summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.dir-locals.el24
-rw-r--r--ChangeLog78
-rw-r--r--ChangeLog.MELT5
-rw-r--r--MAINTAINERS5
-rw-r--r--Makefile.def7
-rw-r--r--Makefile.in988
-rw-r--r--Makefile.tpl13
-rw-r--r--boehm-gc/ChangeLog6
-rwxr-xr-xboehm-gc/configure16
-rwxr-xr-xconfig.guess149
-rwxr-xr-xconfig.sub38
-rw-r--r--config/ChangeLog6
-rw-r--r--config/mh-darwin17
-rwxr-xr-xconfigure54
-rw-r--r--configure.ac45
-rw-r--r--contrib/ChangeLog24
-rw-r--r--contrib/config-list.mk3
-rwxr-xr-xcontrib/gcc_update5
-rw-r--r--contrib/testsuite-management/x86_64-unknown-linux-gnu.xfail17
-rw-r--r--fixincludes/ChangeLog6
-rw-r--r--gcc/ChangeLog8119
-rw-r--r--gcc/ChangeLog-20096
-rw-r--r--gcc/ChangeLog-201110
-rw-r--r--gcc/ChangeLog-201218
-rw-r--r--gcc/ChangeLog.MELT19
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/Makefile.in1735
-rw-r--r--gcc/acinclude.m412
-rw-r--r--gcc/aclocal.m499
-rw-r--r--gcc/ada/ChangeLog2456
-rw-r--r--gcc/ada/ChangeLog-20104
-rw-r--r--gcc/ada/ChangeLog-20112
-rw-r--r--gcc/ada/ChangeLog-20122
-rw-r--r--gcc/ada/a-cfdlli.ads6
-rw-r--r--gcc/ada/a-cfhama.ads6
-rw-r--r--gcc/ada/a-cfhase.ads6
-rw-r--r--gcc/ada/a-cforma.ads6
-rw-r--r--gcc/ada/a-cforse.ads6
-rw-r--r--gcc/ada/a-chahan.adb59
-rw-r--r--gcc/ada/a-chahan.ads52
-rw-r--r--gcc/ada/a-cobove.adb34
-rw-r--r--gcc/ada/a-cofove.ads20
-rw-r--r--gcc/ada/a-coinho-shared.adb358
-rw-r--r--gcc/ada/a-coinho-shared.ads115
-rw-r--r--gcc/ada/a-coinve.adb34
-rw-r--r--gcc/ada/a-convec.adb34
-rw-r--r--gcc/ada/a-except-2005.adb11
-rw-r--r--gcc/ada/a-except-2005.ads17
-rw-r--r--gcc/ada/a-exexda.adb28
-rw-r--r--gcc/ada/a-exexpr-gcc.adb129
-rw-r--r--gcc/ada/a-sequio.adb47
-rw-r--r--gcc/ada/a-tienau.adb10
-rw-r--r--gcc/ada/a-wichha.adb23
-rw-r--r--gcc/ada/a-wichha.ads18
-rw-r--r--gcc/ada/a-zchhan.adb19
-rw-r--r--gcc/ada/a-zchhan.ads9
-rw-r--r--gcc/ada/adaint.c350
-rw-r--r--gcc/ada/adaint.h2
-rw-r--r--gcc/ada/ali.adb112
-rw-r--r--gcc/ada/aspects.adb22
-rw-r--r--gcc/ada/aspects.ads72
-rw-r--r--gcc/ada/atree.adb34
-rw-r--r--gcc/ada/atree.ads49
-rw-r--r--gcc/ada/checks.adb65
-rw-r--r--gcc/ada/cstand.adb50
-rw-r--r--gcc/ada/debug.adb45
-rw-r--r--gcc/ada/einfo.adb379
-rw-r--r--gcc/ada/einfo.ads354
-rw-r--r--gcc/ada/elists.adb49
-rw-r--r--gcc/ada/elists.ads8
-rw-r--r--gcc/ada/errout.adb89
-rw-r--r--gcc/ada/errout.ads10
-rw-r--r--gcc/ada/erroutc.adb6
-rw-r--r--gcc/ada/erroutc.ads3
-rw-r--r--gcc/ada/exp_aggr.adb56
-rw-r--r--gcc/ada/exp_attr.adb217
-rw-r--r--gcc/ada/exp_ch11.adb68
-rw-r--r--gcc/ada/exp_ch3.adb49
-rw-r--r--gcc/ada/exp_ch4.adb237
-rw-r--r--gcc/ada/exp_ch5.adb22
-rw-r--r--gcc/ada/exp_ch6.adb1092
-rw-r--r--gcc/ada/exp_ch6.ads12
-rw-r--r--gcc/ada/exp_ch7.adb121
-rw-r--r--gcc/ada/exp_ch9.adb348
-rw-r--r--gcc/ada/exp_dbug.adb1
-rw-r--r--gcc/ada/exp_disp.adb9
-rw-r--r--gcc/ada/exp_dist.adb37
-rw-r--r--gcc/ada/exp_pakd.adb143
-rw-r--r--gcc/ada/exp_prag.adb146
-rw-r--r--gcc/ada/exp_spark.adb133
-rw-r--r--gcc/ada/exp_spark.ads48
-rw-r--r--gcc/ada/exp_tss.adb4
-rw-r--r--gcc/ada/exp_util.adb187
-rw-r--r--gcc/ada/exp_util.ads16
-rw-r--r--gcc/ada/freeze.adb1382
-rw-r--r--gcc/ada/frontend.adb7
-rw-r--r--gcc/ada/g-arrspl.adb22
-rw-r--r--gcc/ada/g-cppexc.adb139
-rw-r--r--gcc/ada/g-cppexc.ads48
-rw-r--r--gcc/ada/g-decstr.adb222
-rw-r--r--gcc/ada/g-decstr.ads23
-rw-r--r--gcc/ada/gcc-interface/Make-lang.in3579
-rw-r--r--gcc/ada/gcc-interface/Makefile.in56
-rw-r--r--gcc/ada/gcc-interface/cuintp.c45
-rw-r--r--gcc/ada/gcc-interface/decl.c46
-rw-r--r--gcc/ada/gcc-interface/gigi.h7
-rw-r--r--gcc/ada/gcc-interface/trans.c70
-rw-r--r--gcc/ada/gcc-interface/utils.c150
-rw-r--r--gcc/ada/gcc-interface/utils2.c1
-rw-r--r--gcc/ada/gnat1drv.adb7
-rw-r--r--gcc/ada/gnat_rm.texi495
-rw-r--r--gcc/ada/gnat_ugn.texi721
-rw-r--r--gcc/ada/gnatlink.adb112
-rw-r--r--gcc/ada/impunit.adb1
-rw-r--r--gcc/ada/init.c98
-rw-r--r--gcc/ada/itypes.adb4
-rw-r--r--gcc/ada/layout.adb4
-rw-r--r--gcc/ada/lib-util.adb47
-rw-r--r--gcc/ada/lib-util.ads6
-rw-r--r--gcc/ada/lib-writ.adb32
-rw-r--r--gcc/ada/lib-writ.ads115
-rw-r--r--gcc/ada/lib-xref-spark_specific.adb22
-rw-r--r--gcc/ada/lib-xref.adb27
-rw-r--r--gcc/ada/mlib-prj.adb10
-rw-r--r--gcc/ada/opt.ads30
-rw-r--r--gcc/ada/osint.adb6
-rw-r--r--gcc/ada/par-ch13.adb14
-rw-r--r--gcc/ada/par-ch2.adb18
-rw-r--r--gcc/ada/par-ch4.adb8
-rw-r--r--gcc/ada/par-ch6.adb3
-rw-r--r--gcc/ada/par-prag.adb12
-rw-r--r--gcc/ada/prep.adb247
-rw-r--r--gcc/ada/prj-attr.adb3
-rw-r--r--gcc/ada/prj-conf.adb462
-rw-r--r--gcc/ada/prj-nmsc.adb79
-rw-r--r--gcc/ada/prj.ads84
-rw-r--r--gcc/ada/projects.texi247
-rw-r--r--gcc/ada/raise-gcc.c94
-rw-r--r--gcc/ada/raise.h9
-rw-r--r--gcc/ada/restrict.adb23
-rw-r--r--gcc/ada/rtsfind.adb4
-rw-r--r--gcc/ada/rtsfind.ads46
-rw-r--r--gcc/ada/s-atocou-builtin.adb15
-rw-r--r--gcc/ada/s-atocou-x86.adb11
-rw-r--r--gcc/ada/s-atocou.adb11
-rw-r--r--gcc/ada/s-atocou.ads8
-rw-r--r--gcc/ada/s-exctab.adb7
-rw-r--r--gcc/ada/s-imgint.adb36
-rw-r--r--gcc/ada/s-oscons-tmplt.c27
-rw-r--r--gcc/ada/s-osinte-aix.adb44
-rw-r--r--gcc/ada/s-osinte-aix.ads7
-rw-r--r--gcc/ada/s-regpat.adb4
-rw-r--r--gcc/ada/s-stalib.ads58
-rw-r--r--gcc/ada/s-stopoo.ads3
-rw-r--r--gcc/ada/s-stratt-xdr.adb6
-rw-r--r--gcc/ada/s-stratt.ads31
-rw-r--r--gcc/ada/s-ststop.adb349
-rw-r--r--gcc/ada/s-ststop.ads103
-rw-r--r--gcc/ada/s-taprop-posix.adb128
-rw-r--r--gcc/ada/s-valuti.adb26
-rw-r--r--gcc/ada/s-vmexta.adb36
-rw-r--r--gcc/ada/s-vmexta.ads26
-rw-r--r--gcc/ada/s-vxwork-arm.ads19
-rw-r--r--gcc/ada/scng.adb10
-rw-r--r--gcc/ada/scos.ads13
-rw-r--r--gcc/ada/sem.adb3
-rw-r--r--gcc/ada/sem_aggr.adb341
-rw-r--r--gcc/ada/sem_attr.adb635
-rw-r--r--gcc/ada/sem_aux.adb163
-rw-r--r--gcc/ada/sem_aux.ads13
-rw-r--r--gcc/ada/sem_case.adb363
-rw-r--r--gcc/ada/sem_case.ads138
-rw-r--r--gcc/ada/sem_cat.adb5
-rw-r--r--gcc/ada/sem_ch10.adb726
-rw-r--r--gcc/ada/sem_ch11.adb10
-rw-r--r--gcc/ada/sem_ch12.adb107
-rw-r--r--gcc/ada/sem_ch13.adb1035
-rw-r--r--gcc/ada/sem_ch13.ads1
-rw-r--r--gcc/ada/sem_ch3.adb499
-rw-r--r--gcc/ada/sem_ch4.adb68
-rw-r--r--gcc/ada/sem_ch5.adb85
-rw-r--r--gcc/ada/sem_ch6.adb1127
-rw-r--r--gcc/ada/sem_ch6.ads14
-rw-r--r--gcc/ada/sem_ch7.adb220
-rw-r--r--gcc/ada/sem_ch7.ads17
-rw-r--r--gcc/ada/sem_ch8.adb78
-rw-r--r--gcc/ada/sem_ch9.adb23
-rw-r--r--gcc/ada/sem_dim.adb12
-rw-r--r--gcc/ada/sem_disp.adb2
-rw-r--r--gcc/ada/sem_eval.adb13
-rw-r--r--gcc/ada/sem_prag.adb5266
-rw-r--r--gcc/ada/sem_prag.ads78
-rw-r--r--gcc/ada/sem_res.adb125
-rw-r--r--gcc/ada/sem_type.adb15
-rw-r--r--gcc/ada/sem_type.ads9
-rw-r--r--gcc/ada/sem_util.adb745
-rw-r--r--gcc/ada/sem_util.ads64
-rw-r--r--gcc/ada/sem_warn.adb69
-rw-r--r--gcc/ada/sem_warn.ads6
-rw-r--r--gcc/ada/sinfo.adb48
-rw-r--r--gcc/ada/sinfo.ads206
-rw-r--r--gcc/ada/sinput-c.adb5
-rw-r--r--gcc/ada/sinput-d.adb6
-rw-r--r--gcc/ada/sinput-l.adb29
-rw-r--r--gcc/ada/sinput.adb61
-rw-r--r--gcc/ada/sinput.ads34
-rw-r--r--gcc/ada/snames.ads-tmpl56
-rw-r--r--gcc/ada/sprint.adb11
-rw-r--r--gcc/ada/sprint.ads3
-rw-r--r--gcc/ada/stand.adb4
-rw-r--r--gcc/ada/stand.ads8
-rw-r--r--gcc/ada/stylesw.adb21
-rw-r--r--gcc/ada/switch-c.adb6
-rw-r--r--gcc/ada/system-vxworks-arm.ads6
-rw-r--r--gcc/ada/targparm.ads2
-rw-r--r--gcc/ada/thread.c26
-rw-r--r--gcc/ada/types.ads10
-rw-r--r--gcc/ada/ug_words8
-rw-r--r--gcc/ada/usage.adb7
-rw-r--r--gcc/ada/validsw.adb16
-rw-r--r--gcc/ada/vms_data.ads56
-rw-r--r--gcc/ada/warnsw.adb25
-rw-r--r--gcc/ada/warnsw.ads1
-rw-r--r--gcc/alias.c243
-rw-r--r--gcc/alias.h4
-rw-r--r--gcc/alloc-pool.c2
-rw-r--r--gcc/asan.c104
-rw-r--r--gcc/asan.h1
-rw-r--r--gcc/attribs.c35
-rw-r--r--gcc/auto-inc-dec.c10
-rw-r--r--gcc/basic-block.h29
-rw-r--r--gcc/bb-reorder.c29
-rw-r--r--gcc/bitmap.c4
-rw-r--r--gcc/bitmap.h2
-rw-r--r--gcc/bt-load.c26
-rw-r--r--gcc/builtin-types.def43
-rw-r--r--gcc/builtins.c686
-rw-r--r--gcc/builtins.def25
-rw-r--r--gcc/c-family/ChangeLog244
-rw-r--r--gcc/c-family/c-ada-spec.c427
-rw-r--r--gcc/c-family/c-ada-spec.h5
-rw-r--r--gcc/c-family/c-common.c137
-rw-r--r--gcc/c-family/c-common.h174
-rw-r--r--gcc/c-family/c-cppbuiltin.c98
-rw-r--r--gcc/c-family/c-format.c3
-rw-r--r--gcc/c-family/c-gimplify.c2
-rw-r--r--gcc/c-family/c-lex.c17
-rw-r--r--gcc/c-family/c-omp.c415
-rw-r--r--gcc/c-family/c-opts.c10
-rw-r--r--gcc/c-family/c-pragma.c49
-rw-r--r--gcc/c-family/c-pragma.h40
-rw-r--r--gcc/c-family/c-pretty-print.c9
-rw-r--r--gcc/c-family/c-ubsan.c41
-rw-r--r--gcc/c-family/c-ubsan.h1
-rw-r--r--gcc/c-family/c.opt29
-rw-r--r--gcc/c-family/cilk.c1305
-rw-r--r--gcc/c/ChangeLog279
-rw-r--r--gcc/c/Make-lang.in61
-rw-r--r--gcc/c/c-aux-info.c4
-rw-r--r--gcc/c/c-decl.c315
-rw-r--r--gcc/c/c-lang.h3
-rw-r--r--gcc/c/c-objc-common.h9
-rw-r--r--gcc/c/c-parser.c2938
-rw-r--r--gcc/c/c-tree.h15
-rw-r--r--gcc/c/c-typeck.c1556
-rw-r--r--gcc/calls.c13
-rw-r--r--gcc/cfganal.c122
-rw-r--r--gcc/cfgbuild.c2
-rw-r--r--gcc/cfgcleanup.c9
-rw-r--r--gcc/cfgexpand.c963
-rw-r--r--gcc/cfghooks.c2
-rw-r--r--gcc/cfgloop.c145
-rw-r--r--gcc/cfgloop.h47
-rw-r--r--gcc/cfgloopmanip.c6
-rw-r--r--gcc/cfgrtl.c46
-rw-r--r--gcc/cgraph.c443
-rw-r--r--gcc/cgraph.h268
-rw-r--r--gcc/cgraphbuild.c76
-rw-r--r--gcc/cgraphclones.c206
-rw-r--r--gcc/cgraphunit.c339
-rw-r--r--gcc/chkp-builtins.def73
-rw-r--r--gcc/cilk-builtins.def33
-rw-r--r--gcc/cilk-common.c484
-rw-r--r--gcc/cilk.h102
-rw-r--r--gcc/collect2.c34
-rw-r--r--gcc/combine-stack-adj.c4
-rw-r--r--gcc/combine.c71
-rw-r--r--gcc/common.opt62
-rw-r--r--gcc/common/config/arc/arc-common.c117
-rw-r--r--gcc/common/config/i386/i386-common.c1
-rw-r--r--gcc/common/config/m32r/m32r-common.c1
-rw-r--r--gcc/common/config/mmix/mmix-common.c1
-rw-r--r--gcc/common/config/nds32/nds32-common.c117
-rw-r--r--gcc/compare-elim.c6
-rw-r--r--gcc/config.gcc153
-rw-r--r--gcc/config.in6
-rw-r--r--gcc/config/aarch64/aarch64-builtins.c2
-rw-r--r--gcc/config/aarch64/aarch64-simd-builtins.def2
-rw-r--r--gcc/config/aarch64/aarch64-simd.md302
-rw-r--r--gcc/config/aarch64/aarch64.c127
-rw-r--r--gcc/config/aarch64/aarch64.h20
-rw-r--r--gcc/config/aarch64/aarch64.md58
-rw-r--r--gcc/config/aarch64/aarch64.opt4
-rw-r--r--gcc/config/aarch64/arm_neon.h462
-rw-r--r--gcc/config/aarch64/iterators.md19
-rw-r--r--gcc/config/alpha/alpha.c6
-rw-r--r--gcc/config/alpha/x-alpha6
-rw-r--r--gcc/config/arc/arc-modes.def37
-rw-r--r--gcc/config/arc/arc-opts.h28
-rw-r--r--gcc/config/arc/arc-protos.h118
-rw-r--r--gcc/config/arc/arc-simd.h186
-rw-r--r--gcc/config/arc/arc.c9242
-rw-r--r--gcc/config/arc/arc.h1700
-rw-r--r--gcc/config/arc/arc.md5164
-rw-r--r--gcc/config/arc/arc.opt390
-rw-r--r--gcc/config/arc/arc600.md63
-rw-r--r--gcc/config/arc/arc700.md170
-rw-r--r--gcc/config/arc/constraints.md399
-rw-r--r--gcc/config/arc/fpx.md674
-rw-r--r--gcc/config/arc/predicates.md807
-rw-r--r--gcc/config/arc/simdext.md1292
-rw-r--r--gcc/config/arc/t-arc-newlib38
-rw-r--r--gcc/config/arc/t-arc-uClibc20
-rw-r--r--gcc/config/arm/aarch-common-protos.h101
-rw-r--r--gcc/config/arm/aarch-common.c259
-rw-r--r--gcc/config/arm/arm-cores.def4
-rw-r--r--gcc/config/arm/arm-protos.h3
-rw-r--r--gcc/config/arm/arm.c2199
-rw-r--r--gcc/config/arm/arm.md213
-rw-r--r--gcc/config/arm/arm.opt12
-rw-r--r--gcc/config/arm/cortex-a15-neon.md1194
-rw-r--r--gcc/config/arm/cortex-a7.md78
-rw-r--r--gcc/config/arm/cortex-a8-neon.md470
-rw-r--r--gcc/config/arm/cortex-a9-neon.md432
-rw-r--r--gcc/config/arm/iterators.md18
-rw-r--r--gcc/config/arm/neon-schedgen.ml543
-rw-r--r--gcc/config/arm/neon.md917
-rw-r--r--gcc/config/arm/t-aprofile177
-rw-r--r--gcc/config/arm/thumb2.md12
-rw-r--r--gcc/config/arm/types.md735
-rw-r--r--gcc/config/arm/unspecs.md2
-rw-r--r--gcc/config/arm/vfp.md2
-rw-r--r--gcc/config/avr/avr-log.c49
-rw-r--r--gcc/config/avr/avr.c84
-rw-r--r--gcc/config/bfin/bfin-modes.def2
-rw-r--r--gcc/config/bfin/bfin.c21
-rw-r--r--gcc/config/bfin/bfin.md18
-rw-r--r--gcc/config/bfin/uclinux.h8
-rw-r--r--gcc/config/c6x/c6x.md12
-rw-r--r--gcc/config/cris/cris.c7
-rw-r--r--gcc/config/cris/t-elfmulti5
-rw-r--r--gcc/config/darwin-protos.h1
-rw-r--r--gcc/config/darwin.c14
-rw-r--r--gcc/config/frv/frv.c12
-rw-r--r--gcc/config/i386/bdver3.md18
-rw-r--r--gcc/config/i386/constraints.md27
-rw-r--r--gcc/config/i386/i386-builtin-types.def1
-rw-r--r--gcc/config/i386/i386-c.c17
-rw-r--r--gcc/config/i386/i386-modes.def3
-rw-r--r--gcc/config/i386/i386-protos.h8
-rw-r--r--gcc/config/i386/i386.c3477
-rw-r--r--gcc/config/i386/i386.h195
-rw-r--r--gcc/config/i386/i386.md453
-rw-r--r--gcc/config/i386/i386.opt10
-rw-r--r--gcc/config/i386/mmx.md11
-rw-r--r--gcc/config/i386/predicates.md131
-rw-r--r--gcc/config/i386/rtemself.h12
-rw-r--r--gcc/config/i386/sse.md3293
-rw-r--r--gcc/config/i386/sync.md15
-rw-r--r--gcc/config/i386/t-i38619
-rw-r--r--gcc/config/i386/t-rtems7
-rw-r--r--gcc/config/i386/winnt.c5
-rw-r--r--gcc/config/i386/x-darwin7
-rw-r--r--gcc/config/i386/x-i3867
-rw-r--r--gcc/config/i386/x86-tune.def613
-rw-r--r--gcc/config/ia64/hpux.h2
-rw-r--r--gcc/config/ia64/ia64.c139
-rw-r--r--gcc/config/ia64/ia64.md11
-rw-r--r--gcc/config/ia64/predicates.md10
-rw-r--r--gcc/config/iq2000/iq2000.c4
-rw-r--r--gcc/config/iq2000/iq2000.md5
-rw-r--r--gcc/config/m32c/m32c-modes.def2
-rw-r--r--gcc/config/m68k/m68k.c7
-rw-r--r--gcc/config/mcore/t-mcore3
-rw-r--r--gcc/config/mep/mep.c6
-rw-r--r--gcc/config/mep/mep.md19
-rw-r--r--gcc/config/microblaze/microblaze.md5
-rw-r--r--gcc/config/mips/mips.c25
-rw-r--r--gcc/config/mips/mips.h5
-rw-r--r--gcc/config/mips/mips.md55
-rw-r--r--gcc/config/mips/mti-linux.h2
-rw-r--r--gcc/config/mips/t-mti-elf14
-rw-r--r--gcc/config/mips/t-mti-linux14
-rw-r--r--gcc/config/mmix/mmix.c2
-rw-r--r--gcc/config/moxie/uclinux.h8
-rw-r--r--gcc/config/msp430/msp430-modes.def2
-rw-r--r--gcc/config/msp430/msp430-protos.h1
-rw-r--r--gcc/config/msp430/msp430.c191
-rw-r--r--gcc/config/msp430/msp430.h6
-rw-r--r--gcc/config/msp430/msp430.md63
-rw-r--r--gcc/config/msp430/t-msp430245
-rw-r--r--gcc/config/nds32/constants.md46
-rw-r--r--gcc/config/nds32/constraints.md254
-rw-r--r--gcc/config/nds32/iterators.md55
-rw-r--r--gcc/config/nds32/nds32-doubleword.md251
-rw-r--r--gcc/config/nds32/nds32-intrinsic.md97
-rw-r--r--gcc/config/nds32/nds32-modes.def21
-rw-r--r--gcc/config/nds32/nds32-multiple.md410
-rw-r--r--gcc/config/nds32/nds32-opts.h35
-rw-r--r--gcc/config/nds32/nds32-peephole2.md25
-rw-r--r--gcc/config/nds32/nds32-protos.h128
-rw-r--r--gcc/config/nds32/nds32.c5721
-rw-r--r--gcc/config/nds32/nds32.h982
-rw-r--r--gcc/config/nds32/nds32.md2221
-rw-r--r--gcc/config/nds32/nds32.opt102
-rw-r--r--gcc/config/nds32/nds32_intrinsic.h37
-rw-r--r--gcc/config/nds32/pipelines.md29
-rw-r--r--gcc/config/nds32/predicates.md92
-rw-r--r--gcc/config/nds32/t-mlibs38
-rw-r--r--gcc/config/pa/pa-hpux11.h3
-rw-r--r--gcc/config/pa/pa-linux.h3
-rw-r--r--gcc/config/pa/pa.c6
-rw-r--r--gcc/config/pa/pa.md12
-rw-r--r--gcc/config/pa/pa64-hpux.h18
-rw-r--r--gcc/config/pdp11/pdp11.c1
-rw-r--r--gcc/config/picochip/picochip.c1
-rw-r--r--gcc/config/rl78/constraints.md28
-rw-r--r--gcc/config/rl78/rl78-expand.md50
-rw-r--r--gcc/config/rl78/rl78-real.md113
-rw-r--r--gcc/config/rl78/rl78-virt.md16
-rw-r--r--gcc/config/rl78/rl78.c163
-rw-r--r--gcc/config/rl78/rl78.h1
-rw-r--r--gcc/config/rl78/rl78.md2
-rw-r--r--gcc/config/rs6000/aix.h24
-rw-r--r--gcc/config/rs6000/altivec.md433
-rw-r--r--gcc/config/rs6000/constraints.md52
-rw-r--r--gcc/config/rs6000/darwin.md112
-rw-r--r--gcc/config/rs6000/linux.h6
-rw-r--r--gcc/config/rs6000/linux64.h6
-rw-r--r--gcc/config/rs6000/rs6000-builtin.def6
-rw-r--r--gcc/config/rs6000/rs6000-cpus.def7
-rw-r--r--gcc/config/rs6000/rs6000-linux.c38
-rw-r--r--gcc/config/rs6000/rs6000-modes.def2
-rw-r--r--gcc/config/rs6000/rs6000-protos.h6
-rw-r--r--gcc/config/rs6000/rs6000.c1147
-rw-r--r--gcc/config/rs6000/rs6000.h36
-rw-r--r--gcc/config/rs6000/rs6000.md912
-rw-r--r--gcc/config/rs6000/rs6000.opt26
-rw-r--r--gcc/config/rs6000/t-linux4
-rw-r--r--gcc/config/rs6000/t-linux644
-rw-r--r--gcc/config/rs6000/t-rs600018
-rw-r--r--gcc/config/rs6000/t-xilinx28
-rw-r--r--gcc/config/rs6000/vector.md56
-rw-r--r--gcc/config/rs6000/vsx.md760
-rw-r--r--gcc/config/rs6000/x-darwin8
-rw-r--r--gcc/config/rs6000/x-darwin648
-rw-r--r--gcc/config/rx/rx.c18
-rw-r--r--gcc/config/s390/s390.c858
-rw-r--r--gcc/config/s390/s390.md40
-rw-r--r--gcc/config/sh/predicates.md33
-rw-r--r--gcc/config/sh/sh-mem.cc551
-rw-r--r--gcc/config/sh/sh-modes.def4
-rw-r--r--gcc/config/sh/sh-protos.h3
-rw-r--r--gcc/config/sh/sh.c257
-rw-r--r--gcc/config/sh/sh.h11
-rw-r--r--gcc/config/sh/sh.md493
-rw-r--r--gcc/config/sh/sh.opt2
-rw-r--r--gcc/config/sh/sh_treg_combine.cc1509
-rw-r--r--gcc/config/sh/t-sh8
-rw-r--r--gcc/config/sol2.h5
-rw-r--r--gcc/config/sparc/sparc-protos.h3
-rw-r--r--gcc/config/sparc/sparc.c40
-rw-r--r--gcc/config/sparc/sparc.md87
-rw-r--r--gcc/config/sparc/sync.md12
-rw-r--r--gcc/config/sparc/t-sparc19
-rw-r--r--gcc/config/sparc/x-sparc7
-rw-r--r--gcc/config/spu/spu.c7
-rw-r--r--gcc/config/spu/spu.md11
-rw-r--r--gcc/config/t-darwin32
-rw-r--r--gcc/config/t-glibc7
-rw-r--r--gcc/config/t-linux-android10
-rw-r--r--gcc/config/t-sol225
-rw-r--r--gcc/config/tilegx/tilegx.c7
-rw-r--r--gcc/config/tilegx/tilegx.md11
-rw-r--r--gcc/config/tilepro/tilepro.c7
-rw-r--r--gcc/config/tilepro/tilepro.md11
-rw-r--r--gcc/config/v850/v850.c3
-rw-r--r--gcc/config/v850/v850.h4
-rw-r--r--gcc/config/v850/v850.md28
-rw-r--r--gcc/config/vax/vax.c4
-rw-r--r--gcc/config/vax/vax.md4
-rw-r--r--gcc/config/x-darwin6
-rw-r--r--gcc/config/x-linux7
-rw-r--r--gcc/config/x-solaris7
-rwxr-xr-xgcc/configure357
-rw-r--r--gcc/configure.ac58
-rw-r--r--gcc/context.c9
-rw-r--r--gcc/context.h14
-rw-r--r--gcc/convert.c42
-rw-r--r--gcc/coretypes.h3
-rw-r--r--gcc/coverage.c13
-rw-r--r--gcc/cp/ChangeLog636
-rw-r--r--gcc/cp/Make-lang.in112
-rw-r--r--gcc/cp/call.c10
-rw-r--r--gcc/cp/class.c64
-rw-r--r--gcc/cp/cp-array-notation.c3
-rw-r--r--gcc/cp/cp-gimplify.c25
-rw-r--r--gcc/cp/cp-objcp-common.h2
-rw-r--r--gcc/cp/cp-tree.h45
-rw-r--r--gcc/cp/cvt.c6
-rw-r--r--gcc/cp/cxx-pretty-print.c2
-rw-r--r--gcc/cp/decl.c138
-rw-r--r--gcc/cp/decl2.c185
-rw-r--r--gcc/cp/error.c33
-rw-r--r--gcc/cp/except.c20
-rw-r--r--gcc/cp/init.c231
-rw-r--r--gcc/cp/lambda.c19
-rw-r--r--gcc/cp/mangle.c10
-rw-r--r--gcc/cp/method.c49
-rw-r--r--gcc/cp/name-lookup.c2
-rw-r--r--gcc/cp/optimize.c2
-rw-r--r--gcc/cp/parser.c3031
-rw-r--r--gcc/cp/parser.h18
-rw-r--r--gcc/cp/pt.c460
-rw-r--r--gcc/cp/semantics.c1647
-rw-r--r--gcc/cp/tree.c4
-rw-r--r--gcc/cp/type-utils.h2
-rw-r--r--gcc/cp/typeck.c2
-rw-r--r--gcc/cp/typeck2.c12
-rw-r--r--gcc/cppbuiltin.c2
-rw-r--r--gcc/cprop.c15
-rw-r--r--gcc/cse.c22
-rw-r--r--gcc/cselib.c4
-rw-r--r--gcc/data-streamer-in.c2
-rw-r--r--gcc/data-streamer-out.c2
-rw-r--r--gcc/data-streamer.c2
-rw-r--r--gcc/dbgcnt.def1
-rw-r--r--gcc/dbxout.c18
-rw-r--r--gcc/dce.c8
-rw-r--r--gcc/defaults.h8
-rw-r--r--gcc/df-core.c16
-rw-r--r--gcc/df-problems.c6
-rw-r--r--gcc/df-scan.c152
-rw-r--r--gcc/df.h59
-rw-r--r--gcc/diagnostic.c6
-rw-r--r--gcc/doc/contrib.texi13
-rw-r--r--gcc/doc/cpp.texi34
-rw-r--r--gcc/doc/extend.texi900
-rw-r--r--gcc/doc/gcc.texi6
-rw-r--r--gcc/doc/generic.texi73
-rw-r--r--gcc/doc/gimple.texi9
-rw-r--r--gcc/doc/gty.texi59
-rw-r--r--gcc/doc/install.texi305
-rw-r--r--gcc/doc/invoke.texi898
-rw-r--r--gcc/doc/md.texi270
-rw-r--r--gcc/doc/passes.texi86
-rw-r--r--gcc/doc/rtl.texi34
-rw-r--r--gcc/doc/sourcebuild.texi6
-rw-r--r--gcc/doc/tm.texi158
-rw-r--r--gcc/doc/tm.texi.in20
-rw-r--r--gcc/doc/tree-ssa.texi53
-rw-r--r--gcc/dojump.c82
-rw-r--r--gcc/domwalk.c10
-rw-r--r--gcc/domwalk.h4
-rw-r--r--gcc/double-int.c12
-rw-r--r--gcc/dse.c15
-rw-r--r--gcc/dumpfile.c167
-rw-r--r--gcc/dumpfile.h90
-rw-r--r--gcc/dwarf2asm.c2
-rw-r--r--gcc/dwarf2cfi.c11
-rw-r--r--gcc/dwarf2out.c193
-rw-r--r--gcc/emit-rtl.c57
-rw-r--r--gcc/errors.c6
-rw-r--r--gcc/except.c12
-rw-r--r--gcc/explow.c12
-rw-r--r--gcc/expmed.c109
-rw-r--r--gcc/expr.c278
-rw-r--r--gcc/expr.h4
-rw-r--r--gcc/file-find.c2
-rw-r--r--gcc/final.c46
-rw-r--r--gcc/fixed-value.c2
-rw-r--r--gcc/flag-types.h11
-rw-r--r--gcc/fold-const.c323
-rw-r--r--gcc/fortran/ChangeLog195
-rw-r--r--gcc/fortran/Make-lang.in63
-rw-r--r--gcc/fortran/check.c2
-rw-r--r--gcc/fortran/class.c34
-rw-r--r--gcc/fortran/cpp.c6
-rw-r--r--gcc/fortran/decl.c17
-rw-r--r--gcc/fortran/expr.c5
-rw-r--r--gcc/fortran/f95-lang.c19
-rw-r--r--gcc/fortran/gfortran.h1
-rw-r--r--gcc/fortran/gfortran.texi2
-rw-r--r--gcc/fortran/interface.c14
-rw-r--r--gcc/fortran/intrinsic.texi25
-rw-r--r--gcc/fortran/lang.opt8
-rw-r--r--gcc/fortran/options.c8
-rw-r--r--gcc/fortran/parse.c27
-rw-r--r--gcc/fortran/primary.c2
-rw-r--r--gcc/fortran/resolve.c39
-rw-r--r--gcc/fortran/target-memory.c30
-rw-r--r--gcc/fortran/trans-expr.c17
-rw-r--r--gcc/fortran/trans-intrinsic.c6
-rw-r--r--gcc/fortran/trans-io.c28
-rw-r--r--gcc/fortran/trans-openmp.c7
-rw-r--r--gcc/fortran/trans-stmt.c7
-rw-r--r--gcc/fortran/trans-types.c6
-rw-r--r--gcc/fortran/types.def36
-rw-r--r--gcc/function.c102
-rw-r--r--gcc/function.h9
-rw-r--r--gcc/fwprop.c8
-rw-r--r--gcc/gcc-ar.c12
-rw-r--r--gcc/gcc.c76
-rw-r--r--gcc/gcov-io.c17
-rw-r--r--gcc/gcov-io.h15
-rw-r--r--gcc/gcov.c12
-rw-r--r--gcc/gcse.c10
-rw-r--r--gcc/gdbhooks.py3
-rw-r--r--gcc/gdbinit.in5
-rw-r--r--gcc/genattr-common.c2
-rw-r--r--gcc/genattr.c6
-rw-r--r--gcc/genattrtab.c13
-rw-r--r--gcc/genautomata.c9
-rw-r--r--gcc/genconfig.c2
-rw-r--r--gcc/genemit.c3
-rw-r--r--gcc/genextract.c8
-rw-r--r--gcc/genflags.c4
-rw-r--r--gcc/gengenrtl.c2
-rw-r--r--gcc/gengtype-parse.c68
-rw-r--r--gcc/gengtype-state.c50
-rw-r--r--gcc/gengtype.c214
-rw-r--r--gcc/gengtype.h22
-rw-r--r--gcc/genmodes.c45
-rw-r--r--gcc/genopinit.c5
-rw-r--r--gcc/genoutput.c11
-rw-r--r--gcc/genpeep.c3
-rw-r--r--gcc/genpreds.c10
-rw-r--r--gcc/genrecog.c23
-rw-r--r--gcc/gensupport.c33
-rw-r--r--gcc/ggc-common.c8
-rw-r--r--gcc/ggc-page.c16
-rw-r--r--gcc/gimple-builder.c118
-rw-r--r--gcc/gimple-builder.h34
-rw-r--r--gcc/gimple-expr.c721
-rw-r--r--gcc/gimple-expr.h171
-rw-r--r--gcc/gimple-fold.c167
-rw-r--r--gcc/gimple-fold.h23
-rw-r--r--gcc/gimple-iterator.c5
-rw-r--r--gcc/gimple-low.c235
-rw-r--r--gcc/gimple-low.h28
-rw-r--r--gcc/gimple-pretty-print.c263
-rw-r--r--gcc/gimple-pretty-print.h1
-rw-r--r--gcc/gimple-ssa-isolate-paths.c324
-rw-r--r--gcc/gimple-ssa-strength-reduction.c22
-rw-r--r--gcc/gimple-ssa.h154
-rw-r--r--gcc/gimple-streamer-in.c5
-rw-r--r--gcc/gimple-streamer-out.c3
-rw-r--r--gcc/gimple.c1541
-rw-r--r--gcc/gimple.def24
-rw-r--r--gcc/gimple.h671
-rw-r--r--gcc/gimplify.c968
-rw-r--r--gcc/ginclude/stdatomic.h244
-rw-r--r--gcc/go/ChangeLog63
-rw-r--r--gcc/go/Make-lang.in100
-rw-r--r--gcc/go/go-gcc.cc221
-rw-r--r--gcc/go/go-lang.c6
-rw-r--r--gcc/go/gofrontend/backend.h73
-rw-r--r--gcc/go/gofrontend/expressions.cc733
-rw-r--r--gcc/go/gofrontend/expressions.h75
-rw-r--r--gcc/go/gofrontend/gogo-tree.cc312
-rw-r--r--gcc/go/gofrontend/gogo.cc168
-rw-r--r--gcc/go/gofrontend/gogo.h49
-rw-r--r--gcc/go/gofrontend/import.h5
-rw-r--r--gcc/go/gofrontend/lex.cc23
-rw-r--r--gcc/go/gofrontend/parse.cc49
-rw-r--r--gcc/go/gofrontend/runtime.cc7
-rw-r--r--gcc/go/gofrontend/runtime.def6
-rw-r--r--gcc/go/gofrontend/statements.cc20
-rw-r--r--gcc/go/gofrontend/types.cc204
-rw-r--r--gcc/go/gofrontend/types.h28
-rw-r--r--gcc/godump.c2
-rw-r--r--gcc/graph.c6
-rw-r--r--gcc/graphite-blocking.c4
-rw-r--r--gcc/graphite-clast-to-gimple.c24
-rw-r--r--gcc/graphite-dependences.c8
-rw-r--r--gcc/graphite-interchange.c4
-rw-r--r--gcc/graphite-optimize-isl.c221
-rw-r--r--gcc/graphite-poly.c4
-rw-r--r--gcc/graphite-poly.h2
-rw-r--r--gcc/graphite-scop-detection.c30
-rw-r--r--gcc/graphite-sese-to-poly.c87
-rw-r--r--gcc/graphite.c117
-rw-r--r--gcc/haifa-sched.c104
-rw-r--r--gcc/hash-table.c2
-rw-r--r--gcc/hash-table.h30
-rw-r--r--gcc/hooks.c6
-rw-r--r--gcc/hooks.h3
-rw-r--r--gcc/hw-doloop.c5
-rw-r--r--gcc/hwint.c34
-rw-r--r--gcc/hwint.h28
-rw-r--r--gcc/ifcvt.c53
-rw-r--r--gcc/incpath.c6
-rw-r--r--gcc/init-regs.c4
-rw-r--r--gcc/input.h7
-rw-r--r--gcc/internal-fn.c6
-rw-r--r--gcc/internal-fn.def1
-rw-r--r--gcc/intl.c2
-rw-r--r--gcc/intl.h8
-rw-r--r--gcc/ipa-cp.c141
-rw-r--r--gcc/ipa-devirt.c107
-rw-r--r--gcc/ipa-inline-analysis.c158
-rw-r--r--gcc/ipa-inline-transform.c55
-rw-r--r--gcc/ipa-inline.c226
-rw-r--r--gcc/ipa-profile.c65
-rw-r--r--gcc/ipa-prop.c134
-rw-r--r--gcc/ipa-prop.h2
-rw-r--r--gcc/ipa-pure-const.c161
-rw-r--r--gcc/ipa-ref-inline.h4
-rw-r--r--gcc/ipa-ref.c34
-rw-r--r--gcc/ipa-ref.h26
-rw-r--r--gcc/ipa-reference.c103
-rw-r--r--gcc/ipa-reference.h2
-rw-r--r--gcc/ipa-split.c46
-rw-r--r--gcc/ipa-utils.c116
-rw-r--r--gcc/ipa-utils.h15
-rw-r--r--gcc/ipa.c546
-rw-r--r--gcc/ira-build.c228
-rw-r--r--gcc/ira-color.c277
-rw-r--r--gcc/ira-conflicts.c181
-rw-r--r--gcc/ira-costs.c211
-rw-r--r--gcc/ira-int.h81
-rw-r--r--gcc/ira.c553
-rw-r--r--gcc/is-a.h8
-rw-r--r--gcc/java/ChangeLog36
-rw-r--r--gcc/java/Make-lang.in76
-rw-r--r--gcc/java/builtins.c4
-rw-r--r--gcc/java/decl.c2
-rw-r--r--gcc/java/lang.c3
-rw-r--r--gcc/jump.c8
-rw-r--r--gcc/langhooks-def.h16
-rw-r--r--gcc/langhooks.c24
-rw-r--r--gcc/langhooks.h22
-rw-r--r--gcc/loop-doloop.c76
-rw-r--r--gcc/loop-init.c32
-rw-r--r--gcc/loop-invariant.c10
-rw-r--r--gcc/loop-iv.c22
-rw-r--r--gcc/loop-unroll.c19
-rw-r--r--gcc/loop-unswitch.c15
-rw-r--r--gcc/lower-subreg.c34
-rw-r--r--gcc/lra-constraints.c189
-rw-r--r--gcc/lra-eliminations.c129
-rw-r--r--gcc/lra-spills.c49
-rw-r--r--gcc/lra.c34
-rw-r--r--gcc/lto-cgraph.c338
-rw-r--r--gcc/lto-compress.c1
-rw-r--r--gcc/lto-opts.c10
-rw-r--r--gcc/lto-section-in.c15
-rw-r--r--gcc/lto-section-out.c4
-rw-r--r--gcc/lto-streamer-in.c15
-rw-r--r--gcc/lto-streamer-out.c103
-rw-r--r--gcc/lto-streamer.c7
-rw-r--r--gcc/lto-streamer.h20
-rw-r--r--gcc/lto-wrapper.c8
-rw-r--r--gcc/lto/ChangeLog191
-rw-r--r--gcc/lto/Make-lang.in30
-rw-r--r--gcc/lto/lto-lang.c41
-rw-r--r--gcc/lto/lto-object.c2
-rw-r--r--gcc/lto/lto-partition.c243
-rw-r--r--gcc/lto/lto-symtab.c252
-rw-r--r--gcc/lto/lto.c1221
-rw-r--r--gcc/machmode.def8
-rw-r--r--gcc/machmode.h19
-rw-r--r--gcc/mcf.c2
-rw-r--r--gcc/melt-run.proto.h9
-rw-r--r--gcc/melt-runtime.cc11
-rw-r--r--gcc/melt-runtime.h2
-rw-r--r--gcc/melt/xtramelt-ana-gimple.melt11
-rw-r--r--gcc/melt/xtramelt-probe.melt2
-rw-r--r--gcc/mode-classes.def1
-rw-r--r--gcc/mode-switching.c38
-rw-r--r--gcc/modulo-sched.c4
-rw-r--r--gcc/objc/ChangeLog12
-rw-r--r--gcc/objc/Make-lang.in79
-rw-r--r--gcc/objc/objc-act.c1
-rw-r--r--gcc/objcp/ChangeLog10
-rw-r--r--gcc/objcp/Make-lang.in128
-rw-r--r--gcc/omp-builtins.def70
-rw-r--r--gcc/omp-low.c2806
-rw-r--r--gcc/omp-low.h31
-rw-r--r--gcc/optabs.c56
-rw-r--r--gcc/optc-save-gen.awk4
-rw-r--r--gcc/opth-gen.awk2
-rw-r--r--gcc/opts-global.c42
-rw-r--r--gcc/opts.c38
-rw-r--r--gcc/params.def29
-rw-r--r--gcc/pass_manager.h4
-rw-r--r--gcc/passes.c134
-rw-r--r--gcc/passes.def16
-rw-r--r--gcc/plugin.c19
-rw-r--r--gcc/postreload-gcse.c6
-rw-r--r--gcc/postreload.c4
-rw-r--r--gcc/predict.c127
-rw-r--r--gcc/predict.def8
-rw-r--r--gcc/predict.h2
-rw-r--r--gcc/prefix.c2
-rw-r--r--gcc/pretty-print.c2
-rw-r--r--gcc/print-rtl.c6
-rw-r--r--gcc/print-tree.c35
-rw-r--r--gcc/profile.c42
-rw-r--r--gcc/read-md.c2
-rw-r--r--gcc/real.c2
-rw-r--r--gcc/real.h2
-rw-r--r--gcc/recog.c37
-rw-r--r--gcc/ree.c8
-rw-r--r--gcc/reg-notes.def12
-rw-r--r--gcc/reg-stack.c12
-rw-r--r--gcc/regcprop.c4
-rw-r--r--gcc/reginfo.c10
-rw-r--r--gcc/regmove.c1401
-rw-r--r--gcc/regrename.c4
-rw-r--r--gcc/regs.h2
-rw-r--r--gcc/regstat.c2
-rw-r--r--gcc/reload1.c124
-rw-r--r--gcc/reorg.c16
-rw-r--r--gcc/rtl.c2
-rw-r--r--gcc/rtl.def7
-rw-r--r--gcc/rtl.h148
-rw-r--r--gcc/rtlanal.c154
-rw-r--r--gcc/sanitizer.def6
-rw-r--r--gcc/sbitmap.c6
-rw-r--r--gcc/sched-deps.c5
-rw-r--r--gcc/sched-int.h2
-rw-r--r--gcc/sched-rgn.c79
-rw-r--r--gcc/sched-vis.c5
-rw-r--r--gcc/sdbout.c17
-rw-r--r--gcc/sel-sched-ir.c2
-rw-r--r--gcc/sel-sched.c6
-rw-r--r--gcc/sese.c11
-rw-r--r--gcc/sparseset.c2
-rw-r--r--gcc/ssa-iterators.h996
-rw-r--r--gcc/ssaexpand.h79
-rw-r--r--gcc/stack-ptr-mod.c4
-rw-r--r--gcc/statistics.c11
-rw-r--r--gcc/stmt.c873
-rw-r--r--gcc/stor-layout.c80
-rw-r--r--gcc/store-motion.c6
-rw-r--r--gcc/streamer-hooks.c1
-rw-r--r--gcc/streamer-hooks.h12
-rw-r--r--gcc/symtab.c598
-rw-r--r--gcc/sync-builtins.def410
-rw-r--r--gcc/system.h39
-rw-r--r--gcc/target-globals.c1
-rw-r--r--gcc/target-hooks-macros.h2
-rw-r--r--gcc/target.def203
-rw-r--r--gcc/target.h1
-rw-r--r--gcc/targhooks.c213
-rw-r--r--gcc/targhooks.h15
-rw-r--r--gcc/testsuite/ChangeLog1798
-rw-r--r--gcc/testsuite/ChangeLog-20092
-rw-r--r--gcc/testsuite/ChangeLog-20122
-rw-r--r--gcc/testsuite/c-c++-common/asan/pr59029.c7
-rw-r--r--gcc/testsuite/c-c++-common/asan/stack-overflow-1.c3
-rw-r--r--gcc/testsuite/c-c++-common/cilk-plus/CK/compound_cilk_spawn.c26
-rw-r--r--gcc/testsuite/c-c++-common/cilk-plus/CK/concec_cilk_spawn.c20
-rw-r--r--gcc/testsuite/c-c++-common/cilk-plus/CK/fib.c54
-rw-r--r--gcc/testsuite/c-c++-common/cilk-plus/CK/fib_init_expr_xy.c68
-rw-r--r--gcc/testsuite/c-c++-common/cilk-plus/CK/fib_no_return.c73
-rw-r--r--gcc/testsuite/c-c++-common/cilk-plus/CK/fib_no_sync.c67
-rw-r--r--gcc/testsuite/c-c++-common/cilk-plus/CK/invalid_spawns.c11
-rw-r--r--gcc/testsuite/c-c++-common/cilk-plus/CK/no_args_error.c11
-rw-r--r--gcc/testsuite/c-c++-common/cilk-plus/CK/spawn_in_return.c8
-rw-r--r--gcc/testsuite/c-c++-common/cilk-plus/CK/spawnee_inline.c80
-rw-r--r--gcc/testsuite/c-c++-common/cilk-plus/CK/spawner_inline.c67
-rw-r--r--gcc/testsuite/c-c++-common/cilk-plus/CK/spawning_arg.c37
-rw-r--r--gcc/testsuite/c-c++-common/cilk-plus/CK/steal_check.c43
-rw-r--r--gcc/testsuite/c-c++-common/cilk-plus/CK/sync_wo_spawn.c9
-rw-r--r--gcc/testsuite/c-c++-common/cilk-plus/CK/test__cilk.c10
-rw-r--r--gcc/testsuite/c-c++-common/cilk-plus/CK/varargs_test.c47
-rw-r--r--gcc/testsuite/c-c++-common/cpp/openmp-define-1.c6
-rw-r--r--gcc/testsuite/c-c++-common/cpp/openmp-define-2.c7
-rw-r--r--gcc/testsuite/c-c++-common/cpp/openmp-define-3.c11
-rw-r--r--gcc/testsuite/c-c++-common/fold-divmul-1.c11
-rw-r--r--gcc/testsuite/c-c++-common/gomp/atomic-15.c34
-rw-r--r--gcc/testsuite/c-c++-common/gomp/atomic-16.c34
-rw-r--r--gcc/testsuite/c-c++-common/gomp/cancel-1.c396
-rw-r--r--gcc/testsuite/c-c++-common/gomp/depend-1.c79
-rw-r--r--gcc/testsuite/c-c++-common/gomp/depend-2.c19
-rw-r--r--gcc/testsuite/c-c++-common/gomp/map-1.c103
-rw-r--r--gcc/testsuite/c-c++-common/gomp/pr58472.c16
-rw-r--r--gcc/testsuite/c-c++-common/gomp/pr58551.c33
-rw-r--r--gcc/testsuite/c-c++-common/gomp/sections1.c73
-rw-r--r--gcc/testsuite/c-c++-common/gomp/simd1.c31
-rw-r--r--gcc/testsuite/c-c++-common/gomp/simd2.c29
-rw-r--r--gcc/testsuite/c-c++-common/gomp/simd3.c26
-rw-r--r--gcc/testsuite/c-c++-common/gomp/simd4.c21
-rw-r--r--gcc/testsuite/c-c++-common/gomp/simd5.c19
-rw-r--r--gcc/testsuite/c-c++-common/gomp/simd6.c27
-rw-r--r--gcc/testsuite/c-c++-common/gomp/single1.c15
-rw-r--r--gcc/testsuite/c-c++-common/opaque-vector.c2
-rw-r--r--gcc/testsuite/c-c++-common/pr20318.c3
-rw-r--r--gcc/testsuite/c-c++-common/pr57793.c4
-rw-r--r--gcc/testsuite/c-c++-common/torture/pr58794-1.c29
-rw-r--r--gcc/testsuite/c-c++-common/torture/pr58794-2.c21
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/div-by-zero-5.c8
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/shift-4.c14
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/shift-5.c33
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/shift-6.c30
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/vla-1.c48
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/vla-2.c15
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/vla-3.c16
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/vla-4.c13
-rw-r--r--gcc/testsuite/g++.dg/asan/asan_test.cc46
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/Wliteral-suffix.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/Wzero-as-null-pointer-constant-1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/__func__.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/access01.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/alias-decl-0.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/alias-decl-1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/alias-decl-10.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/alias-decl-11.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/alias-decl-12.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/alias-decl-13.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/alias-decl-14.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/alias-decl-15.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/alias-decl-2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/alias-decl-3.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/alias-decl-4.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/alias-decl-5.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/alias-decl-6.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/alias-decl-7.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/alias-decl-8.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/alias-decl-9.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/alias-decl-debug-0.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/alignof.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/alignof2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/alignof3.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/alignof4.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/auto10.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/auto11.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/auto14.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/auto15.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/auto16.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/auto17.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/auto18.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/auto19.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/auto2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/auto20.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/auto21.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/auto22.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/auto23.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/auto24.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/auto25.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/auto26.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/auto28.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/auto39.C6
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/auto4.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/auto40.C11
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/auto5.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/auto7.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/auto9.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/bind.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/bracket1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/bracket2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/bracket4.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/cast-bug.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/cast.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/collapse-bug.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/collapse.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-46336.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-46420.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-47570.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-47969.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-48089.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-49776.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-abi1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-access.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr3.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr4.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr5.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr6.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr7.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-array-tparm.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-array.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-array2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-array3.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-array4.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-attribute.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-auto.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-base.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-base2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-base3.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-base4.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-bitfield.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-bitfield2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-bitfield3.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-builtin1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-cache1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-cleanup.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-complex.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-compound.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-condition.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-condition2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-ctor.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-ctor2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-ctor3.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-ctor4.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-ctor5.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-ctor6.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-ctor7.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-ctor8.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-ctor9.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-data1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-data2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-decl.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-defarg.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-defarg2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-default-ctor.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-delegating.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-delegating2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-delete.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-deref.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-diag1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-diag2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-diag3.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-eh-spec.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-ellipsis.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-ellipsis2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-empty.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-empty2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-empty3.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-empty4.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-empty5.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-ex1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-ex2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-ex3.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-ex4.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-expinst.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-explicit-inst.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-fnptr.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-friend.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-function1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-function2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-function3.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-generated1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-ice.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-ice2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-ice3.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-ice4.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-ice5.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-ice6.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-incomplete1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-incomplete2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-incomplete3.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-initlist.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-initlist2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-initlist3.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-initlist4.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-initlist5.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-is_literal.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-memfn1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-missing.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-mutable1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-neg1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-noexcept.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-noexcept2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-noexcept3.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-noexcept4.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-noexcept5.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-noexcept6.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-non-const-arg.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-non-const-arg2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-non-const-arg3.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-nonlit.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-nonlit2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-nonstatic.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-nullptr.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-object1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-object2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-overflow.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-overflow2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-pedantic.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-pos1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-potential1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-ptrmem.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-ptrsub.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-pure.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-recursion.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-ref1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-ref2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-ref3.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-ref4.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-rom.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-sassert.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-static.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-static2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-static3.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-static4.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-static5.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-static6.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-static7.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-static8.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-stmtexpr.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-string.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-switch.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-switch2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-synth1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-targ.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-template1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-template2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-template3.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-throw.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-typedef1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-typeid.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-union.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-union2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-using.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-using2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-value.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-value2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-value3.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-variadic.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-virtual.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-wstring1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-wstring2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/dc1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/dc2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/dc3.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/dc5.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/decltype-1212.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/decltype-33837.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/decltype-33838.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/decltype-refbug.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/decltype1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/decltype10.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/decltype11.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/decltype12.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/decltype15.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/decltype16.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/decltype17.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/decltype18.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/decltype2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/decltype20.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/decltype21.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/decltype22.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/decltype23.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/decltype24.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/decltype25.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/decltype26.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/decltype27.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/decltype28.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/decltype29.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/decltype3.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/decltype30.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/decltype31.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/decltype32.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/decltype33.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/decltype34.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/decltype35.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/decltype36.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/decltype4.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/decltype5.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/decltype57.C8
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/decltype6.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/decltype9.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/deduce.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/defaulted1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/defaulted10.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/defaulted11.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/defaulted13.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/defaulted14.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/defaulted15.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/defaulted16.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/defaulted17.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/defaulted18.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/defaulted19.C7
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/defaulted19a.C24
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/defaulted2.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/defaulted20.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/defaulted21.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/defaulted22.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/defaulted23.C14
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/defaulted24.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/defaulted25.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/defaulted26.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/defaulted27.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/defaulted28.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/defaulted29.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/defaulted3.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/defaulted30.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/defaulted31.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/defaulted32.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/defaulted34.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/defaulted35.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/defaulted4.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/defaulted43.C14
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/defaulted46.C17
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/defaulted47.C16
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/defaulted5.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/defaulted6.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/defaulted7.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/defaulted8.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/defaulted9.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/deleted1.C6
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/dependent1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/diag1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/elision.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/elision2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/elision_neg.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/enum1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/enum10.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/enum11.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/enum12.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/enum13.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/enum14.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/enum15.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/enum16.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/enum17.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/enum18.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/enum19.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/enum2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/enum20.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/enum21b.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/enum3.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/enum4.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/enum5.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/enum6.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/enum7.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/enum8.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/enum9.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/enum_base.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/enum_base_warn.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/error1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/error2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/error3.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/error4.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/error5.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/error6.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/error7.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/explicit1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/explicit2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/explicit3.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/explicit4.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/explicit5.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/explicit6.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/explicit7.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/extern_template-1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/extern_template-2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/fntmpdefarg1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/fntmpdefarg2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/forw_enum1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/forw_enum10.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/forw_enum2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/forw_enum3.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/forw_enum4.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/forw_enum5.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/forw_enum6.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/forw_enum7.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/forw_enum8.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/forw_enum9.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/friend1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/friend2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/gen-attrs-55.C12
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/gen-attrs-56.C5
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/implicit-copy.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/implicit-trivial1.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/implicit1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/implicit10.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/implicit11.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/implicit12.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/implicit2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/implicit3.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/implicit4.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/implicit5.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/implicit6.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/implicit7.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/implicit8.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/implicit9.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist-array2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist-arrray1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist-deduce.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist-lifetime1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist-lifetime2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist-opt.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist-postfix-open-square.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist-value.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist-value2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist10.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist11.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist12.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist13.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist14.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist15.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist16.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist17.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist18.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist19.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist20.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist21.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist22.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist23.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist24.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist25.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist26.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist27.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist28.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist29.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist3.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist30.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist31.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist32.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist33.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist34.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist35.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist36.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist37.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist38.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist39.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist4.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist40.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist41.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist42.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist43.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist44.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist45.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist46.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist47.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist48.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist49.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist5.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist50.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist51.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist52.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist53.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist54.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist55.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist56.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist57.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist58.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist59.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist6.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist62.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist64.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist7.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist74.C7
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist8.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist9.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/inline-ns1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/inline-ns2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/inline-ns3.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/iop.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice10.C8
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nsdmi5.C7
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this17.C21
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/linkage2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/long_long.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/move1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/named.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/named_refs.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/noexcept01.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/noexcept02.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/noexcept03.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/noexcept04.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/noexcept05.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/noexcept06.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/noexcept07.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/noexcept08.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/noexcept09.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/noexcept10.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/noexcept11.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/noexcept12.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/noexcept13.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/noexcept14.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/noexcept15.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nolinkage1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/not_special.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nsdmi-const1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nsdmi-defer1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nsdmi-defer2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nsdmi-defer3.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nsdmi-defer4.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nsdmi-defer5.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nsdmi-eh1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nsdmi-list1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nsdmi-list2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nsdmi-template1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nsdmi-template2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nsdmi-virtual1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nsdmi1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nsdmi2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nsdmi3.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nsdmi4.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nsdmi5.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nsdmi9.C13
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nullptr01.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nullptr02.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nullptr03.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nullptr04.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nullptr05.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nullptr06.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nullptr07.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nullptr08.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nullptr09.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nullptr10.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nullptr11.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nullptr12.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nullptr13.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nullptr14.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nullptr15.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nullptr16.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nullptr17.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nullptr18.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nullptr19.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nullptr20.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nullptr21.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nullptr22.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nullptr23.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nullptr24.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nullptr25.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nullptr26.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nullptr30.C40
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/overload-conv-1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/overload-conv-2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/overload.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/overload2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/overloadn.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/override1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/override2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/parse1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr31431-2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr31431.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr31432.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr31434.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr31437.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr31438.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr31439.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr31442.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr31443.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr31444.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr31445.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr31993.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr32114.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr32115.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr32125.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr32126.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr32127.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr32128.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr32252.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr32253.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr32566.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr33839.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr33930.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr33955.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr33996.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr34054.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr34056.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr34057.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr34058.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr34060.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr34061.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr38646.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr38795.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr39639.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr42844-2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr45908.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr47416.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr47476.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr48522.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr50491.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr50901.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr51150.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr51216.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr51225.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr51313.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr51547.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr51619.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr58510.C11
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr58563.C8
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr58707.C6
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/range-for1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/range-for10.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/range-for11.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/range-for12.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/range-for13.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/range-for14.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/range-for15.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/range-for16.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/range-for17.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/range-for18.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/range-for19.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/range-for2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/range-for20.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/range-for21.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/range-for22.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/range-for26.C7
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/range-for27.C15
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/range-for3.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/range-for4.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/range-for5.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/range-for6.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/range-for7.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/range-for8.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/reference_collapsing.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv-bitfield.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv-bitfield2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv-cast.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv-cast2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv-conv1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv-deduce.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv-deduce2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv-dotstar.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv-func.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv-func2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv-func3.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv-lvalue-req.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv-reinterpret.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv-restrict.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv-return.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv-template1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv-trivial-bug.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv10.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv1n.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv1p.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv2n.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv2p.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv3n.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv3p.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv4n.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv4p.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv5n.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv5p.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv6n.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv6p.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv7n.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv7p.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv8p.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv9p.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rvo.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/scoped_enum.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/scoped_enum2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/scoped_enum_examples.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/sfinae1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/sfinae10.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/sfinae11.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/sfinae12.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/sfinae13.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/sfinae14.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/sfinae15.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/sfinae16.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/sfinae17.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/sfinae18.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/sfinae19.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/sfinae2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/sfinae20.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/sfinae21.C8
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/sfinae22.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/sfinae23.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/sfinae24.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/sfinae25.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/sfinae26.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/sfinae27.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/sfinae28.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/sfinae29.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/sfinae3.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/sfinae31.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/sfinae32.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/sfinae4.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/sfinae49.C29
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/sfinae5.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/sfinae6.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/sfinae7.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/sfinae8.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/sfinae9.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/static_assert1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/static_assert2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/static_assert3.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/static_assert4.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/static_assert5.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/static_assert6.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/std-layout1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/syntax-err1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/temp-constructor-bug.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/temp-va-arg-bug.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/temp_default1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/temp_default2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/temp_default3.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/temp_default4.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/template_deduction.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/trailing1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/trailing3.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/trailing4.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/trailing5.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/trailing6.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/trailing7.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/trivial1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-addr.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-args-neg.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-args.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-clink-neg.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-concat-neg.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-concat.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-constexpr.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-declare-neg.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-embed-quote.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-friend.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-general.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-implicit-conv-neg.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-inline.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-linkage-neg.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-mangle.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-member-neg.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-namespace.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-nofunc-neg.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-nonempty-str-neg.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-nospace-neg.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-nosuffix-neg.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-nounder-neg.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-operator-neg.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-overflow-neg.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-overflow.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-preproc-neg.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-raw-length.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-raw-op-string-neg.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-raw-op.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-raw-str.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-resolve.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-shadow-neg.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-string-length.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-suffix-neg.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-systemheader.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-template.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-arg-neg.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-arg.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-parms-neg.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-parms.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/union1.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/union2.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/union3.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/union4.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/union5.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/unnamed_refs.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-104.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-bind.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-crash1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-crash2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-default.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-ex1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-ex10.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-ex11.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-ex12.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-ex13.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-ex14.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-ex2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-ex3.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-ex4.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-ex5.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-ex6.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-ex7.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-ex8.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-ex9.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-explicit1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-function.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-init.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-lambda.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-mem_fn.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-new.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-new2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-nondeduce1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-rref.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-throw.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-ttp.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-tuple.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-unify-2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-unify.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-unresolved.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic10.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic100.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic101.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic102.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic103.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic105.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic106.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic107.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic108.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic109.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic11.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic110.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic111.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic112.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic113.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic114.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic115.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic116.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic117.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic118.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic12.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic121.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic13.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic135.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic14.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic143.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic144.C15
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic15.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic16.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic17.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic18.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic19.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic20.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic21.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic22.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic23.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic24.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic25.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic26.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic27.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic28.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic29.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic3.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic30.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic31.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic32.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic33.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic34.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic35.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic36.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic37.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic38.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic39.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic4.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic40.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic41.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic42.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic43.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic44.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic45.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic46.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic47.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic48.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic49.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic5.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic50.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic51.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic52.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic53.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic54.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic55.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic56.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic57.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic58.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic59.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic6.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic63.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic64.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic65.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic66.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic67.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic68.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic69.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic7.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic70.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic71.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic72.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic73.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic75.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic76.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic77.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic78.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic79.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic8.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic80.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic81.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic82.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic83.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic84.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic85.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic86.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic87.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic88.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic89.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic9.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic90.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic91.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic92.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic93.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic94.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic95.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic96.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic97.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic98.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic99.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/vt-33964.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/vt-34050.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/vt-34051-2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/vt-34051.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/vt-34052.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/vt-34055.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/vt-34102.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/vt-34103.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/vt-34219-2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/vt-34219.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/vt-34314.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/vt-34399.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/vt-34606.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/vt-34751.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/vt-34753.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/vt-34754.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/vt-34755.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/vt-34919.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/vt-34961.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/vt-35023.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/vt-35024.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/vt-35026.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/vt-35147.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/vt-35242.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/vt-35243.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/vt-35331.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/vt-37737-1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/vt-37737-2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/vt-40092.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/attr-deprecated-neg.C59
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/attr-deprecated.C59
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/digit-sep-cxx11-neg.C12
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/digit-sep-neg.C26
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/digit-sep.C22
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/pr58500.C8
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/pr58535.C7
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/pr58708.C60
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/pr58979.C4
-rw-r--r--gcc/testsuite/g++.dg/ext/altivec-7.C22
-rw-r--r--gcc/testsuite/g++.dg/ext/anon-struct4.C4
-rw-r--r--gcc/testsuite/g++.dg/ext/attrib47.C21
-rw-r--r--gcc/testsuite/g++.dg/ext/pr58834.C5
-rw-r--r--gcc/testsuite/g++.dg/ext/sync-4.C122
-rw-r--r--gcc/testsuite/g++.dg/gomp/block-0.C6
-rw-r--r--gcc/testsuite/g++.dg/gomp/block-3.C6
-rw-r--r--gcc/testsuite/g++.dg/gomp/clause-3.C10
-rw-r--r--gcc/testsuite/g++.dg/gomp/declare-simd-1.C243
-rw-r--r--gcc/testsuite/g++.dg/gomp/declare-simd-2.C98
-rw-r--r--gcc/testsuite/g++.dg/gomp/depend-1.C70
-rw-r--r--gcc/testsuite/g++.dg/gomp/depend-2.C87
-rw-r--r--gcc/testsuite/g++.dg/gomp/gomp.exp4
-rw-r--r--gcc/testsuite/g++.dg/gomp/openmp-simd-1.C46
-rw-r--r--gcc/testsuite/g++.dg/gomp/openmp-simd-2.C44
-rw-r--r--gcc/testsuite/g++.dg/gomp/simd-1.C31
-rw-r--r--gcc/testsuite/g++.dg/gomp/target-1.C32
-rw-r--r--gcc/testsuite/g++.dg/gomp/target-2.C32
-rw-r--r--gcc/testsuite/g++.dg/gomp/taskgroup-1.C32
-rw-r--r--gcc/testsuite/g++.dg/gomp/teams-1.C66
-rw-r--r--gcc/testsuite/g++.dg/gomp/udr-1.C119
-rw-r--r--gcc/testsuite/g++.dg/gomp/udr-2.C119
-rw-r--r--gcc/testsuite/g++.dg/gomp/udr-3.C191
-rw-r--r--gcc/testsuite/g++.dg/gomp/udr-4.C14
-rw-r--r--gcc/testsuite/g++.dg/gomp/udr-5.C41
-rw-r--r--gcc/testsuite/g++.dg/gomp/udr-6.C59
-rw-r--r--gcc/testsuite/g++.dg/init/array35.C3
-rw-r--r--gcc/testsuite/g++.dg/init/ctor8.C5
-rw-r--r--gcc/testsuite/g++.dg/init/pr25811.C104
-rw-r--r--gcc/testsuite/g++.dg/init/pr29043.C18
-rw-r--r--gcc/testsuite/g++.dg/init/pr43719.C104
-rw-r--r--gcc/testsuite/g++.dg/init/pr44086.C12
-rw-r--r--gcc/testsuite/g++.dg/init/ref14.C2
-rw-r--r--gcc/testsuite/g++.dg/init/uninitialized1.C12
-rw-r--r--gcc/testsuite/g++.dg/lookup/name-clash10.C8
-rw-r--r--gcc/testsuite/g++.dg/lto/lto.exp2
-rw-r--r--gcc/testsuite/g++.dg/lto/pr54625-1_0.c (renamed from gcc/testsuite/gcc.dg/lto/pr54625-1_0.c)0
-rw-r--r--gcc/testsuite/g++.dg/lto/pr54625-1_1.C (renamed from gcc/testsuite/gcc.dg/lto/pr54625-1_1.C)0
-rw-r--r--gcc/testsuite/g++.dg/lto/pr54625-2_0.c (renamed from gcc/testsuite/gcc.dg/lto/pr54625-2_0.c)0
-rw-r--r--gcc/testsuite/g++.dg/lto/pr54625-2_1.C (renamed from gcc/testsuite/gcc.dg/lto/pr54625-2_1.C)0
-rw-r--r--gcc/testsuite/g++.dg/opt/devirt3.C24
-rw-r--r--gcc/testsuite/g++.dg/other/java3.C7
-rw-r--r--gcc/testsuite/g++.dg/other/warning1.C4
-rw-r--r--gcc/testsuite/g++.dg/parse/crash64.C7
-rw-r--r--gcc/testsuite/g++.dg/parse/crash65.C6
-rw-r--r--gcc/testsuite/g++.dg/parse/ivdep.C11
-rw-r--r--gcc/testsuite/g++.dg/parse/pr29234.C16
-rw-r--r--gcc/testsuite/g++.dg/parse/pr52071.C23
-rw-r--r--gcc/testsuite/g++.dg/parse/pr56037.C12
-rw-r--r--gcc/testsuite/g++.dg/parse/pr58705.C5
-rw-r--r--gcc/testsuite/g++.dg/plugin/header_plugin.c1
-rw-r--r--gcc/testsuite/g++.dg/plugin/selfassign.c1
-rw-r--r--gcc/testsuite/g++.dg/template/nontype26.C20
-rw-r--r--gcc/testsuite/g++.dg/template/pr58878.C61
-rw-r--r--gcc/testsuite/g++.dg/tm/pr58516.C7
-rw-r--r--gcc/testsuite/g++.dg/tm/pr58635-1.C14
-rw-r--r--gcc/testsuite/g++.dg/tm/pr58635-2.C8
-rw-r--r--gcc/testsuite/g++.dg/torture/pr49309.C16
-rw-r--r--gcc/testsuite/g++.dg/torture/pr58369.C109
-rw-r--r--gcc/testsuite/g++.dg/torture/pr58464.C268
-rw-r--r--gcc/testsuite/g++.dg/torture/pr58552.C29
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/pr19476-1.C16
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/pr19476-2.C17
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/pr19476-3.C11
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/pr19476-4.C11
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/pr19476-5.C11
-rw-r--r--gcc/testsuite/g++.dg/ubsan/cxx1y-vla.C13
-rw-r--r--gcc/testsuite/g++.dg/vect/pr33426-ivdep-2.cc39
-rw-r--r--gcc/testsuite/g++.dg/vect/pr33426-ivdep-3.cc25
-rw-r--r--gcc/testsuite/g++.dg/vect/pr33426-ivdep-4.cc30
-rw-r--r--gcc/testsuite/g++.dg/vect/pr33426-ivdep.cc19
-rw-r--r--gcc/testsuite/g++.dg/vect/pr58513.cc13
-rw-r--r--gcc/testsuite/g++.dg/vect/slp-pr56812.cc2
-rw-r--r--gcc/testsuite/g++.dg/warn/pr33738.C1
-rw-r--r--gcc/testsuite/g++.dg/warn/wdate-time.C6
-rw-r--r--gcc/testsuite/g++.old-deja/g++.mike/misc9.C2
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/20010327-1.c5
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/20020604-1.c3
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/20080625-1.c3
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/990617-1.c4
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/calls.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/limits-externdecl.c3
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr41181.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr55955.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr58775.c26
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr58946.c20
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr58970-1.c11
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr58970-2.c11
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr58978.c16
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr58997.c19
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/20030125-1.c4
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/strncmp-2.c2
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr58564.c14
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr58570.c22
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr58574.c219
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr58640-2.c35
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr58640.c32
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr58662.c22
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr58831.c40
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr58984.c57
-rw-r--r--gcc/testsuite/gcc.dg/20020312-2.c4
-rw-r--r--gcc/testsuite/gcc.dg/20050922-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/20050922-2.c3
-rw-r--r--gcc/testsuite/gcc.dg/atomic-compare-exchange-1.c1
-rw-r--r--gcc/testsuite/gcc.dg/atomic-compare-exchange-2.c1
-rw-r--r--gcc/testsuite/gcc.dg/atomic-compare-exchange-3.c1
-rw-r--r--gcc/testsuite/gcc.dg/atomic-compare-exchange-4.c1
-rw-r--r--gcc/testsuite/gcc.dg/atomic-compare-exchange-5.c1
-rw-r--r--gcc/testsuite/gcc.dg/atomic-exchange-1.c16
-rw-r--r--gcc/testsuite/gcc.dg/atomic-exchange-2.c16
-rw-r--r--gcc/testsuite/gcc.dg/atomic-exchange-3.c16
-rw-r--r--gcc/testsuite/gcc.dg/atomic-exchange-4.c16
-rw-r--r--gcc/testsuite/gcc.dg/atomic-exchange-5.c16
-rw-r--r--gcc/testsuite/gcc.dg/atomic-fence.c1
-rw-r--r--gcc/testsuite/gcc.dg/atomic-flag.c1
-rw-r--r--gcc/testsuite/gcc.dg/atomic-generic.c1
-rw-r--r--gcc/testsuite/gcc.dg/atomic-invalid.c1
-rw-r--r--gcc/testsuite/gcc.dg/atomic-load-1.c1
-rw-r--r--gcc/testsuite/gcc.dg/atomic-load-2.c1
-rw-r--r--gcc/testsuite/gcc.dg/atomic-load-3.c1
-rw-r--r--gcc/testsuite/gcc.dg/atomic-load-4.c1
-rw-r--r--gcc/testsuite/gcc.dg/atomic-load-5.c1
-rw-r--r--gcc/testsuite/gcc.dg/atomic-lockfree.c1
-rw-r--r--gcc/testsuite/gcc.dg/atomic-noinline.c1
-rw-r--r--gcc/testsuite/gcc.dg/atomic-op-1.c1
-rw-r--r--gcc/testsuite/gcc.dg/atomic-op-2.c1
-rw-r--r--gcc/testsuite/gcc.dg/atomic-op-3.c1
-rw-r--r--gcc/testsuite/gcc.dg/atomic-op-4.c1
-rw-r--r--gcc/testsuite/gcc.dg/atomic-op-5.c1
-rw-r--r--gcc/testsuite/gcc.dg/atomic-param.c1
-rw-r--r--gcc/testsuite/gcc.dg/atomic-store-1.c1
-rw-r--r--gcc/testsuite/gcc.dg/atomic-store-2.c1
-rw-r--r--gcc/testsuite/gcc.dg/atomic-store-3.c1
-rw-r--r--gcc/testsuite/gcc.dg/atomic-store-4.c1
-rw-r--r--gcc/testsuite/gcc.dg/atomic-store-5.c1
-rw-r--r--gcc/testsuite/gcc.dg/atomic-store-6.c13
-rw-r--r--gcc/testsuite/gcc.dg/atomic/atomic.exp34
-rw-r--r--gcc/testsuite/gcc.dg/atomic/c11-atomic-exec-1.c88
-rw-r--r--gcc/testsuite/gcc.dg/atomic/c11-atomic-exec-2.c171
-rw-r--r--gcc/testsuite/gcc.dg/atomic/c11-atomic-exec-3.c85
-rw-r--r--gcc/testsuite/gcc.dg/atomic/c11-atomic-exec-4.c208
-rw-r--r--gcc/testsuite/gcc.dg/atomic/c11-atomic-exec-5.c541
-rw-r--r--gcc/testsuite/gcc.dg/atomic/stdatomic-compare-exchange-1.c81
-rw-r--r--gcc/testsuite/gcc.dg/atomic/stdatomic-compare-exchange-2.c81
-rw-r--r--gcc/testsuite/gcc.dg/atomic/stdatomic-compare-exchange-3.c81
-rw-r--r--gcc/testsuite/gcc.dg/atomic/stdatomic-compare-exchange-4.c81
-rw-r--r--gcc/testsuite/gcc.dg/atomic/stdatomic-exchange-1.c46
-rw-r--r--gcc/testsuite/gcc.dg/atomic/stdatomic-exchange-2.c46
-rw-r--r--gcc/testsuite/gcc.dg/atomic/stdatomic-exchange-3.c46
-rw-r--r--gcc/testsuite/gcc.dg/atomic/stdatomic-exchange-4.c46
-rw-r--r--gcc/testsuite/gcc.dg/atomic/stdatomic-fence.c26
-rw-r--r--gcc/testsuite/gcc.dg/atomic/stdatomic-flag.c38
-rw-r--r--gcc/testsuite/gcc.dg/atomic/stdatomic-generic.c52
-rw-r--r--gcc/testsuite/gcc.dg/atomic/stdatomic-kill-dep.c19
-rw-r--r--gcc/testsuite/gcc.dg/atomic/stdatomic-load-1.c44
-rw-r--r--gcc/testsuite/gcc.dg/atomic/stdatomic-load-2.c44
-rw-r--r--gcc/testsuite/gcc.dg/atomic/stdatomic-load-3.c44
-rw-r--r--gcc/testsuite/gcc.dg/atomic/stdatomic-load-4.c44
-rw-r--r--gcc/testsuite/gcc.dg/atomic/stdatomic-lockfree.c68
-rw-r--r--gcc/testsuite/gcc.dg/atomic/stdatomic-op-1.c341
-rw-r--r--gcc/testsuite/gcc.dg/atomic/stdatomic-op-2.c341
-rw-r--r--gcc/testsuite/gcc.dg/atomic/stdatomic-op-3.c341
-rw-r--r--gcc/testsuite/gcc.dg/atomic/stdatomic-op-4.c341
-rw-r--r--gcc/testsuite/gcc.dg/atomic/stdatomic-store-1.c43
-rw-r--r--gcc/testsuite/gcc.dg/atomic/stdatomic-store-2.c43
-rw-r--r--gcc/testsuite/gcc.dg/atomic/stdatomic-store-3.c43
-rw-r--r--gcc/testsuite/gcc.dg/atomic/stdatomic-store-4.c43
-rw-r--r--gcc/testsuite/gcc.dg/autopar/outer-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/autopar/outer-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/autopar/outer-3.c2
-rw-r--r--gcc/testsuite/gcc.dg/autopar/outer-4.c2
-rw-r--r--gcc/testsuite/gcc.dg/autopar/outer-5.c2
-rw-r--r--gcc/testsuite/gcc.dg/autopar/outer-6.c2
-rw-r--r--gcc/testsuite/gcc.dg/autopar/parallelization-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/builtin-apply2.c2
-rw-r--r--gcc/testsuite/gcc.dg/builtin-complex-err-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/c11-align-1.c41
-rw-r--r--gcc/testsuite/gcc.dg/c11-align-2.c92
-rw-r--r--gcc/testsuite/gcc.dg/c11-align-3.c43
-rw-r--r--gcc/testsuite/gcc.dg/c11-align-4.c9
-rw-r--r--gcc/testsuite/gcc.dg/c11-align-5.c28
-rw-r--r--gcc/testsuite/gcc.dg/c11-anon-struct-1.c72
-rw-r--r--gcc/testsuite/gcc.dg/c11-anon-struct-2.c57
-rw-r--r--gcc/testsuite/gcc.dg/c11-anon-struct-3.c34
-rw-r--r--gcc/testsuite/gcc.dg/c11-atomic-1.c267
-rw-r--r--gcc/testsuite/gcc.dg/c11-atomic-2.c165
-rw-r--r--gcc/testsuite/gcc.dg/c11-atomic-3.c174
-rw-r--r--gcc/testsuite/gcc.dg/c11-float-1.c169
-rw-r--r--gcc/testsuite/gcc.dg/c11-noreturn-1.c59
-rw-r--r--gcc/testsuite/gcc.dg/c11-noreturn-2.c77
-rw-r--r--gcc/testsuite/gcc.dg/c11-noreturn-3.c11
-rw-r--r--gcc/testsuite/gcc.dg/c11-noreturn-4.c11
-rw-r--r--gcc/testsuite/gcc.dg/c11-noreturn-5.c17
-rw-r--r--gcc/testsuite/gcc.dg/c11-pointer-float-1.c28
-rw-r--r--gcc/testsuite/gcc.dg/c11-static-assert-1.c41
-rw-r--r--gcc/testsuite/gcc.dg/c11-static-assert-2.c41
-rw-r--r--gcc/testsuite/gcc.dg/c11-static-assert-3.c28
-rw-r--r--gcc/testsuite/gcc.dg/c11-static-assert-4.c13
-rw-r--r--gcc/testsuite/gcc.dg/c11-static-assert-5.c5
-rw-r--r--gcc/testsuite/gcc.dg/c11-static-assert-6.c5
-rw-r--r--gcc/testsuite/gcc.dg/c11-stdatomic-1.c119
-rw-r--r--gcc/testsuite/gcc.dg/c11-typedef-1.c70
-rw-r--r--gcc/testsuite/gcc.dg/c11-uni-string-1.c112
-rw-r--r--gcc/testsuite/gcc.dg/c11-uni-string-2.c8
-rw-r--r--gcc/testsuite/gcc.dg/c1x-align-1.c41
-rw-r--r--gcc/testsuite/gcc.dg/c1x-align-2.c92
-rw-r--r--gcc/testsuite/gcc.dg/c1x-align-3.c43
-rw-r--r--gcc/testsuite/gcc.dg/c1x-align-4.c9
-rw-r--r--gcc/testsuite/gcc.dg/c1x-anon-struct-1.c72
-rw-r--r--gcc/testsuite/gcc.dg/c1x-anon-struct-2.c57
-rw-r--r--gcc/testsuite/gcc.dg/c1x-anon-struct-3.c34
-rw-r--r--gcc/testsuite/gcc.dg/c1x-float-1.c169
-rw-r--r--gcc/testsuite/gcc.dg/c1x-noreturn-1.c59
-rw-r--r--gcc/testsuite/gcc.dg/c1x-noreturn-2.c77
-rw-r--r--gcc/testsuite/gcc.dg/c1x-noreturn-3.c11
-rw-r--r--gcc/testsuite/gcc.dg/c1x-noreturn-4.c11
-rw-r--r--gcc/testsuite/gcc.dg/c1x-noreturn-5.c17
-rw-r--r--gcc/testsuite/gcc.dg/c1x-pointer-float-1.c28
-rw-r--r--gcc/testsuite/gcc.dg/c1x-static-assert-1.c41
-rw-r--r--gcc/testsuite/gcc.dg/c1x-static-assert-2.c41
-rw-r--r--gcc/testsuite/gcc.dg/c1x-static-assert-3.c28
-rw-r--r--gcc/testsuite/gcc.dg/c1x-static-assert-4.c13
-rw-r--r--gcc/testsuite/gcc.dg/c1x-static-assert-5.c5
-rw-r--r--gcc/testsuite/gcc.dg/c1x-static-assert-6.c5
-rw-r--r--gcc/testsuite/gcc.dg/c1x-typedef-1.c70
-rw-r--r--gcc/testsuite/gcc.dg/c1x-uni-string-1.c112
-rw-r--r--gcc/testsuite/gcc.dg/c1x-uni-string-2.c8
-rw-r--r--gcc/testsuite/gcc.dg/c90-atomic-1.c7
-rw-r--r--gcc/testsuite/gcc.dg/c90-float-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/c99-atomic-1.c8
-rw-r--r--gcc/testsuite/gcc.dg/c99-float-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/c99-stdint-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/c99-stdint-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/cdce1.c3
-rw-r--r--gcc/testsuite/gcc.dg/cilk-plus/cilk-plus.exp34
-rw-r--r--gcc/testsuite/gcc.dg/dfp/pr35739.c16
-rw-r--r--gcc/testsuite/gcc.dg/fold-overflow-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/ftrapv-1.c1
-rw-r--r--gcc/testsuite/gcc.dg/ftrapv-2.c1
-rw-r--r--gcc/testsuite/gcc.dg/gomp/appendix-a/a.35.1.c2
-rw-r--r--gcc/testsuite/gcc.dg/gomp/appendix-a/a.35.3.c2
-rw-r--r--gcc/testsuite/gcc.dg/gomp/appendix-a/a.35.4.c2
-rw-r--r--gcc/testsuite/gcc.dg/gomp/appendix-a/a.35.5.c2
-rw-r--r--gcc/testsuite/gcc.dg/gomp/appendix-a/a.35.6.c2
-rw-r--r--gcc/testsuite/gcc.dg/gomp/block-3.c7
-rw-r--r--gcc/testsuite/gcc.dg/gomp/clause-1.c8
-rw-r--r--gcc/testsuite/gcc.dg/gomp/combined-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/gomp/declare-simd-1.c100
-rw-r--r--gcc/testsuite/gcc.dg/gomp/declare-simd-2.c54
-rw-r--r--gcc/testsuite/gcc.dg/gomp/gomp.exp4
-rw-r--r--gcc/testsuite/gcc.dg/gomp/nesting-1.c41
-rw-r--r--gcc/testsuite/gcc.dg/gomp/openmp-simd-1.c46
-rw-r--r--gcc/testsuite/gcc.dg/gomp/openmp-simd-2.c42
-rw-r--r--gcc/testsuite/gcc.dg/gomp/pr58809.c13
-rw-r--r--gcc/testsuite/gcc.dg/gomp/target-1.c29
-rw-r--r--gcc/testsuite/gcc.dg/gomp/target-2.c29
-rw-r--r--gcc/testsuite/gcc.dg/gomp/taskgroup-1.c29
-rw-r--r--gcc/testsuite/gcc.dg/gomp/teams-1.c61
-rw-r--r--gcc/testsuite/gcc.dg/gomp/udr-1.c46
-rw-r--r--gcc/testsuite/gcc.dg/gomp/udr-2.c42
-rw-r--r--gcc/testsuite/gcc.dg/gomp/udr-3.c77
-rw-r--r--gcc/testsuite/gcc.dg/gomp/udr-4.c6
-rw-r--r--gcc/testsuite/gcc.dg/guality/pr58791-1.c34
-rw-r--r--gcc/testsuite/gcc.dg/guality/pr58791-2.c36
-rw-r--r--gcc/testsuite/gcc.dg/guality/pr58791-3.c28
-rw-r--r--gcc/testsuite/gcc.dg/guality/pr58791-4.c41
-rw-r--r--gcc/testsuite/gcc.dg/guality/pr58791-5.c29
-rw-r--r--gcc/testsuite/gcc.dg/iec-559-macros-1.c16
-rw-r--r--gcc/testsuite/gcc.dg/iec-559-macros-2.c23
-rw-r--r--gcc/testsuite/gcc.dg/iec-559-macros-3.c23
-rw-r--r--gcc/testsuite/gcc.dg/iec-559-macros-4.c23
-rw-r--r--gcc/testsuite/gcc.dg/iec-559-macros-5.c23
-rw-r--r--gcc/testsuite/gcc.dg/iec-559-macros-6.c23
-rw-r--r--gcc/testsuite/gcc.dg/iec-559-macros-7.c20
-rw-r--r--gcc/testsuite/gcc.dg/iec-559-macros-8.c20
-rw-r--r--gcc/testsuite/gcc.dg/iec-559-macros-9.c23
-rw-r--r--gcc/testsuite/gcc.dg/ipa/pr58492.c7
-rw-r--r--gcc/testsuite/gcc.dg/ivdep.c11
-rw-r--r--gcc/testsuite/gcc.dg/mismatch-decl-1.c22
-rw-r--r--gcc/testsuite/gcc.dg/plugin/finish_unit_plugin.c1
-rw-r--r--gcc/testsuite/gcc.dg/plugin/ggcplug.c1
-rw-r--r--gcc/testsuite/gcc.dg/plugin/one_time_plugin.c1
-rw-r--r--gcc/testsuite/gcc.dg/plugin/selfassign.c1
-rw-r--r--gcc/testsuite/gcc.dg/plugin/start_unit_plugin.c1
-rw-r--r--gcc/testsuite/gcc.dg/pr19340.c2
-rw-r--r--gcc/testsuite/gcc.dg/pr30286.c1
-rw-r--r--gcc/testsuite/gcc.dg/pr38364.c1
-rw-r--r--gcc/testsuite/gcc.dg/pr38984.c2
-rw-r--r--gcc/testsuite/gcc.dg/pr57518.c4
-rw-r--r--gcc/testsuite/gcc.dg/pr58463.c15
-rw-r--r--gcc/testsuite/gcc.dg/pr58805.c24
-rw-r--r--gcc/testsuite/gcc.dg/pr58981.c55
-rw-r--r--gcc/testsuite/gcc.dg/superblock.c1
-rw-r--r--gcc/testsuite/gcc.dg/tls/pr42894.c1
-rw-r--r--gcc/testsuite/gcc.dg/torture/builtin-complex-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/torture/builtin-self.c10
-rw-r--r--gcc/testsuite/gcc.dg/torture/c99-contract-1.c21
-rw-r--r--gcc/testsuite/gcc.dg/torture/float128-cmp-invalid.c18
-rw-r--r--gcc/testsuite/gcc.dg/torture/float128-div-underflow.c18
-rw-r--r--gcc/testsuite/gcc.dg/torture/float128-extend-nan.c22
-rw-r--r--gcc/testsuite/gcc.dg/torture/fp-int-convert-float128-timode-3.c23
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr51244-21.c75
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr57748-1.c49
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr57748-2.c43
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr58143-1.c51
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr58143-2.c34
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr58143-3.c18
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr58539.c20
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr58553.c28
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr58554.c20
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr58626.c20
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr58670.c47
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr58779.c12
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr58830.c42
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr58941.c33
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr58955-1.c20
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr58955-2.c18
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr59038.c25
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr59047.c39
-rw-r--r--gcc/testsuite/gcc.dg/torture/restrict-2.c27
-rw-r--r--gcc/testsuite/gcc.dg/torture/restrict-3.c26
-rw-r--r--gcc/testsuite/gcc.dg/torture/restrict-4.c26
-rw-r--r--gcc/testsuite/gcc.dg/torture/restrict-5.c25
-rw-r--r--gcc/testsuite/gcc.dg/tree-prof/time-profiler-1.c22
-rw-r--r--gcc/testsuite/gcc.dg/tree-prof/time-profiler-2.c50
-rw-r--r--gcc/testsuite/gcc.dg/tree-prof/tree-prof.exp2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/alias-23.c18
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/alias-24.c22
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/alias-25.c12
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/alias-26.c13
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/alias-27.c11
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/coalesce-2.c16
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/forwprop-28.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/gen-vect-11.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/gen-vect-11a.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/gen-vect-2.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/gen-vect-25.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/gen-vect-26.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/gen-vect-28.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ipa-split-5.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ipa-split-6.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/isolate-1.c58
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/isolate-2.c43
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/isolate-3.c65
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/isolate-4.c32
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ivopt_infer_2.c5
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ivopt_mult_3.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ldist-11.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ldist-17.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ldist-23.c34
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ldist-pr45948.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/loop-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/loop-39.c26
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/phi-opt-11.c25
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/phi-opt-9.c3
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr20318.c19
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr58480.c19
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr58958.c12
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/predcom-6.c13
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/predcom-7.c18
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/reassoc-28.c7
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/reassoc-32.c29
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/reassoc-33.c27
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/reassoc-34.c24
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/reassoc-35.c26
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/reassoc-36.c25
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/slsr-40.c27
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-3.c47
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-4.c5
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-ccmp-1.c14
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-ccmp-2.c17
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-ccmp-3.c20
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-ccmp-4.c18
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-ccmp-5.c13
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-ccmp-6.c13
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-31.c47
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/vrp47.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/vrp87.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/vrp90.c36
-rw-r--r--gcc/testsuite/gcc.dg/ubsan/c-shift-1.c18
-rw-r--r--gcc/testsuite/gcc.dg/unroll_1.c2
-rw-r--r--gcc/testsuite/gcc.dg/unroll_2.c2
-rw-r--r--gcc/testsuite/gcc.dg/unroll_3.c2
-rw-r--r--gcc/testsuite/gcc.dg/unroll_4.c2
-rw-r--r--gcc/testsuite/gcc.dg/utf-cvt.c2
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-31.c1
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-32.c2
-rw-r--r--gcc/testsuite/gcc.dg/vect/costmodel/i386/i386-costmodel-vect.exp2
-rw-r--r--gcc/testsuite/gcc.dg/vect/costmodel/ppc/ppc-costmodel-vect.exp2
-rw-r--r--gcc/testsuite/gcc.dg/vect/costmodel/spu/spu-costmodel-vect.exp2
-rw-r--r--gcc/testsuite/gcc.dg/vect/costmodel/x86_64/x86_64-costmodel-vect.exp2
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr58508.c70
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-alias-check.c18
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-align-3.c54
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-ivdep-1.c19
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-ivdep-2.c35
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-reduc-pattern-3.c41
-rw-r--r--gcc/testsuite/gcc.dg/vmx/eg-5.c7
-rw-r--r--gcc/testsuite/gcc.dg/vmx/gcc-bug-i.c15
-rw-r--r--gcc/testsuite/gcc.dg/vmx/vec-set.c14
-rw-r--r--gcc/testsuite/gcc.dg/wdate-time.c6
-rw-r--r--gcc/testsuite/gcc.dg/wmul-1.c19
-rw-r--r--gcc/testsuite/gcc.target/aarch64/c-output-template-2.c9
-rw-r--r--gcc/testsuite/gcc.target/aarch64/c-output-template-3.c10
-rw-r--r--gcc/testsuite/gcc.target/aarch64/c-output-template.c9
-rw-r--r--gcc/testsuite/gcc.target/aarch64/pr58460.c35
-rw-r--r--gcc/testsuite/gcc.target/aarch64/vadd_f64.c114
-rw-r--r--gcc/testsuite/gcc.target/aarch64/vclz.c574
-rw-r--r--gcc/testsuite/gcc.target/aarch64/vdiv_f.c361
-rw-r--r--gcc/testsuite/gcc.target/aarch64/vect_saddl_1.c315
-rw-r--r--gcc/testsuite/gcc.target/aarch64/vneg_f.c273
-rw-r--r--gcc/testsuite/gcc.target/aarch64/vneg_s.c309
-rw-r--r--gcc/testsuite/gcc.target/aarch64/vsub_f64.c116
-rw-r--r--gcc/testsuite/gcc.target/arc/barrel-shifter-1.c10
-rw-r--r--gcc/testsuite/gcc.target/arc/barrel-shifter-2.c9
-rw-r--r--gcc/testsuite/gcc.target/arc/jump-around-jump.c123
-rw-r--r--gcc/testsuite/gcc.target/arc/long-calls.c11
-rw-r--r--gcc/testsuite/gcc.target/arc/mA6.c4
-rw-r--r--gcc/testsuite/gcc.target/arc/mA7.c4
-rw-r--r--gcc/testsuite/gcc.target/arc/mARC600.c4
-rw-r--r--gcc/testsuite/gcc.target/arc/mARC601.c4
-rw-r--r--gcc/testsuite/gcc.target/arc/mARC700.c4
-rw-r--r--gcc/testsuite/gcc.target/arc/mcpu-arc600.c4
-rw-r--r--gcc/testsuite/gcc.target/arc/mcpu-arc601.c4
-rw-r--r--gcc/testsuite/gcc.target/arc/mcpu-arc700.c4
-rw-r--r--gcc/testsuite/gcc.target/arc/mcrc.c9
-rw-r--r--gcc/testsuite/gcc.target/arc/mdpfp.c11
-rw-r--r--gcc/testsuite/gcc.target/arc/mdsp-packa.c9
-rw-r--r--gcc/testsuite/gcc.target/arc/mdvbf.c9
-rw-r--r--gcc/testsuite/gcc.target/arc/mlock.c12
-rw-r--r--gcc/testsuite/gcc.target/arc/mmac-24.c9
-rw-r--r--gcc/testsuite/gcc.target/arc/mmac-d16.c9
-rw-r--r--gcc/testsuite/gcc.target/arc/mno-crc.c11
-rw-r--r--gcc/testsuite/gcc.target/arc/mno-dsp-packa.c11
-rw-r--r--gcc/testsuite/gcc.target/arc/mno-dvbf.c11
-rw-r--r--gcc/testsuite/gcc.target/arc/mno-lock.c14
-rw-r--r--gcc/testsuite/gcc.target/arc/mno-mac-24.c11
-rw-r--r--gcc/testsuite/gcc.target/arc/mno-mac-d16.c11
-rw-r--r--gcc/testsuite/gcc.target/arc/mno-rtsc.c11
-rw-r--r--gcc/testsuite/gcc.target/arc/mno-swape.c11
-rw-r--r--gcc/testsuite/gcc.target/arc/mno-xy.c10
-rw-r--r--gcc/testsuite/gcc.target/arc/mrtsc.c9
-rw-r--r--gcc/testsuite/gcc.target/arc/mspfp.c11
-rw-r--r--gcc/testsuite/gcc.target/arc/mswape.c9
-rw-r--r--gcc/testsuite/gcc.target/arc/mtune-ARC600.c4
-rw-r--r--gcc/testsuite/gcc.target/arc/mtune-ARC601.c4
-rw-r--r--gcc/testsuite/gcc.target/arc/mtune-ARC700-xmac4
-rw-r--r--gcc/testsuite/gcc.target/arc/mtune-ARC700.c4
-rw-r--r--gcc/testsuite/gcc.target/arc/mtune-ARC725D.c4
-rw-r--r--gcc/testsuite/gcc.target/arc/mtune-ARC750D.c4
-rw-r--r--gcc/testsuite/gcc.target/arc/mul64.c13
-rw-r--r--gcc/testsuite/gcc.target/arc/mxy.c8
-rw-r--r--gcc/testsuite/gcc.target/arc/no-dpfp-lrsr.c11
-rw-r--r--gcc/testsuite/gcc.target/arm/atomic-comp-swap-release-acquire.c2
-rw-r--r--gcc/testsuite/gcc.target/arm/lp1243022.c201
-rw-r--r--gcc/testsuite/gcc.target/arm/minmax_minus.c1
-rw-r--r--gcc/testsuite/gcc.target/arm/neon-vcond-gt.c2
-rw-r--r--gcc/testsuite/gcc.target/arm/neon-vcond-ltgt.c2
-rw-r--r--gcc/testsuite/gcc.target/arm/neon-vcond-unordered.c2
-rw-r--r--gcc/testsuite/gcc.target/arm/pr58578.c54
-rw-r--r--gcc/testsuite/gcc.target/arm/pr58784.c18
-rw-r--r--gcc/testsuite/gcc.target/arm/require-pic-register-loc.c29
-rw-r--r--gcc/testsuite/gcc.target/arm/thumb-ltu.c2
-rw-r--r--gcc/testsuite/gcc.target/avr/pr58545.c23
-rw-r--r--gcc/testsuite/gcc.target/i386/avx256-unaligned-load-1.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/avx256-unaligned-load-2.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/avx256-unaligned-load-3.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/avx256-unaligned-load-4.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/avx256-unaligned-store-2.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx256-unaligned-store-3.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/builtin-ucmp.c9
-rw-r--r--gcc/testsuite/gcc.target/i386/cold-attribute-2.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_double_3.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_double_5.c8
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_float_3.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_float_5.c8
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_double_1.c24
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_double_2.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_double_3.c24
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_double_4.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_double_5.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_double_6.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_float_1.c24
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_float_2.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_float_3.c24
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_float_4.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_float_5.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_float_6.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/memset-vector_loop-1.c11
-rw-r--r--gcc/testsuite/gcc.target/i386/memset-vector_loop-2.c10
-rw-r--r--gcc/testsuite/gcc.target/i386/pr30315.c44
-rw-r--r--gcc/testsuite/gcc.target/i386/pr49002-2.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/pr49168-1.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/pr57756.c22
-rw-r--r--gcc/testsuite/gcc.target/i386/pr57756_2.c132
-rw-r--r--gcc/testsuite/gcc.target/i386/pr58679-1.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/pr58679-2.c7
-rw-r--r--gcc/testsuite/gcc.target/i386/pr58690.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/pr58759.c38
-rw-r--r--gcc/testsuite/gcc.target/i386/pr58853.c9
-rw-r--r--gcc/testsuite/gcc.target/i386/pr59021.c23
-rw-r--r--gcc/testsuite/gcc.target/i386/pr59034-1.c10
-rw-r--r--gcc/testsuite/gcc.target/i386/pr59034-2.c10
-rw-r--r--gcc/testsuite/gcc.target/i386/vect-abs-s16.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/vect-abs-s32.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/vect-abs-s8.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/vect-div-1.c43
-rw-r--r--gcc/testsuite/gcc.target/mips/bswap-1.c10
-rw-r--r--gcc/testsuite/gcc.target/mips/bswap-2.c9
-rw-r--r--gcc/testsuite/gcc.target/mips/bswap-3.c14
-rw-r--r--gcc/testsuite/gcc.target/mips/bswap-4.c10
-rw-r--r--gcc/testsuite/gcc.target/mips/bswap-5.c20
-rw-r--r--gcc/testsuite/gcc.target/mips/bswap-6.c12
-rw-r--r--gcc/testsuite/gcc.target/mips/mips-ps-5.c4
-rw-r--r--gcc/testsuite/gcc.target/mips/mips-ps-7.c4
-rw-r--r--gcc/testsuite/gcc.target/mips/nor.c11
-rw-r--r--gcc/testsuite/gcc.target/powerpc/altivec-perm-1.c15
-rw-r--r--gcc/testsuite/gcc.target/powerpc/altivec-perm-3.c23
-rw-r--r--gcc/testsuite/gcc.target/powerpc/crypto-builtin-1.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/direct-move.h7
-rw-r--r--gcc/testsuite/gcc.target/powerpc/fusion.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/p8vector-builtin-1.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/p8vector-builtin-2.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/p8vector-builtin-3.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/p8vector-builtin-4.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/p8vector-builtin-5.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/p8vector-fp.c139
-rw-r--r--gcc/testsuite/gcc.target/powerpc/p8vector-ldst.c42
-rw-r--r--gcc/testsuite/gcc.target/powerpc/p8vector-vectorize-1.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/p8vector-vectorize-2.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/p8vector-vectorize-3.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/p8vector-vectorize-4.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/p8vector-vectorize-5.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/ppc-target-1.c3
-rw-r--r--gcc/testsuite/gcc.target/powerpc/ppc-target-2.c3
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr42747.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr43154.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr58673-1.c78
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr58673-2.c217
-rw-r--r--gcc/testsuite/gcc.target/powerpc/recip-3.c12
-rw-r--r--gcc/testsuite/gcc.target/powerpc/recip-5.c12
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vsx-builtin-3.c6
-rw-r--r--gcc/testsuite/gcc.target/s390/htm-1.c48
-rw-r--r--gcc/testsuite/gcc.target/s390/htm-nofloat-2.c55
-rw-r--r--gcc/testsuite/gcc.target/sh/20080410-1.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/attr-isr-trap_exit.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/cmpstr.c27
-rw-r--r--gcc/testsuite/gcc.target/sh/cmpstrn.c21
-rw-r--r--gcc/testsuite/gcc.target/sh/fpul-usage-1.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/mfmovd.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr21255-1.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr21255-2-mb.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr21255-2-ml.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr21255-3.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr33135-1.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr33135-2.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr33135-3.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr33135-4.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr39423-1.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr39423-2.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr49263.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr49468-di.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr49468-si.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr49880-1.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr49880-2.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr49880-3.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr49880-4.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr49880-5.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr50749-qihisi-postinc-1.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr50749-qihisi-postinc-2.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr50749-qihisi-postinc-3.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr50749-qihisi-postinc-4.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr50749-qihisi-predec-1.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr50749-qihisi-predec-2.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr50749-qihisi-predec-3.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr50749-qihisi-predec-4.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr50749-sf-postinc-1.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr50749-sf-postinc-2.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr50749-sf-postinc-3.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr50749-sf-postinc-4.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr50749-sf-predec-1.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr50749-sf-predec-2.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr50749-sf-predec-3.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr50749-sf-predec-4.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr50751-1.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr50751-2.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr50751-3.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr50751-4.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr50751-5.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr50751-6.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr50751-7.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr50751-8.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr51244-1.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr51244-10.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr51244-11.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr51244-12.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr51244-13.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr51244-14.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr51244-15.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr51244-16.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr51244-17.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr51244-18.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr51244-19.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr51244-2.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr51244-20-sh2a.c14
-rw-r--r--gcc/testsuite/gcc.target/sh/pr51244-20.c103
-rw-r--r--gcc/testsuite/gcc.target/sh/pr51244-3.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr51244-4.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr51244-5.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr51244-6.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr51244-7.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr51244-8.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr51244-9.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr52483-1.c34
-rw-r--r--gcc/testsuite/gcc.target/sh/pr52483-2.c67
-rw-r--r--gcc/testsuite/gcc.target/sh/pr52483-3.c28
-rw-r--r--gcc/testsuite/gcc.target/sh/pr52483-4.c14
-rw-r--r--gcc/testsuite/gcc.target/sh/pr52483-5.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr52933-1.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr52933-2.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr53511-1.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr53512-1.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr53512-2.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr53512-3.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr53512-4.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr53568-1.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr53988.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr54089-1.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr54089-2.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr54089-3.c4
-rw-r--r--gcc/testsuite/gcc.target/sh/pr54089-4.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr54089-5.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr54089-6.c10
-rw-r--r--gcc/testsuite/gcc.target/sh/pr54089-7.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr54089-8.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr54089-9.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr54236-1.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr54236-2.c270
-rw-r--r--gcc/testsuite/gcc.target/sh/pr54386.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr54602-1.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr54602-2.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr54602-3.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr54602-4.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr54680.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr54685.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr54760-1.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr54760-2.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr54760-3.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr54760-4.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr55146.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr55160.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr55303-1.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr55303-2.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr55303-3.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr56547-1.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr56547-2.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr6526.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pragma-isr-trap-exit.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/prefetch.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/rte-delay-slot.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/sh2a-band.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/sh2a-bclr.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/sh2a-bclrmem.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/sh2a-bld.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/sh2a-bor.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/sh2a-bset.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/sh2a-bsetmem.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/sh2a-bxor.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/sh2a-jsrn.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/sh2a-movi20s.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/sh2a-movrt.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/sh2a-resbank.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/sh2a-rtsn.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/sh2a-tbr-jump.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/sh4a-bitmovua.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/sh4a-cosf.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/sh4a-fsrra.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/sh4a-sincosf.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/sh4a-sinf.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/sp-switch.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/strlen.c19
-rw-r--r--gcc/testsuite/gcc.target/sh/struct-arg-dw2.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/torture/pr30807.c218
-rw-r--r--gcc/testsuite/gcc.target/sh/torture/pr34777.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/torture/pr58314.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/torture/pr58475.c15
-rw-r--r--gcc/testsuite/gcc.target/sh/torture/pragma-isr.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/torture/pragma-isr2.c2
-rw-r--r--gcc/testsuite/gcc.target/vax/pr56875.c13
-rw-r--r--gcc/testsuite/gcc.target/vax/vax.exp41
-rw-r--r--gcc/testsuite/gfortran.dg/assumed_type_8.f9019
-rw-r--r--gcc/testsuite/gfortran.dg/blockdata_8.f9048
-rw-r--r--gcc/testsuite/gfortran.dg/char_length_19.f9044
-rw-r--r--gcc/testsuite/gfortran.dg/constructor_9.f9022
-rw-r--r--gcc/testsuite/gfortran.dg/defined_assignment_8.f9040
-rw-r--r--gcc/testsuite/gfortran.dg/defined_assignment_9.f9045
-rw-r--r--gcc/testsuite/gfortran.dg/derived_external_function_1.f9027
-rw-r--r--gcc/testsuite/gfortran.dg/extends_15.f9016
-rw-r--r--gcc/testsuite/gfortran.dg/finalize_21.f9012
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/appendix-a/a.35.5.f902
-rw-r--r--gcc/testsuite/gfortran.dg/ldist-pr45199.f2
-rw-r--r--gcc/testsuite/gfortran.dg/openmp-define-1.f907
-rw-r--r--gcc/testsuite/gfortran.dg/openmp-define-2.f907
-rw-r--r--gcc/testsuite/gfortran.dg/openmp-define-3.f9011
-rw-r--r--gcc/testsuite/gfortran.dg/optional_class_1.f9045
-rw-r--r--gcc/testsuite/gfortran.dg/pr58484.f15
-rw-r--r--gcc/testsuite/gfortran.dg/pr58968.f96
-rw-r--r--gcc/testsuite/gfortran.dg/proc_ptr_comp_38.f9012
-rw-r--r--gcc/testsuite/gfortran.dg/reshape_6.f9019
-rw-r--r--gcc/testsuite/gfortran.dg/round_4.f9063
-rw-r--r--gcc/testsuite/gfortran.dg/unlimited_polymorphic_10.f9010
-rw-r--r--gcc/testsuite/gfortran.dg/unlimited_polymorphic_11.f9014
-rw-r--r--gcc/testsuite/gfortran.dg/unlimited_polymorphic_12.f9044
-rw-r--r--gcc/testsuite/gfortran.dg/unlimited_polymorphic_13.f9067
-rw-r--r--gcc/testsuite/gfortran.dg/unlimited_polymorphic_14.f9026
-rw-r--r--gcc/testsuite/gfortran.dg/vect/vect-do-concurrent-1.f9017
-rw-r--r--gcc/testsuite/gfortran.dg/vect/vect.exp4
-rw-r--r--gcc/testsuite/gfortran.dg/wdate-time.F906
-rw-r--r--gcc/testsuite/gnat.dg/opt28.adb31
-rw-r--r--gcc/testsuite/gnat.dg/opt28.ads8
-rw-r--r--gcc/testsuite/gnat.dg/opt28_pkg.ads11
-rw-r--r--gcc/testsuite/gnat.dg/specs/linker_alias.ads2
-rw-r--r--gcc/testsuite/gnat.dg/specs/linker_section.ads2
-rw-r--r--gcc/testsuite/gnat.dg/specs/opt1.ads28
-rw-r--r--gcc/testsuite/gnat.dg/uninit_array.adb22
-rw-r--r--gcc/testsuite/gnat.dg/uninit_array.ads5
-rw-r--r--gcc/testsuite/gnat.dg/uninit_array_pkg.ads11
-rw-r--r--gcc/testsuite/go.test/go-test.exp202
-rw-r--r--gcc/testsuite/go.test/test/alias1.go8
-rw-r--r--gcc/testsuite/go.test/test/args.go5
-rw-r--r--gcc/testsuite/go.test/test/bench/garbage/parser.go94
-rw-r--r--gcc/testsuite/go.test/test/bench/go1/fmt_test.go68
-rw-r--r--gcc/testsuite/go.test/test/bench/go1/http_test.go45
-rw-r--r--gcc/testsuite/go.test/test/bench/go1/json_test.go4
-rw-r--r--gcc/testsuite/go.test/test/bench/go1/jsondata_test.go3607
-rw-r--r--gcc/testsuite/go.test/test/bench/go1/parser_test.go2
-rw-r--r--gcc/testsuite/go.test/test/bench/go1/regexp_test.go59
-rw-r--r--gcc/testsuite/go.test/test/bench/go1/time_test.go25
-rwxr-xr-xgcc/testsuite/go.test/test/bench/shootout/timing.sh32
-rw-r--r--gcc/testsuite/go.test/test/bigalg.go15
-rw-r--r--gcc/testsuite/go.test/test/blank.go24
-rw-r--r--gcc/testsuite/go.test/test/blank1.go5
-rw-r--r--gcc/testsuite/go.test/test/bugs/bug434.go10
-rw-r--r--gcc/testsuite/go.test/test/chan/select2.go2
-rw-r--r--gcc/testsuite/go.test/test/cmp.go18
-rw-r--r--gcc/testsuite/go.test/test/cmplx.go26
-rw-r--r--gcc/testsuite/go.test/test/cmplxdivide.go3
-rw-r--r--gcc/testsuite/go.test/test/const.go41
-rw-r--r--gcc/testsuite/go.test/test/const1.go6
-rw-r--r--gcc/testsuite/go.test/test/const4.go7
-rw-r--r--gcc/testsuite/go.test/test/const5.go8
-rw-r--r--gcc/testsuite/go.test/test/const6.go30
-rw-r--r--gcc/testsuite/go.test/test/copy.go5
-rw-r--r--gcc/testsuite/go.test/test/ddd2.dir/ddd2.go16
-rw-r--r--gcc/testsuite/go.test/test/ddd2.dir/ddd3.go28
-rw-r--r--gcc/testsuite/go.test/test/ddd2.go15
-rw-r--r--gcc/testsuite/go.test/test/ddd3.go33
-rw-r--r--gcc/testsuite/go.test/test/decl.go5
-rw-r--r--gcc/testsuite/go.test/test/declbad.go3
-rw-r--r--gcc/testsuite/go.test/test/defer.go2
-rw-r--r--gcc/testsuite/go.test/test/divide.go8
-rw-r--r--gcc/testsuite/go.test/test/dwarf/dwarf.dir/main.go (renamed from gcc/testsuite/go.test/test/dwarf/main.go)0
-rw-r--r--gcc/testsuite/go.test/test/dwarf/dwarf.dir/z1.go (renamed from gcc/testsuite/go.test/test/dwarf/z1.go)0
-rw-r--r--gcc/testsuite/go.test/test/dwarf/dwarf.dir/z10.go (renamed from gcc/testsuite/go.test/test/dwarf/z10.go)0
-rw-r--r--gcc/testsuite/go.test/test/dwarf/dwarf.dir/z11.go (renamed from gcc/testsuite/go.test/test/dwarf/z11.go)0
-rw-r--r--gcc/testsuite/go.test/test/dwarf/dwarf.dir/z12.go (renamed from gcc/testsuite/go.test/test/dwarf/z12.go)0
-rw-r--r--gcc/testsuite/go.test/test/dwarf/dwarf.dir/z13.go (renamed from gcc/testsuite/go.test/test/dwarf/z13.go)0
-rw-r--r--gcc/testsuite/go.test/test/dwarf/dwarf.dir/z14.go (renamed from gcc/testsuite/go.test/test/dwarf/z14.go)0
-rw-r--r--gcc/testsuite/go.test/test/dwarf/dwarf.dir/z15.go (renamed from gcc/testsuite/go.test/test/dwarf/z15.go)0
-rw-r--r--gcc/testsuite/go.test/test/dwarf/dwarf.dir/z16.go (renamed from gcc/testsuite/go.test/test/dwarf/z16.go)0
-rw-r--r--gcc/testsuite/go.test/test/dwarf/dwarf.dir/z17.go (renamed from gcc/testsuite/go.test/test/dwarf/z17.go)0
-rw-r--r--gcc/testsuite/go.test/test/dwarf/dwarf.dir/z18.go (renamed from gcc/testsuite/go.test/test/dwarf/z18.go)0
-rw-r--r--gcc/testsuite/go.test/test/dwarf/dwarf.dir/z19.go (renamed from gcc/testsuite/go.test/test/dwarf/z19.go)0
-rw-r--r--gcc/testsuite/go.test/test/dwarf/dwarf.dir/z2.go (renamed from gcc/testsuite/go.test/test/dwarf/z2.go)0
-rw-r--r--gcc/testsuite/go.test/test/dwarf/dwarf.dir/z20.go (renamed from gcc/testsuite/go.test/test/dwarf/z20.go)0
-rw-r--r--gcc/testsuite/go.test/test/dwarf/dwarf.dir/z3.go (renamed from gcc/testsuite/go.test/test/dwarf/z3.go)0
-rw-r--r--gcc/testsuite/go.test/test/dwarf/dwarf.dir/z4.go (renamed from gcc/testsuite/go.test/test/dwarf/z4.go)0
-rw-r--r--gcc/testsuite/go.test/test/dwarf/dwarf.dir/z5.go (renamed from gcc/testsuite/go.test/test/dwarf/z5.go)0
-rw-r--r--gcc/testsuite/go.test/test/dwarf/dwarf.dir/z6.go (renamed from gcc/testsuite/go.test/test/dwarf/z6.go)0
-rw-r--r--gcc/testsuite/go.test/test/dwarf/dwarf.dir/z7.go (renamed from gcc/testsuite/go.test/test/dwarf/z7.go)0
-rw-r--r--gcc/testsuite/go.test/test/dwarf/dwarf.dir/z8.go (renamed from gcc/testsuite/go.test/test/dwarf/z8.go)0
-rw-r--r--gcc/testsuite/go.test/test/dwarf/dwarf.dir/z9.go (renamed from gcc/testsuite/go.test/test/dwarf/z9.go)0
-rw-r--r--gcc/testsuite/go.test/test/dwarf/dwarf.go10
-rwxr-xr-xgcc/testsuite/go.test/test/errchk2
-rw-r--r--gcc/testsuite/go.test/test/escape.go2
-rw-r--r--gcc/testsuite/go.test/test/escape2.go212
-rw-r--r--gcc/testsuite/go.test/test/escape5.go144
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug040.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug083.go7
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug085.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug133.go7
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug160.go7
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug191.dir/main.go14
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug191.go16
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug205.go6
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug228.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug255.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug297.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug313.go5
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug322.go7
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug324.dir/prog.go (renamed from gcc/testsuite/go.test/test/fixedbugs/bug324.dir/main.go)0
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug324.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug342.go6
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug357.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug367.dir/prog.go (renamed from gcc/testsuite/go.test/test/fixedbugs/bug367.dir/main.go)0
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug367.go8
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug379.go2
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug382.dir/prog.go13
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug382.go14
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug385_32.go10
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug385_64.go14
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug412.go4
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug414.dir/main.go18
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug414.dir/p1.go34
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug414.dir/prog.go18
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug414.go7
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug424.dir/main.go97
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug424.go93
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug437.dir/x.go25
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug437.go23
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug453.go39
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug454.go21
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug455.go54
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug456.go26
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug457.go15
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug458.go22
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug459.go35
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug460.dir/a.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug460.dir/b.go14
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug460.go10
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug461.go23
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug462.go19
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug463.go22
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug464.go12
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug465.dir/a.go76
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug465.dir/b.go17
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug465.go10
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug466.dir/a.go15
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug466.dir/b.go30
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug466.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug467.dir/p1.go5
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug467.dir/p2.go5
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug467.dir/p3.go7
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug467.go10
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug468.dir/p1.go7
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug468.dir/p2.go25
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug468.go10
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug470.go26
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug471.go18
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug472.dir/p1.go17
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug472.dir/p2.go17
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug472.dir/z.go13
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug472.go10
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug473.go69
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug474.go29
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue2615.go547
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue3552.dir/one.go (renamed from gcc/testsuite/go.test/test/bugs/bug434.dir/one.go)0
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue3552.dir/two.go (renamed from gcc/testsuite/go.test/test/bugs/bug434.dir/two.go)0
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue3552.go10
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue3705.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue3783.go12
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue3924.go13
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue3925.go23
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4066.go37
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4085a.go18
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4085b.go49
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4097.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4099.go26
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4162.go17
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4167.go50
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4232.go33
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4251.go21
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4252.dir/a.go35
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4252.dir/main.go20
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4252.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4264.go19
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4283.go17
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4313.go28
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4316.go64
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4323.go31
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4326.dir/p1.go12
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4326.dir/p2.go5
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4326.dir/q1.go8
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4326.dir/q2.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4326.dir/z.go7
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4326.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4348.go29
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4353.go19
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4359.go19
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4370.dir/p1.go20
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4370.dir/p2.go16
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4370.dir/p3.go13
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4370.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4396a.go27
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4396b.go29
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4399.go15
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4405.go15
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4429.go16
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4448.go37
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4452.go13
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4458.go20
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4463.go87
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4468.go28
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4470.go16
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4495.go29
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4510.dir/f1.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4510.dir/f2.go7
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4510.go7
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4517a.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4517b.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4517c.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4518.go67
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4529.go33
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4545.go19
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4562.go49
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4585.go151
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4590.dir/pkg1.go26
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4590.dir/pkg2.go15
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4590.dir/prog.go25
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4590.go10
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4610.go17
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4614.go20
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4618.go41
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4620.go21
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4654.go71
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4663.go15
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4667.go37
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4734.go21
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4748.go20
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4752.go26
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4785.go20
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4813.go52
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4879.dir/a.go33
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4879.dir/b.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4879.go10
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4909a.go35
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4909b.go80
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4932.dir/foo.go7
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4932.dir/state.go28
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4932.dir/state2.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4932.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4964.dir/a.go27
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4964.dir/b.go34
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue4964.go10
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue5002.go16
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue5056.go34
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue5089.go15
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue5105.dir/a.go7
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue5105.dir/b.go15
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue5105.go10
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue5125.dir/bug.go17
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue5125.dir/main.go10
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue5125.go10
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue5162.go88
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue5231.go45
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue5244.go18
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue5259.dir/bug.go17
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue5259.dir/main.go16
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue5259.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue5260.dir/a.go7
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue5260.dir/b.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue5260.go10
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue5291.dir/pkg1.go34
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue5291.dir/prog.go17
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue5291.go9
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue5470.dir/a.go27
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue5470.dir/b.go13
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue5470.go10
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue5493.go59
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue5515.go34
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue5607.go36
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue5614.dir/rethinkgo.go16
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue5614.dir/x.go7
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue5614.dir/y.go5
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue5614.go11
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue5753.go29
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue5755.dir/a.go60
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue5755.dir/main.go23
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue5755.go10
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue5809.go27
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue5820.go18
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue5841.go16
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/issue887.go36
-rw-r--r--gcc/testsuite/go.test/test/float_lit.go4
-rw-r--r--gcc/testsuite/go.test/test/floatcmp.go3
-rw-r--r--gcc/testsuite/go.test/test/func1.go2
-rw-r--r--gcc/testsuite/go.test/test/func7.go3
-rw-r--r--gcc/testsuite/go.test/test/func8.go4
-rw-r--r--gcc/testsuite/go.test/test/funcdup.go27
-rw-r--r--gcc/testsuite/go.test/test/funcdup2.go17
-rw-r--r--gcc/testsuite/go.test/test/golden.out6
-rw-r--r--gcc/testsuite/go.test/test/goprint.go2
-rw-r--r--gcc/testsuite/go.test/test/import2.dir/import2.go42
-rw-r--r--gcc/testsuite/go.test/test/import2.dir/import3.go52
-rw-r--r--gcc/testsuite/go.test/test/import2.go43
-rw-r--r--gcc/testsuite/go.test/test/import3.go57
-rw-r--r--gcc/testsuite/go.test/test/import4.dir/empty.go10
-rw-r--r--gcc/testsuite/go.test/test/import4.dir/import4.go24
-rw-r--r--gcc/testsuite/go.test/test/import4.go22
-rw-r--r--gcc/testsuite/go.test/test/index.go69
-rw-r--r--gcc/testsuite/go.test/test/init1.go1
-rw-r--r--gcc/testsuite/go.test/test/initializerr.go12
-rw-r--r--gcc/testsuite/go.test/test/interface/embed0.go29
-rw-r--r--gcc/testsuite/go.test/test/interface/embed1.dir/embed0.go27
-rw-r--r--gcc/testsuite/go.test/test/interface/embed1.dir/embed1.go43
-rw-r--r--gcc/testsuite/go.test/test/interface/embed1.go43
-rw-r--r--gcc/testsuite/go.test/test/interface/private.dir/private1.go18
-rw-r--r--gcc/testsuite/go.test/test/interface/private.dir/prog.go33
-rw-r--r--gcc/testsuite/go.test/test/interface/private.go32
-rw-r--r--gcc/testsuite/go.test/test/interface/private1.go20
-rw-r--r--gcc/testsuite/go.test/test/interface/recursive1.dir/recursive1.go15
-rw-r--r--gcc/testsuite/go.test/test/interface/recursive1.dir/recursive2.go20
-rw-r--r--gcc/testsuite/go.test/test/interface/recursive1.go12
-rw-r--r--gcc/testsuite/go.test/test/interface/recursive2.go25
-rw-r--r--gcc/testsuite/go.test/test/literal.go3
-rw-r--r--gcc/testsuite/go.test/test/map.go281
-rw-r--r--gcc/testsuite/go.test/test/mapnan.go64
-rw-r--r--gcc/testsuite/go.test/test/method.go71
-rw-r--r--gcc/testsuite/go.test/test/method4.dir/method4a.go37
-rw-r--r--gcc/testsuite/go.test/test/method4.dir/prog.go104
-rw-r--r--gcc/testsuite/go.test/test/method4.go105
-rw-r--r--gcc/testsuite/go.test/test/method4a.go40
-rw-r--r--gcc/testsuite/go.test/test/method5.go297
-rw-r--r--gcc/testsuite/go.test/test/nil.go7
-rw-r--r--gcc/testsuite/go.test/test/nilptr.go22
-rw-r--r--gcc/testsuite/go.test/test/nul1.go8
-rw-r--r--gcc/testsuite/go.test/test/range.go22
-rw-r--r--gcc/testsuite/go.test/test/recover.go12
-rw-r--r--gcc/testsuite/go.test/test/recover3.go4
-rw-r--r--gcc/testsuite/go.test/test/rename.go6
-rw-r--r--gcc/testsuite/go.test/test/reorder.go28
-rw-r--r--gcc/testsuite/go.test/test/return.go2821
-rw-r--r--gcc/testsuite/go.test/test/rotate.go15
-rw-r--r--gcc/testsuite/go.test/test/rotate0.go12
-rw-r--r--gcc/testsuite/go.test/test/rotate1.go12
-rw-r--r--gcc/testsuite/go.test/test/rotate2.go12
-rw-r--r--gcc/testsuite/go.test/test/rotate3.go12
-rw-r--r--gcc/testsuite/go.test/test/run.go443
-rw-r--r--gcc/testsuite/go.test/test/safe/nousesafe.go2
-rw-r--r--gcc/testsuite/go.test/test/safe/usesafe.go2
-rw-r--r--gcc/testsuite/go.test/test/sigchld.go7
-rw-r--r--gcc/testsuite/go.test/test/sinit.go10
-rw-r--r--gcc/testsuite/go.test/test/sizeof.go137
-rw-r--r--gcc/testsuite/go.test/test/stress/maps.go111
-rw-r--r--gcc/testsuite/go.test/test/stress/parsego.go220
-rw-r--r--gcc/testsuite/go.test/test/stress/runstress.go164
-rw-r--r--gcc/testsuite/go.test/test/string_lit.go3
-rw-r--r--gcc/testsuite/go.test/test/switch.go79
-rw-r--r--gcc/testsuite/go.test/test/switch4.go36
-rw-r--r--gcc/testsuite/go.test/test/testlib94
-rw-r--r--gcc/testsuite/go.test/test/torture.go339
-rw-r--r--gcc/testsuite/go.test/test/typecheck.go18
-rw-r--r--gcc/testsuite/go.test/test/zerodivide.go3
-rw-r--r--gcc/testsuite/lib/atomic-dg.exp104
-rw-r--r--gcc/testsuite/lib/gcc-defs.exp2
-rw-r--r--gcc/testsuite/lib/target-supports.exp78
-rw-r--r--gcc/timevar.def3
-rw-r--r--gcc/toplev.c47
-rw-r--r--gcc/tracer.c6
-rw-r--r--gcc/trans-mem.c157
-rw-r--r--gcc/tree-affine.c9
-rw-r--r--gcc/tree-affine.h2
-rw-r--r--gcc/tree-browser.c2
-rw-r--r--gcc/tree-call-cdce.c23
-rw-r--r--gcc/tree-cfg.c513
-rw-r--r--gcc/tree-cfg.h97
-rw-r--r--gcc/tree-cfgcleanup.c101
-rw-r--r--gcc/tree-cfgcleanup.h28
-rw-r--r--gcc/tree-chrec.c5
-rw-r--r--gcc/tree-chrec.h21
-rw-r--r--gcc/tree-complex.c18
-rw-r--r--gcc/tree-core.h136
-rw-r--r--gcc/tree-data-ref.c30
-rw-r--r--gcc/tree-data-ref.h5
-rw-r--r--gcc/tree-dfa.c107
-rw-r--r--gcc/tree-dfa.h184
-rw-r--r--gcc/tree-dump.c3
-rw-r--r--gcc/tree-dump.h3
-rw-r--r--gcc/tree-eh.c113
-rw-r--r--gcc/tree-eh.h52
-rw-r--r--gcc/tree-emutls.c51
-rw-r--r--gcc/tree-flow-inline.h1306
-rw-r--r--gcc/tree-flow.h696
-rw-r--r--gcc/tree-hasher.h6
-rw-r--r--gcc/tree-if-conv.c15
-rw-r--r--gcc/tree-inline.c93
-rw-r--r--gcc/tree-inline.h4
-rw-r--r--gcc/tree-into-ssa.c141
-rw-r--r--gcc/tree-into-ssa.h52
-rw-r--r--gcc/tree-iterator.c2
-rw-r--r--gcc/tree-loop-distribution.c756
-rw-r--r--gcc/tree-mudflap.c1450
-rw-r--r--gcc/tree-mudflap.h34
-rw-r--r--gcc/tree-nested.c53
-rw-r--r--gcc/tree-nomudflap.c169
-rw-r--r--gcc/tree-nrv.c12
-rw-r--r--gcc/tree-object-size.c16
-rw-r--r--gcc/tree-optimize.c269
-rw-r--r--gcc/tree-outof-ssa.c89
-rw-r--r--gcc/tree-outof-ssa.h78
-rw-r--r--gcc/tree-parloops.c94
-rw-r--r--gcc/tree-parloops.h26
-rw-r--r--gcc/tree-pass.h62
-rw-r--r--gcc/tree-phinodes.c43
-rw-r--r--gcc/tree-phinodes.h83
-rw-r--r--gcc/tree-predcom.c193
-rw-r--r--gcc/tree-pretty-print.c399
-rw-r--r--gcc/tree-pretty-print.h24
-rw-r--r--gcc/tree-profile.c72
-rw-r--r--gcc/tree-scalar-evolution.c99
-rw-r--r--gcc/tree-scalar-evolution.h3
-rw-r--r--gcc/tree-sra.c61
-rw-r--r--gcc/tree-ssa-address.c24
-rw-r--r--gcc/tree-ssa-address.h32
-rw-r--r--gcc/tree-ssa-alias.c123
-rw-r--r--gcc/tree-ssa-alias.h23
-rw-r--r--gcc/tree-ssa-ccp.c126
-rw-r--r--gcc/tree-ssa-coalesce.c49
-rw-r--r--gcc/tree-ssa-coalesce.h25
-rw-r--r--gcc/tree-ssa-copy.c246
-rw-r--r--gcc/tree-ssa-copyrename.c11
-rw-r--r--gcc/tree-ssa-dce.c69
-rw-r--r--gcc/tree-ssa-dom.c103
-rw-r--r--gcc/tree-ssa-dom.h28
-rw-r--r--gcc/tree-ssa-dse.c16
-rw-r--r--gcc/tree-ssa-forwprop.c130
-rw-r--r--gcc/tree-ssa-ifcombine.c62
-rw-r--r--gcc/tree-ssa-live.c18
-rw-r--r--gcc/tree-ssa-live.h29
-rw-r--r--gcc/tree-ssa-loop-ch.c13
-rw-r--r--gcc/tree-ssa-loop-im.c384
-rw-r--r--gcc/tree-ssa-loop-ivcanon.c218
-rw-r--r--gcc/tree-ssa-loop-ivopts.c169
-rw-r--r--gcc/tree-ssa-loop-ivopts.h36
-rw-r--r--gcc/tree-ssa-loop-manip.c12
-rw-r--r--gcc/tree-ssa-loop-manip.h49
-rw-r--r--gcc/tree-ssa-loop-niter.c210
-rw-r--r--gcc/tree-ssa-loop-niter.h48
-rw-r--r--gcc/tree-ssa-loop-prefetch.c69
-rw-r--r--gcc/tree-ssa-loop-unswitch.c66
-rw-r--r--gcc/tree-ssa-loop.c827
-rw-r--r--gcc/tree-ssa-loop.h81
-rw-r--r--gcc/tree-ssa-math-opts.c40
-rw-r--r--gcc/tree-ssa-operands.c103
-rw-r--r--gcc/tree-ssa-operands.h140
-rw-r--r--gcc/tree-ssa-phiopt.c241
-rw-r--r--gcc/tree-ssa-phiprop.c10
-rw-r--r--gcc/tree-ssa-pre.c156
-rw-r--r--gcc/tree-ssa-propagate.c224
-rw-r--r--gcc/tree-ssa-propagate.h23
-rw-r--r--gcc/tree-ssa-reassoc.c1044
-rw-r--r--gcc/tree-ssa-sccvn.c9
-rw-r--r--gcc/tree-ssa-sink.c10
-rw-r--r--gcc/tree-ssa-strlen.c13
-rw-r--r--gcc/tree-ssa-structalias.c71
-rw-r--r--gcc/tree-ssa-tail-merge.c31
-rw-r--r--gcc/tree-ssa-ter.c175
-rw-r--r--gcc/tree-ssa-ter.h26
-rw-r--r--gcc/tree-ssa-threadedge.c198
-rw-r--r--gcc/tree-ssa-threadedge.h36
-rw-r--r--gcc/tree-ssa-threadupdate.c527
-rw-r--r--gcc/tree-ssa-threadupdate.h46
-rw-r--r--gcc/tree-ssa-uncprop.c38
-rw-r--r--gcc/tree-ssa-uninit.c15
-rw-r--r--gcc/tree-ssa.c161
-rw-r--r--gcc/tree-ssa.h9
-rw-r--r--gcc/tree-ssanames.c168
-rw-r--r--gcc/tree-ssanames.h23
-rw-r--r--gcc/tree-stdarg.c12
-rw-r--r--gcc/tree-streamer-in.c2
-rw-r--r--gcc/tree-streamer-out.c1
-rw-r--r--gcc/tree-streamer.c2
-rw-r--r--gcc/tree-streamer.h1
-rw-r--r--gcc/tree-switch-conversion.c15
-rw-r--r--gcc/tree-tailcall.c22
-rw-r--r--gcc/tree-vect-data-refs.c425
-rw-r--r--gcc/tree-vect-generic.c14
-rw-r--r--gcc/tree-vect-loop-manip.c218
-rw-r--r--gcc/tree-vect-loop.c74
-rw-r--r--gcc/tree-vect-patterns.c70
-rw-r--r--gcc/tree-vect-slp.c24
-rw-r--r--gcc/tree-vect-stmts.c51
-rw-r--r--gcc/tree-vectorizer.c22
-rw-r--r--gcc/tree-vectorizer.h50
-rw-r--r--gcc/tree-vrp.c341
-rw-r--r--gcc/tree.c1222
-rw-r--r--gcc/tree.def62
-rw-r--r--gcc/tree.h425
-rw-r--r--gcc/tsan.c16
-rw-r--r--gcc/tsystem.h2
-rw-r--r--gcc/ubsan.c18
-rw-r--r--gcc/value-prof.c59
-rw-r--r--gcc/value-prof.h4
-rw-r--r--gcc/var-tracking.c34
-rw-r--r--gcc/varasm.c74
-rw-r--r--gcc/varpool.c145
-rw-r--r--gcc/vec.c51
-rw-r--r--gcc/vec.h540
-rw-r--r--gcc/vmsdbgout.c8
-rw-r--r--gcc/vtable-verify.c22
-rw-r--r--gcc/web.c6
-rw-r--r--include/ChangeLog20
-rw-r--r--include/ansidecl.h9
-rw-r--r--include/gdb/gdb-index.h99
-rw-r--r--include/libiberty.h34
-rw-r--r--libatomic/ChangeLog23
-rw-r--r--libatomic/Makefile.am3
-rw-r--r--libatomic/Makefile.in9
-rw-r--r--libatomic/auto-config.h.in3
-rw-r--r--libatomic/config/x86/fenv.c116
-rwxr-xr-xlibatomic/configure133
-rw-r--r--libatomic/configure.ac3
-rw-r--r--libatomic/configure.tgt5
-rw-r--r--libatomic/fenv.c72
-rw-r--r--libatomic/libatomic.map4
-rw-r--r--libbacktrace/ChangeLog15
-rwxr-xr-xlibbacktrace/configure24
-rw-r--r--libbacktrace/configure.ac5
-rw-r--r--libbacktrace/elf.c11
-rw-r--r--libcilkrts/ChangeLog155
-rw-r--r--libcilkrts/Makefile.am176
-rw-r--r--libcilkrts/Makefile.in1055
-rw-r--r--libcilkrts/README84
-rw-r--r--libcilkrts/aclocal.m4981
-rw-r--r--libcilkrts/configure16907
-rw-r--r--libcilkrts/configure.ac154
-rw-r--r--libcilkrts/configure.tgt61
-rw-r--r--libcilkrts/include/cilk/cilk.h71
-rw-r--r--libcilkrts/include/cilk/cilk_api.h424
-rw-r--r--libcilkrts/include/cilk/cilk_api_linux.h38
-rw-r--r--libcilkrts/include/cilk/cilk_stub.h55
-rw-r--r--libcilkrts/include/cilk/cilk_undocumented.h131
-rw-r--r--libcilkrts/include/cilk/common.h376
-rw-r--r--libcilkrts/include/cilk/holder.h1000
-rw-r--r--libcilkrts/include/cilk/hyperobject_base.h172
-rw-r--r--libcilkrts/include/cilk/metaprogramming.h606
-rw-r--r--libcilkrts/include/cilk/reducer.h1900
-rw-r--r--libcilkrts/include/cilk/reducer_file.h37
-rw-r--r--libcilkrts/include/cilk/reducer_list.h1127
-rw-r--r--libcilkrts/include/cilk/reducer_max.h46
-rw-r--r--libcilkrts/include/cilk/reducer_min.h46
-rw-r--r--libcilkrts/include/cilk/reducer_min_max.h3606
-rw-r--r--libcilkrts/include/cilk/reducer_opadd.h690
-rw-r--r--libcilkrts/include/cilk/reducer_opand.h604
-rw-r--r--libcilkrts/include/cilk/reducer_opmul.h442
-rw-r--r--libcilkrts/include/cilk/reducer_opor.h598
-rw-r--r--libcilkrts/include/cilk/reducer_opxor.h598
-rw-r--r--libcilkrts/include/cilk/reducer_ostream.h293
-rw-r--r--libcilkrts/include/cilk/reducer_string.h729
-rw-r--r--libcilkrts/include/cilktools/cilkscreen.h108
-rw-r--r--libcilkrts/include/cilktools/cilkview.h278
-rw-r--r--libcilkrts/include/cilktools/fake_mutex.h92
-rw-r--r--libcilkrts/include/cilktools/lock_guard.h86
-rw-r--r--libcilkrts/include/internal/abi.h639
-rw-r--r--libcilkrts/include/internal/cilk_fake.h477
-rw-r--r--libcilkrts/include/internal/cilk_version.h47
-rw-r--r--libcilkrts/include/internal/metacall.h99
-rw-r--r--libcilkrts/include/internal/rev.mk41
-rw-r--r--libcilkrts/mk/cilk-version.mk61
-rw-r--r--libcilkrts/runtime/acknowledgements.dox51
-rw-r--r--libcilkrts/runtime/bug.cpp139
-rw-r--r--libcilkrts/runtime/bug.h141
-rw-r--r--libcilkrts/runtime/c_reducers.c57
-rw-r--r--libcilkrts/runtime/cilk-abi-cilk-for.cpp406
-rw-r--r--libcilkrts/runtime/cilk-abi-vla-internal.c83
-rw-r--r--libcilkrts/runtime/cilk-abi-vla-internal.h90
-rw-r--r--libcilkrts/runtime/cilk-abi.c733
-rw-r--r--libcilkrts/runtime/cilk-ittnotify.h100
-rw-r--r--libcilkrts/runtime/cilk-tbb-interop.h192
-rw-r--r--libcilkrts/runtime/cilk_api.c255
-rw-r--r--libcilkrts/runtime/cilk_fiber-unix.cpp301
-rw-r--r--libcilkrts/runtime/cilk_fiber-unix.h149
-rw-r--r--libcilkrts/runtime/cilk_fiber.cpp1078
-rw-r--r--libcilkrts/runtime/cilk_fiber.h882
-rw-r--r--libcilkrts/runtime/cilk_malloc.c84
-rw-r--r--libcilkrts/runtime/cilk_malloc.h90
-rw-r--r--libcilkrts/runtime/component.h52
-rw-r--r--libcilkrts/runtime/config/generic/cilk-abi-vla.c107
-rw-r--r--libcilkrts/runtime/config/generic/os-fence.h53
-rw-r--r--libcilkrts/runtime/config/generic/os-unix-sysdep.c94
-rw-r--r--libcilkrts/runtime/config/x86/cilk-abi-vla.c441
-rw-r--r--libcilkrts/runtime/config/x86/os-fence.h72
-rw-r--r--libcilkrts/runtime/config/x86/os-unix-sysdep.c123
-rw-r--r--libcilkrts/runtime/doxygen-layout.xml222
-rw-r--r--libcilkrts/runtime/doxygen.cfg1774
-rw-r--r--libcilkrts/runtime/except-gcc.cpp597
-rw-r--r--libcilkrts/runtime/except-gcc.h146
-rw-r--r--libcilkrts/runtime/except.h123
-rw-r--r--libcilkrts/runtime/frame_malloc.c462
-rw-r--r--libcilkrts/runtime/frame_malloc.h205
-rw-r--r--libcilkrts/runtime/full_frame.c181
-rw-r--r--libcilkrts/runtime/full_frame.h493
-rw-r--r--libcilkrts/runtime/global_state.cpp628
-rw-r--r--libcilkrts/runtime/global_state.h417
-rw-r--r--libcilkrts/runtime/jmpbuf.c48
-rw-r--r--libcilkrts/runtime/jmpbuf.h136
-rw-r--r--libcilkrts/runtime/linux-symbols.ver369
-rw-r--r--libcilkrts/runtime/local_state.c68
-rw-r--r--libcilkrts/runtime/local_state.h424
-rw-r--r--libcilkrts/runtime/mac-symbols.txt318
-rw-r--r--libcilkrts/runtime/metacall_impl.c167
-rw-r--r--libcilkrts/runtime/metacall_impl.h123
-rw-r--r--libcilkrts/runtime/os-unix.c511
-rw-r--r--libcilkrts/runtime/os.h236
-rw-r--r--libcilkrts/runtime/os_mutex-unix.c193
-rw-r--r--libcilkrts/runtime/os_mutex.h135
-rw-r--r--libcilkrts/runtime/pedigrees.c112
-rw-r--r--libcilkrts/runtime/pedigrees.h130
-rw-r--r--libcilkrts/runtime/record-replay.cpp770
-rw-r--r--libcilkrts/runtime/record-replay.h432
-rw-r--r--libcilkrts/runtime/reducer_impl.cpp1012
-rw-r--r--libcilkrts/runtime/reducer_impl.h128
-rw-r--r--libcilkrts/runtime/rts-common.h132
-rw-r--r--libcilkrts/runtime/scheduler.c3940
-rw-r--r--libcilkrts/runtime/scheduler.h421
-rw-r--r--libcilkrts/runtime/signal_node.c241
-rw-r--r--libcilkrts/runtime/signal_node.h109
-rw-r--r--libcilkrts/runtime/spin_mutex.c109
-rw-r--r--libcilkrts/runtime/spin_mutex.h129
-rw-r--r--libcilkrts/runtime/stats.c172
-rw-r--r--libcilkrts/runtime/stats.h208
-rw-r--r--libcilkrts/runtime/symbol_test.c62
-rw-r--r--libcilkrts/runtime/sysdep-unix.c807
-rw-r--r--libcilkrts/runtime/sysdep.h285
-rw-r--r--libcilkrts/runtime/worker_mutex.c121
-rw-r--r--libcilkrts/runtime/worker_mutex.h131
-rw-r--r--libcpp/ChangeLog35
-rw-r--r--libcpp/Makefile.in5
-rw-r--r--libcpp/aclocal.m42
-rwxr-xr-xlibcpp/configure13
-rw-r--r--libcpp/configure.ac7
-rw-r--r--libcpp/expr.c67
-rw-r--r--libcpp/include/cpplib.h9
-rw-r--r--libcpp/init.c33
-rw-r--r--libcpp/internal.h2
-rw-r--r--libcpp/lex.c3
-rw-r--r--libcpp/macro.c7
-rw-r--r--libcpp/po/ChangeLog8
-rw-r--r--libcpp/po/sr.po88
-rw-r--r--libcpp/po/tr.po139
-rw-r--r--libdecnumber/ChangeLog8
-rw-r--r--libdecnumber/Makefile.in3
-rw-r--r--libdecnumber/aclocal.m42
-rwxr-xr-xlibdecnumber/configure13
-rw-r--r--libdecnumber/configure.ac7
-rw-r--r--libffi/ChangeLog4
-rwxr-xr-xlibffi/configure16
-rw-r--r--libgcc/ChangeLog253
-rw-r--r--libgcc/Makefile.in2
-rw-r--r--libgcc/config.host52
-rw-r--r--libgcc/config/arc/asm.h30
-rw-r--r--libgcc/config/arc/crtg.S52
-rw-r--r--libgcc/config/arc/crtgend.S34
-rw-r--r--libgcc/config/arc/crti.S42
-rw-r--r--libgcc/config/arc/crtn.S39
-rw-r--r--libgcc/config/arc/divtab-arc700.c70
-rw-r--r--libgcc/config/arc/dp-hack.h101
-rw-r--r--libgcc/config/arc/fp-hack.h85
-rw-r--r--libgcc/config/arc/gmon/atomic.h26
-rw-r--r--libgcc/config/arc/gmon/auxreg.h35
-rw-r--r--libgcc/config/arc/gmon/dcache_linesz.S55
-rw-r--r--libgcc/config/arc/gmon/gmon.c450
-rw-r--r--libgcc/config/arc/gmon/machine-gmon.h65
-rw-r--r--libgcc/config/arc/gmon/mcount.c206
-rw-r--r--libgcc/config/arc/gmon/prof-freq-stub.S40
-rw-r--r--libgcc/config/arc/gmon/prof-freq.c60
-rw-r--r--libgcc/config/arc/gmon/profil.S153
-rw-r--r--libgcc/config/arc/gmon/sys/gmon.h217
-rw-r--r--libgcc/config/arc/gmon/sys/gmon_out.h55
-rw-r--r--libgcc/config/arc/ieee-754/adddf3.S524
-rw-r--r--libgcc/config/arc/ieee-754/addsf3.S344
-rw-r--r--libgcc/config/arc/ieee-754/arc-ieee-754.h56
-rw-r--r--libgcc/config/arc/ieee-754/arc600-dsp/divdf3.S421
-rw-r--r--libgcc/config/arc/ieee-754/arc600-dsp/divsf3.S274
-rw-r--r--libgcc/config/arc/ieee-754/arc600-dsp/muldf3.S231
-rw-r--r--libgcc/config/arc/ieee-754/arc600-dsp/mulsf3.S176
-rw-r--r--libgcc/config/arc/ieee-754/arc600-mul64/divdf3.S410
-rw-r--r--libgcc/config/arc/ieee-754/arc600-mul64/divsf3.S274
-rw-r--r--libgcc/config/arc/ieee-754/arc600-mul64/muldf3.S234
-rw-r--r--libgcc/config/arc/ieee-754/arc600-mul64/mulsf3.S180
-rw-r--r--libgcc/config/arc/ieee-754/arc600/divsf3.S227
-rw-r--r--libgcc/config/arc/ieee-754/arc600/mulsf3.S179
-rw-r--r--libgcc/config/arc/ieee-754/divdf3.S416
-rw-r--r--libgcc/config/arc/ieee-754/divsf3-stdmul.S281
-rw-r--r--libgcc/config/arc/ieee-754/divsf3.S221
-rw-r--r--libgcc/config/arc/ieee-754/divtab-arc-df.c161
-rw-r--r--libgcc/config/arc/ieee-754/divtab-arc-sf.c127
-rw-r--r--libgcc/config/arc/ieee-754/eqdf2.S76
-rw-r--r--libgcc/config/arc/ieee-754/eqsf2.S69
-rw-r--r--libgcc/config/arc/ieee-754/extendsfdf2.S122
-rw-r--r--libgcc/config/arc/ieee-754/fixdfsi.S85
-rw-r--r--libgcc/config/arc/ieee-754/fixsfsi.S71
-rw-r--r--libgcc/config/arc/ieee-754/fixunsdfsi.S80
-rw-r--r--libgcc/config/arc/ieee-754/floatsidf.S77
-rw-r--r--libgcc/config/arc/ieee-754/floatsisf.S99
-rw-r--r--libgcc/config/arc/ieee-754/floatunsidf.S75
-rw-r--r--libgcc/config/arc/ieee-754/gedf2.S86
-rw-r--r--libgcc/config/arc/ieee-754/gesf2.S75
-rw-r--r--libgcc/config/arc/ieee-754/gtdf2.S86
-rw-r--r--libgcc/config/arc/ieee-754/gtsf2.S75
-rw-r--r--libgcc/config/arc/ieee-754/muldf3.S235
-rw-r--r--libgcc/config/arc/ieee-754/mulsf3.S180
-rw-r--r--libgcc/config/arc/ieee-754/orddf2.S63
-rw-r--r--libgcc/config/arc/ieee-754/ordsf2.S63
-rw-r--r--libgcc/config/arc/ieee-754/truncdfsf2.S134
-rw-r--r--libgcc/config/arc/ieee-754/uneqdf2.S73
-rw-r--r--libgcc/config/arc/ieee-754/uneqsf2.S69
-rw-r--r--libgcc/config/arc/initfini.c157
-rw-r--r--libgcc/config/arc/lib1funcs.S1418
-rw-r--r--libgcc/config/arc/libgcc-excl.ver43
-rw-r--r--libgcc/config/arc/t-arc100
-rw-r--r--libgcc/config/arc/t-arc-newlib22
-rw-r--r--libgcc/config/arc/t-arc700-uClibc40
-rw-r--r--libgcc/config/arm/t-vxworks1
-rw-r--r--libgcc/config/cris/arit.c20
-rw-r--r--libgcc/config/cris/mulsi3.S78
-rw-r--r--libgcc/config/cris/sfp-machine.h78
-rw-r--r--libgcc/config/cris/t-elfmulti2
-rw-r--r--libgcc/config/cris/umulsidi3.S289
-rw-r--r--libgcc/config/i386/32/sfp-machine.h6
-rw-r--r--libgcc/config/i386/crtfastmath.c2
-rw-r--r--libgcc/config/i386/crtprec.c2
-rw-r--r--libgcc/config/i386/cygming-crtbegin.c14
-rw-r--r--libgcc/config/i386/sfp-exceptions.c30
-rw-r--r--libgcc/config/nds32/crtzero.S103
-rw-r--r--libgcc/config/nds32/initfini.c159
-rw-r--r--libgcc/config/nds32/isr-library/adj_intr_lvl.inc38
-rw-r--r--libgcc/config/nds32/isr-library/excp_isr.S132
-rw-r--r--libgcc/config/nds32/isr-library/excp_isr_4b.S133
-rw-r--r--libgcc/config/nds32/isr-library/intr_isr.S132
-rw-r--r--libgcc/config/nds32/isr-library/intr_isr_4b.S134
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid00.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid01.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid02.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid03.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid04.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid05.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid06.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid07.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid08.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid09.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid10.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid11.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid12.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid13.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid14.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid15.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid16.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid17.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid18.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid19.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid20.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid21.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid22.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid23.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid24.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid25.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid26.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid27.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid28.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid29.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid30.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid31.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid32.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid33.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid34.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid35.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid36.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid37.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid38.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid39.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid40.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid41.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid42.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid43.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid44.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid45.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid46.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid47.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid48.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid49.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid50.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid51.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid52.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid53.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid54.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid55.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid56.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid57.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid58.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid59.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid60.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid61.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid62.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid63.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid64.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid65.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid66.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid67.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid68.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid69.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid70.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid71.S32
-rw-r--r--libgcc/config/nds32/isr-library/jmptbl_vid72.S32
-rw-r--r--libgcc/config/nds32/isr-library/nmih.S32
-rw-r--r--libgcc/config/nds32/isr-library/reset.S130
-rw-r--r--libgcc/config/nds32/isr-library/reset_4b.S131
-rw-r--r--libgcc/config/nds32/isr-library/restore_all.inc45
-rw-r--r--libgcc/config/nds32/isr-library/restore_fpu_regs.inc36
-rw-r--r--libgcc/config/nds32/isr-library/restore_fpu_regs_00.inc31
-rw-r--r--libgcc/config/nds32/isr-library/restore_fpu_regs_01.inc35
-rw-r--r--libgcc/config/nds32/isr-library/restore_fpu_regs_02.inc43
-rw-r--r--libgcc/config/nds32/isr-library/restore_fpu_regs_03.inc59
-rw-r--r--libgcc/config/nds32/isr-library/restore_mac_regs.inc34
-rw-r--r--libgcc/config/nds32/isr-library/restore_partial.inc47
-rw-r--r--libgcc/config/nds32/isr-library/save_all.inc67
-rw-r--r--libgcc/config/nds32/isr-library/save_fpu_regs.inc36
-rw-r--r--libgcc/config/nds32/isr-library/save_fpu_regs_00.inc33
-rw-r--r--libgcc/config/nds32/isr-library/save_fpu_regs_01.inc37
-rw-r--r--libgcc/config/nds32/isr-library/save_fpu_regs_02.inc45
-rw-r--r--libgcc/config/nds32/isr-library/save_fpu_regs_03.inc61
-rw-r--r--libgcc/config/nds32/isr-library/save_mac_regs.inc34
-rw-r--r--libgcc/config/nds32/isr-library/save_partial.inc69
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid00.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid00_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid01.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid01_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid02.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid02_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid03.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid03_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid04.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid04_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid05.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid05_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid06.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid06_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid07.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid07_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid08.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid08_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid09.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid09_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid10.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid10_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid11.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid11_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid12.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid12_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid13.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid13_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid14.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid14_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid15.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid15_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid16.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid16_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid17.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid17_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid18.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid18_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid19.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid19_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid20.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid20_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid21.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid21_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid22.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid22_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid23.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid23_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid24.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid24_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid25.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid25_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid26.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid26_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid27.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid27_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid28.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid28_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid29.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid29_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid30.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid30_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid31.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid31_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid32.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid32_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid33.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid33_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid34.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid34_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid35.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid35_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid36.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid36_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid37.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid37_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid38.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid38_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid39.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid39_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid40.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid40_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid41.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid41_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid42.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid42_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid43.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid43_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid44.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid44_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid45.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid45_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid46.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid46_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid47.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid47_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid48.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid48_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid49.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid49_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid50.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid50_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid51.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid51_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid52.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid52_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid53.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid53_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid54.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid54_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid55.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid55_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid56.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid56_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid57.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid57_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid58.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid58_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid59.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid59_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid60.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid60_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid61.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid61_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid62.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid62_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid63.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid63_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid64.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid64_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid65.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid65_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid66.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid66_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid67.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid67_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid68.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid68_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid69.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid69_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid70.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid70_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid71.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid71_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid72.S34
-rw-r--r--libgcc/config/nds32/isr-library/vec_vid72_4b.S34
-rw-r--r--libgcc/config/nds32/isr-library/wrh.S32
-rw-r--r--libgcc/config/nds32/lib1asmsrc-mculib.S5213
-rw-r--r--libgcc/config/nds32/lib1asmsrc-newlib.S204
-rw-r--r--libgcc/config/nds32/lib2csrc-mculib/_clzdi2.c38
-rw-r--r--libgcc/config/nds32/lib2csrc-mculib/_clzsi2.c49
-rw-r--r--libgcc/config/nds32/sfp-machine.h91
-rw-r--r--libgcc/config/nds32/t-nds3258
-rw-r--r--libgcc/config/nds32/t-nds32-isr212
-rw-r--r--libgcc/config/nds32/t-nds32-mculib77
-rw-r--r--libgcc/config/nds32/t-nds32-newlib34
-rw-r--r--libgcc/configure13
-rw-r--r--libgcc/configure.ac9
-rw-r--r--libgcc/libgcov.c38
-rw-r--r--libgcc/longlong.h57
-rw-r--r--libgcc/soft-fp/README9
-rw-r--r--libgcc/soft-fp/adddf3.c15
-rw-r--r--libgcc/soft-fp/addsf3.c15
-rw-r--r--libgcc/soft-fp/addtf3.c15
-rw-r--r--libgcc/soft-fp/divdf3.c15
-rw-r--r--libgcc/soft-fp/divsf3.c15
-rw-r--r--libgcc/soft-fp/divtf3.c15
-rw-r--r--libgcc/soft-fp/double.h395
-rw-r--r--libgcc/soft-fp/eqdf2.c19
-rw-r--r--libgcc/soft-fp/eqsf2.c19
-rw-r--r--libgcc/soft-fp/eqtf2.c19
-rw-r--r--libgcc/soft-fp/extenddftf2.c17
-rw-r--r--libgcc/soft-fp/extended.h740
-rw-r--r--libgcc/soft-fp/extendsfdf2.c17
-rw-r--r--libgcc/soft-fp/extendsftf2.c17
-rw-r--r--libgcc/soft-fp/extendxftf2.c22
-rw-r--r--libgcc/soft-fp/fixdfdi.c10
-rw-r--r--libgcc/soft-fp/fixdfsi.c10
-rw-r--r--libgcc/soft-fp/fixdfti.c17
-rw-r--r--libgcc/soft-fp/fixsfdi.c10
-rw-r--r--libgcc/soft-fp/fixsfsi.c10
-rw-r--r--libgcc/soft-fp/fixsfti.c17
-rw-r--r--libgcc/soft-fp/fixtfdi.c10
-rw-r--r--libgcc/soft-fp/fixtfsi.c10
-rw-r--r--libgcc/soft-fp/fixtfti.c17
-rw-r--r--libgcc/soft-fp/fixunsdfdi.c10
-rw-r--r--libgcc/soft-fp/fixunsdfsi.c10
-rw-r--r--libgcc/soft-fp/fixunsdfti.c17
-rw-r--r--libgcc/soft-fp/fixunssfdi.c10
-rw-r--r--libgcc/soft-fp/fixunssfsi.c10
-rw-r--r--libgcc/soft-fp/fixunssfti.c17
-rw-r--r--libgcc/soft-fp/fixunstfdi.c10
-rw-r--r--libgcc/soft-fp/fixunstfsi.c10
-rw-r--r--libgcc/soft-fp/fixunstfti.c17
-rw-r--r--libgcc/soft-fp/floatdidf.c10
-rw-r--r--libgcc/soft-fp/floatdisf.c10
-rw-r--r--libgcc/soft-fp/floatditf.c12
-rw-r--r--libgcc/soft-fp/floatsidf.c12
-rw-r--r--libgcc/soft-fp/floatsisf.c10
-rw-r--r--libgcc/soft-fp/floatsitf.c12
-rw-r--r--libgcc/soft-fp/floattidf.c17
-rw-r--r--libgcc/soft-fp/floattisf.c17
-rw-r--r--libgcc/soft-fp/floattitf.c17
-rw-r--r--libgcc/soft-fp/floatundidf.c10
-rw-r--r--libgcc/soft-fp/floatundisf.c10
-rw-r--r--libgcc/soft-fp/floatunditf.c11
-rw-r--r--libgcc/soft-fp/floatunsidf.c12
-rw-r--r--libgcc/soft-fp/floatunsisf.c10
-rw-r--r--libgcc/soft-fp/floatunsitf.c11
-rw-r--r--libgcc/soft-fp/floatuntidf.c17
-rw-r--r--libgcc/soft-fp/floatuntisf.c17
-rw-r--r--libgcc/soft-fp/floatuntitf.c17
-rw-r--r--libgcc/soft-fp/gedf2.c19
-rw-r--r--libgcc/soft-fp/gesf2.c19
-rw-r--r--libgcc/soft-fp/getf2.c19
-rw-r--r--libgcc/soft-fp/ledf2.c19
-rw-r--r--libgcc/soft-fp/lesf2.c19
-rw-r--r--libgcc/soft-fp/letf2.c19
-rw-r--r--libgcc/soft-fp/muldf3.c15
-rw-r--r--libgcc/soft-fp/mulsf3.c15
-rw-r--r--libgcc/soft-fp/multf3.c15
-rw-r--r--libgcc/soft-fp/negdf2.c15
-rw-r--r--libgcc/soft-fp/negsf2.c15
-rw-r--r--libgcc/soft-fp/negtf2.c15
-rw-r--r--libgcc/soft-fp/op-1.h407
-rw-r--r--libgcc/soft-fp/op-2.h981
-rw-r--r--libgcc/soft-fp/op-4.h1187
-rw-r--r--libgcc/soft-fp/op-8.h135
-rw-r--r--libgcc/soft-fp/op-common.h2689
-rw-r--r--libgcc/soft-fp/quad.h431
-rw-r--r--libgcc/soft-fp/single.h216
-rw-r--r--libgcc/soft-fp/soft-fp.h199
-rw-r--r--libgcc/soft-fp/subdf3.c15
-rw-r--r--libgcc/soft-fp/subsf3.c15
-rw-r--r--libgcc/soft-fp/subtf3.c15
-rw-r--r--libgcc/soft-fp/truncdfsf2.c15
-rw-r--r--libgcc/soft-fp/trunctfdf2.c15
-rw-r--r--libgcc/soft-fp/trunctfsf2.c15
-rw-r--r--libgcc/soft-fp/trunctfxf2.c22
-rw-r--r--libgcc/soft-fp/unorddf2.c17
-rw-r--r--libgcc/soft-fp/unordsf2.c18
-rw-r--r--libgcc/soft-fp/unordtf2.c18
-rw-r--r--libgcc/sync.c29
-rw-r--r--libgfortran/ChangeLog25
-rw-r--r--libgfortran/Makefile.in43
-rw-r--r--libgfortran/aclocal.m474
-rw-r--r--libgfortran/config.h.in3
-rwxr-xr-xlibgfortran/configure35
-rw-r--r--libgfortran/configure.ac2
-rw-r--r--libgfortran/io/list_read.c32
-rw-r--r--libgfortran/io/unix.c43
-rw-r--r--libgo/MERGE2
-rw-r--r--libgo/Makefile.am126
-rw-r--r--libgo/Makefile.in209
-rw-r--r--libgo/config.h.in30
-rwxr-xr-xlibgo/configure119
-rw-r--r--libgo/configure.ac69
-rw-r--r--libgo/go/archive/tar/common.go47
-rw-r--r--libgo/go/archive/tar/reader.go36
-rw-r--r--libgo/go/archive/tar/reader_test.go21
-rw-r--r--libgo/go/archive/tar/tar_test.go11
-rw-r--r--libgo/go/archive/tar/testdata/nil-uid.tarbin0 -> 1024 bytes
-rw-r--r--libgo/go/archive/tar/writer.go174
-rw-r--r--libgo/go/archive/tar/writer_test.go137
-rw-r--r--libgo/go/archive/zip/reader.go27
-rw-r--r--libgo/go/archive/zip/reader_test.go1
-rw-r--r--libgo/go/archive/zip/register.go71
-rw-r--r--libgo/go/archive/zip/struct.go6
-rw-r--r--libgo/go/archive/zip/writer.go18
-rw-r--r--libgo/go/archive/zip/zip_test.go170
-rw-r--r--libgo/go/bufio/bufio.go86
-rw-r--r--libgo/go/bufio/bufio_test.go97
-rw-r--r--libgo/go/bufio/example_test.go8
-rw-r--r--libgo/go/bufio/scan.go6
-rw-r--r--libgo/go/builtin/builtin.go13
-rw-r--r--libgo/go/bytes/bytes.go33
-rw-r--r--libgo/go/bytes/bytes_decl.go14
-rw-r--r--libgo/go/bytes/bytes_test.go60
-rw-r--r--libgo/go/bytes/compare_test.go204
-rw-r--r--libgo/go/bytes/indexbyte.c30
-rw-r--r--libgo/go/bytes/reader_test.go35
-rw-r--r--libgo/go/compress/bzip2/bit_reader.go8
-rw-r--r--libgo/go/compress/bzip2/bzip2.go167
-rw-r--r--libgo/go/compress/bzip2/bzip2_test.go206
-rw-r--r--libgo/go/compress/bzip2/huffman.go9
-rw-r--r--libgo/go/compress/bzip2/move_to_front.go35
-rw-r--r--libgo/go/compress/flate/copy.go27
-rw-r--r--libgo/go/compress/flate/copy_test.go10
-rw-r--r--libgo/go/compress/flate/deflate.go67
-rw-r--r--libgo/go/compress/flate/deflate_test.go64
-rw-r--r--libgo/go/compress/flate/flate_test.go36
-rw-r--r--libgo/go/compress/flate/huffman_bit_writer.go25
-rw-r--r--libgo/go/compress/flate/huffman_code.go92
-rw-r--r--libgo/go/compress/flate/inflate.go19
-rw-r--r--libgo/go/compress/flate/reader_test.go5
-rw-r--r--libgo/go/compress/gzip/gunzip_test.go31
-rw-r--r--libgo/go/compress/gzip/gzip.go66
-rw-r--r--libgo/go/compress/gzip/gzip_test.go32
-rw-r--r--libgo/go/compress/gzip/testdata/issue6550.gzbin0 -> 65536 bytes
-rw-r--r--libgo/go/compress/zlib/writer.go29
-rw-r--r--libgo/go/compress/zlib/writer_test.go65
-rw-r--r--libgo/go/container/heap/heap.go13
-rw-r--r--libgo/go/container/heap/heap_test.go29
-rwxr-xr-xlibgo/go/container/list/list.go25
-rwxr-xr-xlibgo/go/container/list/list_test.go52
-rw-r--r--libgo/go/crypto/cipher/cbc.go14
-rw-r--r--libgo/go/crypto/cipher/gcm.go350
-rw-r--r--libgo/go/crypto/cipher/gcm_test.go175
-rw-r--r--libgo/go/crypto/cipher/io.go11
-rw-r--r--libgo/go/crypto/crypto.go6
-rw-r--r--libgo/go/crypto/des/block.go137
-rw-r--r--libgo/go/crypto/des/des_test.go65
-rw-r--r--libgo/go/crypto/ecdsa/ecdsa.go4
-rw-r--r--libgo/go/crypto/elliptic/elliptic.go12
-rw-r--r--libgo/go/crypto/elliptic/elliptic_test.go57
-rw-r--r--libgo/go/crypto/elliptic/p256.go1186
-rw-r--r--libgo/go/crypto/md5/gen.go2
-rw-r--r--libgo/go/crypto/md5/md5.go14
-rw-r--r--libgo/go/crypto/md5/md5_test.go32
-rw-r--r--libgo/go/crypto/md5/md5block.go2
-rw-r--r--libgo/go/crypto/md5/md5block_decl.go4
-rw-r--r--libgo/go/crypto/rand/rand.go7
-rw-r--r--libgo/go/crypto/rand/rand_unix.go2
-rw-r--r--libgo/go/crypto/rsa/pkcs1v15.go6
-rw-r--r--libgo/go/crypto/rsa/pkcs1v15_test.go8
-rw-r--r--libgo/go/crypto/rsa/pss.go282
-rw-r--r--libgo/go/crypto/rsa/pss_test.go249
-rw-r--r--libgo/go/crypto/rsa/rsa.go2
-rw-r--r--libgo/go/crypto/rsa/rsa_test.go6
-rw-r--r--libgo/go/crypto/rsa/testdata/pss-vect.txt.bz2bin0 -> 28526 bytes
-rw-r--r--libgo/go/crypto/sha1/sha1.go16
-rw-r--r--libgo/go/crypto/sha1/sha1_test.go11
-rw-r--r--libgo/go/crypto/sha1/sha1block_decl.go2
-rw-r--r--libgo/go/crypto/sha256/sha256.go32
-rw-r--r--libgo/go/crypto/sha256/sha256_test.go8
-rw-r--r--libgo/go/crypto/sha512/sha512.go30
-rw-r--r--libgo/go/crypto/sha512/sha512_test.go8
-rw-r--r--libgo/go/crypto/subtle/constant_time.go8
-rw-r--r--libgo/go/crypto/subtle/constant_time_test.go20
-rw-r--r--libgo/go/crypto/tls/cipher_suites.go146
-rw-r--r--libgo/go/crypto/tls/common.go146
-rw-r--r--libgo/go/crypto/tls/conn.go192
-rw-r--r--libgo/go/crypto/tls/generate_cert.go2
-rw-r--r--libgo/go/crypto/tls/handshake_client.go161
-rw-r--r--libgo/go/crypto/tls/handshake_client_test.go2654
-rw-r--r--libgo/go/crypto/tls/handshake_messages.go148
-rw-r--r--libgo/go/crypto/tls/handshake_messages_test.go3
-rw-r--r--libgo/go/crypto/tls/handshake_server.go121
-rw-r--r--libgo/go/crypto/tls/handshake_server_test.go2401
-rw-r--r--libgo/go/crypto/tls/key_agreement.go183
-rw-r--r--libgo/go/crypto/tls/prf.go141
-rw-r--r--libgo/go/crypto/tls/prf_test.go8
-rw-r--r--libgo/go/crypto/tls/tls.go2
-rw-r--r--libgo/go/crypto/x509/cert_pool.go11
-rw-r--r--libgo/go/crypto/x509/pkcs1.go4
-rw-r--r--libgo/go/crypto/x509/pkcs8.go6
-rw-r--r--libgo/go/crypto/x509/pkix/pkix.go2
-rw-r--r--libgo/go/crypto/x509/root_unix.go6
-rw-r--r--libgo/go/crypto/x509/root_windows.go6
-rw-r--r--libgo/go/crypto/x509/sec1.go22
-rw-r--r--libgo/go/crypto/x509/sec1_test.go10
-rw-r--r--libgo/go/crypto/x509/verify.go40
-rw-r--r--libgo/go/crypto/x509/verify_test.go273
-rw-r--r--libgo/go/crypto/x509/x509.go299
-rw-r--r--libgo/go/crypto/x509/x509_test.go46
-rw-r--r--libgo/go/database/sql/convert_test.go4
-rw-r--r--libgo/go/database/sql/driver/types_test.go4
-rw-r--r--libgo/go/database/sql/fakedb_test.go50
-rw-r--r--libgo/go/database/sql/sql.go371
-rw-r--r--libgo/go/database/sql/sql_test.go759
-rw-r--r--libgo/go/debug/dwarf/entry.go7
-rw-r--r--libgo/go/debug/dwarf/type.go43
-rw-r--r--libgo/go/debug/elf/file_test.go1
-rw-r--r--libgo/go/debug/gosym/pclntab.go360
-rw-r--r--libgo/go/debug/gosym/pclntab_test.go46
-rw-r--r--libgo/go/debug/gosym/symtab.go93
-rw-r--r--libgo/go/encoding/asn1/asn1.go44
-rw-r--r--libgo/go/encoding/asn1/asn1_test.go29
-rw-r--r--libgo/go/encoding/asn1/marshal.go14
-rw-r--r--libgo/go/encoding/asn1/marshal_test.go1
-rw-r--r--libgo/go/encoding/binary/binary.go243
-rw-r--r--libgo/go/encoding/binary/binary_test.go59
-rw-r--r--libgo/go/encoding/csv/reader.go58
-rw-r--r--libgo/go/encoding/csv/reader_test.go33
-rw-r--r--libgo/go/encoding/encoding.go48
-rw-r--r--libgo/go/encoding/gob/codec_test.go18
-rw-r--r--libgo/go/encoding/gob/debug.go10
-rw-r--r--libgo/go/encoding/gob/decode.go89
-rw-r--r--libgo/go/encoding/gob/doc.go40
-rw-r--r--libgo/go/encoding/gob/encode.go66
-rw-r--r--libgo/go/encoding/gob/encoder.go12
-rw-r--r--libgo/go/encoding/gob/encoder_test.go42
-rw-r--r--libgo/go/encoding/gob/gobencdec_test.go146
-rw-r--r--libgo/go/encoding/gob/timing_test.go15
-rw-r--r--libgo/go/encoding/gob/type.go104
-rw-r--r--libgo/go/encoding/json/decode.go70
-rw-r--r--libgo/go/encoding/json/decode_test.go167
-rw-r--r--libgo/go/encoding/json/encode.go714
-rw-r--r--libgo/go/encoding/json/encode_test.go123
-rw-r--r--libgo/go/encoding/json/indent.go9
-rw-r--r--libgo/go/encoding/json/scanner.go2
-rw-r--r--libgo/go/encoding/json/scanner_test.go19
-rw-r--r--libgo/go/encoding/json/stream.go11
-rw-r--r--libgo/go/encoding/json/stream_test.go13
-rw-r--r--libgo/go/encoding/json/tags.go2
-rw-r--r--libgo/go/encoding/xml/marshal.go575
-rw-r--r--libgo/go/encoding/xml/marshal_test.go128
-rw-r--r--libgo/go/encoding/xml/read.go206
-rw-r--r--libgo/go/encoding/xml/read_test.go64
-rw-r--r--libgo/go/encoding/xml/xml.go160
-rw-r--r--libgo/go/encoding/xml/xml_test.go14
-rw-r--r--libgo/go/flag/export_test.go7
-rw-r--r--libgo/go/flag/flag.go113
-rw-r--r--libgo/go/flag/flag_test.go50
-rw-r--r--libgo/go/fmt/doc.go33
-rw-r--r--libgo/go/fmt/fmt_test.go89
-rw-r--r--libgo/go/fmt/format.go23
-rw-r--r--libgo/go/fmt/print.go282
-rw-r--r--libgo/go/fmt/scan.go67
-rw-r--r--libgo/go/fmt/scan_test.go5
-rw-r--r--libgo/go/go/ast/ast.go76
-rw-r--r--libgo/go/go/ast/commentmap.go10
-rw-r--r--libgo/go/go/ast/filter.go2
-rw-r--r--libgo/go/go/ast/import.go98
-rw-r--r--libgo/go/go/ast/walk.go3
-rw-r--r--libgo/go/go/build/build.go285
-rw-r--r--libgo/go/go/build/build_test.go105
-rw-r--r--libgo/go/go/build/deps_test.go57
-rw-r--r--libgo/go/go/build/doc.go1
-rw-r--r--libgo/go/go/build/syslist_test.go2
-rw-r--r--libgo/go/go/doc/comment.go11
-rw-r--r--libgo/go/go/doc/doc_test.go10
-rw-r--r--libgo/go/go/doc/example.go2
-rw-r--r--libgo/go/go/doc/example_test.go10
-rw-r--r--libgo/go/go/doc/reader.go2
-rw-r--r--libgo/go/go/doc/synopsis.go12
-rw-r--r--libgo/go/go/doc/testdata/a.0.golden46
-rw-r--r--libgo/go/go/doc/testdata/a.1.golden46
-rw-r--r--libgo/go/go/doc/testdata/a.2.golden46
-rw-r--r--libgo/go/go/doc/testdata/bugpara.0.golden20
-rw-r--r--libgo/go/go/doc/testdata/bugpara.1.golden20
-rw-r--r--libgo/go/go/doc/testdata/bugpara.2.golden20
-rw-r--r--libgo/go/go/doc/testdata/bugpara.go5
-rw-r--r--libgo/go/go/doc/testdata/template.txt4
-rw-r--r--libgo/go/go/doc/testdata/testing.0.golden4
-rw-r--r--libgo/go/go/doc/testdata/testing.1.golden6
-rw-r--r--libgo/go/go/doc/testdata/testing.2.golden4
-rw-r--r--libgo/go/go/doc/testdata/testing.go2
-rw-r--r--libgo/go/go/format/format_test.go1
-rw-r--r--libgo/go/go/parser/interface.go15
-rw-r--r--libgo/go/go/parser/parser.go50
-rw-r--r--libgo/go/go/parser/parser_test.go18
-rw-r--r--libgo/go/go/parser/short_test.go6
-rw-r--r--libgo/go/go/printer/nodes.go32
-rw-r--r--libgo/go/go/printer/testdata/expressions.golden17
-rw-r--r--libgo/go/go/printer/testdata/expressions.input17
-rw-r--r--libgo/go/go/printer/testdata/expressions.raw17
-rw-r--r--libgo/go/go/token/position.go31
-rw-r--r--libgo/go/go/token/position_test.go8
-rw-r--r--libgo/go/hash/hash.go4
-rw-r--r--libgo/go/html/escape.go10
-rw-r--r--libgo/go/html/escape_test.go97
-rw-r--r--libgo/go/html/template/clone_test.go40
-rw-r--r--libgo/go/html/template/content.go6
-rw-r--r--libgo/go/html/template/content_test.go31
-rw-r--r--libgo/go/html/template/context.go2
-rw-r--r--libgo/go/html/template/css.go8
-rw-r--r--libgo/go/html/template/escape.go4
-rw-r--r--libgo/go/html/template/escape_test.go11
-rw-r--r--libgo/go/html/template/js.go2
-rw-r--r--libgo/go/html/template/template.go18
-rw-r--r--libgo/go/html/template/transition.go4
-rw-r--r--libgo/go/image/color/color.go26
-rw-r--r--libgo/go/image/color/palette/gen.go97
-rw-r--r--libgo/go/image/color/palette/palette.go500
-rw-r--r--libgo/go/image/decode_example_test.go113
-rw-r--r--libgo/go/image/draw/draw.go209
-rw-r--r--libgo/go/image/draw/draw_test.go75
-rw-r--r--libgo/go/image/format.go6
-rw-r--r--libgo/go/image/geom.go12
-rw-r--r--libgo/go/image/gif/reader.go13
-rw-r--r--libgo/go/image/gif/reader_test.go83
-rw-r--r--libgo/go/image/gif/writer.go323
-rw-r--r--libgo/go/image/gif/writer_test.go204
-rw-r--r--libgo/go/image/image.go18
-rw-r--r--libgo/go/image/jpeg/dct_test.go2
-rw-r--r--libgo/go/image/jpeg/reader.go4
-rw-r--r--libgo/go/image/names.go2
-rw-r--r--libgo/go/io/io.go28
-rw-r--r--libgo/go/io/io_test.go68
-rw-r--r--libgo/go/io/ioutil/ioutil.go8
-rw-r--r--libgo/go/io/pipe.go4
-rw-r--r--libgo/go/io/pipe_test.go32
-rw-r--r--libgo/go/log/syslog/syslog.go35
-rw-r--r--libgo/go/log/syslog/syslog_test.go34
-rw-r--r--libgo/go/log/syslog/syslog_unix.go2
-rw-r--r--libgo/go/math/asin.go4
-rw-r--r--libgo/go/math/atan.go2
-rw-r--r--libgo/go/math/big/int.go18
-rw-r--r--libgo/go/math/big/int_test.go28
-rw-r--r--libgo/go/math/big/nat_test.go2
-rw-r--r--libgo/go/math/big/rat.go12
-rw-r--r--libgo/go/math/big/rat_test.go26
-rw-r--r--libgo/go/math/bits.go10
-rw-r--r--libgo/go/math/rand/rand.go42
-rw-r--r--libgo/go/math/sin.go4
-rw-r--r--libgo/go/math/tan.go2
-rw-r--r--libgo/go/mime/grammar.go13
-rw-r--r--libgo/go/mime/mediatype.go2
-rw-r--r--libgo/go/mime/mediatype_test.go9
-rw-r--r--libgo/go/mime/multipart/multipart.go6
-rw-r--r--libgo/go/mime/type_plan9.go53
-rw-r--r--libgo/go/mime/type_unix.go2
-rw-r--r--libgo/go/net/cgo_bsd.go3
-rw-r--r--libgo/go/net/cgo_linux.go2
-rw-r--r--libgo/go/net/cgo_netbsd.go2
-rw-r--r--libgo/go/net/cgo_openbsd.go2
-rw-r--r--libgo/go/net/cgo_stub.go2
-rw-r--r--libgo/go/net/cgo_unix.go25
-rw-r--r--libgo/go/net/dial.go128
-rw-r--r--libgo/go/net/dial_gen.go51
-rw-r--r--libgo/go/net/dial_test.go178
-rw-r--r--libgo/go/net/dialgoogle_test.go77
-rw-r--r--libgo/go/net/dnsclient.go12
-rw-r--r--libgo/go/net/dnsclient_unix.go51
-rw-r--r--libgo/go/net/dnsclient_unix_test.go27
-rw-r--r--libgo/go/net/dnsconfig_unix.go2
-rw-r--r--libgo/go/net/dnsname_test.go20
-rw-r--r--libgo/go/net/fd_bsd.go123
-rw-r--r--libgo/go/net/fd_mutex.go184
-rw-r--r--libgo/go/net/fd_mutex_test.go186
-rw-r--r--libgo/go/net/fd_plan9.go16
-rw-r--r--libgo/go/net/fd_poll_runtime.go66
-rw-r--r--libgo/go/net/fd_poll_unix.go360
-rw-r--r--libgo/go/net/fd_posix_test.go57
-rw-r--r--libgo/go/net/fd_unix.go238
-rw-r--r--libgo/go/net/fd_unix_test.go2
-rw-r--r--libgo/go/net/fd_windows.go715
-rw-r--r--libgo/go/net/file_unix.go13
-rw-r--r--libgo/go/net/http/cgi/child.go23
-rw-r--r--libgo/go/net/http/cgi/child_test.go28
-rw-r--r--libgo/go/net/http/client.go21
-rw-r--r--libgo/go/net/http/client_test.go99
-rw-r--r--libgo/go/net/http/cookie.go135
-rw-r--r--libgo/go/net/http/cookie_test.go49
-rw-r--r--libgo/go/net/http/cookiejar/jar.go8
-rw-r--r--libgo/go/net/http/doc.go2
-rw-r--r--libgo/go/net/http/example_test.go18
-rw-r--r--libgo/go/net/http/export_test.go8
-rw-r--r--libgo/go/net/http/fs.go56
-rw-r--r--libgo/go/net/http/fs_test.go59
-rw-r--r--libgo/go/net/http/header.go2
-rw-r--r--libgo/go/net/http/header_test.go5
-rw-r--r--libgo/go/net/http/request.go28
-rw-r--r--libgo/go/net/http/request_test.go2
-rw-r--r--libgo/go/net/http/response.go25
-rw-r--r--libgo/go/net/http/response_test.go62
-rw-r--r--libgo/go/net/http/serve_test.go457
-rw-r--r--libgo/go/net/http/server.go280
-rw-r--r--libgo/go/net/http/server_test.go104
-rw-r--r--libgo/go/net/http/sniff_test.go24
-rw-r--r--libgo/go/net/http/transfer.go44
-rw-r--r--libgo/go/net/http/transport.go40
-rw-r--r--libgo/go/net/http/transport_test.go94
-rw-r--r--libgo/go/net/http/z_last_test.go1
-rw-r--r--libgo/go/net/interface_bsd.go2
-rw-r--r--libgo/go/net/interface_dragonfly.go12
-rw-r--r--libgo/go/net/interface_test.go17
-rw-r--r--libgo/go/net/ip.go39
-rw-r--r--libgo/go/net/ip_test.go38
-rw-r--r--libgo/go/net/ipraw_test.go189
-rw-r--r--libgo/go/net/iprawsock.go9
-rw-r--r--libgo/go/net/iprawsock_posix.go48
-rw-r--r--libgo/go/net/ipsock.go186
-rw-r--r--libgo/go/net/ipsock_plan9.go9
-rw-r--r--libgo/go/net/ipsock_posix.go55
-rw-r--r--libgo/go/net/ipsock_test.go193
-rw-r--r--libgo/go/net/lookup.go58
-rw-r--r--libgo/go/net/lookup_plan9.go8
-rw-r--r--libgo/go/net/lookup_unix.go16
-rw-r--r--libgo/go/net/lookup_windows.go30
-rw-r--r--libgo/go/net/mail/message.go6
-rw-r--r--libgo/go/net/mail/message_test.go10
-rw-r--r--libgo/go/net/mockicmp_test.go116
-rw-r--r--libgo/go/net/mockserver_test.go82
-rw-r--r--libgo/go/net/multicast_test.go2
-rw-r--r--libgo/go/net/net.go54
-rw-r--r--libgo/go/net/net_test.go44
-rw-r--r--libgo/go/net/packetconn_test.go106
-rw-r--r--libgo/go/net/parse_test.go2
-rw-r--r--libgo/go/net/port_unix.go2
-rw-r--r--libgo/go/net/protoconn_test.go40
-rw-r--r--libgo/go/net/race.go31
-rw-r--r--libgo/go/net/race0.go26
-rw-r--r--libgo/go/net/rpc/client.go7
-rw-r--r--libgo/go/net/rpc/debug.go3
-rw-r--r--libgo/go/net/rpc/jsonrpc/server.go3
-rw-r--r--libgo/go/net/rpc/server.go24
-rw-r--r--libgo/go/net/rpc/server_test.go52
-rw-r--r--libgo/go/net/sendfile_dragonfly.go103
-rw-r--r--libgo/go/net/sendfile_freebsd.go6
-rw-r--r--libgo/go/net/sendfile_linux.go6
-rw-r--r--libgo/go/net/sendfile_windows.go35
-rw-r--r--libgo/go/net/singleflight.go53
-rw-r--r--libgo/go/net/smtp/smtp.go22
-rw-r--r--libgo/go/net/smtp/smtp_test.go47
-rw-r--r--libgo/go/net/sock_bsd.go2
-rw-r--r--libgo/go/net/sock_plan9.go10
-rw-r--r--libgo/go/net/sock_posix.go213
-rw-r--r--libgo/go/net/sock_unix.go36
-rw-r--r--libgo/go/net/sock_windows.go27
-rw-r--r--libgo/go/net/sockopt_bsd.go41
-rw-r--r--libgo/go/net/sockopt_linux.go37
-rw-r--r--libgo/go/net/sockopt_posix.go20
-rw-r--r--libgo/go/net/sockopt_windows.go44
-rw-r--r--libgo/go/net/sockoptip_bsd.go18
-rw-r--r--libgo/go/net/sockoptip_linux.go16
-rw-r--r--libgo/go/net/sockoptip_posix.go34
-rw-r--r--libgo/go/net/sockoptip_windows.go17
-rw-r--r--libgo/go/net/sys_cloexec.go2
-rw-r--r--libgo/go/net/tcp_test.go310
-rw-r--r--libgo/go/net/tcpsock.go14
-rw-r--r--libgo/go/net/tcpsock_plan9.go9
-rw-r--r--libgo/go/net/tcpsock_posix.go45
-rw-r--r--libgo/go/net/tcpsockopt_darwin.go27
-rw-r--r--libgo/go/net/tcpsockopt_openbsd.go27
-rw-r--r--libgo/go/net/tcpsockopt_posix.go20
-rw-r--r--libgo/go/net/tcpsockopt_solaris.go25
-rw-r--r--libgo/go/net/tcpsockopt_unix.go31
-rw-r--r--libgo/go/net/tcpsockopt_windows.go21
-rw-r--r--libgo/go/net/textproto/reader.go51
-rw-r--r--libgo/go/net/textproto/textproto.go2
-rw-r--r--libgo/go/net/timeout_test.go47
-rw-r--r--libgo/go/net/udp_test.go58
-rw-r--r--libgo/go/net/udpsock.go14
-rw-r--r--libgo/go/net/udpsock_plan9.go3
-rw-r--r--libgo/go/net/udpsock_posix.go52
-rw-r--r--libgo/go/net/unicast_posix_test.go12
-rw-r--r--libgo/go/net/unix_test.go17
-rw-r--r--libgo/go/net/unixsock.go4
-rw-r--r--libgo/go/net/unixsock_plan9.go2
-rw-r--r--libgo/go/net/unixsock_posix.go89
-rw-r--r--libgo/go/net/url/url.go7
-rw-r--r--libgo/go/net/url/url_test.go24
-rw-r--r--libgo/go/os/dir_unix.go2
-rw-r--r--libgo/go/os/doc.go8
-rw-r--r--libgo/go/os/env_unix_test.go2
-rw-r--r--libgo/go/os/error.go15
-rw-r--r--libgo/go/os/error_posix.go45
-rw-r--r--libgo/go/os/error_unix.go45
-rw-r--r--libgo/go/os/exec/exec.go38
-rw-r--r--libgo/go/os/exec/exec_test.go86
-rw-r--r--libgo/go/os/exec/lp_plan9.go1
-rw-r--r--libgo/go/os/exec/lp_unix.go3
-rw-r--r--libgo/go/os/exec/lp_unix_test.go2
-rw-r--r--libgo/go/os/exec/lp_windows.go16
-rw-r--r--libgo/go/os/exec_posix.go2
-rw-r--r--libgo/go/os/exec_unix.go2
-rw-r--r--libgo/go/os/exec_windows.go13
-rw-r--r--libgo/go/os/export_test.go1
-rw-r--r--libgo/go/os/file.go9
-rw-r--r--libgo/go/os/file_plan9.go17
-rw-r--r--libgo/go/os/file_posix.go11
-rw-r--r--libgo/go/os/file_unix.go15
-rw-r--r--libgo/go/os/getwd.go8
-rw-r--r--libgo/go/os/getwd_darwin.go15
-rw-r--r--libgo/go/os/os_test.go102
-rw-r--r--libgo/go/os/os_unix_test.go42
-rw-r--r--libgo/go/os/path_test.go6
-rw-r--r--libgo/go/os/path_unix.go2
-rw-r--r--libgo/go/os/pipe_bsd.go2
-rw-r--r--libgo/go/os/signal/signal_test.go10
-rw-r--r--libgo/go/os/signal/signal_unix.go2
-rw-r--r--libgo/go/os/stat_dragonfly.go61
-rw-r--r--libgo/go/os/sys_bsd.go2
-rw-r--r--libgo/go/os/user/lookup_plan9.go46
-rw-r--r--libgo/go/os/user/lookup_stubs.go2
-rw-r--r--libgo/go/os/user/lookup_unix.go2
-rw-r--r--libgo/go/os/user/lookup_windows.go77
-rw-r--r--libgo/go/os/user/user.go2
-rw-r--r--libgo/go/os/user/user_test.go14
-rw-r--r--libgo/go/path/filepath/match.go6
-rw-r--r--libgo/go/path/filepath/match_test.go5
-rw-r--r--libgo/go/path/filepath/path_test.go30
-rw-r--r--libgo/go/path/filepath/path_unix.go2
-rw-r--r--libgo/go/path/match_test.go5
-rw-r--r--libgo/go/path/path_test.go5
-rw-r--r--libgo/go/reflect/all_test.go219
-rw-r--r--libgo/go/reflect/deepequal.go39
-rw-r--r--libgo/go/reflect/example_test.go14
-rw-r--r--libgo/go/reflect/makefunc.go26
-rw-r--r--libgo/go/reflect/makefunc_386.S198
-rw-r--r--libgo/go/reflect/makefunc_amd64.S162
-rw-r--r--libgo/go/reflect/makefunc_dummy.c12
-rw-r--r--libgo/go/reflect/makefuncgo_386.go135
-rw-r--r--libgo/go/reflect/makefuncgo_amd64.go493
-rw-r--r--libgo/go/reflect/type.go131
-rw-r--r--libgo/go/reflect/value.go209
-rw-r--r--libgo/go/regexp/all_test.go8
-rw-r--r--libgo/go/regexp/exec2_test.go20
-rw-r--r--libgo/go/regexp/exec_test.go20
-rw-r--r--libgo/go/regexp/regexp.go11
-rw-r--r--libgo/go/regexp/syntax/doc.go8
-rw-r--r--libgo/go/regexp/syntax/parse.go2
-rw-r--r--libgo/go/regexp/syntax/parse_test.go2
-rw-r--r--libgo/go/regexp/syntax/prog.go29
-rw-r--r--libgo/go/regexp/syntax/prog_test.go11
-rw-r--r--libgo/go/runtime/append_test.go48
-rw-r--r--libgo/go/runtime/crash_cgo_test.go34
-rw-r--r--libgo/go/runtime/crash_test.go90
-rw-r--r--libgo/go/runtime/debug/garbage.go34
-rw-r--r--libgo/go/runtime/debug/stack_test.go8
-rw-r--r--libgo/go/runtime/error.go16
-rw-r--r--libgo/go/runtime/export_test.go17
-rw-r--r--libgo/go/runtime/extern.go39
-rw-r--r--libgo/go/runtime/gc_test.go4
-rw-r--r--libgo/go/runtime/malloc_test.go156
-rw-r--r--libgo/go/runtime/map_test.go38
-rw-r--r--libgo/go/runtime/mapspeed_test.go62
-rw-r--r--libgo/go/runtime/mem.go4
-rw-r--r--libgo/go/runtime/memmove_test.go116
-rw-r--r--libgo/go/runtime/mfinal_test.go86
-rw-r--r--libgo/go/runtime/norace_test.go58
-rw-r--r--libgo/go/runtime/parfor_test.go5
-rw-r--r--libgo/go/runtime/pprof/pprof.go6
-rw-r--r--libgo/go/runtime/pprof/pprof_test.go363
-rw-r--r--libgo/go/runtime/proc_test.go250
-rw-r--r--libgo/go/runtime/runtime_test.go46
-rw-r--r--libgo/go/sort/example_interface_test.go79
-rw-r--r--libgo/go/sort/example_multi_test.go19
-rw-r--r--libgo/go/sort/example_wrapper_test.go77
-rw-r--r--libgo/go/sort/search_test.go3
-rw-r--r--libgo/go/sort/sort.go193
-rw-r--r--libgo/go/sort/sort_test.go202
-rw-r--r--libgo/go/strconv/atof.go4
-rw-r--r--libgo/go/strconv/atoi.go7
-rw-r--r--libgo/go/strconv/quote.go2
-rw-r--r--libgo/go/strconv/strconv_test.go3
-rw-r--r--libgo/go/strings/indexbyte.c29
-rw-r--r--libgo/go/strings/strings.go14
-rw-r--r--libgo/go/strings/strings_decl.go8
-rw-r--r--libgo/go/strings/strings_test.go33
-rw-r--r--libgo/go/sync/atomic/64bit_arm.go10
-rw-r--r--libgo/go/sync/atomic/atomic.c129
-rw-r--r--libgo/go/sync/atomic/atomic_test.go397
-rw-r--r--libgo/go/sync/atomic/doc.go31
-rw-r--r--libgo/go/sync/atomic/race.go48
-rw-r--r--libgo/go/sync/cond.go113
-rw-r--r--libgo/go/sync/cond_test.go129
-rw-r--r--libgo/go/sync/example_test.go7
-rw-r--r--libgo/go/sync/once.go4
-rw-r--r--libgo/go/sync/race.go8
-rw-r--r--libgo/go/sync/race0.go6
-rw-r--r--libgo/go/sync/runtime.go18
-rw-r--r--libgo/go/sync/waitgroup.go26
-rw-r--r--libgo/go/syscall/bpf_bsd.go2
-rw-r--r--libgo/go/syscall/consistency_unix_test.go34
-rw-r--r--libgo/go/syscall/env_unix.go2
-rw-r--r--libgo/go/syscall/env_windows.go13
-rw-r--r--libgo/go/syscall/exec_bsd.go10
-rw-r--r--libgo/go/syscall/exec_linux.go14
-rw-r--r--libgo/go/syscall/exec_unix.go2
-rw-r--r--libgo/go/syscall/libcall_linux.go15
-rw-r--r--libgo/go/syscall/libcall_posix.go6
-rw-r--r--libgo/go/syscall/passfd_test.go7
-rw-r--r--libgo/go/syscall/race0.go6
-rw-r--r--libgo/go/syscall/rlimit_linux_test.go41
-rw-r--r--libgo/go/syscall/route_bsd.go37
-rw-r--r--libgo/go/syscall/route_dragonfly.go72
-rw-r--r--libgo/go/syscall/security_windows.go9
-rw-r--r--libgo/go/syscall/signame.c2
-rw-r--r--libgo/go/syscall/sockcmsg_unix.go4
-rw-r--r--libgo/go/syscall/socket.go4
-rw-r--r--libgo/go/syscall/syscall_test.go30
-rw-r--r--libgo/go/syscall/syscall_unix.go22
-rw-r--r--libgo/go/testing/allocs.go8
-rw-r--r--libgo/go/testing/benchmark.go13
-rw-r--r--libgo/go/testing/benchmark_test.go58
-rw-r--r--libgo/go/testing/cover.go86
-rw-r--r--libgo/go/testing/export_test.go10
-rw-r--r--libgo/go/testing/quick/quick.go66
-rw-r--r--libgo/go/testing/quick/quick_test.go107
-rw-r--r--libgo/go/testing/testing.go133
-rw-r--r--libgo/go/text/template/doc.go46
-rw-r--r--libgo/go/text/template/exec.go19
-rw-r--r--libgo/go/text/template/exec_test.go127
-rw-r--r--libgo/go/text/template/funcs.go206
-rw-r--r--libgo/go/text/template/multi_test.go4
-rw-r--r--libgo/go/text/template/parse/lex.go9
-rw-r--r--libgo/go/text/template/parse/lex_test.go10
-rw-r--r--libgo/go/text/template/parse/node.go4
-rw-r--r--libgo/go/text/template/parse/parse.go66
-rw-r--r--libgo/go/text/template/parse/parse_test.go25
-rw-r--r--libgo/go/time/export_test.go2
-rw-r--r--libgo/go/time/format.go256
-rw-r--r--libgo/go/time/genzabbrs.go145
-rw-r--r--libgo/go/time/internal_test.go67
-rw-r--r--libgo/go/time/sleep.go3
-rw-r--r--libgo/go/time/sleep_test.go124
-rw-r--r--libgo/go/time/sys_unix.go2
-rw-r--r--libgo/go/time/time.go124
-rw-r--r--libgo/go/time/time_test.go138
-rw-r--r--libgo/go/time/zoneinfo.go13
-rw-r--r--libgo/go/time/zoneinfo_abbrs_windows.go115
-rw-r--r--libgo/go/time/zoneinfo_read.go4
-rw-r--r--libgo/go/time/zoneinfo_unix.go2
-rw-r--r--libgo/go/time/zoneinfo_windows.go134
-rw-r--r--libgo/go/unicode/graphic.go19
-rw-r--r--libgo/go/unicode/graphic_test.go4
-rwxr-xr-xlibgo/mksysinfo.sh30
-rw-r--r--libgo/runtime/chan.c80
-rw-r--r--libgo/runtime/cpuprof.c8
-rw-r--r--libgo/runtime/env_posix.c5
-rw-r--r--libgo/runtime/go-append.c12
-rw-r--r--libgo/runtime/go-byte-array-to-string.c2
-rw-r--r--libgo/runtime/go-caller.c20
-rw-r--r--libgo/runtime/go-callers.c15
-rw-r--r--libgo/runtime/go-cdiv.c46
-rw-r--r--libgo/runtime/go-int-array-to-string.c2
-rw-r--r--libgo/runtime/go-int-to-string.c2
-rw-r--r--libgo/runtime/go-make-slice.c21
-rw-r--r--libgo/runtime/go-new.c4
-rw-r--r--libgo/runtime/go-nosys.c57
-rw-r--r--libgo/runtime/go-reflect-call.c16
-rw-r--r--libgo/runtime/go-signal.c23
-rw-r--r--libgo/runtime/go-string-to-byte-array.c3
-rw-r--r--libgo/runtime/go-string-to-int-array.c4
-rw-r--r--libgo/runtime/go-strplus.c2
-rw-r--r--libgo/runtime/lfstack.c8
-rw-r--r--libgo/runtime/lock_futex.c73
-rw-r--r--libgo/runtime/lock_sema.c101
-rw-r--r--libgo/runtime/malloc.goc441
-rw-r--r--libgo/runtime/malloc.h112
-rw-r--r--libgo/runtime/mcache.c88
-rw-r--r--libgo/runtime/mcentral.c61
-rw-r--r--libgo/runtime/mem.c24
-rw-r--r--libgo/runtime/mfinal.c19
-rw-r--r--libgo/runtime/mfixalloc.c10
-rw-r--r--libgo/runtime/mgc0.c610
-rw-r--r--libgo/runtime/mgc0.h1
-rw-r--r--libgo/runtime/mheap.c141
-rw-r--r--libgo/runtime/mprof.goc84
-rw-r--r--libgo/runtime/msize.c39
-rw-r--r--libgo/runtime/netpoll.goc97
-rw-r--r--libgo/runtime/netpoll_epoll.c8
-rw-r--r--libgo/runtime/netpoll_kqueue.c32
-rw-r--r--libgo/runtime/netpoll_stub.c2
-rw-r--r--libgo/runtime/panic.c21
-rw-r--r--libgo/runtime/parfor.c4
-rw-r--r--libgo/runtime/print.c5
-rw-r--r--libgo/runtime/proc.c747
-rw-r--r--libgo/runtime/race.h6
-rw-r--r--libgo/runtime/runtime.c83
-rw-r--r--libgo/runtime/runtime.h101
-rw-r--r--libgo/runtime/sema.goc140
-rw-r--r--libgo/runtime/signal_unix.c4
-rw-r--r--libgo/runtime/sigqueue.goc11
-rw-r--r--libgo/runtime/string.goc23
-rw-r--r--libgo/runtime/thread-linux.c24
-rw-r--r--libgo/runtime/time.goc85
-rw-r--r--libgomp/ChangeLog460
-rw-r--r--libgomp/Makefile.am4
-rw-r--r--libgomp/Makefile.in7
-rw-r--r--libgomp/barrier.c12
-rw-r--r--libgomp/config/linux/affinity.c351
-rw-r--r--libgomp/config/linux/bar.c106
-rw-r--r--libgomp/config/linux/bar.h62
-rw-r--r--libgomp/config/linux/proc.c96
-rw-r--r--libgomp/config/linux/proc.h5
-rw-r--r--libgomp/config/posix/affinity.c79
-rw-r--r--libgomp/config/posix/bar.c132
-rw-r--r--libgomp/config/posix/bar.h58
-rwxr-xr-xlibgomp/configure33
-rw-r--r--libgomp/configure.ac4
-rw-r--r--libgomp/env.c825
-rw-r--r--libgomp/fortran.c67
-rw-r--r--libgomp/hashtab.h443
-rw-r--r--libgomp/libgomp.h140
-rw-r--r--libgomp/libgomp.map43
-rw-r--r--libgomp/libgomp.spec.in2
-rw-r--r--libgomp/libgomp.texi643
-rw-r--r--libgomp/libgomp_g.h36
-rw-r--r--libgomp/loop.c68
-rw-r--r--libgomp/omp.h.in46
-rw-r--r--libgomp/omp_lib.f90.in84
-rw-r--r--libgomp/omp_lib.h.in27
-rw-r--r--libgomp/parallel.c153
-rw-r--r--libgomp/sections.c26
-rw-r--r--libgomp/target.c96
-rw-r--r--libgomp/task.c719
-rw-r--r--libgomp/team.c471
-rw-r--r--libgomp/testsuite/lib/libgomp.exp4
-rw-r--r--libgomp/testsuite/libgomp.c++/affinity-1.C4
-rw-r--r--libgomp/testsuite/libgomp.c++/atomic-10.C99
-rw-r--r--libgomp/testsuite/libgomp.c++/atomic-11.C108
-rw-r--r--libgomp/testsuite/libgomp.c++/atomic-12.C58
-rw-r--r--libgomp/testsuite/libgomp.c++/atomic-13.C68
-rw-r--r--libgomp/testsuite/libgomp.c++/atomic-14.C99
-rw-r--r--libgomp/testsuite/libgomp.c++/atomic-15.C108
-rw-r--r--libgomp/testsuite/libgomp.c++/c++.exp3
-rw-r--r--libgomp/testsuite/libgomp.c++/cancel-for-1.C29
-rw-r--r--libgomp/testsuite/libgomp.c++/cancel-for-2.C126
-rw-r--r--libgomp/testsuite/libgomp.c++/cancel-parallel-1.C18
-rw-r--r--libgomp/testsuite/libgomp.c++/cancel-parallel-2.C57
-rw-r--r--libgomp/testsuite/libgomp.c++/cancel-parallel-3.C50
-rw-r--r--libgomp/testsuite/libgomp.c++/cancel-sections-1.C43
-rw-r--r--libgomp/testsuite/libgomp.c++/cancel-taskgroup-1.C4
-rw-r--r--libgomp/testsuite/libgomp.c++/cancel-taskgroup-2.C4
-rw-r--r--libgomp/testsuite/libgomp.c++/cancel-taskgroup-3.C58
-rw-r--r--libgomp/testsuite/libgomp.c++/cancel-test.h47
-rw-r--r--libgomp/testsuite/libgomp.c++/for-10.C44
-rw-r--r--libgomp/testsuite/libgomp.c++/for-11.C108
-rw-r--r--libgomp/testsuite/libgomp.c++/for-9.C33
-rw-r--r--libgomp/testsuite/libgomp.c++/simd-1.C79
-rw-r--r--libgomp/testsuite/libgomp.c++/simd-2.C36
-rw-r--r--libgomp/testsuite/libgomp.c++/simd-3.C131
-rw-r--r--libgomp/testsuite/libgomp.c++/simd-4.C45
-rw-r--r--libgomp/testsuite/libgomp.c++/simd-5.C47
-rw-r--r--libgomp/testsuite/libgomp.c++/simd-6.C70
-rw-r--r--libgomp/testsuite/libgomp.c++/simd-7.C72
-rw-r--r--libgomp/testsuite/libgomp.c++/simd-8.C47
-rw-r--r--libgomp/testsuite/libgomp.c++/target-1.C1
-rw-r--r--libgomp/testsuite/libgomp.c++/target-2-aux.cc5
-rw-r--r--libgomp/testsuite/libgomp.c++/target-2.C58
-rw-r--r--libgomp/testsuite/libgomp.c++/target-3.C1
-rw-r--r--libgomp/testsuite/libgomp.c++/taskgroup-1.C1
-rw-r--r--libgomp/testsuite/libgomp.c++/udr-1.C82
-rw-r--r--libgomp/testsuite/libgomp.c++/udr-2.C88
-rw-r--r--libgomp/testsuite/libgomp.c++/udr-3.C149
-rw-r--r--libgomp/testsuite/libgomp.c++/udr-4.C32
-rw-r--r--libgomp/testsuite/libgomp.c++/udr-5.C49
-rw-r--r--libgomp/testsuite/libgomp.c++/udr-6.C68
-rw-r--r--libgomp/testsuite/libgomp.c++/udr-7.C72
-rw-r--r--libgomp/testsuite/libgomp.c++/udr-8.C39
-rw-r--r--libgomp/testsuite/libgomp.c++/udr-9.C3
-rw-r--r--libgomp/testsuite/libgomp.c/affinity-1.c1146
-rw-r--r--libgomp/testsuite/libgomp.c/atomic-14.c4
-rw-r--r--libgomp/testsuite/libgomp.c/atomic-15.c99
-rw-r--r--libgomp/testsuite/libgomp.c/atomic-16.c58
-rw-r--r--libgomp/testsuite/libgomp.c/atomic-17.c99
-rw-r--r--libgomp/testsuite/libgomp.c/c.exp3
-rw-r--r--libgomp/testsuite/libgomp.c/cancel-for-1.c22
-rw-r--r--libgomp/testsuite/libgomp.c/cancel-for-2.c95
-rw-r--r--libgomp/testsuite/libgomp.c/cancel-parallel-1.c17
-rw-r--r--libgomp/testsuite/libgomp.c/cancel-parallel-2.c53
-rw-r--r--libgomp/testsuite/libgomp.c/cancel-parallel-3.c39
-rw-r--r--libgomp/testsuite/libgomp.c/cancel-sections-1.c38
-rw-r--r--libgomp/testsuite/libgomp.c/cancel-taskgroup-1.c70
-rw-r--r--libgomp/testsuite/libgomp.c/cancel-taskgroup-2.c37
-rw-r--r--libgomp/testsuite/libgomp.c/depend-1.c215
-rw-r--r--libgomp/testsuite/libgomp.c/depend-2.c71
-rw-r--r--libgomp/testsuite/libgomp.c/depend-3.c51
-rw-r--r--libgomp/testsuite/libgomp.c/depend-4.c56
-rw-r--r--libgomp/testsuite/libgomp.c/for-1.c35
-rw-r--r--libgomp/testsuite/libgomp.c/for-1.h25
-rw-r--r--libgomp/testsuite/libgomp.c/for-2.c46
-rw-r--r--libgomp/testsuite/libgomp.c/for-2.h269
-rw-r--r--libgomp/testsuite/libgomp.c/for-3.c110
-rw-r--r--libgomp/testsuite/libgomp.c/lib-1.c2
-rw-r--r--libgomp/testsuite/libgomp.c/pr58392.c58
-rw-r--r--libgomp/testsuite/libgomp.c/simd-1.c57
-rw-r--r--libgomp/testsuite/libgomp.c/simd-2.c36
-rw-r--r--libgomp/testsuite/libgomp.c/simd-3.c131
-rw-r--r--libgomp/testsuite/libgomp.c/simd-4.c42
-rw-r--r--libgomp/testsuite/libgomp.c/simd-5.c44
-rw-r--r--libgomp/testsuite/libgomp.c/simd-6.c44
-rw-r--r--libgomp/testsuite/libgomp.c/target-1.c90
-rw-r--r--libgomp/testsuite/libgomp.c/target-2.c88
-rw-r--r--libgomp/testsuite/libgomp.c/target-3.c17
-rw-r--r--libgomp/testsuite/libgomp.c/target-4.c14
-rw-r--r--libgomp/testsuite/libgomp.c/target-5.c83
-rw-r--r--libgomp/testsuite/libgomp.c/target-6.c68
-rw-r--r--libgomp/testsuite/libgomp.c/target-7.c111
-rw-r--r--libgomp/testsuite/libgomp.c/taskgroup-1.c83
-rw-r--r--libgomp/testsuite/libgomp.c/thread-limit-1.c41
-rw-r--r--libgomp/testsuite/libgomp.c/thread-limit-2.c57
-rw-r--r--libgomp/testsuite/libgomp.c/thread-limit-3.c12
-rw-r--r--libgomp/testsuite/libgomp.c/udr-1.c81
-rw-r--r--libgomp/testsuite/libgomp.c/udr-2.c27
-rw-r--r--libgomp/testsuite/libgomp.c/udr-3.c32
-rw-r--r--libgomp/testsuite/libgomp.fortran/fortran.exp3
-rw-r--r--libgomp/testsuite/libgomp.fortran/lib1.f901
-rw-r--r--libgomp/testsuite/libgomp.fortran/lib2.f1
-rw-r--r--libgomp/testsuite/libgomp.fortran/lib3.f1
-rw-r--r--libgomp/testsuite/libgomp.fortran/openmp_version-1.f9
-rw-r--r--libgomp/testsuite/libgomp.fortran/openmp_version-2.f909
-rw-r--r--libgomp/testsuite/libgomp.graphite/force-parallel-1.c2
-rw-r--r--libgomp/testsuite/libgomp.graphite/force-parallel-2.c2
-rw-r--r--libgomp/testsuite/libgomp.graphite/force-parallel-3.c4
-rw-r--r--libgomp/testsuite/libgomp.graphite/force-parallel-4.c4
-rw-r--r--libgomp/testsuite/libgomp.graphite/force-parallel-5.c4
-rw-r--r--libgomp/testsuite/libgomp.graphite/force-parallel-6.c2
-rw-r--r--libgomp/testsuite/libgomp.graphite/force-parallel-7.c2
-rw-r--r--libgomp/testsuite/libgomp.graphite/force-parallel-8.c4
-rw-r--r--libgomp/testsuite/libgomp.graphite/force-parallel-9.c4
-rw-r--r--libgomp/testsuite/libgomp.graphite/graphite.exp3
-rw-r--r--libgomp/work.c36
-rw-r--r--libiberty/ChangeLog46
-rw-r--r--libiberty/concat.c16
-rwxr-xr-xlibiberty/configure6
-rw-r--r--libiberty/configure.ac6
-rw-r--r--libiberty/cp-demangle.c133
-rw-r--r--libiberty/testsuite/demangle-expected6
-rw-r--r--libiberty/testsuite/test-demangle.c3
-rw-r--r--libiberty/testsuite/test-expandargv.c3
-rw-r--r--libitm/ChangeLog4
-rw-r--r--libitm/configure35
-rw-r--r--libjava/ChangeLog4
-rw-r--r--libjava/classpath/ChangeLog4
-rwxr-xr-xlibjava/classpath/configure24
-rwxr-xr-xlibjava/configure18
-rw-r--r--libjava/libltdl/ChangeLog6
-rw-r--r--libjava/libltdl/acinclude.m412
-rwxr-xr-xlibjava/libltdl/configure32
-rw-r--r--libmudflap/ChangeLog2054
-rw-r--r--libmudflap/Makefile.am97
-rw-r--r--libmudflap/Makefile.in855
-rw-r--r--libmudflap/acinclude.m412
-rw-r--r--libmudflap/aclocal.m41002
-rw-r--r--libmudflap/config.h.in308
-rwxr-xr-xlibmudflap/configure14047
-rw-r--r--libmudflap/configure.ac270
-rw-r--r--libmudflap/mf-heuristics.c169
-rw-r--r--libmudflap/mf-hooks1.c555
-rw-r--r--libmudflap/mf-hooks2.c2198
-rw-r--r--libmudflap/mf-hooks3.c284
-rw-r--r--libmudflap/mf-impl.h419
-rw-r--r--libmudflap/mf-runtime.c2886
-rw-r--r--libmudflap/mf-runtime.h244
-rw-r--r--libmudflap/testsuite/Makefile.am11
-rw-r--r--libmudflap/testsuite/Makefile.in426
-rw-r--r--libmudflap/testsuite/config/default.exp3
-rw-r--r--libmudflap/testsuite/lib/libmudflap.exp311
-rw-r--r--libmudflap/testsuite/lib/mfdg.exp365
-rw-r--r--libmudflap/testsuite/libmudflap.c++/c++frags.exp22
-rw-r--r--libmudflap/testsuite/libmudflap.c++/ctors-1.cxx20
-rw-r--r--libmudflap/testsuite/libmudflap.c++/ctors-2.cxx1
-rw-r--r--libmudflap/testsuite/libmudflap.c++/ctors.exp48
-rw-r--r--libmudflap/testsuite/libmudflap.c++/error1-frag.cxx5
-rw-r--r--libmudflap/testsuite/libmudflap.c++/error2-frag.cxx10
-rw-r--r--libmudflap/testsuite/libmudflap.c++/fail24-frag.cxx16
-rw-r--r--libmudflap/testsuite/libmudflap.c++/pass27-frag.cxx12
-rw-r--r--libmudflap/testsuite/libmudflap.c++/pass28-frag.cxx20
-rw-r--r--libmudflap/testsuite/libmudflap.c++/pass31-frag.cxx12
-rw-r--r--libmudflap/testsuite/libmudflap.c++/pass41-frag.cxx13
-rw-r--r--libmudflap/testsuite/libmudflap.c++/pass55-frag.cxx7
-rw-r--r--libmudflap/testsuite/libmudflap.c++/pass57-frag.cxx28
-rw-r--r--libmudflap/testsuite/libmudflap.c++/pass58-frag.cxx12
-rw-r--r--libmudflap/testsuite/libmudflap.c++/pass60-frag.cxx13
-rw-r--r--libmudflap/testsuite/libmudflap.c++/pass61-frag.cxx20
-rw-r--r--libmudflap/testsuite/libmudflap.c++/pass66-frag.cxx17
-rw-r--r--libmudflap/testsuite/libmudflap.c/cfrags.exp21
-rw-r--r--libmudflap/testsuite/libmudflap.c/externs-1.c16
-rw-r--r--libmudflap/testsuite/libmudflap.c/externs-2.c2
-rw-r--r--libmudflap/testsuite/libmudflap.c/externs.exp43
-rw-r--r--libmudflap/testsuite/libmudflap.c/fail1-frag.c13
-rw-r--r--libmudflap/testsuite/libmudflap.c/fail10-frag.c16
-rw-r--r--libmudflap/testsuite/libmudflap.c/fail11-frag.c20
-rw-r--r--libmudflap/testsuite/libmudflap.c/fail12-frag.c20
-rw-r--r--libmudflap/testsuite/libmudflap.c/fail13-frag.c26
-rw-r--r--libmudflap/testsuite/libmudflap.c/fail14-frag.c29
-rw-r--r--libmudflap/testsuite/libmudflap.c/fail15-frag.c27
-rw-r--r--libmudflap/testsuite/libmudflap.c/fail16-frag.c27
-rw-r--r--libmudflap/testsuite/libmudflap.c/fail17-frag.c18
-rw-r--r--libmudflap/testsuite/libmudflap.c/fail18-frag.c16
-rw-r--r--libmudflap/testsuite/libmudflap.c/fail19-frag.c18
-rw-r--r--libmudflap/testsuite/libmudflap.c/fail2-frag.c13
-rw-r--r--libmudflap/testsuite/libmudflap.c/fail20-frag.c13
-rw-r--r--libmudflap/testsuite/libmudflap.c/fail21-frag.c18
-rw-r--r--libmudflap/testsuite/libmudflap.c/fail22-frag.c17
-rw-r--r--libmudflap/testsuite/libmudflap.c/fail23-frag.c16
-rw-r--r--libmudflap/testsuite/libmudflap.c/fail25-frag.c18
-rw-r--r--libmudflap/testsuite/libmudflap.c/fail26-frag.c24
-rw-r--r--libmudflap/testsuite/libmudflap.c/fail27-frag.c24
-rw-r--r--libmudflap/testsuite/libmudflap.c/fail28-frag.c18
-rw-r--r--libmudflap/testsuite/libmudflap.c/fail29-frag.c17
-rw-r--r--libmudflap/testsuite/libmudflap.c/fail3-frag.c13
-rw-r--r--libmudflap/testsuite/libmudflap.c/fail30-frag.c18
-rw-r--r--libmudflap/testsuite/libmudflap.c/fail31-frag.c24
-rw-r--r--libmudflap/testsuite/libmudflap.c/fail32-frag.c16
-rw-r--r--libmudflap/testsuite/libmudflap.c/fail33-frag.c25
-rw-r--r--libmudflap/testsuite/libmudflap.c/fail34-frag.c22
-rw-r--r--libmudflap/testsuite/libmudflap.c/fail35-frag.c23
-rw-r--r--libmudflap/testsuite/libmudflap.c/fail36-frag.c23
-rw-r--r--libmudflap/testsuite/libmudflap.c/fail37-frag.c26
-rw-r--r--libmudflap/testsuite/libmudflap.c/fail38-frag.c29
-rw-r--r--libmudflap/testsuite/libmudflap.c/fail39-frag.c20
-rw-r--r--libmudflap/testsuite/libmudflap.c/fail4-frag.c13
-rw-r--r--libmudflap/testsuite/libmudflap.c/fail40-frag.c59
-rw-r--r--libmudflap/testsuite/libmudflap.c/fail5-frag.c14
-rw-r--r--libmudflap/testsuite/libmudflap.c/fail6-frag.c17
-rw-r--r--libmudflap/testsuite/libmudflap.c/fail68-frag.c27
-rw-r--r--libmudflap/testsuite/libmudflap.c/fail7-frag.c17
-rw-r--r--libmudflap/testsuite/libmudflap.c/fail8-frag.c19
-rw-r--r--libmudflap/testsuite/libmudflap.c/fail9-frag.c21
-rw-r--r--libmudflap/testsuite/libmudflap.c/heap-scalestress.c79
-rw-r--r--libmudflap/testsuite/libmudflap.c/hook-allocstuff.c16
-rw-r--r--libmudflap/testsuite/libmudflap.c/hook2-allocstuff.c9
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass-stratcliff.c326
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass1-frag.c9
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass10-frag.c12
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass11-frag.c15
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass12-frag.c15
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass13-frag.c17
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass14-frag.c20
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass15-frag.c23
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass16-frag.c22
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass17-frag.c9
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass18-frag.c27
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass19-frag.c11
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass2-frag.c9
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass20-frag.c13
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass21-frag.c15
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass22-frag.c23
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass23-frag.c29
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass24-frag.c18
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass25-frag.c15
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass26-frag.c52
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass29-frag.c15
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass3-frag.c9
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass30-frag.c12
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass32-frag.c18
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass33-frag.c17
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass34-frag.c18
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass35-frag.c14
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass36-frag.c15
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass38-frag.c9
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass4-frag.c9
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass42-frag.c17
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass43-frag.c11
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass44-frag.c14
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass45-frag.c31
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass46-frag.c18
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass47-frag.c12
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass48-frag.c11
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass49-frag.c35
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass5-frag.c11
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass50-frag.c29
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass51-frag.c44
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass52-frag.c36
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass53-frag.c41
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass54-frag.c34
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass56-frag.c14
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass6-frag.c14
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass62-frag.c13
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass63-frag.c6
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass64-frag.c38
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass67-frag.c14
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass7-frag.c13
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass8-frag.c16
-rw-r--r--libmudflap/testsuite/libmudflap.c/pass9-frag.c16
-rw-r--r--libmudflap/testsuite/libmudflap.cth/cthfrags.exp30
-rw-r--r--libmudflap/testsuite/libmudflap.cth/pass37-frag.c58
-rw-r--r--libmudflap/testsuite/libmudflap.cth/pass39-frag.c57
-rw-r--r--libmudflap/testsuite/libmudflap.cth/pass40-frag.c59
-rw-r--r--libmudflap/testsuite/libmudflap.cth/pass59-frag.c39
-rw-r--r--libmudflap/testsuite/mfconfig.exp.in4
-rw-r--r--libobjc/ChangeLog4
-rwxr-xr-xlibobjc/configure18
-rw-r--r--libquadmath/ChangeLog4
-rwxr-xr-xlibquadmath/configure32
-rw-r--r--libsanitizer/ChangeLog67
-rw-r--r--libsanitizer/MERGE2
-rw-r--r--libsanitizer/Makefile.am6
-rw-r--r--libsanitizer/Makefile.in8
-rw-r--r--libsanitizer/asan/Makefile.am21
-rw-r--r--libsanitizer/asan/Makefile.in37
-rw-r--r--libsanitizer/asan/asan_allocator.cc811
-rw-r--r--libsanitizer/asan/asan_allocator.h106
-rw-r--r--libsanitizer/asan/asan_allocator2.cc315
-rw-r--r--libsanitizer/asan/asan_dll_thunk.cc194
-rw-r--r--libsanitizer/asan/asan_fake_stack.cc283
-rw-r--r--libsanitizer/asan/asan_fake_stack.h167
-rw-r--r--libsanitizer/asan/asan_flags.h37
-rw-r--r--libsanitizer/asan/asan_globals.cc143
-rw-r--r--libsanitizer/asan/asan_intercepted_functions.h269
-rw-r--r--libsanitizer/asan/asan_interceptors.cc326
-rw-r--r--libsanitizer/asan/asan_interface_internal.h141
-rw-r--r--libsanitizer/asan/asan_internal.h50
-rw-r--r--libsanitizer/asan/asan_linux.cc36
-rw-r--r--libsanitizer/asan/asan_mac.cc76
-rw-r--r--libsanitizer/asan/asan_mac.h10
-rw-r--r--libsanitizer/asan/asan_malloc_linux.cc9
-rw-r--r--libsanitizer/asan/asan_malloc_mac.cc20
-rw-r--r--libsanitizer/asan/asan_malloc_win.cc15
-rw-r--r--libsanitizer/asan/asan_mapping.h36
-rw-r--r--libsanitizer/asan/asan_new_delete.cc41
-rw-r--r--libsanitizer/asan/asan_poisoning.cc75
-rw-r--r--libsanitizer/asan/asan_poisoning.h57
-rw-r--r--libsanitizer/asan/asan_posix.cc19
-rw-r--r--libsanitizer/asan/asan_preinit.cc6
-rw-r--r--libsanitizer/asan/asan_report.cc308
-rw-r--r--libsanitizer/asan/asan_report.h2
-rw-r--r--libsanitizer/asan/asan_rtl.cc187
-rw-r--r--libsanitizer/asan/asan_stack.cc9
-rw-r--r--libsanitizer/asan/asan_stack.h43
-rw-r--r--libsanitizer/asan/asan_stats.cc97
-rw-r--r--libsanitizer/asan/asan_stats.h13
-rw-r--r--libsanitizer/asan/asan_thread.cc245
-rw-r--r--libsanitizer/asan/asan_thread.h143
-rw-r--r--libsanitizer/asan/asan_thread_registry.cc196
-rw-r--r--libsanitizer/asan/asan_thread_registry.h83
-rw-r--r--libsanitizer/asan/asan_win.cc36
-rw-r--r--libsanitizer/asan/libtool-version4
-rwxr-xr-xlibsanitizer/configure49
-rw-r--r--libsanitizer/configure.ac2
-rw-r--r--libsanitizer/include/sanitizer/common_interface_defs.h10
-rw-r--r--libsanitizer/include/sanitizer/dfsan_interface.h85
-rw-r--r--libsanitizer/include/sanitizer/linux_syscall_hooks.h3067
-rw-r--r--libsanitizer/include/sanitizer/lsan_interface.h50
-rw-r--r--libsanitizer/include/sanitizer/msan_interface.h160
-rw-r--r--libsanitizer/interception/interception.h99
-rw-r--r--libsanitizer/interception/interception_linux.cc8
-rw-r--r--libsanitizer/interception/interception_linux.h7
-rw-r--r--libsanitizer/lsan/Makefile.am60
-rw-r--r--libsanitizer/lsan/Makefile.in514
-rw-r--r--libsanitizer/lsan/libtool-version (renamed from libmudflap/libtool-version)0
-rw-r--r--libsanitizer/lsan/lsan.cc63
-rw-r--r--libsanitizer/lsan/lsan.h21
-rw-r--r--libsanitizer/lsan/lsan_allocator.cc191
-rw-r--r--libsanitizer/lsan/lsan_allocator.h37
-rw-r--r--libsanitizer/lsan/lsan_common.cc577
-rw-r--r--libsanitizer/lsan/lsan_common.h174
-rw-r--r--libsanitizer/lsan/lsan_common_linux.cc139
-rw-r--r--libsanitizer/lsan/lsan_interceptors.cc279
-rw-r--r--libsanitizer/lsan/lsan_thread.cc154
-rw-r--r--libsanitizer/lsan/lsan_thread.h51
-rwxr-xr-xlibsanitizer/merge.sh1
-rw-r--r--libsanitizer/sanitizer_common/Makefile.am36
-rw-r--r--libsanitizer/sanitizer_common/Makefile.in65
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_allocator.cc105
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_allocator.h323
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_allocator_internal.h62
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_atomic_clang.h21
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_atomic_msvc.h27
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_common.cc127
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_common.h195
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc1934
-rwxr-xr-xlibsanitizer/sanitizer_common/sanitizer_common_interceptors_ioctl.inc566
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_common_interceptors_scanf.inc4
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_common_libcdep.cc35
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_common_syscalls.inc2732
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_flags.cc35
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_flags.h35
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_internal_defs.h68
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_libc.cc11
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_libc.h33
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_linux.cc689
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_linux.h81
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cc351
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_mac.cc134
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_mutex.h2
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_placement_new.h2
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_platform.h44
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h94
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_platform_limits_linux.cc45
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cc863
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h789
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_posix.cc211
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_posix_libcdep.cc114
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_printf.cc175
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_procmaps.h54
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_quarantine.h4
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_report_decorator.h2
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_stackdepot.cc34
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_stackdepot.h26
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_stacktrace.cc18
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_stacktrace.h14
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_stoptheworld.h66
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc450
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_suppressions.cc146
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_suppressions.h58
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_symbolizer.cc408
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_symbolizer.h82
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_symbolizer_itanium.cc40
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_symbolizer_linux.cc180
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_symbolizer_mac.cc29
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc595
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_symbolizer_win.cc17
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_syscall_generic.inc22
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_syscall_linux_x86_64.inc85
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_thread_registry.cc277
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_thread_registry.h142
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_win.cc184
-rw-r--r--libsanitizer/tsan/tsan_defs.h1
-rw-r--r--libsanitizer/tsan/tsan_fd.cc7
-rw-r--r--libsanitizer/tsan/tsan_flags.cc12
-rw-r--r--libsanitizer/tsan/tsan_flags.h10
-rw-r--r--libsanitizer/tsan/tsan_interceptors.cc578
-rw-r--r--libsanitizer/tsan/tsan_interface.cc56
-rw-r--r--libsanitizer/tsan/tsan_interface.h56
-rw-r--r--libsanitizer/tsan/tsan_interface_ann.cc99
-rw-r--r--libsanitizer/tsan/tsan_interface_ann.h4
-rw-r--r--libsanitizer/tsan/tsan_interface_atomic.cc84
-rw-r--r--libsanitizer/tsan/tsan_interface_inl.h16
-rw-r--r--libsanitizer/tsan/tsan_interface_java.cc41
-rw-r--r--libsanitizer/tsan/tsan_interface_java.h19
-rw-r--r--libsanitizer/tsan/tsan_mman.cc95
-rw-r--r--libsanitizer/tsan/tsan_mman.h2
-rw-r--r--libsanitizer/tsan/tsan_mutex.cc4
-rw-r--r--libsanitizer/tsan/tsan_mutexset.h2
-rw-r--r--libsanitizer/tsan/tsan_platform.h33
-rw-r--r--libsanitizer/tsan/tsan_platform_linux.cc179
-rw-r--r--libsanitizer/tsan/tsan_platform_mac.cc17
-rw-r--r--libsanitizer/tsan/tsan_platform_windows.cc17
-rw-r--r--libsanitizer/tsan/tsan_report.cc80
-rw-r--r--libsanitizer/tsan/tsan_report.h2
-rw-r--r--libsanitizer/tsan/tsan_rtl.cc324
-rw-r--r--libsanitizer/tsan/tsan_rtl.h196
-rw-r--r--libsanitizer/tsan/tsan_rtl_mutex.cc81
-rw-r--r--libsanitizer/tsan/tsan_rtl_report.cc223
-rw-r--r--libsanitizer/tsan/tsan_rtl_thread.cc460
-rw-r--r--libsanitizer/tsan/tsan_stat.cc99
-rw-r--r--libsanitizer/tsan/tsan_stat.h94
-rw-r--r--libsanitizer/tsan/tsan_suppressions.cc183
-rw-r--r--libsanitizer/tsan/tsan_suppressions.h23
-rw-r--r--libsanitizer/tsan/tsan_symbolize.cc66
-rw-r--r--libsanitizer/tsan/tsan_symbolize.h1
-rw-r--r--libsanitizer/tsan/tsan_symbolize_addr2line_linux.cc3
-rw-r--r--libsanitizer/tsan/tsan_sync.cc66
-rw-r--r--libsanitizer/tsan/tsan_sync.h2
-rw-r--r--libsanitizer/tsan/tsan_update_shadow_word_inl.h3
-rw-r--r--libsanitizer/tsan/tsan_vector.h5
-rw-r--r--libsanitizer/ubsan/ubsan_diag.cc5
-rw-r--r--libsanitizer/ubsan/ubsan_value.h4
-rw-r--r--libssp/ChangeLog4
-rwxr-xr-xlibssp/configure29
-rw-r--r--libstdc++-v3/ChangeLog1063
-rw-r--r--libstdc++-v3/acinclude.m42
-rw-r--r--libstdc++-v3/config/abi/post/x86_64-linux-gnu/x32/baseline_symbols.txt17
-rw-r--r--libstdc++-v3/config/abi/pre/gnu.ver3
-rwxr-xr-xlibstdc++-v3/configure53
-rw-r--r--libstdc++-v3/configure.ac6
-rw-r--r--libstdc++-v3/doc/xml/manual/status_cxx2011.xml36
-rw-r--r--libstdc++-v3/doc/xml/manual/status_cxx2014.xml20
-rw-r--r--libstdc++-v3/include/Makefile.am25
-rw-r--r--libstdc++-v3/include/Makefile.in26
-rw-r--r--libstdc++-v3/include/bits/allocator.h8
-rw-r--r--libstdc++-v3/include/bits/basic_string.h98
-rw-r--r--libstdc++-v3/include/bits/enable_special_members.h278
-rw-r--r--libstdc++-v3/include/bits/forward_list.h44
-rw-r--r--libstdc++-v3/include/bits/functexcept.h4
-rw-r--r--libstdc++-v3/include/bits/hashtable.h9
-rw-r--r--libstdc++-v3/include/bits/hashtable_policy.h42
-rw-r--r--libstdc++-v3/include/bits/parse_numbers.h4
-rw-r--r--libstdc++-v3/include/bits/predefined_ops.h304
-rw-r--r--libstdc++-v3/include/bits/regex.h787
-rw-r--r--libstdc++-v3/include/bits/regex.tcc709
-rw-r--r--libstdc++-v3/include/bits/regex_automaton.h208
-rw-r--r--libstdc++-v3/include/bits/regex_automaton.tcc221
-rw-r--r--libstdc++-v3/include/bits/regex_compiler.h111
-rw-r--r--libstdc++-v3/include/bits/regex_compiler.tcc186
-rw-r--r--libstdc++-v3/include/bits/regex_error.h1
-rw-r--r--libstdc++-v3/include/bits/regex_executor.h326
-rw-r--r--libstdc++-v3/include/bits/regex_executor.tcc597
-rw-r--r--libstdc++-v3/include/bits/regex_scanner.tcc58
-rw-r--r--libstdc++-v3/include/bits/shared_ptr_base.h90
-rw-r--r--libstdc++-v3/include/bits/stl_algo.h3135
-rw-r--r--libstdc++-v3/include/bits/stl_algobase.h194
-rw-r--r--libstdc++-v3/include/bits/stl_bvector.h5
-rw-r--r--libstdc++-v3/include/bits/stl_deque.h120
-rw-r--r--libstdc++-v3/include/bits/stl_function.h349
-rw-r--r--libstdc++-v3/include/bits/stl_heap.h232
-rw-r--r--libstdc++-v3/include/bits/stl_uninitialized.h38
-rw-r--r--libstdc++-v3/include/bits/stl_vector.h5
-rw-r--r--libstdc++-v3/include/bits/unique_ptr.h2
-rw-r--r--libstdc++-v3/include/c_global/cmath5
-rw-r--r--libstdc++-v3/include/c_global/cstdio1
-rw-r--r--libstdc++-v3/include/debug/array9
-rw-r--r--libstdc++-v3/include/debug/deque22
-rw-r--r--libstdc++-v3/include/debug/formatter.h2
-rw-r--r--libstdc++-v3/include/debug/forward_list21
-rw-r--r--libstdc++-v3/include/debug/functions.h22
-rw-r--r--libstdc++-v3/include/debug/safe_iterator.h141
-rw-r--r--libstdc++-v3/include/debug/safe_iterator.tcc72
-rw-r--r--libstdc++-v3/include/debug/safe_local_iterator.h19
-rw-r--r--libstdc++-v3/include/debug/safe_local_iterator.tcc49
-rw-r--r--libstdc++-v3/include/debug/string18
-rw-r--r--libstdc++-v3/include/decimal/decimal21
-rw-r--r--libstdc++-v3/include/experimental/optional823
-rw-r--r--libstdc++-v3/include/ext/vstring.h14
-rw-r--r--libstdc++-v3/include/parallel/algo.h4
-rw-r--r--libstdc++-v3/include/parallel/algobase.h184
-rw-r--r--libstdc++-v3/include/profile/array9
-rw-r--r--libstdc++-v3/include/profile/deque20
-rw-r--r--libstdc++-v3/include/profile/iterator_tracker.h52
-rw-r--r--libstdc++-v3/include/std/array8
-rw-r--r--libstdc++-v3/include/std/bitset44
-rw-r--r--libstdc++-v3/include/std/chrono36
-rw-r--r--libstdc++-v3/include/std/complex34
-rw-r--r--libstdc++-v3/include/std/functional16
-rw-r--r--libstdc++-v3/include/std/mutex24
-rw-r--r--libstdc++-v3/include/std/tuple21
-rw-r--r--libstdc++-v3/include/std/type_traits96
-rw-r--r--libstdc++-v3/include/std/utility61
-rw-r--r--libstdc++-v3/include/std/vector2
-rw-r--r--libstdc++-v3/include/tr2/dynamic_bitset302
-rw-r--r--libstdc++-v3/include/tr2/dynamic_bitset.tcc286
-rw-r--r--libstdc++-v3/libsupc++/del_op.cc3
-rw-r--r--libstdc++-v3/libsupc++/del_opnt.cc18
-rw-r--r--libstdc++-v3/src/c++11/Makefile.am1
-rw-r--r--libstdc++-v3/src/c++11/Makefile.in4
-rw-r--r--libstdc++-v3/src/c++11/functexcept.cc23
-rw-r--r--libstdc++-v3/src/c++11/snprintf_lite.cc161
-rw-r--r--libstdc++-v3/testsuite/20_util/add_lvalue_reference/requirements/typedefs.cc30
-rw-r--r--libstdc++-v3/testsuite/20_util/add_rvalue_reference/requirements/typedefs.cc30
-rw-r--r--libstdc++-v3/testsuite/20_util/common_type/requirements/typedefs-2.cc85
-rw-r--r--libstdc++-v3/testsuite/20_util/common_type/requirements/typedefs-3.cc27
-rw-r--r--libstdc++-v3/testsuite/20_util/conditional/requirements/typedefs-2.cc33
-rw-r--r--libstdc++-v3/testsuite/20_util/decay/requirements/typedefs-2.cc35
-rw-r--r--libstdc++-v3/testsuite/20_util/decay/requirements/typedefs.cc24
-rw-r--r--libstdc++-v3/testsuite/20_util/declval/requirements/1_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/20_util/default_delete/48631_neg.cc1
-rw-r--r--libstdc++-v3/testsuite/20_util/default_delete/void_neg.cc30
-rw-r--r--libstdc++-v3/testsuite/20_util/duration/arithmetic/58850.cc42
-rw-r--r--libstdc++-v3/testsuite/20_util/enable_if/requirements/typedefs-2.cc29
-rw-r--r--libstdc++-v3/testsuite/20_util/enable_shared_from_this/members/assign.cc36
-rw-r--r--libstdc++-v3/testsuite/20_util/enable_shared_from_this/members/unique_ptr.cc62
-rw-r--r--libstdc++-v3/testsuite/20_util/exchange/1.cc6
-rw-r--r--libstdc++-v3/testsuite/20_util/function/58569.cc29
-rw-r--r--libstdc++-v3/testsuite/20_util/function/cons/57465.cc31
-rw-r--r--libstdc++-v3/testsuite/20_util/function_objects/comparisons_void.cc95
-rw-r--r--libstdc++-v3/testsuite/20_util/integer_sequence/intseq.cc27
-rw-r--r--libstdc++-v3/testsuite/20_util/integer_sequence/requirements/typedefs.cc62
-rw-r--r--libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs-1.cc41
-rw-r--r--libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs-3.cc35
-rw-r--r--libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs_neg.cc4
-rw-r--r--libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs-3.cc35
-rw-r--r--libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc4
-rw-r--r--libstdc++-v3/testsuite/20_util/remove_reference/requirements/typedefs.cc30
-rw-r--r--libstdc++-v3/testsuite/20_util/result_of/requirements/typedefs.cc32
-rw-r--r--libstdc++-v3/testsuite/20_util/shared_ptr/cons/43820_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/20_util/shared_ptr/cons/58659.cc68
-rw-r--r--libstdc++-v3/testsuite/20_util/shared_ptr/cons/58839.cc33
-rw-r--r--libstdc++-v3/testsuite/20_util/shared_ptr/cons/void_neg.cc29
-rw-r--r--libstdc++-v3/testsuite/20_util/shared_ptr/creation/58594.cc27
-rw-r--r--libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_copy/58982.cc41
-rw-r--r--libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_copy_n/58982.cc41
-rw-r--r--libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_fill/58982.cc41
-rw-r--r--libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_fill_n/58982.cc41
-rw-r--r--libstdc++-v3/testsuite/20_util/underlying_type/requirements/typedefs-3.cc32
-rw-r--r--libstdc++-v3/testsuite/20_util/unique_ptr/assign/48635_neg.cc4
-rw-r--r--libstdc++-v3/testsuite/23_containers/array/tuple_interface/get_debug_neg.cc6
-rw-r--r--libstdc++-v3/testsuite/23_containers/array/tuple_interface/get_neg.cc6
-rw-r--r--libstdc++-v3/testsuite/23_containers/array/tuple_interface/tuple_element_debug_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/array/tuple_interface/tuple_element_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/assign_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/constructor_1_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/constructor_2_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/insert_neg.cc3
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_set/debug/debug_functions.cc92
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_set/not_default_constructible_hash_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/debug/debug_functions.cc75
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/assign_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_1_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_2_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/insert_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/25_algorithms/adjacent_find/vectorbool.cc44
-rw-r--r--libstdc++-v3/testsuite/25_algorithms/copy/58982.cc42
-rw-r--r--libstdc++-v3/testsuite/25_algorithms/copy_n/58982.cc42
-rw-r--r--libstdc++-v3/testsuite/25_algorithms/find/vectorbool.cc39
-rw-r--r--libstdc++-v3/testsuite/25_algorithms/find_end/vectorbool.cc50
-rw-r--r--libstdc++-v3/testsuite/25_algorithms/find_first_of/vectorbool.cc50
-rw-r--r--libstdc++-v3/testsuite/25_algorithms/find_if/vectorbool.cc39
-rw-r--r--libstdc++-v3/testsuite/25_algorithms/find_if_not/vectorbool.cc40
-rw-r--r--libstdc++-v3/testsuite/25_algorithms/heap/vectorbool.cc146
-rw-r--r--libstdc++-v3/testsuite/25_algorithms/is_permutation/vectorbool.cc50
-rw-r--r--libstdc++-v3/testsuite/25_algorithms/nth_element/58800.cc52
-rw-r--r--libstdc++-v3/testsuite/25_algorithms/nth_element/random_test.cc63
-rw-r--r--libstdc++-v3/testsuite/25_algorithms/partial_sort/random_test.cc62
-rw-r--r--libstdc++-v3/testsuite/25_algorithms/partial_sort_copy/random_test.cc67
-rw-r--r--libstdc++-v3/testsuite/25_algorithms/sort/random_test.cc51
-rw-r--r--libstdc++-v3/testsuite/26_numerics/complex/literals/types.cc46
-rw-r--r--libstdc++-v3/testsuite/26_numerics/complex/literals/values.cc48
-rw-r--r--libstdc++-v3/testsuite/26_numerics/valarray/subset_assignment.cc2
-rw-r--r--libstdc++-v3/testsuite/27_io/ios_base/types/fmtflags/bitmask_operators.cc2
-rw-r--r--libstdc++-v3/testsuite/27_io/ios_base/types/iostate/bitmask_operators.cc2
-rw-r--r--libstdc++-v3/testsuite/27_io/ios_base/types/openmode/bitmask_operators.cc2
-rw-r--r--libstdc++-v3/testsuite/28_regex/algorithms/regex_match/awk/cstring_01.cc14
-rw-r--r--libstdc++-v3/testsuite/28_regex/algorithms/regex_match/basic/empty_range.cc6
-rw-r--r--libstdc++-v3/testsuite/28_regex/algorithms/regex_match/basic/string_01.cc6
-rw-r--r--libstdc++-v3/testsuite/28_regex/algorithms/regex_match/basic/string_range_00_03.cc6
-rw-r--r--libstdc++-v3/testsuite/28_regex/algorithms/regex_match/basic/string_range_01_03.cc6
-rw-r--r--libstdc++-v3/testsuite/28_regex/algorithms/regex_match/basic/string_range_02_03.cc6
-rw-r--r--libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/char/53622.cc70
-rw-r--r--libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/char/57173.cc64
-rw-r--r--libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/char/58576.cc100
-rw-r--r--libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/char/anymatcher.cc4
-rw-r--r--libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/char/backref.cc2
-rw-r--r--libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/char/empty_range.cc10
-rw-r--r--libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/char/emptygroup.cc6
-rw-r--r--libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/char/hex.cc4
-rw-r--r--libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/char/quoted_char.cc20
-rw-r--r--libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/char/ungreedy.cc50
-rw-r--r--libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/wchar_t/anymatcher.cc4
-rw-r--r--libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/wchar_t/cjk_match.cc50
-rw-r--r--libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/wchar_t/hex.cc4
-rw-r--r--libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/53622.cc67
-rw-r--r--libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/57173.cc61
-rw-r--r--libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/cstring_bracket_01.cc35
-rw-r--r--libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/cstring_plus.cc12
-rw-r--r--libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/cstring_questionmark.cc12
-rw-r--r--libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/cstring_range.cc42
-rw-r--r--libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/string_any.cc6
-rw-r--r--libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/string_dispatch_01.cc69
-rw-r--r--libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/string_range_00_03.cc5
-rw-r--r--libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/string_range_01_03.cc6
-rw-r--r--libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/string_range_02_03.cc6
-rw-r--r--libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/wstring_locale.cc6
-rw-r--r--libstdc++-v3/testsuite/28_regex/algorithms/regex_replace/char/basic_replace.cc51
-rw-r--r--libstdc++-v3/testsuite/28_regex/algorithms/regex_search/basic/string_01.cc6
-rw-r--r--libstdc++-v3/testsuite/28_regex/algorithms/regex_search/ecma/assertion.cc30
-rw-r--r--libstdc++-v3/testsuite/28_regex/algorithms/regex_search/ecma/flags.cc48
-rw-r--r--libstdc++-v3/testsuite/28_regex/algorithms/regex_search/ecma/greedy.cc28
-rw-r--r--libstdc++-v3/testsuite/28_regex/algorithms/regex_search/ecma/string_01.cc6
-rw-r--r--libstdc++-v3/testsuite/28_regex/basic_regex/assign/char/cstring.cc2
-rw-r--r--libstdc++-v3/testsuite/28_regex/basic_regex/assign/char/cstring_op.cc2
-rw-r--r--libstdc++-v3/testsuite/28_regex/basic_regex/assign/char/moveable.cc12
-rw-r--r--libstdc++-v3/testsuite/28_regex/basic_regex/assign/char/pstring.cc2
-rw-r--r--libstdc++-v3/testsuite/28_regex/basic_regex/assign/char/range.cc2
-rw-r--r--libstdc++-v3/testsuite/28_regex/basic_regex/assign/char/string.cc2
-rw-r--r--libstdc++-v3/testsuite/28_regex/basic_regex/assign/char/string_op.cc2
-rw-r--r--libstdc++-v3/testsuite/28_regex/basic_regex/assign/wchar_t/cstring.cc2
-rw-r--r--libstdc++-v3/testsuite/28_regex/basic_regex/assign/wchar_t/cstring_op.cc2
-rw-r--r--libstdc++-v3/testsuite/28_regex/basic_regex/assign/wchar_t/pstring.cc2
-rw-r--r--libstdc++-v3/testsuite/28_regex/basic_regex/assign/wchar_t/range.cc2
-rw-r--r--libstdc++-v3/testsuite/28_regex/basic_regex/assign/wchar_t/string.cc2
-rw-r--r--libstdc++-v3/testsuite/28_regex/basic_regex/assign/wchar_t/string_op.cc2
-rw-r--r--libstdc++-v3/testsuite/28_regex/basic_regex/ctors/47724.cc2
-rw-r--r--libstdc++-v3/testsuite/28_regex/basic_regex/ctors/basic/pstring_char.cc2
-rw-r--r--libstdc++-v3/testsuite/28_regex/basic_regex/ctors/basic/pstring_wchar_t.cc2
-rw-r--r--libstdc++-v3/testsuite/28_regex/basic_regex/ctors/basic/raw_string.cc3
-rw-r--r--libstdc++-v3/testsuite/28_regex/basic_regex/ctors/char/cstring.cc2
-rw-r--r--libstdc++-v3/testsuite/28_regex/basic_regex/ctors/char/default.cc2
-rw-r--r--libstdc++-v3/testsuite/28_regex/basic_regex/ctors/char/range.cc2
-rw-r--r--libstdc++-v3/testsuite/28_regex/basic_regex/ctors/copy_char.cc2
-rw-r--r--libstdc++-v3/testsuite/28_regex/basic_regex/ctors/move_char.cc2
-rw-r--r--libstdc++-v3/testsuite/28_regex/basic_regex/ctors/string_char.cc2
-rw-r--r--libstdc++-v3/testsuite/28_regex/basic_regex/ctors/string_wchar_t.cc2
-rw-r--r--libstdc++-v3/testsuite/28_regex/basic_regex/ctors/wchar_t/cstring.cc2
-rw-r--r--libstdc++-v3/testsuite/28_regex/basic_regex/ctors/wchar_t/default.cc2
-rw-r--r--libstdc++-v3/testsuite/28_regex/basic_regex/ctors/wchar_t/range.cc2
-rw-r--r--libstdc++-v3/testsuite/28_regex/match_results/format.cc53
-rw-r--r--libstdc++-v3/testsuite/28_regex/traits/char/ctor.cc2
-rw-r--r--libstdc++-v3/testsuite/28_regex/traits/char/lookup_collatename.cc9
-rw-r--r--libstdc++-v3/testsuite/28_regex/traits/char/translate_nocase.cc2
-rw-r--r--libstdc++-v3/testsuite/28_regex/traits/char/value.cc2
-rw-r--r--libstdc++-v3/testsuite/28_regex/traits/wchar_t/ctor.cc2
-rw-r--r--libstdc++-v3/testsuite/28_regex/traits/wchar_t/lookup_collatename.cc10
-rw-r--r--libstdc++-v3/testsuite/28_regex/traits/wchar_t/translate_nocase.cc2
-rw-r--r--libstdc++-v3/testsuite/28_regex/traits/wchar_t/value.cc2
-rw-r--r--libstdc++-v3/testsuite/29_atomics/atomic/cons/49445.cc1
-rw-r--r--libstdc++-v3/testsuite/29_atomics/atomic/operators/pointer_partial_void.cc8
-rw-r--r--libstdc++-v3/testsuite/29_atomics/atomic_integral/operators/bitwise.cc2
-rw-r--r--libstdc++-v3/testsuite/29_atomics/atomic_integral/operators/decrement.cc2
-rw-r--r--libstdc++-v3/testsuite/29_atomics/atomic_integral/operators/increment.cc2
-rw-r--r--libstdc++-v3/testsuite/decimal/pr58815.cc35
-rw-r--r--libstdc++-v3/testsuite/experimental/optional/assignment/1.cc195
-rw-r--r--libstdc++-v3/testsuite/experimental/optional/assignment/2.cc193
-rw-r--r--libstdc++-v3/testsuite/experimental/optional/assignment/3.cc158
-rw-r--r--libstdc++-v3/testsuite/experimental/optional/assignment/4.cc158
-rw-r--r--libstdc++-v3/testsuite/experimental/optional/assignment/5.cc66
-rw-r--r--libstdc++-v3/testsuite/experimental/optional/assignment/6.cc83
-rw-r--r--libstdc++-v3/testsuite/experimental/optional/cons/copy.cc126
-rw-r--r--libstdc++-v3/testsuite/experimental/optional/cons/default.cc60
-rw-r--r--libstdc++-v3/testsuite/experimental/optional/cons/move.cc126
-rw-r--r--libstdc++-v3/testsuite/experimental/optional/cons/value.cc239
-rw-r--r--libstdc++-v3/testsuite/experimental/optional/constexpr/cons/default.cc42
-rw-r--r--libstdc++-v3/testsuite/experimental/optional/constexpr/cons/value.cc69
-rw-r--r--libstdc++-v3/testsuite/experimental/optional/constexpr/in_place.cc43
-rw-r--r--libstdc++-v3/testsuite/experimental/optional/constexpr/make_optional.cc33
-rw-r--r--libstdc++-v3/testsuite/experimental/optional/constexpr/nullopt.cc46
-rw-r--r--libstdc++-v3/testsuite/experimental/optional/constexpr/observers/1.cc33
-rw-r--r--libstdc++-v3/testsuite/experimental/optional/constexpr/observers/2.cc37
-rw-r--r--libstdc++-v3/testsuite/experimental/optional/constexpr/observers/3.cc37
-rw-r--r--libstdc++-v3/testsuite/experimental/optional/constexpr/observers/4.cc35
-rw-r--r--libstdc++-v3/testsuite/experimental/optional/constexpr/observers/5.cc40
-rw-r--r--libstdc++-v3/testsuite/experimental/optional/constexpr/relops/1.cc99
-rw-r--r--libstdc++-v3/testsuite/experimental/optional/constexpr/relops/2.cc111
-rw-r--r--libstdc++-v3/testsuite/experimental/optional/constexpr/relops/3.cc89
-rw-r--r--libstdc++-v3/testsuite/experimental/optional/constexpr/relops/4.cc101
-rw-r--r--libstdc++-v3/testsuite/experimental/optional/constexpr/relops/5.cc80
-rw-r--r--libstdc++-v3/testsuite/experimental/optional/constexpr/relops/6.cc88
-rw-r--r--libstdc++-v3/testsuite/experimental/optional/in_place.cc66
-rw-r--r--libstdc++-v3/testsuite/experimental/optional/make_optional.cc31
-rw-r--r--libstdc++-v3/testsuite/experimental/optional/nullopt.cc46
-rw-r--r--libstdc++-v3/testsuite/experimental/optional/observers/1.cc33
-rw-r--r--libstdc++-v3/testsuite/experimental/optional/observers/2.cc35
-rw-r--r--libstdc++-v3/testsuite/experimental/optional/observers/3.cc58
-rw-r--r--libstdc++-v3/testsuite/experimental/optional/observers/4.cc35
-rw-r--r--libstdc++-v3/testsuite/experimental/optional/observers/5.cc40
-rw-r--r--libstdc++-v3/testsuite/experimental/optional/relops/1.cc89
-rw-r--r--libstdc++-v3/testsuite/experimental/optional/relops/2.cc101
-rw-r--r--libstdc++-v3/testsuite/experimental/optional/relops/3.cc79
-rw-r--r--libstdc++-v3/testsuite/experimental/optional/relops/4.cc91
-rw-r--r--libstdc++-v3/testsuite/experimental/optional/relops/5.cc70
-rw-r--r--libstdc++-v3/testsuite/experimental/optional/relops/6.cc78
-rw-r--r--libstdc++-v3/testsuite/experimental/optional/requirements.cc256
-rw-r--r--libstdc++-v3/testsuite/experimental/optional/swap/1.cc95
-rw-r--r--libstdc++-v3/testsuite/lib/libstdc++.exp2
-rw-r--r--libstdc++-v3/testsuite/libstdc++-dg/conformance.exp1
-rw-r--r--libstdc++-v3/testsuite/performance/25_algorithms/sort.cc65
-rw-r--r--libstdc++-v3/testsuite/performance/25_algorithms/sort_heap.cc73
-rw-r--r--libstdc++-v3/testsuite/performance/25_algorithms/stable_sort.cc65
-rw-r--r--libstdc++-v3/testsuite/performance/27_io/ifstream_extract_int.cc2
-rw-r--r--libstdc++-v3/testsuite/performance/27_io/ofstream_insert_int.cc2
-rw-r--r--libstdc++-v3/testsuite/performance/28_regex/split.cc45
-rw-r--r--libstdc++-v3/testsuite/performance/28_regex/split.h91
-rw-r--r--libstdc++-v3/testsuite/performance/28_regex/split_bfs.cc46
-rw-r--r--libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/char/cstring.cc2
-rw-r--r--libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/char/cstring_op.cc2
-rw-r--r--libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/char/pstring.cc2
-rw-r--r--libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/char/range.cc2
-rw-r--r--libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/char/string.cc2
-rw-r--r--libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/char/string_op.cc2
-rw-r--r--libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/wchar_t/cstring.cc2
-rw-r--r--libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/wchar_t/cstring_op.cc2
-rw-r--r--libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/wchar_t/pstring.cc2
-rw-r--r--libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/wchar_t/range.cc2
-rw-r--r--libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/wchar_t/string.cc2
-rw-r--r--libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/wchar_t/string_op.cc2
-rw-r--r--libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/ctors/char/cstring.cc2
-rw-r--r--libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/ctors/char/default.cc2
-rw-r--r--libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/ctors/char/pstring.cc2
-rw-r--r--libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/ctors/char/range.cc2
-rw-r--r--libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/ctors/char/string.cc2
-rw-r--r--libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/ctors/wchar_t/cstring.cc2
-rw-r--r--libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/ctors/wchar_t/default.cc2
-rw-r--r--libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/ctors/wchar_t/pstring.cc2
-rw-r--r--libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/ctors/wchar_t/range.cc2
-rw-r--r--libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/ctors/wchar_t/string.cc2
-rw-r--r--libstdc++-v3/testsuite/tr1/7_regular_expressions/match_results/ctors/char/default.cc2
-rw-r--r--libstdc++-v3/testsuite/tr1/7_regular_expressions/regex_traits/char/ctor.cc2
-rw-r--r--libstdc++-v3/testsuite/tr1/7_regular_expressions/regex_traits/char/translate_nocase.cc2
-rw-r--r--libstdc++-v3/testsuite/tr1/7_regular_expressions/regex_traits/char/value.cc2
-rw-r--r--libstdc++-v3/testsuite/tr1/7_regular_expressions/regex_traits/wchar_t/ctor.cc2
-rw-r--r--libstdc++-v3/testsuite/tr1/7_regular_expressions/regex_traits/wchar_t/translate_nocase.cc2
-rw-r--r--libstdc++-v3/testsuite/tr1/7_regular_expressions/regex_traits/wchar_t/value.cc2
-rw-r--r--libstdc++-v3/testsuite/tr2/dynamic_bitset/pr58729.cc64
-rw-r--r--libstdc++-v3/testsuite/util/exception/safety.h22
-rw-r--r--libstdc++-v3/testsuite/util/testsuite_containergen.h97
-rw-r--r--libstdc++-v3/testsuite/util/testsuite_iterators.h4
-rw-r--r--libstdc++-v3/testsuite/util/testsuite_regex.h176
-rw-r--r--libtool.m412
-rw-r--r--libvtv/ChangeLog25
-rw-r--r--libvtv/Makefile.am17
-rw-r--r--libvtv/Makefile.in23
-rwxr-xr-xlibvtv/configure69
-rw-r--r--libvtv/configure.ac21
-rw-r--r--lto-plugin/ChangeLog8
-rwxr-xr-xlto-plugin/configure16
-rw-r--r--zlib/ChangeLog.gcj12
-rw-r--r--zlib/Makefile.am2
-rw-r--r--zlib/Makefile.in3
-rwxr-xr-xzlib/configure28
-rw-r--r--zlib/configure.ac6
5012 files changed, 332074 insertions, 103503 deletions
diff --git a/.dir-locals.el b/.dir-locals.el
new file mode 100644
index 00000000000..b748c8d085f
--- /dev/null
+++ b/.dir-locals.el
@@ -0,0 +1,24 @@
+;; Emacs settings.
+;; Copyright (C) 2012-2013 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 of the License, 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, see <http://www.gnu.org/licenses/>.
+
+(
+ (tcl-mode . ((tcl-indent-level . 4)
+ (tcl-continued-indent-level . 4)
+ (indent-tabs-mode . t)))
+ (nil . ((bug-reference-url-format . "http://gcc.gnu.org/PR%s")))
+ (c-mode . ((c-file-style . "GNU")
+ (indent-tabs-mode . t)))
+)
diff --git a/ChangeLog b/ChangeLog
index b281021925b..97b67e53de4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,75 @@
+2013-11-07 Thomas Schwinge <thomas@codesourcery.com>
+
+ * Makefile.in: Regenerate.
+
+ * Makefile.tpl: Fix typo.
+ * Makefile.in: Regenerate partially.
+
+2013-11-04 Balaji V. Iyer <balaji.v.iyer@intel.com>
+
+ * configure.ac: Added libcilkrts to noconfig list when C++ is not
+ supported.
+ * configure: Regenerated.
+
+2013-11-01 Trevor Saunders <tsaunders@mozilla.com>
+
+* MAINTAINERS (Write After Approval): Add myself.
+
+2013-10-30 Jason Merrill <jason@redhat.com>
+
+ * Makefile.tpl (STAGE1_CONFIGURE_FLAGS): Pass
+ --disable-build-format-warnings.
+
+2013-10-29 Balaji V. Iyer <balaji.v.iyer@intel.com>
+
+ * Makefile.def: Add libcilkrts to target_modules. Make libcilkrts
+ depend on libstdc++ and libgcc.
+ * configure: Regenerate.
+ * configure.ac: Added libcilkrts to target binaries. Also, restrict
+ libcilkrts for POSIX and i*86, and x86_64 architectures.
+ * Makefile.in: Added libcilkrts related fields to support building it.
+
+2013-10-26 Jeff Law <law@redhat.com>
+
+ * Makefile.def (target_modules): Remove libmudflap
+ (languages): Remove check-target-libmudflap).
+ * Makefile.in: Rebuilt.
+ * Makefile.tpl (check-target-libmudflap-c++): Remove.
+ * configure.ac (target_libraries): Remove target-libmudflap.
+ Remove checks which disabled libmudflap on some systems.
+ * configure: Rebuilt.
+ * libmudflap: Directory removed.
+
+2013-10-21 Cong Hou <congh@google.com>
+
+ * MAINTAINERS (Write After Approval): Add myself.
+
+2013-10-16 Mike Stump <mikestump@comcast.net>
+
+ * .dir-locals.el: Add.
+
+2013-10-15 David Malcolm <dmalcolm@redhat.com>
+
+ * configure.ac: Add --enable-host-shared
+ * configure: Regenerate.
+
+2013-01-10 Joern Rennecke <joern.rennecke@embecosm.com>
+
+ Import from savannah.gnu.org:
+ * config.guess: Update to 2013-06-10 version.
+ * config.sub: Update to 2013-10-01 version.
+
+2013-10-01 Simon Cook <simon.cook@embecosm.com>
+
+ Changes to build configuration to allow big endian ARC ELF toolchain
+ * configure.ac: Also add target-libgloss to noconfigdirs for arceb-*-*.
+ * configure: Regenerate.
+
+2013-09-20 Alan Modra <amodra@gmail.com>
+
+ * libtool.m4 (_LT_ENABLE_LOCK <ld -m flags>): Remove non-canonical
+ ppc host match. Support little-endian powerpc linux hosts.
+
2013-09-19 Dodji Seketeli <dodji@redhat.com>
* MAINTAINERS (diagnostic messages): Add myself as diagnostics
@@ -340,7 +412,7 @@
* configure.ac: add --disable-libstdcxx configure option
and handle defaulted state only for VxWorks, ARM-wince-pe and AVR.
-2012-10-30 Ganesh Gopalasubramanian <Ganesh.Gopalasubramanian@amd.com>
+2012-10-30 Ganesh Gopalasubramanian <Ganesh.Gopalasubramanian@amd.com>
* MAINTAINERS (Write After Approval): Add myself.
@@ -780,7 +852,7 @@
* Makefile.def (install-strip-gcc): Depend on install-strip-lto-plugin.
* Makefile.in: Regenerate.
-2011-12-28 Oleg Endo <olegendo@gcc.gnu.org>
+2011-12-28 Oleg Endo <olegendo@gcc.gnu.org>
* MAINTAINERS (Write After Approval): Add myself.
@@ -881,7 +953,7 @@
* config.sub: Import these changes from the config project:
- 2011-10-08 Joern Rennecke <joern.rennecke@embecosm.com>
+ 2011-10-08 Joern Rennecke <joern.rennecke@embecosm.com>
Ben Elliston <bje@gnu.org>
* config.sub (epiphany): New.
diff --git a/ChangeLog.MELT b/ChangeLog.MELT
index 68b02f2493d..a796ec5718e 100644
--- a/ChangeLog.MELT
+++ b/ChangeLog.MELT
@@ -1,4 +1,9 @@
+2013-11-12 Basile Starynkevitch <basile@starynkevitch.net>
+
+ {{merge with trunk GCC 4.9 svn rev 204695; previous trunk merge
+ was 202773; very unstable...}}
+
2013-11-06 Basile Starynkevitch <basile@starynkevitch.net>
{{1.0.1 release}}
diff --git a/MAINTAINERS b/MAINTAINERS
index 4a369d7f5bb..25ae10e5489 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -239,7 +239,6 @@ tree-ssa Diego Novillo dnovillo@google.com
tree-ssa Andrew MacLeod amacleod@redhat.com
PRE Daniel Berlin dberlin@dberlin.org
code sinking Daniel Berlin dberlin@dberlin.org
-mudflap Frank Ch. Eigler fche@redhat.com
tree browser/unparser Sebastian Pop sebastian.pop@amd.com
scev, data dependence Daniel Berlin dberlin@dberlin.org
scev, data dependence Sebastian Pop sebastian.pop@amd.com
@@ -406,6 +405,7 @@ Fergus Henderson fjh@cs.mu.oz.au
Stuart Henderson shenders@gcc.gnu.org
Matthew Hiller hiller@redhat.com
Manfred Hollstein mh@suse.com
+Cong Hou congh@google.com
Falk Hueffner falk@debian.org
Andrew John Hughes gnu_andrew@member.fsf.org
Andy Hutchinson hutchinsonandy@aim.com
@@ -514,6 +514,7 @@ Matthew Sachs msachs@apple.com
Hariharan Sandanagobalane hariharan.gcc@gmail.com
Iain Sandoe iain@codesourcery.com
Duncan Sands baldrick@gcc.gnu.org
+Trevor Saunders tsaunders@mozilla.com
William Schmidt wschmidt@linux.vnet.ibm.com
Tilo Schwarz tilo@tilo-schwarz.de
Dodji Seketeli dodji@gcc.gnu.org
@@ -526,7 +527,7 @@ Johannes Singler singler@kit.edu
Franz Sirl franz.sirl-kernel@lauterbach.com
Jan Sjodin jan.sjodin@amd.com
Edward Smith-Rowland 3dw4rd@verizon.net
-Jayant Sonar jayant.sonar@kpitcummins.com
+Jayant Sonar rsonar.jayant@gmail.com
Michael Sokolov msokolov@ivan.Harhan.ORG
Richard Stallman rms@gnu.org
Basile Starynkevitch basile@starynkevitch.net
diff --git a/Makefile.def b/Makefile.def
index 3ba1a5b9a3a..32296d1160f 100644
--- a/Makefile.def
+++ b/Makefile.def
@@ -117,7 +117,6 @@ target_modules = { module= libstdc++-v3;
bootstrap=true;
lib_path=src/.libs;
raw_cxx=true; };
-target_modules = { module= libmudflap; lib_path=.libs; };
target_modules = { module= libsanitizer;
bootstrap=true;
lib_path=.libs;
@@ -126,6 +125,8 @@ target_modules = { module= libvtv;
bootstrap=true;
lib_path=.libs;
raw_cxx=true; };
+target_modules = { module= libcilkrts;
+ lib_path=.libs; };
target_modules = { module= libssp; lib_path=.libs; };
target_modules = { module= newlib; };
target_modules = { module= libgcc; bootstrap=true; no_check=true; };
@@ -492,6 +493,7 @@ dependencies = { module=all-m4; on=all-build-texinfo; };
// on libgcc and newlib/libgloss.
lang_env_dependencies = { module=libjava; cxx=true; };
lang_env_dependencies = { module=libitm; cxx=true; };
+lang_env_dependencies = { module=libcilkrts; cxx=true; };
lang_env_dependencies = { module=newlib; no_c=true; };
lang_env_dependencies = { module=libgloss; no_c=true; };
lang_env_dependencies = { module=libgcc; no_gcc=true; no_c=true; };
@@ -532,6 +534,8 @@ dependencies = { module=install-target-libsanitizer; on=install-target-libstdc++
dependencies = { module=install-target-libsanitizer; on=install-target-libgcc; };
dependencies = { module=install-target-libvtv; on=install-target-libstdc++-v3; };
dependencies = { module=install-target-libvtv; on=install-target-libgcc; };
+dependencies = { module=install-target-libcilkrts; on=install-target-libstdc++-v3; };
+dependencies = { module=install-target-libcilkrts; on=install-target-libgcc; };
dependencies = { module=install-target-libjava; on=install-target-libgcc; };
dependencies = { module=install-target-libitm; on=install-target-libgcc; };
dependencies = { module=install-target-libobjc; on=install-target-libgcc; };
@@ -551,7 +555,6 @@ dependencies = { module=configure-target-libgfortran; on=all-target-libquadmath;
languages = { language=c; gcc-check-target=check-gcc; };
languages = { language=c++; gcc-check-target=check-c++;
lib-check-target=check-target-libstdc++-v3;
- lib-check-target=check-target-libmudflap-c++;
lib-check-target=check-target-libitm-c++;
lib-check-target=check-target-libgomp-c++; };
languages = { language=fortran; gcc-check-target=check-fortran;
diff --git a/Makefile.in b/Makefile.in
index a13771d40eb..f9e8e0d5cb7 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -166,7 +166,7 @@ BUILD_EXPORTS = \
WINDMC="$(WINDMC_FOR_BUILD)"; export WINDMC;
# These variables must be set on the make command line for directories
-# built for the build system to override those in BASE_FLAGS_TO_PASSS.
+# built for the build system to override those in BASE_FLAGS_TO_PASS.
EXTRA_BUILD_FLAGS = \
CFLAGS="$(CFLAGS_FOR_BUILD)" \
LDFLAGS="$(LDFLAGS_FOR_BUILD)"
@@ -498,8 +498,10 @@ STAGE1_LANGUAGES = @stage1_languages@
# the last argument when conflicting --enable arguments are passed.
# * Likewise, we force-disable coverage flags, since the installed
# compiler probably has never heard of them.
+# * We also disable -Wformat, since older GCCs don't understand newer %s.
STAGE1_CONFIGURE_FLAGS = --disable-intermodule $(STAGE1_CHECKING) \
- --disable-coverage --enable-languages="$(STAGE1_LANGUAGES)"
+ --disable-coverage --enable-languages="$(STAGE1_LANGUAGES)" \
+ --disable-build-format-warnings
STAGEprofile_CFLAGS = $(STAGE2_CFLAGS) -fprofile-generate
STAGEprofile_TFLAGS = $(STAGE2_TFLAGS)
@@ -575,16 +577,12 @@ all:
# This is the list of directories that may be needed in RPATH_ENVVAR
# so that programs built for the target machine work.
-TARGET_LIB_PATH = $(TARGET_LIB_PATH_libstdc++-v3)$(TARGET_LIB_PATH_libmudflap)$(TARGET_LIB_PATH_libsanitizer)$(TARGET_LIB_PATH_libvtv)$(TARGET_LIB_PATH_libssp)$(TARGET_LIB_PATH_libgomp)$(TARGET_LIB_PATH_libitm)$(TARGET_LIB_PATH_libatomic)$(HOST_LIB_PATH_gcc)
+TARGET_LIB_PATH = $(TARGET_LIB_PATH_libstdc++-v3)$(TARGET_LIB_PATH_libsanitizer)$(TARGET_LIB_PATH_libvtv)$(TARGET_LIB_PATH_libcilkrts)$(TARGET_LIB_PATH_libssp)$(TARGET_LIB_PATH_libgomp)$(TARGET_LIB_PATH_libitm)$(TARGET_LIB_PATH_libatomic)$(HOST_LIB_PATH_gcc)
@if target-libstdc++-v3
TARGET_LIB_PATH_libstdc++-v3 = $$r/$(TARGET_SUBDIR)/libstdc++-v3/src/.libs:
@endif target-libstdc++-v3
-@if target-libmudflap
-TARGET_LIB_PATH_libmudflap = $$r/$(TARGET_SUBDIR)/libmudflap/.libs:
-@endif target-libmudflap
-
@if target-libsanitizer
TARGET_LIB_PATH_libsanitizer = $$r/$(TARGET_SUBDIR)/libsanitizer/.libs:
@endif target-libsanitizer
@@ -593,6 +591,10 @@ TARGET_LIB_PATH_libsanitizer = $$r/$(TARGET_SUBDIR)/libsanitizer/.libs:
TARGET_LIB_PATH_libvtv = $$r/$(TARGET_SUBDIR)/libvtv/.libs:
@endif target-libvtv
+@if target-libcilkrts
+TARGET_LIB_PATH_libcilkrts = $$r/$(TARGET_SUBDIR)/libcilkrts/.libs:
+@endif target-libcilkrts
+
@if target-libssp
TARGET_LIB_PATH_libssp = $$r/$(TARGET_SUBDIR)/libssp/.libs:
@endif target-libssp
@@ -927,9 +929,9 @@ configure-host: \
.PHONY: configure-target
configure-target: \
maybe-configure-target-libstdc++-v3 \
- maybe-configure-target-libmudflap \
maybe-configure-target-libsanitizer \
maybe-configure-target-libvtv \
+ maybe-configure-target-libcilkrts \
maybe-configure-target-libssp \
maybe-configure-target-newlib \
maybe-configure-target-libgcc \
@@ -1077,13 +1079,13 @@ all-host: maybe-all-lto-plugin
@if target-libstdc++-v3-no-bootstrap
all-target: maybe-all-target-libstdc++-v3
@endif target-libstdc++-v3-no-bootstrap
-all-target: maybe-all-target-libmudflap
@if target-libsanitizer-no-bootstrap
all-target: maybe-all-target-libsanitizer
@endif target-libsanitizer-no-bootstrap
@if target-libvtv-no-bootstrap
all-target: maybe-all-target-libvtv
@endif target-libvtv-no-bootstrap
+all-target: maybe-all-target-libcilkrts
all-target: maybe-all-target-libssp
all-target: maybe-all-target-newlib
@if target-libgcc-no-bootstrap
@@ -1173,9 +1175,9 @@ info-host: maybe-info-lto-plugin
.PHONY: info-target
info-target: maybe-info-target-libstdc++-v3
-info-target: maybe-info-target-libmudflap
info-target: maybe-info-target-libsanitizer
info-target: maybe-info-target-libvtv
+info-target: maybe-info-target-libcilkrts
info-target: maybe-info-target-libssp
info-target: maybe-info-target-newlib
info-target: maybe-info-target-libgcc
@@ -1256,9 +1258,9 @@ dvi-host: maybe-dvi-lto-plugin
.PHONY: dvi-target
dvi-target: maybe-dvi-target-libstdc++-v3
-dvi-target: maybe-dvi-target-libmudflap
dvi-target: maybe-dvi-target-libsanitizer
dvi-target: maybe-dvi-target-libvtv
+dvi-target: maybe-dvi-target-libcilkrts
dvi-target: maybe-dvi-target-libssp
dvi-target: maybe-dvi-target-newlib
dvi-target: maybe-dvi-target-libgcc
@@ -1339,9 +1341,9 @@ pdf-host: maybe-pdf-lto-plugin
.PHONY: pdf-target
pdf-target: maybe-pdf-target-libstdc++-v3
-pdf-target: maybe-pdf-target-libmudflap
pdf-target: maybe-pdf-target-libsanitizer
pdf-target: maybe-pdf-target-libvtv
+pdf-target: maybe-pdf-target-libcilkrts
pdf-target: maybe-pdf-target-libssp
pdf-target: maybe-pdf-target-newlib
pdf-target: maybe-pdf-target-libgcc
@@ -1422,9 +1424,9 @@ html-host: maybe-html-lto-plugin
.PHONY: html-target
html-target: maybe-html-target-libstdc++-v3
-html-target: maybe-html-target-libmudflap
html-target: maybe-html-target-libsanitizer
html-target: maybe-html-target-libvtv
+html-target: maybe-html-target-libcilkrts
html-target: maybe-html-target-libssp
html-target: maybe-html-target-newlib
html-target: maybe-html-target-libgcc
@@ -1505,9 +1507,9 @@ TAGS-host: maybe-TAGS-lto-plugin
.PHONY: TAGS-target
TAGS-target: maybe-TAGS-target-libstdc++-v3
-TAGS-target: maybe-TAGS-target-libmudflap
TAGS-target: maybe-TAGS-target-libsanitizer
TAGS-target: maybe-TAGS-target-libvtv
+TAGS-target: maybe-TAGS-target-libcilkrts
TAGS-target: maybe-TAGS-target-libssp
TAGS-target: maybe-TAGS-target-newlib
TAGS-target: maybe-TAGS-target-libgcc
@@ -1588,9 +1590,9 @@ install-info-host: maybe-install-info-lto-plugin
.PHONY: install-info-target
install-info-target: maybe-install-info-target-libstdc++-v3
-install-info-target: maybe-install-info-target-libmudflap
install-info-target: maybe-install-info-target-libsanitizer
install-info-target: maybe-install-info-target-libvtv
+install-info-target: maybe-install-info-target-libcilkrts
install-info-target: maybe-install-info-target-libssp
install-info-target: maybe-install-info-target-newlib
install-info-target: maybe-install-info-target-libgcc
@@ -1671,9 +1673,9 @@ install-pdf-host: maybe-install-pdf-lto-plugin
.PHONY: install-pdf-target
install-pdf-target: maybe-install-pdf-target-libstdc++-v3
-install-pdf-target: maybe-install-pdf-target-libmudflap
install-pdf-target: maybe-install-pdf-target-libsanitizer
install-pdf-target: maybe-install-pdf-target-libvtv
+install-pdf-target: maybe-install-pdf-target-libcilkrts
install-pdf-target: maybe-install-pdf-target-libssp
install-pdf-target: maybe-install-pdf-target-newlib
install-pdf-target: maybe-install-pdf-target-libgcc
@@ -1754,9 +1756,9 @@ install-html-host: maybe-install-html-lto-plugin
.PHONY: install-html-target
install-html-target: maybe-install-html-target-libstdc++-v3
-install-html-target: maybe-install-html-target-libmudflap
install-html-target: maybe-install-html-target-libsanitizer
install-html-target: maybe-install-html-target-libvtv
+install-html-target: maybe-install-html-target-libcilkrts
install-html-target: maybe-install-html-target-libssp
install-html-target: maybe-install-html-target-newlib
install-html-target: maybe-install-html-target-libgcc
@@ -1837,9 +1839,9 @@ installcheck-host: maybe-installcheck-lto-plugin
.PHONY: installcheck-target
installcheck-target: maybe-installcheck-target-libstdc++-v3
-installcheck-target: maybe-installcheck-target-libmudflap
installcheck-target: maybe-installcheck-target-libsanitizer
installcheck-target: maybe-installcheck-target-libvtv
+installcheck-target: maybe-installcheck-target-libcilkrts
installcheck-target: maybe-installcheck-target-libssp
installcheck-target: maybe-installcheck-target-newlib
installcheck-target: maybe-installcheck-target-libgcc
@@ -1920,9 +1922,9 @@ mostlyclean-host: maybe-mostlyclean-lto-plugin
.PHONY: mostlyclean-target
mostlyclean-target: maybe-mostlyclean-target-libstdc++-v3
-mostlyclean-target: maybe-mostlyclean-target-libmudflap
mostlyclean-target: maybe-mostlyclean-target-libsanitizer
mostlyclean-target: maybe-mostlyclean-target-libvtv
+mostlyclean-target: maybe-mostlyclean-target-libcilkrts
mostlyclean-target: maybe-mostlyclean-target-libssp
mostlyclean-target: maybe-mostlyclean-target-newlib
mostlyclean-target: maybe-mostlyclean-target-libgcc
@@ -2003,9 +2005,9 @@ clean-host: maybe-clean-lto-plugin
.PHONY: clean-target
clean-target: maybe-clean-target-libstdc++-v3
-clean-target: maybe-clean-target-libmudflap
clean-target: maybe-clean-target-libsanitizer
clean-target: maybe-clean-target-libvtv
+clean-target: maybe-clean-target-libcilkrts
clean-target: maybe-clean-target-libssp
clean-target: maybe-clean-target-newlib
clean-target: maybe-clean-target-libgcc
@@ -2086,9 +2088,9 @@ distclean-host: maybe-distclean-lto-plugin
.PHONY: distclean-target
distclean-target: maybe-distclean-target-libstdc++-v3
-distclean-target: maybe-distclean-target-libmudflap
distclean-target: maybe-distclean-target-libsanitizer
distclean-target: maybe-distclean-target-libvtv
+distclean-target: maybe-distclean-target-libcilkrts
distclean-target: maybe-distclean-target-libssp
distclean-target: maybe-distclean-target-newlib
distclean-target: maybe-distclean-target-libgcc
@@ -2169,9 +2171,9 @@ maintainer-clean-host: maybe-maintainer-clean-lto-plugin
.PHONY: maintainer-clean-target
maintainer-clean-target: maybe-maintainer-clean-target-libstdc++-v3
-maintainer-clean-target: maybe-maintainer-clean-target-libmudflap
maintainer-clean-target: maybe-maintainer-clean-target-libsanitizer
maintainer-clean-target: maybe-maintainer-clean-target-libvtv
+maintainer-clean-target: maybe-maintainer-clean-target-libcilkrts
maintainer-clean-target: maybe-maintainer-clean-target-libssp
maintainer-clean-target: maybe-maintainer-clean-target-newlib
maintainer-clean-target: maybe-maintainer-clean-target-libgcc
@@ -2307,9 +2309,9 @@ check-host: \
.PHONY: check-target
check-target: \
maybe-check-target-libstdc++-v3 \
- maybe-check-target-libmudflap \
maybe-check-target-libsanitizer \
maybe-check-target-libvtv \
+ maybe-check-target-libcilkrts \
maybe-check-target-libssp \
maybe-check-target-newlib \
maybe-check-target-libgcc \
@@ -2463,9 +2465,9 @@ install-host: \
.PHONY: install-target
install-target: \
maybe-install-target-libstdc++-v3 \
- maybe-install-target-libmudflap \
maybe-install-target-libsanitizer \
maybe-install-target-libvtv \
+ maybe-install-target-libcilkrts \
maybe-install-target-libssp \
maybe-install-target-newlib \
maybe-install-target-libgcc \
@@ -2566,9 +2568,9 @@ install-strip-host: \
.PHONY: install-strip-target
install-strip-target: \
maybe-install-strip-target-libstdc++-v3 \
- maybe-install-strip-target-libmudflap \
maybe-install-strip-target-libsanitizer \
maybe-install-strip-target-libvtv \
+ maybe-install-strip-target-libcilkrts \
maybe-install-strip-target-libssp \
maybe-install-strip-target-newlib \
maybe-install-strip-target-libgcc \
@@ -31745,463 +31747,6 @@ maintainer-clean-target-libstdc++-v3:
-.PHONY: configure-target-libmudflap maybe-configure-target-libmudflap
-maybe-configure-target-libmudflap:
-@if gcc-bootstrap
-configure-target-libmudflap: stage_current
-@endif gcc-bootstrap
-@if target-libmudflap
-maybe-configure-target-libmudflap: configure-target-libmudflap
-configure-target-libmudflap:
- @: $(MAKE); $(unstage)
- @r=`${PWD_COMMAND}`; export r; \
- s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
- echo "Checking multilib configuration for libmudflap..."; \
- $(SHELL) $(srcdir)/mkinstalldirs $(TARGET_SUBDIR)/libmudflap ; \
- $(CC_FOR_TARGET) --print-multi-lib > $(TARGET_SUBDIR)/libmudflap/multilib.tmp 2> /dev/null ; \
- if test -r $(TARGET_SUBDIR)/libmudflap/multilib.out; then \
- if cmp -s $(TARGET_SUBDIR)/libmudflap/multilib.tmp $(TARGET_SUBDIR)/libmudflap/multilib.out; then \
- rm -f $(TARGET_SUBDIR)/libmudflap/multilib.tmp; \
- else \
- rm -f $(TARGET_SUBDIR)/libmudflap/Makefile; \
- mv $(TARGET_SUBDIR)/libmudflap/multilib.tmp $(TARGET_SUBDIR)/libmudflap/multilib.out; \
- fi; \
- else \
- mv $(TARGET_SUBDIR)/libmudflap/multilib.tmp $(TARGET_SUBDIR)/libmudflap/multilib.out; \
- fi; \
- test ! -f $(TARGET_SUBDIR)/libmudflap/Makefile || exit 0; \
- $(SHELL) $(srcdir)/mkinstalldirs $(TARGET_SUBDIR)/libmudflap ; \
- $(NORMAL_TARGET_EXPORTS) \
- echo Configuring in $(TARGET_SUBDIR)/libmudflap; \
- cd "$(TARGET_SUBDIR)/libmudflap" || exit 1; \
- case $(srcdir) in \
- /* | [A-Za-z]:[\\/]*) topdir=$(srcdir) ;; \
- *) topdir=`echo $(TARGET_SUBDIR)/libmudflap/ | \
- sed -e 's,\./,,g' -e 's,[^/]*/,../,g' `$(srcdir) ;; \
- esac; \
- srcdiroption="--srcdir=$${topdir}/libmudflap"; \
- libsrcdir="$$s/libmudflap"; \
- rm -f no-such-file || : ; \
- CONFIG_SITE=no-such-file $(SHELL) $${libsrcdir}/configure \
- $(TARGET_CONFIGARGS) --build=${build_alias} --host=${target_alias} \
- --target=${target_alias} $${srcdiroption} \
- || exit 1
-@endif target-libmudflap
-
-
-
-
-
-.PHONY: all-target-libmudflap maybe-all-target-libmudflap
-maybe-all-target-libmudflap:
-@if gcc-bootstrap
-all-target-libmudflap: stage_current
-@endif gcc-bootstrap
-@if target-libmudflap
-TARGET-target-libmudflap=all
-maybe-all-target-libmudflap: all-target-libmudflap
-all-target-libmudflap: configure-target-libmudflap
- @: $(MAKE); $(unstage)
- @r=`${PWD_COMMAND}`; export r; \
- s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
- $(NORMAL_TARGET_EXPORTS) \
- (cd $(TARGET_SUBDIR)/libmudflap && \
- $(MAKE) $(BASE_FLAGS_TO_PASS) $(EXTRA_TARGET_FLAGS) \
- $(TARGET-target-libmudflap))
-@endif target-libmudflap
-
-
-
-
-
-.PHONY: check-target-libmudflap maybe-check-target-libmudflap
-maybe-check-target-libmudflap:
-@if target-libmudflap
-maybe-check-target-libmudflap: check-target-libmudflap
-
-check-target-libmudflap:
- @: $(MAKE); $(unstage)
- @r=`${PWD_COMMAND}`; export r; \
- s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
- $(NORMAL_TARGET_EXPORTS) \
- (cd $(TARGET_SUBDIR)/libmudflap && \
- $(MAKE) $(TARGET_FLAGS_TO_PASS) check)
-
-@endif target-libmudflap
-
-.PHONY: install-target-libmudflap maybe-install-target-libmudflap
-maybe-install-target-libmudflap:
-@if target-libmudflap
-maybe-install-target-libmudflap: install-target-libmudflap
-
-install-target-libmudflap: installdirs
- @: $(MAKE); $(unstage)
- @r=`${PWD_COMMAND}`; export r; \
- s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
- $(NORMAL_TARGET_EXPORTS) \
- (cd $(TARGET_SUBDIR)/libmudflap && \
- $(MAKE) $(TARGET_FLAGS_TO_PASS) install)
-
-@endif target-libmudflap
-
-.PHONY: install-strip-target-libmudflap maybe-install-strip-target-libmudflap
-maybe-install-strip-target-libmudflap:
-@if target-libmudflap
-maybe-install-strip-target-libmudflap: install-strip-target-libmudflap
-
-install-strip-target-libmudflap: installdirs
- @: $(MAKE); $(unstage)
- @r=`${PWD_COMMAND}`; export r; \
- s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
- $(NORMAL_TARGET_EXPORTS) \
- (cd $(TARGET_SUBDIR)/libmudflap && \
- $(MAKE) $(TARGET_FLAGS_TO_PASS) install-strip)
-
-@endif target-libmudflap
-
-# Other targets (info, dvi, pdf, etc.)
-
-.PHONY: maybe-info-target-libmudflap info-target-libmudflap
-maybe-info-target-libmudflap:
-@if target-libmudflap
-maybe-info-target-libmudflap: info-target-libmudflap
-
-info-target-libmudflap: \
- configure-target-libmudflap
- @: $(MAKE); $(unstage)
- @[ -f $(TARGET_SUBDIR)/libmudflap/Makefile ] || exit 0 ; \
- r=`${PWD_COMMAND}`; export r; \
- s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
- $(NORMAL_TARGET_EXPORTS) \
- echo "Doing info in $(TARGET_SUBDIR)/libmudflap" ; \
- for flag in $(EXTRA_TARGET_FLAGS); do \
- eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
- done; \
- (cd $(TARGET_SUBDIR)/libmudflap && \
- $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
- "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
- "RANLIB=$${RANLIB}" \
- "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
- info) \
- || exit 1
-
-@endif target-libmudflap
-
-.PHONY: maybe-dvi-target-libmudflap dvi-target-libmudflap
-maybe-dvi-target-libmudflap:
-@if target-libmudflap
-maybe-dvi-target-libmudflap: dvi-target-libmudflap
-
-dvi-target-libmudflap: \
- configure-target-libmudflap
- @: $(MAKE); $(unstage)
- @[ -f $(TARGET_SUBDIR)/libmudflap/Makefile ] || exit 0 ; \
- r=`${PWD_COMMAND}`; export r; \
- s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
- $(NORMAL_TARGET_EXPORTS) \
- echo "Doing dvi in $(TARGET_SUBDIR)/libmudflap" ; \
- for flag in $(EXTRA_TARGET_FLAGS); do \
- eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
- done; \
- (cd $(TARGET_SUBDIR)/libmudflap && \
- $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
- "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
- "RANLIB=$${RANLIB}" \
- "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
- dvi) \
- || exit 1
-
-@endif target-libmudflap
-
-.PHONY: maybe-pdf-target-libmudflap pdf-target-libmudflap
-maybe-pdf-target-libmudflap:
-@if target-libmudflap
-maybe-pdf-target-libmudflap: pdf-target-libmudflap
-
-pdf-target-libmudflap: \
- configure-target-libmudflap
- @: $(MAKE); $(unstage)
- @[ -f $(TARGET_SUBDIR)/libmudflap/Makefile ] || exit 0 ; \
- r=`${PWD_COMMAND}`; export r; \
- s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
- $(NORMAL_TARGET_EXPORTS) \
- echo "Doing pdf in $(TARGET_SUBDIR)/libmudflap" ; \
- for flag in $(EXTRA_TARGET_FLAGS); do \
- eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
- done; \
- (cd $(TARGET_SUBDIR)/libmudflap && \
- $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
- "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
- "RANLIB=$${RANLIB}" \
- "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
- pdf) \
- || exit 1
-
-@endif target-libmudflap
-
-.PHONY: maybe-html-target-libmudflap html-target-libmudflap
-maybe-html-target-libmudflap:
-@if target-libmudflap
-maybe-html-target-libmudflap: html-target-libmudflap
-
-html-target-libmudflap: \
- configure-target-libmudflap
- @: $(MAKE); $(unstage)
- @[ -f $(TARGET_SUBDIR)/libmudflap/Makefile ] || exit 0 ; \
- r=`${PWD_COMMAND}`; export r; \
- s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
- $(NORMAL_TARGET_EXPORTS) \
- echo "Doing html in $(TARGET_SUBDIR)/libmudflap" ; \
- for flag in $(EXTRA_TARGET_FLAGS); do \
- eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
- done; \
- (cd $(TARGET_SUBDIR)/libmudflap && \
- $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
- "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
- "RANLIB=$${RANLIB}" \
- "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
- html) \
- || exit 1
-
-@endif target-libmudflap
-
-.PHONY: maybe-TAGS-target-libmudflap TAGS-target-libmudflap
-maybe-TAGS-target-libmudflap:
-@if target-libmudflap
-maybe-TAGS-target-libmudflap: TAGS-target-libmudflap
-
-TAGS-target-libmudflap: \
- configure-target-libmudflap
- @: $(MAKE); $(unstage)
- @[ -f $(TARGET_SUBDIR)/libmudflap/Makefile ] || exit 0 ; \
- r=`${PWD_COMMAND}`; export r; \
- s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
- $(NORMAL_TARGET_EXPORTS) \
- echo "Doing TAGS in $(TARGET_SUBDIR)/libmudflap" ; \
- for flag in $(EXTRA_TARGET_FLAGS); do \
- eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
- done; \
- (cd $(TARGET_SUBDIR)/libmudflap && \
- $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
- "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
- "RANLIB=$${RANLIB}" \
- "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
- TAGS) \
- || exit 1
-
-@endif target-libmudflap
-
-.PHONY: maybe-install-info-target-libmudflap install-info-target-libmudflap
-maybe-install-info-target-libmudflap:
-@if target-libmudflap
-maybe-install-info-target-libmudflap: install-info-target-libmudflap
-
-install-info-target-libmudflap: \
- configure-target-libmudflap \
- info-target-libmudflap
- @: $(MAKE); $(unstage)
- @[ -f $(TARGET_SUBDIR)/libmudflap/Makefile ] || exit 0 ; \
- r=`${PWD_COMMAND}`; export r; \
- s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
- $(NORMAL_TARGET_EXPORTS) \
- echo "Doing install-info in $(TARGET_SUBDIR)/libmudflap" ; \
- for flag in $(EXTRA_TARGET_FLAGS); do \
- eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
- done; \
- (cd $(TARGET_SUBDIR)/libmudflap && \
- $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
- "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
- "RANLIB=$${RANLIB}" \
- "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
- install-info) \
- || exit 1
-
-@endif target-libmudflap
-
-.PHONY: maybe-install-pdf-target-libmudflap install-pdf-target-libmudflap
-maybe-install-pdf-target-libmudflap:
-@if target-libmudflap
-maybe-install-pdf-target-libmudflap: install-pdf-target-libmudflap
-
-install-pdf-target-libmudflap: \
- configure-target-libmudflap \
- pdf-target-libmudflap
- @: $(MAKE); $(unstage)
- @[ -f $(TARGET_SUBDIR)/libmudflap/Makefile ] || exit 0 ; \
- r=`${PWD_COMMAND}`; export r; \
- s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
- $(NORMAL_TARGET_EXPORTS) \
- echo "Doing install-pdf in $(TARGET_SUBDIR)/libmudflap" ; \
- for flag in $(EXTRA_TARGET_FLAGS); do \
- eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
- done; \
- (cd $(TARGET_SUBDIR)/libmudflap && \
- $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
- "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
- "RANLIB=$${RANLIB}" \
- "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
- install-pdf) \
- || exit 1
-
-@endif target-libmudflap
-
-.PHONY: maybe-install-html-target-libmudflap install-html-target-libmudflap
-maybe-install-html-target-libmudflap:
-@if target-libmudflap
-maybe-install-html-target-libmudflap: install-html-target-libmudflap
-
-install-html-target-libmudflap: \
- configure-target-libmudflap \
- html-target-libmudflap
- @: $(MAKE); $(unstage)
- @[ -f $(TARGET_SUBDIR)/libmudflap/Makefile ] || exit 0 ; \
- r=`${PWD_COMMAND}`; export r; \
- s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
- $(NORMAL_TARGET_EXPORTS) \
- echo "Doing install-html in $(TARGET_SUBDIR)/libmudflap" ; \
- for flag in $(EXTRA_TARGET_FLAGS); do \
- eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
- done; \
- (cd $(TARGET_SUBDIR)/libmudflap && \
- $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
- "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
- "RANLIB=$${RANLIB}" \
- "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
- install-html) \
- || exit 1
-
-@endif target-libmudflap
-
-.PHONY: maybe-installcheck-target-libmudflap installcheck-target-libmudflap
-maybe-installcheck-target-libmudflap:
-@if target-libmudflap
-maybe-installcheck-target-libmudflap: installcheck-target-libmudflap
-
-installcheck-target-libmudflap: \
- configure-target-libmudflap
- @: $(MAKE); $(unstage)
- @[ -f $(TARGET_SUBDIR)/libmudflap/Makefile ] || exit 0 ; \
- r=`${PWD_COMMAND}`; export r; \
- s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
- $(NORMAL_TARGET_EXPORTS) \
- echo "Doing installcheck in $(TARGET_SUBDIR)/libmudflap" ; \
- for flag in $(EXTRA_TARGET_FLAGS); do \
- eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
- done; \
- (cd $(TARGET_SUBDIR)/libmudflap && \
- $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
- "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
- "RANLIB=$${RANLIB}" \
- "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
- installcheck) \
- || exit 1
-
-@endif target-libmudflap
-
-.PHONY: maybe-mostlyclean-target-libmudflap mostlyclean-target-libmudflap
-maybe-mostlyclean-target-libmudflap:
-@if target-libmudflap
-maybe-mostlyclean-target-libmudflap: mostlyclean-target-libmudflap
-
-mostlyclean-target-libmudflap:
- @: $(MAKE); $(unstage)
- @[ -f $(TARGET_SUBDIR)/libmudflap/Makefile ] || exit 0 ; \
- r=`${PWD_COMMAND}`; export r; \
- s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
- $(NORMAL_TARGET_EXPORTS) \
- echo "Doing mostlyclean in $(TARGET_SUBDIR)/libmudflap" ; \
- for flag in $(EXTRA_TARGET_FLAGS); do \
- eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
- done; \
- (cd $(TARGET_SUBDIR)/libmudflap && \
- $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
- "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
- "RANLIB=$${RANLIB}" \
- "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
- mostlyclean) \
- || exit 1
-
-@endif target-libmudflap
-
-.PHONY: maybe-clean-target-libmudflap clean-target-libmudflap
-maybe-clean-target-libmudflap:
-@if target-libmudflap
-maybe-clean-target-libmudflap: clean-target-libmudflap
-
-clean-target-libmudflap:
- @: $(MAKE); $(unstage)
- @[ -f $(TARGET_SUBDIR)/libmudflap/Makefile ] || exit 0 ; \
- r=`${PWD_COMMAND}`; export r; \
- s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
- $(NORMAL_TARGET_EXPORTS) \
- echo "Doing clean in $(TARGET_SUBDIR)/libmudflap" ; \
- for flag in $(EXTRA_TARGET_FLAGS); do \
- eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
- done; \
- (cd $(TARGET_SUBDIR)/libmudflap && \
- $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
- "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
- "RANLIB=$${RANLIB}" \
- "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
- clean) \
- || exit 1
-
-@endif target-libmudflap
-
-.PHONY: maybe-distclean-target-libmudflap distclean-target-libmudflap
-maybe-distclean-target-libmudflap:
-@if target-libmudflap
-maybe-distclean-target-libmudflap: distclean-target-libmudflap
-
-distclean-target-libmudflap:
- @: $(MAKE); $(unstage)
- @[ -f $(TARGET_SUBDIR)/libmudflap/Makefile ] || exit 0 ; \
- r=`${PWD_COMMAND}`; export r; \
- s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
- $(NORMAL_TARGET_EXPORTS) \
- echo "Doing distclean in $(TARGET_SUBDIR)/libmudflap" ; \
- for flag in $(EXTRA_TARGET_FLAGS); do \
- eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
- done; \
- (cd $(TARGET_SUBDIR)/libmudflap && \
- $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
- "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
- "RANLIB=$${RANLIB}" \
- "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
- distclean) \
- || exit 1
-
-@endif target-libmudflap
-
-.PHONY: maybe-maintainer-clean-target-libmudflap maintainer-clean-target-libmudflap
-maybe-maintainer-clean-target-libmudflap:
-@if target-libmudflap
-maybe-maintainer-clean-target-libmudflap: maintainer-clean-target-libmudflap
-
-maintainer-clean-target-libmudflap:
- @: $(MAKE); $(unstage)
- @[ -f $(TARGET_SUBDIR)/libmudflap/Makefile ] || exit 0 ; \
- r=`${PWD_COMMAND}`; export r; \
- s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
- $(NORMAL_TARGET_EXPORTS) \
- echo "Doing maintainer-clean in $(TARGET_SUBDIR)/libmudflap" ; \
- for flag in $(EXTRA_TARGET_FLAGS); do \
- eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
- done; \
- (cd $(TARGET_SUBDIR)/libmudflap && \
- $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
- "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
- "RANLIB=$${RANLIB}" \
- "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
- maintainer-clean) \
- || exit 1
-
-@endif target-libmudflap
-
-
-
-
-
.PHONY: configure-target-libsanitizer maybe-configure-target-libsanitizer
maybe-configure-target-libsanitizer:
@if gcc-bootstrap
@@ -34150,6 +33695,463 @@ maintainer-clean-target-libvtv:
+.PHONY: configure-target-libcilkrts maybe-configure-target-libcilkrts
+maybe-configure-target-libcilkrts:
+@if gcc-bootstrap
+configure-target-libcilkrts: stage_current
+@endif gcc-bootstrap
+@if target-libcilkrts
+maybe-configure-target-libcilkrts: configure-target-libcilkrts
+configure-target-libcilkrts:
+ @: $(MAKE); $(unstage)
+ @r=`${PWD_COMMAND}`; export r; \
+ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+ echo "Checking multilib configuration for libcilkrts..."; \
+ $(SHELL) $(srcdir)/mkinstalldirs $(TARGET_SUBDIR)/libcilkrts ; \
+ $(CC_FOR_TARGET) --print-multi-lib > $(TARGET_SUBDIR)/libcilkrts/multilib.tmp 2> /dev/null ; \
+ if test -r $(TARGET_SUBDIR)/libcilkrts/multilib.out; then \
+ if cmp -s $(TARGET_SUBDIR)/libcilkrts/multilib.tmp $(TARGET_SUBDIR)/libcilkrts/multilib.out; then \
+ rm -f $(TARGET_SUBDIR)/libcilkrts/multilib.tmp; \
+ else \
+ rm -f $(TARGET_SUBDIR)/libcilkrts/Makefile; \
+ mv $(TARGET_SUBDIR)/libcilkrts/multilib.tmp $(TARGET_SUBDIR)/libcilkrts/multilib.out; \
+ fi; \
+ else \
+ mv $(TARGET_SUBDIR)/libcilkrts/multilib.tmp $(TARGET_SUBDIR)/libcilkrts/multilib.out; \
+ fi; \
+ test ! -f $(TARGET_SUBDIR)/libcilkrts/Makefile || exit 0; \
+ $(SHELL) $(srcdir)/mkinstalldirs $(TARGET_SUBDIR)/libcilkrts ; \
+ $(NORMAL_TARGET_EXPORTS) \
+ echo Configuring in $(TARGET_SUBDIR)/libcilkrts; \
+ cd "$(TARGET_SUBDIR)/libcilkrts" || exit 1; \
+ case $(srcdir) in \
+ /* | [A-Za-z]:[\\/]*) topdir=$(srcdir) ;; \
+ *) topdir=`echo $(TARGET_SUBDIR)/libcilkrts/ | \
+ sed -e 's,\./,,g' -e 's,[^/]*/,../,g' `$(srcdir) ;; \
+ esac; \
+ srcdiroption="--srcdir=$${topdir}/libcilkrts"; \
+ libsrcdir="$$s/libcilkrts"; \
+ rm -f no-such-file || : ; \
+ CONFIG_SITE=no-such-file $(SHELL) $${libsrcdir}/configure \
+ $(TARGET_CONFIGARGS) --build=${build_alias} --host=${target_alias} \
+ --target=${target_alias} $${srcdiroption} \
+ || exit 1
+@endif target-libcilkrts
+
+
+
+
+
+.PHONY: all-target-libcilkrts maybe-all-target-libcilkrts
+maybe-all-target-libcilkrts:
+@if gcc-bootstrap
+all-target-libcilkrts: stage_current
+@endif gcc-bootstrap
+@if target-libcilkrts
+TARGET-target-libcilkrts=all
+maybe-all-target-libcilkrts: all-target-libcilkrts
+all-target-libcilkrts: configure-target-libcilkrts
+ @: $(MAKE); $(unstage)
+ @r=`${PWD_COMMAND}`; export r; \
+ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+ $(NORMAL_TARGET_EXPORTS) \
+ (cd $(TARGET_SUBDIR)/libcilkrts && \
+ $(MAKE) $(BASE_FLAGS_TO_PASS) $(EXTRA_TARGET_FLAGS) \
+ $(TARGET-target-libcilkrts))
+@endif target-libcilkrts
+
+
+
+
+
+.PHONY: check-target-libcilkrts maybe-check-target-libcilkrts
+maybe-check-target-libcilkrts:
+@if target-libcilkrts
+maybe-check-target-libcilkrts: check-target-libcilkrts
+
+check-target-libcilkrts:
+ @: $(MAKE); $(unstage)
+ @r=`${PWD_COMMAND}`; export r; \
+ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+ $(NORMAL_TARGET_EXPORTS) \
+ (cd $(TARGET_SUBDIR)/libcilkrts && \
+ $(MAKE) $(TARGET_FLAGS_TO_PASS) check)
+
+@endif target-libcilkrts
+
+.PHONY: install-target-libcilkrts maybe-install-target-libcilkrts
+maybe-install-target-libcilkrts:
+@if target-libcilkrts
+maybe-install-target-libcilkrts: install-target-libcilkrts
+
+install-target-libcilkrts: installdirs
+ @: $(MAKE); $(unstage)
+ @r=`${PWD_COMMAND}`; export r; \
+ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+ $(NORMAL_TARGET_EXPORTS) \
+ (cd $(TARGET_SUBDIR)/libcilkrts && \
+ $(MAKE) $(TARGET_FLAGS_TO_PASS) install)
+
+@endif target-libcilkrts
+
+.PHONY: install-strip-target-libcilkrts maybe-install-strip-target-libcilkrts
+maybe-install-strip-target-libcilkrts:
+@if target-libcilkrts
+maybe-install-strip-target-libcilkrts: install-strip-target-libcilkrts
+
+install-strip-target-libcilkrts: installdirs
+ @: $(MAKE); $(unstage)
+ @r=`${PWD_COMMAND}`; export r; \
+ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+ $(NORMAL_TARGET_EXPORTS) \
+ (cd $(TARGET_SUBDIR)/libcilkrts && \
+ $(MAKE) $(TARGET_FLAGS_TO_PASS) install-strip)
+
+@endif target-libcilkrts
+
+# Other targets (info, dvi, pdf, etc.)
+
+.PHONY: maybe-info-target-libcilkrts info-target-libcilkrts
+maybe-info-target-libcilkrts:
+@if target-libcilkrts
+maybe-info-target-libcilkrts: info-target-libcilkrts
+
+info-target-libcilkrts: \
+ configure-target-libcilkrts
+ @: $(MAKE); $(unstage)
+ @[ -f $(TARGET_SUBDIR)/libcilkrts/Makefile ] || exit 0 ; \
+ r=`${PWD_COMMAND}`; export r; \
+ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+ $(NORMAL_TARGET_EXPORTS) \
+ echo "Doing info in $(TARGET_SUBDIR)/libcilkrts" ; \
+ for flag in $(EXTRA_TARGET_FLAGS); do \
+ eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
+ done; \
+ (cd $(TARGET_SUBDIR)/libcilkrts && \
+ $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
+ "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
+ "RANLIB=$${RANLIB}" \
+ "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
+ info) \
+ || exit 1
+
+@endif target-libcilkrts
+
+.PHONY: maybe-dvi-target-libcilkrts dvi-target-libcilkrts
+maybe-dvi-target-libcilkrts:
+@if target-libcilkrts
+maybe-dvi-target-libcilkrts: dvi-target-libcilkrts
+
+dvi-target-libcilkrts: \
+ configure-target-libcilkrts
+ @: $(MAKE); $(unstage)
+ @[ -f $(TARGET_SUBDIR)/libcilkrts/Makefile ] || exit 0 ; \
+ r=`${PWD_COMMAND}`; export r; \
+ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+ $(NORMAL_TARGET_EXPORTS) \
+ echo "Doing dvi in $(TARGET_SUBDIR)/libcilkrts" ; \
+ for flag in $(EXTRA_TARGET_FLAGS); do \
+ eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
+ done; \
+ (cd $(TARGET_SUBDIR)/libcilkrts && \
+ $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
+ "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
+ "RANLIB=$${RANLIB}" \
+ "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
+ dvi) \
+ || exit 1
+
+@endif target-libcilkrts
+
+.PHONY: maybe-pdf-target-libcilkrts pdf-target-libcilkrts
+maybe-pdf-target-libcilkrts:
+@if target-libcilkrts
+maybe-pdf-target-libcilkrts: pdf-target-libcilkrts
+
+pdf-target-libcilkrts: \
+ configure-target-libcilkrts
+ @: $(MAKE); $(unstage)
+ @[ -f $(TARGET_SUBDIR)/libcilkrts/Makefile ] || exit 0 ; \
+ r=`${PWD_COMMAND}`; export r; \
+ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+ $(NORMAL_TARGET_EXPORTS) \
+ echo "Doing pdf in $(TARGET_SUBDIR)/libcilkrts" ; \
+ for flag in $(EXTRA_TARGET_FLAGS); do \
+ eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
+ done; \
+ (cd $(TARGET_SUBDIR)/libcilkrts && \
+ $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
+ "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
+ "RANLIB=$${RANLIB}" \
+ "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
+ pdf) \
+ || exit 1
+
+@endif target-libcilkrts
+
+.PHONY: maybe-html-target-libcilkrts html-target-libcilkrts
+maybe-html-target-libcilkrts:
+@if target-libcilkrts
+maybe-html-target-libcilkrts: html-target-libcilkrts
+
+html-target-libcilkrts: \
+ configure-target-libcilkrts
+ @: $(MAKE); $(unstage)
+ @[ -f $(TARGET_SUBDIR)/libcilkrts/Makefile ] || exit 0 ; \
+ r=`${PWD_COMMAND}`; export r; \
+ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+ $(NORMAL_TARGET_EXPORTS) \
+ echo "Doing html in $(TARGET_SUBDIR)/libcilkrts" ; \
+ for flag in $(EXTRA_TARGET_FLAGS); do \
+ eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
+ done; \
+ (cd $(TARGET_SUBDIR)/libcilkrts && \
+ $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
+ "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
+ "RANLIB=$${RANLIB}" \
+ "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
+ html) \
+ || exit 1
+
+@endif target-libcilkrts
+
+.PHONY: maybe-TAGS-target-libcilkrts TAGS-target-libcilkrts
+maybe-TAGS-target-libcilkrts:
+@if target-libcilkrts
+maybe-TAGS-target-libcilkrts: TAGS-target-libcilkrts
+
+TAGS-target-libcilkrts: \
+ configure-target-libcilkrts
+ @: $(MAKE); $(unstage)
+ @[ -f $(TARGET_SUBDIR)/libcilkrts/Makefile ] || exit 0 ; \
+ r=`${PWD_COMMAND}`; export r; \
+ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+ $(NORMAL_TARGET_EXPORTS) \
+ echo "Doing TAGS in $(TARGET_SUBDIR)/libcilkrts" ; \
+ for flag in $(EXTRA_TARGET_FLAGS); do \
+ eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
+ done; \
+ (cd $(TARGET_SUBDIR)/libcilkrts && \
+ $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
+ "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
+ "RANLIB=$${RANLIB}" \
+ "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
+ TAGS) \
+ || exit 1
+
+@endif target-libcilkrts
+
+.PHONY: maybe-install-info-target-libcilkrts install-info-target-libcilkrts
+maybe-install-info-target-libcilkrts:
+@if target-libcilkrts
+maybe-install-info-target-libcilkrts: install-info-target-libcilkrts
+
+install-info-target-libcilkrts: \
+ configure-target-libcilkrts \
+ info-target-libcilkrts
+ @: $(MAKE); $(unstage)
+ @[ -f $(TARGET_SUBDIR)/libcilkrts/Makefile ] || exit 0 ; \
+ r=`${PWD_COMMAND}`; export r; \
+ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+ $(NORMAL_TARGET_EXPORTS) \
+ echo "Doing install-info in $(TARGET_SUBDIR)/libcilkrts" ; \
+ for flag in $(EXTRA_TARGET_FLAGS); do \
+ eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
+ done; \
+ (cd $(TARGET_SUBDIR)/libcilkrts && \
+ $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
+ "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
+ "RANLIB=$${RANLIB}" \
+ "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
+ install-info) \
+ || exit 1
+
+@endif target-libcilkrts
+
+.PHONY: maybe-install-pdf-target-libcilkrts install-pdf-target-libcilkrts
+maybe-install-pdf-target-libcilkrts:
+@if target-libcilkrts
+maybe-install-pdf-target-libcilkrts: install-pdf-target-libcilkrts
+
+install-pdf-target-libcilkrts: \
+ configure-target-libcilkrts \
+ pdf-target-libcilkrts
+ @: $(MAKE); $(unstage)
+ @[ -f $(TARGET_SUBDIR)/libcilkrts/Makefile ] || exit 0 ; \
+ r=`${PWD_COMMAND}`; export r; \
+ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+ $(NORMAL_TARGET_EXPORTS) \
+ echo "Doing install-pdf in $(TARGET_SUBDIR)/libcilkrts" ; \
+ for flag in $(EXTRA_TARGET_FLAGS); do \
+ eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
+ done; \
+ (cd $(TARGET_SUBDIR)/libcilkrts && \
+ $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
+ "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
+ "RANLIB=$${RANLIB}" \
+ "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
+ install-pdf) \
+ || exit 1
+
+@endif target-libcilkrts
+
+.PHONY: maybe-install-html-target-libcilkrts install-html-target-libcilkrts
+maybe-install-html-target-libcilkrts:
+@if target-libcilkrts
+maybe-install-html-target-libcilkrts: install-html-target-libcilkrts
+
+install-html-target-libcilkrts: \
+ configure-target-libcilkrts \
+ html-target-libcilkrts
+ @: $(MAKE); $(unstage)
+ @[ -f $(TARGET_SUBDIR)/libcilkrts/Makefile ] || exit 0 ; \
+ r=`${PWD_COMMAND}`; export r; \
+ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+ $(NORMAL_TARGET_EXPORTS) \
+ echo "Doing install-html in $(TARGET_SUBDIR)/libcilkrts" ; \
+ for flag in $(EXTRA_TARGET_FLAGS); do \
+ eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
+ done; \
+ (cd $(TARGET_SUBDIR)/libcilkrts && \
+ $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
+ "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
+ "RANLIB=$${RANLIB}" \
+ "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
+ install-html) \
+ || exit 1
+
+@endif target-libcilkrts
+
+.PHONY: maybe-installcheck-target-libcilkrts installcheck-target-libcilkrts
+maybe-installcheck-target-libcilkrts:
+@if target-libcilkrts
+maybe-installcheck-target-libcilkrts: installcheck-target-libcilkrts
+
+installcheck-target-libcilkrts: \
+ configure-target-libcilkrts
+ @: $(MAKE); $(unstage)
+ @[ -f $(TARGET_SUBDIR)/libcilkrts/Makefile ] || exit 0 ; \
+ r=`${PWD_COMMAND}`; export r; \
+ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+ $(NORMAL_TARGET_EXPORTS) \
+ echo "Doing installcheck in $(TARGET_SUBDIR)/libcilkrts" ; \
+ for flag in $(EXTRA_TARGET_FLAGS); do \
+ eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
+ done; \
+ (cd $(TARGET_SUBDIR)/libcilkrts && \
+ $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
+ "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
+ "RANLIB=$${RANLIB}" \
+ "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
+ installcheck) \
+ || exit 1
+
+@endif target-libcilkrts
+
+.PHONY: maybe-mostlyclean-target-libcilkrts mostlyclean-target-libcilkrts
+maybe-mostlyclean-target-libcilkrts:
+@if target-libcilkrts
+maybe-mostlyclean-target-libcilkrts: mostlyclean-target-libcilkrts
+
+mostlyclean-target-libcilkrts:
+ @: $(MAKE); $(unstage)
+ @[ -f $(TARGET_SUBDIR)/libcilkrts/Makefile ] || exit 0 ; \
+ r=`${PWD_COMMAND}`; export r; \
+ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+ $(NORMAL_TARGET_EXPORTS) \
+ echo "Doing mostlyclean in $(TARGET_SUBDIR)/libcilkrts" ; \
+ for flag in $(EXTRA_TARGET_FLAGS); do \
+ eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
+ done; \
+ (cd $(TARGET_SUBDIR)/libcilkrts && \
+ $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
+ "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
+ "RANLIB=$${RANLIB}" \
+ "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
+ mostlyclean) \
+ || exit 1
+
+@endif target-libcilkrts
+
+.PHONY: maybe-clean-target-libcilkrts clean-target-libcilkrts
+maybe-clean-target-libcilkrts:
+@if target-libcilkrts
+maybe-clean-target-libcilkrts: clean-target-libcilkrts
+
+clean-target-libcilkrts:
+ @: $(MAKE); $(unstage)
+ @[ -f $(TARGET_SUBDIR)/libcilkrts/Makefile ] || exit 0 ; \
+ r=`${PWD_COMMAND}`; export r; \
+ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+ $(NORMAL_TARGET_EXPORTS) \
+ echo "Doing clean in $(TARGET_SUBDIR)/libcilkrts" ; \
+ for flag in $(EXTRA_TARGET_FLAGS); do \
+ eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
+ done; \
+ (cd $(TARGET_SUBDIR)/libcilkrts && \
+ $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
+ "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
+ "RANLIB=$${RANLIB}" \
+ "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
+ clean) \
+ || exit 1
+
+@endif target-libcilkrts
+
+.PHONY: maybe-distclean-target-libcilkrts distclean-target-libcilkrts
+maybe-distclean-target-libcilkrts:
+@if target-libcilkrts
+maybe-distclean-target-libcilkrts: distclean-target-libcilkrts
+
+distclean-target-libcilkrts:
+ @: $(MAKE); $(unstage)
+ @[ -f $(TARGET_SUBDIR)/libcilkrts/Makefile ] || exit 0 ; \
+ r=`${PWD_COMMAND}`; export r; \
+ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+ $(NORMAL_TARGET_EXPORTS) \
+ echo "Doing distclean in $(TARGET_SUBDIR)/libcilkrts" ; \
+ for flag in $(EXTRA_TARGET_FLAGS); do \
+ eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
+ done; \
+ (cd $(TARGET_SUBDIR)/libcilkrts && \
+ $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
+ "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
+ "RANLIB=$${RANLIB}" \
+ "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
+ distclean) \
+ || exit 1
+
+@endif target-libcilkrts
+
+.PHONY: maybe-maintainer-clean-target-libcilkrts maintainer-clean-target-libcilkrts
+maybe-maintainer-clean-target-libcilkrts:
+@if target-libcilkrts
+maybe-maintainer-clean-target-libcilkrts: maintainer-clean-target-libcilkrts
+
+maintainer-clean-target-libcilkrts:
+ @: $(MAKE); $(unstage)
+ @[ -f $(TARGET_SUBDIR)/libcilkrts/Makefile ] || exit 0 ; \
+ r=`${PWD_COMMAND}`; export r; \
+ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+ $(NORMAL_TARGET_EXPORTS) \
+ echo "Doing maintainer-clean in $(TARGET_SUBDIR)/libcilkrts" ; \
+ for flag in $(EXTRA_TARGET_FLAGS); do \
+ eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
+ done; \
+ (cd $(TARGET_SUBDIR)/libcilkrts && \
+ $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
+ "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
+ "RANLIB=$${RANLIB}" \
+ "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
+ maintainer-clean) \
+ || exit 1
+
+@endif target-libcilkrts
+
+
+
+
+
.PHONY: configure-target-libssp maybe-configure-target-libssp
maybe-configure-target-libssp:
@if gcc-bootstrap
@@ -44237,13 +44239,6 @@ maintainer-clean-target-libatomic:
-@if target-libmudflap
-.PHONY: check-target-libmudflap-c++
-check-target-libmudflap-c++:
- $(MAKE) RUNTESTFLAGS="$(RUNTESTFLAGS) c++frags.exp" check-target-libmudflap
-
-@endif target-libmudflap
-
@if target-libgomp
.PHONY: check-target-libgomp-c++
check-target-libgomp-c++:
@@ -44292,7 +44287,7 @@ check-gcc-c++:
s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
$(HOST_EXPORTS) \
(cd gcc && $(MAKE) $(GCC_FLAGS_TO_PASS) check-c++);
-check-c++: check-gcc-c++ check-target-libstdc++-v3 check-target-libmudflap-c++ check-target-libitm-c++ check-target-libgomp-c++
+check-c++: check-gcc-c++ check-target-libstdc++-v3 check-target-libitm-c++ check-target-libgomp-c++
.PHONY: check-gcc-fortran check-fortran
check-gcc-fortran:
@@ -46375,7 +46370,6 @@ configure-stage3-target-libstdc++-v3: maybe-all-stage3-gcc
configure-stage4-target-libstdc++-v3: maybe-all-stage4-gcc
configure-stageprofile-target-libstdc++-v3: maybe-all-stageprofile-gcc
configure-stagefeedback-target-libstdc++-v3: maybe-all-stagefeedback-gcc
-configure-target-libmudflap: stage_last
configure-stage1-target-libsanitizer: maybe-all-stage1-gcc
configure-stage2-target-libsanitizer: maybe-all-stage2-gcc
configure-stage3-target-libsanitizer: maybe-all-stage3-gcc
@@ -46388,6 +46382,7 @@ configure-stage3-target-libvtv: maybe-all-stage3-gcc
configure-stage4-target-libvtv: maybe-all-stage4-gcc
configure-stageprofile-target-libvtv: maybe-all-stageprofile-gcc
configure-stagefeedback-target-libvtv: maybe-all-stagefeedback-gcc
+configure-target-libcilkrts: stage_last
configure-target-libssp: stage_last
configure-target-newlib: stage_last
configure-stage1-target-libgcc: maybe-all-stage1-gcc
@@ -46422,9 +46417,9 @@ configure-target-libatomic: stage_last
@if gcc-no-bootstrap
configure-target-libstdc++-v3: maybe-all-gcc
-configure-target-libmudflap: maybe-all-gcc
configure-target-libsanitizer: maybe-all-gcc
configure-target-libvtv: maybe-all-gcc
+configure-target-libcilkrts: maybe-all-gcc
configure-target-libssp: maybe-all-gcc
configure-target-newlib: maybe-all-gcc
configure-target-libgcc: maybe-all-gcc
@@ -47223,6 +47218,8 @@ install-target-libsanitizer: maybe-install-target-libstdc++-v3
install-target-libsanitizer: maybe-install-target-libgcc
install-target-libvtv: maybe-install-target-libstdc++-v3
install-target-libvtv: maybe-install-target-libgcc
+install-target-libcilkrts: maybe-install-target-libstdc++-v3
+install-target-libcilkrts: maybe-install-target-libgcc
install-target-libjava: maybe-install-target-libgcc
install-target-libitm: maybe-install-target-libgcc
install-target-libobjc: maybe-install-target-libgcc
@@ -47268,9 +47265,9 @@ configure-stagefeedback-target-libgomp: maybe-all-stagefeedback-target-libgcc
@if gcc-no-bootstrap
configure-target-libstdc++-v3: maybe-all-target-libgcc
-configure-target-libmudflap: maybe-all-target-libgcc
configure-target-libsanitizer: maybe-all-target-libgcc
configure-target-libvtv: maybe-all-target-libgcc
+configure-target-libcilkrts: maybe-all-target-libgcc
configure-target-libssp: maybe-all-target-libgcc
configure-target-newlib: maybe-all-target-libgcc
configure-target-libbacktrace: maybe-all-target-libgcc
@@ -47295,12 +47292,13 @@ configure-target-libatomic: maybe-all-target-libgcc
configure-target-libstdc++-v3: maybe-all-target-newlib maybe-all-target-libgloss
-configure-target-libmudflap: maybe-all-target-newlib maybe-all-target-libgloss
-
configure-target-libsanitizer: maybe-all-target-newlib maybe-all-target-libgloss
configure-target-libvtv: maybe-all-target-newlib maybe-all-target-libgloss
+configure-target-libcilkrts: maybe-all-target-newlib maybe-all-target-libgloss
+configure-target-libcilkrts: maybe-all-target-libstdc++-v3
+
configure-target-libssp: maybe-all-target-newlib maybe-all-target-libgloss
diff --git a/Makefile.tpl b/Makefile.tpl
index 3233a788d8d..92f3f6156c6 100644
--- a/Makefile.tpl
+++ b/Makefile.tpl
@@ -169,7 +169,7 @@ BUILD_EXPORTS = \
WINDMC="$(WINDMC_FOR_BUILD)"; export WINDMC;
# These variables must be set on the make command line for directories
-# built for the build system to override those in BASE_FLAGS_TO_PASSS.
+# built for the build system to override those in BASE_FLAGS_TO_PASS.
EXTRA_BUILD_FLAGS = \
CFLAGS="$(CFLAGS_FOR_BUILD)" \
LDFLAGS="$(LDFLAGS_FOR_BUILD)"
@@ -451,8 +451,10 @@ STAGE1_LANGUAGES = @stage1_languages@
# the last argument when conflicting --enable arguments are passed.
# * Likewise, we force-disable coverage flags, since the installed
# compiler probably has never heard of them.
+# * We also disable -Wformat, since older GCCs don't understand newer %s.
STAGE1_CONFIGURE_FLAGS = --disable-intermodule $(STAGE1_CHECKING) \
- --disable-coverage --enable-languages="$(STAGE1_LANGUAGES)"
+ --disable-coverage --enable-languages="$(STAGE1_LANGUAGES)" \
+ --disable-build-format-warnings
STAGEprofile_CFLAGS = $(STAGE2_CFLAGS) -fprofile-generate
STAGEprofile_TFLAGS = $(STAGE2_TFLAGS)
@@ -1404,13 +1406,6 @@ ENDIF raw_cxx +]
[+ ENDFOR recursive_targets +]
[+ ENDFOR target_modules +]
-@if target-libmudflap
-.PHONY: check-target-libmudflap-c++
-check-target-libmudflap-c++:
- $(MAKE) RUNTESTFLAGS="$(RUNTESTFLAGS) c++frags.exp" check-target-libmudflap
-
-@endif target-libmudflap
-
@if target-libgomp
.PHONY: check-target-libgomp-c++
check-target-libgomp-c++:
diff --git a/boehm-gc/ChangeLog b/boehm-gc/ChangeLog
index 0cd4dbec4d5..cb097bcce68 100644
--- a/boehm-gc/ChangeLog
+++ b/boehm-gc/ChangeLog
@@ -1,4 +1,8 @@
-2013-09-04 Matthias Klose <doko@ubuntu.com>
+2013-09-20 Alan Modra <amodra@gmail.com>
+
+ * configure: Regenerate.
+
+2013-09-04 Matthias Klose <doko@ubuntu.com>
* Makefile.am (libgcjgc_la_LIBADD): Add EXTRA_TEST_LIBS.
* Makefile.in: Regenerate.
diff --git a/boehm-gc/configure b/boehm-gc/configure
index 6020e9884eb..025003cac13 100755
--- a/boehm-gc/configure
+++ b/boehm-gc/configure
@@ -6770,7 +6770,7 @@ ia64-*-hpux*)
rm -rf conftest*
;;
-x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \
+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
@@ -6795,7 +6795,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
;;
esac
;;
- ppc64-*linux*|powerpc64-*linux*)
+ powerpc64le-*linux*)
+ LD="${LD-ld} -m elf32lppclinux"
+ ;;
+ powerpc64-*linux*)
LD="${LD-ld} -m elf32ppclinux"
;;
s390x-*linux*)
@@ -6814,7 +6817,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
x86_64-*linux*)
LD="${LD-ld} -m elf_x86_64"
;;
- ppc*-*linux*|powerpc*-*linux*)
+ powerpcle-*linux*)
+ LD="${LD-ld} -m elf64lppc"
+ ;;
+ powerpc-*linux*)
LD="${LD-ld} -m elf64ppc"
;;
s390*-*linux*|s390*-*tpf*)
@@ -11312,7 +11318,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11315 "configure"
+#line 11321 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -11418,7 +11424,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11421 "configure"
+#line 11427 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
diff --git a/config.guess b/config.guess
index 0aee6044d30..b79252d6b10 100755
--- a/config.guess
+++ b/config.guess
@@ -1,10 +1,8 @@
#! /bin/sh
# Attempt to guess a canonical system name.
-# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
-# 2011, 2012, 2013 Free Software Foundation, Inc.
+# Copyright 1992-2013 Free Software Foundation, Inc.
-timestamp='2012-12-30'
+timestamp='2013-06-10'
# 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
@@ -52,9 +50,7 @@ version="\
GNU config.guess ($timestamp)
Originally written by Per Bothner.
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011,
-2012, 2013 Free Software Foundation, Inc.
+Copyright 1992-2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -136,6 +132,27 @@ UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+case "${UNAME_SYSTEM}" in
+Linux|GNU|GNU/*)
+ # If the system lacks a compiler, then just pick glibc.
+ # We could probably try harder.
+ LIBC=gnu
+
+ eval $set_cc_for_build
+ cat <<-EOF > $dummy.c
+ #include <features.h>
+ #if defined(__UCLIBC__)
+ LIBC=uclibc
+ #elif defined(__dietlibc__)
+ LIBC=dietlibc
+ #else
+ LIBC=gnu
+ #endif
+ EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'`
+ ;;
+esac
+
# Note: order is significant - the case branches are not exclusive.
case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
@@ -857,21 +874,21 @@ EOF
exit ;;
*:GNU:*:*)
# the GNU system
- echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
exit ;;
*:GNU/*:*:*)
# other systems with GNU libc and userland
- echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+ echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC}
exit ;;
i*86:Minix:*:*)
echo ${UNAME_MACHINE}-pc-minix
exit ;;
aarch64:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
aarch64_be:Linux:*:*)
UNAME_MACHINE=aarch64_be
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
alpha:Linux:*:*)
case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
@@ -884,59 +901,54 @@ EOF
EV68*) UNAME_MACHINE=alphaev68 ;;
esac
objdump --private-headers /bin/sh | grep -q ld.so.1
- if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
- echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+ if test "$?" = 0 ; then LIBC="gnulibc1" ; fi
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ arc:Linux:*:* | arceb:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
arm*:Linux:*:*)
eval $set_cc_for_build
if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ARM_EABI__
then
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
else
if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ARM_PCS_VFP
then
- echo ${UNAME_MACHINE}-unknown-linux-gnueabi
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi
else
- echo ${UNAME_MACHINE}-unknown-linux-gnueabihf
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf
fi
fi
exit ;;
avr32*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
cris:Linux:*:*)
- echo ${UNAME_MACHINE}-axis-linux-gnu
+ echo ${UNAME_MACHINE}-axis-linux-${LIBC}
exit ;;
crisv32:Linux:*:*)
- echo ${UNAME_MACHINE}-axis-linux-gnu
+ echo ${UNAME_MACHINE}-axis-linux-${LIBC}
exit ;;
frv:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
hexagon:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
i*86:Linux:*:*)
- LIBC=gnu
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
- #ifdef __dietlibc__
- LIBC=dietlibc
- #endif
-EOF
- eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'`
- echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
+ echo ${UNAME_MACHINE}-pc-linux-${LIBC}
exit ;;
ia64:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
m32r*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
m68*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
mips:Linux:*:* | mips64:Linux:*:*)
eval $set_cc_for_build
@@ -955,54 +967,63 @@ EOF
#endif
EOF
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
- test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+ test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
;;
+ or1k:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
or32:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
padre:Linux:*:*)
- echo sparc-unknown-linux-gnu
+ echo sparc-unknown-linux-${LIBC}
exit ;;
parisc64:Linux:*:* | hppa64:Linux:*:*)
- echo hppa64-unknown-linux-gnu
+ echo hppa64-unknown-linux-${LIBC}
exit ;;
parisc:Linux:*:* | hppa:Linux:*:*)
# Look for CPU level
case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
- PA7*) echo hppa1.1-unknown-linux-gnu ;;
- PA8*) echo hppa2.0-unknown-linux-gnu ;;
- *) echo hppa-unknown-linux-gnu ;;
+ PA7*) echo hppa1.1-unknown-linux-${LIBC} ;;
+ PA8*) echo hppa2.0-unknown-linux-${LIBC} ;;
+ *) echo hppa-unknown-linux-${LIBC} ;;
esac
exit ;;
ppc64:Linux:*:*)
- echo powerpc64-unknown-linux-gnu
+ echo powerpc64-unknown-linux-${LIBC}
exit ;;
ppc:Linux:*:*)
- echo powerpc-unknown-linux-gnu
+ echo powerpc-unknown-linux-${LIBC}
+ exit ;;
+ ppc64le:Linux:*:*)
+ echo powerpc64le-unknown-linux-${LIBC}
+ exit ;;
+ ppcle:Linux:*:*)
+ echo powerpcle-unknown-linux-${LIBC}
exit ;;
s390:Linux:*:* | s390x:Linux:*:*)
- echo ${UNAME_MACHINE}-ibm-linux
+ echo ${UNAME_MACHINE}-ibm-linux-${LIBC}
exit ;;
sh64*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
sh*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
sparc:Linux:*:* | sparc64:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
tile*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
vax:Linux:*:*)
- echo ${UNAME_MACHINE}-dec-linux-gnu
+ echo ${UNAME_MACHINE}-dec-linux-${LIBC}
exit ;;
x86_64:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
xtensa*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
i*86:DYNIX/ptx:4*:*)
# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
@@ -1235,19 +1256,21 @@ EOF
exit ;;
*:Darwin:*:*)
UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
- case $UNAME_PROCESSOR in
- i386)
- eval $set_cc_for_build
- if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
- if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
- (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
- grep IS_64BIT_ARCH >/dev/null
- then
- UNAME_PROCESSOR="x86_64"
- fi
- fi ;;
- unknown) UNAME_PROCESSOR=powerpc ;;
- esac
+ eval $set_cc_for_build
+ if test "$UNAME_PROCESSOR" = unknown ; then
+ UNAME_PROCESSOR=powerpc
+ fi
+ if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+ if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
+ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+ grep IS_64BIT_ARCH >/dev/null
+ then
+ case $UNAME_PROCESSOR in
+ i386) UNAME_PROCESSOR=x86_64 ;;
+ powerpc) UNAME_PROCESSOR=powerpc64 ;;
+ esac
+ fi
+ fi
echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
exit ;;
*:procnto*:*:* | *:QNX:[0123456789]*:*)
diff --git a/config.sub b/config.sub
index 707e9e2efe8..61cb4bc22db 100755
--- a/config.sub
+++ b/config.sub
@@ -1,10 +1,8 @@
#! /bin/sh
# Configuration validation subroutine script.
-# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
-# 2011, 2012, 2013 Free Software Foundation, Inc.
+# Copyright 1992-2013 Free Software Foundation, Inc.
-timestamp='2013-01-11'
+timestamp='2013-10-01'
# 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
@@ -70,9 +68,7 @@ Report bugs and patches to <config-patches@gnu.org>."
version="\
GNU config.sub ($timestamp)
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011,
-2012, 2013 Free Software Foundation, Inc.
+Copyright 1992-2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -256,12 +252,12 @@ case $basic_machine in
| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
| am33_2.0 \
- | arc \
+ | arc | arceb \
| arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
| avr | avr32 \
| be32 | be64 \
| bfin \
- | c4x | clipper \
+ | c4x | c8051 | clipper \
| d10v | d30v | dlx | dsp16xx \
| epiphany \
| fido | fr30 | frv \
@@ -269,6 +265,7 @@ case $basic_machine in
| hexagon \
| i370 | i860 | i960 | ia64 \
| ip2k | iq2000 \
+ | k1om \
| le32 | le64 \
| lm32 \
| m32c | m32r | m32rle | m68000 | m68k | m88k \
@@ -297,10 +294,10 @@ case $basic_machine in
| mt \
| msp430 \
| nds32 | nds32le | nds32be \
- | nios | nios2 \
+ | nios | nios2 | nios2eb | nios2el \
| ns16k | ns32k \
| open8 \
- | or32 \
+ | or1k | or32 \
| pdp10 | pdp11 | pj | pjl \
| powerpc | powerpc64 | powerpc64le | powerpcle \
| pyramid \
@@ -328,7 +325,7 @@ case $basic_machine in
c6x)
basic_machine=tic6x-unknown
;;
- m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip)
+ m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)
basic_machine=$basic_machine-unknown
os=-none
;;
@@ -370,13 +367,13 @@ case $basic_machine in
| aarch64-* | aarch64_be-* \
| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
- | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
| avr-* | avr32-* \
| be32-* | be64-* \
| bfin-* | bs2000-* \
| c[123]* | c30-* | [cjt]90-* | c4x-* \
- | clipper-* | craynv-* | cydra-* \
+ | c8051-* | clipper-* | craynv-* | cydra-* \
| d10v-* | d30v-* | dlx-* \
| elxsi-* \
| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
@@ -385,6 +382,7 @@ case $basic_machine in
| hexagon-* \
| i*86-* | i860-* | i960-* | ia64-* \
| ip2k-* | iq2000-* \
+ | k1om-* \
| le32-* | le64-* \
| lm32-* \
| m32c-* | m32r-* | m32rle-* \
@@ -414,7 +412,7 @@ case $basic_machine in
| mt-* \
| msp430-* \
| nds32-* | nds32le-* | nds32be-* \
- | nios-* | nios2-* \
+ | nios-* | nios2-* | nios2eb-* | nios2el-* \
| none-* | np1-* | ns16k-* | ns32k-* \
| open8-* \
| orion-* \
@@ -798,7 +796,7 @@ case $basic_machine in
os=-mingw64
;;
mingw32)
- basic_machine=i386-pc
+ basic_machine=i686-pc
os=-mingw32
;;
mingw32ce)
@@ -834,7 +832,7 @@ case $basic_machine in
basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
;;
msys)
- basic_machine=i386-pc
+ basic_machine=i686-pc
os=-msys
;;
mvs)
@@ -1550,6 +1548,9 @@ case $basic_machine in
c4x-* | tic4x-*)
os=-coff
;;
+ c8051-*)
+ os=-elf
+ ;;
hexagon-*)
os=-elf
;;
@@ -1593,6 +1594,9 @@ case $basic_machine in
mips*-*)
os=-elf
;;
+ or1k-*)
+ os=-elf
+ ;;
or32-*)
os=-coff
;;
diff --git a/config/ChangeLog b/config/ChangeLog
index ab34cbcc224..e3f6f456695 100644
--- a/config/ChangeLog
+++ b/config/ChangeLog
@@ -1,3 +1,9 @@
+2013-09-29 Iain Sandoe <iain@codesourcery.com>
+
+ * mh-darwin (BOOT_CFLAGS): Only add -mdynamic-no-pic for m32 hosts.
+ (STAGE1_CFLAGS, STAGE1_LDFLAGS): New.
+ Fix over-length lines and amend comments.
+
2013-08-30 Marek Polacek <polacek@redhat.com>
* bootstrap-ubsan.mk: New.
diff --git a/config/mh-darwin b/config/mh-darwin
index 19bf26568b5..a039f201410 100644
--- a/config/mh-darwin
+++ b/config/mh-darwin
@@ -1,7 +1,18 @@
# The -mdynamic-no-pic ensures that the compiler executable is built without
# position-independent-code -- the usual default on Darwin. This fix speeds
# compiles by 3-5%.
-BOOT_CFLAGS += -mdynamic-no-pic
+BOOT_CFLAGS += \
+`case ${host} in i?86-*-darwin* | powerpc-*-darwin*) \
+ echo -mdynamic-no-pic ;; esac;`
-# Ensure we don't try and use -pie, as it is incompatible with pch.
-BOOT_LDFLAGS += `case ${host} in *-*-darwin[1][1-9]*) echo -Wl,-no_pie ;; esac;`
+# ld on Darwin versions >= 10.7 defaults to PIE executables. Disable this for
+# gcc components, since it is incompatible with our pch implementation.
+BOOT_LDFLAGS += \
+`case ${host} in *-*-darwin[1][1-9]*) echo -Wl,-no_pie ;; esac;`
+
+# Similarly, for cross-compilation.
+STAGE1_CFLAGS += \
+`case ${host} in i?86-*-darwin* | powerpc-*-darwin*)\
+ echo -mdynamic-no-pic ;; esac;`
+STAGE1_LDFLAGS += \
+`case ${host} in *-*-darwin[1][1-9]*) echo -Wl,-no_pie ;; esac;`
diff --git a/configure b/configure
index a91689ff419..d4a82137bad 100755
--- a/configure
+++ b/configure
@@ -556,6 +556,7 @@ enable_option_checking=no
ac_subst_vars='LTLIBOBJS
LIBOBJS
compare_exclusions
+host_shared
stage2_werror_flag
stage1_checking
stage1_cflags
@@ -787,6 +788,7 @@ with_build_time_tools
enable_maintainer_mode
enable_stage1_checking
enable_werror
+enable_host_shared
'
ac_precious_vars='build_alias
host_alias
@@ -1490,6 +1492,7 @@ Optional Features:
choose additional checking for stage1 of the
compiler
--enable-werror enable -Werror in bootstrap stage2 and later
+ --enable-host-shared build host code as shared libraries
Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
@@ -2769,10 +2772,10 @@ target_libraries="target-libgcc \
target-libgloss \
target-newlib \
target-libgomp \
+ target-libcilkrts \
target-libatomic \
target-libitm \
target-libstdc++-v3 \
- target-libmudflap \
target-libsanitizer \
target-libvtv \
target-libssp \
@@ -3125,22 +3128,6 @@ if test x$enable_static_libjava != xyes ; then
fi
-# Disable libmudflap on some systems.
-if test x$enable_libmudflap = x ; then
- case "${target}" in
- *-*-linux* | *-*-gnu* | *-*-k*bsd*-gnu | bfin*-*-uclinux* | *-*-kopensolaris*-gnu)
- # Enable libmudflap by default in GNU and friends.
- ;;
- *-*-freebsd*)
- # Enable libmudflap by default in FreeBSD.
- ;;
- *)
- # Disable it by default everywhere else.
- noconfigdirs="$noconfigdirs target-libmudflap"
- ;;
- esac
-fi
-
# Disable libgomp on non POSIX hosted systems.
if test x$enable_libgomp = x ; then
# Enable libgomp by default on hosted POSIX systems.
@@ -3178,6 +3165,25 @@ $as_echo "yes" >&6; }
fi
fi
+# Disable libcilkrts on unsupported systems.
+if test -d ${srcdir}/libcilkrts; then
+ if test x$enable_libcilkrts = x; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libcilkrts support" >&5
+$as_echo_n "checking for libcilkrts support... " >&6; }
+ if (srcdir=${srcdir}/libcilkrts; \
+ . ${srcdir}/configure.tgt; \
+ test -n "$UNSUPPORTED")
+ then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ noconfigdirs="$noconfigdirs target-libcilkrts"
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ fi
+ fi
+fi
+
# Disable libitm on unsupported systems.
if test -d ${srcdir}/libitm; then
if test x$enable_libitm = x; then
@@ -3620,7 +3626,7 @@ case "${target}" in
sh*-*-pe|mips*-*-pe|*arm-wince-pe)
noconfigdirs="$noconfigdirs tcl tk itcl libgui sim"
;;
- arc-*-*)
+ arc-*-*|arceb-*-*)
noconfigdirs="$noconfigdirs target-libgloss"
;;
arm-*-pe*)
@@ -6624,7 +6630,7 @@ esac
case ,${enable_languages}, in
*,c++,*) ;;
*)
- noconfigdirs="$noconfigdirs target-libitm target-libsanitizer target-libvtv"
+ noconfigdirs="$noconfigdirs target-libcilkrts target-libitm target-libsanitizer target-libvtv"
;;
esac
@@ -14570,6 +14576,16 @@ case ${enable_werror} in
esac
+# Enable --enable-host-shared.
+# Check whether --enable-host-shared was given.
+if test "${enable_host_shared+set}" = set; then :
+ enableval=$enable_host_shared; host_shared=$enableval
+else
+ host_shared=no
+fi
+
+
+
# Specify what files to not compare during bootstrap.
compare_exclusions="gcc/cc*-checksum\$(objext) | gcc/ada/*tools/*"
diff --git a/configure.ac b/configure.ac
index d72b40a7af9..30190d65bea 100644
--- a/configure.ac
+++ b/configure.ac
@@ -156,10 +156,10 @@ target_libraries="target-libgcc \
target-libgloss \
target-newlib \
target-libgomp \
+ target-libcilkrts \
target-libatomic \
target-libitm \
target-libstdc++-v3 \
- target-libmudflap \
target-libsanitizer \
target-libvtv \
target-libssp \
@@ -473,22 +473,6 @@ if test x$enable_static_libjava != xyes ; then
fi
AC_SUBST(EXTRA_CONFIGARGS_LIBJAVA)
-# Disable libmudflap on some systems.
-if test x$enable_libmudflap = x ; then
- case "${target}" in
- *-*-linux* | *-*-gnu* | *-*-k*bsd*-gnu | bfin*-*-uclinux* | *-*-kopensolaris*-gnu)
- # Enable libmudflap by default in GNU and friends.
- ;;
- *-*-freebsd*)
- # Enable libmudflap by default in FreeBSD.
- ;;
- *)
- # Disable it by default everywhere else.
- noconfigdirs="$noconfigdirs target-libmudflap"
- ;;
- esac
-fi
-
# Disable libgomp on non POSIX hosted systems.
if test x$enable_libgomp = x ; then
# Enable libgomp by default on hosted POSIX systems.
@@ -523,6 +507,22 @@ if test -d ${srcdir}/libatomic; then
fi
fi
+# Disable libcilkrts on unsupported systems.
+if test -d ${srcdir}/libcilkrts; then
+ if test x$enable_libcilkrts = x; then
+ AC_MSG_CHECKING([for libcilkrts support])
+ if (srcdir=${srcdir}/libcilkrts; \
+ . ${srcdir}/configure.tgt; \
+ test -n "$UNSUPPORTED")
+ then
+ AC_MSG_RESULT([no])
+ noconfigdirs="$noconfigdirs target-libcilkrts"
+ else
+ AC_MSG_RESULT([yes])
+ fi
+ fi
+fi
+
# Disable libitm on unsupported systems.
if test -d ${srcdir}/libitm; then
if test x$enable_libitm = x; then
@@ -956,7 +956,7 @@ case "${target}" in
sh*-*-pe|mips*-*-pe|*arm-wince-pe)
noconfigdirs="$noconfigdirs tcl tk itcl libgui sim"
;;
- arc-*-*)
+ arc-*-*|arceb-*-*)
noconfigdirs="$noconfigdirs target-libgloss"
;;
arm-*-pe*)
@@ -2061,7 +2061,7 @@ esac
case ,${enable_languages}, in
*,c++,*) ;;
*)
- noconfigdirs="$noconfigdirs target-libitm target-libsanitizer target-libvtv"
+ noconfigdirs="$noconfigdirs target-libcilkrts target-libitm target-libsanitizer target-libvtv"
;;
esac
@@ -3301,6 +3301,13 @@ case ${enable_werror} in
esac
AC_SUBST(stage2_werror_flag)
+# Enable --enable-host-shared.
+AC_ARG_ENABLE(host-shared,
+[AS_HELP_STRING([--enable-host-shared],
+ [build host code as shared libraries])],
+[host_shared=$enableval], [host_shared=no])
+AC_SUBST(host_shared)
+
# Specify what files to not compare during bootstrap.
compare_exclusions="gcc/cc*-checksum\$(objext) | gcc/ada/*tools/*"
diff --git a/contrib/ChangeLog b/contrib/ChangeLog
index 931bb87bc24..3b0d76349e2 100644
--- a/contrib/ChangeLog
+++ b/contrib/ChangeLog
@@ -1,3 +1,25 @@
+2013-10-31 Chung-Ju Wu <jasonwucj@gmail.com>
+
+ * config-list.mk (nds32le-elf, nds32be-elf): Add nds32 target.
+
+2013-10-29 Tobias Burnus <burnus@net-b.de>
+
+ * gcc_update (files_and_dependencies): Add rules for
+ libcilkrts.
+
+2013-10-11 Thomas Schwinge <thomas@codesourcery.com>
+
+ * gcc_update (files_and_dependencies): Fix rule for
+ libgomp/testsuite/Makefile.in.
+
+2013-10-01 Joern Rennecke <joern.rennecke@embecosm.com>
+
+ * config-list.mk: Add arc configurations.
+
+2013-09-27 Diego Novillo <dnovillo@google.com>
+
+ * testsuite-management/x86_64-unknown-linux-gnu.xfail: Update.
+
2013-09-12 DJ Delorie <dj@redhat.com>
* config-list.mk: Add msp430-elf.
@@ -10,7 +32,7 @@
* gcc_update (configure): Update to handle svn 1.8.1.
-2013-08-03 Caroline Tice4 <cmtice@google.com>
+2013-08-03 Caroline Tice <cmtice@google.com>
* gcc_update: Add libvtv files.
diff --git a/contrib/config-list.mk b/contrib/config-list.mk
index 85ca6ad13e0..23d6e4aadda 100644
--- a/contrib/config-list.mk
+++ b/contrib/config-list.mk
@@ -14,6 +14,8 @@ TEST=all-gcc
LIST = aarch64-elf aarch64-linux-gnu \
alpha-linux-gnu alpha-freebsd6 alpha-netbsd alpha-openbsd \
alpha64-dec-vms alpha-dec-vms am33_2.0-linux \
+ arc-elf32OPT-with-cpu=arc600 arc-elf32OPT-with-cpu=arc700 \
+ arc-linux-uclibcOPT-with-cpu=arc700 arceb-linux-uclibcOPT-with-cpu=arc700 \
arm-wrs-vxworks arm-netbsdelf \
arm-linux-androideabi arm-uclinux_eabi arm-eabi \
arm-symbianelf avr-rtems avr-elf \
@@ -45,6 +47,7 @@ LIST = aarch64-elf aarch64-linux-gnu \
mips-wrs-vxworks mipstx39-elf mmix-knuth-mmixware mn10300-elf moxie-elf \
moxie-uclinux moxie-rtems pdp11-aout picochip-elfOPT-enable-obsolete \
msp430-elf \
+ nds32le-elf nds32be-elf \
powerpc-darwin8 \
powerpc-darwin7 powerpc64-darwin powerpc-freebsd6 powerpc-netbsd \
powerpc-eabispe powerpc-eabisimaltivec powerpc-eabisim ppc-elf \
diff --git a/contrib/gcc_update b/contrib/gcc_update
index bdf89c4d128..499e5ef6528 100755
--- a/contrib/gcc_update
+++ b/contrib/gcc_update
@@ -139,7 +139,7 @@ libcpp/Makefile.in: libcpp/configure.ac libcpp/aclocal.m4
libcpp/configure: libcpp/configure.ac libcpp/aclocal.m4
libgomp/aclocal.m4: libgomp/configure.ac libgomp/acinclude.m4
libgomp/Makefile.in: libgomp/Makefile.am libgomp/aclocal.m4
-libgomp/testsuite/Makefile.in: libgomp/Makefile.am libgomp/aclocal.m4
+libgomp/testsuite/Makefile.in: libgomp/testsuite/Makefile.am libgomp/aclocal.m4
libgomp/configure: libgomp/configure.ac libgomp/aclocal.m4
libgomp/config.h.in: libgomp/configure.ac libgomp/aclocal.m4
libitm/aclocal.m4: libitm/configure.ac libitm/acinclude.m4
@@ -161,6 +161,9 @@ libsanitizer/sanitizer_common/Makefile.in: libsanitizer/sanitizer_common/Makefil
libvtv/aclocal.m4: libvtv/configure.ac libvtv/acinclude.m4
libvtv/Makefile.in: libvtv/Makefile.am libvtv/aclocal.m4
libvtv/configure: libvtv/configure.ac libvtv/aclocal.m4
+libcilkrts/aclocal.m4: libcilkrts/configure.ac
+libcilkrts/Makefile.in: libcilkrts/Makefile.am
+libcilkrts/configure: libcilkrts/configure.ac
# Top level
Makefile.in: Makefile.tpl Makefile.def
configure: configure.ac config/acx.m4
diff --git a/contrib/testsuite-management/x86_64-unknown-linux-gnu.xfail b/contrib/testsuite-management/x86_64-unknown-linux-gnu.xfail
index 32f2b0d04ce..fdb8268550f 100644
--- a/contrib/testsuite-management/x86_64-unknown-linux-gnu.xfail
+++ b/contrib/testsuite-management/x86_64-unknown-linux-gnu.xfail
@@ -1,7 +1,6 @@
FAIL: g++.dg/guality/pr55665.C -O2 line 23 p == 40
FAIL: g++.dg/guality/pr55665.C -O3 -fomit-frame-pointer line 23 p == 40
FAIL: g++.dg/guality/pr55665.C -O3 -g line 23 p == 40
-FAIL: gcc.dg/attr-ifunc-4.c execution test
XPASS: gcc.dg/guality/example.c -O0 execution test
XPASS: gcc.dg/guality/example.c -O2 execution test
XPASS: gcc.dg/guality/example.c -O2 -flto -fno-use-linker-plugin -flto-partition=none execution test
@@ -100,23 +99,11 @@ FAIL: gcc.dg/guality/vla-2.c -O2 -flto -fno-use-linker-plugin -flto-partition=no
FAIL: gcc.dg/guality/vla-2.c -O2 -flto -fno-use-linker-plugin -flto-partition=none line 25 sizeof (a) == 6 * sizeof (int)
FAIL: gcc.dg/guality/vla-2.c -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects line 16 sizeof (a) == 5 * sizeof (int)
FAIL: gcc.dg/guality/vla-2.c -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects line 25 sizeof (a) == 6 * sizeof (int)
-FAIL: gcc.dg/lto/20090218-1 c_lto_20090218-1_0.o-c_lto_20090218-1_1.o link, -O0 -flto -flto-partition=none -fuse-linker-plugin
-UNRESOLVED: gcc.dg/lto/20090218-1 c_lto_20090218-1_0.o-c_lto_20090218-1_1.o execute -O0 -flto -flto-partition=none -fuse-linker-plugin
-FAIL: gcc.dg/lto/20090218-1 c_lto_20090218-1_0.o-c_lto_20090218-1_1.o link, -O0 -flto -flto-partition=1to1 -fno-use-linker-plugin
-UNRESOLVED: gcc.dg/lto/20090218-1 c_lto_20090218-1_0.o-c_lto_20090218-1_1.o execute -O0 -flto -flto-partition=1to1 -fno-use-linker-plugin
-FAIL: gcc.dg/lto/20090218-1 c_lto_20090218-1_0.o-c_lto_20090218-1_1.o link, -O0 -flto -fuse-linker-plugin -fno-fat-lto-objects
-UNRESOLVED: gcc.dg/lto/20090218-1 c_lto_20090218-1_0.o-c_lto_20090218-1_1.o execute -O0 -flto -fuse-linker-plugin -fno-fat-lto-objects
-FAIL: gfortran.dg/round_4.f90 -O0 execution test
-FAIL: gfortran.dg/round_4.f90 -O1 execution test
-FAIL: gfortran.dg/round_4.f90 -O2 execution test
-FAIL: gfortran.dg/round_4.f90 -O3 -fomit-frame-pointer execution test
-FAIL: gfortran.dg/round_4.f90 -O3 -fomit-frame-pointer -funroll-loops execution test
-FAIL: gfortran.dg/round_4.f90 -O3 -fomit-frame-pointer -funroll-all-loops -finline-functions execution test
-FAIL: gfortran.dg/round_4.f90 -O3 -g execution test
-FAIL: gfortran.dg/round_4.f90 -Os execution test
+FAIL: gcc.dg/tree-ssa/slsr-39.c scan-tree-dump-times slsr "MEM" 4
FAIL: libmudflap.c++/pass41-frag.cxx ( -O) execution test
FAIL: libmudflap.c++/pass41-frag.cxx (-O2) execution test
FAIL: libmudflap.c++/pass41-frag.cxx (-O3) execution test
+FAIL: libmudflap.c++/pass55-frag.cxx (-O3) execution test
FAIL: sourcelocation output - source compiled test
FAIL: sourcelocation -findirect-dispatch output - source compiled test
FAIL: sourcelocation -O3 output - source compiled test
diff --git a/fixincludes/ChangeLog b/fixincludes/ChangeLog
index 4a9d22997ff..925423c3822 100644
--- a/fixincludes/ChangeLog
+++ b/fixincludes/ChangeLog
@@ -1,3 +1,7 @@
+2013-09-20 Alan Modra <amodra@gmail.com>
+
+ * configure: Regenerate.
+
2013-09-02 David Edelsohn <dje.gcc@gmail.com>
* inclhack.def (aix_assert): New fix.
@@ -9,7 +13,7 @@
* inclhack.def (cdef_cplusplus): removed, per Bug 51776
* tests/base/sys/cdefs.h (CDEF_CPLUSPLUS_CHECK): obsolete
-2013-05-23 Alexander Ivchenko <alexander.ivchenko@intel.com>
+2013-05-23 Alexander Ivchenko <alexander.ivchenko@intel.com>
* inclhack.def (complier_h_tradcpp): New.
* fixincl.x: Rebuilt.
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index f02617bf926..9fcafb66865 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8040 @@
+2013-11-12 Bin Cheng <bin.cheng@arm.com>
+
+ * tree-ssa-loop-ivopts.c (force_expr_to_var_cost): Refactor the code.
+ Handle type conversion.
+
+2013-11-11 Martin Liska <marxin.liska@gmail.com>
+ Jan Hubicka <jh@suse.cz>
+
+ * cgraph.c (dump_cgraph_node): Profile dump added.
+ * cgraph.h (struct cgraph_node): New time profile variable added.
+ * cgraphclones.c (cgraph_clone_node): Time profile is cloned.
+ * gcov-io.h (gcov_type): New profiler type introduced.
+ * ipa-profile.c (lto_output_node): Streaming for time profile added.
+ (input_node): Time profiler is read from LTO stream.
+ * predict.c (maybe_hot_count_p): Hot prediction changed.
+ * profile.c (instrument_values): New case for time profiler added.
+ (compute_value_histograms): Read of time profile.
+ * tree-pretty-print.c (dump_function_header): Time profiler is dumped.
+ * tree-profile.c (init_ic_make_global_vars): Time profiler function added.
+ (gimple_init_edge_profiler): TP function instrumentation.
+ (gimple_gen_time_profiler): New.
+ * value-prof.c (gimple_add_histogram_value): Support for time profiler
+ added.
+ (dump_histogram_value): TP type added to dumps.
+ (visit_hist): More sensitive check that takes TP into account.
+ (gimple_find_values_to_profile): TP instrumentation.
+ * value-prof.h (hist_type): New histogram type added.
+ (struct histogram_value_t): Pointer to struct function added.
+ * libgcc/Makefile.in: New GCOV merge function for TP added.
+ * libgcov.c: function_counter variable introduced.
+ (_gcov_merge_time_profile): New.
+ (_gcov_time_profiler): New.
+
+2013-11-11 Marc Glisse <marc.glisse@inria.fr>
+ Jeff Law <law@redhat.com>
+
+ * tree-ssa-alias.c (stmt_kills_ref_p_1): Use
+ ao_ref_init_from_ptr_and_size for builtins.
+
+2013-11-11 Uros Bizjak <ubizjak@gmail.com>
+ H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/58853
+ * config/i386/x86-tune.def
+ (X86_TUNE_MISALIGNED_MOVE_STRING_PRO_EPILOGUES): Rename from
+ TARGET_MISALIGNED_MOVE_STRING_PROLOGUES.
+ * config/i386/i386.h
+ (TARGET_MISALIGNED_MOVE_STRING_PRO_EPILOGUES): Rename from
+ TARGET_MISALIGNED_MOVE_STRING_PROLOGUES_EPILOGUES. Update for renamed
+ X86_TUNE_MISALIGNED_MOVE_STRING_PRO_EPILOGUES.
+ * config/i386/i386.c (ix86_expand_set_or_movmem): Use
+ TARGET_MISALIGNED_MOVE_STRING_PRO_EPILOGUES to calculate
+ misaligned_prologue_used. Check that
+ desired_aling <= epilogue_size_needed.
+
+2013-11-11 Cong Hou <congh@google.com>
+
+ PR tree-optimization/59050
+ * tree-vect-data-refs.c (comp_dr_addr_with_seg_len_pair): Bug fix.
+
+2013-11-11 Joern Rennecke <joern.rennecke@embecosm.com>
+
+ PR middle-end/59049
+ * expmed.c (emit_store_flag): Fail for const-const comparison.
+
+2013-11-11 Tristan Gingold <gingold@adacore.com>
+ Eric Botcazou <ebotcazou@adacore.com>
+
+ * tree.h (CONSTRUCTOR_NO_CLEARING): Define.
+ * tree-core.h (CONSTRUCTOR_NO_CLEARING): Document it.
+ * tree.def (CONSTRUCTOR): Likewise.
+ * doc/generic.texi (CONSTRUCTOR): Likewise. Update description.
+ * gimplify.c (gimplify_init_constructor): Do not clear the object when
+ the constructor is incomplete and CONSTRUCTOR_NO_CLEARING is set.
+
+2013-11-11 Basile Starynkevitch <basile@starynkevitch.net>
+
+ * toplev.c (toplev_main): Move PLUGIN_FINISH invocation before
+ diagnostic_finish.
+
+2013-11-11 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * config/arm/arm.c (arm_new_rtx_costs): Return after handling
+ comparisons.
+
+2013-11-11 Joern Rennecke <joern.rennecke@embecosm.com>
+
+ * config/arc/arc.h (LOGICAL_OP_NON_SHORT_CIRCUIT): Define.
+
+2013-11-08 Jeff Law <law@redhat.com>
+
+ * tree-ssa-threadupdate.c (mark_threaded_blocks): Truncate jump
+ threading paths first, then perform PHI node checks if applicable.
+
+2013-11-10 Karlson2k <k2k@narod.ru>
+ Kai Tietz <ktietz@redhat.com>
+
+ PR plugin/52872
+ * configure.ac: Adding for exported symbols check
+ and for rdynamic-check executable-extension.
+ * configure: Regenerated.
+
+2013-11-10 Uros Bizjak <ubizjak@gmail.com>
+
+ * mode-switching.c (optimize_mode_switching): Mark block as
+ nontransparent, if last_mode at block exit is different from no_mode.
+
+2013-11-09 Jan-Benedict Glaw <jbglaw@lug-owl.de>
+
+ * function.c (NAME__MAIN): Move to...
+ * cfgexpand.c (NAME__MAIN): ...here.
+
+2013-11-09 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * target.def (can_use_doloop_p): New hook.
+ * doc/tm.texi.in (TARGET_CAN_USE_DOLOOP_P): Add.
+ * doc/tm.texi: Regenerate.
+ * doc/md.texi (doloop_begin, doloop_end): Update documentation.
+ * hooks.h (hook_bool_dint_dint_uint_true): Declare.
+ * hooks.c (hook_bool_dint_dint_uint_true): New function.
+ * targhooks.h (can_use_doloop_if_innermost): Declare.
+ * targhooks.c (can_use_doloop_if_innermost): New function.
+ * target.h: Include double-int.h.
+ * loop-doloop.c (doloop_optimize): Call targetm.can_use_doloop_p.
+ Remove iteration count, maximum iteration count, loop depth and
+ enter-at-top inputs from doloop_begin and doloop_end.
+ * config/arc/arc.md (doloop_begin, doloop_end): Update for new
+ interface.
+ * config/arc/arc.c (arc_can_use_doloop_p): New function.
+ (TARGET_CAN_USE_DOLOOP_P): Define.
+ * config/arm/thumb2.md (doloop_end): Update for new interface.
+ * config/arm/arm.c (TARGET_CAN_USE_DOLOOP_P): Define.
+ * config/bfin/bfin.md (doloop_end): Update for new interface.
+ * config/bfin/bfin.c (bfin_can_use_doloop_p): New function.
+ (TARGET_CAN_USE_DOLOOP_P): Define.
+ * config/c6x/c6x.md (doloop_end): Update for new interface.
+ * config/ia64/ia64.md (doloop_end): Update for new interface.
+ * config/ia64/ia64.c (TARGET_CAN_USE_DOLOOP_P): Define.
+ * config/mep/mep.md (doloop_begin, doloop_end): Update for new
+ interface.
+ * config/mep/mep.c (mep_emit_doloop): Likewise.
+ (TARGET_CAN_USE_DOLOOP_P): Define.
+ * config/rs6000/rs6000.md (doloop_end): Update for new interface.
+ * config/rs6000/rs6000.c (TARGET_CAN_USE_DOLOOP_P): Define.
+ * config/s390/s390.md (doloop_end): Update for new interface.
+ * config/sh/sh.md (doloop_end): Likewise.
+ * config/spu/spu.md (doloop_end): Likewise.
+ * config/spu/spu.c (TARGET_CAN_USE_DOLOOP_P): Define.
+ * config/tilegx/tilegx.md (doloop_end): Update for new interface.
+ * config/tilegx/tilegx.c (TARGET_CAN_USE_DOLOOP_P): Define.
+ * config/tilepro/tilepro.md (doloop_end): Update for new interface.
+ * config/tilepro/tilepro.c (TARGET_CAN_USE_DOLOOP_P): Define.
+ * config/v850/v850.md (doloop_begin, doloop_end): Update for new
+ interface.
+ * config/v850/v850.c (TARGET_CAN_USE_DOLOOP_P): Define.
+
+2013-11-08 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR other/59055
+ * doc/extend.texi: Move Cilk Plus Builtins node before Other
+ Builtins node.
+
+2013-11-08 Andrew MacLeod <amacleod@redhat.com>
+ Joseph Myers <joseph@codesourcery.com>
+
+ * ginclude/stdatomic.h: New file.
+ * Makefile.in (USER_H): Add stdatomic.h.
+
+2013-11-08 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * config/arm/arm.c (arm_new_rtx_costs): Break after handling
+ comparisons.
+
+2013-11-08 Jeff Law <law@redhat.com>
+
+ * tree-ssa-threadupdate.h (delete_thread_path): Declare.
+ * tree-ssa-threadupdate.c (delete_thread_path): New function.
+ (ssa_redirect_edges, thread_block_1): Use it.
+ (thread_through_loop_header, mark_threaded_blocks): Likewise.
+ (thread_through_all_blocks, register_jump_thread): Likewise.
+ * tree-ssa-threadedge.c (thread_across_edge): Likewise.
+
+2013-11-08 James Greenhalgh <james.greenhalgh@arm.com>
+
+ * config/arm/aarch-common.c
+ (search_term): New typedef.
+ (shift_rtx_costs): New array.
+ (arm_rtx_shift_left_p): New.
+ (arm_find_sub_rtx_with_search_term): Likewise.
+ (arm_find_sub_rtx_with_code): Likewise.
+ (arm_early_load_addr_dep): Add sanity checking.
+ (arm_no_early_alu_shift_dep): Likewise.
+ (arm_no_early_alu_shift_value_dep): Likewise.
+ (arm_no_early_mul_dep): Likewise.
+ (arm_no_early_store_addr_dep): Likewise.
+
+2013-11-08 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/59047
+ * tree-predcom.c (ref_at_iteration): Handle bitfield accesses properly.
+
+2013-11-08 Ilya Enkovich <ilya.enkovich@intel.com>
+
+ * common.opt (fcheck-pointer-bounds): Move to ...
+ * c-family/c.opt: ... here.
+ * langhooks-def.h (LANG_HOOKS_CHKP_SUPPORTED): Remove.
+ (LANG_HOOKS_INITIALIZER): Remove LANG_HOOKS_CHKP_SUPPORTED.
+ * langhooks.h (lang_hooks): Remove chkp_supported field.
+ * toplev.c (process_options): Remove chkp_supported check.
+
+2013-11-08 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/59038
+ PR tree-optimization/58955
+ * tree-loop-distribution.c (pg_add_dependence_edges): Revert
+ previous change. Handle known dependences correctly.
+
+2013-11-08 Tom de Vries <tom@codesourcery.com>
+
+ * config/rs6000/t-xilinx: Remove duplicate contents.
+
+2013-11-07 Andrew MacLeod <amacleod@redhat.com>
+ Joseph Myers <joseph@codesourcery.com>
+
+ * tree-core.h (enum cv_qualifier): Add TYPE_QUAL_ATOMIC.
+ (enum tree_index): Add TI_ATOMICQI_TYPE, TI_ATOMICHI_TYPE,
+ TI_ATOMICSI_TYPE, TI_ATOMICDI_TYPE and TI_ATOMICTI_TYPE.
+ (struct tree_base): Add atomic_flag field.
+ * tree.h (TYPE_ATOMIC): New accessor macro.
+ (TYPE_QUALS, TYPE_QUALS_NO_ADDR_SPACE): Add TYPE_QUAL_ATOMIC.
+ (TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC): New macro.
+ (atomicQI_type_node, atomicHI_type_node, atomicSI_type_node)
+ (atomicDI_type_node, atomicTI_type_node): New macros for type nodes.
+ * tree.c (set_type_quals): Set TYPE_ATOMIC.
+ (find_atomic_core_type): New function.
+ (build_qualified_type): Adjust alignment for qualified types.
+ (build_atomic_base): New function
+ (build_common_tree_nodes): Build atomicQI_type_node,
+ atomicHI_type_node, atomicSI_type_node, atomicDI_type_node and
+ atomicTI_type_node.
+ * print-tree.c (print_node): Print atomic qualifier.
+ * tree-pretty-print.c (dump_generic_node): Print atomic type attribute.
+ * target.def (atomic_assign_expand_fenv): New hook.
+ * doc/tm.texi.in (TARGET_ATOMIC_ASSIGN_EXPAND_FENV): New @hook.
+ * doc/tm.texi: Regenerate.
+ * targhooks.c (default_atomic_assign_expand_fenv): New function.
+ * targhooks.h (default_atomic_assign_expand_fenv): Declare.
+ * sync-builtins.def (__atomic_feraiseexcept): New built-in function.
+ * config/i386/i386-builtin-types.def (VOID_FTYPE_PUSHORT): New
+ function type.
+ * config/i386/i386.c (enum ix86_builtins): Add
+ IX86_BUILTIN_FNSTENV, IX86_BUILTIN_FLDENV, IX86_BUILTIN_FNSTSW and
+ IX86_BUILTIN_FNCLEX.
+ (bdesc_special_args): Add __builtin_ia32_fnstenv,
+ __builtin_ia32_fldenv, __builtin_ia32_fnstsw and __builtin_ia32_fnclex.
+ (ix86_expand_builtin): Handle the new built-in functions.
+ (ix86_atomic_assign_expand_fenv): New function.
+ (TARGET_ATOMIC_ASSIGN_EXPAND_FENV): New macro.
+ * config/i386/i386.md (UNSPECV_FNSTENV, UNSPECV_FLDENV)
+ (UNSPECV_FNSTSW, UNSPECV_FNCLEX): New unspecs.
+ (fnstenv, fldenv, fnstsw, fnclex): New insns.
+
+2013-11-07 Steve Ellcey <sellcey@mips.com>
+
+ * config/mips/mti-linux.h (SYSROOT_SUFFIX_SPEC): Add fp64 directory.
+ * config/mips/t-mti-linux (MULTILIB_OPTIONS): Add -mfp64 flag.
+ (MULTILIB_DIRNAMES): Add fp64 directory.
+ (MULTILIB_EXCEPTIONS): Add new exclusions.
+
+2013-11-07 Aldy Hernandez <aldyh@redhat.com>
+
+ * gimplify.c (gimple_regimplify_operands): Do not set
+ SSA_NAME_DEF_STMT.
+ * graphite-sese-to-poly.c (remove_simple_copy_phi): Same.
+ (rewrite_close_phi_out_of_ssa): Same.
+ (rewrite_phi_out_of_ssa): Same.
+ (rewrite_degenerate_phi): Same.
+ (handle_scalar_deps_crossing_scop_limits): Same.
+ * tree-if-conv.c (predicate_scalar_phi): Same.
+ * tree-parloops.c (create_loads_for_reductions): Same.
+ (create_final_loads_for_reduction): Same.
+ (create_loads_and_stores_for_name): Same.
+ (transform_to_exit_first_loop): Same.
+ (create_parallel_loop): Same.
+ * tree-ssa-loop-im.c
+ (move_computations_dom_walker::before_dom_children): Same.
+ * tree-ssa-loop-manip.c (rewrite_phi_with_iv): Same.
+ * tree-ssa-pre.c (eliminate_dom_walker::before_dom_children): Same.
+ * tree-ssa-propagate.c (substitute_and_fold): Same.
+ * tree-vect-loop.c (vect_finalize_reduction): Same.
+ * tree-vect-stmts.c (vectorizable_call): Same.
+
+2013-11-07 Mike Stump <mikestump@comcast.net>
+
+ * config/pdp11/pdp11.c: Include dbxout.h.
+ * config/picochip/picochip.c: Likewise.
+
+2013-11-07 Cong Hou <congh@google.com>
+
+ PR tree-optimization/56764
+ * tree-vect-loop-manip.c (vect_create_cond_for_alias_checks):
+ Combine alias checks if it is possible to amortize the runtime
+ overhead. Return the number of alias checks after merging.
+ * tree-vect-data-refs.c (vect_prune_runtime_alias_test_list):
+ Use the function vect_create_cond_for_alias_checks () to check
+ the number of alias checks.
+
+2013-11-07 Jeff Law <law@redhat.com>
+
+ * varpool.c (ctor_for_folding): Fix typo in comment.
+
+2013-11-07 Joern Rennecke <joern.rennecke@embecosm.com>
+
+ * config/arc/arc.c (arc_ifcvt): Use commutativity, e.g.:
+ reg_a := reg_b + reg_a ==> reg_a := reg_a + reg_b
+
+2013-11-07 Jeff Law <law@redhat.com>
+
+ * doc/invoke.texi (-fisolate-erroneous-paths): Document.
+
+ * gimple-ssa-isolate-paths.c (gate_isolate_erroneous_paths):
+ No longer check if we have __builtin_trap, assume it's available.
+
+2013-11-07 Diego Novillo <dnovillo@google.com>
+
+ * attribs.c (lookup_scoped_attribute_spec): Make static.
+ (get_attribute_namespace): Likewise.
+ * builtins.c (more_const_call_expr_args_p): Move from tree.h.
+ (validate_arglist): Move earlier in the file. Make static.
+ (expand_stack_restore): Move from stmt.c
+ (expand_stack_save): Move from stmt.c
+ (rewrite_call_expr_array): Move earlier in the file.
+ (rewrite_call_expr_valist): Likewise.
+ * cfgexpand.c: Include hard-reg-set.h before tree.h
+ Include recog.h.
+ Include output.h.
+ (expand_asm_loc): Move from stmt.c.
+ (n_occurrences): Move from stmt.c.
+ (check_operand_nalternatives): Move from stmt.c.
+ (tree_conflicts_with_clobbers_p): Move from stmt.c.
+ (expand_asm_operands): Move from stmt.c
+ (expand_asm_stmt): Move from stmt.c
+ (expand_computed_goto): Move from stmt.c
+ (expand_goto): Move from stmt.c
+ (expand_null_return_1): Move from stmt.c
+ (expand_null_return): Move from stmt.c
+ (expand_value_return): Move from stmt.c
+ (expand_return): Move from stmt.c
+ (expand_main_function): Move from function.c
+ (stack_protect_prologue): Move from function.c
+ * cgraphclones.c (build_function_type_skip_args): Move from tree.c.
+ (build_function_decl_skip_args): Move from tree.c.
+ * explow.c (tree_expr_size): Move from tree.c.
+ * expr.c (addr_expr_of_non_mem_decl_p): Remove.
+ (fields_length): Move from tree.c.
+ * fold-const.c (size_low_cst): Move from tree.c.
+ (tree_expr_nonzero_warnv_p): Make static. Move earlier in the file.
+ (tree_expr_nonzero_p): Make static. Move earlier in the file.
+ (fold_build3_initializer_loc): Remove.
+ (tree_invalid_nonnegative_warnv_p): Make static.
+ * function.c (expand_main_function): Move to cfgexpand.c.
+ (stack_protect_prologue): Move to cfgexpand.c.
+ (set_insn_locations): Move earlier in the file.
+ * gimple-fold.c: Include langhooks.h.
+ (truth_type_for): Move from tree.c.
+ * print-tree.c (print_vec_tree): Remove.
+ * stmt.c (expand_computed_goto): Move to cfgexpand.c.
+ (expand_goto): Move to cfgexpand.c.
+ (n_occurrences): Move to cfgexpand.c.
+ (expand_asm_loc): Move to cfgexpand.c
+ (tree_conflicts_with_clobbers_p): Move to cfgexpand.c.
+ (expand_asm_operands): Move to cfgexpand.c.
+ (expand_asm_stmt): Move to cfgexpand.c.
+ (check_operand_nalternatives): Move to cfgexpand.c
+ (expand_null_return): Move to cfgexpand.c.
+ (expand_value_return): Move to cfgexpand.c.
+ (expand_null_return_1): Move to cfgexpand.c.
+ (expand_return): Move to cfgexpand.c.
+ (expand_stack_save): Move to builtins.c.
+ (expand_stack_restore): Move to builtins.c
+ * symtab.c: Include output.h.
+ (decl_assembler_name_hash): Move from tree.c.
+ (decl_assembler_name_equal): Move from tree.c.
+ * trans-mem.c (is_tm_safe_or_pure): Move from tree.h.
+ * tree-eh.c (in_array_bounds_p): Move from tree.c.
+ (range_in_array_bounds_p): Move from tree.c.
+ * tree-object-size.c (fini_object_sizes): Make static.
+ * tree-ssa-dom.c (iterative_hash_exprs_commutative): Move from tree.h.
+ * tree-vrp.c (ssa_name_nonnegative_p): Remove.
+ * tree.c (decl_assembler_name_equal): Move to symtab.c.
+ (tree_expr_size): Move to explow.c.
+ (decl_assembler_name_hash): Move to symtab.c.
+ (real_twop): Remove.
+ (tree_expr_size): Move to explow.c.
+ (stabilize_reference_1): Move earlier in the file. Make static.
+ (omp_remove_redundant_declare_simd_attrs): Remove.
+ (simple_cst_list_equal): Move earlier in the file. Make static.
+ (size_low_cst): Move to fold-const.c.
+ (build_type_no_quals): Remove.
+ (build_function_type_skip_args): Move to cgraphclones.c.
+ (build_function_decl_skip_args): Move to cgraphclones.c.
+ (in_array_bounds_p): Move to tree-eh.c.
+ (range_in_array_bounds_p): Move to tree-eh.c.
+ (truth_type_for): Move to gimple-fold.c.
+ (list_equal_p): Remove.
+ * tree.h (decl_assembler_name_equal): Remove.
+ (decl_assembler_name_hash): Remove.
+ (truth_type_for): Remove.
+ (build_type_no_quals): Remove.
+ (build_function_decl_skip_args): Remove.
+ (in_array_bounds_p): Remove.
+ (range_in_array_bounds_p): Remove.
+ (size_low_cst): Remove.
+ (omp_remove_redundant_declare_simd_attrs): Remove.
+ (tree_expr_size): Remove.
+ (fields_length): Remove.
+ (stabilize_reference_1): Remove.
+ (expand_goto): Remove.
+ (expand_stack_save): Remove.
+ (expand_stack_restore): Remove.
+ (expand_return): Remove.
+ (fold_build3_initializer_loc): Remove.
+ (tree_expr_nonzero_p): Remove.
+ (tree_invalid_nonnegative_warnv_p): Remove.
+ (tree_expr_nonzero_warnv_p): Remove.
+ (fold_builtin_snprintf_chk): Remove.
+ (validate_arglist): Remove.
+ (iterative_hash_exprs_commutative): Move to tree-ssa-dom.c.
+ (simple_cst_list_equal): Remove.
+ (real_twop): Remove.
+ (expand_main_function): Remove.
+ (stack_protect_prologue): Remove.
+ (print_vec_tree): Remove.
+ (lookup_scoped_attribute_spec): Remove.
+ (get_attribute_namespace): Remove.
+ (expand_computed_goto): Remove.
+ (expand_asm_stmt): Remove.
+ (list_equal_p): Remove.
+ (ssa_name_nonnegative_p): Remove.
+ (fini_object_sizes): Remove.
+ (addr_expr_of_non_mem_decl_p): Remove.
+ (is_tm_safe_or_pure): Move to trans-mem.c.
+ (more_const_call_expr_args_p): Remove.
+ (save_vtable_map_decl): Remove.
+
+2013-11-07 Thomas Schwinge <thomas@codesourcery.com>
+
+ * doc/sourcebuild.texi (Top Level) <lto-plugin>: GNU ld can use
+ linker plugins, too.
+
+ * config/arc/arc.h (LINK_COMMAND_SPEC): For -ftree-parallelize-loops=*,
+ link to libgomp and its dependencies.
+ * config/ia64/hpux.h (LIB_SPEC): Likewise.
+ * config/pa/pa-hpux11.h (LIB_SPEC): Likewise.
+ * config/pa/pa64-hpux.h (LIB_SPEC): Likewise.
+ * gcc.c (GOMP_SELF_SPECS): Update comment about libgomp's dependencies.
+
+2013-11-07 Jakub Jelinek <jakub@redhat.com>
+
+ * tree-ssa-loop-niter.c: Include tree-ssanames.h.
+ (determine_value_range): Add loop argument. Use get_range_info to
+ improve range.
+ (bound_difference): Adjust caller.
+
+2013-11-07 Richard Biener <rguenther@suse.de>
+ Jakub Jelinek <jakub@redhat.com>
+
+ * tree-vrp.c (find_assert_locations): Pre-seed live bitmaps for loop
+ latches from header PHI arguments from the latch edge.
+
+2013-11-07 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58176
+ * varasm.c (output_constant): Handle NULLPTR_TYPE.
+
+2013-11-07 H.J. Lu <hongjiu.lu@intel.com>
+
+ * config/i386/i386.c (ix86_expand_set_or_movmem): Don't set
+ misaligned_prologue_used when it has been set.
+
+2013-11-07 Yury Gribov <y.gribov@samsung.com>
+ Jakub Jelinek <jakub@redhat.com>
+
+ PR sanitizer/59029
+ * asan.c (get_mem_refs_of_builtin_call): Allow
+ integer literals as addresses in instrumented builtins.
+
+2013-11-07 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * config/aarch64/aarch64.c (aarch64_legitimize_reload_address):
+ Explain why plus_constant is not used.
+
+2013-11-07 Richard Biener <rguenther@suse.de>
+
+ * tree-ssa-ccp.c (canonicalize_float_value): Rename to ...
+ (canonicalize_value): ... this. Also handle stripping of
+ TREE_OVERFLOW.
+ (get_value, set_lattice_value, get_value_for_expr): Adjust.
+ * gimple-fold.c (canonicalize_constructor_val): Strip TREE_OVERFLOW.
+ * tree-ssa-threadedge.c (set_ssa_name_value): Likewise.
+
+2013-11-07 Richard Biener <rguenther@suse.de>
+
+ * tree-dfa.c (get_ref_base_and_extent): Fix casting.
+
+2013-11-07 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/59034
+ * config/i386/i386.md (push peepholer/splitter): Use Pmode
+ with stack_pointer_rtx.
+
+2013-11-07 Bin Cheng <bin.cheng@arm.com>
+
+ * tree-ssa-loop-ivopts.c (get_shiftadd_cost): Check equality
+ using operand_equal_p.
+
+2013-11-07 Bin Cheng <bin.cheng@arm.com>
+
+ * tree-ssa-loop-ivopts.c (alloc_iv): Lower address expressions.
+ * tree-affine.c (get_inner_reference_aff): Return base.
+ * tree-affine.h (get_inner_reference_aff): Change prototype.
+
+2013-11-06 Tobias Burnus <burnus@net-b.de>
+
+ * doc/invoke.texi (Wdate-time): Fix typo.
+
+2013-11-06 Oleg Endo <olegendo@gcc.gnu.org>
+
+ * config/sh/sh.md (addsf3, divsf3, divsf3_i, rsqrtsf2, cmpgtdf_t,
+ cmpeqdf_t, *ieee_ccmpeqdf_t, negdf2, sqrtdf2, absdf2): Use
+ fp_arith_reg_operand instead of arith_reg_operand.
+
+2013-11-06 Oleg Endo <olegendo@gcc.gnu.org>
+
+ * config/sh/sh.md (adddi3): Remove empty constraints.
+ Remove can_create_pseudo_p and arith_reg_operand check.
+ (adddi3_compact, subdi3_compact, *negdi2): Remove constraints.
+ Split before reload.
+
+2013-11-06 Jeff Law <law@redhat.com>
+ Tom Tromey <tromey@redhat.com>
+
+ * gdbinit.in: Disable strict type checking.
+
+2013-11-06 Vladimir Makarov <vmakarov@redhat.com>
+
+ * tree-pass.h (make_pass_live_range_shrinkage): New external.
+ * timevar.def (TV_LIVE_RANGE_SHRINKAGE): New.
+ * sched-rgn.c (gate_handle_live_range_shrinkage): New.
+ (rest_of_handle_live_range_shrinkage): Ditto
+ (class pass_live_range_shrinkage): Ditto.
+ (pass_data_live_range_shrinkage): Ditto.
+ (make_pass_live_range_shrinkage): Ditto.
+ * sched-int.h (initialize_live_range_shrinkage): New prototype.
+ (finish_live_range_shrinkage): Ditto.
+ * sched-deps.c (create_insn_reg_set): Make void return value.
+ * passes.def: Add pass_live_range_shrinkage.
+ * ira.c (update_equiv_regs): Don't move if flag_live_range_shrinkage.
+ * haifa-sched.c (live_range_shrinkage_p): New.
+ (initialize_live_range_shrinkage, finish_live_range_shrinkage):
+ New functions.
+ (rank_for_schedule): Add code for pressure relief through live
+ range shrinkage.
+ (schedule_insn): Print more debug info.
+ (sched_init): Setup SCHED_PRESSURE_WEIGHTED for pressure relief
+ through live range shrinkage.
+ * doc/invoke.texi (-flive-range-shrinkage): New.
+ * common.opt (flive-range-shrinkage): New.
+
+2013-11-06 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/59021
+ * config/i386/i386.c (ix86_avx_u128_mode_needed): Require
+ AVX_U128_DIRTY mode for call_insn RTXes that use AVX256 registers.
+ (ix86_avx_u128_mode_needed): Return AVX_U128_DIRTY mode for call_insn
+ RTXes that return in AVX256 register.
+
+2013-11-06 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/58653
+ * tree-predcom.c (ref_at_iteration): Rewrite to generate a MEM_REF.
+ (prepare_initializers_chain): Adjust.
+
+2013-11-06 Andrew MacLeod <amacleod@redhat.com>
+
+ * gimple.h (block_in_transaction): Move to basic-block.h and rename.
+ (gimple_in_transaction): Use bb_in_transaction.
+ * basic-block.h (bb_in_transaction): Relocate here and rename.
+ * tree-ssa-loop-im.c (execute_sm): Use bb_in_transaction.
+
+2013-11-06 Richard Biener <rguenther@suse.de>
+
+ * tree.c (drop_tree_overflow): New function.
+ * tree.h (drop_tree_overflow): Declare.
+ * gimplify.c (gimplify_expr): Drop TREE_OVERFLOW.
+ * tree-vrp.c (range_int_cst_singleton_p): Use
+ is_overflow_infinity instead of testing TREE_OVERFLOW.
+ (extract_range_from_assert): Likewise.
+ (zero_nonzero_bits_from_vr): Likewise.
+ (extract_range_basic): Likewise.
+ (register_new_assert_for): Use drop_tree_overflow.
+ (vrp_visit_phi_node): Likewise.
+
+2013-11-06 Eric Botcazou <ebotcazou@adacore.com>
+
+ * config/i386/i386.c (ix86_expand_prologue): Optimize stack
+ checking for leaf functions without dynamic stack allocation.
+ * config/ia64/ia64.c (ia64_emit_probe_stack_range): Adjust.
+ (ia64_expand_prologue): Likewise.
+ * config/mips/mips.c (mips_expand_prologue): Likewise.
+ * config/rs6000/rs6000.c (rs6000_emit_prologue): Likewise.
+ * config/sparc/sparc.c (sparc_expand_prologue): Likewise.
+ (sparc_flat_expand_prologue): Likewise.
+
+2013-11-06 James Greenhalgh <james.greenhalgh@arm.com>
+
+ * config/aarch64/arm_neon.h (__ST2_LANE_FUNC): Better model data size.
+ (__ST3_LANE_FUNC): Likewise.
+ (__ST4_LANE_FUNC): Likewise.
+
+2013-11-06 Nick Clifton <nickc@redhat.com>
+
+ * config/msp430/msp430.h (TARGET_CPU_CPP_BUILTINS): Define the
+ name returned by msp430_mcu_name.
+ (LIB_SPEC): If a -T option has not been specified then set a
+ default, mcu-specific, linker script.
+ * config/msp430/t-msp430 (MULTILIB_MATCHES): Add more mcu names.
+ * config/msp430/msp430.c (msp430x_names): Likewise.
+ Alpha sort the names for ease of comparison.
+ (msp430_mcu_name): New function: Returns a string suitable for
+ use as a C preprocessor symbol based upon the name of the MCU
+ being targeted.
+ (msp430_option_override): Accept msp430x and msp430xv2 as generic
+ mcu names.
+ * config/msp430/msp430-protos.h (msp430_mcu_name): Prototype.
+
+ * gcc.c (do_spec_1): Do not insert a space after a %* substitution
+ unless it is the last part of a spec substring.
+ * doc/invoke.texi (Spec Files): Document space insertion
+ behaviour of %*.
+
+2013-11-06 Christian Bruel <christian.bruel@st.com>
+
+ * config/sh/sh-mem.cc (sh_expand_cmpnstr, sh_expand_cmpstr):
+ Factorize probabilities, Use adjust_address instead of
+ adjust_automodify_address when possible. Enable for optimize.
+ (sh_expand_strlen): New function.
+ * config/sh/sh-protos.h (sh_expand_strlen): Declare.
+ * config/sh/sh.md (strlensi): New pattern.
+ (UNSPEC_BUILTIN_STRLEN): Define.
+
+2013-11-06 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/58970
+ * expr.c (get_bit_range): Handle *offset == NULL_TREE.
+ (expand_assignment): If *bitpos is negative, set *offset
+ and adjust *bitpos, so that it is not negative.
+
+2013-11-06 Ganesh Gopalasubramanian <Ganesh.Gopalasubramanian@amd.com>
+
+ * config/i386/bdver3.md : Added two additional decoder units
+ to support issue rate of 4 and remodeled vector unit.
+ * config/i386/i386.c (ix86_issue_rate): Issue rate for BD
+ architectures is set to 4.
+ * config/i386/i386.c (ia32_multipass_dfa_lookahead): DFA
+ lookahead is set to 4 for BD architectures.
+
+2013-11-05 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * config/rs6000/rs6000.c (rs6000_option_override_internal):
+ Remove restriction against use of VSX instructions when generating
+ code for little endian mode.
+
+2013-11-05 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * config/rs6000/altivec.md (mulv4si3): Ensure we generate vmulouh
+ for both big and little endian.
+ (mulv8hi3): Swap input operands for merge high and merge low
+ instructions for little endian.
+
+2013-11-05 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * config/rs6000/altivec.md (vec_widen_umult_even_v16qi): Change
+ define_insn to define_expand that uses even patterns for big
+ endian and odd patterns for little endian.
+ (vec_widen_smult_even_v16qi): Likewise.
+ (vec_widen_umult_even_v8hi): Likewise.
+ (vec_widen_smult_even_v8hi): Likewise.
+ (vec_widen_umult_odd_v16qi): Likewise.
+ (vec_widen_smult_odd_v16qi): Likewise.
+ (vec_widen_umult_odd_v8hi): Likewise.
+ (vec_widen_smult_odd_v8hi): Likewise.
+ (altivec_vmuleub): New define_insn.
+ (altivec_vmuloub): Likewise.
+ (altivec_vmulesb): Likewise.
+ (altivec_vmulosb): Likewise.
+ (altivec_vmuleuh): Likewise.
+ (altivec_vmulouh): Likewise.
+ (altivec_vmulesh): Likewise.
+ (altivec_vmulosh): Likewise.
+
+2013-11-05 Mike Stump <mikestump@comcast.net>
+
+ * Makefile.in (mostlyclean): Remove c-family objects.
+
+2013-11-05 Ian Lance Taylor <iant@google.com>
+
+ * config/i386/sync.md (atomic_compare_and_swap<dwi>_doubleword):
+ If possible, add .cfi directives to record change to bx.
+ * config/i386/i386.c (ix86_emit_cfi): New function.
+ * config/i386/i386-protos.h (ix86_emit_cfi): Declare.
+
+2013-11-05 Steven Bosscher <steven@gcc.gnu.org>
+
+ * rtlanal.c (tablejump_p): Expect a JUMP_TABLE_DATA to always follow
+ immediately after a label for a tablejump pattern.
+
+ * config/arm/arm.c (is_jump_table): Remove.
+ (create_fix_barrier): Use tablejump_p instead.
+ (arm_reorg): Likewise.
+ (thumb1_output_casesi): Expect JUMP_TABLE_DATA to always be NEXT_INSN.
+ (thumb2_output_casesi): Likewise.
+ * config/aarch64/aarch64.c (aarch64_output_casesi): Likewise.
+ * config/sh/sh.md (casesi_worker_1, casesi_worker_2,
+ casesi_shift_media, casesi_load_media): Likewise.
+ * config/iq2000/iq2000.md: Likewise (in anonymous define_insn).
+ * config/microblaze/microblaze.md: Likewise.
+
+2013-11-05 Tobias Burnus <burnus@net-b.de>
+
+ * doc/invoke.texi (-Wdate-time): Document.
+
+2013-11-05 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * double-int.c (lshift_double, rshift_double): Remove
+ SHIFT_COUNT_TRUNCATED handling.
+
+2013-11-05 Jeff Law <law@redhat.com>
+
+ * Makefile.in (OBJS): Add gimple-ssa-isolate-paths.o
+ * common.opt (-fisolate-erroneous-paths): Add option and documentation.
+ * gimple-ssa-isolate-paths.c: New file.
+ * gimple.c (check_loadstore): New function.
+ (infer_nonnull_range): Moved into gimple.c from tree-vrp.c
+ Verify OP is in the argument list and the argument corresponding
+ to OP is a pointer type. Use operand_equal_p rather than
+ pointer equality when testing if OP is on the nonnull list.
+ Use check_loadstore rather than count_ptr_derefs. Handle
+ GIMPLE_RETURN statements.
+ * tree-vrp.c (infer_nonnull_range): Remove.
+ * gimple.h (infer_nonnull_range): Declare.
+ * opts.c (default_options_table): Add OPT_fisolate_erroneous_paths.
+ * passes.def: Add pass_isolate_erroneous_paths.
+ * timevar.def (TV_ISOLATE_ERRONEOUS_PATHS): New timevar.
+ * tree-pass.h (make_pass_isolate_erroneous_paths): Declare.
+ * tree-ssa.c (struct count_ptr_d): Remove.
+ (count_ptr_derefs, count_uses_and_derefs): Remove.
+ * tree-ssa.h (count_uses_and_derefs): Remove.
+
+2013-11-05 Jakub Jelinek <jakub@redhat.com>
+
+ PR rtl-optimization/58997
+ * loop-iv.c (iv_subreg): For IV_UNKNOWN_EXTEND, expect
+ get_iv_value to be in iv->mode rather than iv->extend_mode.
+ (iv_extend): Likewise. Otherwise, if iv->extend != extend,
+ use lowpart_subreg on get_iv_value before calling simplify_gen_unary.
+ * loop-unswitch.c (may_unswitch_on): Make sure op[i] is in the right
+ mode.
+
+2013-11-05 Andrew MacLeod <amacleod@redhat.com>
+
+ * gimple.h: Move some prototypes to gimple-expr.h and add to include
+ list.
+ (extract_ops_from_tree, gimple_call_addr_fndecl, is_gimple_reg_type):
+ Move to gimple-expr.h.
+ * gimple-expr.h: New file. Relocate some prototypes from gimple.h.
+ (types_compatible_p, is_gimple_reg_type, is_gimple_variable,
+ is_gimple_id, virtual_operand_p, is_gimple_addressable,
+ is_gimple_constant, extract_ops_from_tree, gimple_call_addr_fndecl):
+ Relocate here.
+ * gimple.c (extract_ops_from_tree_1, gimple_cond_get_ops_from_tree,
+ gimple_set_body, gimple_body, gimple_has_body_p, is_gimple_lvalue,
+ is_gimple_condexpr, is_gimple_addressable, is_gimple_constant,
+ is_gimple_address, is_gimple_invariant_address,
+ is_gimple_ip_invariant_address, is_gimple_min_invariant,
+ is_gimple_ip_invariant, is_gimple_variable, is_gimple_id,
+ virtual_operand_p, is_gimple_reg, is_gimple_val, is_gimple_asm_val,
+ is_gimple_min_lval, is_gimple_call_addr, is_gimple_mem_ref_addr,
+ gimple_decl_printable_name, useless_type_conversion_p,
+ types_compatible_p, gimple_can_coalesce_p, copy_var_decl): Move to
+ gimple-expr.[ch].
+ * gimple-expr.c: New File.
+ (useless_type_conversion_p, gimple_set_body, gimple_body,
+ gimple_has_body_p, gimple_decl_printable_name, copy_var_decl,
+ gimple_can_coalesce_p, extract_ops_from_tree_1,
+ gimple_cond_get_ops_from_tree, is_gimple_lvalue, is_gimple_condexpr,
+ is_gimple_address, is_gimple_invariant_address,
+ is_gimple_ip_invariant_address, is_gimple_min_invariant,
+ is_gimple_ip_invariant, is_gimple_reg, is_gimple_val,
+ is_gimple_asm_val, is_gimple_min_lval, is_gimple_call_addr,
+ is_gimple_mem_ref_addr): Relocate here.
+ * Makefile.in (OBJS): Add gimple-expr.o.
+
+2013-11-05 David Malcolm <dmalcolm@redhat.com>
+
+ * gengtype-parse.c (struct_field_seq): Support empty structs.
+
+2013-11-05 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/t-rtems (MULTILIB_MATCHES): Fix option typos.
+
+2013-11-05 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386-c.c (ix86_target_macros): Define _SOFT_FLOAT
+ for !TARGET_80387.
+ * config/i386/rtemself.h (TARGET_OS_CPP_BUILTINS): Do not define
+ _SOFT_FLOAT here.
+ (LONG_DOUBLE_TYPE_SIZE): New define.
+ (LIBGCC2_LONG_DOUBLE_TYPE_SIZE): Ditto.
+
+2013-11-05 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58724
+ * doc/extend.texi [visibility ("visibility_type")]: Add example
+ about visibility attribute on namespace declaration.
+
+2013-11-05 Richard Biener <rguenther@suse.de>
+
+ PR ipa/58492
+ * passes.def (all_passes): Start with pass_fixup_cfg again.
+
+2013-11-05 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/58955
+ * tree-loop-distribution.c (pg_add_dependence_edges): Fix
+ edge direction.
+
+2013-11-05 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * config/rs6000/vector.md (vec_pack_sfix_trunc_v2df): Adjust for
+ little endian.
+ (vec_pack_ufix_trunc_v2df): Likewise.
+
+2013-11-05 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR middle-end/58981
+ * doc/md.texi (@code{movmem@var{m}}): Specify Pmode as mode of
+ pattern, instead of word_mode.
+
+ * expr.c (emit_block_move_via_movmem): Don't use mode wider than
+ Pmode for size.
+ (set_storage_via_setmem): Likewise.
+
+2013-11-05 Andrew MacLeod <amacleod@redhat.com>
+
+ * tree-outof-ssa.c (queue_phi_copy_p): Combine phi_ssa_name_p from
+ gimple.h and the rest of the condition in eliminate_build.
+ (eliminate_build): Call new routine.
+ * gimple.h (phi_ssa_name_p): Delete.
+
+2013-11-05 Trevor Saunders <tsaunders@mozilla.com>
+
+ * vec.c (vec_prefix::calculate_allocation): Don't try to handle the
+ case of no prefix and reserving zero slots, because when that's the
+ case we'll never get here.
+ * vec.h (va_heap::reserve): Don't try and handle
+ vec_prefix::calculate_allocation returning zero because that should
+ never happen.
+
+2013-11-05 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/58941
+ * tree-dfa.c (get_ref_base_and_extent): Merge common code
+ in MEM_REF and TARGET_MEM_REF handling. Make sure to
+ process trailing array detection before diving into the
+ view-converted object (and possibly apply some extra offset).
+
+2013-11-05 Joseph Myers <joseph@codesourcery.com>
+
+ * config/i386/i386.c (ix86_float_exceptions_rounding_supported_p):
+ New function.
+ (TARGET_FLOAT_EXCEPTIONS_ROUNDING_SUPPORTED_P): Define.
+
+2013-11-05 Marc Glisse <marc.glisse@inria.fr>
+
+ PR tree-optimization/58958
+ * tree-ssa-alias.c (ao_ref_init_from_ptr_and_size): Use
+ get_addr_base_and_unit_offset instead of get_ref_base_and_extent.
+
+2013-11-05 Marc Glisse <marc.glisse@inria.fr>
+
+ * tree-ssa-alias.h (ranges_overlap_p): Handle negative offsets.
+ * tree-ssa-alias.c (ao_ref_init_from_ptr_and_size): Likewise.
+
+2013-11-05 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/58984
+ * ipa-prop.c (ipa_load_from_parm_agg_1): Add SIZE_P argument,
+ set *SIZE_P if non-NULL on success.
+ (ipa_load_from_parm_agg, ipa_analyze_indirect_call_uses): Adjust
+ callers.
+ (ipcp_transform_function): Likewise. Punt if size of access
+ is different from TYPE_SIZE on v->value's type.
+
+2013-11-05 Tobias Burnus <burnus@net-b.de>
+
+ * doc/invoke.texi (-fopenmp-simd): Document new option.
+ * gimplify.c (gimplify_body): Accept -fopenmp-simd.
+ * omp-low.c (execute_expand_omp, execute_lower_omp): Ditto.
+ * tree.c (attribute_value_equal): Ditto.
+
+2013-11-04 Wei Mi <wmi@google.com>
+
+ * sched-rgn.c (add_branch_dependences): Keep insns in
+ a SCHED_GROUP at the end of BB to remain their location.
+
+2013-11-04 Wei Mi <wmi@google.com>
+
+ * config/i386/i386.c (memory_address_length): Extract a part
+ of code to rip_relative_addr_p.
+ (rip_relative_addr_p): New Function.
+ (ix86_macro_fusion_p): Ditto.
+ (ix86_macro_fusion_pair_p): Ditto.
+ * config/i386/i386.h: Add new tune features about macro-fusion.
+ * config/i386/x86-tune.def (DEF_TUNE): Ditto.
+ * doc/tm.texi: Generated.
+ * doc/tm.texi.in: Ditto.
+ * haifa-sched.c (try_group_insn): New Function.
+ (group_insns_for_macro_fusion): Ditto.
+ (sched_init): Call group_insns_for_macro_fusion.
+ * target.def: Add two hooks: macro_fusion_p and
+ macro_fusion_pair_p.
+
+2013-11-04 Kostya Serebryany <kcc@google.com>
+
+ Update to match the changed asan API.
+ * asan.c (asan_function_start): New function.
+ (asan_emit_stack_protection): Update the string stored in the
+ stack red zone to match new API. Store the PC of the current
+ function in the red zone.
+ (asan_global_struct): Update the __asan_global definition to match
+ the new API.
+ (asan_add_global): Ditto.
+ * asan.h (asan_function_start): New prototype.
+ * final.c (final_start_function): Call asan_function_start.
+ * sanitizer.def (BUILT_IN_ASAN_INIT): Rename __asan_init_v1
+ to __asan_init_v3.
+
+2013-11-04 Wei Mi <wmi@google.com>
+
+ * config/i386/i386-c.c (ix86_target_macros_internal): Separate
+ PROCESSOR_COREI7_AVX out from PROCESSOR_COREI7.
+ * config/i386/i386.c (ix86_option_override_internal): Ditto.
+ (ix86_issue_rate): Ditto.
+ (ix86_adjust_cost): Ditto.
+ (ia32_multipass_dfa_lookahead): Ditto.
+ (ix86_sched_init_global): Ditto.
+ (get_builtin_code_for_version): Ditto.
+ * config/i386/i386.h (enum target_cpu_default): Ditto.
+ (enum processor_type): Ditto.
+ * config/i386/x86-tune.def (DEF_TUNE): Ditto.
+
+2013-11-04 Vladimir Makarov <vmakarov@redhat.com>
+
+ PR rtl-optimization/58967
+ * config/rs6000/rs6000.c (legitimate_lo_sum_address_p): Remove
+ !lra_in_progress for mode sizes bigger word.
+
+2013-11-04 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * config/rs6000/altivec.md (vec_widen_umult_hi_v16qi): Swap
+ arguments to merge instruction for little endian.
+ (vec_widen_umult_lo_v16qi): Likewise.
+ (vec_widen_smult_hi_v16qi): Likewise.
+ (vec_widen_smult_lo_v16qi): Likewise.
+ (vec_widen_umult_hi_v8hi): Likewise.
+ (vec_widen_umult_lo_v8hi): Likewise.
+ (vec_widen_smult_hi_v8hi): Likewise.
+ (vec_widen_smult_lo_v8hi): Likewise.
+
+2013-11-04 Ian Lance Taylor <iant@google.com>
+
+ * builtins.def (ATTR_NOTHROWCALL_LEAF_LIST): Define.
+ * sync-builtins.def: Use ATTR_NOTHROWCALL_LEAF_LIST for all sync
+ builtins that take pointers.
+ * lto-opts.c (lto_write_options): Write -fnon-call-exceptions if set.
+ * lto-wrapper.c (merge_and_complain): Collect OPT_fnon_call_exceptions.
+ (run_gcc): Pass -fnon-call-exceptions.
+
+2013-11-04 Jakub Jelinek <jakub@redhat.com>
+
+ * optabs.c (expand_vec_perm): Revert one incorrect line from
+ 2013-10-31 change.
+
+ PR tree-optimization/58978
+ * tree-vrp.c (all_imm_uses_in_stmt_or_feed_cond): Don't modify
+ use_stmt by single_imm_use directly. Only call single_imm_use
+ on SSA_NAMEs.
+
+2013-11-04 Vladimir Makarov <vmakarov@redhat.com>
+
+ PR rtl-optimization/58968
+ * lra-spills.c (return_regno_p): New function.
+ (lra_final_code_change): Use it.
+
+2013-11-04 Joseph Myers <joseph@codesourcery.com>
+
+ * doc/cpp.texi (__GCC_IEC_559, __GCC_IEC_559_COMPLEX): Document macros.
+ * target.def (float_exceptions_rounding_supported_p): New hook.
+ * targhooks.c (default_float_exceptions_rounding_supported_p): New
+ function.
+ * targhooks.h (default_float_exceptions_rounding_supported_p): Declare.
+ * doc/tm.texi.in (TARGET_FLOAT_EXCEPTIONS_ROUNDING_SUPPORTED_P):
+ New @hook.
+ * doc/tm.texi: Regenerate.
+ * config.gcc (powerpc*-*-linux*): Set extra_objs.
+ * config/rs6000/rs6000-linux.c: New file.
+ * config/rs6000/rs6000-protos.h
+ (rs6000_linux_float_exceptions_rounding_supported_p): Declare.
+ * config/rs6000/linux.h
+ (TARGET_FLOAT_EXCEPTIONS_ROUNDING_SUPPORTED_P): New macro.
+ * config/rs6000/linux64.h
+ (TARGET_FLOAT_EXCEPTIONS_ROUNDING_SUPPORTED_P): Likewise.
+ * config/rs6000/t-linux (rs6000-linux.o): New rule.
+ * config/rs6000/t-linux64 (rs6000-linux.o): Likewise.
+
+2013-11-04 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * config/rs6000/vsx.md (*vsx_le_perm_store_<mode> for VSX_D):
+ Replace the define_insn_and_split with a define_insn and two
+ define_splits, with the split after reload re-permuting the source
+ register to its original value.
+ (*vsx_le_perm_store_<mode> for VSX_W): Likewise.
+ (*vsx_le_perm_store_v8hi): Likewise.
+ (*vsx_le_perm_store_v16qi): Likewise.
+
+2013-11-04 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * config/rs6000/vector.md (vec_pack_trunc_v2df): Adjust for
+ little endian.
+
+2013-11-04 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/58946
+ * tree-ssa-reassoc.c (maybe_optimize_range_tests): Update all
+ bbs with bbinfo[idx].op != NULL before all blocks with
+ bbinfo[idx].op == NULL.
+
+2013-11-04 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * config/avr/avr-log.c (avr_double_int_pop_digit): Delete.
+ (avr_dump_double_int_hex): Likewise.
+ (avr_log_vadump): Remove %D and %X handling.
+ * config/avr/avr.c (avr_double_int_push_digit): Delete.
+ (avr_map_op_t): Change map from double_int to unsigned int.
+ (avr_map_op): Update accordingly.
+ (avr_map, avr_map_metric, avr_has_nibble_0xf, avr_map_decompose)
+ (avr_move_bits, avr_out_insert_bits, avr_fold_builtin): Operate on
+ unsigned ints rather than double_ints.
+
+2013-11-03 Marek Polacek <polacek@redhat.com>
+
+ Implement -fsanitize=vla-bound.
+ * opts.c (common_handle_option): Handle vla-bound.
+ * sanitizer.def (BUILT_IN_UBSAN_HANDLE_VLA_BOUND_NOT_POSITIVE): Define.
+ * flag-types.h (enum sanitize_code): Add SANITIZE_VLA.
+ * asan.c (initialize_sanitizer_builtins): Build BT_FN_VOID_PTR_PTR.
+
+2013-11-02 Bill Schmidt <wschmidt@vnet.linux.ibm.com>
+
+ * config/rs6000/rs6000.c (rs6000_expand_vector_set): Adjust for
+ little endian.
+
+2013-11-02 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/constraints.md (Ts, Tv): New address constrains.
+ * config/i386/i386.md (*lea<mode>, *<mode>_<bndcheck>): Use Ts
+ constraint for address_no_seg_operand.
+ * config/i386/sse.md (*avx512pf_gatherpf<mode>_mask)
+ (*avx512pf_gatherpf<mode>, *avx512pf_scatterpf<mode>_mask)
+ (*avx512pf_scatterpf<mode>, *avx2_gathersi<mode>)
+ (*avx2_gathersi<mode>_2, *avx2_gatherdi<mode>, *avx2_gatherdi<mode>_2)
+ (*avx2_gatherdi<mode>_3, *avx2_gatherdi<mode>_4)
+ (*avx512f_gathersi<mode>, *avx512f_gathersi<mode>_2)
+ (*avx512f_gatherdi<mode>, *avx512f_gatherdi<mode>_2)
+ (*avx512f_scattersi<mode> *avx512f_scatterdi<mode>): Use Tv
+ constraint for vsib_address_operand.
+
+2013-11-02 Steven Bosscher <steven@gcc.gnu.org>
+
+ * gcse.c (pre_delete): Remove references to regmove from comments.
+ * recog.c: (validate_replace_rtx_1): Likewise.
+ * config/rl78/rl78.c: Likewise.
+ * config/v850/v850.h: Likewise, and remove unused ENABLE_REGMOVE_PASS.
+ * common/config/m32r/m32r-common.c: Don't manipulate OPT_fregmove.
+ * common/config/mmix/mmix-common.c: Likewise.
+
+2013-11-01 Trevor Saunders <tsaunders@mozilla.com>
+
+ * function.c (reorder_blocks): Convert block_stack to a stack_vec.
+ * gimplify.c (gimplify_compound_lval): Likewise.
+ * graphite-clast-to-gimple.c (gloog): Likewise.
+ * graphite-dependences.c (loop_is_parallel_p): Likewise.
+ * graphite-scop-detection.c (scopdet_basic_block_info): Likewise.
+ (limit_scop); Likewise.
+ (build_scops): Likewise.
+ (dot_scop): Likewise.
+ * graphite-sese-to-poly.c (sese_dom_walker): Likewise.
+ (build_scop_drs): Likewise.
+ (insert_stmts): Likewise.
+ (insert_out_of_ssa_copy): Likewise.
+ (remove_phi): Likewise.
+ (rewrite_commutative_reductions_out_of_ssa_close_phi): Likewise.
+ * hw-doloop.c (discover_loop): Likewise.
+ * tree-call-cdce.c (shrink_wrap_one_built_in_call): Likewise.
+ * tree-dfa.c (dump_enumerated_decls): Likewise.
+ * tree-if-conv.c (if_convertable_loop_p): Likewise.
+ * tree-inline.c (tree_function_versioning): Likewise.
+ * tree-loop-distribution.c (build_rdg): Likewise.
+ (rdg_flag_vertex_and_dependent): Likewise.
+ (distribute_loop): Likewise.
+ * tree-parloops.c (loop_parallel_p): Likewise.
+ (eliminate_local_variables): Likewise.
+ (separate_decls_in_region): Likewise.
+ * tree-predcom.c (tree_predictive_commoning_loop): Likewise.
+ * tree-ssa-phiopt.c (cond_if_else_store_replacement): Likewise.
+ * tree-ssa-uncprop.c (uncprop_dom_walker): Likewise.
+ * tree-vect-loop.c (vect_analyze_scaler_cycles_1): Likewise.
+ * tree-vect-patterns.c (vect_pattern_recog): Likewise.
+ * tree-vect-stmts.c (vect_mark_stmts_to_be_vectorized): Likewise.
+ (vectorizable_condition): Likewise.
+
+2013-11-01 Uros Bizjak <ubizjak@gmail.com>
+
+ * configure.ac (HAVE_AS_IX86_INTERUNIT_MOVQ): Always define as 0/1.
+ * configure: Regenerate.
+ * config/i386/i386.md (*movdi_internal): Change
+ HAVE_AS_IX86_INTERUNIT_MOVQ to runtime check.
+ (*movdf_internal): Ditto.
+ * config/i386/mmx.md (*mov<mode>_internal): Ditto.
+ * config/i386/sse.md (vec_concatv2di): Output interunit movq
+ for HAVE_AS_IX86_INTERUNIT_MOVQ targets.
+
+2013-10-31 Robert Suchanek <Robert.Suchanek@imgtec.com>
+
+ * lra-spills.c (assign_spill_hard_regs): Remove statement terminator
+ after comment.
+
+2013-10-31 David Malcolm <dmalcolm@redhat.com>
+
+ Automated part of renaming of symtab_node_base to symtab_node.
+
+ Patch autogenerated by rename_symtab.py from
+ https://github.com/davidmalcolm/gcc-refactoring-scripts
+ revision 58bb219cc090b2f4516a9297d868c245495ee622
+ with ChangeLog entry fixed up by hand.
+
+ * cgraph.c (x_cgraph_nodes_queue): Rename symtab_node_base to
+ symtab_node.
+ (cgraph_node_for_asm): Likewise.
+ * cgraph.h (symtab_node_base): Likewise.
+ (cgraph_node): Likewise.
+ (varpool_node): Likewise.
+ (is_a_helper <cgraph_node>::test): Likewise.
+ (is_a_helper <varpool_node>::test): Likewise.
+ (symtab_nodes): Likewise.
+ (symtab_register_node): Likewise.
+ (symtab_unregister_node): Likewise.
+ (symtab_remove_node): Likewise.
+ (symtab_get_node): Likewise.
+ (symtab_node_for_asm): Likewise.
+ (symtab_node_asm_name): Likewise.
+ (symtab_node_name): Likewise.
+ (symtab_insert_node_to_hashtable): Likewise.
+ (symtab_add_to_same_comdat_group): Likewise.
+ (symtab_dissolve_same_comdat_group_list): Likewise.
+ (dump_symtab_node): Likewise.
+ (debug_symtab_node): Likewise.
+ (dump_symtab_base): Likewise.
+ (verify_symtab_node): Likewise.
+ (verify_symtab_base): Likewise.
+ (symtab_used_from_object_file_p): Likewise.
+ (symtab_alias_ultimate_target): Likewise.
+ (symtab_resolve_alias): Likewise.
+ (fixup_same_cpp_alias_visibility): Likewise.
+ (symtab_for_node_and_aliases): Likewise.
+ (symtab_nonoverwritable_alias): Likewise.
+ (availability symtab_node_availability): Likewise.
+ (symtab_semantically_equivalent_p): Likewise.
+ (fixup_same_cpp_alias_visibility): Likewise.
+ (symtab_prevail_in_asm_name_hash): Likewise.
+ (cgraph): Likewise.
+ (varpool): Likewise.
+ (varpool_first_variable): Likewise.
+ (varpool_next_variable): Likewise.
+ (varpool_first_static_initializer): Likewise.
+ (varpool_next_static_initializer): Likewise.
+ (varpool_first_defined_variable): Likewise.
+ (varpool_next_defined_variable): Likewise.
+ (cgraph_first_defined_function): Likewise.
+ (cgraph_next_defined_function): Likewise.
+ (cgraph_first_function): Likewise.
+ (cgraph_next_function): Likewise.
+ (cgraph_first_function_with_gimple_body): Likewise.
+ (cgraph_next_function_with_gimple_body): Likewise.
+ (symtab_alias_target): Likewise.
+ (symtab_real_symbol_p): Likewise.
+ (symtab_can_be_discarded): Likewise.
+ * cgraphbuild.c (mark_address): Likewise.
+ (mark_load): Likewise.
+ (mark_store): Likewise.
+ * cgraphunit.c (decide_is_symbol_needed): Likewise.
+ (first): Likewise.
+ (enqueue_node): Likewise.
+ (referred_to_p): Likewise.
+ (cgraph_process_same_body_aliases): Likewise.
+ (analyze_functions): Likewise.
+ (handle_alias_pairs): Likewise.
+ (output_weakrefs): Likewise.
+ (compile): Likewise.
+ * gimple-fold.c (can_refer_decl_in_current_unit_p): Likewise.
+ * ipa-inline-analysis.c (inline_write_summary): Likewise.
+ * ipa-prop.c (remove_described_reference): Likewise.
+ (try_decrement_rdesc_refcount): Likewise.
+ (ipa_edge_duplication_hook): Likewise.
+ * ipa-ref.c (ipa_record_reference): Likewise.
+ (ipa_maybe_record_reference): Likewise.
+ (ipa_clone_ref): Likewise.
+ (ipa_clone_references): Likewise.
+ (ipa_clone_referring): Likewise.
+ (ipa_find_reference): Likewise.
+ (ipa_remove_stmt_references): Likewise.
+ (ipa_clear_stmts_in_references): Likewise.
+ * ipa-ref.h (symtab_node_base): Likewise.
+ (ipa_ref): Likewise.
+ (ipa_record_reference): Likewise.
+ (ipa_maybe_record_reference): Likewise.
+ (ipa_clone_references): Likewise.
+ (ipa_clone_referring): Likewise.
+ (ipa_clone_ref): Likewise.
+ (ipa_find_reference): Likewise.
+ (ipa_remove_stmt_references): Likewise.
+ (ipa_clear_stmts_in_references): Likewise.
+ * ipa-reference.c (ipa_reference_write_optimization_summary):
+ Likewise.
+ * ipa.c (enqueue_node): Likewise.
+ (process_references): Likewise.
+ (walk_polymorphic_call_targets): Likewise.
+ (symtab_remove_unreachable_nodes): Likewise.
+ (address_taken_from_non_vtable_p): Likewise.
+ (comdat_can_be_unshared_p_1): Likewise.
+ (comdat_can_be_unshared_p): Likewise.
+ (can_replace_by_local_alias): Likewise.
+ (function_and_variable_visibility): Likewise.
+ * is-a.h: Likewise (within example in comment).
+ * lto-cgraph.c (input_cgraph_opt_summary): Likewise.
+ (lto_symtab_encoder_encode): Likewise.
+ (lto_symtab_encoder_delete_node): Likewise.
+ (lto_symtab_encoder_in_partition_p): Likewise.
+ (lto_set_symtab_encoder_in_partition): Likewise.
+ (output_refs): Likewise.
+ (compute_ltrans_boundary): Likewise.
+ (output_symtab): Likewise.
+ (input_node): Likewise.
+ (input_ref): Likewise.
+ (input_edge): Likewise.
+ (input_cgraph_1): Likewise.
+ (input_refs): Likewise.
+ (output_cgraph_opt_summary): Likewise.
+ (input_node_opt_summary): Likewise.
+ (input_cgraph_opt_section): Likewise.
+ * lto-section-in.c (lto_free_function_in_decl_state_for_node):
+ Likewise.
+ * lto-streamer-out.c (lto_output): Likewise.
+ (output_symbol_p): Likewise.
+ (produce_symtab): Likewise.
+ * lto-streamer.h (lto_encoder_entry): Likewise.
+ (lto_free_function_in_decl_state_for_node): Likewise.
+ (lto_symtab_encoder_encode): Likewise.
+ (lto_symtab_encoder_delete_node): Likewise.
+ (lto_symtab_encoder_in_partition_p): Likewise.
+ (lto_set_symtab_encoder_in_partition): Likewise.
+ (lto_symtab_encoder_lookup): Likewise.
+ (lsei_node): Likewise.
+ (lto_symtab_encoder_deref): Likewise.
+ * symtab.c (symtab_hash): Likewise.
+ (assembler_name_hash): Likewise.
+ (symtab_nodes): Likewise.
+ (hash_node): Likewise.
+ (eq_node): Likewise.
+ (hash_node_by_assembler_name): Likewise.
+ (eq_assembler_name): Likewise.
+ (insert_to_assembler_name_hash): Likewise.
+ (unlink_from_assembler_name_hash): Likewise.
+ (symtab_prevail_in_asm_name_hash): Likewise.
+ (symtab_register_node): Likewise.
+ (symtab_insert_node_to_hashtable): Likewise.
+ (symtab_unregister_node): Likewise.
+ (symtab_get_node): Likewise.
+ (symtab_remove_node): Likewise.
+ (symtab_initialize_asm_name_hash): Likewise.
+ (symtab_node_for_asm): Likewise.
+ (symtab_add_to_same_comdat_group): Likewise.
+ (symtab_dissolve_same_comdat_group_list): Likewise.
+ (symtab_node_asm_name): Likewise.
+ (symtab_node_name): Likewise.
+ (dump_symtab_base): Likewise.
+ (dump_symtab_node): Likewise.
+ (dump_symtab): Likewise.
+ (debug_symtab_node): Likewise.
+ (verify_symtab_base): Likewise.
+ (verify_symtab_node): Likewise.
+ (verify_symtab): Likewise.
+ (symtab_used_from_object_file_p): Likewise.
+ (symtab_node_availability): Likewise.
+ (symtab_alias_ultimate_target): Likewise.
+ (fixup_same_cpp_alias_visibility): Likewise.
+ (symtab_resolve_alias): Likewise.
+ (symtab_for_node_and_aliases): Likewise.
+ (symtab_for_node_and_aliases): Likewise.
+ (symtab_nonoverwritable_alias_1): Likewise.
+ (symtab_nonoverwritable_alias): Likewise.
+ (symtab_semantically_equivalent_p): Likewise.
+ * value-prof.c (init_node_map): Likewise.
+ * varasm.c (find_decl): Likewise.
+ * varpool.c (varpool_node_for_asm): Likewise.
+ (varpool_remove_unreferenced_decls): Likewise.
+
+2013-10-31 David Malcolm <dmalcolm@redhat.com>
+
+ Manual part of renaming of symtab_node_base to symtab_node.
+
+ * ipa-ref.h (symtab_node): Remove typedef to pointer type, as it
+ clashes with the preferred name for the base class.
+ (const_symtab_node): Remove redundant typedef.
+
+2013-10-31 Jakub Jelinek <jakub@redhat.com>
+
+ * optabs.c (expand_vec_perm): Avoid vector mode punning
+ SUBREGs in SET_DEST.
+ * expmed.c (store_bit_field_1): Likewise.
+ * config/i386/sse.md (movdi_to_sse, vec_pack_sfix_trunc_v2df,
+ vec_pack_sfix_v2df, vec_shl_<mode>, vec_shr_<mode>,
+ vec_interleave_high<mode>, vec_interleave_low<mode>): Likewise.
+ * config/i386/i386.c (ix86_expand_vector_move_misalign,
+ ix86_expand_sse_movcc, ix86_expand_int_vcond, ix86_expand_vec_perm,
+ ix86_expand_sse_unpack, ix86_expand_args_builtin,
+ ix86_expand_vector_init_duplicate, ix86_expand_vector_set,
+ emit_reduc_half, expand_vec_perm_blend, expand_vec_perm_pshufb,
+ expand_vec_perm_interleave2, expand_vec_perm_pshufb2,
+ expand_vec_perm_vpshufb2_vpermq,
+ expand_vec_perm_vpshufb2_vpermq_even_odd, expand_vec_perm_even_odd_1,
+ expand_vec_perm_broadcast_1, expand_vec_perm_vpshufb4_vpermq2,
+ ix86_expand_sse2_mulv4si3, ix86_expand_pinsr): Likewise.
+ (expand_vec_perm_palignr): Likewise. Modify a copy of *d rather
+ than *d itself.
+
+2013-10-31 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.c (ix86_expand_sse2_abs): Rename function arguments.
+ Use gcc_unreachable for unhandled modes. Do not check results of
+ expand_simple_binop. If not expanded to target, move the result.
+
+2013-10-31 Chung-Ju Wu <jasonwucj@gmail.com>
+ Shiva Chen <shiva0217@gmail.com>
+
+ * config.gcc (nds32*-*-*): Add nds32 target.
+ * config/nds32/nds32.c: New file.
+ * config/nds32/nds32.h: New file.
+ * config/nds32/nds32.md: New file.
+ * config/nds32/constants.md: New file.
+ * config/nds32/constraints.md: New file.
+ * config/nds32/iterators.md: New file.
+ * config/nds32/nds32-doubleword.md: New file.
+ * config/nds32/nds32-intrinsic.md: New file.
+ * config/nds32/nds32_intrinsic.h: New file.
+ * config/nds32/nds32-modes.def: New file.
+ * config/nds32/nds32-multiple.md: New file.
+ * config/nds32/nds32.opt: New file.
+ * config/nds32/nds32-opts.h: New file.
+ * config/nds32/nds32-protos.h: New file.
+ * config/nds32/nds32-peephole2.md: New file.
+ * config/nds32/pipelines.md: New file.
+ * config/nds32/predicates.md: New file.
+ * config/nds32/t-mlibs: New file.
+ * common/config/nds32: New directory and files.
+
+ * doc/invoke.texi (NDS32 options): Document nds32 specific options.
+ * doc/md.texi (NDS32 family): Document nds32 specific constraints.
+ * doc/install.texi (Cross-Compiler-Specific Options): Document
+ --with-nds32-lib for nds32 target.
+ * doc/extend.texi (Function Attributes, Target Builtins): Document
+ nds32 specific attributes.
+
+2013-10-31 Vladimir Makarov <vmakarov@redhat.com>
+
+ * lra-constraints (process_alt_operands): Use the result
+ elimination register for operand when matching constraints.
+
+2013-10-31 Jakub Jelinek <jakub@redhat.com>
+
+ * tree-vrp.c (maybe_set_nonzero_bits): New function.
+ (remove_range_assertions): Call it.
+
+ * tree.c (tree_ctz): New function.
+ * tree.h (tree_ctz): New prototype.
+ * tree-ssanames.h (get_range_info, get_nonzero_bits): Change
+ first argument from tree to const_tree.
+ * tree-ssanames.c (get_range_info, get_nonzero_bits): Likewise.
+ * tree-vectorizer.h (vect_generate_tmps_on_preheader): New prototype.
+ * tree-vect-loop-manip.c (vect_generate_tmps_on_preheader): No longer
+ static.
+ * expr.c (highest_pow2_factor): Reimplemented using tree_ctz.
+ * tree-vect-loop.c (vect_analyze_loop_operations,
+ vect_transform_loop): Don't force scalar loop for bound just because
+ number of iterations is unknown, only do it if it is not known to be
+ a multiple of vectorization_factor.
+ * builtins.c (get_object_alignment_2): Use tree_ctz on offset.
+
+ * gimple-pretty-print.c (dump_ssaname_info): Print newline also
+ in case of VR_VARYING. Print get_nonzero_bits if not all ones.
+ * tree-ssanames.h (struct range_info_def): Add nonzero_bits field.
+ (set_nonzero_bits, get_nonzero_bits): New prototypes.
+ * tree-ssa-ccp.c (get_default_value): Use get_range_info to see if
+ a default def isn't partially constant.
+ (ccp_finalize): If after IPA, set_range_info if integral SSA_NAME
+ is known to be partially zero.
+ (evaluate_stmt): If we'd return otherwise VARYING, use get_range_info
+ to see if a default def isn't partially constant.
+ * tree-ssanames.c (set_range_info): Initialize nonzero_bits upon
+ creation of a range, if VR_RANGE, try to improve nonzero_bits from
+ the range.
+ (set_nonzero_bits, get_nonzero_bits): New functions.
+
+ * tree-cfg.c (assert_unreachable_fallthru_edge_p): New function.
+ * tree-cfg.h (assert_unreachable_fallthru_edge_p): New prototype.
+ * tree-vrp.c (all_imm_uses_in_stmt_or_feed_cond): New function.
+ (remove_range_assertions): If ASSERT_EXPR_VAR has no other immediate
+ uses but in the condition and ASSERT_EXPR and the other successor of
+ the predecessor bb is __builtin_unreachable (), set_range_info of the
+ ASSERT_EXPR_VAR to the range info of the ASSERT_EXPR's lhs.
+
+2013-10-31 Martin Jambor <mjambor@suse.cz>
+
+ PR rtl-optimization/58934
+ Revert:
+ 2013-10-30 Martin Jambor <mjambor@suse.cz>
+ PR rtl-optimization/10474
+ * ira.c (find_moveable_pseudos): Do not calculate dominance info
+ nor df analysis.
+ (interesting_dest_for_shprep): New function.
+ (split_live_ranges_for_shrink_wrap): Likewise.
+ (ira): Calculate dominance info and df analysis. Call
+ split_live_ranges_for_shrink_wrap.
+
+2013-10-31 Richard Sandiford <rsandifo@linux.vnet.ibm.com>
+ Yury Gribov <y.gribov@samsung.com>
+
+ PR sanitizer/58543
+ * asan.c (asan_clear_shadow): Allocate a new vreg for temporary
+ shadow pointer to avoid clobbering the main one.
+
+2013-10-31 Zhenqiang Chen <zhenqiang.chen@linaro.org>
+
+ * lower-subreg.c (resolve_simple_move): Copy REG_INC note.
+
+2013-10-30 Vladimir Makarov <vmakarov@redhat.com>
+
+ PR bootstrap/58933
+ * ira-color.c (update_costs_from_copies): Add new parameter. Use
+ it for calling update_costs_from_allocno.
+ (assign_hard_reg): Call restore_costs_from_copies only for
+ !retry_p. Pass new argument to update_costs_from_copies.
+ (color_pass): Pass new argument to update_costs_from_copies.
+ (ira_mark_allocation_change): Ditto.
+
+2013-10-30 Sharad Singhai <singhai@google.com>
+
+ PR middle-end/58134
+ * opts.c (common_handle_option): Remove deprecated option
+ -ftree-vectorizer-verbose.
+ * doc/invoke.texi (Debugging Options): Ditto.
+ * opts-global.c (handle_common_deferred_options): Ditto.
+ (dump_remap_tree_vectorizer_verbose): Delete.
+ * common.opt: Set -ftree-vectorizer-verbose as an ignored option.
+
+2013-10-30 DJ Delorie <dj@redhat.com>
+
+ * config/rx/rx.c (ADD_RX_BUILTIN0): New macro, used for builtins
+ that take no arguments.
+
+2013-10-30 Joern Rennecke <joern.rennecke@embecosm.com>
+
+ PR other/58545
+ * reload1.c (update_eliminables_and_spill): New function, broken
+ out of reload.
+ (reload): Use it. Check for frame size change after frame size
+ alignment, and call update_eliminables_and_spill first if continue-ing.
+
+2013-10-30 Cong Hou <congh@google.com>
+
+ PR target/58762
+ * config/i386/i386-protos.h (ix86_expand_sse2_abs): New function.
+ * config/i386/i386.c (ix86_expand_sse2_abs): New function.
+ * config/i386/sse.md: Add SSE2 support to abs (8/16/32-bit-int).
+
+2013-10-18 Mikael Pettersson <mikpelinux@gmail.com>
+
+ PR rtl-optimization/58369
+ * reload1.c (compute_reload_subreg_offset): New function.
+ (choose_reload_regs): Use it to pass endian-correct
+ offset to subreg_regno_offset.
+
+2013-10-30 Tobias Burnus <burnus@net-b.de>
+
+ PR other/33426
+ * tree-cfg.c (replace_loop_annotate): Replace warning by
+ warning_at.
+
+2013-10-30 Jason Merrill <jason@redhat.com>
+
+ * configure.ac (loose_warn): Add -Wno-format if
+ --disable-build-format-warnings.
+
+2013-10-30 David Malcolm <dmalcolm@redhat.com>
+
+ * cgraphunit.c (analyze_functions): Split symtab_node declarations
+ onto multiple lines to make things easier for rename_symtab.py.
+
+ * symtab.c (symtab_dissolve_same_comdat_group_list): Likewise.
+ (symtab_semantically_equivalent_p): Likewise.
+
+2013-10-30 Vladimir Makarov <vmakarov@redhat.com>
+
+ PR target/58784
+ * lra.c (check_rtl): Remove address check before LRA work.
+
+2013-10-30 Marc Glisse <marc.glisse@inria.fr>
+
+ * tree-ssa-alias.c (ao_ref_init_from_ptr_and_size): Look for a
+ POINTER_PLUS_EXPR in the defining statement.
+
+2013-10-30 Vladimir Makarov <vmakarov@redhat.com>
+
+ * regmove.c: Remove.
+ * tree-pass.h (make_pass_regmove): Remove.
+ * timevar.def (TV_REGMOVE): Remove.
+ * passes.def (pass_regmove): Remove.
+ * opts.c (default_options_table): Remove entry for regmove.
+ * doc/passes.texi: Remove regmove pass description.
+ * doc/invoke.texi (-foptimize-register-move, -fregmove): Remove
+ options.
+ (-fdump-rtl-regmove): Ditto.
+ * common.opt (foptimize-register-move, fregmove): Ignore.
+ * Makefile.in (OBJS): Remove regmove.o.
+ * regmove.c: Remove.
+ * ira-int.h (struct ira_allocno_pref, ira_pref_t): New structure
+ and type.
+ (struct ira_allocno) New member allocno_prefs.
+ (ALLOCNO_PREFS): New macro.
+ (ira_prefs, ira_prefs_num): New external vars.
+ (ira_setup_alts, ira_get_dup_out_num, ira_debug_pref): New prototypes.
+ (ira_debug_prefs, ira_debug_allocno_prefs, ira_create_pref): Ditto.
+ (ira_add_allocno_pref, ira_remove_pref, ira_remove_allocno_prefs):
+ Ditto.
+ (ira_add_allocno_copy_to_list): Remove prototype.
+ (ira_swap_allocno_copy_ends_if_necessary): Ditto.
+ (ira_pref_iterator): New type.
+ (ira_pref_iter_init, ira_pref_iter_cond): New functions.
+ (FOR_EACH_PREF): New macro.
+ * ira.c (commutative_constraint_p): Move from ira-conflicts.c.
+ (ira_get_dup_out_num): Ditto. Rename from get_dup_num. Modify the
+ code.
+ (ira_setup_alts): New function.
+ (decrease_live_ranges_number): New function.
+ (ira): Call the above function.
+ * ira-build.c (ira_prefs, ira_prefs_num): New global vars.
+ (ira_create_allocno): Initialize allocno prefs.
+ (pref_pool, pref_vec): New static vars.
+ (initiate_prefs, find_allocno_pref, ira_create_pref): New
+ functions.
+ (add_allocno_pref_to_list, ira_add_allocno_pref, print_pref): Ditto.
+ (ira_debug_pref, print_prefs, ira_debug_prefs): Ditto.
+ (print_allocno_prefs, ira_debug_allocno_prefs, finish_pref): Ditto.
+ (ira_remove_pref, ira_remove_allocno_prefs, finish_prefs): Ditto.
+ (ira_add_allocno_copy_to_list): Make static. Rename to
+ add_allocno_copy_to_list.
+ (ira_swap_allocno_copy_ends_if_necessary): Make static. Rename to
+ swap_allocno_copy_ends_if_necessary.
+ (remove_unnecessary_allocnos, remove_low_level_allocnos): Call
+ ira_remove_allocno_prefs.
+ (ira_flattening): Ditto.
+ (ira_build): Call initiate_prefs, print_prefs.
+ (ira_destroy): Call finish_prefs.
+ * ira-color.c (struct update_cost_record): New.
+ (struct allocno_color_data): Add new member update_cost_records.
+ (update_cost_record_pool): New static var.
+ (init_update_cost_records, get_update_cost_record): New functions.
+ (free_update_cost_record_list, finish_update_cost_records): Ditto.
+ (struct update_cost_queue_elem): Add member from.
+ (initiate_cost_update): Call init_update_cost_records.
+ (finish_cost_update): Call finish_update_cost_records.
+ (queue_update_cost, get_next_update_cost): Add new param from.
+ (Update_allocno_cost, update_costs_from_allocno): New functions.
+ (update_costs_from_prefs): Ditto.
+ (update_copy_costs): Rename to update_costs_from_copies.
+ (restore_costs_from_copies): New function.
+ (update_conflict_hard_regno_costs): Don't go back.
+ (assign_hard_reg): Call restore_costs_from_copies. Add printing
+ more debug info.
+ (pop_allocnos): Add priniting more debug info.
+ (color_allocnos): Remove prefs for conflicting hard regs.
+ Call update_costs_from_prefs.
+ * ira-conflicts.c (commutative_constraint_p): Move to ira.c
+ (get_dup_num): Rename, modify, and move to ira.c
+ (process_regs_for_copy): Add prefs.
+ (add_insn_allocno_copies): Put src as first arg of
+ process_regs_for_copy. Remove dead code. Call ira_setup_alts.
+ * ira-costs.c (record_reg_classes): Modify and move code into
+ record_operands_costs.
+ (find_costs_and_classes): Create prefs for the hard reg of small
+ reg class.
+ (process_bb_node_for_hard_reg_moves): Add prefs.
+
+2013-10-30 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/57100
+ * basic-block.h (pre_and_rev_post_order_compute_fn): New function.
+ * cfganal.c (pre_and_rev_post_order_compute_fn): New function
+ as worker for ...
+ (pre_and_rev_post_order_compute): ... which now wraps it.
+ * graph.c (draw_cfg_nodes_no_loops): Use
+ pre_and_rev_post_order_compute_fn to avoid ICEing and dependence
+ on cfun.
+
+2013-10-30 Christian Bruel <christian.bruel@st.com>
+
+ * config/sh/sh-mem.cc (sh_expand_cmpnstr): New function.
+ (sh_expand_cmpstr): Handle known align and schedule improvements.
+ * config/sh/sh-protos.h (sh_expand_cmpstrn): Declare.
+ * config/sh/sh.md (cmpstrnsi): New pattern.
+
+2013-10-30 Martin Jambor <mjambor@suse.cz>
+
+ PR rtl-optimization/10474
+ * ira.c (find_moveable_pseudos): Do not calculate dominance info
+ nor df analysis.
+ (interesting_dest_for_shprep): New function.
+ (split_live_ranges_for_shrink_wrap): Likewise.
+ (ira): Calculate dominance info and df analysis. Call
+ split_live_ranges_for_shrink_wrap.
+
+2013-10-30 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
+
+ PR target/58854
+ * config/arm/arm.c (arm_expand_epilogue_apcs_frame): Emit blockage.
+
+2013-10-30 Ilya Enkovich <ilya.enkovich@intel.com>
+
+ * tree-core.h (tree_index): Add TI_POINTER_BOUNDS_TYPE.
+ * tree.h (POINTER_BOUNDS_P): New.
+ (BOUNDED_TYPE_P): New.
+ (BOUNDED_P): New.
+ (pointer_bounds_type_node): New.
+ * tree.c (build_common_tree_nodes): Initialize
+ pointer_bounds_type_node.
+ * gimple.h (gimple_call_get_nobnd_arg_index): New.
+ (gimple_call_num_nobnd_args): New.
+ (gimple_call_nobnd_arg): New.
+ (gimple_return_retbnd): New.
+ (gimple_return_set_retbnd): New
+ * gimple.c (gimple_build_return): Increase number of ops
+ for return statement.
+ (gimple_call_get_nobnd_arg_index): New.
+ * gimple-pretty-print.c (dump_gimple_return): Print second op.
+
+2013-10-30 Ilya Enkovich <ilya.enkovich@intel.com>
+
+ * ipa.c (cgraph_build_static_cdtor_1): Support contructors
+ with "chkp ctor" and "bnd_legacy" attributes.
+ * gimplify.c (gimplify_init_constructor): Avoid infinite
+ loop during gimplification of bounds initializer.
+
+2013-10-30 Ilya Enkovich <ilya.enkovich@intel.com>
+
+ * c-family/c-common.c (handle_bnd_variable_size_attribute): New.
+ (handle_bnd_legacy): New.
+ (c_common_attribute_table): Add bnd_variable_size and bnd_legacy.
+ * doc/extend.texi: Document bnd_variable_size and bnd_legacy
+ attributes.
+
+2013-10-29 Ilya Enkovich <ilya.enkovich@intel.com>
+
+ * builtin-types.def (BT_FN_VOID_CONST_PTR): New.
+ (BT_FN_PTR_CONST_PTR): New.
+ (BT_FN_CONST_PTR_CONST_PTR): New.
+ (BT_FN_PTR_CONST_PTR_SIZE): New.
+ (BT_FN_PTR_CONST_PTR_CONST_PTR): New.
+ (BT_FN_VOID_PTRPTR_CONST_PTR): New.
+ (BT_FN_VOID_CONST_PTR_SIZE): New.
+ (BT_FN_PTR_CONST_PTR_CONST_PTR_SIZE): New.
+ * chkp-builtins.def: New.
+ * builtins.def: include chkp-builtins.def.
+ (DEF_CHKP_BUILTIN): New.
+ * builtins.c (expand_builtin): Support BUILT_IN_CHKP_INIT_PTR_BOUNDS,
+ BUILT_IN_CHKP_NULL_PTR_BOUNDS, BUILT_IN_CHKP_COPY_PTR_BOUNDS,
+ BUILT_IN_CHKP_CHECK_PTR_LBOUNDS, BUILT_IN_CHKP_CHECK_PTR_UBOUNDS,
+ BUILT_IN_CHKP_CHECK_PTR_BOUNDS, BUILT_IN_CHKP_SET_PTR_BOUNDS,
+ BUILT_IN_CHKP_NARROW_PTR_BOUNDS, BUILT_IN_CHKP_STORE_PTR_BOUNDS,
+ BUILT_IN_CHKP_GET_PTR_LBOUND, BUILT_IN_CHKP_GET_PTR_UBOUND,
+ BUILT_IN_CHKP_BNDMK, BUILT_IN_CHKP_BNDSTX, BUILT_IN_CHKP_BNDCL,
+ BUILT_IN_CHKP_BNDCU, BUILT_IN_CHKP_BNDLDX, BUILT_IN_CHKP_BNDRET,
+ BUILT_IN_CHKP_INTERSECT, BUILT_IN_CHKP_ARG_BND, BUILT_IN_CHKP_NARROW,
+ BUILT_IN_CHKP_EXTRACT_LOWER, BUILT_IN_CHKP_EXTRACT_UPPER.
+ * common.opt (fcheck-pointer-bounds): New.
+ * toplev.c (process_options): Check Pointer Bounds Checker is
+ supported.
+ * doc/extend.texi: Document Pointer Bounds Checker built-in functions.
+
+2013-10-30 Ilya Enkovich <ilya.enkovich@intel.com>
+
+ * target.def (builtin_chkp_function): New.
+ (chkp_bound_type): New.
+ (chkp_bound_mode): New.
+ (fn_abi_va_list_bounds_size): New.
+ (load_bounds_for_arg): New.
+ (store_bounds_for_arg): New.
+ * targhooks.h (default_load_bounds_for_arg): New.
+ (default_store_bounds_for_arg): New.
+ (default_fn_abi_va_list_bounds_size): New.
+ (default_chkp_bound_type): New.
+ (default_chkp_bound_mode): New.
+ (default_builtin_chkp_function): New.
+ * targhooks.c (default_load_bounds_for_arg): New.
+ (default_store_bounds_for_arg): New.
+ (default_fn_abi_va_list_bounds_size): New.
+ (default_chkp_bound_type): New.
+ (default_chkp_bound_mode); New.
+ (default_builtin_chkp_function): New.
+ * doc/tm.texi.in (TARGET_FN_ABI_VA_LIST_BOUNDS_SIZE): New.
+ (TARGET_LOAD_BOUNDS_FOR_ARG): New.
+ (TARGET_STORE_BOUNDS_FOR_ARG): New.
+ (TARGET_BUILTIN_CHKP_FUNCTION): New.
+ (TARGET_CHKP_BOUND_TYPE): New.
+ (TARGET_CHKP_BOUND_MODE): New.
+ * doc/tm.texi: Regenerated.
+ * langhooks.h (lang_hooks): Add chkp_supported field.
+ * langhooks-def.h (LANG_HOOKS_CHKP_SUPPORTED): New.
+ (LANG_HOOKS_INITIALIZER); Add LANG_HOOKS_CHKP_SUPPORTED.
+
+2013-10-29 Andrew Pinski <apinski@cavium.com>
+
+ * tree-ssa-ifcombine.c: Include rtl.h and tm_p.h.
+ (ifcombine_ifandif): Handle cases where maybe_fold_and_comparisons
+ fails, combining the branches anyways.
+ (tree_ssa_ifcombine): Inverse the order of the basic block walk,
+ increases the number of combinings.
+ * gimple.h (gsi_start_nondebug_after_labels_bb): New function.
+
+2013-10-29 Mike Stump <mikestump@comcast.net>
+
+ * machmode.def (PARTIAL_INT_MODE): Add precision and name.
+ * genmodes.c (PARTIAL_INT_MODE): Add precision and name.
+ (make_vector_mode): Increase namebuf to 16.
+ (emit_insn_modes_h): When processing BImode, don't
+ also match partial int modes.
+ (emit_class_narrowest_mode): Likewise.
+
+ * config/bfin/bfin-modes.def: Add precision to PDI.
+ * config/m32c/m32c-modes.def: Add precision to PSI.
+ * config/msp430/msp430-modes.def: Add precision to PSI.
+ * config/rs6000/rs6000-modes.def: Add precision to PTI.
+ * config/sh/sh-modes.def: Add precision to PSI and PDI.
+
+2013-10-29 Oleg Endo <olegendo@gcc.gnu.org>
+
+ PR target/54236
+ * config/sh/sh.md (*addc): Rename existing variations to ...
+ (*addc_r_r_1, *addc_2r_1, *addc_r_1): ... these.
+ (*addc_r_lsb, *addc_r_r_lsb, *addc_r_lsb_r, *addc_2r_lsb, *addc_r_msb,
+ *addc_r_r_msb, *addc_2r_msb): New insn_and_split patterns.
+ * config/sh/sh.c (addsubcosts): Handle some addc special cases.
+
+2013-10-29 Teresa Johnson <tejohnson@google.com>
+
+ PR ipa/58862
+ * tree-ssa-tail-merge.c (replace_block_by): Tolerate profile
+ insanities when updating probabilities.
+
+2013-10-29 David Malcolm <dmalcolm@redhat.com>
+
+ * gdbhooks.py (CGraphNodePrinter.to_string): Update gdb
+ prettyprinter for cgraph_node to reflect the conversion of the
+ symtable types to a C++ class hierarchy: it now *is* a
+ symtab_node_base, rather than having one (named "symbol").
+
+2013-10-29 Balaji V. Iyer <balaji.v.iyer@intel.com>
+
+ * builtins.c (is_builtin_name): Added a check for __cilkrts_detach and
+ __cilkrts_pop_frame. If matched, then return true for built-in
+ function name.
+ (expand_builtin): Added BUILT_IN_CILK_DETACH and
+ BUILT_IN_CILK_POP_FRAME case.
+ * langhooks-def.h (lhd_install_body_with_frame_cleanup): New prototype.
+ (lhs_cilk_detect_spawn): Likewise.
+ (LANG_HOOKS_DECLS): Added LANG_HOOKS_CILKPLUS.
+ (LANG_HOOKS_CILKPLUS_DETECT_SPAWN_AND_UNWRAP): New #define.
+ (LANG_HOOKS_CILKPLUS_FRAME_CLEANUP): Likewise.
+ (LANG_HOOKS_CILKPLUS_GIMPLIFY_SPAWN): Likewise.
+ (LANG_HOOKS_CILKPLUS): Likewise.
+ * tree.h (CILK_SPAWN_FN): Likewise.
+ * builtin.def (DEF_CILK_BUILTIN_STUB): Likewise.
+ * Makefile.in (C_COMMON_OBJS): Added c-family/cilk.o.
+ (OBJS): Added cilk-common.o.
+ (BUILTINS_DEF): Added cilk-builtins.def.
+ * langhooks.c (lhd_install_body_with_frame_cleanup): New function.
+ (lhd_cilk_detect_spawn): Likewise.
+ * langhooks.h (lang_hooks_for_cilkplus): New struct.
+ (struct lang_hooks): Added new field called "cilkplus."
+ * cilk-common.c: New file.
+ * cilk.h: Likewise.
+ * cilk-builtins.def: Likewise.
+ * cppbuiltin.c (define_builtin_macros_for_compilation_flags): Added
+ "__cilk" macro and set it to 200.
+ * function.h (struct function::cilk_frame_decl): New field.
+ (struct function::is_cilk_function): Likewise.
+ (struct function::calls_cilk_spawn): Likewise.
+ * gimplify.c (gimplify_call_expr): Added a check if the function call
+ being gimplified is a spawn detach point. If so, then add pop_frame
+ and detach function calls.
+ (gimplify_expr): Added a CILK_SPAWN_STMT and CILK_SYNC_STMT case
+ for gimplifying _Cilk_spawn and _Cilk_sync statements.
+ (gimplify_return_expr): Added a check for _Cilk_spawn usage in
+ function. If so, added a _Cilk_sync and gimplified it.
+ (gimplify_modify_expr): Added a check for _Cilk_spawn in MODIFY and
+ INIT_EXPRs. If so, then call gimplify_cilk_spawn.
+ * ipa-inline-analysis (initialize_inline_failed): Prevent inlining of
+ spawner function.
+ (can_inline_edge_p): Prevent inling of spawnee function.
+ * ira.c (ira_setup_eliminable_regset): Force usage of frame pointer
+ for functions that use Cilk keywords.
+ * tree-inline.h (struct copy_body_data::remap_var_for_cilk): New field.
+ * tree-pretty-print.c (dump_generic_node): Added CILK_SPAWN_STMT and
+ CILK_SYNC_STMT cases.
+ * tree.def (DEFTREECODE): Added CILK_SPAWN_STMT and CILK_SYNC_STMT
+ trees.
+ * generic.texi (CILK_SPAWN_STMT): Added documentation for _Cilk_spawn.
+ (CILK_SYNC_STMT): Added documentation for _Cilk_sync.
+ * passes.texi (Cilk Keywords): New section that describes the compiler
+ code changes for handling Cilk Keywords.
+
+2013-10-29 David Malcolm <dmalcolm@redhat.com>
+
+ Patch autogenerated by refactor_symtab.py from
+ https://github.com/davidmalcolm/gcc-refactoring-scripts
+ revision 58bb219cc090b2f4516a9297d868c245495ee622
+
+ * asan.c (asan_finish_file): Update for conversion of symtab types to
+ a true class hierarchy.
+ * cfgexpand.c (estimated_stack_frame_size): Likewise.
+ * cgraph.c (cgraph_get_body): Likewise.
+ (cgraph_get_create_real_symbol_node): Likewise.
+ (verify_cgraph_node): Likewise.
+ (verify_edge_corresponds_to_fndecl): Likewise.
+ (verify_edge_count_and_frequency): Likewise.
+ (cgraph_will_be_removed_from_program_if_no_direct_calls): Likewise.
+ (cgraph_can_remove_if_no_direct_calls_p): Likewise.
+ (cgraph_can_remove_if_no_direct_calls_and_refs_p): Likewise.
+ (cgraph_node_cannot_return): Likewise.
+ (cgraph_set_pure_flag_1): Likewise.
+ (cgraph_set_const_flag_1): Likewise.
+ (cgraph_set_nothrow_flag_1): Likewise.
+ (cgraph_make_node_local_1): Likewise.
+ (cgraph_for_node_and_aliases): Likewise.
+ (cgraph_for_node_thunks_and_aliases): Likewise.
+ (cgraph_node_can_be_local_p): Likewise.
+ (cgraph_node_cannot_be_local_p_1): Likewise.
+ (cgraph_function_body_availability): Likewise.
+ (dump_cgraph_node): Likewise.
+ (cgraph_rtl_info): Likewise.
+ (cgraph_mark_address_taken_node): Likewise.
+ (cgraph_remove_node): Likewise.
+ (cgraph_release_function_body): Likewise.
+ (cgraph_update_edges_for_call_stmt_node): Likewise.
+ (cgraph_redirect_edge_call_stmt_to_callee): Likewise.
+ (cgraph_make_edge_direct): Likewise.
+ (cgraph_resolve_speculation): Likewise.
+ (cgraph_speculative_call_info): Likewise.
+ (cgraph_turn_edge_to_speculative): Likewise.
+ (cgraph_create_edge_1): Likewise.
+ (cgraph_set_call_stmt): Likewise.
+ (cgraph_node_for_asm): Likewise.
+ (cgraph_add_thunk): Likewise.
+ (cgraph_same_body_alias): Likewise.
+ (cgraph_create_function_alias): Likewise.
+ (cgraph_create_node): Likewise.
+ (cgraph_create_empty_node): Likewise.
+ (record_function_versions): Likewise.
+ (used_from_object_file_p): Likewise.
+ * cgraph.h (symtab_can_be_discarded): Likewise.
+ (symtab_real_symbol_p): Likewise.
+ (cgraph_mark_force_output_node): Likewise.
+ (cgraph_edge_recursive_p): Likewise.
+ (symtab_alias_target): Likewise.
+ (varpool_all_refs_explicit_p): Likewise.
+ (varpool_can_remove_if_no_refs): Likewise.
+ (cgraph_only_called_directly_or_aliased_p): Likewise.
+ (cgraph_next_function_with_gimple_body): Likewise.
+ (cgraph_first_function_with_gimple_body): Likewise.
+ (cgraph_function_with_gimple_body_p): Likewise.
+ (cgraph_next_function): Likewise.
+ (cgraph_first_function): Likewise.
+ (cgraph_next_defined_function): Likewise.
+ (cgraph_first_defined_function): Likewise.
+ (varpool_next_defined_variable): Likewise.
+ (varpool_first_defined_variable): Likewise.
+ (varpool_next_static_initializer): Likewise.
+ (varpool_first_static_initializer): Likewise.
+ (varpool_next_variable): Likewise.
+ (varpool_first_variable): Likewise.
+ (varpool_node_name): Likewise.
+ (varpool): Likewise.
+ (cgraph): Likewise.
+ (is_a_helper <varpool_node>::test): Likewise.
+ (is_a_helper <cgraph_node>::test): Likewise.
+ (varpool_variable_node): Likewise.
+ (cgraph_function_or_thunk_node): Likewise.
+ (varpool_alias_target): Likewise.
+ (cgraph_alias_target): Likewise.
+ (cgraph_node_name): Likewise.
+ (varpool_node_asm_name): Likewise.
+ (cgraph_node_asm_name): Likewise.
+ * cgraphbuild.c (remove_cgraph_callee_edges): Likewise.
+ (cgraph_rebuild_references): Likewise.
+ (rebuild_cgraph_edges): Likewise.
+ (record_eh_tables): Likewise.
+ (build_cgraph_edges): Likewise.
+ (mark_store): Likewise.
+ (mark_load): Likewise.
+ (mark_address): Likewise.
+ (record_type_list): Likewise.
+ (record_reference): Likewise.
+ * cgraphclones.c (cgraph_materialize_all_clones): Likewise.
+ (cgraph_materialize_clone): Likewise.
+ (cgraph_function_versioning): Likewise.
+ (cgraph_copy_node_for_versioning): Likewise.
+ (update_call_expr): Likewise.
+ (cgraph_find_replacement_node): Likewise.
+ (cgraph_create_virtual_clone): Likewise.
+ (cgraph_clone_node): Likewise.
+ * cgraphunit.c (compile): Likewise.
+ (output_weakrefs): Likewise.
+ (output_in_order): Likewise.
+ (expand_function): Likewise.
+ (assemble_thunks_and_aliases): Likewise.
+ (expand_thunk): Likewise.
+ (mark_functions_to_output): Likewise.
+ (handle_alias_pairs): Likewise.
+ (analyze_functions): Likewise.
+ (walk_polymorphic_call_targets): Likewise.
+ (varpool_finalize_decl): Likewise.
+ (process_function_and_variable_attributes): Likewise.
+ (cgraph_process_same_body_aliases): Likewise.
+ (analyze_function): Likewise.
+ (cgraph_add_new_function): Likewise.
+ (cgraph_finalize_function): Likewise.
+ (referred_to_p): Likewise.
+ (cgraph_reset_node): Likewise.
+ (cgraph_process_new_functions): Likewise.
+ (enqueue_node): Likewise.
+ (decide_is_symbol_needed): Likewise.
+ * coverage.c (coverage_compute_profile_id): Likewise.
+ * dbxout.c (dbxout_expand_expr): Likewise.
+ * dwarf2out.c (premark_types_used_by_global_vars_helper): Likewise.
+ (reference_to_unused): Likewise.
+ * gimple-fold.c (can_refer_decl_in_current_unit_p): Likewise.
+ * gimplify.c (unvisit_body): Likewise.
+ (unshare_body): Likewise.
+ * ipa-cp.c (ipcp_generate_summary): Likewise.
+ (ipcp_decision_stage): Likewise.
+ (identify_dead_nodes): Likewise.
+ (decide_whether_version_node): Likewise.
+ (decide_about_value): Likewise.
+ (perhaps_add_new_callers): Likewise.
+ (create_specialized_node): Likewise.
+ (update_profiling_info): Likewise.
+ (ipcp_propagate_stage): Likewise.
+ (estimate_local_effects): Likewise.
+ (good_cloning_opportunity_p): Likewise.
+ (devirtualization_time_bonus): Likewise.
+ (propagate_constants_accross_call): Likewise.
+ (initialize_node_lattices): Likewise.
+ (ipcp_cloning_candidate_p): Likewise.
+ (determine_versionability): Likewise.
+ (print_all_lattices): Likewise.
+ (print_lattice): Likewise.
+ (ipcp_discover_new_direct_edges): Likewise.
+ * ipa-devirt.c (ipa_devirt): Likewise.
+ (likely_target_p): Likewise.
+ (update_type_inheritance_graph): Likewise.
+ (possible_polymorphic_call_target_p): Likewise.
+ (dump_possible_polymorphic_call_targets): Likewise.
+ (devirt_variable_node_removal_hook): Likewise.
+ (record_binfo): Likewise.
+ (maybe_record_node): Likewise.
+ (build_type_inheritance_graph): Likewise.
+ * ipa-inline-analysis.c (inline_write_summary): Likewise.
+ (inline_generate_summary): Likewise.
+ (inline_analyze_function): Likewise.
+ (do_estimate_growth): Likewise.
+ (simple_edge_hints): Likewise.
+ (estimate_node_size_and_time): Likewise.
+ (estimate_edge_devirt_benefit): Likewise.
+ (compute_inline_parameters): Likewise.
+ (estimate_function_body_sizes): Likewise.
+ (compute_bb_predicates): Likewise.
+ (initialize_inline_failed): Likewise.
+ (dump_inline_summary): Likewise.
+ (dump_inline_edge_summary): Likewise.
+ * ipa-inline-transform.c (inline_transform): Likewise.
+ (preserve_function_body_p): Likewise.
+ (save_inline_function_body): Likewise.
+ (inline_call): Likewise.
+ (clone_inlined_nodes): Likewise.
+ (can_remove_node_now_p): Likewise.
+ (can_remove_node_now_p_1): Likewise.
+ * ipa-inline.c (early_inliner): Likewise.
+ (early_inline_small_functions): Likewise.
+ (inline_always_inline_functions): Likewise.
+ (ipa_inline): Likewise.
+ (flatten_function): Likewise.
+ (inline_small_functions): Likewise.
+ (speculation_useful_p): Likewise.
+ (recursive_inlining): Likewise.
+ (update_caller_keys): Likewise.
+ (reset_edge_caches): Likewise.
+ (update_edge_key): Likewise.
+ (edge_badness): Likewise.
+ (relative_time_benefit): Likewise.
+ (want_inline_self_recursive_call_p): Likewise.
+ (want_inline_small_function_p): Likewise.
+ (want_early_inline_function_p): Likewise.
+ (num_calls): Likewise.
+ (can_early_inline_edge_p): Likewise.
+ (can_inline_edge_p): Likewise.
+ (report_inline_failed_reason): Likewise.
+ * ipa-profile.c (ipa_profile): Likewise.
+ (ipa_propagate_frequency): Likewise.
+ (ipa_propagate_frequency_1): Likewise.
+ (ipa_profile_generate_summary): Likewise.
+ * ipa-prop.c (ipcp_transform_function): Likewise.
+ (read_replacements_section): Likewise.
+ (ipa_prop_read_section): Likewise.
+ (ipa_modify_call_arguments): Likewise.
+ (ipa_print_node_params): Likewise.
+ (propagate_controlled_uses): Likewise.
+ (update_indirect_edges_after_inlining): Likewise.
+ (remove_described_reference): Likewise.
+ (ipa_make_edge_direct_to_target): Likewise.
+ (ipa_analyze_node): Likewise.
+ (ipa_analyze_params_uses): Likewise.
+ (ipa_compute_jump_functions): Likewise.
+ (ipa_get_callee_param_type): Likewise.
+ (ipa_print_node_jump_functions): Likewise.
+ (ipa_initialize_node_params): Likewise.
+ (ipa_populate_param_decls): Likewise.
+ (ipa_func_spec_opts_forbid_analysis_p): Likewise.
+ (write_agg_replacement_chain): Likewise.
+ (ipa_write_node_info): Likewise.
+ (ipa_edge_duplication_hook): Likewise.
+ (try_decrement_rdesc_refcount): Likewise.
+ * ipa-pure-const.c (propagate_nothrow): Likewise.
+ (propagate_pure_const): Likewise.
+ (pure_const_read_summary): Likewise.
+ (pure_const_write_summary): Likewise.
+ (analyze_function): Likewise.
+ * ipa-ref-inline.h (ipa_ref_referred_ref_list): Likewise.
+ (ipa_ref_referring_ref_list): Likewise.
+ * ipa-ref.c (ipa_clear_stmts_in_references): Likewise.
+ (ipa_remove_stmt_references): Likewise.
+ (ipa_find_reference): Likewise.
+ (ipa_dump_referring): Likewise.
+ (ipa_dump_references): Likewise.
+ (ipa_record_reference): Likewise.
+ * ipa-reference.c (ipa_reference_read_optimization_summary): Likewise.
+ (ipa_reference_write_optimization_summary): Likewise.
+ (write_node_summary_p): Likewise.
+ (propagate): Likewise.
+ (read_write_all_from_decl): Likewise.
+ (generate_summary): Likewise.
+ (analyze_function): Likewise.
+ (propagate_bits): Likewise.
+ (ipa_reference_get_not_written_global): Likewise.
+ (ipa_reference_get_not_read_global): Likewise.
+ * ipa-split.c (execute_split_functions): Likewise.
+ (split_function): Likewise.
+ * ipa-utils.c (ipa_merge_profiles): Likewise.
+ (dump_cgraph_node_set): Likewise.
+ (ipa_reverse_postorder): Likewise.
+ (ipa_edge_within_scc): Likewise.
+ (ipa_get_nodes_in_cycle): Likewise.
+ (ipa_free_postorder_info): Likewise.
+ (ipa_reduced_postorder): Likewise.
+ (searchc): Likewise.
+ (recursive_call_p): Likewise.
+ * ipa.c (ipa_cdtor_merge): Likewise.
+ (record_cdtor_fn): Likewise.
+ (function_and_variable_visibility): Likewise.
+ (varpool_externally_visible_p): Likewise.
+ (cgraph_externally_visible_p): Likewise.
+ (comdat_can_be_unshared_p): Likewise.
+ (comdat_can_be_unshared_p_1): Likewise.
+ (address_taken_from_non_vtable_p): Likewise.
+ (ipa_discover_readonly_nonaddressable_vars): Likewise.
+ (symtab_remove_unreachable_nodes): Likewise.
+ (walk_polymorphic_call_targets): Likewise.
+ (process_references): Likewise.
+ (enqueue_node): Likewise.
+ (has_addr_references_p): Likewise.
+ (cgraph_non_local_node_p_1): Likewise.
+ * is-a.h (varpool_analyze_node): Likewise.
+ * lto-cgraph.c (input_symtab): Likewise.
+ (merge_profile_summaries): Likewise.
+ (input_cgraph_1): Likewise.
+ (input_edge): Likewise.
+ (input_varpool_node): Likewise.
+ (input_node): Likewise.
+ (input_overwrite_node): Likewise.
+ (compute_ltrans_boundary): Likewise.
+ (output_refs): Likewise.
+ (lto_output_varpool_node): Likewise.
+ (lto_output_node): Likewise.
+ (reachable_from_other_partition_p): Likewise.
+ (referenced_from_other_partition_p): Likewise.
+ (lto_output_edge): Likewise.
+ (output_node_opt_summary): Likewise.
+ (add_node_to): Likewise.
+ (reachable_from_this_partition_p): Likewise.
+ (lto_set_symtab_encoder_in_partition): Likewise.
+ (lto_symtab_encoder_in_partition_p): Likewise.
+ (lto_set_symtab_encoder_encode_initializer): Likewise.
+ (lto_symtab_encoder_encode_initializer_p): Likewise.
+ (lto_set_symtab_encoder_encode_body): Likewise.
+ (lto_symtab_encoder_encode_body_p): Likewise.
+ * lto-section-in.c (lto_free_function_in_decl_state_for_node):
+ Likewise.
+ * lto-streamer-in.c (lto_read_body): Likewise.
+ (fixup_call_stmt_edges): Likewise.
+ (fixup_call_stmt_edges_1): Likewise.
+ * lto-streamer-out.c (produce_symtab): Likewise.
+ (output_symbol_p): Likewise.
+ (write_symbol): Likewise.
+ (lto_output): Likewise.
+ (copy_function): Likewise.
+ (output_function): Likewise.
+ * passes.c (function_called_by_processed_nodes_p): Likewise.
+ (ipa_write_optimization_summaries): Likewise.
+ (ipa_write_summaries): Likewise.
+ (do_per_function_toporder): Likewise.
+ (do_per_function): Likewise.
+ (dump_passes): Likewise.
+ * symtab.c (symtab_semantically_equivalent_p): Likewise.
+ (symtab_nonoverwritable_alias): Likewise.
+ (symtab_nonoverwritable_alias_1): Likewise.
+ (symtab_for_node_and_aliases): Likewise.
+ (symtab_resolve_alias): Likewise.
+ (fixup_same_cpp_alias_visibility): Likewise.
+ (symtab_alias_ultimate_target): Likewise.
+ (symtab_used_from_object_file_p): Likewise.
+ (verify_symtab_base): Likewise.
+ (dump_symtab_base): Likewise.
+ (symtab_node_name): Likewise.
+ (symtab_node_asm_name): Likewise.
+ (symtab_dissolve_same_comdat_group_list): Likewise.
+ (symtab_add_to_same_comdat_group): Likewise.
+ (symtab_unregister_node): Likewise.
+ (symtab_insert_node_to_hashtable): Likewise.
+ (symtab_register_node): Likewise.
+ (unlink_from_assembler_name_hash): Likewise.
+ (insert_to_assembler_name_hash): Likewise.
+ (eq_assembler_name): Likewise.
+ (hash_node_by_assembler_name): Likewise.
+ (eq_node): Likewise.
+ (hash_node): Likewise.
+ * toplev.c (wrapup_global_declaration_2): Likewise.
+ * trans-mem.c (ipa_tm_execute): Likewise.
+ (ipa_tm_transform_clone): Likewise.
+ (ipa_tm_transform_transaction): Likewise.
+ (ipa_tm_transform_calls_redirect): Likewise.
+ (ipa_tm_insert_gettmclone_call): Likewise.
+ (ipa_tm_insert_irr_call): Likewise.
+ (ipa_tm_create_version): Likewise.
+ (ipa_tm_create_version_alias): Likewise.
+ (ipa_tm_mark_forced_by_abi_node): Likewise.
+ (ipa_tm_mark_force_output_node): Likewise.
+ (ipa_tm_diagnose_tm_safe): Likewise.
+ (ipa_tm_mayenterirr_function): Likewise.
+ (ipa_tm_scan_irr_function): Likewise.
+ (ipa_tm_note_irrevocable): Likewise.
+ (ipa_tm_scan_calls_clone): Likewise.
+ (get_cg_data): Likewise.
+ * tree-eh.c (tree_could_trap_p): Likewise.
+ * tree-emutls.c (ipa_lower_emutls): Likewise.
+ (create_emultls_var): Likewise.
+ (lower_emutls_function_body): Likewise.
+ (gen_emutls_addr): Likewise.
+ (emutls_decl): Likewise.
+ (new_emutls_decl): Likewise.
+ * tree-inline.c (tree_function_versioning): Likewise.
+ (optimize_inline_calls): Likewise.
+ (expand_call_inline): Likewise.
+ (estimate_num_insns): Likewise.
+ (copy_bb): Likewise.
+ (delete_unreachable_blocks_update_callgraph): Likewise.
+ * tree-nested.c (gimplify_all_functions): Likewise.
+ (create_nesting_tree): Likewise.
+ (check_for_nested_with_variably_modified): Likewise.
+ * tree-pretty-print.c (dump_function_header): Likewise.
+ * tree-profile.c (tree_profiling): Likewise.
+ * tree-sra.c (ipa_sra_preliminary_function_checks): Likewise.
+ (modify_function): Likewise.
+ (convert_callers): Likewise.
+ (convert_callers_for_node): Likewise.
+ * tree-ssa-structalias.c (ipa_pta_execute): Likewise.
+ (associate_varinfo_to_alias): Likewise.
+ (create_variable_info_for): Likewise.
+ (get_constraint_for_ssa_var): Likewise.
+ * tree-vectorizer.c (increase_alignment): Likewise.
+ * tree.c (find_decls_types_in_var): Likewise.
+ (find_decls_types_in_node): Likewise.
+ (free_lang_data_in_decl): Likewise.
+ * value-prof.c (gimple_ic_transform): Likewise.
+ (gimple_ic): Likewise.
+ (check_ic_target): Likewise.
+ (init_node_map): Likewise.
+ * varasm.c (decl_binds_to_current_def_p): Likewise.
+ (default_binds_local_p_1): Likewise.
+ (dump_tm_clone_pairs): Likewise.
+ (assemble_alias): Likewise.
+ (find_decl): Likewise.
+ (mark_decl_referenced): Likewise.
+ * varpool.c (varpool_for_node_and_aliases): Likewise.
+ (varpool_extra_name_alias): Likewise.
+ (varpool_create_variable_alias): Likewise.
+ (add_new_static_var): Likewise.
+ (varpool_finalize_named_section_flags): Likewise.
+ (varpool_remove_unreferenced_decls): Likewise.
+ (enqueue_node): Likewise.
+ (varpool_assemble_decl): Likewise.
+ (assemble_aliases): Likewise.
+ (varpool_analyze_node): Likewise.
+ (cgraph_variable_initializer_availability): Likewise.
+ (varpool_add_new_variable): Likewise.
+ (ctor_for_folding): Likewise.
+ (dump_varpool_node): Likewise.
+ (varpool_remove_initializer): Likewise.
+ (varpool_remove_node): Likewise.
+ (varpool_node_for_decl): Likewise.
+ (varpool_create_empty_node): Likewise.
+ * config/i386/i386.c (ix86_generate_version_dispatcher_body): Likewise.
+ (ix86_get_function_versions_dispatcher): Likewise.
+
+2013-10-29 David Malcolm <dmalcolm@redhat.com>
+
+ * cgraph.h (symtab_node_base): Convert to a class;
+ add GTY((desc ("%h.type"), tag ("SYMTAB_SYMBOL"))), and take
+ chain_next/prev from symtab_node_def.
+ (cgraph_node): Inherit from symtab_node; add GTY option
+ tag ("SYMTAB_FUNCTION").
+ (varpool_node): Inherit from symtab_node; add GTY option
+ tag ("SYMTAB_VARIABLE").
+ (symtab_node_def): Remove.
+ (is_a_helper <cgraph_node>::test (symtab_node_def *)): Convert to...
+ (is_a_helper <cgraph_node>::test (symtab_node_base *)): ...this.
+ (is_a_helper <varpool_node>::test (symtab_node_def *)): Convert to...
+ (is_a_helper <varpool_node>::test (symtab_node_base *)): ...this.
+
+ * ipa-ref.h (symtab_node_def): Drop.
+ (symtab_node): Change underlying type from symtab_node_def to
+ symtab_node_base.
+ (const_symtab_node): Likwise.
+
+ * is-a.h: Update examples in comment.
+
+ * symtab.c (symtab_hash): Change symtab_node_def to symtab_node_base.
+ (assembler_name_hash): Likewise.
+
+2013-10-29 Martin Liska <marxin.liska@gmail.com>
+
+ * doc/tree-ssa.texi (gimple_phi_result): Document.
+ (gimple_phi_num_args, gimple_phi_arg): Likewise.
+ (gimple_phi_arg_edge, gimple_phi_arg_def): Likewise.
+ (PHI_RESULT, PHI_NUM_ARGS): Remove.
+ (PHI_ARG_ELT, PHI_ARG_EDGE, PHI_ARG_DEF): Likewise.
+
+2013-10-29 Andrew MacLeod <amacleod@redhat.com>
+
+ * expr.h: Revert change and include tree-core.h.
+ * rtl.h: Revert change and don't include tree-core.h.
+
+2013-10-29 Andrew MacLeod <amacleod@redhat.com>
+
+ * config/darwin.c: Include gimple.h.
+ * config/i386/winnt.c: Likewise.
+
+2013-10-29 Marc Glisse <marc.glisse@inria.fr>
+
+ PR tree-optimization/19831
+ * tree-ssa-alias.c (stmt_kills_ref_p_1): Handle BUILT_IN_FREE.
+
+2013-10-29 Andrew MacLeod <amacleod@redhat.com>
+
+ * tree-outof-ssa.h: Remove include files.
+ * tree-outof-ssa.c: Add required include files from tree-outof-ssa.h.
+ * expr.c: Likewise.
+ * tree-ssa-coalesce.c: Likewise.
+ * cfgexpand.c: Likewise.
+ * tree-ssa-ter.c: Likewise.
+ * ipa-prop.h: Remove gimple.h and tree-core.h from include list.
+ * lto-streamer.h: Likewise.
+ * cgraphbuild.c: Add gimple.h to include list.
+ * data-streamer-in.c: Likewise.
+ * ipa-cp.c: Likewise.
+ * tree-streamer.c: Likewise.
+ * lto-compress.c: Likewise.
+ * ipa-reference.c: Likewise.
+ * data-streamer-out.c: Likewise.
+ * lto-cgraph.c: Likewise.
+ * cgraphclones.c: Likewise.
+ * ipa-utils.c: Likewise.
+ * data-streamer.c: Likewise.
+ * ipa-split.c: Likewise.
+ * lto-section-in.c: Likewise.
+ * tree-streamer-out.c: Likewise.
+ * ipa-prop.c: Likewise.
+ * tree-streamer-in.c: Likewise.
+ * symtab.c: Likewise.
+ * opts-global.c: Likewise.
+ * lto-opts.c: Likewise.
+ * lto-section-out.c: Likewise.
+ * lto-streamer.c: Likewise.
+ * rtl.h: Add tree-core.h to include list.
+ * expr.h: Remove tree-core.h from include list.
+ * gimple.h: Likewise.
+ * ipa-utils.h: Likewise.
+ * streamer-hooks.h: Likewise.
+ * streamer-hooks.c: Include input.h.
+
+2013-10-29 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * config/arm/arm.c (cortexa7_extra_costs): New table.
+ (arm_cortex_a7_tune): New.
+ * config/arm/arm-cores.def: Use cortex_a7 tuning for cortex-a7.
+
+2013-10-29 Eric Botcazou <ebotcazou@adacore.com>
+
+ * expr.c (expand_expr_real_1) <MEM_EXPR>: Eliminate small redundancy.
+
+2013-10-29 David Malcolm <dmalcolm@redhat.com>
+
+ * doc/gty.texi ("Inheritance and GTY"): Make it clear that
+ to use autogenerated markers for a class-hierarchy, every class
+ must have a GTY marker.
+ * gengtype.h (struct type): Add linked list of subclasses to
+ the "s" member of the union.
+ (add_subclass): New decl.
+ * gengtype-state.c (read_state_struct_type): Set up subclass
+ linked list.
+ * gengtype.c (get_ultimate_base_class): New.
+ (add_subclass): New.
+ (new_structure): Set up subclass linked list.
+ (set_gc_used_type): Propagate usage information to subclasses.
+ (output_mangled_typename): Use get_ultimate_base_class.
+ (walk_subclasses): Use the subclass linked list, avoiding an
+ O(N^2) when writing out all types.
+ (walk_type): Issue an error if the base class is missing a tag,
+ rather than generating bogus C code. Add a gcc_unreachable
+ default case, in case people omit tags from concrete subclasses,
+ or get the values wrong.
+ (write_func_for_structure): Issue an error for subclasses for
+ which the base doesn't have a "desc", since otherwise the
+ autogenerated routines for the base would silently fail to visit
+ any subclass fields.
+ (write_root): Use get_ultimate_base_class, tweaking constness of
+ tp to match that function's signature.
+
+2013-10-29 David Malcolm <dmalcolm@redhat.com>
+
+ * doc/gty.texi (GTY Options): Add note about inheritance to
+ description of desc and tag.
+ (Inheritance and GTY): New.
+
+2013-10-29 David Malcolm <dmalcolm@redhat.com>
+
+ * gengtype-parse.c (opts_have): Drop "static" so that
+ we can use this from gengtype.c.
+ * gengtype.c (set_gc_used_type): Mark any base class as used;
+ update field traversal to visit inherited fields.
+ (output_mangled_typename): Convert references to classes within
+ an inheritance hierarchy to reference the ultimate base class,
+ since only it will have gt_ functions.
+ (get_string_option): New.
+ (walk_subclasses): New.
+ (walk_type): Treat GTY structs that have a "desc" as being the
+ root of an inheritance hierarchy. Generate a switch on it
+ within the marking function which walks all subclasses, adding
+ cases for them via walk_subclasses. For subclasses, visit all
+ fields of the type (including inherited ones).
+ (write_func_for_structure): Don't write fns for subclasses, only
+ for the ultimate base class within an inheritance hierarchy.
+ Subclasses-marking will be handled by the base class marking functions.
+ (write_types): Likewise.
+ (write_local_func_for_structure): Likewise.
+ (USED_BY_TYPED_GC_P): Emit allocators for subclasses that have
+ a "tag" option (and are thus concrete subclasses).
+ (write_root): Use the marker function for the ultimate base class.
+ * gengtype.h (FOR_ALL_INHERITED_FIELDS): New.
+ (opts_have): Add declaration.
+
+2013-10-28 Vladimir Makarov <vmakarov@redhat.com>
+
+ * lra-spills.c (lra_final_code_change): Remove useless move insns
+ originated from moves of pseudos.
+
+2013-10-28 Jeff Law <law@redhat.com>
+
+ * lower-subreg.c (resolve_simple_move): Fix comment typo.
+
+2013-10-28 Trevor Saunders <tsaunders@mozilla.com>
+
+ * df-scan.c (df_collection_rec): Adjust.
+ (copy_defs): New constant.
+ (copy_uses): Likewise.
+ (copy_eq_uses): Likewise.
+ (copy_mw): Likewise.
+ (copy_all): Likewise.
+ (df_insn_rescan): Adjust.
+ (df_notes_rescan): Likewise.
+ (df_swap_refs): Likewise.
+ (df_sort_and_compress_refs): Likewise.
+ (df_sort_and_compress_mws): Likewise.
+ (df_install_refs): Likewise.
+ (df_install_mws): Likewise.
+ (df_refs_add_to_chains): Add flags parameter controlling which vectors
+ are coppied.
+ (df_bb_refs_record): Adjust.
+ (df_record_entry_block_defs): Likewise.
+ (df_record_exit_block_defs): Likewise.
+ (df_refs_verify): Likewise.
+ (df_mws_verify): Likewise.
+ (df_insn_refs_verify): Likewise.
+ (df_bb_verify): Likewise.
+ * ipa-pure-const.c (finish_state): Remove.
+ (propagate): Adjust.
+ * tree-data-ref.c tree-ssa-alias.c tree-ssa-loop-ivcanon.c
+ tree-ssa-threadedge.c tree-vect-loop-manip.c tree-vect-slp.c
+ var-tracking.c: Adjust.
+ * vec.c (stack_vecs): Remove.
+ (register_stack_vec): Likewise.
+ (stack_vec_register_index): Likewise.
+ (unregister_stack_vec): Likewise.
+ * vec.h (struct va_stack): Remove.
+ (struct vec<T, A, vl_ptr>): Specialize as
+ struct vec<T, va_heap, vl_ptr> instead since va_heap is the only
+ allocation strategy compatable with the vl_ptr layout.
+ (struct vec<T, va_gc, vl_ptr>): Remove because it now gets an empty
+ specialization anyway.
+ (class stack_vec): New class.
+ (vec_stack_alloc): Remove.
+ (vec<T, va_heap, vl_ptr>::using_auto_storage): New method.
+
+2013-10-28 Alexander Ivchenko <alexander.ivchenko@intel.com>
+ Maxim Kuznetsov <maxim.kuznetsov@intel.com>
+ Sergey Lega <sergey.s.lega@intel.com>
+ Anna Tikhonova <anna.tikhonova@intel.com>
+ Ilya Tocar <ilya.tocar@intel.com>
+ Andrey Turetskiy <andrey.turetskiy@intel.com>
+ Ilya Verbin <ilya.verbin@intel.com>
+ Kirill Yukhin <kirill.yukhin@intel.com>
+ Michael Zolotukhin <michael.v.zolotukhin@intel.com>
+
+ * config/i386/i386.md (prefetch): Allow TARGET_AVX512PF.
+ (*prefetch_avx512pf_<mode>): New.
+ * config/i386/sse.md (avx512f_vmcmp<mode>3): Ditto.
+ (avx512f_maskcmp<mode>3): Ditto.
+ (vashrv16si3): Ditto.
+
+2013-10-28 Alexander Ivchenko <alexander.ivchenko@intel.com>
+ Maxim Kuznetsov <maxim.kuznetsov@intel.com>
+ Sergey Lega <sergey.s.lega@intel.com>
+ Anna Tikhonova <anna.tikhonova@intel.com>
+ Ilya Tocar <ilya.tocar@intel.com>
+ Andrey Turetskiy <andrey.turetskiy@intel.com>
+ Ilya Verbin <ilya.verbin@intel.com>
+ Kirill Yukhin <kirill.yukhin@intel.com>
+ Michael Zolotukhin <michael.v.zolotukhin@intel.com>
+
+ * config/i386/i386.md (any_truncate): New.
+ (trunsuffix): Ditto.
+ * config/i386/predicates.md (const_8_to_9_operand): New.
+ (const_10_to_11_operand): Ditto.
+ (const_12_to_13_operand): Ditto.
+ (const_14_to_15_operand): Ditto.
+ (const_16_to_19_operand): Ditto.
+ (const_20_to_23_operand): Ditto.
+ (const_24_to_27_operand): Ditto.
+ (const_28_to_31_operand): Ditto.
+ * config/i386/sse.md (unspec): Add UNSPEC_UNSIGNED_FIX_NOTRUNC.
+ (cvtusi2<ssescalarmodesuffix>32): New.
+ (cvtusi2<ssescalarmodesuffix>64): Ditto.
+ (ufloatv16siv16sf2): Ditto.
+ (avx512f_fix_notruncv16sfv16si): Ditto.
+ (avx512f_ufix_notruncv16sfv16si): Ditto.
+ (avx512f_vcvtss2usi): Ditto.
+ (avx512f_vcvtss2usiq): Ditto.
+ (avx512f_vcvttss2usi): Ditto.
+ (avx512f_vcvttss2usiq): Ditto.
+ (avx512f_vcvtsd2usi): Ditto.
+ (avx512f_vcvtsd2usiq): Ditto.
+ (avx512f_vcvttsd2usi): Ditto.
+ (avx512f_vcvttsd2usiq): Ditto.
+ (ufloatv8siv8df): Ditto.
+ (avx512f_cvtdq2pd512_2): Ditto.
+ (avx512f_cvtpd2dq512): Ditto.
+ (avx512f_ufix_notruncv8dfv8si): Ditto.
+ (avx512f_cvtpd2ps512): Ditto.
+ (vec_unpacks_lo_v16sf): Ditto.
+ (vec_unpacks_hi_v16sf): Ditto.
+ (vec_unpacks_float_hi_v16si): Ditto.
+ (vec_unpacks_float_lo_v16si): Ditto.
+ (avx512f_unpckhps512): Ditto.
+ (avx512f_unpcklps512): Ditto.
+ (avx512f_movshdup512): Ditto.
+ (avx512f_movsldup512): Ditto.
+ (vec_extract_lo_v32hi): Ditto.
+ (vec_extract_hi_v32hi): Ditto.
+ (vec_extract_lo_v64qi): Ditto.
+ (vec_extract_hi_v64qi): Ditto.
+ (avx512f_unpckhpd512): Ditto.
+ (avx512f_movddup512): Ditto.
+ (avx512f_unpcklpd512): Ditto.
+ (*avx512f_unpcklpd512): Ditto.
+ (avx512f_shufps512_1): Ditto.
+ (avx512f_shufpd512_1): Ditto.
+ (avx512f_interleave_highv8di): Ditto.
+ (avx512f_interleave_lowv8di): Ditto.
+ (PMOV_DST_MODE): Ditto.
+ (pmov_src_mode): Ditto.
+ (pmov_src_lower): Ditto.
+ (pmov_suff): Ditto.
+ (*avx512f_<code><pmov_src_lower><mode>2): Ditto.
+ (*avx512f_<code>v8div16qi2): Ditto.
+ (*avx512f_<code>v8div16qi2_store): Ditto.
+ (vec_widen_umult_even_v16si): Ditto.
+ (*vec_widen_umult_even_v16si): Ditto.
+ (vec_widen_smult_even_v16si): Ditto.
+ (*vec_widen_smult_even_v16si): Ditto.
+ (avx512f_interleave_highv16si): Ditto.
+ (avx512f_interleave_lowv16si): Ditto.
+ (avx512f_<code>v16qiv16si2): Ditto.
+ (avx512f_<code>v16hiv16si2): Ditto.
+ (avx512f_<code>v8qiv8di2): Ditto.
+ (avx512f_<code>v8hiv8di2): Ditto.
+ (avx512f_<code>v8siv8di2): Ditto.
+ (avx512cd_maskb_vec_dupv8di): Ditto.
+ (avx512cd_maskw_vec_dupv16si): Ditto.
+ (avx512f_vcvtph2ps512): Ditto.
+ (avx512f_vcvtps2ph512): Ditto.
+ (VEC_EXTRACT_MODE): Extened with wider modes.
+ (VEC_PERM_AVX2): Ditto.
+ (VEC_PERM_CONST): Ditto.
+
+2013-10-28 Joern Rennecke <joern.rennecke@embecosm.com>
+
+ * config/arc/arc.c (arc_ccfsm_post_advance):
+ Add comment about TYPE_RETURN.
+
+2013-10-28 Bin Cheng <bin.cheng@arm.com>
+
+ * tree-ssa-loop-ivopts.c (strip_offset_1): Change parameter type.
+ Count DECL_FIELD_BIT_OFFSET for COMPONENT_REF.
+ (strip_offset): Convert offset to unsigned number.
+
+2013-10-27 Tom de Vries <tom@codesourcery.com>
+
+ * cfgexpand.c (gimple_expand_cfg): Remove test for parm_birth_insn.
+ Don't commit insertions after NOTE_INSN_FUNCTION_BEG.
+
+2013-10-27 Oleg Endo <olegendo@gcc.gnu.org>
+
+ * config/sh/sh.c (MSW, LSW): Move and rename macros to...
+ * config/sh/sh.h (SH_REG_MSW_OFFSET, SH_REG_LSW_OFFSET): ... here.
+ (TARGET_BIG_ENDIAN): New macro.
+ * config/sh/sh.md: Use it instead of !TARGET_LITTLE_ENDIAN.
+ Use SH_REG_MSW_OFFSET and SH_REG_LSW_OFFSET.
+ * config/sh/sh.c: Likewise.
+ * config/sh/sh.h: Likewise.
+
+2013-10-27 Hans-Peter Nilsson <hp@axis.com>
+
+ * config/cris/cris.c (cris_emit_trap_for_misalignment): Replace the
+ removed PRED_MUDFLAP with PRED_NORETURN. Correct file-path in comment.
+
+2013-10-26 Oleg Endo <olegendo@gcc.gnu.org>
+
+ * config/sh/sh.md (movmemsi): Remove empty constraints and predicates.
+ Fix formatting.
+ (cmpstr_t, cmpstrsi): Fix formatting.
+
+2013-10-26 Oleg Endo <olegendo@gcc.gnu.org>
+
+ PR target/52483
+ * config/sh/predicates.md (general_movdst_operand): Allow reg+reg
+ addressing, do not use general_operand for memory operands.
+
+2013-10-26 Vladimir Makarov <vmakarov@redhat.com>
+
+ Revert:
+ 2013-10-25 Vladimir Makarov <vmakarov@redhat.com>
+ * lra-spills.c (lra_final_code_change): Remove useless move insns.
+
+2013-10-26 Jeff Law <law@redhat.com>
+
+ * predict.c (PRED_MUDFLAP): Remove.
+ * targhooks.c (build_va_arg_indirect_ref): Remove mudflap support.
+
+ * Makefile.in (C_COMMON_OBJS): Remove tree-mudflap.
+ (OBJS): Remove tree-nomudflap.o
+ (GTFILES): Remove tree-mudflap.c
+ * builtins.c (expand_builtin_alloc): Remove mudflap support.
+ * gcc.c (MFWRAP_SPEC, MFLIB_SPEC): Likewise.
+ (mfwrap_spec, mflib_spec): Likewise.
+ (cpp_unique_options, cc1_options, static_specs): Likewise.
+ * gimplify (gimplify_vla_decl, build_va_arg_indirect_ref): Likewise.
+ * passes.def: Likewise.
+ * toplev.c (compile_file, process_options): Likewise.
+ * tree-inline.c (copy_tree_r): Likewise.
+ * tree-pass.,h (make_pass_mudflap_1, make_pass_mudflap_2): Likewise.
+ * varasm.c (make_decl_rtl, make_decl_rtl_for_debug): Likewise.
+ (build_constant_desc, output_constant_def_contents): Likewise.
+ (categorize_decl_for_section): Likewise.
+ * tree-mudflap.c: Removed.
+ * tree-mudflap.h: Removed.
+ * tree-nomudflap.c: Removed.
+ * bfin/uclinux.h (MFWRAP_SPEC): Remove.
+ * moxie/uclinux.h (MFWRAP_SPEC): Likewise.
+ * rs6000/aix.h (MFWRAP_SPEC, MFLIB_SPEC): Likewise.
+ * config/sol2.h (MFLIB_SPEC): Likewise.
+ * doc/install.texi: Remove mudflap references.
+ * doc/passes.texi: Similarly.
+ * doc/sourcebuild.texi: Similarly.
+ * doc/invoke.texi: Remove mudlfap related options.
+
+2013-10-25 Vladimir Makarov <vmakarov@redhat.com>
+
+ PR rtl-optimization/58759
+ * lra-constraints.c (lra_constraints): Remove wrong condition to
+ remove insn setting up an equivalent pseudo.
+
+2013-10-25 Vladimir Makarov <vmakarov@redhat.com>
+
+ * config/rs6000/rs6000-protos.h
+ (rs6000_secondary_memory_needed_mode): New prototype.
+ * config/rs6000/rs6000.c: Include ira.h.
+ (TARGET_LRA_P): Redefine.
+ (rs6000_legitimate_offset_address_p): Call
+ legitimate_constant_pool_address_p in strict mode for LRA.
+ (rs6000_legitimate_address_p): Ditto.
+ (legitimate_lo_sum_address_p): Add code for LRA. Use lra_in_progress.
+ (rs6000_emit_move): Add LRA version of code to generate load/store
+ of SDmode values.
+ (rs6000_secondary_memory_needed_mode): New.
+ (rs6000_alloc_sdmode_stack_slot): Do nothing for LRA.
+ (rs6000_secondary_reload_class): Return NO_REGS for LRA for
+ constants, memory, and FP registers.
+ (rs6000_lra_p): New.
+ * config/rs6000/rs6000.h (SECONDARY_MEMORY_NEEDED_MODE): New macro.
+ * config/rs6000/rs6000.opt (mlra): New option.
+ * lra-spills.c (lra_final_code_change): Remove useless move insns.
+
+2013-10-25 Yufeng Zhang <yufeng.zhang@arm.com>
+
+ * tree-ssa-math-opts.c (convert_plusminus_to_widen): Call
+ has_single_use () and not do the conversion if has_single_use ()
+ returns false for the multiplication result.
+
+2013-10-25 David Malcolm <dmalcolm@redhat.com>
+
+ * tree.h (EXCEPTIONAL_CLASS_P): Rename parameter from "CODE"
+ to "NODE", since this works on a "tree", not an
+ "enum tree_code".
+ (CONSTANT_CLASS_P): Likewise.
+ (TYPE_P): Likewise.
+ (DECL_P): Likewise.
+ (INDIRECT_REF_P): Likewise.
+ (REFERENCE_CLASS_P): Likewise.
+ (COMPARISON_CLASS_P): Likewise.
+ (UNARY_CLASS_P): Likewise.
+ (BINARY_CLASS_P): Likewise.
+ (STATEMENT_CLASS_P): Likewise.
+ (VL_EXP_CLASS_P): Likewise.
+ (EXPRESSION_CLASS_P): Likewise.
+ (IS_TYPE_OR_DECL_P): Likewise.
+
+2013-10-25 Marc Glisse <marc.glisse@inria.fr>
+
+ * tree-ssa-alias.c (ao_ref_init_from_ptr_and_size): Look for an
+ ADDR_EXPR in the defining statement.
+
+2013-10-25 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/58626
+ * tree-loop-distribution.c (enum rdg_dep_type): Remove
+ anti_dd, output_dd and input_dd.
+ (struct rdg_edge): Remove level and relation members.
+ (RDGE_LEVEL, RDGE_RELATION): Remove.
+ (dot_rdg_1): Adjust.
+ (create_rdg_edge_for_ddr): Remove.
+ (create_rdg_edges_for_scalar): Adjust.
+ (create_edge_for_control_dependence): Likewise.
+ (create_rdg_edges): Split into ...
+ (create_rdg_flow_edges): ... this
+ (create_rdg_cd_edges): ... and this.
+ (free_rdg): Adjust.
+ (build_rdg): Likewise, do not compute data dependences or
+ add edges for them.
+ (pg_add_dependence_edges): New function.
+ (pgcmp): Likewise.
+ (distribute_loop): First apply all non-dependence based
+ partition mergings. Then compute dependences between partitions
+ and merge and order partitions according to them.
+
+2013-10-25 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR rtl-optimization/58831
+ * alias.c (init_alias_analysis): At the beginning of each iteration,
+ set the reg_seen[N] bit if static_reg_base_value[N] is non-null.
+
+2013-10-25 Eric Botcazou <ebotcazou@adacore.com>
+
+ * recog.c (search_ofs): New static variable moved from...
+ (peep2_find_free_register): ...here.
+ (peephole2_optimize): Initialize it.
+
+2013-10-25 Tobias Burnus <burnus@net-b.de>
+
+ * doc/invoke.texi (fopenmp): Change supported OpenMP version to 4.0.
+
+2013-10-25 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.h (TARGET_MPX): New define.
+ (TARGET_MPX_P): Ditto.
+
+2013-10-24 Ilya Enkovich <ilya.enkovich@intel.com>
+
+ * config/i386/constraints.md (B): New.
+ (Ti): New.
+ (Tb): New.
+ * config/i386/i386-c.c (ix86_target_macros_internal): Add __MPX__.
+ * config/i386/i386-modes.def (BND32): New.
+ (BND64): New.
+ * config/i386/i386-protos.h (ix86_bnd_prefixed_insn_p): New.
+ * config/i386/i386.c (isa_opts): Add mmpx.
+ (regclass_map): Add bound registers.
+ (dbx_register_map): Likewise.
+ (dbx64_register_map): Likewise.
+ (svr4_dbx_register_map): Likewise.
+ (PTA_MPX): New.
+ (ix86_option_override_internal): Support MPX ISA.
+ (ix86_conditional_register_usage): Support bound registers.
+ (print_reg): Likewise.
+ (ix86_code_end): Add MPX bnd prefix.
+ (output_set_got): Likewise.
+ (ix86_output_call_insn): Likewise.
+ (ix86_print_operand): Add '!' (MPX bnd) print prefix support.
+ (ix86_print_operand_punct_valid_p): Likewise.
+ (ix86_print_operand_address): Support UNSPEC_BNDMK_ADDR and
+ UNSPEC_BNDMK_ADDR.
+ (ix86_class_likely_spilled_p): Add bound regs support.
+ (ix86_hard_regno_mode_ok): Likewise.
+ (x86_order_regs_for_local_alloc): Likewise.
+ (ix86_bnd_prefixed_insn_p): New.
+ * config/i386/i386.h (FIRST_PSEUDO_REGISTER): Fix to new value.
+ (FIXED_REGISTERS): Add bound registers.
+ (CALL_USED_REGISTERS): Likewise.
+ (REG_ALLOC_ORDER): Likewise.
+ (HARD_REGNO_NREGS): Likewise.
+ (TARGET_MPX): New.
+ (VALID_BND_REG_MODE): New.
+ (FIRST_BND_REG): New.
+ (LAST_BND_REG): New.
+ (reg_class): Add BND_REGS.
+ (REG_CLASS_NAMES): Likewise.
+ (REG_CLASS_CONTENTS): Likewise.
+ (BND_REGNO_P): New.
+ (ANY_BND_REG_P): New.
+ (BNDmode): New.
+ (HI_REGISTER_NAMES): Add bound registers.
+ * config/i386/i386.md (UNSPEC_BNDMK): New.
+ (UNSPEC_BNDMK_ADDR): New.
+ (UNSPEC_BNDSTX): New.
+ (UNSPEC_BNDLDX): New.
+ (UNSPEC_BNDLDX_ADDR): New.
+ (UNSPEC_BNDCL): New.
+ (UNSPEC_BNDCU): New.
+ (UNSPEC_BNDCN): New.
+ (UNSPEC_MPX_FENCE): New.
+ (BND0_REG): New.
+ (BND1_REG): New.
+ (type): Add mpxmov, mpxmk, mpxchk, mpxld, mpxst.
+ (length_immediate): Likewise.
+ (prefix_0f): Likewise.
+ (memory): Likewise.
+ (prefix_rep): Check for bnd prefix.
+ (length_nobnd): New.
+ (length): Use length_nobnd if specified.
+ (BND): New.
+ (bnd_ptr): New.
+ (BNDCHECK): New.
+ (bndcheck): New.
+ (*jcc_1): Add bnd prefix and rename length attr to length_nobnd.
+ (*jcc_2): Likewise.
+ (jump): Likewise.
+ (simple_return_internal): Likewise.
+ (simple_return_pop_internal): Likewise.
+ (*indirect_jump): Add MPX bnd prefix.
+ (*tablejump_1): Likewise.
+ (simple_return_internal_long): Likewise.
+ (simple_return_indirect_internal): Likewise.
+ (<mode>_mk): New.
+ (*<mode>_mk): New.
+ (mov<mode>): New.
+ (*mov<mode>_internal_mpx): New.
+ (<mode>_<bndcheck>): New.
+ (*<mode>_<bndcheck>): New.
+ (<mode>_ldx): New.
+ (*<mode>_ldx): New.
+ (<mode>_stx): New.
+ (*<mode>_stx): New.
+ * config/i386/predicates.md (lea_address_operand): Rename to...
+ (address_no_seg_operand): ... this.
+ (address_mpx_no_base_operand): New.
+ (address_mpx_no_index_operand): New.
+ (bnd_mem_operator): New.
+ * config/i386/i386.opt (mmpx): New.
+ * doc/invoke.texi: Add documentation for the flags -mmpx, -mno-mpx.
+ * doc/rtl.texi Add documentation for BND32mode and BND64mode.
+
+2013-10-24 Ilya Enkovich <ilya.enkovich@intel.com>
+
+ * mode-classes.def (MODE_POINTER_BOUNDS): New.
+ * tree.def (POINTER_BOUNDS_TYPE): New.
+ * genmodes.c (complete_mode): Support MODE_POINTER_BOUNDS.
+ (POINTER_BOUNDS_MODE): New.
+ (make_pointer_bounds_mode): New.
+ * machmode.h (POINTER_BOUNDS_MODE_P): New.
+ * stor-layout.c (int_mode_for_mode): Support MODE_POINTER_BOUNDS.
+ (layout_type): Support POINTER_BOUNDS_TYPE.
+ * tree-pretty-print.c (dump_generic_node): Support POINTER_BOUNDS_TYPE.
+ * tree.c (build_int_cst_wide): Support POINTER_BOUNDS_TYPE.
+ (type_contains_placeholder_1): Likewise.
+ * tree.h (POINTER_BOUNDS_TYPE_P): New.
+ * varasm.c (output_constant): Support POINTER_BOUNDS_TYPE.
+ * doc/rtl.texi (MODE_POINTER_BOUNDS): New.
+
+2013-10-24 Igor Shevlyakov <igor.shevlyakov@gmail.com>
+
+ * expr.c (expand_expr_real_1): Use mode of memory reference rather than
+ mode of address computation when calling memory_address_addr_space.
+
+2013-08-24 Richard Henderson <rth@twiddle.net>
+
+ PR rtl/58542
+ * optabs.c (maybe_emit_atomic_exchange): Use create_input_operand
+ instead of create_convert_operand_to.
+ (maybe_emit_sync_lock_test_and_set): Likewise.
+ (expand_atomic_compare_and_swap): Likewise.
+ (maybe_emit_compare_and_swap_exchange_loop): Don't convert_modes.
+
+2013-08-24 Sriraman Tallam <tmsriram@google.com>
+
+ * cgraph.c (cgraph_fnver_htab): Move GTY((...)) to be before htab_t.
+ Change param_is to use the struct and not the pointer to the struct.
+
+2013-10-24 Andrew MacLeod <amacleod@redhat.com>
+
+ * builtins.c (dummy_object, gimplify_va_arg_expr): Move to gimplify.c.
+ * gimplify.c (build_va_arg_indirect_ref, std_gimplify_va_arg_expr):
+ Move to targhooks.c.
+ (dummy_object, gimplify_va_arg_expr): Relocate from builtins.c.
+ * targhooks.c (build_va_arg_indirect_ref, std_gimplify_va_arg_expr):
+ Relocate from gimplify.c.
+ * targhooks.h: Add 2 prototypes.
+ * tree.h: Delete 2 prototypes.
+
+2013-10-24 Igor Shevlyakov <igor.shevlyakov@gmail.com>
+
+ * tree-ssa-loop-ivopts.c (multiplier_allowed_in_address_p ): Check both
+ [reg+mult*reg] and [mult*reg] to determine if multiplier is allowed.
+
+2013-10-24 Cong Hou <congh@google.com>
+
+ * convert.c (convert_to_real): Guard those unsafe math function
+ convertions with flag_unsafe_math_optimizations. Handle sqrt()
+ specially.
+
+2013-10-24 Markus Trippelsdorf <markus@trippelsdorf.de>
+
+ PR ipa/58712
+ * cgraph.c (cgraph_create_edge_1): Add indirect_unknown_callee
+ as argument.
+ (cgraph_create_edge): Use the new argument.
+ (cgraph_create_indirect_edge): Likewise.
+
+2013-10-24 Joern Rennecke <joern.rennecke@embecosm.com>
+
+ * config/arc/arc.c (arc_ccfsm_post_advance): Also handle
+ TYPE_UNCOND_BRANCH.
+ (arc_ifcvt) <case 1 and 2>: Check that arc_ccfsm_post_advance
+ changes statep->state.
+
+2013-10-24 Tobias Burnus <burnus@net-b.de>
+
+ PR other/33426
+ * tree-cfg.c (replace_loop_annotate): New function.
+ (execute_build_cfg): Call it.
+ * gimplify.c (gimple_boolify, gimplify_expr): Handle ANNOTATE_EXPR.
+ * internal-fn.c (expand_ANNOTATE): New function.
+ * internal-fn.def (ANNOTATE): Define as new internal function.
+ * tree-core.h (tree_node_kind): Add annot_expr_ivdep_kind.
+ * tree-pretty-print.c (dump_generic_node): Handle ANNOTATE_EXPR.
+ * tree.def (ANNOTATE_EXPR): New DEFTREECODE.
+ * doc/extend.texi (Pragmas): Document #pragma ivdep.
+ * doc/generic.texi (Expressions): Document ANNOTATE_EXPR.
+
+2013-10-17 Ian Bolton <ian.bolton@arm.com>
+ Marcus Shawcroft <marcus.shawcroft@arm.com>
+
+ * config/aarch64/aarch64.c (aarch64_preferred_reload_class):
+ Special case reload SP+C into none GENERAL_REGS.
+
+2013-10-24 Michael Matz <matz@suse.de>
+
+ * gengtype.c (is_file_equal): Check that files will be same length.
+
+2013-10-25 Christian Bruel <christian.bruel@st.com>
+
+ * config.gcc (sh-*): Add sh-mem.o to extra_obj.
+ * config/sh/t-sh (sh-mem.o): New rule.
+ * config/sh/sh-mem.cc (expand_block_move): Moved here.
+ (sh_expand_cmpstr): New function.
+ * config/sh/sh.c (force_into, expand_block_move): Move to sh-mem.c.
+ * config/sh/sh-protos.h (sh_expand_cmpstr): Declare.
+ * config/sh/sh.md (cmpstrsi, cmpstr_t): New patterns.
+ (rotlhi3_8): Rename.
+
+2013-10-24 Jan-Benedict Glaw <jbglaw@lug-owl.de>
+
+ * configure.ac (ZW_PROG_COMPILER_DEPENDENCIES): Use CXX instead of CC.
+ * Makefile.in (CXXDEPMODE): Assign and change users.
+ (CCDEPMODE): Delete.
+ * configure: Regenerate.
+
+2013-10-23 David Malcolm <dmalcolm@redhat.com>
+
+ * gengtype-parse.c (require_without_advance): New.
+ (type): For GTY-marked types that are not GTY((user)), parse any
+ base classes, requiring them to be single-inheritance, and not
+ be templates. For non-GTY-marked types and GTY((user)),
+ continue to skip over any C++ inheritance specification.
+ * gengtype-state.c (state_writer::write_state_struct_type):
+ Write base class of type (if any).
+ (read_state_struct_type): Read base class of type (if any).
+ * gengtype.c (new_structure): Add a "base_class" parameter.
+ (create_optional_field_): Update for new parameter to new_structure.
+ (adjust_field_rtx_def): Likewise.
+ (adjust_field_tree_exp): Likewise.
+ * gengtype.h (struct type): Add "base_class" field to the s
+ union field.
+ (new_structure): Add "base" parameter.
+
+2013-10-23 Sriraman Tallam <tmsriram@google.com>
+
+ PR target/57756
+ * config/i386/i386.c (ix86_option_override_internal):
+ Change TARGET_SSE2 to TARGET_SSE2_P (opts->...)
+ (ix86_valid_target_attribute_tree):
+ Change TARGET_64BIT to TARGET_64BIT_P (opts->...)
+ Change TARGET_SSE to TARGET_SSE_P (opts->...)
+
+2013-10-23 Andrew MacLeod <amacleod@redhat.com>
+
+ * tree-ssa-loop.h: Remove include files.
+ * gengtype.c (open_base_files): Adjust include list for gtype-desc.c.
+ * cfgloopmanip.c: Move required includes from tree-ssa-loop.h.
+ * graphite-clast-to-gimple.c: Likewise.
+ * graphite-scop-detection.c: Likewise.
+ * graphite-sese-to-poly.c: Likewise.
+ * ipa-inline-analysis.c: Likewise.
+ * ipa-pure-const.c: Likewise.
+ * loop-init.c: Likewise.
+ * passes.c: Likewise.
+ * predict.c: Likewise.
+ * tree-cfg.c: Likewise.
+ * tree-cfgcleanup.c: Likewise.
+ * tree-chrec.c: Likewise.
+ * tree-data-ref.c: Likewise.
+ * tree-loop-distribution.c: Likewise.
+ * tree-parloops.c: Likewise.
+ * tree-predcom.c: Likewise.
+ * tree-scalar-evolution.c: Likewise.
+ * tree-ssa-address.c: Likewise.
+ * tree-ssa.c: Likewise.
+ * tree-ssa-dce.c: Likewise.
+ * tree-ssa-loop.c: Likewise.
+ * tree-ssa-loop-im.c: Likewise.
+ * tree-ssa-loop-ivcanon.c: Likewise.
+ * tree-ssa-loop-ivopts.c: Likewise.
+ * tree-ssa-loop-manip.c: Likewise.
+ * tree-ssa-loop-niter.c: Likewise.
+ * tree-ssa-loop-prefetch.c: Likewise.
+ * tree-ssa-loop-unswitch.c: Likewise.
+ * tree-ssa-reassoc.c: Likewise.
+ * tree-vect-data-refs.c: Likewise.
+ * tree-vect-loop.c: Likewise.
+ * tree-vect-loop-manip.c: Likewise.
+ * tree-vectorizer.c: Likewise.
+ * tree-vect-stmts.c: Likewise.
+ * tree-vrp.c: Likewise.
+
+2013-10-23 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * config/rs6000/altivec.md (mulv8hi3): Adjust for little endian.
+
+2013-10-23 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/58775
+ PR tree-optimization/58791
+ * tree-ssa-reassoc.c (reassoc_stmt_dominates_stmt_p): New function.
+ (insert_stmt_after): Rewritten, don't move the stmt, but really
+ insert it.
+ (get_stmt_uid_with_default): Remove.
+ (build_and_add_sum): Use insert_stmt_after and
+ reassoc_stmt_dominates_stmt_p. Fix up uid if bb contains only labels.
+ (update_range_test): Set uid on stmts added by
+ force_gimple_operand_gsi. Don't immediately modify statements
+ in inter-bb optimization, just update oe->op values.
+ (optimize_range_tests): Return bool whether any changed have been made.
+ (update_ops): New function.
+ (struct inter_bb_range_test_entry): New type.
+ (maybe_optimize_range_tests): Perform statement changes here.
+ (not_dominated_by, appears_later_in_bb, get_def_stmt,
+ ensure_ops_are_available): Remove.
+ (find_insert_point): Rewritten.
+ (rewrite_expr_tree): Remove MOVED argument, add CHANGED argument,
+ return LHS of the (new resp. old) stmt. Don't call
+ ensure_ops_are_available, don't reuse SSA_NAMEs, recurse first
+ instead of last, move new stmt at the right place.
+ (linearize_expr, repropagate_negates): Don't reuse SSA_NAMEs.
+ (negate_value): Likewise. Set uids.
+ (break_up_subtract_bb): Initialize uids.
+ (reassociate_bb): Adjust rewrite_expr_tree caller.
+ (do_reassoc): Don't call renumber_gimple_stmt_uids.
+
+2013-10-23 David Edelsohn <dje.gcc@gmail.com>
+
+ PR target/58838
+ * config/rs6000/rs6000.md (mulsi3_internal1 and splitter): Add
+ TARGET_32BIT final condition.
+ (mulsi3_internal2 and splitter): Same.
+
+2013-10-23 Jeff Law <law@redhat.com>
+
+ * tree-ssa-threadedge.c (thread_across_edge): Do not allow threading
+ through joiner blocks with abnormal outgoing edges.
+
+ * tree-ssa-threadupdate.c (thread_block_1): Renamed from thread_block.
+ Add parameter JOINERS, to allow/disallow threading through joiner
+ blocks.
+ (thread_block): New. Call thread_block_1.
+ (mark_threaded_blocks): Remove code to filter out certain cases
+ of threading through joiner blocks.
+ (thread_through_all_blocks): Document how we can have a dangling
+ edge AUX field and clear it.
+
+2013-10-23 Ian Lance Taylor <iant@google.com>
+
+ * doc/invoke.texi (Option Summary): Remove -fno-default-inline.
+ (C++ Dialect Options): Likewise.
+ (Optimize Options): Likewise.
+
+2013-10-23 Tom de Vries <tom@codesourcery.com>
+
+ PR tree-optimization/58805
+ * tree-ssa-tail-merge.c (stmt_local_def): Add gimple_vdef check.
+
+2013-10-23 Jakub Jelinek <jakub@redhat.com>
+
+ * tree-vect-patterns.c (vect_recog_divmod_pattern): Optimize
+ sequence based on get_range_info returned range.
+
+2013-10-23 Andrew MacLeod <amacleod@redhat.com>
+
+ * tree-ssa.h: Remove all #include's
+ * gengtype.c (open_base_files): Adjust include list for gtype-desc.c.
+ * alias.c: Move required includes from tree-ssa.h.
+ * asan.c: Likewise.
+ * builtins.c: Likewise.
+ * calls.c: Likewise.
+ * cfgexpand.c: Likewise.
+ * cfghooks.c: Likewise.
+ * cfgloop.c: Likewise.
+ * cfgloopmanip.c: Likewise.
+ * cgraph.c: Likewise.
+ * cgraphbuild.c: Likewise.
+ * cgraphclones.c: Likewise.
+ * cgraphunit.c: Likewise.
+ * dse.c: Likewise.
+ * except.c: Likewise.
+ * expr.c: Likewise.
+ * final.c: Likewise.
+ * fold-const.c: Likewise.
+ * ggc-page.c: Likewise.
+ * gimple-builder.c: Likewise.
+ * gimple-fold.c: Likewise.
+ * gimple-iterator.c: Likewise.
+ * gimple-low.c: Likewise.
+ * gimple-pretty-print.c: Likewise.
+ * gimple-ssa-strength-reduction.c: Likewise.
+ * gimple-streamer-in.c: Likewise.
+ * gimple-streamer-out.c: Likewise.
+ * gimplify.c: Likewise.
+ * graphite-blocking.c: Likewise.
+ * graphite-clast-to-gimple.c: Likewise.
+ * graphite-dependences.c: Likewise.
+ * graphite-interchange.c: Likewise.
+ * graphite-optimize-isl.c: Likewise.
+ * graphite-poly.c: Likewise.
+ * graphite-scop-detection.c: Likewise.
+ * graphite-sese-to-poly.c: Likewise.
+ * graphite.c: Likewise.
+ * ipa-cp.c: Likewise.
+ * ipa-inline-analysis.c: Likewise.
+ * ipa-inline-transform.c: Likewise.
+ * ipa-inline.c: Likewise.
+ * ipa-prop.c: Likewise.
+ * ipa-pure-const.c: Likewise.
+ * ipa-reference.c: Likewise.
+ * ipa-split.c: Likewise.
+ * ipa-utils.c: Likewise.
+ * loop-init.c: Likewise.
+ * lto-cgraph.c: Likewise.
+ * lto-section-in.c: Likewise.
+ * lto-section-out.c: Likewise.
+ * lto-streamer-in.c: Likewise.
+ * lto-streamer-out.c: Likewise.
+ * lto-streamer.c: Likewise.
+ * omp-low.c: Likewise.
+ * passes.c: Likewise.
+ * predict.c: Likewise.
+ * print-tree.c: Likewise.
+ * profile.c: Likewise.
+ * sese.c: Likewise.
+ * targhooks.c: Likewise.
+ * tracer.c: Likewise.
+ * trans-mem.c: Likewise.
+ * tree-call-cdce.c: Likewise.
+ * tree-cfg.c: Likewise.
+ * tree-cfgcleanup.c: Likewise.
+ * tree-chrec.c: Likewise.
+ * tree-complex.c: Likewise.
+ * tree-data-ref.c: Likewise.
+ * tree-dfa.c: Likewise.
+ * tree-eh.c: Likewise.
+ * tree-emutls.c: Likewise.
+ * tree-if-conv.c: Likewise.
+ * tree-inline.c: Likewise.
+ * tree-into-ssa.c: Likewise.
+ * tree-loop-distribution.c: Likewise.
+ * tree-mudflap.c: Likewise.
+ * tree-nested.c: Likewise.
+ * tree-nrv.c: Likewise.
+ * tree-object-size.c: Likewise.
+ * tree-outof-ssa.c: Likewise.
+ * tree-parloops.c: Likewise.
+ * tree-phinodes.c: Likewise.
+ * tree-predcom.c: Likewise.
+ * tree-pretty-print.c: Likewise.
+ * tree-profile.c: Likewise.
+ * tree-scalar-evolution.c: Likewise.
+ * tree-sra.c: Likewise.
+ * tree-ssa-address.c: Likewise.
+ * tree-ssa-alias.c: Likewise.
+ * tree-ssa-ccp.c: Likewise.
+ * tree-ssa-coalesce.c: Likewise.
+ * tree-ssa-copy.c: Likewise.
+ * tree-ssa-copyrename.c: Likewise.
+ * tree-ssa-dce.c: Likewise.
+ * tree-ssa-dom.c: Likewise.
+ * tree-ssa-dse.c: Likewise.
+ * tree-ssa-forwprop.c: Likewise.
+ * tree-ssa-ifcombine.c: Likewise.
+ * tree-ssa-live.c: Likewise.
+ * tree-ssa-loop-ch.c: Likewise.
+ * tree-ssa-loop-im.c: Likewise.
+ * tree-ssa-loop-ivcanon.c: Likewise.
+ * tree-ssa-loop-ivopts.c: Likewise.
+ * tree-ssa-loop-manip.c: Likewise.
+ * tree-ssa-loop-niter.c: Likewise.
+ * tree-ssa-loop-prefetch.c: Likewise.
+ * tree-ssa-loop-unswitch.c: Likewise.
+ * tree-ssa-loop.c: Likewise.
+ * tree-ssa-math-opts.c: Likewise.
+ * tree-ssa-operands.c: Likewise.
+ * tree-ssa-phiopt.c: Likewise.
+ * tree-ssa-phiprop.c: Likewise.
+ * tree-ssa-pre.c: Likewise.
+ * tree-ssa-propagate.c: Likewise.
+ * tree-ssa-reassoc.c: Likewise.
+ * tree-ssa-sccvn.c: Likewise.
+ * tree-ssa-sink.c: Likewise.
+ * tree-ssa-strlen.c: Likewise.
+ * tree-ssa-structalias.c: Likewise.
+ * tree-ssa-tail-merge.c: Likewise.
+ * tree-ssa-ter.c: Likewise.
+ * tree-ssa-threadedge.c: Likewise.
+ * tree-ssa-threadupdate.c: Likewise.
+ * tree-ssa-uncprop.c: Likewise.
+ * tree-ssa-uninit.c: Likewise.
+ * tree-ssa.c: Likewise.
+ * tree-ssanames.c: Likewise.
+ * tree-stdarg.c: Likewise.
+ * tree-streamer-in.c: Likewise.
+ * tree-switch-conversion.c: Likewise.
+ * tree-tailcall.c: Likewise.
+ * tree-vect-data-refs.c: Likewise.
+ * tree-vect-generic.c: Likewise.
+ * tree-vect-loop-manip.c: Likewise.
+ * tree-vect-loop.c: Likewise.
+ * tree-vect-patterns.c: Likewise.
+ * tree-vect-slp.c: Likewise.
+ * tree-vect-stmts.c: Likewise.
+ * tree-vectorizer.c: Likewise.
+ * tree-vrp.c: Likewise.
+ * tree.c: Likewise.
+ * tsan.c: Likewise.
+ * value-prof.c: Likewise.
+ * var-tracking.c: Likewise.
+ * varpool.c: Likewise.
+ * vtable-verify.c: Likewise.
+
+2013-10-23 Jan-Benedict Glaw <jbglaw@lug-owl.de>
+
+ * config/tilegx/tilegx.c: Include "tree.h".
+
+2013-10-23 Jakub Jelinek <jakub@redhat.com>
+
+ * gimple-pretty-print.c (dump_ssaname_info): Always print "# " before
+ the info, not after it.
+ (gump_gimple_phi): Add COMMENT argument, if true, print "# " after
+ dump_ssaname_info call.
+ (pp_gimple_stmt_1): Adjust caller.
+ (dump_phi_nodes): Likewise. Don't print "# " here.
+
+2013-10-22 Jan Hubicka <jh@suse.cz>
+
+ * i386.h (TARGET_MISALIGNED_MOVE_STRING_PROLOGUES_EPILOGUES): New
+ tuning flag.
+ * x86-tune.def (TARGET_MISALIGNED_MOVE_STRING_PROLOGUES): Define it.
+ * i386.c (expand_small_movmem_or_setmem): New function.
+ (expand_set_or_movmem_prologue_epilogue_by_misaligned_moves): New
+ function.
+ (alg_usable_p): Add support for value ranges; cleanup.
+ (ix86_expand_set_or_movmem): Add support for misaligned moves.
+
+2013-10-22 Sterling Augustine <saugustine@google.com>
+
+ * doc/invoke.texi: Document -ggnu-pubnames.
+ * common.opt: Add new option -ggnu-pubnames and modify -gpubnames
+ logic.
+ * dwarf2out.c: Include gdb/gdb-index.h.
+ (DEBUG_PUBNAMES_SECTION, DEBUG_PUBTYPES_SECTION): Handle
+ debug_generate_pub_sections.
+ (is_java, output_pubtables, output_pubname): New functions.
+ (include_pubname_in_output): Handle debug_generate_pub_sections at
+ level 2.
+ (size_of_pubnames): Use new local space_for_flags based on
+ debug_generate_pub_sections.
+ (output_pubnames): Unify pubnames and pubtypes output logic.
+ Genericize comments. Call output_pubname.
+ (dwarf2out_finish): Move logic to output_pubnames and call it.
+
+2013-10-22 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/58779
+ * config/i386/i386.c (put_condition_code) <case GTU, case LEU>:
+ Remove CCCmode handling.
+ <case LTU>: Return 'c' suffix for CCCmode.
+ <case GEU>: Return 'nc' suffix for CCCmode.
+ (ix86_cc_mode) <case GTU, case LEU>: Do not generate overflow checks.
+ * config/i386/i386.md (*sub<mode>3_cconly_overflow): Remove.
+ (*sub<mode>3_cc_overflow): Ditto.
+ (*subsi3_zext_cc_overflow): Ditto.
+
+2013-10-22 Steve Ellcey <sellcey@mips.com>
+
+ * config/mips/mips.c (mips_rtx_costs): Fix cost estimate for nor
+ (AND (NOT OP1) (NOT OP2)).
+
+2013-10-22 Bill Schmidt <wschmidt@vnet.ibm.com>
+
+ * config/rs6000/rs6000.c (altivec_expand_vec_perm_const): Reverse
+ meaning of merge-high and merge-low masks for little endian; avoid
+ use of vector-pack masks for little endian for mismatched modes.
+
+2013-10-22 Jan-Benedict Glaw <jbglaw@lug-owl.de>
+
+ * config/tilepro/tilepro.c: Include "tree.h".
+
+2013-10-22 Andreas Schwab <schwab@suse.de>
+
+ * config/m68k/m68k.c (notice_update_cc): Handle register conflict
+ with PRE_DEC.
+
+2013-10-22 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * doc/contrib.texi ([Fran@,{c}ois Dumont], [Tim Shen],
+ [Ed Smith-Rowland]): New entries.
+ ([Stephen M. Webb]): Update.
+
+2013-10-22 Andrew MacLeod <amacleod@redhat.com>
+
+ * tree-ssa-ter.h: Remove duplicate copy of file contents.
+
+2013-10-21 Marek Polacek <polacek@redhat.com>
+
+ PR middle-end/58809
+ * fold-const.c (fold_range_test): Return 0 if the type is not
+ an integral type.
+
+2013-10-21 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * system.h: Move hwint.h include further down.
+ * hwint.h (sext_hwi, zext_hwi): Define unconditionally. Add
+ gcc_checking_asserts.
+ * hwint.c (sext_hwi, zext_hwi): Delete ENABLE_CHECKING versions.
+
+2013-10-21 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ Fix volatile issues in optimize_bit_field_compare.
+ * fold-const.c (optimize_bit_field_compare): Bail out if
+ lvolatilep or rvolatilep.
+
+2013-10-21 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ Fix DECL_BIT_FIELD depencency on flag_strict_volatile_bitfields
+ and get_inner_reference returning different pmode for non-volatile
+ bit-field members dependent on flag_strict_volatile_bitfields.
+ * stor-layout.c (layout_decl): Remove special handling of
+ flag_strict_volatile_bitfields.
+ * expr.c (get_inner_reference): Don't use DECL_BIT_FIELD
+ if flag_strict_volatile_bitfields > 0 and TREE_THIS_VOLATILE.
+
+2013-10-21 Paulo Matos <pmatos@broadcom.com>
+
+ * ipa-inline.c (edge_badness): Cap edge->count at max_count for badness
+ calculations.
+
+2013-10-21 Jeff Law <law@redhat.com>
+
+ * tree-ssa-threadedge.c (thread_through_normal_block): New
+ argument VISITED. Remove VISISTED as a local variable. When we
+ have a threadable jump, verify the destination of the jump has not
+ been visised.
+ (thread_across_edge): Allocate VISITED bitmap once at function
+ scope and use it throughout. Make sure to set appropriate bits in
+ VISITED for E (start of jump thread path).
+ * tree-ssa-threadupdate.c (mark_threaded_blocks): Reject threading
+ through a joiner if any edge on the path has a recorded jump thread.
+
+2013-10-21 Ian Lance Taylor <iant@google.com>
+
+ * doc/invoke.texi (Optimize Options): For -fno-toplevel-reorder,
+ don't imply that attributes can solve all problems.
+ (Directory Options): Fix typo.
+
+2013-10-21 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * config/arm/arm.c (cortexa9_extra_costs): Update mult costs for
+ extend and extend_add.
+
+2013-10-21 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/58794
+ * fold-const.c (operand_equal_p): Compare FIELD_DECL operand
+ of COMPONENT_REFs with OEP_CONSTANT_ADDRESS_OF left in place.
+
+2013-10-21 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/58742
+ * fold-const.c (fold_binary_loc): Fold ((T) (X /[ex] C)) * C
+ to (T) X for sign-changing conversions (or no conversion).
+
+2013-10-20 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.md (kxnor<mode>): Add FLAGS_REG clobber.
+
+2013-10-20 Jan Hubicka <jh@suse.cz>
+
+ * config/i386/i386-tune.def: Add comment; organize into categories
+
+2013-10-21 Michael Zolotukhin <michael.v.zolotukhin@gmail.com>
+
+ * config/i386/i386.c (expand_set_or_movmem_via_loop): Add issetmem
+ argument. Update function comment.
+ (expand_set_or_movmem_via_rep): New function combining
+ expand_movmem_via_rep_mov and expand_setmem_via_rep_stos.
+ (expand_movmem_via_rep_mov): Remove.
+ expand_setmem_via_rep_stos): Remove.
+ (expand_movmem_epilogue): Update calls correspondingly.
+ (expand_setmem_epilogue_via_loop): Likewise.
+ (emit_memset): New.
+ (expand_setmem_epilogue): Add VEC_VALUE argument, refactor.
+ (expand_set_or_movmem_prologue): New function combining
+ expand_movmem_prologue and expand_setmem_prologue.
+ (expand_movmem_prologue): Remove.
+ (expand_setmem_prologue): Remove.
+ (expand_set_or_movmem_constant_prologue): New function combining
+ expand_constant_movmem_prologue and expand_constant_setmem_prologue.
+ (expand_constant_movmem_prologue): Remove.
+ (expand_constant_setmem_prologue): Remove.
+ (promote_duplicated_reg): Allow vector-const0 value.
+ (ix86_expand_set_or_movmem): New function combining ix86_expand_movmem
+ and ix86_expand_setmem.
+ (ix86_expand_movmem): Call ix86_expand_set_or_movmem.
+ (ix86_expand_setmem): Call ix86_expand_set_or_movmem.
+
+2013-10-21 Diego Novillo <dnovillo@google.com>
+
+ * asan.c: Include tree.h
+ * bb-reorder.c: Likewise.
+ * cfgcleanup.c: Likewise.
+ * cfgloopmanip.c: Likewise.
+ * data-streamer-in.c: Likewise.
+ * data-streamer-out.c: Likewise.
+ * data-streamer.c: Likewise.
+ * dwarf2cfi.c: Likewise.
+ * graphite-blocking.c: Likewise.
+ * graphite-clast-to-gimple.c: Likewise.
+ * graphite-dependences.c: Likewise.
+ * graphite-interchange.c: Likewise.
+ * graphite-optimize-isl.c: Likewise.
+ * graphite-poly.c: Likewise.
+ * graphite-scop-detection.c: Likewise.
+ * graphite-sese-to-poly.c: Likewise.
+ * graphite.c: Likewise.
+ * ipa-devirt.c: Likewise.
+ * ipa-profile.c: Likewise.
+ * ipa.c: Likewise.
+ * ira.c: Likewise.
+ * loop-init.c: Likewise.
+ * loop-unroll.c: Likewise.
+ * lower-subreg.c: Likewise.
+ * lto/lto-object.c: Likewise.
+ * recog.c: Likewise.
+ * reginfo.c: Likewise.
+ * tree-loop-distribution.c: Likewise.
+ * tree-parloops.c: Likewise.
+ * tree-ssa-strlen.c: Likewise.
+ * tree-streamer.c: Likewise.
+ * value-prof.c: Likewise.
+ * target-globals.c: Likewise.
+ * expr.h: Include tree-core.h instead of tree.h.
+ * gimple.h: Likewise.
+ * ipa-prop.h: Likewise.
+ * ipa-utils.h: Likewise.
+ * lto-streamer.h: Likewise.
+ * streamer-hooks.h: Likewise.
+ * ipa-reference.h: Include cgraph.h instead of tree.h.
+ * cgraph.h: Include basic-block.h instead of tree.h.
+ * tree-streamer.h: Do not include tree.h.
+ * genattrtab.c (write_header): Generate inclusion of
+ tree.h.
+ * genautomata.c (main): Likewise.
+ * genemit.c: Likewise.
+ * genopinit.c: Likewise.
+ * genoutput.c (output_prologue): Likewise.
+ * genpeep.c: Likewise.
+
+2013-10-20 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * config/rs6000/altivec.md (vec_unpacku_hi_v16qi): Adjust for
+ little endian.
+ (vec_unpacku_hi_v8hi): Likewise.
+ (vec_unpacku_lo_v16qi): Likewise.
+ (vec_unpacku_lo_v8hi): Likewise.
+
+2013-10-20 Jan Hubicka <jh@suse.cz>
+
+ * config/i386/x86-tune.def (X86_TUNE_SLOW_IMUL_IMM32_MEM,
+ X86_TUNE_SLOW_IMUL_IMM8): Keep enabled only for K8 and AMDFAM10.
+ (X86_TUNE_USE_VECTOR_FP_CONVERTS): Disable for generic.
+
+2013-10-20 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * config/mips/mips.h (ISA_HAS_WSBH): Define.
+ * config/mips/mips.md (UNSPEC_WSBH, UNSPEC_DSBH, UNSPEC_DSHD): New
+ constants.
+ (bswaphi2, bswapsi2, bswapdi2, wsbh, dsbh, dshd): New patterns.
+
+2013-10-19 John David Anglin <danglin@gcc.gnu.org>
+
+ PR target/58603
+ * system.h: Undef m_slot.
+
+2013-10-19 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * config/rs6000/rs6000.c (vspltis_constant): Make sure we check
+ all elements for both endian flavors.
+
+2013-10-19 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/58792
+ * config/i386/i386.c (ix86_function_value_regno): Add DX_REG,
+ ST1_REG and XMM1_REG for 32bit and 64bit targets. Also add DI_REG
+ and SI_REG for 64bit SYSV ABI targets.
+
+2013-10-19 Uros Bizjak <ubizjak@gmail.com>
+
+ * mode-switching.c (create_pre_exit): Rename maybe_builtin_apply
+ to multi_reg_return. Clarify that we are skipping USEs of multiple
+ return registers. Use bool type where appropriate.
+
+2013-10-18 Jan Hubicka <jh@suse.cz>
+
+ * config/i386/i386.h (ACCUMULATE_OUTGOING_ARGS): Disable accumulation
+ for cold functions.
+ * x86-tune.def (X86_TUNE_USE_LEAVE): Update comment.
+ (X86_TUNE_PUSH_MEMORY): Likewise.
+ (X86_TUNE_AVX256_UNALIGNED_LOAD_OPTIMAL,
+ X86_TUNE_AVX256_UNALIGNED_STORE_OPTIMAL): New.
+ (X86_TUNE_ACCUMULATE_OUTGOING_ARGS, X86_TUNE_ALWAYS_FANCY_MATH_387):
+ New.
+ * i386.c (x86_accumulate_outgoing_args, x86_arch_always_fancy_math_387,
+ x86_avx256_split_unaligned_load, x86_avx256_split_unaligned_store):
+ Remove.
+ (ix86_option_override_internal): Update to use tune features instead
+ of variables.
+
+2013-10-18 Cong Hou <congh@google.com>
+
+ PR tree-optimization/58508
+ * tree-vect-loop-manip.c (vect_loop_versioning): Hoist loop invariant
+ statement that contains data refs with zero-step.
+
+2013-10-18 Andrew MacLeod <amacleod@redhat.com>
+
+ * tree-ssa.h: Don't include gimple-low.h, tree-ssa-address.h,
+ sbitmap.h, tree-ssa-threadedge.h, tree-ssa-dom.h and tree-cfgcleanup.h.
+ * gimple-low.c (gimple_check_call_arg,
+ gimple_check_call_matching_types): Move to cgraph.c.
+ * gimple-low.h: Remove prototype.
+ * cgraph.c: (gimple_check_call_arg, gimple_check_call_matching_types):
+ Relocate from gimple-low.c.
+ * cgraph.h: Add prototype. Don't include basic-block.h.
+ * gimplify.c: Add gimple-low to include list.
+ * omp-low.c: Add gimple-low and tree-cfgcleanup.h to include list.
+ * tree-eh.c: Add gimple-low to include list.
+ * tree-nested.c: Likewise.
+ * cfgexpand.c: Add tree-ssa-address.h to include list.
+ * expr.c: Likewise.
+ * gimple-fold.c: Likewise.
+ * gimple-ssa-strength-reduction.c: Likewise.
+ * trans-mem.c: Likewise.
+ * tree-mudflap.c: Likewise.
+ * tree-ssa-loop-ivopts.c: Likewise.
+ * tree-ssa-dom.c: Include tree-ssa-threadedge.h and tree-ssa-dom.h.
+ (degenerate_phi_result): Move to tree-phinodes.c.
+ * tree-ssa-loop-ch.c: Include tree-ssa-threadedge.h.
+ * tree-ssa-threadedge.c: Likewise.
+ * tree-vrp.c: Likewise.
+ * tree-phinodes.c (degenerate_phi_result): Relocate here.
+ * tree-ssa-dom.h (degenerate_phi_result): Remove Prototype.
+ * tree-phinodes.h (degenerate_phi_result): Add prototype.
+ * tree-ssa-copy.c: Include tree-ssa-dom.h.
+ * tree-ssa-forwprop.c: Likewise.
+ * tree-cfgcleanup.c (execute_cleanup_cfg_post_optimizing,
+ pass_data_cleanup_cfg_post_optimizing,
+ make_pass_cleanup_cfg_post_optimizing): Relocate from tree-optimize.c.
+ * tree-optimize.c: Delete File.
+ * graphite.c: Include tree-cfgcleanup.h.
+ * passes.c: Likewise.
+ * tree-cfg.c: Likewise.
+ * tree-profile.c: Likewise.
+ * tree-ssa-dse.c: Likewise.
+ * tree-ssa-loop-ivcanon.c: Likewise.
+ * tree-switch-conversion.c: Don't include tree-ssa-operands.h.
+ * tree-outof-ssa.c: Include sbitmap.h.
+ * tree-ssa-live.c: Likewise.
+ * tree-ssa-propagate.c: Likewise.
+ * tree-ssa-structalias.c: Likewise.
+ * tree-stdarg.c: Likewise.
+ * Makefile.in (OBJS): Delete tree-optimize.o.
+ * basic-block.h (gcov_type, gcov_type_unsigned): Move to coretypes.h.
+ * coretypes.h (gcov_type, gcov_type_unsigned): Relocate here.
+ * varasm.c: Include basic-block.h.
+ * cfgloop.h: Include function.h instead of basic-block.h
+ (bb_loop_depth): Move to cfgloop.c.
+ * cfgloop.c (bb_loop_depth): Relocate from cfgloop.h.
+
+2013-10-18 Teresa Johnson <tejohnson@google.com>
+
+ * predict.c (probably_never_executed): Compare frequency-based
+ count to number of training runs.
+ * params.def (UNLIKELY_BB_COUNT_FRACTION): New parameter.
+
+2013-10-18 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * config/arm/arm.c (cortexa9_extra_costs): New table.
+ (arm_cortex_a9_tune): Use cortexa9_extra_costs.
+
+2013-10-18 Jeff Law <law@redhat.com>
+
+ * tree-ssa-threadupdate.c: Do not include "tm.h" or "tm_p.h".
+
+ * tree-ssa-threadupdate.c: Include "dbgcnt.h".
+ (register_jump_thread): Add "registered_jump_thread" debug
+ counter support.
+ * dbgcnt.def (registered_jump_thread): New debug counter.
+
+2013-10-18 Andrew MacLeod <amacleod@redhat.com>
+
+ * config/rs6000/rs6000.c: Include cgraph.h.
+
+2013-10-18 Teresa Johnson <tejohnson@google.com>
+
+ * tree-ssa-tail-merge.c (replace_block_by): Update edge
+ weights during merging.
+
+2013-10-18 Andrew MacLeod <amacleod@redhat.com>
+
+ * tree-cfg.h: Rename from tree-flow.h. Remove #includes.
+ * tree-ssa.h: Relocate required #includes from tree-cfg.h.
+ * tree-ssa-operands.h: Remove prototype.
+ * tree-ssa-operands.c (virtual_operand_p): Move to gimple.c.
+ * gimple.c (virtual_operand_p): Relocate from gimple.c.
+ * gimple.h: Add prototype.
+ * gimple-ssa.h: Include tree-ssa-operands.h.
+ * tree-dump.c: Add tree-cfg.h to include list.
+ * tree-ssa-alias.c: Add ipa-reference.h to include list.
+ * config/alpha/alpha.c: Include gimple-ssa.h instead of tree-flow.h.
+ * config/i386/i386.c: Don't include tree-flow.h.
+ * config/rs6000/rs6000.c: Likewise.
+
+2013-10-18 Jan-Benedict Glaw <jbglaw@lug-owl.de>
+
+ * config/frv/frv.c (frv_init_cumulative_args): Fix wrong cast.
+
+2013-10-18 Richard Biener <rguenther@suse.de>
+
+ * stor-layout.c (layout_type): Do not change TYPE_PRECISION
+ or TYPE_UNSIGNED of integral types.
+ (set_min_and_max_values_for_integral_type): Leave TYPE_MIN/MAX_VALUE
+ NULL_TREE for zero-precision integral types.
+
+2013-10-18 James Greenhalgh <james.greenhalgh@arm.com>
+
+ * config/aarch64/arm_neon.h
+ (vcvt<ds>_n_<fsu><32,64>_<fsu><32,64>): Correct argument types.
+
+2013-10-17 Sriraman Tallam <tmsriram@google.com>
+
+ PR target/57756
+ * opth-gen.awk: Define target_flags_explicit.
+
+2013-10-17 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * config/rs6000/rs6000.c (enum rs6000_reload_reg_type): Add new
+ fields to the reg_addr array that describes the valid addressing
+ mode for any register, general purpose registers, floating point
+ registers, and Altivec registers.
+ (FIRST_RELOAD_REG_CLASS): Likewise.
+ (LAST_RELOAD_REG_CLASS): Likewise.
+ (struct reload_reg_map_type): Likewise.
+ (reload_reg_map_type): Likewise.
+ (RELOAD_REG_VALID): Likewise.
+ (RELOAD_REG_MULTIPLE): Likewise.
+ (RELOAD_REG_INDEXED): Likewise.
+ (RELOAD_REG_OFFSET): Likewise.
+ (RELOAD_REG_PRE_INCDEC): Likewise.
+ (RELOAD_REG_PRE_MODIFY): Likewise.
+ (reg_addr): Likewise.
+ (mode_supports_pre_incdec_p): New helper functions to say whether
+ a given mode supports PRE_INC, PRE_DEC, and PRE_MODIFY.
+ (mode_supports_pre_modify_p): Likewise.
+ (rs6000_debug_vector_unit): Rearrange the -mdebug=reg output to
+ print the valid address mode bits for each mode.
+ (rs6000_debug_print_mode): Likewise.
+ (rs6000_debug_reg_global): Likewise.
+ (rs6000_setup_reg_addr_masks): New function to set up the address
+ mask bits for each type.
+ (rs6000_init_hard_regno_mode_ok): Use memset to clear arrays.
+ Call rs6000_setup_reg_addr_masks to set up the address mask bits.
+ (rs6000_legitimate_address_p): Use mode_supports_pre_incdec_p and
+ mode_supports_pre_modify_p to determine if PRE_INC, PRE_DEC, and
+ PRE_MODIFY are supported.
+ (rs6000_output_move_128bit): Change to use {src,dest}_vmx_p for altivec
+ registers, instead of {src,dest}_av_p.
+ (rs6000_print_options_internal): Tweak the debug output slightly.
+
+2013-10-17 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/sse.md (*vec_widen_smult_even_v8si): Remove
+ isa attribute.
+
+2013-10-17 Andrew MacLeod <amacleod@redhat.com>
+
+ * tree-flow.h (struct omp_region): Move to omp-low.c.
+ Remove omp_ prototypes and variables.
+ * gimple.h (omp_reduction_init): Move prototype to omp-low.h.
+ (copy_var_decl): Relocate prototype from tree-flow.h.
+ * gimple.c (copy_var_decl): Relocate from omp-low.c.
+ * tree.h: Move prototype to omp-low.h.
+ * omp-low.h: New File. Relocate prototypes here.
+ * omp-low.c (struct omp_region): Make local here.
+ (root_omp_region): Make static.
+ (copy_var_decl) Move to gimple.c.
+ (new_omp_region): Make static.
+ (make_gimple_omp_edges): New. Refactored from tree-cfg.c make_edges.
+ * tree-cfg.c: Include omp-low.h.
+ (make_edges): Factor out OMP specific bits to make_gimple_omp_edges.
+ * gimplify.c: Include omp-low.h.
+ * tree-parloops.c: Likewise.
+
+2013-10-17 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.c (ix86_fixup_binary_operands): When both source
+ operands are in memory, prefer to force non-matched operand 1 to
+ the register.
+
+2013-10-17 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ PR target/58673
+ * config/rs6000/rs6000.c (rs6000_legitimate_address_p): Only
+ restrict TImode addresses to single indirect registers if both
+ -mquad-memory and -mvsx-timode are used.
+ (rs6000_output_move_128bit): Use quad_load_store_p to determine if
+ we should emit load/store quad. Remove using %y for quad memory
+ addresses.
+
+ * config/rs6000/rs6000.md (mov<mode>_ppc64, TI/PTImode): Add
+ constraints to allow load/store quad on machines where TImode is
+ not allowed in VSX registers. Use 'n' instead of 'F' constraint
+ for TImode to load integer constants.
+
+2013-10-17 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * config/aarch64/aarch64.c (aarch64_print_operand): Handle 'c'.
+
+2013-10-17 Marcus Shawcroft <marcus.shawcroft@arm.com>
+
+ * config/aarch64/aarch64.c (aarch64_preferred_reload_class): Adjust
+ handling of STACK_REG.
+
+2013-10-17 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/58143
+ * tree-ssa-loop-im.c (arith_code_with_undefined_signed_overflow):
+ New function.
+ (rewrite_to_defined_overflow): Likewise.
+ (move_computations_dom_walker::before_dom): Rewrite stmts
+ with undefined signed overflow that are not always executed
+ into unsigned arithmetic.
+
+2013-10-16 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ PR target/57756
+ * config/rs6000/rs6000.opt (rs6000_isa_flags_explicit): Move the
+ explicit isa flag to be an options variable, instead of using
+ global_options_set. Remove define from rs6000.h.
+ * config/rs6000/rs6000.h (rs6000_isa_flags_explicit): Likewise.
+
+ * config/rs6000/rs6000.c (rs6000_option_override_internal):
+ Initialize rs6000_isa_flags_explicit.
+ (rs6000_function_specific_save): Add gcc_options* parameter, so
+ that the powerpc builds after the 2013-10-15 changes.
+ (rs6000_function_specific_restore): Likewise.
+
+2013-10-16 DJ Delorie <dj@redhat.com>
+
+ * config/rl78/rl78.c (rl78_alloc_address_registers_macax): Verify
+ op is a REG before checking REGNO.
+ (rl78_alloc_physical_registers): Verify pattern is a SET before
+ checking SET_SRC.
+
+2013-10-16 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * config/rs6000/vector.md (vec_unpacks_hi_v4sf): Correct for
+ endianness.
+ (vec_unpacks_lo_v4sf): Likewise.
+ (vec_unpacks_float_hi_v4si): Likewise.
+ (vec_unpacks_float_lo_v4si): Likewise.
+ (vec_unpacku_float_hi_v4si): Likewise.
+ (vec_unpacku_float_lo_v4si): Likewise.
+
+2013-10-16 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * config/rs6000/vsx.md (vsx_concat_<mode>): Adjust output for LE.
+ (vsx_concat_v2sf): Likewise.
+
+2013-10-16 James Greenhalgh <james.greenhalgh@arm.com>
+
+ * config/aarch64/aarch64.md
+ (*mov<mode>_aarch64): Fix output template for DUP (element) Scalar.
+
+2013-10-16 Andrew MacLeod <amacleod@redhat.com>
+
+ PR tree-optimization/58697
+ * cfgloop.c (get_estimated_loop_iterations_int): Rename from
+ estimated_loop_iterations_int.
+ (max_stmt_executions_int): Call get_max_loop_iterations_int.
+ (get_max_loop_iterations_int): New. HWINT version of
+ get_max_loop_iterations.
+ * cfgloop.h: Add prototypes.
+ * loop-iv.c (find_simple_exit): call get_estimated_loop_iterations_int.
+ * loop-unroll.c (decide_peel_once_rolling): Call
+ get_estimated_loop_iterations_int.
+ * tree-ssa-loop-niter.c (estimated_loop_iterations_int): Add back.
+ * tree-ssa-loop-niter.h: Tweak prototypes.
+
+2013-10-16 David Malcolm <dmalcolm@redhat.com>
+
+ * gengtype-parse.c (struct_field_seq): Ignore access-control
+ keywords ("public:" etc).
+
+2013-10-16 Marcus Shawcroft <marcus.shawcroft@arm.com>
+
+ * config/aarch64/aarch64.c (aarch64_regno_regclass): Classify
+ FRAME_POINTER_REGNUM and ARG_POINTER_REGNUM as POINTER_REGS.
+
+2013-10-16 Yvan Roux <yvan.roux@linaro.org>
+
+ * config/arm/arm.opt (mlra): New option.
+ * config/arm/arm.c (arm_lra_p): New function.
+ (TARGET_LRA_P): Define.
+
+2013-10-16 Paulo Matos <pmatos@broadcom.com>
+
+ * tree-core.h (tree_code_name): Remove.
+ * tree.h (get_tree_code_name): New prototype.
+ * tree.c (tree_code_name): Make static.
+ (get_tree_code_name): New function.
+ (dump_tree_statistics, tree_check_failed, tree_not_check_failed,
+ tree_class_check_failed, tree_range_check_failed,
+ tree_not_class_check_failed, omp_clause_check_failed,
+ tree_contains_struct_check_failed, tree_operand_check_failed): Use new
+ wrapper get_tree_code_name instead of calling tree_code_name directly.
+ * tree-vrp.c (dump_asserts_for): Likewise.
+ * tree-dump.c (dequeue_and_dump): Likewise.
+ * tree-pretty-print.c (do_niy, dump_generic_node): Likewise.
+ * tree-pretty-print.h (pp_unsupported_tree): Likewise.
+ * lto-streamer-out.c (lto_write_tree, DFS_write_tree): Likewise.
+ * tree-ssa-dom.c (print_expr_hash_elt): Likewise.
+ * gimple-pretty-print.c (dump_unary_rhs, dump_binary_rhs,
+ dump_ternary_rhs, dump_gimple_assign, dump_gimple_cond,
+ dump_gimple_omp_for): Likewise.
+ * tree-vect-data-refs.c (vect_create_data_ref_ptr): Likewise.
+ * tree-ssa-pre.c (print_pre_expr): Likewise.
+ * ipa-prop.c (ipa_print_node_jump_functions_for_edge): Likewise.
+ * print-tree.c (print_node_brief, print_node): Likewise.
+ * gimple.c (gimple_check_failed): Likewise.
+ * lto-streamer.c (lto_tag_name, print_lto_report): Likewise.
+ * config/frv/frv.c (frv_init_cumulative_args): Likewise.
+ * config/mep/mep.c (mep_validate_vliw): Likewise.
+ * config/iq2000/iq2000.c (init_cumulative_args): Likewise.
+ * config/rs6000/rs6000.c (init_cumulative_args): Likewise.
+
+2013-10-16 Ganesh Gopalasubramanian <Ganesh.Gopalasubramanian@amd.com>
+
+ * config/i386/i386.c (ix86_option_override_internal): Enable FMA4
+ for AMD bdver3.
+
+2013-10-16 Hans-Peter Nilsson <hp@axis.com>
+
+ * config/cris/t-elfmulti (MULTILIB_OPTIONS, MULTILIB_DIRNAMES)
+ (MULTILIB_MATCHES): Add multilib for -march=v8.
+
+2013-10-15 Sriraman Tallam <tmsriram@google.com>
+
+ PR target/57756
+ * optc-save-gen.awk: Add extra parameter to the save and restore
+ target calls.
+ * opth-gen.awk: Generate new TARGET_* macros to accept a parameter.
+ * tree.c (build_optimization_node): New parameter. Add extra parameter
+ to call to cl_optimization_save.
+ (build_target_option_node): New parameter. Add extra parameter
+ to call to cl_target_option_save.
+ * tree.h (build_optimization_node): New parameter.
+ (build_target_option_node): New parameter.
+ * c-family/c-common.c (handle_optimize_attribute): Fix calls to
+ build_optimization_node and build_target_option_node.
+ * c-family/c-pragma.c (handle_pragma_optimize): Ditto.
+ (handle_pragma_push_options): Ditto.
+ * toplev.c (process_options): Ditto.
+ * opts.c (init_options_struct): Check for opts_set non-null.
+ * target.def (target_option.save): New parameter.
+ (target_option.restore): New parameter.
+ * tm.texi: Generate.
+ * config/i386/i386-c.c (ix86_target_macros_internal): Ditto.
+ (ix86_pragma_target_parse): Ditto.
+ * config/i386/i386-protos.h (ix86_valid_target_attribute_tree): New
+ parameters.
+ * config/rs6000/rs6000.c (rs6000_option_override_internal): Fix calls
+ to build_optimization_node and build_target_option_node.
+ (rs6000_valid_attribute_p): Ditto.
+ (rs6000_pragma_target_parse): Ditto.
+ * config/i386/i386.opt (x_ix86_target_flags_explicit): New TargetSave
+ data.
+ * config/i386/i386.h:
+ TARGET_64BIT_P: New Macro
+ TARGET_MMX_P: New Macro.
+ TARGET_3DNOW_P: New Macro.
+ TARGET_3DNOW_A_P: New Macro.
+ TARGET_SSE_P: New Macro.
+ TARGET_SSE2_P: New Macro.
+ TARGET_SSE3_P: New Macro.
+ TARGET_SSSE3_P: New Macro.
+ TARGET_SSE4_1_P: New Macro.
+ TARGET_SSE4_2_P: New Macro.
+ TARGET_AVX_P: New Macro.
+ TARGET_AVX2_P: New Macro.
+ TARGET_AVX512F_P: New Macro.
+ TARGET_AVX512PF_P: New Macro.
+ TARGET_AVX512ER_P: New Macro.
+ TARGET_AVX512CD_P: New Macro.
+ TARGET_FMA_P: New Macro.
+ TARGET_SSE4A_P: New Macro.
+ TARGET_FMA4_P: New Macro.
+ TARGET_XOP_P: New Macro.
+ TARGET_LWP_P: New Macro.
+ TARGET_ABM_P: New Macro.
+ TARGET_BMI_P: New Macro.
+ TARGET_BMI2_P: New Macro.
+ TARGET_LZCNT_P: New Macro.
+ TARGET_TBM_P: New Macro.
+ TARGET_POPCNT_P: New Macro.
+ TARGET_SAHF_P: New Macro.
+ TARGET_MOVBE_P: New Macro.
+ TARGET_CRC32_P: New Macro.
+ TARGET_AES_P: New Macro.
+ TARGET_PCLMUL_P: New Macro.
+ TARGET_CMPXCHG16B_P: New Macro.
+ TARGET_FSGSBASE_P: New Macro.
+ TARGET_RDRND_P: New Macro.
+ TARGET_F16C_P: New Macro.
+ TARGET_RTM_P: New Macro.
+ TARGET_HLE_P: New Macro.
+ TARGET_RDSEED_P: New Macro.
+ TARGET_PRFCHW_P: New Macro.
+ TARGET_ADX_P: New Macro.
+ TARGET_FXSR_P: New Macro.
+ TARGET_XSAVE_P: New Macro.
+ TARGET_XSAVEOPT_P: New Macro.
+ TARGET_LP64_P: New Macro.
+ TARGET_X32_P: New Macro.
+ TARGET_FPMATH_DEFAULT_P: New Macro.
+ TARGET_FLOAT_RETURNS_IN_80387_P: New Macro.
+ * config/i386/i386.c (ix86_option_override_internal): New parameters.
+ opts and opts_set.
+ Change ix86_tune_string to access opts->x_ix86_tune_string.
+ Change ix86_isa_flags to access opts->x_ix86_isa_flags.
+ Change ix86_arch_string to access opts->x_ix86_arch_string.
+ Change ix86_stringop_alg to access opts->x_ix86_stringop_alg.
+ Change ix86_pmode to access opts->x_ix86_pmode.
+ Change ix86_abi to access opts->x_ix86_abi.
+ Change ix86_cmodel to access opts->x_ix86_cmodel.
+ Change ix86_asm_dialect to access opts->x_ix86_asm_dialect.
+ Change ix86_isa_flags_explicit to access
+ opts->x_ix86_isa_flags_explicit.
+ Change ix86_dump_tunes to access opts->x_ix86_dump_tunes.
+ Change ix86_regparm to access opts->x_ix86_regparm.
+ Change ix86_branch_cost to access opts->x_ix86_branch_cost.
+ Change ix86_preferred_stack_boundary_arg to access
+ opts->x_ix86_preferred_stack_boundary_arg.
+ Change ix86_force_align_arg_pointer to access
+ opts->x_ix86_force_align_arg_pointer.
+ Change ix86_incoming_stack_boundar_arg to access
+ opts->x_ix86_incoming_stack_boundar_arg.
+ Change ix86_fpmath to access opts->x_ix86_fpmath.
+ Change ix86_veclibabi_type to access opts->x_ix86_veclibabi_type.
+ Change ix86_recip_name to access opts->x_ix86_recip_name.
+ Change ix86_stack_protector_guard to access
+ opts->x_ix86_stack_protector_guard.
+ Change ix86_tune_memcpy_strategy to access
+ opts->x_ix86_tune_memcpy_strategy.
+ Change ix86_tune_memset_strategy to access
+ opts->x_ix86_tune_memset_strategy.
+ Change global_options to access opts.
+ Change global_options_set to access opts_set.
+ Change TARGET_64BIT to TARGET_64BIT_P (opts->...).
+ Change TARGET_MMX to TARGET_MMX_P (opts->...).
+ Change TARGET_3DNOW to TARGET_3DNOW_P (opts->...).
+ Change TARGET_3DNOW_A to TARGET_3DNOW_A_P (opts->...).
+ Change TARGET_SSE to TARGET_SSE_P (opts->...).
+ Change TARGET_SSE2 to TARGET_SSE2_P (opts->...).
+ Change TARGET_SSE3 to TARGET_SSE3_P (opts->...).
+ Change TARGET_SSSE3 to TARGET_SSSE3_P (opts->...).
+ Change TARGET_SSE4_1 to TARGET_SSE4_1_P (opts->...).
+ Change TARGET_SSE4_2 to TARGET_SSE4_2_P (opts->...).
+ Change TARGET_AVX to TARGET_AVX_P (opts->...).
+ Change TARGET_AVX2 to TARGET_AVX2_P (opts->...).
+ Change TARGET_AVX512F to TARGET_AVX512F_P (opts->...).
+ Change TARGET_AVX512PF to TARGET_AVX512PF_P (opts->...).
+ Change TARGET_AVX512ER to TARGET_AVX512ER_P (opts->...).
+ Change TARGET_AVX512CD to TARGET_AVX512CD_P (opts->...).
+ Change TARGET_FMA to TARGET_FMA_P (opts->...).
+ Change TARGET_SSE4A to TARGET_SSE4A_P (opts->...).
+ Change TARGET_FMA4 to TARGET_FMA4_P (opts->...).
+ Change TARGET_XOP to TARGET_XOP_P (opts->...).
+ Change TARGET_LWP to TARGET_LWP_P (opts->...).
+ Change TARGET_ABM to TARGET_ABM_P (opts->...).
+ Change TARGET_BMI to TARGET_BMI_P (opts->...).
+ Change TARGET_BMI2 to TARGET_BMI2_P (opts->...).
+ Change TARGET_LZCNT to TARGET_LZCNT_P (opts->...).
+ Change TARGET_TBM to TARGET_TBM_P (opts->...).
+ Change TARGET_POPCNT to TARGET_POPCNT_P (opts->...).
+ Change TARGET_SAHF to TARGET_SAHF_P (opts->...).
+ Change TARGET_MOVBE to TARGET_MOVBE_P (opts->...).
+ Change TARGET_CRC32 to TARGET_CRC32_P (opts->...).
+ Change TARGET_AES to TARGET_AES_P (opts->...).
+ Change TARGET_PCLMUL to TARGET_PCLMUL_P (opts->...).
+ Change TARGET_CMPXCHG16B to TARGET_CMPXCHG16B_P (opts->...).
+ Change TARGET_FSGSBASE to TARGET_FSGSBASE_P (opts->...).
+ Change TARGET_RDRND to TARGET_RDRND_P (opts->...).
+ Change TARGET_F16C to TARGET_F16C_P (opts->...).
+ Change TARGET_RTM to TARGET_RTM_P (opts->...).
+ Change TARGET_HLE to TARGET_HLE_P (opts->...).
+ Change TARGET_RDSEED to TARGET_RDSEED_P (opts->...).
+ Change TARGET_PRFCHW to TARGET_PRFCHW_P (opts->...).
+ Change TARGET_ADX to TARGET_ADX_P (opts->...).
+ Change TARGET_FXSR to TARGET_FXSR_P (opts->...).
+ Change TARGET_XSAVE to TARGET_XSAVE_P (opts->...).
+ Change TARGET_XSAVEOPT to TARGET_XSAVEOPT_P (opts->...).
+ Change TARGET_LP64 to TARGET_LP64_P (opts->...).
+ Change TARGET_X32 to TARGET_X32_P (opts->...).
+ Change TARGET_FPMATH_DEFAULT to TARGET_FPMATH_DEFAULT_P (opts->...).
+ Change TARGET_FLOAT_RETURNS_IN_80387 to
+ TARGET_FLOAT_RETURNS_IN_80387_P (opts->...).
+ (ix86_function_specific_save): New parameter. Use opts-> fields
+ to replace global fields.
+ (ix86_function_specific_restore): Ditto.
+ (ix86_valid_target_attribute_inner_p): New parameters.
+ Fix recursive call.
+ Fix call to ix86_handle_option and set_option.
+ (ix86_valid_target_attribute_tree): New parameters.
+ Change global_options to access opts.
+ Change global_options_set to access opts_set.
+ Fix call to ix86_valid_target_attribute_inner_p.
+ Change ix86_tune_string to access opts->x_ix86_tune_string.
+ Change ix86_arch_string to access opts->x_ix86_arch_string.
+ Change ix86_fpmath to access opts->x_ix86_fpmath
+ Fix call to ix86_option_override_internal.
+ Fix call to ix86_add_new_builtins.
+ Fix calls to build_optimization_node and build_target_option_node.
+ (ix86_valid_target_attribute_p): Remove access to global_options.
+ Use new gcc_options structure func_options.
+ Fix call to ix86_valid_target_attribute_tree.
+ Fix call to build_optimization_node.
+ (get_builtin_code_for_version): Fix call to
+ ix86_valid_target_attribute_tree.
+
+2013-10-15 David Malcolm <dmalcolm@redhat.com>
+
+ * Makefile.in (PICFLAG): New.
+ (enable_host_shared): New.
+ (INTERNAL_CFLAGS): Use PICFLAG.
+ (LIBIBERTY): Use pic build of libiberty.a if configured with
+ --enable-host-shared.
+ * configure.ac: Add --enable-host-shared, setting up new
+ PICFLAG variable.
+ * configure: Regenerate.
+ * doc/install.texi (--enable-shared): Add note contrasting it with ...
+ (--enable-host-shared): New option.
+
+2013-10-15 Richard Biener <rguenther@suse.de>
+
+ * tree-tailcall.c (find_tail_calls): Don't use tail-call recursion
+ for built-in functions.
+
+2013-10-15 Zhenqiang Chen <zhenqiang.chen@arm.com>
+
+ * tree-ssa-reassoc.c: Include rtl.h and tm_p.h.
+ (optimize_range_tests_1): New function,
+ extracted from optimize_range_tests.
+ (optimize_range_tests_xor): Similarly.
+ (optimize_range_tests_diff): New function.
+ (optimize_range_tests): Use optimize_range_tests_1.
+
+2013-10-15 Cong Hou <congh@google.com>
+
+ * tree-vect-loop.c (vect_is_simple_reduction_1): Relax the
+ requirement of the reduction pattern so that one operand of the
+ reduction operation can come from outside of the loop.
+
+2013-10-15 James Greenhalgh <james.greenhalgh@arm.com>
+
+ * config/arm/neon-schedgen.ml: Remove.
+ * config/arm/cortex-a9-neon.md: Remove comment regarding
+ neon-schedgen.ml.
+
+2013-10-15 James Greenhalgh <james.greenhalgh@arm.com>
+
+ * config/arm/types: Remove old neon types.
+
+2013-10-15 James Greenhalgh <james.greenhalgh@arm.com>
+
+ * config/arm/cortex-a7.md
+ (cortex_a7_neon_type): New.
+ (cortex_a7_neon_mul): Update for new types.
+ (cortex_a7_neon_mla): Likewise.
+ (cortex_a7_neon): Likewise.
+
+2013-10-15 James Greenhalgh <james.greenhalgh@arm.com>
+
+ * config/arm/cortex-a15-neon.md
+ (cortex_a15_neon_type): New,
+
+ (cortex_a15_neon_int_1): Remove.
+ (cortex_a15_neon_int_2): Likewise.
+ (cortex_a15_neon_int_3): Likewise.
+ (cortex_a15_neon_int_4): Likewise.
+ (cortex_a15_neon_int_5): Likewise.
+ (cortex_a15_neon_vqneg_vqabs): Likewise.
+ (cortex_a15_neon_vmov): Likewise.
+ (cortex_a15_neon_vaba): Likewise.
+ (cortex_a15_neon_vaba_qqq): Likewise.
+ (cortex_a15_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long): Likewise.
+ (cortex_a15_neon_mul_qqq_8_16_32_ddd_32): Likewise.
+ (cortex_a15_neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar):
+ Likewise.
+ (cortex_a15_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long): Likewise.
+ (cortex_a15_neon_mla_qqq_8_16): Likewise.
+ (cortex_a15_neon_mla_ddd_32_qqd_16_ddd_32_scalar): Likewise.
+ (cortex_a15_neon_mla_qqq_32_qqd_32_scalar): Likewise.
+ (cortex_a15_neon_mul_ddd_16_scalar_32_16_long_scalar): Likewise.
+ (cortex_a15_neon_mul_qqd_32_scalar): Likewise.
+ (cortex_a15_neon_mla_ddd_16_scalar_qdd_32_16_long_scalar): Likewise.
+ (cortex_a15_neon_shift_1): Likewise.
+ (cortex_a15_neon_shift_2): Likewise.
+ (cortex_a15_neon_shift_3): Likewise.
+ (cortex_a15_neon_vshl_ddd): Likewise.
+ (cortex_a15_neon_vqshl_vrshl_vqrshl_qqq): Likewise.
+ (cortex_a15_neon_vsra_vrsra): Likewise.
+ (cortex_a15_neon_fp_vmla_ddd_scalar): Likewise.
+ (cortex_a15_neon_fp_vmla_qqq_scalar): Likewise.
+ (cortex_a15_neon_bp_3cycle): Likewise.
+ (cortex_a15_neon_ldm_2): Likewise.
+ (cortex_a15_neon_stm_2): Likewise.
+ (cortex_a15_neon_mcr): Likewise.
+ (cortex_a15_neon_mrc): Likewise.
+ (cortex_a15_neon_fp_vadd_ddd_vabs_dd): Likewise.
+ (cortex_a15_neon_fp_vadd_qqq_vabs_qq): Likewise.
+ (cortex_a15_neon_fp_vmul_ddd): Likewise.
+ (cortex_a15_neon_fp_vmul_qqd): Likewise.
+ (cortex_a15_neon_fp_vmla_ddd): Likewise.
+ (cortex_a15_neon_fp_vmla_qqq): Likewise.
+ (cortex_a15_neon_fp_vmla_ddd_scalar): Likewise.
+ (cortex_a15_neon_fp_vmla_qqq_scalar): Likewise.
+ (cortex_a15_neon_fp_vrecps_vrsqrts_ddd): Likewise.
+ (cortex_a15_neon_fp_vrecps_vrsqrts_qqq): Likewise.
+ (cortex_a15_neon_bp_simple): Likewise.
+ (cortex_a15_neon_bp_2cycle): Likewise.
+ (cortex_a15_neon_bp_3cycle): Likewise.
+ (cortex_a15_neon_vld1_1_2_regs): Likewise.
+ (cortex_a15_neon_vld1_3_4_regs): Likewise.
+ (cortex_a15_neon_vld2_2_regs_vld1_vld2_all_lanes): Likewise.
+ (cortex_a15_neon_vld2_4_regs): Likewise.
+ (cortex_a15_neon_vld3_vld4): Likewise.
+ (cortex_a15_neon_vst1_1_2_regs_vst2_2_regs): Likewise.
+ (cortex_a15_neon_vst1_3_4_regs): Likewise.
+ (cortex_a15_neon_vst2_4_regs_vst3_vst4): Rename to...
+ (cortex_a15_neon_vst2_4_regs_vst3): ...This, update for new attributes.
+ (cortex_a15_neon_vst3_vst4): Rename to...
+ (cortex_a15_neon_vst4): This, update for new attributes.
+ (cortex_a15_neon_vld1_vld2_lane): Update for new attributes.
+ (cortex_a15_neon_vld3_vld4_lane): Likewise.
+ (cortex_a15_neon_vst1_vst2_lane): Likewise.
+ (cortex_a15_neon_vst3_vst4_lane): Likewise.
+ (cortex_a15_neon_vld3_vld4_all_lanes): Likewise.
+ (cortex_a15_neon_ldm_2): Likewise.
+ (cortex_a15_neon_stm_2): Likewise.
+ (cortex_a15_neon_mcr): Likewise.
+ (cortex_a15_neon_mcr_2_mcrr): Likewise.
+ (cortex_a15_neon_mrc): Likewise.
+ (cortex_a15_neon_mrrc): Likewise.
+
+ (cortex_a15_neon_abd): New.
+ (cortex_a15_neon_abd_q): Likewise.
+ (cortex_a15_neon_aba): Likewise.
+ (cortex_a15_neon_aba_q): Likewise.
+ (cortex_a15_neon_acc): Likewise.
+ (cortex_a15_neon_acc_q): Likewise.
+ (cortex_a15_neon_arith_basic): Likewise.
+ (cortex_a15_neon_arith_complex): Likewise.
+ (cortex_a15_neon_multiply): Likewise.
+ (cortex_a15_neon_multiply_q): Likewise.
+ (cortex_a15_neon_mla): Likewise.
+ (cortex_a15_neon_mla_q): Likewise.
+ (cortex_a15_neon_sat_mla_long): Likewise.
+ (cortex_a15_neon_shift_acc): Likewise.
+ (cortex_a15_neon_shift_imm_basic): Likewise.
+ (cortex_a15_neon_shift_imm_complex): Likewise.
+ (cortex_a15_neon_shift_reg_basic): Likewise.
+ (cortex_a15_neon_shift_reg_basic_q): Likewise.
+ (cortex_a15_neon_shift_reg_complex): Likewise.
+ (cortex_a15_neon_shift_reg_complex_q): Likewise.
+ (cortex_a15_neon_fp_negabs): Likewise
+ (cortex_a15_neon_fp_arith): Likewise
+ (cortex_a15_neon_fp_arith_q): Likewise
+ (cortex_a15_neon_fp_cvt_int): Likewise
+ (cortex_a15_neon_fp_cvt_int_q): Likewise
+ (cortex_a15_neon_fp_cvt_16): Likewise
+ (cortex_a15_neon_fp_mul): Likewise
+ (cortex_a15_neon_fp_mul_q): Likewise
+ (cortex_a15_neon_fp_mla): Likewise
+ (cortex_a15_neon_fp_mla_q): Likewise
+ (cortex_a15_neon_fp_recps_rsqrte): Likewise.
+ (cortex_a15_neon_fp_recps_rsqrte_q): Likewise.
+ (cortex_a15_neon_bitops): Likewise.
+ (cortex_a15_neon_bitops_q): Likewise.
+ (cortex_a15_neon_from_gp): Likewise.
+ (cortex_a15_neon_from_gp_q): Likewise.
+ (cortex_a15_neon_tbl3_tbl4): Likewise.
+ (cortex_a15_neon_zip_q): Likewise.
+ (cortex_a15_neon_to_gp): Likewise.
+ (cortex_a15_neon_load_a): Likewise.
+ (cortex_a15_neon_load_b): Likewise.
+ (cortex_a15_neon_load_c): Likewise.
+ (cortex_a15_neon_load_d): Likewise.
+ (cortex_a15_neon_load_e): Likewise.
+ (cortex_a15_neon_load_f): Likewise.
+ (cortex_a15_neon_store_a): Likewise.
+ (cortex_a15_neon_store_b): Likewise.
+ (cortex_a15_neon_store_c): Likewise.
+ (cortex_a15_neon_store_d): Likewise.
+ (cortex_a15_neon_store_e): Likewise.
+ (cortex_a15_neon_store_f): Likewise.
+ (cortex_a15_neon_store_g): Likewise.
+ (cortex_a15_neon_store_h): Likewise.
+ (cortex_a15_vfp_to_from_gp): Likewise.
+
+2013-10-15 James Greenhalgh <james.greenhalgh@arm.com>
+
+ * config/arm/cortex-a9-neon.md (cortex_a9_neon_type): New.
+
+ (cortex_a9_neon_vshl_ddd): Remove.
+ (cortex_a9_neon_vst3_vst4): Likewise.
+ (cortex_a9_neon_vld3_vld4_all_lanes): Likewise.
+
+ (cortex_a9_neon_bit_ops_q): New.
+
+ (cortex_a9_neon_int_1): Use cortex_a8_neon_type.
+ (cortex_a9_neon_int_2): Likewise.
+ (cortex_a9_neon_int_3): Likewise.
+ (cortex_a9_neon_int_4): Likewise.
+ (cortex_a9_neon_int_5): Likewise.
+ (cortex_a9_neon_vqneg_vqabs): Likewise.
+ (cortex_a9_neon_vmov): Likewise.
+ (cortex_a9_neon_vaba): Likewise.
+ (cortex_a9_neon_vaba_qqq): Likewise.
+ (cortex_a9_neon_shift_1): Likewise.
+ (cortex_a9_neon_shift_2): Likewise.
+ (cortex_a9_neon_shift_3): Likewise.
+ (cortex_a9_neon_vqshl_vrshl_vqrshl_qqq): Likewise.
+ (cortex_a9_neon_vsra_vrsra): Likewise.
+ (cortex_a9_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long): Likewise.
+ (cortex_a9_neon_mul_qqq_8_16_32_ddd_32): Likewise.
+ (cortex_a9_neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar):
+ Likewise.
+ (cortex_a9_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long): Likewise.
+ (cortex_a9_neon_mla_qqq_8_16): Likewise.
+ (cortex_a9_neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long):
+ Likewise.
+ (cortex_a9_neon_mla_qqq_32_qqd_32_scalar): Likewise.
+ (cortex_a9_neon_mul_ddd_16_scalar_32_16_long_scalar): Likewise.
+ (cortex_a9_neon_mul_qqd_32_scalar): Likewise.
+ (cortex_a9_neon_mla_ddd_16_scalar_qdd_32_16_long_scalar): Likewise.
+ (cortex_a9_neon_fp_vadd_ddd_vabs_dd): Likewise.
+ (cortex_a9_neon_fp_vadd_qqq_vabs_qq): Likewise.
+ (cortex_a9_neon_fp_vsum): Likewise.
+ (cortex_a9_neon_fp_vmul_ddd): Likewise.
+ (cortex_a9_neon_fp_vmul_qqd): Likewise.
+ (cortex_a9_neon_fp_vmla_ddd): Likewise.
+ (cortex_a9_neon_fp_vmla_qqq): Likewise.
+ (cortex_a9_neon_fp_vmla_ddd_scalar): Likewise.
+ (cortex_a9_neon_fp_vmla_qqq_scalar): Likewise.
+ (cortex_a9_neon_fp_vrecps_vrsqrts_ddd): Likewise.
+ (cortex_a9_neon_fp_vrecps_vrsqrts_qqq): Likewise.
+ (cortex_a9_neon_bp_simple): Likewise.
+ (cortex_a9_neon_bp_2cycle): Likewise.
+ (cortex_a9_neon_bp_3cycle): Likewise.
+ (cortex_a9_neon_ldr): Likewise.
+ (cortex_a9_neon_str): Likewise.
+ (cortex_a9_neon_vld1_1_2_regs): Likewise.
+ (cortex_a9_neon_vld1_3_4_regs): Likewise.
+ (cortex_a9_neon_vld2_2_regs_vld1_vld2_all_lanes): Likewise.
+ (cortex_a9_neon_vld2_4_regs): Likewise.
+ (cortex_a9_neon_vld3_vld4): Likewise.
+ (cortex_a9_neon_vld1_vld2_lane): Likewise.
+ (cortex_a9_neon_vld3_vld4_lane): Likewise.
+ (cortex_a9_neon_vld3_vld4_all_lanes): Likewise.
+ (cortex_a9_neon_vst1_1_2_regs_vst2_2_regs): Likewise.
+ (cortex_a9_neon_vst1_3_4_regs): Likewise.
+ (cortex_a9_neon_vst2_4_regs_vst3_vst4): Likewise.
+ (cortex_a9_neon_vst1_vst2_lane): Likewise.
+ (cortex_a9_neon_vst3_vst4_lane): Likewise.
+ (cortex_a9_neon_mcr): Likewise.
+ (cortex_a9_neon_mcr_2_mcrr): Likewise.
+ (cortex_a9_neon_mrc): Likewise.
+ (cortex_a9_neon_mrrc): Likewise.
+
+2013-10-15 James Greenhalgh <james.greenhalgh@arm.com>
+
+ * config/arm/cortex-a8-neon.md (cortex_a8_neon_type): New.
+
+ (cortex_a8_neon_vshl_ddd): Remove.
+ (cortex_a8_neon_vst3_vst4): Likewise.
+ (cortex_a8_neon_vld3_vld4_all_lanes): Likewise.
+
+ (cortex_a8_neon_bit_ops_q): New.
+
+ (cortex_a8_neon_int_1): Use cortex_a8_neon_type.
+ (cortex_a8_neon_int_2): Likewise..
+ (cortex_a8_neon_int_3): Likewise.
+ (cortex_a8_neon_int_5): Likewise.
+ (cortex_a8_neon_vqneg_vqabs): Likewise.
+ (cortex_a8_neon_int_4): Likewise.
+ (cortex_a8_neon_vaba): Likewise.
+ (cortex_a8_neon_vaba_qqq): Likewise.
+ (cortex_a8_neon_shift_1): Likewise.
+ (cortex_a8_neon_shift_2): Likewise.
+ (cortex_a8_neon_shift_3): Likewise.
+ (cortex_a8_neon_vqshl_vrshl_vqrshl_qqq): Likewise.
+ (cortex_a8_neon_vsra_vrsra): Likewise.
+ (cortex_a8_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long): Likewise.
+ (cortex_a8_neon_mul_qqq_8_16_32_ddd_32): Likewise.
+ (cortex_a8_neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar):
+ Likewise.
+ (cortex_a8_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long): Likewise.
+ (cortex_a8_neon_mla_qqq_8_16): Likewise.
+ (cortex_a8_neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long):
+ Likewise.
+ (cortex_a8_neon_mla_qqq_32_qqd_32_scalar): Likewise.
+ (cortex_a8_neon_mul_ddd_16_scalar_32_16_long_scalar): Likewise.
+ (cortex_a8_neon_mul_qqd_32_scalar): Likewise.
+ (cortex_a8_neon_mla_ddd_16_scalar_qdd_32_16_long_scalar): Likewise.
+ (cortex_a8_neon_fp_vadd_ddd_vabs_dd): Likewise.
+ (cortex_a8_neon_fp_vadd_qqq_vabs_qq): Likewise.
+ (cortex_a8_neon_fp_vsum): Likewise.
+ (cortex_a8_neon_fp_vmul_ddd): Likewise.
+ (cortex_a8_neon_fp_vmul_qqd): Likewise.
+ (cortex_a8_neon_fp_vmla_ddd): Likewise.
+ (cortex_a8_neon_fp_vmla_qqq): Likewise.
+ (cortex_a8_neon_fp_vmla_ddd_scalar): Likewise.
+ (cortex_a8_neon_fp_vmla_qqq_scalar): Likewise.
+ (cortex_a8_neon_fp_vrecps_vrsqrts_ddd): Likewise.
+ (cortex_a8_neon_fp_vrecps_vrsqrts_qqq): Likewise.
+ (cortex_a8_neon_bp_simple): Likewise.
+ (cortex_a8_neon_bp_2cycle): Likewise.
+ (cortex_a8_neon_bp_3cycle): Likewise.
+ (cortex_a8_neon_ldr): Likewise.
+ (cortex_a8_neon_str): Likewise.
+ (cortex_a8_neon_vld1_1_2_regs): Likewise.
+ (cortex_a8_neon_vld1_3_4_regs): Likewise.
+ (cortex_a8_neon_vld2_2_regs_vld1_vld2_all_lanes): Likewise.
+ (cortex_a8_neon_vld2_4_regs): Likewise.
+ (cortex_a8_neon_vld3_vld4): Likewise.
+ (cortex_a8_neon_vld1_vld2_lane): Likewise.
+ (cortex_a8_neon_vld3_vld4_lane): Likewise.
+ (cortex_a8_neon_vst1_1_2_regs_vst2_2_regs): Likewise.
+ (cortex_a8_neon_vst1_3_4_regs): Likewise.
+ (cortex_a8_neon_vst2_4_regs_vst3_vst4): Likewise.
+ (cortex_a8_neon_vst1_vst2_lane): Likewise.
+ (cortex_a8_neon_vst3_vst4_lane): Likewise.
+ (cortex_a8_neon_mcr): Likewise.
+ (cortex_a8_neon_mcr_2_mcrr): Likewise.
+ (cortex_a8_neon_mrc): Likewise.
+ (cortex_a8_neon_mrrc): Likewise.
+
+2013-10-15 James Greenhalgh <james.greenhalgh@arm.com>
+
+ * config/aarch64/iterators.md (Vetype): Add SF and DF modes.
+ (fp): New.
+ * config/aarch64/aarch64-simd.md (neon_type): Remove.
+ (aarch64_simd_dup<mode>): Add "type" attribute.
+ (aarch64_dup_lane<mode>): Likewise.
+ (aarch64_dup_lane_<vswap_width_name><mode>): Likewise.
+ (*aarch64_simd_mov<mode>): Likewise.
+ (aarch64_simd_mov_from_<mode>low): Likewise.
+ (aarch64_simd_mov_from_<mode>high): Likewise.
+ (orn<mode>3): Likewise.
+ (bic<mode>3): Likewise.
+ (add<mode>3): Likewise.
+ (sub<mode>3): Likewise.
+ (mul<mode>3): Likewise.
+ (*aarch64_mul3_elt<mode>): Likewise.
+ (*aarch64_mul3_elt_<vswap_width_name><mode>): Likewise.
+ (*aarch64_mul3_elt_to_128df): Likewise.
+ (*aarch64_mul3_elt_to_64v2df): Likewise.
+ (neg<mode>2): Likewise.
+ (abs<mode>2): Likewise.
+ (abd<mode>_3): Likewise.
+ (aba<mode>_3): Likewise.
+ (fabd<mode>_3): Likewise.
+ (*fabd_scalar<mode>3): Likewise.
+ (and<mode>3): Likewise.
+ (ior<mode>3): Likewise.
+ (xor<mode>3): Likewise.
+ (one_cmpl<mode>2): Likewise.
+ (aarch64_simd_vec_set<mode>): Likewise.
+ (aarch64_simd_lshr<mode>): Likewise.
+ (aarch64_simd_ashr<mode>): Likewise.
+ (aarch64_simd_imm_shl<mode>): Likewise.
+ (aarch64_simd_reg_sshl<mode): Likewise.
+ (aarch64_simd_reg_shl<mode>_unsigned): Likewise.
+ (aarch64_simd_reg_shl<mode>_signed): Likewise.
+ (aarch64_simd_vec_setv2di): Likewise.
+ (aarch64_simd_vec_set<mode>): Likewise.
+ (aarch64_mla<mode>): Likewise.
+ (*aarch64_mla_elt<mode>): Likewise.
+ (*aarch64_mla_elt_<vswap_width_name><mode>): Likewise.
+ (aarch64_mls<mode>): Likewise.
+ (*aarch64_mls_elt<mode>): Likewise.
+ (*aarch64_mls_elt_<vswap_width_name><mode>): Likewise.
+ (<su><maxmin><mode>3): Likewise.
+ (move_lo_quad_<mode>): Likewise.
+ (aarch64_simd_move_hi_quad_<mode>): Likewise.
+ (aarch64_simd_vec_pack_trunc_<mode>): Likewise.
+ (vec_pack_trunc_<mode>): Likewise.
+ (aarch64_simd_vec_unpack<su>_lo_<mode>): Likewise.
+ (aarch64_simd_vec_unpack<su>_hi_<mode>): Likewise.
+ (*aarch64_<su>mlal_lo<mode>): Likewise.
+ (*aarch64_<su>mlal_hi<mode>): Likewise.
+ (*aarch64_<su>mlsl_lo<mode>): Likewise.
+ (*aarch64_<su>mlsl_hi<mode>): Likewise.
+ (*aarch64_<su>mlal<mode>): Likewise.
+ (*aarch64_<su>mlsl<mode>): Likewise.
+ (aarch64_simd_vec_<su>mult_lo_<mode>): Likewise.
+ (aarch64_simd_vec_<su>mult_hi_<mode>): Likewise.
+ (add<mode>3): Likewise.
+ (sub<mode>3): Likewise.
+ (mul<mode>3): Likewise.
+ (div<mode>3): Likewise.
+ (neg<mode>2): Likewise.
+ (abs<mode>2): Likewise.
+ (fma<mode>4): Likewise.
+ (*aarch64_fma4_elt<mode>): Likewise.
+ (*aarch64_fma4_elt_<vswap_width_name><mode>): Likewise.
+ (*aarch64_fma4_elt_to_128df): Likewise.
+ (*aarch64_fma4_elt_to_64v2df): Likewise.
+ (fnma<mode>4): Likewise.
+ (*aarch64_fnma4_elt<mode>): Likewise.
+ (*aarch64_fnma4_elt_<vswap_width_name><mode>
+ (*aarch64_fnma4_elt_to_128df): Likewise.
+ (*aarch64_fnma4_elt_to_64v2df): Likewise.
+ (<frint_pattern><mode>2): Likewise.
+ (l<fcvt_pattern><su_optab><VDQF:mode><fcvt_target>2): Likewise.
+ (<optab><fcvt_target><VDQF:VDQF:mode>2): Likewise.
+ (vec_unpacks_lo_v4sf): Likewise.
+ (aarch64_float_extend_lo_v2df): Likewise.
+ (vec_unpacks_hi_v4sf): Likewise.
+ (aarch64_float_truncate_lo_v2sf): Likewise.
+ (aarch64_float_truncate_hi_v4sf): Likewise.
+ (aarch64_vmls<mode>): Likewise.
+ (<su><maxmin><mode>3): Likewise.
+ (<maxmin_uns><mode>3): Likewise.
+ (reduc_<sur>plus_<mode>): Likewise.
+ (reduc_<sur>plus_v2di): Likewise.
+ (reduc_<sur>plus_v2si): Likewise.
+ (reduc_<sur>plus_<mode>): Likewise.
+ (aarch64_addpv4sf): Likewise.
+ (clz<mode>2): Likewise.
+ (reduc_<maxmin_uns>_<mode>): Likewise.
+ (reduc_<maxmin_uns>_v2di): Likewise.
+ (reduc_<maxmin_uns>_v2si): Likewise.
+ (reduc_<maxmin_uns>_<mode>): Likewise.
+ (reduc_<maxmin_uns>_v4sf): Likewise.
+ (aarch64_simd_bsl<mode>_internal): Likewise.
+ (*aarch64_get_lane_extend<GPI:mode><VDQQH:mode>): Likewise.
+ (*aarch64_get_lane_zero_extendsi<mode>): Likewise.
+ (aarch64_get_lane<mode>): Likewise.
+ (*aarch64_combinez<mode>): Likewise.
+ (aarch64_combine<mode>): Likewise.
+ (aarch64_simd_combine<mode>): Likewise.
+ (aarch64_<ANY_EXTEND:su><ADDSUB:optab>l<mode>_hi_internal): Likewise.
+ (aarch64_<ANY_EXTEND:su><ADDSUB:optab>l<mode>_lo_internal): Likewise.
+ (aarch64_<ANY_EXTEND:su><ADDSUB:optab>l<mode>): Likewise.
+ (aarch64_<ANY_EXTEND:su><ADDSUB:optab>w<mode>): Likewise.
+ (aarch64_<ANY_EXTEND:su><ADDSUB:optab>w2<mode>_internal): Likewise.
+ (aarch64_<sur>h<addsub><mode>): Likewise.
+ (aarch64_<sur><addsub>hn<mode>): Likewise.
+ (aarch64_<sur><addsub>hn2<mode>): Likewise.
+ (aarch64_pmul<mode>): Likewise.
+ (aarch64_<su_optab><optab><mode>): Likewise.
+ (aarch64_<sur>qadd<mode>): Likewise.
+ (aarch64_sqmovun<mode>): Likewise.
+ (aarch64_<sur>qmovn<mode>): Likewise.
+ (aarch64_s<optab><mode>): Likewise.
+ (aarch64_sq<r>dmulh<mode>): Likewise.
+ (aarch64_sq<r>dmulh_lane<mode>): Likewise.
+ (aarch64_sq<r>dmulh_laneq<mode>): Likewise.
+ (aarch64_sq<r>dmulh_lane<mode>): Likewise.
+ (aarch64_sqdml<SBINQOPS:as>l<mode>): Likewise.
+ (aarch64_sqdml<SBINQOPS:as>l_lane<mode>_internal): Likewise.
+ (aarch64_sqdml<SBINQOPS:as>l_lane<mode>_internal): Likewise.
+ (aarch64_sqdml<SBINQOPS:as>l_n<mode>): Likewise.
+ (aarch64_sqdml<SBINQOPS:as>l2<mode>_internal): Likewise.
+ (aarch64_sqdml<SBINQOPS:as>l2_lane<mode>_internal): Likewise.
+ (aarch64_sqdml<SBINQOPS:as>l2_n<mode>_internal): Likewise.
+ (aarch64_sqdmull<mode>): Likewise.
+ (aarch64_sqdmull_lane<mode>_internal): Likewise.
+ (aarch64_sqdmull_n<mode>): Likewise.
+ (aarch64_sqdmull2<mode>_internal): Likewise.
+ (aarch64_sqdmull2_lane<mode>_internal): Likewise.
+ (aarch64_sqdmull2_n<mode>_internal): Likewise.
+ (aarch64_<sur>shl<mode>): Likewise.
+ (aarch64_<sur>q<r>shl<mode>
+ (aarch64_<sur>shll_n<mode>): Likewise.
+ (aarch64_<sur>shll2_n<mode>): Likewise.
+ (aarch64_<sur>shr_n<mode>): Likewise.
+ (aarch64_<sur>sra_n<mode>): Likewise.
+ (aarch64_<sur>s<lr>i_n<mode>): Likewise.
+ (aarch64_<sur>qshl<u>_n<mode>): Likewise.
+ (aarch64_<sur>q<r>shr<u>n_n<mode>): Likewise.
+ (aarch64_cm<optab><mode>): Likewise.
+ (aarch64_cm<optab>di): Likewise.
+ (aarch64_cm<optab><mode>): Likewise.
+ (aarch64_cm<optab>di): Likewise.
+ (aarch64_cmtst<mode>): Likewise.
+ (aarch64_cmtstdi): Likewise.
+ (aarch64_cm<optab><mode>): Likewise.
+ (*aarch64_fac<optab><mode>): Likewise.
+ (aarch64_addp<mode>): Likewise.
+ (aarch64_addpdi): Likewise.
+ (sqrt<mode>2): Likewise.
+ (vec_load_lanesoi<mode>): Likewise.
+ (vec_store_lanesoi<mode>): Likewise.
+ (vec_load_lanesci<mode>): Likewise.
+ (vec_store_lanesci<mode>): Likewise.
+ (vec_load_lanesxi<mode>): Likewise.
+ (vec_store_lanesxi<mode>): Likewise.
+ (*aarch64_mov<mode>): Likewise.
+ (aarch64_ld2<mode>_dreg): Likewise.
+ (aarch64_ld2<mode>_dreg): Likewise.
+ (aarch64_ld3<mode>_dreg): Likewise.
+ (aarch64_ld3<mode>_dreg): Likewise.
+ (aarch64_ld4<mode>_dreg): Likewise.
+ (aarch64_ld4<mode>_dreg): Likewise.
+ (aarch64_tbl1<mode>): Likewise.
+ (aarch64_tbl2v16qi): Likewise.
+ (aarch64_combinev16qi): Likewise.
+ (aarch64_<PERMUTE:perm_insn><PERMUTE:perm_hilo><mode>): Likewise.
+ (aarch64_st2<mode>_dreg): Likewise.
+ (aarch64_st2<mode>_dreg): Likewise.
+ (aarch64_st3<mode>_dreg): Likewise.
+ (aarch64_st3<mode>_dreg): Likewise.
+ (aarch64_st4<mode>_dreg): Likewise.
+ (aarch64_st4<mode>_dreg): Likewise.
+ (*aarch64_simd_ld1r<mode>): Likewise.
+ (aarch64_frecpe<mode>): Likewise.
+ (aarch64_frecp<FRECP:frecp_suffix><mode>): Likewise.
+ (aarch64_frecps<mode>): Likewise.
+
+2013-10-15 James Greenhalgh <james.greenhalgh@arm.com>
+
+ * config/arm/iterators.md (V_elem_ch): New.
+ (q): Likewise.
+ (VQH_type): Likewise.
+ * config/arm/arm.md (is_neon_type): New.
+ (conds): Use is_neon_type.
+ (anddi3_insn): Update type attribute.
+ (xordi3_insn): Likewise.
+ (one_cmpldi2): Likewise.
+ * config/arm/vfp.md (movhf_vfp_neon): Update type attribute.
+ * config/arm/neon.md (neon_mov): Update type attribute.
+ (*movmisalign<mode>_neon_store): Likewise.
+ (*movmisalign<mode>_neon_load): Likewise.
+ (vec_set<mode>_internal): Likewise.
+ (vec_set<mode>_internal): Likewise.
+ (vec_setv2di_internal): Likewise.
+ (vec_extract<mode>): Likewise.
+ (vec_extract<mode>): Likewise.
+ (vec_extractv2di): Likewise.
+ (*add<mode>3_neon): Likewise.
+ (adddi3_neon): Likewise.
+ (*sub<mode>3_neon): Likewise.
+ (subdi3_neon): Likewise.
+ (fma<VCVTF:mode>4): Likewise.
+ (fma<VCVTF:mode>4_intrinsic): Likewise.
+ (*fmsub<VCVTF:mode>4): Likewise.
+ (fmsub<VCVTF:mode>4_intrinsic): Likewise.
+ (neon_vrint<NEON_VRINT:nvrint_variant><VCVTF:mode>): Likewise.
+ (ior<mode>3): Likewise.
+ (and<mode>3): Likewise.
+ (orn<mode>3_neon): Likewise.
+ (orndi3_neon): Likewise.
+ (bic<mode>3_neon): Likewise.
+ (bicdi3_neon): Likewise.
+ (xor<mode>3): Likewise.
+ (one_cmpl<mode>2): Likewise.
+ (abs<mode>2): Likewise.
+ (neg<mode>2): Likewise.
+ (negdi2_neon): Likewise.
+ (*umin<mode>3_neon): Likewise.
+ (*umax<mode>3_neon): Likewise.
+ (*smin<mode>3_neon): Likewise.
+ (*smax<mode>3_neon): Likewise.
+ (vashl<mode>3): Likewise.
+ (vashr<mode>3_imm): Likewise.
+ (vlshr<mode>3_imm): Likewise.
+ (ashl<mode>3_signed): Likewise.
+ (ashl<mode>3_unsigned): Likewise.
+ (neon_load_count): Likewise.
+ (ashldi3_neon_noclobber): Likewise.
+ (ashldi3_neon): Likewise.
+ (signed_shift_di3_neon): Likewise.
+ (unsigned_shift_di3_neon): Likewise.
+ (ashrdi3_neon_imm_noclobber): Likewise.
+ (lshrdi3_neon_imm_noclobber): Likewise.
+ (<shift>di3_neon): Likewise.
+ (widen_ssum<mode>3): Likewise.
+ (widen_usum<mode>3): Likewise.
+ (quad_halves_<code>v4si): Likewise.
+ (quad_halves_<code>v4sf): Likewise.
+ (quad_halves_<code>v8hi): Likewise.
+ (quad_halves_<code>v16qi): Likewise.
+ (reduc_splus_v2di): Likewise.
+ (neon_vpadd_internal<mode>): Likewise.
+ (neon_vpsmin<mode>): Likewise.
+ (neon_vpsmax<mode>): Likewise.
+ (neon_vpumin<mode>): Likewise.
+ (neon_vpumax<mode>): Likewise.
+ (*ss_add<mode>_neon): Likewise.
+ (*us_add<mode>_neon): Likewise.
+ (*ss_sub<mode>_neon): Likewise.
+ (*us_sub<mode>_neon): Likewise.
+ (neon_vadd<mode>_unspec): Likewise.
+ (neon_vaddl<mode>): Likewise.
+ (neon_vaddw<mode>): Likewise.
+ (neon_vhadd<mode>): Likewise.
+ (neon_vqadd<mode>): Likewise.
+ (neon_vaddhn<mode>): Likewise.
+ (neon_vmul<mode>): Likewise.
+ (neon_vfms<VCVTF:mode>): Likewise.
+ (neon_vmlal<mode>): Likewise.
+ (neon_vmls<mode>): Likewise.
+ (neon_vmlsl<mode>): Likewise.
+ (neon_vqdmulh<mode>): Likewise.
+ (neon_vqdmlal<mode>): Likewise.
+ (neon_vqdmlsl<mode>): Likewise.
+ (neon_vmull<mode>): Likewise.
+ (neon_vqdmull<mode>): Likewise.
+ (neon_vsub<mode>_unspec): Likewise.
+ (neon_vsubl<mode>): Likewise.
+ (neon_vsubw<mode>): Likewise.
+ (neon_vqsub<mode>): Likewise.
+ (neon_vhsub<mode>): Likewise.
+ (neon_vsubhn<mode>): Likewise.
+ (neon_vceq<mode>): Likewise.
+ (neon_vcge<mode>): Likewise.
+ (neon_vcgeu<mode>): Likewise.
+ (neon_vcgt<mode>): Likewise.
+ (neon_vcgtu<mode>): Likewise.
+ (neon_vcle<mode>): Likewise.
+ (neon_vclt<mode>): Likewise.
+ (neon_vcage<mode>): Likewise.
+ (neon_vcagt<mode>): Likewise.
+ (neon_vtst<mode>): Likewise.
+ (neon_vabd<mode>): Likewise.
+ (neon_vabdl<mode>): Likewise.
+ (neon_vaba<mode>): Likewise.
+ (neon_vabal<mode>): Likewise.
+ (neon_vmax<mode>): Likewise.
+ (neon_vmin<mode>): Likewise.
+ (neon_vpaddl<mode>): Likewise.
+ (neon_vpadal<mode>): Likewise.
+ (neon_vpmax<mode>): Likewise.
+ (neon_vpmin<mode>): Likewise.
+ (neon_vrecps<mode>): Likewise.
+ (neon_vrsqrts<mode>): Likewise.
+ (neon_vqabs<mode>): Likewise.
+ (neon_vqneg<mode>): Likewise.
+ (neon_vcls<mode>): Likewise.
+ (clz<mode>2): Likewise.
+ (popcount<mode>2): Likewise.
+ (neon_vrecpe<mode>): Likewise.
+ (neon_vrsqrte<mode>): Likewise.
+ (neon_vget_lane<mode>_sext_internal): Likewise.
+ (neon_vget_lane<mode>_zext_internal): Likewise.
+ (neon_vdup_n<mode>): Likewise.
+ (neon_vdup_n<mode>): Likewise.
+ (neon_vdup_nv2di): Likewise.
+ (neon_vdup_lane<mode>_interal): Likewise.
+ (*neon_vswp<mode>): Likewise.
+ (neon_vcombine<mode>): Likewise.
+ (float<mode><V_cvtto>2): Likewise.
+ (floatuns<mode><V_cvtto>2): Likewise.
+ (fix_trunc<mode><V_cvtto>2): Likewise.
+ (fixuns_trunc<mode><V_cvtto>2
+ (neon_vcvt<mode>): Likewise.
+ (neon_vcvt<mode>): Likewise.
+ (neon_vcvtv4sfv4hf): Likewise.
+ (neon_vcvtv4hfv4sf): Likewise.
+ (neon_vcvt_n<mode>): Likewise.
+ (neon_vcvt_n<mode>): Likewise.
+ (neon_vmovn<mode>): Likewise.
+ (neon_vqmovn<mode>): Likewise.
+ (neon_vqmovun<mode>): Likewise.
+ (neon_vmovl<mode>): Likewise.
+ (neon_vmul_lane<mode>): Likewise.
+ (neon_vmul_lane<mode>): Likewise.
+ (neon_vmull_lane<mode>): Likewise.
+ (neon_vqdmull_lane<mode>): Likewise.
+ (neon_vqdmulh_lane<mode>): Likewise.
+ (neon_vqdmulh_lane<mode>): Likewise.
+ (neon_vmla_lane<mode>): Likewise.
+ (neon_vmla_lane<mode>): Likewise.
+ (neon_vmlal_lane<mode>): Likewise.
+ (neon_vqdmlal_lane<mode>): Likewise.
+ (neon_vmls_lane<mode>): Likewise.
+ (neon_vmls_lane<mode>): Likewise.
+ (neon_vmlsl_lane<mode>): Likewise.
+ (neon_vqdmlsl_lane<mode>): Likewise.
+ (neon_vext<mode>): Likewise.
+ (neon_vrev64<mode>): Likewise.
+ (neon_vrev32<mode>): Likewise.
+ (neon_vrev16<mode>): Likewise.
+ (neon_vbsl<mode>_internal): Likewise.
+ (neon_vshl<mode>): Likewise.
+ (neon_vqshl<mode>): Likewise.
+ (neon_vshr_n<mode>): Likewise.
+ (neon_vshrn_n<mode>): Likewise.
+ (neon_vqshrn_n<mode>): Likewise.
+ (neon_vqshrun_n<mode>): Likewise.
+ (neon_vshl_n<mode>): Likewise.
+ (neon_vqshl_n<mode>): Likewise.
+ (neon_vqshlu_n<mode>): Likewise.
+ (neon_vshll_n<mode>): Likewise.
+ (neon_vsra_n<mode>): Likewise.
+ (neon_vsri_n<mode>): Likewise.
+ (neon_vsli_n<mode>): Likewise.
+ (neon_vtbl1v8qi): Likewise.
+ (neon_vtbl2v8qi): Likewise.
+ (neon_vtbl3v8qi): Likewise.
+ (neon_vtbl4v8qi): Likewise.
+ (neon_vtbl1v16qi): Likewise.
+ (neon_vtbl2v16qi): Likewise.
+ (neon_vcombinev16qi): Likewise.
+ (neon_vtbx1v8qi): Likewise.
+ (neon_vtbx2v8qi): Likewise.
+ (neon_vtbx3v8qi): Likewise.
+ (neon_vtbx4v8qi): Likewise.
+ (*neon_vtrn<mode>_insn): Likewise.
+ (*neon_vzip<mode>_insn): Likewise.
+ (*neon_vuzp<mode>_insn): Likewise.
+ (neon_vld1<mode>): Likewise.
+ (neon_vld1_lane<mode>): Likewise.
+ (neon_vld1_lane<mode>): Likewise.
+ (neon_vld1_dup<mode>): Likewise.
+ (neon_vld1_dup<mode>): Likewise.
+ (neon_vld1_dupv2di): Likewise.
+ (neon_vst1<mode>): Likewise.
+ (neon_vst1_lane<mode>): Likewise.
+ (neon_vst1_lane<mode>): Likewise.
+ (neon_vld2<mode>): Likewise.
+ (neon_vld2<mode>): Likewise.
+ (neon_vld2_lane<mode>): Likewise.
+ (neon_vld2_lane<mode>): Likewise.
+ (neon_vld2_dup<mode>): Likewise.
+ (neon_vst2<mode>): Likewise.
+ (neon_vst2<mode>): Likewise.
+ (neon_vst2_lane<mode>): Likewise.
+ (neon_vst2_lane<mode>): Likewise.
+ (neon_vld3<mode>): Likewise.
+ (neon_vld3qa<mode>): Likewise.
+ (neon_vld3qb<mode>): Likewise.
+ (neon_vld3_lane<mode>): Likewise.
+ (neon_vld3_lane<mode>): Likewise.
+ (neon_vld3_dup<mode>): Likewise.
+ (neon_vst3<mode>): Likewise.
+ (neon_vst3qa<mode>): Likewise.
+ (neon_vst3qb<mode>): Likewise.
+ (neon_vst3_lane<mode>): Likewise.
+ (neon_vst3_lane<mode>): Likewise.
+ (neon_vld4<mode>): Likewise.
+ (neon_vld4qa<mode>): Likewise.
+ (neon_vld4qb<mode>): Likewise.
+ (neon_vld4_lane<mode>): Likewise.
+ (neon_vld4_lane<mode>): Likewise.
+ (neon_vld4_dup<mode>): Likewise.
+ (neon_vst4<mode>): Likewise.
+ (neon_vst4qa<mode>): Likewise.
+ (neon_vst4qb<mode>): Likewise.
+ (neon_vst4_lane<mode>): Likewise.
+ (neon_vst4_lane<mode>): Likewise.
+ (neon_vec_unpack<US>_lo_<mode>): Likewise.
+ (neon_vec_unpack<US>_hi_<mode>): Likewise.
+ (neon_vec_<US>mult_lo_<mode>): Likewise.
+ (neon_vec_<US>mult_hi_<mode>): Likewise.
+ (neon_vec_<US>shiftl_<mode>): Likewise.
+ (neon_unpack<US>_<mode>): Likewise.
+ (neon_vec_<US>mult_<mode>): Likewise.
+ (vec_pack_trunc_<mode>): Likewise.
+ (neon_vec_pack_trunc_<mode>): Likewise.
+ (neon_vabd<mode>_2): Likewise.
+ (neon_vabd<mode>_3): Likewise.
+
+2013-10-15 James Greenhalgh <james.greenhalgh@arm.com>
+
+ * config/aarch64/aarch64.md (movtf_aarch64): Update type attribute.
+ (load_pair): Update type attribute.
+ (store_pair): Update type attribute.
+ * config/aarch64/iterators.md (q): New.
+
+2013-10-15 James Greenhalgh <james.greenhalgh@arm.com>
+
+ * config/arm/types.md: Add new types for Neon insns.
+
+2013-10-15 Alexander Ivchenko <alexander.ivchenko@intel.com>
+ Maxim Kuznetsov <maxim.kuznetsov@intel.com>
+ Sergey Lega <sergey.s.lega@intel.com>
+ Anna Tikhonova <anna.tikhonova@intel.com>
+ Ilya Tocar <ilya.tocar@intel.com>
+ Andrey Turetskiy <andrey.turetskiy@intel.com>
+ Ilya Verbin <ilya.verbin@intel.com>
+ Kirill Yukhin <kirill.yukhin@intel.com>
+ Michael Zolotukhin <michael.v.zolotukhin@intel.com>
+
+ * config/i386/sse.md (unspec): Add UNSPEC_RCP14, UNSPEC_RSQRT14,
+ UNSPEC_FIXUPIMM, UNSPEC_SCALEF, UNSPEC_GETEXP, UNSPEC_GETMANT,
+ UNSPEC_EXP2, UNSPEC_RCP28, UNSPEC_RSQRT28.
+ (rcp14<mode>): New.
+ (srcp14<mode>): Ditto.
+ (rsqrt14<mode>): Ditto.
+ (rsqrt14<mode>): Ditto.
+ (avx512f_vmscalef<mode>): Ditto.
+ (avx512f_scalef<mode>): Ditto.
+ (avx512f_getexp<mode>): Ditto.
+ (avx512f_sgetexp<mode>): Ditto.
+ (avx512f_fixupimm<mode>): Ditto.
+ (avx512f_sfixupimm<mode>): Ditto.
+ (avx512f_rndscale<mode>): Ditto.
+ (*avx512er_exp2<mode>): Ditto.
+ (*avx512er_rcp28<mode>): Ditto.
+ (avx512er_rsqrt28<mode>): Ditto.
+ (avx512f_getmant<mode>): Ditto.
+ (avx512f_getmant<mode>): Ditto.
+ (avx512f_rndscale<mode>): Fix formatting.
+
+2013-10-15 Martin Jambor <mjambor@suse.cz>
+
+ * ipa-utils.h (ipa_edge_within_scc): Declare.
+ * ipa-cp.c (edge_within_scc): Moved...
+ * ipa-utils.c (ipa_edge_within_scc): ...here. Updated all callers.
+
+2013-10-15 Alexander Ivchenko <alexander.ivchenko@intel.com>
+ Maxim Kuznetsov <maxim.kuznetsov@intel.com>
+ Sergey Lega <sergey.s.lega@intel.com>
+ Anna Tikhonova <anna.tikhonova@intel.com>
+ Ilya Tocar <ilya.tocar@intel.com>
+ Andrey Turetskiy <andrey.turetskiy@intel.com>
+ Ilya Verbin <ilya.verbin@intel.com>
+ Kirill Yukhin <kirill.yukhin@intel.com>
+ Michael Zolotukhin <michael.v.zolotukhin@intel.com>
+
+ * config/i386/predicates.md (const_8_to_15_operand): New.
+ (const_16_to_31_operand): Ditto.
+ * config/i386/sse.md (V8FI): New.
+ (V16FI): Ditto.
+ (reduc_splus_v8df): Ditto.
+ (reduc_splus_v16sf): Ditto.
+ (avx512f_vextract<shuffletype>32x4_1): Ditto.
+ (vec_extract_hi_<mode>): Ditto.
+ (avx512f_vinsert<shuffletype>32x4_1): Ditto.
+ (vec_set_lo_<mode>): Ditto.
+ (vec_set_hi_<mode>): Ditto.
+ (avx512f_shuf_<shuffletype>64x2_1): Ditto.
+ (avx512f_shuf_<shuffletype>32x4_1): Ditto.
+ (avx512f_pshufd_1): Ditto.
+ (avx512f_broadcast<mode>): Ditto.
+ (avx512f_broadcast<mode>): Ditto.
+ (define_split): Split vec_extract_lo into move.
+ (ssequartermode): Ditto.
+ (ssedoublemode): Extened with wider modes.
+ (vec_extract_lo_<mode>): Ditto.
+
+2013-10-15 Alexander Ivchenko <alexander.ivchenko@intel.com>
+ Maxim Kuznetsov <maxim.kuznetsov@intel.com>
+ Sergey Lega <sergey.s.lega@intel.com>
+ Anna Tikhonova <anna.tikhonova@intel.com>
+ Ilya Tocar <ilya.tocar@intel.com>
+ Andrey Turetskiy <andrey.turetskiy@intel.com>
+ Ilya Verbin <ilya.verbin@intel.com>
+ Kirill Yukhin <kirill.yukhin@intel.com>
+ Michael Zolotukhin <michael.v.zolotukhin@intel.com>
+
+ * config/i386/predicates.md (register_or_constm1_operand): New.
+ * config/i386/sse.md (unspec): Add UNSPEC_UNSIGNED_PCMP, UNSPEC_TESTM,
+ UNSPEC_TESTNM, UNSPEC_VTERNLOG, UNSPEC_ALIGN, UNSPEC_CONFLICT,
+ UNSPEC_MASKED_EQ, UNSPEC_MASKED_GT, UNSPEC_GATHER_PREFETCH,
+ UNSPEC_SCATTER_PREFETCH
+ (VI48_512): New.
+ (avx512f_ucmp<mode>3): Ditto.
+ (avx512f_vternlog<mode>): Ditto.
+ (avx512f_align<mode>): Ditto.
+ (<shift_insn><mode>3): Ditto.
+ (avx512f_<rotate>v<mode>): Ditto.
+ (avx512f_<rotate><mode>): Ditto.
+ (avx512f_eq<mode>3): Ditto.
+ (avx512f_eq<mode>3_1): Ditto.
+ (avx512f_gt<mode>3): Ditto.
+ (avx512f_testm<mode>3): Ditto.
+ (avx512f_testnm<mode>3): Ditto.
+ (avx512pf_gatherpf<mode>): Ditto.
+ (*avx512pf_gatherpf<mode>_mask): Ditto.
+ (*avx512pf_gatherpf<mode>): Ditto.
+ (avx512pf_scatterpf<mode>): Ditto.
+ (*avx512pf_scatterpf<mode>_mask): Ditto.
+ (*avx512pf_scatterpf<mode>): Ditto.
+ (avx512f_vec_dup_gpr<mode>): Ditto.
+ (clz<mode>2): Ditto.
+ (conflict<mode>): Ditto.
+ (REDUC_SMINMAX_MODE): Extened with wider modes.
+ (reduc_<code>_<mode>): Ditto.
+ (vlshr<mode>3): Ditto.
+ (vashl<mode>3): Ditto.
+
+2013-10-15 Alexander Ivchenko <alexander.ivchenko@intel.com>
+ Maxim Kuznetsov <maxim.kuznetsov@intel.com>
+ Sergey Lega <sergey.s.lega@intel.com>
+ Anna Tikhonova <anna.tikhonova@intel.com>
+ Ilya Tocar <ilya.tocar@intel.com>
+ Andrey Turetskiy <andrey.turetskiy@intel.com>
+ Ilya Verbin <ilya.verbin@intel.com>
+ Kirill Yukhin <kirill.yukhin@intel.com>
+ Michael Zolotukhin <michael.v.zolotukhin@intel.com>
+
+ * config/i386/sse.md (unspec): Added UNSPEC_VPERMI2, UNSPEC_VPERMT2,
+ UNSPEC_SCATTER.
+ (VI48F_512): New.
+ (avx512fmaskmode): Ditto.
+ (bcstscalarsuff): Ditto.
+ (avx512f_blendm<mode>): Ditto.
+ (cmp_imm_predicate): Ditto.
+ (avx512f_cmp<mode>3): Ditto.
+ (avx512f_vec_dup<mode>): Ditto.
+ (avx512f_vec_dup_mem<mode>): Ditto.
+ (avx512f_vpermi2var<mode>3): Ditto.
+ (avx512f_vpermt2var<mode>3): Ditto.
+ (vec_init<mode>): Ditto.
+ (avx512f_gathersi<mode>): Ditto.
+ (*avx512f_gathersi<mode>): Ditto.
+ (*avx512f_gathersi<mode>_2): Ditto.
+ (avx512f_gatherdi<mode>): Ditto.
+ (*avx512f_gatherdi<mode>): Ditto.
+ (*avx512f_gatherdi<mode>_2): Ditto.
+ (avx512f_scattersi<mode>): Ditto.
+ (*avx512f_scattersi<mode>): Ditto.
+ (avx512f_scatterdi<mode>): Ditto.
+ (*avx512f_scatterdi<mode>): Ditto.
+ (sseintprefix): Extened with wider modes.
+ (VEC_GATHER_IDXSI): Ditto.
+ (VEC_GATHER_IDXDI): Ditto.
+ (VEC_GATHER_SRCDI): Ditto.
+
+2013-10-15 Matthew Gretton-Dann <matthew.gretton-dann@arm.com>
+ Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
+
+ * config/arm/t-aprofile: New file.
+ * config.gcc: Handle --with-multilib-list option.
+
+2013-10-15 Bernd Schmidt <bernds@codesourcery.com>
+
+ * reload1.c (reloads_unique_chain_p): Ensure that r1 is
+ the input for r2.
+
+2013-10-15 Richard Biener <rguenther@suse.de>
+
+ * tree-loop-distribution.c (build_empty_rdg): Inline into
+ single user.
+ (rdg_flag_vertex): Inline into single user.
+ (rdg_flag_vertex_and_dependent): Likewise.
+ (build_rdg_partition_for_vertex): Remove processed bitmap.
+ (rdg_build_partitions): Simplify.
+
+2013-10-15 Richard Biener <rguenther@suse.de>
+
+ * tree-ssa-forwprop.c (forward_propagate_addr_expr_1):
+ Restructure forwarding through conversions and copies to
+ avoid performing copy-propagation the wrong way. Adjust
+ recursion invocations.
+ (forward_propagate_addr_expr): Add argument stating if we
+ are recursing from a single-use.
+ (ssa_forward_propagate_and_combine): Adjust.
+
+2013-10-14 David Malcolm <dmalcolm@redhat.com>
+
+ * dumpfile.h (gcc::dump_manager): New class, to hold state
+ relating to dumpfile management.
+ (get_dump_file_name): Remove in favor of method of dump_manager.
+ (dump_initialized_p): Likewise.
+ (dump_start): Likewise.
+ (dump_finish): Likewise.
+ (dump_switch_p): Likewise.
+ (dump_register): Likewise.
+ (get_dump_file_info): Likewise.
+ * context.c (gcc::context::context): Construct the dump_manager
+ instance.
+ * context.h (gcc::context::get_dumps): New.
+ (gcc::context::m_dumps): New.
+ * coverage.c (coverage_init): Port to dump_manager API.
+ * dumpfile.c (extra_dump_files): Convert to field of gcc::dump_manager.
+ (extra_dump_files_in_use): Likewise.
+ (extra_dump_files_alloced): Likewise.
+ (gcc::dump_manager::dump_manager): New.
+ (dump_register): Convert to...
+ (gcc::dump_manager::dump_register): ...method, replacing
+ function-static next_dump with m_next_dump field.
+ (get_dump_file_info): Convert to...
+ (gcc::dump_manager::get_dump_file_info): ...method.
+ (get_dump_file_name): Convert to...
+ (gcc::dump_manager::get_dump_file_name): ...method.
+ (dump_start): Convert to...
+ (gcc::dump_manager::dump_start): ...method.
+ (dump_finish): Convert to...
+ (gcc::dump_manager::dump_finish): ...method.
+ (dump_begin): Replace body with...
+ (gcc::dump_manager::dump_begin): ...new method.
+ (dump_phase_enabled_p): Convert to...
+ (gcc::dump_manager::dump_phase_enabled_p): ...method.
+ (dump_phase_enabled_p): Convert to...
+ (gcc::dump_manager::dump_phase_enabled_p): ...method.
+ (dump_initialized_p): Convert to...
+ (gcc::dump_manager::dump_initialized_p): ...method.
+ (dump_flag_name): Replace body with...
+ (gcc::dump_manager::dump_flag_name): ...new method.
+ (dump_enable_all): Convert to...
+ (gcc::dump_manager::dump_enable_all): ...new method.
+ (opt_info_enable_passes): Convert to...
+ (gcc::dump_manager::opt_info_enable_passes): ...new method.
+ (dump_switch_p_1): Convert to...
+ (gcc::dump_manager::dump_switch_p_1): ...new method.
+ (dump_switch_p): Convert to...
+ (gcc::dump_manager::dump_switch_p): ...new method.
+ (opt_info_switch_p): Port to dump_manager API.
+ (enable_rtl_dump_file): Likewise.
+ * opts-global.c (handle_common_deferred_options): Port to new
+ dump_manager API.
+ * passes.c (pass_manager::finish_optimization_passes): Likewise.
+ (pass_manager::register_one_dump_file): Likewise.
+ (pass_manager::register_pass): Likewise.
+ (pass_init_dump_file): Likewise.
+ (pass_fini_dump_file): Likewise.
+ * statistics.c (statistics_early_init): Likewise.
+
+2013-10-14 Richard Biener <rguenther@suse.de>
+
+ * gimple.c (gimple_canonical_types, canonical_type_hash_cache,
+ iterative_hash_canonical_type, gimple_canonical_type_hash,
+ gimple_canonical_types_compatible_p, gimple_canonical_type_eq,
+ gimple_register_canonical_type, print_gimple_types_stats,
+ free_gimple_type_tables): Move to lto/lto.c
+ (gt-gimple.h): Do not include.
+ * gimple.h (gimple_register_canonical_type,
+ print_gimple_types_stats, free_gimple_type_tables): Remove.
+ * Makefile.in (GTFILES): Remove gimple.c.
+
+2013-10-14 Travis Snoozy <quandary@remstate.com>
+
+ PR target/58716
+ * config/msp430/msp430.c (msp430_option_override): Correct thinko
+ scanning for msp430x targets.
+
+2013-10-14 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR bootstrap/58509
+ * config/sparc/sparc-protos.h (widen_mem_for_ldd_peep): Declare.
+ (registers_ok_for_ldd_peep): Move around.
+ * config/sparc/sparc.c (widen_mem_for_ldd_peep): New.
+ * config/sparc/sparc.md (widening peepholes): Use it.
+
+2013-10-14 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/58712
+ PR middle-end/55358
+ * gimple.c (iterative_hash_canonical_type): Make sure to
+ record the hash into the correct hashtable slot.
+
+2013-10-13 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR rtl-optimization/58662
+ * combine.c (try_combine): Take into account death nodes on I2 when
+ splitting a PARALLEL of two independent SETs. Fix dump message.
+
+2013-10-12 Oleg Endo <olegendo@gcc.gnu.org>
+
+ PR target/51244
+ * config/sh/sh_treg_combine.cc: New SH specific RTL pass.
+ * config.gcc (SH extra_objs): Add sh_ifcvt.o.
+ * config/sh/t-sh (sh_treg_combine.o): New entry.
+ * config/sh/sh.c (sh_fixed_condition_code_regs): New function that
+ implements the target hook TARGET_FIXED_CONDITION_CODE_REGS.
+ (register_sh_passes): New function. Register sh_treg_combine pass.
+ (sh_option_override): Invoke it.
+ (sh_canonicalize_comparison): Handle op0_preserve_value.
+ * sh.md (*cbranch_t"): Do not try to optimize missed test and branch
+ opportunities. Canonicalize branch condition.
+ (nott): Allow only if pseudos can be created for non-SH2A.
+
+2013-10-12 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/58690
+ * config/i386/i386.c (ix86_copy_addr_to_reg): New function.
+ (ix86_expand_movmem): Replace copy_addr_to_reg with
+ ix86_copy_addr_to_reg.
+ (ix86_expand_setmem): Likewise.
+
+2013-10-12 Alexander Monakov <amonakov@ispras.ru>
+
+ * config/i386/i386.c (ix86_expand_sse_compare_and_jump): Use mode
+ provided by ix86_fp_compare_mode instead of CCFPUmode.
+
+2013-10-12 James Greenhalgh <james.greenhalgh@arm.com>
+
+ * config/aarch64/arm_neon.h
+ (vtbx<1,3>_<psu>8): Fix register constriants.
+
+2013-10-11 Jeff Law <law@redhat.com>
+
+ PR tree-optimization/58640
+ * tree-ssa-threadupdate.c (mark_threaded_blocks): Truncate jump
+ threading paths that cross over two loop entry points.
+
+2013-10-11 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * config/rs6000/vsx.md (*vsx_le_perm_load_v2di): Generalize to
+ handle vector float as well.
+ (*vsx_le_perm_load_v4si): Likewise.
+ (*vsx_le_perm_store_v2di): Likewise.
+ (*vsx_le_perm_store_v4si): Likewise.
+
+2013-10-11 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * config/rs6000/vector.md (vec_realign_load<mode>): Generate vperm
+ directly to circumvent subtract from splat{31} workaround.
+ * config/rs6000/rs6000-protos.h (altivec_expand_vec_perm_le): New
+ prototype.
+ * config/rs6000/rs6000.c (altivec_expand_vec_perm_le): New.
+ * config/rs6000/altivec.md (define_c_enum "unspec"): Add
+ UNSPEC_VPERM_X and UNSPEC_VPERM_UNS_X.
+ (altivec_vperm_<mode>): Convert to define_insn_and_split to
+ separate big and little endian logic.
+ (*altivec_vperm_<mode>_internal): New define_insn.
+ (altivec_vperm_<mode>_uns): Convert to define_insn_and_split to
+ separate big and little endian logic.
+ (*altivec_vperm_<mode>_uns_internal): New define_insn.
+ (vec_permv16qi): Add little endian logic.
+
+2013-10-11 Marc Glisse <marc.glisse@inria.fr>
+
+ * doc/extend.texi (returns_nonnull): Remove arguments.
+
+2013-10-11 Alexander Ivchenko <alexander.ivchenko@intel.com>
+ Maxim Kuznetsov <maxim.kuznetsov@intel.com>
+ Sergey Lega <sergey.s.lega@intel.com>
+ Anna Tikhonova <anna.tikhonova@intel.com>
+ Ilya Tocar <ilya.tocar@intel.com>
+ Andrey Turetskiy <andrey.turetskiy@intel.com>
+ Ilya Verbin <ilya.verbin@intel.com>
+ Kirill Yukhin <kirill.yukhin@intel.com>
+ Michael Zolotukhin <michael.v.zolotukhin@intel.com>
+
+ * config/i386/sse.md (VI48F_256_512): New.
+ (avx2_permvar<mode>): Change to ...
+ (<avx2_avx512f>_permvar<mode>): This.
+
+2013-10-11 Alexander Ivchenko <alexander.ivchenko@intel.com>
+ Maxim Kuznetsov <maxim.kuznetsov@intel.com>
+ Sergey Lega <sergey.s.lega@intel.com>
+ Anna Tikhonova <anna.tikhonova@intel.com>
+ Ilya Tocar <ilya.tocar@intel.com>
+ Andrey Turetskiy <andrey.turetskiy@intel.com>
+ Ilya Verbin <ilya.verbin@intel.com>
+ Kirill Yukhin <kirill.yukhin@intel.com>
+ Michael Zolotukhin <michael.v.zolotukhin@intel.com>
+
+ * config/i386/i386.c (bdesc_args): Change corresponding pattern for
+ __builtin_ia32_cvtps2dq, __builtin_ia32_cvtps2dq256.
+ * config/i386/sse.md (VI4_AVX): New.
+ (sf2simodelower): Ditto.
+ (sse2_cvtps2dq): Change to ...
+ (<sse2_avx_avx512f>_fix_notrunc<sf2simodelower><mode>): This.
+
+2013-10-11 Alexander Ivchenko <alexander.ivchenko@intel.com>
+ Maxim Kuznetsov <maxim.kuznetsov@intel.com>
+ Sergey Lega <sergey.s.lega@intel.com>
+ Anna Tikhonova <anna.tikhonova@intel.com>
+ Ilya Tocar <ilya.tocar@intel.com>
+ Andrey Turetskiy <andrey.turetskiy@intel.com>
+ Ilya Verbin <ilya.verbin@intel.com>
+ Kirill Yukhin <kirill.yukhin@intel.com>
+ Michael Zolotukhin <michael.v.zolotukhin@intel.com>
+
+ * config/i386/sse.md (V_512): New.
+ (VI_512): Ditto.
+ (vcond<V_512:mode><VF_512:mode>): Ditto.
+ (vcond<V_512:mode><VI_512:mode>): Ditto.
+ (vcondu<V_512:mode><VI_512:mode>): Ditto.
+
+2013-10-11 Alexander Ivchenko <alexander.ivchenko@intel.com>
+ Maxim Kuznetsov <maxim.kuznetsov@intel.com>
+ Sergey Lega <sergey.s.lega@intel.com>
+ Anna Tikhonova <anna.tikhonova@intel.com>
+ Ilya Tocar <ilya.tocar@intel.com>
+ Andrey Turetskiy <andrey.turetskiy@intel.com>
+ Ilya Verbin <ilya.verbin@intel.com>
+ Kirill Yukhin <kirill.yukhin@intel.com>
+ Michael Zolotukhin <michael.v.zolotukhin@intel.com>
+
+ * config/i386/i386.c (ix86_rtx_costs): Enable fma for TARGET_AVX512F.
+ * config/i386/sse.md (FMAMODEM): Changed modes and conditions.
+ (FMAMODE): Ditto.
+ (fma<mode>4): Removed condition.
+ (fms<mode>4): Ditto.
+ (fnma<mode>4): Ditto.
+ (fnms<mode>4): Ditto.
+ (fma4i_fmadd_<mode>): Ditto.
+ (*fma_fmadd_<mode>): Ditto.
+ (*fma_fmsub_<mode>): Ditto.
+ (*fma_fnmadd_<mode>): Ditto.
+ (*fma_fnmsub_<mode>): Ditto.
+ (fmaddsub_<mode>): Allow for TARGET_AVX512F.
+ (*fma_fmaddsub_<mode>): Ditto.
+ (*fma_fmsubadd_<mode>): Ditto.
+ (*fmai_fmadd_<mode>): Ditto.
+ (*fmai_fmsub_<mode>): Ditto.
+ (*fmai_fnmadd_<mode>): Ditto.
+ (*fmai_fnmsub_<mode>): Ditto.
+
+2013-10-11 Alexander Ivchenko <alexander.ivchenko@intel.com>
+ Maxim Kuznetsov <maxim.kuznetsov@intel.com>
+ Sergey Lega <sergey.s.lega@intel.com>
+ Anna Tikhonova <anna.tikhonova@intel.com>
+ Ilya Tocar <ilya.tocar@intel.com>
+ Andrey Turetskiy <andrey.turetskiy@intel.com>
+ Ilya Verbin <ilya.verbin@intel.com>
+ Kirill Yukhin <kirill.yukhin@intel.com>
+ Michael Zolotukhin <michael.v.zolotukhin@intel.com>
+
+ * config/i386/sse.md (VI248_AVX2_8_AVX512F): New.
+ (VI124_256): Changed to ...
+ (VI124_256_48_512): This.
+ (ssepackmode): Extended with wider modes.
+ (<code><mode>3): Changed iterator.
+ (*avx2_<code><mode>3): Ditto.
+ (vec_pack_trunc_<mode>): Ditto.
+
+2013-10-11 Alexander Ivchenko <alexander.ivchenko@intel.com>
+ Maxim Kuznetsov <maxim.kuznetsov@intel.com>
+ Sergey Lega <sergey.s.lega@intel.com>
+ Anna Tikhonova <anna.tikhonova@intel.com>
+ Ilya Tocar <ilya.tocar@intel.com>
+ Andrey Turetskiy <andrey.turetskiy@intel.com>
+ Ilya Verbin <ilya.verbin@intel.com>
+ Kirill Yukhin <kirill.yukhin@intel.com>
+ Michael Zolotukhin <michael.v.zolotukhin@intel.com>
+
+ * config/i386/sse.md (VI124_AVX2_48_AVX512F): New.
+ (VI8F_256_512): Ditto.
+ (abs<mode>2): Changed iterator.
+ (avx2_perm<mode>): Changed to ...
+ (<avx2_avx512f>_perm<mode>): This.
+ (avx2_perm<mode>_1): Changed to ...
+ (<avx2_avx512f>_perm<mode>_1): This.
+
+2013-10-11 Alexander Ivchenko <alexander.ivchenko@intel.com>
+ Maxim Kuznetsov <maxim.kuznetsov@intel.com>
+ Sergey Lega <sergey.s.lega@intel.com>
+ Anna Tikhonova <anna.tikhonova@intel.com>
+ Ilya Tocar <ilya.tocar@intel.com>
+ Andrey Turetskiy <andrey.turetskiy@intel.com>
+ Ilya Verbin <ilya.verbin@intel.com>
+ Kirill Yukhin <kirill.yukhin@intel.com>
+ Michael Zolotukhin <michael.v.zolotukhin@intel.com>
+
+ * config/i386/sse.md (VI48_AVX512F): New.
+ (VI48_AVX2): Changed to ...
+ (VI48_AVX2_48_AVX512F): This.
+ (avx2_ashrv<mode>): Changed to ...
+ (<avx2_avx512f>_ashrv<mode>): This.
+ (avx2_<shift_insn>v<mode>): Changed to ...
+ (<avx2_avx512f>_<shift_insn>v<mode>): This.
+
+2013-10-11 Alexander Ivchenko <alexander.ivchenko@intel.com>
+ Maxim Kuznetsov <maxim.kuznetsov@intel.com>
+ Sergey Lega <sergey.s.lega@intel.com>
+ Anna Tikhonova <anna.tikhonova@intel.com>
+ Ilya Tocar <ilya.tocar@intel.com>
+ Andrey Turetskiy <andrey.turetskiy@intel.com>
+ Ilya Verbin <ilya.verbin@intel.com>
+ Kirill Yukhin <kirill.yukhin@intel.com>
+ Michael Zolotukhin <michael.v.zolotukhin@intel.com>
+
+ * config/i386/sse.md (VI4_AVX512F): New.
+ (VI8_AVX2_AVX512F): Ditto.
+ (mul<mode>3): Extended with wider modes.
+ (*<sse4_1_avx2>_mul<mode>3): Ditto.
+ (mul<mode>3): Ditto.
+ (vec_widen_<s>mult_odd_<mode>): Ditto.
+
+2013-10-11 Alexander Ivchenko <alexander.ivchenko@intel.com>
+ Maxim Kuznetsov <maxim.kuznetsov@intel.com>
+ Sergey Lega <sergey.s.lega@intel.com>
+ Anna Tikhonova <anna.tikhonova@intel.com>
+ Ilya Tocar <ilya.tocar@intel.com>
+ Andrey Turetskiy <andrey.turetskiy@intel.com>
+ Ilya Verbin <ilya.verbin@intel.com>
+ Kirill Yukhin <kirill.yukhin@intel.com>
+ Michael Zolotukhin <michael.v.zolotukhin@intel.com>
+
+ * config/i386/sse.md (VI2_AVX512F): New.
+ (VI124_AVX512F): Ditto.
+ (sseunpackmode): Extended with wider modes.
+ (sseunpackfltmode): Ditto.
+ (vec_unpacks_float_hi_<mode>): Ditto.
+ (vec_unpacks_float_lo_<mode>): Ditto.
+ (vec_unpacku_float_hi_<mode>): Ditto.
+ (vec_unpacku_float_lo_<mode>): Ditto.
+ (vec_unpacks_lo_<mode>): Ditto.
+ (vec_unpacks_hi_<mode>): Ditto.
+ (vec_unpacku_lo_<mode>): Ditto.
+ (vec_unpacku_hi_<mode>): Ditto.
+
+2013-10-11 Alexander Ivchenko <alexander.ivchenko@intel.com>
+ Maxim Kuznetsov <maxim.kuznetsov@intel.com>
+ Sergey Lega <sergey.s.lega@intel.com>
+ Anna Tikhonova <anna.tikhonova@intel.com>
+ Ilya Tocar <ilya.tocar@intel.com>
+ Andrey Turetskiy <andrey.turetskiy@intel.com>
+ Ilya Verbin <ilya.verbin@intel.com>
+ Kirill Yukhin <kirill.yukhin@intel.com>
+ Michael Zolotukhin <michael.v.zolotukhin@intel.com>
+
+ * config/i386/i386.md (multdiv): New.
+ (multdiv_mnemonic): Ditto.
+ * config/i386/sse.md (<sse>_vmmul<mode>3): Changed to...
+ (<sse>_vm<multdiv_mnemonic><mode>3): This.
+ (<sse>_vmdiv<mode>3): Removed.
+
+2013-10-11 Alexander Ivchenko <alexander.ivchenko@intel.com>
+ Maxim Kuznetsov <maxim.kuznetsov@intel.com>
+ Sergey Lega <sergey.s.lega@intel.com>
+ Anna Tikhonova <anna.tikhonova@intel.com>
+ Ilya Tocar <ilya.tocar@intel.com>
+ Andrey Turetskiy <andrey.turetskiy@intel.com>
+ Ilya Verbin <ilya.verbin@intel.com>
+ Kirill Yukhin <kirill.yukhin@intel.com>
+ Michael Zolotukhin <michael.v.zolotukhin@intel.com>
+
+ * config/i386/sse.md (V): Extended with wider modes.
+ (VF2): Ditto.
+ (ssehalfvecmode): Ditto.
+ (i128): Ditto.
+ (ssepackfltmode): Ditto.
+ (avx_vec_concat<mode>): Ditto.
+ (V_256_512): New iterator.
+ (VF2_512_256): Ditto.
+ (si2dfmode): New attribute.
+ (si2dfmodelower): Ditto.
+ (sf2dfmode): Ditto.
+ (concat_tg_mode): Ditto.
+ (floatv4siv4df2): Changed to ...
+ (float<si2dfmodelower><mode>2): This.
+ (avx_cvtps2pd256): Changed to ...
+ (<sse2_avx_avx512f>_cvtps2pd<avxsizesuffix>): This.
+ (vec_pack_trunc_v4df): Changed to ...
+ (vec_pack_trunc_<mode>): This.
+ (avx_vpermil<mode>): Changed to ...
+ (<sse2_avx_avx512f>_vpermil<mode>): This.
+ (<fixsuffix>fix_truncv8dfv8si2): New.
+ (vec_pack_sfix_trunc_v8df): Ditto.
+ (avx512f_rndscale<mode>): Ditto.
+ (avx512f_roundpd512): Ditto.
+ (vec_pack_ufix_trunc_<mode>): Updated iterator.
+
+2013-10-11 Alexander Ivchenko <alexander.ivchenko@intel.com>
+ Maxim Kuznetsov <maxim.kuznetsov@intel.com>
+ Sergey Lega <sergey.s.lega@intel.com>
+ Anna Tikhonova <anna.tikhonova@intel.com>
+ Ilya Tocar <ilya.tocar@intel.com>
+ Andrey Turetskiy <andrey.turetskiy@intel.com>
+ Ilya Verbin <ilya.verbin@intel.com>
+ Kirill Yukhin <kirill.yukhin@intel.com>
+ Michael Zolotukhin <michael.v.zolotukhin@intel.com>
+
+ * config/i386/i386.md (any_fix): New iterator.
+ (fixsuffix): New attribute.
+ * config/i386/sse.md (VF1): Extened with wider modes.
+ (VI): Ditto.
+ (VI_AVX2): Ditto.
+ (VI8): Ditto.
+ (sseintvecmodelower): Ditto.
+ (ssescalarmode): Ditto.
+ (ssescalarnum): Ditto.
+ (VF1_128_256): New.
+ (ssexmmmode): Ditto.
+ (<fixsuffix>fix_truncv16sfv16si2): Ditto.
+ (<sse>_rcp<mode>2): Change iterator.
+ (rsqrt<mode>2): Ditto.
+ (<sse>_rsqrt<mode>2): Ditto.
+ (avx2_vec_dup<mode>): Ditto.
+ (<sse4_1>_round<ssemodesuffix>_sfix<avxsizesuffix>): Ditto.
+ (round<mode>2_sfix): Ditto.
+ (avx2_pbroadcast<mode>): Ditto.
+ (*andnot<mode>3): Handle XI mode.
+ (*<code><mode>3): Ditto.
+ (AVXTOSSEMODE): Removed.
+ (avx_vpermil<mode>): Changed to ...
+ (<sse2_avx_avx512f>_vpermil<mode>): This.
+
+2013-10-11 Alexander Ivchenko <alexander.ivchenko@intel.com>
+ Maxim Kuznetsov <maxim.kuznetsov@intel.com>
+ Sergey Lega <sergey.s.lega@intel.com>
+ Anna Tikhonova <anna.tikhonova@intel.com>
+ Ilya Tocar <ilya.tocar@intel.com>
+ Andrey Turetskiy <andrey.turetskiy@intel.com>
+ Ilya Verbin <ilya.verbin@intel.com>
+ Kirill Yukhin <kirill.yukhin@intel.com>
+ Michael Zolotukhin <michael.v.zolotukhin@intel.com>
+
+ * config/i386/sse.md (<sse2>_movnt<mode>): Update constraint to "v".
+ (<sse>_comi): Ditto.
+ (<sse>_ucomi): Ditto.
+ (sse_cvtss2siq_2): Ditto.
+ (sse2_cvtsd2si): Ditto.
+ (sse2_cvtsd2siq): Ditto.
+ (sse2_cvttsd2si): Ditto.
+ (sse2_cvttsd2siq): Ditto.
+ (<shift_insn><mode>3): Ditto.
+ (sse2_cvtsi2sdq): Update constraint and prefix.
+ (sse_cvtsi2ss): Update prefix.
+ (sse_cvtsi2ssq): Ditto.
+
+2013-10-11 Jakub Jelinek <jakub@redhat.com>
+
+ * tree-vrp.c (infer_nonnull_range): Use is_gimple_call,
+ ignore internal calls.
+
+2013-10-11 Richard Biener <rguenther@suse.de>
+
+ * tree-pretty-print.c (dump_generic_node): Allow to dump both (D)
+ and (ab) for SSA_NAMEs. Mark INTEGER_CSTs with (OVF) if
+ TREE_OVERFLOW is set.
+
+2013-10-11 Thomas Schwinge <thomas@codesourcery.com>
+
+ * tree.h (OMP_CLAUSE_CODE): Remove duplicate definition.
+
+ * gimple.c: GIMPLE statements have subcodes, not sub-codes.
+ * gimple.h: Likewise.
+
+ * doc/generic.texi (OpenMP): OMP_CLAUSE_* are subcodes, not sub-codes.
+
+ * doc/generic.texi (Adding new DECL node types): Explain *_CHECK
+ macros.
+
+ * doc/gimple.texi (is_gimple_omp): Move into the correct section.
+
+ * acinclude.m4 (gcc_GAS_FLAGS): Add more gcc_cv_as_flags overrides.
+ * configure: Regenerate.
+
+2013-10-11 Jakub Jelinek <jakub@redhat.com>
+
+ * tree-pretty-print.c (dump_omp_clause): Handle OMP_CLAUSE__LOOPTEMP_
+ and new OpenMP 4.0 clauses, handle UDR OMP_CLAUSE_REDUCTION,
+ formatting fixes, use pp_colon instead of pp_character (..., ':'),
+ similarly pp_right_paren.
+ (dump_generic_node): Handle OMP_DISTRIBUTE, OMP_TEAMS,
+ OMP_TARGET_DATA, OMP_TARGET, OMP_TARGET_UPDATE, OMP_TASKGROUP,
+ allow OMP_FOR_INIT to be NULL, handle OMP_ATOMIC_SEQ_CST.
+ * tree.c (omp_clause_num_ops, omp_clause_code_name): Add OpenMP 4.0
+ clauses.
+ (omp_declare_simd_clauses_equal,
+ omp_remove_redundant_declare_simd_attrs): New functions.
+ (attribute_value_equal): Use omp_declare_simd_clauses_equal.
+ (walk_tree_1): Handle new OpenMP 4.0 clauses.
+ * tree.h (OMP_LOOP_CHECK): Define.
+ (OMP_FOR_BODY, OMP_FOR_CLAUSES, OMP_FOR_INIT, OMP_FOR_COND,
+ OMP_FOR_INCR, OMP_FOR_PRE_BODY): Use it.
+ (OMP_TASKGROUP_BODY, OMP_TEAMS_BODY, OMP_TEAMS_CLAUSES,
+ OMP_TARGET_DATA_BODY, OMP_TARGET_DATA_CLAUSES, OMP_TARGET_BODY,
+ OMP_TARGET_CLAUSES, OMP_TARGET_UPDATE_CLAUSES, OMP_CLAUSE_SIZE,
+ OMP_ATOMIC_SEQ_CST, OMP_CLAUSE_DEPEND_KIND, OMP_CLAUSE_MAP_KIND,
+ OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION, OMP_CLAUSE_PROC_BIND_KIND,
+ OMP_CLAUSE_REDUCTION_OMP_ORIG_REF, OMP_CLAUSE_ALIGNED_ALIGNMENT,
+ OMP_CLAUSE_NUM_TEAMS_EXPR, OMP_CLAUSE_THREAD_LIMIT_EXPR,
+ OMP_CLAUSE_DEVICE_ID, OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR,
+ OMP_CLAUSE_SIMDLEN_EXPR): Define.
+ (OMP_CLAUSE_DECL): Change range up to OMP_CLAUSE__LOOPTEMP_.
+ (omp_remove_redundant_declare_simd_attrs): New prototype.
+ * gimple.def (GIMPLE_OMP_TASKGROUP, GIMPLE_OMP_TARGET,
+ GIMPLE_OMP_TEAMS): New codes.
+ (GIMPLE_OMP_RETURN): Use GSS_OMP_ATOMIC_STORE instead of GSS_BASE.
+ * omp-low.c (struct omp_context): Add cancel_label and cancellable
+ fields.
+ (target_nesting_level): New variable.
+ (extract_omp_for_data): Handle GF_OMP_FOR_KIND_DISTRIBUTE and
+ OMP_CLAUSE_DIST_SCHEDULE. Don't fallback to library implementation
+ for collapse > 1 static schedule unless ordered.
+ (get_ws_args_for): Add par_stmt argument. Handle combined loops.
+ (determine_parallel_type): Adjust get_ws_args_for caller.
+ (install_var_field): Handle mask & 4 for double indirection.
+ (scan_sharing_clauses): Ignore shared clause on teams construct.
+ Handle OMP_CLAUSE__LOOPTEMP_ and new OpenMP 4.0 clauses.
+ (create_omp_child_function): If inside target or declare target
+ constructs, set "omp declare target" attribute on the child function.
+ (find_combined_for): New function.
+ (scan_omp_parallel): Handle combined loops.
+ (scan_omp_target, scan_omp_teams): New functions.
+ (check_omp_nesting_restrictions): Check new OpenMP 4.0 nesting
+ restrictions and set ctx->cancellable for cancellable constructs.
+ (scan_omp_1_stmt): Call check_omp_nesting_restrictions also on
+ selected builtin calls. Handle GIMPLE_OMP_TASKGROUP,
+ GIMPLE_OMP_TARGET, GIMPLE_OMP_TEAMS.
+ (build_omp_barrier): Add lhs argument, return gimple rather than tree.
+ (omp_clause_aligned_alignment): New function.
+ (lower_rec_simd_input_clauses): Only call SET_DECL_VALUE_EXPR on decls.
+ (lower_rec_input_clauses): Add FD argument. Ignore shared clauses
+ on teams constructs. Handle user defined reductions and new
+ OpenMP 4.0 clauses.
+ (lower_reduction_clauses): Don't set placeholder to address of ref
+ if it has already the right type.
+ (lower_send_clauses): Handle OMP_CLAUSE__LOOPTEMP_.
+ (expand_parallel_call): Use the new non-_start suffixed builtins,
+ handle OMP_CLAUSE_PROC_BIND, don't call the outlined function
+ and GOMP_parallel_end after the call.
+ (expand_task_call): Handle OMP_CLAUSE_DEPEND.
+ (expand_omp_for_init_counts): Handle combined loops.
+ (expand_omp_for_init_vars): Add inner_stmt argument, handle combined
+ loops.
+ (expand_omp_for_generic): Likewise. Use GOMP_loop_end_cancel at the
+ end of cancellable loops.
+ (expand_omp_for_static_nochunk, expand_omp_for_static_chunk):
+ Likewise. Handle collapse > 1 loops.
+ (expand_omp_simd): Handle combined loops.
+ (expand_omp_for): Add inner_stmt argument, adjust callers of
+ expand_omp_for* functions, use expand_omp_for_static*chunk even
+ for collapse > 1 unless ordered.
+ (expand_omp_sections): Use GOMP_sections_end_cancel at the end
+ of cancellable sections.
+ (expand_omp_single): Remove need_barrier variable, just rely on
+ gimple_omp_return_nowait_p. Adjust build_omp_barrier caller.
+ (expand_omp_synch): Allow GIMPLE_OMP_TASKGROUP and GIMPLE_OMP_TEAMS.
+ (expand_omp_atomic_load, expand_omp_atomic_store,
+ expand_omp_atomic_fetch_op): Handle gimple_omp_atomic_seq_cst_p.
+ (expand_omp_target): New function.
+ (expand_omp): Handle combined loops. Handle GIMPLE_OMP_TASKGROUP,
+ GIMPLE_OMP_TEAMS, GIMPLE_OMP_TARGET.
+ (build_omp_regions_1): Immediately close region for
+ GF_OMP_TARGET_KIND_UPDATE.
+ (maybe_add_implicit_barrier_cancel): New function.
+ (lower_omp_sections): Adjust lower_rec_input_clauses caller. Handle
+ cancellation.
+ (lower_omp_single): Likewise. Add clobber after the barrier.
+ (lower_omp_taskgroup): New function.
+ (lower_omp_for): Handle combined loops. Adjust
+ lower_rec_input_clauses caller. Handle cancellation.
+ (lower_depend_clauses): New function.
+ (lower_omp_taskreg): Lower depend clauses. Adjust
+ lower_rec_input_clauses caller. Add clobber after the call. Handle
+ cancellation.
+ (lower_omp_target, lower_omp_teams): New functions.
+ (lower_omp_1): Handle cancellation. Handle GIMPLE_OMP_TASKGROUP,
+ GIMPLE_OMP_TARGET, GIMPLE_OMP_TEAMS and GOMP_barrier, GOMP_cancel
+ and GOMP_cancellation_point calls.
+ (lower_omp): Fold stmts inside of target region.
+ (diagnose_sb_1, diagnose_sb_2): Handle GIMPLE_OMP_TASKGROUP,
+ GIMPLE_OMP_TARGET and GIMPLE_OMP_TEAMS.
+ * builtin-types.def (DEF_FUNCTION_TYPE_8): Document.
+ (BT_FN_VOID_OMPFN_PTR_UINT,
+ BT_FN_VOID_OMPFN_PTR_UINT_LONG_LONG_LONG,
+ BT_FN_VOID_OMPFN_PTR_UINT_LONG_LONG_LONG_LONG,
+ BT_FN_VOID_OMPFN_PTR_OMPCPYFN_LONG_LONG_BOOL_UINT): Remove.
+ (BT_FN_VOID_OMPFN_PTR_UINT_UINT_UINT,
+ BT_FN_VOID_OMPFN_PTR_UINT_LONG_LONG_LONG_UINT,
+ BT_FN_VOID_OMPFN_PTR_UINT_LONG_LONG_LONG_LONG_UINT,
+ BT_FN_BOOL_INT, BT_FN_BOOL_INT_BOOL, BT_FN_VOID_UINT_UINT,
+ BT_FN_VOID_INT_PTR_SIZE_PTR_PTR_PTR,
+ BT_FN_VOID_INT_OMPFN_PTR_SIZE_PTR_PTR_PTR,
+ BT_FN_VOID_OMPFN_PTR_OMPCPYFN_LONG_LONG_BOOL_UINT_PTR): New.
+ * tree-ssa-alias.c (ref_maybe_used_by_call_p_1,
+ call_may_clobber_ref_p_1): Handle BUILT_IN_GOMP_BARRIER_CANCEL,
+ BUILT_IN_GOMP_TASKGROUP_END, BUILT_IN_GOMP_LOOP_END_CANCEL,
+ BUILT_IN_GOMP_SECTIONS_END_CANCEL. Don't handle
+ BUILT_IN_GOMP_PARALLEL_END.
+ * gimple-low.c (lower_stmt): Handle GIMPLE_OMP_TASKGROUP,
+ GIMPLE_OMP_TARGET and GIMPLE_OMP_TEAMS.
+ * gimple-pretty-print.c (dump_gimple_omp_for): Handle
+ GF_OMP_FOR_KIND_DISTRIBUTE.
+ (dump_gimple_omp_target, dump_gimple_omp_teams): New functions.
+ (dump_gimple_omp_block): Handle GIMPLE_OMP_TASKGROUP.
+ (dump_gimple_omp_return): Print lhs if it has any.
+ (dump_gimple_omp_atomic_load, dump_gimple_omp_atomic_store): Handle
+ gimple_omp_atomic_seq_cst_p.
+ (pp_gimple_stmt_1): Handle GIMPLE_OMP_TASKGROUP, GIMPLE_OMP_TARGET
+ and GIMPLE_OMP_TEAMS.
+ * langhooks.c (lhd_omp_mappable_type): New function.
+ * tree-vectorizer.c (struct simd_array_to_simduid): Fix up comment.
+ * langhooks.h (struct lang_hooks_for_types): Add omp_mappable_type
+ hook.
+ * gimplify.c (enum gimplify_omp_var_data): Add GOVD_MAP,
+ GOVD_ALIGNED and GOVD_MAP_TO_ONLY.
+ (enum omp_region_type): Add ORT_TEAMS, ORT_TARGET_DATA and ORT_TARGET.
+ (struct gimplify_omp_ctx): Add combined_loop field.
+ (gimplify_call_expr, gimplify_modify_expr): Don't call fold_stmt
+ on stmts inside of target region.
+ (is_gimple_stmt): Return true for OMP_DISTRIBUTE and OMP_TASKGROUP.
+ (omp_firstprivatize_variable): Handle GOVD_MAP, GOVD_ALIGNED,
+ ORT_TARGET and ORT_TARGET_DATA.
+ (omp_add_variable): Avoid checks on readding var for GOVD_ALIGNED.
+ Handle GOVD_MAP.
+ (omp_notice_threadprivate_variable): Complain about threadprivate
+ variables in target region.
+ (omp_notice_variable): Complain about vars with non-mappable type
+ in target region. Handle ORT_TEAMS, ORT_TARGET and ORT_TARGET_DATA.
+ (omp_check_private): Ignore ORT_TARGET* regions.
+ (gimplify_scan_omp_clauses, gimplify_adjust_omp_clauses_1,
+ gimplify_adjust_omp_clauses): Handle new OpenMP 4.0 clauses.
+ (find_combined_omp_for): New function.
+ (gimplify_omp_for): Handle gimplification of combined loops.
+ (gimplify_omp_workshare): Gimplify also OMP_TARGET, OMP_TARGET_DATA,
+ OMP_TEAMS.
+ (gimplify_omp_target_update): New function.
+ (gimplify_omp_atomic): Handle OMP_ATOMIC_SEQ_CST.
+ (gimplify_expr): Handle OMP_DISTRIBUTE, OMP_TARGET, OMP_TARGET_DATA,
+ OMP_TARGET_UPDATE, OMP_TEAMS, OMP_TASKGROUP.
+ (gimplify_body): If fndecl has "omp declare target" attribute, add
+ implicit ORT_TARGET context around it.
+ * tree.def (OMP_DISTRIBUTE, OMP_TEAMS, OMP_TARGET_DATA, OMP_TARGET,
+ OMP_TASKGROUP, OMP_TARGET_UPDATE): New tree codes.
+ * tree-nested.c (convert_nonlocal_reference_stmt,
+ convert_local_reference_stmt, convert_gimple_call): Handle
+ GIMPLE_OMP_TARGET, GIMPLE_OMP_TEAMS and GIMPLE_OMP_TASKGROUP.
+ * omp-builtins.def (BUILT_IN_GOMP_TASK): Use
+ BT_FN_VOID_OMPFN_PTR_OMPCPYFN_LONG_LONG_BOOL_UINT_PTR
+ instead of BT_FN_VOID_OMPFN_PTR_OMPCPYFN_LONG_LONG_BOOL_UINT.
+ (BUILT_IN_GOMP_TARGET, BUILT_IN_GOMP_TARGET_DATA,
+ BUILT_IN_GOMP_TARGET_END_DATA, BUILT_IN_GOMP_TARGET_UPDATE,
+ BUILT_IN_GOMP_TEAMS, BUILT_IN_BARRIER_CANCEL,
+ BUILT_IN_GOMP_LOOP_END_CANCEL,
+ BUILT_IN_GOMP_SECTIONS_END_CANCEL, BUILT_IN_OMP_GET_TEAM_NUM,
+ BUILT_IN_OMP_GET_NUM_TEAMS, BUILT_IN_GOMP_TASKGROUP_START,
+ BUILT_IN_GOMP_TASKGROUP_END, BUILT_IN_GOMP_PARALLEL_LOOP_STATIC,
+ BUILT_IN_GOMP_PARALLEL_LOOP_DYNAMIC,
+ BUILT_IN_GOMP_PARALLEL_LOOP_GUIDED,
+ BUILT_IN_GOMP_PARALLEL_LOOP_RUNTIME, BUILT_IN_GOMP_PARALLEL,
+ BUILT_IN_GOMP_PARALLEL_SECTIONS, BUILT_IN_GOMP_CANCEL,
+ BUILT_IN_GOMP_CANCELLATION_POINT): New built-ins.
+ (BUILT_IN_GOMP_PARALLEL_LOOP_STATIC_START,
+ BUILT_IN_GOMP_PARALLEL_LOOP_DYNAMIC_START,
+ BUILT_IN_GOMP_PARALLEL_LOOP_GUIDED_START,
+ BUILT_IN_GOMP_PARALLEL_LOOP_RUNTIME_START,
+ BUILT_IN_GOMP_PARALLEL_START, BUILT_IN_GOMP_PARALLEL_END,
+ BUILT_IN_GOMP_PARALLEL_SECTIONS_START): Remove.
+ * tree-inline.c (remap_gimple_stmt, estimate_num_insns):
+ Handle GIMPLE_OMP_TARGET, GIMPLE_OMP_TEAMS and GIMPLE_OMP_TASKGROUP.
+ * gimple.c (gimple_build_omp_taskgroup, gimple_build_omp_target,
+ gimple_build_omp_teams): New functions.
+ (walk_gimple_op): Handle GIMPLE_OMP_TARGET, GIMPLE_OMP_TEAMS and
+ GIMPLE_OMP_TASKGROUP. Walk optional lhs on GIMPLE_OMP_RETURN.
+ (walk_gimple_stmt, gimple_copy): Handle GIMPLE_OMP_TARGET,
+ GIMPLE_OMP_TEAMS and GIMPLE_OMP_TASKGROUP.
+ * gimple.h (enum gf_mask): GF_OMP_FOR_KIND_DISTRIBUTE,
+ GF_OMP_FOR_COMBINED, GF_OMP_FOR_COMBINED_INTO,
+ GF_OMP_TARGET_KIND_MASK, GF_OMP_TARGET_KIND_REGION,
+ GF_OMP_TARGET_KIND_DATA, GF_OMP_TARGET_KIND_UPDATE,
+ GF_OMP_ATOMIC_SEQ_CST): New.
+ (gimple_build_omp_taskgroup, gimple_build_omp_target,
+ gimple_build_omp_teams): New prototypes.
+ (gimple_has_substatements): Handle GIMPLE_OMP_TARGET,
+ GIMPLE_OMP_TEAMS and GIMPLE_OMP_TASKGROUP.
+ (gimple_omp_subcode): Use GIMPLE_OMP_TEAMS instead of
+ GIMPLE_OMP_SINGLE as end of range.
+ (gimple_omp_return_set_lhs, gimple_omp_return_lhs,
+ gimple_omp_return_lhs_ptr, gimple_omp_atomic_seq_cst_p,
+ gimple_omp_atomic_set_seq_cst, gimple_omp_for_combined_p,
+ gimple_omp_for_set_combined_p, gimple_omp_for_combined_into_p,
+ gimple_omp_for_set_combined_into_p, gimple_omp_target_clauses,
+ gimple_omp_target_clauses_ptr, gimple_omp_target_set_clauses,
+ gimple_omp_target_kind, gimple_omp_target_set_kind,
+ gimple_omp_target_child_fn, gimple_omp_target_child_fn_ptr,
+ gimple_omp_target_set_child_fn, gimple_omp_target_data_arg,
+ gimple_omp_target_data_arg_ptr, gimple_omp_target_set_data_arg,
+ gimple_omp_teams_clauses, gimple_omp_teams_clauses_ptr,
+ gimple_omp_teams_set_clauses): New inlines.
+ (CASE_GIMPLE_OMP): Add GIMPLE_OMP_TARGET, GIMPLE_OMP_TEAMS
+ and GIMPLE_OMP_TASKGROUP.
+ * tree-core.h (enum omp_clause_code): Add new OpenMP 4.0 clause codes.
+ (enum omp_clause_depend_kind, enum omp_clause_map_kind,
+ enum omp_clause_proc_bind_kind): New.
+ (union omp_clause_subcode): Add depend_kind, map_kind and
+ proc_bind_kind fields.
+ * tree-cfg.c (make_edges): Handle GIMPLE_OMP_TARGET,
+ GIMPLE_OMP_TEAMS and GIMPLE_OMP_TASKGROUP.
+ * langhooks-def.h (lhd_omp_mappable_type): New prototype.
+ (LANG_HOOKS_OMP_MAPPABLE_TYPE): Define.
+ (LANG_HOOKS_FOR_TYPES_INITIALIZER): Add it.
+
+2013-10-10 Teresa Johnson <tejohnson@google.com>
+
+ * predict.c (tree_estimate_probability): Add new parameter
+ for estimate_bb_frequencies.
+ (estimate_bb_frequencies): Add new parameter to force estimation.
+ (rebuild_frequencies): When max frequency in function is small,
+ recompute counts from frequencies.
+ * predict.h (estimate_bb_frequencies): New parameter.
+
+2013-10-10 David Malcolm <dmalcolm@redhat.com>
+
+ * ipa-inline.c (ipa_inline): Fix leak of "order" when
+ optimizations are disabled.
+
+2013-10-10 David Malcolm <dmalcolm@redhat.com>
+
+ * coverage.c (coverage_finish): Fix leak of da_file_name.
+
+2013-10-10 Jan Hubicka <jh@suse.cz>
+
+ * config/i386/x86-tune.def: Enable X86_TUNE_SSE_TYPELESS_STORES
+ for generic, enable X86_TUNE_SSE_LOAD0_BY_PXOR for Bulldozer,
+ Bobcat and generic.
+
+2013-10-10 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/58670
+ * stmt.c (expand_asm_operands): Add FALLTHRU_BB argument,
+ if any labels are in FALLTHRU_BB, use a special label emitted
+ immediately after the asm goto insn rather than label_rtx
+ of the LABEL_DECL.
+ (expand_asm_stmt): Adjust caller.
+ * cfgrtl.c (commit_one_edge_insertion): Force splitting of
+ edge if the last insn in predecessor is a jump with single successor,
+ but it isn't simplejump_p.
+
+2013-10-10 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/58656
+ * tree-ssa-pre.c (phi_translate): Do not cache failed translations.
+
+2013-10-10 Andrew MacLeod <amacleod@redhat.com>
+
+ * gimplify.c: Include expr.h and tm_p.h for targets with special
+ va-arg padding requirements.
+
+2013-10-10 Andrew MacLeod <amacleod@redhat.com>
+
+ * tree-flow.h: Move some prototypes to gimple.h.
+ (gimple_fold_indirect_ref): Move prototype to gimple-fold.h.
+ * gimple.h: Relocate some prototypes from tree-flow.h
+ * builtins.c (std_gimplify_va_arg_expr, build_va_arg_indirect_ref):
+ Move to gimplify.c.
+ * gimplify.c (gimple_fold_indirect_ref): Move to gimple-fold.c.
+ (build_va_arg_indirect_ref): Relocate and make static.
+ (std_gimplify_va_arg_expr): Relocate here.
+ * gimple-fold.c (gimple_fold_indirect_ref): Relocate here.
+ * gimple-fold.h (gimple_fold_indirect_ref): Add prototype.
+
+2013-10-10 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
+
+ * doc/md.texi: Document the mnemonic attribute.
+
+2013-10-10 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
+
+ PR target/57377
+ * gensupport.c (gen_mnemonic_attr): Handle (set (attr x) y) and
+ (set_attr_alternative x ...) when searching for user defined
+ mnemonic attribute.
+
+2013-10-10 Andrew MacLeod <amacleod@redhat.com>
+
+ * config/aplha/alpha.c: Add gimple-ssa.h to include list.
+
+2013-10-09 Easwaran Raman <eraman@google.com>
+
+ * params.def (PARAM_MIN_SIZE_FOR_STACK_SHARING): New param...
+ * cfgexpand.c (defer_stack_allocation): ...use here
+ * doc/invoke.texi: Add documentation for min-size-for-stack-sharing.
+
+2013-10-09 Zhenqiang Chen <zhenqiang.chen@arm.com>
+
+ * tree-ssa-phiopts.c (rhs_is_fed_for_value_replacement): New function.
+ (operand_equal_for_value_replacement): New function, extracted from
+ value_replacement and enhanced to catch more cases.
+ (value_replacement): Use operand_equal_for_value_replacement.
+
+2013-10-09 Andrew MacLeod <amacleod@redhat.com>
+
+ * loop-doloop.c (doloop_modify, doloop_optimize): Use
+ get_max_loop_iterations.
+
+2013-10-09 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * config/arm/aarch-common.c (arm_early_load_addr_dep):
+ Place comment above function.
+
+2013-10-09 Andrew MacLeod <amacleod@redhat.com>
+
+ * tree-flow.h: Remove all remaining prototypes, enums and structs that
+ are not related to tree-cfg.c.
+ * tree-ssa-address.h: New file. Relocate prototypes.
+ * tree-ssa-address.c: (struct mem_address): Relocate from tree-flow.h.
+ (addr_for_mem_ref): New. Combine call to get_address_description and
+ return addr_for_mem_ref.
+ * expr.c (expand_expr_real_1): Use new addr_for_mem_ref routine.
+ * tree-ssa-live.h: Adjust prototypes.
+ * passes.c: Include tree-ssa-live.h.
+ * gimple-pretty-print.h (gimple_dump_bb): Add prototype.
+ * graphite.c (graphite_transform_loops): Make static.
+ (graphite_transforms, gate_graphite_transforms, pass_data_graphite,
+ make_pass_graphite, pass_data_graphite_transforms,
+ make_pass_graphite_transforms): Relocate here from tree-ssa-loop.c.
+ * ipa-pure-const.c (warn_function_noreturn): Make static.
+ (execute_warn_function_noreturn, gate_warn_function_noreturn,
+ class pass_warn_function_noreturn, make_pass_warn_function_noreturn):
+ Relocate from tree-cfg.c
+ * tree-cfg.c (tree_node_can_be_shared, gimple_empty_block_p): Make
+ static.
+ (execute_warn_function_noreturn, gate_warn_function_noreturn,
+ class pass_warn_function_noreturn, make_pass_warn_function_noreturn):
+ Move to ipa-pure-const.c.
+ (execute_fixup_cfg, class pass_fixup_cfg, make_pass_fixup_cfg):
+ Relocate from tree-optimize.c.
+ * tree-optimize.c (execute_fixup_cfg, class pass_fixup_cfg,
+ make_pass_fixup_cfg): Move to tree-cfg.c.
+ * tree-chrec.h: (enum ev_direction): Relocate here from tree-flow.h.
+ Relocate some prototypes.
+ * tree-data-ref.h (tree_check_data_deps) Add prototype.
+ * tree-dump.c (dump_function_to_file): Remove prototype.
+ Add tree-flow.h to the include file.
+ * tree-dump.h: Remove prototype.
+ * tree-parloops.h: New File. Add prototypes.
+ * tree-parloops.c (gate_tree_parallelize_loops, tree_parallelize_loops,
+ pass_data_parallelize_loops, make_pass_parallelize_loops): Relocate
+ from tree-ssa-loop.c.
+ * tree-predcom.c (run_tree_predictive_commoning,
+ gate_tree_predictive_commoning, pass_data_predcom, make_pass_predcom):
+ Relocate here from tree-ssa-loop.c.
+ * tree-ssa-dom.c (tree_ssa_dominator_optimize) Don't call
+ ssa_name_values.release ().
+ * tree-ssa-threadedge.h: New File. Relocate prototypes here.
+ (ssa_name_values): Relocate from tree-flow.h.
+ * tree-ssa.h: Include tree-ssa-threadedge.h and tree-ssa-address.h.
+ * tree-ssa-loop.c (run_tree_predictive_commoning,
+ gate_tree_predictive_commoning, pass_data_predcom, make_pass_predcom,
+ graphite_transforms, gate_graphite_transforms, pass_data_graphite,
+ make_pass_graphite, pass_data_graphite_transforms,
+ make_pass_graphite_transforms, gate_tree_parallelize_loops,
+ tree_parallelize_loops, pass_data_parallelize_loops,
+ make_pass_parallelize_loops): Move to other files.
+ * tree-vectorizer.h (lpeel_tree_duplicate_loop_to_edge_cfg): Prototype
+ moved here.
+ * tree.h: Remove prototypes from tree-address.c.
+
+2013-10-09 Andrew MacLeod <amacleod@redhat.com>
+
+ * tree-flow.h (tm_restart_node, gimple_df): Move to gimple-ssa.h.
+ (struct int_tree_map): Move to tree-hasher.h
+ (SCALE, LABEL, PERCENT): Move to gimple.h
+ * tree-flow-inline.h: Delete. Move functions to other files.
+ (unmodifiable_var_p, ref_contains_array_ref): Unused, so delete.
+ * gimple-ssa.h (tm_restart_node, gimple_df): Relocate from tree-flow.h.
+ (gimple_in_ssa_p, gimple_vop): Relocate from tree-flow-inline.h
+ * gimple.h (imple_stmt_max_uid, set_gimple_stmt_max_uid,
+ inc_gimple_stmt_max_uid, get_lineno): Relocate from tree-flow-inline.h.
+ (SCALE, LABEL, PERCENT): Relocate from tree-flow.h
+ * tree-hasher.h: Don't include tree-flow.h.
+ (struct int_tree_map): Relocate from tree-flow.h.
+ * tree-sra.c (contains_view_convert_expr_p): Relocate from
+ tree-flow-inline.h and make static.
+ * tree-ssa-alias.h (ranges_overlap_p): Relocate from
+ tree-flow-inline.h.
+ * tree-ssa-operands.c (gimple_ssa_operands): Relocate from
+ tree-flow-inline.h and make static.
+ * tree.h (is_global_var, may_be_aliased): Relocate from
+ tree-flow-inline.h.
+ * Makefile.in (GTFILES): Remove tree-flow.h and add gimple-ssa.h.
+ * value-prof.c: No longer include tree-flow-inline.h.
+ * tree-switch-conversion.c: No longer include tree-flow-inline.h.
+
+2013-10-09 Andrew MacLeod <amacleod@redhat.com>
+
+ * tree-flow.h: Move some protoypes. Include new tree-ssa-loop.h.
+ (struct affine_iv, struct tree_niter_desc): Move to tree-ssa-loop.h.
+ (enum move_pos): Move to tree-ssa-loop-im.h
+ * cfgloop.h: Move some prototypes.
+ (gcov_type_to_double_int): relocate from tree-ssa-loop.niter.c.
+ * tree-flow-inline.h (loop_containing_stmt): Move to tree-ssa-loop.h.
+ * tree-ssa-loop.h: New File. Include other tree-ssa-loop-*.h files.
+ (struct affine_iv, struct tree_niter_desc): Relocate from tree-flow.h.
+ (loop_containing_stmt): Relocate from tree-flow-inline.h.
+ * tree-ssa-loop-ch.c: (do_while_loop_p): Make static.
+ * tree-ssa-loop-im.c (for_each_index): Move to tree-ssa-loop.c.
+ (enum move_pos): Relocate here.
+ (lsm_tmp_name_add, gen_lsm_tmp_name, get_lsm_tmp_name): Move to
+ tree-ssa-loop.c.
+ (execute_sm_if_changed_flag_set): Change get_lsm_tmp_name call.
+ (tree_ssa_loop_im, gate_tree_ssa_loop_im, pass_data_lim,
+ make_pass_lim): Relocate here from tree-ssa-loop.c.
+ * tree-ssa-loop-ivcanon.c (tree_num_loop_insns): Move to
+ tree-ssa-loop.c.
+ (loop_edge_to_cancel, unloop_loops): Make static.
+ (tree_ssa_loop_ivcanon, gate_tree_ssa_loop_ivcanon, pass_data_iv_canon,
+ make_pass_iv_canon): Relocate from tree-ssa-loop.c.
+ (tree_complete_unroll, gate_tree_complete_unroll,
+ pass_data_complete_unroll, make_pass_complete_unroll): Relocate here.
+ (tree_complete_unroll_inner, gate_tree_complete_unroll_inner,
+ pass_data_complete_unrolli, make_pass_complete_unrolli): Relocate here.
+ * tree-ssa-loop-ivopts.c: Remove local prototypes.
+ (stmt_invariant_in_loop_p): Remove unused function.
+ * tree-ssa-loop-ivopts.h: New file. Add prototypes.
+ * tree-ssa-loop-manip.h: New file. Add prototypes.
+ * tree-ssa-loop-niter.c (record_niter_bound): Move to cfgloop.c.
+ (gcov_type_to_double_int): Move to cfgloop.h.
+ (double_int_cmp, bound_index,
+ estimate_numbers_of_iterations_loop): Make static.
+ (estimated_loop_iterations): Factor out get_estimated_loop_iterations.
+ (max_loop_iterations): Factor out get_max_loop_iterations.
+ (estimated_loop_iterations_int, max_stmt_executions_int): Move to
+ cfgloop.c.
+ * tree-ssa-loop-niter.h: New file. Add prototypes.
+ * tree-ssa-loop-prefetch.c (tree_ssa_loop_prefetch,
+ gate_tree_ssa_loop_prefetch, pass_data_loop_prefetch,
+ make_pass_loop_prefetch): Relocate from tree-ssa-loop.c.
+ * tree-ssa-loop-unswitch.c (tree_ssa_loop_unswitch,
+ gate_tree_ssa_loop_unswitch, pass_data_tree_unswitch,
+ make_pass_tree_unswitch): Relocate from tree-ssa-loop.c.
+ * tree-ssa-loop.c (tree_ssa_loop_im, gate_tree_ssa_loop_im,
+ pass_data_lim, make_pass_lim): Move to tree-ssa-loop-im.c.
+ (tree_ssa_loop_unswitch, gate_tree_ssa_loop_unswitch,
+ pass_data_tree_unswitch, make_pass_tree_unswitch): Move.
+ (tree_ssa_loop_ivcanon, gate_tree_ssa_loop_ivcanon, pass_data_iv_canon,
+ make_pass_iv_canon, tree_complete_unroll, gate_tree_complete_unroll,
+ pass_data_complete_unroll, make_pass_complete_unroll,
+ tree_complete_unroll_inner, gate_tree_complete_unroll_inner,
+ pass_data_complete_unrolli, make_pass_complete_unrolli): Move to
+ tree-ssa-loop-ivcanon.c.
+ (tree_ssa_loop_prefetch, gate_tree_ssa_loop_prefetch,
+ pass_data_loop_prefetch, make_pass_loop_prefetch): Move to
+ tree-ssa-loop-prefetch.c.
+ (for_each_index, lsm_tmp_name_add, gen_lsm_tmp_name): Relocate from
+ tree-ssa-loop-im.c.
+ (get_lsm_tmp_name): Relocate and add suffix parameter.
+ (tree_num_loop_insns): Relocate from tree-ssa-ivcanon.c.
+ * tree-scalar-evolution.h (simple_iv): Don't use affive_iv typedef.
+ * cfgloop.c (record_niter_bound, estimated_loop_iterations_int,
+ max_stmt_executions_int): Move from tree-ssa-loop-niter.c.
+ (get_estimated_loop_iterations): Factor out accessor from
+ estimated_loop_iterations in tree-ssa-loop-niter.c.
+ (get_max_loop_iterations): Factor out accessor from
+ _max_loop_iterations in tree-ssa-niter.c.
+ * loop-unroll.c (decide_unroll_constant_iterations,
+ decide_unroll_runtime_iterations, decide_peel_simple,
+ decide_unroll_stupid): Use new get_* accessors.
+
+2013-10-09 Marc Glisse <marc.glisse@inria.fr>
+
+ PR tree-optimization/20318
+ * doc/extend.texi (returns_nonnull): New function attribute.
+ * fold-const.c (tree_expr_nonzero_warnv_p): Look for returns_nonnull
+ attribute.
+ * tree-vrp.c (gimple_stmt_nonzero_warnv_p): Likewise.
+ (stmt_interesting_for_vrp): Accept all GIMPLE_CALL.
+
+2013-10-09 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR middle-end/58570
+ * tree-ssa-alias.c (nonoverlapping_component_refs_of_decl_p): Return
+ false if both components are bitfields.
+
+2013-10-09 Alex Velenko <Alex.Velenko@arm.com>
+
+ * config/aarch64/arm_neon.h (vclz_s8, vclz_s16, vclz_s32)
+ (vclzq_s8, vclzq_s16, vclzq_s32, vclz_u8, vclz_u16, vclz_u32)
+ (vclzq_u8, vclzq_u16, vclzq_u32): Replace ASM with C.
+ * config/aarch64/aarch64.h
+ (CLZ_DEFINED_VALUE_AT_ZERO): Macro fixed for clz.
+ * config/aarch64/aarch64-simd-builtins.def
+ (VAR1 (UNOP, clz, 0, v4si)): Replaced with iterator.
+
+2013-10-09 Alex Velenko <Alex.Velenko@arm.com>
+
+ * config/aarch64/arm_neon.h (vadd_f64, vsub_f64): Implementation added.
+
+2013-10-09 Alex Velenko <Alex.Velenko@arm.com>
+
+ * config/aarch64/arm_neon.h (vdiv_f64): Added.
+
+2013-10-09 Alex Velenko <Alex.Velenko@arm.com>
+
+ * config/aarch64/arm_neon.h (vneg_f32): Asm replaced with C.
+ (vneg_f64): New intrinsic.
+ (vneg_s8): Asm replaced with C.
+ (vneg_s16): Likewise.
+ (vneg_s32): Likewise.
+ (vneg_s64): New intrinsic.
+ (vnegq_f32): Asm replaced with C.
+ (vnegq_f64): Likewise.
+ (vnegq_s8): Likewise.
+ (vnegq_s16): Likewise.
+ (vnegq_s32): Likewise.
+ (vnegq_s64): Likewise.
+
+2013-10-09 Renlin Li <Renlin.Li@arm.com>
+
+ * config/arm/arm.c (arm_output_mi_thunk): Use plus_constant.
+
+2013-10-09 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
+
+ * config/s390/s390.c (s390_register_info_stdarg_fpr): Remove
+ packed stack special handling.
+ (s390_frame_info, s390_emit_prologue, s390_emit_epilogue): Switch
+ back to fixed stack slots for FPRs saved due to stdarg.
+
+2013-10-09 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
+
+ * config/s390/s390.c (s390_frame_info): Restructure function.
+
+2013-10-09 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
+
+ * config/s390/s390.c (struct s390_frame_layout): New field
+ gpr_save_slots.
+ (cfun_save_arg_fprs_p, cfun_gpr_save_slot): New macros.
+ (s390_reg_clobbered_rtx, s390_regs_ever_clobbered): Change type of
+ regs_ever_clobbered to char*.
+ (s390_regs_ever_clobbered): Check crtl->saves_all_registers instead
+ of cfun->has_nonlocal_label. Ignore frame related restore INSNs.
+ (s390_register_info): Enable FPR save slots. Move/Copy some
+ functionality into ...
+ (s390_register_info_gprtofpr, s390_register_info_stdarg_fpr)
+ (s390_register_info_stdarg_gpr, s390_optimize_register_info): New
+ function.
+ (s390_frame_info): Do gpr slot allocation here now. stdarg does
+ not imply a stack frame.
+ (s390_init_frame_layout): Remove variable clobbered_regs.
+ (s390_update_register_info): Remove function.
+ (s390_hard_regno_rename_ok): Call-saved regs without a save slot
+ cannot be used for register renaming.
+ (s390_hard_regno_scratch_ok): New function.
+ (TARGET_HARD_REGNO_SCRATCH_OK): Define target hook.
+ (s390_initial_elimination_offset): Change offset calculation of
+ the return address pointer.
+ (save_gprs): Deal with only r6 being saved from the call-saved regs.
+ (restore_gprs): Set frame related flag.
+ (s390_save_gprs_to_fprs, s390_restore_gprs_from_fprs): New functions.
+ (s390_emit_prologue): Call s390_register_info instead of
+ s390_update_frame_layout. Call s390_save_gprs_to_fprs.
+ (s390_emit_epilogue): Call s390_restore_gprs_from_fprs.
+ (s390_optimize_prologue): Call s390_optimize_register_info.
+ Try to remove also FPR slot save/restore INSNs. Remove frame
+ related flags from restore INSNs.
+
+2013-10-08 DJ Delorie <dj@redhat.com>
+
+ * config/rl78/rl78-expand.md (movqi): use operands[] not operandN.
+ (movhi): Likewise.
+
+ * config/rl78/rl78.c (rl78_print_operand_1): Change %c to %C to
+ avoid conflict with the MI use of %c.
+ * config/rl78/rl78-real.md: change %c to %C throughout.
+ * config/rl78/rl78-virt.md: Likewise.
+
+2013-10-08 Jan Hubicka <jh@suse.cz>
+
+ * config/i386/i386.c (ix86_option_override_internal): Switch
+ to SSE math for -ffast-math when target ISA supports SSE2.
+
+2013-10-08 Andrew MacLeod <amacleod@redhat.com>
+
+ * tree-flow.h: Remove some prototypes.
+ * tree.h: Remove some protypes, add a couple.
+ * tree.c (using_eh_for_cleanups_flag, using_eh_for_cleanups,
+ using_eh_for_cleanups_p): Add interface routines for front ends.
+ * tree-eh.h: New file. Add protoptyes.
+ * tree-eh.c (using_eh_for_cleanups_p, using_eh_for_cleanups): Delete.
+ (add_stmt_to_eh_lp_fn): Make static.
+ (lower_try_finally): Use new using_eh_for_cleanups_p.
+ * emit-rtl.c: Include tree-eh.h.
+ * gimple.h: Include tree-eh.h.
+
+2013-10-08 Marc Glisse <marc.glisse@inria.fr>
+
+ PR tree-optimization/58480
+ * tree-vrp.c (infer_nonnull_range): New function.
+ (infer_value_range): Call infer_nonnull_range.
+
+2013-10-08 Dehao Chen <dehao@google.com>
+
+ PR tree-optimization/58619
+ * tree-inline.c (copy_phis_for_bb): Combine location data
+ only if non-null.
+
+2013-10-08 Zhenqiang Chen <zhenqiang.chen@linaro.org>
+
+ PR target/58423
+ * config/arm/arm.c (arm_emit_ldrd_pop): Attach
+ RTX_FRAME_RELATED_P on INSN.
+
+2013-10-07 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * config/rs6000/rs6000.c (altivec_expand_vec_perm_const_le): New.
+ (altivec_expand_vec_perm_const): Call it.
+
+2013-10-07 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * config/rs6000/vector.md (mov<mode>): Emit permuted move
+ sequences for LE VSX loads and stores at expand time.
+ * config/rs6000/rs6000-protos.h (rs6000_emit_le_vsx_move): New
+ prototype.
+ * config/rs6000/rs6000.c (rs6000_const_vec): New.
+ (rs6000_gen_le_vsx_permute): New.
+ (rs6000_gen_le_vsx_load): New.
+ (rs6000_gen_le_vsx_store): New.
+ (rs6000_gen_le_vsx_move): New.
+ * config/rs6000/vsx.md (*vsx_le_perm_load_v2di): New.
+ (*vsx_le_perm_load_v4si): New.
+ (*vsx_le_perm_load_v8hi): New.
+ (*vsx_le_perm_load_v16qi): New.
+ (*vsx_le_perm_store_v2di): New.
+ (*vsx_le_perm_store_v4si): New.
+ (*vsx_le_perm_store_v8hi): New.
+ (*vsx_le_perm_store_v16qi): New.
+ (*vsx_xxpermdi2_le_<mode>): New.
+ (*vsx_xxpermdi4_le_<mode>): New.
+ (*vsx_xxpermdi8_le_V8HI): New.
+ (*vsx_xxpermdi16_le_V16QI): New.
+ (*vsx_lxvd2x2_le_<mode>): New.
+ (*vsx_lxvd2x4_le_<mode>): New.
+ (*vsx_lxvd2x8_le_V8HI): New.
+ (*vsx_lxvd2x16_le_V16QI): New.
+ (*vsx_stxvd2x2_le_<mode>): New.
+ (*vsx_stxvd2x4_le_<mode>): New.
+ (*vsx_stxvd2x8_le_V8HI): New.
+ (*vsx_stxvd2x16_le_V16QI): New.
+
+2013-10-07 Renlin Li <Renlin.Li@arm.com>
+
+ * config/arm/arm-cores.def (cortex-a53): Use cortex tuning.
+
+2013-10-07 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
+
+ * config/s390/s390.c (s390_register_info): Make the call-saved FPR
+ loop to work also for 31bit ABI.
+ Save the stack pointer for frame_size > 0.
+
+2013-10-07 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
+
+ * config/s390/s390.md ("tbegin", "tbegin_nofloat", "tbegin_retry")
+ ("tbegin_retry_nofloat", "tend", "tabort", "tx_assist"): Remove
+ constraint letters from expanders.
+ ("tbegin_retry", "tbegin_retry_nofloat"): Change predicate of the
+ retry count to general_operand.
+ ("tabort"): Give operand 0 a mode.
+ ("tabort_1"): Add mode and constraint letter for operand 0.
+ * doc/extend.texi: Fix protoype of __builtin_non_tx_store.
+
+2013-10-04 Jeff Law <law@redhat.com>
+
+ * tree-ssa-threadedge.c: Fix some trailing whitespace problems.
+
+ * tree-ssa-threadedge.c (thread_through_normal_block): Broken
+ out of ...
+ (thread_across_edge): Here. Call it.
+
+2013-10-04 Cary Coutant <ccoutant@google.com>
+
+ * dwarf2out.c (dw_sra_loc_expr): Release addr_table entries when
+ discarding a location list expression (or a piece of one).
+
+2013-10-03 Jan Hubicka <jh@suse.cz>
+
+ * config/i386/i386.c (ix86_issue_rate): Pentium4, Nocona has issue
+ rate of 2. Core2, Corei7 and Haswell has issue rate of 4.
+ (ix86_adjust_cost): Remove Atom case; fix core2/corei7/Haswell case.
+
+2013-10-03 Jan Hubicka <jh@suse.cz>
+
+ * config/i386/i386.c (ix86_option_override_internal): Do not enable
+ accumulate-outgoing-args when producing unwind info.
+
+2013-10-03 Wei Mi <wmi@google.com>
+
+ * lra-constraints.c (insert_move_for_subreg): New function
+ extracted from simplify_operand_subreg.
+ (simplify_operand_subreg): Add reload for paradoxical subreg.
+
+2013-10-03 Rong Xu <xur@google.com>
+
+ * ipa-inline-analysis.c (find_foldable_builtin_expect): Find
+ the candidate of builtin_expect such that we should fix the
+ size/time estimation.
+ (estimate_function_body_sizes): Do the acutally size/time fix-up
+ for builtin_expect.
+
+2013-10-03 Rong Xu <xur@google.com>
+
+ * predict.c (tree_predict_by_opcode): Get the probability
+ for builtin_expect from param builtin_expect_probability.
+ * params.def (BUILTIN_EXPECT_PROBABILITY): New parameter.
+ * predict.def (PRED_BUILTIN_EXPECT_RELAXED): Fix comments.
+ * doc/invoke.texi: Add documentation for builtin-expect-probability.
+
+2013-10-03 Marc Glisse <marc.glisse@inria.fr>
+
+ PR c++/19476
+ * common.opt (fcheck-new): Moved from c.opt. Make it 'Common'.
+ * calls.c (alloca_call_p): Use get_callee_fndecl.
+ * fold-const.c (tree_expr_nonzero_warnv_p): Handle operator new.
+ * tree-vrp.c (gimple_stmt_nonzero_warnv_p, stmt_interesting_for_vrp):
+ Likewise.
+ (vrp_visit_stmt): Remove duplicated code.
+
+2013-10-03 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * config/rs6000/rs6000-builtin.def (XSRDPIM): Use floatdf2,
+ ceildf2, btruncdf2, instead of vsx_* name.
+
+ * config/rs6000/vsx.md (vsx_add<mode>3): Change arithmetic
+ iterators to only do V2DF and V4SF here. Move the DF code to
+ rs6000.md where it is combined with SF mode. Replace <VSv> with
+ just 'v' since only vector operations are handled with these insns
+ after moving the DF support to rs6000.md.
+ (vsx_sub<mode>3): Likewise.
+ (vsx_mul<mode>3): Likewise.
+ (vsx_div<mode>3): Likewise.
+ (vsx_fre<mode>2): Likewise.
+ (vsx_neg<mode>2): Likewise.
+ (vsx_abs<mode>2): Likewise.
+ (vsx_nabs<mode>2): Likewise.
+ (vsx_smax<mode>3): Likewise.
+ (vsx_smin<mode>3): Likewise.
+ (vsx_sqrt<mode>2): Likewise.
+ (vsx_rsqrte<mode>2): Likewise.
+ (vsx_fms<mode>4): Likewise.
+ (vsx_nfma<mode>4): Likewise.
+ (vsx_copysign<mode>3): Likewise.
+ (vsx_btrunc<mode>2): Likewise.
+ (vsx_floor<mode>2): Likewise.
+ (vsx_ceil<mode>2): Likewise.
+ (vsx_smaxsf3): Delete scalar ops that were moved to rs6000.md.
+ (vsx_sminsf3): Likewise.
+ (vsx_fmadf4): Likewise.
+ (vsx_fmsdf4): Likewise.
+ (vsx_nfmadf4): Likewise.
+ (vsx_nfmsdf4): Likewise.
+ (vsx_cmpdf_internal1): Likewise.
+
+ * config/rs6000/rs6000.h (TARGET_SF_SPE): Define macros to make it
+ simpler to select whether a target has SPE or traditional floating
+ point support in iterators.
+ (TARGET_DF_SPE): Likewise.
+ (TARGET_SF_FPR): Likewise.
+ (TARGET_DF_FPR): Likewise.
+ (TARGET_SF_INSN): Macros to say whether floating point support
+ exists for a given operation for expanders.
+ (TARGET_DF_INSN): Likewise.
+
+ * config/rs6000/rs6000.c (Ftrad): New mode attributes to allow
+ combining of SF/DF mode operations, using both traditional and VSX
+ registers.
+ (Fvsx): Likewise.
+ (Ff): Likewise.
+ (Fv): Likewise.
+ (Fs): Likewise.
+ (Ffre): Likewise.
+ (FFRE): Likewise.
+ (abs<mode>2): Combine SF/DF modes using traditional floating point
+ instructions. Add support for using the upper DF registers with
+ VSX support, and SF registers with power8-vector support. Update
+ expanders for operations supported by both the SPE and traditional
+ floating point units.
+ (abs<mode>2_fpr): Likewise.
+ (nabs<mode>2): Likewise.
+ (nabs<mode>2_fpr): Likewise.
+ (neg<mode>2): Likewise.
+ (neg<mode>2_fpr): Likewise.
+ (add<mode>3): Likewise.
+ (add<mode>3_fpr): Likewise.
+ (sub<mode>3): Likewise.
+ (sub<mode>3_fpr): Likewise.
+ (mul<mode>3): Likewise.
+ (mul<mode>3_fpr): Likewise.
+ (div<mode>3): Likewise.
+ (div<mode>3_fpr): Likewise.
+ (sqrt<mode>3): Likewise.
+ (sqrt<mode>3_fpr): Likewise.
+ (fre<Fs>): Likewise.
+ (rsqrt<mode>2): Likewise.
+ (cmp<mode>_fpr): Likewise.
+ (smax<mode>3): Likewise.
+ (smin<mode>3): Likewise.
+ (smax<mode>3_vsx): Likewise.
+ (smin<mode>3_vsx): Likewise.
+ (negsf2): Delete SF operations that are merged with DF.
+ (abssf2): Likewise.
+ (addsf3): Likewise.
+ (subsf3): Likewise.
+ (mulsf3): Likewise.
+ (divsf3): Likewise.
+ (fres): Likewise.
+ (fmasf4_fpr): Likewise.
+ (fmssf4_fpr): Likewise.
+ (nfmasf4_fpr): Likewise.
+ (nfmssf4_fpr): Likewise.
+ (sqrtsf2): Likewise.
+ (rsqrtsf_internal1): Likewise.
+ (smaxsf3): Likewise.
+ (sminsf3): Likewise.
+ (cmpsf_internal1): Likewise.
+ (copysign<mode>3_fcpsgn): Add VSX/power8-vector support.
+ (negdf2): Delete DF operations that are merged with SF.
+ (absdf2): Likewise.
+ (nabsdf2): Likewise.
+ (adddf3): Likewise.
+ (subdf3): Likewise.
+ (muldf3): Likewise.
+ (divdf3): Likewise.
+ (fred): Likewise.
+ (rsqrtdf_internal1): Likewise.
+ (fmadf4_fpr): Likewise.
+ (fmsdf4_fpr): Likewise.
+ (nfmadf4_fpr): Likewise.
+ (nfmsdf4_fpr): Likewise.
+ (sqrtdf2): Likewise.
+ (smaxdf3): Likewise.
+ (smindf3): Likewise.
+ (cmpdf_internal1): Likewise.
+ (lrint<mode>di2): Use TARGET_<MODE>_FPR macro.
+ (btrunc<mode>2): Delete separate expander, and combine with the
+ insn and add VSX instruction support. Use TARGET_<MODE>_FPR.
+ (btrunc<mode>2_fpr): Likewise.
+ (ceil<mode>2): Likewise.
+ (ceil<mode>2_fpr): Likewise.
+ (floor<mode>2): Likewise.
+ (floor<mode>2_fpr): Likewise.
+ (fma<mode>4_fpr): Combine SF and DF fused multiply/add support.
+ Add support for using the upper registers with VSX and
+ power8-vector. Move insns to be closer to the define_expands. On
+ VSX systems, prefer the traditional form of FMA over the VSX
+ version, since the traditional form allows the target not to
+ overlap with the inputs.
+ (fms<mode>4_fpr): Likewise.
+ (nfma<mode>4_fpr): Likewise.
+ (nfms<mode>4_fpr): Likewise.
+
+2013-10-03 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+ Richard Earnshaw <richard.earnshaw@arm.com>
+
+ * config/arm/aarch-common-protos.h (struct alu_cost_table): New.
+ (struct mult_cost_table): Likewise.
+ (struct mem_cost_table): Likewise.
+ (struct fp_cost_table): Likewise.
+ (struct vector_cost_table): Likewise.
+ (cpu_cost_table): Likewise.
+ * config/arm/arm.opt (mold-rts-costs): New option.
+ (mnew-generic-costs): Likewise.
+ * config/arm/arm.c (generic_extra_costs): New table.
+ (cortexa15_extra_costs): Likewise.
+ (arm_slowmul_tune): Use NULL as new costs.
+ (arm_fastmul_tune): Likewise.
+ (arm_strongarm_tune): Likewise.
+ (arm_xscale_tune): Likewise.
+ (arm_9e_tune): Likewise.
+ (arm_v6t2_tune): Likewise.
+ (arm_cortex_a5_tune): Likewise.
+ (arm_cortex_a9_tune): Likewise.
+ (arm_v6m_tune): Likewise.
+ (arm_fa726te_tune): Likewise.
+ (arm_cortex_a15_tune): Use cortex15_extra_costs.
+ (arm_cortex_tune): Use generict_extra_costs.
+ (shifter_op_p): New function.
+ (arm_unspec_cost): Likewise.
+ (LIBCALL_COST): Define.
+ (arm_new_rtx_costs): New function.
+ (arm_rtx_costs): Use arm_new_rtx_costs when core-specific
+ table is available. Use old costs otherwise unless mnew-generic-costs
+ is specified.
+ * config/arm/arm-protos.h (tune_params): Add insn_extra_cost field.
+ (cpu_cost_table): Declare.
+
+2013-10-03 Marcus Shawcroft <marcus.shawcroft@arm.com>
+
+ PR target/58460
+ * config/aarch64/aarch64.md (*adds_mul_imm_<mode>)
+ (*subs_mul_imm_<mode>)
+ (*add_<shift>_<mode>, *add_<shift>_si_uxtw,*add_mul_imm_<mode>)
+ (*sub_<shift>_<mode>)
+ (*sub_<shift>_si_uxtw,*sub_mul_imm_<mode>, *sub_mul_imm_si_uxtw):
+ Remove k constraint.
+
+2013-10-03 Ian Bolton <ian.bolton@arm.com>
+
+ * config/aarch64/aarch64.c (aarch64_secondary_reload): Remove legacy
+ code.
+ * config/aarch64/aarch64.md (reload_sp_immediate): Likewise.
+
+2013-10-02 Teresa Johnson <tejohnson@google.com>
+
+ * predict.c (probably_never_executed): New function.
+ (probably_never_executed_bb_p): Invoke probably_never_executed.
+ (probably_never_executed_edge_p): Ditto.
+ * bb-reorder.c (find_rarely_executed_basic_blocks_and_crossing_edges):
+ Treat profile insanities conservatively.
+
+2013-10-02 John David Anglin <danglin@gcc.gnu.org>
+
+ * config.gcc (hppa*64*-*-linux*): Don't add pa/t-linux to tmake_file.
+
+2013-10-02 Vladimir Makarov <vmakarov@redhat.com>
+
+ * lra-constraints.c (process_alt_operand): Calculate scratch_p and
+ use it. Use smaller increase for scratch. Don't increase reject
+ for early clobber scratch.
+ * lra-eliminations.c (eliminate_regs_in_insn): Remove all insns
+ setting eliminated regs except setting fp from hfp.
+ (lra_eliminate): Check lra_insn_recog_data on NULL.
+
+2013-10-02 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ PR target/58587
+ * config/rs6000/rs6000-cpus.def (ISA_2_6_MASKS_SERVER): Turn off
+ setting -mvsx-timode by default until the underlying problem is fixed.
+ (RS6000_CPU, power7 defaults): Likewise.
+
+2013-10-02 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/x-linux (host-linux.o): Remove header dependencies.
+ Use $(COMPILE) and $(POSTCOMPILE).
+ * config/t-linux-android (linux-android.o): Ditto.
+
+2013-10-02 Uros Bizjak <ubizjak@gmail.com>
+
+ * Makefile.in (expmed.o-warn): Remove.
+
+2013-10-02 Andrew MacLeod <amacleod@redhat.com>
+
+ * graphite-scop-detection.c: Include tree-ssa-propagate,h.
+ * graphite-sese-to-poly.c: Include tree-ssa-propagate.h.
+
+2013-10-02 Teresa Johnson <tejohnson@google.com>
+
+ * dojump.c (do_jump_1): Divide probability between
+ both conditions of a TRUTH_ANDIF_EXPR/TRUTH_ORIF_EXPR.
+
+2013-10-02 Tom Tromey <tromey@redhat.com>
+
+ * Makefile.in (DRIVER_DEFINES): Use $(if), not $(and).
+
+2013-10-02 Andrew MacLeod <amacleod@redhat.com>
+
+ * tree-flow.h: Remove some prototypes.
+ * tree-ssa-dce.c (mark_virtual_operand_for_renaming,
+ mark_virtual_phi_result_for_renaming): Move to tree-into-ssa.c.
+ * tree-into-ssa.c (mark_virtual_operand_for_renaming,
+ mark_virtual_phi_result_for_renaming): Relocate here.
+ * tree-into-ssa.h: Add prototypes.
+ * tree-ssa-phiopt.c: (tree_ssa_phiopt_worker) Use
+ single_pred_before_succ_order.
+ (blocks_in_phiopt_order): Rename and move to cfganal.c.
+ (nonfreeing_call_p) Move to gimple.c.
+ * cfganal.c (single_pred_before_succ_order): Move and renamed from
+ tree-ssa-phiopt.c.
+ * basic-block.h (single_pred_before_succ_order): Add prototype.
+ * gimple.c (nonfreeing_call_p): Relocate here.
+ * gimple.h: Add prototype.
+ * tree-ssa-ifcombine.c: Include tree-ssa-phiopt.h.
+ * tree-ssa-dom.h: New file. Relocate prototypes here.
+ * tree-ssa.h: Include tree-ssa-dom.h.
+
+2013-10-02 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/x-i386 (driver-i386.o): Remove header dependencies.
+ Use $(COMPILE) and $(POSTCOMPILE).
+
+ * config/alpha/x-alpha (driver-alpha.o): Ditto.
+
+2013-10-02 Andrew MacLeod <amacleod@redhat.com>
+
+ * tree-flow.h: Remove some prototypes.
+ * gimple-fold.h: Add prototypes from gimple.h and tree-flow.h.
+ * tree-ssa-propagate.h: Relocate prototypes from tree-flow.h.
+ * tree-ssa-copy.c (may_propagate*, propagate_value, replace_exp,
+ propagate_tree_value*): Move from here to...
+ * tree-ssa-propagate.c (may_propagate*, propagate_value, replace_exp,
+ propagate_tree_value*): Relocate here.
+ * tree-ssa-propagate.h: Relocate prototypes from tree-flow.h.
+ * gimple.h: Include gimple-fold.h, move prototypes into gimple-fold.h.
+ * gimple-fold.c: Remove gimple-fold.h from include list.
+ * tree-vrp.c: Remove gimple-fold.h from include list.
+ * tree-ssa-sccvn.c: Remove gimple-fold.h from include list.
+ * tree-ssa-ccp.c: Remove gimple-fold.h from include list.
+ * tree-scalar-evolution.c: Add tree-ssa-propagate.h to include list.
+ * tree-ssa-pre.c: Add tree-ssa-propagate.h to include list.
+ * sese.c: Add tree-ssa-propagate.h to include list.
+
+2013-10-02 Richard Biener <rguenther@suse.de>
+
+ * tree-loop-distribution.c: Include tree-vectorizer.h for
+ find_loop_location.
+ (enum partition_kind): Remove PKIND_REDUCTION.
+ (struct partition_s): Remove has_writes member, add reduction_p member.
+ (partition_alloc): Adjust.
+ (partition_builtin_p): Likewise.
+ (partition_has_writes): Remove.
+ (partition_reduction_p): New function.
+ (partition_merge_into): Likewise.
+ (generate_code_for_partition): Commonize builtin partition
+ handling tail.
+ (rdg_cannot_recompute_vertex_p): Remove.
+ (already_processed_vertex_p): Likewise.
+ (rdg_flag_vertex): Do not set has_writes.
+ (classify_partition): Adjust.
+ (rdg_build_partitions): Do not set has_writes, treat all
+ partitions as useful.
+ (distribute_loop): Record number of library calls generated. Adjust.
+ (tree_loop_distribution): Report number of loops and library
+ calls generated as opt-info.
+
+2013-10-02 Andrew MacLeod <amacleod@redhat.com>
+
+ * tree-flow.h: Include new .h files. Move prototypes.
+ * tree-cfgcleanup.h: New file. Add prototypes from tree-flow.h.
+ * tree-dfa.h: New File. Add prototypes from tree-flow.h.
+ (get_addr_base_and_unit_offset_1) Move from tree-flow-inline.h.
+ * tree-pretty-print.h: Add prototypes from tree-flow.h.
+ * tree-into-ssa.h: New File. Add prototypes from tree-flow.h.
+ ({debug|dump}*): Move debugging prototypes out of tree-into-ssa.c.
+ * tree-into-ssa.c ({debug|dump}*): Move prototypes to header file.
+ * tree.h (get_ref_base_and_extent): Move prototype out.
+ * tree-flow-inline.h (get_addr_base_and_unit_offset_1): Move to
+ tree-dfa.h.
+ * gimple-low.h: New File. Add prototypes from tree-flow.h.
+ * gimple-low.c (try_catch_may_fallthru, block_may_fallthru): Move to...
+ * tree.c (try_catch_may_fallthru, block_may_fallthru): Here.
+ * tree-scalar-evolution.c: Include tree.h.
+ * sese.c: Include tree.h.
+ * dumpfile.c: Move gimple-pretty-print.h include after tree.h.
+ * dwarf2out.c: Include tree-dfa.h.
+ * tree-chrec.c: Include tree.h.
+ * tree-data-ref.c: Include tree.h.
+
+2013-10-02 Yufeng Zhang <yufeng.zhang@arm.com>
+
+ * gimple-ssa-strength-reduction.c (backtrace_base_for_ref):
+ Fix whitespace.
+
+2013-10-02 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * config/t-sol2 (sol2-c.o): Remove header dependencies.
+ Use $(COMPILE) and $(POSTCOMPILE).
+ (sol2-cxx.o): Likewise.
+ (sol2-stubs.o): Likewise.
+ (sol2.o): Likewise.
+ * config/x-solaris (host-solaris.o): Likewise.
+
+ * config/sparc/t-sparc (sparc.o): Remove.
+ (sparc-c.o): Remove header dependencies.
+ Use $(COMPILE) and $(POSTCOMPILE).
+ * config/sparc/x-sparc: Likewise.
+
+2013-10-02 Joern Rennecke <joern.rennecke@embecosm.com>
+
+ * config/arc/arc-opts.h: Add 2013 to Copyright years.
+ * config/arc/arc700.md: Likewise.
+ * config/arc/arc-modes.def: Likewise.
+ * config/arc/arc-simd.h: Likewise.
+ * config/arc/t-arc-uClibc: Likewise.
+ * config/arc/t-arc-newlib: Likewise.
+
+2013-10-02 Renlin Li <renlin.li@arm.com>
+
+ * config/aarch64/aarch64.c (aarch64_expand_prologue): Use
+ plus_constant.
+ (aarch64_expand_epilogue): Likewise.
+
+2013-10-02 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+ Yufeng Zhang <yufeng.zhang@arm.com>
+
+ * gimple-ssa-strength-reduction.c (legal_cast_p_1): Forward
+ declaration.
+ (backtrace_base_for_ref): Call get_unwidened with 'base_in' if
+ 'base_in' represent a conversion and legal_cast_p_1 holds; set
+ 'base_in' with the returned value from get_unwidened.
+
+2013-10-02 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * config/arm/arm.c (arm_legitimize_reload_address): Explain why
+ plus_constant is not used.
+
+2013-10-01 Wei Mi <wmi@google.com>
+
+ * config/i386/x86-tune.def (DEF_TUNE): Remove m_CORE_ALL.
+ * config/i386/i386.md: Add define_peephole2 to
+ break partial reg stall for cvtss2sd/cvtsd2ss.
+
+2013-10-01 Joern Rennecke <joern.rennecke@embecosm.com>
+
+ * config/arc/arc.c (pass_arc_ifcvt::clone):
+ Update for ctxt_ -> m_ctxt change.
+
+2013-10-01 Jeff Law <law@redhat.com>
+
+ * tree-ssa-threadupdate.c (struct redirection_data): Delete
+ outgoing_edge and intermediate_edge fields. Instead store the path.
+ (redirection_data::hash): Hash on the last edge's destination index.
+ (redirection_data::equal): Check the entire thread path.
+ (lookup_redirectio_data): Corresponding changes.
+ (create_edge_and_update_destination_phis): Likewise.
+ (thread_single_edge): Likewise.
+
+2013-10-01 Joern Rennecke <joern.rennecke@embecosm.com>
+ Diego Novillo <dnovillo@google.com>
+
+ * config/arc/simdext.md (UNSPEC_ARC_SIMD_VLD32WH): Delete.
+ (UNSPEC_ARC_SIMD_VLD32WL): Likewise.
+ (vld32wh_insn, vld32wl_insn): Delete commented-out old
+ versions of these patterns.
+
+ * doc/extend.texi (long_call/medium_call/short_call): Typo fix.
+ (__builtin_arc_aligned): Likewise.
+
+ * config/arc/arc.md: Expand adc_0 comment stating the intended
+ purpose and why it isn't ready.
+ Replace commented out call_value_via_label_mixed with a
+ plain comment about bl_s.
+
+ * config/arc/arc.c (stdio.h): Don't include directly.
+ (arc_expand_epilogue): Remove [0]: Remove fp_restored_p.
+ Remove if (1) condition.
+ (arc_encode_section_info): Fix comment.
+
+2013-10-01 Joern Rennecke <joern.rennecke@embecosm.com>
+
+ * config/arc/arc.c (arc_conditional_register_usage):
+ Use ARC_FIRST_SIMD_VR_REG / ARC_LAST_SIMD_VR_REG.
+ Also set reg_alloc_order for DMA config regs.
+
+2013-10-01 Joern Rennecke <joern.rennecke@embecosm.com>
+ Jeremy Bennett <jeremy.bennett@embecosm.com>
+
+ * doc/install.texi (--with-cpu): Mention ARC.
+ (arc-*-elf32): New paragraph.
+ (arc-linux-uclibc): Likewise.
+ * doc/md.texi (Machine Constraints): Add ARC part.
+ * doc/invoke.texi: (menu): Add ARC Options.
+ (Machine Dependent Options) <ARC Options>: Add synopsis.
+ (node ARC Options): Add.
+ * doc/extend.texi (long_call / short_call attribute): Add ARC.
+ (ARC Built-in Functions): New section defining
+ generic ARC built-in functions.
+ (ARC SIMD Built-in Functions): New section defining SIMD specific
+ built-in functions.
+ (Declaring Attributes of Functions): Extended
+ description of short_call and long_call attributes for ARC and
+ added index entries.
+
+2013-10-01 Saurabh Verma <saurabh.verma@codito.com>
+ Ramana Radhakrishnan <ramana.radhakrishnan@codito.com>
+ Joern Rennecke <joern.rennecke@embecosm.com>
+ Muhammad Khurram Riaz <khurram.riaz@arc.com>
+ Brendan Kehoe <brendan@zen.org>
+ Michael Eager <eager@eagercon.com>
+ Simon Cook <simon.cook@embecosm.com>
+ Jeremy Bennett <jeremy.bennett@embecosm.com>
+
+ * config/arc, common/config/arc: New directories.
+
+2013-10-01 Joern Rennecke <joern.rennecke@embecosm.com>
+ Brendan Kehoe <brendan@zen.org>
+ Simon Cook <simon.cook@embecosm.com>
+
+ * config.gcc (arc*-*-elf*, arc*-*-linux-uclibc*): New configurations.
+
+2013-10-01 Andrew MacLeod <amacleod@redhat.com>
+
+ * tree-ssa-live.h (coalesce_ssa_name): Move Prototype to...
+ * tree-ssa-coalesce.h: New. Move prototype to here.
+ * tree-outof-ssa.h: Include tree-ssa-coalesce.h.
+ * tree-ssa-coalesce.c: Include tree-outof-ssa.h.
+ (gimple_can_coalesce_p): Move to...
+ * gimple.c (gimple_can_coalesce_p): Here.
+
+2013-10-01 Andrew MacLeod <amacleod@redhat.com>
+
+ * tree-into-ssa.c (enum need_phi_state): Relocate from tree-flow.h.
+ (dump_decl_set): Move to gimple.c.
+ * gimple.h: Don't include tree-ssa-operands.h.
+ (dump_decl_set): Add prototype.
+ (gimple_vuse_op, gimple_vdef_op, update_stmt, update_stmt_if_modified):
+ Move to gimple-ssa.h.
+ (phi_ssa_name_p, phi_nodes, phi_nodes_ptr, gimple_phi_arg_def,
+ gimple_phi_arg_def_ptr, gimple_phi_arg_edge, gimple_phi_arg_location,
+ gimple_phi_arg_location_from_edge, gimple_phi_arg_set_location,
+ gimple_phi_arg_has_location): Relocate from tree-flow-inline.h
+ * gimple.c (walk_stmt_load_store_ops): Use gimple_phi_arg_def rather
+ than PHI_ARG_DEF.
+ (dump_decl_set): Relocate here.
+ * gimple-ssa.h: New file.
+ (gimple_vuse_op, gimple_vdef_op, update_stmt, update_stmt_if_modified):
+ Relocate from gimple.h.
+ * tree-cfg.c (has_zero_uses_1, single_imm_use_1): Move to...
+ * tree-ssa-operands.c (swap_ssa_operands): Rename from
+ swap_tree_operands and remove non-ssa path.
+ (has_zero_uses_1, single_imm_use_1): Relocate from tree-cfg.c.
+ * tree-ssa-reassoc.c (linearize_expr_tree, repropagate_negates): Use
+ swap_ssa_operands.
+ * tree-vect-loop.c (destroy_loop_vec_info, vect_is_slp_reduction,
+ vect_is_simple_reduction_1): Use swap_ssa_operands.
+ * tree-flow.h: Move various prototypes to tree-phinodes.h.
+ (enum need_phi_state): Move to tree-into-ssa.c.
+ (struct immediate_use_iterator_d, FOR_EACH_IMM_*,
+ BREAK_FROM_IMM_USE_STMT): Move to ssa-iterators.h.
+ (swap_tree_operands): Rename and move prototype to tree-ssa-operands.h.
+ * tree-flow-inline.h (delink_imm_use, link_imm_use_to_list,
+ link_imm_use, set_ssa_use_from_ptr, link_imm_use_stmt, relink_imm_use,
+ relink_imm_use_stmt, end_readonly_imm_use_p, first_readonly_imm_use,
+ next_readonly_imm_use, has_zero_uses, has_single_use, single_imm_use,
+ num_imm_uses): Move to ssa-iterators.h.
+ (get_use_from_ptr, get_def_from_ptr): Move to tree-ssa-operands.h
+ (gimple_phi_arg_imm_use_ptr, phi_arg_index_from_use): Move to
+ tree-phinodes.h.
+ (op_iter_done, op_iter_next_def, op_iter_next_tree,
+ clear_and_done_ssa_iter, op_iter_init, op_iter_init_use,
+ op_iter_init_def, op_iter_init_tree, single_ssa_tree_operand,
+ single_ssa_use_operand, single_ssa_def_operand, zero_ssa_operands,
+ num_ssa_operands, delink_stmt_imm_use, single_phi_def,
+ op_iter_init_phiuse, op_iter_init_phidef, end_imm_use_stmt_p,
+ end_imm_use_stmt_traverse, move_use_after_head, link_use_stmts_after,
+ first_imm_use_stmt, next_imm_use_stmt, first_imm_use_on_stmt,
+ end_imm_use_on_stmt_p, next_imm_use_on_stmt): Move to ssa-iterators.h.
+ (gimple_phi_arg_def, gimple_phi_arg_def_ptr, gimple_phi_arg_edge,
+ gimple_phi_arg_location, gimple_phi_arg_location_from_edge,
+ gimple_phi_arg_set_location, gimple_phi_arg_has_location, phi_nodes,
+ phi_nodes_ptr, phi_ssa_name_p): Move to gimple.h.
+ (set_phi_nodes): Move to tree-phinodes.h.
+ * tree-ssa-operands.h (enum ssa_op_iter_type,
+ struct ssa_operand_iterator_d, SSA_OP*, FOR_EACH_SSA*, SINGLE_SSA*,
+ ZERO_SSA_OPERANDS, NUM_SSA_OPERANDS): Move to ssa-iterators.h.
+ (dump_decl_set): Remove prototype.
+ (get_use_from_ptr, get_def_from_ptr): Relocate from tree-flow.h.
+ * tree-phinodes.h: New file. Move some prototypes from tree-flow.h.
+ (set_phi_nodes): Relocate from tree-flow-inline.h.
+ (gimple_phi_arg_imm_use_ptr, phi_arg_index_from_use): Relocate from
+ tree-flow-inline.h
+ * tree-ssa.h: Add tree-phinodes.h, gimple-ssa.h, ssa-iterators.h to
+ include list. Temporarily add gimple.h to include list.
+ * ssa-iterators.h: New file.
+ (struct immediate_use_iterator_d, FOR_EACH_IMM_*,
+ BREAK_FROM_IMM_USE_STMT): Relocate from tree-flow.h.
+ (enum ssa_op_iter_type, struct ssa_operand_iterator_d, SSA_OP*,
+ FOR_EACH_SSA*, SINGLE_SSA*, ZERO_SSA_OPERANDS, NUM_SSA_OPERANDS):
+ Relocate from tree-ssa-operands.h.
+ (delink_imm_use, link_imm_use_to_list, link_imm_use,
+ set_ssa_use_from_ptr, link_imm_use_stmt, relink_imm_use,
+ relink_imm_use_stmt, end_readonly_imm_use_p, first_readonly_imm_use,
+ next_readonly_imm_use, has_zero_uses, has_single_use, single_imm_use,
+ num_imm_uses, get_use_from_ptr, get_def_from_ptr,
+ phi_arg_index_from_use, op_iter_done, op_iter_next_def,
+ op_iter_next_tree, clear_and_done_ssa_iter, op_iter_init,
+ op_iter_init_use, op_iter_init_def, op_iter_init_tree,
+ single_ssa_tree_operand, single_ssa_use_operand, single_ssa_def_operand,
+ zero_ssa_operands, num_ssa_operands, delink_stmt_imm_use,
+ single_phi_def, op_iter_init_phiuse, op_iter_init_phidef,
+ end_imm_use_stmt_p, end_imm_use_stmt_traverse, move_use_after_head,
+ link_use_stmts_after, first_imm_use_stmt, next_imm_use_stmt,
+ first_imm_use_on_stmt, end_imm_use_on_stmt_p, next_imm_use_on_stmt):
+ Relocate from tree-flow-inline.h.
+ * tree-outof-ssa.h: Change _SSAEXPAND_H macro to GCC_TREE_OUTOF_SSA_H.
+
+2013-10-01 Vidya Praveen <vidyapraveen@arm.com>
+
+ * aarch64-simd.md
+ (aarch64_<ANY_EXTEND:su><ADDSUB:optab>l2<mode>_internal): Rename to ...
+ (aarch64_<ANY_EXTEND:su><ADDSUB:optab>l<mode>_hi_internal): ... this;
+ Insert '\t' to output template.
+ (aarch64_<ANY_EXTEND:su><ADDSUB:optab>l<mode>_lo_internal): New.
+ (aarch64_saddl2<mode>, aarch64_uaddl2<mode>): Modify to call
+ gen_aarch64_<ANY_EXTEND:su><ADDSUB:optab>l<mode>_hi_internal() instead.
+ (aarch64_ssubl2<mode>, aarch64_usubl2<mode>): Ditto.
+
+2013-10-01 Uros Bizjak <ubizjak@gmail.com>
+
+ * doc/install.texi (Host/target specific installation notes for GCC):
+ Put @anchor before @heading.
+ * doc/gcc.texi (titlepage): Use @uref and http:// prefix for website.
+ Use @email for email addresses.
+
+2013-10-01 Jeff Law <law@redhat.com>
+
+ * tree-ssa-threadedge.c (thread_across_edge): Make path a pointer to
+ a vec. Only delete the path if we create one without successfully
+ registering a jump thread.
+ * tree-ssa-threadupdate.h (register_jump_thread): Pass in path vector
+ as a pointer.
+ * tree-ssa-threadupdate.c (threaded_edges): Remove. No longer used
+ (paths): New vector of jump threading paths.
+ (THREAD_TARGET, THREAD_TARGET2): Remove accessor macros.
+ (THREAD_PATH): New accessor macro for the entire thread path.
+ (lookup_redirection_data): Get intermediate and final outgoing edge
+ from the thread path.
+ (create_edge_and_update_destination_phis): Copy the threading path.
+ (ssa_fix_duplicate_block_edges): Get edges and block types from the
+ jump threading path.
+ (ssa_redirect_edges): Get edges and block types from the jump threading
+ path. Free the path vector.
+ (thread_block): Get edges from the jump threading path. Look at the
+ entire path to see if we thread to a loop exit. If we cancel a jump
+ thread request, then free the path vector.
+ (thread_single_edge): Get edges and block types from the jump threading
+ path. Free the path vector.
+ (thread_through_loop_header): Get edges and block types from the jump
+ threading path. Free the path vector.
+ (mark_threaded_blocks): Iterate over the vector of paths and store
+ the path on the appropriate edge. Get edges and block types from the
+ jump threading path.
+ (mark_threaded_blocks): Get edges and block types from the jump
+ threading path. Free the path vector.
+ (thread_through_all_blocks): Use the vector of paths rather than
+ a vector of 3-edge sets.
+ (register_jump_thread): Accept pointer to a path vector rather
+ than the path vector itself. Store the path vector for later use.
+ Simplify.
+
+2013-10-01 Jakub Jelinek <jakub@redhat.com>
+ Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
+
+ PR target/58574
+ * config/s390/s390.c (s390_split_branches): Modify check for table
+ jump insns.
+ (s390_chunkify_start): Rearrange table jump insn check in order to
+ deal with compare and branch insns correctly.
+
+2013-10-01 Kugan Vivekanandarajah <kuganv@linaro.org>
+
+ PR target/58578
+ Revert
+ 2013-04-05 Greta Yorsh <Greta.Yorsh@arm.com>
+ * config/arm/arm.md (arm_ashldi3_1bit): define_insn into
+ define_insn_and_split.
+ (arm_ashrdi3_1bit,arm_lshrdi3_1bit): Likewise.
+ (shiftsi3_compare): New pattern.
+ (rrx): New pattern.
+ * config/arm/unspecs.md (UNSPEC_RRX): New.
+
+2013-10-01 Alan Modra <amodra@gmail.com>
+
+ * stmt.c (expand_asm_operands): Revert part of 2013-09-24 special
+ casing inout operands.
+
+2013-10-01 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/58553
+ * tree-loop-distribution.c (struct partition_s): Add niter member.
+ (classify_partition): Populate niter member for the partition
+ and properly identify whether the relevant store happens before
+ or after the loop exit.
+ (generate_memset_builtin): Use niter member from the partition.
+ (generate_memcpy_builtin): Likewise.
+
+2013-09-30 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * vec.h (vec_prefix, vec): Prefix member names with "m_".
+ * vec.c (vec_prefix::calculate_allocation): Update accordingly.
+
+2013-09-30 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * basic-block.h (edge_list): Prefix member names with "m_".
+ * context.h (context): Likewise.
+ * domwalk.h (dom_walker): Likewise.
+ * gengtype-state.c (s_expr_writer, state_writer): Likewise.
+ * graphite-sese-to-poly.c (sese_dom_walker): Likewise.
+ * hash-table.h (hash_table): Likewise.
+ * machmode.h (bit_field_mode_iterator): Likewise.
+ * pass_manager.h (pass_list): Likewise.
+ * tree-into-ssa.c (mark_def_dom_walker): Likewise.
+ * tree-pass.h (pass_data): Likewise.
+ * tree-ssa-dom.c (dom_opt_dom_walker): Likewise.
+ * tree-ssa-phiopt.c (nontrapping_dom_walker): Likewise,
+ * tree-ssa-uncprop.c (uncprop_dom_walker): Likewise.
+ * asan.c (pass_data_asan): Update accordingly.
+ * cfganal.c (control_dependences::find_control_dependence): Likewise.
+ (control_dependences::control_dependences): Likewise.
+ (control_dependences::~control_dependences): Likewise.
+ (control_dependences::~control_dependences): Likewise.
+ (control_dependences::get_edges_dependent_on): Likewise.
+ * cgraphbuild.c (pass_data_rebuild_cgraph_edges::clone): Likewise.
+ (pass_data_remove_cgraph_callee_edges::clone): Likewise.
+ * context.c (gcc::context::context): Likewise.
+ * cprop.c (pass_rtl_cprop::clone): Likewise.
+ * domwalk.c (dom_walker::walk): Likewise.
+ * ipa-inline-analysis.c (pass_inline_parameters::clone): Likewise.
+ * ipa-pure-const.c (pass_local_pure_const::clone): Likewise.
+ * mode-switching.c (pass_mode_switching::clone): Likewise.
+ * passes.c (opt_pass::opt_pass): Likewise.
+ (pass_manager::pass_manager): Likewise.
+ * predict.c (pass_strip_predict_hints::clone): Likewise.
+ * recog.c (pass_data pass_data_peephole2::clone): Likewise.
+ (pass_split_all_insns::clone): Likewise.
+ * stor-layout.c (bit_field_mode_iterator::bit_field_mode_iterator):
+ Likewise.
+ (bit_field_mode_iterator::next_mode): Likewise.
+ (bit_field_mode_iterator::prefer_smaller_modes): Likewise.
+ * tree-cfg.c (pass_split_crit_edges::clone): Likewise.
+ * tree-cfgcleanup.c (pass_merge_phi::clone): Likewise.
+ * tree-complex.c (pass_lower_complex::clone): Likewise.
+ * tree-eh.c (pass_cleanup_eh::clone): Likewise.
+ * tree-object-size.c (pass_object_sizes::clone): Likewise.
+ * tree-optimize.c (pass_fixup_cfg::clone): Likewise.
+ * tree-ssa-ccp.c (pass_data_ccp::clone): Likewise.
+ (pass_fold_builtins::clone): Likewise.
+ * tree-ssa-copy.c (pass_data_copy_prop::clone): Likewise.
+ * tree-ssa-copyrename.c (pass_rename_ssa_copies::clone): Likewise.
+ * tree-ssa-dce.c (pass_dce::clone, pass_dce_loop::clone): Likewise.
+ (pass_cd_dce::clone): Likewise.
+ * tree-ssa-dom.c (pass_dominator::clone): Likewise.
+ (pass_phi_only_cprop::clone): Likewise.
+ * tree-ssa-dse.c (pass_dse::clone): Likewise.
+ * tree-ssa-forwprop.c (pass_forwprop::clone): Likewise.
+ * tree-ssa-loop.c (pass_lim::clone): Likewise.
+ * tree-ssa-phiopt.c (pass_phiopt::clone): Likewise.
+ * tree-ssa-pre.c (pass_fre::clone): Likewise.
+ * tree-ssa-reassoc.c (pass_reassoc::clone): Likewise.
+ * tree-ssa-uninit.c (pass_late_warn_uninitialized::clone): Likewise.
+ * tree-tailcall.c (pass_tail_recursion::clone): Likewise.
+ * tree-vect-generic.c (pass_lower_vector_ssa::clone): Likewise.
+ * tree-vrp.c (pass_vrp::clone): Likewise.
+ * tsan.c (pass_tsan::clone): Likewise.
+
+2013-09-30 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/58564
+ * fold-const.c (tree_unary_nonnegative_warnv_p): Use
+ INTEGRAL_TYPE_P (t) instead of TREE_CODE (t) == INTEGER_TYPE.
+
+ PR middle-end/58564
+ * fold-const.c (fold_ternary_loc): For A < 0 : <sign bit of A> : 0
+ optimization, punt if sign_bit_p looked through any zero extension.
+
+2013-09-30 Teresa Johnson <tejohnson@google.com>
+
+ * tree-ssa-threadupdate.c (ssa_fix_duplicate_block_edges):
+ Update redirected out edge count in joiner case.
+ (ssa_redirect_edges): Common the joiner and non-joiner cases
+ so that joiner case gets profile updates.
+
+2013-09-30 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/58554
+ * tree-loop-distribution.c (classify_partition): Require
+ unconditionally executed stores for memcpy and memset recognition.
+ (tree_loop_distribution): Calculate dominance info.
+
+2013-09-30 Venkataramanan Kumar <venkataramanan.kumar@linaro.org>
+
+ * config/aarch64/aarch64.h (MCOUNT_NAME): Define.
+ (NO_PROFILE_COUNTERS): Likewise.
+ (PROFILE_HOOK): Likewise.
+ (FUNCTION_PROFILER): Likewise.
+ * config/aarch64/aarch64.c (aarch64_function_profiler): Remove.
+
+2013-09-30 Iain Sandoe <iain@codesourcery.com>
+
+ * config/rs6000/darwin.md (load_macho_picbase_si): Wrap machopic
+ calls and defines in TARGET_MACHO conditional.
+ (load_macho_picbase_di): Likewise.
+ (reload_macho_picbase): Likewise.
+ (reload_macho_picbase_si): Likewise.
+ (reload_macho_picbase_di): Likewise.
+ (nonlocal_goto_receiver): Likewise.
+
+2013-09-30 Nick Clifton <nickc@redhat.com>
+
+ * config/msp430/msp430.c (msp430x_names): New array. Lists MCUs
+ that use the MSP430X ISA.
+ (msp430_option_override): Scan -mmcu command line option for any
+ MCU name that supports the MSP430X ISA.
+ * config/msp430/t-msp430 (MULTILIB_MATCHES): Add matches for known
+ -mmcu options which enable the MSP430X ISA.
+
+2013-09-30 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/58532
+ * tree-cfg.c (make_abnormal_goto_edges): Skip debug statements
+ before looking for setjmp-like calls.
+
+2013-09-29 Iain Sandoe <iain@codesourcery.com>
+
+ PR target/10901
+ * config/darwin-protos.h (machopic_get_function_picbase): New.
+ * config/darwin.c (machopic_get_function_picbase): New.
+ * config/rs6000/darwin.md (load_macho_picbase_si): Update picbase
+ label for a new func. (load_macho_picbase_di): Likewise.
+ (reload_macho_picbase): New expand.
+ (reload_macho_picbase_si): New insn.
+ (reload_macho_picbase_di): New insn.
+ (nonlocal_goto_receiver): New define and split.
+ * config/rs6000/rs6000.md (unspec enum): Add UNSPEC_RELD_MPIC.
+ (unspecv enum): Add UNSPECV_NLGR.
+
+2013-09-29 Iain Sandoe <iain@codesourcery.com>
+
+ * config/rs6000/rs6000.c (rs6000_init_dwarf_reg_sizes_extra): Ensure
+ that altivec registers are correctly sized on Darwin.
+
+2013-09-29 Iain Sandoe <iain@codesourcery.com>
+
+ * config/t-darwin (darwin.o, darwin-c.o, darwin-f.o,
+ darwin-driver.o): Use COMPILE and POSTCOMPILE.
+ * config/x-darwin (host-darwin.o): Likewise.
+ * config/i386/x-darwin (host-i386-darwin.o): Likewise.
+ * config/rs6000/x-darwin (host-ppc-darwin.o): Likewise.
+ * config/rs6000/x-darwin64 (host-ppc64-darwin.o): Likewise.
+
+2013-09-29 Uros Bizjak <ubizjak@gmail.com>
+
+ * doc/invoke.texi: Fix usage of @tie{} command.
+
+2013-09-29 Eric Botcazou <ebotcazou@adacore.com>
+
+ * config/sparc/sync.md: Add peephole for consecutive memory barriers.
+
+2013-09-28 Jan Hubicka <jh@suse.cz>
+
+ * config/i386/x86-tune.def: Add documentation for each of the options;
+ add whitespace.
+
+2013-09-28 Jan Hubicka <jh@suse.cz>
+
+ * x86-tune.def (X86_TUNE_SSE_UNALIGNED_LOAD_OPTIMAL): Enable for
+ generic.
+ (X86_TUNE_SSE_UNALIGNED_STORE_OPTIMAL): Likewise.
+ (X86_TUNE_FOUR_JUMP_LIMIT): Drop for generic and buldozer.
+ (X86_TUNE_PAD_RETURNS): Drop for buldozer chips.
+ (X86_TUNE_AVOID_VECTOR_DECODE): Drop for generic.
+ (X86_TUNE_REASSOC_FP_TO_PARALLEL): Enable for generic.
+
+2013-09-28 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * alloc-pool.c, asan.c, auto-inc-dec.c, basic-block.h, bb-reorder.c,
+ bitmap.c, bitmap.h, bt-load.c, builtins.c, calls.c, cfgcleanup.c,
+ cfgexpand.c, cfghooks.c, cfgloop.c, cfgloopmanip.c, cfgrtl.c, cgraph.c,
+ cgraph.h, cgraphbuild.c, cgraphclones.c, cgraphunit.c, collect2.c,
+ combine-stack-adj.c, combine.c, compare-elim.c, context.c, context.h,
+ cprop.c, cse.c, cselib.c, dbxout.c, dce.c, defaults.h, df-core.c,
+ df-problems.c, df-scan.c, df.h, diagnostic.c, double-int.c, dse.c,
+ dumpfile.c, dwarf2asm.c, dwarf2cfi.c, dwarf2out.c, emit-rtl.c,
+ errors.c, except.c, expmed.c, expr.c, file-find.c, final.c,
+ fixed-value.c, fold-const.c, function.c, fwprop.c, gcc-ar.c, gcc.c,
+ gcov-io.c, gcov-io.h, gcov.c, gcse.c, genattr-common.c, genattr.c,
+ genattrtab.c, genautomata.c, genconfig.c, genemit.c, genextract.c,
+ genflags.c, gengenrtl.c, gengtype-state.c, gengtype.c, genmodes.c,
+ genopinit.c, genoutput.c, genpeep.c, genpreds.c, genrecog.c,
+ gensupport.c, ggc-common.c, ggc-page.c, gimple-fold.c, gimple-low.c,
+ gimple-pretty-print.c, gimple-ssa-strength-reduction.c, gimple.c,
+ gimple.h, godump.c, graphite-clast-to-gimple.c,
+ graphite-optimize-isl.c, graphite-poly.h, graphite-sese-to-poly.c,
+ graphite.c, haifa-sched.c, hash-table.c, hash-table.h, hwint.c,
+ hwint.h, ifcvt.c, incpath.c, init-regs.c, input.h, intl.c, intl.h,
+ ipa-cp.c, ipa-devirt.c, ipa-inline-analysis.c, ipa-inline.c,
+ ipa-profile.c, ipa-pure-const.c, ipa-reference.c, ipa-split.c,
+ ipa-utils.c, ipa.c, ira-build.c, ira.c, jump.c, loop-doloop.c,
+ loop-init.c, loop-invariant.c, loop-iv.c, lower-subreg.c, lto-cgraph.c,
+ lto-streamer-in.c, lto-streamer-out.c, lto-wrapper.c, mcf.c,
+ mode-switching.c, modulo-sched.c, omp-low.c, optabs.c, opts.c,
+ pass_manager.h, passes.c, plugin.c, postreload-gcse.c, postreload.c,
+ predict.c, prefix.c, pretty-print.c, print-rtl.c, print-tree.c,
+ profile.c, read-md.c, real.c, real.h, recog.c, ree.c, reg-stack.c,
+ regcprop.c, reginfo.c, regmove.c, regrename.c, regs.h, regstat.c,
+ reload1.c, reorg.c, rtl.c, rtl.h, rtlanal.c, sbitmap.c, sched-rgn.c,
+ sdbout.c, sel-sched-ir.c, sel-sched.c, sparseset.c, stack-ptr-mod.c,
+ statistics.c, stmt.c, stor-layout.c, store-motion.c, streamer-hooks.h,
+ system.h, target-hooks-macros.h, targhooks.c, targhooks.h, toplev.c,
+ tracer.c, trans-mem.c, tree-browser.c, tree-call-cdce.c, tree-cfg.c,
+ tree-cfgcleanup.c, tree-complex.c, tree-data-ref.c, tree-data-ref.h,
+ tree-eh.c, tree-emutls.c, tree-flow.h, tree-if-conv.c, tree-into-ssa.c,
+ tree-iterator.c, tree-loop-distribution.c, tree-mudflap.c,
+ tree-nested.c, tree-nomudflap.c, tree-nrv.c, tree-object-size.c,
+ tree-optimize.c, tree-pass.h, tree-pretty-print.c, tree-profile.c,
+ tree-scalar-evolution.c, tree-sra.c, tree-ssa-ccp.c,
+ tree-ssa-coalesce.c, tree-ssa-copy.c, tree-ssa-copyrename.c,
+ tree-ssa-dce.c, tree-ssa-dom.c, tree-ssa-dse.c, tree-ssa-forwprop.c,
+ tree-ssa-ifcombine.c, tree-ssa-live.c, tree-ssa-loop-ch.c,
+ tree-ssa-loop-im.c, tree-ssa-loop-ivopts.c, tree-ssa-loop-prefetch.c,
+ tree-ssa-loop.c, tree-ssa-math-opts.c, tree-ssa-operands.c,
+ tree-ssa-phiopt.c, tree-ssa-phiprop.c, tree-ssa-pre.c,
+ tree-ssa-reassoc.c, tree-ssa-sink.c, tree-ssa-strlen.c,
+ tree-ssa-structalias.c, tree-ssa-threadedge.c, tree-ssa-threadupdate.c,
+ tree-ssa-uncprop.c, tree-ssa-uninit.c, tree-ssa.c, tree-ssanames.c,
+ tree-stdarg.c, tree-switch-conversion.c, tree-tailcall.c,
+ tree-vect-data-refs.c, tree-vect-generic.c, tree-vect-loop-manip.c,
+ tree-vect-stmts.c, tree-vectorizer.c, tree-vectorizer.h, tree-vrp.c,
+ tree.c, tree.h, tsan.c, tsystem.h, value-prof.c, var-tracking.c,
+ varasm.c, vec.h, vmsdbgout.c, vtable-verify.c, web.c: Add missing
+ whitespace before "(".
+
+2013-09-28 Sandra Loosemore <sandra@codesourcery.com>
+
+ * expr.h (extract_bit_field): Remove packedp parameter.
+ * expmed.c (extract_fixed_bit_field): Remove packedp parameter
+ from forward declaration.
+ (store_split_bit_field): Remove packedp arg from calls to
+ extract_fixed_bit_field.
+ (extract_bit_field_1): Remove packedp parameter and packedp
+ argument from recursive calls and calls to extract_fixed_bit_field.
+ (extract_bit_field): Remove packedp parameter and corresponding
+ arg to extract_bit_field_1.
+ (extract_fixed_bit_field): Remove packedp parameter. Remove code
+ to issue warnings.
+ (extract_split_bit_field): Remove packedp arg from call to
+ extract_fixed_bit_field.
+ * expr.c (emit_group_load_1): Adjust calls to extract_bit_field.
+ (copy_blkmode_from_reg): Likewise.
+ (copy_blkmode_to_reg): Likewise.
+ (read_complex_part): Likewise.
+ (store_field): Likewise.
+ (expand_expr_real_1): Likewise.
+ * calls.c (store_unaligned_arguments_into_pseudos): Adjust call
+ to extract_bit_field.
+ * config/tilegx/tilegx.c (tilegx_expand_unaligned_load): Adjust
+ call to extract_bit_field.
+ * config/tilepro/tilepro.c (tilepro_expand_unaligned_load): Adjust
+ call to extract_bit_field.
+ * doc/invoke.texi (Code Gen Options): Remove mention of warnings
+ and special packedp behavior from -fstrict-volatile-bitfields
+ documentation.
+
+2013-09-27 Jan-Benedict Glaw <jbglaw@lug-owl.de>
+
+ * lra-eliminations.c (init_elim_table): Guard value_p.
+
+2013-09-27 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * config/rs6000/rs6000.c (rs6000_hard_regno_mode_ok): Allow
+ DFmode, DImode, and SFmode in the upper VSX registers based on the
+ -mupper-regs-{df,sf} flags. Fix wu constraint to be ALTIVEC_REGS
+ if -mpower8-vector. Combine -mvsx-timode handling with the rest
+ of the VSX register handling.
+
+ * config/rs6000/rs6000.md (f32_lv): Use %x0 for VSX regsters.
+ (f32_sv): Likewise.
+ (zero_extendsidi2_lfiwzx): Add support for loading into the
+ Altivec registers with -mpower8-vector. Use wu/wv constraints to
+ only do VSX memory options on Altivec registers.
+ (extendsidi2_lfiwax): Likewise.
+ (extendsfdf2_fpr): Likewise.
+ (mov<mode>_hardfloat, SF/SD modes): Likewise.
+ (mov<mode>_hardfloat32, DF/DD modes): Likewise.
+ (mov<mode>_hardfloat64, DF/DD modes): Likewise.
+ (movdi_internal64): Likewise.
+
+2013-09-27 Xinliang David Li <davidxl@google.com>
+
+ * opts.c (finish_options): Adjust parameters
+ according to vect cost model.
+ (common_handle_option): Set dynamic vect cost
+ model for FDO.
+ targhooks.c (default_add_stmt_cost): Compute stmt cost
+ unconditionally.
+ * tree-vect-loop.c (vect_estimate_min_profitable_iters):
+ Use helper function.
+ * tree-vectorizer.h (unlimited_cost_model): New function.
+ * tree-vect-slp.c (vect_slp_analyze_bb_1): Use helper function.
+ * tree-vect-data-refs.c (vect_peeling_hash_insert): Use helper
+ function.
+ (vect_enhance_data_refs_alignment): Ditto.
+ * flag-types.h: New enum.
+ * common/config/i386/i386-common.c (ix86_option_init_struct):
+ No need to initialize vect_cost_model flag.
+ * config/i386/i386.c (ix86_add_stmt_cost): Compute stmt cost
+ unconditionally.
+
+2013-09-27 Diego Novillo <dnovillo@google.com>
+
+ * gimple.h (enum ssa_mode): Remove.
+
+2013-09-27 Paulo Matos <pmatos@broadcom.com>
+
+ * cfgloop.h (number_of_loops): Fix typo in check for null.
+
+2013-09-27 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/58551
+ * tree-cfg.c (move_sese_region_to_fn): Also move loops that
+ are children of outermost saved_cfun's loop, and set it up to
+ be moved to dest_cfun's outermost loop. Fix up num_nodes adjustments
+ if loop != loop0 and SESE region contains bbs that belong to loop0.
+
+2013-09-27 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * rtlanal.c (must_be_base_p, must_be_index_p): Delete.
+ (binary_scale_code_p, get_base_term, get_index_term): New functions.
+ (set_address_segment, set_address_base, set_address_index)
+ (set_address_disp): Accept the argument unconditionally.
+ (baseness): Remove must_be_base_p and must_be_index_p checks.
+ (decompose_normal_address): Classify as much as possible in the
+ main loop.
+
+2013-09-27 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * cse.c (count_reg_usage): Handle INT_LIST.
+ * lra-eliminations.c (lra_eliminate_regs_1): Likewise.
+ * reginfo.c (reg_scan_mark_refs): Likewise.
+ * reload1.c (eliminate_regs_1): Likewise.
+
+2013-09-27 Iain Sandoe <iain@codesourcery.com>
+
+ PR middle-end/58547
+ * rtlanal.c (lsb_bitfield_op_p): Make both parts of the comparison
+ signed.
+
+2013-09-27 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/58459
+ * tree-ssa-forwprop.c (forward_propagate_addr_expr): Remove
+ restriction not propagating into loops.
+
+2013-09-26 Florian Weimer <fw@deneb.enyo.de>
+
+ * tree-ssa.h (walk_use_def_chains_fn, walk_use_def_chains): Delete.
+ * tree-ssa.c (walk_use_def_chains_1, walk_use_def_chains): Delete.
+ * doc/tree-ssa.texi (Walking use-def chains): Delete.
+
+2013-09-26 Richard Biener <rguenther@suse.de>
+
+ * tree-into-ssa.c (rewrite_into_ssa): Make more SSA names to anonymous.
+
+2013-09-26 Richard Biener <rguenther@suse.de>
+
+ * alias.h (component_uses_parent_alias_set): Rename to ...
+ (component_uses_parent_alias_set_from): ... this.
+ * alias.c (component_uses_parent_alias_set): Rename to ...
+ (component_uses_parent_alias_set_from): ... this and return
+ the desired parent.
+ (reference_alias_ptr_type_1): Use the result from
+ component_uses_parent_alias_set_from instead of stripping
+ components one at a time.
+ * emit-rtl.c (set_mem_attributes_minus_bitpos): Adjust.
+
+2013-09-26 Andrew MacLeod <amacleod@redhat.com>
+
+ * tree-ssa-live.h (find_replaceable_exprs, dump_replaceable_exprs):
+ Move prototypes to...
+ * tree-ssa-ter.h: New File. Move prototypes here.
+ * tree-flow.h (stmt_is_replaceable_p): Remove prototype.
+ * tree-outof-ssa.h: New. Rename ssaexpand.h, include tree-ssa-ter.h.
+ * tree-outof-ssa.c (ssa_is_replaceable_p): New. Refactor common bits
+ from is_replaceable_p.
+ * tree-ssa-ter.c (is_replaceable_p, stmt_is_replaceable_p): Delete.
+ (ter_is_replaceable_p): New. Use new refactored ssa_is_replaceable_p.
+ (process_replaceable): Use ter_is_replaceable_p.
+ (find_replaceable_in_bb): Use ter_is_replaceable_p.
+ * expr.c (stmt_is_replaceable_p): Relocate from tree-ssa-ter.c. Use
+ newly refactored ssa_is_replaceable_p.
+ * cfgexpand.c: Include tree-outof-ssa.h.
+ * ssaexpand.h: Delete.
+
+2013-09-26 Andrew MacLeod <amacleod@redhat.com>
+
+ * gimple.c (gimple_replace_lhs): Move to tree-ssa.c and rename.
+ (struct count_ptr_d, count_ptr_derefs, count_uses_and_derefs): Move to
+ tree-ssa.c
+ (create_gimple_tmp): Delete.
+ (get_expr_type, build_assign, build_type_cast): Move to...
+ * gimple-builder.c: New File.
+ (get_expr_type): Relocate from gimple.c.
+ (build_assign, build_type_cast): Change to only create ssanames.
+ * gimple.h: Move prototypes to...
+ * gimple-builder.h: New File. Here.
+ * tree-ssa.h: And here.
+ * tree-ssa.c (struct count_ptr_d, count_ptr_derefs,
+ count_uses_and_derefs): Relocate from gimple.c.
+ (gimple_replace_ssa_lhs): Renamed gimple_replace_ssa from gimple.c
+ * tree-ssa-reassoc.c (repropagate_negates): Use gimple_replace_ssa_lhs.
+ * tree-ssa-math-opts (execute_cse_reciprocals): Use
+ gimple_replace_ssa_lhs.
+ * asan.c: Include gimple-builder.h.
+ * Makefile.in: Add gimple-builder.o.
+
+2013-09-26 Richard Biener <rguenther@suse.de>
+
+ * tree-ssa-live.c (var_map_base_init): Handle SSA names with
+ DECL_IGNORED_P base VAR_DECLs like anonymous SSA names.
+ (loe_visit_block): Use gcc_checking_assert.
+ * tree-ssa-coalesce.c (create_outofssa_var_map): Use
+ gimple_assign_ssa_name_copy_p.
+ (gimple_can_coalesce_p): Adjust according to the var_map_base_init
+ change.
+
+2013-09-26 David Edelsohn <dje.gcc@gmail.com>
+
+ * config/rs6000/t-rs6000 (rs6000.o): Remove.
+ (rs6000-c.o): Use COMPILE and POSTCOMPILE.
+
+2013-09-26 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/58539
+ * tree-vect-loop.c (vect_create_epilog_for_reduction): Honor
+ the fact that debug statements are not taking part in loop-closed
+ SSA construction.
+
+2013-09-26 Nick Clifton <nickc@redhat.com>
+
+ * config/msp430/msp430.c (msp430_expand_epilogue): Fix compile
+ time warning message.
+ (msp430_print_operand_raw): Delete unused letter parameter.
+ (TARGET_PRINT_OPERAND_ADDRESS): Define.
+ (msp430_print_operand_address): New function.
+ (msp430_print_operand): Move address printing code from here to
+ new function.
+ * config/msp430/msp430.md (movsipsi2): Add comment in generated
+ assembler.
+ (zero_extendpsisi2): Likewise.
+ (extendpsisi2): New pattern.
+ (andneghi3): New pattern.
+
+2013-09-26 Yvan Roux <yvan.roux@linaro.org>
+
+ * config/aarch64/aarch64.opt (mlra): New option.
+ * config/aarch64/aarch64.c (aarch64_lra_p): New function.
+ (TARGET_LRA_P): Define.
+
+2013-09-26 Eric Botcazou <ebotcazou@adacore.com>
+
+ * expr.c (expand_assignment): Remove obsolete comment.
+
+2013-09-25 Jeff Law <law@redhat.com>
+
+ * tree-flow.h (thread_through_all_blocks): Prototype moved into
+ tree-ssa-threadupdate.h.
+ (register_jump_thread): Similarly.
+ * tree-ssa-threadupdate.h: New header file.
+ * tree-ssa-dom.c: Include tree-ssa-threadupdate.h.
+ * tree-vrp.c: Likewise.
+ * tree-ssa-threadedge.c: Include tree-ssa-threadupdate.h.
+ (thread_around_empty_blocks): Change type of path vector argument to
+ an edge,type pair from just an edge. Initialize both elements when
+ appending to a jump threading path. Tweak references to elements
+ appropriately.
+ (thread_across_edge): Similarly. Release memory for the elements
+ as needed.
+ * tree-ssa-threadupdate.c: Include tree-ssa-threadupdate.h.
+ (dump_jump_thread_path): New function broken out from
+ register_jump_thread.
+ (register_jump_thread): Use dump_jump_thread_path. Change type of
+ path vector entries. Search the path for NULL edges and dump
+ the path if one is found. Tweak the conversion of path to 3-edge
+ form to use the block copy type information embedded in the path.
+
+2013-09-25 Yvan Roux <yvan.roux@linaro.org>
+
+ * lra.c (update_inc_notes): Remove all REG_DEAD and REG_UNUSED notes.
+
+2013-09-25 Yvan Roux <yvan.roux@linaro.org>
+ Vladimir Makarov <vmakarov@redhat.com>
+
+ * rtlanal.c (lsb_bitfield_op_p): New predicate for bitfield operations
+ from the least significant bit.
+ (strip_address_mutations): Add bitfield operations handling.
+ (must_be_index_p): Add shifting and rotate operations handling.
+ (set_address_base): Use must_be_base_p predicate.
+ (set_address_index): Use must_be_index_p predicate.
+
+2013-09-25 Alexander Ivchenko <alexander.ivchenko@intel.com>
+ Maxim Kuznetsov <maxim.kuznetsov@intel.com>
+ Sergey Lega <sergey.s.lega@intel.com>
+ Anna Tikhonova <anna.tikhonova@intel.com>
+ Ilya Tocar <ilya.tocar@intel.com>
+ Andrey Turetskiy <andrey.turetskiy@intel.com>
+ Ilya Verbin <ilya.verbin@intel.com>
+ Kirill Yukhin <kirill.yukhin@intel.com>
+ Michael Zolotukhin <michael.v.zolotukhin@intel.com>
+
+ * config/i386/i386.c (ix86_avx256_split_vector_move_misalign):
+ Use new names.
+ (ix86_expand_vector_move_misalign): Support new unaligned load and
+ stores and use new names.
+ (CODE_FOR_sse2_storedqu): Rename to ...
+ (CODE_FOR_sse2_storedquv16qi): ... this.
+ (CODE_FOR_sse2_loaddqu): Rename to ...
+ (CODE_FOR_sse2_loaddquv16qi): ... this.
+ (CODE_FOR_avx_loaddqu256): Rename to ...
+ (CODE_FOR_avx_loaddquv32qi): ... this.
+ (CODE_FOR_avx_storedqu256): Rename to ...
+ (CODE_FOR_avx_storedquv32qi): ... this.
+ * config/i386/i386.md (fpint_logic): New.
+ * config/i386/sse.md (VMOVE): Extend for AVX512.
+ (VF): Ditto.
+ (VF_128_256): New.
+ (VF_512): Ditto.
+ (VI_UNALIGNED_LOADSTORE): Ditto.
+ (sse2_avx_avx512f): Ditto.
+ (sse2_avx2): Extend for AVX512.
+ (sse4_1_avx2): Ditto.
+ (avx2_avx512f): New.
+ (sse): Extend for AVX512.
+ (sse2): Ditto.
+ (sse4_1): Ditto.
+ (avxsizesuffix): Ditto.
+ (sseintvecmode): Ditto.
+ (ssePSmode): Ditto.
+ (<sse>_loadu<ssemodesuffix><avxsizesuffix>): Ditto.
+ (<sse>_storeu<ssemodesuffix><avxsizesuffix>): Ditto.
+ (<sse2>_loaddqu<avxsizesuffix>): Extend for AVX512 and rename to ...
+ (<sse2_avx_avx512f>_loaddqu<mode>): ... this.
+ (<sse2>_storedqu<avxsizesuffix>): Extend for AVX512 and rename to ...
+ (<sse2_avx_avx512f>_storedqu<mode): ... this.
+ (<sse>_movnt<mode>): Replace constraint "x" with "v".
+ (STORENT_MODE): Extend for AVX512.
+ (*absneg<mode>2): Replace constraint "x" with "v".
+ (*mul<mode>3): Ditto.
+ (*ieee_smin<mode>3): Ditto.
+ (*ieee_smax<mode>3): Ditto.
+ (avx_cmp<mode>3): Replace VF with VF_128_256.
+ (*<sse>_maskcmp<mode>3_comm): Ditto.
+ (<sse>_maskcmp<mode>3): Ditto.
+ (<sse>_andnot<mode>3): Extend for AVX512.
+ (<code><mode>3, anylogic): Replace VF with VF_128_256.
+ (<code><mode>3, fpint_logic): New.
+ (*<code><mode>3): Extend for AVX512.
+ (avx512flogicsuff): New.
+ (avx512f_<logic><mode>): Ditto.
+ (<sse>_movmsk<ssemodesuffix><avxsizesuffix>): Replace VF with
+ VF_128_256.
+ (<sse4_1>_blend<ssemodesuffix><avxsizesuffix>): Ditto.
+ (<sse4_1>_blendv<ssemodesuffix><avxsizesuffix>): Ditto.
+ (<sse4_1>_dp<ssemodesuffix><avxsizesuffix>): Ditto.
+ (avx_vtest<ssemodesuffix><avxsizesuffix>): Ditto.
+ (<sse4_1>_round<ssemodesuffix><avxsizesuffix>): Ditto.
+ (xop_vpermil2<mode>3): Ditto.
+ (*avx_vpermilp<mode>): Extend for AVX512 and rename to ...
+ (*<sse2_avx_avx512f>_vpermilp<mode>): ... this.
+ (avx_vpermilvar<mode>3): Extend for AVX512 and rename to ...
+ (<sse2_avx_avx512f>_vpermilvar<mode>3): ... this.
+
+2013-09-25 Tom Tromey <tromey@redhat.com>
+
+ * Makefile.in (PARTITION_H, LTO_SYMTAB_H, COMMON_TARGET_DEF_H)
+ (RTL_ERROR_H, TRANS_MEM_H, COVERAGE_H, DEMANGLE_H, ALIAS_H)
+ (SCHED_INT_H, SEL_SCHED_IR_H, SEL_SCHED_DUMP_H, VALTRACK_H, DDG_H)
+ (GGC_INTERNAL_H, DECNUM_H, BACKTRACE_H, MKDEPS_H, TREE_HASHER_H)
+ (TREE_SSA_LIVE_H, SSAEXPAND_H, DWARF2OUT_H, SCEV_H, OMEGA_H)
+ (TREE_DATA_REF_H, IRA_INT_H, LRA_INT_H, DBGCNT_H, DATA_STREAMER_H)
+ (GIMPLE_STREAMER_H, TREE_STREAMER_H, STREAMER_HOOKS_H)
+ (TREE_VECTORIZER_H, IPA_INLINE_H, GSTAB_H, LIBFUNCS_H)
+ (GRAPHITE_HTAB_H): Remove.
+
+2013-09-25 Tom Tromey <tromey@redhat.com>
+
+ * config/mcore/t-mcore (CROSS_FLOAT_H): Remove.
+
+2013-09-25 Tom Tromey <tromey@redhat.com>
+
+ * config/t-glibc (glibc-c.o): Use COMPILE and POSTCOMPILE.
+
+2013-09-25 Tom Tromey <tromey@redhat.com>
+
+ * config/i386/t-i386 (i386.o): Remove.
+ (i386-c.o): Use COMPILE and POSTCOMPILE.
+
+2013-09-25 Tom Tromey <tromey@redhat.com>
+
+ * Makefile.in ($(out_object_file)): Use COMPILE and POSTCOMPILE.
+
+2013-09-25 Tom Tromey <tromey@redhat.com>
+
+ * Makefile.in (graph.o, sbitmap.o, sparseset.o, gcc-ar.o)
+ (gcc-ranlib.o, gcc-nm.o, collect2.o, collect2-aix.o, tlink.o)
+ (lto-wrapper.o, default-c.o, attribs.o, incpath.o, prefix.o)
+ (gcc.o, options.o, options-save.o, version.o, gtype-desc.o)
+ (trans-mem.o, ggc-common.o, ggc-page.o, ggc-none.o, stringpool.o)
+ (convert.o, double-int.o, lto-compress.o, data-streamer-in.o)
+ (data-streamer-out.o, data-streamer.o, gimple-streamer-in.o)
+ (gimple-streamer-out.o, tree-streamer.o, tree-streamer-in.o)
+ (tree-streamer-out.o, streamer-hooks.o, lto-cgraph.o)
+ (lto-streamer-in.o, lto-streamer-out.o, lto-section-in.o)
+ (lto-section-out.o, lto-opts.o, lto-streamer.o, langhooks.o)
+ (test-dump.o, tree.o, tree-dump.o, tree-inline.o, print-tree.o)
+ (stor-layout.o, asan.o, tsan.o, ubsan.o, tree-ssa-tail-merge.o)
+ (tree-ssa-structalias.o, tree-ssa-uninit.o, tree-ssa.o)
+ (tree-into-ssa.o, tree-ssa-ter.o, tree-ssa-coalesce.o)
+ (tree-outof-ssa.o, tree-ssa-dse.o, tree-ssa-forwprop.o)
+ (tree-ssa-phiprop.o, tree-ssa-ifcombine.o, tree-ssa-phiopt.o)
+ (tree-nrv.o, tree-ssa-copy.o, tree-ssa-propagate.o)
+ (tree-ssa-dom.o, tree-ssa-uncprop.o, tree-ssa-threadedge.o)
+ (tree-ssa-threadupdate.o, tree-ssanames.o, tree-phinodes.o)
+ (domwalk.o, tree-ssa-live.o, tree-ssa-copyrename.o)
+ (tree-ssa-pre.o, tree-ssa-sccvn.o)
+ (gimple-ssa-strength-reduction.o, tree-vrp.o, tree-cfg.o)
+ (tree-cfgcleanup.o, tree-tailcall.o, tree-ssa-sink.o)
+ (tree-nested.o, tree-if-conv.o, tree-iterator.o, tree-dfa.o)
+ (tree-ssa-operands.o, tree-eh.o, tree-ssa-loop.o)
+ (tree-ssa-loop-unswitch.o, tree-ssa-address.o)
+ (tree-ssa-loop-niter.o, tree-ssa-loop-ivcanon.o)
+ (tree-ssa-loop-ch.o, tree-ssa-loop-prefetch.o, tree-predcom.o)
+ (tree-ssa-loop-ivopts.o, tree-affine.o, tree-ssa-loop-manip.o)
+ (tree-ssa-loop-im.o, tree-ssa-math-opts.o, tree-ssa-alias.o)
+ (tree-ssa-reassoc.o, tree-optimize.o, gimplify.o)
+ (gimple-iterator.o, gimple-fold.o, gimple-low.o, omp-low.o)
+ (tree-browser.o, omega.o, tree-chrec.o, tree-scalar-evolution.o)
+ (tree-data-ref.o, sese.o, graphite.o, graphite-blocking.o)
+ (graphite-clast-to-gimple.o, graphite-dependences.o)
+ (graphite-interchange.o, graphite-poly.o)
+ (graphite-scop-detection.o, graphite-sese-to-poly.o)
+ (graphite-optimize-isl.o, tree-vect-loop.o)
+ (tree-vect-loop-manip.o, tree-vect-patterns.o, tree-vect-slp.o)
+ (tree-vect-stmts.o, tree-vect-data-refs.o, tree-vectorizer.o)
+ (vtable-verify.o, tree-loop-distribution.o, tree-parloops.o)
+ (tree-stdarg.o, tree-object-size.o, internal-fn.o, gimple.o)
+ (gimple-pretty-print.o, tree-mudflap.o, tree-nomudflap.o)
+ (tree-pretty-print.o, tree-diagnostic.o, fold-const.o)
+ (diagnostic.o, diagnostic-color.o, opts.o, opts-global.o)
+ (opts-common.o, targhooks.o, common/common-targhooks.o, input.o)
+ (toplev.o, hwint.o, passes.o, plugin.o, main.o, host-default.o)
+ (rtl-error.o, rtl.o, print-rtl.o, rtlanal.o, varasm.o, function.o)
+ (statistics.o, stmt.o, except.o, expr.o, dojump.o, builtins.o)
+ (calls.o, expmed.o, explow.o, optabs.o, dbxout.o, debug.o)
+ (sdbout.o, dwarf2out.o, dwarf2cfi.o, dwarf2asm.o, vmsdbgout.o)
+ (xcoffout.o, godump.o, emit-rtl.o, real.o, realmpfr.o, dfp.o)
+ (fixed-value.o, jump.o, simplify-rtx.o, symtab.o, cgraph.o)
+ (cgraphunit.o, cgraphclones.o, cgraphbuild.o, varpool.o, ipa.o)
+ (ipa-profile.o, ipa-devirt.o, ipa-prop.o, ipa-ref.o, ipa-cp.o)
+ (ipa-split.o, ipa-inline.o, ipa-inline-analysis.o)
+ (ipa-inline-transform.o, ipa-utils.o, ipa-reference.o)
+ (ipa-pure-const.o, coverage.o, cselib.o, cse.o, dce.o, dumpfile.o)
+ (dse.o, fwprop.o, web.o, ree.o, cprop.o, gcse.o, store-motion.o)
+ (resource.o, lcm.o, mode-switching.o, tree-ssa-dce.o)
+ (tree-call-cdce.o, tree-ssa-ccp.o, tree-ssa-strlen.o, tree-sra.o)
+ (tree-switch-conversion.o, tree-complex.o, tree-emutls.o)
+ (tree-vect-generic.o, df-core.o, df-problems.o, df-scan.o)
+ (regstat.o, valtrack.o, var-tracking.o, profile.o, mcf.o)
+ (tree-profile.o, value-prof.o, loop-doloop.o, alloc-pool.o)
+ (auto-inc-dec.o, cfg.o, cfghooks.o, cfgexpand.o, cfgrtl.o)
+ (cfganal.o, cfgbuild.o, cfgcleanup.o, cfgloop.o, cfgloopanal.o)
+ (graphds.o, loop-iv.o, loop-invariant.o, cfgloopmanip.o)
+ (loop-init.o, loop-unswitch.o, loop-unroll.o, dominance.o)
+ (et-forest.o, combine.o, reginfo.o, bitmap.o, vec.o, hash-table.o)
+ (reload.o, reload1.o, rtlhooks.o, postreload.o, postreload-gcse.o)
+ (caller-save.o, bt-load.o, reorg.o, alias.o, stack-ptr-mod.o)
+ (init-regs.o, ira-build.o, ira-costs.o, ira-conflicts.o)
+ (ira-color.o, ira-emit.o, ira-lives.o, ira.o, lra.o)
+ (lra-assigns.o, lra-coalesce.o, lra-constraints.o)
+ (lra-eliminations.o, lra-lives.o, lra-spills.o, regmove.o)
+ (combine-stack-adj.o, compare-elim.o, ddg.o, modulo-sched.o)
+ (haifa-sched.o, sched-deps.o, sched-rgn.o, sched-ebb.o)
+ (sched-vis.o, sel-sched.o, sel-sched-dump.o, sel-sched-ir.o)
+ (final.o, recog.o, reg-stack.o, sreal.o, predict.o, lists.o)
+ (bb-reorder.o, tracer.o, timevar.o, regcprop.o, regrename.o)
+ (ifcvt.o, params.o, pointer-set.o, hooks.o, pretty-print.o)
+ (errors.o, dbgcnt.o, lower-subreg.o, target-globals.o)
+ (hw-doloop.o, file-find.o, context.o, $(common_out_object_file))
+ (insn-attrtab.o, insn-automata.o, insn-dfatab.o, insn-emit.o)
+ (insn-enums.o, insn-extract.o, insn-latencytab.o, insn-modes.o)
+ (insn-opinit.o, insn-output.o, insn-peep.o, insn-preds.o)
+ (insn-recog.o, intl.o, cppbuiltin.o, cppdefault.o, gcov.o)
+ (gcov-dump.o): Remove.
+ (default-c.o): Use COMPILE and POSTCOMPILE.
+ (CFLAGS-gcc.o): New variable.
+ ($(common_out_object_file)): Use COMPILE and POSTCOMPILE.
+
+2013-09-25 Tom Tromey <tromey@redhat.com>
+
+ * Makefile.in (c-family/cppspec.o, c-family/c-common.o)
+ (c-family/c-cppbuiltin.o, c-family/c-dump.o, c-family/c-format.o)
+ (c-family/c-gimplify.o, c-family/c-lex.o, c-family/c-omp.o)
+ (c-family/c-opts.o, c-family/c-pch.o, c-family/c-ppoutput.o)
+ (c-family/c-pragma.o, c-family/c-pretty-print.o)
+ (c-family/c-semantics.o, c-family/c-ada-spec.o)
+ (c-family/array-notation-common.o, c-family/stub-objc.o)
+ (c-family/c-ubsan.o): Remove.
+
+2013-09-25 Tom Tromey <tromey@redhat.com>
+
+ * Makefile.in (C_TREE_H): Reference c/c-tree.h.
+
+2013-09-25 Tom Tromey <tromey@redhat.com>
+
+ * Makefile.in (DRIVER_DEFINES): Use $(and), not shell code,
+ to add -DENABLE_SHARED_LIBGCC.
+ (gcc.o): Don't use subshell.
+
+2013-09-25 Tom Tromey <tromey@redhat.com>
+
+ * Makefile.in (OUTPUT_OPTION): Define as "-o $@".
+ * configure.ac: Don't invoke AM_PROG_CC_C_O.
+ (NO_MINUS_C_MINUS_O, OUTPUT_OPTION): Don't subst.
+ * configure, config.in: Rebuild.
+
+2013-09-25 Tom Tromey <tromey@redhat.com>
+
+ * Makefile.in (CCDEPMODE, DEPDIR, depcomp, COMPILE.base)
+ (COMPILE, POSTCOMPILE): New variables.
+ (.cc.o .c.o): Use COMPILE, POSTCOMPILE.
+ (DEPFILES): New variable.
+ Include ".Po" files.
+ * configure.ac: Add checks for dependency checking.
+ * configure, aclocal.m4: Regenerate.
+
+2013-09-25 Tom Tromey <tromey@redhat.com>
+
+ * Makefile.in (ALL_HOST_BACKEND_OBJS): Add lto-wrapper.o.
+ ($(ALL_HOST_OBJS)): Move order-only dependency to end of file.
+
+2013-09-25 Tom Tromey <tromey@redhat.com>
+
+ * Makefile.in (generated_files): Add options.h,
+ target-hooks-def.h, insn-opinit.h,
+ common/common-target-hooks-def.h, pass-instances.def,
+ c-family/c-target-hooks-def.h.
+
+2013-09-25 Jeff Law <law@redhat.com>
+
+ * tree-ssa-threadedge.c (thread_across_edge): Use foo.last () rather
+ than foo[foo.length () - 1] to access last member in a vec.
+ * tree-ssa-threadupdate.c (register_jump_thread): Similarly.
+
+2013-09-25 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/58521
+ * tree.c (iterative_hash_expr): Remove MEM_REF special handling.
+
+2013-09-25 Jan Hubicka <jh@suse.cz>
+
+ * cgraph.c (cgraph_resolve_speculation): Use semantical equivalency
+ test.
+
+2013-09-25 Marek Polacek <polacek@redhat.com>
+
+ PR sanitizer/58420
+ * ubsan.c (ubsan_type_descriptor): Handle IDENTIFIER_NODEs
+ when determining the type name.
+
+2013-09-24 Oleg Endo <olegendo@gcc.gnu.org>
+
+ * config/sh/sh.md: Fix formatting.
+
+2013-09-24 Xinliang David Li <davidxl@google.com>
+
+ * tree-vect-data-refs.c (vect_enhance_data_refs_alignment): Check
+ max peel iterations parameter.
+ * param.def: New parameter.
+ * doc/invoke.texi: Document New parameter.
+
+2013-09-24 Christophe Lyon <christophe.lyon@linaro.org>
+
+ * gimple-pretty-print.c: Various whitespace tweaks.
+ * tree-core.h: Likewise.
+ * tree-pretty-print.c: Likewise.
+ * tree-ssa-alias.c: Likewise.
+ * tree-ssa-copy.c: Likewise.
+ * tree-ssanames.c: Likewise.
+ * tree-ssanames.h: Likewise.
+ * tree-vrp.c: Likewise.
+
+2013-09-24 Alan Modra <amodra@gmail.com>
+
+ PR middle-end/57134
+ PR middle-end/57586
+ * stmt.c (expand_asm_operands): Call expand_expr with EXPAND_MEMORY
+ for output operands that disallow regs. Don't use EXPAND_WRITE on
+ inout operands.
+
+2013-09-24 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/58513
+ * tree.c (reference_alias_ptr_type): Move ...
+ * alias.c (reference_alias_ptr_type): ... here and implement
+ in terms of the new reference_alias_ptr_type_1.
+ (ref_all_alias_ptr_type_p): New helper.
+ (get_deref_alias_set_1): Drop flag_strict_aliasing here,
+ use ref_all_alias_ptr_type_p.
+ (get_deref_alias_set): Add flag_strict_aliasing check here.
+ (reference_alias_ptr_type_1): New function, split out from ...
+ (get_alias_set): ... here.
+ (alias_ptr_types_compatible_p): New function.
+ * alias.h (reference_alias_ptr_type): Declare.
+ (alias_ptr_types_compatible_p): Likewise.
+ * tree.h (reference_alias_ptr_type): Remove.
+ * fold-const.c (operand_equal_p): Use alias_ptr_types_compatible_p
+ to compare MEM_REF alias types.
+
+2013-09-24 Richard Biener <rguenther@suse.de>
+
+ * tree-vrp.c (vrp_finalize): Check for SSA name presence.
+
+2013-09-23 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * config/rs6000/rs6000.c (rs6000_vector_reload): Delete, combine
+ reload helper function arrays into a single array reg_addr.
+ (reload_fpr_gpr): Likewise.
+ (reload_gpr_vsx): Likewise.
+ (reload_vsx_gpr): Likewise.
+ (struct rs6000_reg_addr): Likewise.
+ (reg_addr): Likewise.
+ (rs6000_debug_reg_global): Change rs6000_vector_reload,
+ reload_fpr_gpr, reload_gpr_vsx, reload_vsx_gpr uses to reg_addr.
+ (rs6000_init_hard_regno_mode_ok): Likewise.
+ (rs6000_secondary_reload_direct_move): Likewise.
+ (rs6000_secondary_reload): Likewise.
+
+ * config/rs6000/rs6000.h (enum r6000_reg_class_enum): Add new
+ constraints: wu, ww, and wy. Repurpose wv constraint added during
+ power8 changes. Put wg constraint in alphabetical order.
+
+ * config/rs6000/rs6000.opt (-mvsx-scalar-float): New debug switch
+ for future work to add ISA 2.07 VSX single precision support.
+ (-mvsx-scalar-double): Change default from -1 to 1, update
+ documentation comment.
+ (-mvsx-scalar-memory): Rename debug switch to -mupper-regs-df.
+ (-mupper-regs-df): New debug switch to control whether DF values
+ can go in the traditional Altivec registers.
+ (-mupper-regs-sf): New debug switch to control whether SF values
+ can go in the traditional Altivec registers.
+
+ * config/rs6000/rs6000.c (rs6000_debug_reg_global): Print wu, ww,
+ and wy constraints.
+ (rs6000_init_hard_regno_mode_ok): Use ssize_t instead of int for
+ loop variables. Rename -mvsx-scalar-memory to -mupper-regs-df.
+ Add new constraints, wu/ww/wy. Repurpose wv constraint.
+ (rs6000_debug_legitimate_address_p): Print if we are running
+ before, during, or after reload.
+ (rs6000_secondary_reload): Add a comment.
+ (rs6000_opt_masks): Add -mupper-regs-df, -mupper-regs-sf.
+
+ * config/rs6000/constraints.md (wa constraint): Sort w<x>
+ constraints. Update documentation string.
+ (wd constraint): Likewise.
+ (wf constraint): Likewise.
+ (wg constraint): Likewise.
+ (wn constraint): Likewise.
+ (ws constraint): Likewise.
+ (wt constraint): Likewise.
+ (wx constraint): Likewise.
+ (wz constraint): Likewise.
+ (wu constraint): New constraint for ISA 2.07 SFmode scalar
+ instructions.
+ (ww constraint): Likewise.
+ (wy constraint): Likewise.
+ (wv constraint): Repurpose ISA 2.07 constraint that we did not use
+ in the previous submissions.
+ * doc/md.texi (PowerPC and IBM RS6000): Likewise.
+
+2013-09-23 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * doc/rtl.texi (REG_NOTES): Say that int_list can also be used.
+ (REG_BR_PROB): Say that the probability is stored in an int_list.
+ * reg-notes.def: Update commentary to mention INT_LIST.
+ * rtl.def (EXPR_LIST, INSN_LIST): Capitalize comments.
+ (INT_LIST): New rtx.
+ * rtl.h (add_int_reg_note, add_shallow_copy_of_reg_note): Declare.
+ * rtlanal.c (int_reg_note_p): New function.
+ (alloc_reg_note): Assert that the note does not have an int argument.
+ (add_int_reg_note, add_shallow_copy_of_reg_note): New functions.
+ * combine.c (distribute_notes): Use add_shallow_copy_of_rtx.
+ * cse.c (cse_process_notes_1): Expect REG_EQUAL to be an EXPR_LIST
+ rather than an INSN_LIST. Handle INT_LIST.
+ * ifcvt.c (cond_exec_process_insns): Take the probability as an int
+ rather than an rtx. Use gen_rtx_INT_LIST to create a REG_BR_PROB note.
+ (cond_exec_process_if_block): Use XINT to extract REG_BR_PROB values.
+ Manipulate them as ints rather than rtxes.
+ * reg-stack.c (subst_asm_stack_regs): Only handle EXPR_LIST notes.
+ * regmove.c (copy_src_to_dest): Likewise.
+ * sched-vis.c (print_insn_with_notes): Handle INT_LIST.
+
+ * config/i386/winnt.c (i386_pe_seh_unwind_emit): Sink pat assignment
+ into the cases that need it.
+ * config/arm/arm.c (arm_unwind_emit): Likewise.
+
+ * asan.c (asan_clear_shadow): Use add_int_reg_note for REG_BR_PROB.
+ * emit-rtl.c (try_split, emit_copy_of_insn_after): Likewise.
+ * loop-doloop.c (add_test, doloop_modify): Likewise.
+ * loop-unswitch.c (compare_and_jump_seq): Likewise.
+ * optabs.c (emit_cmp_and_jump_insn_1): Likewise.
+ * predict.c (combine_predictions_for_insn): Likewise.
+ * print-rtl.c (print_rtx): Handle INT_LIST.
+ * config/aarch64/aarch64.c (aarch64_emit_unlikely_jump): Likewise.
+ * config/alpha/alpha.c (emit_unlikely_jump): Likewise.
+ * config/arm/arm.c (emit_unlikely_jump): Likewise.
+ * config/i386/i386.c (ix86_expand_split_stack_prologue): Likewise.
+ (ix86_split_fp_branch, predict_jump): Likewise.
+ * config/rs6000/rs6000.c (emit_unlikely_jump): Likewise.
+ * config/sh/sh.c (expand_cbranchsi4): Likewise.
+ * config/spu/spu.c (ea_load_store_inline): Likewise.
+
+ * cfgbuild.c (compute_outgoing_frequencies): Use XINT to access the
+ value of a REG_BR_PROB note.
+ * cfgrtl.c (force_nonfallthru_and_redirect): Likewise.
+ (update_br_prob_note, rtl_verify_edges, purge_dead_edges): Likewise.
+ * emit-rtl.c (try_split): Likewise.
+ * predict.c (br_prob_note_reliable_p): Likewise.
+ (invert_br_probabilities, combine_predictions_for_insn): Likewise.
+ * reorg.c (mostly_true_jump): Likewise.
+ * config/bfin/bfin.c (cbranch_predicted_taken_p): Likewise.
+ * config/frv/frv.c (frv_print_operand_jump_hint): Likewise.
+ * config/i386/i386.c (ix86_print_operand): Likewise.
+ * config/ia64/ia64.c (ia64_print_operand): Likewise.
+ * config/mmix/mmix.c (mmix_print_operand): Likewise.
+ * config/rs6000/rs6000.c (output_cbranch): Likewise.
+ * config/s390/s390.c (s390_expand_tbegin): Likewise.
+ * config/sh/sh.c (sh_print_operand, sh_adjust_cost): Likewise.
+ * config/sparc/sparc.c (output_cbranch): Likewise.
+ * config/spu/spu.c (get_branch_target): Likewise.
+ * config/tilegx/tilegx.c (cbranch_predicted_p): Likewise.
+ * config/tilepro/tilepro.c (cbranch_predicted_p): Likewise.
+
+2013-09-23 Jan Hubicka <jh@suse.cz>
+
+ * ipa-cp.c (ipa_get_indirect_edge_target_1): Add sanity check
+ for ipa-devirt.
+ * ipa-utils.h (possible_polymorphic_call_target_p): New function.
+ * ipa-devirt.c (possible_polymorphic_call_target_p): Be tolerant
+ of external calls
+ * gimple-fold.c: Include ipa-utils.h and gimple-pretty-print.h
+ (gimple_fold_call): Dump inconsistent devirtualizations; add
+ sanity check for type based devirtualizations.
+ * ipa-prop.c: Include ipa-utils.h
+ (ipa_intraprocedural_devirtualization): Add sanity check.
+ (try_make_edge_direct_virtual_call): Likewise.
+
+2013-09-23 Eric Botcazou <ebotcazou@adacore.com>
+
+ * tree-ssa-ccp.c (insert_clobber_before_stack_restore): Recurse on copy
+ assignment statements.
+
+2013-09-23 Kugan Vivekanandarajah <kuganv@linaro.org>
+
+ * gimple-pretty-print.c (dump_ssaname_info): New function.
+ (dump_gimple_phi): Call it.
+ (pp_gimple_stmt_1): Likewise.
+ * tree-core.h (tree_ssa_name): New union ssa_name_info_type field.
+ (range_info_def): Declare.
+ * tree-pretty-print.c (pp_double_int): New function.
+ (dump_generic_node): Call it.
+ * tree-pretty-print.h (pp_double_int): Declare.
+ * tree-ssa-alias.c (dump_alias_info): Check pointer type.
+ * tree-ssanames.h (range_info_def): New structure.
+ (value_range_type): Move definition here.
+ (set_range_info, value_range_type, duplicate_ssa_name_range_info):
+ Declare.
+ * tree-ssanames.c (make_ssa_name_fn): Check pointer type at
+ initialization.
+ (set_range_info): New function.
+ (get_range_info): Likewise.
+ (duplicate_ssa_name_range_info): Likewise.
+ (duplicate_ssa_name_fn): Check pointer type and call
+ duplicate_ssa_name_range_info.
+ * tree-ssa-copy.c (fini_copy_prop): Likewise.
+ * tree-vrp.c (value_range_type): Remove definition, now in
+ tree-ssanames.h.
+ (vrp_finalize): Call set_range_info to update value range of SSA_NAMEs.
+ * tree.h (SSA_NAME_PTR_INFO): Macro changed to access via union.
+ (SSA_NAME_RANGE_INFO): New macro.
+
+2013-09-23 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/58464
+ * tree-ssa-pre.c (phi_trans_lookup): Remove.
+ (phi_trans_add): Change to add conditionally on being not present.
+ (phi_translate_1): Remove recursion detection here.
+ (phi_translate): Pre-seed the cache with NULL to catch
+ recursion here in a more generic way.
+ (bitmap_find_leader): Adjust comment.
+ (get_representative_for): Dump value-numbers.
+ (create_expression_by_pieces): Likewise.
+ (insert_into_preds_of_block): Likewise.
+
+2013-09-23 Christian Bruel <christian.bruel@st.com>
+
+ PR target/58475
+ * config/sh/sh.md (movsf_ie): Allow fpul_operand.
+ * config/sh/predicate.md (arith_reg_operand): Disallow FPUL_REG.
+
+2013-09-23 James Greenhalgh <james.greenhalgh@arm.com>
+
+ Revert r202780:
+ 2013-09-20 Renlin Li <renlin.li@arm.com>
+
+ * config/aarch64/aarch64.c (aarch64_expand_prologue): Use
+ plus_constant.
+ (aarch64_expand_epilogue): Likewise.
+ (aarch64_legitimize_reload_address): Likewise.
+
+2013-09-22 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gimplify.c (gimplify_asm_expr): Reset the TREE_CHAIN of clobbers to
+ NULL_TREE before pushing them onto the vector. Likewise for labels.
+
+2013-09-21 Eric Botcazou <ebotcazou@adacore.com>
+
+ * config/ia64/predicates.md (ia64_cbranch_operator): Accept unordered
+ comparison operators when -fno-trapping-math is in effect.
+ * config/ia64/ia64.c (ia64_expand_compare): Add support for unordered
+ comparison operators in TFmode and assert that unsupported operators
+ cannot reach here.
+ (ia64_print_operand): Likewise.
+
+2013-09-21 Jan Hubicka <jh@suse.cz>
+
+ * x86-tune.def (partial_reg_stall): Disable for CoreI7 and newer.
+ (sse_typeless_stores): Enable for core
+ (sse_load0_by_pxor): Likewise.
+ (four_jump_limit): Disable for core.
+ (pad_returns): Likewise.
+ (avoid_vector_decode): Likewise.
+ (fuse_cmp_and_branch): Enable for cores.
+ * i386.c (x86_accumulate_outgoing_args): Disable for cores.
+
+2013-09-20 John David Anglin <danglin@gcc.gnu.org>
+
+ PR middle-end/56791
+ * config/pa/pa.c (pa_option_override): Disable auto increment and
+ decrement instructions until reload is completed.
+
+ * config/pa/pa-linux.h (TARGET_OS_CPP_BUILTINS): Define
+ __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1, __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2,
+ and __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4.
+
+2013-09-20 DJ Delorie <dj@redhat.com>
+ Nick Clifton <nickc@redhat.com>
+
+ * config/rl78/rl78.c: Various whitespace and comment tweaks.
+ (need_to_save): Save bank 0 on interrupts.
+ (characterize_address): Strip far address wrappers.
+ (rl78_as_legitimate_address): Likewise.
+ (transcode_memory_rtx): Likewise.
+ (rl78_peep_movhi_p): Disable this peephole after devirt.
+ (rl78_propogate_register_origins): Forget all origins when a
+ CLOBBER is seen.
+ * config/rl78/rl78-virt.md: Various whitespace tweaks.
+ * config/rl78/rl78-real.md: Various whitespace tweaks. Additional
+ peephole2's.
+ * config/rl78/rl78.md (sel_rb): Disable for G10 just in case.
+ * config/rl78/rl78-expand.md (movqi): Check for subregs of consts.
+ * config/rl78/rl78.h (LINK_SPEC): Pass -gc-sections unless
+ relocating.
+ * config/rl78/constraints.md: Various whitespace and paren tweaks.
+
+2013-09-20 John David Anglin <danglin@gcc.gnu.org>
+
+ * config/pa/pa.md: In "scc" insn patterns, change output template to
+ handle const0_rtx in reg_or_0_operand operands.
+
+2013-09-20 Martin Husemann <martin@NetBSD.org>
+
+ PR target/56875
+ * config/vax/vax.c (vax_output_int_move): Use D format specifier.
+ * config/vax/vax.md (ashldi3, <unnamed>): Ditto.
+
+2013-09-20 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/58484
+ * tree-scalar-evolution.c (struct scev_info_str): Shrink by
+ remembering SSA name version and block index.
+ (new_scev_info_str): Adjust.
+ (hash_scev_info): Likewise. Also hash the block index.
+ (eq_scev_info): Adjust.
+ (find_var_scev_info): Likewise.
+ (struct instantiate_cache_entry): Remove.
+ (struct instantiate_cache_type): Use a htab to map name, block
+ to chrec.
+ (instantiate_cache_type::~instantiate_cache_type): Adjust.
+ (get_instantiated_value_entry): Likewise.
+ (hash_idx_scev_info, eq_idx_scev_info): New functions.
+ (instantiate_scev_name): Adjust.
+
+2013-09-20 Jeff Law <law@redhat.com>
+
+ * tree-ssa-dom.c (record_temporary_equivalences): Add comment.
+
+2013-09-20 Yufeng Zhang <yufeng.zhang@arm.com>
+
+ * config/aarch64/aarch64-builtins.c (aarch64_simd_expand_args):
+ Call aarch64_simd_expand_args to update op[argc].
+
+2013-09-20 Basile Starynkevitch <basile@starynkevitch.net>
+
+ * plugin.c (parse_plugin_arg_opt): Accept equal sign inside
+ plugin argument.
+
+2013-09-20 Basile Starynkevitch <basile@starynkevitch.net>
+
+ * gengtype.c (file_rules): Added rule for *.cc files.
+ (get_output_file_with_visibility): Give fatal message when no
+ rules found.
+
+2013-09-20 Renlin Li <renlin.li@arm.com>
+
+ * config/aarch64/aarch64.c (aarch64_expand_prologue): Use plus_constant.
+ (aarch64_expand_epilogue): Likewise.
+ (aarch64_legitimize_reload_address): Likewise.
+
+2013-09-20 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ PR middle-end/57748
+ * expr.c (expand_assignment): Remove misalignp code path.
+
+2013-09-20 Marek Polacek <polacek@redhat.com>
+
+ PR sanitizer/58413
+ * ubsan.c (get_ubsan_type_info_for_type): Use TYPE_SIZE instead of
+ TYPE_PRECISION. Add asserts.
+
+2013-09-20 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/58453
+ * tree-loop-distribution.c (distribute_loop): Apply the cost
+ model for -ftree-loop-distribute-patterns, too.
+
+2013-09-20 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/58473
+ * tree-chrec.h (build_polynomial_chrec): Use gcc_checking_assert,
+ make type comparison less strict.
+
+2013-09-20 Alan Modra <amodra@gmail.com>
+
+ * configure: Regenerate.
+ * aclocal.m4: Regenerate.
+
2013-09-20 Marek Polacek <polacek@redhat.com>
PR other/58467
@@ -36,7 +8073,8 @@
* i386-c.c (ix86_target_macros_internal): Unify generic64 and 32.
(ix86_target_macros_internal): Likewise.
* driver-i386.c (host_detect_local_cpu): Likewise.
- * i386.c (generic64_memcpy, generic64_memset, generic64_cost): Rename to ..
+ * i386.c (generic64_memcpy, generic64_memset, generic64_cost): Rename
+ to ..
(generic_memcpy, generic_memset, generic_cost): This one.
(generic32_memcpy, generic32_memset, generic32_cost): Remove.
(m_GENERIC32, m_GENERIC64): Remove.
@@ -199,35 +8237,35 @@
(move_computations_stmt): Convert to method
move_computations_dom_walker::before_dom_children.
(move_computations, tree_ssa_lim): Adjust.
- * tree-ssa-phiopt.c (nontrapping_dom_walker): new class
- (nt_init_block): Make method
+ * tree-ssa-phiopt.c (nontrapping_dom_walker): New class.
+ (nt_init_block): Convert to method
notrappping_dom_walker::before_dom_children.
- (nt_fini_block): Make
+ (nt_fini_block): Convert to method
method nontrapping_dom_walker::after_dom_children.
(get_non_trapping): Adjust.
* tree-ssa-pre.c (eliminate_dom_walker): New class.
- (eliminate_bb): Make method eliminate_dom_walker::before_dom_children.
- (eliminate_leave_block): Make method.
+ (eliminate_bb): Convert to method
+ eliminate_dom_walker::before_dom_children.
+ (eliminate_leave_block): Convert to method
eliminate_dom_walker::after_dom_children.
- (eliminate): Adjust
+ (eliminate): Adjust.
* tree-ssa-strlen.c (strlen_dom_walker): New class.
- (strlen_enter_block): Make method
+ (strlen_enter_block): Convert to method
strlen_dom_walker::before_dom_children.
- (strlen_leave_block): Make
+ (strlen_leave_block): Convert to method
method strlen_dom_walker::after_dom_children.
(tree_ssa_strlen): Adjust.
* tree-ssa-uncprop.c (uncprop_dom_walker): New class.
(tree_ssa_uncprop): Adjust.
- (uncprop_leave_block): Make method
+ (uncprop_leave_block): Convert to method
uncprop_dom_walker::after_dom_children.
- (uncprop_leave_block): Make method
+ (uncprop_leave_block): Convert to method
uncprop_dom_walker::before_dom_children.
2013-09-18 Bin Cheng <bin.cheng@arm.com>
- * config/arm/arm.c (thumb1_reorg): Search for flag setting insn
- before branch in same basic block. Check both src and dest of
- the move insn.
+ * config/arm/arm.c (thumb1_reorg): Search for flag setting insn before
+ branch in same basic block. Check both src and dest of the move insn.
2013-09-17 Nick Clifton <nickc@redhat.com>
@@ -297,20 +8335,22 @@
tree-ssa-threadupdate.c
(thread_across_edge): Don't check PHI argument equality when
threading through joiner block here.
-
+
2013-09-17 Andrew MacLeod <amacleod@redhat.com>
* tree-flow.h (ssa_undefined_value_p): Remove prototype.
* tree-ssa.c (ssa_undefined_value_p): Move pass independent parts here.
- (warn_uninit, warn_uninitialized_vars, execute_early_warn_uninitialized,
- make_pass_early_warn_uninitialized): Move to tree-ssa-uninit.c.
- * tree-ssa-uninit.c (ssa_undefined_value_p): Move to tree-ssa.c
- (has_undefined_value_p): New. Pass dependant parts of
+ (warn_uninit, warn_uninitialized_vars,
+ execute_early_warn_uninitialized, make_pass_early_warn_uninitialized):
+ Move to tree-ssa-uninit.c.
+ * tree-ssa-uninit.c (ssa_undefined_value_p): Move to tree-ssa.c.
+ (has_undefined_value_p): New. Pass dependant parts of
ssa_undefined_value_p.
(uninit_undefined_value_p): Use has_undefined_value_p.
- (warn_uninit, warn_uninitialized_vars, execute_early_warn_uninitialized,
- make_pass_early_warn_uninitialized): Move from tree-ssa.c
- * tree-ssa.h: Adjust prototypes
+ (warn_uninit, warn_uninitialized_vars,
+ execute_early_warn_uninitialized, make_pass_early_warn_uninitialized):
+ Move from tree-ssa.c.
+ * tree-ssa.h: Adjust prototypes.
2013-09-17 Jan Hubicka <jh@suse.cz>
@@ -421,7 +8461,8 @@
2013-09-17 Alan Modra <amodra@gmail.com>
PR target/57589
- * config/rs6000/driver-rs6000.c (elf_platform): Revert 2013-06-11 patch.
+ * config/rs6000/driver-rs6000.c (elf_platform): Revert 2013-06-11
+ patch.
2013-09-16 DJ Delorie <dj@redhat.com>
@@ -451,7 +8492,7 @@
(tree_vectorize): Ditto.
(pass_vectorize::gate): Call new function.
(pass_vectorize::execute): Ditto.
- opts.c: O3 default setting change.
+ * opts.c: O3 default setting change.
(finish_options): Check new flag.
* doc/invoke.texi: Document new flags.
* common.opt: New flags.
@@ -584,14 +8625,12 @@
2013-09-16 Diego Novillo <dnovillo@google.com>
- * tree-core.h: Add missing comment lines from refactoring
- of tree.h.
+ * tree-core.h: Add missing comment lines from refactoring of tree.h.
2013-09-16 Jan Hubicka <jh@suse.cz>
* gimple-fold.c (can_refer_decl_in_current_unit_p): Do not accept
- abstract functions; for static functions check the presence
- of body.
+ abstract functions; for static functions check the presence of body.
2013-09-16 James Greenhalgh <james.greenhalgh@arm.com>
@@ -806,7 +8845,6 @@
dll-export inline-functions.
* config/i386/winnt.c (i386_pe_determine_dllexport_p): Likewise.
-
2013-09-13 Jeff Law <law@redhat.com>
PR middle-end/58387
@@ -2797,7 +10835,7 @@
2013-09-04 Dodji Seketeli <dodji@redhat.com>
* tree.h (DECL_BUILT_IN, DECL_IS_BUILTIN): Add more comments
- explaining their differences.
+ explaining their differences.
2013-09-04 Sandeep Kumar Singh<Sandeep.Singh2@kpitcummins.com>
@@ -4043,12 +12081,12 @@
2013-08-21 Kirill Yukhin <kirill.yukhin@intel.com>
- * config/i386/sse.md (V16): Rename to...
- (VMOVE): this.
- (mov<mode>): Update iterator name.
- (*mov<mode>_internal): Ditto.
- (push<mode>1): Ditto.
- (movmisalign<mode>): Ditto.
+ * config/i386/sse.md (V16): Rename to...
+ (VMOVE): this.
+ (mov<mode>): Update iterator name.
+ (*mov<mode>_internal): Ditto.
+ (push<mode>1): Ditto.
+ (movmisalign<mode>): Ditto.
2013-08-20 Jan Hubicka <jh@suse.cz>
@@ -14697,7 +22735,7 @@
PR tree-optimization/57066
* builtins.c (fold_builtin_logb): Return +Inf for -Inf.
-2013-04-25 James Greenhalgh <jame.greenhalgh@arm.com>
+2013-04-25 James Greenhalgh <james.greenhalgh@arm.com>
* config/aarch64/aarch64-simd.md (neg<mode>2): Use VDQ iterator.
@@ -16419,7 +24457,6 @@
(debug_ivtype_elt): Remove unused.
(eq_ivtype_map_elts): Remove unused.
-
2013-04-02 Kai Tietz <ktietz@redhat.com>
PR target/52790
@@ -18637,7 +26674,7 @@
(udivsi3_i4_single, divsi3_i4_single): Use
TARGET_FPU_SINGLE_ONLY || TARGET_FPU_DOUBLE instead of TARGET_HARD_SH4.
-2013-03-13 Dave Korn <dave.korn.cygwin@....>
+2013-03-13 Dave Korn <dave.korn.cygwin@gmail.com>
* config/i386/cygwin.h (SHARED_LIBGCC_SPEC): Make shared libgcc the
default setting.
@@ -19684,7 +27721,7 @@
* target-globals.c (save_target_globals): For init_reg_sets and
target_reinit remporarily set this_fn_optabs to this_target_optabs.
-2013-02-22 James Grennahlgh <james.greenhalgh@arm.com>
+2013-02-22 James Greenhalgh <james.greenhalgh@arm.com>
* config/aarch64/aarch64-simd-builtins.def: Add copyright header.
* config/aarch64/t-aarch64
@@ -20178,7 +28215,7 @@
equal to op0 or op1, and last_insn pattern is CODE operation
with MEM dest and one of the operands matches that MEM.
-2013-02-11 Sriraman Tallam <tmsriramgoogle.com>
+2013-02-11 Sriraman Tallam <tmsriram@google.com>
* doc/extend.texi: Document Function Multiversioning and "default"
parameter string to target attribute.
diff --git a/gcc/ChangeLog-2009 b/gcc/ChangeLog-2009
index 4167065b58d..c95c0ca129e 100644
--- a/gcc/ChangeLog-2009
+++ b/gcc/ChangeLog-2009
@@ -7030,7 +7030,7 @@
Ryan Mansfield <rmansfield@qnx.com>
Diego Novillo <dnovillo@google.com>
Ollie Wild <aaw@google.com>
- Kenneth Zadeck <zadeck@naturalbridge.com>
+ Kenneth Zadeck <zadeck@naturalbridge.com>
* lto-cgraph.c: New file.
* lto-compress.c: New file.
@@ -7091,7 +7091,7 @@
(cgraph_optimize): Make extern.
2009-10-03 Nathan Froyd <froydnj@codesourcery.com>
- Kenneth Zadeck <zadeck@naturalbridge.com>
+ Kenneth Zadeck <zadeck@naturalbridge.com>
* toplev.c (in_lto_p): Declare.
* collect2.c (scan_prog_file): Read all the output when reading
@@ -7142,7 +7142,7 @@
(gimple_eh_must_not_throw_set_fndecl): New.
2009-10-03 Jan Hubicka <jh@suse.cz>
- Kenneth Zadeck <zadeck@naturalbridge.com>
+ Kenneth Zadeck <zadeck@naturalbridge.com>
* ipa-pure-const.c: Include lto-streamer.h.
(register_hooks): Factor out of ...
diff --git a/gcc/ChangeLog-2011 b/gcc/ChangeLog-2011
index ce92ab2febb..75c04fca968 100644
--- a/gcc/ChangeLog-2011
+++ b/gcc/ChangeLog-2011
@@ -9270,7 +9270,7 @@
(sms_schedule): Adjust call to generate_reg_moves.
Don't call free_undo_replace_buff.
-2011-10-10 Matthias Klose <doko@ubuntu.com>
+2011-10-10 Matthias Klose <doko@ubuntu.com>
* common/config/m32c: Remove empty directory.
@@ -13777,11 +13777,11 @@
* doc/extend.texi: Document AVX2 built-in functions.
* doc/invoke.texi: Document -mavx2.
-2011-08-22 Matthias Klose <doko@debian.org>
+2011-08-22 Matthias Klose <doko@debian.org>
Revert:
2011-07-11 Arthur Loiret <aloiret@debian.org>
- Matthias Klose <doko@debian.org>
+ Matthias Klose <doko@debian.org>
* config/mips/t-linux64 (MULTILIB_DIRNAMES): Set to 'n32 . 64' if
tm_defines contains MIPS_ABI_DEFAULT ABI_32, to follow the glibc
convention.
@@ -18472,7 +18472,7 @@
PR middle-end/49736
* expr.c (all_zeros_p): Undo bogus part of last change.
-2011-07-14 Matthias Klose <doko@ubuntu.com>
+2011-07-14 Matthias Klose <doko@ubuntu.com>
* doc/extend.texi (optimize attribute): Fix typo.
@@ -18928,7 +18928,7 @@
--enable-targets=all.
2011-07-11 Arthur Loiret <aloiret@debian.org>
- Matthias Klose <doko@debian.org>
+ Matthias Klose <doko@debian.org>
* config.gcc (mips*-*-linux*): If 'enabled_targets' is 'all', build
a tri-arch compiler defaulting to 32-bit (ABI o32). In this case:
diff --git a/gcc/ChangeLog-2012 b/gcc/ChangeLog-2012
index ad72535e28d..900077783c9 100644
--- a/gcc/ChangeLog-2012
+++ b/gcc/ChangeLog-2012
@@ -4386,7 +4386,7 @@
* config/sh/sh.c (sh_can_use_simple_return_p): Enable with
-freorder-blocks-and-partition.
-2012-11-09 Kenneth Zadeck <zadeck@naturalbridge.com>
+2012-11-09 Kenneth Zadeck <zadeck@naturalbridge.com>
* rtl.h (CONST_SCALAR_INT_P): New macro.
* cfgexpand.c (expand_debug_locations): Changed to use
@@ -4712,7 +4712,7 @@
longer static.
* tree-ssa-loop-ch.c (copy_loop_headers): Use it.
-2012-11-06 Sterling Augustine <saugustine@google.com>
+2012-11-06 Sterling Augustine <saugustine@google.com>
* dwarf2out.c (output_comdat_type_unit): Check for OBJECT_FORMAT_ELF.
@@ -4751,7 +4751,7 @@
* tree-ssa-tail-merge.c (find_duplicate): Do not consider
is_tm_ending_fndecl calls as mergable.
-2012-11-06 Sterling Augustine <saugustine@google.com>
+2012-11-06 Sterling Augustine <saugustine@google.com>
Cary Coutant <ccoutant@google.com>
* common.opt (gno-split-dwarf, gsplit-dwarf): New switches.
@@ -10738,7 +10738,7 @@
* config/i386/i386.c (ix86_rtx_costs): Limit > UNITS_PER_WORD
AND/IOR/XOR cost calculation to MODE_INT class modes.
-2012-09-18 Thomas Quinot <quinot@adacore.com>
+2012-09-18 Thomas Quinot <quinot@adacore.com>
* doc/invoke.texi: Document -fada-spec-parent.
@@ -12749,7 +12749,7 @@
New constraints.
* config/avr/avr.h (LONG_LONG_ACCUM_TYPE_SIZE): Define.
-2012-08-23 Kenneth Zadeck <zadeck@naturalbridge.com>
+2012-08-23 Kenneth Zadeck <zadeck@naturalbridge.com>
* alias.c (rtx_equal_for_memref_p): Convert constant cases.
* combine.c (find_single_use_1, mark_used_regs_combine): Convert
@@ -15922,7 +15922,7 @@
alignment requirements given the known alignment of dynamic_offset.
* function.c (instantiate_virtual_regs): Align dtnamic_offset.
-2012-08-02 Kenneth Zadeck <zadeck@naturalbridge.com>
+2012-08-02 Kenneth Zadeck <zadeck@naturalbridge.com>
* cfgexpand.c (expand_debug_locations): Encapsulate test for
CONST_DOUBLE in macro.
@@ -20452,7 +20452,7 @@
* var-tracking.c (vt_add_function_parameter): Use a preserved
VALUE for the MEM address of an incoming parameter.
-2012-06-26 Sterling Augustine <saugustine@google.com>
+2012-06-26 Sterling Augustine <saugustine@google.com>
* dwarf2out.c (output_pubnames): Add check for DW_TAG_enumerator.
(prune_unused_types): Likewise.
@@ -22305,7 +22305,7 @@
Place new pass_jump2 after pass_stack_adjustments.
* tree-pass.h (pass_jump): Declare.
-2012-06-09 Kenneth Zadeck <zadeck@naturalbridge.com>
+2012-06-09 Kenneth Zadeck <zadeck@naturalbridge.com>
* simplify-rtx.c (simplify_const_binary_operation): Fixed shift
count trucation.
@@ -22716,7 +22716,7 @@
* config/sparc/sparc-protos.h (sparc_initial_elimination_offset):
Prototype it.
-2012-06-02 Kenneth Zadeck <zadeck@naturalbridge.com>
+2012-06-02 Kenneth Zadeck <zadeck@naturalbridge.com>
* expmed.c (expand_mult, choose_multiplier): Change
"2 * HOST_BITS_PER_WIDE_INT" to "HOST_BITS_PER_DOUBLE_INT".
diff --git a/gcc/ChangeLog.MELT b/gcc/ChangeLog.MELT
index a039a288f11..4f5a2b4985d 100644
--- a/gcc/ChangeLog.MELT
+++ b/gcc/ChangeLog.MELT
@@ -1,4 +1,23 @@
+2013-11-11 Basile Starynkevitch <basile@starynkevitch.net>
+
+ {{merge with trunk GCC 4.9 svn rev 204695; very unstable}}
+ * melt-runtime.h (MELT_VERSION_STRING): Bump to "1.0.1+".
+
+ * melt-run.proto.h: Update copyright years.
+ include tree-cfg.h instead of tree-flow.h for GCC 4.9.
+
+ * melt-runtime.cc: Include tree-cfg.h not tree-flow.h for GCC 4.9.
+ (meltgc_walk_gimple_seq): Fatal error with GCC 4.9 since the
+ walk_use_def_chains function disappeared from GCC...
+
+ * melt/xtramelt-ana-gimple.melt (walk_gimple_seq)
+ (walk_gimple_seq_unique_tree): issue some #warning-s for GCC 4.9
+ because walk_use_def_chains function disappeared from GCC...
+
+ * melt/xtramelt-probe.melt (probe_docmd): Issue an error since
+ currently the MELT probe is not usable with GCC 4.9....
+
2013-11-07 Basile Starynkevitch <basile@starynkevitch.net>
* melt-runtime.h (MELT_VERSION_STRING): Bump to "1.0.1".
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index 0f54f2b0175..73f619330e8 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20130920
+20131112
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index f29a913dd16..e0c7af62961 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -135,6 +135,9 @@ 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.
@@ -193,7 +196,6 @@ GCC_WARN_CXXFLAGS = $(LOOSE_WARN) $($(@D)-warn) $(NOCOMMON_FLAG) $($@-warn)
# flex output may yield harmless "no previous prototype" warnings
build/gengtype-lex.o-warn = -Wno-error
gengtype-lex.o-warn = -Wno-error
-expmed.o-warn = -Wno-error
# 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
@@ -308,9 +310,15 @@ write_entries_to_file = $(shell rm -f $(2) || :) $(shell touch $(2)) \
# UNSORTED
# --------
-# Some compilers can't handle cc -c blah.c -o foo/blah.o.
-# In stage2 and beyond, we force this to "-o $@" since we know we're using gcc.
-OUTPUT_OPTION = @OUTPUT_OPTION@
+# 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
@@ -341,6 +349,8 @@ PLUGINLIBS = @pluginlibs@
enable_plugin = @enable_plugin@
+enable_host_shared = @enable_host_shared@
+
CPPLIB = ../libcpp/libcpp.a
CPPINC = -I$(srcdir)/../libcpp/include
@@ -371,6 +381,7 @@ USER_H = $(srcdir)/ginclude/float.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@
@@ -440,16 +451,12 @@ STRIP_FOR_TARGET := $(shell \
HASHTAB_H = $(srcdir)/../include/hashtab.h
OBSTACK_H = $(srcdir)/../include/obstack.h
SPLAY_TREE_H= $(srcdir)/../include/splay-tree.h
-FIBHEAP_H = $(srcdir)/../include/fibheap.h
-PARTITION_H = $(srcdir)/../include/partition.h
MD5_H = $(srcdir)/../include/md5.h
-DWARF2_H = $(srcdir)/../include/dwarf2.h $(srcdir)/../include/dwarf2.def
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
-LTO_SYMTAB_H = $(srcdir)/../include/lto-symtab.h
# Default native SYSTEM_HEADER_DIR, to be overridden by targets.
NATIVE_SYSTEM_HEADER_DIR = @NATIVE_SYSTEM_HEADER_DIR@
@@ -858,18 +865,15 @@ 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
-COMMON_TARGET_DEF_H = common/common-target-def.h \
- common/common-target-hooks-def.h $(HOOKS_H)
RTL_BASE_H = coretypes.h rtl.h rtl.def $(MACHMODE_H) 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 $(MACHMODE_H) double-int.h
RTL_H = $(RTL_BASE_H) $(FLAGS_H) genrtl.h
-RTL_ERROR_H = rtl-error.h $(RTL_H) $(DIAGNOSTIC_CORE_H)
READ_MD_H = $(OBSTACK_H) $(HASHTAB_H) read-md.h
PARAMS_H = params.h params.def
BUILTINS_DEF = builtins.def sync-builtins.def omp-builtins.def \
- gtm-builtins.def sanitizer.def cilkplus.def
+ gtm-builtins.def sanitizer.def cilkplus.def cilk-builtins.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 \
@@ -885,12 +889,8 @@ BASIC_BLOCK_H = basic-block.h $(PREDICT_H) $(VEC_H) $(FUNCTION_H) \
GIMPLE_H = gimple.h gimple.def gsstruct.def pointer-set.h $(VEC_H) \
$(GGC_H) $(BASIC_BLOCK_H) $(TREE_H) tree-ssa-operands.h \
tree-ssa-alias.h $(INTERNAL_FN_H) $(HASH_TABLE_H)
-TRANS_MEM_H = trans-mem.h
GCOV_IO_H = gcov-io.h gcov-iov.h auto-host.h
-COVERAGE_H = coverage.h $(GCOV_IO_H)
-DEMANGLE_H = $(srcdir)/../include/demangle.h
RECOG_H = recog.h
-ALIAS_H = alias.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)
@@ -899,11 +899,6 @@ FUNCTION_H = function.h $(HASHTAB_H) $(TM_H) hard-reg-set.h \
EXPR_H = expr.h insn-config.h $(FUNCTION_H) $(RTL_H) $(FLAGS_H) $(TREE_H) $(MACHMODE_H) $(EMIT_RTL_H)
OPTABS_H = optabs.h insn-codes.h insn-opinit.h
REGS_H = regs.h $(MACHMODE_H) hard-reg-set.h
-SCHED_INT_H = sched-int.h $(INSN_ATTR_H) $(BASIC_BLOCK_H) $(RTL_H) $(DF_H) \
- $(REGSET_H)
-SEL_SCHED_IR_H = sel-sched-ir.h $(INSN_ATTR_H) $(BASIC_BLOCK_H) $(RTL_H) \
- $(GGC_H) $(BITMAP_H) $(SCHED_INT_H) $(CFGLOOP_H) $(REGSET_H)
-SEL_SCHED_DUMP_H = sel-sched-dump.h $(SEL_SCHED_IR_H)
CFGLOOP_H = cfgloop.h $(BASIC_BLOCK_H) double-int.h \
$(BITMAP_H) sbitmap.h
IPA_UTILS_H = ipa-utils.h $(TREE_H) $(CGRAPH_H)
@@ -912,20 +907,16 @@ CGRAPH_H = cgraph.h $(VEC_H) $(TREE_H) $(BASIC_BLOCK_H) $(FUNCTION_H) \
cif-code.def ipa-ref.h ipa-ref-inline.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)
-VALTRACK_H = valtrack.h $(BITMAP_H) $(DF_H) $(RTL_H) $(BASIC_BLOCK_H) \
- $(HASH_TABLE_H)
RESOURCE_H = resource.h hard-reg-set.h $(DF_H)
-DDG_H = ddg.h sbitmap.h $(DF_H)
GCC_H = gcc.h version.h $(DIAGNOSTIC_CORE_H)
GGC_H = ggc.h gtype-desc.h statistics.h
-GGC_INTERNAL_H = ggc-internal.h $(GGC_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-tree.h $(C_COMMON_H) $(DIAGNOSTIC_H)
+C_TREE_H = c/c-tree.h $(C_COMMON_H) $(DIAGNOSTIC_H)
SYSTEM_H = system.h hwint.h $(srcdir)/../include/libiberty.h \
$(srcdir)/../include/safe-ctype.h $(srcdir)/../include/filenames.h
PREDICT_H = predict.h predict.def
@@ -933,11 +924,6 @@ CPPLIB_H = $(srcdir)/../libcpp/include/line-map.h \
$(srcdir)/../libcpp/include/cpplib.h
INPUT_H = $(srcdir)/../libcpp/include/line-map.h input.h
OPTS_H = $(INPUT_H) $(VEC_H) opts.h $(OBSTACK_H)
-DECNUM_H = $(DECNUM)/decContext.h $(DECNUM)/decDPD.h $(DECNUM)/decNumber.h \
- $(DECNUMFMT)/decimal32.h $(DECNUMFMT)/decimal64.h \
- $(DECNUMFMT)/decimal128.h $(DECNUMFMT)/decimal128Local.h
-BACKTRACE_H = $(BACKTRACE)/backtrace.h
-MKDEPS_H = $(srcdir)/../libcpp/include/mkdeps.h
SYMTAB_H = $(srcdir)/../libcpp/include/symtab.h $(OBSTACK_H)
CPP_ID_DATA_H = $(CPPLIB_H) $(srcdir)/../libcpp/include/cpp-id-data.h
CPP_INTERNAL_H = $(srcdir)/../libcpp/internal.h $(CPP_ID_DATA_H)
@@ -948,49 +934,25 @@ TREE_FLOW_H = tree-flow.h tree-flow-inline.h tree-ssa-operands.h \
$(HASHTAB_H) $(CGRAPH_H) $(IPA_REFERENCE_H) \
tree-ssa-alias.h
TREE_SSA_H = tree-ssa.h $(TREE_FLOW_H)
-TREE_HASHER_H = tree-hasher.h $(HASH_TABLE_H) $(TREE_FLOW_H)
-TREE_SSA_LIVE_H = tree-ssa-live.h $(PARTITION_H)
-SSAEXPAND_H = ssaexpand.h $(TREE_SSA_LIVE_H)
PRETTY_PRINT_H = pretty-print.h $(INPUT_H) $(OBSTACK_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)
-DWARF2OUT_H = dwarf2out.h $(DWARF2_H)
C_PRETTY_PRINT_H = c-family/c-pretty-print.h $(PRETTY_PRINT_H) \
$(C_COMMON_H) $(TREE_H)
-SCEV_H = tree-scalar-evolution.h $(GGC_H) tree-chrec.h $(PARAMS_H)
-OMEGA_H = omega.h $(PARAMS_H)
-TREE_DATA_REF_H = tree-data-ref.h $(OMEGA_H) graphds.h $(SCEV_H)
TREE_INLINE_H = tree-inline.h
REAL_H = real.h $(MACHMODE_H)
-IRA_INT_H = ira.h ira-int.h $(CFGLOOP_H) alloc-pool.h
-LRA_INT_H = lra.h $(BITMAP_H) $(RECOG_H) $(INSN_ATTR_H) insn-codes.h \
- insn-config.h $(REGS_H) lra-int.h
-DBGCNT_H = dbgcnt.h dbgcnt.def
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 pointer-set.h
-DATA_STREAMER_H = data-streamer.h $(VEC_H) $(LTO_STREAMER_H)
-GIMPLE_STREAMER_H = gimple-streamer.h $(LTO_STREAMER_H) $(BASIC_BLOCK_H) \
- $(FUNCTION_H)
-TREE_STREAMER_H = tree-streamer.h $(TREE_H) $(LTO_STREAMER_H) \
- $(STREAMER_HOOKS_H)
-STREAMER_HOOKS_H = streamer-hooks.h $(TREE_H)
-TREE_VECTORIZER_H = tree-vectorizer.h $(TREE_DATA_REF_H) $(TARGET_H) \
- $(HASH_TABLE_H)
IPA_PROP_H = ipa-prop.h $(TREE_H) $(VEC_H) $(CGRAPH_H) $(GIMPLE_H) alloc-pool.h
-IPA_INLINE_H = ipa-inline.h $(IPA_PROP_H)
-GSTAB_H = gstab.h stab.def
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
-LIBFUNCS_H = libfuncs.h $(HASHTAB_H)
-GRAPHITE_HTAB_H = graphite-htab.h graphite-clast-to-gimple.h $(HASH_TABLE_H)
CONTEXT_H = context.h
-PASS_MANAGER_H = pass_manager.h pass-instances.def
#
# Now figure out from those variables how to compile and link.
@@ -999,7 +961,7 @@ PASS_MANAGER_H = pass_manager.h pass-instances.def
# 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 @CROSS@
+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
@@ -1022,8 +984,15 @@ ALL_COMPILERFLAGS = $(ALL_CXXFLAGS)
ALL_LINKERFLAGS = $(ALL_CXXFLAGS)
# Build and host support libraries.
+
+# Use the "pic" build of libiberty if --enable-host-shared.
+ifeq ($(enable_host_shared),yes)
+LIBIBERTY = ../libiberty/pic/libiberty.a
+BUILD_LIBIBERTY = $(build_libobjdir)/libiberty/pic/libiberty.a
+else
LIBIBERTY = ../libiberty/libiberty.a
BUILD_LIBIBERTY = $(build_libobjdir)/libiberty/libiberty.a
+endif
# Dependencies on the intl and portability libraries.
LIBDEPS= libcommon.a $(CPPLIB) $(LIBIBERTY) $(LIBINTL_DEP) $(LIBICONV_DEP) \
@@ -1072,8 +1041,23 @@ INCLUDES = -I. -I$(@D) -I$(srcdir) -I$(srcdir)/$(@D) \
$(CPPINC) $(GMPINC) $(DECNUMINC) $(BACKTRACEINC) \
$(CLOOGINC) $(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:
- $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $< $(OUTPUT_OPTION)
+ $(COMPILE) $<
+ $(POSTCOMPILE)
#
# Support for additional languages (other than C).
@@ -1150,15 +1134,12 @@ GCC_OBJS = gcc.o ggc-none.o
c-family-warn = $(STRICT_WARN)
# Language-specific object files shared by all C-family front ends.
-# FIXME: tree-mudflap is C-family only, but it is also part of the middle-end.
-# The mudflap machinery should be properly separated from the front ends, and
-# perhaps turned into a plugin.
C_COMMON_OBJS = c-family/c-common.o c-family/c-cppbuiltin.o c-family/c-dump.o \
c-family/c-format.o c-family/c-gimplify.o c-family/c-lex.o \
c-family/c-omp.o c-family/c-opts.o c-family/c-pch.o \
c-family/c-ppoutput.o c-family/c-pragma.o c-family/c-pretty-print.o \
- c-family/c-semantics.o c-family/c-ada-spec.o tree-mudflap.o \
- c-family/array-notation-common.o c-family/c-ubsan.o
+ c-family/c-semantics.o c-family/c-ada-spec.o \
+ c-family/array-notation-common.o c-family/cilk.o c-family/c-ubsan.o
# Language-independent object files.
# We put the insn-*.o files first so that a parallel make will build
@@ -1204,6 +1185,7 @@ OBJS = \
cgraphbuild.o \
cgraphunit.o \
cgraphclones.o \
+ cilk-common.o \
combine.o \
combine-stack-adj.o \
compare-elim.o \
@@ -1250,10 +1232,13 @@ OBJS = \
gcse.o \
ggc-common.o \
gimple.o \
+ gimple-builder.o \
+ gimple-expr.o \
gimple-iterator.o \
gimple-fold.o \
gimple-low.o \
gimple-pretty-print.o \
+ gimple-ssa-isolate-paths.o \
gimple-ssa-strength-reduction.o \
gimple-streamer-in.o \
gimple-streamer-out.o \
@@ -1348,7 +1333,6 @@ OBJS = \
reg-stack.o \
regcprop.o \
reginfo.o \
- regmove.o \
regrename.o \
regstat.o \
reload.o \
@@ -1406,10 +1390,8 @@ OBJS = \
tree-iterator.o \
tree-loop-distribution.o \
tree-nested.o \
- tree-nomudflap.o \
tree-nrv.o \
tree-object-size.o \
- tree-optimize.o \
tree-outof-ssa.o \
tree-parloops.o \
tree-phinodes.o \
@@ -1502,7 +1484,8 @@ ALL_HOST_FRONTEND_OBJS = $(foreach v,$(CONFIG_LANGUAGES),$($(v)_OBJS))
ALL_HOST_BACKEND_OBJS = $(GCC_OBJS) $(OBJS) $(OBJS-libcommon) \
$(OBJS-libcommon-target) @TREEBROWSER@ main.o c-family/cppspec.o \
- $(COLLECT2_OBJS) $(EXTRA_GCC_OBJS) $(GCOV_OBJS) $(GCOV_DUMP_OBJS)
+ $(COLLECT2_OBJS) $(EXTRA_GCC_OBJS) $(GCOV_OBJS) $(GCOV_DUMP_OBJS) \
+ lto-wrapper.o
# This lists all host object files, whether they are included in this
# compilation or not.
@@ -1884,13 +1867,6 @@ srcextra: gcc.srcextra lang.srcextra
gcc.srcextra: gengtype-lex.c
-cp -p $^ $(srcdir)
-graph.o: graph.c graph.h $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(DIAGNOSTIC_CORE_H) sbitmap.h $(BASIC_BLOCK_H) $(CFGLOOP_H) \
- $(PRETTY_PRINT_H) $(DUMPFILE_H)
-
-sbitmap.o: sbitmap.c sbitmap.h $(CONFIG_H) $(SYSTEM_H) coretypes.h
-sparseset.o: sparseset.c $(SYSTEM_H) sparseset.h $(CONFIG_H)
-
AR_OBJS = file-find.o
AR_LIBS = @COLLECT2_LIBS@
@@ -1910,20 +1886,14 @@ CFLAGS-gcc-ar.o += $(DRIVER_DEFINES) \
-DTARGET_MACHINE=\"$(target_noncanonical)\" \
@TARGET_SYSTEM_ROOT_DEFINE@ -DPERSONALITY=\"ar\"
-gcc-ar.o: gcc-ar.c $(CONFIG_H) $(SYSTEM_H) $(LIBIBERTY_H)
-
CFLAGS-gcc-ranlib.o += $(DRIVER_DEFINES) \
-DTARGET_MACHINE=\"$(target_noncanonical)\" \
@TARGET_SYSTEM_ROOT_DEFINE@ -DPERSONALITY=\"ranlib\"
-gcc-ranlib.o: gcc-ranlib.c $(CONFIG_H) $(SYSTEM_H) $(LIBIBERTY_H)
-
CFLAGS-gcc-nm.o += $(DRIVER_DEFINES) \
-DTARGET_MACHINE=\"$(target_noncanonical)\" \
@TARGET_SYSTEM_ROOT_DEFINE@ -DPERSONALITY=\"nm\"
-gcc-nm.o: gcc-nm.c $(CONFIG_H) $(SYSTEM_H) $(LIBIBERTY_H)
-
# ??? the implicit rules dont trigger if the source file has a different name
# so copy instead
gcc-ranlib.c: gcc-ar.c
@@ -1942,129 +1912,26 @@ collect2$(exeext): $(COLLECT2_OBJS) $(LIBDEPS)
CFLAGS-collect2.o += -DTARGET_MACHINE=\"$(target_noncanonical)\" \
@TARGET_SYSTEM_ROOT_DEFINE@
-collect2.o : collect2.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) intl.h \
- $(OBSTACK_H) $(DEMANGLE_H) collect2.h collect2-aix.h version.h \
- $(DIAGNOSTIC_H) file-find.h
-
-collect2-aix.o : collect2-aix.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- collect2-aix.h
-
-tlink.o: tlink.c $(DEMANGLE_H) $(HASHTAB_H) $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(OBSTACK_H) collect2.h intl.h $(DIAGNOSTIC_CORE_H) $(VEC_H)
lto-wrapper$(exeext): lto-wrapper.o ggc-none.o libcommon-target.a $(LIBDEPS)
+$(LINKER) $(ALL_COMPILERFLAGS) $(LDFLAGS) -o T$@ \
lto-wrapper.o ggc-none.o libcommon-target.a $(LIBS)
mv -f T$@ $@
-lto-wrapper.o: lto-wrapper.c $(CONFIG_H) $(SYSTEM_H) coretypes.h intl.h \
- $(OBSTACK_H) $(DIAGNOSTIC_H) $(OPTS_H) $(OPTIONS_H)
-
# Files used by all variants of C or by the stand-alone pre-processor.
-c-family/cppspec.o: c-family/cppspec.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(GCC_H) $(OPTS_H)
-
-c-family/c-common.o : c-family/c-common.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(TREE_H) \
- $(OBSTACK_H) $(C_COMMON_H) $(FLAGS_H) toplev.h output.h $(C_PRAGMA_H) \
- $(GGC_H) builtin-types.def builtin-attrs.def \
- $(DIAGNOSTIC_H) langhooks.h c-family/c-objc.h \
- $(TARGET_H) tree-iterator.h langhooks.h tree-mudflap.h \
- intl.h $(OPTS_H) $(CPPLIB_H) $(TREE_INLINE_H) $(HASHTAB_H) \
- $(BUILTINS_DEF) $(CGRAPH_H) $(TARGET_DEF_H) \
- gt-c-family-c-common.h $(COMMON_TARGET_H)
-
-c-family/c-cppbuiltin.o : c-family/c-cppbuiltin.c $(CONFIG_H) $(SYSTEM_H) \
- coretypes.h $(TM_H) $(TREE_H) version.h $(C_COMMON_H) $(C_PRAGMA_H) \
- $(FLAGS_H) output.h $(TREE_H) $(TARGET_H) $(COMMON_TARGET_H) \
- $(TM_P_H) debug.h $(CPP_ID_DATA_H) cppbuiltin.h
-
-c-family/c-dump.o : c-family/c-dump.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(TREE_H) $(TREE_DUMP_H)
-
-c-family/c-format.o : c-family/c-format.c c-family/c-format.h \
- $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) langhooks.h \
- $(C_COMMON_H) $(FLAGS_H) intl.h $(C_TARGET_H) \
- $(DIAGNOSTIC_CORE_H) alloc-pool.h c-family/c-objc.h
-
-c-family/c-gimplify.o : c-family/c-gimplify.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) \
- $(C_COMMON_H) $(DIAGNOSTIC_CORE_H) $(GIMPLE_H) \
- $(FLAGS_H) langhooks.h $(LANGHOOKS_DEF_H) \
- $(TM_H) coretypes.h $(C_PRETTY_PRINT_H) $(CGRAPH_H) \
- $(DUMPFILE_H) $(TREE_INLINE_H)
-
-c-family/c-lex.o : c-family/c-lex.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(TREE_H) $(FIXED_VALUE_H) debug.h $(C_COMMON_H) $(SPLAY_TREE_H) \
- $(C_PRAGMA_H) $(INPUT_H) intl.h $(FLAGS_H) \
- $(CPPLIB_H) $(TARGET_H) $(TIMEVAR_H)
-
-c-family/c-omp.o : c-family/c-omp.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TREE_H) $(C_COMMON_H) $(GIMPLE_H) langhooks.h
CFLAGS-c-family/c-opts.o += @TARGET_SYSTEM_ROOT_DEFINE@
-c-family/c-opts.o : c-family/c-opts.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TREE_H) $(C_PRAGMA_H) $(FLAGS_H) toplev.h langhooks.h \
- $(DIAGNOSTIC_H) intl.h debug.h $(C_COMMON_H) $(C_TARGET_H) \
- $(OPTS_H) $(OPTIONS_H) $(MKDEPS_H) incpath.h cppdefault.h
CFLAGS-c-family/c-pch.o += -DHOST_MACHINE=\"$(host)\" \
-DTARGET_MACHINE=\"$(target)\"
-c-family/c-pch.o : c-family/c-pch.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(CPPLIB_H) $(TREE_H) $(C_COMMON_H) output.h $(C_PRAGMA_H) \
- $(GGC_H) debug.h langhooks.h $(FLAGS_H) hosthooks.h version.h \
- $(TARGET_H) $(OPTS_H) $(TIMEVAR_H)
-
-c-family/c-ppoutput.o : c-family/c-ppoutput.c $(CONFIG_H) $(SYSTEM_H) \
- coretypes.h $(C_COMMON_H) $(TREE_H) $(CPPLIB_H) $(CPP_INTERNAL_H) \
- $(C_PRAGMA_H)
-
-c-family/c-pragma.o: c-family/c-pragma.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(TREE_H) $(FUNCTION_H) $(C_PRAGMA_H) output.h \
- $(TM_P_H) $(C_COMMON_H) $(TARGET_H) $(CPPLIB_H) $(FLAGS_H) \
- $(DIAGNOSTIC_H) $(OPTS_H) $(PLUGINS_H) \
- gt-c-family-c-pragma.h
-
-c-family/c-pretty-print.o : c-family/c-pretty-print.c $(C_PRETTY_PRINT_H) \
- $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(DIAGNOSTIC_H) tree-iterator.h intl.h $(TREE_PRETTY_PRINT_H)
-
-c-family/c-semantics.o : c-family/c-semantics.c $(CONFIG_H) $(SYSTEM_H) \
- coretypes.h $(TM_H) $(TREE_H) $(FLAGS_H) \
- $(C_COMMON_H) $(FUNCTION_H) langhooks.h $(SPLAY_TREE_H) $(TIMEVAR_H) \
- tree-iterator.h
-
-c-family/c-ada-spec.o : c-family/c-ada-spec.c c-family/c-ada-spec.h \
- $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(CPP_ID_DATA_H) $(TM_H) \
- coretypes.h tree-iterator.h $(DUMPFILE_H)
-
-c-family/array-notation-common.o : c-family/array-notation-common.c $(TREE_H) \
- $(SYSTEM_H) $(TREE_H) coretypes.h tree-iterator.h $(DIAGNOSTIC_CORE_H)
-
-c-family/stub-objc.o : c-family/stub-objc.c $(CONFIG_H) $(SYSTEM_H) \
- coretypes.h $(TREE_H) $(C_COMMON_H) c-family/c-objc.h
-
-c-family/c-ubsan.o : c-family/c-ubsan.c $(CONFIG_H) $(SYSTEM_H) \
- coretypes.h $(TREE_H) $(C_COMMON_H) c-family/c-ubsan.h \
- alloc-pool.h $(CGRAPH_H) $(GIMPLE_H) $(HASH_TABLE_H) output.h \
- toplev.h ubsan.h
-default-c.o: config/default-c.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(C_TARGET_H) $(C_TARGET_DEF_H)
- $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) \
- $< $(OUTPUT_OPTION)
-
-# Files used by all variants of C and some other languages.
-attribs.o : attribs.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
- $(HASH_TABLE_H) $(FLAGS_H) $(DIAGNOSTIC_CORE_H) $(GGC_H) $(TM_P_H) \
- $(TARGET_H) langhooks.h $(CPPLIB_H) $(PLUGIN_H)
+default-c.o: config/default-c.c
+ $(COMPILE) $<
+ $(POSTCOMPILE)
-incpath.o: incpath.c incpath.h $(CONFIG_H) $(SYSTEM_H) $(CPPLIB_H) \
- intl.h prefix.h coretypes.h $(TM_H) cppdefault.h $(TARGET_H) \
- $(MACHMODE_H)
+# Files used by all variants of C and some other languages.
CFLAGS-prefix.o += -DPREFIX=\"$(prefix)\" -DBASEVER=$(BASEVER_s)
-prefix.o: prefix.c $(CONFIG_H) $(SYSTEM_H) coretypes.h prefix.h \
- $(COMMON_TARGET_H) Makefile $(BASEVER)
# Language-independent files.
@@ -2078,16 +1945,10 @@ DRIVER_DEFINES = \
-DTOOLDIR_BASE_PREFIX=\"$(libsubdir_to_prefix)$(prefix_to_exec_prefix)\" \
@TARGET_SYSTEM_ROOT_DEFINE@ \
$(VALGRIND_DRIVER_DEFINES) \
- `test "X$${SHLIB}" = "X" || test "@enable_shared@" != "yes" || echo "-DENABLE_SHARED_LIBGCC"` \
+ $(if $(SHLIB),$(if $(filter yes,@enable_shared@),-DENABLE_SHARED_LIBGCC)) \
-DCONFIGURE_SPECS="\"@CONFIGURE_SPECS@\""
-gcc.o: gcc.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) intl.h multilib.h \
- Makefile $(lang_specs_files) specs.h prefix.h $(GCC_H) $(FLAGS_H) \
- configargs.h $(OBSTACK_H) $(OPTS_H) $(DIAGNOSTIC_H) $(VEC_H) $(PARAMS_H)
- (SHLIB='$(SHLIB)'; \
- $(COMPILER) $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) \
- $(DRIVER_DEFINES) \
- -c $(srcdir)/gcc.c $(OUTPUT_OPTION))
+CFLAGS-gcc.o += $(DRIVER_DEFINES)
specs.h : s-specs ; @true
s-specs : Makefile
@@ -2124,619 +1985,15 @@ s-options-h: optionlist $(srcdir)/opt-functions.awk $(srcdir)/opt-read.awk \
$(SHELL) $(srcdir)/../move-if-change tmp-options.h options.h
$(STAMP) $@
-options.o: options.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(OPTS_H) intl.h $(OPTIONS_C_EXTRA) insn-attr-common.h
-
-options-save.o: options-save.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TARGET_H) $(FLAGS_H) \
- $(TM_H) $(OPTS_H) intl.h $(OPTIONS_C_EXTRA)
-
dumpvers: dumpvers.c
CFLAGS-version.o += -DBASEVER=$(BASEVER_s) -DDATESTAMP=$(DATESTAMP_s) \
-DREVISION=$(REVISION_s) \
-DDEVPHASE=$(DEVPHASE_s) -DPKGVERSION=$(PKGVERSION_s) \
-DBUGURL=$(BUGURL_s)
-version.o: version.c version.h $(REVISION) $(DATESTAMP) $(BASEVER) $(DEVPHASE)
-
-gtype-desc.o: gtype-desc.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(HASHTAB_H) $(SPLAY_TREE_H) $(OBSTACK_H) $(BITMAP_H) \
- $(INPUT_H) $(TREE_H) $(RTL_H) $(FUNCTION_H) insn-config.h $(EXPR_H) \
- hard-reg-set.h $(BASIC_BLOCK_H) cselib.h $(INSN_ADDR_H) $(OPTABS_H) \
- $(LIBFUNCS_H) debug.h $(GGC_H) $(CGRAPH_H) $(TREE_SSA_H) reload.h \
- $(CPP_ID_DATA_H) tree-chrec.h $(EXCEPT_H) output.h \
- $(CFGLOOP_H) $(TARGET_H) $(IPA_PROP_H) $(LTO_STREAMER_H) \
- target-globals.h
-
-trans-mem.o : trans-mem.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(HASH_TABLE_H) \
- $(TREE_H) $(GIMPLE_H) $(TREE_SSA_H) $(TREE_PASS_H) $(TREE_INLINE_H) \
- $(DIAGNOSTIC_CORE_H) $(DEMANGLE_H) output.h $(TRANS_MEM_H) \
- $(PARAMS_H) $(TARGET_H) langhooks.h \
- $(GIMPLE_PRETTY_PRINT_H) $(CFGLOOP_H) \
- gt-trans-mem.h
-
-ggc-common.o: ggc-common.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(GGC_H) $(HASH_TABLE_H) $(DIAGNOSTIC_CORE_H) $(PARAMS_H) hosthooks.h \
- $(HOSTHOOKS_DEF_H) $(VEC_H) $(PLUGIN_H) $(GGC_INTERNAL_H) $(TIMEVAR_H)
-
-ggc-page.o: ggc-page.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) \
- $(FLAGS_H) $(DIAGNOSTIC_CORE_H) $(GGC_H) $(TIMEVAR_H) $(TM_P_H) $(PARAMS_H) \
- $(TREE_SSA_H) $(PLUGIN_H) $(GGC_INTERNAL_H)
-
-ggc-none.o: ggc-none.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(GGC_H) \
- $(BCONFIG_H)
-
-stringpool.o: stringpool.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TREE_H) $(GGC_H) $(GGC_INTERNAL_H) gt-stringpool.h $(CPPLIB_H) $(SYMTAB_H)
-
-convert.o: convert.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
- $(FLAGS_H) convert.h $(DIAGNOSTIC_CORE_H) langhooks.h
-
-double-int.o: double-int.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H)
# lto-compress.o needs $(ZLIBINC) added to the include flags.
CFLAGS-lto-compress.o += $(ZLIBINC)
-lto-compress.o: lto-compress.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TREE_H) langhooks.h $(LTO_STREAMER_H) $(LTO_SECTION_H) \
- lto-compress.h $(DIAGNOSTIC_CORE_H) $(DIAGNOSTIC_CORE_H)
-data-streamer-in.o: data-streamer-in.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(DATA_STREAMER_H) $(DIAGNOSTIC_H) value-prof.h
-data-streamer-out.o: data-streamer-out.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(DATA_STREAMER_H) value-prof.h
-data-streamer.o: data-streamer.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(DATA_STREAMER_H)
-gimple-streamer-in.o: gimple-streamer-in.c $(CONFIG_H) $(SYSTEM_H) \
- coretypes.h $(GIMPLE_STREAMER_H) $(TREE_SSA_H) $(DATA_STREAMER_H) \
- $(TREE_STREAMER_H) $(DIAGNOSTIC_H)
-gimple-streamer-out.o: gimple-streamer-out.c $(CONFIG_H) $(SYSTEM_H) \
- coretypes.h $(GIMPLE_STREAMER_H) $(DATA_STREAMER_H) $(TREE_SSA_H) \
- $(LTO_STREAMER_H) $(TREE_STREAMER_H)
-tree-streamer.o: tree-streamer.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TREE_STREAMER_H) $(STREAMER_HOOKS_H)
-tree-streamer-in.o: tree-streamer-in.c $(CONFIG_H) $(SYSTEM_H) \
- coretypes.h $(DIAGNOSTIC_H) $(TREE_H) $(TREE_SSA_H) $(TREE_STREAMER_H) \
- $(DATA_STREAMER_H) $(STREAMER_HOOKS_H) $(LTO_STREAMER_H)
-tree-streamer-out.o: tree-streamer-out.c $(CONFIG_H) $(SYSTEM_H) \
- coretypes.h $(DIAGNOSTIC_H) $(TREE_STREAMER_H) $(DATA_STREAMER_H) \
- $(STREAMER_HOOKS_H) $(TM_H)
-streamer-hooks.o: streamer-hooks.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(STREAMER_HOOKS_H)
-lto-cgraph.o: lto-cgraph.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(DIAGNOSTIC_CORE_H) $(EXPR_H) $(FLAGS_H) $(PARAMS_H) input.h \
- $(HASHTAB_H) langhooks.h $(BASIC_BLOCK_H) \
- $(TREE_FLOW_H) $(CGRAPH_H) $(FUNCTION_H) $(GGC_H) $(DIAGNOSTIC_CORE_H) \
- $(EXCEPT_H) $(TIMEVAR_H) pointer-set.h $(LTO_STREAMER_H) \
- $(GCOV_IO_H) $(DATA_STREAMER_H) $(TREE_STREAMER_H) $(TREE_PASS_H) \
- profile.h $(CONTEXT_H) $(PASS_MANAGER_H) ipa-utils.h
-lto-streamer-in.o: lto-streamer-in.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) toplev.h $(DIAGNOSTIC_CORE_H) $(EXPR_H) $(FLAGS_H) $(PARAMS_H) \
- input.h $(HASHTAB_H) $(BASIC_BLOCK_H) $(TREE_FLOW_H) $(TREE_PASS_H) \
- $(CGRAPH_H) $(FUNCTION_H) $(GGC_H) $(DIAGNOSTIC_H) $(EXCEPT_H) debug.h \
- $(IPA_UTILS_H) $(LTO_STREAMER_H) toplev.h $(CFGLOOP_H) \
- $(DATA_STREAMER_H) $(GIMPLE_STREAMER_H) $(TREE_STREAMER_H)
-lto-streamer-out.o : lto-streamer-out.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(DIAGNOSTIC_CORE_H) $(TREE_H) $(EXPR_H) $(FLAGS_H) $(PARAMS_H) input.h \
- $(HASHTAB_H) $(BASIC_BLOCK_H) tree-iterator.h $(CFGLOOP_H) \
- $(TREE_FLOW_H) $(TREE_PASS_H) $(CGRAPH_H) $(FUNCTION_H) $(GGC_H) \
- $(DIAGNOSTIC_CORE_H) $(EXCEPT_H) $(LTO_STREAMER_H) $(DIAGNOSTIC_CORE_H) \
- $(DATA_STREAMER_H) $(STREAMER_HOOKS_H) $(GIMPLE_STREAMER_H) \
- $(TREE_STREAMER_H)
-lto-section-in.o: lto-section-in.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(DIAGNOSTIC_CORE_H) $(EXPR_H) $(FLAGS_H) $(PARAMS_H) input.h \
- $(HASHTAB_H) $(BASIC_BLOCK_H) $(TREE_FLOW_H) $(CGRAPH_H) $(FUNCTION_H) \
- $(GGC_H) $(DIAGNOSTIC_CORE_H) $(EXCEPT_H) $(TIMEVAR_H) \
- $(LTO_STREAMER_H) lto-compress.h
-lto-section-out.o : lto-section-out.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(DIAGNOSTIC_CORE_H) $(TREE_H) $(EXPR_H) $(PARAMS_H) input.h \
- $(HASHTAB_H) $(BASIC_BLOCK_H) $(TREE_FLOW_H) \
- $(CGRAPH_H) $(FUNCTION_H) $(GGC_H) $(EXCEPT_H) pointer-set.h \
- $(BITMAP_H) langhooks.h $(LTO_STREAMER_H) lto-compress.h \
- $(DATA_STREAMER_H)
-lto-opts.o: lto-opts.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TREE_H) \
- $(HASHTAB_H) $(GGC_H) $(BITMAP_H) $(FLAGS_H) $(OPTS_H) $(OPTIONS_H) \
- $(COMMON_TARGET_H) $(DIAGNOSTIC_H) $(LTO_STREAMER_H)
-lto-streamer.o: lto-streamer.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(TREE_H) $(GIMPLE_H) $(BITMAP_H) $(LTO_STREAMER_H) $(FLAGS_H) \
- $(TREE_SSA_H) $(DIAGNOSTIC_CORE_H) $(LTO_SYMTAB_H) toplev.h \
- $(DIAGNOSTIC_CORE_H) $(STREAMER_HOOKS_H)
-langhooks.o : langhooks.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TIMEVAR_H) \
- $(TREE_H) toplev.h $(DIAGNOSTIC_CORE_H) $(TREE_INLINE_H) $(RTL_H) insn-config.h \
- langhooks.h $(TARGET_H) $(LANGHOOKS_DEF_H) $(FLAGS_H) $(GGC_H) $(DIAGNOSTIC_H) \
- intl.h $(GIMPLE_H) $(CGRAPH_H) output.h tree-diagnostic.h
-test-dump.o : test-dump.c $(CONFIG_H) $(SYSTEM_H) $(CORETYPES_H) \
- $(BITMAP_H) sbitmap.h sreal.h $(TREE_H) $(CXX_PARSER_H) $(DWARF2OUT_H) \
- $(GIMPLE_PRETTY_PRINT_H) $(BASIC_BLOCK_H) insn-config.h $(LRA_INT.H) \
- $(SEL_SCHED_DUMP_H) $(IRA_INT_H) $(TREE_DATA_REF_H) $(TREE_SSA_H) \
- $(TREE_SSA_LIVE_H) tree-ssa-alias.h $(OMEGA_H) $(RTL_H)
-tree.o: tree.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
- all-tree.def $(FLAGS_H) $(FUNCTION_H) $(PARAMS_H) \
- toplev.h $(DIAGNOSTIC_CORE_H) $(GGC_H) $(HASHTAB_H) $(TARGET_H) output.h $(TM_P_H) \
- langhooks.h gt-tree.h $(TREE_INLINE_H) tree-iterator.h \
- $(BASIC_BLOCK_H) $(TREE_SSA_H) $(OBSTACK_H) pointer-set.h \
- $(TREE_PASS_H) $(LANGHOOKS_DEF_H) $(DIAGNOSTIC_H) $(CGRAPH_H) \
- $(EXCEPT_H) debug.h intl.h tree-diagnostic.h $(TREE_PRETTY_PRINT_H) \
- $(COMMON_TARGET_H)
-tree-dump.o: tree-dump.c $(CONFIG_H) $(SYSTEM_H) $(TM_H) $(TREE_H) \
- langhooks.h $(TREE_DUMP_H) tree-iterator.h $(TREE_PRETTY_PRINT_H)
-tree-inline.o : tree-inline.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(TREE_H) $(RTL_H) $(FLAGS_H) $(PARAMS_H) $(INPUT_H) insn-config.h \
- $(HASHTAB_H) langhooks.h $(TREE_INLINE_H) $(CGRAPH_H) \
- intl.h $(FUNCTION_H) $(GIMPLE_H) $(CFGLOOP_H) \
- debug.h $(DIAGNOSTIC_H) $(EXCEPT_H) $(TREE_SSA_H) tree-iterator.h tree-mudflap.h \
- $(IPA_PROP_H) value-prof.h $(TREE_PASS_H) $(TARGET_H) \
- $(TREE_PRETTY_PRINT_H)
-print-tree.o : print-tree.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(DUMPFILE_H) \
- $(TM_H) $(TREE_H) $(GGC_H) langhooks.h tree-iterator.h \
- $(DIAGNOSTIC_H) $(TREE_SSA_H) $(GIMPLE_PRETTY_PRINT_H) $(TREE_DUMP_H)
-stor-layout.o : stor-layout.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(TREE_H) $(PARAMS_H) $(FLAGS_H) $(FUNCTION_H) $(EXPR_H) $(RTL_H) \
- $(GGC_H) $(TM_P_H) $(TARGET_H) langhooks.h $(REGS_H) gt-stor-layout.h \
- $(DIAGNOSTIC_CORE_H) $(CGRAPH_H) $(TREE_INLINE_H) $(TREE_DUMP_H) $(GIMPLE_H)
-asan.o : asan.c asan.h $(CONFIG_H) $(SYSTEM_H) $(GIMPLE_H) \
- output.h coretypes.h $(GIMPLE_PRETTY_PRINT_H) $(CFGLOOP_H) \
- tree-iterator.h $(TREE_SSA_H) $(TREE_PASS_H) \
- $(TARGET_H) $(EXPR_H) $(OPTABS_H) $(TM_P_H) langhooks.h \
- $(HASH_TABLE_H) alloc-pool.h
-tsan.o : $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(TREE_INLINE_H) \
- $(GIMPLE_H) $(DIAGNOSTIC_H) langhooks.h \
- $(TM_H) coretypes.h $(TREE_DUMP_H) $(TREE_PASS_H) $(CGRAPH_H) $(GGC_H) \
- $(BASIC_BLOCK_H) $(FLAGS_H) $(FUNCTION_H) \
- $(TM_P_H) $(TREE_SSA_H) $(DIAGNOSTIC_CORE_H) $(GIMPLE_H) tree-iterator.h \
- intl.h cfghooks.h output.h options.h $(C_COMMON_H) tsan.h asan.h \
- tree-ssa-propagate.h
-ubsan.o : ubsan.c ubsan.h $(CONFIG_H) $(SYSTEM_H) $(GIMPLE_H) \
- output.h coretypes.h $(TREE_H) $(CGRAPH_H) $(HASHTAB_H) gt-ubsan.h \
- toplev.h $(C_COMMON_H) $(TM_P_H)
-tree-ssa-tail-merge.o: tree-ssa-tail-merge.c \
- $(SYSTEM_H) $(CONFIG_H) coretypes.h $(TM_H) $(BITMAP_H) \
- $(FLAGS_H) $(TM_P_H) $(BASIC_BLOCK_H) $(CFGLOOP_H) \
- $(TREE_H) $(TREE_SSA_H) $(TREE_INLINE_H) $(TREE_DUMP_H) $(HASH_TABLE_H) \
- $(GIMPLE_H) $(FUNCTION_H) tree-ssa-sccvn.h \
- $(CGRAPH_H) $(GIMPLE_PRETTY_PRINT_H) $(PARAMS_H)
-tree-ssa-structalias.o: tree-ssa-structalias.c $(SYSTEM_H) $(CONFIG_H) \
- coretypes.h $(HASH_TABLE_H) $(TM_H) $(GGC_H) $(OBSTACK_H) $(BITMAP_H) \
- $(FLAGS_H) $(TM_P_H) $(BASIC_BLOCK_H) \
- $(DIAGNOSTIC_H) $(TREE_H) $(TREE_SSA_H) $(TREE_INLINE_H) \
- $(GIMPLE_H) $(HASH_TABLE_H) $(FUNCTION_H) $(CGRAPH_H) \
- $(TREE_PASS_H) alloc-pool.h $(SPLAY_TREE_H) $(PARAMS_H) \
- $(CGRAPH_H) $(ALIAS_H) pointer-set.h
-tree-ssa-uninit.o : tree-ssa-uninit.c $(TREE_SSA_H) $(CONFIG_H) $(SYSTEM_H) \
- $(TREE_H) $(TM_P_H) $(DIAGNOSTIC_H) \
- $(FUNCTION_H) $(TM_H) coretypes.h \
- $(TREE_PASS_H) $(BASIC_BLOCK_H) $(BITMAP_H) \
- $(FLAGS_H) $(HASHTAB_H) pointer-set.h \
- $(GIMPLE_H) $(TREE_INLINE_H) $(GIMPLE_PRETTY_PRINT_H)
-tree-ssa.o : tree-ssa.c $(TREE_SSA_H) $(CONFIG_H) $(SYSTEM_H) \
- $(HASH_TABLE_H) $(TREE_H) $(TM_P_H) $(EXPR_H) $(DIAGNOSTIC_H) \
- toplev.h $(FUNCTION_H) $(TM_H) coretypes.h \
- langhooks.h $(TREE_PASS_H) $(BASIC_BLOCK_H) $(BITMAP_H) \
- $(FLAGS_H) $(GGC_H) $(HASHTAB_H) pointer-set.h \
- $(GIMPLE_H) $(TREE_INLINE_H) $(TARGET_H) \
- $(GIMPLE_PRETTY_PRINT_H) $(CFGLOOP_H)
-tree-into-ssa.o : tree-into-ssa.c $(TREE_SSA_H) $(CONFIG_H) $(SYSTEM_H) \
- $(TREE_H) $(TM_P_H) $(DIAGNOSTIC_CORE_H) \
- $(FUNCTION_H) $(TM_H) coretypes.h \
- langhooks.h domwalk.h $(TREE_PASS_H) $(PARAMS_H) $(BASIC_BLOCK_H) \
- $(BITMAP_H) $(CFGLOOP_H) $(FLAGS_H) $(HASH_TABLE_H) \
- $(GIMPLE_H) $(TREE_INLINE_H) $(GIMPLE_PRETTY_PRINT_H)
-tree-ssa-ter.o : tree-ssa-ter.c $(TREE_SSA_H) $(CONFIG_H) $(SYSTEM_H) \
- $(TREE_H) $(DIAGNOSTIC_H) $(TM_H) coretypes.h $(DUMPFILE_H) \
- $(TREE_SSA_LIVE_H) $(BITMAP_H) $(FLAGS_H) \
- $(GIMPLE_PRETTY_PRINT_H)
-tree-ssa-coalesce.o : tree-ssa-coalesce.c $(TREE_SSA_H) $(CONFIG_H) \
- $(SYSTEM_H) $(TREE_H) $(DIAGNOSTIC_H) $(TM_H) coretypes.h $(DUMPFILE_H) \
- $(TREE_SSA_LIVE_H) $(BITMAP_H) $(FLAGS_H) $(HASH_TABLE_H) \
- $(TREE_PRETTY_PRINT_H)
-tree-outof-ssa.o : tree-outof-ssa.c $(TREE_SSA_H) $(CONFIG_H) $(SYSTEM_H) \
- $(TREE_H) $(DIAGNOSTIC_H) $(TM_H) coretypes.h $(DUMPFILE_H) \
- $(TREE_SSA_LIVE_H) $(BASIC_BLOCK_H) $(BITMAP_H) $(GGC_H) \
- $(EXPR_H) $(SSAEXPAND_H) $(GIMPLE_PRETTY_PRINT_H)
-tree-ssa-dse.o : tree-ssa-dse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(GGC_H) $(TREE_H) $(TM_P_H) $(BASIC_BLOCK_H) \
- $(TREE_SSA_H) $(TREE_PASS_H) domwalk.h $(FLAGS_H) \
- $(GIMPLE_PRETTY_PRINT_H) langhooks.h
-tree-ssa-forwprop.o : tree-ssa-forwprop.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(TREE_H) $(TM_P_H) $(BASIC_BLOCK_H) $(CFGLOOP_H) \
- $(TREE_SSA_H) $(TREE_PASS_H) $(DIAGNOSTIC_H) \
- langhooks.h $(FLAGS_H) $(GIMPLE_H) $(GIMPLE_PRETTY_PRINT_H) $(EXPR_H) \
- $(OPTABS_H) tree-ssa-propagate.h
-tree-ssa-phiprop.o : tree-ssa-phiprop.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(TREE_H) $(TM_P_H) $(BASIC_BLOCK_H) \
- $(TREE_SSA_H) $(TREE_PASS_H) $(DIAGNOSTIC_H) \
- langhooks.h $(FLAGS_H) $(GIMPLE_PRETTY_PRINT_H)
-tree-ssa-ifcombine.o : tree-ssa-ifcombine.c $(CONFIG_H) $(SYSTEM_H) \
- coretypes.h $(TM_H) $(TREE_H) $(BASIC_BLOCK_H) \
- $(TREE_SSA_H) $(TREE_PASS_H) $(DIAGNOSTIC_H) \
- $(TREE_PRETTY_PRINT_H)
-tree-ssa-phiopt.o : tree-ssa-phiopt.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(HASH_TABLE_H) $(TM_H) $(GGC_H) $(TREE_H) $(TM_P_H) $(BASIC_BLOCK_H) \
- $(TREE_SSA_H) $(TREE_PASS_H) langhooks.h $(FLAGS_H) \
- $(DIAGNOSTIC_H) pointer-set.h domwalk.h $(CFGLOOP_H) \
- $(TREE_DATA_REF_H) $(TREE_PRETTY_PRINT_H) $(GIMPLE_PRETTY_PRINT_H) \
- insn-config.h $(EXPR_H) $(OPTABS_H) $(SCEV_H)
-tree-nrv.o : tree-nrv.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(TREE_H) $(FUNCTION_H) $(BASIC_BLOCK_H) $(FLAGS_H) \
- $(DIAGNOSTIC_H) $(TREE_SSA_H) $(TREE_PASS_H) \
- langhooks.h $(TREE_PRETTY_PRINT_H)
-tree-ssa-copy.o : tree-ssa-copy.c $(TREE_SSA_H) $(CONFIG_H) $(SYSTEM_H) \
- $(TREE_H) $(TM_P_H) $(GGC_H) $(DIAGNOSTIC_H) \
- $(FUNCTION_H) $(TM_H) coretypes.h $(SCEV_H) \
- $(BASIC_BLOCK_H) $(TREE_PASS_H) langhooks.h tree-ssa-propagate.h \
- $(FLAGS_H) $(CFGLOOP_H) $(GIMPLE_PRETTY_PRINT_H)
-tree-ssa-propagate.o : tree-ssa-propagate.c $(TREE_SSA_H) $(CONFIG_H) \
- $(SYSTEM_H) $(TREE_H) $(TM_P_H) \
- $(DIAGNOSTIC_H) $(FUNCTION_H) $(TM_H) coretypes.h $(DUMPFILE_H) \
- $(BASIC_BLOCK_H) langhooks.h \
- tree-ssa-propagate.h $(VEC_H) value-prof.h gt-tree-ssa-propagate.h $(FLAGS_H) \
- $(GIMPLE_H) $(GIMPLE_PRETTY_PRINT_H)
-tree-ssa-dom.o : tree-ssa-dom.c $(TREE_SSA_H) $(CONFIG_H) $(SYSTEM_H) \
- $(HASH_TABLE_H) $(TREE_H) $(TM_P_H) $(DIAGNOSTIC_H) \
- $(FUNCTION_H) $(TM_H) coretypes.h \
- $(BASIC_BLOCK_H) domwalk.h $(TREE_PASS_H) $(FLAGS_H) langhooks.h \
- tree-ssa-propagate.h $(CFGLOOP_H) $(PARAMS_H) \
- $(GIMPLE_PRETTY_PRINT_H)
-tree-ssa-uncprop.o : tree-ssa-uncprop.c $(TREE_SSA_H) $(CONFIG_H) \
- $(SYSTEM_H) $(HASH_TABLE_H) $(TREE_H) $(TM_P_H) \
- $(DIAGNOSTIC_H) $(FUNCTION_H) $(TM_H) coretypes.h \
- $(BASIC_BLOCK_H) domwalk.h $(TREE_PASS_H) $(FLAGS_H) \
- tree-ssa-propagate.h
-tree-ssa-threadedge.o : tree-ssa-threadedge.c $(TREE_SSA_H) $(CONFIG_H) \
- $(SYSTEM_H) coretypes.h $(DUMPFILE_H) $(TM_H) $(TREE_H) $(FLAGS_H) \
- $(TM_P_H) $(BASIC_BLOCK_H) $(CFGLOOP_H) \
- $(FUNCTION_H) $(DIAGNOSTIC_H) $(TIMEVAR_H) $(TREE_SSA_H) \
- tree-ssa-propagate.h langhooks.h \
- $(PARAMS_H)
-tree-ssa-threadupdate.o : tree-ssa-threadupdate.c $(TREE_SSA_H) $(CONFIG_H) \
- $(SYSTEM_H) $(TREE_H) $(TM_P_H) $(HASH_TABLE_H) \
- $(DIAGNOSTIC_H) $(FUNCTION_H) $(TM_H) coretypes.h $(DUMPFILE_H) \
- $(BASIC_BLOCK_H) $(FLAGS_H) $(CFGLOOP_H)
-tree-ssanames.o : tree-ssanames.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(TREE_H) $(TREE_SSA_H) $(TREE_PASS_H) tree-ssanames.h
-tree-phinodes.o : tree-phinodes.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(TREE_H) $(GGC_H) $(BASIC_BLOCK_H) $(TREE_SSA_H) \
- gt-tree-phinodes.h $(DIAGNOSTIC_CORE_H) $(GIMPLE_H)
-domwalk.o : domwalk.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(BASIC_BLOCK_H) domwalk.h sbitmap.h
-tree-ssa-live.o : tree-ssa-live.c $(TREE_SSA_H) $(CONFIG_H) $(SYSTEM_H) \
- $(TREE_H) $(DIAGNOSTIC_H) $(TM_H) coretypes.h $(DUMPFILE_H) $(TIMEVAR_H) \
- $(TREE_SSA_LIVE_H) $(BITMAP_H) debug.h $(FLAGS_H) $(HASH_TABLE_H) \
- $(GIMPLE_PRETTY_PRINT_H) $(GIMPLE_H)
-tree-ssa-copyrename.o : tree-ssa-copyrename.c $(TREE_SSA_H) $(CONFIG_H) \
- $(SYSTEM_H) $(TREE_H) $(DIAGNOSTIC_H) $(FUNCTION_H) \
- $(TREE_PASS_H) $(TM_H) coretypes.h $(TREE_SSA_LIVE_H) \
- $(BASIC_BLOCK_H) $(BITMAP_H) $(FLAGS_H) $(HASHTAB_H) langhooks.h \
- $(GIMPLE_H) $(TREE_INLINE_H) $(GIMPLE_H)
-tree-ssa-pre.o : tree-ssa-pre.c $(TREE_SSA_H) $(CONFIG_H) \
- $(SYSTEM_H) $(TREE_H) $(DIAGNOSTIC_H) \
- $(TM_H) coretypes.h $(TREE_PASS_H) $(FLAGS_H) langhooks.h \
- $(CFGLOOP_H) alloc-pool.h $(BASIC_BLOCK_H) $(BITMAP_H) $(HASH_TABLE_H) \
- $(GIMPLE_H) $(TREE_INLINE_H) tree-iterator.h tree-ssa-sccvn.h $(PARAMS_H) \
- $(DBGCNT_H) tree-scalar-evolution.h $(GIMPLE_PRETTY_PRINT_H) domwalk.h \
- $(IPA_PROP_H)
-tree-ssa-sccvn.o : tree-ssa-sccvn.c $(TREE_SSA_H) $(CONFIG_H) \
- $(SYSTEM_H) $(TREE_H) $(DIAGNOSTIC_H) \
- $(TM_H) coretypes.h $(DUMPFILE_H) $(FLAGS_H) $(CFGLOOP_H) \
- alloc-pool.h $(BASIC_BLOCK_H) $(BITMAP_H) $(HASH_TABLE_H) $(GIMPLE_H) \
- $(TREE_INLINE_H) tree-ssa-propagate.h tree-ssa-sccvn.h \
- $(PARAMS_H) $(GIMPLE_PRETTY_PRINT_H) gimple-fold.h
-gimple-ssa-strength-reduction.o : gimple-ssa-strength-reduction.c $(CONFIG_H) \
- $(SYSTEM_H) coretypes.h $(TREE_H) $(GIMPLE_H) $(BASIC_BLOCK_H) \
- $(HASH_TABLE_H) $(TREE_PASS_H) $(CFGLOOP_H) $(TREE_PRETTY_PRINT_H) \
- $(GIMPLE_PRETTY_PRINT_H) alloc-pool.h $(TREE_SSA_H) domwalk.h \
- pointer-set.h expmed.h
-tree-vrp.o : tree-vrp.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
- $(TREE_SSA_H) $(TREE_PASS_H) $(DIAGNOSTIC_CORE_H) $(GGC_H) \
- $(BASIC_BLOCK_H) tree-ssa-propagate.h $(FLAGS_H) $(TREE_DUMP_H) \
- $(CFGLOOP_H) $(SCEV_H) intl.h \
- $(GIMPLE_PRETTY_PRINT_H) gimple-fold.h $(OPTABS_H) $(EXPR_H)
-tree-cfg.o : tree-cfg.c $(TREE_SSA_H) $(CONFIG_H) $(SYSTEM_H) $(HASH_TABLE_H) \
- $(TREE_H) $(TM_P_H) $(GGC_H) $(FLAGS_H) $(TARGET_H) \
- $(DIAGNOSTIC_CORE_H) $(FUNCTION_H) $(TM_H) coretypes.h \
- $(TREE_DUMP_H) $(EXCEPT_H) $(CFGLOOP_H) $(TREE_PASS_H) \
- $(BASIC_BLOCK_H) \
- value-prof.h tree-ssa-propagate.h $(TREE_INLINE_H) $(GIMPLE_PRETTY_PRINT_H)
-tree-cfgcleanup.o : tree-cfgcleanup.c $(TREE_SSA_H) $(CONFIG_H) $(SYSTEM_H) \
- $(TREE_H) $(TM_P_H) $(GGC_H) $(FLAGS_H) \
- $(DIAGNOSTIC_CORE_H) $(FUNCTION_H) $(TM_H) coretypes.h \
- $(EXCEPT_H) langhooks.h $(CFGLOOP_H) $(TREE_PASS_H) \
- $(BASIC_BLOCK_H) $(HASHTAB_H) \
- tree-ssa-propagate.h $(SCEV_H)
-tree-tailcall.o : tree-tailcall.c $(TREE_SSA_H) $(CONFIG_H) $(SYSTEM_H) \
- $(TREE_H) $(TM_P_H) $(FUNCTION_H) $(TM_H) coretypes.h \
- $(EXCEPT_H) $(TREE_PASS_H) $(FLAGS_H) langhooks.h \
- $(BASIC_BLOCK_H) $(DBGCNT_H) $(GIMPLE_PRETTY_PRINT_H) $(TARGET_H) \
- $(COMMON_TARGET_H) $(CFGLOOP_H) ipa-utils.h
-tree-ssa-sink.o : tree-ssa-sink.c $(TREE_SSA_H) $(CONFIG_H) \
- $(SYSTEM_H) $(TREE_H) $(DIAGNOSTIC_H) \
- $(TM_H) coretypes.h $(TREE_PASS_H) $(FLAGS_H) alloc-pool.h \
- $(BASIC_BLOCK_H) $(BITMAP_H) $(CFGLOOP_H) $(HASHTAB_H) \
- $(GIMPLE_H) $(TREE_INLINE_H) tree-iterator.h \
- $(GIMPLE_PRETTY_PRINT_H)
-tree-nested.o: tree-nested.c $(CONFIG_H) $(SYSTEM_H) $(TM_H) $(TREE_H) \
- $(TM_P_H) $(FUNCTION_H) $(TREE_DUMP_H) $(TREE_INLINE_H) \
- tree-iterator.h $(GIMPLE_H) $(CGRAPH_H) $(EXPR_H) langhooks.h \
- gt-tree-nested.h coretypes.h $(TREE_SSA_H) pointer-set.h
-tree-if-conv.o: tree-if-conv.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(TREE_H) $(FLAGS_H) $(BASIC_BLOCK_H) $(TREE_SSA_H) \
- $(CFGLOOP_H) $(TREE_DATA_REF_H) $(TREE_PASS_H) $(DIAGNOSTIC_H) \
- $(DBGCNT_H) $(GIMPLE_PRETTY_PRINT_H)
-tree-iterator.o : tree-iterator.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) \
- coretypes.h $(GGC_H) tree-iterator.h $(GIMPLE_H) gt-tree-iterator.h
-tree-dfa.o : tree-dfa.c $(TREE_SSA_H) $(CONFIG_H) $(SYSTEM_H) \
- $(TREE_H) $(TM_P_H) $(GGC_H) $(DIAGNOSTIC_H) \
- $(TREE_INLINE_H) $(HASHTAB_H) pointer-set.h $(FLAGS_H) $(FUNCTION_H) \
- convert.h $(TM_H) coretypes.h langhooks.h \
- $(TREE_PASS_H) $(PARAMS_H) $(CGRAPH_H) $(BASIC_BLOCK_H) $(GIMPLE_H) \
- $(TREE_PRETTY_PRINT_H)
-tree-ssa-operands.o : tree-ssa-operands.c $(TREE_SSA_H) $(CONFIG_H) \
- $(SYSTEM_H) $(TREE_H) $(GGC_H) $(DIAGNOSTIC_H) $(TREE_INLINE_H) \
- $(FLAGS_H) $(FUNCTION_H) $(TM_H) $(TIMEVAR_H) coretypes.h $(DUMPFILE_H) \
- langhooks.h $(IPA_REFERENCE_H) $(GIMPLE_PRETTY_PRINT_H)
-tree-eh.o : tree-eh.c $(TREE_SSA_H) $(CONFIG_H) $(SYSTEM_H) \
- $(TREE_H) $(TM_H) $(FLAGS_H) $(FUNCTION_H) $(EXCEPT_H) langhooks.h \
- $(HASH_TABLE_H) $(GGC_H) $(TREE_PASS_H) coretypes.h pointer-set.h \
- $(TREE_INLINE_H) tree-iterator.h toplev.h \
- $(DIAGNOSTIC_CORE_H) $(TARGET_H) $(CFGLOOP_H)
-tree-ssa-loop.o : tree-ssa-loop.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(TREE_H) $(TM_P_H) $(BASIC_BLOCK_H) \
- $(DIAGNOSTIC_H) $(TREE_SSA_H) $(TREE_PASS_H) \
- $(CFGLOOP_H) $(FLAGS_H) $(TREE_INLINE_H) $(SCEV_H) $(DIAGNOSTIC_CORE_H) $(TREE_VECTORIZER_H)
-tree-ssa-loop-unswitch.o : tree-ssa-loop-unswitch.c $(TREE_SSA_H) \
- $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(TM_P_H) $(CFGLOOP_H) \
- $(PARAMS_H) $(DIAGNOSTIC_H) $(TM_H) \
- coretypes.h $(TREE_PASS_H) $(BASIC_BLOCK_H) \
- $(TREE_INLINE_H)
-tree-ssa-address.o : tree-ssa-address.c $(TREE_SSA_H) $(CONFIG_H) \
- $(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) \
- $(DIAGNOSTIC_H) $(TM_H) coretypes.h $(DUMPFILE_H) \
- $(FLAGS_H) $(TREE_INLINE_H) $(RECOG_H) insn-config.h \
- $(EXPR_H) gt-tree-ssa-address.h $(GGC_H) tree-affine.h $(TARGET_H) \
- $(TREE_PRETTY_PRINT_H) expmed.h
-tree-ssa-loop-niter.o : tree-ssa-loop-niter.c $(TREE_SSA_H) $(CONFIG_H) \
- $(SYSTEM_H) $(TREE_H) $(TM_P_H) $(CFGLOOP_H) $(PARAMS_H) \
- $(TREE_INLINE_H) $(DIAGNOSTIC_H) $(TM_H) coretypes.h $(DUMPFILE_H) \
- $(DIAGNOSTIC_CORE_H) $(FLAGS_H) $(TREE_DATA_REF_H) \
- $(BASIC_BLOCK_H) $(GGC_H) intl.h $(GIMPLE_PRETTY_PRINT_H) $(TREE_PASS_H)
-tree-ssa-loop-ivcanon.o : tree-ssa-loop-ivcanon.c $(TREE_SSA_H) $(CONFIG_H) \
- $(SYSTEM_H) $(TREE_H) $(TM_P_H) $(CFGLOOP_H) $(PARAMS_H) \
- $(TREE_INLINE_H) $(DIAGNOSTIC_H) $(TM_H) coretypes.h \
- $(FLAGS_H) $(TREE_PASS_H) $(SCEV_H) $(BASIC_BLOCK_H) $(TARGET_H) \
- $(GIMPLE_PRETTY_PRINT_H)
-tree-ssa-loop-ch.o : tree-ssa-loop-ch.c $(TREE_SSA_H) $(CONFIG_H) \
- $(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) $(CFGLOOP_H) $(TREE_INLINE_H) \
- $(DIAGNOSTIC_H) $(TM_H) coretypes.h \
- $(TREE_PASS_H) $(FLAGS_H) $(BASIC_BLOCK_H)
-tree-ssa-loop-prefetch.o: tree-ssa-loop-prefetch.c $(TREE_SSA_H) $(CONFIG_H) \
- $(SYSTEM_H) $(TREE_H) $(TM_P_H) $(CFGLOOP_H) $(EXPR_H) \
- $(DIAGNOSTIC_H) $(TM_H) coretypes.h \
- $(TREE_PASS_H) $(RECOG_H) insn-config.h $(HASHTAB_H) \
- $(CFGLOOP_H) $(PARAMS_H) langhooks.h $(BASIC_BLOCK_H) \
- $(DIAGNOSTIC_CORE_H) langhooks.h $(TREE_INLINE_H) $(TREE_DATA_REF_H) \
- $(OPTABS_H) $(TREE_PRETTY_PRINT_H)
-tree-predcom.o: tree-predcom.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(TM_P_H) \
- $(CFGLOOP_H) $(TREE_SSA_H) $(GGC_H) $(TREE_DATA_REF_H) \
- $(PARAMS_H) $(DIAGNOSTIC_H) $(TREE_PASS_H) $(TM_H) coretypes.h \
- tree-affine.h $(TREE_INLINE_H) $(TREE_PRETTY_PRINT_H)
-tree-ssa-loop-ivopts.o : tree-ssa-loop-ivopts.c $(TREE_SSA_H) $(CONFIG_H) \
- $(SYSTEM_H) $(TREE_H) $(TM_P_H) $(CFGLOOP_H) $(EXPR_H) \
- $(DIAGNOSTIC_H) $(TM_H) coretypes.h \
- $(TREE_PASS_H) $(GGC_H) $(RECOG_H) insn-config.h $(HASH_TABLE_H) $(SCEV_H) \
- $(CFGLOOP_H) $(PARAMS_H) langhooks.h $(BASIC_BLOCK_H) \
- tree-affine.h pointer-set.h $(TARGET_H) \
- $(GIMPLE_PRETTY_PRINT_H) tree-ssa-propagate.h
-tree-affine.o : tree-affine.c tree-affine.h $(CONFIG_H) pointer-set.h \
- $(SYSTEM_H) $(TREE_H) $(GIMPLE_H) \
- coretypes.h $(DUMPFILE_H) $(FLAGS_H) \
- $(TREE_PRETTY_PRINT_H)
-tree-ssa-loop-manip.o : tree-ssa-loop-manip.c $(TREE_SSA_H) $(CONFIG_H) \
- $(SYSTEM_H) coretypes.h $(DUMPFILE_H) $(TM_H) $(TREE_H) \
- $(BASIC_BLOCK_H) $(DIAGNOSTIC_H) $(TREE_SSA_H) \
- $(CFGLOOP_H) $(TREE_PASS_H) \
- $(SCEV_H) $(PARAMS_H) $(TREE_INLINE_H) langhooks.h
-tree-ssa-loop-im.o : tree-ssa-loop-im.c $(TREE_SSA_H) $(CONFIG_H) \
- $(SYSTEM_H) $(HASH_TABLE_H) $(TREE_H) $(TM_P_H) $(CFGLOOP_H) domwalk.h \
- $(PARAMS_H) $(DIAGNOSTIC_H) $(TM_H) coretypes.h \
- $(TREE_PASS_H) $(FLAGS_H) $(BASIC_BLOCK_H) \
- pointer-set.h tree-affine.h tree-ssa-propagate.h $(GIMPLE_PRETTY_PRINT_H)
-tree-ssa-math-opts.o : tree-ssa-math-opts.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(FLAGS_H) $(TREE_H) $(TREE_SSA_H) \
- $(TREE_PASS_H) alloc-pool.h $(BASIC_BLOCK_H) $(TARGET_H) \
- $(DIAGNOSTIC_H) $(RTL_H) $(EXPR_H) $(OPTABS_H) $(GIMPLE_PRETTY_PRINT_H)
-tree-ssa-alias.o : tree-ssa-alias.c $(TREE_SSA_H) $(CONFIG_H) $(SYSTEM_H) \
- $(TREE_H) $(TM_P_H) $(GGC_H) $(TREE_INLINE_H) $(FLAGS_H) \
- $(FUNCTION_H) $(TIMEVAR_H) convert.h $(TM_H) coretypes.h $(DUMPFILE_H) \
- langhooks.h \
- $(PARAMS_H) $(BASIC_BLOCK_H) $(DIAGNOSTIC_H) \
- $(GIMPLE_H) $(VEC_H) $(TARGET_H) \
- pointer-set.h alloc-pool.h \
- $(TREE_PRETTY_PRINT_H)
-tree-ssa-reassoc.o : tree-ssa-reassoc.c $(TREE_SSA_H) $(CONFIG_H) \
- $(SYSTEM_H) $(HASH_TABLE_H) $(TREE_H) $(DIAGNOSTIC_H) \
- $(TM_H) coretypes.h $(TREE_PASS_H) $(FLAGS_H) \
- tree-iterator.h $(BASIC_BLOCK_H) $(GIMPLE_H) $(TREE_INLINE_H) \
- $(VEC_H) langhooks.h alloc-pool.h pointer-set.h $(CFGLOOP_H) \
- $(TARGET_H) $(GIMPLE_PRETTY_PRINT_H) $(DIAGNOSTIC_CORE_H) $(PARAMS_H)
-tree-optimize.o : tree-optimize.c $(TREE_SSA_H) $(CONFIG_H) $(SYSTEM_H) \
- $(TREE_H) $(TM_P_H) $(GGC_H) \
- $(DIAGNOSTIC_H) $(BASIC_BLOCK_H) $(FLAGS_H) $(TM_H) \
- coretypes.h toplev.h $(DIAGNOSTIC_CORE_H) $(FUNCTION_H) langhooks.h \
- $(FLAGS_H) $(CGRAPH_H) $(PLUGIN_H) \
- $(TREE_INLINE_H) $(GGC_H) $(CGRAPH_H) \
- $(TREE_PASS_H) $(CFGLOOP_H) $(EXCEPT_H)
-
-gimplify.o : gimplify.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(GIMPLE_H) \
- $(DIAGNOSTIC_H) $(TREE_INLINE_H) langhooks.h \
- $(LANGHOOKS_DEF_H) $(TREE_SSA_H) $(CGRAPH_H) $(TIMEVAR_H) $(TM_H) \
- coretypes.h $(EXCEPT_H) $(FLAGS_H) $(RTL_H) $(FUNCTION_H) $(EXPR_H) \
- $(GGC_H) gt-gimplify.h $(HASHTAB_H) $(TARGET_H) $(DIAGNOSTIC_CORE_H) $(OPTABS_H) \
- $(SPLAY_TREE_H) $(VEC_H) tree-iterator.h $(TREE_PASS_H) $(TREE_PRETTY_PRINT_H)
-gimple-iterator.o : gimple-iterator.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TREE_H) $(GIMPLE_H) $(TREE_SSA_H) value-prof.h
-gimple-fold.o : gimple-fold.c $(TREE_SSA_H) $(CONFIG_H) coretypes.h \
- $(DUMPFILE_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) $(GGC_H) \
- $(FUNCTION_H) $(TM_H) $(BASIC_BLOCK_H) langhooks.h \
- tree-ssa-propagate.h $(FLAGS_H) $(TARGET_H) gimple-fold.h
-gimple-low.o : gimple-low.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) \
- $(DIAGNOSTIC_CORE_H) $(GIMPLE_H) $(TREE_INLINE_H) langhooks.h \
- $(LANGHOOKS_DEF_H) $(TREE_SSA_H) $(TM_H) coretypes.h \
- $(EXCEPT_H) $(FLAGS_H) $(RTL_H) $(FUNCTION_H) $(TREE_PASS_H) \
- $(HASHTAB_H) $(DIAGNOSTIC_CORE_H) tree-iterator.h langhooks.h
-omp-low.o : omp-low.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
- $(RTL_H) $(GIMPLE_H) $(TREE_INLINE_H) langhooks.h $(DIAGNOSTIC_CORE_H) \
- $(TREE_SSA_H) $(FLAGS_H) $(EXPR_H) $(DIAGNOSTIC_CORE_H) \
- $(TREE_PASS_H) $(GGC_H) $(EXCEPT_H) $(SPLAY_TREE_H) $(OPTABS_H) \
- $(CFGLOOP_H) tree-iterator.h $(TARGET_H) gt-omp-low.h
-tree-browser.o : tree-browser.c tree-browser.def $(CONFIG_H) $(SYSTEM_H) \
- coretypes.h $(HASH_TABLE_H) $(TREE_H) $(TREE_PRETTY_PRINT_H)
-omega.o : omega.c $(OMEGA_H) $(CONFIG_H) $(SYSTEM_H) coretypes.h $(DUMPFILE_H) \
- $(TREE_H) $(DIAGNOSTIC_CORE_H)
-tree-chrec.o : tree-chrec.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(DUMPFILE_H) \
- $(TREE_PRETTY_PRINT_H) $(CFGLOOP_H) $(TREE_SSA_H) $(SCEV_H) \
- $(PARAMS_H)
-tree-scalar-evolution.o : tree-scalar-evolution.c $(CONFIG_H) $(SYSTEM_H) \
- coretypes.h $(DUMPFILE_H) $(HASH_TABLE_H) $(GIMPLE_PRETTY_PRINT_H) \
- $(TREE_SSA_H) $(CFGLOOP_H) $(SCEV_H) $(PARAMS_H) gt-tree-scalar-evolution.h
-tree-data-ref.o : tree-data-ref.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(DUMPFILE_H) \
- $(GIMPLE_PRETTY_PRINT_H) $(TREE_SSA_H) $(CFGLOOP_H) $(TREE_DATA_REF_H) \
- langhooks.h tree-affine.h $(PARAMS_H)
-sese.o : sese.c sese.h $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TREE_PRETTY_PRINT_H) \
- $(TREE_SSA_H) $(CFGLOOP_H) $(TREE_DATA_REF_H) $(TREE_PASS_H) value-prof.h
-graphite.o : graphite.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(DIAGNOSTIC_CORE_H) \
- $(TREE_SSA_H) $(TREE_DUMP_H) $(CFGLOOP_H) $(TREE_DATA_REF_H) sese.h \
- $(DBGCNT_H) $(GRAPHITE_HTAB_H) graphite-poly.h graphite-scop-detection.h \
- graphite-clast-to-gimple.h graphite-sese-to-poly.h
-graphite-blocking.o : graphite-blocking.c $(CONFIG_H) $(SYSTEM_H) \
- coretypes.h $(DUMPFILE_H) $(TREE_SSA_H) $(CFGLOOP_H) $(TREE_DATA_REF_H) \
- sese.h graphite-poly.h
-graphite-clast-to-gimple.o : graphite-clast-to-gimple.c $(CONFIG_H) \
- $(SYSTEM_H) coretypes.h $(DIAGNOSTIC_CORE_H) $(TREE_SSA_H) $(TREE_PASS_H) \
- $(CFGLOOP_H) $(TREE_DATA_REF_H) sese.h $(GRAPHITE_HTAB_H) \
- graphite-poly.h graphite-clast-to-gimple.h
-graphite-dependences.o : graphite-dependences.c $(CONFIG_H) $(SYSTEM_H) \
- coretypes.h $(TREE_SSA_H) $(TREE_PASS_H) $(CFGLOOP_H) $(TREE_DATA_REF_H) \
- sese.h $(GRAPHITE_HTAB_H) graphite-poly.h
-graphite-interchange.o : graphite-interchange.c $(CONFIG_H) $(SYSTEM_H) \
- coretypes.h $(DUMPFILE_H) $(TREE_SSA_H) $(CFGLOOP_H) $(TREE_DATA_REF_H) \
- sese.h graphite-poly.h
-graphite-poly.o : graphite-poly.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(DUMPFILE_H) $(DIAGNOSTIC_CORE_H) $(TREE_SSA_H) $(GIMPLE_PRETTY_PRINT_H) \
- $(CFGLOOP_H) $(TREE_DATA_REF_H) sese.h graphite-poly.h
-graphite-scop-detection.o : graphite-scop-detection.c $(CONFIG_H) $(SYSTEM_H) \
- coretypes.h $(TREE_SSA_H) $(CFGLOOP_H) $(TREE_DATA_REF_H) $(TREE_PASS_H) \
- sese.h graphite-poly.h graphite-scop-detection.h
-graphite-sese-to-poly.o : graphite-sese-to-poly.c $(CONFIG_H) \
- $(SYSTEM_H) coretypes.h $(TREE_SSA_H) $(TREE_PASS_H) $(CFGLOOP_H) \
- $(TREE_DATA_REF_H) domwalk.h sese.h graphite-poly.h \
- graphite-sese-to-poly.h
-graphite-optimize-isl.o : graphite-optimize-isl.c $(CONFIG_H) $(SYSTEM_H) \
- coretypes.h $(DUMPFILE_H) $(TREE_SSA_H) $(CFGLOOP_H) $(TREE_DATA_REF_H) \
- $(SCEV_H) sese.h graphite-poly.h
-tree-vect-loop.o: tree-vect-loop.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(GGC_H) $(TREE_H) $(BASIC_BLOCK_H) $(TREE_SSA_H) $(DUMPFILE_H) \
- $(CFGLOOP_H) $(EXPR_H) $(RECOG_H) $(OPTABS_H) \
- $(DIAGNOSTIC_CORE_H) $(SCEV_H) $(TREE_VECTORIZER_H) \
- $(GIMPLE_PRETTY_PRINT_H) $(TARGET_H) $(TREE_DATA_REF_H)
-tree-vect-loop-manip.o: tree-vect-loop-manip.c $(CONFIG_H) $(SYSTEM_H) \
- coretypes.h $(DUMPFILE_H) $(TM_H) $(GGC_H) $(TREE_H) $(BASIC_BLOCK_H) \
- $(TREE_SSA_H) $(CFGLOOP_H) $(DIAGNOSTIC_CORE_H) \
- $(SCEV_H) $(TREE_VECTORIZER_H) langhooks.h $(GIMPLE_PRETTY_PRINT_H)
-tree-vect-patterns.o: tree-vect-patterns.c $(CONFIG_H) $(SYSTEM_H) \
- coretypes.h $(DUMPFILE_H) \
- $(TM_H) $(GGC_H) $(TREE_H) $(TARGET_H) $(BASIC_BLOCK_H) \
- $(TREE_SSA_H) $(CFGLOOP_H) $(EXPR_H) $(OPTABS_H) $(PARAMS_H) \
- $(TREE_DATA_REF_H) $(TREE_VECTORIZER_H) $(RECOG_H) $(DIAGNOSTIC_CORE_H) \
- $(GIMPLE_PRETTY_PRINT_H)
-tree-vect-slp.o: tree-vect-slp.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(DUMPFILE_H) $(TM_H) $(GGC_H) $(TREE_H) $(TARGET_H) $(BASIC_BLOCK_H) \
- $(DIAGNOSTIC_H) $(TREE_SSA_H) $(CFGLOOP_H) \
- $(EXPR_H) $(RECOG_H) $(OPTABS_H) $(TREE_VECTORIZER_H) \
- $(GIMPLE_PRETTY_PRINT_H) $(TREE_DATA_REF_H) langhooks.h
-tree-vect-stmts.o: tree-vect-stmts.c $(CONFIG_H) $(SYSTEM_H) \
- coretypes.h $(DUMPFILE_H) $(TM_H) $(GGC_H) $(TREE_H) $(TARGET_H) \
- $(BASIC_BLOCK_H) $(TREE_SSA_H) $(CFGLOOP_H) \
- $(EXPR_H) $(RECOG_H) $(OPTABS_H) $(TREE_VECTORIZER_H) \
- langhooks.h $(GIMPLE_PRETTY_PRINT_H)
-tree-vect-data-refs.o: tree-vect-data-refs.c $(CONFIG_H) $(SYSTEM_H) \
- coretypes.h $(DUMPFILE_H) $(TM_H) $(GGC_H) $(TREE_H) $(TARGET_H) \
- $(BASIC_BLOCK_H) $(TREE_SSA_H) $(CFGLOOP_H) \
- $(EXPR_H) $(OPTABS_H) $(SCEV_H) $(TREE_VECTORIZER_H) \
- $(DIAGNOSTIC_CORE_H) $(TM_P_H) $(GIMPLE_PRETTY_PRINT_H)
-tree-vectorizer.o: tree-vectorizer.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(DUMPFILE_H) $(TM_H) $(GGC_H) $(TREE_H) $(TREE_SSA_H) \
- $(CFGLOOP_H) $(TREE_PASS_H) $(TREE_VECTORIZER_H) \
- $(TREE_PRETTY_PRINT_H) $(DBGCNT_H)
-vtable-verify.o: vtable-verify.c vtable-verify.h $(CONFIG_H) \
- $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) cp/cp-tree.h $(TM_P_H) \
- $(BASIC_BLOCK_H) output.h $(TREE_SSA_H) $(TREE_DUMP_H) $(TREE_PASS_H) \
- $(TIMEVAR_H) $(CFGLOOP_H) $(FLAGS_H) $(TREE_INLINE_H) $(SCEV_H) \
- $(DIAGNOSTIC_CORE_H) $(GIMPLE_PRETTY_PRINT_H) toplev.h langhooks.h \
- gt-vtable-verify.h
-tree-loop-distribution.o: tree-loop-distribution.c $(CONFIG_H) $(SYSTEM_H) \
- coretypes.h $(TREE_SSA_H) $(CFGLOOP_H) $(TREE_DATA_REF_H) $(TREE_PASS_H)
-tree-parloops.o: tree-parloops.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TREE_SSA_H) $(TREE_HASHER_H) $(CFGLOOP_H) $(TREE_DATA_REF_H) \
- $(GIMPLE_PRETTY_PRINT_H) $(HASH_TABLE_H) \
- $(TREE_PASS_H) langhooks.h gt-tree-parloops.h $(TREE_VECTORIZER_H)
-tree-stdarg.o: tree-stdarg.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(TREE_H) $(FUNCTION_H) $(TREE_SSA_H) $(TREE_PASS_H) \
- tree-stdarg.h $(TARGET_H) langhooks.h $(GIMPLE_PRETTY_PRINT_H)
-tree-object-size.o: tree-object-size.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(TREE_H) $(DIAGNOSTIC_CORE_H) $(DIAGNOSTIC_H) $(TREE_SSA_H) \
- $(TREE_PASS_H) tree-ssa-propagate.h $(GIMPLE_PRETTY_PRINT_H)
-internal-fn.o : internal-fn.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(INTERNAL_FN_H) $(TREE_H) $(EXPR_H) $(OPTABS_H) $(GIMPLE_H)
-gimple.o : gimple.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TREE_H) \
- $(GGC_H) $(GIMPLE_H) $(DIAGNOSTIC_CORE_H) $(DIAGNOSTIC_H) gt-gimple.h \
- $(TREE_SSA_H) value-prof.h $(FLAGS_H) $(DEMANGLE_H) \
- $(TARGET_H) $(ALIAS_H)
-gimple-pretty-print.o : gimple-pretty-print.c $(CONFIG_H) $(SYSTEM_H) \
- coretypes.h $(DUMPFILE_H) \
- $(TREE_H) $(DIAGNOSTIC_H) $(HASHTAB_H) $(TREE_SSA_H) \
- $(TM_H) $(GIMPLE_H) value-prof.h \
- $(TRANS_MEM_H) $(GIMPLE_PRETTY_PRINT_H)
-tree-mudflap.o : tree-mudflap.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) \
- $(TREE_INLINE_H) $(GIMPLE_H) $(DIAGNOSTIC_H) \
- $(DEMANGLE_H) $(HASHTAB_H) langhooks.h tree-mudflap.h \
- $(TM_H) coretypes.h $(TREE_PASS_H) $(CGRAPH_H) $(GGC_H) \
- gt-tree-mudflap.h $(BASIC_BLOCK_H) $(FLAGS_H) $(FUNCTION_H) \
- $(TM_P_H) $(TREE_SSA_H) $(DIAGNOSTIC_CORE_H) $(GIMPLE_H) tree-iterator.h
-tree-nomudflap.o : $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(TREE_INLINE_H) \
- $(C_TREE_H) $(C_COMMON_H) $(GIMPLE_H) $(DIAGNOSTIC_H) $(HASHTAB_H) \
- output.h langhooks.h tree-mudflap.h $(TM_H) coretypes.h \
- $(GGC_H) gt-tree-mudflap.h $(TREE_PASS_H) $(DIAGNOSTIC_CORE_H)
-tree-pretty-print.o : tree-pretty-print.c $(CONFIG_H) $(SYSTEM_H) \
- $(TREE_H) $(DIAGNOSTIC_H) $(HASHTAB_H) $(TREE_SSA_H) \
- $(TM_H) coretypes.h $(DUMPFILE_H) tree-iterator.h $(SCEV_H) langhooks.h \
- value-prof.h output.h $(TREE_PRETTY_PRINT_H)
-tree-diagnostic.o : tree-diagnostic.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(DUMPFILE_H) \
- $(TREE_H) $(DIAGNOSTIC_H) tree-diagnostic.h langhooks.h $(LANGHOOKS_DEF_H) \
- $(VEC_H) $(TREE_PRETTY_PRINT_H)
-fold-const.o : fold-const.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(TREE_H) $(FLAGS_H) $(DIAGNOSTIC_CORE_H) $(HASH_TABLE_H) $(EXPR_H) \
- $(RTL_H) $(GGC_H) $(TM_P_H) langhooks.h $(MD5_H) intl.h $(TARGET_H) \
- $(GIMPLE_H) realmpfr.h $(TREE_SSA_H)
-diagnostic.o : diagnostic.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- version.h $(DEMANGLE_H) $(INPUT_H) intl.h $(BACKTRACE_H) $(DIAGNOSTIC_H) \
- diagnostic.def diagnostic-color.h
-diagnostic-color.o : diagnostic-color.c $(CONFIG_H) $(SYSTEM_H) diagnostic-color.h
-opts.o : opts.c $(OPTS_H) $(OPTIONS_H) $(DIAGNOSTIC_CORE_H) $(CONFIG_H) $(SYSTEM_H) \
- coretypes.h $(DUMPFILE_H) $(TM_H) \
- $(DIAGNOSTIC_H) insn-attr-common.h intl.h $(COMMON_TARGET_H) \
- $(FLAGS_H) $(PARAMS_H) opts-diagnostic.h diagnostic-color.h
-opts-global.o : opts-global.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(DIAGNOSTIC_H) $(OPTS_H) $(FLAGS_H) $(GGC_H) $(TREE_H) langhooks.h \
- $(TM_H) $(RTL_H) $(DBGCNT_H) debug.h $(LTO_STREAMER_H) output.h \
- $(PLUGIN_H) toplev.h $(TREE_PASS_H)
-opts-common.o : opts-common.c $(OPTS_H) $(FLAGS_H) $(CONFIG_H) $(SYSTEM_H) \
- coretypes.h intl.h $(DIAGNOSTIC_H) $(TM_H)
-targhooks.o : targhooks.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TREE_H) \
- $(EXPR_H) $(TM_H) $(RTL_H) $(TM_P_H) $(FUNCTION_H) output.h $(DIAGNOSTIC_CORE_H) \
- $(MACHMODE_H) $(TARGET_DEF_H) $(TARGET_H) $(GGC_H) gt-targhooks.h \
- $(OPTABS_H) $(RECOG_H) $(REGS_H) reload.h hard-reg-set.h intl.h $(OPTS_H) \
- tree-ssa-alias.h $(TREE_SSA_H)
-common/common-targhooks.o : common/common-targhooks.c $(CONFIG_H) $(SYSTEM_H) \
- coretypes.h $(INPUT_H) $(TM_H) $(COMMON_TARGET_H) common/common-targhooks.h
################################################################
#### added for MELT http://gcc-melt.org
@@ -2840,802 +2097,19 @@ s-bversion: BASE-VER
echo "#define BUILDING_GCC_VERSION (BUILDING_GCC_MAJOR * 1000 + BUILDING_GCC_MINOR)" >> bversion.h
$(STAMP) s-bversion
-input.o : input.c $(CONFIG_H) $(SYSTEM_H) coretypes.h intl.h $(INPUT_H)
-
CFLAGS-toplev.o += -DTARGET_NAME=\"$(target_noncanonical)\"
-toplev.o : toplev.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
- version.h $(RTL_H) $(FUNCTION_H) $(FLAGS_H) xcoffout.h $(INPUT_H) \
- $(INSN_ATTR_H) output.h $(DIAGNOSTIC_H) debug.h insn-config.h intl.h \
- $(RECOG_H) Makefile toplev.h sdbout.h dbxout.h $(EXPR_H) \
- hard-reg-set.h $(BASIC_BLOCK_H) $(EXCEPT_H) $(REGS_H) $(TIMEVAR_H) \
- value-prof.h $(PARAMS_H) $(TM_P_H) reload.h ira.h dwarf2asm.h $(TARGET_H) \
- langhooks.h insn-flags.h $(CFGLOOP_H) hosthooks.h \
- $(CGRAPH_H) $(COVERAGE_H) alloc-pool.h $(GGC_H) \
- $(OPTS_H) params.def tree-mudflap.h $(TREE_PASS_H) $(GIMPLE_H) \
- tree-ssa-alias.h $(PLUGIN_H) realmpfr.h tree-diagnostic.h \
- $(TREE_PRETTY_PRINT_H) opts-diagnostic.h $(COMMON_TARGET_H) \
- tsan.h diagnostic-color.h $(CONTEXT_H) $(PASS_MANAGER_H)
-
-hwint.o : hwint.c $(CONFIG_H) $(SYSTEM_H) $(DIAGNOSTIC_CORE_H)
pass-instances.def: $(srcdir)/passes.def $(srcdir)/gen-pass-instances.awk
$(AWK) -f $(srcdir)/gen-pass-instances.awk \
$(srcdir)/passes.def > pass-instances.def
-passes.o : passes.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
- $(RTL_H) $(FUNCTION_H) $(FLAGS_H) $(INPUT_H) $(INSN_ATTR_H) output.h \
- $(DIAGNOSTIC_CORE_H) debug.h insn-config.h intl.h $(RECOG_H) toplev.h \
- $(EXPR_H) hard-reg-set.h $(BASIC_BLOCK_H) \
- graph.h $(EXCEPT_H) $(REGS_H) value-prof.h \
- $(PARAMS_H) $(TM_P_H) reload.h $(TARGET_H) \
- langhooks.h insn-flags.h $(CFGLOOP_H) \
- hosthooks.h $(CGRAPH_H) $(COVERAGE_H) $(TREE_PASS_H) $(TREE_DUMP_H) \
- $(GGC_H) $(OPTS_H) $(TREE_SSA_H) $(TREE_INLINE_H) \
- gt-passes.h $(DF_H) $(PREDICT_H) $(LTO_STREAMER_H) \
- $(PLUGIN_H) $(IPA_UTILS_H) pass-instances.def \
- $(CONTEXT_H) $(PASS_MANAGER_H)
-
-plugin.o : plugin.c $(PLUGIN_H) $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(HASH_TABLE_H) $(DIAGNOSTIC_CORE_H) $(TREE_H) $(TREE_PASS_H) \
- intl.h $(PLUGIN_VERSION_H) $(GGC_H)
-
-main.o : main.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) toplev.h $(DIAGNOSTIC_CORE_H)
-
-host-default.o : host-default.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- hosthooks.h $(HOSTHOOKS_DEF_H)
-
-rtl-error.o: rtl-error.c $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_ERROR_H) \
- $(INSN_ATTR_H) insn-config.h $(INPUT_H) intl.h $(DIAGNOSTIC_H) \
- $(CONFIG_H)
-
-rtl.o : rtl.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
- $(GGC_H) $(BCONFIG_H) insn-notes.def reg-notes.def $(DIAGNOSTIC_CORE_H)
-
-print-rtl.o : print-rtl.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(DUMPFILE_H) \
- $(TM_H) $(RTL_H) $(TREE_H) hard-reg-set.h $(BASIC_BLOCK_H) $(FLAGS_H) \
- $(BCONFIG_H) $(DIAGNOSTIC_H) cselib.h $(TREE_PRETTY_PRINT_H) \
- $(DWARF2OUT_H)
-rtlanal.o : rtlanal.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(DIAGNOSTIC_CORE_H) \
- $(RTL_H) hard-reg-set.h $(TM_P_H) insn-config.h $(RECOG_H) \
- $(FLAGS_H) $(REGS_H) output.h $(TARGET_H) $(FUNCTION_H) $(TREE_H) \
- $(DF_H) $(EMIT_RTL_H) addresses.h
-
-varasm.o : varasm.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
- $(RTL_H) $(FLAGS_H) $(FUNCTION_H) $(EXPR_H) hard-reg-set.h $(REGS_H) \
- output.h $(DIAGNOSTIC_CORE_H) xcoffout.h debug.h $(GGC_H) $(TM_P_H) \
- $(HASHTAB_H) $(TARGET_H) langhooks.h gt-varasm.h $(BASIC_BLOCK_H) \
- $(CGRAPH_H) $(TARGET_DEF_H) tree-mudflap.h \
- pointer-set.h $(COMMON_TARGET_H) asan.h
-function.o : function.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_ERROR_H) \
- $(TREE_H) $(GIMPLE_H) $(FLAGS_H) $(FUNCTION_H) $(EXPR_H) \
- $(OPTABS_H) $(LIBFUNCS_H) $(REGS_H) hard-reg-set.h insn-config.h $(RECOG_H) \
- output.h $(EXCEPT_H) $(HASHTAB_H) $(GGC_H) $(TM_P_H) langhooks.h \
- gt-function.h $(TARGET_H) $(BASIC_BLOCK_H) $(PREDICT_H) \
- $(TREE_PASS_H) $(DF_H) $(PARAMS_H) bb-reorder.h \
- $(COMMON_TARGET_H)
-statistics.o : statistics.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TREE_PASS_H) $(TREE_DUMP_H) $(HASH_TABLE_H) statistics.h \
- $(FUNCTION_H) $(CONTEXT_H) $(PASS_MANAGER_H)
-stmt.o : stmt.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(DUMPFILE_H) $(TM_H) \
- $(RTL_H) \
- $(TREE_H) $(FLAGS_H) $(FUNCTION_H) insn-config.h hard-reg-set.h $(EXPR_H) \
- $(LIBFUNCS_H) $(EXCEPT_H) $(RECOG_H) $(DIAGNOSTIC_CORE_H) \
- output.h $(GGC_H) $(TM_P_H) langhooks.h $(PREDICT_H) $(OPTABS_H) \
- $(TARGET_H) $(GIMPLE_H) $(MACHMODE_H) $(REGS_H) alloc-pool.h \
- $(PRETTY_PRINT_H) $(BITMAP_H) $(PARAMS_H)
-except.o : except.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
- $(TREE_H) $(FLAGS_H) $(EXCEPT_H) $(FUNCTION_H) $(EXPR_H) $(LIBFUNCS_H) \
- langhooks.h insn-config.h hard-reg-set.h $(BASIC_BLOCK_H) output.h \
- dwarf2asm.h $(DWARF2OUT_H) toplev.h $(DIAGNOSTIC_CORE_H) $(HASH_TABLE_H) \
- intl.h $(GGC_H) \
- gt-except.h $(CGRAPH_H) $(DIAGNOSTIC_H) $(DWARF2_H) \
- $(TARGET_H) $(TM_P_H) $(TREE_PASS_H) $(TREE_SSA_H) \
- $(TREE_PRETTY_PRINT_H) sbitmap.h $(COMMON_TARGET_H) $(CFGLOOP_H)
-expr.o : expr.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
- $(TREE_H) $(FLAGS_H) $(FUNCTION_H) $(REGS_H) $(EXPR_H) $(OPTABS_H) \
- $(LIBFUNCS_H) $(INSN_ATTR_H) insn-config.h $(RECOG_H) output.h \
- typeclass.h hard-reg-set.h toplev.h $(DIAGNOSTIC_CORE_H) hard-reg-set.h $(EXCEPT_H) \
- reload.h langhooks.h intl.h $(TM_P_H) $(TARGET_H) \
- tree-iterator.h gt-expr.h $(MACHMODE_H) $(TIMEVAR_H) $(TREE_SSA_H) \
- $(TREE_PASS_H) $(DF_H) $(DIAGNOSTIC_H) $(SSAEXPAND_H) \
- $(PARAMS_H) $(COMMON_TARGET_H) target-globals.h
-dojump.o : dojump.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TM_P_H) \
- $(RTL_H) $(TREE_H) \
- $(FLAGS_H) $(FUNCTION_H) $(EXPR_H) $(OPTABS_H) $(INSN_ATTR_H) insn-config.h \
- langhooks.h $(GGC_H) gt-dojump.h $(BASIC_BLOCK_H)
-builtins.o : builtins.c builtins.h $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(RTL_H) $(TREE_H) $(GIMPLE_H) $(FLAGS_H) $(TARGET_H) $(FUNCTION_H) $(REGS_H) \
- $(EXPR_H) $(OPTABS_H) insn-config.h $(RECOG_H) output.h typeclass.h \
- hard-reg-set.h $(DIAGNOSTIC_CORE_H) hard-reg-set.h $(EXCEPT_H) \
- $(TM_P_H) $(PREDICT_H) $(LIBFUNCS_H) langhooks.h $(BASIC_BLOCK_H) \
- tree-mudflap.h realmpfr.h $(BUILTINS_DEF) $(MACHMODE_H) \
- $(DIAGNOSTIC_CORE_H) $(TREE_SSA_H) value-prof.h ubsan.h
-calls.o : calls.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
- $(TREE_H) $(FLAGS_H) $(EXPR_H) $(OPTABS_H) langhooks.h $(TARGET_H) \
- $(LIBFUNCS_H) $(REGS_H) $(DIAGNOSTIC_CORE_H) output.h \
- $(FUNCTION_H) $(TIMEVAR_H) $(TM_P_H) $(CGRAPH_H) $(EXCEPT_H) sbitmap.h \
- $(DBGCNT_H) $(TREE_SSA_H)
-expmed.o : expmed.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) \
- $(FLAGS_H) insn-config.h $(EXPR_H) $(OPTABS_H) $(RECOG_H) \
- $(DIAGNOSTIC_CORE_H) $(TM_P_H) langhooks.h $(DF_H) $(TARGET_H) \
- expmed.h
-explow.o : explow.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) \
- $(FLAGS_H) hard-reg-set.h insn-config.h $(EXPR_H) $(OPTABS_H) $(RECOG_H) \
- $(DIAGNOSTIC_CORE_H) $(EXCEPT_H) $(FUNCTION_H) $(GGC_H) $(TM_P_H) langhooks.h gt-explow.h \
- $(TARGET_H) $(COMMON_TARGET_H) output.h $(LIBFUNCS_H)
-optabs.o : optabs.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
- $(TREE_H) $(FLAGS_H) insn-config.h $(EXPR_H) $(OPTABS_H) $(LIBFUNCS_H) \
- $(RECOG_H) reload.h $(DIAGNOSTIC_CORE_H) $(GGC_H) $(TM_P_H) \
- $(EXCEPT_H) gt-optabs.h $(BASIC_BLOCK_H) $(TARGET_H) $(FUNCTION_H)
-dbxout.o : dbxout.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
- $(RTL_H) $(FLAGS_H) $(REGS_H) debug.h $(TM_P_H) $(TARGET_H) $(FUNCTION_H) \
- langhooks.h insn-config.h reload.h $(GSTAB_H) xcoffout.h output.h dbxout.h \
- toplev.h $(DIAGNOSTIC_CORE_H) $(GGC_H) $(OBSTACK_H) $(EXPR_H) $(CGRAPH_H) \
- gt-dbxout.h $(COMMON_TARGET_H)
-debug.o : debug.c debug.h $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H)
-sdbout.o : sdbout.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) debug.h \
- $(TREE_H) $(GGC_H) $(RTL_H) $(REGS_H) $(FLAGS_H) insn-config.h \
- output.h $(DIAGNOSTIC_CORE_H) $(TM_P_H) gsyms.h langhooks.h $(TARGET_H) sdbout.h \
- gt-sdbout.h reload.h
-dwarf2out.o : dwarf2out.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(DUMPFILE_H) \
- $(TM_H) $(TREE_H) version.h $(RTL_H) $(DWARF2_H) debug.h $(FLAGS_H) \
- insn-config.h output.h $(DIAGNOSTIC_H) hard-reg-set.h $(REGS_H) $(EXPR_H) \
- toplev.h $(DIAGNOSTIC_CORE_H) $(DWARF2OUT_H) reload.h \
- $(GGC_H) $(EXCEPT_H) dwarf2asm.h $(TM_P_H) langhooks.h $(HASH_TABLE_H) \
- gt-dwarf2out.h $(TARGET_H) $(CGRAPH_H) $(MD5_H) $(INPUT_H) $(FUNCTION_H) \
- $(GIMPLE_H) ira.h lra.h $(TREE_SSA_H) \
- $(TREE_PRETTY_PRINT_H) $(COMMON_TARGET_H) $(OPTS_H)
-dwarf2cfi.o : dwarf2cfi.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(HASH_TABLE_H) \
- $(TM_H) version.h $(RTL_H) $(EXPR_H) $(REGS_H) $(FUNCTION_H) output.h \
- gt-dwarf2cfi.h debug.h $(DWARF2_H) dwarf2asm.h $(DWARF2OUT_H) $(COMMON_TARGET_H) \
- $(GGC_H) $(TM_P_H) $(TARGET_H) $(TREE_PASS_H) $(BASIC_BLOCK_H) $(EXCEPT_H)
-dwarf2asm.o : dwarf2asm.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(FLAGS_H) $(RTL_H) $(TREE_H) output.h dwarf2asm.h $(TM_P_H) $(GGC_H) \
- gt-dwarf2asm.h $(DWARF2_H) $(SPLAY_TREE_H) $(TARGET_H)
-vmsdbgout.o : vmsdbgout.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) version.h \
- $(FLAGS_H) $(RTL_H) output.h vmsdbg.h debug.h langhooks.h $(FUNCTION_H) $(TARGET_H)
-xcoffout.o : xcoffout.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(TREE_H) $(RTL_H) xcoffout.h $(FLAGS_H) $(DIAGNOSTIC_CORE_H) output.h dbxout.h \
- $(GGC_H) $(TARGET_H) debug.h $(GSTAB_H) xcoff.h
-godump.o : godump.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(DIAGNOSTIC_CORE_H) \
- $(TREE_H) $(GGC_H) pointer-set.h $(OBSTACK_H) debug.h gt-godump.h
-emit-rtl.o : emit-rtl.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
- $(TREE_H) $(FLAGS_H) $(FUNCTION_H) $(REGS_H) insn-config.h $(RECOG_H) \
- $(GGC_H) $(EXPR_H) hard-reg-set.h $(BITMAP_H) $(DIAGNOSTIC_CORE_H) $(BASIC_BLOCK_H) \
- $(HASHTAB_H) $(TM_P_H) debug.h langhooks.h $(TREE_PASS_H) gt-emit-rtl.h \
- $(DF_H) $(PARAMS_H) $(TARGET_H)
-real.o : real.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
- $(DIAGNOSTIC_CORE_H) $(TM_P_H) $(REAL_H) dfp.h realmpfr.h
-realmpfr.o : realmpfr.c realmpfr.h $(CONFIG_H) $(SYSTEM_H) coretypes.h $(REAL_H) $(TREE_H)
-dfp.o : dfp.c dfp.h $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
- $(TM_P_H) $(REAL_H) $(DECNUM_H)
-fixed-value.o: fixed-value.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(TREE_H) $(REAL_H) $(DIAGNOSTIC_CORE_H)
-jump.o : jump.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
- $(FLAGS_H) hard-reg-set.h $(REGS_H) insn-config.h $(RECOG_H) $(EXPR_H) \
- $(EXCEPT_H) $(FUNCTION_H) $(BASIC_BLOCK_H) $(TREE_PASS_H) \
- $(DIAGNOSTIC_CORE_H) $(DIAGNOSTIC_CORE_H) $(INSN_ATTR_H) $(TM_P_H) reload.h \
- $(PREDICT_H) $(TARGET_H)
-simplify-rtx.o : simplify-rtx.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(RTL_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h \
- $(RECOG_H) $(EXPR_H) $(DIAGNOSTIC_CORE_H) $(FUNCTION_H) $(GGC_H) $(TM_P_H) \
- $(TREE_H) $(TARGET_H)
-symtab.o : symtab.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
- langhooks.h $(DIAGNOSTIC_CORE_H) $(FLAGS_H) $(GGC_H) $(TARGET_H) $(CGRAPH_H) \
- $(TIMEVAR_H) $(HASHTAB_H) gt-symtab.h
-cgraph.o : cgraph.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(DUMPFILE_H) \
- $(TM_H) $(TREE_H) $(TIMEVAR_H) \
- langhooks.h toplev.h $(DIAGNOSTIC_CORE_H) $(FLAGS_H) $(GGC_H) $(TARGET_H) $(CGRAPH_H) \
- gt-cgraph.h intl.h $(BASIC_BLOCK_H) debug.h $(HASHTAB_H) \
- $(TREE_INLINE_H) $(TREE_SSA_H) cif-code.def \
- value-prof.h $(EXCEPT_H) $(IPA_UTILS_H) $(DIAGNOSTIC_CORE_H) \
- $(IPA_INLINE_H) $(LTO_STREAMER_H) $(CFGLOOP_H) $(GIMPLE_PRETTY_PRINT_H)
-cgraphunit.o : cgraphunit.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(TREE_H) langhooks.h $(TREE_INLINE_H) toplev.h $(DIAGNOSTIC_CORE_H) $(FLAGS_H) $(GGC_H) \
- $(TARGET_H) $(CGRAPH_H) intl.h pointer-set.h $(FUNCTION_H) $(GIMPLE_H) \
- $(TREE_SSA_H) $(TREE_PASS_H) debug.h $(DIAGNOSTIC_H) \
- $(FIBHEAP_H) output.h $(PARAMS_H) $(RTL_H) $(IPA_PROP_H) \
- gt-cgraphunit.h tree-iterator.h $(COVERAGE_H) $(TREE_DUMP_H) \
- $(GIMPLE_PRETTY_PRINT_H) $(IPA_INLINE_H) $(IPA_UTILS_H) $(CFGLOOP_H) \
- $(LTO_STREAMER_H) output.h $(REGSET_H) $(EXCEPT_H) $(GCC_PLUGIN_H) \
- plugin.h $(CONTEXT_H) $(PASS_MANAGER_H)
-cgraphclones.o : cgraphclones.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(TREE_H) langhooks.h $(TREE_INLINE_H) toplev.h $(DIAGNOSTIC_CORE_H) $(FLAGS_H) $(GGC_H) \
- $(TARGET_H) $(CGRAPH_H) intl.h pointer-set.h $(FUNCTION_H) $(GIMPLE_H) \
- $(TREE_SSA_H) $(TREE_PASS_H) debug.h $(DIAGNOSTIC_H) $(TREE_DUMP_H) \
- $(PARAMS_H) $(RTL_H) $(IPA_PROP_H) \
- tree-iterator.h $(COVERAGE_H) \
- $(GIMPLE_PRETTY_PRINT_H) $(IPA_INLINE_H) $(IPA_UTILS_H) \
- $(LTO_STREAMER_H) $(EXCEPT_H) $(GCC_PLUGIN_H) gt-cgraphclones.h
-cgraphbuild.o : cgraphbuild.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(TREE_H) langhooks.h $(CGRAPH_H) intl.h pointer-set.h $(GIMPLE_H) \
- $(TREE_SSA_H) $(TREE_PASS_H) $(IPA_UTILS_H) $(EXCEPT_H) \
- $(IPA_INLINE_H)
-varpool.o : varpool.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(TREE_H) $(CGRAPH_H) langhooks.h $(DIAGNOSTIC_CORE_H) $(HASHTAB_H) \
- $(GGC_H) $(TIMEVAR_H) debug.h $(TARGET_H) output.h $(GIMPLE_H) \
- $(TREE_SSA_H)
-ipa.o : ipa.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(CGRAPH_H) \
- $(TREE_PASS_H) $(GIMPLE_H) $(TARGET_H) $(GGC_H) pointer-set.h \
- $(IPA_UTILS_H) tree-inline.h profile.h $(PARAMS_H)
-ipa-profile.o : ipa-profile.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(CGRAPH_H) \
- $(TREE_PASS_H) $(GIMPLE_H) $(TARGET_H) $(GGC_H) \
- $(IPA_UTILS_H) $(HASH_TABLE_H) profile.h $(PARAMS_H) \
- value-prof.h alloc-pool.h tree-inline.h $(LTO_STREAMER_H) $(DATA_STREAMER_H) \
- ipa-inline.h
-ipa-devirt.o : ipa-devirt.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(CGRAPH_H) \
- $(GIMPLE_H) $(TARGET_H) $(GGC_H) pointer-set.h \
- $(IPA_UTILS_H) $(HASH_TABLE_H) ipa-inline.h ipa-utils.h $(TREE_PRETTY_PRINT_H) \
- $(DIAGNOSTIC_H)
-ipa-prop.o : ipa-prop.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- langhooks.h $(GGC_H) $(TARGET_H) $(CGRAPH_H) $(IPA_PROP_H) $(DIAGNOSTIC_H) \
- $(TREE_SSA_H) $(TM_H) $(TREE_PASS_H) $(FLAGS_H) $(TREE_H) \
- $(TREE_INLINE_H) $(GIMPLE_H) \
- $(GIMPLE_PRETTY_PRINT_H) $(LTO_STREAMER_H) \
- $(DATA_STREAMER_H) $(TREE_STREAMER_H) $(PARAMS_H)
-ipa-ref.o : ipa-ref.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- langhooks.h $(GGC_H) $(TARGET_H) $(CGRAPH_H) $(TREE_H) $(TARGET_H) \
- $(TREE_SSA_H) $(TM_H) $(TREE_PASS_H) $(FLAGS_H) $(TREE_H) $(GGC_H) \
- $(IPA_UTILS_H)
-ipa-cp.o : ipa-cp.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TREE_H) $(TARGET_H) $(GIMPLE_H) $(CGRAPH_H) $(IPA_PROP_H) $(TREE_SSA_H) \
- $(TREE_PASS_H) $(FLAGS_H) $(DIAGNOSTIC_H) \
- $(TREE_INLINE_H) $(PARAMS_H) $(TREE_PRETTY_PRINT_H) $(IPA_INLINE_H)
-ipa-split.o : ipa-split.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TREE_H) $(TARGET_H) $(CGRAPH_H) $(IPA_PROP_H) $(TREE_SSA_H) \
- $(TREE_PASS_H) $(FLAGS_H) $(DIAGNOSTIC_H) $(TREE_DUMP_H) $(CFGLOOP_H) \
- $(TREE_INLINE_H) $(PARAMS_H) $(GIMPLE_PRETTY_PRINT_H) $(IPA_INLINE_H)
-ipa-inline.o : ipa-inline.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(TREE_H) langhooks.h $(TREE_INLINE_H) $(FLAGS_H) $(CGRAPH_H) intl.h \
- $(DIAGNOSTIC_H) $(FIBHEAP_H) $(PARAMS_H) $(TREE_PASS_H) \
- $(COVERAGE_H) $(GGC_H) $(TREE_SSA_H) $(RTL_H) $(IPA_PROP_H) \
- $(EXCEPT_H) $(GIMPLE_PRETTY_PRINT_H) $(IPA_INLINE_H) $(TARGET_H) \
- $(IPA_UTILS_H) sreal.h
-ipa-inline-analysis.o : ipa-inline-analysis.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(TREE_H) langhooks.h $(TREE_INLINE_H) $(FLAGS_H) $(CGRAPH_H) intl.h \
- $(DIAGNOSTIC_H) $(PARAMS_H) $(TREE_PASS_H) $(CFGLOOP_H) \
- $(HASHTAB_H) $(COVERAGE_H) $(GGC_H) $(TREE_SSA_H) $(IPA_PROP_H) \
- $(GIMPLE_PRETTY_PRINT_H) $(IPA_INLINE_H) $(LTO_STREAMER_H) $(DATA_STREAMER_H) \
- $(TREE_STREAMER_H) ipa-utils.h tree-scalar-evolution.h $(CFGLOOP_H) \
- alloc-pool.h
-ipa-inline-transform.o : ipa-inline-transform.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(TREE_H) langhooks.h $(TREE_INLINE_H) $(FLAGS_H) $(CGRAPH_H) intl.h \
- $(TREE_PASS_H) \
- $(HASHTAB_H) $(COVERAGE_H) $(GGC_H) $(TREE_SSA_H) $(IPA_PROP_H) \
- $(TREE_PASS_H)
-ipa-utils.o : ipa-utils.c $(IPA_UTILS_H) $(CONFIG_H) $(SYSTEM_H) \
- coretypes.h $(DUMPFILE_H) $(TM_H) $(TREE_H) $(TREE_SSA_H) $(TREE_INLINE_H) \
- langhooks.h pointer-set.h $(GGC_H) $(GIMPLE_H) $(SPLAY_TREE_H) \
- $(CGRAPH_H) $(FLAGS_H) $(DIAGNOSTIC_H)
-ipa-reference.o : ipa-reference.c $(CONFIG_H) $(SYSTEM_H) \
- coretypes.h $(TM_H) $(TREE_H) $(TREE_SSA_H) $(TREE_INLINE_H) langhooks.h \
- pointer-set.h $(GGC_H) $(IPA_REFERENCE_H) $(IPA_UTILS_H) $(SPLAY_TREE_H) \
- $(GIMPLE_H) $(CGRAPH_H) $(FLAGS_H) $(TREE_PASS_H) \
- $(DIAGNOSTIC_H) $(FUNCTION_H) $(LTO_STREAMER_H) \
- $(DIAGNOSTIC_CORE_H) $(DATA_STREAMER_H)
-ipa-pure-const.o : ipa-pure-const.c $(CONFIG_H) $(SYSTEM_H) \
- coretypes.h $(TM_H) $(TREE_H) $(TREE_SSA_H) $(TREE_INLINE_H) langhooks.h \
- pointer-set.h $(GGC_H) $(IPA_UTILS_H) $(TARGET_H) \
- $(GIMPLE_H) $(CGRAPH_H) $(FLAGS_H) $(TREE_PASS_H) \
- $(DIAGNOSTIC_H) $(CFGLOOP_H) $(SCEV_H) $(LTO_STREAMER_H) \
- $(GIMPLE_PRETTY_PRINT_H) $(DATA_STREAMER_H) $(TREE_STREAMER_H)
-coverage.o : coverage.c $(GCOV_IO_H) $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(DUMPFILE_H) \
- $(TM_H) $(RTL_H) $(TREE_H) $(FLAGS_H) output.h $(REGS_H) $(EXPR_H) \
- $(FUNCTION_H) $(BASIC_BLOCK_H) toplev.h $(DIAGNOSTIC_CORE_H) $(GGC_H) langhooks.h $(COVERAGE_H) \
- tree-iterator.h $(CGRAPH_H) gcov-io.c $(TM_P_H) \
- $(DIAGNOSTIC_CORE_H) intl.h gt-coverage.h $(TARGET_H) $(HASH_TABLE_H)
-cselib.o : cselib.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(DUMPFILE_H) \
- $(HASH_TABLE_H) $(TM_H) $(RTL_H) \
- $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h $(RECOG_H) \
- $(EMIT_RTL_H) $(DIAGNOSTIC_CORE_H) $(FUNCTION_H) \
- cselib.h gt-cselib.h $(GGC_H) $(TM_P_H) $(PARAMS_H) alloc-pool.h \
- $(HASHTAB_H) $(TARGET_H) $(BITMAP_H) $(TREE_H)
-cse.o : cse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(REGS_H) \
- hard-reg-set.h $(FLAGS_H) insn-config.h $(RECOG_H) $(EXPR_H) toplev.h $(DIAGNOSTIC_CORE_H) \
- $(FUNCTION_H) $(BASIC_BLOCK_H) $(GGC_H) $(TM_P_H) \
- $(EXCEPT_H) $(TARGET_H) $(PARAMS_H) rtlhooks-def.h $(TREE_PASS_H) \
- $(DF_H) $(DBGCNT_H)
-dce.o : dce.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
- $(TREE_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) $(EXCEPT_H) $(DF_H) cselib.h \
- $(DBGCNT_H) dce.h $(VALTRACK_H) $(TREE_PASS_H) $(DBGCNT_H) $(TM_P_H) \
- $(EMIT_RTL_H)
-dumpfile.o: dumpfile.c $(DUMPFILE_H) $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(DIAGNOSTIC_CORE_H) $(GIMPLE_PRETTY_PRINT_H) $(TREE_H)
-dse.o : dse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
- $(TREE_H) $(TM_P_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h \
- $(RECOG_H) $(EXPR_H) $(DF_H) cselib.h $(DBGCNT_H) \
- $(TREE_PASS_H) alloc-pool.h $(ALIAS_H) $(OPTABS_H) $(TARGET_H) \
- $(BITMAP_H) $(PARAMS_H) $(TREE_SSA_H) $(HASH_TABLE_H)
-fwprop.o : fwprop.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
- $(DIAGNOSTIC_CORE_H) insn-config.h $(RECOG_H) $(FLAGS_H) $(OBSTACK_H) $(BASIC_BLOCK_H) \
- $(DF_H) alloc-pool.h $(TREE_PASS_H) $(TARGET_H) \
- $(TM_P_H) $(CFGLOOP_H) $(EMIT_RTL_H) domwalk.h sparseset.h
-web.o : web.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
- hard-reg-set.h $(FLAGS_H) $(BASIC_BLOCK_H) $(FUNCTION_H) $(DIAGNOSTIC_CORE_H) \
- insn-config.h $(RECOG_H) $(DF_H) $(OBSTACK_H) $(TREE_PASS_H)
-ree.o : ree.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
- hard-reg-set.h $(FLAGS_H) $(BASIC_BLOCK_H) $(FUNCTION_H) \
- $(DF_H) $(TREE_PASS_H) $(RECOG_H) $(EXPR_H) \
- $(REGS_H) $(TREE_H) $(TM_P_H) insn-config.h $(INSN_ATTR_H) $(DIAGNOSTIC_CORE_H) \
- $(TARGET_H) $(OPTABS_H) insn-codes.h rtlhooks-def.h $(PARAMS_H) $(CGRAPH_H)
-cprop.o : cprop.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
- $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h \
- $(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H) $(FUNCTION_H) toplev.h $(DIAGNOSTIC_CORE_H) \
- $(TM_P_H) $(PARAMS_H) cselib.h $(EXCEPT_H) $(TREE_H) \
- intl.h $(OBSTACK_H) $(TREE_PASS_H) $(DF_H) $(DBGCNT_H) $(TARGET_H) \
- $(DF_H) $(CFGLOOP_H)
-gcse.o : gcse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
- $(HASH_TABLE_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h $(GGC_H) \
- $(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H) $(FUNCTION_H) toplev.h $(DIAGNOSTIC_CORE_H) \
- $(TM_P_H) $(PARAMS_H) cselib.h $(EXCEPT_H) gt-gcse.h $(TREE_H) \
- intl.h $(OBSTACK_H) $(TREE_PASS_H) $(DF_H) $(DBGCNT_H) $(TARGET_H) \
- $(DF_H) gcse.h
-store-motion.o : store-motion.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(HASH_TABLE_H) $(TM_H) $(RTL_H) \
- $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h $(GGC_H) \
- $(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H) $(FUNCTION_H) toplev.h $(DIAGNOSTIC_CORE_H) \
- $(TM_P_H) $(EXCEPT_H) $(TREE_H) \
- intl.h $(OBSTACK_H) $(TREE_PASS_H) $(DF_H) $(DBGCNT_H)
-resource.o : resource.c $(CONFIG_H) $(RTL_H) hard-reg-set.h $(SYSTEM_H) \
- coretypes.h $(TM_H) $(REGS_H) $(FLAGS_H) output.h $(RESOURCE_H) $(DF_H) \
- $(FUNCTION_H) $(DIAGNOSTIC_CORE_H) $(INSN_ATTR_H) $(EXCEPT_H) $(PARAMS_H) $(TM_P_H)
-lcm.o : lcm.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(DUMPFILE_H) $(TM_H) \
- $(RTL_H) $(REGS_H) \
- hard-reg-set.h $(FLAGS_H) insn-config.h $(INSN_ATTR_H) $(RECOG_H) \
- $(BASIC_BLOCK_H) $(TM_P_H) $(FUNCTION_H) sbitmap.h
-mode-switching.o : mode-switching.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(RTL_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h \
- $(INSN_ATTR_H) $(RECOG_H) $(BASIC_BLOCK_H) $(TM_P_H) $(FUNCTION_H) \
- $(TREE_PASS_H) $(DF_H) $(TARGET_H) $(EMIT_RTL_H)
-tree-ssa-dce.o : tree-ssa-dce.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) \
- $(TREE_SSA_H) $(DIAGNOSTIC_H) $(TM_H) \
- coretypes.h $(TREE_PASS_H) $(FLAGS_H) $(BASIC_BLOCK_H) \
- $(GGC_H) $(GIMPLE_H) $(CFGLOOP_H) $(SCEV_H) $(GIMPLE_PRETTY_PRINT_H)
-tree-call-cdce.o : tree-call-cdce.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) \
- $(TREE_SSA_H) $(TM_H) \
- coretypes.h $(TREE_PASS_H) $(FLAGS_H) $(BASIC_BLOCK_H) \
- $(GIMPLE_H) $(GIMPLE_PRETTY_PRINT_H)
-tree-ssa-ccp.o : tree-ssa-ccp.c $(TREE_SSA_H) $(CONFIG_H) \
- $(SYSTEM_H) $(TREE_H) $(TM_P_H) \
- $(DIAGNOSTIC_H) $(FUNCTION_H) $(TM_H) coretypes.h \
- $(BASIC_BLOCK_H) $(TREE_PASS_H) langhooks.h $(PARAMS_H) \
- tree-ssa-propagate.h value-prof.h $(FLAGS_H) $(TARGET_H) \
- $(DIAGNOSTIC_CORE_H) $(HASH_TABLE_H) \
- $(DBGCNT_H) $(GIMPLE_PRETTY_PRINT_H) gimple-fold.h
-tree-ssa-strlen.o : tree-ssa-strlen.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TREE_SSA_H) $(TREE_PASS_H) domwalk.h alloc-pool.h tree-ssa-propagate.h \
- $(GIMPLE_PRETTY_PRINT_H) $(PARAMS_H) $(EXPR_H) $(HASH_TABLE_H)
-tree-sra.o : tree-sra.c $(CONFIG_H) $(SYSTEM_H) coretypes.h alloc-pool.h \
- $(HASH_TABLE_H) $(TM_H) $(TREE_H) $(GIMPLE_H) $(CGRAPH_H) $(TREE_SSA_H) \
- $(IPA_PROP_H) $(DIAGNOSTIC_H) statistics.h \
- $(PARAMS_H) $(TARGET_H) $(FLAGS_H) \
- $(DBGCNT_H) $(TREE_INLINE_H) $(GIMPLE_PRETTY_PRINT_H) ipa-utils.h
-tree-switch-conversion.o : tree-switch-conversion.c $(CONFIG_H) $(SYSTEM_H) \
- $(TREE_H) $(TM_P_H) $(TREE_SSA_H) $(DIAGNOSTIC_H) $(TREE_INLINE_H) \
- $(TM_H) coretypes.h $(GIMPLE_H) $(CFGLOOP_H) \
- $(TREE_PASS_H) $(FLAGS_H) $(EXPR_H) $(BASIC_BLOCK_H) \
- $(GGC_H) $(OBSTACK_H) $(PARAMS_H) $(CPPLIB_H) $(PARAMS_H) \
- $(GIMPLE_PRETTY_PRINT_H) langhooks.h $(OPTABS_H)
-tree-complex.o : tree-complex.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TREE_H) \
- $(TM_H) $(FLAGS_H) $(TREE_SSA_H) $(TREE_HASHER_H) $(GIMPLE_H) \
- $(CFGLOOP_H) tree-iterator.h $(TREE_PASS_H) tree-ssa-propagate.h
-tree-emutls.o : tree-emutls.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TREE_H) \
- $(GIMPLE_H) $(TREE_PASS_H) $(TREE_SSA_H) $(CGRAPH_H) langhooks.h \
- $(TARGET_H) $(TARGET_DEF_H) tree-iterator.h
-tree-vect-generic.o : tree-vect-generic.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) \
- $(TM_H) $(TREE_SSA_H) $(GIMPLE_H) tree-iterator.h $(TREE_PASS_H) \
- $(FLAGS_H) $(OPTABS_H) $(MACHMODE_H) $(EXPR_H) \
- langhooks.h $(FLAGS_H) $(DIAGNOSTIC_H) gt-tree-vect-generic.h $(GGC_H) \
- coretypes.h insn-codes.h $(DIAGNOSTIC_H) $(TARGET_H)
-df-core.o : df-core.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
- insn-config.h $(RECOG_H) $(FUNCTION_H) $(REGS_H) alloc-pool.h \
- hard-reg-set.h $(BASIC_BLOCK_H) $(DF_H) $(BITMAP_H) sbitmap.h \
- $(TM_P_H) $(FLAGS_H) output.h $(TREE_PASS_H) $(PARAMS_H)
-df-problems.o : df-problems.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(DUMPFILE_H) $(TM_H) \
- $(RTL_H) insn-config.h $(RECOG_H) $(FUNCTION_H) $(REGS_H) alloc-pool.h \
- hard-reg-set.h $(BASIC_BLOCK_H) $(DF_H) $(BITMAP_H) sbitmap.h $(TIMEVAR_H) \
- $(TM_P_H) $(TARGET_H) $(FLAGS_H) $(EXCEPT_H) dce.h $(VALTRACK_H)
-df-scan.o : df-scan.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(DUMPFILE_H) \
- $(TM_H) $(RTL_H) \
- insn-config.h $(RECOG_H) $(FUNCTION_H) $(REGS_H) alloc-pool.h \
- hard-reg-set.h $(BASIC_BLOCK_H) $(DF_H) $(BITMAP_H) sbitmap.h \
- $(TM_P_H) $(FLAGS_H) $(TARGET_H) $(TARGET_DEF_H) $(TREE_H) \
- $(EMIT_RTL_H)
-regstat.o : regstat.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
- $(TM_P_H) $(FLAGS_H) $(REGS_H) $(EXCEPT_H) hard-reg-set.h \
- $(BASIC_BLOCK_H) $(TIMEVAR_H) $(DF_H)
-valtrack.o : valtrack.c $(VALTRACK_H) $(CONFIG_H) $(SYSTEM_H) \
- coretypes.h $(TM_H) $(FUNCTION_H) $(REGS_H) $(EMIT_RTL_H)
-var-tracking.o : var-tracking.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(RTL_H) $(TREE_H) hard-reg-set.h insn-config.h reload.h $(FLAGS_H) \
- $(BASIC_BLOCK_H) bitmap.h alloc-pool.h $(FIBHEAP_H) $(HASH_TABLE_H) \
- $(REGS_H) $(EXPR_H) $(TREE_PASS_H) $(TREE_SSA_H) \
- cselib.h $(TARGET_H) $(DIAGNOSTIC_CORE_H) $(PARAMS_H) $(DIAGNOSTIC_H) \
- pointer-set.h $(RECOG_H) $(TM_P_H) $(TREE_PRETTY_PRINT_H) $(ALIAS_H)
-profile.o : profile.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(DUMPFILE_H) \
- $(TM_H) $(RTL_H) \
- $(TREE_H) $(FLAGS_H) $(REGS_H) $(EXPR_H) $(FUNCTION_H) $(BASIC_BLOCK_H) \
- $(DIAGNOSTIC_CORE_H) $(COVERAGE_H) $(TREE_SSA_H) value-prof.h \
- $(CFGLOOP_H) profile.h
-mcf.o : mcf.c profile.h $(CONFIG_H) $(SYSTEM_H) $(TM_H) coretypes.h \
- $(DUMPFILE_H) $(BASIC_BLOCK_H) langhooks.h $(GCOV_IO_H) $(TREE_H)
-tree-profile.o : tree-profile.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(TARGET_H) $(TREE_H) $(FLAGS_H) $(FUNCTION_H) \
- $(BASIC_BLOCK_H) $(DIAGNOSTIC_CORE_H) $(COVERAGE_H) $(TREE_H) value-prof.h \
- $(TREE_PASS_H) $(TREE_SSA_H) gt-tree-profile.h $(CGRAPH_H)
-value-prof.o : value-prof.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(DUMPFILE_H) \
- $(TM_H) \
- $(BASIC_BLOCK_H) hard-reg-set.h profile.h value-prof.h $(EXPR_H) $(FLAGS_H) \
- $(RECOG_H) insn-config.h $(OPTABS_H) $(REGS_H) $(GGC_H) $(DIAGNOSTIC_H) \
- $(TREE_H) $(COVERAGE_H) $(RTL_H) $(GCOV_IO_H) $(TREE_SSA_H) \
- tree-flow-inline.h $(TIMEVAR_H) $(DIAGNOSTIC_CORE_H) pointer-set.h \
- $(GIMPLE_PRETTY_PRINT_H) $(DATA_STREAMER_H)
-loop-doloop.o : loop-doloop.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(DUMPFILE_H) $(TM_H) \
- $(RTL_H) $(FLAGS_H) $(EXPR_H) hard-reg-set.h $(BASIC_BLOCK_H) $(TM_P_H) \
- $(DIAGNOSTIC_CORE_H) $(CFGLOOP_H) $(PARAMS_H) $(TARGET_H)
-alloc-pool.o : alloc-pool.c $(CONFIG_H) $(SYSTEM_H) alloc-pool.h $(HASH_TABLE_H)
-auto-inc-dec.o : auto-inc-dec.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(TREE_H) $(RTL_H) $(TM_P_H) hard-reg-set.h $(BASIC_BLOCK_H) insn-config.h \
- $(REGS_H) $(FLAGS_H) $(FUNCTION_H) $(EXCEPT_H) $(DIAGNOSTIC_CORE_H) $(RECOG_H) \
- $(EXPR_H) $(TREE_PASS_H) $(DF_H) $(DBGCNT_H) $(TARGET_H)
-cfg.o : cfg.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(DUMPFILE_H) \
- $(DIAGNOSTIC_CORE_H) \
- $(GGC_H) $(OBSTACK_H) alloc-pool.h $(HASH_TABLE_H) $(CFGLOOP_H) $(TREE_H) \
- $(BASIC_BLOCK_H)
-cfghooks.o: cfghooks.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
- $(TREE_H) $(BASIC_BLOCK_H) $(TREE_SSA_H) $(TIMEVAR_H) toplev.h $(DIAGNOSTIC_CORE_H) $(CFGLOOP_H) $(PRETTY_PRINT_H)
-cfgexpand.o : cfgexpand.c $(TREE_SSA_H) $(CONFIG_H) $(SYSTEM_H) \
- $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) $(FUNCTION_H) $(TM_H) \
- coretypes.h $(EXCEPT_H) langhooks.h $(TREE_PASS_H) $(RTL_H) \
- $(DIAGNOSTIC_H) toplev.h $(DIAGNOSTIC_CORE_H) $(BASIC_BLOCK_H) $(FLAGS_H) debug.h $(PARAMS_H) \
- value-prof.h $(TREE_INLINE_H) $(TARGET_H) $(SSAEXPAND_H) $(REGS_H) \
- $(GIMPLE_PRETTY_PRINT_H) $(BITMAP_H) sbitmap.h \
- $(INSN_ATTR_H) $(CFGLOOP_H) asan.h
-cfgrtl.o : cfgrtl.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_ERROR_H) \
- $(FLAGS_H) insn-config.h $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h \
- $(FUNCTION_H) $(EXCEPT_H) $(TM_P_H) $(INSN_ATTR_H) \
- insn-config.h $(EXPR_H) \
- $(CFGLOOP_H) $(OBSTACK_H) $(TARGET_H) $(TREE_H) \
- $(TREE_PASS_H) $(DF_H) $(GGC_H) $(COMMON_TARGET_H) gt-cfgrtl.h bb-reorder.h
-cfganal.o : cfganal.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(BASIC_BLOCK_H) \
- $(TIMEVAR_H) sbitmap.h $(BITMAP_H)
-cfgbuild.o : cfgbuild.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
- $(FLAGS_H) $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h $(DIAGNOSTIC_CORE_H) \
- $(FUNCTION_H) $(EXCEPT_H) $(TIMEVAR_H) $(TREE_H) $(EXPR_H) sbitmap.h
-cfgcleanup.o : cfgcleanup.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(RTL_H) hard-reg-set.h $(FLAGS_H) $(RECOG_H) \
- $(DIAGNOSTIC_CORE_H) insn-config.h cselib.h $(TARGET_H) $(TM_P_H) $(PARAMS_H) \
- $(REGS_H) $(EMIT_RTL_H) $(FUNCTION_H) $(TREE_PASS_H) $(CFGLOOP_H) $(EXPR_H) \
- $(DF_H) $(DBGCNT_H) dce.h
-cfgloop.o : cfgloop.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) coretypes.h \
- $(DUMPFILE_H) $(TM_H) \
- $(BASIC_BLOCK_H) hard-reg-set.h $(CFGLOOP_H) $(FLAGS_H) $(FUNCTION_H) \
- $(OBSTACK_H) toplev.h $(DIAGNOSTIC_CORE_H) $(TREE_SSA_H) $(TREE_H) pointer-set.h \
- $(GGC_H)
-cfgloopanal.o : cfgloopanal.c coretypes.h $(DUMPFILE_H) $(CONFIG_H) \
- $(SYSTEM_H) $(RTL_H) \
- $(BASIC_BLOCK_H) hard-reg-set.h $(CFGLOOP_H) $(EXPR_H) $(TM_H) \
- $(OBSTACK_H) graphds.h $(PARAMS_H)
-graphds.o : graphds.c graphds.h $(CONFIG_H) $(SYSTEM_H) $(BITMAP_H) $(OBSTACK_H) \
- coretypes.h $(VEC_H)
-loop-iv.o : loop-iv.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(DUMPFILE_H) \
- $(RTL_H) $(BASIC_BLOCK_H) \
- hard-reg-set.h $(CFGLOOP_H) $(EXPR_H) $(TM_H) $(OBSTACK_H) \
- intl.h $(DIAGNOSTIC_CORE_H) $(DF_H) $(HASH_TABLE_H)
-loop-invariant.o : loop-invariant.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(DUMPFILE_H) \
- $(RTL_H) $(BASIC_BLOCK_H) hard-reg-set.h $(CFGLOOP_H) $(EXPR_H) $(RECOG_H) \
- $(TM_H) $(TM_P_H) $(FUNCTION_H) $(FLAGS_H) $(DF_H) $(TARGET_H) \
- $(OBSTACK_H) $(HASH_TABLE_H) $(EXCEPT_H) $(PARAMS_H) $(REGS_H) ira.h
-cfgloopmanip.o : cfgloopmanip.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) \
- $(BASIC_BLOCK_H) hard-reg-set.h $(CFGLOOP_H) \
- coretypes.h $(TM_H) $(OBSTACK_H) $(TREE_SSA_H)
-loop-init.o : loop-init.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(GGC_H) \
- $(BASIC_BLOCK_H) hard-reg-set.h $(CFGLOOP_H) \
- coretypes.h $(TM_H) $(OBSTACK_H) $(TREE_PASS_H) $(FLAGS_H) \
- $(REGS_H) $(DF_H) $(TREE_SSA_H)
-loop-unswitch.o : loop-unswitch.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(DUMPFILE_H) \
- $(RTL_H) $(TM_H) $(BASIC_BLOCK_H) hard-reg-set.h $(CFGLOOP_H) $(PARAMS_H) \
- $(EXPR_H) $(TM_H) $(OBSTACK_H)
-loop-unroll.o: loop-unroll.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(DUMPFILE_H) \
- $(RTL_H) $(TM_H) $(BASIC_BLOCK_H) hard-reg-set.h $(CFGLOOP_H) $(PARAMS_H) \
- $(EXPR_H) $(TM_H) $(HASH_TABLE_H) $(RECOG_H) $(OBSTACK_H)
-dominance.o : dominance.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
- hard-reg-set.h $(BASIC_BLOCK_H) et-forest.h $(OBSTACK_H) $(DIAGNOSTIC_CORE_H) \
- $(TIMEVAR_H) graphds.h pointer-set.h $(BITMAP_H)
-et-forest.o : et-forest.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- et-forest.h alloc-pool.h $(BASIC_BLOCK_H)
-combine.o : combine.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
- $(FLAGS_H) $(FUNCTION_H) insn-config.h $(INSN_ATTR_H) $(REGS_H) $(EXPR_H) \
- rtlhooks-def.h $(BASIC_BLOCK_H) $(RECOG_H) hard-reg-set.h \
- $(DIAGNOSTIC_CORE_H) $(TM_P_H) $(TREE_H) $(TARGET_H) \
- output.h $(PARAMS_H) $(OPTABS_H) \
- insn-codes.h $(TREE_PASS_H) $(DF_H) $(VALTRACK_H) \
- $(CGRAPH_H) $(OBSTACK_H)
-reginfo.o : reginfo.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
- hard-reg-set.h $(FLAGS_H) $(BASIC_BLOCK_H) addresses.h $(REGS_H) \
- insn-config.h $(RECOG_H) reload.h $(DIAGNOSTIC_CORE_H) \
- $(FUNCTION_H) output.h $(TM_P_H) $(EXPR_H) $(HASHTAB_H) \
- $(TARGET_H) $(TREE_PASS_H) $(DF_H) ira.h
-bitmap.o : bitmap.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(VEC_H) \
- $(GGC_H) gt-bitmap.h $(BITMAP_H) $(OBSTACK_H) $(HASH_TABLE_H)
-vec.o : vec.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(VEC_H) $(GGC_H) \
- $(DIAGNOSTIC_CORE_H) $(HASHTAB_H)
-hash-table.o : hash-table.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(HASHTAB_H)
-reload.o : reload.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_ERROR_H) \
- $(FLAGS_H) $(EXPR_H) $(OPTABS_H) reload.h $(RECOG_H) \
- hard-reg-set.h insn-config.h $(REGS_H) $(FUNCTION_H) real.h \
- addresses.h $(TM_P_H) $(PARAMS_H) $(TARGET_H) $(DF_H) ira.h $(DIAGNOSTIC_CORE_H)
-reload1.o : reload1.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(DUMPFILE_H) \
- $(TM_H) $(RTL_ERROR_H) \
- $(EXPR_H) $(OPTABS_H) reload.h $(REGS_H) hard-reg-set.h insn-config.h \
- $(BASIC_BLOCK_H) $(RECOG_H) $(FUNCTION_H) $(TM_P_H) \
- addresses.h $(EXCEPT_H) $(TREE_H) $(FLAGS_H) $(MACHMODE_H) \
- $(OBSTACK_H) $(DF_H) $(TARGET_H) $(EMIT_RTL_H) ira.h
-rtlhooks.o : rtlhooks.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
- rtlhooks-def.h $(EXPR_H) $(RECOG_H)
-postreload.o : postreload.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(RTL_H) $(FLAGS_H) $(EXPR_H) $(OPTABS_H) reload.h $(REGS_H) \
- hard-reg-set.h insn-config.h $(BASIC_BLOCK_H) $(RECOG_H) \
- $(FUNCTION_H) $(DIAGNOSTIC_CORE_H) cselib.h $(TM_P_H) $(EXCEPT_H) $(TREE_H) $(MACHMODE_H) \
- $(OBSTACK_H) $(TARGET_H) $(TREE_PASS_H) $(DF_H) $(DBGCNT_H)
-postreload-gcse.o : postreload-gcse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(RTL_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h \
- $(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H) $(FUNCTION_H) $(DIAGNOSTIC_CORE_H) \
- $(TM_P_H) $(EXCEPT_H) $(TREE_H) $(TARGET_H) $(HASH_TABLE_H) intl.h \
- $(OBSTACK_H) $(PARAMS_H) $(TREE_PASS_H) $(DBGCNT_H)
-caller-save.o : caller-save.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(DUMPFILE_H) $(TM_H) $(RTL_H) \
- $(FLAGS_H) $(REGS_H) hard-reg-set.h insn-config.h $(BASIC_BLOCK_H) $(FUNCTION_H) \
- addresses.h $(RECOG_H) reload.h $(EXPR_H) $(DIAGNOSTIC_CORE_H) $(TM_P_H) $(DF_H) \
- gt-caller-save.h $(GGC_H)
-bt-load.o : bt-load.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(EXCEPT_H) \
- $(RTL_H) hard-reg-set.h $(REGS_H) $(TM_P_H) $(FIBHEAP_H) $(EXPR_H) \
- $(TARGET_H) $(FLAGS_H) $(INSN_ATTR_H) $(FUNCTION_H) $(TREE_PASS_H) \
- $(DIAGNOSTIC_CORE_H) $(DF_H) $(RECOG_H) $(CFGLOOP_H)
-reorg.o : reorg.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
- conditions.h hard-reg-set.h $(BASIC_BLOCK_H) $(REGS_H) insn-config.h \
- $(INSN_ATTR_H) $(EXCEPT_H) $(RECOG_H) $(FUNCTION_H) $(FLAGS_H) output.h \
- $(EXPR_H) $(DIAGNOSTIC_CORE_H) $(PARAMS_H) $(TM_P_H) $(OBSTACK_H) $(RESOURCE_H) \
- $(TARGET_H) $(TREE_PASS_H)
-alias.o : alias.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(DUMPFILE_H) \
- $(TM_H) $(RTL_H) \
- $(FLAGS_H) hard-reg-set.h $(BASIC_BLOCK_H) $(REGS_H) $(DIAGNOSTIC_CORE_H) \
- $(ALIAS_H) $(EMIT_RTL_H) $(GGC_H) $(FUNCTION_H) cselib.h $(TREE_H) $(TM_P_H) \
- langhooks.h $(TARGET_H) gt-alias.h $(TIMEVAR_H) $(CGRAPH_H) \
- $(SPLAY_TREE_H) $(DF_H) \
- tree-ssa-alias.h pointer-set.h $(TREE_SSA_H)
-stack-ptr-mod.o : stack-ptr-mod.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(TREE_H) $(RTL_H) $(REGS_H) $(EXPR_H) $(TREE_PASS_H) \
- $(BASIC_BLOCK_H) $(FLAGS_H) output.h $(DF_H)
-init-regs.o : init-regs.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(TREE_H) $(RTL_H) $(REGS_H) $(EXPR_H) $(TREE_PASS_H) \
- $(BASIC_BLOCK_H) $(FLAGS_H) $(DF_H)
-ira-build.o: ira-build.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(TARGET_H) $(RTL_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) \
- insn-config.h $(RECOG_H) $(BASIC_BLOCK_H) $(DIAGNOSTIC_CORE_H) $(TM_P_H) \
- $(PARAMS_H) $(DF_H) sparseset.h $(IRA_INT_H) reload.h
-ira-costs.o: ira-costs.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- hard-reg-set.h $(RTL_H) $(EXPR_H) $(TM_P_H) $(FLAGS_H) $(BASIC_BLOCK_H) \
- $(REGS_H) addresses.h insn-config.h $(RECOG_H) $(DIAGNOSTIC_CORE_H) \
- $(HASH_TABLE_H) $(TARGET_H) $(PARAMS_H) $(IRA_INT_H) reload.h
-ira-conflicts.o: ira-conflicts.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(TARGET_H) $(RTL_H) $(REGS_H) hard-reg-set.h $(TREE_H) $(FLAGS_H) \
- insn-config.h $(RECOG_H) $(BASIC_BLOCK_H) $(DIAGNOSTIC_CORE_H) $(TM_P_H) $(PARAMS_H) \
- $(DF_H) sparseset.h addresses.h $(IRA_INT_H)
-ira-color.o: ira-color.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(HASH_TABLE_H) $(TARGET_H) $(RTL_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) \
- $(EXPR_H) $(BASIC_BLOCK_H) $(DIAGNOSTIC_CORE_H) $(TM_P_H) reload.h $(PARAMS_H) \
- $(DF_H) $(IRA_INT_H)
-ira-emit.o: ira-emit.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(REGS_H) $(RTL_H) $(TM_P_H) $(TARGET_H) $(FLAGS_H) hard-reg-set.h \
- $(BASIC_BLOCK_H) $(EXPR_H) $(RECOG_H) $(PARAMS_H) \
- $(TREE_PASS_H) reload.h $(DF_H) $(IRA_INT_H)
-ira-lives.o: ira-lives.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(TARGET_H) $(RTL_H) $(REGS_H) $(EXCEPT_H) hard-reg-set.h $(FLAGS_H) \
- insn-config.h $(RECOG_H) $(BASIC_BLOCK_H) $(DIAGNOSTIC_CORE_H) $(TM_P_H) $(PARAMS_H) \
- $(DF_H) sparseset.h $(IRA_INT_H)
-ira.o: ira.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(REGS_H) $(RTL_H) $(TM_P_H) $(TARGET_H) $(FLAGS_H) $(OBSTACK_H) \
- $(BITMAP_H) hard-reg-set.h $(BASIC_BLOCK_H) $(DBGCNT_H) $(FUNCTION_H) \
- $(EXPR_H) $(RECOG_H) $(PARAMS_H) $(TREE_PASS_H) output.h \
- $(EXCEPT_H) reload.h toplev.h $(DIAGNOSTIC_CORE_H) \
- $(DF_H) $(GGC_H) $(IRA_INT_H) lra.h
-lra.o : lra.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(RTL_H) $(REGS_H) insn-config.h insn-codes.h $(TIMEVAR_H) $(TREE_PASS_H) \
- $(DF_H) $(RECOG_H) output.h addresses.h $(REGS_H) hard-reg-set.h \
- $(FLAGS_H) $(FUNCTION_H) $(EXPR_H) $(BASIC_BLOCK_H) $(TM_P_H) \
- $(EXCEPT_H) ira.h $(LRA_INT_H)
-lra-assigns.o : lra-assigns.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(RTL_H) $(RTL_ERROR_H) $(REGS_H) insn-config.h $(DF_H) \
- $(RECOG_H) output.h $(REGS_H) hard-reg-set.h $(FLAGS_H) $(FUNCTION_H) \
- $(EXPR_H) $(BASIC_BLOCK_H) $(TM_P_H) $(EXCEPT_H) ira.h \
- rtl-error.h sparseset.h $(LRA_INT_H)
-lra-coalesce.o : lra-coalesce.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(RTL_H) $(REGS_H) insn-config.h $(DF_H) \
- $(RECOG_H) output.h $(REGS_H) hard-reg-set.h $(FLAGS_H) $(FUNCTION_H) \
- $(EXPR_H) $(BASIC_BLOCK_H) $(TM_P_H) $(EXCEPT_H) ira.h \
- rtl-error.h ira.h $(LRA_INT_H)
-lra-constraints.o : lra-constraints.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(RTL_H) $(REGS_H) insn-config.h insn-codes.h $(DF_H) \
- $(RECOG_H) output.h addresses.h $(REGS_H) hard-reg-set.h $(FLAGS_H) \
- $(FUNCTION_H) $(EXPR_H) $(BASIC_BLOCK_H) $(TM_P_H) $(EXCEPT_H) \
- ira.h rtl-error.h $(LRA_INT_H) $(OPTABS_H)
-lra-eliminations.o : lra-eliminations.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(RTL_H) $(REGS_H) insn-config.h $(DF_H) \
- $(RECOG_H) output.h $(REGS_H) hard-reg-set.h $(FLAGS_H) $(FUNCTION_H) \
- $(EXPR_H) $(BASIC_BLOCK_H) $(TM_P_H) $(EXCEPT_H) ira.h \
- rtl-error.h $(LRA_INT_H) $(OPTABS_H)
-lra-lives.o : lra-lives.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(RTL_H) $(REGS_H) insn-config.h $(DF_H) \
- $(RECOG_H) output.h $(REGS_H) hard-reg-set.h $(FLAGS_H) $(FUNCTION_H) \
- $(EXPR_H) $(BASIC_BLOCK_H) $(TM_P_H) $(EXCEPT_H) \
- $(LRA_INT_H)
-lra-spills.o : lra-spills.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(RTL_H) $(REGS_H) insn-config.h $(DF_H) \
- $(RECOG_H) output.h $(REGS_H) hard-reg-set.h $(FLAGS_H) $(FUNCTION_H) \
- $(EXPR_H) $(BASIC_BLOCK_H) $(TM_P_H) $(EXCEPT_H) \
- ira.h $(LRA_INT_H)
-regmove.o : regmove.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
- insn-config.h $(TREE_PASS_H) $(DF_H) \
- $(RECOG_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) $(FUNCTION_H) \
- $(EXPR_H) $(BASIC_BLOCK_H) $(DIAGNOSTIC_CORE_H) $(TM_P_H) \
- $(EXCEPT_H) ira.h reload.h $(TARGET_H)
-combine-stack-adj.o : combine-stack-adj.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(RTL_H) insn-config.h $(TREE_PASS_H) \
- $(RECOG_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) $(FUNCTION_H) \
- $(EXPR_H) $(BASIC_BLOCK_H) $(TM_P_H) $(DF_H) $(EXCEPT_H) reload.h
-compare-elim.o : compare-elim.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(RTL_H) $(TM_P_H) insn-config.h $(RECOG_H) $(FLAGS_H) \
- $(BASIC_BLOCK_H) $(TREE_PASS_H) $(TARGET_H) $(DF_H) domwalk.h
-ddg.o : ddg.c $(DDG_H) $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TARGET_H) \
- $(DIAGNOSTIC_CORE_H) $(RTL_H) $(TM_P_H) $(REGS_H) $(FUNCTION_H) \
- $(FLAGS_H) insn-config.h $(INSN_ATTR_H) $(EXCEPT_H) $(RECOG_H) \
- $(SCHED_INT_H) $(CFGLOOP_H) $(EXPR_H) $(BITMAP_H) \
- hard-reg-set.h sbitmap.h $(TM_H)
-modulo-sched.o : modulo-sched.c $(DDG_H) $(CONFIG_H) $(CONFIG_H) $(SYSTEM_H) \
- coretypes.h $(TARGET_H) $(DIAGNOSTIC_CORE_H) $(RTL_H) $(TM_P_H) $(REGS_H) $(FUNCTION_H) \
- $(FLAGS_H) insn-config.h $(INSN_ATTR_H) $(EXCEPT_H) $(RECOG_H) \
- $(SCHED_INT_H) $(CFGLOOP_H) $(EXPR_H) $(PARAMS_H) \
- $(GCOV_IO_H) hard-reg-set.h $(TM_H) $(TREE_PASS_H) \
- $(DF_H) $(DBGCNT_H)
-haifa-sched.o : haifa-sched.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(DUMPFILE_H) $(TM_H) $(RTL_H) \
- $(SCHED_INT_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h $(FUNCTION_H) \
- $(INSN_ATTR_H) $(DIAGNOSTIC_CORE_H) $(RECOG_H) $(EXCEPT_H) $(TM_P_H) $(TARGET_H) \
- $(PARAMS_H) $(DBGCNT_H) $(CFGLOOP_H) ira.h $(EMIT_RTL_H) $(COMMON_TARGET_H) \
- $(HASH_TABLE_H)
-sched-deps.o : sched-deps.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(RTL_H) $(SCHED_INT_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h \
- $(FUNCTION_H) $(INSN_ATTR_H) $(DIAGNOSTIC_CORE_H) $(RECOG_H) $(EXCEPT_H) cselib.h \
- ira.h $(PARAMS_H) $(TM_P_H) ira.h $(TARGET_H) $(TREE_H) $(EMIT_RTL_H)
-sched-rgn.o : sched-rgn.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(RTL_H) $(SCHED_INT_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h \
- $(FUNCTION_H) $(INSN_ATTR_H) $(DIAGNOSTIC_CORE_H) $(RECOG_H) $(EXCEPT_H) $(PARAMS_H) \
- $(TM_P_H) sel-sched.h $(TARGET_H) $(TREE_PASS_H) \
- $(DBGCNT_H)
-sched-ebb.o : sched-ebb.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(RTL_H) $(SCHED_INT_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h \
- $(FUNCTION_H) $(INSN_ATTR_H) $(DIAGNOSTIC_CORE_H) $(RECOG_H) $(EXCEPT_H) $(TM_P_H) \
- $(PARAMS_H) $(TARGET_H)
-sched-vis.o : sched-vis.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(DUMPFILE_H) \
- $(TM_H) $(INSN_ATTR_H) $(RTL_H) $(TREE_H) $(BASIC_BLOCK_H) $(PRETTY_PRINT_H)
-sel-sched.o : sel-sched.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(RTL_ERROR_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h \
- $(FUNCTION_H) $(INSN_ATTR_H) $(RECOG_H) $(EXCEPT_H) $(PARAMS_H) \
- $(TM_P_H) output.h $(TARGET_H) $(TREE_PASS_H) \
- $(SCHED_INT_H) $(GGC_H) $(TREE_H) langhooks.h rtlhooks-def.h \
- $(SEL_SCHED_IR_H) $(SEL_SCHED_DUMP_H) sel-sched.h $(DBGCNT_H) $(EMIT_RTL_H) ira.h
-sel-sched-dump.o : sel-sched-dump.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(RTL_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h \
- $(FUNCTION_H) $(INSN_ATTR_H) $(DIAGNOSTIC_CORE_H) $(RECOG_H) $(EXCEPT_H) $(PARAMS_H) \
- $(TM_P_H) $(TARGET_H) $(TREE_PASS_H) \
- $(SEL_SCHED_DUMP_H) $(GGC_H) $(TREE_H) $(LANGHOOKS_DEF_H) $(SEL_SCHED_IR_H) \
- $(BASIC_BLOCK_H) cselib.h
-sel-sched-ir.o : sel-sched-ir.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(RTL_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h \
- $(FUNCTION_H) $(INSN_ATTR_H) $(DIAGNOSTIC_CORE_H) $(RECOG_H) $(EXCEPT_H) $(PARAMS_H) \
- $(TM_P_H) $(TARGET_H) $(TREE_PASS_H) $(SCHED_INT_H) $(GGC_H) \
- $(TREE_H) langhooks.h rtlhooks-def.h $(SEL_SCHED_IR_H) $(SEL_SCHED_DUMP_H) \
- $(EMIT_RTL_H)
-final.o : final.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_ERROR_H) \
- $(TREE_H) $(FLAGS_H) intl.h $(REGS_H) $(RECOG_H) conditions.h \
- insn-config.h $(INSN_ATTR_H) $(FUNCTION_H) output.h hard-reg-set.h \
- $(EXCEPT_H) debug.h xcoffout.h toplev.h $(DIAGNOSTIC_CORE_H) reload.h $(DWARF2OUT_H) \
- $(TREE_PASS_H) $(BASIC_BLOCK_H) $(TM_P_H) $(TARGET_H) $(EXPR_H) \
- dbxout.h $(CGRAPH_H) $(COVERAGE_H) \
- $(DF_H) $(GGC_H) $(CFGLOOP_H) $(PARAMS_H) $(TREE_SSA_H) \
- $(TARGET_DEF_H) $(TREE_PRETTY_PRINT_H)
-recog.o : recog.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_ERROR_H) \
- $(FUNCTION_H) $(BASIC_BLOCK_H) $(REGS_H) $(RECOG_H) $(EXPR_H) \
- $(FLAGS_H) insn-config.h $(INSN_ATTR_H) reload.h \
- addresses.h $(TM_P_H) $(TREE_PASS_H) hard-reg-set.h \
- $(DF_H) $(DBGCNT_H) $(TARGET_H) $(DIAGNOSTIC_CORE_H) insn-codes.h
-reg-stack.o : reg-stack.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(RTL_ERROR_H) $(TREE_H) $(RECOG_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) \
- insn-config.h reload.h $(FUNCTION_H) $(TM_P_H) $(GGC_H) \
- $(BASIC_BLOCK_H) \
- $(TREE_PASS_H) $(TARGET_H) $(DF_H) $(EMIT_RTL_H)
-sreal.o: sreal.c $(CONFIG_H) $(SYSTEM_H) coretypes.h sreal.h
-predict.o: predict.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
- $(TREE_H) $(FLAGS_H) insn-config.h $(BASIC_BLOCK_H) $(REGS_H) \
- hard-reg-set.h $(DIAGNOSTIC_CORE_H) $(RECOG_H) $(FUNCTION_H) $(EXCEPT_H) \
- $(TM_P_H) $(PREDICT_H) sreal.h $(PARAMS_H) $(TARGET_H) $(CFGLOOP_H) \
- $(COVERAGE_H) $(SCEV_H) $(GGC_H) predict.def \
- $(TREE_SSA_H) $(TREE_PASS_H) $(EXPR_H) pointer-set.h
-lists.o: lists.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(DIAGNOSTIC_CORE_H) \
- $(RTL_H) $(GGC_H) gt-lists.h
-bb-reorder.o : bb-reorder.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(RTL_H) $(FLAGS_H) output.h $(FIBHEAP_H) \
- $(TARGET_H) $(FUNCTION_H) $(TM_P_H) $(OBSTACK_H) $(EXPR_H) $(REGS_H) \
- $(PARAMS_H) toplev.h $(DIAGNOSTIC_CORE_H) $(TREE_PASS_H) $(DF_H) \
- $(EXCEPT_H) bb-reorder.h
-tracer.o : tracer.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
- $(TREE_H) $(BASIC_BLOCK_H) hard-reg-set.h \
- $(FLAGS_H) $(PARAMS_H) $(COVERAGE_H) $(FIBHEAP_H) \
- $(TREE_PASS_H) $(TREE_SSA_H) $(TREE_INLINE_H) $(CFGLOOP_H)
-timevar.o : timevar.c $(CONFIG_H) $(SYSTEM_H) $(TIMEVAR_H)
-regcprop.o : regcprop.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(RTL_H) insn-config.h $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h \
- $(RECOG_H) $(FUNCTION_H) $(OBSTACK_H) $(FLAGS_H) $(TM_P_H) \
- addresses.h reload.h $(DIAGNOSTIC_CORE_H) $(TREE_PASS_H) $(DF_H)
-regrename.o : regrename.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(RTL_ERROR_H) insn-config.h $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h \
- output.h $(RECOG_H) $(FUNCTION_H) $(OBSTACK_H) $(FLAGS_H) $(TM_P_H) \
- addresses.h reload.h $(TREE_PASS_H) $(DF_H) $(TARGET_H) \
- regrename.h $(EMIT_RTL_H)
-ifcvt.o : ifcvt.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
- $(REGS_H) $(DIAGNOSTIC_CORE_H) $(FLAGS_H) insn-config.h $(FUNCTION_H) $(RECOG_H) \
- $(TARGET_H) $(BASIC_BLOCK_H) $(EXPR_H) output.h $(EXCEPT_H) $(TM_P_H) \
- $(OPTABS_H) $(CFGLOOP_H) hard-reg-set.h pointer-set.h \
- $(TREE_PASS_H) $(DF_H) $(DBGCNT_H)
-params.o : params.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(COMMON_TARGET_H) \
- $(PARAMS_H) $(DIAGNOSTIC_CORE_H)
-pointer-set.o: pointer-set.c pointer-set.h $(CONFIG_H) $(SYSTEM_H)
-hooks.o: hooks.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(HOOKS_H)
-pretty-print.o: $(CONFIG_H) $(SYSTEM_H) coretypes.h intl.h $(PRETTY_PRINT_H) \
- diagnostic-color.h
-errors.o : errors.c $(CONFIG_H) $(SYSTEM_H) errors.h
-dbgcnt.o: dbgcnt.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(DUMPFILE_H) \
- $(DIAGNOSTIC_CORE_H) $(DBGCNT_H)
-lower-subreg.o : lower-subreg.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(MACHMODE_H) $(TM_H) $(RTL_H) $(TM_P_H) $(FLAGS_H) \
- insn-config.h $(BASIC_BLOCK_H) $(RECOG_H) $(OBSTACK_H) $(BITMAP_H) \
- $(EXPR_H) $(EXCEPT_H) $(REGS_H) $(TREE_PASS_H) $(DF_H) dce.h \
- lower-subreg.h
-target-globals.o : target-globals.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) insn-config.h $(MACHMODE_H) $(GGC_H) toplev.h target-globals.h \
- $(FLAGS_H) $(REGS_H) $(RTL_H) reload.h expmed.h $(EXPR_H) $(OPTABS_H) \
- $(LIBFUNCS_H) $(CFGLOOP_H) $(IRA_INT_H) builtins.h gcse.h bb-reorder.h \
- lower-subreg.h
-hw-doloop.o : hw-doloop.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(DUMPFILE_H) \
- $(TM_H) \
- $(RTL_H) $(FLAGS_H) $(EXPR_H) hard-reg-set.h $(BASIC_BLOCK_H) $(TM_P_H) \
- $(DF_H) $(CFGLOOP_H) $(RECOG_H) $(TARGET_H) \
- $(REGS_H) hw-doloop.h
-file-find.o: file-find.c $(CONFIG_H) $(SYSTEM_H) file-find.h
-$(out_object_file): $(out_file) $(CONFIG_H) coretypes.h $(TM_H) $(TREE_H) \
- $(RTL_H) $(REGS_H) hard-reg-set.h insn-config.h conditions.h \
- output.h $(INSN_ATTR_H) $(SYSTEM_H) toplev.h $(DIAGNOSTIC_CORE_H) \
- $(TARGET_H) $(LIBFUNCS_H) $(TARGET_DEF_H) $(FUNCTION_H) $(SCHED_INT_H) \
- $(TM_P_H) $(EXPR_H) langhooks.h $(GGC_H) $(OPTABS_H) $(REAL_H) \
- tm-constrs.h $(GIMPLE_H) $(DF_H) cselib.h $(COMMON_TARGET_H) hw-doloop.h \
- regrename.h
- $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) \
- $(out_file) $(OUTPUT_OPTION)
-context.o: context.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(GGC_H) \
- $(CONTEXT_H) $(PASS_MANAGER_H)
-
-$(common_out_object_file): $(common_out_file) $(CONFIG_H) $(SYSTEM_H) \
- coretypes.h $(COMMON_TARGET_H) $(COMMON_TARGET_DEF_H) $(PARAMS_H) \
- $(DIAGNOSTIC_CORE_H) $(FLAGS_H) $(OPTS_H) $(TM_H) $(TM_P_H) $(MACHMODE_H)
- $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) \
- $< $(OUTPUT_OPTION)
+$(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.
@@ -3656,50 +2130,6 @@ s-mddeps: $(md_file) $(MD_INCLUDES) build/genmddeps$(build_exeext)
$(SHELL) $(srcdir)/../move-if-change tmp-mddeps mddeps.mk
$(STAMP) s-mddeps
-# Header dependencies for generated source files.
-insn-attrtab.o : insn-attrtab.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(RTL_H) $(REGS_H) output.h $(INSN_ATTR_H) \
- insn-config.h $(DIAGNOSTIC_CORE_H) $(RECOG_H) $(TM_P_H) $(FLAGS_H)
-insn-automata.o : insn-automata.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(RTL_H) $(REGS_H) output.h $(INSN_ATTR_H) \
- insn-config.h toplev.h $(DIAGNOSTIC_CORE_H) $(RECOG_H) \
- $(TM_P_H) $(FLAGS_H) $(EMIT_RTL_H)
-insn-dfatab.o : insn-dfatab.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(RTL_H) $(REGS_H) output.h $(INSN_ATTR_H) \
- insn-config.h $(DIAGNOSTIC_CORE_H) $(RECOG_H) $(TM_P_H) $(FLAGS_H)
-insn-emit.o : insn-emit.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(RTL_H) $(TM_P_H) $(FUNCTION_H) $(EXPR_H) $(OPTABS_H) \
- dfp.h $(FLAGS_H) output.h insn-config.h hard-reg-set.h $(RECOG_H) \
- $(RESOURCE_H) reload.h $(DIAGNOSTIC_CORE_H) $(REGS_H) tm-constrs.h \
- $(GGC_H) $(BASIC_BLOCK_H) $(TARGET_H)
-insn-enums.o : insn-enums.c $(CONFIG_H) $(SYSTEM_H) insn-constants.h
-insn-extract.o : insn-extract.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(RTL_H) $(DIAGNOSTIC_CORE_H) insn-config.h $(RECOG_H)
-insn-latencytab.o : insn-latencytab.c $(CONFIG_H) $(SYSTEM_H) \
- coretypes.h $(TM_H) $(RTL_H) $(REGS_H) output.h $(INSN_ATTR_H) \
- insn-config.h $(DIAGNOSTIC_CORE_H) $(RECOG_H) $(TM_P_H) $(FLAGS_H)
-insn-modes.o : insn-modes.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(MACHMODE_H)
-insn-opinit.o : insn-opinit.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(RTL_H) $(TM_P_H) insn-config.h $(FLAGS_H) $(RECOG_H) \
- $(EXPR_H) $(OPTABS_H)
-insn-output.o : insn-output.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(RTL_H) $(GGC_H) $(REGS_H) conditions.h \
- hard-reg-set.h insn-config.h $(INSN_ATTR_H) $(EXPR_H) output.h \
- $(RECOG_H) $(FUNCTION_H) $(DIAGNOSTIC_CORE_H) $(FLAGS_H) insn-codes.h $(TM_P_H)\
- $(TARGET_H) tm-constrs.h
-insn-peep.o : insn-peep.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- insn-config.h $(RTL_H) $(TM_P_H) $(REGS_H) output.h \
- $(RECOG_H) $(EXCEPT_H) $(FUNCTION_H) $(DIAGNOSTIC_CORE_H) $(FLAGS_H) tm-constrs.h
-insn-preds.o : insn-preds.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(RTL_H) $(TREE_H) insn-config.h $(RECOG_H) output.h \
- $(FLAGS_H) $(FUNCTION_H) hard-reg-set.h $(RESOURCE_H) $(TM_P_H) \
- $(DIAGNOSTIC_CORE_H) reload.h $(REGS_H) tm-constrs.h
-insn-recog.o : insn-recog.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(RTL_H) insn-config.h $(RECOG_H) output.h $(FLAGS_H) \
- $(FUNCTION_H) hard-reg-set.h $(RESOURCE_H) $(TM_P_H) $(DIAGNOSTIC_CORE_H) \
- reload.h $(REGS_H) tm-constrs.h
-
# 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,
@@ -3926,8 +2356,8 @@ GTFILES = $(CPP_ID_DATA_H) $(srcdir)/input.h $(srcdir)/coretypes.h \
$(srcdir)/reg-stack.c $(srcdir)/cfgrtl.c \
$(srcdir)/sdbout.c $(srcdir)/stor-layout.c \
$(srcdir)/stringpool.c $(srcdir)/tree.c $(srcdir)/varasm.c \
- $(srcdir)/gimple.h $(srcdir)/gimple.c \
- $(srcdir)/tree-mudflap.c $(srcdir)/tree-flow.h \
+ $(srcdir)/gimple.h \
+ $(srcdir)/gimple-ssa.h \
$(srcdir)/tree-ssanames.c $(srcdir)/tree-eh.c $(srcdir)/tree-ssa-address.c \
$(srcdir)/tree-cfg.c \
$(srcdir)/tree-dfa.c \
@@ -4002,12 +2432,10 @@ s-gtype: build/gengtype$(build_exeext) $(filter-out [%], $(GTFILES)) \
generated_files = config.h tm.h $(TM_P_H) $(TM_H) multilib.h \
$(simple_generated_h) specs.h \
tree-check.h genrtl.h insn-modes.h tm-preds.h tm-constrs.h \
- $(ALL_GTFILES_H) gtype-desc.c gtype-desc.h gcov-iov.h
-
-# 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)
+ $(ALL_GTFILES_H) gtype-desc.c gtype-desc.h gcov-iov.h \
+ options.h target-hooks-def.h insn-opinit.h \
+ common/common-target-hooks-def.h pass-instances.def \
+ c-family/c-target-hooks-def.h
#
# How to compile object files to run on the build machine.
@@ -4199,7 +2627,6 @@ gengtype-lex.c : gengtype-lex.l
#
# Remake internationalization support.
CFLAGS-intl.o += -DLOCALEDIR=\"$(localedir)\"
-intl.o: intl.c $(CONFIG_H) $(SYSTEM_H) coretypes.h intl.h Makefile
#
# Remake cpp.
@@ -4220,13 +2647,8 @@ PREPROCESSOR_DEFINES = \
@TARGET_SYSTEM_ROOT_DEFINE@
CFLAGS-cppbuiltin.o += $(PREPROCESSOR_DEFINES) -DBASEVER=$(BASEVER_s)
-cppbuiltin.o: cppbuiltin.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(TARGET_H) $(TARGET_DEF) $(TREE_H) $(CPP_ID_DATA_H) \
- cppbuiltin.h version.h Makefile
CFLAGS-cppdefault.o += $(PREPROCESSOR_DEFINES)
-cppdefault.o: cppdefault.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- cppdefault.h Makefile
# Note for the stamp targets, we run the program `true' instead of
# having an empty command (nothing following the semicolon).
@@ -4246,11 +2668,6 @@ s-iov: build/gcov-iov$(build_exeext) $(BASEVER) $(DEVPHASE)
$(SHELL) $(srcdir)/../move-if-change tmp-gcov-iov.h gcov-iov.h
$(STAMP) s-iov
-gcov.o: gcov.c gcov-io.c $(GCOV_IO_H) intl.h $(SYSTEM_H) coretypes.h $(TM_H) \
- $(CONFIG_H) version.h $(DIAGNOSTIC_H)
-gcov-dump.o: gcov-dump.c gcov-io.c $(GCOV_IO_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(CONFIG_H) version.h intl.h $(DIAGNOSTIC_H)
-
GCOV_OBJS = gcov.o
gcov$(exeext): $(GCOV_OBJS) $(LIBDEPS)
+$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) $(GCOV_OBJS) $(LIBS) -o $@
@@ -4670,7 +3087,7 @@ gpl.pod: gpl_v3.texi
mostlyclean: lang.mostlyclean
-rm -f $(MOSTLYCLEANFILES)
- -rm -f *$(objext)
+ -rm -f *$(objext) c-family/*$(objext)
-rm -f *$(coverageexts)
# Delete build programs
-rm -f build/*
@@ -5763,3 +4180,17 @@ upgrade-warmelt: melt-build-settings.sh melt-build-param.sh $(srcdir)/melt-buil
## end of MELT specific additions
+#^L
+
+# 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/gcc/acinclude.m4 b/gcc/acinclude.m4
index e68be77f510..6798d6fbc6a 100644
--- a/gcc/acinclude.m4
+++ b/gcc/acinclude.m4
@@ -444,8 +444,16 @@ AC_DEFUN([gcc_GAS_FLAGS],
[AC_CACHE_CHECK([assembler flags], gcc_cv_as_flags,
[ case "$target" in
i[[34567]]86-*-linux*)
- dnl Always pass --32 to ia32 Linux assembler.
- gcc_cv_as_flags="--32"
+ 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.
diff --git a/gcc/aclocal.m4 b/gcc/aclocal.m4
index 3fe609788b7..81db68aa2e1 100644
--- a/gcc/aclocal.m4
+++ b/gcc/aclocal.m4
@@ -1,4 +1,4 @@
-# generated automatically by aclocal 1.13.3 -*- Autoconf -*-
+# generated automatically by aclocal 1.14 -*- Autoconf -*-
# Copyright (C) 1996-2013 Free Software Foundation, Inc.
@@ -12,97 +12,19 @@
# PARTICULAR PURPOSE.
m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])])
-# AM_AUX_DIR_EXPAND -*- Autoconf -*-
-
-# Copyright (C) 2001-2013 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.
-
-# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
-# $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to
-# '$srcdir', '$srcdir/..', or '$srcdir/../..'.
-#
-# Of course, Automake must honor this variable whenever it calls a
-# tool from the auxiliary directory. The problem is that $srcdir (and
-# therefore $ac_aux_dir as well) can be either absolute or relative,
-# depending on how configure is run. This is pretty annoying, since
-# it makes $ac_aux_dir quite unusable in subdirectories: in the top
-# source directory, any form will work fine, but in subdirectories a
-# relative path needs to be adjusted first.
-#
-# $ac_aux_dir/missing
-# fails when called from a subdirectory if $ac_aux_dir is relative
-# $top_srcdir/$ac_aux_dir/missing
-# fails if $ac_aux_dir is absolute,
-# fails when called from a subdirectory in a VPATH build with
-# a relative $ac_aux_dir
-#
-# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
-# are both prefixed by $srcdir. In an in-source build this is usually
-# harmless because $srcdir is '.', but things will broke when you
-# start a VPATH build or use an absolute $srcdir.
-#
-# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
-# iff we strip the leading $srcdir from $ac_aux_dir. That would be:
-# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
-# and then we would define $MISSING as
-# MISSING="\${SHELL} $am_aux_dir/missing"
-# This will work as long as MISSING is not called from configure, because
-# unfortunately $(top_srcdir) has no meaning in configure.
-# However there are other variables, like CC, which are often used in
-# configure, and could therefore not use this "fixed" $ac_aux_dir.
-#
-# Another solution, used here, is to always expand $ac_aux_dir to an
-# absolute PATH. The drawback is that using absolute paths prevent a
-# configured tree to be moved without reconfiguration.
-
-AC_DEFUN([AM_AUX_DIR_EXPAND],
-[dnl Rely on autoconf to set up CDPATH properly.
-AC_PREREQ([2.50])dnl
-# expand $ac_aux_dir to an absolute path
-am_aux_dir=`cd $ac_aux_dir && pwd`
-])
-
-# Copyright (C) 1999-2013 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.
-
-# AM_PROG_CC_C_O
-# --------------
-# Like AC_PROG_CC_C_O, but changed for automake.
-AC_DEFUN([AM_PROG_CC_C_O],
-[AC_REQUIRE([AC_PROG_CC_C_O])dnl
-AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
-AC_REQUIRE_AUX_FILE([compile])dnl
-# FIXME: we rely on the cache variable name because
-# there is no other way.
-set dummy $CC
-am_cc=`echo $[2] | sed ['s/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/']`
-eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o
-if test "$am_t" != yes; then
- # Losing compiler, so override with the script.
- # FIXME: It is wrong to rewrite CC.
- # But if we don't then we get into trouble of one sort or another.
- # A longer-term fix would be to have automake use am__CC in this case,
- # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
- CC="$am_aux_dir/compile $CC"
-fi
-dnl Make sure AC_PROG_CC is never called again, or it will override our
-dnl setting of CC.
-m4_define([AC_PROG_CC],
- [m4_fatal([AC_PROG_CC cannot be called after AM_PROG_CC_C_O])])
-])
-
+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/codeset.m4])
+m4_include([../config/depstand.m4])
m4_include([../config/dfp.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])
@@ -112,9 +34,4 @@ m4_include([../config/picflag.m4])
m4_include([../config/progtest.m4])
m4_include([../config/stdint.m4])
m4_include([../config/warnings.m4])
-m4_include([../libtool.m4])
-m4_include([../ltoptions.m4])
-m4_include([../ltsugar.m4])
-m4_include([../ltversion.m4])
-m4_include([../lt~obsolete.m4])
m4_include([acinclude.m4])
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index 6b0ba092134..a5c9456e4c5 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,3 +1,2455 @@
+2013-11-11 Tristan Gingold <gingold@adacore.com>
+ Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/utils2.c (gnat_build_constructor): Also set the flag
+ CONSTRUCTOR_NO_CLEARING on the constructor.
+
+2013-10-30 Sharad Singhai <singhai@google.com>
+
+ * gnat_ugn.texi: Remove option description for PR middle-end/58134.
+
+2013-10-29 David Malcolm <dmalcolm@redhat.com>
+
+ * gcc-interface/trans.c (finalize_nrv): Update for conversion of
+ symtab types to a true class hierarchy.
+ * gcc-interface/utils.c (gnat_write_global_declarations): Likewise.
+
+2013-10-28 Trevor Saunders <tsaunders@mozilla.com>
+
+ * gcc-interface/decl.c (components_to_record): Adjust stack vector.
+
+2013-10-24 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * gcc-interface/Make-lang.in (ADA_DEPS): Fix quoting.
+
+2013-10-19 Thomas Quinot <quinot@adacore.com>
+
+ * gcc-interface/Makefile.in: Use canonical absolute path to refer to
+ the top source directory and to the libgcc subidrectories.
+
+2013-10-19 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/utils.c (scale_by_factor_of): New function.
+ (rest_of_record_type_compilation): Use scale_by_factor_of in order to
+ scale the original offset for both rounding cases; in the second case,
+ take into accout the addend to compute the alignment. Tidy up.
+
+2013-10-19 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/cuintp.c: Remove useless include directives.
+ (build_cst_from_int): Use standard predicate.
+ (UI_To_gnu): Simplify.
+ (UI_From_gnu): Fix formatting.
+ * gcc-interface/trans.c (post_error): Likewise.
+ (post_error_ne): Likewise.
+
+2013-10-19 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/utils.c (gnat_set_type_context): New function.
+ (gnat_pushdecl): Use it to set the context of the type.
+
+2013-10-17 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * sem_prag.adb (Check_Dependency_Clause):
+ Recognize the scenario where successful clause matching has
+ depleted the available refinement items and the clause to match
+ technically refines to null => null.
+
+2013-10-17 Tristan Gingold <gingold@adacore.com>
+
+ * exp_prag.adb (Expand_Pragma_Import_Or_Interface): Specify
+ External_Name instead of Link_Name for the RTTI declaration.
+
+2013-10-17 Robert Dewar <dewar@adacore.com>
+
+ * sem_prag.adb (Record_Possible_Body_Reference): Fix test for
+ being in body.
+ (Add_Constituent): Merged into Check_Refined_Global_Item.
+ (Check_Matching_Constituent): A constituent that has the proper Part_Of
+ option and comes from a private child or a sibling is now collected.
+ (Check_Matching_Modes): Merged into Check_Refined_Global_Item.
+ (Check_Refined_Global_Item): Code cleanup.
+ (Collect_Constituent): New routine.
+ (Inconsistent_Mode_Error): Moved out from Check_Matching_Modes.
+
+2013-10-17 Ed Schonberg <schonberg@adacore.com>
+
+ * freeze.adb (Check_Current_Instance, Process): Add RM reference
+ and mention immutably limited types, when the current instance
+ is illegal in Ada 2012.
+
+2013-10-17 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_warn.adb (Check_Unused_Withs): If the main unit is a
+ subunit, apply the check to the units mentioned in its context
+ only. This provides additional warnings on with_clauses that
+ are superfluous.
+
+2013-10-17 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * sem_ch3.adb (Analyze_Declarations): Emit an
+ error message concerning state refinement when the spec defines at
+ least one non-null abstract state and the body's SPARK mode is On.
+ (Requires_State_Refinement): New routine.
+
+2013-10-17 Robert Dewar <dewar@adacore.com>
+
+ * sem_ch7.ads: Comment fixes.
+
+2013-10-17 Robert Dewar <dewar@adacore.com>
+
+ * sem_ch7.adb (Analyze_Package_Specification): Remove circuit
+ for ensuring that a package spec requires a body for some other
+ reason than that it contains the declaration of an abstract state.
+
+2013-10-17 Tristan Gingold <gingold@adacore.com>
+
+ * exp_ch11.adb (Expand_N_Raise_Expression): Fix call of
+ Possible_Local_Raise.
+
+2013-10-17 Thomas Quinot <quinot@adacore.com>
+
+ * exp_pakd.adb (Expand_Bit_Packed_Element_Set): Unchecked
+ conversion of Or_Rhs to Etype of New_Rhs is required only when
+ the latter is the result of a byte swap operation.
+
+2013-10-17 Thomas Quinot <quinot@adacore.com>
+
+ * exp_dist.adb (Build_To_Any_Function): For a type with opaque
+ representation that is not transmitted as an unconstrained value,
+ use 'Write, not 'Output, to generate the opaque representation.
+
+2013-10-17 Yannick Moy <moy@adacore.com>
+
+ * sem_res.adb (Resolve_Short_Circuit): Only
+ generate expression-with-action when full expansion is set.
+
+2013-10-17 Yannick Moy <moy@adacore.com>
+
+ * debug.adb Remove obsolete comment.
+
+2013-10-17 Thomas Quinot <quinot@adacore.com>
+
+ * exp_ch4.adb (Process_Transient_Object.Find_Enclosing_Contexts):
+ Avoid late insertion when expanding an expression with action
+ nested within a transient block; Do not inconditionally generate
+ a finalization call if the generated object is from a specific
+ branch of a conditional expression.
+
+2013-10-17 Pascal Obry <obry@adacore.com>
+
+ * g-arrspl.adb: Ensure Finalize call is idempotent.
+ * g-arrspl.adb (Finalize): Makes the call idempotent.
+
+2013-10-17 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * sem_prag.adb (Is_Matching_Input): Account
+ for the case where a state with a null refinement appears as
+ the last input of a refinement clause.
+
+2013-10-17 Robert Dewar <dewar@adacore.com>
+
+ * sem_aux.ads, sem_aux.adb: Minor reformatting.
+
+2013-10-17 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * aspects.adb, aspects.ads, sem_prag.ads: Remove all entries
+ for Refined_Pre from the various tables.
+ * par-prag.adb: Remove the entry for Refined_Pre from the list
+ of pragmas not needing special processing by the parser.
+ * sem_ch13.adb (Analyze_Aspect_Specifications):
+ Remove the processing for aspect Refined_Pre.
+ (Check_Aspect_At_Freeze_Point): Remove the entry for aspect
+ Refined_Pre.
+ * sem_prag.adb (Analyze_Pragma): Refined_Pre is no longer a
+ valid assertion kind. Remove the analysis of pragma Refined_Pre.
+ (Analyze_Refined_Pragma): Update the comment on usage.
+ (Find_Related_Subprogram_Or_Body): Update the comment on
+ usage. Pragma Refined_Pre is no longer processed by this routine.
+ (Is_Valid_Assertion_Kind): Refined_Pre is no longer a valid
+ assertion kind.
+ * snames.ads-tmpl: Remove predefined name Refined_Pre. Remove
+ the pragma id for Refined_Pre.
+
+2013-10-17 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * exp_util.adb, exp_util.ads (Entity_Of): Moved to Sem_Util.
+ * sem_prag.adb (Analyze_Global_In_Decl_List): Mark a null
+ item list as being analyzed.
+ (Analyze_Global_List): Mark a
+ null global list and multiple global items as being analyzed.
+ (Analyze_Input_Item): Check the unit that defines the input
+ variable or state, not the reference to it.
+ * sem_util.ads, sem_util.adb (Entity_Of): Moved from Exp_Util. Ensure
+ that the input has an entity.
+
+2013-10-17 Thomas Quinot <quinot@adacore.com>
+
+ * exp_util.adb (Get_Current_Value_Condition,
+ Set_Current_Value_Condition): Handle the case of expressions
+ with actions * exp_util.adb (Insert_Actions): Handle the case
+ of an expression with actions whose Actions list is empty.
+ * exp_util.adb (Remove_Side_Effects.Side_Effect_Free): An
+ expression with actions that has no Actions and whose Expression
+ is side effect free is itself side effect free.
+ * exp_util.adb (Remove_Side_Effects): Do not set an incorrect etype on
+ temporary 'R' (Def_Id), which is in general an access to Exp_Type, not
+ an Exp_Type.
+ * sem_res.adb (Resolve): For an expression with
+ actions, resolve the expression early. * sem_res.adb
+ (Resolve_Expression_With_Actions): Rewrite an expression with
+ actions whose value is compile time known and which has no
+ actions into just its expression, so that its constant value is
+ available downstream.
+ * sem_res.adb (Resolve_Short_Circuit):
+ Wrap the left operand in an expression with actions to contain
+ any required finalization actions.
+ * exp_ch4.adb (Expand_Expression_With_Actions): For an
+ expression with actions returning a Boolean expression, ensure
+ any finalization action is kept within the Actions list.
+ * sem_warn.adb (Check_References, Check_Unset_Reference): add
+ missing circuitry to handle expressions with actions.
+ * checks.adb (Ensure_Valid): For an expression with actions,
+ insert the validity check on the Expression.
+ * sem_ch13.adb (Build_Static_Predicate.Get_RList): An expression
+ with actions that has a non-empty Actions list is not static. An
+ expression with actions that has an empty Actions list has the
+ static ranges of its Expression.
+ * sem_util.adb (Has_No_Obvious_Side_Effects): An expression with
+ actions with an empty Actions list has no obvious side effects
+ if its Expression itsekf has no obvious side effects.
+
+2013-10-17 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_aux.ads, sem_aux.adb (Is_Immutably_Limited_Type): Make
+ predicate compatible with Ada 2012 definition
+ (Is_Limited_View): New name for previous version of
+ Is_Immutably_Limited_Type. Predicate is true for an untagged
+ record type with a limited component.
+ * exp_ch7.adb, exp_ch6.adb, exp_ch4.adb, exp_ch3.adb, exp_aggr.adb,
+ sem_util.adb, sem_res.adb, sem_prag.adb, sem_attr.adb, sem_ch8.adb,
+ sem_ch6.adb, sem_ch3.adb, exp_util.adb: Use Is_Limited_View
+ * freeze.adb Use Is_Immutably_Limited_Type to check the legality
+ of references to the current instance, Is_Limited_View otherwise.
+
+2013-10-17 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * sem_ch13.adb (Analyze_Aspect_Specifications): Flag aspect
+ Refined_Pre as not supported.
+ * sem_prag.adb (Analyze_Pragma): Ignore pragma Refined_Pre.
+
+2013-10-17 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch12.adb (Validated_Access_Subprogram_Instance): According
+ to AI05-288, actuals for access_to_subprograms must be subtype
+ conformant with the generic formal. Previous to AI05-288
+ only mode conformance was required, but the AI is a binding
+ interpretation that applies to previous versions of the language,
+
+2013-10-17 Robert Dewar <dewar@adacore.com>
+
+ * gnat_ugn.texi: Minor text correction.
+ * ug_words: Add entry for -gnateu /IGNORE_UNRECOGNIZED.
+ * vms_data.ads: Add /IGNORE_UNRECOGNIZED for -gnateu.
+
+2013-10-17 Tristan Gingold <gingold@adacore.com>
+
+ * impunit.adb (Non_Imp_File_Names_95): Add g-cppexc.
+
+2013-10-17 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * sem_prag.adb (Analyze_Constituent): Move the check
+ concerning option Part_Of to routine Check_Matching_Constituent.
+ (Check_Matching_Constituent): Verify that an abstract state
+ that acts as a constituent has the proper Part_Of option in
+ its aspect/pragma Abstract_State. Account for the case when a
+ constituent comes from a private child or private sibling.
+ * sem_util.ads, sem_util.adb (Is_Child_Or_Sibling): New routine.
+
+2013-10-17 Tristan Gingold <gingold@adacore.com>
+
+ * g-cppexc.adb, g-cppexc.ads: New files.
+ * gcc-interface/Makefile.in: Add g-cppexc when building zcx runtimes.
+
+2013-10-17 Thomas Quinot <quinot@adacore.com>
+
+ * exp_ch7.adb: Minor reformatting.
+
+2013-10-17 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_dim.adb (Process_Minus, Process_Divide): Label dimension
+ expression with standard operator and type, for pretty-printing
+ use.
+
+2013-10-17 Bob Duff <duff@adacore.com>
+
+ * gnat_ugn.texi: Document --pp-new and --pp-old switches.
+
+2013-10-17 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * einfo.adb: Flag 159 is now known as From_Limited_With. Replace
+ all references to attribute From_With_Type with From_Limited_With.
+ (From_With_Type): Renamed to From_Limited_With.
+ (Set_From_With_Type): Renamd to Set_From_Limited_With.
+ * einfo.ads: Remove attribute From_With_Type and occurrences in
+ nodes. Add attribute From_Limited_With along with occurrences
+ in nodes.
+ (From_With_Type): Renamed to From_Limited_With along with pragma Inline.
+ (Set_From_With_Type): Renamed to
+ Set_From_Limited_With along with pragma Inline.
+ * sem_ch7.adb, sem_ch8.adb, sem_ch12.adb, sem_ch13.adb, sem_disp.adb,
+ sem_res.adb, sem_type.adb, sem_util.adb, sem_warn.adb,
+ exp_attr.adb, exp_disp.adb, freeze.adb, itypes.adb, layout.adb,
+ lib-writ.adb, rtsfind.adb, sem_attr.adb, sem_aux.adb, sem_ch3.adb,
+ sem_ch4.adb: Replace all references to attribute From_With_Type
+ with From_Limited_With.
+ * sem_ch6.adb: Replace all references to attribute From_With_Type
+ with From_Limited_With.
+ (Designates_From_With_Type): Renamed to Designates_From_Limited_With.
+ (Process_Formals): Update the call to Designates_From_With_Type.
+ * sem_ch10.adb: Replace all references to attribute From_With_Type
+ with From_Limited_With.
+ (Build_Limited_Views): Reimplemented.
+ * gcc-interface/decl.c Replace all references to attribute
+ From_With_Type with From_Limited_With.
+ (finalize_from_with_types): Renamed to finalize_from_limited_with.
+ * gcc-interface/gigi.h (finalize_from_with_types): Renamed to
+ finalize_from_limited_with.
+ * gcc-interface/trans.c: Replace all references to attribute
+ From_With_Type with From_Limited_With.
+ (Compilation_Unit_to_gnu): Update the call to finalize_from_with_types.
+
+2013-10-17 Pascal Obry <obry@adacore.com>
+
+ * projects.texi: Update VCS_Kind documentation.
+
+2013-10-17 Matthew Heaney <heaney@adacore.com>
+
+ * a-convec.adb, a-coinve.adb, a-cobove.adb (Insert, Insert_Space):
+ Inspect value range before converting type.
+
+2013-10-17 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * sem_prag.adb (Analyze_Pragma): Flag the use of pragma Refined_Pre as
+ illegal.
+
+2013-10-17 Vincent Celier <celier@adacore.com>
+
+ * gnat_ugn.texi: Remove VMS conversion of -gnatet and -gnateT,
+ now that they are both in ug_words.
+ * ug_words: Update qualifier for -gnatet Add qualifier for -gnateT
+ * vms_data.ads: Update qualifier for -gnatet Add qualifier
+ for -gnateT
+ * projects.texi: Continue to update the project documentation
+ for VMS.
+
+2013-10-17 Robert Dewar <dewar@adacore.com>
+
+ * einfo.ads, einfo.adb (Has_Body_References): New flag.
+ (Body_References): New field.
+ * sem_prag.adb (Record_Possible_Body_Reference): New procedure
+ (Analyze_Input_Output): Call Record_Possible_Body_Reference
+ (Analyze_Global_Item): Call Record_Possible_Body_Reference
+ (Analyze_Refinement_Clause): Output messages if illegal global refs.
+
+2013-10-17 Thomas Quinot <quinot@adacore.com>
+
+ * freeze.adb (Check_Component_Storage_Order): Reject a record or
+ array type that does not have an explicit Scalar_Storage_Order
+ attribute definition if a component of the record, or the
+ elements of the array, have one.
+ * gnat_rm.texi (attribute Scalar_Storage_Order): Document the above
+ rule.
+
+2013-10-17 Vincent Celier <celier@adacore.com>
+
+ * gnat_ugn.texi: Add examples of switches -gnateD, including
+ one where the value is a string.
+ * projects.texi: Do not convert switches in project files to
+ VMS qualifiers.
+
+2013-10-17 Robert Dewar <dewar@adacore.com>
+
+ * sem_prag.adb (Report_Extra_Clauses): Don't complain about
+ refinements with null input since null should be considered to
+ always match.
+
+2013-10-17 Robert Dewar <dewar@adacore.com>
+
+ * gnat_ugn.texi: Document -gnatw.y/-gnatw.Y.
+ * opt.ads (List_Body_Required_Info): New flag.
+ * prep.adb: Minor reformatting.
+ * sem_ch7.adb (Unit_Requires_Body_Info): New
+ procedure (Analyze_Package_Specification): Add call to
+ Unit_Requires_Body_Info.
+ * ug_words: Add entries for -gnatw.y and -gnatw.Y.
+ * usage.adb: Add line for new warning switch -gnatw.y/.Y.
+ * vms_data.ads: Add entry for [NO_]WHY_SPEC_NEEDS_BODY warning
+ qualifier.
+ * warnsw.ads, warnsw.adb: Implement new warning switch -gnatw.y/.Y.
+
+2013-10-17 Yannick Moy <moy@adacore.com>
+
+ * sem_ch8.adb (Find_Direct_Name): Keep track of assignments for
+ renamings in SPARK mode.
+
+2013-10-17 Yannick Moy <moy@adacore.com>
+
+ * exp_spark.adb (Expand_SPARK): Remove special case for NOT IN
+ operation.
+ * sinfo.ads: Add special comment section to describe SPARK mode
+ effect on tree.
+ * exp_spark.ads: Remove comments, moved to sinfo.ads.
+
+2013-10-17 Yannick Moy <moy@adacore.com>
+
+ * exp_ch3.adb (Expand_Freeze_Class_Wide_Type,
+ Expand_Freeze_Class_Wide_Type, Expand_Freeze_Class_Wide_Type):
+ Remove useless special cases.
+ * exp_ch4.adb (Expand_Allocator_Expression, Expand_N_Allocator,
+ Expand_N_Op_Expon): Remove useless special cases.
+ * exp_ch6.adb (Is_Build_In_Place_Function_Call): Disable build-in-place
+ in SPARK mode by testing Full_Expander_Active instead of
+ Expander_Active.
+ (Make_Build_In_Place_Call_In_Allocator): Remove useless special case.
+ * exp_util.adb (Build_Allocate_Deallocate_Proc): Remove
+ useless special case.
+ * sem_eval.adb (Compile_Time_Known_Value): Remove special handling of
+ deferred constant.
+
+2013-10-17 Yannick Moy <moy@adacore.com>
+
+ * gnat_ugn.texi: Document -gnateT and target file format.
+
+2013-10-17 Vincent Celier <celier@adacore.com>
+
+ * prep.adb (Check_Command_Line_Symbol_Definition): Is_A_String is
+ always False, even when the value starts and ends with double quotes.
+
+2013-10-17 Tristan Gingold <gingold@adacore.com>
+
+ * a-exexpr-gcc.adb: Synchronize declarations of other/all others.
+
+2013-10-17 Thomas Quinot <quinot@adacore.com>
+
+ * exp_pakd.adb: Add missing guard protecting Reverse_Storage_Order
+ call.
+ * sem_res.adb: Minor code cleanup: use named parameter association
+ (not positional) for Boolean parameter Sec_Stack in calls to
+ Establish_Transient_Scope.
+
+2013-10-15 Thomas Quinot <quinot@adacore.com>
+
+ * exp_pakd.adb (Expand_Packed_Element_Set,
+ Expand_Packed_Element_Reference): Adjust for the case of packed
+ arrays of reverse-storage-order types.
+
+2013-10-15 Robert Dewar <dewar@adacore.com>
+
+ * sem_prag.adb: Minor reformatting.
+
+2013-10-15 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_attr.adb (Analyze_Attribute_Specification, case
+ To_Address): If the expression is an identifier, do not modify
+ its type; it will be converted when necessary, and the type of
+ the expression must remain consistent with that of the entity
+ for back-end consistency.
+
+2013-10-15 Robert Dewar <dewar@adacore.com>
+
+ * sem_ch7.adb (Unit_Requires_Body): Add flag
+ Ignore_Abstract_State (Analyze_Package_Specification): Enforce
+ rule requiring Elaborate_Body if a non-null abstract state is
+ specified for a library-level package.
+ * sem_ch7.ads (Unit_Requires_Body): Add flag Ignore_Abstract_State.
+
+2013-10-15 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * sem_prag.adb (Analyze_Constituent): When
+ a state acts as a constituent of another state, ensure that
+ the said state has a Part_Of dependency in its corresponding
+ aspect/pragma Abstract_State.
+
+2013-10-15 Robert Dewar <dewar@adacore.com>
+
+ * par-ch4.adb (P_If_expression): Handle redundant ELSE cleanly.
+
+2013-10-15 Thomas Quinot <quinot@adacore.com>
+
+ * atree.ads (New_Copy, Relocate_Node): Improve documentation
+ (note that these subprograms reset Is_Overloaded).
+
+2013-10-15 Thomas Quinot <quinot@adacore.com>
+
+ * checks.adb (Check_Needed): Handle the case where the test in
+ the left operand of the short circuit is wrapped in a qualified
+ expression, type conversion, or expression with actions.
+
+2013-10-15 Thomas Quinot <quinot@adacore.com>
+
+ * sem_type.adb, sem_type.ads (Save_Interps): Also propagate
+ Is_Overloaded to New_N, for consistency.
+
+2013-10-15 Ed Schonberg <schonberg@adacore.com>
+
+ * a-tienau.adb (Put): Use file parameter to query values of
+ current column and line length.
+
+2013-10-15 Robert Dewar <dewar@adacore.com>
+
+ * sem_prag.adb, exp_ch11.adb, a-except-2005.adb, a-except-2005.ads:
+ Minor reformatting.
+
+2013-10-15 Eric Botcazou <ebotcazou@adacore.com>
+
+ * targparm.ads: Fix minor typo in comment.
+
+2013-10-15 Ed Schonberg <schonberg@adacore.com>
+
+ * lib-xref.adb: handle full views that are derived from private
+ types.
+ * sem_util.adb (Build_Elaboration_Entity): Do nothing in ASIS
+ mode: the elaboration entity is not in the source, and plays no
+ role in semantic analysis. Minor reformatting.
+
+2013-10-15 Tristan Gingold <gingold@adacore.com>
+
+ * adaint.c (__gnat_get_executable_load_address): Remove AIX
+ specific code.
+
+2013-10-15 Ed Schonberg <schonberg@adacore.com>
+
+ * exp_aggr.adb (Aggr_Size_OK): Refine criteria to better handle
+ large static aggregates with static record components, to avoid
+ generating a large number of asignments. Conversely, improve
+ handling of aggregates initialized by a single association,
+ which are most efficiently implemented with a loop.
+
+2013-10-15 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * sem_prag.adb (Analyze_Input_Item): Emit an
+ error when the input item comes from the related package.
+
+2013-10-15 Arnaud Charlet <charlet@adacore.com>
+
+ * exp_ch11.adb (Expand_Exception_Handlers): Restrict previous
+ change.
+
+2013-10-14 Tristan Gingold <gingold@adacore.com>
+
+ * gcc-interface/gigi.h (standard_datatypes): Add
+ ADT_set_exception_parameter_decl
+ (set_exception_parameter_decl): New macro.
+ * gcc-interface/trans.c (gigi): Initialize set_exception_parameter_decl.
+ (Exception_Handler_to_gnu_zcx): Initialize the choice parameter.
+ * gcc-interface/trans.c: Synchronize declarations of other/all others
+ between gigi and the runtime.
+
+2013-10-14 Robert Dewar <dewar@adacore.com>
+
+ * exp_attr.adb (Find_Stream_Subprogram): Optimize
+ Storage_Array stream handling.
+ (Find_Stream_Subprogram): Optimize Stream_Element_Array stream handling
+ * rtsfind.ads: Add entry for Stream_Element_Array Add
+ entries for RE_Storage_Array subprograms Add entries for
+ RE_Stream_Element_Array subprograms
+ * s-ststop.ads, s-ststop.adb: Add processing for System.Storage_Array.
+ Add processing for Ada.Stream_Element_Array.
+
+2013-10-14 Tristan Gingold <gingold@adacore.com>
+
+ * a-except-2005.ads, a-except-2005.adb:
+ (Get_Exception_Machine_Occurrence): New function.
+ * raise-gcc.c (__gnat_unwind_exception_size): New constant.
+
+2013-10-14 Robert Dewar <dewar@adacore.com>
+
+ * sem_res.adb: Minor fix to error message text.
+ * errout.ads, erroutc.ads: Minor reformatting.
+ * s-ststop.ads, s-stratt.ads: Clean up documentation of block IO
+ mode for streams.
+ * s-stratt-xdr.adb: Minor comment update.
+
+2013-10-14 Robert Dewar <dewar@adacore.com>
+
+ * sem_aux.adb, sem_aux.ads, sem_prag.adb: Minor reformatting.
+
+2013-10-14 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_res.adb (Resolve_Actuals): Add error message for a
+ subprogram with an in-out parameter when used in a predicate,
+ to clarify subsequent error at the point of call.
+
+2013-10-14 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * sem_prag.adb (Is_Matching_Input): Consume a matching null input.
+
+2013-10-14 Robert Dewar <dewar@adacore.com>
+
+ * freeze.adb (Freeze_Record): Don't give warning about packed
+ and foreign convention.
+
+2013-10-14 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_aux.adb, sem_aux.ads (Package_Specification): New function, to
+ replace the less efficient idiom Specification.
+ (Unit_Declaration_Node (Pack_Id)), which handles library units and
+ child units.
+ * sem_ch3.adb, sem_ch10.adb, sem_prag.adb, sem_ch12.adb, sem_ch6.adb,
+ exp_disp.adb, sem_cat.adb, exp_dist.adb: Use Package_Specification.
+
+2013-10-14 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * exp_attr.adb (Expand_Update_Attribute): Update the call to
+ Process_Range_Update.
+ (Process_Range_Update): Add new formal parameter Typ and associated
+ comment on usage. Add local constant Index_Typ. Add a type conversion
+ as part of the indexed component to ensure that the loop variable
+ corresponds to the index type.
+
+2013-10-14 Tristan Gingold <gingold@adacore.com>
+
+ * a-exexpr-gcc.adb: Adjust comment.
+ (Others_Value, All_Others_Value,
+ Unhandled_Others_Value): Declare as Character to slightly reduce
+ memory footprint.
+
+2013-10-14 Robert Dewar <dewar@adacore.com>
+
+ * freeze.adb (Size_Known): Size is not known for packed record
+ with aliased components
+
+2013-10-14 Robert Dewar <dewar@adacore.com>
+
+ * sem_ch3.adb: Minor fix to error message.
+ * a-exexpr-gcc.adb, sem_util.adb, sem_case.adb, exp_ch11.adb: Minor
+ reformatting.
+
+2013-10-14 Arnaud Charlet <charlet@adacore.com>
+
+ * exp_ch11.adb: Fix typo.
+
+2013-10-14 Thomas Quinot <quinot@adacore.com>
+
+ * exp_util.ads: Minor reformatting.
+
+2013-10-14 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch3.adb (Build_Derived_Record_Type): Reject full views
+ with no explicit discriminant constraints, when the parents of
+ the partial view and the full view are constrained subtypes with
+ different constraints.
+
+2013-10-14 Robert Dewar <dewar@adacore.com>
+
+ * freeze.adb (Freeze_Array_Type): New procedure, abstracts out
+ this code from Freeze.
+ (Freeze_Array_Type): Detect pragma Pack overriding foreign convention
+ (Freeze_Record_Type): Ditto.
+
+2013-10-14 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * sem_prag.adb (Analyze_Dependency_Clause): Add new local variable
+ Non_Null_Output_Seen. Update the call to Analyze_Input_Output.
+ (Analyze_Input_Item): Streamline the detection mechanism of null and
+ non-null items.
+ (Analyze_Input_List): Add new local variable
+ Non_Null_Input_Seen. Update all calls to Analyze_Input_Output.
+ (Analyze_Input_Output): Add new formal parameter Non_Null_Seen
+ and update the related comment on usage. Update the
+ recursive call to itself. Attribute 'Result is now treated
+ as a non-null item. Detect mixes of null and non-null items.
+ (Analyze_Initialization_Item): Streamline the detection mechanism
+ of null and non-null items.
+
+2013-10-14 Vincent Celier <celier@adacore.com>
+
+ * projects.texi: Add documentation for the new project level
+ attribute Library_Rpath_Options.
+
+2013-10-14 Tristan Gingold <gingold@adacore.com>
+
+ * a-exexpr-gcc.adb (Set_Exception_Parameter): New procedure.
+ (Set_Foreign_Occurrence): New procedure, extracted from
+ Setup_Current_Excep.
+ * exp_ch11.adb (Expand_Exception_Handlers): Do not expand choice
+ parameter in case of zcx.
+ * sem_ch11.adb (Analyze_Exception_Handlers): Need debug info
+ for the choice parameter.
+ * raise-gcc.c: Add comments.
+
+2013-10-14 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * aspects.adb: Add an entry in table Canonical_Aspect for
+ Initial_Condition.
+ * aspects.ads: Add entries in tables Aspect_Id, Aspect_Argument,
+ Aspect_Names and Aspect_Delay for Initial_Condition.
+ * einfo.adb (Get_Pragma): Include pragma Initial_Condition to
+ categorization pragmas.
+ * einfo.ads (Get_Pragma): Update comment on usage.
+ * exp_ch7.adb (Expand_N_Package_Body): Add a runtime check to
+ verify the assertion introduced by pragma Initial_Condition.
+ (Expand_N_Package_Declaration): Add a runtime check to
+ verify the assertion introduced by pragma Initial_Condition.
+ (Expand_Pragma_Initial_Condition): New routine.
+ * par-prag: Include pragma Initial_Condition to the list of
+ pragmas that do not require special processing by the parser.
+ * sem_ch3.adb (Analyze_Declarations): Analyze pragma
+ Initial_Condition at the end of the visible declarations.
+ * sem_ch13.adb (Analyze_Aspect_Specifications): Add processing
+ for aspect Initial_Condition.
+ (Check_Aspect_At_Freeze_Point):
+ Aspect Initial_Condition does not need inspection at freezing.
+ * sem_prag.adb (Analyze_Initial_Condition_In_Decl_Part):
+ New routine.
+ (Analyze_Pragma): Update all calls
+ to Check_Declaration_Order. Add processing for pragma
+ Initial_Condition. Initial_Condition is now a valid assertion
+ kind. Add an entry in table Sig_Flags for Initial_Condition.
+ (Check_Declaration_Order): Reimplemented to handle arbitrary
+ pragmas.
+ (Is_Valid_Assertion_Kind): Add an entry for
+ Initial_Condition.
+ * sem_pag.ads (Analyze_Initial_Condition_In_Decl_Part):
+ New routine.
+ * sem_util.adb (Add_Contract_Item): Pragma Initial_Condition
+ can now be associated with a package spec.
+ * sem_util.ads (Add_Contract_Item): Update comment on usage.
+ * sinfo.ads: Update the documentation of node N_Contract
+ * snames.ads-tmpl: Add new predefined name Initial_Condition. Add
+ new pragma id for Initial_Condition.
+
+2013-10-14 Thomas Quinot <quinot@adacore.com>
+
+ * exp_pakd.adb: Minor reformatting.
+
+2013-10-14 Robert Dewar <dewar@adacore.com>
+
+ * exp_prag.adb: Minor reformatting.
+
+2013-10-14 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_case.adb (Check_Against_Predicate): Handle properly an
+ others clause in various cases.
+
+2013-10-14 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * sem_prag.adb (Check_Matching_Constituent): Do
+ not inspect the hidden states if there are no hidden states. This
+ case arises when the constituents are states coming from a
+ private child.
+
+2013-10-14 Doug Rupp <rupp@adacore.com>
+
+ * init.c [ARMEL and VxWorks] (__gnat_map_signal): Re-arm guard
+ page by clearing VALID bit vice setting page protection.
+
+2013-10-14 Arnaud Charlet <charlet@adacore.com>
+
+ * gnat_rm.texi, adaint.c: Fix typo.
+
+2013-10-14 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_util.adb (Is_Variable, In_Protected_Function): In the
+ body of a protected function, the protected object itself is a
+ constant (not just its components).
+
+2013-10-14 Vincent Celier <celier@adacore.com>
+
+ * snames.ads-tmpl: Add new standard name Library_Rpath_Options.
+
+2013-10-14 Tristan Gingold <gingold@adacore.com>
+
+ * sem_prag.adb (Process_Import_Or_Interface): Allow importing
+ of exception using convention Cpp.
+ * exp_prag.adb (Expand_Pragma_Import_Or_Interface): Expand cpp
+ imported exceptions.
+ * raise-gcc.c (is_handled_by): Filter C++ exception occurrences.
+ * gnat_rm.texi: Document how to import C++ exceptions.
+
+2013-10-14 Jose Ruiz <ruiz@adacore.com>
+
+ * sem_ch13.adb (Sem_Ch13.Analyze_Aspect_Specification): For
+ Priority and CPU aspects, when checking, issue a warning only
+ if it is obviously not a main program.
+
+2013-10-14 Tristan Gingold <gingold@adacore.com>
+
+ * adaint.c: Fix condition for AIX. Minor reformatting.
+
+2013-10-14 Robert Dewar <dewar@adacore.com>
+
+ * sem_ch3.adb, sem_prag.adb, prj.ads: Minor reformatting.
+
+2013-10-14 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * sem_prag.adb (Analyze_Depends_In_Decl_Part):
+ Rename Outputs_Seen to All_Outputs_Seen and update all occurrences
+ of the variable.
+ (Analyze_Input_Output): Add an item to
+ All_Inputs_Seen when it is an input or a self-referential output.
+ (Check_Mode): Comment reformatting.
+ (Analyze_Abstract_State): Remove the restriction that an Export state
+ must also have mode Input_Only or Output_Only.
+
+2013-10-14 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * einfo.adb: Flag 263 is now known as Has_Visible_Refinement.
+ (Has_Non_Null_Refinement): New routine.
+ (Has_Null_Refinement): The routine is now synthesized.
+ (Has_Visible_Refinement): New routine.
+ (Set_Has_Visible_Refinement): New routine.
+ (Write_Entity_Flags): Remove the output for
+ Has_Null_Refinement. Add output for Has_Visible_Refinement.
+ * einfo.ads: Update the occurrences of Has_Non_Null_Refinement,
+ Has_Null_Refinement and Has_Visible_Refinement in entities.
+ (Has_Non_Null_Refinement): New synthesized attribute.
+ (Has_Null_Refinement): This attribute is now synthesized.
+ (Has_Visible_Refinement): New routine with corresponding
+ pragma Inline.
+ (Set_Has_Visible_Refinement): New routine with corresponding pragma
+ Inline.
+ * sem_ch3.adb (Analyze_Declarations): Add new local
+ variable In_Package_Body. Remove state refinements from
+ visibility at the end of the package body declarations.
+ (Remove_Visible_Refinements): New routine.
+ * sem_prag.adb (Analyze_Constituent): Collect a null
+ constituent and mark the state as having visible refinement.
+ (Analyze_Global_Item): Use attribute Has_Visible_Refinement to
+ detect a state with visible refinement.
+ (Analyze_Input_Output): Use attribute Has_Visible_Refinement to detect
+ a state with visible refinement.
+ (Check_Dependency_Clause): Use attribute Has_Non_Null_Refinement rather
+ than checking the contents of list Refinement_Constituents.
+ (Check_In_Out_States): Use attribute Has_Non_Null_Refinement rather
+ than checking the contents of list Refinement_Constituents.
+ (Check_Input_States): Use attribute Has_Non_Null_Refinement rather
+ than checking the contents of list Refinement_Constituents.
+ (Check_Matching_Constituent): Mark a state as having visible refinement.
+ (Check_Output_States): Use attribute Has_Non_Null_Refinement rather than
+ checking the contents of list Refinement_Constituents.
+ (Check_Refined_Global_Item): Use attribute Has_Visible_Refinement
+ to detect a state with visible refinement.
+ (Is_Matching_Input): Use attribute Has_Non_Null_Refinement rather than
+ checking the contents of list Refinement_Constituents.
+ * sem_util.adb (Is_Refined_State): Use attribute
+ Has_Visible_Refinement to detect a state with visible refinement.
+
+2013-10-14 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * sem_prag.adb (Check_Mode): Do not emit an
+ error when inspecting a self referencial output item of an
+ unconstrained type.
+
+2013-10-14 Tristan Gingold <gingold@adacore.com>
+
+ * exp_prag.adb (Expand_Pragma_Import_Export_Exception): Fix
+ target type for code of VMS imported exception.
+ * init.c: Replace Exception_Code by void *.
+ * s-vmexta.adb (Hash, Base_Code_In): Adjust code after changing
+ the type of Exception_Code.
+
+2013-10-14 Vincent Celier <celier@adacore.com>
+
+ * prj.ads: Minor comment updates.
+ * prj-attr.adb: New attribute Library_Rpath_Options.
+
+2013-10-14 Robert Dewar <dewar@adacore.com>
+
+ * gnat_rm.texi: Library_Level attribute now applies to an
+ entity name.
+ * sem_attr.adb (Analyze_Attribute, case Library_Level): Prefix
+ is now an entity name.
+
+2013-10-14 Jose Ruiz <ruiz@adacore.com>
+
+ * sem_ch13.adb (Analyze_Aspect_Specification): For
+ Priority and CPU aspects in subprograms, the expression in the
+ aspect is analyzed and exported.
+
+2013-10-14 Robert Dewar <dewar@adacore.com>
+
+ * s-valuti.adb, prep.adb, scng.adb, errout.adb: Minor reformatting.
+
+2013-10-14 Eric Botcazou <ebotcazou@adacore.com>
+
+ * adaint.c: Further disable __gnat_get_executable_load_address
+ for Linux.
+
+2013-10-14 Vincent Celier <celier@adacore.com>
+
+ * gnat_ugn.texi: Add documentation for comparing symbols to
+ integers in preprocessing expressions.
+
+2013-10-14 Jose Ruiz <ruiz@adacore.com>
+
+ * sem_prag.adb (Analyze_Aspect_Specification): For
+ Priority and CPU aspects in subprograms, the expression in the
+ aspect is analyzed and exported.
+ (Analyze_Pragma): When having a Priority pragma in the
+ main subprogram, load a unit that will force the initialization
+ of the tasking run time, which is needed for setting the required
+ priority.
+
+2013-10-14 Vincent Celier <celier@adacore.com>
+
+ * prj-nmsc.adb (Check_Interfaces): Put in Other_Interfaces all
+ non Ada interface files.
+ * prj.ads (Project_Data): New component Other_Interfaces.
+
+2013-10-14 Arnaud Charlet <charlet@adacore.com>
+
+ * gcc-interface/Makefile.in: Target pairs clean ups.
+
+2013-10-14 Vincent Celier <celier@adacore.com>
+
+ * errout.adb (Write_Error_Summary): Do not output the number
+ of lines when Main_Source_File is unknown.
+ (Output_Messages): Do not write the header when Main_Source_File is
+ unknown.
+
+2013-10-14 Vincent Celier <celier@adacore.com>
+
+ * prep.adb (Expression): Accept terms of the form 'symbol <relop>
+ integer", where relop is =, <, <=, > or >=.
+ (Parse_Def_File): Accept literal integer values.
+ * gcc-interface/Make-lang.in: Add s-valint.o, s-valuns.o and
+ s-valuti.o to the compiler object files.
+
+2013-10-14 Robert Dewar <dewar@adacore.com>
+
+ * exp_prag.adb, exp_ch11.adb, s-exctab.adb: Minor reformatting.
+ * usage.adb: Add line for -gnateu switch.
+
+2013-10-14 Vincent Celier <celier@adacore.com>
+
+ * lib-writ.ads: Add comments to indicate that a path name in
+ D lines may be quoted if the path name includes directories
+ with spaces.
+
+2013-10-14 Robert Dewar <dewar@adacore.com>
+
+ * debug.adb: Document -gnatd.E.
+ * gnat1drv.adb (Adjust_Global_Switches): Set Error_To_Warning
+ if -gnatd.E set.
+ * opt.ads (Error_To_Warning): New switch.
+ * osint.adb: Minor reformatting.
+ * sem_warn.adb (Warn_On_Overlapping_Actuals): Overlap is error
+ in some cases in Ada 2012 mode (unless Error_To_Warning) is set.
+ * sem_warn.ads (Warn_On_Overlapping_Actuals): Document error
+ in Ada 2012 mode.
+
+2013-10-14 Tristan Gingold <gingold@adacore.com>
+
+ * cstand.adb: Add a comment for Standard_Exception_Type.
+
+2013-10-14 Ed Schonberg <schonberg@adacore.com>
+
+ * exp_ch4.adb (Process_Transient_Object): If a transient scope
+ has already been created, use the corresponding Node_To_Be_Wrapped
+ as the insertion point for the controlled actions.
+
+2013-10-14 Tristan Gingold <gingold@adacore.com>
+
+ * cstand.adb (Create_Standard): Change Import_Code component
+ of Standard_Exception_Type to Foreign_Data. Its type is now
+ Standard_A_Char (access to character).
+ * exp_prag.adb (Expand_Pragma_Import_Export_Exception): Adjust
+ definition of Code to match the type of Foreign_Data.
+ * s-stalib.ads (Exception_Data): Replace Import_Code by Foreign_Data
+ Change the definition of standard predefined exceptions.
+ (Exception_Code): Remove.
+ * raise.h (Exception_Code): Remove (Exception_Data): Replace
+ Import_Code field by Foreign_Data.
+ * rtsfind.ads (RE_Exception_Code): Remove
+ (RE_Import_Address): Add.
+ * a-exexpr-gcc.adb (Import_Code_For): Replaced by Foreign_Data_For.
+ * exp_ch11.adb (Expand_N_Exception_Declaration): Associate null
+ to Foreign_Data component.
+ * raise-gcc.c (Import_Code_For): Replaced by Foreign_Data_For.
+ (is_handled_by): Add comments. Use replaced function. Change
+ condition so that an Ada occurrence is never handled by
+ Foreign_Exception.
+ * s-exctab.adb (Internal_Exception): Associate Null_Address to
+ Foreign_Data component.
+ * s-vmexta.adb, s-vmexta.ads (Exception_Code): Declare Replace
+ SSL.Exception_Code by Exception_Code.
+
+2013-10-14 Robert Dewar <dewar@adacore.com>
+
+ * gnat_ugn.texi: Document -gnateu switch.
+ * opt.ads (Ignore_Unrecognized_VWY_Switches): New switch.
+ * stylesw.adb: Ignore unrecognized switch if
+ Ignore_Unrecognized_VWY_Switches set.
+ * switch-c.adb: Implement -gnateu (sets
+ Ignore_Unrecognized_VWY_Switches).
+ * validsw.adb: Ignore unrecognized switch if
+ Ignore_Unrecognized_VWY_Switches set.
+ * warnsw.adb: Ignore unrecognized switch if
+ Ignore_Unrecognized_VWY_Switches set.
+
+2013-10-14 Robert Dewar <dewar@adacore.com>
+
+ * exp_prag.adb, sem_prag.adb, a-exexda.adb, s-vmexta.ads: Minor
+ reformatting.
+
+2013-10-14 Vincent Celier <celier@adacore.com>
+
+ * ali.adb (Get_File_Name): New Boolean parameter May_Be_Quoted,
+ defaulted to False. Calls Get_Name with May_Be_Quoted.
+ (Get_Name): New Boolean parameter May_Be_Quoted, defaulted to
+ False. If May_Be_Quoted is True and first non blank charater is
+ '"', unquote the name.
+ (Scan_ALI): For the file/path name on the D line, call Get_File_Name
+ with May_Be_Quoted = True, as it may have been quoted.
+ * lib-util.adb, lib-util.ads (Write_Info_Name_May_Be_Quoted): New
+ procedure to write file/path names that may contain spaces and if they
+ do are quoted.
+ * lib-writ.adb (Write_ALI): Use new procedure
+ Write_Info_Name_May_Be_Quoted to write file/path names on D lines.
+
+2013-10-14 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * sem_prag.adb (Analyze_Depends_In_Decl_Part,
+ Analyze_Global_In_Decl_Part,
+ Analyze_Pre_Post_Condition_In_Decl_Part): Install the subprogram
+ and its formals only when it is not already installed.
+ * sem_util.adb (Is_Refined_State): A state is refined when it
+ has a non-empty list of constituents.
+
+2013-10-14 Tristan Gingold <gingold@adacore.com>
+
+ * adaint.c: Disable __gnat_get_executable_load_address for linux.
+ * exp_prag.adb: Add comment in Expand_Pragma_Import_Export_Exception.
+
+2013-10-14 Tristan Gingold <gingold@adacore.com>
+
+ * s-vmexta.ads: Add comments.
+
+2013-10-14 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * sem_ch6.adb (Analyze_Subprogram_Body_Contract): Add processing
+ for pragma Refined_State.
+ * sem_ch13.adb (Analyze_Aspect_Specifications): Add processing
+ for aspect Refined_Depends.
+ * sem_prag.adb (Analyze_Contract_Cases_In_Decl_Part):
+ Use Find_Related_Subprogram_Or_Body to find the related
+ context. Use the current scope when determining whether to
+ ensure proper visibility.
+ (Analyze_Depends_In_Decl_Part):
+ Add local variable Spec_Id. Update the comment on usage of
+ Subp_Id. Use Find_Related_Subprogram_Or_Body to find the
+ related context. Extract the corresponding spec of the body
+ (if any). Use the current scope when determining when to
+ ensure proper visibility.
+ (Analyze_Global_In_Decl_Part):
+ Add local variable Spec_Id. Update the comment on usage of
+ Subp_Id. Use Find_Related_Subprogram_Or_Body to find the
+ related context. Extract the corresponding spec of the body
+ (if any). Use the current scope when determining when to
+ ensure proper visibility.
+ (Analyze_Global_Item): Use the
+ entity of the subprogram spec when performing formal parameter
+ checks. Perform state-related checks.
+ (Analyze_Input_Output):
+ Use Is_Attribute_Result to detect 'Result. Query the
+ entity of a subprogram spec when verifying the prefix of
+ 'Result. Perform state-related checks. (Analyze_Pragma):
+ Merge the analysis of Refined_Depends and Refined_Global.
+ (Analyze_Refined_Depends_In_Decl_Part): Provide implemenation.
+ (Analyze_Refined_Global_In_Decl_Part): Move state-related checks
+ to the body of Analyze_Global_In_Decl_Part. Rename local constant
+ List to Items. (Analyze_Refined_Pragma): Remove circuitry to
+ find the proper context, use Find_Related_Subprogram_Or_Body
+ instead.
+ (Check_Function_Return): Query the entity of
+ the subprogram spec when verifying the use of 'Result.
+ (Check_In_Out_States, Check_Input_States, Check_Output_States):
+ Avoid using Has_Null_Refinement to detect a state with
+ a non-null refinement, use the Refinement_Constituents
+ list instead.
+ (Check_Matching_Constituent): Remove initialization code.
+ (Check_Mode_Restriction_In_Function): Use the entity of the subprogram
+ spec when verifying mode usage in functions.
+ (Collect_Global_Items): New routine.
+ (Collect_Subprogram_Inputs_Outputs): Add local
+ variable Spec_Id. Add circuitry for bodies-as-specs. Use
+ pragma Refined_Global when collecting for a body.
+ (Create_Or_Modify_Clause): Use the location of the
+ clause. Rename local variable Clause to New_Clause to avoid
+ confusion and update all occurrences. Use Is_Attribute_Result
+ to detect 'Result.
+ (Find_Related_Subprogram): Removed.
+ (Find_Related_Subprogram_Or_Body): New routine.
+ (Is_Part_Of): Move routine to top level.
+ (Normalize_Clause): Update the
+ comment on usage. The routine can now normalize a clause with
+ multiple outputs by splitting it.
+ (Collect_Global_Items):
+ Rename local constant List to Items. Remove the check for
+ a null list.
+ (Requires_Profile_Installation): Removed.
+ (Split_Multiple_Outputs): New routine.
+ * sem_prag.ads: Update the comments on usage of various
+ pragma-related analysis routines.
+ * sem_util.adb (Contains_Refined_State): The routine can now
+ process pragma [Refined_]Depends.
+ (Has_Refined_State): Removed.
+ (Has_State_In_Dependency): New routine.
+ (Has_State_In_Global): New routine.
+ (Is_Attribute_Result): New routine.
+ * sem_util.ads (Is_Attribute_Result): New routine.
+
+2013-10-14 Emmanuel Briot <briot@adacore.com>
+
+ * s-regpat.adb (Compile): Fix finalization of the automaton
+ when its size was automatically computed to be exactly 1000 bytes.
+
+2013-10-14 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch3.adb (Complete_Private_Subtype): If the full view of
+ the base type is constrained, the full view of the subtype is
+ known to be constrained as well.
+
+2013-10-14 Vincent Celier <celier@adacore.com>
+
+ * projects.texi: Add documentation for new attributes of package
+ Clean: Artifacts_In_Object_Dir and Artifacts_In_Exec_Dir.
+
+2013-10-14 Tristan Gingold <gingold@adacore.com>
+
+ * adaint.c, adaint.h (__gnat_get_executable_load_address):
+ New function.
+ * a-exexda.adb (Append_Info_Basic_Exception_Traceback): Add
+ executable load address (Basic_Exception_Tback_Maxlength): Adjust.
+
+2013-10-14 Vincent Celier <celier@adacore.com>
+
+ * prj-attr.adb: New attributes in package Clean:
+ Artifacts_In_Exec_Dir, Artifacts_In_Object_Dir.
+ * prj-nmsc.adb (Process_Clean (Attributes)): New
+ procedure to process attributes Artifacts_In_Exec_Dir and
+ Artifacts_In_Object_Dir in package Clean.
+ * prj.ads (Project_Configuration): New components
+ Artifacts_In_Exec_Dir and Artifacts_In_Object_Dir.
+ * snames.ads-tmpl: New standard names Artifacts_In_Exec_Dir and
+ Artifacts_In_Object_Dir used only by gprclean.
+
+2013-10-14 Robert Dewar <dewar@adacore.com>
+
+ * exp_attr.adb (Expand_N_Attribute_Reference): Add error
+ entry for Library_Level attribute (which should not survive
+ to expansion)
+ * gnat_rm.texi: Document attribute Library_Level
+ * sem_attr.adb (Analyze_Attribute, case Library_Level): Implement
+ this new attribute (Set_Boolean_Result): Replaces Set_Result
+ (Check_Standard_Prefix): Document that Check_E0 is called
+ (Check_System_Prefix): New procedure
+ * snames.ads-tmpl: Add entry for Library_Level attribute
+
+2013-10-14 Robert Dewar <dewar@adacore.com>
+
+ * exp_ch6.adb, sinfo.ads: Minor reformatting.
+ * checks.adb (Overlap_Check): Use identifier casing in messages.
+
+2013-10-14 Robert Dewar <dewar@adacore.com>
+
+ * einfo.ads, einfo.adb (Default_Aspect_Component_Value): Is on base type
+ only.
+ * exp_aggr.adb (Expand_Array_Aggregate): Handle proper
+ initialization of <> component.
+ * exp_ch3.adb, exp_tss.adb: Minor reformatting
+ * sem_ch13.adb (Default_Aspect_Component_Value, Default_Aspect_Value):
+ Is on base type only.
+ * sinfo.ads: Minor comment revision.
+
+2013-10-14 Robert Dewar <dewar@adacore.com>
+
+ * g-decstr.adb (Decode_Wide_Wide_Character): Fix failure
+ to detect invalid sequences where longer than necessary
+ sequences are used for encoding.
+ (Validate_Wide_Character):
+ Call Decode_Wide_Character to get the above validations.
+ (Validate_Wide_Wide_Character): Same fix
+ * g-decstr.ads: Add documentation making it clear that the UTF-8
+ implementation here recognizes all valid UTF-8 sequences, rather
+ than the well-formed subset corresponding to characters defined
+ in Unicode.
+ (Next_Wide_Character): Remove comment about this
+ being more efficient than Decode_Wide_Character (because this
+ no longer the case).
+ (Prev_Wide_Character): Add note that valid encoding is assumed.
+
+2013-10-14 Robert Dewar <dewar@adacore.com>
+
+ * a-wichha.adb (Character_Set_Version): New function.
+ * a-wichha.ads: Remove comments for pragma Pure (final RM has
+ this).
+ (Character_Set_Version): New function.
+ * gnat_rm.texi: Update doc.
+
+2013-10-14 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * einfo.adb: Flag263 is now known as Has_Null_Refinement.
+ (Has_Null_Refinement): New routine.
+ (Set_Has_Null_Refinement): New routine.
+ (Write_Entity_Flags): Output the status of flag
+ Has_Null_Refinement.
+ * einfo.ads: Add new flag Has_Null_Refinement along with
+ comment on usage and update all nodes subject to the flag.
+ (Has_Null_Refinement): New routine along with pragma Inline.
+ (Set_Has_Null_Refinement): New rouitine along with pragma Inline.
+ * sem_prag.adb (Analyze_Constituent): Mark a state as having
+ a null refinement when the sole constituent is "null".
+ (Analyze_Global_List): Handle null input/output items.
+ (Analyze_Refined_Global_In_Decl_Part): Add local variable
+ Has_Null_State. Add logic to handle combinations of states
+ with null refinements and null global lists and/or items.
+ (Check_In_Out_States, Check_Input_States, Check_Output_States):
+ Use attribute Has_Null_Refinement to detect states with
+ constituents.
+ (Check_Refined_Global_List): Handle null input/output items.
+ (Process_Global_Item): Handle states with null refinements.
+ (Process_Global_List): Handle null input/output items.
+
+2013-10-14 Robert Dewar <dewar@adacore.com>
+
+ * freeze.adb (Freeze_Entity): Reset Is_True_Constant for
+ aliased object
+ * gnat_ugn.texi: Update doc on aliased variables and constants.
+
+2013-10-14 Ed Schonberg <schonberg@adacore.com>
+
+ * exp_pakd.adb (Expand_Packed_Element_Reference): If the
+ reference is an actual in a call, the prefix has not been fully
+ expanded, to account for the additional expansion for parameter
+ passing. the prefix itself is a packed reference as well,
+ recurse to complete the transformation of the prefix.
+
+2013-10-14 Eric Botcazou <ebotcazou@adacore.com>
+
+ * exp_dbug.adb (Debug_Renaming_Declaration): Do not
+ materialize the entity when the renamed object contains an
+ N_Explicit_Dereference.
+ * sem_ch8.adb (Analyze_Object_Renaming):
+ If the renaming comes from source and the renamed object is a
+ dereference, mark the prefix as needing debug information.
+
+2013-10-14 Doug Rupp <rupp@adacore.com>
+
+ * system-vxworks-arm.ads (Stack_Check_Probes, Stack_Check_Limits):
+ Enable Stack Probes, Disable Stack Limit Checking.
+ * init.c [VxWorks] (__gnat_inum_to_ivec): Caste return value.
+ (__gnat_map_signal): Fix signature.
+ (__gnat_error_handler): Make
+ static, fix signature, remove prototype, fix prototype warning.
+ [ARMEL and VxWorks6] (__gnat_map_signal): Check and re-arm guard
+ page for storage_error.
+ * exp_pakd.adb: Minor reformatting.
+
+2013-10-14 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * sem_prag.adb (Analyze_Global_In_Decl_Part): Remove local
+ variable Contract_Seen. Add local variable Proof_Seen.
+ (Analyze_Global_List): Remove the processing for mode
+ Contract_In. Add support for mode Proof_In.
+ (Analyze_Pragma): Update the grammar of pragmas Global and
+ Refined_Global.
+ * snames.ads-tmpl: Remove predefined name Contract_In. Add
+ predefined name Proof_In.
+
+2013-10-14 Robert Dewar <dewar@adacore.com>
+
+ * exp_prag.adb (Expand_Pragma_Check): Generate proper string
+ for invariant
+ * gnat_rm.texi: Add documentation for pragmas
+ Type_Invariant[_Class]
+ * par-prag.adb: Add entries for pragmas Type_Invariant[_Class]
+ * sem_ch13.adb: Minor reformatting
+ * sem_prag.adb: Implement pragmas Type_Invariant[_Class]
+ * snames.ads-tmpl: Add entries for pragmas Type_Invariant[_Class]
+
+2013-10-14 Johannes Kanig <kanig@adacore.com>
+
+ * debug.adb: Release now unused debug switches that were only
+ relevant for gnat2why backend, not the frontend
+ * frontend.adb (Frontend) Do not stop when -gnatd.H is present,
+ was unused
+
+2013-10-14 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * sem_prag.adb (Analyze_Global_Item): Allow
+ references to enclosing formal parameters.
+
+2013-10-14 Thomas Quinot <quinot@adacore.com>
+
+ * einfo.adb (Equivalent_Type): Add missing case
+ E_Access_Subprogram_Type in guard (for remote access to
+ subprograms) * sem_ch8.adb (Find_Direct_Name, Find_Expanded_Name):
+ Add missing guards to account for the presence of RAS types
+ that have already been replaced with the corresponding fat
+ pointer type.
+
+2013-10-14 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * aspects.adb: Add an entry in table Canonical_Aspect for
+ Initializes.
+ * aspects.ads: Add entries in tables Aspect_Id, Aspect_Argument,
+ Aspect_Names and Aspect_Delay for Initializes.
+ * atree.ads, atree.adb (Ekind_In): New seven argument versions of the
+ routines.
+ * einfo.adb: Remove Refined_State_Pragma from the list of node
+ usage. Finalizer is now at position 28.
+ (Contract): Package
+ and package bodies now have a contract.
+ (Finalizer): Update
+ the assertion and node usage.
+ (Get_Pragma): Update the Is_CDG
+ flag to include Abstract_State, Initializes and Refined_State.
+ (Refined_State_Pragma): Removed.
+ (Set_Contract): Package and
+ package bodies now have a contract.
+ (Set_Finalizer): Update the
+ assertion and node usage.
+ (Set_Refined_State_Pragma): Removed.
+ (Write_Field8_Name): Remove the output for Refined_State_Pragma.
+ (Write_Field24_Name): Remove the output for Finalizer. Package
+ and package bodies now have a contract.
+ (Write_Field28_Name):
+ Add output for Finalizer.
+ * einfo.ads: Update the documentation and usage in entities
+ of attribute Contract. Update the node position and usage in
+ entities of attribute Finalizer. Remove the documentation
+ and usage in entities for attribute Refined_State_Pragma.
+ (Refined_State_Pragma): Removed along with pragma Inline.
+ (Set_Refined_State_Pragma): Removed along with pragma Inline.
+ * par-prag.adb: Add Initializes to the pragmas that do not
+ require special processing by the parser.
+ * sem_ch3.adb (Analyze_Declarations): Add local variable
+ Prag. Update the retrieval of pragma Refined_State. Analyze
+ aspect/pragma Initializes at the end of the visible declarations
+ of the related package.
+ * sem_ch6.adb (Analyze_Subprogram_Body_Contract):
+ Add local variables Ref_Depends and Ref_Global. Analyze
+ pragmas Refined_Global and Refined_Depends in that order.
+ (Analyze_Subprogram_Contract): Add local variables Depends and
+ Global. Analyze pragmas Global and Depends in that order.
+ * sem_ch7.adb (Analyze_Package_Body_Helper): Package
+ bodies now have a contract. Move the analysis of the aspect
+ specifications after the defining entity has been decorated.
+ (Analyze_Package_Declaration): Packages now have a contract. Move
+ the analysis of the aspect specifications after the defining
+ entity has been decorated.
+ * sem_ch12.adb (Analyze_Generic_Package_Declaration): Packages
+ now have contracts.
+ * sem_ch13.adb (Analyze_Pragma): Code cleanup for aspect
+ Abstract_State. Add processing for aspect Initializes.
+ (Check_Aspect_At_Freeze_Point): Add an entry for Initializes.
+ * sem_prag.adb: Use Get_Pragma_Arg to extract the expression
+ of a pragma argument. Add an entry in table Sig_Flags for
+ Initializes.
+ (Analyze_Initializes_In_Decl_Part): New routine.
+ (Analyze_Pragma): Check the declaration order of pragmas
+ Abstract_State and Initializes. Abstract_State is now part of
+ the package contract. Analyze pragma Initializes. Check for
+ duplicate Refined_State pragma. Refined_State is now part of
+ the package contract.
+ (Check_Declaration_Order): New routine.
+ (Check_Test_Case): Alphabetized.
+ * sem_prag.ads (Analyze_Initializes_In_Decl_Part): New routine.
+ * sem_util.adb (Add_Contract_Item): Rename formal Subp_Id
+ to Id. This routine can now support contracts on packages and
+ package bodies.
+ * sem_util.ads (Add_Contract_Item): Rename formal Subp_Id to
+ Id. Update comment on usage.
+ * sinfo.ads: Update the usage of N_Contract nodes.
+ * snames.ads-tmpl: Add predefined name Initializes. Add new
+ pragma id for Initializes.
+
+2013-10-13 Nicolas Roche <roche@adacore.com>
+ Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/Make-lang.in (ada/%.o): Replace individual rules with
+ generic rule and add $(POSTCOMPILE).
+ (ADA_DEPS): New.
+ (.adb.o): Add @$(ADA_DEPS).
+ (.ads.o): Likewise.
+ (ada/a-except.o): Likewise.
+ (ada/s-excdeb.): Likewise.
+ (ada/s-assert.o): Likewise.
+ (ada/a-tags.o): Likewise.
+ (ada_generated_files): New variable.
+ Use them as dependency order for GNAT1_ADA_OBJS and GNATBIND_OBJS.
+ (ADA_DEPFILES): New variable.
+ Include them.
+ (ada_OBJS): Define.
+
+2013-10-13 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/decl.c (gnat_to_gnu_entity) <object>: Force all local
+ variables with aggregate types in memory if not optimizing.
+
+2013-10-13 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * sem_prag.adb (Check_Mode): Do
+ not emit an error when we are looking at inputs and
+ the item is an unconstrained or tagged out parameter.
+ (Check_Mode_Restriction_In_Enclosing_Context): Use Get_Pragma
+ to find whether the context is subject to aspect/pragma Global.
+ (Collect_Subprogram_Inputs_Outputs): Unconstrained or tagged
+ out parameters are now considered inputs. Use Get_Pragma to
+ find wheher the subprogram is subject to aspect/pragma Global.
+ (Is_Unconstrained_Or_Tagged_Item): New routine.
+
+2013-10-13 Thomas Quinot <quinot@adacore.com>
+
+ * einfo.ads: Minor reformatting.
+ * gcc-interface/Make-lang.in: Update dependencies.
+
+2013-10-13 Robert Dewar <dewar@adacore.com>
+
+ * gnat_rm.texi: Add documentation for pragmas Pre[_Class]
+ Post[_Class].
+ * par-ch2.adb (Skip_Pragma_Semicolon): Handle extra semicolon nicely.
+ * par-prag.adb: Add entries for pragmas Pre[_Class] and
+ Post[_Class].
+ * sem_prag.adb: Add handling of pragmas Pre[_Class] and
+ Post[_Class].
+ * sem_util.adb (Original_Aspect_Name): Moved here from
+ Sem_Prag.Original_Name, and modified to handle pragmas
+ Pre/Post/Pre_Class/Post_Class.
+ * sem_util.ads (Original_Aspect_Name): Moved here from
+ Sem_Prag.Original_Name.
+ * snames.ads-tmpl: Add entries for pragmas Pre[_Class] and
+ Post[_Class].
+
+2013-10-13 Robert Dewar <dewar@adacore.com>
+
+ * einfo.adb, sem_ch6.adb: Minor reformatting.
+
+2013-10-13 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * einfo.adb: Add node/list usage for Refined_State
+ and Refinement_Constituents.
+ (Get_Pragma): Update the
+ initialization of Is_CDG to include Refined_Global and
+ Refined_Depends. Rename constant Delayed to In_Contract and update
+ all of its occurrences.
+ (Is_Non_Volatile_State): New routine.
+ (Is_Volatile_State): Removed.
+ (Refined_State): New routine.
+ (Refinement_Constituents): New routine.
+ (Set_Refined_State): New routine.
+ (Set_Refinement_Constituents): New routine.
+ (Write_Field8_Name): Add output for Refinement_Constituents.
+ (Write_Field10_Name): Add output for Refined_State.
+ * einfo.ads: Add new synthesized attribute Is_Non_Volatile_State.
+ Remove synthesized attribute Is_Volatile_State. Add new
+ attributes Refined_State and Refinement_Constituents along with
+ usage in nodes.
+ (Get_Pragma): Update the comment on usage.
+ (Is_Non_Volatile_State): New routine.
+ (Is_Volatile_State): Removed.
+ (Refined_State): New routine and pragma Inline.
+ (Refinement_Constituents): New routine and pragma Inline.
+ (Set_Refined_State): New routine and pragma Inline.
+ (Set_Refinement_Constituents): New routine and pragma Inline.
+ * elists.ads, elists.adb (Clone): Removed.
+ (New_Copy_Elist): New routine.
+ (Remove): New routine.
+ * sem_ch3.adb (Analyze_Declarations): Use Defining_Entity
+ to get the entity of the subprogram [body].
+ (Analyze_Object_Declaration): Add initialization for
+ Refined_State.
+ * sem_ch6.adb (Analyze_Subprogram_Body_Contract): Add processing
+ for Refined_Global and Refined_Depends. Emit an error when
+ the body requires Refined_Global, but the aspect/pragma is
+ not present.
+ * sem_ch6.ads (Analyze_Subprogram_Body_Contract): Change
+ procedure signature and add comment on usage.
+ * sem_ch13.adb (Analyze_Aspect_Specifications): Add processing
+ for aspect Refined_Global.
+ * sem_prag.adb (Analyze_Abstract_State): Add initialization
+ of attributes Refined_State and Refinement_Constituents.
+ (Analyze_Depends_In_Decl_Part, Analyze_Global_In_Decl_Part,
+ Analyze_Contract_Cases_In_Decl_Part): Remove local
+ constant Arg1.
+ (Analyze_Pragma): Add processing for pragma
+ Refined_Global. The analysis of Refined_Post and Refined_Pre
+ has been merged. Update an error message in the processing of
+ pragma Refined_State.
+ (Analyze_Refined_Global_In_Decl_Part): Provide implementation.
+ (Analyze_Refined_Pragma): New routine.
+ (Analyze_Refined_Pre_Post_Condition): Removed.
+ (Analyze_Refined_State_In_Decl_Part): Update the call to Clone.
+ (Analyze_Refinement_Clause): Make State_Id visible to all
+ nested subprogram.
+ (Check_Matching_Constituent): Establish
+ a relation between a refined state and its constituent.
+ (Collect_Hidden_States_In_Decls): Remove ??? comment. Look at
+ the entity of the object declaration to establish its kind.
+ * sem_util.adb: Alphabetize with and use clauses.
+ (Contains_Refined_State): New routine.
+ * sem_util.ads (Contains_Refined_State): New routine.
+
+2013-10-13 Thomas Quinot <quinot@adacore.com>
+
+ * scos.ads: Minor documentation clarification.
+
+2013-10-13 Thomas Quinot <quinot@adacore.com>
+
+ * s-oscons-tmplt.c (CLOCK_RT_Ada): Set to CLOCK_MONOTONIC when
+ building on AIX 5.3 or later, and to CLOCK_REALTIME on older
+ versions of AIX.
+ * init.c (pthread_condattr_setclock): Remove now useless weak symbol.
+ * thread.c(__gnat_pthread_condattr_setup): Remove bogus AIX 5.2
+ compatibility shim.
+ * s-osinte-aix.ads(clock_id_t): Fix C mapping (this is a 64-bit
+ type).
+ (clock_gettime): Import from C runtime library.
+ * s-osinte-aix.adb (clock_gettime): Remove bogus emulation body,
+ this routine is provided by the system in current supported
+ versions of AIX.
+
+2013-10-13 Robert Dewar <dewar@adacore.com>
+
+ * sem_ch3.adb: Minor reformatting.
+
+2013-10-13 Ed Schonberg <schonberg@adacore.com>
+
+ * freeze.adb (Freeze_Entity): For a function whose return type
+ is incomplete, do not replace the type with the full view if the
+ type is a limited view. In that case the full view appears in a
+ different unit, and the back-end will retrieve it at the proper
+ elaboration point.
+
+2013-10-13 Yannick Moy <moy@adacore.com>
+
+ * exp_spark.adb (Expand_SPARK_Call): Do not introduce temporaries for
+ actuals.
+
+2013-10-13 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch3.adb: in Ada 2012 access_to_function types can have
+ in-out parameters.
+ (Derived_Type_Declaration): SPARK restriction
+ must be flagged on the original node, since it may have been
+ written as a subtype declaration.
+ (Analyze_Subtype_Declaration): Do not enter name of
+ entity in declaration if it is the current entity, because it may
+ have been inserted in a previous analysis and it appears in the
+ else_part of an if-statement that is rewritten during expansion.
+
+2013-10-13 Yannick Moy <moy@adacore.com>
+
+ * exp_spark.adb (Expand_SPARK_N_Attribute_Reference): Remove procedure.
+ (Expand_SPARK): Remove call to Expand_SPARK_N_Attribute_Reference and
+ Expand_SPARK_N_Simple_Return_Statement.
+ (Expand_SPARK_N_Simple_Return_Statement,
+ Expand_SPARK_Simple_Function_Return): Remove procedures.
+
+2013-10-13 Vincent Celier <celier@adacore.com>
+
+ * gnat_ugn.texi: Minor editing.
+
+2013-10-13 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch3.adb (Check_Abstract_Overriding): If a synchronized
+ operation implements an interface primitive, mark the operation
+ as referenced, to prevent usually spurious messages about unused
+ entities: such operations are called in dispatching select
+ statements that are not visible to the compiler.
+
+2013-10-13 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/decl.c (gnat_to_gnu_param): Remove obsolete comment.
+
+2013-10-11 Jakub Jelinek <jakub@redhat.com>
+
+ * gcc-interface/utils.c (DEF_FUNCTION_TYPE_8): Define.
+
+2013-10-10 Robert Dewar <dewar@adacore.com>
+
+ * par-ch6.adb (Check_Junk_Semicolon_Before_Return): Remove
+ junk code.
+
+2013-10-10 Javier Miranda <miranda@adacore.com>
+
+ * sem_ch13.adb (Freeze_Entity_Checks): Avoid
+ loosing errors on CPP entities in -gnatc mode.
+
+2013-10-10 Robert Dewar <dewar@adacore.com>
+
+ * sem_ch5.adb (Analyze_If_Statement): Only diagnose redundant
+ if from source.
+
+2013-10-10 Robert Dewar <dewar@adacore.com>
+
+ * restrict.adb (Check_SPARK_Restriction): Refine test (don't
+ automatically go to the original node).
+ * sem_ch11.adb (Analyze_Raise_Statement): Only raise
+ statements that come from source violate SPARK restrictions.
+ (Analyze_Raise_xxx_Error): Same fix.
+ * sem_ch3.adb (Analyze_Object_Declaration): Check OK SPARK
+ initialization on original node, not on possibly rewritten
+ expression.
+ * sem_ch4.adb (Analyze_If_Expression): Only if expressions that
+ come from source violate SPARK mode restrictions.
+
+2013-10-10 Robert Dewar <dewar@adacore.com>
+
+ * gnat_ugn.texi: Fix confusing documentation for -gnatyM.
+
+2013-10-10 Yannick Moy <moy@adacore.com>
+
+ * errout.adb (Compilation_Errors): In formal verification mode,
+ always return False.
+
+2013-10-10 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * sem_prag.adb (Collect_Hidden_States_In_Decls): Only consider source
+ non-constant objects.
+
+2013-10-10 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * aspects.adb: Add an entry in table Canonical_Aspect for
+ Refined_State.
+ * aspects.ads: Add entries in tables Aspect_Id, Aspect_Argument,
+ Aspect_Names and Aspect_Delay for Refined_State.
+ * einfo.adb: Add with and use clauses for Elists.
+ Remove Refined_State from the list of node usage.
+ Add Refined_State_Pragma to the list of node usage.
+ (Has_Null_Abstract_State): New routine.
+ (Refined_State): Removed.
+ (Refined_State_Pragma): New routine.
+ (Set_Refined_State): Removed.
+ (Set_Refined_State_Pragma): New routine.
+ (Write_Field8_Name): Add output for Refined_State_Pragma.
+ (Write_Field9_Name): Remove the output for Refined_State.
+ * einfo.ads: Add new synthesized attribute Has_Null_Abstract_State
+ along with usage in nodes. Remove attribute Refined_State along
+ with usage in nodes. Add new attribute Refined_State_Pragma along
+ with usage in nodes.
+ (Has_Null_Abstract_State): New routine.
+ (Refined_State): Removed.
+ (Refined_State_Pragma): New routine.
+ (Set_Refined_State): Removed.
+ (Set_Refined_State_Pragma): New routine.
+ * elists.adb (Clone): New routine.
+ * elists.ads (Clone): New routine.
+ * par-prag.adb: Add Refined_State to the pragmas that do not
+ require special processing by the parser.
+ * sem_ch3.adb: Add with and use clause for Sem_Prag.
+ (Analyze_Declarations): Add local variables Body_Id, Context and
+ Spec_Id. Add processing for delayed aspect/pragma Refined_State.
+ * sem_ch13.adb (Analyze_Aspect_Specifications): Update the
+ handling of aspect Abstract_State. Add processing for aspect
+ Refined_State. Remove the bizzare insertion policy for aspect
+ Abstract_State.
+ (Check_Aspect_At_Freeze_Point): Add an entry for Refined_State.
+ * sem_prag.adb: Add an entry to table Sig_Flags
+ for pragma Refined_State.
+ (Add_Item): Update the
+ comment on usage. The inserted items need not be unique.
+ (Analyze_Contract_Cases_In_Decl_Part): Rename variable Restore to
+ Restore_Scope and update all its occurrences.
+ (Analyze_Pragma):
+ Update the handling of pragma Abstract_State. Add processing for
+ pragma Refined_State.
+ (Analyze_Pre_Post_Condition_In_Decl_Part):
+ Rename variable Restore to Restore_Scope and update all its
+ occurrences.
+ (Analyze_Refined_State_In_Decl_Part): New routine.
+ * sem_prag.ads (Analyze_Refined_State_In_Decl_Part): New routine.
+ * snames.ads-tmpl: Add new predefined name for Refined_State. Add
+ new Pragma_Id for Refined_State.
+
+2013-10-10 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch10.adb (Install_Limited_Withed_Unit): handle properly the
+ case of a record declaration in a limited view, when the record
+ contains a self-referential component of an anonymous access type.
+
+2013-10-10 Thomas Quinot <quinot@adacore.com>
+
+ * exp_ch4.adb (Process_Transient_Object): For any context other
+ than a simple return statement, insert the finalization action
+ after the context, not as an action on the context (which will
+ get evaluated before it).
+
+2013-10-10 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * einfo.adb (Write_Field19_Name): Correct the
+ string name of attribute Default_Aspect_Value.
+
+2013-10-10 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_type.adb (Interface_Present_In_Ancestor): The progenitor
+ in a type declaration may be an interface subtype.
+
+2013-10-10 Robert Dewar <dewar@adacore.com>
+
+ * sinfo.ads (Do_Range_Check): Add special note on handling of
+ range checks for Succ and Pred.
+
+2013-10-10 Robert Dewar <dewar@adacore.com>
+
+ * erroutc.adb (Output_Msg_Text): Remove VMS special handling.
+
+2013-10-10 Robert Dewar <dewar@adacore.com>
+
+ * a-chahan.ads, a-chahan.adb (Is_Line_Terminator): New function
+ (Is_Mark): New function.
+ (Is_Other_Format): New function.
+ (Is_Punctuation_Connector): New function.
+ (Is_Space): New function.
+
+2013-10-10 Robert Dewar <dewar@adacore.com>
+
+ * sem_aggr.adb (Resolve_Array_Aggregate): Redo duplicate/missing
+ choice circuit. Was not quite right in some cases, which showed
+ up in ACATS test B43201C.
+ * sem_attr.adb (Address_Checks): Make sure name is set right
+ for some messages issued.
+ * mlib-prj.adb: Minor code reorganization.
+ * gnat_ugn.texi: Remove special VMS doc for tagging of warning msgs.
+ * exp_ch9.adb: Minor reformatting.
+
+2013-10-10 Tristan Gingold <gingold@adacore.com>
+
+ * lib-writ.adb (Write_Unit_Information): Adjust previous patch.
+
+2013-10-10 Robert Dewar <dewar@adacore.com>
+
+ * sem_ch5.adb (Analyze_If_Statement): Warn on redundant if
+ statement.
+ * sem_util.ads, sem_util.adb (Has_No_Obvious_Side_Effects): New
+ function.
+
+2013-10-10 Ed Schonberg <schonberg@adacore.com>
+
+ * exp_ch9.adb (Expand_N_Timed_Entry_Call): Simplify expansion
+ for the case of a dispatching trigger: there is no need to
+ duplicate the code or create a subprogram to encapsulate the
+ triggering statements. This allows exit statements in the
+ triggering statements, that refer to enclosing loops.
+
+2013-10-10 Robert Dewar <dewar@adacore.com>
+
+ * freeze.adb: Minor reformatting.
+ * sem_ch13.adb (Freeze_Entity_Checks): New procedure
+ (Analyze_Freeze_Entity): Call Freeze_Entity_Checks
+ (Analyze_Freeze_Generic_Entity): Call Freeze_Entity_Checks.
+ * sinfo.ads: Add syntax for sprint for Freeze_Generic_Entity.
+ * sprint.ads: Add syntax for freeze generic entity node.
+
+2013-10-10 Robert Dewar <dewar@adacore.com>
+
+ * einfo.adb, einfo.ads: Minor comment updates.
+
+2013-10-10 Robert Dewar <dewar@adacore.com>
+
+ * lib-writ.adb (Write_Unit_Information): Fatal error if linker
+ options are detected in a predefined generic unit.
+
+2013-10-10 Thomas Quinot <quinot@adacore.com>
+
+ * s-oscons-tmplt.c (CLOCK_REALTIME): Always define, possibly using
+ a dummy placeholder value.
+ (NEED_PTHREAD_CONDATTR_SETCLOCK): Remove, not needed anymore.
+ * thread.c: Adjust #if test accordingly.
+
+2013-10-10 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * exp_ch6.adb (Consequence_Error): Generate an
+ implicit if statement.
+ (Expand_Contract_Cases): Generate an implicit if statement.
+ (Process_Contract_Cases): Do not expand Contract_Cases when no code
+ is being generated.
+
+2013-10-10 Robert Dewar <dewar@adacore.com>
+
+ * sem_attr.adb (Address_Checks): New procedure.
+
+2013-10-10 Ed Schonberg <schonberg@adacore.com>
+
+ * sinfo.ads, sinfo.adb: New Node Freeze_Generic_Entity, to trigger
+ semantic actions at the proper point for entities that previously
+ had no explicit freeze point.
+ * freeze.adb (Freeze_Generic_Entities): generate new nodes to
+ indicate the point at which semantic checks can be performed on
+ entities declared in generic packages.
+ * sem_ch13.ads, sem_ch13.adb: New procedure
+ Analyze_Freeze_Generic_Entity.
+ * exp_util.adb (Insert_Actions): Treat new node like Freeze_Entity.
+ * sem.adb (Analyze): Call Analyze_Freeze_Generic_Entity.
+ * sprint.adb (Sprint_Node): display Analyze_Freeze_Generic_Entity.
+ * gcc-interface/trans.c: Ignore Analyze_Freeze_Generic_Entity.
+ * gcc-interface/Make-lang.in: Update dependencies.
+
+2013-10-10 Robert Dewar <dewar@adacore.com>
+
+ * sem_aggr.adb (Resolve_Array_Aggregate): Identify duplicated
+ cases.
+
+2013-10-10 Robert Dewar <dewar@adacore.com>
+
+ * sem_ch9.adb (Analyze_Task_Body): Aspects are illegal
+ (Analyze_Protected_Body): Aspects are illegal.
+
+2013-10-10 Robert Dewar <dewar@adacore.com>
+
+ * sem_ch6.adb, sem_ch13.adb: Minor reformatting.
+ * sem_case.adb (Check_Choices): Fix bad listing of missing
+ values from predicated subtype case (Check_Choices): List
+ duplicated values.
+ * errout.adb (Set_Msg_Text): Process warning tags in VMS mode
+ * erroutc.adb (Output_Msg_Text): Handle VMS warning tags
+ * gnat_ugn.texi: Document /WARNINGS=TAG_WARNINGS for VMS
+ * ug_words: Add entries for -gnatw.d and -gnatw.D
+ * vms_data.ads: Add [NO]TAG_WARNINGS for -gnatw.D/-gnatw.d
+ * lib-writ.ads: Documentation fixes
+
+2013-10-10 Robert Dewar <dewar@adacore.com>
+
+ * a-wichha.adb, a-wichha.ads, a-zchhan.adb, a-zchhan.ads
+ (Is_Other_Format): New name for Is_Other.
+ (Is_Punctuation_Connector): New name for Is_Punctuation
+
+2013-10-10 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * aspects.adb: Add entries in table Canonical_Aspects for aspects
+ Refined_Depends and Refined_Global.
+ * aspects.ads: Add entries in tables Aspect_Id, Aspect_Argument,
+ Aspect_Names, Aspect_Declay, Aspect_On_Body_Or_Stub_OK for
+ aspects Refined_Depends and Refined_Global.
+ * einfo.adb (Contract): Subprogram bodies are now valid owners
+ of contracts.
+ (Set_Contract): Subprogram bodies are now valid
+ owners of contracts.
+ (Write_Field24_Name): Output the contract
+ attribute for subprogram bodies.
+ * exp_ch6.adb (Expand_Subprogram_Contract): New routine.
+ * exp_ch6.ads (Expand_Subprogram_Contract): New routine.
+ * par-prag.adb: Pragmas Refined_Depends and Refined_Global do
+ not require any special processing by the parser.
+ * sem_ch3.adb (Adjust_D): Renamed to Adjust_Decl.
+ (Analyze_Declarations): Code reformatting. Analyze the contract
+ of a subprogram body at the end of the declarative region.
+ * sem_ch6.adb (Analyze_Generic_Subprogram_Body):
+ Subprogram bodies can now have contracts. Use
+ Expand_Subprogram_Contract to handle the various contract
+ assertions.
+ (Analyze_Subprogram_Body_Contract): New null routine.
+ (Analyze_Subprogram_Body_Helper): Subprogram bodies can now have
+ contracts. Use Expand_Subprogram_Contract to handle the various
+ contract assertions.
+ (Analyze_Subprogram_Contract): Add local
+ variable Nam. Update the call to Analyze_PPC_In_Decl_Part. Capture
+ the pragma name in Nam.
+ (Process_PPCs): Removed.
+ * sem_ch6.ads (Analyze_Subprogram_Body_Contract): New routine.
+ (Analyze_Subprogram_Contract): Update the comment on usage.
+ * sem_ch13.adb (Analyze_Aspect_Specifications): Add null
+ implementations for aspects Refined_Depends and Refined_Global.
+ (Check_Aspect_At_Freeze_Point): Aspects Refined_Depends and
+ Refined_Global do not need to be checked at the freeze point.
+ * sem_prag.adb: Add entries in table Sig_Flags
+ for pragmas Refined_Depends and Refined_Global.
+ (Analyze_Contract_Cases_In_Decl_Part): Add local
+ variable Restore. Use Restore to pop the scope.
+ (Analyze_Depends_In_Decl_Part): Add local variable Restore. Use
+ Restore to pop the scope.
+ (Analyze_Global_In_Decl_List): Add local variable Restore. Use Restore
+ to pop the scope.
+ (Analyze_PPC_In_Decl_Part): Renamed to
+ Analyze_Pre_Post_Condition_In_Decl_Part.
+ (Analyze_Pragma):
+ Add null implementations for pragmas Refined_Depends and
+ Refined_Global. Refined_Pre and Refined_Post are now
+ handled by routine Analyze_Refined_Pre_Post_Condition
+ exclusively.
+ (Analyze_Refined_Depends_In_Decl_Part): New
+ null routine.
+ (Analyze_Refined_Global_In_Decl_Part):
+ New null routine.
+ (Analyze_Refined_Pre_Post):
+ Renamed to Analyze_Refined_Pre_Post_Condition.
+ (Analyze_Refined_Pre_Post_Condition): Analyze the boolean
+ expression.
+ (Check_Precondition_Postcondition): Update the call
+ to Analyze_PPC_In_Decl_Part.
+ * sem_prag.ads: Add entries in table
+ Pragma_On_Body_Or_Stub_OK for pragmas Refined_Depends
+ and Refined_Global.
+ (Analyze_PPC_In_Decl_Part): Renamed
+ to Analyze_Pre_Post_Condition_In_Decl_Part. Update the
+ comment on usage.
+ (Analyze_Refined_Depends_In_Decl_Part): New routine.
+ (Analyze_Refined_Global_In_Decl_Part): New routine.
+ (Analyze_Test_Case_In_Decl_Part): Update the comment on usage.
+ * sem_util.adb (Add_Contract_Item): Rename formal Item to Prag
+ and update all occurrences. Subprogram body contracts can now
+ contain pragmas Refined_Depends and Refined_Global.
+ * sem_util.ads (Add_Contract_Item): Rename formal Item to
+ Prag. Update the comment on usage.
+ * sinfo.ads: Update the comment on structure and usage of
+ N_Contract.
+ * snames.ads-tmpl: Add new predefined names for Refined_Depends
+ and Refined_Global. Add entries in table Pragma_Id for
+ Refined_Depends and Refined_Global.
+
+2013-10-10 Robert Dewar <dewar@adacore.com>
+
+ * types.ads: Minor reformatting.
+
+2013-10-10 Thomas Quinot <quinot@adacore.com>
+
+ * s-taprop-posix.adb: Add missing comment.
+
+2013-10-10 Robert Dewar <dewar@adacore.com>
+
+ * freeze.adb (Freeze_Record_Type): Move choice checking to
+ Analyze_Freeze_Entity (Freeze_Record_Type): Make sure all choices
+ are properly frozen
+ * sem_case.adb (Check_Choices): Remove misguided attempt to
+ freeze choices (this is now done in Freeze_Record_Type where
+ it belongs).
+ (Check_Choices): Remove some analyze/resolve calls
+ that are redundant since they are done in Analyze_Choices.
+ * sem_ch13.adb (Analyze_Freeze_Entity): Do the error
+ checking for choices in variant records here (moved here from
+ Freeze.Freeze_Record_Type)
+
+2013-10-10 Thomas Quinot <quinot@adacore.com>
+
+ * s-oscons-tmplt.c, s-taprop-posix.adb (CLOCK_REALTIME): Always define,
+ possibly using a dummy placeholder value.
+ (Compute_Deadline): For the case of an
+ Absolute_Calendar deadline, if the target uses another clock
+ than CLOCK_REALTIME as CLOCK_RT_Ada, compensate for possible
+ different epoch.
+
+2013-10-10 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch8.adb (Find_Expanded_Name): Handle properly a fully
+ qualified reference to a generic child unit within itself,
+ in an instantiation.
+
+2013-10-10 Pascal Obry <obry@adacore.com>
+
+ * prj-conf.adb: Minor typo fixes in comment.
+
+2013-10-10 Thomas Quinot <quinot@adacore.com>
+
+ * s-taprop-posix.adb (Compute_Deadline): New local subprogram,
+ factors common code between Timed_Sleep and Timed_Delay.
+
+2013-10-10 Robert Dewar <dewar@adacore.com>
+
+ * freeze.adb (Freeze_Record_Type): Don't replace others if
+ expander inactive. This avoids clobbering the ASIS tree in
+ -gnatct mode.
+
+2013-10-10 Robert Dewar <dewar@adacore.com>
+
+ * sem_res.adb (Resolve_Op_Expon): Avoid crash testing for
+ fixed-point case in preanalysis mode (error will be caught during
+ full analysis).
+
+2013-10-10 Robert Dewar <dewar@adacore.com>
+
+ * gnat_rm.texi: Refined_Pre and Refined_Post are now allowed as
+ assertion identifiers for pragma Assertion_Policy.
+ * sem_prag.adb (Is_Valid_Assertion_Kind): Add Refined_Pre/Refined_Post
+ * sem_ch13.adb: Minor reformatting.
+
+2013-10-10 Pascal Obry <obry@adacore.com>
+
+ * prj-conf.adb: Code refactoring.
+
+2013-10-10 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * einfo.adb: Remove Integrity_Level from the node usage list.
+ (Has_Option): Update the implementation to match
+ the new terminology.
+ (Has_Property): Renamed to Has_Option.
+ (Integrity_Level): Removed.
+ (Is_External_State): New routine.
+ (Is_Input_Only_State): Use Has_Option to determine whether a state
+ is Input_Only. (Is_Input_State): Renamed to Is_Input_Only_State.
+ (Is_Output_Only_State): Use Has_Option to determine whether
+ a state is Output_Only.
+ (Is_Output_State): Renamed to
+ Is_Output_Only_State.
+ (Is_Volatile_State): Use Has_Option to determine whether a state is
+ volatile.
+ (Set_Integrity_Level): Removed.
+ (Write_Field8): Remove the entry for Integrity_Level.
+ * einfo.ads: Remove Integrity_Level along with its documentation
+ and usage in nodes. Rename Is_Input_State to Is_Input_Only_State.
+ Rename Is_Output_State to Is_Output_Only_State. Update the
+ documentation of Is_Volatile_State. Update the node structure of
+ E_Abstract_Entity.
+ (Integrity_Level): Removed along with pragma Inline.
+ (Is_External_State): New routine.
+ (Is_Input_State): Renamed to Is_Input_Only_State.
+ (Is_Output_State): Renamed to Is_Output_Only_State.
+ (Set_Integrity_Level): Removed along with pragma Inline.
+ * sem_prag.adb (Analyze_Pragma): Update the checks regarding
+ global items and abstract state modes. Update the implementation
+ of pragma Abstract_State to reflect the new rules and terminology.
+ * snames.ads-tmpl: Remove the predefined name for Integrity
+ level. Add new predefined names for Input_Only, Non_Volatile,
+ Output_Only and Part_Of.
+
+2013-10-10 Ed Schonberg <schonberg@adacore.com>
+
+ * lib-xref.adb (Generate_Reference): Do not generate a reference
+ within a _postcondition procedure: a proper source reference has
+ already been generated when pre- analyzing the original aspect
+ specification, and the use of a formal in a pre/postcondition
+ should not count as a proper use in a subprogram body.
+
+2013-10-10 Robert Dewar <dewar@adacore.com>
+
+ * sem_eval.adb (Why_Non_Static): Fix bomb for deferred constant
+ case
+
+2013-10-10 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * aspects.adb: Add an entry for Aspect_Refined_Post in table
+ Canonical_Aspect.
+ * aspects.ads: Add an entry for Aspect_Refined_Post in tables
+ Aspect_Id, Aspect_Argument, Aspect_Names, Aspect_Delay,
+ Aspect_On_Body_Or_Stub_OK. Update the comment on the use of
+ table Aspect_On_Body_Or_Stub_OK.
+ * par-prag.adb: Add pragma Refined_Post to the list of pragmas
+ that do not require special processing by the parser.
+ * sem_attr.adb (Analyze_Attribute): Add special analysis for
+ attributes 'Old and 'Result when code generation is disabled and
+ they appear in aspect/pragma Refined_Post.
+ (In_Refined_Post): New routine.
+ * sem_ch6.adb (Analyze_Expression_Function): Move various
+ aspects and/or pragmas that apply to an expression function to the
+ corresponding spec or body.
+ (Collect_Body_Postconditions): New routine.
+ (Process_PPCs): Use routine Collect_Body_Postconditions
+ to gather all postcondition pragmas.
+ * sem_ch10.adb (Analyze_Proper_Body): Use routine
+ Relocate_Pragmas_To_Body to move all source pragmas that follow
+ a body stub to the proper body.
+ (Move_Stub_Pragmas_To_Body): Removed.
+ * sem_ch13.adb (Analyze_Aspect_Specifications): Add processing
+ for aspect Refined_Post.
+ (Check_Aspect_At_Freeze_Point): Aspect
+ Refined_Post does not need delayed processing at the freeze point.
+ * sem_prag.adb: Add an entry for pragma Refined_Post in
+ table Sig_Flags.
+ (Analyze_Pragma): Add processing for pragma
+ Refined_Post. Update the processing of pragma Refined_Pre
+ to use common routine Analyze_Refined_Pre_Post.
+ (Analyze_Refined_Pre_Post): New routine.
+ (Relocate_Pragmas_To_Body): New routine.
+ * sem_prag.ads: Table Pragma_On_Stub_OK is now known as
+ Pragma_On_Body_Or_Stub_OK. Update the comment on usage of
+ table Pragma_On_Body_Or_Stub_OK.
+ (Relocate_Pragmas_To_Body): New routine.
+ * snames.ads-tmpl: Add new predefined name for Refined_Post. Add
+ new Pragma_Id for Refined_Post.
+
+2013-10-10 Robert Dewar <dewar@adacore.com>
+
+ * exp_ch3.adb (Expand_N_Variant_Part): Now null, expansion of
+ last choice to others is moved to Freeze_Record_Type.
+ * freeze.adb (Freeze_Record_Type): Expand last variant to others
+ if necessary (moved here from Expand_N_Variant_Part
+
+2013-10-10 Robert Dewar <dewar@adacore.com>
+
+ * lib-xref-spark_specific.adb, par-ch13.adb, sem_prag.adb, sem_prag.ads,
+ sem_ch12.adb, sem_attr.adb, sem_ch6.adb, sem_ch13.adb, a-sequio.adb,
+ s-atocou-builtin.adb: Minor reformatting.
+
+2013-10-10 Thomas Quinot <quinot@adacore.com>
+
+ * s-oscons-tmplt.c (NEED_PTHREAD_CONDATTR_SETCLOCK): This
+ constant needs to be output to s-oscons.h, as it is tested
+ by init.c.
+
+2013-10-10 Robert Dewar <dewar@adacore.com>
+
+ * exp_ch3.adb (Expand_N_Variant_Part): Don't expand choices, too early
+ * exp_ch5.adb (Expand_N_Case_Statement): Use new Has_SP_Choice
+ flag to avoid expanding choices when not necessary.
+ * exp_util.adb: Minor reformatting
+ * freeze.adb (Freeze_Record_Type): Redo expansion of variants
+ * sem_aggr.adb: Minor reformatting
+ * sem_case.ads, sem_case.adb: Major rewrite, separating Analysis and
+ Checking of choices.
+ * sem_ch3.adb (Analyze_Variant_Part): Rewrite to call new
+ Analyze_Choices.
+ * sem_ch4.adb (Analyze_Case_Expression): Call Analyze_Choices
+ and Check_Choices
+ * sem_ch5.adb (Analyze_Case_Statement): Call Analyze_Choices
+ and Check_Choices
+ * sem_util.adb: Minor reformatting
+ * sinfo.ads, sinfo.adb (Has_SP_Choice): New flag.
+
+2013-10-10 Vincent Celier <celier@adacore.com>
+
+ * mlib-prj.adb (Build_Library): Do not issue link dynamic
+ libraries with an Rpath, if switch -R was used.
+
+2013-10-10 Tristan Gingold <gingold@adacore.com>
+
+ * s-stalib.ads (Image_Index_Table_8, Image_Index_Table_16,
+ Image_Index_Table_32): Remove as not used.
+ * s-imgint.adb (Image_Integer): Call Set_Image_Integer and
+ remove duplicated code.
+
+2013-10-10 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * sem_prag.adb (Analyze_Pragma): Provide a
+ more precise error message when pragma Refined_Pre applies to
+ an expression function that is not a completion.
+
+2013-10-10 Thomas Quinot <quinot@adacore.com>
+
+ * sem_attr.adb (Analyse_Attribute, case
+ Attribute_Scalar_Storage_Order): a 'Scalar_Storage_Order attribute
+ reference for a generic type is permitted in GNAT runtime mode.
+ * a-sequio.adb (Read, Write): Use the endianness of the actual
+ type to encode length information written to the file.
+
+2013-10-10 Ed Schonberg <schonberg@adacore.com>
+
+ * par-ch13.adb (Aspect_Specifications_Present)): In earlier than
+ Ada2012 mode, assume that a legal aspect name following "with"
+ keyword is an older gnat switch and not a misplaced with_clause.
+
+2013-10-10 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * aspects.adb: Add an entry for Aspect_Refined_Pre in
+ table Canonical_Aspect.
+ (Aspects_On_Body_OK): Renamed to
+ Aspects_On_Body_Or_Stub_OK.
+ (Aspects_On_Body_Or_Stub_OK):
+ Update the query in table Aspect_On_Body_OK.
+ * aspects.ads: Add an entry for Aspect_Refined_Pre in tables
+ Aspect_Id, Aspect_Argument, Aspect_Names, Aspect_Delay,
+ Aspect_On_Body_Or_Stub_OK. Table Aspect_On_Body_OK is now known as
+ Aspect_On_Body_Or_Stub_OK. Add a section of aspect specifications
+ that apply to body stubs.
+ (Aspects_On_Body_OK): Renamed to Aspects_On_Body_Or_Stub_OK.
+ (Aspects_On_Body_Or_Stub_OK): Update the comment on usage.
+ * par-prag.adb: Add pragma Refined_Pre to the list of pragmas
+ that do not require special processing by the parser.
+ * sem_ch6.adb (Analyze_Subprogram_Body_Helper): Delay the
+ analysis of aspect specifications that apply to a body stub
+ until the proper body is analyzed.
+ * sem_ch10.adb: Add with and use clause for Sem_Ch13.
+ (Analyze_Package_Body_Stub): Set the corresponding spec of the stub.
+ (Analyze_Proper_Body): Relocate all pragmas that apply
+ to a subprogram body stub to the declarations of the proper
+ body. Analyze the aspect specifications of the stub when the
+ proper body is not present.
+ (Analyze_Protected_Body_Stub): Set the corresponding spec of the stub.
+ (Analyze_Task_Body_Stub): Set the corresponding spec of the stub.
+ (Move_Stub_Pragmas_To_Body): New routine.
+ * sem_ch13.adb (Analyze_Aspect_Specifications): Add processing
+ for aspect Refined_Pre.
+ (Check_Aspect_At_Freeze_Point): Aspect
+ Refined_Pre does not need delayed processing at the freeze point.
+ * sem_prag.adb: Remove with and use clause for Snames. Add
+ an entry for Pragma_Refined_Pre in table Sig_Flags.
+ (Analyze_Pragma): Add processing for pragma Refined_Pre.
+ * sem_prag.ads: Add with and use clause for Snames. Add table
+ Pragma_On_Stub_OK.
+ * sinfo.adb (Corresponding_Spec_Of_Stub): New routine.
+ (Set_Corresponding_Spec_Of_Stub): New routine.
+ * sinfo.ads: Add new attribute Corresponding_Spec_Of_Stub
+ along with comment on usage and occurrences in nodes.
+ (Corresponding_Spec_Of_Stub): New routine along with pragma
+ Inline.
+ (Set_Corresponding_Spec_Of_Stub): New routine along
+ with pragma Inline.
+ * snames.ads-tmpl: Add new predefined name for Refined_Pre. Add
+ new Pragma_Id for Refined_Pre.
+
+2013-10-10 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch12.adb (Analyze_Package_Instantiation,
+ Analyze_Subprogram_Instantiation): Improve error message when
+ name in instantiation does not designate a generic unit of the
+ right kind.
+
+2013-10-10 Robert Dewar <dewar@adacore.com>
+
+ * exp_ch3.adb (Expand_N_Variant_Part): Expand statically
+ predicated subtype which appears in Discrete_Choices list.
+ * exp_ch5.adb (Expand_N_Case_Statement): Expand statically
+ predicated subtype which appears in Discrete_Choices list of
+ case statement alternative.
+ * exp_util.ads, exp_util.adb (Expand_Static_Predicates_In_Choices): New
+ procedure.
+ * sem_case.adb: Minor reformatting (Analyze_Choices): Don't
+ expand out Discrete_Choices that are names of subtypes with
+ static predicates. This is now done in the analyzer so that the
+ -gnatct tree is properly formed for ASIS.
+ * sem_case.ads (Generic_Choices_Processing): Does not apply
+ to aggregates any more, so change doc accordingly, and remove
+ unneeded Get_Choices argument.
+ * sem_ch3.adb (Analyze_Variant_Part): Remove no
+ longer used Get_Choices argument in instantiation of
+ Generic_Choices_Processing.
+ * sem_ch4.adb (Analyze_Case_Expression): Remove no
+ longer used Get_Choices argument in instantiation of
+ Generic_Choices_Processing.
+ * sem_ch5.adb (Analyze_Case_Statement): Remove no
+ longer used Get_Choices argument in instantiation of
+ Generic_Choices_Processing.
+ * sinfo.ads: For N_Variant_Part, and N_Case_Statement_Alternative,
+ document that choices that are names of statically predicated
+ subtypes are expanded in the code generation tree passed to the
+ back end, but not in the ASIS tree generated for -gnatct.
+
+2013-10-10 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch7.adb: Revert previous change.
+
+2013-10-10 Gary Dismukes <dismukes@adacore.com>
+
+ * sem_ch13.adb (Analyze_Attribute_Definition_Clause): In the case where
+ the Storage_Pool aspect is specified by an aspect clause and a
+ renaming is used to capture the evaluation of the pool name,
+ insert the renaming in front of the aspect's associated entity
+ declaration rather than in front of the corresponding attribute
+ definition (which hasn't been appended to the declaration
+ list yet).
+
+2013-10-10 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch6.adb (Is_Interface_Conformant): The controlling type
+ of the interface operation is obtained from the ultimate alias
+ of the interface primitive parameter, because that may be in
+ fact an implicit inherited operation whose signature involves
+ the type extension and not the desired interface.
+
+2013-10-10 Ed Schonberg <schonberg@adacore.com>
+
+ * par-ch13.adb (Aspect_Specifications_Present): In Ada 2012,
+ recognize an aspect specification with a misspelled name if it
+ is followed by a a comma or semicolon.
+
+2013-10-10 Vadim Godunko <godunko@adacore.com>
+
+ * s-atocou.adb, s-atocou.ads, s-atocou-x86.adb, s-atocou-builtin.adb:
+ Fix copyright notice.
+
+2013-10-10 Yannick Moy <moy@adacore.com>
+
+ * lib-xref-spark_specific.adb (Enclosing_Subprogram_Or_Package): Get
+ enclosing subprogram for precondition/postcondition/contract cases.
+
+2013-10-10 Robert Dewar <dewar@adacore.com>
+
+ * gnat_rm.texi: Minor fix.
+
+2013-10-10 Robert Dewar <dewar@adacore.com>
+
+ * sem_ch13.adb (Analyze_Attribute_Definition_Clause, case
+ Address): Remove the Comes_From_Source test for the overlap
+ warning.
+
+2013-10-10 Robert Dewar <dewar@adacore.com>
+
+ * sem_util.adb: Minor code reorganization (use Nkind_In).
+ * sem_warn.adb: Minor code reorganization (optimization in
+ Check_Unset_Reference).
+ * exp_ch9.adb, exp_ch4.adb, sinfo.ads: Minor reformatting.
+
+2013-10-10 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch7.adb (Install_Parent_Private_Declarations): When
+ instantiating a child unit, do not install private declaration of
+ a non-generic ancestor of the generic that is also an ancestor
+ of the current unit: its private part will be installed when
+ private part of ancestor itself is analyzed.
+
+2013-10-10 Thomas Quinot <quinot@adacore.com>
+
+ * freeze.adb (Check_Component_Storage_Order): Retrieve component
+ aliased status from type entities directly instead of going back
+ to original component definition.
+ * sem_ch7.adb: Minor reformatting.
+
+2013-10-10 Robert Dewar <dewar@adacore.com>
+
+ * sem_ch13.adb (Analyze_Aspect_Specifications): For Address
+ attribute, consider it to be set in source, because of aliasing
+ considerations.
+ (Analyze_Attribute_Definition_Clause): For the
+ purpose of warning on overlays, take into account the aspect case.
+
+2013-10-10 Robert Dewar <dewar@adacore.com>
+
+ * a-cfdlli.ads, a-cfhase.ads, a-cforma.ads, a-cfhama.ads, a-cforse.ads,
+ a-cofove.ads: Minor reformatting.
+
+2013-10-10 Arnaud Charlet <charlet@adacore.com>
+
+ * gnat_ugn.texi: Remove obsolete mention to -laddr2line.
+
+2013-10-10 Ed Schonberg <schonberg@adacore.com>
+
+ * exp_ch4.adb (Expand_N_Case_Expression): Indicate that the
+ generated variable used as a target of the expression needs
+ no initialization.
+
+2013-10-10 Jose Ruiz <ruiz@adacore.com>
+
+ * exp_util.adb (Corresponding_Runtime_Package): Remove the condition
+ related to No_Dynamic_Attachment which was wrong. Protected types
+ with interrupt handlers (when not using a restricted profile)
+ are always treated as protected types with entries, regardless
+ of the No_Dynamic_Attachment restriction.
+ * exp_ch9.adb (Expand_N_Protected_Type_Declaration): Simplify the code
+ using the result of Corresponding_Runtime_Package.
+ (Install_Private_Data_Declarations): When having
+ static handlers and a non restricted profile, we use the
+ type Static_Interrupt_Protection always, so we removed an
+ extra wrong condition looking at the No_Dynamic_Attachment
+ restriction. Simplify the code using the result of
+ Corresponding_Runtime_Package.
+ (Make_Initialize_Protection): Simplify the code using
+ the result of Corresponding_Runtime_Package.
+ (Install_Private_Data_Declaration): The No_Dynamic_Attachment
+ restriction has nothing to do with static handlers. Remove the extra
+ erroneous condition that was creating the wrong data type.
+
+2013-10-10 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * sem_util.adb (Is_Object_Reference): Attribute
+ 'Old produces an object reference.
+ * gnat_rm.texi: Define accessibility level of
+ X'Update(...) result.
+
+2013-10-10 Yannick Moy <moy@adacore.com>
+
+ * gnat_rm.texi, a-cfdlli.ads, a-cfhase.ads, a-cforma.ads, a-cfhama.ads,
+ a-cforse.ads, a-cofove.ads: Update comment and doc of formal containers
+
+2013-10-10 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch13.adb (Analyze_Aspect_Specifications): For Pre/Post
+ conditions that apply to a subprogram body, preserve the placement
+ and order of the generated pragmas, which must appear before
+ other declarations in the body.
+
+2013-10-10 Bob Duff <duff@adacore.com>
+
+ * gnat_ugn.texi: Add gnat2xml doc.
+
+2013-10-10 Doug Rupp <rupp@adacore.com>
+
+ * s-vxwork-arm.ads: Fix interface to FP_CONTEXT.
+
+2013-10-10 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch13.adb (Analyze_Aspect_Specification): An aspect Import
+ on a variable need not have a convention specified, as long as
+ the implicit convention of the object, obtained from its type,
+ is Ada or Ada-related.
+
+2013-10-10 Robert Dewar <dewar@adacore.com>
+
+ * cstand.adb (Standard_Unsigned_64): New internal type.
+ * gnat_rm.texi: Update documentation on To_Address.
+ * sem_attr.adb (Analyze_Attribute, case To_Address): Fix
+ problem with out of range static values given as literals or
+ named numbers.
+ * stand.ads (Standard_Unsigned_64): New internal type.
+ * stand.adb: Minor reformatting.
+
+2013-10-10 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch4.adb (Analyze_Selected_Component,
+ Has_Mode_Conformant_Spec): If selected component may be an
+ indexing of a parameterless call to a protected function, and
+ expansion is disabled, this is a valid candidate interpretation.
+
+2013-10-10 Arnaud Charlet <charlet@adacore.com>
+
+ * gnat_ugn.texi: Minor editing.
+
+2013-10-10 Robert Dewar <dewar@adacore.com>
+
+ * gnatlink.adb: Minor reformatting.
+
+2013-10-10 Yannick Moy <moy@adacore.com>
+
+ * debug.adb: Free flag d.E and change doc for flag d.K.
+
+2013-10-10 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_prag.adb (Check_Precondition_Postcondition): If the
+ pragma comes from an aspect spec, and the subprogram is a
+ library unit, treat as a ppc in a declarative part in ASIS mode,
+ so that expression in aspect is properly analyzed. In this case
+ there is no later point at which the aspect specification would
+ be examined.
+
+2013-10-10 Bob Duff <duff@adacore.com>
+
+ * opt.ads: Minor comment fix.
+
+2013-10-10 Vadim Godunko <godunko@adacore.com>
+
+ * a-coinho-shared.ads, a-coinho-shared.adb: New file.
+ * s-atocou.ads: Add procedure to initialize counter.
+ * s-atocou.adb: Likewise.
+ * s-atocou-builtin.adb: Likewise.
+ * s-atocou-x86.adb: Likewise.
+ * gcc-interface/Makefile.in: Select special version of
+ Indefinite_Holders package on platforms where atomic built-ins
+ are supported. Update tools target pairs for PikeOS.
+
+2013-10-10 Robert Dewar <dewar@adacore.com>
+
+ * sem_ch3.adb: Minor reformatting.
+
+2013-10-10 Robert Dewar <dewar@adacore.com>
+
+ * sinput-c.adb (Load_File): Ensure Source_Align alignment.
+ * sinput-d.adb (Create_Debug_Source): Ensure Source_Align alignment.
+ * sinput-l.adb (Create_Instantiation_Source): Ensure Source_Align
+ alignment.
+ (Load_File): Ditto.
+ * sinput.ads, sinput.adb (Get_Source_File_Index): New optimized (single
+ line) version.
+ * types.ads (Source_Align): New definition.
+ (Source_Buffer): Document new alignment requirement.
+
+2013-10-10 Robert Dewar <dewar@adacore.com>
+
+ * sem_prag.adb (Analyze_Pragma, case Linker_Section): Allow
+ this for types.
+
+2013-10-10 Robert Dewar <dewar@adacore.com>
+
+ * gnat_rm.texi: Minor adjustment to doc for To_Address attribute.
+
+2013-10-10 Vadim Godunko <godunko@adacore.com>
+
+ * s-stopoo.ads (Root_Storage_Pool): Add pragma
+ Preelaborable_Initialization.
+
+2013-09-25 Tom Tromey <tromey@redhat.com>
+
+ * gcc-interface/Makefile.in (OUTPUT_OPTION): Define as "-o $@".
+
2013-09-18 Eric Botcazou <ebotcazou@adacore.com>
PR ada/58264
@@ -1229,7 +3681,7 @@
* gcc-interface/decl.c (gnat_to_gnu_entity) <E_Array_Subtype>: Use
int_const_binop to shift bounds by 1 when they are integer constants.
-2013-04-25 Arnaud Charlet <charlet@adacore.com>>
+2013-04-25 Arnaud Charlet <charlet@adacore.com>
* gcc-interface/Makefile.in (ADA_EXCLUDE_SRCS): Exclude s-init.ad{s,b}
@@ -4915,7 +7367,7 @@
accept an aspect name followed by a comma, indicating a defaulted
boolean aspect.
-2013-01-04 Joel Brobecker <brobecker@adacore.com brobecker>
+2013-01-04 Joel Brobecker <brobecker@adacore.com>
* gnat_ugn.texi: Document procedure to codesign GDB on Darwin.
Update doc on gnattest --separates switch.
diff --git a/gcc/ada/ChangeLog-2010 b/gcc/ada/ChangeLog-2010
index 6c1aa5932a7..8b372f5acda 100644
--- a/gcc/ada/ChangeLog-2010
+++ b/gcc/ada/ChangeLog-2010
@@ -7983,7 +7983,7 @@
* freeze.adb: Minor reformatting.
-2010-06-17 Joel Brobecker <brobecker@adacore.com brobecker>
+2010-06-17 Joel Brobecker <brobecker@adacore.com>
* gnat_ugn.texi: Add a section introducing gdbserver.
@@ -8032,7 +8032,7 @@
* par-labl.adb (Try_Loop): Test whether the label and the goto are in
the same list.
-2010-06-17 Joel Brobecker <brobecker@adacore.com brobecker>
+2010-06-17 Joel Brobecker <brobecker@adacore.com>
* gnat_ugn.texi: Update the documentation about GDB re: exception
catchpoints.
diff --git a/gcc/ada/ChangeLog-2011 b/gcc/ada/ChangeLog-2011
index 7f5f6f9aa5f..d6dd46a2e79 100644
--- a/gcc/ada/ChangeLog-2011
+++ b/gcc/ada/ChangeLog-2011
@@ -11415,7 +11415,7 @@
* sem_ch8.adb (Is_Primitive_Operator_In_Use): Always check In_Use on
the Base_Type.
-2011-08-03 Joel Brobecker <brobecker@adacore.com brobecker>
+2011-08-03 Joel Brobecker <brobecker@adacore.com>
* g-sha256.ads, g-sha512.ads, g-sha1.ads, g-sha224.ads, g-sha384.ads,
g-sehash.ads: Fix typo. Update header.
diff --git a/gcc/ada/ChangeLog-2012 b/gcc/ada/ChangeLog-2012
index 2bb659a52de..4949e047dbf 100644
--- a/gcc/ada/ChangeLog-2012
+++ b/gcc/ada/ChangeLog-2012
@@ -4452,7 +4452,7 @@
return for unknown exceptions.
* raise-gcc.c (__gnat_personality_seh0): Call __gnat_SEH_error_handler.
-2012-07-09 Joel Brobecker <brobecker@adacore.com brobecker>
+2012-07-09 Joel Brobecker <brobecker@adacore.com>
* exp_dbug.ads (No_Dollar_In_Label): Delete.
diff --git a/gcc/ada/a-cfdlli.ads b/gcc/ada/a-cfdlli.ads
index bfa8ffbcb90..b15b2425e4d 100644
--- a/gcc/ada/a-cfdlli.ads
+++ b/gcc/ada/a-cfdlli.ads
@@ -30,8 +30,10 @@
------------------------------------------------------------------------------
-- This spec is derived from Ada.Containers.Bounded_Doubly_Linked_Lists in the
--- Ada 2012 RM. The modifications are to facilitate formal proofs by making it
--- easier to express properties.
+-- Ada 2012 RM. The modifications are meant to facilitate formal proofs by
+-- making it easier to express properties, and by making the specification of
+-- this unit compatible with SPARK 2014. Note that the API of this unit may be
+-- subject to incompatible changes as SPARK 2014 evolves.
-- The modifications are:
diff --git a/gcc/ada/a-cfhama.ads b/gcc/ada/a-cfhama.ads
index 93a47c56817..dbfcb82e9dc 100644
--- a/gcc/ada/a-cfhama.ads
+++ b/gcc/ada/a-cfhama.ads
@@ -30,8 +30,10 @@
------------------------------------------------------------------------------
-- This spec is derived from package Ada.Containers.Bounded_Hashed_Maps in the
--- Ada 2012 RM. The modifications are to facilitate formal proofs by making it
--- easier to express properties.
+-- Ada 2012 RM. The modifications are meant to facilitate formal proofs by
+-- making it easier to express properties, and by making the specification of
+-- this unit compatible with SPARK 2014. Note that the API of this unit may be
+-- subject to incompatible changes as SPARK 2014 evolves.
-- The modifications are:
diff --git a/gcc/ada/a-cfhase.ads b/gcc/ada/a-cfhase.ads
index 22bfda97e89..c0103cbe0f4 100644
--- a/gcc/ada/a-cfhase.ads
+++ b/gcc/ada/a-cfhase.ads
@@ -30,8 +30,10 @@
------------------------------------------------------------------------------
-- This spec is derived from package Ada.Containers.Bounded_Hashed_Sets in the
--- Ada 2012 RM. The modifications are to facilitate formal proofs by making it
--- easier to express properties.
+-- Ada 2012 RM. The modifications are meant to facilitate formal proofs by
+-- making it easier to express properties, and by making the specification of
+-- this unit compatible with SPARK 2014. Note that the API of this unit may be
+-- subject to incompatible changes as SPARK 2014 evolves.
-- The modifications are:
diff --git a/gcc/ada/a-cforma.ads b/gcc/ada/a-cforma.ads
index 8e323e19dfb..2ddbd90a1ab 100644
--- a/gcc/ada/a-cforma.ads
+++ b/gcc/ada/a-cforma.ads
@@ -30,8 +30,10 @@
------------------------------------------------------------------------------
-- This spec is derived from package Ada.Containers.Bounded_Ordered_Maps in
--- the Ada 2012 RM. The modifications are to facilitate formal proofs by
--- making it easier to express properties.
+-- the Ada 2012 RM. The modifications are meant to facilitate formal proofs by
+-- making it easier to express properties, and by making the specification of
+-- this unit compatible with SPARK 2014. Note that the API of this unit may be
+-- subject to incompatible changes as SPARK 2014 evolves.
-- The modifications are:
diff --git a/gcc/ada/a-cforse.ads b/gcc/ada/a-cforse.ads
index 35e4613b9a8..1d8cdf66786 100644
--- a/gcc/ada/a-cforse.ads
+++ b/gcc/ada/a-cforse.ads
@@ -30,8 +30,10 @@
------------------------------------------------------------------------------
-- This spec is derived from package Ada.Containers.Bounded_Ordered_Sets in
--- the Ada 2012 RM. The modifications are to facilitate formal proofs by
--- making it easier to express properties.
+-- the Ada 2012 RM. The modifications are meant to facilitate formal proofs by
+-- making it easier to express properties, and by making the specification of
+-- this unit compatible with SPARK 2014. Note that the API of this unit may be
+-- subject to incompatible changes as SPARK 2014 evolves.
-- The modifications are:
diff --git a/gcc/ada/a-chahan.adb b/gcc/ada/a-chahan.adb
index c7a77ea57dc..f95a7bb0eaf 100644
--- a/gcc/ada/a-chahan.adb
+++ b/gcc/ada/a-chahan.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2012, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -49,6 +49,7 @@ package body Ada.Characters.Handling is
Hex_Digit : constant Character_Flags := 16;
Digit : constant Character_Flags := 32;
Special : constant Character_Flags := 64;
+ Line_Term : constant Character_Flags := 128;
Letter : constant Character_Flags := Lower or Upper;
Alphanum : constant Character_Flags := Letter or Digit;
@@ -66,10 +67,10 @@ package body Ada.Characters.Handling is
BEL => Control,
BS => Control,
HT => Control,
- LF => Control,
- VT => Control,
- FF => Control,
- CR => Control,
+ LF => Control + Line_Term,
+ VT => Control + Line_Term,
+ FF => Control + Line_Term,
+ CR => Control + Line_Term,
SO => Control,
SI => Control,
@@ -141,7 +142,7 @@ package body Ada.Characters.Handling is
BPH => Control,
NBH => Control,
Reserved_132 => Control,
- NEL => Control,
+ NEL => Control + Line_Term,
SSA => Control,
ESA => Control,
HTS => Control,
@@ -370,6 +371,15 @@ package body Ada.Characters.Handling is
return (Char_Map (Item) and Letter) /= 0;
end Is_Letter;
+ ------------------------
+ -- Is_Line_Terminator --
+ ------------------------
+
+ function Is_Line_Terminator (Item : Character) return Boolean is
+ begin
+ return (Char_Map (Item) and Line_Term) /= 0;
+ end Is_Line_Terminator;
+
--------------
-- Is_Lower --
--------------
@@ -379,6 +389,43 @@ package body Ada.Characters.Handling is
return (Char_Map (Item) and Lower) /= 0;
end Is_Lower;
+ -------------
+ -- Is_Mark --
+ -------------
+
+ function Is_Mark (Item : Character) return Boolean is
+ pragma Unreferenced (Item);
+ begin
+ return False;
+ end Is_Mark;
+
+ ---------------------
+ -- Is_Other_Format --
+ ---------------------
+
+ function Is_Other_Format (Item : Character) return Boolean is
+ begin
+ return Item = Soft_Hyphen;
+ end Is_Other_Format;
+
+ ------------------------------
+ -- Is_Punctuation_Connector --
+ ------------------------------
+
+ function Is_Punctuation_Connector (Item : Character) return Boolean is
+ begin
+ return Item = '_';
+ end Is_Punctuation_Connector;
+
+ --------------
+ -- Is_Space --
+ --------------
+
+ function Is_Space (Item : Character) return Boolean is
+ begin
+ return Item = ' ' or else Item = No_Break_Space;
+ end Is_Space;
+
----------------
-- Is_Special --
----------------
diff --git a/gcc/ada/a-chahan.ads b/gcc/ada/a-chahan.ads
index 98f69ba29d0..ca52f94730c 100644
--- a/gcc/ada/a-chahan.ads
+++ b/gcc/ada/a-chahan.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 1992-2010, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
-- --
-- This specification is derived from the Ada Reference Manual for use with --
-- GNAT. The copyright notice above, and the license provisions that follow --
@@ -42,18 +42,23 @@ package Ada.Characters.Handling is
-- Character Classification Functions --
----------------------------------------
- function Is_Control (Item : Character) return Boolean;
- function Is_Graphic (Item : Character) return Boolean;
- function Is_Letter (Item : Character) return Boolean;
- function Is_Lower (Item : Character) return Boolean;
- function Is_Upper (Item : Character) return Boolean;
- function Is_Basic (Item : Character) return Boolean;
- function Is_Digit (Item : Character) return Boolean;
- function Is_Decimal_Digit (Item : Character) return Boolean
+ function Is_Control (Item : Character) return Boolean;
+ function Is_Graphic (Item : Character) return Boolean;
+ function Is_Letter (Item : Character) return Boolean;
+ function Is_Lower (Item : Character) return Boolean;
+ function Is_Upper (Item : Character) return Boolean;
+ function Is_Basic (Item : Character) return Boolean;
+ function Is_Digit (Item : Character) return Boolean;
+ function Is_Decimal_Digit (Item : Character) return Boolean
renames Is_Digit;
- function Is_Hexadecimal_Digit (Item : Character) return Boolean;
- function Is_Alphanumeric (Item : Character) return Boolean;
- function Is_Special (Item : Character) return Boolean;
+ function Is_Hexadecimal_Digit (Item : Character) return Boolean;
+ function Is_Alphanumeric (Item : Character) return Boolean;
+ function Is_Special (Item : Character) return Boolean;
+ function Is_Line_Terminator (Item : Character) return Boolean;
+ function Is_Mark (Item : Character) return Boolean;
+ function Is_Other_Format (Item : Character) return Boolean;
+ function Is_Punctuation_Connector (Item : Character) return Boolean;
+ function Is_Space (Item : Character) return Boolean;
---------------------------------------------------
-- Conversion Functions for Character and String --
@@ -129,22 +134,27 @@ package Ada.Characters.Handling is
(Item : String) return Wide_String;
private
+ pragma Inline (Is_Alphanumeric);
+ pragma Inline (Is_Basic);
+ pragma Inline (Is_Character);
pragma Inline (Is_Control);
+ pragma Inline (Is_Digit);
pragma Inline (Is_Graphic);
+ pragma Inline (Is_Hexadecimal_Digit);
+ pragma Inline (Is_ISO_646);
pragma Inline (Is_Letter);
+ pragma Inline (Is_Line_Terminator);
pragma Inline (Is_Lower);
- pragma Inline (Is_Upper);
- pragma Inline (Is_Basic);
- pragma Inline (Is_Digit);
- pragma Inline (Is_Hexadecimal_Digit);
- pragma Inline (Is_Alphanumeric);
+ pragma Inline (Is_Mark);
+ pragma Inline (Is_Other_Format);
+ pragma Inline (Is_Punctuation_Connector);
+ pragma Inline (Is_Space);
pragma Inline (Is_Special);
- pragma Inline (To_Lower);
- pragma Inline (To_Upper);
+ pragma Inline (Is_Upper);
pragma Inline (To_Basic);
- pragma Inline (Is_ISO_646);
- pragma Inline (Is_Character);
pragma Inline (To_Character);
+ pragma Inline (To_Lower);
+ pragma Inline (To_Upper);
pragma Inline (To_Wide_Character);
end Ada.Characters.Handling;
diff --git a/gcc/ada/a-cobove.adb b/gcc/ada/a-cobove.adb
index c2790517e01..bcd6118e607 100644
--- a/gcc/ada/a-cobove.adb
+++ b/gcc/ada/a-cobove.adb
@@ -1227,7 +1227,22 @@ package body Ada.Containers.Bounded_Vectors is
-- worry about if No_Index were less than 0, but that case is
-- handled above).
- Max_Length := Count_Type'Base (Index_Type'Last - No_Index);
+ if Index_Type'Last - No_Index >=
+ Count_Type'Pos (Count_Type'Last)
+ then
+ -- We have determined that range of Index_Type has at least as
+ -- many values as in Count_Type, so Count_Type'Last is the
+ -- maximum number of items that are allowed.
+
+ Max_Length := Count_Type'Last;
+
+ else
+ -- The range of Index_Type has fewer values than in Count_Type,
+ -- so the maximum number of items is computed from the range of
+ -- the Index_Type.
+
+ Max_Length := Count_Type'Base (Index_Type'Last - No_Index);
+ end if;
end if;
elsif Index_Type'First <= 0 then
@@ -1685,7 +1700,22 @@ package body Ada.Containers.Bounded_Vectors is
-- worry about if No_Index were less than 0, but that case is
-- handled above).
- Max_Length := Count_Type'Base (Index_Type'Last - No_Index);
+ if Index_Type'Last - No_Index >=
+ Count_Type'Pos (Count_Type'Last)
+ then
+ -- We have determined that range of Index_Type has at least as
+ -- many values as in Count_Type, so Count_Type'Last is the
+ -- maximum number of items that are allowed.
+
+ Max_Length := Count_Type'Last;
+
+ else
+ -- The range of Index_Type has fewer values than in Count_Type,
+ -- so the maximum number of items is computed from the range of
+ -- the Index_Type.
+
+ Max_Length := Count_Type'Base (Index_Type'Last - No_Index);
+ end if;
end if;
elsif Index_Type'First <= 0 then
diff --git a/gcc/ada/a-cofove.ads b/gcc/ada/a-cofove.ads
index 9ca84da460f..604ed8d356b 100644
--- a/gcc/ada/a-cofove.ads
+++ b/gcc/ada/a-cofove.ads
@@ -30,8 +30,10 @@
------------------------------------------------------------------------------
-- This spec is derived from package Ada.Containers.Bounded_Vectors in the Ada
--- 2012 RM. The modifications are to facilitate formal proofs by making it
--- easier to express properties.
+-- 2012 RM. The modifications are meant to facilitate formal proofs by making
+-- it easier to express properties, and by making the specification of this
+-- unit compatible with SPARK 2014. Note that the API of this unit may be
+-- subject to incompatible changes as SPARK 2014 evolves.
-- The modifications are:
@@ -48,12 +50,7 @@
-- function Left (Container : Vector; Position : Cursor) return Vector;
-- function Right (Container : Vector; Position : Cursor) return Vector;
--- Left returns a container containing all elements preceding Position
--- (excluded) in Container. Right returns a container containing all
--- elements following Position (included) in Container. These two new
--- functions are useful to express invariant properties in loops which
--- iterate over containers. Left returns the part of the container already
--- scanned and Right the part not scanned yet.
+-- See detailed specifications for these subprograms
with Ada.Containers;
use Ada.Containers;
@@ -350,9 +347,14 @@ package Ada.Containers.Formal_Vectors is
function Left (Container : Vector; Position : Cursor) return Vector with
Pre => Has_Element (Container, Position) or else Position = No_Element;
-
function Right (Container : Vector; Position : Cursor) return Vector with
Pre => Has_Element (Container, Position) or else Position = No_Element;
+ -- Left returns a container containing all elements preceding Position
+ -- (excluded) in Container. Right returns a container containing all
+ -- elements following Position (included) in Container. These two new
+ -- functions can be used to express invariant properties in loops which
+ -- iterate over containers. Left returns the part of the container already
+ -- scanned and Right the part not scanned yet.
private
diff --git a/gcc/ada/a-coinho-shared.adb b/gcc/ada/a-coinho-shared.adb
new file mode 100644
index 00000000000..9300c0b1dc6
--- /dev/null
+++ b/gcc/ada/a-coinho-shared.adb
@@ -0,0 +1,358 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT LIBRARY COMPONENTS --
+-- --
+-- A D A . C O N T A I N E R S . I N D E F I N I T E _ H O L D E R S --
+-- --
+-- B o d y --
+-- --
+-- Copyright (C) 2013, Free Software Foundation, Inc. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+------------------------------------------------------------------------------
+
+with Ada.Unchecked_Deallocation;
+
+package body Ada.Containers.Indefinite_Holders is
+
+ procedure Free is
+ new Ada.Unchecked_Deallocation (Element_Type, Element_Access);
+
+ ---------
+ -- "=" --
+ ---------
+
+ function "=" (Left, Right : Holder) return Boolean is
+ begin
+ if Left.Reference = null and Right.Reference = null then
+ return True;
+
+ elsif Left.Reference /= null and Right.Reference /= null then
+ return Left.Reference.Element.all = Right.Reference.Element.all;
+
+ else
+ return False;
+ end if;
+ end "=";
+
+ ------------
+ -- Adjust --
+ ------------
+
+ overriding procedure Adjust (Container : in out Holder) is
+ begin
+ if Container.Reference /= null then
+ Reference (Container.Reference);
+ end if;
+
+ Container.Busy := 0;
+ end Adjust;
+
+ ------------
+ -- Assign --
+ ------------
+
+ procedure Assign (Target : in out Holder; Source : Holder) is
+ begin
+ if Target.Busy /= 0 then
+ raise Program_Error with "attempt to tamper with elements";
+ end if;
+
+ if Target.Reference /= Source.Reference then
+ if Target.Reference /= null then
+ Unreference (Target.Reference);
+ end if;
+
+ Target.Reference := Source.Reference;
+
+ if Source.Reference /= null then
+ Reference (Target.Reference);
+ end if;
+ end if;
+ end Assign;
+
+ -----------
+ -- Clear --
+ -----------
+
+ procedure Clear (Container : in out Holder) is
+ begin
+ if Container.Busy /= 0 then
+ raise Program_Error with "attempt to tamper with elements";
+ end if;
+
+ Unreference (Container.Reference);
+ Container.Reference := null;
+ end Clear;
+
+ ----------
+ -- Copy --
+ ----------
+
+ function Copy (Source : Holder) return Holder is
+ begin
+ if Source.Reference = null then
+ return (AF.Controlled with null, 0);
+ else
+ Reference (Source.Reference);
+
+ return (AF.Controlled with Source.Reference, 0);
+ end if;
+ end Copy;
+
+ -------------
+ -- Element --
+ -------------
+
+ function Element (Container : Holder) return Element_Type is
+ begin
+ if Container.Reference = null then
+ raise Constraint_Error with "container is empty";
+ else
+ return Container.Reference.Element.all;
+ end if;
+ end Element;
+
+ --------------
+ -- Finalize --
+ --------------
+
+ overriding procedure Finalize (Container : in out Holder) is
+ begin
+ if Container.Busy /= 0 then
+ raise Program_Error with "attempt to tamper with elements";
+ end if;
+
+ if Container.Reference /= null then
+ Unreference (Container.Reference);
+ Container.Reference := null;
+ end if;
+ end Finalize;
+
+ --------------
+ -- Is_Empty --
+ --------------
+
+ function Is_Empty (Container : Holder) return Boolean is
+ begin
+ return Container.Reference = null;
+ end Is_Empty;
+
+ ----------
+ -- Move --
+ ----------
+
+ procedure Move (Target : in out Holder; Source : in out Holder) is
+ begin
+ if Target.Busy /= 0 then
+ raise Program_Error with "attempt to tamper with elements";
+ end if;
+
+ if Source.Busy /= 0 then
+ raise Program_Error with "attempt to tamper with elements";
+ end if;
+
+ if Target.Reference /= Source.Reference then
+ if Target.Reference /= null then
+ Unreference (Target.Reference);
+ end if;
+
+ Target.Reference := Source.Reference;
+ Source.Reference := null;
+ end if;
+ end Move;
+
+ -------------------
+ -- Query_Element --
+ -------------------
+
+ procedure Query_Element
+ (Container : Holder;
+ Process : not null access procedure (Element : Element_Type))
+ is
+ B : Natural renames Container'Unrestricted_Access.Busy;
+
+ begin
+ if Container.Reference = null then
+ raise Constraint_Error with "container is empty";
+ end if;
+
+ B := B + 1;
+
+ begin
+ Process (Container.Reference.Element.all);
+ exception
+ when others =>
+ B := B - 1;
+ raise;
+ end;
+
+ B := B - 1;
+ end Query_Element;
+
+ ----------
+ -- Read --
+ ----------
+
+ procedure Read
+ (Stream : not null access Ada.Streams.Root_Stream_Type'Class;
+ Container : out Holder)
+ is
+ begin
+ Clear (Container);
+
+ if not Boolean'Input (Stream) then
+ Container.Reference :=
+ new Shared_Holder'
+ (Counter => <>,
+ Element => new Element_Type'(Element_Type'Input (Stream)));
+ end if;
+ end Read;
+
+ ---------------
+ -- Reference --
+ ---------------
+
+ procedure Reference (Item : not null Shared_Holder_Access) is
+ begin
+ System.Atomic_Counters.Increment (Item.Counter);
+ end Reference;
+
+ ---------------------
+ -- Replace_Element --
+ ---------------------
+
+ procedure Replace_Element
+ (Container : in out Holder;
+ New_Item : Element_Type)
+ is
+ -- Element allocator may need an accessibility check in case actual type
+ -- is class-wide or has access discriminants (RM 4.8(10.1) and
+ -- AI12-0035).
+
+ pragma Unsuppress (Accessibility_Check);
+
+ begin
+ if Container.Busy /= 0 then
+ raise Program_Error with "attempt to tamper with elements";
+ end if;
+
+ if Container.Reference = null then
+ -- Holder is empty, allocate new Shared_Holder.
+
+ Container.Reference :=
+ new Shared_Holder'
+ (Counter => <>,
+ Element => new Element_Type'(New_Item));
+
+ elsif System.Atomic_Counters.Is_One (Container.Reference.Counter) then
+ -- Shared_Holder can be reused.
+
+ Free (Container.Reference.Element);
+ Container.Reference.Element := new Element_Type'(New_Item);
+
+ else
+ Unreference (Container.Reference);
+ Container.Reference :=
+ new Shared_Holder'
+ (Counter => <>,
+ Element => new Element_Type'(New_Item));
+ end if;
+ end Replace_Element;
+
+ ---------------
+ -- To_Holder --
+ ---------------
+
+ function To_Holder (New_Item : Element_Type) return Holder is
+ -- The element allocator may need an accessibility check in the case the
+ -- actual type is class-wide or has access discriminants (RM 4.8(10.1)
+ -- and AI12-0035).
+
+ pragma Unsuppress (Accessibility_Check);
+
+ begin
+ return
+ (AF.Controlled with
+ new Shared_Holder'
+ (Counter => <>,
+ Element => new Element_Type'(New_Item)), 0);
+ end To_Holder;
+
+ -----------------
+ -- Unreference --
+ -----------------
+
+ procedure Unreference (Item : not null Shared_Holder_Access) is
+
+ procedure Free is
+ new Ada.Unchecked_Deallocation (Shared_Holder, Shared_Holder_Access);
+
+ Aux : Shared_Holder_Access := Item;
+
+ begin
+ if System.Atomic_Counters.Decrement (Aux.Counter) then
+ Free (Aux.Element);
+ Free (Aux);
+ end if;
+ end Unreference;
+
+ --------------------
+ -- Update_Element --
+ --------------------
+
+ procedure Update_Element
+ (Container : Holder;
+ Process : not null access procedure (Element : in out Element_Type))
+ is
+ B : Natural renames Container'Unrestricted_Access.Busy;
+
+ begin
+ if Container.Reference = null then
+ raise Constraint_Error with "container is empty";
+ end if;
+
+ B := B + 1;
+
+ begin
+ Process (Container.Reference.Element.all);
+ exception
+ when others =>
+ B := B - 1;
+ raise;
+ end;
+
+ B := B - 1;
+ end Update_Element;
+
+ -----------
+ -- Write --
+ -----------
+
+ procedure Write
+ (Stream : not null access Ada.Streams.Root_Stream_Type'Class;
+ Container : Holder)
+ is
+ begin
+ Boolean'Output (Stream, Container.Reference = null);
+
+ if Container.Reference /= null then
+ Element_Type'Output (Stream, Container.Reference.Element.all);
+ end if;
+ end Write;
+
+end Ada.Containers.Indefinite_Holders;
diff --git a/gcc/ada/a-coinho-shared.ads b/gcc/ada/a-coinho-shared.ads
new file mode 100644
index 00000000000..9abeda33a8f
--- /dev/null
+++ b/gcc/ada/a-coinho-shared.ads
@@ -0,0 +1,115 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT LIBRARY COMPONENTS --
+-- --
+-- A D A . C O N T A I N E R S . I N D E F I N I T E _ H O L D E R S --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2013, Free Software Foundation, Inc. --
+-- --
+-- This specification is derived from the Ada Reference Manual for use with --
+-- GNAT. The copyright notice above, and the license provisions that follow --
+-- apply solely to the contents of the part following the private keyword. --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+------------------------------------------------------------------------------
+
+private with Ada.Finalization;
+private with Ada.Streams;
+private with System.Atomic_Counters;
+
+generic
+ type Element_Type (<>) is private;
+ with function "=" (Left, Right : Element_Type) return Boolean is <>;
+
+package Ada.Containers.Indefinite_Holders is
+ pragma Preelaborate (Indefinite_Holders);
+ pragma Remote_Types (Indefinite_Holders);
+
+ type Holder is tagged private;
+ pragma Preelaborable_Initialization (Holder);
+
+ Empty_Holder : constant Holder;
+
+ function "=" (Left, Right : Holder) return Boolean;
+
+ function To_Holder (New_Item : Element_Type) return Holder;
+
+ function Is_Empty (Container : Holder) return Boolean;
+
+ procedure Clear (Container : in out Holder);
+
+ function Element (Container : Holder) return Element_Type;
+
+ procedure Replace_Element
+ (Container : in out Holder;
+ New_Item : Element_Type);
+
+ procedure Query_Element
+ (Container : Holder;
+ Process : not null access procedure (Element : Element_Type));
+ procedure Update_Element
+ (Container : Holder;
+ Process : not null access procedure (Element : in out Element_Type));
+
+ procedure Assign (Target : in out Holder; Source : Holder);
+
+ function Copy (Source : Holder) return Holder;
+
+ procedure Move (Target : in out Holder; Source : in out Holder);
+
+private
+
+ package AF renames Ada.Finalization;
+
+ type Element_Access is access all Element_Type;
+
+ type Shared_Holder is record
+ Counter : System.Atomic_Counters.Atomic_Counter;
+ Element : Element_Access;
+ end record;
+
+ type Shared_Holder_Access is access all Shared_Holder;
+
+ procedure Reference (Item : not null Shared_Holder_Access);
+ -- Increment reference counter
+
+ procedure Unreference (Item : not null Shared_Holder_Access);
+ -- Decrement reference counter, deallocate Item when counter goes to zero
+
+ procedure Read
+ (Stream : not null access Ada.Streams.Root_Stream_Type'Class;
+ Container : out Holder);
+
+ procedure Write
+ (Stream : not null access Ada.Streams.Root_Stream_Type'Class;
+ Container : Holder);
+
+ type Holder is new Ada.Finalization.Controlled with record
+ Reference : Shared_Holder_Access;
+ Busy : Natural := 0;
+ end record;
+ for Holder'Read use Read;
+ for Holder'Write use Write;
+
+ overriding procedure Adjust (Container : in out Holder);
+ overriding procedure Finalize (Container : in out Holder);
+
+ Empty_Holder : constant Holder := (AF.Controlled with null, 0);
+
+end Ada.Containers.Indefinite_Holders;
diff --git a/gcc/ada/a-coinve.adb b/gcc/ada/a-coinve.adb
index cff3a286edb..677fd97e09d 100644
--- a/gcc/ada/a-coinve.adb
+++ b/gcc/ada/a-coinve.adb
@@ -1734,7 +1734,22 @@ package body Ada.Containers.Indefinite_Vectors is
-- worry about if No_Index were less than 0, but that case is
-- handled above).
- Max_Length := Count_Type'Base (Index_Type'Last - No_Index);
+ if Index_Type'Last - No_Index >=
+ Count_Type'Pos (Count_Type'Last)
+ then
+ -- We have determined that range of Index_Type has at least as
+ -- many values as in Count_Type, so Count_Type'Last is the
+ -- maximum number of items that are allowed.
+
+ Max_Length := Count_Type'Last;
+
+ else
+ -- The range of Index_Type has fewer values than in Count_Type,
+ -- so the maximum number of items is computed from the range of
+ -- the Index_Type.
+
+ Max_Length := Count_Type'Base (Index_Type'Last - No_Index);
+ end if;
end if;
elsif Index_Type'First <= 0 then
@@ -2504,7 +2519,22 @@ package body Ada.Containers.Indefinite_Vectors is
-- worry about if No_Index were less than 0, but that case is
-- handled above).
- Max_Length := Count_Type'Base (Index_Type'Last - No_Index);
+ if Index_Type'Last - No_Index >=
+ Count_Type'Pos (Count_Type'Last)
+ then
+ -- We have determined that range of Index_Type has at least as
+ -- many values as in Count_Type, so Count_Type'Last is the
+ -- maximum number of items that are allowed.
+
+ Max_Length := Count_Type'Last;
+
+ else
+ -- The range of Index_Type has fewer values than in Count_Type,
+ -- so the maximum number of items is computed from the range of
+ -- the Index_Type.
+
+ Max_Length := Count_Type'Base (Index_Type'Last - No_Index);
+ end if;
end if;
elsif Index_Type'First <= 0 then
diff --git a/gcc/ada/a-convec.adb b/gcc/ada/a-convec.adb
index 5b722fe8a72..0f4bc19bcba 100644
--- a/gcc/ada/a-convec.adb
+++ b/gcc/ada/a-convec.adb
@@ -1386,7 +1386,22 @@ package body Ada.Containers.Vectors is
-- worry about if No_Index were less than 0, but that case is
-- handled above).
- Max_Length := Count_Type'Base (Index_Type'Last - No_Index);
+ if Index_Type'Last - No_Index >=
+ Count_Type'Pos (Count_Type'Last)
+ then
+ -- We have determined that range of Index_Type has at least as
+ -- many values as in Count_Type, so Count_Type'Last is the
+ -- maximum number of items that are allowed.
+
+ Max_Length := Count_Type'Last;
+
+ else
+ -- The range of Index_Type has fewer values than in Count_Type,
+ -- so the maximum number of items is computed from the range of
+ -- the Index_Type.
+
+ Max_Length := Count_Type'Base (Index_Type'Last - No_Index);
+ end if;
end if;
elsif Index_Type'First <= 0 then
@@ -2033,7 +2048,22 @@ package body Ada.Containers.Vectors is
-- worry about if No_Index were less than 0, but that case is
-- handled above).
- Max_Length := Count_Type'Base (Index_Type'Last - No_Index);
+ if Index_Type'Last - No_Index >=
+ Count_Type'Pos (Count_Type'Last)
+ then
+ -- We have determined that range of Index_Type has at least as
+ -- many values as in Count_Type, so Count_Type'Last is the
+ -- maximum number of items that are allowed.
+
+ Max_Length := Count_Type'Last;
+
+ else
+ -- The range of Index_Type has fewer values than in Count_Type,
+ -- so the maximum number of items is computed from the range of
+ -- the Index_Type.
+
+ Max_Length := Count_Type'Base (Index_Type'Last - No_Index);
+ end if;
end if;
elsif Index_Type'First <= 0 then
diff --git a/gcc/ada/a-except-2005.adb b/gcc/ada/a-except-2005.adb
index 3453eae90ab..b47f167be77 100644
--- a/gcc/ada/a-except-2005.adb
+++ b/gcc/ada/a-except-2005.adb
@@ -861,6 +861,17 @@ package body Ada.Exceptions is
-- in case we do not want any exception tracing support. This is
-- why this package is separated.
+ --------------------------------------
+ -- Get_Exception_Machine_Occurrence --
+ --------------------------------------
+
+ function Get_Exception_Machine_Occurrence
+ (X : Exception_Occurrence) return System.Address
+ is
+ begin
+ return X.Machine_Occurrence;
+ end Get_Exception_Machine_Occurrence;
+
-----------
-- Image --
-----------
diff --git a/gcc/ada/a-except-2005.ads b/gcc/ada/a-except-2005.ads
index bb597ed0982..ca4ff9f9e17 100644
--- a/gcc/ada/a-except-2005.ads
+++ b/gcc/ada/a-except-2005.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 1992-2012, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
-- --
-- This specification is derived from the Ada Reference Manual for use with --
-- GNAT. The copyright notice above, and the license provisions that follow --
@@ -51,12 +51,8 @@ with System.Standard_Library;
with System.Traceback_Entries;
package Ada.Exceptions is
- pragma Warnings (Off);
pragma Preelaborate_05;
- pragma Warnings (On);
- -- In accordance with Ada 2005 AI-362. The warnings pragmas are so that we
- -- can compile this using older compiler versions, which will ignore the
- -- pragma, which is fine for the bootstrap.
+ -- In accordance with Ada 2005 AI-362.
type Exception_Id is private;
pragma Preelaborable_Initialization (Exception_Id);
@@ -337,6 +333,15 @@ private
-- this, and it would not work right, because of the Msg and Tracebacks
-- fields which have unused entries not copied by Save_Occurrence.
+ function Get_Exception_Machine_Occurrence
+ (X : Exception_Occurrence) return System.Address;
+ pragma Export (Ada, Get_Exception_Machine_Occurrence,
+ "__gnat_get_exception_machine_occurrence");
+ -- Get the machine occurrence corresponding to an exception occurrence.
+ -- It is Null_Address if there is no machine occurrence (in runtimes that
+ -- doesn't use GCC mechanism) or if it has been lost (Save_Occurrence
+ -- doesn't save the machine occurrence).
+
function EO_To_String (X : Exception_Occurrence) return String;
function String_To_EO (S : String) return Exception_Occurrence;
pragma Stream_Convert (Exception_Occurrence, String_To_EO, EO_To_String);
diff --git a/gcc/ada/a-exexda.adb b/gcc/ada/a-exexda.adb
index 85b519a5e1e..a201551b702 100644
--- a/gcc/ada/a-exexda.adb
+++ b/gcc/ada/a-exexda.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2012, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -206,6 +206,11 @@ package body Exception_Data is
pragma Export
(Ada, Exception_Message_Length, "__gnat_exception_msg_len");
+ function Get_Executable_Load_Address return System.Address;
+ pragma Import (C, Get_Executable_Load_Address,
+ "__gnat_get_executable_load_address");
+ -- Get the load address of the executable, or Null_Address if not known
+
-------------------------
-- Append_Info_Address --
-------------------------
@@ -377,17 +382,31 @@ package body Exception_Data is
-- As for Basic_Exception_Information:
BETB_Header : constant String := "Call stack traceback locations:";
+ LDAD_Header : constant String := "Load address: ";
procedure Append_Info_Basic_Exception_Traceback
(X : Exception_Occurrence;
Info : in out String;
Ptr : in out Natural)
is
+ Load_Address : Address;
+
begin
if X.Num_Tracebacks = 0 then
return;
end if;
+ -- The executable load address line
+
+ Load_Address := Get_Executable_Load_Address;
+
+ if Load_Address /= Null_Address then
+ Append_Info_String (LDAD_Header, Info, Ptr);
+ Append_Info_Address (Load_Address, Info, Ptr);
+ Append_Info_NL (Info, Ptr);
+ end if;
+
+ -- The traceback lines
Append_Info_String (BETB_Header, Info, Ptr);
Append_Info_NL (Info, Ptr);
@@ -407,11 +426,12 @@ package body Exception_Data is
function Basic_Exception_Tback_Maxlength
(X : Exception_Occurrence) return Natural
is
- Space_Per_Traceback : constant := 2 + 16 + 1;
+ Space_Per_Address : constant := 2 + 16 + 1;
-- Space for "0x" + HHHHHHHHHHHHHHHH + " "
begin
- return BETB_Header'Length + 1 +
- X.Num_Tracebacks * Space_Per_Traceback + 1;
+ return
+ LDAD_Header'Length + Space_Per_Address + BETB_Header'Length + 1 +
+ X.Num_Tracebacks * Space_Per_Address + 1;
end Basic_Exception_Tback_Maxlength;
---------------------------------------
diff --git a/gcc/ada/a-exexpr-gcc.adb b/gcc/ada/a-exexpr-gcc.adb
index 178b7e375f6..a9d9e4b7733 100644
--- a/gcc/ada/a-exexpr-gcc.adb
+++ b/gcc/ada/a-exexpr-gcc.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2012, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -45,11 +45,10 @@ package body Exception_Propagation is
-- Entities to interface with the GCC runtime --
------------------------------------------------
- -- These come from "C++ ABI for Itanium: Exception handling", which is
- -- the reference for GCC.
+ -- These come from "C++ ABI for Itanium: Exception handling", which is the
+ -- reference for GCC.
- -- Return codes from the GCC runtime functions used to propagate
- -- an exception.
+ -- Return codes from GCC runtime functions used to propagate an exception
type Unwind_Reason_Code is
(URC_NO_REASON,
@@ -199,13 +198,14 @@ package body Exception_Propagation is
(GCC_Exception : not null GCC_Exception_Access);
pragma No_Return (Reraise_GCC_Exception);
pragma Export (C, Reraise_GCC_Exception, "__gnat_reraise_zcx");
- -- Called to implement raise without exception, ie reraise. Called
+ -- Called to implement raise without exception, ie reraise. Called
-- directly from gigi.
function Setup_Current_Excep
(GCC_Exception : not null GCC_Exception_Access) return EOA;
pragma Export (C, Setup_Current_Excep, "__gnat_setup_current_excep");
- -- Write Get_Current_Excep.all from GCC_Exception
+ -- Write Get_Current_Excep.all from GCC_Exception. Called by the
+ -- personality routine.
procedure Unhandled_Except_Handler
(GCC_Exception : not null GCC_Exception_Access);
@@ -225,9 +225,8 @@ package body Exception_Propagation is
UW_Argument : System.Address) return Unwind_Reason_Code;
pragma Import (C, CleanupUnwind_Handler,
"__gnat_cleanupunwind_handler");
- -- Hook called at each step of the forced unwinding we perform to
- -- trigger cleanups found during the propagation of an unhandled
- -- exception.
+ -- Hook called at each step of the forced unwinding we perform to trigger
+ -- cleanups found during the propagation of an unhandled exception.
-- GCC runtime functions used. These are C non-void functions, actually,
-- but we ignore the return values. See raise.c as to why we are using
@@ -243,6 +242,18 @@ package body Exception_Propagation is
UW_Argument : System.Address);
pragma Import (C, Unwind_ForcedUnwind, "__gnat_Unwind_ForcedUnwind");
+ procedure Set_Exception_Parameter
+ (Excep : EOA;
+ GCC_Exception : not null GCC_Exception_Access);
+ pragma Export
+ (C, Set_Exception_Parameter, "__gnat_set_exception_parameter");
+ -- Called inserted by gigi to initialize the exception parameter
+
+ procedure Set_Foreign_Occurrence (Excep : EOA; Mo : System.Address);
+ -- Utility routine to initialize occurrence Excep from a foreign exception
+ -- whose machine occurrence is Mo. The message is empty, the backtrace
+ -- is empty too and the exception identity is Foreign_Exception.
+
-- Hooks called when entering/leaving an exception handler for a given
-- occurrence, aimed at handling the stack of active occurrences. The
-- calls are generated by gigi in tree_transform/N_Exception_Handler.
@@ -270,8 +281,8 @@ package body Exception_Propagation is
function Language_For (E : Exception_Data_Ptr) return Character;
pragma Export (C, Language_For, "__gnat_language_for");
- function Import_Code_For (E : Exception_Data_Ptr) return Exception_Code;
- pragma Export (C, Import_Code_For, "__gnat_import_code_for");
+ function Foreign_Data_For (E : Exception_Data_Ptr) return Address;
+ pragma Export (C, Foreign_Data_For, "__gnat_foreign_data_for");
function EID_For (GNAT_Exception : not null GNAT_GCC_Exception_Access)
return Exception_Id;
@@ -282,18 +293,17 @@ package body Exception_Propagation is
---------------------------------------------------------------------------
-- Currently, these only have their address taken and compared so there is
- -- no real point having whole exception data blocks allocated. In any case
- -- the types should match what gigi and the personality routine expect.
- -- The initial value is an arbitrary value that will not exceed the range
- -- of Integer on 16-bit targets (such as AAMP).
+ -- no real point having whole exception data blocks allocated. Note that
+ -- there are corresponding declarations in gigi (trans.c) which must be
+ -- kept properly synchronized.
- Others_Value : constant Integer := 16#7FFF#;
+ Others_Value : constant Character := 'O';
pragma Export (C, Others_Value, "__gnat_others_value");
- All_Others_Value : constant Integer := 16#7FFF#;
+ All_Others_Value : constant Character := 'A';
pragma Export (C, All_Others_Value, "__gnat_all_others_value");
- Unhandled_Others_Value : constant Integer := 16#7FFF#;
+ Unhandled_Others_Value : constant Character := 'U';
pragma Export (C, Unhandled_Others_Value, "__gnat_unhandled_others_value");
-- Special choice (emitted by gigi) to catch and notify unhandled
-- exceptions on targets which always handle exceptions (such as SEH).
@@ -305,6 +315,7 @@ package body Exception_Propagation is
function Allocate_Occurrence return EOA is
Res : GNAT_GCC_Exception_Access;
+
begin
Res :=
new GNAT_GCC_Exception'
@@ -338,6 +349,23 @@ package body Exception_Propagation is
Free (Copy);
end GNAT_GCC_Exception_Cleanup;
+ ----------------------------
+ -- Set_Foreign_Occurrence --
+ ----------------------------
+
+ procedure Set_Foreign_Occurrence (Excep : EOA; Mo : System.Address) is
+ begin
+ Excep.all := (
+ Id => Foreign_Exception'Access,
+ Machine_Occurrence => Mo,
+ Msg => <>,
+ Msg_Length => 0,
+ Exception_Raised => True,
+ Pid => Local_Partition_ID,
+ Num_Tracebacks => 0,
+ Tracebacks => <>);
+ end Set_Foreign_Occurrence;
+
-------------------------
-- Setup_Current_Excep --
-------------------------
@@ -356,22 +384,16 @@ package body Exception_Propagation is
declare
GNAT_Occurrence : constant GNAT_GCC_Exception_Access :=
- To_GNAT_GCC_Exception (GCC_Exception);
+ To_GNAT_GCC_Exception (GCC_Exception);
begin
Excep.all := GNAT_Occurrence.Occurrence;
-
return GNAT_Occurrence.Occurrence'Access;
end;
- else
+ else
-- A default one
- Excep.Id := Foreign_Exception'Access;
- Excep.Machine_Occurrence := GCC_Exception.all'Address;
- Excep.Msg_Length := 0;
- Excep.Exception_Raised := True;
- Excep.Pid := Local_Partition_ID;
- Excep.Num_Tracebacks := 0;
+ Set_Foreign_Occurrence (Excep, GCC_Exception.all'Address);
return Excep;
end if;
@@ -411,6 +433,7 @@ package body Exception_Propagation is
is
begin
-- Simply propagate it
+
Propagate_GCC_Exception (GCC_Exception);
end Reraise_GCC_Exception;
@@ -446,9 +469,10 @@ package body Exception_Propagation is
-- unwinding hook calls Unhandled_Exception_Terminate when end of
-- stack is reached.
- Unwind_ForcedUnwind (GCC_Exception,
- CleanupUnwind_Handler'Address,
- System.Null_Address);
+ Unwind_ForcedUnwind
+ (GCC_Exception,
+ CleanupUnwind_Handler'Address,
+ System.Null_Address);
-- We get here in case of error. The debugger has been notified before
-- the second step above.
@@ -465,6 +489,35 @@ package body Exception_Propagation is
Propagate_GCC_Exception (To_GCC_Exception (Excep.Machine_Occurrence));
end Propagate_Exception;
+ -----------------------------
+ -- Set_Exception_Parameter --
+ -----------------------------
+
+ procedure Set_Exception_Parameter
+ (Excep : EOA;
+ GCC_Exception : not null GCC_Exception_Access)
+ is
+ begin
+ -- Setup the exception occurrence
+
+ if GCC_Exception.Class = GNAT_Exception_Class then
+
+ -- From the GCC exception
+
+ declare
+ GNAT_Occurrence : constant GNAT_GCC_Exception_Access :=
+ To_GNAT_GCC_Exception (GCC_Exception);
+ begin
+ Save_Occurrence (Excep.all, GNAT_Occurrence.Occurrence);
+ end;
+
+ else
+ -- A default one
+
+ Set_Foreign_Occurrence (Excep, GCC_Exception.all'Address);
+ end if;
+ end Set_Exception_Parameter;
+
------------------------------
-- Unhandled_Except_Handler --
------------------------------
@@ -489,16 +542,16 @@ package body Exception_Propagation is
return GNAT_Exception.Occurrence.Id;
end EID_For;
- ---------------------
- -- Import_Code_For --
- ---------------------
+ ----------------------
+ -- Foreign_Data_For --
+ ----------------------
- function Import_Code_For
- (E : SSL.Exception_Data_Ptr) return Exception_Code
+ function Foreign_Data_For
+ (E : SSL.Exception_Data_Ptr) return Address
is
begin
- return E.all.Import_Code;
- end Import_Code_For;
+ return E.Foreign_Data;
+ end Foreign_Data_For;
--------------------------
-- Is_Handled_By_Others --
diff --git a/gcc/ada/a-sequio.adb b/gcc/ada/a-sequio.adb
index 397a778f36f..b84252858bc 100644
--- a/gcc/ada/a-sequio.adb
+++ b/gcc/ada/a-sequio.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2012, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -34,13 +34,16 @@
-- in System.File_IO (for common file functions), or in System.Sequential_IO
-- (for specialized Sequential_IO functions)
-with Interfaces.C_Streams; use Interfaces.C_Streams;
+with Ada.Unchecked_Conversion;
+
with System;
+with System.Byte_Swapping;
with System.CRTL;
with System.File_Control_Block;
with System.File_IO;
with System.Storage_Elements;
-with Ada.Unchecked_Conversion;
+
+with Interfaces.C_Streams; use Interfaces.C_Streams;
package body Ada.Sequential_IO is
@@ -57,8 +60,26 @@ package body Ada.Sequential_IO is
function To_FCB is new Ada.Unchecked_Conversion (File_Mode, FCB.File_Mode);
function To_SIO is new Ada.Unchecked_Conversion (FCB.File_Mode, File_Mode);
+ use type System.Bit_Order;
use type System.CRTL.size_t;
+ procedure Byte_Swap (Siz : in out size_t);
+ -- Byte swap Siz
+
+ ---------------
+ -- Byte_Swap --
+ ---------------
+
+ procedure Byte_Swap (Siz : in out size_t) is
+ use System.Byte_Swapping;
+ begin
+ case Siz'Size is
+ when 32 => Siz := size_t (Bswap_32 (U32 (Siz)));
+ when 64 => Siz := size_t (Bswap_64 (U64 (Siz)));
+ when others => raise Program_Error;
+ end case;
+ end Byte_Swap;
+
-----------
-- Close --
-----------
@@ -170,6 +191,13 @@ package body Ada.Sequential_IO is
FIO.Read_Buf
(AP (File), Rsiz'Address, size_t'Size / System.Storage_Unit);
+ -- If item read has non-default scalar storage order, then the size
+ -- will have been written with that same order, so byte swap it.
+
+ if Element_Type'Scalar_Storage_Order /= System.Default_Bit_Order then
+ Byte_Swap (Rsiz);
+ end if;
+
-- For a type with discriminants, we have to read into a temporary
-- buffer if Item is constrained, to check that the discriminants
-- are correct.
@@ -252,6 +280,10 @@ package body Ada.Sequential_IO is
procedure Write (File : File_Type; Item : Element_Type) is
Siz : constant size_t := (Item'Size + SU - 1) / SU;
+ -- Size to be written, in native representation
+
+ Swapped_Siz : size_t := Siz;
+ -- Same, possibly byte swapped to account for Element_Type endianness
begin
FIO.Check_Write_Status (AP (File));
@@ -261,8 +293,15 @@ package body Ada.Sequential_IO is
if not Element_Type'Definite
or else Element_Type'Has_Discriminants
then
+ -- If item written has non-default scalar storage order, then the
+ -- size is written with that same order, so byte swap it.
+
+ if Element_Type'Scalar_Storage_Order /= System.Default_Bit_Order then
+ Byte_Swap (Swapped_Siz);
+ end if;
+
FIO.Write_Buf
- (AP (File), Siz'Address, size_t'Size / System.Storage_Unit);
+ (AP (File), Swapped_Siz'Address, size_t'Size / System.Storage_Unit);
end if;
FIO.Write_Buf (AP (File), Item'Address, Siz);
diff --git a/gcc/ada/a-tienau.adb b/gcc/ada/a-tienau.adb
index 5498ca4f55d..6ee9bbadc60 100644
--- a/gcc/ada/a-tienau.adb
+++ b/gcc/ada/a-tienau.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2011, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -126,19 +126,19 @@ package body Ada.Text_IO.Enumeration_Aux is
Actual_Width : constant Count := Count'Max (Count (Width), Item'Length);
begin
- -- Deal with limited line length
+ -- Deal with limited line length of output file
- if Line_Length /= 0 then
+ if Line_Length (File) /= 0 then
-- If actual width exceeds line length, raise Layout_Error
- if Actual_Width > Line_Length then
+ if Actual_Width > Line_Length (File) then
raise Layout_Error;
end if;
-- If full width cannot fit on current line move to new line
- if Actual_Width + (Col - 1) > Line_Length then
+ if Actual_Width + (Col (File) - 1) > Line_Length (File) then
New_Line (File);
end if;
end if;
diff --git a/gcc/ada/a-wichha.adb b/gcc/ada/a-wichha.adb
index 3909fcdacc0..6692cbf445f 100644
--- a/gcc/ada/a-wichha.adb
+++ b/gcc/ada/a-wichha.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 2010-2012, Free Software Foundation, Inc. --
+-- Copyright (C) 2010-2013, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -33,6 +33,11 @@ with Ada.Wide_Characters.Unicode; use Ada.Wide_Characters.Unicode;
package body Ada.Wide_Characters.Handling is
+ function Character_Set_Version return String is
+ begin
+ return "Unicode 6.2";
+ end Character_Set_Version;
+
---------------------
-- Is_Alphanumeric --
---------------------
@@ -108,18 +113,18 @@ package body Ada.Wide_Characters.Handling is
function Is_Mark (Item : Wide_Character) return Boolean
renames Ada.Wide_Characters.Unicode.Is_Mark;
- --------------
- -- Is_Other --
- --------------
+ ---------------------
+ -- Is_Other_Format --
+ ---------------------
- function Is_Other (Item : Wide_Character) return Boolean
+ function Is_Other_Format (Item : Wide_Character) return Boolean
renames Ada.Wide_Characters.Unicode.Is_Other;
- --------------------
- -- Is_Punctuation --
- --------------------
+ ------------------------------
+ -- Is_Punctuation_Connector --
+ ------------------------------
- function Is_Punctuation (Item : Wide_Character) return Boolean
+ function Is_Punctuation_Connector (Item : Wide_Character) return Boolean
renames Ada.Wide_Characters.Unicode.Is_Punctuation;
--------------
diff --git a/gcc/ada/a-wichha.ads b/gcc/ada/a-wichha.ads
index a9cff259f7a..583308ec6a0 100644
--- a/gcc/ada/a-wichha.ads
+++ b/gcc/ada/a-wichha.ads
@@ -15,10 +15,12 @@
package Ada.Wide_Characters.Handling is
pragma Pure;
- -- This package is clearly intended to be Pure, by analogy with the
- -- base Ada.Characters.Handling package. The version in the RM does
- -- not yet have this pragma, but that is a clear omission. This will
- -- be fixed in a future version of AI05-0266-1.
+
+ function Character_Set_Version return String;
+ pragma Inline (Character_Set_Version);
+ -- Returns an implementation-defined identifier that identifies the version
+ -- of the character set standard that is used for categorizing characters
+ -- by the implementation. For GNAT this is "Unicode v.v".
function Is_Control (Item : Wide_Character) return Boolean;
pragma Inline (Is_Control);
@@ -78,13 +80,13 @@ package Ada.Wide_Characters.Handling is
-- Returns True if the Wide_Character designated by Item is categorized as
-- mark_non_spacing or mark_spacing_combining, otherwise returns false.
- function Is_Other (Item : Wide_Character) return Boolean;
- pragma Inline (Is_Other);
+ function Is_Other_Format (Item : Wide_Character) return Boolean;
+ pragma Inline (Is_Other_Format);
-- Returns True if the Wide_Character designated by Item is categorized as
-- other_format, otherwise returns false.
- function Is_Punctuation (Item : Wide_Character) return Boolean;
- pragma Inline (Is_Punctuation);
+ function Is_Punctuation_Connector (Item : Wide_Character) return Boolean;
+ pragma Inline (Is_Punctuation_Connector);
-- Returns True if the Wide_Character designated by Item is categorized as
-- punctuation_connector, otherwise returns false.
diff --git a/gcc/ada/a-zchhan.adb b/gcc/ada/a-zchhan.adb
index 483cfd9ec23..54db3ba8130 100644
--- a/gcc/ada/a-zchhan.adb
+++ b/gcc/ada/a-zchhan.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 2010-2012, Free Software Foundation, Inc. --
+-- Copyright (C) 2010-2013, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -108,18 +108,19 @@ package body Ada.Wide_Wide_Characters.Handling is
function Is_Mark (Item : Wide_Wide_Character) return Boolean
renames Ada.Wide_Wide_Characters.Unicode.Is_Mark;
- --------------
- -- Is_Other --
- --------------
+ ---------------------
+ -- Is_Other_Format --
+ ---------------------
- function Is_Other (Item : Wide_Wide_Character) return Boolean
+ function Is_Other_Format (Item : Wide_Wide_Character) return Boolean
renames Ada.Wide_Wide_Characters.Unicode.Is_Other;
- --------------------
- -- Is_Punctuation --
- --------------------
+ ------------------------------
+ -- Is_Punctuation_Connector --
+ ------------------------------
- function Is_Punctuation (Item : Wide_Wide_Character) return Boolean
+ function Is_Punctuation_Connector
+ (Item : Wide_Wide_Character) return Boolean
renames Ada.Wide_Wide_Characters.Unicode.Is_Punctuation;
--------------
diff --git a/gcc/ada/a-zchhan.ads b/gcc/ada/a-zchhan.ads
index 4c78dcd070c..354452b49f5 100644
--- a/gcc/ada/a-zchhan.ads
+++ b/gcc/ada/a-zchhan.ads
@@ -82,13 +82,14 @@ package Ada.Wide_Wide_Characters.Handling is
-- categorized as mark_non_spacing or mark_spacing_combining, otherwise
-- returns false.
- function Is_Other (Item : Wide_Wide_Character) return Boolean;
- pragma Inline (Is_Other);
+ function Is_Other_Format (Item : Wide_Wide_Character) return Boolean;
+ pragma Inline (Is_Other_Format);
-- Returns True if the Wide_Wide_Character designated by Item is
-- categorized as other_format, otherwise returns false.
- function Is_Punctuation (Item : Wide_Wide_Character) return Boolean;
- pragma Inline (Is_Punctuation);
+ function Is_Punctuation_Connector
+ (Item : Wide_Wide_Character) return Boolean;
+ pragma Inline (Is_Punctuation_Connector);
-- Returns True if the Wide_Wide_Character designated by Item is
-- categorized as punctuation_connector, otherwise returns false.
diff --git a/gcc/ada/adaint.c b/gcc/ada/adaint.c
index f76edb73995..3cabec95077 100644
--- a/gcc/ada/adaint.c
+++ b/gcc/ada/adaint.c
@@ -158,9 +158,9 @@ UINT CurrentCodePage;
#define GCC_RESOURCE_H
#include <sys/wait.h>
#elif defined (__nucleus__)
-/* No wait() or waitpid() calls available */
+/* No wait() or waitpid() calls available. */
#else
-/* Default case */
+/* Default case. */
#include <sys/wait.h>
#endif
@@ -182,10 +182,12 @@ UINT CurrentCodePage;
/* Use native 64-bit arithmetic. */
#define unix_time_to_vms(X,Y) \
- { unsigned long long reftime, tmptime = (X); \
+ { \
+ unsigned long long reftime, tmptime = (X); \
$DESCRIPTOR (unixtime,"1-JAN-1970 0:00:00.00"); \
- SYS$BINTIM (&unixtime, &reftime); \
- Y = tmptime * 10000000 + reftime; }
+ SYS$BINTIM (&unixtime, &reftime); \
+ Y = tmptime * 10000000 + reftime; \
+ }
/* descrip.h doesn't have everything ... */
typedef struct fibdef* __fibdef_ptr32 __attribute__ (( mode (SI) ));
@@ -213,8 +215,8 @@ struct vstring
#define SYI$_ACTIVECPU_CNT 0x111e
extern int LIB$GETSYI (int *, unsigned int *);
-extern unsigned int LIB$CALLG_64
- ( unsigned long long argument_list [], int (*user_procedure)(void));
+extern unsigned int LIB$CALLG_64 (unsigned long long argument_list [],
+ int (*user_procedure)(void));
#else
#include <utime.h>
@@ -266,7 +268,7 @@ extern unsigned int LIB$CALLG_64
#define DIR_SEPARATOR '/'
#endif
-/* Check for cross-compilation */
+/* Check for cross-compilation. */
#if defined (CROSS_COMPILE) || defined (CROSS_DIRECTORY_STRUCTURE)
#define IS_CROSS 1
int __gnat_is_cross_compiler = 1;
@@ -382,13 +384,14 @@ to_ptr32 (char **ptr64)
int argc;
__char_ptr_char_ptr32 short_argv;
- for (argc=0; ptr64[argc]; argc++);
+ for (argc = 0; ptr64[argc]; argc++)
+ ;
- /* Reallocate argv with 32 bit pointers. */
+ /* Reallocate argv with 32 bit pointers. */
short_argv = (__char_ptr_char_ptr32) decc$malloc
(sizeof (__char_ptr32) * (argc + 1));
- for (argc=0; ptr64[argc]; argc++)
+ for (argc = 0; ptr64[argc]; argc++)
short_argv[argc] = (__char_ptr32) decc$strdup (ptr64[argc]);
short_argv[argc] = (__char_ptr32) 0;
@@ -405,8 +408,7 @@ static const char ATTR_UNSET = 127;
/* Reset the file attributes as if no system call had been performed */
void
-__gnat_reset_attributes
- (struct file_attributes* attr)
+__gnat_reset_attributes (struct file_attributes* attr)
{
attr->exists = ATTR_UNSET;
@@ -423,8 +425,7 @@ __gnat_reset_attributes
}
OS_Time
-__gnat_current_time
- (void)
+__gnat_current_time (void)
{
time_t res = time (NULL);
return (OS_Time) res;
@@ -435,8 +436,7 @@ __gnat_current_time
long. */
void
-__gnat_current_time_string
- (char *result)
+__gnat_current_time_string (char *result)
{
const char *format = "%Y-%m-%d %H:%M:%S";
/* Format string necessary to describe the ISO 8601 format */
@@ -455,14 +455,8 @@ __gnat_current_time_string
}
void
-__gnat_to_gm_time
- (OS_Time *p_time,
- int *p_year,
- int *p_month,
- int *p_day,
- int *p_hours,
- int *p_mins,
- int *p_secs)
+__gnat_to_gm_time (OS_Time *p_time, int *p_year, int *p_month, int *p_day,
+ int *p_hours, int *p_mins, int *p_secs)
{
struct tm *res;
time_t time = (time_t) *p_time;
@@ -1877,9 +1871,8 @@ __gnat_stat (char *name, GNAT_STRUCT_STAT *statbuf)
int
__gnat_file_exists_attr (char* name, struct file_attributes* attr)
{
- if (attr->exists == ATTR_UNSET) {
- __gnat_stat_to_attr (-1, name, attr);
- }
+ if (attr->exists == ATTR_UNSET)
+ __gnat_stat_to_attr (-1, name, attr);
return attr->exists;
}
@@ -1934,9 +1927,8 @@ __gnat_is_absolute_path (char *name, int length)
int
__gnat_is_regular_file_attr (char* name, struct file_attributes* attr)
{
- if (attr->regular == ATTR_UNSET) {
- __gnat_stat_to_attr (-1, name, attr);
- }
+ if (attr->regular == ATTR_UNSET)
+ __gnat_stat_to_attr (-1, name, attr);
return attr->regular;
}
@@ -1945,6 +1937,7 @@ int
__gnat_is_regular_file (char *name)
{
struct file_attributes attr;
+
__gnat_reset_attributes (&attr);
return __gnat_is_regular_file_attr (name, &attr);
}
@@ -1952,9 +1945,8 @@ __gnat_is_regular_file (char *name)
int
__gnat_is_directory_attr (char* name, struct file_attributes* attr)
{
- if (attr->directory == ATTR_UNSET) {
- __gnat_stat_to_attr (-1, name, attr);
- }
+ if (attr->directory == ATTR_UNSET)
+ __gnat_stat_to_attr (-1, name, attr);
return attr->directory;
}
@@ -1963,6 +1955,7 @@ int
__gnat_is_directory (char *name)
{
struct file_attributes attr;
+
__gnat_reset_attributes (&attr);
return __gnat_is_directory_attr (name, &attr);
}
@@ -1994,7 +1987,8 @@ GetDriveTypeFromPath (TCHAR *wfullpath)
/* Is this a relative path, if so get current drive type. */
if (wpath[0] != _T('\\') ||
- (_tcslen (wpath) > 2 && wpath[0] == _T('\\') && wpath[1] != _T('\\')))
+ (_tcslen (wpath) > 2 && wpath[0] == _T('\\')
+ && wpath[1] != _T('\\')))
return GetDriveType (NULL);
UINT result = GetDriveType (wpath);
@@ -2012,7 +2006,8 @@ GetDriveTypeFromPath (TCHAR *wfullpath)
LPTSTR b = _tcschr (p, _T('\\'));
if (b != NULL)
- { /* logical drive \\.\c\dir\file */
+ {
+ /* logical drive \\.\c\dir\file */
*b++ = _T(':');
*b++ = _T('\\');
*b = _T('\0');
@@ -2027,12 +2022,11 @@ GetDriveTypeFromPath (TCHAR *wfullpath)
}
}
-/* This MingW section contains code to work with ACL. */
+/* This MingW section contains code to work with ACL. */
static int
-__gnat_check_OWNER_ACL
-(TCHAR *wname,
- DWORD CheckAccessDesired,
- GENERIC_MAPPING CheckGenericMapping)
+__gnat_check_OWNER_ACL (TCHAR *wname,
+ DWORD CheckAccessDesired,
+ GENERIC_MAPPING CheckGenericMapping)
{
DWORD dwAccessDesired, dwAccessAllowed;
PRIVILEGE_SET PrivilegeSet;
@@ -2051,7 +2045,7 @@ __gnat_check_OWNER_ACL
(GetProcessHeap (), HEAP_ZERO_MEMORY, nLength)) == NULL)
return 0;
- /* Obtain the security descriptor. */
+ /* Obtain the security descriptor. */
if (!GetFileSecurity
(wname, OWNER_SECURITY_INFORMATION |
@@ -2099,10 +2093,9 @@ __gnat_check_OWNER_ACL
}
static void
-__gnat_set_OWNER_ACL
-(TCHAR *wname,
- DWORD AccessMode,
- DWORD AccessPermissions)
+__gnat_set_OWNER_ACL (TCHAR *wname,
+ DWORD AccessMode,
+ DWORD AccessPermissions)
{
PACL pOldDACL = NULL;
PACL pNewDACL = NULL;
@@ -2160,26 +2153,27 @@ __gnat_can_use_acl (TCHAR *wname)
int
__gnat_is_readable_file_attr (char* name, struct file_attributes* attr)
{
- if (attr->readable == ATTR_UNSET) {
+ if (attr->readable == ATTR_UNSET)
+ {
#if defined (_WIN32) && !defined (RTX)
- TCHAR wname [GNAT_MAX_PATH_LEN + 2];
- GENERIC_MAPPING GenericMapping;
+ TCHAR wname [GNAT_MAX_PATH_LEN + 2];
+ GENERIC_MAPPING GenericMapping;
- S2WSC (wname, name, GNAT_MAX_PATH_LEN + 2);
+ S2WSC (wname, name, GNAT_MAX_PATH_LEN + 2);
- if (__gnat_can_use_acl (wname))
- {
- ZeroMemory (&GenericMapping, sizeof (GENERIC_MAPPING));
- GenericMapping.GenericRead = GENERIC_READ;
- attr->readable =
- __gnat_check_OWNER_ACL (wname, FILE_READ_DATA, GenericMapping);
- }
- else
- attr->readable = GetFileAttributes (wname) != INVALID_FILE_ATTRIBUTES;
+ if (__gnat_can_use_acl (wname))
+ {
+ ZeroMemory (&GenericMapping, sizeof (GENERIC_MAPPING));
+ GenericMapping.GenericRead = GENERIC_READ;
+ attr->readable =
+ __gnat_check_OWNER_ACL (wname, FILE_READ_DATA, GenericMapping);
+ }
+ else
+ attr->readable = GetFileAttributes (wname) != INVALID_FILE_ATTRIBUTES;
#else
- __gnat_stat_to_attr (-1, name, attr);
+ __gnat_stat_to_attr (-1, name, attr);
#endif
- }
+ }
return attr->readable;
}
@@ -2188,6 +2182,7 @@ int
__gnat_is_readable_file (char *name)
{
struct file_attributes attr;
+
__gnat_reset_attributes (&attr);
return __gnat_is_readable_file_attr (name, &attr);
}
@@ -2195,29 +2190,31 @@ __gnat_is_readable_file (char *name)
int
__gnat_is_writable_file_attr (char* name, struct file_attributes* attr)
{
- if (attr->writable == ATTR_UNSET) {
+ if (attr->writable == ATTR_UNSET)
+ {
#if defined (_WIN32) && !defined (RTX)
- TCHAR wname [GNAT_MAX_PATH_LEN + 2];
- GENERIC_MAPPING GenericMapping;
+ TCHAR wname [GNAT_MAX_PATH_LEN + 2];
+ GENERIC_MAPPING GenericMapping;
- S2WSC (wname, name, GNAT_MAX_PATH_LEN + 2);
+ S2WSC (wname, name, GNAT_MAX_PATH_LEN + 2);
- if (__gnat_can_use_acl (wname))
- {
- ZeroMemory (&GenericMapping, sizeof (GENERIC_MAPPING));
- GenericMapping.GenericWrite = GENERIC_WRITE;
+ if (__gnat_can_use_acl (wname))
+ {
+ ZeroMemory (&GenericMapping, sizeof (GENERIC_MAPPING));
+ GenericMapping.GenericWrite = GENERIC_WRITE;
- attr->writable = __gnat_check_OWNER_ACL
+ attr->writable = __gnat_check_OWNER_ACL
(wname, FILE_WRITE_DATA | FILE_APPEND_DATA, GenericMapping)
&& !(GetFileAttributes (wname) & FILE_ATTRIBUTE_READONLY);
- }
- else
- attr->writable = !(GetFileAttributes (wname) & FILE_ATTRIBUTE_READONLY);
+ }
+ else
+ attr->writable =
+ !(GetFileAttributes (wname) & FILE_ATTRIBUTE_READONLY);
#else
- __gnat_stat_to_attr (-1, name, attr);
+ __gnat_stat_to_attr (-1, name, attr);
#endif
- }
+ }
return attr->writable;
}
@@ -2226,6 +2223,7 @@ int
__gnat_is_writable_file (char *name)
{
struct file_attributes attr;
+
__gnat_reset_attributes (&attr);
return __gnat_is_writable_file_attr (name, &attr);
}
@@ -2233,36 +2231,39 @@ __gnat_is_writable_file (char *name)
int
__gnat_is_executable_file_attr (char* name, struct file_attributes* attr)
{
- if (attr->executable == ATTR_UNSET) {
+ if (attr->executable == ATTR_UNSET)
+ {
#if defined (_WIN32) && !defined (RTX)
- TCHAR wname [GNAT_MAX_PATH_LEN + 2];
- GENERIC_MAPPING GenericMapping;
+ TCHAR wname [GNAT_MAX_PATH_LEN + 2];
+ GENERIC_MAPPING GenericMapping;
- S2WSC (wname, name, GNAT_MAX_PATH_LEN + 2);
+ S2WSC (wname, name, GNAT_MAX_PATH_LEN + 2);
- if (__gnat_can_use_acl (wname))
- {
- ZeroMemory (&GenericMapping, sizeof (GENERIC_MAPPING));
- GenericMapping.GenericExecute = GENERIC_EXECUTE;
+ if (__gnat_can_use_acl (wname))
+ {
+ ZeroMemory (&GenericMapping, sizeof (GENERIC_MAPPING));
+ GenericMapping.GenericExecute = GENERIC_EXECUTE;
- attr->executable =
- __gnat_check_OWNER_ACL (wname, FILE_EXECUTE, GenericMapping);
- }
- else
- {
- TCHAR *l, *last = _tcsstr(wname, _T(".exe"));
+ attr->executable =
+ __gnat_check_OWNER_ACL (wname, FILE_EXECUTE, GenericMapping);
+ }
+ else
+ {
+ TCHAR *l, *last = _tcsstr(wname, _T(".exe"));
- /* look for last .exe */
- if (last)
- while ((l = _tcsstr(last+1, _T(".exe")))) last = l;
+ /* look for last .exe */
+ if (last)
+ while ((l = _tcsstr(last+1, _T(".exe"))))
+ last = l;
- attr->executable = GetFileAttributes (wname) != INVALID_FILE_ATTRIBUTES
- && (last - wname) == (int) (_tcslen (wname) - 4);
- }
+ attr->executable =
+ GetFileAttributes (wname) != INVALID_FILE_ATTRIBUTES
+ && (last - wname) == (int) (_tcslen (wname) - 4);
+ }
#else
- __gnat_stat_to_attr (-1, name, attr);
+ __gnat_stat_to_attr (-1, name, attr);
#endif
- }
+ }
return attr->regular && attr->executable;
}
@@ -2271,6 +2272,7 @@ int
__gnat_is_executable_file (char *name)
{
struct file_attributes attr;
+
__gnat_reset_attributes (&attr);
return __gnat_is_executable_file_attr (name, &attr);
}
@@ -2399,19 +2401,20 @@ int
__gnat_is_symbolic_link_attr (char* name ATTRIBUTE_UNUSED,
struct file_attributes* attr)
{
- if (attr->symbolic_link == ATTR_UNSET) {
+ if (attr->symbolic_link == ATTR_UNSET)
+ {
#if defined (__vxworks) || defined (__nucleus__)
- attr->symbolic_link = 0;
+ attr->symbolic_link = 0;
#elif defined (_AIX) || defined (__APPLE__) || defined (__unix__)
- int ret;
- GNAT_STRUCT_STAT statbuf;
- ret = GNAT_LSTAT (name, &statbuf);
- attr->symbolic_link = (!ret && S_ISLNK (statbuf.st_mode));
+ int ret;
+ GNAT_STRUCT_STAT statbuf;
+ ret = GNAT_LSTAT (name, &statbuf);
+ attr->symbolic_link = (!ret && S_ISLNK (statbuf.st_mode));
#else
- attr->symbolic_link = 0;
+ attr->symbolic_link = 0;
#endif
- }
+ }
return attr->symbolic_link;
}
@@ -2419,9 +2422,9 @@ int
__gnat_is_symbolic_link (char *name ATTRIBUTE_UNUSED)
{
struct file_attributes attr;
+
__gnat_reset_attributes (&attr);
return __gnat_is_symbolic_link_attr (name, &attr);
-
}
#if defined (sun) && defined (__SVR4)
@@ -2576,7 +2579,9 @@ __gnat_number_of_cpus (void)
for locking and unlocking tasks since we do not support multiple
threads on this configuration (Cert run time on native Windows). */
-void dummy (void) {}
+static void dummy (void)
+{
+}
void (*Lock_Task) () = &dummy;
void (*Unlock_Task) () = &dummy;
@@ -2836,8 +2841,8 @@ __gnat_os_exit (int status)
/* Locate file on path, that matches a predicate */
char *
-__gnat_locate_file_with_predicate
- (char *file_name, char *path_val, int (*predicate)(char*))
+__gnat_locate_file_with_predicate (char *file_name, char *path_val,
+ int (*predicate)(char *))
{
char *ptr;
char *file_path = (char *) alloca (strlen (file_name) + 1);
@@ -3118,7 +3123,7 @@ __gnat_to_canonical_file_list_init (char *filespec, int onlydirs)
/* Return the next filespec in the list. */
char *
-__gnat_to_canonical_file_list_next ()
+__gnat_to_canonical_file_list_next (void)
{
return new_canonical_filelist[new_canonical_filelist_index++];
}
@@ -3126,7 +3131,7 @@ __gnat_to_canonical_file_list_next ()
/* Free storage used in the wildcard expansion. */
void
-__gnat_to_canonical_file_list_free ()
+__gnat_to_canonical_file_list_free (void)
{
int i;
@@ -3144,7 +3149,7 @@ __gnat_to_canonical_file_list_free ()
/* The functional equivalent of decc$translate_vms routine.
Designed to produce the same output, but is protected against
malformed paths (original version ACCVIOs in this case) and
- does not require VMS-specific DECC RTL */
+ does not require VMS-specific DECC RTL. */
#define NAM$C_MAXRSS 1024
@@ -3161,13 +3166,13 @@ __gnat_translate_vms (char *src)
srcendpos = strchr (src, '\0');
retpos = retbuf;
- /* Look for the node and/or device in front of the path */
+ /* Look for the node and/or device in front of the path. */
pos1 = src;
pos2 = strchr (pos1, ':');
if (pos2 && (pos2 < srcendpos) && (*(pos2 + 1) == ':'))
{
- /* There is a node name. "node_name::" becomes "node_name!" */
+ /* There is a node name. "node_name::" becomes "node_name!". */
disp = pos2 - pos1;
strncpy (retbuf, pos1, disp);
retpos [disp] = '!';
@@ -3178,7 +3183,7 @@ __gnat_translate_vms (char *src)
if (pos2)
{
- /* There is a device name. "dev_name:" becomes "/dev_name/" */
+ /* There is a device name. "dev_name:" becomes "/dev_name/". */
*(retpos++) = '/';
disp = pos2 - pos1;
strncpy (retpos, pos1, disp);
@@ -3188,7 +3193,7 @@ __gnat_translate_vms (char *src)
}
else
/* No explicit device; we must look ahead and prepend /sys$disk/ if
- the path is absolute */
+ the path is absolute. */
if ((*pos1 == '[' || *pos1 == '<') && (pos1 < srcendpos)
&& !strchr (".-]>", *(pos1 + 1)))
{
@@ -3196,14 +3201,14 @@ __gnat_translate_vms (char *src)
retpos += 10;
}
- /* Process the path part */
+ /* Process the path part. */
while (*pos1 == '[' || *pos1 == '<')
{
path_present++;
pos1++;
if (*pos1 == ']' || *pos1 == '>')
{
- /* Special case, [] translates to '.' */
+ /* Special case, [] translates to '.'. */
*(retpos++) = '.';
pos1++;
}
@@ -3211,7 +3216,7 @@ __gnat_translate_vms (char *src)
{
/* '[000000' means root dir. It can be present in the middle of
the path due to expansion of logical devices, in which case
- we skip it */
+ we skip it. */
if (!strncmp (pos1, "000000", 6) && path_present > 1 &&
(*(pos1 + 6) == ']' || *(pos1 + 6) == '>' || *(pos1 + 6) == '.'))
{
@@ -3220,24 +3225,27 @@ __gnat_translate_vms (char *src)
}
else if (*pos1 == '.')
{
- /* Relative path */
+ /* Relative path. */
*(retpos++) = '.';
}
- /* There is a qualified path */
+ /* There is a qualified path. */
while (*pos1 && *pos1 != ']' && *pos1 != '>')
{
switch (*pos1)
{
case '.':
- /* '.' is used to separate directories. Replace it with '/' but
- only if there isn't already '/' just before */
+ /* '.' is used to separate directories. Replace it with '/'
+ but only if there isn't already '/' just before. */
if (*(retpos - 1) != '/')
*(retpos++) = '/';
pos1++;
- if (pos1 + 1 < srcendpos && *pos1 == '.' && *(pos1 + 1) == '.')
+ if (pos1 + 1 < srcendpos
+ && *pos1 == '.'
+ && *(pos1 + 1) == '.')
{
- /* ellipsis refers to entire subtree; replace with '**' */
+ /* Ellipsis refers to entire subtree; replace
+ with '**'. */
*(retpos++) = '*';
*(retpos++) = '*';
*(retpos++) = '/';
@@ -3245,8 +3253,8 @@ __gnat_translate_vms (char *src)
}
break;
case '-' :
- /* When after '.' '[' '<' is equivalent to Unix ".." but there
- may be several in a row */
+ /* When after '.' '[' '<' is equivalent to Unix ".." but
+ there may be several in a row. */
if (*(pos1 - 1) == '.' || *(pos1 - 1) == '[' ||
*(pos1 - 1) == '<')
{
@@ -3260,7 +3268,7 @@ __gnat_translate_vms (char *src)
retpos--;
break;
}
- /* otherwise fall through to default */
+ /* Otherwise fall through to default. */
default:
*(retpos++) = *(pos1++);
}
@@ -3500,7 +3508,7 @@ __gnat_to_host_file_spec (char *filespec)
}
void
-__gnat_adjust_os_resource_limits ()
+__gnat_adjust_os_resource_limits (void)
{
SYS$ADJWSL (131072, 0);
}
@@ -3510,8 +3518,8 @@ __gnat_adjust_os_resource_limits ()
/* Dummy functions for Osint import for non-VMS systems. */
int
-__gnat_to_canonical_file_list_init
- (char *dirspec ATTRIBUTE_UNUSED, int onlydirs ATTRIBUTE_UNUSED)
+__gnat_to_canonical_file_list_init (char *dirspec ATTRIBUTE_UNUSED,
+ int onlydirs ATTRIBUTE_UNUSED)
{
return 0;
}
@@ -3567,7 +3575,7 @@ __gnat_adjust_os_resource_limits (void)
#if defined (__mips_vxworks)
int
-_flush_cache()
+_flush_cache (void)
{
CACHE_USER_FLUSH (0, ENTIRE_CACHE);
}
@@ -3811,9 +3819,9 @@ __gnat_sals_init_using_constructors (void)
we introduce an intermediate procedure to link against the corresponding
one in each situation. */
-extern void GetTimeAsFileTime(LPFILETIME pTime);
+extern void GetTimeAsFileTime (LPFILETIME pTime);
-void GetTimeAsFileTime(LPFILETIME pTime)
+void GetTimeAsFileTime (LPFILETIME pTime)
{
#ifdef RTSS
RtGetRtssTimeAsFileTime (pTime); /* RTSS interface */
@@ -3829,15 +3837,18 @@ void GetTimeAsFileTime(LPFILETIME pTime)
extern void __main (void);
-void __main (void) {}
-#endif
-#endif
+void __main (void)
+{
+}
+#endif /* RTSS */
+#endif /* RTX */
#if defined (__ANDROID__)
#include <pthread.h>
-void *__gnat_lwp_self (void)
+void *
+__gnat_lwp_self (void)
{
return (void *) pthread_self ();
}
@@ -3847,7 +3858,8 @@ void *__gnat_lwp_self (void)
thread. We need to do a system call in order to retrieve this
information. */
#include <sys/syscall.h>
-void *__gnat_lwp_self (void)
+void *
+__gnat_lwp_self (void)
{
return (void *) syscall (__NR_gettid);
}
@@ -3862,65 +3874,103 @@ void *__gnat_lwp_self (void)
/* Dynamic cpu sets */
-cpu_set_t *__gnat_cpu_alloc (size_t count)
+cpu_set_t *
+__gnat_cpu_alloc (size_t count)
{
return CPU_ALLOC (count);
}
-size_t __gnat_cpu_alloc_size (size_t count)
+size_t
+__gnat_cpu_alloc_size (size_t count)
{
return CPU_ALLOC_SIZE (count);
}
-void __gnat_cpu_free (cpu_set_t *set)
+void
+__gnat_cpu_free (cpu_set_t *set)
{
CPU_FREE (set);
}
-void __gnat_cpu_zero (size_t count, cpu_set_t *set)
+void
+__gnat_cpu_zero (size_t count, cpu_set_t *set)
{
CPU_ZERO_S (count, set);
}
-void __gnat_cpu_set (int cpu, size_t count, cpu_set_t *set)
+void
+__gnat_cpu_set (int cpu, size_t count, cpu_set_t *set)
{
/* Ada handles CPU numbers starting from 1, while C identifies the first
CPU by a 0, so we need to adjust. */
CPU_SET_S (cpu - 1, count, set);
}
-#else
+#else /* !CPU_ALLOC */
/* Static cpu sets */
-cpu_set_t *__gnat_cpu_alloc (size_t count ATTRIBUTE_UNUSED)
+cpu_set_t *
+__gnat_cpu_alloc (size_t count ATTRIBUTE_UNUSED)
{
return (cpu_set_t *) xmalloc (sizeof (cpu_set_t));
}
-size_t __gnat_cpu_alloc_size (size_t count ATTRIBUTE_UNUSED)
+size_t
+__gnat_cpu_alloc_size (size_t count ATTRIBUTE_UNUSED)
{
return sizeof (cpu_set_t);
}
-void __gnat_cpu_free (cpu_set_t *set)
+void
+__gnat_cpu_free (cpu_set_t *set)
{
free (set);
}
-void __gnat_cpu_zero (size_t count ATTRIBUTE_UNUSED, cpu_set_t *set)
+void
+__gnat_cpu_zero (size_t count ATTRIBUTE_UNUSED, cpu_set_t *set)
{
CPU_ZERO (set);
}
-void __gnat_cpu_set (int cpu, size_t count ATTRIBUTE_UNUSED, cpu_set_t *set)
+void
+__gnat_cpu_set (int cpu, size_t count ATTRIBUTE_UNUSED, cpu_set_t *set)
{
/* Ada handles CPU numbers starting from 1, while C identifies the first
CPU by a 0, so we need to adjust. */
CPU_SET (cpu - 1, set);
}
+#endif /* !CPU_ALLOC */
+#endif /* linux */
+
+/* Return the load address of the executable, or 0 if not known. In the
+ specific case of error, (void *)-1 can be returned. Beware: this unit may
+ be in a shared library. As low-level units are needed, we allow #include
+ here. */
+
+#if defined (__APPLE__)
+#include <mach-o/dyld.h>
+#elif 0 && defined (__linux__)
+#include <link.h>
#endif
+
+const void *
+__gnat_get_executable_load_address (void)
+{
+#if defined (__APPLE__)
+ return _dyld_get_image_header (0);
+
+#elif 0 && defined (__linux__)
+ /* Currently disabled as it needs at least -ldl. */
+ struct link_map *map = _r_debug.r_map;
+
+ return (const void *)map->l_addr;
+
+#else
+ return NULL;
#endif
+}
#ifdef __cplusplus
}
diff --git a/gcc/ada/adaint.h b/gcc/ada/adaint.h
index 78af57c9dae..554d848f736 100644
--- a/gcc/ada/adaint.h
+++ b/gcc/ada/adaint.h
@@ -287,6 +287,8 @@ extern int get_gcc_version (void);
extern int __gnat_binder_supports_auto_init (void);
extern int __gnat_sals_init_using_constructors (void);
+extern const void * __gnat_get_executable_load_address (void);
+
#ifdef __cplusplus
}
#endif
diff --git a/gcc/ada/ali.adb b/gcc/ada/ali.adb
index 6c2f8187a92..aff6740f405 100644
--- a/gcc/ada/ali.adb
+++ b/gcc/ada/ali.adb
@@ -186,9 +186,13 @@ package body ALI is
function Getc return Character;
-- Get next character, bumping P past the character obtained
- function Get_File_Name (Lower : Boolean := False) return File_Name_Type;
+ function Get_File_Name
+ (Lower : Boolean := False;
+ May_Be_Quoted : Boolean := False) return File_Name_Type;
-- Skip blanks, then scan out a file name (name is left in Name_Buffer
-- with length in Name_Len, as well as returning a File_Name_Type value.
+ -- If May_Be_Quoted is True and the first non blank character is '"',
+ -- then remove starting and ending quotes and undoubled internal quotes.
-- If lower is false, the case is unchanged, if Lower is True then the
-- result is forced to all lower case for systems where file names are
-- not case sensitive. This ensures that gnatbind works correctly
@@ -198,7 +202,8 @@ package body ALI is
function Get_Name
(Ignore_Spaces : Boolean := False;
- Ignore_Special : Boolean := False) return Name_Id;
+ Ignore_Special : Boolean := False;
+ May_Be_Quoted : Boolean := False) return Name_Id;
-- Skip blanks, then scan out a name (name is left in Name_Buffer with
-- length in Name_Len, as well as being returned in Name_Id form).
-- If Lower is set to True then the Name_Buffer will be converted to
@@ -215,6 +220,10 @@ package body ALI is
-- an operator name starting with a double quote which is terminated
-- by another double quote.
--
+ -- If May_Be_Quoted is True and the first non blank character is '"'
+ -- the name is 'unquoted'. In this case Ignore_Special is ignored and
+ -- assumed to be True.
+ --
-- It is an error to set both Ignore_Spaces and Ignore_Special to True.
-- This function handles wide characters properly.
@@ -450,12 +459,14 @@ package body ALI is
-------------------
function Get_File_Name
- (Lower : Boolean := False) return File_Name_Type
+ (Lower : Boolean := False;
+ May_Be_Quoted : Boolean := False) return File_Name_Type
is
F : Name_Id;
begin
- F := Get_Name (Ignore_Special => True);
+ F := Get_Name (Ignore_Special => True,
+ May_Be_Quoted => May_Be_Quoted);
-- Convert file name to all lower case if file names are not case
-- sensitive. This ensures that we handle names in the canonical
@@ -475,8 +486,11 @@ package body ALI is
function Get_Name
(Ignore_Spaces : Boolean := False;
- Ignore_Special : Boolean := False) return Name_Id
+ Ignore_Special : Boolean := False;
+ May_Be_Quoted : Boolean := False) return Name_Id
is
+ Char : Character;
+
begin
Name_Len := 0;
Skip_Space;
@@ -489,38 +503,79 @@ package body ALI is
end if;
end if;
- loop
- Add_Char_To_Name_Buffer (Getc);
+ Char := Getc;
- exit when At_End_Of_Field and then not Ignore_Spaces;
+ -- Deal with quoted characters
- if not Ignore_Special then
- if Name_Buffer (1) = '"' then
- exit when Name_Len > 1 and then Name_Buffer (Name_Len) = '"';
+ if May_Be_Quoted and then Char = '"' then
+ loop
+ if At_Eol then
+ if Ignore_Errors then
+ return Error_Name;
+ else
+ Fatal_Error;
+ end if;
+ end if;
- else
- -- Terminate on parens or angle brackets or equal sign
+ Char := Getc;
- exit when Nextc = '(' or else Nextc = ')'
- or else Nextc = '{' or else Nextc = '}'
- or else Nextc = '<' or else Nextc = '>'
- or else Nextc = '=';
+ if Char = '"' then
+ if At_Eol then
+ exit;
- -- Terminate on comma
+ else
+ Char := Getc;
- exit when Nextc = ',';
+ if Char /= '"' then
+ P := P - 1;
+ exit;
+ end if;
+ end if;
+ end if;
- -- Terminate if left bracket not part of wide char sequence
- -- Note that we only recognize brackets notation so far ???
+ Add_Char_To_Name_Buffer (Char);
+ end loop;
- exit when Nextc = '[' and then T (P + 1) /= '"';
+ -- Other than case of quoted character
- -- Terminate if right bracket not part of wide char sequence
+ else
+ P := P - 1;
+ loop
+ Add_Char_To_Name_Buffer (Getc);
+
+ exit when At_End_Of_Field and then not Ignore_Spaces;
+
+ if not Ignore_Special then
+ if Name_Buffer (1) = '"' then
+ exit when Name_Len > 1
+ and then Name_Buffer (Name_Len) = '"';
+
+ else
+ -- Terminate on parens or angle brackets or equal sign
+
+ exit when Nextc = '(' or else Nextc = ')'
+ or else Nextc = '{' or else Nextc = '}'
+ or else Nextc = '<' or else Nextc = '>'
+ or else Nextc = '=';
+
+ -- Terminate on comma
+
+ exit when Nextc = ',';
+
+ -- Terminate if left bracket not part of wide char
+ -- sequence Note that we only recognize brackets
+ -- notation so far ???
- exit when Nextc = ']' and then T (P - 1) /= '"';
+ exit when Nextc = '[' and then T (P + 1) /= '"';
+
+ -- Terminate if right bracket not part of wide char
+ -- sequence.
+
+ exit when Nextc = ']' and then T (P - 1) /= '"';
+ end if;
end if;
- end if;
- end loop;
+ end loop;
+ end if;
return Name_Find;
end Get_Name;
@@ -2224,7 +2279,10 @@ package body ALI is
-- In the following call, Lower is not set to True, this is either
-- a bug, or it deserves a special comment as to why this is so???
- Sdep.Table (Sdep.Last).Sfile := Get_File_Name;
+ -- The file/path name may be quoted
+
+ Sdep.Table (Sdep.Last).Sfile :=
+ Get_File_Name (May_Be_Quoted => True);
Sdep.Table (Sdep.Last).Stamp := Get_Stamp;
Sdep.Table (Sdep.Last).Dummy_Entry :=
diff --git a/gcc/ada/aspects.adb b/gcc/ada/aspects.adb
index 1d736467b46..091af77ef77 100644
--- a/gcc/ada/aspects.adb
+++ b/gcc/ada/aspects.adb
@@ -140,11 +140,11 @@ package body Aspects is
end if;
end Aspect_Specifications;
- ------------------------
- -- Aspects_On_Body_OK --
- ------------------------
+ --------------------------------
+ -- Aspects_On_Body_Or_Stub_OK --
+ --------------------------------
- function Aspects_On_Body_OK (N : Node_Id) return Boolean is
+ function Aspects_On_Body_Or_Stub_OK (N : Node_Id) return Boolean is
Aspect : Node_Id;
Aspects : List_Id;
@@ -159,12 +159,12 @@ package body Aspects is
N_Task_Body));
-- Look through all aspects and see whether they can be applied to a
- -- body.
+ -- body [stub].
Aspects := Aspect_Specifications (N);
Aspect := First (Aspects);
while Present (Aspect) loop
- if not Aspect_On_Body_OK (Get_Aspect_Id (Aspect)) then
+ if not Aspect_On_Body_Or_Stub_OK (Get_Aspect_Id (Aspect)) then
return False;
end if;
@@ -172,7 +172,7 @@ package body Aspects is
end loop;
return True;
- end Aspects_On_Body_OK;
+ end Aspects_On_Body_Or_Stub_OK;
-----------------
-- Find_Aspect --
@@ -368,9 +368,9 @@ package body Aspects is
N_Single_Protected_Declaration => True,
N_Single_Task_Declaration => True,
N_Subprogram_Body => True,
+ N_Subprogram_Body_Stub => True,
N_Subprogram_Declaration => True,
N_Subprogram_Renaming_Declaration => True,
- N_Subprogram_Body_Stub => True,
N_Subtype_Declaration => True,
N_Task_Body => True,
N_Task_Body_Stub => True,
@@ -440,6 +440,8 @@ package body Aspects is
Aspect_Independent_Components => Aspect_Independent_Components,
Aspect_Inline => Aspect_Inline,
Aspect_Inline_Always => Aspect_Inline,
+ Aspect_Initial_Condition => Aspect_Initial_Condition,
+ Aspect_Initializes => Aspect_Initializes,
Aspect_Input => Aspect_Input,
Aspect_Interrupt_Handler => Aspect_Interrupt_Handler,
Aspect_Interrupt_Priority => Aspect_Priority,
@@ -466,6 +468,10 @@ package body Aspects is
Aspect_Pure_05 => Aspect_Pure_05,
Aspect_Pure_12 => Aspect_Pure_12,
Aspect_Pure_Function => Aspect_Pure_Function,
+ Aspect_Refined_Depends => Aspect_Refined_Depends,
+ Aspect_Refined_Global => Aspect_Refined_Global,
+ Aspect_Refined_Post => Aspect_Refined_Post,
+ Aspect_Refined_State => Aspect_Refined_State,
Aspect_Remote_Access_Type => Aspect_Remote_Access_Type,
Aspect_Remote_Call_Interface => Aspect_Remote_Call_Interface,
Aspect_Remote_Types => Aspect_Remote_Types,
diff --git a/gcc/ada/aspects.ads b/gcc/ada/aspects.ads
index 5e8046d1ad0..2fd4b451bb0 100644
--- a/gcc/ada/aspects.ads
+++ b/gcc/ada/aspects.ads
@@ -96,6 +96,8 @@ package Aspects is
Aspect_External_Tag,
Aspect_Global, -- GNAT
Aspect_Implicit_Dereference,
+ Aspect_Initial_Condition, -- GNAT
+ Aspect_Initializes, -- GNAT
Aspect_Input,
Aspect_Interrupt_Priority,
Aspect_Invariant, -- GNAT
@@ -111,6 +113,10 @@ package Aspects is
Aspect_Predicate, -- GNAT
Aspect_Priority,
Aspect_Read,
+ Aspect_Refined_Depends, -- GNAT
+ Aspect_Refined_Global, -- GNAT
+ Aspect_Refined_Post, -- GNAT
+ Aspect_Refined_State, -- GNAT
Aspect_Relative_Deadline,
Aspect_Scalar_Storage_Order, -- GNAT
Aspect_Simple_Storage_Pool, -- GNAT
@@ -304,6 +310,8 @@ package Aspects is
Aspect_External_Tag => Expression,
Aspect_Global => Expression,
Aspect_Implicit_Dereference => Name,
+ Aspect_Initial_Condition => Expression,
+ Aspect_Initializes => Expression,
Aspect_Input => Name,
Aspect_Interrupt_Priority => Expression,
Aspect_Invariant => Expression,
@@ -319,6 +327,10 @@ package Aspects is
Aspect_Predicate => Expression,
Aspect_Priority => Expression,
Aspect_Read => Name,
+ Aspect_Refined_Depends => Expression,
+ Aspect_Refined_Global => Expression,
+ Aspect_Refined_Post => Expression,
+ Aspect_Refined_State => Expression,
Aspect_Relative_Deadline => Expression,
Aspect_Scalar_Storage_Order => Expression,
Aspect_Simple_Storage_Pool => Name,
@@ -388,6 +400,8 @@ package Aspects is
Aspect_Independent_Components => Name_Independent_Components,
Aspect_Inline => Name_Inline,
Aspect_Inline_Always => Name_Inline_Always,
+ Aspect_Initial_Condition => Name_Initial_Condition,
+ Aspect_Initializes => Name_Initializes,
Aspect_Input => Name_Input,
Aspect_Interrupt_Handler => Name_Interrupt_Handler,
Aspect_Interrupt_Priority => Name_Interrupt_Priority,
@@ -415,6 +429,10 @@ package Aspects is
Aspect_Pure_12 => Name_Pure_12,
Aspect_Pure_Function => Name_Pure_Function,
Aspect_Read => Name_Read,
+ Aspect_Refined_Depends => Name_Refined_Depends,
+ Aspect_Refined_Global => Name_Refined_Global,
+ Aspect_Refined_Post => Name_Refined_Post,
+ Aspect_Refined_State => Name_Refined_State,
Aspect_Relative_Deadline => Name_Relative_Deadline,
Aspect_Remote_Access_Type => Name_Remote_Access_Type,
Aspect_Remote_Call_Interface => Name_Remote_Call_Interface,
@@ -582,6 +600,8 @@ package Aspects is
Aspect_Independent_Components => Always_Delay,
Aspect_Inline => Always_Delay,
Aspect_Inline_Always => Always_Delay,
+ Aspect_Initial_Condition => Always_Delay,
+ Aspect_Initializes => Always_Delay,
Aspect_Input => Always_Delay,
Aspect_Interrupt_Handler => Always_Delay,
Aspect_Interrupt_Priority => Always_Delay,
@@ -606,6 +626,9 @@ package Aspects is
Aspect_Pure_12 => Always_Delay,
Aspect_Pure_Function => Always_Delay,
Aspect_Read => Always_Delay,
+ Aspect_Refined_Depends => Always_Delay,
+ Aspect_Refined_Global => Always_Delay,
+ Aspect_Refined_State => Always_Delay,
Aspect_Relative_Deadline => Always_Delay,
Aspect_Remote_Access_Type => Always_Delay,
Aspect_Remote_Call_Interface => Always_Delay,
@@ -636,6 +659,7 @@ package Aspects is
Aspect_Convention => Never_Delay,
Aspect_Dimension => Never_Delay,
Aspect_Dimension_System => Never_Delay,
+ Aspect_Refined_Post => Never_Delay,
Aspect_SPARK_Mode => Never_Delay,
Aspect_Synchronization => Never_Delay,
Aspect_Test_Case => Never_Delay,
@@ -657,15 +681,49 @@ package Aspects is
Aspect_Volatile => Rep_Aspect,
Aspect_Volatile_Components => Rep_Aspect);
- -- The following table indicates which aspects can apply simultaneously to
- -- both subprogram/package specs and bodies. For instance, the following is
- -- legal:
+ ------------------------------------------------
+ -- Handling of Aspect Specifications on Stubs --
+ ------------------------------------------------
+
+ -- Aspects that appear on the following stub nodes
+
+ -- N_Package_Body_Stub
+ -- N_Protected_Body_Stub
+ -- N_Subprogram_Body_Stub
+ -- N_Task_Body_Stub
+
+ -- are treated as if they apply to the corresponding proper body. Their
+ -- analysis is postponed until the analysis of the proper body takes place
+ -- (see Analyze_Proper_Body). The delay is required because the analysis
+ -- may generate extra code which would be harder to relocate to the body.
+ -- If the proper body is present, the aspect specifications are relocated
+ -- to the corresponding body node:
+
+ -- N_Package_Body
+ -- N_Protected_Body
+ -- N_Subprogram_Body
+ -- N_Task_Body
+
+ -- The subsequent analysis takes care of the aspect-to-pragma conversions
+ -- and verification of pragma legality. In the case where the proper body
+ -- is not available, the aspect specifications are analyzed on the spot
+ -- (see Analyze_Proper_Body) to catch potential errors.
+
+ -- The following table lists all aspects that can apply to a subprogram
+ -- body [stub]. For instance, the following example is legal:
-- package P with SPARK_Mode ...;
-- package body P with SPARK_Mode is ...;
- Aspect_On_Body_OK : constant array (Aspect_Id) of Boolean :=
- (Aspect_SPARK_Mode => True,
+ -- The table should be synchronized with Pragma_On_Body_Or_Stub_OK in unit
+ -- Sem_Prag if the aspects below are implemented by a pragma.
+
+ Aspect_On_Body_Or_Stub_OK : constant array (Aspect_Id) of Boolean :=
+ (Aspect_Refined_Depends => True,
+ Aspect_Refined_Global => True,
+ Aspect_Refined_Post => True,
+ Aspect_SPARK_Mode => True,
+ Aspect_Warnings => True,
others => False);
---------------------------------------------------
@@ -696,9 +754,9 @@ package Aspects is
-- Replace calls, and this function may be used to retrieve the aspect
-- specifications for the original rewritten node in such cases.
- function Aspects_On_Body_OK (N : Node_Id) return Boolean;
+ function Aspects_On_Body_Or_Stub_OK (N : Node_Id) return Boolean;
-- N denotes a body [stub] with aspects. Determine whether all aspects of N
- -- can appear simultaneously in bodies and specs.
+ -- are allowed to appear on a body [stub].
function Find_Aspect (Id : Entity_Id; A : Aspect_Id) return Node_Id;
-- Find the aspect specification of aspect A associated with entity I.
diff --git a/gcc/ada/atree.adb b/gcc/ada/atree.adb
index a6105e2c427..a44a247b896 100644
--- a/gcc/ada/atree.adb
+++ b/gcc/ada/atree.adb
@@ -979,6 +979,26 @@ package body Atree is
end Ekind_In;
function Ekind_In
+ (T : Entity_Kind;
+ V1 : Entity_Kind;
+ V2 : Entity_Kind;
+ V3 : Entity_Kind;
+ V4 : Entity_Kind;
+ V5 : Entity_Kind;
+ V6 : Entity_Kind;
+ V7 : Entity_Kind) return Boolean
+ is
+ begin
+ return T = V1 or else
+ T = V2 or else
+ T = V3 or else
+ T = V4 or else
+ T = V5 or else
+ T = V6 or else
+ T = V7;
+ end Ekind_In;
+
+ function Ekind_In
(E : Entity_Id;
V1 : Entity_Kind;
V2 : Entity_Kind) return Boolean
@@ -1033,6 +1053,20 @@ package body Atree is
return Ekind_In (Ekind (E), V1, V2, V3, V4, V5, V6);
end Ekind_In;
+ function Ekind_In
+ (E : Entity_Id;
+ V1 : Entity_Kind;
+ V2 : Entity_Kind;
+ V3 : Entity_Kind;
+ V4 : Entity_Kind;
+ V5 : Entity_Kind;
+ V6 : Entity_Kind;
+ V7 : Entity_Kind) return Boolean
+ is
+ begin
+ return Ekind_In (Ekind (E), V1, V2, V3, V4, V5, V6, V7);
+ end Ekind_In;
+
------------------------
-- Set_Reporting_Proc --
------------------------
diff --git a/gcc/ada/atree.ads b/gcc/ada/atree.ads
index 123beb3907e..0f47e862f45 100644
--- a/gcc/ada/atree.ads
+++ b/gcc/ada/atree.ads
@@ -462,25 +462,26 @@ package Atree is
-- with copying aspect specifications where this is required.
function New_Copy (Source : Node_Id) return Node_Id;
- -- This function allocates a completely new node, and then initializes it
- -- by copying the contents of the source node into it. The contents of the
- -- source node is not affected. The target node is always marked as not
- -- being in a list (even if the source is a list member). The new node will
- -- have an extension if the source has an extension. New_Copy (Empty)
- -- returns Empty and New_Copy (Error) returns Error. Note that, unlike
- -- Copy_Separate_Tree, New_Copy does not recursively copy any descendents,
- -- so in general parent pointers are not set correctly for the descendents
- -- of the copied node. Both normal and extended nodes (entities) may be
- -- copied using New_Copy.
+ -- This function allocates a completely new node, and then initializes
+ -- it by copying the contents of the source node into it. The contents of
+ -- the source node is not affected. The target node is always marked as
+ -- not being in a list (even if the source is a list member), and not
+ -- overloaded. The new node will have an extension if the source has
+ -- an extension. New_Copy (Empty) returns Empty, and New_Copy (Error)
+ -- returns Error. Note that, unlike Copy_Separate_Tree, New_Copy does not
+ -- recursively copy any descendents, so in general parent pointers are not
+ -- set correctly for the descendents of the copied node. Both normal and
+ -- extended nodes (entities) may be copied using New_Copy.
function Relocate_Node (Source : Node_Id) return Node_Id;
-- Source is a non-entity node that is to be relocated. A new node is
- -- allocated and the contents of Source are copied to this node using
- -- Copy_Node. The parent pointers of descendents of the node are then
+ -- allocated, and the contents of Source are copied to this node, using
+ -- New_Copy. The parent pointers of descendents of the node are then
-- adjusted to point to the relocated copy. The original node is not
-- modified, but the parent pointers of its descendents are no longer
- -- valid. This routine is used in conjunction with the tree rewrite
- -- routines (see descriptions of Replace/Rewrite).
+ -- valid. The new copy is always marked as not overloaded. This routine is
+ -- used in conjunction with the tree rewrite routines (see descriptions of
+ -- Replace/Rewrite).
--
-- Note that the resulting node has the same parent as the source node, and
-- is thus still attached to the tree. It is valid for Source to be Empty,
@@ -736,6 +737,16 @@ package Atree is
V6 : Entity_Kind) return Boolean;
function Ekind_In
+ (E : Entity_Id;
+ V1 : Entity_Kind;
+ V2 : Entity_Kind;
+ V3 : Entity_Kind;
+ V4 : Entity_Kind;
+ V5 : Entity_Kind;
+ V6 : Entity_Kind;
+ V7 : Entity_Kind) return Boolean;
+
+ function Ekind_In
(T : Entity_Kind;
V1 : Entity_Kind;
V2 : Entity_Kind) return Boolean;
@@ -770,6 +781,16 @@ package Atree is
V5 : Entity_Kind;
V6 : Entity_Kind) return Boolean;
+ function Ekind_In
+ (T : Entity_Kind;
+ V1 : Entity_Kind;
+ V2 : Entity_Kind;
+ V3 : Entity_Kind;
+ V4 : Entity_Kind;
+ V5 : Entity_Kind;
+ V6 : Entity_Kind;
+ V7 : Entity_Kind) return Boolean;
+
pragma Inline (Ekind_In);
-- Inline all above functions
diff --git a/gcc/ada/checks.adb b/gcc/ada/checks.adb
index 29a18593167..328e05e5aaf 100644
--- a/gcc/ada/checks.adb
+++ b/gcc/ada/checks.adb
@@ -24,6 +24,7 @@
------------------------------------------------------------------------------
with Atree; use Atree;
+with Casing; use Casing;
with Debug; use Debug;
with Einfo; use Einfo;
with Errout; use Errout;
@@ -2189,7 +2190,9 @@ package body Checks is
Formal_2 : Entity_Id;
Check : in out Node_Id)
is
- Cond : Node_Id;
+ Cond : Node_Id;
+ ID_Casing : constant Casing_Type :=
+ Identifier_Casing (Source_Index (Current_Sem_Unit));
begin
-- Generate:
@@ -2220,9 +2223,17 @@ package body Checks is
end if;
Store_String_Chars ("aliased parameters, actuals for """);
- Store_String_Chars (Get_Name_String (Chars (Formal_1)));
+
+ Get_Name_String (Chars (Formal_1));
+ Set_Casing (ID_Casing);
+ Store_String_Chars (Name_Buffer (1 .. Name_Len));
+
Store_String_Chars (""" and """);
- Store_String_Chars (Get_Name_String (Chars (Formal_2)));
+
+ Get_Name_String (Chars (Formal_2));
+ Set_Casing (ID_Casing);
+ Store_String_Chars (Name_Buffer (1 .. Name_Len));
+
Store_String_Chars (""" overlap");
Insert_Action (Call,
@@ -3543,6 +3554,32 @@ package body Checks is
L : Node_Id;
R : Node_Id;
+ function Left_Expression (Op : Node_Id) return Node_Id;
+ -- Return the relevant expression from the left operand of the given
+ -- short circuit form: this is LO itself, except if LO is a qualified
+ -- expression, a type conversion, or an expression with actions, in
+ -- which case this is Left_Expression (Expression (LO)).
+
+ ---------------------
+ -- Left_Expression --
+ ---------------------
+
+ function Left_Expression (Op : Node_Id) return Node_Id is
+ LE : Node_Id := Left_Opnd (Op);
+ begin
+ while Nkind_In (LE,
+ N_Qualified_Expression,
+ N_Type_Conversion,
+ N_Expression_With_Actions)
+ loop
+ LE := Expression (LE);
+ end loop;
+
+ return LE;
+ end Left_Expression;
+
+ -- Start of processing for Check_Needed
+
begin
-- Always check if not simple entity
@@ -3576,37 +3613,40 @@ package body Checks is
elsif K = N_Op_Or then
exit when N = Right_Opnd (P)
- and then Nkind (Left_Opnd (P)) = N_Op_Eq;
+ and then Nkind (Left_Expression (P)) = N_Op_Eq;
elsif K = N_Or_Else then
exit when (N = Right_Opnd (P)
or else
(Is_List_Member (N)
and then List_Containing (N) = Actions (P)))
- and then Nkind (Left_Opnd (P)) = N_Op_Eq;
+ and then Nkind (Left_Expression (P)) = N_Op_Eq;
-- Similar test for the And/And then case, where the left operand
-- is an inequality test.
elsif K = N_Op_And then
exit when N = Right_Opnd (P)
- and then Nkind (Left_Opnd (P)) = N_Op_Ne;
+ and then Nkind (Left_Expression (P)) = N_Op_Ne;
elsif K = N_And_Then then
exit when (N = Right_Opnd (P)
or else
(Is_List_Member (N)
and then List_Containing (N) = Actions (P)))
- and then Nkind (Left_Opnd (P)) = N_Op_Ne;
+ and then Nkind (Left_Expression (P)) = N_Op_Ne;
end if;
N := P;
end loop;
-- If we fall through the loop, then we have a conditional with an
- -- appropriate test as its left operand. So test further.
+ -- appropriate test as its left operand, so look further.
+
+ L := Left_Expression (P);
+
+ -- L is an "=" or "/=" operator: extract its operands
- L := Left_Opnd (P);
R := Right_Opnd (L);
L := Left_Opnd (L);
@@ -5052,6 +5092,13 @@ package body Checks is
then
return;
+ -- For an expression with actions, we want to insert the validity check
+ -- on the final Expression.
+
+ elsif Nkind (Expr) = N_Expression_With_Actions then
+ Ensure_Valid (Expression (Expr));
+ return;
+
-- An annoying special case. If this is an out parameter of a scalar
-- type, then the value is not going to be accessed, therefore it is
-- inappropriate to do any validity check at the call site.
diff --git a/gcc/ada/cstand.adb b/gcc/ada/cstand.adb
index 09c125dfdce..ed022388049 100644
--- a/gcc/ada/cstand.adb
+++ b/gcc/ada/cstand.adb
@@ -1305,6 +1305,9 @@ package body CStand is
Set_Scope (Standard_Integer_64, Standard_Standard);
Build_Signed_Integer_Type (Standard_Integer_64, 64);
+ -- Standard_Unsigned is not user visible, but is used internally. It
+ -- is an unsigned type with the same length as Standard.Integer.
+
Standard_Unsigned := New_Standard_Entity;
Decl := New_Node (N_Full_Type_Declaration, Stloc);
Set_Defining_Identifier (Decl, Standard_Unsigned);
@@ -1329,6 +1332,32 @@ package body CStand is
Set_Etype (High_Bound (R_Node), Standard_Unsigned);
Set_Scalar_Range (Standard_Unsigned, R_Node);
+ -- Standard_Unsigned_64 is not user visible, but is used internally. It
+ -- is an unsigned type mod 2**64, 64-bits unsigned, size is 64.
+
+ Standard_Unsigned_64 := New_Standard_Entity;
+ Decl := New_Node (N_Full_Type_Declaration, Stloc);
+ Set_Defining_Identifier (Decl, Standard_Unsigned_64);
+ Make_Name (Standard_Unsigned_64, "unsigned_64");
+
+ Set_Ekind (Standard_Unsigned_64, E_Modular_Integer_Type);
+ Set_Scope (Standard_Unsigned_64, Standard_Standard);
+ Set_Etype (Standard_Unsigned_64, Standard_Unsigned_64);
+ Init_Size (Standard_Unsigned_64, 64);
+ Set_Elem_Alignment (Standard_Unsigned_64);
+ Set_Modulus (Standard_Unsigned_64, Uint_2 ** 64);
+ Set_Is_Unsigned_Type (Standard_Unsigned_64);
+ Set_Size_Known_At_Compile_Time
+ (Standard_Unsigned_64);
+ Set_Is_Known_Valid (Standard_Unsigned_64, True);
+
+ R_Node := New_Node (N_Range, Stloc);
+ Set_Low_Bound (R_Node, Make_Integer (Uint_0));
+ Set_High_Bound (R_Node, Make_Integer (Uint_2 ** 64 - 1));
+ Set_Etype (Low_Bound (R_Node), Standard_Unsigned_64);
+ Set_Etype (High_Bound (R_Node), Standard_Unsigned_64);
+ Set_Scalar_Range (Standard_Unsigned_64, R_Node);
+
-- Note: universal integer and universal real are constructed as fully
-- formed signed numeric types, with parameters corresponding to the
-- longest runtime types (Long_Long_Integer and Long_Long_Float). This
@@ -1419,9 +1448,9 @@ package body CStand is
(Type_Definition (Parent (Standard_Duration))));
-- Normally it does not matter that nodes in package Standard are
- -- not marked as analyzed. The Scalar_Range of the fixed-point
- -- type Standard_Duration is an exception, because of the special
- -- test made in Freeze.Freeze_Fixed_Point_Type.
+ -- not marked as analyzed. The Scalar_Range of the fixed-point type
+ -- Standard_Duration is an exception, because of the special test
+ -- made in Freeze.Freeze_Fixed_Point_Type.
Set_Analyzed (Scalar_Range (Standard_Duration));
@@ -1441,14 +1470,11 @@ package body CStand is
end Build_Duration;
-- Build standard exception type. Note that the type name here is
- -- actually used in the generated code, so it must be set correctly
-
- -- ??? Also note that the Import_Code component is now declared
- -- as a System.Standard_Library.Exception_Code to enforce run-time
- -- library implementation consistency. It's too early here to resort
- -- to rtsfind to get the proper node for that type, so we use the
- -- closest possible available type node at hand instead. We should
- -- probably be fixing this up at some point.
+ -- actually used in the generated code, so it must be set correctly.
+ -- The type Standard_Exception_Type must be consistent with the type
+ -- System.Standard_Library.Exception_Data, as the latter is what is
+ -- known by the run-time. Components of the record are documented in
+ -- the declaration in System.Standard_Library.
Standard_Exception_Type := New_Standard_Entity;
Set_Ekind (Standard_Exception_Type, E_Record_Type);
@@ -1472,7 +1498,7 @@ package body CStand is
Make_Component
(Standard_Exception_Type, Standard_A_Char, "HTable_Ptr");
Make_Component
- (Standard_Exception_Type, Standard_Unsigned, "Import_Code");
+ (Standard_Exception_Type, Standard_A_Char, "Foreign_Data");
Make_Component
(Standard_Exception_Type, Standard_A_Char, "Raise_Hook");
diff --git a/gcc/ada/debug.adb b/gcc/ada/debug.adb
index 01624792c61..acda7cfc691 100644
--- a/gcc/ada/debug.adb
+++ b/gcc/ada/debug.adb
@@ -122,19 +122,19 @@ package body Debug is
-- d.B
-- d.C Generate concatenation call, do not generate inline code
-- d.D SPARK strict mode
- -- d.E Force SPARK mode for gnat2why
+ -- d.E Turn selected errors into warnings
-- d.F SPARK mode
-- d.G Frame condition mode for gnat2why
- -- d.H Standard package only mode for gnat2why
+ -- d.H
-- d.I Do not ignore enum representation clauses in CodePeer mode
-- d.J Disable parallel SCIL generation mode
- -- d.K SPARK detection only mode for gnat2why
+ -- d.K
-- d.L Depend on back end for limited types in if and case expressions
-- d.M Relaxed RM semantics
-- d.N Add node to all entities
-- d.O Dump internal SCO tables
-- d.P Previous (non-optimized) handling of length comparisons
- -- d.Q Flow Analysis mode for gnat2why
+ -- d.Q
-- d.R Restrictions in ali files in positional form
-- d.S Force Optimize_Alignment (Space)
-- d.T Force Optimize_Alignment (Time)
@@ -143,7 +143,7 @@ package body Debug is
-- d.W Print out debugging information for Walk_Library_Items
-- d.X
-- d.Y
- -- d.Z Dump flow analysis graphs, for debugging purposes (gnat2why)
+ -- d.Z
-- d1 Error msgs have node numbers where possible
-- d2 Eliminate error flags in verbose form error messages
@@ -581,25 +581,25 @@ package body Debug is
-- d.w This flag turns off the scanning of loops to detect possible
-- infinite loops.
- -- d.A There seems to be a problem with ASIS if we activate the circuit
- -- for reading and writing the aspect specification hash table, so
- -- for now, this is controlled by the debug flag d.A. The hash table
- -- is only written and read if this flag is set.
-
-- d.x No exception handlers in generated code. This causes exception
-- handlers to be eliminated from the generated code. They are still
-- fully compiled and analyzed, they just get eliminated from the
-- code generation step.
+ -- d.A There seems to be a problem with ASIS if we activate the circuit
+ -- for reading and writing the aspect specification hash table, so
+ -- for now, this is controlled by the debug flag d.A. The hash table
+ -- is only written and read if this flag is set.
+
-- d.C Generate call to System.Concat_n.Str_Concat_n routines in cases
-- where we would normally generate inline concatenation code.
-- d.D SPARK strict mode. Interpret compiler permissions as strictly as
-- possible in SPARK mode.
- -- d.E Force SPARK mode for gnat2why. In this mode, errors are issued for
- -- all violations of SPARK in user code, and warnings are issued for
- -- constructs not yet implemented in gnat2why.
+ -- d.E Turn selected errors into warnings. This debug switch causes a
+ -- specific set of error messages into warnings. Setting this switch
+ -- causes Opt.Error_To_Warning to be set to True.
-- d.F SPARK mode. Generate AST in a form suitable for formal
-- verification, as well as additional cross reference information in
@@ -610,10 +610,6 @@ package body Debug is
-- generate Why code. Instead, it generates ALI files with an extra
-- section which contains the effects of subprograms.
- -- d.H Standard package only mode for gnat2why. In this mode, gnat2why
- -- will only generate Why code for package Standard. Any given input
- -- file will be ignored.
-
-- d.I Do not ignore enum representation clauses in CodePeer mode.
-- The default of ignoring representation clauses for enumeration
-- types in CodePeer is good for the majority of Ada code, but in some
@@ -624,9 +620,6 @@ package body Debug is
-- done in parallel to speed processing. This switch disables this
-- behavior.
- -- d.K SPARK detection only mode for gnat2why. In this mode, gnat2why
- -- does not generate Why code.
-
-- d.L Normally the front end generates special expansion for conditional
-- expressions of a limited type. This debug flag removes this special
-- case expansion, leaving it up to the back end to handle conditional
@@ -648,9 +641,6 @@ package body Debug is
-- This is there in case we find a situation where the optimization
-- malfunctions, to provide a work around.
- -- d.Q Flow Analysis mode for gnat2why. When this flag is given,
- -- gnat2why will do flow analysis, and no translation to Why is done.
-
-- d.R As documented in lib-writ.ads, restrictions in the ali file can
-- have two forms, positional and named. The named notation is the
-- current preferred form, but the use of this debug switch will force
@@ -675,15 +665,6 @@ package body Debug is
-- the order in which units are walked. This is primarily for use in
-- debugging CodePeer mode.
- -- d.Z In gnat2why, in Flow analysis mode (-gnatd.Q), dump the different
- -- graphs (control flow, control dependence) for debugging purposes.
- -- This debug flag will be removed when flow analysis is sufficiently
- -- stable.
-
- -- d.Y Prevents the use of the N_Expression_With_Actions node even in the
- -- case of the gcc back end. Provided as a back up in case the new
- -- scheme has problems.
-
-- d1 Error messages have node numbers where possible. Normally error
-- messages have only source locations. This option is useful when
-- debugging errors caused by expanded code, where the source location
diff --git a/gcc/ada/einfo.adb b/gcc/ada/einfo.adb
index 1da975d0a9e..5a8757bac40 100644
--- a/gcc/ada/einfo.adb
+++ b/gcc/ada/einfo.adb
@@ -33,6 +33,7 @@ pragma Style_Checks (All_Checks);
-- Turn off subprogram ordering, not used for this unit
with Atree; use Atree;
+with Elists; use Elists;
with Namet; use Namet;
with Nlists; use Nlists;
with Output; use Output;
@@ -76,16 +77,15 @@ package body Einfo is
-- Associated_Node_For_Itype Node8
-- Dependent_Instances Elist8
-- Hiding_Loop_Variable Node8
- -- Integrity_Level Uint8
-- Mechanism Uint8 (but returns Mechanism_Type)
-- Normalized_First_Bit Uint8
-- Postcondition_Proc Node8
+ -- Refinement_Constituents Elist8
-- Return_Applies_To Node8
-- First_Exit_Statement Node8
-- Class_Wide_Type Node9
-- Current_Value Node9
- -- Refined_State Node9
-- Renaming_Map Uint9
-- Direct_Primitive_Operations Elist10
@@ -93,6 +93,7 @@ package body Einfo is
-- Float_Rep Uint10 (but returns Float_Rep_Kind)
-- Handler_Records List10
-- Normalized_Position_Max Uint10
+ -- Refined_State Node10
-- Component_Bit_Offset Uint11
-- Full_View Node11
@@ -131,6 +132,7 @@ package body Einfo is
-- String_Literal_Low_Bound Node15
-- Access_Disp_Table Elist16
+ -- Body_References Elist16
-- Cloned_Subtype Node16
-- DTC_Entity Node16
-- Entry_Formal Node16
@@ -211,7 +213,6 @@ package body Einfo is
-- Protection_Object Node23
-- Stored_Constraint Elist23
- -- Finalizer Node24
-- Related_Expression Node24
-- Contract Node24
@@ -236,6 +237,7 @@ package body Einfo is
-- Wrapped_Entity Node27
-- Extra_Formals Node28
+ -- Finalizer Node28
-- Initialization_Statements Node28
-- Underlying_Record_View Node28
@@ -435,7 +437,7 @@ package body Einfo is
-- Referenced Flag156
-- Has_Pragma_Inline Flag157
-- Finalize_Storage_Only Flag158
- -- From_With_Type Flag159
+ -- From_Limited_With Flag159
-- Is_Package_Body_Entity Flag160
-- Has_Qualified_Name Flag161
@@ -550,9 +552,9 @@ package body Einfo is
-- Has_Delayed_Rep_Aspects Flag261
-- May_Inherit_Delayed_Rep_Aspects Flag262
+ -- Has_Visible_Refinement Flag263
+ -- Has_Body_References Flag264
- -- (unused) Flag263
- -- (unused) Flag264
-- (unused) Flag265
-- (unused) Flag266
-- (unused) Flag267
@@ -584,11 +586,11 @@ package body Einfo is
-- Local subprograms --
-----------------------
- function Has_Property
- (State : Entity_Id;
- Prop_Nam : Name_Id) return Boolean;
- -- Determine whether abstract state State has a particular property denoted
- -- by the name Prop_Nam.
+ function Has_Option
+ (State : Entity_Id;
+ Opt_Nam : Name_Id) return Boolean;
+ -- Determine whether abstract state State has a particular option denoted
+ -- by the name Opt_Nam.
---------------
-- Float_Rep --
@@ -600,40 +602,40 @@ package body Einfo is
return F'Val (UI_To_Int (Uint10 (Base_Type (Id))));
end Float_Rep;
- ------------------
- -- Has_Property --
- ------------------
+ ----------------
+ -- Has_Option --
+ ----------------
- function Has_Property
- (State : Entity_Id;
- Prop_Nam : Name_Id) return Boolean
+ function Has_Option
+ (State : Entity_Id;
+ Opt_Nam : Name_Id) return Boolean
is
- Par : constant Node_Id := Parent (State);
- Prop : Node_Id;
+ Par : constant Node_Id := Parent (State);
+ Opt : Node_Id;
begin
pragma Assert (Ekind (State) = E_Abstract_State);
- -- States with properties appear as extension aggregates in the tree
+ -- States with options appear as extension aggregates in the tree
if Nkind (Par) = N_Extension_Aggregate then
- if Prop_Nam = Name_Integrity then
+ if Opt_Nam = Name_Part_Of then
return Present (Component_Associations (Par));
else
- Prop := First (Expressions (Par));
- while Present (Prop) loop
- if Chars (Prop) = Prop_Nam then
+ Opt := First (Expressions (Par));
+ while Present (Opt) loop
+ if Chars (Opt) = Opt_Nam then
return True;
end if;
- Next (Prop);
+ Next (Opt);
end loop;
end if;
end if;
return False;
- end Has_Property;
+ end Has_Option;
--------------------------------
-- Attribute Access Functions --
@@ -732,6 +734,12 @@ package body Einfo is
return Flag40 (Id);
end Body_Needed_For_SAL;
+ function Body_References (Id : E) return L is
+ begin
+ pragma Assert (Ekind (Id) = E_Abstract_State);
+ return Elist16 (Id);
+ end Body_References;
+
function C_Pass_By_Copy (Id : E) return B is
begin
pragma Assert (Is_Record_Type (Id));
@@ -852,13 +860,13 @@ package body Einfo is
function Default_Aspect_Component_Value (Id : E) return N is
begin
pragma Assert (Is_Array_Type (Id));
- return Node19 (Id);
+ return Node19 (Base_Type (Id));
end Default_Aspect_Component_Value;
function Default_Aspect_Value (Id : E) return N is
begin
pragma Assert (Is_Scalar_Type (Id));
- return Node19 (Id);
+ return Node19 (Base_Type (Id));
end Default_Aspect_Value;
function Default_Expr_Function (Id : E) return E is
@@ -1066,9 +1074,14 @@ package body Einfo is
function Contract (Id : E) return N is
begin
pragma Assert
- (Ekind_In (Id, E_Entry, E_Entry_Family)
- or else Is_Subprogram (Id)
- or else Is_Generic_Subprogram (Id));
+ (Ekind_In (Id, E_Entry,
+ E_Entry_Family,
+ E_Generic_Package,
+ E_Package,
+ E_Package_Body,
+ E_Subprogram_Body)
+ or else Is_Generic_Subprogram (Id)
+ or else Is_Subprogram (Id));
return Node24 (Id);
end Contract;
@@ -1106,6 +1119,7 @@ package body Einfo is
pragma Assert
(Ekind_In (Id, E_Class_Wide_Type,
E_Class_Wide_Subtype,
+ E_Access_Subprogram_Type,
E_Access_Protected_Subprogram_Type,
E_Anonymous_Access_Protected_Subprogram_Type,
E_Access_Subprogram_Type,
@@ -1178,10 +1192,8 @@ package body Einfo is
function Finalizer (Id : E) return E is
begin
- pragma Assert
- (Ekind (Id) = E_Package
- or else Ekind (Id) = E_Package_Body);
- return Node24 (Id);
+ pragma Assert (Ekind_In (Id, E_Package, E_Package_Body));
+ return Node28 (Id);
end Finalizer;
function First_Entity (Id : E) return E is
@@ -1230,10 +1242,10 @@ package body Einfo is
return Node7 (Id);
end Freeze_Node;
- function From_With_Type (Id : E) return B is
+ function From_Limited_With (Id : E) return B is
begin
return Flag159 (Id);
- end From_With_Type;
+ end From_Limited_With;
function Full_View (Id : E) return E is
begin
@@ -1289,6 +1301,12 @@ package body Einfo is
return Flag139 (Id);
end Has_Biased_Representation;
+ function Has_Body_References (Id : E) return B is
+ begin
+ pragma Assert (Ekind (Id) = E_Abstract_State);
+ return Flag264 (Id);
+ end Has_Body_References;
+
function Has_Completion (Id : E) return B is
begin
return Flag26 (Id);
@@ -1705,6 +1723,12 @@ package body Einfo is
return Flag215 (Id);
end Has_Up_Level_Access;
+ function Has_Visible_Refinement (Id : E) return B is
+ begin
+ pragma Assert (Ekind (Id) = E_Abstract_State);
+ return Flag263 (Id);
+ end Has_Visible_Refinement;
+
function Has_Volatile_Components (Id : E) return B is
begin
return Flag87 (Implementation_Base_Type (Id));
@@ -1760,12 +1784,6 @@ package body Einfo is
return Node28 (Id);
end Initialization_Statements;
- function Integrity_Level (Id : E) return U is
- begin
- pragma Assert (Ekind (Id) = E_Abstract_State);
- return Uint8 (Id);
- end Integrity_Level;
-
function Inner_Instances (Id : E) return L is
begin
return Elist23 (Id);
@@ -2654,12 +2672,18 @@ package body Einfo is
return Flag227 (Id);
end Referenced_As_Out_Parameter;
- function Refined_State (Id : E) return E is
+ function Refined_State (Id : E) return N is
begin
- pragma Assert (Ekind (Id) = E_Abstract_State);
- return Node9 (Id);
+ pragma Assert (Ekind_In (Id, E_Abstract_State, E_Variable));
+ return Node10 (Id);
end Refined_State;
+ function Refinement_Constituents (Id : E) return L is
+ begin
+ pragma Assert (Ekind (Id) = E_Abstract_State);
+ return Elist8 (Id);
+ end Refinement_Constituents;
+
function Register_Exception_Call (Id : E) return N is
begin
pragma Assert (Ekind (Id) = E_Exception);
@@ -3325,6 +3349,12 @@ package body Einfo is
Set_Flag40 (Id, V);
end Set_Body_Needed_For_SAL;
+ procedure Set_Body_References (Id : E; V : L) is
+ begin
+ pragma Assert (Ekind (Id) = E_Abstract_State);
+ Set_Elist16 (Id, V);
+ end Set_Body_References;
+
procedure Set_C_Pass_By_Copy (Id : E; V : B := True) is
begin
pragma Assert (Is_Record_Type (Id) and then Is_Base_Type (Id));
@@ -3445,13 +3475,13 @@ package body Einfo is
procedure Set_Default_Aspect_Component_Value (Id : E; V : E) is
begin
- pragma Assert (Is_Array_Type (Id));
+ pragma Assert (Is_Array_Type (Id) and then Is_Base_Type (Id));
Set_Node19 (Id, V);
end Set_Default_Aspect_Component_Value;
procedure Set_Default_Aspect_Value (Id : E; V : E) is
begin
- pragma Assert (Is_Scalar_Type (Id));
+ pragma Assert (Is_Scalar_Type (Id) and then Is_Base_Type (Id));
Set_Node19 (Id, V);
end Set_Default_Aspect_Value;
@@ -3658,9 +3688,15 @@ package body Einfo is
procedure Set_Contract (Id : E; V : N) is
begin
pragma Assert
- (Ekind_In (Id, E_Entry, E_Entry_Family, E_Void)
- or else Is_Subprogram (Id)
- or else Is_Generic_Subprogram (Id));
+ (Ekind_In (Id, E_Entry,
+ E_Entry_Family,
+ E_Generic_Package,
+ E_Package,
+ E_Package_Body,
+ E_Subprogram_Body,
+ E_Void)
+ or else Is_Generic_Subprogram (Id)
+ or else Is_Subprogram (Id));
Set_Node24 (Id, V);
end Set_Contract;
@@ -3771,10 +3807,8 @@ package body Einfo is
procedure Set_Finalizer (Id : E; V : E) is
begin
- pragma Assert
- (Ekind (Id) = E_Package
- or else Ekind (Id) = E_Package_Body);
- Set_Node24 (Id, V);
+ pragma Assert (Ekind_In (Id, E_Package, E_Package_Body));
+ Set_Node28 (Id, V);
end Set_Finalizer;
procedure Set_First_Entity (Id : E; V : E) is
@@ -3829,13 +3863,11 @@ package body Einfo is
Set_Node7 (Id, V);
end Set_Freeze_Node;
- procedure Set_From_With_Type (Id : E; V : B := True) is
+ procedure Set_From_Limited_With (Id : E; V : B := True) is
begin
- pragma Assert
- (Is_Type (Id)
- or else Ekind (Id) = E_Package);
+ pragma Assert (Is_Type (Id) or else Ekind (Id) = E_Package);
Set_Flag159 (Id, V);
- end Set_From_With_Type;
+ end Set_From_Limited_With;
procedure Set_Full_View (Id : E; V : E) is
begin
@@ -3894,6 +3926,12 @@ package body Einfo is
Set_Flag139 (Id, V);
end Set_Has_Biased_Representation;
+ procedure Set_Has_Body_References (Id : E; V : B := True) is
+ begin
+ pragma Assert (Ekind (Id) = E_Abstract_State);
+ Set_Flag264 (Id, V);
+ end Set_Has_Body_References;
+
procedure Set_Has_Completion (Id : E; V : B := True) is
begin
Set_Flag26 (Id, V);
@@ -4322,6 +4360,12 @@ package body Einfo is
Set_Flag72 (Id, V);
end Set_Has_Unknown_Discriminants;
+ procedure Set_Has_Visible_Refinement (Id : E; V : B := True) is
+ begin
+ pragma Assert (Ekind (Id) = E_Abstract_State);
+ Set_Flag263 (Id, V);
+ end Set_Has_Visible_Refinement;
+
procedure Set_Has_Volatile_Components (Id : E; V : B := True) is
begin
pragma Assert (not Is_Type (Id) or else Is_Base_Type (Id));
@@ -4386,12 +4430,6 @@ package body Einfo is
Set_Node28 (Id, V);
end Set_Initialization_Statements;
- procedure Set_Integrity_Level (Id : E; V : Uint) is
- begin
- pragma Assert (Ekind (Id) = E_Abstract_State);
- Set_Uint8 (Id, V);
- end Set_Integrity_Level;
-
procedure Set_Inner_Instances (Id : E; V : L) is
begin
Set_Elist23 (Id, V);
@@ -5322,10 +5360,16 @@ package body Einfo is
procedure Set_Refined_State (Id : E; V : E) is
begin
- pragma Assert (Ekind (Id) = E_Abstract_State);
- Set_Node9 (Id, V);
+ pragma Assert (Ekind_In (Id, E_Abstract_State, E_Variable));
+ Set_Node10 (Id, V);
end Set_Refined_State;
+ procedure Set_Refinement_Constituents (Id : E; V : L) is
+ begin
+ pragma Assert (Ekind (Id) = E_Abstract_State);
+ Set_Elist8 (Id, V);
+ end Set_Refinement_Constituents;
+
procedure Set_Register_Exception_Call (Id : E; V : N) is
begin
pragma Assert (Ekind (Id) = E_Exception);
@@ -6279,20 +6323,31 @@ package body Einfo is
function Get_Pragma (E : Entity_Id; Id : Pragma_Id) return Node_Id is
Is_CDG : constant Boolean :=
- Id = Pragma_Depends or else Id = Pragma_Global;
- Is_CTC : constant Boolean :=
- Id = Pragma_Contract_Cases or else Id = Pragma_Test_Case;
- Is_PPC : constant Boolean :=
- Id = Pragma_Precondition or else Id = Pragma_Postcondition;
- Delayed : constant Boolean := Is_CDG or Is_CTC or Is_PPC;
- Item : Node_Id;
- Items : Node_Id;
-
- begin
- -- Handle delayed pragmas that appear in N_Contract nodes. Those have to
- -- be extracted from their specialized list.
-
- if Delayed then
+ Id = Pragma_Abstract_State or else
+ Id = Pragma_Depends or else
+ Id = Pragma_Global or else
+ Id = Pragma_Initial_Condition or else
+ Id = Pragma_Initializes or else
+ Id = Pragma_Refined_Depends or else
+ Id = Pragma_Refined_Global or else
+ Id = Pragma_Refined_State;
+ Is_CTC : constant Boolean :=
+ Id = Pragma_Contract_Cases or else
+ Id = Pragma_Test_Case;
+ Is_PPC : constant Boolean :=
+ Id = Pragma_Precondition or else
+ Id = Pragma_Postcondition;
+
+ In_Contract : constant Boolean := Is_CDG or Is_CTC or Is_PPC;
+
+ Item : Node_Id;
+ Items : Node_Id;
+
+ begin
+ -- Handle pragmas that appear in N_Contract nodes. Those have to be
+ -- extracted from their specialized list.
+
+ if In_Contract then
Items := Contract (E);
if No (Items) then
@@ -6322,7 +6377,7 @@ package body Einfo is
-- All nodes in N_Contract are chained using Next_Pragma
- elsif Delayed then
+ elsif In_Contract then
Item := Next_Pragma (Item);
-- Regular pragmas
@@ -6440,6 +6495,65 @@ package body Einfo is
return False;
end Has_Interrupt_Handler;
+ -----------------------------
+ -- Has_Non_Null_Refinement --
+ -----------------------------
+
+ function Has_Non_Null_Refinement (Id : E) return B is
+ begin
+ -- "Refinement" is a concept applicable only to abstract states
+
+ pragma Assert (Ekind (Id) = E_Abstract_State);
+
+ if Has_Visible_Refinement (Id) then
+ pragma Assert (Present (Refinement_Constituents (Id)));
+
+ -- For a refinement to be non-null, the first constituent must be
+ -- anything other than null.
+
+ return
+ Nkind (Node (First_Elmt (Refinement_Constituents (Id)))) /= N_Null;
+ end if;
+
+ return False;
+ end Has_Non_Null_Refinement;
+
+ -----------------------------
+ -- Has_Null_Abstract_State --
+ -----------------------------
+
+ function Has_Null_Abstract_State (Id : E) return B is
+ begin
+ pragma Assert (Ekind_In (Id, E_Generic_Package, E_Package));
+
+ return
+ Present (Abstract_States (Id))
+ and then Is_Null_State (Node (First_Elmt (Abstract_States (Id))));
+ end Has_Null_Abstract_State;
+
+ -------------------------
+ -- Has_Null_Refinement --
+ -------------------------
+
+ function Has_Null_Refinement (Id : E) return B is
+ begin
+ -- "Refinement" is a concept applicable only to abstract states
+
+ pragma Assert (Ekind (Id) = E_Abstract_State);
+
+ if Has_Visible_Refinement (Id) then
+ pragma Assert (Present (Refinement_Constituents (Id)));
+
+ -- For a refinement to be null, the state's sole constituent must be
+ -- a null.
+
+ return
+ Nkind (Node (First_Elmt (Refinement_Constituents (Id)))) = N_Null;
+ end if;
+
+ return False;
+ end Has_Null_Refinement;
+
--------------------
-- Has_Unmodified --
--------------------
@@ -6655,6 +6769,16 @@ package body Einfo is
and then Is_Entity_Attribute_Name (Attribute_Name (N)));
end Is_Entity_Name;
+ -----------------------
+ -- Is_External_State --
+ -----------------------
+
+ function Is_External_State (Id : E) return B is
+ begin
+ return
+ Ekind (Id) = E_Abstract_State and then Has_Option (Id, Name_External);
+ end Is_External_State;
+
------------------
-- Is_Finalizer --
------------------
@@ -6690,15 +6814,27 @@ package body Einfo is
end if;
end Is_Ghost_Subprogram;
- --------------------
- -- Is_Input_State --
- --------------------
+ -------------------------
+ -- Is_Input_Only_State --
+ -------------------------
+
+ function Is_Input_Only_State (Id : E) return B is
+ begin
+ return
+ Ekind (Id) = E_Abstract_State
+ and then Has_Option (Id, Name_Input_Only);
+ end Is_Input_Only_State;
- function Is_Input_State (Id : E) return B is
+ ---------------------------
+ -- Is_Non_Volatile_State --
+ ---------------------------
+
+ function Is_Non_Volatile_State (Id : E) return B is
begin
return
- Ekind (Id) = E_Abstract_State and then Has_Property (Id, Name_Input);
- end Is_Input_State;
+ Ekind (Id) = E_Abstract_State
+ and then Has_Option (Id, Name_Non_Volatile);
+ end Is_Non_Volatile_State;
-------------------
-- Is_Null_State --
@@ -6714,11 +6850,12 @@ package body Einfo is
-- Is_Output_State --
---------------------
- function Is_Output_State (Id : E) return B is
+ function Is_Output_Only_State (Id : E) return B is
begin
return
- Ekind (Id) = E_Abstract_State and then Has_Property (Id, Name_Output);
- end Is_Output_State;
+ Ekind (Id) = E_Abstract_State
+ and then Has_Option (Id, Name_Output_Only);
+ end Is_Output_Only_State;
-----------------------------------
-- Is_Package_Or_Generic_Package --
@@ -6859,17 +6996,6 @@ package body Einfo is
and then Is_Task_Type (Corresponding_Concurrent_Type (Id));
end Is_Task_Record_Type;
- -----------------------
- -- Is_Volatile_State --
- -----------------------
-
- function Is_Volatile_State (Id : E) return B is
- begin
- return
- Ekind (Id) = E_Abstract_State
- and then Has_Property (Id, Name_Volatile);
- end Is_Volatile_State;
-
------------------------
-- Is_Wrapper_Package --
------------------------
@@ -7771,7 +7897,7 @@ package body Einfo is
-- view then we return the Underlying_Type of its non-limited
-- view.
- elsif From_With_Type (Id)
+ elsif From_Limited_With (Id)
and then Present (Non_Limited_View (Id))
then
return Underlying_Type (Non_Limited_View (Id));
@@ -7874,13 +8000,14 @@ package body Einfo is
W ("Entry_Accepted", Flag152 (Id));
W ("Can_Use_Internal_Rep", Flag229 (Id));
W ("Finalize_Storage_Only", Flag158 (Id));
- W ("From_With_Type", Flag159 (Id));
+ W ("From_Limited_With", Flag159 (Id));
W ("Has_Aliased_Components", Flag135 (Id));
W ("Has_Alignment_Clause", Flag46 (Id));
W ("Has_All_Calls_Remote", Flag79 (Id));
W ("Has_Anonymous_Master", Flag253 (Id));
W ("Has_Atomic_Components", Flag86 (Id));
W ("Has_Biased_Representation", Flag139 (Id));
+ W ("Has_Body_References", Flag264 (Id));
W ("Has_Completion", Flag26 (Id));
W ("Has_Completion_In_Body", Flag71 (Id));
W ("Has_Complex_Representation", Flag140 (Id));
@@ -7954,6 +8081,7 @@ package body Einfo is
W ("Has_Unchecked_Union", Flag123 (Id));
W ("Has_Unknown_Discriminants", Flag72 (Id));
W ("Has_Up_Level_Access", Flag215 (Id));
+ W ("Has_Visible_Refinement", Flag263 (Id));
W ("Has_Volatile_Components", Flag87 (Id));
W ("Has_Xref_Entry", Flag182 (Id));
W ("In_Package_Body", Flag48 (Id));
@@ -8281,9 +8409,6 @@ package body Einfo is
when E_Variable =>
Write_Str ("Hiding_Loop_Variable");
- when E_Abstract_State =>
- Write_Str ("Integrity_Level");
-
when Formal_Kind |
E_Function |
E_Subprogram_Body =>
@@ -8296,6 +8421,9 @@ package body Einfo is
when E_Procedure =>
Write_Str ("Postcondition_Proc");
+ when E_Abstract_State =>
+ Write_Str ("Refinement_Constituents");
+
when E_Return_Statement =>
Write_Str ("Return_Applies_To");
@@ -8317,9 +8445,6 @@ package body Einfo is
when Object_Kind =>
Write_Str ("Current_Value");
- when E_Abstract_State =>
- Write_Str ("Refined_State");
-
when E_Function |
E_Generic_Function |
E_Generic_Package |
@@ -8348,7 +8473,7 @@ package body Einfo is
Concurrent_Kind =>
Write_Str ("Direct_Primitive_Operations");
- when Float_Kind =>
+ when Float_Kind =>
Write_Str ("Float_Rep");
when E_In_Parameter |
@@ -8365,6 +8490,10 @@ package body Einfo is
E_Discriminant =>
Write_Str ("Normalized_Position_Max");
+ when E_Abstract_State |
+ E_Variable =>
+ Write_Str ("Refined_State");
+
when others =>
Write_Str ("Field10??");
end case;
@@ -8571,6 +8700,9 @@ package body Einfo is
E_Record_Type_With_Private =>
Write_Str ("Access_Disp_Table");
+ when E_Abstract_State =>
+ Write_Str ("Body_References");
+
when E_Record_Subtype |
E_Class_Wide_Subtype =>
Write_Str ("Cloned_Subtype");
@@ -8659,7 +8791,7 @@ package body Einfo is
Write_Str ("Non_Limited_View");
when E_Incomplete_Subtype =>
- if From_With_Type (Id) then
+ if From_Limited_With (Id) then
Write_Str ("Non_Limited_View");
end if;
@@ -8745,7 +8877,7 @@ package body Einfo is
Write_Str ("Corresponding_Discriminant");
when Scalar_Kind =>
- Write_Str ("Default_Value");
+ Write_Str ("Default_Aspect_Value");
when E_Array_Type =>
Write_Str ("Default_Component_Value");
@@ -9005,10 +9137,6 @@ package body Einfo is
procedure Write_Field24_Name (Id : Entity_Id) is
begin
case Ekind (Id) is
- when E_Package |
- E_Package_Body =>
- Write_Str ("Finalizer");
-
when E_Constant |
E_Variable |
Type_Kind =>
@@ -9016,8 +9144,12 @@ package body Einfo is
when E_Entry |
E_Entry_Family |
- Subprogram_Kind |
- Generic_Subprogram_Kind =>
+ E_Generic_Package |
+ E_Package |
+ E_Package_Body |
+ E_Subprogram_Body |
+ Generic_Subprogram_Kind |
+ Subprogram_Kind =>
Write_Str ("Contract");
when others =>
@@ -9151,7 +9283,12 @@ package body Einfo is
E_Subprogram_Type =>
Write_Str ("Extra_Formals");
- when E_Constant | E_Variable =>
+ when E_Package |
+ E_Package_Body =>
+ Write_Str ("Finalizer");
+
+ when E_Constant |
+ E_Variable =>
Write_Str ("Initialization_Statements");
when E_Record_Type =>
diff --git a/gcc/ada/einfo.ads b/gcc/ada/einfo.ads
index 0449674d861..0eaf13b43f1 100644
--- a/gcc/ada/einfo.ads
+++ b/gcc/ada/einfo.ads
@@ -493,6 +493,12 @@ package Einfo is
-- units. Indicates that the source for the body must be included
-- when the unit is part of a standalone library.
+-- Body_References (Elist16)
+-- Defined in abstract state entities. Only set if Has_Body_References
+-- flag is set True, in which case it contains an element list of global
+-- references (identifiers) in the current package body to this abstract
+-- state that are illegal if the abstract state has a visible refinement.
+
-- C_Pass_By_Copy (Flag125) [implementation base type only]
-- Defined in record types. Set if a pragma Convention for the record
-- type specifies convention C_Pass_By_Copy. This convention name is
@@ -505,10 +511,10 @@ package Einfo is
-- Can_Never_Be_Null (Flag38)
-- This flag is defined in all entities, but can only be set in an object
--- which can never have a null value. This is set True for constant
--- access values initialized to a non-null value. This is also True for
--- all access parameters in Ada 83 and Ada 95 modes, and for access
--- parameters that explicitly exclude null in Ada 2005.
+-- which can never have a null value. Set for constant access values
+-- initialized to a non-null value. This is also set for all access
+-- parameters in Ada 83 and Ada 95 modes, and for access parameters
+-- that explicitly exclude null in Ada 2005.
--
-- This is used to avoid unnecessary resetting of the Is_Known_Non_Null
-- flag for such entities. In Ada 2005 mode, this is also used when
@@ -651,7 +657,7 @@ package Einfo is
-- Corresponding_Concurrent_Type (Node18)
-- Defined in record types that are constructed by the expander to
-- represent task and protected types (Is_Concurrent_Record_Type flag
--- set True). Points to the entity for the corresponding task type or
+-- set). Points to the entity for the corresponding task type or the
-- protected type.
-- Corresponding_Discriminant (Node19)
@@ -678,7 +684,7 @@ package Einfo is
-- Corresponding_Remote_Type (Node22)
-- Defined in record types that describe the fat pointer structure for
-- Remote_Access_To_Subprogram types. References the original access
--- type.
+-- to subprogram type.
-- CR_Discriminant (Node23)
-- Defined in discriminants of concurrent types. Denotes the homologous
@@ -738,13 +744,13 @@ package Einfo is
-- subprograms, this returns the {function,procedure}_specification, not
-- the subprogram_declaration.
--- Default_Aspect_Component_Value (Node19)
+-- Default_Aspect_Component_Value (Node19) [base type only]
-- Defined in array types. Holds the static value specified in a
--- default_component_value aspect specification for the array type.
+-- Default_Component_Value aspect specification for the array type.
--- Default_Aspect_Value (Node19)
+-- Default_Aspect_Value (Node19) [base type only]
-- Defined in scalar types. Holds the static value specified in a
--- default_value aspect specification for the type.
+-- Default_Value aspect specification for the type.
-- Default_Expr_Function (Node21)
-- Defined in parameters. It holds the entity of the parameterless
@@ -1022,9 +1028,10 @@ package Einfo is
-- 'COUNT when it applies to a family member.
-- Contract (Node24)
--- Defined in entries, and in subprogram and generic subprogram entities.
--- Points to the contract of the entity, holding both pre- and
--- postconditions as well as test-cases.
+-- Defined in entry, entry family, package, package body, subprogram and
+-- subprogram body entities as well as their respective generic forms.
+-- Points to the contract of the entity, holding various assertion items
+-- and data classifiers.
-- Entry_Parameters_Type (Node15)
-- Defined in entries. Points to the access-to-record type that is
@@ -1181,7 +1188,7 @@ package Einfo is
-- the Finalize_Storage_Only pragma is required at each level of
-- derivation.
--- Finalizer (Node24)
+-- Finalizer (Node28)
-- Applies to package declarations and bodies. Contains the entity of the
-- library-level program which finalizes all package-level controlled
-- objects.
@@ -1308,19 +1315,11 @@ package Einfo is
-- associated with the entity, then this field is Empty. See package
-- Freeze for further details.
--- From_With_Type (Flag159)
--- Defined in package and type entities. Indicates that the entity
--- appears in a With_Type clause in the context of some other unit,
--- either as the prefix (which must be a package), or as a type name.
--- The package can only be used to retrieve such a type, and the type
--- can be used only in component declarations and access definitions.
--- The With_Type clause is used to construct mutually recursive
--- types, i.e. record types (Java classes) that hold pointers to each
--- other. If such a type is an access type, it has no explicit freeze
--- node, so that the back-end does not attempt to elaborate it.
--- Currently this flag is also used to implement Ada 2005 (AI-50217).
--- It will be renamed to From_Limited_With after removal of the current
--- GNAT with_type clause???
+-- From_Limited_With (Flag159)
+-- Defined in package and type entities. Set to True when the related
+-- entity is generated by the expansion of a limited with clause. Such
+-- an entity is said to be a "shadow" - it acts as the incomplete view
+-- of a type by inheriting relevant attributes from the said type.
-- Full_View (Node11)
-- Defined in all type and subtype entities and in deferred constants.
@@ -1360,14 +1359,14 @@ package Einfo is
-- of derived type declarations).
-- Has_All_Calls_Remote (Flag79)
--- Defined in all library unit entities. Set true if the library unit
--- has an All_Calls_Remote pragma. Note that such entities must also
--- be RCI entities, so the flag Is_Remote_Call_Interface will always
--- be set if this flag is set.
+-- Defined in all library unit entities. Set if the library unit has an
+-- All_Calls_Remote pragma. Note that such entities must also be RCI
+-- entities, so the flag Is_Remote_Call_Interface will always be set if
+-- this flag is set.
-- Has_Anonymous_Master (Flag253)
-- Defined in units (top-level functions and procedures, library-level
--- packages). Set to True if the associated unit contains a heterogeneous
+-- packages). Set if the associated unit contains a heterogeneous
-- finalization master. The master's name is of the form <unit>AM and it
-- services anonymous access-to-controlled types with an undetermined
-- lifetime.
@@ -1404,6 +1403,10 @@ package Einfo is
-- size of the type, forcing biased representation for the object, but
-- the subtype is still an unbiased type.
+-- Has_Body_References (Flag264)
+-- Defined in entities for abstract states. Set if Body_References has
+-- at least one entry.
+
-- Has_Completion (Flag26)
-- Defined in all entities that require a completion (functions,
-- procedures, private types, limited private types, incomplete types,
@@ -1437,11 +1440,11 @@ package Einfo is
-- in sem_aux is used to test for this case.
-- Has_Contiguous_Rep (Flag181)
--- Defined in enumeration types. True if the type as a representation
+-- Defined in enumeration types. Set if the type as a representation
-- clause whose entries are successive integers.
-- Has_Controlling_Result (Flag98)
--- Defined in E_Function entities. True if the function is a primitive
+-- Defined in E_Function entities. Set if the function is a primitive
-- function of a tagged type which can dispatch on result.
-- Has_Controlled_Component (Flag43) [base type only]
@@ -1451,13 +1454,13 @@ package Einfo is
-- Has_Controlled_Component is set for at least one component).
-- Has_Convention_Pragma (Flag119)
--- Defined in all entities. Set true for an entity for which a valid
--- Convention, Import, or Export pragma has been given. Used to prevent
--- more than one such pragma appearing for a given entity (RM B.1(45)).
+-- Defined in all entities. Set for an entity for which a valid pragma
+-- Convention, Import, or Export has been given. Used to prevent more
+-- than one such pragma appearing for a given entity (RM B.1(45)).
-- Has_Delayed_Aspects (Flag200)
--- Defined in all entities. Set true if the Rep_Item chain for the entity
--- has one or more N_Aspect_Definition nodes chained which are not to be
+-- Defined in all entities. Set if the Rep_Item chain for the entity has
+-- one or more N_Aspect_Definition nodes chained which are not to be
-- evaluated till the freeze point. The aspect definition expression
-- clause has been preanalyzed to get visibility at the point of use,
-- but no other action has been taken.
@@ -1530,18 +1533,18 @@ package Einfo is
-- Convention_Intrinsic, Convention_Entry or Convention_Protected).
-- Has_Forward_Instantiation (Flag175)
--- Defined in package entities. Set true for packages that contain
--- instantiations of local generic entities, before the corresponding
--- generic body has been seen. If a package has a forward instantiation,
--- we cannot inline subprograms appearing in the same package because
--- the placement requirements of the instance will conflict with the
--- linear elaboration of front-end inlining.
+-- Defined in package entities. Set for packages that instantiate local
+-- generic entities before the corresponding generic body has been seen.
+-- If a package has a forward instantiation, we cannot inline subprograms
+-- appearing in the same package because the placement requirements of
+-- the instance will conflict with the linear elaboration of front-end
+-- inlining.
-- Has_Fully_Qualified_Name (Flag173)
--- Defined in all entities. Set True if the name in the Chars field has
--- been replaced by the fully qualified name, as used for debug output.
--- See Exp_Dbug for a full description of the use of this flag and also
--- the related flag Has_Qualified_Name.
+-- Defined in all entities. Set if the name in the Chars field has been
+-- replaced by the fully qualified name, as used for debug output. See
+-- Exp_Dbug for a full description of the use of this flag and also the
+-- related flag Has_Qualified_Name.
-- Has_Gigi_Rep_Item (Flag82)
-- Defined in all entities. Set if the rep item chain (referenced by
@@ -1575,7 +1578,7 @@ package Einfo is
-- applies (as set by coresponding pragma or aspect specification).
-- Has_Inheritable_Invariants (Flag248)
--- Defined in all type entities. Set True in private types from which one
+-- Defined in all type entities. Set in private types from which one
-- or more Invariant'Class aspects will be inherited if a another type is
-- derived from the type (i.e. those types which have an Invariant'Class
-- aspect, or which inherit one or more Invariant'Class aspects). Also
@@ -1598,7 +1601,7 @@ package Einfo is
-- Interrupt_Handler applies.
-- Has_Invariants (Flag232)
--- Defined in all type entities and in subprogram entities. Set True in
+-- Defined in all type entities and in subprogram entities. Set in
-- private types if an Invariant or Invariant'Class aspect applies to the
-- type, or if the type inherits one or more Invariant'Class aspects.
-- Also set in the corresponding full type. Note: if this flag is set
@@ -1635,6 +1638,10 @@ package Einfo is
-- optimizations to ensure that they are consistent with exceptions.
-- See documentation in Gigi for further details.
+-- Has_Non_Null_Refinement (synth)
+-- Defined in E_Abstract_State entities. True if the state has at least
+-- one variable or state constituent in aspect/pragma Refined_State.
+
-- Has_Non_Standard_Rep (Flag75) [implementation base type only]
-- Defined in all type entities. Set when some representation clause
-- or pragma causes the representation of the item to be significantly
@@ -1645,15 +1652,23 @@ package Einfo is
-- are not considered to be significant since they do not affect
-- stored bit patterns.
+-- Has_Null_Abstract_State (synth)
+-- Defined in package entities. True if the package is subject to a null
+-- Abstract_State aspect/pragma.
+
+-- Has_Null_Refinement (synth)
+-- Defined in E_Abstract_State entities. True if the state has a null
+-- refinement in aspect/pragma Refined_State.
+
-- Has_Object_Size_Clause (Flag172)
-- Defined in entities for types and subtypes. Set if an Object_Size
-- clause has been processed for the type Used to prevent multiple
-- Object_Size clauses for a given entity.
-- Has_Per_Object_Constraint (Flag154)
--- Defined in E_Component entities, true if the subtype of the
--- component has a per object constraint. Per object constraints result
--- from the following situations:
+-- Defined in E_Component entities. Set if the subtype of the component
+-- has a per object constraint. Per object constraints result from the
+-- following situations :
--
-- 1. N_Attribute_Reference - when the prefix is the enclosing type and
-- the attribute is Access.
@@ -1765,27 +1780,27 @@ package Einfo is
-- some ancestor is derived from a private type, making some components
-- invisible and aggregates illegal. Used to check the legality of
-- selected components and aggregates. The flag is set at the point of
--- derivation.
--- The legality of an aggregate of a type with a private ancestor must
--- be checked because it also depends on the visibility at the point the
--- aggregate is resolved. See sem_aggr.adb. This is part of AI05-0115.
+-- derivation. The legality of an aggregate of a type with a private
+-- ancestor must be checked because it also depends on the visibility
+-- at the point the aggregate is resolved. See sem_aggr.adb. This is
+-- part of AI05-0115.
-- Has_Private_Declaration (Flag155)
--- Defined in all entities. Returns True if it is the defining entity
--- of a private type declaration or its corresponding full declaration.
--- This flag is thus preserved when the full and the partial views are
--- exchanged, to indicate if a full type declaration is a completion.
--- Used for semantic checks in E.4(18) and elsewhere.
+-- Defined in all entities. Set if it is the defining entity of a private
+-- type declaration or its corresponding full declaration. This flag is
+-- thus preserved when the full and the partial views are exchanged, to
+-- indicate if a full type declaration is a completion. Used for semantic
+-- checks in E.4(18) and elsewhere.
-- Has_Qualified_Name (Flag161)
--- Defined in all entities. Set True if the name in the Chars field
--- has been replaced by its qualified name, as used for debug output.
--- See Exp_Dbug for a full description of qualification requirements.
--- For some entities, the name is the fully qualified name, but there
--- are exceptions. In particular, for local variables in procedures,
--- we do not include the procedure itself or higher scopes. See also
--- the flag Has_Fully_Qualified_Name, which is set if the name does
--- indeed include the fully qualified name.
+-- Defined in all entities. Set if the name in the Chars field has
+-- been replaced by its qualified name, as used for debug output. See
+-- Exp_Dbug for a full description of qualification requirements. For
+-- some entities, the name is the fully qualified name, but there are
+-- exceptions. In particular, for local variables in procedures, we
+-- do not include the procedure itself or higher scopes. See also the
+-- flag Has_Fully_Qualified_Name, which is set if the name does indeed
+-- include the fully qualified name.
-- Has_RACW (Flag214)
-- Defined in package spec entities. Set if the spec contains the
@@ -1904,6 +1919,11 @@ package Einfo is
-- VM_Target /= No_VM, for efficiency, since only the .NET back-end
-- makes use of it to generate proper code for up-level references.
+-- Has_Visible_Refinement (Flag263)
+-- Defined in E_Abstract_State entities. Set when a state has at least
+-- one refinement constituent and analysis is in the region between
+-- pragma Refined_State and the end of the package body declarations.
+
-- Has_Volatile_Components (Flag87) [implementation base type only]
-- Defined in all types and objects. Set only for an array type or array
-- object if a valid pragma Volatile_Components or a valid pragma
@@ -1969,11 +1989,6 @@ package Einfo is
-- instantiated within the given generic. Used to diagnose circular
-- instantiations.
--- Integrity_Level (Uint8)
--- Defined for E_Abstract_State entities. Contains the numerical value of
--- the integrity level state property. A value of Uint_0 designates a non
--- existent integrity.
-
-- Interface_Alias (Node25)
-- Defined in subprograms that cover a primitive operation of an abstract
-- interface type. Can be set only if the Is_Hidden flag is also set,
@@ -2168,7 +2183,7 @@ package Einfo is
-- Set if the type or subtype is constrained.
-- Is_Constr_Subt_For_U_Nominal (Flag80)
--- Defined in all types and subtypes. Set true only for the constructed
+-- Defined in all types and subtypes. Set only for the constructed
-- subtype of an object whose nominal subtype is unconstrained. Note
-- that the constructed subtype itself will be constrained.
@@ -2225,9 +2240,9 @@ package Einfo is
-- entity is associated with a dispatch table.
-- Is_Dispatching_Operation (Flag6)
--- Defined in all entities. Set true for procedures, functions,
--- generic procedures and generic functions if the corresponding
--- operation is dispatching.
+-- Defined in all entities. Set for procedures, functions, generic
+-- procedures, and generic functions if the corresponding operation
+-- is dispatching.
-- Is_Dynamic_Scope (synthesized)
-- Applies to all Entities. Returns True if the entity is a dynamic
@@ -2253,9 +2268,9 @@ package Einfo is
-- entities and False for all other entity kinds.
-- Is_Entry_Formal (Flag52)
--- Defined in all entities. Set only for entry formals (which can
--- only be in, in-out or out parameters). This flag is used to speed
--- up the test for the need to replace references in Exp_Ch2.
+-- Defined in all entities. Set only for entry formals (which can only
+-- be in, in-out or out parameters). This flag is used to speed up the
+-- test for the need to replace references in Exp_Ch2.
-- Is_Exported (Flag99)
-- Defined in all entities. Set if the entity is exported. For now we
@@ -2263,6 +2278,10 @@ package Einfo is
-- and variables, but that may well change later on. Exceptions can only
-- be exported in the OpenVMS and Java VM implementations of GNAT.
+-- Is_External_State (synthesized)
+-- Applies to all entities, true for abstract states that are subject to
+-- option External.
+
-- Is_Finalizer (synthesized)
-- Applies to all entities, true for procedures containing finalization
-- code to process local or library level objects.
@@ -2334,7 +2353,7 @@ package Einfo is
-- convention.
-- Is_Hidden (Flag57)
--- Defined in all entities. Set true for all entities declared in the
+-- Defined in all entities. Set for all entities declared in the
-- private part or body of a package. Also marks generic formals of a
-- formal package declared without a box. For library level entities,
-- this flag is set if the entity is not publicly visible. This flag
@@ -2344,7 +2363,7 @@ package Einfo is
-- Private_Declaration in sem_ch7).
-- Is_Hidden_Open_Scope (Flag171)
--- Defined in all entities. Set true for a scope that contains the
+-- Defined in all entities. Set for a scope that contains the
-- instantiation of a child unit, and whose entities are not visible
-- during analysis of the instance.
@@ -2380,9 +2399,9 @@ package Einfo is
-- inherited by their instances. It is also set on the body entities
-- of inlined subprograms. See also Has_Pragma_Inline.
--- Is_Input_State (synthesized)
+-- Is_Input_Only_State (synthesized)
-- Applies to all entities, true for abstract states that are subject to
--- property Input.
+-- option Input_Only.
-- Is_Instantiated (Flag126)
-- Defined in generic packages and generic subprograms. Set if the unit
@@ -2458,20 +2477,20 @@ package Einfo is
-- to be defined) must be in the same scope as the type.
-- Is_Known_Non_Null (Flag37)
--- Defined in all entities. Relevant (and can be set True) only for
+-- Defined in all entities. Relevant (and can be set) only for
-- objects of an access type. It is set if the object is currently
-- known to have a non-null value (meaning that no access checks
-- are needed). The indication can for example come from assignment
-- of an access parameter or an allocator whose value is known non-null.
--
-- Note: this flag is set according to the sequential flow of the
--- program, watching the current value of the variable. However,
--- this processing can miss cases of changing the value of an aliased
--- or constant object, so even if this flag is set, it should not
--- be believed if the variable is aliased or volatile. It would
--- be a little neater to avoid the flag being set in the first
--- place in such cases, but that's trickier, and there is only
--- one place that tests the value anyway.
+-- program, watching the current value of the variable. However, this
+-- processing can miss cases of changing the value of an aliased or
+-- constant object, so even if this flag is set, it should not be
+-- believed if the variable is aliased or volatile. It would be a
+-- little neater to avoid the flag being set in the first place in
+-- such cases, but that's trickier, and there is only one place that
+-- tests the value anyway.
--
-- The flag is dynamically set and reset as semantic analysis and
-- expansion proceeds. Its value is meaningless once the tree is
@@ -2479,7 +2498,7 @@ package Einfo is
-- Thus this flag has no meaning to the back end.
-- Is_Known_Null (Flag204)
--- Defined in all entities. Relevant (and can be set True) only for
+-- Defined in all entities. Relevant (and can be set ) only for
-- objects of an access type. It is set if the object is currently known
-- to have a null value (meaning that a dereference will surely raise
-- constraint error exception). The indication can come from an
@@ -2573,6 +2592,10 @@ package Einfo is
-- set right, at which point, these comments can be removed, and the
-- tests for static subtypes greatly simplified.
+-- Is_Non_Volatile_State (synthesized)
+-- Applies to all entities, true for abstract states that are subject to
+-- option Non_Volatile.
+
-- Is_Null_Init_Proc (Flag178)
-- Defined in procedure entities. Set for generated init proc procedures
-- (used to initialize composite types), if the code for the procedure
@@ -2613,9 +2636,9 @@ package Einfo is
-- Applies to all entities, true for ordinary fixed point types and
-- subtypes.
--- Is_Output_State (synthesized)
+-- Is_Output_Only_State (synthesized)
-- Applies to all entities, true for abstract states that are subject to
--- property Output.
+-- option Output_Only.
-- Is_Package_Or_Generic_Package (synthesized)
-- Applies to all entities. True for packages and generic packages.
@@ -2833,7 +2856,7 @@ package Einfo is
-- Wide_Wide_Character).
-- Is_Statically_Allocated (Flag28)
--- Defined in all entities. This can only be set True for exception,
+-- Defined in all entities. This can only be set for exception,
-- variable, constant, and type/subtype entities. If the flag is set,
-- then the variable or constant must be allocated statically rather
-- than on the local stack frame. For exceptions, the meaning is that
@@ -2943,7 +2966,7 @@ package Einfo is
-- or Export_Valued_Procedure pragma applies to the procedure entity.
-- Is_Visible_Formal (Flag206)
--- Defined in all entities. Set True for instances of the formals of a
+-- Defined in all entities. Set for instances of the formals of a
-- formal package. Indicates that the entity must be made visible in the
-- body of the instance, to reproduce the visibility of the generic.
-- This simplifies visibility settings in instance bodies.
@@ -2974,10 +2997,6 @@ package Einfo is
-- optimizations on volatile objects should test Treat_As_Volatile
-- rather than testing this flag.
--- Is_Volatile_State (synthesized)
--- Applies to all entities, true for abstract states that are subject to
--- property Volatile.
-
-- Is_Wrapper_Package (synthesized)
-- Defined in package entities. Indicates that the package has been
-- created as a wrapper for a subprogram instantiation.
@@ -3054,10 +3073,10 @@ package Einfo is
-- Value attributes for the enumeration type in question.
-- Low_Bound_Tested (Flag205)
--- Defined in all entities. Currently this can only be set True for
--- formal parameter entries of a standard unconstrained one-dimensional
--- array or string type. Indicates that an explicit test of the low bound
--- of the formal appeared in the code, e.g. in a pragma Assert. If this
+-- Defined in all entities. Currently this can only be set for formal
+-- parameter entries of a standard unconstrained one-dimensional array
+-- or string type. Indicates that an explicit test of the low bound of
+-- the formal appeared in the code, e.g. in a pragma Assert. If this
-- flag is set, warnings about assuming the index low bound to be one
-- are suppressed.
@@ -3248,8 +3267,8 @@ package Einfo is
-- the defining entity in the original declaration.
-- Nonzero_Is_True (Flag162) [base type only]
--- Defined in enumeration types. True if any non-zero value is to be
--- interpreted as true. Currently this is set true for derived Boolean
+-- Defined in enumeration types. Set if any non-zero value is to be
+-- interpreted as true. Currently this is set for derived Boolean
-- types which have a convention of C, C++ or Fortran.
-- No_Pool_Assigned (Flag131) [root type only]
@@ -3534,9 +3553,14 @@ package Einfo is
-- we have a separate warning for variables that are only assigned and
-- never read, and out parameters are a special case.
--- Refined_State (Node9)
--- Defined in E_Abstract_State entities. Contains the entity of the
--- abstract state completion which is usually foung in package bodies.
+-- Refined_State (Node10)
+-- Defined in abstract states and variables. Contains the entity of an
+-- ancestor state whose refinement mentions this item.
+
+-- Refinement_Constituents (Elist8)
+-- Present in abstract state entities. Contains all the constituents that
+-- refine the state, in other words, all the hidden states that appear in
+-- the constituent_list of aspect/pragma Refined_State.
-- Register_Exception_Call (Node20)
-- Defined in exception entities. When an exception is declared,
@@ -3787,8 +3811,8 @@ package Einfo is
-- Static_Predicate (List25)
-- Defined in discrete types/subtypes with predicates (Has_Predicates
--- set True). Set if the type/subtype has a static predicate. Points to
--- a list of expression and N_Range nodes that represent the predicate
+-- set). Set if the type/subtype has a static predicate. Points to a
+-- list of expression and N_Range nodes that represent the predicate
-- in canonical form. The canonical form has entries sorted in ascending
-- order, with duplicates eliminated, and adjacent ranges coalesced, so
-- that there is always a gap in the values between successive entries.
@@ -5017,7 +5041,7 @@ package Einfo is
-- Depends_On_Private (Flag14)
-- Discard_Names (Flag88)
-- Finalize_Storage_Only (Flag158) (base type only)
- -- From_With_Type (Flag159)
+ -- From_Limited_With (Flag159)
-- Has_Aliased_Components (Flag135) (base type only)
-- Has_Alignment_Clause (Flag46)
-- Has_Atomic_Components (Flag86) (base type only)
@@ -5093,12 +5117,18 @@ package Einfo is
------------------------------------------
-- E_Abstract_State
- -- Integrity_Level (Uint8)
- -- Refined_State (Node9)
- -- Is_Input_State (synth)
+ -- Refinement_Constituents (Elist8)
+ -- Refined_State (Node10)
+ -- Body_References (Elist16)
+ -- Has_Body_References (Flag264)
+ -- Has_Visible_Refinement (Flag263)
+ -- Has_Non_Null_Refinement (synth)
+ -- Has_Null_Refinement (synth)
+ -- Is_External_State (synth)
+ -- Is_Input_Only_State (synth)
-- Is_Null_State (synth)
- -- Is_Output_State (synth)
- -- Is_Volatile_State (synth)
+ -- Is_Output_Only_State (synth)
+ -- Is_Non_Volatile_State (synth)
-- E_Access_Protected_Subprogram_Type
-- Equivalent_Type (Node18)
@@ -5156,7 +5186,7 @@ package Einfo is
-- E_Array_Type
-- E_Array_Subtype
-- First_Index (Node17)
- -- Default_Aspect_Component_Value (Node19)
+ -- Default_Aspect_Component_Value (Node19) (base type only)
-- Component_Type (Node20) (base type only)
-- Original_Array_Type (Node21)
-- Component_Size (Uint22) (base type only)
@@ -5307,7 +5337,7 @@ package Einfo is
-- Accept_Address (Elist21)
-- Scope_Depth_Value (Uint22)
-- Protection_Object (Node23) (protected kind)
- -- Contract (Node24) (for entry only)
+ -- Contract (Node24)
-- PPC_Wrapper (Node25)
-- Extra_Formals (Node28)
-- Default_Expressions_Processed (Flag108)
@@ -5339,7 +5369,7 @@ package Einfo is
-- Lit_Indexes (Node15) (root type only)
-- Lit_Strings (Node16) (root type only)
-- First_Literal (Node17)
- -- Default_Aspect_Value (Node19)
+ -- Default_Aspect_Value (Node19) (base type only)
-- Scalar_Range (Node20)
-- Enum_Pos_To_Rep (Node23) (type only)
-- Static_Predicate (List25)
@@ -5371,7 +5401,7 @@ package Einfo is
-- E_Floating_Point_Subtype
-- Digits_Value (Uint17)
-- Float_Rep (Uint10) (Float_Rep_Kind)
- -- Default_Aspect_Value (Node19)
+ -- Default_Aspect_Value (Node19) (base type only)
-- Scalar_Range (Node20)
-- Machine_Emax_Value (synth)
-- Machine_Emin_Value (synth)
@@ -5549,7 +5579,7 @@ package Einfo is
-- E_Modular_Integer_Type
-- E_Modular_Integer_Subtype
-- Modulus (Uint17) (base type only)
- -- Default_Aspect_Value (Node19)
+ -- Default_Aspect_Value (Node19) (base type only)
-- Original_Array_Type (Node21)
-- Scalar_Range (Node20)
-- Static_Predicate (List25)
@@ -5568,6 +5598,7 @@ package Einfo is
-- Alias (Node18)
-- Extra_Accessibility_Of_Result (Node19)
-- Last_Entity (Node20)
+ -- Contract (Node24)
-- Overridden_Operation (Node26)
-- Subprograms_For_Type (Node29)
-- Has_Invariants (Flag232)
@@ -5583,7 +5614,7 @@ package Einfo is
-- E_Ordinary_Fixed_Point_Type
-- E_Ordinary_Fixed_Point_Subtype
-- Delta_Value (Ureal18)
- -- Default_Aspect_Value (Node19)
+ -- Default_Aspect_Value (Node19) (base type only)
-- Scalar_Range (Node20)
-- Small_Value (Ureal21)
-- Has_Small_Clause (Flag67)
@@ -5612,17 +5643,18 @@ package Einfo is
-- Generic_Renamings (Elist23) (for an instance)
-- Inner_Instances (Elist23) (generic case only)
-- Limited_View (Node23) (non-generic/instance)
- -- Finalizer (Node24) (non-generic case only)
+ -- Contract (Node24)
-- Abstract_States (Elist25)
-- Package_Instantiation (Node26)
-- Current_Use_Clause (Node27)
+ -- Finalizer (Node28) (non-generic case only)
-- SPARK_Mode_Pragmas (Node32)
-- Delay_Subprogram_Descriptors (Flag50)
-- Body_Needed_For_SAL (Flag40)
-- Discard_Names (Flag88)
-- Elaboration_Entity_Required (Flag174)
-- Elaborate_Body_Desirable (Flag210) (non-generic case only)
- -- From_With_Type (Flag159)
+ -- From_Limited_With (Flag159)
-- Has_All_Calls_Remote (Flag79)
-- Has_Anonymous_Master (Flag253)
-- Has_Completion (Flag26)
@@ -5636,6 +5668,7 @@ package Einfo is
-- Is_Visible_Lib_Unit (Flag116)
-- Renamed_In_Spec (Flag231) (non-generic case only)
-- Static_Elaboration_Desired (Flag77) (non-generic case only)
+ -- Has_Null_Abstract_State (synth)
-- Is_Wrapper_Package (synth) (non-generic case only)
-- Scope_Depth (synth)
@@ -5646,7 +5679,8 @@ package Einfo is
-- Spec_Entity (Node19)
-- Last_Entity (Node20)
-- Scope_Depth_Value (Uint22)
- -- Finalizer (Node24) (non-generic case only)
+ -- Contract (Node24)
+ -- Finalizer (Node28) (non-generic case only)
-- SPARK_Mode_Pragmas (Node32)
-- Delay_Subprogram_Descriptors (Flag50)
-- Has_Anonymous_Master (Flag253)
@@ -5834,7 +5868,7 @@ package Einfo is
-- E_Signed_Integer_Type
-- E_Signed_Integer_Subtype
- -- Default_Aspect_Value (Node19)
+ -- Default_Aspect_Value (Node19) (base type only)
-- Scalar_Range (Node20)
-- Static_Predicate (List25)
-- Has_Biased_Representation (Flag139)
@@ -5864,6 +5898,7 @@ package Einfo is
-- Corresponding_Protected_Entry (Node18)
-- Last_Entity (Node20)
-- Scope_Depth_Value (Uint22)
+ -- Contract (Node24)
-- Extra_Formals (Node28)
-- SPARK_Mode_Pragmas (Node32)
-- Scope_Depth (synth)
@@ -5907,6 +5942,7 @@ package Einfo is
-- E_Variable
-- Hiding_Loop_Variable (Node8)
-- Current_Value (Node9)
+ -- Refined_State (Node10)
-- Esize (Uint12)
-- Extra_Accessibility (Node13)
-- Alignment (Uint14)
@@ -6198,6 +6234,7 @@ package Einfo is
function Block_Node (Id : E) return N;
function Body_Entity (Id : E) return E;
function Body_Needed_For_SAL (Id : E) return B;
+ function Body_References (Id : E) return L;
function CR_Discriminant (Id : E) return E;
function C_Pass_By_Copy (Id : E) return B;
function Can_Never_Be_Null (Id : E) return B;
@@ -6282,7 +6319,7 @@ package Einfo is
function First_Rep_Item (Id : E) return N;
function Float_Rep (Id : E) return F;
function Freeze_Node (Id : E) return N;
- function From_With_Type (Id : E) return B;
+ function From_Limited_With (Id : E) return B;
function Full_View (Id : E) return E;
function Generic_Homonym (Id : E) return E;
function Generic_Renamings (Id : E) return L;
@@ -6293,6 +6330,7 @@ package Einfo is
function Has_Anonymous_Master (Id : E) return B;
function Has_Atomic_Components (Id : E) return B;
function Has_Biased_Representation (Id : E) return B;
+ function Has_Body_References (Id : E) return B;
function Has_Completion (Id : E) return B;
function Has_Completion_In_Body (Id : E) return B;
function Has_Complex_Representation (Id : E) return B;
@@ -6369,6 +6407,7 @@ package Einfo is
function Has_Unchecked_Union (Id : E) return B;
function Has_Unknown_Discriminants (Id : E) return B;
function Has_Up_Level_Access (Id : E) return B;
+ function Has_Visible_Refinement (Id : E) return B;
function Has_Volatile_Components (Id : E) return B;
function Has_Xref_Entry (Id : E) return B;
function Hiding_Loop_Variable (Id : E) return E;
@@ -6377,7 +6416,6 @@ package Einfo is
function In_Private_Part (Id : E) return B;
function In_Use (Id : E) return B;
function Initialization_Statements (Id : E) return N;
- function Integrity_Level (Id : E) return U;
function Inner_Instances (Id : E) return L;
function Interface_Alias (Id : E) return E;
function Interface_Name (Id : E) return N;
@@ -6536,6 +6574,7 @@ package Einfo is
function Referenced_As_LHS (Id : E) return B;
function Referenced_As_Out_Parameter (Id : E) return B;
function Refined_State (Id : E) return E;
+ function Refinement_Constituents (Id : E) return L;
function Register_Exception_Call (Id : E) return N;
function Related_Array_Object (Id : E) return E;
function Related_Expression (Id : E) return N;
@@ -6674,18 +6713,23 @@ package Einfo is
function Has_Attach_Handler (Id : E) return B;
function Has_Entries (Id : E) return B;
function Has_Foreign_Convention (Id : E) return B;
+ function Has_Non_Null_Refinement (Id : E) return B;
+ function Has_Null_Abstract_State (Id : E) return B;
+ function Has_Null_Refinement (Id : E) return B;
function Implementation_Base_Type (Id : E) return E;
function Is_Base_Type (Id : E) return B;
function Is_Boolean_Type (Id : E) return B;
function Is_Constant_Object (Id : E) return B;
function Is_Discriminal (Id : E) return B;
function Is_Dynamic_Scope (Id : E) return B;
+ function Is_External_State (Id : E) return B;
function Is_Finalizer (Id : E) return B;
function Is_Ghost_Entity (Id : E) return B;
function Is_Ghost_Subprogram (Id : E) return B;
- function Is_Input_State (Id : E) return B;
+ function Is_Input_Only_State (Id : E) return B;
+ function Is_Non_Volatile_State (Id : E) return B;
function Is_Null_State (Id : E) return B;
- function Is_Output_State (Id : E) return B;
+ function Is_Output_Only_State (Id : E) return B;
function Is_Package_Or_Generic_Package (Id : E) return B;
function Is_Prival (Id : E) return B;
function Is_Protected_Component (Id : E) return B;
@@ -6696,7 +6740,6 @@ package Einfo is
function Is_Synchronized_Interface (Id : E) return B;
function Is_Task_Interface (Id : E) return B;
function Is_Task_Record_Type (Id : E) return B;
- function Is_Volatile_State (Id : E) return B;
function Is_Wrapper_Package (Id : E) return B;
function Last_Formal (Id : E) return E;
function Machine_Emax_Value (Id : E) return U;
@@ -6811,6 +6854,7 @@ package Einfo is
procedure Set_Block_Node (Id : E; V : N);
procedure Set_Body_Entity (Id : E; V : E);
procedure Set_Body_Needed_For_SAL (Id : E; V : B := True);
+ procedure Set_Body_References (Id : E; V : L);
procedure Set_CR_Discriminant (Id : E; V : E);
procedure Set_C_Pass_By_Copy (Id : E; V : B := True);
procedure Set_Can_Never_Be_Null (Id : E; V : B := True);
@@ -6894,7 +6938,7 @@ package Einfo is
procedure Set_First_Rep_Item (Id : E; V : N);
procedure Set_Float_Rep (Id : E; V : F);
procedure Set_Freeze_Node (Id : E; V : N);
- procedure Set_From_With_Type (Id : E; V : B := True);
+ procedure Set_From_Limited_With (Id : E; V : B := True);
procedure Set_Full_View (Id : E; V : E);
procedure Set_Generic_Homonym (Id : E; V : E);
procedure Set_Generic_Renamings (Id : E; V : L);
@@ -6905,6 +6949,7 @@ package Einfo is
procedure Set_Has_Anonymous_Master (Id : E; V : B := True);
procedure Set_Has_Atomic_Components (Id : E; V : B := True);
procedure Set_Has_Biased_Representation (Id : E; V : B := True);
+ procedure Set_Has_Body_References (Id : E; V : B := True);
procedure Set_Has_Completion (Id : E; V : B := True);
procedure Set_Has_Completion_In_Body (Id : E; V : B := True);
procedure Set_Has_Complex_Representation (Id : E; V : B := True);
@@ -6980,6 +7025,7 @@ package Einfo is
procedure Set_Has_Unchecked_Union (Id : E; V : B := True);
procedure Set_Has_Unknown_Discriminants (Id : E; V : B := True);
procedure Set_Has_Up_Level_Access (Id : E; V : B := True);
+ procedure Set_Has_Visible_Refinement (Id : E; V : B := True);
procedure Set_Has_Volatile_Components (Id : E; V : B := True);
procedure Set_Has_Xref_Entry (Id : E; V : B := True);
procedure Set_Hiding_Loop_Variable (Id : E; V : E);
@@ -6988,7 +7034,6 @@ package Einfo is
procedure Set_In_Private_Part (Id : E; V : B := True);
procedure Set_In_Use (Id : E; V : B := True);
procedure Set_Initialization_Statements (Id : E; V : N);
- procedure Set_Integrity_Level (Id : E; V : U);
procedure Set_Inner_Instances (Id : E; V : L);
procedure Set_Interface_Alias (Id : E; V : E);
procedure Set_Interface_Name (Id : E; V : N);
@@ -7153,6 +7198,7 @@ package Einfo is
procedure Set_Referenced_As_LHS (Id : E; V : B := True);
procedure Set_Referenced_As_Out_Parameter (Id : E; V : B := True);
procedure Set_Refined_State (Id : E; V : E);
+ procedure Set_Refinement_Constituents (Id : E; V : L);
procedure Set_Register_Exception_Call (Id : E; V : N);
procedure Set_Related_Array_Object (Id : E; V : E);
procedure Set_Related_Expression (Id : E; V : N);
@@ -7397,11 +7443,19 @@ package Einfo is
-- Empty is returned.
function Get_Pragma (E : Entity_Id; Id : Pragma_Id) return Node_Id;
- -- Searches the Rep_Item chain for a given entity E, for an instance of
- -- a pragma with the given pragma Id. If found, the value returned is the
- -- N_Pragma node, otherwise Empty is returned. Delayed pragmas such as
- -- Precondition, Postcondition, Contract_Cases, Depends and Global appear
- -- in the N_Contract node of entity E and are also handled by this routine.
+ -- Searches the Rep_Item chain of entity E, for an instance of a pragma
+ -- with the given pragma Id. If found, the value returned is the N_Pragma
+ -- node, otherwise Empty is returned. The following contract pragmas that
+ -- appear in N_Contract nodes are also handled by this routine:
+ -- Contract_Cases
+ -- Depends
+ -- Global
+ -- Initial_Condition
+ -- Initializes
+ -- Precondition
+ -- Postcondition
+ -- Refined_Depends
+ -- Refined_Global
function Get_Record_Representation_Clause (E : Entity_Id) return Node_Id;
-- Searches the Rep_Item chain for a given entity E, for a record
@@ -7522,6 +7576,7 @@ package Einfo is
pragma Inline (Block_Node);
pragma Inline (Body_Entity);
pragma Inline (Body_Needed_For_SAL);
+ pragma Inline (Body_References);
pragma Inline (CR_Discriminant);
pragma Inline (C_Pass_By_Copy);
pragma Inline (Can_Never_Be_Null);
@@ -7603,7 +7658,7 @@ package Einfo is
pragma Inline (First_Private_Entity);
pragma Inline (First_Rep_Item);
pragma Inline (Freeze_Node);
- pragma Inline (From_With_Type);
+ pragma Inline (From_Limited_With);
pragma Inline (Full_View);
pragma Inline (Generic_Homonym);
pragma Inline (Generic_Renamings);
@@ -7614,6 +7669,7 @@ package Einfo is
pragma Inline (Has_Anonymous_Master);
pragma Inline (Has_Atomic_Components);
pragma Inline (Has_Biased_Representation);
+ pragma Inline (Has_Body_References);
pragma Inline (Has_Completion);
pragma Inline (Has_Completion_In_Body);
pragma Inline (Has_Complex_Representation);
@@ -7689,6 +7745,7 @@ package Einfo is
pragma Inline (Has_Unchecked_Union);
pragma Inline (Has_Unknown_Discriminants);
pragma Inline (Has_Up_Level_Access);
+ pragma Inline (Has_Visible_Refinement);
pragma Inline (Has_Volatile_Components);
pragma Inline (Has_Xref_Entry);
pragma Inline (Hiding_Loop_Variable);
@@ -7696,7 +7753,6 @@ package Einfo is
pragma Inline (In_Package_Body);
pragma Inline (In_Private_Part);
pragma Inline (In_Use);
- pragma Inline (Integrity_Level);
pragma Inline (Inner_Instances);
pragma Inline (Interface_Alias);
pragma Inline (Interface_Name);
@@ -7904,6 +7960,7 @@ package Einfo is
pragma Inline (Referenced_As_LHS);
pragma Inline (Referenced_As_Out_Parameter);
pragma Inline (Refined_State);
+ pragma Inline (Refinement_Constituents);
pragma Inline (Register_Exception_Call);
pragma Inline (Related_Array_Object);
pragma Inline (Related_Expression);
@@ -7984,6 +8041,7 @@ package Einfo is
pragma Inline (Set_Block_Node);
pragma Inline (Set_Body_Entity);
pragma Inline (Set_Body_Needed_For_SAL);
+ pragma Inline (Set_Body_References);
pragma Inline (Set_CR_Discriminant);
pragma Inline (Set_C_Pass_By_Copy);
pragma Inline (Set_Can_Never_Be_Null);
@@ -8063,7 +8121,7 @@ package Einfo is
pragma Inline (Set_First_Private_Entity);
pragma Inline (Set_First_Rep_Item);
pragma Inline (Set_Freeze_Node);
- pragma Inline (Set_From_With_Type);
+ pragma Inline (Set_From_Limited_With);
pragma Inline (Set_Full_View);
pragma Inline (Set_Generic_Homonym);
pragma Inline (Set_Generic_Renamings);
@@ -8074,6 +8132,7 @@ package Einfo is
pragma Inline (Set_Has_Anonymous_Master);
pragma Inline (Set_Has_Atomic_Components);
pragma Inline (Set_Has_Biased_Representation);
+ pragma Inline (Set_Has_Body_References);
pragma Inline (Set_Has_Completion);
pragma Inline (Set_Has_Completion_In_Body);
pragma Inline (Set_Has_Complex_Representation);
@@ -8149,6 +8208,7 @@ package Einfo is
pragma Inline (Set_Has_Unchecked_Union);
pragma Inline (Set_Has_Unknown_Discriminants);
pragma Inline (Set_Has_Up_Level_Access);
+ pragma Inline (Set_Has_Visible_Refinement);
pragma Inline (Set_Has_Volatile_Components);
pragma Inline (Set_Has_Xref_Entry);
pragma Inline (Set_Hiding_Loop_Variable);
@@ -8157,7 +8217,6 @@ package Einfo is
pragma Inline (Set_In_Private_Part);
pragma Inline (Set_In_Use);
pragma Inline (Set_Inner_Instances);
- pragma Inline (Set_Integrity_Level);
pragma Inline (Set_Interface_Alias);
pragma Inline (Set_Interface_Name);
pragma Inline (Set_Interfaces);
@@ -8321,6 +8380,7 @@ package Einfo is
pragma Inline (Set_Referenced_As_LHS);
pragma Inline (Set_Referenced_As_Out_Parameter);
pragma Inline (Set_Refined_State);
+ pragma Inline (Set_Refinement_Constituents);
pragma Inline (Set_Register_Exception_Call);
pragma Inline (Set_Related_Array_Object);
pragma Inline (Set_Related_Expression);
diff --git a/gcc/ada/elists.adb b/gcc/ada/elists.adb
index 6170585272e..7e62ce49f69 100644
--- a/gcc/ada/elists.adb
+++ b/gcc/ada/elists.adb
@@ -287,6 +287,34 @@ package body Elists is
Elmts.Release;
end Lock;
+ --------------------
+ -- New_Copy_Elist --
+ --------------------
+
+ function New_Copy_Elist (List : Elist_Id) return Elist_Id is
+ Result : Elist_Id;
+ Elmt : Elmt_Id;
+
+ begin
+ if List = No_Elist then
+ return No_Elist;
+
+ -- Replicate the contents of the input list while preserving the
+ -- original order.
+
+ else
+ Result := New_Elmt_List;
+
+ Elmt := First_Elmt (List);
+ while Present (Elmt) loop
+ Append_Elmt (Node (Elmt), Result);
+ Next_Elmt (Elmt);
+ end loop;
+
+ return Result;
+ end if;
+ end New_Copy_Elist;
+
-------------------
-- New_Elmt_List --
-------------------
@@ -397,6 +425,27 @@ package body Elists is
return Elmt /= No_Elmt;
end Present;
+ ------------
+ -- Remove --
+ ------------
+
+ procedure Remove (List : Elist_Id; N : Node_Or_Entity_Id) is
+ Elmt : Elmt_Id;
+
+ begin
+ if Present (List) then
+ Elmt := First_Elmt (List);
+ while Present (Elmt) loop
+ if Node (Elmt) = N then
+ Remove_Elmt (List, Elmt);
+ exit;
+ end if;
+
+ Next_Elmt (Elmt);
+ end loop;
+ end if;
+ end Remove;
+
-----------------
-- Remove_Elmt --
-----------------
diff --git a/gcc/ada/elists.ads b/gcc/ada/elists.ads
index 8f66e0553bf..f0331362ea3 100644
--- a/gcc/ada/elists.ads
+++ b/gcc/ada/elists.ads
@@ -137,12 +137,20 @@ package Elists is
-- Add a new element (N) right after the pre-existing element Elmt
-- It is invalid to call this subprogram with Elmt = No_Elmt.
+ function New_Copy_Elist (List : Elist_Id) return Elist_Id;
+ -- Replicate the contents of a list. Internal list nodes are not shared and
+ -- order of elements is preserved.
+
procedure Replace_Elmt (Elmt : Elmt_Id; New_Node : Node_Or_Entity_Id);
pragma Inline (Replace_Elmt);
-- Causes the given element of the list to refer to New_Node, the node
-- which was previously referred to by Elmt is effectively removed from
-- the list and replaced by New_Node.
+ procedure Remove (List : Elist_Id; N : Node_Or_Entity_Id);
+ -- Remove a node or an entity from a list. If the list does not contain the
+ -- item in question, the routine has no effect.
+
procedure Remove_Elmt (List : Elist_Id; Elmt : Elmt_Id);
-- Removes Elmt from the given list. The node itself is not affected,
-- but the space used by the list element may be (but is not required
diff --git a/gcc/ada/errout.adb b/gcc/ada/errout.adb
index 12cf828a2f2..2c783b2bddf 100644
--- a/gcc/ada/errout.adb
+++ b/gcc/ada/errout.adb
@@ -49,7 +49,6 @@ with Sinfo; use Sinfo;
with Snames; use Snames;
with Stand; use Stand;
with Stylesw; use Stylesw;
-with Targparm; use Targparm;
with Uname; use Uname;
package body Errout is
@@ -234,6 +233,15 @@ package body Errout is
begin
if not Finalize_Called then
raise Program_Error;
+
+ -- In formal verification mode, errors issued when generating Why code
+ -- are not compilation errors, and should not result in exiting with
+ -- an error status. These errors are handled in the driver of the
+ -- verification process instead.
+
+ elsif SPARK_Mode and not Frame_Condition_Mode then
+ return False;
+
else
return Erroutc.Compilation_Errors;
end if;
@@ -1617,15 +1625,19 @@ package body Errout is
Set_Standard_Error;
end if;
- -- Message giving total number of lines
+ -- Message giving total number of lines. Don't give this message if
+ -- the Main_Source line is unknown (this happens in error situations,
+ -- e.g. when integrated preprocessing fails).
- Write_Str (" ");
- Write_Int (Num_Source_Lines (Main_Source_File));
+ if Main_Source_File /= No_Source_File then
+ Write_Str (" ");
+ Write_Int (Num_Source_Lines (Main_Source_File));
- if Num_Source_Lines (Main_Source_File) = 1 then
- Write_Str (" line: ");
- else
- Write_Str (" lines: ");
+ if Num_Source_Lines (Main_Source_File) = 1 then
+ Write_Str (" line: ");
+ else
+ Write_Str (" lines: ");
+ end if;
end if;
if Total_Errors_Detected = 0 then
@@ -1823,8 +1835,13 @@ package body Errout is
begin
Write_Eol;
- Write_Header (Sfile);
- Write_Eol;
+
+ -- Only write the header if Sfile is known
+
+ if Sfile /= No_Source_File then
+ Write_Header (Sfile);
+ Write_Eol;
+ end if;
-- Normally, we don't want an "error messages from file"
-- message when listing the entire file, so we set the
@@ -1839,28 +1856,33 @@ package body Errout is
Current_Error_Source_File := Sfile;
end if;
- for N in 1 .. Last_Source_Line (Sfile) loop
- while E /= No_Error_Msg
- and then Errors.Table (E).Deleted
- loop
- E := Errors.Table (E).Next;
- end loop;
+ -- Only output the listing if Sfile is known, to avoid
+ -- crashing the compiler.
+
+ if Sfile /= No_Source_File then
+ for N in 1 .. Last_Source_Line (Sfile) loop
+ while E /= No_Error_Msg
+ and then Errors.Table (E).Deleted
+ loop
+ E := Errors.Table (E).Next;
+ end loop;
- Err_Flag :=
- E /= No_Error_Msg
- and then Errors.Table (E).Line = N
- and then Errors.Table (E).Sfile = Sfile;
+ Err_Flag :=
+ E /= No_Error_Msg
+ and then Errors.Table (E).Line = N
+ and then Errors.Table (E).Sfile = Sfile;
- Output_Source_Line (N, Sfile, Err_Flag);
+ Output_Source_Line (N, Sfile, Err_Flag);
- if Err_Flag then
- Output_Error_Msgs (E);
+ if Err_Flag then
+ Output_Error_Msgs (E);
- if not Debug_Flag_2 then
- Write_Eol;
+ if not Debug_Flag_2 then
+ Write_Eol;
+ end if;
end if;
- end if;
- end loop;
+ end loop;
+ end if;
end;
end if;
end loop;
@@ -1909,7 +1931,13 @@ package body Errout is
and then (not Full_List or else Full_List_File_Name /= null)
then
Write_Eol;
- Write_Header (Main_Source_File);
+
+ -- Output the header only when Main_Source_File is known
+
+ if Main_Source_File /= No_Source_File then
+ Write_Header (Main_Source_File);
+ end if;
+
E := First_Error_Msg;
-- Loop through error lines
@@ -2705,7 +2733,7 @@ package body Errout is
Warning_Msg_Char := ' ';
if P <= Text'Last and then Text (P) = '?' then
- if Warning_Doc_Switch and not OpenVMS_On_Target then
+ if Warning_Doc_Switch then
Warning_Msg_Char := '?';
end if;
@@ -2717,7 +2745,7 @@ package body Errout is
Text (P) in 'A' .. 'Z')
and then Text (P + 1) = '?'
then
- if Warning_Doc_Switch and not OpenVMS_On_Target then
+ if Warning_Doc_Switch then
Warning_Msg_Char := Text (P);
end if;
@@ -2805,7 +2833,6 @@ package body Errout is
if Error_Msg_Warn
and Warning_Doc_Switch
- and not OpenVMS_On_Target
then
Warning_Msg_Char := '?';
end if;
diff --git a/gcc/ada/errout.ads b/gcc/ada/errout.ads
index 0c363222c37..e268d1f58d7 100644
--- a/gcc/ada/errout.ads
+++ b/gcc/ada/errout.ads
@@ -313,6 +313,8 @@ package Errout is
-- taken as an Ada reserved word, and are converted to the default
-- case for reserved words (see Scans package spec). Surrounding
-- quotes are added unless manual quotation mode is currently set.
+ -- RM and SPARK are special exceptions, they are never treated as
+ -- keywords, and just appear verbatim, with no surrounding quotes.
-- Insertion character ` (Backquote: set manual quotation mode)
-- The backquote character always appears in pairs. Each backquote of
@@ -813,9 +815,11 @@ package Errout is
-- matching Warnings Off pragma preceding this one.
function Compilation_Errors return Boolean;
- -- Returns true if errors have been detected, or warnings in -gnatwe
- -- (treat warnings as errors) mode. Note that it is mandatory to call
- -- Finalize before calling this routine.
+ -- Returns True if errors have been detected, or warnings in -gnatwe (treat
+ -- warnings as errors) mode. Note that it is mandatory to call Finalize
+ -- before calling this routine. Always returns False in formal verification
+ -- mode, because errors issued when generating Why code are not compilation
+ -- errors, and should not result in exiting with an error status.
procedure Error_Msg_CRT (Feature : String; N : Node_Id);
-- Posts a non-fatal message on node N saying that the feature identified
diff --git a/gcc/ada/erroutc.adb b/gcc/ada/erroutc.adb
index 97ce9d77891..e2631f84e7f 100644
--- a/gcc/ada/erroutc.adb
+++ b/gcc/ada/erroutc.adb
@@ -31,6 +31,7 @@
with Atree; use Atree;
with Casing; use Casing;
+with Csets; use Csets;
with Debug; use Debug;
with Err_Vars; use Err_Vars;
with Namet; use Namet;
@@ -461,10 +462,7 @@ package body Erroutc is
Warn_Tag := new String'(" [-gnatw" & Warn_Chr & ']');
else pragma Assert (Warn_Chr in 'A' .. 'Z');
- Warn_Tag :=
- new String'(" [-gnatw."
- & Character'Val (Character'Pos (Warn_Chr) + 32)
- & ']');
+ Warn_Tag := new String'(" [-gnatw." & Fold_Lower (Warn_Chr) & ']');
end if;
else
diff --git a/gcc/ada/erroutc.ads b/gcc/ada/erroutc.ads
index 02101852d44..647e58bafdd 100644
--- a/gcc/ada/erroutc.ads
+++ b/gcc/ada/erroutc.ads
@@ -427,7 +427,8 @@ package Erroutc is
-- Handle reserved word insertion (upper case letters). The Text argument
-- is the current error message input text, and J is an index which on
-- entry points to the first character of the reserved word, and on exit
- -- points past the last character of the reserved word.
+ -- points past the last character of the reserved word. Note that RM and
+ -- SPARK are treated specially and not considered to be keywords.
procedure Set_Msg_Insertion_Run_Time_Name;
-- If package System contains a definition for Run_Time_Name (see package
diff --git a/gcc/ada/exp_aggr.adb b/gcc/ada/exp_aggr.adb
index e0a91324a80..20a82b1d7f1 100644
--- a/gcc/ada/exp_aggr.adb
+++ b/gcc/ada/exp_aggr.adb
@@ -376,7 +376,7 @@ package body Exp_Aggr is
-- Start of processing for Aggr_Size_OK
begin
- -- The normal aggregate limit is 5000, but we increase this limit to
+ -- The normal aggregate limit is 50000, but we increase this limit to
-- 2**24 (about 16 million) if Restrictions (No_Elaboration_Code) or
-- Restrictions (No_Implicit_Loops) is specified, since in either case
-- we are at risk of declaring the program illegal because of this
@@ -389,10 +389,14 @@ package body Exp_Aggr is
-- efficient to construct a one-dimensional equivalent array with static
-- components.
+ -- Conversely, we decrease the maximum size if none of the above
+ -- requirements apply, and if the aggregate has a single component
+ -- association, which will be more efficient if implemented with a loop.
+
-- Finally, we use a small limit in CodePeer mode where we favor loops
-- instead of thousands of single assignments (from large aggregates).
- Max_Aggr_Size := 5000;
+ Max_Aggr_Size := 50000;
if CodePeer_Mode then
Max_Aggr_Size := 100;
@@ -404,6 +408,11 @@ package body Exp_Aggr is
and then Static_Elaboration_Desired (Current_Scope)))
then
Max_Aggr_Size := 2 ** 24;
+
+ elsif No (Expressions (N))
+ and then No (Next (First (Component_Associations (N))))
+ then
+ Max_Aggr_Size := 5000;
end if;
Siz := Component_Count (Component_Type (Typ));
@@ -619,7 +628,7 @@ package body Exp_Aggr is
-- If component is limited, aggregate must be expanded because each
-- component assignment must be built in place.
- if Is_Immutably_Limited_Type (Component_Type (Typ)) then
+ if Is_Limited_View (Component_Type (Typ)) then
return False;
end if;
@@ -3338,7 +3347,7 @@ package body Exp_Aggr is
-- in place within the caller's scope).
or else
- (Is_Immutably_Limited_Type (Typ)
+ (Is_Limited_View (Typ)
and then
(Nkind (Parent (Parent_Node)) = N_Extended_Return_Statement
or else Nkind (Parent_Node) = N_Simple_Return_Statement))
@@ -4878,6 +4887,43 @@ package body Exp_Aggr is
Check_Same_Aggr_Bounds (N, 1);
end if;
+ -- STEP 1d
+
+ -- If we have a default component value, or simple initialization is
+ -- required for the component type, then we replace <> in component
+ -- associations by the required default value.
+
+ declare
+ Default_Val : Node_Id;
+ Assoc : Node_Id;
+
+ begin
+ if (Present (Default_Aspect_Component_Value (Typ))
+ or else Needs_Simple_Initialization (Ctyp))
+ and then Present (Component_Associations (N))
+ then
+ Assoc := First (Component_Associations (N));
+ while Present (Assoc) loop
+ if Nkind (Assoc) = N_Component_Association
+ and then Box_Present (Assoc)
+ then
+ Set_Box_Present (Assoc, False);
+
+ if Present (Default_Aspect_Component_Value (Typ)) then
+ Default_Val := Default_Aspect_Component_Value (Typ);
+ else
+ Default_Val := Get_Simple_Init_Val (Ctyp, N);
+ end if;
+
+ Set_Expression (Assoc, New_Copy_Tree (Default_Val));
+ Analyze_And_Resolve (Expression (Assoc), Ctyp);
+ end if;
+
+ Next (Assoc);
+ end loop;
+ end if;
+ end;
+
-- STEP 2
-- Here we test for is packed array aggregate that we can handle at
@@ -5622,7 +5668,7 @@ package body Exp_Aggr is
-- Extension aggregates, aggregates in extended return statements, and
-- aggregates for C++ imported types must be expanded.
- if Ada_Version >= Ada_2005 and then Is_Immutably_Limited_Type (Typ) then
+ if Ada_Version >= Ada_2005 and then Is_Limited_View (Typ) then
if not Nkind_In (Parent (N), N_Object_Declaration,
N_Component_Association)
then
diff --git a/gcc/ada/exp_attr.adb b/gcc/ada/exp_attr.adb
index 00347672511..bd193598b0d 100644
--- a/gcc/ada/exp_attr.adb
+++ b/gcc/ada/exp_attr.adb
@@ -1296,14 +1296,14 @@ package body Exp_Attr is
-- Handle designated types that come from the limited view
if Ekind (Btyp_DDT) = E_Incomplete_Type
- and then From_With_Type (Btyp_DDT)
+ and then From_Limited_With (Btyp_DDT)
and then Present (Non_Limited_View (Btyp_DDT))
then
Btyp_DDT := Non_Limited_View (Btyp_DDT);
elsif Is_Class_Wide_Type (Btyp_DDT)
and then Ekind (Etype (Btyp_DDT)) = E_Incomplete_Type
- and then From_With_Type (Etype (Btyp_DDT))
+ and then From_Limited_With (Etype (Btyp_DDT))
and then Present (Non_Limited_View (Etype (Btyp_DDT)))
and then Present (Class_Wide_Type
(Non_Limited_View (Etype (Btyp_DDT))))
@@ -6485,6 +6485,7 @@ package body Exp_Attr is
Attribute_Has_Tagged_Values |
Attribute_Large |
Attribute_Last_Valid |
+ Attribute_Library_Level |
Attribute_Lock_Free |
Attribute_Machine_Emax |
Attribute_Machine_Emin |
@@ -6608,12 +6609,14 @@ package body Exp_Attr is
procedure Process_Range_Update
(Temp : Entity_Id;
Comp : Node_Id;
- Expr : Node_Id);
+ Expr : Node_Id;
+ Typ : Entity_Id);
-- Generate the statements necessary to update a slice of the prefix.
-- The code is inserted before the attribute N. Temp denotes the entity
-- of the anonymous object created to reflect the changes in values.
-- Comp is range of the slice to be updated. Expr is an expression
- -- yielding the new value of Comp.
+ -- yielding the new value of Comp. Typ is the type of the prefix of
+ -- attribute Update.
-----------------------------------------
-- Process_Component_Or_Element_Update --
@@ -6687,10 +6690,12 @@ package body Exp_Attr is
procedure Process_Range_Update
(Temp : Entity_Id;
Comp : Node_Id;
- Expr : Node_Id)
+ Expr : Node_Id;
+ Typ : Entity_Id)
is
- Loc : constant Source_Ptr := Sloc (Comp);
- Index : Entity_Id;
+ Index_Typ : constant Entity_Id := Etype (First_Index (Typ));
+ Loc : constant Source_Ptr := Sloc (Comp);
+ Index : Entity_Id;
begin
-- A range update appears as
@@ -6702,7 +6707,7 @@ package body Exp_Attr is
-- value of Expr:
-- for Index in Low .. High loop
- -- Temp (Index) := Expr;
+ -- Temp (<Index_Typ> (Index)) := Expr;
-- end loop;
Index := Make_Temporary (Loc, 'I');
@@ -6721,7 +6726,8 @@ package body Exp_Attr is
Name =>
Make_Indexed_Component (Loc,
Prefix => New_Reference_To (Temp, Loc),
- Expressions => New_List (New_Reference_To (Index, Loc))),
+ Expressions => New_List (
+ Convert_To (Index_Typ, New_Reference_To (Index, Loc)))),
Expression => Relocate_Node (Expr))),
End_Label => Empty));
@@ -6729,10 +6735,10 @@ package body Exp_Attr is
-- Local variables
- Aggr : constant Node_Id := First (Expressions (N));
+ Aggr : constant Node_Id := First (Expressions (N));
Loc : constant Source_Ptr := Sloc (N);
- Pref : constant Node_Id := Prefix (N);
- Typ : constant Entity_Id := Etype (Pref);
+ Pref : constant Node_Id := Prefix (N);
+ Typ : constant Entity_Id := Etype (Pref);
Assoc : Node_Id;
Comp : Node_Id;
Expr : Node_Id;
@@ -6762,7 +6768,7 @@ package body Exp_Attr is
Expr := Expression (Assoc);
while Present (Comp) loop
if Nkind (Comp) = N_Range then
- Process_Range_Update (Temp, Comp, Expr);
+ Process_Range_Update (Temp, Comp, Expr, Typ);
else
Process_Component_Or_Element_Update (Temp, Comp, Expr, Typ);
end if;
@@ -6879,7 +6885,7 @@ package body Exp_Attr is
-- Function to check whether the specified run-time call is available
-- in the run time used. In the case of a configurable run time, it
-- is normal that some subprograms are not there.
-
+ --
-- I don't understand this routine at all, why is this not just a
-- call to RTE_Available? And if for some reason we need a different
-- routine with different semantics, why is not in Rtsfind ???
@@ -6893,8 +6899,7 @@ package body Exp_Attr is
-- Assume that the unit will always be available when using a
-- "normal" (not configurable) run time.
- return not Configurable_Run_Time_Mode
- or else RTE_Available (Entity);
+ return not Configurable_Run_Time_Mode or else RTE_Available (Entity);
end Is_Available;
-- Start of processing for Find_Stream_Subprogram
@@ -6929,9 +6934,148 @@ package body Exp_Attr is
and then
not Is_Predefined_File_Name (Unit_File_Name (Current_Sem_Unit))
then
+ -- Storage_Array as defined in package System.Storage_Elements
+
+ if Is_RTE (Base_Typ, RE_Storage_Array) then
+
+ -- Case of No_Stream_Optimizations restriction active
+
+ if Restriction_Active (No_Stream_Optimizations) then
+ if Nam = TSS_Stream_Input
+ and then Is_Available (RE_Storage_Array_Input)
+ then
+ return RTE (RE_Storage_Array_Input);
+
+ elsif Nam = TSS_Stream_Output
+ and then Is_Available (RE_Storage_Array_Output)
+ then
+ return RTE (RE_Storage_Array_Output);
+
+ elsif Nam = TSS_Stream_Read
+ and then Is_Available (RE_Storage_Array_Read)
+ then
+ return RTE (RE_Storage_Array_Read);
+
+ elsif Nam = TSS_Stream_Write
+ and then Is_Available (RE_Storage_Array_Write)
+ then
+ return RTE (RE_Storage_Array_Write);
+
+ elsif Nam /= TSS_Stream_Input and then
+ Nam /= TSS_Stream_Output and then
+ Nam /= TSS_Stream_Read and then
+ Nam /= TSS_Stream_Write
+ then
+ raise Program_Error;
+ end if;
+
+ -- Restriction No_Stream_Optimizations is not set, so we can go
+ -- ahead and optimize using the block IO forms of the routines.
+
+ else
+ if Nam = TSS_Stream_Input
+ and then Is_Available (RE_Storage_Array_Input_Blk_IO)
+ then
+ return RTE (RE_Storage_Array_Input_Blk_IO);
+
+ elsif Nam = TSS_Stream_Output
+ and then Is_Available (RE_Storage_Array_Output_Blk_IO)
+ then
+ return RTE (RE_Storage_Array_Output_Blk_IO);
+
+ elsif Nam = TSS_Stream_Read
+ and then Is_Available (RE_Storage_Array_Read_Blk_IO)
+ then
+ return RTE (RE_Storage_Array_Read_Blk_IO);
+
+ elsif Nam = TSS_Stream_Write
+ and then Is_Available (RE_Storage_Array_Write_Blk_IO)
+ then
+ return RTE (RE_Storage_Array_Write_Blk_IO);
+
+ elsif Nam /= TSS_Stream_Input and then
+ Nam /= TSS_Stream_Output and then
+ Nam /= TSS_Stream_Read and then
+ Nam /= TSS_Stream_Write
+ then
+ raise Program_Error;
+ end if;
+ end if;
+
+ -- Stream_Element_Array as defined in package Ada.Streams
+
+ elsif Is_RTE (Base_Typ, RE_Stream_Element_Array) then
+
+ -- Case of No_Stream_Optimizations restriction active
+
+ if Restriction_Active (No_Stream_Optimizations) then
+ if Nam = TSS_Stream_Input
+ and then Is_Available (RE_Stream_Element_Array_Input)
+ then
+ return RTE (RE_Stream_Element_Array_Input);
+
+ elsif Nam = TSS_Stream_Output
+ and then Is_Available (RE_Stream_Element_Array_Output)
+ then
+ return RTE (RE_Stream_Element_Array_Output);
+
+ elsif Nam = TSS_Stream_Read
+ and then Is_Available (RE_Stream_Element_Array_Read)
+ then
+ return RTE (RE_Stream_Element_Array_Read);
+
+ elsif Nam = TSS_Stream_Write
+ and then Is_Available (RE_Stream_Element_Array_Write)
+ then
+ return RTE (RE_Stream_Element_Array_Write);
+
+ elsif Nam /= TSS_Stream_Input and then
+ Nam /= TSS_Stream_Output and then
+ Nam /= TSS_Stream_Read and then
+ Nam /= TSS_Stream_Write
+ then
+ raise Program_Error;
+ end if;
+
+ -- Restriction No_Stream_Optimizations is not set, so we can go
+ -- ahead and optimize using the block IO forms of the routines.
+
+ else
+ if Nam = TSS_Stream_Input
+ and then Is_Available (RE_Stream_Element_Array_Input_Blk_IO)
+ then
+ return RTE (RE_Stream_Element_Array_Input_Blk_IO);
+
+ elsif Nam = TSS_Stream_Output
+ and then Is_Available (RE_Stream_Element_Array_Output_Blk_IO)
+ then
+ return RTE (RE_Stream_Element_Array_Output_Blk_IO);
+
+ elsif Nam = TSS_Stream_Read
+ and then Is_Available (RE_Stream_Element_Array_Read_Blk_IO)
+ then
+ return RTE (RE_Stream_Element_Array_Read_Blk_IO);
+
+ elsif Nam = TSS_Stream_Write
+ and then Is_Available (RE_Stream_Element_Array_Write_Blk_IO)
+ then
+ return RTE (RE_Stream_Element_Array_Write_Blk_IO);
+
+ elsif Nam /= TSS_Stream_Input and then
+ Nam /= TSS_Stream_Output and then
+ Nam /= TSS_Stream_Read and then
+ Nam /= TSS_Stream_Write
+ then
+ raise Program_Error;
+ end if;
+ end if;
+
-- String as defined in package Ada
- if Base_Typ = Standard_String then
+ elsif Base_Typ = Standard_String then
+
+ -- Case of No_Stream_Optimizations restriction active
+
if Restriction_Active (No_Stream_Optimizations) then
if Nam = TSS_Stream_Input
and then Is_Available (RE_String_Input)
@@ -6961,6 +7105,9 @@ package body Exp_Attr is
raise Program_Error;
end if;
+ -- Restriction No_Stream_Optimizations is not set, so we can go
+ -- ahead and optimize using the block IO forms of the routines.
+
else
if Nam = TSS_Stream_Input
and then Is_Available (RE_String_Input_Blk_IO)
@@ -6982,9 +7129,9 @@ package body Exp_Attr is
then
return RTE (RE_String_Write_Blk_IO);
- elsif Nam /= TSS_Stream_Input and then
+ elsif Nam /= TSS_Stream_Input and then
Nam /= TSS_Stream_Output and then
- Nam /= TSS_Stream_Read and then
+ Nam /= TSS_Stream_Read and then
Nam /= TSS_Stream_Write
then
raise Program_Error;
@@ -6994,6 +7141,9 @@ package body Exp_Attr is
-- Wide_String as defined in package Ada
elsif Base_Typ = Standard_Wide_String then
+
+ -- Case of No_Stream_Optimizations restriction active
+
if Restriction_Active (No_Stream_Optimizations) then
if Nam = TSS_Stream_Input
and then Is_Available (RE_Wide_String_Input)
@@ -7015,14 +7165,17 @@ package body Exp_Attr is
then
return RTE (RE_Wide_String_Write);
- elsif Nam /= TSS_Stream_Input and then
+ elsif Nam /= TSS_Stream_Input and then
Nam /= TSS_Stream_Output and then
- Nam /= TSS_Stream_Read and then
+ Nam /= TSS_Stream_Read and then
Nam /= TSS_Stream_Write
then
raise Program_Error;
end if;
+ -- Restriction No_Stream_Optimizations is not set, so we can go
+ -- ahead and optimize using the block IO forms of the routines.
+
else
if Nam = TSS_Stream_Input
and then Is_Available (RE_Wide_String_Input_Blk_IO)
@@ -7044,9 +7197,9 @@ package body Exp_Attr is
then
return RTE (RE_Wide_String_Write_Blk_IO);
- elsif Nam /= TSS_Stream_Input and then
+ elsif Nam /= TSS_Stream_Input and then
Nam /= TSS_Stream_Output and then
- Nam /= TSS_Stream_Read and then
+ Nam /= TSS_Stream_Read and then
Nam /= TSS_Stream_Write
then
raise Program_Error;
@@ -7056,6 +7209,9 @@ package body Exp_Attr is
-- Wide_Wide_String as defined in package Ada
elsif Base_Typ = Standard_Wide_Wide_String then
+
+ -- Case of No_Stream_Optimizations restriction active
+
if Restriction_Active (No_Stream_Optimizations) then
if Nam = TSS_Stream_Input
and then Is_Available (RE_Wide_Wide_String_Input)
@@ -7077,14 +7233,17 @@ package body Exp_Attr is
then
return RTE (RE_Wide_Wide_String_Write);
- elsif Nam /= TSS_Stream_Input and then
+ elsif Nam /= TSS_Stream_Input and then
Nam /= TSS_Stream_Output and then
- Nam /= TSS_Stream_Read and then
+ Nam /= TSS_Stream_Read and then
Nam /= TSS_Stream_Write
then
raise Program_Error;
end if;
+ -- Restriction No_Stream_Optimizations is not set, so we can go
+ -- ahead and optimize using the block IO forms of the routines.
+
else
if Nam = TSS_Stream_Input
and then Is_Available (RE_Wide_Wide_String_Input_Blk_IO)
@@ -7106,9 +7265,9 @@ package body Exp_Attr is
then
return RTE (RE_Wide_Wide_String_Write_Blk_IO);
- elsif Nam /= TSS_Stream_Input and then
+ elsif Nam /= TSS_Stream_Input and then
Nam /= TSS_Stream_Output and then
- Nam /= TSS_Stream_Read and then
+ Nam /= TSS_Stream_Read and then
Nam /= TSS_Stream_Write
then
raise Program_Error;
@@ -7117,9 +7276,7 @@ package body Exp_Attr is
end if;
end if;
- if Is_Tagged_Type (Typ)
- and then Is_Derived_Type (Typ)
- then
+ if Is_Tagged_Type (Typ) and then Is_Derived_Type (Typ) then
return Find_Prim_Op (Typ, Nam);
else
return Find_Inherited_TSS (Typ, Nam);
diff --git a/gcc/ada/exp_ch11.adb b/gcc/ada/exp_ch11.adb
index 90ca6dae79b..8be585c7725 100644
--- a/gcc/ada/exp_ch11.adb
+++ b/gcc/ada/exp_ch11.adb
@@ -1025,7 +1025,13 @@ package body Exp_Ch11 is
-- ...
-- end;
- if Present (Choice_Parameter (Handler)) then
+ -- This expansion is not performed when using GCC ZCX. Gigi
+ -- will insert a call to initialize the choice parameter.
+
+ if Present (Choice_Parameter (Handler))
+ and then (Exception_Mechanism /= Back_End_Exceptions
+ or else CodePeer_Mode)
+ then
declare
Cparm : constant Entity_Id := Choice_Parameter (Handler);
Cloc : constant Source_Ptr := Sloc (Cparm);
@@ -1033,43 +1039,42 @@ package body Exp_Ch11 is
Save : Node_Id;
begin
- -- Note use of No_Location to hide this code from the
- -- debugger, so single stepping doesn't jump back and
- -- forth.
+ -- Note: No_Location used to hide code from the debugger,
+ -- so single stepping doesn't jump back and forth.
Save :=
Make_Procedure_Call_Statement (No_Location,
- Name =>
+ Name =>
New_Occurrence_Of
(RTE (RE_Save_Occurrence), No_Location),
Parameter_Associations => New_List (
New_Occurrence_Of (Cparm, No_Location),
Make_Explicit_Dereference (No_Location,
- Make_Function_Call (No_Location,
- Name =>
- Make_Explicit_Dereference (No_Location,
- New_Occurrence_Of
- (RTE (RE_Get_Current_Excep),
- No_Location))))));
+ Prefix =>
+ Make_Function_Call (No_Location,
+ Name =>
+ Make_Explicit_Dereference (No_Location,
+ Prefix =>
+ New_Occurrence_Of
+ (RTE (RE_Get_Current_Excep),
+ No_Location))))));
Mark_Rewrite_Insertion (Save);
Prepend (Save, Statements (Handler));
Obj_Decl :=
- Make_Object_Declaration
- (Cloc,
- Defining_Identifier => Cparm,
- Object_Definition =>
- New_Occurrence_Of
- (RTE (RE_Exception_Occurrence), Cloc));
+ Make_Object_Declaration (Cloc,
+ Defining_Identifier => Cparm,
+ Object_Definition =>
+ New_Occurrence_Of
+ (RTE (RE_Exception_Occurrence), Cloc));
Set_No_Initialization (Obj_Decl, True);
Rewrite (Handler,
Make_Exception_Handler (Hloc,
Choice_Parameter => Empty,
Exception_Choices => Exception_Choices (Handler),
-
- Statements => New_List (
+ Statements => New_List (
Make_Block_Statement (Hloc,
Declarations => New_List (Obj_Decl),
Handled_Statement_Sequence =>
@@ -1166,18 +1171,17 @@ package body Exp_Ch11 is
-- Generates:
-- exceptE : constant String := "A.B.EXCEP"; -- static data
- -- except : exception_data := (
- -- Handled_By_Other => False,
- -- Lang => 'A',
- -- Name_Length => exceptE'Length,
- -- Full_Name => exceptE'Address,
- -- HTable_Ptr => null,
- -- Import_Code => 0,
- -- Raise_Hook => null,
- -- );
+ -- except : exception_data :=
+ -- (Handled_By_Other => False,
+ -- Lang => 'A',
+ -- Name_Length => exceptE'Length,
+ -- Full_Name => exceptE'Address,
+ -- HTable_Ptr => null,
+ -- Foreign_Data => null,
+ -- Raise_Hook => null);
-- (protecting test only needed if not at library level)
- --
+
-- exceptF : Boolean := True -- static data
-- if exceptF then
-- exceptF := False;
@@ -1319,9 +1323,9 @@ package body Exp_Ch11 is
Append_To (L, Make_Null (Loc));
- -- Import_Code component: 0
+ -- Foreign_Data component: null
- Append_To (L, Make_Integer_Literal (Loc, 0));
+ Append_To (L, Make_Null (Loc));
-- Raise_Hook component: null
@@ -1446,7 +1450,7 @@ package body Exp_Ch11 is
RCE : Node_Id;
begin
- Possible_Local_Raise (N, Name (N));
+ Possible_Local_Raise (N, Entity (Name (N)));
-- Later we must teach the back end/gigi how to deal with this, but
-- for now we will assume the type is Standard_Boolean and transform
diff --git a/gcc/ada/exp_ch3.adb b/gcc/ada/exp_ch3.adb
index a21de7edb16..f1ab0c5e765 100644
--- a/gcc/ada/exp_ch3.adb
+++ b/gcc/ada/exp_ch3.adb
@@ -1893,7 +1893,7 @@ package body Exp_Ch3 is
if Needs_Finalization (Typ)
and then not (Nkind_In (Kind, N_Aggregate, N_Extension_Aggregate))
- and then not Is_Immutably_Limited_Type (Typ)
+ and then not Is_Limited_View (Typ)
then
Append_To (Res,
Make_Adjust_Call
@@ -4940,7 +4940,7 @@ package body Exp_Ch3 is
Next_Elmt (Discr);
end loop;
- -- Now collect values of initialized components.
+ -- Now collect values of initialized components
Comp := First_Component (Full_Type);
while Present (Comp) loop
@@ -4957,11 +4957,11 @@ package body Exp_Ch3 is
Next_Component (Comp);
end loop;
- -- Finally, box-initialize remaining components.
+ -- Finally, box-initialize remaining components
Append_To (Component_Associations (Aggr),
Make_Component_Association (Loc,
- Choices => New_List (Make_Others_Choice (Loc)),
+ Choices => New_List (Make_Others_Choice (Loc)),
Expression => Empty));
Set_Box_Present (Last (Component_Associations (Aggr)));
Set_Expression (N, Aggr);
@@ -5310,7 +5310,7 @@ package body Exp_Ch3 is
-- creating the object (via allocator) and initializing it.
if Is_Return_Object (Def_Id)
- and then Is_Immutably_Limited_Type (Typ)
+ and then Is_Limited_View (Typ)
then
null;
@@ -5578,7 +5578,7 @@ package body Exp_Ch3 is
-- renaming declaration.
if Needs_Finalization (Typ)
- and then not Is_Immutably_Limited_Type (Typ)
+ and then not Is_Limited_View (Typ)
and then not Rewrite_As_Renaming
then
Insert_Action_After (Init_After,
@@ -5846,23 +5846,18 @@ package body Exp_Ch3 is
-- Expand_N_Variant_Part --
---------------------------
- -- If the last variant does not contain the Others choice, replace it with
- -- an N_Others_Choice node since Gigi always wants an Others. Note that we
- -- do not bother to call Analyze on the modified variant part, since its
- -- only effect would be to compute the Others_Discrete_Choices node
- -- laboriously, and of course we already know the list of choices that
- -- corresponds to the others choice (it's the list we are replacing!)
+ -- Note: this procedure no longer has any effect. It used to be that we
+ -- would replace the choices in the last variant by a when others, and
+ -- also expanded static predicates in variant choices here, but both of
+ -- those activities were being done too early, since we can't check the
+ -- choices until the statically predicated subtypes are frozen, which can
+ -- happen as late as the free point of the record, and we can't change the
+ -- last choice to an others before checking the choices, which is now done
+ -- at the freeze point of the record.
procedure Expand_N_Variant_Part (N : Node_Id) is
- Last_Var : constant Node_Id := Last_Non_Pragma (Variants (N));
- Others_Node : Node_Id;
begin
- if Nkind (First (Discrete_Choices (Last_Var))) /= N_Others_Choice then
- Others_Node := Make_Others_Choice (Sloc (Last_Var));
- Set_Others_Discrete_Choices
- (Others_Node, Discrete_Choices (Last_Var));
- Set_Discrete_Choices (Last_Var, New_List (Others_Node));
- end if;
+ null;
end Expand_N_Variant_Part;
---------------------------------
@@ -6156,12 +6151,6 @@ package body Exp_Ch3 is
elsif CodePeer_Mode then
return;
-
- -- Do not create TSS routine Finalize_Address when compiling in SPARK
- -- mode because it is not necessary and results in useless expansion.
-
- elsif SPARK_Mode then
- return;
end if;
-- Create the body of TSS primitive Finalize_Address. This automatically
@@ -6908,13 +6897,9 @@ package body Exp_Ch3 is
-- be done before the bodies of all predefined primitives are
-- created. If Def_Id is limited, Stream_Input and Stream_Read
-- may produce build-in-place allocations and for those the
- -- expander needs Finalize_Address. Do not create the body of
- -- Finalize_Address in SPARK mode since it is not needed.
-
- if not SPARK_Mode then
- Make_Finalize_Address_Body (Def_Id);
- end if;
+ -- expander needs Finalize_Address.
+ Make_Finalize_Address_Body (Def_Id);
Predef_List := Predefined_Primitive_Bodies (Def_Id, Renamed_Eq);
Append_Freeze_Actions (Def_Id, Predef_List);
end if;
diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb
index 0802f2dfa51..ad65378cffb 100644
--- a/gcc/ada/exp_ch4.adb
+++ b/gcc/ada/exp_ch4.adb
@@ -1244,7 +1244,7 @@ package body Exp_Ch4 is
-- want to Adjust.
if not Aggr_In_Place
- and then not Is_Immutably_Limited_Type (T)
+ and then not Is_Limited_View (T)
then
Insert_Action (N,
@@ -1268,14 +1268,10 @@ package body Exp_Ch4 is
-- * .NET/JVM - these targets do not support address arithmetic
-- and unchecked conversion, key elements of Finalize_Address.
- -- * SPARK mode - the call is useless and results in unwanted
- -- expansion.
-
-- * CodePeer mode - TSS primitive Finalize_Address is not
-- created in this mode.
if VM_Target = No_VM
- and then not SPARK_Mode
and then not CodePeer_Mode
and then Present (Finalization_Master (PtrT))
and then Present (Temp_Decl)
@@ -4295,16 +4291,13 @@ package body Exp_Ch4 is
end if;
-- The finalization master must be inserted and analyzed as part of
- -- the current semantic unit. This form of expansion is not carried
- -- out in SPARK mode because it is useless. Note that the master is
- -- updated when analysis changes current units.
+ -- the current semantic unit. Note that the master is updated when
+ -- analysis changes current units.
- if not SPARK_Mode then
- if Present (Rel_Typ) then
- Set_Finalization_Master (PtrT, Finalization_Master (Rel_Typ));
- else
- Set_Finalization_Master (PtrT, Current_Anonymous_Master);
- end if;
+ if Present (Rel_Typ) then
+ Set_Finalization_Master (PtrT, Finalization_Master (Rel_Typ));
+ else
+ Set_Finalization_Master (PtrT, Current_Anonymous_Master);
end if;
end if;
@@ -4839,15 +4832,11 @@ package body Exp_Ch4 is
-- Set_Finalize_Address
-- (<PtrT>FM, <T>FD'Unrestricted_Access);
- -- Do not generate this call in the following cases:
- --
- -- * SPARK mode - the call is useless and results in
- -- unwanted expansion.
- --
- -- * CodePeer mode - TSS primitive Finalize_Address is
- -- not created in this mode.
+ -- Do not generate this call in CodePeer mode, as TSS
+ -- primitive Finalize_Address is not created in this
+ -- mode.
- elsif not (SPARK_Mode or CodePeer_Mode) then
+ elsif not CodePeer_Mode then
Insert_Action (N,
Make_Set_Finalize_Address_Call
(Loc => Loc,
@@ -4891,6 +4880,7 @@ package body Exp_Ch4 is
Loc : constant Source_Ptr := Sloc (N);
Typ : constant Entity_Id := Etype (N);
Cstmt : Node_Id;
+ Decl : Node_Id;
Tnn : Entity_Id;
Pnn : Entity_Id;
Actions : List_Id;
@@ -4958,19 +4948,24 @@ package body Exp_Ch4 is
Append_To (Actions,
Make_Full_Type_Declaration (Loc,
Defining_Identifier => Pnn,
- Type_Definition =>
+ Type_Definition =>
Make_Access_To_Object_Definition (Loc,
- All_Present => True,
- Subtype_Indication =>
- New_Reference_To (Typ, Loc))));
+ All_Present => True,
+ Subtype_Indication => New_Reference_To (Typ, Loc))));
Ttyp := Pnn;
end if;
Tnn := Make_Temporary (Loc, 'T');
- Append_To (Actions,
+
+ -- Create declaration for target of expression, and indicate that it
+ -- does not require initialization.
+
+ Decl :=
Make_Object_Declaration (Loc,
Defining_Identifier => Tnn,
- Object_Definition => New_Occurrence_Of (Ttyp, Loc)));
+ Object_Definition => New_Occurrence_Of (Ttyp, Loc));
+ Set_No_Initialization (Decl);
+ Append_To (Actions, Decl);
-- Now process the alternatives
@@ -7315,9 +7310,9 @@ package body Exp_Ch4 is
begin
Binary_Op_Validity_Checks (N);
- -- CodePeer and GNATprove want to see the unexpanded N_Op_Expon node
+ -- CodePeer wants to see the unexpanded N_Op_Expon node
- if CodePeer_Mode or SPARK_Mode then
+ if CodePeer_Mode then
return;
end if;
@@ -12140,24 +12135,44 @@ package body Exp_Ch4 is
(Decl : Node_Id;
Rel_Node : Node_Id)
is
- function Find_Enclosing_Context (N : Node_Id) return Node_Id;
- -- Find the logical context where N appears. The context is chosen such
- -- that it is possible to insert before and after it.
+ Hook_Context : Node_Id;
+ -- Node on which to insert the hook pointer (as an action)
- ----------------------------
- -- Find_Enclosing_Context --
- ----------------------------
+ Finalization_Context : Node_Id;
+ -- Node after which to insert finalization actions
+
+ Finalize_Always : Boolean;
+ -- If False, call to finalizer includes a test of whether the
+ -- hook pointer is null.
- function Find_Enclosing_Context (N : Node_Id) return Node_Id is
+ procedure Find_Enclosing_Contexts (N : Node_Id);
+ -- Find the logical context where N appears, and initializae
+ -- Hook_Context and Finalization_Context accordingly. Also
+ -- sets Finalize_Always.
+
+ -----------------------------
+ -- Find_Enclosing_Contexts --
+ -----------------------------
+
+ procedure Find_Enclosing_Contexts (N : Node_Id) is
Par : Node_Id;
Top : Node_Id;
+ Wrapped_Node : Node_Id;
+ -- Note: if we are in a transient scope, we want to reuse it as
+ -- the context for actions insertion, if possible. But if N is itself
+ -- part of the stored actions for the current transient scope,
+ -- then we need to insert at the appropriate (inner) location in
+ -- the not as an action on Node_To_Be_Wrapped.
+
+ In_Cond_Expr : constant Boolean := Within_Case_Or_If_Expression (N);
+
begin
-- When the node is inside a case/if expression, the lifetime of any
-- temporary controlled object is extended. Find a suitable insertion
-- node by locating the topmost case or if expressions.
- if Within_Case_Or_If_Expression (N) then
+ if In_Cond_Expr then
Par := N;
Top := N;
while Present (Par) loop
@@ -12187,7 +12202,8 @@ package body Exp_Ch4 is
N_Parameter_Association,
N_Pragma_Argument_Association)
then
- return Par;
+ Hook_Context := Par;
+ goto Hook_Context_Found;
-- Prevent the search from going too far
@@ -12198,26 +12214,10 @@ package body Exp_Ch4 is
Par := Parent (Par);
end loop;
- return Par;
-
- -- Short circuit operators in complex expressions are converted into
- -- expression_with_actions.
+ Hook_Context := Par;
+ goto Hook_Context_Found;
else
- -- Handle the case where the node is buried deep inside an if
- -- statement. The temporary controlled object must be finalized
- -- before the then, elsif or else statements are evaluated.
-
- -- if Something
- -- and then Ctrl_Func_Call
- -- then
- -- <result must be finalized at this point>
- -- <statements>
- -- end if;
-
- -- To achieve this, find the topmost logical operator. Generated
- -- actions are then inserted before/after it.
-
Par := N;
while Present (Par) loop
@@ -12254,14 +12254,23 @@ package body Exp_Ch4 is
-- Proc (... and then Ctrl_Func_Call ...);
+ if Scope_Is_Transient then
+ Wrapped_Node := Node_To_Be_Wrapped;
+ else
+ Wrapped_Node := Empty;
+ end if;
+
while Present (Par) loop
- if Nkind_In (Par, N_Assignment_Statement,
+ if Par = Wrapped_Node
+ or else
+ Nkind_In (Par, N_Assignment_Statement,
N_Object_Declaration,
N_Pragma,
N_Procedure_Call_Statement,
N_Simple_Return_Statement)
then
- return Par;
+ Hook_Context := Par;
+ goto Hook_Context_Found;
-- Prevent the search from going too far
@@ -12274,25 +12283,71 @@ package body Exp_Ch4 is
-- Return the topmost short circuit operator
- return Top;
+ Hook_Context := Top;
end if;
- end Find_Enclosing_Context;
+
+ <<Hook_Context_Found>>
+
+ -- Special case for Boolean EWAs: capture expression in a temporary,
+ -- whose declaration will serve as the context around which to insert
+ -- finalization code. The finalization thus remains local to the
+ -- specific condition being evaluated.
+
+ if Is_Boolean_Type (Etype (N)) then
+
+ -- In this case, the finalization context is chosen so that
+ -- we know at finalization point that the hook pointer is
+ -- never null, so no need for a test, we can call the finalizer
+ -- unconditionally, except in the case where the object is
+ -- created in a specific branch of a conditional expression.
+
+ Finalize_Always :=
+ not (In_Cond_Expr
+ or else
+ Nkind_In (Original_Node (N), N_Case_Expression,
+ N_If_Expression));
+
+ declare
+ Loc : constant Source_Ptr := Sloc (N);
+ Temp : constant Entity_Id := Make_Temporary (Loc, 'E', N);
+ begin
+ Append_To (Actions (N),
+ Make_Object_Declaration (Loc,
+ Defining_Identifier => Temp,
+ Constant_Present => True,
+ Object_Definition =>
+ New_Occurrence_Of (Etype (N), Loc),
+ Expression => Expression (N)));
+ Finalization_Context := Last (Actions (N));
+
+ Analyze (Last (Actions (N)));
+
+ Set_Expression (N, New_Occurrence_Of (Temp, Loc));
+ Analyze (Expression (N));
+ end;
+
+ else
+ Finalize_Always := False;
+ Finalization_Context := Hook_Context;
+ end if;
+ end Find_Enclosing_Contexts;
-- Local variables
- Context : constant Node_Id := Find_Enclosing_Context (Rel_Node);
Loc : constant Source_Ptr := Sloc (Decl);
Obj_Id : constant Entity_Id := Defining_Identifier (Decl);
Obj_Typ : constant Node_Id := Etype (Obj_Id);
Desig_Typ : Entity_Id;
Expr : Node_Id;
- Fin_Call : Node_Id;
+ Fin_Stmts : List_Id;
Ptr_Id : Entity_Id;
Temp_Id : Entity_Id;
-- Start of processing for Process_Transient_Object
begin
+ Find_Enclosing_Contexts (Rel_Node);
+
-- Step 1: Create the access type which provides a reference to the
-- transient controlled object.
@@ -12309,7 +12364,7 @@ package body Exp_Ch4 is
Ptr_Id := Make_Temporary (Loc, 'A');
- Insert_Action (Context,
+ Insert_Action (Hook_Context,
Make_Full_Type_Declaration (Loc,
Defining_Identifier => Ptr_Id,
Type_Definition =>
@@ -12324,7 +12379,7 @@ package body Exp_Ch4 is
Temp_Id := Make_Temporary (Loc, 'T');
- Insert_Action (Context,
+ Insert_Action (Hook_Context,
Make_Object_Declaration (Loc,
Defining_Identifier => Temp_Id,
Object_Definition => New_Reference_To (Ptr_Id, Loc)));
@@ -12338,6 +12393,13 @@ package body Exp_Ch4 is
-- Step 3: Hook the transient object to the temporary
+ -- This must be inserted right after the object declaration, so that
+ -- the assignment is executed if, and only if, the object is actually
+ -- created (whereas the declaration of the hook pointer, and the
+ -- finalization call, may be inserted at an outer level, and may
+ -- remain unused for some executions, if the actual creation of
+ -- the object is conditional).
+
-- The use of unchecked conversion / unrestricted access is needed to
-- avoid an accessibility violation. Note that the finalization code is
-- structured in such a way that the "hook" is processed only when it
@@ -12377,34 +12439,29 @@ package body Exp_Ch4 is
-- insert the finalization code after the return statement as this will
-- render it unreachable.
- if Nkind (Context) /= N_Simple_Return_Statement then
- Fin_Call :=
- Make_Implicit_If_Statement (Decl,
- Condition =>
- Make_Op_Ne (Loc,
- Left_Opnd => New_Reference_To (Temp_Id, Loc),
- Right_Opnd => Make_Null (Loc)),
-
- Then_Statements => New_List (
- Make_Final_Call
- (Obj_Ref =>
- Make_Explicit_Dereference (Loc,
- Prefix => New_Reference_To (Temp_Id, Loc)),
- Typ => Desig_Typ),
-
- Make_Assignment_Statement (Loc,
- Name => New_Reference_To (Temp_Id, Loc),
- Expression => Make_Null (Loc))));
+ if Nkind (Finalization_Context) /= N_Simple_Return_Statement then
+ Fin_Stmts := New_List (
+ Make_Final_Call
+ (Obj_Ref =>
+ Make_Explicit_Dereference (Loc,
+ Prefix => New_Reference_To (Temp_Id, Loc)),
+ Typ => Desig_Typ),
- -- Use the Actions list of logical operators when inserting the
- -- finalization call. This ensures that all transient controlled
- -- objects are finalized after the operators are evaluated.
+ Make_Assignment_Statement (Loc,
+ Name => New_Reference_To (Temp_Id, Loc),
+ Expression => Make_Null (Loc)));
- if Nkind_In (Context, N_And_Then, N_Or_Else) then
- Insert_Action (Context, Fin_Call);
- else
- Insert_Action_After (Context, Fin_Call);
+ if not Finalize_Always then
+ Fin_Stmts := New_List (
+ Make_Implicit_If_Statement (Decl,
+ Condition =>
+ Make_Op_Ne (Loc,
+ Left_Opnd => New_Reference_To (Temp_Id, Loc),
+ Right_Opnd => Make_Null (Loc)),
+ Then_Statements => Fin_Stmts));
end if;
+
+ Insert_Actions_After (Finalization_Context, Fin_Stmts);
end if;
end Process_Transient_Object;
diff --git a/gcc/ada/exp_ch5.adb b/gcc/ada/exp_ch5.adb
index 95e649a13e9..f166ff464ae 100644
--- a/gcc/ada/exp_ch5.adb
+++ b/gcc/ada/exp_ch5.adb
@@ -2537,7 +2537,11 @@ package body Exp_Ch5 is
-- if statement, since this can result in subsequent optimizations.
-- This helps not only with case statements in the source of a
-- simple form, but also with generated code (discriminant check
- -- functions in particular)
+ -- functions in particular).
+
+ -- Note: it is OK to do this before expanding out choices for any
+ -- static predicates, since the if statement processing will handle
+ -- the static predicate case fine.
elsif Len = 2 then
Chlist := Discrete_Choices (First (Alternatives (N)));
@@ -2617,12 +2621,18 @@ package body Exp_Ch5 is
Set_Discrete_Choices (Last_Alt, New_List (Others_Node));
end if;
- Alt := First (Alternatives (N));
- while Present (Alt)
- and then Nkind (Alt) = N_Case_Statement_Alternative
- loop
+ -- Deal with possible declarations of controlled objects, and also
+ -- with rewriting choice sequences for static predicate references.
+
+ Alt := First_Non_Pragma (Alternatives (N));
+ while Present (Alt) loop
Process_Statements_For_Controlled_Objects (Alt);
- Next (Alt);
+
+ if Has_SP_Choice (Alt) then
+ Expand_Static_Predicates_In_Choices (Alt);
+ end if;
+
+ Next_Non_Pragma (Alt);
end loop;
end;
end Expand_N_Case_Statement;
diff --git a/gcc/ada/exp_ch6.adb b/gcc/ada/exp_ch6.adb
index d48544fdada..adc0987fc44 100644
--- a/gcc/ada/exp_ch6.adb
+++ b/gcc/ada/exp_ch6.adb
@@ -3947,7 +3947,7 @@ package body Exp_Ch6 is
-- result from the secondary stack.
if Needs_Finalization (Etype (Subp)) then
- if not Is_Immutably_Limited_Type (Etype (Subp))
+ if not Is_Limited_View (Etype (Subp))
and then
(No (First_Formal (Subp))
or else
@@ -4311,7 +4311,7 @@ package body Exp_Ch6 is
if No (Checks) then
Checks :=
- Make_If_Statement (Loc,
+ Make_Implicit_If_Statement (CCs,
Condition => Cond,
Then_Statements => New_List (Error));
@@ -4481,7 +4481,7 @@ package body Exp_Ch6 is
-- end if;
Append_To (Decls,
- Make_If_Statement (Loc,
+ Make_Implicit_If_Statement (CCs,
Condition => Relocate_Node (Case_Guard),
Then_Statements => New_List (
Set (Flag),
@@ -4536,7 +4536,7 @@ package body Exp_Ch6 is
end if;
CG_Checks :=
- Make_If_Statement (Loc,
+ Make_Implicit_If_Statement (CCs,
Condition =>
Make_Op_Eq (Loc,
Left_Opnd => New_Reference_To (Count, Loc),
@@ -7100,7 +7100,7 @@ package body Exp_Ch6 is
then
null;
- elsif Is_Immutably_Limited_Type (Typ) then
+ elsif Is_Limited_View (Typ) then
Set_Returns_By_Ref (Spec_Id);
elsif Present (Utyp) and then CW_Or_Has_Controlled_Part (Utyp) then
@@ -7702,7 +7702,7 @@ package body Exp_Ch6 is
-- the type of the expression may be.
if not Comes_From_Extended_Return_Statement (N)
- and then Is_Immutably_Limited_Type (Etype (Expression (N)))
+ and then Is_Limited_View (Etype (Expression (N)))
and then Ada_Version >= Ada_2005
and then not Debug_Flag_Dot_L
@@ -7781,7 +7781,7 @@ package body Exp_Ch6 is
-- type that requires special processing (indicated by the fact that
-- it requires a cleanup scope for the secondary stack case).
- if Is_Immutably_Limited_Type (Exptyp)
+ if Is_Limited_View (Exptyp)
or else Is_Limited_Interface (Exptyp)
then
null;
@@ -8084,8 +8084,9 @@ package body Exp_Ch6 is
-- AI05-0073: If function has a controlling access result, check that
-- the tag of the return value, if it is not null, matches designated
-- type of return type.
- -- The return expression is referenced twice in the code below, so
- -- it must be made free of side effects. Given that different compilers
+
+ -- The return expression is referenced twice in the code below, so it
+ -- must be made free of side effects. Given that different compilers
-- may evaluate these parameters in different order, both occurrences
-- perform a copy.
@@ -8489,6 +8490,1050 @@ package body Exp_Ch6 is
end Expand_Simple_Function_Return;
--------------------------------
+ -- Expand_Subprogram_Contract --
+ --------------------------------
+
+ procedure Expand_Subprogram_Contract
+ (N : Node_Id;
+ Spec_Id : Entity_Id;
+ Body_Id : Entity_Id)
+ is
+ procedure Add_Invariant_And_Predicate_Checks
+ (Subp_Id : Entity_Id;
+ Stmts : in out List_Id;
+ Result : out Node_Id);
+ -- Process the result of function Subp_Id (if applicable) and all its
+ -- formals. Add invariant and predicate checks where applicable. The
+ -- routine appends all the checks to list Stmts. If Subp_Id denotes a
+ -- function, Result contains the entity of parameter _Result, to be
+ -- used in the creation of procedure _Postconditions.
+
+ procedure Append_Enabled_Item (Item : Node_Id; List : in out List_Id);
+ -- Append a node to a list. If there is no list, create a new one. When
+ -- the item denotes a pragma, it is added to the list only when it is
+ -- enabled.
+
+ procedure Build_Postconditions_Procedure
+ (Subp_Id : Entity_Id;
+ Stmts : List_Id;
+ Result : Entity_Id);
+ -- Create the body of procedure _Postconditions which handles various
+ -- assertion actions on exit from subprogram Subp_Id. Stmts is the list
+ -- of statements to be checked on exit. Parameter Result is the entity
+ -- of parameter _Result when Subp_Id denotes a function.
+
+ function Build_Pragma_Check_Equivalent
+ (Prag : Node_Id;
+ Subp_Id : Entity_Id := Empty;
+ Inher_Id : Entity_Id := Empty) return Node_Id;
+ -- Transform a [refined] pre- or postcondition denoted by Prag into an
+ -- equivalent pragma Check. When the pre- or postcondition is inherited,
+ -- the routine corrects the references of all formals of Inher_Id to
+ -- point to the formals of Subp_Id.
+
+ procedure Collect_Body_Postconditions (Stmts : in out List_Id);
+ -- Process all postconditions found in the declarations of the body. The
+ -- routine appends the pragma Check equivalents to list Stmts.
+
+ procedure Collect_Spec_Postconditions
+ (Subp_Id : Entity_Id;
+ Stmts : in out List_Id);
+ -- Process all [inherited] postconditions of subprogram spec Subp_Id.
+ -- The routine appends the pragma Check equivalents to list Stmts.
+
+ procedure Collect_Spec_Preconditions (Subp_Id : Entity_Id);
+ -- Process all [inherited] preconditions of subprogram spec Subp_Id. The
+ -- routine prepends the pragma Check equivalents to the declarations of
+ -- the body.
+
+ procedure Prepend_To_Declarations (Item : Node_Id);
+ -- Prepend a single item to the declarations of the subprogram body
+
+ procedure Process_Contract_Cases
+ (Subp_Id : Entity_Id;
+ Stmts : in out List_Id);
+ -- Process pragma Contract_Cases of subprogram spec Subp_Id. The routine
+ -- appends the expanded code to list Stmts.
+
+ ----------------------------------------
+ -- Add_Invariant_And_Predicate_Checks --
+ ----------------------------------------
+
+ procedure Add_Invariant_And_Predicate_Checks
+ (Subp_Id : Entity_Id;
+ Stmts : in out List_Id;
+ Result : out Node_Id)
+ is
+ procedure Add_Invariant_Access_Checks (Id : Entity_Id);
+ -- Id denotes the return value of a function or a formal parameter.
+ -- Add an invariant check if the type of Id is access to a type with
+ -- invariants. The routine appends the generated code to Stmts.
+
+ function Invariant_Checks_OK (Typ : Entity_Id) return Boolean;
+ -- Determine whether type Typ can benefit from invariant checks. To
+ -- qualify, the type must have a non-null invariant procedure and
+ -- subprogram Subp_Id must appear visible from the point of view of
+ -- the type.
+
+ function Predicate_Checks_OK (Typ : Entity_Id) return Boolean;
+ -- Determine whether type Typ can benefit from predicate checks. To
+ -- qualify, the type must have at least one checked predicate.
+
+ ---------------------------------
+ -- Add_Invariant_Access_Checks --
+ ---------------------------------
+
+ procedure Add_Invariant_Access_Checks (Id : Entity_Id) is
+ Loc : constant Source_Ptr := Sloc (N);
+ Ref : Node_Id;
+ Typ : Entity_Id;
+
+ begin
+ Typ := Etype (Id);
+
+ if Is_Access_Type (Typ) and then not Is_Access_Constant (Typ) then
+ Typ := Designated_Type (Typ);
+
+ if Invariant_Checks_OK (Typ) then
+ Ref :=
+ Make_Explicit_Dereference (Loc,
+ Prefix => New_Occurrence_Of (Id, Loc));
+ Set_Etype (Ref, Typ);
+
+ -- Generate:
+ -- if <Id> /= null then
+ -- <invariant_call (<Ref>)>
+ -- end if;
+
+ Append_Enabled_Item
+ (Item =>
+ Make_If_Statement (Loc,
+ Condition =>
+ Make_Op_Ne (Loc,
+ Left_Opnd => New_Occurrence_Of (Id, Loc),
+ Right_Opnd => Make_Null (Loc)),
+ Then_Statements => New_List (
+ Make_Invariant_Call (Ref))),
+ List => Stmts);
+ end if;
+ end if;
+ end Add_Invariant_Access_Checks;
+
+ -------------------------
+ -- Invariant_Checks_OK --
+ -------------------------
+
+ function Invariant_Checks_OK (Typ : Entity_Id) return Boolean is
+ function Has_Null_Body (Proc_Id : Entity_Id) return Boolean;
+ -- Determine whether the body of procedure Proc_Id contains a sole
+ -- null statement, possibly followed by an optional return.
+
+ function Has_Public_Visibility_Of_Subprogram return Boolean;
+ -- Determine whether type Typ has public visibility of subprogram
+ -- Subp_Id.
+
+ -------------------
+ -- Has_Null_Body --
+ -------------------
+
+ function Has_Null_Body (Proc_Id : Entity_Id) return Boolean is
+ Body_Id : Entity_Id;
+ Decl : Node_Id;
+ Spec : Node_Id;
+ Stmt1 : Node_Id;
+ Stmt2 : Node_Id;
+
+ begin
+ Spec := Parent (Proc_Id);
+ Decl := Parent (Spec);
+
+ -- Retrieve the entity of the invariant procedure body
+
+ if Nkind (Spec) = N_Procedure_Specification
+ and then Nkind (Decl) = N_Subprogram_Declaration
+ then
+ Body_Id := Corresponding_Body (Decl);
+
+ -- The body acts as a spec
+
+ else
+ Body_Id := Proc_Id;
+ end if;
+
+ -- The body will be generated later
+
+ if No (Body_Id) then
+ return False;
+ end if;
+
+ Spec := Parent (Body_Id);
+ Decl := Parent (Spec);
+
+ pragma Assert
+ (Nkind (Spec) = N_Procedure_Specification
+ and then Nkind (Decl) = N_Subprogram_Body);
+
+ Stmt1 := First (Statements (Handled_Statement_Sequence (Decl)));
+
+ -- Look for a null statement followed by an optional return
+ -- statement.
+
+ if Nkind (Stmt1) = N_Null_Statement then
+ Stmt2 := Next (Stmt1);
+
+ if Present (Stmt2) then
+ return Nkind (Stmt2) = N_Simple_Return_Statement;
+ else
+ return True;
+ end if;
+ end if;
+
+ return False;
+ end Has_Null_Body;
+
+ -----------------------------------------
+ -- Has_Public_Visibility_Of_Subprogram --
+ -----------------------------------------
+
+ function Has_Public_Visibility_Of_Subprogram return Boolean is
+ Subp_Decl : constant Node_Id := Unit_Declaration_Node (Subp_Id);
+ Vis_Decls : constant List_Id :=
+ Visible_Declarations (Specification
+ (Unit_Declaration_Node (Scope (Typ))));
+ begin
+ -- An Initialization procedure must be considered visible even
+ -- though it is internally generated.
+
+ if Is_Init_Proc (Defining_Entity (Subp_Decl)) then
+ return True;
+
+ -- Internally generated code is never publicly visible except
+ -- for a subprogram that is the implementation of an expression
+ -- function. In that case the visibility is determined by the
+ -- last check.
+
+ elsif not Comes_From_Source (Subp_Decl)
+ and then
+ (Nkind (Original_Node (Subp_Decl)) /= N_Expression_Function
+ or else not
+ Comes_From_Source (Defining_Entity (Subp_Decl)))
+ then
+ return False;
+
+ -- Determine whether the subprogram is declared in the visible
+ -- declarations of the package containing the type.
+
+ else
+ return List_Containing (Subp_Decl) = Vis_Decls;
+ end if;
+ end Has_Public_Visibility_Of_Subprogram;
+
+ -- Start of processing for Invariant_Checks_OK
+
+ begin
+ return
+ Has_Invariants (Typ)
+ and then Present (Invariant_Procedure (Typ))
+ and then not Has_Null_Body (Invariant_Procedure (Typ))
+ and then Has_Public_Visibility_Of_Subprogram;
+ end Invariant_Checks_OK;
+
+ -------------------------
+ -- Predicate_Checks_OK --
+ -------------------------
+
+ function Predicate_Checks_OK (Typ : Entity_Id) return Boolean is
+ function Has_Checked_Predicate return Boolean;
+ -- Determine whether type Typ has or inherits at least one
+ -- predicate aspect or pragma, for which the applicable policy is
+ -- Checked.
+
+ ---------------------------
+ -- Has_Checked_Predicate --
+ ---------------------------
+
+ function Has_Checked_Predicate return Boolean is
+ Anc : Entity_Id;
+ Pred : Node_Id;
+
+ begin
+ -- Climb the ancestor type chain staring from the input. This
+ -- is done because the input type may lack aspect/pragma
+ -- predicate and simply inherit those from its ancestor.
+
+ -- Note that predicate pragmas include all three cases of
+ -- predicate aspects (Predicate, Dynamic_Predicate,
+ -- Static_Predicate), so this routine checks for all three
+ -- cases.
+
+ Anc := Typ;
+ while Present (Anc) loop
+ Pred := Get_Pragma (Anc, Pragma_Predicate);
+
+ if Present (Pred) and then not Is_Ignored (Pred) then
+ return True;
+ end if;
+
+ Anc := Nearest_Ancestor (Anc);
+ end loop;
+
+ return False;
+ end Has_Checked_Predicate;
+
+ -- Start of processing for Predicate_Checks_OK
+
+ begin
+ return
+ Has_Predicates (Typ)
+ and then Present (Predicate_Function (Typ))
+ and then Has_Checked_Predicate;
+ end Predicate_Checks_OK;
+
+ -- Local variables
+
+ Loc : constant Source_Ptr := Sloc (N);
+ Formal : Entity_Id;
+ Typ : Entity_Id;
+
+ -- Start of processing for Add_Invariant_And_Predicate_Checks
+
+ begin
+ Result := Empty;
+
+ -- Do not generate any checks if no code is being generated
+
+ if not Expander_Active then
+ return;
+ end if;
+
+ -- Process the result of a function
+
+ if Ekind_In (Subp_Id, E_Function, E_Generic_Function) then
+ Typ := Etype (Subp_Id);
+
+ -- Generate _Result which is used in procedure _Postconditions to
+ -- verify the return value.
+
+ Result := Make_Defining_Identifier (Loc, Name_uResult);
+ Set_Etype (Result, Typ);
+
+ -- Add an invariant check when the return type has invariants and
+ -- the related function is visible to the outside.
+
+ if Invariant_Checks_OK (Typ) then
+ Append_Enabled_Item
+ (Item =>
+ Make_Invariant_Call (New_Occurrence_Of (Result, Loc)),
+ List => Stmts);
+ end if;
+
+ -- Add an invariant check when the return type is an access to a
+ -- type with invariants.
+
+ Add_Invariant_Access_Checks (Result);
+ end if;
+
+ -- Add invariant and predicates for all formals that qualify
+
+ Formal := First_Formal (Subp_Id);
+ while Present (Formal) loop
+ Typ := Etype (Formal);
+
+ if Ekind (Formal) /= E_In_Parameter
+ or else Is_Access_Type (Typ)
+ then
+ if Invariant_Checks_OK (Typ) then
+ Append_Enabled_Item
+ (Item =>
+ Make_Invariant_Call (New_Occurrence_Of (Formal, Loc)),
+ List => Stmts);
+ end if;
+
+ Add_Invariant_Access_Checks (Formal);
+
+ if Predicate_Checks_OK (Typ) then
+ Append_Enabled_Item
+ (Item =>
+ Make_Predicate_Check
+ (Typ, New_Reference_To (Formal, Loc)),
+ List => Stmts);
+ end if;
+ end if;
+
+ Next_Formal (Formal);
+ end loop;
+ end Add_Invariant_And_Predicate_Checks;
+
+ -------------------------
+ -- Append_Enabled_Item --
+ -------------------------
+
+ procedure Append_Enabled_Item (Item : Node_Id; List : in out List_Id) is
+ begin
+ -- Do not chain ignored or disabled pragmas
+
+ if Nkind (Item) = N_Pragma
+ and then (Is_Ignored (Item) or else Is_Disabled (Item))
+ then
+ null;
+
+ -- Add the item
+
+ else
+ if No (List) then
+ List := New_List;
+ end if;
+
+ Append (Item, List);
+ end if;
+ end Append_Enabled_Item;
+
+ ------------------------------------
+ -- Build_Postconditions_Procedure --
+ ------------------------------------
+
+ procedure Build_Postconditions_Procedure
+ (Subp_Id : Entity_Id;
+ Stmts : List_Id;
+ Result : Entity_Id)
+ is
+ procedure Insert_After_Last_Declaration (Stmt : Node_Id);
+ -- Insert node Stmt after the last declaration of the subprogram body
+
+ -----------------------------------
+ -- Insert_After_Last_Declaration --
+ -----------------------------------
+
+ procedure Insert_After_Last_Declaration (Stmt : Node_Id) is
+ Decls : List_Id := Declarations (N);
+
+ begin
+ -- Ensure that the body has a declaration list
+
+ if No (Decls) then
+ Decls := New_List;
+ Set_Declarations (N, Decls);
+ end if;
+
+ Append_To (Decls, Stmt);
+ end Insert_After_Last_Declaration;
+
+ -- Local variables
+
+ Loc : constant Source_Ptr := Sloc (N);
+ Params : List_Id := No_List;
+ Proc_Id : Entity_Id;
+
+ -- Start of processing for Build_Postconditions_Procedure
+
+ begin
+ -- Do not create the routine if no code is being generated
+
+ if not Expander_Active then
+ return;
+
+ -- Nothing to do if there are no actions to check on exit
+
+ elsif No (Stmts) then
+ return;
+ end if;
+
+ Proc_Id := Make_Defining_Identifier (Loc, Name_uPostconditions);
+
+ -- The related subprogram is a function, create the specification of
+ -- parameter _Result.
+
+ if Present (Result) then
+ Params := New_List (
+ Make_Parameter_Specification (Loc,
+ Defining_Identifier => Result,
+ Parameter_Type =>
+ New_Reference_To (Etype (Result), Loc)));
+ end if;
+
+ -- Insert _Postconditions after the last declaration of the body.
+ -- This ensures that the body will not cause any premature freezing
+ -- as it may mention types:
+
+ -- procedure Proc (Obj : Array_Typ) is
+ -- procedure _postconditions is
+ -- begin
+ -- ... Obj ...
+ -- end _postconditions;
+
+ -- subtype T is Array_Typ (Obj'First (1) .. Obj'Last (1));
+ -- begin
+
+ -- In the example above, Obj is of type T but the incorrect placement
+ -- of _Postconditions will cause a crash in gigi due to an out of
+ -- order reference. The body of _Postconditions must be placed after
+ -- the declaration of Temp to preserve correct visibility.
+
+ Insert_After_Last_Declaration (
+ Make_Subprogram_Body (Loc,
+ Specification =>
+ Make_Procedure_Specification (Loc,
+ Defining_Unit_Name => Proc_Id,
+ Parameter_Specifications => Params),
+
+ Declarations => Empty_List,
+ Handled_Statement_Sequence =>
+ Make_Handled_Sequence_Of_Statements (Loc, Stmts)));
+
+ -- Set the attributes of the related subprogram to capture the
+ -- generated procedure.
+
+ if Ekind_In (Subp_Id, E_Generic_Procedure, E_Procedure) then
+ Set_Postcondition_Proc (Subp_Id, Proc_Id);
+ end if;
+
+ Set_Has_Postconditions (Subp_Id);
+ end Build_Postconditions_Procedure;
+
+ -----------------------------------
+ -- Build_Pragma_Check_Equivalent --
+ -----------------------------------
+
+ function Build_Pragma_Check_Equivalent
+ (Prag : Node_Id;
+ Subp_Id : Entity_Id := Empty;
+ Inher_Id : Entity_Id := Empty) return Node_Id
+ is
+ Loc : constant Source_Ptr := Sloc (Prag);
+ Prag_Nam : constant Name_Id := Pragma_Name (Prag);
+ Check_Prag : Node_Id;
+ Formals_Map : Elist_Id;
+ Inher_Formal : Entity_Id;
+ Msg_Arg : Node_Id;
+ Nam : Name_Id;
+ Subp_Formal : Entity_Id;
+
+ begin
+ Formals_Map := No_Elist;
+
+ -- When the pre- or postcondition is inherited, map the formals of
+ -- the inherited subprogram to those of the current subprogram.
+
+ if Present (Inher_Id) then
+ pragma Assert (Present (Subp_Id));
+
+ Formals_Map := New_Elmt_List;
+
+ -- Create a relation <inherited formal> => <subprogram formal>
+
+ Inher_Formal := First_Formal (Inher_Id);
+ Subp_Formal := First_Formal (Subp_Id);
+ while Present (Inher_Formal) and then Present (Subp_Formal) loop
+ Append_Elmt (Inher_Formal, Formals_Map);
+ Append_Elmt (Subp_Formal, Formals_Map);
+
+ Next_Formal (Inher_Formal);
+ Next_Formal (Subp_Formal);
+ end loop;
+ end if;
+
+ -- Copy the original pragma while performing substitutions (if
+ -- applicable).
+
+ Check_Prag :=
+ New_Copy_Tree
+ (Source => Prag,
+ Map => Formals_Map,
+ New_Scope => Current_Scope);
+
+ -- Mark the pragma as being internally generated and reset the
+ -- Analyzed flag.
+
+ Set_Comes_From_Source (Check_Prag, False);
+ Set_Analyzed (Check_Prag, False);
+
+ -- For a postcondition pragma within a generic, preserve the pragma
+ -- for later expansion. This is also used when an error was detected,
+ -- thus setting Expander_Active to False.
+
+ if Prag_Nam = Name_Postcondition and then not Expander_Active then
+ return Check_Prag;
+ end if;
+
+ if Present (Corresponding_Aspect (Prag)) then
+ Nam := Chars (Identifier (Corresponding_Aspect (Prag)));
+ else
+ Nam := Prag_Nam;
+ end if;
+
+ -- Convert the copy into pragma Check by correcting the name and
+ -- adding a check_kind argument.
+
+ Set_Pragma_Identifier
+ (Check_Prag, Make_Identifier (Loc, Name_Check));
+
+ Prepend_To (Pragma_Argument_Associations (Check_Prag),
+ Make_Pragma_Argument_Association (Loc,
+ Expression => Make_Identifier (Loc, Nam)));
+
+ -- Update the error message when the pragma is inherited
+
+ if Present (Inher_Id) then
+ Msg_Arg := Last (Pragma_Argument_Associations (Check_Prag));
+
+ if Chars (Msg_Arg) = Name_Message then
+ String_To_Name_Buffer (Strval (Expression (Msg_Arg)));
+
+ -- Insert "inherited" to improve the error message
+
+ if Name_Buffer (1 .. 8) = "failed p" then
+ Insert_Str_In_Name_Buffer ("inherited ", 8);
+ Set_Strval (Expression (Msg_Arg), String_From_Name_Buffer);
+ end if;
+ end if;
+ end if;
+
+ return Check_Prag;
+ end Build_Pragma_Check_Equivalent;
+
+ ---------------------------------
+ -- Collect_Body_Postconditions --
+ ---------------------------------
+
+ procedure Collect_Body_Postconditions (Stmts : in out List_Id) is
+ procedure Collect_Body_Postconditions_Of_Kind (Post_Nam : Name_Id);
+ -- Process postconditions of a particular kind denoted by Post_Nam
+
+ -----------------------------------------
+ -- Collect_Body_Postconditions_Of_Kind --
+ -----------------------------------------
+
+ procedure Collect_Body_Postconditions_Of_Kind (Post_Nam : Name_Id) is
+ Check_Prag : Node_Id;
+ Decl : Node_Id;
+
+ begin
+ pragma Assert (Nam_In (Post_Nam, Name_Postcondition,
+ Name_Refined_Post));
+
+ -- Inspect the declarations of the subprogram body looking for a
+ -- pragma that matches the desired name.
+
+ Decl := First (Declarations (N));
+ while Present (Decl) loop
+ if Nkind (Decl) = N_Pragma then
+ if Pragma_Name (Decl) = Post_Nam then
+ Analyze (Decl);
+ Check_Prag := Build_Pragma_Check_Equivalent (Decl);
+
+ if Expander_Active then
+ Append_Enabled_Item
+ (Item => Check_Prag,
+ List => Stmts);
+
+ -- When analyzing a generic unit, save the pragma for
+ -- later.
+
+ else
+ Prepend_To_Declarations (Check_Prag);
+ end if;
+ end if;
+
+ -- Skip internally generated code
+
+ elsif not Comes_From_Source (Decl) then
+ null;
+
+ -- Postconditions in bodies are usually grouped at the top of
+ -- the declarations. There is no point in inspecting the whole
+ -- source list.
+
+ else
+ exit;
+ end if;
+
+ Next (Decl);
+ end loop;
+ end Collect_Body_Postconditions_Of_Kind;
+
+ -- Start of processing for Collect_Body_Postconditions
+
+ begin
+ Collect_Body_Postconditions_Of_Kind (Name_Refined_Post);
+ Collect_Body_Postconditions_Of_Kind (Name_Postcondition);
+ end Collect_Body_Postconditions;
+
+ ---------------------------------
+ -- Collect_Spec_Postconditions --
+ ---------------------------------
+
+ procedure Collect_Spec_Postconditions
+ (Subp_Id : Entity_Id;
+ Stmts : in out List_Id)
+ is
+ Inher_Subps : constant Subprogram_List :=
+ Inherited_Subprograms (Subp_Id);
+ Check_Prag : Node_Id;
+ Prag : Node_Id;
+ Inher_Subp_Id : Entity_Id;
+
+ begin
+ -- Process the contract of the spec
+
+ Prag := Pre_Post_Conditions (Contract (Subp_Id));
+ while Present (Prag) loop
+ if Pragma_Name (Prag) = Name_Postcondition then
+ Check_Prag := Build_Pragma_Check_Equivalent (Prag);
+
+ if Expander_Active then
+ Append_Enabled_Item
+ (Item => Check_Prag,
+ List => Stmts);
+
+ -- When analyzing a generic unit, save the pragma for later
+
+ else
+ Prepend_To_Declarations (Check_Prag);
+ end if;
+ end if;
+
+ Prag := Next_Pragma (Prag);
+ end loop;
+
+ -- Process the contracts of all inherited subprograms, looking for
+ -- class-wide postconditions.
+
+ for Index in Inher_Subps'Range loop
+ Inher_Subp_Id := Inher_Subps (Index);
+
+ Prag := Pre_Post_Conditions (Contract (Inher_Subp_Id));
+ while Present (Prag) loop
+ if Pragma_Name (Prag) = Name_Postcondition
+ and then Class_Present (Prag)
+ then
+ Check_Prag :=
+ Build_Pragma_Check_Equivalent
+ (Prag => Prag,
+ Subp_Id => Subp_Id,
+ Inher_Id => Inher_Subp_Id);
+
+ if Expander_Active then
+ Append_Enabled_Item
+ (Item => Check_Prag,
+ List => Stmts);
+
+ -- When analyzing a generic unit, save the pragma for later
+
+ else
+ Prepend_To_Declarations (Check_Prag);
+ end if;
+ end if;
+
+ Prag := Next_Pragma (Prag);
+ end loop;
+ end loop;
+ end Collect_Spec_Postconditions;
+
+ --------------------------------
+ -- Collect_Spec_Preconditions --
+ --------------------------------
+
+ procedure Collect_Spec_Preconditions (Subp_Id : Entity_Id) is
+ procedure Merge_Preconditions (From : Node_Id; Into : Node_Id);
+ -- Merge two class-wide preconditions by "or else"-ing them. The
+ -- changes are accumulated in parameter Into. Update the error
+ -- message of Into.
+
+ -------------------------
+ -- Merge_Preconditions --
+ -------------------------
+
+ procedure Merge_Preconditions (From : Node_Id; Into : Node_Id) is
+ function Expression_Arg (Prag : Node_Id) return Node_Id;
+ -- Return the boolean expression argument of a precondition while
+ -- updating its parenteses count for the subsequent merge.
+
+ function Message_Arg (Prag : Node_Id) return Node_Id;
+ -- Return the message argument of a precondition
+
+ --------------------
+ -- Expression_Arg --
+ --------------------
+
+ function Expression_Arg (Prag : Node_Id) return Node_Id is
+ Args : constant List_Id := Pragma_Argument_Associations (Prag);
+ Arg : constant Node_Id := Get_Pragma_Arg (Next (First (Args)));
+
+ begin
+ if Paren_Count (Arg) = 0 then
+ Set_Paren_Count (Arg, 1);
+ end if;
+
+ return Arg;
+ end Expression_Arg;
+
+ -----------------
+ -- Message_Arg --
+ -----------------
+
+ function Message_Arg (Prag : Node_Id) return Node_Id is
+ Args : constant List_Id := Pragma_Argument_Associations (Prag);
+ begin
+ return Get_Pragma_Arg (Last (Args));
+ end Message_Arg;
+
+ -- Local variables
+
+ From_Expr : constant Node_Id := Expression_Arg (From);
+ From_Msg : constant Node_Id := Message_Arg (From);
+ Into_Expr : constant Node_Id := Expression_Arg (Into);
+ Into_Msg : constant Node_Id := Message_Arg (Into);
+ Loc : constant Source_Ptr := Sloc (Into);
+
+ -- Start of processing for Merge_Preconditions
+
+ begin
+ -- Merge the two preconditions by "or else"-ing them
+
+ Rewrite (Into_Expr,
+ Make_Or_Else (Loc,
+ Right_Opnd => Relocate_Node (Into_Expr),
+ Left_Opnd => From_Expr));
+
+ -- Merge the two error messages to produce a single message of the
+ -- form:
+
+ -- failed precondition from ...
+ -- also failed inherited precondition from ...
+
+ if not Exception_Locations_Suppressed then
+ Start_String (Strval (Into_Msg));
+ Store_String_Char (ASCII.LF);
+ Store_String_Chars (" also ");
+ Store_String_Chars (Strval (From_Msg));
+
+ Set_Strval (Into_Msg, End_String);
+ end if;
+ end Merge_Preconditions;
+
+ -- Local variables
+
+ Inher_Subps : constant Subprogram_List :=
+ Inherited_Subprograms (Subp_Id);
+ Check_Prag : Node_Id;
+ Class_Pre : Node_Id := Empty;
+ Inher_Subp_Id : Entity_Id;
+ Prag : Node_Id;
+
+ -- Start of processing for Collect_Spec_Preconditions
+
+ begin
+ -- Process the contract of the spec
+
+ Prag := Pre_Post_Conditions (Contract (Subp_Id));
+ while Present (Prag) loop
+ if Pragma_Name (Prag) = Name_Precondition then
+ Check_Prag := Build_Pragma_Check_Equivalent (Prag);
+
+ -- Save the sole class-wide precondition (if any) for the next
+ -- step where it will be merged with inherited preconditions.
+
+ if Class_Present (Prag) then
+ Class_Pre := Check_Prag;
+
+ -- Accumulate the corresponding Check pragmas to the top of the
+ -- declarations. Prepending the items ensures that they will
+ -- be evaluated in their original order.
+
+ else
+ Prepend_To_Declarations (Check_Prag);
+ end if;
+ end if;
+
+ Prag := Next_Pragma (Prag);
+ end loop;
+
+ -- Process the contracts of all inherited subprograms, looking for
+ -- class-wide preconditions.
+
+ for Index in Inher_Subps'Range loop
+ Inher_Subp_Id := Inher_Subps (Index);
+
+ Prag := Pre_Post_Conditions (Contract (Inher_Subp_Id));
+ while Present (Prag) loop
+ if Pragma_Name (Prag) = Name_Precondition
+ and then Class_Present (Prag)
+ then
+ Check_Prag :=
+ Build_Pragma_Check_Equivalent
+ (Prag => Prag,
+ Subp_Id => Subp_Id,
+ Inher_Id => Inher_Subp_Id);
+
+ -- The spec or an inherited subprogram already yielded a
+ -- class-wide precondition. Merge the existing precondition
+ -- with the current one using "or else".
+
+ if Present (Class_Pre) then
+ Merge_Preconditions (Check_Prag, Class_Pre);
+ else
+ Class_Pre := Check_Prag;
+ end if;
+ end if;
+
+ Prag := Next_Pragma (Prag);
+ end loop;
+ end loop;
+
+ -- Add the merged class-wide preconditions (if any)
+
+ if Present (Class_Pre) then
+ Prepend_To_Declarations (Class_Pre);
+ end if;
+ end Collect_Spec_Preconditions;
+
+ -----------------------------
+ -- Prepend_To_Declarations --
+ -----------------------------
+
+ procedure Prepend_To_Declarations (Item : Node_Id) is
+ Decls : List_Id := Declarations (N);
+
+ begin
+ -- Ensure that the body has a declarative list
+
+ if No (Decls) then
+ Decls := New_List;
+ Set_Declarations (N, Decls);
+ end if;
+
+ Prepend_To (Decls, Item);
+ end Prepend_To_Declarations;
+
+ ----------------------------
+ -- Process_Contract_Cases --
+ ----------------------------
+
+ procedure Process_Contract_Cases
+ (Subp_Id : Entity_Id;
+ Stmts : in out List_Id)
+ is
+ Prag : Node_Id;
+
+ begin
+ -- Do not build the Contract_Cases circuitry if no code is being
+ -- generated.
+
+ if not Expander_Active then
+ return;
+ end if;
+
+ Prag := Contract_Test_Cases (Contract (Subp_Id));
+ while Present (Prag) loop
+ if Pragma_Name (Prag) = Name_Contract_Cases then
+ Expand_Contract_Cases
+ (CCs => Prag,
+ Subp_Id => Subp_Id,
+ Decls => Declarations (N),
+ Stmts => Stmts);
+ end if;
+
+ Prag := Next_Pragma (Prag);
+ end loop;
+ end Process_Contract_Cases;
+
+ -- Local variables
+
+ Post_Stmts : List_Id := No_List;
+ Result : Entity_Id;
+ Subp_Id : Entity_Id;
+
+ -- Start of processing for Expand_Subprogram_Contract
+
+ begin
+ if Present (Spec_Id) then
+ Subp_Id := Spec_Id;
+ else
+ Subp_Id := Body_Id;
+ end if;
+
+ -- Do not process a predicate function as its body will end up with a
+ -- recursive call to itself and blow up the stack.
+
+ if Ekind (Subp_Id) = E_Function
+ and then Is_Predicate_Function (Subp_Id)
+ then
+ return;
+
+ -- Do not process TSS subprograms
+
+ elsif Get_TSS_Name (Subp_Id) /= TSS_Null then
+ return;
+ end if;
+
+ -- The expansion of a subprogram contract involves the relocation of
+ -- various contract assertions to the declarations of the body in a
+ -- particular order. The order is as follows:
+
+ -- function Example (...) return ... is
+ -- procedure _Postconditions (...) is
+ -- begin
+ -- <refined postconditions from body>
+ -- <postconditions from body>
+ -- <postconditions from spec>
+ -- <inherited postconditions>
+ -- <contract cases>
+ -- <invariant check of function result (if applicable)>
+ -- <invariant and predicate checks of parameters>
+ -- end _Postconditions;
+
+ -- <inherited preconditions>
+ -- <preconditions from spec>
+ -- <preconditions from body>
+ -- <refined preconditions from body>
+
+ -- <source declarations>
+ -- begin
+ -- <source statements>
+
+ -- _Preconditions (Result);
+ -- return Result;
+ -- end Example;
+
+ -- Routine _Postconditions holds all contract assertions that must be
+ -- verified on exit from the related routine.
+
+ -- Collect all [inherited] preconditions from the spec, transform them
+ -- into Check pragmas and add them to the declarations of the body in
+ -- the order outlined above.
+
+ if Present (Spec_Id) then
+ Collect_Spec_Preconditions (Spec_Id);
+ end if;
+
+ -- Transform all [refined] postconditions of the body into Check
+ -- pragmas. The resulting pragmas are accumulated in list Post_Stmts.
+
+ Collect_Body_Postconditions (Post_Stmts);
+
+ -- Transform all [inherited] postconditions from the spec into Check
+ -- pragmas. The resulting pragmas are accumulated in list Post_Stmts.
+
+ if Present (Spec_Id) then
+ Collect_Spec_Postconditions (Spec_Id, Post_Stmts);
+
+ -- Transform pragma Contract_Cases from the spec into its circuitry
+
+ Process_Contract_Cases (Spec_Id, Post_Stmts);
+ end if;
+
+ -- Apply invariant and predicate checks on the result of a function (if
+ -- applicable) and all formals. The resulting checks are accumulated in
+ -- list Post_Stmts.
+
+ Add_Invariant_And_Predicate_Checks (Subp_Id, Post_Stmts, Result);
+
+ -- Construct procedure _Postconditions
+
+ Build_Postconditions_Procedure (Subp_Id, Post_Stmts, Result);
+ end Expand_Subprogram_Contract;
+
+ --------------------------------
-- Is_Build_In_Place_Function --
--------------------------------
@@ -8527,7 +9572,7 @@ package body Exp_Ch6 is
-- may return objects of nonlimited descendants.
else
- return Is_Immutably_Limited_Type (Etype (E))
+ return Is_Limited_View (Etype (E))
and then Ada_Version >= Ada_2005
and then not Debug_Flag_Dot_L;
end if;
@@ -8554,7 +9599,11 @@ package body Exp_Ch6 is
-- disabled (such as with -gnatc) since those would trip over the raise
-- of Program_Error below.
- if not Expander_Active then
+ -- In SPARK mode, build-in-place calls are not expanded, so that we
+ -- may end up with a call that is neither resolved to an entity, nor
+ -- an indirect call.
+
+ if not Full_Expander_Active then
return False;
end if;
@@ -8571,14 +9620,7 @@ package body Exp_Ch6 is
return False;
else
- -- In SPARK mode, build-in-place calls are not expanded, so that we
- -- may end up with a call that is neither resolved to an entity, nor
- -- an indirect call.
-
- if SPARK_Mode then
- return False;
-
- elsif Is_Entity_Name (Name (Exp_Node)) then
+ if Is_Entity_Name (Name (Exp_Node)) then
Function_Id := Entity (Name (Exp_Node));
-- In the case of an explicitly dereferenced call, use the subprogram
@@ -8771,7 +9813,7 @@ package body Exp_Ch6 is
Typ : constant Entity_Id := Etype (Subp);
Utyp : constant Entity_Id := Underlying_Type (Typ);
begin
- if Is_Immutably_Limited_Type (Typ) then
+ if Is_Limited_View (Typ) then
Set_Returns_By_Ref (Subp);
elsif Present (Utyp) and then CW_Or_Has_Controlled_Part (Utyp) then
Set_Returns_By_Ref (Subp);
@@ -9047,14 +10089,10 @@ package body Exp_Ch6 is
then
null;
- -- Do not generate the call to Set_Finalize_Address in SPARK mode
- -- because it is not necessary and results in unwanted expansion.
- -- This expansion is also not carried out in CodePeer mode because
- -- Finalize_Address is never built.
+ -- Do not generate the call to Set_Finalize_Address in CodePeer mode
+ -- because Finalize_Address is never built.
- elsif not SPARK_Mode
- and then not CodePeer_Mode
- then
+ elsif not CodePeer_Mode then
Insert_Action (Allocator,
Make_Set_Finalize_Address_Call (Loc,
Typ => Etype (Function_Id),
diff --git a/gcc/ada/exp_ch6.ads b/gcc/ada/exp_ch6.ads
index f9829f52b34..02cca2401df 100644
--- a/gcc/ada/exp_ch6.ads
+++ b/gcc/ada/exp_ch6.ads
@@ -82,6 +82,18 @@ package Exp_Ch6 is
-- Subp_Id's body. All generated code is added to list Stmts. If Stmts is
-- empty, a new list is created.
+ procedure Expand_Subprogram_Contract
+ (N : Node_Id;
+ Spec_Id : Entity_Id;
+ Body_Id : Entity_Id);
+ -- Expand the contracts of a subprogram body and its correspoding spec (if
+ -- any). This routine processes all [refined] pre- and postconditions as
+ -- well as Contract_Cases, invariants and predicates. N is the body of the
+ -- subprogram. Spec_Id denotes the entity of its specification. Body_Id
+ -- denotes the entity of the subprogram body. This routine is not a "pure"
+ -- expansion mechanism as it is invoked during analysis and may perform
+ -- actions for generic subprograms or set up contract assertions for ASIS.
+
procedure Freeze_Subprogram (N : Node_Id);
-- generate the appropriate expansions related to Subprogram freeze
-- nodes (e.g. the filling of the corresponding Dispatch Table for
diff --git a/gcc/ada/exp_ch7.adb b/gcc/ada/exp_ch7.adb
index fdaf213ff86..8449f6aba1f 100644
--- a/gcc/ada/exp_ch7.adb
+++ b/gcc/ada/exp_ch7.adb
@@ -310,11 +310,11 @@ package body Exp_Ch7 is
Defer_Abort : Boolean;
Fin_Id : out Entity_Id);
-- N may denote an accept statement, block, entry body, package body,
- -- package spec, protected body, subprogram body, and a task body. Create
+ -- package spec, protected body, subprogram body, or a task body. Create
-- a procedure which contains finalization calls for all controlled objects
-- declared in the declarative or statement region of N. The calls are
-- built in reverse order relative to the original declarations. In the
- -- case of a tack body, the routine delays the creation of the finalizer
+ -- case of a task body, the routine delays the creation of the finalizer
-- until all statements have been moved to the task body procedure.
-- Clean_Stmts may contain additional context-dependent code used to abort
-- asynchronous calls or complete tasks (see Build_Cleanup_Statements).
@@ -368,6 +368,11 @@ package body Exp_Ch7 is
-- Given an arbitrary entity, traverse the scope chain looking for the
-- first enclosing function. Return Empty if no function was found.
+ procedure Expand_Pragma_Initial_Condition (N : Node_Id);
+ -- Subsidiary to the expansion of package specs and bodies. Generate a
+ -- runtime check needed to verify the assumption introduced by pragma
+ -- Initial_Condition. N denotes the package spec or body.
+
function Make_Call
(Loc : Source_Ptr;
Proc_Id : Entity_Id;
@@ -427,7 +432,7 @@ package body Exp_Ch7 is
Typ => Typ,
Stmts => Make_Deep_Array_Body (Initialize_Case, Typ)));
- if not Is_Immutably_Limited_Type (Typ) then
+ if not Is_Limited_View (Typ) then
Set_TSS (Typ,
Make_Deep_Proc
(Prim => Adjust_Case,
@@ -3222,7 +3227,7 @@ package body Exp_Ch7 is
Typ => Typ,
Stmts => Make_Deep_Record_Body (Initialize_Case, Typ)));
- if not Is_Immutably_Limited_Type (Typ) then
+ if not Is_Limited_View (Typ) then
Set_TSS (Typ,
Make_Deep_Proc
(Prim => Adjust_Case,
@@ -3959,6 +3964,15 @@ package body Exp_Ch7 is
end if;
Build_Task_Activation_Call (N);
+
+ -- When the package is subject to pragma Initial_Condition, the
+ -- assertion expression must be verified at the end of the body
+ -- statements.
+
+ if Present (Get_Pragma (Spec_Ent, Pragma_Initial_Condition)) then
+ Expand_Pragma_Initial_Condition (N);
+ end if;
+
Pop_Scope;
end if;
@@ -4053,10 +4067,9 @@ package body Exp_Ch7 is
if No_Body then
Push_Scope (Id);
- if Has_RACW (Id) then
-
- -- Generate RACW subprogram bodies
+ -- Generate RACW subprogram bodies
+ if Has_RACW (Id) then
Decls := Private_Declarations (Spec);
if No (Decls) then
@@ -4072,11 +4085,19 @@ package body Exp_Ch7 is
Analyze_List (Decls);
end if;
+ -- Generate task activation call as last step of elaboration
+
if Present (Activation_Chain_Entity (N)) then
+ Build_Task_Activation_Call (N);
+ end if;
- -- Generate task activation call as last step of elaboration
+ -- When the package is subject to pragma Initial_Condition and lacks
+ -- a body, the assertion expression must be verified at the end of
+ -- the visible declarations. Otherwise the check is performed at the
+ -- end of the body statements (see Expand_N_Package_Body).
- Build_Task_Activation_Call (N);
+ if Present (Get_Pragma (Id, Pragma_Initial_Condition)) then
+ Expand_Pragma_Initial_Condition (N);
end if;
Pop_Scope;
@@ -4114,6 +4135,88 @@ package body Exp_Ch7 is
end if;
end Expand_N_Package_Declaration;
+ -------------------------------------
+ -- Expand_Pragma_Initial_Condition --
+ -------------------------------------
+
+ procedure Expand_Pragma_Initial_Condition (N : Node_Id) is
+ Loc : constant Source_Ptr := Sloc (N);
+ Check : Node_Id;
+ Expr : Node_Id;
+ Init_Cond : Node_Id;
+ List : List_Id;
+ Pack_Id : Entity_Id;
+
+ begin
+ if Nkind (N) = N_Package_Body then
+ Pack_Id := Corresponding_Spec (N);
+
+ if Present (Handled_Statement_Sequence (N)) then
+ List := Statements (Handled_Statement_Sequence (N));
+
+ -- The package body lacks statements, create an empty list
+
+ else
+ List := New_List;
+
+ Set_Handled_Statement_Sequence (N,
+ Make_Handled_Sequence_Of_Statements (Loc, Statements => List));
+ end if;
+
+ elsif Nkind (N) = N_Package_Declaration then
+ Pack_Id := Defining_Entity (N);
+
+ if Present (Visible_Declarations (Specification (N))) then
+ List := Visible_Declarations (Specification (N));
+
+ -- The package lacks visible declarations, create an empty list
+
+ else
+ List := New_List;
+
+ Set_Visible_Declarations (Specification (N), List);
+ end if;
+
+ -- This routine should not be used on anything other than packages
+
+ else
+ raise Program_Error;
+ end if;
+
+ Init_Cond := Get_Pragma (Pack_Id, Pragma_Initial_Condition);
+
+ -- The caller should check whether the package is subject to pragma
+ -- Initial_Condition.
+
+ pragma Assert (Present (Init_Cond));
+
+ Expr :=
+ Get_Pragma_Arg (First (Pragma_Argument_Associations (Init_Cond)));
+
+ -- The assertion expression was found to be illegal, do not generate the
+ -- runtime check as it will repeat the illegality.
+
+ if Error_Posted (Init_Cond) or else Error_Posted (Expr) then
+ return;
+ end if;
+
+ -- Generate:
+ -- pragma Check (Initial_Condition, <Expr>);
+
+ Check :=
+ Make_Pragma (Loc,
+ Chars => Name_Check,
+ Pragma_Argument_Associations => New_List (
+ Make_Pragma_Argument_Association (Loc,
+ Expression => Make_Identifier (Loc, Name_Initial_Condition)),
+
+ Make_Pragma_Argument_Association (Loc,
+ Expression => New_Copy_Tree (Expr))));
+
+ Append_To (List, Check);
+ Analyze (Check);
+ end Expand_Pragma_Initial_Condition;
+
-----------------------------
-- Find_Node_To_Be_Wrapped --
-----------------------------
diff --git a/gcc/ada/exp_ch9.adb b/gcc/ada/exp_ch9.adb
index 16e83091529..8db80bde74b 100644
--- a/gcc/ada/exp_ch9.adb
+++ b/gcc/ada/exp_ch9.adb
@@ -8987,8 +8987,6 @@ package body Exp_Ch9 is
(Prot_Typ, Cdecls, Loc);
begin
- -- Could this be simplified using Corresponding_Runtime_Package???
-
if Has_Attach_Handler (Prot_Typ) then
Ritem := First_Rep_Item (Prot_Typ);
while Present (Ritem) loop
@@ -9000,47 +8998,40 @@ package body Exp_Ch9 is
Next_Rep_Item (Ritem);
end loop;
+ end if;
- if Restricted_Profile then
- if Has_Entries (Prot_Typ) then
- Protection_Subtype :=
- New_Reference_To (RTE (RE_Protection_Entry), Loc);
- else
- Protection_Subtype :=
- New_Reference_To (RTE (RE_Protection), Loc);
- end if;
+ -- Determine the proper protection type. There are two special
+ -- cases: 1) when the protected type has dynamic interrupt
+ -- handlers, and 2) when it has static handlers and we use a
+ -- restricted profile.
- else
- Protection_Subtype :=
- Make_Subtype_Indication (Loc,
- Subtype_Mark =>
- New_Reference_To
- (RTE (RE_Static_Interrupt_Protection), Loc),
- Constraint =>
- Make_Index_Or_Discriminant_Constraint (Loc,
- Constraints => New_List (
- Entry_Count_Expr,
- Make_Integer_Literal (Loc, Num_Attach_Handler))));
- end if;
+ if Has_Attach_Handler (Prot_Typ)
+ and then not Restricted_Profile
+ then
+ Protection_Subtype :=
+ Make_Subtype_Indication (Loc,
+ Subtype_Mark =>
+ New_Reference_To
+ (RTE (RE_Static_Interrupt_Protection), Loc),
+ Constraint =>
+ Make_Index_Or_Discriminant_Constraint (Loc,
+ Constraints => New_List (
+ Entry_Count_Expr,
+ Make_Integer_Literal (Loc, Num_Attach_Handler))));
elsif Has_Interrupt_Handler (Prot_Typ)
and then not Restriction_Active (No_Dynamic_Attachment)
then
Protection_Subtype :=
- Make_Subtype_Indication (Loc,
- Subtype_Mark =>
- New_Reference_To
- (RTE (RE_Dynamic_Interrupt_Protection), Loc),
- Constraint =>
- Make_Index_Or_Discriminant_Constraint (Loc,
- Constraints => New_List (Entry_Count_Expr)));
-
- -- Type has explicit entries or generated primitive entry wrappers
+ Make_Subtype_Indication (Loc,
+ Subtype_Mark =>
+ New_Reference_To
+ (RTE (RE_Dynamic_Interrupt_Protection), Loc),
+ Constraint =>
+ Make_Index_Or_Discriminant_Constraint (Loc,
+ Constraints => New_List (Entry_Count_Expr)));
- elsif Has_Entries (Prot_Typ)
- or else (Ada_Version >= Ada_2005
- and then Present (Interface_List (N)))
- then
+ else
case Corresponding_Runtime_Package (Prot_Typ) is
when System_Tasking_Protected_Objects_Entries =>
Protection_Subtype :=
@@ -9056,13 +9047,13 @@ package body Exp_Ch9 is
Protection_Subtype :=
New_Reference_To (RTE (RE_Protection_Entry), Loc);
+ when System_Tasking_Protected_Objects =>
+ Protection_Subtype :=
+ New_Reference_To (RTE (RE_Protection), Loc);
+
when others =>
raise Program_Error;
end case;
-
- else
- Protection_Subtype :=
- New_Reference_To (RTE (RE_Protection), Loc);
end if;
Object_Comp :=
@@ -11957,7 +11948,10 @@ package body Exp_Ch9 is
-- end if;
-- end;
- -- 3) Ada 2005 (AI-345): When T.E is a dispatching procedure call;
+ -- 3) Ada 2005 (AI-345): When T.E is a dispatching procedure call, there
+ -- is no delay and the triggering statements are executed. We first
+ -- determine the kind of of the triggering call and then execute a
+ -- synchronized operation or a direct call.
-- declare
-- B : Boolean := False;
@@ -11974,7 +11968,7 @@ package body Exp_Ch9 is
-- or else K = Ada.Tags.TK_Tagged
-- then
-- <dispatching-call>;
- -- <triggering-statements>
+ -- B := True;
-- else
-- S :=
@@ -11998,20 +11992,19 @@ package body Exp_Ch9 is
-- then
-- <dispatching-call>;
-- end if;
-
- -- <triggering-statements>
- -- else
- -- <timed-statements>
- -- end if;
+ -- end if;
-- end if;
+
+ -- if B then
+ -- <triggering-statements>
+ -- else
+ -- <timed-statements>
+ -- end if;
-- end;
-- The triggering statement and the sequence of timed statements have not
-- been analyzed yet (see Analyzed_Timed_Entry_Call), but they may contain
- -- global references if within an instantiation. To prevent duplication
- -- between various uses of those statements, they are encapsulated into a
- -- local procedure which is invoked multiple time when the trigger is a
- -- dispatching call.
+ -- global references if within an instantiation.
procedure Expand_N_Timed_Entry_Call (N : Node_Id) is
Loc : constant Source_Ptr := Sloc (N);
@@ -12054,63 +12047,6 @@ package body Exp_Ch9 is
P : Entity_Id; -- Parameter block
S : Entity_Id; -- Primitive operation slot
- procedure Rewrite_Triggering_Statements;
- -- If the trigger is a dispatching call, the expansion inserts multiple
- -- copies of the abortable part. This is both inefficient, and may lead
- -- to duplicate definitions that the back-end will reject, when the
- -- abortable part includes loops. This procedure rewrites the abortable
- -- part into a call to a generated procedure.
-
- -----------------------------------
- -- Rewrite_Triggering_Statements --
- -----------------------------------
-
- procedure Rewrite_Triggering_Statements is
- Proc : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uA);
- Decl : Node_Id;
- Stat : Node_Id;
-
- begin
- Decl :=
- Make_Subprogram_Body (Loc,
- Specification =>
- Make_Procedure_Specification (Loc, Defining_Unit_Name => Proc),
- Declarations => New_List,
- Handled_Statement_Sequence =>
- Make_Handled_Sequence_Of_Statements (Loc, E_Stats));
-
- Append_To (Decls, Decl);
-
- -- Adjust the scope of blocks in the procedure. Needed because blocks
- -- generate declarations that are processed before other analysis
- -- takes place, and their scope is already set. The backend depends
- -- on the scope chain to determine the legality of some anonymous
- -- types, and thus we must indicate that the block is within the new
- -- procedure.
-
- Stat := First (E_Stats);
- while Present (Stat) loop
- if Nkind (Stat) = N_Block_Statement then
- Insert_Before (Stat,
- Make_Implicit_Label_Declaration (Sloc (Stat),
- Defining_Identifier =>
- Make_Defining_Identifier (
- Sloc (Stat), Chars (Identifier (Stat)))));
- end if;
-
- Next (Stat);
- end loop;
-
- -- Analyze (Decl);
-
- -- Rewrite abortable part into a call to this procedure.
-
- E_Stats :=
- New_List
- (Make_Procedure_Call_Statement (Loc,
- Name => New_Occurrence_Of (Proc, Loc)));
- end Rewrite_Triggering_Statements;
-
-- Start of processing for Expand_N_Timed_Entry_Call
begin
@@ -12153,7 +12089,6 @@ package body Exp_Ch9 is
if Is_Disp_Select then
Extract_Dispatching_Call (E_Call, Call_Ent, Obj, Actuals, Formals);
Decls := New_List;
- Rewrite_Triggering_Statements;
Stmts := New_List;
@@ -12358,20 +12293,10 @@ package body Exp_Ch9 is
-- then
-- <dispatching-call>
-- end if;
- -- <triggering-statements>
- -- else
- -- <timed-statements>
-- end if;
- -- Note: we used to do Copy_Separate_List here, but this was changed
- -- to New_Copy_List_Tree with no explanation or RH note??? We should
- -- explain the need for the change ???
-
- N_Stats := New_Copy_List_Tree (E_Stats);
-
- Prepend_To (N_Stats,
+ N_Stats := New_List (
Make_Implicit_If_Statement (N,
-
Condition =>
Make_Or_Else (Loc,
Left_Opnd =>
@@ -12400,19 +12325,17 @@ package body Exp_Ch9 is
Append_To (Conc_Typ_Stmts,
Make_Implicit_If_Statement (N,
Condition => New_Reference_To (B, Loc),
- Then_Statements => N_Stats,
- Else_Statements => D_Stats));
+ Then_Statements => N_Stats));
-- Generate:
-- <dispatching-call>;
- -- <triggering-statements>
-
- -- Note: the following was Copy_Separate_List but it was changed to
- -- New_Copy_List_Tree without comments or RH documentation ??? We
- -- should explain the need for the change ???
+ -- B := True;
- Lim_Typ_Stmts := New_Copy_List_Tree (E_Stats);
- Prepend_To (Lim_Typ_Stmts, New_Copy_Tree (E_Call));
+ Lim_Typ_Stmts :=
+ New_List (New_Copy_Tree (E_Call),
+ Make_Assignment_Statement (Loc,
+ Name => New_Occurrence_Of (B, Loc),
+ Expression => New_Occurrence_Of (Standard_True, Loc)));
-- Generate:
-- if K = Ada.Tags.TK_Limited_Tagged
@@ -12429,8 +12352,24 @@ package body Exp_Ch9 is
Then_Statements => Lim_Typ_Stmts,
Else_Statements => Conc_Typ_Stmts));
+ -- Generate:
+
+ -- if B then
+ -- <triggering-statements>
+ -- else
+ -- <timed-statements>
+ -- end if;
+
+ Append_To (Stmts,
+ Make_Implicit_If_Statement (N,
+ Condition => New_Occurrence_Of (B, Loc),
+ Then_Statements => E_Stats,
+ Else_Statements => D_Stats));
+
else
- -- Skip assignments to temporaries created for in-out parameters.
+ -- Simple case of a non-dispatching trigger. Skip assignments to
+ -- temporaries created for in-out parameters.
+
-- This makes unwarranted assumptions about the shape of the expanded
-- tree for the call, and should be cleaned up ???
@@ -13095,7 +13034,6 @@ package body Exp_Ch9 is
if Has_Attach_Handler (Conc_Typ)
and then not Restricted_Profile
- and then not Restriction_Active (No_Dynamic_Attachment)
then
Prot_Typ := RE_Static_Interrupt_Protection;
@@ -13104,14 +13042,7 @@ package body Exp_Ch9 is
then
Prot_Typ := RE_Dynamic_Interrupt_Protection;
- -- The type has explicit entries or generated primitive entry
- -- wrappers.
-
- elsif Has_Entries (Conc_Typ)
- or else
- (Ada_Version >= Ada_2005
- and then Present (Interface_List (Parent (Conc_Typ))))
- then
+ else
case Corresponding_Runtime_Package (Conc_Typ) is
when System_Tasking_Protected_Objects_Entries =>
Prot_Typ := RE_Protection_Entries;
@@ -13119,12 +13050,12 @@ package body Exp_Ch9 is
when System_Tasking_Protected_Objects_Single_Entry =>
Prot_Typ := RE_Protection_Entry;
+ when System_Tasking_Protected_Objects =>
+ Prot_Typ := RE_Protection;
+
when others =>
raise Program_Error;
end case;
-
- else
- Prot_Typ := RE_Protection;
end if;
-- Generate:
@@ -13659,91 +13590,108 @@ package body Exp_Ch9 is
-- considered equivalent to a protected type with entries in the
-- context of dispatching select statements.
- if Has_Entry
- or else Has_Interfaces (Protect_Rec)
- or else
- ((Has_Attach_Handler (Ptyp) or else Has_Interrupt_Handler (Ptyp))
- and then not Restriction_Active (No_Dynamic_Attachment))
- then
- declare
- Pkg_Id : constant RTU_Id :=
- Corresponding_Runtime_Package (Ptyp);
+ -- Protected types with interrupt handlers (when not using a
+ -- restricted profile) are also considered equivalent to protected
+ -- types with entries.
- Called_Subp : RE_Id;
+ -- The types which are used (Static_Interrupt_Protection and
+ -- Dynamic_Interrupt_Protection) are derived from Protection_Entries.
- begin
- case Pkg_Id is
- when System_Tasking_Protected_Objects_Entries =>
- Called_Subp := RE_Initialize_Protection_Entries;
+ declare
+ Pkg_Id : constant RTU_Id := Corresponding_Runtime_Package (Ptyp);
- when System_Tasking_Protected_Objects =>
- Called_Subp := RE_Initialize_Protection;
+ Called_Subp : RE_Id;
- when System_Tasking_Protected_Objects_Single_Entry =>
- Called_Subp := RE_Initialize_Protection_Entry;
+ begin
+ case Pkg_Id is
+ when System_Tasking_Protected_Objects_Entries =>
+ Called_Subp := RE_Initialize_Protection_Entries;
- when others =>
- raise Program_Error;
- end case;
+ -- Argument Compiler_Info
- if Has_Entry
- or else not Restricted
- or else Has_Interfaces (Protect_Rec)
- then
Append_To (Args,
Make_Attribute_Reference (Loc,
Prefix => Make_Identifier (Loc, Name_uInit),
Attribute_Name => Name_Address));
- end if;
- -- Entry_Bodies parameter. This is a pointer to an array of
- -- pointers to the entry body procedures and barrier functions
- -- of the object. If the protected type has no entries this
- -- object will not exist, in this case, pass a null.
+ when System_Tasking_Protected_Objects_Single_Entry =>
+ Called_Subp := RE_Initialize_Protection_Entry;
- if Has_Entry then
- P_Arr := Entry_Bodies_Array (Ptyp);
+ -- Argument Compiler_Info
Append_To (Args,
Make_Attribute_Reference (Loc,
- Prefix => New_Reference_To (P_Arr, Loc),
- Attribute_Name => Name_Unrestricted_Access));
+ Prefix => Make_Identifier (Loc, Name_uInit),
+ Attribute_Name => Name_Address));
+
+ when System_Tasking_Protected_Objects =>
+ Called_Subp := RE_Initialize_Protection;
+
+ when others =>
+ raise Program_Error;
+ end case;
- if Pkg_Id = System_Tasking_Protected_Objects_Entries then
+ -- Entry_Bodies parameter. This is a pointer to an array of
+ -- pointers to the entry body procedures and barrier functions of
+ -- the object. If the protected type has no entries this object
+ -- will not exist, in this case, pass a null (it can happen when
+ -- there are protected interrupt handlers or interfaces).
- -- Find index mapping function (clumsy but ok for now)
+ if Has_Entry then
+ P_Arr := Entry_Bodies_Array (Ptyp);
- while Ekind (P_Arr) /= E_Function loop
- Next_Entity (P_Arr);
- end loop;
+ -- Argument Entry_Body (for single entry) or Entry_Bodies (for
+ -- multiple entries).
- Append_To (Args,
- Make_Attribute_Reference (Loc,
- Prefix => New_Reference_To (P_Arr, Loc),
- Attribute_Name => Name_Unrestricted_Access));
- end if;
+ Append_To (Args,
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Reference_To (P_Arr, Loc),
+ Attribute_Name => Name_Unrestricted_Access));
- elsif Pkg_Id =
- System_Tasking_Protected_Objects_Single_Entry
- then
- Append_To (Args, Make_Null (Loc));
+ if Pkg_Id = System_Tasking_Protected_Objects_Entries then
+
+ -- Find index mapping function (clumsy but ok for now)
+
+ while Ekind (P_Arr) /= E_Function loop
+ Next_Entity (P_Arr);
+ end loop;
- elsif Pkg_Id = System_Tasking_Protected_Objects_Entries then
- Append_To (Args, Make_Null (Loc));
- Append_To (Args, Make_Null (Loc));
+ Append_To (Args,
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Reference_To (P_Arr, Loc),
+ Attribute_Name => Name_Unrestricted_Access));
end if;
- Append_To (L,
- Make_Procedure_Call_Statement (Loc,
- Name => New_Reference_To (RTE (Called_Subp), Loc),
- Parameter_Associations => Args));
- end;
- else
+ elsif Pkg_Id = System_Tasking_Protected_Objects_Single_Entry then
+
+ -- This is the case where we have a protected object with
+ -- interfaces and no entries, and the single entry restriction
+ -- is in effect. We pass a null pointer for the entry
+ -- parameter because there is no actual entry.
+
+ Append_To (Args, Make_Null (Loc));
+
+ elsif Pkg_Id = System_Tasking_Protected_Objects_Entries then
+
+ -- This is the case where we have a protected object with no
+ -- entries and:
+ -- - either interrupt handlers with non restricted profile,
+ -- - or interfaces
+ -- Note that the types which are used for interrupt handlers
+ -- (Static/Dynamic_Interrupt_Protection) are derived from
+ -- Protection_Entries. We pass two null pointers because there
+ -- is no actual entry, and the initialization procedure needs
+ -- both Entry_Bodies and Find_Body_Index.
+
+ Append_To (Args, Make_Null (Loc));
+ Append_To (Args, Make_Null (Loc));
+ end if;
+
Append_To (L,
Make_Procedure_Call_Statement (Loc,
- Name => New_Reference_To (RTE (RE_Initialize_Protection), Loc),
+ Name => New_Reference_To (RTE (Called_Subp), Loc),
Parameter_Associations => Args));
- end if;
+ end;
end if;
if Has_Attach_Handler (Ptyp) then
diff --git a/gcc/ada/exp_dbug.adb b/gcc/ada/exp_dbug.adb
index cc5ff4fc8fb..7dd72069aca 100644
--- a/gcc/ada/exp_dbug.adb
+++ b/gcc/ada/exp_dbug.adb
@@ -411,7 +411,6 @@ package body Exp_Dbug is
Ren := Prefix (Ren);
when N_Explicit_Dereference =>
- Set_Materialize_Entity (Ent);
Prepend_String_To_Buffer ("XA");
Ren := Prefix (Ren);
diff --git a/gcc/ada/exp_disp.adb b/gcc/ada/exp_disp.adb
index 7490e9df7bf..8ba4704328a 100644
--- a/gcc/ada/exp_disp.adb
+++ b/gcc/ada/exp_disp.adb
@@ -1568,7 +1568,7 @@ package body Exp_Disp is
else
Actual_Dup := Relocate_Node (Actual);
- if From_With_Type (Actual_Typ) then
+ if From_Limited_With (Actual_Typ) then
-- If the type of the actual parameter comes from a limited
-- with-clause and the non-limited view is already available
@@ -1983,7 +1983,7 @@ package body Exp_Disp is
begin
if Ekind (Typ) = E_Incomplete_Type then
- if From_With_Type (Typ) then
+ if From_Limited_With (Typ) then
Typ := Non_Limited_View (Typ);
else
Typ := Full_View (Typ);
@@ -7645,7 +7645,7 @@ package body Exp_Disp is
end if;
return List_Containing (Parent (Typ)) =
- Visible_Declarations (Specification (Unit_Declaration_Node (Scop)));
+ Visible_Declarations (Package_Specification (Scop));
end Original_View_In_Visible_Part;
------------------
@@ -8446,8 +8446,7 @@ package body Exp_Disp is
and then In_Private_Part (Current_Scope)
and then
List_Containing (Parent (Prim)) =
- Private_Declarations
- (Specification (Unit_Declaration_Node (Current_Scope)))
+ Private_Declarations (Package_Specification (Current_Scope))
and then Original_View_In_Visible_Part (Typ)
then
-- We exclude Input and Output stream operations because
diff --git a/gcc/ada/exp_dist.adb b/gcc/ada/exp_dist.adb
index 364330339fe..068a950ba11 100644
--- a/gcc/ada/exp_dist.adb
+++ b/gcc/ada/exp_dist.adb
@@ -2874,8 +2874,7 @@ package body Exp_Dist is
if RCI_Locator = Empty then
RCI_Locator_Decl :=
- RCI_Package_Locator
- (Loc, Specification (Unit_Declaration_Node (RCI_Package)));
+ RCI_Package_Locator (Loc, Package_Specification (RCI_Package));
Prepend_To (Current_Sem_Unit_Declarations, RCI_Locator_Decl);
Analyze (RCI_Locator_Decl);
RCI_Locator := Defining_Unit_Name (RCI_Locator_Decl);
@@ -9839,7 +9838,8 @@ package body Exp_Dist is
-- Constrained and unconstrained array types
declare
- Constrained : constant Boolean := Is_Constrained (Typ);
+ Constrained : constant Boolean :=
+ not Transmit_As_Unconstrained (Typ);
procedure TA_Ary_Add_Process_Element
(Stmts : List_Id;
@@ -9958,16 +9958,29 @@ package body Exp_Dist is
-- Generate:
-- T'Output (Strm'Access, E);
+ -- or
+ -- T'Write (Strm'Access, E);
+ -- depending on whether to transmit as unconstrained
- Append_To (Stms,
- Make_Attribute_Reference (Loc,
- Prefix => New_Occurrence_Of (Typ, Loc),
- Attribute_Name => Name_Output,
- Expressions => New_List (
- Make_Attribute_Reference (Loc,
- Prefix => New_Occurrence_Of (Strm, Loc),
- Attribute_Name => Name_Access),
- New_Occurrence_Of (Expr_Parameter, Loc))));
+ declare
+ Attr_Name : Name_Id;
+ begin
+ if Transmit_As_Unconstrained (Typ) then
+ Attr_Name := Name_Output;
+ else
+ Attr_Name := Name_Write;
+ end if;
+
+ Append_To (Stms,
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Occurrence_Of (Typ, Loc),
+ Attribute_Name => Attr_Name,
+ Expressions => New_List (
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Occurrence_Of (Strm, Loc),
+ Attribute_Name => Name_Access),
+ New_Occurrence_Of (Expr_Parameter, Loc))));
+ end;
-- Generate:
-- BS_To_Any (Strm, A);
diff --git a/gcc/ada/exp_pakd.adb b/gcc/ada/exp_pakd.adb
index 0d9ed4ee19d..0baab98d9cd 100644
--- a/gcc/ada/exp_pakd.adb
+++ b/gcc/ada/exp_pakd.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2012, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -543,39 +543,78 @@ package body Exp_Pakd is
-- array type on the fly). Such actions are inserted into the tree
-- directly using Insert_Action.
- function Byte_Swap (N : Node_Id) return Node_Id;
+ function Byte_Swap
+ (N : Node_Id;
+ Left_Justify : Boolean := False;
+ Right_Justify : Boolean := False) return Node_Id;
-- Wrap N in a call to a byte swapping function, with appropriate type
- -- conversions.
+ -- conversions. If Left_Justify is set True, the value is left justified
+ -- before swapping. If Right_Justify is set True, the value is right
+ -- justified after swapping. The Etype of the returned node is an
+ -- integer type of an appropriate power-of-2 size.
---------------
-- Byte_Swap --
---------------
- function Byte_Swap (N : Node_Id) return Node_Id is
+ function Byte_Swap
+ (N : Node_Id;
+ Left_Justify : Boolean := False;
+ Right_Justify : Boolean := False) return Node_Id
+ is
Loc : constant Source_Ptr := Sloc (N);
T : constant Entity_Id := Etype (N);
+ T_Size : constant Uint := RM_Size (T);
+
Swap_RE : RE_Id;
Swap_F : Entity_Id;
+ Swap_T : Entity_Id;
+ -- Swapping function
+
+ Arg : Node_Id;
+ Swapped : Node_Id;
+ Shift : Uint;
begin
- pragma Assert (Esize (T) > 8);
+ pragma Assert (T_Size > 8);
- if Esize (T) <= 16 then
+ if T_Size <= 16 then
Swap_RE := RE_Bswap_16;
- elsif Esize (T) <= 32 then
+
+ elsif T_Size <= 32 then
Swap_RE := RE_Bswap_32;
- else pragma Assert (Esize (T) <= 64);
+
+ else pragma Assert (T_Size <= 64);
Swap_RE := RE_Bswap_64;
end if;
Swap_F := RTE (Swap_RE);
+ Swap_T := Etype (Swap_F);
+ Shift := Esize (Swap_T) - T_Size;
+
+ Arg := RJ_Unchecked_Convert_To (Swap_T, N);
+
+ if Left_Justify and then Shift > Uint_0 then
+ Arg :=
+ Make_Op_Shift_Left (Loc,
+ Left_Opnd => Arg,
+ Right_Opnd => Make_Integer_Literal (Loc, Shift));
+ end if;
+
+ Swapped :=
+ Make_Function_Call (Loc,
+ Name => New_Occurrence_Of (Swap_F, Loc),
+ Parameter_Associations => New_List (Arg));
+
+ if Right_Justify and then Shift > Uint_0 then
+ Swapped :=
+ Make_Op_Shift_Right (Loc,
+ Left_Opnd => Swapped,
+ Right_Opnd => Make_Integer_Literal (Loc, Shift));
+ end if;
- return
- Unchecked_Convert_To (T,
- Make_Function_Call (Loc,
- Name => New_Occurrence_Of (Swap_F, Loc),
- Parameter_Associations =>
- New_List (Unchecked_Convert_To (Etype (Swap_F), N))));
+ Set_Etype (Swapped, Swap_T);
+ return Swapped;
end Byte_Swap;
------------------------------
@@ -1326,8 +1365,8 @@ package body Exp_Pakd is
-- The expression for the shift value that is required
Shift_Used : Boolean := False;
- -- Set True if Shift has been used in the generated code at least
- -- once, so that it must be duplicated if used again
+ -- Set True if Shift has been used in the generated code at least once,
+ -- so that it must be duplicated if used again.
New_Lhs : Node_Id;
New_Rhs : Node_Id;
@@ -1537,7 +1576,9 @@ package body Exp_Pakd is
and then not In_Reverse_Storage_Order_Object (Obj)
then
Require_Byte_Swapping := True;
- New_Rhs := Byte_Swap (New_Rhs);
+ New_Rhs := Byte_Swap (New_Rhs,
+ Left_Justify => Bytes_Big_Endian,
+ Right_Justify => not Bytes_Big_Endian);
end if;
end;
@@ -1610,7 +1651,6 @@ package body Exp_Pakd is
-- not a left justified conversion.
Rhs := RJ_Unchecked_Convert_To (Etype (Obj), Rhs);
-
end Fixup_Rhs;
begin
@@ -1660,6 +1700,14 @@ package body Exp_Pakd is
if Nkind (New_Rhs) = N_Op_And then
Set_Paren_Count (New_Rhs, 1);
+ Set_Etype (New_Rhs, Etype (Left_Opnd (New_Rhs)));
+ end if;
+
+ -- If New_Rhs has been byte swapped, need to convert Or_Rhs
+ -- to the return type of the byte swapping function now.
+
+ if Require_Byte_Swapping then
+ Or_Rhs := Unchecked_Convert_To (Etype (New_Rhs), Or_Rhs);
end if;
New_Rhs :=
@@ -1671,7 +1719,11 @@ package body Exp_Pakd is
if Require_Byte_Swapping then
Set_Etype (New_Rhs, Etype (Obj));
- New_Rhs := Byte_Swap (New_Rhs);
+ New_Rhs :=
+ Unchecked_Convert_To (Etype (Obj),
+ Byte_Swap (New_Rhs,
+ Left_Justify => not Bytes_Big_Endian,
+ Right_Justify => Bytes_Big_Endian));
end if;
-- Now do the rewrite
@@ -1991,7 +2043,25 @@ package body Exp_Pakd is
Lit : Node_Id;
Arg : Node_Id;
+ Byte_Swapped : Boolean;
+ -- Set true if bytes were swapped for the purpose of extracting the
+ -- element, in which case we must swap back if the component type is
+ -- a composite type with reverse scalar storage order.
+
begin
+ -- If the node is an actual in a call, the prefix has not been fully
+ -- expanded, to account for the additional expansion for in-out actuals
+ -- (see expand_actuals for details). If the prefix itself is a packed
+ -- reference as well, we have to recurse to complete the transformation
+ -- of the prefix.
+
+ if Nkind (Prefix (N)) = N_Indexed_Component
+ and then not Analyzed (Prefix (N))
+ and then Is_Bit_Packed_Array (Etype (Prefix (Prefix (N))))
+ then
+ Expand_Packed_Element_Reference (Prefix (N));
+ end if;
+
-- If not bit packed, we have the enumeration case, which is easily
-- dealt with (just adjust the subscripts of the indexed component)
@@ -2044,7 +2114,13 @@ package body Exp_Pakd is
and then Esize (Atyp) > 8
and then not In_Reverse_Storage_Order_Object (Obj)
then
- Obj := Byte_Swap (Obj);
+ Obj := Byte_Swap (Obj,
+ Left_Justify => Bytes_Big_Endian,
+ Right_Justify => not Bytes_Big_Endian);
+ Byte_Swapped := True;
+
+ else
+ Byte_Swapped := False;
end if;
-- We generate a shift right to position the field, followed by a
@@ -2062,6 +2138,21 @@ package body Exp_Pakd is
Left_Opnd => Make_Shift_Right (Obj, Shift),
Right_Opnd => Lit);
+ -- Swap back if necessary
+
+ Set_Etype (Arg, Ctyp);
+
+ if Byte_Swapped
+ and then (Is_Record_Type (Ctyp) or else Is_Array_Type (Ctyp))
+ and then Reverse_Storage_Order (Ctyp)
+ then
+ Arg :=
+ Byte_Swap
+ (Arg,
+ Left_Justify => not Bytes_Big_Endian,
+ Right_Justify => False);
+ end if;
+
-- We needed to analyze this before we do the unchecked convert
-- below, but we need it temporarily attached to the tree for
-- this analysis (hence the temporary Set_Parent call).
@@ -2584,6 +2675,18 @@ package body Exp_Pakd is
Source_Siz := UI_To_Int (RM_Size (Source_Typ));
Target_Siz := UI_To_Int (RM_Size (Target_Typ));
+ -- For a little-endian target type stored byte-swapped on a
+ -- big-endian machine, do not mask to Target_Siz bits.
+
+ if Bytes_Big_Endian
+ and then (Is_Record_Type (Target_Typ)
+ or else
+ Is_Array_Type (Target_Typ))
+ and then Reverse_Storage_Order (Target_Typ)
+ then
+ Source_Siz := Target_Siz;
+ end if;
+
-- First step, if the source type is not a discrete type, then we first
-- convert to a modular type of the source length, since otherwise, on
-- a big-endian machine, we get left-justification. We do it for little-
diff --git a/gcc/ada/exp_prag.adb b/gcc/ada/exp_prag.adb
index eeafa72d356..693aac9b35f 100644
--- a/gcc/ada/exp_prag.adb
+++ b/gcc/ada/exp_prag.adb
@@ -311,6 +311,10 @@ package body Exp_Prag is
-- at" is omitted for name = Assertion, since it is redundant, given
-- that the name of the exception is Assert_Failure.)
+ -- Also, instead of "XXX failed at", we generate slightly
+ -- different messages for some of the contract assertions (see
+ -- code below for details).
+
-- An alternative expansion is used when the No_Exception_Propagation
-- restriction is active and there is a local Assert_Failure handler.
-- This is not a common combination of circumstances, but it occurs in
@@ -400,6 +404,15 @@ package body Exp_Prag is
Insert_Str_In_Name_Buffer ("failed ", 1);
Add_Str_To_Name_Buffer (" from ");
+ -- For special case of Invariant, the string is "failed
+ -- invariant from yy", to be consistent with the string that is
+ -- generated for the aspect case (the code later on checks for
+ -- this specific string to modify it in some cases, so this is
+ -- functionally important).
+
+ elsif Nam = Name_Invariant then
+ Add_Str_To_Name_Buffer ("failed invariant from ");
+
-- For all other checks, the string is "xxx failed at yyy"
-- where xxx is the check name with current source file casing.
@@ -530,30 +543,34 @@ package body Exp_Prag is
-- Expand_Pragma_Import_Or_Interface --
---------------------------------------
- -- When applied to a variable, the default initialization must not be done.
- -- As it is already done when the pragma is found, we just get rid of the
- -- call the initialization procedure which followed the object declaration.
- -- The call is inserted after the declaration, but validity checks may
- -- also have been inserted and the initialization call does not necessarily
- -- appear immediately after the object declaration.
-
- -- We can't use the freezing mechanism for this purpose, since we have to
- -- elaborate the initialization expression when it is first seen (i.e. this
- -- elaboration cannot be deferred to the freeze point).
-
procedure Expand_Pragma_Import_Or_Interface (N : Node_Id) is
Def_Id : Entity_Id;
Init_Call : Node_Id;
begin
Def_Id := Entity (Arg2 (N));
+
+ -- Variable case
+
if Ekind (Def_Id) = E_Variable then
+ -- When applied to a variable, the default initialization must not be
+ -- done. As it is already done when the pragma is found, we just get
+ -- rid of the call the initialization procedure which followed the
+ -- object declaration. The call is inserted after the declaration,
+ -- but validity checks may also have been inserted and thus the
+ -- initialization call does not necessarily appear immediately
+ -- after the object declaration.
+
+ -- We can't use the freezing mechanism for this purpose, since we
+ -- have to elaborate the initialization expression when it is first
+ -- seen (so this elaboration cannot be deferred to the freeze point).
+
-- Find and remove generated initialization call for object, if any
Init_Call := Remove_Init_Call (Def_Id, Rep_Clause => N);
- -- Any default initialization expression should be removed (e.g.,
+ -- Any default initialization expression should be removed (e.g.
-- null defaults for access objects, zero initialization of packed
-- bit arrays). Imported objects aren't allowed to have explicit
-- initialization, so the expression must have been generated by
@@ -562,6 +579,71 @@ package body Exp_Prag is
if No (Init_Call) and then Present (Expression (Parent (Def_Id))) then
Set_Expression (Parent (Def_Id), Empty);
end if;
+
+ -- Case of exception with convention C++
+
+ elsif Ekind (Def_Id) = E_Exception
+ and then Convention (Def_Id) = Convention_CPP
+ then
+ -- Import a C++ convention
+
+ declare
+ Loc : constant Source_Ptr := Sloc (N);
+ Rtti_Name : constant Node_Id := Arg3 (N);
+ Dum : constant Entity_Id := Make_Temporary (Loc, 'D');
+ Exdata : List_Id;
+ Lang_Char : Node_Id;
+ Foreign_Data : Node_Id;
+
+ begin
+ Exdata := Component_Associations (Expression (Parent (Def_Id)));
+
+ Lang_Char := Next (First (Exdata));
+
+ -- Change the one-character language designator to 'C'
+
+ Rewrite (Expression (Lang_Char),
+ Make_Character_Literal (Loc,
+ Chars => Name_uC,
+ Char_Literal_Value => UI_From_Int (Character'Pos ('C'))));
+ Analyze (Expression (Lang_Char));
+
+ -- Change the value of Foreign_Data
+
+ Foreign_Data := Next (Next (Next (Next (Lang_Char))));
+
+ Insert_Actions (Def_Id, New_List (
+ Make_Object_Declaration (Loc,
+ Defining_Identifier => Dum,
+ Object_Definition =>
+ New_Occurrence_Of (Standard_Character, Loc)),
+
+ Make_Pragma (Loc,
+ Chars => Name_Import,
+ Pragma_Argument_Associations => New_List (
+ Make_Pragma_Argument_Association (Loc,
+ Expression => Make_Identifier (Loc, Name_Ada)),
+
+ Make_Pragma_Argument_Association (Loc,
+ Expression => Make_Identifier (Loc, Chars (Dum))),
+
+ Make_Pragma_Argument_Association (Loc,
+ Chars => Name_External_Name,
+ Expression => Relocate_Node (Rtti_Name))))));
+
+ Rewrite (Expression (Foreign_Data),
+ Unchecked_Convert_To (Standard_A_Char,
+ Make_Attribute_Reference (Loc,
+ Prefix => Make_Identifier (Loc, Chars (Dum)),
+ Attribute_Name => Name_Address)));
+ Analyze (Expression (Foreign_Data));
+ end;
+
+ -- No special expansion required for any other case
+
+ else
+ null;
+
end if;
end Expand_Pragma_Import_Or_Interface;
@@ -603,6 +685,8 @@ package body Exp_Prag is
Code : Node_Id;
begin
+ -- Compute the symbol for the code of the condition
+
if Present (Interface_Name (Id)) then
Excep_Image := Strval (Interface_Name (Id));
else
@@ -626,23 +710,35 @@ package body Exp_Prag is
Analyze (Expression (Lang_Char));
if Exception_Code (Id) /= No_Uint then
+
+ -- The code for the exception is present. Create a linker
+ -- alias to define the symbol.
+
Code :=
- Make_Integer_Literal (Loc,
- Intval => Exception_Code (Id));
+ Unchecked_Convert_To (RTE (RE_Address),
+ Make_Integer_Literal (Loc,
+ Intval => Exception_Code (Id)));
+
+ -- Declare a dummy object
Excep_Object :=
Make_Object_Declaration (Loc,
Defining_Identifier => Excep_Internal,
Object_Definition =>
- New_Reference_To (RTE (RE_Exception_Code), Loc));
+ New_Reference_To (RTE (RE_Address), Loc));
Insert_Action (N, Excep_Object);
Analyze (Excep_Object);
+ -- Clear severity bits
+
Start_String;
Store_String_Int
(UI_To_Int (Exception_Code (Id)) / 8 * 8);
+ -- Insert a pragma Linker_Alias to set the value of the
+ -- dummy object symbol.
+
Excep_Alias :=
Make_Pragma (Loc,
Chars => Name_Linker_Alias,
@@ -658,6 +754,9 @@ package body Exp_Prag is
Insert_Action (N, Excep_Alias);
Analyze (Excep_Alias);
+ -- Insert a pragma Export to give a Linker_Name to the
+ -- dummy object.
+
Export_Pragma :=
Make_Pragma (Loc,
Chars => Name_Export,
@@ -682,15 +781,16 @@ package body Exp_Prag is
else
Code :=
- Unchecked_Convert_To (RTE (RE_Exception_Code),
- Make_Function_Call (Loc,
- Name =>
- New_Reference_To (RTE (RE_Import_Value), Loc),
- Parameter_Associations => New_List
- (Make_String_Literal (Loc,
- Strval => Excep_Image))));
+ Make_Function_Call (Loc,
+ Name =>
+ New_Reference_To (RTE (RE_Import_Address), Loc),
+ Parameter_Associations => New_List
+ (Make_String_Literal (Loc,
+ Strval => Excep_Image)));
end if;
+ -- Generate the call to Register_VMS_Exception
+
Rewrite (Call,
Make_Procedure_Call_Statement (Loc,
Name => New_Reference_To
@@ -702,7 +802,7 @@ package body Exp_Prag is
Prefix => New_Occurrence_Of (Id, Loc),
Attribute_Name => Name_Unrestricted_Access)))));
- Analyze_And_Resolve (Code, RTE (RE_Exception_Code));
+ Analyze_And_Resolve (Code, RTE (RE_Address));
Analyze (Call);
end if;
diff --git a/gcc/ada/exp_spark.adb b/gcc/ada/exp_spark.adb
index 0050799a104..a4415e837e7 100644
--- a/gcc/ada/exp_spark.adb
+++ b/gcc/ada/exp_spark.adb
@@ -25,19 +25,13 @@
with Atree; use Atree;
with Einfo; use Einfo;
-with Exp_Attr; use Exp_Attr;
-with Exp_Ch4; use Exp_Ch4;
-with Exp_Ch6; use Exp_Ch6;
with Exp_Dbug; use Exp_Dbug;
with Exp_Util; use Exp_Util;
-with Rtsfind; use Rtsfind;
with Sem_Aux; use Sem_Aux;
with Sem_Res; use Sem_Res;
with Sem_Util; use Sem_Util;
with Sinfo; use Sinfo;
-with Snames; use Snames;
with Stand; use Stand;
-with Tbuild; use Tbuild;
package body Exp_SPARK is
@@ -47,22 +41,11 @@ package body Exp_SPARK is
procedure Expand_SPARK_Call (N : Node_Id);
-- This procedure contains common processing for function and procedure
- -- calls:
- -- * expansion of actuals to introduce necessary temporaries
- -- * replacement of renaming by subprogram renamed
-
- procedure Expand_SPARK_N_Attribute_Reference (N : Node_Id);
- -- Expand attributes 'Old and 'Result only
+ -- calls: replacement of renaming by subprogram renamed
procedure Expand_SPARK_N_Object_Renaming_Declaration (N : Node_Id);
-- Perform name evaluation for a renamed object
- procedure Expand_SPARK_N_Simple_Return_Statement (N : Node_Id);
- -- Insert conversion on function return if necessary
-
- procedure Expand_SPARK_Simple_Function_Return (N : Node_Id);
- -- Expand simple return from function
-
procedure Expand_Potential_Renaming (N : Node_Id);
-- N denotes a N_Identifier or N_Expanded_Name. If N references a renaming,
-- replace N with the renamed object.
@@ -74,8 +57,6 @@ package body Exp_SPARK is
procedure Expand_SPARK (N : Node_Id) is
begin
case Nkind (N) is
- when N_Attribute_Reference =>
- Expand_SPARK_N_Attribute_Reference (N);
-- Qualification of entity names in formal verification mode
-- is limited to the addition of a suffix for homonyms (see
@@ -98,18 +79,9 @@ package body Exp_SPARK is
N_Identifier =>
Expand_Potential_Renaming (N);
- -- A NOT IN B gets transformed to NOT (A IN B). This is the same
- -- expansion used in the normal case, so shared the code.
-
- when N_Not_In =>
- Expand_N_Not_In (N);
-
when N_Object_Renaming_Declaration =>
Expand_SPARK_N_Object_Renaming_Declaration (N);
- when N_Simple_Return_Statement =>
- Expand_SPARK_N_Simple_Return_Statement (N);
-
-- In SPARK mode, no other constructs require expansion
when others =>
@@ -124,7 +96,6 @@ package body Exp_SPARK is
procedure Expand_SPARK_Call (N : Node_Id) is
Call_Node : constant Node_Id := N;
Parent_Subp : Entity_Id;
- Subp : Entity_Id;
begin
-- Ignore if previous error
@@ -138,14 +109,12 @@ package body Exp_SPARK is
-- Call using access to subprogram with explicit dereference
if Nkind (Name (Call_Node)) = N_Explicit_Dereference then
- Subp := Etype (Name (Call_Node));
Parent_Subp := Empty;
-- Case of call to simple entry, where the Name is a selected component
-- whose prefix is the task, and whose selector name is the entry name
elsif Nkind (Name (Call_Node)) = N_Selected_Component then
- Subp := Entity (Selector_Name (Name (Call_Node)));
Parent_Subp := Empty;
-- Case of call to member of entry family, where Name is an indexed
@@ -153,20 +122,14 @@ package body Exp_SPARK is
-- task and entry family name, and the index being the entry index.
elsif Nkind (Name (Call_Node)) = N_Indexed_Component then
- Subp := Entity (Selector_Name (Prefix (Name (Call_Node))));
Parent_Subp := Empty;
-- Normal case
else
- Subp := Entity (Name (Call_Node));
- Parent_Subp := Alias (Subp);
+ Parent_Subp := Alias (Entity (Name (Call_Node)));
end if;
- -- Various expansion activities for actuals are carried out
-
- Expand_Actuals (N, Subp);
-
-- If the subprogram is a renaming, replace it in the call with the name
-- of the actual subprogram being called.
@@ -179,24 +142,6 @@ package body Exp_SPARK is
end if;
end Expand_SPARK_Call;
- ----------------------------------------
- -- Expand_SPARK_N_Attribute_Reference --
- ----------------------------------------
-
- procedure Expand_SPARK_N_Attribute_Reference (N : Node_Id) is
- Id : constant Attribute_Id := Get_Attribute_Id (Attribute_Name (N));
-
- begin
- case Id is
- when Attribute_Old |
- Attribute_Result =>
- Expand_N_Attribute_Reference (N);
-
- when others =>
- null;
- end case;
- end Expand_SPARK_N_Attribute_Reference;
-
------------------------------------------------
-- Expand_SPARK_N_Object_Renaming_Declaration --
------------------------------------------------
@@ -208,80 +153,6 @@ package body Exp_SPARK is
Evaluate_Name (Name (N));
end Expand_SPARK_N_Object_Renaming_Declaration;
- --------------------------------------------
- -- Expand_SPARK_N_Simple_Return_Statement --
- --------------------------------------------
-
- procedure Expand_SPARK_N_Simple_Return_Statement (N : Node_Id) is
- begin
- -- Defend against previous errors (i.e. the return statement calls a
- -- function that is not available in configurable runtime).
-
- if Present (Expression (N))
- and then Nkind (Expression (N)) = N_Empty
- then
- return;
- end if;
-
- -- Distinguish the function and non-function cases:
-
- case Ekind (Return_Applies_To (Return_Statement_Entity (N))) is
-
- when E_Function |
- E_Generic_Function =>
- Expand_SPARK_Simple_Function_Return (N);
-
- when E_Procedure |
- E_Generic_Procedure |
- E_Entry |
- E_Entry_Family |
- E_Return_Statement =>
- null;
-
- when others =>
- raise Program_Error;
- end case;
-
- exception
- when RE_Not_Available =>
- return;
- end Expand_SPARK_N_Simple_Return_Statement;
-
- -----------------------------------------
- -- Expand_SPARK_Simple_Function_Return --
- -----------------------------------------
-
- procedure Expand_SPARK_Simple_Function_Return (N : Node_Id) is
- Scope_Id : constant Entity_Id :=
- Return_Applies_To (Return_Statement_Entity (N));
- -- The function we are returning from
-
- R_Type : constant Entity_Id := Etype (Scope_Id);
- -- The result type of the function
-
- Exp : constant Node_Id := Expression (N);
- pragma Assert (Present (Exp));
-
- Exptyp : constant Entity_Id := Etype (Exp);
- -- The type of the expression (not necessarily the same as R_Type)
-
- begin
- -- Check the result expression of a scalar function against the subtype
- -- of the function by inserting a conversion. This conversion must
- -- eventually be performed for other classes of types, but for now it's
- -- only done for scalars.
- -- ???
-
- if Is_Scalar_Type (Exptyp) then
- Rewrite (Exp, Convert_To (R_Type, Exp));
-
- -- The expression is resolved to ensure that the conversion gets
- -- expanded to generate a possible constraint check.
-
- Analyze_And_Resolve (Exp, R_Type);
- end if;
- end Expand_SPARK_Simple_Function_Return;
-
-------------------------------
-- Expand_Potential_Renaming --
-------------------------------
diff --git a/gcc/ada/exp_spark.ads b/gcc/ada/exp_spark.ads
index 726b69ac014..c422bc73e52 100644
--- a/gcc/ada/exp_spark.ads
+++ b/gcc/ada/exp_spark.ads
@@ -30,54 +30,6 @@
-- Expand_SPARK is called directly by Expander.Expand.
--- SPARK expansion has three main objectives:
-
--- 1. Perform limited expansion to explicit some Ada rules and constructs
--- (translate 'Old and 'Result, replace renamings by renamed, insert
--- conversions, expand actuals in calls to introduce temporaries, expand
--- generics instantiations)
-
--- 2. Facilitate treatment for the formal verification back-end (fully
--- qualify names, expand set membership, compute data dependences)
-
--- 3. Avoid the introduction of low-level code that is difficult to analyze
--- formally, as typically done in the full expansion for high-level
--- constructs (tasking, dispatching)
-
--- To fulfill objective 1, Expand_SPARK selectively expands some constructs.
-
--- To fulfill objective 2, the tree after SPARK expansion should be fully
--- analyzed semantically. In particular, all expression must have their proper
--- type, and semantic links should be set between tree nodes (partial to full
--- view, etc.) Some kinds of nodes should be either absent, or can be ignored
--- by the formal verification backend:
-
--- N_Object_Renaming_Declaration: can be ignored safely
--- N_Expression_Function: absent (rewitten)
--- N_Expression_With_Actions: absent (not generated)
-
--- SPARK cross-references are generated from the regular cross-references
--- (used for browsing and code understanding) and additional references
--- collected during semantic analysis, in particular on all
--- dereferences. These SPARK cross-references are output in a separate section
--- of ALI files, as described in spark_xrefs.adb. They are the basis for the
--- computation of data dependences in the formal verification backend. This
--- implies that all cross-references should be generated in this mode, even
--- those that would not make sense from a user point-of-view, and that
--- cross-references that do not lead to data dependences for subprograms can
--- be safely ignored.
-
--- To support the formal verification of units parameterized by data, the
--- value of deferred constants should not be considered as a compile-time
--- constant at program locations where the full view is not visible.
-
--- To fulfill objective 3, Expand_SPARK does not expand features that are not
--- formally analyzed (tasking), or for which formal analysis relies on the
--- source level representation (dispatching, aspects, pragmas). However, these
--- should be semantically analyzed, which sometimes requires the insertion of
--- semantic pre-analysis, for example for subprogram contracts and pragma
--- check/assert.
-
with Types; use Types;
package Exp_SPARK is
diff --git a/gcc/ada/exp_tss.adb b/gcc/ada/exp_tss.adb
index 8b19f9190db..2b6dc92d315 100644
--- a/gcc/ada/exp_tss.adb
+++ b/gcc/ada/exp_tss.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2010, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -211,7 +211,7 @@ package body Exp_Tss is
begin
return Present (BIP)
and then (Restriction_Active (No_Default_Initialization)
- or else not Is_Null_Init_Proc (BIP));
+ or else not Is_Null_Init_Proc (BIP));
end Has_Non_Null_Base_Init_Proc;
---------------
diff --git a/gcc/ada/exp_util.adb b/gcc/ada/exp_util.adb
index ca8bc9839ab..a14b1bc1e19 100644
--- a/gcc/ada/exp_util.adb
+++ b/gcc/ada/exp_util.adb
@@ -560,13 +560,6 @@ package body Exp_Util is
-- Start of processing for Build_Allocate_Deallocate_Proc
begin
- -- Do not perform this expansion in SPARK mode because it is not
- -- necessary.
-
- if SPARK_Mode then
- return;
- end if;
-
-- Obtain the attributes of the allocation / deallocation
if Nkind (N) = N_Free_Statement then
@@ -1631,10 +1624,15 @@ package body Exp_Util is
-- node to recognize this case.
or else Present (Interface_List (Parent (Typ)))
- or else
- (((Has_Attach_Handler (Typ) and then not Restricted_Profile)
- or else Has_Interrupt_Handler (Typ))
- and then not Restriction_Active (No_Dynamic_Attachment))
+
+ -- Protected types with interrupt handlers (when not using a
+ -- restricted profile) are also considered equivalent to
+ -- protected types with entries. The types which are used
+ -- (Static_Interrupt_Protection and Dynamic_Interrupt_Protection)
+ -- are derived from Protection_Entries.
+
+ or else (Has_Attach_Handler (Typ) and then not Restricted_Profile)
+ or else Has_Interrupt_Handler (Typ)
then
if Abort_Allowed
or else Restriction_Active (No_Entry_Queue) = False
@@ -1773,35 +1771,6 @@ package body Exp_Util is
end if;
end Ensure_Defined;
- ---------------
- -- Entity_Of --
- ---------------
-
- function Entity_Of (N : Node_Id) return Entity_Id is
- Id : Entity_Id;
-
- begin
- Id := Empty;
-
- if Is_Entity_Name (N) then
- Id := Entity (N);
-
- -- Follow a possible chain of renamings to reach the root renamed
- -- object.
-
- while Present (Renamed_Object (Id)) loop
- if Is_Entity_Name (Renamed_Object (Id)) then
- Id := Entity (Renamed_Object (Id));
- else
- Id := Empty;
- exit;
- end if;
- end loop;
- end if;
-
- return Id;
- end Entity_Of;
-
--------------------
-- Entry_Names_OK --
--------------------
@@ -1941,6 +1910,69 @@ package body Exp_Util is
end if;
end Evolve_Or_Else;
+ -----------------------------------------
+ -- Expand_Static_Predicates_In_Choices --
+ -----------------------------------------
+
+ procedure Expand_Static_Predicates_In_Choices (N : Node_Id) is
+ pragma Assert (Nkind_In (N, N_Case_Statement_Alternative, N_Variant));
+
+ Choices : constant List_Id := Discrete_Choices (N);
+
+ Choice : Node_Id;
+ Next_C : Node_Id;
+ P : Node_Id;
+ C : Node_Id;
+
+ begin
+ Choice := First (Choices);
+ while Present (Choice) loop
+ Next_C := Next (Choice);
+
+ -- Check for name of subtype with static predicate
+
+ if Is_Entity_Name (Choice)
+ and then Is_Type (Entity (Choice))
+ and then Has_Predicates (Entity (Choice))
+ then
+ -- Loop through entries in predicate list, converting to choices
+ -- and inserting in the list before the current choice. Note that
+ -- if the list is empty, corresponding to a False predicate, then
+ -- no choices are inserted.
+
+ P := First (Static_Predicate (Entity (Choice)));
+ while Present (P) loop
+
+ -- If low bound and high bounds are equal, copy simple choice
+
+ if Expr_Value (Low_Bound (P)) = Expr_Value (High_Bound (P)) then
+ C := New_Copy (Low_Bound (P));
+
+ -- Otherwise copy a range
+
+ else
+ C := New_Copy (P);
+ end if;
+
+ -- Change Sloc to referencing choice (rather than the Sloc of
+ -- the predicate declaration element itself).
+
+ Set_Sloc (C, Sloc (Choice));
+ Insert_Before (Choice, C);
+ Next (P);
+ end loop;
+
+ -- Delete the predicated entry
+
+ Remove (Choice);
+ end if;
+
+ -- Move to next choice to check
+
+ Choice := Next_C;
+ end loop;
+ end Expand_Static_Predicates_In_Choices;
+
------------------------------
-- Expand_Subtype_From_Expr --
------------------------------
@@ -2166,7 +2198,7 @@ package body Exp_Util is
-- function being called is build-in-place. This will have to be revised
-- when build-in-place functions are generalized to other types.
- elsif Is_Immutably_Limited_Type (Exp_Typ)
+ elsif Is_Limited_View (Exp_Typ)
and then
(Is_Class_Wide_Type (Exp_Typ)
or else Is_Interface (Exp_Typ)
@@ -2645,18 +2677,36 @@ package body Exp_Util is
(N : Node_Id;
S : Boolean)
is
- Cond : Node_Id;
- Sens : Boolean;
+ Cond : Node_Id;
+ Prev_Cond : Node_Id;
+ Sens : Boolean;
begin
Cond := N;
Sens := S;
- -- Deal with NOT operators, inverting sense
+ loop
+ Prev_Cond := Cond;
- while Nkind (Cond) = N_Op_Not loop
- Cond := Right_Opnd (Cond);
- Sens := not Sens;
+ -- Deal with NOT operators, inverting sense
+
+ while Nkind (Cond) = N_Op_Not loop
+ Cond := Right_Opnd (Cond);
+ Sens := not Sens;
+ end loop;
+
+ -- Deal with conversions, qualifications, and expressions with
+ -- actions.
+
+ while Nkind_In (Cond,
+ N_Type_Conversion,
+ N_Qualified_Expression,
+ N_Expression_With_Actions)
+ loop
+ Cond := Expression (Cond);
+ end loop;
+
+ exit when Cond = Prev_Cond;
end loop;
-- Deal with AND THEN and AND cases
@@ -2737,8 +2787,15 @@ package body Exp_Util is
return;
- -- Case of Boolean variable reference, return as though the
- -- reference had said var = True.
+ elsif Nkind_In (Cond,
+ N_Type_Conversion,
+ N_Qualified_Expression,
+ N_Expression_With_Actions)
+ then
+ Cond := Expression (Cond);
+
+ -- Case of Boolean variable reference, return as though the
+ -- reference had said var = True.
else
if Is_Entity_Name (Cond) and then Ent = Entity (Cond) then
@@ -3345,8 +3402,13 @@ package body Exp_Util is
when N_Expression_With_Actions =>
if N = Expression (P) then
- Insert_List_After_And_Analyze
- (Last (Actions (P)), Ins_Actions);
+ if Is_Empty_List (Actions (P)) then
+ Append_List_To (Actions (P), Ins_Actions);
+ Analyze_List (Actions (P));
+ else
+ Insert_List_After_And_Analyze
+ (Last (Actions (P)), Ins_Actions);
+ end if;
return;
end if;
@@ -3448,7 +3510,8 @@ package body Exp_Util is
-- Freeze entity behaves like a declaration or statement
- N_Freeze_Entity
+ N_Freeze_Entity |
+ N_Freeze_Generic_Entity
=>
-- Do not insert here if the item is not a list member (this
-- happens for example with a triggering statement, and the
@@ -6640,6 +6703,14 @@ package body Exp_Util is
when N_Explicit_Dereference =>
return Safe_Prefixed_Reference (N);
+ -- An expression with action is side effect free if its expression
+ -- is side effect free and it has no actions.
+
+ when N_Expression_With_Actions =>
+ return Is_Empty_List (Actions (N))
+ and then
+ Side_Effect_Free (Expression (N));
+
-- A call to _rep_to_pos is side effect free, since we generate
-- this pure function call ourselves. Moreover it is critically
-- important to make this exception, since otherwise we can have
@@ -7019,7 +7090,7 @@ package body Exp_Util is
if Ada_Version >= Ada_2005
and then Nkind (Exp) = N_Function_Call
- and then Is_Immutably_Limited_Type (Etype (Exp))
+ and then Is_Limited_View (Etype (Exp))
and then Nkind (Parent (Exp)) /= N_Object_Declaration
then
declare
@@ -7041,7 +7112,6 @@ package body Exp_Util is
end if;
Def_Id := Make_Temporary (Loc, 'R', Exp);
- Set_Etype (Def_Id, Exp_Type);
-- The regular expansion of functions with side effects involves the
-- generation of an access type to capture the return value found on
@@ -7718,7 +7788,14 @@ package body Exp_Util is
Set_Entity_Current_Value (Right_Opnd (Cond));
end if;
- -- Check possible boolean variable reference
+ elsif Nkind_In (Cond,
+ N_Type_Conversion,
+ N_Qualified_Expression,
+ N_Expression_With_Actions)
+ then
+ Set_Expression_Current_Value (Expression (Cond));
+
+ -- Check possible boolean variable reference
else
Set_Entity_Current_Value (Cond);
diff --git a/gcc/ada/exp_util.ads b/gcc/ada/exp_util.ads
index 568b9f7d5c1..bf72220f826 100644
--- a/gcc/ada/exp_util.ads
+++ b/gcc/ada/exp_util.ads
@@ -349,19 +349,15 @@ package Exp_Util is
-- used to ensure that an Itype is properly defined outside a conditional
-- construct when it is referenced in more than one branch.
- function Entity_Of (N : Node_Id) return Entity_Id;
- -- Return the entity of N or Empty. If N is a renaming, return the entity
- -- of the root renamed object.
-
function Entry_Names_OK return Boolean;
-- Determine whether it is appropriate to dynamically allocate strings
-- which represent entry [family member] names. These strings are created
-- by the compiler and used by GDB.
procedure Evaluate_Name (Nam : Node_Id);
- -- Remove the all side effects from a name which appears as part of an
- -- object renaming declaration. More comments are needed here that explain
- -- how this differs from Force_Evaluation and Remove_Side_Effects ???
+ -- Remove all side effects from a name which appears as part of an object
+ -- renaming declaration. More comments are needed here that explain how
+ -- this differs from Force_Evaluation and Remove_Side_Effects ???
procedure Evolve_And_Then (Cond : in out Node_Id; Cond1 : Node_Id);
-- Rewrites Cond with the expression: Cond and then Cond1. If Cond is
@@ -377,6 +373,12 @@ package Exp_Util is
-- indicating that no checks were required). The Sloc field of the
-- constructed N_Or_Else node is copied from Cond1.
+ procedure Expand_Static_Predicates_In_Choices (N : Node_Id);
+ -- N is either a case alternative or a variant. The Discrete_Choices field
+ -- of N points to a list of choices. If any of these choices is the name
+ -- of a (statically) predicated subtype, then it is rewritten as the series
+ -- of choices that correspond to the values allowed for the subtype.
+
procedure Expand_Subtype_From_Expr
(N : Node_Id;
Unc_Type : Entity_Id;
diff --git a/gcc/ada/freeze.adb b/gcc/ada/freeze.adb
index 58098be741d..f6c60678143 100644
--- a/gcc/ada/freeze.adb
+++ b/gcc/ada/freeze.adb
@@ -92,11 +92,15 @@ package body Freeze is
procedure Check_Component_Storage_Order
(Encl_Type : Entity_Id;
- Comp : Entity_Id);
+ Comp : Entity_Id;
+ ADC : Node_Id);
-- For an Encl_Type that has a Scalar_Storage_Order attribute definition
- -- clause, verify that the component type is compatible. For arrays,
- -- Comp is Empty; for records, it is the entity of the component under
- -- consideration.
+ -- clause, verify that the component type has an explicit and compatible
+ -- attribute/aspect. For arrays, Comp is Empty; for records, it is the
+ -- entity of the component under consideration. For an Encl_Type that
+ -- does not have a Scalar_Storage_Order attribute definition clause,
+ -- verify that the component also does not have such a clause.
+ -- ADC is the attribute definition clause if present (or Empty).
procedure Check_Strict_Alignment (E : Entity_Id);
-- E is a base type. If E is tagged or has a component that is aliased
@@ -835,7 +839,7 @@ package body Freeze is
and then not Has_Independent_Components (T);
Packed_Size : Uint := Uint_0;
- -- SIze in bis so far
+ -- Size in bits so far
begin
-- Test for variant part present
@@ -846,8 +850,9 @@ package body Freeze is
and then Nkind (Type_Definition (Parent (T))) =
N_Record_Definition
and then not Null_Present (Type_Definition (Parent (T)))
- and then Present (Variant_Part
- (Component_List (Type_Definition (Parent (T)))))
+ and then
+ Present (Variant_Part
+ (Component_List (Type_Definition (Parent (T)))))
then
-- If variant part is present, and type is unconstrained,
-- then we must have defaulted discriminants, or a size
@@ -880,11 +885,13 @@ package body Freeze is
end if;
-- We do not know the packed size if we have a by reference
- -- type, or an atomic type or an atomic component.
+ -- type, or an atomic type or an atomic component, or an
+ -- aliased component (because packing does not touch these).
if Is_Atomic (Ctyp)
or else Is_Atomic (Comp)
or else Is_By_Reference_Type (Ctyp)
+ or else Is_Aliased (Comp)
then
Packed_Size_Known := False;
end if;
@@ -1065,17 +1072,19 @@ package body Freeze is
procedure Check_Component_Storage_Order
(Encl_Type : Entity_Id;
- Comp : Entity_Id)
+ Comp : Entity_Id;
+ ADC : Node_Id)
is
Comp_Type : Entity_Id;
- Comp_Def : Node_Id;
+ Comp_ADC : Node_Id;
Err_Node : Node_Id;
- ADC : Node_Id;
Comp_Byte_Aligned : Boolean;
-- Set True for the record case, when Comp starts on a byte boundary
-- (in which case it is allowed to have different storage order).
+ Component_Aliased : Boolean;
+
begin
-- Record case
@@ -1084,15 +1093,15 @@ package body Freeze is
Comp_Type := Etype (Comp);
if Is_Tag (Comp) then
- Comp_Def := Empty;
Comp_Byte_Aligned := True;
+ Component_Aliased := False;
else
- Comp_Def := Component_Definition (Parent (Comp));
Comp_Byte_Aligned :=
Present (Component_Clause (Comp))
and then
Normalized_First_Bit (Comp) mod System_Storage_Unit = 0;
+ Component_Aliased := Is_Aliased (Comp);
end if;
-- Array case
@@ -1100,21 +1109,33 @@ package body Freeze is
else
Err_Node := Encl_Type;
Comp_Type := Component_Type (Encl_Type);
- Comp_Def := Component_Definition
- (Type_Definition (Declaration_Node (Encl_Type)));
Comp_Byte_Aligned := False;
+ Component_Aliased := Has_Aliased_Components (Encl_Type);
end if;
-- Note: the Reverse_Storage_Order flag is set on the base type, but
-- the attribute definition clause is attached to the first subtype.
Comp_Type := Base_Type (Comp_Type);
- ADC := Get_Attribute_Definition_Clause
- (First_Subtype (Comp_Type),
- Attribute_Scalar_Storage_Order);
+ Comp_ADC := Get_Attribute_Definition_Clause
+ (First_Subtype (Comp_Type),
+ Attribute_Scalar_Storage_Order);
+
+ -- Case of enclosing type not having explicit SSO: component cannot
+ -- have it either.
+
+ if No (ADC) then
+ if Present (Comp_ADC) then
+ Error_Msg_N
+ ("composite type must have explicit scalar storage order",
+ Err_Node);
+ end if;
- if Is_Record_Type (Comp_Type) or else Is_Array_Type (Comp_Type) then
+ -- Case of enclosing type having explicit SSO: check compatible
+ -- attribute on Comp_Type if composite.
+
+ elsif Is_Record_Type (Comp_Type) or else Is_Array_Type (Comp_Type) then
if Present (Comp) and then Chars (Comp) = Name_uParent then
if Reverse_Storage_Order (Encl_Type)
/=
@@ -1139,7 +1160,10 @@ package body Freeze is
& "storage order as enclosing composite", Err_Node);
end if;
- elsif Present (Comp_Def) and then Aliased_Present (Comp_Def) then
+ -- Enclosing type has explicit SSO, non-composite component must not
+ -- be aliased.
+
+ elsif Component_Aliased then
Error_Msg_N
("aliased component not permitted for type with "
& "explicit Scalar_Storage_Order", Err_Node);
@@ -1697,8 +1721,15 @@ package body Freeze is
-- integer literal without an explicit corresponding size clause. The
-- caller has checked that Utype is a modular integer type.
+ procedure Freeze_Array_Type (Arr : Entity_Id);
+ -- Freeze array type, including freezing index and component types
+
+ function Freeze_Generic_Entities (Pack : Entity_Id) return List_Id;
+ -- Create Freeze_Generic_Entity nodes for types declared in a generic
+ -- package. Recurse on inner generic packages.
+
procedure Freeze_Record_Type (Rec : Entity_Id);
- -- Freeze each component, handle some representation clauses, and freeze
+ -- Freeze record type, including freezing component types, and freezing
-- primitive operations if this is a tagged type.
-------------------
@@ -1841,8 +1872,16 @@ package body Freeze is
and then Is_Type (Entity (Prefix (N)))
and then Entity (Prefix (N)) = E
then
- Error_Msg_N
- ("current instance must be a limited type", Prefix (N));
+ if Ada_Version < Ada_2012 then
+ Error_Msg_N
+ ("current instance must be a limited type",
+ Prefix (N));
+ else
+ Error_Msg_N
+ ("current instance must be an immutably limited " &
+ "type (RM-2012, 7.5 (8.1/3))",
+ Prefix (N));
+ end if;
return Abandon;
else
return OK;
@@ -1943,6 +1982,558 @@ package body Freeze is
end if;
end Check_Suspicious_Modulus;
+ -----------------------
+ -- Freeze_Array_Type --
+ -----------------------
+
+ procedure Freeze_Array_Type (Arr : Entity_Id) is
+ FS : constant Entity_Id := First_Subtype (Arr);
+ Ctyp : constant Entity_Id := Component_Type (Arr);
+ Clause : Entity_Id;
+
+ Non_Standard_Enum : Boolean := False;
+ -- Set true if any of the index types is an enumeration type with a
+ -- non-standard representation.
+
+ begin
+ Freeze_And_Append (Ctyp, N, Result);
+
+ Indx := First_Index (Arr);
+ while Present (Indx) loop
+ Freeze_And_Append (Etype (Indx), N, Result);
+
+ if Is_Enumeration_Type (Etype (Indx))
+ and then Has_Non_Standard_Rep (Etype (Indx))
+ then
+ Non_Standard_Enum := True;
+ end if;
+
+ Next_Index (Indx);
+ end loop;
+
+ -- Processing that is done only for base types
+
+ if Ekind (Arr) = E_Array_Type then
+
+ -- Propagate flags for component type
+
+ if Is_Controlled (Component_Type (Arr))
+ or else Has_Controlled_Component (Ctyp)
+ then
+ Set_Has_Controlled_Component (Arr);
+ end if;
+
+ if Has_Unchecked_Union (Component_Type (Arr)) then
+ Set_Has_Unchecked_Union (Arr);
+ end if;
+
+ -- Warn for pragma Pack overriding foreign convention
+
+ if Has_Foreign_Convention (Ctyp)
+ and then Has_Pragma_Pack (Arr)
+ then
+ declare
+ CN : constant Name_Id :=
+ Get_Convention_Name (Convention (Ctyp));
+ PP : constant Node_Id :=
+ Get_Pragma (First_Subtype (Arr), Pragma_Pack);
+ begin
+ if Present (PP) then
+ Error_Msg_Name_1 := CN;
+ Error_Msg_Sloc := Sloc (Arr);
+ Error_Msg_N
+ ("pragma Pack affects convention % components #??",
+ PP);
+ Error_Msg_Name_1 := CN;
+ Error_Msg_N
+ ("\array components may not have % compatible "
+ & "representation??", PP);
+ end if;
+ end;
+ end if;
+
+ -- If packing was requested or if the component size was
+ -- set explicitly, then see if bit packing is required. This
+ -- processing is only done for base types, since all of the
+ -- representation aspects involved are type-related. This is not
+ -- just an optimization, if we start processing the subtypes, they
+ -- interfere with the settings on the base type (this is because
+ -- Is_Packed has a slightly different meaning before and after
+ -- freezing).
+
+ declare
+ Csiz : Uint;
+ Esiz : Uint;
+
+ begin
+ if (Is_Packed (Arr) or else Has_Pragma_Pack (Arr))
+ and then Known_Static_RM_Size (Ctyp)
+ and then not Has_Component_Size_Clause (Arr)
+ then
+ Csiz := UI_Max (RM_Size (Ctyp), 1);
+
+ elsif Known_Component_Size (Arr) then
+ Csiz := Component_Size (Arr);
+
+ elsif not Known_Static_Esize (Ctyp) then
+ Csiz := Uint_0;
+
+ else
+ Esiz := Esize (Ctyp);
+
+ -- We can set the component size if it is less than 16,
+ -- rounding it up to the next storage unit size.
+
+ if Esiz <= 8 then
+ Csiz := Uint_8;
+ elsif Esiz <= 16 then
+ Csiz := Uint_16;
+ else
+ Csiz := Uint_0;
+ end if;
+
+ -- Set component size up to match alignment if it would
+ -- otherwise be less than the alignment. This deals with
+ -- cases of types whose alignment exceeds their size (the
+ -- padded type cases).
+
+ if Csiz /= 0 then
+ declare
+ A : constant Uint := Alignment_In_Bits (Ctyp);
+ begin
+ if Csiz < A then
+ Csiz := A;
+ end if;
+ end;
+ end if;
+ end if;
+
+ -- Case of component size that may result in packing
+
+ if 1 <= Csiz and then Csiz <= 64 then
+ declare
+ Ent : constant Entity_Id :=
+ First_Subtype (Arr);
+ Pack_Pragma : constant Node_Id :=
+ Get_Rep_Pragma (Ent, Name_Pack);
+ Comp_Size_C : constant Node_Id :=
+ Get_Attribute_Definition_Clause
+ (Ent, Attribute_Component_Size);
+ begin
+ -- Warn if we have pack and component size so that the
+ -- pack is ignored.
+
+ -- Note: here we must check for the presence of a
+ -- component size before checking for a Pack pragma to
+ -- deal with the case where the array type is a derived
+ -- type whose parent is currently private.
+
+ if Present (Comp_Size_C)
+ and then Has_Pragma_Pack (Ent)
+ and then Warn_On_Redundant_Constructs
+ then
+ Error_Msg_Sloc := Sloc (Comp_Size_C);
+ Error_Msg_NE
+ ("?r?pragma Pack for& ignored!",
+ Pack_Pragma, Ent);
+ Error_Msg_N
+ ("\?r?explicit component size given#!",
+ Pack_Pragma);
+ Set_Is_Packed (Base_Type (Ent), False);
+ Set_Is_Bit_Packed_Array (Base_Type (Ent), False);
+ end if;
+
+ -- Set component size if not already set by a component
+ -- size clause.
+
+ if not Present (Comp_Size_C) then
+ Set_Component_Size (Arr, Csiz);
+ end if;
+
+ -- Check for base type of 8, 16, 32 bits, where an
+ -- unsigned subtype has a length one less than the
+ -- base type (e.g. Natural subtype of Integer).
+
+ -- In such cases, if a component size was not set
+ -- explicitly, then generate a warning.
+
+ if Has_Pragma_Pack (Arr)
+ and then not Present (Comp_Size_C)
+ and then
+ (Csiz = 7 or else Csiz = 15 or else Csiz = 31)
+ and then Esize (Base_Type (Ctyp)) = Csiz + 1
+ then
+ Error_Msg_Uint_1 := Csiz;
+
+ if Present (Pack_Pragma) then
+ Error_Msg_N
+ ("??pragma Pack causes component size "
+ & "to be ^!", Pack_Pragma);
+ Error_Msg_N
+ ("\??use Component_Size to set "
+ & "desired value!", Pack_Pragma);
+ end if;
+ end if;
+
+ -- Actual packing is not needed for 8, 16, 32, 64. Also
+ -- not needed for 24 if alignment is 1.
+
+ if Csiz = 8
+ or else Csiz = 16
+ or else Csiz = 32
+ or else Csiz = 64
+ or else (Csiz = 24 and then Alignment (Ctyp) = 1)
+ then
+ -- Here the array was requested to be packed, but
+ -- the packing request had no effect, so Is_Packed
+ -- is reset.
+
+ -- Note: semantically this means that we lose track
+ -- of the fact that a derived type inherited a pragma
+ -- Pack that was non- effective, but that seems fine.
+
+ -- We regard a Pack pragma as a request to set a
+ -- representation characteristic, and this request
+ -- may be ignored.
+
+ Set_Is_Packed (Base_Type (Arr), False);
+ Set_Is_Bit_Packed_Array (Base_Type (Arr), False);
+
+ if Known_Static_Esize (Component_Type (Arr))
+ and then Esize (Component_Type (Arr)) = Csiz
+ then
+ Set_Has_Non_Standard_Rep
+ (Base_Type (Arr), False);
+ end if;
+
+ -- In all other cases, packing is indeed needed
+
+ else
+ Set_Has_Non_Standard_Rep (Base_Type (Arr), True);
+ Set_Is_Bit_Packed_Array (Base_Type (Arr), True);
+ Set_Is_Packed (Base_Type (Arr), True);
+ end if;
+ end;
+ end if;
+ end;
+
+ -- Check for Atomic_Components or Aliased with unsuitable packing
+ -- or explicit component size clause given.
+
+ if (Has_Atomic_Components (Arr)
+ or else Has_Aliased_Components (Arr))
+ and then (Has_Component_Size_Clause (Arr)
+ or else Is_Packed (Arr))
+ then
+ Alias_Atomic_Check : declare
+
+ procedure Complain_CS (T : String);
+ -- Outputs error messages for incorrect CS clause or pragma
+ -- Pack for aliased or atomic components (T is "aliased" or
+ -- "atomic");
+
+ -----------------
+ -- Complain_CS --
+ -----------------
+
+ procedure Complain_CS (T : String) is
+ begin
+ if Has_Component_Size_Clause (Arr) then
+ Clause :=
+ Get_Attribute_Definition_Clause
+ (FS, Attribute_Component_Size);
+
+ if Known_Static_Esize (Ctyp) then
+ Error_Msg_N
+ ("incorrect component size for "
+ & T & " components", Clause);
+ Error_Msg_Uint_1 := Esize (Ctyp);
+ Error_Msg_N
+ ("\only allowed value is^", Clause);
+
+ else
+ Error_Msg_N
+ ("component size cannot be given for "
+ & T & " components", Clause);
+ end if;
+
+ else
+ Error_Msg_N
+ ("cannot pack " & T & " components",
+ Get_Rep_Pragma (FS, Name_Pack));
+ end if;
+
+ return;
+ end Complain_CS;
+
+ -- Start of processing for Alias_Atomic_Check
+
+ begin
+
+ -- If object size of component type isn't known, we cannot
+ -- be sure so we defer to the back end.
+
+ if not Known_Static_Esize (Ctyp) then
+ null;
+
+ -- Case where component size has no effect. First check for
+ -- object size of component type multiple of the storage
+ -- unit size.
+
+ elsif Esize (Ctyp) mod System_Storage_Unit = 0
+
+ -- OK in both packing case and component size case if RM
+ -- size is known and static and same as the object size.
+
+ and then
+ ((Known_Static_RM_Size (Ctyp)
+ and then Esize (Ctyp) = RM_Size (Ctyp))
+
+ -- Or if we have an explicit component size clause and
+ -- the component size and object size are equal.
+
+ or else
+ (Has_Component_Size_Clause (Arr)
+ and then Component_Size (Arr) = Esize (Ctyp)))
+ then
+ null;
+
+ elsif Has_Aliased_Components (Arr)
+ or else Is_Aliased (Ctyp)
+ then
+ Complain_CS ("aliased");
+
+ elsif Has_Atomic_Components (Arr)
+ or else Is_Atomic (Ctyp)
+ then
+ Complain_CS ("atomic");
+ end if;
+ end Alias_Atomic_Check;
+ end if;
+
+ -- Warn for case of atomic type
+
+ Clause := Get_Rep_Pragma (FS, Name_Atomic);
+
+ if Present (Clause)
+ and then not Addressable (Component_Size (FS))
+ then
+ Error_Msg_NE
+ ("non-atomic components of type& may not be "
+ & "accessible by separate tasks??", Clause, Arr);
+
+ if Has_Component_Size_Clause (Arr) then
+ Error_Msg_Sloc :=
+ Sloc
+ (Get_Attribute_Definition_Clause
+ (FS, Attribute_Component_Size));
+ Error_Msg_N
+ ("\because of component size clause#??",
+ Clause);
+
+ elsif Has_Pragma_Pack (Arr) then
+ Error_Msg_Sloc :=
+ Sloc (Get_Rep_Pragma (FS, Name_Pack));
+ Error_Msg_N
+ ("\because of pragma Pack#??", Clause);
+ end if;
+ end if;
+
+ -- Check for scalar storage order
+
+ Check_Component_Storage_Order
+ (Encl_Type => Arr,
+ Comp => Empty,
+ ADC => Get_Attribute_Definition_Clause
+ (First_Subtype (Arr),
+ Attribute_Scalar_Storage_Order));
+
+ -- Processing that is done only for subtypes
+
+ else
+ -- Acquire alignment from base type
+
+ if Unknown_Alignment (Arr) then
+ Set_Alignment (Arr, Alignment (Base_Type (Arr)));
+ Adjust_Esize_Alignment (Arr);
+ end if;
+ end if;
+
+ -- Specific checks for bit-packed arrays
+
+ if Is_Bit_Packed_Array (Arr) then
+
+ -- Check number of elements for bit packed arrays that come from
+ -- source and have compile time known ranges. The bit-packed
+ -- arrays circuitry does not support arrays with more than
+ -- Integer'Last + 1 elements, and when this restriction is
+ -- violated, causes incorrect data access.
+
+ -- For the case where this is not compile time known, a run-time
+ -- check should be generated???
+
+ if Comes_From_Source (Arr) and then Is_Constrained (Arr) then
+ declare
+ Elmts : Uint;
+ Index : Node_Id;
+ Ilen : Node_Id;
+ Ityp : Entity_Id;
+
+ begin
+ Elmts := Uint_1;
+ Index := First_Index (Arr);
+ while Present (Index) loop
+ Ityp := Etype (Index);
+
+ -- Never generate an error if any index is of a generic
+ -- type. We will check this in instances.
+
+ if Is_Generic_Type (Ityp) then
+ Elmts := Uint_0;
+ exit;
+ end if;
+
+ Ilen :=
+ Make_Attribute_Reference (Loc,
+ Prefix =>
+ New_Occurrence_Of (Ityp, Loc),
+ Attribute_Name => Name_Range_Length);
+ Analyze_And_Resolve (Ilen);
+
+ -- No attempt is made to check number of elements
+ -- if not compile time known.
+
+ if Nkind (Ilen) /= N_Integer_Literal then
+ Elmts := Uint_0;
+ exit;
+ end if;
+
+ Elmts := Elmts * Intval (Ilen);
+ Next_Index (Index);
+ end loop;
+
+ if Elmts > Intval (High_Bound
+ (Scalar_Range
+ (Standard_Integer))) + 1
+ then
+ Error_Msg_N
+ ("bit packed array type may not have "
+ & "more than Integer''Last+1 elements", Arr);
+ end if;
+ end;
+ end if;
+
+ -- Check size
+
+ if Known_RM_Size (Arr) then
+ declare
+ SizC : constant Node_Id := Size_Clause (Arr);
+
+ Discard : Boolean;
+ pragma Warnings (Off, Discard);
+
+ begin
+ -- It is not clear if it is possible to have no size clause
+ -- at this stage, but it is not worth worrying about. Post
+ -- error on the entity name in the size clause if present,
+ -- else on the type entity itself.
+
+ if Present (SizC) then
+ Check_Size (Name (SizC), Arr, RM_Size (Arr), Discard);
+ else
+ Check_Size (Arr, Arr, RM_Size (Arr), Discard);
+ end if;
+ end;
+ end if;
+ end if;
+
+ -- If any of the index types was an enumeration type with a
+ -- non-standard rep clause, then we indicate that the array type
+ -- is always packed (even if it is not bit packed).
+
+ if Non_Standard_Enum then
+ Set_Has_Non_Standard_Rep (Base_Type (Arr));
+ Set_Is_Packed (Base_Type (Arr));
+ end if;
+
+ Set_Component_Alignment_If_Not_Set (Arr);
+
+ -- If the array is packed, we must create the packed array type to be
+ -- used to actually implement the type. This is only needed for real
+ -- array types (not for string literal types, since they are present
+ -- only for the front end).
+
+ if Is_Packed (Arr)
+ and then Ekind (Arr) /= E_String_Literal_Subtype
+ then
+ Create_Packed_Array_Type (Arr);
+ Freeze_And_Append (Packed_Array_Type (Arr), N, Result);
+
+ -- Size information of packed array type is copied to the array
+ -- type, since this is really the representation. But do not
+ -- override explicit existing size values. If the ancestor subtype
+ -- is constrained the packed_array_type will be inherited from it,
+ -- but the size may have been provided already, and must not be
+ -- overridden either.
+
+ if not Has_Size_Clause (Arr)
+ and then
+ (No (Ancestor_Subtype (Arr))
+ or else not Has_Size_Clause (Ancestor_Subtype (Arr)))
+ then
+ Set_Esize (Arr, Esize (Packed_Array_Type (Arr)));
+ Set_RM_Size (Arr, RM_Size (Packed_Array_Type (Arr)));
+ end if;
+
+ if not Has_Alignment_Clause (Arr) then
+ Set_Alignment (Arr, Alignment (Packed_Array_Type (Arr)));
+ end if;
+ end if;
+
+ -- For non-packed arrays set the alignment of the array to the
+ -- alignment of the component type if it is unknown. Skip this
+ -- in atomic case (atomic arrays may need larger alignments).
+
+ if not Is_Packed (Arr)
+ and then Unknown_Alignment (Arr)
+ and then Known_Alignment (Ctyp)
+ and then Known_Static_Component_Size (Arr)
+ and then Known_Static_Esize (Ctyp)
+ and then Esize (Ctyp) = Component_Size (Arr)
+ and then not Is_Atomic (Arr)
+ then
+ Set_Alignment (Arr, Alignment (Component_Type (Arr)));
+ end if;
+ end Freeze_Array_Type;
+
+ -----------------------------
+ -- Freeze_Generic_Entities --
+ -----------------------------
+
+ function Freeze_Generic_Entities (Pack : Entity_Id) return List_Id is
+ E : Entity_Id;
+ F : Node_Id;
+ Flist : List_Id;
+
+ begin
+ Flist := New_List;
+ E := First_Entity (Pack);
+ while Present (E) loop
+ if Is_Type (E) and then not Is_Generic_Type (E) then
+ F := Make_Freeze_Generic_Entity (Sloc (Pack));
+ Set_Entity (F, E);
+ Append_To (Flist, F);
+
+ elsif Ekind (E) = E_Generic_Package then
+ Append_List_To (Flist, Freeze_Generic_Entities (E));
+ end if;
+
+ Next_Entity (E);
+ end loop;
+
+ return Flist;
+ end Freeze_Generic_Entities;
+
------------------------
-- Freeze_Record_Type --
------------------------
@@ -1970,6 +2561,11 @@ package body Freeze is
-- clause (used to warn about useless Bit_Order pragmas, and also
-- to detect cases where Implicit_Packing may have an effect).
+ Aliased_Component : Boolean := False;
+ -- Set True if we find at least one component which is aliased. This
+ -- is used to prevent Implicit_Packing of the record, since packing
+ -- cannot modify the size of alignment of an aliased component.
+
All_Scalar_Components : Boolean := True;
-- Set False if we encounter a component of a non-scalar type
@@ -1993,6 +2589,11 @@ package body Freeze is
-- freeze node at some eventual point of call. Protected operations
-- are handled elsewhere.
+ procedure Freeze_Choices_In_Variant_Part (VP : Node_Id);
+ -- Make sure that all types mentioned in Discrete_Choices of the
+ -- variants referenceed by the Variant_Part VP are frozen. This is
+ -- a recursive routine to deal with nested variants.
+
---------------------
-- Check_Allocator --
---------------------
@@ -2045,6 +2646,50 @@ package body Freeze is
end if;
end Check_Itype;
+ ------------------------------------
+ -- Freeze_Choices_In_Variant_Part --
+ ------------------------------------
+
+ procedure Freeze_Choices_In_Variant_Part (VP : Node_Id) is
+ pragma Assert (Nkind (VP) = N_Variant_Part);
+
+ Variant : Node_Id;
+ Choice : Node_Id;
+ CL : Node_Id;
+
+ begin
+ -- Loop through variants
+
+ Variant := First_Non_Pragma (Variants (VP));
+ while Present (Variant) loop
+
+ -- Loop through choices, checking that all types are frozen
+
+ Choice := First_Non_Pragma (Discrete_Choices (Variant));
+ while Present (Choice) loop
+ if Nkind (Choice) in N_Has_Etype
+ and then Present (Etype (Choice))
+ then
+ Freeze_And_Append (Etype (Choice), N, Result);
+ end if;
+
+ Next_Non_Pragma (Choice);
+ end loop;
+
+ -- Check for nested variant part to process
+
+ CL := Component_List (Variant);
+
+ if not Null_Present (CL) then
+ if Present (Variant_Part (CL)) then
+ Freeze_Choices_In_Variant_Part (Variant_Part (CL));
+ end if;
+ end if;
+
+ Next_Non_Pragma (Variant);
+ end loop;
+ end Freeze_Choices_In_Variant_Part;
+
-- Start of processing for Freeze_Record_Type
begin
@@ -2094,6 +2739,9 @@ package body Freeze is
Comp := First_Entity (Rec);
Prev := Empty;
while Present (Comp) loop
+ if Is_Aliased (Comp) then
+ Aliased_Component := True;
+ end if;
-- Handle the component and discriminant case
@@ -2119,6 +2767,36 @@ package body Freeze is
Freeze_And_Append (Etype (Comp), N, Result);
+ -- Warn for pragma Pack overriding foreign convention
+
+ if Has_Foreign_Convention (Etype (Comp))
+ and then Has_Pragma_Pack (Rec)
+
+ -- Don't warn for aliased components, since override
+ -- cannot happen in that case.
+
+ and then not Is_Aliased (Comp)
+ then
+ declare
+ CN : constant Name_Id :=
+ Get_Convention_Name (Convention (Etype (Comp)));
+ PP : constant Node_Id :=
+ Get_Pragma (Rec, Pragma_Pack);
+ begin
+ if Present (PP) then
+ Error_Msg_Name_1 := CN;
+ Error_Msg_Sloc := Sloc (Comp);
+ Error_Msg_N
+ ("pragma Pack affects convention % component#??",
+ PP);
+ Error_Msg_Name_1 := CN;
+ Error_Msg_NE
+ ("\component & may not have % compatible "
+ & "representation??", PP, Comp);
+ end if;
+ end;
+ end if;
+
-- Check for error of component clause given for variable
-- sized type. We have to delay this test till this point,
-- since the component type has to be frozen for us to know
@@ -2272,7 +2950,7 @@ package body Freeze is
begin
if Present (Alloc) then
- -- If component is pointer to a classwide type, freeze
+ -- If component is pointer to a class-wide type, freeze
-- the specific type in the expression being allocated.
-- The expression may be a subtype indication, in which
-- case freeze the subtype mark.
@@ -2351,15 +3029,16 @@ package body Freeze is
("??scalar storage order specified but no component clause",
ADC);
end if;
+ end if;
- -- Check attribute on component types
+ -- Check consistent attribute setting on component types
- Comp := First_Component (Rec);
- while Present (Comp) loop
- Check_Component_Storage_Order (Rec, Comp);
- Next_Component (Comp);
- end loop;
- end if;
+ Comp := First_Component (Rec);
+ while Present (Comp) loop
+ Check_Component_Storage_Order
+ (Encl_Type => Rec, Comp => Comp, ADC => ADC);
+ Next_Component (Comp);
+ end loop;
-- Deal with Bit_Order aspect specifying a non-default bit order
@@ -2367,7 +3046,8 @@ package body Freeze is
if Present (ADC) and then Base_Type (Rec) = Rec then
if not (Placed_Component or else Is_Packed (Rec)) then
- Error_Msg_N ("??bit order specification has no effect", ADC);
+ Error_Msg_N
+ ("??bit order specification has no effect", ADC);
Error_Msg_N
("\??since no component clauses were specified", ADC);
@@ -2443,15 +3123,13 @@ package body Freeze is
-- remote type here since that is what we are semantically freezing.
-- This prevents the freeze node for that type in an inner scope.
- -- Also, Check for controlled components and unchecked unions.
- -- Finally, enforce the restriction that access attributes with a
- -- current instance prefix can only apply to limited types.
-
if Ekind (Rec) = E_Record_Type then
if Present (Corresponding_Remote_Type (Rec)) then
Freeze_And_Append (Corresponding_Remote_Type (Rec), N, Result);
end if;
+ -- Check for controlled components and unchecked unions.
+
Comp := First_Component (Rec);
while Present (Comp) loop
@@ -2459,18 +3137,18 @@ package body Freeze is
-- equivalent type. See Make_CW_Equivalent_Type.
if not Is_Class_Wide_Equivalent_Type (Rec)
- and then (Has_Controlled_Component (Etype (Comp))
- or else (Chars (Comp) /= Name_uParent
- and then Is_Controlled (Etype (Comp)))
- or else (Is_Protected_Type (Etype (Comp))
- and then
- Present
- (Corresponding_Record_Type
- (Etype (Comp)))
- and then
- Has_Controlled_Component
- (Corresponding_Record_Type
- (Etype (Comp)))))
+ and then
+ (Has_Controlled_Component (Etype (Comp))
+ or else
+ (Chars (Comp) /= Name_uParent
+ and then Is_Controlled (Etype (Comp)))
+ or else
+ (Is_Protected_Type (Etype (Comp))
+ and then
+ Present (Corresponding_Record_Type (Etype (Comp)))
+ and then
+ Has_Controlled_Component
+ (Corresponding_Record_Type (Etype (Comp)))))
then
Set_Has_Controlled_Component (Rec);
end if;
@@ -2490,11 +3168,17 @@ package body Freeze is
end loop;
end if;
+ -- Enforce the restriction that access attributes with a current
+ -- instance prefix can only apply to limited types. This comment
+ -- is floating here, but does not seem to belong here???
+
+ -- Set component alignment if not otherwise already set
+
Set_Component_Alignment_If_Not_Set (Rec);
-- For first subtypes, check if there are any fixed-point fields with
-- component clauses, where we must check the size. This is not done
- -- till the freeze point, since for fixed-point types, we do not know
+ -- till the freeze point since for fixed-point types, we do not know
-- the size until the type is frozen. Similar processing applies to
-- bit packed arrays.
@@ -2565,6 +3249,10 @@ package body Freeze is
and then not Placed_Component
+ -- Or even one component is aliased
+
+ and then not Aliased_Component
+
-- Must have size clause and all scalar components
and then Has_Size_Clause (Rec)
@@ -2613,6 +3301,53 @@ package body Freeze is
end;
end if;
end if;
+
+ -- All done if not a full record definition
+
+ if Ekind (Rec) /= E_Record_Type then
+ return;
+ end if;
+
+ -- Finally we need to check the variant part to make sure that
+ -- all types within choices are properly frozen as part of the
+ -- freezing of the record type.
+
+ Check_Variant_Part : declare
+ D : constant Node_Id := Declaration_Node (Rec);
+ T : Node_Id;
+ C : Node_Id;
+
+ begin
+ -- Find component list
+
+ C := Empty;
+
+ if Nkind (D) = N_Full_Type_Declaration then
+ T := Type_Definition (D);
+
+ if Nkind (T) = N_Record_Definition then
+ C := Component_List (T);
+
+ elsif Nkind (T) = N_Derived_Type_Definition
+ and then Present (Record_Extension_Part (T))
+ then
+ C := Component_List (Record_Extension_Part (T));
+ end if;
+ end if;
+
+ -- Case of variant part present
+
+ if Present (C) and then Present (Variant_Part (C)) then
+ Freeze_Choices_In_Variant_Part (Variant_Part (C));
+ end if;
+
+ -- Note: we used to call Check_Choices here, but it is too early,
+ -- since predicated subtypes are frozen here, but their freezing
+ -- actions are in Analyze_Freeze_Entity, which has not been called
+ -- yet for entities frozen within this procedure, so we moved that
+ -- call to the Analyze_Freeze_Entity for the record type.
+
+ end Check_Variant_Part;
end Freeze_Record_Type;
-- Start of processing for Freeze_Entity
@@ -2659,6 +3394,12 @@ package body Freeze is
then
return No_List;
+ -- Generic types need no freeze node and have no delayed semantic
+ -- checks.
+
+ elsif Is_Generic_Type (E) then
+ return No_List;
+
-- Do not freeze a global entity within an inner scope created during
-- expansion. A call to subprogram E within some internal procedure
-- (a stream attribute for example) might require freezing E, but the
@@ -2728,6 +3469,9 @@ package body Freeze is
return No_List;
end if;
end;
+
+ elsif Ekind (E) = E_Generic_Package then
+ return Freeze_Generic_Entities (E);
end if;
-- Add checks to detect proper initialization of scalars that may appear
@@ -2813,6 +3557,7 @@ package body Freeze is
if Is_Incomplete_Type (F_Type)
and then Present (Full_View (F_Type))
+ and then not From_Limited_With (F_Type)
then
F_Type := Full_View (F_Type);
Set_Etype (Formal, F_Type);
@@ -2962,7 +3707,7 @@ package body Freeze is
Error_Msg_Qual_Level := 0;
end if;
- if not From_With_Type (F_Type) then
+ if not From_Limited_With (F_Type) then
if Is_Access_Type (F_Type) then
F_Type := Designated_Type (F_Type);
end if;
@@ -2991,10 +3736,15 @@ package body Freeze is
R_Type := Etype (E);
-- AI05-0151: the return type may have been incomplete
- -- at the point of declaration.
+ -- at the point of declaration. Replace it with the full
+ -- view, unless the current type is a limited view. In
+ -- that case the full view is in a different unit, and
+ -- gigi finds the non-limited view after the other unit
+ -- is elaborated.
if Ekind (R_Type) = E_Incomplete_Type
and then Present (Full_View (R_Type))
+ and then not From_Limited_With (R_Type)
then
R_Type := Full_View (R_Type);
Set_Etype (E, R_Type);
@@ -3196,6 +3946,24 @@ package body Freeze is
Check_Address_Clause (E);
+ -- Reset Is_True_Constant for aliased object. We consider that
+ -- the fact that something is aliased may indicate that some
+ -- funny business is going on, e.g. an aliased object is passed
+ -- by reference to a procedure which captures the address of
+ -- the object, which is later used to assign a new value. Such
+ -- code is highly dubious, but we choose to make it "work" for
+ -- aliased objects.
+
+ -- However, we don't do that for internal entities. We figure
+ -- that if we deliberately set Is_True_Constant for an internal
+ -- entity, e.g. a dispatch table entry, then we mean it!
+
+ if (Is_Aliased (E) or else Is_Aliased (Etype (E)))
+ and then not Is_Internal_Name (Chars (E))
+ then
+ Set_Is_True_Constant (E, False);
+ end if;
+
-- If the object needs any kind of default initialization, an
-- error must be issued if No_Default_Initialization applies.
-- The check doesn't apply to imported objects, which are not
@@ -3372,7 +4140,6 @@ package body Freeze is
end if;
end;
end if;
-
end if;
-- Case of a type or subtype being frozen
@@ -3399,7 +4166,9 @@ package body Freeze is
if Present (Scope (E))
and then Is_Generic_Unit (Scope (E))
- and then not Has_Predicates (E)
+ and then
+ (not Has_Predicates (E)
+ and then not Has_Delayed_Freeze (E))
then
Check_Compile_Time_Size (E);
return No_List;
@@ -3581,506 +4350,10 @@ package body Freeze is
Inherit_Aspects_At_Freeze_Point (E);
end if;
- -- For array type, freeze index types and component type first
- -- before freezing the array (RM 13.14(15)).
+ -- Array type
if Is_Array_Type (E) then
- declare
- FS : constant Entity_Id := First_Subtype (E);
- Ctyp : constant Entity_Id := Component_Type (E);
- Clause : Entity_Id;
-
- Non_Standard_Enum : Boolean := False;
- -- Set true if any of the index types is an enumeration type
- -- with a non-standard representation.
-
- begin
- Freeze_And_Append (Ctyp, N, Result);
-
- Indx := First_Index (E);
- while Present (Indx) loop
- Freeze_And_Append (Etype (Indx), N, Result);
-
- if Is_Enumeration_Type (Etype (Indx))
- and then Has_Non_Standard_Rep (Etype (Indx))
- then
- Non_Standard_Enum := True;
- end if;
-
- Next_Index (Indx);
- end loop;
-
- -- Processing that is done only for base types
-
- if Ekind (E) = E_Array_Type then
-
- -- Propagate flags for component type
-
- if Is_Controlled (Component_Type (E))
- or else Has_Controlled_Component (Ctyp)
- then
- Set_Has_Controlled_Component (E);
- end if;
-
- if Has_Unchecked_Union (Component_Type (E)) then
- Set_Has_Unchecked_Union (E);
- end if;
-
- -- If packing was requested or if the component size was set
- -- explicitly, then see if bit packing is required. This
- -- processing is only done for base types, since all the
- -- representation aspects involved are type-related. This
- -- is not just an optimization, if we start processing the
- -- subtypes, they interfere with the settings on the base
- -- type (this is because Is_Packed has a slightly different
- -- meaning before and after freezing).
-
- declare
- Csiz : Uint;
- Esiz : Uint;
-
- begin
- if (Is_Packed (E) or else Has_Pragma_Pack (E))
- and then Known_Static_RM_Size (Ctyp)
- and then not Has_Component_Size_Clause (E)
- then
- Csiz := UI_Max (RM_Size (Ctyp), 1);
-
- elsif Known_Component_Size (E) then
- Csiz := Component_Size (E);
-
- elsif not Known_Static_Esize (Ctyp) then
- Csiz := Uint_0;
-
- else
- Esiz := Esize (Ctyp);
-
- -- We can set the component size if it is less than
- -- 16, rounding it up to the next storage unit size.
-
- if Esiz <= 8 then
- Csiz := Uint_8;
- elsif Esiz <= 16 then
- Csiz := Uint_16;
- else
- Csiz := Uint_0;
- end if;
-
- -- Set component size up to match alignment if it
- -- would otherwise be less than the alignment. This
- -- deals with cases of types whose alignment exceeds
- -- their size (padded types).
-
- if Csiz /= 0 then
- declare
- A : constant Uint := Alignment_In_Bits (Ctyp);
- begin
- if Csiz < A then
- Csiz := A;
- end if;
- end;
- end if;
- end if;
-
- -- Case of component size that may result in packing
-
- if 1 <= Csiz and then Csiz <= 64 then
- declare
- Ent : constant Entity_Id :=
- First_Subtype (E);
- Pack_Pragma : constant Node_Id :=
- Get_Rep_Pragma (Ent, Name_Pack);
- Comp_Size_C : constant Node_Id :=
- Get_Attribute_Definition_Clause
- (Ent, Attribute_Component_Size);
- begin
- -- Warn if we have pack and component size so that
- -- the pack is ignored.
-
- -- Note: here we must check for the presence of a
- -- component size before checking for a Pack pragma
- -- to deal with the case where the array type is a
- -- derived type whose parent is currently private.
-
- if Present (Comp_Size_C)
- and then Has_Pragma_Pack (Ent)
- and then Warn_On_Redundant_Constructs
- then
- Error_Msg_Sloc := Sloc (Comp_Size_C);
- Error_Msg_NE
- ("?r?pragma Pack for& ignored!",
- Pack_Pragma, Ent);
- Error_Msg_N
- ("\?r?explicit component size given#!",
- Pack_Pragma);
- Set_Is_Packed (Base_Type (Ent), False);
- Set_Is_Bit_Packed_Array (Base_Type (Ent), False);
- end if;
-
- -- Set component size if not already set by a
- -- component size clause.
-
- if not Present (Comp_Size_C) then
- Set_Component_Size (E, Csiz);
- end if;
-
- -- Check for base type of 8, 16, 32 bits, where an
- -- unsigned subtype has a length one less than the
- -- base type (e.g. Natural subtype of Integer).
-
- -- In such cases, if a component size was not set
- -- explicitly, then generate a warning.
-
- if Has_Pragma_Pack (E)
- and then not Present (Comp_Size_C)
- and then
- (Csiz = 7 or else Csiz = 15 or else Csiz = 31)
- and then Esize (Base_Type (Ctyp)) = Csiz + 1
- then
- Error_Msg_Uint_1 := Csiz;
-
- if Present (Pack_Pragma) then
- Error_Msg_N
- ("??pragma Pack causes component size "
- & "to be ^!", Pack_Pragma);
- Error_Msg_N
- ("\??use Component_Size to set "
- & "desired value!", Pack_Pragma);
- end if;
- end if;
-
- -- Actual packing is not needed for 8, 16, 32, 64.
- -- Also not needed for 24 if alignment is 1.
-
- if Csiz = 8
- or else Csiz = 16
- or else Csiz = 32
- or else Csiz = 64
- or else (Csiz = 24 and then Alignment (Ctyp) = 1)
- then
- -- Here the array was requested to be packed,
- -- but the packing request had no effect, so
- -- Is_Packed is reset.
-
- -- Note: semantically this means that we lose
- -- track of the fact that a derived type
- -- inherited a pragma Pack that was non-
- -- effective, but that seems fine.
-
- -- We regard a Pack pragma as a request to set
- -- a representation characteristic, and this
- -- request may be ignored.
-
- Set_Is_Packed (Base_Type (E), False);
- Set_Is_Bit_Packed_Array (Base_Type (E), False);
-
- if Known_Static_Esize (Component_Type (E))
- and then Esize (Component_Type (E)) = Csiz
- then
- Set_Has_Non_Standard_Rep
- (Base_Type (E), False);
- end if;
-
- -- In all other cases, packing is indeed needed
-
- else
- Set_Has_Non_Standard_Rep (Base_Type (E), True);
- Set_Is_Bit_Packed_Array (Base_Type (E), True);
- Set_Is_Packed (Base_Type (E), True);
- end if;
- end;
- end if;
- end;
-
- -- Check for Atomic_Components or Aliased with unsuitable
- -- packing or explicit component size clause given.
-
- if (Has_Atomic_Components (E)
- or else Has_Aliased_Components (E))
- and then (Has_Component_Size_Clause (E)
- or else Is_Packed (E))
- then
- Alias_Atomic_Check : declare
-
- procedure Complain_CS (T : String);
- -- Outputs error messages for incorrect CS clause or
- -- pragma Pack for aliased or atomic components (T is
- -- "aliased" or "atomic");
-
- -----------------
- -- Complain_CS --
- -----------------
-
- procedure Complain_CS (T : String) is
- begin
- if Has_Component_Size_Clause (E) then
- Clause :=
- Get_Attribute_Definition_Clause
- (FS, Attribute_Component_Size);
-
- if Known_Static_Esize (Ctyp) then
- Error_Msg_N
- ("incorrect component size for "
- & T & " components", Clause);
- Error_Msg_Uint_1 := Esize (Ctyp);
- Error_Msg_N
- ("\only allowed value is^", Clause);
-
- else
- Error_Msg_N
- ("component size cannot be given for "
- & T & " components", Clause);
- end if;
-
- else
- Error_Msg_N
- ("cannot pack " & T & " components",
- Get_Rep_Pragma (FS, Name_Pack));
- end if;
-
- return;
- end Complain_CS;
-
- -- Start of processing for Alias_Atomic_Check
-
- begin
-
- -- If object size of component type isn't known, we
- -- cannot be sure so we defer to the back end.
-
- if not Known_Static_Esize (Ctyp) then
- null;
-
- -- Case where component size has no effect. First
- -- check for object size of component type multiple
- -- of the storage unit size.
-
- elsif Esize (Ctyp) mod System_Storage_Unit = 0
-
- -- OK in both packing case and component size case
- -- if RM size is known and static and the same as
- -- the object size.
-
- and then
- ((Known_Static_RM_Size (Ctyp)
- and then Esize (Ctyp) = RM_Size (Ctyp))
-
- -- Or if we have an explicit component size
- -- clause and the component size and object size
- -- are equal.
-
- or else
- (Has_Component_Size_Clause (E)
- and then Component_Size (E) = Esize (Ctyp)))
- then
- null;
-
- elsif Has_Aliased_Components (E)
- or else Is_Aliased (Ctyp)
- then
- Complain_CS ("aliased");
-
- elsif Has_Atomic_Components (E)
- or else Is_Atomic (Ctyp)
- then
- Complain_CS ("atomic");
- end if;
- end Alias_Atomic_Check;
- end if;
-
- -- Warn for case of atomic type
-
- Clause := Get_Rep_Pragma (FS, Name_Atomic);
-
- if Present (Clause)
- and then not Addressable (Component_Size (FS))
- then
- Error_Msg_NE
- ("non-atomic components of type& may not be "
- & "accessible by separate tasks??", Clause, E);
-
- if Has_Component_Size_Clause (E) then
- Error_Msg_Sloc :=
- Sloc
- (Get_Attribute_Definition_Clause
- (FS, Attribute_Component_Size));
- Error_Msg_N
- ("\because of component size clause#??",
- Clause);
-
- elsif Has_Pragma_Pack (E) then
- Error_Msg_Sloc :=
- Sloc (Get_Rep_Pragma (FS, Name_Pack));
- Error_Msg_N
- ("\because of pragma Pack#??", Clause);
- end if;
- end if;
-
- -- Check for scalar storage order
-
- if Present (Get_Attribute_Definition_Clause
- (E, Attribute_Scalar_Storage_Order))
- then
- Check_Component_Storage_Order (E, Empty);
- end if;
-
- -- Processing that is done only for subtypes
-
- else
- -- Acquire alignment from base type
-
- if Unknown_Alignment (E) then
- Set_Alignment (E, Alignment (Base_Type (E)));
- Adjust_Esize_Alignment (E);
- end if;
- end if;
-
- -- Specific checks for bit-packed arrays
-
- if Is_Bit_Packed_Array (E) then
-
- -- Check number of elements for bit packed arrays that come
- -- from source and have compile time known ranges. The
- -- bit-packed arrays circuitry does not support arrays
- -- with more than Integer'Last + 1 elements, and when this
- -- restriction is violated, causes incorrect data access.
-
- -- For the case where this is not compile time known, a
- -- run-time check should be generated???
-
- if Comes_From_Source (E) and then Is_Constrained (E) then
- declare
- Elmts : Uint;
- Index : Node_Id;
- Ilen : Node_Id;
- Ityp : Entity_Id;
-
- begin
- Elmts := Uint_1;
- Index := First_Index (E);
- while Present (Index) loop
- Ityp := Etype (Index);
-
- -- Never generate an error if any index is of a
- -- generic type. We will check this in instances.
-
- if Is_Generic_Type (Ityp) then
- Elmts := Uint_0;
- exit;
- end if;
-
- Ilen :=
- Make_Attribute_Reference (Loc,
- Prefix =>
- New_Occurrence_Of (Ityp, Loc),
- Attribute_Name => Name_Range_Length);
- Analyze_And_Resolve (Ilen);
-
- -- No attempt is made to check number of elements
- -- if not compile time known.
-
- if Nkind (Ilen) /= N_Integer_Literal then
- Elmts := Uint_0;
- exit;
- end if;
-
- Elmts := Elmts * Intval (Ilen);
- Next_Index (Index);
- end loop;
-
- if Elmts > Intval (High_Bound
- (Scalar_Range
- (Standard_Integer))) + 1
- then
- Error_Msg_N
- ("bit packed array type may not have "
- & "more than Integer''Last+1 elements", E);
- end if;
- end;
- end if;
-
- -- Check size
-
- if Known_RM_Size (E) then
- declare
- SizC : constant Node_Id := Size_Clause (E);
-
- Discard : Boolean;
- pragma Warnings (Off, Discard);
-
- begin
- -- It is not clear if it is possible to have no size
- -- clause at this stage, but it is not worth worrying
- -- about. Post error on the entity name in the size
- -- clause if present, else on the type entity itself.
-
- if Present (SizC) then
- Check_Size (Name (SizC), E, RM_Size (E), Discard);
- else
- Check_Size (E, E, RM_Size (E), Discard);
- end if;
- end;
- end if;
- end if;
-
- -- If any of the index types was an enumeration type with a
- -- non-standard rep clause, then we indicate that the array
- -- type is always packed (even if it is not bit packed).
-
- if Non_Standard_Enum then
- Set_Has_Non_Standard_Rep (Base_Type (E));
- Set_Is_Packed (Base_Type (E));
- end if;
-
- Set_Component_Alignment_If_Not_Set (E);
-
- -- If the array is packed, we must create the packed array
- -- type to be used to actually implement the type. This is
- -- only needed for real array types (not for string literal
- -- types, since they are present only for the front end).
-
- if Is_Packed (E)
- and then Ekind (E) /= E_String_Literal_Subtype
- then
- Create_Packed_Array_Type (E);
- Freeze_And_Append (Packed_Array_Type (E), N, Result);
-
- -- Size information of packed array type is copied to the
- -- array type, since this is really the representation. But
- -- do not override explicit existing size values. If the
- -- ancestor subtype is constrained the packed_array_type
- -- will be inherited from it, but the size may have been
- -- provided already, and must not be overridden either.
-
- if not Has_Size_Clause (E)
- and then
- (No (Ancestor_Subtype (E))
- or else not Has_Size_Clause (Ancestor_Subtype (E)))
- then
- Set_Esize (E, Esize (Packed_Array_Type (E)));
- Set_RM_Size (E, RM_Size (Packed_Array_Type (E)));
- end if;
-
- if not Has_Alignment_Clause (E) then
- Set_Alignment (E, Alignment (Packed_Array_Type (E)));
- end if;
- end if;
-
- -- For non-packed arrays set the alignment of the array to the
- -- alignment of the component type if it is unknown. Skip this
- -- in atomic case (atomic arrays may need larger alignments).
-
- if not Is_Packed (E)
- and then Unknown_Alignment (E)
- and then Known_Alignment (Ctyp)
- and then Known_Static_Component_Size (E)
- and then Known_Static_Esize (Ctyp)
- and then Esize (Ctyp) = Component_Size (E)
- and then not Is_Atomic (E)
- then
- Set_Alignment (E, Alignment (Component_Type (E)));
- end if;
- end;
+ Freeze_Array_Type (E);
-- For a class-wide type, the corresponding specific type is
-- frozen as well (RM 13.14(15))
@@ -4142,7 +4415,9 @@ package body Freeze is
-- for the case of a private type with record extension (we will do
-- that later when the full type is frozen).
- elsif Ekind_In (E, E_Record_Type, E_Record_Subtype) then
+ elsif Ekind_In (E, E_Record_Type, E_Record_Subtype)
+ and then not Is_Generic_Unit (Scope (E))
+ then
Freeze_Record_Type (E);
-- For a concurrent type, freeze corresponding record type. This
@@ -4446,6 +4721,7 @@ package body Freeze is
if Is_Pure_Unit_Access_Type (E)
and then (Ada_Version < Ada_2005
or else not No_Pool_Assigned (E))
+ and then not Is_Generic_Unit (Scope (E))
then
Error_Msg_N ("named access type not allowed in pure unit", E);
@@ -4518,7 +4794,7 @@ package body Freeze is
if Has_Private_Declaration (E) then
if (not Is_Record_Type (E)
- or else not Is_Immutably_Limited_Type (E))
+ or else not Is_Limited_View (E))
and then not Is_Private_Type (E)
then
Error_Msg_Name_1 := Name_Simple_Storage_Pool_Type;
diff --git a/gcc/ada/frontend.adb b/gcc/ada/frontend.adb
index 7c56ac9789f..8a64134d91d 100644
--- a/gcc/ada/frontend.adb
+++ b/gcc/ada/frontend.adb
@@ -99,13 +99,6 @@ begin
CStand.Create_Standard;
- -- If the -gnatd.H flag is present, we are only interested in the Standard
- -- package, so the frontend has done its job here.
-
- if Debug_Flag_Dot_HH then
- return;
- end if;
-
-- Check possible symbol definitions specified by -gnateD switches
Prepcomp.Process_Command_Line_Symbol_Definitions;
diff --git a/gcc/ada/g-arrspl.adb b/gcc/ada/g-arrspl.adb
index a897b13f913..9229610554f 100644
--- a/gcc/ada/g-arrspl.adb
+++ b/gcc/ada/g-arrspl.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 2002-2009, Free Software Foundation, Inc. --
+-- Copyright (C) 2002-2013, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -118,14 +118,22 @@ package body GNAT.Array_Split is
procedure Free is
new Ada.Unchecked_Deallocation (Natural, Counter);
+ Ref_Counter : Counter := S.Ref_Counter;
+
begin
- S.Ref_Counter.all := S.Ref_Counter.all - 1;
+ -- Ensure call is idempotent
+
+ S.Ref_Counter := null;
- if S.Ref_Counter.all = 0 then
- Free (S.Source);
- Free (S.Indexes);
- Free (S.Slices);
- Free (S.Ref_Counter);
+ if Ref_Counter /= null then
+ Ref_Counter.all := Ref_Counter.all - 1;
+
+ if Ref_Counter.all = 0 then
+ Free (S.Source);
+ Free (S.Indexes);
+ Free (S.Slices);
+ Free (Ref_Counter);
+ end if;
end if;
end Finalize;
diff --git a/gcc/ada/g-cppexc.adb b/gcc/ada/g-cppexc.adb
new file mode 100644
index 00000000000..d89cf0ccac3
--- /dev/null
+++ b/gcc/ada/g-cppexc.adb
@@ -0,0 +1,139 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- G N A T . C P P _ E X C E P T I O N S --
+-- --
+-- B o d y --
+-- --
+-- Copyright (C) 2013, AdaCore --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+with System;
+with System.Storage_Elements;
+with Interfaces.C; use Interfaces.C;
+with Ada.Unchecked_Conversion;
+with System.Standard_Library; use System.Standard_Library;
+
+package body GNAT.CPP_Exceptions is
+
+ -- Note: all functions prefixed by __cxa are part of the c++ ABI for
+ -- exception handling. As they are provided by the c++ library, there
+ -- must be no dependencies on it in the compiled code of this unit, but
+ -- there can be dependencies in instances. This is required to be able
+ -- to build the shared library without the c++ library.
+
+ function To_Exception_Data_Ptr is new
+ Ada.Unchecked_Conversion
+ (Exception_Id, Exception_Data_Ptr);
+ -- Convert an Exception_Id to its non-private type. This is used to get
+ -- the RTTI of a C++ exception
+
+ function Get_Exception_Machine_Occurrence
+ (X : Exception_Occurrence) return System.Address;
+ pragma Import (Ada, Get_Exception_Machine_Occurrence,
+ "__gnat_get_exception_machine_occurrence");
+ -- Imported function (from Ada.Exceptions) that returns the machine
+ -- occurrence from an exception occurrence.
+
+ -------------------------
+ -- Raise_Cpp_Exception --
+ -------------------------
+
+ procedure Raise_Cpp_Exception (Id : Exception_Id; Value : T)
+ is
+ Id_Data : constant Exception_Data_Ptr := To_Exception_Data_Ptr (Id);
+ -- Get a non-private view on the exception
+
+ type T_Acc is access all T;
+ pragma Convention (C, T_Acc);
+ -- Access type to the object compatible with C
+
+ Occ : T_Acc;
+ -- The occurrence to propagate
+
+ function cxa_allocate_exception (Size : size_t) return T_Acc;
+ pragma Import (C, cxa_allocate_exception, "__cxa_allocate_exception");
+ -- The C++ function to allocate an occurrence
+
+ procedure cxa_throw (Obj : T_Acc; Tinfo : System.Address;
+ Dest : System.Address);
+ pragma Import (C, cxa_throw, "__cxa_throw");
+ pragma No_Return (cxa_throw);
+ -- The C++ function to raise an exception
+ begin
+ -- Check the exception was imported from C++
+
+ if Id_Data.Lang /= 'C' then
+ raise Constraint_Error;
+ end if;
+
+ -- Allocate the C++ occurrence
+
+ Occ := cxa_allocate_exception (T'Size / System.Storage_Unit);
+
+ -- Set the object
+
+ Occ.all := Value;
+
+ -- Throw the exception
+
+ cxa_throw (Occ, Id_Data.Foreign_Data, System.Null_Address);
+ end Raise_Cpp_Exception;
+
+ ----------------
+ -- Get_Object --
+ ----------------
+
+ function Get_Object (X : Exception_Occurrence) return T
+ is
+ use System;
+ use System.Storage_Elements;
+
+ Unwind_Exception_Size : Natural;
+ pragma Import (C, Unwind_Exception_Size, "__gnat_unwind_exception_size");
+ -- Size in bytes of _Unwind_Exception
+
+ Exception_Addr : constant Address :=
+ Get_Exception_Machine_Occurrence (X);
+ -- Machine occurrence of X
+
+ begin
+ -- Check the machine occurrence exists
+
+ if Exception_Addr = Null_Address then
+ raise Constraint_Error;
+ end if;
+
+ declare
+ -- Import the object from the occurrence
+ Result : T;
+ pragma Import (Ada, Result);
+ for Result'Address use
+ Exception_Addr + Storage_Offset (Unwind_Exception_Size);
+ begin
+ -- And return it
+ return Result;
+ end;
+ end Get_Object;
+end GNAT.CPP_Exceptions;
diff --git a/gcc/ada/g-cppexc.ads b/gcc/ada/g-cppexc.ads
new file mode 100644
index 00000000000..60105e6f98c
--- /dev/null
+++ b/gcc/ada/g-cppexc.ads
@@ -0,0 +1,48 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- G N A T . C P P _ E X C E P T I O N S --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2013, AdaCore --
+-- --
+-- GNAT is free software; you can redistribute it and/or modify it under --
+-- terms of the GNU General Public License as published by the Free Soft- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- This package provides an interface for raising and handling C++ exceptions
+
+with Ada.Exceptions; use Ada.Exceptions;
+
+package GNAT.CPP_Exceptions is
+ generic
+ type T is private;
+ procedure Raise_Cpp_Exception (Id : Exception_Id; Value : T);
+ -- Raise a C++ exception identified by Id. Associate Value with this
+ -- occurrence. Id must refer to an exception that has the Cpp convention.
+
+ generic
+ type T is private;
+ function Get_Object (X : Exception_Occurrence) return T;
+ -- Extract the object associated with X. The exception of the occurrence
+ -- X must have a Cpp Convention.
+end GNAT.CPP_Exceptions;
diff --git a/gcc/ada/g-decstr.adb b/gcc/ada/g-decstr.adb
index a08584f22e3..255e78a2614 100644
--- a/gcc/ada/g-decstr.adb
+++ b/gcc/ada/g-decstr.adb
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 2007-2010, AdaCore --
+-- Copyright (C) 2007-2013, AdaCore --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -192,6 +192,11 @@ package body GNAT.Decode_String is
elsif (U and 2#11100000#) = 2#110_00000# then
W := U and 2#00011111#;
Get_UTF_Byte;
+
+ if W not in 16#00_0080# .. 16#00_07FF# then
+ Bad;
+ end if;
+
Result := Wide_Wide_Character'Val (W);
-- 16#00_0800#-16#00_ffff#: 1110xxxx 10xxxxxx 10xxxxxx
@@ -200,6 +205,11 @@ package body GNAT.Decode_String is
W := U and 2#00001111#;
Get_UTF_Byte;
Get_UTF_Byte;
+
+ if W not in 16#00_0800# .. 16#00_FFFF# then
+ Bad;
+ end if;
+
Result := Wide_Wide_Character'Val (W);
-- 16#01_0000#-16#10_FFFF#: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
@@ -211,6 +221,10 @@ package body GNAT.Decode_String is
Get_UTF_Byte;
end loop;
+ if W not in 16#01_0000# .. 16#10_FFFF# then
+ Bad;
+ end if;
+
Result := Wide_Wide_Character'Val (W);
-- 16#0020_0000#-16#03FF_FFFF#: 111110xx 10xxxxxx 10xxxxxx
@@ -223,6 +237,10 @@ package body GNAT.Decode_String is
Get_UTF_Byte;
end loop;
+ if W not in 16#0020_0000# .. 16#03FF_FFFF# then
+ Bad;
+ end if;
+
Result := Wide_Wide_Character'Val (W);
-- All other cases are invalid, note that this includes:
@@ -304,100 +322,10 @@ package body GNAT.Decode_String is
-------------------------
procedure Next_Wide_Character (Input : String; Ptr : in out Natural) is
+ Discard : Wide_Character;
+ pragma Unreferenced (Discard);
begin
- if Ptr < Input'First then
- Past_End;
- end if;
-
- -- Special efficient encoding for UTF-8 case
-
- if Encoding_Method = WCEM_UTF8 then
- UTF8 : declare
- U : Unsigned_32;
-
- procedure Getc;
- pragma Inline (Getc);
- -- Gets the character at Input (Ptr) and returns code in U as
- -- Unsigned_32 value. On return Ptr is bumped past the character.
-
- procedure Skip_UTF_Byte;
- pragma Inline (Skip_UTF_Byte);
- -- Skips past one encoded byte which must be 2#10xxxxxx#
-
- ----------
- -- Getc --
- ----------
-
- procedure Getc is
- begin
- if Ptr > Input'Last then
- Past_End;
- else
- U := Unsigned_32 (Character'Pos (Input (Ptr)));
- Ptr := Ptr + 1;
- end if;
- end Getc;
-
- -------------------
- -- Skip_UTF_Byte --
- -------------------
-
- procedure Skip_UTF_Byte is
- begin
- Getc;
-
- if (U and 2#11000000#) /= 2#10_000000# then
- Bad;
- end if;
- end Skip_UTF_Byte;
-
- -- Start of processing for UTF-8 case
-
- begin
- -- 16#00_0000#-16#00_007F#: 0xxxxxxx
-
- Getc;
-
- if (U and 2#10000000#) = 2#00000000# then
- return;
-
- -- 16#00_0080#-16#00_07FF#: 110xxxxx 10xxxxxx
-
- elsif (U and 2#11100000#) = 2#110_00000# then
- Skip_UTF_Byte;
-
- -- 16#00_0800#-16#00_ffff#: 1110xxxx 10xxxxxx 10xxxxxx
-
- elsif (U and 2#11110000#) = 2#1110_0000# then
- Skip_UTF_Byte;
- Skip_UTF_Byte;
-
- -- Any other code is invalid, note that this includes:
-
- -- 16#01_0000#-16#10_FFFF#: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
-
- -- 16#0020_0000#-16#03FF_FFFF#: 111110xx 10xxxxxx 10xxxxxx
- -- 10xxxxxx 10xxxxxx
-
- -- 16#0400_0000#-16#7FFF_FFFF#: 1111110x 10xxxxxx 10xxxxxx
- -- 10xxxxxx 10xxxxxx 10xxxxxx
-
- -- since Wide_Character does not allow codes > 16#FFFF#
-
- else
- Bad;
- end if;
- end UTF8;
-
- -- Non-UTF-8 case
-
- else
- declare
- Discard : Wide_Character;
- begin
- Decode_Wide_Character (Input, Ptr, Discard);
- end;
- end if;
+ Decode_Wide_Character (Input, Ptr, Discard);
end Next_Wide_Character;
------------------------------
@@ -405,110 +333,10 @@ package body GNAT.Decode_String is
------------------------------
procedure Next_Wide_Wide_Character (Input : String; Ptr : in out Natural) is
+ Discard : Wide_Wide_Character;
+ pragma Unreferenced (Discard);
begin
- -- Special efficient encoding for UTF-8 case
-
- if Encoding_Method = WCEM_UTF8 then
- UTF8 : declare
- U : Unsigned_32;
-
- procedure Getc;
- pragma Inline (Getc);
- -- Gets the character at Input (Ptr) and returns code in U as
- -- Unsigned_32 value. On return Ptr is bumped past the character.
-
- procedure Skip_UTF_Byte;
- pragma Inline (Skip_UTF_Byte);
- -- Skips past one encoded byte which must be 2#10xxxxxx#
-
- ----------
- -- Getc --
- ----------
-
- procedure Getc is
- begin
- if Ptr > Input'Last then
- Past_End;
- else
- U := Unsigned_32 (Character'Pos (Input (Ptr)));
- Ptr := Ptr + 1;
- end if;
- end Getc;
-
- -------------------
- -- Skip_UTF_Byte --
- -------------------
-
- procedure Skip_UTF_Byte is
- begin
- Getc;
-
- if (U and 2#11000000#) /= 2#10_000000# then
- Bad;
- end if;
- end Skip_UTF_Byte;
-
- -- Start of processing for UTF-8 case
-
- begin
- if Ptr < Input'First then
- Past_End;
- end if;
-
- -- 16#00_0000#-16#00_007F#: 0xxxxxxx
-
- Getc;
-
- if (U and 2#10000000#) = 2#00000000# then
- null;
-
- -- 16#00_0080#-16#00_07FF#: 110xxxxx 10xxxxxx
-
- elsif (U and 2#11100000#) = 2#110_00000# then
- Skip_UTF_Byte;
-
- -- 16#00_0800#-16#00_ffff#: 1110xxxx 10xxxxxx 10xxxxxx
-
- elsif (U and 2#11110000#) = 2#1110_0000# then
- Skip_UTF_Byte;
- Skip_UTF_Byte;
-
- -- 16#01_0000#-16#10_FFFF#: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
-
- elsif (U and 2#11111000#) = 2#11110_000# then
- for K in 1 .. 3 loop
- Skip_UTF_Byte;
- end loop;
-
- -- 16#0020_0000#-16#03FF_FFFF#: 111110xx 10xxxxxx 10xxxxxx
- -- 10xxxxxx 10xxxxxx
-
- elsif (U and 2#11111100#) = 2#111110_00# then
- for K in 1 .. 4 loop
- Skip_UTF_Byte;
- end loop;
-
- -- Any other code is invalid, note that this includes:
-
- -- 16#0400_0000#-16#7FFF_FFFF#: 1111110x 10xxxxxx 10xxxxxx
- -- 10xxxxxx 10xxxxxx 10xxxxxx
-
- -- since Wide_Wide_Character does not allow codes > 16#03FF_FFFF#
-
- else
- Bad;
- end if;
- end UTF8;
-
- -- Non-UTF-8 case
-
- else
- declare
- Discard : Wide_Wide_Character;
- begin
- Decode_Wide_Wide_Character (Input, Ptr, Discard);
- end;
- end if;
+ Decode_Wide_Wide_Character (Input, Ptr, Discard);
end Next_Wide_Wide_Character;
--------------
diff --git a/gcc/ada/g-decstr.ads b/gcc/ada/g-decstr.ads
index e4d7b7f1633..d59f10dcb20 100644
--- a/gcc/ada/g-decstr.ads
+++ b/gcc/ada/g-decstr.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 2007-2010, AdaCore --
+-- Copyright (C) 2007-2013, AdaCore --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -47,6 +47,17 @@
-- does not make any assumptions about the character coding. See also the
-- packages Ada.Wide_[Wide_]Characters.Unicode for unicode specific functions.
+-- In particular, in the case of UTF-8, all valid UTF-8 encodings, as listed
+-- in table 3.6 of the Unicode Standard, version 6.2.0, are recognized as
+-- legitimate. This includes the full range 16#0000_0000# .. 16#03FF_FFFF#.
+-- This includes codes in the range 16#D800# - 16#DFFF#. These codes all
+-- have UTF-8 encoding sequences that are well-defined (e.g. the encoding for
+-- 16#D800# is ED A0 80). But these codes do not correspond to defined Unicode
+-- characters and are thus considered to be "not well-formed" (see table 3.7
+-- of the Unicode Standard). If you need to exclude these codes, you must do
+-- that manually, e.g. use Decode_Wide_Character/Decode_Wide_String and check
+-- that the resulting code(s) are not in this range.
+
-- Note on the use of brackets encoding (WCEM_Brackets). The brackets encoding
-- method is ambiguous in the context of this package, since there is no way
-- to tell if ["1234"] is eight unencoded characters or one encoded character.
@@ -86,7 +97,6 @@ package GNAT.Decode_String is
-- will be raised.
function Decode_Wide_Wide_String (S : String) return Wide_Wide_String;
- pragma Inline (Decode_Wide_Wide_String);
-- Same as above function but for Wide_Wide_String output
procedure Decode_Wide_Wide_String
@@ -124,16 +134,17 @@ package GNAT.Decode_String is
(Input : String;
Ptr : in out Natural;
Result : out Wide_Wide_Character);
+ pragma Inline (Decode_Wide_Wide_Character);
-- Same as above procedure but with Wide_Wide_Character input
procedure Next_Wide_Character (Input : String; Ptr : in out Natural);
+ pragma Inline (Next_Wide_Character);
-- This procedure examines the input string starting at Input (Ptr), and
-- advances Ptr past one character in the encoded string, so that on return
-- Ptr points to the next encoded character. Constraint_Error is raised if
-- an invalid encoding is encountered, or the end of the string is reached
-- or if Ptr is less than String'First on entry, or if the character
- -- skipped is not a valid Wide_Character code. This call may be more
- -- efficient than calling Decode_Wide_Character and discarding the result.
+ -- skipped is not a valid Wide_Character code.
procedure Prev_Wide_Character (Input : String; Ptr : in out Natural);
-- This procedure is similar to Next_Encoded_Character except that it moves
@@ -149,8 +160,12 @@ package GNAT.Decode_String is
-- WCEM_Brackets). For all other encodings, we work by starting at the
-- beginning of the string and moving forward till Ptr is reached, which
-- is correct but slow.
+ --
+ -- Note: this routine assumes that the sequence prior to Ptr is correctly
+ -- encoded, it does not have a defined behavior if this is not the case.
procedure Next_Wide_Wide_Character (Input : String; Ptr : in out Natural);
+ pragma Inline (Next_Wide_Wide_Character);
-- Similar to Next_Wide_Character except that codes skipped must be valid
-- Wide_Wide_Character codes.
diff --git a/gcc/ada/gcc-interface/Make-lang.in b/gcc/ada/gcc-interface/Make-lang.in
index fbbb417f649..cd3676f9447 100644
--- a/gcc/ada/gcc-interface/Make-lang.in
+++ b/gcc/ada/gcc-interface/Make-lang.in
@@ -100,10 +100,27 @@ ada-warn = $(ADA_CFLAGS) $(filter-out -pedantic, $(STRICT_WARN))
# Unresolved warnings in specific files.
ada/adaint.o-warn = -Wno-error
+ada/%.o: ada/gcc-interface/%.c
+ $(COMPILE) $<
+ $(POSTCOMPILE)
+
+# Function that dumps the dependencies of an Ada object file by parsing the
+# associated ALI file. We match the lines starting with D to achieve that.
+ADA_DEPS=case $@ in \
+ *sdefault.o);; \
+ *)a="`echo $@ | sed -e 's/.o$$/.ali/'`"; \
+ echo "$@: `cat $$a | \
+ sed -ne 's;^D \([a-z0-9_\.-]*\).*;ada/\1;gp' | \
+ tr -d '\015' | tr '\n' ' '`" > $(dir $@)/$(DEPDIR)/$(patsubst %.o,%.Po,$(notdir $@));; \
+ esac;
+
.adb.o:
$(CC) -c $(ALL_ADAFLAGS) $(ADA_INCLUDES) $< $(OUTPUT_OPTION)
+ @$(ADA_DEPS)
+
.ads.o:
$(CC) -c $(ALL_ADAFLAGS) $(ADA_INCLUDES) $< $(OUTPUT_OPTION)
+ @$(ADA_DEPS)
# Define the names for selecting Ada in LANGUAGES.
ada: gnat1$(exeext) gnatbind$(exeext)
@@ -354,11 +371,14 @@ GNAT_ADA_OBJS = \
ada/s-traent.o \
ada/s-unstyp.o \
ada/s-utf_32.o \
+ ada/s-valint.o \
+ ada/s-valuns.o \
+ ada/s-valuti.o \
ada/s-wchcnv.o \
ada/s-wchcon.o \
ada/s-wchjis.o \
ada/scans.o \
- ada/scil_ll.o \
+ ada/scil_ll.o \
ada/scn.o \
ada/scng.o \
ada/scos.o \
@@ -905,9 +925,6 @@ $(check_acats_targets): check-acats%:
# Compiling object files from source files.
-# Note that dependencies on obstack.h are not written
-# because that file is not part of GCC.
-
# Ada language specific files.
ada/b_gnat1.adb : $(GNAT1_ADA_OBJS)
@@ -946,27 +963,29 @@ ada/sdefault.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
ada/s-wchcon.ads ada/system.ads ada/table.adb ada/table.ads ada/tree_io.ads \
ada/types.ads ada/unchdeal.ads ada/unchconv.ads
-ADA_TREE_H = ada/gcc-interface/ada-tree.h
-
-# Special flags - see gcc-interface/Makefile.in for the template
+# Special flags - see gcc-interface/Makefile.in for the template.
ada/a-except.o : ada/a-except.adb ada/a-except.ads
$(CC) -c $(ALL_ADAFLAGS) $(FORCE_DEBUG_ADAFLAGS) -O1 -fno-inline \
$(ADA_INCLUDES) $< $(OUTPUT_OPTION)
+ @$(ADA_DEPS)
ada/s-excdeb.o : ada/s-excdeb.adb ada/s-excdeb.ads
$(CC) -c $(ALL_ADAFLAGS) $(FORCE_DEBUG_ADAFLAGS) -O0 \
$(ADA_INCLUDES) $< $(OUTPUT_OPTION)
+ @$(ADA_DEPS)
ada/s-assert.o : ada/s-assert.adb ada/s-assert.ads
$(CC) -c $(ALL_ADAFLAGS) $(FORCE_DEBUG_ADAFLAGS) $(ADA_INCLUDES) \
$< $(OUTPUT_OPTION)
+ @$(ADA_DEPS)
ada/a-tags.o : ada/a-tags.adb ada/a-tags.ads
$(CC) -c $(ALL_ADAFLAGS) $(FORCE_DEBUG_ADAFLAGS) $(ADA_INCLUDES) \
$< $(OUTPUT_OPTION)
+ @$(ADA_DEPS)
-# dependencies for windows specific tool (mdll)
+# Dependencies for windows specific tool (mdll)
ada/mdll.o : ada/mdll.adb ada/mdll.ads ada/mdll-fil.ads ada/mdll-utl.ads
$(CC) -c $(ALL_ADAFLAGS) $(ADA_INCLUDES) $< $(OUTPUT_OPTION)
@@ -977,3539 +996,17 @@ ada/mdll-fil.o : ada/mdll-fil.adb ada/mdll.ads ada/mdll-fil.ads
ada/mdll-utl.o : ada/mdll-utl.adb ada/mdll.ads ada/mdll-utl.ads ada/sdefault.ads ada/types.ads
$(CC) -c $(ALL_ADAFLAGS) $(ADA_INCLUDES) $< $(OUTPUT_OPTION)
-ada/adadecode.o : ada/adadecode.c $(CONFIG_H) $(SYSTEM_H) ada/adadecode.h ada/adaint.h
-ada/adaint.o : ada/adaint.c $(CONFIG_H) $(SYSTEM_H) ada/adaint.h version.h
-ada/argv.o : ada/argv.c $(CONFIG_H) $(SYSTEM_H) ada/adaint.h
-ada/cio.o : ada/cio.c $(CONFIG_H) $(SYSTEM_H) ada/adaint.h
-ada/cstreams.o : ada/cstreams.c $(CONFIG_H) $(SYSTEM_H) ada/adaint.h
-ada/env.o: ada/env.c $(CONFIG_H) $(SYSTEM_H) ada/env.h
-ada/exit.o : ada/exit.c $(CONFIG_H) $(SYSTEM_H) ada/adaint.h
-ada/final.o : ada/final.c
-ada/init.o : ada/init.c $(CONFIG_H) $(SYSTEM_H) ada/adaint.h ada/raise.h
-ada/initialize.o : ada/initialize.c $(CONFIG_H) $(SYSTEM_H) ada/raise.h
-ada/link.o : ada/link.c auto-host.h
-ada/raise.o : ada/raise.c $(CONFIG_H) $(SYSTEM_H) ada/adaint.h ada/raise.h
-ada/seh_init.o: ada/seh_init.c $(CONFIG_H) $(SYSTEM_H) ada/raise.h
-ada/targext.o : ada/targext.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H)
-
-ada/cuintp.o : ada/gcc-interface/cuintp.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(TREE_H) ada/gcc-interface/ada.h ada/types.h ada/uintp.h \
- ada/atree.h ada/elists.h ada/nlists.h ada/stringt.h ada/fe.h $(ADA_TREE_H) \
- ada/gcc-interface/gigi.h
- $(COMPILER) -c $(ALL_COMPILERFLAGS) -I.. $(ALL_CPPFLAGS) $< -o $@
-
-ada/decl.o : ada/gcc-interface/decl.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(TREE_H) $(FLAGS_H) toplev.h $(TARGET_H) $(TREE_INLINE_H) \
- $(DIAGNOSTIC_CORE_H) ada/gcc-interface/ada.h ada/types.h ada/atree.h \
- ada/elists.h ada/namet.h ada/nlists.h ada/repinfo.h ada/snames.h \
- ada/stringt.h ada/uintp.h ada/fe.h ada/sinfo.h ada/einfo.h $(ADA_TREE_H) \
- ada/gcc-interface/gigi.h gt-ada-decl.h
- $(COMPILER) -c $(ALL_COMPILERFLAGS) -I.. $(ALL_CPPFLAGS) $< -o $@
-
-ada/misc.o : ada/gcc-interface/misc.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(TREE_H) $(DIAGNOSTIC_H) $(TARGET_H) $(FUNCTION_H) \
- $(FLAGS_H) debug.h toplev.h langhooks.h \
- $(LANGHOOKS_DEF_H) $(OPTS_H) $(OPTIONS_H) $(TREE_INLINE_H) \
- ada/gcc-interface/ada.h ada/adadecode.h ada/types.h ada/atree.h \
- ada/elists.h ada/namet.h ada/nlists.h ada/stringt.h ada/uintp.h ada/fe.h \
- ada/sinfo.h ada/einfo.h $(ADA_TREE_H) ada/gcc-interface/gigi.h \
- gt-ada-misc.h
- $(COMPILER) -c $(ALL_COMPILERFLAGS) -I.. $(ALL_CPPFLAGS) $< -o $@
-
-ada/targtyps.o : ada/gcc-interface/targtyps.c $(CONFIG_H) $(SYSTEM_H) \
- coretypes.h $(TM_H) $(TM_P_H) $(TREE_H) ada/gcc-interface/ada.h \
- ada/types.h ada/atree.h ada/elists.h ada/namet.h ada/nlists.h \
- ada/snames.h ada/stringt.h ada/uintp.h ada/urealp.h ada/fe.h ada/sinfo.h \
- ada/einfo.h $(ADA_TREE_H) ada/gcc-interface/gigi.h
- $(COMPILER) -c $(ALL_COMPILERFLAGS) -I.. $(ALL_CPPFLAGS) $< -o $@
-
-ada/trans.o : ada/gcc-interface/trans.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(TREE_H) $(FLAGS_H) output.h tree-iterator.h $(GIMPLE_H) \
- $(BITMAP_H) $(CGRAPH_H) $(DIAGNOSTIC_H) $(OPTS_H) $(TARGET_H) \
- ada/gcc-interface/ada.h ada/adadecode.h ada/types.h ada/atree.h \
- ada/elists.h ada/namet.h ada/nlists.h ada/snames.h ada/stringt.h \
- ada/uintp.h ada/urealp.h ada/fe.h ada/sinfo.h ada/einfo.h \
- ada/gcc-interface/gadaint.h $(ADA_TREE_H) ada/gcc-interface/gigi.h \
- gt-ada-trans.h
- $(COMPILER) -c $(ALL_COMPILERFLAGS) -I.. $(ALL_CPPFLAGS) $< -o $@
-
-ada/utils.o : ada/gcc-interface/utils.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(TREE_H) $(FLAGS_H) toplev.h $(RTL_H) output.h debug.h convert.h \
- $(TARGET_H) $(COMMON_TARGET_H) function.h langhooks.h \
- $(CGRAPH_H) $(DIAGNOSTIC_H) $(TIMEVAR_H) \
- $(TREE_DUMP_H) $(TREE_INLINE_H) tree-iterator.h \
- ada/gcc-interface/ada.h ada/types.h ada/atree.h ada/elists.h ada/namet.h \
- ada/nlists.h ada/stringt.h ada/uintp.h ada/fe.h ada/sinfo.h ada/einfo.h \
- $(ADA_TREE_H) ada/gcc-interface/gigi.h gt-ada-utils.h gtype-ada.h
- $(COMPILER) -c $(ALL_COMPILERFLAGS) -I.. $(ALL_CPPFLAGS) $< -o $@
-
-ada/utils2.o : ada/gcc-interface/utils2.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(TREE_H) $(FLAGS_H) toplev.h $(TREE_INLINE_H) \
- ada/gcc-interface/ada.h ada/types.h ada/atree.h ada/elists.h ada/namet.h \
- ada/nlists.h ada/snames.h ada/stringt.h ada/uintp.h ada/fe.h ada/sinfo.h \
- ada/einfo.h $(ADA_TREE_H) ada/gcc-interface/gigi.h
- $(COMPILER) -c $(ALL_COMPILERFLAGS) -I.. $(ALL_CPPFLAGS) $< -o $@
-
-#
-# DO NOT PUT SPECIAL RULES BELOW, THIS SECTION IS UPDATED AUTOMATICALLY
-#
-# GNAT DEPENDENCIES
-# regular dependencies
-ada/a-charac.o : ada/ada.ads ada/a-charac.ads ada/system.ads
-
-ada/a-chlat1.o : ada/ada.ads ada/a-charac.ads ada/a-chlat1.ads \
- ada/system.ads
-
-ada/a-clrefi.o : ada/ada.ads ada/a-comlin.ads ada/a-clrefi.ads \
- ada/a-clrefi.adb ada/a-except.ads ada/a-unccon.ads ada/a-uncdea.ads \
- ada/system.ads ada/s-exctab.ads ada/s-exctab.adb ada/s-htable.ads \
- ada/s-os_lib.ads ada/s-parame.ads ada/s-secsta.ads ada/s-soflin.ads \
- ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb \
- ada/s-string.ads ada/s-traent.ads
-
-ada/a-comlin.o : ada/ada.ads ada/a-comlin.ads ada/a-comlin.adb \
- ada/a-unccon.ads ada/system.ads ada/s-secsta.ads ada/s-stoele.ads \
- ada/s-stoele.adb
-
-ada/a-elchha.o : ada/ada.ads ada/a-except.ads ada/a-elchha.ads \
- ada/a-elchha.adb ada/a-unccon.ads ada/system.ads ada/s-parame.ads \
- ada/s-soflin.ads ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads \
- ada/s-stoele.adb ada/s-traent.ads
-
-ada/a-except.o : ada/ada.ads ada/a-except.ads ada/a-except.adb \
- ada/a-exexda.adb ada/a-exextr.adb ada/a-elchha.ads ada/a-excpol.adb \
- ada/a-exstat.adb ada/a-unccon.ads ada/system.ads ada/s-exctab.ads \
- ada/s-excdeb.ads ada/s-parame.ads ada/s-secsta.ads ada/s-soflin.ads \
- ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads ada/s-traent.ads
-
-ada/a-ioexce.o : ada/ada.ads ada/a-except.ads ada/a-ioexce.ads \
- ada/a-unccon.ads ada/system.ads ada/s-exctab.ads ada/s-exctab.adb \
- ada/s-htable.ads ada/s-parame.ads ada/s-soflin.ads ada/s-stache.ads \
- ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb ada/s-traent.ads
-
-ada/ada.o : ada/ada.ads ada/system.ads
-
-ada/ali-util.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/ali.ads ada/ali.adb ada/ali-util.ads \
- ada/ali-util.adb ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/binderr.ads ada/butil.ads ada/casing.ads \
- ada/csets.ads ada/debug.ads ada/einfo.ads ada/einfo.adb \
- ada/err_vars.ads ada/errout.ads ada/erroutc.ads ada/fname.ads \
- ada/fname-uf.ads ada/gnat.ads ada/g-byorma.ads ada/g-htable.ads \
- ada/gnatvsn.ads ada/hostparm.ads ada/interfac.ads ada/lib.ads \
- ada/namet.ads ada/namet.adb ada/nlists.ads ada/opt.ads ada/osint.ads \
- ada/output.ads ada/restrict.ads ada/restrict.adb ada/rident.ads \
- ada/scans.ads ada/scng.ads ada/scng.adb ada/sinfo.ads ada/sinfo.adb \
- ada/sinput.ads ada/sinput.adb ada/sinput-c.ads ada/snames.ads \
- ada/stand.ads ada/stringt.ads ada/stringt.adb ada/styleg.ads \
- ada/styleg.adb ada/stylesw.ads ada/system.ads ada/s-assert.ads \
- ada/s-carun8.ads ada/s-crc32.ads ada/s-crc32.adb ada/s-exctab.ads \
- ada/s-htable.ads ada/s-htable.adb ada/s-imenne.ads ada/s-memory.ads \
- ada/s-os_lib.ads ada/s-parame.ads ada/s-rident.ads ada/s-secsta.ads \
- ada/s-soflin.ads ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads \
- ada/s-stoele.adb ada/s-strhas.ads ada/s-string.ads ada/s-traent.ads \
- ada/s-unstyp.ads ada/s-utf_32.ads ada/s-utf_32.adb ada/s-wchcon.ads \
- ada/table.ads ada/table.adb ada/tree_io.ads ada/types.ads ada/types.adb \
- ada/uintp.ads ada/uintp.adb ada/uname.ads ada/unchconv.ads \
- ada/unchdeal.ads ada/urealp.ads ada/urealp.adb ada/widechar.ads
-
-ada/ali.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads ada/a-uncdea.ads \
- ada/ali.ads ada/ali.adb ada/alloc.ads ada/butil.ads ada/casing.ads \
- ada/debug.ads ada/fname.ads ada/gnat.ads ada/g-htable.ads \
- ada/gnatvsn.ads ada/hostparm.ads ada/interfac.ads ada/namet.ads \
- ada/namet.adb ada/opt.ads ada/osint.ads ada/output.ads ada/rident.ads \
- ada/system.ads ada/s-assert.ads ada/s-exctab.ads ada/s-exctab.adb \
- ada/s-htable.ads ada/s-htable.adb ada/s-imenne.ads ada/s-memory.ads \
- ada/s-os_lib.ads ada/s-parame.ads ada/s-rident.ads ada/s-secsta.ads \
- ada/s-soflin.ads ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads \
- ada/s-stoele.adb ada/s-strhas.ads ada/s-string.ads ada/s-traent.ads \
- ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads ada/table.adb \
- ada/tree_io.ads ada/types.ads ada/unchconv.ads ada/unchdeal.ads \
- ada/widechar.ads
-
-ada/alloc.o : ada/alloc.ads ada/system.ads
-
-ada/aspects.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/aspects.adb \
- ada/atree.ads ada/atree.adb ada/casing.ads ada/debug.ads ada/einfo.ads \
- ada/einfo.adb ada/gnat.ads ada/g-htable.ads ada/hostparm.ads \
- ada/namet.ads ada/nlists.ads ada/nlists.adb ada/opt.ads ada/output.ads \
- ada/sinfo.ads ada/sinfo.adb ada/sinput.ads ada/snames.ads ada/stand.ads \
- ada/system.ads ada/s-assert.ads ada/s-exctab.ads ada/s-htable.ads \
- ada/s-htable.adb ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads \
- ada/s-parame.ads ada/s-stalib.ads ada/s-strhas.ads ada/s-string.ads \
- ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads \
- ada/table.adb ada/tree_io.ads ada/types.ads ada/uintp.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads
-
-ada/atree.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/debug.ads ada/einfo.ads \
- ada/hostparm.ads ada/namet.ads ada/nlists.ads ada/nlists.adb \
- ada/opt.ads ada/output.ads ada/sinfo.ads ada/sinfo.adb ada/sinput.ads \
- ada/snames.ads ada/system.ads ada/s-assert.ads ada/s-exctab.ads \
- ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads \
- ada/s-stalib.ads ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads \
- ada/s-wchcon.ads ada/table.ads ada/table.adb ada/tree_io.ads \
- ada/types.ads ada/uintp.ads ada/unchconv.ads ada/unchdeal.ads \
- ada/urealp.ads
-
-ada/back_end.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/back_end.ads ada/back_end.adb ada/casing.ads \
- ada/csets.ads ada/debug.ads ada/einfo.ads ada/elists.ads \
- ada/err_vars.ads ada/errout.ads ada/erroutc.ads ada/fname.ads \
- ada/gnat.ads ada/g-byorma.ads ada/g-hesorg.ads ada/gnatvsn.ads \
- ada/hostparm.ads ada/lib.ads ada/lib.adb ada/lib-list.adb \
- ada/lib-sort.adb ada/namet.ads ada/nlists.ads ada/nlists.adb \
- ada/opt.ads ada/osint.ads ada/osint-c.ads ada/output.ads ada/scans.ads \
- ada/sinfo.ads ada/sinput.ads ada/sinput.adb ada/snames.ads \
- ada/stand.ads ada/stringt.ads ada/switch.ads ada/switch-c.ads \
- ada/system.ads ada/s-assert.ads ada/s-exctab.ads ada/s-imenne.ads \
- ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads ada/s-secsta.ads \
- ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads \
- ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads \
- ada/table.adb ada/tree_io.ads ada/types.ads ada/uintp.ads ada/uname.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads ada/widechar.ads
-
-ada/bcheck.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/ali.ads ada/ali.adb ada/ali-util.ads \
- ada/ali-util.adb ada/alloc.ads ada/atree.ads ada/bcheck.ads \
- ada/bcheck.adb ada/binderr.ads ada/butil.ads ada/casing.ads \
- ada/csets.ads ada/debug.ads ada/einfo.ads ada/err_vars.ads \
- ada/fname.ads ada/gnat.ads ada/g-htable.ads ada/gnatvsn.ads \
- ada/hostparm.ads ada/interfac.ads ada/namet.ads ada/namet.adb \
- ada/opt.ads ada/osint.ads ada/output.ads ada/restrict.ads \
- ada/rident.ads ada/scans.ads ada/scng.ads ada/scng.adb ada/sinfo.ads \
- ada/sinput.ads ada/sinput-c.ads ada/snames.ads ada/stringt.ads \
- ada/styleg.ads ada/styleg.adb ada/stylesw.ads ada/system.ads \
- ada/s-assert.ads ada/s-crc32.ads ada/s-exctab.ads ada/s-htable.ads \
- ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads \
- ada/s-rident.ads ada/s-secsta.ads ada/s-soflin.ads ada/s-stache.ads \
- ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads \
- ada/s-traent.ads ada/s-unstyp.ads ada/s-utf_32.ads ada/s-wchcon.ads \
- ada/table.ads ada/table.adb ada/tree_io.ads ada/types.ads ada/uintp.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads ada/widechar.ads
-
-ada/binde.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/ali.ads ada/ali.adb ada/alloc.ads ada/binde.ads \
- ada/binde.adb ada/binderr.ads ada/butil.ads ada/casing.ads \
- ada/debug.ads ada/fname.ads ada/gnat.ads ada/g-htable.ads \
- ada/gnatvsn.ads ada/hostparm.ads ada/interfac.ads ada/namet.ads \
- ada/namet.adb ada/opt.ads ada/osint.ads ada/output.ads ada/rident.ads \
- ada/system.ads ada/s-assert.ads ada/s-casuti.ads ada/s-exctab.ads \
- ada/s-htable.ads ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads \
- ada/s-parame.ads ada/s-rident.ads ada/s-secsta.ads ada/s-soflin.ads \
- ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb \
- ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads \
- ada/table.ads ada/table.adb ada/targparm.ads ada/tree_io.ads \
- ada/types.ads ada/unchconv.ads ada/unchdeal.ads ada/widechar.ads
-
-ada/binderr.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/binderr.ads ada/binderr.adb \
- ada/butil.ads ada/debug.ads ada/hostparm.ads ada/namet.ads ada/opt.ads \
- ada/output.ads ada/system.ads ada/s-assert.ads ada/s-exctab.ads \
- ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads ada/s-stalib.ads \
- ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads \
- ada/table.ads ada/table.adb ada/tree_io.ads ada/types.ads \
- ada/unchconv.ads ada/unchdeal.ads
-
-ada/bindgen.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/ali.ads ada/ali.adb ada/alloc.ads ada/binde.ads \
- ada/binde.adb ada/binderr.ads ada/bindgen.ads ada/bindgen.adb \
- ada/butil.ads ada/casing.ads ada/debug.ads ada/fname.ads ada/gnat.ads \
- ada/g-hesora.ads ada/g-htable.ads ada/gnatvsn.ads ada/hostparm.ads \
- ada/namet.ads ada/opt.ads ada/osint.ads ada/osint-b.ads ada/output.ads \
- ada/rident.ads ada/system.ads ada/s-assert.ads ada/s-casuti.ads \
- ada/s-exctab.ads ada/s-htable.ads ada/s-imenne.ads ada/s-memory.ads \
- ada/s-os_lib.ads ada/s-parame.ads ada/s-rident.ads ada/s-secsta.ads \
- ada/s-soflin.ads ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads \
- ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads \
- ada/s-wchcon.ads ada/table.ads ada/table.adb ada/targparm.ads \
- ada/tree_io.ads ada/types.ads ada/unchconv.ads ada/unchdeal.ads
-
-ada/bindusg.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/bindusg.ads ada/bindusg.adb \
- ada/debug.ads ada/gnatvsn.ads ada/hostparm.ads ada/namet.ads \
- ada/opt.ads ada/osint.ads ada/output.ads ada/switch.ads ada/system.ads \
- ada/s-assert.ads ada/s-exctab.ads ada/s-memory.ads ada/s-os_lib.ads \
- ada/s-parame.ads ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb \
- ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads \
- ada/table.ads ada/table.adb ada/tree_io.ads ada/types.ads \
- ada/unchconv.ads ada/unchdeal.ads
-
-ada/butil.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/butil.ads ada/butil.adb \
- ada/debug.ads ada/hostparm.ads ada/namet.ads ada/opt.ads ada/output.ads \
- ada/rident.ads ada/system.ads ada/s-assert.ads ada/s-exctab.ads \
- ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads ada/s-rident.ads \
- ada/s-stalib.ads ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads \
- ada/s-wchcon.ads ada/table.ads ada/table.adb ada/targparm.ads \
- ada/tree_io.ads ada/types.ads ada/unchconv.ads ada/unchdeal.ads
-
-ada/casing.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/casing.ads ada/casing.adb \
- ada/csets.ads ada/csets.adb ada/debug.ads ada/hostparm.ads \
- ada/namet.ads ada/opt.ads ada/output.ads ada/system.ads \
- ada/s-assert.ads ada/s-exctab.ads ada/s-memory.ads ada/s-os_lib.ads \
- ada/s-parame.ads ada/s-stalib.ads ada/s-string.ads ada/s-traent.ads \
- ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads ada/table.adb \
- ada/tree_io.ads ada/types.ads ada/unchconv.ads ada/unchdeal.ads \
- ada/widechar.ads
-
-ada/checks.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/checks.ads ada/checks.adb \
- ada/csets.ads ada/debug.ads ada/einfo.ads ada/einfo.adb ada/elists.ads \
- ada/elists.adb ada/err_vars.ads ada/errout.ads ada/erroutc.ads \
- ada/eval_fat.ads ada/exp_aggr.ads ada/exp_ch11.ads ada/exp_ch2.ads \
- ada/exp_ch4.ads ada/exp_ch6.ads ada/exp_ch7.ads ada/exp_disp.ads \
- ada/exp_dist.ads ada/exp_pakd.ads ada/exp_tss.ads ada/exp_util.ads \
- ada/exp_util.adb ada/expander.ads ada/fname.ads ada/fname-uf.ads \
- ada/freeze.ads ada/get_targ.ads ada/gnat.ads ada/g-hesorg.ads \
- ada/g-htable.ads ada/gnatvsn.ads ada/hostparm.ads ada/inline.ads \
- ada/itypes.ads ada/lib.ads ada/lib.adb ada/lib-list.adb \
- ada/lib-load.ads ada/lib-sort.adb ada/lib-util.ads ada/lib-xref.ads \
- ada/namet.ads ada/namet-sp.ads ada/nlists.ads ada/nlists.adb \
- ada/nmake.ads ada/nmake.adb ada/opt.ads ada/opt.adb ada/output.ads \
- ada/put_spark_xrefs.ads ada/restrict.ads ada/restrict.adb \
- ada/rident.ads ada/rtsfind.ads ada/rtsfind.adb ada/scans.ads \
- ada/sem.ads ada/sem_attr.ads ada/sem_aux.ads ada/sem_cat.ads \
- ada/sem_ch3.ads ada/sem_ch6.ads ada/sem_ch7.ads ada/sem_ch8.ads \
- ada/sem_disp.ads ada/sem_dist.ads ada/sem_eval.ads ada/sem_eval.adb \
- ada/sem_res.ads ada/sem_type.ads ada/sem_util.ads ada/sem_util.adb \
- ada/sem_warn.ads ada/set_targ.ads ada/sinfo.ads ada/sinfo.adb \
- ada/sinput.ads ada/snames.ads ada/sprint.ads ada/stand.ads \
- ada/stringt.ads ada/stringt.adb ada/style.ads ada/styleg.ads \
- ada/styleg.adb ada/stylesw.ads ada/system.ads ada/s-assert.ads \
- ada/s-exctab.ads ada/s-htable.ads ada/s-imenne.ads ada/s-memory.ads \
- ada/s-os_lib.ads ada/s-parame.ads ada/s-rident.ads ada/s-secsta.ads \
- ada/s-soflin.ads ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads \
- ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads \
- ada/s-wchcon.ads ada/table.ads ada/table.adb ada/targparm.ads \
- ada/tbuild.ads ada/tbuild.adb ada/tree_io.ads ada/ttypes.ads \
- ada/types.ads ada/uintp.ads ada/uintp.adb ada/uname.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads ada/urealp.adb \
- ada/validsw.ads ada/warnsw.ads ada/widechar.ads
-
-ada/comperr.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/comperr.ads ada/comperr.adb \
- ada/csets.ads ada/debug.ads ada/einfo.ads ada/err_vars.ads \
- ada/errout.ads ada/erroutc.ads ada/fname.ads ada/gnat.ads \
- ada/g-hesorg.ads ada/gnatvsn.ads ada/hostparm.ads ada/lib.ads \
- ada/lib.adb ada/lib-list.adb ada/lib-sort.adb ada/namet.ads \
- ada/nlists.ads ada/opt.ads ada/osint.ads ada/output.ads ada/output.adb \
- ada/rident.ads ada/sdefault.ads ada/sinfo.ads ada/sinfo.adb \
- ada/sinput.ads ada/snames.ads ada/sprint.ads ada/stand.ads \
- ada/stringt.ads ada/system.ads ada/s-assert.ads ada/s-exctab.ads \
- ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads \
- ada/s-rident.ads ada/s-secsta.ads ada/s-soflin.ads ada/s-stache.ads \
- ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads \
- ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads \
- ada/table.adb ada/targparm.ads ada/tree_io.ads ada/treepr.ads \
- ada/types.ads ada/uintp.ads ada/uname.ads ada/unchconv.ads \
- ada/unchdeal.ads ada/urealp.ads ada/widechar.ads
-
-ada/csets.o : ada/ada.ads ada/a-unccon.ads ada/a-uncdea.ads ada/csets.ads \
- ada/csets.adb ada/hostparm.ads ada/opt.ads ada/system.ads \
- ada/s-exctab.ads ada/s-stalib.ads ada/s-string.ads ada/s-unstyp.ads \
- ada/s-wchcon.ads ada/types.ads ada/unchconv.ads ada/unchdeal.ads
-
-ada/cstand.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/checks.ads ada/csets.ads \
- ada/cstand.ads ada/cstand.adb ada/debug.ads ada/einfo.ads ada/einfo.adb \
- ada/elists.ads ada/elists.adb ada/err_vars.ads ada/errout.ads \
- ada/erroutc.ads ada/exp_ch11.ads ada/exp_disp.ads ada/exp_tss.ads \
- ada/exp_util.ads ada/fname.ads ada/freeze.ads ada/get_targ.ads \
- ada/gnat.ads ada/g-htable.ads ada/hostparm.ads ada/interfac.ads \
- ada/layout.ads ada/lib.ads ada/lib-util.ads ada/lib-xref.ads \
- ada/namet.ads ada/namet-sp.ads ada/nlists.ads ada/nlists.adb \
- ada/nmake.ads ada/nmake.adb ada/opt.ads ada/output.ads \
- ada/put_spark_xrefs.ads ada/restrict.ads ada/rident.ads ada/rtsfind.ads \
- ada/scans.ads ada/scn.ads ada/scng.ads ada/scng.adb ada/sem.ads \
- ada/sem_attr.ads ada/sem_aux.ads ada/sem_ch8.ads ada/sem_disp.ads \
- ada/sem_eval.ads ada/sem_mech.ads ada/sem_res.ads ada/sem_type.ads \
- ada/sem_util.ads ada/sem_util.adb ada/set_targ.ads ada/sinfo.ads \
- ada/sinfo.adb ada/sinput.ads ada/snames.ads ada/stand.ads \
- ada/stringt.ads ada/style.ads ada/styleg.ads ada/styleg.adb \
- ada/stylesw.ads ada/system.ads ada/s-assert.ads ada/s-crc32.ads \
- ada/s-exctab.ads ada/s-htable.ads ada/s-imenne.ads ada/s-memory.ads \
- ada/s-os_lib.ads ada/s-parame.ads ada/s-rident.ads ada/s-secsta.ads \
- ada/s-soflin.ads ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads \
- ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads \
- ada/s-utf_32.ads ada/s-wchcon.ads ada/table.ads ada/table.adb \
- ada/targparm.ads ada/tbuild.ads ada/tree_io.ads ada/ttypes.ads \
- ada/types.ads ada/uintp.ads ada/uintp.adb ada/uname.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads ada/urealp.adb \
- ada/widechar.ads
-
-ada/debug.o : ada/debug.ads ada/debug.adb ada/system.ads
-
-ada/debug_a.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/debug.ads ada/debug_a.ads \
- ada/debug_a.adb ada/einfo.ads ada/hostparm.ads ada/namet.ads \
- ada/nlists.ads ada/opt.ads ada/output.ads ada/sinfo.ads ada/sinput.ads \
- ada/snames.ads ada/system.ads ada/s-assert.ads ada/s-exctab.ads \
- ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads \
- ada/s-stalib.ads ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads \
- ada/s-wchcon.ads ada/table.ads ada/table.adb ada/tree_io.ads \
- ada/types.ads ada/uintp.ads ada/unchconv.ads ada/unchdeal.ads \
- ada/urealp.ads
-
-ada/einfo.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/debug.ads ada/einfo.ads ada/einfo.adb \
- ada/gnat.ads ada/g-htable.ads ada/hostparm.ads ada/namet.ads \
- ada/nlists.ads ada/nlists.adb ada/opt.ads ada/output.ads ada/sinfo.ads \
- ada/sinfo.adb ada/sinput.ads ada/snames.ads ada/snames.adb \
- ada/stand.ads ada/system.ads ada/s-assert.ads ada/s-exctab.ads \
- ada/s-htable.ads ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads \
- ada/s-parame.ads ada/s-stalib.ads ada/s-string.ads ada/s-traent.ads \
- ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads ada/table.adb \
- ada/tree_io.ads ada/types.ads ada/uintp.ads ada/uintp.adb \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads ada/urealp.adb
-
-ada/elists.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/debug.ads ada/elists.ads \
- ada/elists.adb ada/hostparm.ads ada/opt.ads ada/output.ads \
- ada/system.ads ada/s-assert.ads ada/s-exctab.ads ada/s-memory.ads \
- ada/s-os_lib.ads ada/s-parame.ads ada/s-stalib.ads ada/s-string.ads \
- ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads \
- ada/table.adb ada/tree_io.ads ada/types.ads ada/unchconv.ads \
- ada/unchdeal.ads
-
-ada/err_vars.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/debug.ads ada/err_vars.ads \
- ada/hostparm.ads ada/namet.ads ada/opt.ads ada/output.ads \
- ada/system.ads ada/s-assert.ads ada/s-exctab.ads ada/s-exctab.adb \
- ada/s-htable.ads ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads \
- ada/s-soflin.ads ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads \
- ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads \
- ada/s-wchcon.ads ada/table.ads ada/table.adb ada/tree_io.ads \
- ada/types.ads ada/uintp.ads ada/unchconv.ads ada/unchdeal.ads
-
-ada/errout.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/csets.ads ada/debug.ads ada/einfo.ads \
- ada/einfo.adb ada/err_vars.ads ada/errout.ads ada/errout.adb \
- ada/erroutc.ads ada/erroutc.adb ada/fname.ads ada/gnat.ads \
- ada/g-byorma.ads ada/g-hesorg.ads ada/gnatvsn.ads ada/hostparm.ads \
- ada/lib.ads ada/lib.adb ada/lib-list.adb ada/lib-sort.adb ada/namet.ads \
- ada/nlists.ads ada/nlists.adb ada/opt.ads ada/output.ads ada/rident.ads \
- ada/scans.ads ada/sem_aux.ads ada/sinfo.ads ada/sinfo.adb \
- ada/sinput.ads ada/sinput.adb ada/snames.ads ada/stand.ads \
- ada/stringt.ads ada/stylesw.ads ada/system.ads ada/s-assert.ads \
- ada/s-exctab.ads ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads \
- ada/s-parame.ads ada/s-rident.ads ada/s-secsta.ads ada/s-soflin.ads \
- ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb \
- ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads \
- ada/table.ads ada/table.adb ada/targparm.ads ada/tree_io.ads \
- ada/types.ads ada/uintp.ads ada/uname.ads ada/unchconv.ads \
- ada/unchdeal.ads ada/urealp.ads ada/widechar.ads
-
-ada/erroutc.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/debug.ads ada/einfo.ads \
- ada/err_vars.ads ada/erroutc.ads ada/erroutc.adb ada/gnat.ads \
- ada/g-byorma.ads ada/hostparm.ads ada/interfac.ads ada/namet.ads \
- ada/namet.adb ada/nlists.ads ada/opt.ads ada/output.ads ada/output.adb \
- ada/rident.ads ada/scans.ads ada/sinfo.ads ada/sinput.ads \
- ada/sinput.adb ada/snames.ads ada/system.ads ada/s-assert.ads \
- ada/s-exctab.ads ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads \
- ada/s-parame.ads ada/s-rident.ads ada/s-secsta.ads ada/s-soflin.ads \
- ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb \
- ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads \
- ada/table.ads ada/table.adb ada/targparm.ads ada/tree_io.ads \
- ada/types.ads ada/uintp.ads ada/unchconv.ads ada/unchdeal.ads \
- ada/urealp.ads ada/widechar.ads
-
-ada/eval_fat.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/debug.ads ada/einfo.ads \
- ada/err_vars.ads ada/errout.ads ada/erroutc.ads ada/eval_fat.ads \
- ada/eval_fat.adb ada/exp_tss.ads ada/gnat.ads ada/g-htable.ads \
- ada/hostparm.ads ada/namet.ads ada/opt.ads ada/output.ads \
- ada/sem_util.ads ada/snames.ads ada/system.ads ada/s-assert.ads \
- ada/s-exctab.ads ada/s-htable.ads ada/s-memory.ads ada/s-os_lib.ads \
- ada/s-parame.ads ada/s-stalib.ads ada/s-string.ads ada/s-traent.ads \
- ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads ada/table.adb \
- ada/tree_io.ads ada/types.ads ada/uintp.ads ada/uintp.adb \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads ada/urealp.adb
-
-ada/exp_aggr.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/checks.ads ada/checks.adb \
- ada/csets.ads ada/debug.ads ada/einfo.ads ada/einfo.adb ada/elists.ads \
- ada/elists.adb ada/err_vars.ads ada/errout.ads ada/erroutc.ads \
- ada/eval_fat.ads ada/exp_aggr.ads ada/exp_aggr.adb ada/exp_ch11.ads \
- ada/exp_ch2.ads ada/exp_ch3.ads ada/exp_ch4.ads ada/exp_ch6.ads \
- ada/exp_ch7.ads ada/exp_ch9.ads ada/exp_disp.ads ada/exp_dist.ads \
- ada/exp_pakd.ads ada/exp_tss.ads ada/exp_util.ads ada/exp_util.adb \
- ada/expander.ads ada/fname.ads ada/fname-uf.ads ada/freeze.ads \
- ada/get_targ.ads ada/gnat.ads ada/g-hesorg.ads ada/g-htable.ads \
- ada/hostparm.ads ada/inline.ads ada/itypes.ads ada/lib.ads ada/lib.adb \
- ada/lib-list.adb ada/lib-load.ads ada/lib-sort.adb ada/lib-util.ads \
- ada/lib-xref.ads ada/namet.ads ada/namet-sp.ads ada/nlists.ads \
- ada/nlists.adb ada/nmake.ads ada/nmake.adb ada/opt.ads ada/output.ads \
- ada/put_spark_xrefs.ads ada/restrict.ads ada/restrict.adb \
- ada/rident.ads ada/rtsfind.ads ada/rtsfind.adb ada/scans.ads \
- ada/sem.ads ada/sem_aggr.ads ada/sem_attr.ads ada/sem_aux.ads \
- ada/sem_cat.ads ada/sem_ch3.ads ada/sem_ch6.ads ada/sem_ch7.ads \
- ada/sem_ch8.ads ada/sem_disp.ads ada/sem_dist.ads ada/sem_eval.ads \
- ada/sem_eval.adb ada/sem_res.ads ada/sem_type.ads ada/sem_util.ads \
- ada/sem_util.adb ada/sem_warn.ads ada/set_targ.ads ada/sinfo.ads \
- ada/sinfo.adb ada/sinput.ads ada/snames.ads ada/sprint.ads \
- ada/stand.ads ada/stringt.ads ada/stringt.adb ada/style.ads \
- ada/styleg.ads ada/styleg.adb ada/stylesw.ads ada/system.ads \
- ada/s-assert.ads ada/s-exctab.ads ada/s-exctab.adb ada/s-htable.ads \
- ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads \
- ada/s-rident.ads ada/s-secsta.ads ada/s-soflin.ads ada/s-stache.ads \
- ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads \
- ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads \
- ada/table.adb ada/targparm.ads ada/tbuild.ads ada/tbuild.adb \
- ada/tree_io.ads ada/ttypes.ads ada/types.ads ada/uintp.ads \
- ada/uintp.adb ada/uname.ads ada/unchconv.ads ada/unchdeal.ads \
- ada/urealp.ads ada/validsw.ads ada/warnsw.ads ada/widechar.ads
-
-ada/exp_atag.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/csets.ads ada/debug.ads ada/einfo.ads \
- ada/einfo.adb ada/elists.ads ada/elists.adb ada/err_vars.ads \
- ada/errout.ads ada/erroutc.ads ada/exp_atag.ads ada/exp_atag.adb \
- ada/exp_disp.ads ada/exp_dist.ads ada/exp_tss.ads ada/exp_util.ads \
- ada/fname.ads ada/fname-uf.ads ada/gnat.ads ada/g-htable.ads \
- ada/hostparm.ads ada/lib.ads ada/lib-load.ads ada/namet.ads \
- ada/nlists.ads ada/nlists.adb ada/nmake.ads ada/nmake.adb ada/opt.ads \
- ada/output.ads ada/restrict.ads ada/rident.ads ada/rtsfind.ads \
- ada/rtsfind.adb ada/sem.ads ada/sem_aux.ads ada/sem_aux.adb \
- ada/sem_ch7.ads ada/sem_disp.ads ada/sem_dist.ads ada/sem_util.ads \
- ada/sinfo.ads ada/sinfo.adb ada/sinput.ads ada/snames.ads ada/stand.ads \
- ada/stringt.ads ada/system.ads ada/s-assert.ads ada/s-exctab.ads \
- ada/s-htable.ads ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads \
- ada/s-parame.ads ada/s-rident.ads ada/s-soflin.ads ada/s-stache.ads \
- ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads \
- ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads \
- ada/table.adb ada/tbuild.ads ada/tbuild.adb ada/tree_io.ads \
- ada/types.ads ada/uintp.ads ada/uintp.adb ada/uname.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads
-
-ada/exp_attr.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/checks.ads ada/csets.ads ada/debug.ads \
- ada/debug_a.ads ada/einfo.ads ada/einfo.adb ada/elists.ads \
- ada/elists.adb ada/err_vars.ads ada/errout.ads ada/erroutc.ads \
- ada/exp_aggr.ads ada/exp_atag.ads ada/exp_attr.ads ada/exp_attr.adb \
- ada/exp_ch11.ads ada/exp_ch2.ads ada/exp_ch3.ads ada/exp_ch6.ads \
- ada/exp_ch7.ads ada/exp_ch9.ads ada/exp_disp.ads ada/exp_dist.ads \
- ada/exp_imgv.ads ada/exp_pakd.ads ada/exp_strm.ads ada/exp_tss.ads \
- ada/exp_util.ads ada/exp_util.adb ada/exp_vfpt.ads ada/expander.ads \
- ada/fname.ads ada/fname-uf.ads ada/freeze.ads ada/get_targ.ads \
- ada/gnat.ads ada/g-hesorg.ads ada/g-htable.ads ada/gnatvsn.ads \
- ada/hostparm.ads ada/inline.ads ada/itypes.ads ada/lib.ads ada/lib.adb \
- ada/lib-list.adb ada/lib-load.ads ada/lib-sort.adb ada/lib-util.ads \
- ada/lib-xref.ads ada/namet.ads ada/namet-sp.ads ada/nlists.ads \
- ada/nlists.adb ada/nmake.ads ada/nmake.adb ada/opt.ads ada/output.ads \
- ada/put_spark_xrefs.ads ada/restrict.ads ada/restrict.adb \
- ada/rident.ads ada/rtsfind.ads ada/scans.ads ada/sem.ads ada/sem.adb \
- ada/sem_attr.ads ada/sem_aux.ads ada/sem_ch10.ads ada/sem_ch11.ads \
- ada/sem_ch12.ads ada/sem_ch13.ads ada/sem_ch2.ads ada/sem_ch3.ads \
- ada/sem_ch4.ads ada/sem_ch5.ads ada/sem_ch6.ads ada/sem_ch7.ads \
- ada/sem_ch8.ads ada/sem_ch9.ads ada/sem_disp.ads ada/sem_eval.ads \
- ada/sem_prag.ads ada/sem_res.ads ada/sem_type.ads ada/sem_util.ads \
- ada/sem_util.adb ada/set_targ.ads ada/sinfo.ads ada/sinfo.adb \
- ada/sinput.ads ada/snames.ads ada/stand.ads ada/stringt.ads \
- ada/stringt.adb ada/style.ads ada/styleg.ads ada/styleg.adb \
- ada/stylesw.ads ada/system.ads ada/s-assert.ads ada/s-carun8.ads \
- ada/s-exctab.ads ada/s-htable.ads ada/s-imenne.ads ada/s-memory.ads \
- ada/s-os_lib.ads ada/s-parame.ads ada/s-rident.ads ada/s-secsta.ads \
- ada/s-soflin.ads ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads \
- ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads \
- ada/s-wchcon.ads ada/table.ads ada/table.adb ada/targparm.ads \
- ada/tbuild.ads ada/tbuild.adb ada/tree_io.ads ada/ttypes.ads \
- ada/types.ads ada/types.adb ada/uintp.ads ada/uintp.adb ada/uname.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads ada/validsw.ads \
- ada/warnsw.ads ada/widechar.ads
-
-ada/exp_cg.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/debug.ads ada/einfo.ads ada/einfo.adb \
- ada/elists.ads ada/elists.adb ada/exp_cg.ads ada/exp_cg.adb \
- ada/exp_dbug.ads ada/exp_disp.ads ada/exp_tss.ads ada/gnat.ads \
- ada/g-htable.ads ada/hostparm.ads ada/interfac.ads ada/lib.ads \
- ada/namet.ads ada/namet.adb ada/nlists.ads ada/opt.ads ada/output.ads \
- ada/sem_aux.ads ada/sem_aux.adb ada/sem_disp.ads ada/sem_type.ads \
- ada/sem_util.ads ada/sinfo.ads ada/sinfo.adb ada/sinput.ads \
- ada/snames.ads ada/stand.ads ada/system.ads ada/s-assert.ads \
- ada/s-exctab.ads ada/s-htable.ads ada/s-imenne.ads ada/s-memory.ads \
- ada/s-os_lib.ads ada/s-parame.ads ada/s-secsta.ads ada/s-soflin.ads \
- ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb \
- ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads \
- ada/table.ads ada/table.adb ada/tree_io.ads ada/types.ads ada/uintp.ads \
- ada/uintp.adb ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads \
- ada/widechar.ads
-
-ada/exp_ch11.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/casing.adb ada/csets.ads ada/debug.ads \
- ada/debug_a.ads ada/einfo.ads ada/einfo.adb ada/elists.ads \
- ada/elists.adb ada/err_vars.ads ada/errout.ads ada/erroutc.ads \
- ada/exp_ch11.ads ada/exp_ch11.adb ada/exp_ch7.ads ada/exp_tss.ads \
- ada/exp_util.ads ada/expander.ads ada/fname.ads ada/fname-uf.ads \
- ada/gnat.ads ada/g-htable.ads ada/hostparm.ads ada/inline.ads \
- ada/lib.ads ada/lib-load.ads ada/namet.ads ada/nlists.ads \
- ada/nlists.adb ada/nmake.ads ada/nmake.adb ada/opt.ads ada/output.ads \
- ada/restrict.ads ada/restrict.adb ada/rident.ads ada/rtsfind.ads \
- ada/sem.ads ada/sem.adb ada/sem_attr.ads ada/sem_aux.ads \
- ada/sem_ch10.ads ada/sem_ch11.ads ada/sem_ch12.ads ada/sem_ch13.ads \
- ada/sem_ch2.ads ada/sem_ch3.ads ada/sem_ch4.ads ada/sem_ch5.ads \
- ada/sem_ch6.ads ada/sem_ch7.ads ada/sem_ch8.ads ada/sem_ch9.ads \
- ada/sem_prag.ads ada/sem_res.ads ada/sem_util.ads ada/sinfo.ads \
- ada/sinfo.adb ada/sinput.ads ada/snames.ads ada/stand.ads \
- ada/stringt.ads ada/system.ads ada/s-assert.ads ada/s-exctab.ads \
- ada/s-htable.ads ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads \
- ada/s-parame.ads ada/s-rident.ads ada/s-secsta.ads ada/s-soflin.ads \
- ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb \
- ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads \
- ada/table.ads ada/table.adb ada/targparm.ads ada/tbuild.ads \
- ada/tbuild.adb ada/tree_io.ads ada/types.ads ada/uintp.ads \
- ada/uintp.adb ada/uname.ads ada/unchconv.ads ada/unchdeal.ads \
- ada/urealp.ads ada/warnsw.ads ada/widechar.ads
-
-ada/exp_ch12.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/checks.ads ada/debug.ads ada/einfo.ads \
- ada/einfo.adb ada/elists.ads ada/exp_ch12.ads ada/exp_ch12.adb \
- ada/exp_tss.ads ada/exp_util.ads ada/hostparm.ads ada/lib.ads \
- ada/namet.ads ada/nlists.ads ada/nmake.ads ada/nmake.adb ada/opt.ads \
- ada/output.ads ada/restrict.ads ada/rident.ads ada/rtsfind.ads \
- ada/sem_aux.ads ada/sinfo.ads ada/sinfo.adb ada/sinput.ads \
- ada/snames.ads ada/stand.ads ada/stringt.ads ada/system.ads \
- ada/s-assert.ads ada/s-exctab.ads ada/s-imenne.ads ada/s-memory.ads \
- ada/s-os_lib.ads ada/s-parame.ads ada/s-rident.ads ada/s-stalib.ads \
- ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads \
- ada/table.ads ada/table.adb ada/tbuild.ads ada/tbuild.adb \
- ada/tree_io.ads ada/types.ads ada/uintp.ads ada/unchconv.ads \
- ada/unchdeal.ads ada/urealp.ads
-
-ada/exp_ch13.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/checks.ads ada/debug.ads ada/einfo.ads \
- ada/einfo.adb ada/elists.ads ada/err_vars.ads ada/errout.ads \
- ada/erroutc.ads ada/exp_ch13.ads ada/exp_ch13.adb ada/exp_ch3.ads \
- ada/exp_ch6.ads ada/exp_imgv.ads ada/exp_tss.ads ada/exp_util.ads \
- ada/fname.ads ada/fname-uf.ads ada/hostparm.ads ada/lib.ads \
- ada/namet.ads ada/nlists.ads ada/nlists.adb ada/nmake.ads ada/nmake.adb \
- ada/opt.ads ada/output.ads ada/restrict.ads ada/restrict.adb \
- ada/rident.ads ada/rtsfind.ads ada/sem.ads ada/sem_aux.ads \
- ada/sem_ch7.ads ada/sem_ch8.ads ada/sem_eval.ads ada/sem_util.ads \
- ada/sinfo.ads ada/sinfo.adb ada/sinput.ads ada/snames.ads ada/stand.ads \
- ada/system.ads ada/s-assert.ads ada/s-exctab.ads ada/s-imenne.ads \
- ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads ada/s-rident.ads \
- ada/s-secsta.ads ada/s-soflin.ads ada/s-stache.ads ada/s-stalib.ads \
- ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads \
- ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads ada/table.adb \
- ada/targparm.ads ada/tbuild.ads ada/tree_io.ads ada/types.ads \
- ada/uintp.ads ada/uname.ads ada/unchconv.ads ada/unchdeal.ads \
- ada/urealp.ads ada/validsw.ads
-
-ada/exp_ch2.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/checks.ads ada/debug.ads ada/einfo.ads \
- ada/einfo.adb ada/elists.ads ada/elists.adb ada/exp_ch2.ads \
- ada/exp_ch2.adb ada/exp_smem.ads ada/exp_tss.ads ada/exp_util.ads \
- ada/hostparm.ads ada/interfac.ads ada/namet.ads ada/namet.adb \
- ada/nlists.ads ada/nmake.ads ada/nmake.adb ada/opt.ads ada/output.ads \
- ada/rtsfind.ads ada/sem.ads ada/sem_eval.ads ada/sem_res.ads \
- ada/sem_util.ads ada/sem_warn.ads ada/sinfo.ads ada/sinfo.adb \
- ada/sinput.ads ada/snames.ads ada/stand.ads ada/system.ads \
- ada/s-assert.ads ada/s-exctab.ads ada/s-imenne.ads ada/s-memory.ads \
- ada/s-os_lib.ads ada/s-parame.ads ada/s-secsta.ads ada/s-stalib.ads \
- ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads \
- ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads ada/table.adb \
- ada/tbuild.ads ada/tree_io.ads ada/types.ads ada/uintp.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads ada/widechar.ads
-
-ada/exp_ch3.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/checks.ads ada/checks.adb \
- ada/csets.ads ada/debug.ads ada/einfo.ads ada/einfo.adb ada/elists.ads \
- ada/elists.adb ada/err_vars.ads ada/errout.ads ada/erroutc.ads \
- ada/eval_fat.ads ada/exp_aggr.ads ada/exp_atag.ads ada/exp_cg.ads \
- ada/exp_ch11.ads ada/exp_ch2.ads ada/exp_ch3.ads ada/exp_ch3.adb \
- ada/exp_ch4.ads ada/exp_ch6.ads ada/exp_ch7.ads ada/exp_ch9.ads \
- ada/exp_dbug.ads ada/exp_disp.ads ada/exp_disp.adb ada/exp_dist.ads \
- ada/exp_pakd.ads ada/exp_smem.ads ada/exp_strm.ads ada/exp_tss.ads \
- ada/exp_tss.adb ada/exp_util.ads ada/exp_util.adb ada/expander.ads \
- ada/fname.ads ada/fname-uf.ads ada/freeze.ads ada/get_targ.ads \
- ada/gnat.ads ada/g-htable.ads ada/hostparm.ads ada/inline.ads \
- ada/interfac.ads ada/itypes.ads ada/layout.ads ada/lib.ads \
- ada/lib-load.ads ada/namet.ads ada/namet.adb ada/nlists.ads \
- ada/nlists.adb ada/nmake.ads ada/nmake.adb ada/opt.ads ada/output.ads \
- ada/restrict.ads ada/restrict.adb ada/rident.ads ada/rtsfind.ads \
- ada/rtsfind.adb ada/scil_ll.ads ada/sem.ads ada/sem_attr.ads \
- ada/sem_aux.ads ada/sem_aux.adb ada/sem_cat.ads ada/sem_ch3.ads \
- ada/sem_ch6.ads ada/sem_ch7.ads ada/sem_ch8.ads ada/sem_disp.ads \
- ada/sem_dist.ads ada/sem_eval.ads ada/sem_eval.adb ada/sem_mech.ads \
- ada/sem_res.ads ada/sem_scil.ads ada/sem_type.ads ada/sem_util.ads \
- ada/sem_warn.ads ada/set_targ.ads ada/sinfo.ads ada/sinfo.adb \
- ada/sinput.ads ada/snames.ads ada/sprint.ads ada/stand.ads \
- ada/stringt.ads ada/system.ads ada/s-assert.ads ada/s-exctab.ads \
- ada/s-htable.ads ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads \
- ada/s-parame.ads ada/s-rident.ads ada/s-secsta.ads ada/s-soflin.ads \
- ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb \
- ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads \
- ada/table.ads ada/table.adb ada/targparm.ads ada/tbuild.ads \
- ada/tbuild.adb ada/tree_io.ads ada/ttypes.ads ada/types.ads \
- ada/uintp.ads ada/uintp.adb ada/uname.ads ada/unchconv.ads \
- ada/unchdeal.ads ada/urealp.ads ada/validsw.ads ada/warnsw.ads \
- ada/widechar.ads
-
-ada/exp_ch4.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/checks.ads ada/checks.adb \
- ada/csets.ads ada/debug.ads ada/einfo.ads ada/einfo.adb ada/elists.ads \
- ada/elists.adb ada/err_vars.ads ada/errout.ads ada/erroutc.ads \
- ada/eval_fat.ads ada/exp_aggr.ads ada/exp_atag.ads ada/exp_ch11.ads \
- ada/exp_ch2.ads ada/exp_ch3.ads ada/exp_ch4.ads ada/exp_ch4.adb \
- ada/exp_ch6.ads ada/exp_ch7.ads ada/exp_ch9.ads ada/exp_disp.ads \
- ada/exp_fixd.ads ada/exp_intr.ads ada/exp_pakd.ads ada/exp_tss.ads \
- ada/exp_util.ads ada/exp_util.adb ada/exp_vfpt.ads ada/expander.ads \
- ada/fname.ads ada/fname-uf.ads ada/freeze.ads ada/get_targ.ads \
- ada/gnat.ads ada/g-hesorg.ads ada/g-htable.ads ada/hostparm.ads \
- ada/inline.ads ada/interfac.ads ada/itypes.ads ada/lib.ads ada/lib.adb \
- ada/lib-list.adb ada/lib-sort.adb ada/lib-util.ads ada/lib-xref.ads \
- ada/namet.ads ada/namet.adb ada/namet-sp.ads ada/nlists.ads \
- ada/nlists.adb ada/nmake.ads ada/nmake.adb ada/opt.ads ada/output.ads \
- ada/par_sco.ads ada/put_spark_xrefs.ads ada/restrict.ads \
- ada/restrict.adb ada/rident.ads ada/rtsfind.ads ada/scans.ads \
- ada/scil_ll.ads ada/sem.ads ada/sem_attr.ads ada/sem_aux.ads \
- ada/sem_aux.adb ada/sem_cat.ads ada/sem_ch13.ads ada/sem_ch3.ads \
- ada/sem_ch6.ads ada/sem_ch8.ads ada/sem_disp.ads ada/sem_eval.ads \
- ada/sem_eval.adb ada/sem_res.ads ada/sem_type.ads ada/sem_util.ads \
- ada/sem_util.adb ada/sem_warn.ads ada/set_targ.ads ada/sinfo.ads \
- ada/sinfo.adb ada/sinput.ads ada/snames.ads ada/sprint.ads \
- ada/stand.ads ada/stringt.ads ada/style.ads ada/styleg.ads \
- ada/styleg.adb ada/stylesw.ads ada/system.ads ada/s-assert.ads \
- ada/s-exctab.ads ada/s-exctab.adb ada/s-htable.ads ada/s-imenne.ads \
- ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads ada/s-rident.ads \
- ada/s-secsta.ads ada/s-soflin.ads ada/s-stache.ads ada/s-stalib.ads \
- ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads \
- ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads ada/table.adb \
- ada/targparm.ads ada/tbuild.ads ada/tbuild.adb ada/tree_io.ads \
- ada/ttypes.ads ada/types.ads ada/uintp.ads ada/uintp.adb ada/uname.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads ada/urealp.adb \
- ada/validsw.ads ada/warnsw.ads ada/widechar.ads
-
-ada/exp_ch5.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/checks.ads ada/checks.adb \
- ada/csets.ads ada/debug.ads ada/einfo.ads ada/einfo.adb ada/elists.ads \
- ada/err_vars.ads ada/errout.ads ada/erroutc.ads ada/eval_fat.ads \
- ada/exp_aggr.ads ada/exp_ch11.ads ada/exp_ch2.ads ada/exp_ch4.ads \
- ada/exp_ch5.ads ada/exp_ch5.adb ada/exp_ch6.ads ada/exp_ch7.ads \
- ada/exp_dbug.ads ada/exp_disp.ads ada/exp_pakd.ads ada/exp_tss.ads \
- ada/exp_util.ads ada/exp_util.adb ada/expander.ads ada/fname.ads \
- ada/fname-uf.ads ada/freeze.ads ada/get_targ.ads ada/gnat.ads \
- ada/g-htable.ads ada/hostparm.ads ada/inline.ads ada/itypes.ads \
- ada/lib.ads ada/lib-util.ads ada/lib-xref.ads ada/namet.ads \
- ada/namet-sp.ads ada/nlists.ads ada/nlists.adb ada/nmake.ads \
- ada/nmake.adb ada/opt.ads ada/output.ads ada/put_spark_xrefs.ads \
- ada/restrict.ads ada/restrict.adb ada/rident.ads ada/rtsfind.ads \
- ada/scans.ads ada/sem.ads ada/sem_attr.ads ada/sem_aux.ads \
- ada/sem_cat.ads ada/sem_ch13.ads ada/sem_ch3.ads ada/sem_ch6.ads \
- ada/sem_ch8.ads ada/sem_disp.ads ada/sem_eval.ads ada/sem_eval.adb \
- ada/sem_res.ads ada/sem_type.ads ada/sem_util.ads ada/sem_util.adb \
- ada/sem_warn.ads ada/set_targ.ads ada/sinfo.ads ada/sinfo.adb \
- ada/sinput.ads ada/snames.ads ada/sprint.ads ada/stand.ads \
- ada/stringt.ads ada/stringt.adb ada/style.ads ada/styleg.ads \
- ada/styleg.adb ada/stylesw.ads ada/system.ads ada/s-assert.ads \
- ada/s-exctab.ads ada/s-htable.ads ada/s-imenne.ads ada/s-memory.ads \
- ada/s-os_lib.ads ada/s-parame.ads ada/s-rident.ads ada/s-secsta.ads \
- ada/s-soflin.ads ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads \
- ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads \
- ada/s-wchcon.ads ada/table.ads ada/table.adb ada/targparm.ads \
- ada/tbuild.ads ada/tbuild.adb ada/tree_io.ads ada/ttypes.ads \
- ada/types.ads ada/uintp.ads ada/uname.ads ada/unchconv.ads \
- ada/unchdeal.ads ada/urealp.ads ada/validsw.ads ada/warnsw.ads
-
-ada/exp_ch6.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/checks.ads ada/checks.adb \
- ada/csets.ads ada/debug.ads ada/debug_a.ads ada/einfo.ads ada/einfo.adb \
- ada/elists.ads ada/elists.adb ada/err_vars.ads ada/errout.ads \
- ada/erroutc.ads ada/eval_fat.ads ada/exp_aggr.ads ada/exp_atag.ads \
- ada/exp_cg.ads ada/exp_ch11.ads ada/exp_ch2.ads ada/exp_ch3.ads \
- ada/exp_ch4.ads ada/exp_ch6.ads ada/exp_ch6.adb ada/exp_ch7.ads \
- ada/exp_ch9.ads ada/exp_dbug.ads ada/exp_disp.ads ada/exp_disp.adb \
- ada/exp_dist.ads ada/exp_intr.ads ada/exp_pakd.ads ada/exp_tss.ads \
- ada/exp_util.ads ada/exp_util.adb ada/exp_vfpt.ads ada/expander.ads \
- ada/fname.ads ada/fname-uf.ads ada/freeze.ads ada/get_targ.ads \
- ada/gnat.ads ada/g-hesorg.ads ada/g-htable.ads ada/hostparm.ads \
- ada/inline.ads ada/itypes.ads ada/layout.ads ada/lib.ads ada/lib.adb \
- ada/lib-list.adb ada/lib-load.ads ada/lib-sort.adb ada/lib-util.ads \
- ada/lib-xref.ads ada/namet.ads ada/namet-sp.ads ada/nlists.ads \
- ada/nlists.adb ada/nmake.ads ada/nmake.adb ada/opt.ads ada/output.ads \
- ada/put_spark_xrefs.ads ada/restrict.ads ada/restrict.adb \
- ada/rident.ads ada/rtsfind.ads ada/rtsfind.adb ada/scans.ads \
- ada/scil_ll.ads ada/sem.ads ada/sem.adb ada/sem_attr.ads \
- ada/sem_aux.ads ada/sem_aux.adb ada/sem_ch10.ads ada/sem_ch11.ads \
- ada/sem_ch12.ads ada/sem_ch13.ads ada/sem_ch2.ads ada/sem_ch3.ads \
- ada/sem_ch4.ads ada/sem_ch5.ads ada/sem_ch6.ads ada/sem_ch7.ads \
- ada/sem_ch8.ads ada/sem_ch9.ads ada/sem_dim.ads ada/sem_disp.ads \
- ada/sem_dist.ads ada/sem_eval.ads ada/sem_mech.ads ada/sem_prag.ads \
- ada/sem_res.ads ada/sem_scil.ads ada/sem_type.ads ada/sem_util.ads \
- ada/sem_util.adb ada/sem_warn.ads ada/set_targ.ads ada/sinfo.ads \
- ada/sinfo.adb ada/sinput.ads ada/snames.ads ada/sprint.ads \
- ada/stand.ads ada/stringt.ads ada/stringt.adb ada/style.ads \
- ada/styleg.ads ada/styleg.adb ada/stylesw.ads ada/system.ads \
- ada/s-assert.ads ada/s-exctab.ads ada/s-htable.ads ada/s-imenne.ads \
- ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads ada/s-rident.ads \
- ada/s-secsta.ads ada/s-soflin.ads ada/s-stache.ads ada/s-stalib.ads \
- ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads \
- ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads ada/table.adb \
- ada/targparm.ads ada/tbuild.ads ada/tbuild.adb ada/tree_io.ads \
- ada/ttypes.ads ada/types.ads ada/uintp.ads ada/uintp.adb ada/uname.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads ada/validsw.ads \
- ada/warnsw.ads ada/widechar.ads
-
-ada/exp_ch7.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/checks.ads ada/csets.ads ada/debug.ads \
- ada/debug_a.ads ada/einfo.ads ada/einfo.adb ada/elists.ads \
- ada/elists.adb ada/err_vars.ads ada/errout.ads ada/erroutc.ads \
- ada/exp_aggr.ads ada/exp_ch11.ads ada/exp_ch6.ads ada/exp_ch7.ads \
- ada/exp_ch7.adb ada/exp_ch9.ads ada/exp_dbug.ads ada/exp_disp.ads \
- ada/exp_dist.ads ada/exp_tss.ads ada/exp_util.ads ada/exp_util.adb \
- ada/expander.ads ada/fname.ads ada/fname-uf.ads ada/freeze.ads \
- ada/get_targ.ads ada/gnat.ads ada/g-hesorg.ads ada/g-htable.ads \
- ada/hostparm.ads ada/inline.ads ada/itypes.ads ada/lib.ads ada/lib.adb \
- ada/lib-list.adb ada/lib-load.ads ada/lib-sort.adb ada/lib-util.ads \
- ada/lib-xref.ads ada/namet.ads ada/namet-sp.ads ada/nlists.ads \
- ada/nlists.adb ada/nmake.ads ada/nmake.adb ada/opt.ads ada/output.ads \
- ada/put_spark_xrefs.ads ada/restrict.ads ada/restrict.adb \
- ada/rident.ads ada/rtsfind.ads ada/scans.ads ada/sem.ads ada/sem.adb \
- ada/sem_attr.ads ada/sem_aux.ads ada/sem_aux.adb ada/sem_ch10.ads \
- ada/sem_ch11.ads ada/sem_ch12.ads ada/sem_ch13.ads ada/sem_ch2.ads \
- ada/sem_ch3.ads ada/sem_ch4.ads ada/sem_ch5.ads ada/sem_ch6.ads \
- ada/sem_ch7.ads ada/sem_ch8.ads ada/sem_ch9.ads ada/sem_disp.ads \
- ada/sem_eval.ads ada/sem_prag.ads ada/sem_res.ads ada/sem_type.ads \
- ada/sem_util.ads ada/sem_util.adb ada/set_targ.ads ada/sinfo.ads \
- ada/sinfo.adb ada/sinput.ads ada/snames.ads ada/stand.ads \
- ada/stringt.ads ada/style.ads ada/styleg.ads ada/styleg.adb \
- ada/stylesw.ads ada/system.ads ada/s-assert.ads ada/s-exctab.ads \
- ada/s-htable.ads ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads \
- ada/s-parame.ads ada/s-rident.ads ada/s-secsta.ads ada/s-soflin.ads \
- ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb \
- ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads \
- ada/table.ads ada/table.adb ada/targparm.ads ada/tbuild.ads \
- ada/tbuild.adb ada/tree_io.ads ada/ttypes.ads ada/types.ads \
- ada/uintp.ads ada/uintp.adb ada/uname.ads ada/unchconv.ads \
- ada/unchdeal.ads ada/urealp.ads ada/validsw.ads ada/warnsw.ads \
- ada/widechar.ads
-
-ada/exp_ch8.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/checks.ads ada/debug.ads ada/einfo.ads \
- ada/einfo.adb ada/elists.ads ada/err_vars.ads ada/errout.ads \
- ada/erroutc.ads ada/exp_aggr.ads ada/exp_ch4.ads ada/exp_ch6.ads \
- ada/exp_ch7.ads ada/exp_ch8.ads ada/exp_ch8.adb ada/exp_dbug.ads \
- ada/exp_tss.ads ada/exp_util.ads ada/exp_util.adb ada/freeze.ads \
- ada/get_targ.ads ada/hostparm.ads ada/inline.ads ada/itypes.ads \
- ada/lib.ads ada/namet.ads ada/nlists.ads ada/nlists.adb ada/nmake.ads \
- ada/nmake.adb ada/opt.ads ada/output.ads ada/restrict.ads \
- ada/rident.ads ada/rtsfind.ads ada/sem.ads ada/sem_aux.ads \
- ada/sem_ch8.ads ada/sem_eval.ads ada/sem_res.ads ada/sem_type.ads \
- ada/sem_util.ads ada/set_targ.ads ada/sinfo.ads ada/sinfo.adb \
- ada/sinput.ads ada/snames.ads ada/stand.ads ada/stringt.ads \
- ada/system.ads ada/s-assert.ads ada/s-exctab.ads ada/s-imenne.ads \
- ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads ada/s-rident.ads \
- ada/s-secsta.ads ada/s-soflin.ads ada/s-stache.ads ada/s-stalib.ads \
- ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads \
- ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads ada/table.adb \
- ada/targparm.ads ada/tbuild.ads ada/tree_io.ads ada/ttypes.ads \
- ada/types.ads ada/uintp.ads ada/unchconv.ads ada/unchdeal.ads \
- ada/urealp.ads ada/validsw.ads ada/warnsw.ads
-
-ada/exp_ch9.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/checks.ads ada/csets.ads ada/debug.ads \
- ada/einfo.ads ada/einfo.adb ada/elists.ads ada/elists.adb \
- ada/err_vars.ads ada/errout.ads ada/erroutc.ads ada/exp_aggr.ads \
- ada/exp_ch11.ads ada/exp_ch3.ads ada/exp_ch6.ads ada/exp_ch7.ads \
- ada/exp_ch9.ads ada/exp_ch9.adb ada/exp_dbug.ads ada/exp_disp.ads \
- ada/exp_sel.ads ada/exp_smem.ads ada/exp_tss.ads ada/exp_util.ads \
- ada/exp_util.adb ada/fname.ads ada/fname-uf.ads ada/freeze.ads \
- ada/get_targ.ads ada/gnat.ads ada/g-htable.ads ada/gnatvsn.ads \
- ada/hostparm.ads ada/inline.ads ada/interfac.ads ada/itypes.ads \
- ada/layout.ads ada/lib.ads ada/lib-util.ads ada/lib-xref.ads \
- ada/namet.ads ada/namet.adb ada/namet-sp.ads ada/nlists.ads \
- ada/nlists.adb ada/nmake.ads ada/nmake.adb ada/opt.ads ada/opt.adb \
- ada/output.ads ada/put_spark_xrefs.ads ada/restrict.ads \
- ada/restrict.adb ada/rident.ads ada/rtsfind.ads ada/scans.ads \
- ada/sem.ads ada/sem_attr.ads ada/sem_aux.ads ada/sem_aux.adb \
- ada/sem_ch11.ads ada/sem_ch13.ads ada/sem_ch3.ads ada/sem_ch5.ads \
- ada/sem_ch6.ads ada/sem_ch8.ads ada/sem_ch9.ads ada/sem_ch9.adb \
- ada/sem_disp.ads ada/sem_elab.ads ada/sem_eval.ads ada/sem_res.ads \
- ada/sem_type.ads ada/sem_util.ads ada/sem_util.adb ada/sem_warn.ads \
- ada/set_targ.ads ada/sinfo.ads ada/sinfo.adb ada/sinput.ads \
- ada/snames.ads ada/stand.ads ada/stringt.ads ada/style.ads \
- ada/styleg.ads ada/styleg.adb ada/stylesw.ads ada/system.ads \
- ada/s-assert.ads ada/s-exctab.ads ada/s-htable.ads ada/s-imenne.ads \
- ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads ada/s-rident.ads \
- ada/s-secsta.ads ada/s-soflin.ads ada/s-stache.ads ada/s-stalib.ads \
- ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads \
- ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads ada/table.adb \
- ada/targparm.ads ada/tbuild.ads ada/tbuild.adb ada/tree_io.ads \
- ada/ttypes.ads ada/types.ads ada/uintp.ads ada/uname.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads ada/validsw.ads \
- ada/warnsw.ads ada/widechar.ads
-
-ada/exp_code.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/checks.ads ada/csets.ads ada/debug.ads \
- ada/einfo.ads ada/elists.ads ada/err_vars.ads ada/errout.ads \
- ada/erroutc.ads ada/eval_fat.ads ada/exp_ch11.ads ada/exp_code.ads \
- ada/exp_code.adb ada/exp_disp.ads ada/exp_tss.ads ada/exp_util.ads \
- ada/fname.ads ada/freeze.ads ada/get_targ.ads ada/gnat.ads \
- ada/g-hesorg.ads ada/g-htable.ads ada/hostparm.ads ada/interfac.ads \
- ada/lib.ads ada/lib.adb ada/lib-list.adb ada/lib-sort.adb \
- ada/lib-util.ads ada/lib-xref.ads ada/namet.ads ada/namet.adb \
- ada/namet-sp.ads ada/nlists.ads ada/nlists.adb ada/nmake.ads \
- ada/nmake.adb ada/opt.ads ada/output.ads ada/put_spark_xrefs.ads \
- ada/restrict.ads ada/rident.ads ada/rtsfind.ads ada/scans.ads \
- ada/sem.ads ada/sem_attr.ads ada/sem_aux.ads ada/sem_cat.ads \
- ada/sem_ch6.ads ada/sem_ch8.ads ada/sem_disp.ads ada/sem_eval.ads \
- ada/sem_eval.adb ada/sem_res.ads ada/sem_type.ads ada/sem_util.ads \
- ada/sem_util.adb ada/sem_warn.ads ada/set_targ.ads ada/sinfo.ads \
- ada/sinfo.adb ada/sinput.ads ada/snames.ads ada/stand.ads \
- ada/stringt.ads ada/stringt.adb ada/style.ads ada/styleg.ads \
- ada/styleg.adb ada/stylesw.ads ada/system.ads ada/s-assert.ads \
- ada/s-carun8.ads ada/s-exctab.ads ada/s-htable.ads ada/s-imenne.ads \
- ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads ada/s-rident.ads \
- ada/s-secsta.ads ada/s-soflin.ads ada/s-stache.ads ada/s-stalib.ads \
- ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads \
- ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads ada/table.adb \
- ada/targparm.ads ada/tbuild.ads ada/tree_io.ads ada/ttypes.ads \
- ada/types.ads ada/types.adb ada/uintp.ads ada/uname.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads ada/widechar.ads
-
-ada/exp_dbug.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/debug.ads ada/einfo.ads ada/einfo.adb \
- ada/exp_dbug.ads ada/exp_dbug.adb ada/exp_tss.ads ada/gnat.ads \
- ada/g-htable.ads ada/hostparm.ads ada/interfac.ads ada/namet.ads \
- ada/namet.adb ada/nlists.ads ada/nlists.adb ada/nmake.ads ada/nmake.adb \
- ada/opt.ads ada/output.ads ada/rident.ads ada/sem_aux.ads \
- ada/sem_eval.ads ada/sem_util.ads ada/sinfo.ads ada/sinfo.adb \
- ada/sinput.ads ada/snames.ads ada/stand.ads ada/stringt.ads \
- ada/system.ads ada/s-assert.ads ada/s-exctab.ads ada/s-htable.ads \
- ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads \
- ada/s-rident.ads ada/s-secsta.ads ada/s-soflin.ads ada/s-stache.ads \
- ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads \
- ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads \
- ada/table.adb ada/targparm.ads ada/tbuild.ads ada/tree_io.ads \
- ada/types.ads ada/uintp.ads ada/uintp.adb ada/unchconv.ads \
- ada/unchdeal.ads ada/urealp.ads ada/urealp.adb ada/widechar.ads
-
-ada/exp_disp.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/checks.ads ada/csets.ads ada/debug.ads \
- ada/einfo.ads ada/einfo.adb ada/elists.ads ada/elists.adb \
- ada/err_vars.ads ada/errout.ads ada/erroutc.ads ada/exp_aggr.ads \
- ada/exp_atag.ads ada/exp_cg.ads ada/exp_ch11.ads ada/exp_ch6.ads \
- ada/exp_ch7.ads ada/exp_dbug.ads ada/exp_disp.ads ada/exp_disp.adb \
- ada/exp_tss.ads ada/exp_tss.adb ada/exp_util.ads ada/exp_util.adb \
- ada/fname.ads ada/fname-uf.ads ada/freeze.ads ada/get_targ.ads \
- ada/gnat.ads ada/g-htable.ads ada/gnatvsn.ads ada/hostparm.ads \
- ada/inline.ads ada/interfac.ads ada/itypes.ads ada/layout.ads \
- ada/lib.ads ada/lib-util.ads ada/lib-xref.ads ada/namet.ads \
- ada/namet.adb ada/namet-sp.ads ada/nlists.ads ada/nlists.adb \
- ada/nmake.ads ada/nmake.adb ada/opt.ads ada/opt.adb ada/output.ads \
- ada/put_spark_xrefs.ads ada/restrict.ads ada/restrict.adb \
- ada/rident.ads ada/rtsfind.ads ada/scans.ads ada/scil_ll.ads \
- ada/sem.ads ada/sem_attr.ads ada/sem_aux.ads ada/sem_aux.adb \
- ada/sem_ch6.ads ada/sem_ch7.ads ada/sem_ch8.ads ada/sem_disp.ads \
- ada/sem_eval.ads ada/sem_res.ads ada/sem_type.ads ada/sem_util.ads \
- ada/sem_util.adb ada/set_targ.ads ada/sinfo.ads ada/sinfo.adb \
- ada/sinput.ads ada/snames.ads ada/stand.ads ada/stringt.ads \
- ada/stringt.adb ada/style.ads ada/styleg.ads ada/styleg.adb \
- ada/stylesw.ads ada/system.ads ada/s-assert.ads ada/s-carun8.ads \
- ada/s-exctab.ads ada/s-htable.ads ada/s-imenne.ads ada/s-memory.ads \
- ada/s-os_lib.ads ada/s-parame.ads ada/s-rident.ads ada/s-secsta.ads \
- ada/s-soflin.ads ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads \
- ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads \
- ada/s-wchcon.ads ada/table.ads ada/table.adb ada/targparm.ads \
- ada/tbuild.ads ada/tbuild.adb ada/tree_io.ads ada/ttypes.ads \
- ada/types.ads ada/types.adb ada/uintp.ads ada/uintp.adb ada/uname.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads ada/validsw.ads \
- ada/warnsw.ads ada/widechar.ads
-
-ada/exp_dist.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/csets.ads ada/debug.ads ada/einfo.ads \
- ada/einfo.adb ada/elists.ads ada/elists.adb ada/exp_atag.ads \
- ada/exp_disp.ads ada/exp_dist.ads ada/exp_dist.adb ada/exp_strm.ads \
- ada/exp_tss.ads ada/exp_util.ads ada/fname.ads ada/get_targ.ads \
- ada/gnat.ads ada/g-hesorg.ads ada/g-htable.ads ada/hostparm.ads \
- ada/inline.ads ada/lib.ads ada/lib.adb ada/lib-list.adb \
- ada/lib-sort.adb ada/namet.ads ada/nlists.ads ada/nlists.adb \
- ada/nmake.ads ada/nmake.adb ada/opt.ads ada/output.ads ada/restrict.ads \
- ada/rident.ads ada/rtsfind.ads ada/sem.ads ada/sem_aux.ads \
- ada/sem_aux.adb ada/sem_cat.ads ada/sem_ch12.ads ada/sem_ch3.ads \
- ada/sem_ch8.ads ada/sem_dist.ads ada/sem_eval.ads ada/sem_util.ads \
- ada/set_targ.ads ada/sinfo.ads ada/sinfo.adb ada/sinput.ads \
- ada/snames.ads ada/stand.ads ada/stringt.ads ada/stringt.adb \
- ada/system.ads ada/s-assert.ads ada/s-exctab.ads ada/s-htable.ads \
- ada/s-htable.adb ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads \
- ada/s-parame.ads ada/s-rident.ads ada/s-secsta.ads ada/s-soflin.ads \
- ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb \
- ada/s-strhas.ads ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads \
- ada/s-wchcon.ads ada/table.ads ada/table.adb ada/tbuild.ads \
- ada/tbuild.adb ada/tree_io.ads ada/ttypes.ads ada/types.ads \
- ada/uintp.ads ada/uintp.adb ada/uname.ads ada/unchconv.ads \
- ada/unchdeal.ads ada/urealp.ads ada/warnsw.ads ada/widechar.ads
-
-ada/exp_fixd.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/checks.ads ada/debug.ads ada/einfo.ads \
- ada/einfo.adb ada/elists.ads ada/err_vars.ads ada/errout.ads \
- ada/erroutc.ads ada/eval_fat.ads ada/exp_fixd.ads ada/exp_fixd.adb \
- ada/exp_tss.ads ada/exp_util.ads ada/freeze.ads ada/gnat.ads \
- ada/g-htable.ads ada/hostparm.ads ada/lib.ads ada/namet.ads \
- ada/nlists.ads ada/nlists.adb ada/nmake.ads ada/nmake.adb ada/opt.ads \
- ada/output.ads ada/rtsfind.ads ada/sem.ads ada/sem_aux.ads \
- ada/sem_cat.ads ada/sem_ch6.ads ada/sem_ch8.ads ada/sem_eval.ads \
- ada/sem_eval.adb ada/sem_res.ads ada/sem_type.ads ada/sem_util.ads \
- ada/sem_warn.ads ada/sinfo.ads ada/sinfo.adb ada/sinput.ads \
- ada/snames.ads ada/stand.ads ada/stringt.ads ada/system.ads \
- ada/s-assert.ads ada/s-exctab.ads ada/s-htable.ads ada/s-imenne.ads \
- ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads ada/s-soflin.ads \
- ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb \
- ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads \
- ada/table.ads ada/table.adb ada/tbuild.ads ada/tree_io.ads \
- ada/types.ads ada/uintp.ads ada/uintp.adb ada/unchconv.ads \
- ada/unchdeal.ads ada/urealp.ads ada/urealp.adb
-
-ada/exp_imgv.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/checks.ads ada/csets.ads ada/debug.ads \
- ada/einfo.ads ada/einfo.adb ada/elists.ads ada/err_vars.ads \
- ada/errout.ads ada/erroutc.ads ada/exp_dist.ads ada/exp_imgv.ads \
- ada/exp_imgv.adb ada/exp_tss.ads ada/exp_util.ads ada/fname.ads \
- ada/fname-uf.ads ada/get_targ.ads ada/gnat.ads ada/g-hesorg.ads \
- ada/g-htable.ads ada/hostparm.ads ada/lib.ads ada/lib.adb \
- ada/lib-list.adb ada/lib-load.ads ada/lib-sort.adb ada/namet.ads \
- ada/nlists.ads ada/nlists.adb ada/nmake.ads ada/nmake.adb ada/opt.ads \
- ada/output.ads ada/restrict.ads ada/rident.ads ada/rtsfind.ads \
- ada/rtsfind.adb ada/sem.ads ada/sem_aux.ads ada/sem_ch7.ads \
- ada/sem_dist.ads ada/sem_res.ads ada/sem_util.ads ada/set_targ.ads \
- ada/sinfo.ads ada/sinfo.adb ada/sinput.ads ada/snames.ads ada/stand.ads \
- ada/stringt.ads ada/stringt.adb ada/system.ads ada/s-assert.ads \
- ada/s-exctab.ads ada/s-htable.ads ada/s-imenne.ads ada/s-memory.ads \
- ada/s-os_lib.ads ada/s-parame.ads ada/s-rident.ads ada/s-secsta.ads \
- ada/s-soflin.ads ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads \
- ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads \
- ada/s-wchcon.ads ada/table.ads ada/table.adb ada/tbuild.ads \
- ada/tbuild.adb ada/tree_io.ads ada/ttypes.ads ada/types.ads \
- ada/uintp.ads ada/uintp.adb ada/uname.ads ada/unchconv.ads \
- ada/unchdeal.ads ada/urealp.ads ada/urealp.adb ada/widechar.ads
-
-ada/exp_intr.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/checks.ads ada/csets.ads ada/debug.ads \
- ada/einfo.ads ada/einfo.adb ada/elists.ads ada/elists.adb \
- ada/err_vars.ads ada/errout.ads ada/erroutc.ads ada/exp_aggr.ads \
- ada/exp_atag.ads ada/exp_ch11.ads ada/exp_ch4.ads ada/exp_ch6.ads \
- ada/exp_ch7.ads ada/exp_code.ads ada/exp_disp.ads ada/exp_fixd.ads \
- ada/exp_intr.ads ada/exp_intr.adb ada/exp_tss.ads ada/exp_util.ads \
- ada/exp_util.adb ada/fname.ads ada/fname-uf.ads ada/freeze.ads \
- ada/get_targ.ads ada/gnat.ads ada/g-byorma.ads ada/g-htable.ads \
- ada/hostparm.ads ada/inline.ads ada/interfac.ads ada/itypes.ads \
- ada/lib.ads ada/lib-util.ads ada/lib-xref.ads ada/namet.ads \
- ada/namet.adb ada/namet-sp.ads ada/nlists.ads ada/nlists.adb \
- ada/nmake.ads ada/nmake.adb ada/opt.ads ada/output.ads \
- ada/put_spark_xrefs.ads ada/restrict.ads ada/restrict.adb \
- ada/rident.ads ada/rtsfind.ads ada/scans.ads ada/sem.ads \
- ada/sem_attr.ads ada/sem_aux.ads ada/sem_ch8.ads ada/sem_disp.ads \
- ada/sem_eval.ads ada/sem_res.ads ada/sem_type.ads ada/sem_util.ads \
- ada/sem_util.adb ada/set_targ.ads ada/sinfo.ads ada/sinfo.adb \
- ada/sinput.ads ada/sinput.adb ada/snames.ads ada/stand.ads \
- ada/stringt.ads ada/style.ads ada/styleg.ads ada/styleg.adb \
- ada/stylesw.ads ada/system.ads ada/s-assert.ads ada/s-exctab.ads \
- ada/s-htable.ads ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads \
- ada/s-parame.ads ada/s-rident.ads ada/s-secsta.ads ada/s-soflin.ads \
- ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb \
- ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads \
- ada/table.ads ada/table.adb ada/targparm.ads ada/tbuild.ads \
- ada/tbuild.adb ada/tree_io.ads ada/ttypes.ads ada/types.ads \
- ada/uintp.ads ada/uintp.adb ada/uname.ads ada/unchconv.ads \
- ada/unchdeal.ads ada/urealp.ads ada/urealp.adb ada/validsw.ads \
- ada/warnsw.ads ada/widechar.ads
-
-ada/exp_pakd.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/checks.ads ada/checks.adb \
- ada/debug.ads ada/einfo.ads ada/einfo.adb ada/elists.ads \
- ada/err_vars.ads ada/errout.ads ada/erroutc.ads ada/eval_fat.ads \
- ada/exp_aggr.ads ada/exp_ch11.ads ada/exp_ch2.ads ada/exp_ch4.ads \
- ada/exp_ch6.ads ada/exp_ch7.ads ada/exp_dbug.ads ada/exp_pakd.ads \
- ada/exp_pakd.adb ada/exp_tss.ads ada/exp_util.ads ada/exp_util.adb \
- ada/expander.ads ada/freeze.ads ada/get_targ.ads ada/gnat.ads \
- ada/g-htable.ads ada/hostparm.ads ada/inline.ads ada/itypes.ads \
- ada/layout.ads ada/lib.ads ada/namet.ads ada/nlists.ads ada/nlists.adb \
- ada/nmake.ads ada/nmake.adb ada/opt.ads ada/output.ads ada/restrict.ads \
- ada/rident.ads ada/rtsfind.ads ada/sem.ads ada/sem_aux.ads \
- ada/sem_ch13.ads ada/sem_ch3.ads ada/sem_ch8.ads ada/sem_eval.ads \
- ada/sem_res.ads ada/sem_type.ads ada/sem_util.ads ada/sem_warn.ads \
- ada/set_targ.ads ada/sinfo.ads ada/sinfo.adb ada/sinput.ads \
- ada/snames.ads ada/sprint.ads ada/stand.ads ada/stringt.ads \
- ada/system.ads ada/s-assert.ads ada/s-exctab.ads ada/s-htable.ads \
- ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads \
- ada/s-rident.ads ada/s-secsta.ads ada/s-soflin.ads ada/s-stache.ads \
- ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads \
- ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads \
- ada/table.adb ada/targparm.ads ada/tbuild.ads ada/tbuild.adb \
- ada/tree_io.ads ada/ttypes.ads ada/types.ads ada/uintp.ads \
- ada/uintp.adb ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads \
- ada/validsw.ads ada/warnsw.ads
-
-ada/exp_prag.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/casing.adb ada/csets.ads ada/debug.ads \
- ada/einfo.ads ada/einfo.adb ada/err_vars.ads ada/errout.ads \
- ada/erroutc.ads ada/exp_ch11.ads ada/exp_prag.ads ada/exp_prag.adb \
- ada/exp_tss.ads ada/exp_util.ads ada/expander.ads ada/fname.ads \
- ada/fname-uf.ads ada/gnat.ads ada/g-byorma.ads ada/g-htable.ads \
- ada/hostparm.ads ada/interfac.ads ada/lib.ads ada/namet.ads \
- ada/namet.adb ada/nlists.ads ada/nlists.adb ada/nmake.ads ada/nmake.adb \
- ada/opt.ads ada/output.ads ada/restrict.ads ada/restrict.adb \
- ada/rident.ads ada/rtsfind.ads ada/scans.ads ada/sem.ads \
- ada/sem_ch8.ads ada/sem_res.ads ada/sem_util.ads ada/sinfo.ads \
- ada/sinfo.adb ada/sinput.ads ada/sinput.adb ada/snames.ads \
- ada/snames.adb ada/stand.ads ada/stringt.ads ada/stringt.adb \
- ada/system.ads ada/s-assert.ads ada/s-exctab.ads ada/s-htable.ads \
- ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads \
- ada/s-rident.ads ada/s-secsta.ads ada/s-soflin.ads ada/s-stache.ads \
- ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads \
- ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads \
- ada/table.adb ada/targparm.ads ada/tbuild.ads ada/tree_io.ads \
- ada/types.ads ada/uintp.ads ada/uintp.adb ada/uname.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads ada/widechar.ads
-
-ada/exp_sel.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/atree.ads ada/debug.ads \
- ada/einfo.ads ada/einfo.adb ada/elists.ads ada/exp_sel.ads \
- ada/exp_sel.adb ada/hostparm.ads ada/lib.ads ada/namet.ads \
- ada/nlists.ads ada/nlists.adb ada/nmake.ads ada/nmake.adb ada/opt.ads \
- ada/output.ads ada/restrict.ads ada/rident.ads ada/rtsfind.ads \
- ada/sem_aux.ads ada/sinfo.ads ada/sinfo.adb ada/snames.ads \
- ada/stand.ads ada/stringt.ads ada/system.ads ada/s-assert.ads \
- ada/s-exctab.ads ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads \
- ada/s-parame.ads ada/s-rident.ads ada/s-stalib.ads ada/s-string.ads \
- ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads \
- ada/table.adb ada/tbuild.ads ada/tbuild.adb ada/tree_io.ads \
- ada/types.ads ada/uintp.ads ada/unchconv.ads ada/unchdeal.ads \
- ada/urealp.ads
-
-ada/exp_smem.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/debug.ads ada/einfo.ads ada/einfo.adb \
- ada/exp_ch9.ads ada/exp_smem.ads ada/exp_smem.adb ada/exp_tss.ads \
- ada/exp_util.ads ada/hostparm.ads ada/namet.ads ada/nlists.ads \
- ada/nlists.adb ada/nmake.ads ada/nmake.adb ada/opt.ads ada/output.ads \
- ada/rtsfind.ads ada/sem.ads ada/sem_aux.ads ada/sem_util.ads \
- ada/sinfo.ads ada/sinfo.adb ada/sinput.ads ada/snames.ads ada/stand.ads \
- ada/stringt.ads ada/stringt.adb ada/system.ads ada/s-assert.ads \
- ada/s-exctab.ads ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads \
- ada/s-parame.ads ada/s-stalib.ads ada/s-string.ads ada/s-traent.ads \
- ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads ada/table.adb \
- ada/tbuild.ads ada/tree_io.ads ada/types.ads ada/uintp.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads
-
-ada/exp_spark.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/debug.ads ada/einfo.ads ada/einfo.adb \
- ada/exp_attr.ads ada/exp_ch4.ads ada/exp_ch6.ads ada/exp_dbug.ads \
- ada/exp_spark.ads ada/exp_spark.adb ada/exp_tss.ads ada/exp_util.ads \
- ada/hostparm.ads ada/namet.ads ada/nlists.ads ada/opt.ads \
- ada/output.ads ada/rtsfind.ads ada/sem_aux.ads ada/sem_aux.adb \
- ada/sem_res.ads ada/sem_util.ads ada/sinfo.ads ada/sinfo.adb \
- ada/sinput.ads ada/snames.ads ada/stand.ads ada/system.ads \
- ada/s-assert.ads ada/s-exctab.ads ada/s-imenne.ads ada/s-memory.ads \
- ada/s-os_lib.ads ada/s-parame.ads ada/s-soflin.ads ada/s-stache.ads \
- ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads \
- ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads \
- ada/table.adb ada/tbuild.ads ada/tree_io.ads ada/types.ads \
- ada/uintp.ads ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads
-
-ada/exp_strm.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/debug.ads ada/einfo.ads ada/einfo.adb \
- ada/elists.ads ada/elists.adb ada/exp_strm.ads ada/exp_strm.adb \
- ada/exp_tss.ads ada/exp_util.ads ada/get_targ.ads ada/gnat.ads \
- ada/g-htable.ads ada/hostparm.ads ada/lib.ads ada/namet.ads \
- ada/nlists.ads ada/nlists.adb ada/nmake.ads ada/nmake.adb ada/opt.ads \
- ada/output.ads ada/restrict.ads ada/rident.ads ada/rtsfind.ads \
- ada/sem_aux.ads ada/sem_util.ads ada/set_targ.ads ada/sinfo.ads \
- ada/sinfo.adb ada/sinput.ads ada/snames.ads ada/stand.ads \
- ada/stringt.ads ada/system.ads ada/s-assert.ads ada/s-exctab.ads \
- ada/s-htable.ads ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads \
- ada/s-parame.ads ada/s-rident.ads ada/s-stalib.ads ada/s-string.ads \
- ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads \
- ada/table.adb ada/tbuild.ads ada/tbuild.adb ada/tree_io.ads \
- ada/ttypes.ads ada/types.ads ada/uintp.ads ada/uintp.adb \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads
-
-ada/exp_tss.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/csets.ads ada/debug.ads ada/einfo.ads \
- ada/einfo.adb ada/elists.ads ada/elists.adb ada/err_vars.ads \
- ada/errout.ads ada/erroutc.ads ada/exp_tss.ads ada/exp_tss.adb \
- ada/exp_util.ads ada/fname.ads ada/fname-uf.ads ada/gnat.ads \
- ada/g-hesorg.ads ada/hostparm.ads ada/interfac.ads ada/lib.ads \
- ada/lib.adb ada/lib-list.adb ada/lib-sort.adb ada/namet.ads \
- ada/namet.adb ada/nlists.ads ada/nlists.adb ada/opt.ads ada/output.ads \
- ada/restrict.ads ada/restrict.adb ada/rident.ads ada/rtsfind.ads \
- ada/sem_aux.ads ada/sem_util.ads ada/sinfo.ads ada/sinfo.adb \
- ada/sinput.ads ada/snames.ads ada/stand.ads ada/stringt.ads \
- ada/system.ads ada/s-assert.ads ada/s-exctab.ads ada/s-imenne.ads \
- ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads ada/s-rident.ads \
- ada/s-secsta.ads ada/s-soflin.ads ada/s-stache.ads ada/s-stalib.ads \
- ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads \
- ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads ada/table.adb \
- ada/tree_io.ads ada/types.ads ada/uintp.ads ada/uname.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads ada/widechar.ads
-
-ada/exp_util.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/casing.adb ada/checks.ads \
- ada/csets.ads ada/debug.ads ada/debug_a.ads ada/einfo.ads ada/einfo.adb \
- ada/elists.ads ada/elists.adb ada/err_vars.ads ada/errout.ads \
- ada/erroutc.ads ada/eval_fat.ads ada/exp_aggr.ads ada/exp_ch6.ads \
- ada/exp_ch7.ads ada/exp_tss.ads ada/exp_util.ads ada/exp_util.adb \
- ada/expander.ads ada/fname.ads ada/fname-uf.ads ada/freeze.ads \
- ada/get_targ.ads ada/gnat.ads ada/g-hesorg.ads ada/g-htable.ads \
- ada/hostparm.ads ada/inline.ads ada/interfac.ads ada/itypes.ads \
- ada/lib.ads ada/lib.adb ada/lib-list.adb ada/lib-load.ads \
- ada/lib-sort.adb ada/namet.ads ada/namet.adb ada/nlists.ads \
- ada/nlists.adb ada/nmake.ads ada/nmake.adb ada/opt.ads ada/output.ads \
- ada/restrict.ads ada/restrict.adb ada/rident.ads ada/rtsfind.ads \
- ada/sem.ads ada/sem.adb ada/sem_attr.ads ada/sem_aux.ads \
- ada/sem_cat.ads ada/sem_ch10.ads ada/sem_ch11.ads ada/sem_ch12.ads \
- ada/sem_ch13.ads ada/sem_ch2.ads ada/sem_ch3.ads ada/sem_ch4.ads \
- ada/sem_ch5.ads ada/sem_ch6.ads ada/sem_ch7.ads ada/sem_ch8.ads \
- ada/sem_ch9.ads ada/sem_eval.ads ada/sem_eval.adb ada/sem_prag.ads \
- ada/sem_res.ads ada/sem_type.ads ada/sem_util.ads ada/sem_warn.ads \
- ada/set_targ.ads ada/sinfo.ads ada/sinfo.adb ada/sinput.ads \
- ada/snames.ads ada/stand.ads ada/stringt.ads ada/stringt.adb \
- ada/system.ads ada/s-assert.ads ada/s-carun8.ads ada/s-exctab.ads \
- ada/s-htable.ads ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads \
- ada/s-parame.ads ada/s-rident.ads ada/s-secsta.ads ada/s-soflin.ads \
- ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb \
- ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads \
- ada/table.ads ada/table.adb ada/targparm.ads ada/tbuild.ads \
- ada/tbuild.adb ada/tree_io.ads ada/ttypes.ads ada/types.ads \
- ada/types.adb ada/uintp.ads ada/uintp.adb ada/uname.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads ada/urealp.adb \
- ada/validsw.ads ada/warnsw.ads ada/widechar.ads
-
-ada/exp_vfpt.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/debug.ads ada/einfo.ads ada/einfo.adb \
- ada/eval_fat.ads ada/exp_vfpt.ads ada/exp_vfpt.adb ada/gnat.ads \
- ada/g-htable.ads ada/hostparm.ads ada/namet.ads ada/nlists.ads \
- ada/nlists.adb ada/nmake.ads ada/nmake.adb ada/opt.ads ada/output.ads \
- ada/rtsfind.ads ada/sem_res.ads ada/sinfo.ads ada/sinfo.adb \
- ada/sinput.ads ada/snames.ads ada/stand.ads ada/system.ads \
- ada/s-assert.ads ada/s-exctab.ads ada/s-htable.ads ada/s-imenne.ads \
- ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads ada/s-stalib.ads \
- ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads \
- ada/table.ads ada/table.adb ada/tbuild.ads ada/tree_io.ads \
- ada/types.ads ada/uintp.ads ada/uintp.adb ada/unchconv.ads \
- ada/unchdeal.ads ada/urealp.ads ada/urealp.adb
-
-ada/expander.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/debug.ads ada/debug_a.ads \
- ada/debug_a.adb ada/einfo.ads ada/elists.ads ada/exp_aggr.ads \
- ada/exp_attr.ads ada/exp_ch11.ads ada/exp_ch12.ads ada/exp_ch13.ads \
- ada/exp_ch2.ads ada/exp_ch3.ads ada/exp_ch4.ads ada/exp_ch5.ads \
- ada/exp_ch6.ads ada/exp_ch7.ads ada/exp_ch8.ads ada/exp_ch9.ads \
- ada/exp_prag.ads ada/exp_spark.ads ada/exp_tss.ads ada/expander.ads \
- ada/expander.adb ada/fname.ads ada/hostparm.ads ada/inline.ads \
- ada/lib.ads ada/lib-load.ads ada/namet.ads ada/nlists.ads ada/opt.ads \
- ada/output.ads ada/restrict.ads ada/rident.ads ada/rtsfind.ads \
- ada/sem.ads ada/sem.adb ada/sem_attr.ads ada/sem_aux.ads \
- ada/sem_ch10.ads ada/sem_ch11.ads ada/sem_ch12.ads ada/sem_ch13.ads \
- ada/sem_ch2.ads ada/sem_ch3.ads ada/sem_ch4.ads ada/sem_ch5.ads \
- ada/sem_ch6.ads ada/sem_ch7.ads ada/sem_ch8.ads ada/sem_ch9.ads \
- ada/sem_prag.ads ada/sem_util.ads ada/sinfo.ads ada/sinput.ads \
- ada/snames.ads ada/stand.ads ada/system.ads ada/s-assert.ads \
- ada/s-exctab.ads ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads \
- ada/s-parame.ads ada/s-rident.ads ada/s-soflin.ads ada/s-stache.ads \
- ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads \
- ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads \
- ada/table.adb ada/tree_io.ads ada/types.ads ada/uintp.ads ada/uname.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads ada/warnsw.ads
-
-ada/fmap.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/debug.ads ada/fmap.ads ada/fmap.adb \
- ada/gnat.ads ada/g-htable.ads ada/hostparm.ads ada/namet.ads \
- ada/opt.ads ada/osint.ads ada/output.ads ada/system.ads \
- ada/s-assert.ads ada/s-exctab.ads ada/s-htable.ads ada/s-htable.adb \
- ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads ada/s-stalib.ads \
- ada/s-stoele.ads ada/s-stoele.adb ada/s-strhas.ads ada/s-string.ads \
- ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads \
- ada/table.adb ada/tree_io.ads ada/types.ads ada/unchconv.ads \
- ada/unchdeal.ads
-
-ada/fname-uf.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/casing.ads ada/debug.ads \
- ada/fmap.ads ada/fname.ads ada/fname-uf.ads ada/fname-uf.adb \
- ada/gnat.ads ada/g-htable.ads ada/hostparm.ads ada/krunch.ads \
- ada/namet.ads ada/opt.ads ada/osint.ads ada/output.ads ada/rident.ads \
- ada/system.ads ada/s-assert.ads ada/s-exctab.ads ada/s-htable.ads \
- ada/s-htable.adb ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads \
- ada/s-rident.ads ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb \
- ada/s-strhas.ads ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads \
- ada/s-wchcon.ads ada/table.ads ada/table.adb ada/targparm.ads \
- ada/tree_io.ads ada/types.ads ada/uname.ads ada/unchconv.ads \
- ada/unchdeal.ads ada/widechar.ads
-
-ada/fname.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/debug.ads ada/fname.ads \
- ada/fname.adb ada/hostparm.ads ada/namet.ads ada/opt.ads ada/output.ads \
- ada/system.ads ada/s-assert.ads ada/s-exctab.ads ada/s-memory.ads \
- ada/s-os_lib.ads ada/s-parame.ads ada/s-stalib.ads ada/s-string.ads \
- ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads \
- ada/table.adb ada/tree_io.ads ada/types.ads ada/unchconv.ads \
- ada/unchdeal.ads
-
-ada/freeze.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/checks.ads ada/csets.ads ada/debug.ads \
- ada/debug_a.ads ada/einfo.ads ada/einfo.adb ada/elists.ads \
- ada/elists.adb ada/err_vars.ads ada/errout.ads ada/erroutc.ads \
- ada/exp_aggr.ads ada/exp_ch11.ads ada/exp_ch3.ads ada/exp_ch6.ads \
- ada/exp_ch7.ads ada/exp_disp.ads ada/exp_pakd.ads ada/exp_tss.ads \
- ada/exp_util.ads ada/exp_util.adb ada/expander.ads ada/fname.ads \
- ada/freeze.ads ada/freeze.adb ada/get_targ.ads ada/gnat.ads \
- ada/g-hesorg.ads ada/g-htable.ads ada/hostparm.ads ada/inline.ads \
- ada/interfac.ads ada/itypes.ads ada/layout.ads ada/lib.ads ada/lib.adb \
- ada/lib-list.adb ada/lib-load.ads ada/lib-sort.adb ada/lib-util.ads \
- ada/lib-xref.ads ada/namet.ads ada/namet.adb ada/namet-sp.ads \
- ada/nlists.ads ada/nlists.adb ada/nmake.ads ada/nmake.adb ada/opt.ads \
- ada/output.ads ada/put_spark_xrefs.ads ada/restrict.ads ada/rident.ads \
- ada/rtsfind.ads ada/scans.ads ada/sem.ads ada/sem.adb ada/sem_aggr.ads \
- ada/sem_attr.ads ada/sem_aux.ads ada/sem_aux.adb ada/sem_cat.ads \
- ada/sem_ch10.ads ada/sem_ch11.ads ada/sem_ch12.ads ada/sem_ch13.ads \
- ada/sem_ch2.ads ada/sem_ch3.ads ada/sem_ch4.ads ada/sem_ch5.ads \
- ada/sem_ch6.ads ada/sem_ch7.ads ada/sem_ch8.ads ada/sem_ch9.ads \
- ada/sem_dim.ads ada/sem_disp.ads ada/sem_dist.ads ada/sem_elab.ads \
- ada/sem_elim.ads ada/sem_eval.ads ada/sem_intr.ads ada/sem_mech.ads \
- ada/sem_prag.ads ada/sem_res.ads ada/sem_res.adb ada/sem_type.ads \
- ada/sem_util.ads ada/sem_util.adb ada/sem_warn.ads ada/set_targ.ads \
- ada/sinfo.ads ada/sinfo.adb ada/sinfo-cn.ads ada/sinput.ads \
- ada/snames.ads ada/stand.ads ada/stringt.ads ada/style.ads \
- ada/styleg.ads ada/styleg.adb ada/stylesw.ads ada/system.ads \
- ada/s-assert.ads ada/s-exctab.ads ada/s-exctab.adb ada/s-htable.ads \
- ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads \
- ada/s-rident.ads ada/s-secsta.ads ada/s-soflin.ads ada/s-stache.ads \
- ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads \
- ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads \
- ada/table.adb ada/targparm.ads ada/tbuild.ads ada/tree_io.ads \
- ada/ttypes.ads ada/types.ads ada/uintp.ads ada/uintp.adb ada/uname.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads ada/validsw.ads \
- ada/warnsw.ads ada/widechar.ads
-
-ada/frontend.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/checks.ads ada/csets.ads \
- ada/cstand.ads ada/debug.ads ada/einfo.ads ada/elists.ads \
- ada/err_vars.ads ada/errout.ads ada/erroutc.ads ada/exp_dbug.ads \
- ada/fmap.ads ada/fname.ads ada/fname-uf.ads ada/frontend.ads \
- ada/frontend.adb ada/gnat.ads ada/g-dyntab.ads ada/g-dyntab.adb \
- ada/g-hesorg.ads ada/hostparm.ads ada/inline.ads ada/interfac.ads \
- ada/lib.ads ada/lib.adb ada/lib-list.adb ada/lib-load.ads \
- ada/lib-sort.adb ada/live.ads ada/namet.ads ada/nlists.ads \
- ada/nlists.adb ada/nmake.ads ada/opt.ads ada/osint.ads ada/output.ads \
- ada/par.ads ada/prep.ads ada/prepcomp.ads ada/restrict.ads \
- ada/restrict.adb ada/rident.ads ada/rtsfind.ads ada/scans.ads \
- ada/scil_ll.ads ada/scn.ads ada/scng.ads ada/scng.adb ada/sem.ads \
- ada/sem_aux.ads ada/sem_ch8.ads ada/sem_elab.ads ada/sem_prag.ads \
- ada/sem_scil.ads ada/sem_vfpt.ads ada/sem_warn.ads ada/sinfo.ads \
- ada/sinfo.adb ada/sinput.ads ada/sinput-l.ads ada/snames.ads \
- ada/sprint.ads ada/stand.ads ada/stringt.ads ada/style.ads \
- ada/styleg.ads ada/styleg.adb ada/stylesw.ads ada/system.ads \
- ada/s-assert.ads ada/s-crc32.ads ada/s-exctab.ads ada/s-imenne.ads \
- ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads ada/s-rident.ads \
- ada/s-secsta.ads ada/s-soflin.ads ada/s-stache.ads ada/s-stalib.ads \
- ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads \
- ada/s-unstyp.ads ada/s-utf_32.ads ada/s-wchcon.ads ada/table.ads \
- ada/table.adb ada/targparm.ads ada/tbuild.ads ada/tbuild.adb \
- ada/tree_io.ads ada/types.ads ada/uintp.ads ada/uname.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads ada/warnsw.ads \
- ada/widechar.ads
-
-ada/g-byorma.o : ada/gnat.ads ada/g-byorma.ads ada/g-byorma.adb \
- ada/system.ads
-
-ada/g-hesora.o : ada/gnat.ads ada/g-hesora.ads ada/g-hesora.adb \
- ada/system.ads
-
-ada/g-htable.o : ada/gnat.ads ada/g-htable.ads ada/g-htable.adb \
- ada/system.ads ada/s-htable.ads
-
-ada/g-spchge.o : ada/gnat.ads ada/g-spchge.ads ada/g-spchge.adb \
- ada/system.ads
-
-ada/g-speche.o : ada/gnat.ads ada/g-speche.ads ada/g-speche.adb \
- ada/g-spchge.ads ada/g-spchge.adb ada/system.ads
-
-ada/g-u3spch.o : ada/gnat.ads ada/g-spchge.ads ada/g-spchge.adb \
- ada/g-u3spch.ads ada/g-u3spch.adb ada/system.ads ada/s-wchcnv.ads \
- ada/s-wchcon.ads
-
-ada/get_spark_xrefs.o : ada/ada.ads ada/a-ioexce.ads ada/a-unccon.ads \
- ada/get_spark_xrefs.ads ada/get_spark_xrefs.adb ada/gnat.ads \
- ada/g-hesorg.ads ada/g-table.ads ada/g-table.adb ada/spark_xrefs.ads \
- ada/system.ads ada/s-assert.ads ada/s-exctab.ads ada/s-memory.ads \
- ada/s-stalib.ads ada/s-unstyp.ads ada/types.ads ada/unchconv.ads \
- ada/unchdeal.ads
-
-ada/get_targ.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/debug.ads ada/einfo.ads \
- ada/get_targ.ads ada/get_targ.adb ada/hostparm.ads ada/namet.ads \
- ada/opt.ads ada/output.ads ada/snames.ads ada/system.ads \
- ada/s-assert.ads ada/s-exctab.ads ada/s-memory.ads ada/s-os_lib.ads \
- ada/s-parame.ads ada/s-stalib.ads ada/s-string.ads ada/s-traent.ads \
- ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads ada/table.adb \
- ada/tree_io.ads ada/types.ads ada/uintp.ads ada/unchconv.ads \
- ada/unchdeal.ads ada/urealp.ads
-
-ada/gnat.o : ada/gnat.ads ada/system.ads
-
-ada/gnat1drv.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/back_end.ads ada/casing.ads ada/comperr.ads \
- ada/csets.ads ada/debug.ads ada/einfo.ads ada/elists.ads \
- ada/err_vars.ads ada/errout.ads ada/erroutc.ads ada/exp_cg.ads \
- ada/exp_ch6.ads ada/fmap.ads ada/fname.ads ada/fname-uf.ads \
- ada/frontend.ads ada/get_targ.ads ada/gnat.ads ada/g-byorma.ads \
- ada/g-hesorg.ads ada/g-table.ads ada/g-table.adb ada/gnat1drv.ads \
- ada/gnat1drv.adb ada/gnatvsn.ads ada/hostparm.ads ada/inline.ads \
- ada/lib.ads ada/lib.adb ada/lib-list.adb ada/lib-sort.adb \
- ada/lib-util.ads ada/lib-writ.ads ada/lib-xref.ads ada/namet.ads \
- ada/nlists.ads ada/opt.ads ada/osint.ads ada/output.ads ada/par_sco.ads \
- ada/prepcomp.ads ada/put_spark_xrefs.ads ada/repinfo.ads \
- ada/restrict.ads ada/rident.ads ada/rtsfind.ads ada/scans.ads \
- ada/scos.ads ada/sem.ads ada/sem_ch12.ads ada/sem_ch13.ads \
- ada/sem_ch8.ads ada/sem_elim.ads ada/sem_eval.ads ada/sem_type.ads \
- ada/set_targ.ads ada/sinfo.ads ada/sinfo.adb ada/sinput.ads \
- ada/sinput.adb ada/sinput-l.ads ada/snames.ads ada/sprint.ads \
- ada/stand.ads ada/stringt.ads ada/stylesw.ads ada/system.ads \
- ada/s-assert.ads ada/s-exctab.ads ada/s-imenne.ads ada/s-memory.ads \
- ada/s-os_lib.ads ada/s-parame.ads ada/s-rident.ads ada/s-secsta.ads \
- ada/s-soflin.ads ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads \
- ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads \
- ada/s-wchcon.ads ada/table.ads ada/table.adb ada/targparm.ads \
- ada/tree_gen.ads ada/tree_io.ads ada/treepr.ads ada/ttypes.ads \
- ada/types.ads ada/uintp.ads ada/uname.ads ada/unchconv.ads \
- ada/unchdeal.ads ada/urealp.ads ada/usage.ads ada/validsw.ads \
- ada/warnsw.ads ada/widechar.ads
-
-ada/gnatbind.o : ada/ada.ads ada/a-comlin.ads ada/a-clrefi.ads \
- ada/a-except.ads ada/a-unccon.ads ada/a-uncdea.ads ada/ali.ads \
- ada/ali.adb ada/ali-util.ads ada/alloc.ads ada/bcheck.ads ada/binde.ads \
- ada/binde.adb ada/binderr.ads ada/bindgen.ads ada/bindusg.ads \
- ada/butil.ads ada/casing.ads ada/csets.ads ada/debug.ads ada/fmap.ads \
- ada/fname.ads ada/gnat.ads ada/g-htable.ads ada/gnatbind.ads \
- ada/gnatbind.adb ada/gnatvsn.ads ada/hostparm.ads ada/namet.ads \
- ada/opt.ads ada/osint.ads ada/osint-b.ads ada/output.ads ada/rident.ads \
- ada/snames.ads ada/switch.ads ada/switch.adb ada/switch-b.ads \
- ada/system.ads ada/s-assert.ads ada/s-casuti.ads ada/s-exctab.ads \
- ada/s-htable.ads ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads \
- ada/s-parame.ads ada/s-rident.ads ada/s-secsta.ads ada/s-soflin.ads \
- ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb \
- ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads \
- ada/table.ads ada/table.adb ada/targparm.ads ada/tree_io.ads \
- ada/types.ads ada/unchconv.ads ada/unchdeal.ads
-
-ada/gnatvsn.o : ada/ada.ads ada/a-unccon.ads ada/gnatvsn.ads \
- ada/gnatvsn.adb ada/system.ads ada/s-secsta.ads ada/s-stoele.ads \
- ada/s-stoele.adb
-
-ada/hostparm.o : ada/ada.ads ada/a-unccon.ads ada/hostparm.ads \
- ada/system.ads ada/s-exctab.ads ada/s-stalib.ads ada/s-unstyp.ads \
- ada/types.ads ada/unchconv.ads ada/unchdeal.ads
-
-ada/impunit.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/csets.ads ada/debug.ads ada/einfo.ads \
- ada/err_vars.ads ada/errout.ads ada/erroutc.ads ada/fname.ads \
- ada/fname-uf.ads ada/gnat.ads ada/g-hesorg.ads ada/hostparm.ads \
- ada/impunit.ads ada/impunit.adb ada/lib.ads ada/lib.adb \
- ada/lib-list.adb ada/lib-sort.adb ada/namet.ads ada/nlists.ads \
- ada/opt.ads ada/output.ads ada/sinfo.ads ada/sinfo.adb ada/sinput.ads \
- ada/snames.ads ada/stand.ads ada/stringt.ads ada/system.ads \
- ada/s-assert.ads ada/s-exctab.ads ada/s-imenne.ads ada/s-memory.ads \
- ada/s-os_lib.ads ada/s-parame.ads ada/s-secsta.ads ada/s-soflin.ads \
- ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb \
- ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads \
- ada/table.ads ada/table.adb ada/tree_io.ads ada/types.ads ada/uintp.ads \
- ada/uname.ads ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads \
- ada/widechar.ads
-
-ada/inline.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/csets.ads ada/debug.ads ada/einfo.ads \
- ada/einfo.adb ada/elists.ads ada/elists.adb ada/err_vars.ads \
- ada/errout.ads ada/erroutc.ads ada/exp_ch7.ads ada/exp_tss.ads \
- ada/fname.ads ada/fname-uf.ads ada/gnat.ads ada/g-hesorg.ads \
- ada/hostparm.ads ada/inline.ads ada/inline.adb ada/lib.ads ada/lib.adb \
- ada/lib-list.adb ada/lib-sort.adb ada/namet.ads ada/nlists.ads \
- ada/nlists.adb ada/opt.ads ada/output.ads ada/sem.ads ada/sem_aux.ads \
- ada/sem_ch10.ads ada/sem_ch12.ads ada/sem_ch8.ads ada/sem_util.ads \
- ada/sinfo.ads ada/sinfo.adb ada/sinput.ads ada/snames.ads ada/stand.ads \
- ada/stringt.ads ada/system.ads ada/s-assert.ads ada/s-exctab.ads \
- ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads \
- ada/s-secsta.ads ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb \
- ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads \
- ada/table.ads ada/table.adb ada/tree_io.ads ada/types.ads ada/uintp.ads \
- ada/uname.ads ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads \
- ada/warnsw.ads ada/widechar.ads
-
-ada/interfac.o : ada/interfac.ads ada/system.ads
-
-ada/itypes.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/debug.ads ada/einfo.ads ada/einfo.adb \
- ada/exp_tss.ads ada/gnat.ads ada/g-htable.ads ada/hostparm.ads \
- ada/itypes.ads ada/itypes.adb ada/namet.ads ada/nlists.ads ada/opt.ads \
- ada/output.ads ada/rident.ads ada/sem.ads ada/sem_util.ads \
- ada/sinfo.ads ada/sinfo.adb ada/sinput.ads ada/snames.ads ada/stand.ads \
- ada/system.ads ada/s-assert.ads ada/s-exctab.ads ada/s-htable.ads \
- ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads \
- ada/s-rident.ads ada/s-stalib.ads ada/s-string.ads ada/s-traent.ads \
- ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads ada/table.adb \
- ada/targparm.ads ada/tree_io.ads ada/types.ads ada/uintp.ads \
- ada/uintp.adb ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads
-
-ada/krunch.o : ada/ada.ads ada/a-unccon.ads ada/hostparm.ads \
- ada/krunch.ads ada/krunch.adb ada/system.ads ada/s-assert.ads \
- ada/s-exctab.ads ada/s-stalib.ads ada/s-unstyp.ads ada/types.ads \
- ada/unchconv.ads ada/unchdeal.ads
-
-ada/layout.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/checks.ads ada/csets.ads ada/debug.ads \
- ada/einfo.ads ada/einfo.adb ada/elists.ads ada/err_vars.ads \
- ada/errout.ads ada/erroutc.ads ada/exp_ch11.ads ada/exp_ch3.ads \
- ada/exp_disp.ads ada/exp_tss.ads ada/exp_util.ads ada/fname.ads \
- ada/freeze.ads ada/get_targ.ads ada/gnat.ads ada/g-htable.ads \
- ada/hostparm.ads ada/layout.ads ada/layout.adb ada/lib.ads \
- ada/lib-util.ads ada/lib-xref.ads ada/namet.ads ada/namet-sp.ads \
- ada/nlists.ads ada/nlists.adb ada/nmake.ads ada/nmake.adb ada/opt.ads \
- ada/output.ads ada/put_spark_xrefs.ads ada/repinfo.ads ada/repinfo.adb \
- ada/restrict.ads ada/rident.ads ada/rtsfind.ads ada/scans.ads \
- ada/sem.ads ada/sem_attr.ads ada/sem_aux.ads ada/sem_ch13.ads \
- ada/sem_ch8.ads ada/sem_disp.ads ada/sem_eval.ads ada/sem_res.ads \
- ada/sem_type.ads ada/sem_util.ads ada/sem_util.adb ada/set_targ.ads \
- ada/sinfo.ads ada/sinfo.adb ada/sinput.ads ada/snames.ads ada/stand.ads \
- ada/stringt.ads ada/style.ads ada/styleg.ads ada/styleg.adb \
- ada/stylesw.ads ada/system.ads ada/s-assert.ads ada/s-exctab.ads \
- ada/s-htable.ads ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads \
- ada/s-parame.ads ada/s-rident.ads ada/s-secsta.ads ada/s-soflin.ads \
- ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb \
- ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads \
- ada/table.ads ada/table.adb ada/targparm.ads ada/tbuild.ads \
- ada/tbuild.adb ada/tree_io.ads ada/ttypes.ads ada/types.ads \
- ada/uintp.ads ada/uintp.adb ada/uname.ads ada/unchconv.ads \
- ada/unchdeal.ads ada/urealp.ads
-
-ada/lib-load.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/csets.ads ada/debug.ads ada/einfo.ads \
- ada/einfo.adb ada/elists.ads ada/err_vars.ads ada/errout.ads \
- ada/erroutc.ads ada/fname.ads ada/fname-uf.ads ada/gnat.ads \
- ada/g-byorma.ads ada/g-hesorg.ads ada/hostparm.ads ada/interfac.ads \
- ada/lib.ads ada/lib.adb ada/lib-list.adb ada/lib-load.ads \
- ada/lib-load.adb ada/lib-sort.adb ada/namet.ads ada/nlists.ads \
- ada/nmake.ads ada/nmake.adb ada/opt.ads ada/osint.ads ada/osint-c.ads \
- ada/output.ads ada/par.ads ada/restrict.ads ada/rident.ads \
- ada/scans.ads ada/scn.ads ada/scng.ads ada/scng.adb ada/sem_aux.ads \
- ada/sinfo.ads ada/sinfo.adb ada/sinput.ads ada/sinput.adb \
- ada/sinput-l.ads ada/snames.ads ada/stand.ads ada/stringt.ads \
- ada/style.ads ada/styleg.ads ada/styleg.adb ada/stylesw.ads \
- ada/system.ads ada/s-assert.ads ada/s-crc32.ads ada/s-exctab.ads \
- ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads \
- ada/s-rident.ads ada/s-secsta.ads ada/s-soflin.ads ada/s-stache.ads \
- ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads \
- ada/s-traent.ads ada/s-unstyp.ads ada/s-utf_32.ads ada/s-wchcon.ads \
- ada/table.ads ada/table.adb ada/tbuild.ads ada/tbuild.adb \
- ada/tree_io.ads ada/types.ads ada/uintp.ads ada/uname.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads ada/widechar.ads
-
-ada/lib-util.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/debug.ads ada/hostparm.ads \
- ada/lib.ads ada/lib-util.ads ada/lib-util.adb ada/namet.ads ada/opt.ads \
- ada/osint.ads ada/osint-c.ads ada/output.ads ada/stringt.ads \
- ada/stringt.adb ada/system.ads ada/s-assert.ads ada/s-carun8.ads \
- ada/s-exctab.ads ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads \
- ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads \
- ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads \
- ada/table.adb ada/tree_io.ads ada/types.ads ada/types.adb ada/uintp.ads \
- ada/unchconv.ads ada/unchdeal.ads
-
-ada/lib-writ.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/ali.ads ada/ali.adb ada/alloc.ads ada/aspects.ads \
- ada/atree.ads ada/atree.adb ada/butil.ads ada/casing.ads ada/csets.ads \
- ada/debug.ads ada/einfo.ads ada/einfo.adb ada/elists.ads \
- ada/err_vars.ads ada/errout.ads ada/erroutc.ads ada/fname.ads \
- ada/fname-uf.ads ada/gnat.ads ada/g-byorma.ads ada/g-hesorg.ads \
- ada/g-htable.ads ada/gnatvsn.ads ada/hostparm.ads ada/interfac.ads \
- ada/lib.ads ada/lib.adb ada/lib-list.adb ada/lib-sort.adb \
- ada/lib-util.ads ada/lib-util.adb ada/lib-writ.ads ada/lib-writ.adb \
- ada/lib-xref.ads ada/namet.ads ada/nlists.ads ada/nlists.adb \
- ada/nmake.ads ada/opt.ads ada/osint.ads ada/osint-c.ads ada/output.ads \
- ada/par.ads ada/par_sco.ads ada/put_spark_xrefs.ads ada/restrict.ads \
- ada/restrict.adb ada/rident.ads ada/scans.ads ada/scn.ads ada/scng.ads \
- ada/scng.adb ada/sem_aux.ads ada/sinfo.ads ada/sinfo.adb ada/sinput.ads \
- ada/sinput.adb ada/snames.ads ada/stand.ads ada/stringt.ads \
- ada/stringt.adb ada/style.ads ada/styleg.ads ada/styleg.adb \
- ada/stylesw.ads ada/system.ads ada/s-assert.ads ada/s-casuti.ads \
- ada/s-crc32.ads ada/s-exctab.ads ada/s-htable.ads ada/s-imenne.ads \
- ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads ada/s-rident.ads \
- ada/s-secsta.ads ada/s-soflin.ads ada/s-stache.ads ada/s-stalib.ads \
- ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads \
- ada/s-unstyp.ads ada/s-utf_32.ads ada/s-wchcon.ads ada/table.ads \
- ada/table.adb ada/tbuild.ads ada/tbuild.adb ada/tree_io.ads \
- ada/types.ads ada/uintp.ads ada/uname.ads ada/unchconv.ads \
- ada/unchdeal.ads ada/urealp.ads ada/widechar.ads
-
-ada/lib-xref.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/checks.ads ada/csets.ads ada/debug.ads \
- ada/einfo.ads ada/einfo.adb ada/elists.ads ada/elists.adb \
- ada/err_vars.ads ada/errout.ads ada/erroutc.ads ada/exp_ch11.ads \
- ada/exp_disp.ads ada/exp_tss.ads ada/exp_util.ads ada/fname.ads \
- ada/freeze.ads ada/get_targ.ads ada/gnat.ads ada/g-byorma.ads \
- ada/g-hesorg.ads ada/g-hesorg.adb ada/g-htable.ads ada/g-table.ads \
- ada/g-table.adb ada/hostparm.ads ada/interfac.ads ada/lib.ads \
- ada/lib.adb ada/lib-list.adb ada/lib-sort.adb ada/lib-util.ads \
- ada/lib-util.adb ada/lib-xref.ads ada/lib-xref.adb \
- ada/lib-xref-spark_specific.adb ada/namet.ads ada/namet.adb \
- ada/namet-sp.ads ada/nlists.ads ada/nlists.adb ada/nmake.ads \
- ada/nmake.adb ada/opt.ads ada/osint.ads ada/osint-c.ads ada/output.ads \
- ada/put_spark_xrefs.ads ada/put_spark_xrefs.adb ada/restrict.ads \
- ada/rident.ads ada/rtsfind.ads ada/scans.ads ada/sem.ads \
- ada/sem_attr.ads ada/sem_aux.ads ada/sem_aux.adb ada/sem_ch8.ads \
- ada/sem_disp.ads ada/sem_eval.ads ada/sem_prag.ads ada/sem_res.ads \
- ada/sem_type.ads ada/sem_util.ads ada/sem_util.adb ada/sem_warn.ads \
- ada/set_targ.ads ada/sinfo.ads ada/sinfo.adb ada/sinput.ads \
- ada/sinput.adb ada/snames.ads ada/spark_xrefs.ads ada/spark_xrefs.adb \
- ada/stand.ads ada/stringt.ads ada/style.ads ada/styleg.ads \
- ada/styleg.adb ada/stylesw.ads ada/system.ads ada/s-assert.ads \
- ada/s-exctab.ads ada/s-htable.ads ada/s-htable.adb ada/s-imenne.ads \
- ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads ada/s-rident.ads \
- ada/s-secsta.ads ada/s-soflin.ads ada/s-stache.ads ada/s-stalib.ads \
- ada/s-stoele.ads ada/s-stoele.adb ada/s-strhas.ads ada/s-string.ads \
- ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads \
- ada/table.adb ada/targparm.ads ada/tbuild.ads ada/tree_io.ads \
- ada/ttypes.ads ada/types.ads ada/uintp.ads ada/uname.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads ada/widechar.ads
-
-ada/lib.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads ada/a-uncdea.ads \
- ada/alloc.ads ada/aspects.ads ada/atree.ads ada/atree.adb \
- ada/casing.ads ada/csets.ads ada/debug.ads ada/einfo.ads ada/einfo.adb \
- ada/fname.ads ada/gnat.ads ada/g-byorma.ads ada/g-hesorg.ads \
- ada/g-hesorg.adb ada/hostparm.ads ada/interfac.ads ada/lib.ads \
- ada/lib.adb ada/lib-list.adb ada/lib-sort.adb ada/namet.ads \
- ada/namet.adb ada/nlists.ads ada/nlists.adb ada/opt.ads ada/output.ads \
- ada/scans.ads ada/sinfo.ads ada/sinfo.adb ada/sinput.ads ada/sinput.adb \
- ada/snames.ads ada/stand.ads ada/stringt.ads ada/system.ads \
- ada/s-assert.ads ada/s-exctab.ads ada/s-imenne.ads ada/s-memory.ads \
- ada/s-os_lib.ads ada/s-parame.ads ada/s-secsta.ads ada/s-stalib.ads \
- ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads \
- ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads ada/table.adb \
- ada/tree_io.ads ada/types.ads ada/uintp.ads ada/uname.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads ada/widechar.ads
-
-ada/live.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/csets.ads ada/debug.ads ada/einfo.ads \
- ada/einfo.adb ada/exp_tss.ads ada/fname.ads ada/gnat.ads \
- ada/g-hesorg.ads ada/hostparm.ads ada/lib.ads ada/lib.adb \
- ada/lib-list.adb ada/lib-sort.adb ada/live.ads ada/live.adb \
- ada/namet.ads ada/nlists.ads ada/nlists.adb ada/opt.ads ada/output.ads \
- ada/sem_aux.ads ada/sem_util.ads ada/sinfo.ads ada/sinfo.adb \
- ada/sinput.ads ada/snames.ads ada/stand.ads ada/stringt.ads \
- ada/system.ads ada/s-assert.ads ada/s-exctab.ads ada/s-imenne.ads \
- ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads ada/s-secsta.ads \
- ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads \
- ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads \
- ada/table.adb ada/tree_io.ads ada/types.ads ada/uintp.ads ada/uname.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads ada/widechar.ads
-
-ada/namet-sp.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/debug.ads ada/gnat.ads \
- ada/g-u3spch.ads ada/hostparm.ads ada/interfac.ads ada/namet.ads \
- ada/namet.adb ada/namet-sp.ads ada/namet-sp.adb ada/opt.ads \
- ada/output.ads ada/system.ads ada/s-assert.ads ada/s-carun8.ads \
- ada/s-exctab.ads ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads \
- ada/s-secsta.ads ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb \
- ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcnv.ads \
- ada/s-wchcon.ads ada/table.ads ada/table.adb ada/tree_io.ads \
- ada/types.ads ada/types.adb ada/unchconv.ads ada/unchdeal.ads \
- ada/widechar.ads
-
-ada/namet.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/debug.ads ada/hostparm.ads \
- ada/interfac.ads ada/namet.ads ada/namet.adb ada/opt.ads ada/output.ads \
- ada/system.ads ada/s-assert.ads ada/s-carun8.ads ada/s-exctab.ads \
- ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads ada/s-secsta.ads \
- ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads \
- ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads \
- ada/table.adb ada/tree_io.ads ada/types.ads ada/types.adb \
- ada/unchconv.ads ada/unchdeal.ads ada/widechar.ads
-
-ada/nlists.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/debug.ads ada/einfo.ads \
- ada/hostparm.ads ada/namet.ads ada/nlists.ads ada/nlists.adb \
- ada/opt.ads ada/output.ads ada/sinfo.ads ada/sinput.ads ada/snames.ads \
- ada/system.ads ada/s-assert.ads ada/s-exctab.ads ada/s-imenne.ads \
- ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads ada/s-stalib.ads \
- ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads \
- ada/table.ads ada/table.adb ada/tree_io.ads ada/types.ads ada/uintp.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads
-
-ada/nmake.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/atree.ads ada/debug.ads \
- ada/einfo.ads ada/hostparm.ads ada/namet.ads ada/nlists.ads \
- ada/nmake.ads ada/nmake.adb ada/opt.ads ada/output.ads ada/sinfo.ads \
- ada/sinfo.adb ada/snames.ads ada/stand.ads ada/system.ads \
- ada/s-assert.ads ada/s-exctab.ads ada/s-memory.ads ada/s-os_lib.ads \
- ada/s-parame.ads ada/s-stalib.ads ada/s-string.ads ada/s-traent.ads \
- ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads ada/table.adb \
- ada/tree_io.ads ada/types.ads ada/uintp.ads ada/unchconv.ads \
- ada/unchdeal.ads ada/urealp.ads
-
-ada/opt.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads ada/a-uncdea.ads \
- ada/gnatvsn.ads ada/hostparm.ads ada/opt.ads ada/opt.adb ada/system.ads \
- ada/s-exctab.ads ada/s-os_lib.ads ada/s-parame.ads ada/s-secsta.ads \
- ada/s-soflin.ads ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads \
- ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads \
- ada/s-wchcon.ads ada/tree_io.ads ada/types.ads ada/unchconv.ads \
- ada/unchdeal.ads
-
-ada/osint-b.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/debug.ads ada/hostparm.ads \
- ada/namet.ads ada/opt.ads ada/osint.ads ada/osint-b.ads ada/osint-b.adb \
- ada/output.ads ada/rident.ads ada/system.ads ada/s-assert.ads \
- ada/s-exctab.ads ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads \
- ada/s-rident.ads ada/s-secsta.ads ada/s-soflin.ads ada/s-stache.ads \
- ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads \
- ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads \
- ada/table.adb ada/targparm.ads ada/tree_io.ads ada/types.ads \
- ada/unchconv.ads ada/unchdeal.ads
-
-ada/osint-c.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/debug.ads ada/hostparm.ads \
- ada/interfac.ads ada/namet.ads ada/namet.adb ada/opt.ads ada/osint.ads \
- ada/osint-c.ads ada/osint-c.adb ada/output.ads ada/system.ads \
- ada/s-assert.ads ada/s-exctab.ads ada/s-memory.ads ada/s-os_lib.ads \
- ada/s-parame.ads ada/s-secsta.ads ada/s-soflin.ads ada/s-stache.ads \
- ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads \
- ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads \
- ada/table.adb ada/tree_io.ads ada/types.ads ada/unchconv.ads \
- ada/unchdeal.ads ada/widechar.ads
-
-ada/osint.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/debug.ads ada/fmap.ads ada/gnat.ads \
- ada/g-htable.ads ada/gnatvsn.ads ada/hostparm.ads ada/interfac.ads \
- ada/namet.ads ada/namet.adb ada/opt.ads ada/osint.ads ada/osint.adb \
- ada/output.ads ada/rident.ads ada/sdefault.ads ada/system.ads \
- ada/s-assert.ads ada/s-casuti.ads ada/s-exctab.ads ada/s-htable.ads \
- ada/s-htable.adb ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads \
- ada/s-rident.ads ada/s-secsta.ads ada/s-soflin.ads ada/s-stache.ads \
- ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb ada/s-strhas.ads \
- ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads \
- ada/table.ads ada/table.adb ada/targparm.ads ada/tree_io.ads \
- ada/types.ads ada/unchconv.ads ada/unchdeal.ads ada/widechar.ads
-
-ada/output.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/hostparm.ads ada/output.ads ada/output.adb \
- ada/system.ads ada/s-assert.ads ada/s-exctab.ads ada/s-exctab.adb \
- ada/s-htable.ads ada/s-os_lib.ads ada/s-parame.ads ada/s-soflin.ads \
- ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb \
- ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads ada/types.ads \
- ada/unchconv.ads ada/unchdeal.ads
-
-ada/par.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads ada/a-uncdea.ads \
- ada/alloc.ads ada/aspects.ads ada/aspects.adb ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/checks.ads ada/csets.ads ada/debug.ads \
- ada/einfo.ads ada/elists.ads ada/elists.adb ada/err_vars.ads \
- ada/errout.ads ada/errout.adb ada/erroutc.ads ada/exp_ch11.ads \
- ada/exp_disp.ads ada/exp_tss.ads ada/exp_util.ads ada/fname.ads \
- ada/fname-uf.ads ada/freeze.ads ada/get_targ.ads ada/gnat.ads \
- ada/g-byorma.ads ada/g-hesorg.ads ada/g-htable.ads ada/g-speche.ads \
- ada/gnatvsn.ads ada/hostparm.ads ada/interfac.ads ada/lib.ads \
- ada/lib.adb ada/lib-list.adb ada/lib-load.ads ada/lib-sort.adb \
- ada/lib-util.ads ada/lib-xref.ads ada/namet.ads ada/namet.adb \
- ada/namet-sp.ads ada/nlists.ads ada/nlists.adb ada/nmake.ads \
- ada/nmake.adb ada/opt.ads ada/osint.ads ada/output.ads ada/par.ads \
- ada/par.adb ada/par-ch10.adb ada/par-ch11.adb ada/par-ch12.adb \
- ada/par-ch13.adb ada/par-ch2.adb ada/par-ch3.adb ada/par-ch4.adb \
- ada/par-ch5.adb ada/par-ch6.adb ada/par-ch7.adb ada/par-ch8.adb \
- ada/par-ch9.adb ada/par-endh.adb ada/par-labl.adb ada/par-load.adb \
- ada/par-prag.adb ada/par-sync.adb ada/par-tchk.adb ada/par-util.adb \
- ada/par_sco.ads ada/put_spark_xrefs.ads ada/restrict.ads ada/rident.ads \
- ada/rtsfind.ads ada/scans.ads ada/scans.adb ada/scn.ads ada/scng.ads \
- ada/scng.adb ada/sem.ads ada/sem_attr.ads ada/sem_aux.ads \
- ada/sem_ch8.ads ada/sem_disp.ads ada/sem_eval.ads ada/sem_res.ads \
- ada/sem_type.ads ada/sem_util.ads ada/sem_util.adb ada/set_targ.ads \
- ada/sinfo.ads ada/sinfo.adb ada/sinfo-cn.ads ada/sinput.ads \
- ada/sinput.adb ada/sinput-l.ads ada/snames.ads ada/snames.adb \
- ada/stand.ads ada/stringt.ads ada/stringt.adb ada/style.ads \
- ada/style.adb ada/styleg.ads ada/styleg.adb ada/stylesw.ads \
- ada/system.ads ada/s-assert.ads ada/s-carun8.ads ada/s-crc32.ads \
- ada/s-exctab.ads ada/s-exctab.adb ada/s-htable.ads ada/s-imenne.ads \
- ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads ada/s-rident.ads \
- ada/s-secsta.ads ada/s-soflin.ads ada/s-stache.ads ada/s-stalib.ads \
- ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads \
- ada/s-unstyp.ads ada/s-utf_32.ads ada/s-wchcon.ads ada/table.ads \
- ada/table.adb ada/targparm.ads ada/tbuild.ads ada/tbuild.adb \
- ada/tree_io.ads ada/ttypes.ads ada/types.ads ada/types.adb \
- ada/uintp.ads ada/uintp.adb ada/uname.ads ada/unchconv.ads \
- ada/unchdeal.ads ada/urealp.ads ada/validsw.ads ada/warnsw.ads \
- ada/widechar.ads
-
-ada/par_sco.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/aspects.adb \
- ada/atree.ads ada/atree.adb ada/casing.ads ada/csets.ads ada/debug.ads \
- ada/einfo.ads ada/err_vars.ads ada/errout.ads ada/erroutc.ads \
- ada/exp_tss.ads ada/fname.ads ada/gnat.ads ada/g-byorma.ads \
- ada/g-hesorg.ads ada/g-hesorg.adb ada/g-htable.ads ada/g-table.ads \
- ada/g-table.adb ada/hostparm.ads ada/lib.ads ada/lib.adb \
- ada/lib-list.adb ada/lib-sort.adb ada/lib-util.ads ada/lib-util.adb \
- ada/namet.ads ada/nlists.ads ada/nlists.adb ada/opt.ads ada/osint.ads \
- ada/osint-c.ads ada/output.ads ada/par_sco.ads ada/par_sco.adb \
- ada/put_scos.ads ada/put_scos.adb ada/scans.ads ada/scos.ads \
- ada/scos.adb ada/sem.ads ada/sem_util.ads ada/sinfo.ads ada/sinfo.adb \
- ada/sinput.ads ada/sinput.adb ada/snames.ads ada/stand.ads \
- ada/stringt.ads ada/system.ads ada/s-assert.ads ada/s-exctab.ads \
- ada/s-htable.ads ada/s-htable.adb ada/s-imenne.ads ada/s-memory.ads \
- ada/s-os_lib.ads ada/s-parame.ads ada/s-secsta.ads ada/s-stalib.ads \
- ada/s-stoele.ads ada/s-stoele.adb ada/s-strhas.ads ada/s-string.ads \
- ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads \
- ada/table.adb ada/tree_io.ads ada/types.ads ada/uintp.ads ada/uname.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads ada/widechar.ads
-
-ada/prep.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/casing.ads ada/csets.ads \
- ada/debug.ads ada/err_vars.ads ada/gnat.ads ada/g-dyntab.ads \
- ada/g-dyntab.adb ada/g-hesorg.ads ada/g-hesorg.adb ada/hostparm.ads \
- ada/namet.ads ada/opt.ads ada/osint.ads ada/output.ads ada/prep.ads \
- ada/prep.adb ada/scans.ads ada/sinput.ads ada/snames.ads \
- ada/stringt.ads ada/stringt.adb ada/system.ads ada/s-assert.ads \
- ada/s-carun8.ads ada/s-exctab.ads ada/s-memory.ads ada/s-os_lib.ads \
- ada/s-parame.ads ada/s-secsta.ads ada/s-soflin.ads ada/s-stache.ads \
- ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads \
- ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads \
- ada/table.adb ada/tree_io.ads ada/types.ads ada/uintp.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads
-
-ada/prepcomp.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/atree.ads ada/casing.ads \
- ada/csets.ads ada/debug.ads ada/einfo.ads ada/err_vars.ads \
- ada/errout.ads ada/erroutc.ads ada/gnat.ads ada/g-dyntab.ads \
- ada/g-dyntab.adb ada/g-hesorg.ads ada/hostparm.ads ada/interfac.ads \
- ada/lib.ads ada/lib-writ.ads ada/namet.ads ada/opt.ads ada/osint.ads \
- ada/output.ads ada/prep.ads ada/prep.adb ada/prepcomp.ads \
- ada/prepcomp.adb ada/restrict.ads ada/rident.ads ada/scans.ads \
- ada/scn.ads ada/scng.ads ada/scng.adb ada/sinfo.ads ada/sinput.ads \
- ada/sinput-l.ads ada/snames.ads ada/stringt.ads ada/stringt.adb \
- ada/style.ads ada/styleg.ads ada/styleg.adb ada/stylesw.ads \
- ada/system.ads ada/s-assert.ads ada/s-carun8.ads ada/s-crc32.ads \
- ada/s-exctab.ads ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads \
- ada/s-rident.ads ada/s-secsta.ads ada/s-soflin.ads ada/s-stache.ads \
- ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads \
- ada/s-traent.ads ada/s-unstyp.ads ada/s-utf_32.ads ada/s-wchcon.ads \
- ada/table.ads ada/table.adb ada/tree_io.ads ada/types.ads ada/uintp.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads ada/widechar.ads
-
-ada/put_scos.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/debug.ads ada/gnat.ads \
- ada/g-hesorg.ads ada/g-table.ads ada/g-table.adb ada/hostparm.ads \
- ada/namet.ads ada/opt.ads ada/output.ads ada/put_scos.ads \
- ada/put_scos.adb ada/scos.ads ada/system.ads ada/s-assert.ads \
- ada/s-exctab.ads ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads \
- ada/s-stalib.ads ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads \
- ada/s-wchcon.ads ada/table.ads ada/table.adb ada/tree_io.ads \
- ada/types.ads ada/unchconv.ads ada/unchdeal.ads
-
-ada/put_spark_xrefs.o : ada/ada.ads ada/a-unccon.ads ada/gnat.ads \
- ada/g-hesorg.ads ada/g-table.ads ada/g-table.adb \
- ada/put_spark_xrefs.ads ada/put_spark_xrefs.adb ada/spark_xrefs.ads \
- ada/system.ads ada/s-assert.ads ada/s-exctab.ads ada/s-memory.ads \
- ada/s-stalib.ads ada/s-unstyp.ads ada/types.ads ada/unchconv.ads \
- ada/unchdeal.ads
-
-ada/repinfo.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/csets.ads ada/debug.ads ada/einfo.ads \
- ada/einfo.adb ada/fname.ads ada/gnat.ads ada/g-byorma.ads \
- ada/g-hesorg.ads ada/g-htable.ads ada/hostparm.ads ada/lib.ads \
- ada/lib.adb ada/lib-list.adb ada/lib-sort.adb ada/namet.ads \
- ada/nlists.ads ada/opt.ads ada/output.ads ada/output.adb \
- ada/repinfo.ads ada/repinfo.adb ada/scans.ads ada/sem_aux.ads \
- ada/sinfo.ads ada/sinfo.adb ada/sinput.ads ada/sinput.adb \
- ada/snames.ads ada/stand.ads ada/stringt.ads ada/system.ads \
- ada/s-assert.ads ada/s-exctab.ads ada/s-htable.ads ada/s-imenne.ads \
- ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads ada/s-secsta.ads \
- ada/s-soflin.ads ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads \
- ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads \
- ada/s-wchcon.ads ada/table.ads ada/table.adb ada/tree_io.ads \
- ada/types.ads ada/uintp.ads ada/uintp.adb ada/uname.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads ada/widechar.ads
-
-ada/restrict.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/aspects.adb \
- ada/atree.ads ada/atree.adb ada/casing.ads ada/casing.adb ada/csets.ads \
- ada/debug.ads ada/einfo.ads ada/einfo.adb ada/err_vars.ads \
- ada/errout.ads ada/erroutc.ads ada/fname.ads ada/fname-uf.ads \
- ada/gnat.ads ada/g-byorma.ads ada/g-hesorg.ads ada/g-htable.ads \
- ada/hostparm.ads ada/interfac.ads ada/lib.ads ada/lib.adb \
- ada/lib-list.adb ada/lib-sort.adb ada/namet.ads ada/namet.adb \
- ada/nlists.ads ada/opt.ads ada/output.ads ada/restrict.ads \
- ada/restrict.adb ada/rident.ads ada/scans.ads ada/sinfo.ads \
- ada/sinfo.adb ada/sinput.ads ada/sinput.adb ada/snames.ads \
- ada/stand.ads ada/stringt.ads ada/system.ads ada/s-assert.ads \
- ada/s-exctab.ads ada/s-htable.ads ada/s-imenne.ads ada/s-memory.ads \
- ada/s-os_lib.ads ada/s-parame.ads ada/s-rident.ads ada/s-secsta.ads \
- ada/s-soflin.ads ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads \
- ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads \
- ada/s-wchcon.ads ada/table.ads ada/table.adb ada/tree_io.ads \
- ada/types.ads ada/uintp.ads ada/uintp.adb ada/uname.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads ada/widechar.ads
-
-ada/rident.o : ada/rident.ads ada/system.ads ada/s-rident.ads
-
-ada/rtsfind.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/csets.ads ada/debug.ads ada/einfo.ads \
- ada/einfo.adb ada/elists.ads ada/elists.adb ada/err_vars.ads \
- ada/errout.ads ada/erroutc.ads ada/exp_dist.ads ada/exp_tss.ads \
- ada/fname.ads ada/fname-uf.ads ada/gnat.ads ada/g-hesorg.ads \
- ada/hostparm.ads ada/interfac.ads ada/lib.ads ada/lib.adb \
- ada/lib-list.adb ada/lib-load.ads ada/lib-sort.adb ada/namet.ads \
- ada/namet.adb ada/nlists.ads ada/nmake.ads ada/nmake.adb ada/opt.ads \
- ada/output.ads ada/restrict.ads ada/rident.ads ada/rtsfind.ads \
- ada/rtsfind.adb ada/sem.ads ada/sem_aux.ads ada/sem_ch7.ads \
- ada/sem_dist.ads ada/sem_util.ads ada/sinfo.ads ada/sinfo.adb \
- ada/sinput.ads ada/snames.ads ada/stand.ads ada/stringt.ads \
- ada/system.ads ada/s-assert.ads ada/s-exctab.ads ada/s-exctab.adb \
- ada/s-htable.ads ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads \
- ada/s-parame.ads ada/s-rident.ads ada/s-secsta.ads ada/s-soflin.ads \
- ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb \
- ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads \
- ada/table.ads ada/table.adb ada/tbuild.ads ada/tree_io.ads \
- ada/types.ads ada/uintp.ads ada/uname.ads ada/unchconv.ads \
- ada/unchdeal.ads ada/urealp.ads ada/widechar.ads
-
-ada/s-addope.o : ada/ada.ads ada/a-unccon.ads ada/system.ads \
- ada/s-addope.ads ada/s-addope.adb
-
-ada/s-assert.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/system.ads ada/s-assert.ads ada/s-assert.adb ada/s-exctab.ads \
- ada/s-exctab.adb ada/s-excdeb.ads ada/s-htable.ads ada/s-parame.ads \
- ada/s-soflin.ads ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads \
- ada/s-stoele.adb ada/s-traent.ads
-
-ada/s-bitops.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/system.ads ada/s-bitops.ads ada/s-bitops.adb ada/s-parame.ads \
- ada/s-stalib.ads ada/s-traent.ads ada/s-unstyp.ads
-
-ada/s-carun8.o : ada/ada.ads ada/a-unccon.ads ada/system.ads \
- ada/s-addope.ads ada/s-addope.adb ada/s-carun8.ads ada/s-carun8.adb
-
-ada/s-casuti.o : ada/system.ads ada/s-casuti.ads ada/s-casuti.adb
-
-ada/s-conca2.o : ada/system.ads ada/s-conca2.ads ada/s-conca2.adb
-
-ada/s-conca3.o : ada/system.ads ada/s-conca2.ads ada/s-conca3.ads \
- ada/s-conca3.adb
-
-ada/s-conca4.o : ada/system.ads ada/s-conca3.ads ada/s-conca4.ads \
- ada/s-conca4.adb
-
-ada/s-conca5.o : ada/system.ads ada/s-conca4.ads ada/s-conca5.ads \
- ada/s-conca5.adb
-
-ada/s-conca6.o : ada/system.ads ada/s-conca5.ads ada/s-conca6.ads \
- ada/s-conca6.adb
-
-ada/s-conca7.o : ada/system.ads ada/s-conca6.ads ada/s-conca7.ads \
- ada/s-conca7.adb
-
-ada/s-conca8.o : ada/system.ads ada/s-conca7.ads ada/s-conca8.ads \
- ada/s-conca8.adb
-
-ada/s-conca9.o : ada/system.ads ada/s-conca8.ads ada/s-conca9.ads \
- ada/s-conca9.adb
-
-ada/s-crc32.o : ada/interfac.ads ada/system.ads ada/s-crc32.ads \
- ada/s-crc32.adb
-
-ada/s-crtl.o : ada/system.ads ada/s-crtl.ads ada/s-parame.ads
-
-ada/s-excdeb.o : ada/ada.ads ada/a-unccon.ads ada/system.ads \
- ada/s-excdeb.ads ada/s-excdeb.adb ada/s-stalib.ads
-
-ada/s-except.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/system.ads ada/s-exctab.ads ada/s-exctab.adb ada/s-except.ads \
- ada/s-except.adb ada/s-htable.ads ada/s-parame.ads ada/s-soflin.ads \
- ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb \
- ada/s-traent.ads
-
-ada/s-exctab.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/system.ads ada/s-exctab.ads ada/s-exctab.adb \
- ada/s-htable.ads ada/s-htable.adb ada/s-parame.ads ada/s-soflin.ads \
- ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb \
- ada/s-strhas.ads ada/s-traent.ads
-
-ada/s-htable.o : ada/ada.ads ada/a-uncdea.ads ada/system.ads \
- ada/s-htable.ads ada/s-htable.adb ada/s-strhas.ads
-
-ada/s-imenne.o : ada/ada.ads ada/a-unccon.ads ada/system.ads \
- ada/s-assert.ads ada/s-exctab.ads ada/s-imenne.ads ada/s-imenne.adb \
- ada/s-stalib.ads
-
-ada/s-imgenu.o : ada/ada.ads ada/a-unccon.ads ada/system.ads \
- ada/s-imgenu.ads ada/s-imgenu.adb ada/s-secsta.ads ada/s-stoele.ads \
- ada/s-stoele.adb
-
-ada/s-mastop.o : ada/ada.ads ada/a-unccon.ads ada/system.ads \
- ada/s-mastop.ads ada/s-mastop.adb ada/s-stoele.ads ada/s-stoele.adb
-
-ada/s-memory.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/system.ads ada/s-crtl.ads ada/s-memory.ads ada/s-memory.adb \
- ada/s-parame.ads ada/s-soflin.ads ada/s-stache.ads ada/s-stalib.ads \
- ada/s-stoele.ads ada/s-stoele.adb ada/s-traent.ads
-
-ada/s-os_lib.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/system.ads ada/s-casuti.ads ada/s-crtl.ads \
- ada/s-exctab.ads ada/s-exctab.adb ada/s-htable.ads ada/s-os_lib.ads \
- ada/s-os_lib.adb ada/s-parame.ads ada/s-secsta.ads ada/s-soflin.ads \
- ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb \
- ada/s-string.ads ada/s-traent.ads
-
-ada/s-parame.o : ada/system.ads ada/s-parame.ads ada/s-parame.adb
-
-ada/s-purexc.o : ada/system.ads ada/s-purexc.ads
-
-ada/s-restri.o : ada/system.ads ada/s-restri.ads ada/s-restri.adb \
- ada/s-rident.ads
-
-ada/s-secsta.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/system.ads ada/s-parame.ads ada/s-secsta.ads \
- ada/s-secsta.adb ada/s-soflin.ads ada/s-stache.ads ada/s-stalib.ads \
- ada/s-stoele.ads ada/s-stoele.adb ada/s-traent.ads
-
-ada/s-soflin.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/system.ads ada/s-parame.ads ada/s-secsta.ads ada/s-soflin.ads \
- ada/s-soflin.adb ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads \
- ada/s-stoele.adb ada/s-traent.ads
-
-ada/s-sopco3.o : ada/ada.ads ada/a-unccon.ads ada/system.ads \
- ada/s-secsta.ads ada/s-stoele.ads ada/s-stoele.adb ada/s-sopco3.ads \
- ada/s-sopco3.adb
-
-ada/s-sopco4.o : ada/ada.ads ada/a-unccon.ads ada/system.ads \
- ada/s-secsta.ads ada/s-stoele.ads ada/s-stoele.adb ada/s-sopco4.ads \
- ada/s-sopco4.adb
-
-ada/s-sopco5.o : ada/ada.ads ada/a-unccon.ads ada/system.ads \
- ada/s-secsta.ads ada/s-stoele.ads ada/s-stoele.adb ada/s-sopco5.ads \
- ada/s-sopco5.adb
-
-ada/s-stache.o : ada/ada.ads ada/a-unccon.ads ada/system.ads \
- ada/s-stache.ads ada/s-stache.adb ada/s-stoele.ads ada/s-stoele.adb
-
-ada/s-stalib.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/system.ads ada/s-memory.ads ada/s-parame.ads ada/s-soflin.ads \
- ada/s-stache.ads ada/s-stalib.ads ada/s-stalib.adb ada/s-stoele.ads \
- ada/s-stoele.adb ada/s-traent.ads
-
-ada/s-stoele.o : ada/ada.ads ada/a-unccon.ads ada/system.ads \
- ada/s-stoele.ads ada/s-stoele.adb
-
-ada/s-strcom.o : ada/ada.ads ada/a-unccon.ads ada/system.ads \
- ada/s-strcom.ads ada/s-strcom.adb
-
-ada/s-strhas.o : ada/system.ads ada/s-strhas.ads ada/s-strhas.adb
-
-ada/s-string.o : ada/ada.ads ada/a-uncdea.ads ada/system.ads \
- ada/s-string.ads ada/s-string.adb
-
-ada/s-strops.o : ada/ada.ads ada/a-unccon.ads ada/system.ads \
- ada/s-secsta.ads ada/s-stoele.ads ada/s-stoele.adb ada/s-strops.ads \
- ada/s-strops.adb
-
-ada/s-traent.o : ada/system.ads ada/s-traent.ads ada/s-traent.adb
-
-ada/s-unstyp.o : ada/system.ads ada/s-unstyp.ads
-
-ada/s-utf_32.o : ada/system.ads ada/s-utf_32.ads ada/s-utf_32.adb
-
-ada/s-wchcnv.o : ada/interfac.ads ada/system.ads ada/s-wchcnv.ads \
- ada/s-wchcnv.adb ada/s-wchcon.ads ada/s-wchjis.ads
-
-ada/s-wchcon.o : ada/system.ads ada/s-wchcon.ads ada/s-wchcon.adb
-
-ada/s-wchjis.o : ada/system.ads ada/s-wchjis.ads ada/s-wchjis.adb
-
-ada/scans.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/debug.ads ada/hostparm.ads \
- ada/interfac.ads ada/namet.ads ada/namet.adb ada/opt.ads ada/output.ads \
- ada/scans.ads ada/scans.adb ada/snames.ads ada/system.ads \
- ada/s-assert.ads ada/s-exctab.ads ada/s-memory.ads ada/s-os_lib.ads \
- ada/s-parame.ads ada/s-secsta.ads ada/s-stalib.ads ada/s-stoele.ads \
- ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads \
- ada/s-wchcon.ads ada/table.ads ada/table.adb ada/tree_io.ads \
- ada/types.ads ada/uintp.ads ada/unchconv.ads ada/unchdeal.ads \
- ada/urealp.ads ada/widechar.ads
-
-ada/scil_ll.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/debug.ads ada/einfo.ads \
- ada/hostparm.ads ada/namet.ads ada/nlists.ads ada/opt.ads \
- ada/output.ads ada/scil_ll.ads ada/scil_ll.adb ada/sinfo.ads \
- ada/sinput.ads ada/snames.ads ada/system.ads ada/s-assert.ads \
- ada/s-exctab.ads ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads \
- ada/s-parame.ads ada/s-stalib.ads ada/s-string.ads ada/s-traent.ads \
- ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads ada/table.adb \
- ada/tree_io.ads ada/types.ads ada/uintp.ads ada/unchconv.ads \
- ada/unchdeal.ads ada/urealp.ads
-
-ada/scn.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads ada/a-uncdea.ads \
- ada/alloc.ads ada/aspects.ads ada/atree.ads ada/atree.adb \
- ada/casing.ads ada/csets.ads ada/debug.ads ada/einfo.ads \
- ada/err_vars.ads ada/errout.ads ada/erroutc.ads ada/fname.ads \
- ada/fname-uf.ads ada/gnat.ads ada/g-byorma.ads ada/g-htable.ads \
- ada/hostparm.ads ada/interfac.ads ada/lib.ads ada/namet.ads \
- ada/namet.adb ada/nlists.ads ada/opt.ads ada/output.ads \
- ada/restrict.ads ada/restrict.adb ada/rident.ads ada/scans.ads \
- ada/scn.ads ada/scn.adb ada/scng.ads ada/scng.adb ada/sinfo.ads \
- ada/sinfo.adb ada/sinput.ads ada/sinput.adb ada/snames.ads \
- ada/stand.ads ada/stringt.ads ada/stringt.adb ada/style.ads \
- ada/style.adb ada/styleg.ads ada/styleg.adb ada/stylesw.ads \
- ada/system.ads ada/s-assert.ads ada/s-carun8.ads ada/s-crc32.ads \
- ada/s-crc32.adb ada/s-exctab.ads ada/s-htable.ads ada/s-imenne.ads \
- ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads ada/s-rident.ads \
- ada/s-secsta.ads ada/s-soflin.ads ada/s-stache.ads ada/s-stalib.ads \
- ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads \
- ada/s-unstyp.ads ada/s-utf_32.ads ada/s-utf_32.adb ada/s-wchcon.ads \
- ada/table.ads ada/table.adb ada/tree_io.ads ada/types.ads ada/types.adb \
- ada/uintp.ads ada/uintp.adb ada/uname.ads ada/unchconv.ads \
- ada/unchdeal.ads ada/urealp.ads ada/urealp.adb ada/widechar.ads
-
-ada/scng.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/atree.ads ada/casing.ads \
- ada/csets.ads ada/debug.ads ada/einfo.ads ada/hostparm.ads \
- ada/interfac.ads ada/namet.ads ada/opt.ads ada/output.ads \
- ada/restrict.ads ada/rident.ads ada/scans.ads ada/scng.ads ada/scng.adb \
- ada/sinfo.ads ada/sinput.ads ada/snames.ads ada/stringt.ads \
- ada/styleg.ads ada/stylesw.ads ada/system.ads ada/s-assert.ads \
- ada/s-crc32.ads ada/s-exctab.ads ada/s-memory.ads ada/s-os_lib.ads \
- ada/s-parame.ads ada/s-rident.ads ada/s-stalib.ads ada/s-string.ads \
- ada/s-traent.ads ada/s-unstyp.ads ada/s-utf_32.ads ada/s-wchcon.ads \
- ada/table.ads ada/table.adb ada/tree_io.ads ada/types.ads ada/uintp.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads ada/widechar.ads
-
-ada/scos.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/debug.ads ada/gnat.ads \
- ada/g-hesorg.ads ada/g-hesorg.adb ada/g-table.ads ada/g-table.adb \
- ada/hostparm.ads ada/namet.ads ada/opt.ads ada/output.ads ada/scos.ads \
- ada/scos.adb ada/system.ads ada/s-assert.ads ada/s-exctab.ads \
- ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads ada/s-stalib.ads \
- ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads \
- ada/table.ads ada/table.adb ada/tree_io.ads ada/types.ads \
- ada/unchconv.ads ada/unchdeal.ads
-
-ada/sem.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads ada/a-uncdea.ads \
- ada/alloc.ads ada/aspects.ads ada/atree.ads ada/atree.adb \
- ada/casing.ads ada/csets.ads ada/debug.ads ada/debug_a.ads \
- ada/debug_a.adb ada/einfo.ads ada/einfo.adb ada/elists.ads \
- ada/elists.adb ada/exp_tss.ads ada/expander.ads ada/fname.ads \
- ada/gnat.ads ada/g-hesorg.ads ada/hostparm.ads ada/inline.ads \
- ada/lib.ads ada/lib.adb ada/lib-list.adb ada/lib-load.ads \
- ada/lib-sort.adb ada/namet.ads ada/nlists.ads ada/nlists.adb \
- ada/opt.ads ada/output.ads ada/restrict.ads ada/rident.ads ada/sem.ads \
- ada/sem.adb ada/sem_attr.ads ada/sem_aux.ads ada/sem_ch10.ads \
- ada/sem_ch11.ads ada/sem_ch12.ads ada/sem_ch13.ads ada/sem_ch2.ads \
- ada/sem_ch2.adb ada/sem_ch3.ads ada/sem_ch4.ads ada/sem_ch5.ads \
- ada/sem_ch6.ads ada/sem_ch7.ads ada/sem_ch8.ads ada/sem_ch9.ads \
- ada/sem_dim.ads ada/sem_prag.ads ada/sem_util.ads ada/sinfo.ads \
- ada/sinfo.adb ada/sinput.ads ada/snames.ads ada/stand.ads \
- ada/stringt.ads ada/system.ads ada/s-assert.ads ada/s-exctab.ads \
- ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads \
- ada/s-rident.ads ada/s-secsta.ads ada/s-stalib.ads ada/s-stoele.ads \
- ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads \
- ada/s-wchcon.ads ada/table.ads ada/table.adb ada/tree_io.ads \
- ada/types.ads ada/uintp.ads ada/uname.ads ada/unchconv.ads \
- ada/unchdeal.ads ada/urealp.ads ada/warnsw.ads ada/widechar.ads
-
-ada/sem_aggr.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/checks.ads ada/checks.adb \
- ada/csets.ads ada/debug.ads ada/einfo.ads ada/einfo.adb ada/elists.ads \
- ada/elists.adb ada/err_vars.ads ada/errout.ads ada/erroutc.ads \
- ada/eval_fat.ads ada/exp_aggr.ads ada/exp_ch11.ads ada/exp_ch2.ads \
- ada/exp_ch4.ads ada/exp_ch6.ads ada/exp_ch7.ads ada/exp_disp.ads \
- ada/exp_pakd.ads ada/exp_tss.ads ada/exp_util.ads ada/exp_util.adb \
- ada/expander.ads ada/fname.ads ada/freeze.ads ada/get_targ.ads \
- ada/gnat.ads ada/g-hesorg.ads ada/g-htable.ads ada/gnatvsn.ads \
- ada/hostparm.ads ada/inline.ads ada/itypes.ads ada/lib.ads ada/lib.adb \
- ada/lib-list.adb ada/lib-sort.adb ada/lib-util.ads ada/lib-xref.ads \
- ada/namet.ads ada/namet-sp.ads ada/nlists.ads ada/nlists.adb \
- ada/nmake.ads ada/nmake.adb ada/opt.ads ada/opt.adb ada/output.ads \
- ada/put_spark_xrefs.ads ada/restrict.ads ada/rident.ads ada/rtsfind.ads \
- ada/scans.ads ada/sem.ads ada/sem_aggr.ads ada/sem_aggr.adb \
- ada/sem_attr.ads ada/sem_aux.ads ada/sem_cat.ads ada/sem_ch13.ads \
- ada/sem_ch3.ads ada/sem_ch6.ads ada/sem_ch8.ads ada/sem_dim.ads \
- ada/sem_disp.ads ada/sem_eval.ads ada/sem_eval.adb ada/sem_res.ads \
- ada/sem_type.ads ada/sem_util.ads ada/sem_util.adb ada/sem_warn.ads \
- ada/set_targ.ads ada/sinfo.ads ada/sinfo.adb ada/sinput.ads \
- ada/snames.ads ada/sprint.ads ada/stand.ads ada/stringt.ads \
- ada/stringt.adb ada/style.ads ada/styleg.ads ada/styleg.adb \
- ada/stylesw.ads ada/system.ads ada/s-assert.ads ada/s-exctab.ads \
- ada/s-htable.ads ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads \
- ada/s-parame.ads ada/s-rident.ads ada/s-secsta.ads ada/s-soflin.ads \
- ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb \
- ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads \
- ada/table.ads ada/table.adb ada/targparm.ads ada/tbuild.ads \
- ada/tbuild.adb ada/tree_io.ads ada/ttypes.ads ada/types.ads \
- ada/uintp.ads ada/uintp.adb ada/uname.ads ada/unchconv.ads \
- ada/unchdeal.ads ada/urealp.ads ada/validsw.ads ada/warnsw.ads \
- ada/widechar.ads
-
-ada/sem_attr.o : ada/ada.ads ada/a-charac.ads ada/a-chlat1.ads \
- ada/a-except.ads ada/a-unccon.ads ada/a-uncdea.ads ada/alloc.ads \
- ada/aspects.ads ada/atree.ads ada/atree.adb ada/casing.ads \
- ada/checks.ads ada/checks.adb ada/csets.ads ada/debug.ads \
- ada/debug_a.ads ada/einfo.ads ada/einfo.adb ada/elists.ads \
- ada/elists.adb ada/err_vars.ads ada/errout.ads ada/erroutc.ads \
- ada/eval_fat.ads ada/exp_aggr.ads ada/exp_ch11.ads ada/exp_ch2.ads \
- ada/exp_ch4.ads ada/exp_ch6.ads ada/exp_ch7.ads ada/exp_disp.ads \
- ada/exp_dist.ads ada/exp_pakd.ads ada/exp_tss.ads ada/exp_util.ads \
- ada/exp_util.adb ada/expander.ads ada/fname.ads ada/fname-uf.ads \
- ada/freeze.ads ada/get_targ.ads ada/gnat.ads ada/g-byorma.ads \
- ada/g-hesorg.ads ada/g-htable.ads ada/gnatvsn.ads ada/hostparm.ads \
- ada/inline.ads ada/interfac.ads ada/itypes.ads ada/lib.ads ada/lib.adb \
- ada/lib-list.adb ada/lib-load.ads ada/lib-sort.adb ada/lib-util.ads \
- ada/lib-xref.ads ada/namet.ads ada/namet.adb ada/namet-sp.ads \
- ada/nlists.ads ada/nlists.adb ada/nmake.ads ada/nmake.adb ada/opt.ads \
- ada/output.ads ada/put_spark_xrefs.ads ada/restrict.ads \
- ada/restrict.adb ada/rident.ads ada/rtsfind.ads ada/scans.ads \
- ada/sdefault.ads ada/sem.ads ada/sem.adb ada/sem_aggr.ads \
- ada/sem_attr.ads ada/sem_attr.adb ada/sem_aux.ads ada/sem_aux.adb \
- ada/sem_cat.ads ada/sem_ch10.ads ada/sem_ch11.ads ada/sem_ch12.ads \
- ada/sem_ch13.ads ada/sem_ch2.ads ada/sem_ch3.ads ada/sem_ch4.ads \
- ada/sem_ch5.ads ada/sem_ch6.ads ada/sem_ch7.ads ada/sem_ch8.ads \
- ada/sem_ch9.ads ada/sem_dim.ads ada/sem_disp.ads ada/sem_dist.ads \
- ada/sem_elab.ads ada/sem_elim.ads ada/sem_eval.ads ada/sem_eval.adb \
- ada/sem_intr.ads ada/sem_prag.ads ada/sem_res.ads ada/sem_res.adb \
- ada/sem_type.ads ada/sem_util.ads ada/sem_util.adb ada/sem_warn.ads \
- ada/set_targ.ads ada/sinfo.ads ada/sinfo.adb ada/sinfo-cn.ads \
- ada/sinput.ads ada/sinput.adb ada/snames.ads ada/snames.adb \
- ada/sprint.ads ada/stand.ads ada/stringt.ads ada/stringt.adb \
- ada/style.ads ada/styleg.ads ada/styleg.adb ada/stylesw.ads \
- ada/system.ads ada/s-assert.ads ada/s-carun8.ads ada/s-exctab.ads \
- ada/s-exctab.adb ada/s-htable.ads ada/s-imenne.ads ada/s-memory.ads \
- ada/s-os_lib.ads ada/s-parame.ads ada/s-rident.ads ada/s-secsta.ads \
- ada/s-soflin.ads ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads \
- ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads \
- ada/s-wchcon.ads ada/table.ads ada/table.adb ada/targparm.ads \
- ada/tbuild.ads ada/tbuild.adb ada/tree_io.ads ada/ttypes.ads \
- ada/types.ads ada/types.adb ada/uintp.ads ada/uintp.adb ada/uname.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads ada/urealp.adb \
- ada/validsw.ads ada/warnsw.ads ada/widechar.ads
-
-ada/sem_aux.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/debug.ads ada/einfo.ads ada/einfo.adb \
- ada/hostparm.ads ada/namet.ads ada/nlists.ads ada/opt.ads \
- ada/output.ads ada/sem_aux.ads ada/sem_aux.adb ada/sinfo.ads \
- ada/sinfo.adb ada/sinput.ads ada/snames.ads ada/stand.ads \
- ada/system.ads ada/s-assert.ads ada/s-exctab.ads ada/s-imenne.ads \
- ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads ada/s-stalib.ads \
- ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads \
- ada/table.ads ada/table.adb ada/tree_io.ads ada/types.ads ada/uintp.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads
-
-ada/sem_case.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/debug.ads ada/einfo.ads ada/einfo.adb \
- ada/err_vars.ads ada/errout.ads ada/erroutc.ads ada/exp_tss.ads \
- ada/gnat.ads ada/g-hesorg.ads ada/g-hesorg.adb ada/g-htable.ads \
- ada/hostparm.ads ada/interfac.ads ada/namet.ads ada/namet.adb \
- ada/nlists.ads ada/nlists.adb ada/nmake.ads ada/nmake.adb ada/opt.ads \
- ada/output.ads ada/sem.ads ada/sem_aux.ads ada/sem_case.ads \
- ada/sem_case.adb ada/sem_eval.ads ada/sem_res.ads ada/sem_type.ads \
- ada/sem_util.ads ada/sinfo.ads ada/sinfo.adb ada/sinput.ads \
- ada/snames.ads ada/stand.ads ada/system.ads ada/s-assert.ads \
- ada/s-exctab.ads ada/s-htable.ads ada/s-imenne.ads ada/s-memory.ads \
- ada/s-os_lib.ads ada/s-parame.ads ada/s-secsta.ads ada/s-stalib.ads \
- ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads \
- ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads ada/table.adb \
- ada/tbuild.ads ada/tree_io.ads ada/types.ads ada/uintp.ads \
- ada/uintp.adb ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads \
- ada/widechar.ads
-
-ada/sem_cat.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/checks.ads ada/csets.ads ada/debug.ads \
- ada/einfo.ads ada/einfo.adb ada/elists.ads ada/elists.adb \
- ada/err_vars.ads ada/errout.ads ada/erroutc.ads ada/exp_ch11.ads \
- ada/exp_disp.ads ada/exp_tss.ads ada/exp_util.ads ada/fname.ads \
- ada/freeze.ads ada/get_targ.ads ada/gnat.ads ada/g-hesorg.ads \
- ada/g-htable.ads ada/hostparm.ads ada/lib.ads ada/lib.adb \
- ada/lib-list.adb ada/lib-sort.adb ada/lib-util.ads ada/lib-xref.ads \
- ada/namet.ads ada/namet-sp.ads ada/nlists.ads ada/nlists.adb \
- ada/nmake.ads ada/opt.ads ada/output.ads ada/put_spark_xrefs.ads \
- ada/restrict.ads ada/rident.ads ada/rtsfind.ads ada/scans.ads \
- ada/sem.ads ada/sem_attr.ads ada/sem_aux.ads ada/sem_cat.ads \
- ada/sem_cat.adb ada/sem_ch8.ads ada/sem_disp.ads ada/sem_dist.ads \
- ada/sem_eval.ads ada/sem_res.ads ada/sem_type.ads ada/sem_util.ads \
- ada/sem_util.adb ada/set_targ.ads ada/sinfo.ads ada/sinfo.adb \
- ada/sinput.ads ada/snames.ads ada/stand.ads ada/stringt.ads \
- ada/style.ads ada/styleg.ads ada/styleg.adb ada/stylesw.ads \
- ada/system.ads ada/s-assert.ads ada/s-exctab.ads ada/s-htable.ads \
- ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads \
- ada/s-rident.ads ada/s-secsta.ads ada/s-soflin.ads ada/s-stache.ads \
- ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads \
- ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads \
- ada/table.adb ada/targparm.ads ada/tbuild.ads ada/tree_io.ads \
- ada/ttypes.ads ada/types.ads ada/uintp.ads ada/uname.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads ada/widechar.ads
-
-ada/sem_ch10.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/checks.ads ada/csets.ads ada/debug.ads \
- ada/debug_a.ads ada/einfo.ads ada/einfo.adb ada/elists.ads \
- ada/elists.adb ada/err_vars.ads ada/errout.ads ada/erroutc.ads \
- ada/exp_ch11.ads ada/exp_disp.ads ada/exp_tss.ads ada/exp_util.ads \
- ada/expander.ads ada/fname.ads ada/fname-uf.ads ada/freeze.ads \
- ada/get_targ.ads ada/gnat.ads ada/g-byorma.ads ada/g-hesorg.ads \
- ada/g-htable.ads ada/gnatvsn.ads ada/hostparm.ads ada/impunit.ads \
- ada/inline.ads ada/interfac.ads ada/lib.ads ada/lib.adb \
- ada/lib-list.adb ada/lib-load.ads ada/lib-sort.adb ada/lib-util.ads \
- ada/lib-xref.ads ada/namet.ads ada/namet.adb ada/namet-sp.ads \
- ada/nlists.ads ada/nlists.adb ada/nmake.ads ada/nmake.adb ada/opt.ads \
- ada/opt.adb ada/output.ads ada/par_sco.ads ada/put_spark_xrefs.ads \
- ada/restrict.ads ada/restrict.adb ada/rident.ads ada/rtsfind.ads \
- ada/scans.ads ada/sem.ads ada/sem.adb ada/sem_attr.ads ada/sem_aux.ads \
- ada/sem_ch10.ads ada/sem_ch10.adb ada/sem_ch11.ads ada/sem_ch12.ads \
- ada/sem_ch13.ads ada/sem_ch2.ads ada/sem_ch3.ads ada/sem_ch4.ads \
- ada/sem_ch5.ads ada/sem_ch6.ads ada/sem_ch7.ads ada/sem_ch8.ads \
- ada/sem_ch9.ads ada/sem_disp.ads ada/sem_dist.ads ada/sem_eval.ads \
- ada/sem_prag.ads ada/sem_res.ads ada/sem_type.ads ada/sem_util.ads \
- ada/sem_util.adb ada/sem_warn.ads ada/set_targ.ads ada/sinfo.ads \
- ada/sinfo.adb ada/sinfo-cn.ads ada/sinput.ads ada/sinput.adb \
- ada/snames.ads ada/stand.ads ada/stringt.ads ada/style.ads \
- ada/styleg.ads ada/styleg.adb ada/stylesw.ads ada/system.ads \
- ada/s-assert.ads ada/s-exctab.ads ada/s-htable.ads ada/s-imenne.ads \
- ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads ada/s-rident.ads \
- ada/s-secsta.ads ada/s-soflin.ads ada/s-stache.ads ada/s-stalib.ads \
- ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads \
- ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads ada/table.adb \
- ada/targparm.ads ada/tbuild.ads ada/tree_io.ads ada/ttypes.ads \
- ada/types.ads ada/uintp.ads ada/uname.ads ada/unchconv.ads \
- ada/unchdeal.ads ada/urealp.ads ada/warnsw.ads ada/widechar.ads
-
-ada/sem_ch11.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/checks.ads ada/debug.ads ada/einfo.ads \
- ada/einfo.adb ada/err_vars.ads ada/errout.ads ada/erroutc.ads \
- ada/exp_code.ads ada/exp_tss.ads ada/fname.ads ada/hostparm.ads \
- ada/lib.ads ada/lib-util.ads ada/lib-xref.ads ada/namet.ads \
- ada/nlists.ads ada/nlists.adb ada/nmake.ads ada/nmake.adb ada/opt.ads \
- ada/output.ads ada/par_sco.ads ada/put_spark_xrefs.ads ada/restrict.ads \
- ada/rident.ads ada/rtsfind.ads ada/sem.ads ada/sem_aux.ads \
- ada/sem_ch11.ads ada/sem_ch11.adb ada/sem_ch13.ads ada/sem_ch5.ads \
- ada/sem_ch8.ads ada/sem_eval.ads ada/sem_res.ads ada/sem_util.ads \
- ada/sem_warn.ads ada/sem_warn.adb ada/sinfo.ads ada/sinfo.adb \
- ada/sinput.ads ada/snames.ads ada/stand.ads ada/stringt.ads \
- ada/system.ads ada/s-assert.ads ada/s-exctab.ads ada/s-imenne.ads \
- ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads ada/s-rident.ads \
- ada/s-soflin.ads ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads \
- ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads \
- ada/s-wchcon.ads ada/table.ads ada/table.adb ada/tree_io.ads \
- ada/types.ads ada/uintp.ads ada/unchconv.ads ada/unchdeal.ads \
- ada/urealp.ads
-
-ada/sem_ch12.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/aspects.adb \
- ada/atree.ads ada/atree.adb ada/casing.ads ada/checks.ads ada/csets.ads \
- ada/debug.ads ada/debug_a.ads ada/einfo.ads ada/einfo.adb \
- ada/elists.ads ada/elists.adb ada/err_vars.ads ada/errout.ads \
- ada/erroutc.ads ada/exp_ch11.ads ada/exp_ch7.ads ada/exp_disp.ads \
- ada/exp_dist.ads ada/exp_tss.ads ada/exp_util.ads ada/expander.ads \
- ada/fname.ads ada/fname-uf.ads ada/freeze.ads ada/get_targ.ads \
- ada/gnat.ads ada/g-hesorg.ads ada/g-htable.ads ada/hostparm.ads \
- ada/inline.ads ada/inline.adb ada/itypes.ads ada/lib.ads ada/lib.adb \
- ada/lib-list.adb ada/lib-load.ads ada/lib-sort.adb ada/lib-util.ads \
- ada/lib-xref.ads ada/namet.ads ada/namet-sp.ads ada/nlists.ads \
- ada/nlists.adb ada/nmake.ads ada/nmake.adb ada/opt.ads ada/output.ads \
- ada/put_spark_xrefs.ads ada/restrict.ads ada/rident.ads ada/rtsfind.ads \
- ada/rtsfind.adb ada/scans.ads ada/sem.ads ada/sem.adb ada/sem_attr.ads \
- ada/sem_aux.ads ada/sem_cat.ads ada/sem_ch10.ads ada/sem_ch11.ads \
- ada/sem_ch12.ads ada/sem_ch12.adb ada/sem_ch13.ads ada/sem_ch2.ads \
- ada/sem_ch3.ads ada/sem_ch4.ads ada/sem_ch5.ads ada/sem_ch6.ads \
- ada/sem_ch7.ads ada/sem_ch8.ads ada/sem_ch9.ads ada/sem_dim.ads \
- ada/sem_disp.ads ada/sem_dist.ads ada/sem_elab.ads ada/sem_elim.ads \
- ada/sem_eval.ads ada/sem_prag.ads ada/sem_res.ads ada/sem_type.ads \
- ada/sem_util.ads ada/sem_util.adb ada/sem_warn.ads ada/set_targ.ads \
- ada/sinfo.ads ada/sinfo.adb ada/sinfo-cn.ads ada/sinput.ads \
- ada/sinput-l.ads ada/snames.ads ada/stand.ads ada/stringt.ads \
- ada/style.ads ada/styleg.ads ada/styleg.adb ada/stylesw.ads \
- ada/system.ads ada/s-assert.ads ada/s-exctab.ads ada/s-exctab.adb \
- ada/s-htable.ads ada/s-htable.adb ada/s-imenne.ads ada/s-memory.ads \
- ada/s-os_lib.ads ada/s-parame.ads ada/s-rident.ads ada/s-secsta.ads \
- ada/s-soflin.ads ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads \
- ada/s-stoele.adb ada/s-strhas.ads ada/s-string.ads ada/s-traent.ads \
- ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads ada/table.adb \
- ada/targparm.ads ada/tbuild.ads ada/tbuild.adb ada/tree_io.ads \
- ada/ttypes.ads ada/types.ads ada/uintp.ads ada/uintp.adb ada/uname.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads ada/urealp.adb \
- ada/warnsw.ads ada/widechar.ads
-
-ada/sem_ch13.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/aspects.adb \
- ada/atree.ads ada/atree.adb ada/casing.ads ada/checks.ads ada/csets.ads \
- ada/debug.ads ada/einfo.ads ada/einfo.adb ada/elists.ads ada/elists.adb \
- ada/err_vars.ads ada/errout.ads ada/erroutc.ads ada/eval_fat.ads \
- ada/exp_aggr.ads ada/exp_ch11.ads ada/exp_ch6.ads ada/exp_ch7.ads \
- ada/exp_disp.ads ada/exp_dist.ads ada/exp_tss.ads ada/exp_util.ads \
- ada/exp_util.adb ada/fname.ads ada/fname-uf.ads ada/freeze.ads \
- ada/get_targ.ads ada/gnat.ads ada/g-hesorg.ads ada/g-hesorg.adb \
- ada/g-htable.ads ada/hostparm.ads ada/inline.ads ada/interfac.ads \
- ada/itypes.ads ada/lib.ads ada/lib.adb ada/lib-list.adb \
- ada/lib-load.ads ada/lib-sort.adb ada/lib-util.ads ada/lib-xref.ads \
- ada/namet.ads ada/namet.adb ada/namet-sp.ads ada/nlists.ads \
- ada/nlists.adb ada/nmake.ads ada/nmake.adb ada/opt.ads ada/output.ads \
- ada/put_spark_xrefs.ads ada/restrict.ads ada/rident.ads ada/rtsfind.ads \
- ada/rtsfind.adb ada/scans.ads ada/sem.ads ada/sem_attr.ads \
- ada/sem_aux.ads ada/sem_aux.adb ada/sem_cat.ads ada/sem_ch13.ads \
- ada/sem_ch13.adb ada/sem_ch3.ads ada/sem_ch6.ads ada/sem_ch7.ads \
- ada/sem_ch8.ads ada/sem_ch9.ads ada/sem_dim.ads ada/sem_disp.ads \
- ada/sem_dist.ads ada/sem_eval.ads ada/sem_eval.adb ada/sem_prag.ads \
- ada/sem_res.ads ada/sem_type.ads ada/sem_util.ads ada/sem_util.adb \
- ada/sem_warn.ads ada/set_targ.ads ada/sinfo.ads ada/sinfo.adb \
- ada/sinput.ads ada/snames.ads ada/stand.ads ada/stringt.ads \
- ada/style.ads ada/styleg.ads ada/styleg.adb ada/stylesw.ads \
- ada/system.ads ada/s-assert.ads ada/s-exctab.ads ada/s-exctab.adb \
- ada/s-htable.ads ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads \
- ada/s-parame.ads ada/s-rident.ads ada/s-secsta.ads ada/s-soflin.ads \
- ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb \
- ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads \
- ada/table.ads ada/table.adb ada/targparm.ads ada/tbuild.ads \
- ada/tbuild.adb ada/tree_io.ads ada/ttypes.ads ada/types.ads \
- ada/uintp.ads ada/uintp.adb ada/uname.ads ada/unchconv.ads \
- ada/unchdeal.ads ada/urealp.ads ada/urealp.adb ada/validsw.ads \
- ada/warnsw.ads ada/widechar.ads
-
-ada/sem_ch2.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/debug.ads ada/einfo.ads \
- ada/hostparm.ads ada/namet.ads ada/nlists.ads ada/opt.ads \
- ada/output.ads ada/restrict.ads ada/rident.ads ada/sem_ch2.ads \
- ada/sem_ch2.adb ada/sem_ch8.ads ada/sem_dim.ads ada/sinfo.ads \
- ada/sinfo.adb ada/sinput.ads ada/snames.ads ada/stand.ads \
- ada/system.ads ada/s-assert.ads ada/s-carun8.ads ada/s-exctab.ads \
- ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads \
- ada/s-rident.ads ada/s-stalib.ads ada/s-string.ads ada/s-traent.ads \
- ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads ada/table.adb \
- ada/tree_io.ads ada/types.ads ada/types.adb ada/uintp.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads
-
-ada/sem_ch3.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/checks.ads ada/checks.adb \
- ada/csets.ads ada/debug.ads ada/debug_a.ads ada/einfo.ads ada/einfo.adb \
- ada/elists.ads ada/elists.adb ada/err_vars.ads ada/errout.ads \
- ada/erroutc.ads ada/eval_fat.ads ada/exp_aggr.ads ada/exp_ch11.ads \
- ada/exp_ch2.ads ada/exp_ch3.ads ada/exp_ch4.ads ada/exp_ch6.ads \
- ada/exp_ch7.ads ada/exp_ch9.ads ada/exp_disp.ads ada/exp_dist.ads \
- ada/exp_pakd.ads ada/exp_tss.ads ada/exp_util.ads ada/exp_util.adb \
- ada/expander.ads ada/fname.ads ada/fname-uf.ads ada/freeze.ads \
- ada/get_targ.ads ada/gnat.ads ada/g-hesorg.ads ada/g-htable.ads \
- ada/hostparm.ads ada/inline.ads ada/interfac.ads ada/itypes.ads \
- ada/layout.ads ada/lib.ads ada/lib.adb ada/lib-list.adb \
- ada/lib-load.ads ada/lib-sort.adb ada/lib-util.ads ada/lib-xref.ads \
- ada/namet.ads ada/namet.adb ada/namet-sp.ads ada/nlists.ads \
- ada/nlists.adb ada/nmake.ads ada/nmake.adb ada/opt.ads ada/output.ads \
- ada/put_spark_xrefs.ads ada/restrict.ads ada/restrict.adb \
- ada/rident.ads ada/rtsfind.ads ada/scans.ads ada/sem.ads ada/sem.adb \
- ada/sem_attr.ads ada/sem_aux.ads ada/sem_aux.adb ada/sem_case.ads \
- ada/sem_case.adb ada/sem_cat.ads ada/sem_cat.adb ada/sem_ch10.ads \
- ada/sem_ch11.ads ada/sem_ch12.ads ada/sem_ch13.ads ada/sem_ch2.ads \
- ada/sem_ch3.ads ada/sem_ch3.adb ada/sem_ch4.ads ada/sem_ch5.ads \
- ada/sem_ch6.ads ada/sem_ch7.ads ada/sem_ch8.ads ada/sem_ch9.ads \
- ada/sem_dim.ads ada/sem_disp.ads ada/sem_dist.ads ada/sem_elim.ads \
- ada/sem_eval.ads ada/sem_eval.adb ada/sem_mech.ads ada/sem_prag.ads \
- ada/sem_res.ads ada/sem_smem.ads ada/sem_type.ads ada/sem_util.ads \
- ada/sem_util.adb ada/sem_warn.ads ada/set_targ.ads ada/sinfo.ads \
- ada/sinfo.adb ada/sinput.ads ada/snames.ads ada/sprint.ads \
- ada/stand.ads ada/stringt.ads ada/style.ads ada/styleg.ads \
- ada/styleg.adb ada/stylesw.ads ada/system.ads ada/s-assert.ads \
- ada/s-exctab.ads ada/s-htable.ads ada/s-imenne.ads ada/s-memory.ads \
- ada/s-os_lib.ads ada/s-parame.ads ada/s-rident.ads ada/s-secsta.ads \
- ada/s-soflin.ads ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads \
- ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads \
- ada/s-wchcon.ads ada/table.ads ada/table.adb ada/targparm.ads \
- ada/tbuild.ads ada/tbuild.adb ada/tree_io.ads ada/ttypes.ads \
- ada/types.ads ada/uintp.ads ada/uintp.adb ada/uname.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads ada/urealp.adb \
- ada/validsw.ads ada/warnsw.ads ada/widechar.ads
-
-ada/sem_ch4.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/checks.ads ada/csets.ads ada/debug.ads \
- ada/debug_a.ads ada/einfo.ads ada/einfo.adb ada/elists.ads \
- ada/elists.adb ada/err_vars.ads ada/errout.ads ada/erroutc.ads \
- ada/eval_fat.ads ada/exp_ch11.ads ada/exp_ch6.ads ada/exp_ch7.ads \
- ada/exp_disp.ads ada/exp_tss.ads ada/exp_util.ads ada/expander.ads \
- ada/fname.ads ada/fname-uf.ads ada/freeze.ads ada/get_targ.ads \
- ada/gnat.ads ada/g-hesorg.ads ada/g-htable.ads ada/hostparm.ads \
- ada/interfac.ads ada/itypes.ads ada/lib.ads ada/lib.adb \
- ada/lib-list.adb ada/lib-sort.adb ada/lib-util.ads ada/lib-xref.ads \
- ada/namet.ads ada/namet.adb ada/namet-sp.ads ada/nlists.ads \
- ada/nlists.adb ada/nmake.ads ada/nmake.adb ada/opt.ads ada/output.ads \
- ada/put_spark_xrefs.ads ada/restrict.ads ada/restrict.adb \
- ada/rident.ads ada/rtsfind.ads ada/scans.ads ada/sem.ads \
- ada/sem_aggr.ads ada/sem_attr.ads ada/sem_aux.ads ada/sem_case.ads \
- ada/sem_case.adb ada/sem_cat.ads ada/sem_ch13.ads ada/sem_ch3.ads \
- ada/sem_ch4.ads ada/sem_ch4.adb ada/sem_ch6.ads ada/sem_ch8.ads \
- ada/sem_dim.ads ada/sem_disp.ads ada/sem_dist.ads ada/sem_elab.ads \
- ada/sem_elim.ads ada/sem_eval.ads ada/sem_eval.adb ada/sem_intr.ads \
- ada/sem_res.ads ada/sem_res.adb ada/sem_type.ads ada/sem_util.ads \
- ada/sem_util.adb ada/sem_warn.ads ada/set_targ.ads ada/sinfo.ads \
- ada/sinfo.adb ada/sinfo-cn.ads ada/sinput.ads ada/snames.ads \
- ada/stand.ads ada/stringt.ads ada/style.ads ada/styleg.ads \
- ada/styleg.adb ada/stylesw.ads ada/system.ads ada/s-assert.ads \
- ada/s-exctab.ads ada/s-htable.ads ada/s-imenne.ads ada/s-memory.ads \
- ada/s-os_lib.ads ada/s-parame.ads ada/s-rident.ads ada/s-secsta.ads \
- ada/s-soflin.ads ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads \
- ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads \
- ada/s-wchcon.ads ada/table.ads ada/table.adb ada/targparm.ads \
- ada/tbuild.ads ada/tbuild.adb ada/tree_io.ads ada/ttypes.ads \
- ada/types.ads ada/uintp.ads ada/uintp.adb ada/uname.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads ada/widechar.ads
-
-ada/sem_ch5.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/checks.ads ada/checks.adb \
- ada/csets.ads ada/debug.ads ada/debug_a.ads ada/einfo.ads ada/einfo.adb \
- ada/elists.ads ada/err_vars.ads ada/errout.ads ada/erroutc.ads \
- ada/eval_fat.ads ada/exp_aggr.ads ada/exp_ch11.ads ada/exp_ch2.ads \
- ada/exp_ch4.ads ada/exp_ch6.ads ada/exp_ch7.ads ada/exp_code.ads \
- ada/exp_disp.ads ada/exp_pakd.ads ada/exp_tss.ads ada/exp_util.ads \
- ada/exp_util.adb ada/expander.ads ada/fname.ads ada/fname-uf.ads \
- ada/freeze.ads ada/get_targ.ads ada/gnat.ads ada/g-hesorg.ads \
- ada/g-htable.ads ada/gnatvsn.ads ada/hostparm.ads ada/inline.ads \
- ada/itypes.ads ada/lib.ads ada/lib-load.ads ada/lib-util.ads \
- ada/lib-xref.ads ada/namet.ads ada/namet-sp.ads ada/nlists.ads \
- ada/nlists.adb ada/nmake.ads ada/nmake.adb ada/opt.ads ada/opt.adb \
- ada/output.ads ada/par_sco.ads ada/put_spark_xrefs.ads ada/restrict.ads \
- ada/restrict.adb ada/rident.ads ada/rtsfind.ads ada/scans.ads \
- ada/sem.ads ada/sem.adb ada/sem_aggr.ads ada/sem_attr.ads \
- ada/sem_aux.ads ada/sem_case.ads ada/sem_case.adb ada/sem_cat.ads \
- ada/sem_ch10.ads ada/sem_ch11.ads ada/sem_ch12.ads ada/sem_ch13.ads \
- ada/sem_ch2.ads ada/sem_ch3.ads ada/sem_ch4.ads ada/sem_ch5.ads \
- ada/sem_ch5.adb ada/sem_ch6.ads ada/sem_ch7.ads ada/sem_ch8.ads \
- ada/sem_ch9.ads ada/sem_dim.ads ada/sem_disp.ads ada/sem_dist.ads \
- ada/sem_elab.ads ada/sem_elim.ads ada/sem_eval.ads ada/sem_eval.adb \
- ada/sem_intr.ads ada/sem_prag.ads ada/sem_res.ads ada/sem_res.adb \
- ada/sem_type.ads ada/sem_util.ads ada/sem_util.adb ada/sem_warn.ads \
- ada/sem_warn.adb ada/set_targ.ads ada/sinfo.ads ada/sinfo.adb \
- ada/sinfo-cn.ads ada/sinput.ads ada/snames.ads ada/sprint.ads \
- ada/stand.ads ada/stringt.ads ada/style.ads ada/styleg.ads \
- ada/styleg.adb ada/stylesw.ads ada/system.ads ada/s-assert.ads \
- ada/s-exctab.ads ada/s-htable.ads ada/s-imenne.ads ada/s-memory.ads \
- ada/s-os_lib.ads ada/s-parame.ads ada/s-rident.ads ada/s-secsta.ads \
- ada/s-soflin.ads ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads \
- ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads \
- ada/s-wchcon.ads ada/table.ads ada/table.adb ada/targparm.ads \
- ada/tbuild.ads ada/tree_io.ads ada/ttypes.ads ada/types.ads \
- ada/uintp.ads ada/uintp.adb ada/uname.ads ada/unchconv.ads \
- ada/unchdeal.ads ada/urealp.ads ada/validsw.ads ada/warnsw.ads
-
-ada/sem_ch6.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/checks.ads ada/csets.ads ada/debug.ads \
- ada/debug_a.ads ada/einfo.ads ada/einfo.adb ada/elists.ads \
- ada/elists.adb ada/err_vars.ads ada/errout.ads ada/erroutc.ads \
- ada/eval_fat.ads ada/exp_ch11.ads ada/exp_ch6.ads ada/exp_ch7.ads \
- ada/exp_ch9.ads ada/exp_dbug.ads ada/exp_disp.ads ada/exp_tss.ads \
- ada/exp_util.ads ada/expander.ads ada/fname.ads ada/fname-uf.ads \
- ada/freeze.ads ada/get_targ.ads ada/gnat.ads ada/g-hesorg.ads \
- ada/g-htable.ads ada/gnatvsn.ads ada/hostparm.ads ada/inline.ads \
- ada/interfac.ads ada/itypes.ads ada/layout.ads ada/lib.ads ada/lib.adb \
- ada/lib-list.adb ada/lib-load.ads ada/lib-sort.adb ada/lib-util.ads \
- ada/lib-xref.ads ada/namet.ads ada/namet.adb ada/namet-sp.ads \
- ada/nlists.ads ada/nlists.adb ada/nmake.ads ada/nmake.adb ada/opt.ads \
- ada/opt.adb ada/output.ads ada/put_spark_xrefs.ads ada/restrict.ads \
- ada/restrict.adb ada/rident.ads ada/rtsfind.ads ada/scans.ads \
- ada/sem.ads ada/sem.adb ada/sem_attr.ads ada/sem_aux.ads \
- ada/sem_aux.adb ada/sem_cat.ads ada/sem_ch10.ads ada/sem_ch11.ads \
- ada/sem_ch12.ads ada/sem_ch13.ads ada/sem_ch2.ads ada/sem_ch3.ads \
- ada/sem_ch4.ads ada/sem_ch5.ads ada/sem_ch6.ads ada/sem_ch6.adb \
- ada/sem_ch7.ads ada/sem_ch8.ads ada/sem_ch9.ads ada/sem_dim.ads \
- ada/sem_disp.ads ada/sem_dist.ads ada/sem_elim.ads ada/sem_eval.ads \
- ada/sem_eval.adb ada/sem_mech.ads ada/sem_prag.ads ada/sem_res.ads \
- ada/sem_type.ads ada/sem_util.ads ada/sem_util.adb ada/sem_warn.ads \
- ada/set_targ.ads ada/sinfo.ads ada/sinfo.adb ada/sinfo-cn.ads \
- ada/sinput.ads ada/snames.ads ada/snames.adb ada/stand.ads \
- ada/stringt.ads ada/stringt.adb ada/style.ads ada/styleg.ads \
- ada/styleg.adb ada/stylesw.ads ada/system.ads ada/s-assert.ads \
- ada/s-carun8.ads ada/s-exctab.ads ada/s-htable.ads ada/s-imenne.ads \
- ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads ada/s-rident.ads \
- ada/s-secsta.ads ada/s-soflin.ads ada/s-stache.ads ada/s-stalib.ads \
- ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads \
- ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads ada/table.adb \
- ada/targparm.ads ada/tbuild.ads ada/tbuild.adb ada/tree_io.ads \
- ada/ttypes.ads ada/types.ads ada/uintp.ads ada/uintp.adb ada/uname.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads ada/validsw.ads \
- ada/warnsw.ads ada/widechar.ads
-
-ada/sem_ch7.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/checks.ads ada/csets.ads ada/debug.ads \
- ada/einfo.ads ada/einfo.adb ada/elists.ads ada/elists.adb \
- ada/err_vars.ads ada/errout.ads ada/erroutc.ads ada/exp_ch11.ads \
- ada/exp_dbug.ads ada/exp_disp.ads ada/exp_dist.ads ada/exp_tss.ads \
- ada/exp_util.ads ada/fname.ads ada/freeze.ads ada/get_targ.ads \
- ada/gnat.ads ada/g-hesorg.ads ada/g-htable.ads ada/hostparm.ads \
- ada/inline.ads ada/interfac.ads ada/lib.ads ada/lib.adb \
- ada/lib-list.adb ada/lib-sort.adb ada/lib-util.ads ada/lib-xref.ads \
- ada/namet.ads ada/namet.adb ada/namet-sp.ads ada/nlists.ads \
- ada/nlists.adb ada/nmake.ads ada/nmake.adb ada/opt.ads ada/output.ads \
- ada/put_spark_xrefs.ads ada/restrict.ads ada/rident.ads ada/rtsfind.ads \
- ada/scans.ads ada/sem.ads ada/sem_attr.ads ada/sem_aux.ads \
- ada/sem_cat.ads ada/sem_ch10.ads ada/sem_ch12.ads ada/sem_ch13.ads \
- ada/sem_ch3.ads ada/sem_ch6.ads ada/sem_ch7.ads ada/sem_ch7.adb \
- ada/sem_ch8.ads ada/sem_disp.ads ada/sem_eval.ads ada/sem_res.ads \
- ada/sem_type.ads ada/sem_util.ads ada/sem_util.adb ada/sem_warn.ads \
- ada/set_targ.ads ada/sinfo.ads ada/sinfo.adb ada/sinput.ads \
- ada/snames.ads ada/snames.adb ada/stand.ads ada/stringt.ads \
- ada/style.ads ada/styleg.ads ada/styleg.adb ada/stylesw.ads \
- ada/system.ads ada/s-assert.ads ada/s-exctab.ads ada/s-htable.ads \
- ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads \
- ada/s-rident.ads ada/s-secsta.ads ada/s-soflin.ads ada/s-stache.ads \
- ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads \
- ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads \
- ada/table.adb ada/targparm.ads ada/tbuild.ads ada/tree_io.ads \
- ada/ttypes.ads ada/types.ads ada/uintp.ads ada/uintp.adb ada/uname.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads ada/warnsw.ads \
- ada/widechar.ads
-
-ada/sem_ch8.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/checks.ads ada/csets.ads ada/debug.ads \
- ada/debug_a.ads ada/einfo.ads ada/einfo.adb ada/elists.ads \
- ada/elists.adb ada/err_vars.ads ada/errout.ads ada/erroutc.ads \
- ada/exp_ch11.ads ada/exp_ch6.ads ada/exp_ch7.ads ada/exp_disp.ads \
- ada/exp_dist.ads ada/exp_tss.ads ada/exp_util.ads ada/expander.ads \
- ada/fname.ads ada/fname-uf.ads ada/freeze.ads ada/get_targ.ads \
- ada/gnat.ads ada/g-hesorg.ads ada/g-htable.ads ada/gnatvsn.ads \
- ada/hostparm.ads ada/impunit.ads ada/inline.ads ada/interfac.ads \
- ada/itypes.ads ada/lib.ads ada/lib.adb ada/lib-list.adb \
- ada/lib-load.ads ada/lib-sort.adb ada/lib-util.ads ada/lib-xref.ads \
- ada/namet.ads ada/namet.adb ada/namet-sp.ads ada/nlists.ads \
- ada/nlists.adb ada/nmake.ads ada/nmake.adb ada/opt.ads ada/opt.adb \
- ada/output.ads ada/put_spark_xrefs.ads ada/restrict.ads \
- ada/restrict.adb ada/rident.ads ada/rtsfind.ads ada/rtsfind.adb \
- ada/scans.ads ada/sem.ads ada/sem.adb ada/sem_aggr.ads ada/sem_attr.ads \
- ada/sem_aux.ads ada/sem_cat.ads ada/sem_ch10.ads ada/sem_ch11.ads \
- ada/sem_ch12.ads ada/sem_ch13.ads ada/sem_ch2.ads ada/sem_ch3.ads \
- ada/sem_ch4.ads ada/sem_ch5.ads ada/sem_ch6.ads ada/sem_ch7.ads \
- ada/sem_ch8.ads ada/sem_ch8.adb ada/sem_ch9.ads ada/sem_dim.ads \
- ada/sem_disp.ads ada/sem_dist.ads ada/sem_elab.ads ada/sem_elim.ads \
- ada/sem_eval.ads ada/sem_intr.ads ada/sem_prag.ads ada/sem_res.ads \
- ada/sem_res.adb ada/sem_type.ads ada/sem_util.ads ada/sem_util.adb \
- ada/sem_warn.ads ada/set_targ.ads ada/sinfo.ads ada/sinfo.adb \
- ada/sinfo-cn.ads ada/sinput.ads ada/snames.ads ada/stand.ads \
- ada/stringt.ads ada/style.ads ada/styleg.ads ada/styleg.adb \
- ada/stylesw.ads ada/system.ads ada/s-assert.ads ada/s-exctab.ads \
- ada/s-htable.ads ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads \
- ada/s-parame.ads ada/s-rident.ads ada/s-secsta.ads ada/s-soflin.ads \
- ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb \
- ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads \
- ada/table.ads ada/table.adb ada/targparm.ads ada/tbuild.ads \
- ada/tree_io.ads ada/ttypes.ads ada/types.ads ada/uintp.ads \
- ada/uintp.adb ada/uname.ads ada/unchconv.ads ada/unchdeal.ads \
- ada/urealp.ads ada/warnsw.ads ada/widechar.ads
-
-ada/sem_ch9.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/aspects.adb \
- ada/atree.ads ada/atree.adb ada/casing.ads ada/checks.ads \
- ada/checks.adb ada/csets.ads ada/debug.ads ada/debug_a.ads \
- ada/einfo.ads ada/einfo.adb ada/elists.ads ada/err_vars.ads \
- ada/errout.ads ada/erroutc.ads ada/eval_fat.ads ada/exp_ch11.ads \
- ada/exp_ch2.ads ada/exp_ch4.ads ada/exp_ch6.ads ada/exp_ch7.ads \
- ada/exp_ch9.ads ada/exp_disp.ads ada/exp_pakd.ads ada/exp_tss.ads \
- ada/exp_util.ads ada/expander.ads ada/fname.ads ada/fname-uf.ads \
- ada/freeze.ads ada/get_targ.ads ada/gnat.ads ada/g-htable.ads \
- ada/gnatvsn.ads ada/hostparm.ads ada/inline.ads ada/itypes.ads \
- ada/layout.ads ada/lib.ads ada/lib-load.ads ada/lib-util.ads \
- ada/lib-xref.ads ada/namet.ads ada/namet-sp.ads ada/nlists.ads \
- ada/nlists.adb ada/nmake.ads ada/nmake.adb ada/opt.ads ada/opt.adb \
- ada/output.ads ada/put_spark_xrefs.ads ada/restrict.ads \
- ada/restrict.adb ada/rident.ads ada/rtsfind.ads ada/scans.ads \
- ada/sem.ads ada/sem.adb ada/sem_aggr.ads ada/sem_attr.ads \
- ada/sem_aux.ads ada/sem_cat.ads ada/sem_ch10.ads ada/sem_ch11.ads \
- ada/sem_ch12.ads ada/sem_ch13.ads ada/sem_ch2.ads ada/sem_ch3.ads \
- ada/sem_ch4.ads ada/sem_ch5.ads ada/sem_ch6.ads ada/sem_ch7.ads \
- ada/sem_ch8.ads ada/sem_ch9.ads ada/sem_ch9.adb ada/sem_dim.ads \
- ada/sem_disp.ads ada/sem_dist.ads ada/sem_elab.ads ada/sem_elim.ads \
- ada/sem_eval.ads ada/sem_intr.ads ada/sem_prag.ads ada/sem_res.ads \
- ada/sem_res.adb ada/sem_type.ads ada/sem_util.ads ada/sem_util.adb \
- ada/sem_warn.ads ada/set_targ.ads ada/sinfo.ads ada/sinfo.adb \
- ada/sinfo-cn.ads ada/sinput.ads ada/snames.ads ada/sprint.ads \
- ada/stand.ads ada/stringt.ads ada/style.ads ada/styleg.ads \
- ada/styleg.adb ada/stylesw.ads ada/system.ads ada/s-assert.ads \
- ada/s-exctab.ads ada/s-htable.ads ada/s-imenne.ads ada/s-memory.ads \
- ada/s-os_lib.ads ada/s-parame.ads ada/s-rident.ads ada/s-secsta.ads \
- ada/s-soflin.ads ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads \
- ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads \
- ada/s-wchcon.ads ada/table.ads ada/table.adb ada/targparm.ads \
- ada/tbuild.ads ada/tree_io.ads ada/ttypes.ads ada/types.ads \
- ada/uintp.ads ada/uintp.adb ada/uname.ads ada/unchconv.ads \
- ada/unchdeal.ads ada/urealp.ads ada/validsw.ads ada/warnsw.ads
-
-ada/sem_dim.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/checks.ads ada/csets.ads ada/debug.ads \
- ada/einfo.ads ada/einfo.adb ada/elists.ads ada/err_vars.ads \
- ada/errout.ads ada/erroutc.ads ada/exp_ch11.ads ada/exp_disp.ads \
- ada/exp_dist.ads ada/exp_tss.ads ada/exp_util.ads ada/fname.ads \
- ada/fname-uf.ads ada/freeze.ads ada/get_targ.ads ada/gnat.ads \
- ada/g-byorma.ads ada/g-hesorg.ads ada/g-htable.ads ada/hostparm.ads \
- ada/lib.ads ada/lib.adb ada/lib-list.adb ada/lib-load.ads \
- ada/lib-sort.adb ada/lib-util.ads ada/lib-xref.ads ada/namet.ads \
- ada/namet-sp.ads ada/nlists.ads ada/nlists.adb ada/nmake.ads \
- ada/nmake.adb ada/opt.ads ada/output.ads ada/put_spark_xrefs.ads \
- ada/restrict.ads ada/rident.ads ada/rtsfind.ads ada/rtsfind.adb \
- ada/scans.ads ada/sem.ads ada/sem_attr.ads ada/sem_aux.ads \
- ada/sem_ch7.ads ada/sem_ch8.ads ada/sem_dim.ads ada/sem_dim.adb \
- ada/sem_disp.ads ada/sem_dist.ads ada/sem_eval.ads ada/sem_res.ads \
- ada/sem_type.ads ada/sem_util.ads ada/sem_util.adb ada/set_targ.ads \
- ada/sinfo.ads ada/sinfo.adb ada/sinput.ads ada/sinput.adb \
- ada/snames.ads ada/stand.ads ada/stringt.ads ada/stringt.adb \
- ada/style.ads ada/styleg.ads ada/styleg.adb ada/stylesw.ads \
- ada/system.ads ada/s-assert.ads ada/s-exctab.ads ada/s-htable.ads \
- ada/s-htable.adb ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads \
- ada/s-parame.ads ada/s-rident.ads ada/s-secsta.ads ada/s-soflin.ads \
- ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb \
- ada/s-strhas.ads ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads \
- ada/s-wchcon.ads ada/table.ads ada/table.adb ada/targparm.ads \
- ada/tbuild.ads ada/tbuild.adb ada/tree_io.ads ada/ttypes.ads \
- ada/types.ads ada/uintp.ads ada/uname.ads ada/unchconv.ads \
- ada/unchdeal.ads ada/urealp.ads ada/widechar.ads
-
-ada/sem_disp.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/checks.ads ada/csets.ads ada/debug.ads \
- ada/einfo.ads ada/einfo.adb ada/elists.ads ada/elists.adb \
- ada/err_vars.ads ada/errout.ads ada/erroutc.ads ada/exp_atag.ads \
- ada/exp_cg.ads ada/exp_ch11.ads ada/exp_ch6.ads ada/exp_ch7.ads \
- ada/exp_dbug.ads ada/exp_disp.ads ada/exp_disp.adb ada/exp_tss.ads \
- ada/exp_util.ads ada/fname.ads ada/fname-uf.ads ada/freeze.ads \
- ada/get_targ.ads ada/gnat.ads ada/g-htable.ads ada/gnatvsn.ads \
- ada/hostparm.ads ada/interfac.ads ada/itypes.ads ada/layout.ads \
- ada/lib.ads ada/lib-util.ads ada/lib-xref.ads ada/namet.ads \
- ada/namet.adb ada/namet-sp.ads ada/nlists.ads ada/nlists.adb \
- ada/nmake.ads ada/nmake.adb ada/opt.ads ada/opt.adb ada/output.ads \
- ada/put_spark_xrefs.ads ada/restrict.ads ada/restrict.adb \
- ada/rident.ads ada/rtsfind.ads ada/scans.ads ada/scil_ll.ads \
- ada/sem.ads ada/sem_attr.ads ada/sem_aux.ads ada/sem_aux.adb \
- ada/sem_ch3.ads ada/sem_ch6.ads ada/sem_ch7.ads ada/sem_ch8.ads \
- ada/sem_disp.ads ada/sem_disp.adb ada/sem_eval.ads ada/sem_res.ads \
- ada/sem_type.ads ada/sem_util.ads ada/sem_util.adb ada/set_targ.ads \
- ada/sinfo.ads ada/sinfo.adb ada/sinput.ads ada/snames.ads ada/stand.ads \
- ada/stringt.ads ada/style.ads ada/styleg.ads ada/styleg.adb \
- ada/stylesw.ads ada/system.ads ada/s-assert.ads ada/s-exctab.ads \
- ada/s-htable.ads ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads \
- ada/s-parame.ads ada/s-rident.ads ada/s-secsta.ads ada/s-soflin.ads \
- ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb \
- ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads \
- ada/table.ads ada/table.adb ada/targparm.ads ada/tbuild.ads \
- ada/tree_io.ads ada/ttypes.ads ada/types.ads ada/uintp.ads \
- ada/uname.ads ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads \
- ada/widechar.ads
-
-ada/sem_dist.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/debug.ads ada/einfo.ads ada/einfo.adb \
- ada/err_vars.ads ada/errout.ads ada/erroutc.ads ada/exp_dist.ads \
- ada/exp_tss.ads ada/hostparm.ads ada/namet.ads ada/nlists.ads \
- ada/nlists.adb ada/nmake.ads ada/nmake.adb ada/opt.ads ada/output.ads \
- ada/rtsfind.ads ada/sem.ads ada/sem_aux.ads ada/sem_disp.ads \
- ada/sem_dist.ads ada/sem_dist.adb ada/sem_eval.ads ada/sem_res.ads \
- ada/sem_util.ads ada/sinfo.ads ada/sinfo.adb ada/sinput.ads \
- ada/snames.ads ada/stand.ads ada/stringt.ads ada/stringt.adb \
- ada/system.ads ada/s-assert.ads ada/s-carun8.ads ada/s-exctab.ads \
- ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads \
- ada/s-stalib.ads ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads \
- ada/s-wchcon.ads ada/table.ads ada/table.adb ada/tbuild.ads \
- ada/tree_io.ads ada/types.ads ada/types.adb ada/uintp.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads
-
-ada/sem_elab.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/checks.ads ada/csets.ads ada/debug.ads \
- ada/einfo.ads ada/einfo.adb ada/elists.ads ada/elists.adb \
- ada/err_vars.ads ada/errout.ads ada/erroutc.ads ada/exp_ch11.ads \
- ada/exp_disp.ads ada/exp_tss.ads ada/exp_util.ads ada/expander.ads \
- ada/fname.ads ada/fname-uf.ads ada/freeze.ads ada/get_targ.ads \
- ada/gnat.ads ada/g-byorma.ads ada/g-hesorg.ads ada/g-htable.ads \
- ada/hostparm.ads ada/interfac.ads ada/lib.ads ada/lib.adb \
- ada/lib-list.adb ada/lib-load.ads ada/lib-sort.adb ada/lib-util.ads \
- ada/lib-xref.ads ada/namet.ads ada/namet.adb ada/namet-sp.ads \
- ada/nlists.ads ada/nlists.adb ada/nmake.ads ada/nmake.adb ada/opt.ads \
- ada/output.ads ada/put_spark_xrefs.ads ada/restrict.ads \
- ada/restrict.adb ada/rident.ads ada/rtsfind.ads ada/scans.ads \
- ada/sem.ads ada/sem_attr.ads ada/sem_aux.ads ada/sem_cat.ads \
- ada/sem_ch7.ads ada/sem_ch8.ads ada/sem_disp.ads ada/sem_elab.ads \
- ada/sem_elab.adb ada/sem_eval.ads ada/sem_res.ads ada/sem_type.ads \
- ada/sem_util.ads ada/sem_util.adb ada/set_targ.ads ada/sinfo.ads \
- ada/sinfo.adb ada/sinput.ads ada/sinput.adb ada/snames.ads \
- ada/stand.ads ada/stringt.ads ada/style.ads ada/styleg.ads \
- ada/styleg.adb ada/stylesw.ads ada/system.ads ada/s-assert.ads \
- ada/s-exctab.ads ada/s-htable.ads ada/s-imenne.ads ada/s-memory.ads \
- ada/s-os_lib.ads ada/s-parame.ads ada/s-rident.ads ada/s-secsta.ads \
- ada/s-soflin.ads ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads \
- ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads \
- ada/s-wchcon.ads ada/table.ads ada/table.adb ada/targparm.ads \
- ada/tbuild.ads ada/tbuild.adb ada/tree_io.ads ada/ttypes.ads \
- ada/types.ads ada/uintp.ads ada/uname.ads ada/unchconv.ads \
- ada/unchdeal.ads ada/urealp.ads ada/widechar.ads
-
-ada/sem_elim.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/csets.ads ada/debug.ads ada/einfo.ads \
- ada/einfo.adb ada/err_vars.ads ada/errout.ads ada/erroutc.ads \
- ada/exp_tss.ads ada/fname.ads ada/gnat.ads ada/g-byorma.ads \
- ada/g-hesorg.ads ada/g-htable.ads ada/hostparm.ads ada/lib.ads \
- ada/lib.adb ada/lib-list.adb ada/lib-sort.adb ada/namet.ads \
- ada/nlists.ads ada/nlists.adb ada/opt.ads ada/output.ads ada/scans.ads \
- ada/sem.ads ada/sem_aux.ads ada/sem_aux.adb ada/sem_elim.ads \
- ada/sem_elim.adb ada/sem_prag.ads ada/sem_util.ads ada/sinfo.ads \
- ada/sinfo.adb ada/sinput.ads ada/sinput.adb ada/snames.ads \
- ada/stand.ads ada/stringt.ads ada/system.ads ada/s-assert.ads \
- ada/s-exctab.ads ada/s-htable.ads ada/s-htable.adb ada/s-imenne.ads \
- ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads ada/s-secsta.ads \
- ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb ada/s-strhas.ads \
- ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads \
- ada/table.ads ada/table.adb ada/tree_io.ads ada/types.ads ada/uintp.ads \
- ada/uname.ads ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads \
- ada/widechar.ads
-
-ada/sem_eval.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/checks.ads ada/csets.ads ada/debug.ads \
- ada/debug_a.ads ada/einfo.ads ada/einfo.adb ada/elists.ads \
- ada/elists.adb ada/err_vars.ads ada/errout.ads ada/erroutc.ads \
- ada/eval_fat.ads ada/exp_ch11.ads ada/exp_ch6.ads ada/exp_ch7.ads \
- ada/exp_disp.ads ada/exp_tss.ads ada/exp_util.ads ada/expander.ads \
- ada/fname.ads ada/freeze.ads ada/get_targ.ads ada/gnat.ads \
- ada/g-htable.ads ada/hostparm.ads ada/interfac.ads ada/itypes.ads \
- ada/lib.ads ada/lib-util.ads ada/lib-xref.ads ada/namet.ads \
- ada/namet.adb ada/namet-sp.ads ada/nlists.ads ada/nlists.adb \
- ada/nmake.ads ada/nmake.adb ada/opt.ads ada/output.ads \
- ada/put_spark_xrefs.ads ada/restrict.ads ada/rident.ads ada/rtsfind.ads \
- ada/scans.ads ada/sem.ads ada/sem_aggr.ads ada/sem_attr.ads \
- ada/sem_aux.ads ada/sem_aux.adb ada/sem_cat.ads ada/sem_ch13.ads \
- ada/sem_ch4.ads ada/sem_ch6.ads ada/sem_ch8.ads ada/sem_dim.ads \
- ada/sem_disp.ads ada/sem_dist.ads ada/sem_elab.ads ada/sem_elim.ads \
- ada/sem_eval.ads ada/sem_eval.adb ada/sem_intr.ads ada/sem_res.ads \
- ada/sem_res.adb ada/sem_type.ads ada/sem_util.ads ada/sem_util.adb \
- ada/sem_warn.ads ada/set_targ.ads ada/sinfo.ads ada/sinfo.adb \
- ada/sinfo-cn.ads ada/sinput.ads ada/snames.ads ada/stand.ads \
- ada/stringt.ads ada/stringt.adb ada/style.ads ada/styleg.ads \
- ada/styleg.adb ada/stylesw.ads ada/system.ads ada/s-assert.ads \
- ada/s-exctab.ads ada/s-htable.ads ada/s-imenne.ads ada/s-memory.ads \
- ada/s-os_lib.ads ada/s-parame.ads ada/s-rident.ads ada/s-secsta.ads \
- ada/s-soflin.ads ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads \
- ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads \
- ada/s-wchcon.ads ada/table.ads ada/table.adb ada/targparm.ads \
- ada/tbuild.ads ada/tbuild.adb ada/tree_io.ads ada/ttypes.ads \
- ada/types.ads ada/uintp.ads ada/uintp.adb ada/uname.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads ada/urealp.adb \
- ada/widechar.ads
-
-ada/sem_intr.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/csets.ads ada/debug.ads ada/einfo.ads \
- ada/einfo.adb ada/err_vars.ads ada/errout.ads ada/erroutc.ads \
- ada/exp_tss.ads ada/fname.ads ada/gnat.ads ada/g-hesorg.ads \
- ada/hostparm.ads ada/interfac.ads ada/lib.ads ada/lib.adb \
- ada/lib-list.adb ada/lib-sort.adb ada/namet.ads ada/namet.adb \
- ada/nlists.ads ada/opt.ads ada/output.ads ada/rident.ads \
- ada/sem_aux.ads ada/sem_aux.adb ada/sem_eval.ads ada/sem_intr.ads \
- ada/sem_intr.adb ada/sem_util.ads ada/sinfo.ads ada/sinfo.adb \
- ada/sinput.ads ada/snames.ads ada/stand.ads ada/stringt.ads \
- ada/stringt.adb ada/system.ads ada/s-assert.ads ada/s-exctab.ads \
- ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads \
- ada/s-rident.ads ada/s-secsta.ads ada/s-stalib.ads ada/s-stoele.ads \
- ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads \
- ada/s-wchcon.ads ada/table.ads ada/table.adb ada/targparm.ads \
- ada/tree_io.ads ada/types.ads ada/uintp.ads ada/uname.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads ada/widechar.ads
-
-ada/sem_mech.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/debug.ads ada/einfo.ads ada/einfo.adb \
- ada/err_vars.ads ada/errout.ads ada/erroutc.ads ada/exp_tss.ads \
- ada/hostparm.ads ada/interfac.ads ada/namet.ads ada/namet.adb \
- ada/nlists.ads ada/nlists.adb ada/opt.ads ada/output.ads ada/rident.ads \
- ada/sem.ads ada/sem_aux.ads ada/sem_mech.ads ada/sem_mech.adb \
- ada/sem_util.ads ada/sinfo.ads ada/sinfo.adb ada/sinput.ads \
- ada/snames.ads ada/stand.ads ada/system.ads ada/s-assert.ads \
- ada/s-exctab.ads ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads \
- ada/s-parame.ads ada/s-rident.ads ada/s-secsta.ads ada/s-stalib.ads \
- ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads \
- ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads ada/table.adb \
- ada/targparm.ads ada/tree_io.ads ada/types.ads ada/uintp.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads ada/widechar.ads
-
-ada/sem_prag.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/ali.ads ada/alloc.ads ada/aspects.ads \
- ada/aspects.adb ada/atree.ads ada/atree.adb ada/casing.ads \
- ada/checks.ads ada/checks.adb ada/csets.ads ada/debug.ads \
- ada/debug_a.ads ada/einfo.ads ada/einfo.adb ada/elists.ads \
- ada/elists.adb ada/err_vars.ads ada/errout.ads ada/erroutc.ads \
- ada/eval_fat.ads ada/exp_ch11.ads ada/exp_ch2.ads ada/exp_ch4.ads \
- ada/exp_ch6.ads ada/exp_ch7.ads ada/exp_code.ads ada/exp_disp.ads \
- ada/exp_dist.ads ada/exp_pakd.ads ada/exp_tss.ads ada/exp_util.ads \
- ada/expander.ads ada/fname.ads ada/fname-uf.ads ada/freeze.ads \
- ada/get_targ.ads ada/gnat.ads ada/g-byorma.ads ada/g-hesorg.ads \
- ada/g-htable.ads ada/gnatvsn.ads ada/hostparm.ads ada/inline.ads \
- ada/interfac.ads ada/itypes.ads ada/lib.ads ada/lib.adb \
- ada/lib-list.adb ada/lib-load.ads ada/lib-sort.adb ada/lib-util.ads \
- ada/lib-writ.ads ada/lib-writ.adb ada/lib-xref.ads ada/namet.ads \
- ada/namet.adb ada/namet-sp.ads ada/nlists.ads ada/nlists.adb \
- ada/nmake.ads ada/nmake.adb ada/opt.ads ada/osint.ads ada/osint-c.ads \
- ada/output.ads ada/par.ads ada/par_sco.ads ada/put_spark_xrefs.ads \
- ada/restrict.ads ada/restrict.adb ada/rident.ads ada/rtsfind.ads \
- ada/scans.ads ada/scn.ads ada/scng.ads ada/scng.adb ada/sem.ads \
- ada/sem.adb ada/sem_aggr.ads ada/sem_attr.ads ada/sem_aux.ads \
- ada/sem_aux.adb ada/sem_cat.ads ada/sem_ch10.ads ada/sem_ch11.ads \
- ada/sem_ch12.ads ada/sem_ch13.ads ada/sem_ch13.adb ada/sem_ch2.ads \
- ada/sem_ch3.ads ada/sem_ch4.ads ada/sem_ch5.ads ada/sem_ch6.ads \
- ada/sem_ch7.ads ada/sem_ch8.ads ada/sem_ch9.ads ada/sem_dim.ads \
- ada/sem_disp.ads ada/sem_dist.ads ada/sem_elab.ads ada/sem_elim.ads \
- ada/sem_eval.ads ada/sem_eval.adb ada/sem_intr.ads ada/sem_mech.ads \
- ada/sem_prag.ads ada/sem_prag.adb ada/sem_res.ads ada/sem_res.adb \
- ada/sem_type.ads ada/sem_util.ads ada/sem_util.adb ada/sem_vfpt.ads \
- ada/sem_warn.ads ada/sem_warn.adb ada/set_targ.ads ada/sinfo.ads \
- ada/sinfo.adb ada/sinfo-cn.ads ada/sinput.ads ada/sinput.adb \
- ada/snames.ads ada/snames.adb ada/sprint.ads ada/stand.ads \
- ada/stringt.ads ada/stringt.adb ada/style.ads ada/styleg.ads \
- ada/styleg.adb ada/stylesw.ads ada/system.ads ada/s-assert.ads \
- ada/s-casuti.ads ada/s-carun8.ads ada/s-crc32.ads ada/s-exctab.ads \
- ada/s-exctab.adb ada/s-htable.ads ada/s-imenne.ads ada/s-memory.ads \
- ada/s-os_lib.ads ada/s-parame.ads ada/s-rident.ads ada/s-secsta.ads \
- ada/s-soflin.ads ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads \
- ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads \
- ada/s-utf_32.ads ada/s-wchcon.ads ada/table.ads ada/table.adb \
- ada/targparm.ads ada/tbuild.ads ada/tbuild.adb ada/tree_io.ads \
- ada/ttypes.ads ada/types.ads ada/types.adb ada/uintp.ads ada/uintp.adb \
- ada/uname.ads ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads \
- ada/urealp.adb ada/validsw.ads ada/warnsw.ads ada/widechar.ads
-
-ada/sem_res.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/checks.ads ada/checks.adb \
- ada/csets.ads ada/debug.ads ada/debug_a.ads ada/debug_a.adb \
- ada/einfo.ads ada/einfo.adb ada/elists.ads ada/err_vars.ads \
- ada/errout.ads ada/erroutc.ads ada/eval_fat.ads ada/exp_aggr.ads \
- ada/exp_ch11.ads ada/exp_ch2.ads ada/exp_ch4.ads ada/exp_ch6.ads \
- ada/exp_ch7.ads ada/exp_disp.ads ada/exp_dist.ads ada/exp_pakd.ads \
- ada/exp_tss.ads ada/exp_util.ads ada/exp_util.adb ada/expander.ads \
- ada/fname.ads ada/fname-uf.ads ada/freeze.ads ada/get_targ.ads \
- ada/gnat.ads ada/g-hesorg.ads ada/g-htable.ads ada/gnatvsn.ads \
- ada/hostparm.ads ada/inline.ads ada/interfac.ads ada/itypes.ads \
- ada/lib.ads ada/lib.adb ada/lib-list.adb ada/lib-load.ads \
- ada/lib-sort.adb ada/lib-util.ads ada/lib-xref.ads ada/namet.ads \
- ada/namet.adb ada/namet-sp.ads ada/nlists.ads ada/nlists.adb \
- ada/nmake.ads ada/nmake.adb ada/opt.ads ada/opt.adb ada/output.ads \
- ada/put_spark_xrefs.ads ada/restrict.ads ada/restrict.adb \
- ada/rident.ads ada/rtsfind.ads ada/rtsfind.adb ada/scans.ads \
- ada/sem.ads ada/sem.adb ada/sem_aggr.ads ada/sem_attr.ads \
- ada/sem_aux.ads ada/sem_cat.ads ada/sem_ch10.ads ada/sem_ch11.ads \
- ada/sem_ch12.ads ada/sem_ch13.ads ada/sem_ch2.ads ada/sem_ch3.ads \
- ada/sem_ch4.ads ada/sem_ch5.ads ada/sem_ch6.ads ada/sem_ch7.ads \
- ada/sem_ch8.ads ada/sem_ch9.ads ada/sem_dim.ads ada/sem_disp.ads \
- ada/sem_dist.ads ada/sem_elab.ads ada/sem_elim.ads ada/sem_eval.ads \
- ada/sem_eval.adb ada/sem_intr.ads ada/sem_prag.ads ada/sem_res.ads \
- ada/sem_res.adb ada/sem_type.ads ada/sem_util.ads ada/sem_util.adb \
- ada/sem_warn.ads ada/set_targ.ads ada/sinfo.ads ada/sinfo.adb \
- ada/sinfo-cn.ads ada/sinput.ads ada/snames.ads ada/sprint.ads \
- ada/stand.ads ada/stringt.ads ada/stringt.adb ada/style.ads \
- ada/styleg.ads ada/styleg.adb ada/stylesw.ads ada/system.ads \
- ada/s-assert.ads ada/s-carun8.ads ada/s-exctab.ads ada/s-htable.ads \
- ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads \
- ada/s-rident.ads ada/s-secsta.ads ada/s-soflin.ads ada/s-stache.ads \
- ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads \
- ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads \
- ada/table.adb ada/targparm.ads ada/tbuild.ads ada/tbuild.adb \
- ada/tree_io.ads ada/ttypes.ads ada/types.ads ada/types.adb \
- ada/uintp.ads ada/uintp.adb ada/uname.ads ada/unchconv.ads \
- ada/unchdeal.ads ada/urealp.ads ada/urealp.adb ada/validsw.ads \
- ada/warnsw.ads ada/widechar.ads
-
-ada/sem_scil.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/debug.ads ada/einfo.ads ada/einfo.adb \
- ada/hostparm.ads ada/namet.ads ada/nlists.ads ada/nlists.adb \
- ada/opt.ads ada/output.ads ada/rtsfind.ads ada/scil_ll.ads \
- ada/sem_aux.ads ada/sem_scil.ads ada/sem_scil.adb ada/sinfo.ads \
- ada/sinfo.adb ada/sinput.ads ada/snames.ads ada/stand.ads \
- ada/system.ads ada/s-assert.ads ada/s-exctab.ads ada/s-imenne.ads \
- ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads ada/s-stalib.ads \
- ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads \
- ada/table.ads ada/table.adb ada/tree_io.ads ada/types.ads ada/uintp.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads
-
-ada/sem_smem.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/debug.ads ada/einfo.ads ada/einfo.adb \
- ada/err_vars.ads ada/errout.ads ada/erroutc.ads ada/hostparm.ads \
- ada/namet.ads ada/nlists.ads ada/opt.ads ada/output.ads ada/sem_aux.ads \
- ada/sem_smem.ads ada/sem_smem.adb ada/sinfo.ads ada/sinfo.adb \
- ada/sinput.ads ada/snames.ads ada/stand.ads ada/system.ads \
- ada/s-assert.ads ada/s-exctab.ads ada/s-imenne.ads ada/s-memory.ads \
- ada/s-os_lib.ads ada/s-parame.ads ada/s-stalib.ads ada/s-string.ads \
- ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads \
- ada/table.adb ada/tree_io.ads ada/types.ads ada/uintp.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads
-
-ada/sem_type.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/checks.ads ada/csets.ads ada/debug.ads \
- ada/einfo.ads ada/einfo.adb ada/elists.ads ada/elists.adb \
- ada/err_vars.ads ada/errout.ads ada/erroutc.ads ada/exp_ch11.ads \
- ada/exp_disp.ads ada/exp_tss.ads ada/exp_util.ads ada/fname.ads \
- ada/freeze.ads ada/get_targ.ads ada/gnat.ads ada/g-hesorg.ads \
- ada/g-htable.ads ada/hostparm.ads ada/inline.ads ada/interfac.ads \
- ada/lib.ads ada/lib.adb ada/lib-list.adb ada/lib-sort.adb \
- ada/lib-util.ads ada/lib-xref.ads ada/namet.ads ada/namet.adb \
- ada/namet-sp.ads ada/nlists.ads ada/nlists.adb ada/nmake.ads \
- ada/opt.ads ada/output.ads ada/put_spark_xrefs.ads ada/restrict.ads \
- ada/rident.ads ada/rtsfind.ads ada/scans.ads ada/sem.ads \
- ada/sem_attr.ads ada/sem_aux.ads ada/sem_ch12.ads ada/sem_ch6.ads \
- ada/sem_ch8.ads ada/sem_disp.ads ada/sem_dist.ads ada/sem_eval.ads \
- ada/sem_res.ads ada/sem_type.ads ada/sem_type.adb ada/sem_util.ads \
- ada/sem_util.adb ada/set_targ.ads ada/sinfo.ads ada/sinfo.adb \
- ada/sinput.ads ada/snames.ads ada/stand.ads ada/stringt.ads \
- ada/style.ads ada/styleg.ads ada/styleg.adb ada/stylesw.ads \
- ada/system.ads ada/s-assert.ads ada/s-exctab.ads ada/s-htable.ads \
- ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads \
- ada/s-rident.ads ada/s-secsta.ads ada/s-soflin.ads ada/s-stache.ads \
- ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads \
- ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads \
- ada/table.adb ada/targparm.ads ada/tbuild.ads ada/tree_io.ads \
- ada/treepr.ads ada/ttypes.ads ada/types.ads ada/uintp.ads ada/uintp.adb \
- ada/uname.ads ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads \
- ada/warnsw.ads ada/widechar.ads
-
-ada/sem_util.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/checks.ads ada/csets.ads ada/debug.ads \
- ada/debug_a.ads ada/einfo.ads ada/einfo.adb ada/elists.ads \
- ada/elists.adb ada/err_vars.ads ada/errout.ads ada/erroutc.ads \
- ada/eval_fat.ads ada/exp_ch11.ads ada/exp_disp.ads ada/exp_dist.ads \
- ada/exp_tss.ads ada/exp_util.ads ada/expander.ads ada/fname.ads \
- ada/fname-uf.ads ada/freeze.ads ada/get_targ.ads ada/gnat.ads \
- ada/g-byorma.ads ada/g-hesorg.ads ada/g-htable.ads ada/hostparm.ads \
- ada/inline.ads ada/interfac.ads ada/lib.ads ada/lib.adb \
- ada/lib-list.adb ada/lib-load.ads ada/lib-sort.adb ada/lib-util.ads \
- ada/lib-xref.ads ada/namet.ads ada/namet.adb ada/namet-sp.ads \
- ada/nlists.ads ada/nlists.adb ada/nmake.ads ada/nmake.adb ada/opt.ads \
- ada/output.ads ada/put_spark_xrefs.ads ada/restrict.ads \
- ada/restrict.adb ada/rident.ads ada/rtsfind.ads ada/rtsfind.adb \
- ada/scans.ads ada/sem.ads ada/sem.adb ada/sem_attr.ads ada/sem_aux.ads \
- ada/sem_cat.ads ada/sem_ch10.ads ada/sem_ch11.ads ada/sem_ch12.ads \
- ada/sem_ch13.ads ada/sem_ch2.ads ada/sem_ch3.ads ada/sem_ch4.ads \
- ada/sem_ch5.ads ada/sem_ch6.ads ada/sem_ch7.ads ada/sem_ch8.ads \
- ada/sem_ch9.ads ada/sem_disp.ads ada/sem_dist.ads ada/sem_eval.ads \
- ada/sem_eval.adb ada/sem_prag.ads ada/sem_res.ads ada/sem_type.ads \
- ada/sem_util.ads ada/sem_util.adb ada/sem_warn.ads ada/set_targ.ads \
- ada/sinfo.ads ada/sinfo.adb ada/sinput.ads ada/sinput.adb \
- ada/snames.ads ada/stand.ads ada/stringt.ads ada/style.ads \
- ada/styleg.ads ada/styleg.adb ada/stylesw.ads ada/system.ads \
- ada/s-assert.ads ada/s-exctab.ads ada/s-htable.ads ada/s-htable.adb \
- ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads \
- ada/s-rident.ads ada/s-secsta.ads ada/s-soflin.ads ada/s-stache.ads \
- ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb ada/s-strhas.ads \
- ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads \
- ada/table.ads ada/table.adb ada/targparm.ads ada/tbuild.ads \
- ada/tbuild.adb ada/tree_io.ads ada/ttypes.ads ada/types.ads \
- ada/uintp.ads ada/uintp.adb ada/uname.ads ada/unchconv.ads \
- ada/unchdeal.ads ada/urealp.ads ada/urealp.adb ada/warnsw.ads \
- ada/widechar.ads
-
-ada/sem_vfpt.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/atree.ads ada/cstand.ads \
- ada/debug.ads ada/einfo.ads ada/einfo.adb ada/hostparm.ads \
- ada/namet.ads ada/nlists.ads ada/opt.ads ada/output.ads ada/rident.ads \
- ada/sem_vfpt.ads ada/sem_vfpt.adb ada/sinfo.ads ada/snames.ads \
- ada/stand.ads ada/system.ads ada/s-assert.ads ada/s-exctab.ads \
- ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads \
- ada/s-rident.ads ada/s-stalib.ads ada/s-string.ads ada/s-traent.ads \
- ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads ada/table.adb \
- ada/targparm.ads ada/tree_io.ads ada/types.ads ada/uintp.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads
-
-ada/sem_warn.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/checks.ads ada/csets.ads ada/debug.ads \
- ada/einfo.ads ada/einfo.adb ada/elists.ads ada/err_vars.ads \
- ada/errout.ads ada/erroutc.ads ada/exp_ch11.ads ada/exp_code.ads \
- ada/exp_disp.ads ada/exp_tss.ads ada/exp_util.ads ada/fname.ads \
- ada/freeze.ads ada/get_targ.ads ada/gnat.ads ada/g-byorma.ads \
- ada/g-hesorg.ads ada/g-htable.ads ada/hostparm.ads ada/interfac.ads \
- ada/lib.ads ada/lib.adb ada/lib-list.adb ada/lib-sort.adb \
- ada/lib-util.ads ada/lib-xref.ads ada/namet.ads ada/namet.adb \
- ada/namet-sp.ads ada/nlists.ads ada/nlists.adb ada/nmake.ads \
- ada/opt.ads ada/output.ads ada/par_sco.ads ada/put_spark_xrefs.ads \
- ada/restrict.ads ada/rident.ads ada/rtsfind.ads ada/scans.ads \
- ada/sem.ads ada/sem_attr.ads ada/sem_aux.ads ada/sem_aux.adb \
- ada/sem_ch8.ads ada/sem_disp.ads ada/sem_eval.ads ada/sem_res.ads \
- ada/sem_type.ads ada/sem_util.ads ada/sem_util.adb ada/sem_warn.ads \
- ada/sem_warn.adb ada/set_targ.ads ada/sinfo.ads ada/sinfo.adb \
- ada/sinput.ads ada/sinput.adb ada/snames.ads ada/stand.ads \
- ada/stringt.ads ada/style.ads ada/styleg.ads ada/styleg.adb \
- ada/stylesw.ads ada/system.ads ada/s-assert.ads ada/s-exctab.ads \
- ada/s-htable.ads ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads \
- ada/s-parame.ads ada/s-rident.ads ada/s-secsta.ads ada/s-soflin.ads \
- ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb \
- ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads \
- ada/table.ads ada/table.adb ada/targparm.ads ada/tbuild.ads \
- ada/tree_io.ads ada/ttypes.ads ada/types.ads ada/uintp.ads \
- ada/uintp.adb ada/uname.ads ada/unchconv.ads ada/unchdeal.ads \
- ada/urealp.ads ada/widechar.ads
-
-ada/set_targ.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/debug.ads ada/einfo.ads \
- ada/get_targ.ads ada/hostparm.ads ada/namet.ads ada/opt.ads \
- ada/output.ads ada/set_targ.ads ada/set_targ.adb ada/snames.ads \
- ada/system.ads ada/s-assert.ads ada/s-exctab.ads ada/s-memory.ads \
- ada/s-os_lib.ads ada/s-parame.ads ada/s-stalib.ads ada/s-string.ads \
- ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads \
- ada/table.adb ada/tree_io.ads ada/types.ads ada/uintp.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads
-
-ada/sinfo-cn.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/debug.ads ada/einfo.ads \
- ada/hostparm.ads ada/namet.ads ada/nlists.ads ada/opt.ads \
- ada/output.ads ada/sinfo.ads ada/sinfo.adb ada/sinfo-cn.ads \
- ada/sinfo-cn.adb ada/sinput.ads ada/snames.ads ada/system.ads \
- ada/s-assert.ads ada/s-exctab.ads ada/s-imenne.ads ada/s-memory.ads \
- ada/s-os_lib.ads ada/s-parame.ads ada/s-stalib.ads ada/s-string.ads \
- ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads \
- ada/table.adb ada/tree_io.ads ada/types.ads ada/uintp.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads
-
-ada/sinfo.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/debug.ads ada/einfo.ads ada/gnat.ads \
- ada/g-htable.ads ada/hostparm.ads ada/namet.ads ada/nlists.ads \
- ada/opt.ads ada/output.ads ada/sinfo.ads ada/sinfo.adb ada/sinput.ads \
- ada/snames.ads ada/system.ads ada/s-assert.ads ada/s-exctab.ads \
- ada/s-htable.ads ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads \
- ada/s-parame.ads ada/s-stalib.ads ada/s-string.ads ada/s-traent.ads \
- ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads ada/table.adb \
- ada/tree_io.ads ada/types.ads ada/uintp.ads ada/uintp.adb \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads
-
-ada/sinput-c.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/debug.ads ada/einfo.ads ada/gnat.ads \
- ada/g-byorma.ads ada/hostparm.ads ada/namet.ads ada/nlists.ads \
- ada/opt.ads ada/output.ads ada/scans.ads ada/sinfo.ads ada/sinput.ads \
- ada/sinput.adb ada/sinput-c.ads ada/sinput-c.adb ada/snames.ads \
- ada/system.ads ada/s-assert.ads ada/s-exctab.ads ada/s-imenne.ads \
- ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads ada/s-secsta.ads \
- ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads \
- ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads \
- ada/table.adb ada/tree_io.ads ada/types.ads ada/uintp.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads ada/widechar.ads
-
-ada/sinput-d.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/debug.ads ada/einfo.ads ada/gnat.ads \
- ada/g-byorma.ads ada/hostparm.ads ada/namet.ads ada/nlists.ads \
- ada/opt.ads ada/osint.ads ada/osint-c.ads ada/output.ads ada/scans.ads \
- ada/sinfo.ads ada/sinput.ads ada/sinput.adb ada/sinput-d.ads \
- ada/sinput-d.adb ada/snames.ads ada/system.ads ada/s-assert.ads \
- ada/s-exctab.ads ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads \
- ada/s-parame.ads ada/s-secsta.ads ada/s-stalib.ads ada/s-stoele.ads \
- ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads \
- ada/s-wchcon.ads ada/table.ads ada/table.adb ada/tree_io.ads \
- ada/types.ads ada/uintp.ads ada/unchconv.ads ada/unchdeal.ads \
- ada/urealp.ads ada/widechar.ads
-
-ada/sinput-l.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/csets.ads ada/debug.ads ada/einfo.ads \
- ada/einfo.adb ada/err_vars.ads ada/errout.ads ada/erroutc.ads \
- ada/exp_tss.ads ada/fname.ads ada/gnat.ads ada/g-byorma.ads \
- ada/g-dyntab.ads ada/g-dyntab.adb ada/g-hesorg.ads ada/hostparm.ads \
- ada/interfac.ads ada/lib.ads ada/namet.ads ada/nlists.ads ada/opt.ads \
- ada/osint.ads ada/output.ads ada/prep.ads ada/prepcomp.ads \
- ada/restrict.ads ada/rident.ads ada/scans.ads ada/scn.ads ada/scng.ads \
- ada/scng.adb ada/sem_aux.ads ada/sem_util.ads ada/sinfo.ads \
- ada/sinfo.adb ada/sinput.ads ada/sinput.adb ada/sinput-l.ads \
- ada/sinput-l.adb ada/snames.ads ada/stand.ads ada/stringt.ads \
- ada/style.ads ada/styleg.ads ada/styleg.adb ada/stylesw.ads \
- ada/system.ads ada/s-assert.ads ada/s-crc32.ads ada/s-exctab.ads \
- ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads \
- ada/s-rident.ads ada/s-secsta.ads ada/s-soflin.ads ada/s-stache.ads \
- ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads \
- ada/s-traent.ads ada/s-unstyp.ads ada/s-utf_32.ads ada/s-wchcon.ads \
- ada/table.ads ada/table.adb ada/tree_io.ads ada/types.ads ada/uintp.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads ada/widechar.ads
-
-ada/sinput.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/debug.ads ada/einfo.ads ada/gnat.ads \
- ada/g-byorma.ads ada/hostparm.ads ada/interfac.ads ada/namet.ads \
- ada/namet.adb ada/nlists.ads ada/nlists.adb ada/opt.ads ada/output.ads \
- ada/scans.ads ada/sinfo.ads ada/sinput.ads ada/sinput.adb \
- ada/snames.ads ada/system.ads ada/s-assert.ads ada/s-exctab.ads \
- ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads \
- ada/s-secsta.ads ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb \
- ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads \
- ada/table.ads ada/table.adb ada/tree_io.ads ada/types.ads ada/uintp.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads ada/widechar.ads
-
-ada/snames.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/debug.ads ada/hostparm.ads \
- ada/interfac.ads ada/namet.ads ada/namet.adb ada/opt.ads ada/output.ads \
- ada/snames.ads ada/snames.adb ada/system.ads ada/s-assert.ads \
- ada/s-exctab.ads ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads \
- ada/s-secsta.ads ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb \
- ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads \
- ada/table.ads ada/table.adb ada/tree_io.ads ada/types.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/widechar.ads
-
-ada/spark_xrefs.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/gnat.ads ada/g-hesorg.ads ada/g-hesorg.adb \
- ada/g-table.ads ada/g-table.adb ada/hostparm.ads ada/output.ads \
- ada/output.adb ada/put_spark_xrefs.ads ada/put_spark_xrefs.adb \
- ada/spark_xrefs.ads ada/spark_xrefs.adb ada/system.ads ada/s-assert.ads \
- ada/s-exctab.ads ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads \
- ada/s-soflin.ads ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads \
- ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads \
- ada/types.ads ada/unchconv.ads ada/unchdeal.ads
-
-ada/sprint.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/csets.ads ada/debug.ads ada/einfo.ads \
- ada/einfo.adb ada/exp_tss.ads ada/fname.ads ada/gnat.ads \
- ada/g-byorma.ads ada/g-hesorg.ads ada/g-htable.ads ada/hostparm.ads \
- ada/interfac.ads ada/lib.ads ada/lib.adb ada/lib-list.adb \
- ada/lib-sort.adb ada/namet.ads ada/namet.adb ada/nlists.ads \
- ada/nlists.adb ada/opt.ads ada/output.ads ada/output.adb \
- ada/rtsfind.ads ada/scans.ads ada/sem_eval.ads ada/sem_util.ads \
- ada/sinfo.ads ada/sinfo.adb ada/sinput.ads ada/sinput.adb \
- ada/sinput-d.ads ada/snames.ads ada/sprint.ads ada/sprint.adb \
- ada/stand.ads ada/stringt.ads ada/stringt.adb ada/system.ads \
- ada/s-assert.ads ada/s-exctab.ads ada/s-htable.ads ada/s-imenne.ads \
- ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads ada/s-secsta.ads \
- ada/s-soflin.ads ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads \
- ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads \
- ada/s-wchcon.ads ada/table.ads ada/table.adb ada/tree_io.ads \
- ada/types.ads ada/uintp.ads ada/uintp.adb ada/uname.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads ada/urealp.adb \
- ada/widechar.ads
-
-ada/stand.o : ada/ada.ads ada/a-unccon.ads ada/a-uncdea.ads ada/stand.ads \
- ada/stand.adb ada/system.ads ada/s-exctab.ads ada/s-os_lib.ads \
- ada/s-stalib.ads ada/s-string.ads ada/s-unstyp.ads ada/tree_io.ads \
- ada/types.ads ada/unchconv.ads ada/unchdeal.ads
-
-ada/stringt.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/debug.ads ada/hostparm.ads \
- ada/namet.ads ada/opt.ads ada/output.ads ada/stringt.ads \
- ada/stringt.adb ada/system.ads ada/s-assert.ads ada/s-carun8.ads \
- ada/s-exctab.ads ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads \
- ada/s-stalib.ads ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads \
- ada/s-wchcon.ads ada/table.ads ada/table.adb ada/tree_io.ads \
- ada/types.ads ada/types.adb ada/unchconv.ads ada/unchdeal.ads
-
-ada/style.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/csets.ads ada/debug.ads ada/einfo.ads \
- ada/einfo.adb ada/err_vars.ads ada/errout.ads ada/erroutc.ads \
- ada/gnat.ads ada/g-byorma.ads ada/hostparm.ads ada/interfac.ads \
- ada/namet.ads ada/namet.adb ada/nlists.ads ada/opt.ads ada/output.ads \
- ada/scans.ads ada/sinfo.ads ada/sinfo.adb ada/sinput.ads ada/sinput.adb \
- ada/snames.ads ada/stand.ads ada/style.ads ada/style.adb ada/styleg.ads \
- ada/styleg.adb ada/stylesw.ads ada/system.ads ada/s-assert.ads \
- ada/s-exctab.ads ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads \
- ada/s-parame.ads ada/s-secsta.ads ada/s-soflin.ads ada/s-stache.ads \
- ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads \
- ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads \
- ada/table.adb ada/tree_io.ads ada/types.ads ada/uintp.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads ada/widechar.ads
-
-ada/styleg.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/atree.ads ada/casing.ads \
- ada/csets.ads ada/debug.ads ada/einfo.ads ada/err_vars.ads \
- ada/hostparm.ads ada/namet.ads ada/opt.ads ada/output.ads ada/scans.ads \
- ada/sinfo.ads ada/sinput.ads ada/snames.ads ada/styleg.ads \
- ada/styleg.adb ada/stylesw.ads ada/system.ads ada/s-assert.ads \
- ada/s-exctab.ads ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads \
- ada/s-stalib.ads ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads \
- ada/s-wchcon.ads ada/table.ads ada/table.adb ada/tree_io.ads \
- ada/types.ads ada/uintp.ads ada/unchconv.ads ada/unchdeal.ads \
- ada/urealp.ads
-
-ada/stylesw.o : ada/ada.ads ada/a-unccon.ads ada/a-uncdea.ads \
- ada/hostparm.ads ada/opt.ads ada/stylesw.ads ada/stylesw.adb \
- ada/system.ads ada/s-assert.ads ada/s-exctab.ads ada/s-stalib.ads \
- ada/s-string.ads ada/s-unstyp.ads ada/s-wchcon.ads ada/types.ads \
- ada/unchconv.ads ada/unchdeal.ads
-
-ada/switch-b.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/debug.ads ada/gnatvsn.ads \
- ada/hostparm.ads ada/namet.ads ada/opt.ads ada/osint.ads ada/output.ads \
- ada/switch.ads ada/switch-b.ads ada/switch-b.adb ada/system.ads \
- ada/s-assert.ads ada/s-exctab.ads ada/s-memory.ads ada/s-os_lib.ads \
- ada/s-parame.ads ada/s-soflin.ads ada/s-stache.ads ada/s-stalib.ads \
- ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads \
- ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads ada/table.adb \
- ada/tree_io.ads ada/types.ads ada/unchconv.ads ada/unchdeal.ads
-
-ada/switch-c.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/debug.ads ada/einfo.ads \
- ada/get_targ.ads ada/gnatvsn.ads ada/hostparm.ads ada/lib.ads \
- ada/namet.ads ada/opt.ads ada/osint.ads ada/output.ads ada/set_targ.ads \
- ada/snames.ads ada/stylesw.ads ada/switch.ads ada/switch-c.ads \
- ada/switch-c.adb ada/system.ads ada/s-assert.ads ada/s-exctab.ads \
- ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads ada/s-soflin.ads \
- ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb \
- ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads \
- ada/table.ads ada/table.adb ada/tree_io.ads ada/ttypes.ads \
- ada/types.ads ada/uintp.ads ada/unchconv.ads ada/unchdeal.ads \
- ada/urealp.ads ada/validsw.ads ada/warnsw.ads
-
-ada/switch.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/debug.ads ada/gnatvsn.ads \
- ada/hostparm.ads ada/namet.ads ada/opt.ads ada/osint.ads ada/output.ads \
- ada/switch.ads ada/switch.adb ada/system.ads ada/s-assert.ads \
- ada/s-exctab.ads ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads \
- ada/s-secsta.ads ada/s-soflin.ads ada/s-stache.ads ada/s-stalib.ads \
- ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads \
- ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads ada/table.adb \
- ada/tree_io.ads ada/types.ads ada/unchconv.ads ada/unchdeal.ads
-
-ada/system.o : ada/system.ads
-
-ada/table.o : ada/ada.ads ada/a-unccon.ads ada/a-uncdea.ads ada/debug.ads \
- ada/hostparm.ads ada/opt.ads ada/output.ads ada/system.ads \
- ada/s-exctab.ads ada/s-memory.ads ada/s-os_lib.ads ada/s-stalib.ads \
- ada/s-string.ads ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads \
- ada/table.adb ada/tree_io.ads ada/types.ads ada/unchconv.ads \
- ada/unchdeal.ads
-
-ada/targparm.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/csets.ads ada/debug.ads \
- ada/hostparm.ads ada/interfac.ads ada/namet.ads ada/namet.adb \
- ada/opt.ads ada/osint.ads ada/output.ads ada/rident.ads ada/system.ads \
- ada/s-assert.ads ada/s-exctab.ads ada/s-imenne.ads ada/s-memory.ads \
- ada/s-os_lib.ads ada/s-parame.ads ada/s-rident.ads ada/s-secsta.ads \
- ada/s-soflin.ads ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads \
- ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads \
- ada/s-wchcon.ads ada/table.ads ada/table.adb ada/targparm.ads \
- ada/targparm.adb ada/tree_io.ads ada/types.ads ada/unchconv.ads \
- ada/unchdeal.ads ada/widechar.ads
-
-ada/tbuild.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/csets.ads ada/debug.ads ada/einfo.ads \
- ada/einfo.adb ada/elists.ads ada/elists.adb ada/fname.ads ada/gnat.ads \
- ada/g-hesorg.ads ada/g-htable.ads ada/hostparm.ads ada/interfac.ads \
- ada/lib.ads ada/lib.adb ada/lib-list.adb ada/lib-sort.adb ada/namet.ads \
- ada/namet.adb ada/nlists.ads ada/nmake.ads ada/nmake.adb ada/opt.ads \
- ada/output.ads ada/restrict.ads ada/rident.ads ada/sem_aux.ads \
- ada/sinfo.ads ada/sinfo.adb ada/sinput.ads ada/snames.ads ada/stand.ads \
- ada/stringt.ads ada/stringt.adb ada/system.ads ada/s-assert.ads \
- ada/s-exctab.ads ada/s-htable.ads ada/s-imenne.ads ada/s-memory.ads \
- ada/s-os_lib.ads ada/s-parame.ads ada/s-rident.ads ada/s-secsta.ads \
- ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads \
- ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads \
- ada/table.adb ada/tbuild.ads ada/tbuild.adb ada/tree_io.ads \
- ada/types.ads ada/uintp.ads ada/uintp.adb ada/uname.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads ada/urealp.adb \
- ada/widechar.ads
-
-ada/tree_gen.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/casing.ads ada/debug.ads ada/einfo.ads ada/elists.ads ada/fname.ads \
- ada/hostparm.ads ada/lib.ads ada/namet.ads ada/nlists.ads ada/opt.ads \
- ada/osint.ads ada/osint-c.ads ada/output.ads ada/repinfo.ads \
- ada/sem_aux.ads ada/sinfo.ads ada/sinput.ads ada/snames.ads \
- ada/stand.ads ada/stringt.ads ada/system.ads ada/s-assert.ads \
- ada/s-exctab.ads ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads \
- ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads \
- ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads \
- ada/table.adb ada/tree_gen.ads ada/tree_gen.adb ada/tree_in.ads \
- ada/tree_io.ads ada/types.ads ada/uintp.ads ada/unchconv.ads \
- ada/unchdeal.ads ada/urealp.ads
-
-ada/tree_in.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/casing.ads ada/csets.ads ada/debug.ads ada/einfo.ads ada/elists.ads \
- ada/fname.ads ada/hostparm.ads ada/lib.ads ada/namet.ads ada/nlists.ads \
- ada/opt.ads ada/output.ads ada/repinfo.ads ada/sem_aux.ads \
- ada/sinfo.ads ada/sinput.ads ada/snames.ads ada/stand.ads \
- ada/stringt.ads ada/system.ads ada/s-assert.ads ada/s-exctab.ads \
- ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads ada/s-stalib.ads \
- ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads \
- ada/table.ads ada/table.adb ada/tree_in.ads ada/tree_in.adb \
- ada/tree_io.ads ada/types.ads ada/uintp.ads ada/unchconv.ads \
- ada/unchdeal.ads ada/urealp.ads
-
-ada/tree_io.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/debug.ads ada/hostparm.ads ada/output.ads \
- ada/system.ads ada/s-exctab.ads ada/s-exctab.adb ada/s-htable.ads \
- ada/s-os_lib.ads ada/s-parame.ads ada/s-soflin.ads ada/s-stache.ads \
- ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads \
- ada/s-traent.ads ada/s-unstyp.ads ada/tree_io.ads ada/tree_io.adb \
- ada/types.ads ada/unchconv.ads ada/unchdeal.ads
-
-ada/treepr.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/csets.ads ada/debug.ads ada/einfo.ads \
- ada/einfo.adb ada/elists.ads ada/elists.adb ada/fname.ads ada/gnat.ads \
- ada/g-byorma.ads ada/g-hesorg.ads ada/g-htable.ads ada/hostparm.ads \
- ada/lib.ads ada/lib.adb ada/lib-list.adb ada/lib-sort.adb ada/namet.ads \
- ada/nlists.ads ada/nlists.adb ada/opt.ads ada/output.ads ada/output.adb \
- ada/scans.ads ada/scil_ll.ads ada/sem_mech.ads ada/sinfo.ads \
- ada/sinfo.adb ada/sinput.ads ada/sinput.adb ada/snames.ads \
- ada/stand.ads ada/stringt.ads ada/system.ads ada/s-assert.ads \
- ada/s-exctab.ads ada/s-htable.ads ada/s-imenne.ads ada/s-memory.ads \
- ada/s-os_lib.ads ada/s-parame.ads ada/s-secsta.ads ada/s-soflin.ads \
- ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb \
- ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads \
- ada/table.ads ada/table.adb ada/tree_io.ads ada/treepr.ads \
- ada/treepr.adb ada/treeprs.ads ada/types.ads ada/uintp.ads \
- ada/uintp.adb ada/uname.ads ada/unchconv.ads ada/unchdeal.ads \
- ada/urealp.ads ada/widechar.ads
-
-ada/treeprs.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/debug.ads ada/hostparm.ads \
- ada/namet.ads ada/opt.ads ada/output.ads ada/sinfo.ads ada/system.ads \
- ada/s-assert.ads ada/s-exctab.ads ada/s-memory.ads ada/s-os_lib.ads \
- ada/s-parame.ads ada/s-stalib.ads ada/s-string.ads ada/s-traent.ads \
- ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads ada/table.adb \
- ada/tree_io.ads ada/treeprs.ads ada/types.ads ada/uintp.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads
-
-ada/ttypes.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/debug.ads ada/einfo.ads \
- ada/get_targ.ads ada/hostparm.ads ada/namet.ads ada/opt.ads \
- ada/output.ads ada/set_targ.ads ada/snames.ads ada/system.ads \
- ada/s-assert.ads ada/s-exctab.ads ada/s-memory.ads ada/s-os_lib.ads \
- ada/s-parame.ads ada/s-stalib.ads ada/s-string.ads ada/s-traent.ads \
- ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads ada/table.adb \
- ada/tree_io.ads ada/ttypes.ads ada/types.ads ada/uintp.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads
-
-ada/types.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads ada/system.ads \
- ada/s-assert.ads ada/s-carun8.ads ada/s-exctab.ads ada/s-exctab.adb \
- ada/s-htable.ads ada/s-parame.ads ada/s-soflin.ads ada/s-stache.ads \
- ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb ada/s-traent.ads \
- ada/s-unstyp.ads ada/types.ads ada/types.adb ada/unchconv.ads \
- ada/unchdeal.ads
-
-ada/uintp.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/debug.ads ada/gnat.ads \
- ada/g-htable.ads ada/hostparm.ads ada/opt.ads ada/output.ads \
- ada/system.ads ada/s-assert.ads ada/s-exctab.ads ada/s-htable.ads \
- ada/s-htable.adb ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads \
- ada/s-stalib.ads ada/s-strhas.ads ada/s-string.ads ada/s-traent.ads \
- ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads ada/table.adb \
- ada/tree_io.ads ada/types.ads ada/uintp.ads ada/uintp.adb \
- ada/unchconv.ads ada/unchdeal.ads
-
-ada/uname.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
- ada/atree.adb ada/casing.ads ada/csets.ads ada/debug.ads ada/einfo.ads \
- ada/fname.ads ada/gnat.ads ada/g-byorma.ads ada/g-hesorg.ads \
- ada/hostparm.ads ada/lib.ads ada/lib.adb ada/lib-list.adb \
- ada/lib-sort.adb ada/namet.ads ada/nlists.ads ada/nlists.adb \
- ada/opt.ads ada/output.ads ada/scans.ads ada/sinfo.ads ada/sinfo.adb \
- ada/sinput.ads ada/sinput.adb ada/snames.ads ada/stand.ads \
- ada/stringt.ads ada/system.ads ada/s-assert.ads ada/s-exctab.ads \
- ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads \
- ada/s-secsta.ads ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb \
- ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads \
- ada/table.ads ada/table.adb ada/tree_io.ads ada/types.ads ada/uintp.ads \
- ada/uname.ads ada/uname.adb ada/unchconv.ads ada/unchdeal.ads \
- ada/urealp.ads ada/widechar.ads
-
-ada/urealp.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/debug.ads ada/gnat.ads \
- ada/g-htable.ads ada/hostparm.ads ada/opt.ads ada/output.ads \
- ada/system.ads ada/s-assert.ads ada/s-exctab.ads ada/s-htable.ads \
- ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads ada/s-stalib.ads \
- ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads \
- ada/table.ads ada/table.adb ada/tree_io.ads ada/types.ads ada/uintp.ads \
- ada/uintp.adb ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads \
- ada/urealp.adb
-
-ada/usage.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/debug.ads ada/hostparm.ads \
- ada/namet.ads ada/opt.ads ada/osint.ads ada/output.ads ada/rident.ads \
- ada/system.ads ada/s-assert.ads ada/s-exctab.ads ada/s-memory.ads \
- ada/s-os_lib.ads ada/s-parame.ads ada/s-rident.ads ada/s-stalib.ads \
- ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads \
- ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads ada/table.adb \
- ada/targparm.ads ada/tree_io.ads ada/types.ads ada/unchconv.ads \
- ada/unchdeal.ads ada/usage.ads ada/usage.adb
-
-ada/validsw.o : ada/ada.ads ada/a-unccon.ads ada/a-uncdea.ads \
- ada/hostparm.ads ada/opt.ads ada/system.ads ada/s-exctab.ads \
- ada/s-stalib.ads ada/s-string.ads ada/s-unstyp.ads ada/s-wchcon.ads \
- ada/types.ads ada/unchconv.ads ada/unchdeal.ads ada/validsw.ads \
- ada/validsw.adb
+ada_generated_files = ada/sinfo.h ada/einfo.h ada/nmake.adb ada/nmake.ads \
+ ada/treeprs.ads ada/snames.ads ada/snames.adb ada/snames.h
-ada/warnsw.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/alloc.ads ada/debug.ads ada/err_vars.ads \
- ada/hostparm.ads ada/namet.ads ada/opt.ads ada/output.ads \
- ada/system.ads ada/s-assert.ads ada/s-exctab.ads ada/s-memory.ads \
- ada/s-os_lib.ads ada/s-parame.ads ada/s-stalib.ads ada/s-string.ads \
- ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads \
- ada/table.adb ada/tree_io.ads ada/types.ads ada/uintp.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/warnsw.ads ada/warnsw.adb
+# When building from scratch we don't have dependency files, the only thing
+# we need to ensure is that the generated files are created first.
+$(GNAT1_ADA_OBJS) $(GNATBIND_OBJS): | $(ada_generated_files)
-ada/widechar.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
- ada/a-uncdea.ads ada/hostparm.ads ada/interfac.ads ada/opt.ads \
- ada/system.ads ada/s-exctab.ads ada/s-parame.ads ada/s-soflin.ads \
- ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb \
- ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcnv.ads \
- ada/s-wchcnv.adb ada/s-wchcon.ads ada/s-wchjis.ads ada/types.ads \
- ada/unchconv.ads ada/unchdeal.ads ada/widechar.ads ada/widechar.adb
+# Manually include the auto-generated dependencies for the Ada host objects.
+ADA_DEPFILES = $(foreach obj,(GNAT1_ADA_OBJS) $(GNATBIND_OBJS),\
+ $(dir $(obj))/$(DEPDIR)/$(patsubst %.o,%.Po,$(notdir $(obj))))
+-include $(ADA_DEPFILES)
-# end of regular dependencies
+# Automatically include the auto-generated dependencies for the C host objects.
+ada_OBJS = $(GNAT1_C_OBJS)
diff --git a/gcc/ada/gcc-interface/Makefile.in b/gcc/ada/gcc-interface/Makefile.in
index 4fd368283a9..91778c5fcf6 100644
--- a/gcc/ada/gcc-interface/Makefile.in
+++ b/gcc/ada/gcc-interface/Makefile.in
@@ -1,5 +1,5 @@
# Makefile for GNU Ada Compiler (GNAT).
-# Copyright (C) 1994-2012 Free Software Foundation, Inc.
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
#This file is part of GCC.
@@ -122,7 +122,7 @@ THREAD_KIND = native
THREADSLIB =
GMEM_LIB =
MISCLIB =
-OUTPUT_OPTION = @OUTPUT_OPTION@
+OUTPUT_OPTION = -o $@
objext = .o
exeext =
@@ -167,6 +167,13 @@ tmake_file = @tmake_file@
# Directory where sources are, from where we are.
VPATH = $(srcdir)/ada
+# Full path to top source directory
+# In particular this is used to access libgcc headers, so that references to
+# these headers from GNAT runtime objects have path names in debugging info
+# that are consistent with libgcc objects. Also used for other references to
+# the top source directory for consistency.
+ftop_srcdir := $(shell cd $(srcdir)/..;${PWD_COMMAND})
+
fsrcdir := $(shell cd $(srcdir);${PWD_COMMAND})
fsrcpfx := $(shell cd $(srcdir);${PWD_COMMAND})/
fcurdir := $(shell ${PWD_COMMAND})
@@ -262,7 +269,7 @@ TOOLS_LIBS = ../link.o ../targext.o ../../ggc-none.o ../../libcommon-target.a \
# Both . and srcdir are used, in that order,
# so that tm.h and config.h will be found in the compilation
# subdirectory rather than in the source directory.
-INCLUDES = -I- -I. -I.. -I$(srcdir)/ada -I$(srcdir) -I$(srcdir)/../include $(GMPINC)
+INCLUDES = -I- -I. -I.. -I$(srcdir)/ada -I$(srcdir) -I$(ftop_srcdir)/include $(GMPINC)
ADA_INCLUDES = -I- -I. -I$(srcdir)/ada
@@ -272,11 +279,11 @@ ADA_INCLUDES = -I- -I. -I$(srcdir)/ada
ifneq ($(findstring vxworks,$(target_os)),)
INCLUDES_FOR_SUBDIR = -iquote . -iquote .. -iquote ../.. \
-iquote $(fsrcdir)/ada \
- -I$(fsrcdir)/../include $(GMPINC)
+ -I$(ftop_srcdir)/include $(GMPINC)
else
INCLUDES_FOR_SUBDIR = -iquote . -iquote .. -iquote ../.. \
-iquote $(fsrcdir)/ada -iquote $(fsrcdir) \
- -I$(fsrcdir)/../include $(GMPINC)
+ -I$(ftop_srcdir)/include $(GMPINC)
endif
ADA_INCLUDES_FOR_SUBDIR = -I. -I$(fsrcdir)/ada
@@ -408,6 +415,8 @@ DUMMY_SOCKETS_TARGET_PAIRS = \
# special version of Ada.Strings.Unbounded package can be used.
ATOMICS_TARGET_PAIRS = \
+ a-coinho.adb<a-coinho-shared.adb \
+ a-coinho.ads<a-coinho-shared.ads \
a-stunau.adb<a-stunau-shared.adb \
a-suteio.adb<a-suteio-shared.adb \
a-strunb.ads<a-strunb-shared.ads \
@@ -493,6 +502,13 @@ endif
# PowerPC and e500v2 VxWorks
ifeq ($(strip $(filter-out powerpc% wrs vxworks,$(target_cpu) $(target_vendor) $(target_os))),)
+
+ ifeq ($(strip $(filter-out e500%, $(target_alias))),)
+ ARCH_STR=e500
+ else
+ ARCH_STR=ppc
+ endif
+
LIBGNAT_TARGET_PAIRS = \
a-intnam.ads<a-intnam-vxworks.ads \
a-numaux.ads<a-numaux-vxworks.ads \
@@ -545,7 +561,7 @@ ifeq ($(strip $(filter-out powerpc% wrs vxworks,$(target_cpu) $(target_vendor) $
s-vxwext.ads<s-vxwext-rtp.ads \
s-vxwext.adb<s-vxwext-rtp.adb \
s-tpopsp.adb<s-tpopsp-vxworks-rtp.adb \
- system.ads<system-vxworks-ppc-rtp.ads
+ system.ads<system-vxworks-$(ARCH_STR)-rtp.ads
EXTRA_GNATRTL_NONTASKING_OBJS=s-vxwexc.o
else
@@ -555,7 +571,7 @@ ifeq ($(strip $(filter-out powerpc% wrs vxworks,$(target_cpu) $(target_vendor) $
s-vxwext.ads<s-vxwext-rtp.ads \
s-vxwext.adb<s-vxwext-rtp-smp.adb \
s-tpopsp.adb<s-tpopsp-vxworks-tls.adb \
- system.ads<system-vxworks-ppc-rtp.ads
+ system.ads<system-vxworks-$(ARCH_STR)-rtp.ads
EXTRA_GNATRTL_NONTASKING_OBJS=s-vxwexc.o
EXTRA_LIBGNAT_OBJS+=affinity.o
@@ -567,7 +583,7 @@ ifeq ($(strip $(filter-out powerpc% wrs vxworks,$(target_cpu) $(target_vendor) $
s-tpopsp.adb<s-tpopsp-vxworks-tls.adb \
s-vxwext.ads<s-vxwext-kernel.ads \
s-vxwext.adb<s-vxwext-kernel-smp.adb \
- system.ads<system-vxworks-ppc-kernel.ads
+ system.ads<system-vxworks-$(ARCH_STR)-kernel.ads
EH_MECHANISM=-gcc
EXTRA_LIBGNAT_OBJS+=affinity.o
@@ -581,7 +597,7 @@ ifeq ($(strip $(filter-out powerpc% wrs vxworks,$(target_cpu) $(target_vendor) $
LIBGNAT_TARGET_PAIRS += \
s-vxwext.ads<s-vxwext-kernel.ads \
s-vxwext.adb<s-vxwext-kernel.adb \
- system.ads<system-vxworks-ppc-kernel.ads
+ system.ads<system-vxworks-$(ARCH_STR)-kernel.ads
else
LIBGNAT_TARGET_PAIRS += \
system.ads<system-vxworks-ppc.ads
@@ -984,7 +1000,7 @@ ifeq ($(strip $(filter-out mips% wrs vx%,$(target_cpu) $(target_vendor) $(target
EXTRA_LIBGNAT_OBJS+=vx_stack_info.o
endif
-# ARM linux, Android eabi
+# ARM android
ifeq ($(strip $(filter-out arm% linux-androideabi,$(target_cpu) $(target_os))),)
LIBGNAT_TARGET_PAIRS = \
a-intnam.ads<a-intnam-linux.ads \
@@ -1201,6 +1217,7 @@ ifeq ($(strip $(filter-out %86 linux%,$(target_cpu) $(target_os))),)
indepsw.adb<indepsw-gnu.adb
GNATLIB_SHARED = gnatlib-shared-dual
+ MISCLIB = -ldl
GMEM_LIB = gmemlib
LIBRARY_VERSION := $(LIB_VERSION)
endif
@@ -1581,7 +1598,14 @@ ifeq ($(strip $(filter-out alpha64 ia64 dec hp vms% openvms% alphavms%,$(target_
LIBRARY_VERSION := $(subst .,_,$(LIB_VERSION))
endif
-# *-elf, *-eabi or *-eabispe
+# PikeOS
+ifeq ($(strip $(filter-out powerpc% %86 sysgo pikeos,$(target_cpu) $(target_vendor) $(target_os)))),)
+ TOOLS_TARGET_PAIRS=\
+ mlib-tgt-specific.adb<mlib-tgt-specific-xi.adb \
+ indepsw.adb<indepsw-gnu.adb
+endif
+
+# *-elf, *-eabi, or *-eabispe
ifeq ($(strip $(filter-out elf eabi eabispe,$(target_os))),)
TOOLS_TARGET_PAIRS=\
mlib-tgt-specific.adb<mlib-tgt-specific-xi.adb \
@@ -2147,6 +2171,7 @@ ifeq ($(strip $(filter-out %x86_64 linux%,$(target_cpu) $(target_os))),)
EXTRA_GNATRTL_TASKING_OBJS=s-linux.o a-exetim.o
EH_MECHANISM=-gcc
THREADSLIB=-lpthread -lrt
+ MISCLIB = -ldl
GNATLIB_SHARED=gnatlib-shared-dual
GMEM_LIB = gmemlib
LIBRARY_VERSION := $(LIB_VERSION)
@@ -2291,9 +2316,10 @@ ifeq ($(strip $(filter-out arm nucleus%,$(target_cpu) $(target_os))),)
GNATRTL_SOCKETS_OBJS =
endif
-ifneq ($(EH_MECHANISM),)
- LIBGNAT_TARGET_PAIRS += a-exexpr.adb<a-exexpr$(EH_MECHANISM).adb
- EXTRA_LIBGNAT_OBJS+=raise$(EH_MECHANISM).o
+ifeq ($(EH_MECHANISM),-gcc)
+ LIBGNAT_TARGET_PAIRS += a-exexpr.adb<a-exexpr-gcc.adb
+ EXTRA_LIBGNAT_OBJS+=raise-gcc.o
+ EXTRA_GNATRTL_NONTASKING_OBJS+=g-cppexc.o
endif
# Use the Ada 2005 version of Ada.Exceptions by default, unless specified
@@ -2998,7 +3024,7 @@ vx_stack_info.o : vx_stack_info.c
raise-gcc.o : raise-gcc.c raise.h
$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ADA_CFLAGS) \
- -iquote $(srcdir) -iquote $(srcdir)/../libgcc \
+ -iquote $(srcdir) -iquote $(ftop_srcdir)/libgcc \
$(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
cio.o : cio.c
diff --git a/gcc/ada/gcc-interface/cuintp.c b/gcc/ada/gcc-interface/cuintp.c
index e077d9ce009..9b58b0ecc64 100644
--- a/gcc/ada/gcc-interface/cuintp.c
+++ b/gcc/ada/gcc-interface/cuintp.c
@@ -6,7 +6,7 @@
* *
* C Implementation File *
* *
- * Copyright (C) 1992-2012, Free Software Foundation, Inc. *
+ * Copyright (C) 1992-2013, Free Software Foundation, Inc. *
* *
* GNAT is free software; you can redistribute it and/or modify it under *
* terms of the GNU General Public License as published by the Free Soft- *
@@ -23,8 +23,8 @@
* *
****************************************************************************/
-/* This file corresponds to the Ada package body Uintp. It was created
- manually from the files uintp.ads and uintp.adb. */
+/* This file corresponds to the Ada package body Uintp. It was created
+ manually from the files uintp.ads and uintp.adb. */
#include "config.h"
#include "system.h"
@@ -35,11 +35,6 @@
#include "ada.h"
#include "types.h"
#include "uintp.h"
-#include "atree.h"
-#include "elists.h"
-#include "nlists.h"
-#include "stringt.h"
-#include "fe.h"
#include "ada-tree.h"
#include "gigi.h"
@@ -53,13 +48,13 @@
the integer value itself. The origin of the Uints_Ptr table is adjusted so
that a Uint value of Uint_Bias indexes the first element.
- First define a utility function that operates like build_int_cst for
- integral types and does a conversion to floating-point for real types. */
+ First define a utility function that operates like build_int_cst_type for
+ integral types and does a conversion for floating-point types. */
static tree
build_cst_from_int (tree type, HOST_WIDE_INT low)
{
- if (TREE_CODE (type) == REAL_TYPE)
+ if (SCALAR_FLOAT_TYPE_P (type))
return convert (type, build_int_cst (NULL_TREE, low));
else
return build_int_cst_type (type, low);
@@ -73,20 +68,15 @@ build_cst_from_int (tree type, HOST_WIDE_INT low)
tree
UI_To_gnu (Uint Input, tree type)
{
+ /* We might have a TYPE with biased representation and be passed an unbiased
+ value that doesn't fit. We always use an unbiased type to be able to hold
+ any such possible value for intermediate computations and then rely on a
+ conversion back to TYPE to perform the bias adjustment when need be. */
+ tree comp_type
+ = TREE_CODE (type) == INTEGER_TYPE && TYPE_BIASED_REPRESENTATION_P (type)
+ ? get_base_type (type) : type;
tree gnu_ret;
- /* We might have a TYPE with biased representation and be passed an
- unbiased value that doesn't fit. We always use an unbiased type able
- to hold any such possible value for intermediate computations, and
- then rely on a conversion back to TYPE to perform the bias adjustment
- when need be. */
-
- int biased_type_p
- = (TREE_CODE (type) == INTEGER_TYPE
- && TYPE_BIASED_REPRESENTATION_P (type));
-
- tree comp_type = biased_type_p ? get_base_type (type) : type;
-
if (Input <= Uint_Direct_Last)
gnu_ret = build_cst_from_int (comp_type, Input - Uint_Direct_Bias);
else
@@ -188,12 +178,13 @@ UI_From_gnu (tree Input)
{
v[i] = tree_low_cst (fold_build1 (ABS_EXPR, gnu_type,
fold_build2 (TRUNC_MOD_EXPR, gnu_type,
- gnu_temp, gnu_base)),
- 0);
+ gnu_temp, gnu_base)), 0);
gnu_temp = fold_build2 (TRUNC_DIV_EXPR, gnu_type, gnu_temp, gnu_base);
}
- temp.Low_Bound = 1, temp.High_Bound = Max_For_Dint;
- vec.Array = v, vec.Bounds = &temp;
+ temp.Low_Bound = 1;
+ temp.High_Bound = Max_For_Dint;
+ vec.Bounds = &temp;
+ vec.Array = v;
return Vector_To_Uint (vec, tree_int_cst_sgn (Input) < 0);
}
diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c
index 456d7ab7ad9..d3866023155 100644
--- a/gcc/ada/gcc-interface/decl.c
+++ b/gcc/ada/gcc-interface/decl.c
@@ -98,7 +98,7 @@ struct incomplete
static int defer_incomplete_level = 0;
static struct incomplete *defer_incomplete_list;
-/* This variable is used to delay expanding From_With_Type types until the
+/* This variable is used to delay expanding From_Limited_With types until the
end of the spec. */
static struct incomplete *defer_limited_with;
@@ -1497,7 +1497,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
/* If we are defining an Out parameter and optimization isn't enabled,
create a fake PARM_DECL for debugging purposes and make it point to
the VAR_DECL. Suppress debug info for the latter but make sure it
- will live on the stack so that it can be accessed from within the
+ will live in memory so that it can be accessed from within the
debugger through the PARM_DECL. */
if (kind == E_Out_Parameter
&& definition
@@ -1520,7 +1520,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
/* If this is a renaming pointer, attach the renamed object to it and
register it if we are at the global level. Note that an external
constant is at the global level. */
- else if (TREE_CODE (gnu_decl) == VAR_DECL && renamed_obj)
+ if (TREE_CODE (gnu_decl) == VAR_DECL && renamed_obj)
{
SET_DECL_RENAMED_OBJECT (gnu_decl, renamed_obj);
if ((!definition && kind == E_Constant) || global_bindings_p ())
@@ -1579,6 +1579,19 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
&& Has_Nested_Block_With_Handler (Scope (gnat_entity)))
TREE_ADDRESSABLE (gnu_decl) = 1;
+ /* If this is a local variable with non-BLKmode and aggregate type,
+ and optimization isn't enabled, then force it in memory so that
+ a register won't be allocated to it with possible subparts left
+ uninitialized and reaching the register allocator. */
+ else if (TREE_CODE (gnu_decl) == VAR_DECL
+ && !DECL_EXTERNAL (gnu_decl)
+ && !TREE_STATIC (gnu_decl)
+ && DECL_MODE (gnu_decl) != BLKmode
+ && AGGREGATE_TYPE_P (TREE_TYPE (gnu_decl))
+ && !TYPE_IS_FAT_POINTER_P (TREE_TYPE (gnu_decl))
+ && !optimize)
+ TREE_ADDRESSABLE (gnu_decl) = 1;
+
/* If we are defining an object with variable size or an object with
fixed size that will be dynamically allocated, and we are using the
setjmp/longjmp exception mechanism, update the setjmp buffer. */
@@ -3725,7 +3738,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
/* Whether it comes from a limited with. */
bool is_from_limited_with
= (IN (Ekind (gnat_desig_equiv), Incomplete_Kind)
- && From_With_Type (gnat_desig_equiv));
+ && From_Limited_With (gnat_desig_equiv));
/* The "full view" of the designated type. If this is an incomplete
entity from a limited with, treat its non-limited view as the full
view. Otherwise, if this is an incomplete or private type, use the
@@ -4217,7 +4230,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
we are only annotating types, break circularities here. */
if (type_annotate_only
&& IN (Ekind (gnat_return_type), Incomplete_Kind)
- && From_With_Type (gnat_return_type)
+ && From_Limited_With (gnat_return_type)
&& In_Extended_Main_Code_Unit
(Non_Limited_View (gnat_return_type))
&& !present_gnu_tree (Non_Limited_View (gnat_return_type)))
@@ -4330,7 +4343,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
we are only annotating types, break circularities here. */
if (type_annotate_only
&& IN (Ekind (gnat_param_type), Incomplete_Kind)
- && From_With_Type (Etype (gnat_param_type))
+ && From_Limited_With (Etype (gnat_param_type))
&& In_Extended_Main_Code_Unit
(Non_Limited_View (gnat_param_type))
&& !present_gnu_tree (Non_Limited_View (gnat_param_type)))
@@ -4725,7 +4738,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
full view, whichever is present. This is used in all the tests
below. */
Entity_Id full_view
- = (IN (kind, Incomplete_Kind) && From_With_Type (gnat_entity))
+ = (IN (kind, Incomplete_Kind) && From_Limited_With (gnat_entity))
? Non_Limited_View (gnat_entity)
: Present (Full_View (gnat_entity))
? Full_View (gnat_entity)
@@ -5477,10 +5490,10 @@ is_cplusplus_method (Entity_Id gnat_entity)
return false;
}
-/* Finalize the processing of From_With_Type incomplete types. */
+/* Finalize the processing of From_Limited_With incomplete types. */
void
-finalize_from_with_types (void)
+finalize_from_limited_with (void)
{
struct incomplete *p, *next;
@@ -5824,12 +5837,8 @@ gnat_to_gnu_param (Entity_Id gnat_param, Mechanism_Type mech,
ro_param || by_ref || by_component_ptr);
DECL_BY_REF_P (gnu_param) = by_ref;
DECL_BY_COMPONENT_PTR_P (gnu_param) = by_component_ptr;
- DECL_BY_DESCRIPTOR_P (gnu_param) = (mech == By_Descriptor ||
- mech == By_Short_Descriptor);
- /* Note that, in case of a parameter passed by double reference, the
- DECL_POINTS_TO_READONLY_P flag is meant for the second reference.
- The first reference always points to read-only, as it points to
- the second reference, i.e. the reference to the actual parameter. */
+ DECL_BY_DESCRIPTOR_P (gnu_param)
+ = (mech == By_Descriptor || mech == By_Short_Descriptor);
DECL_POINTS_TO_READONLY_P (gnu_param)
= (ro_param && (by_ref || by_component_ptr));
DECL_CAN_NEVER_BE_NULL_P (gnu_param) = Can_Never_Be_Null (gnat_param);
@@ -6994,13 +7003,11 @@ components_to_record (tree gnu_record_type, Node_Id gnat_component_list,
tree gnu_union_type, gnu_union_name;
tree this_first_free_pos, gnu_variant_list = NULL_TREE;
bool union_field_needs_strict_alignment = false;
- vec <vinfo_t, va_stack> variant_types;
+ stack_vec <vinfo_t, 16> variant_types;
vinfo_t *gnu_variant;
unsigned int variants_align = 0;
unsigned int i;
- vec_stack_alloc (vinfo_t, variant_types, 16);
-
if (TREE_CODE (gnu_name) == TYPE_DECL)
gnu_name = DECL_NAME (gnu_name);
@@ -7196,9 +7203,6 @@ components_to_record (tree gnu_record_type, Node_Id gnat_component_list,
gnu_variant_list = gnu_field;
}
- /* We are done with the variants. */
- variant_types.release ();
-
/* Only make the QUAL_UNION_TYPE if there are non-empty variants. */
if (gnu_variant_list)
{
diff --git a/gcc/ada/gcc-interface/gigi.h b/gcc/ada/gcc-interface/gigi.h
index d18fd4d2207..832803ccfc3 100644
--- a/gcc/ada/gcc-interface/gigi.h
+++ b/gcc/ada/gcc-interface/gigi.h
@@ -93,8 +93,8 @@ do { \
mark_visited (EXP); \
} while (0)
-/* Finalize the processing of From_With_Type incomplete types. */
-extern void finalize_from_with_types (void);
+/* Finalize the processing of From_Limited_With incomplete types. */
+extern void finalize_from_limited_with (void);
/* Return the equivalent type to be used for GNAT_ENTITY, if it's a
kind of type (such E_Task_Type) that has a different type which Gigi
@@ -411,6 +411,7 @@ enum standard_datatypes
ADT_update_setjmp_buf_decl,
ADT_raise_nodefer_decl,
ADT_reraise_zcx_decl,
+ ADT_set_exception_parameter_decl,
ADT_begin_handler_decl,
ADT_end_handler_decl,
ADT_unhandled_except_decl,
@@ -470,6 +471,8 @@ extern GTY(()) tree gnat_raise_decls_ext[(int) LAST_REASON_CODE + 1];
#define update_setjmp_buf_decl gnat_std_decls[(int) ADT_update_setjmp_buf_decl]
#define raise_nodefer_decl gnat_std_decls[(int) ADT_raise_nodefer_decl]
#define reraise_zcx_decl gnat_std_decls[(int) ADT_reraise_zcx_decl]
+#define set_exception_parameter_decl \
+ gnat_std_decls[(int) ADT_set_exception_parameter_decl]
#define begin_handler_decl gnat_std_decls[(int) ADT_begin_handler_decl]
#define others_decl gnat_std_decls[(int) ADT_others_decl]
#define all_others_decl gnat_std_decls[(int) ADT_all_others_decl]
diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c
index 7e56f22c3f0..1d76e6aa468 100644
--- a/gcc/ada/gcc-interface/trans.c
+++ b/gcc/ada/gcc-interface/trans.c
@@ -565,6 +565,15 @@ gigi (Node_Id gnat_root, int max_gnat_node, int number_name ATTRIBUTE_UNUSED,
NULL_TREE, is_disabled, true, true, true, NULL, Empty);
DECL_IGNORED_P (get_excptr_decl) = 1;
+ set_exception_parameter_decl
+ = create_subprog_decl
+ (get_identifier ("__gnat_set_exception_parameter"), NULL_TREE,
+ build_function_type_list (void_type_node,
+ ptr_void_type_node,
+ ptr_void_type_node,
+ NULL_TREE),
+ NULL_TREE, is_disabled, true, true, true, NULL, Empty);
+
raise_nodefer_decl
= create_subprog_decl
(get_identifier ("__gnat_raise_nodefer_with_msg"), NULL_TREE,
@@ -632,20 +641,20 @@ gigi (Node_Id gnat_root, int max_gnat_node, int number_name ATTRIBUTE_UNUSED,
others_decl
= create_var_decl (get_identifier ("OTHERS"),
get_identifier ("__gnat_others_value"),
- integer_type_node, NULL_TREE, true, false, true, false,
- NULL, Empty);
+ unsigned_char_type_node,
+ NULL_TREE, true, false, true, false, NULL, Empty);
all_others_decl
= create_var_decl (get_identifier ("ALL_OTHERS"),
get_identifier ("__gnat_all_others_value"),
- integer_type_node, NULL_TREE, true, false, true, false,
- NULL, Empty);
+ unsigned_char_type_node,
+ NULL_TREE, true, false, true, false, NULL, Empty);
unhandled_others_decl
= create_var_decl (get_identifier ("UNHANDLED_OTHERS"),
get_identifier ("__gnat_unhandled_others_value"),
- integer_type_node, NULL_TREE, true, false, true, false,
- NULL, Empty);
+ unsigned_char_type_node,
+ NULL_TREE, true, false, true, false, NULL, Empty);
main_identifier_node = get_identifier ("main");
@@ -3237,7 +3246,7 @@ finalize_nrv (tree fndecl, bitmap nrv, vec<tree, va_gc> *other, Node_Id gnat_ret
/* Prune also the candidates that are referenced by nested functions. */
node = cgraph_get_create_node (fndecl);
for (node = node->nested; node; node = node->next_nested)
- walk_tree_without_duplicates (&DECL_SAVED_TREE (node->symbol.decl), prune_nrv_r,
+ walk_tree_without_duplicates (&DECL_SAVED_TREE (node->decl), prune_nrv_r,
&data);
if (bitmap_empty_p (nrv))
return;
@@ -4885,6 +4894,19 @@ Exception_Handler_to_gnu_zcx (Node_Id gnat_node)
add_stmt_with_node (build_call_n_expr (begin_handler_decl, 1,
gnu_incoming_exc_ptr),
gnat_node);
+
+ /* Declare and initialize the choice parameter, if present. */
+ if (Present (Choice_Parameter (gnat_node)))
+ {
+ tree gnu_param = gnat_to_gnu_entity
+ (Choice_Parameter (gnat_node), NULL_TREE, 1);
+
+ add_stmt (build_call_n_expr
+ (set_exception_parameter_decl, 2,
+ build_unary_op (ADDR_EXPR, NULL_TREE, gnu_param),
+ gnu_incoming_exc_ptr));
+ }
+
/* We don't have an End_Label at hand to set the location of the cleanup
actions, so we use that of the exception handler itself instead. */
add_cleanup (build_call_n_expr (end_handler_decl, 1, gnu_incoming_exc_ptr),
@@ -4987,7 +5009,7 @@ Compilation_Unit_to_gnu (Node_Id gnat_node)
/* Process any pragmas and actions following the unit. */
add_stmt_list (Pragmas_After (Aux_Decls_Node (gnat_node)));
add_stmt_list (Actions (Aux_Decls_Node (gnat_node)));
- finalize_from_with_types ();
+ finalize_from_limited_with ();
/* Save away what we've made so far and record this potential elaboration
procedure. */
@@ -6607,7 +6629,7 @@ gnat_to_gnu (Node_Id gnat_node)
Present (gnat_temp);
gnat_temp = Next_Formal_With_Extras (gnat_temp))
if (Is_Itype (Etype (gnat_temp))
- && !From_With_Type (Etype (gnat_temp)))
+ && !From_Limited_With (Etype (gnat_temp)))
gnat_to_gnu_entity (Etype (gnat_temp), NULL_TREE, 0);
/* Then the result type, set to Standard_Void_Type for procedures. */
@@ -6615,7 +6637,7 @@ gnat_to_gnu (Node_Id gnat_node)
Entity_Id gnat_temp_type
= Etype (Defining_Entity (Specification (gnat_node)));
- if (Is_Itype (gnat_temp_type) && !From_With_Type (gnat_temp_type))
+ if (Is_Itype (gnat_temp_type) && !From_Limited_With (gnat_temp_type))
gnat_to_gnu_entity (Etype (gnat_temp_type), NULL_TREE, 0);
}
@@ -6988,6 +7010,10 @@ gnat_to_gnu (Node_Id gnat_node)
gnu_result = end_stmt_group ();
break;
+ case N_Freeze_Generic_Entity:
+ gnu_result = alloc_stmt_list ();
+ break;
+
case N_Itype_Reference:
if (!present_gnu_tree (Itype (gnat_node)))
process_type (Itype (gnat_node));
@@ -9195,10 +9221,14 @@ post_error (const char *msg, Node_Id node)
String_Template temp;
Fat_Pointer fp;
- temp.Low_Bound = 1, temp.High_Bound = strlen (msg);
- fp.Array = msg, fp.Bounds = &temp;
- if (Present (node))
- Error_Msg_N (fp, node);
+ if (No (node))
+ return;
+
+ temp.Low_Bound = 1;
+ temp.High_Bound = strlen (msg);
+ fp.Bounds = &temp;
+ fp.Array = msg;
+ Error_Msg_N (fp, node);
}
/* Similar to post_error, but NODE is the node at which to post the error and
@@ -9210,10 +9240,14 @@ post_error_ne (const char *msg, Node_Id node, Entity_Id ent)
String_Template temp;
Fat_Pointer fp;
- temp.Low_Bound = 1, temp.High_Bound = strlen (msg);
- fp.Array = msg, fp.Bounds = &temp;
- if (Present (node))
- Error_Msg_NE (fp, node, ent);
+ if (No (node))
+ return;
+
+ temp.Low_Bound = 1;
+ temp.High_Bound = strlen (msg);
+ fp.Bounds = &temp;
+ fp.Array = msg;
+ Error_Msg_NE (fp, node, ent);
}
/* Similar to post_error_ne, but NUM is the number to use for the '^'. */
diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c
index 2c3e096f120..01a60280e63 100644
--- a/gcc/ada/gcc-interface/utils.c
+++ b/gcc/ada/gcc-interface/utils.c
@@ -232,6 +232,7 @@ static tree compute_related_constant (tree, tree);
static tree split_plus (tree, tree *);
static tree float_type_for_precision (int, enum machine_mode);
static tree convert_to_fat_pointer (tree, tree);
+static unsigned int scale_by_factor_of (tree, unsigned int);
static bool potential_alignment_gap (tree, tree, tree);
/* Initialize data structures of the utils.c module. */
@@ -531,6 +532,22 @@ gnat_zaplevel (void)
free_binding_level = level;
}
+/* Set the context of TYPE and its parallel types (if any) to CONTEXT. */
+
+static void
+gnat_set_type_context (tree type, tree context)
+{
+ tree decl = TYPE_STUB_DECL (type);
+
+ TYPE_CONTEXT (type) = context;
+
+ while (decl && DECL_PARALLEL_TYPE (decl))
+ {
+ TYPE_CONTEXT (DECL_PARALLEL_TYPE (decl)) = context;
+ decl = TYPE_STUB_DECL (DECL_PARALLEL_TYPE (decl));
+ }
+}
+
/* Record DECL as belonging to the current lexical scope and use GNAT_NODE
for location information and flag propagation. */
@@ -612,7 +629,7 @@ gnat_pushdecl (tree decl, Node_Id gnat_node)
if (TREE_CODE (t) == POINTER_TYPE)
TYPE_NEXT_PTR_TO (t) = tt;
TYPE_NAME (tt) = DECL_NAME (decl);
- TYPE_CONTEXT (tt) = DECL_CONTEXT (decl);
+ gnat_set_type_context (tt, DECL_CONTEXT (decl));
TYPE_STUB_DECL (tt) = TYPE_STUB_DECL (t);
DECL_ORIGINAL_TYPE (decl) = tt;
}
@@ -622,7 +639,7 @@ gnat_pushdecl (tree decl, Node_Id gnat_node)
/* We need a variant for the placeholder machinery to work. */
tree tt = build_variant_type_copy (t);
TYPE_NAME (tt) = decl;
- TYPE_CONTEXT (tt) = DECL_CONTEXT (decl);
+ gnat_set_type_context (tt, DECL_CONTEXT (decl));
TREE_USED (tt) = TREE_USED (t);
TREE_TYPE (decl) = tt;
if (DECL_ORIGINAL_TYPE (TYPE_NAME (t)))
@@ -644,7 +661,7 @@ gnat_pushdecl (tree decl, Node_Id gnat_node)
if (!(TYPE_NAME (t) && TREE_CODE (TYPE_NAME (t)) == TYPE_DECL))
{
TYPE_NAME (t) = decl;
- TYPE_CONTEXT (t) = DECL_CONTEXT (decl);
+ gnat_set_type_context (t, DECL_CONTEXT (decl));
}
}
}
@@ -1692,93 +1709,74 @@ rest_of_record_type_compilation (tree record_type)
TYPE_SIZE_UNIT (new_record_type)
= size_int (TYPE_ALIGN (record_type) / BITS_PER_UNIT);
- /* Now scan all the fields, replacing each field with a new
- field corresponding to the new encoding. */
+ /* Now scan all the fields, replacing each field with a new field
+ corresponding to the new encoding. */
for (old_field = TYPE_FIELDS (record_type); old_field;
old_field = DECL_CHAIN (old_field))
{
tree field_type = TREE_TYPE (old_field);
tree field_name = DECL_NAME (old_field);
- tree new_field;
tree curpos = bit_position (old_field);
+ tree pos, new_field;
bool var = false;
unsigned int align = 0;
- tree pos;
-
- /* See how the position was modified from the last position.
- There are two basic cases we support: a value was added
- to the last position or the last position was rounded to
- a boundary and they something was added. Check for the
- first case first. If not, see if there is any evidence
- of rounding. If so, round the last position and try
- again.
+ /* We're going to do some pattern matching below so remove as many
+ conversions as possible. */
+ curpos = remove_conversions (curpos, true);
- If this is a union, the position can be taken as zero. */
+ /* See how the position was modified from the last position.
- /* Some computations depend on the shape of the position expression,
- so strip conversions to make sure it's exposed. */
- curpos = remove_conversions (curpos, true);
+ There are two basic cases we support: a value was added
+ to the last position or the last position was rounded to
+ a boundary and they something was added. Check for the
+ first case first. If not, see if there is any evidence
+ of rounding. If so, round the last position and retry.
+ If this is a union, the position can be taken as zero. */
if (TREE_CODE (new_record_type) == UNION_TYPE)
- pos = bitsize_zero_node, align = 0;
+ pos = bitsize_zero_node;
else
pos = compute_related_constant (curpos, last_pos);
- if (!pos && TREE_CODE (curpos) == MULT_EXPR
+ if (!pos
+ && TREE_CODE (curpos) == MULT_EXPR
&& host_integerp (TREE_OPERAND (curpos, 1), 1))
{
tree offset = TREE_OPERAND (curpos, 0);
align = tree_low_cst (TREE_OPERAND (curpos, 1), 1);
-
- /* An offset which is a bitwise AND with a mask increases the
- alignment according to the number of trailing zeros. */
- offset = remove_conversions (offset, true);
- if (TREE_CODE (offset) == BIT_AND_EXPR
- && TREE_CODE (TREE_OPERAND (offset, 1)) == INTEGER_CST)
- {
- unsigned HOST_WIDE_INT mask
- = TREE_INT_CST_LOW (TREE_OPERAND (offset, 1));
- unsigned int i;
-
- for (i = 0; i < HOST_BITS_PER_WIDE_INT; i++)
- {
- if (mask & 1)
- break;
- mask >>= 1;
- align *= 2;
- }
- }
-
- pos = compute_related_constant (curpos,
- round_up (last_pos, align));
+ align = scale_by_factor_of (offset, align);
+ last_pos = round_up (last_pos, align);
+ pos = compute_related_constant (curpos, last_pos);
}
- else if (!pos && TREE_CODE (curpos) == PLUS_EXPR
- && TREE_CODE (TREE_OPERAND (curpos, 1)) == INTEGER_CST
+ else if (!pos
+ && TREE_CODE (curpos) == PLUS_EXPR
+ && host_integerp (TREE_OPERAND (curpos, 1), 1)
&& TREE_CODE (TREE_OPERAND (curpos, 0)) == MULT_EXPR
- && host_integerp (TREE_OPERAND
- (TREE_OPERAND (curpos, 0), 1),
- 1))
+ && host_integerp
+ (TREE_OPERAND (TREE_OPERAND (curpos, 0), 1), 1))
{
+ tree offset = TREE_OPERAND (TREE_OPERAND (curpos, 0), 0);
+ unsigned HOST_WIDE_INT addend
+ = tree_low_cst (TREE_OPERAND (curpos, 1), 1);
align
- = tree_low_cst
- (TREE_OPERAND (TREE_OPERAND (curpos, 0), 1), 1);
- pos = compute_related_constant (curpos,
- round_up (last_pos, align));
+ = tree_low_cst (TREE_OPERAND (TREE_OPERAND (curpos, 0), 1), 1);
+ align = scale_by_factor_of (offset, align);
+ align = MIN (align, addend & -addend);
+ last_pos = round_up (last_pos, align);
+ pos = compute_related_constant (curpos, last_pos);
}
- else if (potential_alignment_gap (prev_old_field, old_field,
- pos))
+ else if (potential_alignment_gap (prev_old_field, old_field, pos))
{
align = TYPE_ALIGN (field_type);
- pos = compute_related_constant (curpos,
- round_up (last_pos, align));
+ last_pos = round_up (last_pos, align);
+ pos = compute_related_constant (curpos, last_pos);
}
/* If we can't compute a position, set it to zero.
- ??? We really should abort here, but it's too much work
- to get this correct for all cases. */
-
+ ??? We really should abort here, but it's too much work
+ to get this correct for all cases. */
if (!pos)
pos = bitsize_zero_node;
@@ -2560,6 +2558,32 @@ value_factor_p (tree value, HOST_WIDE_INT factor)
return false;
}
+/* Return VALUE scaled by the biggest power-of-2 factor of EXPR. */
+
+static unsigned int
+scale_by_factor_of (tree expr, unsigned int value)
+{
+ expr = remove_conversions (expr, true);
+
+ /* An expression which is a bitwise AND with a mask has a power-of-2 factor
+ corresponding to the number of trailing zeros of the mask. */
+ if (TREE_CODE (expr) == BIT_AND_EXPR
+ && TREE_CODE (TREE_OPERAND (expr, 1)) == INTEGER_CST)
+ {
+ unsigned HOST_WIDE_INT mask = TREE_INT_CST_LOW (TREE_OPERAND (expr, 1));
+ unsigned int i = 0;
+
+ while ((mask & 1) == 0 && i < HOST_BITS_PER_WIDE_INT)
+ {
+ mask >>= 1;
+ value *= 2;
+ i++;
+ }
+ }
+
+ return value;
+}
+
/* Given two consecutive field decls PREV_FIELD and CURR_FIELD, return true
unless we can prove these 2 fields are laid out in such a way that no gap
exist between the end of PREV_FIELD and the beginning of CURR_FIELD. OFFSET
@@ -5609,7 +5633,7 @@ gnat_write_global_declarations (void)
TREE_STATIC (dummy_global) = 1;
TREE_ASM_WRITTEN (dummy_global) = 1;
node = varpool_node_for_decl (dummy_global);
- node->symbol.force_output = 1;
+ node->force_output = 1;
while (!types_used_by_cur_var_decl->is_empty ())
{
@@ -5765,6 +5789,7 @@ enum c_builtin_type
#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_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,
@@ -5783,6 +5808,7 @@ enum c_builtin_type
#undef DEF_FUNCTION_TYPE_5
#undef DEF_FUNCTION_TYPE_6
#undef DEF_FUNCTION_TYPE_7
+#undef DEF_FUNCTION_TYPE_8
#undef DEF_FUNCTION_TYPE_VAR_0
#undef DEF_FUNCTION_TYPE_VAR_1
#undef DEF_FUNCTION_TYPE_VAR_2
@@ -5878,6 +5904,10 @@ install_builtin_function_types (void)
#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_VAR_0(ENUM, RETURN) \
def_fn_type (ENUM, RETURN, 1, 0);
#define DEF_FUNCTION_TYPE_VAR_1(ENUM, RETURN, ARG1) \
diff --git a/gcc/ada/gcc-interface/utils2.c b/gcc/ada/gcc-interface/utils2.c
index 64f7564a75d..9410b4083bf 100644
--- a/gcc/ada/gcc-interface/utils2.c
+++ b/gcc/ada/gcc-interface/utils2.c
@@ -1874,6 +1874,7 @@ gnat_build_constructor (tree type, vec<constructor_elt, va_gc> *v)
v->qsort (compare_elmt_bitpos);
result = build_constructor (type, v);
+ CONSTRUCTOR_NO_CLEARING (result) = 1;
TREE_CONSTANT (result) = TREE_STATIC (result) = allconstant;
TREE_SIDE_EFFECTS (result) = side_effects;
TREE_READONLY (result) = TYPE_READONLY (type) || allconstant;
diff --git a/gcc/ada/gnat1drv.adb b/gcc/ada/gnat1drv.adb
index b0e3087508f..24341acd991 100644
--- a/gcc/ada/gnat1drv.adb
+++ b/gcc/ada/gnat1drv.adb
@@ -117,6 +117,13 @@ procedure Gnat1drv is
Relaxed_RM_Semantics := True;
end if;
+ -- -gnatd.E sets Error_To_Warning mode, causing selected error messages
+ -- to be treated as warnings instead of errors.
+
+ if Debug_Flag_Dot_EE then
+ Error_To_Warning := True;
+ end if;
+
-- Disable CodePeer_Mode in Check_Syntax, since we need front-end
-- expansion.
diff --git a/gcc/ada/gnat_rm.texi b/gcc/ada/gnat_rm.texi
index c1109b9c98a..5dcfbe86634 100644
--- a/gcc/ada/gnat_rm.texi
+++ b/gcc/ada/gnat_rm.texi
@@ -206,11 +206,15 @@ Implementation Defined Pragmas
* Pragma Passive::
* Pragma Persistent_BSS::
* Pragma Polling::
+* Pragma Post::
* Pragma Postcondition::
+* Pragma Post_Class::
+* Pragma Pre::
* Pragma Precondition::
* Pragma Predicate::
* Pragma Preelaborable_Initialization::
* Pragma Preelaborate_05::
+* Pragma Pre_Class::
* Pragma Priority_Specific_Dispatching::
* Pragma Profile::
* Pragma Profile_Warnings::
@@ -249,6 +253,8 @@ Implementation Defined Pragmas
* Pragma Thread_Local_Storage::
* Pragma Time_Slice::
* Pragma Title::
+* Pragma Type_Invariant::
+* Pragma Type_Invariant_Class::
* Pragma Unchecked_Union::
* Pragma Unimplemented_Unit::
* Pragma Universal_Aliasing ::
@@ -331,6 +337,7 @@ Implementation Defined Attributes
* Attribute Integer_Value::
* Attribute Invalid_Value::
* Attribute Large::
+* Attribute Library_Level::
* Attribute Loop_Entry::
* Attribute Machine_Size::
* Attribute Mantissa::
@@ -1022,11 +1029,15 @@ consideration, the use of these pragmas should be minimized.
* Pragma Passive::
* Pragma Persistent_BSS::
* Pragma Polling::
+* Pragma Post::
* Pragma Postcondition::
+* Pragma Post_Class::
+* Pragma Pre::
* Pragma Precondition::
* Pragma Predicate::
* Pragma Preelaborable_Initialization::
* Pragma Preelaborate_05::
+* Pragma Pre_Class::
* Pragma Priority_Specific_Dispatching::
* Pragma Profile::
* Pragma Profile_Warnings::
@@ -1065,6 +1076,8 @@ consideration, the use of these pragmas should be minimized.
* Pragma Thread_Local_Storage::
* Pragma Time_Slice::
* Pragma Title::
+* Pragma Type_Invariant::
+* Pragma Type_Invariant_Class::
* Pragma Unchecked_Union::
* Pragma Unimplemented_Unit::
* Pragma Universal_Aliasing ::
@@ -1375,7 +1388,9 @@ ID_ASSERTION_KIND ::= Assertions |
Loop_Variant |
Postcondition |
Precondition |
- Predicate
+ Predicate |
+ Refined_Post |
+ Refined_Pre |
Statement_Assertions
POLICY_IDENTIFIER ::= Check | Disable | Ignore
@@ -1391,7 +1406,10 @@ are implementation defined additions recognized by the GNAT compiler.
The pragma applies in both cases to pragmas and aspects with matching
names, e.g. @code{Pre} applies to the Pre aspect, and @code{Precondition}
applies to both the @code{Precondition} pragma
-and the aspect @code{Precondition}.
+and the aspect @code{Precondition}. Note that the identifiers for
+pragmas Pre_Class and Post_Class are Pre'Class and Post'Class (not
+Pre_Class and Post_Class), since these pragmas are intended to be
+identical to the corresponding aspects).
If the policy is @code{CHECK}, then assertions are enabled, i.e.
the corresponding pragma or aspect is activated.
@@ -5014,6 +5032,28 @@ Note that polling can also be enabled by use of the @option{-gnatP} switch.
@xref{Switches for gcc,,, gnat_ugn, @value{EDITION} User's Guide}, for
details.
+@node Pragma Post
+@unnumberedsec Pragma Post
+@cindex Post
+@cindex Checks, postconditions
+@findex Postconditions
+@noindent
+Syntax:
+
+@smallexample @c ada
+pragma Post (Boolean_Expression);
+@end smallexample
+
+@noindent
+The @code{Post} pragma is intended to be an exact replacement for
+the language-defined
+@code{Post} aspect, and shares its restrictions and semantics.
+It must appear either immediately following the corresponding
+subprogram declaration (only other pragmas may intervene), or
+if there is no separate subprogram declaration, then it can
+appear at the start of the declarations in a subprogram body
+(preceded only by other pragmas).
+
@node Pragma Postcondition
@unnumberedsec Pragma Postcondition
@cindex Postcondition
@@ -5171,6 +5211,69 @@ inlining (-gnatN option set) are accepted and legality-checked
by the compiler, but are ignored at run-time even if postcondition
checking is enabled.
+Note that pragma @code{Postcondition} differs from the language-defined
+@code{Post} aspect (and corresponding @code{Post} pragma) in allowing
+multiple occurrences, allowing occurences in the body even if there
+is a separate spec, and allowing a second string parameter, and the
+use of the pragma identifier @code{Check}. Historically, pragma
+@code{Postcondition} was implemented prior to the development of
+Ada 2012, and has been retained in its original form for
+compatibility purposes.
+
+@node Pragma Post_Class
+@unnumberedsec Pragma Post_Class
+@cindex Post
+@cindex Checks, postconditions
+@findex Postconditions
+@noindent
+Syntax:
+
+@smallexample @c ada
+pragma Post_Class (Boolean_Expression);
+@end smallexample
+
+@noindent
+The @code{Post_Class} pragma is intended to be an exact replacement for
+the language-defined
+@code{Post'Class} aspect, and shares its restrictions and semantics.
+It must appear either immediately following the corresponding
+subprogram declaration (only other pragmas may intervene), or
+if there is no separate subprogram declaration, then it can
+appear at the start of the declarations in a subprogram body
+(preceded only by other pragmas).
+
+Note: This pragma is called @code{Post_Class} rather than
+@code{Post'Class} because the latter would not be strictly
+conforming to the allowed syntax for pragmas. The motivation
+for provinding pragmas equivalent to the aspects is to allow a program
+to be written using the pragmas, and then compiled if necessary
+using an Ada compiler that does not recognize the pragmas or
+aspects, but is prepared to ignore the pragmas. The assertion
+policy that controls this pragma is @code{Post'Class}, not
+@code{Post_Class}.
+
+@node Pragma Pre
+@unnumberedsec Pragma Pre
+@cindex Pre
+@cindex Checks, preconditions
+@findex Preconditions
+@noindent
+Syntax:
+
+@smallexample @c ada
+pragma Pre (Boolean_Expression);
+@end smallexample
+
+@noindent
+The @code{Pre} pragma is intended to be an exact replacement for
+the language-defined
+@code{Pre} aspect, and shares its restrictions and semantics.
+It must appear either immediately following the corresponding
+subprogram declaration (only other pragmas may intervene), or
+if there is no separate subprogram declaration, then it can
+appear at the start of the declarations in a subprogram body
+(preceded only by other pragmas).
+
@node Pragma Precondition
@unnumberedsec Pragma Precondition
@cindex Preconditions
@@ -5219,6 +5322,15 @@ inlining (-gnatN option set) are accepted and legality-checked
by the compiler, but are ignored at run-time even if precondition
checking is enabled.
+Note that pragma @code{Precondition} differs from the language-defined
+@code{Pre} aspect (and corresponding @code{Pre} pragma) in allowing
+multiple occurrences, allowing occurences in the body even if there
+is a separate spec, and allowing a second string parameter, and the
+use of the pragma identifier @code{Check}. Historically, pragma
+@code{Precondition} was implemented prior to the development of
+Ada 2012, and has been retained in its original form for
+compatibility purposes.
+
@node Pragma Predicate
@unnumberedsec Pragma Predicate
@findex Predicate
@@ -5260,6 +5372,21 @@ subtype Q is R with
Dynamic_Predicate => F(Q) or G(Q);
@end smallexample
+Note that there is are no pragmas @code{Dynamic_Predicate}
+or @code{Static_Predicate}. That is
+because these pragmas would affect legality and semantics of
+the program and thus do not have a neutral effect if ignored.
+The motivation behind providing pragmas equivalent to
+corresponding aspects is to allow a program to be written
+using the pragmas, and then compiled with a compiler that
+will ignore the pragmas. That doesn't work in the case of
+static and dynamic predicates, since if the corresponding
+pragmas are ignored, then the behavior of the program is
+fundamentally changed (for example a membership test
+@code{A in B} would not take into account a predicate
+defined for subtype B). When following this approach, the
+use of predicates should be avoided.
+
@node Pragma Preelaborable_Initialization
@unnumberedsec Pragma Preelaborable_Initialization
@findex Preelaborable_Initialization
@@ -5293,6 +5420,38 @@ equivalent to @code{pragma Prelaborate} when operating in later
Ada versions. This is used to handle some cases where packages
not previously preelaborable became so in Ada 2005.
+@node Pragma Pre_Class
+@unnumberedsec Pragma Pre_Class
+@cindex Pre_Class
+@cindex Checks, preconditions
+@findex Preconditions
+@noindent
+Syntax:
+
+@smallexample @c ada
+pragma Pre_Class (Boolean_Expression);
+@end smallexample
+
+@noindent
+The @code{Pre_Class} pragma is intended to be an exact replacement for
+the language-defined
+@code{Pre'Class} aspect, and shares its restrictions and semantics.
+It must appear either immediately following the corresponding
+subprogram declaration (only other pragmas may intervene), or
+if there is no separate subprogram declaration, then it can
+appear at the start of the declarations in a subprogram body
+(preceded only by other pragmas).
+
+Note: This pragma is called @code{Pre_Class} rather than
+@code{Pre'Class} because the latter would not be strictly
+conforming to the allowed syntax for pragmas. The motivation
+for providing pragmas equivalent to the aspects is to allow a program
+to be written using the pragmas, and then compiled if necessary
+using an Ada compiler that does not recognize the pragmas or
+aspects, but is prepared to ignore the pragmas. The assertion
+policy that controls this pragma is @code{Pre'Class}, not
+@code{Pre_Class}.
+
@node Pragma Priority_Specific_Dispatching
@unnumberedsec Pragma Priority_Specific_Dispatching
@findex Priority_Specific_Dispatching
@@ -6647,6 +6806,56 @@ for this pragma, i.e.@: the parameters may be given in any order if named
notation is used, and named and positional notation can be mixed
following the normal rules for procedure calls in Ada.
+@node Pragma Type_Invariant
+@unnumberedsec Pragma Type_Invariant
+@findex Invariant
+@findex Type_Invariant pragma
+@noindent
+Syntax:
+
+@smallexample @c ada
+pragma Type_Invariant
+ ([Entity =>] type_LOCAL_NAME,
+ [Check =>] EXPRESSION);
+@end smallexample
+
+@noindent
+The @code{Type_Invariant} pragma is intended to be an exact
+replacement for the language-defined @code{Type_Invariant}
+aspect, and shares its restrictions and semantics. It differs
+from the language defined @code{Invariant} pragma in that it
+does not permit a string parameter, and it is
+controlled by the assertion identifier @code{Type_Invariant}
+rather than @code{Invariant}.
+
+@node Pragma Type_Invariant_Class
+@unnumberedsec Pragma Type_Invariant_Class
+@findex Invariant
+@findex Type_Invariant_Class pragma
+@noindent
+Syntax:
+
+@smallexample @c ada
+pragma Type_Invariant_Class
+ ([Entity =>] type_LOCAL_NAME,
+ [Check =>] EXPRESSION);
+@end smallexample
+
+@noindent
+The @code{Type_Invariant_Class} pragma is intended to be an exact
+replacement for the language-defined @code{Type_Invariant'Class}
+aspect, and shares its restrictions and semantics.
+
+Note: This pragma is called @code{Type_Invariant_Class} rather than
+@code{Type_Invariant'Class} because the latter would not be strictly
+conforming to the allowed syntax for pragmas. The motivation
+for providing pragmas equivalent to the aspects is to allow a program
+to be written using the pragmas, and then compiled if necessary
+using an Ada compiler that does not recognize the pragmas or
+aspects, but is prepared to ignore the pragmas. The assertion
+policy that controls this pragma is @code{Type_Invariant'Class},
+not @code{Type_Invariant_Class}.
+
@node Pragma Unchecked_Union
@unnumberedsec Pragma Unchecked_Union
@cindex Unions in C
@@ -7634,6 +7843,7 @@ consideration, you should minimize the use of these attributes.
* Attribute Integer_Value::
* Attribute Invalid_Value::
* Attribute Large::
+* Attribute Library_Level::
* Attribute Loop_Entry::
* Attribute Machine_Size::
* Attribute Mantissa::
@@ -8133,6 +8343,30 @@ The @code{Large} attribute is provided for compatibility with Ada 83. See
the Ada 83 reference manual for an exact description of the semantics of
this attribute.
+@node Attribute Library_Level
+@unnumberedsec Attribute Library_Level
+@findex Library_Level
+@noindent
+@noindent
+@code{P'Library_Level}, where P is an entity name,
+returns a Boolean value which is True if the entity is declared
+at the library level, and False otherwise. Note that within a
+generic instantition, the name of the generic unit denotes the
+instance, which means that this attribute can be used to test
+if a generic is instantiated at the library level, as shown
+in this example:
+
+@smallexample @c ada
+generic
+ ...
+package Gen is
+ pragma Compile_Time_Error
+ (not Gen'Library_Level,
+ "Gen can only be instantiated at library level");
+ ...
+end Gen;
+@end smallexample
+
@node Attribute Loop_Entry
@unnumberedsec Attribute Loop_Entry
@findex Loop_Entry
@@ -8493,6 +8727,10 @@ have a @code{Scalar_Storage_Order} attribute definition clause. In addition,
if the component does not start on a byte boundary, then the scalar storage
order specified for S and for the nested component type shall be identical.
+If @var{S} appears as the type of a record or array component, the enclosing
+record or array shall also have a @code{Scalar_Storage_Order} attribute
+definition clause.
+
No component of a type that has a @code{Scalar_Storage_Order} attribute
definition may be aliased.
@@ -8665,11 +8903,15 @@ denotes a function identical to
@code{System.Storage_Elements.To_Address} except that
it is a static attribute. This means that if its argument is
a static expression, then the result of the attribute is a
-static expression. The result is that such an expression can be
+static expression. This means that such an expression can be
used in contexts (e.g.@: preelaborable packages) which require a
static expression and where the function call could not be used
(since the function call is always non-static, even if its
-argument is static).
+argument is static). The argument must be in the range
+-(2**(m-1) .. 2**m-1, where m is the memory size
+(typically 32 or 64). Negative values are intepreted in a
+modular manner (e.g. -1 means the same as 16#FFFF_FFFF# on
+a 32 bits machine).
@node Attribute Type_Class
@unnumberedsec Attribute Type_Class
@@ -8777,7 +9019,7 @@ The @code{Update} attribute creates a copy of an array or record value
with one or more modified components. The syntax is:
@smallexample @c ada
-PREFIX'Update (AGGREGATE);
+PREFIX'Update (AGGREGATE)
@end smallexample
@noindent
@@ -8825,6 +9067,8 @@ kept in mind when considering efficiency.
The @code{Update} attribute cannot be applied to prefixes of a limited
type, and cannot reference discriminants in the case of a record type.
+The accessibility level of an Update attribute result object is defined
+as for an aggregate.
In the record case, no component can be mentioned more than once. In
the array case, two overlapping ranges can appear in the aggregate,
@@ -11723,6 +11967,7 @@ where @var{nnn} is an integer.
@emph{Exception_Name:} nnnnn
@emph{Message:} mmmmm
@emph{PID:} ppp
+@emph{Load address:} 0xhhhh
@emph{Call stack traceback locations:}
0xhhhh 0xhhhh 0xhhhh ... 0xhhh
@end smallexample
@@ -11744,10 +11989,12 @@ present only if the Process Id is nonzero). Currently we are
not making use of this field.
@item
-The Call stack traceback locations line and the following values
-are present only if at least one traceback location was recorded.
-The values are given in C style format, with lower case letters
-for a-f, and only as many digits present as are necessary.
+The Load address line, the Call stack traceback locations line and the
+following values are present only if at least one traceback location was
+recorded. The Load address indicates the address at which the main executable
+was loaded; this line may not be present if operating system hasn't relocated
+the main executable. The values are given in C style format, with lower case
+letters for a-f, and only as many digits present as are necessary.
@end itemize
@noindent
@@ -12003,7 +12250,18 @@ See items describing the integer and floating-point types supported.
@sp 1
@cartouche
@noindent
-@strong{61}. The accuracy actually achieved by the elementary
+@strong{61}. The string returned by @code{Character_Set_Version}.
+See A.3.5(3).
+@end cartouche
+@noindent
+@code{Ada.Wide_Characters.Handling.Character_Set_Version} returns
+the string "Unicode 6.2", referring to version 6.2.x of the
+Unicode specification.
+
+@sp 1
+@cartouche
+@noindent
+@strong{62}. The accuracy actually achieved by the elementary
functions. See A.5.1(1).
@end cartouche
@noindent
@@ -12013,7 +12271,7 @@ library. Only fast math mode is implemented.
@sp 1
@cartouche
@noindent
-@strong{62}. The sign of a zero result from some of the operators or
+@strong{63}. The sign of a zero result from some of the operators or
functions in @code{Numerics.Generic_Elementary_Functions}, when
@code{Float_Type'Signed_Zeros} is @code{True}. See A.5.1(46).
@end cartouche
@@ -12024,7 +12282,7 @@ floating-point.
@sp 1
@cartouche
@noindent
-@strong{63}. The value of
+@strong{64}. The value of
@code{Numerics.Float_Random.Max_Image_Width}. See A.5.2(27).
@end cartouche
@noindent
@@ -12033,7 +12291,7 @@ Maximum image width is 6864, see library file @file{s-rannum.ads}.
@sp 1
@cartouche
@noindent
-@strong{64}. The value of
+@strong{65}. The value of
@code{Numerics.Discrete_Random.Max_Image_Width}. See A.5.2(27).
@end cartouche
@noindent
@@ -12042,7 +12300,7 @@ Maximum image width is 6864, see library file @file{s-rannum.ads}.
@sp 1
@cartouche
@noindent
-@strong{65}. The algorithms for random number generation. See
+@strong{66}. The algorithms for random number generation. See
A.5.2(32).
@end cartouche
@noindent
@@ -12053,7 +12311,7 @@ The algorithm is the Mersenne Twister, as documented in the source file
@sp 1
@cartouche
@noindent
-@strong{66}. The string representation of a random number generator's
+@strong{67}. The string representation of a random number generator's
state. See A.5.2(38).
@end cartouche
@noindent
@@ -12064,7 +12322,7 @@ of the state vector.
@sp 1
@cartouche
@noindent
-@strong{67}. The minimum time interval between calls to the
+@strong{68}. The minimum time interval between calls to the
time-dependent Reset procedure that are guaranteed to initiate different
random number sequences. See A.5.2(45).
@end cartouche
@@ -12075,7 +12333,7 @@ random numbers is one microsecond.
@sp 1
@cartouche
@noindent
-@strong{68}. The values of the @code{Model_Mantissa},
+@strong{69}. The values of the @code{Model_Mantissa},
@code{Model_Emin}, @code{Model_Epsilon}, @code{Model},
@code{Safe_First}, and @code{Safe_Last} attributes, if the Numerics
Annex is not supported. See A.5.3(72).
@@ -12087,7 +12345,7 @@ Run the compiler with @option{-gnatS} to produce a listing of package
@sp 1
@cartouche
@noindent
-@strong{69}. Any implementation-defined characteristics of the
+@strong{70}. Any implementation-defined characteristics of the
input-output packages. See A.7(14).
@end cartouche
@noindent
@@ -12097,7 +12355,7 @@ packages.
@sp 1
@cartouche
@noindent
-@strong{70}. The value of @code{Buffer_Size} in @code{Storage_IO}. See
+@strong{71}. The value of @code{Buffer_Size} in @code{Storage_IO}. See
A.9(10).
@end cartouche
@noindent
@@ -12108,7 +12366,7 @@ boundary.
@sp 1
@cartouche
@noindent
-@strong{71}. External files for standard input, standard output, and
+@strong{72}. External files for standard input, standard output, and
standard error See A.10(5).
@end cartouche
@noindent
@@ -12118,7 +12376,7 @@ libraries. See source file @file{i-cstrea.ads} for further details.
@sp 1
@cartouche
@noindent
-@strong{72}. The accuracy of the value produced by @code{Put}. See
+@strong{73}. The accuracy of the value produced by @code{Put}. See
A.10.9(36).
@end cartouche
@noindent
@@ -12129,7 +12387,7 @@ significant digit positions.
@sp 1
@cartouche
@noindent
-@strong{73}. The meaning of @code{Argument_Count}, @code{Argument}, and
+@strong{74}. The meaning of @code{Argument_Count}, @code{Argument}, and
@code{Command_Name}. See A.15(1).
@end cartouche
@noindent
@@ -12139,7 +12397,7 @@ main program in the natural manner.
@sp 1
@cartouche
@noindent
-@strong{74}. The interpretation of the @code{Form} parameter in procedure
+@strong{75}. The interpretation of the @code{Form} parameter in procedure
@code{Create_Directory}. See A.16(56).
@end cartouche
@noindent
@@ -12148,7 +12406,7 @@ The @code{Form} parameter is not used.
@sp 1
@cartouche
@noindent
-@strong{75}. The interpretation of the @code{Form} parameter in procedure
+@strong{76}. The interpretation of the @code{Form} parameter in procedure
@code{Create_Path}. See A.16(60).
@end cartouche
@noindent
@@ -12157,7 +12415,7 @@ The @code{Form} parameter is not used.
@sp 1
@cartouche
@noindent
-@strong{76}. The interpretation of the @code{Form} parameter in procedure
+@strong{77}. The interpretation of the @code{Form} parameter in procedure
@code{Copy_File}. See A.16(68).
@end cartouche
@noindent
@@ -12236,7 +12494,7 @@ Form => "mode=internal, preserve=timestamps"
@sp 1
@cartouche
@noindent
-@strong{77}. Implementation-defined convention names. See B.1(11).
+@strong{78}. Implementation-defined convention names. See B.1(11).
@end cartouche
@noindent
The following convention names are supported
@@ -12303,7 +12561,7 @@ implementations, these names are accepted silently.
@sp 1
@cartouche
@noindent
-@strong{78}. The meaning of link names. See B.1(36).
+@strong{79}. The meaning of link names. See B.1(36).
@end cartouche
@noindent
Link names are the actual names used by the linker.
@@ -12311,7 +12569,7 @@ Link names are the actual names used by the linker.
@sp 1
@cartouche
@noindent
-@strong{79}. The manner of choosing link names when neither the link
+@strong{80}. The manner of choosing link names when neither the link
name nor the address of an imported or exported entity is specified. See
B.1(36).
@end cartouche
@@ -12323,7 +12581,7 @@ letters.
@sp 1
@cartouche
@noindent
-@strong{80}. The effect of pragma @code{Linker_Options}. See B.1(37).
+@strong{81}. The effect of pragma @code{Linker_Options}. See B.1(37).
@end cartouche
@noindent
The string passed to @code{Linker_Options} is presented uninterpreted as
@@ -12344,7 +12602,7 @@ from the corresponding package spec.
@sp 1
@cartouche
@noindent
-@strong{81}. The contents of the visible part of package
+@strong{82}. The contents of the visible part of package
@code{Interfaces} and its language-defined descendants. See B.2(1).
@end cartouche
@noindent
@@ -12353,7 +12611,7 @@ See files with prefix @file{i-} in the distributed library.
@sp 1
@cartouche
@noindent
-@strong{82}. Implementation-defined children of package
+@strong{83}. Implementation-defined children of package
@code{Interfaces}. The contents of the visible part of package
@code{Interfaces}. See B.2(11).
@end cartouche
@@ -12363,7 +12621,7 @@ See files with prefix @file{i-} in the distributed library.
@sp 1
@cartouche
@noindent
-@strong{83}. The types @code{Floating}, @code{Long_Floating},
+@strong{84}. The types @code{Floating}, @code{Long_Floating},
@code{Binary}, @code{Long_Binary}, @code{Decimal_ Element}, and
@code{COBOL_Character}; and the initialization of the variables
@code{Ada_To_COBOL} and @code{COBOL_To_Ada}, in
@@ -12391,7 +12649,7 @@ For initialization, see the file @file{i-cobol.ads} in the distributed library.
@sp 1
@cartouche
@noindent
-@strong{84}. Support for access to machine instructions. See C.1(1).
+@strong{85}. Support for access to machine instructions. See C.1(1).
@end cartouche
@noindent
See documentation in file @file{s-maccod.ads} in the distributed library.
@@ -12399,7 +12657,7 @@ See documentation in file @file{s-maccod.ads} in the distributed library.
@sp 1
@cartouche
@noindent
-@strong{85}. Implementation-defined aspects of access to machine
+@strong{86}. Implementation-defined aspects of access to machine
operations. See C.1(9).
@end cartouche
@noindent
@@ -12408,7 +12666,7 @@ See documentation in file @file{s-maccod.ads} in the distributed library.
@sp 1
@cartouche
@noindent
-@strong{86}. Implementation-defined aspects of interrupts. See C.3(2).
+@strong{87}. Implementation-defined aspects of interrupts. See C.3(2).
@end cartouche
@noindent
Interrupts are mapped to signals or conditions as appropriate. See
@@ -12419,7 +12677,7 @@ on the interrupts supported on a particular target.
@sp 1
@cartouche
@noindent
-@strong{87}. Implementation-defined aspects of pre-elaboration. See
+@strong{88}. Implementation-defined aspects of pre-elaboration. See
C.4(13).
@end cartouche
@noindent
@@ -12429,7 +12687,7 @@ except under control of the debugger.
@sp 1
@cartouche
@noindent
-@strong{88}. The semantics of pragma @code{Discard_Names}. See C.5(7).
+@strong{89}. The semantics of pragma @code{Discard_Names}. See C.5(7).
@end cartouche
@noindent
Pragma @code{Discard_Names} causes names of enumeration literals to
@@ -12440,7 +12698,7 @@ Pos values.
@sp 1
@cartouche
@noindent
-@strong{89}. The result of the @code{Task_Identification.Image}
+@strong{90}. The result of the @code{Task_Identification.Image}
attribute. See C.7.1(7).
@end cartouche
@noindent
@@ -12470,7 +12728,7 @@ virtual address of the control block of the task.
@sp 1
@cartouche
@noindent
-@strong{90}. The value of @code{Current_Task} when in a protected entry
+@strong{91}. The value of @code{Current_Task} when in a protected entry
or interrupt handler. See C.7.1(17).
@end cartouche
@noindent
@@ -12480,7 +12738,7 @@ convenient thread, so the value of @code{Current_Task} is undefined.
@sp 1
@cartouche
@noindent
-@strong{91}. The effect of calling @code{Current_Task} from an entry
+@strong{92}. The effect of calling @code{Current_Task} from an entry
body or interrupt handler. See C.7.1(19).
@end cartouche
@noindent
@@ -12491,7 +12749,7 @@ executing the code.
@sp 1
@cartouche
@noindent
-@strong{92}. Implementation-defined aspects of
+@strong{93}. Implementation-defined aspects of
@code{Task_Attributes}. See C.7.2(19).
@end cartouche
@noindent
@@ -12500,7 +12758,7 @@ There are no implementation-defined aspects of @code{Task_Attributes}.
@sp 1
@cartouche
@noindent
-@strong{93}. Values of all @code{Metrics}. See D(2).
+@strong{94}. Values of all @code{Metrics}. See D(2).
@end cartouche
@noindent
The metrics information for GNAT depends on the performance of the
@@ -12515,7 +12773,7 @@ the required metrics.
@sp 1
@cartouche
@noindent
-@strong{94}. The declarations of @code{Any_Priority} and
+@strong{95}. The declarations of @code{Any_Priority} and
@code{Priority}. See D.1(11).
@end cartouche
@noindent
@@ -12524,7 +12782,7 @@ See declarations in file @file{system.ads}.
@sp 1
@cartouche
@noindent
-@strong{95}. Implementation-defined execution resources. See D.1(15).
+@strong{96}. Implementation-defined execution resources. See D.1(15).
@end cartouche
@noindent
There are no implementation-defined execution resources.
@@ -12532,7 +12790,7 @@ There are no implementation-defined execution resources.
@sp 1
@cartouche
@noindent
-@strong{96}. Whether, on a multiprocessor, a task that is waiting for
+@strong{97}. Whether, on a multiprocessor, a task that is waiting for
access to a protected object keeps its processor busy. See D.2.1(3).
@end cartouche
@noindent
@@ -12542,7 +12800,7 @@ object does not keep its processor busy.
@sp 1
@cartouche
@noindent
-@strong{97}. The affect of implementation defined execution resources
+@strong{98}. The affect of implementation defined execution resources
on task dispatching. See D.2.1(9).
@end cartouche
@noindent
@@ -12553,7 +12811,7 @@ underlying operating system.
@sp 1
@cartouche
@noindent
-@strong{98}. Implementation-defined @code{policy_identifiers} allowed
+@strong{99}. Implementation-defined @code{policy_identifiers} allowed
in a pragma @code{Task_Dispatching_Policy}. See D.2.2(3).
@end cartouche
@noindent
@@ -12563,7 +12821,7 @@ pragma.
@sp 1
@cartouche
@noindent
-@strong{99}. Implementation-defined aspects of priority inversion. See
+@strong{100}. Implementation-defined aspects of priority inversion. See
D.2.2(16).
@end cartouche
@noindent
@@ -12573,7 +12831,7 @@ of delay expirations for lower priority tasks.
@sp 1
@cartouche
@noindent
-@strong{100}. Implementation-defined task dispatching. See D.2.2(18).
+@strong{101}. Implementation-defined task dispatching. See D.2.2(18).
@end cartouche
@noindent
The policy is the same as that of the underlying threads implementation.
@@ -12581,7 +12839,7 @@ The policy is the same as that of the underlying threads implementation.
@sp 1
@cartouche
@noindent
-@strong{101}. Implementation-defined @code{policy_identifiers} allowed
+@strong{102}. Implementation-defined @code{policy_identifiers} allowed
in a pragma @code{Locking_Policy}. See D.3(4).
@end cartouche
@noindent
@@ -12598,7 +12856,7 @@ concurrently.
@sp 1
@cartouche
@noindent
-@strong{102}. Default ceiling priorities. See D.3(10).
+@strong{103}. Default ceiling priorities. See D.3(10).
@end cartouche
@noindent
The ceiling priority of protected objects of the type
@@ -12608,7 +12866,7 @@ Reference Manual D.3(10),
@sp 1
@cartouche
@noindent
-@strong{103}. The ceiling of any protected object used internally by
+@strong{104}. The ceiling of any protected object used internally by
the implementation. See D.3(16).
@end cartouche
@noindent
@@ -12618,7 +12876,7 @@ The ceiling priority of internal protected objects is
@sp 1
@cartouche
@noindent
-@strong{104}. Implementation-defined queuing policies. See D.4(1).
+@strong{105}. Implementation-defined queuing policies. See D.4(1).
@end cartouche
@noindent
There are no implementation-defined queuing policies.
@@ -12626,7 +12884,7 @@ There are no implementation-defined queuing policies.
@sp 1
@cartouche
@noindent
-@strong{105}. On a multiprocessor, any conditions that cause the
+@strong{106}. On a multiprocessor, any conditions that cause the
completion of an aborted construct to be delayed later than what is
specified for a single processor. See D.6(3).
@end cartouche
@@ -12637,7 +12895,7 @@ processor, there are no further delays.
@sp 1
@cartouche
@noindent
-@strong{106}. Any operations that implicitly require heap storage
+@strong{107}. Any operations that implicitly require heap storage
allocation. See D.7(8).
@end cartouche
@noindent
@@ -12647,7 +12905,7 @@ task creation.
@sp 1
@cartouche
@noindent
-@strong{107}. Implementation-defined aspects of pragma
+@strong{108}. Implementation-defined aspects of pragma
@code{Restrictions}. See D.7(20).
@end cartouche
@noindent
@@ -12656,7 +12914,7 @@ There are no such implementation-defined aspects.
@sp 1
@cartouche
@noindent
-@strong{108}. Implementation-defined aspects of package
+@strong{109}. Implementation-defined aspects of package
@code{Real_Time}. See D.8(17).
@end cartouche
@noindent
@@ -12665,7 +12923,7 @@ There are no implementation defined aspects of package @code{Real_Time}.
@sp 1
@cartouche
@noindent
-@strong{109}. Implementation-defined aspects of
+@strong{110}. Implementation-defined aspects of
@code{delay_statements}. See D.9(8).
@end cartouche
@noindent
@@ -12675,7 +12933,7 @@ delayed (see D.9(7)).
@sp 1
@cartouche
@noindent
-@strong{110}. The upper bound on the duration of interrupt blocking
+@strong{111}. The upper bound on the duration of interrupt blocking
caused by the implementation. See D.12(5).
@end cartouche
@noindent
@@ -12685,7 +12943,7 @@ no cases is it more than 10 milliseconds.
@sp 1
@cartouche
@noindent
-@strong{111}. The means for creating and executing distributed
+@strong{112}. The means for creating and executing distributed
programs. See E(5).
@end cartouche
@noindent
@@ -12695,7 +12953,7 @@ distributed programs. See the GLADE reference manual for further details.
@sp 1
@cartouche
@noindent
-@strong{112}. Any events that can result in a partition becoming
+@strong{113}. Any events that can result in a partition becoming
inaccessible. See E.1(7).
@end cartouche
@noindent
@@ -12704,7 +12962,7 @@ See the GLADE reference manual for full details on such events.
@sp 1
@cartouche
@noindent
-@strong{113}. The scheduling policies, treatment of priorities, and
+@strong{114}. The scheduling policies, treatment of priorities, and
management of shared resources between partitions in certain cases. See
E.1(11).
@end cartouche
@@ -12715,7 +12973,7 @@ multi-partition execution.
@sp 1
@cartouche
@noindent
-@strong{114}. Events that cause the version of a compilation unit to
+@strong{115}. Events that cause the version of a compilation unit to
change. See E.3(5).
@end cartouche
@noindent
@@ -12728,7 +12986,7 @@ comments.
@sp 1
@cartouche
@noindent
-@strong{115}. Whether the execution of the remote subprogram is
+@strong{116}. Whether the execution of the remote subprogram is
immediately aborted as a result of cancellation. See E.4(13).
@end cartouche
@noindent
@@ -12738,7 +12996,7 @@ a distributed application.
@sp 1
@cartouche
@noindent
-@strong{116}. Implementation-defined aspects of the PCS@. See E.5(25).
+@strong{117}. Implementation-defined aspects of the PCS@. See E.5(25).
@end cartouche
@noindent
See the GLADE reference manual for a full description of all implementation
@@ -12747,7 +13005,7 @@ defined aspects of the PCS@.
@sp 1
@cartouche
@noindent
-@strong{117}. Implementation-defined interfaces in the PCS@. See
+@strong{118}. Implementation-defined interfaces in the PCS@. See
E.5(26).
@end cartouche
@noindent
@@ -12757,7 +13015,7 @@ implementation defined interfaces.
@sp 1
@cartouche
@noindent
-@strong{118}. The values of named numbers in the package
+@strong{119}. The values of named numbers in the package
@code{Decimal}. See F.2(7).
@end cartouche
@noindent
@@ -12777,7 +13035,7 @@ implementation defined interfaces.
@sp 1
@cartouche
@noindent
-@strong{119}. The value of @code{Max_Picture_Length} in the package
+@strong{120}. The value of @code{Max_Picture_Length} in the package
@code{Text_IO.Editing}. See F.3.3(16).
@end cartouche
@noindent
@@ -12786,7 +13044,7 @@ implementation defined interfaces.
@sp 1
@cartouche
@noindent
-@strong{120}. The value of @code{Max_Picture_Length} in the package
+@strong{121}. The value of @code{Max_Picture_Length} in the package
@code{Wide_Text_IO.Editing}. See F.3.4(5).
@end cartouche
@noindent
@@ -12795,7 +13053,7 @@ implementation defined interfaces.
@sp 1
@cartouche
@noindent
-@strong{121}. The accuracy actually achieved by the complex elementary
+@strong{122}. The accuracy actually achieved by the complex elementary
functions and by other complex arithmetic operations. See G.1(1).
@end cartouche
@noindent
@@ -12805,7 +13063,7 @@ operations. Only fast math mode is currently supported.
@sp 1
@cartouche
@noindent
-@strong{122}. The sign of a zero result (or a component thereof) from
+@strong{123}. The sign of a zero result (or a component thereof) from
any operator or function in @code{Numerics.Generic_Complex_Types}, when
@code{Real'Signed_Zeros} is True. See G.1.1(53).
@end cartouche
@@ -12816,7 +13074,7 @@ implementation advice.
@sp 1
@cartouche
@noindent
-@strong{123}. The sign of a zero result (or a component thereof) from
+@strong{124}. The sign of a zero result (or a component thereof) from
any operator or function in
@code{Numerics.Generic_Complex_Elementary_Functions}, when
@code{Real'Signed_Zeros} is @code{True}. See G.1.2(45).
@@ -12828,7 +13086,7 @@ implementation advice.
@sp 1
@cartouche
@noindent
-@strong{124}. Whether the strict mode or the relaxed mode is the
+@strong{125}. Whether the strict mode or the relaxed mode is the
default. See G.2(2).
@end cartouche
@noindent
@@ -12838,7 +13096,7 @@ provides a highly efficient implementation of strict mode.
@sp 1
@cartouche
@noindent
-@strong{125}. The result interval in certain cases of fixed-to-float
+@strong{126}. The result interval in certain cases of fixed-to-float
conversion. See G.2.1(10).
@end cartouche
@noindent
@@ -12849,7 +13107,7 @@ floating-point format.
@sp 1
@cartouche
@noindent
-@strong{126}. The result of a floating point arithmetic operation in
+@strong{127}. The result of a floating point arithmetic operation in
overflow situations, when the @code{Machine_Overflows} attribute of the
result type is @code{False}. See G.2.1(13).
@end cartouche
@@ -12866,7 +13124,7 @@ properly generated.
@sp 1
@cartouche
@noindent
-@strong{127}. The result interval for division (or exponentiation by a
+@strong{128}. The result interval for division (or exponentiation by a
negative exponent), when the floating point hardware implements division
as multiplication by a reciprocal. See G.2.1(16).
@end cartouche
@@ -12876,7 +13134,7 @@ Not relevant, division is IEEE exact.
@sp 1
@cartouche
@noindent
-@strong{128}. The definition of close result set, which determines the
+@strong{129}. The definition of close result set, which determines the
accuracy of certain fixed point multiplications and divisions. See
G.2.3(5).
@end cartouche
@@ -12889,7 +13147,7 @@ is converted to the target type.
@sp 1
@cartouche
@noindent
-@strong{129}. Conditions on a @code{universal_real} operand of a fixed
+@strong{130}. Conditions on a @code{universal_real} operand of a fixed
point multiplication or division for which the result shall be in the
perfect result set. See G.2.3(22).
@end cartouche
@@ -12901,7 +13159,7 @@ representable in 64-bits.
@sp 1
@cartouche
@noindent
-@strong{130}. The result of a fixed point arithmetic operation in
+@strong{131}. The result of a fixed point arithmetic operation in
overflow situations, when the @code{Machine_Overflows} attribute of the
result type is @code{False}. See G.2.3(27).
@end cartouche
@@ -12912,7 +13170,7 @@ types.
@sp 1
@cartouche
@noindent
-@strong{131}. The result of an elementary function reference in
+@strong{132}. The result of an elementary function reference in
overflow situations, when the @code{Machine_Overflows} attribute of the
result type is @code{False}. See G.2.4(4).
@end cartouche
@@ -12922,7 +13180,7 @@ IEEE infinite and Nan values are produced as appropriate.
@sp 1
@cartouche
@noindent
-@strong{132}. The value of the angle threshold, within which certain
+@strong{133}. The value of the angle threshold, within which certain
elementary functions, complex arithmetic operations, and complex
elementary functions yield results conforming to a maximum relative
error bound. See G.2.4(10).
@@ -12933,7 +13191,7 @@ Information on this subject is not yet available.
@sp 1
@cartouche
@noindent
-@strong{133}. The accuracy of certain elementary functions for
+@strong{134}. The accuracy of certain elementary functions for
parameters beyond the angle threshold. See G.2.4(10).
@end cartouche
@noindent
@@ -12942,7 +13200,7 @@ Information on this subject is not yet available.
@sp 1
@cartouche
@noindent
-@strong{134}. The result of a complex arithmetic operation or complex
+@strong{135}. The result of a complex arithmetic operation or complex
elementary function reference in overflow situations, when the
@code{Machine_Overflows} attribute of the corresponding real type is
@code{False}. See G.2.6(5).
@@ -12953,7 +13211,7 @@ IEEE infinite and Nan values are produced as appropriate.
@sp 1
@cartouche
@noindent
-@strong{135}. The accuracy of certain complex arithmetic operations and
+@strong{136}. The accuracy of certain complex arithmetic operations and
certain complex elementary functions for parameters (or components
thereof) beyond the angle threshold. See G.2.6(8).
@end cartouche
@@ -12963,7 +13221,7 @@ Information on those subjects is not yet available.
@sp 1
@cartouche
@noindent
-@strong{136}. Information regarding bounded errors and erroneous
+@strong{137}. Information regarding bounded errors and erroneous
execution. See H.2(1).
@end cartouche
@noindent
@@ -12972,7 +13230,7 @@ Information on this subject is not yet available.
@sp 1
@cartouche
@noindent
-@strong{137}. Implementation-defined aspects of pragma
+@strong{138}. Implementation-defined aspects of pragma
@code{Inspection_Point}. See H.3.2(8).
@end cartouche
@noindent
@@ -12982,7 +13240,7 @@ be examined by the debugger at the inspection point.
@sp 1
@cartouche
@noindent
-@strong{138}. Implementation-defined aspects of pragma
+@strong{139}. Implementation-defined aspects of pragma
@code{Restrictions}. See H.4(25).
@end cartouche
@noindent
@@ -12993,7 +13251,7 @@ generated code. Checks must suppressed by use of pragma @code{Suppress}.
@sp 1
@cartouche
@noindent
-@strong{139}. Any restrictions on pragma @code{Restrictions}. See
+@strong{140}. Any restrictions on pragma @code{Restrictions}. See
H.4(27).
@end cartouche
@noindent
@@ -16991,9 +17249,11 @@ is specifically authorized by the Ada Reference Manual
@cindex Formal container for doubly linked lists
@noindent
-This child of @code{Ada.Containers} defines a modified version of the Ada 2005
-container for doubly linked lists, meant to facilitate formal verification of
-code using such containers.
+This child of @code{Ada.Containers} defines a modified version of the
+Ada 2005 container for doubly linked lists, meant to facilitate formal
+verification of code using such containers. The specification of this
+unit is compatible with SPARK 2014. Note that the API of this unit may
+be subject to incompatible changes as SPARK 2014 evolves.
@node Ada.Containers.Formal_Hashed_Maps (a-cfhama.ads)
@section @code{Ada.Containers.Formal_Hashed_Maps} (@file{a-cfhama.ads})
@@ -17001,9 +17261,11 @@ code using such containers.
@cindex Formal container for hashed maps
@noindent
-This child of @code{Ada.Containers} defines a modified version of the Ada 2005
-container for hashed maps, meant to facilitate formal verification of
-code using such containers.
+This child of @code{Ada.Containers} defines a modified version of the
+Ada 2005 container for hashed maps, meant to facilitate formal
+verification of code using such containers. The specification of this
+unit is compatible with SPARK 2014. Note that the API of this unit may
+be subject to incompatible changes as SPARK 2014 evolves.
@node Ada.Containers.Formal_Hashed_Sets (a-cfhase.ads)
@section @code{Ada.Containers.Formal_Hashed_Sets} (@file{a-cfhase.ads})
@@ -17011,9 +17273,11 @@ code using such containers.
@cindex Formal container for hashed sets
@noindent
-This child of @code{Ada.Containers} defines a modified version of the Ada 2005
-container for hashed sets, meant to facilitate formal verification of
-code using such containers.
+This child of @code{Ada.Containers} defines a modified version of the
+Ada 2005 container for hashed sets, meant to facilitate formal
+verification of code using such containers. The specification of this
+unit is compatible with SPARK 2014. Note that the API of this unit may
+be subject to incompatible changes as SPARK 2014 evolves.
@node Ada.Containers.Formal_Ordered_Maps (a-cforma.ads)
@section @code{Ada.Containers.Formal_Ordered_Maps} (@file{a-cforma.ads})
@@ -17021,9 +17285,11 @@ code using such containers.
@cindex Formal container for ordered maps
@noindent
-This child of @code{Ada.Containers} defines a modified version of the Ada 2005
-container for ordered maps, meant to facilitate formal verification of
-code using such containers.
+This child of @code{Ada.Containers} defines a modified version of the
+Ada 2005 container for ordered maps, meant to facilitate formal
+verification of code using such containers. The specification of this
+unit is compatible with SPARK 2014. Note that the API of this unit may
+be subject to incompatible changes as SPARK 2014 evolves.
@node Ada.Containers.Formal_Ordered_Sets (a-cforse.ads)
@section @code{Ada.Containers.Formal_Ordered_Sets} (@file{a-cforse.ads})
@@ -17031,9 +17297,11 @@ code using such containers.
@cindex Formal container for ordered sets
@noindent
-This child of @code{Ada.Containers} defines a modified version of the Ada 2005
-container for ordered sets, meant to facilitate formal verification of
-code using such containers.
+This child of @code{Ada.Containers} defines a modified version of the
+Ada 2005 container for ordered sets, meant to facilitate formal
+verification of code using such containers. The specification of this
+unit is compatible with SPARK 2014. Note that the API of this unit may
+be subject to incompatible changes as SPARK 2014 evolves.
@node Ada.Containers.Formal_Vectors (a-cofove.ads)
@section @code{Ada.Containers.Formal_Vectors} (@file{a-cofove.ads})
@@ -17041,9 +17309,11 @@ code using such containers.
@cindex Formal container for vectors
@noindent
-This child of @code{Ada.Containers} defines a modified version of the Ada 2005
-container for vectors, meant to facilitate formal verification of
-code using such containers.
+This child of @code{Ada.Containers} defines a modified version of the
+Ada 2005 container for vectors, meant to facilitate formal
+verification of code using such containers. The specification of this
+unit is compatible with SPARK 2014. Note that the API of this unit may
+be subject to incompatible changes as SPARK 2014 evolves.
@node Ada.Command_Line.Environment (a-colien.ads)
@section @code{Ada.Command_Line.Environment} (@file{a-colien.ads})
@@ -18611,6 +18881,19 @@ occurrence has no message, and the simple name of the exception identity
contains @samp{Foreign_Exception}. Finalization and awaiting dependent
tasks works properly when such foreign exceptions are propagated.
+It is also possible to import a C++ exception using the following syntax:
+
+@smallexample @c ada
+LOCAL_NAME : exception;
+pragma Import (Cpp,
+ [Entity =>] LOCAL_NAME,
+ [External_Name =>] static_string_EXPRESSION);
+@end smallexample
+
+@noindent
+The @code{External_Name} is the name of the C++ RTTI symbol. You can then
+cover a specific C++ exception in an exception handler.
+
@node Interfacing to COBOL
@section Interfacing to COBOL
diff --git a/gcc/ada/gnat_ugn.texi b/gcc/ada/gnat_ugn.texi
index 40ffc35dacd..edb3886a03a 100644
--- a/gcc/ada/gnat_ugn.texi
+++ b/gcc/ada/gnat_ugn.texi
@@ -179,6 +179,9 @@ AdaCore@*
* Tools Supporting Project Files::
* The Cross-Referencing Tools gnatxref and gnatfind::
* The GNAT Pretty-Printer gnatpp::
+@ifclear vms
+* The Ada-to-XML converter gnat2xml::
+@end ifclear
* The GNAT Metrics Tool gnatmetric::
* File Name Krunching with gnatkr::
* Preprocessing with gnatprep::
@@ -241,7 +244,7 @@ By default, @value{EDITION} assumes Ada 2012, but you can override with a
compiler switch (@pxref{Compiling Different Versions of Ada})
to explicitly specify the language version.
Throughout this manual, references to ``Ada'' without a year suffix
-apply to both all Ada 95/2005/2012 versions of the language.
+apply to all Ada 95/2005/2012 versions of the language.
@ifclear FSFEDITION
For ease of exposition, ``@value{EDITION}'' will be referred to simply as
@@ -328,6 +331,12 @@ way to navigate through sources.
version of an Ada source file with control over casing, indentation,
comment placement, and other elements of program presentation style.
+@ifclear vms
+@item
+@ref{The Ada-to-XML converter gnat2xml}, shows how to convert Ada
+source code into XML.
+@end ifclear
+
@item
@ref{The GNAT Metrics Tool gnatmetric}, shows how to compute various
metrics for an Ada source file, such as the number of types and subprograms,
@@ -3816,9 +3825,120 @@ temporary use of special test software.
@cindex @option{-gnateS} (@command{gcc})
Synonym of @option{-fdump-scos}, kept for backards compatibility.
-@item ^-gnatet^/TARGET_DEPENDENT_INFO^
-@cindex @option{-gnatet} (@command{gcc})
-Generate target dependent information.
+@item -gnatet=@var{path}
+@cindex @option{-gnatet=file} (@command{gcc})
+Generate target dependent information. The format of the output file is
+described in the section about switch @option{-gnateT}.
+
+@item -gnateT=@var{path}
+@cindex @option{-gnateT} (@command{gcc})
+Read target dependent information, such as endianness or sizes and alignments
+of base type. If this switch is passed, the default target dependent
+information of the compiler is replaced by the one read from the input file.
+This is used by tools other than the compiler, e.g. to do
+semantic analysis of programs that will run on some other target than
+the machine on which the tool is run.
+
+The following target dependent values should be defined,
+where @code{Nat} denotes a natural integer value, @code{Pos} denotes a
+positive integer value, and fields marked with a question mark are
+boolean fields, where a value of 0 is False, and a value of 1 is True:
+
+@smallexample
+Bits_BE : Nat; -- Bits stored big-endian?
+Bits_Per_Unit : Pos; -- Bits in a storage unit
+Bits_Per_Word : Pos; -- Bits in a word
+Bytes_BE : Nat; -- Bytes stored big-endian?
+Char_Size : Pos; -- Standard.Character'Size
+Double_Float_Alignment : Nat; -- Alignment of double float
+Double_Scalar_Alignment : Nat; -- Alignment of double length scalar
+Double_Size : Pos; -- Standard.Long_Float'Size
+Float_Size : Pos; -- Standard.Float'Size
+Float_Words_BE : Nat; -- Float words stored big-endian?
+Int_Size : Pos; -- Standard.Integer'Size
+Long_Double_Size : Pos; -- Standard.Long_Long_Float'Size
+Long_Long_Size : Pos; -- Standard.Long_Long_Integer'Size
+Long_Size : Pos; -- Standard.Long_Integer'Size
+Maximum_Alignment : Pos; -- Maximum permitted alignment
+Max_Unaligned_Field : Pos; -- Maximum size for unaligned bit field
+Pointer_Size : Pos; -- System.Address'Size
+Short_Size : Pos; -- Standard.Short_Integer'Size
+Strict_Alignment : Nat; -- Strict alignment?
+System_Allocator_Alignment : Nat; -- Alignment for malloc calls
+Wchar_T_Size : Pos; -- Interfaces.C.wchar_t'Size
+Words_BE : Nat; -- Words stored big-endian?
+@end smallexample
+
+The format of the input file is as follows. First come the values of
+the variables defined above, with one line per value:
+
+@smallexample
+name value
+@end smallexample
+
+where @code{name} is the name of the parameter, spelled out in full,
+and cased as in the above list, and @code{value} is an unsigned decimal
+integer. Two or more blanks separates the name from the value.
+
+All the variables must be present, in alphabetical order (i.e. the
+same order as the list above).
+
+Then there is a blank line to separate the two parts of the file. Then
+come the lines showing the floating-point types to be registered, with
+one line per registered mode:
+
+@smallexample
+name digs float_rep size alignment
+@end smallexample
+
+where @code{name} is the string name of the type (which can have
+single spaces embedded in the name (e.g. long double), @code{digs} is
+the number of digits for the floating-point type, @code{float_rep} is
+the float representation (I/V/A for IEEE-754-Binary, Vax_Native,
+AAMP), @code{size} is the size in bits, @code{alignment} is the
+alignment in bits. The name is followed by at least two blanks, fields
+are separated by at least one blank, and a LF character immediately
+follows the alignment field.
+
+Here is an example of target parametrization file:
+
+@smallexample
+Bits_BE 0
+Bits_Per_Unit 8
+Bits_Per_Word 64
+Bytes_BE 0
+Char_Size 8
+Double_Float_Alignment 0
+Double_Scalar_Alignment 0
+Double_Size 64
+Float_Size 32
+Float_Words_BE 0
+Int_Size 64
+Long_Double_Size 128
+Long_Long_Size 64
+Long_Size 64
+Maximum_Alignment 16
+Max_Unaligned_Field 64
+Pointer_Size 64
+Short_Size 16
+Strict_Alignment 0
+System_Allocator_Alignment 16
+Wchar_T_Size 32
+Words_BE 0
+
+float 15 I 64 64
+double 15 I 64 64
+long double 18 I 80 128
+TF 33 I 128 128
+@end smallexample
+
+@item -gnateu
+@cindex @option{-gnateu} (@command{gcc})
+Ignore unrecognized validity, warning, and style switches that
+appear after this switch is given. This may be useful when
+compiling sources developed on a later version of the compiler
+with an earlier version. Of course the earlier version must
+support this switch.
@item ^-gnateV^/PARAMETER_VALIDITY_CHECK^
@cindex @option{-gnateV} (@command{gcc})
@@ -4773,9 +4893,7 @@ individually controlled. The warnings that are not turned on by this
switch are
@option{-gnatwd} (implicit dereferencing),
@option{-gnatwh} (hiding),
-@ifclear vms
@option{-gnatw.d} (tag warnings with -gnatw switch)
-@end ifclear
@option{-gnatw.h} (holes (gaps) in record layouts)
@option{-gnatw.i} (overlapping actuals),
@option{-gnatw.k} (redefinition of names in standard),
@@ -4924,7 +5042,6 @@ this warning option.
This switch suppresses warnings for implicit dereferences in
indexed components, slices, and selected components.
-@ifclear vms
@item -gnatw.d
@emph{Activate tagging of warning messages.}
@cindex @option{-gnatw.d} (@command{gcc})
@@ -4940,7 +5057,6 @@ affected by the use of @code{-gnatwa}.
If this switch is set, then warning messages return to the default
mode in which warnings are not tagged as described above for
@code{-gnatw.d}.
-@end ifclear
@item -gnatwe
@emph{Treat warnings and style checks as errors.}
@@ -5622,6 +5738,25 @@ This warning can also be turned on using @option{-gnatwa}.
This switch suppresses the warnings intended to help in identifying
incompatibilities between Ada language versions.
+@item -gnatw.y
+@emph{Activate information messages for why package spec needs body}
+@cindex @option{-gnatw.y} (@command{gcc})
+@cindex Package spec needing body
+There are a number of cases in which a package spec needs a body.
+For example, the use of pragma Elaborate_Body, or the declaration
+of a procedure specification requiring a completion. This switch
+causes information messages to be output showing why a package
+specification requires a body. This can be useful in the case of
+a large package specification which is unexpectedly requiring a
+body. The default is that such information messages are not output.
+
+@item -gnatw.Y
+@emph{Disable information messages for why package spec needs body}
+@cindex @option{-gnatw.Y} (@command{gcc})
+@cindex No information messages for why package spec needs body
+This switch suppresses the output of information messages showing why
+a package specification needs a body.
+
@item -gnatwz
@emph{Activate warnings on unchecked conversions.}
@cindex @option{-gnatwz} (@command{gcc})
@@ -7589,11 +7724,23 @@ Examples of valid lines in a preprocessor data file:
Define or redefine a preprocessing symbol, associated with value. If no value
is given on the command line, then the value of the symbol is @code{True}.
A symbol is an identifier, following normal Ada (case-insensitive)
-rules for its syntax, and value is any sequence (including an empty sequence)
-of characters from the set (letters, digits, period, underline).
+rules for its syntax, and value is either an arbitrary string between double
+quotes or any sequence (including an empty sequence) of characters from the
+set (letters, digits, period, underline).
Ada reserved words may be used as symbols, with the exceptions of @code{if},
@code{else}, @code{elsif}, @code{end}, @code{and}, @code{or} and @code{then}.
+@ifclear vms
+@noindent
+Examples:
+
+@smallexample
+ -gnateDToto=Titi
+ -gnateDFoo
+ -gnateDFoo=\"Foo-Bar\"
+@end smallexample
+@end ifclear
+
@noindent
A symbol declared with this ^switch^switch^ on the command line replaces a
symbol with the same name either in a definition file or specified with a
@@ -9999,6 +10146,7 @@ some guidelines on debugging optimized code.
* Vectorization of loops::
* Other Optimization Switches::
* Optimization and Strict Aliasing::
+* Aliased Variables and Optimization::
@ifset vms
* Coverage Analysis::
@@ -10548,11 +10696,6 @@ preferably to other optimizations by means of pragma @code{Loop_Optimize}:
placed immediately within the loop will convey the appropriate hint to the
compiler for this loop.
-You can obtain information about the vectorization performed by the compiler
-by specifying @option{-ftree-vectorizer-verbose=N}. For more details of
-this switch, see @ref{Debugging Options,,Options for Debugging Your Program
-or GCC, gcc, Using the GNU Compiler Collection (GCC)}.
-
@node Other Optimization Switches
@subsection Other Optimization Switches
@cindex Optimization Switches
@@ -10797,6 +10940,58 @@ has on size and speed of the code. If you really need to use
review any uses of unchecked conversion of access types,
particularly if you are getting the warnings described above.
+@node Aliased Variables and Optimization
+@subsection Aliased Variables and Optimization
+@cindex Aliasing
+There are scenarios in which programs may
+use low level techniques to modify variables
+that otherwise might be considered to be unassigned. For example,
+a variable can be passed to a procedure by reference, which takes
+the address of the parameter and uses the address to modify the
+variable's value, even though it is passed as an IN parameter.
+Consider the following example:
+
+@smallexample @c ada
+procedure P is
+ Max_Length : constant Natural := 16;
+ type Char_Ptr is access all Character;
+
+ procedure Get_String(Buffer: Char_Ptr; Size : Integer);
+ pragma Import (C, Get_String, "get_string");
+
+ Name : aliased String (1 .. Max_Length) := (others => ' ');
+ Temp : Char_Ptr;
+
+ function Addr (S : String) return Char_Ptr is
+ function To_Char_Ptr is
+ new Ada.Unchecked_Conversion (System.Address, Char_Ptr);
+ begin
+ return To_Char_Ptr (S (S'First)'Address);
+ end;
+
+begin
+ Temp := Addr (Name);
+ Get_String (Temp, Max_Length);
+end;
+@end smallexample
+
+@noindent
+where Get_String is a C function that uses the address in Temp to
+modify the variable @code{Name}. This code is dubious, and arguably
+erroneous, and the compiler would be entitled to assume that
+@code{Name} is never modified, and generate code accordingly.
+
+However, in practice, this would cause some existing code that
+seems to work with no optimization to start failing at high
+levels of optimzization.
+
+What the compiler does for such cases is to assume that marking
+a variable as aliased indicates that some "funny business" may
+be going on. The optimizer recognizes the aliased keyword and
+inhibits optimizations that assume the value cannot be assigned.
+This means that the above example will in fact "work" reliably,
+that is, it will produce the expected results.
+
@ifset vms
@node Coverage Analysis
@subsection Coverage Analysis
@@ -13622,6 +13817,14 @@ version as output.
You can specify various style directives via switches; e.g.,
identifier case conventions, rules of indentation, and comment layout.
+Note: A newly-redesigned set of formatting algorithms used by gnatpp
+is now available.
+To invoke the new experimental formatting algorithms, use the
+@option{--pp-new} switch.
+The default is @option{--pp-old}; that is, gnatpp uses the old
+formatting algorithms by default.
+We intend to make @option{--pp-new} the default at some point.
+
To produce a reformatted file, @command{gnatpp} generates and uses the ASIS
tree for the input source and thus requires the input to be syntactically and
semantically legal.
@@ -14230,6 +14433,14 @@ Display Copyright and version, then exit disregarding all other options.
@cindex @option{--help} @command{gnatpp}
Display usage, then exit disregarding all other options.
+@item --pp-new
+@cindex @option{--pp-new} @command{gnatpp}
+Use the new experimental formatting algorithms.
+
+@item --pp-old
+@cindex @option{--pp-old} @command{gnatpp}
+Use the old formatting algorithms. This is the default.
+
@item ^-files @var{filename}^/FILES=@var{filename}^
@cindex @option{^-files^/FILES^} (@code{gnatpp})
Take the argument source files from the specified file. This file should be an
@@ -14786,6 +14997,468 @@ end Test;
@end cartouche
@end smallexample
+@ifclear vms
+@c *********************************
+@node The Ada-to-XML converter gnat2xml
+@chapter The Ada-to-XML converter @command{gnat2xml}
+@findex gnat2xml
+@cindex XML generation
+
+@noindent
+The @command{gnat2xml} tool is an ASIS-based utility that converts
+Ada source code into XML.
+
+@menu
+* Switches for gnat2xml::
+* Driving gnat2xml with gnatmake or gprbuild::
+* Other Programs::
+* Structure of the XML::
+@end menu
+
+@node Switches for gnat2xml
+@section Switches for @command{gnat2xml}
+
+@noindent
+@command{gnat2xml} takes Ada source code as input, and produces XML
+that conforms to the schema.
+
+Usage:
+
+@smallexample
+gnat2xml [options] files
+@end smallexample
+
+``files'' are the Ada source file names.
+
+@noindent
+Options:
+@smallexample
+-h
+--help -- generate usage information and quit, ignoring all other options
+
+-mdir -- generate one .xml file for each Ada source file, in directory
+ @file{dir}. (Default is to generate the XML to standard output.)
+
+-q -- debugging version, with interspersed source, and a more
+ compact representation of "sloc". This version does not conform
+ to any schema.
+
+-I <include-dir>
+ directories to search for dependencies
+ You can also set the ADA_INCLUDE_PATH environment variable for this.
+
+-v -- verbose (print out the command line options, and the names of
+ output files as they are generated).
+
+-t -- do not delete tree files when done (they are deleted by default).
+
+-cargs ... -- options to pass to gcc
+@end smallexample
+
+@noindent
+You can generate the ``tree files'' ahead of time using the -gnatct switch:
+
+@smallexample
+gnatmake -gnat2012 -gnatct *.ad[sb]
+@end smallexample
+
+@noindent
+If tree files do not exist, @command{gnat2xml} will create them by running gcc.
+See the ASIS documentation for more information on tree files.
+
+Example:
+
+@smallexample
+mkdir xml-files
+gnat2xml -v -mxml-files *.ad[sb] -cargs -gnat2012
+@end smallexample
+
+@noindent
+The above will create *.xml files in the @file{xml-files} subdirectory.
+For example, if there is an Ada package Mumble.Dumble, whose spec and
+body source code lives in mumble-dumble.ads and mumble-dumble.adb,
+the above will produce xml-files/mumble-dumble.ads.xml and
+xml-files/mumble-dumble.adb.xml.
+
+@node Driving gnat2xml with gnatmake or gprbuild
+@section Driving @command{gnat2xml} with @command{gnatmake} or @command{gprbuild}
+
+@noindent
+You can use gnatmake or gprbuild to drive @command{gnat2xml} to get
+incremental updates of the XML files on a per-source-file basis. For
+example, if you already have a bunch of XML files, and then you change
+one source file, it will regenerate XML files only for that source
+file, and other source files that depend on it. Gnatmake and gprbuild
+take care of tracking inter-file dependencies. For example, if
+this.adb says @code{with That;}, then this.adb depends on that.ads.
+
+To do this, you tell gnatmake/gprbuild to pretend that
+@command{gnat2xml} is the Ada compiler (instead of using gcc as the
+Ada compiler, as is normal).
+
+To tell gnatmake to use @command{gnat2xml} instead of gcc as the
+``compiler'', for example:
+
+@smallexample
+gnatmake -gnatc *.adb --GCC="gnat2xml -t -mxml"
+@end smallexample
+
+@noindent
+The @option{--GCC=} switch tells gnatmake that the ``compiler'' to run
+is @command{gnat2xml -t -mxml}. The @option{-t} switch means to keep the tree
+files, so they can be reused on the next run. (@command{gnat2xml}
+deletes them by default.) As usual, @option{-mxml} means to put the
+XML files in the @file{xml} subdirectory.
+
+You must give the @option{-gnatc} switch to gnatmake, which means
+``compile only; do not generate object code''. Otherwise, gnatmake will
+complain about missing object (*.o) files; @command{gnat2xml} of
+course does not generate *.o files.
+
+Using gprbuild is similar: you tell it to use @command{gnat2xml}
+instead of gcc. First write a project file, such as my_project.gpr:
+
+@smallexample @c projectfile
+project My_Project is
+
+ package Compiler is
+ for Driver ("ada") use "gnat2xml";
+ -- Use gnat2xml instead of the usual gcc.
+
+ for Default_Switches ("ada") use ("-t", "-mxml");
+ -- Same switches as in the gnatmake case.
+ end Compiler;
+
+end My_Project;
+@end smallexample
+
+@noindent
+Then:
+
+@smallexample @c projectfile
+gprbuild --no-object-check -P my_project.gpr
+@end smallexample
+
+@noindent
+The @option{--no-object-check} switch serves the same purpose as
+@option{-gnatc} in the gnatmake case --- it tells gprbuild not to
+expect that the ``compiler'' (really @command{gnat2xml}) will produce
+*.o files.
+
+See the gprbuild documentation for information on many other things
+you can put in the project file, such as telling it where to find
+the source files.
+
+@node Other Programs
+@section Other Programs
+
+@noindent
+The distribution includes two other programs that are related to
+@command{gnat2xml}:
+
+@command{gnat2xsd} is the schema generator, which generates the schema
+to standard output, based on the structure of Ada as encoded by
+ASIS. You don't need to run @command{gnat2xsd} in order to use
+@command{gnat2xml}. To generate the schema, type:
+
+@smallexample
+gnat2xsd > ada-schema.xsd
+@end smallexample
+
+@noindent
+@command{gnat2xml} generates XML files that will validate against
+@file{ada-schema.xsd}.
+
+@command{xml2gnat} is a back-translator that translates the XML back
+into Ada source code. The Ada generated by @command{xml2gnat} has
+identical semantics to the original Ada code passed to
+@command{gnat2xml}. It is not textually identical, however --- for
+example, no attempt is made to preserve the original indentation.
+
+@node Structure of the XML
+@section Structure of the XML
+
+@noindent
+The primary documentation for the structure of the XML generated by
+@command{gnat2xml} is the schema (see @command{gnat2xsd} above). The
+following documentation gives additional details needed to understand
+the schema and therefore the XML.
+
+The elements listed under Defining Occurrences, Usage Occurrences, and
+Other Elements represent the syntactic structure of the Ada program.
+Element names are given in lower case, with the corresponding element
+type Capitalized_Like_This. The element and element type names are
+derived directly from the ASIS enumeration type Flat_Element_Kinds,
+declared in Asis.Extensions.Flat_Kinds, with the leading ``An_'' or ``A_''
+removed. For example, the ASIS enumeration literal
+An_Assignment_Statement corresponds to the XML element
+assignment_statement of XML type Assignment_Statement.
+
+To understand the details of the schema and the corresponding XML, it is
+necessary to understand the ASIS standard, as well as the GNAT-specific
+extension to ASIS.
+
+A defining occurrence is an identifier (or character literal or operator
+symbol) declared by a declaration. A usage occurrence is an identifier
+(or ...) that references such a declared entity. For example, in:
+
+@smallexample
+type T is range 1..10;
+X, Y : constant T := 1;
+@end smallexample
+
+@noindent
+The first ``T'' is the defining occurrence of a type. The ``X'' is the
+defining occurrence of a constant, as is the ``Y'', and the second ``T'' is
+a usage occurrence referring to the defining occurrence of T.
+
+Each element has a 'sloc' (source location), and subelements for each
+syntactic subtree, reflecting the Ada grammar as implemented by ASIS.
+The types of subelements are as defined in the ASIS standard. For
+example, for the right-hand side of an assignment_statement we have
+the following comment in asis-statements.ads:
+
+@smallexample
+------------------------------------------------------------------------------
+-- 18.3 function Assignment_Expression
+------------------------------------------------------------------------------
+
+ function Assignment_Expression
+ (Statement : Asis.Statement)
+ return Asis.Expression;
+
+------------------------------------------------------------------------------
+...
+-- Returns the expression from the right hand side of the assignment.
+...
+-- Returns Element_Kinds:
+-- An_Expression
+@end smallexample
+
+@noindent
+The corresponding sub-element of type Assignment_Statement is:
+
+@smallexample
+<xsd:element name="assignment_expression_q" type="Expression_Class"/>
+@end smallexample
+
+@noindent
+where Expression_Class is defined by an xsd:choice of all the
+various kinds of expression.
+
+The 'sloc' of each element indicates the starting and ending line and
+column numbers. Column numbers are character counts; that is, a tab
+counts as 1, not as however many spaces it might expand to.
+
+Subelements of type Element have names ending in ``_q'' (for ASIS
+``Query''), and those of type Element_List end in ``_ql'' (``Query returning
+List'').
+
+Some subelements are ``Boolean''. For example, Private_Type_Definition
+has has_abstract_q and has_limited_q, to indicate whether those
+keywords are present, as in @code{type T is abstract limited
+private;}. False is represented by a Nil_Element. True is represented
+by an element type specific to that query (for example, Abstract and
+Limited).
+
+The root of the tree is a Compilation_Unit, with attributes:
+
+@itemize @bullet
+@item
+unit_kind, unit_class, and unit_origin. These are strings that match the
+enumeration literals of types Unit_Kinds, Unit_Classes, and Unit_Origins
+in package Asis.
+
+@item
+unit_full_name is the full expanded name of the unit, starting from a
+root library unit. So for @code{package P.Q.R is ...},
+@code{unit_full_name="P.Q.R"}. Same for @code{separate (P.Q) package R is ...}.
+
+@item
+def_name is the same as unit_full_name for library units; for subunits,
+it is just the simple name.
+
+@item
+source_file is the name of the Ada source file. For example, for
+the spec of @code{P.Q.R}, @code{source_file="p-q-r.ads"}. This allows one to
+interpret the source locations --- the ``sloc'' of all elements
+within this Compilation_Unit refers to line and column numbers
+within the named file.
+@end itemize
+
+@noindent
+Defining occurrences have these attributes:
+
+@itemize @bullet
+@item
+def_name is the simple name of the declared entity, as written in the Ada
+source code.
+
+@item
+def is a unique URI of the form:
+
+ ada://kind/fully/qualified/name
+
+where:
+
+ kind indicates the kind of Ada entity being declared (see below), and
+
+ fully/qualified/name, is the fully qualified name of the Ada
+ entity, with each of ``fully'', ``qualified'', and ``name'' being
+ mangled for uniqueness. We do not document the mangling
+ algorithm, which is subject to change; we just guarantee that the
+ names are unique in the face of overloading.
+
+@item
+type is the type of the declared object, or @code{null} for
+declarations of things other than objects.
+@end itemize
+
+@noindent
+Usage occurrences have these attributes:
+
+@itemize @bullet
+@item
+ref_name is the same as the def_name of the corresponding defining
+occurrence. This attribute is not of much use, because of
+overloading; use ref for lookups, instead.
+
+@item
+ref is the same as the def of the corresponding defining
+occurrence.
+@end itemize
+
+@noindent
+In summary, @code{def_name} and @code{ref_name} are as in the source
+code of the declaration, possibly overloaded, whereas @code{def} and
+@code{ref} are unique-ified.
+
+Literal elements have this attribute:
+
+@itemize @bullet
+@item
+lit_val is the value of the literal as written in the source text,
+appropriately escaped (e.g. @code{"} ---> @code{&quot;}). This applies
+only to numeric and string literals. Enumeration literals in Ada are
+not really "literals" in the usual sense; they are usage occurrences,
+and have ref_name and ref as described above. Note also that string
+literals used as operator symbols are treated as defining or usage
+occurrences, not as literals.
+@end itemize
+
+@noindent
+Elements that can syntactically represent names and expressions (which
+includes usage occurrences, plus function calls and so forth) have this
+attribute:
+
+@itemize @bullet
+@item
+type. If the element represents an expression or the name of an object,
+'type' is the 'def' for the defining occurrence of the type of that
+expression or name. Names of other kinds of entities, such as package
+names and type names, do not have a type in Ada; these have type="null"
+in the XML.
+@end itemize
+
+@noindent
+Pragma elements have this attribute:
+
+@itemize @bullet
+@item
+pragma_name is the name of the pragma. For language-defined pragmas, the
+pragma name is redundant with the element kind (for example, an
+assert_pragma element necessarily has pragma_name="Assert"). However, all
+implementation-defined pragmas are lumped together in ASIS as a single
+element kind (for example, the GNAT-specific pragma Unreferenced is
+represented by an implementation_defined_pragma element with
+pragma_name="Unreferenced").
+@end itemize
+
+@noindent
+Defining occurrences of formal parameters and generic formal objects have this
+attribute:
+
+@itemize @bullet
+@item
+mode indicates that the parameter is of mode 'in', 'in out', or 'out'.
+@end itemize
+
+@noindent
+The "kind" part of the "def" and "ref" attributes is taken from the ASIS
+enumeration type Flat_Declaration_Kinds, declared in
+Asis.Extensions.Flat_Kinds, with the leading "An_" or "A_" removed, and
+any trailing "_Declaration" or "_Specification" removed. Thus, the
+possible kinds are as follows:
+
+@smallexample
+ordinary_type
+task_type
+protected_type
+incomplete_type
+tagged_incomplete_type
+private_type
+private_extension
+subtype
+variable
+constant
+deferred_constant
+single_task
+single_protected
+integer_number
+real_number
+enumeration_literal
+discriminant
+component
+loop_parameter
+generalized_iterator
+element_iterator
+procedure
+function
+parameter
+procedure_body
+function_body
+return_variable
+return_constant
+null_procedure
+expression_function
+package
+package_body
+object_renaming
+exception_renaming
+package_renaming
+procedure_renaming
+function_renaming
+generic_package_renaming
+generic_procedure_renaming
+generic_function_renaming
+task_body
+protected_body
+entry
+entry_body
+entry_index
+procedure_body_stub
+function_body_stub
+package_body_stub
+task_body_stub
+protected_body_stub
+exception
+choice_parameter
+generic_procedure
+generic_function
+generic_package
+package_instantiation
+procedure_instantiation
+function_instantiation
+formal_object
+formal_type
+formal_incomplete_type
+formal_procedure
+formal_function
+formal_package
+formal_package_declaration_with_box
+@end smallexample
+@end ifclear
+
@c *********************************
@node The GNAT Metrics Tool gnatmetric
@chapter The GNAT Metrics Tool @command{gnatmetric}
@@ -16154,6 +16827,11 @@ In this example, @i{expression} is defined by the following grammar:
@i{expression} ::= <symbol>
@i{expression} ::= <symbol> = "<value>"
@i{expression} ::= <symbol> = <symbol>
+@i{expression} ::= <symbol> = <integer>
+@i{expression} ::= <symbol> > <integer>
+@i{expression} ::= <symbol> >= <integer>
+@i{expression} ::= <symbol> < <integer>
+@i{expression} ::= <symbol> <= <integer>
@i{expression} ::= <symbol> 'Defined
@i{expression} ::= not @i{expression}
@i{expression} ::= @i{expression} and @i{expression}
@@ -16186,6 +16864,11 @@ symbol definition must be one of the (case-insensitive) literals
corresponding lines are included, and if the value is false, they are
excluded.
+When comparing a symbol to an integer, the integer is any non negative
+literal integer as defined in the Ada Reference Manual, such as 3, 16#FF# or
+2#11#. The symbol value must also be a non negative integer. Integer values
+in the range 0 .. 2**31-1 are supported.
+
The test (@i{expression} ::= <symbol> @code{'Defined}) is true only if
the symbol has been defined in the definition file or by a @option{-D}
switch on the command line. Otherwise, the test is false.
@@ -18565,8 +19248,8 @@ by @command{gnatstub} to compile an argument source file.
@item ^-gnatyM^/MAX_LINE_LENGTH=^@var{n}
@cindex @option{^-gnatyM^/MAX_LINE_LENGTH^} (@command{gnatstub})
-(@var{n} is a non-negative integer). Set the maximum line length in the
-body stub to @var{n}; the default is 79. The maximum value that can be
+(@var{n} is a non-negative integer). Set the maximum line length that is
+allowed in a source file. The default is 79. The maximum value that can be
specified is 32767. Note that in the special case of configuration
pragma files, the maximum is always 32767 regardless of whether or
not this switch appears.
@@ -21267,7 +21950,7 @@ end STB;
@end smallexample
@smallexample
-$ gnatmake -g .\stb -bargs -E -largs -lgnat -laddr2line -lintl
+$ gnatmake -g .\stb -bargs -E
$ stb
0040149F in stb.p1 at stb.adb:8
@@ -26919,7 +27602,7 @@ The preprocessing language allows such constructs as
@smallexample
@group
-#if DEBUG or PRIORITY > 4 then
+#if DEBUG or else (PRIORITY > 4) then
bunch of declarations
#else
completely different bunch of declarations
diff --git a/gcc/ada/gnatlink.adb b/gcc/ada/gnatlink.adb
index 793feb95690..68262f447e4 100644
--- a/gcc/ada/gnatlink.adb
+++ b/gcc/ada/gnatlink.adb
@@ -265,9 +265,7 @@ procedure Gnatlink is
end loop;
Findex2 := File_Name'Last;
- while Findex2 > Findex1
- and then File_Name (Findex2) /= '.'
- loop
+ while Findex2 > Findex1 and then File_Name (Findex2) /= '.' loop
Findex2 := Findex2 - 1;
end loop;
@@ -343,7 +341,8 @@ procedure Gnatlink is
------------------
procedure Process_Args is
- Next_Arg : Integer;
+ Next_Arg : Integer;
+
Skip_Next : Boolean := False;
-- Set to true if the next argument is to be added into the list of
-- linker's argument without parsing it.
@@ -637,8 +636,8 @@ procedure Gnatlink is
Linker_Objects.Table (Linker_Objects.Last) :=
new String'(Arg);
- -- If host object file, record object file
- -- e.g. accept foo.o as well as foo.obj on VMS target
+ -- If host object file, record object file e.g. accept foo.o
+ -- as well as foo.obj on VMS target.
elsif Arg'Length > Get_Object_Suffix.all'Length
and then Arg
@@ -684,8 +683,8 @@ procedure Gnatlink is
and then Linker_Options.Last >= Linker_Options.First
then
Ali_File_Name :=
- new String'(Linker_Options.Table (Linker_Options.First).all &
- ".ali");
+ new String'(Linker_Options.Table (Linker_Options.First).all
+ & ".ali");
end if;
end Process_Args;
@@ -895,6 +894,7 @@ procedure Gnatlink is
procedure Store_File_Context is
use type System.CRTL.long;
+
begin
RB_Next_Line := Next_Line;
RB_Nfirst := Nfirst;
@@ -995,9 +995,10 @@ procedure Gnatlink is
Linker_Objects.Table (Linker_Objects.Last) :=
new String'(Next_Line (Nfirst .. Nlast));
- Link_Bytes := Link_Bytes + Nlast - Nfirst + 2;
-- Nlast - Nfirst + 1, for the size, plus one for the space between
-- each arguments.
+
+ Link_Bytes := Link_Bytes + Nlast - Nfirst + 2;
end loop;
Objs_End := Linker_Objects.Last;
@@ -1127,10 +1128,12 @@ procedure Gnatlink is
elsif Next_Line (Nfirst .. Nlast) = "-ldecgnat"
or else Next_Line (Nfirst .. Nlast) = "-lgnarl"
or else Next_Line (Nfirst .. Nlast) = "-lgnat"
- or else Next_Line
+ or else
+ Next_Line
(1 .. Natural'Min (Nlast, 8 + Library_Version'Length)) =
Shared_Lib ("gnarl")
- or else Next_Line
+ or else
+ Next_Line
(1 .. Natural'Min (Nlast, 7 + Library_Version'Length)) =
Shared_Lib ("gnat")
then
@@ -1138,8 +1141,8 @@ procedure Gnatlink is
-- We will be looking for the static version of the library
-- as it is in the same directory as the shared version.
- if Next_Line (Nlast - Library_Version'Length + 1 .. Nlast)
- = Library_Version
+ if Next_Line (Nlast - Library_Version'Length + 1 .. Nlast) =
+ Library_Version
then
-- Set Last to point to last character before the
-- library version.
@@ -1159,11 +1162,10 @@ procedure Gnatlink is
File_Path : String_Access;
Object_Lib_Extension : constant String :=
- Value (Object_Library_Ext_Ptr);
+ Value (Object_Library_Ext_Ptr);
File_Name : constant String := "lib" &
- Next_Line (Nfirst + 2 .. Last) &
- Object_Lib_Extension;
+ Next_Line (Nfirst + 2 .. Last) & Object_Lib_Extension;
Run_Path_Opt : constant String :=
Value (Run_Path_Option_Ptr);
@@ -1179,9 +1181,9 @@ procedure Gnatlink is
if File_Path /= null then
if GNAT_Static then
- -- If static gnatlib found, explicitly
- -- specify to overcome possible linker
- -- default usage of shared version.
+ -- If static gnatlib found, explicitly specify to
+ -- overcome possible linker default usage of shared
+ -- version.
Linker_Options.Increment_Last;
@@ -1191,9 +1193,9 @@ procedure Gnatlink is
elsif GNAT_Shared then
if Opt.Run_Path_Option then
- -- If shared gnatlib desired, add the
- -- appropriate system specific switch
- -- so that it can be located at runtime.
+ -- If shared gnatlib desired, add appropriate
+ -- system specific switch so that it can be
+ -- located at runtime.
if Run_Path_Opt'Length /= 0 then
@@ -1204,6 +1206,7 @@ procedure Gnatlink is
declare
Path : String (1 .. File_Path'Length + 15);
+
Path_Last : constant Natural :=
File_Path'Length;
@@ -1299,9 +1302,9 @@ procedure Gnatlink is
Run_Path_Opt
then
-- We have found an already
- -- specified run_path_option: we
- -- will add to this switch,
- -- because only one
+ -- specified run_path_option:
+ -- we will add to this
+ -- switch, because only one
-- run_path_option should be
-- specified.
@@ -1378,9 +1381,8 @@ procedure Gnatlink is
end if;
else
- -- If gnatlib library not found, then
- -- add it anyway in case some other
- -- mechanism may find it.
+ -- If gnatlib library not found, then add it anyway in
+ -- case some other mechanism may find it.
Linker_Options.Increment_Last;
Linker_Options.Table (Linker_Options.Last) :=
@@ -1872,8 +1874,9 @@ begin
if Compile_Bind_File then
Bind_Step : declare
Success : Boolean;
- Args : Argument_List
- (1 .. Binder_Options_From_ALI.Last + Binder_Options.Last + 1);
+
+ Args : Argument_List
+ (1 .. Binder_Options_From_ALI.Last + Binder_Options.Last + 1);
begin
for J in 1 .. Binder_Options_From_ALI.Last loop
@@ -1954,8 +1957,7 @@ begin
elsif RTX_RTSS_Kernel_Module_On_Target then
- -- Remove flags not relevant for Microsoft linker and adapt some
- -- others.
+ -- Remove irrelevant flags for Microsoft linker, adapt some others
for J in reverse Linker_Options.First .. Linker_Options.Last loop
@@ -1976,12 +1978,13 @@ begin
-- Replace "-L" by its counterpart "/LIBPATH:" and UNIX "/" by
-- Windows "\".
+
elsif Linker_Options.Table (J) (1 .. 2) = "-L" then
declare
Libpath_Option : constant String_Access := new String'
("/LIBPATH:" &
- Linker_Options.Table (J)
- (3 .. Linker_Options.Table (J).all'Last));
+ Linker_Options.Table
+ (J) (3 .. Linker_Options.Table (J).all'Last));
begin
for Index in 10 .. Libpath_Option'Last loop
if Libpath_Option (Index) = '/' then
@@ -1993,10 +1996,12 @@ begin
end;
-- Replace "-g" by "/DEBUG"
+
elsif Linker_Options.Table (J) (1 .. 2) = "-g" then
Linker_Options.Table (J) := new String'("/DEBUG");
-- Replace "-o" by "/OUT:"
+
elsif Linker_Options.Table (J) (1 .. 2) = "-o" then
Linker_Options.Table (J + 1) := new String'
("/OUT:" & Linker_Options.Table (J + 1).all);
@@ -2007,6 +2012,7 @@ begin
Num_Args := Num_Args - 1;
-- Replace "--stack=" by "/STACK:"
+
elsif Linker_Options.Table (J) (1 .. 8) = "--stack=" then
Linker_Options.Table (J) := new String'
("/STACK:" &
@@ -2014,6 +2020,7 @@ begin
(9 .. Linker_Options.Table (J).all'Last));
-- Replace "-v" by its counterpart "/VERBOSE"
+
elsif Linker_Options.Table (J) (1 .. 2) = "-v" then
Linker_Options.Table (J) := new String'("/VERBOSE");
end if;
@@ -2069,30 +2076,30 @@ begin
end;
end if;
- -- Remove duplicate stack size setting from the Linker_Options
- -- table. The stack setting option "-Xlinker --stack=R,C" can be
- -- found in one line when set by a pragma Linker_Options or in two
- -- lines ("-Xlinker" then "--stack=R,C") when set on the command
- -- line. We also check for the "-Wl,--stack=R" style option.
+ -- Remove duplicate stack size setting from the Linker_Options table.
+ -- The stack setting option "-Xlinker --stack=R,C" can be found
+ -- in one line when set by a pragma Linker_Options or in two lines
+ -- ("-Xlinker" then "--stack=R,C") when set on the command line. We
+ -- also check for the "-Wl,--stack=R" style option.
- -- We must remove the second stack setting option instance
- -- because the one on the command line will always be the first
- -- one. And any subsequent stack setting option will overwrite the
- -- previous one. This is done especially for GNAT/NT where we set
- -- the stack size for tasking programs by a pragma in the NT
- -- specific tasking package System.Task_Primitives.Operations.
+ -- We must remove the second stack setting option instance because
+ -- the one on the command line will always be the first one. And any
+ -- subsequent stack setting option will overwrite the previous one.
+ -- This is done especially for GNAT/NT where we set the stack size
+ -- for tasking programs by a pragma in the NT specific tasking
+ -- package System.Task_Primitives.Operations.
-- Note: This is not a FOR loop that runs from Linker_Options.First
-- to Linker_Options.Last, since operations within the loop can
-- modify the length of the table.
Clean_Link_Option_Set : declare
- J : Natural := Linker_Options.First;
+ J : Natural;
Shared_Libgcc_Seen : Boolean := False;
begin
+ J := Linker_Options.First;
while J <= Linker_Options.Last loop
-
if Linker_Options.Table (J).all = "-Xlinker"
and then J < Linker_Options.Last
and then Linker_Options.Table (J + 1)'Length > 8
@@ -2128,12 +2135,12 @@ begin
-- pragma Linker_Options set in the NT runtime.
if (Linker_Options.Table (J)'Length > 17
- and then Linker_Options.Table (J) (1 .. 17)
- = "-Xlinker --stack=")
+ and then Linker_Options.Table (J) (1 .. 17) =
+ "-Xlinker --stack=")
or else
(Linker_Options.Table (J)'Length > 12
- and then Linker_Options.Table (J) (1 .. 12)
- = "-Wl,--stack=")
+ and then Linker_Options.Table (J) (1 .. 12) =
+ "-Wl,--stack=")
then
if Stack_Op then
Linker_Options.Table (J .. Linker_Options.Last - 1) :=
@@ -2245,8 +2252,7 @@ begin
Write_Eol;
for J in
- Response_File_Objects.First ..
- Response_File_Objects.Last
+ Response_File_Objects.First .. Response_File_Objects.Last
loop
Write_Str (Response_File_Objects.Table (J).all);
Write_Eol;
diff --git a/gcc/ada/impunit.adb b/gcc/ada/impunit.adb
index bb62264c66b..6b6b45febaa 100644
--- a/gcc/ada/impunit.adb
+++ b/gcc/ada/impunit.adb
@@ -253,6 +253,7 @@ package body Impunit is
("g-cgideb", F), -- GNAT.CGI.Debug
("g-comlin", F), -- GNAT.Command_Line
("g-comver", F), -- GNAT.Compiler_Version
+ ("g-cppexc", F), -- GNAT.CPP_Exceptions
("g-crc32 ", F), -- GNAT.CRC32
("g-ctrl_c", F), -- GNAT.Ctrl_C
("g-curexc", F), -- GNAT.Current_Exception
diff --git a/gcc/ada/init.c b/gcc/ada/init.c
index 1b2e188ab51..7f8b3a3e58c 100644
--- a/gcc/ada/init.c
+++ b/gcc/ada/init.c
@@ -226,19 +226,6 @@ nanosleep (struct timestruc_t *Rqtp, struct timestruc_t *Rmtp)
#endif /* _AIXVERSION_430 */
-/* Version of AIX before 5.3 don't have pthread_condattr_setclock:
- * supply it as a weak symbol here so that if linking on a 5.3 or newer
- * machine, we get the real one.
- */
-
-#ifndef _AIXVERSION_530
-#pragma weak pthread_condattr_setclock
-int
-pthread_condattr_setclock (pthread_condattr_t *attr, clockid_t cl) {
- return 0;
-}
-#endif
-
static void
__gnat_error_handler (int sig,
siginfo_t *si ATTRIBUTE_UNUSED,
@@ -443,19 +430,22 @@ __gnat_install_handler (void)
#pragma weak linux_sigaction
int linux_sigaction (int signum, const struct sigaction *act,
- struct sigaction *oldact) {
+ struct sigaction *oldact)
+{
return sigaction (signum, act, oldact);
}
#define sigaction(signum, act, oldact) linux_sigaction (signum, act, oldact)
#pragma weak fake_linux_sigfillset
-void fake_linux_sigfillset (sigset_t *set) {
+void fake_linux_sigfillset (sigset_t *set)
+{
sigfillset (set);
}
#define sigfillset(set) fake_linux_sigfillset (set)
#pragma weak fake_linux_sigemptyset
-void fake_linux_sigemptyset (sigset_t *set) {
+void fake_linux_sigemptyset (sigset_t *set)
+{
sigemptyset (set);
}
#define sigemptyset(set) fake_linux_sigemptyset (set)
@@ -593,7 +583,7 @@ __gnat_install_handler (void)
/* Turn the current Linux task into a native Xenomai task */
- rt_task_shadow(&main_task, "environment_task", prio, T_FPU);
+ rt_task_shadow (&main_task, "environment_task", prio, T_FPU);
#endif
/* Set up signal handler to map synchronous signals to appropriate
@@ -910,10 +900,10 @@ extern struct Exception_Data Layout_Error;
extern struct Exception_Data Non_Ada_Error;
#define Coded_Exception system__vms_exception_table__coded_exception
-extern struct Exception_Data *Coded_Exception (Exception_Code);
+extern struct Exception_Data *Coded_Exception (void *);
#define Base_Code_In system__vms_exception_table__base_code_in
-extern Exception_Code Base_Code_In (Exception_Code);
+extern void *Base_Code_In (void *);
/* DEC Ada exceptions are not defined in a header file, so they
must be declared. */
@@ -1046,8 +1036,7 @@ static const struct cond_except system_cond_except_table [] =
should be use with caution since the implementation has been kept
very simple. */
-typedef int
-resignal_predicate (int code);
+typedef int resignal_predicate (int code);
static const int * const cond_resignal_table [] =
{
@@ -1136,7 +1125,7 @@ copy_msg (struct descriptor_s *msgdesc, char *message)
/* Scan TABLE for a match for the condition contained in SIGARGS,
and return the entry, or the empty entry if no match found. */
static const struct cond_except *
- scan_conditions ( int *sigargs, const struct cond_except *table [])
+scan_conditions ( int *sigargs, const struct cond_except *table [])
{
int i;
struct cond_except entry;
@@ -1190,7 +1179,7 @@ __gnat_handle_vms_condition (int *sigargs, void *mechargs)
{
struct Exception_Data *exception = 0;
unsigned int needs_adjust = 0;
- Exception_Code base_code;
+ void *base_code;
struct descriptor_s gnat_facility = {4, 0, "GNAT"};
char message [Default_Exception_Msg_Max_Length];
@@ -1209,7 +1198,7 @@ __gnat_handle_vms_condition (int *sigargs, void *mechargs)
#ifdef IN_RTS
/* See if it's an imported exception. Beware that registered exceptions
are bound to their base code, with the severity bits masked off. */
- base_code = Base_Code_In ((Exception_Code) sigargs[1]);
+ base_code = Base_Code_In ((void *) sigargs[1]);
exception = Coded_Exception (base_code);
#endif
@@ -1674,12 +1663,14 @@ __gnat_install_handler ()
#include <iv.h>
#endif
+#if defined (ARMEL) && (_WRS_VXWORKS_MAJOR == 6)
+#include <vmLib.h>
+#endif
+
#ifdef VTHREADS
#include "private/vThreadsP.h"
#endif
-void __gnat_error_handler (int, void *, struct sigcontext *);
-
#ifndef __RTP__
/* Directly vectored Interrupt routines are not supported when using RTPs. */
@@ -1690,7 +1681,7 @@ extern int __gnat_inum_to_ivec (int);
int
__gnat_inum_to_ivec (int num)
{
- return INUM_TO_IVEC (num);
+ return (int) INUM_TO_IVEC (num);
}
#endif
@@ -1724,8 +1715,8 @@ __gnat_clear_exception_count (void)
/* Handle different SIGnal to exception mappings in different VxWorks
versions. */
static void
-__gnat_map_signal (int sig, void *si ATTRIBUTE_UNUSED,
- struct sigcontext *sc ATTRIBUTE_UNUSED)
+__gnat_map_signal (int sig, siginfo_t *si ATTRIBUTE_UNUSED,
+ void *sc ATTRIBUTE_UNUSED)
{
struct Exception_Data *exception;
const char *msg;
@@ -1812,6 +1803,49 @@ __gnat_map_signal (int sig, void *si ATTRIBUTE_UNUSED,
msg = "unhandled signal";
}
+ /* On ARM VxWorks 6.x, the guard page is left un-armed by the kernel
+ after being violated, so subsequent violations aren't detected.
+ so we retrieve the address of the guard page from the TCB and compare it
+ with the page that is violated (pREG 12 in the context) and re-arm that
+ page if there's a match. Additionally we're are assured this is a
+ genuine stack overflow condition and and set the message and exception
+ to that effect. */
+#if defined (ARMEL) && (_WRS_VXWORKS_MAJOR == 6)
+
+ /* We re-arm the guard page by marking it invalid */
+
+#define PAGE_SIZE 4096
+#define REG_IP 12
+
+ if (sig == SIGSEGV || sig == SIGBUS || sig == SIGILL)
+ {
+ TASK_ID tid = taskIdSelf ();
+ WIND_TCB *pTcb = taskTcb (tid);
+ unsigned long violated_page
+ = ((struct sigcontext *) sc)->sc_pregs->r[REG_IP] & ~(PAGE_SIZE - 1);
+
+ if ((unsigned long) (pTcb->pStackEnd - PAGE_SIZE) == violated_page)
+ {
+ vmStateSet (NULL, violated_page,
+ PAGE_SIZE, VM_STATE_MASK_VALID, VM_STATE_VALID_NOT);
+ exception = &storage_error;
+
+ switch (sig)
+ {
+ case SIGSEGV:
+ msg = "SIGSEGV: stack overflow";
+ break;
+ case SIGBUS:
+ msg = "SIGBUS: stack overflow";
+ break;
+ case SIGILL:
+ msg = "SIGILL: stack overflow";
+ break;
+ }
+ }
+ }
+#endif /* defined (ARMEL) && (_WRS_VXWORKS_MAJOR == 6) */
+
__gnat_clear_exception_count ();
Raise_From_Signal_Handler (exception, msg);
}
@@ -1819,8 +1853,8 @@ __gnat_map_signal (int sig, void *si ATTRIBUTE_UNUSED,
/* Tasking and Non-tasking signal handler. Map SIGnal to Ada exception
propagation after the required low level adjustments. */
-void
-__gnat_error_handler (int sig, void *si, struct sigcontext *sc)
+static void
+__gnat_error_handler (int sig, siginfo_t *si, void *sc)
{
sigset_t mask;
@@ -1878,7 +1912,7 @@ __gnat_install_handler (void)
exceptions. Make sure that the handler isn't interrupted by another
signal that might cause a scheduling event! */
- act.sa_handler = __gnat_error_handler;
+ act.sa_sigaction = __gnat_error_handler;
act.sa_flags = SA_SIGINFO | SA_ONSTACK;
sigemptyset (&act.sa_mask);
diff --git a/gcc/ada/itypes.adb b/gcc/ada/itypes.adb
index e9a86b411ae..20915bc42c3 100644
--- a/gcc/ada/itypes.adb
+++ b/gcc/ada/itypes.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2008, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -105,7 +105,7 @@ package body Itypes is
Set_Etype (I_Typ, Base_Type (T));
Set_Depends_On_Private (I_Typ, Depends_On_Private (T));
Set_Is_Public (I_Typ, Is_Public (T));
- Set_From_With_Type (I_Typ, From_With_Type (T));
+ Set_From_Limited_With (I_Typ, From_Limited_With (T));
Set_Is_Access_Constant (I_Typ, Is_Access_Constant (T));
Set_Is_Generic_Type (I_Typ, Is_Generic_Type (T));
Set_Is_Volatile (I_Typ, Is_Volatile (T));
diff --git a/gcc/ada/layout.adb b/gcc/ada/layout.adb
index 55fe37812ce..ff49104e066 100644
--- a/gcc/ada/layout.adb
+++ b/gcc/ada/layout.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 2001-2012, Free Software Foundation, Inc. --
+-- Copyright (C) 2001-2013, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -2388,7 +2388,7 @@ package body Layout is
-- If we only have a limited view of the type, see whether the
-- non-limited view is available.
- if From_With_Type (Designated_Type (E))
+ if From_Limited_With (Designated_Type (E))
and then Ekind (Designated_Type (E)) = E_Incomplete_Type
and then Present (Non_Limited_View (Designated_Type (E)))
then
diff --git a/gcc/ada/lib-util.adb b/gcc/ada/lib-util.adb
index 9047690d663..ae6e204c223 100644
--- a/gcc/ada/lib-util.adb
+++ b/gcc/ada/lib-util.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2009, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -176,6 +176,51 @@ package body Lib.Util is
Write_Info_Name (Name_Id (Name));
end Write_Info_Name;
+ -----------------------------------
+ -- Write_Info_Name_May_Be_Quoted --
+ -----------------------------------
+
+ procedure Write_Info_Name_May_Be_Quoted (Name : File_Name_Type) is
+ Quoted : Boolean := False;
+ Cur : Positive;
+
+ begin
+ Get_Name_String (Name);
+
+ -- The file/path name is quoted only if it includes spaces
+
+ for J in 1 .. Name_Len loop
+ if Name_Buffer (J) = ' ' then
+ Quoted := True;
+ exit;
+ end if;
+ end loop;
+
+ -- Deal with quoting string if needed
+
+ if Quoted then
+ Insert_Str_In_Name_Buffer ("""", 1);
+ Add_Char_To_Name_Buffer ('"');
+
+ -- Any character '"' is doubled
+
+ Cur := 2;
+ while Cur < Name_Len loop
+ if Name_Buffer (Cur) = '"' then
+ Insert_Str_In_Name_Buffer ("""", Cur);
+ Cur := Cur + 2;
+ else
+ Cur := Cur + 1;
+ end if;
+ end loop;
+ end if;
+
+ Info_Buffer (Info_Buffer_Len + 1 .. Info_Buffer_Len + Name_Len) :=
+ Name_Buffer (1 .. Name_Len);
+ Info_Buffer_Len := Info_Buffer_Len + Name_Len;
+ Info_Buffer_Col := Info_Buffer_Col + Name_Len;
+ end Write_Info_Name_May_Be_Quoted;
+
--------------------
-- Write_Info_Nat --
--------------------
diff --git a/gcc/ada/lib-util.ads b/gcc/ada/lib-util.ads
index b34bd277a09..f4034d62d6d 100644
--- a/gcc/ada/lib-util.ads
+++ b/gcc/ada/lib-util.ads
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2009, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -65,6 +65,10 @@ package Lib.Util is
-- name is written literally from the names table entry without modifying
-- the case, using simply Get_Name_String.
+ procedure Write_Info_Name_May_Be_Quoted (Name : File_Name_Type);
+ -- Similar to Write_Info_Name, but if Name includes spaces, then it is
+ -- quoted and the '"' are doubled.
+
procedure Write_Info_Slit (S : String_Id);
-- Write string literal value in format required for L/N lines in ali file
diff --git a/gcc/ada/lib-writ.adb b/gcc/ada/lib-writ.adb
index c95b9dc4f83..f794162e20b 100644
--- a/gcc/ada/lib-writ.adb
+++ b/gcc/ada/lib-writ.adb
@@ -38,6 +38,7 @@ with Gnatvsn; use Gnatvsn;
with Opt; use Opt;
with Osint; use Osint;
with Osint.C; use Osint.C;
+with Output; use Output;
with Par;
with Par_SCO; use Par_SCO;
with Restrict; use Restrict;
@@ -281,7 +282,7 @@ package body Lib.Writ is
end if;
else
- Set_From_With_Type (Cunit_Entity (Unum));
+ Set_From_Limited_With (Cunit_Entity (Unum));
end if;
if Implicit_With (Unum) /= Yes then
@@ -615,9 +616,28 @@ package body Lib.Writ is
Write_With_Lines;
- -- Output linker option lines
+ -- Generate the linker option lines
for J in 1 .. Linker_Option_Lines.Last loop
+
+ -- Pragma Linker_Options is not allowed in predefined generic
+ -- units. This is because they won't be read, due to the fact that
+ -- with lines for generic units lack the file name and lib name
+ -- parameters (see Lib_Writ spec for an explanation).
+
+ if Is_Generic_Unit (Cunit_Entity (Main_Unit))
+ and then
+ Is_Predefined_File_Name (Unit_File_Name (Current_Sem_Unit))
+ and then Linker_Option_Lines.Table (J).Unit = Unit_Num
+ then
+ Set_Standard_Error;
+ Write_Line
+ ("linker options not allowed in predefined generic unit");
+ raise Unrecoverable_Error;
+ end if;
+
+ -- Output one linker option line
+
declare
S : Linker_Option_Entry renames Linker_Option_Lines.Table (J);
begin
@@ -790,7 +810,7 @@ package body Lib.Writ is
Write_Info_Initiate ('Z');
elsif Ekind (Cunit_Entity (Unum)) = E_Package
- and then From_With_Type (Cunit_Entity (Unum))
+ and then From_Limited_With (Cunit_Entity (Unum))
then
Write_Info_Initiate ('Y');
@@ -858,7 +878,7 @@ package body Lib.Writ is
end if;
if Ekind (Cunit_Entity (Unum)) = E_Package
- and then From_With_Type (Cunit_Entity (Unum))
+ and then From_Limited_With (Cunit_Entity (Unum))
then
null;
else
@@ -940,7 +960,7 @@ package body Lib.Writ is
for Unum in Units.First .. Last_Unit loop
if Cunit_Entity (Unum) = Empty
- or else not From_With_Type (Cunit_Entity (Unum))
+ or else not From_Limited_With (Cunit_Entity (Unum))
then
Num_Sdep := Num_Sdep + 1;
Sdep_Table (Num_Sdep) := Unum;
@@ -1408,7 +1428,7 @@ package body Lib.Writ is
Fname := Name_Find;
end if;
- Write_Info_Name (Fname);
+ Write_Info_Name_May_Be_Quoted (Fname);
Write_Info_Tab (25);
Write_Info_Str (String (Time_Stamp (Sind)));
Write_Info_Char (' ');
diff --git a/gcc/ada/lib-writ.ads b/gcc/ada/lib-writ.ads
index b9d69c2c99c..f886b668ce0 100644
--- a/gcc/ada/lib-writ.ads
+++ b/gcc/ada/lib-writ.ads
@@ -183,55 +183,55 @@ package Lib.Writ is
-- corresponding source file. Parameters is a sequence of zero or more
-- two letter codes that indicate configuration pragmas and other
-- parameters that apply:
- --
+
-- The arguments are as follows:
- --
+
-- CE Compilation errors. If this is present it means that the ali
-- file resulted from a compilation with the -gnatQ switch set,
-- and illegalities were detected. The ali file contents may
-- not be completely reliable, but the format will be correct
-- and complete. Note that NO is always present if CE is
-- present.
- --
+
-- DB Detect_Blocking pragma is in effect for all units in this
-- file.
- --
+
-- Ex A valid Partition_Elaboration_Policy pragma applies to all
-- the units in this file, where x is the first character
-- (upper case) of the policy name (e.g. 'C' for Concurrent).
- --
+
-- FD Configuration pragmas apply to all the units in this file
-- specifying a possibly non-standard floating point format
-- (VAX float with Long_Float using D_Float).
- --
+
-- FG Configuration pragmas apply to all the units in this file
-- specifying a possibly non-standard floating point format
-- (VAX float with Long_Float using G_Float).
- --
+
-- FI Configuration pragmas apply to all the units in this file
-- specifying a possibly non-standard floating point format
-- (IEEE Float).
- --
+
-- Lx A valid Locking_Policy pragma applies to all the units in
-- this file, where x is the first character (upper case) of
-- the policy name (e.g. 'C' for Ceiling_Locking).
- --
+
-- NO No object. This flag indicates that the units in this file
-- were not compiled to produce an object. This can occur as a
-- result of the use of -gnatc, or if no object can be produced
-- (e.g. when a package spec is compiled instead of the body,
-- or a subunit on its own).
- --
+
-- NR No_Run_Time. Indicates that a pragma No_Run_Time applies
-- to all units in the file.
- --
+
-- NS Normalize_Scalars pragma in effect for all units in
-- this file.
- --
+
-- Qx A valid Queueing_Policy pragma applies to all the units
-- in this file, where x is the first character (upper case)
-- of the policy name (e.g. 'P' for Priority_Queueing).
- --
+
-- SL Indicates that the unit is an Interface to a Standalone
-- Library. Note that this indication is never given by the
-- compiler, but is added by the Project Manager in gnatmake
@@ -240,19 +240,19 @@ package Lib.Writ is
-- SS This unit references System.Secondary_Stack (that is,
-- the unit makes use of the secondary stack facilities).
- --
+
-- Tx A valid Task_Dispatching_Policy pragma applies to all
-- the units in this file, where x is the first character
-- (upper case) of the corresponding policy name (e.g. 'F'
-- for FIFO_Within_Priorities).
- --
+
-- UA Unreserve_All_Interrupts pragma was processed in one or
-- more units in this file
- --
+
-- ZX Units in this file use zero-cost exceptions and have
-- generated exception tables. If ZX is not present, the
-- longjmp/setjmp exception scheme is in use.
- --
+
-- Note that language defined units never output policy (Lx, Tx, Qx)
-- parameters. Language defined units must correctly handle all
-- possible cases. These values are checked for consistency by the
@@ -513,19 +513,19 @@ package Lib.Writ is
-- The lines for each compilation unit have the following form
-- U unit-name source-name version <<attributes>>
- --
+
-- This line identifies the unit to which this section of the library
-- information file applies. The first three parameters are the unit
-- name in internal format, as described in package Uname, and the name
-- of the source file containing the unit.
- --
+
-- Version is the version given as eight hexadecimal characters with
-- upper case letters. This value is the exclusive or of the source
-- checksums of the unit and all its semantically dependent units.
- --
+
-- The <<attributes>> are a series of two letter codes indicating
-- information about the unit:
- --
+
-- BD Unit does not have pragma Elaborate_Body, but the elaboration
-- circuit has determined that it would be a good idea if this
-- pragma were present, since the body of the package contains
@@ -533,7 +533,7 @@ package Lib.Writ is
-- visible part of the package. The binder will try, but does
-- not promise, to keep the elaboration of the body close to
-- the elaboration of the spec.
- --
+
-- DE Dynamic Elaboration. This unit was compiled with the dynamic
-- elaboration model, as set by either the -gnatE switch or
-- pragma Elaboration_Checks (Dynamic).
@@ -545,7 +545,7 @@ package Lib.Writ is
-- body together whenever possible, and for an instance it is
-- always possible; however setting EB ensures that this is done
-- even when using the -p gnatbind switch).
- --
+
-- EE Elaboration entity is present which must be set true when
-- the unit is elaborated. The name of the elaboration entity is
-- formed from the unit name in the usual way. If EE is present,
@@ -554,28 +554,28 @@ package Lib.Writ is
-- be set even if NE is set. This happens when the boolean is
-- needed solely for checking for the case of access before
-- elaboration.
- --
+
-- GE Unit is a generic declaration, or corresponding body
--
-- IL Unit source uses a style with identifiers in all lower-case
-- IU (IL) or all upper case (IU). If the standard mixed-case usage
-- is detected, or the compiler cannot determine the style, then
-- no I parameter will appear.
- --
+
-- IS Initialize_Scalars pragma applies to this unit, or else there
-- is at least one use of the Invalid_Value attribute.
- --
+
-- KM Unit source uses a style with keywords in mixed case (KM)
-- KU or all upper case (KU). If the standard lower-case usage is
-- is detected, or the compiler cannot determine the style, then
-- no K parameter will appear.
- --
+
-- NE Unit has no elaboration routine. All subprogram bodies and
-- specs are in this category. Package bodies and specs may or
-- may not have NE set, depending on whether or not elaboration
-- code is required. Set if N_Compilation_Unit node has flag
-- Has_No_Elaboration_Code set.
- --
+
-- OL The units in this file are compiled with a local pragma
-- Optimize_Alignment, so no consistency requirement applies
-- to these units. All internal units have this status since
@@ -584,33 +584,33 @@ package Lib.Writ is
-- OO Optimize_Alignment (Off) is the default setting for all
-- units in this file. All files in the partition that specify
-- a default must specify the same default.
- --
+
-- OS Optimize_Alignment (Space) is the default setting for all
-- units in this file. All files in the partition that specify
-- a default must specify the same default.
- --
+
-- OT Optimize_Alignment (Time) is the default setting for all
-- units in this file. All files in the partition that specify
-- a default must specify the same default.
- --
+
-- PF The unit has a library-level (package) finalizer
- --
+
-- PK Unit is package, rather than a subprogram
- --
+
-- PU Unit has pragma Pure
- --
+
-- PR Unit has pragma Preelaborate
- --
+
-- RA Unit declares a Remote Access to Class-Wide (RACW) type
- --
+
-- RC Unit has pragma Remote_Call_Interface
- --
+
-- RT Unit has pragma Remote_Types
- --
+
-- SP Unit has pragma Shared_Passive.
- --
+
-- SU Unit is a subprogram, rather than a package
- --
+
-- The attributes may appear in any order, separated by spaces.
-- -----------------------------
@@ -624,7 +624,7 @@ package Lib.Writ is
-- Y unit-name [source-name lib-name] [E] [EA] [ED] [AD]
-- or
-- Z unit-name [source-name lib-name] [E] [EA] [ED] [AD]
- --
+
-- One W line is present for each unit that is mentioned in an explicit
-- non-limited with clause by the current unit. One Y line is present
-- for each unit that is mentioned in an explicit limited with clause
@@ -638,26 +638,32 @@ package Lib.Writ is
-- third parameter is the file name of the library information file
-- that contains the results of compiling this unit. The optional
-- modifiers are used as follows:
- --
+
-- E pragma Elaborate applies to this unit
- --
+
-- EA pragma Elaborate_All applies to this unit
- --
+
-- ED Elaborate_Desirable set for this unit, which means that there
-- is no Elaborate, but the analysis suggests that Program_Error
-- may be raised if the Elaborate conditions cannot be satisfied.
-- The binder will attempt to treat ED as E if it can.
- --
+
-- AD Elaborate_All_Desirable set for this unit, which means that
-- there is no Elaborate_All, but the analysis suggests that
-- Program_Error may be raised if the Elaborate_All conditions
-- cannot be satisfied. The binder will attempt to treat AD as
-- EA if it can.
- --
+
-- The parameter source-name and lib-name are omitted for the case of a
-- generic unit compiled with earlier versions of GNAT which did not
- -- generate object or ali files for generics.
- --
+ -- generate object or ali files for generics. For compatibility in the
+ -- bootstrap path we continue to omit these entries for predefined
+ -- generic units, even though we do now generate object and ali files.
+
+ -- However, in SPARK mode, we always generate source-name and lib-name
+ -- parameters. Bootstrap issues do not apply there, and we need this
+ -- information to properly compute frame conditions of subprograms.
+
-- The parameter source-name and lib-name are also omitted for the W
-- lines that result from use of a Restriction_Set attribute which gets
-- a result of False from a No_Dependence check, in the case where the
@@ -696,6 +702,12 @@ package Lib.Writ is
-- source file, so that this order is preserved by the binder in
-- constructing the set of linker arguments.
+ -- Note: Linker_Options lines never appear in the ALI file generated for
+ -- a predefined generic unit, and there is cicuitry in Sem_Prag to enforce
+ -- this restriction, which is needed because of not generating source name
+ -- and lib name parameters on the with lines for such files, as explained
+ -- above in the section on with lines.
+
-- --------------
-- -- N Notes --
-- --------------
@@ -765,6 +777,13 @@ package Lib.Writ is
-- D source-name time-stamp checksum [subunit-name] line:file-name
+ -- source-name also includes preprocessing data file and preprocessing
+ -- definition file. These preprocessing files may be given as full
+ -- path names instead of simple file names. If a full path name
+ -- includes a directory with spaces, the path name is quoted (quote
+ -- characters (") added at start and end, and any internal quotes are
+ -- doubled).
+
-- The time-stamp field contains the time stamp of the corresponding
-- source file. See types.ads for details on time stamp representation.
diff --git a/gcc/ada/lib-xref-spark_specific.adb b/gcc/ada/lib-xref-spark_specific.adb
index 78413137b0f..849ff0e2dbf 100644
--- a/gcc/ada/lib-xref-spark_specific.adb
+++ b/gcc/ada/lib-xref-spark_specific.adb
@@ -1020,17 +1020,27 @@ package body SPARK_Specific is
Result := Defining_Unit_Name (Specification (Result));
exit;
- -- The enclosing subprogram for a pre- or postconditions should be
- -- the subprogram to which the pragma is attached. This is not
- -- always the case in the AST, as the pragma may be declared after
- -- the declaration of the subprogram. Return Empty in this case.
-
when N_Pragma =>
+
+ -- The enclosing subprogram for a precondition, postcondition,
+ -- or contract case should be the subprogram to which the
+ -- pragma is attached, which can be found by following
+ -- previous elements in the list to which the pragma belongs.
+
if Get_Pragma_Id (Result) = Pragma_Precondition
or else
Get_Pragma_Id (Result) = Pragma_Postcondition
+ or else
+ Get_Pragma_Id (Result) = Pragma_Contract_Cases
then
- return Empty;
+ if Is_List_Member (Result)
+ and then Present (Prev (Result))
+ then
+ Result := Prev (Result);
+ else
+ Result := Parent (Result);
+ end if;
+
else
Result := Parent (Result);
end if;
diff --git a/gcc/ada/lib-xref.adb b/gcc/ada/lib-xref.adb
index 182c2b0a979..972d9637b74 100644
--- a/gcc/ada/lib-xref.adb
+++ b/gcc/ada/lib-xref.adb
@@ -610,6 +610,15 @@ package body Lib.Xref is
Error_Msg_NE ("& is only defined in Ada 2012?y?", N, E);
end if;
+ -- Do not generate references if we are within a postcondition sub-
+ -- program, because the reference does not comes from source, and the
+ -- pre-analysis of the aspect has already created an entry for the ali
+ -- file at the proper source location.
+
+ if Chars (Current_Scope) = Name_uPostconditions then
+ return;
+ end if;
+
-- Never collect references if not in main source unit. However, we omit
-- this test if Typ is 'e' or 'k', since these entries are structural,
-- and it is useful to have them in units that reference packages as
@@ -1298,9 +1307,23 @@ package body Lib.Xref is
Right := '>';
end if;
- -- If non-derived ptr, get directly designated type.
+ -- If the completion of a private type is itself a derived
+ -- type, we need the parent of the full view.
+
+ elsif Is_Private_Type (Tref)
+ and then Present (Full_View (Tref))
+ and then Etype (Full_View (Tref)) /= Full_View (Tref)
+ then
+ Tref := Etype (Full_View (Tref));
+
+ if Left /= '(' then
+ Left := '<';
+ Right := '>';
+ end if;
+
+ -- If non-derived pointer, get directly designated type.
-- If the type has a full view, all references are on the
- -- partial view, that is seen first.
+ -- partial view that is seen first.
elsif Is_Access_Type (Tref) then
Tref := Directly_Designated_Type (Tref);
diff --git a/gcc/ada/mlib-prj.adb b/gcc/ada/mlib-prj.adb
index 3101354d14a..945f9137252 100644
--- a/gcc/ada/mlib-prj.adb
+++ b/gcc/ada/mlib-prj.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 2001-2011, AdaCore --
+-- Copyright (C) 2001-2013, AdaCore --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -1185,9 +1185,9 @@ package body MLib.Prj is
Delete_File (Get_Name_String (Path), Succ);
- if not Succ then
- null;
- end if;
+ -- We ignore a failure in this Delete_File operation.
+ -- Is that OK??? If so, worth a comment as to why we
+ -- are OK with the operation failing
end;
end if;
@@ -1651,7 +1651,7 @@ package body MLib.Prj is
-- content of Rpath. As Rpath contains at least libgnat directory
-- path name, it is guaranteed that it is not null.
- if Path_Option /= null then
+ if Opt.Run_Path_Option and then Path_Option /= null then
Opts.Increment_Last;
Opts.Table (Opts.Last) :=
new String'(Path_Option.all & Rpath (1 .. Rpath_Last));
diff --git a/gcc/ada/opt.ads b/gcc/ada/opt.ads
index 605dc89e839..06d9a4bcbab 100644
--- a/gcc/ada/opt.ads
+++ b/gcc/ada/opt.ads
@@ -516,6 +516,13 @@ package Opt is
-- to make a single long message, and then this message is split up into
-- multiple lines not exceeding the specified length. Set by -gnatj=nn.
+ Error_To_Warning : Boolean := False;
+ -- GNAT
+ -- If True, then certain error messages (e.g. parameter overlap messages
+ -- for procedure calls in Ada 2012 mode) are treated as warnings instead
+ -- of errors. Set by debug flag -gnatd.E. A search for Error_To_Warning
+ -- will identify affected messages.
+
Exception_Handler_Encountered : Boolean := False;
-- GNAT
-- This flag is set true if the parser encounters an exception handler.
@@ -719,6 +726,12 @@ package Opt is
-- Set True to ignore all Style_Checks pragmas. Can be set True by use
-- of -gnateY.
+ Ignore_Unrecognized_VWY_Switches : Boolean := False;
+ -- GNAT
+ -- Set True to ignore unrecognized y, V, w switches. Can be set True
+ -- by use of -gnateu, causing subsequent unrecognized switches to result
+ -- in a warning rather than an error.
+
Implementation_Unit_Warnings : Boolean := True;
-- GNAT
-- Set True to active warnings for use of implementation internal units.
@@ -828,6 +841,11 @@ package Opt is
-- Set to True to skip compile and bind steps (except when Bind_Only is
-- set to True).
+ List_Body_Required_Info : Boolean := False;
+ -- GNATMAKE
+ -- List info messages about why a package requires a body. Modified by use
+ -- of -gnatw.y/.Y.
+
List_Inherited_Aspects : Boolean := False;
-- GNAT
-- List inherited invariants, preconditions, and postconditions from
@@ -1734,12 +1752,12 @@ package Opt is
Ada_Version_Config : Ada_Version_Type;
-- GNAT
-- This is the value of the configuration switch for the Ada 83 mode, as
- -- set by the command line switches -gnat83/95/05, and possibly modified by
- -- the use of configuration pragmas Ada_*. This switch is used to set the
- -- initial value for Ada_Version mode at the start of analysis of a unit.
- -- Note however that the setting of this flag is ignored for internal and
- -- predefined units (which are always compiled in the most up to date
- -- version of Ada).
+ -- set by the command line switches -gnat83/95/2005/2012, and possibly
+ -- modified by the use of configuration pragmas Ada_*. This switch is used
+ -- to set the initial value for Ada_Version mode at the start of analysis
+ -- of a unit. Note however that the setting of this flag is ignored for
+ -- internal and predefined units (which are always compiled in the most up
+ -- to date version of Ada).
Ada_Version_Pragma_Config : Node_Id;
-- This will be set non empty if it is set by a configuration pragma
diff --git a/gcc/ada/osint.adb b/gcc/ada/osint.adb
index 8765b4cb60e..aefffc3ed59 100644
--- a/gcc/ada/osint.adb
+++ b/gcc/ada/osint.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2012, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -1044,8 +1044,8 @@ package body Osint is
procedure Fail (S : String) is
begin
- -- We use Output in case there is a special output set up.
- -- In this case Set_Standard_Error will have no immediate effect.
+ -- We use Output in case there is a special output set up. In this case
+ -- Set_Standard_Error will have no immediate effect.
Set_Standard_Error;
Osint.Write_Program_Name;
diff --git a/gcc/ada/par-ch13.adb b/gcc/ada/par-ch13.adb
index 26b8056f80f..18c63a3bf6c 100644
--- a/gcc/ada/par-ch13.adb
+++ b/gcc/ada/par-ch13.adb
@@ -78,15 +78,19 @@ package body Ch13 is
-- are in Ada 2012 mode, Strict is False, and we consider that we have
-- an aspect specification if the identifier is an aspect name (even if
-- not followed by =>) or the identifier is not an aspect name but is
- -- followed by =>. P_Aspect_Specifications will generate messages if the
- -- aspect specification is ill-formed.
+ -- followed by =>, by a comma, or by a semicolon. The last two cases
+ -- correspond to (misspelled) Boolean aspects with a defaulted value of
+ -- True. P_Aspect_Specifications will generate messages if the aspect
+ -- specification is ill-formed.
elsif not Strict then
if Get_Aspect_Id (Token_Name) /= No_Aspect then
Result := True;
else
Scan; -- past identifier
- Result := Token = Tok_Arrow;
+ Result := Token = Tok_Arrow or else
+ Token = Tok_Comma or else
+ Token = Tok_Semicolon;
end if;
-- If earlier than Ada 2012, check for valid aspect identifier (possibly
@@ -107,9 +111,9 @@ package body Ch13 is
-- The identifier may be the name of a boolean aspect with a
-- defaulted True value. Further checks when analyzing aspect
- -- specification.
+ -- specification, which may include further aspects.
- elsif Token = Tok_Comma then
+ elsif Token = Tok_Comma or else Token = Tok_Semicolon then
Result := True;
elsif Token = Tok_Apostrophe then
diff --git a/gcc/ada/par-ch2.adb b/gcc/ada/par-ch2.adb
index 224c63b7eb9..2218dacb17e 100644
--- a/gcc/ada/par-ch2.adb
+++ b/gcc/ada/par-ch2.adb
@@ -250,23 +250,15 @@ package body Ch2 is
procedure Skip_Pragma_Semicolon is
begin
- if Token /= Tok_Semicolon then
+ -- If skipping the pragma, ignore a missing semicolon
- -- If skipping the pragma, ignore a missing semicolon
+ if Token /= Tok_Semicolon and then Skipping then
+ null;
- if Skipping then
- null;
-
- -- Otherwise demand a semicolon
-
- else
- T_Semicolon;
- end if;
-
- -- Scan past semicolon if present
+ -- Otherwise demand a semicolon
else
- Scan;
+ T_Semicolon;
end if;
end Skip_Pragma_Semicolon;
diff --git a/gcc/ada/par-ch4.adb b/gcc/ada/par-ch4.adb
index 5766639816a..cdf0dab653a 100644
--- a/gcc/ada/par-ch4.adb
+++ b/gcc/ada/par-ch4.adb
@@ -3120,6 +3120,14 @@ package body Ch4 is
Scan; -- Past ELSE
Append_To (Exprs, P_Expression);
+ -- Skip redundant ELSE parts
+
+ while Token = Tok_Else loop
+ Error_Msg_SC ("only one ELSE part is allowed");
+ Scan; -- past ELSE
+ Discard_Junk_Node (P_Expression);
+ end loop;
+
-- Two expression case (implied True, filled in during semantics)
else
diff --git a/gcc/ada/par-ch6.adb b/gcc/ada/par-ch6.adb
index f060b3f2822..560cf4c989c 100644
--- a/gcc/ada/par-ch6.adb
+++ b/gcc/ada/par-ch6.adb
@@ -73,9 +73,6 @@ package body Ch6 is
else
Restore_Scan_State (Scan_State);
end if;
-
- elsif Bad_Spelling_Of (Tok_Return) then
- null;
end if;
end Check_Junk_Semicolon_Before_Return;
diff --git a/gcc/ada/par-prag.adb b/gcc/ada/par-prag.adb
index 5de6ecc0081..4cb9fd16ad4 100644
--- a/gcc/ada/par-prag.adb
+++ b/gcc/ada/par-prag.adb
@@ -1185,7 +1185,9 @@ begin
Pragma_Import_Valued_Procedure |
Pragma_Independent |
Pragma_Independent_Components |
+ Pragma_Initial_Condition |
Pragma_Initialize_Scalars |
+ Pragma_Initializes |
Pragma_Inline |
Pragma_Inline_Always |
Pragma_Inline_Generic |
@@ -1234,11 +1236,15 @@ begin
Pragma_Preelaborable_Initialization |
Pragma_Polling |
Pragma_Persistent_BSS |
+ Pragma_Post |
Pragma_Postcondition |
+ Pragma_Post_Class |
+ Pragma_Pre |
Pragma_Precondition |
Pragma_Predicate |
Pragma_Preelaborate |
Pragma_Preelaborate_05 |
+ Pragma_Pre_Class |
Pragma_Priority |
Pragma_Priority_Specific_Dispatching |
Pragma_Profile |
@@ -1250,6 +1256,10 @@ begin
Pragma_Pure_12 |
Pragma_Pure_Function |
Pragma_Queuing_Policy |
+ Pragma_Refined_Depends |
+ Pragma_Refined_Global |
+ Pragma_Refined_Post |
+ Pragma_Refined_State |
Pragma_Relative_Deadline |
Pragma_Remote_Access_Type |
Pragma_Remote_Call_Interface |
@@ -1283,6 +1293,8 @@ begin
Pragma_Thread_Local_Storage |
Pragma_Time_Slice |
Pragma_Title |
+ Pragma_Type_Invariant |
+ Pragma_Type_Invariant_Class |
Pragma_Unchecked_Union |
Pragma_Unimplemented_Unit |
Pragma_Universal_Aliasing |
diff --git a/gcc/ada/prep.adb b/gcc/ada/prep.adb
index 3ec2087926a..c38234b052e 100644
--- a/gcc/ada/prep.adb
+++ b/gcc/ada/prep.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 2002-2012, Free Software Foundation, Inc. --
+-- Copyright (C) 2002-2013, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -33,6 +33,7 @@ with Snames; use Snames;
with Sinput;
with Stringt; use Stringt;
with Table;
+with Uintp; use Uintp;
with GNAT.Heap_Sort_G;
@@ -146,21 +147,19 @@ package body Prep is
type Pp_State is record
If_Ptr : Source_Ptr;
- -- The location of the #if statement.
- -- Used to flag #if with no corresponding #end if, at the end.
+ -- The location of the #if statement (used to flag #if with no
+ -- corresponding #end if, at the end).
Else_Ptr : Source_Ptr;
- -- The location of the #else statement.
- -- Used to detect multiple #else.
+ -- The location of the #else statement (used to detect multiple #else's)
Deleting : Boolean;
-- Set to True when the code should be deleted or commented out
Match_Seen : Boolean;
- -- Set to True when a condition in an #if or an #elsif is True.
- -- Also set to True if Deleting at the previous level is True.
- -- Used to decide if Deleting should be set to True in a following
- -- #elsif or #else.
+ -- Set to True when a condition in an #if or an #elsif is True. Also set
+ -- to True if Deleting at the previous level is True. Used to decide if
+ -- Deleting should be set to True in a following #elsif or #else.
end record;
@@ -189,13 +188,13 @@ package body Prep is
function Expression
(Evaluate_It : Boolean;
Complemented : Boolean := False) return Boolean;
- -- Evaluate a condition in an #if or an #elsif statement.
- -- If Evaluate_It is False, the condition is effectively evaluated,
- -- otherwise, only the syntax is checked.
+ -- Evaluate a condition in an #if or an #elsif statement. If Evaluate_It
+ -- is False, the condition is effectively evaluated, otherwise, only the
+ -- syntax is checked.
procedure Go_To_End_Of_Line;
- -- Advance the scan pointer until we reach an end of line or the end
- -- of the buffer.
+ -- Advance the scan pointer until we reach an end of line or the end of the
+ -- buffer.
function Matching_Strings (S1, S2 : String_Id) return Boolean;
-- Returns True if the two string parameters are equal (case insensitive)
@@ -250,6 +249,7 @@ package body Prep is
-- If no character '=', then the value is True
if Index = 0 then
+
-- Put the symbol in the name buffer
Name_Len := Definition'Length;
@@ -284,9 +284,14 @@ package body Prep is
end loop;
end if;
- -- And put the value in the result
+ -- Even if the value is a string, we still set Is_A_String to False,
+ -- to avoid adding additional quotes in the preprocessed sources when
+ -- replacing $<symbol>.
Result.Is_A_String := False;
+
+ -- Put the value in the result
+
Start_String;
Store_String_Chars (Definition (Index + 1 .. Definition'Last));
Result.Value := End_String;
@@ -372,8 +377,8 @@ package body Prep is
Complemented : Boolean := False) return Boolean
is
Evaluation : Boolean := Evaluate_It;
- -- Is set to False after an "or else" when left term is True and
- -- after an "and then" when left term is False.
+ -- Is set to False after an "or else" when left term is True and after
+ -- an "and then" when left term is False.
Final_Result : Boolean := False;
@@ -390,6 +395,8 @@ package body Prep is
Symbol_Value1 : String_Id;
Symbol_Value2 : String_Id;
+ Relop : Token_Type;
+
begin
-- Loop for each term
@@ -398,12 +405,13 @@ package body Prep is
Current_Result := False;
- case Token is
+ -- Scan current term, starting with Token
- when Tok_Left_Paren =>
+ case Token is
- -- ( expression )
+ -- Handle parenthesized expression
+ when Tok_Left_Paren =>
Scan.all;
Current_Result := Expression (Evaluation);
@@ -415,14 +423,15 @@ package body Prep is
("`)` expected", Token_Ptr);
end if;
- when Tok_Not =>
-
- -- not expression
+ -- Handle not expression
+ when Tok_Not =>
Scan.all;
Current_Result :=
not Expression (Evaluation, Complemented => True);
+ -- Handle sequence starting with identifier
+
when Tok_Identifier =>
Symbol_Name1 := Token_Name;
Symbol_Pos1 := Token_Ptr;
@@ -447,12 +456,105 @@ package body Prep is
Current_Result := Index_Of (Symbol_Name1) /= No_Symbol;
end if;
- elsif Token = Tok_Equal then
- Scan.all;
+ -- Handle relational operator
+ elsif
+ Token = Tok_Equal or else
+ Token = Tok_Less or else
+ Token = Tok_Less_Equal or else
+ Token = Tok_Greater or else
+ Token = Tok_Greater_Equal
+ then
+ Relop := Token;
+ Scan.all;
Change_Reserved_Keyword_To_Symbol;
- if Token = Tok_Identifier then
+ if Token = Tok_Integer_Literal then
+
+ -- symbol = integer
+ -- symbol < integer
+ -- symbol <= integer
+ -- symbol > integer
+ -- symbol >= integer
+
+ declare
+ Value : constant Int := UI_To_Int (Int_Literal_Value);
+ Data : Symbol_Data;
+
+ Symbol_Value : Int;
+ -- Value of symbol as Int
+
+ begin
+ if Evaluation then
+ Symbol1 := Index_Of (Symbol_Name1);
+
+ if Symbol1 = No_Symbol then
+ Error_Msg_Name_1 := Symbol_Name1;
+ Error_Msg ("unknown symbol %", Symbol_Pos1);
+ Symbol_Value1 := No_String;
+
+ else
+ Data := Mapping.Table (Symbol1);
+
+ if Data.Is_A_String then
+ Error_Msg_Name_1 := Symbol_Name1;
+ Error_Msg
+ ("symbol % value is not integer",
+ Symbol_Pos1);
+
+ else
+ begin
+ String_To_Name_Buffer (Data.Value);
+ Symbol_Value :=
+ Int'Value (Name_Buffer (1 .. Name_Len));
+
+ case Relop is
+ when Tok_Equal =>
+ Current_Result :=
+ Symbol_Value = Value;
+
+ when Tok_Less =>
+ Current_Result :=
+ Symbol_Value < Value;
+
+ when Tok_Less_Equal =>
+ Current_Result :=
+ Symbol_Value <= Value;
+
+ when Tok_Greater =>
+ Current_Result :=
+ Symbol_Value > Value;
+
+ when Tok_Greater_Equal =>
+ Current_Result :=
+ Symbol_Value >= Value;
+
+ when others =>
+ null;
+ end case;
+
+ exception
+ when Constraint_Error =>
+ Error_Msg_Name_1 := Symbol_Name1;
+ Error_Msg
+ ("symbol % value is not an integer",
+ Symbol_Pos1);
+ end;
+ end if;
+ end if;
+ end if;
+
+ Scan.all;
+ end;
+
+ -- Error if relational operator other than = if not numbers
+
+ elsif Relop /= Tok_Equal then
+ Error_Msg ("number expected", Token_Ptr);
+
+ -- Equality comparison of two strings
+
+ elsif Token = Tok_Identifier then
-- symbol = symbol
@@ -495,10 +597,11 @@ package body Prep is
end if;
if Symbol_Value1 /= No_String
- and then Symbol_Value2 /= No_String
+ and then
+ Symbol_Value2 /= No_String
then
- Current_Result := Matching_Strings
- (Symbol_Value1, Symbol_Value2);
+ Current_Result :=
+ Matching_Strings (Symbol_Value1, Symbol_Value2);
end if;
end if;
@@ -535,12 +638,13 @@ package body Prep is
else
Error_Msg
- ("symbol or literal string expected", Token_Ptr);
+ ("literal integer, symbol or literal string expected",
+ Token_Ptr);
end if;
- else
- -- symbol (True or False)
+ -- Handle True or False
+ else
if Evaluation then
Symbol1 := Index_Of (Symbol_Name1);
@@ -582,6 +686,8 @@ package body Prep is
end if;
end if;
+ -- Unrecognized sequence
+
when others =>
Error_Msg ("`(`, NOT or symbol expected", Token_Ptr);
end case;
@@ -599,7 +705,7 @@ package body Prep is
Final_Result := Final_Result and Current_Result;
end case;
- -- Check the next operator
+ -- Handle AND
if Token = Tok_And then
if Complemented then
@@ -622,6 +728,8 @@ package body Prep is
end if;
end if;
+ -- Handle OR
+
elsif Token = Tok_Or then
if Complemented then
Error_Msg
@@ -643,9 +751,9 @@ package body Prep is
end if;
end if;
- else
- -- No operator: exit the term loop
+ -- No AND/OR operator, so exit from the loop through terms
+ else
exit;
end if;
end loop;
@@ -732,7 +840,6 @@ package body Prep is
Get_Name_String (Mapping.Table (Order (Op1)).Symbol);
S2 : constant String :=
Get_Name_String (Mapping.Table (Order (Op2)).Symbol);
-
begin
return S1 < S2;
end Lt;
@@ -869,6 +976,8 @@ package body Prep is
-- Parse_Def_File --
--------------------
+ -- This procedure REALLY needs some more comments ???
+
procedure Parse_Def_File is
Symbol : Symbol_Id;
Symbol_Name : Name_Id;
@@ -914,7 +1023,32 @@ package body Prep is
Scan.all;
- if Token = Tok_String_Literal then
+ if Token = Tok_Integer_Literal then
+ declare
+ Ptr : Source_Ptr := Token_Ptr;
+
+ begin
+ Start_String;
+ while Ptr < Scan_Ptr loop
+ Store_String_Char (Sinput.Source (Ptr));
+ Ptr := Ptr + 1;
+ end loop;
+
+ Data := (Symbol => Symbol_Name,
+ Original => Original_Name,
+ On_The_Command_Line => False,
+ Is_A_String => False,
+ Value => End_String);
+ end;
+
+ Scan.all;
+
+ if Token /= Tok_End_Of_Line and then Token /= Tok_EOF then
+ Error_Msg ("extraneous text in definition", Token_Ptr);
+ goto Cleanup;
+ end if;
+
+ elsif Token = Tok_String_Literal then
Data := (Symbol => Symbol_Name,
Original => Original_Name,
On_The_Command_Line => False,
@@ -984,9 +1118,10 @@ package body Prep is
Symbol := Index_Of (Symbol_Name);
if Symbol /= No_Symbol then
+
-- If we already have an entry for this symbol, replace it
- -- with the new value, except if the symbol was declared
- -- on the command line.
+ -- with the new value, except if the symbol was declared on
+ -- the command line.
if Mapping.Table (Symbol).On_The_Command_Line then
goto Continue;
@@ -1088,8 +1223,7 @@ package body Prep is
begin
Start_Of_Processing := Scan_Ptr;
- -- We need to call Scan for the first time, because Initialize_Scanner
- -- is no longer doing it.
+ -- First a call to Scan, because Initialize_Scanner is not doing it
Scan.all;
@@ -1182,8 +1316,8 @@ package body Prep is
Scan.all;
end if;
- -- It is an error to have trailing characters after
- -- the condition or "then".
+ -- It is an error to have trailing characters after the
+ -- condition or "then".
if Token /= Tok_End_Of_Line
and then Token /= Tok_EOF
@@ -1196,8 +1330,9 @@ package body Prep is
Go_To_End_Of_Line;
end if;
- -- Depending on the value of the condition, set the
- -- new values of Deleting and Match_Seen.
+ -- Depending on the value of the condition, set the new
+ -- values of Deleting and Match_Seen.
+
if Pp_States.Last > 0 then
if Pp_States.Table (Pp_States.Last).Match_Seen then
Pp_States.Table (Pp_States.Last).Deleting := True;
@@ -1226,8 +1361,7 @@ package body Prep is
No_Error_Found := False;
end if;
- -- Set the possibly new values of Deleting and
- -- Match_Seen.
+ -- Set the possibly new values of Deleting and Match_Seen
if Pp_States.Last > 0 then
if Pp_States.Table (Pp_States.Last).Match_Seen then
@@ -1241,8 +1375,7 @@ package body Prep is
False;
end if;
- -- Set the Else_Ptr to check for illegal #elsif
- -- later.
+ -- Set the Else_Ptr to check for illegal #elsif later
Pp_States.Table (Pp_States.Last).Else_Ptr :=
Token_Ptr;
@@ -1250,7 +1383,8 @@ package body Prep is
Scan.all;
- -- It is an error to have characters after "#else"
+ -- Error of character present after "#else"
+
if Token /= Tok_End_Of_Line
and then Token /= Tok_EOF
then
@@ -1287,8 +1421,8 @@ package body Prep is
else
Scan.all;
- -- It is an error to have character after
- -- "#end if;".
+ -- Error of character present after "#end if;"
+
if Token /= Tok_End_Of_Line
and then Token /= Tok_EOF
then
@@ -1418,15 +1552,14 @@ package body Prep is
pragma Assert (Token = Tok_End_Of_Line or else Token = Tok_EOF);
- -- At this point, the token is either end of line or EOF.
- -- The line to possibly output stops just before the token.
+ -- At this point, the token is either end of line or EOF. The line to
+ -- possibly output stops just before the token.
Output_Line (Start_Of_Processing, Token_Ptr - 1);
-- If we are at the end of a line, the scan pointer is at the first
- -- non blank character, not necessarily the first character of the
- -- line; so, we have to deduct Start_Of_Processing from the token
- -- pointer.
+ -- non-blank character (may not be the first character of the line),
+ -- so we have to deduct Start_Of_Processing from the token pointer.
if Token = Tok_End_Of_Line then
if (Sinput.Source (Token_Ptr) = ASCII.CR
diff --git a/gcc/ada/prj-attr.adb b/gcc/ada/prj-attr.adb
index a69281130dd..4f818f84717 100644
--- a/gcc/ada/prj-attr.adb
+++ b/gcc/ada/prj-attr.adb
@@ -111,6 +111,7 @@ package body Prj.Attr is
"SVlibrary_auto_init#" &
"LVleading_library_options#" &
"LVlibrary_options#" &
+ "Lalibrary_rpath_options#" &
"SVlibrary_src_dir#" &
"SVlibrary_ali_dir#" &
"SVlibrary_gcc#" &
@@ -288,6 +289,8 @@ package body Prj.Attr is
"LVswitches#" &
"Lasource_artifact_extensions#" &
"Laobject_artifact_extensions#" &
+ "LVartifacts_in_exec_dir#" &
+ "LVartifacts_in_object_dir#" &
-- package Cross_Reference
diff --git a/gcc/ada/prj-conf.adb b/gcc/ada/prj-conf.adb
index 48241efbdd0..f16509b18ab 100644
--- a/gcc/ada/prj-conf.adb
+++ b/gcc/ada/prj-conf.adb
@@ -68,16 +68,6 @@ package body Prj.Conf is
-- Local_Subprograms --
-----------------------
- procedure Add_Attributes
- (Project_Tree : Project_Tree_Ref;
- Conf_Decl : Declarations;
- User_Decl : in out Declarations);
- -- Process the attributes in the config declarations.
- -- For single string values, if the attribute is not declared in the user
- -- declarations, declare it with the value in the config declarations.
- -- For string list values, prepend the value in the user declarations with
- -- the value in the config declarations.
-
function Check_Target
(Config_File : Prj.Project_Id;
Autoconf_Specified : Boolean;
@@ -109,219 +99,6 @@ package body Prj.Conf is
-- projects, so that when the second phase of the processing is performed
-- these attributes are automatically taken into account.
- --------------------
- -- Add_Attributes --
- --------------------
-
- procedure Add_Attributes
- (Project_Tree : Project_Tree_Ref;
- Conf_Decl : Declarations;
- User_Decl : in out Declarations)
- is
- Shared : constant Shared_Project_Tree_Data_Access := Project_Tree.Shared;
- Conf_Attr_Id : Variable_Id;
- Conf_Attr : Variable;
- Conf_Array_Id : Array_Id;
- Conf_Array : Array_Data;
- Conf_Array_Elem_Id : Array_Element_Id;
- Conf_Array_Elem : Array_Element;
- Conf_List : String_List_Id;
- Conf_List_Elem : String_Element;
-
- User_Attr_Id : Variable_Id;
- User_Attr : Variable;
- User_Array_Id : Array_Id;
- User_Array : Array_Data;
- User_Array_Elem_Id : Array_Element_Id;
- User_Array_Elem : Array_Element;
-
- begin
- Conf_Attr_Id := Conf_Decl.Attributes;
- User_Attr_Id := User_Decl.Attributes;
- while Conf_Attr_Id /= No_Variable loop
- Conf_Attr := Shared.Variable_Elements.Table (Conf_Attr_Id);
- User_Attr := Shared.Variable_Elements.Table (User_Attr_Id);
-
- if not Conf_Attr.Value.Default then
- if User_Attr.Value.Default then
-
- -- No attribute declared in user project file: just copy the
- -- value of the configuration attribute.
-
- User_Attr.Value := Conf_Attr.Value;
- Shared.Variable_Elements.Table (User_Attr_Id) := User_Attr;
-
- elsif User_Attr.Value.Kind = List
- and then Conf_Attr.Value.Values /= Nil_String
- then
- -- List attribute declared in both the user project and the
- -- configuration project: prepend the user list with the
- -- configuration list.
-
- declare
- User_List : constant String_List_Id :=
- User_Attr.Value.Values;
- Conf_List : String_List_Id := Conf_Attr.Value.Values;
- Conf_Elem : String_Element;
- New_List : String_List_Id;
- New_Elem : String_Element;
-
- begin
- -- Create new list
-
- String_Element_Table.Increment_Last
- (Shared.String_Elements);
- New_List :=
- String_Element_Table.Last (Shared.String_Elements);
-
- -- Value of attribute is new list
-
- User_Attr.Value.Values := New_List;
- Shared.Variable_Elements.Table (User_Attr_Id) := User_Attr;
-
- loop
- -- Get each element of configuration list
-
- Conf_Elem := Shared.String_Elements.Table (Conf_List);
- New_Elem := Conf_Elem;
- Conf_List := Conf_Elem.Next;
-
- if Conf_List = Nil_String then
-
- -- If it is the last element in the list, connect to
- -- first element of user list, and we are done.
-
- New_Elem.Next := User_List;
- Shared.String_Elements.Table (New_List) := New_Elem;
- exit;
-
- else
- -- If it is not the last element in the list, add to
- -- new list.
-
- String_Element_Table.Increment_Last
- (Shared.String_Elements);
- New_Elem.Next :=
- String_Element_Table.Last (Shared.String_Elements);
- Shared.String_Elements.Table (New_List) := New_Elem;
- New_List := New_Elem.Next;
- end if;
- end loop;
- end;
- end if;
- end if;
-
- Conf_Attr_Id := Conf_Attr.Next;
- User_Attr_Id := User_Attr.Next;
- end loop;
-
- Conf_Array_Id := Conf_Decl.Arrays;
- while Conf_Array_Id /= No_Array loop
- Conf_Array := Shared.Arrays.Table (Conf_Array_Id);
-
- User_Array_Id := User_Decl.Arrays;
- while User_Array_Id /= No_Array loop
- User_Array := Shared.Arrays.Table (User_Array_Id);
- exit when User_Array.Name = Conf_Array.Name;
- User_Array_Id := User_Array.Next;
- end loop;
-
- -- If this associative array does not exist in the user project file,
- -- do a shallow copy of the full associative array.
-
- if User_Array_Id = No_Array then
- Array_Table.Increment_Last (Shared.Arrays);
- User_Array := Conf_Array;
- User_Array.Next := User_Decl.Arrays;
- User_Decl.Arrays := Array_Table.Last (Shared.Arrays);
- Shared.Arrays.Table (User_Decl.Arrays) := User_Array;
-
- -- Otherwise, check each array element
-
- else
- Conf_Array_Elem_Id := Conf_Array.Value;
- while Conf_Array_Elem_Id /= No_Array_Element loop
- Conf_Array_Elem :=
- Shared.Array_Elements.Table (Conf_Array_Elem_Id);
-
- User_Array_Elem_Id := User_Array.Value;
- while User_Array_Elem_Id /= No_Array_Element loop
- User_Array_Elem :=
- Shared.Array_Elements.Table (User_Array_Elem_Id);
- exit when User_Array_Elem.Index = Conf_Array_Elem.Index;
- User_Array_Elem_Id := User_Array_Elem.Next;
- end loop;
-
- -- If the array element doesn't exist in the user array, insert
- -- a shallow copy of the conf array element in the user array.
-
- if User_Array_Elem_Id = No_Array_Element then
- Array_Element_Table.Increment_Last (Shared.Array_Elements);
- User_Array_Elem := Conf_Array_Elem;
- User_Array_Elem.Next := User_Array.Value;
- User_Array.Value :=
- Array_Element_Table.Last (Shared.Array_Elements);
- Shared.Array_Elements.Table (User_Array.Value) :=
- User_Array_Elem;
- Shared.Arrays.Table (User_Array_Id) := User_Array;
-
- -- Otherwise, if the value is a string list, prepend the conf
- -- array element value to the array element.
-
- elsif Conf_Array_Elem.Value.Kind = List then
- Conf_List := Conf_Array_Elem.Value.Values;
-
- if Conf_List /= Nil_String then
- declare
- Link : constant String_List_Id :=
- User_Array_Elem.Value.Values;
- Previous : String_List_Id := Nil_String;
- Next : String_List_Id;
-
- begin
- loop
- Conf_List_Elem :=
- Shared.String_Elements.Table (Conf_List);
- String_Element_Table.Increment_Last
- (Shared.String_Elements);
- Next :=
- String_Element_Table.Last
- (Shared.String_Elements);
- Shared.String_Elements.Table (Next) :=
- Conf_List_Elem;
-
- if Previous = Nil_String then
- User_Array_Elem.Value.Values := Next;
- Shared.Array_Elements.Table
- (User_Array_Elem_Id) := User_Array_Elem;
-
- else
- Shared.String_Elements.Table
- (Previous).Next := Next;
- end if;
-
- Previous := Next;
-
- Conf_List := Conf_List_Elem.Next;
-
- if Conf_List = Nil_String then
- Shared.String_Elements.Table (Previous).Next :=
- Link;
- exit;
- end if;
- end loop;
- end;
- end if;
- end if;
-
- Conf_Array_Elem_Id := Conf_Array_Elem.Next;
- end loop;
- end if;
-
- Conf_Array_Id := Conf_Array.Next;
- end loop;
- end Add_Attributes;
-
------------------------------------
-- Add_Default_GNAT_Naming_Scheme --
------------------------------------
@@ -464,6 +241,235 @@ package body Prj.Conf is
(Config_File : Prj.Project_Id;
Project_Tree : Prj.Project_Tree_Ref)
is
+ procedure Add_Attributes
+ (Project_Tree : Project_Tree_Ref;
+ Conf_Decl : Declarations;
+ User_Decl : in out Declarations);
+ -- Process the attributes in the config declarations. For
+ -- single string values, if the attribute is not declared in
+ -- the user declarations, declare it with the value in the
+ -- config declarations. For string list values, prepend the
+ -- value in the user declarations with the value in the config
+ -- declarations.
+
+ --------------------
+ -- Add_Attributes --
+ --------------------
+
+ procedure Add_Attributes
+ (Project_Tree : Project_Tree_Ref;
+ Conf_Decl : Declarations;
+ User_Decl : in out Declarations)
+ is
+ Shared : constant Shared_Project_Tree_Data_Access :=
+ Project_Tree.Shared;
+ Conf_Attr_Id : Variable_Id;
+ Conf_Attr : Variable;
+ Conf_Array_Id : Array_Id;
+ Conf_Array : Array_Data;
+ Conf_Array_Elem_Id : Array_Element_Id;
+ Conf_Array_Elem : Array_Element;
+ Conf_List : String_List_Id;
+ Conf_List_Elem : String_Element;
+
+ User_Attr_Id : Variable_Id;
+ User_Attr : Variable;
+ User_Array_Id : Array_Id;
+ User_Array : Array_Data;
+ User_Array_Elem_Id : Array_Element_Id;
+ User_Array_Elem : Array_Element;
+
+ begin
+ Conf_Attr_Id := Conf_Decl.Attributes;
+ User_Attr_Id := User_Decl.Attributes;
+
+ while Conf_Attr_Id /= No_Variable loop
+ Conf_Attr := Shared.Variable_Elements.Table (Conf_Attr_Id);
+ User_Attr := Shared.Variable_Elements.Table (User_Attr_Id);
+
+ if not Conf_Attr.Value.Default then
+ if User_Attr.Value.Default then
+
+ -- No attribute declared in user project file: just copy
+ -- the value of the configuration attribute.
+
+ User_Attr.Value := Conf_Attr.Value;
+ Shared.Variable_Elements.Table (User_Attr_Id) := User_Attr;
+
+ elsif User_Attr.Value.Kind = List
+ and then Conf_Attr.Value.Values /= Nil_String
+ then
+ -- List attribute declared in both the user project and the
+ -- configuration project: prepend the user list with the
+ -- configuration list.
+
+ declare
+ User_List : constant String_List_Id :=
+ User_Attr.Value.Values;
+ Conf_List : String_List_Id := Conf_Attr.Value.Values;
+ Conf_Elem : String_Element;
+ New_List : String_List_Id;
+ New_Elem : String_Element;
+
+ begin
+ -- Create new list
+
+ String_Element_Table.Increment_Last
+ (Shared.String_Elements);
+ New_List :=
+ String_Element_Table.Last (Shared.String_Elements);
+
+ -- Value of attribute is new list
+
+ User_Attr.Value.Values := New_List;
+ Shared.Variable_Elements.Table (User_Attr_Id) :=
+ User_Attr;
+
+ loop
+ -- Get each element of configuration list
+
+ Conf_Elem := Shared.String_Elements.Table (Conf_List);
+ New_Elem := Conf_Elem;
+ Conf_List := Conf_Elem.Next;
+
+ if Conf_List = Nil_String then
+
+ -- If it is the last element in the list, connect
+ -- to first element of user list, and we are done.
+
+ New_Elem.Next := User_List;
+ Shared.String_Elements.Table (New_List) := New_Elem;
+ exit;
+
+ else
+ -- If it is not the last element in the list, add
+ -- to new list.
+
+ String_Element_Table.Increment_Last
+ (Shared.String_Elements);
+ New_Elem.Next := String_Element_Table.Last
+ (Shared.String_Elements);
+ Shared.String_Elements.Table (New_List) := New_Elem;
+ New_List := New_Elem.Next;
+ end if;
+ end loop;
+ end;
+ end if;
+ end if;
+
+ Conf_Attr_Id := Conf_Attr.Next;
+ User_Attr_Id := User_Attr.Next;
+ end loop;
+
+ Conf_Array_Id := Conf_Decl.Arrays;
+ while Conf_Array_Id /= No_Array loop
+ Conf_Array := Shared.Arrays.Table (Conf_Array_Id);
+
+ User_Array_Id := User_Decl.Arrays;
+ while User_Array_Id /= No_Array loop
+ User_Array := Shared.Arrays.Table (User_Array_Id);
+ exit when User_Array.Name = Conf_Array.Name;
+ User_Array_Id := User_Array.Next;
+ end loop;
+
+ -- If this associative array does not exist in the user project
+ -- file, do a shallow copy of the full associative array.
+
+ if User_Array_Id = No_Array then
+ Array_Table.Increment_Last (Shared.Arrays);
+ User_Array := Conf_Array;
+ User_Array.Next := User_Decl.Arrays;
+ User_Decl.Arrays := Array_Table.Last (Shared.Arrays);
+ Shared.Arrays.Table (User_Decl.Arrays) := User_Array;
+
+ -- Otherwise, check each array element
+
+ else
+ Conf_Array_Elem_Id := Conf_Array.Value;
+ while Conf_Array_Elem_Id /= No_Array_Element loop
+ Conf_Array_Elem :=
+ Shared.Array_Elements.Table (Conf_Array_Elem_Id);
+
+ User_Array_Elem_Id := User_Array.Value;
+ while User_Array_Elem_Id /= No_Array_Element loop
+ User_Array_Elem :=
+ Shared.Array_Elements.Table (User_Array_Elem_Id);
+ exit when User_Array_Elem.Index = Conf_Array_Elem.Index;
+ User_Array_Elem_Id := User_Array_Elem.Next;
+ end loop;
+
+ -- If the array element doesn't exist in the user array,
+ -- insert a shallow copy of the conf array element in the
+ -- user array.
+
+ if User_Array_Elem_Id = No_Array_Element then
+ Array_Element_Table.Increment_Last
+ (Shared.Array_Elements);
+ User_Array_Elem := Conf_Array_Elem;
+ User_Array_Elem.Next := User_Array.Value;
+ User_Array.Value :=
+ Array_Element_Table.Last (Shared.Array_Elements);
+ Shared.Array_Elements.Table (User_Array.Value) :=
+ User_Array_Elem;
+ Shared.Arrays.Table (User_Array_Id) := User_Array;
+
+ -- Otherwise, if the value is a string list, prepend the
+ -- conf array element value to the array element.
+
+ elsif Conf_Array_Elem.Value.Kind = List then
+ Conf_List := Conf_Array_Elem.Value.Values;
+
+ if Conf_List /= Nil_String then
+ declare
+ Link : constant String_List_Id :=
+ User_Array_Elem.Value.Values;
+ Previous : String_List_Id := Nil_String;
+ Next : String_List_Id;
+
+ begin
+ loop
+ Conf_List_Elem :=
+ Shared.String_Elements.Table (Conf_List);
+ String_Element_Table.Increment_Last
+ (Shared.String_Elements);
+ Next :=
+ String_Element_Table.Last
+ (Shared.String_Elements);
+ Shared.String_Elements.Table (Next) :=
+ Conf_List_Elem;
+
+ if Previous = Nil_String then
+ User_Array_Elem.Value.Values := Next;
+ Shared.Array_Elements.Table
+ (User_Array_Elem_Id) := User_Array_Elem;
+
+ else
+ Shared.String_Elements.Table
+ (Previous).Next := Next;
+ end if;
+
+ Previous := Next;
+
+ Conf_List := Conf_List_Elem.Next;
+
+ if Conf_List = Nil_String then
+ Shared.String_Elements.Table
+ (Previous).Next := Link;
+ exit;
+ end if;
+ end loop;
+ end;
+ end if;
+ end if;
+
+ Conf_Array_Elem_Id := Conf_Array_Elem.Next;
+ end loop;
+ end if;
+
+ Conf_Array_Id := Conf_Array.Next;
+ end loop;
+ end Add_Attributes;
+
Shared : constant Shared_Project_Tree_Data_Access := Project_Tree.Shared;
Conf_Decl : constant Declarations := Config_File.Decl;
@@ -483,9 +489,9 @@ package body Prj.Conf is
if Proj.Project /= Config_File then
User_Decl := Proj.Project.Decl;
Add_Attributes
- (Project_Tree => Project_Tree,
- Conf_Decl => Conf_Decl,
- User_Decl => User_Decl);
+ (Project_Tree => Project_Tree,
+ Conf_Decl => Conf_Decl,
+ User_Decl => User_Decl);
Conf_Pack_Id := Conf_Decl.Packages;
while Conf_Pack_Id /= No_Package loop
@@ -637,8 +643,8 @@ package body Prj.Conf is
-- Check for switches --config and --RTS in package Builder
procedure Get_Project_Target;
- -- Target_Name is empty, get the specifiedtarget in the project file,
- -- if any.
+ -- If Target_Name is empty, get the specified target in the project
+ -- file, if any.
function Get_Config_Switches return Argument_List_Access;
-- Return the --config switches to use for gprconfig
diff --git a/gcc/ada/prj-nmsc.adb b/gcc/ada/prj-nmsc.adb
index f1538de9922..eb647df1492 100644
--- a/gcc/ada/prj-nmsc.adb
+++ b/gcc/ada/prj-nmsc.adb
@@ -1127,6 +1127,9 @@ package body Prj.Nmsc is
procedure Process_Builder (Attributes : Variable_Id);
-- Process the simple attributes of package Builder
+ procedure Process_Clean (Attributes : Variable_Id);
+ -- Process the simple attributes of package Clean
+
procedure Process_Clean (Arrays : Array_Id);
-- Process the associated array attributes of package Clean
@@ -1256,6 +1259,55 @@ package body Prj.Nmsc is
-- Process_Clean --
-------------------
+ procedure Process_Clean (Attributes : Variable_Id) is
+ Attribute_Id : Variable_Id;
+ Attribute : Variable;
+ List : String_List_Id;
+
+ begin
+ -- Process non associated array attributes from package Clean
+
+ Attribute_Id := Attributes;
+ while Attribute_Id /= No_Variable loop
+ Attribute := Shared.Variable_Elements.Table (Attribute_Id);
+
+ if not Attribute.Value.Default then
+ if Attribute.Name = Name_Artifacts_In_Exec_Dir then
+
+ -- Attribute Artifacts_In_Exec_Dir: the list of file
+ -- names to be cleaned in the exec dir of the main
+ -- project.
+
+ List := Attribute.Value.Values;
+
+ if List /= Nil_String then
+ Put (Into_List =>
+ Project.Config.Artifacts_In_Exec_Dir,
+ From_List => List,
+ In_Tree => Data.Tree);
+ end if;
+
+ elsif Attribute.Name = Name_Artifacts_In_Object_Dir then
+
+ -- Attribute Artifacts_In_Exec_Dir: the list of file
+ -- names to be cleaned in the object dir of every
+ -- project.
+
+ List := Attribute.Value.Values;
+
+ if List /= Nil_String then
+ Put (Into_List =>
+ Project.Config.Artifacts_In_Object_Dir,
+ From_List => List,
+ In_Tree => Data.Tree);
+ end if;
+ end if;
+ end if;
+
+ Attribute_Id := Attribute.Next;
+ end loop;
+ end Process_Clean;
+
procedure Process_Clean (Arrays : Array_Id) is
Current_Array_Id : Array_Id;
Current_Array : Array_Data;
@@ -1932,6 +1984,7 @@ package body Prj.Nmsc is
-- Process attributes of package Clean
+ Process_Clean (Element.Decl.Attributes);
Process_Clean (Element.Decl.Arrays);
when Name_Compiler =>
@@ -2663,7 +2716,8 @@ package body Prj.Nmsc is
Other : Source_Id;
Unit_Found : Boolean;
- Interface_ALIs : String_List_Id := Nil_String;
+ Interface_ALIs : String_List_Id := Nil_String;
+ Other_Interfaces : String_List_Id := Nil_String;
begin
if not Interfaces.Default then
@@ -2718,6 +2772,8 @@ package body Prj.Nmsc is
Other.Declared_In_Interfaces := True;
end if;
+ -- Unit based case
+
if Source.Language.Config.Kind = Unit_Based then
if Source.Kind = Spec
and then Other_Part (Source) /= No_Source
@@ -2741,6 +2797,26 @@ package body Prj.Nmsc is
Interface_ALIs :=
String_Element_Table.Last
(Shared.String_Elements);
+
+ -- File based case
+
+ else
+ String_Element_Table.Increment_Last
+ (Shared.String_Elements);
+
+ Shared.String_Elements.Table
+ (String_Element_Table.Last
+ (Shared.String_Elements)) :=
+ (Value => Name_Id (Source.File),
+ Index => 0,
+ Display_Value => Name_Id (Source.Display_File),
+ Location => No_Location,
+ Flag => False,
+ Next => Other_Interfaces);
+
+ Other_Interfaces :=
+ String_Element_Table.Last
+ (Shared.String_Elements);
end if;
Debug_Output
@@ -2772,6 +2848,7 @@ package body Prj.Nmsc is
Project.Interfaces_Defined := True;
Project.Lib_Interface_ALIs := Interface_ALIs;
+ Project.Other_Interfaces := Other_Interfaces;
elsif Project.Library and then not Library_Interface.Default then
diff --git a/gcc/ada/prj.ads b/gcc/ada/prj.ads
index 66f878688d0..089d0c76c0d 100644
--- a/gcc/ada/prj.ads
+++ b/gcc/ada/prj.ads
@@ -165,8 +165,8 @@ package Prj is
-- The defined kinds of variables
Ignored : constant Variable_Kind;
- -- Used to indicate that a package declaration must be ignored
- -- while processing the project tree (unknown package name).
+ -- Used to indicate that a package declaration must be ignored while
+ -- processing the project tree (unknown package name).
type Variable_Value (Kind : Variable_Kind := Undefined) is record
Project : Project_Id := No_Project;
@@ -262,7 +262,7 @@ package Prj is
Attributes => No_Variable,
Arrays => No_Array,
Packages => No_Package);
- -- Default value of Declarations: indicates that there is no declarations
+ -- Default value of Declarations: used if there are no declarations
type Package_Element is record
Name : Name_Id := No_Name;
@@ -435,8 +435,8 @@ package Prj is
function Other_Part (Source : Source_Id) return Source_Id;
pragma Inline (Other_Part);
- -- Source ID for the other part, if any: for a spec, indicates its body;
- -- for a body, indicates its spec.
+ -- Source ID for the other part, if any: for a spec, returns its body;
+ -- for a body, returns its spec.
No_Source : constant Source_Id := null;
@@ -595,9 +595,9 @@ package Prj is
-- spec pattern.
Config_File_Unique : Boolean := False;
- -- Indicate if the config file specified to the compiler needs to be
- -- unique. If it is unique, then all config files are concatenated into
- -- a temp config file.
+ -- True if the config file specified to the compiler needs to be unique.
+ -- If it is unique, then all config files are concatenated into a temp
+ -- config file.
Binder_Driver : File_Name_Type := No_File;
-- The name of the binder driver for the language, if any
@@ -675,16 +675,26 @@ package Prj is
Clean_Object_Artifacts => No_Name_List,
Clean_Source_Artifacts => No_Name_List);
- -- The following record ???
-
type Language_Data is record
- Name : Name_Id := No_Name;
- Display_Name : Name_Id := No_Name;
- Config : Language_Config := No_Language_Config;
- First_Source : Source_Id := No_Source;
+ Name : Name_Id := No_Name;
+ -- The name of the language in lower case
+
+ Display_Name : Name_Id := No_Name;
+ -- The name of the language, as found in attribute Languages
+
+ Config : Language_Config := No_Language_Config;
+ -- Configuration of the language
+
+ First_Source : Source_Id := No_Source;
+ -- Head of the list of sources of the language in the project
+
Mapping_Files : Mapping_Files_Htable.Instance :=
Mapping_Files_Htable.Nil;
- Next : Language_Ptr := No_Language_Index;
+ -- Hash table containing the mapping of the sources to their path names
+
+ Next : Language_Ptr := No_Language_Index;
+ -- Next language of the project
+
end record;
No_Language_Data : constant Language_Data :=
@@ -755,8 +765,7 @@ package Prj is
-- recursive notation <dir>/** is used in attribute Source_Dirs.
Language : Language_Ptr := No_Language_Index;
- -- Index of the language. This is an index into
- -- Project_Tree.Languages_Data.
+ -- Language of the source
In_Interfaces : Boolean := True;
-- False when the source is not included in interfaces, when attribute
@@ -1133,6 +1142,17 @@ package Prj is
Auto_Init_Supported : Boolean := False;
-- True if automatic initialisation is supported for shared stand-alone
-- libraries.
+
+ -- Cleaning
+
+ Artifacts_In_Exec_Dir : Name_List_Index := No_Name_List;
+ -- List of regexp file names to be cleaned in the exec directory of the
+ -- main project.
+
+ Artifacts_In_Object_Dir : Name_List_Index := No_Name_List;
+ -- List of regexp file names to be cleaned in the object directory of
+ -- all projects.
+
end record;
Default_Project_Config : constant Project_Configuration :=
@@ -1167,7 +1187,9 @@ package Prj is
Lib_Version_Options => No_Name_List,
Symbolic_Link_Supported => False,
Lib_Maj_Min_Id_Supported => False,
- Auto_Init_Supported => False);
+ Auto_Init_Supported => False,
+ Artifacts_In_Exec_Dir => No_Name_List,
+ Artifacts_In_Object_Dir => No_Name_List);
-------------------------
-- Aggregated projects --
@@ -1245,10 +1267,8 @@ package Prj is
---------------
Languages : Language_Ptr := No_Language_Index;
- -- First index of the language data in the project.
- -- This is an index into the project_tree_data.languages_data.
- -- Traversing the list gives access to all the languages supported by
- -- the project.
+ -- First index of the language data in the project. Traversing the list
+ -- gives access to all the languages supported by the project.
--------------
-- Projects --
@@ -1332,19 +1352,20 @@ package Prj is
-- Indicate that this is a Standalone Library Project File
Lib_Interface_ALIs : String_List_Id := Nil_String;
- -- For Standalone Library Project Files, indicate the list of Interface
- -- ALI files.
+ -- For Standalone Library Project Files, list of Interface ALI files.
+
+ Other_Interfaces : String_List_Id := Nil_String;
+ -- List of non unit based sources in attribute Interfaces
Lib_Auto_Init : Boolean := False;
- -- For non static Stand-Alone Library Project Files, indicate if
- -- the library initialisation should be automatic.
+ -- For non static Stand-Alone Library Project Files, True if the library
+ -- initialisation should be automatic.
Symbol_Data : Symbol_Record := No_Symbols;
-- Symbol file name, reference symbol file name, symbol policy
Need_To_Build_Lib : Boolean := False;
- -- Indicates that the library of a Library Project needs to be built or
- -- rebuilt.
+ -- True if the library of a Library Project needs to be built or rebuilt
-------------
-- Sources --
@@ -1402,8 +1423,8 @@ package Prj is
-- The path name of the configuration pragmas file, if any
Config_File_Temp : Boolean := False;
- -- An indication that the configuration pragmas file is a temporary file
- -- that must be deleted at the end.
+ -- True if the configuration pragmas file is a temporary file that must
+ -- be deleted at the end.
Config_Checked : Boolean := False;
-- A flag to avoid checking repetitively the configuration pragmas file
@@ -1959,8 +1980,7 @@ private
-- setting the env var to the same value. When different from No_Path,
-- this indicates that logical names (VMS) or environment variables were
-- created and should be deassigned to avoid polluting the environment
- -- on VMS.
- -- gnatmake only
+ -- on VMS. This is for gnatmake only.
Current_Object_Path_File : Path_Name_Type := No_Path;
-- Current value of project object path file env var. Used to avoid
diff --git a/gcc/ada/projects.texi b/gcc/ada/projects.texi
index 7072e0e6ada..4a6f0533eb4 100644
--- a/gcc/ada/projects.texi
+++ b/gcc/ada/projects.texi
@@ -41,7 +41,7 @@ project files allow you to specify:
@item The directory in which the compiler's output
(@file{ALI} files, object files, tree files, etc.) is to be placed
@item The directory in which the executable programs are to be placed
-@item Switch settings for any of the project-enabled tools;
+@item ^Switch^Switch^ settings for any of the project-enabled tools;
you can apply these settings either globally or to individual compilation units.
@item The source files containing the main subprogram(s) to be built
@item The source programming language(s)
@@ -68,7 +68,7 @@ Subsystems}).
More generally, the Project Manager lets you structure large development
efforts into hierarchical subsystems, where build decisions are delegated
to the subsystem level, and thus different compilation environments
- (switch settings) used for different subsystems.
+ (^switch^switch^ settings) used for different subsystems.
@item You can organize GNAT projects in a hierarchy: a child project
can extend a parent project, inheriting the parent's source files and
optionally overriding any of them with alternative versions
@@ -89,7 +89,7 @@ easily handled:
@itemize @bullet
@item Using a common set of source files and generating object files in different
- directories via different switch settings. It can be used for instance, for
+ directories via different ^switch^switch^ settings. It can be used for instance, for
generating separate sets of object files for debugging and for production.
@item Using a mostly-shared set of source files with different versions of
some units or subunits. It can be used for instance, for grouping and hiding
@@ -174,6 +174,7 @@ detailed later in this documentation. They are summarized here as a reference.
@b{Object_Dir} attribute. In order to store objects in
two or more object directories, the system must be split into
distinct subsystems with their own project file.
+/first exam
@end table
@@ -184,7 +185,8 @@ following examples.
The Ada source files @file{pack.ads}, @file{pack.adb}, and @file{proc.adb} are in
the @file{common/} directory. The file @file{proc.adb} contains an Ada main
subprogram @code{Proc} that @code{with}s package @code{Pack}. We want to compile
-these source files with the switch @option{-O2}, and put the resulting files in
+these source files with the ^switch^switch^
+@option{^-O2^-O2^}, and put the resulting files in
the directory @file{obj/}.
@smallexample
@@ -448,7 +450,8 @@ Its value is the path to the object directory, either absolute or
relative to the directory containing the project file. This
directory must already exist and be readable and writable, although
some tools have a switch to create the directory if needed (See
-the switch @code{-p} for @command{gnatmake} and @command{gprbuild}).
+the switch @code{^-p^/CREATE_MISSING_DIRS^} for @command{gnatmake}
+and @command{gprbuild}).
If the attribute @code{Object_Dir} is not specified, it defaults to
the project directory, that is the directory containing the project file.
@@ -614,13 +617,13 @@ packages would be involved in the build process.
@noindent
Let's first examine the compiler switches. As stated in the initial description
-of the example, we want to compile all files with @option{-O2}. This is a
+of the example, we want to compile all files with @option{^-O2^-O2^}. This is a
compiler switch, although it is usual, on the command line, to pass it to the
builder which then passes it to the compiler. It is recommended to use directly
the right package, which will make the setup easier to understand for other
people.
-Several attributes can be used to specify the switches:
+Several attributes can be used to specify the ^switches^switches^:
@table @asis
@item @b{Default_Switches}:
@@ -633,49 +636,53 @@ Several attributes can be used to specify the switches:
likely be used for each language, and each compiler has its own set of
switches). The value of the attribute is a list of switches.
- In this example, we want to compile all Ada source files with the
- @option{-O2} switch, and the resulting project file is as follows
+ In this example, we want to compile all Ada source files with the ^switch^switch^
+ @option{^-O2^-O2^}, and the resulting project file is as follows
(only the @code{Compiler} package is shown):
@smallexample
@b{package} Compiler @b{is}
- @b{for} Default_Switches ("Ada") @b{use} ("-O2");
+ @b{for} Default_Switches ("Ada") @b{use} ("^-O2^-O2^");
@b{end} Compiler;
@end smallexample
-@item @b{Switches}:
-@cindex @code{Switches}
- in some cases, we might want to use specific switches
+@item @b{^Switches^Switches^}:
+@cindex @code{^Switches^Switches^}
+ in some cases, we might want to use specific ^switches^switches^
for one or more files. For instance, compiling @file{proc.adb} might not be
possible at high level of optimization because of a compiler issue.
- In such a case, the @emph{Switches}
+ In such a case, the @emph{^Switches^Switches^}
attribute (indexed on the file name) can be used and will override the
switches defined by @emph{Default_Switches}. Our project file would
become:
@smallexample
- @b{package} Compiler @b{is}
- @b{for} Default_Switches ("Ada") @b{use} ("-O2");
- @b{for} Switches ("proc.adb") @b{use} ("-O0");
- @b{end} Compiler;
+ package Compiler is
+ for Default_Switches ("Ada")
+ use ("^-O2^-O2^");
+ for ^Switches^Switches^ ("proc.adb")
+ use ("^-O0^-O0^");
+ end Compiler;
@end smallexample
@noindent
- @code{Switches} may take a pattern as an index, such as in:
+ @code{^Switches^Switches^} may take a pattern as an index, such as in:
@smallexample
- @b{package} Compiler @b{is}
- @b{for} Default_Switches ("Ada") @b{use} ("-O2");
- @b{for} Switches ("pkg*") @b{use} ("-O0");
- @b{end} Compiler;
+ package Compiler is
+ for Default_Switches ("Ada")
+ use ("^-O2^-O2^");
+ for ^Switches^Switches^ ("pkg*")
+ use ("^-O0^-O0^");
+ end Compiler;
@end smallexample
@noindent
- Sources @file{pkg.adb} and @file{pkg-child.adb} would be compiled with -O0,
- not -O2.
+ Sources @file{pkg.adb} and @file{pkg-child.adb} would be compiled with ^-O0^-O0^,
+ not ^-O2^-O2^.
@noindent
- @code{Switches} can also be given a language name as index instead of a file
+ @code{^Switches^Switches^} can also be given a language name as index instead of a file
name in which case it has the same semantics as @emph{Default_Switches}.
However, indexes with wild cards are never valid for language name.
@@ -689,7 +696,7 @@ Several attributes can be used to specify the switches:
@end table
The switches for the other tools are defined in a similar manner through the
-@b{Default_Switches} and @b{Switches} attributes, respectively in the
+@b{Default_Switches} and @b{^Switches^Switches^} attributes, respectively in the
@emph{Builder} package (for @command{gnatmake} and @command{gprbuild}),
the @emph{Binder} package (binding Ada executables) and the @emph{Linker}
package (for linking executables).
@@ -816,8 +823,8 @@ project C_Main is
package Compiler is
C_Switches := ("-pedantic");
for Default_Switches ("C") use C_Switches;
- for Default_Switches ("Ada") use ("-gnaty");
- for Switches ("main.c") use C_Switches & ("-g");
+ for Default_Switches ("Ada") use ("^-gnaty^-gnaty^");
+ for ^Switches^Switches^ ("main.c") use C_Switches & ("-g");
end Compiler;
end C_Main;
@end smallexample
@@ -841,7 +848,7 @@ In this specific situation the use of a variable could have been
replaced by a reference to the @code{Default_Switches} attribute:
@smallexample @c projectfile
- for Switches ("c_main.c") use Compiler'Default_Switches ("C") & ("-g");
+ for ^Switches^Switches^ ("c_main.c") use Compiler'Default_Switches ("C") & ("-g");
@end smallexample
@noindent
@@ -1353,10 +1360,12 @@ There are two main approaches to avoiding this duplication:
@smallexample @c projectfile
project Logging is
package Compiler is
- for Switches ("Ada") use ("-O2");
+ for ^Switches^Switches^ ("Ada")
+ use ("^-O2^-O2^");
end Compiler;
package Binder is
- for Switches ("Ada") use ("-E");
+ for ^Switches^Switches^ ("Ada")
+ use ("-E");
end Binder;
end Logging;
@@ -1364,7 +1373,7 @@ There are two main approaches to avoiding this duplication:
project Build is
package Compiler renames Logging.Compiler;
package Binder is
- for Switches ("Ada") use Logging.Binder'Switches ("Ada");
+ for ^Switches^Switches^ ("Ada") use Logging.Binder'Switches ("Ada");
end Binder;
end Build;
@end smallexample
@@ -1394,9 +1403,10 @@ There are two main approaches to avoiding this duplication:
@smallexample @c projectfile
abstract project Shared is
- for Source_Files use (); -- no project
+ for Source_Files use (); -- no sources
package Compiler is
- for Switches ("Ada") use ("-O2");
+ for ^Switches^Switches^ ("Ada")
+ use ("^-O2^-O2^");
end Compiler;
end Shared;
@@ -1482,7 +1492,7 @@ information, when the second will focus on improving code optimization).
Let's enhance our example to support a debug and a release modes.The issue is to
let the user choose what kind of system he is building:
-use @option{-g} as compiler switches in debug mode and @option{-O2}
+use @option{-g} as compiler switches in debug mode and @option{^-O2^-O2^}
in release mode. We will also setup the projects so that we do not share the
same object directory in both modes, otherwise switching from one to the other
might trigger more recompilations than needed or mix objects from the 2 modes.
@@ -1556,9 +1566,11 @@ sections in the project. The following example shows how this can be done:
package Compiler is
case Mode is
when "debug" =>
- for Switches ("Ada") use ("-g");
+ for ^Switches^Switches^ ("Ada")
+ use ("-g");
when "release" =>
- for Switches ("Ada") use ("-O2");
+ for ^Switches^Switches^ ("Ada")
+ use ("^-O2^-O2^");
end case;
end Compiler;
end Build;
@@ -2414,7 +2426,7 @@ building. The syntax looks like
for External ("BUILD") use "PRODUCTION";
package Builder is
- for Switches ("Ada") use ("-q");
+ for ^Switches^Switches^ ("Ada") use ("-q");
end Builder;
end Agg;
@end smallexample
@@ -2681,15 +2693,15 @@ an aggregate project. In this package, only the following attributes
are valid:
@table @asis
-@item @b{Switches}:
-@cindex @code{Switches}
+@item @b{^Switches^Switches^}:
+@cindex @code{^Switches^Switches^}
This attribute gives the list of switches to use for the builder
(@command{gprbuild} or @command{gnatmake}), depending on the language of the
main file. For instance,
@smallexample @c projectfile
-for Switches ("Ada") use ("-d", "-p");
-for Switches ("C") use ("-p");
+for ^Switches^Switches^ ("Ada") use ("-d", "-p");
+for ^Switches^Switches^ ("C") use ("-p");
@end smallexample
These switches are only read from the main aggregate project (the
@@ -2705,8 +2717,8 @@ This attribute gives the list of compiler switches for the various
languages. For instance,
@smallexample @c projectfile
-for Global_Compilation_Switches ("Ada") use ("-O1", "-g");
-for Global_Compilation_Switches ("C") use ("-O2");
+for Global_Compilation_Switches ("Ada") use ("^O1^-O1^", "-g");
+for Global_Compilation_Switches ("C") use ("^-O2^-O2^");
@end smallexample
This attribute is only taken into account in the aggregate project
@@ -2728,34 +2740,39 @@ both depend on C. Here is an extra for all of these projects:
aggregate project Agg is
for Project_Files use ("a.gpr", "b.gpr");
package Builder is
- for Global_Compilation_Switches ("Ada") use ("-O2");
+ for Global_Compilation_Switches ("Ada") use ("^-O2^-O2^");
end Builder;
end Agg;
with "c.gpr";
project A is
package Builder is
- for Global_Compilation_Switches ("Ada") use ("-O1");
+ for Global_Compilation_Switches ("Ada") use ("^-O1^-O1^");
-- ignored
end Builder;
package Compiler is
- for Default_Switches ("Ada") use ("-O1", "-g");
- for Switches ("a_file1.adb") use ("-O0");
+ for Default_Switches ("Ada")
+ use ("^-O1^-O1^", "-g");
+ for ^Switches^Switches^ ("a_file1.adb")
+ use ("^-O0^-O0^");
end Compiler;
end A;
with "c.gpr";
project B is
package Compiler is
- for Default_Switches ("Ada") use ("-O0");
+ for Default_Switches ("Ada") use ("^-O0^-O0^");
end Compiler;
end B;
project C is
package Compiler is
- for Default_Switches ("Ada") use ("-O3", "-gnatn");
- for Switches ("c_file1.adb") use ("-O0", "-g");
+ for Default_Switches ("Ada")
+ use ("^-O3^-O3^",
+ "^-gnatn^-gnatn^");
+ for ^Switches^Switches^ ("c_file1.adb")
+ use ("^-O0^-O0^", "-g");
end Compiler;
end C;
@end smallexample
@@ -2764,13 +2781,13 @@ then the following switches are used:
@itemize @bullet
@item all files from project A except a_file1.adb are compiled
- with "-O2 -g", since the aggregate project has priority.
+ with "^-O2^-O2^ -g", since the aggregate project has priority.
@item the file a_file1.adb is compiled with
- "-O0", since the Compiler.Switches has priority
+ "^-O0^-O0^", since the Compiler.Switches has priority
@item all files from project B are compiled with
- "-O2", since the aggregate project has priority
-@item all files from C are compiled with "-O2 -gnatn", except for
- c_file1.adb which is compiled with "-O0 -g"
+ "^-O2^-O2^", since the aggregate project has priority
+@item all files from C are compiled with "^-O2^-O2^ -gnatn", except for
+ c_file1.adb which is compiled with "^-O0^-O0^ -g"
@end itemize
Even though C is seen through two paths (through A and through
@@ -3141,25 +3158,25 @@ The following packages are currently supported in project files
@item Cross_Reference
This package specifies the options used when calling the library tool
@command{gnatxref} via the @command{gnat} driver. Its attributes
- @b{Default_Switches} and @b{Switches} have the same semantics as for the
+ @b{Default_Switches} and @b{^Switches^Switches^} have the same semantics as for the
package @code{Builder}.
@item Eliminate
This package specifies the options used when calling the tool
@command{gnatelim} via the @command{gnat} driver. Its attributes
- @b{Default_Switches} and @b{Switches} have the same semantics as for the
+ @b{Default_Switches} and @b{^Switches^Switches^} have the same semantics as for the
package @code{Builder}.
@item Finder
This package specifies the options used when calling the search tool
@command{gnatfind} via the @command{gnat} driver. Its attributes
- @b{Default_Switches} and @b{Switches} have the same semantics as for the
+ @b{Default_Switches} and @b{^Switches^Switches^} have the same semantics as for the
package @code{Builder}.
-@item Gnatls
+@item ^Gnatls^Gnatls^
This package the options to use when invoking @command{gnatls} via the
@command{gnat} driver.
-@item Gnatstub
+@item ^Gnatstub^Gnatstub^
This package specifies the options used when calling the tool
@command{gnatstub} via the @command{gnat} driver. Its attributes
- @b{Default_Switches} and @b{Switches} have the same semantics as for the
+ @b{Default_Switches} and @b{^Switches^Switches^} have the same semantics as for the
package @code{Builder}.
@item IDE
This package specifies the options used when starting an integrated
@@ -3173,7 +3190,7 @@ The following packages are currently supported in project files
@item Metrics
This package specifies the options used when calling the tool
@command{gnatmetric} via the @command{gnat} driver. Its attributes
- @b{Default_Switches} and @b{Switches} have the same semantics as for the
+ @b{Default_Switches} and @b{^Switches^Switches^} have the same semantics as for the
package @code{Builder}.
@item Naming
This package specifies the naming conventions that apply
@@ -3184,7 +3201,7 @@ The following packages are currently supported in project files
@item Pretty_Printer
This package specifies the options used when calling the formatting tool
@command{gnatpp} via the @command{gnat} driver. Its attributes
- @b{Default_Switches} and @b{Switches} have the same semantics as for the
+ @b{Default_Switches} and @b{^Switches^Switches^} have the same semantics as for the
package @code{Builder}.
@item Remote
This package is used by @command{gprbuild} to describe how distributed
@@ -3192,7 +3209,7 @@ The following packages are currently supported in project files
@item Stack
This package specifies the options used when calling the tool
@command{gnatstack} via the @command{gnat} driver. Its attributes
- @b{Default_Switches} and @b{Switches} have the same semantics as for the
+ @b{Default_Switches} and @b{^Switches^Switches^} have the same semantics as for the
package @code{Builder}.
@item Synchronize
This package specifies the options used when calling the tool
@@ -3401,11 +3418,14 @@ last separator and the end are components of the string list.
@end smallexample
@noindent
-If the external value is "-O2,-g", the result is ("-O2", "-g").
+If the external value is "^-O2^-O2^,-g",
+the result is ("^-O2^-O2^", "-g").
-If the external value is ",-O2,-g,", the result is also ("-O2", "-g").
+If the external value is ",^-O2^-O2^,-g,",
+the result is also ("^-O2^-O2^", "-g").
-if the external value is "-gnav", the result is ("-gnatv").
+if the external value is "^-gnatv^-gnatv^",
+the result is ("^-gnatv^-gnatv^").
If the external value is ",,", the result is ("").
@@ -3582,9 +3602,11 @@ project MyProj is
package Compiler is
case OS is
when "GNU/Linux" | "Unix" =>
- for Switches ("Ada") use ("-gnath");
+ for ^Switches^Switches^ ("Ada")
+ use ("-gnath");
when "NT" =>
- for Switches ("Ada") use ("-gnatP");
+ for ^Switches^Switches^ ("Ada")
+ use ("^-gnatP^-gnatP^");
when others =>
null;
end case;
@@ -3608,8 +3630,8 @@ end MyProj;
* Package Cross_Reference Attributes::
* Package Eliminate Attributes::
* Package Finder Attributes::
-* Package gnatls Attributes::
-* Package gnatstub Attributes::
+* Package ^gnatls^gnatls^ Attributes::
+* Package ^gnatstub^gnatstub^ Attributes::
* Package IDE Attributes::
* Package Install Attributes::
* Package Linker Attributes::
@@ -3663,8 +3685,9 @@ Here are some examples of attribute declarations:
-- indexed attributes
for Body ("main") use "Main.ada";
- for Switches ("main.ada") use ("-v", "-gnatv");
- for Switches ("main.ada") use Builder'Switches ("main.ada") & "-g";
+ for ^Switches^Switches^ ("main.ada")
+ use ("-v", "^-gnatv^-gnatv^");
+ for ^Switches^Switches^ ("main.ada") use Builder'Switches ("main.ada") & "-g";
-- indexed attributes copy (from package Builder in project Default)
-- The package name must always be specified, even if it is the current
@@ -3962,6 +3985,14 @@ the command line when linking a shared library.
Value is a list of options that are to be used when linking a shared library.
+@item @b{Library_Rpath_Options}: list, indexed, case-insensitive index
+
+Index is a language name. Value is a list of options for an invocation of the
+compiler of the language. This invocation is done for a shared library project
+with sources of the language. The output of the invocation is the path name
+of a shared library file. The directory name is to be put in the run path
+option switch when linking the shared library for the project.
+
@item @b{Library_Src_Dir}: single
Value is the name of the directory where copies of the sources of the
@@ -4158,10 +4189,10 @@ sources of runtime libraries are located.
@item @b{Default_Switches}: list, indexed, case-insensitive index
Index is a language name. Value is the list of switches to be used when binding
-code of the language, if there is no applicable attribute Switches.
+code of the language, if there is no applicable attribute ^Switches^Switches^.
-@item @b{Switches}: list, optional index, indexed, case-insensitive index,
- others allowed
+@item @b{^Switches^Switches^}: list, optional index, indexed,
+ case-insensitive index, others allowed
Index is either a language name or a source file name. Value is the list of
switches to be used when binding code. Index is either the source file name
@@ -4215,7 +4246,7 @@ Index is a language name. Value is the list of builder switches to be used when
building an executable of the language, if there is no applicable attribute
Switches.
-@item @b{Switches}: list, optional index, indexed, case-insensitive index,
+@item @b{^Switches^Switches^}: list, optional index, indexed, case-insensitive index,
others allowed
Index is either a language name or a source file name. Value is the list of
@@ -4261,9 +4292,9 @@ project tree.
Index is a language name. Value is a list of switches to be used when invoking
@code{gnatcheck} for a source of the language, if there is no applicable
-attribute Switches.
+attribute ^Switches^Switches^.
-@item @b{Switches}: list, optional index, indexed, case-insensitive index,
+@item @b{^Switches^Switches^}: list, optional index, indexed, case-insensitive index,
others allowed
Index is a source file name. Value is the list of switches to be used when
@@ -4276,7 +4307,7 @@ invoking @code{gnatcheck} for the source.
@itemize @bullet
-@item @b{Switches}: list
+@item @b{^Switches^Switches^}: list
Value is a list of switches to be used by the cleaning application.
@@ -4292,6 +4323,16 @@ Index is a language names. Value is the list of extensions for file names
derived from source file names that need to be cleaned in the object
directory of the project.
+@item @b{Artifacts_In_Object_Dir}: single
+
+Value is a list of file names expressed as regular expressions that are to be
+deleted by gprclean in the object directory of the project.
+
+@item @b{Artifacts_In_Exec_Dir}: single
+
+Value is list of file names expressed as regular expressions that are to be
+deleted by gprclean in the exec directory of the main project.
+
@end itemize
@node Package Compiler Attributes
@@ -4309,7 +4350,7 @@ Index is a language name. Value is a list of switches to be used when invoking
the compiler for the language for a source of the project, if there is no
applicable attribute Switches.
-@item @b{Switches}: list, optional index, indexed, case-insensitive index,
+@item @b{^Switches^Switches^}: list, optional index, indexed, case-insensitive index,
others allowed
Index is a source file name or a language name. Value is the list of switches
@@ -4543,7 +4584,7 @@ Index is a language name. Value is a list of switches to be used when invoking
@code{gnatxref} for a source of the language, if there is no applicable
attribute Switches.
-@item @b{Switches}: list, optional index, indexed, case-insensitive index,
+@item @b{^Switches^Switches^}: list, optional index, indexed, case-insensitive index,
others allowed
Index is a source file name. Value is the list of switches to be used when
@@ -4562,7 +4603,7 @@ Index is a language name. Value is a list of switches to be used when invoking
@code{gnatelim} for a source of the language, if there is no applicable
attribute Switches.
-@item @b{Switches}: list, optional index, indexed, case-insensitive index,
+@item @b{^Switches^Switches^}: list, optional index, indexed, case-insensitive index,
others allowed
Index is a source file name. Value is the list of switches to be used when
@@ -4581,7 +4622,7 @@ Index is a language name. Value is a list of switches to be used when invoking
@code{gnatfind} for a source of the language, if there is no applicable
attribute Switches.
-@item @b{Switches}: list, optional index, indexed, case-insensitive index,
+@item @b{^Switches^Switches^}: list, optional index, indexed, case-insensitive index,
others allowed
Index is a source file name. Value is the list of switches to be used when
@@ -4589,19 +4630,19 @@ invoking @code{gnatfind} for the source.
@end itemize
-@node Package gnatls Attributes
-@subsubsection Package gnatls Attributes
+@node Package ^gnatls^gnatls^ Attributes
+@subsubsection Package ^gnatls^gnatls^ Attributes
@itemize @bullet
-@item @b{Switches}: list
+@item @b{^Switches^Switches^}: list
Value is a list of switches to be used when invoking @code{gnatls}.
@end itemize
-@node Package gnatstub Attributes
-@subsubsection Package gnatstub Attributes
+@node Package ^gnatstub^gnatstub^ Attributes
+@subsubsection Package ^gnatstub^gnatstub^ Attributes
@itemize @bullet
@@ -4609,9 +4650,9 @@ Value is a list of switches to be used when invoking @code{gnatls}.
Index is a language name. Value is a list of switches to be used when invoking
@code{gnatstub} for a source of the language, if there is no applicable
-attribute Switches.
+attribute ^Switches^Switches^.
-@item @b{Switches}: list, optional index, indexed, case-insensitive index,
+@item @b{^Switches^Switches^}: list, optional index, indexed, case-insensitive index,
others allowed
Index is a source file name. Value is the list of switches to be used when
@@ -4658,16 +4699,18 @@ the handling of switches.
Value is a string that specifies the name of the debugger to be used, such as
gdb, powerpc-wrs-vxworks-gdb or gdb-4.
-@item @b{gnatlist}: single
+@item @b{^gnatlist^gnatlist^}: single
-Value is a string that specifies the name of the @command{gnatls} utility
+Value is a string that specifies the name of the @command{^gnatls^gnatls^} utility
to be used to retrieve information about the predefined path; for example,
-@code{"gnatls"}, @code{"powerpc-wrs-vxworks-gnatls"}.
+@code{"^gnatls^gnatls^"}, @code{"powerpc-wrs-vxworks-gnatls"}.
@item @b{VCS_Kind}: single
Value is a string used to specify the Version Control System (VCS) to be used
-for this project, for example CVS, RCS, ClearCase or Perforce.
+for this project, for example "Subversion", "ClearCase". If the
+value is set to "Auto", the IDE will try to detect the actual VCS used
+on the list of supported ones.
@item @b{VCS_File_Check}: single
@@ -4746,7 +4789,7 @@ Index is a source file name or a language name. Value is the list of switches
to be used at the beginning of the command line when invoking the linker to
build an executable for the source or for its language.
-@item @b{Switches}: list, optional index, indexed, case-insensitive index,
+@item @b{^Switches^Switches^}: list, optional index, indexed, case-insensitive index,
others allowed
Index is a source file name or a language name. Value is the list of switches
@@ -4819,7 +4862,7 @@ Index is a language name. Value is a list of switches to be used when invoking
@code{gnatmetric} for a source of the language, if there is no applicable
attribute Switches.
-@item @b{Switches}: list, optional index, indexed, case-insensitive index,
+@item @b{^Switches^Switches^}: list, optional index, indexed, case-insensitive index,
others allowed
Index is a source file name. Value is the list of switches to be used when
@@ -4907,7 +4950,7 @@ Index is a language name. Value is a list of switches to be used when invoking
@code{gnatpp} for a source of the language, if there is no applicable
attribute Switches.
-@item @b{Switches}: list, optional index, indexed, case-insensitive index,
+@item @b{^Switches^Switches^}: list, optional index, indexed, case-insensitive index,
others allowed
Index is a source file name. Value is the list of switches to be used when
@@ -4936,7 +4979,7 @@ Value is the root directory used by the slave machines.
@itemize @bullet
-@item @b{Switches}: list
+@item @b{^Switches^Switches^}: list
Value is the list of switches to be used when invoking @code{gnatstack}.
@@ -4953,7 +4996,7 @@ Index is a language name. Value is a list of switches to be used when invoking
@code{gnatsync} for a source of the language, if there is no applicable
attribute Switches.
-@item @b{Switches}: list, optional index, indexed, case-insensitive index,
+@item @b{^Switches^Switches^}: list, optional index, indexed, case-insensitive index,
others allowed
Index is a source file name. Value is the list of switches to be used when
diff --git a/gcc/ada/raise-gcc.c b/gcc/ada/raise-gcc.c
index d80456436ec..ca1e84afa9a 100644
--- a/gcc/ada/raise-gcc.c
+++ b/gcc/ada/raise-gcc.c
@@ -87,6 +87,36 @@ extern void __gnat_unhandled_except_handler (_Unwind_Exception *);
#define CXX_EXCEPTION_CLASS 0x474e5543432b2b00ULL
#define GNAT_EXCEPTION_CLASS 0x474e552d41646100ULL
+/* Structure of a C++ exception, represented as a C structure... See
+ unwind-cxx.h for the full definition. */
+
+struct __cxa_exception
+{
+ void *exceptionType;
+ void (*exceptionDestructor)(void *);
+
+ void (*unexpectedHandler)();
+ void (*terminateHandler)();
+
+ struct __cxa_exception *nextException;
+
+ int handlerCount;
+
+#ifdef __ARM_EABI_UNWINDER__
+ struct __cxa_exception* nextPropagatingException;
+
+ int propagationCount;
+#else
+ int handlerSwitchValue;
+ const unsigned char *actionRecord;
+ const unsigned char *languageSpecificData;
+ _Unwind_Ptr catchTemp;
+ void *adjustedPtr;
+#endif
+
+ _Unwind_Exception unwindHeader;
+};
+
/* --------------------------------------------------------------
-- The DB stuff below is there for debugging purposes only. --
-------------------------------------------------------------- */
@@ -812,22 +842,32 @@ get_call_site_action_for (_Unwind_Ptr ip,
#define Is_Handled_By_Others __gnat_is_handled_by_others
#define Language_For __gnat_language_for
-#define Import_Code_For __gnat_import_code_for
+#define Foreign_Data_For __gnat_foreign_data_for
#define EID_For __gnat_eid_for
extern bool Is_Handled_By_Others (_Unwind_Ptr eid);
extern char Language_For (_Unwind_Ptr eid);
-extern Exception_Code Import_Code_For (_Unwind_Ptr eid);
+extern void *Foreign_Data_For (_Unwind_Ptr eid);
extern Exception_Id EID_For (_GNAT_Exception * e);
+#define Foreign_Exception system__exceptions__foreign_exception
+extern struct Exception_Data Foreign_Exception;
+
+#ifdef VMS
+#define Non_Ada_Error system__aux_dec__non_ada_error
+extern struct Exception_Data Non_Ada_Error;
+#endif
+
static enum action_kind
is_handled_by (_Unwind_Ptr choice, _GNAT_Exception * propagated_exception)
{
+ /* All others choice match everything. */
if (choice == GNAT_ALL_OTHERS)
return handler;
+ /* GNAT exception occurrence. */
if (propagated_exception->common.exception_class == GNAT_EXCEPTION_CLASS)
{
/* Pointer to the GNAT exception data corresponding to the propagated
@@ -845,6 +885,7 @@ is_handled_by (_Unwind_Ptr choice, _GNAT_Exception * propagated_exception)
if (choice == E || (choice == GNAT_OTHERS && Is_Handled_By_Others (E)))
return handler;
+#ifdef VMS
/* In addition, on OpenVMS, Non_Ada_Error matches VMS exceptions, and we
may have different exception data pointers that should match for the
same condition code, if both an export and an import have been
@@ -852,29 +893,41 @@ is_handled_by (_Unwind_Ptr choice, _GNAT_Exception * propagated_exception)
occurrence are expected to have been masked off regarding severity
bits already (at registration time for the former and from within the
low level exception vector for the latter). */
-#ifdef VMS
-# define Non_Ada_Error system__aux_dec__non_ada_error
- extern struct Exception_Data Non_Ada_Error;
-
if ((Language_For (E) == 'V'
&& choice != GNAT_OTHERS
&& ((Language_For (choice) == 'V'
- && Import_Code_For (choice) != 0
- && Import_Code_For (choice) == Import_Code_For (E))
+ && Foreign_Data_For (choice) != 0
+ && Foreign_Data_For (choice) == Foreign_Data_For (E))
|| choice == (_Unwind_Ptr)&Non_Ada_Error)))
return handler;
#endif
+
+ /* Otherwise, it doesn't match an Ada choice. */
+ return nothing;
}
- else
- {
-# define Foreign_Exception system__exceptions__foreign_exception
- extern struct Exception_Data Foreign_Exception;
- if (choice == GNAT_ALL_OTHERS
- || choice == GNAT_OTHERS
- || choice == (_Unwind_Ptr) &Foreign_Exception)
+ /* All others and others choice match any foreign exception. */
+ if (choice == GNAT_ALL_OTHERS
+ || choice == GNAT_OTHERS
+ || choice == (_Unwind_Ptr) &Foreign_Exception)
+ return handler;
+
+ /* C++ exception occurrences. */
+ if (propagated_exception->common.exception_class == CXX_EXCEPTION_CLASS
+ && Language_For (choice) == 'C')
+ {
+ void *choice_typeinfo = Foreign_Data_For (choice);
+ void *except_typeinfo =
+ (((struct __cxa_exception *)
+ ((_Unwind_Exception *)propagated_exception + 1)) - 1)->exceptionType;
+
+ /* Typeinfo are directly compared, which might not be correct if they
+ aren't merged. ??? We should call the == operator if this module is
+ compiled in C++. */
+ if (choice_typeinfo == except_typeinfo)
return handler;
}
+
return nothing;
}
@@ -1164,7 +1217,9 @@ PERSONALITY_FUNCTION (version_arg_t version_arg,
setup_to_install
(uw_context, uw_exception, action.landing_pad, action.ttype_filter);
- /* Write current exception, so that it can be retrieved from Ada. */
+ /* Write current exception, so that it can be retrieved from Ada. It was
+ already done during phase 1 (just above), but in between, one or several
+ exceptions may have been raised (in cleanup handlers). */
__gnat_setup_current_excep (uw_exception);
return _URC_INSTALL_CONTEXT;
@@ -1408,3 +1463,10 @@ __gnat_personality_seh0 (PEXCEPTION_RECORD ms_exc, void *this_frame,
ms_disp, __gnat_personality_imp);
}
#endif /* SEH */
+
+#if !defined (__USING_SJLJ_EXCEPTIONS__)
+/* Size of the _Unwind_Exception structure. This is used by g-cppexc to get
+ the offset to the C++ object. */
+
+const int __gnat_unwind_exception_size = sizeof (_Unwind_Exception);
+#endif
diff --git a/gcc/ada/raise.h b/gcc/ada/raise.h
index 57611542350..8f699bc6269 100644
--- a/gcc/ada/raise.h
+++ b/gcc/ada/raise.h
@@ -6,7 +6,7 @@
* *
* C Header File *
* *
- * Copyright (C) 1992-2012, Free Software Foundation, Inc. *
+ * Copyright (C) 1992-2013, Free Software Foundation, Inc. *
* *
* GNAT is free software; you can redistribute it and/or modify it under *
* terms of the GNU General Public License as published by the Free Soft- *
@@ -35,15 +35,14 @@ extern "C" {
/* C counterparts of what System.Standard_Library defines. */
-typedef unsigned Exception_Code;
-
struct Exception_Data
{
char Not_Handled_By_Others;
char Lang;
int Name_Length;
- char *Full_Name, *Htable_Ptr;
- Exception_Code Import_Code;
+ char *Full_Name;
+ char *Htable_Ptr;
+ void *Foreign_Data;
void (*Raise_Hook)(void);
};
diff --git a/gcc/ada/restrict.adb b/gcc/ada/restrict.adb
index ea0f89c43bc..668c4440d8d 100644
--- a/gcc/ada/restrict.adb
+++ b/gcc/ada/restrict.adb
@@ -1406,9 +1406,30 @@ package body Restrict is
is
Msg_Issued : Boolean;
Save_Error_Msg_Sloc : Source_Ptr;
+ Onode : constant Node_Id := Original_Node (N);
begin
- if Force or else Comes_From_Source (Original_Node (N)) then
+ -- Output message if Force set
+
+ if Force
+
+ -- Or if this node comes from source
+
+ or else Comes_From_Source (N)
+
+ -- Or if this is a range node which rewrites a range attribute and
+ -- the range attribute comes from source.
+
+ or else (Nkind (N) = N_Range
+ and then Nkind (Onode) = N_Attribute_Reference
+ and then Attribute_Name (Onode) = Name_Range
+ and then Comes_From_Source (Onode))
+
+ -- Or this is an expression that does not come from source, which is
+ -- a rewriting of an expression that does come from source.
+
+ or else (Nkind (N) in N_Subexpr and then Comes_From_Source (Onode))
+ then
if Restriction_Check_Required (SPARK_05)
and then Is_In_Hidden_Part_In_SPARK (Sloc (N))
then
diff --git a/gcc/ada/rtsfind.adb b/gcc/ada/rtsfind.adb
index 22abb9a581f..75c4c5a5969 100644
--- a/gcc/ada/rtsfind.adb
+++ b/gcc/ada/rtsfind.adb
@@ -760,7 +760,7 @@ package body Rtsfind is
-- a real semantic dependence when the purpose of the limited_with
-- is precisely to avoid such.
- if From_With_Type (Cunit_Entity (U.Unum)) then
+ if From_Limited_With (Cunit_Entity (U.Unum)) then
null;
else
@@ -1120,7 +1120,7 @@ package body Rtsfind is
-- only has a limited view, scan the corresponding list of
-- incomplete types.
- if From_With_Type (U.Entity) then
+ if From_Limited_With (U.Entity) then
Pkg_Ent := First_Entity (Limited_View (U.Entity));
else
Pkg_Ent := First_Entity (U.Entity);
diff --git a/gcc/ada/rtsfind.ads b/gcc/ada/rtsfind.ads
index 88cd740b00a..5ae85f32b96 100644
--- a/gcc/ada/rtsfind.ads
+++ b/gcc/ada/rtsfind.ads
@@ -591,6 +591,7 @@ package Rtsfind is
RE_Root_Stream_Type, -- Ada.Streams
RE_Stream_Element, -- Ada.Streams
+ RE_Stream_Element_Array, -- Ada.Streams
RE_Stream_Element_Offset, -- Ada.Streams
RE_Stream_Access, -- Ada.Streams.Stream_IO
@@ -748,6 +749,7 @@ package Rtsfind is
RE_Uint64, -- System.Atomic_Primitives
RE_AST_Handler, -- System.Aux_DEC
+ RE_Import_Address, -- System.Aux_DEC
RE_Import_Value, -- System.Aux_DEC
RE_No_AST_Handler, -- System.Aux_DEC
RE_Type_Class, -- System.Aux_DEC
@@ -1413,7 +1415,6 @@ package Rtsfind is
RE_Shared_Var_Procs, -- System.Shared_Storage
RE_Abort_Undefer_Direct, -- System.Standard_Library
- RE_Exception_Code, -- System.Standard_Library
RE_Exception_Data_Ptr, -- System.Standard_Library
RE_Integer_Address, -- System.Storage_Elements
@@ -1477,6 +1478,24 @@ package Rtsfind is
RE_W_WC, -- System.Stream_Attributes
RE_W_WWC, -- System.Stream_Attributes
+ RE_Storage_Array_Input, -- System.Strings.Stream_Ops
+ RE_Storage_Array_Input_Blk_IO, -- System.Strings.Stream_Ops
+ RE_Storage_Array_Output, -- System.Strings.Stream_Ops
+ RE_Storage_Array_Output_Blk_IO, -- System.Strings.Stream_Ops
+ RE_Storage_Array_Read, -- System.Strings.Stream_Ops
+ RE_Storage_Array_Read_Blk_IO, -- System.Strings.Stream_Ops
+ RE_Storage_Array_Write, -- System.Strings.Stream_Ops
+ RE_Storage_Array_Write_Blk_IO, -- System.Strings.Stream_Ops
+
+ RE_Stream_Element_Array_Input, -- System.Strings.Stream_Ops
+ RE_Stream_Element_Array_Input_Blk_IO, -- System.Strings.Stream_Ops
+ RE_Stream_Element_Array_Output, -- System.Strings.Stream_Ops
+ RE_Stream_Element_Array_Output_Blk_IO, -- System.Strings.Stream_Ops
+ RE_Stream_Element_Array_Read, -- System.Strings.Stream_Ops
+ RE_Stream_Element_Array_Read_Blk_IO, -- System.Strings.Stream_Ops
+ RE_Stream_Element_Array_Write, -- System.Strings.Stream_Ops
+ RE_Stream_Element_Array_Write_Blk_IO, -- System.Strings.Stream_Ops
+
RE_String_Input, -- System.Strings.Stream_Ops
RE_String_Input_Blk_IO, -- System.Strings.Stream_Ops
RE_String_Output, -- System.Strings.Stream_Ops
@@ -1485,6 +1504,7 @@ package Rtsfind is
RE_String_Read_Blk_IO, -- System.Strings.Stream_Ops
RE_String_Write, -- System.Strings.Stream_Ops
RE_String_Write_Blk_IO, -- System.Strings.Stream_Ops
+
RE_Wide_String_Input, -- System.Strings.Stream_Ops
RE_Wide_String_Input_Blk_IO, -- System.Strings.Stream_Ops
RE_Wide_String_Output, -- System.Strings.Stream_Ops
@@ -1493,6 +1513,7 @@ package Rtsfind is
RE_Wide_String_Read_Blk_IO, -- System.Strings.Stream_Ops
RE_Wide_String_Write, -- System.Strings.Stream_Ops
RE_Wide_String_Write_Blk_IO, -- System.Strings.Stream_Ops
+
RE_Wide_Wide_String_Input, -- System.Strings.Stream_Ops
RE_Wide_Wide_String_Input_Blk_IO, -- System.Strings.Stream_Ops
RE_Wide_Wide_String_Output, -- System.Strings.Stream_Ops
@@ -1844,6 +1865,7 @@ package Rtsfind is
RE_Root_Stream_Type => Ada_Streams,
RE_Stream_Element => Ada_Streams,
+ RE_Stream_Element_Array => Ada_Streams,
RE_Stream_Element_Offset => Ada_Streams,
RE_Stream_Access => Ada_Streams_Stream_IO,
@@ -2001,6 +2023,7 @@ package Rtsfind is
RE_Uint64 => System_Atomic_Primitives,
RE_AST_Handler => System_Aux_DEC,
+ RE_Import_Address => System_Aux_DEC,
RE_Import_Value => System_Aux_DEC,
RE_No_AST_Handler => System_Aux_DEC,
RE_Type_Class => System_Aux_DEC,
@@ -2670,7 +2693,6 @@ package Rtsfind is
RE_Shared_Var_Procs => System_Shared_Storage,
RE_Abort_Undefer_Direct => System_Standard_Library,
- RE_Exception_Code => System_Standard_Library,
RE_Exception_Data_Ptr => System_Standard_Library,
RE_Integer_Address => System_Storage_Elements,
@@ -2734,6 +2756,24 @@ package Rtsfind is
RE_W_WC => System_Stream_Attributes,
RE_W_WWC => System_Stream_Attributes,
+ RE_Storage_Array_Input => System_Strings_Stream_Ops,
+ RE_Storage_Array_Input_Blk_IO => System_Strings_Stream_Ops,
+ RE_Storage_Array_Output => System_Strings_Stream_Ops,
+ RE_Storage_Array_Output_Blk_IO => System_Strings_Stream_Ops,
+ RE_Storage_Array_Read => System_Strings_Stream_Ops,
+ RE_Storage_Array_Read_Blk_IO => System_Strings_Stream_Ops,
+ RE_Storage_Array_Write => System_Strings_Stream_Ops,
+ RE_Storage_Array_Write_Blk_IO => System_Strings_Stream_Ops,
+
+ RE_Stream_Element_Array_Input => System_Strings_Stream_Ops,
+ RE_Stream_Element_Array_Input_Blk_IO => System_Strings_Stream_Ops,
+ RE_Stream_Element_Array_Output => System_Strings_Stream_Ops,
+ RE_Stream_Element_Array_Output_Blk_IO => System_Strings_Stream_Ops,
+ RE_Stream_Element_Array_Read => System_Strings_Stream_Ops,
+ RE_Stream_Element_Array_Read_Blk_IO => System_Strings_Stream_Ops,
+ RE_Stream_Element_Array_Write => System_Strings_Stream_Ops,
+ RE_Stream_Element_Array_Write_Blk_IO => System_Strings_Stream_Ops,
+
RE_String_Input => System_Strings_Stream_Ops,
RE_String_Input_Blk_IO => System_Strings_Stream_Ops,
RE_String_Output => System_Strings_Stream_Ops,
@@ -2742,6 +2782,7 @@ package Rtsfind is
RE_String_Read_Blk_IO => System_Strings_Stream_Ops,
RE_String_Write => System_Strings_Stream_Ops,
RE_String_Write_Blk_IO => System_Strings_Stream_Ops,
+
RE_Wide_String_Input => System_Strings_Stream_Ops,
RE_Wide_String_Input_Blk_IO => System_Strings_Stream_Ops,
RE_Wide_String_Output => System_Strings_Stream_Ops,
@@ -2749,6 +2790,7 @@ package Rtsfind is
RE_Wide_String_Read => System_Strings_Stream_Ops,
RE_Wide_String_Read_Blk_IO => System_Strings_Stream_Ops,
RE_Wide_String_Write => System_Strings_Stream_Ops,
+
RE_Wide_String_Write_Blk_IO => System_Strings_Stream_Ops,
RE_Wide_Wide_String_Input => System_Strings_Stream_Ops,
RE_Wide_Wide_String_Input_Blk_IO => System_Strings_Stream_Ops,
diff --git a/gcc/ada/s-atocou-builtin.adb b/gcc/ada/s-atocou-builtin.adb
index f230721af00..55436aa8388 100644
--- a/gcc/ada/s-atocou-builtin.adb
+++ b/gcc/ada/s-atocou-builtin.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 2011, AdaCore --
+-- Copyright (C) 2011-2013, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -64,14 +64,23 @@ package body System.Atomic_Counters is
procedure Increment (Item : in out Atomic_Counter) is
begin
- -- Note: the use of Unrestricted_Access here is required because we
- -- are obtaining an access-to-volatile pointer to a non-volatile object.
+ -- Note: the use of Unrestricted_Access here is required because we are
+ -- obtaining an access-to-volatile pointer to a non-volatile object.
-- This is not allowed for [Unchecked_]Access, but is safe in this case
-- because we know that no aliases are being created.
Sync_Add_And_Fetch (Item.Value'Unrestricted_Access, 1);
end Increment;
+ ----------------
+ -- Initialize --
+ ----------------
+
+ procedure Initialize (Item : out Atomic_Counter) is
+ begin
+ Item.Value := 1;
+ end Initialize;
+
------------
-- Is_One --
------------
diff --git a/gcc/ada/s-atocou-x86.adb b/gcc/ada/s-atocou-x86.adb
index bd02c35699f..b85b40274fa 100644
--- a/gcc/ada/s-atocou-x86.adb
+++ b/gcc/ada/s-atocou-x86.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 2011, AdaCore --
+-- Copyright (C) 2011-2013, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -74,6 +74,15 @@ package body System.Atomic_Counters is
Volatile => True);
end Increment;
+ ----------------
+ -- Initialize --
+ ----------------
+
+ procedure Initialize (Item : out Atomic_Counter) is
+ begin
+ Item.Value := 1;
+ end Initialize;
+
------------
-- Is_One --
------------
diff --git a/gcc/ada/s-atocou.adb b/gcc/ada/s-atocou.adb
index 8f2ca01b6d9..51cc79ba59d 100644
--- a/gcc/ada/s-atocou.adb
+++ b/gcc/ada/s-atocou.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 2011, AdaCore --
+-- Copyright (C) 2011-2013, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -57,6 +57,15 @@ package body System.Atomic_Counters is
raise Program_Error;
end Increment;
+ ----------------
+ -- Initialize --
+ ----------------
+
+ procedure Initialize (Item : out Atomic_Counter) is
+ begin
+ raise Program_Error;
+ end Initialize;
+
------------
-- Is_One --
------------
diff --git a/gcc/ada/s-atocou.ads b/gcc/ada/s-atocou.ads
index cad18d29896..55d6bf0ece8 100644
--- a/gcc/ada/s-atocou.ads
+++ b/gcc/ada/s-atocou.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 2011, AdaCore --
+-- Copyright (C) 2011-2013, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -65,6 +65,12 @@ package System.Atomic_Counters is
pragma Inline_Always (Is_One);
-- Returns True when value of the atomic counter is one.
+ procedure Initialize (Item : out Atomic_Counter);
+ pragma Inline_Always (Initialize);
+ -- Initialize counter by setting its value to one. This subprogram is
+ -- intended to be used in special cases when counter object can't be
+ -- initialized in standard way.
+
private
type Unsigned_32 is mod 2 ** 32;
diff --git a/gcc/ada/s-exctab.adb b/gcc/ada/s-exctab.adb
index 5f2228ceb1a..afd46e96f7d 100644
--- a/gcc/ada/s-exctab.adb
+++ b/gcc/ada/s-exctab.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1996-2009, Free Software Foundation, Inc. --
+-- Copyright (C) 1996-2013, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -67,15 +67,12 @@ package body System.Exception_Table is
S1 : constant Big_String_Ptr := To_Ptr (A);
S2 : constant Big_String_Ptr := To_Ptr (B);
J : Integer := 1;
-
begin
loop
if S1 (J) /= S2 (J) then
return False;
-
elsif S1 (J) = ASCII.NUL then
return True;
-
else
J := J + 1;
end if;
@@ -180,7 +177,7 @@ package body System.Exception_Table is
Name_Length => Copy'Length,
Full_Name => Dyn_Copy.all'Address,
HTable_Ptr => null,
- Import_Code => 0,
+ Foreign_Data => Null_Address,
Raise_Hook => null);
Register_Exception (Res);
diff --git a/gcc/ada/s-imgint.adb b/gcc/ada/s-imgint.adb
index 12bc0f26f17..88dc5849def 100644
--- a/gcc/ada/s-imgint.adb
+++ b/gcc/ada/s-imgint.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2009, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -42,39 +42,15 @@ package body System.Img_Int is
is
pragma Assert (S'First = 1);
- procedure Set_Digits (T : Integer);
- -- Set digits of absolute value of T, which is zero or negative. We work
- -- with the negative of the value so that the largest negative number is
- -- not a special case.
-
- ----------------
- -- Set_Digits --
- ----------------
-
- procedure Set_Digits (T : Integer) is
- begin
- if T <= -10 then
- Set_Digits (T / 10);
- P := P + 1;
- S (P) := Character'Val (48 - (T rem 10));
- else
- P := P + 1;
- S (P) := Character'Val (48 - T);
- end if;
- end Set_Digits;
-
- -- Start of processing for Image_Integer
-
begin
- P := 1;
-
if V >= 0 then
- S (P) := ' ';
- Set_Digits (-V);
+ S (1) := ' ';
+ P := 1;
else
- S (P) := '-';
- Set_Digits (V);
+ P := 0;
end if;
+
+ Set_Image_Integer (V, S, P);
end Image_Integer;
-----------------------
diff --git a/gcc/ada/s-oscons-tmplt.c b/gcc/ada/s-oscons-tmplt.c
index 096488671e0..2357d61d699 100644
--- a/gcc/ada/s-oscons-tmplt.c
+++ b/gcc/ada/s-oscons-tmplt.c
@@ -7,7 +7,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 2000-2012, Free Software Foundation, Inc. --
+-- Copyright (C) 2000-2013, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -1389,13 +1389,10 @@ CST(Inet_Pton_Linkname, "")
/* Note: On HP-UX, CLOCK_REALTIME is an enum, not a macro. */
-#if defined(CLOCK_REALTIME) || defined (__hpux__)
-# define HAVE_CLOCK_REALTIME
+#if !(defined(CLOCK_REALTIME) || defined (__hpux__))
+# define CLOCK_REALTIME (-1)
#endif
-
-#ifdef HAVE_CLOCK_REALTIME
CND(CLOCK_REALTIME, "System realtime clock")
-#endif
#ifdef CLOCK_MONOTONIC
CND(CLOCK_MONOTONIC, "System monotonic clock")
@@ -1410,19 +1407,19 @@ CND(CLOCK_FASTEST, "Fastest clock")
#endif
CND(CLOCK_THREAD_CPUTIME_ID, "Thread CPU clock")
-#if defined(__APPLE__)
-/* There's no clock_gettime or clock_id's on Darwin, generate a dummy value */
-# define CLOCK_RT_Ada "-1"
-
-#elif defined(__FreeBSD__) || defined(_AIX)
+#if defined(__FreeBSD__) || (defined(_AIX) && defined(_AIXVERSION_530))
/** On these platforms use system provided monotonic clock instead of
** the default CLOCK_REALTIME. We then need to set up cond var attributes
** appropriately (see thread.c).
+ **
+ ** Note that AIX 5.2 does not support CLOCK_MONOTONIC timestamps for
+ ** pthread_cond_timedwait (and does not have pthread_condattr_setclock),
+ ** hence the conditionalization on AIX version above). _AIXVERSION_530
+ ** is defined in AIX 5.3 and more recent versions.
**/
# define CLOCK_RT_Ada "CLOCK_MONOTONIC"
-# define NEED_PTHREAD_CONDATTR_SETCLOCK
-#elif defined(HAVE_CLOCK_REALTIME)
+#else
/* By default use CLOCK_REALTIME */
# define CLOCK_RT_Ada "CLOCK_REALTIME"
#endif
@@ -1435,13 +1432,11 @@ CNS(CLOCK_RT_Ada, "")
/*
-- Sizes of pthread data types
-
*/
#if defined (__APPLE__) || defined (DUMMY)
/*
-- (on Darwin, these are just placeholders)
-
*/
#define PTHREAD_SIZE __PTHREAD_SIZE__
#define PTHREAD_ATTR_SIZE __PTHREAD_ATTR_SIZE__
@@ -1463,7 +1458,9 @@ CNS(CLOCK_RT_Ada, "")
#define PTHREAD_RWLOCK_SIZE (sizeof (pthread_rwlock_t))
#define PTHREAD_ONCE_SIZE (sizeof (pthread_once_t))
#endif
+/*
+*/
CND(PTHREAD_SIZE, "pthread_t")
CND(PTHREAD_ATTR_SIZE, "pthread_attr_t")
CND(PTHREAD_MUTEXATTR_SIZE, "pthread_mutexattr_t")
diff --git a/gcc/ada/s-osinte-aix.adb b/gcc/ada/s-osinte-aix.adb
index bfe03a637b2..2d5f160ca5f 100644
--- a/gcc/ada/s-osinte-aix.adb
+++ b/gcc/ada/s-osinte-aix.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1997-2009, Free Software Foundation, Inc. --
+-- Copyright (C) 1997-2013, Free Software Foundation, Inc. --
-- --
-- GNARL is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -99,48 +99,6 @@ package body System.OS_Interface is
tv_nsec => long (Long_Long_Integer (F * 10#1#E9)));
end To_Timespec;
- -------------------
- -- clock_gettime --
- -------------------
-
- function clock_gettime
- (clock_id : clockid_t;
- tp : access timespec)
- return int
- is
- pragma Unreferenced (clock_id);
-
- -- Older AIX don't have clock_gettime, so use gettimeofday
-
- use Interfaces;
-
- type timeval is array (1 .. 2) of C.long;
-
- procedure timeval_to_duration
- (T : not null access timeval;
- sec : not null access C.long;
- usec : not null access C.long);
- pragma Import (C, timeval_to_duration, "__gnat_timeval_to_duration");
-
- Micro : constant := 10**6;
- sec : aliased C.long;
- usec : aliased C.long;
- TV : aliased timeval;
- Result : int;
-
- function gettimeofday
- (Tv : access timeval;
- Tz : System.Address := System.Null_Address) return int;
- pragma Import (C, gettimeofday, "gettimeofday");
-
- begin
- Result := gettimeofday (TV'Access, System.Null_Address);
- pragma Assert (Result = 0);
- timeval_to_duration (TV'Access, sec'Access, usec'Access);
- tp.all := To_Timespec (Duration (sec) + Duration (usec) / Micro);
- return Result;
- end clock_gettime;
-
-----------------
-- sched_yield --
-----------------
diff --git a/gcc/ada/s-osinte-aix.ads b/gcc/ada/s-osinte-aix.ads
index c89e7296e14..6fce65ffd23 100644
--- a/gcc/ada/s-osinte-aix.ads
+++ b/gcc/ada/s-osinte-aix.ads
@@ -7,7 +7,7 @@
-- S p e c --
-- --
-- Copyright (C) 1991-1994, Florida State University --
--- Copyright (C) 1995-2011, Free Software Foundation, Inc. --
+-- Copyright (C) 1995-2013, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -41,6 +41,7 @@
with Ada.Unchecked_Conversion;
with Interfaces.C;
+with Interfaces.C.Extensions;
package System.OS_Interface is
pragma Preelaborate;
@@ -55,6 +56,7 @@ package System.OS_Interface is
subtype int is Interfaces.C.int;
subtype short is Interfaces.C.short;
subtype long is Interfaces.C.long;
+ subtype long_long is Interfaces.C.Extensions.long_long;
subtype unsigned is Interfaces.C.unsigned;
subtype unsigned_short is Interfaces.C.unsigned_short;
subtype unsigned_long is Interfaces.C.unsigned_long;
@@ -197,11 +199,12 @@ package System.OS_Interface is
type timespec is private;
- type clockid_t is new int;
+ type clockid_t is new long_long;
function clock_gettime
(clock_id : clockid_t;
tp : access timespec) return int;
+ pragma Import (C, clock_gettime, "clock_gettime");
function To_Duration (TS : timespec) return Duration;
pragma Inline (To_Duration);
diff --git a/gcc/ada/s-regpat.adb b/gcc/ada/s-regpat.adb
index cee229ef6b5..88143289e44 100644
--- a/gcc/ada/s-regpat.adb
+++ b/gcc/ada/s-regpat.adb
@@ -7,7 +7,7 @@
-- B o d y --
-- --
-- Copyright (C) 1986 by University of Toronto. --
--- Copyright (C) 1999-2011, AdaCore --
+-- Copyright (C) 1999-2013, AdaCore --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -921,7 +921,7 @@ package body System.Regpat is
Link_Tail (IP, Ender);
- if Have_Branch and then Emit_Ptr <= PM.Size then
+ if Have_Branch and then Emit_Ptr <= PM.Size + 1 then
-- Hook the tails of the branches to the closing node
diff --git a/gcc/ada/s-stalib.ads b/gcc/ada/s-stalib.ads
index f9a28e08017..6658afbae31 100644
--- a/gcc/ada/s-stalib.ads
+++ b/gcc/ada/s-stalib.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 1992-2011, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -74,26 +74,6 @@ package System.Standard_Library is
function To_Ptr is
new Ada.Unchecked_Conversion (System.Address, Big_String_Ptr);
- ---------------------------------------------
- -- Type For Enumeration Image Index Tables --
- ---------------------------------------------
-
- -- Note: these types are declared at the start of this unit, since
- -- they must appear before any enumeration types declared in this
- -- unit. Note that the spec of system is already elaborated at
- -- this point (since we are a child of system), which means that
- -- enumeration types in package System cannot use these types.
-
- type Image_Index_Table_8 is
- array (Integer range <>) of Short_Short_Integer;
- type Image_Index_Table_16 is
- array (Integer range <>) of Short_Integer;
- type Image_Index_Table_32 is
- array (Integer range <>) of Integer;
- -- These types are used to generate the index vector used for enumeration
- -- type image tables. See spec of Exp_Imgv in the main GNAT sources for a
- -- full description of the data structures that are used here.
-
-------------------------------------
-- Exception Declarations and Data --
-------------------------------------
@@ -105,20 +85,6 @@ package System.Standard_Library is
type Exception_Data_Ptr is access all Exception_Data;
-- An equivalent of Exception_Id that is public
- type Exception_Code is mod 2 ** Integer'Size;
- -- A scalar value bound to some exception data. Typically used for
- -- imported or exported exceptions on VMS. Having a separate type for this
- -- is useful to enforce consistency throughout the various run-time units
- -- handling such codes, and having it unsigned is the most appropriate
- -- choice for it's currently single use on VMS.
-
- -- ??? The construction in Cstand has no way to access the proper type
- -- node for Exception_Code, and currently uses Standard_Unsigned as a
- -- fallback. The representations shall match, and the size clause below
- -- is aimed at ensuring that.
-
- for Exception_Code'Size use Integer'Size;
-
-- The following record defines the underlying representation of exceptions
-- WARNING! Any changes to this may need to be reflected in the following
@@ -141,6 +107,7 @@ package System.Standard_Library is
-- A character indicating the language raising the exception.
-- Set to "A" for exceptions defined by an Ada program.
-- Set to "V" for imported VMS exceptions.
+ -- Set to "C" for imported C++ exceptions.
Name_Length : Natural;
-- Length of fully expanded name of exception
@@ -154,11 +121,10 @@ package System.Standard_Library is
-- built (by Register_Exception in s-exctab.adb) for converting between
-- identities and names.
- Import_Code : Exception_Code;
- -- Value for imported exceptions. Needed only for the handling of
- -- Import/Export_Exception for the VMS case, but present in all
- -- implementations (we might well extend this mechanism for other
- -- systems in the future).
+ Foreign_Data : Address;
+ -- Data for imported exceptions. This represents the exception code
+ -- for the handling of Import/Export_Exception for the VMS case.
+ -- This represents the address of the RTTI for the C++ case.
Raise_Hook : Raise_Action;
-- This field can be used to place a "hook" on an exception. If the
@@ -189,7 +155,7 @@ package System.Standard_Library is
Name_Length => Constraint_Error_Name'Length,
Full_Name => Constraint_Error_Name'Address,
HTable_Ptr => null,
- Import_Code => 0,
+ Foreign_Data => Null_Address,
Raise_Hook => null);
Numeric_Error_Def : aliased Exception_Data :=
@@ -198,7 +164,7 @@ package System.Standard_Library is
Name_Length => Numeric_Error_Name'Length,
Full_Name => Numeric_Error_Name'Address,
HTable_Ptr => null,
- Import_Code => 0,
+ Foreign_Data => Null_Address,
Raise_Hook => null);
Program_Error_Def : aliased Exception_Data :=
@@ -207,7 +173,7 @@ package System.Standard_Library is
Name_Length => Program_Error_Name'Length,
Full_Name => Program_Error_Name'Address,
HTable_Ptr => null,
- Import_Code => 0,
+ Foreign_Data => Null_Address,
Raise_Hook => null);
Storage_Error_Def : aliased Exception_Data :=
@@ -216,7 +182,7 @@ package System.Standard_Library is
Name_Length => Storage_Error_Name'Length,
Full_Name => Storage_Error_Name'Address,
HTable_Ptr => null,
- Import_Code => 0,
+ Foreign_Data => Null_Address,
Raise_Hook => null);
Tasking_Error_Def : aliased Exception_Data :=
@@ -225,7 +191,7 @@ package System.Standard_Library is
Name_Length => Tasking_Error_Name'Length,
Full_Name => Tasking_Error_Name'Address,
HTable_Ptr => null,
- Import_Code => 0,
+ Foreign_Data => Null_Address,
Raise_Hook => null);
Abort_Signal_Def : aliased Exception_Data :=
@@ -234,7 +200,7 @@ package System.Standard_Library is
Name_Length => Abort_Signal_Name'Length,
Full_Name => Abort_Signal_Name'Address,
HTable_Ptr => null,
- Import_Code => 0,
+ Foreign_Data => Null_Address,
Raise_Hook => null);
pragma Export (C, Constraint_Error_Def, "constraint_error");
diff --git a/gcc/ada/s-stopoo.ads b/gcc/ada/s-stopoo.ads
index e2d66ff747d..d6153acd409 100644
--- a/gcc/ada/s-stopoo.ads
+++ b/gcc/ada/s-stopoo.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 1992-2011, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
-- --
-- This specification is derived from the Ada Reference Manual for use with --
-- GNAT. The copyright notice above, and the license provisions that follow --
@@ -41,6 +41,7 @@ package System.Storage_Pools is
type Root_Storage_Pool is abstract
new Ada.Finalization.Limited_Controlled with private;
+ pragma Preelaborable_Initialization (Root_Storage_Pool);
procedure Allocate
(Pool : in out Root_Storage_Pool;
diff --git a/gcc/ada/s-stratt-xdr.adb b/gcc/ada/s-stratt-xdr.adb
index d63c2514779..ae4c9b37e7c 100644
--- a/gcc/ada/s-stratt-xdr.adb
+++ b/gcc/ada/s-stratt-xdr.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1996-2012, Free Software Foundation, Inc. --
+-- Copyright (C) 1996-2013, Free Software Foundation, Inc. --
-- --
-- GARLIC is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -283,6 +283,10 @@ package body System.Stream_Attributes is
-- Block_IO_OK --
-----------------
+ -- We must inhibit Block_IO, because in XDR mode, each element is output
+ -- according to XDR requirements, which is not at all the same as writing
+ -- the whole array in one block.
+
function Block_IO_OK return Boolean is
begin
return False;
diff --git a/gcc/ada/s-stratt.ads b/gcc/ada/s-stratt.ads
index 498700e06b5..ce1b4f5e124 100644
--- a/gcc/ada/s-stratt.ads
+++ b/gcc/ada/s-stratt.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 1992-2010, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -88,7 +88,6 @@ package System.Stream_Attributes is
-- the first subtype is specified, or where an enumeration representation
-- clause is given, these three types are treated like any other cases
-- of enumeration types, as described above.
- -- for
---------------------
-- Input Functions --
@@ -114,8 +113,8 @@ package System.Stream_Attributes is
function I_SF (Stream : not null access RST) return Short_Float;
function I_SI (Stream : not null access RST) return Short_Integer;
function I_SSI (Stream : not null access RST) return Short_Short_Integer;
- function I_SSU (Stream : not null access RST)
- return UST.Short_Short_Unsigned;
+ function I_SSU (Stream : not null access RST) return
+ UST.Short_Short_Unsigned;
function I_SU (Stream : not null access RST) return UST.Short_Unsigned;
function I_U (Stream : not null access RST) return UST.Unsigned;
function I_WC (Stream : not null access RST) return Wide_Character;
@@ -125,10 +124,10 @@ package System.Stream_Attributes is
-- Output Procedures --
-----------------------
- -- Procedures for S'Write attribute. These procedures are also used
- -- for 'Output, since for elementary types there is no difference
- -- between 'Write and 'Output because there are no discriminants
- -- or bounds to be written.
+ -- Procedures for S'Write attribute. These procedures are also used for
+ -- 'Output, since for elementary types there is no difference between
+ -- 'Write and 'Output because there are no discriminants or bounds to
+ -- be written.
procedure W_AD (Stream : not null access RST; Item : Fat_Pointer);
procedure W_AS (Stream : not null access RST; Item : Thin_Pointer);
@@ -140,17 +139,15 @@ package System.Stream_Attributes is
procedure W_LI (Stream : not null access RST; Item : Long_Integer);
procedure W_LLF (Stream : not null access RST; Item : Long_Long_Float);
procedure W_LLI (Stream : not null access RST; Item : Long_Long_Integer);
- procedure W_LLU (Stream : not null access RST;
- Item : UST.Long_Long_Unsigned);
+ procedure W_LLU (Stream : not null access RST; Item :
+ UST.Long_Long_Unsigned);
procedure W_LU (Stream : not null access RST; Item : UST.Long_Unsigned);
procedure W_SF (Stream : not null access RST; Item : Short_Float);
procedure W_SI (Stream : not null access RST; Item : Short_Integer);
- procedure W_SSI (Stream : not null access RST;
- Item : Short_Short_Integer);
- procedure W_SSU (Stream : not null access RST;
- Item : UST.Short_Short_Unsigned);
- procedure W_SU (Stream : not null access RST;
- Item : UST.Short_Unsigned);
+ procedure W_SSI (Stream : not null access RST; Item : Short_Short_Integer);
+ procedure W_SSU (Stream : not null access RST; Item :
+ UST.Short_Short_Unsigned);
+ procedure W_SU (Stream : not null access RST; Item : UST.Short_Unsigned);
procedure W_U (Stream : not null access RST; Item : UST.Unsigned);
procedure W_WC (Stream : not null access RST; Item : Wide_Character);
procedure W_WWC (Stream : not null access RST; Item : Wide_Wide_Character);
@@ -160,7 +157,7 @@ package System.Stream_Attributes is
-- distributed with GNAT, and s-stratt-xdr.adb, which is based on the XDR
-- standard. Both bodies share the same spec. The role of this function is
-- to indicate whether the current version of System.Stream_Attributes
- -- supports block IO.
+ -- supports block IO. See System.Strings.Stream_Ops (s-ststop) for details.
private
pragma Inline (I_AD);
diff --git a/gcc/ada/s-ststop.adb b/gcc/ada/s-ststop.adb
index d9f8d0f8ed9..f57ff09fa6a 100644
--- a/gcc/ada/s-ststop.adb
+++ b/gcc/ada/s-ststop.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 2008-2010, Free Software Foundation, Inc. --
+-- Copyright (C) 2008-2013, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -35,7 +35,9 @@ with Ada.Streams; use Ada.Streams;
with Ada.Streams.Stream_IO; use Ada.Streams.Stream_IO;
with Ada.Unchecked_Conversion;
-with System.Stream_Attributes; use System;
+with System; use System;
+with System.Storage_Elements; use System.Storage_Elements;
+with System.Stream_Attributes;
package body System.Strings.Stream_Ops is
@@ -46,31 +48,32 @@ package body System.Strings.Stream_Ops is
-- The following package provides an IO framework for strings. Depending
-- on the version of System.Stream_Attributes as well as the size of
- -- formal parameter Character_Type, the package will either utilize block
- -- IO or character-by-character IO.
+ -- formal parameter Element_Type, the package will either utilize block
+ -- IO or element-by-element IO.
generic
- type Character_Type is private;
- type String_Type is array (Positive range <>) of Character_Type;
+ type Element_Type is private;
+ type Index_Type is range <>;
+ type Array_Type is array (Index_Type range <>) of Element_Type;
package Stream_Ops_Internal is
function Input
(Strm : access Root_Stream_Type'Class;
- IO : IO_Kind) return String_Type;
+ IO : IO_Kind) return Array_Type;
procedure Output
(Strm : access Root_Stream_Type'Class;
- Item : String_Type;
+ Item : Array_Type;
IO : IO_Kind);
procedure Read
(Strm : access Root_Stream_Type'Class;
- Item : out String_Type;
+ Item : out Array_Type;
IO : IO_Kind);
procedure Write
(Strm : access Root_Stream_Type'Class;
- Item : String_Type;
+ Item : Array_Type;
IO : IO_Kind);
end Stream_Ops_Internal;
@@ -86,31 +89,36 @@ package body System.Strings.Stream_Ops is
Default_Block_Size : constant := 512 * 8;
- -- Shorthand notation for stream element and character sizes
+ -- Shorthand notation for stream element and element type sizes
- C_Size : constant Integer := Character_Type'Size;
+ ET_Size : constant Integer := Element_Type'Size;
SE_Size : constant Integer := Stream_Element'Size;
- -- The following constants describe the number of stream elements or
- -- characters that can fit into a default block.
+ -- The following constants describe the number of array elements or
+ -- stream elements that can fit into a default block.
+
+ AE_In_Default_Block : constant Index_Type :=
+ Index_Type (Default_Block_Size / ET_Size);
+ -- Number of array elements in a default block
- C_In_Default_Block : constant Integer := Default_Block_Size / C_Size;
SE_In_Default_Block : constant Integer := Default_Block_Size / SE_Size;
+ -- Number of storage elements in a default block
-- Buffer types
subtype Default_Block is Stream_Element_Array
(1 .. Stream_Element_Offset (SE_In_Default_Block));
- subtype String_Block is String_Type (1 .. C_In_Default_Block);
+ subtype Array_Block is
+ Array_Type (Index_Type range 1 .. AE_In_Default_Block);
-- Conversions to and from Default_Block
function To_Default_Block is
- new Ada.Unchecked_Conversion (String_Block, Default_Block);
+ new Ada.Unchecked_Conversion (Array_Block, Default_Block);
- function To_String_Block is
- new Ada.Unchecked_Conversion (Default_Block, String_Block);
+ function To_Array_Block is
+ new Ada.Unchecked_Conversion (Default_Block, Array_Block);
-----------
-- Input --
@@ -118,7 +126,7 @@ package body System.Strings.Stream_Ops is
function Input
(Strm : access Root_Stream_Type'Class;
- IO : IO_Kind) return String_Type
+ IO : IO_Kind) return Array_Type
is
begin
if Strm = null then
@@ -126,23 +134,21 @@ package body System.Strings.Stream_Ops is
end if;
declare
- Low : Positive;
- High : Positive;
+ Low : Index_Type;
+ High : Index_Type;
begin
-- Read the bounds of the string
- Positive'Read (Strm, Low);
- Positive'Read (Strm, High);
+ Index_Type'Read (Strm, Low);
+ Index_Type'Read (Strm, High);
- declare
- Item : String_Type (Low .. High);
+ -- Read the character content of the string
+ declare
+ Item : Array_Type (Low .. High);
begin
- -- Read the character content of the string
-
Read (Strm, Item, IO);
-
return Item;
end;
end;
@@ -154,7 +160,7 @@ package body System.Strings.Stream_Ops is
procedure Output
(Strm : access Root_Stream_Type'Class;
- Item : String_Type;
+ Item : Array_Type;
IO : IO_Kind)
is
begin
@@ -164,8 +170,8 @@ package body System.Strings.Stream_Ops is
-- Write the bounds of the string
- Positive'Write (Strm, Item'First);
- Positive'Write (Strm, Item'Last);
+ Index_Type'Write (Strm, Item'First);
+ Index_Type'Write (Strm, Item'Last);
-- Write the character content of the string
@@ -178,7 +184,7 @@ package body System.Strings.Stream_Ops is
procedure Read
(Strm : access Root_Stream_Type'Class;
- Item : out String_Type;
+ Item : out Array_Type;
IO : IO_Kind)
is
begin
@@ -194,15 +200,13 @@ package body System.Strings.Stream_Ops is
-- Block IO
- if IO = Block_IO
- and then Stream_Attributes.Block_IO_OK
- then
+ if IO = Block_IO and then Stream_Attributes.Block_IO_OK then
declare
-- Determine the size in BITS of the block necessary to contain
-- the whole string.
Block_Size : constant Natural :=
- (Item'Last - Item'First + 1) * C_Size;
+ Integer (Item'Last - Item'First + 1) * ET_Size;
-- Item can be larger than what the default block can store,
-- determine the number of whole reads necessary to read the
@@ -218,8 +222,8 @@ package body System.Strings.Stream_Ops is
-- String indexes
- Low : Positive := Item'First;
- High : Positive := Low + C_In_Default_Block - 1;
+ Low : Index_Type := Item'First;
+ High : Index_Type := Low + AE_In_Default_Block - 1;
-- End of stream error detection
@@ -237,10 +241,10 @@ package body System.Strings.Stream_Ops is
begin
for Counter in 1 .. Blocks loop
Read (Strm.all, Block, Last);
- Item (Low .. High) := To_String_Block (Block);
+ Item (Low .. High) := To_Array_Block (Block);
Low := High + 1;
- High := Low + C_In_Default_Block - 1;
+ High := Low + AE_In_Default_Block - 1;
Sum := Sum + Last;
Last := 0;
end loop;
@@ -254,17 +258,18 @@ package body System.Strings.Stream_Ops is
subtype Rem_Block is Stream_Element_Array
(1 .. Stream_Element_Offset (Rem_Size / SE_Size));
- subtype Rem_String_Block is
- String_Type (1 .. Rem_Size / C_Size);
+ subtype Rem_Array_Block is
+ Array_Type (Index_Type range
+ 1 .. Index_Type (Rem_Size / ET_Size));
- function To_Rem_String_Block is new
- Ada.Unchecked_Conversion (Rem_Block, Rem_String_Block);
+ function To_Rem_Array_Block is new
+ Ada.Unchecked_Conversion (Rem_Block, Rem_Array_Block);
Block : Rem_Block;
begin
Read (Strm.all, Block, Last);
- Item (Low .. Item'Last) := To_Rem_String_Block (Block);
+ Item (Low .. Item'Last) := To_Rem_Array_Block (Block);
Sum := Sum + Last;
end;
@@ -275,7 +280,7 @@ package body System.Strings.Stream_Ops is
-- words, the stream does not contain enough elements to fully
-- populate Item.
- if (Integer (Sum) * SE_Size) / C_Size < Item'Length then
+ if (Integer (Sum) * SE_Size) / ET_Size < Item'Length then
raise End_Error;
end if;
end;
@@ -284,12 +289,11 @@ package body System.Strings.Stream_Ops is
else
declare
- C : Character_Type;
-
+ E : Element_Type;
begin
for Index in Item'First .. Item'Last loop
- Character_Type'Read (Strm, C);
- Item (Index) := C;
+ Element_Type'Read (Strm, E);
+ Item (Index) := E;
end loop;
end;
end if;
@@ -301,7 +305,7 @@ package body System.Strings.Stream_Ops is
procedure Write
(Strm : access Root_Stream_Type'Class;
- Item : String_Type;
+ Item : Array_Type;
IO : IO_Kind)
is
begin
@@ -317,14 +321,12 @@ package body System.Strings.Stream_Ops is
-- Block IO
- if IO = Block_IO
- and then Stream_Attributes.Block_IO_OK
- then
+ if IO = Block_IO and then Stream_Attributes.Block_IO_OK then
declare
-- Determine the size in BITS of the block necessary to contain
-- the whole string.
- Block_Size : constant Natural := Item'Length * C_Size;
+ Block_Size : constant Natural := Item'Length * ET_Size;
-- Item can be larger than what the default block can store,
-- determine the number of whole writes necessary to output the
@@ -340,8 +342,8 @@ package body System.Strings.Stream_Ops is
-- String indexes
- Low : Positive := Item'First;
- High : Positive := Low + C_In_Default_Block - 1;
+ Low : Index_Type := Item'First;
+ High : Index_Type := Low + AE_In_Default_Block - 1;
begin
-- Step 1: If the string is too large, write out individual
@@ -349,9 +351,8 @@ package body System.Strings.Stream_Ops is
for Counter in 1 .. Blocks loop
Write (Strm.all, To_Default_Block (Item (Low .. High)));
-
Low := High + 1;
- High := Low + C_In_Default_Block - 1;
+ High := Low + AE_In_Default_Block - 1;
end loop;
-- Step 2: Write out any remaining elements
@@ -361,11 +362,12 @@ package body System.Strings.Stream_Ops is
subtype Rem_Block is Stream_Element_Array
(1 .. Stream_Element_Offset (Rem_Size / SE_Size));
- subtype Rem_String_Block is
- String_Type (1 .. Rem_Size / C_Size);
+ subtype Rem_Array_Block is
+ Array_Type (Index_Type range
+ 1 .. Index_Type (Rem_Size / ET_Size));
function To_Rem_Block is new
- Ada.Unchecked_Conversion (Rem_String_Block, Rem_Block);
+ Ada.Unchecked_Conversion (Rem_Array_Block, Rem_Block);
begin
Write (Strm.all, To_Rem_Block (Item (Low .. Item'Last)));
@@ -377,28 +379,233 @@ package body System.Strings.Stream_Ops is
else
for Index in Item'First .. Item'Last loop
- Character_Type'Write (Strm, Item (Index));
+ Element_Type'Write (Strm, Item (Index));
end loop;
end if;
end Write;
end Stream_Ops_Internal;
- -- Specific instantiations for all Ada string types
+ -- Specific instantiations for all Ada array types handled
+
+ package Storage_Array_Ops is
+ new Stream_Ops_Internal
+ (Element_Type => Storage_Element,
+ Index_Type => Storage_Offset,
+ Array_Type => Storage_Array);
+
+ package Stream_Element_Array_Ops is
+ new Stream_Ops_Internal
+ (Element_Type => Stream_Element,
+ Index_Type => Stream_Element_Offset,
+ Array_Type => Stream_Element_Array);
package String_Ops is
new Stream_Ops_Internal
- (Character_Type => Character,
- String_Type => String);
+ (Element_Type => Character,
+ Index_Type => Positive,
+ Array_Type => String);
package Wide_String_Ops is
new Stream_Ops_Internal
- (Character_Type => Wide_Character,
- String_Type => Wide_String);
+ (Element_Type => Wide_Character,
+ Index_Type => Positive,
+ Array_Type => Wide_String);
package Wide_Wide_String_Ops is
new Stream_Ops_Internal
- (Character_Type => Wide_Wide_Character,
- String_Type => Wide_Wide_String);
+ (Element_Type => Wide_Wide_Character,
+ Index_Type => Positive,
+ Array_Type => Wide_Wide_String);
+
+ -------------------------
+ -- Storage_Array_Input --
+ -------------------------
+
+ function Storage_Array_Input
+ (Strm : access Ada.Streams.Root_Stream_Type'Class) return Storage_Array
+ is
+ begin
+ return Storage_Array_Ops.Input (Strm, Byte_IO);
+ end Storage_Array_Input;
+
+ --------------------------------
+ -- Storage_Array_Input_Blk_IO --
+ --------------------------------
+
+ function Storage_Array_Input_Blk_IO
+ (Strm : access Ada.Streams.Root_Stream_Type'Class) return Storage_Array
+ is
+ begin
+ return Storage_Array_Ops.Input (Strm, Block_IO);
+ end Storage_Array_Input_Blk_IO;
+
+ --------------------------
+ -- Storage_Array_Output --
+ --------------------------
+
+ procedure Storage_Array_Output
+ (Strm : access Ada.Streams.Root_Stream_Type'Class;
+ Item : Storage_Array)
+ is
+ begin
+ Storage_Array_Ops.Output (Strm, Item, Byte_IO);
+ end Storage_Array_Output;
+
+ ---------------------------------
+ -- Storage_Array_Output_Blk_IO --
+ ---------------------------------
+
+ procedure Storage_Array_Output_Blk_IO
+ (Strm : access Ada.Streams.Root_Stream_Type'Class;
+ Item : Storage_Array)
+ is
+ begin
+ Storage_Array_Ops.Output (Strm, Item, Block_IO);
+ end Storage_Array_Output_Blk_IO;
+
+ ------------------------
+ -- Storage_Array_Read --
+ ------------------------
+
+ procedure Storage_Array_Read
+ (Strm : access Ada.Streams.Root_Stream_Type'Class;
+ Item : out Storage_Array)
+ is
+ begin
+ Storage_Array_Ops.Read (Strm, Item, Byte_IO);
+ end Storage_Array_Read;
+
+ -------------------------------
+ -- Storage_Array_Read_Blk_IO --
+ -------------------------------
+
+ procedure Storage_Array_Read_Blk_IO
+ (Strm : access Ada.Streams.Root_Stream_Type'Class;
+ Item : out Storage_Array)
+ is
+ begin
+ Storage_Array_Ops.Read (Strm, Item, Block_IO);
+ end Storage_Array_Read_Blk_IO;
+
+ -------------------------
+ -- Storage_Array_Write --
+ -------------------------
+
+ procedure Storage_Array_Write
+ (Strm : access Ada.Streams.Root_Stream_Type'Class;
+ Item : Storage_Array)
+ is
+ begin
+ Storage_Array_Ops.Write (Strm, Item, Byte_IO);
+ end Storage_Array_Write;
+
+ --------------------------------
+ -- Storage_Array_Write_Blk_IO --
+ --------------------------------
+
+ procedure Storage_Array_Write_Blk_IO
+ (Strm : access Ada.Streams.Root_Stream_Type'Class;
+ Item : Storage_Array)
+ is
+ begin
+ Storage_Array_Ops.Write (Strm, Item, Block_IO);
+ end Storage_Array_Write_Blk_IO;
+
+ --------------------------------
+ -- Stream_Element_Array_Input --
+ --------------------------------
+
+ function Stream_Element_Array_Input
+ (Strm : access Ada.Streams.Root_Stream_Type'Class)
+ return Stream_Element_Array
+ is
+ begin
+ return Stream_Element_Array_Ops.Input (Strm, Byte_IO);
+ end Stream_Element_Array_Input;
+
+ ---------------------------------------
+ -- Stream_Element_Array_Input_Blk_IO --
+ ---------------------------------------
+
+ function Stream_Element_Array_Input_Blk_IO
+ (Strm : access Ada.Streams.Root_Stream_Type'Class)
+ return Stream_Element_Array
+ is
+ begin
+ return Stream_Element_Array_Ops.Input (Strm, Block_IO);
+ end Stream_Element_Array_Input_Blk_IO;
+
+ ---------------------------------
+ -- Stream_Element_Array_Output --
+ ---------------------------------
+
+ procedure Stream_Element_Array_Output
+ (Strm : access Ada.Streams.Root_Stream_Type'Class;
+ Item : Stream_Element_Array)
+ is
+ begin
+ Stream_Element_Array_Ops.Output (Strm, Item, Byte_IO);
+ end Stream_Element_Array_Output;
+
+ ----------------------------------------
+ -- Stream_Element_Array_Output_Blk_IO --
+ ----------------------------------------
+
+ procedure Stream_Element_Array_Output_Blk_IO
+ (Strm : access Ada.Streams.Root_Stream_Type'Class;
+ Item : Stream_Element_Array)
+ is
+ begin
+ Stream_Element_Array_Ops.Output (Strm, Item, Block_IO);
+ end Stream_Element_Array_Output_Blk_IO;
+
+ -------------------------------
+ -- Stream_Element_Array_Read --
+ -------------------------------
+
+ procedure Stream_Element_Array_Read
+ (Strm : access Ada.Streams.Root_Stream_Type'Class;
+ Item : out Stream_Element_Array)
+ is
+ begin
+ Stream_Element_Array_Ops.Read (Strm, Item, Byte_IO);
+ end Stream_Element_Array_Read;
+
+ --------------------------------------
+ -- Stream_Element_Array_Read_Blk_IO --
+ --------------------------------------
+
+ procedure Stream_Element_Array_Read_Blk_IO
+ (Strm : access Ada.Streams.Root_Stream_Type'Class;
+ Item : out Stream_Element_Array)
+ is
+ begin
+ Stream_Element_Array_Ops.Read (Strm, Item, Block_IO);
+ end Stream_Element_Array_Read_Blk_IO;
+
+ --------------------------------
+ -- Stream_Element_Array_Write --
+ --------------------------------
+
+ procedure Stream_Element_Array_Write
+ (Strm : access Ada.Streams.Root_Stream_Type'Class;
+ Item : Stream_Element_Array)
+ is
+ begin
+ Stream_Element_Array_Ops.Write (Strm, Item, Byte_IO);
+ end Stream_Element_Array_Write;
+
+ ---------------------------------------
+ -- Stream_Element_Array_Write_Blk_IO --
+ ---------------------------------------
+
+ procedure Stream_Element_Array_Write_Blk_IO
+ (Strm : access Ada.Streams.Root_Stream_Type'Class;
+ Item : Stream_Element_Array)
+ is
+ begin
+ Stream_Element_Array_Ops.Write (Strm, Item, Block_IO);
+ end Stream_Element_Array_Write_Blk_IO;
------------------
-- String_Input --
diff --git a/gcc/ada/s-ststop.ads b/gcc/ada/s-ststop.ads
index db7059069b7..a3fb3c6e6b2 100644
--- a/gcc/ada/s-ststop.ads
+++ b/gcc/ada/s-ststop.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 2009, Free Software Foundation, Inc. --
+-- Copyright (C) 2009-2013, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -30,28 +30,119 @@
------------------------------------------------------------------------------
-- This package provides subprogram implementations of stream attributes for
--- the following types:
+-- the following types using a "block IO" approach in which the entire data
+-- item is written in one operation, instead of writing individual characters.
+
+-- Ada.Stream_Element_Array
-- Ada.String
-- Ada.Wide_String
-- Ada.Wide_Wide_String
---
+-- System.Storage_Array
+
+-- Note: this routine is in Ada.Strings because historically it handled only
+-- the string types. It is not worth moving it at this stage.
+
-- The compiler will generate references to the subprograms in this package
-- when expanding stream attributes for the above mentioned types. Example:
---
+
-- String'Output (Some_Stream, Some_String);
---
+
-- will be expanded into:
---
+
-- String_Output (Some_Stream, Some_String);
-- or
-- String_Output_Blk_IO (Some_Stream, Some_String);
+-- String_Output form is used if pragma Restrictions (No_String_Optimziations)
+-- is active, which requires element by element operations. The BLK_IO form
+-- is used if this restriction is not set, allowing block optimization.
+
+-- Note that if System.Stream_Attributes.Block_IO_OK is False, then the BLK_IO
+-- form is treated as equivalent to the normal case, so that the optimization
+-- is inhibited anyway, regardless of the setting of the restriction. This
+-- handles versions of System.Stream_Attributes (in particular the XDR version
+-- found in s-stratt-xdr) which do not permit block io optimization.
+
pragma Compiler_Unit;
with Ada.Streams;
+with System.Storage_Elements;
+
package System.Strings.Stream_Ops is
+ -------------------------------------
+ -- Storage_Array stream operations --
+ -------------------------------------
+
+ function Storage_Array_Input
+ (Strm : access Ada.Streams.Root_Stream_Type'Class)
+ return System.Storage_Elements.Storage_Array;
+
+ function Storage_Array_Input_Blk_IO
+ (Strm : access Ada.Streams.Root_Stream_Type'Class)
+ return System.Storage_Elements.Storage_Array;
+
+ procedure Storage_Array_Output
+ (Strm : access Ada.Streams.Root_Stream_Type'Class;
+ Item : System.Storage_Elements.Storage_Array);
+
+ procedure Storage_Array_Output_Blk_IO
+ (Strm : access Ada.Streams.Root_Stream_Type'Class;
+ Item : System.Storage_Elements.Storage_Array);
+
+ procedure Storage_Array_Read
+ (Strm : access Ada.Streams.Root_Stream_Type'Class;
+ Item : out System.Storage_Elements.Storage_Array);
+
+ procedure Storage_Array_Read_Blk_IO
+ (Strm : access Ada.Streams.Root_Stream_Type'Class;
+ Item : out System.Storage_Elements.Storage_Array);
+
+ procedure Storage_Array_Write
+ (Strm : access Ada.Streams.Root_Stream_Type'Class;
+ Item : System.Storage_Elements.Storage_Array);
+
+ procedure Storage_Array_Write_Blk_IO
+ (Strm : access Ada.Streams.Root_Stream_Type'Class;
+ Item : System.Storage_Elements.Storage_Array);
+
+ --------------------------------------------
+ -- Stream_Element_Array stream operations --
+ --------------------------------------------
+
+ function Stream_Element_Array_Input
+ (Strm : access Ada.Streams.Root_Stream_Type'Class)
+ return Ada.Streams.Stream_Element_Array;
+
+ function Stream_Element_Array_Input_Blk_IO
+ (Strm : access Ada.Streams.Root_Stream_Type'Class)
+ return Ada.Streams.Stream_Element_Array;
+
+ procedure Stream_Element_Array_Output
+ (Strm : access Ada.Streams.Root_Stream_Type'Class;
+ Item : Ada.Streams.Stream_Element_Array);
+
+ procedure Stream_Element_Array_Output_Blk_IO
+ (Strm : access Ada.Streams.Root_Stream_Type'Class;
+ Item : Ada.Streams.Stream_Element_Array);
+
+ procedure Stream_Element_Array_Read
+ (Strm : access Ada.Streams.Root_Stream_Type'Class;
+ Item : out Ada.Streams.Stream_Element_Array);
+
+ procedure Stream_Element_Array_Read_Blk_IO
+ (Strm : access Ada.Streams.Root_Stream_Type'Class;
+ Item : out Ada.Streams.Stream_Element_Array);
+
+ procedure Stream_Element_Array_Write
+ (Strm : access Ada.Streams.Root_Stream_Type'Class;
+ Item : Ada.Streams.Stream_Element_Array);
+
+ procedure Stream_Element_Array_Write_Blk_IO
+ (Strm : access Ada.Streams.Root_Stream_Type'Class;
+ Item : Ada.Streams.Stream_Element_Array);
+
------------------------------
-- String stream operations --
------------------------------
diff --git a/gcc/ada/s-taprop-posix.adb b/gcc/ada/s-taprop-posix.adb
index 667603b73b7..c7747abd27c 100644
--- a/gcc/ada/s-taprop-posix.adb
+++ b/gcc/ada/s-taprop-posix.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2011, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
-- --
-- GNARL is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -178,6 +178,18 @@ package body System.Task_Primitives.Operations is
pragma Import (C,
GNAT_pthread_condattr_setup, "__gnat_pthread_condattr_setup");
+ procedure Compute_Deadline
+ (Time : Duration;
+ Mode : ST.Delay_Modes;
+ Check_Time : out Duration;
+ Abs_Time : out Duration;
+ Rel_Time : out Duration);
+ -- Helper for Timed_Sleep and Timed_Delay: given a deadline specified by
+ -- Time and Mode, compute the current clock reading (Check_Time), and the
+ -- target absolute and relative clock readings (Abs_Time, Rel_Time). The
+ -- epoch for Time depends on Mode; the epoch for Check_Time and Abs_Time
+ -- is always that of CLOCK_RT_Ada.
+
-------------------
-- Abort_Handler --
-------------------
@@ -236,6 +248,67 @@ package body System.Task_Primitives.Operations is
end if;
end Abort_Handler;
+ ----------------------
+ -- Compute_Deadline --
+ ----------------------
+
+ procedure Compute_Deadline
+ (Time : Duration;
+ Mode : ST.Delay_Modes;
+ Check_Time : out Duration;
+ Abs_Time : out Duration;
+ Rel_Time : out Duration)
+ is
+ begin
+ Check_Time := Monotonic_Clock;
+
+ -- Relative deadline
+
+ if Mode = Relative then
+ Abs_Time := Duration'Min (Time, Max_Sensible_Delay) + Check_Time;
+
+ if Relative_Timed_Wait then
+ Rel_Time := Duration'Min (Max_Sensible_Delay, Time);
+ end if;
+
+ pragma Warnings (Off);
+ -- Comparison "OSC.CLOCK_RT_Ada = OSC.CLOCK_REALTIME" is compile
+ -- time known.
+
+ -- Absolute deadline specified using the tasking clock (CLOCK_RT_Ada)
+
+ elsif Mode = Absolute_RT
+ or else OSC.CLOCK_RT_Ada = OSC.CLOCK_REALTIME
+ then
+ pragma Warnings (On);
+ Abs_Time := Duration'Min (Check_Time + Max_Sensible_Delay, Time);
+
+ if Relative_Timed_Wait then
+ Rel_Time := Duration'Min (Max_Sensible_Delay, Time - Check_Time);
+ end if;
+
+ -- Absolute deadline specified using the real-time clock, in the
+ -- case where it is not the same as the tasking clock: compensate for
+ -- difference between clock epochs (Base_Time - Base_Cal_Time).
+
+ else
+ declare
+ Cal_Check_Time : constant Duration :=
+ OS_Primitives.Monotonic_Clock;
+ RT_Time : constant Duration :=
+ Time + Check_Time - Cal_Check_Time;
+ begin
+ Abs_Time :=
+ Duration'Min (Check_Time + Max_Sensible_Delay, RT_Time);
+
+ if Relative_Timed_Wait then
+ Rel_Time :=
+ Duration'Min (Max_Sensible_Delay, RT_Time - Check_Time);
+ end if;
+ end;
+ end if;
+ end Compute_Deadline;
+
-----------------
-- Stack_Guard --
-----------------
@@ -528,10 +601,11 @@ package body System.Task_Primitives.Operations is
is
pragma Unreferenced (Reason);
- Base_Time : constant Duration := Monotonic_Clock;
- Check_Time : Duration := Base_Time;
- Rel_Time : Duration;
+ Base_Time : Duration;
+ Check_Time : Duration;
Abs_Time : Duration;
+ Rel_Time : Duration;
+
Request : aliased timespec;
Result : Interfaces.C.int;
@@ -539,20 +613,13 @@ package body System.Task_Primitives.Operations is
Timedout := True;
Yielded := False;
- if Mode = Relative then
- Abs_Time := Duration'Min (Time, Max_Sensible_Delay) + Check_Time;
-
- if Relative_Timed_Wait then
- Rel_Time := Duration'Min (Max_Sensible_Delay, Time);
- end if;
-
- else
- Abs_Time := Duration'Min (Check_Time + Max_Sensible_Delay, Time);
-
- if Relative_Timed_Wait then
- Rel_Time := Duration'Min (Max_Sensible_Delay, Time - Check_Time);
- end if;
- end if;
+ Compute_Deadline
+ (Time => Time,
+ Mode => Mode,
+ Check_Time => Check_Time,
+ Abs_Time => Abs_Time,
+ Rel_Time => Rel_Time);
+ Base_Time := Check_Time;
if Abs_Time > Check_Time then
Request :=
@@ -597,8 +664,8 @@ package body System.Task_Primitives.Operations is
Time : Duration;
Mode : ST.Delay_Modes)
is
- Base_Time : constant Duration := Monotonic_Clock;
- Check_Time : Duration := Base_Time;
+ Base_Time : Duration;
+ Check_Time : Duration;
Abs_Time : Duration;
Rel_Time : Duration;
Request : aliased timespec;
@@ -613,20 +680,13 @@ package body System.Task_Primitives.Operations is
Write_Lock (Self_ID);
- if Mode = Relative then
- Abs_Time := Duration'Min (Time, Max_Sensible_Delay) + Check_Time;
-
- if Relative_Timed_Wait then
- Rel_Time := Duration'Min (Max_Sensible_Delay, Time);
- end if;
-
- else
- Abs_Time := Duration'Min (Check_Time + Max_Sensible_Delay, Time);
-
- if Relative_Timed_Wait then
- Rel_Time := Duration'Min (Max_Sensible_Delay, Time - Check_Time);
- end if;
- end if;
+ Compute_Deadline
+ (Time => Time,
+ Mode => Mode,
+ Check_Time => Check_Time,
+ Abs_Time => Abs_Time,
+ Rel_Time => Rel_Time);
+ Base_Time := Check_Time;
if Abs_Time > Check_Time then
Request :=
diff --git a/gcc/ada/s-valuti.adb b/gcc/ada/s-valuti.adb
index e25f78c4501..ce6db6fecb4 100644
--- a/gcc/ada/s-valuti.adb
+++ b/gcc/ada/s-valuti.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2012, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -134,9 +134,9 @@ package body System.Val_Util is
-- Scan out the exponent value as an unsigned integer. Values larger
-- than (Integer'Last / 10) are simply considered large enough here.
- -- This assumption is correct for all machines we know of (e.g. in
- -- the case of 16 bit integers it allows exponents up to 3276, which
- -- is large enough for the largest floating types in base 2.)
+ -- This assumption is correct for all machines we know of (e.g. in the
+ -- case of 16 bit integers it allows exponents up to 3276, which is
+ -- large enough for the largest floating types in base 2.)
X := 0;
@@ -222,8 +222,8 @@ package body System.Val_Util is
P : Natural := Ptr.all;
begin
- -- Deal with case of null string (all blanks!). As per spec, we
- -- raise constraint error, with Ptr unchanged, and thus > Max.
+ -- Deal with case of null string (all blanks!). As per spec, we raise
+ -- constraint error, with Ptr unchanged, and thus > Max.
if P > Max then
Bad_Value (Str);
@@ -300,16 +300,16 @@ package body System.Val_Util is
begin
P := P + 1;
- -- If underscore is at the end of string, then this is an error and
- -- we raise Constraint_Error, leaving the pointer past the underscore.
- -- This seems a bit strange. It means e.g. that if the field is:
+ -- If underscore is at the end of string, then this is an error and we
+ -- raise Constraint_Error, leaving the pointer past the underscore. This
+ -- seems a bit strange. It means e.g. that if the field is:
-- 345_
- -- that Constraint_Error is raised. You might think that the RM in
- -- this case would scan out the 345 as a valid integer, leaving the
- -- pointer at the underscore, but the ACVC suite clearly requires
- -- an error in this situation (see for example CE3704M).
+ -- that Constraint_Error is raised. You might think that the RM in this
+ -- case would scan out the 345 as a valid integer, leaving the pointer
+ -- at the underscore, but the ACVC suite clearly requires an error in
+ -- this situation (see for example CE3704M).
if P > Max then
Ptr.all := P;
diff --git a/gcc/ada/s-vmexta.adb b/gcc/ada/s-vmexta.adb
index b19e27436ea..1164ff8994f 100644
--- a/gcc/ada/s-vmexta.adb
+++ b/gcc/ada/s-vmexta.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1997-2009, Free Software Foundation, Inc. --
+-- Copyright (C) 1997-2013, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -33,11 +33,10 @@
with System.HTable;
pragma Elaborate_All (System.HTable);
+with System.Storage_Elements; use System.Storage_Elements;
package body System.VMS_Exception_Table is
- use type SSL.Exception_Code;
-
type HTable_Headers is range 1 .. 37;
type Exception_Code_Data;
@@ -47,7 +46,7 @@ package body System.VMS_Exception_Table is
-- Ada exception.
type Exception_Code_Data is record
- Code : SSL.Exception_Code;
+ Code : Exception_Code;
Except : SSL.Exception_Data_Ptr;
HTable_Ptr : Exception_Code_Data_Ptr;
end record;
@@ -59,8 +58,8 @@ package body System.VMS_Exception_Table is
function Get_HT_Link (T : Exception_Code_Data_Ptr)
return Exception_Code_Data_Ptr;
- function Hash (F : SSL.Exception_Code) return HTable_Headers;
- function Get_Key (T : Exception_Code_Data_Ptr) return SSL.Exception_Code;
+ function Hash (F : Exception_Code) return HTable_Headers;
+ function Get_Key (T : Exception_Code_Data_Ptr) return Exception_Code;
package Exception_Code_HTable is new System.HTable.Static_HTable (
Header_Num => HTable_Headers,
@@ -69,7 +68,7 @@ package body System.VMS_Exception_Table is
Null_Ptr => null,
Set_Next => Set_HT_Link,
Next => Get_HT_Link,
- Key => SSL.Exception_Code,
+ Key => Exception_Code,
Get_Key => Get_Key,
Hash => Hash,
Equal => "=");
@@ -79,10 +78,10 @@ package body System.VMS_Exception_Table is
------------------
function Base_Code_In
- (Code : SSL.Exception_Code) return SSL.Exception_Code
+ (Code : Exception_Code) return Exception_Code
is
begin
- return Code and not 2#0111#;
+ return To_Address (To_Integer (Code) and not 2#0111#);
end Base_Code_In;
---------------------
@@ -90,7 +89,7 @@ package body System.VMS_Exception_Table is
---------------------
function Coded_Exception
- (X : SSL.Exception_Code) return SSL.Exception_Data_Ptr
+ (X : Exception_Code) return SSL.Exception_Data_Ptr
is
Res : Exception_Code_Data_Ptr;
@@ -121,7 +120,7 @@ package body System.VMS_Exception_Table is
-------------
function Get_Key (T : Exception_Code_Data_Ptr)
- return SSL.Exception_Code
+ return Exception_Code
is
begin
return T.Code;
@@ -132,13 +131,14 @@ package body System.VMS_Exception_Table is
----------
function Hash
- (F : SSL.Exception_Code) return HTable_Headers
+ (F : Exception_Code) return HTable_Headers
is
- Headers_Magnitude : constant SSL.Exception_Code :=
- SSL.Exception_Code (HTable_Headers'Last - HTable_Headers'First + 1);
+ Headers_Magnitude : constant Exception_Code :=
+ Exception_Code (HTable_Headers'Last - HTable_Headers'First + 1);
begin
- return HTable_Headers (F mod Headers_Magnitude + 1);
+ return HTable_Headers
+ (To_Address ((To_Integer (F) mod To_Integer (Headers_Magnitude)) + 1));
end Hash;
----------------------------
@@ -146,13 +146,13 @@ package body System.VMS_Exception_Table is
----------------------------
procedure Register_VMS_Exception
- (Code : SSL.Exception_Code;
+ (Code : Exception_Code;
E : SSL.Exception_Data_Ptr)
is
-- We bind the exception data with the base code found in the
-- input value, that is with the severity bits masked off.
- Excode : constant SSL.Exception_Code := Base_Code_In (Code);
+ Excode : constant Exception_Code := Base_Code_In (Code);
begin
-- The exception data registered here is mostly filled prior to this
@@ -165,7 +165,7 @@ package body System.VMS_Exception_Table is
-- routine attempts to match the import codes in this case.
E.Lang := 'V';
- E.Import_Code := Excode;
+ E.Foreign_Data := Excode;
if Exception_Code_HTable.Get (Excode) = null then
Exception_Code_HTable.Set (new Exception_Code_Data'(Excode, E, null));
diff --git a/gcc/ada/s-vmexta.ads b/gcc/ada/s-vmexta.ads
index e19929e1df9..5ad3f3cd373 100644
--- a/gcc/ada/s-vmexta.ads
+++ b/gcc/ada/s-vmexta.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 1997-2009, Free Software Foundation, Inc. --
+-- Copyright (C) 1997-2013, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -29,7 +29,7 @@
-- --
------------------------------------------------------------------------------
--- This package is usually used only on Alpha/VMS systems in the case
+-- This package is usually used only on OpenVMS systems in the case
-- where there is at least one Import/Export exception present.
with System.Standard_Library;
@@ -38,22 +38,30 @@ package System.VMS_Exception_Table is
package SSL renames System.Standard_Library;
+ subtype Exception_Code is System.Address;
+
procedure Register_VMS_Exception
- (Code : SSL.Exception_Code;
+ (Code : Exception_Code;
E : SSL.Exception_Data_Ptr);
- -- Register an exception in the hash table mapping with a VMS
- -- condition code.
+ -- Register an exception in hash table mapping with a VMS condition code.
+ --
+ -- The table is used by exception code (the personnality routine) to detect
+ -- wether a VMS exception (aka condition) is known by the Ada code. In
+ -- that case, the identity of the imported or exported exception is used
+ -- to create the occurrence.
-- LOTS more comments needed here regarding the entire scheme ???
private
- function Base_Code_In (Code : SSL.Exception_Code) return SSL.Exception_Code;
+ -- The following functions are directly called (without import/export) in
+ -- init.c by __gnat_handle_vms_condition.
+
+ function Base_Code_In (Code : Exception_Code) return Exception_Code;
-- Value of Code with the severity bits masked off
- function Coded_Exception (X : SSL.Exception_Code)
+ function Coded_Exception (X : Exception_Code)
return SSL.Exception_Data_Ptr;
- -- Given a VMS condition, find and return it's allocated Ada exception
- -- (called only from init.c).
+ -- Given a VMS condition, find and return its allocated Ada exception
end System.VMS_Exception_Table;
diff --git a/gcc/ada/s-vxwork-arm.ads b/gcc/ada/s-vxwork-arm.ads
index 1aa6670e164..8c4cf7e53e2 100644
--- a/gcc/ada/s-vxwork-arm.ads
+++ b/gcc/ada/s-vxwork-arm.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 1998-2009, Free Software Foundation, Inc. --
+-- Copyright (C) 1998-2013, Free Software Foundation, Inc. --
-- --
-- GNARL is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -31,15 +31,30 @@
-- This is the ARM VxWorks version of this package
+with Interfaces.C;
+
package System.VxWorks is
pragma Preelaborate (System.VxWorks);
+ package IC renames Interfaces.C;
+
-- Floating point context record. ARM version
+ FP_SGPR_NUM_REGS : constant := 32;
+ type Fpr_Sgpr_Array is array (1 .. FP_SGPR_NUM_REGS) of IC.unsigned;
+
-- The record definition below matches what arch/arm/fppArmLib.h says
type FP_CONTEXT is record
- Dummy : Integer;
+ fpsid : IC.unsigned; -- system ID register
+ fpscr : IC.unsigned; -- status and control register
+ fpexc : IC.unsigned; -- exception register
+ fpinst : IC.unsigned; -- instruction register
+ fpinst2 : IC.unsigned; -- instruction register 2
+ mfvfr0 : IC.unsigned; -- media and VFP feature Register 0
+ mfvfr1 : IC.unsigned; -- media and VFP feature Register 1
+ pad : IC.unsigned;
+ vfp_gpr : Fpr_Sgpr_Array;
end record;
for FP_CONTEXT'Alignment use 4;
diff --git a/gcc/ada/scng.adb b/gcc/ada/scng.adb
index e05d1d692ad..ef3d665554a 100644
--- a/gcc/ada/scng.adb
+++ b/gcc/ada/scng.adb
@@ -592,14 +592,12 @@ package body Scng is
-- which the digit was expected on input, and is unchanged on return.
procedure Scan_Integer;
- -- Procedure to scan integer literal. On entry, Scan_Ptr points to a
- -- digit, on exit Scan_Ptr points past the last character of the
- -- integer.
+ -- Scan integer literal. On entry, Scan_Ptr points to a digit, on
+ -- exit Scan_Ptr points past the last character of the integer.
--
-- For each digit encountered, UI_Int_Value is multiplied by 10, and
- -- the value of the digit added to the result. In addition, the
- -- value in Scale is decremented by one for each actual digit
- -- scanned.
+ -- the value of the digit added to the result. In addition, the value
+ -- in Scale is decremented by one for each actual digit scanned.
--------------------------
-- Error_Digit_Expected --
diff --git a/gcc/ada/scos.ads b/gcc/ada/scos.ads
index dc4248e12d9..6efc5cebcc9 100644
--- a/gcc/ada/scos.ads
+++ b/gcc/ada/scos.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 2009-2012, Free Software Foundation, Inc. --
+-- Copyright (C) 2009-2013, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -367,11 +367,12 @@ package SCOs is
Last : Boolean := False;
Pragma_Sloc : Source_Ptr := No_Location;
- -- For the statement SCO for a pragma, or for any expression SCO nested
- -- in a pragma Debug/Assert/PPC, location of PRAGMA token (used for
- -- control of SCO output, value not recorded in ALI file). For the
- -- decision SCO for an aspect, or for any expression SCO nested in an
- -- aspect, location of aspect identifier token (likewise).
+ -- For the decision SCO of a pragma, or for the decision SCO of any
+ -- expression nested in a pragma Debug/Assert/PPC, location of PRAGMA
+ -- token (used for control of SCO output, value not recorded in ALI
+ -- file). Similarly, for the decision SCO of an aspect, or for the
+ -- decision SCO of any expression nested in an aspect, location of
+ -- aspect identifier token.
Pragma_Aspect_Name : Name_Id := No_Name;
-- For the SCO for a pragma/aspect, gives the pragma/apsect name
diff --git a/gcc/ada/sem.adb b/gcc/ada/sem.adb
index 4249ad95595..6094b14f438 100644
--- a/gcc/ada/sem.adb
+++ b/gcc/ada/sem.adb
@@ -242,6 +242,9 @@ package body Sem is
when N_Freeze_Entity =>
Analyze_Freeze_Entity (N);
+ when N_Freeze_Generic_Entity =>
+ Analyze_Freeze_Generic_Entity (N);
+
when N_Full_Type_Declaration =>
Analyze_Full_Type_Declaration (N);
diff --git a/gcc/ada/sem_aggr.adb b/gcc/ada/sem_aggr.adb
index 9d7d7b7e4b1..5aec38a32d0 100644
--- a/gcc/ada/sem_aggr.adb
+++ b/gcc/ada/sem_aggr.adb
@@ -65,23 +65,35 @@ with Uintp; use Uintp;
package body Sem_Aggr is
type Case_Bounds is record
- Choice_Lo : Node_Id;
- Choice_Hi : Node_Id;
- Choice_Node : Node_Id;
+ Lo : Node_Id;
+ -- Low bound of choice. Once we sort the Case_Table, then entries
+ -- will be in order of ascending Choice_Lo values.
+
+ Hi : Node_Id;
+ -- High Bound of choice. The sort does not pay any attention to the
+ -- high bound, so choices 1 .. 4 and 1 .. 5 could be in either order.
+
+ Highest : Uint;
+ -- If there are duplicates or missing entries, then in the sorted
+ -- table, this records the highest value among Choice_Hi values
+ -- seen so far, including this entry.
+
+ Choice : Node_Id;
+ -- The node of the choice
end record;
type Case_Table_Type is array (Nat range <>) of Case_Bounds;
- -- Table type used by Check_Case_Choices procedure
+ -- Table type used by Check_Case_Choices procedure. Entry zero is not
+ -- used (reserved for the sort). Real entries start at one.
-----------------------
-- Local Subprograms --
-----------------------
procedure Sort_Case_Table (Case_Table : in out Case_Table_Type);
- -- Sort the Case Table using the Lower Bound of each Choice as the key.
- -- A simple insertion sort is used since the number of choices in a case
- -- statement of variant part will usually be small and probably in near
- -- sorted order.
+ -- Sort the Case Table using the Lower Bound of each Choice as the key. A
+ -- simple insertion sort is used since the choices in a case statement will
+ -- usually be in near sorted order.
procedure Check_Can_Never_Be_Null (Typ : Entity_Id; Expr : Node_Id);
-- Ada 2005 (AI-231): Check bad usage of null for a component for which
@@ -1723,9 +1735,9 @@ package body Sem_Aggr is
-- Variables local to Resolve_Array_Aggregate
- Assoc : Node_Id;
- Choice : Node_Id;
- Expr : Node_Id;
+ Assoc : Node_Id;
+ Choice : Node_Id;
+ Expr : Node_Id;
Discard : Node_Id;
pragma Warnings (Off, Discard);
@@ -1900,21 +1912,14 @@ package body Sem_Aggr is
High : Node_Id;
-- Denote the lowest and highest values in an aggregate choice
- Hi_Val : Uint;
- Lo_Val : Uint;
- -- High end of one range and Low end of the next. Should be
- -- contiguous if there is no hole in the list of values.
-
- Missing_Values : Boolean;
- -- Set True if missing index values
-
S_Low : Node_Id := Empty;
S_High : Node_Id := Empty;
-- if a choice in an aggregate is a subtype indication these
-- denote the lowest and highest values of the subtype
- Table : Case_Table_Type (1 .. Case_Table_Size);
- -- Used to sort all the different choice values
+ Table : Case_Table_Type (0 .. Case_Table_Size);
+ -- Used to sort all the different choice values. Entry zero is
+ -- reserved for sorting purposes.
Single_Choice : Boolean;
-- Set to true every time there is a single discrete choice in a
@@ -2026,9 +2031,9 @@ package body Sem_Aggr is
end if;
Nb_Discrete_Choices := Nb_Discrete_Choices + 1;
- Table (Nb_Discrete_Choices).Choice_Lo := Low;
- Table (Nb_Discrete_Choices).Choice_Hi := High;
- Table (Nb_Discrete_Choices).Choice_Node := Choice;
+ Table (Nb_Discrete_Choices).Lo := Low;
+ Table (Nb_Discrete_Choices).Hi := High;
+ Table (Nb_Discrete_Choices).Choice := Choice;
Next (Choice);
@@ -2064,14 +2069,14 @@ package body Sem_Aggr is
-- Resolve_Aggr_Expr to check the rules about
-- dimensionality.
- if not Resolve_Aggr_Expr (Assoc,
- Single_Elmt => Single_Choice)
+ if not Resolve_Aggr_Expr
+ (Assoc, Single_Elmt => Single_Choice)
then
return Failure;
end if;
- elsif not Resolve_Aggr_Expr (Expression (Assoc),
- Single_Elmt => Single_Choice)
+ elsif not Resolve_Aggr_Expr
+ (Expression (Assoc), Single_Elmt => Single_Choice)
then
return Failure;
@@ -2134,87 +2139,207 @@ package body Sem_Aggr is
end loop;
-- If aggregate contains more than one choice then these must be
- -- static. Sort them and check that they are contiguous.
+ -- static. Check for duplicate and missing values.
+
+ -- Note: there is duplicated code here wrt Check_Choice_Set in
+ -- the body of Sem_Case, and it is possible we could just reuse
+ -- that procedure. To be checked ???
if Nb_Discrete_Choices > 1 then
- Sort_Case_Table (Table);
- Missing_Values := False;
+ Check_Choices : declare
+ Choice : Node_Id;
+ -- Location of choice for messages
- Outer : for J in 1 .. Nb_Discrete_Choices - 1 loop
- if Expr_Value (Table (J).Choice_Hi) >=
- Expr_Value (Table (J + 1).Choice_Lo)
- then
- Error_Msg_N
- ("duplicate choice values in array aggregate",
- Table (J).Choice_Node);
- return Failure;
+ Hi_Val : Uint;
+ Lo_Val : Uint;
+ -- High end of one range and Low end of the next. Should be
+ -- contiguous if there is no hole in the list of values.
- elsif not Others_Present then
- Hi_Val := Expr_Value (Table (J).Choice_Hi);
- Lo_Val := Expr_Value (Table (J + 1).Choice_Lo);
+ Lo_Dup : Uint;
+ Hi_Dup : Uint;
+ -- End points of duplicated range
- -- If missing values, output error messages
+ Missing_Or_Duplicates : Boolean := False;
+ -- Set True if missing or duplicate choices found
- if Lo_Val - Hi_Val > 1 then
+ procedure Output_Bad_Choices (Lo, Hi : Uint; C : Node_Id);
+ -- Output continuation message with a representation of the
+ -- bounds (just Lo if Lo = Hi, else Lo .. Hi). C is the
+ -- choice node where the message is to be posted.
- -- Header message if not first missing value
+ ------------------------
+ -- Output_Bad_Choices --
+ ------------------------
- if not Missing_Values then
- Error_Msg_N
- ("missing index value(s) in array aggregate", N);
- Missing_Values := True;
+ procedure Output_Bad_Choices (Lo, Hi : Uint; C : Node_Id) is
+ begin
+ -- Enumeration type case
+
+ if Is_Enumeration_Type (Index_Typ) then
+ Error_Msg_Name_1 :=
+ Chars (Get_Enum_Lit_From_Pos (Index_Typ, Lo, Loc));
+ Error_Msg_Name_2 :=
+ Chars (Get_Enum_Lit_From_Pos (Index_Typ, Hi, Loc));
+
+ if Lo = Hi then
+ Error_Msg_N ("\\ %!", C);
+ else
+ Error_Msg_N ("\\ % .. %!", C);
end if;
- -- Output values of missing indexes
+ -- Integer types case
- Lo_Val := Lo_Val - 1;
- Hi_Val := Hi_Val + 1;
+ else
+ Error_Msg_Uint_1 := Lo;
+ Error_Msg_Uint_2 := Hi;
- -- Enumeration type case
+ if Lo = Hi then
+ Error_Msg_N ("\\ ^!", C);
+ else
+ Error_Msg_N ("\\ ^ .. ^!", C);
+ end if;
+ end if;
+ end Output_Bad_Choices;
- if Is_Enumeration_Type (Index_Typ) then
- Error_Msg_Name_1 :=
- Chars
- (Get_Enum_Lit_From_Pos
- (Index_Typ, Hi_Val, Loc));
+ -- Start of processing for Check_Choices
- if Lo_Val = Hi_Val then
- Error_Msg_N ("\ %", N);
- else
- Error_Msg_Name_2 :=
- Chars
- (Get_Enum_Lit_From_Pos
- (Index_Typ, Lo_Val, Loc));
- Error_Msg_N ("\ % .. %", N);
- end if;
+ begin
+ Sort_Case_Table (Table);
- -- Integer types case
+ -- First we do a quick linear loop to find out if we have
+ -- any duplicates or missing entries (usually we have a
+ -- legal aggregate, so this will get us out quickly).
- else
- Error_Msg_Uint_1 := Hi_Val;
+ for J in 1 .. Nb_Discrete_Choices - 1 loop
+ Hi_Val := Expr_Value (Table (J).Hi);
+ Lo_Val := Expr_Value (Table (J + 1).Lo);
- if Lo_Val = Hi_Val then
- Error_Msg_N ("\ ^", N);
- else
- Error_Msg_Uint_2 := Lo_Val;
- Error_Msg_N ("\ ^ .. ^", N);
- end if;
+ if Lo_Val <= Hi_Val
+ or else (Lo_Val > Hi_Val + 1
+ and then not Others_Present)
+ then
+ Missing_Or_Duplicates := True;
+ exit;
+ end if;
+ end loop;
+
+ -- If we have missing or duplicate entries, first fill in
+ -- the Highest entries to make life easier in the following
+ -- loops to detect bad entries.
+
+ if Missing_Or_Duplicates then
+ Table (1).Highest := Expr_Value (Table (1).Hi);
+
+ for J in 2 .. Nb_Discrete_Choices loop
+ Table (J).Highest :=
+ UI_Max
+ (Table (J - 1).Highest, Expr_Value (Table (J).Hi));
+ end loop;
+
+ -- Loop through table entries to find duplicate indexes
+
+ for J in 2 .. Nb_Discrete_Choices loop
+ Lo_Val := Expr_Value (Table (J).Lo);
+ Hi_Val := Expr_Value (Table (J).Hi);
+
+ -- Case where we have duplicates (the lower bound of
+ -- this choice is less than or equal to the highest
+ -- high bound found so far).
+
+ if Lo_Val <= Table (J - 1).Highest then
+
+ -- We move backwards looking for duplicates. We can
+ -- abandon this loop as soon as we reach a choice
+ -- highest value that is less than Lo_Val.
+
+ for K in reverse 1 .. J - 1 loop
+ exit when Table (K).Highest < Lo_Val;
+
+ -- Here we may have duplicates between entries
+ -- for K and J. Get range of duplicates.
+
+ Lo_Dup :=
+ UI_Max (Lo_Val, Expr_Value (Table (K).Lo));
+ Hi_Dup :=
+ UI_Min (Hi_Val, Expr_Value (Table (K).Hi));
+
+ -- Nothing to do if duplicate range is null
+
+ if Lo_Dup > Hi_Dup then
+ null;
+
+ -- Otherwise place proper message
+
+ else
+ -- We place message on later choice, with a
+ -- line reference to the earlier choice.
+
+ if Sloc (Table (J).Choice) <
+ Sloc (Table (K).Choice)
+ then
+ Choice := Table (K).Choice;
+ Error_Msg_Sloc := Sloc (Table (J).Choice);
+ else
+ Choice := Table (J).Choice;
+ Error_Msg_Sloc := Sloc (Table (K).Choice);
+ end if;
+
+ if Lo_Dup = Hi_Dup then
+ Error_Msg_N
+ ("index value in array aggregate "
+ & "duplicates the one given#!", Choice);
+ else
+ Error_Msg_N
+ ("index values in array aggregate "
+ & "duplicate those given#!", Choice);
+ end if;
+
+ Output_Bad_Choices (Lo_Dup, Hi_Dup, Choice);
+ end if;
+ end loop;
end if;
+ end loop;
+
+ -- Loop through entries in table to find missing indexes.
+ -- Not needed if others, since missing impossible.
+
+ if not Others_Present then
+ for J in 2 .. Nb_Discrete_Choices loop
+ Lo_Val := Expr_Value (Table (J).Lo);
+ Hi_Val := Table (J - 1).Highest;
+
+ if Lo_Val > Hi_Val + 1 then
+ Choice := Table (J).Lo;
+
+ if Hi_Val + 1 = Lo_Val - 1 then
+ Error_Msg_N
+ ("missing index value in array aggregate!",
+ Choice);
+ else
+ Error_Msg_N
+ ("missing index values in array aggregate!",
+ Choice);
+ end if;
+
+ Output_Bad_Choices
+ (Hi_Val + 1, Lo_Val - 1, Choice);
+ end if;
+ end loop;
end if;
- end if;
- end loop Outer;
- if Missing_Values then
- Set_Etype (N, Any_Composite);
- return Failure;
- end if;
+ -- If either missing or duplicate values, return failure
+
+ Set_Etype (N, Any_Composite);
+ return Failure;
+ end if;
+ end Check_Choices;
end if;
-- STEP 2 (B): Compute aggregate bounds and min/max choices values
if Nb_Discrete_Choices > 0 then
- Choices_Low := Table (1).Choice_Lo;
- Choices_High := Table (Nb_Discrete_Choices).Choice_Hi;
+ Choices_Low := Table (1).Lo;
+ Choices_High := Table (Nb_Discrete_Choices).Hi;
end if;
-- If Others is present, then bounds of aggregate come from the
@@ -2525,8 +2650,9 @@ package body Sem_Aggr is
Check_Unset_Reference (Aggregate_Bounds (N));
if not Others_Present and then Nb_Discrete_Choices = 0 then
- Set_High_Bound (Aggregate_Bounds (N),
- Duplicate_Subexpr (High_Bound (Aggregate_Bounds (N))));
+ Set_High_Bound
+ (Aggregate_Bounds (N),
+ Duplicate_Subexpr (High_Bound (Aggregate_Bounds (N))));
end if;
-- Check the dimensions of each component in the array aggregate
@@ -3416,6 +3542,7 @@ package body Sem_Aggr is
begin
-- A record aggregate is restricted in SPARK:
+
-- Each named association can have only a single choice.
-- OTHERS cannot be used.
-- Positional and named associations cannot be mixed.
@@ -3758,6 +3885,8 @@ package body Sem_Aggr is
end loop;
end Find_Private_Ancestor;
+ -- Start of processing for Step_5
+
begin
if Is_Derived_Type (Typ) and then Is_Tagged_Type (Typ) then
Parent_Typ_List := New_Elmt_List;
@@ -3822,11 +3951,12 @@ package body Sem_Aggr is
if Nkind (Dnode) = N_Full_Type_Declaration then
Record_Def := Type_Definition (Dnode);
- Gather_Components (Base_Type (Typ),
- Component_List (Record_Def),
- Governed_By => New_Assoc_List,
- Into => Components,
- Report_Errors => Errors_Found);
+ Gather_Components
+ (Base_Type (Typ),
+ Component_List (Record_Def),
+ Governed_By => New_Assoc_List,
+ Into => Components,
+ Report_Errors => Errors_Found);
end if;
end if;
@@ -3915,19 +4045,20 @@ package body Sem_Aggr is
null;
elsif not Has_Unknown_Discriminants (Typ) then
- Gather_Components (Base_Type (Typ),
- Component_List (Record_Def),
- Governed_By => New_Assoc_List,
- Into => Components,
- Report_Errors => Errors_Found);
+ Gather_Components
+ (Base_Type (Typ),
+ Component_List (Record_Def),
+ Governed_By => New_Assoc_List,
+ Into => Components,
+ Report_Errors => Errors_Found);
else
Gather_Components
(Base_Type (Underlying_Record_View (Typ)),
- Component_List (Record_Def),
- Governed_By => New_Assoc_List,
- Into => Components,
- Report_Errors => Errors_Found);
+ Component_List (Record_Def),
+ Governed_By => New_Assoc_List,
+ Into => Components,
+ Report_Errors => Errors_Found);
end if;
end if;
@@ -4590,21 +4721,19 @@ package body Sem_Aggr is
---------------------
procedure Sort_Case_Table (Case_Table : in out Case_Table_Type) is
- L : constant Int := Case_Table'First;
U : constant Int := Case_Table'Last;
K : Int;
J : Int;
T : Case_Bounds;
begin
- K := L;
- while K /= U loop
+ K := 1;
+ while K < U loop
T := Case_Table (K + 1);
J := K + 1;
- while J /= L
- and then Expr_Value (Case_Table (J - 1).Choice_Lo) >
- Expr_Value (T.Choice_Lo)
+ while J > 1
+ and then Expr_Value (Case_Table (J - 1).Lo) > Expr_Value (T.Lo)
loop
Case_Table (J) := Case_Table (J - 1);
J := J - 1;
diff --git a/gcc/ada/sem_attr.adb b/gcc/ada/sem_attr.adb
index ae58c9d2504..231d0b2e296 100644
--- a/gcc/ada/sem_attr.adb
+++ b/gcc/ada/sem_attr.adb
@@ -189,6 +189,11 @@ package body Sem_Attr is
-- where therefore the prefix of the attribute does not match the enclosing
-- scope.
+ procedure Set_Boolean_Result (N : Node_Id; B : Boolean);
+ -- Rewrites node N with an occurrence of either Standard_False or
+ -- Standard_True, depending on the value of the parameter B. The
+ -- result is marked as a static expression.
+
-----------------------
-- Analyze_Attribute --
-----------------------
@@ -212,6 +217,12 @@ package body Sem_Attr is
-- Local Subprograms --
-----------------------
+ procedure Address_Checks;
+ -- Semantic checks for valid use of Address attribute. This was made
+ -- a separate routine with the idea of using it for unrestricted access
+ -- which seems like it should follow the same rules, but that turned
+ -- out to be impractical. So now this is only used for Address.
+
procedure Analyze_Access_Attribute;
-- Used for Access, Unchecked_Access, Unrestricted_Access attributes.
-- Internally, Id distinguishes which of the three cases is involved.
@@ -303,10 +314,6 @@ package body Sem_Attr is
-- Verify that prefix of attribute N is a float type and that
-- two attribute expressions are present
- procedure Legal_Formal_Attribute;
- -- Common processing for attributes Definite and Has_Discriminants.
- -- Checks that prefix is generic indefinite formal type.
-
procedure Check_SPARK_Restriction_On_Attribute;
-- Issue an error in formal mode because attribute N is allowed
@@ -337,13 +344,17 @@ package body Sem_Attr is
-- Verify that prefix of attribute N is a scalar type
procedure Check_Standard_Prefix;
- -- Verify that prefix of attribute N is package Standard
+ -- Verify that prefix of attribute N is package Standard. Also checks
+ -- that there are no arguments.
procedure Check_Stream_Attribute (Nam : TSS_Name_Type);
-- Validity checking for stream attribute. Nam is the TSS name of the
-- corresponding possible defined attribute function (e.g. for the
-- Read attribute, Nam will be TSS_Stream_Read).
+ procedure Check_System_Prefix;
+ -- Verify that prefix of attribute N is package System
+
procedure Check_PolyORB_Attribute;
-- Validity checking for PolyORB/DSA attribute
@@ -377,6 +388,14 @@ package body Sem_Attr is
pragma No_Return (Error_Attr);
-- Like Error_Attr, but error is posted at the start of the prefix
+ function In_Refined_Post return Boolean;
+ -- Determine whether the current attribute appears in pragma
+ -- Refined_Post.
+
+ procedure Legal_Formal_Attribute;
+ -- Common processing for attributes Definite and Has_Discriminants.
+ -- Checks that prefix is generic indefinite formal type.
+
procedure Standard_Attribute (Val : Int);
-- Used to process attributes whose prefix is package Standard which
-- yield values of type Universal_Integer. The attribute reference
@@ -391,6 +410,151 @@ package body Sem_Attr is
-- non-scalar arguments or returns a non-scalar result. Verifies that
-- such a call does not appear in a preelaborable context.
+ --------------------
+ -- Address_Checks --
+ --------------------
+
+ procedure Address_Checks is
+ begin
+ -- An Address attribute created by expansion is legal even when it
+ -- applies to other entity-denoting expressions.
+
+ if not Comes_From_Source (N) then
+ return;
+
+ -- Address attribute on a protected object self reference is legal
+
+ elsif Is_Protected_Self_Reference (P) then
+ return;
+
+ -- Address applied to an entity
+
+ elsif Is_Entity_Name (P) then
+ declare
+ Ent : constant Entity_Id := Entity (P);
+
+ begin
+ if Is_Subprogram (Ent) then
+ Set_Address_Taken (Ent);
+ Kill_Current_Values (Ent);
+
+ -- An Address attribute is accepted when generated by the
+ -- compiler for dispatching operation, and an error is
+ -- issued once the subprogram is frozen (to avoid confusing
+ -- errors about implicit uses of Address in the dispatch
+ -- table initialization).
+
+ if Has_Pragma_Inline_Always (Entity (P))
+ and then Comes_From_Source (P)
+ then
+ Error_Attr_P
+ ("prefix of % attribute cannot be Inline_Always "
+ & "subprogram");
+
+ -- It is illegal to apply 'Address to an intrinsic
+ -- subprogram. This is now formalized in AI05-0095.
+ -- In an instance, an attempt to obtain 'Address of an
+ -- intrinsic subprogram (e.g the renaming of a predefined
+ -- operator that is an actual) raises Program_Error.
+
+ elsif Convention (Ent) = Convention_Intrinsic then
+ if In_Instance then
+ Rewrite (N,
+ Make_Raise_Program_Error (Loc,
+ Reason => PE_Address_Of_Intrinsic));
+
+ else
+ Error_Msg_Name_1 := Aname;
+ Error_Msg_N
+ ("cannot take % of intrinsic subprogram", N);
+ end if;
+
+ -- Issue an error if prefix denotes an eliminated subprogram
+
+ else
+ Check_For_Eliminated_Subprogram (P, Ent);
+ end if;
+
+ -- Object or label reference
+
+ elsif Is_Object (Ent) or else Ekind (Ent) = E_Label then
+ Set_Address_Taken (Ent);
+
+ -- Deal with No_Implicit_Aliasing restriction
+
+ if Restriction_Check_Required (No_Implicit_Aliasing) then
+ if not Is_Aliased_View (P) then
+ Check_Restriction (No_Implicit_Aliasing, P);
+ else
+ Check_No_Implicit_Aliasing (P);
+ end if;
+ end if;
+
+ -- If we have an address of an object, and the attribute
+ -- comes from source, then set the object as potentially
+ -- source modified. We do this because the resulting address
+ -- can potentially be used to modify the variable and we
+ -- might not detect this, leading to some junk warnings.
+
+ Set_Never_Set_In_Source (Ent, False);
+
+ -- Allow Address to be applied to task or protected type,
+ -- returning null address (what is that about???)
+
+ elsif (Is_Concurrent_Type (Etype (Ent))
+ and then Etype (Ent) = Base_Type (Ent))
+ or else Ekind (Ent) = E_Package
+ or else Is_Generic_Unit (Ent)
+ then
+ Rewrite (N,
+ New_Occurrence_Of (RTE (RE_Null_Address), Sloc (N)));
+
+ -- Anything else is illegal
+
+ else
+ Error_Attr ("invalid prefix for % attribute", P);
+ end if;
+ end;
+
+ -- Allow Address if the prefix is a reference to the AST_Entry
+ -- attribute. If expansion is active, the attribute will be
+ -- replaced by a function call, and address will work fine and
+ -- get the proper value, but if expansion is not active, then
+ -- the check here allows proper semantic analysis of the reference.
+
+ elsif Nkind (P) = N_Attribute_Reference
+ and then Attribute_Name (P) = Name_AST_Entry
+ then
+ Rewrite (N,
+ New_Occurrence_Of (RTE (RE_Null_Address), Sloc (N)));
+
+ -- Object is OK
+
+ elsif Is_Object_Reference (P) then
+ return;
+
+ -- Subprogram called using dot notation
+
+ elsif Nkind (P) = N_Selected_Component
+ and then Is_Subprogram (Entity (Selector_Name (P)))
+ then
+ return;
+
+ -- What exactly are we allowing here ??? and is this properly
+ -- documented in the sinfo documentation for this node ???
+
+ elsif Relaxed_RM_Semantics
+ and then Nkind (P) = N_Attribute_Reference
+ then
+ return;
+
+ -- All other non-entity name cases are illegal
+
+ else
+ Error_Attr ("invalid prefix for % attribute", P);
+ end if;
+ end Address_Checks;
+
------------------------------
-- Analyze_Access_Attribute --
------------------------------
@@ -1472,7 +1636,7 @@ package body Sem_Attr is
Typ := Etype (E);
- if From_With_Type (Typ) then
+ if From_Limited_With (Typ) then
Error_Attr_P
("prefix of % attribute cannot be an incomplete type");
@@ -1491,7 +1655,7 @@ package body Sem_Attr is
-- entities may occur in subprogram formals.
if Is_Incomplete_Type (Typ)
- and then From_With_Type (Typ)
+ and then From_Limited_With (Typ)
and then Present (Non_Limited_View (Typ))
and then Is_Legal_Shadow_Entity_In_Body (Typ)
then
@@ -1817,6 +1981,17 @@ package body Sem_Attr is
Check_Not_CPP_Type;
end Check_Stream_Attribute;
+ -------------------------
+ -- Check_System_Prefix --
+ -------------------------
+
+ procedure Check_System_Prefix is
+ begin
+ if Nkind (P) /= N_Identifier or else Chars (P) /= Name_System then
+ Error_Attr ("only allowed prefix for % attribute is System", P);
+ end if;
+ end Check_System_Prefix;
+
-----------------------
-- Check_Task_Prefix --
-----------------------
@@ -1927,6 +2102,60 @@ package body Sem_Attr is
Error_Attr;
end Error_Attr_P;
+ ---------------------
+ -- In_Refined_Post --
+ ---------------------
+
+ function In_Refined_Post return Boolean is
+ function Is_Refined_Post (Prag : Node_Id) return Boolean;
+ -- Determine whether Prag denotes one of the incarnations of pragma
+ -- Refined_Post (either as is or pragma Check (Refined_Post, ...).
+
+ ---------------------
+ -- Is_Refined_Post --
+ ---------------------
+
+ function Is_Refined_Post (Prag : Node_Id) return Boolean is
+ Args : constant List_Id := Pragma_Argument_Associations (Prag);
+ Nam : constant Name_Id := Pragma_Name (Prag);
+
+ begin
+ if Nam = Name_Refined_Post then
+ return True;
+
+ elsif Nam = Name_Check then
+ pragma Assert (Present (Args));
+
+ return Chars (Expression (First (Args))) = Name_Refined_Post;
+ end if;
+
+ return False;
+ end Is_Refined_Post;
+
+ -- Local variables
+
+ Stmt : Node_Id;
+
+ -- Start of processing for In_Refined_Post
+
+ begin
+ Stmt := Parent (N);
+ while Present (Stmt) loop
+ if Nkind (Stmt) = N_Pragma and then Is_Refined_Post (Stmt) then
+ return True;
+
+ -- Prevent the search from going too far
+
+ elsif Is_Body_Or_Package_Declaration (Stmt) then
+ exit;
+ end if;
+
+ Stmt := Parent (Stmt);
+ end loop;
+
+ return False;
+ end In_Refined_Post;
+
----------------------------
-- Legal_Formal_Attribute --
----------------------------
@@ -2252,136 +2481,7 @@ package body Sem_Attr is
when Attribute_Address =>
Check_E0;
-
- -- Check for some junk cases, where we have to allow the address
- -- attribute but it does not make much sense, so at least for now
- -- just replace with Null_Address.
-
- -- We also do this if the prefix is a reference to the AST_Entry
- -- attribute. If expansion is active, the attribute will be
- -- replaced by a function call, and address will work fine and
- -- get the proper value, but if expansion is not active, then
- -- the check here allows proper semantic analysis of the reference.
-
- -- An Address attribute created by expansion is legal even when it
- -- applies to other entity-denoting expressions.
-
- if Is_Protected_Self_Reference (P) then
-
- -- Address attribute on a protected object self reference is legal
-
- null;
-
- elsif Is_Entity_Name (P) then
- declare
- Ent : constant Entity_Id := Entity (P);
-
- begin
- if Is_Subprogram (Ent) then
- Set_Address_Taken (Ent);
- Kill_Current_Values (Ent);
-
- -- An Address attribute is accepted when generated by the
- -- compiler for dispatching operation, and an error is
- -- issued once the subprogram is frozen (to avoid confusing
- -- errors about implicit uses of Address in the dispatch
- -- table initialization).
-
- if Has_Pragma_Inline_Always (Entity (P))
- and then Comes_From_Source (P)
- then
- Error_Attr_P
- ("prefix of % attribute cannot be Inline_Always" &
- " subprogram");
-
- -- It is illegal to apply 'Address to an intrinsic
- -- subprogram. This is now formalized in AI05-0095.
- -- In an instance, an attempt to obtain 'Address of an
- -- intrinsic subprogram (e.g the renaming of a predefined
- -- operator that is an actual) raises Program_Error.
-
- elsif Convention (Ent) = Convention_Intrinsic then
- if In_Instance then
- Rewrite (N,
- Make_Raise_Program_Error (Loc,
- Reason => PE_Address_Of_Intrinsic));
-
- else
- Error_Msg_N
- ("cannot take Address of intrinsic subprogram", N);
- end if;
-
- -- Issue an error if prefix denotes an eliminated subprogram
-
- else
- Check_For_Eliminated_Subprogram (P, Ent);
- end if;
-
- elsif Is_Object (Ent)
- or else Ekind (Ent) = E_Label
- then
- Set_Address_Taken (Ent);
-
- -- Deal with No_Implicit_Aliasing restriction
-
- if Restriction_Check_Required (No_Implicit_Aliasing) then
- if not Is_Aliased_View (P) then
- Check_Restriction (No_Implicit_Aliasing, P);
- else
- Check_No_Implicit_Aliasing (P);
- end if;
- end if;
-
- -- If we have an address of an object, and the attribute
- -- comes from source, then set the object as potentially
- -- source modified. We do this because the resulting address
- -- can potentially be used to modify the variable and we
- -- might not detect this, leading to some junk warnings.
-
- Set_Never_Set_In_Source (Ent, False);
-
- elsif (Is_Concurrent_Type (Etype (Ent))
- and then Etype (Ent) = Base_Type (Ent))
- or else Ekind (Ent) = E_Package
- or else Is_Generic_Unit (Ent)
- then
- Rewrite (N,
- New_Occurrence_Of (RTE (RE_Null_Address), Sloc (N)));
-
- else
- Error_Attr ("invalid prefix for % attribute", P);
- end if;
- end;
-
- elsif Nkind (P) = N_Attribute_Reference
- and then Attribute_Name (P) = Name_AST_Entry
- then
- Rewrite (N,
- New_Occurrence_Of (RTE (RE_Null_Address), Sloc (N)));
-
- elsif Is_Object_Reference (P) then
- null;
-
- elsif Nkind (P) = N_Selected_Component
- and then Is_Subprogram (Entity (Selector_Name (P)))
- then
- null;
-
- -- What exactly are we allowing here ??? and is this properly
- -- documented in the sinfo documentation for this node ???
-
- elsif not Comes_From_Source (N) then
- null;
-
- elsif Relaxed_RM_Semantics
- and then Nkind (P) = N_Attribute_Reference
- then
- null;
-
- else
- Error_Attr ("invalid prefix for % attribute", P);
- end if;
-
+ Address_Checks;
Set_Etype (N, RTE (RE_Address));
------------------
@@ -3583,6 +3683,24 @@ package body Sem_Attr is
Check_Array_Type;
Set_Etype (N, Universal_Integer);
+ -------------------
+ -- Library_Level --
+ -------------------
+
+ when Attribute_Library_Level =>
+ Check_E0;
+
+ if not Is_Entity_Name (P) then
+ Error_Attr_P ("prefix of % attribute must be an entity name");
+ end if;
+
+ if not Inside_A_Generic then
+ Set_Boolean_Result (N,
+ Is_Library_Level_Entity (Entity (P)));
+ end if;
+
+ Set_Etype (N, Standard_Boolean);
+
---------------
-- Lock_Free --
---------------
@@ -3775,7 +3893,7 @@ package body Sem_Attr is
-- Loop_Entry must create a constant initialized by the evaluated
-- prefix.
- if Is_Immutably_Limited_Type (Etype (P)) then
+ if Is_Limited_View (Etype (P)) then
Error_Attr_P ("prefix of attribute % cannot be limited");
end if;
@@ -4281,7 +4399,32 @@ package body Sem_Attr is
Error_Attr ("% attribute can only appear in postcondition", P);
end if;
- -- Body case, where we must be inside a generated _Postcondition
+ -- Check the legality of attribute 'Old when it appears inside pragma
+ -- Refined_Post. These specialized checks are required only when code
+ -- generation is disabled. In the general case pragma Refined_Post is
+ -- transformed into pragma Check by Process_PPCs which in turn is
+ -- relocated to procedure _Postconditions. From then on the legality
+ -- of 'Old is determined as usual.
+
+ elsif not Expander_Active and then In_Refined_Post then
+ Preanalyze_And_Resolve (P);
+ P_Type := Etype (P);
+ Set_Etype (N, P_Type);
+
+ if Is_Limited_Type (P_Type) then
+ Error_Attr ("attribute % cannot apply to limited objects", P);
+ end if;
+
+ if Is_Entity_Name (P)
+ and then Is_Constant_Object (Entity (P))
+ then
+ Error_Msg_N
+ ("??attribute Old applied to constant has no effect", P);
+ end if;
+
+ return;
+
+ -- Body case, where we must be inside a generated _Postconditions
-- procedure, or else the attribute use is definitely misplaced. The
-- postcondition itself may have generated transient scopes, and is
-- not necessarily the current one.
@@ -4302,8 +4445,8 @@ package body Sem_Attr is
-- If the attribute reference is generated for a Requires clause,
-- then no expressions follow. Otherwise it is a primary, in which
- -- case, if expressions follow, the attribute reference must be
- -- an indexable object, so rewrite the node accordingly.
+ -- case, if expressions follow, the attribute reference must be an
+ -- indexable object, so rewrite the node accordingly.
if Present (E1) then
Rewrite (N,
@@ -4320,8 +4463,8 @@ package body Sem_Attr is
Check_E0;
- -- Prefix has not been analyzed yet, and its full analysis will
- -- take place during expansion (see below).
+ -- Prefix has not been analyzed yet, and its full analysis will take
+ -- place during expansion (see below).
Preanalyze_And_Resolve (P);
P_Type := Etype (P);
@@ -4725,7 +4868,32 @@ package body Sem_Attr is
Set_Is_Overloaded (P, False);
end if;
- -- Body case, where we must be inside a generated _Postcondition
+ -- Check the legality of attribute 'Result when it appears inside
+ -- pragma Refined_Post. These specialized checks are required only
+ -- when code generation is disabled. In the general case pragma
+ -- Refined_Post is transformed into pragma Check by Process_PPCs
+ -- which in turn is relocated to procedure _Postconditions. From
+ -- then on the legality of 'Result is determined as usual.
+
+ elsif not Expander_Active and then In_Refined_Post then
+ PS := Current_Scope;
+
+ -- The prefix denotes the proper related function
+
+ if Is_Entity_Name (P)
+ and then Ekind (Entity (P)) = E_Function
+ and then Entity (P) = PS
+ then
+ null;
+
+ else
+ Error_Msg_Name_2 := Chars (PS);
+ Error_Attr ("incorrect prefix for % attribute, expected %", P);
+ end if;
+
+ Set_Etype (N, Etype (PS));
+
+ -- Body case, where we must be inside a generated _Postconditions
-- procedure, and the prefix must be on the scope stack, or else the
-- attribute use is definitely misplaced. The postcondition itself
-- may have generated transient scopes, and is not necessarily the
@@ -4763,9 +4931,9 @@ package body Sem_Attr is
null;
else
- Error_Msg_NE
- ("incorrect prefix for % attribute, expected &", P, PS);
- Error_Attr;
+ Error_Msg_Name_2 := Chars (PS);
+ Error_Attr
+ ("incorrect prefix for % attribute, expected %", P);
end if;
Rewrite (N, Make_Identifier (Sloc (N), Name_uResult));
@@ -4835,35 +5003,10 @@ package body Sem_Attr is
U : Node_Id;
Unam : Unit_Name_Type;
- procedure Set_Result (B : Boolean);
- -- Replace restriction node by static constant False or True,
- -- depending on the value of B.
-
- ----------------
- -- Set_Result --
- ----------------
-
- procedure Set_Result (B : Boolean) is
- begin
- if B then
- Rewrite (N, New_Occurrence_Of (Standard_True, Loc));
- else
- Rewrite (N, New_Occurrence_Of (Standard_False, Loc));
- end if;
-
- Set_Is_Static_Expression (N);
- end Set_Result;
-
- -- Start of processing for Restriction_Set
-
begin
Check_E1;
Analyze (P);
-
- if Nkind (P) /= N_Identifier or else Chars (P) /= Name_System then
- Set_Result (False);
- Error_Attr_P ("prefix of % attribute must be System");
- end if;
+ Check_System_Prefix;
-- No_Dependence case
@@ -4872,7 +5015,7 @@ package body Sem_Attr is
U := Explicit_Actual_Parameter (E1);
if not OK_No_Dependence_Unit_Name (U) then
- Set_Result (False);
+ Set_Boolean_Result (N, False);
Error_Attr;
end if;
@@ -4883,14 +5026,14 @@ package body Sem_Attr is
if Designate_Same_Unit (U, No_Dependences.Table (J).Unit)
and then No_Dependences.Table (J).Warn = False
then
- Set_Result (True);
+ Set_Boolean_Result (N, True);
return;
end if;
end loop;
-- If not in the No_Dependence table, result is False
- Set_Result (False);
+ Set_Boolean_Result (N, False);
-- In this case, we must ensure that the binder will reject any
-- other unit in the partition that sets No_Dependence for this
@@ -4913,29 +5056,29 @@ package body Sem_Attr is
else
if Nkind (E1) /= N_Identifier then
- Set_Result (False);
+ Set_Boolean_Result (N, False);
Error_Attr ("attribute % requires restriction identifier", E1);
else
R := Get_Restriction_Id (Process_Restriction_Synonyms (E1));
if R = Not_A_Restriction_Id then
- Set_Result (False);
+ Set_Boolean_Result (N, False);
Error_Msg_Node_1 := E1;
Error_Attr ("invalid restriction identifier &", E1);
elsif R not in Partition_Boolean_Restrictions then
- Set_Result (False);
+ Set_Boolean_Result (N, False);
Error_Msg_Node_1 := E1;
Error_Attr
("& is not a boolean partition-wide restriction", E1);
end if;
if Restriction_Active (R) then
- Set_Result (True);
+ Set_Boolean_Result (N, True);
else
Check_Restriction (R, N);
- Set_Result (False);
+ Set_Boolean_Result (N, False);
end if;
end if;
end if;
@@ -5040,21 +5183,42 @@ package body Sem_Attr is
--------------------------
when Attribute_Scalar_Storage_Order => Scalar_Storage_Order :
+ declare
+ Ent : Entity_Id := Empty;
+
begin
Check_E0;
Check_Type;
- if not Is_Record_Type (P_Type) or else Is_Array_Type (P_Type) then
- Error_Attr_P
- ("prefix of % attribute must be record or array type");
- end if;
+ if not (Is_Record_Type (P_Type) or else Is_Array_Type (P_Type)) then
+
+ -- In GNAT mode, the attribute applies to generic types as well
+ -- as composite types, and for non-composite types always returns
+ -- the default bit order for the target.
+
+ if not (GNAT_Mode and then Is_Generic_Type (P_Type))
+ and then not In_Instance
+ then
+ Error_Attr_P
+ ("prefix of % attribute must be record or array type");
+
+ elsif not Is_Generic_Type (P_Type) then
+ if Bytes_Big_Endian then
+ Ent := RTE (RE_High_Order_First);
+ else
+ Ent := RTE (RE_Low_Order_First);
+ end if;
+ end if;
+
+ elsif Bytes_Big_Endian xor Reverse_Storage_Order (P_Type) then
+ Ent := RTE (RE_High_Order_First);
- if Bytes_Big_Endian xor Reverse_Storage_Order (P_Type) then
- Rewrite (N,
- New_Occurrence_Of (RTE (RE_High_Order_First), Loc));
else
- Rewrite (N,
- New_Occurrence_Of (RTE (RE_Low_Order_First), Loc));
+ Ent := RTE (RE_Low_Order_First);
+ end if;
+
+ if Present (Ent) then
+ Rewrite (N, New_Occurrence_Of (Ent, Loc));
end if;
Set_Etype (N, RTE (RE_Bit_Order));
@@ -5439,18 +5603,50 @@ package body Sem_Attr is
-- To_Address --
----------------
- when Attribute_To_Address =>
+ when Attribute_To_Address => To_Address : declare
+ Val : Uint;
+
+ begin
Check_E1;
Analyze (P);
-
- if Nkind (P) /= N_Identifier or else Chars (P) /= Name_System then
- Error_Attr_P ("prefix of % attribute must be System");
- end if;
+ Check_System_Prefix;
Generate_Reference (RTE (RE_Address), P);
Analyze_And_Resolve (E1, Any_Integer);
Set_Etype (N, RTE (RE_Address));
+ -- Static expression case, check range and set appropriate type
+
+ if Is_OK_Static_Expression (E1) then
+ Val := Expr_Value (E1);
+
+ if Val < -(2 ** UI_From_Int (Standard'Address_Size - 1))
+ or else
+ Val > 2 ** UI_From_Int (Standard'Address_Size) - 1
+ then
+ Error_Attr ("address value out of range for % attribute", E1);
+ end if;
+
+ -- In most cases the expression is a numeric literal or some other
+ -- address expression, but if it is a declared constant it may be
+ -- of a compatible type that must be left on the node.
+
+ if Is_Entity_Name (E1) then
+ null;
+
+ -- Set type to universal integer if negative
+
+ elsif Val < 0 then
+ Set_Etype (E1, Universal_Integer);
+
+ -- Otherwise set type to Unsigned_64 to accomodate max values
+
+ else
+ Set_Etype (E1, Standard_Unsigned_64);
+ end if;
+ end if;
+ end To_Address;
+
------------
-- To_Any --
------------
@@ -5642,7 +5838,9 @@ package body Sem_Attr is
-------------------------
-- This is a GNAT specific attribute which is like Access except that
- -- all scope checks and checks for aliased views are omitted.
+ -- all scope checks and checks for aliased views are omitted. It is
+ -- documented as being equivalent to the use of the Address attribute
+ -- followed by an unchecked conversion to the target access type.
when Attribute_Unrestricted_Access =>
@@ -5663,6 +5861,18 @@ package body Sem_Attr is
Set_Address_Taken (Entity (P));
end if;
+ -- It might seem reasonable to call Address_Checks here to apply the
+ -- same set of semantic checks that we enforce for 'Address (after
+ -- all we document Unrestricted_Access as being equivalent to the
+ -- use of Address followed by an Unchecked_Conversion). However, if
+ -- we do enable these checks, we get multiple failures in both the
+ -- compiler run-time and in our regression test suite, so we leave
+ -- out these checks for now. To be investigated further some time???
+
+ -- Address_Checks;
+
+ -- Now complete analysis using common access processing
+
Analyze_Access_Attribute;
------------
@@ -5784,7 +5994,7 @@ package body Sem_Attr is
then
Error_Attr_P ("prefix of attribute % must be a record or array");
- elsif Is_Immutably_Limited_Type (P_Type) then
+ elsif Is_Limited_View (P_Type) then
Error_Attr ("prefix of attribute % cannot be limited", N);
elsif Nkind (E1) /= N_Aggregate then
@@ -6616,8 +6826,8 @@ package body Sem_Attr is
return;
end if;
- -- Cases where P is not an object. Cannot do anything if P is
- -- not the name of an entity.
+ -- Cases where P is not an object. Cannot do anything if P is not the
+ -- name of an entity.
elsif not Is_Entity_Name (P) then
Check_Expressions;
@@ -6715,10 +6925,9 @@ package body Sem_Attr is
-- We can fold 'Alignment applied to a type if the alignment is known
-- (as happens for an alignment from an attribute definition clause).
- -- At this stage, this can happen only for types (e.g. record
- -- types) for which the size is always non-static. We exclude
- -- generic types from consideration (since they have bogus
- -- sizes set within templates).
+ -- At this stage, this can happen only for types (e.g. record types) for
+ -- which the size is always non-static. We exclude generic types from
+ -- consideration (since they have bogus sizes set within templates).
elsif Id = Attribute_Alignment
and then Is_Type (P_Entity)
@@ -8925,6 +9134,7 @@ package body Sem_Attr is
Attribute_First_Bit |
Attribute_Input |
Attribute_Last_Bit |
+ Attribute_Library_Level |
Attribute_Maximum_Alignment |
Attribute_Old |
Attribute_Output |
@@ -9495,7 +9705,7 @@ package body Sem_Attr is
-- use of it. If it is an incomplete subtype, use the base type
-- in any case.
- if From_With_Type (Des_Btyp)
+ if From_Limited_With (Des_Btyp)
and then Present (Non_Limited_View (Des_Btyp))
then
Des_Btyp := Non_Limited_View (Des_Btyp);
@@ -10228,6 +10438,23 @@ package body Sem_Attr is
Eval_Attribute (N);
end Resolve_Attribute;
+ ------------------------
+ -- Set_Boolean_Result --
+ ------------------------
+
+ procedure Set_Boolean_Result (N : Node_Id; B : Boolean) is
+ Loc : constant Source_Ptr := Sloc (N);
+
+ begin
+ if B then
+ Rewrite (N, New_Occurrence_Of (Standard_True, Loc));
+ else
+ Rewrite (N, New_Occurrence_Of (Standard_False, Loc));
+ end if;
+
+ Set_Is_Static_Expression (N);
+ end Set_Boolean_Result;
+
--------------------------------
-- Stream_Attribute_Available --
--------------------------------
diff --git a/gcc/ada/sem_aux.adb b/gcc/ada/sem_aux.adb
index 3c5d2af59ba..d67517e2ceb 100644
--- a/gcc/ada/sem_aux.adb
+++ b/gcc/ada/sem_aux.adb
@@ -91,7 +91,7 @@ package body Sem_Aux is
elsif Is_Class_Wide_Type (Typ)
and then Is_Incomplete_Type (Etype (Typ))
- and then From_With_Type (Etype (Typ))
+ and then From_Limited_With (Etype (Typ))
and then Present (Non_Limited_View (Etype (Typ)))
then
return Class_Wide_Type (Non_Limited_View (Etype (Typ)));
@@ -865,48 +865,6 @@ package body Sem_Aux is
elsif Is_Concurrent_Type (Btype) then
return True;
- elsif Is_Record_Type (Btype) then
-
- -- Note that we return True for all limited interfaces, even though
- -- (unsynchronized) limited interfaces can have descendants that are
- -- nonlimited, because this is a predicate on the type itself, and
- -- things like functions with limited interface results need to be
- -- handled as build in place even though they might return objects
- -- of a type that is not inherently limited.
-
- if Is_Class_Wide_Type (Btype) then
- return Is_Immutably_Limited_Type (Root_Type (Btype));
-
- else
- declare
- C : Entity_Id;
-
- begin
- C := First_Component (Btype);
- while Present (C) loop
-
- -- Don't consider components with interface types (which can
- -- only occur in the case of a _parent component anyway).
- -- They don't have any components, plus it would cause this
- -- function to return true for nonlimited types derived from
- -- limited interfaces.
-
- if not Is_Interface (Etype (C))
- and then Is_Immutably_Limited_Type (Etype (C))
- then
- return True;
- end if;
-
- C := Next_Component (C);
- end loop;
- end;
-
- return False;
- end if;
-
- elsif Is_Array_Type (Btype) then
- return Is_Immutably_Limited_Type (Component_Type (Btype));
-
else
return False;
end if;
@@ -1024,6 +982,105 @@ package body Sem_Aux is
end if;
end Is_Limited_Type;
+ ---------------------
+ -- Is_Limited_View --
+ ---------------------
+
+ function Is_Limited_View (Ent : Entity_Id) return Boolean is
+ Btype : constant Entity_Id := Available_View (Base_Type (Ent));
+
+ begin
+ if Is_Limited_Record (Btype) then
+ return True;
+
+ elsif Ekind (Btype) = E_Limited_Private_Type
+ and then Nkind (Parent (Btype)) = N_Formal_Type_Declaration
+ then
+ return not In_Package_Body (Scope ((Btype)));
+
+ elsif Is_Private_Type (Btype) then
+
+ -- AI05-0063: A type derived from a limited private formal type is
+ -- not immutably limited in a generic body.
+
+ if Is_Derived_Type (Btype)
+ and then Is_Generic_Type (Etype (Btype))
+ then
+ if not Is_Limited_Type (Etype (Btype)) then
+ return False;
+
+ -- A descendant of a limited formal type is not immutably limited
+ -- in the generic body, or in the body of a generic child.
+
+ elsif Ekind (Scope (Etype (Btype))) = E_Generic_Package then
+ return not In_Package_Body (Scope (Btype));
+
+ else
+ return False;
+ end if;
+
+ else
+ declare
+ Utyp : constant Entity_Id := Underlying_Type (Btype);
+ begin
+ if No (Utyp) then
+ return False;
+ else
+ return Is_Limited_View (Utyp);
+ end if;
+ end;
+ end if;
+
+ elsif Is_Concurrent_Type (Btype) then
+ return True;
+
+ elsif Is_Record_Type (Btype) then
+
+ -- Note that we return True for all limited interfaces, even though
+ -- (unsynchronized) limited interfaces can have descendants that are
+ -- nonlimited, because this is a predicate on the type itself, and
+ -- things like functions with limited interface results need to be
+ -- handled as build in place even though they might return objects
+ -- of a type that is not inherently limited.
+
+ if Is_Class_Wide_Type (Btype) then
+ return Is_Limited_View (Root_Type (Btype));
+
+ else
+ declare
+ C : Entity_Id;
+
+ begin
+ C := First_Component (Btype);
+ while Present (C) loop
+
+ -- Don't consider components with interface types (which can
+ -- only occur in the case of a _parent component anyway).
+ -- They don't have any components, plus it would cause this
+ -- function to return true for nonlimited types derived from
+ -- limited interfaces.
+
+ if not Is_Interface (Etype (C))
+ and then Is_Limited_View (Etype (C))
+ then
+ return True;
+ end if;
+
+ C := Next_Component (C);
+ end loop;
+ end;
+
+ return False;
+ end if;
+
+ elsif Is_Array_Type (Btype) then
+ return Is_Limited_View (Component_Type (Btype));
+
+ else
+ return False;
+ end if;
+ end Is_Limited_View;
+
----------------------
-- Nearest_Ancestor --
----------------------
@@ -1151,6 +1208,26 @@ package body Sem_Aux is
and then Has_Discriminants (Typ));
end Object_Type_Has_Constrained_Partial_View;
+ ---------------------------
+ -- Package_Specification --
+ ---------------------------
+
+ function Package_Specification (Pack_Id : Entity_Id) return Node_Id is
+ N : Node_Id;
+
+ begin
+ N := Parent (Pack_Id);
+ while Nkind (N) /= N_Package_Specification loop
+ N := Parent (N);
+
+ if No (N) then
+ raise Program_Error;
+ end if;
+ end loop;
+
+ return N;
+ end Package_Specification;
+
---------------
-- Tree_Read --
---------------
diff --git a/gcc/ada/sem_aux.ads b/gcc/ada/sem_aux.ads
index e7086cc0ecc..49d75acfa70 100644
--- a/gcc/ada/sem_aux.ads
+++ b/gcc/ada/sem_aux.ads
@@ -281,6 +281,12 @@ package Sem_Aux is
-- so. False for other type entities, or any entities that are not types.
function Is_Immutably_Limited_Type (Ent : Entity_Id) return Boolean;
+ -- Implements definition in Ada 2012 RM-7.5 (8.1/3). This differs from the
+ -- following predicate in that an untagged record with immutably limited
+ -- components is NOT by itself immutably limited. This matters, e.g. when
+ -- checking the legality of an access to the current instance.
+
+ function Is_Limited_View (Ent : Entity_Id) return Boolean;
-- Ent is any entity. True for a type that is "inherently" limited (i.e.
-- cannot become nonlimited). From the Ada 2005 RM-7.5(8.1/2), "a type with
-- a part that is of a task, protected, or explicitly limited record type".
@@ -294,7 +300,8 @@ package Sem_Aux is
-- Ent is any entity. Returns true if Ent is a limited type (limited
-- private type, limited interface type, task type, protected type,
-- composite containing a limited component, or a subtype of any of
- -- these types).
+ -- these types). This older routine overlaps with the previous one, this
+ -- should be cleaned up???
function Nearest_Ancestor (Typ : Entity_Id) return Entity_Id;
-- Given a subtype Typ, this function finds out the nearest ancestor from
@@ -348,4 +355,8 @@ package Sem_Aux is
-- it returns the subprogram, task or protected body node for it. The unit
-- may be a child unit with any number of ancestors.
+ function Package_Specification (Pack_Id : Entity_Id) return Node_Id;
+ -- Given an entity for a package or generic package, return corresponding
+ -- package specification. Simplifies handling of child units, and better
+ -- than the old idiom: Specification (Unit_Declaration_Node (Pack_Id)).
end Sem_Aux;
diff --git a/gcc/ada/sem_case.adb b/gcc/ada/sem_case.adb
index 515d2a6009e..b3f47a6df9b 100644
--- a/gcc/ada/sem_case.adb
+++ b/gcc/ada/sem_case.adb
@@ -57,15 +57,15 @@ package body Sem_Case is
-- to the choice node itself.
type Choice_Table_Type is array (Nat range <>) of Choice_Bounds;
- -- Table type used to sort the choices present in a case statement, array
- -- aggregate or record variant. The actual entries are stored in 1 .. Last,
- -- but we have a 0 entry for convenience in sorting.
+ -- Table type used to sort the choices present in a case statement or
+ -- record variant. The actual entries are stored in 1 .. Last, but we
+ -- have a 0 entry for use in sorting.
-----------------------
-- Local Subprograms --
-----------------------
- procedure Check_Choices
+ procedure Check_Choice_Set
(Choice_Table : in out Choice_Table_Type;
Bounds_Type : Entity_Id;
Subtyp : Entity_Id;
@@ -95,7 +95,7 @@ package body Sem_Case is
(Case_Table : Choice_Table_Type;
Others_Choice : Node_Id;
Choice_Type : Entity_Id);
- -- The case table is the table generated by a call to Analyze_Choices
+ -- The case table is the table generated by a call to Check_Choices
-- (with just 1 .. Last_Choice entries present). Others_Choice is a
-- pointer to the N_Others_Choice node (this routine is only called if
-- an others choice is present), and Choice_Type is the discrete type
@@ -103,11 +103,11 @@ package body Sem_Case is
-- determine the set of values covered by others. This choice list is
-- set in the Others_Discrete_Choices field of the N_Others_Choice node.
- -------------------
- -- Check_Choices --
- -------------------
+ ----------------------
+ -- Check_Choice_Set --
+ ----------------------
- procedure Check_Choices
+ procedure Check_Choice_Set
(Choice_Table : in out Choice_Table_Type;
Bounds_Type : Entity_Id;
Subtyp : Entity_Id;
@@ -126,6 +126,10 @@ package body Sem_Case is
-- choice that covered a predicate set. Error denotes whether the check
-- found an illegal intersection.
+ procedure Dup_Choice (Lo, Hi : Uint; C : Node_Id);
+ -- Post message "duplication of choice value(s) bla bla at xx". Message
+ -- is posted at location C. Caller sets Error_Msg_Sloc for xx.
+
procedure Explain_Non_Static_Bound;
-- Called when we find a non-static bound, requiring the base type to
-- be covered. Provides where possible a helpful explanation of why the
@@ -145,8 +149,7 @@ package body Sem_Case is
procedure Missing_Choices (Pred : Node_Id; Prev_Hi : Uint);
-- Emit an error message for each non-covered static predicate set.
- -- Prev_Hi denotes the upper bound of the last choice that covered a
- -- set.
+ -- Prev_Hi denotes the upper bound of the last choice covering a set.
procedure Move_Choice (From : Natural; To : Natural);
-- Move routine for sorting the Choice_Table
@@ -238,6 +241,7 @@ package body Sem_Case is
Choice_Hi : constant Uint := Expr_Value (Choice.Hi);
Choice_Lo : constant Uint := Expr_Value (Choice.Lo);
Loc : Source_Ptr;
+ LocN : Node_Id;
Next_Hi : Uint;
Next_Lo : Uint;
Pred_Hi : Uint;
@@ -249,11 +253,13 @@ package body Sem_Case is
-- Find the proper error message location
if Present (Choice.Node) then
- Loc := Sloc (Choice.Node);
+ LocN := Choice.Node;
else
- Loc := Sloc (Case_Node);
+ LocN := Case_Node;
end if;
+ Loc := Sloc (LocN);
+
if Present (Pred) then
Pred_Lo := Expr_Value (Low_Bound (Pred));
Pred_Hi := Expr_Value (High_Bound (Pred));
@@ -263,16 +269,17 @@ package body Sem_Case is
else
Illegal_Range (Loc, Choice_Lo, Choice_Hi);
Error := True;
-
return;
end if;
-- Step 1: Detect duplicate choices
- if Inside_Range (Choice_Lo, Choice_Hi, Prev_Lo)
- or else Inside_Range (Choice_Lo, Choice_Hi, Prev_Hi)
- then
- Error_Msg ("duplication of choice value", Loc);
+ if Inside_Range (Choice_Lo, Choice_Hi, Prev_Lo) then
+ Dup_Choice (Prev_Lo, UI_Min (Prev_Hi, Choice_Hi), LocN);
+ Error := True;
+
+ elsif Inside_Range (Choice_Lo, Choice_Hi, Prev_Hi) then
+ Dup_Choice (UI_Max (Choice_Lo, Prev_Lo), Prev_Hi, LocN);
Error := True;
-- Step 2: Detect full coverage
@@ -312,8 +319,16 @@ package body Sem_Case is
-- ^ illegal ^
elsif Pred_Lo < Choice_Lo and then Pred_Hi < Choice_Lo then
- Missing_Choice (Pred_Lo, Pred_Hi);
- Error := True;
+ if Others_Present then
+
+ -- Current predicate set is covered by others clause.
+
+ null;
+
+ else
+ Missing_Choice (Pred_Lo, Pred_Hi);
+ Error := True;
+ end if;
-- There may be several static predicate sets between the current
-- one and the choice. Inspect the next static predicate set.
@@ -377,7 +392,12 @@ package body Sem_Case is
if Others_Present then
Prev_Lo := Choice_Lo;
Prev_Hi := Choice_Hi;
- Next (Pred);
+
+ -- Check whether predicate set is fully covered by choice
+
+ if Pred_Hi = Choice_Hi then
+ Next (Pred);
+ end if;
-- Choice_Lo Choice_Hi Pred_Hi
-- +===========+===========+
@@ -422,6 +442,45 @@ package body Sem_Case is
end if;
end Check_Against_Predicate;
+ ----------------
+ -- Dup_Choice --
+ ----------------
+
+ procedure Dup_Choice (Lo, Hi : Uint; C : Node_Id) is
+ begin
+ -- In some situations, we call this with a null range, and obviously
+ -- we don't want to complain in this case.
+
+ if Lo > Hi then
+ return;
+ end if;
+
+ -- Case of only one value that is missing
+
+ if Lo = Hi then
+ if Is_Integer_Type (Bounds_Type) then
+ Error_Msg_Uint_1 := Lo;
+ Error_Msg_N ("duplication of choice value: ^#!", C);
+ else
+ Error_Msg_Name_1 := Choice_Image (Lo, Bounds_Type);
+ Error_Msg_N ("duplication of choice value: %#!", C);
+ end if;
+
+ -- More than one choice value, so print range of values
+
+ else
+ if Is_Integer_Type (Bounds_Type) then
+ Error_Msg_Uint_1 := Lo;
+ Error_Msg_Uint_2 := Hi;
+ Error_Msg_N ("duplication of choice values: ^ .. ^#!", C);
+ else
+ Error_Msg_Name_1 := Choice_Image (Lo, Bounds_Type);
+ Error_Msg_Name_2 := Choice_Image (Hi, Bounds_Type);
+ Error_Msg_N ("duplication of choice values: % .. %#!", C);
+ end if;
+ end if;
+ end Dup_Choice;
+
------------------------------
-- Explain_Non_Static_Bound --
------------------------------
@@ -443,21 +502,21 @@ package body Sem_Case is
if Nkind (Case_Node) = N_Variant_Part then
Error_Msg_NE
- ("bounds of & are not static," &
- " alternatives must cover base type", Expr, Expr);
+ ("bounds of & are not static, "
+ & "alternatives must cover base type!", Expr, Expr);
-- If this is a case statement, the expression may be non-static
-- or else the subtype may be at fault.
elsif Is_Entity_Name (Expr) then
Error_Msg_NE
- ("bounds of & are not static," &
- " alternatives must cover base type", Expr, Expr);
+ ("bounds of & are not static, "
+ & "alternatives must cover base type!", Expr, Expr);
else
Error_Msg_N
- ("subtype of expression is not static,"
- & " alternatives must cover base type!", Expr);
+ ("subtype of expression is not static, "
+ & "alternatives must cover base type!", Expr);
end if;
-- Otherwise the expression is not static, even if the bounds of the
@@ -600,7 +659,7 @@ package body Sem_Case is
Prev_Lo : Uint;
Prev_Hi : Uint;
- -- Start of processing for Check_Choices
+ -- Start of processing for Check_Choice_Set
begin
-- Choice_Table must start at 0 which is an unused location used by the
@@ -693,10 +752,12 @@ package body Sem_Case is
if Sloc (Prev_Choice) <= Sloc (Choice) then
Error_Msg_Sloc := Sloc (Prev_Choice);
- Error_Msg_N ("duplication of choice value#", Choice);
+ Dup_Choice
+ (Choice_Lo, UI_Min (Choice_Hi, Prev_Hi), Choice);
else
Error_Msg_Sloc := Sloc (Choice);
- Error_Msg_N ("duplication of choice value#", Prev_Choice);
+ Dup_Choice
+ (Choice_Lo, UI_Min (Choice_Hi, Prev_Hi), Prev_Choice);
end if;
elsif not Others_Present and then Choice_Lo /= Prev_Hi + 1 then
@@ -708,15 +769,15 @@ package body Sem_Case is
end if;
end loop;
- if not Others_Present and then Expr_Value (Bounds_Hi) > Choice_Hi then
- Missing_Choice (Choice_Hi + 1, Bounds_Hi);
+ if not Others_Present and then Expr_Value (Bounds_Hi) > Prev_Hi then
+ Missing_Choice (Prev_Hi + 1, Bounds_Hi);
- if Expr_Value (Bounds_Hi) > Choice_Hi + 1 then
+ if Expr_Value (Bounds_Hi) > Prev_Hi + 1 then
Explain_Non_Static_Bound;
end if;
end if;
end if;
- end Check_Choices;
+ end Check_Choice_Set;
------------------
-- Choice_Image --
@@ -801,11 +862,10 @@ package body Sem_Case is
Previous_Hi : Uint;
function Build_Choice (Value1, Value2 : Uint) return Node_Id;
- -- Builds a node representing the missing choices given by the
- -- Value1 and Value2. A N_Range node is built if there is more than
- -- one literal value missing. Otherwise a single N_Integer_Literal,
- -- N_Identifier or N_Character_Literal is built depending on what
- -- Choice_Type is.
+ -- Builds a node representing the missing choices given by Value1 and
+ -- Value2. A N_Range node is built if there is more than one literal
+ -- value missing. Otherwise a single N_Integer_Literal, N_Identifier
+ -- or N_Character_Literal is built depending on what Choice_Type is.
function Lit_Of (Value : Uint) return Node_Id;
-- Returns the Node_Id for the enumeration literal corresponding to the
@@ -977,11 +1037,11 @@ package body Sem_Case is
null;
end No_OP;
- --------------------------------
- -- Generic_Choices_Processing --
- --------------------------------
+ -----------------------------
+ -- Generic_Analyze_Choices --
+ -----------------------------
- package body Generic_Choices_Processing is
+ package body Generic_Analyze_Choices is
-- The following type is used to gather the entries for the choice
-- table, so that we can then allocate the right length.
@@ -994,20 +1054,143 @@ package body Sem_Case is
Nxt : Link_Ptr;
end record;
- procedure Free is new Ada.Unchecked_Deallocation (Link, Link_Ptr);
-
---------------------
-- Analyze_Choices --
---------------------
procedure Analyze_Choices
- (N : Node_Id;
- Subtyp : Entity_Id;
- Raises_CE : out Boolean;
- Others_Present : out Boolean)
+ (Alternatives : List_Id;
+ Subtyp : Entity_Id)
+ is
+ Choice_Type : constant Entity_Id := Base_Type (Subtyp);
+ -- The actual type against which the discrete choices are resolved.
+ -- Note that this type is always the base type not the subtype of the
+ -- ruling expression, index or discriminant.
+
+ Expected_Type : Entity_Id;
+ -- The expected type of each choice. Equal to Choice_Type, except if
+ -- the expression is universal, in which case the choices can be of
+ -- any integer type.
+
+ Alt : Node_Id;
+ -- A case statement alternative or a variant in a record type
+ -- declaration.
+
+ Choice : Node_Id;
+ Kind : Node_Kind;
+ -- The node kind of the current Choice
+
+ begin
+ -- Set Expected type (= choice type except for universal integer,
+ -- where we accept any integer type as a choice).
+
+ if Choice_Type = Universal_Integer then
+ Expected_Type := Any_Integer;
+ else
+ Expected_Type := Choice_Type;
+ end if;
+
+ -- Now loop through the case alternatives or record variants
+
+ Alt := First (Alternatives);
+ while Present (Alt) loop
+
+ -- If pragma, just analyze it
+
+ if Nkind (Alt) = N_Pragma then
+ Analyze (Alt);
+
+ -- Otherwise we have an alternative. In most cases the semantic
+ -- processing leaves the list of choices unchanged
+
+ -- Check each choice against its base type
+
+ else
+ Choice := First (Discrete_Choices (Alt));
+ while Present (Choice) loop
+ Analyze (Choice);
+ Kind := Nkind (Choice);
+
+ -- Choice is a Range
+
+ if Kind = N_Range
+ or else (Kind = N_Attribute_Reference
+ and then Attribute_Name (Choice) = Name_Range)
+ then
+ Resolve (Choice, Expected_Type);
+
+ -- Choice is a subtype name, nothing further to do now
+
+ elsif Is_Entity_Name (Choice)
+ and then Is_Type (Entity (Choice))
+ then
+ null;
+
+ -- Choice is a subtype indication
+
+ elsif Kind = N_Subtype_Indication then
+ Resolve_Discrete_Subtype_Indication
+ (Choice, Expected_Type);
+
+ -- Others choice, no analysis needed
+
+ elsif Kind = N_Others_Choice then
+ null;
+
+ -- Only other possibility is an expression
+
+ else
+ Resolve (Choice, Expected_Type);
+ end if;
+
+ -- Move to next choice
+
+ Next (Choice);
+ end loop;
+
+ Process_Associated_Node (Alt);
+ end if;
+
+ Next (Alt);
+ end loop;
+ end Analyze_Choices;
+
+ end Generic_Analyze_Choices;
+
+ ---------------------------
+ -- Generic_Check_Choices --
+ ---------------------------
+
+ package body Generic_Check_Choices is
+
+ -- The following type is used to gather the entries for the choice
+ -- table, so that we can then allocate the right length.
+
+ type Link;
+ type Link_Ptr is access all Link;
+
+ type Link is record
+ Val : Choice_Bounds;
+ Nxt : Link_Ptr;
+ end record;
+
+ procedure Free is new Ada.Unchecked_Deallocation (Link, Link_Ptr);
+
+ -------------------
+ -- Check_Choices --
+ -------------------
+
+ procedure Check_Choices
+ (N : Node_Id;
+ Alternatives : List_Id;
+ Subtyp : Entity_Id;
+ Others_Present : out Boolean)
is
E : Entity_Id;
+ Raises_CE : Boolean;
+ -- Set True if one of the bounds of a choice raises CE
+
Enode : Node_Id;
-- This is where we post error messages for bounds out of range
@@ -1044,9 +1227,6 @@ package body Sem_Case is
Kind : Node_Kind;
-- The node kind of the current Choice
- Delete_Choice : Boolean;
- -- Set to True to delete the current choice
-
Others_Choice : Node_Id := Empty;
-- Remember others choice if it is present (empty otherwise)
@@ -1168,12 +1348,20 @@ package body Sem_Case is
Num_Choices := Num_Choices + 1;
end Check;
- -- Start of processing for Analyze_Choices
+ -- Start of processing for Check_Choices
begin
Raises_CE := False;
Others_Present := False;
+ -- If Subtyp is not a discrete type or there was some other error,
+ -- then don't try any semantic checking on the choices since we have
+ -- a complete mess.
+
+ if not Is_Discrete_Type (Subtyp) or else Subtyp = Any_Type then
+ return;
+ end if;
+
-- If Subtyp is not a static subtype Ada 95 requires then we use the
-- bounds of its base type to determine the values covered by the
-- discrete choices.
@@ -1212,7 +1400,7 @@ package body Sem_Case is
-- Now loop through the case alternatives or record variants
- Alt := First (Get_Alternatives (N));
+ Alt := First (Alternatives);
while Present (Alt) loop
-- If pragma, just analyze it
@@ -1220,13 +1408,14 @@ package body Sem_Case is
if Nkind (Alt) = N_Pragma then
Analyze (Alt);
- -- Otherwise check each choice against its base type
+ -- Otherwise we have an alternative. In most cases the semantic
+ -- processing leaves the list of choices unchanged
+
+ -- Check each choice against its base type
else
- Choice := First (Get_Choices (Alt));
+ Choice := First (Discrete_Choices (Alt));
while Present (Choice) loop
- Delete_Choice := False;
- Analyze (Choice);
Kind := Nkind (Choice);
-- Choice is a Range
@@ -1235,7 +1424,6 @@ package body Sem_Case is
or else (Kind = N_Attribute_Reference
and then Attribute_Name (Choice) = Name_Range)
then
- Resolve (Choice, Expected_Type);
Check (Choice, Low_Bound (Choice), High_Bound (Choice));
-- Choice is a subtype name
@@ -1243,9 +1431,13 @@ package body Sem_Case is
elsif Is_Entity_Name (Choice)
and then Is_Type (Entity (Choice))
then
+ -- Check for inappropriate type
+
if not Covers (Expected_Type, Etype (Choice)) then
Wrong_Type (Choice, Choice_Type);
+ -- Type is OK, so check further
+
else
E := Entity (Choice);
@@ -1260,34 +1452,32 @@ package body Sem_Case is
then
Bad_Predicated_Subtype_Use
("cannot use subtype& with non-static "
- & "predicate as case alternative", Choice, E,
- Suggest_Static => True);
+ & "predicate as case alternative",
+ Choice, E, Suggest_Static => True);
- -- Static predicate case
+ -- Static predicate case
else
declare
- Copy : constant List_Id := Empty_List;
- P : Node_Id;
- C : Node_Id;
+ P : Node_Id;
+ C : Node_Id;
begin
-- Loop through entries in predicate list,
- -- converting to choices. Note that if the
+ -- checking each entry. Note that if the
-- list is empty, corresponding to a False
- -- predicate, then no choices are inserted.
+ -- predicate, then no choices are checked.
P := First (Static_Predicate (E));
while Present (P) loop
C := New_Copy (P);
Set_Sloc (C, Sloc (Choice));
- Append_To (Copy, C);
+ Check (C, Low_Bound (C), High_Bound (C));
Next (P);
end loop;
-
- Insert_List_After (Choice, Copy);
- Delete_Choice := True;
end;
+
+ Set_Has_SP_Choice (Alt);
end if;
-- Not predicated subtype case
@@ -1306,8 +1496,6 @@ package body Sem_Case is
Resolve_Discrete_Subtype_Indication
(Choice, Expected_Type);
- -- Here for other than predicated subtype case
-
if Etype (Choice) /= Any_Type then
declare
C : constant Node_Id := Constraint (Choice);
@@ -1323,7 +1511,8 @@ package body Sem_Case is
else
if Is_OK_Static_Expression (L)
- and then Is_OK_Static_Expression (H)
+ and then
+ Is_OK_Static_Expression (H)
then
if Expr_Value (L) > Expr_Value (H) then
Process_Empty_Choice (Choice);
@@ -1351,9 +1540,9 @@ package body Sem_Case is
-- alternative and as its only choice.
elsif Kind = N_Others_Choice then
- if not (Choice = First (Get_Choices (Alt))
- and then Choice = Last (Get_Choices (Alt))
- and then Alt = Last (Get_Alternatives (N)))
+ if not (Choice = First (Discrete_Choices (Alt))
+ and then Choice = Last (Discrete_Choices (Alt))
+ and then Alt = Last (Alternatives))
then
Error_Msg_N
("the choice OTHERS must appear alone and last",
@@ -1367,22 +1556,12 @@ package body Sem_Case is
-- Only other possibility is an expression
else
- Resolve (Choice, Expected_Type);
Check (Choice, Choice, Choice);
end if;
- -- Move to next choice, deleting the current one if the
- -- flag requesting this deletion is set True.
-
- declare
- C : constant Node_Id := Choice;
- begin
- Next (Choice);
+ -- Move to next choice
- if Delete_Choice then
- Remove (C);
- end if;
- end;
+ Next (Choice);
end loop;
Process_Associated_Node (Alt);
@@ -1412,7 +1591,7 @@ package body Sem_Case is
end loop;
end;
- Check_Choices
+ Check_Choice_Set
(Choice_Table,
Bounds_Type,
Subtyp,
@@ -1431,8 +1610,8 @@ package body Sem_Case is
Choice_Type => Bounds_Type);
end if;
end;
- end Analyze_Choices;
+ end Check_Choices;
- end Generic_Choices_Processing;
+ end Generic_Check_Choices;
end Sem_Case;
diff --git a/gcc/ada/sem_case.ads b/gcc/ada/sem_case.ads
index ccee41f02a9..c6917f06837 100644
--- a/gcc/ada/sem_case.ads
+++ b/gcc/ada/sem_case.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 1996-2010, Free Software Foundation, Inc. --
+-- Copyright (C) 1996-2013, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -30,58 +30,124 @@
-- aggregate case, since issues with nested aggregates make that case
-- substantially different.
+-- The following processing is required for such cases:
+
+-- 1. Analysis of names of subtypes, constants, expressions appearing within
+-- the choices. This must be done when the construct is encountered to get
+-- proper visibility of names.
+
+-- 2. Checking for semantic correctness of the choices. A lot of this could
+-- be done at the time when the construct is encountered, but not all, since
+-- in the case of variants, statically predicated subtypes won't be frozen
+-- (and the choice sets known) till the enclosing record type is frozen. So
+-- at least the check for no overlaps and covering the range must be delayed
+-- till the freeze point in this case.
+
+-- 3. Set the Others_Discrete_Choices list for an others choice. This is
+-- used in various ways, e.g. to construct the disriminant checking function
+-- for the case of a variant with an others choice.
+
+-- 4. In the case of static predicates, we need to expand out choices that
+-- correspond to the predicate for the back end. This expansion destroys
+-- the list of choices, so it should be delayed to expansion time. We do
+-- not want to mess up the -gnatct ASIS tree, which needs to be able to
+
+-- Step 1 is performed by the generic procedure Analyze_Choices, which is
+-- called when the variant record or case statement/expression is first
+-- encountered.
+
+-- Step 2 is performed by the generic procedure Check_Choices. We decide to
+-- do all semantic checking in that step, since as noted above some of this
+-- has to be deferred to the freeze point in any case for variants. For case
+-- statements and expressions, this procedure can be called at the time the
+-- case construct is encountered (after calling Analyze_Choices).
+
+-- Step 3 is also performed by Check_Choices, since we need the static ranges
+-- for predicated subtypes to accurately construct this.
+
+-- Step 4 is performed by the procedure Expand_Static_Predicates_In_Choices.
+-- For case statements, this call only happens during expansion, so the tree
+-- generated for ASIS does not have this expansion. For the Variant case, the
+-- expansion is done in the ASIS -gnatct case, but with a proper Rewrite call
+-- on the N_Variant node, so ASIS can retrieve the original. The reason we do
+-- the expansion unconditionally for variants is that other processing, for
+-- example for aggregates, relies on having a complete list of choices.
+
+-- Historical note: We used to perform all four of these functions at once in
+-- a single procedure called Analyze_Choices. This routine was called at the
+-- time the construct was first encountered. That seemed to work OK up to Ada
+-- 2005, but the introduction of statically predicated subtypes with delayed
+-- evaluation of the static ranges made this completely wrong, both because
+-- the ASIS tree got destroyed by step 4, and steps 2 and 3 were too early
+-- in the variant record case.
+
with Types; use Types;
package Sem_Case is
procedure No_OP (C : Node_Id);
-- The no-operation routine. Does absolutely nothing. Can be used
- -- in the following generic for the parameter Process_Empty_Choice.
+ -- in the following generics for the parameters Process_Empty_Choice,
+ -- or Process_Associated_Node.
generic
- with function Get_Alternatives (N : Node_Id) return List_Id;
- -- Function needed to get to the actual list of case statement
- -- alternatives, or array aggregate component associations or
- -- record variants from which we can then access the actual lists
- -- of discrete choices. N is the node for the original construct
- -- i.e. a case statement, an array aggregate or a record variant.
-
- with function Get_Choices (A : Node_Id) return List_Id;
- -- Given a case statement alternative, array aggregate component
- -- association or record variant A we need different access functions
- -- to get to the actual list of discrete choices.
+ with procedure Process_Associated_Node (A : Node_Id);
+ -- Associated with each case alternative or record variant A there is
+ -- a node or list of nodes that need additional processing. This routine
+ -- implements that processing.
+
+ package Generic_Analyze_Choices is
+
+ procedure Analyze_Choices
+ (Alternatives : List_Id;
+ Subtyp : Entity_Id);
+ -- From a case expression, case statement, or record variant, this
+ -- routine analyzes the corresponding list of discrete choices which
+ -- appear in each element of the list Alternatives (for the variant
+ -- part case, this is the variants, for a case expression or statement,
+ -- this is the Alternatives).
+ --
+ -- Subtyp is the subtype of the discrete choices. The type against which
+ -- the discrete choices must be resolved is its base type.
+ end Generic_Analyze_Choices;
+
+ generic
with procedure Process_Empty_Choice (Choice : Node_Id);
- -- Processing to carry out for an empty Choice
+ -- Processing to carry out for an empty Choice. Set to No_Op (declared
+ -- above) if no such processing is required.
with procedure Process_Non_Static_Choice (Choice : Node_Id);
- -- Processing to carry out for a non static Choice
+ -- Processing to carry out for a non static Choice (gives an error msg)
with procedure Process_Associated_Node (A : Node_Id);
- -- Associated with each case alternative, aggregate component
- -- association or record variant A there is a node or list of nodes
- -- that need semantic processing. This routine implements that
- -- processing.
+ -- Associated with each case alternative or record variant A there is
+ -- a node or list of nodes that need semantic processing. This routine
+ -- implements that processing.
- package Generic_Choices_Processing is
+ package Generic_Check_Choices is
- procedure Analyze_Choices
- (N : Node_Id;
- Subtyp : Entity_Id;
- Raises_CE : out Boolean;
- Others_Present : out Boolean);
- -- From a case expression, case statement, array aggregate or record
- -- variant N, this routine analyzes the corresponding list of discrete
- -- choices. Subtyp is the subtype of the discrete choices. The type
- -- against which the discrete choices must be resolved is its base type.
+ procedure Check_Choices
+ (N : Node_Id;
+ Alternatives : List_Id;
+ Subtyp : Entity_Id;
+ Others_Present : out Boolean);
+ -- From a case expression, case statement, or record variant N, this
+ -- routine analyzes the corresponding list of discrete choices which
+ -- appear in each element of the list Alternatives (for the variant
+ -- part case, this is the variants, for a case expression or statement,
+ -- this is the Alternatives).
--
- -- In one of the bounds of a discrete choice raises a constraint
- -- error the flag Raise_CE is set.
+ -- Subtyp is the subtype of the discrete choices. The type against which
+ -- the discrete choices must be resolved is its base type.
--
- -- Finally Others_Present is set to True if an Others choice is present
- -- in the list of choices, and in this case the call also sets
- -- Others_Discrete_Choices in the N_Others_Choice node.
-
- end Generic_Choices_Processing;
+ -- Others_Present is set to True if an Others choice is present in the
+ -- list of choices, and in this case Others_Discrete_Choices is set in
+ -- the N_Others_Choice node.
+ --
+ -- If a Discrete_Choice list contains at least one instance of a subtype
+ -- with a static predicate, then the Has_SP_Choice flag is set true in
+ -- the parent node (N_Variant, N_Case_Expression/Statement_Alternative).
+ end Generic_Check_Choices;
end Sem_Case;
diff --git a/gcc/ada/sem_cat.adb b/gcc/ada/sem_cat.adb
index e4615393dd2..79201c4edf0 100644
--- a/gcc/ada/sem_cat.adb
+++ b/gcc/ada/sem_cat.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2012, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -561,8 +561,7 @@ package body Sem_Cat is
and then Is_Package_Or_Generic_Package (Unit_Entity)
and then Unit_Kind /= N_Package_Body
and then List_Containing (N) =
- Visible_Declarations
- (Specification (Unit_Declaration_Node (Unit_Entity)))
+ Visible_Declarations (Package_Specification (Unit_Entity))
and then not In_Package_Body (Unit_Entity)
and then not In_Instance;
diff --git a/gcc/ada/sem_ch10.adb b/gcc/ada/sem_ch10.adb
index 6c36bf2cdb7..78520f8b0a1 100644
--- a/gcc/ada/sem_ch10.adb
+++ b/gcc/ada/sem_ch10.adb
@@ -53,6 +53,7 @@ with Sem_Ch3; use Sem_Ch3;
with Sem_Ch6; use Sem_Ch6;
with Sem_Ch7; use Sem_Ch7;
with Sem_Ch8; use Sem_Ch8;
+with Sem_Ch13; use Sem_Ch13;
with Sem_Dist; use Sem_Dist;
with Sem_Prag; use Sem_Prag;
with Sem_Util; use Sem_Util;
@@ -329,9 +330,8 @@ package body Sem_Ch10 is
function Same_Unit (N : Node_Id; P : Entity_Id) return Boolean is
begin
return Entity (N) = P
- or else
- (Present (Renamed_Object (P))
- and then Entity (N) = Renamed_Object (P));
+ or else (Present (Renamed_Object (P))
+ and then Entity (N) = Renamed_Object (P));
end Same_Unit;
-- Start of processing for Process_Body_Clauses
@@ -403,14 +403,12 @@ package body Sem_Ch10 is
elsif Nkind (Cont_Item) = N_Pragma
and then
Nam_In (Pragma_Name (Cont_Item), Name_Elaborate,
- Name_Elaborate_All)
+ Name_Elaborate_All)
and then not Used_Type_Or_Elab
then
Prag_Unit :=
First (Pragma_Argument_Associations (Cont_Item));
- while Present (Prag_Unit)
- and then not Used_Type_Or_Elab
- loop
+ while Present (Prag_Unit) and then not Used_Type_Or_Elab loop
if Entity (Expression (Prag_Unit)) = Nam_Ent then
Used_Type_Or_Elab := True;
end if;
@@ -477,7 +475,7 @@ package body Sem_Ch10 is
-- with Pack;
-- with Pack;
-- pragma Elaborate (Pack);
- --
+
-- In this case, the second with clause is redundant since
-- the pragma applies only to the first "with Pack;".
@@ -557,10 +555,8 @@ package body Sem_Ch10 is
if (Withed_In_Spec
and then not Used_Type_Or_Elab)
and then
- ((not Used_In_Spec
- and then not Used_In_Body)
- or else
- Used_In_Spec)
+ ((not Used_In_Spec and then not Used_In_Body)
+ or else Used_In_Spec)
then
Error_Msg_N -- CODEFIX
("redundant with clause in body??", Clause);
@@ -1013,9 +1009,8 @@ package body Sem_Ch10 is
N_Package_Renaming_Declaration,
N_Subprogram_Declaration)
or else Nkind (Unit_Node) in N_Generic_Declaration
- or else
- (Nkind (Unit_Node) = N_Subprogram_Body
- and then Acts_As_Spec (Unit_Node))
+ or else (Nkind (Unit_Node) = N_Subprogram_Body
+ and then Acts_As_Spec (Unit_Node))
then
Remove_Unit_From_Visibility (Defining_Entity (Unit_Node));
@@ -1581,6 +1576,7 @@ package body Sem_Ch10 is
Set_Has_Completion (Nam);
Set_Scope (Defining_Entity (N), Current_Scope);
+ Set_Corresponding_Spec_Of_Stub (N, Nam);
Generate_Reference (Nam, Id, 'b');
Analyze_Proper_Body (N, Nam);
end if;
@@ -1664,6 +1660,10 @@ package body Sem_Ch10 is
end if;
end Optional_Subunit;
+ -- Local variables
+
+ Stub_Id : Entity_Id;
+
-- Start of processing for Analyze_Proper_Body
begin
@@ -1818,6 +1818,7 @@ package body Sem_Ch10 is
declare
Comp_Unit : constant Node_Id := Cunit (Unum);
+ Prop_Body : Node_Id;
begin
-- Check for child unit instead of subunit
@@ -1830,6 +1831,8 @@ package body Sem_Ch10 is
-- OK, we have a subunit
else
+ Prop_Body := Proper_Body (Unit (Comp_Unit));
+
-- Set corresponding stub (even if errors)
Set_Corresponding_Stub (Unit (Comp_Unit), N);
@@ -1845,11 +1848,17 @@ package body Sem_Ch10 is
SCO_Record (Unum);
end if;
- -- Propagate any aspect specifications associated with
- -- with the stub to the proper body.
+ -- Propagate all aspect specifications associated with
+ -- the stub to the proper body.
+
+ Move_Or_Merge_Aspects (From => N, To => Prop_Body);
- Move_Or_Merge_Aspects
- (From => N, To => Proper_Body (Unit (Comp_Unit)));
+ -- Move all source pragmas that follow the body stub and
+ -- apply to it to the declarations of the proper body.
+
+ if Nkind (N) = N_Subprogram_Body_Stub then
+ Relocate_Pragmas_To_Body (N, Target_Body => Prop_Body);
+ end if;
-- Analyze the unit if semantics active
@@ -1869,6 +1878,24 @@ package body Sem_Ch10 is
Version_Update (Cunit (Main_Unit), Comp_Unit);
end if;
end;
+
+ -- The unit which should contain the proper subprogram body does
+ -- not exist. Analyze the aspect specifications of the stub (if
+ -- any).
+
+ elsif Nkind (N) = N_Subprogram_Body_Stub
+ and then Has_Aspects (N)
+ then
+ Stub_Id := Defining_Unit_Name (Specification (N));
+
+ -- Restore the proper visibility of the stub and its formals
+
+ Push_Scope (Stub_Id);
+ Install_Formals (Stub_Id);
+
+ Analyze_Aspect_Specifications (N, Stub_Id);
+
+ Pop_Scope;
end if;
end if;
@@ -1899,13 +1926,13 @@ package body Sem_Ch10 is
Nam := Full_View (Nam);
end if;
- if No (Nam)
- or else not Is_Protected_Type (Etype (Nam))
- then
+ if No (Nam) or else not Is_Protected_Type (Etype (Nam)) then
Error_Msg_N ("missing specification for Protected body", N);
+
else
Set_Scope (Defining_Entity (N), Current_Scope);
Set_Has_Completion (Etype (Nam));
+ Set_Corresponding_Spec_Of_Stub (N, Nam);
Generate_Reference (Nam, Defining_Identifier (N), 'b');
Analyze_Proper_Body (N, Etype (Nam));
end if;
@@ -1936,9 +1963,7 @@ package body Sem_Ch10 is
N_Subprogram_Body)
then
Decl := First (Declarations (Parent (N)));
- while Present (Decl)
- and then Decl /= N
- loop
+ while Present (Decl) and then Decl /= N loop
if Nkind (Decl) = N_Subprogram_Body_Stub
and then (Chars (Defining_Unit_Name (Specification (Decl))) =
Chars (Defining_Unit_Name (Specification (N))))
@@ -2150,9 +2175,7 @@ package body Sem_Ch10 is
E := First_Entity (Current_Scope);
while Present (E) loop
- if not Is_Child_Unit (E)
- or else Is_Visible_Lib_Unit (E)
- then
+ if not Is_Child_Unit (E) or else Is_Visible_Lib_Unit (E) then
Set_Is_Immediately_Visible (E);
end if;
@@ -2278,8 +2301,8 @@ package body Sem_Ch10 is
if Is_Package_Or_Generic_Package (Par_Unit) then
if not Is_Immediately_Visible (Par_Unit)
or else (Present (First_Entity (Par_Unit))
- and then not Is_Immediately_Visible
- (First_Entity (Par_Unit)))
+ and then not
+ Is_Immediately_Visible (First_Entity (Par_Unit)))
then
Set_Is_Immediately_Visible (Par_Unit);
Install_Visible_Declarations (Par_Unit);
@@ -2351,6 +2374,7 @@ package body Sem_Ch10 is
else
Set_Scope (Defining_Entity (N), Current_Scope);
Generate_Reference (Nam, Defining_Identifier (N), 'b');
+ Set_Corresponding_Spec_Of_Stub (N, Nam);
-- Check for duplicate stub, if so give message and terminate
@@ -2888,7 +2912,7 @@ package body Sem_Ch10 is
or else Private_Present (Item)
or else Nkind_In (Lib_Unit, N_Package_Body, N_Subunit)
or else (Nkind (Lib_Unit) = N_Subprogram_Body
- and then not Acts_As_Spec (Parent (Lib_Unit)))
+ and then not Acts_As_Spec (Parent (Lib_Unit)))
then
null;
@@ -3429,7 +3453,7 @@ package body Sem_Ch10 is
if Nkind (Lib_Unit) = N_Package_Body
or else (Nkind (Lib_Unit) = N_Subprogram_Body
- and then not Acts_As_Spec (N))
+ and then not Acts_As_Spec (N))
then
Install_Context (Library_Unit (N));
@@ -3601,9 +3625,7 @@ package body Sem_Ch10 is
-- Check all the enclosing scopes.
E2 := E;
- while E2 /= Standard_Standard
- and then E2 /= WEnt
- loop
+ while E2 /= Standard_Standard and then E2 /= WEnt loop
E2 := Scope (E2);
end loop;
@@ -3821,9 +3843,7 @@ package body Sem_Ch10 is
Check_Private_Limited_Withed_Unit (Item);
- if not Implicit_With (Item)
- and then Is_Child_Spec (Unit (N))
- then
+ if not Implicit_With (Item) and then Is_Child_Spec (Unit (N)) then
Check_Renamings (Parent_Spec (Unit (N)), Item);
end if;
@@ -3877,7 +3897,7 @@ package body Sem_Ch10 is
and then
Ekind (Defining_Identifier (Decl)) = E_Incomplete_Subtype
and then
- From_With_Type (Defining_Identifier (Decl))
+ From_Limited_With (Defining_Identifier (Decl))
then
Def_Id := Defining_Identifier (Decl);
Non_Lim_View := Non_Limited_View (Def_Id);
@@ -3963,7 +3983,7 @@ package body Sem_Ch10 is
or else Nkind (Original_Node (Lib_Unit)) in N_Generic_Instantiation
or else
(Nkind (Lib_Unit) = N_Package_Declaration
- and then Present (Generic_Parent (Specification (Lib_Unit))))
+ and then Present (Generic_Parent (Specification (Lib_Unit))))
then
null;
else
@@ -4008,7 +4028,7 @@ package body Sem_Ch10 is
Is_Private_Descendant (P_Name)
or else Private_Present (Parent (Lib_Unit)));
- P_Spec := Specification (Unit_Declaration_Node (P_Name));
+ P_Spec := Package_Specification (P_Name);
Push_Scope (P_Name);
-- Save current visibility of unit
@@ -4026,9 +4046,7 @@ package body Sem_Ch10 is
Set_Use (Generic_Formal_Declarations (Parent (P_Spec)));
end if;
- if Is_Private
- or else Private_Present (Parent (Lib_Unit))
- then
+ if Is_Private or else Private_Present (Parent (Lib_Unit)) then
Install_Private_Declarations (P_Name);
Install_Private_With_Clauses (P_Name);
Set_Use (Private_Declarations (P_Spec));
@@ -4957,7 +4975,18 @@ package body Sem_Ch10 is
-- Replace E in the homonyms list, so that the limited view
-- becomes available.
- if E = Non_Limited_View (Lim_Typ) then
+ -- If the non-limited view is a record with an anonymous
+ -- self-referential component, the analysis of the record
+ -- declaration creates an incomplete type with the same name
+ -- in order to define an internal access type. The visible
+ -- entity is now the incomplete type, and that is the one to
+ -- replace in the visibility structure.
+
+ if E = Non_Limited_View (Lim_Typ)
+ or else
+ (Ekind (E) = E_Incomplete_Type
+ and then Full_View (E) = Non_Limited_View (Lim_Typ))
+ then
Set_Homonym (Lim_Typ, Homonym (Prev));
Set_Current_Entity (Lim_Typ);
@@ -4969,9 +4998,7 @@ package body Sem_Ch10 is
-- limited_with_clause.
exit when No (E);
-
exit when E = Non_Limited_View (Lim_Typ);
-
Prev := Homonym (Prev);
end loop;
@@ -5049,7 +5076,7 @@ package body Sem_Ch10 is
end if;
Set_Entity (Name (N), P);
- Set_From_With_Type (P);
+ Set_From_Limited_With (P);
end Install_Limited_Withed_Unit;
-------------------------
@@ -5093,7 +5120,7 @@ package body Sem_Ch10 is
if Sloc (Uname) /= No_Location
and then (not Is_Internal_File_Name (Unit_File_Name (Current_Sem_Unit))
- or else Current_Sem_Unit = Main_Unit)
+ or else Current_Sem_Unit = Main_Unit)
then
Check_Restricted_Unit
(Unit_Name (Get_Source_Unit (Uname)), With_Clause);
@@ -5165,7 +5192,7 @@ package body Sem_Ch10 is
-- tions on the use of package entities.
if Ekind (Uname) = E_Package then
- Set_From_With_Type (Uname, False);
+ Set_From_Limited_With (Uname, False);
end if;
-- Ada 2005 (AI-377): it is illegal for a with_clause to name a child
@@ -5189,9 +5216,7 @@ package body Sem_Ch10 is
begin
U2 := Homonym (Uname);
- while Present (U2)
- and then U2 /= Standard_Standard
- loop
+ while Present (U2) and then U2 /= Standard_Standard loop
P2 := Scope (U2);
Decl2 := Unit_Declaration_Node (P2);
@@ -5354,328 +5379,262 @@ package body Sem_Ch10 is
-------------------------
procedure Build_Limited_Views (N : Node_Id) is
+ Nam : constant Node_Id := Name (N);
Unum : constant Unit_Number_Type := Get_Source_Unit (Library_Unit (N));
- P : constant Entity_Id := Cunit_Entity (Unum);
-
- Spec : Node_Id; -- To denote a package specification
- Lim_Typ : Entity_Id; -- To denote shadow entities
- Comp_Typ : Entity_Id; -- To denote real entities
-
- Lim_Header : Entity_Id; -- Package entity
- Last_Lim_E : Entity_Id := Empty; -- Last limited entity built
- Last_Pub_Lim_E : Entity_Id; -- To set the first private entity
-
- procedure Decorate_Incomplete_Type (E : Entity_Id; Scop : Entity_Id);
- -- Add attributes of an incomplete type to a shadow entity. The same
- -- attributes are placed on the real entity, so that gigi receives
- -- a consistent view.
-
- procedure Decorate_Package_Specification (P : Entity_Id);
- -- Add attributes of a package entity to the entity in a package
- -- declaration
-
- procedure Decorate_Tagged_Type
- (Loc : Source_Ptr;
- T : Entity_Id;
- Scop : Entity_Id;
- Mark : Boolean := False);
- -- Set basic attributes of tagged type T, including its class-wide type.
- -- The parameters Loc, Scope are used to decorate the class-wide type.
- -- Use flag Mark to label the class-wide type as Materialize_Entity.
-
- procedure Build_Chain (Scope : Entity_Id; First_Decl : Node_Id);
- -- Construct list of shadow entities and attach it to entity of
- -- package that is mentioned in a limited_with clause.
-
- function New_Internal_Shadow_Entity
- (Kind : Entity_Kind;
- Sloc_Value : Source_Ptr;
- Id_Char : Character) return Entity_Id;
- -- Build a new internal entity and append it to the list of shadow
- -- entities available through the limited-header
-
- -----------------
- -- Build_Chain --
- -----------------
-
- procedure Build_Chain (Scope : Entity_Id; First_Decl : Node_Id) is
- Analyzed_Unit : constant Boolean := Analyzed (Cunit (Unum));
- Is_Tagged : Boolean;
- Decl : Node_Id;
+ Pack : constant Entity_Id := Cunit_Entity (Unum);
+
+ Shadow_Pack : Entity_Id;
+ -- The corresponding shadow entity of the withed package. This entity
+ -- offers incomplete views of all types and visible packages declared
+ -- within.
+
+ Last_Shadow : Entity_Id := Empty;
+ -- The last shadow entity created by routine Build_Shadow_Entity
+
+ function Build_Shadow_Entity
+ (Ent : Entity_Id;
+ Scop : Entity_Id;
+ Is_Tagged : Boolean := False) return Entity_Id;
+ -- Create a shadow entity that hides Ent and offers an incomplete view
+ -- of Ent. Scop is the proper scope. Flag Is_Tagged should be set when
+ -- Ent is a tagged type. The generated entity is added to Lim_Header.
+ -- This routine updates the value of Last_Shadow.
+
+ procedure Decorate_Package (Ent : Entity_Id; Scop : Entity_Id);
+ -- Perform minimal decoration of a package or its corresponding shadow
+ -- entity denoted by Ent. Scop is the proper scope.
+
+ procedure Decorate_Type
+ (Ent : Entity_Id;
+ Scop : Entity_Id;
+ Is_Tagged : Boolean := False;
+ Materialize : Boolean := False);
+ -- Perform minimal decoration of a type or its corresponding shadow
+ -- entity denoted by Ent. Scop is the proper scope. Flag Is_Tagged
+ -- should be set when Ent is a tagged type. Flag Materialize should be
+ -- set when Ent is a tagged type and its class-wide type needs to appear
+ -- in the tree.
+
+ procedure Process_Declarations (Decls : List_Id; Scop : Entity_Id);
+ -- Inspect declarative list Decls and create shadow entities for all
+ -- types and packages encountered. Scop is the proper scope.
+
+ -------------------------
+ -- Build_Shadow_Entity --
+ -------------------------
+
+ function Build_Shadow_Entity
+ (Ent : Entity_Id;
+ Scop : Entity_Id;
+ Is_Tagged : Boolean := False) return Entity_Id
+ is
+ Shadow : constant Entity_Id := Make_Temporary (Sloc (Ent), 'Z');
begin
- Decl := First_Decl;
- while Present (Decl) loop
+ -- The shadow entity must share the same name and parent as the
+ -- entity it hides.
- -- For each library_package_declaration in the environment, there
- -- is an implicit declaration of a *limited view* of that library
- -- package. The limited view of a package contains:
-
- -- * For each nested package_declaration, a declaration of the
- -- limited view of that package, with the same defining-
- -- program-unit name.
-
- -- * For each type_declaration in the visible part, an incomplete
- -- type-declaration with the same defining_identifier, whose
- -- completion is the type_declaration. If the type_declaration
- -- is tagged, then the incomplete_type_declaration is tagged
- -- incomplete.
-
- -- The partial view is tagged if the declaration has the
- -- explicit keyword, or else if it is a type extension, both
- -- of which can be ascertained syntactically.
-
- if Nkind (Decl) = N_Full_Type_Declaration then
- Is_Tagged :=
- (Nkind (Type_Definition (Decl)) = N_Record_Definition
- and then Tagged_Present (Type_Definition (Decl)))
- or else
- (Nkind (Type_Definition (Decl)) = N_Derived_Type_Definition
- and then
- Present
- (Record_Extension_Part (Type_Definition (Decl))));
+ Set_Chars (Shadow, Chars (Ent));
+ Set_Parent (Shadow, Parent (Ent));
+ Set_Ekind (Shadow, Ekind (Ent));
+ Set_Is_Internal (Shadow);
+ Set_From_Limited_With (Shadow);
- Comp_Typ := Defining_Identifier (Decl);
+ -- Add the new shadow entity to the limited view of the package
- if not Analyzed_Unit then
- if Is_Tagged then
- Decorate_Tagged_Type (Sloc (Decl), Comp_Typ, Scope, True);
- else
- Decorate_Incomplete_Type (Comp_Typ, Scope);
- end if;
- end if;
+ Last_Shadow := Shadow;
+ Append_Entity (Shadow, Shadow_Pack);
- -- Create shadow entity for type
+ if Is_Type (Ent) then
+ Decorate_Type (Shadow, Scop, Is_Tagged);
- Lim_Typ :=
- New_Internal_Shadow_Entity
- (Kind => Ekind (Comp_Typ),
- Sloc_Value => Sloc (Comp_Typ),
- Id_Char => 'Z');
+ if Is_Incomplete_Or_Private_Type (Ent) then
+ Set_Private_Dependents (Shadow, New_Elmt_List);
+ end if;
- Set_Chars (Lim_Typ, Chars (Comp_Typ));
- Set_Parent (Lim_Typ, Parent (Comp_Typ));
- Set_From_With_Type (Lim_Typ);
+ Set_Non_Limited_View (Shadow, Ent);
- if Is_Tagged then
- Decorate_Tagged_Type (Sloc (Decl), Lim_Typ, Scope);
- else
- Decorate_Incomplete_Type (Lim_Typ, Scope);
- end if;
+ elsif Ekind (Ent) = E_Package then
+ Decorate_Package (Shadow, Scop);
+ end if;
- Set_Non_Limited_View (Lim_Typ, Comp_Typ);
- Set_Private_Dependents (Lim_Typ, New_Elmt_List);
+ return Shadow;
+ end Build_Shadow_Entity;
- elsif Nkind_In (Decl, N_Private_Type_Declaration,
- N_Incomplete_Type_Declaration,
- N_Task_Type_Declaration,
- N_Protected_Type_Declaration)
- then
- Comp_Typ := Defining_Identifier (Decl);
+ ----------------------
+ -- Decorate_Package --
+ ----------------------
- Is_Tagged :=
- Nkind_In (Decl, N_Private_Type_Declaration,
- N_Incomplete_Type_Declaration)
- and then Tagged_Present (Decl);
+ procedure Decorate_Package (Ent : Entity_Id; Scop : Entity_Id) is
+ begin
+ Set_Ekind (Ent, E_Package);
+ Set_Etype (Ent, Standard_Void_Type);
+ Set_Scope (Ent, Scop);
+ end Decorate_Package;
+
+ -------------------
+ -- Decorate_Type --
+ -------------------
+
+ procedure Decorate_Type
+ (Ent : Entity_Id;
+ Scop : Entity_Id;
+ Is_Tagged : Boolean := False;
+ Materialize : Boolean := False)
+ is
+ CW_Typ : Entity_Id;
- if not Analyzed_Unit then
- if Is_Tagged then
- Decorate_Tagged_Type (Sloc (Decl), Comp_Typ, Scope, True);
- else
- Decorate_Incomplete_Type (Comp_Typ, Scope);
- end if;
- end if;
+ begin
+ -- An unanalyzed type or a shadow entity of a type is treated as an
+ -- incomplete type.
+
+ Set_Ekind (Ent, E_Incomplete_Type);
+ Set_Etype (Ent, Ent);
+ Set_Scope (Ent, Scop);
+ Set_Is_First_Subtype (Ent);
+ Set_Stored_Constraint (Ent, No_Elist);
+ Set_Full_View (Ent, Empty);
+ Init_Size_Align (Ent);
+
+ -- A tagged type and its corresponding shadow entity share one common
+ -- class-wide type.
+
+ if Is_Tagged then
+ Set_Is_Tagged_Type (Ent);
+
+ if No (Class_Wide_Type (Ent)) then
+ CW_Typ :=
+ New_External_Entity
+ (E_Void, Scope (Ent), Sloc (Ent), Ent, 'C', 0, 'T');
+
+ Set_Class_Wide_Type (Ent, CW_Typ);
+
+ -- Set parent to be the same as the parent of the tagged type.
+ -- We need a parent field set, and it is supposed to point to
+ -- the declaration of the type. The tagged type declaration
+ -- essentially declares two separate types, the tagged type
+ -- itself and the corresponding class-wide type, so it is
+ -- reasonable for the parent fields to point to the declaration
+ -- in both cases.
+
+ Set_Parent (CW_Typ, Parent (Ent));
+
+ Set_Ekind (CW_Typ, E_Class_Wide_Type);
+ Set_Etype (CW_Typ, Ent);
+ Set_Scope (CW_Typ, Scop);
+ Set_Is_Tagged_Type (CW_Typ);
+ Set_Is_First_Subtype (CW_Typ);
+ Init_Size_Align (CW_Typ);
+ Set_Has_Unknown_Discriminants (CW_Typ);
+ Set_Class_Wide_Type (CW_Typ, CW_Typ);
+ Set_Equivalent_Type (CW_Typ, Empty);
+ Set_From_Limited_With (CW_Typ, From_Limited_With (Ent));
+ Set_Materialize_Entity (CW_Typ, Materialize);
+ end if;
+ end if;
+ end Decorate_Type;
- Lim_Typ :=
- New_Internal_Shadow_Entity
- (Kind => Ekind (Comp_Typ),
- Sloc_Value => Sloc (Comp_Typ),
- Id_Char => 'Z');
+ --------------------------
+ -- Process_Declarations --
+ --------------------------
- Set_Chars (Lim_Typ, Chars (Comp_Typ));
- Set_Parent (Lim_Typ, Parent (Comp_Typ));
- Set_From_With_Type (Lim_Typ);
+ procedure Process_Declarations (Decls : List_Id; Scop : Entity_Id) is
+ Is_Analyzed : constant Boolean := Analyzed (Cunit (Unum));
+ Is_Tagged : Boolean;
+ Decl : Node_Id;
+ Def : Node_Id;
+ Pack : Entity_Id;
+ Shadow : Entity_Id;
+ Typ : Entity_Id;
- if Is_Tagged then
- Decorate_Tagged_Type (Sloc (Decl), Lim_Typ, Scope);
- else
- Decorate_Incomplete_Type (Lim_Typ, Scope);
- end if;
+ begin
+ -- Inspect the declarative list, looking for type declarations and
+ -- nested packages.
- Set_Non_Limited_View (Lim_Typ, Comp_Typ);
+ Decl := First (Decls);
+ while Present (Decl) loop
- -- Initialize Private_Depedents, so the field has the proper
- -- type, even though the list will remain empty.
+ -- Types
- Set_Private_Dependents (Lim_Typ, New_Elmt_List);
+ if Nkind_In (Decl, N_Full_Type_Declaration,
+ N_Incomplete_Type_Declaration,
+ N_Private_Extension_Declaration,
+ N_Private_Type_Declaration,
+ N_Protected_Type_Declaration,
+ N_Task_Type_Declaration)
+ then
+ Typ := Defining_Entity (Decl);
- elsif Nkind (Decl) = N_Private_Extension_Declaration then
- Comp_Typ := Defining_Identifier (Decl);
+ -- Determine whether the type is tagged. Note that packages
+ -- included via a limited with clause are not always analyzed,
+ -- hence the tree lookup rather than the use of attribute
+ -- Is_Tagged_Type.
- if not Analyzed_Unit then
- Decorate_Tagged_Type (Sloc (Decl), Comp_Typ, Scope, True);
- end if;
+ if Nkind (Decl) = N_Full_Type_Declaration then
+ Def := Type_Definition (Decl);
- -- Create shadow entity for type
+ Is_Tagged :=
+ (Nkind (Def) = N_Record_Definition
+ and then Tagged_Present (Def))
+ or else
+ (Nkind (Def) = N_Derived_Type_Definition
+ and then Present (Record_Extension_Part (Def)));
- Lim_Typ :=
- New_Internal_Shadow_Entity
- (Kind => Ekind (Comp_Typ),
- Sloc_Value => Sloc (Comp_Typ),
- Id_Char => 'Z');
+ elsif Nkind_In (Decl, N_Incomplete_Type_Declaration,
+ N_Private_Type_Declaration)
+ then
+ Is_Tagged := Tagged_Present (Decl);
- Set_Chars (Lim_Typ, Chars (Comp_Typ));
- Set_Parent (Lim_Typ, Parent (Comp_Typ));
- Set_From_With_Type (Lim_Typ);
+ elsif Nkind (Decl) = N_Private_Extension_Declaration then
+ Is_Tagged := True;
- Decorate_Tagged_Type (Sloc (Decl), Lim_Typ, Scope);
- Set_Non_Limited_View (Lim_Typ, Comp_Typ);
+ else
+ Is_Tagged := False;
+ end if;
- elsif Nkind (Decl) = N_Package_Declaration then
+ -- Perform minor decoration when the withed package has not
+ -- been analyzed.
- -- Local package
+ if not Is_Analyzed then
+ Decorate_Type (Typ, Scop, Is_Tagged, True);
+ end if;
- declare
- Spec : constant Node_Id := Specification (Decl);
+ -- Create a shadow entity that hides the type and offers an
+ -- incomplete view of the said type.
- begin
- Comp_Typ := Defining_Unit_Name (Spec);
+ Shadow := Build_Shadow_Entity (Typ, Scop, Is_Tagged);
- if not Analyzed (Cunit (Unum)) then
- Decorate_Package_Specification (Comp_Typ);
- Set_Scope (Comp_Typ, Scope);
- end if;
+ -- Packages
- Lim_Typ :=
- New_Internal_Shadow_Entity
- (Kind => Ekind (Comp_Typ),
- Sloc_Value => Sloc (Comp_Typ),
- Id_Char => 'Z');
+ elsif Nkind (Decl) = N_Package_Declaration then
+ Pack := Defining_Entity (Decl);
- Decorate_Package_Specification (Lim_Typ);
- Set_Scope (Lim_Typ, Scope);
+ -- Perform minor decoration when the withed package has not
+ -- been analyzed.
- Set_Chars (Lim_Typ, Chars (Comp_Typ));
- Set_Parent (Lim_Typ, Parent (Comp_Typ));
- Set_From_With_Type (Lim_Typ);
+ if not Is_Analyzed then
+ Decorate_Package (Pack, Scop);
+ end if;
- -- Note: The non_limited_view attribute is not used
- -- for local packages.
+ -- Create a shadow entity that offers a limited view of all
+ -- visible types declared within.
- Build_Chain
- (Scope => Lim_Typ,
- First_Decl => First (Visible_Declarations (Spec)));
- end;
+ Shadow := Build_Shadow_Entity (Pack, Scop);
+
+ Process_Declarations
+ (Decls => Visible_Declarations (Specification (Decl)),
+ Scop => Shadow);
end if;
Next (Decl);
end loop;
- end Build_Chain;
-
- ------------------------------
- -- Decorate_Incomplete_Type --
- ------------------------------
-
- procedure Decorate_Incomplete_Type (E : Entity_Id; Scop : Entity_Id) is
- begin
- Set_Ekind (E, E_Incomplete_Type);
- Set_Scope (E, Scop);
- Set_Etype (E, E);
- Set_Is_First_Subtype (E, True);
- Set_Stored_Constraint (E, No_Elist);
- Set_Full_View (E, Empty);
- Init_Size_Align (E);
- end Decorate_Incomplete_Type;
-
- --------------------------
- -- Decorate_Tagged_Type --
- --------------------------
-
- procedure Decorate_Tagged_Type
- (Loc : Source_Ptr;
- T : Entity_Id;
- Scop : Entity_Id;
- Mark : Boolean := False)
- is
- CW : Entity_Id;
-
- begin
- Decorate_Incomplete_Type (T, Scop);
- Set_Is_Tagged_Type (T);
-
- -- Build corresponding class_wide type, if not previously done
-
- -- Note: The class-wide entity is shared by the limited-view
- -- and the full-view.
-
- if No (Class_Wide_Type (T)) then
- CW := New_External_Entity (E_Void, Scope (T), Loc, T, 'C', 0, 'T');
-
- -- Set parent to be the same as the parent of the tagged type.
- -- We need a parent field set, and it is supposed to point to
- -- the declaration of the type. The tagged type declaration
- -- essentially declares two separate types, the tagged type
- -- itself and the corresponding class-wide type, so it is
- -- reasonable for the parent fields to point to the declaration
- -- in both cases.
-
- Set_Parent (CW, Parent (T));
+ end Process_Declarations;
- -- Set remaining fields of classwide type
+ -- Local variables
- Set_Ekind (CW, E_Class_Wide_Type);
- Set_Etype (CW, T);
- Set_Scope (CW, Scop);
- Set_Is_Tagged_Type (CW);
- Set_Is_First_Subtype (CW, True);
- Init_Size_Align (CW);
- Set_Has_Unknown_Discriminants (CW, True);
- Set_Class_Wide_Type (CW, CW);
- Set_Equivalent_Type (CW, Empty);
- Set_From_With_Type (CW, From_With_Type (T));
- Set_Materialize_Entity (CW, Mark);
-
- -- Link type to its class-wide type
-
- Set_Class_Wide_Type (T, CW);
- end if;
- end Decorate_Tagged_Type;
-
- ------------------------------------
- -- Decorate_Package_Specification --
- ------------------------------------
-
- procedure Decorate_Package_Specification (P : Entity_Id) is
- begin
- -- Place only the most basic attributes
-
- Set_Ekind (P, E_Package);
- Set_Etype (P, Standard_Void_Type);
- end Decorate_Package_Specification;
-
- --------------------------------
- -- New_Internal_Shadow_Entity --
- --------------------------------
-
- function New_Internal_Shadow_Entity
- (Kind : Entity_Kind;
- Sloc_Value : Source_Ptr;
- Id_Char : Character) return Entity_Id
- is
- E : constant Entity_Id := Make_Temporary (Sloc_Value, Id_Char);
-
- begin
- Set_Ekind (E, Kind);
- Set_Is_Internal (E, True);
-
- if Kind in Type_Kind then
- Init_Size_Align (E);
- end if;
-
- Append_Entity (E, Lim_Header);
- Last_Lim_E := E;
- return E;
- end New_Internal_Shadow_Entity;
+ Last_Public_Shadow : Entity_Id := Empty;
+ Private_Shadow : Entity_Id;
+ Spec : Node_Id;
-- Start of processing for Build_Limited_Views
@@ -5691,49 +5650,51 @@ package body Sem_Ch10 is
null;
when N_Subprogram_Declaration =>
- Error_Msg_N ("subprograms not allowed in "
- & "limited with_clauses", N);
+ Error_Msg_N ("subprograms not allowed in limited with_clauses", N);
return;
when N_Generic_Package_Declaration |
N_Generic_Subprogram_Declaration =>
- Error_Msg_N ("generics not allowed in "
- & "limited with_clauses", N);
+ Error_Msg_N ("generics not allowed in limited with_clauses", N);
return;
when N_Generic_Instantiation =>
- Error_Msg_N ("generic instantiations not allowed in "
- & "limited with_clauses", N);
+ Error_Msg_N
+ ("generic instantiations not allowed in limited with_clauses",
+ N);
return;
when N_Generic_Renaming_Declaration =>
- Error_Msg_N ("generic renamings not allowed in "
- & "limited with_clauses", N);
+ Error_Msg_N
+ ("generic renamings not allowed in limited with_clauses", N);
return;
when N_Subprogram_Renaming_Declaration =>
- Error_Msg_N ("renamed subprograms not allowed in "
- & "limited with_clauses", N);
+ Error_Msg_N
+ ("renamed subprograms not allowed in limited with_clauses", N);
return;
when N_Package_Renaming_Declaration =>
- Error_Msg_N ("renamed packages not allowed in "
- & "limited with_clauses", N);
+ Error_Msg_N
+ ("renamed packages not allowed in limited with_clauses", N);
return;
when others =>
raise Program_Error;
end case;
- -- The limited unit is not analyzed but the with clause must be
- -- minimally decorated so that checks on unused with clause also work
- -- with limited with clauses.
+ -- The withed unit may not be analyzed, but the with calause itself
+ -- must be minimally decorated. This ensures that the checks on unused
+ -- with clauses also process limieted withs.
+
+ Set_Ekind (Pack, E_Package);
+ Set_Etype (Pack, Standard_Void_Type);
- if Is_Entity_Name (Name (N)) then
- Set_Entity (Name (N), P);
+ if Is_Entity_Name (Nam) then
+ Set_Entity (Nam, Pack);
- elsif Nkind (Name (N)) = N_Selected_Component then
- Set_Entity (Selector_Name (Name (N)), P);
+ elsif Nkind (Nam) = N_Selected_Component then
+ Set_Entity (Selector_Name (Nam), Pack);
end if;
-- Check if the chain is already built
@@ -5744,41 +5705,37 @@ package body Sem_Ch10 is
return;
end if;
- Set_Ekind (P, E_Package);
+ -- Create the shadow package wich hides the withed unit and provides
+ -- incomplete view of all types and packages declared within.
- -- Build the header of the limited_view
+ Shadow_Pack := Make_Temporary (Sloc (N), 'Z');
+ Set_Ekind (Shadow_Pack, E_Package);
+ Set_Is_Internal (Shadow_Pack);
+ Set_Limited_View (Pack, Shadow_Pack);
- Lim_Header := Make_Temporary (Sloc (N), 'Z');
- Set_Ekind (Lim_Header, E_Package);
- Set_Is_Internal (Lim_Header);
- Set_Limited_View (P, Lim_Header);
+ -- Inspect the visible declarations of the withed unit and create shadow
+ -- entities that hide existing types and packages.
- -- Create the auxiliary chain. All the shadow entities are appended to
- -- the list of entities of the limited-view header
+ Process_Declarations
+ (Decls => Visible_Declarations (Spec),
+ Scop => Pack);
- Build_Chain
- (Scope => P,
- First_Decl => First (Visible_Declarations (Spec)));
+ Last_Public_Shadow := Last_Shadow;
- -- Save the last built shadow entity. It is needed later to set the
- -- reference to the first shadow entity in the private part
+ -- Ada 2005 (AI-262): Build the limited view of the private declarations
+ -- to accomodate limited private with clauses.
- Last_Pub_Lim_E := Last_Lim_E;
+ Process_Declarations
+ (Decls => Private_Declarations (Spec),
+ Scop => Pack);
- -- Ada 2005 (AI-262): Add the limited view of the private declarations
- -- Required to give support to limited-private-with clauses
-
- Build_Chain (Scope => P,
- First_Decl => First (Private_Declarations (Spec)));
-
- if Last_Pub_Lim_E /= Empty then
- Set_First_Private_Entity
- (Lim_Header, Next_Entity (Last_Pub_Lim_E));
+ if Present (Last_Public_Shadow) then
+ Private_Shadow := Next_Entity (Last_Public_Shadow);
else
- Set_First_Private_Entity
- (Lim_Header, First_Entity (P));
+ Private_Shadow := First_Entity (Shadow_Pack);
end if;
+ Set_First_Private_Entity (Shadow_Pack, Private_Shadow);
Set_Limited_View_Installed (Spec);
end Build_Limited_Views;
@@ -5801,9 +5758,7 @@ package body Sem_Ch10 is
Ent : Entity_Id;
begin
- if Is_Subprogram (E)
- and then Has_Pragma_Inline (E)
- then
+ if Is_Subprogram (E) and then Has_Pragma_Inline (E) then
return True;
elsif Ekind_In (E, E_Generic_Function, E_Generic_Procedure) then
@@ -6095,7 +6050,7 @@ package body Sem_Ch10 is
-- Indicate that the limited view of the package is not installed
- Set_From_With_Type (P, False);
+ Set_From_Limited_With (P, False);
Set_Limited_View_Installed (N, False);
end Remove_Limited_With_Clause;
@@ -6190,9 +6145,8 @@ package body Sem_Ch10 is
begin
Item := First (Context_Items (Comp_Unit));
while Present (Item) loop
- if Nkind (Item) = N_With_Clause
- and then Private_Present (Item)
- then
+ if Nkind (Item) = N_With_Clause and then Private_Present (Item) then
+
-- If private_with_clause is redundant, remove it from context,
-- as a small optimization to subsequent handling of private_with
-- clauses in other nested packages.
@@ -6275,9 +6229,7 @@ package body Sem_Ch10 is
Set_Name_Entity_Id (Chars (E), Homonym (E));
else
- while Present (Prev)
- and then Homonym (Prev) /= E
- loop
+ while Present (Prev) and then Homonym (Prev) /= E loop
Prev := Homonym (Prev);
end loop;
diff --git a/gcc/ada/sem_ch11.adb b/gcc/ada/sem_ch11.adb
index 180ecc6ca0b..a397edfb40e 100644
--- a/gcc/ada/sem_ch11.adb
+++ b/gcc/ada/sem_ch11.adb
@@ -199,6 +199,7 @@ package body Sem_Ch11 is
if Comes_From_Source (Choice) then
Check_Restriction (No_Exception_Propagation, Choice);
+ Set_Debug_Info_Needed (Choice);
end if;
if No (H_Scope) then
@@ -489,7 +490,10 @@ package body Sem_Ch11 is
Par : Node_Id;
begin
- Check_SPARK_Restriction ("raise statement is not allowed", N);
+ if Comes_From_Source (N) then
+ Check_SPARK_Restriction ("raise statement is not allowed", N);
+ end if;
+
Check_Unreachable_Code (N);
-- Check exception restrictions on the original source
@@ -687,7 +691,9 @@ package body Sem_Ch11 is
-- Start of processing for Analyze_Raise_xxx_Error
begin
- Check_SPARK_Restriction ("raise statement is not allowed", N);
+ if Nkind (Original_Node (N)) = N_Raise_Statement then
+ Check_SPARK_Restriction ("raise statement is not allowed", N);
+ end if;
if No (Etype (N)) then
Set_Etype (N, Standard_Void_Type);
diff --git a/gcc/ada/sem_ch12.adb b/gcc/ada/sem_ch12.adb
index 035d0b0bfda..1572e4ff6dc 100644
--- a/gcc/ada/sem_ch12.adb
+++ b/gcc/ada/sem_ch12.adb
@@ -3022,6 +3022,15 @@ package body Sem_Ch12 is
Id := Defining_Entity (N);
Generate_Definition (Id);
+ -- Expansion is not applied to generic units
+
+ Start_Generic;
+
+ Enter_Name (Id);
+ Set_Ekind (Id, E_Generic_Package);
+ Set_Etype (Id, Standard_Void_Type);
+ Set_Contract (Id, Make_Contract (Sloc (Id)));
+
-- Analyze aspects now, so that generated pragmas appear in the
-- declarations before building and analyzing the generic copy.
@@ -3029,13 +3038,6 @@ package body Sem_Ch12 is
Analyze_Aspect_Specifications (N, Id);
end if;
- -- Expansion is not applied to generic units
-
- Start_Generic;
-
- Enter_Name (Id);
- Set_Ekind (Id, E_Generic_Package);
- Set_Etype (Id, Standard_Void_Type);
Push_Scope (Id);
Enter_Generic_Scope (Id);
Set_Inner_Instances (Id, New_Elmt_List);
@@ -3124,7 +3126,7 @@ package body Sem_Ch12 is
Aspects : constant List_Id := Aspect_Specifications (N);
begin
Set_Has_Aspects (N, False);
- Move_Aspects (New_N, N);
+ Move_Aspects (New_N, To => N);
Set_Has_Aspects (Original_Node (N), False);
Set_Aspect_Specifications (Original_Node (N), Aspects);
end;
@@ -3475,12 +3477,12 @@ package body Sem_Ch12 is
-- Ada 2005 (AI-50217): Cannot use instance in limited with_clause
- if From_With_Type (Gen_Unit) then
+ if From_Limited_With (Gen_Unit) then
Error_Msg_N
("cannot instantiate a limited withed package", Gen_Id);
else
- Error_Msg_N
- ("expect name of generic package in instantiation", Gen_Id);
+ Error_Msg_NE
+ ("& is not the name of a generic package", Gen_Id, Gen_Unit);
end if;
Restore_Env;
@@ -3717,8 +3719,7 @@ package body Sem_Ch12 is
(Unit_Requires_Body (Gen_Unit)
or else Enclosing_Body_Present
or else Present (Corresponding_Body (Gen_Decl)))
- and then (Is_In_Main_Unit (N)
- or else Might_Inline_Subp)
+ and then (Is_In_Main_Unit (N) or else Might_Inline_Subp)
and then not Is_Actual_Pack
and then not Inline_Now
and then (Operating_Mode = Generate_Code
@@ -3728,8 +3729,7 @@ package body Sem_Ch12 is
-- If front_end_inlining is enabled, do not instantiate body if
-- within a generic context.
- if (Front_End_Inlining
- and then not Expander_Active)
+ if (Front_End_Inlining and then not Expander_Active)
or else Is_Generic_Unit (Cunit_Entity (Main_Unit))
then
Needs_Body := False;
@@ -4669,34 +4669,17 @@ package body Sem_Ch12 is
-- Verify that it is a generic subprogram of the right kind, and that
-- it does not lead to a circular instantiation.
- if not Ekind_In (Gen_Unit, E_Generic_Procedure, E_Generic_Function) then
- Error_Msg_N ("expect generic subprogram in instantiation", Gen_Id);
+ if K = E_Procedure and then Ekind (Gen_Unit) /= E_Generic_Procedure then
+ Error_Msg_NE
+ ("& is not the name of a generic procedure", Gen_Id, Gen_Unit);
+
+ elsif K = E_Function and then Ekind (Gen_Unit) /= E_Generic_Function then
+ Error_Msg_NE
+ ("& is not the name of a generic function", Gen_Id, Gen_Unit);
elsif In_Open_Scopes (Gen_Unit) then
Error_Msg_NE ("instantiation of & within itself", N, Gen_Unit);
- elsif K = E_Procedure
- and then Ekind (Gen_Unit) /= E_Generic_Procedure
- then
- if Ekind (Gen_Unit) = E_Generic_Function then
- Error_Msg_N
- ("cannot instantiate generic function as procedure", Gen_Id);
- else
- Error_Msg_N
- ("expect name of generic procedure in instantiation", Gen_Id);
- end if;
-
- elsif K = E_Function
- and then Ekind (Gen_Unit) /= E_Generic_Function
- then
- if Ekind (Gen_Unit) = E_Generic_Procedure then
- Error_Msg_N
- ("cannot instantiate generic procedure as function", Gen_Id);
- else
- Error_Msg_N
- ("expect name of generic function in instantiation", Gen_Id);
- end if;
-
else
Set_Entity (Gen_Id, Gen_Unit);
Set_Is_Instantiated (Gen_Unit);
@@ -4775,7 +4758,7 @@ package body Sem_Ch12 is
-- pre/postconditions on the instance are analyzed below, in a
-- separate step.
- Move_Aspects (Act_Tree, Act_Decl);
+ Move_Aspects (Act_Tree, To => Act_Decl);
Set_Categorization_From_Pragmas (Act_Decl);
if Parent_Installed then
@@ -5681,8 +5664,7 @@ package body Sem_Ch12 is
(Related_Instance (Instance))));
else
Gen_Id :=
- Generic_Parent
- (Specification (Unit_Declaration_Node (Instance)));
+ Generic_Parent (Package_Specification (Instance));
end if;
Parent_Scope := Scope (Gen_Id);
@@ -8382,7 +8364,7 @@ package body Sem_Ch12 is
-- of its generic parent.
if Is_Generic_Instance (Par) then
- Gen := Generic_Parent (Specification (Unit_Declaration_Node (Par)));
+ Gen := Generic_Parent (Package_Specification (Par));
Gen_E := First_Entity (Gen);
end if;
@@ -8466,8 +8448,7 @@ package body Sem_Ch12 is
------------------
procedure Install_Spec (Par : Entity_Id) is
- Spec : constant Node_Id :=
- Specification (Unit_Declaration_Node (Par));
+ Spec : constant Node_Id := Package_Specification (Par);
begin
-- If this parent of the child instance is a top-level unit,
@@ -8536,8 +8517,7 @@ package body Sem_Ch12 is
First_Par := Inst_Par;
- Gen_Par :=
- Generic_Parent (Specification (Unit_Declaration_Node (Inst_Par)));
+ Gen_Par := Generic_Parent (Package_Specification (Inst_Par));
First_Gen := Gen_Par;
@@ -8555,9 +8535,7 @@ package body Sem_Ch12 is
Inst_Par := Renamed_Entity (Inst_Par);
end if;
- Gen_Par :=
- Generic_Parent
- (Specification (Unit_Declaration_Node (Inst_Par)));
+ Gen_Par := Generic_Parent (Package_Specification (Inst_Par));
if Present (Gen_Par) then
Prepend_Elmt (Inst_Par, Ancestors);
@@ -9026,7 +9004,7 @@ package body Sem_Ch12 is
end if;
if Nkind (Parent (Actual_Pack)) = N_Defining_Program_Unit_Name then
- Parent_Spec := Specification (Unit_Declaration_Node (Actual_Pack));
+ Parent_Spec := Package_Specification (Actual_Pack);
else
Parent_Spec := Parent (Actual_Pack);
end if;
@@ -10551,23 +10529,13 @@ package body Sem_Ch12 is
-- only mode conformance was required.
-- This is a binding interpretation that applies to previous versions
- -- of the language, but for now we retain the milder check in order
- -- to preserve ACATS tests. These will be protested eventually ???
-
- if Ada_Version < Ada_2012 then
- Check_Mode_Conformant
- (Designated_Type (Act_T),
- Designated_Type (A_Gen_T),
- Actual,
- Get_Inst => True);
+ -- of the language, no need to maintain previous weaker checks.
- else
- Check_Subtype_Conformant
- (Designated_Type (Act_T),
- Designated_Type (A_Gen_T),
- Actual,
- Get_Inst => True);
- end if;
+ Check_Subtype_Conformant
+ (Designated_Type (Act_T),
+ Designated_Type (A_Gen_T),
+ Actual,
+ Get_Inst => True);
if Ekind (Base_Type (Act_T)) = E_Access_Protected_Subprogram_Type then
if Ekind (A_Gen_T) = E_Access_Subprogram_Type then
@@ -10632,7 +10600,7 @@ package body Sem_Ch12 is
-- with clause, in which case retrieve the non-limited view. This
-- applies to incomplete types as well as to class-wide types.
- if From_With_Type (Desig_Act) then
+ if From_Limited_With (Desig_Act) then
Desig_Act := Available_View (Desig_Act);
end if;
@@ -12588,8 +12556,7 @@ package body Sem_Ch12 is
elsif S = Current_Scope and then Is_Generic_Instance (S) then
declare
Par : constant Entity_Id :=
- Generic_Parent
- (Specification (Unit_Declaration_Node (S)));
+ Generic_Parent (Package_Specification (S));
begin
if Present (Par)
and then P = Scope (Par)
diff --git a/gcc/ada/sem_ch13.adb b/gcc/ada/sem_ch13.adb
index 37b9e9a82b9..15862442175 100644
--- a/gcc/ada/sem_ch13.adb
+++ b/gcc/ada/sem_ch13.adb
@@ -44,6 +44,7 @@ with Rident; use Rident;
with Rtsfind; use Rtsfind;
with Sem; use Sem;
with Sem_Aux; use Sem_Aux;
+with Sem_Case; use Sem_Case;
with Sem_Ch3; use Sem_Ch3;
with Sem_Ch6; use Sem_Ch6;
with Sem_Ch8; use Sem_Ch8;
@@ -111,6 +112,13 @@ package body Sem_Ch13 is
-- list is stored in Static_Predicate (Typ), and the Expr is rewritten as
-- a canonicalized membership operation.
+ procedure Freeze_Entity_Checks (N : Node_Id);
+ -- Called from Analyze_Freeze_Entity and Analyze_Generic_Freeze Entity
+ -- to generate appropriate semantic checks that are delayed until this
+ -- point (they had to be delayed this long for cases of delayed aspects,
+ -- e.g. analysis of statically predicated subtypes in choices, for which
+ -- we have to be sure the subtypes in question are frozen before checking.
+
function Get_Alignment_Value (Expr : Node_Id) return Uint;
-- Given the expression for an alignment value, returns the corresponding
-- Uint value. If the value is inappropriate, then error messages are
@@ -762,17 +770,9 @@ package body Sem_Ch13 is
Set_Has_Default_Aspect (Base_Type (Ent));
if Is_Scalar_Type (Ent) then
- Set_Default_Aspect_Value (Ent, Expr);
-
- -- Place default value of base type as well, because that is
- -- the semantics of the aspect. It is convenient to link the
- -- aspect to both the (possibly anonymous) base type and to
- -- the given first subtype.
-
Set_Default_Aspect_Value (Base_Type (Ent), Expr);
-
else
- Set_Default_Aspect_Component_Value (Ent, Expr);
+ Set_Default_Aspect_Component_Value (Base_Type (Ent), Expr);
end if;
end Analyze_Aspect_Default_Value;
@@ -888,7 +888,7 @@ package body Sem_Ch13 is
when Aspect_Scalar_Storage_Order =>
if (Is_Record_Type (E) or else Is_Array_Type (E))
and then No (Get_Attribute_Definition_Clause
- (E, Attribute_Scalar_Storage_Order))
+ (E, Attribute_Scalar_Storage_Order))
and then Reverse_Storage_Order (P)
then
Set_Reverse_Storage_Order (Base_Type (E));
@@ -1189,10 +1189,29 @@ package body Sem_Ch13 is
elsif Nkind (N) = N_Subprogram_Body then
if No (Declarations (N)) then
- Set_Declarations (N, New_List);
- end if;
+ Set_Declarations (N, New_List (Prag));
+ else
+ declare
+ D : Node_Id;
+ begin
- Append (Prag, Declarations (N));
+ -- There may be several aspects associated with the body;
+ -- preserve the ordering of the corresponding pragmas.
+
+ D := First (Declarations (N));
+ while Present (D) loop
+ exit when Nkind (D) /= N_Pragma
+ or else not From_Aspect_Specification (D);
+ Next (D);
+ end loop;
+
+ if No (D) then
+ Append (Prag, Declarations (N));
+ else
+ Insert_Before (D, Prag);
+ end if;
+ end;
+ end if;
-- Default
@@ -1364,9 +1383,8 @@ package body Sem_Ch13 is
pragma Assert (not Is_Disabled (Aspect));
- -- Certan aspects allow for an optional name or expression. Do
- -- not generate a pragma with an empty argument association
- -- list.
+ -- Certain aspects allow for an optional name or expression. Do
+ -- not generate a pragma with empty argument association list.
if No (Args) or else No (Expression (First (Args))) then
Args := No_List;
@@ -1403,9 +1421,9 @@ package body Sem_Ch13 is
goto Continue;
end if;
- -- Skip looking at aspect if it is totally disabled. Just mark
- -- it as such for later reference in the tree. This also sets
- -- the Is_Ignored and Is_Checked flags appropriately.
+ -- Skip looking at aspect if it is totally disabled. Just mark it
+ -- as such for later reference in the tree. This also sets the
+ -- Is_Ignored and Is_Checked flags appropriately.
Check_Applicable_Policy (Aspect);
@@ -1574,6 +1592,18 @@ package body Sem_Ch13 is
goto Continue;
end if;
+ -- For case of address aspect, we don't consider that we
+ -- know the entity is never set in the source, since it is
+ -- is likely aliasing is occurring.
+
+ -- Note: one might think that the analysis of the resulting
+ -- attribute definition clause would take care of that, but
+ -- that's not the case since it won't be from source.
+
+ if A_Id = Aspect_Address then
+ Set_Never_Set_In_Source (E, False);
+ end if;
+
-- Construct the attribute definition clause
Aitem :=
@@ -1764,22 +1794,126 @@ package body Sem_Ch13 is
-- CPU, Interrupt_Priority, Priority
- -- These three aspects can be specified for a subprogram body,
- -- in which case we generate pragmas for them and insert them
- -- ahead of local declarations, rather than after the body.
+ -- These three aspects can be specified for a subprogram spec
+ -- or body, in which case we analyze the expression and export
+ -- the value of the aspect.
+
+ -- Previously, we generated an equivalent pragma for bodies
+ -- (note that the specs cannot contain these pragmas). The
+ -- pragma was inserted ahead of local declarations, rather than
+ -- after the body. This leads to a certain duplication between
+ -- the processing performed for the aspect and the pragma, but
+ -- given the straightforward handling required it is simpler
+ -- to duplicate than to translate the aspect in the spec into
+ -- a pragma in the declarative part of the body.
when Aspect_CPU |
Aspect_Interrupt_Priority |
Aspect_Priority =>
- if Nkind (N) = N_Subprogram_Body then
- Make_Aitem_Pragma
- (Pragma_Argument_Associations => New_List (
- Make_Pragma_Argument_Association (Sloc (Expr),
- Expression => Relocate_Node (Expr))),
- Pragma_Name => Chars (Id));
+ if Nkind_In (N, N_Subprogram_Body,
+ N_Subprogram_Declaration)
+ then
+ -- Analyze the aspect expression
+
+ Analyze_And_Resolve (Expr, Standard_Integer);
+
+ -- Interrupt_Priority aspect not allowed for main
+ -- subprograms. ARM D.1 does not forbid this explicitly,
+ -- but ARM J.15.11 (6/3) does not permit pragma
+ -- Interrupt_Priority for subprograms.
+
+ if A_Id = Aspect_Interrupt_Priority then
+ Error_Msg_N
+ ("Interrupt_Priority aspect cannot apply to "
+ & "subprogram", Expr);
+
+ -- The expression must be static
+
+ elsif not Is_Static_Expression (Expr) then
+ Flag_Non_Static_Expr
+ ("aspect requires static expression!", Expr);
+
+ -- Check whether this is the main subprogram. Issue a
+ -- warning only if it is obviously not a main program
+ -- (when it has parameters or when the subprogram is
+ -- within a package).
+
+ elsif Present (Parameter_Specifications
+ (Specification (N)))
+ or else not Is_Compilation_Unit (Defining_Entity (N))
+ then
+ -- See ARM D.1 (14/3) and D.16 (12/3)
+
+ Error_Msg_N
+ ("aspect applied to subprogram other than the "
+ & "main subprogram has no effect??", Expr);
+
+ -- Otherwise check in range and export the value
+
+ -- For the CPU aspect
+
+ elsif A_Id = Aspect_CPU then
+ if Is_In_Range (Expr, RTE (RE_CPU_Range)) then
+
+ -- Value is correct so we export the value to make
+ -- it available at execution time.
+
+ Set_Main_CPU
+ (Main_Unit, UI_To_Int (Expr_Value (Expr)));
+
+ else
+ Error_Msg_N
+ ("main subprogram CPU is out of range", Expr);
+ end if;
+
+ -- For the Priority aspect
+
+ elsif A_Id = Aspect_Priority then
+ if Is_In_Range (Expr, RTE (RE_Priority)) then
+
+ -- Value is correct so we export the value to make
+ -- it available at execution time.
+
+ Set_Main_Priority
+ (Main_Unit, UI_To_Int (Expr_Value (Expr)));
+
+ else
+ Error_Msg_N
+ ("main subprogram priority is out of range",
+ Expr);
+ end if;
+ end if;
+
+ -- Load an arbitrary entity from System.Tasking.Stages
+ -- or System.Tasking.Restricted.Stages (depending on
+ -- the supported profile) to make sure that one of these
+ -- packages is implicitly with'ed, since we need to have
+ -- the tasking run time active for the pragma Priority to
+ -- have any effect. Previously with with'ed the package
+ -- System.Tasking, but this package does not trigger the
+ -- required initialization of the run-time library.
+
+ declare
+ Discard : Entity_Id;
+ pragma Warnings (Off, Discard);
+ begin
+ if Restricted_Profile then
+ Discard := RTE (RE_Activate_Restricted_Tasks);
+ else
+ Discard := RTE (RE_Activate_Tasks);
+ end if;
+ end;
+
+ -- Handling for these Aspects in subprograms is complete
+
+ goto Continue;
+
+ -- For tasks
else
+ -- Pass the aspect as an attribute
+
Aitem :=
Make_Attribute_Definition_Clause (Loc,
Name => Ent,
@@ -1845,12 +1979,43 @@ package body Sem_Ch13 is
-- Abstract_State
- when Aspect_Abstract_State =>
- Make_Aitem_Pragma
- (Pragma_Argument_Associations => New_List (
- Make_Pragma_Argument_Association (Loc,
- Expression => Relocate_Node (Expr))),
- Pragma_Name => Name_Abstract_State);
+ -- Aspect Abstract_State introduces implicit declarations for
+ -- all state abstraction entities it defines. To emulate this
+ -- behavior, insert the pragma at the beginning of the visible
+ -- declarations of the related package so that it is analyzed
+ -- immediately.
+
+ when Aspect_Abstract_State => Abstract_State : declare
+ Decls : List_Id;
+
+ begin
+ if Nkind_In (N, N_Generic_Package_Declaration,
+ N_Package_Declaration)
+ then
+ Decls := Visible_Declarations (Specification (N));
+
+ Make_Aitem_Pragma
+ (Pragma_Argument_Associations => New_List (
+ Make_Pragma_Argument_Association (Loc,
+ Expression => Relocate_Node (Expr))),
+ Pragma_Name => Name_Abstract_State);
+ Decorate_Delayed_Aspect_And_Pragma (Aspect, Aitem);
+
+ if No (Decls) then
+ Decls := New_List;
+ Set_Visible_Declarations (N, Decls);
+ end if;
+
+ Prepend_To (Decls, Aitem);
+
+ else
+ Error_Msg_NE
+ ("aspect & must apply to a package declaration",
+ Aspect, Id);
+ end if;
+
+ goto Continue;
+ end Abstract_State;
-- Depends
@@ -1888,6 +2053,83 @@ package body Sem_Ch13 is
Insert_Delayed_Pragma (Aitem);
goto Continue;
+ -- Initial_Condition
+
+ -- Aspect Initial_Condition covers the visible declarations of
+ -- a package and all hidden states through functions. As such,
+ -- it must be evaluated at the end of the said declarations.
+
+ when Aspect_Initial_Condition => Initial_Condition : declare
+ Decls : List_Id;
+
+ begin
+ if Nkind_In (N, N_Generic_Package_Declaration,
+ N_Package_Declaration)
+ then
+ Decls := Visible_Declarations (Specification (N));
+
+ Make_Aitem_Pragma
+ (Pragma_Argument_Associations => New_List (
+ Make_Pragma_Argument_Association (Loc,
+ Expression => Relocate_Node (Expr))),
+ Pragma_Name =>
+ Name_Initial_Condition);
+ Decorate_Delayed_Aspect_And_Pragma (Aspect, Aitem);
+
+ if No (Decls) then
+ Decls := New_List;
+ Set_Visible_Declarations (N, Decls);
+ end if;
+
+ Prepend_To (Decls, Aitem);
+
+ else
+ Error_Msg_NE
+ ("aspect & must apply to a package declaration",
+ Aspect, Id);
+ end if;
+
+ goto Continue;
+ end Initial_Condition;
+
+ -- Initializes
+
+ -- Aspect Initializes coverts the visible declarations of a
+ -- package. As such, it must be evaluated at the end of the
+ -- said declarations.
+
+ when Aspect_Initializes => Initializes : declare
+ Decls : List_Id;
+
+ begin
+ if Nkind_In (N, N_Generic_Package_Declaration,
+ N_Package_Declaration)
+ then
+ Decls := Visible_Declarations (Specification (N));
+
+ Make_Aitem_Pragma
+ (Pragma_Argument_Associations => New_List (
+ Make_Pragma_Argument_Association (Loc,
+ Expression => Relocate_Node (Expr))),
+ Pragma_Name => Name_Initializes);
+ Decorate_Delayed_Aspect_And_Pragma (Aspect, Aitem);
+
+ if No (Decls) then
+ Decls := New_List;
+ Set_Visible_Declarations (N, Decls);
+ end if;
+
+ Prepend_To (Decls, Aitem);
+
+ else
+ Error_Msg_NE
+ ("aspect & must apply to a package declaration",
+ Aspect, Id);
+ end if;
+
+ goto Continue;
+ end Initializes;
+
-- SPARK_Mode
when Aspect_SPARK_Mode =>
@@ -1897,6 +2139,87 @@ package body Sem_Ch13 is
Expression => Relocate_Node (Expr))),
Pragma_Name => Name_SPARK_Mode);
+ -- Refined_Depends
+
+ -- Aspect Refined_Depends must be delayed because it can
+ -- mention state refinements introduced by aspect Refined_State
+ -- and further classified by aspect Refined_Global. Since both
+ -- those aspects are delayed, so is Refined_Depends.
+
+ when Aspect_Refined_Depends =>
+ Make_Aitem_Pragma
+ (Pragma_Argument_Associations => New_List (
+ Make_Pragma_Argument_Association (Loc,
+ Expression => Relocate_Node (Expr))),
+ Pragma_Name => Name_Refined_Depends);
+
+ Decorate_Delayed_Aspect_And_Pragma (Aspect, Aitem);
+ Insert_Delayed_Pragma (Aitem);
+ goto Continue;
+
+ -- Refined_Global
+
+ -- Aspect Refined_Global must be delayed because it can mention
+ -- state refinements introduced by aspect Refined_State. Since
+ -- Refined_State is already delayed due to forward references,
+ -- so is Refined_Global.
+
+ when Aspect_Refined_Global =>
+ Make_Aitem_Pragma
+ (Pragma_Argument_Associations => New_List (
+ Make_Pragma_Argument_Association (Loc,
+ Expression => Relocate_Node (Expr))),
+ Pragma_Name => Name_Refined_Global);
+
+ Decorate_Delayed_Aspect_And_Pragma (Aspect, Aitem);
+ Insert_Delayed_Pragma (Aitem);
+ goto Continue;
+
+ -- Refined_Post
+
+ when Aspect_Refined_Post =>
+ Make_Aitem_Pragma
+ (Pragma_Argument_Associations => New_List (
+ Make_Pragma_Argument_Association (Loc,
+ Expression => Relocate_Node (Expr))),
+ Pragma_Name => Name_Refined_Post);
+
+ -- Refined_State
+
+ when Aspect_Refined_State => Refined_State : declare
+ Decls : List_Id;
+
+ begin
+ -- The corresponding pragma for Refined_State is inserted in
+ -- the declarations of the related package body. This action
+ -- synchronizes both the source and from-aspect versions of
+ -- the pragma.
+
+ if Nkind (N) = N_Package_Body then
+ Decls := Declarations (N);
+
+ Make_Aitem_Pragma
+ (Pragma_Argument_Associations => New_List (
+ Make_Pragma_Argument_Association (Loc,
+ Expression => Relocate_Node (Expr))),
+ Pragma_Name => Name_Refined_State);
+ Decorate_Delayed_Aspect_And_Pragma (Aspect, Aitem);
+
+ if No (Decls) then
+ Decls := New_List;
+ Set_Declarations (N, Decls);
+ end if;
+
+ Prepend_To (Decls, Aitem);
+
+ else
+ Error_Msg_NE
+ ("aspect & must apply to a package body", Aspect, Id);
+ end if;
+
+ goto Continue;
+ end Refined_State;
+
-- Relative_Deadline
when Aspect_Relative_Deadline =>
@@ -2208,7 +2531,31 @@ package body Sem_Ch13 is
Next (A);
end loop;
+ -- It is legal to specify Import for a variable, in
+ -- order to suppress initialization for it, without
+ -- specifying explicitly its convention. However this
+ -- is only legal if the convention of the object type
+ -- is Ada or similar.
+
if No (A) then
+ if Ekind (E) = E_Variable
+ and then A_Id = Aspect_Import
+ then
+ declare
+ C : constant Convention_Id :=
+ Convention (Etype (E));
+ begin
+ if C = Convention_Ada or else
+ C = Convention_Ada_Pass_By_Copy or else
+ C = Convention_Ada_Pass_By_Reference
+ then
+ goto Continue;
+ end if;
+ end;
+ end if;
+
+ -- Otherwise, Convention must be specified
+
Error_Msg_N
("missing Convention aspect for Export/Import",
Aspect);
@@ -2317,21 +2664,6 @@ package body Sem_Ch13 is
Set_From_Aspect_Specification (Aitem, True);
end if;
- -- Aspect Abstract_State introduces implicit declarations for all
- -- state abstraction entities it defines. To emulate this behavior
- -- insert the pragma at the start of the visible declarations of
- -- the related package.
-
- if Nam = Name_Abstract_State
- and then Nkind (N) = N_Package_Declaration
- then
- if No (Visible_Declarations (Specification (N))) then
- Set_Visible_Declarations (Specification (N), New_List);
- end if;
-
- Prepend (Aitem, Visible_Declarations (Specification (N)));
- goto Continue;
-
-- In the context of a compilation unit, we directly put the
-- pragma in the Pragmas_After list of the N_Compilation_Unit_Aux
-- node (no delay is required here) except for aspects on a
@@ -2340,7 +2672,7 @@ package body Sem_Ch13 is
-- copy (see sem_ch12), and for package instantiations, where
-- the library unit pragmas are better handled early.
- elsif Nkind (Parent (N)) = N_Compilation_Unit
+ if Nkind (Parent (N)) = N_Compilation_Unit
and then (Present (Aitem) or else Is_Boolean_Aspect (Aspect))
then
declare
@@ -2368,9 +2700,8 @@ package body Sem_Ch13 is
end if;
end if;
- -- If the aspect is on a subprogram body (relevant aspects
- -- are Inline and Priority), add the pragma in front of
- -- the declarations.
+ -- If the aspect is on a subprogram body (relevant aspect
+ -- is Inline), add the pragma in front of the declarations.
if Nkind (N) = N_Subprogram_Body then
if No (Declarations (N)) then
@@ -3430,16 +3761,21 @@ package body Sem_Ch13 is
-- then we make an entry in the table for checking the size
-- and alignment of the overlaying variable. We defer this
-- check till after code generation to take full advantage
- -- of the annotation done by the back end. This entry is
- -- only made if the address clause comes from source.
+ -- of the annotation done by the back end.
-- If the entity has a generic type, the check will be
-- performed in the instance if the actual type justifies
-- it, and we do not insert the clause in the table to
-- prevent spurious warnings.
+ -- Note: we used to test Comes_From_Source and only give
+ -- this warning for source entities, but we have removed
+ -- this test. It really seems bogus to generate overlays
+ -- that would trigger this warning in generated code.
+ -- Furthermore, by removing the test, we handle the
+ -- aspect case properly.
+
if Address_Clause_Overlay_Warnings
- and then Comes_From_Source (N)
and then Present (O_Ent)
and then Is_Object (O_Ent)
then
@@ -4321,7 +4657,17 @@ package body Sem_Ch13 is
Name => Expr);
begin
- Insert_Before (N, Rnode);
+ -- If the attribute definition clause comes from an aspect
+ -- clause, then insert the renaming before the associated
+ -- entity's declaration, since the attribute clause has
+ -- not yet been appended to the declaration list.
+
+ if From_Aspect_Specification (N) then
+ Insert_Before (Parent (Entity (N)), Rnode);
+ else
+ Insert_Before (N, Rnode);
+ end if;
+
Analyze (Rnode);
Set_Associated_Storage_Pool (U_Ent, Pool);
end;
@@ -4970,189 +5316,18 @@ package body Sem_Ch13 is
---------------------------
procedure Analyze_Freeze_Entity (N : Node_Id) is
- E : constant Entity_Id := Entity (N);
-
begin
- -- Remember that we are processing a freezing entity. Required to
- -- ensure correct decoration of internal entities associated with
- -- interfaces (see New_Overloaded_Entity).
-
- Inside_Freezing_Actions := Inside_Freezing_Actions + 1;
-
- -- For tagged types covering interfaces add internal entities that link
- -- the primitives of the interfaces with the primitives that cover them.
- -- Note: These entities were originally generated only when generating
- -- code because their main purpose was to provide support to initialize
- -- the secondary dispatch tables. They are now generated also when
- -- compiling with no code generation to provide ASIS the relationship
- -- between interface primitives and tagged type primitives. They are
- -- also used to locate primitives covering interfaces when processing
- -- generics (see Derive_Subprograms).
-
- if Ada_Version >= Ada_2005
- and then Ekind (E) = E_Record_Type
- and then Is_Tagged_Type (E)
- and then not Is_Interface (E)
- and then Has_Interfaces (E)
- then
- -- This would be a good common place to call the routine that checks
- -- overriding of interface primitives (and thus factorize calls to
- -- Check_Abstract_Overriding located at different contexts in the
- -- compiler). However, this is not possible because it causes
- -- spurious errors in case of late overriding.
-
- Add_Internal_Interface_Entities (E);
- end if;
-
- -- Check CPP types
-
- if Ekind (E) = E_Record_Type
- and then Is_CPP_Class (E)
- and then Is_Tagged_Type (E)
- and then Tagged_Type_Expansion
- and then Expander_Active
- then
- if CPP_Num_Prims (E) = 0 then
-
- -- If the CPP type has user defined components then it must import
- -- primitives from C++. This is required because if the C++ class
- -- has no primitives then the C++ compiler does not added the _tag
- -- component to the type.
-
- pragma Assert (Chars (First_Entity (E)) = Name_uTag);
-
- if First_Entity (E) /= Last_Entity (E) then
- Error_Msg_N
- ("'C'P'P type must import at least one primitive from C++??",
- E);
- end if;
- end if;
-
- -- Check that all its primitives are abstract or imported from C++.
- -- Check also availability of the C++ constructor.
-
- declare
- Has_Constructors : constant Boolean := Has_CPP_Constructors (E);
- Elmt : Elmt_Id;
- Error_Reported : Boolean := False;
- Prim : Node_Id;
-
- begin
- Elmt := First_Elmt (Primitive_Operations (E));
- while Present (Elmt) loop
- Prim := Node (Elmt);
-
- if Comes_From_Source (Prim) then
- if Is_Abstract_Subprogram (Prim) then
- null;
-
- elsif not Is_Imported (Prim)
- or else Convention (Prim) /= Convention_CPP
- then
- Error_Msg_N
- ("primitives of 'C'P'P types must be imported from C++ "
- & "or abstract??", Prim);
-
- elsif not Has_Constructors
- and then not Error_Reported
- then
- Error_Msg_Name_1 := Chars (E);
- Error_Msg_N
- ("??'C'P'P constructor required for type %", Prim);
- Error_Reported := True;
- end if;
- end if;
-
- Next_Elmt (Elmt);
- end loop;
- end;
- end if;
-
- -- Check Ada derivation of CPP type
-
- if Expander_Active
- and then Tagged_Type_Expansion
- and then Ekind (E) = E_Record_Type
- and then Etype (E) /= E
- and then Is_CPP_Class (Etype (E))
- and then CPP_Num_Prims (Etype (E)) > 0
- and then not Is_CPP_Class (E)
- and then not Has_CPP_Constructors (Etype (E))
- then
- -- If the parent has C++ primitives but it has no constructor then
- -- check that all the primitives are overridden in this derivation;
- -- otherwise the constructor of the parent is needed to build the
- -- dispatch table.
-
- declare
- Elmt : Elmt_Id;
- Prim : Node_Id;
-
- begin
- Elmt := First_Elmt (Primitive_Operations (E));
- while Present (Elmt) loop
- Prim := Node (Elmt);
-
- if not Is_Abstract_Subprogram (Prim)
- and then No (Interface_Alias (Prim))
- and then Find_Dispatching_Type (Ultimate_Alias (Prim)) /= E
- then
- Error_Msg_Name_1 := Chars (Etype (E));
- Error_Msg_N
- ("'C'P'P constructor required for parent type %", E);
- exit;
- end if;
-
- Next_Elmt (Elmt);
- end loop;
- end;
- end if;
-
- Inside_Freezing_Actions := Inside_Freezing_Actions - 1;
-
- -- If we have a type with predicates, build predicate function
-
- if Is_Type (E) and then Has_Predicates (E) then
- Build_Predicate_Functions (E, N);
- end if;
-
- -- If type has delayed aspects, this is where we do the preanalysis at
- -- the freeze point, as part of the consistent visibility check. Note
- -- that this must be done after calling Build_Predicate_Functions or
- -- Build_Invariant_Procedure since these subprograms fix occurrences of
- -- the subtype name in the saved expression so that they will not cause
- -- trouble in the preanalysis.
-
- if Has_Delayed_Aspects (E)
- and then Scope (E) = Current_Scope
- then
- -- Retrieve the visibility to the discriminants in order to properly
- -- analyze the aspects.
-
- Push_Scope_And_Install_Discriminants (E);
-
- declare
- Ritem : Node_Id;
-
- begin
- -- Look for aspect specification entries for this entity
-
- Ritem := First_Rep_Item (E);
- while Present (Ritem) loop
- if Nkind (Ritem) = N_Aspect_Specification
- and then Entity (Ritem) = E
- and then Is_Delayed_Aspect (Ritem)
- then
- Check_Aspect_At_Freeze_Point (Ritem);
- end if;
+ Freeze_Entity_Checks (N);
+ end Analyze_Freeze_Entity;
- Next_Rep_Item (Ritem);
- end loop;
- end;
+ -----------------------------------
+ -- Analyze_Freeze_Generic_Entity --
+ -----------------------------------
- Uninstall_Discriminants_And_Pop_Scope (E);
- end if;
- end Analyze_Freeze_Entity;
+ procedure Analyze_Freeze_Generic_Entity (N : Node_Id) is
+ begin
+ Freeze_Entity_Checks (N);
+ end Analyze_Freeze_Generic_Entity;
------------------------------------------
-- Analyze_Record_Representation_Clause --
@@ -5922,7 +6097,6 @@ package body Sem_Ch13 is
if Present (SId) then
PDecl := Unit_Declaration_Node (SId);
-
else
PDecl := Build_Invariant_Procedure_Declaration (Typ);
end if;
@@ -7096,6 +7270,16 @@ package body Sem_Ch13 is
when N_Qualified_Expression =>
return Get_RList (Expression (Exp));
+ -- Expression with actions: if no actions, dig out expression
+
+ when N_Expression_With_Actions =>
+ if Is_Empty_List (Actions (Exp)) then
+ return Get_RList (Expression (Exp));
+
+ else
+ raise Non_Static;
+ end if;
+
-- Xor operator
when N_Op_Xor =>
@@ -7705,12 +7889,18 @@ package body Sem_Ch13 is
Aspect_Dimension |
Aspect_Dimension_System |
Aspect_Implicit_Dereference |
+ Aspect_Initial_Condition |
+ Aspect_Initializes |
Aspect_Post |
Aspect_Postcondition |
Aspect_Pre |
Aspect_Precondition |
+ Aspect_Refined_Depends |
+ Aspect_Refined_Global |
+ Aspect_Refined_Post |
+ Aspect_Refined_State |
Aspect_SPARK_Mode |
- Aspect_Test_Case =>
+ Aspect_Test_Case =>
raise Program_Error;
end case;
@@ -8922,6 +9112,369 @@ package body Sem_Ch13 is
end if;
end Check_Size;
+ --------------------------
+ -- Freeze_Entity_Checks --
+ --------------------------
+
+ procedure Freeze_Entity_Checks (N : Node_Id) is
+ E : constant Entity_Id := Entity (N);
+
+ Non_Generic_Case : constant Boolean := Nkind (N) = N_Freeze_Entity;
+ -- True in non-generic case. Some of the processing here is skipped
+ -- for the generic case since it is not needed. Basically in the
+ -- generic case, we only need to do stuff that might generate error
+ -- messages or warnings.
+ begin
+ -- Remember that we are processing a freezing entity. Required to
+ -- ensure correct decoration of internal entities associated with
+ -- interfaces (see New_Overloaded_Entity).
+
+ Inside_Freezing_Actions := Inside_Freezing_Actions + 1;
+
+ -- For tagged types covering interfaces add internal entities that link
+ -- the primitives of the interfaces with the primitives that cover them.
+ -- Note: These entities were originally generated only when generating
+ -- code because their main purpose was to provide support to initialize
+ -- the secondary dispatch tables. They are now generated also when
+ -- compiling with no code generation to provide ASIS the relationship
+ -- between interface primitives and tagged type primitives. They are
+ -- also used to locate primitives covering interfaces when processing
+ -- generics (see Derive_Subprograms).
+
+ -- This is not needed in the generic case
+
+ if Ada_Version >= Ada_2005
+ and then Non_Generic_Case
+ and then Ekind (E) = E_Record_Type
+ and then Is_Tagged_Type (E)
+ and then not Is_Interface (E)
+ and then Has_Interfaces (E)
+ then
+ -- This would be a good common place to call the routine that checks
+ -- overriding of interface primitives (and thus factorize calls to
+ -- Check_Abstract_Overriding located at different contexts in the
+ -- compiler). However, this is not possible because it causes
+ -- spurious errors in case of late overriding.
+
+ Add_Internal_Interface_Entities (E);
+ end if;
+
+ -- Check CPP types
+
+ if Ekind (E) = E_Record_Type
+ and then Is_CPP_Class (E)
+ and then Is_Tagged_Type (E)
+ and then Tagged_Type_Expansion
+ then
+ if CPP_Num_Prims (E) = 0 then
+
+ -- If the CPP type has user defined components then it must import
+ -- primitives from C++. This is required because if the C++ class
+ -- has no primitives then the C++ compiler does not added the _tag
+ -- component to the type.
+
+ if First_Entity (E) /= Last_Entity (E) then
+ Error_Msg_N
+ ("'C'P'P type must import at least one primitive from C++??",
+ E);
+ end if;
+ end if;
+
+ -- Check that all its primitives are abstract or imported from C++.
+ -- Check also availability of the C++ constructor.
+
+ declare
+ Has_Constructors : constant Boolean := Has_CPP_Constructors (E);
+ Elmt : Elmt_Id;
+ Error_Reported : Boolean := False;
+ Prim : Node_Id;
+
+ begin
+ Elmt := First_Elmt (Primitive_Operations (E));
+ while Present (Elmt) loop
+ Prim := Node (Elmt);
+
+ if Comes_From_Source (Prim) then
+ if Is_Abstract_Subprogram (Prim) then
+ null;
+
+ elsif not Is_Imported (Prim)
+ or else Convention (Prim) /= Convention_CPP
+ then
+ Error_Msg_N
+ ("primitives of 'C'P'P types must be imported from C++ "
+ & "or abstract??", Prim);
+
+ elsif not Has_Constructors
+ and then not Error_Reported
+ then
+ Error_Msg_Name_1 := Chars (E);
+ Error_Msg_N
+ ("??'C'P'P constructor required for type %", Prim);
+ Error_Reported := True;
+ end if;
+ end if;
+
+ Next_Elmt (Elmt);
+ end loop;
+ end;
+ end if;
+
+ -- Check Ada derivation of CPP type
+
+ if Expander_Active -- why? losing errors in -gnatc mode???
+ and then Tagged_Type_Expansion
+ and then Ekind (E) = E_Record_Type
+ and then Etype (E) /= E
+ and then Is_CPP_Class (Etype (E))
+ and then CPP_Num_Prims (Etype (E)) > 0
+ and then not Is_CPP_Class (E)
+ and then not Has_CPP_Constructors (Etype (E))
+ then
+ -- If the parent has C++ primitives but it has no constructor then
+ -- check that all the primitives are overridden in this derivation;
+ -- otherwise the constructor of the parent is needed to build the
+ -- dispatch table.
+
+ declare
+ Elmt : Elmt_Id;
+ Prim : Node_Id;
+
+ begin
+ Elmt := First_Elmt (Primitive_Operations (E));
+ while Present (Elmt) loop
+ Prim := Node (Elmt);
+
+ if not Is_Abstract_Subprogram (Prim)
+ and then No (Interface_Alias (Prim))
+ and then Find_Dispatching_Type (Ultimate_Alias (Prim)) /= E
+ then
+ Error_Msg_Name_1 := Chars (Etype (E));
+ Error_Msg_N
+ ("'C'P'P constructor required for parent type %", E);
+ exit;
+ end if;
+
+ Next_Elmt (Elmt);
+ end loop;
+ end;
+ end if;
+
+ Inside_Freezing_Actions := Inside_Freezing_Actions - 1;
+
+ -- If we have a type with predicates, build predicate function. This
+ -- is not needed in the generic casee
+
+ if Non_Generic_Case and then Is_Type (E) and then Has_Predicates (E) then
+ Build_Predicate_Functions (E, N);
+ end if;
+
+ -- If type has delayed aspects, this is where we do the preanalysis at
+ -- the freeze point, as part of the consistent visibility check. Note
+ -- that this must be done after calling Build_Predicate_Functions or
+ -- Build_Invariant_Procedure since these subprograms fix occurrences of
+ -- the subtype name in the saved expression so that they will not cause
+ -- trouble in the preanalysis.
+
+ -- This is also not needed in the generic case
+
+ if Non_Generic_Case
+ and then Has_Delayed_Aspects (E)
+ and then Scope (E) = Current_Scope
+ then
+ -- Retrieve the visibility to the discriminants in order to properly
+ -- analyze the aspects.
+
+ Push_Scope_And_Install_Discriminants (E);
+
+ declare
+ Ritem : Node_Id;
+
+ begin
+ -- Look for aspect specification entries for this entity
+
+ Ritem := First_Rep_Item (E);
+ while Present (Ritem) loop
+ if Nkind (Ritem) = N_Aspect_Specification
+ and then Entity (Ritem) = E
+ and then Is_Delayed_Aspect (Ritem)
+ then
+ Check_Aspect_At_Freeze_Point (Ritem);
+ end if;
+
+ Next_Rep_Item (Ritem);
+ end loop;
+ end;
+
+ Uninstall_Discriminants_And_Pop_Scope (E);
+ end if;
+
+ -- For a record type, deal with variant parts. This has to be delayed
+ -- to this point, because of the issue of statically precicated
+ -- subtypes, which we have to ensure are frozen before checking
+ -- choices, since we need to have the static choice list set.
+
+ if Is_Record_Type (E) then
+ Check_Variant_Part : declare
+ D : constant Node_Id := Declaration_Node (E);
+ T : Node_Id;
+ C : Node_Id;
+ VP : Node_Id;
+
+ Others_Present : Boolean;
+ pragma Warnings (Off, Others_Present);
+ -- Indicates others present, not used in this case
+
+ procedure Non_Static_Choice_Error (Choice : Node_Id);
+ -- Error routine invoked by the generic instantiation below when
+ -- the variant part has a non static choice.
+
+ procedure Process_Declarations (Variant : Node_Id);
+ -- Processes declarations associated with a variant. We analyzed
+ -- the declarations earlier (in Sem_Ch3.Analyze_Variant_Part),
+ -- but we still need the recursive call to Check_Choices for any
+ -- nested variant to get its choices properly processed. This is
+ -- also where we expand out the choices if expansion is active.
+
+ package Variant_Choices_Processing is new
+ Generic_Check_Choices
+ (Process_Empty_Choice => No_OP,
+ Process_Non_Static_Choice => Non_Static_Choice_Error,
+ Process_Associated_Node => Process_Declarations);
+ use Variant_Choices_Processing;
+
+ -----------------------------
+ -- Non_Static_Choice_Error --
+ -----------------------------
+
+ procedure Non_Static_Choice_Error (Choice : Node_Id) is
+ begin
+ Flag_Non_Static_Expr
+ ("choice given in variant part is not static!", Choice);
+ end Non_Static_Choice_Error;
+
+ --------------------------
+ -- Process_Declarations --
+ --------------------------
+
+ procedure Process_Declarations (Variant : Node_Id) is
+ CL : constant Node_Id := Component_List (Variant);
+ VP : Node_Id;
+
+ begin
+ -- Check for static predicate present in this variant
+
+ if Has_SP_Choice (Variant) then
+
+ -- Here we expand. You might expect to find this call in
+ -- Expand_N_Variant_Part, but that is called when we first
+ -- see the variant part, and we cannot do this expansion
+ -- earlier than the freeze point, since for statically
+ -- predicated subtypes, the predicate is not known till
+ -- the freeze point.
+
+ -- Furthermore, we do this expansion even if the expander
+ -- is not active, because other semantic processing, e.g.
+ -- for aggregates, requires the expanded list of choices.
+
+ -- If the expander is not active, then we can't just clobber
+ -- the list since it would invalidate the ASIS -gnatct tree.
+ -- So we have to rewrite the variant part with a Rewrite
+ -- call that replaces it with a copy and clobber the copy.
+
+ if not Expander_Active then
+ declare
+ NewV : constant Node_Id := New_Copy (Variant);
+ begin
+ Set_Discrete_Choices
+ (NewV, New_Copy_List (Discrete_Choices (Variant)));
+ Rewrite (Variant, NewV);
+ end;
+ end if;
+
+ Expand_Static_Predicates_In_Choices (Variant);
+ end if;
+
+ -- We don't need to worry about the declarations in the variant
+ -- (since they were analyzed by Analyze_Choices when we first
+ -- encountered the variant), but we do need to take care of
+ -- expansion of any nested variants.
+
+ if not Null_Present (CL) then
+ VP := Variant_Part (CL);
+
+ if Present (VP) then
+ Check_Choices
+ (VP, Variants (VP), Etype (Name (VP)), Others_Present);
+ end if;
+ end if;
+ end Process_Declarations;
+
+ -- Start of processing for Check_Variant_Part
+
+ begin
+ -- Find component list
+
+ C := Empty;
+
+ if Nkind (D) = N_Full_Type_Declaration then
+ T := Type_Definition (D);
+
+ if Nkind (T) = N_Record_Definition then
+ C := Component_List (T);
+
+ elsif Nkind (T) = N_Derived_Type_Definition
+ and then Present (Record_Extension_Part (T))
+ then
+ C := Component_List (Record_Extension_Part (T));
+ end if;
+ end if;
+
+ -- Case of variant part present
+
+ if Present (C) and then Present (Variant_Part (C)) then
+ VP := Variant_Part (C);
+
+ -- Check choices
+
+ Check_Choices
+ (VP, Variants (VP), Etype (Name (VP)), Others_Present);
+
+ -- If the last variant does not contain the Others choice,
+ -- replace it with an N_Others_Choice node since Gigi always
+ -- wants an Others. Note that we do not bother to call Analyze
+ -- on the modified variant part, since its only effect would be
+ -- to compute the Others_Discrete_Choices node laboriously, and
+ -- of course we already know the list of choices corresponding
+ -- to the others choice (it's the list we're replacing!)
+
+ -- We only want to do this if the expander is active, since
+ -- we do not want to clobber the ASIS tree!
+
+ if Expander_Active then
+ declare
+ Last_Var : constant Node_Id :=
+ Last_Non_Pragma (Variants (VP));
+
+ Others_Node : Node_Id;
+
+ begin
+ if Nkind (First (Discrete_Choices (Last_Var))) /=
+ N_Others_Choice
+ then
+ Others_Node := Make_Others_Choice (Sloc (Last_Var));
+ Set_Others_Discrete_Choices
+ (Others_Node, Discrete_Choices (Last_Var));
+ Set_Discrete_Choices
+ (Last_Var, New_List (Others_Node));
+ end if;
+ end;
+ end if;
+ end if;
+ end Check_Variant_Part;
+ end if;
+ end Freeze_Entity_Checks;
+
-------------------------
-- Get_Alignment_Value --
-------------------------
@@ -9050,6 +9603,7 @@ package body Sem_Ch13 is
-- Default_Component_Value
if Is_Array_Type (Typ)
+ and then Is_Base_Type (Typ)
and then Has_Rep_Item (Typ, Name_Default_Component_Value, False)
and then Has_Rep_Item (Typ, Name_Default_Component_Value)
then
@@ -9061,6 +9615,7 @@ package body Sem_Ch13 is
-- Default_Value
if Is_Scalar_Type (Typ)
+ and then Is_Base_Type (Typ)
and then Has_Rep_Item (Typ, Name_Default_Value, False)
and then Has_Rep_Item (Typ, Name_Default_Value)
then
@@ -9653,7 +10208,7 @@ package body Sem_Ch13 is
-- Exclude imported types, which may be frozen if they appear in a
-- representation clause for a local type.
- and then not From_With_Type (T)
+ and then not From_Limited_With (T)
-- Exclude generated entities (not coming from source). The common
-- case is when we generate a renaming which prematurely freezes the
diff --git a/gcc/ada/sem_ch13.ads b/gcc/ada/sem_ch13.ads
index 0d95174c14a..37bf09132ab 100644
--- a/gcc/ada/sem_ch13.ads
+++ b/gcc/ada/sem_ch13.ads
@@ -33,6 +33,7 @@ package Sem_Ch13 is
procedure Analyze_Enumeration_Representation_Clause (N : Node_Id);
procedure Analyze_Free_Statement (N : Node_Id);
procedure Analyze_Freeze_Entity (N : Node_Id);
+ procedure Analyze_Freeze_Generic_Entity (N : Node_Id);
procedure Analyze_Record_Representation_Clause (N : Node_Id);
procedure Analyze_Code_Statement (N : Node_Id);
diff --git a/gcc/ada/sem_ch3.adb b/gcc/ada/sem_ch3.adb
index ea41423b46f..01d6dddd102 100644
--- a/gcc/ada/sem_ch3.adb
+++ b/gcc/ada/sem_ch3.adb
@@ -64,6 +64,7 @@ with Sem_Dist; use Sem_Dist;
with Sem_Elim; use Sem_Elim;
with Sem_Eval; use Sem_Eval;
with Sem_Mech; use Sem_Mech;
+with Sem_Prag; use Sem_Prag;
with Sem_Res; use Sem_Res;
with Sem_Smem; use Sem_Smem;
with Sem_Type; use Sem_Type;
@@ -895,7 +896,7 @@ package body Sem_Ch3 is
-- (which is declared elsewhere in some other scope).
if Ekind (Desig_Type) = E_Incomplete_Type
- and then not From_With_Type (Desig_Type)
+ and then not From_Limited_With (Desig_Type)
and then Is_Overloadable (Current_Scope)
then
Append_Elmt (Current_Scope, Private_Dependents (Desig_Type));
@@ -949,7 +950,7 @@ package body Sem_Ch3 is
-- generic formal, because no use of it will reach the backend.
elsif Nkind (Related_Nod) = N_Function_Specification
- and then not From_With_Type (Desig_Type)
+ and then not From_Limited_With (Desig_Type)
and then not Is_Generic_Type (Desig_Type)
then
if Present (Enclosing_Prot_Type) then
@@ -981,7 +982,6 @@ package body Sem_Ch3 is
(T_Name : Entity_Id;
T_Def : Node_Id)
is
-
procedure Check_For_Premature_Usage (Def : Node_Id);
-- Check that type T_Name is not used, directly or recursively, as a
-- parameter or a return type in Def. Def is either a subtype, an
@@ -1131,7 +1131,7 @@ package body Sem_Ch3 is
Scope_Id => Current_Scope));
else
- if From_With_Type (Typ) then
+ if From_Limited_With (Typ) then
-- AI05-151: Incomplete types are allowed in all basic
-- declarations, including access to subprograms.
@@ -1235,12 +1235,14 @@ package body Sem_Ch3 is
-- be updated when the full type declaration is seen. This only applies
-- to incomplete types declared in some enclosing scope, not to limited
-- views from other packages.
+ -- Prior to Ada 2012, access to functions can only have in_parameters.
if Present (Formals) then
Formal := First_Formal (Desig_Type);
while Present (Formal) loop
if Ekind (Formal) /= E_In_Parameter
and then Nkind (T_Def) = N_Access_Function_Definition
+ and then Ada_Version < Ada_2012
then
Error_Msg_N ("functions can only have IN parameters", Formal);
end if;
@@ -1358,7 +1360,7 @@ package body Sem_Ch3 is
-- If the type has appeared already in a with_type clause, it is frozen
-- and the pointer size is already set. Else, initialize.
- if not From_With_Type (T) then
+ if not From_Limited_With (T) then
Init_Size_Align (T);
end if;
@@ -2056,28 +2058,141 @@ package body Sem_Ch3 is
--------------------------
procedure Analyze_Declarations (L : List_Id) is
- D : Node_Id;
- Freeze_From : Entity_Id := Empty;
- Next_Node : Node_Id;
+ Decl : Node_Id;
- procedure Adjust_D;
- -- Adjust D not to include implicit label declarations, since these
+ procedure Adjust_Decl;
+ -- Adjust Decl not to include implicit label declarations, since these
-- have strange Sloc values that result in elaboration check problems.
-- (They have the sloc of the label as found in the source, and that
-- is ahead of the current declarative part).
- --------------
- -- Adjust_D --
- --------------
+ procedure Remove_Visible_Refinements (Spec_Id : Entity_Id);
+ -- Spec_Id is the entity of a package that may define abstract states.
+ -- If the states have visible refinement, remove the visibility of each
+ -- constituent at the end of the package body declarations.
+
+ function Requires_State_Refinement
+ (Spec_Id : Entity_Id;
+ Body_Id : Entity_Id) return Boolean;
+ -- Determine whether a package denoted by its spec and body entities
+ -- requires refinement of abstract states.
+
+ -----------------
+ -- Adjust_Decl --
+ -----------------
- procedure Adjust_D is
+ procedure Adjust_Decl is
begin
- while Present (Prev (D))
- and then Nkind (D) = N_Implicit_Label_Declaration
+ while Present (Prev (Decl))
+ and then Nkind (Decl) = N_Implicit_Label_Declaration
loop
- Prev (D);
+ Prev (Decl);
end loop;
- end Adjust_D;
+ end Adjust_Decl;
+
+ --------------------------------
+ -- Remove_Visible_Refinements --
+ --------------------------------
+
+ procedure Remove_Visible_Refinements (Spec_Id : Entity_Id) is
+ State_Elmt : Elmt_Id;
+ begin
+ if Present (Abstract_States (Spec_Id)) then
+ State_Elmt := First_Elmt (Abstract_States (Spec_Id));
+ while Present (State_Elmt) loop
+ Set_Has_Visible_Refinement (Node (State_Elmt), False);
+ Next_Elmt (State_Elmt);
+ end loop;
+ end if;
+ end Remove_Visible_Refinements;
+
+ -------------------------------
+ -- Requires_State_Refinement --
+ -------------------------------
+
+ function Requires_State_Refinement
+ (Spec_Id : Entity_Id;
+ Body_Id : Entity_Id) return Boolean
+ is
+ function Mode_Is_Off (Prag : Node_Id) return Boolean;
+ -- Given pragma SPARK_Mode, determine whether the mode is Off
+
+ -----------------
+ -- Mode_Is_Off --
+ -----------------
+
+ function Mode_Is_Off (Prag : Node_Id) return Boolean is
+ Mode : Node_Id;
+
+ begin
+ -- The default SPARK mode is On
+
+ if No (Prag) then
+ return False;
+ end if;
+
+ Mode :=
+ Get_Pragma_Arg (First (Pragma_Argument_Associations (Prag)));
+
+ -- Then the pragma lacks an argument, the default mode is On
+
+ if No (Mode) then
+ return False;
+ else
+ return Chars (Mode) = Name_Off;
+ end if;
+ end Mode_Is_Off;
+
+ -- Start of processing for Requires_State_Refinement
+
+ begin
+ -- A package that does not define at least one abstract state cannot
+ -- possibly require refinement.
+
+ if No (Abstract_States (Spec_Id)) then
+ return False;
+
+ -- The package instroduces a single null state which does not merit
+ -- refinement.
+
+ elsif Has_Null_Abstract_State (Spec_Id) then
+ return False;
+
+ -- Check whether the package body is subject to pragma SPARK_Mode. If
+ -- it is and the mode is Off, the package body is considered to be in
+ -- regular Ada and does not require refinement.
+
+ elsif Mode_Is_Off (SPARK_Mode_Pragmas (Body_Id)) then
+ return False;
+
+ -- The body's SPARK_Mode may be inherited from a similar pragma that
+ -- appears in the private declarations of the spec. The pragma we are
+ -- interested appears as the second entry in SPARK_Mode_Pragmas.
+
+ elsif Present (SPARK_Mode_Pragmas (Spec_Id))
+ and then Mode_Is_Off (Next_Pragma (SPARK_Mode_Pragmas (Spec_Id)))
+ then
+ return False;
+
+ -- The spec defines at least one abstract state and the body has no
+ -- way of circumventing the refinement.
+
+ else
+ return True;
+ end if;
+ end Requires_State_Refinement;
+
+ -- Local variables
+
+ Body_Id : Entity_Id;
+ Context : Node_Id;
+ Freeze_From : Entity_Id := Empty;
+ Next_Decl : Node_Id;
+ Prag : Node_Id;
+ Spec_Id : Entity_Id;
+
+ In_Package_Body : Boolean := False;
+ -- Flag set when the current declaration list belongs to a package body
-- Start of processing for Analyze_Declarations
@@ -2086,23 +2201,23 @@ package body Sem_Ch3 is
Check_Later_Vs_Basic_Declarations (L, During_Parsing => False);
end if;
- D := First (L);
- while Present (D) loop
+ Decl := First (L);
+ while Present (Decl) loop
-- Package spec cannot contain a package declaration in SPARK
- if Nkind (D) = N_Package_Declaration
+ if Nkind (Decl) = N_Package_Declaration
and then Nkind (Parent (L)) = N_Package_Specification
then
Check_SPARK_Restriction
("package specification cannot contain a package declaration",
- D);
+ Decl);
end if;
-- Complete analysis of declaration
- Analyze (D);
- Next_Node := Next (D);
+ Analyze (Decl);
+ Next_Decl := Next (Decl);
if No (Freeze_From) then
Freeze_From := First_Entity (Current_Scope);
@@ -2124,7 +2239,7 @@ package body Sem_Ch3 is
-- be a freeze point once delayed freezing of bodies is implemented.
-- (This is needed in any case for early instantiations ???).
- if No (Next_Node) then
+ if No (Next_Decl) then
if Nkind_In (Parent (L), N_Component_List,
N_Task_Definition,
N_Protected_Definition)
@@ -2136,8 +2251,8 @@ package body Sem_Ch3 is
Freeze_From := First_Entity (Current_Scope);
end if;
- Adjust_D;
- Freeze_All (Freeze_From, D);
+ Adjust_Decl;
+ Freeze_All (Freeze_From, Decl);
Freeze_From := Last_Entity (Current_Scope);
elsif Scope (Current_Scope) /= Standard_Standard
@@ -2150,8 +2265,8 @@ package body Sem_Ch3 is
or else No (Private_Declarations (Parent (L)))
or else Is_Empty_List (Private_Declarations (Parent (L)))
then
- Adjust_D;
- Freeze_All (Freeze_From, D);
+ Adjust_Decl;
+ Freeze_All (Freeze_From, Decl);
Freeze_From := Last_Entity (Current_Scope);
end if;
@@ -2170,44 +2285,96 @@ package body Sem_Ch3 is
-- care to attach the bodies at a proper place in the tree so as to
-- not cause unwanted freezing at that point.
- elsif not Analyzed (Next_Node)
- and then (Nkind_In (Next_Node, N_Subprogram_Body,
+ elsif not Analyzed (Next_Decl)
+ and then (Nkind_In (Next_Decl, N_Subprogram_Body,
N_Entry_Body,
N_Package_Body,
N_Protected_Body,
N_Task_Body)
or else
- Nkind (Next_Node) in N_Body_Stub)
+ Nkind (Next_Decl) in N_Body_Stub)
then
- Adjust_D;
- Freeze_All (Freeze_From, D);
+ Adjust_Decl;
+ Freeze_All (Freeze_From, Decl);
Freeze_From := Last_Entity (Current_Scope);
end if;
- D := Next_Node;
+ Decl := Next_Decl;
end loop;
- -- One more thing to do, we need to scan the declarations to check for
- -- any precondition/postcondition pragmas (Pre/Post aspects have by this
- -- stage been converted into corresponding pragmas). It is at this point
- -- that we analyze the expressions in such pragmas, to implement the
- -- delayed visibility requirement.
+ if Present (L) then
+ Context := Parent (L);
- declare
- Decl : Node_Id;
- Subp_Id : Entity_Id;
+ -- Analyze pragmas Initializes and Initial_Condition of a package at
+ -- the end of the visible declarations as the pragmas have visibility
+ -- over the said region.
- begin
- Decl := First (L);
- while Present (Decl) loop
- if Nkind (Decl) = N_Subprogram_Declaration then
- Subp_Id := Defining_Unit_Name (Specification (Decl));
- Analyze_Subprogram_Contract (Subp_Id);
+ if Nkind (Context) = N_Package_Specification
+ and then L = Visible_Declarations (Context)
+ then
+ Spec_Id := Defining_Entity (Parent (Context));
+ Prag := Get_Pragma (Spec_Id, Pragma_Initializes);
+
+ if Present (Prag) then
+ Analyze_Initializes_In_Decl_Part (Prag);
end if;
- Next (Decl);
- end loop;
- end;
+ Prag := Get_Pragma (Spec_Id, Pragma_Initial_Condition);
+
+ if Present (Prag) then
+ Analyze_Initial_Condition_In_Decl_Part (Prag);
+ end if;
+
+ -- Analyze the state refinements within a package body now, after
+ -- all hidden states have been encountered and freely visible.
+ -- Refinements must be processed before pragmas Refined_Depends and
+ -- Refined_Global because the last two may mention constituents.
+
+ elsif Nkind (Context) = N_Package_Body then
+ In_Package_Body := True;
+
+ Body_Id := Defining_Entity (Context);
+ Spec_Id := Corresponding_Spec (Context);
+ Prag := Get_Pragma (Body_Id, Pragma_Refined_State);
+
+ -- The analysis of pragma Refined_State detects whether the spec
+ -- has abstract states available for refinement.
+
+ if Present (Prag) then
+ Analyze_Refined_State_In_Decl_Part (Prag);
+
+ -- State refinement is required when the package declaration has
+ -- abstract states. Null states are not considered.
+
+ elsif Requires_State_Refinement (Spec_Id, Body_Id) then
+ Error_Msg_NE
+ ("package & requires state refinement", Context, Spec_Id);
+ end if;
+ end if;
+ end if;
+
+ -- Analyze the contracts of a subprogram declaration or a body now due
+ -- to delayed visibility requirements of aspects.
+
+ Decl := First (L);
+ while Present (Decl) loop
+ if Nkind (Decl) = N_Subprogram_Body then
+ Analyze_Subprogram_Body_Contract (Defining_Entity (Decl));
+
+ elsif Nkind (Decl) = N_Subprogram_Declaration then
+ Analyze_Subprogram_Contract (Defining_Entity (Decl));
+ end if;
+
+ Next (Decl);
+ end loop;
+
+ -- State refinements are visible upto the end the of the package body
+ -- declarations. Hide the refinements from visibility to restore the
+ -- original state conditions.
+
+ if In_Package_Body then
+ Remove_Visible_Refinements (Spec_Id);
+ end if;
end Analyze_Declarations;
-----------------------------------
@@ -2459,7 +2626,7 @@ package body Sem_Ch3 is
-- finalization list at the point the access type is frozen, to
-- prevent unsatisfied references at link time.
- if not From_With_Type (T) or else Is_Access_Type (T) then
+ if not From_Limited_With (T) or else Is_Access_Type (T) then
Set_Has_Delayed_Freeze (T);
end if;
end;
@@ -3230,7 +3397,7 @@ package body Sem_Ch3 is
end if;
end if;
- -- Check incorrect use of dynamically tagged expressions.
+ -- Check incorrect use of dynamically tagged expressions
if Is_Tagged_Type (T) then
Check_Dynamically_Tagged_Expression
@@ -3248,7 +3415,7 @@ package body Sem_Ch3 is
-- Only call test if needed
and then Restriction_Check_Required (SPARK_05)
- and then not Is_SPARK_Initialization_Expr (E)
+ and then not Is_SPARK_Initialization_Expr (Original_Node (E))
then
Check_SPARK_Restriction
("initialization expression is not appropriate", E);
@@ -3505,7 +3672,7 @@ package body Sem_Ch3 is
if Constant_Present (N) then
Set_Ekind (Id, E_Constant);
- Set_Is_True_Constant (Id, True);
+ Set_Is_True_Constant (Id);
else
Set_Ekind (Id, E_Variable);
@@ -3728,6 +3895,13 @@ package body Sem_Ch3 is
end if;
<<Leave>>
+ -- Initialize the refined state of a variable here because this is a
+ -- common destination for legal and illegal object declarations.
+
+ if Ekind (Id) = E_Variable then
+ Set_Refined_State (Id, Empty);
+ end if;
+
if Has_Aspects (N) then
Analyze_Aspect_Specifications (N, Id);
end if;
@@ -4017,6 +4191,13 @@ package body Sem_Ch3 is
-- type with constraints. In this case the entity has been introduced
-- in the private declaration.
+ -- Finally this happens in some complex cases when validity checks are
+ -- enabled, where the same subtype declaration may be analyzed twice.
+ -- This can happen if the subtype is created by the pre-analysis of
+ -- an attribute tht gives the range of a loop statement, and the loop
+ -- itself appears within an if_statement that will be rewritten during
+ -- expansion.
+
if Skip
or else (Present (Etype (Id))
and then (Is_Private_Type (Etype (Id))
@@ -4025,6 +4206,9 @@ package body Sem_Ch3 is
then
null;
+ elsif Current_Entity (Id) = Id then
+ null;
+
else
Enter_Name (Id);
end if;
@@ -4362,11 +4546,11 @@ package body Sem_Ch3 is
-- Ada 2005 (AI-412): Decorate an incomplete subtype of an
-- incomplete type visible through a limited with clause.
- if From_With_Type (T)
+ if From_Limited_With (T)
and then Present (Non_Limited_View (T))
then
- Set_From_With_Type (Id);
- Set_Non_Limited_View (Id, Non_Limited_View (T));
+ Set_From_Limited_With (Id);
+ Set_Non_Limited_View (Id, Non_Limited_View (T));
-- Ada 2005 (AI-412): Add the regular incomplete subtype
-- to the private dependents of the original incomplete
@@ -4590,61 +4774,31 @@ package body Sem_Ch3 is
--------------------------
procedure Analyze_Variant_Part (N : Node_Id) is
+ Discr_Name : Node_Id;
+ Discr_Type : Entity_Id;
- procedure Non_Static_Choice_Error (Choice : Node_Id);
- -- Error routine invoked by the generic instantiation below when the
- -- variant part has a non static choice.
-
- procedure Process_Declarations (Variant : Node_Id);
- -- Analyzes all the declarations associated with a Variant. Needed by
- -- the generic instantiation below.
-
- package Variant_Choices_Processing is new
- Generic_Choices_Processing
- (Get_Alternatives => Variants,
- Get_Choices => Discrete_Choices,
- Process_Empty_Choice => No_OP,
- Process_Non_Static_Choice => Non_Static_Choice_Error,
- Process_Associated_Node => Process_Declarations);
- use Variant_Choices_Processing;
- -- Instantiation of the generic choice processing package
-
- -----------------------------
- -- Non_Static_Choice_Error --
- -----------------------------
+ procedure Process_Variant (A : Node_Id);
+ -- Analyze declarations for a single variant
- procedure Non_Static_Choice_Error (Choice : Node_Id) is
- begin
- Flag_Non_Static_Expr
- ("choice given in variant part is not static!", Choice);
- end Non_Static_Choice_Error;
+ package Analyze_Variant_Choices is
+ new Generic_Analyze_Choices (Process_Variant);
+ use Analyze_Variant_Choices;
- --------------------------
- -- Process_Declarations --
- --------------------------
+ ---------------------
+ -- Process_Variant --
+ ---------------------
- procedure Process_Declarations (Variant : Node_Id) is
+ procedure Process_Variant (A : Node_Id) is
+ CL : constant Node_Id := Component_List (A);
begin
- if not Null_Present (Component_List (Variant)) then
- Analyze_Declarations (Component_Items (Component_List (Variant)));
+ if not Null_Present (CL) then
+ Analyze_Declarations (Component_Items (CL));
- if Present (Variant_Part (Component_List (Variant))) then
- Analyze (Variant_Part (Component_List (Variant)));
+ if Present (Variant_Part (CL)) then
+ Analyze (Variant_Part (CL));
end if;
end if;
- end Process_Declarations;
-
- -- Local Variables
-
- Discr_Name : Node_Id;
- Discr_Type : Entity_Id;
-
- Dont_Care : Boolean;
- Others_Present : Boolean := False;
-
- pragma Warnings (Off, Dont_Care);
- pragma Warnings (Off, Others_Present);
- -- We don't care about the assigned values of any of these
+ end Process_Variant;
-- Start of processing for Analyze_Variant_Part
@@ -4673,9 +4827,18 @@ package body Sem_Ch3 is
return;
end if;
- -- Call the instantiated Analyze_Choices which does the rest of the work
+ -- Now analyze the choices, which also analyzes the declarations that
+ -- are associated with each choice.
+
+ Analyze_Choices (Variants (N), Discr_Type);
+
+ -- Note: we used to instantiate and call Check_Choices here to check
+ -- that the choices covered the discriminant, but it's too early to do
+ -- that because of statically predicated subtypes, whose analysis may
+ -- be deferred to their freeze point which may be as late as the freeze
+ -- point of the containing record. So this call is now to be found in
+ -- Freeze_Record_Declaration.
- Analyze_Choices (N, Discr_Type, Dont_Care, Others_Present);
end Analyze_Variant_Part;
----------------------------
@@ -5101,12 +5264,14 @@ package body Sem_Ch3 is
if Nkind (Def) = N_Access_Definition then
if Present (Access_To_Subprogram_Definition (Def)) then
- Set_Etype (Def,
+ Set_Etype
+ (Def,
Replace_Anonymous_Access_To_Protected_Subprogram
(Spec));
else
Find_Type (Subtype_Mark (Def));
end if;
+
else
Find_Type (Def);
end if;
@@ -7251,45 +7416,65 @@ package body Sem_Ch3 is
and then (Is_Constrained (Parent_Type) or else Constraint_Present)
then
-- First, we must analyze the constraint (see comment in point 5.)
+ -- The constraint may come from the subtype indication of the full
+ -- declaration.
if Constraint_Present then
New_Discrs := Build_Discriminant_Constraints (Parent_Type, Indic);
- if Has_Discriminants (Derived_Type)
- and then Has_Private_Declaration (Derived_Type)
- and then Present (Discriminant_Constraint (Derived_Type))
- then
- -- Verify that constraints of the full view statically match
- -- those given in the partial view.
+ -- If there is no explicit constraint, there might be one that is
+ -- inherited from a constrained parent type. In that case verify that
+ -- it conforms to the constraint in the partial view. In perverse
+ -- cases the parent subtypes of the partial and full view can have
+ -- different constraints.
- declare
- C1, C2 : Elmt_Id;
+ elsif Present (Stored_Constraint (Parent_Type)) then
+ New_Discrs := Stored_Constraint (Parent_Type);
- begin
- C1 := First_Elmt (New_Discrs);
- C2 := First_Elmt (Discriminant_Constraint (Derived_Type));
- while Present (C1) and then Present (C2) loop
- if Fully_Conformant_Expressions (Node (C1), Node (C2))
- or else
- (Is_OK_Static_Expression (Node (C1))
- and then
- Is_OK_Static_Expression (Node (C2))
- and then
+ else
+ New_Discrs := No_Elist;
+ end if;
+
+ if Has_Discriminants (Derived_Type)
+ and then Has_Private_Declaration (Derived_Type)
+ and then Present (Discriminant_Constraint (Derived_Type))
+ and then Present (New_Discrs)
+ then
+ -- Verify that constraints of the full view statically match
+ -- those given in the partial view.
+
+ declare
+ C1, C2 : Elmt_Id;
+
+ begin
+ C1 := First_Elmt (New_Discrs);
+ C2 := First_Elmt (Discriminant_Constraint (Derived_Type));
+ while Present (C1) and then Present (C2) loop
+ if Fully_Conformant_Expressions (Node (C1), Node (C2))
+ or else
+ (Is_OK_Static_Expression (Node (C1))
+ and then Is_OK_Static_Expression (Node (C2))
+ and then
Expr_Value (Node (C1)) = Expr_Value (Node (C2)))
- then
- null;
+ then
+ null;
+ else
+ if Constraint_Present then
+ Error_Msg_N
+ ("constraint not conformant to previous declaration",
+ Node (C1));
else
- Error_Msg_N (
- "constraint not conformant to previous declaration",
- Node (C1));
+ Error_Msg_N
+ ("constraint of full view is incompatible "
+ & "with partial view", N);
end if;
+ end if;
- Next_Elmt (C1);
- Next_Elmt (C2);
- end loop;
- end;
- end if;
+ Next_Elmt (C1);
+ Next_Elmt (C2);
+ end loop;
+ end;
end if;
-- Insert and analyze the declaration for the unconstrained base type
@@ -9418,6 +9603,17 @@ package body Sem_Ch3 is
end if;
end if;
+ -- If the operation is a wrapper for a synchronized primitive, it
+ -- may be called indirectly through a dispatching select. We assume
+ -- that it will be referenced elsewhere indirectly, and suppress
+ -- warnings about an unused entity.
+
+ if Is_Primitive_Wrapper (Subp)
+ and then Present (Wrapped_Entity (Subp))
+ then
+ Set_Referenced (Wrapped_Entity (Subp));
+ end if;
+
Next_Elmt (Elmt);
end loop;
end Check_Abstract_Overriding;
@@ -9440,7 +9636,7 @@ package body Sem_Ch3 is
-- or else be a partial view.
if Nkind (Discriminant_Type (D)) = N_Access_Definition then
- if Is_Immutably_Limited_Type (Current_Scope)
+ if Is_Limited_View (Current_Scope)
or else
(Nkind (Parent (Current_Scope)) = N_Private_Type_Declaration
and then Limited_Present (Parent (Current_Scope)))
@@ -10336,6 +10532,14 @@ package body Sem_Ch3 is
Set_First_Entity (Full, First_Entity (Full_Base));
Set_Last_Entity (Full, Last_Entity (Full_Base));
+ -- If the underlying base type is constrained, we know that the
+ -- full view of the subtype is constrained as well (the converse
+ -- is not necessarily true).
+
+ if Is_Constrained (Full_Base) then
+ Set_Is_Constrained (Full);
+ end if;
+
when others =>
Copy_Node (Full_Base, Full);
@@ -10795,8 +10999,7 @@ package body Sem_Ch3 is
elsif Ekind (Current_Scope) = E_Package
and then
List_Containing (Parent (Prev)) /=
- Visible_Declarations
- (Specification (Unit_Declaration_Node (Current_Scope)))
+ Visible_Declarations (Package_Specification (Current_Scope))
then
Error_Msg_N
("deferred constant must be declared in visible part",
@@ -11810,13 +12013,12 @@ package body Sem_Ch3 is
-- incomplete type or imported via a limited with clause.
if Has_Discriminants (T)
- or else
- (From_With_Type (T)
- and then Present (Non_Limited_View (T))
- and then Nkind (Parent (Non_Limited_View (T))) =
- N_Full_Type_Declaration
- and then Present (Discriminant_Specifications
- (Parent (Non_Limited_View (T)))))
+ or else (From_Limited_With (T)
+ and then Present (Non_Limited_View (T))
+ and then Nkind (Parent (Non_Limited_View (T))) =
+ N_Full_Type_Declaration
+ and then Present (Discriminant_Specifications
+ (Parent (Non_Limited_View (T)))))
then
Error_Msg_N
("(Ada 2005) incomplete subtype may not be constrained", C);
@@ -14779,7 +14981,8 @@ package body Sem_Ch3 is
-- extensions of tagged record types.
if No (Extension) then
- Check_SPARK_Restriction ("derived type is not allowed", N);
+ Check_SPARK_Restriction
+ ("derived type is not allowed", Original_Node (N));
end if;
end Derived_Type_Declaration;
diff --git a/gcc/ada/sem_ch4.adb b/gcc/ada/sem_ch4.adb
index c4247cd403d..52aa233746b 100644
--- a/gcc/ada/sem_ch4.adb
+++ b/gcc/ada/sem_ch4.adb
@@ -1315,14 +1315,17 @@ package body Sem_Ch4 is
-- Error routine invoked by the generic instantiation below when
-- the case expression has a non static choice.
- package Case_Choices_Processing is new
- Generic_Choices_Processing
- (Get_Alternatives => Alternatives,
- Get_Choices => Discrete_Choices,
- Process_Empty_Choice => No_OP,
+ package Case_Choices_Analysis is new
+ Generic_Analyze_Choices
+ (Process_Associated_Node => No_OP);
+ use Case_Choices_Analysis;
+
+ package Case_Choices_Checking is new
+ Generic_Check_Choices
+ (Process_Empty_Choice => No_OP,
Process_Non_Static_Choice => Non_Static_Choice_Error,
Process_Associated_Node => No_OP);
- use Case_Choices_Processing;
+ use Case_Choices_Checking;
--------------------------
-- Has_Static_Predicate --
@@ -1364,8 +1367,8 @@ package body Sem_Ch4 is
Exp_Type : Entity_Id;
Exp_Btype : Entity_Id;
- Dont_Care : Boolean;
Others_Present : Boolean;
+ -- Indicates if Others was present
-- Start of processing for Analyze_Case_Expression
@@ -1428,9 +1431,7 @@ package body Sem_Ch4 is
-- If error already reported by Resolve, nothing more to do
- if Exp_Btype = Any_Discrete
- or else Exp_Btype = Any_Type
- then
+ if Exp_Btype = Any_Discrete or else Exp_Btype = Any_Type then
return;
elsif Exp_Btype = Any_Character then
@@ -1462,10 +1463,11 @@ package body Sem_Ch4 is
then
null;
- -- Call instantiated Analyze_Choices which does the rest of the work
+ -- Call Analyze_Choices and Check_Choices to do the rest of the work
else
- Analyze_Choices (N, Exp_Type, Dont_Care, Others_Present);
+ Analyze_Choices (Alternatives (N), Exp_Type);
+ Check_Choices (N, Alternatives (N), Exp_Type, Others_Present);
end if;
if Exp_Type = Universal_Integer and then not Others_Present then
@@ -1859,8 +1861,8 @@ package body Sem_Ch4 is
-- incomplete type imported through a limited_with clause,
-- if the full view is visible.
- if From_With_Type (DT)
- and then not From_With_Type (Scope (DT))
+ if From_Limited_With (DT)
+ and then not From_Limited_With (Scope (DT))
and then
(Is_Immediately_Visible (Scope (DT))
or else
@@ -2031,7 +2033,9 @@ package body Sem_Ch4 is
return;
end if;
- Check_SPARK_Restriction ("if expression is not allowed", N);
+ if Comes_From_Source (N) then
+ Check_SPARK_Restriction ("if expression is not allowed", N);
+ end if;
Else_Expr := Next (Then_Expr);
@@ -3962,10 +3966,24 @@ package body Sem_Ch4 is
Next (Param);
end loop;
- -- One of the specs has additional formals
+ -- One of the specs has additional formals; there is no match, unless
+ -- this may be an indexing of a parameterless call.
+
+ -- Note that when expansion is disabled, the corresponding record
+ -- type of synchronized types is not constructed, so that there is
+ -- no point is attempting an interpretation as a prefixed call, as
+ -- this is bound to fail because the primitive operations will not
+ -- be properly located.
if Present (Comp_Param) or else Present (Param) then
- return False;
+ if Needs_No_Actuals (Comp)
+ and then Is_Array_Type (Etype (Comp))
+ and then not Expander_Active
+ then
+ return True;
+ else
+ return False;
+ end if;
end if;
return True;
@@ -4055,7 +4073,7 @@ package body Sem_Ch4 is
-- full view if available.
if Is_Incomplete_Type (Prefix_Type)
- and then From_With_Type (Prefix_Type)
+ and then From_Limited_With (Prefix_Type)
and then Present (Non_Limited_View (Prefix_Type))
then
Prefix_Type := Get_Full_View (Non_Limited_View (Prefix_Type));
@@ -4065,7 +4083,7 @@ package body Sem_Ch4 is
end if;
elsif Ekind (Prefix_Type) = E_Class_Wide_Type
- and then From_With_Type (Prefix_Type)
+ and then From_Limited_With (Prefix_Type)
and then Present (Non_Limited_View (Etype (Prefix_Type)))
then
Prefix_Type :=
@@ -4173,7 +4191,7 @@ package body Sem_Ch4 is
-- end Pkg; -- Comp is not visible
if Nkind (Name) = N_Explicit_Dereference
- and then From_With_Type (Etype (Prefix (Name)))
+ and then From_Limited_With (Etype (Prefix (Name)))
and then not Is_Potentially_Use_Visible (Etype (Name))
and then Nkind (Parent (Cunit_Entity (Current_Sem_Unit))) =
N_Package_Specification
@@ -4626,7 +4644,7 @@ package body Sem_Ch4 is
Inc : constant Entity_Id := First_Subtype (Type_To_Use);
begin
- if From_With_Type (Scope (Type_To_Use)) then
+ if From_Limited_With (Scope (Type_To_Use)) then
Error_Msg_NE
("\limited view of& has no components", N, Inc);
@@ -5346,7 +5364,7 @@ package body Sem_Ch4 is
-- usage of an entity from the limited view.
if not Analyzed (Etype (Actual))
- and then From_With_Type (Etype (Actual))
+ and then From_Limited_With (Etype (Actual))
then
Error_Msg_Qual_Level := 1;
Error_Msg_NE
@@ -6507,8 +6525,8 @@ package body Sem_Ch4 is
-- incomplete type imported through a limited_with clause,
-- if the full view is visible.
- if From_With_Type (Typ)
- and then not From_With_Type (Scope (Typ))
+ if From_Limited_With (Typ)
+ and then not From_Limited_With (Scope (Typ))
and then
(Is_Immediately_Visible (Scope (Typ))
or else
@@ -7735,7 +7753,7 @@ package body Sem_Ch4 is
-- non-limited view. If still incomplete, retrieve full view.
if Ekind (Obj_Type) = E_Incomplete_Type
- and then From_With_Type (Obj_Type)
+ and then From_Limited_With (Obj_Type)
then
Obj_Type := Get_Full_View (Non_Limited_View (Obj_Type));
end if;
diff --git a/gcc/ada/sem_ch5.adb b/gcc/ada/sem_ch5.adb
index 2f8eced6fc9..a29aece272c 100644
--- a/gcc/ada/sem_ch5.adb
+++ b/gcc/ada/sem_ch5.adb
@@ -1018,12 +1018,12 @@ package body Sem_Ch5 is
Exp_Type : Entity_Id;
Exp_Btype : Entity_Id;
Last_Choice : Nat;
- Dont_Care : Boolean;
+
Others_Present : Boolean;
+ -- Indicates if Others was present
pragma Warnings (Off, Last_Choice);
- pragma Warnings (Off, Dont_Care);
- -- Don't care about assigned values
+ -- Don't care about assigned value
Statements_Analyzed : Boolean := False;
-- Set True if at least some statement sequences get analyzed. If False
@@ -1039,17 +1039,21 @@ package body Sem_Ch5 is
-- case statement has a non static choice.
procedure Process_Statements (Alternative : Node_Id);
- -- Analyzes all the statements associated with a case alternative.
- -- Needed by the generic instantiation below.
-
- package Case_Choices_Processing is new
- Generic_Choices_Processing
- (Get_Alternatives => Alternatives,
- Get_Choices => Discrete_Choices,
- Process_Empty_Choice => No_OP,
+ -- Analyzes the statements associated with a case alternative. Needed
+ -- by instantiation below.
+
+ package Analyze_Case_Choices is new
+ Generic_Analyze_Choices
+ (Process_Associated_Node => Process_Statements);
+ use Analyze_Case_Choices;
+ -- Instantiation of the generic choice analysis package
+
+ package Check_Case_Choices is new
+ Generic_Check_Choices
+ (Process_Empty_Choice => No_OP,
Process_Non_Static_Choice => Non_Static_Choice_Error,
- Process_Associated_Node => Process_Statements);
- use Case_Choices_Processing;
+ Process_Associated_Node => No_Op);
+ use Check_Case_Choices;
-- Instantiation of the generic choice processing package
-----------------------------
@@ -1155,9 +1159,7 @@ package body Sem_Ch5 is
-- If error already reported by Resolve, nothing more to do
- if Exp_Btype = Any_Discrete
- or else Exp_Btype = Any_Type
- then
+ if Exp_Btype = Any_Discrete or else Exp_Btype = Any_Type then
return;
elsif Exp_Btype = Any_Character then
@@ -1186,12 +1188,12 @@ package body Sem_Ch5 is
Exp_Type := Exp_Btype;
end if;
- -- Call instantiated Analyze_Choices which does the rest of the work
+ -- Call instantiated procedures to analyzwe and check discrete choices
- Analyze_Choices (N, Exp_Type, Dont_Care, Others_Present);
+ Analyze_Choices (Alternatives (N), Exp_Type);
+ Check_Choices (N, Alternatives (N), Exp_Type, Others_Present);
- -- A case statement with a single OTHERS alternative is not allowed
- -- in SPARK.
+ -- Case statement with single OTHERS alternative not allowed in SPARK
if Others_Present and then List_Length (Alternatives (N)) = 1 then
Check_SPARK_Restriction
@@ -1214,6 +1216,12 @@ package body Sem_Ch5 is
Unblocked_Exit_Count := Save_Unblocked_Exit_Count;
end if;
+ -- If the expander is active it will detect the case of a statically
+ -- determined single alternative and remove warnings for the case, but
+ -- if we are not doing expansion, that circuit won't be active. Here we
+ -- duplicate the effect of removing warnings in the same way, so that
+ -- we will get the same set of warnings in -gnatc mode.
+
if not Expander_Active
and then Compile_Time_Known_Value (Expression (N))
and then Serious_Errors_Detected = 0
@@ -1569,6 +1577,43 @@ package body Sem_Ch5 is
Remove_Warning_Messages (Then_Statements (N));
end if;
end if;
+
+ -- Warn on redundant if statement that has no effect
+
+ -- Note, we could also check empty ELSIF parts ???
+
+ if Warn_On_Redundant_Constructs
+
+ -- If statement must be from source
+
+ and then Comes_From_Source (N)
+
+ -- Condition must not have obvious side effect
+
+ and then Has_No_Obvious_Side_Effects (Condition (N))
+
+ -- No elsif parts of else part
+
+ and then No (Elsif_Parts (N))
+ and then No (Else_Statements (N))
+
+ -- Then must be a single null statement
+
+ and then List_Length (Then_Statements (N)) = 1
+ then
+ -- Go to original node, since we may have rewritten something as
+ -- a null statement (e.g. a case we could figure the outcome of).
+
+ declare
+ T : constant Node_Id := First (Then_Statements (N));
+ S : constant Node_Id := Original_Node (T);
+
+ begin
+ if Comes_From_Source (S) and then Nkind (S) = N_Null_Statement then
+ Error_Msg_N ("if statement has no effect?r?", N);
+ end if;
+ end;
+ end if;
end Analyze_If_Statement;
----------------------------------------
diff --git a/gcc/ada/sem_ch6.adb b/gcc/ada/sem_ch6.adb
index 7913d362f1e..3b5eee1680b 100644
--- a/gcc/ada/sem_ch6.adb
+++ b/gcc/ada/sem_ch6.adb
@@ -212,17 +212,6 @@ package body Sem_Ch6 is
-- Create the declaration for an inequality operator that is implicitly
-- created by a user-defined equality operator that yields a boolean.
- procedure Process_PPCs
- (N : Node_Id;
- Spec_Id : Entity_Id;
- Body_Id : Entity_Id);
- -- Called from Analyze[_Generic]_Subprogram_Body to deal with scanning post
- -- conditions for the body and assembling and inserting the _postconditions
- -- procedure. N is the node for the subprogram body and Body_Id/Spec_Id are
- -- the entities for the body and separate spec (if there is no separate
- -- spec, Spec_Id is Empty). Note that invariants and predicates may also
- -- provide postconditions, and are also handled in this procedure.
-
procedure Set_Formal_Validity (Formal_Id : Entity_Id);
-- Formal_Id is an formal parameter entity. This procedure deals with
-- setting the proper validity status for this entity, which depends on
@@ -349,15 +338,25 @@ package body Sem_Ch6 is
Make_Handled_Sequence_Of_Statements (LocX,
Statements => New_List (Ret)));
+ -- If the expression completes a generic subprogram, we must create a
+ -- separate node for the body, because at instantiation the original
+ -- node of the generic copy must be a generic subprogram body, and
+ -- cannot be a expression function. Otherwise we just rewrite the
+ -- expression with the non-generic body.
+
if Present (Prev) and then Ekind (Prev) = E_Generic_Function then
+ Insert_After (N, New_Body);
- -- If the expression completes a generic subprogram, we must create a
- -- separate node for the body, because at instantiation the original
- -- node of the generic copy must be a generic subprogram body, and
- -- cannot be a expression function. Otherwise we just rewrite the
- -- expression with the non-generic body.
+ -- Propagate any aspects or pragmas that apply to the expression
+ -- function to the proper body when the expression function acts
+ -- as a completion.
+
+ if Has_Aspects (N) then
+ Move_Aspects (N, To => New_Body);
+ end if;
+
+ Relocate_Pragmas_To_Body (New_Body);
- Insert_After (N, New_Body);
Rewrite (N, Make_Null_Statement (Loc));
Set_Has_Completion (Prev, False);
Analyze (N);
@@ -371,6 +370,12 @@ package body Sem_Ch6 is
Generate_Reference (Prev, Defining_Entity (N), 'b', Force => True);
Rewrite (N, New_Body);
+
+ -- Propagate any pragmas that apply to the expression function to the
+ -- proper body when the expression function acts as a completion.
+ -- Aspects are automatically transfered because of node rewriting.
+
+ Relocate_Pragmas_To_Body (N);
Analyze (N);
-- Prev is the previous entity with the same name, but it is can
@@ -581,7 +586,7 @@ package body Sem_Ch6 is
("(Ada 2005) cannot copy object of a limited type " &
"(RM-2005 6.5(5.5/2))", Expr);
- if Is_Immutably_Limited_Type (R_Type) then
+ if Is_Limited_View (R_Type) then
Error_Msg_N
("\return by reference not permitted in Ada 2005", Expr);
end if;
@@ -601,7 +606,7 @@ package body Sem_Ch6 is
("return of limited object not permitted in Ada 2005 "
& "(RM-2005 6.5(5.5/2))?y?", Expr);
- elsif Is_Immutably_Limited_Type (R_Type) then
+ elsif Is_Limited_View (R_Type) then
Error_Msg_N
("return by reference not permitted in Ada 2005 "
& "(RM-2005 6.5(5.5/2))?y?", Expr);
@@ -875,7 +880,7 @@ package body Sem_Ch6 is
("aliased only allowed for limited"
& " return objects in Ada 2012?", N);
- elsif not Is_Immutably_Limited_Type (R_Type) then
+ elsif not Is_Limited_View (R_Type) then
Error_Msg_N ("aliased only allowed for limited"
& " return objects", N);
end if;
@@ -958,7 +963,7 @@ package body Sem_Ch6 is
-- check the static cases.
if (Ada_Version < Ada_2005 or else Debug_Flag_Dot_L)
- and then Is_Immutably_Limited_Type (Etype (Scope_Id))
+ and then Is_Limited_View (Etype (Scope_Id))
and then Object_Access_Level (Expr) >
Subprogram_Access_Level (Scope_Id)
then
@@ -1104,7 +1109,7 @@ package body Sem_Ch6 is
-- Visible generic entity is callable within its own body
Set_Ekind (Gen_Id, Ekind (Body_Id));
- Set_Contract (Body_Id, Empty);
+ Set_Contract (Body_Id, Make_Contract (Sloc (Body_Id)));
Set_Ekind (Body_Id, E_Subprogram_Body);
Set_Convention (Body_Id, Convention (Gen_Id));
Set_Is_Obsolescent (Body_Id, Is_Obsolescent (Gen_Id));
@@ -1140,13 +1145,14 @@ package body Sem_Ch6 is
Set_Actual_Subtypes (N, Current_Scope);
- -- Deal with preconditions and postconditions. In formal verification
- -- mode, we keep pre- and postconditions attached to entities rather
- -- than inserted in the code, in order to facilitate a distinct
- -- treatment for them.
+ -- Deal with [refined] preconditions, postconditions, Contract_Cases,
+ -- invariants and predicates associated with the body and its spec.
+ -- Note that this is not pure expansion as Expand_Subprogram_Contract
+ -- prepares the contract assertions for generic subprograms or for
+ -- ASIS. Do not generate contract checks in SPARK mode.
if not SPARK_Mode then
- Process_PPCs (N, Gen_Id, Body_Id);
+ Expand_Subprogram_Contract (N, Gen_Id, Body_Id);
end if;
-- If the generic unit carries pre- or post-conditions, copy them
@@ -1965,6 +1971,79 @@ package body Sem_Ch6 is
end if;
end Analyze_Subprogram_Body;
+ --------------------------------------
+ -- Analyze_Subprogram_Body_Contract --
+ --------------------------------------
+
+ procedure Analyze_Subprogram_Body_Contract (Body_Id : Entity_Id) is
+ Body_Decl : constant Node_Id := Parent (Parent (Body_Id));
+ Spec_Id : constant Entity_Id := Corresponding_Spec (Body_Decl);
+ Prag : Node_Id;
+ Ref_Depends : Node_Id := Empty;
+ Ref_Global : Node_Id := Empty;
+
+ begin
+ -- When a subprogram body declaration is erroneous, its defining entity
+ -- is left unanalyzed. There is nothing left to do in this case because
+ -- the body lacks a contract.
+
+ if not Analyzed (Body_Id) then
+ return;
+ end if;
+
+ -- Locate and store pragmas Refined_Depends and Refined_Global since
+ -- their order of analysis matters.
+
+ Prag := Classifications (Contract (Body_Id));
+ while Present (Prag) loop
+ if Pragma_Name (Prag) = Name_Refined_Depends then
+ Ref_Depends := Prag;
+ elsif Pragma_Name (Prag) = Name_Refined_Global then
+ Ref_Global := Prag;
+ end if;
+
+ Prag := Next_Pragma (Prag);
+ end loop;
+
+ -- Analyze Refined_Global first as Refined_Depends may mention items
+ -- classified in the global refinement.
+
+ if Present (Ref_Global) then
+ Analyze_Refined_Global_In_Decl_Part (Ref_Global);
+
+ -- When the corresponding Global aspect/pragma references a state with
+ -- visible refinement, the body requires Refined_Global.
+
+ elsif Present (Spec_Id) then
+ Prag := Get_Pragma (Spec_Id, Pragma_Global);
+
+ if Present (Prag) and then Contains_Refined_State (Prag) then
+ Error_Msg_NE
+ ("body of subprogram & requires global refinement",
+ Body_Decl, Spec_Id);
+ end if;
+ end if;
+
+ -- Refined_Depends must be analyzed after Refined_Global in order to see
+ -- the modes of all global refinements.
+
+ if Present (Ref_Depends) then
+ Analyze_Refined_Depends_In_Decl_Part (Ref_Depends);
+
+ -- When the corresponding Depends aspect/pragma references a state with
+ -- visible refinement, the body requires Refined_Depends.
+
+ elsif Present (Spec_Id) then
+ Prag := Get_Pragma (Spec_Id, Pragma_Depends);
+
+ if Present (Prag) and then Contains_Refined_State (Prag) then
+ Error_Msg_NE
+ ("body of subprogram & requires dependance refinement",
+ Body_Decl, Spec_Id);
+ end if;
+ end if;
+ end Analyze_Subprogram_Body_Contract;
+
------------------------------------
-- Analyze_Subprogram_Body_Helper --
------------------------------------
@@ -2421,7 +2500,7 @@ package body Sem_Ch6 is
begin
if Ekind (Typ) = E_Incomplete_Type
- and then From_With_Type (Typ)
+ and then From_Limited_With (Typ)
and then Present (Non_Limited_View (Typ))
then
Set_Etype (Id, Non_Limited_View (Typ));
@@ -2672,20 +2751,30 @@ package body Sem_Ch6 is
end if;
end if;
- -- Language-defined aspects cannot appear in a subprogram body if the
- -- corresponding spec already has aspects. Exception to this rule are
- -- certain user-defined aspects. Aspects that apply to a body stub are
- -- moved to the proper body. Do not emit an error in this case.
+ -- Language-defined aspects cannot appear in a subprogram body [stub] if
+ -- the subprogram has a separate spec. Certainly implementation-defined
+ -- aspects are allowed to appear (per Aspects_On_Body_Of_Stub_OK).
if Has_Aspects (N) then
if Present (Spec_Id)
- and then Nkind (N) not in N_Body_Stub
- and then Nkind (Parent (N)) /= N_Subunit
- and then not Aspects_On_Body_OK (N)
+ and then not Aspects_On_Body_Or_Stub_OK (N)
+
+ -- Do not emit an error on a subprogram body stub that act as
+ -- its own spec.
+
+ and then Nkind (Parent (Parent (Spec_Id))) /= N_Subprogram_Body_Stub
then
Error_Msg_N
("aspect specifications must appear in subprogram declaration",
- N);
+ N);
+
+ -- Delay the analysis of aspect specifications that apply to a body
+ -- stub until the proper body is analyzed. If the corresponding body
+ -- is missing, the aspects are still analyzed in Analyze_Proper_Body.
+
+ elsif Nkind (N) in N_Body_Stub then
+ null;
+
else
Analyze_Aspect_Specifications (N, Body_Id);
end if;
@@ -2835,7 +2924,12 @@ package body Sem_Ch6 is
Reference_Body_Formals (Spec_Id, Body_Id);
end if;
- if Nkind (N) /= N_Subprogram_Body_Stub then
+ if Nkind (N) = N_Subprogram_Body_Stub then
+ Set_Corresponding_Spec_Of_Stub (N, Spec_Id);
+
+ -- Regular body
+
+ else
Set_Corresponding_Spec (N, Spec_Id);
-- Ada 2005 (AI-345): If the operation is a primitive operation
@@ -2852,12 +2946,9 @@ package body Sem_Ch6 is
and then Present (First_Entity (Spec_Id))
and then Ekind (Etype (First_Entity (Spec_Id))) = E_Record_Type
and then Is_Tagged_Type (Etype (First_Entity (Spec_Id)))
- and then
- Present (Interfaces (Etype (First_Entity (Spec_Id))))
- and then
- Present
- (Corresponding_Concurrent_Type
- (Etype (First_Entity (Spec_Id))))
+ and then Present (Interfaces (Etype (First_Entity (Spec_Id))))
+ and then Present (Corresponding_Concurrent_Type
+ (Etype (First_Entity (Spec_Id))))
then
declare
Typ : constant Entity_Id := Etype (First_Entity (Spec_Id));
@@ -2905,7 +2996,7 @@ package body Sem_Ch6 is
end if;
Set_Corresponding_Body (Unit_Declaration_Node (Spec_Id), Body_Id);
- Set_Contract (Body_Id, Empty);
+ Set_Contract (Body_Id, Make_Contract (Sloc (Body_Id)));
Set_Ekind (Body_Id, E_Subprogram_Body);
Set_Scope (Body_Id, Scope (Spec_Id));
Set_Is_Obsolescent (Body_Id, Is_Obsolescent (Spec_Id));
@@ -2967,7 +3058,9 @@ package body Sem_Ch6 is
if Ekind (Rtyp) = E_Anonymous_Access_Type then
Etyp := Directly_Designated_Type (Rtyp);
- if Is_Class_Wide_Type (Etyp) and then From_With_Type (Etyp) then
+ if Is_Class_Wide_Type (Etyp)
+ and then From_Limited_With (Etyp)
+ then
Set_Directly_Designated_Type
(Etype (Current_Scope), Available_View (Etyp));
end if;
@@ -3089,13 +3182,14 @@ package body Sem_Ch6 is
HSS := Handled_Statement_Sequence (N);
Set_Actual_Subtypes (N, Current_Scope);
- -- Deal with preconditions and postconditions. In formal verification
- -- mode, we keep pre- and postconditions attached to entities rather
- -- than inserted in the code, in order to facilitate a distinct
- -- treatment for them.
+ -- Deal with [refined] preconditions, postconditions, Contract_Cases,
+ -- invariants and predicates associated with the body and its spec.
+ -- Note that this is not pure expansion as Expand_Subprogram_Contract
+ -- prepares the contract assertions for generic subprograms or for ASIS.
+ -- Do not generate contract checks in SPARK mode.
if not SPARK_Mode then
- Process_PPCs (N, Spec_Id, Body_Id);
+ Expand_Subprogram_Contract (N, Spec_Id, Body_Id);
end if;
-- Add a declaration for the Protection object, renaming declarations
@@ -3505,23 +3599,23 @@ package body Sem_Ch6 is
-- Local variables
Items : constant Node_Id := Contract (Subp);
- Error_CCase : Node_Id;
- Error_Post : Node_Id;
+ Depends : Node_Id := Empty;
+ Error_CCase : Node_Id := Empty;
+ Error_Post : Node_Id := Empty;
+ Global : Node_Id := Empty;
+ Nam : Name_Id;
Prag : Node_Id;
-- Start of processing for Analyze_Subprogram_Contract
begin
- Error_CCase := Empty;
- Error_Post := Empty;
-
if Present (Items) then
-- Analyze pre- and postconditions
Prag := Pre_Post_Conditions (Items);
while Present (Prag) loop
- Analyze_PPC_In_Decl_Part (Prag, Subp);
+ Analyze_Pre_Post_Condition_In_Decl_Part (Prag, Subp);
-- Verify whether a postcondition mentions attribute 'Result and
-- its expression introduces a post-state.
@@ -3539,7 +3633,9 @@ package body Sem_Ch6 is
Prag := Contract_Test_Cases (Items);
while Present (Prag) loop
- if Pragma_Name (Prag) = Name_Contract_Cases then
+ Nam := Pragma_Name (Prag);
+
+ if Nam = Name_Contract_Cases then
Analyze_Contract_Cases_In_Decl_Part (Prag);
-- Verify whether contract-cases mention attribute 'Result and
@@ -3553,7 +3649,7 @@ package body Sem_Ch6 is
end if;
else
- pragma Assert (Pragma_Name (Prag) = Name_Test_Case);
+ pragma Assert (Nam = Name_Test_Case);
Analyze_Test_Case_In_Decl_Part (Prag, Subp);
end if;
@@ -3564,15 +3660,30 @@ package body Sem_Ch6 is
Prag := Classifications (Contract (Subp));
while Present (Prag) loop
- if Pragma_Name (Prag) = Name_Depends then
- Analyze_Depends_In_Decl_Part (Prag);
- else
- pragma Assert (Pragma_Name (Prag) = Name_Global);
- Analyze_Global_In_Decl_Part (Prag);
+ Nam := Pragma_Name (Prag);
+
+ if Nam = Name_Depends then
+ Depends := Prag;
+ else pragma Assert (Nam = Name_Global);
+ Global := Prag;
end if;
Prag := Next_Pragma (Prag);
end loop;
+
+ -- Analyze Global first as Depends may mention items classified in
+ -- the global categorization.
+
+ if Present (Global) then
+ Analyze_Global_In_Decl_Part (Global);
+ end if;
+
+ -- Depends must be analyzed after Global in order to see the modes of
+ -- all global items.
+
+ if Present (Depends) then
+ Analyze_Depends_In_Decl_Part (Depends);
+ end if;
end if;
-- Emit an error when none of the postconditions or contract-cases
@@ -6438,7 +6549,9 @@ package body Sem_Ch6 is
then
Set_Has_Delayed_Freeze (Designator);
- elsif Ekind (T) = E_Incomplete_Type and then From_With_Type (T) then
+ elsif Ekind (T) = E_Incomplete_Type
+ and then From_Limited_With (T)
+ then
Set_Has_Delayed_Freeze (Designator);
-- AI05-0151: In Ada 2012, Incomplete types can appear in the profile
@@ -6480,7 +6593,7 @@ package body Sem_Ch6 is
Typ : constant Entity_Id := Etype (Designator);
Utyp : constant Entity_Id := Underlying_Type (Typ);
begin
- if Is_Immutably_Limited_Type (Typ) then
+ if Is_Limited_View (Typ) then
Set_Returns_By_Ref (Designator);
elsif Present (Utyp) and then CW_Or_Has_Controlled_Part (Utyp) then
Set_Returns_By_Ref (Designator);
@@ -7602,14 +7715,14 @@ package body Sem_Ch6 is
-- access-to-class-wide type in a formal. Both entities designate the
-- same type.
- if From_With_Type (T1) and then T2 = Available_View (T1) then
+ if From_Limited_With (T1) and then T2 = Available_View (T1) then
return True;
- elsif From_With_Type (T2) and then T1 = Available_View (T2) then
+ elsif From_Limited_With (T2) and then T1 = Available_View (T2) then
return True;
- elsif From_With_Type (T1)
- and then From_With_Type (T2)
+ elsif From_Limited_With (T1)
+ and then From_Limited_With (T2)
and then Available_View (T1) = Available_View (T2)
then
return True;
@@ -8103,7 +8216,8 @@ package body Sem_Ch6 is
-- the designated type comes from the limited view (for back-end
-- purposes).
- Set_From_With_Type (Formal_Typ, From_With_Type (Result_Subt));
+ Set_From_Limited_With
+ (Formal_Typ, From_Limited_With (Result_Subt));
Layout_Type (Formal_Typ);
@@ -9100,7 +9214,12 @@ package body Sem_Ch6 is
Iface_Prim : Entity_Id;
Prim : Entity_Id) return Boolean
is
- Iface : constant Entity_Id := Find_Dispatching_Type (Iface_Prim);
+ -- The operation may in fact be an inherited (implicit) operation
+ -- rather than the original interface primitive, so retrieve the
+ -- ultimate ancestor.
+
+ Iface : constant Entity_Id :=
+ Find_Dispatching_Type (Ultimate_Alias (Iface_Prim));
Typ : constant Entity_Id := Find_Dispatching_Type (Prim);
function Controlling_Formal (Prim : Entity_Id) return Entity_Id;
@@ -9111,9 +9230,10 @@ package body Sem_Ch6 is
------------------------
function Controlling_Formal (Prim : Entity_Id) return Entity_Id is
- E : Entity_Id := First_Entity (Prim);
+ E : Entity_Id;
begin
+ E := First_Entity (Prim);
while Present (E) loop
if Is_Formal (E) and then Is_Controlling_Formal (E) then
return E;
@@ -9158,8 +9278,8 @@ package body Sem_Ch6 is
-- The mode of the controlling formals must match
elsif Present (Iface_Ctrl_F)
- and then Present (Prim_Ctrl_F)
- and then Ekind (Iface_Ctrl_F) /= Ekind (Prim_Ctrl_F)
+ and then Present (Prim_Ctrl_F)
+ and then Ekind (Iface_Ctrl_F) /= Ekind (Prim_Ctrl_F)
then
return False;
@@ -9185,7 +9305,7 @@ package body Sem_Ch6 is
return False;
else
return
- Type_Conformant (Prim, Iface_Prim,
+ Type_Conformant (Prim, Ultimate_Alias (Iface_Prim),
Skip_Controlling_Formals => True);
end if;
@@ -10203,8 +10323,7 @@ package body Sem_Ch6 is
and then In_Private_Part (Current_Scope)
then
Priv_Decls :=
- Private_Declarations
- (Specification (Unit_Declaration_Node (Current_Scope)));
+ Private_Declarations (Package_Specification (Current_Scope));
return In_Package_Body (Current_Scope)
or else
@@ -10832,7 +10951,7 @@ package body Sem_Ch6 is
First_Out_Param : Entity_Id := Empty;
-- Used for setting Is_Only_Out_Parameter
- function Designates_From_With_Type (Typ : Entity_Id) return Boolean;
+ function Designates_From_Limited_With (Typ : Entity_Id) return Boolean;
-- Determine whether an access type designates a type coming from a
-- limited view.
@@ -10841,11 +10960,11 @@ package body Sem_Ch6 is
-- default has the type of the formal, so we must also check explicitly
-- for an access attribute.
- -------------------------------
- -- Designates_From_With_Type --
- -------------------------------
+ ----------------------------------
+ -- Designates_From_Limited_With --
+ ----------------------------------
- function Designates_From_With_Type (Typ : Entity_Id) return Boolean is
+ function Designates_From_Limited_With (Typ : Entity_Id) return Boolean is
Desig : Entity_Id := Typ;
begin
@@ -10858,8 +10977,9 @@ package body Sem_Ch6 is
end if;
return
- Ekind (Desig) = E_Incomplete_Type and then From_With_Type (Desig);
- end Designates_From_With_Type;
+ Ekind (Desig) = E_Incomplete_Type
+ and then From_Limited_With (Desig);
+ end Designates_From_Limited_With;
---------------------------
-- Is_Class_Wide_Default --
@@ -10917,7 +11037,7 @@ package body Sem_Ch6 is
if Is_Tagged_Type (Formal_Type) then
if Ekind (Scope (Current_Scope)) = E_Package
- and then not From_With_Type (Formal_Type)
+ and then not From_Limited_With (Formal_Type)
and then not Is_Generic_Type (Formal_Type)
and then not Is_Class_Wide_Type (Formal_Type)
then
@@ -11100,7 +11220,7 @@ package body Sem_Ch6 is
-- is also class-wide.
if Ekind (Formal_Type) = E_Anonymous_Access_Type
- and then not Designates_From_With_Type (Formal_Type)
+ and then not Designates_From_Limited_With (Formal_Type)
and then Is_Class_Wide_Default (Default)
and then not Is_Class_Wide_Type (Designated_Type (Formal_Type))
then
@@ -11214,841 +11334,6 @@ package body Sem_Ch6 is
end if;
end Process_Formals;
- ------------------
- -- Process_PPCs --
- ------------------
-
- procedure Process_PPCs
- (N : Node_Id;
- Spec_Id : Entity_Id;
- Body_Id : Entity_Id)
- is
- Loc : constant Source_Ptr := Sloc (N);
- Prag : Node_Id;
- Parms : List_Id;
-
- Designator : Entity_Id;
- -- Subprogram designator, set from Spec_Id if present, else Body_Id
-
- Precond : Node_Id := Empty;
- -- Set non-Empty if we prepend precondition to the declarations. This
- -- is used to hook up inherited preconditions (adding the condition
- -- expression with OR ELSE, and adding the message).
-
- Inherited_Precond : Node_Id;
- -- Precondition inherited from parent subprogram
-
- Inherited : constant Subprogram_List :=
- Inherited_Subprograms (Spec_Id);
- -- List of subprograms inherited by this subprogram
-
- Plist : List_Id := No_List;
- -- List of generated postconditions
-
- procedure Append_Enabled_Item (Item : Node_Id; List : in out List_Id);
- -- Append a node to a list. If there is no list, create a new one. When
- -- the item denotes a pragma, it is added to the list only when it is
- -- enabled.
-
- procedure Check_Access_Invariants (E : Entity_Id);
- -- If the subprogram returns an access to a type with invariants, or
- -- has access parameters whose designated type has an invariant, then
- -- under the same visibility conditions as for other invariant checks,
- -- the type invariant must be applied to the returned value.
-
- function Grab_PPC (Pspec : Entity_Id := Empty) return Node_Id;
- -- Prag contains an analyzed precondition or postcondition pragma. This
- -- function copies the pragma, changes it to the corresponding Check
- -- pragma and returns the Check pragma as the result. If Pspec is non-
- -- empty, this is the case of inheriting a PPC, where we must change
- -- references to parameters of the inherited subprogram to point to the
- -- corresponding parameters of the current subprogram.
-
- function Has_Checked_Predicate (Typ : Entity_Id) return Boolean;
- -- Determine whether type Typ has or inherits at least one predicate
- -- aspect or pragma, for which the applicable policy is Checked.
-
- function Has_Null_Body (Proc_Id : Entity_Id) return Boolean;
- -- Determine whether the body of procedure Proc_Id contains a sole null
- -- statement, possibly followed by an optional return.
-
- procedure Insert_After_Last_Declaration (Nod : Node_Id);
- -- Insert node Nod after the last declaration of the context
-
- function Is_Public_Subprogram_For (T : Entity_Id) return Boolean;
- -- T is the entity for a private type for which invariants are defined.
- -- This function returns True if the procedure corresponding to the
- -- value of Designator is a public procedure from the point of view of
- -- this type (i.e. its spec is in the visible part of the package that
- -- contains the declaration of the private type). A True value means
- -- that an invariant check is required (for an IN OUT parameter, or
- -- the returned value of a function.
-
- -------------------------
- -- Append_Enabled_Item --
- -------------------------
-
- procedure Append_Enabled_Item (Item : Node_Id; List : in out List_Id) is
- begin
- -- Do not chain ignored or disabled pragmas
-
- if Nkind (Item) = N_Pragma
- and then (Is_Ignored (Item) or else Is_Disabled (Item))
- then
- null;
-
- -- Add the item
-
- else
- if No (List) then
- List := New_List;
- end if;
-
- Append (Item, List);
- end if;
- end Append_Enabled_Item;
-
- -----------------------------
- -- Check_Access_Invariants --
- -----------------------------
-
- procedure Check_Access_Invariants (E : Entity_Id) is
- Call : Node_Id;
- Obj : Node_Id;
- Typ : Entity_Id;
-
- begin
- if Is_Access_Type (Etype (E))
- and then not Is_Access_Constant (Etype (E))
- then
- Typ := Designated_Type (Etype (E));
-
- if Has_Invariants (Typ)
- and then Present (Invariant_Procedure (Typ))
- and then not Has_Null_Body (Invariant_Procedure (Typ))
- and then Is_Public_Subprogram_For (Typ)
- then
- Obj :=
- Make_Explicit_Dereference (Loc,
- Prefix => New_Occurrence_Of (E, Loc));
- Set_Etype (Obj, Typ);
-
- Call := Make_Invariant_Call (Obj);
-
- Append_Enabled_Item
- (Make_If_Statement (Loc,
- Condition =>
- Make_Op_Ne (Loc,
- Left_Opnd => Make_Null (Loc),
- Right_Opnd => New_Occurrence_Of (E, Loc)),
- Then_Statements => New_List (Call)),
- List => Plist);
- end if;
- end if;
- end Check_Access_Invariants;
-
- --------------
- -- Grab_PPC --
- --------------
-
- function Grab_PPC (Pspec : Entity_Id := Empty) return Node_Id is
- Nam : constant Name_Id := Pragma_Name (Prag);
- Map : Elist_Id;
- CP : Node_Id;
-
- Ename : Name_Id;
- -- Effective name of pragma (maybe Pre/Post rather than Precondition/
- -- Postcodition if the pragma came from a Pre/Post aspect). We need
- -- the name right when we generate the Check pragma, since we want
- -- the right set of check policies to apply.
-
- begin
- -- Prepare map if this is the case where we have to map entities of
- -- arguments in the overridden subprogram to corresponding entities
- -- of the current subprogram.
-
- if No (Pspec) then
- Map := No_Elist;
-
- else
- declare
- PF : Entity_Id;
- CF : Entity_Id;
-
- begin
- Map := New_Elmt_List;
- PF := First_Formal (Pspec);
- CF := First_Formal (Designator);
- while Present (PF) loop
- Append_Elmt (PF, Map);
- Append_Elmt (CF, Map);
- Next_Formal (PF);
- Next_Formal (CF);
- end loop;
- end;
- end if;
-
- -- Now we can copy the tree, doing any required substitutions
-
- CP := New_Copy_Tree (Prag, Map => Map, New_Scope => Current_Scope);
-
- -- Set Analyzed to false, since we want to reanalyze the check
- -- procedure. Note that it is only at the outer level that we
- -- do this fiddling, for the spec cases, the already preanalyzed
- -- parameters are not affected.
-
- Set_Analyzed (CP, False);
-
- -- We also make sure Comes_From_Source is False for the copy
-
- Set_Comes_From_Source (CP, False);
-
- -- For a postcondition pragma within a generic, preserve the pragma
- -- for later expansion. This is also used when an error was detected,
- -- thus setting Expander_Active to False.
-
- if Nam = Name_Postcondition
- and then not Expander_Active
- then
- return CP;
- end if;
-
- -- Get effective name of aspect
-
- if Present (Corresponding_Aspect (Prag)) then
- Ename := Chars (Identifier (Corresponding_Aspect (Prag)));
- else
- Ename := Nam;
- end if;
-
- -- Change copy of pragma into corresponding pragma Check
-
- Prepend_To (Pragma_Argument_Associations (CP),
- Make_Pragma_Argument_Association (Sloc (Prag),
- Expression => Make_Identifier (Loc, Ename)));
- Set_Pragma_Identifier (CP, Make_Identifier (Sloc (Prag), Name_Check));
-
- -- If this is inherited case and the current message starts with
- -- "failed p", we change it to "failed inherited p...".
-
- if Present (Pspec) then
- declare
- Msg : constant Node_Id :=
- Last (Pragma_Argument_Associations (CP));
-
- begin
- if Chars (Msg) = Name_Message then
- String_To_Name_Buffer (Strval (Expression (Msg)));
-
- if Name_Buffer (1 .. 8) = "failed p" then
- Insert_Str_In_Name_Buffer ("inherited ", 8);
- Set_Strval
- (Expression (Last (Pragma_Argument_Associations (CP))),
- String_From_Name_Buffer);
- end if;
- end if;
- end;
- end if;
-
- -- Return the check pragma
-
- return CP;
- end Grab_PPC;
-
- ---------------------------
- -- Has_Checked_Predicate --
- ---------------------------
-
- function Has_Checked_Predicate (Typ : Entity_Id) return Boolean is
- Anc : Entity_Id;
- Pred : Node_Id;
-
- begin
- -- Climb the ancestor type chain staring from the input. This is done
- -- because the input type may lack aspect/pragma predicate and simply
- -- inherit those from its ancestor.
-
- -- Note that predicate pragmas include all three cases of predicate
- -- aspects (Predicate, Dynamic_Predicate, Static_Predicate), so this
- -- routine checks for all three cases.
-
- Anc := Typ;
- while Present (Anc) loop
- Pred := Get_Pragma (Anc, Pragma_Predicate);
-
- if Present (Pred) and then not Is_Ignored (Pred) then
- return True;
- end if;
-
- Anc := Nearest_Ancestor (Anc);
- end loop;
-
- return False;
- end Has_Checked_Predicate;
-
- -------------------
- -- Has_Null_Body --
- -------------------
-
- function Has_Null_Body (Proc_Id : Entity_Id) return Boolean is
- Body_Id : Entity_Id;
- Decl : Node_Id;
- Spec : Node_Id;
- Stmt1 : Node_Id;
- Stmt2 : Node_Id;
-
- begin
- Spec := Parent (Proc_Id);
- Decl := Parent (Spec);
-
- -- Retrieve the entity of the invariant procedure body
-
- if Nkind (Spec) = N_Procedure_Specification
- and then Nkind (Decl) = N_Subprogram_Declaration
- then
- Body_Id := Corresponding_Body (Decl);
-
- -- The body acts as a spec
-
- else
- Body_Id := Proc_Id;
- end if;
-
- -- The body will be generated later
-
- if No (Body_Id) then
- return False;
- end if;
-
- Spec := Parent (Body_Id);
- Decl := Parent (Spec);
-
- pragma Assert
- (Nkind (Spec) = N_Procedure_Specification
- and then Nkind (Decl) = N_Subprogram_Body);
-
- Stmt1 := First (Statements (Handled_Statement_Sequence (Decl)));
-
- -- Look for a null statement followed by an optional return statement
-
- if Nkind (Stmt1) = N_Null_Statement then
- Stmt2 := Next (Stmt1);
-
- if Present (Stmt2) then
- return Nkind (Stmt2) = N_Simple_Return_Statement;
- else
- return True;
- end if;
- end if;
-
- return False;
- end Has_Null_Body;
-
- -----------------------------------
- -- Insert_After_Last_Declaration --
- -----------------------------------
-
- procedure Insert_After_Last_Declaration (Nod : Node_Id) is
- Decls : constant List_Id := Declarations (N);
-
- begin
- if No (Decls) then
- Set_Declarations (N, New_List (Nod));
- else
- Append_To (Decls, Nod);
- end if;
- end Insert_After_Last_Declaration;
-
- ------------------------------
- -- Is_Public_Subprogram_For --
- ------------------------------
-
- -- The type T is a private type, its declaration is therefore in
- -- the list of public declarations of some package. The test for a
- -- public subprogram is that its declaration is in this same list
- -- of declarations for the same package (note that all the public
- -- declarations are in one list, and all the private declarations
- -- in another, so this deals with the public/private distinction).
-
- function Is_Public_Subprogram_For (T : Entity_Id) return Boolean is
- DD : constant Node_Id := Unit_Declaration_Node (Designator);
- -- The subprogram declaration for the subprogram in question
-
- TL : constant List_Id :=
- Visible_Declarations
- (Specification (Unit_Declaration_Node (Scope (T))));
- -- The list of declarations containing the private declaration of
- -- the type. We know it is a private type, so we know its scope is
- -- the package in question, and we know it must be in the visible
- -- declarations of this package.
-
- begin
- -- If the subprogram declaration is not a list member, it must be
- -- an Init_Proc, in which case we want to consider it to be a
- -- public subprogram, since we do get initializations to deal with.
- -- Other internally generated subprograms are not public.
-
- if not Is_List_Member (DD)
- and then Is_Init_Proc (Defining_Entity (DD))
- then
- return True;
-
- -- The declaration may have been generated for an expression function
- -- so check whether that function comes from source.
-
- elsif not Comes_From_Source (DD)
- and then
- (Nkind (Original_Node (DD)) /= N_Expression_Function
- or else not Comes_From_Source (Defining_Entity (DD)))
- then
- return False;
-
- -- Otherwise we test whether the subprogram is declared in the
- -- visible declarations of the package containing the type.
-
- else
- return TL = List_Containing (DD);
- end if;
- end Is_Public_Subprogram_For;
-
- -- Local variables
-
- Formal : Node_Id;
- Formal_Typ : Entity_Id;
- Func_Typ : Entity_Id;
- Post_Proc : Entity_Id;
- Result : Node_Id;
-
- -- Start of processing for Process_PPCs
-
- begin
- -- Capture designator from spec if present, else from body
-
- if Present (Spec_Id) then
- Designator := Spec_Id;
- else
- Designator := Body_Id;
- end if;
-
- -- Do not process a predicate function as its body will contain a
- -- recursive call to itself and blow up the stack.
-
- if Ekind (Designator) = E_Function
- and then Is_Predicate_Function (Designator)
- then
- return;
-
- -- Internally generated subprograms, such as type-specific functions,
- -- don't get assertion checks.
-
- elsif Get_TSS_Name (Designator) /= TSS_Null then
- return;
- end if;
-
- -- Grab preconditions from spec
-
- if Present (Spec_Id) then
-
- -- Loop through PPC pragmas from spec. Note that preconditions from
- -- the body will be analyzed and converted when we scan the body
- -- declarations below.
-
- Prag := Pre_Post_Conditions (Contract (Spec_Id));
- while Present (Prag) loop
- if Pragma_Name (Prag) = Name_Precondition then
-
- -- For Pre (or Precondition pragma), we simply prepend the
- -- pragma to the list of declarations right away so that it
- -- will be executed at the start of the procedure. Note that
- -- this processing reverses the order of the list, which is
- -- what we want since new entries were chained to the head of
- -- the list. There can be more than one precondition when we
- -- use pragma Precondition.
-
- if not Class_Present (Prag) then
- Prepend (Grab_PPC, Declarations (N));
-
- -- For Pre'Class there can only be one pragma, and we save
- -- it in Precond for now. We will add inherited Pre'Class
- -- stuff before inserting this pragma in the declarations.
- else
- Precond := Grab_PPC;
- end if;
- end if;
-
- Prag := Next_Pragma (Prag);
- end loop;
-
- -- Now deal with inherited preconditions
-
- for J in Inherited'Range loop
- Prag := Pre_Post_Conditions (Contract (Inherited (J)));
-
- while Present (Prag) loop
- if Pragma_Name (Prag) = Name_Precondition
- and then Class_Present (Prag)
- then
- Inherited_Precond := Grab_PPC (Inherited (J));
-
- -- No precondition so far, so establish this as the first
-
- if No (Precond) then
- Precond := Inherited_Precond;
-
- -- Here we already have a precondition, add inherited one
-
- else
- -- Add new precondition to old one using OR ELSE
-
- declare
- New_Expr : constant Node_Id :=
- Get_Pragma_Arg
- (Next (First (Pragma_Argument_Associations
- (Inherited_Precond))));
- Old_Expr : constant Node_Id :=
- Get_Pragma_Arg
- (Next (First (Pragma_Argument_Associations
- (Precond))));
-
- begin
- if Paren_Count (Old_Expr) = 0 then
- Set_Paren_Count (Old_Expr, 1);
- end if;
-
- if Paren_Count (New_Expr) = 0 then
- Set_Paren_Count (New_Expr, 1);
- end if;
-
- Rewrite (Old_Expr,
- Make_Or_Else (Sloc (Old_Expr),
- Left_Opnd => Relocate_Node (Old_Expr),
- Right_Opnd => New_Expr));
- end;
-
- -- Add new message in the form:
-
- -- failed precondition from bla
- -- also failed inherited precondition from bla
- -- ...
-
- -- Skip this if exception locations are suppressed
-
- if not Exception_Locations_Suppressed then
- declare
- New_Msg : constant Node_Id :=
- Get_Pragma_Arg
- (Last
- (Pragma_Argument_Associations
- (Inherited_Precond)));
- Old_Msg : constant Node_Id :=
- Get_Pragma_Arg
- (Last
- (Pragma_Argument_Associations
- (Precond)));
- begin
- Start_String (Strval (Old_Msg));
- Store_String_Chars (ASCII.LF & " also ");
- Store_String_Chars (Strval (New_Msg));
- Set_Strval (Old_Msg, End_String);
- end;
- end if;
- end if;
- end if;
-
- Prag := Next_Pragma (Prag);
- end loop;
- end loop;
-
- -- If we have built a precondition for Pre'Class (including any
- -- Pre'Class aspects inherited from parent subprograms), then we
- -- insert this composite precondition at this stage.
-
- if Present (Precond) then
- Prepend (Precond, Declarations (N));
- end if;
- end if;
-
- -- Build postconditions procedure if needed and prepend the following
- -- declaration to the start of the declarations for the subprogram.
-
- -- procedure _postconditions [(_Result : resulttype)] is
- -- begin
- -- pragma Check (Postcondition, condition [,message]);
- -- pragma Check (Postcondition, condition [,message]);
- -- ...
- -- Invariant_Procedure (_Result) ...
- -- Invariant_Procedure (Arg1)
- -- ...
- -- end;
-
- -- First we deal with the postconditions in the body
-
- if Is_Non_Empty_List (Declarations (N)) then
-
- -- Loop through declarations
-
- Prag := First (Declarations (N));
- while Present (Prag) loop
- if Nkind (Prag) = N_Pragma then
-
- -- Capture postcondition pragmas
-
- if Pragma_Name (Prag) = Name_Postcondition then
- Analyze (Prag);
-
- -- If expansion is disabled, as in a generic unit, save
- -- pragma for later expansion.
-
- if not Expander_Active then
- Prepend (Grab_PPC, Declarations (N));
- else
- Append_Enabled_Item (Grab_PPC, Plist);
- end if;
- end if;
-
- Next (Prag);
-
- -- Not a pragma, if comes from source, then end scan
-
- elsif Comes_From_Source (Prag) then
- exit;
-
- -- Skip stuff not coming from source
-
- else
- Next (Prag);
- end if;
- end loop;
- end if;
-
- -- Now deal with any postconditions from the spec
-
- if Present (Spec_Id) then
- Spec_Postconditions : declare
- procedure Process_Contract_Cases (Spec : Node_Id);
- -- This processes the Contract_Test_Cases from Spec, processing
- -- any contract-cases from the list. The caller has checked that
- -- Contract_Test_Cases is non-Empty.
-
- procedure Process_Post_Conditions
- (Spec : Node_Id;
- Class : Boolean);
- -- This processes the Pre_Post_Conditions from Spec, processing
- -- any postconditions from the list. If Class is True, then only
- -- postconditions marked with Class_Present are considered. The
- -- caller has checked that Pre_Post_Conditions is non-Empty.
-
- ----------------------------
- -- Process_Contract_Cases --
- ----------------------------
-
- procedure Process_Contract_Cases (Spec : Node_Id) is
- begin
- -- Loop through Contract_Cases pragmas from spec
-
- Prag := Contract_Test_Cases (Contract (Spec));
- loop
- if Pragma_Name (Prag) = Name_Contract_Cases then
- Expand_Contract_Cases
- (CCs => Prag,
- Subp_Id => Spec_Id,
- Decls => Declarations (N),
- Stmts => Plist);
- end if;
-
- Prag := Next_Pragma (Prag);
- exit when No (Prag);
- end loop;
- end Process_Contract_Cases;
-
- -----------------------------
- -- Process_Post_Conditions --
- -----------------------------
-
- procedure Process_Post_Conditions
- (Spec : Node_Id;
- Class : Boolean)
- is
- Pspec : Node_Id;
-
- begin
- if Class then
- Pspec := Spec;
- else
- Pspec := Empty;
- end if;
-
- -- Loop through PPC pragmas from spec
-
- Prag := Pre_Post_Conditions (Contract (Spec));
- loop
- if Pragma_Name (Prag) = Name_Postcondition
- and then (not Class or else Class_Present (Prag))
- then
- if not Expander_Active then
- Prepend (Grab_PPC (Pspec), Declarations (N));
- else
- Append_Enabled_Item (Grab_PPC (Pspec), Plist);
- end if;
- end if;
-
- Prag := Next_Pragma (Prag);
- exit when No (Prag);
- end loop;
- end Process_Post_Conditions;
-
- -- Start of processing for Spec_Postconditions
-
- begin
- -- Process postconditions expressed as contract-cases
-
- if Present (Contract_Test_Cases (Contract (Spec_Id))) then
- Process_Contract_Cases (Spec_Id);
- end if;
-
- -- Process spec postconditions
-
- if Present (Pre_Post_Conditions (Contract (Spec_Id))) then
- Process_Post_Conditions (Spec_Id, Class => False);
- end if;
-
- -- Process inherited postconditions
-
- for J in Inherited'Range loop
- if Present (Pre_Post_Conditions (Contract (Inherited (J)))) then
- Process_Post_Conditions (Inherited (J), Class => True);
- end if;
- end loop;
- end Spec_Postconditions;
- end if;
-
- -- Add an invariant call to check the result of a function
-
- if Ekind (Designator) /= E_Procedure and then Expander_Active then
- Func_Typ := Etype (Designator);
- Result := Make_Defining_Identifier (Loc, Name_uResult);
-
- Set_Etype (Result, Func_Typ);
-
- -- Add argument for return
-
- Parms := New_List (
- Make_Parameter_Specification (Loc,
- Defining_Identifier => Result,
- Parameter_Type => New_Occurrence_Of (Func_Typ, Loc)));
-
- -- Add invariant call if returning type with invariants and this is a
- -- public function, i.e. a function declared in the visible part of
- -- the package defining the private type.
-
- if Has_Invariants (Func_Typ)
- and then Present (Invariant_Procedure (Func_Typ))
- and then not Has_Null_Body (Invariant_Procedure (Func_Typ))
- and then Is_Public_Subprogram_For (Func_Typ)
- then
- Append_Enabled_Item
- (Make_Invariant_Call (New_Occurrence_Of (Result, Loc)), Plist);
- end if;
-
- -- Same if return value is an access to type with invariants
-
- Check_Access_Invariants (Result);
-
- -- Procedure case
-
- else
- Parms := No_List;
- end if;
-
- -- Add invariant calls and predicate calls for parameters. Note that
- -- this is done for functions as well, since in Ada 2012 they can have
- -- IN OUT args.
-
- if Expander_Active then
- Formal := First_Formal (Designator);
- while Present (Formal) loop
- if Ekind (Formal) /= E_In_Parameter
- or else Is_Access_Type (Etype (Formal))
- then
- Formal_Typ := Etype (Formal);
-
- if Has_Invariants (Formal_Typ)
- and then Present (Invariant_Procedure (Formal_Typ))
- and then not Has_Null_Body (Invariant_Procedure (Formal_Typ))
- and then Is_Public_Subprogram_For (Formal_Typ)
- then
- Append_Enabled_Item
- (Make_Invariant_Call (New_Occurrence_Of (Formal, Loc)),
- Plist);
- end if;
-
- Check_Access_Invariants (Formal);
-
- if Has_Predicates (Formal_Typ)
- and then Present (Predicate_Function (Formal_Typ))
- and then Has_Checked_Predicate (Formal_Typ)
- then
- Append_Enabled_Item
- (Make_Predicate_Check
- (Formal_Typ, New_Occurrence_Of (Formal, Loc)),
- Plist);
- end if;
- end if;
-
- Next_Formal (Formal);
- end loop;
- end if;
-
- -- Build and insert postcondition procedure
-
- if Expander_Active and then Present (Plist) then
- Post_Proc :=
- Make_Defining_Identifier (Loc, Chars => Name_uPostconditions);
-
- -- Insert the corresponding body of a post condition pragma after the
- -- last declaration of the context. This ensures that the body will
- -- not cause any premature freezing as it may mention types:
-
- -- procedure Proc (Obj : Array_Typ) is
- -- procedure _postconditions is
- -- begin
- -- ... Obj ...
- -- end _postconditions;
-
- -- subtype T is Array_Typ (Obj'First (1) .. Obj'Last (1));
- -- begin
-
- -- In the example above, Obj is of type T but the incorrect placement
- -- of _postconditions will cause a crash in gigi due to an out of
- -- order reference. The body of _postconditions must be placed after
- -- the declaration of Temp to preserve correct visibility.
-
- Insert_After_Last_Declaration (
- Make_Subprogram_Body (Loc,
- Specification =>
- Make_Procedure_Specification (Loc,
- Defining_Unit_Name => Post_Proc,
- Parameter_Specifications => Parms),
-
- Declarations => Empty_List,
-
- Handled_Statement_Sequence =>
- Make_Handled_Sequence_Of_Statements (Loc,
- Statements => Plist)));
-
- Set_Ekind (Post_Proc, E_Procedure);
-
- -- If this is a procedure, set the Postcondition_Proc attribute on
- -- the proper defining entity for the subprogram.
-
- if Ekind (Designator) = E_Procedure then
- Set_Postcondition_Proc (Designator, Post_Proc);
- end if;
-
- Set_Has_Postconditions (Designator);
- end if;
- end Process_PPCs;
-
----------------------------
-- Reference_Body_Formals --
----------------------------
diff --git a/gcc/ada/sem_ch6.ads b/gcc/ada/sem_ch6.ads
index d967c017ae0..fc0c365e06b 100644
--- a/gcc/ada/sem_ch6.ads
+++ b/gcc/ada/sem_ch6.ads
@@ -46,9 +46,21 @@ package Sem_Ch6 is
procedure Analyze_Subprogram_Declaration (N : Node_Id);
procedure Analyze_Subprogram_Body (N : Node_Id);
+ procedure Analyze_Subprogram_Body_Contract (Body_Id : Entity_Id);
+ -- Analyze all delayed aspects chained on the contract of subprogram body
+ -- Body_Id as if they appeared at the end of a declarative region. The
+ -- aspects in question are:
+ -- Refined_Depends
+ -- Refined_Global
+
procedure Analyze_Subprogram_Contract (Subp : Entity_Id);
-- Analyze all delayed aspects chained on the contract of subprogram Subp
- -- as if they appeared at the end of a declarative region.
+ -- as if they appeared at the end of a declarative region. The aspects in
+ -- question are:
+ -- Contract_Cases
+ -- Postcondition
+ -- Precondition
+ -- Test_Case
function Analyze_Subprogram_Specification (N : Node_Id) return Entity_Id;
-- Analyze subprogram specification in both subprogram declarations
diff --git a/gcc/ada/sem_ch7.adb b/gcc/ada/sem_ch7.adb
index e06b6b997cf..76875b27afc 100644
--- a/gcc/ada/sem_ch7.adb
+++ b/gcc/ada/sem_ch7.adb
@@ -136,6 +136,11 @@ package body Sem_Ch7 is
-- inherited private operation has been overridden, then it's replaced by
-- the overriding operation.
+ procedure Unit_Requires_Body_Info (P : Entity_Id);
+ -- Outputs info messages showing why package specification P requires a
+ -- body. Caller has checked that the switch requesting this information
+ -- is set, and that the package does indeed require a body.
+
--------------------------
-- Analyze_Package_Body --
--------------------------
@@ -224,15 +229,10 @@ package body Sem_Ch7 is
Body_Id := Defining_Entity (N);
- if Has_Aspects (N) then
- Analyze_Aspect_Specifications (N, Body_Id);
- end if;
+ -- Body is body of package instantiation. Corresponding spec has already
+ -- been set.
if Present (Corresponding_Spec (N)) then
-
- -- Body is body of package instantiation. Corresponding spec has
- -- already been set.
-
Spec_Id := Corresponding_Spec (N);
Pack_Decl := Unit_Declaration_Node (Spec_Id);
@@ -315,6 +315,7 @@ package body Sem_Ch7 is
Set_Ekind (Body_Id, E_Package_Body);
Set_Body_Entity (Spec_Id, Body_Id);
Set_Spec_Entity (Body_Id, Spec_Id);
+ Set_Contract (Body_Id, Make_Contract (Sloc (Body_Id)));
-- Defining name for the package body is not a visible entity: Only the
-- defining name for the declaration is visible.
@@ -338,6 +339,10 @@ package body Sem_Ch7 is
Set_Has_Completion (Spec_Id);
Last_Spec_Entity := Last_Entity (Spec_Id);
+ if Has_Aspects (N) then
+ Analyze_Aspect_Specifications (N, Body_Id);
+ end if;
+
Push_Scope (Spec_Id);
Set_Categorization_From_Pragmas (N);
@@ -770,6 +775,21 @@ package body Sem_Ch7 is
-- True when this package declaration is not a nested declaration
begin
+ if Debug_Flag_C then
+ Write_Str ("==> package spec ");
+ Write_Name (Chars (Id));
+ Write_Str (" from ");
+ Write_Location (Sloc (N));
+ Write_Eol;
+ Indent;
+ end if;
+
+ Generate_Definition (Id);
+ Enter_Name (Id);
+ Set_Ekind (Id, E_Package);
+ Set_Etype (Id, Standard_Void_Type);
+ Set_Contract (Id, Make_Contract (Sloc (Id)));
+
-- Analyze aspect specifications immediately, since we need to recognize
-- things like Pure early enough to diagnose violations during analysis.
@@ -784,24 +804,10 @@ package body Sem_Ch7 is
-- limited with Pkg; -- ERROR
-- package Pkg is ...
- if From_With_Type (Id) then
+ if From_Limited_With (Id) then
return;
end if;
- if Debug_Flag_C then
- Write_Str ("==> package spec ");
- Write_Name (Chars (Id));
- Write_Str (" from ");
- Write_Location (Sloc (N));
- Write_Eol;
- Indent;
- end if;
-
- Generate_Definition (Id);
- Enter_Name (Id);
- Set_Ekind (Id, E_Package);
- Set_Etype (Id, Standard_Void_Type);
-
Push_Scope (Id);
PF := Is_Pure (Enclosing_Lib_Unit_Entity);
@@ -1167,6 +1173,11 @@ package body Sem_Ch7 is
-- then finish off by looping through the nongeneric parents
-- and installing their private declarations.
+ -- If one of the non-generic parents is itself on the scope
+ -- stack, do not install its private declarations: they are
+ -- installed in due time when the private part of that parent
+ -- is analyzed. This is delicate ???
+
else
while Present (Inst_Par)
and then Inst_Par /= Standard_Standard
@@ -1477,7 +1488,19 @@ package body Sem_Ch7 is
Clear_Constants (Id, First_Private_Entity (Id));
end if;
+ -- Issue an error in SPARK mode if a package specification contains
+ -- more than one tagged type or type extension.
+
Check_One_Tagged_Type_Or_Extension_At_Most;
+
+ -- If switch set, output information on why body required
+
+ if List_Body_Required_Info
+ and then In_Extended_Main_Source_Unit (Id)
+ and then Unit_Requires_Body (Id)
+ then
+ Unit_Requires_Body_Info (Id);
+ end if;
end Analyze_Package_Specification;
--------------------------------------
@@ -1529,7 +1552,7 @@ package body Sem_Ch7 is
E := First_Entity (Spec_Id);
while Present (E) loop
if Ekind (E) = E_Anonymous_Access_Type
- and then From_With_Type (E)
+ and then From_Limited_With (E)
then
IR := Make_Itype_Reference (Sloc (P_Body));
Set_Itype (IR, E);
@@ -1649,8 +1672,8 @@ package body Sem_Ch7 is
and then No (Interface_Alias (Node (Op_Elmt_2)))
then
-- The private inherited operation has been
- -- overridden by an explicit subprogram: replace
- -- the former by the latter.
+ -- overridden by an explicit subprogram:
+ -- replace the former by the latter.
New_Op := Node (Op_Elmt_2);
Replace_Elmt (Op_Elmt, New_Op);
@@ -2582,7 +2605,10 @@ package body Sem_Ch7 is
-- Unit_Requires_Body --
------------------------
- function Unit_Requires_Body (P : Entity_Id) return Boolean is
+ function Unit_Requires_Body
+ (P : Entity_Id;
+ Ignore_Abstract_State : Boolean := False) return Boolean
+ is
E : Entity_Id;
begin
@@ -2621,12 +2647,17 @@ package body Sem_Ch7 is
end;
-- A [generic] package that introduces at least one non-null abstract
- -- state requires completion. A null abstract state always appears as
- -- the sole element of the state list.
+ -- state requires completion. However, there is a separate rule that
+ -- requires that such a package have a reason other than this for a
+ -- body being required (if necessary a pragma Elaborate_Body must be
+ -- provided). If Ignore_Abstract_State is True, we don't do this check
+ -- (so we can use Unit_Requires_Body to check for some other reason).
elsif Ekind_In (P, E_Generic_Package, E_Package)
+ and then not Ignore_Abstract_State
and then Present (Abstract_States (P))
- and then not Is_Null_State (Node (First_Elmt (Abstract_States (P))))
+ and then
+ not Is_Null_State (Node (First_Elmt (Abstract_States (P))))
then
return True;
end if;
@@ -2703,4 +2734,135 @@ package body Sem_Ch7 is
return False;
end Unit_Requires_Body;
+ -----------------------------
+ -- Unit_Requires_Body_Info --
+ -----------------------------
+
+ procedure Unit_Requires_Body_Info (P : Entity_Id) is
+ E : Entity_Id;
+
+ begin
+ -- Imported entity never requires body. Right now, only subprograms can
+ -- be imported, but perhaps in the future we will allow import of
+ -- packages.
+
+ if Is_Imported (P) then
+ return;
+
+ -- Body required if library package with pragma Elaborate_Body
+
+ elsif Has_Pragma_Elaborate_Body (P) then
+ Error_Msg_N
+ ("?Y?info: & requires body (Elaborate_Body)", P);
+
+ -- Body required if subprogram
+
+ elsif Is_Subprogram (P) or else Is_Generic_Subprogram (P) then
+ Error_Msg_N ("?Y?info: & requires body (subprogram case)", P);
+
+ -- Body required if generic parent has Elaborate_Body
+
+ elsif Ekind (P) = E_Package
+ and then Nkind (Parent (P)) = N_Package_Specification
+ and then Present (Generic_Parent (Parent (P)))
+ then
+ declare
+ G_P : constant Entity_Id := Generic_Parent (Parent (P));
+ begin
+ if Has_Pragma_Elaborate_Body (G_P) then
+ Error_Msg_N
+ ("?Y?info: & requires body (generic parent Elaborate_Body)",
+ P);
+ end if;
+ end;
+
+ -- A [generic] package that introduces at least one non-null abstract
+ -- state requires completion. However, there is a separate rule that
+ -- requires that such a package have a reason other than this for a
+ -- body being required (if necessary a pragma Elaborate_Body must be
+ -- provided). If Ignore_Abstract_State is True, we don't do this check
+ -- (so we can use Unit_Requires_Body to check for some other reason).
+
+ elsif Ekind_In (P, E_Generic_Package, E_Package)
+ and then Present (Abstract_States (P))
+ and then
+ not Is_Null_State (Node (First_Elmt (Abstract_States (P))))
+ then
+ Error_Msg_N
+ ("?Y?info: & requires body (non-null abstract state aspect)",
+ P);
+ end if;
+
+ -- Otherwise search entity chain for entity requiring completion
+
+ E := First_Entity (P);
+ while Present (E) loop
+
+ -- Always ignore child units. Child units get added to the entity
+ -- list of a parent unit, but are not original entities of the
+ -- parent, and so do not affect whether the parent needs a body.
+
+ if Is_Child_Unit (E) then
+ null;
+
+ -- Ignore formal packages and their renamings
+
+ elsif Ekind (E) = E_Package
+ and then Nkind (Original_Node (Unit_Declaration_Node (E))) =
+ N_Formal_Package_Declaration
+ then
+ null;
+
+ -- Otherwise test to see if entity requires a completion.
+ -- Note that subprogram entities whose declaration does not come
+ -- from source are ignored here on the basis that we assume the
+ -- expander will provide an implicit completion at some point.
+
+ elsif (Is_Overloadable (E)
+ and then Ekind (E) /= E_Enumeration_Literal
+ and then Ekind (E) /= E_Operator
+ and then not Is_Abstract_Subprogram (E)
+ and then not Has_Completion (E)
+ and then Comes_From_Source (Parent (E)))
+
+ or else
+ (Ekind (E) = E_Package
+ and then E /= P
+ and then not Has_Completion (E)
+ and then Unit_Requires_Body (E))
+
+ or else
+ (Ekind (E) = E_Incomplete_Type
+ and then No (Full_View (E))
+ and then not Is_Generic_Type (E))
+
+ or else
+ (Ekind_In (E, E_Task_Type, E_Protected_Type)
+ and then not Has_Completion (E))
+
+ or else
+ (Ekind (E) = E_Generic_Package
+ and then E /= P
+ and then not Has_Completion (E)
+ and then Unit_Requires_Body (E))
+
+ or else
+ (Is_Generic_Subprogram (E)
+ and then not Has_Completion (E))
+
+ then
+ Error_Msg_Node_2 := E;
+ Error_Msg_NE
+ ("?Y?info: & requires body (& requires completion)",
+ E, P);
+
+ -- Entity that does not require completion
+
+ else
+ null;
+ end if;
+
+ Next_Entity (E);
+ end loop;
+ end Unit_Requires_Body_Info;
end Sem_Ch7;
diff --git a/gcc/ada/sem_ch7.ads b/gcc/ada/sem_ch7.ads
index 0445b242949..783fc57efa0 100644
--- a/gcc/ada/sem_ch7.ads
+++ b/gcc/ada/sem_ch7.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 1992-2008, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -52,9 +52,18 @@ package Sem_Ch7 is
-- but is deferred until the compilation of the private part of the
-- child for public child packages.
- function Unit_Requires_Body (P : Entity_Id) return Boolean;
- -- Check if a unit requires a body. A specification requires a body
- -- if it contains declarations that require completion in a body.
+ function Unit_Requires_Body
+ (P : Entity_Id;
+ Ignore_Abstract_State : Boolean := False) return Boolean;
+ -- Check if a unit requires a body. A specification requires a body if it
+ -- contains declarations that require completion in a body. If the flag
+ -- Ignore_Abstract_State is set True, then the test for a non-null abstract
+ -- state (which normally requires a body) is not carried out. This allows
+ -- the use of this routine to tell if there is some other reason that a
+ -- body is required (as is required for analyzing Abstract_State). This
+ -- is not currently used, but may be useful in future if we implement a
+ -- compatibility mode which warns about possible incompatibilities if a
+ -- SPARK 2014 program is compiled with a SPARK-unaware compiler.
procedure May_Need_Implicit_Body (E : Entity_Id);
-- If a package declaration contains tasks or RACWs and does not require
diff --git a/gcc/ada/sem_ch8.adb b/gcc/ada/sem_ch8.adb
index 1e6470bf223..61d97667840 100644
--- a/gcc/ada/sem_ch8.adb
+++ b/gcc/ada/sem_ch8.adb
@@ -883,7 +883,7 @@ package body Sem_Ch8 is
-- there is no copy involved and no performance hit.
if Nkind (Nam) = N_Function_Call
- and then Is_Immutably_Limited_Type (Etype (Nam))
+ and then Is_Limited_View (Etype (Nam))
and then not Is_Constrained (Etype (Nam))
and then Comes_From_Source (N)
then
@@ -1208,11 +1208,22 @@ package body Sem_Ch8 is
-- may have been rewritten in several ways.
elsif Is_Object_Reference (Nam) then
- if Comes_From_Source (N)
- and then Is_Dependent_Component_Of_Mutable_Object (Nam)
- then
- Error_Msg_N
- ("illegal renaming of discriminant-dependent component", Nam);
+ if Comes_From_Source (N) then
+ if Is_Dependent_Component_Of_Mutable_Object (Nam) then
+ Error_Msg_N
+ ("illegal renaming of discriminant-dependent component", Nam);
+ end if;
+
+ -- If the renaming comes from source and the renamed object is a
+ -- dereference, then mark the prefix as needing debug information,
+ -- since it might have been rewritten hence internally generated
+ -- and Debug_Renaming_Declaration will link the renaming to it.
+
+ if Nkind (Nam) = N_Explicit_Dereference
+ and then Is_Entity_Name (Prefix (Nam))
+ then
+ Set_Debug_Info_Needed (Entity (Prefix (Nam)));
+ end if;
end if;
-- A static function call may have been folded into a literal
@@ -4093,7 +4104,7 @@ package body Sem_Ch8 is
T := Entity (Id);
- if T = Any_Type or else From_With_Type (T) then
+ if T = Any_Type or else From_Limited_With (T) then
null;
-- Note that the use_type clause may mention a subtype of the type
@@ -4987,6 +4998,7 @@ package body Sem_Ch8 is
if Comes_From_Source (N)
and then Is_Remote_Access_To_Subprogram_Type (E)
+ and then Ekind (E) = E_Access_Subprogram_Type
and then Expander_Active
and then Get_PCS_Name /= Name_No_DSA
then
@@ -5061,9 +5073,14 @@ package body Sem_Ch8 is
-- Entity is unambiguous, indicate that it is referenced here
-- For a renaming of an object, always generate simple reference,
- -- we don't try to keep track of assignments in this case.
+ -- we don't try to keep track of assignments in this case, except
+ -- in SPARK mode where renamings are traversed for generating
+ -- local effects of subprograms.
- if Is_Object (E) and then Present (Renamed_Object (E)) then
+ if Is_Object (E)
+ and then Present (Renamed_Object (E))
+ and then not SPARK_Mode
+ then
Generate_Reference (E, N);
-- If the renamed entity is a private protected component,
@@ -5157,12 +5174,10 @@ package body Sem_Ch8 is
Selector : constant Node_Id := Selector_Name (N);
Candidate : Entity_Id := Empty;
P_Name : Entity_Id;
- O_Name : Entity_Id;
Id : Entity_Id;
begin
P_Name := Entity (Prefix (N));
- O_Name := P_Name;
-- If the prefix is a renamed package, look for the entity in the
-- original package.
@@ -5206,7 +5221,7 @@ package body Sem_Ch8 is
-- The non-limited view may itself be incomplete, in which case
-- get the full view if available.
- elsif From_With_Type (Id)
+ elsif From_Limited_With (Id)
and then Is_Type (Id)
and then Ekind (Id) = E_Incomplete_Type
and then Present (Non_Limited_View (Id))
@@ -5340,15 +5355,22 @@ package body Sem_Ch8 is
else
-- Within the instantiation of a child unit, the prefix may
-- denote the parent instance, but the selector has the name
- -- of the original child. Find whether we are within the
- -- corresponding instance, and get the proper entity, which
- -- can only be an enclosing scope.
-
- if O_Name /= P_Name
- and then In_Open_Scopes (P_Name)
+ -- of the original child. That is to say, when A.B appears
+ -- within an instantiation of generic child unit B, the scope
+ -- stack includes an instance of A (P_Name) and an instance
+ -- of B under some other name. We scan the scope to find this
+ -- child instance, which is the desired entity.
+ -- Note that the parent may itself be a child instance, if
+ -- the reference is of the form A.B.C, in which case A.B has
+ -- already been rewritten with the proper entity.
+
+ if In_Open_Scopes (P_Name)
and then Is_Generic_Instance (P_Name)
then
declare
+ Gen_Par : constant Entity_Id :=
+ Generic_Parent (Specification
+ (Unit_Declaration_Node (P_Name)));
S : Entity_Id := Current_Scope;
P : Entity_Id;
@@ -5365,9 +5387,12 @@ package body Sem_Ch8 is
P := Generic_Parent (Specification
(Unit_Declaration_Node (S)));
+ -- Check that P is a generic child of the generic
+ -- parent of the prefix.
+
if Present (P)
- and then Chars (Scope (P)) = Chars (O_Name)
and then Chars (P) = Chars (Selector)
+ and then Scope (P) = Gen_Par
then
Id := S;
goto Found;
@@ -5480,6 +5505,7 @@ package body Sem_Ch8 is
<<Found>>
if Comes_From_Source (N)
and then Is_Remote_Access_To_Subprogram_Type (Id)
+ and then Ekind (Id) = E_Access_Subprogram_Type
and then Present (Equivalent_Type (Id))
then
-- If we are not actually generating distribution code (i.e. the
@@ -5493,8 +5519,8 @@ package body Sem_Ch8 is
-- Ada 2005 (AI-50217): Check usage of entities in limited withed units
- if Ekind (P_Name) = E_Package and then From_With_Type (P_Name) then
- if From_With_Type (Id)
+ if Ekind (P_Name) = E_Package and then From_Limited_With (P_Name) then
+ if From_Limited_With (Id)
or else Is_Type (Id)
or else Ekind (Id) = E_Package
then
@@ -6302,7 +6328,7 @@ package body Sem_Ch8 is
-- tagged if the type itself has an untagged incomplete
-- type view in its package.
- if From_With_Type (T)
+ if From_Limited_With (T)
and then not Is_Tagged_Type (Available_View (T))
then
Error_Msg_N
@@ -6493,7 +6519,7 @@ package body Sem_Ch8 is
-- Ada 2005 (AI-251, AI-50217): Handle interfaces visible through
-- limited-with clauses
- if From_With_Type (T_Name)
+ if From_Limited_With (T_Name)
and then Ekind (T_Name) in Incomplete_Kind
and then Present (Non_Limited_View (T_Name))
and then Is_Interface (Non_Limited_View (T_Name))
@@ -7071,7 +7097,7 @@ package body Sem_Ch8 is
or else (Is_Private_Type (T1) and then Has_Discriminants (T1))
or else (Is_Task_Type (T1) and then Has_Discriminants (T1))
or else (Is_Incomplete_Type (T1)
- and then From_With_Type (T1)
+ and then From_Limited_With (T1)
and then Present (Non_Limited_View (T1))
and then Is_Record_Type
(Get_Full_View (Non_Limited_View (T1))));
@@ -7852,7 +7878,7 @@ package body Sem_Ch8 is
-- Ada 2005 (AI-50217): Check restriction
- if From_With_Type (P) then
+ if From_Limited_With (P) then
Error_Msg_N ("limited withed package cannot appear in use clause", N);
end if;
@@ -8175,7 +8201,7 @@ package body Sem_Ch8 is
-- a limited view unless we only have a limited view of its enclosing
-- package.
- elsif From_With_Type (T) and then From_With_Type (Scope (T)) then
+ elsif From_Limited_With (T) and then From_Limited_With (Scope (T)) then
Error_Msg_N
("incomplete type from limited view "
& "cannot appear in use clause", Id);
diff --git a/gcc/ada/sem_ch9.adb b/gcc/ada/sem_ch9.adb
index 52dcb90d184..b7374ba8398 100644
--- a/gcc/ada/sem_ch9.adb
+++ b/gcc/ada/sem_ch9.adb
@@ -1736,16 +1736,16 @@ package body Sem_Ch9 is
-- Protected bodies are currently removed by the expander. Since there
-- are no language-defined aspects that apply to a protected body, it is
- -- not worth changing the whole expansion to accomodate user-defined
- -- aspects. Plus we cannot possibly known the semantics of user-defined
- -- aspects in order to plan ahead.
+ -- not worth changing the whole expansion to accomodate implementation-
+ -- defined aspects. Plus we cannot possibly known the semantics of such
+ -- future implementation defined aspects in order to plan ahead.
if Has_Aspects (N) then
Error_Msg_N
- ("?user-defined aspects on protected bodies are not supported", N);
+ ("aspects on protected bodies are not allowed",
+ First (Aspect_Specifications (N)));
- -- The aspects are removed for now to prevent cascading errors down
- -- stream.
+ -- Remove illegal aspects to prevent cascaded errors later on
Remove_Aspects (N);
end if;
@@ -2726,15 +2726,15 @@ package body Sem_Ch9 is
-- Task bodies are transformed into a subprogram spec and body pair by
-- the expander. Since there are no language-defined aspects that apply
-- to a task body, it is not worth changing the whole expansion to
- -- accomodate user-defined aspects. Plus we cannot possibly known the
- -- semantics of user-defined aspects in order to plan ahead.
+ -- accomodate implementation-defined aspects. Plus we cannot possibly
+ -- know semantics of such aspects in order to plan ahead.
if Has_Aspects (N) then
Error_Msg_N
- ("?user-defined aspects on task bodies are not supported", N);
+ ("aspects on task bodies are not allowed",
+ First (Aspect_Specifications (N)));
- -- The aspects are removed for now to prevent cascading errors down
- -- stream.
+ -- Remove illegal aspects to prevent cascaded errors later on
Remove_Aspects (N);
end if;
@@ -2763,7 +2763,6 @@ package body Sem_Ch9 is
then
if Nkind (Parent (Spec_Id)) = N_Task_Type_Declaration then
Error_Msg_NE ("duplicate body for task type&", N, Spec_Id);
-
else
Error_Msg_NE ("duplicate body for task&", N, Spec_Id);
end if;
diff --git a/gcc/ada/sem_dim.adb b/gcc/ada/sem_dim.adb
index 79c1e15037a..233e30168a2 100644
--- a/gcc/ada/sem_dim.adb
+++ b/gcc/ada/sem_dim.adb
@@ -2277,6 +2277,12 @@ package body Sem_Dim is
Result := No_Rational;
end if;
+ -- Provide minimal semantic information on dimension expressions,
+ -- even though they have no run-time existence. This is for use by
+ -- ASIS tools, in particular pretty-printing.
+
+ Set_Entity (N, Standard_Op_Minus);
+ Set_Etype (N, Standard_Integer);
return Result;
end Process_Minus;
@@ -2302,6 +2308,12 @@ package body Sem_Dim is
Result := Left_Rat / Right_Rat;
end if;
+ -- Provide minimal semantic information on dimension expressions,
+ -- even though they have no run-time existence. This is for use by
+ -- ASIS tools, in particular pretty-printing.
+
+ Set_Entity (N, Standard_Op_Divide);
+ Set_Etype (N, Standard_Integer);
return Result;
end Process_Divide;
diff --git a/gcc/ada/sem_disp.adb b/gcc/ada/sem_disp.adb
index 9f80a7dcea1..7b815812a32 100644
--- a/gcc/ada/sem_disp.adb
+++ b/gcc/ada/sem_disp.adb
@@ -331,7 +331,7 @@ package body Sem_Disp is
-- Ada 2005 (AI-50217)
- elsif From_With_Type (Designated_Type (T))
+ elsif From_Limited_With (Designated_Type (T))
and then Present (Non_Limited_View (Designated_Type (T)))
and then Scope (Designated_Type (T)) = Scope (Subp)
then
diff --git a/gcc/ada/sem_eval.adb b/gcc/ada/sem_eval.adb
index 94ce100a7c5..99b6e775218 100644
--- a/gcc/ada/sem_eval.adb
+++ b/gcc/ada/sem_eval.adb
@@ -1353,16 +1353,7 @@ package body Sem_Eval is
if Ekind (E) = E_Enumeration_Literal then
return True;
- -- In SPARK mode, the value of deferred constants should be
- -- ignored outside the scope of their full view. This allows
- -- parameterized formal verification, in which a deferred constant
- -- value if not known from client units.
-
- elsif Ekind (E) = E_Constant
- and then not (SPARK_Mode
- and then Present (Full_View (E))
- and then not In_Open_Scopes (Scope (E)))
- then
+ elsif Ekind (E) = E_Constant then
V := Constant_Value (E);
return Present (V) and then Compile_Time_Known_Value (V);
end if;
@@ -5578,7 +5569,7 @@ package body Sem_Eval is
then
Error_Msg_N ("\aggregate (#) is never static", N);
- elsif not Is_Static_Expression (CV) then
+ elsif No (CV) or else not Is_Static_Expression (CV) then
Error_Msg_NE
("\& is not a static constant (RM 4.9(5))", N, E);
end if;
diff --git a/gcc/ada/sem_prag.adb b/gcc/ada/sem_prag.adb
index 8d716aa8454..19d88778715 100644
--- a/gcc/ada/sem_prag.adb
+++ b/gcc/ada/sem_prag.adb
@@ -75,7 +75,6 @@ with Stand; use Stand;
with Sinfo; use Sinfo;
with Sinfo.CN; use Sinfo.CN;
with Sinput; use Sinput;
-with Snames; use Snames;
with Stringt; use Stringt;
with Stylesw; use Stylesw;
with Table;
@@ -169,9 +168,9 @@ package body Sem_Prag is
-------------------------------------
procedure Add_Item (Item : Entity_Id; To_List : in out Elist_Id);
- -- Subsidiary routine to the analysis of pragmas Depends and Global. Append
- -- an input or output item to a list. If the list is empty, a new one is
- -- created.
+ -- Subsidiary routine to the analysis of pragmas Depends, Global and
+ -- Refined_State. Append an entity to a list. If the list is empty, create
+ -- a new list.
function Adjust_External_Name_Case (N : Node_Id) return Node_Id;
-- This routine is used for possible casing adjustment of an explicit
@@ -205,27 +204,49 @@ package body Sem_Prag is
-- _Post, _Invariant, or _Type_Invariant, which are special names used
-- in identifiers to represent these attribute references.
+ procedure Collect_Global_Items
+ (Prag : Node_Id;
+ In_Items : in out Elist_Id;
+ In_Out_Items : in out Elist_Id;
+ Out_Items : in out Elist_Id;
+ Has_In_State : out Boolean;
+ Has_In_Out_State : out Boolean;
+ Has_Out_State : out Boolean;
+ Has_Null_State : out Boolean);
+ -- Subsidiary to the analysis of pragma Refined_Depends/Refined_Global.
+ -- Prag denotes pragma [Refined_]Global. Gather all input, in out and
+ -- output items of Prag in lists In_Items, In_Out_Items and Out_Items.
+ -- Flags Has_In_State, Has_In_Out_State and Has_Out_State are set when
+ -- there is at least one abstract state with visible refinement available
+ -- in the corresponding mode. Flag Has_Null_State is set when at least
+ -- state has a null refinement.
+
procedure Collect_Subprogram_Inputs_Outputs
(Subp_Id : Entity_Id;
Subp_Inputs : in out Elist_Id;
Subp_Outputs : in out Elist_Id;
Global_Seen : out Boolean);
- -- Subsidiary to the analysis of pragma Global and pragma Depends. Gather
- -- all inputs and outputs of subprogram Subp_Id in lists Subp_Inputs and
- -- Subp_Outputs. If the case where the subprogram has no inputs and/or
- -- outputs, the corresponding returned list is No_Elist. Flag Global_Seen
- -- is set when the related subprogram has aspect/pragma Global.
-
- function Find_Related_Subprogram
- (Prag : Node_Id;
- Check_Duplicates : Boolean := False) return Node_Id;
- -- Find the declaration of the related subprogram subject to pragma Prag.
- -- If flag Check_Duplicates is set, the routine emits errors concerning
- -- duplicate pragmas. If a related subprogram is found, then either the
- -- corresponding N_Subprogram_Declaration node is returned, or, if the
- -- pragma applies to a subprogram body, then the N_Subprogram_Body node
- -- is returned. Note that in the latter case, no check is made to ensure
- -- that there is no separate declaration of the subprogram.
+ -- Subsidiary to the analysis of pragma Depends, Global, Refined_Depends
+ -- and Refined_Global. Gather all inputs and outputs of subprogram Subp_Id
+ -- in lists Subp_Inputs and Subp_Outputs. If the case where the subprogram
+ -- has no inputs and/oroutputs, the returned list is No_Elist. Global_Seen
+ -- is set when the related subprogram has pragma [Refined_]Global.
+
+ function Find_Related_Subprogram_Or_Body
+ (Prag : Node_Id;
+ Do_Checks : Boolean := False) return Node_Id;
+ -- Subsidiary to the analysis of pragmas Contract_Cases, Depends, Global,
+ -- Refined_Depends, Refined_Global and Refined_Post. Find the declaration
+ -- of the related subprogram [body or stub] subject to pragma Prag. If flag
+ -- Do_Checks is set, the routine reports duplicate pragmas and detects
+ -- improper use of refinement pragmas in stand alone expression functions.
+ -- The returned value depends on the related pragma as follows:
+ -- 1) Pragmas Contract_Cases, Depends and Global yield the corresponding
+ -- N_Subprogram_Declaration node or if the pragma applies to a stand
+ -- alone body, the N_Subprogram_Body node or Empty if illegal.
+ -- 2) Pragmas Refined_Depends, Refined_Global and Refined_Post yield
+ -- N_Subprogram_Body or N_Subprogram_Body_Stub nodes or Empty if
+ -- illegal.
function Get_Base_Subprogram (Def_Id : Entity_Id) return Entity_Id;
-- If Def_Id refers to a renamed subprogram, then the base subprogram (the
@@ -237,45 +258,49 @@ package body Sem_Prag is
-- Get_SPARK_Mode_Id. Convert a name into a corresponding value of type
-- SPARK_Mode_Id.
- function Original_Name (N : Node_Id) return Name_Id;
- -- N is a pragma node or aspect specification node. This function returns
- -- the name of the pragma or aspect in original source form, taking into
- -- account possible rewrites, and also cases where a pragma comes from an
- -- aspect (in such cases, the name can be different from the pragma name,
- -- e.g. a Pre aspect generates a Precondition pragma). This also deals with
- -- the presence of 'Class, which results in one of the special names
- -- Name_uPre, Name_uPost, Name_uInvariant, or Name_uType_Invariant being
- -- returned to represent the corresponding aspects with x'Class names.
+ function Is_Part_Of
+ (State : Entity_Id;
+ Ancestor : Entity_Id) return Boolean;
+ -- Subsidiary to the processing of pragma Refined_Depends and pragma
+ -- Refined_Global. Determine whether abstract state State is part of an
+ -- ancestor abstract state Ancestor. For this relationship to hold, State
+ -- must have option Part_Of in its Abstract_State definition.
+
+ function Is_Unconstrained_Or_Tagged_Item (Item : Entity_Id) return Boolean;
+ -- Subsidiary to Collect_Subprogram_Inputs_Outputs and the analysis of
+ -- pragma Depends. Determine whether the type of dependency item Item is
+ -- tagged, unconstrained array, unconstrained record or a record with at
+ -- least one unconstrained component.
procedure Preanalyze_CTC_Args (N, Arg_Req, Arg_Ens : Node_Id);
-- Preanalyze the boolean expressions in the Requires and Ensures arguments
-- of a Test_Case pragma if present (possibly Empty). We treat these as
-- spec expressions (i.e. similar to a default expression).
+ procedure Record_Possible_Body_Reference
+ (Item : Node_Id;
+ Item_Id : Entity_Id);
+ -- Given an entity reference (Item) and the corresponding Entity (Item_Id),
+ -- determines if we have a body reference to an abstract state, which may
+ -- be illegal if the state is refined within the body.
+
procedure Rewrite_Assertion_Kind (N : Node_Id);
-- If N is Pre'Class, Post'Class, Invariant'Class, or Type_Invariant'Class,
-- then it is rewritten as an identifier with the corresponding special
-- name _Pre, _Post, _Invariant, or _Type_Invariant. Used by pragmas
-- Check, Check_Policy.
+ procedure Set_Unit_Name (N : Node_Id; With_Item : Node_Id);
+ -- Place semantic information on the argument of an Elaborate/Elaborate_All
+ -- pragma. Entity name for unit and its parents is taken from item in
+ -- previous with_clause that mentions the unit.
+
procedure rv;
-- This is a dummy function called by the processing for pragma Reviewable.
-- It is there for assisting front end debugging. By placing a Reviewable
-- pragma in the source program, a breakpoint on rv catches this place in
-- the source, allowing convenient stepping to the point of interest.
- function Requires_Profile_Installation
- (Prag : Node_Id;
- Subp : Node_Id) return Boolean;
- -- Subsidiary routine to the analysis of pragma Depends and pragma Global.
- -- Determine whether the profile of subprogram Subp must be installed into
- -- visibility to access its formals from pragma Prag.
-
- procedure Set_Unit_Name (N : Node_Id; With_Item : Node_Id);
- -- Place semantic information on the argument of an Elaborate/Elaborate_All
- -- pragma. Entity name for unit and its parents is taken from item in
- -- previous with_clause that mentions the unit.
-
--------------
-- Add_Item --
--------------
@@ -286,7 +311,7 @@ package body Sem_Prag is
To_List := New_Elmt_List;
end if;
- Append_Unique_Elmt (Item, To_List);
+ Append_Elmt (Item, To_List);
end Add_Item;
-------------------------------
@@ -402,20 +427,22 @@ package body Sem_Prag is
-- Local variables
- Arg1 : constant Node_Id := First (Pragma_Argument_Associations (N));
All_Cases : Node_Id;
CCase : Node_Id;
Subp_Decl : Node_Id;
Subp_Id : Entity_Id;
+ Restore_Scope : Boolean := False;
+ -- Gets set True if we do a Push_Scope needing a Pop_Scope on exit
+
-- Start of processing for Analyze_Contract_Cases_In_Decl_Part
begin
Set_Analyzed (N);
- Subp_Decl := Find_Related_Subprogram (N);
- Subp_Id := Defining_Unit_Name (Specification (Subp_Decl));
- All_Cases := Expression (Arg1);
+ Subp_Decl := Find_Related_Subprogram_Or_Body (N);
+ Subp_Id := Defining_Entity (Subp_Decl);
+ All_Cases := Get_Pragma_Arg (First (Pragma_Argument_Associations (N)));
-- Multiple contract cases appear in aggregate form
@@ -431,7 +458,8 @@ package body Sem_Prag is
-- pertaining to subprogram declarations. Skip the installation
-- for subprogram bodies because the formals are already visible.
- if Requires_Profile_Installation (N, Subp_Decl) then
+ if not In_Open_Scopes (Subp_Id) then
+ Restore_Scope := True;
Push_Scope (Subp_Id);
Install_Formals (Subp_Id);
end if;
@@ -442,7 +470,7 @@ package body Sem_Prag is
Next (CCase);
end loop;
- if Requires_Profile_Installation (N, Subp_Decl) then
+ if Restore_Scope then
End_Scope;
end if;
end if;
@@ -457,29 +485,33 @@ package body Sem_Prag is
----------------------------------
procedure Analyze_Depends_In_Decl_Part (N : Node_Id) is
- Arg1 : constant Node_Id := First (Pragma_Argument_Associations (N));
- Loc : constant Source_Ptr := Sloc (N);
+ Loc : constant Source_Ptr := Sloc (N);
All_Inputs_Seen : Elist_Id := No_Elist;
-- A list containing the entities of all the inputs processed so far.
- -- This Elist is populated with unique entities because the same input
+ -- The list is populated with unique entities because the same input
-- may appear in multiple input lists.
+ All_Outputs_Seen : Elist_Id := No_Elist;
+ -- A list containing the entities of all the outputs processed so far.
+ -- The list is populated with unique entities because output items are
+ -- unique in a dependence relation.
+
Global_Seen : Boolean := False;
-- A flag set when pragma Global has been processed
- Outputs_Seen : Elist_Id := No_Elist;
- -- A list containing the entities of all the outputs processed so far.
- -- The elements of this list may come from different output lists.
-
Null_Output_Seen : Boolean := False;
-- A flag used to track the legality of a null output
Result_Seen : Boolean := False;
-- A flag set when Subp_Id'Result is processed
+ Spec_Id : Entity_Id;
+ -- The entity of the subprogram subject to pragma [Refined_]Depends
+
Subp_Id : Entity_Id;
- -- The entity of the subprogram subject to pragma Depends
+ -- The entity of the subprogram [body or stub] subject to pragma
+ -- [Refined_]Depends.
Subp_Inputs : Elist_Id := No_Elist;
Subp_Outputs : Elist_Id := No_Elist;
@@ -500,12 +532,11 @@ package body Sem_Prag is
Item_Id : Entity_Id;
Is_Input : Boolean;
Self_Ref : Boolean);
- -- Ensure that an item has a proper "in", "in out" or "out" mode
- -- depending on its function. If this is not the case, emit an error.
- -- Item and Item_Id denote the attributes of an item. Flag Is_Input
- -- should be set when item comes from an input list. Flag Self_Ref
- -- should be set when the item is an output and the dependency clause
- -- has operator "+".
+ -- Ensure that an item has a proper IN, IN OUT, or OUT mode depending
+ -- on its function. If this is not the case, emit an error. Item and
+ -- Item_Id denote the attributes of an item. Flag Is_Input should be set
+ -- when item comes from an input list. Flag Self_Ref should be set when
+ -- the item is an output and the dependency clause has operator "+".
procedure Check_Usage
(Subp_Items : Elist_Id;
@@ -515,10 +546,9 @@ package body Sem_Prag is
-- error if this is not the case.
procedure Normalize_Clause (Clause : Node_Id);
- -- Remove a self-dependency "+" from the input list of a clause.
- -- Depending on the contents of the relation, either split the the
- -- clause into multiple smaller clauses or perform the normalization in
- -- place.
+ -- Remove a self-dependency "+" from the input list of a clause. Split
+ -- a clause with multiple outputs into multiple clauses with a single
+ -- output.
-------------------------------
-- Analyze_Dependency_Clause --
@@ -532,12 +562,13 @@ package body Sem_Prag is
-- Verify the legality of a single input list
procedure Analyze_Input_Output
- (Item : Node_Id;
- Is_Input : Boolean;
- Self_Ref : Boolean;
- Top_Level : Boolean;
- Seen : in out Elist_Id;
- Null_Seen : in out Boolean);
+ (Item : Node_Id;
+ Is_Input : Boolean;
+ Self_Ref : Boolean;
+ Top_Level : Boolean;
+ Seen : in out Elist_Id;
+ Null_Seen : in out Boolean;
+ Non_Null_Seen : in out Boolean);
-- Verify the legality of a single input or output item. Flag
-- Is_Input should be set whenever Item is an input, False when it
-- denotes an output. Flag Self_Ref should be set when the item is an
@@ -545,7 +576,8 @@ package body Sem_Prag is
-- be set whenever Item appears immediately within an input or output
-- list. Seen is a collection of all abstract states, variables and
-- formals processed so far. Flag Null_Seen denotes whether a null
- -- input or output has been encountered.
+ -- input or output has been encountered. Flag Non_Null_Seen denotes
+ -- whether a non-null input or output has been encountered.
------------------------
-- Analyze_Input_List --
@@ -556,8 +588,9 @@ package body Sem_Prag is
-- A list containing the entities of all inputs that appear in the
-- current input list.
- Null_Input_Seen : Boolean := False;
- -- A flag used to track the legality of a null input
+ Non_Null_Input_Seen : Boolean := False;
+ Null_Input_Seen : Boolean := False;
+ -- Flags used to check the legality of an input list
Input : Node_Id;
@@ -573,12 +606,13 @@ package body Sem_Prag is
Input := First (Expressions (Inputs));
while Present (Input) loop
Analyze_Input_Output
- (Item => Input,
- Is_Input => True,
- Self_Ref => False,
- Top_Level => False,
- Seen => Inputs_Seen,
- Null_Seen => Null_Input_Seen);
+ (Item => Input,
+ Is_Input => True,
+ Self_Ref => False,
+ Top_Level => False,
+ Seen => Inputs_Seen,
+ Null_Seen => Null_Input_Seen,
+ Non_Null_Seen => Non_Null_Input_Seen);
Next (Input);
end loop;
@@ -591,12 +625,13 @@ package body Sem_Prag is
else
Analyze_Input_Output
- (Item => Inputs,
- Is_Input => True,
- Self_Ref => False,
- Top_Level => False,
- Seen => Inputs_Seen,
- Null_Seen => Null_Input_Seen);
+ (Item => Inputs,
+ Is_Input => True,
+ Self_Ref => False,
+ Top_Level => False,
+ Seen => Inputs_Seen,
+ Null_Seen => Null_Input_Seen,
+ Non_Null_Seen => Non_Null_Input_Seen);
end if;
-- Detect an illegal dependency clause of the form
@@ -615,12 +650,13 @@ package body Sem_Prag is
--------------------------
procedure Analyze_Input_Output
- (Item : Node_Id;
- Is_Input : Boolean;
- Self_Ref : Boolean;
- Top_Level : Boolean;
- Seen : in out Elist_Id;
- Null_Seen : in out Boolean)
+ (Item : Node_Id;
+ Is_Input : Boolean;
+ Self_Ref : Boolean;
+ Top_Level : Boolean;
+ Seen : in out Elist_Id;
+ Null_Seen : in out Boolean;
+ Non_Null_Seen : in out Boolean)
is
Is_Output : constant Boolean := not Is_Input;
Grouped : Node_Id;
@@ -643,12 +679,13 @@ package body Sem_Prag is
Grouped := First (Expressions (Item));
while Present (Grouped) loop
Analyze_Input_Output
- (Item => Grouped,
- Is_Input => Is_Input,
- Self_Ref => Self_Ref,
- Top_Level => False,
- Seen => Seen,
- Null_Seen => Null_Seen);
+ (Item => Grouped,
+ Is_Input => Is_Input,
+ Self_Ref => Self_Ref,
+ Top_Level => False,
+ Seen => Seen,
+ Null_Seen => Null_Seen,
+ Non_Null_Seen => Non_Null_Seen);
Next (Grouped);
end loop;
@@ -659,20 +696,20 @@ package body Sem_Prag is
-- Process Function'Result in the context of a dependency clause
- elsif Nkind (Item) = N_Attribute_Reference
- and then Attribute_Name (Item) = Name_Result
- then
+ elsif Is_Attribute_Result (Item) then
+ Non_Null_Seen := True;
+
-- It is sufficent to analyze the prefix of 'Result in order to
-- establish legality of the attribute.
Analyze (Prefix (Item));
-- The prefix of 'Result must denote the function for which
- -- aspect/pragma Depends applies.
+ -- pragma Depends applies.
if not Is_Entity_Name (Prefix (Item))
- or else Ekind (Subp_Id) /= E_Function
- or else Entity (Prefix (Item)) /= Subp_Id
+ or else Ekind (Spec_Id) /= E_Function
+ or else Entity (Prefix (Item)) /= Spec_Id
then
Error_Msg_Name_1 := Name_Result;
Error_Msg_N
@@ -685,6 +722,10 @@ package body Sem_Prag is
elsif Is_Input then
Error_Msg_N ("function result cannot act as input", Item);
+ elsif Null_Seen then
+ Error_Msg_N
+ ("cannot mix null and non-null dependency items", Item);
+
else
Result_Seen := True;
end if;
@@ -697,19 +738,39 @@ package body Sem_Prag is
if Null_Seen then
Error_Msg_N
("multiple null dependency relations not allowed", Item);
+
+ elsif Non_Null_Seen then
+ Error_Msg_N
+ ("cannot mix null and non-null dependency items", Item);
+
else
Null_Seen := True;
- if Is_Output and then not Is_Last then
- Error_Msg_N
- ("null output list must be the last clause in a "
- & "dependency relation", Item);
+ if Is_Output then
+ if not Is_Last then
+ Error_Msg_N
+ ("null output list must be the last clause in a "
+ & "dependency relation", Item);
+
+ -- Catch a useless dependence of the form:
+ -- null =>+ ...
+
+ elsif Self_Ref then
+ Error_Msg_N
+ ("useless dependence, null depends on itself", Item);
+ end if;
end if;
end if;
-- Default case
else
+ Non_Null_Seen := True;
+
+ if Null_Seen then
+ Error_Msg_N ("cannot mix null and non-null items", Item);
+ end if;
+
Analyze (Item);
-- Find the entity of the item. If this is a renaming, climb
@@ -718,6 +779,8 @@ package body Sem_Prag is
Item_Id := Entity_Of (Item);
+ Record_Possible_Body_Reference (Item, Item_Id);
+
if Present (Item_Id) then
if Ekind_In (Item_Id, E_Abstract_State,
E_In_Parameter,
@@ -740,20 +803,56 @@ package body Sem_Prag is
Add_Item (Item_Id, Seen);
end if;
- -- Detect an illegal use of an input related to a null
- -- output. Such input items cannot appear in other input
- -- lists.
+ -- Detect illegal use of an input related to a null
+ -- output. Such input items cannot appear in other
+ -- input lists.
- if Null_Output_Seen
+ if Is_Input
+ and then Null_Output_Seen
and then Contains (All_Inputs_Seen, Item_Id)
then
Error_Msg_N
("input of a null output list appears in multiple "
& "input lists", Item);
- else
+ end if;
+
+ -- Add an input or a self-referential output to the list
+ -- of all processed inputs.
+
+ if Is_Input or else Self_Ref then
Add_Item (Item_Id, All_Inputs_Seen);
end if;
+ if Ekind (Item_Id) = E_Abstract_State then
+
+ -- The state acts as a constituent of some other
+ -- state. Ensure that the other state is a proper
+ -- ancestor of the item.
+
+ if Present (Refined_State (Item_Id)) then
+ if not Is_Part_Of
+ (Item_Id, Refined_State (Item_Id))
+ then
+ Error_Msg_Name_1 :=
+ Chars (Refined_State (Item_Id));
+ Error_Msg_NE
+ ("state & is not a valid constituent of "
+ & "ancestor state %", Item, Item_Id);
+ return;
+ end if;
+
+ -- An abstract state with visible refinement cannot
+ -- appear in pragma [Refined_]Global as its place must
+ -- be taken by some of its constituents.
+
+ elsif Has_Visible_Refinement (Item_Id) then
+ Error_Msg_NE
+ ("cannot mention state & in global refinement, "
+ & "use its constituents instead", Item, Item_Id);
+ return;
+ end if;
+ end if;
+
-- When the item renames an entire object, replace the
-- item with a reference to the object.
@@ -787,6 +886,9 @@ package body Sem_Prag is
Output : Node_Id;
Self_Ref : Boolean;
+ Non_Null_Output_Seen : Boolean := False;
+ -- Flag used to check the legality of an output list
+
-- Start of processing for Analyze_Dependency_Clause
begin
@@ -806,12 +908,13 @@ package body Sem_Prag is
Output := First (Choices (Clause));
while Present (Output) loop
Analyze_Input_Output
- (Item => Output,
- Is_Input => False,
- Self_Ref => Self_Ref,
- Top_Level => True,
- Seen => Outputs_Seen,
- Null_Seen => Null_Output_Seen);
+ (Item => Output,
+ Is_Input => False,
+ Self_Ref => Self_Ref,
+ Top_Level => True,
+ Seen => All_Outputs_Seen,
+ Null_Seen => Null_Output_Seen,
+ Non_Null_Seen => Non_Null_Output_Seen);
Next (Output);
end loop;
@@ -827,10 +930,10 @@ package body Sem_Prag is
procedure Check_Function_Return is
begin
- if Ekind (Subp_Id) = E_Function and then not Result_Seen then
+ if Ekind (Spec_Id) = E_Function and then not Result_Seen then
Error_Msg_NE
("result of & must appear in exactly one output list",
- N, Subp_Id);
+ N, Spec_Id);
end if;
end Check_Function_Return;
@@ -848,20 +951,32 @@ package body Sem_Prag is
-- Input
if Is_Input then
- if Ekind (Item_Id) = E_Out_Parameter
- or else (Global_Seen
- and then not Appears_In (Subp_Inputs, Item_Id))
+
+ -- IN and IN OUT parameters already have the proper mode to act
+ -- as input. OUT parameters are valid inputs only when their type
+ -- is unconstrained or tagged as their discriminants, array bouns
+ -- or tags can be read. In general, states and variables are
+ -- considered to have mode IN OUT unless they are classified by
+ -- pragma [Refined_]Global. In that case, the item must appear in
+ -- an input global list.
+
+ if (Ekind (Item_Id) = E_Out_Parameter
+ and then not Is_Unconstrained_Or_Tagged_Item (Item_Id))
+ or else
+ (Global_Seen and then not Appears_In (Subp_Inputs, Item_Id))
then
Error_Msg_NE
- ("item & must have mode in or in out", Item, Item_Id);
+ ("item & must have mode IN or `IN OUT`", Item, Item_Id);
end if;
-- Self-referential output
elsif Self_Ref then
- -- A self-referential state or variable must appear in both input
- -- and output lists of a subprogram.
+ -- In general, states and variables are considered to have mode
+ -- IN OUT unless they are explicitly moded by pragma [Refined_]
+ -- Global. If this is the case, then the item must appear in both
+ -- an input and output global list.
if Ekind_In (Item_Id, E_Abstract_State, E_Variable) then
if Global_Seen
@@ -870,23 +985,41 @@ package body Sem_Prag is
and then
Appears_In (Subp_Outputs, Item_Id))
then
- Error_Msg_NE ("item & must have mode in out", Item, Item_Id);
+ Error_Msg_NE
+ ("item & must have mode `IN OUT`", Item, Item_Id);
end if;
- -- Self-referential parameter
+ -- A self-referential OUT parameter of an unconstrained or tagged
+ -- type acts as an input because the discriminants, array bounds
+ -- or the tag may be read. Note that the presence of [Refined_]
+ -- Global is not significant here because the item is a parameter.
+
+ elsif Ekind (Item_Id) = E_Out_Parameter
+ and then Is_Unconstrained_Or_Tagged_Item (Item_Id)
+ then
+ null;
+
+ -- The remaining cases are IN, IN OUT, and OUT parameters. To
+ -- qualify as self-referential item, the parameter must be of
+ -- mode IN OUT.
elsif Ekind (Item_Id) /= E_In_Out_Parameter then
- Error_Msg_NE ("item & must have mode in out", Item, Item_Id);
+ Error_Msg_NE ("item & must have mode `IN OUT`", Item, Item_Id);
end if;
- -- Regular output
+ -- Output
+
+ -- IN OUT and OUT parameters already have the proper mode to act as
+ -- output. In general, states and variables are considered to have
+ -- mode IN OUT unless they are moded by pragma [Refined_]Global. In
+ -- that case, the item must appear in an output global list.
elsif Ekind (Item_Id) = E_In_Parameter
or else
(Global_Seen and then not Appears_In (Subp_Outputs, Item_Id))
then
Error_Msg_NE
- ("item & must have mode out or in out", Item, Item_Id);
+ ("item & must have mode OUT or `IN OUT`", Item, Item_Id);
end if;
end Check_Mode;
@@ -984,6 +1117,11 @@ package body Sem_Prag is
-- Flag Multiple should be set when Output comes from a list with
-- multiple items.
+ procedure Split_Multiple_Outputs;
+ -- If Clause contains more than one output, split the clause into
+ -- multiple clauses with a single output. All new clauses are added
+ -- after Clause.
+
-----------------------------
-- Create_Or_Modify_Clause --
-----------------------------
@@ -1099,25 +1237,23 @@ package body Sem_Prag is
-- Local variables
- Loc : constant Source_Ptr := Sloc (Output);
- Clause : Node_Id;
+ Loc : constant Source_Ptr := Sloc (Clause);
+ New_Clause : Node_Id;
-- Start of processing for Create_Or_Modify_Clause
begin
- -- A function result cannot depend on itself because it cannot
- -- appear in the input list of a relation.
+ -- A null output depending on itself does not require any
+ -- normalization.
- if Nkind (Output) = N_Attribute_Reference
- and then Attribute_Name (Output) = Name_Result
- then
- Error_Msg_N ("function result cannot depend on itself", Output);
+ if Nkind (Output) = N_Null then
return;
- -- A null output depending on itself does not require any
- -- normalization.
+ -- A function result cannot depend on itself because it cannot
+ -- appear in the input list of a relation.
- elsif Nkind (Output) = N_Null then
+ elsif Is_Attribute_Result (Output) then
+ Error_Msg_N ("function result cannot depend on itself", Output);
return;
end if;
@@ -1144,16 +1280,15 @@ package body Sem_Prag is
else
-- Unchain the output from its output list as it will appear in
-- a new clause. Note that we cannot simply rewrite the output
- -- as null because this will violate the semantics of aspect or
- -- pragma Depends.
+ -- as null because this will violate the semantics of pragma
+ -- Depends.
Remove (Output);
- -- Create a new clause of the form:
-
+ -- Generate a new clause of the form:
-- (Output => Inputs)
- Clause :=
+ New_Clause :=
Make_Component_Association (Loc,
Choices => New_List (Output),
Expression => New_Copy_Tree (Inputs));
@@ -1162,16 +1297,80 @@ package body Sem_Prag is
-- been analyzed. There is not need to reanalyze it or
-- renormalize it again.
- Set_Analyzed (Clause);
+ Set_Analyzed (New_Clause);
Propagate_Output
- (Output => First (Choices (Clause)),
- Inputs => Expression (Clause));
+ (Output => First (Choices (New_Clause)),
+ Inputs => Expression (New_Clause));
- Insert_After (After, Clause);
+ Insert_After (After, New_Clause);
end if;
end Create_Or_Modify_Clause;
+ ----------------------------
+ -- Split_Multiple_Outputs --
+ ----------------------------
+
+ procedure Split_Multiple_Outputs is
+ Inputs : constant Node_Id := Expression (Clause);
+ Loc : constant Source_Ptr := Sloc (Clause);
+ Outputs : constant Node_Id := First (Choices (Clause));
+ Last_Output : Node_Id;
+ Next_Output : Node_Id;
+ Output : Node_Id;
+ Split : Node_Id;
+
+ -- Start of processing for Split_Multiple_Outputs
+
+ begin
+ -- Multiple outputs appear as an aggregate. Nothing to do when
+ -- the clause has exactly one output.
+
+ if Nkind (Outputs) = N_Aggregate then
+ Last_Output := Last (Expressions (Outputs));
+
+ -- Create a clause for each output. Note that each time a new
+ -- clause is created, the original output list slowly shrinks
+ -- until there is one item left.
+
+ Output := First (Expressions (Outputs));
+ while Present (Output) loop
+ Next_Output := Next (Output);
+
+ -- Unhook the output from the original output list as it
+ -- will be relocated to a new clause.
+
+ Remove (Output);
+
+ -- Special processing for the last output. At this point
+ -- the original aggregate has been stripped down to one
+ -- element. Replace the aggregate by the element itself.
+
+ if Output = Last_Output then
+ Rewrite (Outputs, Output);
+
+ else
+ -- Generate a clause of the form:
+ -- (Output => Inputs)
+
+ Split :=
+ Make_Component_Association (Loc,
+ Choices => New_List (Output),
+ Expression => New_Copy_Tree (Inputs));
+
+ -- The new clause contains replicated content that has
+ -- already been analyzed. There is not need to reanalyze
+ -- them.
+
+ Set_Analyzed (Split);
+ Insert_After (Clause, Split);
+ end if;
+
+ Output := Next_Output;
+ end loop;
+ end if;
+ end Split_Multiple_Outputs;
+
-- Local variables
Outputs : constant Node_Id := First (Choices (Clause));
@@ -1226,6 +1425,11 @@ package body Sem_Prag is
Multiple => False);
end if;
end if;
+
+ -- Split a clause with multiple outputs into multiple clauses with a
+ -- single output.
+
+ Split_Multiple_Outputs;
end Normalize_Clause;
-- Local variables
@@ -1235,14 +1439,35 @@ package body Sem_Prag is
Last_Clause : Node_Id;
Subp_Decl : Node_Id;
+ Restore_Scope : Boolean := False;
+ -- Gets set True if we do a Push_Scope needing a Pop_Scope on exit
+
-- Start of processing for Analyze_Depends_In_Decl_Part
begin
Set_Analyzed (N);
- Subp_Decl := Find_Related_Subprogram (N);
- Subp_Id := Defining_Unit_Name (Specification (Subp_Decl));
- Clause := Expression (Arg1);
+ Subp_Decl := Find_Related_Subprogram_Or_Body (N);
+ Subp_Id := Defining_Entity (Subp_Decl);
+
+ -- The logic in this routine is used to analyze both pragma Depends and
+ -- pragma Refined_Depends since they have the same syntax and base
+ -- semantics. Find the entity of the corresponding spec when analyzing
+ -- Refined_Depends.
+
+ if Nkind (Subp_Decl) = N_Subprogram_Body
+ and then not Acts_As_Spec (Subp_Decl)
+ then
+ Spec_Id := Corresponding_Spec (Subp_Decl);
+
+ elsif Nkind (Subp_Decl) = N_Subprogram_Body_Stub then
+ Spec_Id := Corresponding_Spec_Of_Stub (Subp_Decl);
+
+ else
+ Spec_Id := Subp_Id;
+ end if;
+
+ Clause := Get_Pragma_Arg (First (Pragma_Argument_Associations (N)));
-- Empty dependency list
@@ -1250,7 +1475,7 @@ package body Sem_Prag is
-- Gather all states, variables and formal parameters that the
-- subprogram may depend on. These items are obtained from the
- -- parameter profile or pragma Global (if available).
+ -- parameter profile or pragma [Refined_]Global (if available).
Collect_Subprogram_Inputs_Outputs
(Subp_Id => Subp_Id,
@@ -1262,7 +1487,7 @@ package body Sem_Prag is
-- dependency.
Check_Usage (Subp_Inputs, All_Inputs_Seen, True);
- Check_Usage (Subp_Outputs, Outputs_Seen, False);
+ Check_Usage (Subp_Outputs, All_Outputs_Seen, False);
Check_Function_Return;
-- Dependency clauses appear as component associations of an aggregate
@@ -1274,7 +1499,7 @@ package body Sem_Prag is
-- Gather all states, variables and formal parameters that the
-- subprogram may depend on. These items are obtained from the
- -- parameter profile or pragma Global (if available).
+ -- parameter profile or pragma [Refined_]Global (if available).
Collect_Subprogram_Inputs_Outputs
(Subp_Id => Subp_Id,
@@ -1287,9 +1512,10 @@ package body Sem_Prag is
-- to subprogram declarations. Skip the installation for subprogram
-- bodies because the formals are already visible.
- if Requires_Profile_Installation (N, Subp_Decl) then
- Push_Scope (Subp_Id);
- Install_Formals (Subp_Id);
+ if not In_Open_Scopes (Spec_Id) then
+ Restore_Scope := True;
+ Push_Scope (Spec_Id);
+ Install_Formals (Spec_Id);
end if;
Clause := First (Component_Associations (Clause));
@@ -1297,8 +1523,7 @@ package body Sem_Prag is
Errors := Serious_Errors_Detected;
-- Normalization may create extra clauses that contain replicated
- -- input and output names. There is no need to reanalyze or
- -- renormalize these extra clauses.
+ -- input and output names. There is no need to reanalyze them.
if not Analyzed (Clause) then
Set_Analyzed (Clause);
@@ -1306,19 +1531,19 @@ package body Sem_Prag is
Analyze_Dependency_Clause
(Clause => Clause,
Is_Last => Clause = Last_Clause);
+ end if;
- -- Do not normalize an erroneous clause because the inputs or
- -- outputs may denote illegal items.
+ -- Do not normalize an erroneous clause because the inputs and/or
+ -- outputs may denote illegal items.
- if Errors = Serious_Errors_Detected then
- Normalize_Clause (Clause);
- end if;
+ if Serious_Errors_Detected = Errors then
+ Normalize_Clause (Clause);
end if;
Next (Clause);
end loop;
- if Requires_Profile_Installation (N, Subp_Decl) then
+ if Restore_Scope then
End_Scope;
end if;
@@ -1326,7 +1551,7 @@ package body Sem_Prag is
-- dependency.
Check_Usage (Subp_Inputs, All_Inputs_Seen, True);
- Check_Usage (Subp_Outputs, Outputs_Seen, False);
+ Check_Usage (Subp_Outputs, All_Outputs_Seen, False);
Check_Function_Return;
-- The top level dependency relation is malformed
@@ -1341,19 +1566,21 @@ package body Sem_Prag is
---------------------------------
procedure Analyze_Global_In_Decl_Part (N : Node_Id) is
- Arg1 : constant Node_Id := First (Pragma_Argument_Associations (N));
-
Seen : Elist_Id := No_Elist;
-- A list containing the entities of all the items processed so far. It
-- plays a role in detecting distinct entities.
+ Spec_Id : Entity_Id;
+ -- The entity of the subprogram subject to pragma [Refined_]Global
+
Subp_Id : Entity_Id;
- -- The entity of the subprogram subject to pragma Global
+ -- The entity of the subprogram [body or stub] subject to pragma
+ -- [Refined_]Global.
- Contract_Seen : Boolean := False;
- In_Out_Seen : Boolean := False;
- Input_Seen : Boolean := False;
- Output_Seen : Boolean := False;
+ In_Out_Seen : Boolean := False;
+ Input_Seen : Boolean := False;
+ Output_Seen : Boolean := False;
+ Proof_Seen : Boolean := False;
-- Flags used to verify the consistency of modes
procedure Analyze_Global_List
@@ -1427,14 +1654,18 @@ package body Sem_Prag is
Item_Id := Entity_Of (Item);
if Present (Item_Id) then
+ Record_Possible_Body_Reference (Item, Item_Id);
- -- A global item cannot reference a formal parameter. Do this
- -- check first to provide a better error diagnostic.
+ -- A global item may denote a formal parameter of an enclosing
+ -- subprogram. Do this check first to provide a better error
+ -- diagnostic.
if Is_Formal (Item_Id) then
- Error_Msg_N
- ("global item cannot reference formal parameter", Item);
- return;
+ if Scope (Item_Id) = Spec_Id then
+ Error_Msg_N
+ ("global item cannot reference formal parameter", Item);
+ return;
+ end if;
-- The only legal references are those to abstract states and
-- variables.
@@ -1445,6 +1676,33 @@ package body Sem_Prag is
return;
end if;
+ if Ekind (Item_Id) = E_Abstract_State then
+
+ -- The state acts as a constituent of some other state.
+ -- Ensure that the other state is a proper ancestor of the
+ -- item.
+
+ if Present (Refined_State (Item_Id)) then
+ if not Is_Part_Of (Item_Id, Refined_State (Item_Id)) then
+ Error_Msg_Name_1 := Chars (Refined_State (Item_Id));
+ Error_Msg_NE
+ ("state & is not a valid constituent of ancestor "
+ & "state %", Item, Item_Id);
+ return;
+ end if;
+
+ -- An abstract state with visible refinement cannot appear
+ -- in pragma [Refined_]Global as its place must be taken by
+ -- some of its constituents.
+
+ elsif Has_Visible_Refinement (Item_Id) then
+ Error_Msg_NE
+ ("cannot mention state & in global refinement, use its "
+ & "constituents instead", Item, Item_Id);
+ return;
+ end if;
+ end if;
+
-- When the item renames an entire object, replace the item
-- with a reference to the object.
@@ -1464,27 +1722,27 @@ package body Sem_Prag is
-- valid choices. Perform mode- and usage-specific checks.
if Ekind (Item_Id) = E_Abstract_State
- and then Is_Volatile_State (Item_Id)
+ and then Is_External_State (Item_Id)
then
- -- A global item of mode In_Out or Output cannot denote a
- -- volatile Input state.
+ -- A global item of mode In_Out or Output cannot denote an
+ -- external Input_Only state.
- if Is_Input_State (Item_Id)
+ if Is_Input_Only_State (Item_Id)
and then Nam_In (Global_Mode, Name_In_Out, Name_Output)
then
Error_Msg_N
("global item of mode In_Out or Output cannot reference "
- & "Volatile Input state", Item);
+ & "External Input_Only state", Item);
- -- A global item of mode In_Out or Input cannot reference a
- -- volatile Output state.
+ -- A global item of mode In_Out or Input cannot reference an
+ -- external Output_Only state.
- elsif Is_Output_State (Item_Id)
+ elsif Is_Output_Only_State (Item_Id)
and then Nam_In (Global_Mode, Name_In_Out, Name_Input)
then
Error_Msg_N
("global item of mode In_Out or Input cannot reference "
- & "Volatile Output state", Item);
+ & "External Output_Only state", Item);
end if;
end if;
@@ -1540,12 +1798,12 @@ package body Sem_Prag is
begin
-- Traverse the scope stack looking for enclosing subprograms
- -- subject to aspect/pragma Global.
+ -- subject to pragma [Refined_]Global.
Context := Scope (Subp_Id);
while Present (Context) and then Context /= Standard_Standard loop
if Is_Subprogram (Context)
- and then Has_Aspect (Context, Aspect_Global)
+ and then Present (Get_Pragma (Context, Pragma_Global))
then
Collect_Subprogram_Inputs_Outputs
(Subp_Id => Context,
@@ -1582,7 +1840,7 @@ package body Sem_Prag is
procedure Check_Mode_Restriction_In_Function (Mode : Node_Id) is
begin
- if Ekind (Subp_Id) = E_Function then
+ if Ekind (Spec_Id) = E_Function then
Error_Msg_N
("global mode & not applicable to functions", Mode);
end if;
@@ -1597,17 +1855,21 @@ package body Sem_Prag is
-- Start of processing for Analyze_Global_List
begin
+ if Nkind (List) = N_Null then
+ Set_Analyzed (List);
+
-- Single global item declaration
- if Nkind_In (List, N_Expanded_Name,
- N_Identifier,
- N_Selected_Component)
+ elsif Nkind_In (List, N_Expanded_Name,
+ N_Identifier,
+ N_Selected_Component)
then
Analyze_Global_Item (List, Global_Mode);
-- Simple global list or moded global list declaration
elsif Nkind (List) = N_Aggregate then
+ Set_Analyzed (List);
-- The declaration of a simple global list appear as a collection
-- of expressions.
@@ -1640,10 +1902,7 @@ package body Sem_Prag is
Mode := First (Choices (Assoc));
if Nkind (Mode) = N_Identifier then
- if Chars (Mode) = Name_Contract_In then
- Check_Duplicate_Mode (Mode, Contract_Seen);
-
- elsif Chars (Mode) = Name_In_Out then
+ if Chars (Mode) = Name_In_Out then
Check_Duplicate_Mode (Mode, In_Out_Seen);
Check_Mode_Restriction_In_Function (Mode);
@@ -1654,6 +1913,9 @@ package body Sem_Prag is
Check_Duplicate_Mode (Mode, Output_Seen);
Check_Mode_Restriction_In_Function (Mode);
+ elsif Chars (Mode) = Name_Proof_In then
+ Check_Duplicate_Mode (Mode, Proof_Seen);
+
else
Error_Msg_N ("invalid mode selector", Mode);
end if;
@@ -1673,7 +1935,7 @@ package body Sem_Prag is
Next (Assoc);
end loop;
- -- Something went horribly wrong, we have a malformed tree
+ -- Invalid tree
else
raise Program_Error;
@@ -1688,22 +1950,43 @@ package body Sem_Prag is
-- Local variables
- List : Node_Id;
+ Items : Node_Id;
Subp_Decl : Node_Id;
+ Restore_Scope : Boolean := False;
+ -- Set True if we do a Push_Scope requiring a Pop_Scope on exit
+
-- Start of processing for Analyze_Global_In_Decl_List
begin
Set_Analyzed (N);
- Subp_Decl := Find_Related_Subprogram (N);
- Subp_Id := Defining_Unit_Name (Specification (Subp_Decl));
- List := Expression (Arg1);
+ Subp_Decl := Find_Related_Subprogram_Or_Body (N);
+ Subp_Id := Defining_Entity (Subp_Decl);
+
+ -- The logic in this routine is used to analyze both pragma Global and
+ -- pragma Refined_Global since they have the same syntax and base
+ -- semantics. Find the entity of the corresponding spec when analyzing
+ -- Refined_Global.
+
+ if Nkind (Subp_Decl) = N_Subprogram_Body
+ and then not Acts_As_Spec (Subp_Decl)
+ then
+ Spec_Id := Corresponding_Spec (Subp_Decl);
+
+ elsif Nkind (Subp_Decl) = N_Subprogram_Body_Stub then
+ Spec_Id := Corresponding_Spec_Of_Stub (Subp_Decl);
+
+ else
+ Spec_Id := Subp_Id;
+ end if;
+
+ Items := Get_Pragma_Arg (First (Pragma_Argument_Associations (N)));
-- There is nothing to be done for a null global list
- if Nkind (List) = N_Null then
- null;
+ if Nkind (Items) = N_Null then
+ Set_Analyzed (Items);
-- Analyze the various forms of global lists and items. Note that some
-- of these may be malformed in which case the analysis emits error
@@ -1714,171 +1997,533 @@ package body Sem_Prag is
-- item. This falls out of the general rule of aspects pertaining to
-- subprogram declarations.
- if Requires_Profile_Installation (N, Subp_Decl) then
- Push_Scope (Subp_Id);
- Install_Formals (Subp_Id);
+ if not In_Open_Scopes (Spec_Id) then
+ Restore_Scope := True;
+ Push_Scope (Spec_Id);
+ Install_Formals (Spec_Id);
end if;
- Analyze_Global_List (List);
+ Analyze_Global_List (Items);
- if Requires_Profile_Installation (N, Subp_Decl) then
+ if Restore_Scope then
End_Scope;
end if;
end if;
end Analyze_Global_In_Decl_Part;
- ------------------------------
- -- Analyze_PPC_In_Decl_Part --
- ------------------------------
+ --------------------------------------------
+ -- Analyze_Initial_Condition_In_Decl_Part --
+ --------------------------------------------
+
+ procedure Analyze_Initial_Condition_In_Decl_Part (N : Node_Id) is
+ Pack_Id : constant Entity_Id := Defining_Entity (Parent (Parent (N)));
+ Prag_Init : constant Node_Id :=
+ Get_Pragma (Pack_Id, Pragma_Initializes);
+ -- The related pragma Initializes
+
+ Vars : Elist_Id := No_Elist;
+ -- A list of all variables declared in pragma Initializes
+
+ procedure Collect_Variables;
+ -- Inspect the initialization list of pragma Initializes and collect the
+ -- entities of all variables declared within the related package.
+
+ function Match_Variable (N : Node_Id) return Traverse_Result;
+ -- Determine whether arbitrary node N denotes a variable declared in the
+ -- visible declarations of the related package.
+
+ procedure Report_Unused_Variables;
+ -- Emit errors for all variables found in list Vars
+
+ -----------------------
+ -- Collect_Variables --
+ -----------------------
+
+ procedure Collect_Variables is
+ procedure Collect_Variable (Item : Node_Id);
+ -- Determine whether Item denotes a variable that appears in the
+ -- related package and if it does, add it to list Vars.
+
+ ----------------------
+ -- Collect_Variable --
+ ----------------------
+
+ procedure Collect_Variable (Item : Node_Id) is
+ Item_Id : Entity_Id;
+
+ begin
+ if Is_Entity_Name (Item) and then Present (Entity (Item)) then
+ Item_Id := Entity (Item);
+
+ -- The item is a variable declared in the related package
+
+ if Ekind (Item_Id) = E_Variable
+ and then Scope (Item_Id) = Pack_Id
+ then
+ Add_Item (Item_Id, Vars);
+ end if;
+ end if;
+ end Collect_Variable;
+
+ -- Local variables
+
+ Inits : constant Node_Id :=
+ Get_Pragma_Arg
+ (First (Pragma_Argument_Associations (Prag_Init)));
+ Init : Node_Id;
+
+ -- Start of processing for Collect_Variables
+
+ begin
+ -- Multiple initialization items appear as an aggregate
+
+ if Nkind (Inits) = N_Aggregate
+ and then Present (Expressions (Inits))
+ then
+ Init := First (Expressions (Inits));
+ while Present (Init) loop
+ Collect_Variable (Init);
+
+ Next (Init);
+ end loop;
+
+ -- Single initialization item
+
+ else
+ Collect_Variable (Inits);
+ end if;
+ end Collect_Variables;
+
+ --------------------
+ -- Match_Variable --
+ --------------------
+
+ function Match_Variable (N : Node_Id) return Traverse_Result is
+ Var_Id : Entity_Id;
+
+ begin
+ -- Find a variable declared within the related package and try to
+ -- remove it from the list of collected variables found in pragma
+ -- Initializes.
+
+ if Is_Entity_Name (N)
+ and then Present (Entity (N))
+ then
+ Var_Id := Entity (N);
+
+ if Ekind (Var_Id) = E_Variable
+ and then Scope (Var_Id) = Pack_Id
+ then
+ Remove (Vars, Var_Id);
+ end if;
+ end if;
+
+ return OK;
+ end Match_Variable;
+
+ procedure Match_Variables is new Traverse_Proc (Match_Variable);
+
+ -----------------------------
+ -- Report_Unused_Variables --
+ -----------------------------
+
+ procedure Report_Unused_Variables is
+ Posted : Boolean := False;
+ Var_Elmt : Elmt_Id;
+ Var_Id : Entity_Id;
+
+ begin
+ if Present (Vars) then
+ Var_Elmt := First_Elmt (Vars);
+ while Present (Var_Elmt) loop
+ Var_Id := Node (Var_Elmt);
+
+ if not Posted then
+ Posted := True;
+ Error_Msg_Name_1 := Name_Initial_Condition;
+ Error_Msg_N
+ ("expression of % must mention the following variables",
+ N);
+ end if;
+
+ Error_Msg_Sloc := Sloc (Var_Id);
+ Error_Msg_NE ("\ & declared #", N, Var_Id);
+
+ Next_Elmt (Var_Elmt);
+ end loop;
+ end if;
+ end Report_Unused_Variables;
+
+ Expr : constant Node_Id :=
+ Get_Pragma_Arg (First (Pragma_Argument_Associations (N)));
+ Errors : constant Nat := Serious_Errors_Detected;
- procedure Analyze_PPC_In_Decl_Part (N : Node_Id; S : Entity_Id) is
- Arg1 : constant Node_Id := First (Pragma_Argument_Associations (N));
+ -- Start of processing for Analyze_Initial_Condition_In_Decl_Part
begin
- -- Install formals and push subprogram spec onto scope stack so that we
- -- can see the formals from the pragma.
+ Set_Analyzed (N);
- Install_Formals (S);
- Push_Scope (S);
+ -- Pragma Initial_Condition depends on the names enumerated in pragma
+ -- Initializes. Without those, the analysis cannot take place.
- -- Preanalyze the boolean expression, we treat this as a spec expression
- -- (i.e. similar to a default expression).
+ if No (Prag_Init) then
+ Error_Msg_Name_1 := Name_Initial_Condition;
+ Error_Msg_Name_2 := Name_Initializes;
- -- In ASIS mode, for a pragma generated from a source aspect, analyze
- -- directly the the original aspect expression, which is shared with
- -- the generated pragma.
+ Error_Msg_N ("% requires the presence of aspect or pragma %", N);
+ return;
+ end if;
- if ASIS_Mode and then Present (Corresponding_Aspect (N)) then
- Preanalyze_Assert_Expression
- (Expression (Corresponding_Aspect (N)), Standard_Boolean);
- else
- Preanalyze_Assert_Expression
- (Get_Pragma_Arg (Arg1), Standard_Boolean);
+ -- The expression is preanalyzed because it has not been moved to its
+ -- final place yet. A direct analysis may generate sife effects and this
+ -- is not desired at this point.
+
+ Preanalyze_And_Resolve (Expr, Standard_Boolean);
+
+ -- Perform variable matching only when the expression is legal
+
+ if Serious_Errors_Detected = Errors then
+ Collect_Variables;
+
+ -- Verify that all variables mentioned in pragma Initializes are used
+ -- in the expression of pragma Initial_Condition.
+
+ Match_Variables (Expr);
end if;
- -- For a class-wide condition, a reference to a controlling formal must
- -- be interpreted as having the class-wide type (or an access to such)
- -- so that the inherited condition can be properly applied to any
- -- overriding operation (see ARM12 6.6.1 (7)).
+ -- Emit errors for all variables that should participate in the
+ -- expression of pragma Initial_Condition.
- if Class_Present (N) then
- Class_Wide_Condition : declare
- T : constant Entity_Id := Find_Dispatching_Type (S);
+ if Serious_Errors_Detected = Errors then
+ Report_Unused_Variables;
+ end if;
+ end Analyze_Initial_Condition_In_Decl_Part;
- ACW : Entity_Id := Empty;
- -- Access to T'class, created if there is a controlling formal
- -- that is an access parameter.
+ --------------------------------------
+ -- Analyze_Initializes_In_Decl_Part --
+ --------------------------------------
- function Get_ACW return Entity_Id;
- -- If the expression has a reference to an controlling access
- -- parameter, create an access to T'class for the necessary
- -- conversions if one does not exist.
+ procedure Analyze_Initializes_In_Decl_Part (N : Node_Id) is
+ Pack_Spec : constant Node_Id := Parent (N);
+ Pack_Id : constant Entity_Id := Defining_Entity (Parent (Pack_Spec));
- function Process (N : Node_Id) return Traverse_Result;
- -- ARM 6.1.1: Within the expression for a Pre'Class or Post'Class
- -- aspect for a primitive subprogram of a tagged type T, a name
- -- that denotes a formal parameter of type T is interpreted as
- -- having type T'Class. Similarly, a name that denotes a formal
- -- accessparameter of type access-to-T is interpreted as having
- -- type access-to-T'Class. This ensures the expression is well-
- -- defined for a primitive subprogram of a type descended from T.
- -- Note that this replacement is not done for selector names in
- -- parameter associations. These carry an entity for reference
- -- purposes, but semantically they are just identifiers.
+ Items_Seen : Elist_Id := No_Elist;
+ -- A list of all initialization items processed so far. This list is
+ -- used to detect duplicate items.
- -------------
- -- Get_ACW --
- -------------
+ Non_Null_Seen : Boolean := False;
+ Null_Seen : Boolean := False;
+ -- Flags used to check the legality of a null initialization list
- function Get_ACW return Entity_Id is
- Loc : constant Source_Ptr := Sloc (N);
- Decl : Node_Id;
+ States_And_Vars : Elist_Id := No_Elist;
+ -- A list of all abstract states and variables declared in the visible
+ -- declarations of the related package. This list is used to detect the
+ -- legality of initialization items.
- begin
- if No (ACW) then
- Decl := Make_Full_Type_Declaration (Loc,
- Defining_Identifier => Make_Temporary (Loc, 'T'),
- Type_Definition =>
- Make_Access_To_Object_Definition (Loc,
- Subtype_Indication =>
- New_Occurrence_Of (Class_Wide_Type (T), Loc),
- All_Present => True));
-
- Insert_Before (Unit_Declaration_Node (S), Decl);
- Analyze (Decl);
- ACW := Defining_Identifier (Decl);
- Freeze_Before (Unit_Declaration_Node (S), ACW);
- end if;
+ procedure Analyze_Initialization_Item (Item : Node_Id);
+ -- Verify the legality of a single initialization item
- return ACW;
- end Get_ACW;
+ procedure Analyze_Initialization_Item_With_Inputs (Item : Node_Id);
+ -- Verify the legality of a single initialization item followed by a
+ -- list of input items.
- -------------
- -- Process --
- -------------
+ procedure Collect_States_And_Variables;
+ -- Inspect the visible declarations of the related package and gather
+ -- the entities of all abstract states and variables in States_And_Vars.
- function Process (N : Node_Id) return Traverse_Result is
- Loc : constant Source_Ptr := Sloc (N);
- Typ : Entity_Id;
+ ---------------------------------
+ -- Analyze_Initialization_Item --
+ ---------------------------------
- begin
- if Is_Entity_Name (N)
- and then Present (Entity (N))
- and then Is_Formal (Entity (N))
- and then Nkind (Parent (N)) /= N_Type_Conversion
- and then
- (Nkind (Parent (N)) /= N_Parameter_Association
- or else N /= Selector_Name (Parent (N)))
- then
- if Etype (Entity (N)) = T then
- Typ := Class_Wide_Type (T);
+ procedure Analyze_Initialization_Item (Item : Node_Id) is
+ Item_Id : Entity_Id;
+
+ begin
+ -- Null initialization list
+
+ if Nkind (Item) = N_Null then
+ if Null_Seen then
+ Error_Msg_N ("multiple null initializations not allowed", Item);
+
+ elsif Non_Null_Seen then
+ Error_Msg_N
+ ("cannot mix null and non-null initialization items", Item);
+ else
+ Null_Seen := True;
+ end if;
+
+ -- Initialization item
+
+ else
+ Non_Null_Seen := True;
+
+ if Null_Seen then
+ Error_Msg_N
+ ("cannot mix null and non-null initialization items", Item);
+ end if;
+
+ Analyze (Item);
+
+ if Is_Entity_Name (Item) then
+ Item_Id := Entity (Item);
+
+ if Ekind_In (Item_Id, E_Abstract_State, E_Variable) then
+
+ -- The state or variable must be declared in the visible
+ -- declarations of the package.
+
+ if not Contains (States_And_Vars, Item_Id) then
+ Error_Msg_Name_1 := Chars (Pack_Id);
+ Error_Msg_NE
+ ("initialization item & must appear in the visible "
+ & "declarations of package %", Item, Item_Id);
+
+ -- Detect a duplicate use of the same initialization item
+
+ elsif Contains (Items_Seen, Item_Id) then
+ Error_Msg_N ("duplicate initialization item", Item);
+
+ -- The item is legal, add it to the list of processed states
+ -- and variables.
- elsif Is_Access_Type (Etype (Entity (N)))
- and then Designated_Type (Etype (Entity (N))) = T
- then
- Typ := Get_ACW;
else
- Typ := Empty;
+ Add_Item (Item_Id, Items_Seen);
end if;
- if Present (Typ) then
- Rewrite (N,
- Make_Type_Conversion (Loc,
- Subtype_Mark =>
- New_Occurrence_Of (Typ, Loc),
- Expression => New_Occurrence_Of (Entity (N), Loc)));
- Set_Etype (N, Typ);
- end if;
+ -- The item references something that is not a state or a
+ -- variable.
+
+ else
+ Error_Msg_N
+ ("initialization item must denote variable or state",
+ Item);
end if;
- return OK;
- end Process;
+ -- Some form of illegal construct masquerading as a name
- procedure Replace_Type is new Traverse_Proc (Process);
+ else
+ Error_Msg_N
+ ("initialization item must denote variable or state", Item);
+ end if;
+ end if;
+ end Analyze_Initialization_Item;
- -- Start of processing for Class_Wide_Condition
+ ---------------------------------------------
+ -- Analyze_Initialization_Item_With_Inputs --
+ ---------------------------------------------
+
+ procedure Analyze_Initialization_Item_With_Inputs (Item : Node_Id) is
+ Inputs_Seen : Elist_Id := No_Elist;
+ -- A list of all inputs processed so far. This list is used to detect
+ -- duplicate uses of an input.
+
+ Non_Null_Seen : Boolean := False;
+ Null_Seen : Boolean := False;
+ -- Flags used to check the legality of an input list
+
+ procedure Analyze_Input_Item (Input : Node_Id);
+ -- Verify the legality of a single input item
+
+ ------------------------
+ -- Analyze_Input_Item --
+ ------------------------
+
+ procedure Analyze_Input_Item (Input : Node_Id) is
+ Input_Id : Entity_Id;
begin
- if not Present (T) then
- Error_Msg_Name_1 :=
- Chars (Identifier (Corresponding_Aspect (N)));
+ -- Null input list
+
+ if Nkind (Input) = N_Null then
+ if Null_Seen then
+ Error_Msg_N
+ ("multiple null initializations not allowed", Item);
+
+ elsif Non_Null_Seen then
+ Error_Msg_N
+ ("cannot mix null and non-null initialization item", Item);
+ else
+ Null_Seen := True;
+ end if;
+
+ -- Input item
+
+ else
+ Non_Null_Seen := True;
+
+ if Null_Seen then
+ Error_Msg_N
+ ("cannot mix null and non-null initialization item", Item);
+ end if;
+
+ Analyze (Input);
+
+ if Is_Entity_Name (Input) then
+ Input_Id := Entity (Input);
+
+ if Ekind_In (Input_Id, E_Abstract_State, E_Variable) then
+
+ -- The input cannot denote states or variables declared
+ -- within the related package.
+
+ if In_Same_Code_Unit (Item, Input_Id) then
+ Error_Msg_Name_1 := Chars (Pack_Id);
+ Error_Msg_NE
+ ("input item & cannot denote a visible variable or "
+ & "state of package %", Input, Input_Id);
+
+ -- Detect a duplicate use of the same input item
+
+ elsif Contains (Inputs_Seen, Input_Id) then
+ Error_Msg_N ("duplicate input item", Input);
+
+ -- Input is legal, add it to the list of processed inputs
+
+ else
+ Add_Item (Input_Id, Inputs_Seen);
+ end if;
- Error_Msg_Name_2 := Name_Class;
+ -- The input references something that is not a state or a
+ -- variable.
+ else
+ Error_Msg_N
+ ("input item must denote variable or state", Input);
+ end if;
+
+ -- Some form of illegal construct masquerading as a name
+
+ else
+ Error_Msg_N
+ ("input item must denote variable or state", Input);
+ end if;
+ end if;
+ end Analyze_Input_Item;
+
+ -- Local variables
+
+ Inputs : constant Node_Id := Expression (Item);
+ Elmt : Node_Id;
+ Input : Node_Id;
+
+ Name_Seen : Boolean := False;
+ -- A flag used to detect multiple item names
+
+ -- Start of processing for Analyze_Initialization_Item_With_Inputs
+
+ begin
+ -- Inspect the name of an item with inputs
+
+ Elmt := First (Choices (Item));
+ while Present (Elmt) loop
+ if Name_Seen then
+ Error_Msg_N ("only one item allowed in initialization", Elmt);
+ else
+ Name_Seen := True;
+ Analyze_Initialization_Item (Elmt);
+ end if;
+
+ Next (Elmt);
+ end loop;
+
+ -- Multiple input items appear as an aggregate
+
+ if Nkind (Inputs) = N_Aggregate then
+ if Present (Expressions (Inputs)) then
+ Input := First (Expressions (Inputs));
+ while Present (Input) loop
+ Analyze_Input_Item (Input);
+ Next (Input);
+ end loop;
+ end if;
+
+ if Present (Component_Associations (Inputs)) then
Error_Msg_N
- ("aspect `%''%` can only be specified for a primitive "
- & "operation of a tagged type", Corresponding_Aspect (N));
+ ("inputs must appear in named association form", Inputs);
end if;
- Replace_Type (Get_Pragma_Arg (Arg1));
- end Class_Wide_Condition;
- end if;
+ -- Single input item
- -- Remove the subprogram from the scope stack now that the pre-analysis
- -- of the precondition/postcondition is done.
+ else
+ Analyze_Input_Item (Inputs);
+ end if;
+ end Analyze_Initialization_Item_With_Inputs;
- End_Scope;
- end Analyze_PPC_In_Decl_Part;
+ ----------------------------------
+ -- Collect_States_And_Variables --
+ ----------------------------------
+
+ procedure Collect_States_And_Variables is
+ Decl : Node_Id;
+
+ begin
+ -- Collect the abstract states defined in the package (if any)
+
+ if Present (Abstract_States (Pack_Id)) then
+ States_And_Vars := New_Copy_Elist (Abstract_States (Pack_Id));
+ end if;
+
+ -- Collect all variables the appear in the visible declarations of
+ -- the related package.
+
+ if Present (Visible_Declarations (Pack_Spec)) then
+ Decl := First (Visible_Declarations (Pack_Spec));
+ while Present (Decl) loop
+ if Nkind (Decl) = N_Object_Declaration
+ and then Ekind (Defining_Entity (Decl)) = E_Variable
+ and then Comes_From_Source (Decl)
+ then
+ Add_Item (Defining_Entity (Decl), States_And_Vars);
+ end if;
+
+ Next (Decl);
+ end loop;
+ end if;
+ end Collect_States_And_Variables;
+
+ -- Local variables
+
+ Inits : constant Node_Id :=
+ Get_Pragma_Arg (First (Pragma_Argument_Associations (N)));
+ Init : Node_Id;
+
+ -- Start of processing for Analyze_Initializes_In_Decl_Part
+
+ begin
+ Set_Analyzed (N);
+
+ -- Initialize the various lists used during analysis
+
+ Collect_States_And_Variables;
+
+ -- Multiple initialization clauses appear as an aggregate
+
+ if Nkind (Inits) = N_Aggregate then
+ if Present (Expressions (Inits)) then
+ Init := First (Expressions (Inits));
+ while Present (Init) loop
+ Analyze_Initialization_Item (Init);
+
+ Next (Init);
+ end loop;
+ end if;
+
+ if Present (Component_Associations (Inits)) then
+ Init := First (Component_Associations (Inits));
+ while Present (Init) loop
+ Analyze_Initialization_Item_With_Inputs (Init);
+
+ Next (Init);
+ end loop;
+ end if;
+
+ -- Various forms of a single initialization clause. Note that these may
+ -- include malformed initializations.
+
+ else
+ Analyze_Initialization_Item (Inits);
+ end if;
+ end Analyze_Initializes_In_Decl_Part;
--------------------
-- Analyze_Pragma --
@@ -1923,6 +2568,16 @@ package body Sem_Prag is
-- In Ada 95 or 05 mode, these are implementation defined pragmas, so
-- should be caught by the No_Implementation_Pragmas restriction.
+ procedure Analyze_Refined_Pragma
+ (Spec_Id : out Entity_Id;
+ Body_Id : out Entity_Id;
+ Legal : out Boolean);
+ -- Subsidiary routine to the analysis of body pragmas Refined_Depends,
+ -- Refined_Global and Refined_Post. Check the placement and related
+ -- context of the pragma. Spec_Id is the entity of the related
+ -- subprogram. Body_Id is the entity of the subprogram body. Flag Legal
+ -- is set when the pragma is properly placed.
+
procedure Check_Ada_83_Warning;
-- Issues a warning message for the current pragma if operating in Ada
-- 83 mode (used for language pragmas that are not a standard part of
@@ -2026,16 +2681,10 @@ package body Sem_Prag is
-- UU_Typ is the related Unchecked_Union type. Flag In_Variant_Part
-- should be set when Comp comes from a record variant.
- procedure Check_Test_Case;
- -- Called to process a test-case pragma. It starts with checking pragma
- -- arguments, and the rest of the treatment is similar to the one for
- -- pre- and postcondition in Check_Precondition_Postcondition, except
- -- the placement rules for the test-case pragma are stricter. These
- -- pragmas may only occur after a subprogram spec declared directly
- -- in a package spec unit. In this case, the pragma is chained to the
- -- subprogram in question (using Contract_Test_Cases and Next_Pragma)
- -- and analysis of the pragma is delayed till the end of the spec. In
- -- all other cases, an error message for bad placement is given.
+ procedure Check_Declaration_Order (First : Node_Id; Second : Node_Id);
+ -- Subsidiary routine to the analysis of pragmas Abstract_State,
+ -- Initial_Condition and Initializes. Determine whether pragma First
+ -- appears before pragma Second. If this is not the case, emit an error.
procedure Check_Duplicate_Pragma (E : Entity_Id);
-- Check if a rep item of the same name as the current pragma is already
@@ -2115,6 +2764,13 @@ package body Sem_Prag is
-- In this version of the procedure, the identifier name is given as
-- a string with lower case letters.
+ procedure Check_Pre_Post;
+ -- Called to perform checks for Pre, Pre_Class, Post, Post_Class
+ -- pragmas. These are processed by transformation to equivalent
+ -- Precondition and Postcondition pragmas, but Pre and Post need an
+ -- additional check that they are not used in a subprogram body when
+ -- there is a separate spec present.
+
procedure Check_Precondition_Postcondition (In_Body : out Boolean);
-- Called to process a precondition or postcondition pragma. There are
-- three cases:
@@ -2145,6 +2801,17 @@ package body Sem_Prag is
-- that the constraint is static as required by the restrictions for
-- Unchecked_Union.
+ procedure Check_Test_Case;
+ -- Called to process a test-case pragma. It starts with checking pragma
+ -- arguments, and the rest of the treatment is similar to the one for
+ -- pre- and postcondition in Check_Precondition_Postcondition, except
+ -- the placement rules for the test-case pragma are stricter. These
+ -- pragmas may only occur after a subprogram spec declared directly
+ -- in a package spec unit. In this case, the pragma is chained to the
+ -- subprogram in question (using Contract_Test_Cases and Next_Pragma)
+ -- and analysis of the pragma is delayed till the end of the spec. In
+ -- all other cases, an error message for bad placement is given.
+
procedure Check_Valid_Configuration_Pragma;
-- Legality checks for placement of a configuration pragma
@@ -2449,6 +3116,85 @@ package body Sem_Prag is
end if;
end Ada_2012_Pragma;
+ ----------------------------
+ -- Analyze_Refined_Pragma --
+ ----------------------------
+
+ procedure Analyze_Refined_Pragma
+ (Spec_Id : out Entity_Id;
+ Body_Id : out Entity_Id;
+ Legal : out Boolean)
+ is
+ Body_Decl : Node_Id;
+ Pack_Spec : Node_Id;
+ Spec_Decl : Node_Id;
+
+ begin
+ -- Assume that the pragma is illegal
+
+ Spec_Id := Empty;
+ Body_Id := Empty;
+ Legal := False;
+
+ GNAT_Pragma;
+ Check_Arg_Count (1);
+ Check_No_Identifiers;
+
+ -- Verify the placement of the pragma and check for duplicates. The
+ -- pragma must apply to a subprogram body [stub].
+
+ Body_Decl := Find_Related_Subprogram_Or_Body (N, Do_Checks => True);
+
+ if not Nkind_In (Body_Decl, N_Subprogram_Body,
+ N_Subprogram_Body_Stub)
+ then
+ Pragma_Misplaced;
+ return;
+ end if;
+
+ Body_Id := Defining_Entity (Body_Decl);
+
+ -- The body [stub] must not act as a spec, in other words it has to
+ -- be paired with a corresponding spec.
+
+ if Nkind (Body_Decl) = N_Subprogram_Body then
+ Spec_Id := Corresponding_Spec (Body_Decl);
+ else
+ Spec_Id := Corresponding_Spec_Of_Stub (Body_Decl);
+ end if;
+
+ if No (Spec_Id) then
+ Error_Pragma ("pragma % cannot apply to a stand alone body");
+ return;
+ end if;
+
+ -- The pragma may only apply to the body [stub] of a subprogram
+ -- declared in the visible part of a package. Retrieve the context of
+ -- the subprogram declaration.
+
+ Spec_Decl := Parent (Parent (Spec_Id));
+
+ pragma Assert
+ (Nkind_In (Spec_Decl, N_Abstract_Subprogram_Declaration,
+ N_Generic_Subprogram_Declaration,
+ N_Subprogram_Declaration));
+
+ Pack_Spec := Parent (Spec_Decl);
+
+ if Nkind (Pack_Spec) /= N_Package_Specification
+ or else List_Containing (Spec_Decl) /=
+ Visible_Declarations (Pack_Spec)
+ then
+ Error_Pragma
+ ("pragma % must apply to the body of a visible subprogram");
+ return;
+ end if;
+
+ -- If we get here, then the pragma is legal
+
+ Legal := True;
+ end Analyze_Refined_Pragma;
+
--------------------------
-- Check_Ada_83_Warning --
--------------------------
@@ -2913,6 +3659,107 @@ package body Sem_Prag is
end if;
end Check_Component;
+ -----------------------------
+ -- Check_Declaration_Order --
+ -----------------------------
+
+ procedure Check_Declaration_Order (First : Node_Id; Second : Node_Id) is
+ procedure Check_Aspect_Specification_Order;
+ -- Inspect the aspect specifications of the context to determine the
+ -- proper order.
+
+ --------------------------------------
+ -- Check_Aspect_Specification_Order --
+ --------------------------------------
+
+ procedure Check_Aspect_Specification_Order is
+ Asp_First : constant Node_Id := Corresponding_Aspect (First);
+ Asp_Second : constant Node_Id := Corresponding_Aspect (Second);
+ Asp : Node_Id;
+
+ begin
+ -- Both aspects must be part of the same aspect specification list
+
+ pragma Assert
+ (List_Containing (Asp_First) = List_Containing (Asp_Second));
+
+ -- Try to reach Second starting from First in a left to right
+ -- traversal of the aspect specifications.
+
+ Asp := Next (Asp_First);
+ while Present (Asp) loop
+
+ -- The order is ok, First is followed by Second
+
+ if Asp = Asp_Second then
+ return;
+ end if;
+
+ Next (Asp);
+ end loop;
+
+ -- If we get here, then the aspects are out of order
+
+ Error_Msg_N ("aspect % cannot come after aspect %", First);
+ end Check_Aspect_Specification_Order;
+
+ -- Local variables
+
+ Stmt : Node_Id;
+
+ -- Start of processing for Check_Declaration_Order
+
+ begin
+ -- Cannot check the order if one of the pragmas is missing
+
+ if No (First) or else No (Second) then
+ return;
+ end if;
+
+ -- Set up the error names in case the order is incorrect
+
+ Error_Msg_Name_1 := Pragma_Name (First);
+ Error_Msg_Name_2 := Pragma_Name (Second);
+
+ if From_Aspect_Specification (First) then
+
+ -- Both pragmas are actually aspects, check their declaration
+ -- order in the associated aspect specification list. Otherwise
+ -- First is an aspect and Second a source pragma.
+
+ if From_Aspect_Specification (Second) then
+ Check_Aspect_Specification_Order;
+ end if;
+
+ -- Abstract_States is a source pragma
+
+ else
+ if From_Aspect_Specification (Second) then
+ Error_Msg_N ("pragma % cannot come after aspect %", First);
+
+ -- Both pragmas are source constructs. Try to reach First from
+ -- Second by traversing the declarations backwards.
+
+ else
+ Stmt := Prev (Second);
+ while Present (Stmt) loop
+
+ -- The order is ok, First is followed by Second
+
+ if Stmt = First then
+ return;
+ end if;
+
+ Prev (Stmt);
+ end loop;
+
+ -- If we get here, then the pragmas are out of order
+
+ Error_Msg_N ("pragma % cannot come after pragma %", First);
+ end if;
+ end if;
+ end Check_Declaration_Order;
+
----------------------------
-- Check_Duplicate_Pragma --
----------------------------
@@ -3402,6 +4249,97 @@ package body Sem_Prag is
Check_Optional_Identifier (Arg, Name_Find);
end Check_Optional_Identifier;
+ --------------------
+ -- Check_Pre_Post --
+ --------------------
+
+ procedure Check_Pre_Post is
+ P : Node_Id;
+ PO : Node_Id;
+
+ begin
+ if not Is_List_Member (N) then
+ Pragma_Misplaced;
+ end if;
+
+ -- If we are within an inlined body, the legality of the pragma
+ -- has been checked already.
+
+ if In_Inlined_Body then
+ return;
+ end if;
+
+ -- Search prior declarations
+
+ P := N;
+ while Present (Prev (P)) loop
+ P := Prev (P);
+
+ -- If the previous node is a generic subprogram, do not go to to
+ -- the original node, which is the unanalyzed tree: we need to
+ -- attach the pre/postconditions to the analyzed version at this
+ -- point. They get propagated to the original tree when analyzing
+ -- the corresponding body.
+
+ if Nkind (P) not in N_Generic_Declaration then
+ PO := Original_Node (P);
+ else
+ PO := P;
+ end if;
+
+ -- Skip past prior pragma
+
+ if Nkind (PO) = N_Pragma then
+ null;
+
+ -- Skip stuff not coming from source
+
+ elsif not Comes_From_Source (PO) then
+
+ -- The condition may apply to a subprogram instantiation
+
+ if Nkind (PO) = N_Subprogram_Declaration
+ and then Present (Generic_Parent (Specification (PO)))
+ then
+ return;
+
+ elsif Nkind (PO) = N_Subprogram_Declaration
+ and then In_Instance
+ then
+ return;
+
+ -- For all other cases of non source code, do nothing
+
+ else
+ null;
+ end if;
+
+ -- Only remaining possibility is subprogram declaration
+
+ else
+ return;
+ end if;
+ end loop;
+
+ -- If we fall through loop, pragma is at start of list, so see if it
+ -- is at the start of declarations of a subprogram body.
+
+ PO := Parent (N);
+
+ if Nkind (PO) = N_Subprogram_Body
+ and then List_Containing (N) = Declarations (PO)
+ then
+ -- This is only allowed if there is no separate specification
+
+ if Present (Corresponding_Spec (PO)) then
+ Error_Pragma
+ ("pragma% must apply to subprogram specification");
+ end if;
+
+ return;
+ end if;
+ end Check_Pre_Post;
+
--------------------------------------
-- Check_Precondition_Postcondition --
--------------------------------------
@@ -3441,7 +4379,7 @@ package body Sem_Prag is
-- compatibility with earlier uses of the Ada pragma, apply this
-- rule only to aspect specifications.
- -- The above discrpency needs documentation. Robert is dubious
+ -- The above discrepency needs documentation. Robert is dubious
-- about whether it is a good idea ???
elsif Nkind (PO) = N_Subprogram_Declaration
@@ -3654,10 +4592,12 @@ package body Sem_Prag is
elsif Nkind (PO) = N_Compilation_Unit_Aux then
-- In formal verification mode, analyze pragma expression for
- -- correctness, as it is not expanded later.
+ -- correctness, as it is not expanded later. Ditto in ASIS_Mode
+ -- where there is no later point at which the aspect will be
+ -- analyzed.
- if SPARK_Mode then
- Analyze_PPC_In_Decl_Part
+ if SPARK_Mode or else ASIS_Mode then
+ Analyze_Pre_Post_Condition_In_Decl_Part
(N, Defining_Entity (Unit (Parent (PO))));
end if;
@@ -4031,7 +4971,7 @@ package body Sem_Prag is
Pragma_Misplaced;
elsif (Nkind (Parent_Node) = N_Generic_Package_Declaration
- or else Nkind (Parent_Node) =
+ or else Nkind (Parent_Node) =
N_Generic_Subprogram_Declaration)
and then Plist = Generic_Formal_Declarations (Parent_Node)
then
@@ -4294,7 +5234,7 @@ package body Sem_Prag is
-- Get name from corresponding aspect
- Error_Msg_Name_1 := Original_Name (N);
+ Error_Msg_Name_1 := Original_Aspect_Name (N);
end if;
end Fix_Error;
@@ -6414,6 +7354,34 @@ package body Sem_Prag is
Check_CPP_Type_Has_No_Defaults (Def_Id);
end if;
+ -- Import a CPP exception
+
+ elsif C = Convention_CPP
+ and then Ekind (Def_Id) = E_Exception
+ then
+ if No (Arg3) then
+ Error_Pragma_Arg
+ ("'External_'Name arguments is required for 'Cpp exception",
+ Arg3);
+ else
+ -- As only a string is allowed, Check_Arg_Is_External_Name
+ -- isn't called.
+ Check_Arg_Is_Static_Expression (Arg3, Standard_String);
+ end if;
+
+ if Present (Arg4) then
+ Error_Pragma_Arg
+ ("Link_Name argument not allowed for imported Cpp exception",
+ Arg4);
+ end if;
+
+ -- Do not call Set_Interface_Name as the name of the exception
+ -- shouldn't be modified (and in particular it shouldn't be
+ -- the External_Name). For exceptions, the External_Name is the
+ -- name of the RTTI structure.
+
+ -- ??? Emit an error if pragma Import/Export_Exception is present
+
elsif Nkind (Parent (Def_Id)) = N_Incomplete_Type_Declaration then
Check_No_Link_Name;
Check_Arg_Count (3);
@@ -8188,7 +9156,7 @@ package body Sem_Prag is
-- Here to start processing for recognized pragma
Prag_Id := Get_Pragma_Id (Pname);
- Pname := Original_Name (N);
+ Pname := Original_Aspect_Name (N);
-- Check applicable policy. We skip this if Is_Checked or Is_Ignored
-- is already set, indicating that we have already checked the policy
@@ -8283,19 +9251,21 @@ package body Sem_Prag is
-- ABSTRACT_STATE_LIST ::=
-- null
- -- | STATE_NAME_WITH_PROPERTIES {, STATE_NAME_WITH_PROPERTIES}
+ -- | STATE_NAME_WITH_OPTIONS
+ -- | (STATE_NAME_WITH_OPTIONS {, STATE_NAME_WITH_OPTIONS})
- -- STATE_NAME_WITH_PROPERTIES ::=
- -- STATE_NAME
- -- | (STATE_NAME with PROPERTY_LIST)
+ -- STATE_NAME_WITH_OPTIONS ::=
+ -- state_NAME
+ -- | (state_NAME with OPTION_LIST)
- -- PROPERTY_LIST ::= PROPERTY {, PROPERTY}
- -- PROPERTY ::= SIMPLE_PROPERTY | NAME_VALUE_PROPERTY
+ -- OPTION_LIST ::= OPTION {, OPTION}
- -- SIMPLE_PROPERTY ::= IDENTIFIER
- -- NAME_VALUE_PROPERTY ::= IDENTIFIER => EXPRESSION
+ -- OPTION ::= SIMPLE_OPTION | NAME_VALUE_OPTION
- -- STATE_NAME ::= DEFINING_IDENTIFIER
+ -- SIMPLE_OPTION ::=
+ -- External | Non_Volatile | Input_Only | Output_Only
+
+ -- NAME_VALUE_OPTION ::= Part_Of => abstract_state_NAME
when Pragma_Abstract_State => Abstract_State : declare
Pack_Id : Entity_Id;
@@ -8315,46 +9285,47 @@ package body Sem_Prag is
----------------------------
procedure Analyze_Abstract_State (State : Node_Id) is
- procedure Check_Duplicate_Property
- (Prop : Node_Id;
+ procedure Check_Duplicate_Option
+ (Opt : Node_Id;
Status : in out Boolean);
- -- Flag Status denotes whether a particular property has been
+ -- Flag Status denotes whether a particular option has been
-- seen while processing a state. This routine verifies that
- -- Prop is not a duplicate property and sets the flag Status.
+ -- Opt is not a duplicate property and sets the flag Status.
- ------------------------------
- -- Check_Duplicate_Property --
- ------------------------------
+ ----------------------------
+ -- Check_Duplicate_Option --
+ ----------------------------
- procedure Check_Duplicate_Property
- (Prop : Node_Id;
+ procedure Check_Duplicate_Option
+ (Opt : Node_Id;
Status : in out Boolean)
is
begin
if Status then
- Error_Msg_N ("duplicate state property", Prop);
+ Error_Msg_N ("duplicate state option", Opt);
end if;
Status := True;
- end Check_Duplicate_Property;
+ end Check_Duplicate_Option;
-- Local variables
- Errors : constant Nat := Serious_Errors_Detected;
- Loc : constant Source_Ptr := Sloc (State);
- Assoc : Node_Id;
- Id : Entity_Id;
- Is_Null : Boolean := False;
- Level : Uint := Uint_0;
- Name : Name_Id;
- Prop : Node_Id;
+ Errors : constant Nat := Serious_Errors_Detected;
+ Loc : constant Source_Ptr := Sloc (State);
+ Assoc : Node_Id;
+ Id : Entity_Id;
+ Is_Null : Boolean := False;
+ Name : Name_Id;
+ Opt : Node_Id;
+ Par_State : Node_Id;
- -- Flags used to verify the consistency of properties
+ -- Flags used to verify the consistency of options
- Input_Seen : Boolean := False;
- Integrity_Seen : Boolean := False;
- Output_Seen : Boolean := False;
- Volatile_Seen : Boolean := False;
+ External_Seen : Boolean := False;
+ Input_Seen : Boolean := False;
+ Non_Volatile_Seen : Boolean := False;
+ Output_Seen : Boolean := False;
+ Part_Of_Seen : Boolean := False;
-- Start of processing for Analyze_Abstract_State
@@ -8370,7 +9341,7 @@ package body Sem_Prag is
elsif Nkind (State) = N_Null then
Name := New_Internal_Name ('S');
- Is_Null := True;
+ Is_Null := True;
Null_Seen := True;
-- Catch a case where a null state appears in a list of
@@ -8388,7 +9359,7 @@ package body Sem_Prag is
Name := Chars (State);
Non_Null_Seen := True;
- -- State declaration with various properties. This construct
+ -- State declaration with various options. This construct
-- appears as an extension aggregate in the tree.
elsif Nkind (State) = N_Extension_Aggregate then
@@ -8401,69 +9372,98 @@ package body Sem_Prag is
Ancestor_Part (State));
end if;
- -- Process properties Input, Output and Volatile. Ensure
- -- that none of them appear more than once.
-
- Prop := First (Expressions (State));
- while Present (Prop) loop
- if Nkind (Prop) = N_Identifier then
- if Chars (Prop) = Name_Input then
- Check_Duplicate_Property (Prop, Input_Seen);
- elsif Chars (Prop) = Name_Output then
- Check_Duplicate_Property (Prop, Output_Seen);
- elsif Chars (Prop) = Name_Volatile then
- Check_Duplicate_Property (Prop, Volatile_Seen);
+ -- Process options External, Input_Only, Output_Only and
+ -- Volatile. Ensure that none of them appear more than once.
+
+ Opt := First (Expressions (State));
+ while Present (Opt) loop
+ if Nkind (Opt) = N_Identifier then
+ if Chars (Opt) = Name_External then
+ Check_Duplicate_Option (Opt, External_Seen);
+ elsif Chars (Opt) = Name_Input_Only then
+ Check_Duplicate_Option (Opt, Input_Seen);
+ elsif Chars (Opt) = Name_Output_Only then
+ Check_Duplicate_Option (Opt, Output_Seen);
+ elsif Chars (Opt) = Name_Non_Volatile then
+ Check_Duplicate_Option (Opt, Non_Volatile_Seen);
+
+ -- Ensure that the abstract state component of option
+ -- Part_Of has not been omitted.
+
+ elsif Chars (Opt) = Name_Part_Of then
+ Error_Msg_N
+ ("option Part_Of requires an abstract state",
+ Opt);
else
- Error_Msg_N ("invalid state property", Prop);
+ Error_Msg_N ("invalid state option", Opt);
end if;
else
- Error_Msg_N ("invalid state property", Prop);
+ Error_Msg_N ("invalid state option", Opt);
end if;
- Next (Prop);
+ Next (Opt);
end loop;
- -- Volatile requires exactly one Input or Output
+ -- External may appear on its own or with exactly one option
+ -- Input_Only or Output_Only, but not both.
- if Volatile_Seen and then Input_Seen = Output_Seen then
+ if External_Seen
+ and then Input_Seen
+ and then Output_Seen
+ then
Error_Msg_N
- ("property Volatile requires exactly one Input or "
- & "Output", State);
+ ("option External requires exactly one option "
+ & "Input_Only or Output_Only", State);
end if;
- -- Either Input or Output require Volatile
+ -- Either Input_Only or Output_Only require External
if (Input_Seen or Output_Seen)
- and then not Volatile_Seen
+ and then not External_Seen
then
Error_Msg_N
- ("properties Input and Output require Volatile", State);
+ ("options Input_Only and Output_Only require option "
+ & "External", State);
end if;
- -- State property Integrity appears as a component
- -- association.
+ -- Option Part_Of appears as a component association
Assoc := First (Component_Associations (State));
while Present (Assoc) loop
- Prop := First (Choices (Assoc));
- while Present (Prop) loop
- if Nkind (Prop) = N_Identifier
- and then Chars (Prop) = Name_Integrity
+ Opt := First (Choices (Assoc));
+ while Present (Opt) loop
+ if Nkind (Opt) = N_Identifier
+ and then Chars (Opt) = Name_Part_Of
then
- Check_Duplicate_Property (Prop, Integrity_Seen);
+ Check_Duplicate_Option (Opt, Part_Of_Seen);
else
- Error_Msg_N ("invalid state property", Prop);
+ Error_Msg_N ("invalid state option", Opt);
end if;
- Next (Prop);
+ Next (Opt);
end loop;
- if Nkind (Expression (Assoc)) = N_Integer_Literal then
- Level := Intval (Expression (Assoc));
+ -- Part_Of must denote a parent state. Ensure that the
+ -- tree is not malformed by checking the expression of
+ -- the component association.
+
+ Par_State := Expression (Assoc);
+ pragma Assert (Present (Par_State));
+
+ Analyze (Par_State);
+
+ -- Part_Of specified a legal state, this automatically
+ -- makes the state a constituent.
+
+ if Is_Entity_Name (Par_State)
+ and then Present (Entity (Par_State))
+ and then Ekind (Entity (Par_State)) = E_Abstract_State
+ then
+ null;
else
Error_Msg_N
- ("integrity level must be an integer literal",
- Expression (Assoc));
+ ("option Part_Of must denote an abstract state",
+ Par_State);
end if;
Next (Assoc);
@@ -8486,12 +9486,12 @@ package body Sem_Prag is
-- from the original state declaration. Decorate the entity.
Id := Make_Defining_Identifier (Loc, New_External_Name (Name));
- Set_Comes_From_Source (Id, not Is_Null);
- Set_Parent (Id, State);
- Set_Ekind (Id, E_Abstract_State);
- Set_Etype (Id, Standard_Void_Type);
- Set_Integrity_Level (Id, Level);
- Set_Refined_State (Id, Empty);
+ Set_Comes_From_Source (Id, not Is_Null);
+ Set_Parent (Id, State);
+ Set_Ekind (Id, E_Abstract_State);
+ Set_Etype (Id, Standard_Void_Type);
+ Set_Refined_State (Id, Empty);
+ Set_Refinement_Constituents (Id, New_Elmt_List);
-- Every non-null state must be nameable and resolvable the
-- same way a constant is.
@@ -8520,8 +9520,8 @@ package body Sem_Prag is
-- Local variables
- Par : Node_Id;
- State : Node_Id;
+ Context : constant Node_Id := Parent (Parent (N));
+ State : Node_Id;
-- Start of processing for Abstract_State
@@ -8533,25 +9533,24 @@ package body Sem_Prag is
-- Ensure the proper placement of the pragma. Abstract states must
-- be associated with a package declaration.
- if From_Aspect_Specification (N) then
- Par := Parent (Corresponding_Aspect (N));
- else
- Par := Parent (Parent (N));
- end if;
-
- if Nkind (Par) = N_Compilation_Unit then
- Par := Unit (Par);
- end if;
-
- if not Nkind_In (Par, N_Generic_Package_Declaration,
- N_Package_Declaration)
+ if not Nkind_In (Context, N_Generic_Package_Declaration,
+ N_Package_Declaration)
then
Pragma_Misplaced;
return;
end if;
- Pack_Id := Defining_Entity (Par);
- State := Expression (Arg1);
+ Pack_Id := Defining_Entity (Context);
+ Add_Contract_Item (N, Pack_Id);
+
+ -- Verify the declaration order of pragmas Abstract_State and
+ -- Initializes.
+
+ Check_Declaration_Order
+ (First => N,
+ Second => Get_Pragma (Pack_Id, Pragma_Initializes));
+
+ State := Expression (Arg1);
-- Multiple abstract states appear as an aggregate
@@ -8962,13 +9961,15 @@ package body Sem_Prag is
-- Assume |
-- Contract_Cases |
-- Debug |
+ -- Initial_Condition |
-- Loop_Invariant |
-- Loop_Variant |
-- Postcondition |
-- Precondition |
-- Predicate |
+ -- Refined_Post |
-- Statement_Assertions
- --
+
-- Note: The RM_ASSERTION_KIND list is language-defined, and the
-- ID_ASSERTION_KIND list contains implementation-defined additions
-- recognized by GNAT. The effect is to control the behavior of
@@ -9634,7 +10635,7 @@ package body Sem_Prag is
if Is_Checked (N) and then not Split_PPC (N) then
- -- Mark pragma/aspect SCO as enabled
+ -- Mark aspect/pragma SCO as enabled
Set_SCO_Pragma_Enabled (Loc);
end if;
@@ -10110,9 +11111,7 @@ package body Sem_Prag is
-- Contract_Cases --
--------------------
- -- pragma Contract_Cases (CONTRACT_CASE_LIST);
-
- -- CONTRACT_CASE_LIST ::= CONTRACT_CASE {, CONTRACT_CASE}
+ -- pragma Contract_Cases ((CONTRACT_CASE {, CONTRACT_CASE));
-- CONTRACT_CASE ::= CASE_GUARD => CONSEQUENCE
@@ -10122,17 +11121,22 @@ package body Sem_Prag is
when Pragma_Contract_Cases => Contract_Cases : declare
Subp_Decl : Node_Id;
- Subp_Id : Entity_Id;
begin
GNAT_Pragma;
Check_Arg_Count (1);
+ -- The pragma is analyzed at the end of the declarative part which
+ -- contains the related subprogram. Reset the analyzed flag.
+
+ Set_Analyzed (N, False);
+
-- Ensure the proper placement of the pragma. Contract_Cases must
-- be associated with a subprogram declaration or a body that acts
-- as a spec.
- Subp_Decl := Find_Related_Subprogram (N, Check_Duplicates => True);
+ Subp_Decl :=
+ Find_Related_Subprogram_Or_Body (N, Do_Checks => True);
if Nkind (Subp_Decl) /= N_Subprogram_Declaration
and then (Nkind (Subp_Decl) /= N_Subprogram_Body
@@ -10142,15 +11146,8 @@ package body Sem_Prag is
return;
end if;
- Subp_Id := Defining_Unit_Name (Specification (Subp_Decl));
-
- -- The pragma is analyzed at the end of the declarative part which
- -- contains the related subprogram. Reset the analyzed flag.
-
- Set_Analyzed (N, False);
-
- -- When the aspect/pragma appears on a subprogram body, perform
- -- the full analysis now.
+ -- When the pragma appears on a subprogram body, perform the full
+ -- analysis now.
if Nkind (Subp_Decl) = N_Subprogram_Body then
Analyze_Contract_Cases_In_Decl_Part (N);
@@ -10167,7 +11164,7 @@ package body Sem_Prag is
-- Chain the pragma on the contract for further processing
- Add_Contract_Item (N, Subp_Id);
+ Add_Contract_Item (N, Defining_Entity (Subp_Decl));
end Contract_Cases;
----------------
@@ -10642,7 +11639,6 @@ package body Sem_Prag is
when Pragma_Depends => Depends : declare
Subp_Decl : Node_Id;
- Subp_Id : Entity_Id;
begin
GNAT_Pragma;
@@ -10653,7 +11649,8 @@ package body Sem_Prag is
-- associated with a subprogram declaration or a body that acts
-- as a spec.
- Subp_Decl := Find_Related_Subprogram (N, Check_Duplicates => True);
+ Subp_Decl :=
+ Find_Related_Subprogram_Or_Body (N, Do_Checks => True);
if Nkind (Subp_Decl) /= N_Subprogram_Declaration
and then (Nkind (Subp_Decl) /= N_Subprogram_Body
@@ -10663,10 +11660,8 @@ package body Sem_Prag is
return;
end if;
- Subp_Id := Defining_Unit_Name (Specification (Subp_Decl));
-
- -- When the aspect/pragma appears on a subprogram body, perform
- -- the full analysis now.
+ -- When the pragma appears on a subprogram body, perform the full
+ -- analysis now.
if Nkind (Subp_Decl) = N_Subprogram_Body then
Analyze_Depends_In_Decl_Part (N);
@@ -10683,7 +11678,7 @@ package body Sem_Prag is
-- Chain the pragma on the contract for further processing
- Add_Contract_Item (N, Subp_Id);
+ Add_Contract_Item (N, Defining_Entity (Subp_Decl));
end Depends;
---------------------
@@ -11216,7 +12211,6 @@ package body Sem_Prag is
Name_Link_Name));
Check_At_Least_N_Arguments (2);
-
Check_At_Most_N_Arguments (4);
Process_Convention (C, Def_Id);
@@ -11879,7 +12873,7 @@ package body Sem_Prag is
-- Global --
------------
- -- pragma Global (GLOBAL_SPECIFICATION)
+ -- pragma Global (GLOBAL_SPECIFICATION);
-- GLOBAL_SPECIFICATION ::=
-- null
@@ -11888,13 +12882,12 @@ package body Sem_Prag is
-- MODED_GLOBAL_LIST ::= MODE_SELECTOR => GLOBAL_LIST
- -- MODE_SELECTOR ::= Input | Output | In_Out | Contract_In
+ -- MODE_SELECTOR ::= In_Out | Input | Output | Proof_In
-- GLOBAL_LIST ::= GLOBAL_ITEM | (GLOBAL_ITEM {, GLOBAL_ITEM})
-- GLOBAL_ITEM ::= NAME
when Pragma_Global => Global : declare
Subp_Decl : Node_Id;
- Subp_Id : Entity_Id;
begin
GNAT_Pragma;
@@ -11905,7 +12898,8 @@ package body Sem_Prag is
-- associated with a subprogram declaration or a body that acts
-- as a spec.
- Subp_Decl := Find_Related_Subprogram (N, Check_Duplicates => True);
+ Subp_Decl :=
+ Find_Related_Subprogram_Or_Body (N, Do_Checks => True);
if Nkind (Subp_Decl) /= N_Subprogram_Declaration
and then (Nkind (Subp_Decl) /= N_Subprogram_Body
@@ -11915,10 +12909,8 @@ package body Sem_Prag is
return;
end if;
- Subp_Id := Defining_Unit_Name (Specification (Subp_Decl));
-
- -- When the aspect/pragma appears on a subprogram body, perform
- -- the full analysis now.
+ -- When the pragma appears on a subprogram body, perform the full
+ -- analysis now.
if Nkind (Subp_Decl) = N_Subprogram_Body then
Analyze_Global_In_Decl_Part (N);
@@ -11935,7 +12927,7 @@ package body Sem_Prag is
-- Chain the pragma on the contract for further processing
- Add_Contract_Item (N, Subp_Id);
+ Add_Contract_Item (N, Defining_Entity (Subp_Decl));
end Global;
-----------
@@ -12617,6 +13609,80 @@ package body Sem_Prag is
end if;
end Independent_Components;
+ -----------------------
+ -- Initial_Condition --
+ -----------------------
+
+ -- pragma Initial_Condition (boolean_EXPRESSION);
+
+ when Pragma_Initial_Condition => Initial_Condition : declare
+ Context : constant Node_Id := Parent (Parent (N));
+ Pack_Id : Entity_Id;
+ Stmt : Node_Id;
+
+ begin
+ GNAT_Pragma;
+ S14_Pragma;
+ Check_Arg_Count (1);
+
+ -- Ensure the proper placement of the pragma. Initial_Condition
+ -- must be associated with a package declaration.
+
+ if not Nkind_In (Context, N_Generic_Package_Declaration,
+ N_Package_Declaration)
+ then
+ Pragma_Misplaced;
+ return;
+ end if;
+
+ Stmt := Prev (N);
+ while Present (Stmt) loop
+
+ -- Skip prior pragmas, but check for duplicates
+
+ if Nkind (Stmt) = N_Pragma then
+ if Pragma_Name (Stmt) = Pname then
+ Error_Msg_Name_1 := Pname;
+ Error_Msg_Sloc := Sloc (Stmt);
+ Error_Msg_N ("pragma % duplicates pragma declared #", N);
+ end if;
+
+ -- Skip internally generated code
+
+ elsif not Comes_From_Source (Stmt) then
+ null;
+
+ -- The pragma does not apply to a legal construct, issue an
+ -- error and stop the analysis.
+
+ else
+ Pragma_Misplaced;
+ return;
+ end if;
+
+ Stmt := Prev (Stmt);
+ end loop;
+
+ -- The pragma must be analyzed at the end of the visible
+ -- declarations of the related package. Save the pragma for later
+ -- (see Analyze_Initial_Condition_In_Decl_Part) by adding it to
+ -- the contract of the package.
+
+ Pack_Id := Defining_Entity (Context);
+ Add_Contract_Item (N, Pack_Id);
+
+ -- Verify the declaration order of pragma Initial_Condition with
+ -- respect to pragmas Abstract_State and Initializes.
+
+ Check_Declaration_Order
+ (First => Get_Pragma (Pack_Id, Pragma_Abstract_State),
+ Second => N);
+
+ Check_Declaration_Order
+ (First => Get_Pragma (Pack_Id, Pragma_Initializes),
+ Second => N);
+ end Initial_Condition;
+
------------------------
-- Initialize_Scalars --
------------------------
@@ -12640,6 +13706,91 @@ package body Sem_Prag is
Initialize_Scalars := True;
end if;
+ -----------------
+ -- Initializes --
+ -----------------
+
+ -- pragma Initializes (INITIALIZATION_SPEC);
+
+ -- INITIALIZATION_SPEC ::= null | INITIALIZATION_LIST
+
+ -- INITIALIZATION_LIST ::=
+ -- INITIALIZATION_ITEM
+ -- | (INITIALIZATION_ITEM {, INITIALIZATION_ITEM})
+
+ -- INITIALIZATION_ITEM ::= name [=> INPUT_LIST]
+
+ -- INPUT_LIST ::=
+ -- null
+ -- | INPUT
+ -- | (INPUT {, INPUT})
+
+ -- INPUT ::= name
+
+ when Pragma_Initializes => Initializes : declare
+ Context : constant Node_Id := Parent (Parent (N));
+ Pack_Id : Entity_Id;
+ Stmt : Node_Id;
+
+ begin
+ GNAT_Pragma;
+ S14_Pragma;
+ Check_Arg_Count (1);
+
+ -- Ensure the proper placement of the pragma. Initializes must be
+ -- associated with a package declaration.
+
+ if not Nkind_In (Context, N_Generic_Package_Declaration,
+ N_Package_Declaration)
+ then
+ Pragma_Misplaced;
+ return;
+ end if;
+
+ Stmt := Prev (N);
+ while Present (Stmt) loop
+
+ -- Skip prior pragmas, but check for duplicates
+
+ if Nkind (Stmt) = N_Pragma then
+ if Pragma_Name (Stmt) = Pname then
+ Error_Msg_Name_1 := Pname;
+ Error_Msg_Sloc := Sloc (Stmt);
+ Error_Msg_N ("pragma % duplicates pragma declared #", N);
+ end if;
+
+ -- Skip internally generated code
+
+ elsif not Comes_From_Source (Stmt) then
+ null;
+
+ -- The pragma does not apply to a legal construct, issue an
+ -- error and stop the analysis.
+
+ else
+ Pragma_Misplaced;
+ return;
+ end if;
+
+ Stmt := Prev (Stmt);
+ end loop;
+
+ -- The pragma must be analyzed at the end of the visible
+ -- declarations of the related package. Save the pragma for later
+ -- (see Analyze_Initializes_In_Decl_Part) by adding it to the
+ -- contract of the package.
+
+ Pack_Id := Defining_Entity (Context);
+ Add_Contract_Item (N, Pack_Id);
+
+ -- Verify the declaration order of pragmas Abstract_State and
+ -- Initializes.
+
+ Check_Declaration_Order
+ (First => Get_Pragma (Pack_Id, Pragma_Abstract_State),
+ Second => N);
+ end Initializes;
+
------------
-- Inline --
------------
@@ -13075,7 +14226,7 @@ package body Sem_Prag is
begin
GNAT_Pragma;
Check_At_Least_N_Arguments (2);
- Check_At_Most_N_Arguments (3);
+ Check_At_Most_N_Arguments (3);
Check_Optional_Identifier (Arg1, Name_Entity);
Check_Optional_Identifier (Arg2, Name_Check);
@@ -13736,10 +14887,13 @@ package body Sem_Prag is
Check_Arg_Is_Library_Level_Local_Name (Arg1);
Check_Arg_Is_Static_Expression (Arg2, Standard_String);
- -- This pragma applies only to objects
+ -- This pragma applies to objects and types
- if not Is_Object (Entity (Get_Pragma_Arg (Arg1))) then
- Error_Pragma_Arg ("pragma% applies only to objects", Arg1);
+ if not Is_Object (Entity (Get_Pragma_Arg (Arg1)))
+ and then not Is_Type (Entity (Get_Pragma_Arg (Arg1)))
+ then
+ Error_Pragma_Arg
+ ("pragma% applies only to objects and types", Arg1);
end if;
-- The only processing required is to link this item on to the
@@ -14672,7 +15826,7 @@ package body Sem_Prag is
begin
GNAT_Pragma;
Check_At_Least_N_Arguments (1);
- Check_At_Most_N_Arguments (2);
+ Check_At_Most_N_Arguments (2);
-- Process first argument
@@ -15044,6 +16198,34 @@ package body Sem_Prag is
Check_Arg_Is_One_Of (Arg1, Name_On, Name_Off);
Polling_Required := (Chars (Get_Pragma_Arg (Arg1)) = Name_On);
+ ------------------
+ -- Post[_Class] --
+ ------------------
+
+ -- pragma Post (Boolean_EXPRESSION);
+ -- pragma Post_Class (Boolean_EXPRESSION);
+
+ when Pragma_Post | Pragma_Post_Class => Post : declare
+ PC_Pragma : Node_Id;
+
+ begin
+ GNAT_Pragma;
+ Check_Arg_Count (1);
+ Check_No_Identifiers;
+ Check_Pre_Post;
+
+ -- Rewrite Post[_Class] pragma as Precondition pragma setting the
+ -- flag Class_Present to True for the Post_Class case.
+
+ Set_Class_Present (N, Prag_Id = Pragma_Pre_Class);
+ PC_Pragma := New_Copy (N);
+ Set_Pragma_Identifier
+ (PC_Pragma, Make_Identifier (Loc, Name_Postcondition));
+ Rewrite (N, PC_Pragma);
+ Set_Analyzed (N, False);
+ Analyze (N);
+ end Post;
+
-------------------
-- Postcondition --
-------------------
@@ -15078,6 +16260,34 @@ package body Sem_Prag is
end if;
end Postcondition;
+ -----------------
+ -- Pre[_Class] --
+ -----------------
+
+ -- pragma Pre (Boolean_EXPRESSION);
+ -- pragma Pre_Class (Boolean_EXPRESSION);
+
+ when Pragma_Pre | Pragma_Pre_Class => Pre : declare
+ PC_Pragma : Node_Id;
+
+ begin
+ GNAT_Pragma;
+ Check_Arg_Count (1);
+ Check_No_Identifiers;
+ Check_Pre_Post;
+
+ -- Rewrite Pre[_Class] pragma as Precondition pragma setting the
+ -- flag Class_Present to True for the Pre_Class case.
+
+ Set_Class_Present (N, Prag_Id = Pragma_Pre_Class);
+ PC_Pragma := New_Copy (N);
+ Set_Pragma_Identifier
+ (PC_Pragma, Make_Identifier (Loc, Name_Precondition));
+ Rewrite (N, PC_Pragma);
+ Set_Analyzed (N, False);
+ Analyze (N);
+ end Pre;
+
------------------
-- Precondition --
------------------
@@ -15091,7 +16301,7 @@ package body Sem_Prag is
begin
GNAT_Pragma;
Check_At_Least_N_Arguments (1);
- Check_At_Most_N_Arguments (2);
+ Check_At_Most_N_Arguments (2);
Check_Optional_Identifier (Arg1, Name_Check);
Check_Precondition_Postcondition (In_Body);
@@ -15318,16 +16528,24 @@ package body Sem_Prag is
Set_Main_Priority
(Current_Sem_Unit, UI_To_Int (Expr_Value (Arg)));
- -- Load an arbitrary entity from System.Tasking to make sure
- -- this package is implicitly with'ed, since we need to have
- -- the tasking run-time active for the pragma Priority to have
- -- any effect.
+ -- Load an arbitrary entity from System.Tasking.Stages or
+ -- System.Tasking.Restricted.Stages (depending on the
+ -- supported profile) to make sure that one of these packages
+ -- is implicitly with'ed, since we need to have the tasking
+ -- run time active for the pragma Priority to have any effect.
+ -- Previously with with'ed the package System.Tasking, but
+ -- this package does not trigger the required initialization
+ -- of the run-time library.
declare
Discard : Entity_Id;
pragma Warnings (Off, Discard);
begin
- Discard := RTE (RE_Task_List);
+ if Restricted_Profile then
+ Discard := RTE (RE_Activate_Restricted_Tasks);
+ else
+ Discard := RTE (RE_Activate_Tasks);
+ end if;
end;
-- Task or Protected, must be of type Integer
@@ -15929,6 +17147,171 @@ package body Sem_Prag is
when Pragma_Rational =>
Set_Rational_Profile;
+ ------------------------------------
+ -- Refined_Depends/Refined_Global --
+ ------------------------------------
+
+ -- pragma Refined_Depends (DEPENDENCY_RELATION);
+
+ -- DEPENDENCY_RELATION ::=
+ -- null
+ -- | DEPENDENCY_CLAUSE {, DEPENDENCY_CLAUSE}
+
+ -- DEPENDENCY_CLAUSE ::=
+ -- OUTPUT_LIST =>[+] INPUT_LIST
+ -- | NULL_DEPENDENCY_CLAUSE
+
+ -- NULL_DEPENDENCY_CLAUSE ::= null => INPUT_LIST
+
+ -- OUTPUT_LIST ::= OUTPUT | (OUTPUT {, OUTPUT})
+
+ -- INPUT_LIST ::= null | INPUT | (INPUT {, INPUT})
+
+ -- OUTPUT ::= NAME | FUNCTION_RESULT
+ -- INPUT ::= NAME
+
+ -- where FUNCTION_RESULT is a function Result attribute_reference
+
+ -- pragma Refined_Global (GLOBAL_SPECIFICATION);
+
+ -- GLOBAL_SPECIFICATION ::=
+ -- null
+ -- | GLOBAL_LIST
+ -- | MODED_GLOBAL_LIST {, MODED_GLOBAL_LIST}
+
+ -- MODED_GLOBAL_LIST ::= MODE_SELECTOR => GLOBAL_LIST
+
+ -- MODE_SELECTOR ::= In_Out | Input | Output | Proof_In
+ -- GLOBAL_LIST ::= GLOBAL_ITEM | (GLOBAL_ITEM {, GLOBAL_ITEM})
+ -- GLOBAL_ITEM ::= NAME
+
+ when Pragma_Refined_Depends |
+ Pragma_Refined_Global => Refined_Depends_Global :
+ declare
+ Body_Id : Entity_Id;
+ Legal : Boolean;
+ Spec_Id : Entity_Id;
+
+ begin
+ Analyze_Refined_Pragma (Spec_Id, Body_Id, Legal);
+
+ -- Save the pragma in the contract of the subprogram body. The
+ -- remaining analysis is performed at the end of the enclosing
+ -- declarations.
+
+ if Legal then
+ Add_Contract_Item (N, Body_Id);
+ end if;
+ end Refined_Depends_Global;
+
+ ------------------
+ -- Refined_Post --
+ ------------------
+
+ -- pragma Refined_Post (boolean_EXPRESSION);
+
+ when Pragma_Refined_Post => Refined_Post : declare
+ Body_Id : Entity_Id;
+ Legal : Boolean;
+ Spec_Id : Entity_Id;
+
+ begin
+ Analyze_Refined_Pragma (Spec_Id, Body_Id, Legal);
+
+ -- Analyze the boolean expression as a "spec expression"
+
+ if Legal then
+ Analyze_Pre_Post_Condition_In_Decl_Part (N, Spec_Id);
+ end if;
+ end Refined_Post;
+
+ -------------------
+ -- Refined_State --
+ -------------------
+
+ -- pragma Refined_State (REFINEMENT_LIST);
+
+ -- REFINEMENT_LIST ::=
+ -- REFINEMENT_CLAUSE
+ -- | (REFINEMENT_CLAUSE {, REFINEMENT_CLAUSE})
+
+ -- REFINEMENT_CLAUSE ::= state_NAME => CONSTITUENT_LIST
+
+ -- CONSTITUENT_LIST ::=
+ -- null
+ -- | CONSTITUENT
+ -- | (CONSTITUENT {, CONSTITUENT})
+
+ -- CONSTITUENT ::= object_NAME | state_NAME
+
+ when Pragma_Refined_State => Refined_State : declare
+ Context : constant Node_Id := Parent (N);
+ Spec_Id : Entity_Id;
+ Stmt : Node_Id;
+
+ begin
+ GNAT_Pragma;
+ S14_Pragma;
+ Check_Arg_Count (1);
+
+ -- Ensure the proper placement of the pragma. Refined states must
+ -- be associated with a package body.
+
+ if Nkind (Context) /= N_Package_Body then
+ Pragma_Misplaced;
+ return;
+ end if;
+
+ Stmt := Prev (N);
+ while Present (Stmt) loop
+
+ -- Skip prior pragmas, but check for duplicates
+
+ if Nkind (Stmt) = N_Pragma then
+ if Pragma_Name (Stmt) = Pname then
+ Error_Msg_Name_1 := Pname;
+ Error_Msg_Sloc := Sloc (Stmt);
+ Error_Msg_N ("pragma % duplicates pragma declared #", N);
+ end if;
+
+ -- Skip internally generated code
+
+ elsif not Comes_From_Source (Stmt) then
+ null;
+
+ -- The pragma does not apply to a legal construct, issue an
+ -- error and stop the analysis.
+
+ else
+ Pragma_Misplaced;
+ return;
+ end if;
+
+ Stmt := Prev (Stmt);
+ end loop;
+
+ -- State refinement is allowed only when the corresponding package
+ -- declaration has a non-null pragma Abstract_State.
+
+ Spec_Id := Corresponding_Spec (Context);
+
+ if No (Abstract_States (Spec_Id))
+ or else Has_Null_Abstract_State (Spec_Id)
+ then
+ Error_Msg_NE
+ ("useless refinement, package & does not define abstract "
+ & "states", N, Spec_Id);
+ return;
+ end if;
+
+ -- The pragma must be analyzed at the end of the declarations as
+ -- it has visibility over the whole declarative region. Save the
+ -- pragma for later (see Analyze_Refined_Depends_In_Decl_Part) by
+ -- adding it to the contract of the package body.
+
+ Add_Contract_Item (N, Defining_Entity (Context));
+ end Refined_State;
+
-----------------------
-- Relative_Deadline --
-----------------------
@@ -16285,7 +17668,7 @@ package body Sem_Prag is
-- in Freeze_Entity).
if Is_Record_Type (Typ)
- and then not Is_Immutably_Limited_Type (Typ)
+ and then not Is_Limited_View (Typ)
then
Error_Pragma
("pragma% can only apply to explicitly limited record type");
@@ -17467,6 +18850,34 @@ package body Sem_Prag is
end loop;
end Title;
+ ----------------------------
+ -- Type_Invariant[_Class] --
+ ----------------------------
+
+ -- pragma Type_Invariant[_Class]
+ -- ([Entity =>] type_LOCAL_NAME,
+ -- [Check =>] EXPRESSION);
+
+ when Pragma_Type_Invariant |
+ Pragma_Type_Invariant_Class =>
+ Type_Invariant : declare
+ I_Pragma : Node_Id;
+
+ begin
+ Check_Arg_Count (2);
+
+ -- Rewrite Type_Invariant[_Class] pragma as an Invariant pragma,
+ -- setting Class_Present for the Type_Invariant_Class case.
+
+ Set_Class_Present (N, Prag_Id = Pragma_Type_Invariant_Class);
+ I_Pragma := New_Copy (N);
+ Set_Pragma_Identifier
+ (I_Pragma, Make_Identifier (Loc, Name_Invariant));
+ Rewrite (N, I_Pragma);
+ Set_Analyzed (N, False);
+ Analyze (N);
+ end Type_Invariant;
+
---------------------
-- Unchecked_Union --
---------------------
@@ -18260,6 +19671,2233 @@ package body Sem_Prag is
when Pragma_Exit => null;
end Analyze_Pragma;
+ ---------------------------------------------
+ -- Analyze_Pre_Post_Condition_In_Decl_Part --
+ ---------------------------------------------
+
+ procedure Analyze_Pre_Post_Condition_In_Decl_Part
+ (Prag : Node_Id;
+ Subp_Id : Entity_Id)
+ is
+ Arg1 : constant Node_Id := First (Pragma_Argument_Associations (Prag));
+ Nam : constant Name_Id := Original_Aspect_Name (Prag);
+ Expr : Node_Id;
+
+ Restore_Scope : Boolean := False;
+ -- Gets set True if we do a Push_Scope needing a Pop_Scope on exit
+
+ begin
+ -- Ensure that the subprogram and its formals are visible when analyzing
+ -- the expression of the pragma.
+
+ if not In_Open_Scopes (Subp_Id) then
+ Restore_Scope := True;
+ Push_Scope (Subp_Id);
+ Install_Formals (Subp_Id);
+ end if;
+
+ -- Preanalyze the boolean expression, we treat this as a spec expression
+ -- (i.e. similar to a default expression).
+
+ Expr := Get_Pragma_Arg (Arg1);
+
+ -- In ASIS mode, for a pragma generated from a source aspect, analyze
+ -- the original aspect expression, which is shared with the generated
+ -- pragma.
+
+ if ASIS_Mode and then Present (Corresponding_Aspect (Prag)) then
+ Expr := Expression (Corresponding_Aspect (Prag));
+ end if;
+
+ Preanalyze_Assert_Expression (Expr, Standard_Boolean);
+
+ -- For a class-wide condition, a reference to a controlling formal must
+ -- be interpreted as having the class-wide type (or an access to such)
+ -- so that the inherited condition can be properly applied to any
+ -- overriding operation (see ARM12 6.6.1 (7)).
+
+ if Class_Present (Prag) then
+ Class_Wide_Condition : declare
+ T : constant Entity_Id := Find_Dispatching_Type (Subp_Id);
+
+ ACW : Entity_Id := Empty;
+ -- Access to T'class, created if there is a controlling formal
+ -- that is an access parameter.
+
+ function Get_ACW return Entity_Id;
+ -- If the expression has a reference to an controlling access
+ -- parameter, create an access to T'class for the necessary
+ -- conversions if one does not exist.
+
+ function Process (N : Node_Id) return Traverse_Result;
+ -- ARM 6.1.1: Within the expression for a Pre'Class or Post'Class
+ -- aspect for a primitive subprogram of a tagged type T, a name
+ -- that denotes a formal parameter of type T is interpreted as
+ -- having type T'Class. Similarly, a name that denotes a formal
+ -- accessparameter of type access-to-T is interpreted as having
+ -- type access-to-T'Class. This ensures the expression is well-
+ -- defined for a primitive subprogram of a type descended from T.
+ -- Note that this replacement is not done for selector names in
+ -- parameter associations. These carry an entity for reference
+ -- purposes, but semantically they are just identifiers.
+
+ -------------
+ -- Get_ACW --
+ -------------
+
+ function Get_ACW return Entity_Id is
+ Loc : constant Source_Ptr := Sloc (Prag);
+ Decl : Node_Id;
+
+ begin
+ if No (ACW) then
+ Decl :=
+ Make_Full_Type_Declaration (Loc,
+ Defining_Identifier => Make_Temporary (Loc, 'T'),
+ Type_Definition =>
+ Make_Access_To_Object_Definition (Loc,
+ Subtype_Indication =>
+ New_Occurrence_Of (Class_Wide_Type (T), Loc),
+ All_Present => True));
+
+ Insert_Before (Unit_Declaration_Node (Subp_Id), Decl);
+ Analyze (Decl);
+ ACW := Defining_Identifier (Decl);
+ Freeze_Before (Unit_Declaration_Node (Subp_Id), ACW);
+ end if;
+
+ return ACW;
+ end Get_ACW;
+
+ -------------
+ -- Process --
+ -------------
+
+ function Process (N : Node_Id) return Traverse_Result is
+ Loc : constant Source_Ptr := Sloc (N);
+ Typ : Entity_Id;
+
+ begin
+ if Is_Entity_Name (N)
+ and then Present (Entity (N))
+ and then Is_Formal (Entity (N))
+ and then Nkind (Parent (N)) /= N_Type_Conversion
+ and then
+ (Nkind (Parent (N)) /= N_Parameter_Association
+ or else N /= Selector_Name (Parent (N)))
+ then
+ if Etype (Entity (N)) = T then
+ Typ := Class_Wide_Type (T);
+
+ elsif Is_Access_Type (Etype (Entity (N)))
+ and then Designated_Type (Etype (Entity (N))) = T
+ then
+ Typ := Get_ACW;
+ else
+ Typ := Empty;
+ end if;
+
+ if Present (Typ) then
+ Rewrite (N,
+ Make_Type_Conversion (Loc,
+ Subtype_Mark =>
+ New_Occurrence_Of (Typ, Loc),
+ Expression => New_Occurrence_Of (Entity (N), Loc)));
+ Set_Etype (N, Typ);
+ end if;
+ end if;
+
+ return OK;
+ end Process;
+
+ procedure Replace_Type is new Traverse_Proc (Process);
+
+ -- Start of processing for Class_Wide_Condition
+
+ begin
+ if not Present (T) then
+
+ -- Pre'Class/Post'Class aspect cases
+
+ if From_Aspect_Specification (Prag) then
+ if Nam = Name_uPre then
+ Error_Msg_Name_1 := Name_Pre;
+ else
+ Error_Msg_Name_1 := Name_Post;
+ end if;
+
+ Error_Msg_Name_2 := Name_Class;
+
+ Error_Msg_N
+ ("aspect `%''%` can only be specified for a primitive "
+ & "operation of a tagged type",
+ Corresponding_Aspect (Prag));
+
+ -- Pre_Class, Post_Class pragma cases
+
+ else
+ if Nam = Name_uPre then
+ Error_Msg_Name_1 := Name_Pre_Class;
+ else
+ Error_Msg_Name_1 := Name_Post_Class;
+ end if;
+
+ Error_Msg_N
+ ("pragma% can only be specified for a primitive "
+ & "operation of a tagged type",
+ Corresponding_Aspect (Prag));
+ end if;
+ end if;
+
+ Replace_Type (Get_Pragma_Arg (Arg1));
+ end Class_Wide_Condition;
+ end if;
+
+ -- Remove the subprogram from the scope stack now that the pre-analysis
+ -- of the precondition/postcondition is done.
+
+ if Restore_Scope then
+ End_Scope;
+ end if;
+ end Analyze_Pre_Post_Condition_In_Decl_Part;
+
+ ------------------------------------------
+ -- Analyze_Refined_Depends_In_Decl_Part --
+ ------------------------------------------
+
+ procedure Analyze_Refined_Depends_In_Decl_Part (N : Node_Id) is
+ Dependencies : List_Id := No_List;
+ Depends : Node_Id;
+ -- The corresponding Depends pragma along with its clauses
+
+ Global : Node_Id := Empty;
+ -- The corresponding Refined_Global pragma (if any)
+
+ Out_Items : Elist_Id := No_Elist;
+ -- All output items as defined in pragma Refined_Global (if any)
+
+ Refinements : List_Id := No_List;
+ -- The clauses of pragma Refined_Depends
+
+ Spec_Id : Entity_Id;
+ -- The entity of the subprogram subject to pragma Refined_Depends
+
+ procedure Check_Dependency_Clause (Dep_Clause : Node_Id);
+ -- Verify the legality of a single clause
+
+ procedure Report_Extra_Clauses;
+ -- Emit an error for each extra clause the appears in Refined_Depends
+
+ -----------------------------
+ -- Check_Dependency_Clause --
+ -----------------------------
+
+ procedure Check_Dependency_Clause (Dep_Clause : Node_Id) is
+ function Inputs_Match
+ (Ref_Clause : Node_Id;
+ Do_Checks : Boolean) return Boolean;
+ -- Determine whether the inputs of clause Dep_Clause match those of
+ -- clause Ref_Clause. If flag Do_Checks is set, the routine reports
+ -- missed or extra input items.
+
+ function Output_Constituents (State_Id : Entity_Id) return Elist_Id;
+ -- Given a state denoted by State_Id, return a list of all output
+ -- constituents that may be referenced within Refined_Depends. The
+ -- contents of the list depend on whethe Refined_Global is present.
+
+ procedure Report_Unused_Constituents (Constits : Elist_Id);
+ -- Emit errors for all constituents found in list Constits
+
+ ------------------
+ -- Inputs_Match --
+ ------------------
+
+ function Inputs_Match
+ (Ref_Clause : Node_Id;
+ Do_Checks : Boolean) return Boolean
+ is
+ Ref_Inputs : List_Id;
+ -- The input list of the refinement clause
+
+ function Is_Matching_Input (Dep_Input : Node_Id) return Boolean;
+ -- Determine whether input Dep_Input matches one of the inputs of
+ -- clause Ref_Clause.
+
+ procedure Report_Extra_Inputs;
+ -- Emit errors for all extra inputs that appear in Ref_Clause
+
+ -----------------------
+ -- Is_Matching_Input --
+ -----------------------
+
+ function Is_Matching_Input (Dep_Input : Node_Id) return Boolean is
+ procedure Match_Error (Msg : String; N : Node_Id);
+ -- Emit a matching error if flag Do_Checks is set
+
+ -----------------
+ -- Match_Error --
+ -----------------
+
+ procedure Match_Error (Msg : String; N : Node_Id) is
+ begin
+ if Do_Checks then
+ Error_Msg_N (Msg, N);
+ end if;
+ end Match_Error;
+
+ -- Local variables
+
+ Dep_Id : Node_Id;
+ Next_Ref_Input : Node_Id;
+ Ref_Id : Entity_Id;
+ Ref_Input : Node_Id;
+
+ Has_Constituent : Boolean := False;
+ -- Flag set when the refinement input list contains at least
+ -- one constituent of the state denoted by Dep_Id.
+
+ Has_Null_State : Boolean := False;
+ -- Flag set when the dependency input is a state with a null
+ -- refinement.
+
+ Has_Refined_State : Boolean := False;
+ -- Flag set when the dependency input is a state with visible
+ -- refinement.
+
+ -- Start of processing for Is_Matching_Input
+
+ begin
+ -- Match a null input with another null input
+
+ if Nkind (Dep_Input) = N_Null then
+ Ref_Input := First (Ref_Inputs);
+
+ -- Remove the matching null from the pool of candidates
+
+ if Nkind (Ref_Input) = N_Null then
+ Remove (Ref_Input);
+ return True;
+
+ else
+ Match_Error
+ ("null input cannot be matched in corresponding "
+ & "refinement clause", Dep_Input);
+ end if;
+
+ -- Remaining cases are formal parameters, variables, and states
+
+ else
+ Dep_Id := Entity_Of (Dep_Input);
+
+ -- Inspect all inputs of the refinement clause and attempt
+ -- to match against the inputs of the dependence clause.
+
+ Ref_Input := First (Ref_Inputs);
+ while Present (Ref_Input) loop
+
+ -- Store the next input now because a match will remove
+ -- it from the list.
+
+ Next_Ref_Input := Next (Ref_Input);
+
+ if Ekind (Dep_Id) = E_Abstract_State then
+
+ -- A state with a null refinement matches either a
+ -- null input list or nothing at all (no input):
+
+ -- Refined_State => (State => null)
+
+ -- No input
+
+ -- Depends => (<output> => (State, Input))
+ -- Refined_Depends => (<output> => Input) -- OK
+
+ -- Null input list
+
+ -- Depends => (<output> => State)
+ -- Refined_Depends => (<output> => null) -- OK
+
+ if Has_Null_Refinement (Dep_Id) then
+ Has_Null_State := True;
+
+ -- Remove the matching null from the pool of
+ -- candidates.
+
+ if Nkind (Ref_Input) = N_Null then
+ Remove (Ref_Input);
+ end if;
+
+ return True;
+
+ -- The state has a non-null refinement in which case
+ -- remove all the matching constituents of the state:
+
+ -- Refined_State => (State => (C1, C2))
+ -- Depends => (<output> => State)
+ -- Refined_Depends => (<output> => (C1, C2))
+
+ elsif Has_Non_Null_Refinement (Dep_Id) then
+ Has_Refined_State := True;
+
+ -- Ref_Input is an entity name
+
+ if Is_Entity_Name (Ref_Input) then
+ Ref_Id := Entity_Of (Ref_Input);
+
+ -- The input of the refinement clause is a valid
+ -- constituent of the state. Remove the input
+ -- from the pool of candidates. Note that the
+ -- search continues because the state may be
+ -- represented by multiple constituents.
+
+ if Ekind_In (Ref_Id, E_Abstract_State,
+ E_Variable)
+ and then Present (Refined_State (Ref_Id))
+ and then Refined_State (Ref_Id) = Dep_Id
+ then
+ Has_Constituent := True;
+ Remove (Ref_Input);
+ end if;
+ end if;
+ end if;
+
+ -- Formal parameters and variables are matched on
+ -- entities. If this is the case, remove the input from
+ -- the candidate list.
+
+ elsif Is_Entity_Name (Ref_Input)
+ and then Entity_Of (Ref_Input) = Dep_Id
+ then
+ Remove (Ref_Input);
+ return True;
+ end if;
+
+ Ref_Input := Next_Ref_Input;
+ end loop;
+
+ -- When a state with a null refinement appears as the last
+ -- input, it matches nothing:
+
+ -- Refined_State => (State => null)
+ -- Depends => (<output> => (Input, State))
+ -- Refined_Depends => (<output> => Input) -- OK
+
+ if Ekind (Dep_Id) = E_Abstract_State
+ and then Has_Null_Refinement (Dep_Id)
+ and then No (Ref_Input)
+ then
+ Has_Null_State := True;
+ end if;
+ end if;
+
+ -- A state with visible refinement was matched against one or
+ -- more of its constituents.
+
+ if Has_Constituent then
+ return True;
+
+ -- A state with a null refinement matched null or nothing
+
+ elsif Has_Null_State then
+ return True;
+
+ -- The input of a dependence clause does not have a matching
+ -- input in the refinement clause, emit an error.
+
+ else
+ Match_Error
+ ("input cannot be matched in corresponding refinement "
+ & "clause", Dep_Input);
+
+ if Has_Refined_State then
+ Match_Error
+ ("\check the use of constituents in dependence "
+ & "refinement", Dep_Input);
+ end if;
+
+ return False;
+ end if;
+ end Is_Matching_Input;
+
+ -------------------------
+ -- Report_Extra_Inputs --
+ -------------------------
+
+ procedure Report_Extra_Inputs is
+ Input : Node_Id;
+
+ begin
+ if Present (Ref_Inputs) and then Do_Checks then
+ Input := First (Ref_Inputs);
+ while Present (Input) loop
+ Error_Msg_N
+ ("unmatched or extra input in refinement clause",
+ Input);
+
+ Next (Input);
+ end loop;
+ end if;
+ end Report_Extra_Inputs;
+
+ -- Local variables
+
+ Dep_Inputs : constant Node_Id := Expression (Dep_Clause);
+ Inputs : constant Node_Id := Expression (Ref_Clause);
+ Dep_Input : Node_Id;
+ Result : Boolean;
+
+ -- Start of processing for Inputs_Match
+
+ begin
+ -- Construct a list of all refinement inputs. Note that the input
+ -- list is copied because the algorithm modifies its contents and
+ -- this should not be visible in Refined_Depends.
+
+ if Nkind (Inputs) = N_Aggregate then
+ Ref_Inputs := New_Copy_List (Expressions (Inputs));
+ else
+ Ref_Inputs := New_List (Inputs);
+ end if;
+
+ -- Depending on whether the original dependency clause mentions
+ -- states with visible refinement, the corresponding refinement
+ -- clause may differ greatly in structure and contents:
+
+ -- State with null refinement
+
+ -- Refined_State => (State => null)
+ -- Depends => (<output> => State)
+ -- Refined_Depends => (<output> => null)
+
+ -- Depends => (<output> => (State, Input))
+ -- Refined_Depends => (<output> => Input)
+
+ -- Depends => (<output> => (Input_1, State, Input_2))
+ -- Refined_Depends => (<output> => (Input_1, Input_2))
+
+ -- State with non-null refinement
+
+ -- Refined_State => (State_1 => (C1, C2))
+ -- Depends => (<output> => State)
+ -- Refined_Depends => (<output> => C1)
+ -- or
+ -- Refined_Depends => (<output> => (C1, C2))
+
+ if Nkind (Dep_Inputs) = N_Aggregate then
+ Dep_Input := First (Expressions (Dep_Inputs));
+ while Present (Dep_Input) loop
+ if not Is_Matching_Input (Dep_Input) then
+ Result := False;
+ end if;
+
+ Next (Dep_Input);
+ end loop;
+
+ Result := True;
+
+ -- Solitary input
+
+ else
+ Result := Is_Matching_Input (Dep_Inputs);
+ end if;
+
+ Report_Extra_Inputs;
+ return Result;
+ end Inputs_Match;
+
+ -------------------------
+ -- Output_Constituents --
+ -------------------------
+
+ function Output_Constituents (State_Id : Entity_Id) return Elist_Id is
+ Item_Elmt : Elmt_Id;
+ Item_Id : Entity_Id;
+ Result : Elist_Id := No_Elist;
+
+ begin
+ -- The related subprogram is subject to pragma Refined_Global. All
+ -- usable output constituents are defined in its output item list.
+
+ if Present (Global) then
+ Item_Elmt := First_Elmt (Out_Items);
+ while Present (Item_Elmt) loop
+ Item_Id := Node (Item_Elmt);
+
+ -- The constituent is part of the refinement of the input
+ -- state, add it to the result list.
+
+ if Refined_State (Item_Id) = State_Id then
+ Add_Item (Item_Id, Result);
+ end if;
+
+ Next_Elmt (Item_Elmt);
+ end loop;
+
+ -- When pragma Refined_Global is not present, the usable output
+ -- constituents are all the constituents as defined in pragma
+ -- Refined_State. Note that the elements are copied because the
+ -- algorithm trims the list and this should not be reflected in
+ -- the state itself.
+
+ else
+ Result := New_Copy_Elist (Refinement_Constituents (State_Id));
+ end if;
+
+ return Result;
+ end Output_Constituents;
+
+ --------------------------------
+ -- Report_Unused_Constituents --
+ --------------------------------
+
+ procedure Report_Unused_Constituents (Constits : Elist_Id) is
+ Constit : Entity_Id;
+ Elmt : Elmt_Id;
+ Posted : Boolean := False;
+
+ begin
+ if Present (Constits) then
+ Elmt := First_Elmt (Constits);
+ while Present (Elmt) loop
+ Constit := Node (Elmt);
+
+ -- A constituent must always refine a state
+
+ pragma Assert (Present (Refined_State (Constit)));
+
+ -- When a state has a visible refinement and its mode is
+ -- Output_Only, all its constituents must be used as
+ -- outputs.
+
+ if not Posted then
+ Posted := True;
+ Error_Msg_NE
+ ("output only state & must be replaced by all its "
+ & "constituents in dependence refinement",
+ N, Refined_State (Constit));
+ end if;
+
+ Error_Msg_NE
+ ("\ constituent & is missing in output list", N, Constit);
+
+ Next_Elmt (Elmt);
+ end loop;
+ end if;
+ end Report_Unused_Constituents;
+
+ -- Local variables
+
+ Dep_Output : constant Node_Id := First (Choices (Dep_Clause));
+ Dep_Id : Entity_Id;
+ Matching_Clause : Node_Id := Empty;
+ Next_Ref_Clause : Node_Id;
+ Ref_Clause : Node_Id;
+ Ref_Id : Entity_Id;
+ Ref_Output : Node_Id;
+
+ Has_Constituent : Boolean := False;
+ -- Flag set when the refinement output list contains at least one
+ -- constituent of the state denoted by Dep_Id.
+
+ Has_Null_State : Boolean := False;
+ -- Flag set when the output of clause Dep_Clause is a state with a
+ -- null refinement.
+
+ Has_Refined_State : Boolean := False;
+ -- Flag set when the output of clause Dep_Clause is a state with
+ -- visible refinement.
+
+ Out_Constits : Elist_Id := No_Elist;
+ -- This list contains the entities all output constituents of state
+ -- Dep_Id as defined in pragma Refined_State.
+
+ -- Start of processing for Check_Dependency_Clause
+
+ begin
+ -- The analysis of pragma Depends should produce normalized clauses
+ -- with exactly one output. This is important because output items
+ -- are unique in the whole dependence relation and can be used as
+ -- keys.
+
+ pragma Assert (No (Next (Dep_Output)));
+
+ -- Inspect all clauses of Refined_Depends and attempt to match the
+ -- output of Dep_Clause against an output from the refinement clauses
+ -- set.
+
+ Ref_Clause := First (Refinements);
+ while Present (Ref_Clause) loop
+ Matching_Clause := Empty;
+
+ -- Store the next clause now because a match will trim the list of
+ -- refinement clauses and this side effect should not be visible
+ -- in pragma Refined_Depends.
+
+ Next_Ref_Clause := Next (Ref_Clause);
+
+ -- The analysis of pragma Refined_Depends should produce
+ -- normalized clauses with exactly one output.
+
+ Ref_Output := First (Choices (Ref_Clause));
+ pragma Assert (No (Next (Ref_Output)));
+
+ -- Two null output lists match if their inputs match
+
+ if Nkind (Dep_Output) = N_Null
+ and then Nkind (Ref_Output) = N_Null
+ then
+ Matching_Clause := Ref_Clause;
+ exit;
+
+ -- Two function 'Result attributes match if their inputs match.
+ -- Note that there is no need to compare the two prefixes because
+ -- the attributes cannot denote anything but the related function.
+
+ elsif Is_Attribute_Result (Dep_Output)
+ and then Is_Attribute_Result (Ref_Output)
+ then
+ Matching_Clause := Ref_Clause;
+ exit;
+
+ -- The remaining cases are formal parameters, variables and states
+
+ elsif Is_Entity_Name (Dep_Output) then
+ Dep_Id := Entity_Of (Dep_Output);
+
+ if Ekind (Dep_Id) = E_Abstract_State then
+
+ -- A state with a null refinement matches either a null
+ -- output list or nothing at all (no clause):
+
+ -- Refined_State => (State => null)
+
+ -- No clause
+
+ -- Depends => (State => null)
+ -- Refined_Depends => null -- OK
+
+ -- Null output list
+
+ -- Depends => (State => <input>)
+ -- Refined_Depends => (null => <input>) -- OK
+
+ if Has_Null_Refinement (Dep_Id) then
+ Has_Null_State := True;
+
+ -- When a state with null refinement matches a null
+ -- output, compare their inputs.
+
+ if Nkind (Ref_Output) = N_Null then
+ Matching_Clause := Ref_Clause;
+ end if;
+
+ exit;
+
+ -- The state has a non-null refinement in which case the
+ -- match is based on constituents and inputs. A state with
+ -- multiple output constituents may match multiple clauses:
+
+ -- Refined_State => (State => (C1, C2))
+ -- Depends => (State => <input>)
+ -- Refined_Depends => ((C1, C2) => <input>)
+
+ -- When normalized, the above becomes:
+
+ -- Refined_Depends => (C1 => <input>,
+ -- C2 => <input>)
+
+ elsif Has_Non_Null_Refinement (Dep_Id) then
+ Has_Refined_State := True;
+
+ -- Store the entities of all output constituents of an
+ -- Output_Only state with visible refinement.
+
+ if No (Out_Constits)
+ and then Is_Output_Only_State (Dep_Id)
+ then
+ Out_Constits := Output_Constituents (Dep_Id);
+ end if;
+
+ if Is_Entity_Name (Ref_Output) then
+ Ref_Id := Entity_Of (Ref_Output);
+
+ -- The output of the refinement clause is a valid
+ -- constituent of the state. Remove the clause from
+ -- the pool of candidates if both input lists match.
+ -- Note that the search continues because one clause
+ -- may have been normalized into multiple clauses as
+ -- per the example above.
+
+ if Ekind_In (Ref_Id, E_Abstract_State, E_Variable)
+ and then Present (Refined_State (Ref_Id))
+ and then Refined_State (Ref_Id) = Dep_Id
+ and then Inputs_Match
+ (Ref_Clause, Do_Checks => False)
+ then
+ Has_Constituent := True;
+ Remove (Ref_Clause);
+
+ -- The matching constituent may act as an output
+ -- for an Output_Only state. Remove the item from
+ -- the available output constituents.
+
+ Remove (Out_Constits, Ref_Id);
+ end if;
+ end if;
+ end if;
+
+ -- Formal parameters and variables match if their inputs match
+
+ elsif Is_Entity_Name (Ref_Output)
+ and then Entity_Of (Ref_Output) = Dep_Id
+ then
+ Matching_Clause := Ref_Clause;
+ exit;
+ end if;
+ end if;
+
+ Ref_Clause := Next_Ref_Clause;
+ end loop;
+
+ -- Handle the case where pragma Depends contains one or more clauses
+ -- that only mention states with null refinements. In that case the
+ -- corresponding pragma Refined_Depends may have a null relation.
+
+ -- Refined_State => (State => null)
+ -- Depends => (State => null)
+ -- Refined_Depends => null -- OK
+
+ -- Another instance of the same scenario occurs when the list of
+ -- refinements has been depleted while processing previous clauses.
+
+ if Is_Entity_Name (Dep_Output)
+ and then (No (Refinements) or else Is_Empty_List (Refinements))
+ then
+ Dep_Id := Entity_Of (Dep_Output);
+
+ if Ekind (Dep_Id) = E_Abstract_State
+ and then Has_Null_Refinement (Dep_Id)
+ then
+ Has_Null_State := True;
+ end if;
+ end if;
+
+ -- The above search produced a match based on unique output. Ensure
+ -- that the inputs match as well and if they do, remove the clause
+ -- from the pool of candidates.
+
+ if Present (Matching_Clause) then
+ if Inputs_Match (Matching_Clause, Do_Checks => True) then
+ Remove (Matching_Clause);
+ end if;
+
+ -- A state with a visible refinement was matched against one or
+ -- more clauses containing appropriate constituents.
+
+ elsif Has_Constituent then
+ null;
+
+ -- A state with a null refinement did not warrant a clause
+
+ elsif Has_Null_State then
+ null;
+
+ -- The dependence relation of pragma Refined_Depends does not contain
+ -- a matching clause, emit an error.
+
+ else
+ Error_Msg_NE
+ ("dependence clause of subprogram & has no matching refinement "
+ & "in body", Ref_Clause, Spec_Id);
+
+ if Has_Refined_State then
+ Error_Msg_N
+ ("\check the use of constituents in dependence refinement",
+ Ref_Clause);
+ end if;
+ end if;
+
+ -- Emit errors for all unused constituents of an Output_Only state
+ -- with visible refinement.
+
+ Report_Unused_Constituents (Out_Constits);
+ end Check_Dependency_Clause;
+
+ --------------------------
+ -- Report_Extra_Clauses --
+ --------------------------
+
+ procedure Report_Extra_Clauses is
+ Clause : Node_Id;
+
+ begin
+ if Present (Refinements) then
+ Clause := First (Refinements);
+ while Present (Clause) loop
+
+ -- Do not complain about a null input refinement, since a null
+ -- input legitimately matches anything.
+
+ if Nkind (Clause) /= N_Component_Association
+ or else Nkind (Expression (Clause)) /= N_Null
+ then
+ Error_Msg_N
+ ("unmatched or extra clause in dependence refinement",
+ Clause);
+ end if;
+
+ Next (Clause);
+ end loop;
+ end if;
+ end Report_Extra_Clauses;
+
+ -- Local variables
+
+ Body_Decl : constant Node_Id := Parent (N);
+ Body_Id : constant Entity_Id := Defining_Entity (Body_Decl);
+ Errors : constant Nat := Serious_Errors_Detected;
+ Clause : Node_Id;
+ Deps : Node_Id;
+ Refs : Node_Id;
+
+ -- The following are dummy variables that capture unused output of
+ -- routine Collect_Global_Items.
+
+ D1, D2 : Elist_Id := No_Elist;
+ D3, D4, D5, D6 : Boolean;
+
+ -- Start of processing for Analyze_Refined_Depends_In_Decl_Part
+
+ begin
+ Spec_Id := Corresponding_Spec (Body_Decl);
+ Depends := Get_Pragma (Spec_Id, Pragma_Depends);
+
+ -- The subprogram declarations lacks pragma Depends. This renders
+ -- Refined_Depends useless as there is nothing to refine.
+
+ if No (Depends) then
+ Error_Msg_NE
+ ("useless refinement, subprogram & lacks dependence clauses",
+ N, Spec_Id);
+ return;
+ end if;
+
+ Deps := Get_Pragma_Arg (First (Pragma_Argument_Associations (Depends)));
+
+ -- A null dependency relation renders the refinement useless because it
+ -- cannot possibly mention abstract states with visible refinement. Note
+ -- that the inverse is not true as states may be refined to null.
+
+ if Nkind (Deps) = N_Null then
+ Error_Msg_NE
+ ("useless refinement, subprogram & does not depend on abstract "
+ & "state with visible refinement", N, Spec_Id);
+ return;
+ end if;
+
+ -- Multiple dependency clauses appear as component associations of an
+ -- aggregate.
+
+ pragma Assert (Nkind (Deps) = N_Aggregate);
+ Dependencies := Component_Associations (Deps);
+
+ -- Analyze Refined_Depends as if it behaved as a regular pragma Depends.
+ -- This ensures that the categorization of all refined dependency items
+ -- is consistent with their role.
+
+ Analyze_Depends_In_Decl_Part (N);
+ Refs := Get_Pragma_Arg (First (Pragma_Argument_Associations (N)));
+
+ if Serious_Errors_Detected = Errors then
+
+ -- The related subprogram may be subject to pragma Refined_Global. If
+ -- this is the case, gather all output items. These are needed when
+ -- verifying the use of constituents that apply to output states with
+ -- visible refinement.
+
+ Global := Get_Pragma (Body_Id, Pragma_Refined_Global);
+
+ if Present (Global) then
+ Collect_Global_Items
+ (Prag => Global,
+ In_Items => D1,
+ In_Out_Items => D2,
+ Out_Items => Out_Items,
+ Has_In_State => D3,
+ Has_In_Out_State => D4,
+ Has_Out_State => D5,
+ Has_Null_State => D6);
+ end if;
+
+ if Nkind (Refs) = N_Null then
+ Refinements := No_List;
+
+ -- Multiple dependency clauses appear as component associations of an
+ -- aggregate. Note that the clauses are copied because the algorithm
+ -- modifies them and this should not be visible in Refined_Depends.
+
+ else pragma Assert (Nkind (Refs) = N_Aggregate);
+ Refinements := New_Copy_List (Component_Associations (Refs));
+ end if;
+
+ -- Inspect all the clauses of pragma Depends looking for a matching
+ -- clause in pragma Refined_Depends. The approach is to use the
+ -- sole output of a clause as a key. Output items are unique in a
+ -- dependence relation. Clause normalization also ensured that all
+ -- clauses have exactly one output. Depending on what the key is, one
+ -- or more refinement clauses may satisfy the dependency clause. Each
+ -- time a dependency clause is matched, its related refinement clause
+ -- is consumed. In the end, two things may happen:
+
+ -- 1) A clause of pragma Depends was not matched in which case
+ -- Check_Dependency_Clause reports the error.
+
+ -- 2) Refined_Depends has an extra clause in which case the error
+ -- is reported by Report_Extra_Clauses.
+
+ Clause := First (Dependencies);
+ while Present (Clause) loop
+ Check_Dependency_Clause (Clause);
+ Next (Clause);
+ end loop;
+ end if;
+
+ if Serious_Errors_Detected = Errors then
+ Report_Extra_Clauses;
+ end if;
+ end Analyze_Refined_Depends_In_Decl_Part;
+
+ -----------------------------------------
+ -- Analyze_Refined_Global_In_Decl_Part --
+ -----------------------------------------
+
+ procedure Analyze_Refined_Global_In_Decl_Part (N : Node_Id) is
+ Global : Node_Id;
+ -- The corresponding Global pragma
+
+ Has_In_State : Boolean := False;
+ Has_In_Out_State : Boolean := False;
+ Has_Out_State : Boolean := False;
+ -- These flags are set when the corresponding Global pragma has a state
+ -- of mode Input, In_Out and Output respectively with a visible
+ -- refinement.
+
+ Has_Null_State : Boolean := False;
+ -- This flag is set when the corresponding Global pragma has at least
+ -- one state with a null refinement.
+
+ In_Constits : Elist_Id := No_Elist;
+ In_Out_Constits : Elist_Id := No_Elist;
+ Out_Constits : Elist_Id := No_Elist;
+ -- These lists contain the entities of all Input, In_Out and Output
+ -- constituents that appear in Refined_Global and participate in state
+ -- refinement.
+
+ In_Items : Elist_Id := No_Elist;
+ In_Out_Items : Elist_Id := No_Elist;
+ Out_Items : Elist_Id := No_Elist;
+ -- These list contain the entities of all Input, In_Out and Output items
+ -- defined in the corresponding Global pragma.
+
+ procedure Check_In_Out_States;
+ -- Determine whether the corresponding Global pragma mentions In_Out
+ -- states with visible refinement and if so, ensure that one of the
+ -- following completions apply to the constituents of the state:
+ -- 1) there is at least one constituent of mode In_Out
+ -- 2) there is at least one Input and one Output constituent
+ -- 3) not all constituents are present and one of them is of mode
+ -- Output.
+ -- This routine may remove elements from In_Constits, In_Out_Constits
+ -- and Out_Constits.
+
+ procedure Check_Input_States;
+ -- Determine whether the corresponding Global pragma mentions Input
+ -- states with visible refinement and if so, ensure that at least one of
+ -- its constituents appears as an Input item in Refined_Global.
+ -- This routine may remove elements from In_Constits, In_Out_Constits
+ -- and Out_Constits.
+
+ procedure Check_Output_States;
+ -- Determine whether the corresponding Global pragma mentions Output
+ -- states with visible refinement and if so, ensure that all of its
+ -- constituents appear as Output items in Refined_Global. This routine
+ -- may remove elements from In_Constits, In_Out_Constits and
+ -- Out_Constits.
+
+ procedure Check_Refined_Global_List
+ (List : Node_Id;
+ Global_Mode : Name_Id := Name_Input);
+ -- Verify the legality of a single global list declaration. Global_Mode
+ -- denotes the current mode in effect.
+
+ function Present_Then_Remove
+ (List : Elist_Id;
+ Item : Entity_Id) return Boolean;
+ -- Search List for a particular entity Item. If Item has been found,
+ -- remove it from List. This routine is used to strip lists In_Constits,
+ -- In_Out_Constits and Out_Constits of valid constituents.
+
+ procedure Report_Extra_Constituents;
+ -- Emit an error for each constituent found in lists In_Constits,
+ -- In_Out_Constits and Out_Constits.
+
+ -------------------------
+ -- Check_In_Out_States --
+ -------------------------
+
+ procedure Check_In_Out_States is
+ procedure Check_Constituent_Usage (State_Id : Entity_Id);
+ -- Determine whether one of the following coverage scenarios is in
+ -- effect:
+ -- 1) there is at least one constituent of mode In_Out
+ -- 2) there is at least one Input and one Output constituent
+ -- 3) not all constituents are present and one of them is of mode
+ -- Output.
+ -- If this is not the case, emit an error.
+
+ -----------------------------
+ -- Check_Constituent_Usage --
+ -----------------------------
+
+ procedure Check_Constituent_Usage (State_Id : Entity_Id) is
+ Constit_Elmt : Elmt_Id;
+ Constit_Id : Entity_Id;
+ Has_Missing : Boolean := False;
+ In_Out_Seen : Boolean := False;
+ In_Seen : Boolean := False;
+ Out_Seen : Boolean := False;
+
+ begin
+ -- Process all the constituents of the state and note their modes
+ -- within the global refinement.
+
+ Constit_Elmt := First_Elmt (Refinement_Constituents (State_Id));
+ while Present (Constit_Elmt) loop
+ Constit_Id := Node (Constit_Elmt);
+
+ if Present_Then_Remove (In_Constits, Constit_Id) then
+ In_Seen := True;
+
+ elsif Present_Then_Remove (In_Out_Constits, Constit_Id) then
+ In_Out_Seen := True;
+
+ elsif Present_Then_Remove (Out_Constits, Constit_Id) then
+ Out_Seen := True;
+
+ else
+ Has_Missing := True;
+ end if;
+
+ Next_Elmt (Constit_Elmt);
+ end loop;
+
+ -- A single In_Out constituent is a valid completion
+
+ if In_Out_Seen then
+ null;
+
+ -- A pair of one Input and one Output constituent is a valid
+ -- completion.
+
+ elsif In_Seen and then Out_Seen then
+ null;
+
+ -- A single Output constituent is a valid completion only when
+ -- some of the other constituents are missing.
+
+ elsif Has_Missing and then Out_Seen then
+ null;
+
+ else
+ Error_Msg_NE
+ ("global refinement of state & redefines the mode of its "
+ & "constituents", N, State_Id);
+ end if;
+ end Check_Constituent_Usage;
+
+ -- Local variables
+
+ Item_Elmt : Elmt_Id;
+ Item_Id : Entity_Id;
+
+ -- Start of processing for Check_In_Out_States
+
+ begin
+ -- Inspect the In_Out items of the corresponding Global pragma
+ -- looking for a state with a visible refinement.
+
+ if Has_In_Out_State and then Present (In_Out_Items) then
+ Item_Elmt := First_Elmt (In_Out_Items);
+ while Present (Item_Elmt) loop
+ Item_Id := Node (Item_Elmt);
+
+ -- Ensure that one of the three coverage variants is satisfied
+
+ if Ekind (Item_Id) = E_Abstract_State
+ and then Has_Non_Null_Refinement (Item_Id)
+ then
+ Check_Constituent_Usage (Item_Id);
+ end if;
+
+ Next_Elmt (Item_Elmt);
+ end loop;
+ end if;
+ end Check_In_Out_States;
+
+ ------------------------
+ -- Check_Input_States --
+ ------------------------
+
+ procedure Check_Input_States is
+ procedure Check_Constituent_Usage (State_Id : Entity_Id);
+ -- Determine whether at least one constituent of state State_Id with
+ -- visible refinement is used and has mode Input. Ensure that the
+ -- remaining constituents do not have In_Out or Output modes.
+
+ -----------------------------
+ -- Check_Constituent_Usage --
+ -----------------------------
+
+ procedure Check_Constituent_Usage (State_Id : Entity_Id) is
+ Constit_Elmt : Elmt_Id;
+ Constit_Id : Entity_Id;
+ In_Seen : Boolean := False;
+
+ begin
+ Constit_Elmt := First_Elmt (Refinement_Constituents (State_Id));
+ while Present (Constit_Elmt) loop
+ Constit_Id := Node (Constit_Elmt);
+
+ -- At least one of the constituents appears as an Input
+
+ if Present_Then_Remove (In_Constits, Constit_Id) then
+ In_Seen := True;
+
+ -- The constituent appears in the global refinement, but has
+ -- mode In_Out or Output.
+
+ elsif Present_Then_Remove (In_Out_Constits, Constit_Id)
+ or else Present_Then_Remove (Out_Constits, Constit_Id)
+ then
+ Error_Msg_Name_1 := Chars (State_Id);
+ Error_Msg_NE
+ ("constituent & of state % must have mode Input in global "
+ & "refinement", N, Constit_Id);
+ end if;
+
+ Next_Elmt (Constit_Elmt);
+ end loop;
+
+ -- Not one of the constituents appeared as Input
+
+ if not In_Seen then
+ Error_Msg_NE
+ ("global refinement of state & must include at least one "
+ & "constituent of mode Input", N, State_Id);
+ end if;
+ end Check_Constituent_Usage;
+
+ -- Local variables
+
+ Item_Elmt : Elmt_Id;
+ Item_Id : Entity_Id;
+
+ -- Start of processing for Check_Input_States
+
+ begin
+ -- Inspect the Input items of the corresponding Global pragma
+ -- looking for a state with a visible refinement.
+
+ if Has_In_State and then Present (In_Items) then
+ Item_Elmt := First_Elmt (In_Items);
+ while Present (Item_Elmt) loop
+ Item_Id := Node (Item_Elmt);
+
+ -- Ensure that at least one of the constituents is utilized and
+ -- is of mode Input.
+
+ if Ekind (Item_Id) = E_Abstract_State
+ and then Has_Non_Null_Refinement (Item_Id)
+ then
+ Check_Constituent_Usage (Item_Id);
+ end if;
+
+ Next_Elmt (Item_Elmt);
+ end loop;
+ end if;
+ end Check_Input_States;
+
+ -------------------------
+ -- Check_Output_States --
+ -------------------------
+
+ procedure Check_Output_States is
+ procedure Check_Constituent_Usage (State_Id : Entity_Id);
+ -- Determine whether all constituents of state State_Id with visible
+ -- refinement are used and have mode Output. Emit an error if this is
+ -- not the case.
+
+ -----------------------------
+ -- Check_Constituent_Usage --
+ -----------------------------
+
+ procedure Check_Constituent_Usage (State_Id : Entity_Id) is
+ Constit_Elmt : Elmt_Id;
+ Constit_Id : Entity_Id;
+
+ begin
+ Constit_Elmt := First_Elmt (Refinement_Constituents (State_Id));
+ while Present (Constit_Elmt) loop
+ Constit_Id := Node (Constit_Elmt);
+
+ if Present_Then_Remove (Out_Constits, Constit_Id) then
+ null;
+
+ else
+ Remove (In_Constits, Constit_Id);
+ Remove (In_Out_Constits, Constit_Id);
+
+ Error_Msg_Name_1 := Chars (State_Id);
+ Error_Msg_NE
+ ("constituent & of state % must have mode Output in "
+ & "global refinement", N, Constit_Id);
+ end if;
+
+ Next_Elmt (Constit_Elmt);
+ end loop;
+ end Check_Constituent_Usage;
+
+ -- Local variables
+
+ Item_Elmt : Elmt_Id;
+ Item_Id : Entity_Id;
+
+ -- Start of processing for Check_Output_States
+
+ begin
+ -- Inspect the Output items of the corresponding Global pragma
+ -- looking for a state with a visible refinement.
+
+ if Has_Out_State and then Present (Out_Items) then
+ Item_Elmt := First_Elmt (Out_Items);
+ while Present (Item_Elmt) loop
+ Item_Id := Node (Item_Elmt);
+
+ -- Ensure that all of the constituents are utilized and they
+ -- have mode Output.
+
+ if Ekind (Item_Id) = E_Abstract_State
+ and then Has_Non_Null_Refinement (Item_Id)
+ then
+ Check_Constituent_Usage (Item_Id);
+ end if;
+
+ Next_Elmt (Item_Elmt);
+ end loop;
+ end if;
+ end Check_Output_States;
+
+ -------------------------------
+ -- Check_Refined_Global_List --
+ -------------------------------
+
+ procedure Check_Refined_Global_List
+ (List : Node_Id;
+ Global_Mode : Name_Id := Name_Input)
+ is
+ procedure Check_Refined_Global_Item
+ (Item : Node_Id;
+ Global_Mode : Name_Id);
+ -- Verify the legality of a single global item declaration. Parameter
+ -- Global_Mode denotes the current mode in effect.
+
+ -------------------------------
+ -- Check_Refined_Global_Item --
+ -------------------------------
+
+ procedure Check_Refined_Global_Item
+ (Item : Node_Id;
+ Global_Mode : Name_Id)
+ is
+ Item_Id : constant Entity_Id := Entity_Of (Item);
+
+ procedure Inconsistent_Mode_Error (Expect : Name_Id);
+ -- Issue a common error message for all mode mismatches. Expect
+ -- denotes the expected mode.
+
+ -----------------------------
+ -- Inconsistent_Mode_Error --
+ -----------------------------
+
+ procedure Inconsistent_Mode_Error (Expect : Name_Id) is
+ begin
+ Error_Msg_NE
+ ("global item & has inconsistent modes", Item, Item_Id);
+
+ Error_Msg_Name_1 := Global_Mode;
+ Error_Msg_N ("\ expected mode %", Item);
+
+ Error_Msg_Name_1 := Expect;
+ Error_Msg_N ("\ found mode %", Item);
+ end Inconsistent_Mode_Error;
+
+ -- Start of processing for Check_Refined_Global_Item
+
+ begin
+ -- The state or variable acts as a constituent of a state, collect
+ -- it for the state completeness checks performed later on.
+
+ if Present (Refined_State (Item_Id)) then
+ if Global_Mode = Name_Input then
+ Add_Item (Item_Id, In_Constits);
+
+ elsif Global_Mode = Name_In_Out then
+ Add_Item (Item_Id, In_Out_Constits);
+
+ elsif Global_Mode = Name_Output then
+ Add_Item (Item_Id, Out_Constits);
+ end if;
+
+ -- When not a constituent, ensure that both occurrences of the
+ -- item in pragmas Global and Refined_Global match.
+
+ elsif Contains (In_Items, Item_Id) then
+ if Global_Mode /= Name_Input then
+ Inconsistent_Mode_Error (Name_Input);
+ end if;
+
+ elsif Contains (In_Out_Items, Item_Id) then
+ if Global_Mode /= Name_In_Out then
+ Inconsistent_Mode_Error (Name_In_Out);
+ end if;
+
+ elsif Contains (Out_Items, Item_Id) then
+ if Global_Mode /= Name_Output then
+ Inconsistent_Mode_Error (Name_Output);
+ end if;
+
+ -- The item does not appear in the corresponding Global pragma, it
+ -- must be an extra.
+
+ else
+ Error_Msg_NE ("extra global item &", Item, Item_Id);
+ end if;
+ end Check_Refined_Global_Item;
+
+ -- Local variables
+
+ Item : Node_Id;
+
+ -- Start of processing for Check_Refined_Global_List
+
+ begin
+ if Nkind (List) = N_Null then
+ null;
+
+ -- Single global item declaration
+
+ elsif Nkind_In (List, N_Expanded_Name,
+ N_Identifier,
+ N_Selected_Component)
+ then
+ Check_Refined_Global_Item (List, Global_Mode);
+
+ -- Simple global list or moded global list declaration
+
+ elsif Nkind (List) = N_Aggregate then
+
+ -- The declaration of a simple global list appear as a collection
+ -- of expressions.
+
+ if Present (Expressions (List)) then
+ Item := First (Expressions (List));
+ while Present (Item) loop
+ Check_Refined_Global_Item (Item, Global_Mode);
+
+ Next (Item);
+ end loop;
+
+ -- The declaration of a moded global list appears as a collection
+ -- of component associations where individual choices denote
+ -- modes.
+
+ elsif Present (Component_Associations (List)) then
+ Item := First (Component_Associations (List));
+ while Present (Item) loop
+ Check_Refined_Global_List
+ (List => Expression (Item),
+ Global_Mode => Chars (First (Choices (Item))));
+
+ Next (Item);
+ end loop;
+
+ -- Invalid tree
+
+ else
+ raise Program_Error;
+ end if;
+
+ -- Invalid list
+
+ else
+ raise Program_Error;
+ end if;
+ end Check_Refined_Global_List;
+
+ -------------------------
+ -- Present_Then_Remove --
+ -------------------------
+
+ function Present_Then_Remove
+ (List : Elist_Id;
+ Item : Entity_Id) return Boolean
+ is
+ Elmt : Elmt_Id;
+
+ begin
+ if Present (List) then
+ Elmt := First_Elmt (List);
+ while Present (Elmt) loop
+ if Node (Elmt) = Item then
+ Remove_Elmt (List, Elmt);
+ return True;
+ end if;
+
+ Next_Elmt (Elmt);
+ end loop;
+ end if;
+
+ return False;
+ end Present_Then_Remove;
+
+ -------------------------------
+ -- Report_Extra_Constituents --
+ -------------------------------
+
+ procedure Report_Extra_Constituents is
+ procedure Report_Extra_Constituents_In_List (List : Elist_Id);
+ -- Emit an error for every element of List
+
+ ---------------------------------------
+ -- Report_Extra_Constituents_In_List --
+ ---------------------------------------
+
+ procedure Report_Extra_Constituents_In_List (List : Elist_Id) is
+ Constit_Elmt : Elmt_Id;
+
+ begin
+ if Present (List) then
+ Constit_Elmt := First_Elmt (List);
+ while Present (Constit_Elmt) loop
+ Error_Msg_NE ("extra constituent &", N, Node (Constit_Elmt));
+ Next_Elmt (Constit_Elmt);
+ end loop;
+ end if;
+ end Report_Extra_Constituents_In_List;
+
+ -- Start of processing for Report_Extra_Constituents
+
+ begin
+ Report_Extra_Constituents_In_List (In_Constits);
+ Report_Extra_Constituents_In_List (In_Out_Constits);
+ Report_Extra_Constituents_In_List (Out_Constits);
+ end Report_Extra_Constituents;
+
+ -- Local variables
+
+ Body_Decl : constant Node_Id := Parent (N);
+ Errors : constant Nat := Serious_Errors_Detected;
+ Items : constant Node_Id :=
+ Get_Pragma_Arg (First (Pragma_Argument_Associations (N)));
+ Spec_Id : constant Entity_Id := Corresponding_Spec (Body_Decl);
+
+ -- Start of processing for Analyze_Refined_Global_In_Decl_Part
+
+ begin
+ Global := Get_Pragma (Spec_Id, Pragma_Global);
+
+ -- The subprogram declaration lacks pragma Global. This renders
+ -- Refined_Global useless as there is nothing to refine.
+
+ if No (Global) then
+ Error_Msg_NE
+ ("useless refinement, subprogram & lacks global items", N, Spec_Id);
+ return;
+ end if;
+
+ -- Extract all relevant items from the corresponding Global pragma
+
+ Collect_Global_Items
+ (Prag => Global,
+ In_Items => In_Items,
+ In_Out_Items => In_Out_Items,
+ Out_Items => Out_Items,
+ Has_In_State => Has_In_State,
+ Has_In_Out_State => Has_In_Out_State,
+ Has_Out_State => Has_Out_State,
+ Has_Null_State => Has_Null_State);
+
+ -- The corresponding Global pragma must mention at least one state with
+ -- a visible refinement at the point Refined_Global is processed. States
+ -- with null refinements warrant a Refined_Global pragma.
+
+ if not Has_In_State
+ and then not Has_In_Out_State
+ and then not Has_Out_State
+ and then not Has_Null_State
+ then
+ Error_Msg_NE
+ ("useless refinement, subprogram & does not mention abstract state "
+ & "with visible refinement", N, Spec_Id);
+ return;
+ end if;
+
+ -- The global refinement of inputs and outputs cannot be null when the
+ -- corresponding Global pragma contains at least one item except in the
+ -- case where we have states with null refinements.
+
+ if Nkind (Items) = N_Null
+ and then
+ (Present (In_Items)
+ or else Present (In_Out_Items)
+ or else Present (Out_Items))
+ and then not Has_Null_State
+ then
+ Error_Msg_NE
+ ("refinement cannot be null, subprogram & has global items",
+ N, Spec_Id);
+ return;
+ end if;
+
+ -- Analyze Refined_Global as if it behaved as a regular pragma Global.
+ -- This ensures that the categorization of all refined global items is
+ -- consistent with their role.
+
+ Analyze_Global_In_Decl_Part (N);
+
+ -- Perform all refinement checks with respect to completeness and mode
+ -- matching.
+
+ if Serious_Errors_Detected = Errors then
+ Check_Refined_Global_List (Items);
+ end if;
+
+ -- For Input states with visible refinement, at least one constituent
+ -- must be used as an Input in the global refinement.
+
+ if Serious_Errors_Detected = Errors then
+ Check_Input_States;
+ end if;
+
+ -- Verify all possible completion variants for In_Out states with
+ -- visible refinement.
+
+ if Serious_Errors_Detected = Errors then
+ Check_In_Out_States;
+ end if;
+
+ -- For Output states with visible refinement, all constituents must be
+ -- used as Outputs in the global refinement.
+
+ if Serious_Errors_Detected = Errors then
+ Check_Output_States;
+ end if;
+
+ -- Emit errors for all constituents that belong to other states with
+ -- visible refinement that do not appear in Global.
+
+ if Serious_Errors_Detected = Errors then
+ Report_Extra_Constituents;
+ end if;
+ end Analyze_Refined_Global_In_Decl_Part;
+
+ ----------------------------------------
+ -- Analyze_Refined_State_In_Decl_Part --
+ ----------------------------------------
+
+ procedure Analyze_Refined_State_In_Decl_Part (N : Node_Id) is
+ Pack_Body : constant Node_Id := Parent (N);
+ Spec_Id : constant Entity_Id := Corresponding_Spec (Pack_Body);
+
+ Abstr_States : Elist_Id := No_Elist;
+ -- A list of all abstract states defined in the package declaration. The
+ -- list is used to report unrefined states.
+
+ Constituents_Seen : Elist_Id := No_Elist;
+ -- A list that contains all constituents processed so far. The list is
+ -- used to detect multiple uses of the same constituent.
+
+ Hidden_States : Elist_Id := No_Elist;
+ -- A list of all hidden states (abstract states and variables) that
+ -- appear in the package spec and body. The list is used to report
+ -- unused hidden states.
+
+ Refined_States_Seen : Elist_Id := No_Elist;
+ -- A list that contains all refined states processed so far. The list is
+ -- used to detect duplicate refinements.
+
+ procedure Analyze_Refinement_Clause (Clause : Node_Id);
+ -- Perform full analysis of a single refinement clause
+
+ procedure Collect_Hidden_States;
+ -- Gather the entities of all hidden states that appear in the spec and
+ -- body of the related package in Hidden_States.
+
+ procedure Report_Unrefined_States;
+ -- Emit errors for all abstract states that have not been refined by
+ -- the pragma.
+
+ procedure Report_Unused_Hidden_States;
+ -- Emit errors for all hidden states of the related package that do not
+ -- participate in a refinement.
+
+ -------------------------------
+ -- Analyze_Refinement_Clause --
+ -------------------------------
+
+ procedure Analyze_Refinement_Clause (Clause : Node_Id) is
+ State_Id : Entity_Id := Empty;
+ -- The entity of the state being refined in the current clause
+
+ Non_Null_Seen : Boolean := False;
+ Null_Seen : Boolean := False;
+ -- Flags used to detect multiple uses of null in a single clause or a
+ -- mixture of null and non-null constituents.
+
+ procedure Analyze_Constituent (Constit : Node_Id);
+ -- Perform full analysis of a single constituent
+
+ procedure Check_Matching_State
+ (State : Node_Id;
+ State_Id : Entity_Id);
+ -- Determine whether state State denoted by its name State_Id appears
+ -- in Abstr_States. Emit an error when attempting to re-refine the
+ -- state or when the state is not defined in the package declaration.
+ -- Otherwise remove the state from Abstr_States.
+
+ -------------------------
+ -- Analyze_Constituent --
+ -------------------------
+
+ procedure Analyze_Constituent (Constit : Node_Id) is
+ procedure Check_Matching_Constituent (Constit_Id : Entity_Id);
+ -- Determine whether constituent Constit denoted by its entity
+ -- Constit_Id appears in Hidden_States. Emit an error when the
+ -- constituent is not a valid hidden state of the related package
+ -- or when it is used more than once. Otherwise remove the
+ -- constituent from Hidden_States.
+
+ --------------------------------
+ -- Check_Matching_Constituent --
+ --------------------------------
+
+ procedure Check_Matching_Constituent (Constit_Id : Entity_Id) is
+ procedure Collect_Constituent;
+ -- Add constituent Constit_Id to the refinements of State_Id
+
+ -------------------------
+ -- Collect_Constituent --
+ -------------------------
+
+ procedure Collect_Constituent is
+ begin
+ -- Add the constituent to the lis of processed items to aid
+ -- with the detection of duplicates.
+
+ Add_Item (Constit_Id, Constituents_Seen);
+
+ -- Collect the constituent in the list of refinement items.
+ -- Establish a relation between the refined state and its
+ -- constituent.
+
+ Append_Elmt (Constit_Id, Refinement_Constituents (State_Id));
+ Set_Refined_State (Constit_Id, State_Id);
+
+ -- The state has at least one legal constituent, mark the
+ -- start of the refinement region. The region ends when the
+ -- body declarations end (see routine Analyze_Declarations).
+
+ Set_Has_Visible_Refinement (State_Id);
+ end Collect_Constituent;
+
+ -- Local variables
+
+ State_Elmt : Elmt_Id;
+
+ -- Start of processing for Check_Matching_Constituent
+
+ begin
+ -- Detect a duplicate use of a constituent
+
+ if Contains (Constituents_Seen, Constit_Id) then
+ Error_Msg_NE
+ ("duplicate use of constituent &", Constit, Constit_Id);
+ return;
+
+ -- A state can act as a constituent only when it is part of
+ -- another state. This relation is expressed by option Part_Of
+ -- of pragma Abstract_State.
+
+ elsif Ekind (Constit_Id) = E_Abstract_State then
+ if not Is_Part_Of (Constit_Id, State_Id) then
+ Error_Msg_Name_1 := Chars (State_Id);
+ Error_Msg_NE
+ ("state & is not a valid constituent of ancestor "
+ & "state %", Constit, Constit_Id);
+ return;
+
+ -- The constituent has the proper Part_Of option, but may
+ -- not appear in the immediate hidden state of the related
+ -- package. This case arises when the constituent appears
+ -- in a private child or a private sibling. Recognize these
+ -- scenarios and collect the constituent.
+
+ elsif Is_Child_Or_Sibling
+ (Pack_1 => Scope (State_Id),
+ Pack_2 => Scope (Constit_Id),
+ Private_Child => True)
+ then
+ Collect_Constituent;
+ return;
+ end if;
+ end if;
+
+ -- Inspect the hidden states of the related package looking for
+ -- a match.
+
+ if Present (Hidden_States) then
+ State_Elmt := First_Elmt (Hidden_States);
+ while Present (State_Elmt) loop
+
+ -- A valid hidden state or variable acts as a constituent
+
+ if Node (State_Elmt) = Constit_Id then
+
+ -- Add the constituent to the lis of processed items
+ -- to aid with the detection of duplicates. Remove the
+ -- constituent from Hidden_States to signal that it
+ -- has already been matched.
+
+ Add_Item (Constit_Id, Constituents_Seen);
+ Remove_Elmt (Hidden_States, State_Elmt);
+
+ Collect_Constituent;
+ return;
+ end if;
+
+ Next_Elmt (State_Elmt);
+ end loop;
+ end if;
+
+ -- If we get here, we are refining a state that is not hidden
+ -- with respect to the related package.
+
+ Error_Msg_Name_1 := Chars (Spec_Id);
+ Error_Msg_NE
+ ("cannot use & in refinement, constituent is not a hidden "
+ & "state of package %", Constit, Constit_Id);
+ end Check_Matching_Constituent;
+
+ -- Local variables
+
+ Constit_Id : Entity_Id;
+
+ -- Start of processing for Analyze_Constituent
+
+ begin
+ -- Detect multiple uses of null in a single refinement clause or a
+ -- mixture of null and non-null constituents.
+
+ if Nkind (Constit) = N_Null then
+ if Null_Seen then
+ Error_Msg_N
+ ("multiple null constituents not allowed", Constit);
+
+ elsif Non_Null_Seen then
+ Error_Msg_N
+ ("cannot mix null and non-null constituents", Constit);
+
+ else
+ Null_Seen := True;
+
+ -- Collect the constituent in the list of refinement items
+
+ Append_Elmt (Constit, Refinement_Constituents (State_Id));
+
+ -- The state has at least one legal constituent, mark the
+ -- start of the refinement region. The region ends when the
+ -- body declarations end (see Analyze_Declarations).
+
+ Set_Has_Visible_Refinement (State_Id);
+ end if;
+
+ -- Non-null constituents
+
+ else
+ Non_Null_Seen := True;
+
+ if Null_Seen then
+ Error_Msg_N
+ ("cannot mix null and non-null constituents", Constit);
+ end if;
+
+ Analyze (Constit);
+
+ -- Ensure that the constituent denotes a valid state or a
+ -- whole variable.
+
+ if Is_Entity_Name (Constit) then
+ Constit_Id := Entity (Constit);
+
+ if Ekind_In (Constit_Id, E_Abstract_State, E_Variable) then
+ Check_Matching_Constituent (Constit_Id);
+
+ else
+ Error_Msg_NE
+ ("constituent & must denote a variable or state",
+ Constit, Constit_Id);
+ end if;
+
+ -- The constituent is illegal
+
+ else
+ Error_Msg_N ("malformed constituent", Constit);
+ end if;
+ end if;
+ end Analyze_Constituent;
+
+ --------------------------
+ -- Check_Matching_State --
+ --------------------------
+
+ procedure Check_Matching_State
+ (State : Node_Id;
+ State_Id : Entity_Id)
+ is
+ State_Elmt : Elmt_Id;
+
+ begin
+ -- Detect a duplicate refinement of a state
+
+ if Contains (Refined_States_Seen, State_Id) then
+ Error_Msg_NE
+ ("duplicate refinement of state &", State, State_Id);
+ return;
+ end if;
+
+ -- Inspect the abstract states defined in the package declaration
+ -- looking for a match.
+
+ State_Elmt := First_Elmt (Abstr_States);
+ while Present (State_Elmt) loop
+
+ -- A valid abstract state is being refined in the body. Add
+ -- the state to the list of processed refined states to aid
+ -- with the detection of duplicate refinements. Remove the
+ -- state from Abstr_States to signal that it has already been
+ -- refined.
+
+ if Node (State_Elmt) = State_Id then
+ Add_Item (State_Id, Refined_States_Seen);
+ Remove_Elmt (Abstr_States, State_Elmt);
+ return;
+ end if;
+
+ Next_Elmt (State_Elmt);
+ end loop;
+
+ -- If we get here, we are refining a state that is not defined in
+ -- the package declaration.
+
+ Error_Msg_Name_1 := Chars (Spec_Id);
+ Error_Msg_NE
+ ("cannot refine state, & is not defined in package %",
+ State, State_Id);
+ end Check_Matching_State;
+
+ -- Local declarations
+
+ Constit : Node_Id;
+ State : Node_Id;
+
+ -- Start of processing for Analyze_Refinement_Clause
+
+ begin
+ -- Analyze the state name of a refinement clause
+
+ State := First (Choices (Clause));
+ while Present (State) loop
+ if Present (State_Id) then
+ Error_Msg_N
+ ("refinement clause cannot cover multiple states", State);
+
+ else
+ Analyze (State);
+
+ -- Ensure that the state name denotes a valid abstract state
+ -- that is defined in the spec of the related package.
+
+ if Is_Entity_Name (State) then
+ State_Id := Entity (State);
+
+ -- Catch any attempts to re-refine a state or refine a
+ -- state that is not defined in the package declaration.
+
+ if Ekind (State_Id) = E_Abstract_State then
+ Check_Matching_State (State, State_Id);
+ else
+ Error_Msg_NE
+ ("& must denote an abstract state", State, State_Id);
+ end if;
+
+ -- Enforce SPARK RM (6.1.5(4)): A global item shall not
+ -- denote a state abstraction whose refinement is visible
+ -- (a state abstraction cannot be named within its enclosing
+ -- package's body other than in its refinement).
+
+ if Has_Body_References (State_Id) then
+ declare
+ Ref : Elmt_Id;
+ Nod : Node_Id;
+ begin
+ Ref := First_Elmt (Body_References (State_Id));
+ while Present (Ref) loop
+ Nod := Node (Ref);
+ Error_Msg_N
+ ("global reference to & not allowed "
+ & "(SPARK RM 6.1.5(4))", Nod);
+ Error_Msg_Sloc := Sloc (State);
+ Error_Msg_N ("\refinement of & is visible#", Nod);
+ Next_Elmt (Ref);
+ end loop;
+ end;
+ end if;
+
+ -- The state name is illegal
+
+ else
+ Error_Msg_N
+ ("malformed state name in refinement clause", State);
+ end if;
+ end if;
+
+ Next (State);
+ end loop;
+
+ -- Analyze all constituents of the refinement. Multiple constituents
+ -- appear as an aggregate.
+
+ Constit := Expression (Clause);
+
+ if Nkind (Constit) = N_Aggregate then
+ if Present (Component_Associations (Constit)) then
+ Error_Msg_N
+ ("constituents of refinement clause must appear in "
+ & "positional form", Constit);
+
+ else pragma Assert (Present (Expressions (Constit)));
+ Constit := First (Expressions (Constit));
+ while Present (Constit) loop
+ Analyze_Constituent (Constit);
+
+ Next (Constit);
+ end loop;
+ end if;
+
+ -- Various forms of a single constituent. Note that these may include
+ -- malformed constituents.
+
+ else
+ Analyze_Constituent (Constit);
+ end if;
+ end Analyze_Refinement_Clause;
+
+ ---------------------------
+ -- Collect_Hidden_States --
+ ---------------------------
+
+ procedure Collect_Hidden_States is
+ procedure Collect_Hidden_States_In_Decls (Decls : List_Id);
+ -- Find all hidden states that appear in declarative list Decls and
+ -- append their entities to Result.
+
+ ------------------------------------
+ -- Collect_Hidden_States_In_Decls --
+ ------------------------------------
+
+ procedure Collect_Hidden_States_In_Decls (Decls : List_Id) is
+ procedure Collect_Abstract_States (States : Elist_Id);
+ -- Copy the abstract states defined in list States to list Result
+
+ -----------------------------
+ -- Collect_Abstract_States --
+ -----------------------------
+
+ procedure Collect_Abstract_States (States : Elist_Id) is
+ State_Elmt : Elmt_Id;
+
+ begin
+ State_Elmt := First_Elmt (States);
+ while Present (State_Elmt) loop
+ Add_Item (Node (State_Elmt), Hidden_States);
+
+ Next_Elmt (State_Elmt);
+ end loop;
+ end Collect_Abstract_States;
+
+ -- Local variables
+
+ Decl : Node_Id;
+
+ -- Start of processing for Collect_Hidden_States_In_Decls
+
+ begin
+ Decl := First (Decls);
+ while Present (Decl) loop
+
+ -- Source objects (non-constants) are valid hidden states
+
+ if Nkind (Decl) = N_Object_Declaration
+ and then Ekind (Defining_Entity (Decl)) = E_Variable
+ and then Comes_From_Source (Decl)
+ then
+ Add_Item (Defining_Entity (Decl), Hidden_States);
+
+ -- Gather the abstract states of a package along with all
+ -- hidden states in its visible declarations.
+
+ elsif Nkind (Decl) = N_Package_Declaration then
+ Collect_Abstract_States
+ (Abstract_States (Defining_Entity (Decl)));
+
+ Collect_Hidden_States_In_Decls
+ (Visible_Declarations (Specification (Decl)));
+ end if;
+
+ Next (Decl);
+ end loop;
+ end Collect_Hidden_States_In_Decls;
+
+ -- Local variables
+
+ Pack_Spec : constant Node_Id := Package_Specification (Spec_Id);
+
+ -- Start of processing for Collect_Hidden_States
+
+ begin
+ -- Process the private declarations of the package spec and the
+ -- declarations of the body.
+
+ Collect_Hidden_States_In_Decls (Private_Declarations (Pack_Spec));
+ Collect_Hidden_States_In_Decls (Declarations (Pack_Body));
+ end Collect_Hidden_States;
+
+ -----------------------------
+ -- Report_Unrefined_States --
+ -----------------------------
+
+ procedure Report_Unrefined_States is
+ State_Elmt : Elmt_Id;
+
+ begin
+ if Present (Abstr_States) then
+ State_Elmt := First_Elmt (Abstr_States);
+ while Present (State_Elmt) loop
+ Error_Msg_N
+ ("abstract state & must be refined", Node (State_Elmt));
+
+ Next_Elmt (State_Elmt);
+ end loop;
+ end if;
+ end Report_Unrefined_States;
+
+ ---------------------------------
+ -- Report_Unused_Hidden_States --
+ ---------------------------------
+
+ procedure Report_Unused_Hidden_States is
+ Posted : Boolean := False;
+ State_Elmt : Elmt_Id;
+ State_Id : Entity_Id;
+
+ begin
+ if Present (Hidden_States) then
+ State_Elmt := First_Elmt (Hidden_States);
+ while Present (State_Elmt) loop
+ State_Id := Node (State_Elmt);
+
+ -- Generate an error message of the form:
+
+ -- package ... has unused hidden states
+ -- abstract state ... defined at ...
+ -- variable ... defined at ...
+
+ if not Posted then
+ Posted := True;
+ Error_Msg_NE
+ ("package & has unused hidden states", N, Spec_Id);
+ end if;
+
+ Error_Msg_Sloc := Sloc (State_Id);
+
+ if Ekind (State_Id) = E_Abstract_State then
+ Error_Msg_NE ("\ abstract state & defined #", N, State_Id);
+ else
+ Error_Msg_NE ("\ variable & defined #", N, State_Id);
+ end if;
+
+ Next_Elmt (State_Elmt);
+ end loop;
+ end if;
+ end Report_Unused_Hidden_States;
+
+ -- Local declarations
+
+ Clauses : constant Node_Id :=
+ Get_Pragma_Arg (First (Pragma_Argument_Associations (N)));
+ Clause : Node_Id;
+
+ -- Start of processing for Analyze_Refined_State_In_Decl_Part
+
+ begin
+ Set_Analyzed (N);
+
+ -- Initialize the various lists used during analysis
+
+ Abstr_States := New_Copy_Elist (Abstract_States (Spec_Id));
+ Collect_Hidden_States;
+
+ -- Multiple state refinements appear as an aggregate
+
+ if Nkind (Clauses) = N_Aggregate then
+ if Present (Expressions (Clauses)) then
+ Error_Msg_N
+ ("state refinements must appear as component associations",
+ Clauses);
+
+ else pragma Assert (Present (Component_Associations (Clauses)));
+ Clause := First (Component_Associations (Clauses));
+ while Present (Clause) loop
+ Analyze_Refinement_Clause (Clause);
+
+ Next (Clause);
+ end loop;
+ end if;
+
+ -- Various forms of a single state refinement. Note that these may
+ -- include malformed refinements.
+
+ else
+ Analyze_Refinement_Clause (Clauses);
+ end if;
+
+ -- Ensure that all abstract states have been refined and all hidden
+ -- states of the related package unilized in refinements.
+
+ Report_Unrefined_States;
+ Report_Unused_Hidden_States;
+ end Analyze_Refined_State_In_Decl_Part;
+
------------------------------------
-- Analyze_Test_Case_In_Decl_Part --
------------------------------------
@@ -18380,7 +22018,7 @@ package body Sem_Prag is
PP : Node_Id;
Policy : Name_Id;
- Ename : constant Name_Id := Original_Name (N);
+ Ename : constant Name_Id := Original_Aspect_Name (N);
begin
-- No effect if not valid assertion kind name
@@ -18450,6 +22088,153 @@ package body Sem_Prag is
end if;
end Check_Applicable_Policy;
+ --------------------------
+ -- Collect_Global_Items --
+ --------------------------
+
+ procedure Collect_Global_Items
+ (Prag : Node_Id;
+ In_Items : in out Elist_Id;
+ In_Out_Items : in out Elist_Id;
+ Out_Items : in out Elist_Id;
+ Has_In_State : out Boolean;
+ Has_In_Out_State : out Boolean;
+ Has_Out_State : out Boolean;
+ Has_Null_State : out Boolean)
+ is
+ procedure Process_Global_List
+ (List : Node_Id;
+ Mode : Name_Id := Name_Input);
+ -- Collect all items housed in a global list. Formal Mode denotes the
+ -- current mode in effect.
+
+ -------------------------
+ -- Process_Global_List --
+ -------------------------
+
+ procedure Process_Global_List
+ (List : Node_Id;
+ Mode : Name_Id := Name_Input)
+ is
+ procedure Process_Global_Item (Item : Node_Id; Mode : Name_Id);
+ -- Add a single item to the appropriate list. Formal Mode denotes the
+ -- current mode in effect.
+
+ -------------------------
+ -- Process_Global_Item --
+ -------------------------
+
+ procedure Process_Global_Item (Item : Node_Id; Mode : Name_Id) is
+ Item_Id : constant Entity_Id := Entity_Of (Item);
+
+ begin
+ -- Signal that the global list contains at least one abstract
+ -- state with a visible refinement. Note that the refinement may
+ -- be null in which case there are no constituents.
+
+ if Ekind (Item_Id) = E_Abstract_State then
+ if Has_Null_Refinement (Item_Id) then
+ Has_Null_State := True;
+
+ elsif Has_Non_Null_Refinement (Item_Id) then
+ if Mode = Name_Input then
+ Has_In_State := True;
+ elsif Mode = Name_In_Out then
+ Has_In_Out_State := True;
+ elsif Mode = Name_Output then
+ Has_Out_State := True;
+ end if;
+ end if;
+ end if;
+
+ -- Add the item to the proper list
+
+ if Mode = Name_Input then
+ Add_Item (Item_Id, In_Items);
+ elsif Mode = Name_In_Out then
+ Add_Item (Item_Id, In_Out_Items);
+ elsif Mode = Name_Output then
+ Add_Item (Item_Id, Out_Items);
+ end if;
+ end Process_Global_Item;
+
+ -- Local variables
+
+ Item : Node_Id;
+
+ -- Start of processing for Process_Global_List
+
+ begin
+ if Nkind (List) = N_Null then
+ null;
+
+ -- Single global item declaration
+
+ elsif Nkind_In (List, N_Expanded_Name,
+ N_Identifier,
+ N_Selected_Component)
+ then
+ Process_Global_Item (List, Mode);
+
+ -- Single global list or moded global list declaration
+
+ elsif Nkind (List) = N_Aggregate then
+
+ -- The declaration of a simple global list appear as a collection
+ -- of expressions.
+
+ if Present (Expressions (List)) then
+ Item := First (Expressions (List));
+ while Present (Item) loop
+ Process_Global_Item (Item, Mode);
+
+ Next (Item);
+ end loop;
+
+ -- The declaration of a moded global list appears as a collection
+ -- of component associations where individual choices denote mode.
+
+ elsif Present (Component_Associations (List)) then
+ Item := First (Component_Associations (List));
+ while Present (Item) loop
+ Process_Global_List
+ (List => Expression (Item),
+ Mode => Chars (First (Choices (Item))));
+
+ Next (Item);
+ end loop;
+
+ -- Invalid tree
+
+ else
+ raise Program_Error;
+ end if;
+
+ -- Invalid list
+
+ else
+ raise Program_Error;
+ end if;
+ end Process_Global_List;
+
+ -- Local variables
+
+ Items : constant Node_Id :=
+ Get_Pragma_Arg (First (Pragma_Argument_Associations (Prag)));
+
+ -- Start of processing for Collect_Global_Items
+
+ begin
+ -- Assume that no states have been encountered
+
+ Has_In_State := False;
+ Has_In_Out_State := False;
+ Has_Out_State := False;
+ Has_Null_State := False;
+
+ Process_Global_List (Items);
+ end Collect_Global_Items;
+
---------------------------------------
-- Collect_Subprogram_Inputs_Outputs --
---------------------------------------
@@ -18499,17 +22284,20 @@ package body Sem_Prag is
-- Start of processing for Collect_Global_List
begin
+ if Nkind (List) = N_Null then
+ null;
+
-- Single global item declaration
- if Nkind_In (List, N_Expanded_Name,
- N_Identifier,
- N_Selected_Component)
+ elsif Nkind_In (List, N_Expanded_Name,
+ N_Identifier,
+ N_Selected_Component)
then
Collect_Global_Item (List, Mode);
-- Simple global list or moded global list declaration
- else
+ elsif Nkind (List) = N_Aggregate then
if Present (Expressions (List)) then
Item := First (Expressions (List));
while Present (Item) loop
@@ -18526,23 +22314,37 @@ package body Sem_Prag is
Next (Assoc);
end loop;
end if;
+
+ -- Invalid list
+
+ else
+ raise Program_Error;
end if;
end Collect_Global_List;
-- Local variables
- Formal : Entity_Id;
- Global : Node_Id;
- List : Node_Id;
+ Formal : Entity_Id;
+ Global : Node_Id;
+ List : Node_Id;
+ Spec_Id : Entity_Id;
-- Start of processing for Collect_Subprogram_Inputs_Outputs
begin
Global_Seen := False;
+ -- Find the entity of the corresponding spec when processing a body
+
+ if Ekind (Subp_Id) = E_Subprogram_Body then
+ Spec_Id := Corresponding_Spec (Parent (Parent (Subp_Id)));
+ else
+ Spec_Id := Subp_Id;
+ end if;
+
-- Process all formal parameters
- Formal := First_Formal (Subp_Id);
+ Formal := First_Formal (Spec_Id);
while Present (Formal) loop
if Ekind_In (Formal, E_In_Out_Parameter, E_In_Parameter) then
Add_Item (Formal, Subp_Inputs);
@@ -18550,29 +22352,47 @@ package body Sem_Prag is
if Ekind_In (Formal, E_In_Out_Parameter, E_Out_Parameter) then
Add_Item (Formal, Subp_Outputs);
+
+ -- Out parameters can act as inputs when the related type is
+ -- tagged, unconstrained array, unconstrained record or record
+ -- with unconstrained components.
+
+ if Ekind (Formal) = E_Out_Parameter
+ and then Is_Unconstrained_Or_Tagged_Item (Formal)
+ then
+ Add_Item (Formal, Subp_Inputs);
+ end if;
end if;
Next_Formal (Formal);
end loop;
- -- If the subprogram is subject to pragma Global, traverse all global
- -- lists and gather the relevant items.
+ -- When processing a subprogram body, look for pragma Refined_Global as
+ -- it provides finer granularity of inputs and outputs.
- Global := Find_Aspect (Subp_Id, Aspect_Global);
- if Present (Global) then
- Global_Seen := True;
+ if Ekind (Subp_Id) = E_Subprogram_Body then
+ Global := Get_Pragma (Subp_Id, Pragma_Refined_Global);
- -- Retrieve the pragma as it contains the analyzed lists
+ -- Subprogram declaration case, look for pragma Global
- Global := Aspect_Rep_Item (Global);
- List := Expression (First (Pragma_Argument_Associations (Global)));
+ else
+ Global := Get_Pragma (Spec_Id, Pragma_Global);
+ end if;
+
+ if Present (Global) then
+ Global_Seen := True;
+ List := Expression (First (Pragma_Argument_Associations (Global)));
-- The pragma may not have been analyzed because of the arbitrary
-- declaration order of aspects. Make sure that it is analyzed for
-- the purposes of item extraction.
if not Analyzed (List) then
- Analyze_Global_In_Decl_Part (Global);
+ if Pragma_Name (Global) = Name_Refined_Global then
+ Analyze_Refined_Global_In_Decl_Part (Global);
+ else
+ Analyze_Global_In_Decl_Part (Global);
+ end if;
end if;
-- Nothing to be done for a null global list
@@ -18593,77 +22413,92 @@ package body Sem_Prag is
Name_Priority_Specific_Dispatching);
end Delay_Config_Pragma_Analyze;
- -----------------------------
- -- Find_Related_Subprogram --
- -----------------------------
+ -------------------------------------
+ -- Find_Related_Subprogram_Or_Body --
+ -------------------------------------
- function Find_Related_Subprogram
- (Prag : Node_Id;
- Check_Duplicates : Boolean := False) return Node_Id
+ function Find_Related_Subprogram_Or_Body
+ (Prag : Node_Id;
+ Do_Checks : Boolean := False) return Node_Id
is
- Context : constant Node_Id := Parent (Prag);
- Nam : constant Name_Id := Pragma_Name (Prag);
- Elmt : Node_Id;
- Subp_Decl : Node_Id;
+ Context : constant Node_Id := Parent (Prag);
+ Nam : constant Name_Id := Pragma_Name (Prag);
+ Stmt : Node_Id;
+
+ Look_For_Body : constant Boolean :=
+ Nam_In (Nam, Name_Refined_Depends,
+ Name_Refined_Global,
+ Name_Refined_Post);
+ -- Refinement pragmas must be associated with a subprogram body [stub]
begin
pragma Assert (Nkind (Prag) = N_Pragma);
- -- If the pragma comes from an aspect, then what we want is the
- -- declaration to which the aspect is attached, i.e. its parent.
+ -- If the pragma is a byproduct of aspect expansion, return the related
+ -- context of the original aspect.
if Present (Corresponding_Aspect (Prag)) then
return Parent (Corresponding_Aspect (Prag));
end if;
- -- Otherwise the pragma must be a list element, and the first thing to
- -- do is to position past any previous pragmas or generated code. What
- -- we are doing here is looking for the preceding declaration. This is
- -- also where we will check for a duplicate pragma.
+ -- Otherwise the pragma is a source construct, most likely part of a
+ -- declarative list. Skip preceding declarations while looking for a
+ -- proper subprogram declaration.
pragma Assert (Is_List_Member (Prag));
- Elmt := Prag;
- loop
- Elmt := Prev (Elmt);
- exit when No (Elmt);
+ Stmt := Prev (Prag);
+ while Present (Stmt) loop
- -- Typically want we will want is the declaration original node. But
- -- for the generic subprogram case, don't go to to the original node,
- -- which is the unanalyzed tree: we need to attach the pre- and post-
- -- conditions to the analyzed version at this point. They propagate
- -- to the original tree when analyzing the corresponding body.
+ -- Skip prior pragmas, but check for duplicates
- if Nkind (Elmt) not in N_Generic_Declaration then
- Subp_Decl := Original_Node (Elmt);
- else
- Subp_Decl := Elmt;
- end if;
-
- -- Skip prior pragmas
-
- if Nkind (Subp_Decl) = N_Pragma then
- if Check_Duplicates and then Pragma_Name (Subp_Decl) = Nam then
+ if Nkind (Stmt) = N_Pragma then
+ if Do_Checks and then Pragma_Name (Stmt) = Nam then
Error_Msg_Name_1 := Nam;
- Error_Msg_Sloc := Sloc (Subp_Decl);
+ Error_Msg_Sloc := Sloc (Stmt);
Error_Msg_N ("pragma % duplicates pragma declared #", Prag);
end if;
+ -- Emit an error when a refinement pragma appears on an expression
+ -- function without a completion.
+
+ elsif Do_Checks
+ and then Look_For_Body
+ and then Nkind (Stmt) = N_Subprogram_Declaration
+ and then Nkind (Original_Node (Stmt)) = N_Expression_Function
+ and then not Has_Completion (Defining_Entity (Stmt))
+ then
+ Error_Msg_Name_1 := Nam;
+ Error_Msg_N
+ ("pragma % cannot apply to a stand alone expression function",
+ Prag);
+
+ return Empty;
+
+ -- The refinement pragma applies to a subprogram body stub
+
+ elsif Look_For_Body
+ and then Nkind (Stmt) = N_Subprogram_Body_Stub
+ then
+ return Stmt;
+
-- Skip internally generated code
- elsif not Comes_From_Source (Subp_Decl) then
+ elsif not Comes_From_Source (Stmt) then
null;
- -- Otherwise we have a declaration to return
+ -- Return the current construct which is either a subprogram body,
+ -- a subprogram declaration or is illegal.
else
- return Subp_Decl;
+ return Stmt;
end if;
+
+ Prev (Stmt);
end loop;
- -- We fell through, which means there was no declaration preceding the
- -- pragma (either it was the first element of the list, or we only had
- -- other pragmas and generated code before it).
+ -- If we fall through, then the pragma was either the first declaration
+ -- or it was preceded by other pragmas and no source constructs.
-- The pragma is associated with a library-level subprogram
@@ -18675,12 +22510,12 @@ package body Sem_Prag is
elsif Nkind (Context) = N_Subprogram_Body then
return Context;
- -- Otherwise no subprogram found, return original pragma
+ -- No candidate subprogram [body] found
else
- return Prag;
+ return Empty;
end if;
- end Find_Related_Subprogram;
+ end Find_Related_Subprogram_Or_Body;
-------------------------
-- Get_Base_Subprogram --
@@ -18943,7 +22778,9 @@ package body Sem_Prag is
Pragma_Import_Valued_Procedure => 0,
Pragma_Independent => 0,
Pragma_Independent_Components => 0,
+ Pragma_Initial_Condition => -1,
Pragma_Initialize_Scalars => -1,
+ Pragma_Initializes => -1,
Pragma_Inline => 0,
Pragma_Inline_Always => 0,
Pragma_Inline_Generic => 0,
@@ -18991,14 +22828,18 @@ package body Sem_Prag is
Pragma_Page => -1,
Pragma_Partition_Elaboration_Policy => -1,
Pragma_Passive => -1,
- Pragma_Preelaborable_Initialization => -1,
- Pragma_Polling => -1,
Pragma_Persistent_BSS => 0,
+ Pragma_Polling => -1,
+ Pragma_Post => -1,
Pragma_Postcondition => -1,
+ Pragma_Post_Class => -1,
+ Pragma_Pre => -1,
Pragma_Precondition => -1,
Pragma_Predicate => -1,
+ Pragma_Preelaborable_Initialization => -1,
Pragma_Preelaborate => -1,
Pragma_Preelaborate_05 => -1,
+ Pragma_Pre_Class => -1,
Pragma_Priority => -1,
Pragma_Priority_Specific_Dispatching => -1,
Pragma_Profile => 0,
@@ -19012,6 +22853,10 @@ package body Sem_Prag is
Pragma_Queuing_Policy => -1,
Pragma_Rational => -1,
Pragma_Ravenscar => -1,
+ Pragma_Refined_Depends => -1,
+ Pragma_Refined_Global => -1,
+ Pragma_Refined_Post => -1,
+ Pragma_Refined_State => -1,
Pragma_Relative_Deadline => -1,
Pragma_Remote_Access_Type => -1,
Pragma_Remote_Call_Interface => -1,
@@ -19050,6 +22895,8 @@ package body Sem_Prag is
Pragma_Thread_Local_Storage => 0,
Pragma_Time_Slice => -1,
Pragma_Title => -1,
+ Pragma_Type_Invariant => -1,
+ Pragma_Type_Invariant_Class => -1,
Pragma_Unchecked_Union => 0,
Pragma_Unimplemented_Unit => -1,
Pragma_Universal_Aliasing => -1,
@@ -19121,6 +22968,40 @@ package body Sem_Prag is
end if;
end Is_Non_Significant_Pragma_Reference;
+ ----------------
+ -- Is_Part_Of --
+ ----------------
+
+ function Is_Part_Of
+ (State : Entity_Id;
+ Ancestor : Entity_Id) return Boolean
+ is
+ Options : constant Node_Id := Parent (State);
+ Name : Node_Id;
+ Option : Node_Id;
+ Value : Node_Id;
+
+ begin
+ -- A state declaration with option Part_Of appears as an extension
+ -- aggregate with component associations.
+
+ if Nkind (Options) = N_Extension_Aggregate then
+ Option := First (Component_Associations (Options));
+ while Present (Option) loop
+ Name := First (Choices (Option));
+ Value := Expression (Option);
+
+ if Chars (Name) = Name_Part_Of then
+ return Entity (Value) = Ancestor;
+ end if;
+
+ Next (Option);
+ end loop;
+ end if;
+
+ return False;
+ end Is_Part_Of;
+
------------------------------
-- Is_Pragma_String_Literal --
------------------------------
@@ -19208,6 +23089,62 @@ package body Sem_Prag is
and then List_Containing (N) = Private_Declarations (Parent (N));
end Is_Private_SPARK_Mode;
+ -------------------------------------
+ -- Is_Unconstrained_Or_Tagged_Item --
+ -------------------------------------
+
+ function Is_Unconstrained_Or_Tagged_Item
+ (Item : Entity_Id) return Boolean
+ is
+ function Has_Unconstrained_Component (Typ : Entity_Id) return Boolean;
+ -- Determine whether record type Typ has at least one unconstrained
+ -- component.
+
+ ---------------------------------
+ -- Has_Unconstrained_Component --
+ ---------------------------------
+
+ function Has_Unconstrained_Component (Typ : Entity_Id) return Boolean is
+ Comp : Entity_Id;
+
+ begin
+ Comp := First_Component (Typ);
+ while Present (Comp) loop
+ if Is_Unconstrained_Or_Tagged_Item (Comp) then
+ return True;
+ end if;
+
+ Next_Component (Comp);
+ end loop;
+
+ return False;
+ end Has_Unconstrained_Component;
+
+ -- Local variables
+
+ Typ : constant Entity_Id := Etype (Item);
+
+ -- Start of processing for Is_Unconstrained_Or_Tagged_Item
+
+ begin
+ if Is_Tagged_Type (Typ) then
+ return True;
+
+ elsif Is_Array_Type (Typ) and then not Is_Constrained (Typ) then
+ return True;
+
+ elsif Is_Record_Type (Typ) then
+ if Has_Discriminants (Typ) and then not Is_Constrained (Typ) then
+ return True;
+ else
+ return Has_Unconstrained_Component (Typ);
+ end if;
+
+ else
+ return False;
+ end if;
+ end Is_Unconstrained_Or_Tagged_Item;
+
-----------------------------
-- Is_Valid_Assertion_Kind --
-----------------------------
@@ -19234,6 +23171,7 @@ package body Sem_Prag is
Name_Assume |
Name_Contract_Cases |
Name_Debug |
+ Name_Initial_Condition |
Name_Invariant |
Name_uInvariant |
Name_Loop_Invariant |
@@ -19241,6 +23179,7 @@ package body Sem_Prag is
Name_Postcondition |
Name_Precondition |
Name_Predicate |
+ Name_Refined_Post |
Name_Statement_Assertions => return True;
when others => return False;
@@ -19323,66 +23262,6 @@ package body Sem_Prag is
end if;
end Make_Aspect_For_PPC_In_Gen_Sub_Decl;
- -------------------
- -- Original_Name --
- -------------------
-
- function Original_Name (N : Node_Id) return Name_Id is
- Pras : Node_Id;
- Name : Name_Id;
-
- begin
- pragma Assert (Nkind_In (N, N_Aspect_Specification, N_Pragma));
- Pras := N;
-
- if Is_Rewrite_Substitution (Pras)
- and then Nkind (Original_Node (Pras)) = N_Pragma
- then
- Pras := Original_Node (Pras);
- end if;
-
- -- Case where we came from aspect specication
-
- if Nkind (Pras) = N_Pragma and then From_Aspect_Specification (Pras) then
- Pras := Corresponding_Aspect (Pras);
- end if;
-
- -- Get name from aspect or pragma
-
- if Nkind (Pras) = N_Pragma then
- Name := Pragma_Name (Pras);
- else
- Name := Chars (Identifier (Pras));
- end if;
-
- -- Deal with 'Class
-
- if Class_Present (Pras) then
- case Name is
-
- -- Names that need converting to special _xxx form
-
- when Name_Pre => Name := Name_uPre;
- when Name_Post => Name := Name_uPost;
- when Name_Invariant => Name := Name_uInvariant;
- when Name_Type_Invariant => Name := Name_uType_Invariant;
-
- -- Names already in special _xxx form (leave them alone)
-
- when Name_uPre => null;
- when Name_uPost => null;
- when Name_uInvariant => null;
- when Name_uType_Invariant => null;
-
- -- Anything else is impossible with Class_Present set True
-
- when others => raise Program_Error;
- end case;
- end if;
-
- return Name;
- end Original_Name;
-
-------------------------
-- Preanalyze_CTC_Args --
-------------------------
@@ -19446,6 +23325,137 @@ package body Sem_Prag is
end Process_Compilation_Unit_Pragmas;
+ ------------------------------------
+ -- Record_Possible_Body_Reference --
+ ------------------------------------
+
+ procedure Record_Possible_Body_Reference
+ (Item : Node_Id;
+ Item_Id : Entity_Id)
+ is
+ begin
+ if Is_Body_Name (Unit_Name (Get_Source_Unit (Item)))
+ and then Ekind (Item_Id) = E_Abstract_State
+ then
+ if not Has_Body_References (Item_Id) then
+ Set_Has_Body_References (Item_Id, True);
+ Set_Body_References (Item_Id, New_Elmt_List);
+ end if;
+
+ Append_Elmt (Item, Body_References (Item_Id));
+ end if;
+ end Record_Possible_Body_Reference;
+
+ ------------------------------
+ -- Relocate_Pragmas_To_Body --
+ ------------------------------
+
+ procedure Relocate_Pragmas_To_Body
+ (Subp_Body : Node_Id;
+ Target_Body : Node_Id := Empty)
+ is
+ procedure Relocate_Pragma (Prag : Node_Id);
+ -- Remove a single pragma from its current list and add it to the
+ -- declarations of the proper body (either Subp_Body or Target_Body).
+
+ ---------------------
+ -- Relocate_Pragma --
+ ---------------------
+
+ procedure Relocate_Pragma (Prag : Node_Id) is
+ Decls : List_Id;
+ Target : Node_Id;
+
+ begin
+ -- When subprogram stubs or expression functions are involves, the
+ -- destination declaration list belongs to the proper body.
+
+ if Present (Target_Body) then
+ Target := Target_Body;
+ else
+ Target := Subp_Body;
+ end if;
+
+ Decls := Declarations (Target);
+
+ if No (Decls) then
+ Decls := New_List;
+ Set_Declarations (Target, Decls);
+ end if;
+
+ -- Unhook the pragma from its current list
+
+ Remove (Prag);
+ Prepend (Prag, Decls);
+ end Relocate_Pragma;
+
+ -- Local variables
+
+ Body_Id : constant Entity_Id :=
+ Defining_Unit_Name (Specification (Subp_Body));
+ Next_Stmt : Node_Id;
+ Stmt : Node_Id;
+
+ -- Start of processing for Relocate_Pragmas_To_Body
+
+ begin
+ -- Do not process a body that comes from a separate unit as no construct
+ -- can possibly follow it.
+
+ if not Is_List_Member (Subp_Body) then
+ return;
+
+ -- Do not relocate pragmas that follow a stub if the stub does not have
+ -- a proper body.
+
+ elsif Nkind (Subp_Body) = N_Subprogram_Body_Stub
+ and then No (Target_Body)
+ then
+ return;
+
+ -- Do not process internally generated routine _Postconditions
+
+ elsif Ekind (Body_Id) = E_Procedure
+ and then Chars (Body_Id) = Name_uPostconditions
+ then
+ return;
+ end if;
+
+ -- Look at what is following the body. We are interested in certain kind
+ -- of pragmas (either from source or byproducts of expansion) that can
+ -- apply to a body [stub].
+
+ Stmt := Next (Subp_Body);
+ while Present (Stmt) loop
+
+ -- Preserve the following statement for iteration purposes due to a
+ -- possible relocation of a pragma.
+
+ Next_Stmt := Next (Stmt);
+
+ -- Move a candidate pragma following the body to the declarations of
+ -- the body.
+
+ if Nkind (Stmt) = N_Pragma
+ and then Pragma_On_Body_Or_Stub_OK (Get_Pragma_Id (Stmt))
+ then
+ Relocate_Pragma (Stmt);
+
+ -- Skip internally generated code
+
+ elsif not Comes_From_Source (Stmt) then
+ null;
+
+ -- No candidate pragmas are available for relocation
+
+ else
+ exit;
+ end if;
+
+ Stmt := Next_Stmt;
+ end loop;
+ end Relocate_Pragmas_To_Body;
+
----------------------------
-- Rewrite_Assertion_Kind --
----------------------------
@@ -19484,44 +23494,6 @@ package body Sem_Prag is
null;
end rv;
- -----------------------------------
- -- Requires_Profile_Installation --
- -----------------------------------
-
- function Requires_Profile_Installation
- (Prag : Node_Id;
- Subp : Node_Id) return Boolean
- is
- begin
- -- When aspects Depends and Global are associated with a subprogram
- -- declaration, their corresponding pragmas are analyzed at the end of
- -- the declarative part. This is done out of context, therefore the
- -- formals must be installed in visibility.
-
- if Nkind (Subp) = N_Subprogram_Declaration then
- return True;
-
- -- When aspects Depends and Global are associated with a subprogram body
- -- which is also a compilation unit, their corresponding pragmas appear
- -- in the Pragmas_After list. The Pragmas_After collection is analyzed
- -- out of context and the formals must be installed in visibility. This
- -- does not apply when the pragma is a source construct.
-
- elsif Nkind (Subp) = N_Subprogram_Body then
- if Nkind (Parent (Subp)) = N_Compilation_Unit then
- return Present (Corresponding_Aspect (Prag));
- else
- return False;
- end if;
-
- -- In all other cases the two corresponding pragmas are analyzed in
- -- context and the formals are already visibile.
-
- else
- return False;
- end if;
- end Requires_Profile_Installation;
-
--------------------------------
-- Set_Encoded_Interface_Name --
--------------------------------
diff --git a/gcc/ada/sem_prag.ads b/gcc/ada/sem_prag.ads
index ecfb3eda75a..c03799dd56f 100644
--- a/gcc/ada/sem_prag.ads
+++ b/gcc/ada/sem_prag.ads
@@ -26,11 +26,25 @@
-- Pragma handling is isolated in a separate package
-- (logically this processing belongs in chapter 4)
-with Namet; use Namet;
-with Types; use Types;
+with Namet; use Namet;
+with Snames; use Snames;
+with Types; use Types;
package Sem_Prag is
+ -- The following table lists all the implementation-defined pragmas that
+ -- may apply to a body stub (no language defined pragmas apply). The table
+ -- should be synchronized with Aspect_On_Body_Or_Stub_OK in unit Aspects if
+ -- the pragmas below implement an aspect.
+
+ Pragma_On_Body_Or_Stub_OK : constant array (Pragma_Id) of Boolean :=
+ (Pragma_Refined_Depends => True,
+ Pragma_Refined_Global => True,
+ Pragma_Refined_Post => True,
+ Pragma_SPARK_Mode => True,
+ Pragma_Warnings => True,
+ others => False);
+
-----------------
-- Subprograms --
-----------------
@@ -42,26 +56,47 @@ package Sem_Prag is
-- Perform full analysis and expansion of delayed pragma Contract_Cases
procedure Analyze_Depends_In_Decl_Part (N : Node_Id);
- -- Perform full analysis of delayed pragma Depends
+ -- Perform full analysis of delayed pragma Depends. This routine is also
+ -- capable of performing basic analysis of pragma Refined_Depends.
procedure Analyze_Global_In_Decl_Part (N : Node_Id);
- -- Perform full analysis of delayed pragma Global
+ -- Perform full analysis of delayed pragma Global. This routine is also
+ -- capable of performing basic analysis of pragma Refind_Global.
+
+ procedure Analyze_Initial_Condition_In_Decl_Part (N : Node_Id);
+ -- Perform full analysis of delayed pragma Initial_Condition
+
+ procedure Analyze_Initializes_In_Decl_Part (N : Node_Id);
+ -- Perform full analysis of delayed pragma Initializes
- procedure Analyze_PPC_In_Decl_Part (N : Node_Id; S : Entity_Id);
- -- Special analyze routine for precondition/postcondition pragma that
- -- appears within a declarative part where the pragma is associated
- -- with a subprogram specification. N is the pragma node, and S is the
- -- entity for the related subprogram. This procedure does a preanalysis
- -- of the expressions in the pragma as "spec expressions" (see section
- -- in Sem "Handling of Default and Per-Object Expressions...").
+ procedure Analyze_Pre_Post_Condition_In_Decl_Part
+ (Prag : Node_Id;
+ Subp_Id : Entity_Id);
+ -- Perform preanalysis of a [refined] precondition or postcondition that
+ -- appears on a subprogram declaration or body [stub]. Prag denotes the
+ -- pragma, Subp_Id is the entity of the related subprogram. The preanalysis
+ -- of the expression is done as "spec expression" (see section "Handling
+ -- of Default and Per-Object Expressions in Sem).
+
+ procedure Analyze_Refined_Depends_In_Decl_Part (N : Node_Id);
+ -- Preform full analysis of delayed pragma Refined_Depends. This routine
+ -- uses Analyze_Depends_In_Decl_Part as a starting point, then performs
+ -- various consistency checks between Depends and Refined_Depends.
+
+ procedure Analyze_Refined_Global_In_Decl_Part (N : Node_Id);
+ -- Perform full analysis of delayed pragma Refined_Global. This routine
+ -- uses Analyze_Global_In_Decl_Part as a starting point, then performs
+ -- various consistency checks between Global and Refined_Global.
+
+ procedure Analyze_Refined_State_In_Decl_Part (N : Node_Id);
+ -- Perform full analysis of delayed pragma Refined_State
procedure Analyze_Test_Case_In_Decl_Part (N : Node_Id; S : Entity_Id);
- -- Special analyze routine for contract-case and test-case pragmas that
- -- appears within a declarative part where the pragma is associated with
- -- a subprogram specification. N is the pragma node, and S is the entity
- -- for the related subprogram. This procedure does a preanalysis of the
- -- expressions in the pragma as "spec expressions" (see section in Sem
- -- "Handling of Default and Per-Object Expressions...").
+ -- Perform preanalysis of pragma Test_Case that applies to a subprogram
+ -- declaration. Parameter N denotes the pragma, S is the entity of the
+ -- related subprogram. The preanalysis of the expression is done as "spec
+ -- expression" (see section "Handling of Default and Per-Object Expressions
+ -- in Sem).
procedure Check_Applicable_Policy (N : Node_Id);
-- N is either an N_Aspect or an N_Pragma node. There are two cases. If
@@ -155,6 +190,15 @@ package Sem_Prag is
-- Suppress_All at this stage, since it can appear after the unit instead
-- of before (actually we allow it to appear anywhere).
+ procedure Relocate_Pragmas_To_Body
+ (Subp_Body : Node_Id;
+ Target_Body : Node_Id := Empty);
+ -- Resocate all pragmas that follow and apply to subprogram body Subp_Body
+ -- to its own declaration list. Candidate pragmas are classified in table
+ -- Pragma_On_Body_Or_Stub_OK. If Target_Body is set, the pragma are moved
+ -- to the declarations of Target_Body. This formal should be set when
+ -- dealing with subprogram body stubs or expression functions.
+
procedure Set_Encoded_Interface_Name (E : Entity_Id; S : Node_Id);
-- This routine is used to set an encoded interface name. The node S is an
-- N_String_Literal node for the external name to be set, and E is an
diff --git a/gcc/ada/sem_res.adb b/gcc/ada/sem_res.adb
index 387e06f31db..9a76e04adf6 100644
--- a/gcc/ada/sem_res.adb
+++ b/gcc/ada/sem_res.adb
@@ -2095,10 +2095,19 @@ package body Sem_Res is
Check_Parameterless_Call (N);
+ -- The resolution of an Expression_With_Actions is determined by
+ -- its Expression.
+
+ if Nkind (N) = N_Expression_With_Actions then
+ Resolve (Expression (N), Typ);
+
+ Found := True;
+ Expr_Type := Etype (Expression (N));
+
-- If not overloaded, then we know the type, and all that needs doing
-- is to check that this type is compatible with the context.
- if not Is_Overloaded (N) then
+ elsif not Is_Overloaded (N) then
Found := Covers (Typ, Etype (N));
Expr_Type := Etype (N);
@@ -3602,7 +3611,7 @@ package body Sem_Res is
and then Full_Expander_Active
and then (Is_Controlled (Etype (F)) or else Has_Task (Etype (F)))
then
- Establish_Transient_Scope (A, False);
+ Establish_Transient_Scope (A, Sec_Stack => False);
Resolve (A, Etype (F));
-- A small optimization: if one of the actuals is a concatenation
@@ -3621,7 +3630,7 @@ package body Sem_Res is
and then Chars (Nam) = Name_Asm)
and then not Static_Concatenation (A)
then
- Establish_Transient_Scope (A, False);
+ Establish_Transient_Scope (A, Sec_Stack => False);
Resolve (A, Etype (F));
else
@@ -3634,7 +3643,7 @@ package body Sem_Res is
then
Error_Msg_N
("conversion between unrelated limited array types "
- & "not allowed (\A\I-00246)", A);
+ & "not allowed ('A'I-00246)", A);
if Is_Limited_Type (Etype (F)) then
Explain_Limited_Type (Etype (F), A);
@@ -3666,8 +3675,8 @@ package body Sem_Res is
then
New_Itype := Create_Itype (E_Anonymous_Access_Type, A);
Set_Etype (New_Itype, Etype (A));
- Set_Directly_Designated_Type (New_Itype,
- Directly_Designated_Type (Etype (A)));
+ Set_Directly_Designated_Type
+ (New_Itype, Directly_Designated_Type (Etype (A)));
Set_Etype (A, New_Itype);
end if;
@@ -3680,7 +3689,7 @@ package body Sem_Res is
if (Is_Controlled (DDT) or else Has_Task (DDT))
and then Full_Expander_Active
then
- Establish_Transient_Scope (A, False);
+ Establish_Transient_Scope (A, Sec_Stack => False);
end if;
end;
@@ -3701,7 +3710,7 @@ package body Sem_Res is
if Is_Tagged_Type (F_Typ)
and then (Is_Concurrent_Type (F_Typ)
- or else Is_Concurrent_Record_Type (F_Typ))
+ or else Is_Concurrent_Record_Type (F_Typ))
then
-- If the actual is overloaded, look for an interpretation
-- that has a synchronized type.
@@ -3768,10 +3777,10 @@ package body Sem_Res is
Resolve (A, Etype (F));
end if;
end;
- else
- -- not a synchronized operation.
+ -- Not a synchronized operation
+ else
Resolve (A, Etype (F));
end if;
end if;
@@ -3933,6 +3942,16 @@ package body Sem_Res is
and then not Is_Init_Proc (Nam)
then
Error_Msg_NE ("actual for& must be a variable", A, F);
+
+ if Is_Subprogram (Current_Scope)
+ and then
+ (Is_Invariant_Procedure (Current_Scope)
+ or else Is_Predicate_Function (Current_Scope))
+ then
+ Error_Msg_N
+ ("function used in predicate cannot "
+ & "modify its argument", F);
+ end if;
end if;
-- What's the following about???
@@ -4155,7 +4174,7 @@ package body Sem_Res is
and then (Is_Class_Wide_Type (Designated_Type (A_Typ))
or else (Nkind (A) = N_Attribute_Reference
and then
- Is_Class_Wide_Type (Etype (Prefix (A)))))
+ Is_Class_Wide_Type (Etype (Prefix (A)))))
and then not Is_Class_Wide_Type (Designated_Type (F_Typ))
and then not Is_Controlling_Formal (F)
@@ -4179,12 +4198,14 @@ package body Sem_Res is
Eval_Actual (A);
-- If it is a named association, treat the selector_name as a
- -- proper identifier, and mark the corresponding entity. Ignore
- -- this reference in SPARK mode, as it refers to an entity not in
- -- scope at the point of reference, so the reference should be
- -- ignored for computing effects of subprograms.
+ -- proper identifier, and mark the corresponding entity.
if Nkind (Parent (A)) = N_Parameter_Association
+
+ -- Ignore reference in SPARK mode, as it refers to an entity not
+ -- in scope at the point of reference, so the reference should
+ -- be ignored for computing effects of subprograms.
+
and then not SPARK_Mode
then
Set_Entity (Selector_Name (Parent (A)), F);
@@ -4344,7 +4365,7 @@ package body Sem_Res is
-- of the current b-i-p implementation to unify the handling for
-- multiple kinds of storage pools). ???
- if Is_Immutably_Limited_Type (Desig_T)
+ if Is_Limited_View (Desig_T)
and then Nkind (Expression (E)) = N_Function_Call
then
declare
@@ -4583,7 +4604,7 @@ package body Sem_Res is
if Ada_Version >= Ada_2012
and then Is_Limited_Type (Desig_T)
- and then not Is_Immutably_Limited_Type (Scope (Discr))
+ and then not Is_Limited_View (Scope (Discr))
then
Error_Msg_N
("only immutably limited types can have anonymous "
@@ -7262,6 +7283,17 @@ package body Sem_Res is
procedure Resolve_Expression_With_Actions (N : Node_Id; Typ : Entity_Id) is
begin
Set_Etype (N, Typ);
+
+ -- If N has no actions, and its expression has been constant folded,
+ -- then rewrite N as just its expression. Note, we can't do this in
+ -- the general case of Is_Empty_List (Actions (N)) as this would cause
+ -- Expression (N) to be expanded again.
+
+ if Is_Empty_List (Actions (N))
+ and then Compile_Time_Known_Value (Expression (N))
+ then
+ Rewrite (N, Expression (N));
+ end if;
end Resolve_Expression_With_Actions;
---------------------------
@@ -8295,19 +8327,22 @@ package body Sem_Res is
begin
-- Catch attempts to do fixed-point exponentiation with universal
-- operands, which is a case where the illegality is not caught during
- -- normal operator analysis.
+ -- normal operator analysis. This is not done in preanalysis mode
+ -- since the tree is not fully decorated during preanalysis.
- if Is_Fixed_Point_Type (Typ) and then Comes_From_Source (N) then
- Error_Msg_N ("exponentiation not available for fixed point", N);
- return;
+ if Full_Analysis then
+ if Is_Fixed_Point_Type (Typ) and then Comes_From_Source (N) then
+ Error_Msg_N ("exponentiation not available for fixed point", N);
+ return;
- elsif Nkind (Parent (N)) in N_Op
- and then Is_Fixed_Point_Type (Etype (Parent (N)))
- and then Etype (N) = Universal_Real
- and then Comes_From_Source (N)
- then
- Error_Msg_N ("exponentiation not available for fixed point", N);
- return;
+ elsif Nkind (Parent (N)) in N_Op
+ and then Is_Fixed_Point_Type (Etype (Parent (N)))
+ and then Etype (N) = Universal_Real
+ and then Comes_From_Source (N)
+ then
+ Error_Msg_N ("exponentiation not available for fixed point", N);
+ return;
+ end if;
end if;
if Comes_From_Source (N)
@@ -8326,7 +8361,7 @@ package body Sem_Res is
end if;
-- We do the resolution using the base type, because intermediate values
- -- in expressions always are of the base type, not a subtype of it.
+ -- in expressions are always of the base type, not a subtype of it.
Resolve (Left_Opnd (N), B_Typ);
Resolve (Right_Opnd (N), Standard_Integer);
@@ -8981,6 +9016,30 @@ package body Sem_Res is
R : constant Node_Id := Right_Opnd (N);
begin
+ -- Ensure all actions associated with the left operand (e.g.
+ -- finalization of transient controlled objects) are fully evaluated
+ -- locally within an expression with actions. This is particularly
+ -- helpful for coverage analysis. However this should not happen in
+ -- generics.
+
+ if Full_Expander_Active then
+ declare
+ Reloc_L : constant Node_Id := Relocate_Node (L);
+ begin
+ Save_Interps (Old_N => L, New_N => Reloc_L);
+
+ Rewrite (L,
+ Make_Expression_With_Actions (Sloc (L),
+ Actions => New_List,
+ Expression => Reloc_L));
+
+ -- Set Comes_From_Source on L to preserve warnings for unset
+ -- reference.
+
+ Set_Comes_From_Source (L, Comes_From_Source (Reloc_L));
+ end;
+ end if;
+
Resolve (L, B_Typ);
Resolve (R, B_Typ);
@@ -9843,7 +9902,7 @@ package body Sem_Res is
-- Ada 2005 (AI-217): Handle entities from limited views
- if From_With_Type (Opnd) then
+ if From_Limited_With (Opnd) then
Error_Msg_Qual_Level := 99;
Error_Msg_NE -- CODEFIX
("missing WITH clause on package &", N,
@@ -9852,7 +9911,7 @@ package body Sem_Res is
("type conversions require visibility of the full view",
N);
- elsif From_With_Type (Target)
+ elsif From_Limited_With (Target)
and then not
(Is_Access_Type (Target_Typ)
and then Present (Non_Limited_View (Etype (Target))))
@@ -10856,7 +10915,7 @@ package body Sem_Res is
-- it to determine whether the conversion is legal.
elsif Is_Class_Wide_Type (Opnd_Type)
- and then From_With_Type (Opnd_Type)
+ and then From_Limited_With (Opnd_Type)
and then Present (Non_Limited_View (Etype (Opnd_Type)))
and then Is_Interface (Non_Limited_View (Etype (Opnd_Type)))
then
@@ -11331,7 +11390,7 @@ package body Sem_Res is
-- Handle the limited view of a type
if Is_Incomplete_Type (Desig)
- and then From_With_Type (Desig)
+ and then From_Limited_With (Desig)
and then Present (Non_Limited_View (Desig))
then
return Available_View (Desig);
diff --git a/gcc/ada/sem_type.adb b/gcc/ada/sem_type.adb
index 78e49224e59..8e0fd5fa80d 100644
--- a/gcc/ada/sem_type.adb
+++ b/gcc/ada/sem_type.adb
@@ -1127,7 +1127,7 @@ package body Sem_Type is
then
return Covers (Designated_Type (T1), Designated_Type (T2))
or else
- (From_With_Type (Designated_Type (T1))
+ (From_Limited_With (Designated_Type (T1))
and then Covers (Designated_Type (T2), Designated_Type (T1)));
-- A boolean operation on integer literals is compatible with modular
@@ -1205,7 +1205,7 @@ package body Sem_Type is
-- Ada 2005 (AI-50217): Additional branches to make the shadow entity
-- obtained through a limited_with compatible with its real entity.
- elsif From_With_Type (T1) then
+ elsif From_Limited_With (T1) then
-- If the expected type is the non-limited view of a type, the
-- expression may have the limited view. If that one in turn is
@@ -1221,7 +1221,7 @@ package body Sem_Type is
return False;
end if;
- elsif From_With_Type (T2) then
+ elsif From_Limited_With (T2) then
-- If units in the context have Limited_With clauses on each other,
-- either type might have a limited view. Checks performed elsewhere
@@ -2611,8 +2611,13 @@ package body Sem_Type is
begin
AI := First (Interface_List (Parent (Target_Typ)));
+
+ -- The progenitor itself may be a subtype of an interface type.
+
while Present (AI) loop
- if Etype (AI) = Iface_Typ then
+ if Etype (AI) = Iface_Typ
+ or else Base_Type (Etype (AI)) = Iface_Typ
+ then
return True;
elsif Present (Interfaces (Etype (AI)))
@@ -3204,6 +3209,8 @@ package body Sem_Type is
begin
if Is_Overloaded (Old_N) then
+ Set_Is_Overloaded (New_N);
+
if Nkind (Old_N) = N_Selected_Component
and then Is_Overloaded (Selector_Name (Old_N))
then
diff --git a/gcc/ada/sem_type.ads b/gcc/ada/sem_type.ads
index 2c5c1dba778..60eefa51c75 100644
--- a/gcc/ada/sem_type.ads
+++ b/gcc/ada/sem_type.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 1992-2011, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -124,7 +124,7 @@ package Sem_Type is
-- denotes whether an interpretation has been disabled by an abstract
-- operator. Add_One_Interp includes semantic processing to deal with
-- adding entries that hide one another etc.
-
+ --
-- For operators, the legality of the operation depends on the visibility
-- of T and its scope. If the operator is an equality or comparison, T is
-- always Boolean, and we use Opnd_Type, which is a candidate type for one
@@ -158,8 +158,9 @@ package Sem_Type is
procedure Save_Interps (Old_N : Node_Id; New_N : Node_Id);
-- If an overloaded node is rewritten during semantic analysis, its
-- possible interpretations must be linked to the copy. This procedure
- -- transfers the overload information from Old_N, the old node, to
- -- New_N, its new copy. It has no effect in the non-overloaded case.
+ -- transfers the overload information (Is_Overloaded flag, and list of
+ -- interpretations) from Old_N, the old node, to New_N, its new copy.
+ -- It has no effect in the non-overloaded case.
function Covers (T1, T2 : Entity_Id) return Boolean;
-- This is the basic type compatibility routine. T1 is the expected type,
diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb
index dcad44f1bba..08acd702caf 100644
--- a/gcc/ada/sem_util.adb
+++ b/gcc/ada/sem_util.adb
@@ -27,8 +27,8 @@ with Atree; use Atree;
with Casing; use Casing;
with Checks; use Checks;
with Debug; use Debug;
-with Errout; use Errout;
with Elists; use Elists;
+with Errout; use Errout;
with Exp_Ch11; use Exp_Ch11;
with Exp_Disp; use Exp_Disp;
with Exp_Util; use Exp_Util;
@@ -212,25 +212,114 @@ package body Sem_Util is
-- Add_Contract_Item --
-----------------------
- procedure Add_Contract_Item (Item : Node_Id; Subp_Id : Entity_Id) is
- Items : constant Node_Id := Contract (Subp_Id);
+ procedure Add_Contract_Item (Prag : Node_Id; Id : Entity_Id) is
+ Items : constant Node_Id := Contract (Id);
Nam : Name_Id;
+ N : Node_Id;
begin
- if Present (Items) and then Nkind (Item) = N_Pragma then
- Nam := Pragma_Name (Item);
+ -- The related context must have a contract and the item to be added
+ -- must be a pragma.
+
+ pragma Assert (Present (Items));
+ pragma Assert (Nkind (Prag) = N_Pragma);
+
+ Nam := Original_Aspect_Name (Prag);
+
+ -- Contract items related to [generic] packages. The applicable pragmas
+ -- are:
+ -- Abstract_States
+ -- Initial_Condition
+ -- Initializes
+
+ if Ekind_In (Id, E_Generic_Package, E_Package) then
+ if Nam_In (Nam, Name_Abstract_State,
+ Name_Initial_Condition,
+ Name_Initializes)
+ then
+ Set_Next_Pragma (Prag, Classifications (Items));
+ Set_Classifications (Items, Prag);
+
+ -- The pragma is not a proper contract item
+
+ else
+ raise Program_Error;
+ end if;
+
+ -- Contract items related to package bodies. The applicable pragmas are:
+ -- Refined_States
+
+ elsif Ekind (Id) = E_Package_Body then
+ if Nam = Name_Refined_State then
+ Set_Next_Pragma (Prag, Classifications (Items));
+ Set_Classifications (Items, Prag);
- if Nam_In (Nam, Name_Precondition, Name_Postcondition) then
- Set_Next_Pragma (Item, Pre_Post_Conditions (Items));
- Set_Pre_Post_Conditions (Items, Item);
+ -- The pragma is not a proper contract item
+
+ else
+ raise Program_Error;
+ end if;
+
+ -- Contract items related to subprogram or entry declarations. The
+ -- applicable pragmas are:
+ -- Contract_Cases
+ -- Depends
+ -- Global
+ -- Post
+ -- Postcondition
+ -- Pre
+ -- Precondition
+ -- Test_Case
+
+ elsif Ekind_In (Id, E_Entry, E_Entry_Family)
+ or else Is_Generic_Subprogram (Id)
+ or else Is_Subprogram (Id)
+ then
+ if Nam_In (Nam, Name_Precondition,
+ Name_Postcondition,
+ Name_Pre,
+ Name_Post,
+ Name_uPre,
+ Name_uPost)
+ then
+ -- Before we add a precondition or postcondition to the list,
+ -- make sure we do not have a disallowed duplicate, which can
+ -- happen if we use a pragma for Pre[_Class] or Post[_Class]
+ -- instead of the corresponding aspect.
+
+ if not From_Aspect_Specification (Prag)
+ and then Nam_In (Nam, Name_Pre_Class,
+ Name_Pre,
+ Name_uPre,
+ Name_Post_Class,
+ Name_Post,
+ Name_uPost)
+ then
+ N := Pre_Post_Conditions (Items);
+ while Present (N) loop
+ if not Split_PPC (N)
+ and then Original_Aspect_Name (N) = Nam
+ then
+ Error_Msg_Sloc := Sloc (N);
+ Error_Msg_NE
+ ("duplication of aspect for & given#", Prag, Id);
+ return;
+ else
+ N := Next_Pragma (N);
+ end if;
+ end loop;
+ end if;
+
+ Set_Next_Pragma (Prag, Pre_Post_Conditions (Items));
+ Set_Pre_Post_Conditions (Items, Prag);
elsif Nam_In (Nam, Name_Contract_Cases, Name_Test_Case) then
- Set_Next_Pragma (Item, Contract_Test_Cases (Items));
- Set_Contract_Test_Cases (Items, Item);
+ Set_Next_Pragma (Prag, Contract_Test_Cases (Items));
+ Set_Contract_Test_Cases (Items, Prag);
elsif Nam_In (Nam, Name_Depends, Name_Global) then
- Set_Next_Pragma (Item, Classifications (Items));
- Set_Classifications (Items, Item);
+ Set_Next_Pragma (Prag, Classifications (Items));
+ Set_Classifications (Items, Prag);
-- The pragma is not a proper contract item
@@ -238,10 +327,21 @@ package body Sem_Util is
raise Program_Error;
end if;
- -- The subprogram has not been properly decorated or the item is illegal
+ -- Contract items related to subprogram bodies. The applicable pragmas
+ -- are:
+ -- Refined_Depends
+ -- Refined_Global
- else
- raise Program_Error;
+ elsif Ekind (Id) = E_Subprogram_Body then
+ if Nam_In (Nam, Name_Refined_Depends, Name_Refined_Global) then
+ Set_Next_Pragma (Prag, Classifications (Items));
+ Set_Classifications (Items, Prag);
+
+ -- The pragma is not a proper contract item
+
+ else
+ raise Program_Error;
+ end if;
end if;
end Add_Contract_Item;
@@ -323,7 +423,7 @@ package body Sem_Util is
Decl := First
(Visible_Declarations
- (Specification (Unit_Declaration_Node (Current_Scope))));
+ (Package_Specification (Current_Scope)));
while Present (Decl) loop
if Nkind (Decl) = N_Private_Extension_Declaration
and then Defining_Entity (Decl) = Typ
@@ -1069,6 +1169,13 @@ package body Sem_Util is
return;
end if;
+ -- Ignore in ASIS mode, elaboration entity is not in source and plays
+ -- no role in analysis.
+
+ if ASIS_Mode then
+ return;
+ end if;
+
-- Construct name of elaboration entity as xxx_E, where xxx is the unit
-- name with dots replaced by double underscore. We have to manually
-- construct this name, since it will be elaborated in the outer scope,
@@ -1338,7 +1445,7 @@ package body Sem_Util is
-- Ada 2005 (AI-50217): If the type is available through a limited
-- with_clause, verify that its full view has been analyzed.
- if From_With_Type (T)
+ if From_Limited_With (T)
and then Present (Non_Limited_View (T))
and then Ekind (Non_Limited_View (T)) /= E_Incomplete_Type
then
@@ -3141,6 +3248,208 @@ package body Sem_Util is
end if;
end Conditional_Delay;
+ ----------------------------
+ -- Contains_Refined_State --
+ ----------------------------
+
+ function Contains_Refined_State (Prag : Node_Id) return Boolean is
+ function Has_State_In_Dependency (List : Node_Id) return Boolean;
+ -- Determine whether a dependency list mentions a state with a visible
+ -- refinement.
+
+ function Has_State_In_Global (List : Node_Id) return Boolean;
+ -- Determine whether a global list mentions a state with a visible
+ -- refinement.
+
+ function Is_Refined_State (Item : Node_Id) return Boolean;
+ -- Determine whether Item is a reference to an abstract state with a
+ -- visible refinement.
+
+ -----------------------------
+ -- Has_State_In_Dependency --
+ -----------------------------
+
+ function Has_State_In_Dependency (List : Node_Id) return Boolean is
+ Clause : Node_Id;
+ Output : Node_Id;
+
+ begin
+ -- A null dependency list does not mention any states
+
+ if Nkind (List) = N_Null then
+ return False;
+
+ -- Dependency clauses appear as component associations of an
+ -- aggregate.
+
+ elsif Nkind (List) = N_Aggregate
+ and then Present (Component_Associations (List))
+ then
+ Clause := First (Component_Associations (List));
+ while Present (Clause) loop
+
+ -- Inspect the outputs of a dependency clause
+
+ Output := First (Choices (Clause));
+ while Present (Output) loop
+ if Is_Refined_State (Output) then
+ return True;
+ end if;
+
+ Next (Output);
+ end loop;
+
+ -- Inspect the outputs of a dependency clause
+
+ if Is_Refined_State (Expression (Clause)) then
+ return True;
+ end if;
+
+ Next (Clause);
+ end loop;
+
+ -- If we get here, then none of the dependency clauses mention a
+ -- state with visible refinement.
+
+ return False;
+
+ -- An illegal pragma managed to sneak in
+
+ else
+ raise Program_Error;
+ end if;
+ end Has_State_In_Dependency;
+
+ -------------------------
+ -- Has_State_In_Global --
+ -------------------------
+
+ function Has_State_In_Global (List : Node_Id) return Boolean is
+ Item : Node_Id;
+
+ begin
+ -- A null global list does not mention any states
+
+ if Nkind (List) = N_Null then
+ return False;
+
+ -- Simple global list or moded global list declaration
+
+ elsif Nkind (List) = N_Aggregate then
+
+ -- The declaration of a simple global list appear as a collection
+ -- of expressions.
+
+ if Present (Expressions (List)) then
+ Item := First (Expressions (List));
+ while Present (Item) loop
+ if Is_Refined_State (Item) then
+ return True;
+ end if;
+
+ Next (Item);
+ end loop;
+
+ -- The declaration of a moded global list appears as a collection
+ -- of component associations where individual choices denote
+ -- modes.
+
+ else
+ Item := First (Component_Associations (List));
+ while Present (Item) loop
+ if Has_State_In_Global (Expression (Item)) then
+ return True;
+ end if;
+
+ Next (Item);
+ end loop;
+ end if;
+
+ -- If we get here, then the simple/moded global list did not
+ -- mention any states with a visible refinement.
+
+ return False;
+
+ -- Single global item declaration
+
+ elsif Is_Entity_Name (List) then
+ return Is_Refined_State (List);
+
+ -- An illegal pragma managed to sneak in
+
+ else
+ raise Program_Error;
+ end if;
+ end Has_State_In_Global;
+
+ ----------------------
+ -- Is_Refined_State --
+ ----------------------
+
+ function Is_Refined_State (Item : Node_Id) return Boolean is
+ Elmt : Node_Id;
+ Item_Id : Entity_Id;
+
+ begin
+ if Nkind (Item) = N_Null then
+ return False;
+
+ -- States cannot be subject to attribute 'Result. This case arises
+ -- in dependency relations.
+
+ elsif Nkind (Item) = N_Attribute_Reference
+ and then Attribute_Name (Item) = Name_Result
+ then
+ return False;
+
+ -- Multiple items appear as an aggregate. This case arises in
+ -- dependency relations.
+
+ elsif Nkind (Item) = N_Aggregate
+ and then Present (Expressions (Item))
+ then
+ Elmt := First (Expressions (Item));
+ while Present (Elmt) loop
+ if Is_Refined_State (Elmt) then
+ return True;
+ end if;
+
+ Next (Elmt);
+ end loop;
+
+ -- If we get here, then none of the inputs or outputs reference a
+ -- state with visible refinement.
+
+ return False;
+
+ -- Single item
+
+ else
+ Item_Id := Entity_Of (Item);
+
+ return
+ Ekind (Item_Id) = E_Abstract_State
+ and then Has_Visible_Refinement (Item_Id);
+ end if;
+ end Is_Refined_State;
+
+ -- Local variables
+
+ Arg : constant Node_Id :=
+ Get_Pragma_Arg (First (Pragma_Argument_Associations (Prag)));
+ Nam : constant Name_Id := Pragma_Name (Prag);
+
+ -- Start of processing for Contains_Refined_State
+
+ begin
+ if Nam = Name_Depends then
+ return Has_State_In_Dependency (Arg);
+
+ else pragma Assert (Nam = Name_Global);
+ return Has_State_In_Global (Arg);
+ end if;
+ end Contains_Refined_State;
+
-------------------------
-- Copy_Component_List --
-------------------------
@@ -4274,7 +4583,6 @@ package body Sem_Util is
procedure Ensure_Freeze_Node (E : Entity_Id) is
FN : Node_Id;
-
begin
if No (Freeze_Node (E)) then
FN := Make_Freeze_Entity (Sloc (E));
@@ -4567,9 +4875,14 @@ package body Sem_Util is
-- Inherited discriminants and components in derived record types are
-- immediately visible. Itypes are not.
+ -- Unless the Itype is for a record type with a corresponding remote
+ -- type (what is that about, it was not commented ???)
+
if Ekind_In (Def_Id, E_Discriminant, E_Component)
- or else (No (Corresponding_Remote_Type (Def_Id))
- and then not Is_Itype (Def_Id))
+ or else
+ ((not Is_Record_Type (Def_Id)
+ or else No (Corresponding_Remote_Type (Def_Id)))
+ and then not Is_Itype (Def_Id))
then
Set_Is_Immediately_Visible (Def_Id);
Set_Current_Entity (Def_Id);
@@ -4669,6 +4982,35 @@ package body Sem_Util is
end if;
end Enter_Name;
+ ---------------
+ -- Entity_Of --
+ ---------------
+
+ function Entity_Of (N : Node_Id) return Entity_Id is
+ Id : Entity_Id;
+
+ begin
+ Id := Empty;
+
+ if Is_Entity_Name (N) then
+ Id := Entity (N);
+
+ -- Follow a possible chain of renamings to reach the root renamed
+ -- object.
+
+ while Present (Id) and then Present (Renamed_Object (Id)) loop
+ if Is_Entity_Name (Renamed_Object (Id)) then
+ Id := Entity (Renamed_Object (Id));
+ else
+ Id := Empty;
+ exit;
+ end if;
+ end loop;
+ end if;
+
+ return Id;
+ end Entity_Of;
+
--------------------------
-- Explain_Limited_Type --
--------------------------
@@ -5184,9 +5526,9 @@ package body Sem_Util is
Discrim := First (Choices (Assoc));
exit Find_Constraint when Chars (Discrim_Name) = Chars (Discrim)
or else (Present (Corresponding_Discriminant (Entity (Discrim)))
- and then
- Chars (Corresponding_Discriminant (Entity (Discrim)))
- = Chars (Discrim_Name))
+ and then
+ Chars (Corresponding_Discriminant (Entity (Discrim))) =
+ Chars (Discrim_Name))
or else Chars (Original_Record_Component (Entity (Discrim)))
= Chars (Discrim_Name);
@@ -5274,7 +5616,6 @@ package body Sem_Util is
Find_Discrete_Value : while Present (Variant) loop
Discrete_Choice := First (Discrete_Choices (Variant));
while Present (Discrete_Choice) loop
-
exit Find_Discrete_Value when
Nkind (Discrete_Choice) = N_Others_Choice;
@@ -5305,8 +5646,8 @@ package body Sem_Util is
-- If we have found the corresponding choice, recursively add its
-- components to the Into list.
- Gather_Components (Empty,
- Component_List (Variant), Governed_By, Into, Report_Errors);
+ Gather_Components
+ (Empty, Component_List (Variant), Governed_By, Into, Report_Errors);
end Gather_Components;
------------------------
@@ -6441,6 +6782,51 @@ package body Sem_Util is
return False;
end Has_Interfaces;
+ ---------------------------------
+ -- Has_No_Obvious_Side_Effects --
+ ---------------------------------
+
+ function Has_No_Obvious_Side_Effects (N : Node_Id) return Boolean is
+ begin
+ -- For now, just handle literals, constants, and non-volatile
+ -- variables and expressions combining these with operators or
+ -- short circuit forms.
+
+ if Nkind (N) in N_Numeric_Or_String_Literal then
+ return True;
+
+ elsif Nkind (N) = N_Character_Literal then
+ return True;
+
+ elsif Nkind (N) in N_Unary_Op then
+ return Has_No_Obvious_Side_Effects (Right_Opnd (N));
+
+ elsif Nkind (N) in N_Binary_Op or else Nkind (N) in N_Short_Circuit then
+ return Has_No_Obvious_Side_Effects (Left_Opnd (N))
+ and then
+ Has_No_Obvious_Side_Effects (Right_Opnd (N));
+
+ elsif Nkind (N) = N_Expression_With_Actions
+ and then
+ Is_Empty_List (Actions (N))
+ then
+ return Has_No_Obvious_Side_Effects (Expression (N));
+
+ elsif Nkind (N) in N_Has_Entity then
+ return Present (Entity (N))
+ and then Ekind_In (Entity (N), E_Variable,
+ E_Constant,
+ E_Enumeration_Literal,
+ E_In_Parameter,
+ E_Out_Parameter,
+ E_In_Out_Parameter)
+ and then not Is_Volatile (Entity (N));
+
+ else
+ return False;
+ end if;
+ end Has_No_Obvious_Side_Effects;
+
------------------------
-- Has_Null_Exclusion --
------------------------
@@ -7794,7 +8180,7 @@ package body Sem_Util is
-- statement is aliased if its type is immutably limited.
or else (Is_Return_Object (E)
- and then Is_Immutably_Limited_Type (Etype (E)));
+ and then Is_Limited_View (Etype (E)));
elsif Nkind (Obj) = N_Selected_Component then
return Is_Aliased (Entity (Selector_Name (Obj)));
@@ -7929,6 +8315,17 @@ package body Sem_Util is
end if;
end Is_Atomic_Object;
+ -------------------------
+ -- Is_Attribute_Result --
+ -------------------------
+
+ function Is_Attribute_Result (N : Node_Id) return Boolean is
+ begin
+ return
+ Nkind (N) = N_Attribute_Reference
+ and then Attribute_Name (N) = Name_Result;
+ end Is_Attribute_Result;
+
------------------------------------
-- Is_Body_Or_Package_Declaration --
------------------------------------
@@ -7962,6 +8359,181 @@ package body Sem_Util is
Is_RTE (Root_Type (Under), RO_WW_Super_String));
end Is_Bounded_String;
+ -------------------------
+ -- Is_Child_Or_Sibling --
+ -------------------------
+
+ function Is_Child_Or_Sibling
+ (Pack_1 : Entity_Id;
+ Pack_2 : Entity_Id;
+ Private_Child : Boolean) return Boolean
+ is
+ function Distance_From_Standard (Pack : Entity_Id) return Nat;
+ -- Given an arbitrary package, return the number of "climbs" necessary
+ -- to reach scope Standard_Standard.
+
+ procedure Equalize_Depths
+ (Pack : in out Entity_Id;
+ Depth : in out Nat;
+ Depth_To_Reach : Nat);
+ -- Given an arbitrary package, its depth and a target depth to reach,
+ -- climb the scope chain until the said depth is reached. The pointer
+ -- to the package and its depth a modified during the climb.
+
+ function Is_Child (Pack : Entity_Id) return Boolean;
+ -- Given a package Pack, determine whether it is a child package that
+ -- satisfies the privacy requirement (if set).
+
+ ----------------------------
+ -- Distance_From_Standard --
+ ----------------------------
+
+ function Distance_From_Standard (Pack : Entity_Id) return Nat is
+ Dist : Nat;
+ Scop : Entity_Id;
+
+ begin
+ Dist := 0;
+ Scop := Pack;
+ while Present (Scop) and then Scop /= Standard_Standard loop
+ Dist := Dist + 1;
+ Scop := Scope (Scop);
+ end loop;
+
+ return Dist;
+ end Distance_From_Standard;
+
+ ---------------------
+ -- Equalize_Depths --
+ ---------------------
+
+ procedure Equalize_Depths
+ (Pack : in out Entity_Id;
+ Depth : in out Nat;
+ Depth_To_Reach : Nat)
+ is
+ begin
+ -- The package must be at a greater or equal depth
+
+ if Depth < Depth_To_Reach then
+ raise Program_Error;
+ end if;
+
+ -- Climb the scope chain until the desired depth is reached
+
+ while Present (Pack) and then Depth /= Depth_To_Reach loop
+ Pack := Scope (Pack);
+ Depth := Depth - 1;
+ end loop;
+ end Equalize_Depths;
+
+ --------------
+ -- Is_Child --
+ --------------
+
+ function Is_Child (Pack : Entity_Id) return Boolean is
+ begin
+ if Is_Child_Unit (Pack) then
+ if Private_Child then
+ return Is_Private_Descendant (Pack);
+ else
+ return True;
+ end if;
+
+ -- The package is nested, it cannot act a child or a sibling
+
+ else
+ return False;
+ end if;
+ end Is_Child;
+
+ -- Local variables
+
+ P_1 : Entity_Id := Pack_1;
+ P_1_Child : Boolean := False;
+ P_1_Depth : Nat := Distance_From_Standard (P_1);
+ P_2 : Entity_Id := Pack_2;
+ P_2_Child : Boolean := False;
+ P_2_Depth : Nat := Distance_From_Standard (P_2);
+
+ -- Start of processing for Is_Child_Or_Sibling
+
+ begin
+ pragma Assert
+ (Ekind (Pack_1) = E_Package and then Ekind (Pack_2) = E_Package);
+
+ -- Both packages denote the same entity, therefore they cannot be
+ -- children or siblings.
+
+ if P_1 = P_2 then
+ return False;
+
+ -- One of the packages is at a deeper level than the other. Note that
+ -- both may still come from differen hierarchies.
+
+ -- (root) P_2
+ -- / \ :
+ -- X P_2 or X
+ -- : :
+ -- P_1 P_1
+
+ elsif P_1_Depth > P_2_Depth then
+ Equalize_Depths (P_1, P_1_Depth, P_2_Depth);
+ P_1_Child := True;
+
+ -- (root) P_1
+ -- / \ :
+ -- P_1 X or X
+ -- : :
+ -- P_2 P_2
+
+ elsif P_2_Depth > P_1_Depth then
+ Equalize_Depths (P_2, P_2_Depth, P_1_Depth);
+ P_2_Child := True;
+ end if;
+
+ -- At this stage the package pointers have been elevated to the same
+ -- depth. If the related entities are the same, then one package is a
+ -- potential child of the other:
+
+ -- P_1
+ -- :
+ -- X became P_1 P_2 or vica versa
+ -- :
+ -- P_2
+
+ if P_1 = P_2 then
+ if P_1_Child then
+ return Is_Child (Pack_1);
+ else pragma Assert (P_2_Child);
+ return Is_Child (Pack_2);
+ end if;
+
+ -- The packages may come from the same package chain or from entirely
+ -- different hierarcies. To determine this, climb the scope stack until
+ -- a common root is found.
+
+ -- (root) (root 1) (root 2)
+ -- / \ | |
+ -- P_1 P_2 P_1 P_2
+
+ else
+ while Present (P_1) and then Present (P_2) loop
+
+ -- The two packages may be siblings
+
+ if P_1 = P_2 then
+ return Is_Child (Pack_1) and then Is_Child (Pack_2);
+ end if;
+
+ P_1 := Scope (P_1);
+ P_2 := Scope (P_2);
+ end loop;
+ end if;
+
+ return False;
+ end Is_Child_Or_Sibling;
+
-----------------------------
-- Is_Concurrent_Interface --
-----------------------------
@@ -8655,6 +9227,7 @@ package body Sem_Util is
return Is_Fully_Initialized_Variant (U);
end if;
end;
+
else
return False;
end if;
@@ -8787,7 +9360,7 @@ package body Sem_Util is
begin
return
Is_Class_Wide_Type (Typ)
- and then (Is_Limited_Type (Typ) or else From_With_Type (Typ));
+ and then (Is_Limited_Type (Typ) or else From_Limited_With (Typ));
end Is_Limited_Class_Wide_Type;
---------------------------------
@@ -8863,10 +9436,12 @@ package body Sem_Util is
when N_Function_Call =>
return Etype (N) /= Standard_Void_Type;
- -- Attributes 'Input and 'Result produce objects
+ -- Attributes 'Input, 'Old and 'Result produce objects
when N_Attribute_Reference =>
- return Nam_In (Attribute_Name (N), Name_Input, Name_Result);
+ return
+ Nam_In
+ (Attribute_Name (N), Name_Input, Name_Old, Name_Result);
when N_Selected_Component =>
return
@@ -9844,7 +10419,8 @@ package body Sem_Util is
function In_Protected_Function (E : Entity_Id) return Boolean;
-- Within a protected function, the private components of the enclosing
-- protected type are constants. A function nested within a (protected)
- -- procedure is not itself protected.
+ -- procedure is not itself protected. Within the body of a protected
+ -- function the current instance of the protected type is a constant.
function Is_Variable_Prefix (P : Node_Id) return Boolean;
-- Prefixes can involve implicit dereferences, in which case we must
@@ -9856,12 +10432,24 @@ package body Sem_Util is
---------------------------
function In_Protected_Function (E : Entity_Id) return Boolean is
- Prot : constant Entity_Id := Scope (E);
+ Prot : Entity_Id;
S : Entity_Id;
begin
+ -- E is the current instance of a type
+
+ if Is_Type (E) then
+ Prot := E;
+
+ -- E is an object
+
+ else
+ Prot := Scope (E);
+ end if;
+
if not Is_Protected_Type (Prot) then
return False;
+
else
S := Current_Scope;
while Present (S) and then S /= Prot loop
@@ -9982,9 +10570,13 @@ package body Sem_Util is
or else K = E_In_Out_Parameter
or else K = E_Generic_In_Out_Parameter
- -- Current instance of type
+ -- Current instance of type. If this is a protected type, check
+ -- we are not within the body of one of its protected functions.
+
+ or else (Is_Type (E)
+ and then In_Open_Scopes (E)
+ and then not In_Protected_Function (E))
- or else (Is_Type (E) and then In_Open_Scopes (E))
or else (Is_Incomplete_Or_Private_Type (E)
and then In_Open_Scopes (Full_View (E)));
end;
@@ -12215,8 +12807,8 @@ package body Sem_Util is
end if;
if Nkind (P) = N_Selected_Component
- and then Present (
- Entry_Formal (Entity (Selector_Name (P))))
+ and then
+ Present (Entry_Formal (Entity (Selector_Name (P))))
then
-- Case of a reference to an entry formal
@@ -12240,15 +12832,15 @@ package body Sem_Util is
end if;
end;
- elsif Nkind (Exp) = N_Type_Conversion
- or else Nkind (Exp) = N_Unchecked_Type_Conversion
+ elsif Nkind_In (Exp, N_Type_Conversion,
+ N_Unchecked_Type_Conversion)
then
Exp := Expression (Exp);
goto Continue;
- elsif Nkind (Exp) = N_Slice
- or else Nkind (Exp) = N_Indexed_Component
- or else Nkind (Exp) = N_Selected_Component
+ elsif Nkind_In (Exp, N_Slice,
+ N_Indexed_Component,
+ N_Selected_Component)
then
Exp := Prefix (Exp);
goto Continue;
@@ -12307,7 +12899,9 @@ package body Sem_Util is
-- source. This excludes, for example, calls to a dispatching
-- assignment operation when the left-hand side is tagged.
- if Modification_Comes_From_Source or else SPARK_Mode then
+ -- Why is SPARK mode different here ???
+
+ if Modification_Comes_From_Source or SPARK_Mode then
Generate_Reference (Ent, Exp, 'm');
-- If the target of the assignment is the bound variable
@@ -12653,6 +13247,71 @@ package body Sem_Util is
end if;
end Object_Access_Level;
+ --------------------------
+ -- Original_Aspect_Name --
+ --------------------------
+
+ function Original_Aspect_Name (N : Node_Id) return Name_Id is
+ Pras : Node_Id;
+ Name : Name_Id;
+
+ begin
+ pragma Assert (Nkind_In (N, N_Aspect_Specification, N_Pragma));
+ Pras := N;
+
+ if Is_Rewrite_Substitution (Pras)
+ and then Nkind (Original_Node (Pras)) = N_Pragma
+ then
+ Pras := Original_Node (Pras);
+ end if;
+
+ -- Case where we came from aspect specication
+
+ if Nkind (Pras) = N_Pragma and then From_Aspect_Specification (Pras) then
+ Pras := Corresponding_Aspect (Pras);
+ end if;
+
+ -- Get name from aspect or pragma
+
+ if Nkind (Pras) = N_Pragma then
+ Name := Pragma_Name (Pras);
+ else
+ Name := Chars (Identifier (Pras));
+ end if;
+
+ -- Deal with 'Class
+
+ if Class_Present (Pras) then
+ case Name is
+
+ -- Names that need converting to special _xxx form
+
+ when Name_Pre |
+ Name_Pre_Class =>
+ Name := Name_uPre;
+
+ when Name_Post |
+ Name_Post_Class =>
+ Name := Name_uPost;
+
+ when Name_Invariant =>
+ Name := Name_uInvariant;
+
+ when Name_Type_Invariant |
+ Name_Type_Invariant_Class =>
+ Name := Name_uType_Invariant;
+
+ -- Nothing to do for other cases (e.g. a Check that derived
+ -- from Pre_Class and has the flag set). Also we do nothing
+ -- if the name is already in special _xxx form.
+
+ when others =>
+ null;
+ end case;
+ end if;
+
+ return Name;
+ end Original_Aspect_Name;
--------------------------------------
-- Original_Corresponding_Operation --
--------------------------------------
@@ -14970,7 +15629,7 @@ package body Sem_Util is
("\\found an access type with designated}!",
Expr, Designated_Type (Found_Type));
else
- if From_With_Type (Found_Type) then
+ if From_Limited_With (Found_Type) then
Error_Msg_NE ("\\found incomplete}!", Expr, Found_Type);
Error_Msg_Qual_Level := 99;
Error_Msg_NE -- CODEFIX
diff --git a/gcc/ada/sem_util.ads b/gcc/ada/sem_util.ads
index 7ea5657aa2b..8227ee2735b 100644
--- a/gcc/ada/sem_util.ads
+++ b/gcc/ada/sem_util.ads
@@ -43,10 +43,21 @@ package Sem_Util is
-- Add A to the list of access types to process when expanding the
-- freeze node of E.
- procedure Add_Contract_Item (Item : Node_Id; Subp_Id : Entity_Id);
- -- Add a contract item (pragma Precondition, Postcondition, Test_Case,
- -- Contract_Cases, Global, Depends) to the contract of a subprogram. Item
- -- denotes a pragma and Subp_Id is the related subprogram.
+ procedure Add_Contract_Item (Prag : Node_Id; Id : Entity_Id);
+ -- Add pragma Prag to the contract of an entry, a package [body] or a
+ -- subprogram [body] denoted by Id. The following are valid pragmas:
+ -- Abstract_States
+ -- Contract_Cases
+ -- Depends
+ -- Global
+ -- Initial_Condition
+ -- Initializes
+ -- Postcondition
+ -- Precondition
+ -- Refined_Depends
+ -- Refined_Global
+ -- Refined_States
+ -- Test_Case
procedure Add_Global_Declaration (N : Node_Id);
-- These procedures adds a declaration N at the library level, to be
@@ -319,6 +330,13 @@ package Sem_Util is
-- Sets the Has_Delayed_Freeze flag of New if the Delayed_Freeze flag of
-- Old is set and Old has no yet been Frozen (i.e. Is_Frozen is false).
+ function Contains_Refined_State (Prag : Node_Id) return Boolean;
+ -- Determine whether pragma Prag contains a reference to the entity of an
+ -- abstract state with a visible refinement. Prag must denote one of the
+ -- following pragmas:
+ -- Depends
+ -- Global
+
function Copy_Parameter_List (Subp_Id : Entity_Id) return List_Id;
-- Utility to create a parameter profile for a new subprogram spec, when
-- the subprogram has a body that acts as spec. This is done for some cases
@@ -463,6 +481,10 @@ package Sem_Util is
-- Note: Enter_Name is not used for overloadable entities, instead these
-- are entered using Sem_Ch6.Enter_Overloadable_Entity.
+ function Entity_Of (N : Node_Id) return Entity_Id;
+ -- Return the entity of N or Empty. If N is a renaming, return the entity
+ -- of the root renamed object.
+
procedure Explain_Limited_Type (T : Entity_Id; N : Node_Id);
-- This procedure is called after issuing a message complaining about an
-- inappropriate use of limited type T. If useful, it adds additional
@@ -735,6 +757,17 @@ package Sem_Util is
-- Use_Full_View controls if the check is done using its full view (if
-- available).
+ function Has_No_Obvious_Side_Effects (N : Node_Id) return Boolean;
+ -- This is a simple minded function for determining whether an expression
+ -- has no obvious side effects. It is used only for determining whether
+ -- warnings are needed in certain situations, and is not guaranteed to
+ -- be accurate in either direction. Exceptions may mean an expression
+ -- does in fact have side effects, but this may be ignored and True is
+ -- returned, or a complex expression may in fact be side effect free
+ -- but we don't recognize it here and return False. The Side_Effect_Free
+ -- routine in Remove_Side_Effects is much more extensive and perhaps could
+ -- be shared, so that this routine would be more accurate.
+
function Has_Null_Exclusion (N : Node_Id) return Boolean;
-- Determine whether node N has a null exclusion
@@ -874,6 +907,9 @@ package Sem_Util is
-- Determines if the given node denotes an atomic object in the sense of
-- the legality checks described in RM C.6(12).
+ function Is_Attribute_Result (N : Node_Id) return Boolean;
+ -- Determine whether node N denotes attribute 'Result
+
function Is_Body_Or_Package_Declaration (N : Node_Id) return Boolean;
-- Determine whether node N denotes a body or a package declaration
@@ -913,6 +949,16 @@ package Sem_Util is
-- This is the RM definition, a type is a descendent of another type if it
-- is the same type or is derived from a descendent of the other type.
+ function Is_Child_Or_Sibling
+ (Pack_1 : Entity_Id;
+ Pack_2 : Entity_Id;
+ Private_Child : Boolean) return Boolean;
+ -- Determine the following relations between two arbitrary packages:
+ -- 1) One package is the parent of a child package
+ -- 2) Both packages are siblings and share a common parent
+ -- If flag Private_Child is set, then the child in case 1) or both siblings
+ -- in case 2) must be private.
+
function Is_Concurrent_Interface (T : Entity_Id) return Boolean;
-- First determine whether type T is an interface and then check whether
-- it is of protected, synchronized or task kind.
@@ -1340,6 +1386,16 @@ package Sem_Util is
-- convenience, qualified expressions applied to object names are also
-- allowed as actuals for this function.
+ function Original_Aspect_Name (N : Node_Id) return Name_Id;
+ -- N is a pragma node or aspect specification node. This function returns
+ -- the name of the pragma or aspect in original source form, taking into
+ -- account possible rewrites, and also cases where a pragma comes from an
+ -- aspect (in such cases, the name can be different from the pragma name,
+ -- e.g. a Pre aspect generates a Precondition pragma). This also deals with
+ -- the presence of 'Class, which results in one of the special names
+ -- Name_uPre, Name_uPost, Name_uInvariant, or Name_uType_Invariant being
+ -- returned to represent the corresponding aspects with x'Class names.
+
function Primitive_Names_Match (E1, E2 : Entity_Id) return Boolean;
-- Returns True if the names of both entities correspond with matching
-- primitives. This routine includes support for the case in which one
diff --git a/gcc/ada/sem_warn.adb b/gcc/ada/sem_warn.adb
index 68c3ca89b51..5603464f15e 100644
--- a/gcc/ada/sem_warn.adb
+++ b/gcc/ada/sem_warn.adb
@@ -1310,6 +1310,7 @@ package body Sem_Warn is
UR := Original_Node (UR);
while Nkind (UR) = N_Type_Conversion
or else Nkind (UR) = N_Qualified_Expression
+ or else Nkind (UR) = N_Expression_With_Actions
loop
UR := Expression (UR);
end loop;
@@ -1674,6 +1675,15 @@ package body Sem_Warn is
return;
end if;
+ -- Nothing to do for numeric or string literal. Do this test early to
+ -- save time in a common case (it does not matter that we do not include
+ -- character literal here, since that will be caught later on in the
+ -- when others branch of the case statement).
+
+ if Nkind (N) in N_Numeric_Or_String_Literal then
+ return;
+ end if;
+
-- Ignore reference unless it comes from source. Almost always if we
-- have a reference from generated code, it is bogus (e.g. calls to init
-- procs to set default discriminant values).
@@ -1707,7 +1717,7 @@ package body Sem_Warn is
and then (No (Unset_Reference (E))
or else
Earlier_In_Extended_Unit
- (Sloc (N), Sloc (Unset_Reference (E))))
+ (Sloc (N), Sloc (Unset_Reference (E))))
and then not Has_Pragma_Unmodified_Check_Spec (E)
and then not Warnings_Off_Check_Spec (E)
then
@@ -2025,9 +2035,12 @@ package body Sem_Warn is
Check_Unset_Reference (Pref);
end;
- -- For type conversions or qualifications examine the expression
+ -- For type conversions, qualifications, or expressions with actions,
+ -- examine the expression.
- when N_Type_Conversion | N_Qualified_Expression =>
+ when N_Type_Conversion |
+ N_Qualified_Expression |
+ N_Expression_With_Actions =>
Check_Unset_Reference (Expression (N));
-- For explicit dereference, always check prefix, which will generate
@@ -2425,7 +2438,7 @@ package body Sem_Warn is
or else Referenced_As_LHS_Check_Spec (Ent)
or else Referenced_As_Out_Parameter_Check_Spec (Ent)
or else
- (From_With_Type (Ent)
+ (From_Limited_With (Ent)
and then Is_Incomplete_Type (Ent)
and then Present (Non_Limited_View (Ent))
and then Referenced (Non_Limited_View (Ent)))
@@ -2532,13 +2545,16 @@ package body Sem_Warn is
return;
end if;
- -- Flag any unused with clauses, but skip this step if we are compiling
- -- a subunit on its own, since we do not have enough information to
- -- determine whether with's are used. We will get the relevant warnings
- -- when we compile the parent. This is the normal style of GNAT
- -- compilation in any case.
+ -- Flag any unused with clauses. For a subunit, check only the units
+ -- in its context, not those of the parent, which may be needed by other
+ -- subunits. We will get the full warnings when we compile the parent,
+ -- but the following is helpful when compiling a subunit by itself.
if Nkind (Unit (Cunit (Main_Unit))) = N_Subunit then
+ if Current_Sem_Unit = Main_Unit then
+ Check_One_Unit (Main_Unit);
+ end if;
+
return;
end if;
@@ -3401,12 +3417,26 @@ package body Sem_Warn is
then
null;
- -- Here we may need to issue message
+ -- Here we may need to issue overlap message
else
Error_Msg_Warn :=
+
+ -- Overlap checking is an error only in Ada 2012. For
+ -- earlier versions of Ada, this is a warning.
+
Ada_Version < Ada_2012
- or else not Is_Elementary_Type (Etype (Form1));
+
+ -- Overlap is only illegal in Ada 2012 in the case of
+ -- elementary types (passed by copy). For other types,
+ -- we always have a warning in all Ada versions.
+
+ or else not Is_Elementary_Type (Etype (Form1))
+
+ -- Finally, debug flag -gnatd.E changes the error to a
+ -- warning even in Ada 2012 mode.
+
+ or else Error_To_Warning;
declare
Act : Node_Id;
@@ -3448,23 +3478,28 @@ package body Sem_Warn is
then
if Act1 = First_Actual (N) then
Error_Msg_FE
- ("`IN OUT` prefix overlaps with "
- & "actual for&?I?", Act1, Form);
+ ("<`IN OUT` prefix overlaps with "
+ & "actual for&", Act1, Form);
else
-- For greater clarity, give name of formal
Error_Msg_Node_2 := Form;
Error_Msg_FE
- ("writable actual for & overlaps with "
- & "actual for&?I?", Act1, Form);
+ ("<writable actual for & overlaps with "
+ & "actual for&", Act1, Form);
end if;
else
+ -- For greater clarity, give name of formal
+
Error_Msg_Node_2 := Form;
+
+ -- This is one of the messages
+
Error_Msg_FE
- ("writable actual for & overlaps with "
- & "actual for&?I?", Act1, Form1);
+ ("<writable actual for & overlaps with "
+ & "actual for&", Act1, Form1);
end if;
end;
end if;
diff --git a/gcc/ada/sem_warn.ads b/gcc/ada/sem_warn.ads
index 0a8839512bb..22a3c6c42ef 100644
--- a/gcc/ada/sem_warn.ads
+++ b/gcc/ada/sem_warn.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 1999-2011, Free Software Foundation, Inc. --
+-- Copyright (C) 1999-2013, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -198,7 +198,9 @@ package Sem_Warn is
procedure Warn_On_Overlapping_Actuals (Subp : Entity_Id; N : Node_Id);
-- Called on a subprogram call. Checks whether an IN OUT actual that is
-- not by-copy may overlap with another actual, thus leading to aliasing
- -- in the body of the called subprogram.
+ -- in the body of the called subprogram. This is indeed a warning in Ada
+ -- versions prior to Ada 2012, but, unless Opt.Error_To_Warning is set by
+ -- use of debug flag -gnatd.E, this is illegal and generates an error.
procedure Warn_On_Suspicious_Index (Name : Entity_Id; X : Node_Id);
-- This is called after resolving an indexed component or a slice. Name
diff --git a/gcc/ada/sinfo.adb b/gcc/ada/sinfo.adb
index 6cb18c1890c..ba583398e08 100644
--- a/gcc/ada/sinfo.adb
+++ b/gcc/ada/sinfo.adb
@@ -691,6 +691,17 @@ package body Sinfo is
return Node5 (N);
end Corresponding_Spec;
+ function Corresponding_Spec_Of_Stub
+ (N : Node_Id) return Entity_Id is
+ begin
+ pragma Assert (False
+ or else NT (N).Nkind = N_Package_Body_Stub
+ or else NT (N).Nkind = N_Protected_Body_Stub
+ or else NT (N).Nkind = N_Subprogram_Body_Stub
+ or else NT (N).Nkind = N_Task_Body_Stub);
+ return Node2 (N);
+ end Corresponding_Spec_Of_Stub;
+
function Corresponding_Stub
(N : Node_Id) return Node_Id is
begin
@@ -1093,7 +1104,8 @@ package body Sinfo is
or else NT (N).Nkind in N_Has_Entity
or else NT (N).Nkind = N_Aspect_Specification
or else NT (N).Nkind = N_Attribute_Definition_Clause
- or else NT (N).Nkind = N_Freeze_Entity);
+ or else NT (N).Nkind = N_Freeze_Entity
+ or else NT (N).Nkind = N_Freeze_Generic_Entity);
return Node4 (N);
end Entity;
@@ -1541,6 +1553,16 @@ package body Sinfo is
return Flag13 (N);
end Has_Self_Reference;
+ function Has_SP_Choice
+ (N : Node_Id) return Boolean is
+ begin
+ pragma Assert (False
+ or else NT (N).Nkind = N_Case_Expression_Alternative
+ or else NT (N).Nkind = N_Case_Statement_Alternative
+ or else NT (N).Nkind = N_Variant);
+ return Flag15 (N);
+ end Has_SP_Choice;
+
function Has_Storage_Size_Pragma
(N : Node_Id) return Boolean is
begin
@@ -3817,6 +3839,17 @@ package body Sinfo is
Set_Node5 (N, Val); -- semantic field, no parent set
end Set_Corresponding_Spec;
+ procedure Set_Corresponding_Spec_Of_Stub
+ (N : Node_Id; Val : Entity_Id) is
+ begin
+ pragma Assert (False
+ or else NT (N).Nkind = N_Package_Body_Stub
+ or else NT (N).Nkind = N_Protected_Body_Stub
+ or else NT (N).Nkind = N_Subprogram_Body_Stub
+ or else NT (N).Nkind = N_Task_Body_Stub);
+ Set_Node2 (N, Val); -- semantic field, no parent set
+ end Set_Corresponding_Spec_Of_Stub;
+
procedure Set_Corresponding_Stub
(N : Node_Id; Val : Node_Id) is
begin
@@ -4219,7 +4252,8 @@ package body Sinfo is
or else NT (N).Nkind in N_Has_Entity
or else NT (N).Nkind = N_Aspect_Specification
or else NT (N).Nkind = N_Attribute_Definition_Clause
- or else NT (N).Nkind = N_Freeze_Entity);
+ or else NT (N).Nkind = N_Freeze_Entity
+ or else NT (N).Nkind = N_Freeze_Generic_Entity);
Set_Node4 (N, Val); -- semantic field, no parent set
end Set_Entity;
@@ -4658,6 +4692,16 @@ package body Sinfo is
Set_Flag13 (N, Val);
end Set_Has_Self_Reference;
+ procedure Set_Has_SP_Choice
+ (N : Node_Id; Val : Boolean := True) is
+ begin
+ pragma Assert (False
+ or else NT (N).Nkind = N_Case_Expression_Alternative
+ or else NT (N).Nkind = N_Case_Statement_Alternative
+ or else NT (N).Nkind = N_Variant);
+ Set_Flag15 (N, Val);
+ end Set_Has_SP_Choice;
+
procedure Set_Has_Storage_Size_Pragma
(N : Node_Id; Val : Boolean := True) is
begin
diff --git a/gcc/ada/sinfo.ads b/gcc/ada/sinfo.ads
index 112f8fc00ab..a54ef6afa88 100644
--- a/gcc/ada/sinfo.ads
+++ b/gcc/ada/sinfo.ads
@@ -508,6 +508,48 @@ package Sinfo is
-- simply ignore these nodes, since they are not relevant to the task
-- of back annotating representation information.
+ ----------------
+ -- SPARK Mode --
+ ----------------
+
+ -- When a file is compiled in SPARK mode (-gnatd.F), a very light expansion
+ -- is performed and the analysis must generate a tree in a form that meets
+ -- additional requirements.
+
+ -- The SPARK expansion does two transformations of the tree, that cannot be
+ -- postponed after the frontend semantic analysis:
+
+ -- 1. Replace renamings by renamed (object/subprogram). This requires
+ -- introducing temporaries at the point of the renaming, which must be
+ -- properly analyzed.
+
+ -- 2. Fully qualify entity names. This is needed to generate suitable
+ -- local effects/call-graphs in ALI files, with the completely
+ -- qualified names (in particular the suffix to distinguish homonyms).
+
+ -- The tree after SPARK expansion should be fully analyzed semantically,
+ -- which sometimes requires the insertion of semantic pre-analysis, for
+ -- example for subprogram contracts and pragma check/assert. In particular,
+ -- all expression must have their proper type, and semantic links should be
+ -- set between tree nodes (partial to full view, etc.) Some kinds of nodes
+ -- should be either absent, or can be ignored by the formal verification
+ -- backend:
+
+ -- N_Object_Renaming_Declaration: can be ignored safely
+ -- N_Expression_Function: absent (rewitten)
+ -- N_Expression_With_Actions: absent (not generated)
+
+ -- SPARK cross-references are generated from the regular cross-references
+ -- (used for browsing and code understanding) and additional references
+ -- collected during semantic analysis, in particular on all dereferences.
+ -- These SPARK cross-references are output in a separate section of ALI
+ -- files, as described in spark_xrefs.adb. They are the basis for the
+ -- computation of data dependences in the formal verification backend.
+ -- This implies that all cross-references should be generated in this mode,
+ -- even those that would not make sense from a user point-of-view, and that
+ -- cross-references that do not lead to data dependences for subprograms
+ -- can be safely ignored.
+
------------------------
-- Common Flag Fields --
------------------------
@@ -822,6 +864,11 @@ package Sinfo is
-- In Ada 2012, Corresponding_Spec is set on expression functions that
-- complete a subprogram declaration.
+ -- Corresponding_Spec_Of_Stub (Node2-Sem)
+ -- This field is present in subprogram, package, task and protected body
+ -- stubs where it points to the corresponding spec of the stub. Due to
+ -- clashes in the structure of nodes, we cannot use Corresponding_Spec.
+
-- Corresponding_Stub (Node3-Sem)
-- This field is present in an N_Subunit node. It holds the node in
-- the parent unit that is the stub declaration for the subunit. It is
@@ -929,6 +976,15 @@ package Sinfo is
-- listed above (e.g. in a return statement), an additional type
-- conversion node is introduced to represent the required check.
+ -- A special case arises for the arguments of the Pred/Succ attributes.
+ -- Here the range check needed is against First + 1 .. Last (Pred) or
+ -- First .. Last - 1 (Succ) of the corresponding base type. Essentially
+ -- these checks are what would be performed within the implicit body of
+ -- the functions that correspond to these attributes. In these cases,
+ -- the Do_Range check flag is set on the argument to the attribute
+ -- function, and the back end must special case the appropriate range
+ -- to check against.
+
-- Do_Storage_Check (Flag17-Sem)
-- This flag is set in an N_Allocator node to indicate that a storage
-- check is required for the allocation, or in an N_Subprogram_Body node
@@ -1238,6 +1294,12 @@ package Sinfo is
-- enclosing type. Such a self-reference can only appear in default-
-- initialized aggregate for a record type.
+ -- Has_SP_Choice (Flag15-Sem)
+ -- Present in all nodes containing a Discrete_Choices field (N_Variant,
+ -- N_Case_Expression_Alternative, N_Case_Statement_Alternative). Set to
+ -- True if the Discrete_Choices list has at least one occurrence of a
+ -- statically predicated subtype.
+
-- Has_Storage_Size_Pragma (Flag5-Sem)
-- A flag present in an N_Task_Definition node to flag the presence of a
-- Storage_Size pragma.
@@ -3056,8 +3118,7 @@ package Sinfo is
-- VARIANT_PART ::=
-- case discriminant_DIRECT_NAME is
- -- VARIANT
- -- {VARIANT}
+ -- VARIANT {VARIANT}
-- end case;
-- Note: the variants list can contain pragmas as well as variants.
@@ -3083,6 +3144,14 @@ package Sinfo is
-- Enclosing_Variant (Node2-Sem)
-- Present_Expr (Uint3-Sem)
-- Dcheck_Function (Node5-Sem)
+ -- Has_SP_Choice (Flag15-Sem)
+
+ -- Note: in the list of Discrete_Choices, the tree passed to the back
+ -- end does not have choice entries corresponding to names of statically
+ -- predicated subtypes. Such entries are always expanded out to the list
+ -- of equivalent values or ranges. The ASIS tree generated in -gnatct
+ -- mode also has this expansion, but done with a proper Rewrite call on
+ -- the N_Variant node so that ASIS can properly retrieve the original.
---------------------------------
-- 3.8.1 Discrete Choice List --
@@ -3569,7 +3638,7 @@ package Sinfo is
-- Sloc points to first selector name
-- Choices (List1)
-- Loop_Actions (List2-Sem)
- -- Expression (Node3)
+ -- Expression (Node3) (empty if Box_Present)
-- Box_Present (Flag15)
-- Inherited_Discriminant (Flag13)
@@ -4067,12 +4136,16 @@ package Sinfo is
-- Actions (List1)
-- Discrete_Choices (List4)
-- Expression (Node3)
+ -- Has_SP_Choice (Flag15-Sem)
-- Note: The Actions field temporarily holds any actions associated with
-- evaluation of the Expression. During expansion of the case expression
-- these actions are wrapped into an N_Expressions_With_Actions node
-- replacing the original expression.
+ -- Note: this node never appears in the tree passed to the back end,
+ -- since the expander converts case expressions into case statements.
+
---------------------------------
-- 4.5.9 Quantified Expression --
---------------------------------
@@ -4381,6 +4454,13 @@ package Sinfo is
-- Sloc points to WHEN
-- Discrete_Choices (List4)
-- Statements (List3)
+ -- Has_SP_Choice (Flag15-Sem)
+
+ -- Note: in the list of Discrete_Choices, the tree passed to the back
+ -- end does not have choice entries corresponding to names of statically
+ -- predicated subtypes. Such entries are always expanded out to the list
+ -- of equivalent values or ranges. The ASIS tree generated in -gnatct
+ -- mode does not have this expansion, and has the original choices.
-------------------------
-- 5.5 Loop Statement --
@@ -6055,6 +6135,7 @@ package Sinfo is
-- N_Subprogram_Body_Stub
-- Sloc points to FUNCTION or PROCEDURE
-- Specification (Node1)
+ -- Corresponding_Spec_Of_Stub (Node2-Sem)
-- Library_Unit (Node4-Sem) points to the subunit
-- Corresponding_Body (Node5-Sem)
@@ -6069,6 +6150,7 @@ package Sinfo is
-- N_Package_Body_Stub
-- Sloc points to PACKAGE
-- Defining_Identifier (Node1)
+ -- Corresponding_Spec_Of_Stub (Node2-Sem)
-- Library_Unit (Node4-Sem) points to the subunit
-- Corresponding_Body (Node5-Sem)
@@ -6083,6 +6165,7 @@ package Sinfo is
-- N_Task_Body_Stub
-- Sloc points to TASK
-- Defining_Identifier (Node1)
+ -- Corresponding_Spec_Of_Stub (Node2-Sem)
-- Library_Unit (Node4-Sem) points to the subunit
-- Corresponding_Body (Node5-Sem)
@@ -6099,6 +6182,7 @@ package Sinfo is
-- N_Protected_Body_Stub
-- Sloc points to PROTECTED
-- Defining_Identifier (Node1)
+ -- Corresponding_Spec_Of_Stub (Node2-Sem)
-- Library_Unit (Node4-Sem) points to the subunit
-- Corresponding_Body (Node5-Sem)
@@ -7109,12 +7193,16 @@ package Sinfo is
-- Contract --
--------------
- -- This node is used to hold the various parts of an entry or subprogram
- -- contract, consisting in pre- and postconditions on the one hand, and
- -- test-cases on the other hand.
+ -- This node is used to hold the various parts of an entry, subprogram
+ -- [body] or package [body] contract, in particular:
+ -- Abstract states declared by a package declaration
+ -- Contract cases that apply to a subprogram
+ -- Dependency relations of inputs and output of a subprogram
+ -- Global annotations classifying data as input or output
+ -- Initialization sequences for a package declaration
+ -- Pre- and postconditions that apply to a subprogram
- -- It is referenced from an entry, a subprogram or a generic subprogram
- -- entity.
+ -- The node appears in an entry and [generic] subprogram [body] entity.
-- Sprint syntax: <none> as the node should not appear in the tree, but
-- only attached to an entry or [generic] subprogram
@@ -7127,9 +7215,15 @@ package Sinfo is
-- Classifications (Node3) (set to Empty if none)
-- Pre_Post_Conditions contains a collection of pragmas that correspond
- -- to pre- and postconditions associated with an entry or a subprogram.
- -- The pragmas can either come from source or be the byproduct of aspect
- -- expansion. The ordering in the list is in LIFO fashion.
+ -- to pre- and postconditions associated with an entry or a subprogram
+ -- [body or stub]. The pragmas can either come from source or be the
+ -- byproduct of aspect expansion. Currently the following pragmas appear
+ -- in this list:
+ -- Post
+ -- Postcondition
+ -- Pre
+ -- Precondition
+ -- The ordering in the list is in LIFO fashion.
-- Note that there might be multiple preconditions or postconditions
-- in this list, either because they come from separate pragmas in the
@@ -7140,10 +7234,18 @@ package Sinfo is
-- to aspects/pragmas Contract_Cases and Test_Case. The ordering in the
-- list is in LIFO fashion.
- -- Classifications contains pragmas that either categorize subprogram
- -- inputs and outputs or establish dependencies between them. Currently
- -- pragmas Depends and Global are stored in this list. The ordering is
- -- in LIFO fashion.
+ -- Classifications contains pragmas that either declare, categorize or
+ -- establish dependencies between subprogram or package inputs and
+ -- outputs. Currently the following pragmas appear in this list:
+ -- Abstract_States
+ -- Depends
+ -- Global
+ -- Initial_Condition
+ -- Initializes
+ -- Refined_Depends
+ -- Refined_Global
+ -- Refined_States
+ -- The ordering is in LIFO fashion.
-------------------
-- Expanded_Name --
@@ -7286,6 +7388,29 @@ package Sinfo is
-- Note: in the case where a debug source file is generated, the Sloc
-- for this node points to the FREEZE keyword in the Sprint file output.
+ ---------------------------
+ -- Freeze_Generic_Entity --
+ ---------------------------
+
+ -- The freeze point of an entity indicates the point at which the
+ -- information needed to generate code for the entity is complete.
+ -- The freeze node for an entity triggers expander activities, such as
+ -- build initialization procedures, and backend activities, such as
+ -- completing the elaboration of packages.
+
+ -- For entities declared within a generic unit, for which no code is
+ -- generated, the freeze point is not equally meaningful. However, in
+ -- Ada 2012 several semantic checks on declarations must be delayed to
+ -- the freeze point, and we need to include such a mark in the tree to
+ -- trigger these checks. The Freeze_Generic_Entity node plays no other
+ -- role, and is ignored by the expander and the back-end.
+
+ -- Sprint syntax: freeze_generic entity-name
+
+ -- N_Freeze_Generic_Entity
+ -- Sloc points near freeze point
+ -- Entity (Node4-Sem)
+
--------------------------------
-- Implicit Label Declaration --
--------------------------------
@@ -7564,7 +7689,7 @@ package Sinfo is
-- N_Subprogram_Info
-- Sloc points to the entity for the procedure
-- Identifier (Node1) identifier referencing the procedure
- -- Etype (Node5-Sem) type (always set to Ada.Exceptions.Code_Loc
+ -- Etype (Node5-Sem) type (always set to Ada.Exceptions.Code_Loc)
-- Note: in the case where a debug source file is generated, the Sloc
-- for this node points to the quote in the Sprint file output.
@@ -7822,13 +7947,18 @@ package Sinfo is
N_Raise_Program_Error,
N_Raise_Storage_Error,
+ -- N_Subexpr, N_Has_Etype, N_Numeric_Or_String_Literal
+
+ N_Integer_Literal,
+ N_Real_Literal,
+ N_String_Literal,
+
-- N_Subexpr, N_Has_Etype
N_Explicit_Dereference,
N_Expression_With_Actions,
N_If_Expression,
N_Indexed_Component,
- N_Integer_Literal,
N_Null,
N_Qualified_Expression,
N_Quantified_Expression,
@@ -7838,11 +7968,9 @@ package Sinfo is
N_Extension_Aggregate,
N_Raise_Expression,
N_Range,
- N_Real_Literal,
N_Reference,
N_Selected_Component,
N_Slice,
- N_String_Literal,
N_Subprogram_Info,
N_Type_Conversion,
N_Unchecked_Expression,
@@ -8049,6 +8177,7 @@ package Sinfo is
N_Formal_Incomplete_Type_Definition,
N_Formal_Signed_Integer_Type_Definition,
N_Freeze_Entity,
+ N_Freeze_Generic_Entity,
N_Generic_Association,
N_Handled_Sequence_Of_Statements,
N_Index_Or_Discriminant_Constraint,
@@ -8143,8 +8272,8 @@ package Sinfo is
N_Expanded_Name ..
N_Attribute_Reference;
-- Nodes that have Entity fields
- -- Warning: DOES NOT INCLUDE N_Freeze_Entity, N_Aspect_Specification,
- -- or N_Attribute_Definition_Clause.
+ -- Warning: DOES NOT INCLUDE N_Freeze_Entity, N_Freeze_Generic_Entity,
+ -- N_Aspect_Specification, or N_Attribute_Definition_Clause.
subtype N_Has_Etype is Node_Kind range
N_Error ..
@@ -8173,6 +8302,10 @@ package Sinfo is
N_In ..
N_Not_In;
+ subtype N_Numeric_Or_String_Literal is Node_Kind range
+ N_Integer_Literal ..
+ N_String_Literal;
+
subtype N_Op is Node_Kind range
N_Op_Add ..
N_Op_Plus;
@@ -8484,6 +8617,9 @@ package Sinfo is
function Corresponding_Spec
(N : Node_Id) return Node_Id; -- Node5
+ function Corresponding_Spec_Of_Stub
+ (N : Node_Id) return Node_Id; -- Node2
+
function Corresponding_Stub
(N : Node_Id) return Node_Id; -- Node3
@@ -8742,6 +8878,9 @@ package Sinfo is
function Has_Self_Reference
(N : Node_Id) return Boolean; -- Flag13
+ function Has_SP_Choice
+ (N : Node_Id) return Boolean; -- Flag15
+
function Has_Storage_Size_Pragma
(N : Node_Id) return Boolean; -- Flag5
@@ -9480,6 +9619,9 @@ package Sinfo is
procedure Set_Corresponding_Spec
(N : Node_Id; Val : Node_Id); -- Node5
+ procedure Set_Corresponding_Spec_Of_Stub
+ (N : Node_Id; Val : Node_Id); -- Node2
+
procedure Set_Corresponding_Stub
(N : Node_Id; Val : Node_Id); -- Node3
@@ -9735,6 +9877,9 @@ package Sinfo is
procedure Set_Has_Self_Reference
(N : Node_Id; Val : Boolean := True); -- Flag13
+ procedure Set_Has_SP_Choice
+ (N : Node_Id; Val : Boolean := True); -- Flag15
+
procedure Set_Has_Storage_Size_Pragma
(N : Node_Id; Val : Boolean := True); -- Flag5
@@ -11490,28 +11635,28 @@ package Sinfo is
N_Subprogram_Body_Stub =>
(1 => True, -- Specification (Node1)
- 2 => False, -- unused
+ 2 => False, -- Corresponding_Spec_Of_Stub (Node2-Sem)
3 => False, -- unused
4 => False, -- Library_Unit (Node4-Sem)
5 => False), -- Corresponding_Body (Node5-Sem)
N_Package_Body_Stub =>
(1 => True, -- Defining_Identifier (Node1)
- 2 => False, -- unused
+ 2 => False, -- Corresponding_Spec_Of_Stub (Node2-Sem)
3 => False, -- unused
4 => False, -- Library_Unit (Node4-Sem)
5 => False), -- Corresponding_Body (Node5-Sem)
N_Task_Body_Stub =>
(1 => True, -- Defining_Identifier (Node1)
- 2 => False, -- unused
+ 2 => False, -- Corresponding_Spec_Of_Stub (Node2-Sem)
3 => False, -- unused
4 => False, -- Library_Unit (Node4-Sem)
5 => False), -- Corresponding_Body (Node5-Sem)
N_Protected_Body_Stub =>
(1 => True, -- Defining_Identifier (Node1)
- 2 => False, -- unused
+ 2 => False, -- Corresponding_Spec_Of_Stub (Node2-Sem)
3 => False, -- unused
4 => False, -- Library_Unit (Node4-Sem)
5 => False), -- Corresponding_Body (Node5-Sem)
@@ -11838,6 +11983,13 @@ package Sinfo is
4 => False, -- Entity (Node4-Sem)
5 => False), -- First_Subtype_Link (Node5-Sem)
+ N_Freeze_Generic_Entity =>
+ (1 => False, -- unused
+ 2 => False, -- unused
+ 3 => False, -- unused
+ 4 => False, -- Entity (Node4-Sem)
+ 5 => False), -- unused
+
N_Implicit_Label_Declaration =>
(1 => True, -- Defining_Identifier (Node1)
2 => False, -- Label_Construct (Node2-Sem)
@@ -12078,6 +12230,7 @@ package Sinfo is
pragma Inline (Corresponding_Generic_Association);
pragma Inline (Corresponding_Integer_Value);
pragma Inline (Corresponding_Spec);
+ pragma Inline (Corresponding_Spec_Of_Stub);
pragma Inline (Corresponding_Stub);
pragma Inline (Dcheck_Function);
pragma Inline (Declarations);
@@ -12160,6 +12313,7 @@ package Sinfo is
pragma Inline (Has_Init_Expression);
pragma Inline (Has_Local_Raise);
pragma Inline (Has_Self_Reference);
+ pragma Inline (Has_SP_Choice);
pragma Inline (Has_No_Elaboration_Code);
pragma Inline (Has_Pragma_Suppress_All);
pragma Inline (Has_Private_View);
@@ -12407,6 +12561,7 @@ package Sinfo is
pragma Inline (Set_Corresponding_Generic_Association);
pragma Inline (Set_Corresponding_Integer_Value);
pragma Inline (Set_Corresponding_Spec);
+ pragma Inline (Set_Corresponding_Spec_Of_Stub);
pragma Inline (Set_Corresponding_Stub);
pragma Inline (Set_Dcheck_Function);
pragma Inline (Set_Declarations);
@@ -12492,6 +12647,7 @@ package Sinfo is
pragma Inline (Set_Has_Private_View);
pragma Inline (Set_Has_Relative_Deadline_Pragma);
pragma Inline (Set_Has_Self_Reference);
+ pragma Inline (Set_Has_SP_Choice);
pragma Inline (Set_Has_Storage_Size_Pragma);
pragma Inline (Set_Has_Wide_Character);
pragma Inline (Set_Has_Wide_Wide_Character);
diff --git a/gcc/ada/sinput-c.adb b/gcc/ada/sinput-c.adb
index 4ad212b4314..83dadaf408c 100644
--- a/gcc/ada/sinput-c.adb
+++ b/gcc/ada/sinput-c.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2012, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -68,7 +68,8 @@ package body Sinput.C is
if X = Source_File.First then
Lo := First_Source_Ptr;
else
- Lo := Source_File.Table (X - 1).Source_Last + 1;
+ Lo := ((Source_File.Table (X - 1).Source_Last + Source_Align) /
+ Source_Align) * Source_Align;
end if;
Name_Len := Path'Length;
diff --git a/gcc/ada/sinput-d.adb b/gcc/ada/sinput-d.adb
index a860058c900..f150ebf7f0a 100644
--- a/gcc/ada/sinput-d.adb
+++ b/gcc/ada/sinput-d.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 2002-2007, Free Software Foundation, Inc. --
+-- Copyright (C) 2002-2013, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -62,7 +62,9 @@ package body Sinput.D is
Loc : out Source_Ptr)
is
begin
- Loc := Source_File.Table (Source_File.Last).Source_Last + 1;
+ Loc :=
+ ((Source_File.Table (Source_File.Last).Source_Last + Source_Align) /
+ Source_Align) * Source_Align;
Source_File.Append (Source_File.Table (Source));
Dfile := Source_File.Last;
diff --git a/gcc/ada/sinput-l.adb b/gcc/ada/sinput-l.adb
index 64a7cdb68b4..b72278851b4 100644
--- a/gcc/ada/sinput-l.adb
+++ b/gcc/ada/sinput-l.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2012, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -112,7 +112,6 @@ package body Sinput.L is
procedure Complete_Source_File_Entry is
CSF : constant Source_File_Index := Current_Source_File;
-
begin
Trim_Lines_Table (CSF);
Source_File.Table (CSF).Source_Checksum := Checksum;
@@ -158,7 +157,6 @@ package body Sinput.L is
Snew.Inlined_Call := Sloc (Inst_Node);
else
-
-- If the spec has been instantiated already, and we are now
-- creating the instance source for the corresponding body now,
-- retrieve the instance id that was assigned to the spec, which
@@ -167,10 +165,10 @@ package body Sinput.L is
Inst_Spec := Instance_Spec (Inst_Node);
if Present (Inst_Spec) then
declare
- Inst_Spec_Ent : Entity_Id;
+ Inst_Spec_Ent : Entity_Id;
-- Instance spec entity
- Inst_Spec_Sloc : Source_Ptr;
+ Inst_Spec_Sloc : Source_Ptr;
-- Virtual sloc of the spec instance source
Inst_Spec_Inst_Id : Instance_Id;
@@ -188,12 +186,13 @@ package body Sinput.L is
-- The specification of the instance entity has a virtual
-- sloc within the instance sloc range.
+
-- ??? But the Unit_Declaration_Node has the sloc of the
-- instantiation, which is somewhat of an oddity.
- Inst_Spec_Sloc :=
- Sloc (Specification (Unit_Declaration_Node
- (Inst_Spec_Ent)));
+ Inst_Spec_Sloc :=
+ Sloc
+ (Specification (Unit_Declaration_Node (Inst_Spec_Ent)));
Inst_Spec_Inst_Id :=
Source_File.Table
(Get_Source_File_Index (Inst_Spec_Sloc)).Instance;
@@ -209,11 +208,16 @@ package body Sinput.L is
end if;
end if;
- -- Now we need to compute the new values of Source_First,
+ -- Now we need to compute the new values of Source_First and
-- Source_Last and adjust the source file pointer to have the
-- correct virtual origin for the new range of values.
- Snew.Source_First := Source_File.Table (Xnew - 1).Source_Last + 1;
+ -- Source_First must be greater than the last Source_Last value
+ -- and also must be a multiple of Source_Align
+
+ Snew.Source_First :=
+ ((Source_File.Table (Xnew - 1).Source_Last + Source_Align) /
+ Source_Align) * Source_Align;
A.Adjust := Snew.Source_First - A.Lo;
Snew.Source_Last := A.Hi + A.Adjust;
@@ -398,10 +402,13 @@ package body Sinput.L is
Source_File.Increment_Last;
X := Source_File.Last;
+ -- Compute starting index, respecting alignment requirement
+
if X = Source_File.First then
Lo := First_Source_Ptr;
else
- Lo := Source_File.Table (X - 1).Source_Last + 1;
+ Lo := ((Source_File.Table (X - 1).Source_Last + Source_Align) /
+ Source_Align) * Source_Align;
end if;
Osint.Read_Source_File (N, Lo, Hi, Src, T);
diff --git a/gcc/ada/sinput.adb b/gcc/ada/sinput.adb
index a01c045d91f..7bd0a693470 100644
--- a/gcc/ada/sinput.adb
+++ b/gcc/ada/sinput.adb
@@ -434,44 +434,9 @@ package body Sinput is
-- Get_Source_File_Index --
---------------------------
- Source_Cache_First : Source_Ptr := 1;
- Source_Cache_Last : Source_Ptr := 0;
- -- Records the First and Last subscript values for the most recently
- -- referenced entry in the source table, to optimize the common case of
- -- repeated references to the same entry. The initial values force an
- -- initial search to set the cache value.
-
- Source_Cache_Index : Source_File_Index := No_Source_File;
- -- Contains the index of the entry corresponding to Source_Cache
-
function Get_Source_File_Index (S : Source_Ptr) return Source_File_Index is
begin
- if S in Source_Cache_First .. Source_Cache_Last then
- return Source_Cache_Index;
-
- else
- pragma Assert (Source_File_Index_Table (Int (S) / Chunk_Size)
- /=
- No_Source_File);
- for J in Source_File_Index_Table (Int (S) / Chunk_Size)
- .. Source_File.Last
- loop
- if S in Source_File.Table (J).Source_First ..
- Source_File.Table (J).Source_Last
- then
- Source_Cache_Index := J;
- Source_Cache_First :=
- Source_File.Table (Source_Cache_Index).Source_First;
- Source_Cache_Last :=
- Source_File.Table (Source_Cache_Index).Source_Last;
- return Source_Cache_Index;
- end if;
- end loop;
- end if;
-
- -- We must find a matching entry in the above loop!
-
- raise Program_Error;
+ return Source_File_Index_Table (Int (S) / Source_Align);
end Get_Source_File_Index;
----------------
@@ -480,9 +445,6 @@ package body Sinput is
procedure Initialize is
begin
- Source_Cache_First := 1;
- Source_Cache_Last := 0;
- Source_Cache_Index := No_Source_File;
Source_gnat_adc := No_Source_File;
First_Time_Around := True;
@@ -724,15 +686,13 @@ package body Sinput is
Ind : Int;
SP : Source_Ptr;
SL : constant Source_Ptr := Source_File.Table (Xnew).Source_Last;
-
begin
- SP := (Source_File.Table (Xnew).Source_First + Chunk_Size - 1)
- / Chunk_Size * Chunk_Size;
- Ind := Int (SP) / Chunk_Size;
-
+ SP := Source_File.Table (Xnew).Source_First;
+ pragma Assert (SP mod Source_Align = 0);
+ Ind := Int (SP) / Source_Align;
while SP <= SL loop
Source_File_Index_Table (Ind) := Xnew;
- SP := SP + Chunk_Size;
+ SP := SP + Source_Align;
Ind := Ind + 1;
end loop;
end Set_Source_File_Index_Table;
@@ -921,19 +881,14 @@ package body Sinput is
end loop;
end if;
- -- Reset source cache pointers to force new read
-
- Source_Cache_First := 1;
- Source_Cache_Last := 0;
-
-- Read in source file table and instance table
Source_File.Tree_Read;
Instances.Tree_Read;
- -- The pointers we read in there for the source buffer and lines
- -- table pointers are junk. We now read in the actual data that
- -- is referenced by these two fields.
+ -- The pointers we read in there for the source buffer and lines table
+ -- pointers are junk. We now read in the actual data that is referenced
+ -- by these two fields.
for J in Source_File.First .. Source_File.Last loop
declare
diff --git a/gcc/ada/sinput.ads b/gcc/ada/sinput.ads
index f678ff62984..b5b2d747cc1 100644
--- a/gcc/ada/sinput.ads
+++ b/gcc/ada/sinput.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 1992-2012, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -342,36 +342,17 @@ package Sinput is
-- The Get_Source_File_Index function is called very frequently. Earlier
-- versions cached a single entry, but then reverted to a serial search,
- -- and this proved to be a significant source of inefficiency. To get
- -- around this, we use the following directly indexed array. The space
- -- of possible input values is a value of type Source_Ptr which is simply
- -- an Int value. The values in this space are allocated sequentially as
- -- new units are loaded.
-
- -- The following table has an entry for each 4K range of possible
- -- Source_Ptr values. The value in the table is the lowest value
- -- Source_File_Index whose Source_Ptr range contains value in the
- -- range.
-
- -- For example, the entry with index 4 in this table represents Source_Ptr
- -- values in the range 4*4096 .. 5*4096-1. The Source_File_Index value
- -- stored would be the lowest numbered source file with at least one byte
- -- in this range.
-
- -- The algorithm used in Get_Source_File_Index is simply to access this
- -- table and then do a serial search starting at the given position. This
- -- will almost always terminate with one or two checks.
+ -- and this proved to be a significant source of inefficiency. We then
+ -- switched to using a table with a start point followed by a serial
+ -- search. Now we make sure source buffers are on a reasonable boundary
+ -- (see Types.Source_Align), and we can just use a direct look up in the
+ -- following table.
-- Note that this array is pretty large, but in most operating systems
-- it will not be allocated in physical memory unless it is actually used.
- Chunk_Power : constant := 12;
- Chunk_Size : constant := 2 ** Chunk_Power;
- -- Change comments above if value changed. Note that Chunk_Size must
- -- be a power of 2 (to allow for efficient access to the table).
-
Source_File_Index_Table :
- array (Int range 0 .. Int'Last / Chunk_Size) of Source_File_Index;
+ array (Int range 0 .. 1 + (Int'Last / Source_Align)) of Source_File_Index;
procedure Set_Source_File_Index_Table (Xnew : Source_File_Index);
-- Sets entries in the Source_File_Index_Table for the newly created
@@ -605,6 +586,7 @@ package Sinput is
-- value is the physical line number in the source being compiled.
function Get_Source_File_Index (S : Source_Ptr) return Source_File_Index;
+ pragma Inline (Get_Source_File_Index);
-- Return file table index of file identified by given source pointer
-- value. This call must always succeed, since any valid source pointer
-- value belongs to some previously loaded source file.
diff --git a/gcc/ada/snames.ads-tmpl b/gcc/ada/snames.ads-tmpl
index 70afdb70110..0be49580d98 100644
--- a/gcc/ada/snames.ads-tmpl
+++ b/gcc/ada/snames.ads-tmpl
@@ -142,11 +142,8 @@ package Snames is
Name_Dimension : constant Name_Id := N + $;
Name_Dimension_System : constant Name_Id := N + $;
Name_Dynamic_Predicate : constant Name_Id := N + $;
- Name_Post : constant Name_Id := N + $;
- Name_Pre : constant Name_Id := N + $;
Name_Static_Predicate : constant Name_Id := N + $;
Name_Synchronization : constant Name_Id := N + $;
- Name_Type_Invariant : constant Name_Id := N + $;
-- Some special names used by the expander. Note that the lower case u's
-- at the start of these names get translated to extra underscores. These
@@ -449,7 +446,7 @@ package Snames is
Name_Wide_Character_Encoding : constant Name_Id := N + $; -- GNAT
Last_Configuration_Pragma_Name : constant Name_Id := N + $;
- -- Remaining pragma names
+ -- Remaining pragma names (non-configuration pragmas)
Name_Abort_Defer : constant Name_Id := N + $; -- GNAT
Name_Abstract_State : constant Name_Id := N + $; -- GNAT
@@ -512,6 +509,8 @@ package Snames is
Name_Import_Valued_Procedure : constant Name_Id := N + $; -- GNAT
Name_Independent : constant Name_Id := N + $; -- Ada 12
Name_Independent_Components : constant Name_Id := N + $; -- Ada 12
+ Name_Initial_Condition : constant Name_Id := N + $; -- GNAT
+ Name_Initializes : constant Name_Id := N + $; -- GNAT
Name_Inline : constant Name_Id := N + $;
Name_Inline_Always : constant Name_Id := N + $; -- GNAT
Name_Inline_Generic : constant Name_Id := N + $; -- GNAT
@@ -562,12 +561,16 @@ package Snames is
Name_Pack : constant Name_Id := N + $;
Name_Page : constant Name_Id := N + $;
Name_Passive : constant Name_Id := N + $; -- GNAT
+ Name_Post : constant Name_Id := N + $; -- GNAT
Name_Postcondition : constant Name_Id := N + $; -- GNAT
+ Name_Post_Class : constant Name_Id := N + $; -- GNAT
+ Name_Pre : constant Name_Id := N + $; -- GNAT
Name_Precondition : constant Name_Id := N + $; -- GNAT
Name_Predicate : constant Name_Id := N + $; -- GNAT
Name_Preelaborable_Initialization : constant Name_Id := N + $; -- Ada 05
Name_Preelaborate : constant Name_Id := N + $;
Name_Preelaborate_05 : constant Name_Id := N + $; -- GNAT
+ Name_Pre_Class : constant Name_Id := N + $; -- GNAT
-- Note: Priority is not in this list because its name matches the name of
-- the corresponding attribute. However, it is included in the definition
@@ -580,6 +583,10 @@ package Snames is
Name_Pure_05 : constant Name_Id := N + $; -- GNAT
Name_Pure_12 : constant Name_Id := N + $; -- GNAT
Name_Pure_Function : constant Name_Id := N + $; -- GNAT
+ Name_Refined_Depends : constant Name_Id := N + $; -- GNAT
+ Name_Refined_Global : constant Name_Id := N + $; -- GNAT
+ Name_Refined_Post : constant Name_Id := N + $; -- GNAT
+ Name_Refined_State : constant Name_Id := N + $; -- GNAT
Name_Relative_Deadline : constant Name_Id := N + $; -- Ada 05
Name_Remote_Access_Type : constant Name_Id := N + $; -- GNAT
Name_Remote_Call_Interface : constant Name_Id := N + $;
@@ -612,6 +619,8 @@ package Snames is
Name_Thread_Local_Storage : constant Name_Id := N + $; -- GNAT
Name_Time_Slice : constant Name_Id := N + $; -- GNAT
Name_Title : constant Name_Id := N + $; -- GNAT
+ Name_Type_Invariant : constant Name_Id := N + $; -- GNAT
+ Name_Type_Invariant_Class : constant Name_Id := N + $; -- GNAT
Name_Unchecked_Union : constant Name_Id := N + $; -- Ada 05
Name_Unimplemented_Unit : constant Name_Id := N + $; -- GNAT
Name_Universal_Aliasing : constant Name_Id := N + $; -- GNAT
@@ -685,7 +694,6 @@ package Snames is
Name_Code : constant Name_Id := N + $;
Name_Component : constant Name_Id := N + $;
Name_Component_Size_4 : constant Name_Id := N + $;
- Name_Contract_In : constant Name_Id := N + $;
Name_Copy : constant Name_Id := N + $;
Name_D_Float : constant Name_Id := N + $;
Name_Decreases : constant Name_Id := N + $;
@@ -711,7 +719,7 @@ package Snames is
Name_In_Out : constant Name_Id := N + $;
Name_Increases : constant Name_Id := N + $;
Name_Info : constant Name_Id := N + $;
- Name_Integrity : constant Name_Id := N + $;
+ Name_Input_Only : constant Name_Id := N + $;
Name_Internal : constant Name_Id := N + $;
Name_Link_Name : constant Name_Id := N + $;
Name_Lowercase : constant Name_Id := N + $;
@@ -745,10 +753,14 @@ package Snames is
Name_No_Unroll : constant Name_Id := N + $;
Name_No_Vector : constant Name_Id := N + $;
Name_Nominal : constant Name_Id := N + $;
+ Name_Non_Volatile : constant Name_Id := N + $;
Name_On : constant Name_Id := N + $;
Name_Optional : constant Name_Id := N + $;
+ Name_Output_Only : constant Name_Id := N + $;
Name_Policy : constant Name_Id := N + $;
Name_Parameter_Types : constant Name_Id := N + $;
+ Name_Part_Of : constant Name_Id := N + $;
+ Name_Proof_In : constant Name_Id := N + $;
Name_Reason : constant Name_Id := N + $;
Name_Reference : constant Name_Id := N + $;
Name_Requires : constant Name_Id := N + $;
@@ -795,20 +807,15 @@ package Snames is
-- Names of recognized attributes. The entries with the comment "Ada 83"
-- are attributes that are defined in Ada 83, but not in Ada 95. These
- -- attributes are implemented in both Ada 83 and Ada 95 modes in GNAT.
+ -- attributes are implemented in all Ada modes in GNAT.
-- The entries marked GNAT are attributes that are defined by GNAT and
- -- implemented in both Ada 83 and Ada 95 modes. Full descriptions of these
- -- implementation dependent attributes may be found in the appropriate
- -- section in Sem_Attr.
+ -- implemented in all Ada modes. Full descriptions of these implementation
+ -- dependent attributes may be found in the appropriate Sem_Attr section.
-- The entries marked VMS are recognized only in OpenVMS implementations
-- of GNAT, and are treated as illegal in all other contexts.
- -- The entries marked HiLite are attributes that are defined by Hi-Lite
- -- and implemented in GNAT operating under formal verification mode. The
- -- entries are treated as illegal in all other contexts.
-
First_Attribute_Name : constant Name_Id := N + $;
Name_Abort_Signal : constant Name_Id := N + $; -- GNAT
Name_Access : constant Name_Id := N + $;
@@ -869,8 +876,9 @@ package Snames is
Name_Last_Valid : constant Name_Id := N + $; -- Ada 12
Name_Leading_Part : constant Name_Id := N + $;
Name_Length : constant Name_Id := N + $;
+ Name_Library_Level : constant Name_Id := N + $; -- GNAT
Name_Lock_Free : constant Name_Id := N + $; -- GNAT
- Name_Loop_Entry : constant Name_Id := N + $; -- HiLite
+ Name_Loop_Entry : constant Name_Id := N + $; -- GNAT
Name_Machine_Emax : constant Name_Id := N + $;
Name_Machine_Emin : constant Name_Id := N + $;
Name_Machine_Mantissa : constant Name_Id := N + $;
@@ -1213,7 +1221,7 @@ package Snames is
-- Additional reserved words and identifiers used in GNAT Project Files
-- Note that Name_External is already previously declared.
- -- The names with the -- GB annotation are only used in gprbuild.
+ -- Names with a -- GB annotation are only used in gprbuild or gprclean
Name_Active : constant Name_Id := N + $;
Name_Aggregate : constant Name_Id := N + $;
@@ -1221,6 +1229,8 @@ package Snames is
Name_Archive_Builder_Append_Option : constant Name_Id := N + $;
Name_Archive_Indexer : constant Name_Id := N + $;
Name_Archive_Suffix : constant Name_Id := N + $;
+ Name_Artifacts_In_Exec_Dir : constant Name_Id := N + $; -- GB
+ Name_Artifacts_In_Object_Dir : constant Name_Id := N + $; -- GB
Name_Binder : constant Name_Id := N + $;
Name_Body_Suffix : constant Name_Id := N + $;
Name_Builder : constant Name_Id := N + $;
@@ -1292,6 +1302,7 @@ package Snames is
Name_Library_Options : constant Name_Id := N + $;
Name_Library_Partial_Linker : constant Name_Id := N + $;
Name_Library_Reference_Symbol_File : constant Name_Id := N + $;
+ Name_Library_Rpath_Options : constant Name_Id := N + $; -- GB
Name_Library_Standalone : constant Name_Id := N + $;
Name_Library_Encapsulated_Options : constant Name_Id := N + $; -- GB
Name_Library_Encapsulated_Supported : constant Name_Id := N + $; -- GB
@@ -1486,6 +1497,7 @@ package Snames is
Attribute_Last_Valid,
Attribute_Leading_Part,
Attribute_Length,
+ Attribute_Library_Level,
Attribute_Lock_Free,
Attribute_Loop_Entry,
Attribute_Machine_Emax,
@@ -1817,6 +1829,8 @@ package Snames is
Pragma_Import_Valued_Procedure,
Pragma_Independent,
Pragma_Independent_Components,
+ Pragma_Initial_Condition,
+ Pragma_Initializes,
Pragma_Inline,
Pragma_Inline_Always,
Pragma_Inline_Generic,
@@ -1849,17 +1863,25 @@ package Snames is
Pragma_Pack,
Pragma_Page,
Pragma_Passive,
+ Pragma_Post,
Pragma_Postcondition,
+ Pragma_Post_Class,
+ Pragma_Pre,
Pragma_Precondition,
Pragma_Predicate,
Pragma_Preelaborable_Initialization,
Pragma_Preelaborate,
Pragma_Preelaborate_05,
+ Pragma_Pre_Class,
Pragma_Psect_Object,
Pragma_Pure,
Pragma_Pure_05,
Pragma_Pure_12,
Pragma_Pure_Function,
+ Pragma_Refined_Depends,
+ Pragma_Refined_Global,
+ Pragma_Refined_Post,
+ Pragma_Refined_State,
Pragma_Relative_Deadline,
Pragma_Remote_Access_Type,
Pragma_Remote_Call_Interface,
@@ -1883,6 +1905,8 @@ package Snames is
Pragma_Thread_Local_Storage,
Pragma_Time_Slice,
Pragma_Title,
+ Pragma_Type_Invariant,
+ Pragma_Type_Invariant_Class,
Pragma_Unchecked_Union,
Pragma_Unimplemented_Unit,
Pragma_Universal_Aliasing,
diff --git a/gcc/ada/sprint.adb b/gcc/ada/sprint.adb
index 5259dd776ff..43ed21a2862 100644
--- a/gcc/ada/sprint.adb
+++ b/gcc/ada/sprint.adb
@@ -800,6 +800,7 @@ package body Sprint is
-- do not duplicate the output at this point.
if Nkind (Node) = N_Freeze_Entity
+ or else Nkind (Node) = N_Freeze_Generic_Entity
or else Nkind (Node) = N_Implicit_Label_Declaration
then
Sprint_Node_Actual (Node);
@@ -1862,6 +1863,16 @@ package body Sprint is
Write_Rewrite_Str (">>>");
end if;
+ when N_Freeze_Generic_Entity =>
+ if Dump_Original_Only then
+ null;
+
+ else
+ Write_Indent;
+ Write_Str_With_Col_Check_Sloc ("freeze_generic ");
+ Write_Id (Entity (Node));
+ end if;
+
when N_Full_Type_Declaration =>
Write_Indent_Str_Sloc ("type ");
Sprint_Node (Defining_Identifier (Node));
diff --git a/gcc/ada/sprint.ads b/gcc/ada/sprint.ads
index 173d148677d..72fde2f23eb 100644
--- a/gcc/ada/sprint.ads
+++ b/gcc/ada/sprint.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 1992-2012, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -57,6 +57,7 @@ package Sprint is
-- Expression with range check {expression}
-- Free statement free expr [storage_pool = xxx]
-- Freeze entity with freeze actions freeze entityname [ actions ]
+ -- Freeze generic entity freeze_generic entityname
-- Implicit call to run time routine $routine-name
-- Implicit exportation $pragma import (...)
-- Implicit importation $pragma export (...)
diff --git a/gcc/ada/stand.adb b/gcc/ada/stand.adb
index ab703fbb73d..55ec41839b6 100644
--- a/gcc/ada/stand.adb
+++ b/gcc/ada/stand.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992,1993,1994,1995,2009 Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -76,7 +76,6 @@ package body Stand is
Tree_Read_Int (Int (Standard_Op_Shift_Left));
Tree_Read_Int (Int (Standard_Op_Shift_Right));
Tree_Read_Int (Int (Standard_Op_Shift_Right_Arithmetic));
-
end Tree_Read;
----------------
@@ -121,7 +120,6 @@ package body Stand is
Tree_Write_Int (Int (Standard_Op_Shift_Left));
Tree_Write_Int (Int (Standard_Op_Shift_Right));
Tree_Write_Int (Int (Standard_Op_Shift_Right_Arithmetic));
-
end Tree_Write;
end Stand;
diff --git a/gcc/ada/stand.ads b/gcc/ada/stand.ads
index 33a184ccfbc..0f6b876937e 100644
--- a/gcc/ada/stand.ads
+++ b/gcc/ada/stand.ads
@@ -451,13 +451,15 @@ package Stand is
Standard_Integer_16 : Entity_Id;
Standard_Integer_32 : Entity_Id;
Standard_Integer_64 : Entity_Id;
- -- These are signed integer types with the indicated sizes, They are used
- -- for the underlying implementation types for fixed-point and enumeration
- -- types.
+ -- These are signed integer types with the indicated sizes. Used for the
+ -- underlying implementation types for fixed-point and enumeration types.
Standard_Unsigned : Entity_Id;
-- An unsigned type of the same size as Standard_Integer
+ Standard_Unsigned_64 : Entity_Id;
+ -- An unsigned type, mod 2 ** 64, size of 64 bits.
+
Abort_Signal : Entity_Id;
-- Entity for abort signal exception
diff --git a/gcc/ada/stylesw.adb b/gcc/ada/stylesw.adb
index 7b78a164395..a708da9e5bc 100644
--- a/gcc/ada/stylesw.adb
+++ b/gcc/ada/stylesw.adb
@@ -25,6 +25,7 @@
with Hostparm; use Hostparm;
with Opt; use Opt;
+with Output; use Output;
package body Stylesw is
@@ -466,9 +467,13 @@ package body Stylesw is
null;
when others =>
- Err_Col := Err_Col - 1;
- Bad_Style_Switch ("invalid style switch: " & C);
- return;
+ if Ignore_Unrecognized_VWY_Switches then
+ Write_Line ("unrecognized switch -gnaty" & C & " ignored");
+ else
+ Err_Col := Err_Col - 1;
+ Bad_Style_Switch ("invalid style switch: " & C);
+ return;
+ end if;
end case;
-- Turning switches off
@@ -571,9 +576,13 @@ package body Stylesw is
null;
when others =>
- Err_Col := Err_Col - 1;
- Bad_Style_Switch ("invalid style switch: " & C);
- return;
+ if Ignore_Unrecognized_VWY_Switches then
+ Write_Line ("unrecognized switch -gnaty-" & C & " ignored");
+ else
+ Err_Col := Err_Col - 1;
+ Bad_Style_Switch ("invalid style switch: " & C);
+ return;
+ end if;
end case;
end if;
end loop;
diff --git a/gcc/ada/switch-c.adb b/gcc/ada/switch-c.adb
index 197be06a19e..0d80f44a3a5 100644
--- a/gcc/ada/switch-c.adb
+++ b/gcc/ada/switch-c.adb
@@ -717,6 +717,12 @@ package body Switch.C is
return;
+ -- -gnateu (unrecognized y,V,w switches)
+
+ when 'u' =>
+ Ptr := Ptr + 1;
+ Ignore_Unrecognized_VWY_Switches := True;
+
-- -gnateV (validity checks on parameters)
when 'V' =>
diff --git a/gcc/ada/system-vxworks-arm.ads b/gcc/ada/system-vxworks-arm.ads
index ae8ddd51065..60a41e1b27b 100644
--- a/gcc/ada/system-vxworks-arm.ads
+++ b/gcc/ada/system-vxworks-arm.ads
@@ -7,7 +7,7 @@
-- S p e c --
-- (VxWorks Version ARM) --
-- --
--- Copyright (C) 1992-2012, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
-- --
-- This specification is derived from the Ada Reference Manual for use with --
-- GNAT. The copyright notice above, and the license provisions that follow --
@@ -142,8 +142,8 @@ private
Preallocated_Stacks : constant Boolean := False;
Signed_Zeros : constant Boolean := True;
Stack_Check_Default : constant Boolean := False;
- Stack_Check_Probes : constant Boolean := False;
- Stack_Check_Limits : constant Boolean := True;
+ Stack_Check_Probes : constant Boolean := True;
+ Stack_Check_Limits : constant Boolean := False;
Support_Aggregates : constant Boolean := True;
Support_Composite_Assign : constant Boolean := True;
Support_Composite_Compare : constant Boolean := True;
diff --git a/gcc/ada/targparm.ads b/gcc/ada/targparm.ads
index 17c934a0ab1..c3cace3c559 100644
--- a/gcc/ada/targparm.ads
+++ b/gcc/ada/targparm.ads
@@ -402,7 +402,7 @@ package Targparm is
-- appropriate default in some cases, e.g. on embedded targets which do not
-- allow the possibility of multi-processors. The default can be overridden
-- using pragmas Enable/Disable_Atomic_Synchronization and also by use of
- -- the debug flags gnat.d and gnatd.e.
+ -- the corresponding debug flags -gnatd.e and -gnatd.d.
Support_Aggregates_On_Target : Boolean := True;
-- In the general case, the use of aggregates may generate calls
diff --git a/gcc/ada/thread.c b/gcc/ada/thread.c
index 87d7603cfa0..31309e05b6e 100644
--- a/gcc/ada/thread.c
+++ b/gcc/ada/thread.c
@@ -6,7 +6,7 @@
* *
* C Implementation File *
* *
- * Copyright (C) 2011, Free Software Foundation, Inc. *
+ * Copyright (C) 2011-2013, Free Software Foundation, Inc. *
* *
* GNAT is free software; you can redistribute it and/or modify it under *
* terms of the GNU General Public License as published by the Free Soft- *
@@ -33,31 +33,15 @@
#include "s-oscons.h"
-#ifdef NEED_PTHREAD_CONDATTR_SETCLOCK
+/* If the clock we used for tasking (CLOCK_RT_Ada) is not the default
+ * CLOCK_REALTIME, we need to set cond var attributes accordingly.
+ */
+#if CLOCK_RT_Ada != CLOCK_REALTIME
# include <pthread.h>
# include <time.h>
-#ifndef _AIXVERSION_530
-/* We use the same runtime library for AIX 5.2 and 5.3, but pthread_condattr_
- * setclock exists only on the latter, so for the former provide a dummy
- * implementation (declared below, weak symbol defined in init.c).
- *
- * Note: this means that under AIX 5.2 we'll be using CLOCK_MONOTONIC
- * timestamps from clock_gettime() as arguments to pthread_cond_timedwait,
- * which expects a CLOCK_REALTIME value, which is technically wrong, but
- * inocuous in practice on that particular platform since both clocks happen
- * to use close epochs.
- */
-
-extern int pthread_condattr_setclock (pthread_condattr_t *attr, clockid_t cl);
-#endif
-
int
__gnat_pthread_condattr_setup(pthread_condattr_t *attr) {
-/*
- * If using a clock other than CLOCK_REALTIME for the Ada Monotonic_Clock,
- * the corresponding clock id must be set for condition variables.
- */
return pthread_condattr_setclock (attr, CLOCK_RT_Ada);
}
diff --git a/gcc/ada/types.ads b/gcc/ada/types.ads
index 4bbaa6b43da..4888d69e190 100644
--- a/gcc/ada/types.ads
+++ b/gcc/ada/types.ads
@@ -172,7 +172,7 @@ package Types is
for Physical_Line_Number'Size use 32;
-- Line number type, used for storing physical line numbers (i.e. line
-- numbers in the physical file being compiled, unaffected by the presence
- -- of source reference pragmas.
+ -- of source reference pragmas).
type Column_Number is range 0 .. 32767;
for Column_Number'Size use 16;
@@ -183,11 +183,17 @@ package Types is
No_Column_Number : constant Column_Number := 0;
-- Special value used to indicate no column number
+ Source_Align : constant := 2 ** 12;
+ -- Alignment requirement for source buffers (by keeping source buffers
+ -- aligned, we can optimize the implementation of Get_Source_File_Index.
+ -- See this routine in Sinput for details.
+
subtype Source_Buffer is Text_Buffer;
-- Type used to store text of a source file. The buffer for the main
-- source (the source specified on the command line) has a lower bound
-- starting at zero. Subsequent subsidiary sources have lower bounds
- -- which are one greater than the previous upper bound.
+ -- which are one greater than the previous upper bound, rounded up to
+ -- a multiple of Source_Align.
subtype Big_Source_Buffer is Text_Buffer (0 .. Text_Ptr'Last);
-- This is a virtual type used as the designated type of the access type
diff --git a/gcc/ada/ug_words b/gcc/ada/ug_words
index d450164ee4c..1f73288481a 100644
--- a/gcc/ada/ug_words
+++ b/gcc/ada/ug_words
@@ -72,7 +72,9 @@ gcc -c ^ GNAT COMPILE
-gnatep ^ /DATA_PREPROCESSING
-gnateP ^ /CATEGORIZATION_WARNINGS
-gnateS ^ /SCO_OUTPUT
--gnatet ^ /TARGET_DEPENDENT_INFO
+-gnatet ^ /WRITE_TARGET_DEPENDENT_INFO
+-gnateT ^ /READ_TARGET_DEPENDENT_INFO
+-gnateu ^ /IGNORE_UNRECOGNIZED
-gnateV ^ /PARAMETER_VALIDITY_CHECK
-gnateY ^ /IGNORE_STYLE_CHECKS_PRAGMAS
-gnatE ^ /CHECKS=ELABORATION
@@ -142,6 +144,8 @@ gcc -c ^ GNAT COMPILE
-gnatwC ^ /WARNINGS=NOCONDITIONALS
-gnatw.c ^ /WARNINGS=MISSING_COMPONENT_CLAUSES
-gnatw.C ^ /WARNINGS=NOMISSING_COMPONENT_CLAUSES
+-gnatw.d ^ /WARNINGS=TAG_WARNINGS
+-gnatw.D ^ /WARNINGS=NOTAG_WARNINGS
-gnatwd ^ /WARNINGS=IMPLICIT_DEREFERENCE
-gnatwD ^ /WARNINGS=NOIMPLICIT_DEREFERENCE
-gnatwe ^ /WARNINGS=ERRORS
@@ -202,6 +206,8 @@ gcc -c ^ GNAT COMPILE
-gnatw.X ^ /WARNINGS=NOLOCAL_RAISE_HANDLING
-gnatwy ^ /WARNINGS=ADA_2005_COMPATIBILITY
-gnatwY ^ /WARNINGS=NOADA_2005_COMPATIBILITY
+-gnatw.y ^ /WARNINGS=WHY_SPEC_NEEDS_BODY
+-gnatw.Y ^ /WARNINGS=NOWHY_SPEC_NEEDS_BODY
-gnatwz ^ /WARNINGS=UNCHECKED_CONVERSIONS
-gnatwZ ^ /WARNINGS=NOUNCHECKED_CONVERSIONS
-gnatW8 ^ /WIDE_CHARACTER_ENCODING=UTF8
diff --git a/gcc/ada/usage.adb b/gcc/ada/usage.adb
index ffcd7246905..3f566f47fb5 100644
--- a/gcc/ada/usage.adb
+++ b/gcc/ada/usage.adb
@@ -251,6 +251,11 @@ begin
Write_Switch_Char ("eT=?");
Write_Line ("Read target dependent information file ?, e.g. gnateT=tdf");
+ -- Line for -gnateu switch
+
+ Write_Switch_Char ("eu");
+ Write_Line ("Ignore unrecognized style/validity/warning switches");
+
-- Line for -gnateV switch
Write_Switch_Char ("eV");
@@ -571,6 +576,8 @@ begin
Write_Line (" .X* turn off warnings for non-local exception");
Write_Line (" y*+ turn on warnings for Ada compatibility issues");
Write_Line (" Y turn off warnings for Ada compatibility issues");
+ Write_Line (" .y turn on info messages for why pkg body needed");
+ Write_Line (" .Y* turn off info messages for why pkg body needed");
Write_Line (" z*+ turn on warnings for suspicious " &
"unchecked conversion");
Write_Line (" Z turn off warnings for suspicious " &
diff --git a/gcc/ada/validsw.adb b/gcc/ada/validsw.adb
index b37825ed461..517180ad936 100644
--- a/gcc/ada/validsw.adb
+++ b/gcc/ada/validsw.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 2001-2012, Free Software Foundation, Inc. --
+-- Copyright (C) 2001-2013, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -23,7 +23,8 @@
-- --
------------------------------------------------------------------------------
-with Opt; use Opt;
+with Opt; use Opt;
+with Output; use Output;
package body Validsw is
@@ -229,9 +230,14 @@ package body Validsw is
null;
when others =>
- OK := False;
- Err_Col := J - 1;
- return;
+ if Ignore_Unrecognized_VWY_Switches then
+ Write_Line ("unrecognized switch -gnatV" & C & " ignored");
+ else
+ OK := False;
+ Err_Col := J - 1;
+ return;
+ end if;
+
end case;
end loop;
diff --git a/gcc/ada/vms_data.ads b/gcc/ada/vms_data.ads
index f92788af69b..aa22577efce 100644
--- a/gcc/ada/vms_data.ads
+++ b/gcc/ada/vms_data.ads
@@ -1802,6 +1802,13 @@ package VMS_Data is
-- otherwise ignored. Allows style checks to be fully controlled by
-- command line qualifiers.
+ S_GCC_IgnoreU : aliased constant S := "/IGNORE_UNRECOGNIZED " &
+ "-gnateu";
+ -- /IGNORE_UNRECOGNIZED
+ --
+ -- Causes unrecognized style switches, validity switches, and warning
+ -- switches to be ignored rather than generating an error message.
+
S_GCC_Immed : aliased constant S := "/IMMEDIATE_ERRORS " &
"-gnatdO";
-- /NOIMMEDIATE_ERRORS (D)
@@ -2885,12 +2892,17 @@ package VMS_Data is
--
-- All compiler tables start at nnn times usual starting size.
- S_GCC_Target : aliased constant S := "/TARGET_DEPENDENT_INFO " &
- "-gnatet";
- -- /NOTARGET_DEPENDENT_INFO (D)
- -- /TARGET_DEPENDENT_INFO
+ S_GCC_Target_W : aliased constant S := "/WRITE_TARGET_DEPENDENT_INFO=<" &
+ "-gnatet=>";
+ -- /WRITE_TARGET_DEPENDENT_INFO=file
--
- -- Generate target dependent information.
+ -- Generate target dependent information to file.
+
+ S_GCC_Target_R : aliased constant S := "/READ_TARGET_DEPENDENT_INFO=<" &
+ "-gnateT=>";
+ -- /READ_TARGET_DEPENDENT_INFO=file
+ --
+ -- Read target dependent information from file.
S_GCC_Trace : aliased constant S := "/TRACE_UNITS " &
"-gnatdc";
@@ -3094,6 +3106,10 @@ package VMS_Data is
"-gnatwd " &
"NO_IMPLICIT_DEREFERENCE " &
"-gnatwD " &
+ "TAG_WARNINGS " &
+ "-gnatw.d " &
+ "NOTAG_WARNINGS " &
+ "-gnatw.D " &
"ERRORS " &
"-gnatwe " &
"UNREFERENCED_FORMALS " &
@@ -3218,6 +3234,10 @@ package VMS_Data is
"-gnatwy " &
"NOADA_2005_COMPATIBILITY " &
"-gnatwY " &
+ "WHY_SPEC_NEEDS_BODY " &
+ "-gnatw.y " &
+ "NO_WHY_SPEC_NEEDS_BODY " &
+ "-gnatw.Y " &
"UNCHECKED_CONVERSIONS " &
"-gnatwz " &
"NOUNCHECKED_CONVERSIONS " &
@@ -3483,12 +3503,24 @@ package VMS_Data is
-- VARIABLES_UNINITIALIZED Activates warnings on unassigned variables.
-- Causes warnings to be generated when a variable
-- is accessed which may not be properly
- -- uninitialized.
- -- The default is that such warnings are
- -- generated.
+ -- uninitialized. The default is that such
+ -- warnings are generated.
+ --
+ -- NOVARIABLES_UNINITIALIZED
+ -- Suppress warnings for uninitialized variables.
+ --
+ -- TAG_WARNINGS Causes the string [xxx] to be added to warnings
+ -- that are controlled by the warning string xxx,
+ -- e.g. [REDUNDANT], or if the warning is enabled
+ -- by default, the tag is [enabled by default].
+ --
+ -- NOTAG_WARNINGS Turns off warning tag output (default setting).
+ --
+ -- WHY_SPEC_NEEDS_BODY Generates information messages showing why a
+ -- package specification requires a body.
--
- -- NOVARIABLES_UNINITIALIZED Suppress warnings for uninitialized
- -- variables.
+ -- NO_WHY_SPEC_NEEDS_BODY Turns off information messages showing why a
+ -- package specification requires a body.
S_GCC_WarnX : aliased constant S := "/NOWARNINGS " &
"-gnatws";
@@ -3681,6 +3713,7 @@ package VMS_Data is
S_GCC_IdentX 'Access,
S_GCC_IgnoreR 'Access,
S_GCC_IgnoreS 'Access,
+ S_GCC_IgnoreU 'Access,
S_GCC_Immed 'Access,
S_GCC_Inline 'Access,
S_GCC_InlineX 'Access,
@@ -3723,7 +3756,8 @@ package VMS_Data is
S_GCC_Symbol 'Access,
S_GCC_Syntax 'Access,
S_GCC_Table 'Access,
- S_GCC_Target 'Access,
+ S_GCC_Target_W'Access,
+ S_GCC_Target_R'Access,
S_GCC_Trace 'Access,
S_GCC_Tree 'Access,
S_GCC_Trys 'Access,
diff --git a/gcc/ada/warnsw.adb b/gcc/ada/warnsw.adb
index 36360f96d63..009b450784c 100644
--- a/gcc/ada/warnsw.adb
+++ b/gcc/ada/warnsw.adb
@@ -25,6 +25,7 @@
with Err_Vars; use Err_Vars;
with Opt; use Opt;
+with Output; use Output;
package body Warnsw is
@@ -50,6 +51,8 @@ package body Warnsw is
W.Implementation_Unit_Warnings;
Ineffective_Inline_Warnings :=
W.Ineffective_Inline_Warnings;
+ List_Body_Required_Info :=
+ W.List_Body_Required_Info;
List_Inherited_Aspects :=
W.List_Inherited_Aspects;
Warning_Doc_Switch :=
@@ -144,6 +147,8 @@ package body Warnsw is
Implementation_Unit_Warnings;
W.Ineffective_Inline_Warnings :=
Ineffective_Inline_Warnings;
+ W.List_Body_Required_Info :=
+ List_Body_Required_Info;
W.List_Inherited_Aspects :=
List_Inherited_Aspects;
W.Warning_Doc_Switch :=
@@ -256,6 +261,7 @@ package body Warnsw is
Elab_Warnings := True;
Implementation_Unit_Warnings := True;
Ineffective_Inline_Warnings := True;
+ List_Body_Required_Info := True;
List_Inherited_Aspects := True;
Warning_Doc_Switch := True;
Warn_On_Ada_2005_Compatibility := True;
@@ -385,8 +391,18 @@ package body Warnsw is
Warn_On_Non_Local_Exception := False;
No_Warn_On_Non_Local_Exception := True;
+ when 'y' =>
+ List_Body_Required_Info := True;
+
+ when 'Y' =>
+ List_Body_Required_Info := False;
+
when others =>
- return False;
+ if Ignore_Unrecognized_VWY_Switches then
+ Write_Line ("unrecognized switch -gnatw." & C & " ignored");
+ else
+ return False;
+ end if;
end case;
return True;
@@ -406,6 +422,7 @@ package body Warnsw is
Elab_Warnings := False;
Implementation_Unit_Warnings := False;
Ineffective_Inline_Warnings := True;
+ List_Body_Required_Info := False;
List_Inherited_Aspects := False;
Warning_Doc_Switch := False;
Warn_On_Ada_2005_Compatibility := True;
@@ -487,6 +504,7 @@ package body Warnsw is
Elab_Warnings := False;
Implementation_Unit_Warnings := False;
Ineffective_Inline_Warnings := False;
+ List_Body_Required_Info := False;
List_Inherited_Aspects := False;
Warning_Doc_Switch := False;
Warn_On_Ada_2005_Compatibility := False;
@@ -672,6 +690,11 @@ package body Warnsw is
Warn_On_Unchecked_Conversion := False;
when others =>
+ if Ignore_Unrecognized_VWY_Switches then
+ Write_Line ("unrecognized switch -gnatw" & C & " ignored");
+ else
+ return False;
+ end if;
return False;
end case;
diff --git a/gcc/ada/warnsw.ads b/gcc/ada/warnsw.ads
index b39f545802d..0358fd77d4f 100644
--- a/gcc/ada/warnsw.ads
+++ b/gcc/ada/warnsw.ads
@@ -68,6 +68,7 @@ package Warnsw is
Elab_Warnings : Boolean;
Implementation_Unit_Warnings : Boolean;
Ineffective_Inline_Warnings : Boolean;
+ List_Body_Required_Info : Boolean;
List_Inherited_Aspects : Boolean;
Warning_Doc_Switch : Boolean;
Warn_On_Ada_2005_Compatibility : Boolean;
diff --git a/gcc/alias.c b/gcc/alias.c
index 966e9d28d5a..1736169b476 100644
--- a/gcc/alias.c
+++ b/gcc/alias.c
@@ -40,11 +40,11 @@ along with GCC; see the file COPYING3. If not see
#include "timevar.h"
#include "dumpfile.h"
#include "target.h"
-#include "cgraph.h"
#include "df.h"
#include "tree-ssa-alias.h"
#include "pointer-set.h"
-#include "tree-ssa.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
/* The aliasing API provided here solves related but different problems:
@@ -500,51 +500,70 @@ objects_must_conflict_p (tree t1, tree t2)
return alias_sets_must_conflict_p (set1, set2);
}
-/* Return true if all nested component references handled by
- get_inner_reference in T are such that we should use the alias set
- provided by the object at the heart of T.
-
- This is true for non-addressable components (which don't have their
- own alias set), as well as components of objects in alias set zero.
- This later point is a special case wherein we wish to override the
- alias set used by the component, but we don't have per-FIELD_DECL
- assignable alias sets. */
-
-bool
-component_uses_parent_alias_set (const_tree t)
+/* Return the outermost parent of component present in the chain of
+ component references handled by get_inner_reference in T with the
+ following property:
+ - the component is non-addressable, or
+ - the parent has alias set zero,
+ or NULL_TREE if no such parent exists. In the former cases, the alias
+ set of this parent is the alias set that must be used for T itself. */
+
+tree
+component_uses_parent_alias_set_from (const_tree t)
{
- while (1)
- {
- /* If we're at the end, it vacuously uses its own alias set. */
- if (!handled_component_p (t))
- return false;
+ const_tree found = NULL_TREE;
+ while (handled_component_p (t))
+ {
switch (TREE_CODE (t))
{
case COMPONENT_REF:
if (DECL_NONADDRESSABLE_P (TREE_OPERAND (t, 1)))
- return true;
+ found = t;
break;
case ARRAY_REF:
case ARRAY_RANGE_REF:
if (TYPE_NONALIASED_COMPONENT (TREE_TYPE (TREE_OPERAND (t, 0))))
- return true;
+ found = t;
break;
case REALPART_EXPR:
case IMAGPART_EXPR:
break;
- default:
+ case BIT_FIELD_REF:
+ case VIEW_CONVERT_EXPR:
/* Bitfields and casts are never addressable. */
- return true;
+ found = t;
+ break;
+
+ default:
+ gcc_unreachable ();
}
+ if (get_alias_set (TREE_TYPE (TREE_OPERAND (t, 0))) == 0)
+ found = t;
+
t = TREE_OPERAND (t, 0);
- if (get_alias_set (TREE_TYPE (t)) == 0)
- return true;
}
+
+ if (found)
+ return TREE_OPERAND (found, 0);
+
+ return NULL_TREE;
+}
+
+
+/* Return whether the pointer-type T effective for aliasing may
+ access everything and thus the reference has to be assigned
+ alias-set zero. */
+
+static bool
+ref_all_alias_ptr_type_p (const_tree t)
+{
+ return (TREE_CODE (TREE_TYPE (t)) == VOID_TYPE
+ || TYPE_REF_CAN_ALIAS_ALL (t));
}
/* Return the alias set for the memory pointed to by T, which may be
@@ -554,11 +573,6 @@ component_uses_parent_alias_set (const_tree t)
static alias_set_type
get_deref_alias_set_1 (tree t)
{
- /* If we're not doing any alias analysis, just assume everything
- aliases everything else. */
- if (!flag_strict_aliasing)
- return 0;
-
/* All we care about is the type. */
if (! TYPE_P (t))
t = TREE_TYPE (t);
@@ -566,8 +580,7 @@ get_deref_alias_set_1 (tree t)
/* If we have an INDIRECT_REF via a void pointer, we don't
know anything about what that might alias. Likewise if the
pointer is marked that way. */
- if (TREE_CODE (TREE_TYPE (t)) == VOID_TYPE
- || TYPE_REF_CAN_ALIAS_ALL (t))
+ if (ref_all_alias_ptr_type_p (t))
return 0;
return -1;
@@ -579,6 +592,11 @@ get_deref_alias_set_1 (tree t)
alias_set_type
get_deref_alias_set (tree t)
{
+ /* If we're not doing any alias analysis, just assume everything
+ aliases everything else. */
+ if (!flag_strict_aliasing)
+ return 0;
+
alias_set_type set = get_deref_alias_set_1 (t);
/* Fall back to the alias-set of the pointed-to type. */
@@ -592,6 +610,98 @@ get_deref_alias_set (tree t)
return set;
}
+/* Return the pointer-type relevant for TBAA purposes from the
+ memory reference tree *T or NULL_TREE in which case *T is
+ adjusted to point to the outermost component reference that
+ can be used for assigning an alias set. */
+
+static tree
+reference_alias_ptr_type_1 (tree *t)
+{
+ tree inner;
+
+ /* Get the base object of the reference. */
+ inner = *t;
+ while (handled_component_p (inner))
+ {
+ /* If there is a VIEW_CONVERT_EXPR in the chain we cannot use
+ the type of any component references that wrap it to
+ determine the alias-set. */
+ if (TREE_CODE (inner) == VIEW_CONVERT_EXPR)
+ *t = TREE_OPERAND (inner, 0);
+ inner = TREE_OPERAND (inner, 0);
+ }
+
+ /* Handle pointer dereferences here, they can override the
+ alias-set. */
+ if (INDIRECT_REF_P (inner)
+ && ref_all_alias_ptr_type_p (TREE_TYPE (TREE_OPERAND (inner, 0))))
+ return TREE_TYPE (TREE_OPERAND (inner, 0));
+ else if (TREE_CODE (inner) == TARGET_MEM_REF)
+ return TREE_TYPE (TMR_OFFSET (inner));
+ else if (TREE_CODE (inner) == MEM_REF
+ && ref_all_alias_ptr_type_p (TREE_TYPE (TREE_OPERAND (inner, 1))))
+ return TREE_TYPE (TREE_OPERAND (inner, 1));
+
+ /* If the innermost reference is a MEM_REF that has a
+ conversion embedded treat it like a VIEW_CONVERT_EXPR above,
+ using the memory access type for determining the alias-set. */
+ if (TREE_CODE (inner) == MEM_REF
+ && (TYPE_MAIN_VARIANT (TREE_TYPE (inner))
+ != TYPE_MAIN_VARIANT
+ (TREE_TYPE (TREE_TYPE (TREE_OPERAND (inner, 1))))))
+ return TREE_TYPE (TREE_OPERAND (inner, 1));
+
+ /* Otherwise, pick up the outermost object that we could have
+ a pointer to. */
+ tree tem = component_uses_parent_alias_set_from (*t);
+ if (tem)
+ *t = tem;
+
+ return NULL_TREE;
+}
+
+/* Return the pointer-type relevant for TBAA purposes from the
+ gimple memory reference tree T. This is the type to be used for
+ the offset operand of MEM_REF or TARGET_MEM_REF replacements of T
+ and guarantees that get_alias_set will return the same alias
+ set for T and the replacement. */
+
+tree
+reference_alias_ptr_type (tree t)
+{
+ tree ptype = reference_alias_ptr_type_1 (&t);
+ /* If there is a given pointer type for aliasing purposes, return it. */
+ if (ptype != NULL_TREE)
+ return ptype;
+
+ /* Otherwise build one from the outermost component reference we
+ may use. */
+ if (TREE_CODE (t) == MEM_REF
+ || TREE_CODE (t) == TARGET_MEM_REF)
+ return TREE_TYPE (TREE_OPERAND (t, 1));
+ else
+ return build_pointer_type (TYPE_MAIN_VARIANT (TREE_TYPE (t)));
+}
+
+/* Return whether the pointer-types T1 and T2 used to determine
+ two alias sets of two references will yield the same answer
+ from get_deref_alias_set. */
+
+bool
+alias_ptr_types_compatible_p (tree t1, tree t2)
+{
+ if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
+ return true;
+
+ if (ref_all_alias_ptr_type_p (t1)
+ || ref_all_alias_ptr_type_p (t2))
+ return false;
+
+ return (TYPE_MAIN_VARIANT (TREE_TYPE (t1))
+ == TYPE_MAIN_VARIANT (TREE_TYPE (t2)));
+}
+
/* Return the alias set for T, which may be either a type or an
expression. Call language-specific routine for help, if needed. */
@@ -615,8 +725,6 @@ get_alias_set (tree t)
aren't types. */
if (! TYPE_P (t))
{
- tree inner;
-
/* Give the language a chance to do something with this tree
before we look at it. */
STRIP_NOPS (t);
@@ -624,51 +732,11 @@ get_alias_set (tree t)
if (set != -1)
return set;
- /* Get the base object of the reference. */
- inner = t;
- while (handled_component_p (inner))
- {
- /* If there is a VIEW_CONVERT_EXPR in the chain we cannot use
- the type of any component references that wrap it to
- determine the alias-set. */
- if (TREE_CODE (inner) == VIEW_CONVERT_EXPR)
- t = TREE_OPERAND (inner, 0);
- inner = TREE_OPERAND (inner, 0);
- }
-
- /* Handle pointer dereferences here, they can override the
- alias-set. */
- if (INDIRECT_REF_P (inner))
- {
- set = get_deref_alias_set_1 (TREE_OPERAND (inner, 0));
- if (set != -1)
- return set;
- }
- else if (TREE_CODE (inner) == TARGET_MEM_REF)
- return get_deref_alias_set (TMR_OFFSET (inner));
- else if (TREE_CODE (inner) == MEM_REF)
- {
- set = get_deref_alias_set_1 (TREE_OPERAND (inner, 1));
- if (set != -1)
- return set;
- }
-
- /* If the innermost reference is a MEM_REF that has a
- conversion embedded treat it like a VIEW_CONVERT_EXPR above,
- using the memory access type for determining the alias-set. */
- if (TREE_CODE (inner) == MEM_REF
- && TYPE_MAIN_VARIANT (TREE_TYPE (inner))
- != TYPE_MAIN_VARIANT
- (TREE_TYPE (TREE_TYPE (TREE_OPERAND (inner, 1)))))
- return get_deref_alias_set (TREE_OPERAND (inner, 1));
-
- /* Otherwise, pick up the outermost object that we could have a pointer
- to, processing conversions as above. */
- while (component_uses_parent_alias_set (t))
- {
- t = TREE_OPERAND (t, 0);
- STRIP_NOPS (t);
- }
+ /* Get the alias pointer-type to use or the outermost object
+ that we could have a pointer to. */
+ tree ptype = reference_alias_ptr_type_1 (&t);
+ if (ptype != NULL)
+ return get_deref_alias_set (ptype);
/* If we've already determined the alias set for a decl, just return
it. This is necessary for C++ anonymous unions, whose component
@@ -2907,16 +2975,13 @@ init_alias_analysis (void)
/* Wipe the reg_seen array clean. */
bitmap_clear (reg_seen);
- /* Mark all hard registers which may contain an address.
- The stack, frame and argument pointers may contain an address.
- An argument register which can hold a Pmode value may contain
- an address even if it is not in BASE_REGS.
-
- The address expression is VOIDmode for an argument and
- Pmode for other registers. */
-
- memcpy (new_reg_base_value, static_reg_base_value,
- FIRST_PSEUDO_REGISTER * sizeof (rtx));
+ /* Initialize the alias information for this pass. */
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ if (static_reg_base_value[i])
+ {
+ new_reg_base_value[i] = static_reg_base_value[i];
+ bitmap_set_bit (reg_seen, i);
+ }
/* Walk the insns adding values to the new_reg_base_value array. */
for (i = 0; i < rpo_cnt; i++)
diff --git a/gcc/alias.h b/gcc/alias.h
index af739a8eef6..ff190eb094e 100644
--- a/gcc/alias.h
+++ b/gcc/alias.h
@@ -33,7 +33,7 @@ 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 bool component_uses_parent_alias_set (const_tree);
+extern tree component_uses_parent_alias_set_from (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);
@@ -41,6 +41,8 @@ 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);
+tree reference_alias_ptr_type (tree);
+bool alias_ptr_types_compatible_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
diff --git a/gcc/alloc-pool.c b/gcc/alloc-pool.c
index 65907544565..64535685de0 100644
--- a/gcc/alloc-pool.c
+++ b/gcc/alloc-pool.c
@@ -316,7 +316,7 @@ pool_alloc (alloc_pool pool)
/* Pull the first free element from the free list, and return it. */
header = pool->returned_free_list;
- VALGRIND_DISCARD (VALGRIND_MAKE_MEM_DEFINED (header, sizeof(*header)));
+ VALGRIND_DISCARD (VALGRIND_MAKE_MEM_DEFINED (header, sizeof (*header)));
pool->returned_free_list = header->next;
pool->elts_free--;
diff --git a/gcc/asan.c b/gcc/asan.c
index 1397173b3f6..950d332c0d5 100644
--- a/gcc/asan.c
+++ b/gcc/asan.c
@@ -22,9 +22,11 @@ along with GCC; see the file COPYING3. If not see
#include "config.h"
#include "system.h"
#include "coretypes.h"
+#include "tree.h"
#include "gimple.h"
#include "tree-iterator.h"
-#include "tree-ssa.h"
+#include "cgraph.h"
+#include "tree-ssanames.h"
#include "tree-pass.h"
#include "asan.h"
#include "gimple-pretty-print.h"
@@ -37,6 +39,7 @@ along with GCC; see the file COPYING3. If not see
#include "hash-table.h"
#include "alloc-pool.h"
#include "cfgloop.h"
+#include "gimple-builder.h"
/* AddressSanitizer finds out-of-bounds and use-after-free bugs
with <2x slowdown on average.
@@ -56,11 +59,13 @@ along with GCC; see the file COPYING3. If not see
if ((X & 7) + N - 1 > ShadowValue)
__asan_report_loadN(X);
Stores are instrumented similarly, but using __asan_report_storeN functions.
- A call too __asan_init() is inserted to the list of module CTORs.
+ A call too __asan_init_vN() is inserted to the list of module CTORs.
+ N is the version number of the AddressSanitizer API. The changes between the
+ API versions are listed in libsanitizer/asan/asan_interface_internal.h.
The run-time library redefines malloc (so that redzone are inserted around
the allocated memory) and free (so that reuse of free-ed memory is delayed),
- provides __asan_report* and __asan_init functions.
+ provides __asan_report* and __asan_init_vN functions.
Read more:
http://code.google.com/p/address-sanitizer/wiki/AddressSanitizerAlgorithm
@@ -122,9 +127,11 @@ along with GCC; see the file COPYING3. If not see
where '(...){n}' means the content inside the parenthesis occurs 'n'
times, with 'n' being the number of variables on the stack.
+
+ 3/ The following 8 bytes contain the PC of the current function which
+ will be used by the run-time library to print an error message.
- 3/ The following 16 bytes of the red zone have no particular
- format.
+ 4/ The following 8 bytes are reserved for internal use by the run-time.
The shadow memory for that stack layout is going to look like this:
@@ -202,6 +209,9 @@ along with GCC; see the file COPYING3. If not see
// Name of the global variable.
const void *__name;
+ // Name of the module where the global variable is declared.
+ const void *__module_name;
+
// This is always set to NULL for now.
uptr __has_dynamic_init;
}
@@ -705,7 +715,7 @@ get_mem_refs_of_builtin_call (const gimple call,
instrument_derefs. */
if (TREE_CODE (dest) == ADDR_EXPR)
dest = TREE_OPERAND (dest, 0);
- else if (TREE_CODE (dest) == SSA_NAME)
+ else if (TREE_CODE (dest) == SSA_NAME || TREE_CODE (dest) == INTEGER_CST)
dest = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (dest)),
dest, build_int_cst (TREE_TYPE (dest), 0));
else
@@ -895,7 +905,7 @@ asan_clear_shadow (rtx shadow_mem, HOST_WIDE_INT len)
gcc_assert ((len & 3) == 0);
top_label = gen_label_rtx ();
- addr = force_reg (Pmode, XEXP (shadow_mem, 0));
+ addr = copy_to_mode_reg (Pmode, XEXP (shadow_mem, 0));
shadow_mem = adjust_automodify_address (shadow_mem, SImode, addr, 0);
end = force_reg (Pmode, plus_constant (Pmode, addr, len));
emit_label (top_label);
@@ -908,7 +918,16 @@ asan_clear_shadow (rtx shadow_mem, HOST_WIDE_INT len)
emit_cmp_and_jump_insns (addr, end, LT, NULL_RTX, Pmode, true, top_label);
jump = get_last_insn ();
gcc_assert (JUMP_P (jump));
- add_reg_note (jump, REG_BR_PROB, GEN_INT (REG_BR_PROB_BASE * 80 / 100));
+ add_int_reg_note (jump, REG_BR_PROB, REG_BR_PROB_BASE * 80 / 100);
+}
+
+void
+asan_function_start (void)
+{
+ section *fnsec = function_section (current_function_decl);
+ switch_to_section (fnsec);
+ ASM_OUTPUT_DEBUG_LABEL (asm_out_file, "LASANPC",
+ current_function_funcdef_no);
}
/* Insert code to protect stack vars. The prologue sequence should be emitted
@@ -926,12 +945,13 @@ asan_emit_stack_protection (rtx base, HOST_WIDE_INT *offsets, tree *decls,
int length)
{
rtx shadow_base, shadow_mem, ret, mem;
+ char buf[30];
unsigned char shadow_bytes[4];
HOST_WIDE_INT base_offset = offsets[length - 1], offset, prev_offset;
HOST_WIDE_INT last_offset, last_size;
int l;
unsigned char cur_shadow_byte = ASAN_STACK_MAGIC_LEFT;
- tree str_cst;
+ tree str_cst, decl, id;
if (shadow_ptr_types[0] == NULL_TREE)
asan_init_shadow_ptr_types ();
@@ -939,11 +959,6 @@ asan_emit_stack_protection (rtx base, HOST_WIDE_INT *offsets, tree *decls,
/* First of all, prepare the description string. */
pretty_printer asan_pp;
- if (DECL_NAME (current_function_decl))
- pp_tree_identifier (&asan_pp, DECL_NAME (current_function_decl));
- else
- pp_string (&asan_pp, "<unknown>");
- pp_space (&asan_pp);
pp_decimal_int (&asan_pp, length / 2 - 1);
pp_space (&asan_pp);
for (l = length - 2; l; l -= 2)
@@ -973,6 +988,20 @@ asan_emit_stack_protection (rtx base, HOST_WIDE_INT *offsets, tree *decls,
emit_move_insn (mem, gen_int_mode (ASAN_STACK_FRAME_MAGIC, ptr_mode));
mem = adjust_address (mem, VOIDmode, GET_MODE_SIZE (ptr_mode));
emit_move_insn (mem, expand_normal (str_cst));
+ mem = adjust_address (mem, VOIDmode, GET_MODE_SIZE (ptr_mode));
+ ASM_GENERATE_INTERNAL_LABEL (buf, "LASANPC", current_function_funcdef_no);
+ id = get_identifier (buf);
+ decl = build_decl (DECL_SOURCE_LOCATION (current_function_decl),
+ VAR_DECL, id, char_type_node);
+ SET_DECL_ASSEMBLER_NAME (decl, id);
+ TREE_ADDRESSABLE (decl) = 1;
+ TREE_READONLY (decl) = 1;
+ DECL_ARTIFICIAL (decl) = 1;
+ DECL_IGNORED_P (decl) = 1;
+ TREE_STATIC (decl) = 1;
+ TREE_PUBLIC (decl) = 0;
+ TREE_USED (decl) = 1;
+ emit_move_insn (mem, expand_normal (build_fold_addr_expr (decl)));
shadow_base = expand_binop (Pmode, lshr_optab, base,
GEN_INT (ASAN_SHADOW_SHIFT),
NULL_RTX, 1, OPTAB_DIRECT);
@@ -1921,20 +1950,21 @@ transform_statements (void)
uptr __size;
uptr __size_with_redzone;
const void *__name;
+ const void *__module_name;
uptr __has_dynamic_init;
} type. */
static tree
asan_global_struct (void)
{
- static const char *field_names[5]
+ static const char *field_names[6]
= { "__beg", "__size", "__size_with_redzone",
- "__name", "__has_dynamic_init" };
- tree fields[5], ret;
+ "__name", "__module_name", "__has_dynamic_init" };
+ tree fields[6], ret;
int i;
ret = make_node (RECORD_TYPE);
- for (i = 0; i < 5; i++)
+ for (i = 0; i < 6; i++)
{
fields[i]
= build_decl (UNKNOWN_LOCATION, FIELD_DECL,
@@ -1959,21 +1989,20 @@ asan_add_global (tree decl, tree type, vec<constructor_elt, va_gc> *v)
{
tree init, uptr = TREE_TYPE (DECL_CHAIN (TYPE_FIELDS (type)));
unsigned HOST_WIDE_INT size;
- tree str_cst, refdecl = decl;
+ tree str_cst, module_name_cst, refdecl = decl;
vec<constructor_elt, va_gc> *vinner = NULL;
- pretty_printer asan_pp;
+ pretty_printer asan_pp, module_name_pp;
if (DECL_NAME (decl))
pp_tree_identifier (&asan_pp, DECL_NAME (decl));
else
pp_string (&asan_pp, "<unknown>");
- pp_space (&asan_pp);
- pp_left_paren (&asan_pp);
- pp_string (&asan_pp, main_input_filename);
- pp_right_paren (&asan_pp);
str_cst = asan_pp_string (&asan_pp);
+ pp_string (&module_name_pp, main_input_filename);
+ module_name_cst = asan_pp_string (&module_name_pp);
+
if (asan_needs_local_alias (decl))
{
char buf[20];
@@ -2001,6 +2030,8 @@ asan_add_global (tree decl, tree type, vec<constructor_elt, va_gc> *v)
CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE, build_int_cst (uptr, size));
CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE,
fold_convert (const_ptr_type_node, str_cst));
+ CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE,
+ fold_convert (const_ptr_type_node, module_name_cst));
CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE, build_int_cst (uptr, 0));
init = build_constructor (type, vinner);
CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, init);
@@ -2018,6 +2049,9 @@ initialize_sanitizer_builtins (void)
tree BT_FN_VOID = build_function_type_list (void_type_node, NULL_TREE);
tree BT_FN_VOID_PTR
= build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
+ tree BT_FN_VOID_PTR_PTR
+ = build_function_type_list (void_type_node, ptr_type_node,
+ ptr_type_node, NULL_TREE);
tree BT_FN_VOID_PTR_PTR_PTR
= build_function_type_list (void_type_node, ptr_type_node,
ptr_type_node, ptr_type_node, NULL_TREE);
@@ -2152,7 +2186,7 @@ add_string_csts (void **slot, void *data)
static GTY(()) tree asan_ctor_statements;
/* Module-level instrumentation.
- - Insert __asan_init() into the list of CTORs.
+ - Insert __asan_init_vN() into the list of CTORs.
- TODO: insert redzones around globals.
*/
@@ -2172,8 +2206,8 @@ asan_finish_file (void)
tree fn = builtin_decl_implicit (BUILT_IN_ASAN_INIT);
append_to_statement_list (build_call_expr (fn, 0), &asan_ctor_statements);
FOR_EACH_DEFINED_VARIABLE (vnode)
- if (TREE_ASM_WRITTEN (vnode->symbol.decl)
- && asan_protect_global (vnode->symbol.decl))
+ if (TREE_ASM_WRITTEN (vnode->decl)
+ && asan_protect_global (vnode->decl))
++gcount;
htab_t const_desc_htab = constant_pool_htab ();
htab_traverse (const_desc_htab, count_string_csts, &gcount);
@@ -2194,9 +2228,9 @@ asan_finish_file (void)
DECL_IGNORED_P (var) = 1;
vec_alloc (v, gcount);
FOR_EACH_DEFINED_VARIABLE (vnode)
- if (TREE_ASM_WRITTEN (vnode->symbol.decl)
- && asan_protect_global (vnode->symbol.decl))
- asan_add_global (vnode->symbol.decl, TREE_TYPE (type), v);
+ if (TREE_ASM_WRITTEN (vnode->decl)
+ && asan_protect_global (vnode->decl))
+ asan_add_global (vnode->decl, TREE_TYPE (type), v);
struct asan_add_string_csts_data aascd;
aascd.type = TREE_TYPE (type);
aascd.v = v;
@@ -2267,12 +2301,12 @@ const pass_data pass_data_asan =
class pass_asan : public gimple_opt_pass
{
public:
- pass_asan(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_asan, ctxt)
+ pass_asan (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_asan, ctxt)
{}
/* opt_pass methods: */
- opt_pass * clone () { return new pass_asan (ctxt_); }
+ opt_pass * clone () { return new pass_asan (m_ctxt); }
bool gate () { return gate_asan (); }
unsigned int execute () { return asan_instrument (); }
@@ -2313,8 +2347,8 @@ const pass_data pass_data_asan_O0 =
class pass_asan_O0 : public gimple_opt_pass
{
public:
- pass_asan_O0(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_asan_O0, ctxt)
+ pass_asan_O0 (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_asan_O0, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/asan.h b/gcc/asan.h
index 62dbe984967..e56468424c9 100644
--- a/gcc/asan.h
+++ b/gcc/asan.h
@@ -21,6 +21,7 @@ along with GCC; see the file COPYING3. If not see
#ifndef TREE_ASAN
#define TREE_ASAN
+extern void asan_function_start (void);
extern void asan_finish_file (void);
extern rtx asan_emit_stack_protection (rtx, HOST_WIDE_INT *, tree *, int);
extern bool asan_protect_global (tree);
diff --git a/gcc/attribs.c b/gcc/attribs.c
index 164385b2b3c..296bcd6eb74 100644
--- a/gcc/attribs.c
+++ b/gcc/attribs.c
@@ -297,7 +297,7 @@ register_scoped_attribute (const struct attribute_spec *attr,
/* Return the spec for the scoped attribute with namespace NS and
name NAME. */
-const struct attribute_spec *
+static const struct attribute_spec *
lookup_scoped_attribute_spec (const_tree ns, const_tree name)
{
struct substring attr;
@@ -334,7 +334,23 @@ lookup_attribute_spec (const_tree name)
return lookup_scoped_attribute_spec (ns, name);
}
-
+
+/* Return the namespace of the attribute ATTR. This accessor works on
+ GNU and C++11 (scoped) attributes. On GNU attributes,
+ it returns an identifier tree for the string "gnu".
+
+ Please read the comments of cxx11_attribute_p to understand the
+ format of attributes. */
+
+static tree
+get_attribute_namespace (const_tree attr)
+{
+ if (cxx11_attribute_p (attr))
+ return TREE_PURPOSE (TREE_PURPOSE (attr));
+ return get_identifier ("gnu");
+}
+
+
/* 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
@@ -659,21 +675,6 @@ get_attribute_name (const_tree attr)
return TREE_PURPOSE (attr);
}
-/* Return the namespace of the attribute ATTR. This accessor works on
- GNU and C++11 (scoped) attributes. On GNU attributes,
- it returns an identifier tree for the string "gnu".
-
- Please read the comments of cxx11_attribute_p to understand the
- format of attributes. */
-
-tree
-get_attribute_namespace (const_tree attr)
-{
- if (cxx11_attribute_p (attr))
- return TREE_PURPOSE (TREE_PURPOSE (attr));
- return get_identifier ("gnu");
-}
-
/* Subroutine of set_method_tm_attributes. Apply TM attribute ATTR
to the method FNDECL. */
diff --git a/gcc/auto-inc-dec.c b/gcc/auto-inc-dec.c
index 0d92b1d79b5..6006b70c085 100644
--- a/gcc/auto-inc-dec.c
+++ b/gcc/auto-inc-dec.c
@@ -1452,9 +1452,9 @@ merge_in_block (int max_reg, basic_block bb)
{
/* In this case, we must clear these vectors since the trick of
testing if the stale insn in the block will not work. */
- memset (reg_next_use, 0, max_reg * sizeof(rtx));
- memset (reg_next_inc_use, 0, max_reg * sizeof(rtx));
- memset (reg_next_def, 0, max_reg * sizeof(rtx));
+ memset (reg_next_use, 0, max_reg * sizeof (rtx));
+ memset (reg_next_inc_use, 0, max_reg * sizeof (rtx));
+ memset (reg_next_def, 0, max_reg * sizeof (rtx));
df_recompute_luids (bb);
merge_in_block (max_reg, bb);
}
@@ -1526,8 +1526,8 @@ const pass_data pass_data_inc_dec =
class pass_inc_dec : public rtl_opt_pass
{
public:
- pass_inc_dec(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_inc_dec, ctxt)
+ pass_inc_dec (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_inc_dec, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/basic-block.h b/gcc/basic-block.h
index ad04d4de83e..9c28f14afa4 100644
--- a/gcc/basic-block.h
+++ b/gcc/basic-block.h
@@ -24,13 +24,11 @@ along with GCC; see the file COPYING3. If not see
#include "vec.h"
#include "function.h"
-/* Type we use to hold basic block counters. Should be at least
+/* Use gcov_type to hold basic block counters. Should be at least
64bit. Although a counter cannot be negative, we use a signed
type, because erroneous negative counts can be generated when the
flow graph is manipulated by various optimizations. A signed type
makes those easy to detect. */
-typedef HOST_WIDEST_INT gcov_type;
-typedef unsigned HOST_WIDEST_INT gcov_type_unsigned;
/* Control flow edge information. */
struct GTY((user)) edge_def {
@@ -214,8 +212,8 @@ struct GTY((chain_next ("%h.next_bb"), chain_prev ("%h.prev_bb"))) basic_block_d
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)];
+ [(int) sizeof (struct rtl_bb_info)
+ - (int) sizeof (struct gimple_bb_info)];
#define BB_FREQ_MAX 10000
@@ -324,9 +322,9 @@ struct GTY(()) control_flow_graph {
#define profile_status_for_function(FN) ((FN)->cfg->x_profile_status)
#define BASIC_BLOCK_FOR_FUNCTION(FN,N) \
- ((*basic_block_info_for_function(FN))[(N)])
+ ((*basic_block_info_for_function (FN))[(N)])
#define SET_BASIC_BLOCK_FOR_FUNCTION(FN,N,BB) \
- ((*basic_block_info_for_function(FN))[(N)] = (BB))
+ ((*basic_block_info_for_function (FN))[(N)] = (BB))
/* Defines for textual backward source compatibility. */
#define ENTRY_BLOCK_PTR (cfun->cfg->x_entry_block_ptr)
@@ -353,7 +351,7 @@ struct GTY(()) control_flow_graph {
#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)
-#define FOR_EACH_BB_REVERSE(BB) FOR_EACH_BB_REVERSE_FN(BB, cfun)
+#define FOR_EACH_BB_REVERSE(BB) FOR_EACH_BB_REVERSE_FN (BB, cfun)
/* For iterating over insns in basic block. */
#define FOR_BB_INSNS(BB, INSN) \
@@ -479,7 +477,7 @@ private:
void clear_control_dependence_bitmap (basic_block);
void find_control_dependence (int);
vec<bitmap> control_dependence_map;
- edge_list *el;
+ edge_list *m_el;
};
/* The base value for branch probability notes and edge probabilities. */
@@ -797,12 +795,15 @@ extern void connect_infinite_loops_to_exit (void);
extern int post_order_compute (int *, bool, bool);
extern basic_block dfs_find_deadend (basic_block);
extern int inverted_post_order_compute (int *);
+extern int pre_and_rev_post_order_compute_fn (struct function *,
+ int *, int *, bool);
extern int pre_and_rev_post_order_compute (int *, int *, bool);
extern int dfs_enumerate_from (basic_block, int,
bool (*)(const_basic_block, const void *),
basic_block *, int, const void *);
extern void compute_dominance_frontiers (struct bitmap_head_def *);
extern bitmap compute_idf (bitmap, struct bitmap_head_def *);
+extern basic_block * single_pred_before_succ_order (void);
/* In cfgrtl.c */
extern rtx block_label (basic_block);
@@ -896,6 +897,14 @@ struct loop *get_loop_copy (struct loop *);
#include "cfghooks.h"
+/* 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)
@@ -951,7 +960,7 @@ extern void default_rtl_profile (void);
/* In profile.c. */
typedef struct gcov_working_set_info gcov_working_set_t;
-extern gcov_working_set_t *find_working_set(unsigned pct_times_10);
+extern gcov_working_set_t *find_working_set (unsigned pct_times_10);
/* Check tha probability is sane. */
diff --git a/gcc/bb-reorder.c b/gcc/bb-reorder.c
index 6b034aba5c9..8e2348f476c 100644
--- a/gcc/bb-reorder.c
+++ b/gcc/bb-reorder.c
@@ -82,6 +82,7 @@
#include "system.h"
#include "coretypes.h"
#include "tm.h"
+#include "tree.h"
#include "rtl.h"
#include "regs.h"
#include "flags.h"
@@ -1564,8 +1565,24 @@ find_rarely_executed_basic_blocks_and_crossing_edges (void)
/* Mark which partition (hot/cold) each basic block belongs in. */
FOR_EACH_BB (bb)
{
+ bool cold_bb = false;
+
if (probably_never_executed_bb_p (cfun, bb))
{
+ /* Handle profile insanities created by upstream optimizations
+ by also checking the incoming edge weights. If there is a non-cold
+ incoming edge, conservatively prevent this block from being split
+ into the cold section. */
+ cold_bb = true;
+ FOR_EACH_EDGE (e, ei, bb->preds)
+ if (!probably_never_executed_edge_p (cfun, e))
+ {
+ cold_bb = false;
+ break;
+ }
+ }
+ if (cold_bb)
+ {
BB_SET_PARTITION (bb, BB_COLD_PARTITION);
cold_bb_count++;
}
@@ -2329,8 +2346,8 @@ const pass_data pass_data_reorder_blocks =
class pass_reorder_blocks : public rtl_opt_pass
{
public:
- pass_reorder_blocks(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_reorder_blocks, ctxt)
+ pass_reorder_blocks (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_reorder_blocks, ctxt)
{}
/* opt_pass methods: */
@@ -2495,8 +2512,8 @@ const pass_data pass_data_duplicate_computed_gotos =
class pass_duplicate_computed_gotos : public rtl_opt_pass
{
public:
- pass_duplicate_computed_gotos(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_duplicate_computed_gotos, ctxt)
+ pass_duplicate_computed_gotos (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_duplicate_computed_gotos, ctxt)
{}
/* opt_pass methods: */
@@ -2719,8 +2736,8 @@ const pass_data pass_data_partition_blocks =
class pass_partition_blocks : public rtl_opt_pass
{
public:
- pass_partition_blocks(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_partition_blocks, ctxt)
+ pass_partition_blocks (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_partition_blocks, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/bitmap.c b/gcc/bitmap.c
index 2c5d228fdd1..ecaca42d00e 100644
--- a/gcc/bitmap.c
+++ b/gcc/bitmap.c
@@ -811,7 +811,7 @@ bitmap_first_set_bit (const_bitmap a)
bit_no += ix * BITMAP_WORD_BITS;
#if GCC_VERSION >= 3004
- gcc_assert (sizeof(long) == sizeof (word));
+ gcc_assert (sizeof (long) == sizeof (word));
bit_no += __builtin_ctzl (word);
#else
/* Binary search for the first set bit. */
@@ -863,7 +863,7 @@ bitmap_last_set_bit (const_bitmap a)
found_bit:
bit_no += ix * BITMAP_WORD_BITS;
#if GCC_VERSION >= 3004
- gcc_assert (sizeof(long) == sizeof (word));
+ gcc_assert (sizeof (long) == sizeof (word));
bit_no += BITMAP_WORD_BITS - __builtin_clzl (word) - 1;
#else
/* Hopefully this is a twos-complement host... */
diff --git a/gcc/bitmap.h b/gcc/bitmap.h
index ada414d8836..b3cb5da98e9 100644
--- a/gcc/bitmap.h
+++ b/gcc/bitmap.h
@@ -300,7 +300,7 @@ 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);
+extern hashval_t bitmap_hash (const_bitmap);
/* Allocate a bitmap from a bit obstack. */
#define BITMAP_ALLOC(OBSTACK) bitmap_obstack_alloc (OBSTACK)
diff --git a/gcc/bt-load.c b/gcc/bt-load.c
index b53435680ec..5384d01d525 100644
--- a/gcc/bt-load.c
+++ b/gcc/bt-load.c
@@ -605,7 +605,7 @@ compute_defs_uses_and_gen (fibheap_t all_btr_defs, btr_def *def_array,
}
if (dump_file)
- dump_btrs_live(i);
+ dump_btrs_live (i);
}
}
@@ -691,13 +691,13 @@ link_btr_uses (btr_def *def_array, btr_user *use_array, sbitmap *bb_out,
for this one. */
bitmap_and_compl (reaching_defs, reaching_defs,
btr_defset[def->btr - first_btr]);
- bitmap_set_bit(reaching_defs, insn_uid);
+ bitmap_set_bit (reaching_defs, insn_uid);
}
if (user != NULL)
{
/* Find all the reaching defs for this use. */
- sbitmap reaching_defs_of_reg = sbitmap_alloc(max_uid);
+ sbitmap reaching_defs_of_reg = sbitmap_alloc (max_uid);
unsigned int uid = 0;
sbitmap_iterator sbi;
@@ -1363,7 +1363,7 @@ migrate_btr_def (btr_def def, int min_cost)
if (btr != -1)
{
move_btr_def (attempt, btr, def, live_range, &btrs_live_in_range);
- bitmap_copy(live_range, def->live_range);
+ bitmap_copy (live_range, def->live_range);
btr_used_near_def = 0;
def_moved = 1;
def_basic_block_freq = basic_block_freq (def->bb);
@@ -1406,11 +1406,11 @@ migrate_btr_defs (enum reg_class btr_class, int allow_callee_save)
for (i = NUM_FIXED_BLOCKS; i < last_basic_block; i++)
{
basic_block bb = BASIC_BLOCK (i);
- fprintf(dump_file,
- "Basic block %d: count = " HOST_WIDEST_INT_PRINT_DEC
- " loop-depth = %d idom = %d\n",
- i, (HOST_WIDEST_INT) bb->count, bb_loop_depth (bb),
- get_immediate_dominator (CDI_DOMINATORS, bb)->index);
+ fprintf (dump_file,
+ "Basic block %d: count = " HOST_WIDEST_INT_PRINT_DEC
+ " loop-depth = %d idom = %d\n",
+ i, (HOST_WIDEST_INT) bb->count, bb_loop_depth (bb),
+ get_immediate_dominator (CDI_DOMINATORS, bb)->index);
}
}
@@ -1524,8 +1524,8 @@ const pass_data pass_data_branch_target_load_optimize1 =
class pass_branch_target_load_optimize1 : public rtl_opt_pass
{
public:
- pass_branch_target_load_optimize1(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_branch_target_load_optimize1, ctxt)
+ pass_branch_target_load_optimize1 (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_branch_target_load_optimize1, ctxt)
{}
/* opt_pass methods: */
@@ -1593,8 +1593,8 @@ const pass_data pass_data_branch_target_load_optimize2 =
class pass_branch_target_load_optimize2 : public rtl_opt_pass
{
public:
- pass_branch_target_load_optimize2(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_branch_target_load_optimize2, ctxt)
+ pass_branch_target_load_optimize2 (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_branch_target_load_optimize2, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/builtin-types.def b/gcc/builtin-types.def
index 2634eccabab..1f9ae4e2317 100644
--- a/gcc/builtin-types.def
+++ b/gcc/builtin-types.def
@@ -34,6 +34,8 @@ along with GCC; see the file COPYING3. If not see
DEF_FUNCTION_TYPE_5 (ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5)
DEF_FUNCTION_TYPE_6 (ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6)
DEF_FUNCTION_TYPE_7 (ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7)
+ DEF_FUNCTION_TYPE_8 (ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7,
+ ARG8)
These macros describe function types. ENUM is as above. The
RETURN type is one of the enumerals already defined. ARG1, ARG2,
@@ -224,12 +226,16 @@ 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_ULONG_ULONG, BT_ULONG, BT_ULONG)
DEF_FUNCTION_TYPE_1 (BT_FN_ULONGLONG_ULONGLONG, BT_ULONGLONG, BT_ULONGLONG)
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_BOOL_INT, BT_BOOL, BT_INT)
+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_POINTER_TYPE (BT_PTR_FN_VOID_PTR, BT_FN_VOID_PTR)
@@ -341,6 +347,12 @@ 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_VOID_UINT_UINT, BT_VOID, BT_UINT, BT_UINT)
+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_POINTER_TYPE (BT_PTR_FN_VOID_PTR_PTR, BT_FN_VOID_PTR_PTR)
@@ -411,8 +423,6 @@ 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_VOID_OMPFN_PTR_UINT, BT_VOID, BT_PTR_FN_VOID_PTR,
- BT_PTR, BT_UINT)
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)
@@ -425,6 +435,7 @@ DEF_FUNCTION_TYPE_3 (BT_FN_VOID_VPTR_I2_INT, BT_VOID, BT_VOLATILE_PTR, BT_I2, BT
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_PTR_CONST_PTR_CONST_PTR_SIZE, BT_PTR, BT_CONST_PTR, BT_CONST_PTR, BT_SIZE)
DEF_FUNCTION_TYPE_4 (BT_FN_SIZE_CONST_PTR_SIZE_SIZE_FILEPTR,
BT_SIZE, BT_CONST_PTR, BT_SIZE, BT_SIZE, BT_FILEPTR)
@@ -467,6 +478,9 @@ 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_OMPFN_PTR_UINT_UINT_UINT,
+ BT_VOID, BT_PTR_FN_VOID_PTR, BT_PTR, BT_UINT, BT_UINT,
+ BT_UINT)
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,
@@ -474,9 +488,6 @@ DEF_FUNCTION_TYPE_6 (BT_FN_INT_STRING_SIZE_INT_SIZE_CONST_STRING_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_VOID_OMPFN_PTR_UINT_LONG_LONG_LONG,
- BT_VOID, BT_PTR_FN_VOID_PTR, BT_PTR, BT_UINT,
- BT_LONG, BT_LONG, BT_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)
@@ -497,19 +508,27 @@ DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_VPTR_PTR_I16_BOOL_INT_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_6 (BT_FN_VOID_INT_PTR_SIZE_PTR_PTR_PTR,
+ BT_VOID, BT_INT, BT_PTR, BT_SIZE, BT_PTR, BT_PTR, BT_PTR)
-
-DEF_FUNCTION_TYPE_7 (BT_FN_VOID_OMPFN_PTR_UINT_LONG_LONG_LONG_LONG,
+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_LONG)
-DEF_FUNCTION_TYPE_7 (BT_FN_VOID_OMPFN_PTR_OMPCPYFN_LONG_LONG_BOOL_UINT,
- BT_VOID, BT_PTR_FN_VOID_PTR, BT_PTR,
- BT_PTR_FN_VOID_PTR_PTR, BT_LONG, BT_LONG,
- BT_BOOL, 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_OMPFN_PTR_SIZE_PTR_PTR_PTR,
+ BT_VOID, BT_INT, BT_PTR_FN_VOID_PTR, BT_PTR, BT_SIZE,
+ BT_PTR, BT_PTR, 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_VOID_OMPFN_PTR_OMPCPYFN_LONG_LONG_BOOL_UINT_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)
DEF_FUNCTION_TYPE_VAR_0 (BT_FN_VOID_VAR, BT_VOID)
DEF_FUNCTION_TYPE_VAR_0 (BT_FN_INT_VAR, BT_INT)
diff --git a/gcc/builtins.c b/gcc/builtins.c
index d19ca68baba..7a04664c909 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -43,17 +43,15 @@ along with GCC; see the file COPYING3. If not see
#include "target.h"
#include "langhooks.h"
#include "basic-block.h"
-#include "tree-mudflap.h"
-#include "tree-ssa.h"
+#include "tree-ssanames.h"
+#include "tree-dfa.h"
#include "value-prof.h"
#include "diagnostic-core.h"
#include "builtins.h"
#include "ubsan.h"
+#include "cilk.h"
-#ifndef PAD_VARARGS_DOWN
-#define PAD_VARARGS_DOWN BYTES_BIG_ENDIAN
-#endif
static tree do_mpc_arg1 (tree, tree, int (*)(mpc_ptr, mpc_srcptr, mpc_rnd_t));
struct target_builtins default_target_builtins;
@@ -238,6 +236,10 @@ is_builtin_name (const char *name)
return true;
if (strncmp (name, "__atomic_", 9) == 0)
return true;
+ if (flag_enable_cilkplus
+ && (!strcmp (name, "__cilkrts_detach")
+ || !strcmp (name, "__cilkrts_pop_frame")))
+ return true;
return false;
}
@@ -312,7 +314,7 @@ get_object_alignment_2 (tree exp, unsigned int *alignp,
tree offset;
enum machine_mode mode;
int unsignedp, volatilep;
- unsigned int inner, align = BITS_PER_UNIT;
+ unsigned int align = BITS_PER_UNIT;
bool known_alignment = false;
/* Get the innermost object and the constant (bitpos) and possibly
@@ -421,50 +423,16 @@ get_object_alignment_2 (tree exp, unsigned int *alignp,
/* If there is a non-constant offset part extract the maximum
alignment that can prevail. */
- inner = ~0U;
- while (offset)
+ if (offset)
{
- tree next_offset;
-
- if (TREE_CODE (offset) == PLUS_EXPR)
- {
- next_offset = TREE_OPERAND (offset, 0);
- offset = TREE_OPERAND (offset, 1);
- }
- else
- next_offset = NULL;
- if (host_integerp (offset, 1))
- {
- /* Any overflow in calculating offset_bits won't change
- the alignment. */
- unsigned offset_bits
- = ((unsigned) tree_low_cst (offset, 1) * BITS_PER_UNIT);
-
- if (offset_bits)
- inner = MIN (inner, (offset_bits & -offset_bits));
- }
- else if (TREE_CODE (offset) == MULT_EXPR
- && host_integerp (TREE_OPERAND (offset, 1), 1))
- {
- /* Any overflow in calculating offset_factor won't change
- the alignment. */
- unsigned offset_factor
- = ((unsigned) tree_low_cst (TREE_OPERAND (offset, 1), 1)
- * BITS_PER_UNIT);
-
- if (offset_factor)
- inner = MIN (inner, (offset_factor & -offset_factor));
- }
- else
+ int trailing_zeros = tree_ctz (offset);
+ if (trailing_zeros < HOST_BITS_PER_INT)
{
- inner = MIN (inner, BITS_PER_UNIT);
- break;
+ unsigned int inner = (1U << trailing_zeros) * BITS_PER_UNIT;
+ if (inner)
+ align = MIN (align, inner);
}
- offset = next_offset;
}
- /* Alignment is innermost object alignment adjusted by the constant
- and non-constant offset parts. */
- align = MIN (align, inner);
*alignp = align;
*bitposp = bitpos & (*alignp - 1);
@@ -1082,6 +1050,63 @@ expand_builtin_longjmp (rtx buf_addr, rtx value)
}
}
+static inline bool
+more_const_call_expr_args_p (const const_call_expr_arg_iterator *iter)
+{
+ return (iter->i < iter->n);
+}
+
+/* This function validates the types of a function call argument list
+ against a specified list of tree_codes. If the last specifier is a 0,
+ that represents an ellipses, otherwise the last specifier must be a
+ VOID_TYPE. */
+
+static bool
+validate_arglist (const_tree callexpr, ...)
+{
+ enum tree_code code;
+ bool res = 0;
+ va_list ap;
+ const_call_expr_arg_iterator iter;
+ const_tree arg;
+
+ va_start (ap, callexpr);
+ init_const_call_expr_arg_iterator (callexpr, &iter);
+
+ do
+ {
+ code = (enum tree_code) va_arg (ap, int);
+ switch (code)
+ {
+ case 0:
+ /* This signifies an ellipses, any further arguments are all ok. */
+ res = true;
+ goto end;
+ case VOID_TYPE:
+ /* This signifies an endlink, if no arguments remain, return
+ true, otherwise return false. */
+ res = !more_const_call_expr_args_p (&iter);
+ goto end;
+ default:
+ /* If no parameters remain or the parameter's code does not
+ match the specified code, return false. Otherwise continue
+ checking any remaining arguments. */
+ arg = next_const_call_expr_arg (&iter);
+ if (!validate_arg (arg, code))
+ goto end;
+ break;
+ }
+ }
+ while (1);
+
+ /* We need gotos here since we can only have one VA_CLOSE in a
+ function. */
+ end: ;
+ va_end (ap);
+
+ return res;
+}
+
/* Expand a call to __builtin_nonlocal_goto. We're passed the target label
and the address of the save area. */
@@ -1703,7 +1728,7 @@ expand_builtin_apply (rtx function, rtx arguments, rtx argsize)
else
#endif
emit_stack_restore (SAVE_BLOCK, old_stack_level);
- fixup_args_size_notes (call_insn, get_last_insn(), 0);
+ fixup_args_size_notes (call_insn, get_last_insn (), 0);
OK_DEFER_POP;
@@ -4172,7 +4197,7 @@ std_canonical_va_list_type (tree type)
if (INDIRECT_REF_P (type))
type = TREE_TYPE (type);
- else if (POINTER_TYPE_P (type) && POINTER_TYPE_P (TREE_TYPE(type)))
+ else if (POINTER_TYPE_P (type) && POINTER_TYPE_P (TREE_TYPE (type)))
type = TREE_TYPE (type);
wtype = va_list_type_node;
htype = type;
@@ -4237,219 +4262,6 @@ expand_builtin_va_start (tree exp)
return const0_rtx;
}
-/* The "standard" implementation of va_arg: read the value from the
- current (padded) address and increment by the (padded) size. */
-
-tree
-std_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
- gimple_seq *post_p)
-{
- tree addr, t, type_size, rounded_size, valist_tmp;
- unsigned HOST_WIDE_INT align, boundary;
- bool indirect;
-
-#ifdef ARGS_GROW_DOWNWARD
- /* All of the alignment and movement below is for args-grow-up machines.
- As of 2004, there are only 3 ARGS_GROW_DOWNWARD targets, and they all
- implement their own specialized gimplify_va_arg_expr routines. */
- gcc_unreachable ();
-#endif
-
- indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false);
- if (indirect)
- type = build_pointer_type (type);
-
- align = PARM_BOUNDARY / BITS_PER_UNIT;
- boundary = targetm.calls.function_arg_boundary (TYPE_MODE (type), type);
-
- /* When we align parameter on stack for caller, if the parameter
- alignment is beyond MAX_SUPPORTED_STACK_ALIGNMENT, it will be
- aligned at MAX_SUPPORTED_STACK_ALIGNMENT. We will match callee
- here with caller. */
- if (boundary > MAX_SUPPORTED_STACK_ALIGNMENT)
- boundary = MAX_SUPPORTED_STACK_ALIGNMENT;
-
- boundary /= BITS_PER_UNIT;
-
- /* Hoist the valist value into a temporary for the moment. */
- valist_tmp = get_initialized_tmp_var (valist, pre_p, NULL);
-
- /* va_list pointer is aligned to PARM_BOUNDARY. If argument actually
- requires greater alignment, we must perform dynamic alignment. */
- if (boundary > align
- && !integer_zerop (TYPE_SIZE (type)))
- {
- t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
- fold_build_pointer_plus_hwi (valist_tmp, boundary - 1));
- gimplify_and_add (t, pre_p);
-
- t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
- fold_build2 (BIT_AND_EXPR, TREE_TYPE (valist),
- valist_tmp,
- build_int_cst (TREE_TYPE (valist), -boundary)));
- gimplify_and_add (t, pre_p);
- }
- else
- boundary = align;
-
- /* If the actual alignment is less than the alignment of the type,
- adjust the type accordingly so that we don't assume strict alignment
- when dereferencing the pointer. */
- boundary *= BITS_PER_UNIT;
- if (boundary < TYPE_ALIGN (type))
- {
- type = build_variant_type_copy (type);
- TYPE_ALIGN (type) = boundary;
- }
-
- /* Compute the rounded size of the type. */
- type_size = size_in_bytes (type);
- rounded_size = round_up (type_size, align);
-
- /* Reduce rounded_size so it's sharable with the postqueue. */
- gimplify_expr (&rounded_size, pre_p, post_p, is_gimple_val, fb_rvalue);
-
- /* Get AP. */
- addr = valist_tmp;
- if (PAD_VARARGS_DOWN && !integer_zerop (rounded_size))
- {
- /* Small args are padded downward. */
- t = fold_build2_loc (input_location, GT_EXPR, sizetype,
- rounded_size, size_int (align));
- t = fold_build3 (COND_EXPR, sizetype, t, size_zero_node,
- size_binop (MINUS_EXPR, rounded_size, type_size));
- addr = fold_build_pointer_plus (addr, t);
- }
-
- /* Compute new value for AP. */
- t = fold_build_pointer_plus (valist_tmp, rounded_size);
- t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
- gimplify_and_add (t, pre_p);
-
- addr = fold_convert (build_pointer_type (type), addr);
-
- if (indirect)
- addr = build_va_arg_indirect_ref (addr);
-
- return build_va_arg_indirect_ref (addr);
-}
-
-/* Build an indirect-ref expression over the given TREE, which represents a
- piece of a va_arg() expansion. */
-tree
-build_va_arg_indirect_ref (tree addr)
-{
- addr = build_simple_mem_ref_loc (EXPR_LOCATION (addr), addr);
-
- if (flag_mudflap) /* Don't instrument va_arg INDIRECT_REF. */
- mf_mark (addr);
-
- return addr;
-}
-
-/* Return a dummy expression of type TYPE in order to keep going after an
- error. */
-
-static tree
-dummy_object (tree type)
-{
- tree t = build_int_cst (build_pointer_type (type), 0);
- return build2 (MEM_REF, type, t, t);
-}
-
-/* Gimplify __builtin_va_arg, aka VA_ARG_EXPR, which is not really a
- builtin function, but a very special sort of operator. */
-
-enum gimplify_status
-gimplify_va_arg_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
-{
- tree promoted_type, have_va_type;
- tree valist = TREE_OPERAND (*expr_p, 0);
- tree type = TREE_TYPE (*expr_p);
- tree t;
- location_t loc = EXPR_LOCATION (*expr_p);
-
- /* Verify that valist is of the proper type. */
- have_va_type = TREE_TYPE (valist);
- if (have_va_type == error_mark_node)
- return GS_ERROR;
- have_va_type = targetm.canonical_va_list_type (have_va_type);
-
- if (have_va_type == NULL_TREE)
- {
- error_at (loc, "first argument to %<va_arg%> not of type %<va_list%>");
- return GS_ERROR;
- }
-
- /* Generate a diagnostic for requesting data of a type that cannot
- be passed through `...' due to type promotion at the call site. */
- if ((promoted_type = lang_hooks.types.type_promotes_to (type))
- != type)
- {
- static bool gave_help;
- bool warned;
-
- /* Unfortunately, this is merely undefined, rather than a constraint
- violation, so we cannot make this an error. If this call is never
- executed, the program is still strictly conforming. */
- warned = warning_at (loc, 0,
- "%qT is promoted to %qT when passed through %<...%>",
- type, promoted_type);
- if (!gave_help && warned)
- {
- gave_help = true;
- inform (loc, "(so you should pass %qT not %qT to %<va_arg%>)",
- promoted_type, type);
- }
-
- /* We can, however, treat "undefined" any way we please.
- Call abort to encourage the user to fix the program. */
- if (warned)
- inform (loc, "if this code is reached, the program will abort");
- /* Before the abort, allow the evaluation of the va_list
- expression to exit or longjmp. */
- gimplify_and_add (valist, pre_p);
- t = build_call_expr_loc (loc,
- builtin_decl_implicit (BUILT_IN_TRAP), 0);
- gimplify_and_add (t, pre_p);
-
- /* This is dead code, but go ahead and finish so that the
- mode of the result comes out right. */
- *expr_p = dummy_object (type);
- return GS_ALL_DONE;
- }
- else
- {
- /* Make it easier for the backends by protecting the valist argument
- from multiple evaluations. */
- if (TREE_CODE (have_va_type) == ARRAY_TYPE)
- {
- /* For this case, the backends will be expecting a pointer to
- TREE_TYPE (abi), but it's possible we've
- actually been given an array (an actual TARGET_FN_ABI_VA_LIST).
- So fix it. */
- if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
- {
- tree p1 = build_pointer_type (TREE_TYPE (have_va_type));
- valist = fold_convert_loc (loc, p1,
- build_fold_addr_expr_loc (loc, valist));
- }
-
- gimplify_expr (&valist, pre_p, post_p, is_gimple_val, fb_rvalue);
- }
- else
- gimplify_expr (&valist, pre_p, post_p, is_gimple_min_lval, fb_lvalue);
-
- if (!targetm.gimplify_va_arg_expr)
- /* FIXME: Once most targets are converted we should merely
- assert this is non-null. */
- return GS_ALL_DONE;
-
- *expr_p = targetm.gimplify_va_arg_expr (valist, type, pre_p, post_p);
- return GS_OK;
- }
-}
-
/* Expand EXP, a call to __builtin_va_end. */
static rtx
@@ -4578,10 +4390,6 @@ expand_builtin_alloca (tree exp, bool cannot_accumulate)
bool alloca_with_align = (DECL_FUNCTION_CODE (get_callee_fndecl (exp))
== BUILT_IN_ALLOCA_WITH_ALIGN);
- /* Emit normal call if we use mudflap. */
- if (flag_mudflap)
- return NULL_RTX;
-
valid_arglist
= (alloca_with_align
? validate_arglist (exp, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE)
@@ -5342,7 +5150,7 @@ get_memmodel (tree exp)
return MEMMODEL_SEQ_CST;
}
- if ((INTVAL(op) & MEMMODEL_MASK) >= MEMMODEL_LAST)
+ if ((INTVAL (op) & MEMMODEL_MASK) >= MEMMODEL_LAST)
{
warning (OPT_Winvalid_memory_model,
"invalid memory model argument to builtin");
@@ -5546,7 +5354,7 @@ expand_builtin_atomic_fetch_op (enum machine_mode mode, tree exp, rtx target,
STRIP_NOPS (addr);
gcc_assert (TREE_OPERAND (addr, 0) == fndecl);
- TREE_OPERAND (addr, 0) = builtin_decl_explicit(ext_call);
+ TREE_OPERAND (addr, 0) = builtin_decl_explicit (ext_call);
/* Expand the call here so we can emit trailing code. */
ret = expand_call (exp, target, ignore);
@@ -5830,6 +5638,33 @@ expand_builtin_set_thread_pointer (tree exp)
}
+/* Emit code to restore the current value of stack. */
+
+static void
+expand_stack_restore (tree var)
+{
+ rtx prev, sa = expand_normal (var);
+
+ sa = convert_memory_address (Pmode, sa);
+
+ prev = get_last_insn ();
+ emit_stack_restore (SAVE_BLOCK, sa);
+ fixup_args_size_notes (prev, get_last_insn (), 0);
+}
+
+
+/* Emit code to save the current value of stack. */
+
+static rtx
+expand_stack_save (void)
+{
+ rtx ret = NULL_RTX;
+
+ do_pending_stack_adjust ();
+ emit_stack_save (SAVE_BLOCK, &ret);
+ return ret;
+}
+
/* Expand an expression EXP that calls a built-in function,
with result going to TARGET if that's convenient
(and in mode MODE if that's convenient).
@@ -5861,7 +5696,18 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
&& fcode != BUILT_IN_EXECVE
&& fcode != BUILT_IN_ALLOCA
&& fcode != BUILT_IN_ALLOCA_WITH_ALIGN
- && fcode != BUILT_IN_FREE)
+ && fcode != BUILT_IN_FREE
+ && fcode != BUILT_IN_CHKP_SET_PTR_BOUNDS
+ && fcode != BUILT_IN_CHKP_INIT_PTR_BOUNDS
+ && fcode != BUILT_IN_CHKP_NULL_PTR_BOUNDS
+ && fcode != BUILT_IN_CHKP_COPY_PTR_BOUNDS
+ && fcode != BUILT_IN_CHKP_NARROW_PTR_BOUNDS
+ && fcode != BUILT_IN_CHKP_STORE_PTR_BOUNDS
+ && fcode != BUILT_IN_CHKP_CHECK_PTR_LBOUNDS
+ && fcode != BUILT_IN_CHKP_CHECK_PTR_UBOUNDS
+ && fcode != BUILT_IN_CHKP_CHECK_PTR_BOUNDS
+ && fcode != BUILT_IN_CHKP_GET_PTR_LBOUND
+ && fcode != BUILT_IN_CHKP_GET_PTR_UBOUND)
return expand_call (exp, target, ignore);
/* The built-in function expanders test for target == const0_rtx
@@ -6905,6 +6751,59 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
expand_builtin_set_thread_pointer (exp);
return const0_rtx;
+ case BUILT_IN_CILK_DETACH:
+ expand_builtin_cilk_detach (exp);
+ return const0_rtx;
+
+ case BUILT_IN_CILK_POP_FRAME:
+ expand_builtin_cilk_pop_frame (exp);
+ return const0_rtx;
+
+ case BUILT_IN_CHKP_INIT_PTR_BOUNDS:
+ case BUILT_IN_CHKP_NULL_PTR_BOUNDS:
+ case BUILT_IN_CHKP_COPY_PTR_BOUNDS:
+ return expand_normal (CALL_EXPR_ARG (exp, 0));
+
+ case BUILT_IN_CHKP_CHECK_PTR_LBOUNDS:
+ case BUILT_IN_CHKP_CHECK_PTR_UBOUNDS:
+ case BUILT_IN_CHKP_CHECK_PTR_BOUNDS:
+ case BUILT_IN_CHKP_SET_PTR_BOUNDS:
+ case BUILT_IN_CHKP_NARROW_PTR_BOUNDS:
+ case BUILT_IN_CHKP_STORE_PTR_BOUNDS:
+ case BUILT_IN_CHKP_GET_PTR_LBOUND:
+ case BUILT_IN_CHKP_GET_PTR_UBOUND:
+ /* We allow user CHKP builtins if Pointer Bounds
+ Checker is off. */
+ if (!flag_check_pointer_bounds)
+ {
+ if (fcode == BUILT_IN_CHKP_SET_PTR_BOUNDS
+ || fcode == BUILT_IN_CHKP_NARROW_PTR_BOUNDS)
+ return expand_normal (CALL_EXPR_ARG (exp, 0));
+ else if (fcode == BUILT_IN_CHKP_GET_PTR_LBOUND)
+ return expand_normal (size_zero_node);
+ else if (fcode == BUILT_IN_CHKP_GET_PTR_UBOUND)
+ return expand_normal (size_int (-1));
+ else
+ return const0_rtx;
+ }
+ /* FALLTHROUGH */
+
+ case BUILT_IN_CHKP_BNDMK:
+ case BUILT_IN_CHKP_BNDSTX:
+ case BUILT_IN_CHKP_BNDCL:
+ case BUILT_IN_CHKP_BNDCU:
+ case BUILT_IN_CHKP_BNDLDX:
+ case BUILT_IN_CHKP_BNDRET:
+ case BUILT_IN_CHKP_INTERSECT:
+ case BUILT_IN_CHKP_ARG_BND:
+ case BUILT_IN_CHKP_NARROW:
+ case BUILT_IN_CHKP_EXTRACT_LOWER:
+ case BUILT_IN_CHKP_EXTRACT_UPPER:
+ /* Software implementation of pointers checker is NYI.
+ Target support is required. */
+ error ("Your target platform does not support -fcheck-pointers");
+ break;
+
default: /* just do library call, if unknown builtin */
break;
}
@@ -9644,8 +9543,8 @@ static tree
fold_builtin_fma (location_t loc, tree arg0, tree arg1, tree arg2, tree type)
{
if (validate_arg (arg0, REAL_TYPE)
- && validate_arg(arg1, REAL_TYPE)
- && validate_arg(arg2, REAL_TYPE))
+ && validate_arg (arg1, REAL_TYPE)
+ && validate_arg (arg2, REAL_TYPE))
{
tree tem = fold_fma (loc, type, arg0, arg1, arg2);
if (tem)
@@ -10387,13 +10286,13 @@ fold_builtin_1 (location_t loc, tree fndecl, tree arg0, bool ignore)
break;
CASE_FLT_FN (BUILT_IN_CCOS):
- return fold_builtin_ccos(loc, arg0, type, fndecl, /*hyper=*/ false);
+ return fold_builtin_ccos (loc, arg0, type, fndecl, /*hyper=*/ false);
CASE_FLT_FN (BUILT_IN_CCOSH):
- return fold_builtin_ccos(loc, arg0, type, fndecl, /*hyper=*/ true);
+ return fold_builtin_ccos (loc, arg0, type, fndecl, /*hyper=*/ true);
CASE_FLT_FN (BUILT_IN_CPROJ):
- return fold_builtin_cproj(loc, arg0, type);
+ return fold_builtin_cproj (loc, arg0, type);
CASE_FLT_FN (BUILT_IN_CSIN):
if (validate_arg (arg0, COMPLEX_TYPE)
@@ -10768,26 +10667,26 @@ fold_builtin_2 (location_t loc, tree fndecl, tree arg0, tree arg1, bool ignore)
CASE_FLT_FN (BUILT_IN_DREM):
CASE_FLT_FN (BUILT_IN_REMAINDER):
if (validate_arg (arg0, REAL_TYPE)
- && validate_arg(arg1, REAL_TYPE))
+ && validate_arg (arg1, REAL_TYPE))
return do_mpfr_arg2 (arg0, arg1, type, mpfr_remainder);
break;
CASE_FLT_FN_REENT (BUILT_IN_GAMMA): /* GAMMA_R */
CASE_FLT_FN_REENT (BUILT_IN_LGAMMA): /* LGAMMA_R */
if (validate_arg (arg0, REAL_TYPE)
- && validate_arg(arg1, POINTER_TYPE))
+ && validate_arg (arg1, POINTER_TYPE))
return do_mpfr_lgamma_r (arg0, arg1, type);
break;
CASE_FLT_FN (BUILT_IN_ATAN2):
if (validate_arg (arg0, REAL_TYPE)
- && validate_arg(arg1, REAL_TYPE))
+ && validate_arg (arg1, REAL_TYPE))
return do_mpfr_arg2 (arg0, arg1, type, mpfr_atan2);
break;
CASE_FLT_FN (BUILT_IN_FDIM):
if (validate_arg (arg0, REAL_TYPE)
- && validate_arg(arg1, REAL_TYPE))
+ && validate_arg (arg1, REAL_TYPE))
return do_mpfr_arg2 (arg0, arg1, type, mpfr_dim);
break;
@@ -10969,8 +10868,8 @@ fold_builtin_3 (location_t loc, tree fndecl,
CASE_FLT_FN (BUILT_IN_REMQUO):
if (validate_arg (arg0, REAL_TYPE)
- && validate_arg(arg1, REAL_TYPE)
- && validate_arg(arg2, POINTER_TYPE))
+ && validate_arg (arg1, REAL_TYPE)
+ && validate_arg (arg2, POINTER_TYPE))
return do_mpfr_remquo (arg0, arg1, arg2);
break;
@@ -11147,47 +11046,51 @@ fold_builtin_n (location_t loc, tree fndecl, tree *args, int nargs, bool ignore)
return NULL_TREE;
}
-/* Builtins with folding operations that operate on "..." arguments
- need special handling; we need to store the arguments in a convenient
- data structure before attempting any folding. Fortunately there are
- only a few builtins that fall into this category. FNDECL is the
- function, EXP is the CALL_EXPR for the call, and IGNORE is true if the
- result of the function call is ignored. */
+/* Construct a new CALL_EXPR to FNDECL using the tail of the argument
+ list ARGS along with N new arguments in NEWARGS. SKIP is the number
+ of arguments in ARGS to be omitted. OLDNARGS is the number of
+ elements in ARGS. */
static tree
-fold_builtin_varargs (location_t loc, tree fndecl, tree exp,
- bool ignore ATTRIBUTE_UNUSED)
+rewrite_call_expr_valist (location_t loc, int oldnargs, tree *args,
+ int skip, tree fndecl, int n, va_list newargs)
{
- enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
- tree ret = NULL_TREE;
+ int nargs = oldnargs - skip + n;
+ tree *buffer;
- switch (fcode)
+ if (n > 0)
{
- case BUILT_IN_SPRINTF_CHK:
- case BUILT_IN_VSPRINTF_CHK:
- ret = fold_builtin_sprintf_chk (loc, exp, fcode);
- break;
+ int i, j;
- case BUILT_IN_SNPRINTF_CHK:
- case BUILT_IN_VSNPRINTF_CHK:
- ret = fold_builtin_snprintf_chk (loc, exp, NULL_TREE, fcode);
- break;
+ buffer = XALLOCAVEC (tree, nargs);
+ for (i = 0; i < n; i++)
+ buffer[i] = va_arg (newargs, tree);
+ for (j = skip; j < oldnargs; j++, i++)
+ buffer[i] = args[j];
+ }
+ else
+ buffer = args + skip;
- case BUILT_IN_FPCLASSIFY:
- ret = fold_builtin_fpclassify (loc, exp);
- break;
+ return build_call_expr_loc_array (loc, fndecl, nargs, buffer);
+}
- default:
- break;
- }
- if (ret)
- {
- ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
- SET_EXPR_LOCATION (ret, loc);
- TREE_NO_WARNING (ret) = 1;
- return ret;
- }
- return NULL_TREE;
+/* Construct a new CALL_EXPR to FNDECL using the tail of the argument
+ list ARGS along with N new arguments specified as the "..."
+ parameters. SKIP is the number of arguments in ARGS to be omitted.
+ OLDNARGS is the number of elements in ARGS. */
+
+static tree
+rewrite_call_expr_array (location_t loc, int oldnargs, tree *args,
+ int skip, tree fndecl, int n, ...)
+{
+ va_list ap;
+ tree t;
+
+ va_start (ap, n);
+ t = rewrite_call_expr_valist (loc, oldnargs, args, skip, fndecl, n, ap);
+ va_end (ap);
+
+ return t;
}
/* Return true if FNDECL shouldn't be folded right now.
@@ -11378,53 +11281,6 @@ fold_builtin_call_array (location_t loc, tree type,
return build_call_array_loc (loc, type, fn, n, argarray);
}
-/* Construct a new CALL_EXPR to FNDECL using the tail of the argument
- list ARGS along with N new arguments in NEWARGS. SKIP is the number
- of arguments in ARGS to be omitted. OLDNARGS is the number of
- elements in ARGS. */
-
-static tree
-rewrite_call_expr_valist (location_t loc, int oldnargs, tree *args,
- int skip, tree fndecl, int n, va_list newargs)
-{
- int nargs = oldnargs - skip + n;
- tree *buffer;
-
- if (n > 0)
- {
- int i, j;
-
- buffer = XALLOCAVEC (tree, nargs);
- for (i = 0; i < n; i++)
- buffer[i] = va_arg (newargs, tree);
- for (j = skip; j < oldnargs; j++, i++)
- buffer[i] = args[j];
- }
- else
- buffer = args + skip;
-
- return build_call_expr_loc_array (loc, fndecl, nargs, buffer);
-}
-
-/* Construct a new CALL_EXPR to FNDECL using the tail of the argument
- list ARGS along with N new arguments specified as the "..."
- parameters. SKIP is the number of arguments in ARGS to be omitted.
- OLDNARGS is the number of elements in ARGS. */
-
-static tree
-rewrite_call_expr_array (location_t loc, int oldnargs, tree *args,
- int skip, tree fndecl, int n, ...)
-{
- va_list ap;
- tree t;
-
- va_start (ap, n);
- t = rewrite_call_expr_valist (loc, oldnargs, args, skip, fndecl, n, ap);
- va_end (ap);
-
- return t;
-}
-
/* Construct a new CALL_EXPR using the tail of the argument list of EXP
along with N new arguments specified as the "..." parameters. SKIP
is the number of arguments in EXP to be omitted. This function is used
@@ -11514,57 +11370,6 @@ validate_gimple_arglist (const_gimple call, ...)
return res;
}
-/* This function validates the types of a function call argument list
- against a specified list of tree_codes. If the last specifier is a 0,
- that represents an ellipses, otherwise the last specifier must be a
- VOID_TYPE. */
-
-bool
-validate_arglist (const_tree callexpr, ...)
-{
- enum tree_code code;
- bool res = 0;
- va_list ap;
- const_call_expr_arg_iterator iter;
- const_tree arg;
-
- va_start (ap, callexpr);
- init_const_call_expr_arg_iterator (callexpr, &iter);
-
- do
- {
- code = (enum tree_code) va_arg (ap, int);
- switch (code)
- {
- case 0:
- /* This signifies an ellipses, any further arguments are all ok. */
- res = true;
- goto end;
- case VOID_TYPE:
- /* This signifies an endlink, if no arguments remain, return
- true, otherwise return false. */
- res = !more_const_call_expr_args_p (&iter);
- goto end;
- default:
- /* If no parameters remain or the parameter's code does not
- match the specified code, return false. Otherwise continue
- checking any remaining arguments. */
- arg = next_const_call_expr_arg (&iter);
- if (!validate_arg (arg, code))
- goto end;
- break;
- }
- }
- while (1);
-
- /* We need gotos here since we can only have one VA_CLOSE in a
- function. */
- end: ;
- va_end (ap);
-
- return res;
-}
-
/* Default target-specific builtin expander that does nothing. */
rtx
@@ -13336,7 +13141,7 @@ fold_builtin_snprintf_chk_1 (location_t loc, int nargs, tree *args,
BUILT_IN_VSNPRINTF_CHK. If MAXLEN is not NULL, it is maximum length
passed as second argument. */
-tree
+static tree
fold_builtin_snprintf_chk (location_t loc, tree exp, tree maxlen,
enum built_in_function fcode)
{
@@ -13344,6 +13149,49 @@ fold_builtin_snprintf_chk (location_t loc, tree exp, tree maxlen,
CALL_EXPR_ARGP (exp), maxlen, fcode);
}
+/* Builtins with folding operations that operate on "..." arguments
+ need special handling; we need to store the arguments in a convenient
+ data structure before attempting any folding. Fortunately there are
+ only a few builtins that fall into this category. FNDECL is the
+ function, EXP is the CALL_EXPR for the call, and IGNORE is true if the
+ result of the function call is ignored. */
+
+static tree
+fold_builtin_varargs (location_t loc, tree fndecl, tree exp,
+ bool ignore ATTRIBUTE_UNUSED)
+{
+ enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
+ tree ret = NULL_TREE;
+
+ switch (fcode)
+ {
+ case BUILT_IN_SPRINTF_CHK:
+ case BUILT_IN_VSPRINTF_CHK:
+ ret = fold_builtin_sprintf_chk (loc, exp, fcode);
+ break;
+
+ case BUILT_IN_SNPRINTF_CHK:
+ case BUILT_IN_VSNPRINTF_CHK:
+ ret = fold_builtin_snprintf_chk (loc, exp, NULL_TREE, fcode);
+ break;
+
+ case BUILT_IN_FPCLASSIFY:
+ ret = fold_builtin_fpclassify (loc, exp);
+ break;
+
+ default:
+ break;
+ }
+ if (ret)
+ {
+ ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
+ SET_EXPR_LOCATION (ret, loc);
+ TREE_NO_WARNING (ret) = 1;
+ return ret;
+ }
+ return NULL_TREE;
+}
+
/* Fold a call to the {,v}printf{,_unlocked} and __{,v}printf_chk builtins.
FMT and ARG are the arguments to the call; we don't fold cases with
more than 2 arguments, and ARG may be null if this is a 1-argument case.
@@ -13943,7 +13791,7 @@ do_mpfr_bessel_n (tree arg1, tree arg2, tree type,
&& host_integerp (arg1, 0)
&& TREE_CODE (arg2) == REAL_CST && !TREE_OVERFLOW (arg2))
{
- const HOST_WIDE_INT n = tree_low_cst(arg1, 0);
+ const HOST_WIDE_INT n = tree_low_cst (arg1, 0);
const REAL_VALUE_TYPE *const ra = &TREE_REAL_CST (arg2);
if (n == (long)n
@@ -14071,7 +13919,7 @@ do_mpfr_lgamma_r (tree arg, tree arg_sg, tree type)
negative integer. */
if (real_isfinite (ra)
&& ra->cl != rvc_zero
- && !(real_isneg(ra) && real_isinteger(ra, TYPE_MODE (type))))
+ && !(real_isneg (ra) && real_isinteger (ra, TYPE_MODE (type))))
{
const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
const int prec = fmt->p;
@@ -14140,8 +13988,8 @@ do_mpc_arg1 (tree arg, tree type, int (*func)(mpc_ptr, mpc_srcptr, mpc_rnd_t))
mpc_t m;
mpc_init2 (m, prec);
- mpfr_from_real (mpc_realref(m), re, rnd);
- mpfr_from_real (mpc_imagref(m), im, rnd);
+ mpfr_from_real (mpc_realref (m), re, rnd);
+ mpfr_from_real (mpc_imagref (m), im, rnd);
mpfr_clear_flags ();
inexact = func (m, m, crnd);
result = do_mpc_ckconv (m, type, inexact, /*force_convert=*/ 0);
@@ -14196,10 +14044,10 @@ do_mpc_arg2 (tree arg0, tree arg1, tree type, int do_nonfinite,
mpc_init2 (m0, prec);
mpc_init2 (m1, prec);
- mpfr_from_real (mpc_realref(m0), re0, rnd);
- mpfr_from_real (mpc_imagref(m0), im0, rnd);
- mpfr_from_real (mpc_realref(m1), re1, rnd);
- mpfr_from_real (mpc_imagref(m1), im1, rnd);
+ mpfr_from_real (mpc_realref (m0), re0, rnd);
+ mpfr_from_real (mpc_imagref (m0), im0, rnd);
+ mpfr_from_real (mpc_realref (m1), re1, rnd);
+ mpfr_from_real (mpc_imagref (m1), im1, rnd);
mpfr_clear_flags ();
inexact = func (m0, m0, m1, crnd);
result = do_mpc_ckconv (m0, type, inexact, do_nonfinite);
diff --git a/gcc/builtins.def b/gcc/builtins.def
index 8ccf3ae3578..3082548731d 100644
--- a/gcc/builtins.def
+++ b/gcc/builtins.def
@@ -147,6 +147,13 @@ along with GCC; see the file COPYING3. If not see
false, true, true, ATTRS, false, \
(flag_openmp || flag_tree_parallelize_loops))
+/* Builtin used by implementation of Cilk Plus. Most of these are decomposed
+ by the compiler but a few are implemented in libcilkrts. */
+#undef DEF_CILK_BUILTIN_STUB
+#define DEF_CILK_BUILTIN_STUB(ENUM, NAME) \
+ DEF_BUILTIN (ENUM, NAME, BUILT_IN_NORMAL, BT_LAST, BT_LAST, false, false, \
+ false, ATTR_LAST, false, false)
+
/* Builtin used by the implementation of GNU TM. These
functions are mapped to the actual implementation of the STM library. */
#undef DEF_TM_BUILTIN
@@ -169,6 +176,12 @@ along with GCC; see the file COPYING3. If not see
DEF_BUILTIN (ENUM, NAME, BUILT_IN_NORMAL, BT_FN_INT_VAR, BT_LAST, \
false, false, false, ATTRS, false, flag_enable_cilkplus)
+/* Builtin used by the implementation of Pointer Bounds Checker. */
+#undef DEF_CHKP_BUILTIN
+#define DEF_CHKP_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
+ DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
+ true, true, false, ATTRS, true, true)
+
/* 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". */
@@ -200,6 +213,12 @@ along with GCC; see the file COPYING3. If not see
#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)
@@ -846,6 +865,9 @@ DEF_GCC_BUILTIN (BUILT_IN_LINE, "LINE", BT_FN_INT, ATTR_NOTHROW_LEAF_LIST)
/* OpenMP builtins. */
#include "omp-builtins.def"
+/* Cilk keywords builtins. */
+#include "cilk-builtins.def"
+
/* GTM builtins. */
#include "gtm-builtins.def"
@@ -854,3 +876,6 @@ DEF_GCC_BUILTIN (BUILT_IN_LINE, "LINE", BT_FN_INT, ATTR_NOTHROW_LEAF_LIST)
/* Cilk Plus builtins. */
#include "cilkplus.def"
+
+/* Pointer Bounds Checker builtins. */
+#include "chkp-builtins.def"
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index 1772ba56b49..6b2a5ab811b 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,245 @@
+2013-11-09 Joseph Myers <joseph@codesourcery.com>
+
+ * c-common.c (atomic_size_supported_p): New function.
+ (resolve_overloaded_atomic_exchange)
+ (resolve_overloaded_atomic_compare_exchange)
+ (resolve_overloaded_atomic_load, resolve_overloaded_atomic_store):
+ Use it instead of comparing size with a local list of sizes.
+
+2013-11-07 Andrew MacLeod <amacleod@redhat.com>
+ Joseph Myers <joseph@codesourcery.com>
+
+ * c-common.h (enum rid): Add RID_ATOMIC.
+ * c-common.c (c_common_reswords): Add _Atomic.
+ (sync_resolve_params): Use TYPE_MAIN_VARIANT on pointer argument.
+ (keyword_is_type_qualifier): Accept RID_ATOMIC.
+ * c-format.c (check_format_types): Check for extra _Atomic
+ qualifiers in format argument.
+ * c-pretty-print.c (pp_c_cv_qualifiers): Handle atomic qualifier.
+ (pp_c_type_qualifier_list): Mention _Atomic in comment.
+
+2013-11-06 Tobias Burnus <burnus@net-b.de>
+
+ * c-common.c (reason_option_codes_t): Add CPP_W_DATE_TIME.
+
+2013-11-06 Joseph Myers <joseph@codesourcery.com>
+
+ * c-opts.c (c_common_post_options): Set -ffp-contract=off in C
+ standards modes.
+ * c-cppbuiltin.c (cpp_iec_559_value): Consider -ffp-contract=fast
+ to mean lack of IEEE 754 support.
+
+2013-11-05 Tobias Burnus <burnus@net-b.de>
+
+ * c.opt (-Wdate-time): New option
+ * c-opts.c (sanitize_cpp_opts): Pass on to libcpp.
+
+2013-11-05 Joseph Myers <joseph@codesourcery.com>
+
+ * c-cppbuiltin.c (cpp_iec_559_value): Test
+ flag_excess_precision_cmdline not flag_excess_precision.
+
+2013-11-05 Tobias Burnus <burnus@net-b.de>
+
+ * c.opt (fopenmp-simd): New option.
+ * c-pragma.c (omp_pragmas): Move pragmas which can contain simd to ...
+ (omp_pragmas): ... this new struct.
+ (c_pp_lookup_pragma): Also walk omp_pragmas.
+ (init_pragma): Init pragmas for -fopenmp-simd.
+
+2013-11-04 Marek Polacek <polacek@redhat.com>
+
+ PR c++/58979
+ * c-common.c (invalid_indirection_error): Handle RO_ARROW_STAR case.
+
+2013-11-04 Joseph Myers <joseph@codesourcery.com>
+
+ * c-cppbuiltin.c (cpp_iec_559_value, cpp_iec_559_complex_value):
+ New functions.
+ (c_cpp_builtins): Define __GCC_IEC_559 and __GCC_IEC_559_COMPLEX.
+
+2013-11-04 Eric Botcazou <ebotcazou@adacore.com>
+
+ * c-ada-spec.h (cpp_operation): Add IS_TRIVIAL.
+ (dump_ada_specs): Adjust prototype of second callback.
+ * c-ada-spec.c (cpp_check): New global variable.
+ (dump_ada_nodes): Remove cpp_check parameter and do not pass it down.
+ (print_generic_ada_decl): Likewise.
+ (has_static_fields): Change return type to bool and add guard.
+ (has_nontrivial_methods): New predicate.
+ (is_tagged_type): Change return type to bool.
+ (separate_class_package): Call has_nontrivial_methods.
+ (pp_ada_tree_identifier): Minor tweaks.
+ (dump_ada_function_declaration): Adjust calls to dump_generic_ada_node.
+ (dump_ada_array_domains): Likewise.
+ (dump_ada_array_type): Likewise.
+ (dump_template_types): Remove cpp_check parameter and do not pass it to
+ dump_generic_ada_node.
+ (dump_ada_template): Likewise.
+ (dump_generic_ada_node): Remove cpp_check parameter and do not pass it
+ recursively.
+ (print_ada_methods): Change return type to integer. Remove cpp_check
+ parameter and do not pass it down.
+ (dump_nested_types): Remove cpp_check parameter and do not pass it to
+ dump_generic_ada_node.
+ (print_ada_declaration): Likewise. Test RECORD_OR_UNION_TYPE_P before
+ accessing methods.
+ (print_ada_struct_decl): Remove cpp_check parameter and do not pass it
+ down. Use has_nontrivial_methods to recognize C++ classes. Use return
+ value of print_ada_methods.
+ (dump_ads): Rename cpp_check parameter to check and adjust prototype.
+ Set cpp_check to it before invoking dump_ada_nodes.
+ (dump_ada_specs): Likewise.
+
+2013-11-03 Marek Polacek <polacek@redhat.com>
+
+ * c-ubsan.c: Don't include hash-table.h.
+ (ubsan_instrument_vla): New function.
+ * c-ubsan.h: Declare it.
+
+2013-10-31 David Malcolm <dmalcolm@redhat.com>
+
+ Automated part of renaming of symtab_node_base to symtab_node.
+
+ Patch autogenerated by rename_symtab.py from
+ https://github.com/davidmalcolm/gcc-refactoring-scripts
+ revision 58bb219cc090b2f4516a9297d868c245495ee622
+
+ * c-pragma.c (maybe_apply_pending_pragma_weaks): Rename
+ symtab_node_base to symtab_node.
+
+2013-10-31 Edward Smith-Rowland <3dw4rd@verizon.net>
+
+ Implement C++14 digit separators.
+ * c-lex.c (interpret_float): Remove digit separators from scratch string
+ before building real literal.
+
+2013-10-30 Jakub Jelinek <jakub@redhat.com>
+
+ * cilk.c (create_cilk_helper_decl): Use HOST_WIDE_INT_PRINT_DEC.
+
+2013-10-29 Balaji V. Iyer <balaji.v.iyer@intel.com>
+
+ * c-common.c (c_common_reswords[]): Added _Cilk_spawn and _Cilk_sync
+ fields.
+ (c_define_builtins): Called cilk_init_builtins if Cilk Plus is
+ enabled.
+ * c-common.h (enum rid): Added RID_CILK_SPAWN and RID_CILK_SYNC.
+ (insert_cilk_frame): New prototype.
+ (cilk_init_builtins): Likewise.
+ (gimplify_cilk_spawn): Likewise.
+ (c_cilk_install_body_w_frame_cleanup): Likewise.
+ (cilk_detect_spawn_and_unwrap): Likewise.
+ (cilk_set_spawn_marker): Likewise.
+ (build_cilk_sync): Likewise.
+ (build_cilk_spawn): Likewise.
+ * cilk.c: New file.
+
+2013-10-29 David Malcolm <dmalcolm@redhat.com>
+
+ Patch autogenerated by refactor_symtab.py from
+ https://github.com/davidmalcolm/gcc-refactoring-scripts
+ revision 58bb219cc090b2f4516a9297d868c245495ee622
+
+ * c-gimplify.c (c_genericize): Update for conversion of symtab types
+ to a true class hierarchy.
+ * c-pragma.c (maybe_apply_pending_pragma_weaks): Likewise.
+
+2013-10-27 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * c-lex.c (interpret_integer): Remove call to cpp_num_sign_extend.
+
+2013-10-26 Jeff Law <law@redhat.com>
+
+ * c-family/c-common.c (c_define_builtins): Remove mudflap support.
+ * c-family/c.opt: Ignore and warn for mudflap options.
+
+2013-10-24 Tobias Burnus <burnus@net-b.de>
+
+ PR other/33426
+ * c-pragma.c (init_pragma) Add #pragma ivdep handling.
+ * c-pragma.h (pragma_kind): Add PRAGMA_IVDEP.
+
+2013-10-23 Jason Merrill <jason@redhat.com>
+
+ * c-format.c (gcc_cxxdiag_char_table): Add %X.
+
+2013-10-11 Jakub Jelinek <jakub@redhat.com>
+
+ * c-common.h (omp_clause_mask::operator !=): New method.
+ * c-omp.c (c_omp_split_clauses): Use if ((mask & something) != 0)
+ instead of if (mask & something) tests everywhere.
+
+ * c-cppbuiltin.c (c_cpp_builtins): Predefine _OPENMP to
+ 201307 instead of 201107.
+ * c-common.c (DEF_FUNCTION_TYPE_8): Define.
+ (c_common_attribute_table): Add "omp declare target" and
+ "omp declare simd" attributes.
+ (handle_omp_declare_target_attribute,
+ handle_omp_declare_simd_attribute): New functions.
+ * c-omp.c: Include c-pragma.h.
+ (c_finish_omp_taskgroup): New function.
+ (c_finish_omp_atomic): Add swapped argument, if true,
+ build the operation first with rhs, lhs arguments and use NOP_EXPR
+ build_modify_expr.
+ (c_finish_omp_for): Add code argument, pass it down to make_code.
+ (c_omp_split_clauses): New function.
+ (c_split_parallel_clauses): Removed.
+ (c_omp_declare_simd_clause_cmp, c_omp_declare_simd_clauses_to_numbers,
+ c_omp_declare_simd_clauses_to_decls): New functions.
+ * c-common.h (omp_clause_mask): New type.
+ (OMP_CLAUSE_MASK_1): Define.
+ (omp_clause_mask::omp_clause_mask, omp_clause_mask::operator &=,
+ omp_clause_mask::operator |=, omp_clause_mask::operator ~,
+ omp_clause_mask::operator |, omp_clause_mask::operator &,
+ omp_clause_mask::operator <<, omp_clause_mask::operator >>,
+ omp_clause_mask::operator ==): New methods.
+ (enum c_omp_clause_split): New.
+ (c_finish_omp_taskgroup): New prototype.
+ (c_finish_omp_atomic): Add swapped argument.
+ (c_finish_omp_for): Add code argument.
+ (c_omp_split_clauses): New prototype.
+ (c_split_parallel_clauses): Removed.
+ (c_omp_declare_simd_clauses_to_numbers,
+ c_omp_declare_simd_clauses_to_decls): New prototypes.
+ * c-pragma.c (omp_pragmas): Add new OpenMP 4.0 constructs.
+ * c-pragma.h (enum pragma_kind): Add PRAGMA_OMP_CANCEL,
+ PRAGMA_OMP_CANCELLATION_POINT, PRAGMA_OMP_DECLARE_REDUCTION,
+ PRAGMA_OMP_DISTRIBUTE, PRAGMA_OMP_END_DECLARE_TARGET, PRAGMA_OMP_SIMD,
+ PRAGMA_OMP_TARGET, PRAGMA_OMP_TASKGROUP and PRAGMA_OMP_TEAMS.
+ Remove PRAGMA_OMP_PARALLEL_FOR and PRAGMA_OMP_PARALLEL_SECTIONS.
+ (enum pragma_omp_clause): Add PRAGMA_OMP_CLAUSE_ALIGNED,
+ PRAGMA_OMP_CLAUSE_DEPEND, PRAGMA_OMP_CLAUSE_DEVICE,
+ PRAGMA_OMP_CLAUSE_DIST_SCHEDULE, PRAGMA_OMP_CLAUSE_FOR,
+ PRAGMA_OMP_CLAUSE_FROM, PRAGMA_OMP_CLAUSE_INBRANCH,
+ PRAGMA_OMP_CLAUSE_LINEAR, PRAGMA_OMP_CLAUSE_MAP,
+ PRAGMA_OMP_CLAUSE_NOTINBRANCH, PRAGMA_OMP_CLAUSE_NUM_TEAMS,
+ PRAGMA_OMP_CLAUSE_PARALLEL, PRAGMA_OMP_CLAUSE_PROC_BIND,
+ PRAGMA_OMP_CLAUSE_SAFELEN, PRAGMA_OMP_CLAUSE_SECTIONS,
+ PRAGMA_OMP_CLAUSE_SIMDLEN, PRAGMA_OMP_CLAUSE_TASKGROUP,
+ PRAGMA_OMP_CLAUSE_THREAD_LIMIT, PRAGMA_OMP_CLAUSE_TO and
+ PRAGMA_OMP_CLAUSE_UNIFORM.
+
+2013-10-09 Marc Glisse <marc.glisse@inria.fr>
+
+ PR tree-optimization/20318
+ * c-common.c (handle_returns_nonnull_attribute): New function.
+ (c_common_attribute_table): Add returns_nonnull.
+
+2013-10-03 Marc Glisse <marc.glisse@inria.fr>
+
+ PR c++/19476
+ * c.opt (fcheck-new): Move to common.opt.
+
+2013-09-25 Marek Polacek <polacek@redhat.com>
+ Jakub Jelinek <jakub@redhat.com>
+
+ PR sanitizer/58413
+ * c-ubsan.c (ubsan_instrument_shift): Don't instrument
+ an expression if we can prove it is correct.
+ (ubsan_instrument_division): Likewise. Remove unnecessary
+ check.
+
2013-09-18 Marek Polacek <polacek@redhat.com>
PR sanitizer/58411
@@ -314,7 +556,7 @@
* c-family/array-notation-common.c (length_mismatch_in_expr_p): Delete
unused variables l_length and l_node.
-2013-07-04 Joern Rennecke <joern.rennecke@embecosm.com>
+2013-07-04 Joern Rennecke <joern.rennecke@embecosm.com>
PR c/57821
* c-common.c (complete_array_type): Delay folding first index
diff --git a/gcc/c-family/c-ada-spec.c b/gcc/c-family/c-ada-spec.c
index eac57838752..3f325e77098 100644
--- a/gcc/c-family/c-ada-spec.c
+++ b/gcc/c-family/c-ada-spec.c
@@ -46,32 +46,31 @@ along with GCC; see the file COPYING3. If not see
#endif /* HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG */
/* Local functions, macros and variables. */
-static int dump_generic_ada_node (pretty_printer *, tree, tree,
- int (*)(tree, cpp_operation), int, int, bool);
-static int print_ada_declaration (pretty_printer *, tree, tree,
- int (*cpp_check)(tree, cpp_operation), int);
-static void print_ada_struct_decl (pretty_printer *, tree, tree,
- int (*cpp_check)(tree, cpp_operation), int,
- bool);
+static int dump_generic_ada_node (pretty_printer *, tree, tree, int, int,
+ bool);
+static int print_ada_declaration (pretty_printer *, tree, tree, int);
+static void print_ada_struct_decl (pretty_printer *, tree, tree, int, bool);
static void dump_sloc (pretty_printer *buffer, tree node);
static void print_comment (pretty_printer *, const char *);
-static void print_generic_ada_decl (pretty_printer *, tree,
- int (*)(tree, cpp_operation), const char *);
+static void print_generic_ada_decl (pretty_printer *, tree, const char *);
static char *get_ada_package (const char *);
-static void dump_ada_nodes (pretty_printer *, const char *,
- int (*)(tree, cpp_operation));
+static void dump_ada_nodes (pretty_printer *, const char *);
static void reset_ada_withs (void);
static void dump_ada_withs (FILE *);
static void dump_ads (const char *, void (*)(const char *),
- int (*)(tree, cpp_operation));
+ int (*)(const_tree, cpp_operation));
static char *to_ada_name (const char *, int *);
static bool separate_class_package (tree);
-#define INDENT(SPACE) do { \
- int i; for (i = 0; i<SPACE; i++) pp_space (buffer); } while (0)
+#define INDENT(SPACE) \
+ do { int i; for (i = 0; i<SPACE; i++) pp_space (buffer); } while (0)
#define INDENT_INCR 3
+/* Global hook used to perform C++ queries on nodes. */
+static int (*cpp_check) (const_tree, cpp_operation) = NULL;
+
+
/* Given a cpp MACRO, compute the max length BUFFER_LEN of the macro, as well
as max length PARAM_LEN of arguments for fun_like macros, and also set
SUPPORTED to 0 if the macro cannot be mapped to an Ada construct. */
@@ -636,11 +635,10 @@ unmark_visited_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
}
/* Dump nodes into PP relevant to SOURCE_FILE, as collected by previous calls
- to collect_ada_nodes. CPP_CHECK is used to perform C++ queries on nodes. */
+ to collect_ada_nodes. */
static void
-dump_ada_nodes (pretty_printer *pp, const char *source_file,
- int (*cpp_check)(tree, cpp_operation))
+dump_ada_nodes (pretty_printer *pp, const char *source_file)
{
int i, j;
cpp_comment_table *comments;
@@ -676,7 +674,7 @@ dump_ada_nodes (pretty_printer *pp, const char *source_file,
if (j == comments->count
|| LOCATION_LINE (decl_sloc (to_dump[i], false))
< LOCATION_LINE (comments->entries[j].sloc))
- print_generic_ada_decl (pp, to_dump[i++], cpp_check, source_file);
+ print_generic_ada_decl (pp, to_dump[i++], source_file);
else
break;
}
@@ -736,18 +734,15 @@ print_comment (pretty_printer *pp, const char *comment)
pp_newline (pp);
}
-/* Prints declaration DECL to PP in Ada syntax. The current source file being
- handled is SOURCE_FILE, and CPP_CHECK is used to perform C++ queries on
- nodes. */
+/* Print declaration DECL to PP in Ada syntax. The current source file being
+ handled is SOURCE_FILE. */
static void
-print_generic_ada_decl (pretty_printer *pp, tree decl,
- int (*cpp_check)(tree, cpp_operation),
- const char* source_file)
+print_generic_ada_decl (pretty_printer *pp, tree decl, const char *source_file)
{
source_file_base = source_file;
- if (print_ada_declaration (pp, decl, 0, cpp_check, INDENT_INCR))
+ if (print_ada_declaration (pp, decl, 0, INDENT_INCR))
{
pp_newline (pp);
pp_newline (pp);
@@ -941,23 +936,25 @@ get_underlying_decl (tree type)
/* Return whether TYPE has static fields. */
-static int
+static bool
has_static_fields (const_tree type)
{
tree tmp;
+ if (!type || !RECORD_OR_UNION_TYPE_P (type))
+ return false;
+
for (tmp = TYPE_FIELDS (type); tmp; tmp = TREE_CHAIN (tmp))
- {
- if (DECL_NAME (tmp) && TREE_STATIC (tmp))
- return true;
- }
+ if (DECL_NAME (tmp) && TREE_STATIC (tmp))
+ return true;
+
return false;
}
/* Return whether TYPE corresponds to an Ada tagged type (has a dispatch
table). */
-static int
+static bool
is_tagged_type (const_tree type)
{
tree tmp;
@@ -972,6 +969,35 @@ is_tagged_type (const_tree type)
return false;
}
+/* Return whether TYPE has non-trivial methods, i.e. methods that do something
+ for the objects of TYPE. In C++, all classes have implicit special methods,
+ e.g. constructors and destructors, but they can be trivial if the type is
+ sufficiently simple. */
+
+static bool
+has_nontrivial_methods (const_tree type)
+{
+ tree tmp;
+
+ if (!type || !RECORD_OR_UNION_TYPE_P (type))
+ return false;
+
+ /* Only C++ types can have methods. */
+ if (!cpp_check)
+ return false;
+
+ /* A non-trivial type has non-trivial special methods. */
+ if (!cpp_check (type, IS_TRIVIAL))
+ return true;
+
+ /* If there are user-defined methods, they are deemed non-trivial. */
+ for (tmp = TYPE_METHODS (type); tmp; tmp = TREE_CHAIN (tmp))
+ if (!DECL_ARTIFICIAL (tmp))
+ return true;
+
+ return false;
+}
+
/* Generate a legal Ada name from a C NAME, returning a malloc'd string.
SPACE_FOUND, if not NULL, is used to indicate whether a space was found in
NAME. */
@@ -1193,15 +1219,8 @@ to_ada_name (const char *name, int *space_found)
static bool
separate_class_package (tree decl)
{
- if (decl)
- {
- tree type = TREE_TYPE (decl);
- return type
- && TREE_CODE (type) == RECORD_TYPE
- && (TYPE_METHODS (type) || has_static_fields (type));
- }
- else
- return false;
+ tree type = TREE_TYPE (decl);
+ return has_nontrivial_methods (type) || has_static_fields (type);
}
static bool package_prefix = true;
@@ -1221,7 +1240,6 @@ pp_ada_tree_identifier (pretty_printer *buffer, tree node, tree type,
/* If the entity is a type and comes from another file, generate "package"
prefix. */
-
decl = get_underlying_decl (type);
if (decl)
@@ -1246,30 +1264,27 @@ pp_ada_tree_identifier (pretty_printer *buffer, tree node, tree type,
case UNION_TYPE:
case QUAL_UNION_TYPE:
case TYPE_DECL:
- {
- char *s1 = get_ada_package (xloc.file);
-
- if (package_prefix)
- {
- append_withs (s1, limited_access);
- pp_string (buffer, s1);
- pp_dot (buffer);
- }
- free (s1);
- }
+ if (package_prefix)
+ {
+ char *s1 = get_ada_package (xloc.file);
+ append_withs (s1, limited_access);
+ pp_string (buffer, s1);
+ pp_dot (buffer);
+ free (s1);
+ }
break;
default:
break;
}
-
- if (separate_class_package (decl))
- {
- pp_string (buffer, "Class_");
- pp_string (buffer, s);
- pp_dot (buffer);
- }
-
- }
+
+ /* Generate the additional package prefix for C++ classes. */
+ if (separate_class_package (decl))
+ {
+ pp_string (buffer, "Class_");
+ pp_string (buffer, s);
+ pp_dot (buffer);
+ }
+ }
}
}
@@ -1527,15 +1542,13 @@ dump_ada_function_declaration (pretty_printer *buffer, tree func,
pp_string (buffer, buf);
}
- dump_generic_ada_node
- (buffer, TREE_TYPE (arg), node, NULL, spc, 0, true);
+ dump_generic_ada_node (buffer, TREE_TYPE (arg), node, spc, 0, true);
}
else
{
sprintf (buf, "arg%d : ", num);
pp_string (buffer, buf);
- dump_generic_ada_node
- (buffer, TREE_VALUE (arg), node, NULL, spc, 0, true);
+ dump_generic_ada_node (buffer, TREE_VALUE (arg), node, spc, 0, true);
}
if (TREE_TYPE (arg) && TREE_TYPE (TREE_TYPE (arg))
@@ -1593,13 +1606,13 @@ dump_ada_array_domains (pretty_printer *buffer, tree node, int spc)
first = 0;
if (min)
- dump_generic_ada_node (buffer, min, NULL_TREE, NULL, spc, 0, true);
+ dump_generic_ada_node (buffer, min, NULL_TREE, spc, 0, true);
pp_string (buffer, " .. ");
/* If the upper bound is zero, gcc may generate a NULL_TREE
for TYPE_MAX_VALUE rather than an integer_cst. */
if (max)
- dump_generic_ada_node (buffer, max, NULL_TREE, NULL, spc, 0, true);
+ dump_generic_ada_node (buffer, max, NULL_TREE, spc, 0, true);
else
pp_string (buffer, "0");
}
@@ -1687,18 +1700,16 @@ dump_ada_array_type (pretty_printer *buffer, tree t, int spc)
pp_string (buffer, "aliased ");
dump_generic_ada_node
- (buffer, TREE_TYPE (tmp), TREE_TYPE (t), NULL, spc, false, true);
+ (buffer, TREE_TYPE (tmp), TREE_TYPE (t), spc, false, true);
}
}
/* Dump in BUFFER type names associated with a template, each prepended with
- '_'. TYPES is the TREE_PURPOSE of a DECL_TEMPLATE_INSTANTIATIONS.
- CPP_CHECK is used to perform C++ queries on nodes.
- SPC is the indentation level. */
+ '_'. TYPES is the TREE_PURPOSE of a DECL_TEMPLATE_INSTANTIATIONS. SPC is
+ the indentation level. */
static void
-dump_template_types (pretty_printer *buffer, tree types,
- int (*cpp_check)(tree, cpp_operation), int spc)
+dump_template_types (pretty_printer *buffer, tree types, int spc)
{
size_t i;
size_t len = TREE_VEC_LENGTH (types);
@@ -1707,7 +1718,7 @@ dump_template_types (pretty_printer *buffer, tree types,
{
tree elem = TREE_VEC_ELT (types, i);
pp_underscore (buffer);
- if (!dump_generic_ada_node (buffer, elem, 0, cpp_check, spc, false, true))
+ if (!dump_generic_ada_node (buffer, elem, 0, spc, false, true))
{
pp_string (buffer, "unknown");
pp_scalar (buffer, "%lu", (unsigned long) TREE_HASH (elem));
@@ -1716,12 +1727,10 @@ dump_template_types (pretty_printer *buffer, tree types,
}
/* Dump in BUFFER the contents of all class instantiations associated with
- a given template T. CPP_CHECK is used to perform C++ queries on nodes.
- SPC is the indentation level. */
+ a given template T. SPC is the indentation level. */
static int
-dump_ada_template (pretty_printer *buffer, tree t,
- int (*cpp_check)(tree, cpp_operation), int spc)
+dump_ada_template (pretty_printer *buffer, tree t, int spc)
{
/* DECL_VINDEX is DECL_TEMPLATE_INSTANTIATIONS in this context. */
tree inst = DECL_VINDEX (t);
@@ -1750,15 +1759,15 @@ dump_ada_template (pretty_printer *buffer, tree t,
INDENT (spc);
pp_string (buffer, "package ");
package_prefix = false;
- dump_generic_ada_node (buffer, instance, t, cpp_check, spc, false, true);
- dump_template_types (buffer, types, cpp_check, spc);
+ dump_generic_ada_node (buffer, instance, t, spc, false, true);
+ dump_template_types (buffer, types, spc);
pp_string (buffer, " is");
spc += INDENT_INCR;
newline_and_indent (buffer, spc);
TREE_VISITED (get_underlying_decl (instance)) = 1;
pp_string (buffer, "type ");
- dump_generic_ada_node (buffer, instance, t, cpp_check, spc, false, true);
+ dump_generic_ada_node (buffer, instance, t, spc, false, true);
package_prefix = true;
if (is_tagged_type (instance))
@@ -1766,7 +1775,7 @@ dump_ada_template (pretty_printer *buffer, tree t,
else
pp_string (buffer, " is limited ");
- dump_generic_ada_node (buffer, instance, t, cpp_check, spc, false, false);
+ dump_generic_ada_node (buffer, instance, t, spc, false, false);
pp_newline (buffer);
spc -= INDENT_INCR;
newline_and_indent (buffer, spc);
@@ -1775,8 +1784,8 @@ dump_ada_template (pretty_printer *buffer, tree t,
newline_and_indent (buffer, spc);
pp_string (buffer, "use ");
package_prefix = false;
- dump_generic_ada_node (buffer, instance, t, cpp_check, spc, false, true);
- dump_template_types (buffer, types, cpp_check, spc);
+ dump_generic_ada_node (buffer, instance, t, spc, false, true);
+ dump_template_types (buffer, types, spc);
package_prefix = true;
pp_semicolon (buffer);
pp_newline (buffer);
@@ -1819,14 +1828,12 @@ static bool in_function = true;
static bool bitfield_used = false;
/* Recursively dump in BUFFER Ada declarations corresponding to NODE of type
- TYPE. CPP_CHECK is used to perform C++ queries on nodes. SPC is the
- indentation level. LIMITED_ACCESS indicates whether NODE can be referenced
- via a "limited with" clause. NAME_ONLY indicates whether we should only
- dump the name of NODE, instead of its full declaration. */
+ TYPE. SPC is the indentation level. LIMITED_ACCESS indicates whether NODE
+ can be referenced via a "limited with" clause. NAME_ONLY indicates whether
+ we should only dump the name of NODE, instead of its full declaration. */
static int
-dump_generic_ada_node (pretty_printer *buffer, tree node, tree type,
- int (*cpp_check)(tree, cpp_operation), int spc,
+dump_generic_ada_node (pretty_printer *buffer, tree node, tree type, int spc,
int limited_access, bool name_only)
{
if (node == NULL_TREE)
@@ -1848,8 +1855,7 @@ dump_generic_ada_node (pretty_printer *buffer, tree node, tree type,
case TREE_BINFO:
dump_generic_ada_node
- (buffer, BINFO_TYPE (node), type, cpp_check,
- spc, limited_access, name_only);
+ (buffer, BINFO_TYPE (node), type, spc, limited_access, name_only);
case TREE_VEC:
pp_string (buffer, "--- unexpected node: TREE_VEC");
@@ -1876,7 +1882,7 @@ dump_generic_ada_node (pretty_printer *buffer, tree node, tree type,
case ENUMERAL_TYPE:
if (name_only)
dump_generic_ada_node
- (buffer, TYPE_NAME (node), node, cpp_check, spc, 0, true);
+ (buffer, TYPE_NAME (node), node, spc, 0, true);
else
{
tree value = TYPE_VALUES (node);
@@ -1906,7 +1912,7 @@ dump_generic_ada_node (pretty_printer *buffer, tree node, tree type,
pp_string (buffer, "pragma Convention (C, ");
dump_generic_ada_node
(buffer, DECL_NAME (type) ? type : TYPE_NAME (node), type,
- cpp_check, spc, 0, true);
+ spc, 0, true);
pp_right_paren (buffer);
}
else
@@ -1923,14 +1929,14 @@ dump_generic_ada_node (pretty_printer *buffer, tree node, tree type,
dump_generic_ada_node
(buffer, DECL_NAME (type) ? type : TYPE_NAME (node), type,
- cpp_check, spc, 0, true);
+ spc, 0, true);
pp_string (buffer, " := ");
dump_generic_ada_node
(buffer,
TREE_CODE (TREE_VALUE (value)) == INTEGER_CST ?
TREE_VALUE (value) : DECL_INITIAL (TREE_VALUE (value)),
- node, cpp_check, spc, false, true);
+ node, spc, false, true);
}
}
}
@@ -1991,8 +1997,7 @@ dump_generic_ada_node (pretty_printer *buffer, tree node, tree type,
case REFERENCE_TYPE:
if (name_only && TYPE_NAME (node))
dump_generic_ada_node
- (buffer, TYPE_NAME (node), node, cpp_check,
- spc, limited_access, true);
+ (buffer, TYPE_NAME (node), node, spc, limited_access, true);
else if (TREE_CODE (TREE_TYPE (node)) == FUNCTION_TYPE)
{
@@ -2020,7 +2025,7 @@ dump_generic_ada_node (pretty_printer *buffer, tree node, tree type,
{
pp_string (buffer, " return ");
dump_generic_ada_node
- (buffer, TREE_TYPE (fnode), type, cpp_check, spc, 0, true);
+ (buffer, TREE_TYPE (fnode), type, spc, 0, true);
}
/* If we are dumping the full type, it means we are part of a
@@ -2031,7 +2036,7 @@ dump_generic_ada_node (pretty_printer *buffer, tree node, tree type,
newline_and_indent (buffer, spc);
pp_string (buffer, "pragma Convention (C, ");
dump_generic_ada_node
- (buffer, type, 0, cpp_check, spc, false, true);
+ (buffer, type, 0, spc, false, true);
pp_right_paren (buffer);
}
}
@@ -2158,11 +2163,11 @@ dump_generic_ada_node (pretty_printer *buffer, tree node, tree type,
&& type_name != NULL_TREE)
dump_generic_ada_node
(buffer, type_name,
- TREE_TYPE (node), cpp_check, spc, is_access, true);
+ TREE_TYPE (node), spc, is_access, true);
else
dump_generic_ada_node
(buffer, TREE_TYPE (node), TREE_TYPE (node),
- cpp_check, spc, 0, true);
+ spc, 0, true);
}
}
}
@@ -2171,8 +2176,7 @@ dump_generic_ada_node (pretty_printer *buffer, tree node, tree type,
case ARRAY_TYPE:
if (name_only)
dump_generic_ada_node
- (buffer, TYPE_NAME (node), node, cpp_check,
- spc, limited_access, true);
+ (buffer, TYPE_NAME (node), node, spc, limited_access, true);
else
dump_ada_array_type (buffer, node, spc);
break;
@@ -2184,8 +2188,7 @@ dump_generic_ada_node (pretty_printer *buffer, tree node, tree type,
{
if (TYPE_NAME (node))
dump_generic_ada_node
- (buffer, TYPE_NAME (node), node, cpp_check,
- spc, limited_access, true);
+ (buffer, TYPE_NAME (node), node, spc, limited_access, true);
else
{
pp_string (buffer, "anon_");
@@ -2193,8 +2196,7 @@ dump_generic_ada_node (pretty_printer *buffer, tree node, tree type,
}
}
else
- print_ada_struct_decl
- (buffer, node, type, cpp_check, spc, true);
+ print_ada_struct_decl (buffer, node, type, spc, true);
break;
case INTEGER_CST:
@@ -2287,12 +2289,11 @@ dump_generic_ada_node (pretty_printer *buffer, tree node, tree type,
pp_string (buffer, first ? "tagged limited " : " with ");
}
- else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (node))
- && TYPE_METHODS (TREE_TYPE (node)))
+ else if (has_nontrivial_methods (TREE_TYPE (node)))
pp_string (buffer, "limited ");
dump_generic_ada_node
- (buffer, TREE_TYPE (node), type, cpp_check, spc, false, false);
+ (buffer, TREE_TYPE (node), type, spc, false, false);
}
break;
@@ -2311,41 +2312,41 @@ dump_generic_ada_node (pretty_printer *buffer, tree node, tree type,
return 1;
}
-/* Dump in BUFFER NODE's methods. CPP_CHECK is used to perform C++ queries on
- nodes. SPC is the indentation level. */
+/* Dump in BUFFER NODE's methods. SPC is the indentation level. Return 1 if
+ methods were printed, 0 otherwise. */
-static void
-print_ada_methods (pretty_printer *buffer, tree node,
- int (*cpp_check)(tree, cpp_operation), int spc)
+static int
+print_ada_methods (pretty_printer *buffer, tree node, int spc)
{
- tree tmp = TYPE_METHODS (node);
int res = 1;
+ tree tmp;
- if (tmp)
- {
- pp_semicolon (buffer);
+ if (!has_nontrivial_methods (node))
+ return 0;
- for (; tmp; tmp = TREE_CHAIN (tmp))
+ pp_semicolon (buffer);
+
+ for (tmp = TYPE_METHODS (node); tmp; tmp = TREE_CHAIN (tmp))
+ {
+ if (res)
{
- if (res)
- {
- pp_newline (buffer);
- pp_newline (buffer);
- }
- res = print_ada_declaration (buffer, tmp, node, cpp_check, spc);
+ pp_newline (buffer);
+ pp_newline (buffer);
}
+ res = print_ada_declaration (buffer, tmp, node, spc);
}
+
+ return 1;
}
/* Dump in BUFFER anonymous types nested inside T's definition.
PARENT is the parent node of T.
FORWARD indicates whether a forward declaration of T should be generated.
- CPP_CHECK is used to perform C++ queries on
- nodes. SPC is the indentation level. */
+ SPC is the indentation level. */
static void
dump_nested_types (pretty_printer *buffer, tree t, tree parent, bool forward,
- int (*cpp_check)(tree, cpp_operation), int spc)
+ int spc)
{
tree field, outer, decl;
@@ -2363,8 +2364,7 @@ dump_nested_types (pretty_printer *buffer, tree t, tree parent, bool forward,
if (forward)
{
pp_string (buffer, "type ");
- dump_generic_ada_node
- (buffer, t, t, cpp_check, spc, false, true);
+ dump_generic_ada_node (buffer, t, t, spc, false, true);
pp_semicolon (buffer);
newline_and_indent (buffer, spc);
TREE_VISITED (t) = 1;
@@ -2406,8 +2406,7 @@ dump_nested_types (pretty_printer *buffer, tree t, tree parent, bool forward,
/* Generate forward declaration. */
pp_string (buffer, "type ");
- dump_generic_ada_node
- (buffer, decl, 0, cpp_check, spc, false, true);
+ dump_generic_ada_node (buffer, decl, 0, spc, false, true);
pp_semicolon (buffer);
newline_and_indent (buffer, spc);
@@ -2431,30 +2430,28 @@ dump_nested_types (pretty_printer *buffer, tree t, tree parent, bool forward,
case UNION_TYPE:
TREE_VISITED (t) = 1;
- dump_nested_types (buffer, field, t, false, cpp_check, spc);
+ dump_nested_types (buffer, field, t, false, spc);
pp_string (buffer, "type ");
if (TYPE_NAME (TREE_TYPE (field)))
{
dump_generic_ada_node
- (buffer, TYPE_NAME (TREE_TYPE (field)), 0, cpp_check,
- spc, false, true);
+ (buffer, TYPE_NAME (TREE_TYPE (field)), 0, spc, false,
+ true);
pp_string (buffer, " (discr : unsigned := 0) is ");
print_ada_struct_decl
- (buffer, TREE_TYPE (field), t, cpp_check, spc, false);
+ (buffer, TREE_TYPE (field), t, spc, false);
pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
dump_generic_ada_node
- (buffer, TREE_TYPE (field), 0, cpp_check,
- spc, false, true);
+ (buffer, TREE_TYPE (field), 0, spc, false, true);
pp_string (buffer, ");");
newline_and_indent (buffer, spc);
pp_string (buffer, "pragma Unchecked_Union (");
dump_generic_ada_node
- (buffer, TREE_TYPE (field), 0, cpp_check,
- spc, false, true);
+ (buffer, TREE_TYPE (field), 0, spc, false, true);
pp_string (buffer, ");");
}
else
@@ -2463,7 +2460,7 @@ dump_nested_types (pretty_printer *buffer, tree t, tree parent, bool forward,
(buffer, parent, field,
"_union (discr : unsigned := 0) is ");
print_ada_struct_decl
- (buffer, TREE_TYPE (field), t, cpp_check, spc, false);
+ (buffer, TREE_TYPE (field), t, spc, false);
pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
dump_ada_double_name (buffer, parent, field, "_union);");
newline_and_indent (buffer, spc);
@@ -2480,27 +2477,25 @@ dump_nested_types (pretty_printer *buffer, tree t, tree parent, bool forward,
{
pp_string (buffer, "type ");
dump_generic_ada_node
- (buffer, t, parent, 0, spc, false, true);
+ (buffer, t, parent, spc, false, true);
pp_semicolon (buffer);
newline_and_indent (buffer, spc);
}
TREE_VISITED (t) = 1;
- dump_nested_types (buffer, field, t, false, cpp_check, spc);
+ dump_nested_types (buffer, field, t, false, spc);
pp_string (buffer, "type ");
if (TYPE_NAME (TREE_TYPE (field)))
{
dump_generic_ada_node
- (buffer, TREE_TYPE (field), 0, cpp_check,
- spc, false, true);
+ (buffer, TREE_TYPE (field), 0, spc, false, true);
pp_string (buffer, " is ");
print_ada_struct_decl
- (buffer, TREE_TYPE (field), t, cpp_check, spc, false);
+ (buffer, TREE_TYPE (field), t, spc, false);
pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
dump_generic_ada_node
- (buffer, TREE_TYPE (field), 0, cpp_check,
- spc, false, true);
+ (buffer, TREE_TYPE (field), 0, spc, false, true);
pp_string (buffer, ");");
}
else
@@ -2508,7 +2503,7 @@ dump_nested_types (pretty_printer *buffer, tree t, tree parent, bool forward,
dump_ada_double_name
(buffer, parent, field, "_struct is ");
print_ada_struct_decl
- (buffer, TREE_TYPE (field), t, cpp_check, spc, false);
+ (buffer, TREE_TYPE (field), t, spc, false);
pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
dump_ada_double_name (buffer, parent, field, "_struct);");
}
@@ -2557,12 +2552,11 @@ type_name (tree t)
}
/* Print in BUFFER the declaration of a variable T of type TYPE in Ada syntax.
- CPP_CHECK is used to perform C++ queries on nodes. SPC is the indentation
- level. Return 1 if a declaration was printed, 0 otherwise. */
+ SPC is the indentation level. Return 1 if a declaration was printed,
+ 0 otherwise. */
static int
-print_ada_declaration (pretty_printer *buffer, tree t, tree type,
- int (*cpp_check)(tree, cpp_operation), int spc)
+print_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc)
{
int is_var = 0, need_indent = 0;
int is_class = false;
@@ -2571,7 +2565,7 @@ print_ada_declaration (pretty_printer *buffer, tree t, tree type,
tree orig = NULL_TREE;
if (cpp_check && cpp_check (t, IS_TEMPLATE))
- return dump_ada_template (buffer, t, cpp_check, spc);
+ return dump_ada_template (buffer, t, spc);
if (TREE_CODE (t) == CONST_DECL && TREE_CODE (TREE_TYPE (t)) == ENUMERAL_TYPE)
/* Skip enumeral values: will be handled as part of the type itself. */
@@ -2599,20 +2593,18 @@ print_ada_declaration (pretty_printer *buffer, tree t, tree type,
if (RECORD_OR_UNION_TYPE_P (typ) && !TYPE_FIELDS (typ))
{
pp_string (buffer, "-- skipped empty struct ");
- dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
+ dump_generic_ada_node (buffer, t, type, spc, false, true);
}
else
{
if (!TREE_VISITED (stub)
&& DECL_SOURCE_FILE (stub) == source_file_base)
- dump_nested_types
- (buffer, stub, stub, true, cpp_check, spc);
+ dump_nested_types (buffer, stub, stub, true, spc);
pp_string (buffer, "subtype ");
- dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
+ dump_generic_ada_node (buffer, t, type, spc, false, true);
pp_string (buffer, " is ");
- dump_generic_ada_node
- (buffer, typ, type, 0, spc, false, true);
+ dump_generic_ada_node (buffer, typ, type, spc, false, true);
pp_semicolon (buffer);
}
return 1;
@@ -2671,7 +2663,7 @@ print_ada_declaration (pretty_printer *buffer, tree t, tree type,
if (!TYPE_FIELDS (TREE_TYPE (t)))
{
pp_string (buffer, "-- skipped empty struct ");
- dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
+ dump_generic_ada_node (buffer, t, type, spc, false, true);
return 1;
}
@@ -2680,7 +2672,7 @@ print_ada_declaration (pretty_printer *buffer, tree t, tree type,
|| *IDENTIFIER_POINTER (decl_name) == '$'))
{
pp_string (buffer, "-- skipped anonymous struct ");
- dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
+ dump_generic_ada_node (buffer, t, type, spc, false, true);
TREE_VISITED (t) = 1;
return 1;
}
@@ -2689,14 +2681,13 @@ print_ada_declaration (pretty_printer *buffer, tree t, tree type,
pp_string (buffer, "subtype ");
else
{
- dump_nested_types (buffer, t, t, false, cpp_check, spc);
+ dump_nested_types (buffer, t, t, false, spc);
if (separate_class_package (t))
{
is_class = true;
pp_string (buffer, "package Class_");
- dump_generic_ada_node
- (buffer, t, type, 0, spc, false, true);
+ dump_generic_ada_node (buffer, t, type, spc, false, true);
pp_string (buffer, " is");
spc += INDENT_INCR;
newline_and_indent (buffer, spc);
@@ -2718,7 +2709,7 @@ print_ada_declaration (pretty_printer *buffer, tree t, tree type,
case FUNCTION_TYPE:
pp_string (buffer, "-- skipped function type ");
- dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
+ dump_generic_ada_node (buffer, t, type, spc, false, true);
return 1;
break;
@@ -2752,7 +2743,7 @@ print_ada_declaration (pretty_printer *buffer, tree t, tree type,
INDENT (spc);
/* Print variable's name. */
- dump_generic_ada_node (buffer, t, type, cpp_check, spc, false, true);
+ dump_generic_ada_node (buffer, t, type, spc, false, true);
if (TREE_CODE (t) == TYPE_DECL)
{
@@ -2760,8 +2751,7 @@ print_ada_declaration (pretty_printer *buffer, tree t, tree type,
if (orig && TYPE_NAME (orig) && orig != TREE_TYPE (t))
dump_generic_ada_node
- (buffer, TYPE_NAME (orig), type,
- cpp_check, spc, false, true);
+ (buffer, TYPE_NAME (orig), type, spc, false, true);
else
dump_ada_array_type (buffer, t, spc);
}
@@ -2780,7 +2770,7 @@ print_ada_declaration (pretty_printer *buffer, tree t, tree type,
&& TREE_CODE (tmp) != INTEGER_TYPE)
pp_string (buffer, "aliased ");
- dump_generic_ada_node (buffer, tmp, type, 0, spc, false, true);
+ dump_generic_ada_node (buffer, tmp, type, spc, false, true);
}
else
{
@@ -2795,7 +2785,8 @@ print_ada_declaration (pretty_printer *buffer, tree t, tree type,
}
else if (TREE_CODE (t) == FUNCTION_DECL)
{
- bool is_function = true, is_method, is_abstract_class = false;
+ bool is_function = true, is_abstract_class = false;
+ bool is_method = TREE_CODE (TREE_TYPE (t)) == METHOD_TYPE;
tree decl_name = DECL_NAME (t);
int prev_in_function = in_function;
bool is_abstract = false;
@@ -2852,7 +2843,6 @@ print_ada_declaration (pretty_printer *buffer, tree t, tree type,
pp_string (buffer, "function ");
in_function = is_function;
- is_method = TREE_CODE (TREE_TYPE (t)) == METHOD_TYPE;
if (is_destructor)
print_destructor (buffer, t);
@@ -2874,18 +2864,17 @@ print_ada_declaration (pretty_printer *buffer, tree t, tree type,
else
{
dump_generic_ada_node
- (buffer, TREE_TYPE (TREE_TYPE (t)), type, cpp_check,
- spc, false, true);
+ (buffer, TREE_TYPE (TREE_TYPE (t)), type, spc, false, true);
}
}
- if (is_constructor && cpp_check && type
- && AGGREGATE_TYPE_P (type)
+ if (is_constructor
+ && RECORD_OR_UNION_TYPE_P (type)
&& TYPE_METHODS (type))
{
- tree tmp = TYPE_METHODS (type);
+ tree tmp;
- for (; tmp; tmp = TREE_CHAIN (tmp))
+ for (tmp = TYPE_METHODS (type); tmp; tmp = TREE_CHAIN (tmp))
if (cpp_check (tmp, IS_ABSTRACT))
{
is_abstract_class = 1;
@@ -2937,8 +2926,7 @@ print_ada_declaration (pretty_printer *buffer, tree t, tree type,
INDENT (spc);
/* Anonymous structs/unions */
- dump_generic_ada_node
- (buffer, TREE_TYPE (t), t, cpp_check, spc, false, true);
+ dump_generic_ada_node (buffer, TREE_TYPE (t), t, spc, false, true);
if (TREE_CODE (TREE_TYPE (t)) == UNION_TYPE
|| TREE_CODE (TREE_TYPE (t)) == QUAL_UNION_TYPE)
@@ -2949,14 +2937,15 @@ print_ada_declaration (pretty_printer *buffer, tree t, tree type,
pp_string (buffer, " is ");
/* Check whether we have an Ada interface compatible class. */
- if (cpp_check && AGGREGATE_TYPE_P (TREE_TYPE (t))
+ if (cpp_check
+ && RECORD_OR_UNION_TYPE_P (TREE_TYPE (t))
&& TYPE_METHODS (TREE_TYPE (t)))
{
int num_fields = 0;
- tree tmp = TYPE_FIELDS (TREE_TYPE (t));
+ tree tmp;
/* Check that there are no fields other than the virtual table. */
- for (; tmp; tmp = TREE_CHAIN (tmp))
+ for (tmp = TYPE_FIELDS (TREE_TYPE (t)); tmp; tmp = TREE_CHAIN (tmp))
{
if (TREE_CODE (tmp) == TYPE_DECL)
continue;
@@ -2984,17 +2973,16 @@ print_ada_declaration (pretty_printer *buffer, tree t, tree type,
newline_and_indent (buffer, spc);
pp_string (buffer, "pragma Import (CPP, ");
dump_generic_ada_node
- (buffer, TYPE_NAME (TREE_TYPE (t)), type, cpp_check,
- spc, false, true);
+ (buffer, TYPE_NAME (TREE_TYPE (t)), type, spc, false, true);
pp_right_paren (buffer);
- print_ada_methods (buffer, TREE_TYPE (t), cpp_check, spc);
+ print_ada_methods (buffer, TREE_TYPE (t), spc);
}
else
{
if (is_abstract_record)
pp_string (buffer, "abstract ");
- dump_generic_ada_node (buffer, t, t, cpp_check, spc, false, false);
+ dump_generic_ada_node (buffer, t, t, spc, false, false);
}
}
else
@@ -3006,7 +2994,7 @@ print_ada_declaration (pretty_printer *buffer, tree t, tree type,
check_name (buffer, t);
/* Print variable/type's name. */
- dump_generic_ada_node (buffer, t, t, cpp_check, spc, false, true);
+ dump_generic_ada_node (buffer, t, t, spc, false, true);
if (TREE_CODE (t) == TYPE_DECL)
{
@@ -3020,8 +3008,7 @@ print_ada_declaration (pretty_printer *buffer, tree t, tree type,
pp_string (buffer, " is ");
- dump_generic_ada_node
- (buffer, orig, t, cpp_check, spc, false, is_subtype);
+ dump_generic_ada_node (buffer, orig, t, spc, false, is_subtype);
}
else
{
@@ -3043,7 +3030,7 @@ print_ada_declaration (pretty_printer *buffer, tree t, tree type,
pp_string (buffer, "aliased ");
dump_generic_ada_node
- (buffer, TREE_TYPE (t), t, cpp_check, spc, false, true);
+ (buffer, TREE_TYPE (t), t, spc, false, true);
}
else
{
@@ -3053,8 +3040,7 @@ print_ada_declaration (pretty_printer *buffer, tree t, tree type,
pp_string (buffer, "aliased ");
dump_generic_ada_node
- (buffer, TREE_TYPE (t), TREE_TYPE (t), cpp_check,
- spc, false, true);
+ (buffer, TREE_TYPE (t), TREE_TYPE (t), spc, false, true);
}
}
}
@@ -3066,7 +3052,7 @@ print_ada_declaration (pretty_printer *buffer, tree t, tree type,
pp_string (buffer, "end;");
newline_and_indent (buffer, spc);
pp_string (buffer, "use Class_");
- dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
+ dump_generic_ada_node (buffer, t, type, spc, false, true);
pp_semicolon (buffer);
pp_newline (buffer);
@@ -3089,18 +3075,16 @@ print_ada_declaration (pretty_printer *buffer, tree t, tree type,
}
/* Prints in BUFFER a structure NODE of type TYPE: name, fields, and methods
- with Ada syntax. CPP_CHECK is used to perform C++ queries on nodes. SPC
- is the indentation level. If DISPLAY_CONVENTION is true, also print the
- pragma Convention for NODE. */
+ with Ada syntax. SPC is the indentation level. If DISPLAY_CONVENTION is
+ true, also print the pragma Convention for NODE. */
static void
-print_ada_struct_decl (pretty_printer *buffer, tree node, tree type,
- int (*cpp_check)(tree, cpp_operation), int spc,
+print_ada_struct_decl (pretty_printer *buffer, tree node, tree type, int spc,
bool display_convention)
{
tree tmp;
- int is_union =
- TREE_CODE (node) == UNION_TYPE || TREE_CODE (node) == QUAL_UNION_TYPE;
+ const bool is_union
+ = TREE_CODE (node) == UNION_TYPE || TREE_CODE (node) == QUAL_UNION_TYPE;
char buf[32];
int field_num = 0;
int field_spc = spc + INDENT_INCR;
@@ -3134,8 +3118,7 @@ print_ada_struct_decl (pretty_printer *buffer, tree node, tree type,
if (!is_tagged_type (TREE_TYPE (tmp)))
{
if (!TYPE_NAME (TREE_TYPE (tmp)))
- print_ada_declaration
- (buffer, tmp, type, cpp_check, field_spc);
+ print_ada_declaration (buffer, tmp, type, field_spc);
else
{
INDENT (field_spc);
@@ -3179,8 +3162,7 @@ print_ada_struct_decl (pretty_printer *buffer, tree node, tree type,
pp_newline (buffer);
}
- if (print_ada_declaration (buffer,
- tmp, type, cpp_check, field_spc))
+ if (print_ada_declaration (buffer, tmp, type, field_spc))
{
pp_newline (buffer);
field_num++;
@@ -3214,7 +3196,7 @@ print_ada_struct_decl (pretty_printer *buffer, tree node, tree type,
if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type)))
{
- if (TYPE_METHODS (TREE_TYPE (type)))
+ if (has_nontrivial_methods (TREE_TYPE (type)))
pp_string (buffer, "pragma Import (CPP, ");
else
pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
@@ -3223,8 +3205,7 @@ print_ada_struct_decl (pretty_printer *buffer, tree node, tree type,
pp_string (buffer, "pragma Convention (C, ");
package_prefix = false;
- dump_generic_ada_node
- (buffer, TREE_TYPE (type), type, cpp_check, spc, false, true);
+ dump_generic_ada_node (buffer, TREE_TYPE (type), type, spc, false, true);
package_prefix = true;
pp_right_paren (buffer);
@@ -3234,8 +3215,7 @@ print_ada_struct_decl (pretty_printer *buffer, tree node, tree type,
newline_and_indent (buffer, spc);
pp_string (buffer, "pragma Unchecked_Union (");
- dump_generic_ada_node
- (buffer, TREE_TYPE (type), type, cpp_check, spc, false, true);
+ dump_generic_ada_node (buffer, TREE_TYPE (type), type, spc, false, true);
pp_right_paren (buffer);
}
@@ -3245,15 +3225,14 @@ print_ada_struct_decl (pretty_printer *buffer, tree node, tree type,
newline_and_indent (buffer, spc);
pp_string (buffer, "pragma Pack (");
dump_generic_ada_node
- (buffer, TREE_TYPE (type), type, cpp_check, spc, false, true);
+ (buffer, TREE_TYPE (type), type, spc, false, true);
pp_right_paren (buffer);
bitfield_used = false;
}
- print_ada_methods (buffer, node, cpp_check, spc);
+ need_semicolon = !print_ada_methods (buffer, node, spc);
/* Print the static fields of the structure, if any. */
- need_semicolon = TYPE_METHODS (node) == NULL_TREE;
for (tmp = TYPE_FIELDS (node); tmp; tmp = TREE_CHAIN (tmp))
{
if (DECL_NAME (tmp) && TREE_STATIC (tmp))
@@ -3265,20 +3244,19 @@ print_ada_struct_decl (pretty_printer *buffer, tree node, tree type,
}
pp_newline (buffer);
pp_newline (buffer);
- print_ada_declaration (buffer, tmp, type, cpp_check, spc);
+ print_ada_declaration (buffer, tmp, type, spc);
}
}
}
/* Dump all the declarations in SOURCE_FILE to an Ada spec.
COLLECT_ALL_REFS is a front-end callback used to collect all relevant
- nodes for SOURCE_FILE. CPP_CHECK is used to perform C++ queries on
- nodes. */
+ nodes for SOURCE_FILE. CHECK is used to perform C++ queries on nodes. */
static void
dump_ads (const char *source_file,
void (*collect_all_refs)(const char *),
- int (*cpp_check)(tree, cpp_operation))
+ int (*check)(const_tree, cpp_operation))
{
char *ads_name;
char *pkg_name;
@@ -3316,7 +3294,8 @@ dump_ads (const char *source_file,
(*collect_all_refs) (source_file);
/* Dump all references. */
- dump_ada_nodes (&pp, source_file, cpp_check);
+ cpp_check = check;
+ dump_ada_nodes (&pp, source_file);
/* Requires Ada 2005 syntax, so generate corresponding pragma.
Also, disable style checks since this file is auto-generated. */
@@ -3370,21 +3349,21 @@ collect_source_ref (const char *filename)
}
/* Main entry point: dump all Ada specs corresponding to SOURCE_REFS
- using callbacks COLLECT_ALL_REFS and CPP_CHECK.
+ using callbacks COLLECT_ALL_REFS and CHECK.
COLLECT_ALL_REFS is a front-end callback used to collect all relevant
nodes for a given source file.
- CPP_CHECK is used to perform C++ queries on nodes, or NULL for the C
+ CHECK is used to perform C++ queries on nodes, or NULL for the C
front-end. */
void
dump_ada_specs (void (*collect_all_refs)(const char *),
- int (*cpp_check)(tree, cpp_operation))
+ int (*check)(const_tree, cpp_operation))
{
int i;
/* Iterate over the list of files to dump specs for */
for (i = 0; i < source_refs_used; i++)
- dump_ads (source_refs[i], collect_all_refs, cpp_check);
+ dump_ads (source_refs[i], collect_all_refs, check);
/* Free files table. */
free (source_refs);
diff --git a/gcc/c-family/c-ada-spec.h b/gcc/c-family/c-ada-spec.h
index 0bc249f8fe5..64f0ecd4b22 100644
--- a/gcc/c-family/c-ada-spec.h
+++ b/gcc/c-family/c-ada-spec.h
@@ -29,13 +29,14 @@ typedef enum {
IS_CONSTRUCTOR,
IS_DESTRUCTOR,
IS_COPY_CONSTRUCTOR,
- IS_TEMPLATE
+ IS_TEMPLATE,
+ IS_TRIVIAL
} cpp_operation;
extern location_t decl_sloc (const_tree, bool);
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));
+ int (*)(const_tree, cpp_operation));
#endif /* ! C_ADA_SPEC_H */
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 8ecb70cfa7c..93481b93027 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -39,7 +39,6 @@ along with GCC; see the file COPYING3. If not see
#include "diagnostic.h"
#include "tree-iterator.h"
#include "hashtab.h"
-#include "tree-mudflap.h"
#include "opts.h"
#include "cgraph.h"
#include "target-def.h"
@@ -371,6 +370,13 @@ static tree ignore_attribute (tree *, tree, tree, int, bool *);
static tree handle_no_split_stack_attribute (tree *, tree, tree, int, bool *);
static tree handle_fnspec_attribute (tree *, tree, tree, int, bool *);
static tree handle_warn_unused_attribute (tree *, tree, tree, int, bool *);
+static tree handle_returns_nonnull_attribute (tree *, tree, tree, int, bool *);
+static tree handle_omp_declare_simd_attribute (tree *, tree, tree, int,
+ bool *);
+static tree handle_omp_declare_target_attribute (tree *, tree, tree, int,
+ bool *);
+static tree handle_bnd_variable_size_attribute (tree *, tree, tree, int, bool *);
+static tree handle_bnd_legacy (tree *, tree, tree, int, bool *);
static void check_function_nonnull (tree, int, tree *);
static void check_nonnull_arg (void *, tree, unsigned HOST_WIDE_INT);
@@ -403,8 +409,11 @@ 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 },
+ { "_Cilk_spawn", RID_CILK_SPAWN, 0 },
+ { "_Cilk_sync", RID_CILK_SYNC, 0 },
{ "_Imaginary", RID_IMAGINARY, D_CONLY },
{ "_Decimal32", RID_DFLOAT32, D_CONLY | D_EXT },
{ "_Decimal64", RID_DFLOAT64, D_CONLY | D_EXT },
@@ -747,6 +756,16 @@ const struct attribute_spec c_common_attribute_table[] =
handle_fnspec_attribute, false },
{ "warn_unused", 0, 0, false, false, false,
handle_warn_unused_attribute, false },
+ { "returns_nonnull", 0, 0, false, true, true,
+ handle_returns_nonnull_attribute, false },
+ { "omp declare simd", 0, -1, true, false, false,
+ handle_omp_declare_simd_attribute, false },
+ { "omp declare target", 0, 0, true, false, false,
+ handle_omp_declare_target_attribute, false },
+ { "bnd_variable_size", 0, 0, true, false, false,
+ handle_bnd_variable_size_attribute, false },
+ { "bnd_legacy", 0, 0, true, false, false,
+ handle_bnd_legacy, false },
{ NULL, 0, 0, false, false, false, NULL, false }
};
@@ -5054,6 +5073,7 @@ enum c_builtin_type
#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_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,
@@ -5072,6 +5092,7 @@ enum c_builtin_type
#undef DEF_FUNCTION_TYPE_5
#undef DEF_FUNCTION_TYPE_6
#undef DEF_FUNCTION_TYPE_7
+#undef DEF_FUNCTION_TYPE_8
#undef DEF_FUNCTION_TYPE_VAR_0
#undef DEF_FUNCTION_TYPE_VAR_1
#undef DEF_FUNCTION_TYPE_VAR_2
@@ -5154,6 +5175,10 @@ c_define_builtins (tree va_list_ref_type_node, tree va_list_arg_type_node)
#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_VAR_0(ENUM, RETURN) \
def_fn_type (ENUM, RETURN, 1, 0);
#define DEF_FUNCTION_TYPE_VAR_1(ENUM, RETURN, ARG1) \
@@ -5204,8 +5229,8 @@ c_define_builtins (tree va_list_ref_type_node, tree va_list_arg_type_node)
build_common_builtin_nodes ();
- if (flag_mudflap)
- mudflap_init ();
+ if (flag_enable_cilkplus)
+ cilk_init_builtins ();
}
/* Like get_identifier, but avoid warnings about null arguments when
@@ -8000,6 +8025,38 @@ handle_fnspec_attribute (tree *node ATTRIBUTE_UNUSED, tree ARG_UNUSED (name),
return NULL_TREE;
}
+/* Handle a "bnd_variable_size" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_bnd_variable_size_attribute (tree *node, tree name, tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags), bool *no_add_attrs)
+{
+ if (TREE_CODE (*node) != FIELD_DECL)
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
+/* Handle a "bnd_legacy" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_bnd_legacy (tree *node, tree name, tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags), bool *no_add_attrs)
+{
+ if (TREE_CODE (*node) != FUNCTION_DECL)
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
/* Handle a "warn_unused" attribute; arguments as in
struct attribute_spec.handler. */
@@ -8021,6 +8078,24 @@ handle_warn_unused_attribute (tree *node, tree name,
return NULL_TREE;
}
+/* Handle an "omp declare simd" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_omp_declare_simd_attribute (tree *, tree, tree, int, bool *)
+{
+ return NULL_TREE;
+}
+
+/* Handle an "omp declare target" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_omp_declare_target_attribute (tree *, tree, tree, int, bool *)
+{
+ return NULL_TREE;
+}
+
/* Handle a "returns_twice" attribute; arguments as in
struct attribute_spec.handler. */
@@ -9014,7 +9089,7 @@ handle_optimize_attribute (tree *node, tree name, tree args,
/* Parse options, and update the vector. */
parse_optimize_options (args, true);
DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node)
- = build_optimization_node ();
+ = build_optimization_node (&global_options);
/* Restore current options. */
cl_optimization_restore (&global_options, &cur_opts);
@@ -9048,6 +9123,23 @@ handle_no_split_stack_attribute (tree *node, tree name,
return NULL_TREE;
}
+
+/* Handle a "returns_nonnull" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_returns_nonnull_attribute (tree *node, tree, tree, int,
+ bool *no_add_attrs)
+{
+ // Even without a prototype we still have a return type we can check.
+ if (TREE_CODE (TREE_TYPE (*node)) != POINTER_TYPE)
+ {
+ error ("returns_nonnull attribute on a function not returning a pointer");
+ *no_add_attrs = true;
+ }
+ return NULL_TREE;
+}
+
/* Check for valid arguments being passed to a function with FNTYPE.
There are NARGS arguments in the array ARGARRAY. */
@@ -9474,6 +9566,7 @@ static const struct reason_option_codes_t option_codes[] = {
{CPP_W_INVALID_PCH, OPT_Winvalid_pch},
{CPP_W_WARNING_DIRECTIVE, OPT_Wcpp},
{CPP_W_LITERAL_SUFFIX, OPT_Wliteral_suffix},
+ {CPP_W_DATE_TIME, OPT_Wdate_time},
{CPP_W_NONE, 0}
};
@@ -9843,6 +9936,11 @@ invalid_indirection_error (location_t loc, tree type, ref_operator errstring)
"invalid type argument of %<->%> (have %qT)",
type);
break;
+ case RO_ARROW_STAR:
+ error_at (loc,
+ "invalid type argument of %<->*%> (have %qT)",
+ type);
+ break;
case RO_IMPLICIT_CONVERSION:
error_at (loc,
"invalid type argument of implicit conversion (have %qT)",
@@ -10075,6 +10173,7 @@ sync_resolve_params (location_t loc, tree orig_function, tree function,
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. */
@@ -10304,6 +10403,27 @@ add_atomic_size_parameter (unsigned n, location_t loc, tree function,
}
+/* 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.
@@ -10329,7 +10449,7 @@ resolve_overloaded_atomic_exchange (location_t loc, tree function,
}
/* If not a lock-free size, change to the library generic format. */
- if (n != 1 && n != 2 && n != 4 && n != 8 && n != 16)
+ if (!atomic_size_supported_p (n))
{
*new_return = add_atomic_size_parameter (n, loc, function, params);
return true;
@@ -10394,7 +10514,7 @@ resolve_overloaded_atomic_compare_exchange (location_t loc, tree function,
}
/* If not a lock-free size, change to the library generic format. */
- if (n != 1 && n != 2 && n != 4 && n != 8 && n != 16)
+ 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,
@@ -10470,7 +10590,7 @@ resolve_overloaded_atomic_load (location_t loc, tree function,
}
/* If not a lock-free size, change to the library generic format. */
- if (n != 1 && n != 2 && n != 4 && n != 8 && n != 16)
+ if (!atomic_size_supported_p (n))
{
*new_return = add_atomic_size_parameter (n, loc, function, params);
return true;
@@ -10530,7 +10650,7 @@ resolve_overloaded_atomic_store (location_t loc, tree function,
}
/* If not a lock-free size, change to the library generic format. */
- if (n != 1 && n != 2 && n != 4 && n != 8 && n != 16)
+ if (!atomic_size_supported_p (n))
{
*new_return = add_atomic_size_parameter (n, loc, function, params);
return true;
@@ -11471,6 +11591,7 @@ keyword_is_type_qualifier (enum rid keyword)
case RID_CONST:
case RID_VOLATILE:
case RID_RESTRICT:
+ case RID_ATOMIC:
return true;
default:
return false;
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 722ba6e5c15..74fd59fb5ee 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -66,7 +66,7 @@ enum rid
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_NORETURN, RID_ATOMIC,
/* C extensions */
RID_COMPLEX, RID_THREAD, RID_SAT,
@@ -148,6 +148,9 @@ enum rid
/* C++11 */
RID_CONSTEXPR, RID_DECLTYPE, RID_NOEXCEPT, RID_NULLPTR, RID_STATIC_ASSERT,
+ /* Cilk Plus keywords. */
+ RID_CILK_SPAWN, RID_CILK_SYNC,
+
/* Objective-C ("AT" reserved words - they are only keywords when
they follow '@') */
RID_AT_ENCODE, RID_AT_END,
@@ -1034,17 +1037,166 @@ extern void pp_dir_change (cpp_reader *, const char *);
extern bool check_missing_format_attribute (tree, tree);
/* In c-omp.c */
+#if HOST_BITS_PER_WIDE_INT >= 64
+typedef unsigned HOST_WIDE_INT omp_clause_mask;
+# define OMP_CLAUSE_MASK_1 ((omp_clause_mask) 1)
+#else
+struct omp_clause_mask
+{
+ inline omp_clause_mask ();
+ inline omp_clause_mask (unsigned HOST_WIDE_INT l);
+ inline omp_clause_mask (unsigned HOST_WIDE_INT l,
+ unsigned HOST_WIDE_INT h);
+ inline omp_clause_mask &operator &= (omp_clause_mask);
+ inline omp_clause_mask &operator |= (omp_clause_mask);
+ inline omp_clause_mask operator ~ () const;
+ inline omp_clause_mask operator & (omp_clause_mask) const;
+ inline omp_clause_mask operator | (omp_clause_mask) const;
+ inline omp_clause_mask operator >> (int);
+ inline omp_clause_mask operator << (int);
+ inline bool operator == (omp_clause_mask) const;
+ inline bool operator != (omp_clause_mask) const;
+ unsigned HOST_WIDE_INT low, high;
+};
+
+inline
+omp_clause_mask::omp_clause_mask ()
+{
+}
+
+inline
+omp_clause_mask::omp_clause_mask (unsigned HOST_WIDE_INT l)
+: low (l), high (0)
+{
+}
+
+inline
+omp_clause_mask::omp_clause_mask (unsigned HOST_WIDE_INT l,
+ unsigned HOST_WIDE_INT h)
+: low (l), high (h)
+{
+}
+
+inline omp_clause_mask &
+omp_clause_mask::operator &= (omp_clause_mask b)
+{
+ low &= b.low;
+ high &= b.high;
+ return *this;
+}
+
+inline omp_clause_mask &
+omp_clause_mask::operator |= (omp_clause_mask b)
+{
+ low |= b.low;
+ high |= b.high;
+ return *this;
+}
+
+inline omp_clause_mask
+omp_clause_mask::operator ~ () const
+{
+ omp_clause_mask ret (~low, ~high);
+ return ret;
+}
+
+inline omp_clause_mask
+omp_clause_mask::operator | (omp_clause_mask b) const
+{
+ omp_clause_mask ret (low | b.low, high | b.high);
+ return ret;
+}
+
+inline omp_clause_mask
+omp_clause_mask::operator & (omp_clause_mask b) const
+{
+ omp_clause_mask ret (low & b.low, high & b.high);
+ return ret;
+}
+
+inline omp_clause_mask
+omp_clause_mask::operator << (int amount)
+{
+ omp_clause_mask ret;
+ if (amount >= HOST_BITS_PER_WIDE_INT)
+ {
+ ret.low = 0;
+ ret.high = low << (amount - HOST_BITS_PER_WIDE_INT);
+ }
+ else if (amount == 0)
+ ret = *this;
+ else
+ {
+ ret.low = low << amount;
+ ret.high = (low >> (HOST_BITS_PER_WIDE_INT - amount))
+ | (high << amount);
+ }
+ return ret;
+}
+
+inline omp_clause_mask
+omp_clause_mask::operator >> (int amount)
+{
+ omp_clause_mask ret;
+ if (amount >= HOST_BITS_PER_WIDE_INT)
+ {
+ ret.low = high >> (amount - HOST_BITS_PER_WIDE_INT);
+ ret.high = 0;
+ }
+ else if (amount == 0)
+ ret = *this;
+ else
+ {
+ ret.low = (high << (HOST_BITS_PER_WIDE_INT - amount))
+ | (low >> amount);
+ ret.high = high >> amount;
+ }
+ return ret;
+}
+
+inline bool
+omp_clause_mask::operator == (omp_clause_mask b) const
+{
+ return low == b.low && high == b.high;
+}
+
+inline bool
+omp_clause_mask::operator != (omp_clause_mask b) const
+{
+ return low != b.low || high != b.high;
+}
+
+# define OMP_CLAUSE_MASK_1 omp_clause_mask (1)
+#endif
+
+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
+};
+
extern tree c_finish_omp_master (location_t, tree);
+extern tree c_finish_omp_taskgroup (location_t, tree);
extern tree c_finish_omp_critical (location_t, tree, tree);
extern tree c_finish_omp_ordered (location_t, tree);
extern void c_finish_omp_barrier (location_t);
extern tree c_finish_omp_atomic (location_t, enum tree_code, enum tree_code,
- tree, tree, tree, tree, tree);
+ tree, tree, tree, tree, tree, bool, bool);
extern void c_finish_omp_flush (location_t);
extern void c_finish_omp_taskwait (location_t);
extern void c_finish_omp_taskyield (location_t);
-extern tree c_finish_omp_for (location_t, tree, tree, tree, tree, tree, tree);
-extern void c_split_parallel_clauses (location_t, tree, tree *, tree *);
+extern tree c_finish_omp_for (location_t, enum tree_code, tree, tree, tree,
+ tree, tree, tree);
+extern void c_omp_split_clauses (location_t, enum tree_code, omp_clause_mask,
+ 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 enum omp_clause_default_kind c_omp_predetermined_sharing (tree);
/* Not in c-omp.c; provided by the front end. */
@@ -1207,4 +1359,18 @@ extern void cilkplus_extract_an_triplets (vec<tree, va_gc> *, size_t, size_t,
vec<vec<an_parts> > *);
extern vec <tree, va_gc> *fix_sec_implicit_args
(location_t, vec <tree, va_gc> *, vec<an_loop_parts>, size_t, tree);
+
+/* In cilk.c. */
+extern tree insert_cilk_frame (tree);
+extern void cilk_init_builtins (void);
+extern int gimplify_cilk_spawn (tree *, gimple_seq *, gimple_seq *);
+extern void c_cilk_install_body_w_frame_cleanup (tree, tree);
+extern bool cilk_detect_spawn_and_unwrap (tree *);
+extern bool cilk_set_spawn_marker (location_t, tree);
+extern tree build_cilk_sync (void);
+extern tree build_cilk_spawn (location_t, tree);
+extern tree make_cilk_frame (tree);
+extern tree create_cilk_function_exit (tree, bool, bool);
+extern tree cilk_install_body_pedigree_operations (tree);
+
#endif /* ! GCC_C_COMMON_H */
diff --git a/gcc/c-family/c-cppbuiltin.c b/gcc/c-family/c-cppbuiltin.c
index 94078c00460..b9a0f18cd7e 100644
--- a/gcc/c-family/c-cppbuiltin.c
+++ b/gcc/c-family/c-cppbuiltin.c
@@ -683,6 +683,95 @@ cpp_atomic_builtins (cpp_reader *pfile)
(have_swap[psize]? 2 : 1));
}
+/* 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 unpredictable
+ excess precision to mean lack of IEEE 754 support. The same
+ applies to unpredictable contraction. For C++, and outside
+ strict conformance mode, do not consider these options to mean
+ lack of IEEE 754 support. */
+ if (flag_iso
+ && !c_dialect_cxx ()
+ && TARGET_FLT_EVAL_METHOD != 0
+ && flag_excess_precision_cmdline != EXCESS_PRECISION_STANDARD)
+ 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;
+}
+
/* Hook that registers front end and target-specific built-ins. */
void
c_cpp_builtins (cpp_reader *pfile)
@@ -760,6 +849,13 @@ c_cpp_builtins (cpp_reader *pfile)
/* stdint.h and the testsuite need to know these. */
builtin_define_stdint_macros ();
+ /* Provide information for library headers to determine whether to
+ define macros such as __STDC_IEC_559__ and
+ __STDC_IEC_559_COMPLEX__. */
+ builtin_define_with_int_value ("__GCC_IEC_559", cpp_iec_559_value ());
+ builtin_define_with_int_value ("__GCC_IEC_559_COMPLEX",
+ cpp_iec_559_complex_value ());
+
/* float.h needs to know this. */
builtin_define_with_int_value ("__FLT_EVAL_METHOD__",
TARGET_FLT_EVAL_METHOD);
@@ -896,7 +992,7 @@ c_cpp_builtins (cpp_reader *pfile)
cpp_define (pfile, "__SSP__=1");
if (flag_openmp)
- cpp_define (pfile, "_OPENMP=201107");
+ cpp_define (pfile, "_OPENMP=201307");
if (int128_integer_type_node != NULL_TREE)
builtin_define_type_sizeof ("__SIZEOF_INT128__",
diff --git a/gcc/c-family/c-format.c b/gcc/c-family/c-format.c
index c11d93aa89d..99cae172a5b 100644
--- a/gcc/c-family/c-format.c
+++ b/gcc/c-family/c-format.c
@@ -721,7 +721,7 @@ static const format_char_info gcc_cxxdiag_char_table[] =
/* Custom conversion specifiers. */
/* These will require a "tree" at runtime. */
- { "ADEFKSTV",0,STD_C89,{ T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+#", "", NULL },
+ { "ADEFKSTVX",0,STD_C89,{ T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+#", "", NULL },
{ "v", 0,STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q#", "", NULL },
@@ -2374,6 +2374,7 @@ check_format_types (format_wanted_type *types)
&& pedantic
&& (TYPE_READONLY (cur_type)
|| TYPE_VOLATILE (cur_type)
+ || TYPE_ATOMIC (cur_type)
|| TYPE_RESTRICT (cur_type)))
warning (OPT_Wformat_, "extra type qualifiers in format "
"argument (argument %d)",
diff --git a/gcc/c-family/c-gimplify.c b/gcc/c-family/c-gimplify.c
index 3ff0a31cb23..2a4f633ad4f 100644
--- a/gcc/c-family/c-gimplify.c
+++ b/gcc/c-family/c-gimplify.c
@@ -98,7 +98,7 @@ c_genericize (tree fndecl)
/* Dump all nested functions now. */
cgn = cgraph_get_create_node (fndecl);
for (cgn = cgn->nested; cgn ; cgn = cgn->next_nested)
- c_genericize (cgn->symbol.decl);
+ c_genericize (cgn->decl);
}
static void
diff --git a/gcc/c-family/c-lex.c b/gcc/c-family/c-lex.c
index 819e9d51e10..6484352f4c6 100644
--- a/gcc/c-family/c-lex.c
+++ b/gcc/c-family/c-lex.c
@@ -595,12 +595,10 @@ interpret_integer (const cpp_token *token, unsigned int flags,
tree value, type;
enum integer_type_kind itk;
cpp_num integer;
- cpp_options *options = cpp_get_options (parse_in);
*overflow = OT_NONE;
integer = cpp_interpret_integer (parse_in, token, flags);
- integer = cpp_num_sign_extend (integer, options->precision);
if (integer.overflow)
*overflow = OT_OVERFLOW;
@@ -776,8 +774,19 @@ interpret_float (const cpp_token *token, unsigned int flags,
}
copy = (char *) alloca (copylen + 1);
- memcpy (copy, token->val.str.text, copylen);
- copy[copylen] = '\0';
+ if (cxx_dialect > cxx11)
+ {
+ 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)
diff --git a/gcc/c-family/c-omp.c b/gcc/c-family/c-omp.c
index f05b60a4035..f001a75cd22 100644
--- a/gcc/c-family/c-omp.c
+++ b/gcc/c-family/c-omp.c
@@ -26,6 +26,7 @@ along with GCC; see the file COPYING3. If not see
#include "coretypes.h"
#include "tree.h"
#include "c-common.h"
+#include "c-pragma.h"
#include "gimple.h" /* For create_tmp_var_raw. */
#include "langhooks.h"
@@ -41,6 +42,17 @@ c_finish_omp_master (location_t loc, tree stmt)
return t;
}
+/* Complete a #pragma omp taskgroup construct. STMT is the structured-block
+ that follows the pragma. LOC is the l*/
+
+tree
+c_finish_omp_taskgroup (location_t loc, tree stmt)
+{
+ tree t = add_stmt (build1 (OMP_TASKGROUP, void_type_node, stmt));
+ SET_EXPR_LOCATION (t, loc);
+ return t;
+}
+
/* Complete a #pragma omp critical construct. STMT is the structured-block
that follows the pragma, NAME is the identifier in the pragma, or null
if it was omitted. LOC is the location of the #pragma. */
@@ -122,7 +134,7 @@ c_finish_omp_taskyield (location_t loc)
tree
c_finish_omp_atomic (location_t loc, enum tree_code code,
enum tree_code opcode, tree lhs, tree rhs,
- tree v, tree lhs1, tree rhs1)
+ tree v, tree lhs1, tree rhs1, bool swapped, bool seq_cst)
{
tree x, type, addr;
@@ -168,6 +180,7 @@ c_finish_omp_atomic (location_t loc, enum tree_code code,
{
x = build1 (OMP_ATOMIC_READ, type, addr);
SET_EXPR_LOCATION (x, loc);
+ OMP_ATOMIC_SEQ_CST (x) = seq_cst;
return build_modify_expr (loc, v, NULL_TREE, NOP_EXPR,
loc, x, NULL_TREE);
return x;
@@ -176,8 +189,12 @@ c_finish_omp_atomic (location_t loc, enum tree_code code,
/* There are lots of warnings, errors, and conversions that need to happen
in the course of interpreting a statement. Use the normal mechanisms
to do this, and then take it apart again. */
- x = build_modify_expr (input_location, lhs, NULL_TREE, opcode,
- input_location, rhs, NULL_TREE);
+ if (swapped)
+ {
+ rhs = build2_loc (loc, opcode, TREE_TYPE (lhs), rhs, lhs);
+ opcode = NOP_EXPR;
+ }
+ x = build_modify_expr (loc, lhs, NULL_TREE, opcode, loc, rhs, NULL_TREE);
if (x == error_mark_node)
return error_mark_node;
gcc_assert (TREE_CODE (x) == MODIFY_EXPR);
@@ -188,6 +205,7 @@ c_finish_omp_atomic (location_t loc, enum tree_code code,
type = void_type_node;
x = build2 (code, type, addr, rhs);
SET_EXPR_LOCATION (x, loc);
+ OMP_ATOMIC_SEQ_CST (x) = seq_cst;
/* Generally it is hard to prove lhs1 and lhs are the same memory
location, just diagnose different variables. */
@@ -339,8 +357,8 @@ check_omp_for_incr_expr (location_t loc, tree exp, tree decl)
the loop. */
tree
-c_finish_omp_for (location_t locus, tree declv, tree initv, tree condv,
- tree incrv, tree body, tree pre_body)
+c_finish_omp_for (location_t locus, enum tree_code code, tree declv,
+ tree initv, tree condv, tree incrv, tree body, tree pre_body)
{
location_t elocus;
bool fail = false;
@@ -565,7 +583,7 @@ c_finish_omp_for (location_t locus, tree declv, tree initv, tree condv,
return NULL;
else
{
- tree t = make_node (OMP_FOR);
+ tree t = make_node (code);
TREE_TYPE (t) = void_type_node;
OMP_FOR_INIT (t) = initv;
@@ -579,21 +597,55 @@ c_finish_omp_for (location_t locus, tree declv, tree initv, tree condv,
}
}
-
-/* Divide CLAUSES into two lists: those that apply to a parallel
- construct, and those that apply to a work-sharing construct. Place
- the results in *PAR_CLAUSES and *WS_CLAUSES respectively. In
- addition, add a nowait clause to the work-sharing list. LOC is the
- location of the OMP_PARALLEL*. */
+/* Right now we have 14 different combined constructs, this
+ function attempts to split or duplicate clauses for combined
+ constructs. CODE is the innermost construct in the combined construct,
+ and MASK allows to determine which constructs are combined together,
+ as every construct has at least one clause that no other construct
+ has (except for OMP_SECTIONS, but that can be only combined with parallel).
+ Combined constructs are:
+ #pragma omp parallel for
+ #pragma omp parallel sections
+ #pragma omp parallel for simd
+ #pragma omp for simd
+ #pragma omp distribute simd
+ #pragma omp distribute parallel for
+ #pragma omp distribute parallel for simd
+ #pragma omp teams distribute
+ #pragma omp teams distribute parallel for
+ #pragma omp teams distribute parallel for simd
+ #pragma omp target teams
+ #pragma omp target teams distribute
+ #pragma omp target teams distribute parallel for
+ #pragma omp target teams distribute parallel for simd */
void
-c_split_parallel_clauses (location_t loc, tree clauses,
- tree *par_clauses, tree *ws_clauses)
+c_omp_split_clauses (location_t loc, enum tree_code code,
+ omp_clause_mask mask, tree clauses, tree *cclauses)
{
- tree next;
+ tree next, c;
+ enum c_omp_clause_split s;
+ int i;
- *par_clauses = NULL;
- *ws_clauses = build_omp_clause (loc, OMP_CLAUSE_NOWAIT);
+ for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++)
+ cclauses[i] = NULL;
+ /* Add implicit nowait clause on
+ #pragma omp parallel {for,for simd,sections}. */
+ if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0)
+ switch (code)
+ {
+ case OMP_FOR:
+ case OMP_SIMD:
+ cclauses[C_OMP_CLAUSE_SPLIT_FOR]
+ = build_omp_clause (loc, OMP_CLAUSE_NOWAIT);
+ break;
+ case OMP_SECTIONS:
+ cclauses[C_OMP_CLAUSE_SPLIT_SECTIONS]
+ = build_omp_clause (loc, OMP_CLAUSE_NOWAIT);
+ break;
+ default:
+ break;
+ }
for (; clauses ; clauses = next)
{
@@ -601,32 +653,333 @@ c_split_parallel_clauses (location_t loc, tree clauses,
switch (OMP_CLAUSE_CODE (clauses))
{
- case OMP_CLAUSE_PRIVATE:
- case OMP_CLAUSE_SHARED:
- case OMP_CLAUSE_FIRSTPRIVATE:
- case OMP_CLAUSE_LASTPRIVATE:
- case OMP_CLAUSE_REDUCTION:
+ /* First the clauses that are unique to some constructs. */
+ case OMP_CLAUSE_DEVICE:
+ case OMP_CLAUSE_MAP:
+ s = C_OMP_CLAUSE_SPLIT_TARGET;
+ break;
+ case OMP_CLAUSE_NUM_TEAMS:
+ case OMP_CLAUSE_THREAD_LIMIT:
+ s = C_OMP_CLAUSE_SPLIT_TEAMS;
+ break;
+ case OMP_CLAUSE_DIST_SCHEDULE:
+ s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
+ break;
case OMP_CLAUSE_COPYIN:
- case OMP_CLAUSE_IF:
case OMP_CLAUSE_NUM_THREADS:
- case OMP_CLAUSE_DEFAULT:
- OMP_CLAUSE_CHAIN (clauses) = *par_clauses;
- *par_clauses = clauses;
+ case OMP_CLAUSE_PROC_BIND:
+ s = C_OMP_CLAUSE_SPLIT_PARALLEL;
break;
-
- case OMP_CLAUSE_SCHEDULE:
case OMP_CLAUSE_ORDERED:
+ case OMP_CLAUSE_SCHEDULE:
+ case OMP_CLAUSE_NOWAIT:
+ s = C_OMP_CLAUSE_SPLIT_FOR;
+ break;
+ case OMP_CLAUSE_SAFELEN:
+ case OMP_CLAUSE_LINEAR:
+ case OMP_CLAUSE_ALIGNED:
+ s = C_OMP_CLAUSE_SPLIT_SIMD;
+ break;
+ /* Duplicate this to all of distribute, for and simd. */
case OMP_CLAUSE_COLLAPSE:
- OMP_CLAUSE_CHAIN (clauses) = *ws_clauses;
- *ws_clauses = clauses;
+ if (code == OMP_SIMD)
+ {
+ c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
+ OMP_CLAUSE_COLLAPSE);
+ OMP_CLAUSE_COLLAPSE_EXPR (c)
+ = OMP_CLAUSE_COLLAPSE_EXPR (clauses);
+ OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
+ cclauses[C_OMP_CLAUSE_SPLIT_SIMD] = c;
+ }
+ if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0)
+ {
+ if ((mask & (OMP_CLAUSE_MASK_1
+ << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0)
+ {
+ c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
+ OMP_CLAUSE_COLLAPSE);
+ OMP_CLAUSE_COLLAPSE_EXPR (c)
+ = OMP_CLAUSE_COLLAPSE_EXPR (clauses);
+ OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
+ cclauses[C_OMP_CLAUSE_SPLIT_FOR] = c;
+ s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
+ }
+ else
+ s = C_OMP_CLAUSE_SPLIT_FOR;
+ }
+ else
+ s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
+ break;
+ /* Private clause is supported on all constructs but target,
+ it is enough to put it on the innermost one. For
+ #pragma omp {for,sections} put it on parallel though,
+ as that's what we did for OpenMP 3.1. */
+ case OMP_CLAUSE_PRIVATE:
+ switch (code)
+ {
+ case OMP_SIMD: s = C_OMP_CLAUSE_SPLIT_SIMD; break;
+ case OMP_FOR: case OMP_SECTIONS:
+ case OMP_PARALLEL: s = C_OMP_CLAUSE_SPLIT_PARALLEL; break;
+ case OMP_DISTRIBUTE: s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE; break;
+ case OMP_TEAMS: s = C_OMP_CLAUSE_SPLIT_TEAMS; break;
+ default: gcc_unreachable ();
+ }
+ break;
+ /* Firstprivate clause is supported on all constructs but
+ target and simd. Put it on the outermost of those and
+ duplicate on parallel. */
+ case OMP_CLAUSE_FIRSTPRIVATE:
+ if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS))
+ != 0)
+ {
+ if ((mask & ((OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS)
+ | (OMP_CLAUSE_MASK_1
+ << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE))) != 0)
+ {
+ c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
+ OMP_CLAUSE_FIRSTPRIVATE);
+ OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
+ OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL];
+ cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] = c;
+ if ((mask & (OMP_CLAUSE_MASK_1
+ << PRAGMA_OMP_CLAUSE_NUM_TEAMS)) != 0)
+ s = C_OMP_CLAUSE_SPLIT_TEAMS;
+ else
+ s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
+ }
+ else
+ /* This must be
+ #pragma omp parallel{, for{, simd}, sections}. */
+ s = C_OMP_CLAUSE_SPLIT_PARALLEL;
+ }
+ else if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS))
+ != 0)
+ {
+ /* This must be #pragma omp {,target }teams distribute. */
+ gcc_assert (code == OMP_DISTRIBUTE);
+ s = C_OMP_CLAUSE_SPLIT_TEAMS;
+ }
+ else if ((mask & (OMP_CLAUSE_MASK_1
+ << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0)
+ {
+ /* This must be #pragma omp distribute simd. */
+ gcc_assert (code == OMP_SIMD);
+ s = C_OMP_CLAUSE_SPLIT_TEAMS;
+ }
+ else
+ {
+ /* This must be #pragma omp for simd. */
+ gcc_assert (code == OMP_SIMD);
+ s = C_OMP_CLAUSE_SPLIT_FOR;
+ }
+ break;
+ /* Lastprivate is allowed on for, sections and simd. In
+ parallel {for{, simd},sections} we actually want to put it on
+ parallel rather than for or sections. */
+ case OMP_CLAUSE_LASTPRIVATE:
+ if (code == OMP_FOR || code == OMP_SECTIONS)
+ {
+ if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS))
+ != 0)
+ s = C_OMP_CLAUSE_SPLIT_PARALLEL;
+ else
+ s = C_OMP_CLAUSE_SPLIT_FOR;
+ break;
+ }
+ gcc_assert (code == OMP_SIMD);
+ if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0)
+ {
+ c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
+ OMP_CLAUSE_LASTPRIVATE);
+ OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
+ if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS))
+ != 0)
+ s = C_OMP_CLAUSE_SPLIT_PARALLEL;
+ else
+ s = C_OMP_CLAUSE_SPLIT_FOR;
+ OMP_CLAUSE_CHAIN (c) = cclauses[s];
+ cclauses[s] = c;
+ }
+ s = C_OMP_CLAUSE_SPLIT_SIMD;
+ break;
+ /* Shared and default clauses are allowed on private and teams. */
+ case OMP_CLAUSE_SHARED:
+ case OMP_CLAUSE_DEFAULT:
+ if (code == OMP_TEAMS)
+ {
+ s = C_OMP_CLAUSE_SPLIT_TEAMS;
+ break;
+ }
+ if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS))
+ != 0)
+ {
+ c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
+ OMP_CLAUSE_CODE (clauses));
+ if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_SHARED)
+ OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
+ else
+ OMP_CLAUSE_DEFAULT_KIND (c)
+ = OMP_CLAUSE_DEFAULT_KIND (clauses);
+ OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
+ cclauses[C_OMP_CLAUSE_SPLIT_TEAMS] = c;
+
+ }
+ s = C_OMP_CLAUSE_SPLIT_PARALLEL;
+ break;
+ /* Reduction is allowed on simd, for, parallel, sections and teams.
+ Duplicate it on all of them, but omit on for or sections if
+ parallel is present. */
+ case OMP_CLAUSE_REDUCTION:
+ if (code == OMP_SIMD)
+ {
+ c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
+ OMP_CLAUSE_REDUCTION);
+ OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
+ OMP_CLAUSE_REDUCTION_CODE (c)
+ = OMP_CLAUSE_REDUCTION_CODE (clauses);
+ OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
+ = OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses);
+ OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
+ cclauses[C_OMP_CLAUSE_SPLIT_SIMD] = c;
+ }
+ if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0)
+ {
+ if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS))
+ != 0)
+ {
+ c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
+ OMP_CLAUSE_REDUCTION);
+ OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
+ OMP_CLAUSE_REDUCTION_CODE (c)
+ = OMP_CLAUSE_REDUCTION_CODE (clauses);
+ OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
+ = OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses);
+ OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL];
+ cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] = c;
+ s = C_OMP_CLAUSE_SPLIT_TEAMS;
+ }
+ else if ((mask & (OMP_CLAUSE_MASK_1
+ << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0)
+ s = C_OMP_CLAUSE_SPLIT_PARALLEL;
+ else
+ s = C_OMP_CLAUSE_SPLIT_FOR;
+ }
+ else if (code == OMP_SECTIONS)
+ s = C_OMP_CLAUSE_SPLIT_PARALLEL;
+ else
+ s = C_OMP_CLAUSE_SPLIT_TEAMS;
+ break;
+ case OMP_CLAUSE_IF:
+ /* FIXME: This is currently being discussed. */
+ if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS))
+ != 0)
+ s = C_OMP_CLAUSE_SPLIT_PARALLEL;
+ else
+ s = C_OMP_CLAUSE_SPLIT_TARGET;
break;
-
default:
gcc_unreachable ();
}
+ OMP_CLAUSE_CHAIN (clauses) = cclauses[s];
+ cclauses[s] = clauses;
}
}
+
+/* qsort callback to compare #pragma omp declare simd clauses. */
+
+static int
+c_omp_declare_simd_clause_cmp (const void *p, const void *q)
+{
+ tree a = *(const tree *) p;
+ tree b = *(const tree *) q;
+ if (OMP_CLAUSE_CODE (a) != OMP_CLAUSE_CODE (b))
+ {
+ if (OMP_CLAUSE_CODE (a) > OMP_CLAUSE_CODE (b))
+ return -1;
+ return 1;
+ }
+ if (OMP_CLAUSE_CODE (a) != OMP_CLAUSE_SIMDLEN
+ && OMP_CLAUSE_CODE (a) != OMP_CLAUSE_INBRANCH
+ && OMP_CLAUSE_CODE (a) != OMP_CLAUSE_NOTINBRANCH)
+ {
+ int c = tree_low_cst (OMP_CLAUSE_DECL (a), 0);
+ int d = tree_low_cst (OMP_CLAUSE_DECL (b), 0);
+ if (c < d)
+ return 1;
+ if (c > d)
+ return -1;
+ }
+ return 0;
+}
+
+/* Change PARM_DECLs in OMP_CLAUSE_DECL of #pragma omp declare simd
+ CLAUSES on FNDECL into argument indexes and sort them. */
+
+tree
+c_omp_declare_simd_clauses_to_numbers (tree parms, tree clauses)
+{
+ tree c;
+ vec<tree> clvec = vNULL;
+
+ for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
+ {
+ if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_SIMDLEN
+ && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_INBRANCH
+ && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_NOTINBRANCH)
+ {
+ tree decl = OMP_CLAUSE_DECL (c);
+ tree arg;
+ int idx;
+ for (arg = parms, idx = 0; arg;
+ arg = TREE_CHAIN (arg), idx++)
+ if (arg == decl)
+ break;
+ if (arg == NULL_TREE)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD is not an function argument", decl);
+ continue;
+ }
+ OMP_CLAUSE_DECL (c) = build_int_cst (integer_type_node, idx);
+ }
+ clvec.safe_push (c);
+ }
+ if (!clvec.is_empty ())
+ {
+ unsigned int len = clvec.length (), i;
+ clvec.qsort (c_omp_declare_simd_clause_cmp);
+ clauses = clvec[0];
+ for (i = 0; i < len; i++)
+ OMP_CLAUSE_CHAIN (clvec[i]) = (i < len - 1) ? clvec[i + 1] : NULL_TREE;
+ }
+ clvec.release ();
+ return clauses;
+}
+
+/* Change argument indexes in CLAUSES of FNDECL back to PARM_DECLs. */
+
+void
+c_omp_declare_simd_clauses_to_decls (tree fndecl, tree clauses)
+{
+ tree c;
+
+ for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
+ if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_SIMDLEN
+ && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_INBRANCH
+ && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_NOTINBRANCH)
+ {
+ int idx = tree_low_cst (OMP_CLAUSE_DECL (c), 0), i;
+ tree arg;
+ for (arg = DECL_ARGUMENTS (fndecl), i = 0; arg;
+ arg = TREE_CHAIN (arg), i++)
+ if (i == idx)
+ break;
+ gcc_assert (arg);
+ OMP_CLAUSE_DECL (c) = arg;
+ }
+}
+
/* True if OpenMP sharing attribute of DECL is predetermined. */
enum omp_clause_default_kind
diff --git a/gcc/c-family/c-opts.c b/gcc/c-family/c-opts.c
index 702fe1a8bdf..34fe94de34b 100644
--- a/gcc/c-family/c-opts.c
+++ b/gcc/c-family/c-opts.c
@@ -827,6 +827,15 @@ c_common_post_options (const char **pfilename)
? 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 ()
+ && (global_options_set.x_flag_fp_contract_mode
+ == (enum fp_contract_mode) 0))
+ flag_fp_contract_mode = FP_CONTRACT_OFF;
+
/* 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)
@@ -1198,6 +1207,7 @@ sanitize_cpp_opts (void)
cpp_opts->unsigned_char = !flag_signed_char;
cpp_opts->stdc_0_in_system_headers = STDC_0_IN_SYSTEM_HEADERS;
+ cpp_opts->warn_date_time = cpp_warn_date_time;
/* Wlong-long is disabled by default. It is enabled by:
[-Wpedantic | -Wtraditional] -std=[gnu|c]++98 ; or
diff --git a/gcc/c-family/c-pragma.c b/gcc/c-family/c-pragma.c
index 309859fc8ec..c75b0872b44 100644
--- a/gcc/c-family/c-pragma.c
+++ b/gcc/c-family/c-pragma.c
@@ -307,7 +307,7 @@ maybe_apply_pending_pragma_weaks (void)
tree alias_id, id, decl;
int i;
pending_weak *pe;
- symtab_node target;
+ symtab_node *target;
if (!pending_weaks)
return;
@@ -322,7 +322,7 @@ maybe_apply_pending_pragma_weaks (void)
target = symtab_node_for_asm (id);
decl = build_decl (UNKNOWN_LOCATION,
- target ? TREE_CODE (target->symbol.decl) : FUNCTION_DECL,
+ target ? TREE_CODE (target->decl) : FUNCTION_DECL,
alias_id, default_function_type);
DECL_ARTIFICIAL (decl) = 1;
@@ -872,7 +872,7 @@ handle_pragma_optimize (cpp_reader *ARG_UNUSED(dummy))
parse_optimize_options (args, false);
current_optimize_pragma = chainon (current_optimize_pragma, args);
- optimization_current_node = build_optimization_node ();
+ optimization_current_node = build_optimization_node (&global_options);
c_cpp_builtins_optimize_pragma (parse_in,
optimization_previous_node,
optimization_current_node);
@@ -914,8 +914,8 @@ handle_pragma_push_options (cpp_reader *ARG_UNUSED(dummy))
options_stack = p;
/* Save optimization and target flags in binary format. */
- p->optimize_binary = build_optimization_node ();
- p->target_binary = build_target_option_node ();
+ p->optimize_binary = build_optimization_node (&global_options);
+ p->target_binary = build_target_option_node (&global_options);
/* Save optimization and target flags in string list format. */
p->optimize_strings = copy_list (current_optimize_pragma);
@@ -1167,25 +1167,38 @@ struct omp_pragma_def { const char *name; unsigned int id; };
static const struct omp_pragma_def omp_pragmas[] = {
{ "atomic", PRAGMA_OMP_ATOMIC },
{ "barrier", PRAGMA_OMP_BARRIER },
+ { "cancel", PRAGMA_OMP_CANCEL },
+ { "cancellation", PRAGMA_OMP_CANCELLATION_POINT },
{ "critical", PRAGMA_OMP_CRITICAL },
+ { "end", PRAGMA_OMP_END_DECLARE_TARGET },
{ "flush", PRAGMA_OMP_FLUSH },
- { "for", PRAGMA_OMP_FOR },
{ "master", PRAGMA_OMP_MASTER },
{ "ordered", PRAGMA_OMP_ORDERED },
- { "parallel", PRAGMA_OMP_PARALLEL },
{ "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_REDUCTION },
+ { "distribute", PRAGMA_OMP_DISTRIBUTE },
+ { "for", PRAGMA_OMP_FOR },
+ { "parallel", PRAGMA_OMP_PARALLEL },
+ { "simd", PRAGMA_OMP_SIMD },
+ { "target", PRAGMA_OMP_TARGET },
+ { "task", PRAGMA_OMP_TASK },
+ { "teams", PRAGMA_OMP_TEAMS },
+};
void
c_pp_lookup_pragma (unsigned int id, const char **space, const char **name)
{
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_omp_pragmas; ++i)
@@ -1196,6 +1209,14 @@ c_pp_lookup_pragma (unsigned int id, const char **space, const char **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 ()))
{
@@ -1348,11 +1369,23 @@ init_pragma (void)
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);
+ cpp_register_deferred_pragma (parse_in, "GCC", "ivdep", PRAGMA_IVDEP, false,
+ false);
#ifdef HANDLE_PRAGMA_PACK_WITH_EXPANSION
c_register_pragma_with_expansion (0, "pack", handle_pragma_pack);
#else
diff --git a/gcc/c-family/c-pragma.h b/gcc/c-family/c-pragma.h
index 41215db00a0..705bcb472a9 100644
--- a/gcc/c-family/c-pragma.h
+++ b/gcc/c-family/c-pragma.h
@@ -29,50 +29,78 @@ typedef enum pragma_kind {
PRAGMA_OMP_ATOMIC,
PRAGMA_OMP_BARRIER,
+ PRAGMA_OMP_CANCEL,
+ PRAGMA_OMP_CANCELLATION_POINT,
PRAGMA_OMP_CRITICAL,
+ PRAGMA_OMP_DECLARE_REDUCTION,
+ PRAGMA_OMP_DISTRIBUTE,
+ PRAGMA_OMP_END_DECLARE_TARGET,
PRAGMA_OMP_FLUSH,
PRAGMA_OMP_FOR,
PRAGMA_OMP_MASTER,
PRAGMA_OMP_ORDERED,
PRAGMA_OMP_PARALLEL,
- PRAGMA_OMP_PARALLEL_FOR,
- PRAGMA_OMP_PARALLEL_SECTIONS,
PRAGMA_OMP_SECTION,
PRAGMA_OMP_SECTIONS,
+ PRAGMA_OMP_SIMD,
PRAGMA_OMP_SINGLE,
+ PRAGMA_OMP_TARGET,
PRAGMA_OMP_TASK,
+ PRAGMA_OMP_TASKGROUP,
PRAGMA_OMP_TASKWAIT,
PRAGMA_OMP_TASKYIELD,
PRAGMA_OMP_THREADPRIVATE,
+ PRAGMA_OMP_TEAMS,
PRAGMA_GCC_PCH_PREPROCESS,
+ PRAGMA_IVDEP,
PRAGMA_FIRST_EXTERNAL
} pragma_kind;
-/* All clauses defined by OpenMP 2.5 and 3.0.
+/* All clauses defined by OpenMP 2.5, 3.0, 3.1 and 4.0.
Used internally by both C and C++ parsers. */
typedef enum pragma_omp_clause {
PRAGMA_OMP_CLAUSE_NONE = 0,
+ PRAGMA_OMP_CLAUSE_ALIGNED,
PRAGMA_OMP_CLAUSE_COLLAPSE,
PRAGMA_OMP_CLAUSE_COPYIN,
PRAGMA_OMP_CLAUSE_COPYPRIVATE,
PRAGMA_OMP_CLAUSE_DEFAULT,
+ PRAGMA_OMP_CLAUSE_DEPEND,
+ PRAGMA_OMP_CLAUSE_DEVICE,
+ PRAGMA_OMP_CLAUSE_DIST_SCHEDULE,
+ PRAGMA_OMP_CLAUSE_FINAL,
PRAGMA_OMP_CLAUSE_FIRSTPRIVATE,
+ PRAGMA_OMP_CLAUSE_FOR,
+ PRAGMA_OMP_CLAUSE_FROM,
PRAGMA_OMP_CLAUSE_IF,
+ PRAGMA_OMP_CLAUSE_INBRANCH,
PRAGMA_OMP_CLAUSE_LASTPRIVATE,
+ PRAGMA_OMP_CLAUSE_LINEAR,
+ PRAGMA_OMP_CLAUSE_MAP,
+ PRAGMA_OMP_CLAUSE_MERGEABLE,
+ PRAGMA_OMP_CLAUSE_NOTINBRANCH,
PRAGMA_OMP_CLAUSE_NOWAIT,
+ PRAGMA_OMP_CLAUSE_NUM_TEAMS,
PRAGMA_OMP_CLAUSE_NUM_THREADS,
PRAGMA_OMP_CLAUSE_ORDERED,
+ PRAGMA_OMP_CLAUSE_PARALLEL,
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_UNTIED,
- PRAGMA_OMP_CLAUSE_FINAL,
- PRAGMA_OMP_CLAUSE_MERGEABLE
+ PRAGMA_OMP_CLAUSE_SIMDLEN,
+ PRAGMA_OMP_CLAUSE_TASKGROUP,
+ PRAGMA_OMP_CLAUSE_THREAD_LIMIT,
+ PRAGMA_OMP_CLAUSE_TO,
+ PRAGMA_OMP_CLAUSE_UNIFORM,
+ PRAGMA_OMP_CLAUSE_UNTIED
} pragma_omp_clause;
extern struct cpp_reader* parse_in;
diff --git a/gcc/c-family/c-pretty-print.c b/gcc/c-family/c-pretty-print.c
index d0283e8af4d..652c3a89215 100644
--- a/gcc/c-family/c-pretty-print.c
+++ b/gcc/c-family/c-pretty-print.c
@@ -179,8 +179,16 @@ pp_c_cv_qualifiers (c_pretty_printer *pp, int qualifiers, bool func_type)
if (p != NULL && (*p == '*' || *p == '&'))
pp_c_whitespace (pp);
+ if (qualifiers & TYPE_QUAL_ATOMIC)
+ {
+ pp_c_ws_string (pp, "_Atomic");
+ previous = true;
+ }
+
if (qualifiers & TYPE_QUAL_CONST)
{
+ if (previous)
+ pp_c_whitespace (pp);
pp_c_ws_string (pp, func_type ? "__attribute__((const))" : "const");
previous = true;
}
@@ -244,6 +252,7 @@ pp_c_space_for_pointer_operator (c_pretty_printer *pp, tree t)
__restrict__ -- GNU C
address-space-qualifier -- GNU C
volatile
+ _Atomic -- C11
address-space-qualifier:
identifier -- GNU C */
diff --git a/gcc/c-family/c-ubsan.c b/gcc/c-family/c-ubsan.c
index 9f43f6d55b8..c9896381db2 100644
--- a/gcc/c-family/c-ubsan.c
+++ b/gcc/c-family/c-ubsan.c
@@ -25,7 +25,6 @@ along with GCC; see the file COPYING3. If not see
#include "alloc-pool.h"
#include "cgraph.h"
#include "gimple.h"
-#include "hash-table.h"
#include "output.h"
#include "toplev.h"
#include "ubsan.h"
@@ -51,14 +50,6 @@ ubsan_instrument_division (location_t loc, tree op0, tree op1)
if (TREE_CODE (type) != INTEGER_TYPE)
return NULL_TREE;
- /* If we *know* that the divisor is not -1 or 0, we don't have to
- instrument this expression.
- ??? We could use decl_constant_value to cover up more cases. */
- if (TREE_CODE (op1) == INTEGER_CST
- && integer_nonzerop (op1)
- && !integer_minus_onep (op1))
- return NULL_TREE;
-
t = fold_build2 (EQ_EXPR, boolean_type_node,
op1, build_int_cst (type, 0));
@@ -74,6 +65,11 @@ ubsan_instrument_division (location_t loc, tree op0, tree op1)
t = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, t, x);
}
+ /* If the condition was folded to 0, no need to instrument
+ this expression. */
+ if (integer_zerop (t))
+ return NULL_TREE;
+
/* In case we have a SAVE_EXPR in a conditional context, we need to
make sure it gets evaluated before the condition. */
t = fold_build2 (COMPOUND_EXPR, TREE_TYPE (t), op0, t);
@@ -89,8 +85,7 @@ ubsan_instrument_division (location_t loc, tree op0, tree op1)
return t;
}
-/* Instrument left and right shifts. If not instrumenting, return
- NULL_TREE. */
+/* Instrument left and right shifts. */
tree
ubsan_instrument_shift (location_t loc, enum tree_code code,
@@ -138,6 +133,11 @@ ubsan_instrument_shift (location_t loc, enum tree_code code,
tt = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, x, tt);
}
+ /* If the condition was folded to 0, no need to instrument
+ this expression. */
+ if (integer_zerop (t) && (tt == NULL_TREE || integer_zerop (tt)))
+ return NULL_TREE;
+
/* In case we have a SAVE_EXPR in a conditional context, we need to
make sure it gets evaluated before the condition. */
t = fold_build2 (COMPOUND_EXPR, TREE_TYPE (t), op0, t);
@@ -156,3 +156,22 @@ ubsan_instrument_shift (location_t loc, enum tree_code code,
return t;
}
+
+/* Instrument variable length array bound. */
+
+tree
+ubsan_instrument_vla (location_t loc, tree size)
+{
+ tree type = TREE_TYPE (size);
+ tree t, tt;
+
+ t = fold_build2 (LE_EXPR, boolean_type_node, size, build_int_cst (type, 0));
+ tree data = ubsan_create_data ("__ubsan_vla_data",
+ loc, ubsan_type_descriptor (type), NULL_TREE);
+ data = build_fold_addr_expr_loc (loc, data);
+ tt = builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_VLA_BOUND_NOT_POSITIVE);
+ tt = build_call_expr_loc (loc, tt, 2, data, ubsan_encode_value (size));
+ t = fold_build3 (COND_EXPR, void_type_node, t, tt, void_zero_node);
+
+ return t;
+}
diff --git a/gcc/c-family/c-ubsan.h b/gcc/c-family/c-ubsan.h
index b032b707cc3..fdf27d9e21e 100644
--- a/gcc/c-family/c-ubsan.h
+++ b/gcc/c-family/c-ubsan.h
@@ -23,5 +23,6 @@ along with GCC; see the file COPYING3. If not see
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);
#endif /* GCC_C_UBSAN_H */
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 24d1b87d11f..0026683730e 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -538,8 +538,7 @@ C ObjC Var(warn_missing_prototypes) Warning
Warn about global functions without prototypes
Wmudflap
-C ObjC C++ ObjC++ Var(warn_mudflap) Init(1) Warning
-Warn about constructs not instrumented by -fmudflap
+C ObjC C++ ObjC++ Ignore Warn(switch %qs is no longer supported)
Wmultichar
C ObjC C++ ObjC++ Warning
@@ -641,6 +640,10 @@ Wpragmas
C ObjC C++ ObjC++ Var(warn_pragmas) Init(1) Warning
Warn about misuses of pragmas
+Wdate-time
+Common Var(cpp_warn_date_time) Warning
+Warn about __TIME__, __DATE__ and __TIMESTAMP__ usage
+
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
@@ -851,14 +854,15 @@ fcanonical-system-headers
C ObjC C++ ObjC++
Where shorter, use canonicalized paths to systems headers.
+fcheck-pointer-bounds
+C ObjC C++ ObjC++ LTO Report Var(flag_check_pointer_bounds)
+Add Pointer Bounds Checker instrumentation. fchkp-* flags are used to
+control instrumentation.
+
fcilkplus
C ObjC C++ ObjC++ LTO Report Var(flag_enable_cilkplus) Init(0)
Enable Cilk Plus
-fcheck-new
-C++ ObjC++ Var(flag_check_new)
-Check the return value of new
-
fcond-mismatch
C ObjC C++ ObjC++
Allow the arguments of the '?' operator to have different types
@@ -1001,16 +1005,13 @@ C ObjC C++ ObjC++ Var(flag_ms_extensions)
Don't warn about uses of Microsoft extensions
fmudflap
-C ObjC C++ ObjC++ RejectNegative Report Var(flag_mudflap)
-Add mudflap bounds-checking instrumentation for single-threaded program
+C ObjC C++ ObjC++ Ignore Warn(switch %qs is no longer supported)
fmudflapth
-C ObjC C++ ObjC++ RejectNegative Report Var(flag_mudflap,2)
-Add mudflap bounds-checking instrumentation for multi-threaded program
+C ObjC C++ ObjC++ Ignore Warn(switch %qs is no longer supported)
fmudflapir
-C ObjC C++ ObjC++ RejectNegative Report Var(flag_mudflap_ignore_reads)
-Ignore read operations when inserting mudflap instrumentation
+C ObjC C++ ObjC++ Ignore Warn(switch %qs is no longer supported)
fname-mangling-version-
C++ ObjC++ Joined Ignore Warn(switch %qs is no longer supported)
@@ -1077,6 +1078,10 @@ fopenmp
C ObjC C++ ObjC++ 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\"
diff --git a/gcc/c-family/cilk.c b/gcc/c-family/cilk.c
new file mode 100644
index 00000000000..f719d551869
--- /dev/null
+++ b/gcc/c-family/cilk.c
@@ -0,0 +1,1305 @@
+/* This file is part of the Intel(R) Cilk(TM) Plus support
+ This file contains the CilkPlus Intrinsics
+ Copyright (C) 2013 Free Software Foundation, Inc.
+ Contributed by Balaji V. Iyer <balaji.v.iyer@intel.com>,
+ Intel Corporation
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have 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 "tree.h"
+#include "langhooks.h"
+#include "gimple.h"
+#include "tree-iterator.h"
+#include "tree-inline.h"
+#include "c-family/c-common.h"
+#include "toplev.h"
+#include "cgraph.h"
+#include "diagnostic.h"
+#include "cilk.h"
+
+enum add_variable_type {
+ /* Reference to previously-defined variable. */
+ ADD_READ,
+ /* Definition of a new variable in inner-scope. */
+ ADD_BIND,
+ /* Write to possibly previously-defined variable. */
+ ADD_WRITE
+};
+
+enum cilk_block_type {
+ /* Indicates a _Cilk_spawn block. 30 was an arbitary number picked for
+ ease of debugging. */
+ CILK_BLOCK_SPAWN = 30,
+ /* Indicates _Cilk_for statement block. */
+ CILK_BLOCK_FOR
+};
+
+struct wrapper_data
+{
+ /* Kind of function to be created. */
+ enum cilk_block_type type;
+ /* Signature of helper function. */
+ tree fntype;
+ /* Containing function. */
+ tree context;
+ /* Disposition of all variables in the inner statement. */
+ struct pointer_map_t *decl_map;
+ /* True if this function needs a static chain. */
+ bool nested;
+ /* Arguments to be passed to wrapper function, currently a list. */
+ tree arglist;
+ /* Argument types, a list. */
+ tree argtypes;
+ /* Incoming parameters. */
+ tree parms;
+ /* Outer BLOCK object. */
+ tree block;
+};
+
+static void extract_free_variables (tree, struct wrapper_data *,
+ enum add_variable_type);
+static HOST_WIDE_INT cilk_wrapper_count;
+
+/* Marks the CALL_EXPR or FUNCTION_DECL, FCALL, as a spawned function call
+ and the current function as a spawner. Emit error if the function call
+ is outside a function or if a non function-call is spawned. */
+
+inline bool
+cilk_set_spawn_marker (location_t loc, tree fcall)
+{
+ if (!current_function_decl)
+ {
+ error_at (loc, "%<_Cilk_spawn%> may only be used inside a function");
+ return false;
+ }
+ else if (fcall == error_mark_node)
+ /* Error reporting here is not necessary here since if FCALL is an
+ error_mark_node, the function marking it as error would have reported
+ it. */
+ return false;
+ else if (TREE_CODE (fcall) != CALL_EXPR
+ && TREE_CODE (fcall) != FUNCTION_DECL
+ /* In C++, TARGET_EXPR is generated when we have an overloaded
+ '=' operator. */
+ && TREE_CODE (fcall) != TARGET_EXPR)
+ {
+ error_at (loc, "only function calls can be spawned");
+ return false;
+ }
+ else
+ {
+ cfun->calls_cilk_spawn = true;
+ return true;
+ }
+}
+
+/* This function will output the exit conditions for a spawn call. */
+
+tree
+create_cilk_function_exit (tree frame, bool detaches, bool needs_sync)
+{
+ tree epi = alloc_stmt_list ();
+
+ if (needs_sync)
+ append_to_statement_list (build_cilk_sync (), &epi);
+ tree func_ptr = build1 (ADDR_EXPR, cilk_frame_ptr_type_decl, frame);
+ tree pop_frame = build_call_expr (cilk_pop_fndecl, 1, func_ptr);
+ tree worker = cilk_dot (frame, CILK_TI_FRAME_WORKER, 0);
+ tree current = cilk_arrow (worker, CILK_TI_WORKER_CUR, 0);
+ tree parent = cilk_dot (frame, CILK_TI_FRAME_PARENT, 0);
+ tree set_current = build2 (MODIFY_EXPR, void_type_node, current, parent);
+ append_to_statement_list (set_current, &epi);
+ append_to_statement_list (pop_frame, &epi);
+ tree call = build_call_expr (cilk_leave_fndecl, 1, func_ptr);
+ if (!detaches)
+ {
+ tree flags = cilk_dot (frame, CILK_TI_FRAME_FLAGS, false);
+ tree flags_cmp_expr = fold_build2 (NE_EXPR, TREE_TYPE (flags), flags,
+ build_int_cst (TREE_TYPE (flags),
+ CILK_FRAME_VERSION));
+ call = fold_build3 (COND_EXPR, void_type_node, flags_cmp_expr,
+ call, build_empty_stmt (EXPR_LOCATION (flags)));
+ }
+ append_to_statement_list (call, &epi);
+ return epi;
+}
+
+/* Trying to get the correct cfun for the FUNCTION_DECL indicated by OUTER. */
+
+static void
+pop_cfun_to (tree outer)
+{
+ pop_cfun ();
+ current_function_decl = outer;
+ gcc_assert (cfun == DECL_STRUCT_FUNCTION (current_function_decl));
+ gcc_assert (cfun->decl == current_function_decl);
+}
+
+/* This function does whatever is necessary to make the compiler emit a newly
+ generated function, FNDECL. */
+
+static void
+call_graph_add_fn (tree fndecl)
+{
+ const tree outer = current_function_decl;
+ struct function *f = DECL_STRUCT_FUNCTION (fndecl);
+ gcc_assert (TREE_CODE (fndecl) == FUNCTION_DECL);
+
+ f->is_cilk_function = 1;
+ f->curr_properties = cfun->curr_properties;
+ gcc_assert (cfun == DECL_STRUCT_FUNCTION (outer));
+ gcc_assert (cfun->decl == outer);
+
+ push_cfun (f);
+ cgraph_create_node (fndecl);
+ pop_cfun_to (outer);
+}
+
+/* Return true if this is a tree which is allowed to contain a spawn as
+ operand 0.
+ A spawn call may be wrapped in a series of unary operations such
+ as conversions. These conversions need not be "useless"
+ to be disregarded because they are retained in the spawned
+ statement. They are bypassed only to look for a spawn
+ within.
+ A comparison to constant is simple enough to allow, and
+ is used to convert to bool. */
+
+static bool
+cilk_ignorable_spawn_rhs_op (tree exp)
+{
+ enum tree_code code = TREE_CODE (exp);
+ switch (TREE_CODE_CLASS (code))
+ {
+ case tcc_expression:
+ return code == ADDR_EXPR;
+ case tcc_comparison:
+ /* We need the spawn as operand 0 for now. That's where it
+ appears in the only case we really care about, conversion
+ to bool. */
+ return (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST);
+ case tcc_unary:
+ case tcc_reference:
+ return true;
+ default:
+ return false;
+ }
+}
+
+/* Helper function for walk_tree. If *TP is a CILK_SPAWN_STMT, then unwrap
+ this "wrapper." The function returns NULL_TREE regardless. */
+
+static tree
+unwrap_cilk_spawn_stmt (tree *tp, int *walk_subtrees, void *)
+{
+ if (TREE_CODE (*tp) == CILK_SPAWN_STMT)
+ {
+ *tp = CILK_SPAWN_FN (*tp);
+ *walk_subtrees = 0;
+ }
+ return NULL_TREE;
+}
+
+/* Returns true when EXP is a CALL_EXPR with _Cilk_spawn in front. Unwraps
+ CILK_SPAWN_STMT wrapper from the CALL_EXPR in *EXP0 statement. */
+
+static bool
+recognize_spawn (tree exp, tree *exp0)
+{
+ bool spawn_found = false;
+ if (TREE_CODE (exp) == CILK_SPAWN_STMT)
+ {
+ /* Remove the CALL_EXPR from CILK_SPAWN_STMT wrapper. */
+ exp = CILK_SPAWN_FN (exp);
+ walk_tree (exp0, unwrap_cilk_spawn_stmt, NULL, NULL);
+ spawn_found = true;
+ }
+ return spawn_found;
+}
+
+/* Returns true if *EXP0 is a recognized form of spawn. Recognized forms are,
+ after conversion to void, a call expression at outer level or an assignment
+ at outer level with the right hand side being a spawned call.
+ In addition to this, it also unwraps the CILK_SPAWN_STMT cover from the
+ CALL_EXPR that is being spawned.
+ Note that `=' in C++ may turn into a CALL_EXPR rather than a MODIFY_EXPR. */
+
+bool
+cilk_detect_spawn_and_unwrap (tree *exp0)
+{
+ tree exp = *exp0;
+
+ if (!TREE_SIDE_EFFECTS (exp))
+ return false;
+
+ /* Strip off any conversion to void. It does not affect whether spawn
+ is supported here. */
+ if (TREE_CODE (exp) == CONVERT_EXPR && VOID_TYPE_P (TREE_TYPE (exp)))
+ exp = TREE_OPERAND (exp, 0);
+
+ if (TREE_CODE (exp) == MODIFY_EXPR || TREE_CODE (exp) == INIT_EXPR)
+ exp = TREE_OPERAND (exp, 1);
+
+ while (cilk_ignorable_spawn_rhs_op (exp))
+ exp = TREE_OPERAND (exp, 0);
+
+ if (TREE_CODE (exp) == TARGET_EXPR)
+ if (TARGET_EXPR_INITIAL (exp)
+ && TREE_CODE (TARGET_EXPR_INITIAL (exp)) != AGGR_INIT_EXPR)
+ exp = TARGET_EXPR_INITIAL (exp);
+
+ /* Happens with C++ TARGET_EXPR. */
+ if (exp == NULL_TREE)
+ return false;
+
+ while (TREE_CODE (exp) == CLEANUP_POINT_EXPR || TREE_CODE (exp) == EXPR_STMT)
+ exp = TREE_OPERAND (exp, 0);
+
+ /* Now we should have a CALL_EXPR with a CILK_SPAWN_STMT wrapper around
+ it, or return false. */
+ if (recognize_spawn (exp, exp0))
+ return true;
+ return false;
+}
+
+/* This function will build and return a FUNCTION_DECL using information
+ from *WD. */
+
+static tree
+create_cilk_helper_decl (struct wrapper_data *wd)
+{
+ char name[20];
+ if (wd->type == CILK_BLOCK_FOR)
+ sprintf (name, "_cilk_for_" HOST_WIDE_INT_PRINT_DEC, cilk_wrapper_count++);
+ else if (wd->type == CILK_BLOCK_SPAWN)
+ sprintf (name, "_cilk_spn_" HOST_WIDE_INT_PRINT_DEC, cilk_wrapper_count++);
+ else
+ gcc_unreachable ();
+
+ clean_symbol_name (name);
+ tree fndecl = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL,
+ get_identifier (name), wd->fntype);
+
+ TREE_PUBLIC (fndecl) = 0;
+ TREE_STATIC (fndecl) = 1;
+ TREE_USED (fndecl) = 1;
+ DECL_ARTIFICIAL (fndecl) = 0;
+ DECL_IGNORED_P (fndecl) = 0;
+ DECL_EXTERNAL (fndecl) = 0;
+
+ DECL_CONTEXT (fndecl) = wd->context;
+ tree block = make_node (BLOCK);
+ DECL_INITIAL (fndecl) = block;
+ TREE_USED (block) = 1;
+ gcc_assert (!DECL_SAVED_TREE (fndecl));
+
+ /* Inlining would defeat the purpose of this wrapper.
+ Either it secretly switches stack frames or it allocates
+ a stable stack frame to hold function arguments even if
+ the parent stack frame is stolen. */
+ DECL_UNINLINABLE (fndecl) = 1;
+
+ tree result_decl = build_decl (UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE,
+ void_type_node);
+ DECL_ARTIFICIAL (result_decl) = 0;
+ DECL_IGNORED_P (result_decl) = 1;
+ DECL_CONTEXT (result_decl) = fndecl;
+ DECL_RESULT (fndecl) = result_decl;
+
+ return fndecl;
+}
+
+/* A function used by walk tree to find wrapper parms. */
+
+static bool
+wrapper_parm_cb (const void *key0, void **val0, void *data)
+{
+ struct wrapper_data *wd = (struct wrapper_data *) data;
+ tree arg = * (tree *)&key0;
+ tree val = (tree)*val0;
+ tree parm;
+
+ if (val == error_mark_node || val == arg)
+ return true;
+
+ if (TREE_CODE (val) == PAREN_EXPR)
+ {
+ /* We should not reach here with a register receiver.
+ We may see a register variable modified in the
+ argument list. Because register variables are
+ worker-local we don't need to work hard to support
+ them in code that spawns. */
+ if ((TREE_CODE (arg) == VAR_DECL) && DECL_HARD_REGISTER (arg))
+ {
+ error_at (EXPR_LOCATION (arg),
+ "explicit register variable %qD may not be modified in "
+ "spawn", arg);
+ arg = null_pointer_node;
+ }
+ else
+ arg = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (arg)), arg);
+
+ val = TREE_OPERAND (val, 0);
+ *val0 = val;
+ gcc_assert (TREE_CODE (val) == INDIRECT_REF);
+ parm = TREE_OPERAND (val, 0);
+ STRIP_NOPS (parm);
+ }
+ else
+ parm = val;
+ TREE_CHAIN (parm) = wd->parms;
+ wd->parms = parm;
+ wd->argtypes = tree_cons (NULL_TREE, TREE_TYPE (parm), wd->argtypes);
+ wd->arglist = tree_cons (NULL_TREE, arg, wd->arglist);
+ return true;
+}
+
+/* This function is used to build a wrapper of a certain type. */
+
+static void
+build_wrapper_type (struct wrapper_data *wd)
+{
+ wd->arglist = NULL_TREE;
+ wd->parms = NULL_TREE;
+ wd->argtypes = void_list_node;
+
+ pointer_map_traverse (wd->decl_map, wrapper_parm_cb, wd);
+ gcc_assert (wd->type != CILK_BLOCK_FOR);
+
+ /* Now build a function.
+ Its return type is void (all side effects are via explicit parameters).
+ Its parameters are WRAPPER_PARMS with type WRAPPER_TYPES.
+ Actual arguments in the caller are WRAPPER_ARGS. */
+ wd->fntype = build_function_type (void_type_node, wd->argtypes);
+}
+
+/* This function checks all the CALL_EXPRs in *TP found by cilk_outline. */
+
+static tree
+check_outlined_calls (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
+ void *data)
+{
+ bool *throws = (bool *) data;
+ tree t = *tp;
+ int flags;
+
+ if (TREE_CODE (t) != CALL_EXPR)
+ return 0;
+ flags = call_expr_flags (t);
+
+ if (!(flags & ECF_NOTHROW) && flag_exceptions)
+ *throws = true;
+ if (flags & ECF_RETURNS_TWICE)
+ error_at (EXPR_LOCATION (t),
+ "cannot spawn call to function that returns twice");
+ return 0;
+}
+
+/* Each DECL in the source code (spawned statement) is passed to this function
+ once. Each instance of the DECL is replaced with the result of this
+ function.
+
+ The parameters of the wrapper should have been entered into the map already.
+ This function only deals with variables with scope limited to the
+ spawned expression. */
+
+static tree
+copy_decl_for_cilk (tree decl, copy_body_data *id)
+{
+ switch (TREE_CODE (decl))
+ {
+ case VAR_DECL:
+ return copy_decl_no_change (decl, id);
+
+ case LABEL_DECL:
+ error_at (EXPR_LOCATION (decl), "invalid use of label %q+D in "
+ "%<_Cilk_spawn%>",
+ decl);
+ return error_mark_node;
+
+ case RESULT_DECL:
+ case PARM_DECL:
+ /* RESULT_DECL and PARM_DECL has already been entered into the map. */
+ default:
+ gcc_unreachable ();
+ return error_mark_node;
+ }
+}
+
+/* Copy all local variables. */
+
+static bool
+for_local_cb (const void *k_v, void **vp, void *p)
+{
+ tree k = *(tree *) &k_v;
+ tree v = (tree) *vp;
+
+ if (v == error_mark_node)
+ *vp = copy_decl_no_change (k, (copy_body_data *) p);
+ return true;
+}
+
+/* Copy all local declarations from a _Cilk_spawned function's body. */
+
+static bool
+wrapper_local_cb (const void *k_v, void **vp, void *data)
+{
+ copy_body_data *id = (copy_body_data *) data;
+ tree key = *(tree *) &k_v;
+ tree val = (tree) *vp;
+
+ if (val == error_mark_node)
+ *vp = copy_decl_for_cilk (key, id);
+
+ return true;
+}
+
+/* Alter a tree STMT from OUTER_FN to form the body of INNER_FN. */
+
+static void
+cilk_outline (tree inner_fn, tree *stmt_p, struct wrapper_data *wd)
+{
+ const tree outer_fn = wd->context;
+ const bool nested = (wd->type == CILK_BLOCK_FOR);
+ copy_body_data id;
+ bool throws;
+
+ DECL_STATIC_CHAIN (outer_fn) = 1;
+
+ memset (&id, 0, sizeof (id));
+ /* Copy from the function containing the spawn... */
+ id.src_fn = outer_fn;
+
+ /* ...to the wrapper. */
+ id.dst_fn = inner_fn;
+ id.src_cfun = DECL_STRUCT_FUNCTION (outer_fn);
+
+ /* There shall be no RETURN in spawn helper. */
+ id.retvar = 0;
+ id.decl_map = wd->decl_map;
+ id.copy_decl = nested ? copy_decl_no_change : copy_decl_for_cilk;
+ id.block = DECL_INITIAL (inner_fn);
+ id.transform_lang_insert_block = NULL;
+
+ id.transform_new_cfg = true;
+ id.transform_call_graph_edges = CB_CGE_MOVE;
+ id.remap_var_for_cilk = true;
+ id.regimplify = true; /* unused? */
+
+ insert_decl_map (&id, wd->block, DECL_INITIAL (inner_fn));
+
+ /* We don't want the private variables any more. */
+ pointer_map_traverse (wd->decl_map, nested ? for_local_cb : wrapper_local_cb,
+ &id);
+
+ walk_tree (stmt_p, copy_tree_body_r, &id, NULL);
+
+ /* See if this function can throw or calls something that should
+ not be spawned. The exception part is only necessary if
+ flag_exceptions && !flag_non_call_exceptions. */
+ throws = false ;
+ (void) walk_tree_without_duplicates (stmt_p, check_outlined_calls, &throws);
+}
+
+/* Generate the body of a wrapper function that assigns the
+ result of the expression RHS into RECEIVER. RECEIVER must
+ be NULL if this is not a spawn -- the wrapper will return
+ a value. If this is a spawn, the wrapper will return void. */
+
+static tree
+create_cilk_wrapper_body (tree stmt, struct wrapper_data *wd)
+{
+ const tree outer = current_function_decl;
+ tree fndecl;
+ tree p;
+
+ /* Build the type of the wrapper and its argument list from the
+ variables that it requires. */
+ build_wrapper_type (wd);
+
+ /* Emit a function that takes WRAPPER_PARMS incoming and applies ARGS
+ (modified) to the wrapped function. Return the wrapper and modified ARGS
+ to the caller to generate a function call. */
+ fndecl = create_cilk_helper_decl (wd);
+ push_struct_function (fndecl);
+ if (wd->nested && (wd->type == CILK_BLOCK_FOR))
+ {
+ gcc_assert (TREE_VALUE (wd->arglist) == NULL_TREE);
+ TREE_VALUE (wd->arglist) = build2 (FDESC_EXPR, ptr_type_node,
+ fndecl, integer_one_node);
+ }
+ DECL_ARGUMENTS (fndecl) = wd->parms;
+
+ for (p = wd->parms; p; p = TREE_CHAIN (p))
+ DECL_CONTEXT (p) = fndecl;
+
+ cilk_outline (fndecl, &stmt, wd);
+ stmt = fold_build_cleanup_point_expr (void_type_node, stmt);
+ gcc_assert (!DECL_SAVED_TREE (fndecl));
+ lang_hooks.cilkplus.install_body_with_frame_cleanup (fndecl, stmt);
+ gcc_assert (DECL_SAVED_TREE (fndecl));
+
+ pop_cfun_to (outer);
+
+ /* Recognize the new function. */
+ call_graph_add_fn (fndecl);
+ return fndecl;
+}
+
+/* Initializes the wrapper data structure. */
+
+static void
+init_wd (struct wrapper_data *wd, enum cilk_block_type type)
+{
+ wd->type = type;
+ wd->fntype = NULL_TREE;
+ wd->context = current_function_decl;
+ wd->decl_map = pointer_map_create ();
+ /* _Cilk_for bodies are always nested. Others start off as
+ normal functions. */
+ wd->nested = (type == CILK_BLOCK_FOR);
+ wd->arglist = NULL_TREE;
+ wd->argtypes = NULL_TREE;
+ wd->block = NULL_TREE;
+}
+
+/* Clears the wrapper data structure. */
+
+static void
+free_wd (struct wrapper_data *wd)
+{
+ pointer_map_destroy (wd->decl_map);
+ wd->nested = false;
+ wd->arglist = NULL_TREE;
+ wd->argtypes = NULL_TREE;
+ wd->parms = NULL_TREE;
+}
+
+
+ /* Given a variable in an expression to be extracted into
+ a helper function, declare the helper function parameter
+ to receive it.
+
+ On entry the value of the (key, value) pair may be
+
+ (*, error_mark_node) -- Variable is private to helper function,
+ do nothing.
+
+ (var, var) -- Reference to outer scope (function or global scope).
+
+ (var, integer 0) -- Capture by value, save newly-declared PARM_DECL
+ for value in value slot.
+
+ (var, integer 1) -- Capture by reference, declare pointer to type
+ as new PARM_DECL and store (spawn_stmt (indirect_ref (parm)).
+
+ (var, ???) -- Pure output argument, handled similarly to above.
+*/
+
+static bool
+declare_one_free_variable (const void *var0, void **map0,
+ void *data ATTRIBUTE_UNUSED)
+{
+ const_tree var = (const_tree) var0;
+ tree map = (tree)*map0;
+ tree var_type = TREE_TYPE (var), arg_type;
+ bool by_reference;
+ tree parm;
+
+ gcc_assert (DECL_P (var));
+
+ /* Ignore truly local variables. */
+ if (map == error_mark_node)
+ return true;
+ /* Ignore references to the parent function. */
+ if (map == var)
+ return true;
+
+ gcc_assert (TREE_CODE (map) == INTEGER_CST);
+
+ /* A value is passed by reference if:
+
+ 1. It is addressable, so that a copy may not be made.
+ 2. It is modified in the spawned statement.
+ In the future this function may want to arrange
+ a warning if the spawned statement is a loop body
+ because an output argument would indicate a race.
+ Note: Earlier passes must have marked the variable addressable.
+ 3. It is expensive to copy. */
+ by_reference =
+ (TREE_ADDRESSABLE (var_type)
+ /* Arrays must be passed by reference. This is required for C
+ semantics -- arrays are not first class objects. Other
+ aggregate types can and should be passed by reference if
+ they are not passed to the spawned function. We aren't yet
+ distinguishing safe uses in argument calculation from unsafe
+ uses as outgoing function arguments, so we make a copy to
+ stabilize the value. */
+ || TREE_CODE (var_type) == ARRAY_TYPE
+ || (tree) map == integer_one_node);
+
+ if (by_reference)
+ var_type = build_qualified_type (build_pointer_type (var_type),
+ TYPE_QUAL_RESTRICT);
+ gcc_assert (!TREE_ADDRESSABLE (var_type));
+
+ /* Maybe promote to int. */
+ if (INTEGRAL_TYPE_P (var_type) && COMPLETE_TYPE_P (var_type)
+ && INT_CST_LT_UNSIGNED (TYPE_SIZE (var_type),
+ TYPE_SIZE (integer_type_node)))
+ arg_type = integer_type_node;
+ else
+ arg_type = var_type;
+
+ parm = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL_TREE, var_type);
+ DECL_ARG_TYPE (parm) = arg_type;
+ DECL_ARTIFICIAL (parm) = 0;
+ TREE_READONLY (parm) = 1;
+
+ if (by_reference)
+ {
+ parm = build1 (INDIRECT_REF, TREE_TYPE (var_type), parm);
+ parm = build1 (PAREN_EXPR, void_type_node, parm);
+ }
+ *map0 = parm;
+ return true;
+}
+
+/* Returns a wrapper function for a _Cilk_spawn. */
+
+static tree
+create_cilk_wrapper (tree exp, tree *args_out)
+{
+ struct wrapper_data wd;
+ tree fndecl;
+
+ init_wd (&wd, CILK_BLOCK_SPAWN);
+
+ if (TREE_CODE (exp) == CONVERT_EXPR)
+ exp = TREE_OPERAND (exp, 0);
+
+ /* Special handling for top level INIT_EXPR. Usually INIT_EXPR means the
+ variable is defined in the spawned expression and can be private to the
+ spawn helper. A top level INIT_EXPR defines a variable to be initialized
+ by spawn and the variable must remain in the outer function. */
+ if (TREE_CODE (exp) == INIT_EXPR)
+ {
+ extract_free_variables (TREE_OPERAND (exp, 0), &wd, ADD_WRITE);
+ extract_free_variables (TREE_OPERAND (exp, 1), &wd, ADD_READ);
+ /* TREE_TYPE should be void. Be defensive. */
+ if (TREE_TYPE (exp) != void_type_node)
+ extract_free_variables (TREE_TYPE (exp), &wd, ADD_READ);
+ }
+ else
+ extract_free_variables (exp, &wd, ADD_READ);
+ pointer_map_traverse (wd.decl_map, declare_one_free_variable, &wd);
+ wd.block = TREE_BLOCK (exp);
+ if (!wd.block)
+ wd.block = DECL_INITIAL (current_function_decl);
+
+ /* Now fvars maps the old variable to incoming variable. Update
+ the expression and arguments to refer to the new names. */
+ fndecl = create_cilk_wrapper_body (exp, &wd);
+ *args_out = wd.arglist;
+
+ free_wd (&wd);
+
+ return fndecl;
+}
+
+/* Transform *SPAWN_P, a spawned CALL_EXPR, to gimple. *SPAWN_P can be a
+ CALL_EXPR, INIT_EXPR or MODIFY_EXPR. Returns GS_OK if everything is fine,
+ and GS_UNHANDLED, otherwise. */
+
+int
+gimplify_cilk_spawn (tree *spawn_p, gimple_seq *before ATTRIBUTE_UNUSED,
+ gimple_seq *after ATTRIBUTE_UNUSED)
+{
+ tree expr = *spawn_p;
+ tree function, call1, call2, new_args;
+ tree ii_args = NULL_TREE;
+ int total_args = 0, ii = 0;
+ tree *arg_array;
+ tree setjmp_cond_expr = NULL_TREE;
+ tree setjmp_expr, spawn_expr, setjmp_value = NULL_TREE;
+
+ cfun->calls_cilk_spawn = 1;
+ cfun->is_cilk_function = 1;
+
+ /* Remove CLEANUP_POINT_EXPR and EXPR_STMT from *spawn_p. */
+ while (TREE_CODE (expr) == CLEANUP_POINT_EXPR
+ || TREE_CODE (expr) == EXPR_STMT)
+ expr = TREE_OPERAND (expr, 0);
+
+ new_args = NULL;
+ function = create_cilk_wrapper (expr, &new_args);
+
+ /* This should give the number of parameters. */
+ total_args = list_length (new_args);
+ arg_array = XNEWVEC (tree, total_args);
+
+ ii_args = new_args;
+ for (ii = 0; ii < total_args; ii++)
+ {
+ arg_array[ii] = TREE_VALUE (ii_args);
+ ii_args = TREE_CHAIN (ii_args);
+ }
+
+ TREE_USED (function) = 1;
+ rest_of_decl_compilation (function, 0, 0);
+
+ call1 = cilk_call_setjmp (cfun->cilk_frame_decl);
+
+ if (*arg_array == NULL_TREE)
+ call2 = build_call_expr (function, 0);
+ else
+ call2 = build_call_expr_loc_array (EXPR_LOCATION (*spawn_p), function,
+ total_args, arg_array);
+ *spawn_p = alloc_stmt_list ();
+ tree f_ptr_type = build_pointer_type (TREE_TYPE (cfun->cilk_frame_decl));
+ tree frame_ptr = build1 (ADDR_EXPR, f_ptr_type, cfun->cilk_frame_decl);
+ tree save_fp = build_call_expr (cilk_save_fp_fndecl, 1, frame_ptr);
+ append_to_statement_list (save_fp, spawn_p);
+ setjmp_value = create_tmp_var (TREE_TYPE (call1), NULL);
+ setjmp_expr = fold_build2 (MODIFY_EXPR, void_type_node, setjmp_value, call1);
+
+ append_to_statement_list_force (setjmp_expr, spawn_p);
+
+ setjmp_cond_expr = fold_build2 (EQ_EXPR, TREE_TYPE (call1), setjmp_value,
+ build_int_cst (TREE_TYPE (call1), 0));
+ spawn_expr = fold_build3 (COND_EXPR, void_type_node, setjmp_cond_expr,
+ call2, build_empty_stmt (EXPR_LOCATION (call1)));
+ append_to_statement_list (spawn_expr, spawn_p);
+
+ return GS_OK;
+}
+
+/* Make the frames necessary for a spawn call. */
+
+tree
+make_cilk_frame (tree fn)
+{
+ struct function *f = DECL_STRUCT_FUNCTION (fn);
+ tree decl;
+
+ if (f->cilk_frame_decl)
+ return f->cilk_frame_decl;
+
+ decl = build_decl (EXPR_LOCATION (fn), VAR_DECL, NULL_TREE,
+ cilk_frame_type_decl);
+ DECL_CONTEXT (decl) = fn;
+ DECL_SEEN_IN_BIND_EXPR_P (decl) = 1;
+ f->cilk_frame_decl = decl;
+ return decl;
+}
+
+/* Returns a STATEMENT_LIST with all the pedigree operations required for
+ install body with frame cleanup functions. FRAME_PTR is the pointer to
+ __cilkrts_stack_frame created by make_cilk_frame. */
+
+tree
+cilk_install_body_pedigree_operations (tree frame_ptr)
+{
+ tree body_list = alloc_stmt_list ();
+ tree enter_frame = build_call_expr (cilk_enter_fast_fndecl, 1, frame_ptr);
+ append_to_statement_list (enter_frame, &body_list);
+
+ tree parent = cilk_arrow (frame_ptr, CILK_TI_FRAME_PARENT, 0);
+ tree worker = cilk_arrow (frame_ptr, CILK_TI_FRAME_WORKER, 0);
+
+ tree pedigree = cilk_arrow (frame_ptr, CILK_TI_FRAME_PEDIGREE, 0);
+ tree pedigree_rank = cilk_dot (pedigree, CILK_TI_PEDIGREE_RANK, 0);
+ tree parent_pedigree = cilk_dot (pedigree, CILK_TI_PEDIGREE_PARENT, 0);
+ tree pedigree_parent = cilk_arrow (parent, CILK_TI_FRAME_PEDIGREE, 0);
+ tree pedigree_parent_rank = cilk_dot (pedigree_parent,
+ CILK_TI_PEDIGREE_RANK, 0);
+ tree pedigree_parent_parent = cilk_dot (pedigree_parent,
+ CILK_TI_PEDIGREE_PARENT, 0);
+ tree worker_pedigree = cilk_arrow (worker, CILK_TI_WORKER_PEDIGREE, 1);
+ tree w_pedigree_rank = cilk_dot (worker_pedigree, CILK_TI_PEDIGREE_RANK, 0);
+ tree w_pedigree_parent = cilk_dot (worker_pedigree,
+ CILK_TI_PEDIGREE_PARENT, 0);
+
+ /* sf.pedigree.rank = worker->pedigree.rank. */
+ tree exp1 = build2 (MODIFY_EXPR, void_type_node, pedigree_rank,
+ w_pedigree_rank);
+ append_to_statement_list (exp1, &body_list);
+
+ /* sf.pedigree.parent = worker->pedigree.parent. */
+ exp1 = build2 (MODIFY_EXPR, void_type_node, parent_pedigree,
+ w_pedigree_parent);
+ append_to_statement_list (exp1, &body_list);
+
+ /* sf.call_parent->pedigree.rank = worker->pedigree.rank. */
+ exp1 = build2 (MODIFY_EXPR, void_type_node, pedigree_parent_rank,
+ w_pedigree_rank);
+ append_to_statement_list (exp1, &body_list);
+
+ /* sf.call_parent->pedigree.parent = worker->pedigree.parent. */
+ exp1 = build2 (MODIFY_EXPR, void_type_node, pedigree_parent_parent,
+ w_pedigree_parent);
+ append_to_statement_list (exp1, &body_list);
+
+ /* sf->worker.pedigree.rank = 0. */
+ exp1 = build2 (MODIFY_EXPR, void_type_node, w_pedigree_rank,
+ build_zero_cst (uint64_type_node));
+ append_to_statement_list (exp1, &body_list);
+
+ /* sf->pedigree.parent = &sf->pedigree. */
+ exp1 = build2 (MODIFY_EXPR, void_type_node, w_pedigree_parent,
+ build1 (ADDR_EXPR,
+ build_pointer_type (cilk_pedigree_type_decl),
+ pedigree));
+ append_to_statement_list (exp1, &body_list);
+ return body_list;
+}
+
+/* Inserts "cleanup" functions after the function-body of FNDECL. FNDECL is a
+ spawn-helper and BODY is the newly created body for FNDECL. */
+
+void
+c_cilk_install_body_w_frame_cleanup (tree fndecl, tree body)
+{
+ tree list = alloc_stmt_list ();
+ tree frame = make_cilk_frame (fndecl);
+ tree dtor = create_cilk_function_exit (frame, false, true);
+ add_local_decl (cfun, frame);
+
+ DECL_SAVED_TREE (fndecl) = list;
+ tree frame_ptr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (frame)),
+ frame);
+ tree body_list = cilk_install_body_pedigree_operations (frame_ptr);
+ gcc_assert (TREE_CODE (body_list) == STATEMENT_LIST);
+
+ tree detach_expr = build_call_expr (cilk_detach_fndecl, 1, frame_ptr);
+ append_to_statement_list (detach_expr, &body_list);
+ append_to_statement_list (body, &body_list);
+ append_to_statement_list (build_stmt (EXPR_LOCATION (body), TRY_FINALLY_EXPR,
+ body_list, dtor), &list);
+}
+
+/* Add a new variable, VAR to a variable list in WD->DECL_MAP. HOW indicates
+ whether the variable is previously defined, currently defined, or a variable
+ that is being written to. */
+
+static void
+add_variable (struct wrapper_data *wd, tree var, enum add_variable_type how)
+{
+ void **valp;
+
+ valp = pointer_map_contains (wd->decl_map, (void *) var);
+ if (valp)
+ {
+ tree val = (tree) *valp;
+ /* If the variable is local, do nothing. */
+ if (val == error_mark_node)
+ return;
+ /* If the variable was entered with itself as value,
+ meaning it belongs to an outer scope, do not alter
+ the value. */
+ if (val == var)
+ return;
+ /* A statement expression may cause a variable to be
+ bound twice, once in BIND_EXPR and again in a
+ DECL_EXPR. That case caused a return in the
+ test above. Any other duplicate definition is
+ an error. */
+ gcc_assert (how != ADD_BIND);
+ if (how != ADD_WRITE)
+ return;
+ /* This variable might have been entered as read but is now written. */
+ *valp = (void *) var;
+ wd->nested = true;
+ return;
+ }
+ else
+ {
+ tree val = NULL_TREE;
+
+ /* Nested function rewriting silently discards hard register
+ assignments for function scope variables, and they wouldn't
+ work anyway. Warn here. This misses one case: if the
+ register variable is used as the loop bound or increment it
+ has already been added to the map. */
+ if ((how != ADD_BIND) && (TREE_CODE (var) == VAR_DECL)
+ && !DECL_EXTERNAL (var) && DECL_HARD_REGISTER (var))
+ warning (0, "register assignment ignored for %qD used in Cilk block",
+ var);
+
+ switch (how)
+ {
+ /* ADD_BIND means always make a fresh new variable. */
+ case ADD_BIND:
+ val = error_mark_node;
+ break;
+ /* ADD_READ means
+ 1. For cilk_for, refer to the outer scope definition as-is
+ 2. For a spawned block, take a scalar in an rgument
+ and otherwise refer to the outer scope definition as-is.
+ 3. For a spawned call, take a scalar in an argument. */
+ case ADD_READ:
+ switch (wd->type)
+ {
+ case CILK_BLOCK_FOR:
+ val = var;
+ break;
+ case CILK_BLOCK_SPAWN:
+ if (TREE_ADDRESSABLE (var))
+ {
+ val = var;
+ wd->nested = true;
+ break;
+ }
+ val = integer_zero_node;
+ break;
+ }
+ break;
+ case ADD_WRITE:
+ switch (wd->type)
+ {
+ case CILK_BLOCK_FOR:
+ val = var;
+ wd->nested = true;
+ break;
+ case CILK_BLOCK_SPAWN:
+ if (TREE_ADDRESSABLE (var))
+ val = integer_one_node;
+ else
+ {
+ val = var;
+ wd->nested = true;
+ }
+ break;
+ }
+ }
+ *pointer_map_insert (wd->decl_map, (void *) var) = val;
+ }
+}
+
+/* Find the variables referenced in an expression T. This does not avoid
+ duplicates because a variable may be read in one context and written in
+ another. HOW describes the context in which the reference is seen. If
+ NESTED is true a nested function is being generated and variables in the
+ original context should not be remapped. */
+
+static void
+extract_free_variables (tree t, struct wrapper_data *wd,
+ enum add_variable_type how)
+{
+ if (t == NULL_TREE)
+ return;
+
+ enum tree_code code = TREE_CODE (t);
+ bool is_expr = IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code));
+
+ if (is_expr)
+ extract_free_variables (TREE_TYPE (t), wd, ADD_READ);
+
+ switch (code)
+ {
+ case ERROR_MARK:
+ case IDENTIFIER_NODE:
+ case INTEGER_CST:
+ case REAL_CST:
+ case FIXED_CST:
+ case STRING_CST:
+ case BLOCK:
+ case PLACEHOLDER_EXPR:
+ case FIELD_DECL:
+ case VOID_TYPE:
+ case REAL_TYPE:
+ /* These do not contain variable references. */
+ return;
+
+ case SSA_NAME:
+ /* Currently we don't see SSA_NAME. */
+ extract_free_variables (SSA_NAME_VAR (t), wd, how);
+ return;
+
+ case LABEL_DECL:
+ /* This might be a reference to a label outside the Cilk block,
+ which is an error, or a reference to a label in the Cilk block
+ that we haven't seen yet. We can't tell. Ignore it. An
+ invalid use will cause an error later in copy_decl_for_cilk. */
+ return;
+
+ case RESULT_DECL:
+ if (wd->type != CILK_BLOCK_SPAWN)
+ TREE_ADDRESSABLE (t) = 1;
+ case VAR_DECL:
+ case PARM_DECL:
+ if (!TREE_STATIC (t) && !DECL_EXTERNAL (t))
+ add_variable (wd, t, how);
+ return;
+
+ case NON_LVALUE_EXPR:
+ case CONVERT_EXPR:
+ case NOP_EXPR:
+ extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_READ);
+ return;
+
+ case INIT_EXPR:
+ extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_BIND);
+ extract_free_variables (TREE_OPERAND (t, 1), wd, ADD_READ);
+ return;
+
+ case MODIFY_EXPR:
+ case PREDECREMENT_EXPR:
+ case PREINCREMENT_EXPR:
+ case POSTDECREMENT_EXPR:
+ case POSTINCREMENT_EXPR:
+ /* These write their result. */
+ extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_WRITE);
+ extract_free_variables (TREE_OPERAND (t, 1), wd, ADD_READ);
+ return;
+
+ case ADDR_EXPR:
+ /* This might modify its argument, and the value needs to be
+ passed by reference in any case to preserve identity and
+ type if is a promoting type. In the case of a nested loop
+ just notice that we touch the variable. It will already
+ be addressable, and marking it modified will cause a spurious
+ warning about writing the control variable. */
+ if (wd->type != CILK_BLOCK_SPAWN)
+ extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_READ);
+ else
+ extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_WRITE);
+ return;
+
+ case ARRAY_REF:
+ /* Treating ARRAY_REF and BIT_FIELD_REF identically may
+ mark the array as written but the end result is correct
+ because the array is passed by pointer anyway. */
+ case BIT_FIELD_REF:
+ /* Propagate the access type to the object part of which
+ is being accessed here. As for ADDR_EXPR, don't do this
+ in a nested loop, unless the access is to a fixed index. */
+ if (wd->type != CILK_BLOCK_FOR || TREE_CONSTANT (TREE_OPERAND (t, 1)))
+ extract_free_variables (TREE_OPERAND (t, 0), wd, how);
+ else
+ extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_READ);
+ extract_free_variables (TREE_OPERAND (t, 1), wd, ADD_READ);
+ extract_free_variables (TREE_OPERAND (t, 2), wd, ADD_READ);
+ return;
+
+ case TREE_LIST:
+ extract_free_variables (TREE_PURPOSE (t), wd, ADD_READ);
+ extract_free_variables (TREE_VALUE (t), wd, ADD_READ);
+ extract_free_variables (TREE_CHAIN (t), wd, ADD_READ);
+ return;
+
+ case TREE_VEC:
+ {
+ int len = TREE_VEC_LENGTH (t);
+ int i;
+ for (i = 0; i < len; i++)
+ extract_free_variables (TREE_VEC_ELT (t, i), wd, ADD_READ);
+ return;
+ }
+
+ case VECTOR_CST:
+ {
+ unsigned ii = 0;
+ for (ii = 0; ii < VECTOR_CST_NELTS (t); ii++)
+ extract_free_variables (VECTOR_CST_ELT (t, ii), wd, ADD_READ);
+ break;
+ }
+
+ case COMPLEX_CST:
+ extract_free_variables (TREE_REALPART (t), wd, ADD_READ);
+ extract_free_variables (TREE_IMAGPART (t), wd, ADD_READ);
+ return;
+
+ case BIND_EXPR:
+ {
+ tree decl;
+ for (decl = BIND_EXPR_VARS (t); decl; decl = TREE_CHAIN (decl))
+ {
+ add_variable (wd, decl, ADD_BIND);
+ /* A self-referential initialization is no problem because
+ we already entered the variable into the map as local. */
+ extract_free_variables (DECL_INITIAL (decl), wd, ADD_READ);
+ extract_free_variables (DECL_SIZE (decl), wd, ADD_READ);
+ extract_free_variables (DECL_SIZE_UNIT (decl), wd, ADD_READ);
+ }
+ extract_free_variables (BIND_EXPR_BODY (t), wd, ADD_READ);
+ return;
+ }
+
+ case STATEMENT_LIST:
+ {
+ tree_stmt_iterator i;
+ for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i))
+ extract_free_variables (*tsi_stmt_ptr (i), wd, ADD_READ);
+ return;
+ }
+
+ case TARGET_EXPR:
+ {
+ extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_BIND);
+ extract_free_variables (TREE_OPERAND (t, 1), wd, ADD_READ);
+ extract_free_variables (TREE_OPERAND (t, 2), wd, ADD_READ);
+ if (TREE_OPERAND (t, 3) != TREE_OPERAND (t, 1))
+ extract_free_variables (TREE_OPERAND (t, 3), wd, ADD_READ);
+ return;
+ }
+
+ case RETURN_EXPR:
+ if (TREE_NO_WARNING (t))
+ {
+ gcc_assert (errorcount);
+ return;
+ }
+ return;
+
+ case DECL_EXPR:
+ if (TREE_CODE (DECL_EXPR_DECL (t)) != TYPE_DECL)
+ extract_free_variables (DECL_EXPR_DECL (t), wd, ADD_BIND);
+ return;
+
+ case INTEGER_TYPE:
+ case ENUMERAL_TYPE:
+ case BOOLEAN_TYPE:
+ extract_free_variables (TYPE_MIN_VALUE (t), wd, ADD_READ);
+ extract_free_variables (TYPE_MAX_VALUE (t), wd, ADD_READ);
+ return;
+
+ case POINTER_TYPE:
+ extract_free_variables (TREE_TYPE (t), wd, ADD_READ);
+ break;
+
+ case ARRAY_TYPE:
+ extract_free_variables (TREE_TYPE (t), wd, ADD_READ);
+ extract_free_variables (TYPE_DOMAIN (t), wd, ADD_READ);
+ return;
+
+ case RECORD_TYPE:
+ extract_free_variables (TYPE_FIELDS (t), wd, ADD_READ);
+ return;
+
+ case METHOD_TYPE:
+ extract_free_variables (TYPE_ARG_TYPES (t), wd, ADD_READ);
+ extract_free_variables (TYPE_METHOD_BASETYPE (t), wd, ADD_READ);
+ return;
+
+ case AGGR_INIT_EXPR:
+ case CALL_EXPR:
+ {
+ int len = 0;
+ int ii = 0;
+ if (TREE_CODE (TREE_OPERAND (t, 0)) == INTEGER_CST)
+ {
+ len = TREE_INT_CST_LOW (TREE_OPERAND (t, 0));
+
+ for (ii = 0; ii < len; ii++)
+ extract_free_variables (TREE_OPERAND (t, ii), wd, ADD_READ);
+ extract_free_variables (TREE_TYPE (t), wd, ADD_READ);
+ }
+ break;
+ }
+
+ default:
+ if (is_expr)
+ {
+ int i, len;
+
+ /* Walk over all the sub-trees of this operand. */
+ len = TREE_CODE_LENGTH (code);
+
+ /* Go through the subtrees. We need to do this in forward order so
+ that the scope of a FOR_EXPR is handled properly. */
+ for (i = 0; i < len; ++i)
+ extract_free_variables (TREE_OPERAND (t, i), wd, ADD_READ);
+ }
+ }
+}
+
+
+/* Add appropriate frames needed for a Cilk spawned function call, FNDECL.
+ Returns the __cilkrts_stack_frame * variable. */
+
+tree
+insert_cilk_frame (tree fndecl)
+{
+ tree addr, body, enter, out, orig_body;
+ location_t loc = EXPR_LOCATION (fndecl);
+
+ if (!cfun || cfun->decl != fndecl)
+ push_cfun (DECL_STRUCT_FUNCTION (fndecl));
+
+ tree decl = cfun->cilk_frame_decl;
+ if (!decl)
+ {
+ tree *saved_tree = &DECL_SAVED_TREE (fndecl);
+ decl = make_cilk_frame (fndecl);
+ add_local_decl (cfun, decl);
+
+ addr = build1 (ADDR_EXPR, cilk_frame_ptr_type_decl, decl);
+ enter = build_call_expr (cilk_enter_fndecl, 1, addr);
+ out = create_cilk_function_exit (cfun->cilk_frame_decl, false, true);
+
+ /* The new body will be:
+ __cilkrts_enter_frame_1 (&sf);
+ try {
+ orig_body;
+ }
+ finally {
+ __cilkrts_pop_frame (&sf);
+ __cilkrts_leave_frame (&sf);
+ } */
+
+ body = alloc_stmt_list ();
+ orig_body = *saved_tree;
+
+ if (TREE_CODE (orig_body) == BIND_EXPR)
+ orig_body = BIND_EXPR_BODY (orig_body);
+
+ append_to_statement_list (enter, &body);
+ append_to_statement_list (build_stmt (loc, TRY_FINALLY_EXPR, orig_body,
+ out), &body);
+ if (TREE_CODE (*saved_tree) == BIND_EXPR)
+ BIND_EXPR_BODY (*saved_tree) = body;
+ else
+ *saved_tree = body;
+ }
+ return decl;
+}
+
+/* Wraps CALL, a CALL_EXPR, into a CILK_SPAWN_STMT tree and returns it. */
+
+tree
+build_cilk_spawn (location_t loc, tree call)
+{
+ if (!cilk_set_spawn_marker (loc, call))
+ return error_mark_node;
+ tree spawn_stmt = build1 (CILK_SPAWN_STMT, TREE_TYPE (call), call);
+ TREE_SIDE_EFFECTS (spawn_stmt) = 1;
+ return spawn_stmt;
+}
+
+/* Returns a tree of type CILK_SYNC_STMT. */
+
+tree
+build_cilk_sync (void)
+{
+ tree sync = build0 (CILK_SYNC_STMT, void_type_node);
+ TREE_SIDE_EFFECTS (sync) = 1;
+ return sync;
+}
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 81b2018e8c0..e38bcb8cdbd 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,280 @@
+2013-11-07 Joseph Myers <joseph@codesourcery.com>
+ Andrew MacLeod <amacleod@redhat.com>
+
+ * c-aux-info.c (gen_type): Handle atomic qualifier.
+ * c-decl.c (validate_proto_after_old_defn): Do not remove atomic
+ qualifiers when compating types.
+ (shadow_tag_warned): Handle atomic_p in declspecs.
+ (quals_from_declspecs): Likewise.
+ (start_decl): Use c_type_promotes_to when promoting argument
+ types.
+ (grokdeclarator): Handle _Atomic.
+ (get_parm_info): Diagnose any qualifier on "void" as only
+ parameter.
+ (store_parm_decls_oldstyle): Do not remove atomic qualifiers when
+ comparing types. Use c_type_promotes_to when promoting argument
+ types.
+ (finish_function): Use c_type_promotes_to when promoting argument
+ types.
+ (build_null_declspecs): Handle atomic_p in declspecs.
+ (declspecs_add_qual): Handle RID_ATOMIC.
+ * c-parser.c (c_token_starts_typename, c_token_is_qualifier)
+ (c_token_starts_declspecs): Handle RID_ATOMIC.
+ (c_parser_declspecs): Handle atomic type specifiers and
+ qualifiers.
+ (c_parser_typeof_specifier): Remove const and _Atomic qualifiers
+ from types of expressions with atomic type.
+ (c_parser_direct_declarator_inner): Use convert_lvalue_to_rvalue.
+ (c_parser_attribute_any_word): Handle RID_ATOMIC.
+ (c_parser_initializer, c_parser_initelt, c_parser_initval)
+ (c_parser_statement_after_labels, c_parser_switch_statement)
+ (c_parser_for_statement, c_parser_expr_no_commas)
+ (c_parser_conditional_expression, c_parser_binary_expression)
+ (c_parser_cast_expression, c_parser_unary_expression)
+ (c_parser_postfix_expression)
+ (c_parser_postfix_expression_after_primary, c_parser_expression):
+ Use convert_lvalue_to_rvalue.
+ (c_parser_expression_conv, c_parser_expr_list): Document
+ conversion of lvalues to rvalues. Use convert_lvalue_to_rvalue.
+ (c_parser_objc_synchronized_statement): Use
+ convert_lvalue_to_rvalue.
+ (c_parser_objc_selector): Handle RID_ATOMIC.
+ (c_parser_objc_receiver, c_parser_array_notation): Use
+ convert_lvalue_to_rvalue.
+ * c-tree.h (ctsk_typeof): Adjust comment to mention use for
+ _Atomic (type-name).
+ (struct c_declspecs): Add atomic_p field.
+ (convert_lvalue_to_rvalue): Declare.
+ * c-typeck.c (c_type_promotes_to): Promote atomic types to
+ corresponding atomic types.
+ (qualify_type): Don't add _Atomic qualifiers from second argument.
+ (comp_target_types): Do not allow _Atomic mismatches.
+ (type_lists_compatible_p): Do not remove atomic qualifiers when
+ comparing types.
+ (really_atomic_lvalue, convert_lvalue_to_rvalue)
+ (build_atomic_assign): New functions.
+ (build_unary_op): Use build_atomic_assign for atomic increment and
+ decrement.
+ (build_conditional_expr): Do not treat _Atomic void as a qualified
+ version of void.
+ (build_modify_expr): Use build_atomic_assign for atomic LHS.
+ (find_anonymous_field_with_type, convert_to_anonymous_field)
+ (convert_for_assignment): Do not remove atomic qualifiers when
+ comparing types.
+ (digest_init): Do not accept initialization of arrays of atomic
+ elements by string constants.
+ (build_asm_expr): Use convert_lvalue_to_rvalue.
+ (build_binary_op): Do not treat _Atomic void as a qualified
+ version of void.
+
+2013-11-06 DJ Delorie <dj@redhat.com>
+
+ * c-decl.c (locate_old_decl): If a previous conflicting decl is
+ both explicit and builtin, print the location of the explicit one.
+
+2013-11-05 Tobias Burnus <burnus@net-b.de>
+
+ * c-parser.c (c_parser_omp_for, c_parser_omp_parallel,
+ c_parser_omp_distribute, c_parser_omp_teams,
+ c_parser_omp_target, c_parser_omp_declare): Handle
+ -fopenmp-simd.
+
+2013-11-03 Marek Polacek <polacek@redhat.com>
+
+ * c-decl.c (grokdeclarator): Add VLA instrumentation.
+
+2013-11-01 Jakub Jelinek <jakub@redhat.com>
+
+ * c-typeck.c (c_finish_omp_clauses) <case OMP_CLAUSE_UNIFORM>: Go to
+ check_dup_generic at the end, unless remove is true.
+ (c_finish_omp_clauses) <case OMP_CLAUSE_REDUCTION>: Add break; after
+ remove = true;.
+ (c_finish_omp_clauses) <case OMP_CLAUSE_COPYIN>: Likewise.
+
+2013-10-31 Jakub Jelinek <jakub@redhat.com>
+
+ * c-typeck.c (c_finish_omp_clauses): Diagnose aligned clause
+ with decl that is not pointer nor array.
+
+2013-10-29 Balaji V. Iyer <balaji.v.iyer@intel.com>
+
+ * c-decl.c (finish_function): Added a call for insert_cilk_frame when
+ a spawning function is found.
+ * c-objc-common.h (LANG_HOOKS_CILKPLUS_GIMPLIFY_SPAWN): New #define.
+ (LANG_HOOKS_CILKPLUS_FRAME_CLEANUP): Likewise.
+ (LANG_HOOKS_CILKPLUS_DETECT_SPAWN_AND_UNWRAP): Likewise.
+ * c-parser.c (c_parser_statement_after_labels): Added RID_CILK_SYNC
+ case.
+ (c_parser_postfix_expression): Added RID_CILK_SPAWN case.
+ * c-typeck.c (build_compound_expr): Reject _Cilk_spawn in a comma
+ expr.
+ (c_finish_return): Added a check to reject _Cilk_spawn in return
+ expression.
+ (build_cilk_spawn): New function.
+ (build_cilk_sync): Likewise.
+ * Makefile.in (c-decl.o): Added cilk.h in dependency list.
+
+2013-10-27 Tobias Burnus <burnus@net-b.de>
+
+ PR other/33426
+ * c-parser.c (c_parser_while_statement, c_parser_while_statement,
+ c_parser_pragma): Add GCC ivdep support to 'do' and 'while'.
+ (c_parser_statement_after_labels): Update calls.
+
+2013-10-24 Tobias Burnus <burnus@net-b.de>
+
+ PR other/33426
+ * c-parser.c (c_parser_pragma, c_parser_for_statement):
+ Handle PRAGMA_IVDEP.
+ (c_parser_statement_after_labels): Update call.
+
+2013-10-24 Marek Polacek <polacek@redhat.com>
+
+ * c-parser.c (c_parser_struct_declaration): Add a comment.
+ (c_parser_declarator): Don't allow _Alignas here.
+
+2013-10-17 Andrew MacLeod <amacleod@redhat.com>
+
+ * c-parser.c: Include omp-low.h.
+ * c-typeck.c: Likewise.
+
+2013-10-17 Marek Polacek <polacek@redhat.com>
+
+ PR c/58267
+ * c-parser.c (c_parser_declspecs): Add alignspec_ok parameter.
+ Document syntax of the array-declarator.
+ (c_parser_declspecs) <RID_ALIGNAS>: Bail out if alignment specs
+ are not permitted.
+ (c_parser_declaration_or_fndef): Adjust c_parser_declspecs call.
+ (c_parser_struct_declaration): Likewise.
+ (c_parser_declarator): Likewise.
+ (c_parser_direct_declarator_inner): Likewise.
+ (c_parser_parameter_declaration): Likewise.
+ (c_parser_type_name): Likewise.
+
+2013-10-11 Jakub Jelinek <jakub@redhat.com>
+
+ * c-lang.h (current_omp_declare_target_attribute): New extern
+ decl.
+ * c-parser.c: Include c-lang.h.
+ (struct c_parser): Change tokens to c_token *.
+ Add tokens_buf field. Change tokens_avail type to unsigned int.
+ (c_parser_consume_token): If parser->tokens isn't
+ &parser->tokens_buf[0], increment parser->tokens.
+ (c_parser_consume_pragma): Likewise.
+ (enum pragma_context): Add pragma_struct and pragma_param.
+ (c_parser_external_declaration): Adjust
+ c_parser_declaration_or_fndef caller.
+ (c_parser_declaration_or_fndef): Add omp_declare_simd_clauses
+ argument, if it is non-vNULL vector, call c_finish_omp_declare_simd.
+ Adjust recursive call.
+ (c_parser_struct_or_union_specifier): Use pragma_struct instead
+ of pragma_external.
+ (c_parser_parameter_declaration): Use pragma_param instead of
+ pragma_external.
+ (c_parser_compound_statement_nostart, c_parser_label,
+ c_parser_for_statement): Adjust
+ c_parser_declaration_or_fndef callers.
+ (c_parser_expr_no_commas): Add omp_atomic_lhs argument, pass
+ it through to c_parser_conditional_expression.
+ (c_parser_conditional_expression): Add omp_atomic_lhs argument,
+ pass it through to c_parser_binary_expression. Adjust recursive
+ call.
+ (c_parser_binary_expression): Remove prec argument, add
+ omp_atomic_lhs argument instead. Always start from PREC_NONE, if
+ omp_atomic_lhs is non-NULL and one of the arguments of toplevel
+ binop matches it, use build2 instead of parser_build_binary_op.
+ (c_parser_pragma): Handle PRAGMA_OMP_CANCEL,
+ PRAGMA_OMP_CANCELLATION_POINT, PRAGMA_OMP_TARGET,
+ PRAGMA_OMP_END_DECLARE_TARGET, PRAGMA_OMP_DECLARE_REDUCTION.
+ Handle pragma_struct and pragma_param the same as pragma_external.
+ (c_parser_omp_clause_name): Parse new OpenMP 4.0 clause names.
+ (c_parser_omp_variable_list): Parse array sections for
+ OMP_CLAUSE_{DEPEND,MAP,TO,FROM} clauses.
+ (c_parser_omp_clause_collapse): Fully fold collapse expression.
+ (c_parser_omp_clause_reduction): Handle user defined reductions.
+ (c_parser_omp_clause_branch, c_parser_omp_clause_cancelkind,
+ c_parser_omp_clause_num_teams, c_parser_omp_clause_thread_limit,
+ c_parser_omp_clause_aligned, c_parser_omp_clause_linear,
+ c_parser_omp_clause_safelen, c_parser_omp_clause_simdlen,
+ c_parser_omp_clause_depend, c_parser_omp_clause_map,
+ c_parser_omp_clause_device, c_parser_omp_clause_dist_schedule,
+ c_parser_omp_clause_proc_bind, c_parser_omp_clause_to,
+ c_parser_omp_clause_from, c_parser_omp_clause_uniform): New functions.
+ (c_parser_omp_all_clauses): Add finish_p argument. Don't call
+ c_finish_omp_clauses if it is false. Handle new OpenMP 4.0 clauses.
+ (c_parser_omp_atomic): Parse seq_cst clause, pass true if it is
+ present to c_finish_omp_atomic. Handle OpenMP 4.0 atomic forms.
+ (c_parser_omp_for_loop): Add CODE argument, pass it through
+ to c_finish_omp_for. Change last argument to cclauses,
+ and adjust uses to grab parallel clauses from the array of all
+ the split clauses. Adjust c_parser_binary_expression,
+ c_parser_declaration_or_fndef and c_finish_omp_for callers.
+ (omp_split_clauses): New function.
+ (c_parser_omp_simd): New function.
+ (c_parser_omp_for): Add p_name, mask and cclauses arguments.
+ Allow the function to be called also when parsing combined constructs,
+ and call c_parser_omp_simd when parsing for simd.
+ (c_parser_omp_sections_scope): If section-sequence doesn't start with
+ #pragma omp section, require exactly one structured-block instead of
+ sequence of statements.
+ (c_parser_omp_sections): Add p_name, mask and cclauses arguments.
+ Allow the function to be called also when parsing combined constructs.
+ (c_parser_omp_parallel): Add p_name, mask and cclauses arguments.
+ Allow the function to be called also when parsing combined
+ constructs.
+ (c_parser_omp_taskgroup, c_parser_omp_cancel,
+ c_parser_omp_cancellation_point, c_parser_omp_distribute,
+ c_parser_omp_teams, c_parser_omp_target_data,
+ c_parser_omp_target_update, c_parser_omp_target,
+ c_parser_omp_declare_simd, c_finish_omp_declare_simd,
+ c_parser_omp_declare_target, c_parser_omp_end_declare_target,
+ c_parser_omp_declare_reduction, c_parser_omp_declare): New functions.
+ (c_parser_omp_construct): Add p_name and mask vars. Handle
+ PRAGMA_OMP_DISTRIBUTE, PRAGMA_OMP_SIMD, PRAGMA_OMP_TASKGROUP,
+ PRAGMA_OMP_TEAMS. Adjust c_parser_omp_for, c_parser_omp_parallel
+ and c_parser_omp_sections callers.
+ (c_parse_file): Initialize tparser.tokens and the_parser->tokens here.
+ (OMP_FOR_CLAUSE_MASK, OMP_SECTIONS_CLAUSE_MASK,
+ OMP_SINGLE_CLAUSE_MASK): Use OMP_CLAUSE_MASK_1 instead of 1.
+ (OMP_PARALLEL_CLAUSE_MASK): Likewise. Add OMP_CLAUSE_PROC_BIND.
+ (OMP_TASK_CLAUSE_MASK): Use OMP_CLAUSE_MASK_1 instead of 1. Add
+ OMP_CLAUSE_DEPEND.
+ (OMP_SIMD_CLAUSE_MASK, OMP_CANCEL_CLAUSE_MASK,
+ OMP_CANCELLATION_POINT_CLAUSE_MASK, OMP_DISTRIBUTE_CLAUSE_MASK,
+ OMP_TEAMS_CLAUSE_MASK, OMP_TARGET_DATA_CLAUSE_MASK,
+ OMP_TARGET_UPDATE_CLAUSE_MASK, OMP_TARGET_CLAUSE_MASK,
+ OMP_DECLARE_SIMD_CLAUSE_MASK): Define.
+ * c-typeck.c: Include tree-inline.h.
+ (c_finish_omp_cancel, c_finish_omp_cancellation_point,
+ handle_omp_array_sections_1, handle_omp_array_sections,
+ c_clone_omp_udr, c_find_omp_placeholder_r): New functions.
+ (c_finish_omp_clauses): Handle new OpenMP 4.0 clauses and
+ user defined reductions.
+ (c_tree_equal): New function.
+ * c-tree.h (temp_store_parm_decls, temp_pop_parm_decls,
+ c_finish_omp_cancel, c_finish_omp_cancellation_point, c_tree_equal,
+ c_omp_reduction_id, c_omp_reduction_decl, c_omp_reduction_lookup,
+ c_check_omp_declare_reduction_r): New prototypes.
+ * c-decl.c (current_omp_declare_target_attribute): New variable.
+ (c_decl_attributes): New function.
+ (start_decl, start_function): Use it instead of decl_attributes.
+ (temp_store_parm_decls, temp_pop_parm_decls, c_omp_reduction_id,
+ c_omp_reduction_decl, c_omp_reduction_lookup,
+ c_check_omp_declare_reduction_r): New functions.
+
+2013-09-25 Tom Tromey <tromey@redhat.com>
+
+ * Make-lang.in (c/gccspec.o): Remove.
+ (CFLAGS-c/gccspec.o): New variable.
+ (cc1-checksum.o, C_TREE_H, c/c-aux-info.o, c/c-convert.o)
+ (c/c-decl.o, c/c-errors.o, c/c-lang.o, c/c-objc-common.o)
+ (c/c-parser.o, c/c-typeck.o, c/c-array-notation.o): Remove.
+
+2013-09-25 Tom Tromey <tromey@redhat.com>
+
+ * Make-lang.in (c/gccspec.o): Don't use subshell.
+
2013-09-18 Marek Polacek <polacek@redhat.com>
PR sanitize/58443
@@ -78,7 +355,7 @@
PR c++/57793
* c-decl.c (finish_struct): Check for too-large class.
-2013-07-04 Joern Rennecke <joern.rennecke@embecosm.com>
+2013-07-04 Joern Rennecke <joern.rennecke@embecosm.com>
PR c/57821
* c-typeck.c (set_init_index): When folding, check for index overflow.
diff --git a/gcc/c/Make-lang.in b/gcc/c/Make-lang.in
index 1161742c274..d79fc4f410c 100644
--- a/gcc/c/Make-lang.in
+++ b/gcc/c/Make-lang.in
@@ -44,12 +44,7 @@ c: cc1$(exeext)
# 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).
-c/gccspec.o: c/gccspec.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(GCC_H) \
- $(OPTS_H)
- (SHLIB='$(SHLIB)'; \
- $(COMPILER) $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) \
- $(DRIVER_DEFINES) \
- -c $(srcdir)/c/gccspec.c $(OUTPUT_OPTION))
+CFLAGS-c/gccspec.o += $(DRIVER_DEFINES)
# The C compiler itself.
@@ -72,8 +67,6 @@ cc1-checksum.c : build/genchecksum$(build_exeext) checksum-options \
checksum-options > cc1-checksum.c.tmp && \
$(srcdir)/../move-if-change cc1-checksum.c.tmp cc1-checksum.c
-cc1-checksum.o : cc1-checksum.c $(CONFIG_H) $(SYSTEM_H)
-
cc1$(exeext): $(C_OBJS) cc1-checksum.o $(BACKEND) $(LIBDEPS)
+$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ $(C_OBJS) \
cc1-checksum.o $(BACKEND) $(LIBS) $(BACKENDLIBS)
@@ -145,55 +138,3 @@ c.stageprofile: stageprofile-start
c.stagefeedback: stagefeedback-start
-mv c/*$(objext) stagefeedback/c
-#
-# .o: .h dependencies.
-# C language specific files.
-C_TREE_H = c/c-tree.h $(C_COMMON_H) $(DIAGNOSTIC_H)
-c/c-aux-info.o : c/c-aux-info.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(C_TREE_H) $(TREE_H) $(FLAGS_H)
-
-c/c-convert.o : c/c-convert.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(TREE_H) $(C_TREE_H) $(FLAGS_H) $(C_COMMON_H) convert.h \
- langhooks.h $(TARGET_H)
-
-c/c-decl.o : c/c-decl.c c/c-lang.h $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(TREE_H) $(C_TREE_H) $(GGC_H) $(TARGET_H) $(FLAGS_H) $(FUNCTION_H) \
- output.h debug.h toplev.h intl.h $(TM_P_H) $(TREE_INLINE_H) \
- $(TIMEVAR_H) $(OPTS_H) $(C_PRAGMA_H) gt-c-c-decl.h $(CGRAPH_H) \
- $(HASH_TABLE_H) $(LANGHOOKS_DEF_H) \
- dumpfile.h $(C_COMMON_H) $(CPPLIB_H) $(DIAGNOSTIC_CORE_H) \
- $(INPUT_H) langhooks.h pointer-set.h tree-iterator.h \
- $(PLUGIN_H) c-family/c-ada-spec.h c-family/c-objc.h
-
-c/c-errors.o: c/c-errors.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
- $(C_TREE_H) $(FLAGS_H) $(DIAGNOSTIC_H) $(TM_P_H)
-
-c/c-lang.o : c/c-lang.c c/c-objc-common.h \
- $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
- $(C_TREE_H) $(DIAGNOSTIC_CORE_H) \
- langhooks.h $(LANGHOOKS_DEF_H) $(C_COMMON_H) gtype-c.h \
- $(C_PRAGMA_H) $(TREE_INLINE_H)
-
-c/c-objc-common.o : c/c-objc-common.c c/c-objc-common.h \
- $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TREE_H) $(C_TREE_H) $(FLAGS_H) $(DIAGNOSTIC_H) \
- langhooks.h $(GGC_H) $(C_PRETTY_PRINT_H) intl.h \
- $(TREE_PRETTY_PRINT_H)
-
-c/c-parser.o : c/c-parser.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(TREE_H) $(C_TREE_H) $(C_COMMON_H) $(C_PRAGMA_H) $(CPPLIB_H) \
- $(GGC_H) $(TIMEVAR_H) $(INPUT_H) $(FLAGS_H) \
- gt-c-c-parser.h langhooks.h \
- $(VEC_H) $(TARGET_H) $(CGRAPH_H) $(PLUGIN_H) \
- c-family/c-objc.h
-
-c/c-typeck.o : c/c-typeck.c c/c-lang.h $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(TREE_H) $(C_TREE_H) $(TARGET_H) $(FLAGS_H) intl.h \
- langhooks.h tree-iterator.h $(BITMAP_H) $(GIMPLE_H) \
- c-family/c-objc.h c-family/c-common.h
-
-c/c-array-notation.o: c/c-array-notation.c c/c-lang.h $(CONFIG_H) \
- $(SYSTEM_H) coretypes.h $(TREE_H) $(C_TREE_H) $(TARGET_H) \
- intl.h output.h $(EXPR_H) langhooks.h tree-iterator.h $(BITMAP_H) \
- $(GIMPLE_H) c-family/c-objc.h
-
diff --git a/gcc/c/c-aux-info.c b/gcc/c/c-aux-info.c
index dd9c7685bc6..823a3c49f6f 100644
--- a/gcc/c/c-aux-info.c
+++ b/gcc/c/c-aux-info.c
@@ -285,6 +285,8 @@ gen_type (const char *ret_val, tree t, formals_style style)
switch (TREE_CODE (t))
{
case POINTER_TYPE:
+ if (TYPE_ATOMIC (t))
+ ret_val = concat ("_Atomic ", ret_val, NULL);
if (TYPE_READONLY (t))
ret_val = concat ("const ", ret_val, NULL);
if (TYPE_VOLATILE (t))
@@ -425,6 +427,8 @@ gen_type (const char *ret_val, tree t, formals_style style)
gcc_unreachable ();
}
}
+ if (TYPE_ATOMIC (t))
+ ret_val = concat ("_Atomic ", ret_val, NULL);
if (TYPE_READONLY (t))
ret_val = concat ("const ", ret_val, NULL);
if (TYPE_VOLATILE (t))
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index f26334829d8..9520e4d2d6e 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -45,6 +45,7 @@ along with GCC; see the file COPYING3. If not see
#include "c-family/c-common.h"
#include "c-family/c-objc.h"
#include "c-family/c-pragma.h"
+#include "c-family/c-ubsan.h"
#include "c-lang.h"
#include "langhooks.h"
#include "tree-iterator.h"
@@ -56,6 +57,7 @@ along with GCC; see the file COPYING3. If not see
#include "pointer-set.h"
#include "plugin.h"
#include "c-family/c-ada-spec.h"
+#include "cilk.h"
/* In grokdeclarator, distinguish syntactic contexts of declarators. */
enum decl_context
@@ -147,6 +149,9 @@ static bool undef_nested_function;
enum machine_mode c_default_pointer_mode = VOIDmode;
+/* If non-zero, implicit "omp declare target" attribute is added into the
+ attribute lists. */
+int current_omp_declare_target_attribute;
/* Each c_binding structure describes one binding of an identifier to
a decl. All the decls in a scope - irrespective of namespace - are
@@ -1579,8 +1584,14 @@ validate_proto_after_old_defn (tree newdecl, tree newtype, tree oldtype)
if (oldargtype == error_mark_node || newargtype == error_mark_node)
return false;
- oldargtype = TYPE_MAIN_VARIANT (oldargtype);
- newargtype = TYPE_MAIN_VARIANT (newargtype);
+ oldargtype = (TYPE_ATOMIC (oldargtype)
+ ? c_build_qualified_type (TYPE_MAIN_VARIANT (oldargtype),
+ TYPE_QUAL_ATOMIC)
+ : TYPE_MAIN_VARIANT (oldargtype));
+ newargtype = (TYPE_ATOMIC (newargtype)
+ ? c_build_qualified_type (TYPE_MAIN_VARIANT (newargtype),
+ TYPE_QUAL_ATOMIC)
+ : TYPE_MAIN_VARIANT (newargtype));
if (END_OF_ARGLIST (oldargtype) && END_OF_ARGLIST (newargtype))
break;
@@ -1629,7 +1640,8 @@ validate_proto_after_old_defn (tree newdecl, tree newtype, tree oldtype)
static void
locate_old_decl (tree decl)
{
- if (TREE_CODE (decl) == FUNCTION_DECL && DECL_BUILT_IN (decl))
+ if (TREE_CODE (decl) == FUNCTION_DECL && DECL_BUILT_IN (decl)
+ && !C_DECL_DECLARED_BUILTIN (decl))
;
else if (DECL_INITIAL (decl))
inform (input_location, "previous definition of %q+D was here", decl);
@@ -3709,6 +3721,7 @@ shadow_tag_warned (const struct c_declspecs *declspecs, int warned)
&& declspecs->typespec_kind != ctsk_tagfirstref
&& (declspecs->const_p
|| declspecs->volatile_p
+ || declspecs->atomic_p
|| declspecs->restrict_p
|| declspecs->address_space))
{
@@ -3798,6 +3811,7 @@ shadow_tag_warned (const struct c_declspecs *declspecs, int warned)
if (!warned && !in_system_header && (declspecs->const_p
|| declspecs->volatile_p
+ || declspecs->atomic_p
|| declspecs->restrict_p
|| declspecs->address_space))
{
@@ -3829,6 +3843,7 @@ quals_from_declspecs (const struct c_declspecs *specs)
int quals = ((specs->const_p ? TYPE_QUAL_CONST : 0)
| (specs->volatile_p ? TYPE_QUAL_VOLATILE : 0)
| (specs->restrict_p ? TYPE_QUAL_RESTRICT : 0)
+ | (specs->atomic_p ? TYPE_QUAL_ATOMIC : 0)
| (ENCODE_QUAL_ADDR_SPACE (specs->address_space)));
gcc_assert (!specs->type
&& !specs->decl_attr
@@ -3971,6 +3986,35 @@ groktypename (struct c_type_name *type_name, tree *expr,
return type;
}
+/* Wrapper for decl_attributes that adds some implicit attributes
+ to VAR_DECLs or FUNCTION_DECLs. */
+
+static tree
+c_decl_attributes (tree *node, tree attributes, int flags)
+{
+ /* Add implicit "omp declare target" attribute if requested. */
+ if (current_omp_declare_target_attribute
+ && ((TREE_CODE (*node) == VAR_DECL && TREE_STATIC (*node))
+ || TREE_CODE (*node) == FUNCTION_DECL))
+ {
+ if (TREE_CODE (*node) == VAR_DECL
+ && ((DECL_CONTEXT (*node)
+ && TREE_CODE (DECL_CONTEXT (*node)) == FUNCTION_DECL)
+ || (current_function_decl && !DECL_EXTERNAL (*node))))
+ error ("%q+D in block scope inside of declare target directive",
+ *node);
+ else if (TREE_CODE (*node) == VAR_DECL
+ && !COMPLETE_TYPE_P (TREE_TYPE (*node)))
+ error ("%q+D in declare target directive does not have mappable type",
+ *node);
+ else
+ attributes = tree_cons (get_identifier ("omp declare target"),
+ NULL_TREE, attributes);
+ }
+ return decl_attributes (node, attributes, flags);
+}
+
+
/* Decode a declarator in an ordinary declaration or data definition.
This is called as soon as the type information and variable name
have been parsed, before parsing the initializer if any.
@@ -4105,7 +4149,7 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs,
DECL_COMMON (decl) = 1;
/* Set attributes here so if duplicate decl, will have proper attributes. */
- decl_attributes (&decl, attributes, 0);
+ c_decl_attributes (&decl, attributes, 0);
/* Handle gnu_inline attribute. */
if (declspecs->inline_p
@@ -4135,7 +4179,7 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs,
tree type = TREE_TYPE (args);
if (type && INTEGRAL_TYPE_P (type)
&& TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
- DECL_ARG_TYPE (args) = integer_type_node;
+ DECL_ARG_TYPE (args) = c_type_promotes_to (type);
}
}
}
@@ -4908,6 +4952,7 @@ grokdeclarator (const struct c_declarator *declarator,
int constp;
int restrictp;
int volatilep;
+ int atomicp;
int type_quals = TYPE_UNQUALIFIED;
tree name = NULL_TREE;
bool funcdef_flag = false;
@@ -5062,6 +5107,7 @@ grokdeclarator (const struct c_declarator *declarator,
constp = declspecs->const_p + TYPE_READONLY (element_type);
restrictp = declspecs->restrict_p + TYPE_RESTRICT (element_type);
volatilep = declspecs->volatile_p + TYPE_VOLATILE (element_type);
+ atomicp = declspecs->atomic_p + TYPE_ATOMIC (element_type);
as1 = declspecs->address_space;
as2 = TYPE_ADDR_SPACE (element_type);
address_space = ADDR_SPACE_GENERIC_P (as1)? as2 : as1;
@@ -5074,6 +5120,9 @@ grokdeclarator (const struct c_declarator *declarator,
pedwarn (loc, OPT_Wpedantic, "duplicate %<restrict%>");
if (volatilep > 1)
pedwarn (loc, OPT_Wpedantic, "duplicate %<volatile%>");
+ if (atomicp > 1)
+ pedwarn (loc, OPT_Wpedantic, "duplicate %<_Atomic%>");
+
}
if (!ADDR_SPACE_GENERIC_P (as1) && !ADDR_SPACE_GENERIC_P (as2) && as1 != as2)
@@ -5087,8 +5136,16 @@ grokdeclarator (const struct c_declarator *declarator,
type_quals = ((constp ? TYPE_QUAL_CONST : 0)
| (restrictp ? TYPE_QUAL_RESTRICT : 0)
| (volatilep ? TYPE_QUAL_VOLATILE : 0)
+ | (atomicp ? TYPE_QUAL_ATOMIC : 0)
| ENCODE_QUAL_ADDR_SPACE (address_space));
+ /* Applying the _Atomic qualifier to an array type (through the use
+ of typedefs or typeof) must be detected here. If the qualifier
+ is introduced later, any appearance of applying it to an array is
+ actually applying it to an element of that array. */
+ if (atomicp && TREE_CODE (type) == ARRAY_TYPE)
+ error_at (loc, "%<_Atomic%>-qualified array type");
+
/* Warn about storage classes that are invalid for certain
kinds of declarations (parameters, typenames, etc.). */
@@ -5378,6 +5435,16 @@ grokdeclarator (const struct c_declarator *declarator,
with known value. */
this_size_varies = size_varies = true;
warn_variable_length_array (name, size);
+ if (flag_sanitize & SANITIZE_VLA
+ && decl_context == NORMAL)
+ {
+ /* Evaluate the array size only once. */
+ size = c_save_expr (size);
+ size = c_fully_fold (size, false, NULL);
+ size = fold_build2 (COMPOUND_EXPR, TREE_TYPE (size),
+ ubsan_instrument_vla (loc, size),
+ size);
+ }
}
if (integer_zerop (size) && !this_size_varies)
@@ -5654,9 +5721,15 @@ grokdeclarator (const struct c_declarator *declarator,
{
/* Merge any constancy or volatility into the target type
for the pointer. */
-
- if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
- && type_quals)
+ if ((type_quals & TYPE_QUAL_ATOMIC)
+ && TREE_CODE (type) == FUNCTION_TYPE)
+ {
+ error_at (loc,
+ "%<_Atomic%>-qualified function type");
+ type_quals &= ~TYPE_QUAL_ATOMIC;
+ }
+ else if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
+ && type_quals)
pedwarn (loc, OPT_Wpedantic,
"ISO C forbids qualified function types");
if (type_quals)
@@ -5770,7 +5843,20 @@ grokdeclarator (const struct c_declarator *declarator,
/* Check the type and width of a bit-field. */
if (bitfield)
- check_bitfield_type_and_width (&type, width, name);
+ {
+ check_bitfield_type_and_width (&type, width, name);
+ /* C11 makes it implementation-defined (6.7.2.1#5) whether
+ atomic types are permitted for bit-fields; we have no code to
+ make bit-field accesses atomic, so disallow them. */
+ if (type_quals & TYPE_QUAL_ATOMIC)
+ {
+ if (name)
+ error ("bit-field %qE has atomic type", name);
+ else
+ error ("bit-field has atomic type");
+ type_quals &= ~TYPE_QUAL_ATOMIC;
+ }
+ }
/* Reject invalid uses of _Alignas. */
if (declspecs->alignas_p)
@@ -5833,8 +5919,15 @@ grokdeclarator (const struct c_declarator *declarator,
if (storage_class == csc_typedef)
{
tree decl;
- if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
- && type_quals)
+ if ((type_quals & TYPE_QUAL_ATOMIC)
+ && TREE_CODE (type) == FUNCTION_TYPE)
+ {
+ error_at (loc,
+ "%<_Atomic%>-qualified function type");
+ type_quals &= ~TYPE_QUAL_ATOMIC;
+ }
+ else if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
+ && type_quals)
pedwarn (loc, OPT_Wpedantic,
"ISO C forbids qualified function types");
if (type_quals)
@@ -5879,8 +5972,15 @@ grokdeclarator (const struct c_declarator *declarator,
and fields. */
gcc_assert (storage_class == csc_none && !threadp
&& !declspecs->inline_p && !declspecs->noreturn_p);
- if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
- && type_quals)
+ if ((type_quals & TYPE_QUAL_ATOMIC)
+ && TREE_CODE (type) == FUNCTION_TYPE)
+ {
+ error_at (loc,
+ "%<_Atomic%>-qualified function type");
+ type_quals &= ~TYPE_QUAL_ATOMIC;
+ }
+ else if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
+ && type_quals)
pedwarn (loc, OPT_Wpedantic,
"ISO C forbids const or volatile function types");
if (type_quals)
@@ -5946,7 +6046,13 @@ grokdeclarator (const struct c_declarator *declarator,
}
else if (TREE_CODE (type) == FUNCTION_TYPE)
{
- if (type_quals)
+ if (type_quals & TYPE_QUAL_ATOMIC)
+ {
+ error_at (loc,
+ "%<_Atomic%>-qualified function type");
+ type_quals &= ~TYPE_QUAL_ATOMIC;
+ }
+ else if (type_quals)
pedwarn (loc, OPT_Wpedantic,
"ISO C forbids qualified function types");
if (type_quals)
@@ -6041,7 +6147,13 @@ grokdeclarator (const struct c_declarator *declarator,
FUNCTION_DECL, declarator->u.id, type);
decl = build_decl_attribute_variant (decl, decl_attr);
- if (pedantic && type_quals && !DECL_IN_SYSTEM_HEADER (decl))
+ if (type_quals & TYPE_QUAL_ATOMIC)
+ {
+ error_at (loc,
+ "%<_Atomic%>-qualified function type");
+ type_quals &= ~TYPE_QUAL_ATOMIC;
+ }
+ else if (pedantic && type_quals && !DECL_IN_SYSTEM_HEADER (decl))
pedwarn (loc, OPT_Wpedantic,
"ISO C forbids qualified function types");
@@ -6414,8 +6526,7 @@ get_parm_info (bool ellipsis, tree expr)
&& !DECL_NAME (b->decl) /* anonymous */
&& VOID_TYPE_P (TREE_TYPE (b->decl))) /* of void type */
{
- if (TREE_THIS_VOLATILE (b->decl)
- || TREE_READONLY (b->decl)
+ if (TYPE_QUALS (TREE_TYPE (b->decl)) != TYPE_UNQUALIFIED
|| C_DECL_REGISTER (b->decl))
error ("%<void%> as only parameter may not be qualified");
@@ -7727,7 +7838,7 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator,
loc = DECL_SOURCE_LOCATION (decl1);
- decl_attributes (&decl1, attributes, 0);
+ c_decl_attributes (&decl1, attributes, 0);
if (DECL_DECLARED_INLINE_P (decl1)
&& DECL_UNINLINABLE (decl1)
@@ -8168,11 +8279,15 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
type for parameters declared with qualified type. */
if (TREE_TYPE (parm) != error_mark_node
&& TREE_TYPE (type) != error_mark_node
- && !comptypes (TYPE_MAIN_VARIANT (DECL_ARG_TYPE (parm)),
- TYPE_MAIN_VARIANT (TREE_VALUE (type))))
+ && ((TYPE_ATOMIC (DECL_ARG_TYPE (parm))
+ != TYPE_ATOMIC (TREE_VALUE (type)))
+ || !comptypes (TYPE_MAIN_VARIANT (DECL_ARG_TYPE (parm)),
+ TYPE_MAIN_VARIANT (TREE_VALUE (type)))))
{
- if (TYPE_MAIN_VARIANT (TREE_TYPE (parm))
- == TYPE_MAIN_VARIANT (TREE_VALUE (type)))
+ if ((TYPE_ATOMIC (DECL_ARG_TYPE (parm))
+ == TYPE_ATOMIC (TREE_VALUE (type)))
+ && (TYPE_MAIN_VARIANT (TREE_TYPE (parm))
+ == TYPE_MAIN_VARIANT (TREE_VALUE (type))))
{
/* Adjust argument to match prototype. E.g. a previous
`int foo(float);' prototype causes
@@ -8185,7 +8300,8 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
&& INTEGRAL_TYPE_P (TREE_TYPE (parm))
&& TYPE_PRECISION (TREE_TYPE (parm))
< TYPE_PRECISION (integer_type_node))
- DECL_ARG_TYPE (parm) = integer_type_node;
+ DECL_ARG_TYPE (parm)
+ = c_type_promotes_to (TREE_TYPE (parm));
/* ??? Is it possible to get here with a
built-in prototype or will it always have
@@ -8324,6 +8440,44 @@ store_parm_decls (void)
if (arg_info->pending_sizes)
add_stmt (arg_info->pending_sizes);
}
+
+/* Store PARM_DECLs in PARMS into scope temporarily. Used for
+ c_finish_omp_declare_simd for function prototypes. No diagnostics
+ should be done. */
+
+void
+temp_store_parm_decls (tree fndecl, tree parms)
+{
+ push_scope ();
+ for (tree p = parms; p; p = DECL_CHAIN (p))
+ {
+ DECL_CONTEXT (p) = fndecl;
+ if (DECL_NAME (p))
+ bind (DECL_NAME (p), p, current_scope,
+ /*invisible=*/false, /*nested=*/false,
+ UNKNOWN_LOCATION);
+ }
+}
+
+/* Undo what temp_store_parm_decls did. */
+
+void
+temp_pop_parm_decls (void)
+{
+ /* Clear all bindings in this temporary scope, so that
+ pop_scope doesn't create a BLOCK. */
+ struct c_binding *b = current_scope->bindings;
+ current_scope->bindings = NULL;
+ for (; b; b = free_binding_and_advance (b))
+ {
+ gcc_assert (TREE_CODE (b->decl) == PARM_DECL);
+ gcc_assert (I_SYMBOL_BINDING (b->id) == b);
+ I_SYMBOL_BINDING (b->id) = b->shadowed;
+ if (b->shadowed && b->shadowed->u.type)
+ TREE_TYPE (b->shadowed->decl) = b->shadowed->u.type;
+ }
+ pop_scope ();
+}
/* Finish up a function declaration and compile that function
@@ -8349,7 +8503,7 @@ finish_function (void)
tree type = TREE_TYPE (args);
if (INTEGRAL_TYPE_P (type)
&& TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
- DECL_ARG_TYPE (args) = integer_type_node;
+ DECL_ARG_TYPE (args) = c_type_promotes_to (type);
}
}
@@ -8377,6 +8531,12 @@ finish_function (void)
/* Tie off the statement tree for this function. */
DECL_SAVED_TREE (fndecl) = pop_stmt_list (DECL_SAVED_TREE (fndecl));
+ /* If the function has _Cilk_spawn in front of a function call inside it
+ i.e. it is a spawning function, then add the appropriate Cilk plus
+ functions inside. */
+ if (fn_contains_cilk_spawn_p (cfun))
+ cfun->cilk_frame_decl = insert_cilk_frame (fndecl);
+
finish_fname_decls ();
/* Complain if there's just no return statement. */
@@ -8822,6 +8982,7 @@ build_null_declspecs (void)
ret->thread_p = false;
ret->const_p = false;
ret->volatile_p = false;
+ ret->atomic_p = false;
ret->restrict_p = false;
ret->saturating_p = false;
ret->alignas_p = false;
@@ -8883,6 +9044,10 @@ declspecs_add_qual (source_location loc,
specs->restrict_p = true;
specs->locations[cdw_restrict] = loc;
break;
+ case RID_ATOMIC:
+ dupe = specs->atomic_p;
+ specs->atomic_p = true;
+ break;
default:
gcc_unreachable ();
}
@@ -10158,4 +10323,106 @@ c_register_addr_space (const char *word, addr_space_t as)
ridpointers [rid] = id;
}
+/* Return identifier to look up for omp declare reduction. */
+
+tree
+c_omp_reduction_id (enum tree_code reduction_code, tree reduction_id)
+{
+ const char *p = NULL;
+ switch (reduction_code)
+ {
+ case PLUS_EXPR: p = "+"; break;
+ case MULT_EXPR: p = "*"; break;
+ case MINUS_EXPR: p = "-"; break;
+ case BIT_AND_EXPR: p = "&"; break;
+ case BIT_XOR_EXPR: p = "^"; break;
+ case BIT_IOR_EXPR: p = "|"; break;
+ case TRUTH_ANDIF_EXPR: p = "&&"; break;
+ case TRUTH_ORIF_EXPR: p = "||"; break;
+ case MIN_EXPR: p = "min"; break;
+ case MAX_EXPR: p = "max"; break;
+ default:
+ break;
+ }
+
+ if (p == NULL)
+ {
+ if (TREE_CODE (reduction_id) != IDENTIFIER_NODE)
+ return error_mark_node;
+ p = IDENTIFIER_POINTER (reduction_id);
+ }
+
+ const char prefix[] = "omp declare reduction ";
+ size_t lenp = sizeof (prefix);
+ size_t len = strlen (p);
+ char *name = XALLOCAVEC (char, lenp + len);
+ memcpy (name, prefix, lenp - 1);
+ memcpy (name + lenp - 1, p, len + 1);
+ return get_identifier (name);
+}
+
+/* Lookup REDUCTION_ID in the current scope, or create an artificial
+ VAR_DECL, bind it into the current scope and return it. */
+
+tree
+c_omp_reduction_decl (tree reduction_id)
+{
+ struct c_binding *b = I_SYMBOL_BINDING (reduction_id);
+ if (b != NULL && B_IN_CURRENT_SCOPE (b))
+ return b->decl;
+
+ tree decl = build_decl (BUILTINS_LOCATION, VAR_DECL,
+ reduction_id, integer_type_node);
+ DECL_ARTIFICIAL (decl) = 1;
+ DECL_EXTERNAL (decl) = 1;
+ TREE_STATIC (decl) = 1;
+ TREE_PUBLIC (decl) = 0;
+ bind (reduction_id, decl, current_scope, true, false, BUILTINS_LOCATION);
+ return decl;
+}
+
+/* Lookup REDUCTION_ID in the first scope where it has entry for TYPE. */
+
+tree
+c_omp_reduction_lookup (tree reduction_id, tree type)
+{
+ struct c_binding *b = I_SYMBOL_BINDING (reduction_id);
+ while (b)
+ {
+ tree t;
+ for (t = DECL_INITIAL (b->decl); t; t = TREE_CHAIN (t))
+ if (comptypes (TREE_PURPOSE (t), type))
+ return TREE_VALUE (t);
+ b = b->shadowed;
+ }
+ return error_mark_node;
+}
+
+/* Helper function called via walk_tree, to diagnose invalid
+ #pragma omp declare reduction combiners or initializers. */
+
+tree
+c_check_omp_declare_reduction_r (tree *tp, int *, void *data)
+{
+ tree *vars = (tree *) data;
+ if (SSA_VAR_P (*tp)
+ && !DECL_ARTIFICIAL (*tp)
+ && *tp != vars[0]
+ && *tp != vars[1])
+ {
+ location_t loc = DECL_SOURCE_LOCATION (vars[0]);
+ if (strcmp (IDENTIFIER_POINTER (DECL_NAME (vars[0])), "omp_out") == 0)
+ error_at (loc, "%<#pragma omp declare reduction%> combiner refers to "
+ "variable %qD which is not %<omp_out%> nor %<omp_in%>",
+ *tp);
+ else
+ error_at (loc, "%<#pragma omp declare reduction%> initializer refers "
+ "to variable %qD which is not %<omp_priv%> nor "
+ "%<omp_orig%>",
+ *tp);
+ return *tp;
+ }
+ return NULL_TREE;
+}
+
#include "gt-c-c-decl.h"
diff --git a/gcc/c/c-lang.h b/gcc/c/c-lang.h
index 5ff7cd5422e..cbd5d1fa643 100644
--- a/gcc/c/c-lang.h
+++ b/gcc/c/c-lang.h
@@ -55,5 +55,8 @@ struct GTY(()) language_function {
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/gcc/c/c-objc-common.h b/gcc/c/c-objc-common.h
index e1448248cd6..6ae7b3e0fb7 100644
--- a/gcc/c/c-objc-common.h
+++ b/gcc/c/c-objc-common.h
@@ -105,4 +105,13 @@ along with GCC; see the file COPYING3. If not see
#undef LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P
#define LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P c_vla_unspec_p
+#undef LANG_HOOKS_CILKPLUS_GIMPLIFY_SPAWN
+#define LANG_HOOKS_CILKPLUS_GIMPLIFY_SPAWN gimplify_cilk_spawn
+
+#undef LANG_HOOKS_CILKPLUS_FRAME_CLEANUP
+#define LANG_HOOKS_CILKPLUS_FRAME_CLEANUP c_cilk_install_body_w_frame_cleanup
+
+#undef LANG_HOOKS_CILKPLUS_DETECT_SPAWN_AND_UNWRAP
+#define LANG_HOOKS_CILKPLUS_DETECT_SPAWN_AND_UNWRAP \
+ cilk_detect_spawn_and_unwrap
#endif /* GCC_C_OBJC_COMMON */
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index b612e29c852..09cce1c0924 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -46,6 +46,7 @@ along with GCC; see the file COPYING3. If not see
#include "timevar.h"
#include "c-family/c-pragma.h"
#include "c-tree.h"
+#include "c-lang.h"
#include "flags.h"
#include "ggc.h"
#include "c-family/c-common.h"
@@ -54,6 +55,7 @@ along with GCC; see the file COPYING3. If not see
#include "target.h"
#include "cgraph.h"
#include "plugin.h"
+#include "omp-low.h"
/* Initialization routine for this file. */
@@ -162,9 +164,12 @@ typedef struct GTY (()) c_token {
tokens of look-ahead; more are not needed for C. */
typedef struct GTY(()) c_parser {
/* The look-ahead tokens. */
- c_token tokens[2];
- /* How many look-ahead tokens are available (0, 1 or 2). */
- short tokens_avail;
+ c_token * GTY((skip)) tokens;
+ /* Buffer for look-ahead tokens. */
+ c_token tokens_buf[2];
+ /* How many look-ahead tokens are available (0, 1 or 2, or
+ more if parsing from pre-lexed tokens). */
+ unsigned int tokens_avail;
/* True if a syntax error is being recovered from; false otherwise.
c_parser_error sets this flag. It should clear this flag when
enough tokens have been consumed to recover from the error. */
@@ -489,6 +494,7 @@ c_token_starts_typename (c_token *token)
case RID_UNION:
case RID_TYPEOF:
case RID_CONST:
+ case RID_ATOMIC:
case RID_VOLATILE:
case RID_RESTRICT:
case RID_ATTRIBUTE:
@@ -571,6 +577,7 @@ c_token_is_qualifier (c_token *token)
case RID_VOLATILE:
case RID_RESTRICT:
case RID_ATTRIBUTE:
+ case RID_ATOMIC:
return true;
default:
return false;
@@ -651,6 +658,7 @@ c_token_starts_declspecs (c_token *token)
case RID_ACCUM:
case RID_SAT:
case RID_ALIGNAS:
+ case RID_ATOMIC:
return true;
default:
return false;
@@ -736,7 +744,9 @@ c_parser_consume_token (c_parser *parser)
gcc_assert (parser->tokens[0].type != CPP_EOF);
gcc_assert (!parser->in_pragma || parser->tokens[0].type != CPP_PRAGMA_EOL);
gcc_assert (parser->error || parser->tokens[0].type != CPP_PRAGMA);
- if (parser->tokens_avail == 2)
+ if (parser->tokens != &parser->tokens_buf[0])
+ parser->tokens++;
+ else if (parser->tokens_avail == 2)
parser->tokens[0] = parser->tokens[1];
parser->tokens_avail--;
}
@@ -750,7 +760,9 @@ c_parser_consume_pragma (c_parser *parser)
gcc_assert (!parser->in_pragma);
gcc_assert (parser->tokens_avail >= 1);
gcc_assert (parser->tokens[0].type == CPP_PRAGMA);
- if (parser->tokens_avail == 2)
+ if (parser->tokens != &parser->tokens_buf[0])
+ parser->tokens++;
+ else if (parser->tokens_avail == 2)
parser->tokens[0] = parser->tokens[1];
parser->tokens_avail--;
parser->in_pragma = true;
@@ -1112,11 +1124,11 @@ enum c_parser_prec {
static void c_parser_external_declaration (c_parser *);
static void c_parser_asm_definition (c_parser *);
static void c_parser_declaration_or_fndef (c_parser *, bool, bool, bool,
- bool, bool, tree *);
+ bool, bool, tree *, vec<c_token>);
static void c_parser_static_assert_declaration_no_semi (c_parser *);
static void c_parser_static_assert_declaration (c_parser *);
static void c_parser_declspecs (c_parser *, struct c_declspecs *, bool, bool,
- bool, enum c_lookahead_kind);
+ bool, bool, enum c_lookahead_kind);
static struct c_typespec c_parser_enum_specifier (c_parser *);
static struct c_typespec c_parser_struct_or_union_specifier (c_parser *);
static tree c_parser_struct_declaration (c_parser *);
@@ -1148,18 +1160,19 @@ static void c_parser_statement (c_parser *);
static void c_parser_statement_after_labels (c_parser *);
static void c_parser_if_statement (c_parser *);
static void c_parser_switch_statement (c_parser *);
-static void c_parser_while_statement (c_parser *);
-static void c_parser_do_statement (c_parser *);
-static void c_parser_for_statement (c_parser *);
+static void c_parser_while_statement (c_parser *, bool);
+static void c_parser_do_statement (c_parser *, bool);
+static void c_parser_for_statement (c_parser *, bool);
static tree c_parser_asm_statement (c_parser *);
static tree c_parser_asm_operands (c_parser *);
static tree c_parser_asm_goto_operands (c_parser *);
static tree c_parser_asm_clobbers (c_parser *);
-static struct c_expr c_parser_expr_no_commas (c_parser *, struct c_expr *);
+static struct c_expr c_parser_expr_no_commas (c_parser *, struct c_expr *,
+ tree = NULL_TREE);
static struct c_expr c_parser_conditional_expression (c_parser *,
- struct c_expr *);
+ struct c_expr *, tree);
static struct c_expr c_parser_binary_expression (c_parser *, struct c_expr *,
- enum c_parser_prec);
+ tree);
static struct c_expr c_parser_cast_expression (c_parser *, struct c_expr *);
static struct c_expr c_parser_unary_expression (c_parser *);
static struct c_expr c_parser_sizeof_expression (c_parser *);
@@ -1185,9 +1198,15 @@ static void c_parser_omp_barrier (c_parser *);
static void c_parser_omp_flush (c_parser *);
static void c_parser_omp_taskwait (c_parser *);
static void c_parser_omp_taskyield (c_parser *);
+static void c_parser_omp_cancel (c_parser *);
+static void c_parser_omp_cancellation_point (c_parser *);
-enum pragma_context { pragma_external, pragma_stmt, pragma_compound };
+enum pragma_context { pragma_external, pragma_struct, pragma_param,
+ pragma_stmt, pragma_compound };
static bool c_parser_pragma (c_parser *, enum pragma_context);
+static bool c_parser_omp_target (c_parser *, enum pragma_context);
+static void c_parser_omp_end_declare_target (c_parser *);
+static void c_parser_omp_declare (c_parser *, enum pragma_context);
/* These Objective-C parser functions are only ever called when
compiling Objective-C. */
@@ -1360,11 +1379,14 @@ c_parser_external_declaration (c_parser *parser)
an @interface or @protocol with prefix attributes). We can
only tell which after parsing the declaration specifiers, if
any, and the first declarator. */
- c_parser_declaration_or_fndef (parser, true, true, true, false, true, NULL);
+ c_parser_declaration_or_fndef (parser, true, true, true, false, true,
+ NULL, vNULL);
break;
}
}
+static void c_finish_omp_declare_simd (c_parser *, tree, tree, vec<c_token>);
+
/* Parse a declaration or function definition (C90 6.5, 6.7.1, C99
6.7, 6.9.1). If FNDEF_OK is true, a function definition is
accepted; otherwise (old-style parameter declarations) only other
@@ -1440,7 +1462,8 @@ static void
c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
bool static_assert_ok, bool empty_ok,
bool nested, bool start_attr_ok,
- tree *objc_foreach_object_declaration)
+ tree *objc_foreach_object_declaration,
+ vec<c_token> omp_declare_simd_clauses)
{
struct c_declspecs *specs;
tree prefix_attrs;
@@ -1475,7 +1498,8 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
fndef_ok = !nested;
}
- c_parser_declspecs (parser, specs, true, true, start_attr_ok, cla_nonabstract_decl);
+ c_parser_declspecs (parser, specs, true, true, start_attr_ok,
+ true, cla_nonabstract_decl);
if (parser->error)
{
c_parser_skip_to_end_of_block_or_statement (parser);
@@ -1610,6 +1634,9 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
C_DTR_NORMAL, &dummy);
if (declarator == NULL)
{
+ if (omp_declare_simd_clauses.exists ())
+ c_finish_omp_declare_simd (parser, NULL_TREE, NULL_TREE,
+ omp_declare_simd_clauses);
c_parser_skip_to_end_of_block_or_statement (parser);
return;
}
@@ -1646,6 +1673,9 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
chainon (postfix_attrs, all_prefix_attrs));
if (!d)
d = error_mark_node;
+ if (omp_declare_simd_clauses.exists ())
+ c_finish_omp_declare_simd (parser, d, NULL_TREE,
+ omp_declare_simd_clauses);
start_init (d, asm_name, global_bindings_p ());
init_loc = c_parser_peek_token (parser)->location;
init = c_parser_initializer (parser);
@@ -1662,6 +1692,28 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
tree d = start_decl (declarator, specs, false,
chainon (postfix_attrs,
all_prefix_attrs));
+ if (omp_declare_simd_clauses.exists ())
+ {
+ tree parms = NULL_TREE;
+ if (d && TREE_CODE (d) == FUNCTION_DECL)
+ {
+ struct c_declarator *ce = declarator;
+ while (ce != NULL)
+ if (ce->kind == cdk_function)
+ {
+ parms = ce->u.arg_info->parms;
+ break;
+ }
+ else
+ ce = ce->declarator;
+ }
+ if (parms)
+ temp_store_parm_decls (d, parms);
+ c_finish_omp_declare_simd (parser, d, parms,
+ omp_declare_simd_clauses);
+ if (parms)
+ temp_pop_parm_decls ();
+ }
if (d)
finish_decl (d, UNKNOWN_LOCATION, NULL_TREE,
NULL_TREE, asm_name);
@@ -1751,8 +1803,11 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
while (c_parser_next_token_is_not (parser, CPP_EOF)
&& c_parser_next_token_is_not (parser, CPP_OPEN_BRACE))
c_parser_declaration_or_fndef (parser, false, false, false,
- true, false, NULL);
+ true, false, NULL, vNULL);
store_parm_decls ();
+ if (omp_declare_simd_clauses.exists ())
+ c_finish_omp_declare_simd (parser, current_function_decl, NULL_TREE,
+ omp_declare_simd_clauses);
DECL_STRUCT_FUNCTION (current_function_decl)->function_start_locus
= c_parser_peek_token (parser)->location;
fnbody = c_parser_compound_statement (parser);
@@ -1892,8 +1947,9 @@ c_parser_static_assert_declaration_no_semi (c_parser *parser)
/* Parse some declaration specifiers (possibly none) (C90 6.5, C99
6.7), adding them to SPECS (which may already include some).
Storage class specifiers are accepted iff SCSPEC_OK; type
- specifiers are accepted iff TYPESPEC_OK; attributes are accepted at
- the start iff START_ATTR_OK.
+ specifiers are accepted iff TYPESPEC_OK; alignment specifiers are
+ accepted iff ALIGNSPEC_OK; attributes are accepted at the start
+ iff START_ATTR_OK.
declaration-specifiers:
storage-class-specifier declaration-specifiers[opt]
@@ -1938,8 +1994,10 @@ c_parser_static_assert_declaration_no_semi (c_parser *parser)
struct-or-union-specifier
enum-specifier
typedef-name
+ atomic-type-specifier
(_Bool and _Complex are new in C99.)
+ (atomic-type-specifier is new in C11.)
C90 6.5.3, C99 6.7.3:
@@ -1948,8 +2006,10 @@ c_parser_static_assert_declaration_no_semi (c_parser *parser)
restrict
volatile
address-space-qualifier
+ _Atomic
(restrict is new in C99.)
+ (_Atomic is new in C11.)
GNU extensions:
@@ -1978,6 +2038,9 @@ c_parser_static_assert_declaration_no_semi (c_parser *parser)
(_Fract, _Accum, and _Sat are new from ISO/IEC DTR 18037:
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1169.pdf)
+ atomic-type-specifier
+ _Atomic ( type-name )
+
Objective-C:
type-specifier:
@@ -1989,7 +2052,7 @@ c_parser_static_assert_declaration_no_semi (c_parser *parser)
static void
c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
bool scspec_ok, bool typespec_ok, bool start_attr_ok,
- enum c_lookahead_kind la)
+ bool alignspec_ok, enum c_lookahead_kind la)
{
bool attrs_ok = start_attr_ok;
bool seen_type = specs->typespec_kind != ctsk_none;
@@ -2171,6 +2234,64 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
t = c_parser_typeof_specifier (parser);
declspecs_add_type (loc, specs, t);
break;
+ case RID_ATOMIC:
+ /* C parser handling of Objective-C constructs needs
+ checking for correct lvalue-to-rvalue conversions, and
+ the code in build_modify_expr handling various
+ Objective-C cases, and that in build_unary_op handling
+ Objective-C cases for increment / decrement, also needs
+ updating; uses of TYPE_MAIN_VARIANT in objc_compare_types
+ and objc_types_are_equivalent may also need updates. */
+ if (c_dialect_objc ())
+ sorry ("%<_Atomic%> in Objective-C");
+ /* C parser handling of OpenMP constructs needs checking for
+ correct lvalue-to-rvalue conversions. */
+ if (flag_openmp)
+ sorry ("%<_Atomic%> with OpenMP");
+ if (!flag_isoc11)
+ {
+ if (flag_isoc99)
+ pedwarn (loc, OPT_Wpedantic,
+ "ISO C99 does not support the %<_Atomic%> qualifier");
+ else
+ pedwarn (loc, OPT_Wpedantic,
+ "ISO C90 does not support the %<_Atomic%> qualifier");
+ }
+ attrs_ok = true;
+ tree value;
+ value = c_parser_peek_token (parser)->value;
+ c_parser_consume_token (parser);
+ if (typespec_ok && c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+ {
+ /* _Atomic ( type-name ). */
+ seen_type = true;
+ c_parser_consume_token (parser);
+ struct c_type_name *type = c_parser_type_name (parser);
+ t.kind = ctsk_typeof;
+ t.spec = error_mark_node;
+ t.expr = NULL_TREE;
+ t.expr_const_operands = true;
+ if (type != NULL)
+ t.spec = groktypename (type, &t.expr,
+ &t.expr_const_operands);
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+ "expected %<)%>");
+ if (t.spec != error_mark_node)
+ {
+ if (TREE_CODE (t.spec) == ARRAY_TYPE)
+ error_at (loc, "%<_Atomic%>-qualified array type");
+ else if (TREE_CODE (t.spec) == FUNCTION_TYPE)
+ error_at (loc, "%<_Atomic%>-qualified function type");
+ else if (TYPE_QUALS (t.spec) != TYPE_UNQUALIFIED)
+ error_at (loc, "%<_Atomic%> applied to a qualified type");
+ else
+ t.spec = c_build_qualified_type (t.spec, TYPE_QUAL_ATOMIC);
+ }
+ declspecs_add_type (loc, specs, t);
+ }
+ else
+ declspecs_add_qual (loc, specs, value);
+ break;
case RID_CONST:
case RID_VOLATILE:
case RID_RESTRICT:
@@ -2185,6 +2306,8 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
declspecs_add_attrs (loc, specs, attrs);
break;
case RID_ALIGNAS:
+ if (!alignspec_ok)
+ goto out;
align = c_parser_alignas_specifier (parser);
declspecs_add_alignas (loc, specs, align);
break;
@@ -2481,7 +2604,7 @@ c_parser_struct_or_union_specifier (c_parser *parser)
/* Accept #pragmas at struct scope. */
if (c_parser_next_token_is (parser, CPP_PRAGMA))
{
- c_parser_pragma (parser, pragma_external);
+ c_parser_pragma (parser, pragma_struct);
continue;
}
/* Parse some comma-separated declarations, but not the
@@ -2590,7 +2713,13 @@ c_parser_struct_declaration (c_parser *parser)
}
specs = build_null_declspecs ();
decl_loc = c_parser_peek_token (parser)->location;
- c_parser_declspecs (parser, specs, false, true, true, cla_nonabstract_decl);
+ /* Strictly by the standard, we shouldn't allow _Alignas here,
+ but it appears to have been intended to allow it there, so
+ we're keeping it as it is until WG14 reaches a conclusion
+ of N1731.
+ <http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1731.pdf> */
+ c_parser_declspecs (parser, specs, false, true, true,
+ true, cla_nonabstract_decl);
if (parser->error)
return NULL_TREE;
if (!specs->declspecs_seen_p)
@@ -2765,6 +2894,16 @@ c_parser_typeof_specifier (c_parser *parser)
if (was_vm)
ret.expr = c_fully_fold (expr.value, false, &ret.expr_const_operands);
pop_maybe_used (was_vm);
+ /* For use in macros such as those in <stdatomic.h>, remove
+ _Atomic and const qualifiers from atomic types. (Possibly
+ all qualifiers should be removed; const can be an issue for
+ more macros using typeof than just the <stdatomic.h>
+ ones.) */
+ if (ret.spec != error_mark_node && TYPE_ATOMIC (ret.spec))
+ ret.spec = c_build_qualified_type (ret.spec,
+ (TYPE_QUALS (ret.spec)
+ & ~(TYPE_QUAL_ATOMIC
+ | TYPE_QUAL_CONST)));
}
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
return ret;
@@ -2838,6 +2977,12 @@ c_parser_alignas_specifier (c_parser * parser)
type-qualifier-list type-qualifier
type-qualifier-list attributes
+ array-declarator:
+ [ type-qualifier-list[opt] assignment-expression[opt] ]
+ [ static type-qualifier-list[opt] assignment-expression ]
+ [ type-qualifier-list static assignment-expression ]
+ [ type-qualifier-list[opt] * ]
+
parameter-type-list:
parameter-list
parameter-list , ...
@@ -2896,7 +3041,8 @@ c_parser_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind,
struct c_declspecs *quals_attrs = build_null_declspecs ();
struct c_declarator *inner;
c_parser_consume_token (parser);
- c_parser_declspecs (parser, quals_attrs, false, false, true, cla_prefer_id);
+ c_parser_declspecs (parser, quals_attrs, false, false, true,
+ false, cla_prefer_id);
inner = c_parser_declarator (parser, type_seen_p, kind, seen_id);
if (inner == NULL)
return NULL;
@@ -3046,14 +3192,19 @@ c_parser_direct_declarator_inner (c_parser *parser, bool id_present,
struct c_declspecs *quals_attrs = build_null_declspecs ();
bool static_seen;
bool star_seen;
- tree dimen;
+ struct c_expr dimen;
+ dimen.value = NULL_TREE;
+ dimen.original_code = ERROR_MARK;
+ dimen.original_type = NULL_TREE;
c_parser_consume_token (parser);
- c_parser_declspecs (parser, quals_attrs, false, false, true, cla_prefer_id);
+ c_parser_declspecs (parser, quals_attrs, false, false, true,
+ false, cla_prefer_id);
static_seen = c_parser_next_token_is_keyword (parser, RID_STATIC);
if (static_seen)
c_parser_consume_token (parser);
if (static_seen && !quals_attrs->declspecs_seen_p)
- c_parser_declspecs (parser, quals_attrs, false, false, true, cla_prefer_id);
+ c_parser_declspecs (parser, quals_attrs, false, false, true,
+ false, cla_prefer_id);
if (!quals_attrs->declspecs_seen_p)
quals_attrs = NULL;
/* If "static" is present, there must be an array dimension.
@@ -3062,19 +3213,19 @@ c_parser_direct_declarator_inner (c_parser *parser, bool id_present,
if (static_seen)
{
star_seen = false;
- dimen = c_parser_expr_no_commas (parser, NULL).value;
+ dimen = c_parser_expr_no_commas (parser, NULL);
}
else
{
if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
{
- dimen = NULL_TREE;
+ dimen.value = NULL_TREE;
star_seen = false;
}
else if (flag_enable_cilkplus
&& c_parser_next_token_is (parser, CPP_COLON))
{
- dimen = error_mark_node;
+ dimen.value = error_mark_node;
star_seen = false;
error_at (c_parser_peek_token (parser)->location,
"array notations cannot be used in declaration");
@@ -3084,20 +3235,20 @@ c_parser_direct_declarator_inner (c_parser *parser, bool id_present,
{
if (c_parser_peek_2nd_token (parser)->type == CPP_CLOSE_SQUARE)
{
- dimen = NULL_TREE;
+ dimen.value = NULL_TREE;
star_seen = true;
c_parser_consume_token (parser);
}
else
{
star_seen = false;
- dimen = c_parser_expr_no_commas (parser, NULL).value;
+ dimen = c_parser_expr_no_commas (parser, NULL);
}
}
else
{
star_seen = false;
- dimen = c_parser_expr_no_commas (parser, NULL).value;
+ dimen = c_parser_expr_no_commas (parser, NULL);
}
}
if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
@@ -3116,9 +3267,9 @@ c_parser_direct_declarator_inner (c_parser *parser, bool id_present,
"expected %<]%>");
return NULL;
}
- if (dimen)
- mark_exp_read (dimen);
- declarator = build_array_declarator (brace_loc, dimen, quals_attrs,
+ if (dimen.value)
+ dimen = convert_lvalue_to_rvalue (brace_loc, dimen, true, true);
+ declarator = build_array_declarator (brace_loc, dimen.value, quals_attrs,
static_seen, star_seen);
if (declarator == NULL)
return NULL;
@@ -3329,7 +3480,7 @@ c_parser_parameter_declaration (c_parser *parser, tree attrs)
/* Accept #pragmas between parameter declarations. */
while (c_parser_next_token_is (parser, CPP_PRAGMA))
- c_parser_pragma (parser, pragma_external);
+ c_parser_pragma (parser, pragma_param);
if (!c_parser_next_token_starts_declspecs (parser))
{
@@ -3356,7 +3507,8 @@ c_parser_parameter_declaration (c_parser *parser, tree attrs)
declspecs_add_attrs (input_location, specs, attrs);
attrs = NULL_TREE;
}
- c_parser_declspecs (parser, specs, true, true, true, cla_nonabstract_decl);
+ c_parser_declspecs (parser, specs, true, true, true, true,
+ cla_nonabstract_decl);
finish_declspecs (specs);
pending_xref_error ();
prefix_attrs = specs->attrs;
@@ -3487,6 +3639,7 @@ c_parser_attribute_any_word (c_parser *parser)
case RID_SAT:
case RID_TRANSACTION_ATOMIC:
case RID_TRANSACTION_CANCEL:
+ case RID_ATOMIC:
ok = true;
break;
default:
@@ -3665,7 +3818,8 @@ c_parser_type_name (c_parser *parser)
struct c_declarator *declarator;
struct c_type_name *ret;
bool dummy = false;
- c_parser_declspecs (parser, specs, false, true, true, cla_prefer_type);
+ c_parser_declspecs (parser, specs, false, true, true, false,
+ cla_prefer_type);
if (!specs->declspecs_seen_p)
{
c_parser_error (parser, "expected specifier-qualifier-list");
@@ -3742,7 +3896,7 @@ c_parser_initializer (c_parser *parser)
ret = c_parser_expr_no_commas (parser, NULL);
if (TREE_CODE (ret.value) != STRING_CST
&& TREE_CODE (ret.value) != COMPOUND_LITERAL_EXPR)
- ret = default_function_array_read_conversion (loc, ret);
+ ret = convert_lvalue_to_rvalue (loc, ret, true, true);
return ret;
}
}
@@ -3921,8 +4075,8 @@ c_parser_initelt (c_parser *parser, struct obstack * braced_init_obstack)
c_parser_consume_token (parser);
exp_loc = c_parser_peek_token (parser)->location;
next = c_parser_expr_no_commas (parser, NULL);
- next = default_function_array_read_conversion (exp_loc,
- next);
+ next = convert_lvalue_to_rvalue (exp_loc, next,
+ true, true);
rec = build_compound_expr (comma_loc, rec, next.value);
}
parse_message_args:
@@ -4018,7 +4172,7 @@ c_parser_initval (c_parser *parser, struct c_expr *after,
if (init.value != NULL_TREE
&& TREE_CODE (init.value) != STRING_CST
&& TREE_CODE (init.value) != COMPOUND_LITERAL_EXPR)
- init = default_function_array_read_conversion (loc, init);
+ init = convert_lvalue_to_rvalue (loc, init, true, true);
}
process_init_element (init, false, braced_init_obstack);
}
@@ -4074,7 +4228,11 @@ c_parser_initval (c_parser *parser, struct c_expr *after,
openmp-directive:
barrier-directive
- flush-directive */
+ flush-directive
+ taskwait-directive
+ taskyield-directive
+ cancel-directive
+ cancellation-point-directive */
static tree
c_parser_compound_statement (c_parser *parser)
@@ -4179,7 +4337,8 @@ c_parser_compound_statement_nostart (c_parser *parser)
{
last_label = false;
mark_valid_location_for_stdc_pragma (false);
- c_parser_declaration_or_fndef (parser, true, true, true, true, true, NULL);
+ c_parser_declaration_or_fndef (parser, true, true, true, true,
+ true, NULL, vNULL);
if (last_stmt)
pedwarn_c90 (loc,
(pedantic && !flag_isoc99)
@@ -4207,7 +4366,7 @@ c_parser_compound_statement_nostart (c_parser *parser)
last_label = false;
mark_valid_location_for_stdc_pragma (false);
c_parser_declaration_or_fndef (parser, true, true, true, true,
- true, NULL);
+ true, NULL, vNULL);
/* Following the old parser, __extension__ does not
disable this diagnostic. */
restore_extension_diagnostics (ext);
@@ -4345,7 +4504,8 @@ c_parser_label (c_parser *parser)
c_parser_declaration_or_fndef (parser, /*fndef_ok*/ false,
/*static_assert_ok*/ true,
/*empty_ok*/ true, /*nested*/ true,
- /*start_attr_ok*/ true, NULL);
+ /*start_attr_ok*/ true, NULL,
+ vNULL);
}
}
}
@@ -4408,9 +4568,12 @@ c_parser_label (c_parser *parser)
openmp-construct:
parallel-construct
for-construct
+ simd-construct
+ for-simd-construct
sections-construct
single-construct
parallel-for-construct
+ parallel-for-simd-construct
parallel-sections-construct
master-construct
critical-construct
@@ -4423,6 +4586,12 @@ c_parser_label (c_parser *parser)
for-construct:
for-directive iteration-statement
+ simd-construct:
+ simd-directive iteration-statements
+
+ for-simd-construct:
+ for-simd-directive iteration-statements
+
sections-construct:
sections-directive section-scope
@@ -4432,6 +4601,9 @@ c_parser_label (c_parser *parser)
parallel-for-construct:
parallel-for-directive iteration-statement
+ parallel-for-simd-construct:
+ parallel-for-simd-directive iteration-statement
+
parallel-sections-construct:
parallel-sections-directive section-scope
@@ -4489,13 +4661,21 @@ c_parser_statement_after_labels (c_parser *parser)
c_parser_switch_statement (parser);
break;
case RID_WHILE:
- c_parser_while_statement (parser);
+ c_parser_while_statement (parser, false);
break;
case RID_DO:
- c_parser_do_statement (parser);
+ c_parser_do_statement (parser, false);
break;
case RID_FOR:
- c_parser_for_statement (parser);
+ c_parser_for_statement (parser, false);
+ break;
+ case RID_CILK_SYNC:
+ c_parser_consume_token (parser);
+ c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+ if (!flag_enable_cilkplus)
+ error_at (loc, "-fcilkplus must be enabled to use %<_Cilk_sync%>");
+ else
+ add_stmt (build_cilk_sync ());
break;
case RID_GOTO:
c_parser_consume_token (parser);
@@ -4507,12 +4687,12 @@ c_parser_statement_after_labels (c_parser *parser)
}
else if (c_parser_next_token_is (parser, CPP_MULT))
{
- tree val;
+ struct c_expr val;
c_parser_consume_token (parser);
- val = c_parser_expression (parser).value;
- mark_exp_read (val);
- stmt = c_finish_goto_ptr (loc, val);
+ val = c_parser_expression (parser);
+ val = convert_lvalue_to_rvalue (loc, val, false, true);
+ stmt = c_finish_goto_ptr (loc, val.value);
}
else
c_parser_error (parser, "expected identifier or %<*%>");
@@ -4561,9 +4741,10 @@ c_parser_statement_after_labels (c_parser *parser)
}
else
{
- tree expr = c_parser_expression (parser).value;
- expr = c_fully_fold (expr, false, NULL);
- stmt = objc_build_throw_stmt (loc, expr);
+ struct c_expr expr = c_parser_expression (parser);
+ expr = convert_lvalue_to_rvalue (loc, expr, false, false);
+ expr.value = c_fully_fold (expr.value, false, NULL);
+ stmt = objc_build_throw_stmt (loc, expr.value);
goto expect_semicolon;
}
break;
@@ -4775,6 +4956,7 @@ c_parser_if_statement (c_parser *parser)
static void
c_parser_switch_statement (c_parser *parser)
{
+ struct c_expr ce;
tree block, expr, body, save_break;
location_t switch_loc = c_parser_peek_token (parser)->location;
location_t switch_cond_loc;
@@ -4784,7 +4966,9 @@ c_parser_switch_statement (c_parser *parser)
if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
{
switch_cond_loc = c_parser_peek_token (parser)->location;
- expr = c_parser_expression (parser).value;
+ ce = c_parser_expression (parser);
+ ce = convert_lvalue_to_rvalue (switch_cond_loc, ce, true, false);
+ expr = ce.value;
if (flag_enable_cilkplus && contains_array_notation_expr (expr))
{
error_at (switch_cond_loc,
@@ -4822,7 +5006,7 @@ c_parser_switch_statement (c_parser *parser)
*/
static void
-c_parser_while_statement (c_parser *parser)
+c_parser_while_statement (c_parser *parser, bool ivdep)
{
tree block, cond, body, save_break, save_cont;
location_t loc;
@@ -4837,6 +5021,11 @@ c_parser_while_statement (c_parser *parser)
"statement");
cond = error_mark_node;
}
+
+ if (ivdep && cond != error_mark_node)
+ cond = build2 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
+ build_int_cst (integer_type_node,
+ annot_expr_ivdep_kind));
save_break = c_break_label;
c_break_label = NULL_TREE;
save_cont = c_cont_label;
@@ -4855,7 +5044,7 @@ c_parser_while_statement (c_parser *parser)
*/
static void
-c_parser_do_statement (c_parser *parser)
+c_parser_do_statement (c_parser *parser, bool ivdep)
{
tree block, cond, body, save_break, save_cont, new_break, new_cont;
location_t loc;
@@ -4884,7 +5073,10 @@ c_parser_do_statement (c_parser *parser)
"do-while statement");
cond = error_mark_node;
}
-
+ if (ivdep && cond != error_mark_node)
+ cond = build2 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
+ build_int_cst (integer_type_node,
+ annot_expr_ivdep_kind));
if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
c_parser_skip_to_end_of_block_or_statement (parser);
c_finish_loop (loc, cond, NULL, body, new_break, new_cont, false);
@@ -4948,7 +5140,7 @@ c_parser_do_statement (c_parser *parser)
*/
static void
-c_parser_for_statement (c_parser *parser)
+c_parser_for_statement (c_parser *parser, bool ivdep)
{
tree block, cond, incr, save_break, save_cont, body;
/* The following are only used when parsing an ObjC foreach statement. */
@@ -4979,7 +5171,7 @@ c_parser_for_statement (c_parser *parser)
else if (c_parser_next_tokens_start_declaration (parser))
{
c_parser_declaration_or_fndef (parser, true, true, true, true, true,
- &object_expression);
+ &object_expression, vNULL);
parser->objc_could_be_foreach_context = false;
if (c_parser_next_token_is_keyword (parser, RID_IN))
@@ -5008,7 +5200,7 @@ c_parser_for_statement (c_parser *parser)
ext = disable_extension_diagnostics ();
c_parser_consume_token (parser);
c_parser_declaration_or_fndef (parser, true, true, true, true,
- true, &object_expression);
+ true, &object_expression, vNULL);
parser->objc_could_be_foreach_context = false;
restore_extension_diagnostics (ext);
@@ -5029,8 +5221,10 @@ c_parser_for_statement (c_parser *parser)
{
init_expr:
{
+ struct c_expr ce;
tree init_expression;
- init_expression = c_parser_expression (parser).value;
+ ce = c_parser_expression (parser);
+ init_expression = ce.value;
parser->objc_could_be_foreach_context = false;
if (c_parser_next_token_is_keyword (parser, RID_IN))
{
@@ -5042,6 +5236,8 @@ c_parser_for_statement (c_parser *parser)
}
else
{
+ ce = convert_lvalue_to_rvalue (loc, ce, true, false);
+ init_expression = ce.value;
c_finish_expr_stmt (loc, init_expression);
c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
}
@@ -5054,8 +5250,17 @@ c_parser_for_statement (c_parser *parser)
{
if (c_parser_next_token_is (parser, CPP_SEMICOLON))
{
- c_parser_consume_token (parser);
- cond = NULL_TREE;
+ if (ivdep)
+ {
+ c_parser_error (parser, "missing loop condition in loop with "
+ "%<GCC ivdep%> pragma");
+ cond = error_mark_node;
+ }
+ else
+ {
+ c_parser_consume_token (parser);
+ cond = NULL_TREE;
+ }
}
else
{
@@ -5069,6 +5274,10 @@ c_parser_for_statement (c_parser *parser)
c_parser_skip_until_found (parser, CPP_SEMICOLON,
"expected %<;%>");
}
+ if (ivdep && cond != error_mark_node)
+ cond = build2 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
+ build_int_cst (integer_type_node,
+ annot_expr_ivdep_kind));
}
/* Parse the increment expression (the third expression in a
for-statement). In the case of a foreach-statement, this is
@@ -5089,7 +5298,11 @@ c_parser_for_statement (c_parser *parser)
collection_expression = c_fully_fold (c_parser_expression (parser).value,
false, NULL);
else
- incr = c_process_expr_stmt (loc, c_parser_expression (parser).value);
+ {
+ struct c_expr ce = c_parser_expression (parser);
+ ce = convert_lvalue_to_rvalue (loc, ce, true, false);
+ incr = c_process_expr_stmt (loc, ce.value);
+ }
}
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
}
@@ -5396,13 +5609,14 @@ c_parser_asm_goto_operands (c_parser *parser)
error. */
static struct c_expr
-c_parser_expr_no_commas (c_parser *parser, struct c_expr *after)
+c_parser_expr_no_commas (c_parser *parser, struct c_expr *after,
+ tree omp_atomic_lhs)
{
struct c_expr lhs, rhs, ret;
enum tree_code code;
location_t op_location, exp_location;
gcc_assert (!after || c_dialect_objc ());
- lhs = c_parser_conditional_expression (parser, after);
+ lhs = c_parser_conditional_expression (parser, after, omp_atomic_lhs);
op_location = c_parser_peek_token (parser)->location;
switch (c_parser_peek_token (parser)->type)
{
@@ -5445,7 +5659,7 @@ c_parser_expr_no_commas (c_parser *parser, struct c_expr *after)
c_parser_consume_token (parser);
exp_location = c_parser_peek_token (parser)->location;
rhs = c_parser_expr_no_commas (parser, NULL);
- rhs = default_function_array_read_conversion (exp_location, rhs);
+ rhs = convert_lvalue_to_rvalue (exp_location, rhs, true, true);
ret.value = build_modify_expr (op_location, lhs.value, lhs.original_type,
code, exp_location, rhs.value,
@@ -5476,19 +5690,20 @@ c_parser_expr_no_commas (c_parser *parser, struct c_expr *after)
*/
static struct c_expr
-c_parser_conditional_expression (c_parser *parser, struct c_expr *after)
+c_parser_conditional_expression (c_parser *parser, struct c_expr *after,
+ tree omp_atomic_lhs)
{
struct c_expr cond, exp1, exp2, ret;
location_t cond_loc, colon_loc, middle_loc;
gcc_assert (!after || c_dialect_objc ());
- cond = c_parser_binary_expression (parser, after, PREC_NONE);
+ cond = c_parser_binary_expression (parser, after, omp_atomic_lhs);
if (c_parser_next_token_is_not (parser, CPP_QUERY))
return cond;
cond_loc = c_parser_peek_token (parser)->location;
- cond = default_function_array_read_conversion (cond_loc, cond);
+ cond = convert_lvalue_to_rvalue (cond_loc, cond, true, true);
c_parser_consume_token (parser);
if (c_parser_next_token_is (parser, CPP_COLON))
{
@@ -5535,8 +5750,8 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after)
}
{
location_t exp2_loc = c_parser_peek_token (parser)->location;
- exp2 = c_parser_conditional_expression (parser, NULL);
- exp2 = default_function_array_read_conversion (exp2_loc, exp2);
+ exp2 = c_parser_conditional_expression (parser, NULL, NULL_TREE);
+ exp2 = convert_lvalue_to_rvalue (exp2_loc, exp2, true, true);
}
c_inhibit_evaluation_warnings -= cond.value == truthvalue_true_node;
ret.value = build_conditional_expr (colon_loc, cond.value,
@@ -5568,8 +5783,13 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after)
/* Parse a binary expression; that is, a logical-OR-expression (C90
6.3.5-6.3.14, C99 6.5.5-6.5.14). If AFTER is not NULL then it is
an Objective-C message expression which is the primary-expression
- starting the expression as an initializer. PREC is the starting
- precedence, usually PREC_NONE.
+ starting the expression as an initializer.
+
+ OMP_ATOMIC_LHS is NULL, unless parsing OpenMP #pragma omp atomic,
+ when it should be the unfolded lhs. In a valid OpenMP source,
+ one of the operands of the toplevel binary expression must be equal
+ to it. In that case, just return a build2 created binary operation
+ rather than result of parser_build_binary_op.
multiplicative-expression:
cast-expression
@@ -5622,7 +5842,7 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after)
static struct c_expr
c_parser_binary_expression (c_parser *parser, struct c_expr *after,
- enum c_parser_prec prec)
+ tree omp_atomic_lhs)
{
/* A binary expression is parsed using operator-precedence parsing,
with the operands being cast expressions. All the binary
@@ -5675,21 +5895,35 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after,
break; \
} \
stack[sp - 1].expr \
- = default_function_array_read_conversion (stack[sp - 1].loc, \
- stack[sp - 1].expr); \
+ = convert_lvalue_to_rvalue (stack[sp - 1].loc, \
+ stack[sp - 1].expr, true, true); \
stack[sp].expr \
- = default_function_array_read_conversion (stack[sp].loc, \
- stack[sp].expr); \
- stack[sp - 1].expr = parser_build_binary_op (stack[sp].loc, \
- stack[sp].op, \
- stack[sp - 1].expr, \
- stack[sp].expr); \
+ = convert_lvalue_to_rvalue (stack[sp].loc, \
+ stack[sp].expr, true, true); \
+ if (__builtin_expect (omp_atomic_lhs != NULL_TREE, 0) && sp == 1 \
+ && c_parser_peek_token (parser)->type == CPP_SEMICOLON \
+ && ((1 << stack[sp].prec) \
+ & (1 << (PREC_BITOR | PREC_BITXOR | PREC_BITAND | PREC_SHIFT \
+ | PREC_ADD | PREC_MULT))) \
+ && stack[sp].op != TRUNC_MOD_EXPR \
+ && stack[0].expr.value != error_mark_node \
+ && stack[1].expr.value != error_mark_node \
+ && (c_tree_equal (stack[0].expr.value, omp_atomic_lhs) \
+ || c_tree_equal (stack[1].expr.value, omp_atomic_lhs))) \
+ stack[0].expr.value \
+ = build2 (stack[1].op, TREE_TYPE (stack[0].expr.value), \
+ stack[0].expr.value, stack[1].expr.value); \
+ else \
+ stack[sp - 1].expr = parser_build_binary_op (stack[sp].loc, \
+ stack[sp].op, \
+ stack[sp - 1].expr, \
+ stack[sp].expr); \
sp--; \
} while (0)
gcc_assert (!after || c_dialect_objc ());
stack[0].loc = c_parser_peek_token (parser)->location;
stack[0].expr = c_parser_cast_expression (parser, after);
- stack[0].prec = prec;
+ stack[0].prec = PREC_NONE;
sp = 0;
while (true)
{
@@ -5778,18 +6012,14 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after,
}
binary_loc = c_parser_peek_token (parser)->location;
while (oprec <= stack[sp].prec)
- {
- if (sp == 0)
- goto out;
- POP;
- }
+ POP;
c_parser_consume_token (parser);
switch (ocode)
{
case TRUTH_ANDIF_EXPR:
stack[sp].expr
- = default_function_array_read_conversion (stack[sp].loc,
- stack[sp].expr);
+ = convert_lvalue_to_rvalue (stack[sp].loc,
+ stack[sp].expr, true, true);
stack[sp].expr.value = c_objc_common_truthvalue_conversion
(stack[sp].loc, default_conversion (stack[sp].expr.value));
c_inhibit_evaluation_warnings += (stack[sp].expr.value
@@ -5797,8 +6027,8 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after,
break;
case TRUTH_ORIF_EXPR:
stack[sp].expr
- = default_function_array_read_conversion (stack[sp].loc,
- stack[sp].expr);
+ = convert_lvalue_to_rvalue (stack[sp].loc,
+ stack[sp].expr, true, true);
stack[sp].expr.value = c_objc_common_truthvalue_conversion
(stack[sp].loc, default_conversion (stack[sp].expr.value));
c_inhibit_evaluation_warnings += (stack[sp].expr.value
@@ -5869,7 +6099,7 @@ c_parser_cast_expression (c_parser *parser, struct c_expr *after)
{
location_t expr_loc = c_parser_peek_token (parser)->location;
expr = c_parser_cast_expression (parser, NULL);
- expr = default_function_array_read_conversion (expr_loc, expr);
+ expr = convert_lvalue_to_rvalue (expr_loc, expr, true, true);
}
ret.value = c_cast_expr (cast_loc, type_name, expr.value);
ret.original_code = ERROR_MARK;
@@ -5960,7 +6190,7 @@ c_parser_unary_expression (c_parser *parser)
c_parser_consume_token (parser);
exp_loc = c_parser_peek_token (parser)->location;
op = c_parser_cast_expression (parser, NULL);
- op = default_function_array_read_conversion (exp_loc, op);
+ op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
ret.value = build_indirect_ref (op_loc, op.value, RO_UNARY_STAR);
return ret;
case CPP_PLUS:
@@ -5971,25 +6201,25 @@ c_parser_unary_expression (c_parser *parser)
c_parser_consume_token (parser);
exp_loc = c_parser_peek_token (parser)->location;
op = c_parser_cast_expression (parser, NULL);
- op = default_function_array_read_conversion (exp_loc, op);
+ op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
return parser_build_unary_op (op_loc, CONVERT_EXPR, op);
case CPP_MINUS:
c_parser_consume_token (parser);
exp_loc = c_parser_peek_token (parser)->location;
op = c_parser_cast_expression (parser, NULL);
- op = default_function_array_read_conversion (exp_loc, op);
+ op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
return parser_build_unary_op (op_loc, NEGATE_EXPR, op);
case CPP_COMPL:
c_parser_consume_token (parser);
exp_loc = c_parser_peek_token (parser)->location;
op = c_parser_cast_expression (parser, NULL);
- op = default_function_array_read_conversion (exp_loc, op);
+ op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
return parser_build_unary_op (op_loc, BIT_NOT_EXPR, op);
case CPP_NOT:
c_parser_consume_token (parser);
exp_loc = c_parser_peek_token (parser)->location;
op = c_parser_cast_expression (parser, NULL);
- op = default_function_array_read_conversion (exp_loc, op);
+ op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
return parser_build_unary_op (op_loc, TRUTH_NOT_EXPR, op);
case CPP_AND_AND:
/* Refer to the address of a label as a pointer. */
@@ -6782,10 +7012,13 @@ c_parser_postfix_expression (c_parser *parser)
}
else
{
+ struct c_expr ce;
tree idx;
loc = c_parser_peek_token (parser)->location;
c_parser_consume_token (parser);
- idx = c_parser_expression (parser).value;
+ ce = c_parser_expression (parser);
+ ce = convert_lvalue_to_rvalue (loc, ce, false, false);
+ idx = ce.value;
idx = c_fully_fold (idx, false, NULL);
c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
"expected %<]%>");
@@ -6908,11 +7141,11 @@ c_parser_postfix_expression (c_parser *parser)
e1_p = &(*cexpr_list)[0];
e2_p = &(*cexpr_list)[1];
- mark_exp_read (e1_p->value);
+ *e1_p = convert_lvalue_to_rvalue (loc, *e1_p, true, true);
if (TREE_CODE (e1_p->value) == EXCESS_PRECISION_EXPR)
e1_p->value = convert (TREE_TYPE (e1_p->value),
TREE_OPERAND (e1_p->value, 0));
- mark_exp_read (e2_p->value);
+ *e2_p = convert_lvalue_to_rvalue (loc, *e2_p, true, true);
if (TREE_CODE (e2_p->value) == EXCESS_PRECISION_EXPR)
e2_p->value = convert (TREE_TYPE (e2_p->value),
TREE_OPERAND (e2_p->value, 0));
@@ -6960,7 +7193,7 @@ c_parser_postfix_expression (c_parser *parser)
}
FOR_EACH_VEC_SAFE_ELT (cexpr_list, i, p)
- mark_exp_read (p->value);
+ *p = convert_lvalue_to_rvalue (loc, *p, true, true);
if (vec_safe_length (cexpr_list) == 2)
expr.value =
@@ -7046,6 +7279,30 @@ c_parser_postfix_expression (c_parser *parser)
case RID_GENERIC:
expr = c_parser_generic_selection (parser);
break;
+ case RID_CILK_SPAWN:
+ c_parser_consume_token (parser);
+ if (!flag_enable_cilkplus)
+ {
+ error_at (loc, "-fcilkplus must be enabled to use "
+ "%<_Cilk_spawn%>");
+ expr = c_parser_postfix_expression (parser);
+ expr.value = error_mark_node;
+ }
+ if (c_parser_peek_token (parser)->keyword == RID_CILK_SPAWN)
+ {
+ error_at (loc, "consecutive %<_Cilk_spawn%> keywords "
+ "are not permitted");
+ /* Now flush out all the _Cilk_spawns. */
+ while (c_parser_peek_token (parser)->keyword == RID_CILK_SPAWN)
+ c_parser_consume_token (parser);
+ expr = c_parser_postfix_expression (parser);
+ }
+ else
+ {
+ expr = c_parser_postfix_expression (parser);
+ expr.value = build_cilk_spawn (loc, expr.value);
+ }
+ break;
default:
c_parser_error (parser, "expected expression");
expr.value = error_mark_node;
@@ -7280,7 +7537,7 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
case CPP_DEREF:
/* Structure element reference. */
c_parser_consume_token (parser);
- expr = default_function_array_conversion (expr_loc, expr);
+ expr = convert_lvalue_to_rvalue (expr_loc, expr, true, false);
if (c_parser_next_token_is (parser, CPP_NAME))
ident = c_parser_peek_token (parser)->value;
else
@@ -7358,8 +7615,11 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
static struct c_expr
c_parser_expression (c_parser *parser)
{
+ location_t tloc = c_parser_peek_token (parser)->location;
struct c_expr expr;
expr = c_parser_expr_no_commas (parser, NULL);
+ if (c_parser_next_token_is (parser, CPP_COMMA))
+ expr = convert_lvalue_to_rvalue (tloc, expr, true, false);
while (c_parser_next_token_is (parser, CPP_COMMA))
{
struct c_expr next;
@@ -7374,7 +7634,7 @@ c_parser_expression (c_parser *parser)
if (DECL_P (lhsval) || handled_component_p (lhsval))
mark_exp_read (lhsval);
next = c_parser_expr_no_commas (parser, NULL);
- next = default_function_array_conversion (expr_loc, next);
+ next = convert_lvalue_to_rvalue (expr_loc, next, true, false);
expr.value = build_compound_expr (loc, expr.value, next.value);
expr.original_code = COMPOUND_EXPR;
expr.original_type = next.original_type;
@@ -7382,8 +7642,8 @@ c_parser_expression (c_parser *parser)
return expr;
}
-/* Parse an expression and convert functions or arrays to
- pointers. */
+/* Parse an expression and convert functions or arrays to pointers and
+ lvalues to rvalues. */
static struct c_expr
c_parser_expression_conv (c_parser *parser)
@@ -7391,12 +7651,13 @@ c_parser_expression_conv (c_parser *parser)
struct c_expr expr;
location_t loc = c_parser_peek_token (parser)->location;
expr = c_parser_expression (parser);
- expr = default_function_array_conversion (loc, expr);
+ expr = convert_lvalue_to_rvalue (loc, expr, true, false);
return expr;
}
/* Parse a non-empty list of expressions. If CONVERT_P, convert
- functions and arrays to pointers. If FOLD_P, fold the expressions.
+ functions and arrays to pointers and lvalues to rvalues. If
+ FOLD_P, fold the expressions.
nonempty-expr-list:
assignment-expression
@@ -7426,7 +7687,7 @@ c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p,
cur_sizeof_arg_loc = c_parser_peek_2nd_token (parser)->location;
expr = c_parser_expr_no_commas (parser, NULL);
if (convert_p)
- expr = default_function_array_read_conversion (loc, expr);
+ expr = convert_lvalue_to_rvalue (loc, expr, true, true);
if (fold_p)
expr.value = c_fully_fold (expr.value, false, NULL);
ret->quick_push (expr.value);
@@ -7450,7 +7711,7 @@ c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p,
cur_sizeof_arg_loc = UNKNOWN_LOCATION;
expr = c_parser_expr_no_commas (parser, NULL);
if (convert_p)
- expr = default_function_array_read_conversion (loc, expr);
+ expr = convert_lvalue_to_rvalue (loc, expr, true, true);
if (fold_p)
expr.value = c_fully_fold (expr.value, false, NULL);
vec_safe_push (ret, expr.value);
@@ -7955,7 +8216,7 @@ c_parser_objc_methodprotolist (c_parser *parser)
}
else
c_parser_declaration_or_fndef (parser, false, false, true,
- false, true, NULL);
+ false, true, NULL, vNULL);
break;
}
}
@@ -8356,7 +8617,9 @@ c_parser_objc_synchronized_statement (c_parser *parser)
objc_maybe_warn_exceptions (loc);
if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
{
- expr = c_parser_expression (parser).value;
+ struct c_expr ce = c_parser_expression (parser);
+ ce = convert_lvalue_to_rvalue (loc, ce, false, false);
+ expr = ce.value;
expr = c_fully_fold (expr, false, NULL);
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
}
@@ -8376,6 +8639,7 @@ c_parser_objc_synchronized_statement (c_parser *parser)
break continue return goto asm sizeof typeof __alignof
unsigned long const short volatile signed restrict _Complex
in out inout bycopy byref oneway int char float double void _Bool
+ _Atomic
??? Why this selection of keywords but not, for example, storage
class specifiers? */
@@ -8434,6 +8698,7 @@ c_parser_objc_selector (c_parser *parser)
case RID_DOUBLE:
case RID_VOID:
case RID_BOOL:
+ case RID_ATOMIC:
c_parser_consume_token (parser);
return value;
default:
@@ -8486,6 +8751,8 @@ c_parser_objc_selector_arg (c_parser *parser)
static tree
c_parser_objc_receiver (c_parser *parser)
{
+ location_t loc = c_parser_peek_token (parser)->location;
+
if (c_parser_peek_token (parser)->type == CPP_NAME
&& (c_parser_peek_token (parser)->id_kind == C_ID_TYPENAME
|| c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME))
@@ -8494,7 +8761,9 @@ c_parser_objc_receiver (c_parser *parser)
c_parser_consume_token (parser);
return objc_get_class_reference (id);
}
- return c_fully_fold (c_parser_expression (parser).value, false, NULL);
+ struct c_expr ce = c_parser_expression (parser);
+ ce = convert_lvalue_to_rvalue (loc, ce, false, false);
+ return c_fully_fold (ce.value, false, NULL);
}
/* Parse objc-message-args.
@@ -8936,10 +9205,39 @@ c_parser_pragma (c_parser *parser, enum pragma_context context)
c_parser_omp_taskyield (parser);
return false;
+ case PRAGMA_OMP_CANCEL:
+ if (context != pragma_compound)
+ {
+ if (context == pragma_stmt)
+ c_parser_error (parser, "%<#pragma omp cancel%> may only be "
+ "used in compound statements");
+ goto bad_stmt;
+ }
+ c_parser_omp_cancel (parser);
+ return false;
+
+ case PRAGMA_OMP_CANCELLATION_POINT:
+ if (context != pragma_compound)
+ {
+ if (context == pragma_stmt)
+ c_parser_error (parser, "%<#pragma omp cancellation point%> may "
+ "only be used in compound statements");
+ goto bad_stmt;
+ }
+ c_parser_omp_cancellation_point (parser);
+ return false;
+
case PRAGMA_OMP_THREADPRIVATE:
c_parser_omp_threadprivate (parser);
return false;
+ case PRAGMA_OMP_TARGET:
+ return c_parser_omp_target (parser, context);
+
+ case PRAGMA_OMP_END_DECLARE_TARGET:
+ c_parser_omp_end_declare_target (parser);
+ return false;
+
case PRAGMA_OMP_SECTION:
error_at (c_parser_peek_token (parser)->location,
"%<#pragma omp section%> may only be used in "
@@ -8947,6 +9245,27 @@ c_parser_pragma (c_parser *parser, enum pragma_context context)
c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
return false;
+ case PRAGMA_OMP_DECLARE_REDUCTION:
+ c_parser_omp_declare (parser, context);
+ return false;
+ case PRAGMA_IVDEP:
+ c_parser_consume_pragma (parser);
+ c_parser_skip_to_pragma_eol (parser);
+ if (!c_parser_next_token_is_keyword (parser, RID_FOR)
+ && !c_parser_next_token_is_keyword (parser, RID_WHILE)
+ && !c_parser_next_token_is_keyword (parser, RID_DO))
+ {
+ c_parser_error (parser, "for, while or do statement expected");
+ return false;
+ }
+ if (c_parser_next_token_is_keyword (parser, RID_FOR))
+ c_parser_for_statement (parser, true);
+ else if (c_parser_next_token_is_keyword (parser, RID_WHILE))
+ c_parser_while_statement (parser, true);
+ else
+ c_parser_do_statement (parser, true);
+ return false;
+
case PRAGMA_GCC_PCH_PREPROCESS:
c_parser_error (parser, "%<#pragma GCC pch_preprocess%> must be first");
c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
@@ -8955,7 +9274,7 @@ c_parser_pragma (c_parser *parser, enum pragma_context context)
default:
if (id < PRAGMA_FIRST_EXTERNAL)
{
- if (context == pragma_external)
+ if (context != pragma_stmt && context != pragma_compound)
{
bad_stmt:
c_parser_error (parser, "expected declaration specifiers");
@@ -9020,7 +9339,7 @@ c_parser_pragma_pch_preprocess (c_parser *parser)
c_common_pch_pragma (parse_in, TREE_STRING_POINTER (name));
}
-/* OpenMP 2.5 parsing routines. */
+/* OpenMP 2.5 / 3.0 / 3.1 / 4.0 parsing routines. */
/* Returns name of the next clause.
If the clause is not recognized PRAGMA_OMP_CLAUSE_NONE is returned and
@@ -9036,12 +9355,18 @@ c_parser_omp_clause_name (c_parser *parser)
result = PRAGMA_OMP_CLAUSE_IF;
else if (c_parser_next_token_is_keyword (parser, RID_DEFAULT))
result = PRAGMA_OMP_CLAUSE_DEFAULT;
+ else if (c_parser_next_token_is_keyword (parser, RID_FOR))
+ result = PRAGMA_OMP_CLAUSE_FOR;
else if (c_parser_next_token_is (parser, CPP_NAME))
{
const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
switch (p[0])
{
+ case 'a':
+ if (!strcmp ("aligned", p))
+ result = PRAGMA_OMP_CLAUSE_ALIGNED;
+ break;
case 'c':
if (!strcmp ("collapse", p))
result = PRAGMA_OMP_CLAUSE_COLLAPSE;
@@ -9050,23 +9375,45 @@ c_parser_omp_clause_name (c_parser *parser)
else if (!strcmp ("copyprivate", p))
result = PRAGMA_OMP_CLAUSE_COPYPRIVATE;
break;
+ case 'd':
+ if (!strcmp ("depend", p))
+ result = PRAGMA_OMP_CLAUSE_DEPEND;
+ else if (!strcmp ("device", p))
+ result = PRAGMA_OMP_CLAUSE_DEVICE;
+ else if (!strcmp ("dist_schedule", p))
+ result = PRAGMA_OMP_CLAUSE_DIST_SCHEDULE;
+ break;
case 'f':
if (!strcmp ("final", p))
result = PRAGMA_OMP_CLAUSE_FINAL;
else if (!strcmp ("firstprivate", p))
result = PRAGMA_OMP_CLAUSE_FIRSTPRIVATE;
+ else if (!strcmp ("from", p))
+ result = PRAGMA_OMP_CLAUSE_FROM;
+ break;
+ case 'i':
+ if (!strcmp ("inbranch", p))
+ result = PRAGMA_OMP_CLAUSE_INBRANCH;
break;
case 'l':
if (!strcmp ("lastprivate", p))
result = PRAGMA_OMP_CLAUSE_LASTPRIVATE;
+ else if (!strcmp ("linear", p))
+ result = PRAGMA_OMP_CLAUSE_LINEAR;
break;
case 'm':
- if (!strcmp ("mergeable", p))
+ if (!strcmp ("map", p))
+ result = PRAGMA_OMP_CLAUSE_MAP;
+ else if (!strcmp ("mergeable", p))
result = PRAGMA_OMP_CLAUSE_MERGEABLE;
break;
case 'n':
- if (!strcmp ("nowait", p))
+ if (!strcmp ("notinbranch", p))
+ result = PRAGMA_OMP_CLAUSE_NOTINBRANCH;
+ else if (!strcmp ("nowait", p))
result = PRAGMA_OMP_CLAUSE_NOWAIT;
+ else if (!strcmp ("num_teams", p))
+ result = PRAGMA_OMP_CLAUSE_NUM_TEAMS;
else if (!strcmp ("num_threads", p))
result = PRAGMA_OMP_CLAUSE_NUM_THREADS;
break;
@@ -9075,21 +9422,41 @@ c_parser_omp_clause_name (c_parser *parser)
result = PRAGMA_OMP_CLAUSE_ORDERED;
break;
case 'p':
- if (!strcmp ("private", p))
+ if (!strcmp ("parallel", p))
+ result = PRAGMA_OMP_CLAUSE_PARALLEL;
+ else if (!strcmp ("private", p))
result = PRAGMA_OMP_CLAUSE_PRIVATE;
+ else if (!strcmp ("proc_bind", p))
+ result = PRAGMA_OMP_CLAUSE_PROC_BIND;
break;
case 'r':
if (!strcmp ("reduction", p))
result = PRAGMA_OMP_CLAUSE_REDUCTION;
break;
case 's':
- if (!strcmp ("schedule", p))
+ if (!strcmp ("safelen", p))
+ result = PRAGMA_OMP_CLAUSE_SAFELEN;
+ else if (!strcmp ("schedule", p))
result = PRAGMA_OMP_CLAUSE_SCHEDULE;
+ else if (!strcmp ("sections", p))
+ result = PRAGMA_OMP_CLAUSE_SECTIONS;
else if (!strcmp ("shared", p))
result = PRAGMA_OMP_CLAUSE_SHARED;
+ else if (!strcmp ("simdlen", p))
+ result = PRAGMA_OMP_CLAUSE_SIMDLEN;
+ break;
+ case 't':
+ if (!strcmp ("taskgroup", p))
+ result = PRAGMA_OMP_CLAUSE_TASKGROUP;
+ else if (!strcmp ("thread_limit", p))
+ result = PRAGMA_OMP_CLAUSE_THREAD_LIMIT;
+ else if (!strcmp ("to", p))
+ result = PRAGMA_OMP_CLAUSE_TO;
break;
case 'u':
- if (!strcmp ("untied", p))
+ if (!strcmp ("uniform", p))
+ result = PRAGMA_OMP_CLAUSE_UNIFORM;
+ else if (!strcmp ("untied", p))
result = PRAGMA_OMP_CLAUSE_UNTIED;
break;
}
@@ -9133,8 +9500,7 @@ check_no_duplicate_clause (tree clauses, enum omp_clause_code code,
static tree
c_parser_omp_variable_list (c_parser *parser,
location_t clause_loc,
- enum omp_clause_code kind,
- tree list)
+ enum omp_clause_code kind, tree list)
{
if (c_parser_next_token_is_not (parser, CPP_NAME)
|| c_parser_peek_token (parser)->id_kind != C_ID_ID)
@@ -9146,22 +9512,70 @@ c_parser_omp_variable_list (c_parser *parser,
tree t = lookup_name (c_parser_peek_token (parser)->value);
if (t == NULL_TREE)
- undeclared_variable (c_parser_peek_token (parser)->location,
- c_parser_peek_token (parser)->value);
- else if (t == error_mark_node)
+ {
+ undeclared_variable (c_parser_peek_token (parser)->location,
+ c_parser_peek_token (parser)->value);
+ t = error_mark_node;
+ }
+
+ c_parser_consume_token (parser);
+
+ if (t == error_mark_node)
;
else if (kind != 0)
{
- tree u = build_omp_clause (clause_loc, kind);
- OMP_CLAUSE_DECL (u) = t;
- OMP_CLAUSE_CHAIN (u) = list;
- list = u;
+ switch (kind)
+ {
+ case OMP_CLAUSE_MAP:
+ case OMP_CLAUSE_FROM:
+ case OMP_CLAUSE_TO:
+ case OMP_CLAUSE_DEPEND:
+ while (c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
+ {
+ tree low_bound = NULL_TREE, length = NULL_TREE;
+
+ c_parser_consume_token (parser);
+ if (!c_parser_next_token_is (parser, CPP_COLON))
+ low_bound = c_parser_expression (parser).value;
+ if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
+ length = integer_one_node;
+ else
+ {
+ /* Look for `:'. */
+ if (!c_parser_require (parser, CPP_COLON,
+ "expected %<:%>"))
+ {
+ t = error_mark_node;
+ break;
+ }
+ if (!c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
+ length = c_parser_expression (parser).value;
+ }
+ /* Look for the closing `]'. */
+ if (!c_parser_require (parser, CPP_CLOSE_SQUARE,
+ "expected %<]%>"))
+ {
+ t = error_mark_node;
+ break;
+ }
+ t = tree_cons (low_bound, length, t);
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (t != error_mark_node)
+ {
+ tree u = build_omp_clause (clause_loc, kind);
+ OMP_CLAUSE_DECL (u) = t;
+ OMP_CLAUSE_CHAIN (u) = list;
+ list = u;
+ }
}
else
list = tree_cons (t, NULL_TREE, list);
- c_parser_consume_token (parser);
-
if (c_parser_next_token_is_not (parser, CPP_COMMA))
break;
@@ -9209,6 +9623,8 @@ c_parser_omp_clause_collapse (c_parser *parser, tree list)
}
if (num == error_mark_node)
return list;
+ mark_exp_read (num);
+ num = c_fully_fold (num, false, NULL);
if (!INTEGRAL_TYPE_P (TREE_TYPE (num))
|| !host_integerp (num, 0)
|| (n = tree_low_cst (num, 0)) <= 0
@@ -9474,11 +9890,17 @@ c_parser_omp_clause_private (c_parser *parser, tree list)
reduction-operator:
One of: + * - & ^ | && ||
-
+
OpenMP 3.1:
reduction-operator:
- One of: + * - & ^ | && || max min */
+ One of: + * - & ^ | && || max min
+
+ OpenMP 4.0:
+
+ reduction-operator:
+ One of: + * - & ^ | && ||
+ identifier */
static tree
c_parser_omp_clause_reduction (c_parser *parser, tree list)
@@ -9486,7 +9908,8 @@ c_parser_omp_clause_reduction (c_parser *parser, tree list)
location_t clause_loc = c_parser_peek_token (parser)->location;
if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
{
- enum tree_code code;
+ enum tree_code code = ERROR_MARK;
+ tree reduc_id = NULL_TREE;
switch (c_parser_peek_token (parser)->type)
{
@@ -9528,8 +9951,9 @@ c_parser_omp_clause_reduction (c_parser *parser, tree list)
code = MAX_EXPR;
break;
}
+ reduc_id = c_parser_peek_token (parser)->value;
+ break;
}
- /* FALLTHRU */
default:
c_parser_error (parser,
"expected %<+%>, %<*%>, %<-%>, %<&%>, "
@@ -9538,6 +9962,7 @@ c_parser_omp_clause_reduction (c_parser *parser, tree list)
return list;
}
c_parser_consume_token (parser);
+ reduc_id = c_omp_reduction_id (code, reduc_id);
if (c_parser_require (parser, CPP_COLON, "expected %<:%>"))
{
tree nl, c;
@@ -9545,7 +9970,17 @@ c_parser_omp_clause_reduction (c_parser *parser, tree list)
nl = c_parser_omp_variable_list (parser, clause_loc,
OMP_CLAUSE_REDUCTION, list);
for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
- OMP_CLAUSE_REDUCTION_CODE (c) = code;
+ {
+ tree type = TREE_TYPE (OMP_CLAUSE_DECL (c));
+ OMP_CLAUSE_REDUCTION_CODE (c) = code;
+ if (code == ERROR_MARK
+ || !(INTEGRAL_TYPE_P (type)
+ || TREE_CODE (type) == REAL_TYPE
+ || TREE_CODE (type) == COMPLEX_TYPE))
+ OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
+ = c_omp_reduction_lookup (reduc_id,
+ TYPE_MAIN_VARIANT (type));
+ }
list = nl;
}
@@ -9675,13 +10110,544 @@ c_parser_omp_clause_untied (c_parser *parser ATTRIBUTE_UNUSED, tree list)
return c;
}
+/* OpenMP 4.0:
+ inbranch
+ notinbranch */
+
+static tree
+c_parser_omp_clause_branch (c_parser *parser ATTRIBUTE_UNUSED,
+ enum omp_clause_code code, tree list)
+{
+ check_no_duplicate_clause (list, code, omp_clause_code_name[code]);
+
+ tree c = build_omp_clause (c_parser_peek_token (parser)->location, code);
+ OMP_CLAUSE_CHAIN (c) = list;
+
+ return c;
+}
+
+/* OpenMP 4.0:
+ parallel
+ for
+ sections
+ taskgroup */
+
+static tree
+c_parser_omp_clause_cancelkind (c_parser *parser ATTRIBUTE_UNUSED,
+ enum omp_clause_code code, tree list)
+{
+ tree c = build_omp_clause (c_parser_peek_token (parser)->location, code);
+ OMP_CLAUSE_CHAIN (c) = list;
+
+ return c;
+}
+
+/* OpenMP 4.0:
+ num_teams ( expression ) */
+
+static tree
+c_parser_omp_clause_num_teams (c_parser *parser, tree list)
+{
+ location_t num_teams_loc = c_parser_peek_token (parser)->location;
+ if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ {
+ location_t expr_loc = c_parser_peek_token (parser)->location;
+ tree c, t = c_parser_expression (parser).value;
+ mark_exp_read (t);
+ t = c_fully_fold (t, false, NULL);
+
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
+ {
+ c_parser_error (parser, "expected integer expression");
+ return list;
+ }
+
+ /* Attempt to statically determine when the number isn't positive. */
+ c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t,
+ build_int_cst (TREE_TYPE (t), 0));
+ if (CAN_HAVE_LOCATION_P (c))
+ SET_EXPR_LOCATION (c, expr_loc);
+ if (c == boolean_true_node)
+ {
+ warning_at (expr_loc, 0, "%<num_teams%> value must be positive");
+ t = integer_one_node;
+ }
+
+ check_no_duplicate_clause (list, OMP_CLAUSE_NUM_TEAMS, "num_teams");
+
+ c = build_omp_clause (num_teams_loc, OMP_CLAUSE_NUM_TEAMS);
+ OMP_CLAUSE_NUM_TEAMS_EXPR (c) = t;
+ OMP_CLAUSE_CHAIN (c) = list;
+ list = c;
+ }
+
+ return list;
+}
+
+/* OpenMP 4.0:
+ thread_limit ( expression ) */
+
+static tree
+c_parser_omp_clause_thread_limit (c_parser *parser, tree list)
+{
+ location_t num_teams_loc = c_parser_peek_token (parser)->location;
+ if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ {
+ location_t expr_loc = c_parser_peek_token (parser)->location;
+ tree c, t = c_parser_expression (parser).value;
+ mark_exp_read (t);
+ t = c_fully_fold (t, false, NULL);
+
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
+ {
+ c_parser_error (parser, "expected integer expression");
+ return list;
+ }
+
+ /* Attempt to statically determine when the number isn't positive. */
+ c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t,
+ build_int_cst (TREE_TYPE (t), 0));
+ if (CAN_HAVE_LOCATION_P (c))
+ SET_EXPR_LOCATION (c, expr_loc);
+ if (c == boolean_true_node)
+ {
+ warning_at (expr_loc, 0, "%<thread_limit%> value must be positive");
+ t = integer_one_node;
+ }
+
+ check_no_duplicate_clause (list, OMP_CLAUSE_THREAD_LIMIT,
+ "thread_limit");
+
+ c = build_omp_clause (num_teams_loc, OMP_CLAUSE_THREAD_LIMIT);
+ OMP_CLAUSE_THREAD_LIMIT_EXPR (c) = t;
+ OMP_CLAUSE_CHAIN (c) = list;
+ list = c;
+ }
+
+ return list;
+}
+
+/* OpenMP 4.0:
+ aligned ( variable-list )
+ aligned ( variable-list : constant-expression ) */
+
+static tree
+c_parser_omp_clause_aligned (c_parser *parser, tree list)
+{
+ location_t clause_loc = c_parser_peek_token (parser)->location;
+ tree nl, c;
+
+ if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ return list;
+
+ nl = c_parser_omp_variable_list (parser, clause_loc,
+ OMP_CLAUSE_ALIGNED, list);
+
+ if (c_parser_next_token_is (parser, CPP_COLON))
+ {
+ c_parser_consume_token (parser);
+ tree alignment = c_parser_expr_no_commas (parser, NULL).value;
+ mark_exp_read (alignment);
+ alignment = c_fully_fold (alignment, false, NULL);
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (alignment))
+ && TREE_CODE (alignment) != INTEGER_CST
+ && tree_int_cst_sgn (alignment) != 1)
+ {
+ error_at (clause_loc, "%<aligned%> clause alignment expression must "
+ "be positive constant integer expression");
+ alignment = NULL_TREE;
+ }
+
+ for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
+ OMP_CLAUSE_ALIGNED_ALIGNMENT (c) = alignment;
+ }
+
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+ return nl;
+}
+
+/* OpenMP 4.0:
+ linear ( variable-list )
+ linear ( variable-list : expression ) */
+
+static tree
+c_parser_omp_clause_linear (c_parser *parser, tree list)
+{
+ location_t clause_loc = c_parser_peek_token (parser)->location;
+ tree nl, c, step;
+
+ if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ return list;
+
+ nl = c_parser_omp_variable_list (parser, clause_loc,
+ OMP_CLAUSE_LINEAR, list);
+
+ if (c_parser_next_token_is (parser, CPP_COLON))
+ {
+ c_parser_consume_token (parser);
+ step = c_parser_expression (parser).value;
+ mark_exp_read (step);
+ step = c_fully_fold (step, false, NULL);
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (step)))
+ {
+ error_at (clause_loc, "%<linear%> clause step expression must "
+ "be integral");
+ step = integer_one_node;
+ }
+
+ }
+ else
+ step = integer_one_node;
+
+ for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
+ {
+ OMP_CLAUSE_LINEAR_STEP (c) = step;
+ }
+
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+ return nl;
+}
+
+/* OpenMP 4.0:
+ safelen ( constant-expression ) */
+
+static tree
+c_parser_omp_clause_safelen (c_parser *parser, tree list)
+{
+ location_t clause_loc = c_parser_peek_token (parser)->location;
+ tree c, t;
+
+ if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ return list;
+
+ t = c_parser_expr_no_commas (parser, NULL).value;
+ mark_exp_read (t);
+ t = c_fully_fold (t, false, NULL);
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (t))
+ && TREE_CODE (t) != INTEGER_CST
+ && tree_int_cst_sgn (t) != 1)
+ {
+ error_at (clause_loc, "%<safelen%> clause expression must "
+ "be positive constant integer expression");
+ t = NULL_TREE;
+ }
+
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+ if (t == NULL_TREE || t == error_mark_node)
+ return list;
+
+ check_no_duplicate_clause (list, OMP_CLAUSE_SAFELEN, "safelen");
+
+ c = build_omp_clause (clause_loc, OMP_CLAUSE_SAFELEN);
+ OMP_CLAUSE_SAFELEN_EXPR (c) = t;
+ OMP_CLAUSE_CHAIN (c) = list;
+ return c;
+}
+
+/* OpenMP 4.0:
+ simdlen ( constant-expression ) */
+
+static tree
+c_parser_omp_clause_simdlen (c_parser *parser, tree list)
+{
+ location_t clause_loc = c_parser_peek_token (parser)->location;
+ tree c, t;
+
+ if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ return list;
+
+ t = c_parser_expr_no_commas (parser, NULL).value;
+ mark_exp_read (t);
+ t = c_fully_fold (t, false, NULL);
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (t))
+ && TREE_CODE (t) != INTEGER_CST
+ && tree_int_cst_sgn (t) != 1)
+ {
+ error_at (clause_loc, "%<simdlen%> clause expression must "
+ "be positive constant integer expression");
+ t = NULL_TREE;
+ }
+
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+ if (t == NULL_TREE || t == error_mark_node)
+ return list;
+
+ check_no_duplicate_clause (list, OMP_CLAUSE_SIMDLEN, "simdlen");
+
+ c = build_omp_clause (clause_loc, OMP_CLAUSE_SIMDLEN);
+ OMP_CLAUSE_SIMDLEN_EXPR (c) = t;
+ OMP_CLAUSE_CHAIN (c) = list;
+ return c;
+}
+
+/* OpenMP 4.0:
+ depend ( depend-kind: variable-list )
+
+ depend-kind:
+ in | out | inout */
+
+static tree
+c_parser_omp_clause_depend (c_parser *parser, tree list)
+{
+ location_t clause_loc = c_parser_peek_token (parser)->location;
+ enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_INOUT;
+ tree nl, c;
+
+ if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ return list;
+
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ {
+ const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+ if (strcmp ("in", p) == 0)
+ kind = OMP_CLAUSE_DEPEND_IN;
+ else if (strcmp ("inout", p) == 0)
+ kind = OMP_CLAUSE_DEPEND_INOUT;
+ else if (strcmp ("out", p) == 0)
+ kind = OMP_CLAUSE_DEPEND_OUT;
+ else
+ goto invalid_kind;
+ }
+ else
+ goto invalid_kind;
+
+ c_parser_consume_token (parser);
+ if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
+ goto resync_fail;
+
+ nl = c_parser_omp_variable_list (parser, clause_loc,
+ OMP_CLAUSE_DEPEND, list);
+
+ for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
+ OMP_CLAUSE_DEPEND_KIND (c) = kind;
+
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+ return nl;
+
+ invalid_kind:
+ c_parser_error (parser, "invalid depend kind");
+ resync_fail:
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+ return list;
+}
+
+/* OpenMP 4.0:
+ map ( map-kind: variable-list )
+ map ( variable-list )
+
+ map-kind:
+ alloc | to | from | tofrom */
+
+static tree
+c_parser_omp_clause_map (c_parser *parser, tree list)
+{
+ location_t clause_loc = c_parser_peek_token (parser)->location;
+ enum omp_clause_map_kind kind = OMP_CLAUSE_MAP_TOFROM;
+ tree nl, c;
+
+ if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ return list;
+
+ if (c_parser_next_token_is (parser, CPP_NAME)
+ && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
+ {
+ const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+ if (strcmp ("alloc", p) == 0)
+ kind = OMP_CLAUSE_MAP_ALLOC;
+ else if (strcmp ("to", p) == 0)
+ kind = OMP_CLAUSE_MAP_TO;
+ else if (strcmp ("from", p) == 0)
+ kind = OMP_CLAUSE_MAP_FROM;
+ else if (strcmp ("tofrom", p) == 0)
+ kind = OMP_CLAUSE_MAP_TOFROM;
+ else
+ {
+ c_parser_error (parser, "invalid map kind");
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+ "expected %<)%>");
+ return list;
+ }
+ c_parser_consume_token (parser);
+ c_parser_consume_token (parser);
+ }
+
+ nl = c_parser_omp_variable_list (parser, clause_loc, OMP_CLAUSE_MAP, list);
+
+ for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
+ OMP_CLAUSE_MAP_KIND (c) = kind;
+
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+ return nl;
+}
+
+/* OpenMP 4.0:
+ device ( expression ) */
+
+static tree
+c_parser_omp_clause_device (c_parser *parser, tree list)
+{
+ location_t clause_loc = c_parser_peek_token (parser)->location;
+ if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ {
+ tree c, t = c_parser_expr_no_commas (parser, NULL).value;
+ mark_exp_read (t);
+ t = c_fully_fold (t, false, NULL);
+
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
+ {
+ c_parser_error (parser, "expected integer expression");
+ return list;
+ }
+
+ check_no_duplicate_clause (list, OMP_CLAUSE_DEVICE, "device");
+
+ c = build_omp_clause (clause_loc, OMP_CLAUSE_DEVICE);
+ OMP_CLAUSE_DEVICE_ID (c) = t;
+ OMP_CLAUSE_CHAIN (c) = list;
+ list = c;
+ }
+
+ return list;
+}
+
+/* OpenMP 4.0:
+ dist_schedule ( static )
+ dist_schedule ( static , expression ) */
+
+static tree
+c_parser_omp_clause_dist_schedule (c_parser *parser, tree list)
+{
+ tree c, t = NULL_TREE;
+ location_t loc = c_parser_peek_token (parser)->location;
+
+ if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ return list;
+
+ if (!c_parser_next_token_is_keyword (parser, RID_STATIC))
+ {
+ c_parser_error (parser, "invalid dist_schedule kind");
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+ "expected %<)%>");
+ return list;
+ }
+
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is (parser, CPP_COMMA))
+ {
+ c_parser_consume_token (parser);
+
+ t = c_parser_expr_no_commas (parser, NULL).value;
+ mark_exp_read (t);
+ t = c_fully_fold (t, false, NULL);
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+ }
+ else
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+ "expected %<,%> or %<)%>");
+
+ check_no_duplicate_clause (list, OMP_CLAUSE_SCHEDULE, "schedule");
+ if (t == error_mark_node)
+ return list;
+
+ c = build_omp_clause (loc, OMP_CLAUSE_DIST_SCHEDULE);
+ OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (c) = t;
+ OMP_CLAUSE_CHAIN (c) = list;
+ return c;
+}
+
+/* OpenMP 4.0:
+ proc_bind ( proc-bind-kind )
+
+ proc-bind-kind:
+ master | close | spread */
+
+static tree
+c_parser_omp_clause_proc_bind (c_parser *parser, tree list)
+{
+ location_t clause_loc = c_parser_peek_token (parser)->location;
+ enum omp_clause_proc_bind_kind kind;
+ tree c;
+
+ if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ return list;
+
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ {
+ const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+ if (strcmp ("master", p) == 0)
+ kind = OMP_CLAUSE_PROC_BIND_MASTER;
+ else if (strcmp ("close", p) == 0)
+ kind = OMP_CLAUSE_PROC_BIND_CLOSE;
+ else if (strcmp ("spread", p) == 0)
+ kind = OMP_CLAUSE_PROC_BIND_SPREAD;
+ else
+ goto invalid_kind;
+ }
+ else
+ goto invalid_kind;
+
+ c_parser_consume_token (parser);
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+ c = build_omp_clause (clause_loc, OMP_CLAUSE_PROC_BIND);
+ OMP_CLAUSE_PROC_BIND_KIND (c) = kind;
+ OMP_CLAUSE_CHAIN (c) = list;
+ return c;
+
+ invalid_kind:
+ c_parser_error (parser, "invalid proc_bind kind");
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+ return list;
+}
+
+/* OpenMP 4.0:
+ to ( variable-list ) */
+
+static tree
+c_parser_omp_clause_to (c_parser *parser, tree list)
+{
+ return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_TO, list);
+}
+
+/* OpenMP 4.0:
+ from ( variable-list ) */
+
+static tree
+c_parser_omp_clause_from (c_parser *parser, tree list)
+{
+ return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_FROM, list);
+}
+
+/* OpenMP 4.0:
+ uniform ( variable-list ) */
+
+static tree
+c_parser_omp_clause_uniform (c_parser *parser, tree list)
+{
+ /* The clauses location. */
+ location_t loc = c_parser_peek_token (parser)->location;
+
+ if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ {
+ list = c_parser_omp_variable_list (parser, loc, OMP_CLAUSE_UNIFORM,
+ list);
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+ }
+ return list;
+}
+
/* Parse all OpenMP clauses. The set clauses allowed by the directive
is a bitmask in MASK. Return the list of clauses found; the result
of clause default goes in *pdefault. */
static tree
-c_parser_omp_all_clauses (c_parser *parser, unsigned int mask,
- const char *where)
+c_parser_omp_all_clauses (c_parser *parser, omp_clause_mask mask,
+ const char *where, bool finish_p = true)
{
tree clauses = NULL;
bool first = true;
@@ -9696,7 +10662,6 @@ c_parser_omp_all_clauses (c_parser *parser, unsigned int mask,
if (!first && c_parser_next_token_is (parser, CPP_COMMA))
c_parser_consume_token (parser);
- first = false;
here = c_parser_peek_token (parser)->location;
c_kind = c_parser_omp_clause_name (parser);
@@ -9770,11 +10735,116 @@ c_parser_omp_all_clauses (c_parser *parser, unsigned int mask,
clauses = c_parser_omp_clause_untied (parser, clauses);
c_name = "untied";
break;
+ case PRAGMA_OMP_CLAUSE_INBRANCH:
+ clauses = c_parser_omp_clause_branch (parser, OMP_CLAUSE_INBRANCH,
+ clauses);
+ c_name = "inbranch";
+ break;
+ case PRAGMA_OMP_CLAUSE_NOTINBRANCH:
+ clauses = c_parser_omp_clause_branch (parser, OMP_CLAUSE_NOTINBRANCH,
+ clauses);
+ c_name = "notinbranch";
+ break;
+ case PRAGMA_OMP_CLAUSE_PARALLEL:
+ clauses
+ = c_parser_omp_clause_cancelkind (parser, OMP_CLAUSE_PARALLEL,
+ clauses);
+ c_name = "parallel";
+ if (!first)
+ {
+ clause_not_first:
+ error_at (here, "%qs must be the first clause of %qs",
+ c_name, where);
+ clauses = prev;
+ }
+ break;
+ case PRAGMA_OMP_CLAUSE_FOR:
+ clauses
+ = c_parser_omp_clause_cancelkind (parser, OMP_CLAUSE_FOR,
+ clauses);
+ c_name = "for";
+ if (!first)
+ goto clause_not_first;
+ break;
+ case PRAGMA_OMP_CLAUSE_SECTIONS:
+ clauses
+ = c_parser_omp_clause_cancelkind (parser, OMP_CLAUSE_SECTIONS,
+ clauses);
+ c_name = "sections";
+ if (!first)
+ goto clause_not_first;
+ break;
+ case PRAGMA_OMP_CLAUSE_TASKGROUP:
+ clauses
+ = c_parser_omp_clause_cancelkind (parser, OMP_CLAUSE_TASKGROUP,
+ clauses);
+ c_name = "taskgroup";
+ if (!first)
+ goto clause_not_first;
+ break;
+ case PRAGMA_OMP_CLAUSE_TO:
+ clauses = c_parser_omp_clause_to (parser, clauses);
+ c_name = "to";
+ break;
+ case PRAGMA_OMP_CLAUSE_FROM:
+ clauses = c_parser_omp_clause_from (parser, clauses);
+ c_name = "from";
+ break;
+ case PRAGMA_OMP_CLAUSE_UNIFORM:
+ clauses = c_parser_omp_clause_uniform (parser, clauses);
+ c_name = "uniform";
+ break;
+ case PRAGMA_OMP_CLAUSE_NUM_TEAMS:
+ clauses = c_parser_omp_clause_num_teams (parser, clauses);
+ c_name = "num_teams";
+ break;
+ case PRAGMA_OMP_CLAUSE_THREAD_LIMIT:
+ clauses = c_parser_omp_clause_thread_limit (parser, clauses);
+ c_name = "thread_limit";
+ break;
+ case PRAGMA_OMP_CLAUSE_ALIGNED:
+ clauses = c_parser_omp_clause_aligned (parser, clauses);
+ c_name = "aligned";
+ break;
+ case PRAGMA_OMP_CLAUSE_LINEAR:
+ clauses = c_parser_omp_clause_linear (parser, clauses);
+ c_name = "linear";
+ break;
+ case PRAGMA_OMP_CLAUSE_DEPEND:
+ clauses = c_parser_omp_clause_depend (parser, clauses);
+ c_name = "depend";
+ break;
+ case PRAGMA_OMP_CLAUSE_MAP:
+ clauses = c_parser_omp_clause_map (parser, clauses);
+ c_name = "map";
+ break;
+ case PRAGMA_OMP_CLAUSE_DEVICE:
+ clauses = c_parser_omp_clause_device (parser, clauses);
+ c_name = "device";
+ break;
+ case PRAGMA_OMP_CLAUSE_DIST_SCHEDULE:
+ clauses = c_parser_omp_clause_dist_schedule (parser, clauses);
+ c_name = "dist_schedule";
+ break;
+ case PRAGMA_OMP_CLAUSE_PROC_BIND:
+ clauses = c_parser_omp_clause_proc_bind (parser, clauses);
+ c_name = "proc_bind";
+ break;
+ case PRAGMA_OMP_CLAUSE_SAFELEN:
+ clauses = c_parser_omp_clause_safelen (parser, clauses);
+ c_name = "safelen";
+ break;
+ case PRAGMA_OMP_CLAUSE_SIMDLEN:
+ clauses = c_parser_omp_clause_simdlen (parser, clauses);
+ c_name = "simdlen";
+ break;
default:
c_parser_error (parser, "expected %<#pragma omp%> clause");
goto saw_error;
}
+ first = false;
+
if (((mask >> c_kind) & 1) == 0 && !parser->error)
{
/* Remove the invalid clause(s) from the list to avoid
@@ -9787,7 +10857,10 @@ c_parser_omp_all_clauses (c_parser *parser, unsigned int mask,
saw_error:
c_parser_skip_to_pragma_eol (parser);
- return c_finish_omp_clauses (clauses);
+ if (finish_p)
+ return c_finish_omp_clauses (clauses);
+
+ return clauses;
}
/* OpenMP 2.5:
@@ -9843,10 +10916,18 @@ c_parser_omp_structured_block (c_parser *parser)
update-stmt:
expression-stmt | x = x binop expr
capture-stmt:
- v = x binop= expr | v = x++ | v = ++x | v = x-- | v = --x
+ v = expression-stmt
capture-block:
{ v = x; update-stmt; } | { update-stmt; v = x; }
+ OpenMP 4.0:
+ update-stmt:
+ expression-stmt | x = x binop expr | x = expr binop x
+ capture-stmt:
+ v = update-stmt
+ capture-block:
+ { v = x; update-stmt; } | { update-stmt; v = x; } | { v = x; x = expr; }
+
where x and v are lvalue expressions with scalar type.
LOC is the location of the #pragma token. */
@@ -9856,10 +10937,13 @@ c_parser_omp_atomic (location_t loc, c_parser *parser)
{
tree lhs = NULL_TREE, rhs = NULL_TREE, v = NULL_TREE;
tree lhs1 = NULL_TREE, rhs1 = NULL_TREE;
- tree stmt, orig_lhs;
+ tree stmt, orig_lhs, unfolded_lhs = NULL_TREE, unfolded_lhs1 = NULL_TREE;
enum tree_code code = OMP_ATOMIC, opcode = NOP_EXPR;
- struct c_expr rhs_expr;
+ struct c_expr expr;
+ location_t eloc;
bool structured_block = false;
+ bool swapped = false;
+ bool seq_cst = false;
if (c_parser_next_token_is (parser, CPP_NAME))
{
@@ -9878,6 +10962,15 @@ c_parser_omp_atomic (location_t loc, c_parser *parser)
if (p)
c_parser_consume_token (parser);
}
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ {
+ const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+ if (!strcmp (p, "seq_cst"))
+ {
+ seq_cst = true;
+ c_parser_consume_token (parser);
+ }
+ }
c_parser_skip_to_pragma_eol (parser);
switch (code)
@@ -9931,7 +11024,11 @@ c_parser_omp_atomic (location_t loc, c_parser *parser)
/* For structured_block case we don't know yet whether
old or new x should be captured. */
restart:
- lhs = c_parser_unary_expression (parser).value;
+ eloc = c_parser_peek_token (parser)->location;
+ expr = c_parser_unary_expression (parser);
+ lhs = expr.value;
+ expr = default_function_array_conversion (eloc, expr);
+ unfolded_lhs = expr.value;
lhs = c_fully_fold (lhs, false, NULL);
orig_lhs = lhs;
switch (TREE_CODE (lhs))
@@ -9958,6 +11055,7 @@ restart:
/* FALLTHROUGH */
case PREINCREMENT_EXPR:
lhs = TREE_OPERAND (lhs, 0);
+ unfolded_lhs = NULL_TREE;
opcode = PLUS_EXPR;
rhs = integer_one_node;
break;
@@ -9968,6 +11066,7 @@ restart:
/* FALLTHROUGH */
case PREDECREMENT_EXPR:
lhs = TREE_OPERAND (lhs, 0);
+ unfolded_lhs = NULL_TREE;
opcode = MINUS_EXPR;
rhs = integer_one_node;
break;
@@ -9993,6 +11092,7 @@ restart:
/* This is pre or post increment. */
rhs = TREE_OPERAND (lhs, 1);
lhs = TREE_OPERAND (lhs, 0);
+ unfolded_lhs = NULL_TREE;
opcode = NOP_EXPR;
if (code == OMP_ATOMIC_CAPTURE_NEW
&& !structured_block
@@ -10007,6 +11107,7 @@ restart:
/* This is pre or post decrement. */
rhs = TREE_OPERAND (lhs, 1);
lhs = TREE_OPERAND (lhs, 0);
+ unfolded_lhs = NULL_TREE;
opcode = NOP_EXPR;
if (code == OMP_ATOMIC_CAPTURE_NEW
&& !structured_block
@@ -10047,87 +11148,67 @@ restart:
opcode = BIT_XOR_EXPR;
break;
case CPP_EQ:
- if (structured_block || code == OMP_ATOMIC)
+ c_parser_consume_token (parser);
+ eloc = c_parser_peek_token (parser)->location;
+ expr = c_parser_expr_no_commas (parser, NULL, unfolded_lhs);
+ rhs1 = expr.value;
+ switch (TREE_CODE (rhs1))
{
- location_t aloc = c_parser_peek_token (parser)->location;
- location_t rhs_loc;
- enum c_parser_prec oprec = PREC_NONE;
-
- c_parser_consume_token (parser);
- rhs1 = c_parser_unary_expression (parser).value;
- rhs1 = c_fully_fold (rhs1, false, NULL);
- if (rhs1 == error_mark_node)
- goto saw_error;
- switch (c_parser_peek_token (parser)->type)
+ case MULT_EXPR:
+ case TRUNC_DIV_EXPR:
+ case PLUS_EXPR:
+ case MINUS_EXPR:
+ case LSHIFT_EXPR:
+ case RSHIFT_EXPR:
+ case BIT_AND_EXPR:
+ case BIT_IOR_EXPR:
+ case BIT_XOR_EXPR:
+ if (c_tree_equal (TREE_OPERAND (rhs1, 0), unfolded_lhs))
{
- case CPP_SEMICOLON:
- if (code == OMP_ATOMIC_CAPTURE_NEW)
- {
- code = OMP_ATOMIC_CAPTURE_OLD;
- v = lhs;
- lhs = NULL_TREE;
- lhs1 = rhs1;
- rhs1 = NULL_TREE;
- c_parser_consume_token (parser);
- goto restart;
- }
- c_parser_error (parser,
- "invalid form of %<#pragma omp atomic%>");
- goto saw_error;
- case CPP_MULT:
- opcode = MULT_EXPR;
- oprec = PREC_MULT;
- break;
- case CPP_DIV:
- opcode = TRUNC_DIV_EXPR;
- oprec = PREC_MULT;
- break;
- case CPP_PLUS:
- opcode = PLUS_EXPR;
- oprec = PREC_ADD;
- break;
- case CPP_MINUS:
- opcode = MINUS_EXPR;
- oprec = PREC_ADD;
- break;
- case CPP_LSHIFT:
- opcode = LSHIFT_EXPR;
- oprec = PREC_SHIFT;
- break;
- case CPP_RSHIFT:
- opcode = RSHIFT_EXPR;
- oprec = PREC_SHIFT;
- break;
- case CPP_AND:
- opcode = BIT_AND_EXPR;
- oprec = PREC_BITAND;
- break;
- case CPP_OR:
- opcode = BIT_IOR_EXPR;
- oprec = PREC_BITOR;
- break;
- case CPP_XOR:
- opcode = BIT_XOR_EXPR;
- oprec = PREC_BITXOR;
- break;
- default:
- c_parser_error (parser,
- "invalid operator for %<#pragma omp atomic%>");
- goto saw_error;
+ opcode = TREE_CODE (rhs1);
+ rhs = c_fully_fold (TREE_OPERAND (rhs1, 1), false, NULL);
+ rhs1 = c_fully_fold (TREE_OPERAND (rhs1, 0), false, NULL);
+ goto stmt_done;
}
- loc = aloc;
- c_parser_consume_token (parser);
- rhs_loc = c_parser_peek_token (parser)->location;
- if (commutative_tree_code (opcode))
- oprec = (enum c_parser_prec) (oprec - 1);
- rhs_expr = c_parser_binary_expression (parser, NULL, oprec);
- rhs_expr = default_function_array_read_conversion (rhs_loc,
- rhs_expr);
- rhs = rhs_expr.value;
- rhs = c_fully_fold (rhs, false, NULL);
- goto stmt_done;
- }
- /* FALLTHROUGH */
+ if (c_tree_equal (TREE_OPERAND (rhs1, 1), unfolded_lhs))
+ {
+ opcode = TREE_CODE (rhs1);
+ rhs = c_fully_fold (TREE_OPERAND (rhs1, 0), false, NULL);
+ rhs1 = c_fully_fold (TREE_OPERAND (rhs1, 1), false, NULL);
+ swapped = !commutative_tree_code (opcode);
+ goto stmt_done;
+ }
+ break;
+ case ERROR_MARK:
+ goto saw_error;
+ default:
+ break;
+ }
+ if (c_parser_peek_token (parser)->type == CPP_SEMICOLON)
+ {
+ if (structured_block && code == OMP_ATOMIC_CAPTURE_NEW)
+ {
+ code = OMP_ATOMIC_CAPTURE_OLD;
+ v = lhs;
+ lhs = NULL_TREE;
+ expr = default_function_array_read_conversion (eloc, expr);
+ unfolded_lhs1 = expr.value;
+ lhs1 = c_fully_fold (unfolded_lhs1, false, NULL);
+ rhs1 = NULL_TREE;
+ c_parser_consume_token (parser);
+ goto restart;
+ }
+ if (structured_block)
+ {
+ opcode = NOP_EXPR;
+ expr = default_function_array_read_conversion (eloc, expr);
+ rhs = c_fully_fold (expr.value, false, NULL);
+ rhs1 = NULL_TREE;
+ goto stmt_done;
+ }
+ }
+ c_parser_error (parser, "invalid form of %<#pragma omp atomic%>");
+ goto saw_error;
default:
c_parser_error (parser,
"invalid operator for %<#pragma omp atomic%>");
@@ -10138,12 +11219,10 @@ restart:
c_finish_omp_atomic. */
loc = c_parser_peek_token (parser)->location;
c_parser_consume_token (parser);
- {
- location_t rhs_loc = c_parser_peek_token (parser)->location;
- rhs_expr = c_parser_expression (parser);
- rhs_expr = default_function_array_read_conversion (rhs_loc, rhs_expr);
- }
- rhs = rhs_expr.value;
+ eloc = c_parser_peek_token (parser)->location;
+ expr = c_parser_expression (parser);
+ expr = default_function_array_read_conversion (eloc, expr);
+ rhs = expr.value;
rhs = c_fully_fold (rhs, false, NULL);
break;
}
@@ -10158,7 +11237,11 @@ stmt_done:
goto saw_error;
if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
goto saw_error;
- lhs1 = c_parser_unary_expression (parser).value;
+ eloc = c_parser_peek_token (parser)->location;
+ expr = c_parser_unary_expression (parser);
+ lhs1 = expr.value;
+ expr = default_function_array_read_conversion (eloc, expr);
+ unfolded_lhs1 = expr.value;
lhs1 = c_fully_fold (lhs1, false, NULL);
if (lhs1 == error_mark_node)
goto saw_error;
@@ -10169,7 +11252,16 @@ stmt_done:
c_parser_require (parser, CPP_CLOSE_BRACE, "expected %<}%>");
}
done:
- stmt = c_finish_omp_atomic (loc, code, opcode, lhs, rhs, v, lhs1, rhs1);
+ if (unfolded_lhs && unfolded_lhs1
+ && !c_tree_equal (unfolded_lhs, unfolded_lhs1))
+ {
+ error ("%<#pragma omp atomic capture%> uses two different "
+ "expressions for memory");
+ stmt = error_mark_node;
+ }
+ else
+ stmt = c_finish_omp_atomic (loc, code, opcode, lhs, rhs, v, lhs1, rhs1,
+ swapped, seq_cst);
if (stmt != error_mark_node)
add_stmt (stmt);
@@ -10249,8 +11341,8 @@ c_parser_omp_flush (c_parser *parser)
LOC is the location of the OMP in "#pragma omp". */
static tree
-c_parser_omp_for_loop (location_t loc,
- c_parser *parser, tree clauses, tree *par_clauses)
+c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
+ tree clauses, tree *cclauses)
{
tree decl, cond, incr, save_break, save_cont, body, init, stmt, cl;
tree declv, condv, incrv, initv, ret = NULL;
@@ -10290,7 +11382,8 @@ c_parser_omp_for_loop (location_t loc,
{
if (i > 0)
vec_safe_push (for_block, c_begin_compound_stmt (true));
- c_parser_declaration_or_fndef (parser, true, true, true, true, true, NULL);
+ c_parser_declaration_or_fndef (parser, true, true, true, true, true,
+ NULL, vNULL);
decl = check_for_loop_decls (for_loc, flag_isoc99);
if (decl == NULL)
goto error_init;
@@ -10337,8 +11430,8 @@ c_parser_omp_for_loop (location_t loc,
if (c_parser_next_token_is_not (parser, CPP_SEMICOLON))
{
location_t cond_loc = c_parser_peek_token (parser)->location;
- struct c_expr cond_expr = c_parser_binary_expression (parser, NULL,
- PREC_NONE);
+ struct c_expr cond_expr
+ = c_parser_binary_expression (parser, NULL, NULL_TREE);
cond = cond_expr.value;
cond = c_objc_common_truthvalue_conversion (cond_loc, cond);
@@ -10477,13 +11570,15 @@ c_parser_omp_for_loop (location_t loc,
an error from the initialization parsing. */
if (!fail)
{
- stmt = c_finish_omp_for (loc, declv, initv, condv, incrv, body, NULL);
+ stmt = c_finish_omp_for (loc, code, declv, initv, condv,
+ incrv, body, NULL);
if (stmt)
{
- if (par_clauses != NULL)
+ if (cclauses != NULL
+ && cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] != NULL)
{
tree *c;
- for (c = par_clauses; *c ; )
+ for (c = &cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL]; *c ; )
if (OMP_CLAUSE_CODE (*c) != OMP_CLAUSE_FIRSTPRIVATE
&& OMP_CLAUSE_CODE (*c) != OMP_CLAUSE_LASTPRIVATE)
c = &OMP_CLAUSE_CHAIN (*c);
@@ -10532,33 +11627,135 @@ pop_scopes:
return ret;
}
+/* Helper function for OpenMP parsing, split clauses and call
+ finish_omp_clauses on each of the set of clauses afterwards. */
+
+static void
+omp_split_clauses (location_t loc, enum tree_code code,
+ omp_clause_mask mask, tree clauses, tree *cclauses)
+{
+ int i;
+ c_omp_split_clauses (loc, code, mask, clauses, cclauses);
+ for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++)
+ if (cclauses[i])
+ cclauses[i] = c_finish_omp_clauses (cclauses[i]);
+}
+
+/* OpenMP 4.0:
+ #pragma omp simd simd-clause[optseq] new-line
+ for-loop
+
+ LOC is the location of the #pragma token.
+*/
+
+#define OMP_SIMD_CLAUSE_MASK \
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SAFELEN) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALIGNED) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE))
+
+static tree
+c_parser_omp_simd (location_t loc, c_parser *parser,
+ char *p_name, omp_clause_mask mask, tree *cclauses)
+{
+ tree block, clauses, ret;
+
+ strcat (p_name, " simd");
+ mask |= OMP_SIMD_CLAUSE_MASK;
+ mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDERED);
+
+ clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
+ if (cclauses)
+ {
+ omp_split_clauses (loc, OMP_SIMD, mask, clauses, cclauses);
+ clauses = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
+ }
+
+ block = c_begin_compound_stmt (true);
+ ret = c_parser_omp_for_loop (loc, parser, OMP_SIMD, clauses, cclauses);
+ block = c_end_compound_stmt (loc, block, true);
+ add_stmt (block);
+
+ return ret;
+}
+
/* OpenMP 2.5:
#pragma omp for for-clause[optseq] new-line
for-loop
+ OpenMP 4.0:
+ #pragma omp for simd for-simd-clause[optseq] new-line
+ for-loop
+
LOC is the location of the #pragma token.
*/
-#define OMP_FOR_CLAUSE_MASK \
- ( (1u << PRAGMA_OMP_CLAUSE_PRIVATE) \
- | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
- | (1u << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
- | (1u << PRAGMA_OMP_CLAUSE_REDUCTION) \
- | (1u << PRAGMA_OMP_CLAUSE_ORDERED) \
- | (1u << PRAGMA_OMP_CLAUSE_SCHEDULE) \
- | (1u << PRAGMA_OMP_CLAUSE_COLLAPSE) \
- | (1u << PRAGMA_OMP_CLAUSE_NOWAIT))
+#define OMP_FOR_CLAUSE_MASK \
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDERED) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
static tree
-c_parser_omp_for (location_t loc, c_parser *parser)
+c_parser_omp_for (location_t loc, c_parser *parser,
+ char *p_name, omp_clause_mask mask, tree *cclauses)
{
tree block, clauses, ret;
- clauses = c_parser_omp_all_clauses (parser, OMP_FOR_CLAUSE_MASK,
- "#pragma omp for");
+ strcat (p_name, " for");
+ mask |= OMP_FOR_CLAUSE_MASK;
+ if (cclauses)
+ mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT);
+
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ {
+ const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+
+ if (strcmp (p, "simd") == 0)
+ {
+ tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
+ if (cclauses == NULL)
+ cclauses = cclauses_buf;
+
+ c_parser_consume_token (parser);
+ if (!flag_openmp) /* flag_openmp_simd */
+ return c_parser_omp_simd (loc, parser, p_name, mask, cclauses);
+ block = c_begin_compound_stmt (true);
+ ret = c_parser_omp_simd (loc, parser, p_name, mask, cclauses);
+ block = c_end_compound_stmt (loc, block, true);
+ if (ret == NULL_TREE)
+ return ret;
+ ret = make_node (OMP_FOR);
+ TREE_TYPE (ret) = void_type_node;
+ OMP_FOR_BODY (ret) = block;
+ OMP_FOR_CLAUSES (ret) = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
+ SET_EXPR_LOCATION (ret, loc);
+ add_stmt (ret);
+ return ret;
+ }
+ }
+ if (!flag_openmp) /* flag_openmp_simd */
+ {
+ c_parser_skip_to_pragma_eol (parser);
+ return NULL_TREE;
+ }
+
+ clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
+ if (cclauses)
+ {
+ omp_split_clauses (loc, OMP_FOR, mask, clauses, cclauses);
+ clauses = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
+ }
block = c_begin_compound_stmt (true);
- ret = c_parser_omp_for_loop (loc, parser, clauses, NULL);
+ ret = c_parser_omp_for_loop (loc, parser, OMP_FOR, clauses, cclauses);
block = c_end_compound_stmt (loc, block, true);
add_stmt (block);
@@ -10623,21 +11820,7 @@ c_parser_omp_sections_scope (location_t sections_loc, c_parser *parser)
if (c_parser_peek_token (parser)->pragma_kind != PRAGMA_OMP_SECTION)
{
- substmt = push_stmt_list ();
-
- while (1)
- {
- c_parser_statement (parser);
-
- if (c_parser_peek_token (parser)->pragma_kind == PRAGMA_OMP_SECTION)
- break;
- if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
- break;
- if (c_parser_next_token_is (parser, CPP_EOF))
- break;
- }
-
- substmt = pop_stmt_list (substmt);
+ substmt = c_parser_omp_structured_block (parser);
substmt = build1 (OMP_SECTION, void_type_node, substmt);
SET_EXPR_LOCATION (substmt, loc);
add_stmt (substmt);
@@ -10688,20 +11871,30 @@ c_parser_omp_sections_scope (location_t sections_loc, c_parser *parser)
LOC is the location of the #pragma token.
*/
-#define OMP_SECTIONS_CLAUSE_MASK \
- ( (1u << PRAGMA_OMP_CLAUSE_PRIVATE) \
- | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
- | (1u << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
- | (1u << PRAGMA_OMP_CLAUSE_REDUCTION) \
- | (1u << PRAGMA_OMP_CLAUSE_NOWAIT))
+#define OMP_SECTIONS_CLAUSE_MASK \
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
static tree
-c_parser_omp_sections (location_t loc, c_parser *parser)
+c_parser_omp_sections (location_t loc, c_parser *parser,
+ char *p_name, omp_clause_mask mask, tree *cclauses)
{
tree block, clauses, ret;
- clauses = c_parser_omp_all_clauses (parser, OMP_SECTIONS_CLAUSE_MASK,
- "#pragma omp sections");
+ strcat (p_name, " sections");
+ mask |= OMP_SECTIONS_CLAUSE_MASK;
+ if (cclauses)
+ mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT);
+
+ clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
+ if (cclauses)
+ {
+ omp_split_clauses (loc, OMP_SECTIONS, mask, clauses, cclauses);
+ clauses = cclauses[C_OMP_CLAUSE_SPLIT_SECTIONS];
+ }
block = c_begin_compound_stmt (true);
ret = c_parser_omp_sections_scope (loc, parser);
@@ -10721,76 +11914,79 @@ c_parser_omp_sections (location_t loc, c_parser *parser)
LOC is the location of the #pragma token.
*/
-#define OMP_PARALLEL_CLAUSE_MASK \
- ( (1u << PRAGMA_OMP_CLAUSE_IF) \
- | (1u << PRAGMA_OMP_CLAUSE_PRIVATE) \
- | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
- | (1u << PRAGMA_OMP_CLAUSE_DEFAULT) \
- | (1u << PRAGMA_OMP_CLAUSE_SHARED) \
- | (1u << PRAGMA_OMP_CLAUSE_COPYIN) \
- | (1u << PRAGMA_OMP_CLAUSE_REDUCTION) \
- | (1u << PRAGMA_OMP_CLAUSE_NUM_THREADS))
+#define OMP_PARALLEL_CLAUSE_MASK \
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COPYIN) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PROC_BIND))
static tree
-c_parser_omp_parallel (location_t loc, c_parser *parser)
+c_parser_omp_parallel (location_t loc, c_parser *parser,
+ char *p_name, omp_clause_mask mask, tree *cclauses)
{
- enum pragma_kind p_kind = PRAGMA_OMP_PARALLEL;
- const char *p_name = "#pragma omp parallel";
- tree stmt, clauses, par_clause, ws_clause, block;
- unsigned int mask = OMP_PARALLEL_CLAUSE_MASK;
+ tree stmt, clauses, block;
+
+ strcat (p_name, " parallel");
+ mask |= OMP_PARALLEL_CLAUSE_MASK;
if (c_parser_next_token_is_keyword (parser, RID_FOR))
{
+ tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
+ if (cclauses == NULL)
+ cclauses = cclauses_buf;
+
c_parser_consume_token (parser);
- p_kind = PRAGMA_OMP_PARALLEL_FOR;
- p_name = "#pragma omp parallel for";
- mask |= OMP_FOR_CLAUSE_MASK;
- mask &= ~(1u << PRAGMA_OMP_CLAUSE_NOWAIT);
+ if (!flag_openmp) /* flag_openmp_simd */
+ return c_parser_omp_for (loc, parser, p_name, mask, cclauses);
+ block = c_begin_omp_parallel ();
+ c_parser_omp_for (loc, parser, p_name, mask, cclauses);
+ stmt
+ = c_finish_omp_parallel (loc, cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
+ block);
+ OMP_PARALLEL_COMBINED (stmt) = 1;
+ return stmt;
+ }
+ else if (cclauses)
+ {
+ error_at (loc, "expected %<for%> after %qs", p_name);
+ c_parser_skip_to_pragma_eol (parser);
+ return NULL_TREE;
+ }
+ else if (!flag_openmp) /* flag_openmp_simd */
+ {
+ c_parser_skip_to_pragma_eol (parser);
+ return NULL_TREE;
}
else if (c_parser_next_token_is (parser, CPP_NAME))
{
const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
if (strcmp (p, "sections") == 0)
{
+ tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
+ if (cclauses == NULL)
+ cclauses = cclauses_buf;
+
c_parser_consume_token (parser);
- p_kind = PRAGMA_OMP_PARALLEL_SECTIONS;
- p_name = "#pragma omp parallel sections";
- mask |= OMP_SECTIONS_CLAUSE_MASK;
- mask &= ~(1u << PRAGMA_OMP_CLAUSE_NOWAIT);
+ block = c_begin_omp_parallel ();
+ c_parser_omp_sections (loc, parser, p_name, mask, cclauses);
+ stmt = c_finish_omp_parallel (loc,
+ cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
+ block);
+ OMP_PARALLEL_COMBINED (stmt) = 1;
+ return stmt;
}
}
- clauses = c_parser_omp_all_clauses (parser, mask, p_name);
+ clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
- switch (p_kind)
- {
- case PRAGMA_OMP_PARALLEL:
- block = c_begin_omp_parallel ();
- c_parser_statement (parser);
- stmt = c_finish_omp_parallel (loc, clauses, block);
- break;
-
- case PRAGMA_OMP_PARALLEL_FOR:
- block = c_begin_omp_parallel ();
- c_split_parallel_clauses (loc, clauses, &par_clause, &ws_clause);
- c_parser_omp_for_loop (loc, parser, ws_clause, &par_clause);
- stmt = c_finish_omp_parallel (loc, par_clause, block);
- OMP_PARALLEL_COMBINED (stmt) = 1;
- break;
-
- case PRAGMA_OMP_PARALLEL_SECTIONS:
- block = c_begin_omp_parallel ();
- c_split_parallel_clauses (loc, clauses, &par_clause, &ws_clause);
- stmt = c_parser_omp_sections_scope (loc, parser);
- if (stmt)
- OMP_SECTIONS_CLAUSES (stmt) = ws_clause;
- stmt = c_finish_omp_parallel (loc, par_clause, block);
- OMP_PARALLEL_COMBINED (stmt) = 1;
- break;
-
- default:
- gcc_unreachable ();
- }
+ block = c_begin_omp_parallel ();
+ c_parser_statement (parser);
+ stmt = c_finish_omp_parallel (loc, clauses, block);
return stmt;
}
@@ -10802,11 +11998,11 @@ c_parser_omp_parallel (location_t loc, c_parser *parser)
LOC is the location of the #pragma.
*/
-#define OMP_SINGLE_CLAUSE_MASK \
- ( (1u << PRAGMA_OMP_CLAUSE_PRIVATE) \
- | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
- | (1u << PRAGMA_OMP_CLAUSE_COPYPRIVATE) \
- | (1u << PRAGMA_OMP_CLAUSE_NOWAIT))
+#define OMP_SINGLE_CLAUSE_MASK \
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COPYPRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
static tree
c_parser_omp_single (location_t loc, c_parser *parser)
@@ -10829,15 +12025,16 @@ c_parser_omp_single (location_t loc, c_parser *parser)
LOC is the location of the #pragma.
*/
-#define OMP_TASK_CLAUSE_MASK \
- ( (1u << PRAGMA_OMP_CLAUSE_IF) \
- | (1u << PRAGMA_OMP_CLAUSE_UNTIED) \
- | (1u << PRAGMA_OMP_CLAUSE_DEFAULT) \
- | (1u << PRAGMA_OMP_CLAUSE_PRIVATE) \
- | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
- | (1u << PRAGMA_OMP_CLAUSE_SHARED) \
- | (1u << PRAGMA_OMP_CLAUSE_FINAL) \
- | (1u << PRAGMA_OMP_CLAUSE_MERGEABLE))
+#define OMP_TASK_CLAUSE_MASK \
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNTIED) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FINAL) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MERGEABLE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND))
static tree
c_parser_omp_task (location_t loc, c_parser *parser)
@@ -10880,6 +12077,1016 @@ c_parser_omp_taskyield (c_parser *parser)
c_finish_omp_taskyield (loc);
}
+/* OpenMP 4.0:
+ # pragma omp taskgroup new-line
+*/
+
+static tree
+c_parser_omp_taskgroup (c_parser *parser)
+{
+ location_t loc = c_parser_peek_token (parser)->location;
+ c_parser_skip_to_pragma_eol (parser);
+ return c_finish_omp_taskgroup (loc, c_parser_omp_structured_block (parser));
+}
+
+/* OpenMP 4.0:
+ # pragma omp cancel cancel-clause[optseq] new-line
+
+ LOC is the location of the #pragma.
+*/
+
+#define OMP_CANCEL_CLAUSE_MASK \
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PARALLEL) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FOR) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SECTIONS) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASKGROUP) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF))
+
+static void
+c_parser_omp_cancel (c_parser *parser)
+{
+ location_t loc = c_parser_peek_token (parser)->location;
+
+ c_parser_consume_pragma (parser);
+ tree clauses = c_parser_omp_all_clauses (parser, OMP_CANCEL_CLAUSE_MASK,
+ "#pragma omp cancel");
+
+ c_finish_omp_cancel (loc, clauses);
+}
+
+/* OpenMP 4.0:
+ # pragma omp cancellation point cancelpt-clause[optseq] new-line
+
+ LOC is the location of the #pragma.
+*/
+
+#define OMP_CANCELLATION_POINT_CLAUSE_MASK \
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PARALLEL) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FOR) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SECTIONS) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASKGROUP))
+
+static void
+c_parser_omp_cancellation_point (c_parser *parser)
+{
+ location_t loc = c_parser_peek_token (parser)->location;
+ tree clauses;
+ bool point_seen = false;
+
+ c_parser_consume_pragma (parser);
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ {
+ const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+ if (strcmp (p, "point") == 0)
+ {
+ c_parser_consume_token (parser);
+ point_seen = true;
+ }
+ }
+ if (!point_seen)
+ {
+ c_parser_error (parser, "expected %<point%>");
+ c_parser_skip_to_pragma_eol (parser);
+ return;
+ }
+
+ clauses
+ = c_parser_omp_all_clauses (parser, OMP_CANCELLATION_POINT_CLAUSE_MASK,
+ "#pragma omp cancellation point");
+
+ c_finish_omp_cancellation_point (loc, clauses);
+}
+
+/* OpenMP 4.0:
+ #pragma omp distribute distribute-clause[optseq] new-line
+ for-loop */
+
+#define OMP_DISTRIBUTE_CLAUSE_MASK \
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)\
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE))
+
+static tree
+c_parser_omp_distribute (location_t loc, c_parser *parser,
+ char *p_name, omp_clause_mask mask, tree *cclauses)
+{
+ tree clauses, block, ret;
+
+ strcat (p_name, " distribute");
+ mask |= OMP_DISTRIBUTE_CLAUSE_MASK;
+
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ {
+ const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+ bool simd = false;
+ bool parallel = false;
+
+ if (strcmp (p, "simd") == 0)
+ simd = true;
+ else
+ parallel = strcmp (p, "parallel") == 0;
+ if (parallel || simd)
+ {
+ tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
+ if (cclauses == NULL)
+ cclauses = cclauses_buf;
+ c_parser_consume_token (parser);
+ if (!flag_openmp) /* flag_openmp_simd */
+ {
+ if (simd)
+ return c_parser_omp_simd (loc, parser, p_name, mask, cclauses);
+ else
+ return c_parser_omp_parallel (loc, parser, p_name, mask,
+ cclauses);
+ }
+ block = c_begin_compound_stmt (true);
+ if (simd)
+ ret = c_parser_omp_simd (loc, parser, p_name, mask, cclauses);
+ else
+ ret = c_parser_omp_parallel (loc, parser, p_name, mask, cclauses);
+ block = c_end_compound_stmt (loc, block, true);
+ if (ret == NULL)
+ return ret;
+ ret = make_node (OMP_DISTRIBUTE);
+ TREE_TYPE (ret) = void_type_node;
+ OMP_FOR_BODY (ret) = block;
+ OMP_FOR_CLAUSES (ret) = cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE];
+ SET_EXPR_LOCATION (ret, loc);
+ add_stmt (ret);
+ return ret;
+ }
+ }
+ if (!flag_openmp) /* flag_openmp_simd */
+ {
+ c_parser_skip_to_pragma_eol (parser);
+ return NULL_TREE;
+ }
+
+ clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
+ if (cclauses)
+ {
+ omp_split_clauses (loc, OMP_DISTRIBUTE, mask, clauses, cclauses);
+ clauses = cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE];
+ }
+
+ block = c_begin_compound_stmt (true);
+ ret = c_parser_omp_for_loop (loc, parser, OMP_DISTRIBUTE, clauses, NULL);
+ block = c_end_compound_stmt (loc, block, true);
+ add_stmt (block);
+
+ return ret;
+}
+
+/* OpenMP 4.0:
+ # pragma omp teams teams-clause[optseq] new-line
+ structured-block */
+
+#define OMP_TEAMS_CLAUSE_MASK \
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_THREAD_LIMIT) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT))
+
+static tree
+c_parser_omp_teams (location_t loc, c_parser *parser,
+ char *p_name, omp_clause_mask mask, tree *cclauses)
+{
+ tree clauses, block, ret;
+
+ strcat (p_name, " teams");
+ mask |= OMP_TEAMS_CLAUSE_MASK;
+
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ {
+ const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+ if (strcmp (p, "distribute") == 0)
+ {
+ tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
+ if (cclauses == NULL)
+ cclauses = cclauses_buf;
+
+ c_parser_consume_token (parser);
+ if (!flag_openmp) /* flag_openmp_simd */
+ return c_parser_omp_distribute (loc, parser, p_name, mask, cclauses);
+ block = c_begin_compound_stmt (true);
+ ret = c_parser_omp_distribute (loc, parser, p_name, mask, cclauses);
+ block = c_end_compound_stmt (loc, block, true);
+ if (ret == NULL)
+ return ret;
+ clauses = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
+ ret = make_node (OMP_TEAMS);
+ TREE_TYPE (ret) = void_type_node;
+ OMP_TEAMS_CLAUSES (ret) = clauses;
+ OMP_TEAMS_BODY (ret) = block;
+ return add_stmt (ret);
+ }
+ }
+ if (!flag_openmp) /* flag_openmp_simd */
+ {
+ c_parser_skip_to_pragma_eol (parser);
+ return NULL_TREE;
+ }
+
+ clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
+ if (cclauses)
+ {
+ omp_split_clauses (loc, OMP_TEAMS, mask, clauses, cclauses);
+ clauses = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
+ }
+
+ tree stmt = make_node (OMP_TEAMS);
+ TREE_TYPE (stmt) = void_type_node;
+ OMP_TEAMS_CLAUSES (stmt) = clauses;
+ OMP_TEAMS_BODY (stmt) = c_parser_omp_structured_block (parser);
+
+ return add_stmt (stmt);
+}
+
+/* OpenMP 4.0:
+ # pragma omp target data target-data-clause[optseq] new-line
+ structured-block */
+
+#define OMP_TARGET_DATA_CLAUSE_MASK \
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF))
+
+static tree
+c_parser_omp_target_data (location_t loc, c_parser *parser)
+{
+ tree stmt = make_node (OMP_TARGET_DATA);
+ TREE_TYPE (stmt) = void_type_node;
+
+ OMP_TARGET_DATA_CLAUSES (stmt)
+ = c_parser_omp_all_clauses (parser, OMP_TARGET_DATA_CLAUSE_MASK,
+ "#pragma omp target data");
+ keep_next_level ();
+ tree block = c_begin_compound_stmt (true);
+ add_stmt (c_parser_omp_structured_block (parser));
+ OMP_TARGET_DATA_BODY (stmt) = c_end_compound_stmt (loc, block, true);
+
+ SET_EXPR_LOCATION (stmt, loc);
+ return add_stmt (stmt);
+}
+
+/* OpenMP 4.0:
+ # pragma omp target update target-update-clause[optseq] new-line */
+
+#define OMP_TARGET_UPDATE_CLAUSE_MASK \
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FROM) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TO) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF))
+
+static bool
+c_parser_omp_target_update (location_t loc, c_parser *parser,
+ enum pragma_context context)
+{
+ if (context == pragma_stmt)
+ {
+ error_at (loc,
+ "%<#pragma omp target update%> may only be "
+ "used in compound statements");
+ c_parser_skip_to_pragma_eol (parser);
+ return false;
+ }
+
+ tree clauses
+ = c_parser_omp_all_clauses (parser, OMP_TARGET_UPDATE_CLAUSE_MASK,
+ "#pragma omp target update");
+ if (find_omp_clause (clauses, OMP_CLAUSE_TO) == NULL_TREE
+ && find_omp_clause (clauses, OMP_CLAUSE_FROM) == NULL_TREE)
+ {
+ error_at (loc,
+ "%<#pragma omp target update must contain at least one "
+ "%<from%> or %<to%> clauses");
+ return false;
+ }
+
+ tree stmt = make_node (OMP_TARGET_UPDATE);
+ TREE_TYPE (stmt) = void_type_node;
+ OMP_TARGET_UPDATE_CLAUSES (stmt) = clauses;
+ SET_EXPR_LOCATION (stmt, loc);
+ add_stmt (stmt);
+ return false;
+}
+
+/* OpenMP 4.0:
+ # pragma omp target target-clause[optseq] new-line
+ structured-block */
+
+#define OMP_TARGET_CLAUSE_MASK \
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF))
+
+static bool
+c_parser_omp_target (c_parser *parser, enum pragma_context context)
+{
+ location_t loc = c_parser_peek_token (parser)->location;
+ c_parser_consume_pragma (parser);
+
+ if (context != pragma_stmt && context != pragma_compound)
+ {
+ c_parser_error (parser, "expected declaration specifiers");
+ c_parser_skip_to_pragma_eol (parser);
+ return false;
+ }
+
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ {
+ const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+
+ if (strcmp (p, "teams") == 0)
+ {
+ tree cclauses[C_OMP_CLAUSE_SPLIT_COUNT];
+ char p_name[sizeof ("#pragma omp target teams distribute "
+ "parallel for simd")];
+
+ c_parser_consume_token (parser);
+ if (!flag_openmp) /* flag_openmp_simd */
+ return c_parser_omp_teams (loc, parser, p_name,
+ OMP_TARGET_CLAUSE_MASK, cclauses);
+ strcpy (p_name, "#pragma omp target");
+ keep_next_level ();
+ tree block = c_begin_compound_stmt (true);
+ tree ret = c_parser_omp_teams (loc, parser, p_name,
+ OMP_TARGET_CLAUSE_MASK, cclauses);
+ block = c_end_compound_stmt (loc, block, true);
+ if (ret == NULL)
+ return ret;
+ tree stmt = make_node (OMP_TARGET);
+ TREE_TYPE (stmt) = void_type_node;
+ OMP_TARGET_CLAUSES (stmt) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
+ OMP_TARGET_BODY (stmt) = block;
+ add_stmt (stmt);
+ return true;
+ }
+ else if (!flag_openmp) /* flag_openmp_simd */
+ {
+ c_parser_skip_to_pragma_eol (parser);
+ return NULL_TREE;
+ }
+ else if (strcmp (p, "data") == 0)
+ {
+ c_parser_consume_token (parser);
+ c_parser_omp_target_data (loc, parser);
+ return true;
+ }
+ else if (strcmp (p, "update") == 0)
+ {
+ c_parser_consume_token (parser);
+ return c_parser_omp_target_update (loc, parser, context);
+ }
+ }
+
+ tree stmt = make_node (OMP_TARGET);
+ TREE_TYPE (stmt) = void_type_node;
+
+ OMP_TARGET_CLAUSES (stmt)
+ = c_parser_omp_all_clauses (parser, OMP_TARGET_CLAUSE_MASK,
+ "#pragma omp target");
+ keep_next_level ();
+ tree block = c_begin_compound_stmt (true);
+ add_stmt (c_parser_omp_structured_block (parser));
+ OMP_TARGET_BODY (stmt) = c_end_compound_stmt (loc, block, true);
+
+ SET_EXPR_LOCATION (stmt, loc);
+ add_stmt (stmt);
+ return true;
+}
+
+/* OpenMP 4.0:
+ # pragma omp declare simd declare-simd-clauses[optseq] new-line */
+
+#define OMP_DECLARE_SIMD_CLAUSE_MASK \
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SIMDLEN) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALIGNED) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNIFORM) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_INBRANCH) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOTINBRANCH))
+
+static void
+c_parser_omp_declare_simd (c_parser *parser, enum pragma_context context)
+{
+ vec<c_token> clauses = vNULL;
+ while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
+ {
+ c_token *token = c_parser_peek_token (parser);
+ if (token->type == CPP_EOF)
+ {
+ c_parser_skip_to_pragma_eol (parser);
+ clauses.release ();
+ return;
+ }
+ clauses.safe_push (*token);
+ c_parser_consume_token (parser);
+ }
+ clauses.safe_push (*c_parser_peek_token (parser));
+ c_parser_skip_to_pragma_eol (parser);
+
+ while (c_parser_next_token_is (parser, CPP_PRAGMA))
+ {
+ if (c_parser_peek_token (parser)->pragma_kind
+ != PRAGMA_OMP_DECLARE_REDUCTION
+ || c_parser_peek_2nd_token (parser)->type != CPP_NAME
+ || strcmp (IDENTIFIER_POINTER
+ (c_parser_peek_2nd_token (parser)->value),
+ "simd") != 0)
+ {
+ c_parser_error (parser,
+ "%<#pragma omp declare simd%> must be followed by "
+ "function declaration or definition or another "
+ "%<#pragma omp declare simd%>");
+ clauses.release ();
+ return;
+ }
+ c_parser_consume_pragma (parser);
+ while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
+ {
+ c_token *token = c_parser_peek_token (parser);
+ if (token->type == CPP_EOF)
+ {
+ c_parser_skip_to_pragma_eol (parser);
+ clauses.release ();
+ return;
+ }
+ clauses.safe_push (*token);
+ c_parser_consume_token (parser);
+ }
+ clauses.safe_push (*c_parser_peek_token (parser));
+ c_parser_skip_to_pragma_eol (parser);
+ }
+
+ /* Make sure nothing tries to read past the end of the tokens. */
+ c_token eof_token;
+ memset (&eof_token, 0, sizeof (eof_token));
+ eof_token.type = CPP_EOF;
+ clauses.safe_push (eof_token);
+ clauses.safe_push (eof_token);
+
+ switch (context)
+ {
+ case pragma_external:
+ if (c_parser_next_token_is (parser, CPP_KEYWORD)
+ && c_parser_peek_token (parser)->keyword == RID_EXTENSION)
+ {
+ int ext = disable_extension_diagnostics ();
+ do
+ c_parser_consume_token (parser);
+ while (c_parser_next_token_is (parser, CPP_KEYWORD)
+ && c_parser_peek_token (parser)->keyword == RID_EXTENSION);
+ c_parser_declaration_or_fndef (parser, true, true, true, false, true,
+ NULL, clauses);
+ restore_extension_diagnostics (ext);
+ }
+ else
+ c_parser_declaration_or_fndef (parser, true, true, true, false, true,
+ NULL, clauses);
+ break;
+ case pragma_struct:
+ case pragma_param:
+ c_parser_error (parser, "%<#pragma omp declare simd%> must be followed by "
+ "function declaration or definition");
+ break;
+ case pragma_compound:
+ case pragma_stmt:
+ if (c_parser_next_token_is (parser, CPP_KEYWORD)
+ && c_parser_peek_token (parser)->keyword == RID_EXTENSION)
+ {
+ int ext = disable_extension_diagnostics ();
+ do
+ c_parser_consume_token (parser);
+ while (c_parser_next_token_is (parser, CPP_KEYWORD)
+ && c_parser_peek_token (parser)->keyword == RID_EXTENSION);
+ if (c_parser_next_tokens_start_declaration (parser))
+ {
+ c_parser_declaration_or_fndef (parser, true, true, true, true,
+ true, NULL, clauses);
+ restore_extension_diagnostics (ext);
+ break;
+ }
+ restore_extension_diagnostics (ext);
+ }
+ else if (c_parser_next_tokens_start_declaration (parser))
+ {
+ c_parser_declaration_or_fndef (parser, true, true, true, true, true,
+ NULL, clauses);
+ break;
+ }
+ c_parser_error (parser, "%<#pragma omp declare simd%> must be followed by "
+ "function declaration or definition");
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ clauses.release ();
+}
+
+/* Finalize #pragma omp declare simd clauses after FNDECL has been parsed,
+ and put that into "omp declare simd" attribute. */
+
+static void
+c_finish_omp_declare_simd (c_parser *parser, tree fndecl, tree parms,
+ vec<c_token> clauses)
+{
+ /* Normally first token is CPP_NAME "simd". CPP_EOF there indicates
+ error has been reported and CPP_PRAGMA that c_finish_omp_declare_simd
+ has already processed the tokens. */
+ if (clauses[0].type == CPP_EOF)
+ return;
+ if (fndecl == NULL_TREE || TREE_CODE (fndecl) != FUNCTION_DECL)
+ {
+ error ("%<#pragma omp declare simd%> not immediately followed by "
+ "a function declaration or definition");
+ clauses[0].type = CPP_EOF;
+ return;
+ }
+ if (clauses[0].type != CPP_NAME)
+ {
+ error_at (DECL_SOURCE_LOCATION (fndecl),
+ "%<#pragma omp declare simd%> not immediately followed by "
+ "a single function declaration or definition");
+ clauses[0].type = CPP_EOF;
+ return;
+ }
+
+ if (parms == NULL_TREE)
+ parms = DECL_ARGUMENTS (fndecl);
+
+ unsigned int tokens_avail = parser->tokens_avail;
+ gcc_assert (parser->tokens == &parser->tokens_buf[0]);
+ parser->tokens = clauses.address ();
+ parser->tokens_avail = clauses.length ();
+
+ /* c_parser_omp_declare_simd pushed 2 extra CPP_EOF tokens at the end. */
+ while (parser->tokens_avail > 3)
+ {
+ c_token *token = c_parser_peek_token (parser);
+ gcc_assert (token->type == CPP_NAME
+ && strcmp (IDENTIFIER_POINTER (token->value), "simd") == 0);
+ c_parser_consume_token (parser);
+ parser->in_pragma = true;
+
+ tree c = c_parser_omp_all_clauses (parser, OMP_DECLARE_SIMD_CLAUSE_MASK,
+ "#pragma omp declare simd");
+ c = c_omp_declare_simd_clauses_to_numbers (parms, c);
+ if (c != NULL_TREE)
+ c = tree_cons (NULL_TREE, c, NULL_TREE);
+ c = build_tree_list (get_identifier ("omp declare simd"), c);
+ TREE_CHAIN (c) = DECL_ATTRIBUTES (fndecl);
+ DECL_ATTRIBUTES (fndecl) = c;
+ }
+
+ parser->tokens = &parser->tokens_buf[0];
+ parser->tokens_avail = tokens_avail;
+ clauses[0].type = CPP_PRAGMA;
+}
+
+
+/* OpenMP 4.0:
+ # pragma omp declare target new-line
+ declarations and definitions
+ # pragma omp end declare target new-line */
+
+static void
+c_parser_omp_declare_target (c_parser *parser)
+{
+ c_parser_skip_to_pragma_eol (parser);
+ current_omp_declare_target_attribute++;
+}
+
+static void
+c_parser_omp_end_declare_target (c_parser *parser)
+{
+ location_t loc = c_parser_peek_token (parser)->location;
+ c_parser_consume_pragma (parser);
+ if (c_parser_next_token_is (parser, CPP_NAME)
+ && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value),
+ "declare") == 0)
+ {
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is (parser, CPP_NAME)
+ && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value),
+ "target") == 0)
+ c_parser_consume_token (parser);
+ else
+ {
+ c_parser_error (parser, "expected %<target%>");
+ c_parser_skip_to_pragma_eol (parser);
+ return;
+ }
+ }
+ else
+ {
+ c_parser_error (parser, "expected %<declare%>");
+ c_parser_skip_to_pragma_eol (parser);
+ return;
+ }
+ c_parser_skip_to_pragma_eol (parser);
+ if (!current_omp_declare_target_attribute)
+ error_at (loc, "%<#pragma omp end declare target%> without corresponding "
+ "%<#pragma omp declare target%>");
+ else
+ current_omp_declare_target_attribute--;
+}
+
+
+/* OpenMP 4.0
+ #pragma omp declare reduction (reduction-id : typename-list : expression) \
+ initializer-clause[opt] new-line
+
+ initializer-clause:
+ initializer (omp_priv = initializer)
+ initializer (function-name (argument-list)) */
+
+static void
+c_parser_omp_declare_reduction (c_parser *parser, enum pragma_context context)
+{
+ unsigned int tokens_avail = 0, i;
+ vec<tree> types = vNULL;
+ vec<c_token> clauses = vNULL;
+ enum tree_code reduc_code = ERROR_MARK;
+ tree reduc_id = NULL_TREE;
+ tree type;
+ location_t rloc = c_parser_peek_token (parser)->location;
+
+ if (context == pragma_struct || context == pragma_param)
+ {
+ error ("%<#pragma omp declare reduction%> not at file or block scope");
+ goto fail;
+ }
+
+ if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ goto fail;
+
+ switch (c_parser_peek_token (parser)->type)
+ {
+ case CPP_PLUS:
+ reduc_code = PLUS_EXPR;
+ break;
+ case CPP_MULT:
+ reduc_code = MULT_EXPR;
+ break;
+ case CPP_MINUS:
+ reduc_code = MINUS_EXPR;
+ break;
+ case CPP_AND:
+ reduc_code = BIT_AND_EXPR;
+ break;
+ case CPP_XOR:
+ reduc_code = BIT_XOR_EXPR;
+ break;
+ case CPP_OR:
+ reduc_code = BIT_IOR_EXPR;
+ break;
+ case CPP_AND_AND:
+ reduc_code = TRUTH_ANDIF_EXPR;
+ break;
+ case CPP_OR_OR:
+ reduc_code = TRUTH_ORIF_EXPR;
+ break;
+ case CPP_NAME:
+ const char *p;
+ p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+ if (strcmp (p, "min") == 0)
+ {
+ reduc_code = MIN_EXPR;
+ break;
+ }
+ if (strcmp (p, "max") == 0)
+ {
+ reduc_code = MAX_EXPR;
+ break;
+ }
+ reduc_id = c_parser_peek_token (parser)->value;
+ break;
+ default:
+ c_parser_error (parser,
+ "expected %<+%>, %<*%>, %<-%>, %<&%>, "
+ "%<^%>, %<|%>, %<&&%>, %<||%>, %<min%> or identifier");
+ goto fail;
+ }
+
+ tree orig_reduc_id, reduc_decl;
+ orig_reduc_id = reduc_id;
+ reduc_id = c_omp_reduction_id (reduc_code, reduc_id);
+ reduc_decl = c_omp_reduction_decl (reduc_id);
+ c_parser_consume_token (parser);
+
+ if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
+ goto fail;
+
+ while (true)
+ {
+ location_t loc = c_parser_peek_token (parser)->location;
+ struct c_type_name *ctype = c_parser_type_name (parser);
+ if (ctype != NULL)
+ {
+ type = groktypename (ctype, NULL, NULL);
+ if (type == error_mark_node)
+ ;
+ else if ((INTEGRAL_TYPE_P (type)
+ || TREE_CODE (type) == REAL_TYPE
+ || TREE_CODE (type) == COMPLEX_TYPE)
+ && orig_reduc_id == NULL_TREE)
+ error_at (loc, "predeclared arithmetic type in "
+ "%<#pragma omp declare reduction%>");
+ else if (TREE_CODE (type) == FUNCTION_TYPE
+ || TREE_CODE (type) == ARRAY_TYPE)
+ error_at (loc, "function or array type in "
+ "%<#pragma omp declare reduction%>");
+ else if (TYPE_QUALS_NO_ADDR_SPACE (type))
+ error_at (loc, "const, volatile or restrict qualified type in "
+ "%<#pragma omp declare reduction%>");
+ else
+ {
+ tree t;
+ for (t = DECL_INITIAL (reduc_decl); t; t = TREE_CHAIN (t))
+ if (comptypes (TREE_PURPOSE (t), type))
+ {
+ error_at (loc, "redeclaration of %qs "
+ "%<#pragma omp declare reduction%> for "
+ "type %qT",
+ IDENTIFIER_POINTER (reduc_id)
+ + sizeof ("omp declare reduction ") - 1,
+ type);
+ location_t ploc
+ = DECL_SOURCE_LOCATION (TREE_VEC_ELT (TREE_VALUE (t),
+ 0));
+ error_at (ploc, "previous %<#pragma omp declare "
+ "reduction%>");
+ break;
+ }
+ if (t == NULL_TREE)
+ types.safe_push (type);
+ }
+ if (c_parser_next_token_is (parser, CPP_COMMA))
+ c_parser_consume_token (parser);
+ else
+ break;
+ }
+ else
+ break;
+ }
+
+ if (!c_parser_require (parser, CPP_COLON, "expected %<:%>")
+ || types.is_empty ())
+ {
+ fail:
+ clauses.release ();
+ types.release ();
+ while (true)
+ {
+ c_token *token = c_parser_peek_token (parser);
+ if (token->type == CPP_EOF || token->type == CPP_PRAGMA_EOL)
+ break;
+ c_parser_consume_token (parser);
+ }
+ c_parser_skip_to_pragma_eol (parser);
+ return;
+ }
+
+ if (types.length () > 1)
+ {
+ while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
+ {
+ c_token *token = c_parser_peek_token (parser);
+ if (token->type == CPP_EOF)
+ goto fail;
+ clauses.safe_push (*token);
+ c_parser_consume_token (parser);
+ }
+ clauses.safe_push (*c_parser_peek_token (parser));
+ c_parser_skip_to_pragma_eol (parser);
+
+ /* Make sure nothing tries to read past the end of the tokens. */
+ c_token eof_token;
+ memset (&eof_token, 0, sizeof (eof_token));
+ eof_token.type = CPP_EOF;
+ clauses.safe_push (eof_token);
+ clauses.safe_push (eof_token);
+ }
+
+ int errs = errorcount;
+ FOR_EACH_VEC_ELT (types, i, type)
+ {
+ tokens_avail = parser->tokens_avail;
+ gcc_assert (parser->tokens == &parser->tokens_buf[0]);
+ if (!clauses.is_empty ())
+ {
+ parser->tokens = clauses.address ();
+ parser->tokens_avail = clauses.length ();
+ parser->in_pragma = true;
+ }
+
+ bool nested = current_function_decl != NULL_TREE;
+ if (nested)
+ c_push_function_context ();
+ tree fndecl = build_decl (BUILTINS_LOCATION, FUNCTION_DECL,
+ reduc_id, default_function_type);
+ current_function_decl = fndecl;
+ allocate_struct_function (fndecl, true);
+ push_scope ();
+ tree stmt = push_stmt_list ();
+ /* Intentionally BUILTINS_LOCATION, so that -Wshadow doesn't
+ warn about these. */
+ tree omp_out = build_decl (BUILTINS_LOCATION, VAR_DECL,
+ get_identifier ("omp_out"), type);
+ DECL_ARTIFICIAL (omp_out) = 1;
+ DECL_CONTEXT (omp_out) = fndecl;
+ pushdecl (omp_out);
+ tree omp_in = build_decl (BUILTINS_LOCATION, VAR_DECL,
+ get_identifier ("omp_in"), type);
+ DECL_ARTIFICIAL (omp_in) = 1;
+ DECL_CONTEXT (omp_in) = fndecl;
+ pushdecl (omp_in);
+ struct c_expr combiner = c_parser_expression (parser);
+ struct c_expr initializer;
+ tree omp_priv = NULL_TREE, omp_orig = NULL_TREE;
+ bool bad = false;
+ initializer.value = error_mark_node;
+ if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+ bad = true;
+ else if (c_parser_next_token_is (parser, CPP_NAME)
+ && strcmp (IDENTIFIER_POINTER
+ (c_parser_peek_token (parser)->value),
+ "initializer") == 0)
+ {
+ c_parser_consume_token (parser);
+ pop_scope ();
+ push_scope ();
+ omp_priv = build_decl (BUILTINS_LOCATION, VAR_DECL,
+ get_identifier ("omp_priv"), type);
+ DECL_ARTIFICIAL (omp_priv) = 1;
+ DECL_INITIAL (omp_priv) = error_mark_node;
+ DECL_CONTEXT (omp_priv) = fndecl;
+ pushdecl (omp_priv);
+ omp_orig = build_decl (BUILTINS_LOCATION, VAR_DECL,
+ get_identifier ("omp_orig"), type);
+ DECL_ARTIFICIAL (omp_orig) = 1;
+ DECL_CONTEXT (omp_orig) = fndecl;
+ pushdecl (omp_orig);
+ if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ bad = true;
+ else if (!c_parser_next_token_is (parser, CPP_NAME))
+ {
+ c_parser_error (parser, "expected %<omp_priv%> or "
+ "function-name");
+ bad = true;
+ }
+ else if (strcmp (IDENTIFIER_POINTER
+ (c_parser_peek_token (parser)->value),
+ "omp_priv") != 0)
+ {
+ if (c_parser_peek_2nd_token (parser)->type != CPP_OPEN_PAREN
+ || c_parser_peek_token (parser)->id_kind != C_ID_ID)
+ {
+ c_parser_error (parser, "expected function-name %<(%>");
+ bad = true;
+ }
+ else
+ initializer = c_parser_postfix_expression (parser);
+ if (initializer.value
+ && TREE_CODE (initializer.value) == CALL_EXPR)
+ {
+ int j;
+ tree c = initializer.value;
+ for (j = 0; j < call_expr_nargs (c); j++)
+ if (TREE_CODE (CALL_EXPR_ARG (c, j)) == ADDR_EXPR
+ && TREE_OPERAND (CALL_EXPR_ARG (c, j), 0) == omp_priv)
+ break;
+ if (j == call_expr_nargs (c))
+ error ("one of the initializer call arguments should be "
+ "%<&omp_priv%>");
+ }
+ }
+ else
+ {
+ c_parser_consume_token (parser);
+ if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
+ bad = true;
+ else
+ {
+ tree st = push_stmt_list ();
+ start_init (omp_priv, NULL_TREE, 0);
+ location_t loc = c_parser_peek_token (parser)->location;
+ struct c_expr init = c_parser_initializer (parser);
+ finish_init ();
+ finish_decl (omp_priv, loc, init.value,
+ init.original_type, NULL_TREE);
+ pop_stmt_list (st);
+ }
+ }
+ if (!bad
+ && !c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+ bad = true;
+ }
+
+ if (!bad)
+ {
+ c_parser_skip_to_pragma_eol (parser);
+
+ tree t = tree_cons (type, make_tree_vec (omp_priv ? 6 : 3),
+ DECL_INITIAL (reduc_decl));
+ DECL_INITIAL (reduc_decl) = t;
+ DECL_SOURCE_LOCATION (omp_out) = rloc;
+ TREE_VEC_ELT (TREE_VALUE (t), 0) = omp_out;
+ TREE_VEC_ELT (TREE_VALUE (t), 1) = omp_in;
+ TREE_VEC_ELT (TREE_VALUE (t), 2) = combiner.value;
+ walk_tree (&combiner.value, c_check_omp_declare_reduction_r,
+ &TREE_VEC_ELT (TREE_VALUE (t), 0), NULL);
+ if (omp_priv)
+ {
+ DECL_SOURCE_LOCATION (omp_priv) = rloc;
+ TREE_VEC_ELT (TREE_VALUE (t), 3) = omp_priv;
+ TREE_VEC_ELT (TREE_VALUE (t), 4) = omp_orig;
+ TREE_VEC_ELT (TREE_VALUE (t), 5) = initializer.value;
+ walk_tree (&initializer.value, c_check_omp_declare_reduction_r,
+ &TREE_VEC_ELT (TREE_VALUE (t), 3), NULL);
+ walk_tree (&DECL_INITIAL (omp_priv),
+ c_check_omp_declare_reduction_r,
+ &TREE_VEC_ELT (TREE_VALUE (t), 3), NULL);
+ }
+ }
+
+ pop_stmt_list (stmt);
+ pop_scope ();
+ if (cfun->language != NULL)
+ {
+ ggc_free (cfun->language);
+ cfun->language = NULL;
+ }
+ set_cfun (NULL);
+ current_function_decl = NULL_TREE;
+ if (nested)
+ c_pop_function_context ();
+
+ if (!clauses.is_empty ())
+ {
+ parser->tokens = &parser->tokens_buf[0];
+ parser->tokens_avail = tokens_avail;
+ }
+ if (bad)
+ goto fail;
+ if (errs != errorcount)
+ break;
+ }
+
+ clauses.release ();
+ types.release ();
+}
+
+
+/* OpenMP 4.0
+ #pragma omp declare simd declare-simd-clauses[optseq] new-line
+ #pragma omp declare reduction (reduction-id : typename-list : expression) \
+ initializer-clause[opt] new-line
+ #pragma omp declare target new-line */
+
+static void
+c_parser_omp_declare (c_parser *parser, enum pragma_context context)
+{
+ c_parser_consume_pragma (parser);
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ {
+ const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+ if (strcmp (p, "simd") == 0)
+ {
+ /* c_parser_consume_token (parser); done in
+ c_parser_omp_declare_simd. */
+ c_parser_omp_declare_simd (parser, context);
+ return;
+ }
+ if (strcmp (p, "reduction") == 0)
+ {
+ c_parser_consume_token (parser);
+ c_parser_omp_declare_reduction (parser, context);
+ return;
+ }
+ if (!flag_openmp) /* flag_openmp_simd */
+ {
+ c_parser_skip_to_pragma_eol (parser);
+ return;
+ }
+ if (strcmp (p, "target") == 0)
+ {
+ c_parser_consume_token (parser);
+ c_parser_omp_declare_target (parser);
+ return;
+ }
+ }
+
+ c_parser_error (parser, "expected %<simd%> or %<reduction%> "
+ "or %<target%>");
+ c_parser_skip_to_pragma_eol (parser);
+}
+
/* Main entry point to parsing most OpenMP pragmas. */
static void
@@ -10888,6 +13095,8 @@ c_parser_omp_construct (c_parser *parser)
enum pragma_kind p_kind;
location_t loc;
tree stmt;
+ char p_name[sizeof "#pragma omp teams distribute parallel for simd"];
+ omp_clause_mask mask (0);
loc = c_parser_peek_token (parser)->location;
p_kind = c_parser_peek_token (parser)->pragma_kind;
@@ -10901,8 +13110,13 @@ c_parser_omp_construct (c_parser *parser)
case PRAGMA_OMP_CRITICAL:
stmt = c_parser_omp_critical (loc, parser);
break;
+ case PRAGMA_OMP_DISTRIBUTE:
+ strcpy (p_name, "#pragma omp");
+ stmt = c_parser_omp_distribute (loc, parser, p_name, mask, NULL);
+ break;
case PRAGMA_OMP_FOR:
- stmt = c_parser_omp_for (loc, parser);
+ strcpy (p_name, "#pragma omp");
+ stmt = c_parser_omp_for (loc, parser, p_name, mask, NULL);
break;
case PRAGMA_OMP_MASTER:
stmt = c_parser_omp_master (loc, parser);
@@ -10911,10 +13125,16 @@ c_parser_omp_construct (c_parser *parser)
stmt = c_parser_omp_ordered (loc, parser);
break;
case PRAGMA_OMP_PARALLEL:
- stmt = c_parser_omp_parallel (loc, parser);
+ strcpy (p_name, "#pragma omp");
+ stmt = c_parser_omp_parallel (loc, parser, p_name, mask, NULL);
break;
case PRAGMA_OMP_SECTIONS:
- stmt = c_parser_omp_sections (loc, parser);
+ strcpy (p_name, "#pragma omp");
+ stmt = c_parser_omp_sections (loc, parser, p_name, mask, NULL);
+ break;
+ case PRAGMA_OMP_SIMD:
+ strcpy (p_name, "#pragma omp");
+ stmt = c_parser_omp_simd (loc, parser, p_name, mask, NULL);
break;
case PRAGMA_OMP_SINGLE:
stmt = c_parser_omp_single (loc, parser);
@@ -10922,6 +13142,13 @@ c_parser_omp_construct (c_parser *parser)
case PRAGMA_OMP_TASK:
stmt = c_parser_omp_task (loc, parser);
break;
+ case PRAGMA_OMP_TASKGROUP:
+ stmt = c_parser_omp_taskgroup (parser);
+ break;
+ case PRAGMA_OMP_TEAMS:
+ strcpy (p_name, "#pragma omp");
+ stmt = c_parser_omp_teams (loc, parser, p_name, mask, NULL);
+ break;
default:
gcc_unreachable ();
}
@@ -11148,7 +13375,7 @@ c_parser_transaction_expression (c_parser *parser, enum rid keyword)
*/
static tree
-c_parser_transaction_cancel(c_parser *parser)
+c_parser_transaction_cancel (c_parser *parser)
{
location_t loc = c_parser_peek_token (parser)->location;
tree attrs;
@@ -11208,6 +13435,7 @@ c_parse_file (void)
c_parser tparser;
memset (&tparser, 0, sizeof tparser);
+ tparser.tokens = &tparser.tokens_buf[0];
the_parser = &tparser;
if (c_parser_peek_token (&tparser)->pragma_kind == PRAGMA_GCC_PCH_PREPROCESS)
@@ -11215,6 +13443,8 @@ c_parse_file (void)
the_parser = ggc_alloc_c_parser ();
*the_parser = tparser;
+ if (tparser.tokens == &tparser.tokens_buf[0])
+ the_parser->tokens = &the_parser->tokens_buf[0];
/* Initialize EH, if we've been told to do so. */
if (flag_exceptions)
@@ -11320,7 +13550,9 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index,
return error_mark_node;
}
c_parser_consume_token (parser); /* consume the ':' */
- end_index = c_parser_expression (parser).value;
+ struct c_expr ce = c_parser_expression (parser);
+ ce = convert_lvalue_to_rvalue (loc, ce, false, false);
+ end_index = ce.value;
if (!end_index || end_index == error_mark_node)
{
c_parser_skip_to_end_of_block_or_statement (parser);
@@ -11329,7 +13561,9 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index,
if (c_parser_peek_token (parser)->type == CPP_COLON)
{
c_parser_consume_token (parser);
- stride = c_parser_expression (parser).value;
+ ce = c_parser_expression (parser);
+ ce = convert_lvalue_to_rvalue (loc, ce, false, false);
+ stride = ce.value;
if (!stride || stride == error_mark_node)
{
c_parser_skip_to_end_of_block_or_statement (parser);
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index d1a871daa68..8dffa9c1674 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -163,7 +163,7 @@ enum c_typespec_kind {
ctsk_typedef,
/* An ObjC-specific kind of type specifier. */
ctsk_objc,
- /* A typeof specifier. */
+ /* A typeof specifier, or _Atomic ( type-name ). */
ctsk_typeof
};
@@ -328,6 +328,8 @@ struct c_declspecs {
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
@@ -526,6 +528,8 @@ extern tree start_struct (location_t, enum tree_code, tree,
struct 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);
extern struct c_parm *build_c_parm (struct c_declspecs *, tree,
@@ -583,6 +587,8 @@ 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 void mark_exp_read (tree);
extern tree composite_type (tree, tree);
extern tree build_component_ref (location_t, tree, tree);
@@ -637,9 +643,12 @@ 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);
extern tree c_build_va_arg (location_t, tree, tree);
extern tree c_finish_transaction (location_t, tree, int);
+extern bool c_tree_equal (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. */
@@ -663,6 +672,10 @@ extern enum machine_mode c_default_pointer_mode;
/* In c-decl.c */
extern void c_finish_incomplete_decl (tree);
extern void c_write_global_declarations (void);
+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 *);
/* In c-errors.c */
extern void pedwarn_c90 (location_t, int opt, const char *, ...) ATTRIBUTE_GCC_DIAG(3,4);
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 7ecafe4894c..5ef1f9303f1 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -37,6 +37,8 @@ along with GCC; see the file COPYING3. If not see
#include "tree-iterator.h"
#include "bitmap.h"
#include "gimple.h"
+#include "tree-inline.h"
+#include "omp-low.h"
#include "c-family/c-objc.h"
#include "c-family/c-common.h"
#include "c-family/c-ubsan.h"
@@ -263,18 +265,25 @@ c_incomplete_type_error (const_tree value, const_tree type)
tree
c_type_promotes_to (tree type)
{
- if (TYPE_MAIN_VARIANT (type) == float_type_node)
- return double_type_node;
+ tree ret = NULL_TREE;
- if (c_promoting_integer_type_p (type))
+ if (TYPE_MAIN_VARIANT (type) == float_type_node)
+ ret = double_type_node;
+ else if (c_promoting_integer_type_p (type))
{
/* Preserve unsignedness if not really getting any wider. */
if (TYPE_UNSIGNED (type)
&& (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node)))
- return unsigned_type_node;
- return integer_type_node;
+ ret = unsigned_type_node;
+ else
+ ret = integer_type_node;
}
+ if (ret != NULL_TREE)
+ return (TYPE_ATOMIC (type)
+ ? c_build_qualified_type (ret, TYPE_QUAL_ATOMIC)
+ : ret);
+
return type;
}
@@ -325,7 +334,7 @@ qualify_type (tree type, tree like)
return c_build_qualified_type (type,
TYPE_QUALS_NO_ADDR_SPACE (type)
- | TYPE_QUALS_NO_ADDR_SPACE (like)
+ | TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (like)
| ENCODE_QUAL_ADDR_SPACE (as_common));
}
@@ -1212,9 +1221,13 @@ comp_target_types (location_t location, tree ttl, tree ttr)
/* Do not lose qualifiers on element types of array types that are
pointer targets by taking their TYPE_MAIN_VARIANT. */
if (TREE_CODE (mvl) != ARRAY_TYPE)
- mvl = TYPE_MAIN_VARIANT (mvl);
+ mvl = (TYPE_ATOMIC (mvl)
+ ? c_build_qualified_type (TYPE_MAIN_VARIANT (mvl), TYPE_QUAL_ATOMIC)
+ : TYPE_MAIN_VARIANT (mvl));
if (TREE_CODE (mvr) != ARRAY_TYPE)
- mvr = TYPE_MAIN_VARIANT (mvr);
+ mvr = (TYPE_ATOMIC (mvr)
+ ? c_build_qualified_type (TYPE_MAIN_VARIANT (mvr), TYPE_QUAL_ATOMIC)
+ : TYPE_MAIN_VARIANT (mvr));
enum_and_int_p = false;
val = comptypes_check_enum_int (mvl, mvr, &enum_and_int_p);
@@ -1631,9 +1644,15 @@ type_lists_compatible_p (const_tree args1, const_tree args2,
mv1 = a1 = TREE_VALUE (args1);
mv2 = a2 = TREE_VALUE (args2);
if (mv1 && mv1 != error_mark_node && TREE_CODE (mv1) != ARRAY_TYPE)
- mv1 = TYPE_MAIN_VARIANT (mv1);
+ mv1 = (TYPE_ATOMIC (mv1)
+ ? c_build_qualified_type (TYPE_MAIN_VARIANT (mv1),
+ TYPE_QUAL_ATOMIC)
+ : TYPE_MAIN_VARIANT (mv1));
if (mv2 && mv2 != error_mark_node && TREE_CODE (mv2) != ARRAY_TYPE)
- mv2 = TYPE_MAIN_VARIANT (mv2);
+ mv2 = (TYPE_ATOMIC (mv2)
+ ? c_build_qualified_type (TYPE_MAIN_VARIANT (mv2),
+ TYPE_QUAL_ATOMIC)
+ : TYPE_MAIN_VARIANT (mv2));
/* A null pointer instead of a type
means there is supposed to be an argument
but nothing is specified about what type it has.
@@ -1676,7 +1695,10 @@ type_lists_compatible_p (const_tree args1, const_tree args2,
tree mv3 = TREE_TYPE (memb);
if (mv3 && mv3 != error_mark_node
&& TREE_CODE (mv3) != ARRAY_TYPE)
- mv3 = TYPE_MAIN_VARIANT (mv3);
+ mv3 = (TYPE_ATOMIC (mv3)
+ ? c_build_qualified_type (TYPE_MAIN_VARIANT (mv3),
+ TYPE_QUAL_ATOMIC)
+ : TYPE_MAIN_VARIANT (mv3));
if (comptypes_internal (mv3, mv2, enum_and_int_p,
different_types_p))
break;
@@ -1698,7 +1720,10 @@ type_lists_compatible_p (const_tree args1, const_tree args2,
tree mv3 = TREE_TYPE (memb);
if (mv3 && mv3 != error_mark_node
&& TREE_CODE (mv3) != ARRAY_TYPE)
- mv3 = TYPE_MAIN_VARIANT (mv3);
+ mv3 = (TYPE_ATOMIC (mv3)
+ ? c_build_qualified_type (TYPE_MAIN_VARIANT (mv3),
+ TYPE_QUAL_ATOMIC)
+ : TYPE_MAIN_VARIANT (mv3));
if (comptypes_internal (mv3, mv1, enum_and_int_p,
different_types_p))
break;
@@ -1911,6 +1936,84 @@ default_function_array_read_conversion (location_t loc, struct c_expr exp)
return default_function_array_conversion (loc, exp);
}
+/* Return whether EXPR should be treated as an atomic lvalue for the
+ purposes of load and store handling. */
+
+static bool
+really_atomic_lvalue (tree expr)
+{
+ if (expr == error_mark_node || TREE_TYPE (expr) == error_mark_node)
+ return false;
+ if (!TYPE_ATOMIC (TREE_TYPE (expr)))
+ return false;
+ if (!lvalue_p (expr))
+ return false;
+
+ /* Ignore _Atomic on register variables, since their addresses can't
+ be taken so (a) atomicity is irrelevant and (b) the normal atomic
+ sequences wouldn't work. Ignore _Atomic on structures containing
+ bit-fields, since accessing elements of atomic structures or
+ unions is undefined behavior (C11 6.5.2.3#5), but it's unclear if
+ it's undefined at translation time or execution time, and the
+ normal atomic sequences again wouldn't work. */
+ while (handled_component_p (expr))
+ {
+ if (TREE_CODE (expr) == COMPONENT_REF
+ && DECL_C_BIT_FIELD (TREE_OPERAND (expr, 1)))
+ return false;
+ expr = TREE_OPERAND (expr, 0);
+ }
+ if (DECL_P (expr) && C_DECL_REGISTER (expr))
+ return false;
+ return true;
+}
+
+/* Convert expression EXP (location LOC) from lvalue to rvalue,
+ including converting functions and arrays to pointers if CONVERT_P.
+ If READ_P, also mark the expression as having been read. */
+
+struct c_expr
+convert_lvalue_to_rvalue (location_t loc, struct c_expr exp,
+ bool convert_p, bool read_p)
+{
+ if (read_p)
+ mark_exp_read (exp.value);
+ if (convert_p)
+ exp = default_function_array_conversion (loc, exp);
+ if (really_atomic_lvalue (exp.value))
+ {
+ vec<tree, va_gc> *params;
+ tree nonatomic_type, tmp, tmp_addr, fndecl, func_call;
+ tree expr_type = TREE_TYPE (exp.value);
+ tree expr_addr = build_unary_op (loc, ADDR_EXPR, exp.value, 0);
+ tree seq_cst = build_int_cst (integer_type_node, MEMMODEL_SEQ_CST);
+
+ gcc_assert (TYPE_ATOMIC (expr_type));
+
+ /* Expansion of a generic atomic load may require an addition
+ element, so allocate enough to prevent a resize. */
+ vec_alloc (params, 4);
+
+ /* Remove the qualifiers for the rest of the expressions and
+ create the VAL temp variable to hold the RHS. */
+ nonatomic_type = build_qualified_type (expr_type, TYPE_UNQUALIFIED);
+ tmp = create_tmp_var (nonatomic_type, NULL);
+ tmp_addr = build_unary_op (loc, ADDR_EXPR, tmp, 0);
+ TREE_ADDRESSABLE (tmp) = 1;
+
+ /* Issue __atomic_load (&expr, &tmp, SEQ_CST); */
+ fndecl = builtin_decl_explicit (BUILT_IN_ATOMIC_LOAD);
+ params->quick_push (expr_addr);
+ params->quick_push (tmp_addr);
+ params->quick_push (seq_cst);
+ func_call = build_function_call_vec (loc, fndecl, params, NULL);
+
+ /* Return tmp which contains the value loaded. */
+ exp.value = build2 (COMPOUND_EXPR, nonatomic_type, func_call, tmp);
+ }
+ return exp;
+}
+
/* EXP is an expression of integer type. Apply the integer promotions
to it and return the promoted value. */
@@ -3433,6 +3536,215 @@ pointer_diff (location_t loc, tree op0, tree op1)
return convert (restype, result);
}
+/* Expand atomic compound assignments into an approriate sequence as
+ specified by the C11 standard section 6.5.16.2.
+ given
+ _Atomic T1 E1
+ T2 E2
+ E1 op= E2
+
+ This sequence is used for all types for which these operations are
+ supported.
+
+ In addition, built-in versions of the 'fe' prefixed routines may
+ need to be invoked for floating point (real, complex or vector) when
+ floating-point exceptions are supported. See 6.5.16.2 footnote 113.
+
+ T1 newval;
+ T1 old;
+ T1 *addr
+ T2 val
+ fenv_t fenv
+
+ addr = &E1;
+ val = (E2);
+ __atomic_load (addr, &old, SEQ_CST);
+ feholdexcept (&fenv);
+loop:
+ newval = old op val;
+ if (__atomic_compare_exchange_strong (addr, &old, &newval, SEQ_CST,
+ SEQ_CST))
+ goto done;
+ feclearexcept (FE_ALL_EXCEPT);
+ goto loop:
+done:
+ feupdateenv (&fenv);
+
+ Also note that the compiler is simply issuing the generic form of
+ the atomic operations. This requires temp(s) and has their address
+ taken. The atomic processing is smart enough to figure out when the
+ size of an object can utilize a lock-free version, and convert the
+ built-in call to the appropriate lock-free routine. The optimizers
+ will then dispose of any temps that are no longer required, and
+ lock-free implementations are utilized as long as there is target
+ support for the required size.
+
+ If the operator is NOP_EXPR, then this is a simple assignment, and
+ an __atomic_store is issued to perform the assignment rather than
+ the above loop.
+
+*/
+
+/* Build an atomic assignment at LOC, expanding into the proper
+ sequence to store LHS MODIFYCODE= RHS. Return a value representing
+ the result of the operation, unless RETURN_OLD_P in which case
+ return the old value of LHS (this is only for postincrement and
+ postdecrement). */
+static tree
+build_atomic_assign (location_t loc, tree lhs, enum tree_code modifycode,
+ tree rhs, bool return_old_p)
+{
+ tree fndecl, func_call;
+ vec<tree, va_gc> *params;
+ tree val, nonatomic_lhs_type, nonatomic_rhs_type, newval, newval_addr;
+ tree old, old_addr;
+ tree compound_stmt;
+ tree stmt, goto_stmt;
+ tree loop_label, loop_decl, done_label, done_decl;
+
+ tree lhs_type = TREE_TYPE (lhs);
+ tree lhs_addr = build_unary_op (loc, ADDR_EXPR, lhs, 0);
+ tree seq_cst = build_int_cst (integer_type_node, MEMMODEL_SEQ_CST);
+ tree rhs_type = TREE_TYPE (rhs);
+
+ gcc_assert (TYPE_ATOMIC (lhs_type));
+
+ if (return_old_p)
+ gcc_assert (modifycode == PLUS_EXPR || modifycode == MINUS_EXPR);
+
+ /* Allocate enough vector items for a compare_exchange. */
+ vec_alloc (params, 6);
+
+ /* Create a compound statement to hold the sequence of statements
+ with a loop. */
+ compound_stmt = c_begin_compound_stmt (false);
+
+ /* Fold the RHS if it hasn't already been folded. */
+ if (modifycode != NOP_EXPR)
+ rhs = c_fully_fold (rhs, false, NULL);
+
+ /* Remove the qualifiers for the rest of the expressions and create
+ the VAL temp variable to hold the RHS. */
+ nonatomic_lhs_type = build_qualified_type (lhs_type, TYPE_UNQUALIFIED);
+ nonatomic_rhs_type = build_qualified_type (rhs_type, TYPE_UNQUALIFIED);
+ val = create_tmp_var (nonatomic_rhs_type, NULL);
+ TREE_ADDRESSABLE (val) = 1;
+ rhs = build2 (MODIFY_EXPR, nonatomic_rhs_type, val, rhs);
+ SET_EXPR_LOCATION (rhs, loc);
+ add_stmt (rhs);
+
+ /* NOP_EXPR indicates it's a straight store of the RHS. Simply issue
+ an atomic_store. */
+ if (modifycode == NOP_EXPR)
+ {
+ /* Build __atomic_store (&lhs, &val, SEQ_CST) */
+ rhs = build_unary_op (loc, ADDR_EXPR, val, 0);
+ fndecl = builtin_decl_explicit (BUILT_IN_ATOMIC_STORE);
+ params->quick_push (lhs_addr);
+ params->quick_push (rhs);
+ params->quick_push (seq_cst);
+ func_call = build_function_call_vec (loc, fndecl, params, NULL);
+ add_stmt (func_call);
+
+ /* Finish the compound statement. */
+ compound_stmt = c_end_compound_stmt (loc, compound_stmt, false);
+
+ /* VAL is the value which was stored, return a COMPOUND_STMT of
+ the statement and that value. */
+ return build2 (COMPOUND_EXPR, nonatomic_lhs_type, compound_stmt, val);
+ }
+
+ /* Create the variables and labels required for the op= form. */
+ old = create_tmp_var (nonatomic_lhs_type, NULL);
+ old_addr = build_unary_op (loc, ADDR_EXPR, old, 0);
+ TREE_ADDRESSABLE (val) = 1;
+
+ newval = create_tmp_var (nonatomic_lhs_type, NULL);
+ newval_addr = build_unary_op (loc, ADDR_EXPR, newval, 0);
+ TREE_ADDRESSABLE (newval) = 1;
+
+ loop_decl = create_artificial_label (loc);
+ loop_label = build1 (LABEL_EXPR, void_type_node, loop_decl);
+
+ done_decl = create_artificial_label (loc);
+ done_label = build1 (LABEL_EXPR, void_type_node, done_decl);
+
+ /* __atomic_load (addr, &old, SEQ_CST). */
+ fndecl = builtin_decl_explicit (BUILT_IN_ATOMIC_LOAD);
+ params->quick_push (lhs_addr);
+ params->quick_push (old_addr);
+ params->quick_push (seq_cst);
+ func_call = build_function_call_vec (loc, fndecl, params, NULL);
+ add_stmt (func_call);
+ params->truncate (0);
+
+ /* Create the expressions for floating-point environment
+ manipulation, if required. */
+ bool need_fenv = (flag_trapping_math
+ && (FLOAT_TYPE_P (lhs_type) || FLOAT_TYPE_P (rhs_type)));
+ tree hold_call = NULL_TREE, clear_call = NULL_TREE, update_call = NULL_TREE;
+ if (need_fenv)
+ targetm.atomic_assign_expand_fenv (&hold_call, &clear_call, &update_call);
+
+ if (hold_call)
+ add_stmt (hold_call);
+
+ /* loop: */
+ add_stmt (loop_label);
+
+ /* newval = old + val; */
+ rhs = build_binary_op (loc, modifycode, old, val, 1);
+ rhs = convert_for_assignment (loc, nonatomic_lhs_type, rhs, NULL_TREE,
+ ic_assign, false, NULL_TREE,
+ NULL_TREE, 0);
+ if (rhs != error_mark_node)
+ {
+ rhs = build2 (MODIFY_EXPR, nonatomic_lhs_type, newval, rhs);
+ SET_EXPR_LOCATION (rhs, loc);
+ add_stmt (rhs);
+ }
+
+ /* if (__atomic_compare_exchange (addr, &old, &new, false, SEQ_CST, SEQ_CST))
+ goto done; */
+ fndecl = builtin_decl_explicit (BUILT_IN_ATOMIC_COMPARE_EXCHANGE);
+ params->quick_push (lhs_addr);
+ params->quick_push (old_addr);
+ params->quick_push (newval_addr);
+ params->quick_push (integer_zero_node);
+ params->quick_push (seq_cst);
+ params->quick_push (seq_cst);
+ func_call = build_function_call_vec (loc, fndecl, params, NULL);
+
+ goto_stmt = build1 (GOTO_EXPR, void_type_node, done_decl);
+ SET_EXPR_LOCATION (goto_stmt, loc);
+
+ stmt = build3 (COND_EXPR, void_type_node, func_call, goto_stmt, NULL_TREE);
+ SET_EXPR_LOCATION (stmt, loc);
+ add_stmt (stmt);
+
+ if (clear_call)
+ add_stmt (clear_call);
+
+ /* goto loop; */
+ goto_stmt = build1 (GOTO_EXPR, void_type_node, loop_decl);
+ SET_EXPR_LOCATION (goto_stmt, loc);
+ add_stmt (goto_stmt);
+
+ /* done: */
+ add_stmt (done_label);
+
+ if (update_call)
+ add_stmt (update_call);
+
+ /* Finish the compound statement. */
+ compound_stmt = c_end_compound_stmt (loc, compound_stmt, false);
+
+ /* NEWVAL is the value that was successfully stored, return a
+ COMPOUND_EXPR of the statement and the appropriate value. */
+ return build2 (COMPOUND_EXPR, nonatomic_lhs_type, compound_stmt,
+ return_old_p ? old : newval);
+}
+
/* Construct and perhaps optimize a tree representation
for a unary operation. CODE, a tree_code, specifies the operation
and XARG is the operand.
@@ -3633,6 +3945,9 @@ build_unary_op (location_t location,
/* Ensure the argument is fully folded inside any SAVE_EXPR. */
arg = c_fully_fold (arg, false, NULL);
+ bool atomic_op;
+ atomic_op = really_atomic_lvalue (arg);
+
/* Increment or decrement the real part of the value,
and don't change the imaginary part. */
if (typecode == COMPLEX_TYPE)
@@ -3642,21 +3957,25 @@ build_unary_op (location_t location,
pedwarn (location, OPT_Wpedantic,
"ISO C does not support %<++%> and %<--%> on complex types");
- arg = stabilize_reference (arg);
- real = build_unary_op (EXPR_LOCATION (arg), REALPART_EXPR, arg, 1);
- imag = build_unary_op (EXPR_LOCATION (arg), IMAGPART_EXPR, arg, 1);
- real = build_unary_op (EXPR_LOCATION (arg), code, real, 1);
- if (real == error_mark_node || imag == error_mark_node)
- return error_mark_node;
- ret = build2 (COMPLEX_EXPR, TREE_TYPE (arg),
- real, imag);
- goto return_build_unary_op;
+ if (!atomic_op)
+ {
+ arg = stabilize_reference (arg);
+ real = build_unary_op (EXPR_LOCATION (arg), REALPART_EXPR, arg, 1);
+ imag = build_unary_op (EXPR_LOCATION (arg), IMAGPART_EXPR, arg, 1);
+ real = build_unary_op (EXPR_LOCATION (arg), code, real, 1);
+ if (real == error_mark_node || imag == error_mark_node)
+ return error_mark_node;
+ ret = build2 (COMPLEX_EXPR, TREE_TYPE (arg),
+ real, imag);
+ goto return_build_unary_op;
+ }
}
/* Report invalid types. */
if (typecode != POINTER_TYPE && typecode != FIXED_POINT_TYPE
- && typecode != INTEGER_TYPE && typecode != REAL_TYPE)
+ && typecode != INTEGER_TYPE && typecode != REAL_TYPE
+ && typecode != COMPLEX_TYPE)
{
if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
error_at (location, "wrong type argument to increment");
@@ -3747,6 +4066,24 @@ build_unary_op (location_t location,
|| code == POSTINCREMENT_EXPR)
? lv_increment : lv_decrement));
+ /* If the argument is atomic, use the special code sequences for
+ atomic compound assignment. */
+ if (atomic_op)
+ {
+ arg = stabilize_reference (arg);
+ ret = build_atomic_assign (location, arg,
+ ((code == PREINCREMENT_EXPR
+ || code == POSTINCREMENT_EXPR)
+ ? PLUS_EXPR
+ : MINUS_EXPR),
+ (FRACT_MODE_P (TYPE_MODE (argtype))
+ ? inc
+ : integer_one_node),
+ (code == POSTINCREMENT_EXPR
+ || code == POSTDECREMENT_EXPR));
+ goto return_build_unary_op;
+ }
+
if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE)
val = boolean_increment (code, arg);
else
@@ -4257,7 +4594,8 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
"used in conditional expression");
return error_mark_node;
}
- else if (VOID_TYPE_P (TREE_TYPE (type1)))
+ else if (VOID_TYPE_P (TREE_TYPE (type1))
+ && !TYPE_ATOMIC (TREE_TYPE (type1)))
{
if (TREE_CODE (TREE_TYPE (type2)) == FUNCTION_TYPE)
pedwarn (colon_loc, OPT_Wpedantic,
@@ -4266,7 +4604,8 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
result_type = build_pointer_type (qualify_type (TREE_TYPE (type1),
TREE_TYPE (type2)));
}
- else if (VOID_TYPE_P (TREE_TYPE (type2)))
+ else if (VOID_TYPE_P (TREE_TYPE (type2))
+ && !TYPE_ATOMIC (TREE_TYPE (type2)))
{
if (TREE_CODE (TREE_TYPE (type1)) == FUNCTION_TYPE)
pedwarn (colon_loc, OPT_Wpedantic,
@@ -4385,6 +4724,14 @@ build_compound_expr (location_t loc, tree expr1, tree expr2)
tree eptype = NULL_TREE;
tree ret;
+ if (flag_enable_cilkplus
+ && (TREE_CODE (expr1) == CILK_SPAWN_STMT
+ || TREE_CODE (expr2) == CILK_SPAWN_STMT))
+ {
+ error_at (loc,
+ "spawned function call cannot be part of a comma expression");
+ return error_mark_node;
+ }
expr1_int_operands = EXPR_INT_CONST_OPERANDS (expr1);
if (expr1_int_operands)
expr1 = remove_c_maybe_const_expr (expr1);
@@ -4840,6 +5187,7 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
tree lhstype = TREE_TYPE (lhs);
tree olhstype = lhstype;
bool npc;
+ bool is_atomic_op;
/* Types that aren't fully specified cannot be used in assignments. */
lhs = require_complete_type (lhs);
@@ -4852,6 +5200,8 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
if (!objc_is_property_ref (lhs) && !lvalue_or_else (location, lhs, lv_assign))
return error_mark_node;
+ is_atomic_op = really_atomic_lvalue (lhs);
+
if (TREE_CODE (rhs) == EXCESS_PRECISION_EXPR)
{
rhs_semantic_type = TREE_TYPE (rhs);
@@ -4882,12 +5232,17 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
{
lhs = c_fully_fold (lhs, false, NULL);
lhs = stabilize_reference (lhs);
- newrhs = build_binary_op (location,
- modifycode, lhs, rhs, 1);
- /* The original type of the right hand side is no longer
- meaningful. */
- rhs_origtype = NULL_TREE;
+ /* Construct the RHS for any non-atomic compound assignemnt. */
+ if (!is_atomic_op)
+ {
+ newrhs = build_binary_op (location,
+ modifycode, lhs, rhs, 1);
+
+ /* The original type of the right hand side is no longer
+ meaningful. */
+ rhs_origtype = NULL_TREE;
+ }
}
if (c_dialect_objc ())
@@ -4949,23 +5304,39 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
? rhs_origtype
: TREE_TYPE (rhs));
if (checktype != error_mark_node
- && TYPE_MAIN_VARIANT (checktype) != TYPE_MAIN_VARIANT (lhs_origtype))
+ && (TYPE_MAIN_VARIANT (checktype) != TYPE_MAIN_VARIANT (lhs_origtype)
+ || (is_atomic_op && modifycode != NOP_EXPR)))
warning_at (location, OPT_Wc___compat,
"enum conversion in assignment is invalid in C++");
}
+ /* If the lhs is atomic, remove that qualifier. */
+ if (is_atomic_op)
+ {
+ lhstype = build_qualified_type (lhstype,
+ (TYPE_QUALS (lhstype)
+ & ~TYPE_QUAL_ATOMIC));
+ olhstype = build_qualified_type (olhstype,
+ (TYPE_QUALS (lhstype)
+ & ~TYPE_QUAL_ATOMIC));
+ }
+
/* Convert new value to destination type. Fold it first, then
restore any excess precision information, for the sake of
conversion warnings. */
- npc = null_pointer_constant_p (newrhs);
- newrhs = c_fully_fold (newrhs, false, NULL);
- if (rhs_semantic_type)
- newrhs = build1 (EXCESS_PRECISION_EXPR, rhs_semantic_type, newrhs);
- newrhs = convert_for_assignment (location, lhstype, newrhs, rhs_origtype,
- ic_assign, npc, NULL_TREE, NULL_TREE, 0);
- if (TREE_CODE (newrhs) == ERROR_MARK)
- return error_mark_node;
+ if (!(is_atomic_op && modifycode != NOP_EXPR))
+ {
+ npc = null_pointer_constant_p (newrhs);
+ newrhs = c_fully_fold (newrhs, false, NULL);
+ if (rhs_semantic_type)
+ newrhs = build1 (EXCESS_PRECISION_EXPR, rhs_semantic_type, newrhs);
+ newrhs = convert_for_assignment (location, lhstype, newrhs, rhs_origtype,
+ ic_assign, npc, NULL_TREE,
+ NULL_TREE, 0);
+ if (TREE_CODE (newrhs) == ERROR_MARK)
+ return error_mark_node;
+ }
/* Emit ObjC write barrier, if necessary. */
if (c_dialect_objc () && flag_objc_gc)
@@ -4980,9 +5351,14 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
/* Scan operands. */
- result = build2 (MODIFY_EXPR, lhstype, lhs, newrhs);
- TREE_SIDE_EFFECTS (result) = 1;
- protected_set_expr_location (result, location);
+ if (is_atomic_op)
+ result = build_atomic_assign (location, lhs, modifycode, newrhs, false);
+ else
+ {
+ result = build2 (MODIFY_EXPR, lhstype, lhs, newrhs);
+ TREE_SIDE_EFFECTS (result) = 1;
+ protected_set_expr_location (result, location);
+ }
/* If we got the LHS in a different type for storing in,
convert the result back to the nominal type of LHS
@@ -5014,8 +5390,12 @@ find_anonymous_field_with_type (tree struct_type, tree type)
field != NULL_TREE;
field = TREE_CHAIN (field))
{
+ tree fieldtype = (TYPE_ATOMIC (TREE_TYPE (field))
+ ? c_build_qualified_type (TREE_TYPE (field),
+ TYPE_QUAL_ATOMIC)
+ : TYPE_MAIN_VARIANT (TREE_TYPE (field)));
if (DECL_NAME (field) == NULL
- && comptypes (type, TYPE_MAIN_VARIANT (TREE_TYPE (field))))
+ && comptypes (type, fieldtype))
{
if (found)
return false;
@@ -5053,7 +5433,10 @@ convert_to_anonymous_field (location_t location, tree type, tree rhs)
|| TREE_CODE (rhs_struct_type) == UNION_TYPE);
gcc_assert (POINTER_TYPE_P (type));
- lhs_main_type = TYPE_MAIN_VARIANT (TREE_TYPE (type));
+ lhs_main_type = (TYPE_ATOMIC (TREE_TYPE (type))
+ ? c_build_qualified_type (TREE_TYPE (type),
+ TYPE_QUAL_ATOMIC)
+ : TYPE_MAIN_VARIANT (TREE_TYPE (type)));
found_field = NULL_TREE;
found_sub_field = false;
@@ -5065,7 +5448,11 @@ convert_to_anonymous_field (location_t location, tree type, tree rhs)
|| (TREE_CODE (TREE_TYPE (field)) != RECORD_TYPE
&& TREE_CODE (TREE_TYPE (field)) != UNION_TYPE))
continue;
- if (comptypes (lhs_main_type, TYPE_MAIN_VARIANT (TREE_TYPE (field))))
+ tree fieldtype = (TYPE_ATOMIC (TREE_TYPE (field))
+ ? c_build_qualified_type (TREE_TYPE (field),
+ TYPE_QUAL_ATOMIC)
+ : TYPE_MAIN_VARIANT (TREE_TYPE (field)));
+ if (comptypes (lhs_main_type, fieldtype))
{
if (found_field != NULL_TREE)
return NULL_TREE;
@@ -5355,17 +5742,18 @@ convert_for_assignment (location_t location, tree type, tree rhs,
and vice versa; otherwise, targets must be the same.
Meanwhile, the lhs target must have all the qualifiers of
the rhs. */
- if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr)
+ if ((VOID_TYPE_P (ttl) && !TYPE_ATOMIC (ttl))
+ || (VOID_TYPE_P (ttr) && !TYPE_ATOMIC (ttr))
|| comp_target_types (location, memb_type, rhstype))
{
+ int lquals = TYPE_QUALS (ttl) & ~TYPE_QUAL_ATOMIC;
+ int rquals = TYPE_QUALS (ttr) & ~TYPE_QUAL_ATOMIC;
/* If this type won't generate any warnings, use it. */
- if (TYPE_QUALS (ttl) == TYPE_QUALS (ttr)
+ if (lquals == rquals
|| ((TREE_CODE (ttr) == FUNCTION_TYPE
&& TREE_CODE (ttl) == FUNCTION_TYPE)
- ? ((TYPE_QUALS (ttl) | TYPE_QUALS (ttr))
- == TYPE_QUALS (ttr))
- : ((TYPE_QUALS (ttl) | TYPE_QUALS (ttr))
- == TYPE_QUALS (ttl))))
+ ? ((lquals | rquals) == rquals)
+ : ((lquals | rquals) == lquals)))
break;
/* Keep looking for a better type, but remember this one. */
@@ -5456,9 +5844,15 @@ convert_for_assignment (location_t location, tree type, tree rhs,
addr_space_t asr;
if (TREE_CODE (mvl) != ARRAY_TYPE)
- mvl = TYPE_MAIN_VARIANT (mvl);
+ mvl = (TYPE_ATOMIC (mvl)
+ ? c_build_qualified_type (TYPE_MAIN_VARIANT (mvl),
+ TYPE_QUAL_ATOMIC)
+ : TYPE_MAIN_VARIANT (mvl));
if (TREE_CODE (mvr) != ARRAY_TYPE)
- mvr = TYPE_MAIN_VARIANT (mvr);
+ mvr = (TYPE_ATOMIC (mvr)
+ ? c_build_qualified_type (TYPE_MAIN_VARIANT (mvr),
+ TYPE_QUAL_ATOMIC)
+ : TYPE_MAIN_VARIANT (mvr));
/* Opaque pointers are treated like void pointers. */
is_opaque_pointer = vector_targets_convertible_p (ttl, ttr);
@@ -5559,13 +5953,15 @@ convert_for_assignment (location_t location, tree type, tree rhs,
/* Any non-function converts to a [const][volatile] void *
and vice versa; otherwise, targets must be the same.
Meanwhile, the lhs target must have all the qualifiers of the rhs. */
- if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr)
+ if ((VOID_TYPE_P (ttl) && !TYPE_ATOMIC (ttl))
+ || (VOID_TYPE_P (ttr) && !TYPE_ATOMIC (ttr))
|| (target_cmp = comp_target_types (location, type, rhstype))
|| is_opaque_pointer
|| ((c_common_unsigned_type (mvl)
== c_common_unsigned_type (mvr))
- && c_common_signed_type (mvl)
- == c_common_signed_type (mvr)))
+ && (c_common_signed_type (mvl)
+ == c_common_signed_type (mvr))
+ && TYPE_ATOMIC (mvl) == TYPE_ATOMIC (mvr)))
{
if (pedantic
&& ((VOID_TYPE_P (ttl) && TREE_CODE (ttr) == FUNCTION_TYPE)
@@ -5588,8 +5984,9 @@ convert_for_assignment (location_t location, tree type, tree rhs,
else if (TREE_CODE (ttr) != FUNCTION_TYPE
&& TREE_CODE (ttl) != FUNCTION_TYPE)
{
- if (TYPE_QUALS_NO_ADDR_SPACE (ttr)
- & ~TYPE_QUALS_NO_ADDR_SPACE (ttl))
+ /* Assignments between atomic and non-atomic objects are OK. */
+ if (TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (ttr)
+ & ~TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (ttl))
{
WARN_FOR_QUALIFIERS (location, 0,
G_("passing argument %d of %qE discards "
@@ -6062,7 +6459,11 @@ digest_init (location_t init_loc, tree type, tree init, tree origtype,
if (code == ARRAY_TYPE && inside_init
&& TREE_CODE (inside_init) == STRING_CST)
{
- tree typ1 = TYPE_MAIN_VARIANT (TREE_TYPE (type));
+ tree typ1
+ = (TYPE_ATOMIC (TREE_TYPE (type))
+ ? c_build_qualified_type (TYPE_MAIN_VARIANT (TREE_TYPE (type)),
+ TYPE_QUAL_ATOMIC)
+ : TYPE_MAIN_VARIANT (TREE_TYPE (type)));
/* Note that an array could be both an array of character type
and an array of wchar_t if wchar_t is signed char or unsigned
char. */
@@ -8600,7 +9001,7 @@ build_asm_expr (location_t loc, tree string, tree outputs, tree inputs,
struct c_expr expr;
memset (&expr, 0, sizeof (expr));
expr.value = input;
- expr = default_function_array_conversion (loc, expr);
+ expr = convert_lvalue_to_rvalue (loc, expr, true, false);
input = c_fully_fold (expr.value, false, NULL);
if (input != error_mark_node && VOID_TYPE_P (TREE_TYPE (input)))
@@ -8692,6 +9093,12 @@ c_finish_return (location_t loc, tree retval, tree origtype)
return error_mark_node;
}
}
+ if (flag_enable_cilkplus && retval && TREE_CODE (retval) == CILK_SPAWN_STMT)
+ {
+ error_at (loc, "use of %<_Cilk_spawn%> in a return statement is not "
+ "allowed");
+ return error_mark_node;
+ }
if (retval)
{
tree semantic_type = NULL_TREE;
@@ -10080,13 +10487,13 @@ build_binary_op (location_t location, enum tree_code code,
"disjoint address spaces");
return error_mark_node;
}
- else if (VOID_TYPE_P (tt0))
+ else if (VOID_TYPE_P (tt0) && !TYPE_ATOMIC (tt0))
{
if (pedantic && TREE_CODE (tt1) == FUNCTION_TYPE)
pedwarn (location, OPT_Wpedantic, "ISO C forbids "
"comparison of %<void *%> with function pointer");
}
- else if (VOID_TYPE_P (tt1))
+ else if (VOID_TYPE_P (tt1) && !TYPE_ATOMIC (tt1))
{
if (pedantic && TREE_CODE (tt0) == FUNCTION_TYPE)
pedwarn (location, OPT_Wpedantic, "ISO C forbids "
@@ -10692,6 +11099,537 @@ c_finish_omp_task (location_t loc, tree clauses, tree block)
return add_stmt (stmt);
}
+/* Generate GOMP_cancel call for #pragma omp cancel. */
+
+void
+c_finish_omp_cancel (location_t loc, tree clauses)
+{
+ tree fn = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
+ int mask = 0;
+ if (find_omp_clause (clauses, OMP_CLAUSE_PARALLEL))
+ mask = 1;
+ else if (find_omp_clause (clauses, OMP_CLAUSE_FOR))
+ mask = 2;
+ else if (find_omp_clause (clauses, OMP_CLAUSE_SECTIONS))
+ mask = 4;
+ else if (find_omp_clause (clauses, OMP_CLAUSE_TASKGROUP))
+ mask = 8;
+ else
+ {
+ error_at (loc, "%<#pragma omp cancel must specify one of "
+ "%<parallel%>, %<for%>, %<sections%> or %<taskgroup%> "
+ "clauses");
+ return;
+ }
+ tree ifc = find_omp_clause (clauses, OMP_CLAUSE_IF);
+ if (ifc != NULL_TREE)
+ {
+ tree type = TREE_TYPE (OMP_CLAUSE_IF_EXPR (ifc));
+ ifc = fold_build2_loc (OMP_CLAUSE_LOCATION (ifc), NE_EXPR,
+ boolean_type_node, OMP_CLAUSE_IF_EXPR (ifc),
+ build_zero_cst (type));
+ }
+ else
+ ifc = boolean_true_node;
+ tree stmt = build_call_expr_loc (loc, fn, 2,
+ build_int_cst (integer_type_node, mask),
+ ifc);
+ add_stmt (stmt);
+}
+
+/* Generate GOMP_cancellation_point call for
+ #pragma omp cancellation point. */
+
+void
+c_finish_omp_cancellation_point (location_t loc, tree clauses)
+{
+ tree fn = builtin_decl_explicit (BUILT_IN_GOMP_CANCELLATION_POINT);
+ int mask = 0;
+ if (find_omp_clause (clauses, OMP_CLAUSE_PARALLEL))
+ mask = 1;
+ else if (find_omp_clause (clauses, OMP_CLAUSE_FOR))
+ mask = 2;
+ else if (find_omp_clause (clauses, OMP_CLAUSE_SECTIONS))
+ mask = 4;
+ else if (find_omp_clause (clauses, OMP_CLAUSE_TASKGROUP))
+ mask = 8;
+ else
+ {
+ error_at (loc, "%<#pragma omp cancellation point must specify one of "
+ "%<parallel%>, %<for%>, %<sections%> or %<taskgroup%> "
+ "clauses");
+ return;
+ }
+ tree stmt = build_call_expr_loc (loc, fn, 1,
+ build_int_cst (integer_type_node, mask));
+ add_stmt (stmt);
+}
+
+/* Helper function for handle_omp_array_sections. Called recursively
+ to handle multiple array-section-subscripts. C is the clause,
+ T current expression (initially OMP_CLAUSE_DECL), which is either
+ a TREE_LIST for array-section-subscript (TREE_PURPOSE is low-bound
+ expression if specified, TREE_VALUE length expression if specified,
+ TREE_CHAIN is what it has been specified after, or some decl.
+ TYPES vector is populated with array section types, MAYBE_ZERO_LEN
+ set to true if any of the array-section-subscript could have length
+ of zero (explicit or implicit), FIRST_NON_ONE is the index of the
+ first array-section-subscript which is known not to have length
+ of one. Given say:
+ map(a[:b][2:1][:c][:2][:d][e:f][2:5])
+ FIRST_NON_ONE will be 3, array-section-subscript [:b], [2:1] and [:c]
+ all are or may have length of 1, array-section-subscript [:2] is the
+ first one knonwn not to have length 1. For array-section-subscript
+ <= FIRST_NON_ONE we diagnose non-contiguous arrays if low bound isn't
+ 0 or length isn't the array domain max + 1, for > FIRST_NON_ONE we
+ can if MAYBE_ZERO_LEN is false. MAYBE_ZERO_LEN will be true in the above
+ case though, as some lengths could be zero. */
+
+static tree
+handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
+ bool &maybe_zero_len, unsigned int &first_non_one)
+{
+ tree ret, low_bound, length, type;
+ if (TREE_CODE (t) != TREE_LIST)
+ {
+ if (t == error_mark_node || TREE_TYPE (t) == error_mark_node)
+ return error_mark_node;
+ if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL)
+ {
+ if (DECL_P (t))
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD is not a variable in %qs clause", t,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ else
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qE is not a variable in %qs clause", t,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ return error_mark_node;
+ }
+ else if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
+ && TREE_CODE (t) == VAR_DECL && DECL_THREAD_LOCAL_P (t))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD is threadprivate variable in %qs clause", t,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ return error_mark_node;
+ }
+ return t;
+ }
+
+ ret = handle_omp_array_sections_1 (c, TREE_CHAIN (t), types,
+ maybe_zero_len, first_non_one);
+ if (ret == error_mark_node || ret == NULL_TREE)
+ return ret;
+
+ type = TREE_TYPE (ret);
+ low_bound = TREE_PURPOSE (t);
+ length = TREE_VALUE (t);
+
+ if (low_bound == error_mark_node || length == error_mark_node)
+ return error_mark_node;
+
+ if (low_bound && !INTEGRAL_TYPE_P (TREE_TYPE (low_bound)))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "low bound %qE of array section does not have integral type",
+ low_bound);
+ return error_mark_node;
+ }
+ if (length && !INTEGRAL_TYPE_P (TREE_TYPE (length)))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "length %qE of array section does not have integral type",
+ length);
+ return error_mark_node;
+ }
+ if (low_bound
+ && TREE_CODE (low_bound) == INTEGER_CST
+ && TYPE_PRECISION (TREE_TYPE (low_bound))
+ > TYPE_PRECISION (sizetype))
+ low_bound = fold_convert (sizetype, low_bound);
+ if (length
+ && TREE_CODE (length) == INTEGER_CST
+ && TYPE_PRECISION (TREE_TYPE (length))
+ > TYPE_PRECISION (sizetype))
+ length = fold_convert (sizetype, length);
+ if (low_bound == NULL_TREE)
+ low_bound = integer_zero_node;
+
+ if (length != NULL_TREE)
+ {
+ if (!integer_nonzerop (length))
+ maybe_zero_len = true;
+ if (first_non_one == types.length ()
+ && (TREE_CODE (length) != INTEGER_CST || integer_onep (length)))
+ first_non_one++;
+ }
+ if (TREE_CODE (type) == ARRAY_TYPE)
+ {
+ if (length == NULL_TREE
+ && (TYPE_DOMAIN (type) == NULL_TREE
+ || TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "for unknown bound array type length expression must "
+ "be specified");
+ return error_mark_node;
+ }
+ if (TREE_CODE (low_bound) == INTEGER_CST
+ && tree_int_cst_sgn (low_bound) == -1)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "negative low bound in array section in %qs clause",
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ return error_mark_node;
+ }
+ if (length != NULL_TREE
+ && TREE_CODE (length) == INTEGER_CST
+ && tree_int_cst_sgn (length) == -1)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "negative length in array section in %qs clause",
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ return error_mark_node;
+ }
+ if (TYPE_DOMAIN (type)
+ && TYPE_MAX_VALUE (TYPE_DOMAIN (type))
+ && TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type)))
+ == INTEGER_CST)
+ {
+ tree size = size_binop (PLUS_EXPR,
+ TYPE_MAX_VALUE (TYPE_DOMAIN (type)),
+ size_one_node);
+ if (TREE_CODE (low_bound) == INTEGER_CST)
+ {
+ if (tree_int_cst_lt (size, low_bound))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "low bound %qE above array section size "
+ "in %qs clause", low_bound,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ return error_mark_node;
+ }
+ if (tree_int_cst_equal (size, low_bound))
+ maybe_zero_len = true;
+ else if (length == NULL_TREE
+ && first_non_one == types.length ()
+ && tree_int_cst_equal
+ (TYPE_MAX_VALUE (TYPE_DOMAIN (type)),
+ low_bound))
+ first_non_one++;
+ }
+ else if (length == NULL_TREE)
+ {
+ maybe_zero_len = true;
+ if (first_non_one == types.length ())
+ first_non_one++;
+ }
+ if (length && TREE_CODE (length) == INTEGER_CST)
+ {
+ if (tree_int_cst_lt (size, length))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "length %qE above array section size "
+ "in %qs clause", length,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ return error_mark_node;
+ }
+ if (TREE_CODE (low_bound) == INTEGER_CST)
+ {
+ tree lbpluslen
+ = size_binop (PLUS_EXPR,
+ fold_convert (sizetype, low_bound),
+ fold_convert (sizetype, length));
+ if (TREE_CODE (lbpluslen) == INTEGER_CST
+ && tree_int_cst_lt (size, lbpluslen))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "high bound %qE above array section size "
+ "in %qs clause", lbpluslen,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ return error_mark_node;
+ }
+ }
+ }
+ }
+ else if (length == NULL_TREE)
+ {
+ maybe_zero_len = true;
+ if (first_non_one == types.length ())
+ first_non_one++;
+ }
+
+ /* For [lb:] we will need to evaluate lb more than once. */
+ if (length == NULL_TREE && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND)
+ {
+ tree lb = c_save_expr (low_bound);
+ if (lb != low_bound)
+ {
+ TREE_PURPOSE (t) = lb;
+ low_bound = lb;
+ }
+ }
+ }
+ else if (TREE_CODE (type) == POINTER_TYPE)
+ {
+ if (length == NULL_TREE)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "for pointer type length expression must be specified");
+ return error_mark_node;
+ }
+ /* If there is a pointer type anywhere but in the very first
+ array-section-subscript, the array section can't be contiguous. */
+ if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
+ && TREE_CODE (TREE_CHAIN (t)) == TREE_LIST)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "array section is not contiguous in %qs clause",
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ return error_mark_node;
+ }
+ }
+ else
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qE does not have pointer or array type", ret);
+ return error_mark_node;
+ }
+ if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND)
+ types.safe_push (TREE_TYPE (ret));
+ /* We will need to evaluate lb more than once. */
+ tree lb = c_save_expr (low_bound);
+ if (lb != low_bound)
+ {
+ TREE_PURPOSE (t) = lb;
+ low_bound = lb;
+ }
+ ret = build_array_ref (OMP_CLAUSE_LOCATION (c), ret, low_bound);
+ return ret;
+}
+
+/* Handle array sections for clause C. */
+
+static bool
+handle_omp_array_sections (tree c)
+{
+ bool maybe_zero_len = false;
+ unsigned int first_non_one = 0;
+ vec<tree> types = vNULL;
+ tree first = handle_omp_array_sections_1 (c, OMP_CLAUSE_DECL (c), types,
+ maybe_zero_len, first_non_one);
+ if (first == error_mark_node)
+ {
+ types.release ();
+ return true;
+ }
+ if (first == NULL_TREE)
+ {
+ types.release ();
+ return false;
+ }
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
+ {
+ tree t = OMP_CLAUSE_DECL (c);
+ tree tem = NULL_TREE;
+ types.release ();
+ /* Need to evaluate side effects in the length expressions
+ if any. */
+ while (TREE_CODE (t) == TREE_LIST)
+ {
+ if (TREE_VALUE (t) && TREE_SIDE_EFFECTS (TREE_VALUE (t)))
+ {
+ if (tem == NULL_TREE)
+ tem = TREE_VALUE (t);
+ else
+ tem = build2 (COMPOUND_EXPR, TREE_TYPE (tem),
+ TREE_VALUE (t), tem);
+ }
+ t = TREE_CHAIN (t);
+ }
+ if (tem)
+ first = build2 (COMPOUND_EXPR, TREE_TYPE (first), tem, first);
+ first = c_fully_fold (first, false, NULL);
+ OMP_CLAUSE_DECL (c) = first;
+ }
+ else
+ {
+ unsigned int num = types.length (), i;
+ tree t, side_effects = NULL_TREE, size = NULL_TREE;
+ tree condition = NULL_TREE;
+
+ if (int_size_in_bytes (TREE_TYPE (first)) <= 0)
+ maybe_zero_len = true;
+
+ for (i = num, t = OMP_CLAUSE_DECL (c); i > 0;
+ t = TREE_CHAIN (t))
+ {
+ tree low_bound = TREE_PURPOSE (t);
+ tree length = TREE_VALUE (t);
+
+ i--;
+ if (low_bound
+ && TREE_CODE (low_bound) == INTEGER_CST
+ && TYPE_PRECISION (TREE_TYPE (low_bound))
+ > TYPE_PRECISION (sizetype))
+ low_bound = fold_convert (sizetype, low_bound);
+ if (length
+ && TREE_CODE (length) == INTEGER_CST
+ && TYPE_PRECISION (TREE_TYPE (length))
+ > TYPE_PRECISION (sizetype))
+ length = fold_convert (sizetype, length);
+ if (low_bound == NULL_TREE)
+ low_bound = integer_zero_node;
+ if (!maybe_zero_len && i > first_non_one)
+ {
+ if (integer_nonzerop (low_bound))
+ goto do_warn_noncontiguous;
+ if (length != NULL_TREE
+ && TREE_CODE (length) == INTEGER_CST
+ && TYPE_DOMAIN (types[i])
+ && TYPE_MAX_VALUE (TYPE_DOMAIN (types[i]))
+ && TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (types[i])))
+ == INTEGER_CST)
+ {
+ tree size;
+ size = size_binop (PLUS_EXPR,
+ TYPE_MAX_VALUE (TYPE_DOMAIN (types[i])),
+ size_one_node);
+ if (!tree_int_cst_equal (length, size))
+ {
+ do_warn_noncontiguous:
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "array section is not contiguous in %qs "
+ "clause",
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ types.release ();
+ return true;
+ }
+ }
+ if (length != NULL_TREE
+ && TREE_SIDE_EFFECTS (length))
+ {
+ if (side_effects == NULL_TREE)
+ side_effects = length;
+ else
+ side_effects = build2 (COMPOUND_EXPR,
+ TREE_TYPE (side_effects),
+ length, side_effects);
+ }
+ }
+ else
+ {
+ tree l;
+
+ if (i > first_non_one && length && integer_nonzerop (length))
+ continue;
+ if (length)
+ l = fold_convert (sizetype, length);
+ else
+ {
+ l = size_binop (PLUS_EXPR,
+ TYPE_MAX_VALUE (TYPE_DOMAIN (types[i])),
+ size_one_node);
+ l = size_binop (MINUS_EXPR, l,
+ fold_convert (sizetype, low_bound));
+ }
+ if (i > first_non_one)
+ {
+ l = fold_build2 (NE_EXPR, boolean_type_node, l,
+ size_zero_node);
+ if (condition == NULL_TREE)
+ condition = l;
+ else
+ condition = fold_build2 (BIT_AND_EXPR, boolean_type_node,
+ l, condition);
+ }
+ else if (size == NULL_TREE)
+ {
+ size = size_in_bytes (TREE_TYPE (types[i]));
+ size = size_binop (MULT_EXPR, size, l);
+ if (condition)
+ size = fold_build3 (COND_EXPR, sizetype, condition,
+ size, size_zero_node);
+ }
+ else
+ size = size_binop (MULT_EXPR, size, l);
+ }
+ }
+ types.release ();
+ if (side_effects)
+ size = build2 (COMPOUND_EXPR, sizetype, side_effects, size);
+ first = c_fully_fold (first, false, NULL);
+ OMP_CLAUSE_DECL (c) = first;
+ if (size)
+ size = c_fully_fold (size, false, NULL);
+ OMP_CLAUSE_SIZE (c) = size;
+ if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
+ return false;
+ tree c2 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
+ OMP_CLAUSE_MAP_KIND (c2) = OMP_CLAUSE_MAP_POINTER;
+ if (!c_mark_addressable (t))
+ return false;
+ OMP_CLAUSE_DECL (c2) = t;
+ t = build_fold_addr_expr (first);
+ t = fold_convert_loc (OMP_CLAUSE_LOCATION (c), ptrdiff_type_node, t);
+ tree ptr = OMP_CLAUSE_DECL (c2);
+ if (!POINTER_TYPE_P (TREE_TYPE (ptr)))
+ ptr = build_fold_addr_expr (ptr);
+ t = fold_build2_loc (OMP_CLAUSE_LOCATION (c), MINUS_EXPR,
+ ptrdiff_type_node, t,
+ fold_convert_loc (OMP_CLAUSE_LOCATION (c),
+ ptrdiff_type_node, ptr));
+ t = c_fully_fold (t, false, NULL);
+ OMP_CLAUSE_SIZE (c2) = t;
+ OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (c);
+ OMP_CLAUSE_CHAIN (c) = c2;
+ }
+ return false;
+}
+
+/* Helper function of finish_omp_clauses. Clone STMT as if we were making
+ an inline call. But, remap
+ the OMP_DECL1 VAR_DECL (omp_out resp. omp_orig) to PLACEHOLDER
+ and OMP_DECL2 VAR_DECL (omp_in resp. omp_priv) to DECL. */
+
+static tree
+c_clone_omp_udr (tree stmt, tree omp_decl1, tree omp_decl2,
+ tree decl, tree placeholder)
+{
+ copy_body_data id;
+ struct pointer_map_t *decl_map = pointer_map_create ();
+
+ *pointer_map_insert (decl_map, omp_decl1) = placeholder;
+ *pointer_map_insert (decl_map, omp_decl2) = decl;
+ memset (&id, 0, sizeof (id));
+ id.src_fn = DECL_CONTEXT (omp_decl1);
+ id.dst_fn = current_function_decl;
+ id.src_cfun = DECL_STRUCT_FUNCTION (id.src_fn);
+ id.decl_map = decl_map;
+
+ id.copy_decl = copy_decl_no_change;
+ id.transform_call_graph_edges = CB_CGE_DUPLICATE;
+ id.transform_new_cfg = true;
+ id.transform_return_to_modify = false;
+ id.transform_lang_insert_block = NULL;
+ id.eh_lp_nr = 0;
+ walk_tree (&stmt, copy_tree_body_r, &id, NULL);
+ pointer_map_destroy (decl_map);
+ return stmt;
+}
+
+/* Helper function of c_finish_omp_clauses, called via walk_tree.
+ Find OMP_CLAUSE_PLACEHOLDER (passed in DATA) in *TP. */
+
+static tree
+c_find_omp_placeholder_r (tree *tp, int *, void *data)
+{
+ if (*tp == (tree) data)
+ return *tp;
+ return NULL_TREE;
+}
+
/* For all elements of CLAUSES, validate them vs OpenMP constraints.
Remove any elements from the list that are invalid. */
@@ -10699,13 +11637,17 @@ tree
c_finish_omp_clauses (tree clauses)
{
bitmap_head generic_head, firstprivate_head, lastprivate_head;
+ bitmap_head aligned_head;
tree c, t, *pc = &clauses;
- const char *name;
+ bool branch_seen = false;
+ bool copyprivate_seen = false;
+ tree *nowait_clause = NULL;
bitmap_obstack_initialize (NULL);
bitmap_initialize (&generic_head, &bitmap_default_obstack);
bitmap_initialize (&firstprivate_head, &bitmap_default_obstack);
bitmap_initialize (&lastprivate_head, &bitmap_default_obstack);
+ bitmap_initialize (&aligned_head, &bitmap_default_obstack);
for (pc = &clauses, c = clauses; c ; c = *pc)
{
@@ -10716,28 +11658,19 @@ c_finish_omp_clauses (tree clauses)
switch (OMP_CLAUSE_CODE (c))
{
case OMP_CLAUSE_SHARED:
- name = "shared";
need_implicitly_determined = true;
goto check_dup_generic;
case OMP_CLAUSE_PRIVATE:
- name = "private";
need_complete = true;
need_implicitly_determined = true;
goto check_dup_generic;
case OMP_CLAUSE_REDUCTION:
- name = "reduction";
need_implicitly_determined = true;
t = OMP_CLAUSE_DECL (c);
- if (AGGREGATE_TYPE_P (TREE_TYPE (t))
- || POINTER_TYPE_P (TREE_TYPE (t)))
- {
- error_at (OMP_CLAUSE_LOCATION (c),
- "%qE has invalid type for %<reduction%>", t);
- remove = true;
- }
- else if (FLOAT_TYPE_P (TREE_TYPE (t)))
+ if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) == NULL_TREE
+ && FLOAT_TYPE_P (TREE_TYPE (t)))
{
enum tree_code r_code = OMP_CLAUSE_REDUCTION_CODE (c);
const char *r_name = NULL;
@@ -10774,22 +11707,123 @@ c_finish_omp_clauses (tree clauses)
"%qE has invalid type for %<reduction(%s)%>",
t, r_name);
remove = true;
+ break;
+ }
+ }
+ else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) == error_mark_node)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "user defined reduction not found for %qD", t);
+ remove = true;
+ break;
+ }
+ else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
+ {
+ tree list = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
+ tree type = TYPE_MAIN_VARIANT (TREE_TYPE (t));
+ tree placeholder = build_decl (OMP_CLAUSE_LOCATION (c),
+ VAR_DECL, NULL_TREE, type);
+ OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = placeholder;
+ DECL_ARTIFICIAL (placeholder) = 1;
+ DECL_IGNORED_P (placeholder) = 1;
+ if (TREE_ADDRESSABLE (TREE_VEC_ELT (list, 0)))
+ c_mark_addressable (placeholder);
+ if (TREE_ADDRESSABLE (TREE_VEC_ELT (list, 1)))
+ c_mark_addressable (OMP_CLAUSE_DECL (c));
+ OMP_CLAUSE_REDUCTION_MERGE (c)
+ = c_clone_omp_udr (TREE_VEC_ELT (list, 2),
+ TREE_VEC_ELT (list, 0),
+ TREE_VEC_ELT (list, 1),
+ OMP_CLAUSE_DECL (c), placeholder);
+ OMP_CLAUSE_REDUCTION_MERGE (c)
+ = build3_loc (OMP_CLAUSE_LOCATION (c), BIND_EXPR,
+ void_type_node, NULL_TREE,
+ OMP_CLAUSE_REDUCTION_MERGE (c), NULL_TREE);
+ TREE_SIDE_EFFECTS (OMP_CLAUSE_REDUCTION_MERGE (c)) = 1;
+ if (TREE_VEC_LENGTH (list) == 6)
+ {
+ if (TREE_ADDRESSABLE (TREE_VEC_ELT (list, 3)))
+ c_mark_addressable (OMP_CLAUSE_DECL (c));
+ if (TREE_ADDRESSABLE (TREE_VEC_ELT (list, 4)))
+ c_mark_addressable (placeholder);
+ tree init = TREE_VEC_ELT (list, 5);
+ if (init == error_mark_node)
+ init = DECL_INITIAL (TREE_VEC_ELT (list, 3));
+ OMP_CLAUSE_REDUCTION_INIT (c)
+ = c_clone_omp_udr (init, TREE_VEC_ELT (list, 4),
+ TREE_VEC_ELT (list, 3),
+ OMP_CLAUSE_DECL (c), placeholder);
+ if (TREE_VEC_ELT (list, 5) == error_mark_node)
+ OMP_CLAUSE_REDUCTION_INIT (c)
+ = build2 (INIT_EXPR, TREE_TYPE (t), t,
+ OMP_CLAUSE_REDUCTION_INIT (c));
+ if (walk_tree (&OMP_CLAUSE_REDUCTION_INIT (c),
+ c_find_omp_placeholder_r,
+ placeholder, NULL))
+ OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c) = 1;
+ }
+ else
+ {
+ tree init;
+ if (AGGREGATE_TYPE_P (TREE_TYPE (t)))
+ init = build_constructor (TREE_TYPE (t), NULL);
+ else
+ init = fold_convert (TREE_TYPE (t), integer_zero_node);
+ OMP_CLAUSE_REDUCTION_INIT (c)
+ = build2 (INIT_EXPR, TREE_TYPE (t), t, init);
}
+ OMP_CLAUSE_REDUCTION_INIT (c)
+ = build3_loc (OMP_CLAUSE_LOCATION (c), BIND_EXPR,
+ void_type_node, NULL_TREE,
+ OMP_CLAUSE_REDUCTION_INIT (c), NULL_TREE);
+ TREE_SIDE_EFFECTS (OMP_CLAUSE_REDUCTION_INIT (c)) = 1;
}
goto check_dup_generic;
case OMP_CLAUSE_COPYPRIVATE:
- name = "copyprivate";
+ copyprivate_seen = true;
+ if (nowait_clause)
+ {
+ error_at (OMP_CLAUSE_LOCATION (*nowait_clause),
+ "%<nowait%> clause must not be used together "
+ "with %<copyprivate%>");
+ *nowait_clause = OMP_CLAUSE_CHAIN (*nowait_clause);
+ nowait_clause = NULL;
+ }
goto check_dup_generic;
case OMP_CLAUSE_COPYIN:
- name = "copyin";
t = OMP_CLAUSE_DECL (c);
if (TREE_CODE (t) != VAR_DECL || !DECL_THREAD_LOCAL_P (t))
{
error_at (OMP_CLAUSE_LOCATION (c),
"%qE must be %<threadprivate%> for %<copyin%>", t);
remove = true;
+ break;
+ }
+ goto check_dup_generic;
+
+ case OMP_CLAUSE_LINEAR:
+ t = OMP_CLAUSE_DECL (c);
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (t))
+ && TREE_CODE (TREE_TYPE (t)) != POINTER_TYPE)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "linear clause applied to non-integral non-pointer "
+ "variable with type %qT", TREE_TYPE (t));
+ remove = true;
+ break;
+ }
+ if (TREE_CODE (TREE_TYPE (OMP_CLAUSE_DECL (c))) == POINTER_TYPE)
+ {
+ tree s = OMP_CLAUSE_LINEAR_STEP (c);
+ s = pointer_int_sum (OMP_CLAUSE_LOCATION (c), PLUS_EXPR,
+ OMP_CLAUSE_DECL (c), s);
+ s = fold_build2_loc (OMP_CLAUSE_LOCATION (c), MINUS_EXPR,
+ sizetype, s, OMP_CLAUSE_DECL (c));
+ if (s == error_mark_node)
+ s = size_one_node;
+ OMP_CLAUSE_LINEAR_STEP (c) = s;
}
goto check_dup_generic;
@@ -10798,7 +11832,8 @@ c_finish_omp_clauses (tree clauses)
if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL)
{
error_at (OMP_CLAUSE_LOCATION (c),
- "%qE is not a variable in clause %qs", t, name);
+ "%qE is not a variable in clause %qs", t,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
remove = true;
}
else if (bitmap_bit_p (&generic_head, DECL_UID (t))
@@ -10814,7 +11849,6 @@ c_finish_omp_clauses (tree clauses)
break;
case OMP_CLAUSE_FIRSTPRIVATE:
- name = "firstprivate";
t = OMP_CLAUSE_DECL (c);
need_complete = true;
need_implicitly_determined = true;
@@ -10836,7 +11870,6 @@ c_finish_omp_clauses (tree clauses)
break;
case OMP_CLAUSE_LASTPRIVATE:
- name = "lastprivate";
t = OMP_CLAUSE_DECL (c);
need_complete = true;
need_implicitly_determined = true;
@@ -10857,16 +11890,176 @@ c_finish_omp_clauses (tree clauses)
bitmap_set_bit (&lastprivate_head, DECL_UID (t));
break;
+ case OMP_CLAUSE_ALIGNED:
+ t = OMP_CLAUSE_DECL (c);
+ if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qE is not a variable in %<aligned%> clause", t);
+ remove = true;
+ }
+ else if (!POINTER_TYPE_P (TREE_TYPE (t))
+ && TREE_CODE (TREE_TYPE (t)) != ARRAY_TYPE)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qE in %<aligned%> clause is neither a pointer nor "
+ "an array", t);
+ remove = true;
+ }
+ else if (bitmap_bit_p (&aligned_head, DECL_UID (t)))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qE appears more than once in %<aligned%> clauses",
+ t);
+ remove = true;
+ }
+ else
+ bitmap_set_bit (&aligned_head, DECL_UID (t));
+ break;
+
+ case OMP_CLAUSE_DEPEND:
+ t = OMP_CLAUSE_DECL (c);
+ if (TREE_CODE (t) == TREE_LIST)
+ {
+ if (handle_omp_array_sections (c))
+ remove = true;
+ break;
+ }
+ if (t == error_mark_node)
+ remove = true;
+ else if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qE is not a variable in %<depend%> clause", t);
+ remove = true;
+ }
+ else if (!c_mark_addressable (t))
+ remove = true;
+ break;
+
+ case OMP_CLAUSE_MAP:
+ case OMP_CLAUSE_TO:
+ case OMP_CLAUSE_FROM:
+ t = OMP_CLAUSE_DECL (c);
+ if (TREE_CODE (t) == TREE_LIST)
+ {
+ if (handle_omp_array_sections (c))
+ remove = true;
+ else
+ {
+ t = OMP_CLAUSE_DECL (c);
+ if (!COMPLETE_TYPE_P (TREE_TYPE (t)))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "array section does not have mappable type "
+ "in %qs clause",
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ remove = true;
+ }
+ }
+ break;
+ }
+ if (t == error_mark_node)
+ remove = true;
+ else if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qE is not a variable in %qs clause", t,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ remove = true;
+ }
+ else if (TREE_CODE (t) == VAR_DECL && DECL_THREAD_LOCAL_P (t))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD is threadprivate variable in %qs clause", t,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ remove = true;
+ }
+ else if (!c_mark_addressable (t))
+ remove = true;
+ else if (!COMPLETE_TYPE_P (TREE_TYPE (t))
+ && !(OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
+ && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD does not have a mappable type in %qs clause", t,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ remove = true;
+ }
+ else if (bitmap_bit_p (&generic_head, DECL_UID (t)))
+ {
+ if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
+ error ("%qD appears more than once in motion clauses", t);
+ else
+ error ("%qD appears more than once in map clauses", t);
+ remove = true;
+ }
+ else
+ bitmap_set_bit (&generic_head, DECL_UID (t));
+ break;
+
+ case OMP_CLAUSE_UNIFORM:
+ t = OMP_CLAUSE_DECL (c);
+ if (TREE_CODE (t) != PARM_DECL)
+ {
+ if (DECL_P (t))
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD is not an argument in %<uniform%> clause", t);
+ else
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qE is not an argument in %<uniform%> clause", t);
+ remove = true;
+ break;
+ }
+ goto check_dup_generic;
+
+ case OMP_CLAUSE_NOWAIT:
+ if (copyprivate_seen)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<nowait%> clause must not be used together "
+ "with %<copyprivate%>");
+ remove = true;
+ break;
+ }
+ nowait_clause = pc;
+ pc = &OMP_CLAUSE_CHAIN (c);
+ continue;
+
case OMP_CLAUSE_IF:
case OMP_CLAUSE_NUM_THREADS:
+ case OMP_CLAUSE_NUM_TEAMS:
+ case OMP_CLAUSE_THREAD_LIMIT:
case OMP_CLAUSE_SCHEDULE:
- case OMP_CLAUSE_NOWAIT:
case OMP_CLAUSE_ORDERED:
case OMP_CLAUSE_DEFAULT:
case OMP_CLAUSE_UNTIED:
case OMP_CLAUSE_COLLAPSE:
case OMP_CLAUSE_FINAL:
case OMP_CLAUSE_MERGEABLE:
+ case OMP_CLAUSE_SAFELEN:
+ case OMP_CLAUSE_SIMDLEN:
+ case OMP_CLAUSE_DEVICE:
+ case OMP_CLAUSE_DIST_SCHEDULE:
+ case OMP_CLAUSE_PARALLEL:
+ case OMP_CLAUSE_FOR:
+ case OMP_CLAUSE_SECTIONS:
+ case OMP_CLAUSE_TASKGROUP:
+ case OMP_CLAUSE_PROC_BIND:
+ pc = &OMP_CLAUSE_CHAIN (c);
+ continue;
+
+ case OMP_CLAUSE_INBRANCH:
+ case OMP_CLAUSE_NOTINBRANCH:
+ if (branch_seen)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<inbranch%> clause is incompatible with "
+ "%<notinbranch%>");
+ remove = true;
+ break;
+ }
+ branch_seen = true;
pc = &OMP_CLAUSE_CHAIN (c);
continue;
@@ -10912,7 +12105,8 @@ c_finish_omp_clauses (tree clauses)
{
error_at (OMP_CLAUSE_LOCATION (c),
"%qE is predetermined %qs for %qs",
- t, share_name, name);
+ t, share_name,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
remove = true;
}
}
@@ -11016,3 +12210,205 @@ c_build_va_arg (location_t loc, tree expr, tree type)
"C++ requires promoted type, not enum type, in %<va_arg%>");
return build_va_arg (loc, expr, type);
}
+
+/* Return truthvalue of whether T1 is the same tree structure as T2.
+ Return 1 if they are the same. Return 0 if they are different. */
+
+bool
+c_tree_equal (tree t1, tree t2)
+{
+ enum tree_code code1, code2;
+
+ if (t1 == t2)
+ return true;
+ if (!t1 || !t2)
+ return false;
+
+ for (code1 = TREE_CODE (t1);
+ CONVERT_EXPR_CODE_P (code1)
+ || code1 == NON_LVALUE_EXPR;
+ code1 = TREE_CODE (t1))
+ t1 = TREE_OPERAND (t1, 0);
+ for (code2 = TREE_CODE (t2);
+ CONVERT_EXPR_CODE_P (code2)
+ || code2 == NON_LVALUE_EXPR;
+ code2 = TREE_CODE (t2))
+ t2 = TREE_OPERAND (t2, 0);
+
+ /* They might have become equal now. */
+ if (t1 == t2)
+ return true;
+
+ if (code1 != code2)
+ return false;
+
+ switch (code1)
+ {
+ case INTEGER_CST:
+ return TREE_INT_CST_LOW (t1) == TREE_INT_CST_LOW (t2)
+ && TREE_INT_CST_HIGH (t1) == TREE_INT_CST_HIGH (t2);
+
+ case REAL_CST:
+ return REAL_VALUES_EQUAL (TREE_REAL_CST (t1), TREE_REAL_CST (t2));
+
+ case STRING_CST:
+ return TREE_STRING_LENGTH (t1) == TREE_STRING_LENGTH (t2)
+ && !memcmp (TREE_STRING_POINTER (t1), TREE_STRING_POINTER (t2),
+ TREE_STRING_LENGTH (t1));
+
+ case FIXED_CST:
+ return FIXED_VALUES_IDENTICAL (TREE_FIXED_CST (t1),
+ TREE_FIXED_CST (t2));
+
+ case COMPLEX_CST:
+ return c_tree_equal (TREE_REALPART (t1), TREE_REALPART (t2))
+ && c_tree_equal (TREE_IMAGPART (t1), TREE_IMAGPART (t2));
+
+ case VECTOR_CST:
+ return operand_equal_p (t1, t2, OEP_ONLY_CONST);
+
+ case CONSTRUCTOR:
+ /* We need to do this when determining whether or not two
+ non-type pointer to member function template arguments
+ are the same. */
+ if (!comptypes (TREE_TYPE (t1), TREE_TYPE (t2))
+ || CONSTRUCTOR_NELTS (t1) != CONSTRUCTOR_NELTS (t2))
+ return false;
+ {
+ tree field, value;
+ unsigned int i;
+ FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (t1), i, field, value)
+ {
+ constructor_elt *elt2 = CONSTRUCTOR_ELT (t2, i);
+ if (!c_tree_equal (field, elt2->index)
+ || !c_tree_equal (value, elt2->value))
+ return false;
+ }
+ }
+ return true;
+
+ case TREE_LIST:
+ if (!c_tree_equal (TREE_PURPOSE (t1), TREE_PURPOSE (t2)))
+ return false;
+ if (!c_tree_equal (TREE_VALUE (t1), TREE_VALUE (t2)))
+ return false;
+ return c_tree_equal (TREE_CHAIN (t1), TREE_CHAIN (t2));
+
+ case SAVE_EXPR:
+ return c_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
+
+ case CALL_EXPR:
+ {
+ tree arg1, arg2;
+ call_expr_arg_iterator iter1, iter2;
+ if (!c_tree_equal (CALL_EXPR_FN (t1), CALL_EXPR_FN (t2)))
+ return false;
+ for (arg1 = first_call_expr_arg (t1, &iter1),
+ arg2 = first_call_expr_arg (t2, &iter2);
+ arg1 && arg2;
+ arg1 = next_call_expr_arg (&iter1),
+ arg2 = next_call_expr_arg (&iter2))
+ if (!c_tree_equal (arg1, arg2))
+ return false;
+ if (arg1 || arg2)
+ return false;
+ return true;
+ }
+
+ case TARGET_EXPR:
+ {
+ tree o1 = TREE_OPERAND (t1, 0);
+ tree o2 = TREE_OPERAND (t2, 0);
+
+ /* Special case: if either target is an unallocated VAR_DECL,
+ it means that it's going to be unified with whatever the
+ TARGET_EXPR is really supposed to initialize, so treat it
+ as being equivalent to anything. */
+ if (TREE_CODE (o1) == VAR_DECL && DECL_NAME (o1) == NULL_TREE
+ && !DECL_RTL_SET_P (o1))
+ /*Nop*/;
+ else if (TREE_CODE (o2) == VAR_DECL && DECL_NAME (o2) == NULL_TREE
+ && !DECL_RTL_SET_P (o2))
+ /*Nop*/;
+ else if (!c_tree_equal (o1, o2))
+ return false;
+
+ return c_tree_equal (TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1));
+ }
+
+ case COMPONENT_REF:
+ if (TREE_OPERAND (t1, 1) != TREE_OPERAND (t2, 1))
+ return false;
+ return c_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
+
+ case PARM_DECL:
+ case VAR_DECL:
+ case CONST_DECL:
+ case FIELD_DECL:
+ case FUNCTION_DECL:
+ case IDENTIFIER_NODE:
+ case SSA_NAME:
+ return false;
+
+ case TREE_VEC:
+ {
+ unsigned ix;
+ if (TREE_VEC_LENGTH (t1) != TREE_VEC_LENGTH (t2))
+ return false;
+ for (ix = TREE_VEC_LENGTH (t1); ix--;)
+ if (!c_tree_equal (TREE_VEC_ELT (t1, ix),
+ TREE_VEC_ELT (t2, ix)))
+ return false;
+ return true;
+ }
+
+ default:
+ break;
+ }
+
+ switch (TREE_CODE_CLASS (code1))
+ {
+ case tcc_unary:
+ case tcc_binary:
+ case tcc_comparison:
+ case tcc_expression:
+ case tcc_vl_exp:
+ case tcc_reference:
+ case tcc_statement:
+ {
+ int i, n = TREE_OPERAND_LENGTH (t1);
+
+ switch (code1)
+ {
+ case PREINCREMENT_EXPR:
+ case PREDECREMENT_EXPR:
+ case POSTINCREMENT_EXPR:
+ case POSTDECREMENT_EXPR:
+ n = 1;
+ break;
+ case ARRAY_REF:
+ n = 2;
+ break;
+ default:
+ break;
+ }
+
+ if (TREE_CODE_CLASS (code1) == tcc_vl_exp
+ && n != TREE_OPERAND_LENGTH (t2))
+ return false;
+
+ for (i = 0; i < n; ++i)
+ if (!c_tree_equal (TREE_OPERAND (t1, i), TREE_OPERAND (t2, i)))
+ return false;
+
+ return true;
+ }
+
+ case tcc_type:
+ return comptypes (t1, t2);
+ default:
+ gcc_unreachable ();
+ }
+ /* We can get here with --disable-checking. */
+ return false;
+}
diff --git a/gcc/calls.c b/gcc/calls.c
index 3930d5e170a..c04ed32801f 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -40,7 +40,6 @@ along with GCC; see the file COPYING3. If not see
#include "cgraph.h"
#include "except.h"
#include "dbgcnt.h"
-#include "tree-ssa.h"
/* Like PREFERRED_STACK_BOUNDARY but in units of bytes, not bits. */
#define STACK_BYTES (PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT)
@@ -635,11 +634,10 @@ gimple_alloca_call_p (const_gimple stmt)
bool
alloca_call_p (const_tree exp)
{
+ tree fndecl;
if (TREE_CODE (exp) == CALL_EXPR
- && TREE_CODE (CALL_EXPR_FN (exp)) == ADDR_EXPR
- && (TREE_CODE (TREE_OPERAND (CALL_EXPR_FN (exp), 0)) == FUNCTION_DECL)
- && (special_function_p (TREE_OPERAND (CALL_EXPR_FN (exp), 0), 0)
- & ECF_MAY_BE_ALLOCA))
+ && (fndecl = get_callee_fndecl (exp))
+ && (special_function_p (fndecl, 0) & ECF_MAY_BE_ALLOCA))
return true;
return false;
}
@@ -1026,7 +1024,7 @@ store_unaligned_arguments_into_pseudos (struct arg_data *args, int num_actuals)
int bitsize = MIN (bytes * BITS_PER_UNIT, BITS_PER_WORD);
args[i].aligned_regs[j] = reg;
- word = extract_bit_field (word, bitsize, 0, 1, false, NULL_RTX,
+ word = extract_bit_field (word, bitsize, 0, 1, NULL_RTX,
word_mode, word_mode);
/* There is no need to restrict this code to loading items
@@ -1732,7 +1730,8 @@ internal_arg_pointer_based_exp_scan (void)
if (val != NULL_RTX)
{
if (idx >= internal_arg_pointer_exp_state.cache.length ())
- internal_arg_pointer_exp_state.cache.safe_grow_cleared(idx + 1);
+ internal_arg_pointer_exp_state.cache
+ .safe_grow_cleared (idx + 1);
internal_arg_pointer_exp_state.cache[idx] = val;
}
}
diff --git a/gcc/cfganal.c b/gcc/cfganal.c
index c4ea7dd0a1f..b2216117227 100644
--- a/gcc/cfganal.c
+++ b/gcc/cfganal.c
@@ -389,18 +389,18 @@ control_dependences::find_control_dependence (int edge_index)
basic_block current_block;
basic_block ending_block;
- gcc_assert (INDEX_EDGE_PRED_BB (el, edge_index) != EXIT_BLOCK_PTR);
+ gcc_assert (INDEX_EDGE_PRED_BB (m_el, edge_index) != EXIT_BLOCK_PTR);
- if (INDEX_EDGE_PRED_BB (el, edge_index) == ENTRY_BLOCK_PTR)
+ if (INDEX_EDGE_PRED_BB (m_el, edge_index) == ENTRY_BLOCK_PTR)
ending_block = single_succ (ENTRY_BLOCK_PTR);
else
- ending_block = find_pdom (INDEX_EDGE_PRED_BB (el, edge_index));
+ ending_block = find_pdom (INDEX_EDGE_PRED_BB (m_el, edge_index));
- for (current_block = INDEX_EDGE_SUCC_BB (el, edge_index);
+ for (current_block = INDEX_EDGE_SUCC_BB (m_el, edge_index);
current_block != ending_block && current_block != EXIT_BLOCK_PTR;
current_block = find_pdom (current_block))
{
- edge e = INDEX_EDGE (el, edge_index);
+ edge e = INDEX_EDGE (m_el, edge_index);
/* For abnormal edges, we don't make current_block control
dependent because instructions that throw are always necessary
@@ -416,13 +416,13 @@ control_dependences::find_control_dependence (int edge_index)
list EL, ala Morgan, Section 3.6. */
control_dependences::control_dependences (struct edge_list *edges)
- : el (edges)
+ : m_el (edges)
{
timevar_push (TV_CONTROL_DEPENDENCES);
control_dependence_map.create (last_basic_block);
for (int i = 0; i < last_basic_block; ++i)
control_dependence_map.quick_push (BITMAP_ALLOC (NULL));
- for (int i = 0; i < NUM_EDGES (el); ++i)
+ for (int i = 0; i < NUM_EDGES (m_el); ++i)
find_control_dependence (i);
timevar_pop (TV_CONTROL_DEPENDENCES);
}
@@ -434,7 +434,7 @@ control_dependences::~control_dependences ()
for (unsigned i = 0; i < control_dependence_map.length (); ++i)
BITMAP_FREE (control_dependence_map[i]);
control_dependence_map.release ();
- free_edge_list (el);
+ free_edge_list (m_el);
}
/* Returns the bitmap of edges the basic-block I is dependent on. */
@@ -450,7 +450,7 @@ control_dependences::get_edges_dependent_on (int i)
edge
control_dependences::get_edge (int i)
{
- return INDEX_EDGE (el, i);
+ return INDEX_EDGE (m_el, i);
}
@@ -878,20 +878,22 @@ inverted_post_order_compute (int *post_order)
return post_order_num;
}
-/* Compute the depth first search order and store in the array
- PRE_ORDER if nonzero, marking the nodes visited in VISITED. If
- REV_POST_ORDER is nonzero, return the reverse completion number for each
- node. Returns the number of nodes visited. A depth first search
- tries to get as far away from the starting point as quickly as
- possible.
+/* Compute the depth first search order of FN and store in the array
+ PRE_ORDER if nonzero. If REV_POST_ORDER is nonzero, return the
+ reverse completion number for each node. Returns the number of nodes
+ visited. A depth first search tries to get as far away from the starting
+ point as quickly as possible.
- pre_order is a really a preorder numbering of the graph.
- rev_post_order is really a reverse postorder numbering of the graph.
- */
+ In case the function has unreachable blocks the number of nodes
+ visited does not include them.
+
+ pre_order is a really a preorder numbering of the graph.
+ rev_post_order is really a reverse postorder numbering of the graph. */
int
-pre_and_rev_post_order_compute (int *pre_order, int *rev_post_order,
- bool include_entry_exit)
+pre_and_rev_post_order_compute_fn (struct function *fn,
+ int *pre_order, int *rev_post_order,
+ bool include_entry_exit)
{
edge_iterator *stack;
int sp;
@@ -921,7 +923,7 @@ pre_and_rev_post_order_compute (int *pre_order, int *rev_post_order,
bitmap_clear (visited);
/* Push the first edge on to the stack. */
- stack[sp++] = ei_start (ENTRY_BLOCK_PTR->succs);
+ stack[sp++] = ei_start (ENTRY_BLOCK_PTR_FOR_FUNCTION (fn)->succs);
while (sp)
{
@@ -935,7 +937,8 @@ pre_and_rev_post_order_compute (int *pre_order, int *rev_post_order,
dest = ei_edge (ei)->dest;
/* Check if the edge destination has been visited yet. */
- if (dest != EXIT_BLOCK_PTR && ! bitmap_bit_p (visited, dest->index))
+ if (dest != EXIT_BLOCK_PTR_FOR_FUNCTION (fn)
+ && ! bitmap_bit_p (visited, dest->index))
{
/* Mark that we have visited the destination. */
bitmap_set_bit (visited, dest->index);
@@ -956,7 +959,8 @@ pre_and_rev_post_order_compute (int *pre_order, int *rev_post_order,
}
else
{
- if (ei_one_before_end_p (ei) && src != ENTRY_BLOCK_PTR
+ if (ei_one_before_end_p (ei)
+ && src != ENTRY_BLOCK_PTR_FOR_FUNCTION (fn)
&& rev_post_order)
/* There are no more successors for the SRC node
so assign its reverse completion number. */
@@ -979,9 +983,24 @@ pre_and_rev_post_order_compute (int *pre_order, int *rev_post_order,
pre_order_num++;
if (rev_post_order)
rev_post_order[rev_post_order_num--] = EXIT_BLOCK;
- /* The number of nodes visited should be the number of blocks. */
- gcc_assert (pre_order_num == n_basic_blocks);
}
+
+ return pre_order_num;
+}
+
+/* Like pre_and_rev_post_order_compute_fn but operating on the
+ current function and asserting that all nodes were visited. */
+
+int
+pre_and_rev_post_order_compute (int *pre_order, int *rev_post_order,
+ bool include_entry_exit)
+{
+ int pre_order_num
+ = pre_and_rev_post_order_compute_fn (cfun, pre_order, rev_post_order,
+ include_entry_exit);
+ if (include_entry_exit)
+ /* The number of nodes visited should be the number of blocks. */
+ gcc_assert (pre_order_num == n_basic_blocks);
else
/* The number of nodes visited should be the number of blocks minus
the entry and exit blocks which are not visited here. */
@@ -1465,3 +1484,56 @@ bitmap_union_of_preds (sbitmap dst, sbitmap *src, basic_block b)
*r++ |= *p++;
}
}
+
+/* Returns the list of basic blocks in the function in an order that guarantees
+ that if a block X has just a single predecessor Y, then Y is after X in the
+ ordering. */
+
+basic_block *
+single_pred_before_succ_order (void)
+{
+ basic_block x, y;
+ basic_block *order = XNEWVEC (basic_block, n_basic_blocks);
+ unsigned n = n_basic_blocks - NUM_FIXED_BLOCKS;
+ unsigned np, i;
+ sbitmap visited = sbitmap_alloc (last_basic_block);
+
+#define MARK_VISITED(BB) (bitmap_set_bit (visited, (BB)->index))
+#define VISITED_P(BB) (bitmap_bit_p (visited, (BB)->index))
+
+ bitmap_clear (visited);
+
+ MARK_VISITED (ENTRY_BLOCK_PTR);
+ FOR_EACH_BB (x)
+ {
+ if (VISITED_P (x))
+ continue;
+
+ /* Walk the predecessors of x as long as they have precisely one
+ predecessor and add them to the list, so that they get stored
+ after x. */
+ for (y = x, np = 1;
+ single_pred_p (y) && !VISITED_P (single_pred (y));
+ y = single_pred (y))
+ np++;
+ for (y = x, i = n - np;
+ single_pred_p (y) && !VISITED_P (single_pred (y));
+ y = single_pred (y), i++)
+ {
+ order[i] = y;
+ MARK_VISITED (y);
+ }
+ order[i] = y;
+ MARK_VISITED (y);
+
+ gcc_assert (i == n - 1);
+ n -= np;
+ }
+
+ sbitmap_free (visited);
+ gcc_assert (n == 0);
+ return order;
+
+#undef MARK_VISITED
+#undef VISITED_P
+}
diff --git a/gcc/cfgbuild.c b/gcc/cfgbuild.c
index ac6aefb86df..a9ed5f14b17 100644
--- a/gcc/cfgbuild.c
+++ b/gcc/cfgbuild.c
@@ -542,7 +542,7 @@ compute_outgoing_frequencies (basic_block b)
if (note)
{
- probability = INTVAL (XEXP (note, 0));
+ probability = XINT (note, 0);
e = BRANCH_EDGE (b);
e->probability = probability;
e->count = apply_probability (b->count, probability);
diff --git a/gcc/cfgcleanup.c b/gcc/cfgcleanup.c
index e88fe2ed500..51611907368 100644
--- a/gcc/cfgcleanup.c
+++ b/gcc/cfgcleanup.c
@@ -34,6 +34,7 @@ along with GCC; see the file COPYING3. If not see
#include "coretypes.h"
#include "tm.h"
#include "rtl.h"
+#include "tree.h"
#include "hard-reg-set.h"
#include "regs.h"
#include "insn-config.h"
@@ -3089,8 +3090,8 @@ const pass_data pass_data_jump =
class pass_jump : public rtl_opt_pass
{
public:
- pass_jump(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_jump, ctxt)
+ pass_jump (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_jump, ctxt)
{}
/* opt_pass methods: */
@@ -3133,8 +3134,8 @@ const pass_data pass_data_jump2 =
class pass_jump2 : public rtl_opt_pass
{
public:
- pass_jump2(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_jump2, ctxt)
+ pass_jump2 (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_jump2, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index 88e48c2a342..4e622c0b9a0 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -21,13 +21,23 @@ along with GCC; see the file COPYING3. If not see
#include "system.h"
#include "coretypes.h"
#include "tm.h"
-#include "tree.h"
#include "rtl.h"
+#include "hard-reg-set.h"
+#include "tree.h"
#include "tm_p.h"
#include "basic-block.h"
#include "function.h"
#include "expr.h"
#include "langhooks.h"
+#include "bitmap.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "cgraph.h"
+#include "tree-cfg.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
+#include "tree-dfa.h"
#include "tree-ssa.h"
#include "tree-pass.h"
#include "except.h"
@@ -40,13 +50,24 @@ along with GCC; see the file COPYING3. If not see
#include "tree-inline.h"
#include "value-prof.h"
#include "target.h"
-#include "ssaexpand.h"
-#include "bitmap.h"
+#include "tree-ssa-live.h"
+#include "tree-outof-ssa.h"
#include "sbitmap.h"
#include "cfgloop.h"
#include "regs.h" /* For reg_renumber. */
#include "insn-attr.h" /* For INSN_SCHEDULING. */
#include "asan.h"
+#include "tree-ssa-address.h"
+#include "recog.h"
+#include "output.h"
+
+/* Some systems use __main in a way incompatible with its use in gcc, in these
+ cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
+ give the same symbol without quotes for an alternative entry point. You
+ must define both, or neither. */
+#ifndef NAME__MAIN
+#define NAME__MAIN "__main"
+#endif
/* This variable holds information helping the rewriting of SSA trees
into RTL. */
@@ -569,7 +590,7 @@ add_partitioned_vars_to_ptset (struct pt_solution *pt,
|| pt->vars == NULL
/* The pointed-to vars bitmap is shared, it is enough to
visit it once. */
- || pointer_set_insert(visited, pt->vars))
+ || pointer_set_insert (visited, pt->vars))
return;
bitmap_clear (temp);
@@ -1131,7 +1152,9 @@ defer_stack_allocation (tree var, bool toplevel)
other hand, we don't want the function's stack frame size to
get completely out of hand. So we avoid adding scalars and
"small" aggregates to the list at all. */
- if (optimize == 0 && tree_low_cst (DECL_SIZE_UNIT (var), 1) < 32)
+ if (optimize == 0
+ && (tree_low_cst (DECL_SIZE_UNIT (var), 1)
+ < PARAM_VALUE (PARAM_MIN_SIZE_FOR_STACK_SHARING)))
return false;
return true;
@@ -1184,7 +1207,7 @@ expand_one_var (tree var, bool toplevel, bool really_expand)
{
/* stack_alignment_estimated shouldn't change after stack
realign decision made */
- gcc_assert(!crtl->stack_realign_processed);
+ gcc_assert (!crtl->stack_realign_processed);
crtl->stack_alignment_estimated = align;
}
@@ -1497,7 +1520,7 @@ estimated_stack_frame_size (struct cgraph_node *node)
HOST_WIDE_INT size = 0;
size_t i;
tree var;
- struct function *fn = DECL_STRUCT_FUNCTION (node->symbol.decl);
+ struct function *fn = DECL_STRUCT_FUNCTION (node->decl);
push_cfun (fn);
@@ -1723,7 +1746,7 @@ expand_used_vars (void)
case SPCT_FLAG_DEFAULT:
if (cfun->calls_alloca || has_protected_decls)
- create_stack_guard();
+ create_stack_guard ();
break;
default:
@@ -1770,7 +1793,7 @@ expand_used_vars (void)
var_end_seq
= asan_emit_stack_protection (virtual_stack_vars_rtx,
data.asan_vec.address (),
- data.asan_decl_vec. address(),
+ data.asan_decl_vec. address (),
data.asan_vec.length ());
}
@@ -2182,6 +2205,866 @@ expand_call_stmt (gimple stmt)
mark_transaction_restart_calls (stmt);
}
+
+/* Generate RTL for an asm statement (explicit assembler code).
+ STRING is a STRING_CST node containing the assembler code text,
+ or an ADDR_EXPR containing a STRING_CST. VOL nonzero means the
+ insn is volatile; don't optimize it. */
+
+static void
+expand_asm_loc (tree string, int vol, location_t locus)
+{
+ rtx body;
+
+ if (TREE_CODE (string) == ADDR_EXPR)
+ string = TREE_OPERAND (string, 0);
+
+ body = gen_rtx_ASM_INPUT_loc (VOIDmode,
+ ggc_strdup (TREE_STRING_POINTER (string)),
+ locus);
+
+ MEM_VOLATILE_P (body) = vol;
+
+ emit_insn (body);
+}
+
+/* Return the number of times character C occurs in string S. */
+static int
+n_occurrences (int c, const char *s)
+{
+ int n = 0;
+ while (*s)
+ n += (*s++ == c);
+ return n;
+}
+
+/* A subroutine of expand_asm_operands. Check that all operands have
+ the same number of alternatives. Return true if so. */
+
+static bool
+check_operand_nalternatives (tree outputs, tree inputs)
+{
+ if (outputs || inputs)
+ {
+ tree tmp = TREE_PURPOSE (outputs ? outputs : inputs);
+ int nalternatives
+ = n_occurrences (',', TREE_STRING_POINTER (TREE_VALUE (tmp)));
+ tree next = inputs;
+
+ if (nalternatives + 1 > MAX_RECOG_ALTERNATIVES)
+ {
+ error ("too many alternatives in %<asm%>");
+ return false;
+ }
+
+ tmp = outputs;
+ while (tmp)
+ {
+ const char *constraint
+ = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (tmp)));
+
+ if (n_occurrences (',', constraint) != nalternatives)
+ {
+ error ("operand constraints for %<asm%> differ "
+ "in number of alternatives");
+ return false;
+ }
+
+ if (TREE_CHAIN (tmp))
+ tmp = TREE_CHAIN (tmp);
+ else
+ tmp = next, next = 0;
+ }
+ }
+
+ return true;
+}
+
+/* Check for overlap between registers marked in CLOBBERED_REGS and
+ anything inappropriate in T. Emit error and return the register
+ variable definition for error, NULL_TREE for ok. */
+
+static bool
+tree_conflicts_with_clobbers_p (tree t, HARD_REG_SET *clobbered_regs)
+{
+ /* Conflicts between asm-declared register variables and the clobber
+ list are not allowed. */
+ tree overlap = tree_overlaps_hard_reg_set (t, clobbered_regs);
+
+ if (overlap)
+ {
+ error ("asm-specifier for variable %qE conflicts with asm clobber list",
+ DECL_NAME (overlap));
+
+ /* Reset registerness to stop multiple errors emitted for a single
+ variable. */
+ DECL_REGISTER (overlap) = 0;
+ return true;
+ }
+
+ return false;
+}
+
+/* Generate RTL for an asm statement with arguments.
+ STRING is the instruction template.
+ OUTPUTS is a list of output arguments (lvalues); INPUTS a list of inputs.
+ Each output or input has an expression in the TREE_VALUE and
+ a tree list in TREE_PURPOSE which in turn contains a constraint
+ name in TREE_VALUE (or NULL_TREE) and a constraint string
+ in TREE_PURPOSE.
+ CLOBBERS is a list of STRING_CST nodes each naming a hard register
+ that is clobbered by this insn.
+
+ LABELS is a list of labels, and if LABELS is non-NULL, FALLTHRU_BB
+ should be the fallthru basic block of the asm goto.
+
+ Not all kinds of lvalue that may appear in OUTPUTS can be stored directly.
+ Some elements of OUTPUTS may be replaced with trees representing temporary
+ values. The caller should copy those temporary values to the originally
+ specified lvalues.
+
+ VOL nonzero means the insn is volatile; don't optimize it. */
+
+static void
+expand_asm_operands (tree string, tree outputs, tree inputs,
+ tree clobbers, tree labels, basic_block fallthru_bb,
+ int vol, location_t locus)
+{
+ rtvec argvec, constraintvec, labelvec;
+ rtx body;
+ int ninputs = list_length (inputs);
+ int noutputs = list_length (outputs);
+ int nlabels = list_length (labels);
+ int ninout;
+ int nclobbers;
+ HARD_REG_SET clobbered_regs;
+ int clobber_conflict_found = 0;
+ tree tail;
+ tree t;
+ int i;
+ /* Vector of RTX's of evaluated output operands. */
+ rtx *output_rtx = XALLOCAVEC (rtx, noutputs);
+ int *inout_opnum = XALLOCAVEC (int, noutputs);
+ rtx *real_output_rtx = XALLOCAVEC (rtx, noutputs);
+ enum machine_mode *inout_mode = XALLOCAVEC (enum machine_mode, noutputs);
+ const char **constraints = XALLOCAVEC (const char *, noutputs + ninputs);
+ int old_generating_concat_p = generating_concat_p;
+ rtx fallthru_label = NULL_RTX;
+
+ /* An ASM with no outputs needs to be treated as volatile, for now. */
+ if (noutputs == 0)
+ vol = 1;
+
+ if (! check_operand_nalternatives (outputs, inputs))
+ return;
+
+ string = resolve_asm_operand_names (string, outputs, inputs, labels);
+
+ /* Collect constraints. */
+ i = 0;
+ for (t = outputs; t ; t = TREE_CHAIN (t), i++)
+ constraints[i] = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t)));
+ for (t = inputs; t ; t = TREE_CHAIN (t), i++)
+ constraints[i] = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t)));
+
+ /* Sometimes we wish to automatically clobber registers across an asm.
+ Case in point is when the i386 backend moved from cc0 to a hard reg --
+ maintaining source-level compatibility means automatically clobbering
+ the flags register. */
+ clobbers = targetm.md_asm_clobbers (outputs, inputs, clobbers);
+
+ /* Count the number of meaningful clobbered registers, ignoring what
+ we would ignore later. */
+ nclobbers = 0;
+ CLEAR_HARD_REG_SET (clobbered_regs);
+ for (tail = clobbers; tail; tail = TREE_CHAIN (tail))
+ {
+ const char *regname;
+ int nregs;
+
+ if (TREE_VALUE (tail) == error_mark_node)
+ return;
+ regname = TREE_STRING_POINTER (TREE_VALUE (tail));
+
+ i = decode_reg_name_and_count (regname, &nregs);
+ if (i == -4)
+ ++nclobbers;
+ else if (i == -2)
+ error ("unknown register name %qs in %<asm%>", regname);
+
+ /* Mark clobbered registers. */
+ if (i >= 0)
+ {
+ int reg;
+
+ for (reg = i; reg < i + nregs; reg++)
+ {
+ ++nclobbers;
+
+ /* Clobbering the PIC register is an error. */
+ if (reg == (int) PIC_OFFSET_TABLE_REGNUM)
+ {
+ error ("PIC register clobbered by %qs in %<asm%>", regname);
+ return;
+ }
+
+ SET_HARD_REG_BIT (clobbered_regs, reg);
+ }
+ }
+ }
+
+ /* First pass over inputs and outputs checks validity and sets
+ mark_addressable if needed. */
+
+ ninout = 0;
+ for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
+ {
+ tree val = TREE_VALUE (tail);
+ tree type = TREE_TYPE (val);
+ const char *constraint;
+ bool is_inout;
+ bool allows_reg;
+ bool allows_mem;
+
+ /* If there's an erroneous arg, emit no insn. */
+ if (type == error_mark_node)
+ return;
+
+ /* Try to parse the output constraint. If that fails, there's
+ no point in going further. */
+ constraint = constraints[i];
+ if (!parse_output_constraint (&constraint, i, ninputs, noutputs,
+ &allows_mem, &allows_reg, &is_inout))
+ return;
+
+ if (! allows_reg
+ && (allows_mem
+ || is_inout
+ || (DECL_P (val)
+ && REG_P (DECL_RTL (val))
+ && GET_MODE (DECL_RTL (val)) != TYPE_MODE (type))))
+ mark_addressable (val);
+
+ if (is_inout)
+ ninout++;
+ }
+
+ ninputs += ninout;
+ if (ninputs + noutputs > MAX_RECOG_OPERANDS)
+ {
+ error ("more than %d operands in %<asm%>", MAX_RECOG_OPERANDS);
+ return;
+ }
+
+ for (i = 0, tail = inputs; tail; i++, tail = TREE_CHAIN (tail))
+ {
+ bool allows_reg, allows_mem;
+ const char *constraint;
+
+ /* If there's an erroneous arg, emit no insn, because the ASM_INPUT
+ would get VOIDmode and that could cause a crash in reload. */
+ if (TREE_TYPE (TREE_VALUE (tail)) == error_mark_node)
+ return;
+
+ constraint = constraints[i + noutputs];
+ if (! parse_input_constraint (&constraint, i, ninputs, noutputs, ninout,
+ constraints, &allows_mem, &allows_reg))
+ return;
+
+ if (! allows_reg && allows_mem)
+ mark_addressable (TREE_VALUE (tail));
+ }
+
+ /* Second pass evaluates arguments. */
+
+ /* Make sure stack is consistent for asm goto. */
+ if (nlabels > 0)
+ do_pending_stack_adjust ();
+
+ ninout = 0;
+ for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
+ {
+ tree val = TREE_VALUE (tail);
+ tree type = TREE_TYPE (val);
+ bool is_inout;
+ bool allows_reg;
+ bool allows_mem;
+ rtx op;
+ bool ok;
+
+ ok = parse_output_constraint (&constraints[i], i, ninputs,
+ noutputs, &allows_mem, &allows_reg,
+ &is_inout);
+ gcc_assert (ok);
+
+ /* If an output operand is not a decl or indirect ref and our constraint
+ allows a register, make a temporary to act as an intermediate.
+ Make the asm insn write into that, then our caller will copy it to
+ the real output operand. Likewise for promoted variables. */
+
+ generating_concat_p = 0;
+
+ real_output_rtx[i] = NULL_RTX;
+ if ((TREE_CODE (val) == INDIRECT_REF
+ && allows_mem)
+ || (DECL_P (val)
+ && (allows_mem || REG_P (DECL_RTL (val)))
+ && ! (REG_P (DECL_RTL (val))
+ && GET_MODE (DECL_RTL (val)) != TYPE_MODE (type)))
+ || ! allows_reg
+ || is_inout)
+ {
+ op = expand_expr (val, NULL_RTX, VOIDmode,
+ !allows_reg ? EXPAND_MEMORY : EXPAND_WRITE);
+ if (MEM_P (op))
+ op = validize_mem (op);
+
+ if (! allows_reg && !MEM_P (op))
+ error ("output number %d not directly addressable", i);
+ if ((! allows_mem && MEM_P (op))
+ || GET_CODE (op) == CONCAT)
+ {
+ real_output_rtx[i] = op;
+ op = gen_reg_rtx (GET_MODE (op));
+ if (is_inout)
+ emit_move_insn (op, real_output_rtx[i]);
+ }
+ }
+ else
+ {
+ op = assign_temp (type, 0, 1);
+ op = validize_mem (op);
+ if (!MEM_P (op) && TREE_CODE (TREE_VALUE (tail)) == SSA_NAME)
+ set_reg_attrs_for_decl_rtl (SSA_NAME_VAR (TREE_VALUE (tail)), op);
+ TREE_VALUE (tail) = make_tree (type, op);
+ }
+ output_rtx[i] = op;
+
+ generating_concat_p = old_generating_concat_p;
+
+ if (is_inout)
+ {
+ inout_mode[ninout] = TYPE_MODE (type);
+ inout_opnum[ninout++] = i;
+ }
+
+ if (tree_conflicts_with_clobbers_p (val, &clobbered_regs))
+ clobber_conflict_found = 1;
+ }
+
+ /* Make vectors for the expression-rtx, constraint strings,
+ and named operands. */
+
+ argvec = rtvec_alloc (ninputs);
+ constraintvec = rtvec_alloc (ninputs);
+ labelvec = rtvec_alloc (nlabels);
+
+ body = gen_rtx_ASM_OPERANDS ((noutputs == 0 ? VOIDmode
+ : GET_MODE (output_rtx[0])),
+ ggc_strdup (TREE_STRING_POINTER (string)),
+ empty_string, 0, argvec, constraintvec,
+ labelvec, locus);
+
+ MEM_VOLATILE_P (body) = vol;
+
+ /* Eval the inputs and put them into ARGVEC.
+ Put their constraints into ASM_INPUTs and store in CONSTRAINTS. */
+
+ for (i = 0, tail = inputs; tail; tail = TREE_CHAIN (tail), ++i)
+ {
+ bool allows_reg, allows_mem;
+ const char *constraint;
+ tree val, type;
+ rtx op;
+ bool ok;
+
+ constraint = constraints[i + noutputs];
+ ok = parse_input_constraint (&constraint, i, ninputs, noutputs, ninout,
+ constraints, &allows_mem, &allows_reg);
+ gcc_assert (ok);
+
+ generating_concat_p = 0;
+
+ val = TREE_VALUE (tail);
+ type = TREE_TYPE (val);
+ /* EXPAND_INITIALIZER will not generate code for valid initializer
+ constants, but will still generate code for other types of operand.
+ This is the behavior we want for constant constraints. */
+ op = expand_expr (val, NULL_RTX, VOIDmode,
+ allows_reg ? EXPAND_NORMAL
+ : allows_mem ? EXPAND_MEMORY
+ : EXPAND_INITIALIZER);
+
+ /* Never pass a CONCAT to an ASM. */
+ if (GET_CODE (op) == CONCAT)
+ op = force_reg (GET_MODE (op), op);
+ else if (MEM_P (op))
+ op = validize_mem (op);
+
+ if (asm_operand_ok (op, constraint, NULL) <= 0)
+ {
+ if (allows_reg && TYPE_MODE (type) != BLKmode)
+ op = force_reg (TYPE_MODE (type), op);
+ else if (!allows_mem)
+ warning (0, "asm operand %d probably doesn%'t match constraints",
+ i + noutputs);
+ else if (MEM_P (op))
+ {
+ /* We won't recognize either volatile memory or memory
+ with a queued address as available a memory_operand
+ at this point. Ignore it: clearly this *is* a memory. */
+ }
+ else
+ gcc_unreachable ();
+ }
+
+ generating_concat_p = old_generating_concat_p;
+ ASM_OPERANDS_INPUT (body, i) = op;
+
+ ASM_OPERANDS_INPUT_CONSTRAINT_EXP (body, i)
+ = gen_rtx_ASM_INPUT (TYPE_MODE (type),
+ ggc_strdup (constraints[i + noutputs]));
+
+ if (tree_conflicts_with_clobbers_p (val, &clobbered_regs))
+ clobber_conflict_found = 1;
+ }
+
+ /* Protect all the operands from the queue now that they have all been
+ evaluated. */
+
+ generating_concat_p = 0;
+
+ /* For in-out operands, copy output rtx to input rtx. */
+ for (i = 0; i < ninout; i++)
+ {
+ int j = inout_opnum[i];
+ char buffer[16];
+
+ ASM_OPERANDS_INPUT (body, ninputs - ninout + i)
+ = output_rtx[j];
+
+ sprintf (buffer, "%d", j);
+ ASM_OPERANDS_INPUT_CONSTRAINT_EXP (body, ninputs - ninout + i)
+ = gen_rtx_ASM_INPUT (inout_mode[i], ggc_strdup (buffer));
+ }
+
+ /* Copy labels to the vector. */
+ for (i = 0, tail = labels; i < nlabels; ++i, tail = TREE_CHAIN (tail))
+ {
+ rtx r;
+ /* If asm goto has any labels in the fallthru basic block, use
+ a label that we emit immediately after the asm goto. Expansion
+ may insert further instructions into the same basic block after
+ asm goto and if we don't do this, insertion of instructions on
+ the fallthru edge might misbehave. See PR58670. */
+ if (fallthru_bb
+ && label_to_block_fn (cfun, TREE_VALUE (tail)) == fallthru_bb)
+ {
+ if (fallthru_label == NULL_RTX)
+ fallthru_label = gen_label_rtx ();
+ r = fallthru_label;
+ }
+ else
+ r = label_rtx (TREE_VALUE (tail));
+ ASM_OPERANDS_LABEL (body, i) = gen_rtx_LABEL_REF (Pmode, r);
+ }
+
+ generating_concat_p = old_generating_concat_p;
+
+ /* Now, for each output, construct an rtx
+ (set OUTPUT (asm_operands INSN OUTPUTCONSTRAINT OUTPUTNUMBER
+ ARGVEC CONSTRAINTS OPNAMES))
+ If there is more than one, put them inside a PARALLEL. */
+
+ if (nlabels > 0 && nclobbers == 0)
+ {
+ gcc_assert (noutputs == 0);
+ emit_jump_insn (body);
+ }
+ else if (noutputs == 0 && nclobbers == 0)
+ {
+ /* No output operands: put in a raw ASM_OPERANDS rtx. */
+ emit_insn (body);
+ }
+ else if (noutputs == 1 && nclobbers == 0)
+ {
+ ASM_OPERANDS_OUTPUT_CONSTRAINT (body) = ggc_strdup (constraints[0]);
+ emit_insn (gen_rtx_SET (VOIDmode, output_rtx[0], body));
+ }
+ else
+ {
+ rtx obody = body;
+ int num = noutputs;
+
+ if (num == 0)
+ num = 1;
+
+ body = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (num + nclobbers));
+
+ /* For each output operand, store a SET. */
+ for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
+ {
+ XVECEXP (body, 0, i)
+ = gen_rtx_SET (VOIDmode,
+ output_rtx[i],
+ gen_rtx_ASM_OPERANDS
+ (GET_MODE (output_rtx[i]),
+ ggc_strdup (TREE_STRING_POINTER (string)),
+ ggc_strdup (constraints[i]),
+ i, argvec, constraintvec, labelvec, locus));
+
+ MEM_VOLATILE_P (SET_SRC (XVECEXP (body, 0, i))) = vol;
+ }
+
+ /* If there are no outputs (but there are some clobbers)
+ store the bare ASM_OPERANDS into the PARALLEL. */
+
+ if (i == 0)
+ XVECEXP (body, 0, i++) = obody;
+
+ /* Store (clobber REG) for each clobbered register specified. */
+
+ for (tail = clobbers; tail; tail = TREE_CHAIN (tail))
+ {
+ const char *regname = TREE_STRING_POINTER (TREE_VALUE (tail));
+ int reg, nregs;
+ int j = decode_reg_name_and_count (regname, &nregs);
+ rtx clobbered_reg;
+
+ if (j < 0)
+ {
+ if (j == -3) /* `cc', which is not a register */
+ continue;
+
+ if (j == -4) /* `memory', don't cache memory across asm */
+ {
+ XVECEXP (body, 0, i++)
+ = gen_rtx_CLOBBER (VOIDmode,
+ gen_rtx_MEM
+ (BLKmode,
+ gen_rtx_SCRATCH (VOIDmode)));
+ continue;
+ }
+
+ /* Ignore unknown register, error already signaled. */
+ continue;
+ }
+
+ for (reg = j; reg < j + nregs; reg++)
+ {
+ /* Use QImode since that's guaranteed to clobber just
+ * one reg. */
+ clobbered_reg = gen_rtx_REG (QImode, reg);
+
+ /* Do sanity check for overlap between clobbers and
+ respectively input and outputs that hasn't been
+ handled. Such overlap should have been detected and
+ reported above. */
+ if (!clobber_conflict_found)
+ {
+ int opno;
+
+ /* We test the old body (obody) contents to avoid
+ tripping over the under-construction body. */
+ for (opno = 0; opno < noutputs; opno++)
+ if (reg_overlap_mentioned_p (clobbered_reg,
+ output_rtx[opno]))
+ internal_error
+ ("asm clobber conflict with output operand");
+
+ for (opno = 0; opno < ninputs - ninout; opno++)
+ if (reg_overlap_mentioned_p (clobbered_reg,
+ ASM_OPERANDS_INPUT (obody,
+ opno)))
+ internal_error
+ ("asm clobber conflict with input operand");
+ }
+
+ XVECEXP (body, 0, i++)
+ = gen_rtx_CLOBBER (VOIDmode, clobbered_reg);
+ }
+ }
+
+ if (nlabels > 0)
+ emit_jump_insn (body);
+ else
+ emit_insn (body);
+ }
+
+ if (fallthru_label)
+ emit_label (fallthru_label);
+
+ /* For any outputs that needed reloading into registers, spill them
+ back to where they belong. */
+ for (i = 0; i < noutputs; ++i)
+ if (real_output_rtx[i])
+ emit_move_insn (real_output_rtx[i], output_rtx[i]);
+
+ crtl->has_asm_statement = 1;
+ free_temp_slots ();
+}
+
+
+static void
+expand_asm_stmt (gimple stmt)
+{
+ int noutputs;
+ tree outputs, tail, t;
+ tree *o;
+ size_t i, n;
+ const char *s;
+ tree str, out, in, cl, labels;
+ location_t locus = gimple_location (stmt);
+ basic_block fallthru_bb = NULL;
+
+ /* Meh... convert the gimple asm operands into real tree lists.
+ Eventually we should make all routines work on the vectors instead
+ of relying on TREE_CHAIN. */
+ out = NULL_TREE;
+ n = gimple_asm_noutputs (stmt);
+ if (n > 0)
+ {
+ t = out = gimple_asm_output_op (stmt, 0);
+ for (i = 1; i < n; i++)
+ t = TREE_CHAIN (t) = gimple_asm_output_op (stmt, i);
+ }
+
+ in = NULL_TREE;
+ n = gimple_asm_ninputs (stmt);
+ if (n > 0)
+ {
+ t = in = gimple_asm_input_op (stmt, 0);
+ for (i = 1; i < n; i++)
+ t = TREE_CHAIN (t) = gimple_asm_input_op (stmt, i);
+ }
+
+ cl = NULL_TREE;
+ n = gimple_asm_nclobbers (stmt);
+ if (n > 0)
+ {
+ t = cl = gimple_asm_clobber_op (stmt, 0);
+ for (i = 1; i < n; i++)
+ t = TREE_CHAIN (t) = gimple_asm_clobber_op (stmt, i);
+ }
+
+ labels = NULL_TREE;
+ n = gimple_asm_nlabels (stmt);
+ if (n > 0)
+ {
+ edge fallthru = find_fallthru_edge (gimple_bb (stmt)->succs);
+ if (fallthru)
+ fallthru_bb = fallthru->dest;
+ t = labels = gimple_asm_label_op (stmt, 0);
+ for (i = 1; i < n; i++)
+ t = TREE_CHAIN (t) = gimple_asm_label_op (stmt, i);
+ }
+
+ s = gimple_asm_string (stmt);
+ str = build_string (strlen (s), s);
+
+ if (gimple_asm_input_p (stmt))
+ {
+ expand_asm_loc (str, gimple_asm_volatile_p (stmt), locus);
+ return;
+ }
+
+ outputs = out;
+ noutputs = gimple_asm_noutputs (stmt);
+ /* o[I] is the place that output number I should be written. */
+ o = (tree *) alloca (noutputs * sizeof (tree));
+
+ /* Record the contents of OUTPUTS before it is modified. */
+ for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
+ o[i] = TREE_VALUE (tail);
+
+ /* Generate the ASM_OPERANDS insn; store into the TREE_VALUEs of
+ OUTPUTS some trees for where the values were actually stored. */
+ expand_asm_operands (str, outputs, in, cl, labels, fallthru_bb,
+ gimple_asm_volatile_p (stmt), locus);
+
+ /* Copy all the intermediate outputs into the specified outputs. */
+ for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
+ {
+ if (o[i] != TREE_VALUE (tail))
+ {
+ expand_assignment (o[i], TREE_VALUE (tail), false);
+ free_temp_slots ();
+
+ /* Restore the original value so that it's correct the next
+ time we expand this function. */
+ TREE_VALUE (tail) = o[i];
+ }
+ }
+}
+
+/* Emit code to jump to the address
+ specified by the pointer expression EXP. */
+
+static void
+expand_computed_goto (tree exp)
+{
+ rtx x = expand_normal (exp);
+
+ x = convert_memory_address (Pmode, x);
+
+ do_pending_stack_adjust ();
+ emit_indirect_jump (x);
+}
+
+/* Generate RTL code for a `goto' statement with target label LABEL.
+ LABEL should be a LABEL_DECL tree node that was or will later be
+ defined with `expand_label'. */
+
+static void
+expand_goto (tree label)
+{
+#ifdef ENABLE_CHECKING
+ /* Check for a nonlocal goto to a containing function. Should have
+ gotten translated to __builtin_nonlocal_goto. */
+ tree context = decl_function_context (label);
+ gcc_assert (!context || context == current_function_decl);
+#endif
+
+ emit_jump (label_rtx (label));
+}
+
+/* Output a return with no value. */
+
+static void
+expand_null_return_1 (void)
+{
+ clear_pending_stack_adjust ();
+ do_pending_stack_adjust ();
+ emit_jump (return_label);
+}
+
+/* Generate RTL to return from the current function, with no value.
+ (That is, we do not do anything about returning any value.) */
+
+void
+expand_null_return (void)
+{
+ /* If this function was declared to return a value, but we
+ didn't, clobber the return registers so that they are not
+ propagated live to the rest of the function. */
+ clobber_return_register ();
+
+ expand_null_return_1 ();
+}
+
+/* Generate RTL to return from the current function, with value VAL. */
+
+static void
+expand_value_return (rtx val)
+{
+ /* Copy the value to the return location unless it's already there. */
+
+ tree decl = DECL_RESULT (current_function_decl);
+ rtx return_reg = DECL_RTL (decl);
+ if (return_reg != val)
+ {
+ tree funtype = TREE_TYPE (current_function_decl);
+ tree type = TREE_TYPE (decl);
+ int unsignedp = TYPE_UNSIGNED (type);
+ enum machine_mode old_mode = DECL_MODE (decl);
+ enum machine_mode mode;
+ if (DECL_BY_REFERENCE (decl))
+ mode = promote_function_mode (type, old_mode, &unsignedp, funtype, 2);
+ else
+ mode = promote_function_mode (type, old_mode, &unsignedp, funtype, 1);
+
+ if (mode != old_mode)
+ val = convert_modes (mode, old_mode, val, unsignedp);
+
+ if (GET_CODE (return_reg) == PARALLEL)
+ emit_group_load (return_reg, val, type, int_size_in_bytes (type));
+ else
+ emit_move_insn (return_reg, val);
+ }
+
+ expand_null_return_1 ();
+}
+
+/* Generate RTL to evaluate the expression RETVAL and return it
+ from the current function. */
+
+static void
+expand_return (tree retval)
+{
+ rtx result_rtl;
+ rtx val = 0;
+ tree retval_rhs;
+
+ /* If function wants no value, give it none. */
+ if (TREE_CODE (TREE_TYPE (TREE_TYPE (current_function_decl))) == VOID_TYPE)
+ {
+ expand_normal (retval);
+ expand_null_return ();
+ return;
+ }
+
+ if (retval == error_mark_node)
+ {
+ /* Treat this like a return of no value from a function that
+ returns a value. */
+ expand_null_return ();
+ return;
+ }
+ else if ((TREE_CODE (retval) == MODIFY_EXPR
+ || TREE_CODE (retval) == INIT_EXPR)
+ && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
+ retval_rhs = TREE_OPERAND (retval, 1);
+ else
+ retval_rhs = retval;
+
+ result_rtl = DECL_RTL (DECL_RESULT (current_function_decl));
+
+ /* If we are returning the RESULT_DECL, then the value has already
+ been stored into it, so we don't have to do anything special. */
+ if (TREE_CODE (retval_rhs) == RESULT_DECL)
+ expand_value_return (result_rtl);
+
+ /* If the result is an aggregate that is being returned in one (or more)
+ registers, load the registers here. */
+
+ else if (retval_rhs != 0
+ && TYPE_MODE (TREE_TYPE (retval_rhs)) == BLKmode
+ && REG_P (result_rtl))
+ {
+ val = copy_blkmode_to_reg (GET_MODE (result_rtl), retval_rhs);
+ if (val)
+ {
+ /* Use the mode of the result value on the return register. */
+ PUT_MODE (result_rtl, GET_MODE (val));
+ expand_value_return (val);
+ }
+ else
+ expand_null_return ();
+ }
+ else if (retval_rhs != 0
+ && !VOID_TYPE_P (TREE_TYPE (retval_rhs))
+ && (REG_P (result_rtl)
+ || (GET_CODE (result_rtl) == PARALLEL)))
+ {
+ /* Calculate the return value into a temporary (usually a pseudo
+ reg). */
+ tree ot = TREE_TYPE (DECL_RESULT (current_function_decl));
+ tree nt = build_qualified_type (ot, TYPE_QUALS (ot) | TYPE_QUAL_CONST);
+
+ val = assign_temp (nt, 0, 1);
+ val = expand_expr (retval_rhs, val, GET_MODE (val), EXPAND_NORMAL);
+ val = force_not_mem (val);
+ /* Return the calculated value. */
+ expand_value_return (val);
+ }
+ else
+ {
+ /* No hard reg used; calculate value into hard return reg. */
+ expand_expr (retval, const0_rtx, VOIDmode, EXPAND_NORMAL);
+ expand_value_return (result_rtl);
+ }
+}
+
/* A subroutine of expand_gimple_stmt, expanding one gimple statement
STMT that doesn't require special handling for outgoing edges. That
is no tailcalls and no GIMPLE_COND. */
@@ -4522,6 +5405,52 @@ expand_stack_alignment (void)
fixup_tail_calls ();
}
}
+
+
+static void
+expand_main_function (void)
+{
+#if (defined(INVOKE__main) \
+ || (!defined(HAS_INIT_SECTION) \
+ && !defined(INIT_SECTION_ASM_OP) \
+ && !defined(INIT_ARRAY_SECTION_ASM_OP)))
+ emit_library_call (init_one_libfunc (NAME__MAIN), LCT_NORMAL, VOIDmode, 0);
+#endif
+}
+
+
+/* Expand code to initialize the stack_protect_guard. This is invoked at
+ the beginning of a function to be protected. */
+
+#ifndef HAVE_stack_protect_set
+# define HAVE_stack_protect_set 0
+# define gen_stack_protect_set(x,y) (gcc_unreachable (), NULL_RTX)
+#endif
+
+static void
+stack_protect_prologue (void)
+{
+ tree guard_decl = targetm.stack_protect_guard ();
+ rtx x, y;
+
+ x = expand_normal (crtl->stack_protect_guard);
+ y = expand_normal (guard_decl);
+
+ /* Allow the target to copy from Y to X without leaking Y into a
+ register. */
+ if (HAVE_stack_protect_set)
+ {
+ rtx insn = gen_stack_protect_set (x, y);
+ if (insn)
+ {
+ emit_insn (insn);
+ return;
+ }
+ }
+
+ /* Otherwise do a straight move. */
+ emit_move_insn (x, y);
+}
/* Translate the intermediate representation contained in the CFG
from GIMPLE trees to RTL.
@@ -4778,14 +5707,18 @@ gimple_expand_cfg (void)
if (e->insns.r)
{
rebuild_jump_labels_chain (e->insns.r);
- /* Avoid putting insns before parm_birth_insn. */
+ /* Put insns after parm birth, but before
+ NOTE_INSNS_FUNCTION_BEG. */
if (e->src == ENTRY_BLOCK_PTR
- && single_succ_p (ENTRY_BLOCK_PTR)
- && parm_birth_insn)
+ && single_succ_p (ENTRY_BLOCK_PTR))
{
rtx insns = e->insns.r;
e->insns.r = NULL_RTX;
- emit_insn_after_noloc (insns, parm_birth_insn, e->dest);
+ if (NOTE_P (parm_birth_insn)
+ && NOTE_KIND (parm_birth_insn) == NOTE_INSN_FUNCTION_BEG)
+ emit_insn_before_noloc (insns, parm_birth_insn, e->dest);
+ else
+ emit_insn_after_noloc (insns, parm_birth_insn, e->dest);
}
else
commit_one_edge_insertion (e);
@@ -4934,8 +5867,8 @@ const pass_data pass_data_expand =
class pass_expand : public rtl_opt_pass
{
public:
- pass_expand(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_expand, ctxt)
+ pass_expand (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_expand, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/cfghooks.c b/gcc/cfghooks.c
index a4248354d97..c12a62fca50 100644
--- a/gcc/cfghooks.c
+++ b/gcc/cfghooks.c
@@ -1443,6 +1443,6 @@ account_profile_record (struct profile_record *record, int after_pass)
|| bb == EXIT_BLOCK_PTR_FOR_FUNCTION (cfun))
continue;
gcc_assert (cfg_hooks->account_profile_record);
- cfg_hooks->account_profile_record(bb, after_pass, record);
+ cfg_hooks->account_profile_record (bb, after_pass, record);
}
}
diff --git a/gcc/cfgloop.c b/gcc/cfgloop.c
index 928edd46228..3ff8e841bac 100644
--- a/gcc/cfgloop.c
+++ b/gcc/cfgloop.c
@@ -28,7 +28,8 @@ along with GCC; see the file COPYING3. If not see
#include "diagnostic-core.h"
#include "flags.h"
#include "tree.h"
-#include "tree-ssa.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
#include "pointer-set.h"
#include "ggc.h"
#include "dumpfile.h"
@@ -433,7 +434,7 @@ flow_loops_find (struct loops *loops)
/* Gather all loop headers in reverse completion order and allocate
loop structures for loops that are not already present. */
- larray.create (loops->larray->length());
+ larray.create (loops->larray->length ());
for (b = 0; b < n_basic_blocks - NUM_FIXED_BLOCKS; b++)
{
basic_block header = BASIC_BLOCK (rc_order[b]);
@@ -509,7 +510,7 @@ flow_loops_find (struct loops *loops)
}
}
- larray.release();
+ larray.release ();
return loops;
}
@@ -1781,3 +1782,141 @@ get_loop_location (struct loop *loop)
return DECL_SOURCE_LOCATION (current_function_decl);
}
+/* Records that every statement in LOOP is executed I_BOUND times.
+ REALISTIC is true if I_BOUND is expected to be close to the real number
+ of iterations. UPPER is true if we are sure the loop iterates at most
+ I_BOUND times. */
+
+void
+record_niter_bound (struct loop *loop, double_int i_bound, bool realistic,
+ bool upper)
+{
+ /* Update the bounds only when there is no previous estimation, or when the
+ current estimation is smaller. */
+ if (upper
+ && (!loop->any_upper_bound
+ || i_bound.ult (loop->nb_iterations_upper_bound)))
+ {
+ loop->any_upper_bound = true;
+ loop->nb_iterations_upper_bound = i_bound;
+ }
+ if (realistic
+ && (!loop->any_estimate
+ || i_bound.ult (loop->nb_iterations_estimate)))
+ {
+ loop->any_estimate = true;
+ loop->nb_iterations_estimate = i_bound;
+ }
+
+ /* If an upper bound is smaller than the realistic estimate of the
+ number of iterations, use the upper bound instead. */
+ if (loop->any_upper_bound
+ && loop->any_estimate
+ && loop->nb_iterations_upper_bound.ult (loop->nb_iterations_estimate))
+ loop->nb_iterations_estimate = loop->nb_iterations_upper_bound;
+}
+
+/* Similar to get_estimated_loop_iterations, but returns the estimate only
+ if it fits to HOST_WIDE_INT. If this is not the case, or the estimate
+ on the number of iterations of LOOP could not be derived, returns -1. */
+
+HOST_WIDE_INT
+get_estimated_loop_iterations_int (struct loop *loop)
+{
+ double_int nit;
+ HOST_WIDE_INT hwi_nit;
+
+ if (!get_estimated_loop_iterations (loop, &nit))
+ return -1;
+
+ if (!nit.fits_shwi ())
+ return -1;
+ hwi_nit = nit.to_shwi ();
+
+ return hwi_nit < 0 ? -1 : hwi_nit;
+}
+
+/* Returns an upper bound on the number of executions of statements
+ in the LOOP. For statements before the loop exit, this exceeds
+ the number of execution of the latch by one. */
+
+HOST_WIDE_INT
+max_stmt_executions_int (struct loop *loop)
+{
+ HOST_WIDE_INT nit = get_max_loop_iterations_int (loop);
+ HOST_WIDE_INT snit;
+
+ if (nit == -1)
+ return -1;
+
+ snit = (HOST_WIDE_INT) ((unsigned HOST_WIDE_INT) nit + 1);
+
+ /* If the computation overflows, return -1. */
+ return snit < 0 ? -1 : snit;
+}
+
+/* Sets NIT to the estimated number of executions of the latch of the
+ LOOP. If we have no reliable estimate, the function returns false, otherwise
+ returns true. */
+
+bool
+get_estimated_loop_iterations (struct loop *loop, double_int *nit)
+{
+ /* Even if the bound is not recorded, possibly we can derrive one from
+ profile. */
+ if (!loop->any_estimate)
+ {
+ if (loop->header->count)
+ {
+ *nit = gcov_type_to_double_int
+ (expected_loop_iterations_unbounded (loop) + 1);
+ return true;
+ }
+ return false;
+ }
+
+ *nit = loop->nb_iterations_estimate;
+ return true;
+}
+
+/* Sets NIT to an upper bound for the maximum number of executions of the
+ latch of the LOOP. If we have no reliable estimate, the function returns
+ false, otherwise returns true. */
+
+bool
+get_max_loop_iterations (struct loop *loop, double_int *nit)
+{
+ if (!loop->any_upper_bound)
+ return false;
+
+ *nit = loop->nb_iterations_upper_bound;
+ return true;
+}
+
+/* Similar to get_max_loop_iterations, but returns the estimate only
+ if it fits to HOST_WIDE_INT. If this is not the case, or the estimate
+ on the number of iterations of LOOP could not be derived, returns -1. */
+
+HOST_WIDE_INT
+get_max_loop_iterations_int (struct loop *loop)
+{
+ double_int nit;
+ HOST_WIDE_INT hwi_nit;
+
+ if (!get_max_loop_iterations (loop, &nit))
+ return -1;
+
+ if (!nit.fits_shwi ())
+ return -1;
+ hwi_nit = nit.to_shwi ();
+
+ return hwi_nit < 0 ? -1 : hwi_nit;
+}
+
+/* Returns the loop depth of the loop BB belongs to. */
+
+int
+bb_loop_depth (const_basic_block bb)
+{
+ return bb->loop_father ? loop_depth (bb->loop_father) : 0;
+}
diff --git a/gcc/cfgloop.h b/gcc/cfgloop.h
index cd2f527bb47..87086d49022 100644
--- a/gcc/cfgloop.h
+++ b/gcc/cfgloop.h
@@ -20,11 +20,10 @@ along with GCC; see the file COPYING3. If not see
#ifndef GCC_CFGLOOP_H
#define GCC_CFGLOOP_H
-#include "basic-block.h"
#include "double-int.h"
-
#include "bitmap.h"
#include "sbitmap.h"
+#include "function.h"
/* Structure to hold decision about unrolling/peeling. */
enum lpt_dec
@@ -255,7 +254,6 @@ extern bool flow_bb_inside_loop_p (const struct loop *, const_basic_block);
extern struct loop * find_common_loop (struct loop *, struct loop *);
struct loop *superloop_at_depth (struct loop *, unsigned);
struct eni_weights_d;
-extern unsigned tree_num_loop_insns (struct loop *, struct eni_weights_d *);
extern int num_loop_insns (const struct loop *);
extern int average_num_loop_insns (const struct loop *);
extern unsigned get_loop_level (const struct loop *);
@@ -306,16 +304,6 @@ gcov_type expected_loop_iterations_unbounded (const struct loop *);
extern unsigned expected_loop_iterations (const struct loop *);
extern rtx doloop_condition_get (rtx);
-void estimate_numbers_of_iterations_loop (struct loop *);
-void record_niter_bound (struct loop *, double_int, bool, bool);
-bool estimated_loop_iterations (struct loop *, double_int *);
-bool max_loop_iterations (struct loop *, double_int *);
-HOST_WIDE_INT estimated_loop_iterations_int (struct loop *);
-HOST_WIDE_INT max_loop_iterations_int (struct loop *);
-bool max_stmt_executions (struct loop *, double_int *);
-bool estimated_stmt_executions (struct loop *, double_int *);
-HOST_WIDE_INT max_stmt_executions_int (struct loop *);
-HOST_WIDE_INT estimated_stmt_executions_int (struct loop *);
/* Loop manipulation. */
extern bool can_duplicate_loop_p (const struct loop *loop);
@@ -466,14 +454,6 @@ loop_depth (const struct loop *loop)
return vec_safe_length (loop->superloops);
}
-/* Returns the loop depth of the loop BB belongs to. */
-
-static inline int
-bb_loop_depth (const_basic_block bb)
-{
- return bb->loop_father ? loop_depth (bb->loop_father) : 0;
-}
-
/* Returns the immediate superloop of LOOP, or NULL if LOOP is the outermost
loop. */
@@ -515,7 +495,7 @@ static inline unsigned
number_of_loops (struct function *fn)
{
struct loops *loops = loops_for_fn (fn);
- if (!fn)
+ if (!loops)
return 0;
return vec_safe_length (loops->larray);
@@ -735,7 +715,6 @@ enum
extern void unroll_and_peel_loops (int);
extern void doloop_optimize_loops (void);
extern void move_loop_invariants (void);
-extern bool finite_loop_p (struct loop *);
extern void scale_loop_profile (struct loop *loop, int scale, gcov_type iteration_bound);
extern vec<basic_block> get_loop_hot_path (const struct loop *loop);
@@ -751,5 +730,27 @@ loop_outermost (struct loop *loop)
return (*loop->superloops)[1];
}
+extern void record_niter_bound (struct loop *, double_int, bool, bool);
+extern HOST_WIDE_INT get_estimated_loop_iterations_int (struct loop *);
+extern HOST_WIDE_INT get_max_loop_iterations_int (struct loop *);
+extern bool get_estimated_loop_iterations (struct loop *loop, double_int *nit);
+extern bool get_max_loop_iterations (struct loop *loop, double_int *nit);
+extern int bb_loop_depth (const_basic_block);
+/* Converts VAL to double_int. */
+
+static inline double_int
+gcov_type_to_double_int (gcov_type val)
+{
+ double_int ret;
+
+ ret.low = (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;
+ ret.high = (unsigned HOST_WIDE_INT) val;
+
+ return ret;
+}
#endif /* GCC_CFGLOOP_H */
diff --git a/gcc/cfgloopmanip.c b/gcc/cfgloopmanip.c
index ed8a2075f7a..be876db354f 100644
--- a/gcc/cfgloopmanip.c
+++ b/gcc/cfgloopmanip.c
@@ -24,7 +24,9 @@ along with GCC; see the file COPYING3. If not see
#include "rtl.h"
#include "basic-block.h"
#include "cfgloop.h"
-#include "tree-ssa.h"
+#include "tree.h"
+#include "gimple.h"
+#include "tree-ssa-loop-manip.h"
#include "dumpfile.h"
static void copy_loops_to (struct loop **, int,
@@ -950,7 +952,7 @@ unloop (struct loop *loop, bool *irred_invalidated,
remove_bb_from_loops (body[i]);
add_bb_to_loop (body[i], loop_outer (loop));
}
- free(body);
+ free (body);
while (loop->inner)
{
diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c
index eb6b312d5c8..d6733a2af31 100644
--- a/gcc/cfgrtl.c
+++ b/gcc/cfgrtl.c
@@ -479,8 +479,8 @@ const pass_data pass_data_free_cfg =
class pass_free_cfg : public rtl_opt_pass
{
public:
- pass_free_cfg(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_free_cfg, ctxt)
+ pass_free_cfg (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_free_cfg, ctxt)
{}
/* opt_pass methods: */
@@ -1441,7 +1441,7 @@ void
emit_barrier_after_bb (basic_block bb)
{
rtx barrier = emit_barrier_after (BB_END (bb));
- gcc_assert (current_ir_type() == IR_RTL_CFGRTL
+ gcc_assert (current_ir_type () == IR_RTL_CFGRTL
|| current_ir_type () == IR_RTL_CFGLAYOUT);
if (current_ir_type () == IR_RTL_CFGLAYOUT)
BB_FOOTER (bb) = unlink_insn_chain (barrier, barrier);
@@ -1480,7 +1480,7 @@ force_nonfallthru_and_redirect (edge e, basic_block target, rtx jump_label)
note = find_reg_note (BB_END (e->src), REG_BR_PROB, NULL_RTX);
if (note)
{
- int prob = INTVAL (XEXP (note, 0));
+ int prob = XINT (note, 0);
b->probability = prob;
/* Update this to use GCOV_COMPUTE_SCALE. */
@@ -1959,10 +1959,18 @@ commit_one_edge_insertion (edge e)
}
/* If the source has one successor and the edge is not abnormal,
- insert there. Except for the entry block. */
+ insert there. Except for the entry block.
+ Don't do this if the predecessor ends in a jump other than
+ unconditional simple jump. E.g. for asm goto that points all
+ its labels at the fallthru basic block, we can't insert instructions
+ before the asm goto, as the asm goto can have various of side effects,
+ and can't emit instructions after the asm goto, as it must end
+ the basic block. */
else if ((e->flags & EDGE_ABNORMAL) == 0
&& single_succ_p (e->src)
- && e->src != ENTRY_BLOCK_PTR)
+ && e->src != ENTRY_BLOCK_PTR
+ && (!JUMP_P (BB_END (e->src))
+ || simplejump_p (BB_END (e->src))))
{
bb = e->src;
@@ -2207,9 +2215,9 @@ update_br_prob_note (basic_block bb)
if (!JUMP_P (BB_END (bb)))
return;
note = find_reg_note (BB_END (bb), REG_BR_PROB, NULL_RTX);
- if (!note || INTVAL (XEXP (note, 0)) == BRANCH_EDGE (bb)->probability)
+ if (!note || XINT (note, 0) == BRANCH_EDGE (bb)->probability)
return;
- XEXP (note, 0) = GEN_INT (BRANCH_EDGE (bb)->probability);
+ XINT (note, 0) = BRANCH_EDGE (bb)->probability;
}
/* Get the last insn associated with block BB (that includes barriers and
@@ -2346,7 +2354,7 @@ verify_hot_cold_block_grouping (void)
again (in compgoto). Ensure we don't call this before going back
into linearized RTL when any layout fixes would have been committed. */
if (!crtl->bb_reorder_complete
- || current_ir_type() != IR_RTL_CFGRTL)
+ || current_ir_type () != IR_RTL_CFGRTL)
return err;
FOR_EACH_BB (bb)
@@ -2399,11 +2407,11 @@ rtl_verify_edges (void)
&& EDGE_COUNT (bb->succs) >= 2
&& any_condjump_p (BB_END (bb)))
{
- if (INTVAL (XEXP (note, 0)) != BRANCH_EDGE (bb)->probability
+ if (XINT (note, 0) != BRANCH_EDGE (bb)->probability
&& profile_status != PROFILE_ABSENT)
{
- error ("verify_flow_info: REG_BR_PROB does not match cfg %wi %i",
- INTVAL (XEXP (note, 0)), BRANCH_EDGE (bb)->probability);
+ error ("verify_flow_info: REG_BR_PROB does not match cfg %i %i",
+ XINT (note, 0), BRANCH_EDGE (bb)->probability);
err = 1;
}
}
@@ -3104,7 +3112,7 @@ purge_dead_edges (basic_block bb)
b = BRANCH_EDGE (bb);
f = FALLTHRU_EDGE (bb);
- b->probability = INTVAL (XEXP (note, 0));
+ b->probability = XINT (note, 0);
f->probability = REG_BR_PROB_BASE - b->probability;
/* Update these to use GCOV_COMPUTE_SCALE. */
b->count = bb->count * b->probability / REG_BR_PROB_BASE;
@@ -3484,8 +3492,8 @@ const pass_data pass_data_into_cfg_layout_mode =
class pass_into_cfg_layout_mode : public rtl_opt_pass
{
public:
- pass_into_cfg_layout_mode(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_into_cfg_layout_mode, ctxt)
+ pass_into_cfg_layout_mode (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_into_cfg_layout_mode, ctxt)
{}
/* opt_pass methods: */
@@ -3521,8 +3529,8 @@ const pass_data pass_data_outof_cfg_layout_mode =
class pass_outof_cfg_layout_mode : public rtl_opt_pass
{
public:
- pass_outof_cfg_layout_mode(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_outof_cfg_layout_mode, ctxt)
+ pass_outof_cfg_layout_mode (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_outof_cfg_layout_mode, ctxt)
{}
/* opt_pass methods: */
@@ -3735,7 +3743,7 @@ fixup_reorder_chain (void)
rtx note = find_reg_note (bb_end_insn, REG_BR_PROB, 0);
if (note
- && INTVAL (XEXP (note, 0)) < REG_BR_PROB_BASE / 2
+ && XINT (note, 0) < REG_BR_PROB_BASE / 2
&& invert_jump (bb_end_insn,
(e_fall->dest == EXIT_BLOCK_PTR
? NULL_RTX
@@ -4887,7 +4895,7 @@ rtl_lv_add_condition_to_bb (basic_block first_head ,
end_sequence ();
/* Add the new cond , in the new head. */
- emit_insn_after(seq, BB_END(cond_bb));
+ emit_insn_after (seq, BB_END (cond_bb));
}
diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index 722f8ca97e9..385b11da797 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -42,6 +42,9 @@ along with GCC; see the file COPYING3. If not see
#include "gimple.h"
#include "timevar.h"
#include "dumpfile.h"
+#include "gimple-ssa.h"
+#include "cgraph.h"
+#include "tree-cfg.h"
#include "tree-ssa.h"
#include "value-prof.h"
#include "except.h"
@@ -61,7 +64,7 @@ static inline void cgraph_edge_remove_caller (struct cgraph_edge *e);
static inline void cgraph_edge_remove_callee (struct cgraph_edge *e);
/* Queue of cgraph nodes scheduled to be lowered. */
-symtab_node x_cgraph_nodes_queue;
+symtab_node *x_cgraph_nodes_queue;
#define cgraph_nodes_queue ((struct cgraph_node *)x_cgraph_nodes_queue)
/* Number of nodes in existence. */
@@ -135,7 +138,7 @@ bool cpp_implicit_aliases_done;
The cgraph_function_version_info has a THIS_NODE field that is the
corresponding cgraph_node.. */
-static htab_t GTY((param_is (struct cgraph_function_version_info *)))
+static GTY((param_is (struct cgraph_function_version_info))) htab_t
cgraph_fnver_htab = NULL;
/* Hash function for cgraph_fnver_htab. */
@@ -271,8 +274,8 @@ record_function_versions (tree decl1, tree decl2)
/* Macros to access the next item in the list of free cgraph nodes and
edges. */
-#define NEXT_FREE_NODE(NODE) cgraph ((NODE)->symbol.next)
-#define SET_NEXT_FREE_NODE(NODE,NODE2) ((NODE))->symbol.next = (symtab_node)NODE2
+#define NEXT_FREE_NODE(NODE) cgraph ((NODE)->next)
+#define SET_NEXT_FREE_NODE(NODE,NODE2) ((NODE))->next = NODE2
#define NEXT_FREE_EDGE(EDGE) (EDGE)->prev_caller
/* Register HOOK to be called with DATA on each removed edge. */
@@ -510,7 +513,7 @@ cgraph_create_empty_node (void)
{
struct cgraph_node *node = cgraph_allocate_node ();
- node->symbol.type = SYMTAB_FUNCTION;
+ node->type = SYMTAB_FUNCTION;
node->frequency = NODE_FREQUENCY_NORMAL;
node->count_materialization_scale = REG_BR_PROB_BASE;
cgraph_n_nodes++;
@@ -525,8 +528,8 @@ cgraph_create_node (tree decl)
struct cgraph_node *node = cgraph_create_empty_node ();
gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
- node->symbol.decl = decl;
- symtab_register_node ((symtab_node) node);
+ node->decl = decl;
+ symtab_register_node (node);
if (DECL_CONTEXT (decl) && TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL)
{
@@ -564,12 +567,12 @@ cgraph_create_function_alias (tree alias, tree target)
|| TREE_CODE (target) == IDENTIFIER_NODE);
gcc_assert (TREE_CODE (alias) == FUNCTION_DECL);
alias_node = cgraph_get_create_node (alias);
- gcc_assert (!alias_node->symbol.definition);
- alias_node->symbol.alias_target = target;
- alias_node->symbol.definition = true;
- alias_node->symbol.alias = true;
+ gcc_assert (!alias_node->definition);
+ alias_node->alias_target = target;
+ alias_node->definition = true;
+ alias_node->alias = true;
if (lookup_attribute ("weakref", DECL_ATTRIBUTES (alias)) != NULL)
- alias_node->symbol.weakref = true;
+ alias_node->weakref = true;
return alias_node;
}
@@ -592,10 +595,10 @@ cgraph_same_body_alias (struct cgraph_node *decl_node ATTRIBUTE_UNUSED, tree ali
return NULL;
n = cgraph_create_function_alias (alias, decl);
- n->symbol.cpp_implicit_alias = true;
+ n->cpp_implicit_alias = true;
if (cpp_implicit_aliases_done)
- symtab_resolve_alias ((symtab_node)n,
- (symtab_node)cgraph_get_node (decl));
+ symtab_resolve_alias (n,
+ cgraph_get_node (decl));
return n;
}
@@ -616,8 +619,8 @@ cgraph_add_thunk (struct cgraph_node *decl_node ATTRIBUTE_UNUSED,
node = cgraph_get_node (alias);
if (node)
{
- gcc_assert (node->symbol.definition);
- gcc_assert (!node->symbol.alias);
+ gcc_assert (node->definition);
+ gcc_assert (!node->alias);
gcc_assert (!node->thunk.thunk_p);
cgraph_remove_node (node);
}
@@ -632,7 +635,7 @@ cgraph_add_thunk (struct cgraph_node *decl_node ATTRIBUTE_UNUSED,
node->thunk.virtual_offset_p = virtual_offset != NULL;
node->thunk.alias = real_alias;
node->thunk.thunk_p = true;
- node->symbol.definition = true;
+ node->definition = true;
return node;
}
@@ -644,9 +647,9 @@ struct cgraph_node *
cgraph_node_for_asm (tree asmname)
{
/* We do not want to look at inline clones. */
- for (symtab_node node = symtab_node_for_asm (asmname);
+ for (symtab_node *node = symtab_node_for_asm (asmname);
node;
- node = node->symbol.next_sharing_asm_name)
+ node = node->next_sharing_asm_name)
{
cgraph_node *cn = dyn_cast <cgraph_node> (node);
if (cn && !cn->global.inlined_to)
@@ -801,7 +804,7 @@ cgraph_set_call_stmt (struct cgraph_edge *e, gimple new_stmt,
e = cgraph_make_edge_direct (e, new_callee);
}
- push_cfun (DECL_STRUCT_FUNCTION (e->caller->symbol.decl));
+ push_cfun (DECL_STRUCT_FUNCTION (e->caller->decl));
e->can_throw_external = stmt_can_throw_external (new_stmt);
pop_cfun ();
if (e->caller->call_site_hash)
@@ -814,7 +817,8 @@ cgraph_set_call_stmt (struct cgraph_edge *e, gimple new_stmt,
static struct cgraph_edge *
cgraph_create_edge_1 (struct cgraph_node *caller, struct cgraph_node *callee,
- gimple call_stmt, gcov_type count, int freq)
+ gimple call_stmt, gcov_type count, int freq,
+ bool indir_unknown_callee)
{
struct cgraph_edge *edge;
@@ -859,13 +863,13 @@ cgraph_create_edge_1 (struct cgraph_node *caller, struct cgraph_node *callee,
gcc_assert (freq <= CGRAPH_FREQ_MAX);
edge->call_stmt = call_stmt;
- push_cfun (DECL_STRUCT_FUNCTION (caller->symbol.decl));
+ push_cfun (DECL_STRUCT_FUNCTION (caller->decl));
edge->can_throw_external
= call_stmt ? stmt_can_throw_external (call_stmt) : false;
pop_cfun ();
if (call_stmt
- && callee && callee->symbol.decl
- && !gimple_check_call_matching_types (call_stmt, callee->symbol.decl,
+ && callee && callee->decl
+ && !gimple_check_call_matching_types (call_stmt, callee->decl,
false))
edge->call_stmt_cannot_inline_p = true;
else
@@ -874,6 +878,7 @@ cgraph_create_edge_1 (struct cgraph_node *caller, struct cgraph_node *callee,
edge->indirect_info = NULL;
edge->indirect_inlining_edge = 0;
edge->speculative = false;
+ edge->indirect_unknown_callee = indir_unknown_callee;
if (call_stmt && caller->call_site_hash)
cgraph_add_edge_to_call_site_hash (edge);
@@ -887,9 +892,8 @@ cgraph_create_edge (struct cgraph_node *caller, struct cgraph_node *callee,
gimple call_stmt, gcov_type count, int freq)
{
struct cgraph_edge *edge = cgraph_create_edge_1 (caller, callee, call_stmt,
- count, freq);
+ count, freq, false);
- edge->indirect_unknown_callee = 0;
initialize_inline_failed (edge);
edge->next_caller = callee->callers;
@@ -926,10 +930,9 @@ cgraph_create_indirect_edge (struct cgraph_node *caller, gimple call_stmt,
gcov_type count, int freq)
{
struct cgraph_edge *edge = cgraph_create_edge_1 (caller, NULL, call_stmt,
- count, freq);
+ count, freq, true);
tree target;
- edge->indirect_unknown_callee = 1;
initialize_inline_failed (edge);
edge->indirect_info = cgraph_allocate_init_indirect_info ();
@@ -1078,14 +1081,14 @@ cgraph_turn_edge_to_speculative (struct cgraph_edge *e,
{
fprintf (dump_file, "Indirect call -> speculative call"
" %s/%i => %s/%i\n",
- xstrdup (cgraph_node_name (n)), n->symbol.order,
- xstrdup (cgraph_node_name (n2)), n2->symbol.order);
+ xstrdup (cgraph_node_name (n)), n->order,
+ xstrdup (cgraph_node_name (n2)), n2->order);
}
e->speculative = true;
e2 = cgraph_create_edge (n, n2, e->call_stmt, direct_count, direct_frequency);
initialize_inline_failed (e2);
e2->speculative = true;
- if (TREE_NOTHROW (n2->symbol.decl))
+ if (TREE_NOTHROW (n2->decl))
e2->can_throw_external = false;
else
e2->can_throw_external = e->can_throw_external;
@@ -1093,7 +1096,7 @@ cgraph_turn_edge_to_speculative (struct cgraph_edge *e,
e->count -= e2->count;
e->frequency -= e2->frequency;
cgraph_call_edge_duplication_hooks (e, e2);
- ref = ipa_record_reference ((symtab_node)n, (symtab_node)n2,
+ ref = ipa_record_reference (n, n2,
IPA_REF_ADDR, e->call_stmt);
ref->lto_stmt_uid = e->lto_stmt_uid;
ref->speculative = e->speculative;
@@ -1147,7 +1150,7 @@ cgraph_speculative_call_info (struct cgraph_edge *e,
indirect = e2;
reference = NULL;
- for (i = 0; ipa_ref_list_reference_iterate (&e->caller->symbol.ref_list,
+ for (i = 0; ipa_ref_list_reference_iterate (&e->caller->ref_list,
i, ref); i++)
if (ref->speculative
&& ((ref->stmt && ref->stmt == e->call_stmt)
@@ -1188,7 +1191,9 @@ cgraph_resolve_speculation (struct cgraph_edge *edge, tree callee_decl)
gcc_assert (edge->speculative);
cgraph_speculative_call_info (edge, e2, edge, ref);
- if (ref->referred->symbol.decl != callee_decl)
+ if (!callee_decl
+ || !symtab_semantically_equivalent_p (ref->referred,
+ symtab_get_node (callee_decl)))
{
if (dump_file)
{
@@ -1196,16 +1201,16 @@ cgraph_resolve_speculation (struct cgraph_edge *edge, tree callee_decl)
{
fprintf (dump_file, "Speculative indirect call %s/%i => %s/%i has "
"turned out to have contradicting known target ",
- xstrdup (cgraph_node_name (edge->caller)), edge->caller->symbol.order,
- xstrdup (cgraph_node_name (e2->callee)), e2->callee->symbol.order);
+ xstrdup (cgraph_node_name (edge->caller)), edge->caller->order,
+ xstrdup (cgraph_node_name (e2->callee)), e2->callee->order);
print_generic_expr (dump_file, callee_decl, 0);
fprintf (dump_file, "\n");
}
else
{
fprintf (dump_file, "Removing speculative call %s/%i => %s/%i\n",
- xstrdup (cgraph_node_name (edge->caller)), edge->caller->symbol.order,
- xstrdup (cgraph_node_name (e2->callee)), e2->callee->symbol.order);
+ xstrdup (cgraph_node_name (edge->caller)), edge->caller->order,
+ xstrdup (cgraph_node_name (e2->callee)), e2->callee->order);
}
}
}
@@ -1247,7 +1252,7 @@ cgraph_make_edge_direct (struct cgraph_edge *edge, struct cgraph_node *callee)
/* If we are redirecting speculative call, make it non-speculative. */
if (edge->indirect_unknown_callee && edge->speculative)
{
- edge = cgraph_resolve_speculation (edge, callee->symbol.decl);
+ edge = cgraph_resolve_speculation (edge, callee->decl);
/* On successful speculation just return the pre existing direct edge. */
if (!edge->indirect_unknown_callee)
@@ -1278,7 +1283,7 @@ cgraph_make_edge_direct (struct cgraph_edge *edge, struct cgraph_node *callee)
if (edge->call_stmt)
edge->call_stmt_cannot_inline_p
- = !gimple_check_call_matching_types (edge->call_stmt, callee->symbol.decl,
+ = !gimple_check_call_matching_types (edge->call_stmt, callee->decl,
false);
/* We need to re-determine the inlining status of the edge. */
@@ -1315,23 +1320,23 @@ cgraph_redirect_edge_call_stmt_to_callee (struct cgraph_edge *e)
signature. We did not update the call statement yet, so compare it
with the reference that still points to the proper type. */
else if (!gimple_check_call_matching_types (e->call_stmt,
- ref->referred->symbol.decl,
+ ref->referred->decl,
true))
{
if (dump_file)
fprintf (dump_file, "Not expanding speculative call of %s/%i -> %s/%i\n"
"Type mismatch.\n",
xstrdup (cgraph_node_name (e->caller)),
- e->caller->symbol.order,
+ e->caller->order,
xstrdup (cgraph_node_name (e->callee)),
- e->callee->symbol.order);
+ e->callee->order);
e = cgraph_resolve_speculation (e, NULL);
/* We are producing the final function body and will throw away the
callgraph edges really soon. Reset the counts/frequencies to
keep verifier happy in the case of roundoff errors. */
e->count = gimple_bb (e->call_stmt)->count;
e->frequency = compute_call_stmt_bb_frequency
- (e->caller->symbol.decl, gimple_bb (e->call_stmt));
+ (e->caller->decl, gimple_bb (e->call_stmt));
}
/* Expand speculation into GIMPLE code. */
else
@@ -1341,12 +1346,12 @@ cgraph_redirect_edge_call_stmt_to_callee (struct cgraph_edge *e)
"Expanding speculative call of %s/%i -> %s/%i count:"
HOST_WIDEST_INT_PRINT_DEC"\n",
xstrdup (cgraph_node_name (e->caller)),
- e->caller->symbol.order,
+ e->caller->order,
xstrdup (cgraph_node_name (e->callee)),
- e->callee->symbol.order,
+ e->callee->order,
(HOST_WIDEST_INT)e->count);
gcc_assert (e2->speculative);
- push_cfun (DECL_STRUCT_FUNCTION (e->caller->symbol.decl));
+ push_cfun (DECL_STRUCT_FUNCTION (e->caller->decl));
new_stmt = gimple_ic (e->call_stmt, cgraph (ref->referred),
e->count || e2->count
? RDIV (e->count * REG_BR_PROB_BASE,
@@ -1360,9 +1365,9 @@ cgraph_redirect_edge_call_stmt_to_callee (struct cgraph_edge *e)
cgraph_set_call_stmt_including_clones (e->caller, e->call_stmt,
new_stmt, false);
e->frequency = compute_call_stmt_bb_frequency
- (e->caller->symbol.decl, gimple_bb (e->call_stmt));
+ (e->caller->decl, gimple_bb (e->call_stmt));
e2->frequency = compute_call_stmt_bb_frequency
- (e2->caller->symbol.decl, gimple_bb (e2->call_stmt));
+ (e2->caller->decl, gimple_bb (e2->call_stmt));
e2->speculative = false;
ref->speculative = false;
ref->stmt = NULL;
@@ -1376,7 +1381,7 @@ cgraph_redirect_edge_call_stmt_to_callee (struct cgraph_edge *e)
}
if (e->indirect_unknown_callee
- || decl == e->callee->symbol.decl)
+ || decl == e->callee->decl)
return e->call_stmt;
#ifdef ENABLE_CHECKING
@@ -1390,8 +1395,8 @@ cgraph_redirect_edge_call_stmt_to_callee (struct cgraph_edge *e)
if (cgraph_dump_file)
{
fprintf (cgraph_dump_file, "updating call of %s/%i -> %s/%i: ",
- xstrdup (cgraph_node_name (e->caller)), e->caller->symbol.order,
- xstrdup (cgraph_node_name (e->callee)), e->callee->symbol.order);
+ xstrdup (cgraph_node_name (e->caller)), e->caller->order,
+ xstrdup (cgraph_node_name (e->callee)), e->callee->order);
print_gimple_stmt (cgraph_dump_file, e->call_stmt, 0, dump_flags);
if (e->callee->clone.combined_args_to_skip)
{
@@ -1408,7 +1413,7 @@ cgraph_redirect_edge_call_stmt_to_callee (struct cgraph_edge *e)
new_stmt
= gimple_call_copy_skip_args (e->call_stmt,
e->callee->clone.combined_args_to_skip);
- gimple_call_set_fndecl (new_stmt, e->callee->symbol.decl);
+ gimple_call_set_fndecl (new_stmt, e->callee->decl);
gimple_call_set_fntype (new_stmt, gimple_call_fntype (e->call_stmt));
if (gimple_vdef (new_stmt)
@@ -1431,7 +1436,7 @@ cgraph_redirect_edge_call_stmt_to_callee (struct cgraph_edge *e)
else
{
new_stmt = e->call_stmt;
- gimple_call_set_fndecl (new_stmt, e->callee->symbol.decl);
+ gimple_call_set_fndecl (new_stmt, e->callee->decl);
update_stmt (new_stmt);
}
@@ -1481,7 +1486,7 @@ cgraph_update_edges_for_call_stmt_node (struct cgraph_node *node,
struct cgraph_node *callee = e->callee;
while (callee)
{
- if (callee->symbol.decl == new_call
+ if (callee->decl == new_call
|| callee->former_clone_of == new_call)
return;
callee = callee->clone_of;
@@ -1633,7 +1638,7 @@ release_function_body (tree decl)
}
if (cfun->value_histograms)
free_histograms ();
- pop_cfun();
+ pop_cfun ();
gimple_set_body (decl, NULL);
/* Struct function hangs a lot of data that would leak if we didn't
removed all pointers to it. */
@@ -1654,17 +1659,17 @@ cgraph_release_function_body (struct cgraph_node *node)
node->ipa_transforms_to_apply.release ();
if (!node->used_as_abstract_origin && cgraph_state != CGRAPH_STATE_PARSING)
{
- DECL_RESULT (node->symbol.decl) = NULL;
- DECL_ARGUMENTS (node->symbol.decl) = NULL;
+ DECL_RESULT (node->decl) = NULL;
+ DECL_ARGUMENTS (node->decl) = NULL;
}
/* If the node is abstract and needed, then do not clear DECL_INITIAL
of its associated function function declaration because it's
needed to emit debug info later. */
- if (!node->used_as_abstract_origin && DECL_INITIAL (node->symbol.decl))
- DECL_INITIAL (node->symbol.decl) = error_mark_node;
- release_function_body (node->symbol.decl);
- if (node->symbol.lto_file_data)
- lto_free_function_in_decl_state_for_node ((symtab_node) node);
+ if (!node->used_as_abstract_origin && DECL_INITIAL (node->decl))
+ DECL_INITIAL (node->decl) = error_mark_node;
+ release_function_body (node->decl);
+ if (node->lto_file_data)
+ lto_free_function_in_decl_state_for_node (node);
}
/* Remove the node from cgraph. */
@@ -1682,8 +1687,8 @@ cgraph_remove_node (struct cgraph_node *node)
/* Incremental inlining access removed nodes stored in the postorder list.
*/
- node->symbol.force_output = false;
- node->symbol.forced_by_abi = false;
+ node->force_output = false;
+ node->forced_by_abi = false;
for (n = node->nested; n; n = n->next_nested)
n->origin = NULL;
node->nested = NULL;
@@ -1695,7 +1700,7 @@ cgraph_remove_node (struct cgraph_node *node)
node2 = &(*node2)->next_nested;
*node2 = node->next_nested;
}
- symtab_unregister_node ((symtab_node)node);
+ symtab_unregister_node (node);
if (node->prev_sibling_clone)
node->prev_sibling_clone->next_sibling_clone = node->next_sibling_clone;
else if (node->clone_of)
@@ -1739,18 +1744,18 @@ cgraph_remove_node (struct cgraph_node *node)
*/
if (cgraph_state != CGRAPH_LTO_STREAMING)
{
- n = cgraph_get_node (node->symbol.decl);
+ n = cgraph_get_node (node->decl);
if (!n
|| (!n->clones && !n->clone_of && !n->global.inlined_to
&& (cgraph_global_info_ready
- && (TREE_ASM_WRITTEN (n->symbol.decl)
- || DECL_EXTERNAL (n->symbol.decl)
- || !n->symbol.analyzed
- || (!flag_wpa && n->symbol.in_other_partition)))))
+ && (TREE_ASM_WRITTEN (n->decl)
+ || DECL_EXTERNAL (n->decl)
+ || !n->analyzed
+ || (!flag_wpa && n->in_other_partition)))))
cgraph_release_function_body (node);
}
- node->symbol.decl = NULL;
+ node->decl = NULL;
if (node->call_site_hash)
{
htab_delete (node->call_site_hash);
@@ -1760,8 +1765,8 @@ cgraph_remove_node (struct cgraph_node *node)
/* Clear out the node to NULL all pointers and add the node to the free
list. */
- memset (node, 0, sizeof(*node));
- node->symbol.type = SYMTAB_FUNCTION;
+ memset (node, 0, sizeof (*node));
+ node->type = SYMTAB_FUNCTION;
node->uid = uid;
SET_NEXT_FREE_NODE (node, free_nodes);
free_nodes = node;
@@ -1786,9 +1791,9 @@ cgraph_mark_address_taken_node (struct cgraph_node *node)
of the object was taken (and thus it should be set on node alias is
referring to). We should remove the first use and the remove the
following set. */
- node->symbol.address_taken = 1;
+ node->address_taken = 1;
node = cgraph_function_or_thunk_node (node, NULL);
- node->symbol.address_taken = 1;
+ node->address_taken = 1;
}
/* Return local info for the compiled function. */
@@ -1830,7 +1835,7 @@ cgraph_rtl_info (tree decl)
node = cgraph_get_node (decl);
if (!node
|| (decl != current_function_decl
- && !TREE_ASM_WRITTEN (node->symbol.decl)))
+ && !TREE_ASM_WRITTEN (node->decl)))
return NULL;
return &node->rtl;
}
@@ -1866,18 +1871,18 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node)
struct cgraph_edge *edge;
int indirect_calls_count = 0;
- dump_symtab_base (f, (symtab_node) node);
+ dump_symtab_base (f, node);
if (node->global.inlined_to)
fprintf (f, " Function %s/%i is inline copy in %s/%i\n",
xstrdup (cgraph_node_name (node)),
- node->symbol.order,
+ node->order,
xstrdup (cgraph_node_name (node->global.inlined_to)),
- node->global.inlined_to->symbol.order);
+ node->global.inlined_to->order);
if (node->clone_of)
fprintf (f, " Clone of %s/%i\n",
cgraph_node_asm_name (node->clone_of),
- node->clone_of->symbol.order);
+ node->clone_of->order);
if (cgraph_function_flags_ready)
fprintf (f, " Availability: %s\n",
cgraph_availability_names [cgraph_function_body_availability (node)]);
@@ -1885,13 +1890,14 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node)
if (node->profile_id)
fprintf (f, " Profile id: %i\n",
node->profile_id);
+ fprintf (f, " First run: %i\n", node->tp_first_run);
fprintf (f, " Function flags:");
if (node->count)
fprintf (f, " executed "HOST_WIDEST_INT_PRINT_DEC"x",
(HOST_WIDEST_INT)node->count);
if (node->origin)
fprintf (f, " nested in: %s", cgraph_node_asm_name (node->origin));
- if (gimple_has_body_p (node->symbol.decl))
+ if (gimple_has_body_p (node->decl))
fprintf (f, " body");
if (node->process)
fprintf (f, " process");
@@ -1921,7 +1927,7 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node)
(int)node->thunk.virtual_value,
(int)node->thunk.virtual_offset_p);
}
- if (node->symbol.alias && node->thunk.alias
+ if (node->alias && node->thunk.alias
&& DECL_P (node->thunk.alias))
{
fprintf (f, " Alias of %s",
@@ -1937,7 +1943,7 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node)
for (edge = node->callers; edge; edge = edge->next_caller)
{
fprintf (f, "%s/%i ", cgraph_node_asm_name (edge->caller),
- edge->caller->symbol.order);
+ edge->caller->order);
if (edge->count)
fprintf (f, "("HOST_WIDEST_INT_PRINT_DEC"x) ",
(HOST_WIDEST_INT)edge->count);
@@ -1945,26 +1951,26 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node)
fprintf (f, "(%.2f per call) ",
edge->frequency / (double)CGRAPH_FREQ_BASE);
if (edge->speculative)
- fprintf(f, "(speculative) ");
+ fprintf (f, "(speculative) ");
if (!edge->inline_failed)
- fprintf(f, "(inlined) ");
+ fprintf (f, "(inlined) ");
if (edge->indirect_inlining_edge)
- fprintf(f, "(indirect_inlining) ");
+ fprintf (f, "(indirect_inlining) ");
if (edge->can_throw_external)
- fprintf(f, "(can throw external) ");
+ fprintf (f, "(can throw external) ");
}
fprintf (f, "\n Calls: ");
for (edge = node->callees; edge; edge = edge->next_callee)
{
fprintf (f, "%s/%i ", cgraph_node_asm_name (edge->callee),
- edge->callee->symbol.order);
+ edge->callee->order);
if (edge->speculative)
- fprintf(f, "(speculative) ");
+ fprintf (f, "(speculative) ");
if (!edge->inline_failed)
- fprintf(f, "(inlined) ");
+ fprintf (f, "(inlined) ");
if (edge->indirect_inlining_edge)
- fprintf(f, "(indirect_inlining) ");
+ fprintf (f, "(indirect_inlining) ");
if (edge->count)
fprintf (f, "("HOST_WIDEST_INT_PRINT_DEC"x) ",
(HOST_WIDEST_INT)edge->count);
@@ -1972,7 +1978,7 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node)
fprintf (f, "(%.2f per call) ",
edge->frequency / (double)CGRAPH_FREQ_BASE);
if (edge->can_throw_external)
- fprintf(f, "(can throw external) ");
+ fprintf (f, "(can throw external) ");
}
fprintf (f, "\n");
@@ -2042,20 +2048,20 @@ enum availability
cgraph_function_body_availability (struct cgraph_node *node)
{
enum availability avail;
- if (!node->symbol.analyzed)
+ if (!node->analyzed)
avail = AVAIL_NOT_AVAILABLE;
else if (node->local.local)
avail = AVAIL_LOCAL;
- else if (node->symbol.alias && node->symbol.weakref)
+ else if (node->alias && node->weakref)
cgraph_function_or_thunk_node (node, &avail);
- else if (lookup_attribute ("ifunc", DECL_ATTRIBUTES (node->symbol.decl)))
+ else if (lookup_attribute ("ifunc", DECL_ATTRIBUTES (node->decl)))
avail = AVAIL_OVERWRITABLE;
- else if (!node->symbol.externally_visible)
+ else if (!node->externally_visible)
avail = AVAIL_AVAILABLE;
/* Inline functions are safe to be analyzed even if their symbol can
be overwritten at runtime. It is not meaningful to enforce any sane
behaviour on replacing inline function by different body. */
- else if (DECL_DECLARED_INLINE_P (node->symbol.decl))
+ else if (DECL_DECLARED_INLINE_P (node->decl))
avail = AVAIL_AVAILABLE;
/* If the function can be overwritten, return OVERWRITABLE. Take
@@ -2068,8 +2074,8 @@ cgraph_function_body_availability (struct cgraph_node *node)
AVAIL_AVAILABLE here? That would be good reason to preserve this
bit. */
- else if (decl_replaceable_p (node->symbol.decl)
- && !DECL_EXTERNAL (node->symbol.decl))
+ else if (decl_replaceable_p (node->decl)
+ && !DECL_EXTERNAL (node->decl))
avail = AVAIL_OVERWRITABLE;
else avail = AVAIL_AVAILABLE;
@@ -2081,12 +2087,12 @@ static bool
cgraph_node_cannot_be_local_p_1 (struct cgraph_node *node,
void *data ATTRIBUTE_UNUSED)
{
- return !(!node->symbol.force_output
- && ((DECL_COMDAT (node->symbol.decl)
- && !node->symbol.forced_by_abi
- && !symtab_used_from_object_file_p ((symtab_node) node)
- && !node->symbol.same_comdat_group)
- || !node->symbol.externally_visible));
+ return !(!node->force_output
+ && ((DECL_COMDAT (node->decl)
+ && !node->forced_by_abi
+ && !symtab_used_from_object_file_p (node)
+ && !node->same_comdat_group)
+ || !node->externally_visible));
}
/* Return true if NODE can be made local for API change.
@@ -2096,7 +2102,7 @@ cgraph_node_cannot_be_local_p_1 (struct cgraph_node *node,
bool
cgraph_node_can_be_local_p (struct cgraph_node *node)
{
- return (!node->symbol.address_taken
+ return (!node->address_taken
&& !cgraph_for_node_and_aliases (node,
cgraph_node_cannot_be_local_p_1,
NULL, true));
@@ -2125,7 +2131,7 @@ cgraph_for_node_thunks_and_aliases (struct cgraph_node *node,
if (cgraph_for_node_thunks_and_aliases (e->caller, callback, data,
include_overwritable))
return true;
- for (i = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list, i, ref); i++)
+ for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list, i, ref); i++)
if (ref->use == IPA_REF_ALIAS)
{
struct cgraph_node *alias = ipa_ref_referring_node (ref);
@@ -2153,7 +2159,7 @@ cgraph_for_node_and_aliases (struct cgraph_node *node,
if (callback (node, data))
return true;
- for (i = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list, i, ref); i++)
+ for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list, i, ref); i++)
if (ref->use == IPA_REF_ALIAS)
{
struct cgraph_node *alias = ipa_ref_referring_node (ref);
@@ -2172,16 +2178,16 @@ static bool
cgraph_make_node_local_1 (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
{
gcc_checking_assert (cgraph_node_can_be_local_p (node));
- if (DECL_COMDAT (node->symbol.decl) || DECL_EXTERNAL (node->symbol.decl))
+ if (DECL_COMDAT (node->decl) || DECL_EXTERNAL (node->decl))
{
- symtab_make_decl_local (node->symbol.decl);
+ symtab_make_decl_local (node->decl);
- node->symbol.externally_visible = false;
- node->symbol.forced_by_abi = false;
+ node->externally_visible = false;
+ node->forced_by_abi = false;
node->local.local = true;
- node->symbol.unique_name = (node->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY
- || node->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY_EXP);
- node->symbol.resolution = LDPR_PREVAILING_DEF_IRONLY;
+ node->unique_name = (node->resolution == LDPR_PREVAILING_DEF_IRONLY
+ || node->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP);
+ node->resolution = LDPR_PREVAILING_DEF_IRONLY;
gcc_assert (cgraph_function_body_availability (node) == AVAIL_LOCAL);
}
return false;
@@ -2203,7 +2209,7 @@ cgraph_set_nothrow_flag_1 (struct cgraph_node *node, void *data)
{
struct cgraph_edge *e;
- TREE_NOTHROW (node->symbol.decl) = data != NULL;
+ TREE_NOTHROW (node->decl) = data != NULL;
if (data != NULL)
for (e = node->callers; e; e = e->next_caller)
@@ -2230,13 +2236,13 @@ cgraph_set_const_flag_1 (struct cgraph_node *node, void *data)
optimized out. */
if (data && !((size_t)data & 2))
{
- if (DECL_STATIC_CONSTRUCTOR (node->symbol.decl))
- DECL_STATIC_CONSTRUCTOR (node->symbol.decl) = 0;
- if (DECL_STATIC_DESTRUCTOR (node->symbol.decl))
- DECL_STATIC_DESTRUCTOR (node->symbol.decl) = 0;
+ if (DECL_STATIC_CONSTRUCTOR (node->decl))
+ DECL_STATIC_CONSTRUCTOR (node->decl) = 0;
+ if (DECL_STATIC_DESTRUCTOR (node->decl))
+ DECL_STATIC_DESTRUCTOR (node->decl) = 0;
}
- TREE_READONLY (node->symbol.decl) = data != NULL;
- DECL_LOOPING_CONST_OR_PURE_P (node->symbol.decl) = ((size_t)data & 2) != 0;
+ TREE_READONLY (node->decl) = data != NULL;
+ DECL_LOOPING_CONST_OR_PURE_P (node->decl) = ((size_t)data & 2) != 0;
return false;
}
@@ -2260,13 +2266,13 @@ cgraph_set_pure_flag_1 (struct cgraph_node *node, void *data)
optimized out. */
if (data && !((size_t)data & 2))
{
- if (DECL_STATIC_CONSTRUCTOR (node->symbol.decl))
- DECL_STATIC_CONSTRUCTOR (node->symbol.decl) = 0;
- if (DECL_STATIC_DESTRUCTOR (node->symbol.decl))
- DECL_STATIC_DESTRUCTOR (node->symbol.decl) = 0;
+ if (DECL_STATIC_CONSTRUCTOR (node->decl))
+ DECL_STATIC_CONSTRUCTOR (node->decl) = 0;
+ if (DECL_STATIC_DESTRUCTOR (node->decl))
+ DECL_STATIC_DESTRUCTOR (node->decl) = 0;
}
- DECL_PURE_P (node->symbol.decl) = data != NULL;
- DECL_LOOPING_CONST_OR_PURE_P (node->symbol.decl) = ((size_t)data & 2) != 0;
+ DECL_PURE_P (node->decl) = data != NULL;
+ DECL_LOOPING_CONST_OR_PURE_P (node->decl) = ((size_t)data & 2) != 0;
return false;
}
@@ -2287,7 +2293,7 @@ cgraph_set_pure_flag (struct cgraph_node *node, bool pure, bool looping)
bool
cgraph_node_cannot_return (struct cgraph_node *node)
{
- int flags = flags_from_decl_or_type (node->symbol.decl);
+ int flags = flags_from_decl_or_type (node->decl);
if (!flag_exceptions)
return (flags & ECF_NORETURN) != 0;
else
@@ -2326,19 +2332,19 @@ cgraph_can_remove_if_no_direct_calls_and_refs_p (struct cgraph_node *node)
{
gcc_assert (!node->global.inlined_to);
/* Extern inlines can always go, we will use the external definition. */
- if (DECL_EXTERNAL (node->symbol.decl))
+ if (DECL_EXTERNAL (node->decl))
return true;
/* When function is needed, we can not remove it. */
- if (node->symbol.force_output || node->symbol.used_from_other_partition)
+ if (node->force_output || node->used_from_other_partition)
return false;
- if (DECL_STATIC_CONSTRUCTOR (node->symbol.decl)
- || DECL_STATIC_DESTRUCTOR (node->symbol.decl))
+ if (DECL_STATIC_CONSTRUCTOR (node->decl)
+ || DECL_STATIC_DESTRUCTOR (node->decl))
return false;
/* Only COMDAT functions can be removed if externally visible. */
- if (node->symbol.externally_visible
- && (!DECL_COMDAT (node->symbol.decl)
- || node->symbol.forced_by_abi
- || symtab_used_from_object_file_p ((symtab_node) node)))
+ if (node->externally_visible
+ && (!DECL_COMDAT (node->decl)
+ || node->forced_by_abi
+ || symtab_used_from_object_file_p (node)))
return false;
return true;
}
@@ -2358,9 +2364,9 @@ bool
cgraph_can_remove_if_no_direct_calls_p (struct cgraph_node *node)
{
/* Extern inlines can always go, we will use the external definition. */
- if (DECL_EXTERNAL (node->symbol.decl))
+ if (DECL_EXTERNAL (node->decl))
return true;
- if (node->symbol.address_taken)
+ if (node->address_taken)
return false;
return !cgraph_for_node_and_aliases (node, nonremovable_p, NULL, true);
}
@@ -2370,7 +2376,7 @@ cgraph_can_remove_if_no_direct_calls_p (struct cgraph_node *node)
static bool
used_from_object_file_p (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
{
- return symtab_used_from_object_file_p ((symtab_node) node);
+ return symtab_used_from_object_file_p (node);
}
/* Return true when function NODE can be expected to be removed
@@ -2397,7 +2403,7 @@ cgraph_will_be_removed_from_program_if_no_direct_calls (struct cgraph_node *node
return cgraph_only_called_directly_p (node);
else
{
- if (DECL_EXTERNAL (node->symbol.decl))
+ if (DECL_EXTERNAL (node->decl))
return true;
return cgraph_can_remove_if_no_direct_calls_p (node);
}
@@ -2487,7 +2493,7 @@ verify_edge_count_and_frequency (struct cgraph_edge *e)
error ("caller edge frequency is too large");
error_found = true;
}
- if (gimple_has_body_p (e->caller->symbol.decl)
+ if (gimple_has_body_p (e->caller->decl)
&& !e->caller->global.inlined_to
&& !e->speculative
/* FIXME: Inline-analysis sets frequency to 0 when edge is optimized out.
@@ -2497,12 +2503,12 @@ verify_edge_count_and_frequency (struct cgraph_edge *e)
&& ((inline_edge_summary_vec.length () <= (unsigned) e->uid)
|| !inline_edge_summary (e)->predicate)))
&& (e->frequency
- != compute_call_stmt_bb_frequency (e->caller->symbol.decl,
+ != compute_call_stmt_bb_frequency (e->caller->decl,
gimple_bb (e->call_stmt))))
{
error ("caller edge frequency %i does not match BB frequency %i",
e->frequency,
- compute_call_stmt_bb_frequency (e->caller->symbol.decl,
+ compute_call_stmt_bb_frequency (e->caller->decl,
gimple_bb (e->call_stmt)));
error_found = true;
}
@@ -2544,11 +2550,11 @@ verify_edge_corresponds_to_fndecl (struct cgraph_edge *e, tree decl)
/* We do not know if a node from a different partition is an alias or what it
aliases and therefore cannot do the former_clone_of check reliably. */
- if (!node || node->symbol.in_other_partition || e->callee->symbol.in_other_partition)
+ if (!node || node->in_other_partition || e->callee->in_other_partition)
return false;
node = cgraph_function_or_thunk_node (node, NULL);
- if (e->callee->former_clone_of != node->symbol.decl
+ if (e->callee->former_clone_of != node->decl
/* IPA-CP sometimes redirect edge to clone and then back to the former
function. This ping-pong has to go, eventually. */
&& (node != cgraph_function_or_thunk_node (e->callee, NULL))
@@ -2563,7 +2569,7 @@ DEBUG_FUNCTION void
verify_cgraph_node (struct cgraph_node *node)
{
struct cgraph_edge *e;
- struct function *this_cfun = DECL_STRUCT_FUNCTION (node->symbol.decl);
+ struct function *this_cfun = DECL_STRUCT_FUNCTION (node->decl);
basic_block this_block;
gimple_stmt_iterator gsi;
bool error_found = false;
@@ -2572,7 +2578,7 @@ verify_cgraph_node (struct cgraph_node *node)
return;
timevar_push (TV_CGRAPH_VERIFY);
- error_found |= verify_symtab_base ((symtab_node) node);
+ error_found |= verify_symtab_base (node);
for (e = node->callees; e; e = e->next_callee)
if (e->aux)
{
@@ -2586,27 +2592,27 @@ verify_cgraph_node (struct cgraph_node *node)
error ("execution count is negative");
error_found = true;
}
- if (node->global.inlined_to && node->symbol.same_comdat_group)
+ if (node->global.inlined_to && node->same_comdat_group)
{
error ("inline clone in same comdat group list");
error_found = true;
}
- if (!node->symbol.definition && !node->symbol.in_other_partition && node->local.local)
+ if (!node->definition && !node->in_other_partition && node->local.local)
{
error ("local symbols must be defined");
error_found = true;
}
- if (node->global.inlined_to && node->symbol.externally_visible)
+ if (node->global.inlined_to && node->externally_visible)
{
error ("externally visible inline clone");
error_found = true;
}
- if (node->global.inlined_to && node->symbol.address_taken)
+ if (node->global.inlined_to && node->address_taken)
{
error ("inline clone with address taken");
error_found = true;
}
- if (node->global.inlined_to && node->symbol.force_output)
+ if (node->global.inlined_to && node->force_output)
{
error ("inline clone is forced to output");
error_found = true;
@@ -2709,7 +2715,7 @@ verify_cgraph_node (struct cgraph_node *node)
error_found = true;
}
- if (node->symbol.analyzed && node->symbol.alias)
+ if (node->analyzed && node->alias)
{
bool ref_found = false;
int i;
@@ -2720,7 +2726,7 @@ verify_cgraph_node (struct cgraph_node *node)
error ("Alias has call edges");
error_found = true;
}
- for (i = 0; ipa_ref_list_reference_iterate (&node->symbol.ref_list,
+ for (i = 0; ipa_ref_list_reference_iterate (&node->ref_list,
i, ref); i++)
if (ref->use != IPA_REF_ALIAS)
{
@@ -2740,7 +2746,7 @@ verify_cgraph_node (struct cgraph_node *node)
error_found = true;
}
}
- if (node->symbol.analyzed && node->thunk.thunk_p)
+ if (node->analyzed && node->thunk.thunk_p)
{
if (!node->callees)
{
@@ -2752,15 +2758,15 @@ verify_cgraph_node (struct cgraph_node *node)
error ("More than one edge out of thunk node");
error_found = true;
}
- if (gimple_has_body_p (node->symbol.decl))
+ if (gimple_has_body_p (node->decl))
{
error ("Thunk is not supposed to have body");
error_found = true;
}
}
- else if (node->symbol.analyzed && gimple_has_body_p (node->symbol.decl)
- && !TREE_ASM_WRITTEN (node->symbol.decl)
- && (!DECL_EXTERNAL (node->symbol.decl) || node->global.inlined_to)
+ else if (node->analyzed && gimple_has_body_p (node->decl)
+ && !TREE_ASM_WRITTEN (node->decl)
+ && (!DECL_EXTERNAL (node->decl) || node->global.inlined_to)
&& !flag_wpa)
{
if (this_cfun->cfg)
@@ -2799,7 +2805,7 @@ verify_cgraph_node (struct cgraph_node *node)
if (verify_edge_corresponds_to_fndecl (e, decl))
{
error ("edge points to wrong declaration:");
- debug_tree (e->callee->symbol.decl);
+ debug_tree (e->callee->decl);
fprintf (stderr," Instead of:");
debug_tree (decl);
error_found = true;
@@ -2825,7 +2831,7 @@ verify_cgraph_node (struct cgraph_node *node)
}
}
for (i = 0;
- ipa_ref_list_reference_iterate (&node->symbol.ref_list, i, ref);
+ ipa_ref_list_reference_iterate (&node->ref_list, i, ref);
i++)
if (ref->stmt && !pointer_set_contains (stmts, ref->stmt))
{
@@ -2914,17 +2920,17 @@ cgraph_get_create_real_symbol_node (tree decl)
{
first_clone->clone_of = node;
node->clones = first_clone;
- symtab_prevail_in_asm_name_hash ((symtab_node) node);
- symtab_insert_node_to_hashtable ((symtab_node) node);
+ symtab_prevail_in_asm_name_hash (node);
+ symtab_insert_node_to_hashtable (node);
if (dump_file)
fprintf (dump_file, "Introduced new external node "
"(%s/%i) and turned into root of the clone tree.\n",
- xstrdup (cgraph_node_name (node)), node->symbol.order);
+ xstrdup (cgraph_node_name (node)), node->order);
}
else if (dump_file)
fprintf (dump_file, "Introduced new external node "
"(%s/%i).\n", xstrdup (cgraph_node_name (node)),
- node->symbol.order);
+ node->order);
return node;
}
@@ -2963,14 +2969,14 @@ cgraph_get_body (struct cgraph_node *node)
struct lto_file_decl_data *file_data;
const char *data, *name;
size_t len;
- tree decl = node->symbol.decl;
+ tree decl = node->decl;
if (DECL_RESULT (decl))
return false;
gcc_assert (in_lto_p);
- file_data = node->symbol.lto_file_data;
+ file_data = node->lto_file_data;
name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
/* We may have renamed the declaration, e.g., a static function. */
@@ -2992,7 +2998,102 @@ cgraph_get_body (struct cgraph_node *node)
lto_stats.num_function_bodies++;
lto_free_section_data (file_data, LTO_section_function_body, name,
data, len);
- lto_free_function_in_decl_state_for_node ((symtab_node) node);
+ lto_free_function_in_decl_state_for_node (node);
+ return true;
+}
+
+/* Verify if the type of the argument matches that of the function
+ declaration. If we cannot verify this or there is a mismatch,
+ return false. */
+
+static bool
+gimple_check_call_args (gimple stmt, tree fndecl, bool args_count_match)
+{
+ tree parms, p;
+ unsigned int i, nargs;
+
+ /* Calls to internal functions always match their signature. */
+ if (gimple_call_internal_p (stmt))
+ return true;
+
+ nargs = gimple_call_num_args (stmt);
+
+ /* Get argument types for verification. */
+ if (fndecl)
+ parms = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
+ else
+ parms = TYPE_ARG_TYPES (gimple_call_fntype (stmt));
+
+ /* Verify if the type of the argument matches that of the function
+ declaration. If we cannot verify this or there is a mismatch,
+ return false. */
+ if (fndecl && DECL_ARGUMENTS (fndecl))
+ {
+ for (i = 0, p = DECL_ARGUMENTS (fndecl);
+ i < nargs;
+ i++, p = DECL_CHAIN (p))
+ {
+ tree arg;
+ /* We cannot distinguish a varargs function from the case
+ of excess parameters, still deferring the inlining decision
+ to the callee is possible. */
+ if (!p)
+ break;
+ arg = gimple_call_arg (stmt, i);
+ if (p == error_mark_node
+ || arg == error_mark_node
+ || (!types_compatible_p (DECL_ARG_TYPE (p), TREE_TYPE (arg))
+ && !fold_convertible_p (DECL_ARG_TYPE (p), arg)))
+ return false;
+ }
+ if (args_count_match && p)
+ return false;
+ }
+ else if (parms)
+ {
+ for (i = 0, p = parms; i < nargs; i++, p = TREE_CHAIN (p))
+ {
+ tree arg;
+ /* If this is a varargs function defer inlining decision
+ to callee. */
+ if (!p)
+ break;
+ arg = gimple_call_arg (stmt, i);
+ if (TREE_VALUE (p) == error_mark_node
+ || arg == error_mark_node
+ || TREE_CODE (TREE_VALUE (p)) == VOID_TYPE
+ || (!types_compatible_p (TREE_VALUE (p), TREE_TYPE (arg))
+ && !fold_convertible_p (TREE_VALUE (p), arg)))
+ return false;
+ }
+ }
+ else
+ {
+ if (nargs != 0)
+ return false;
+ }
+ return true;
+}
+
+/* Verify if the type of the argument and lhs of CALL_STMT matches
+ that of the function declaration CALLEE. If ARGS_COUNT_MATCH is
+ true, the arg count needs to be the same.
+ If we cannot verify this or there is a mismatch, return false. */
+
+bool
+gimple_check_call_matching_types (gimple call_stmt, tree callee,
+ bool args_count_match)
+{
+ tree lhs;
+
+ if ((DECL_RESULT (callee)
+ && !DECL_BY_REFERENCE (DECL_RESULT (callee))
+ && (lhs = gimple_call_lhs (call_stmt)) != NULL_TREE
+ && !useless_type_conversion_p (TREE_TYPE (DECL_RESULT (callee)),
+ TREE_TYPE (lhs))
+ && !fold_convertible_p (TREE_TYPE (DECL_RESULT (callee)), lhs))
+ || !gimple_check_call_args (call_stmt, callee, args_count_match))
+ return false;
return true;
}
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index 50e8743bbf7..dd99dc830b6 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -24,7 +24,6 @@ along with GCC; see the file COPYING3. If not see
#include "is-a.h"
#include "plugin-api.h"
#include "vec.h"
-#include "tree.h"
#include "basic-block.h"
#include "function.h"
#include "ipa-ref.h"
@@ -40,8 +39,11 @@ enum symtab_type
/* Base of all entries in the symbol table.
The symtab_node is inherited by cgraph and varpol nodes. */
-struct GTY(()) symtab_node_base
+class GTY((desc ("%h.type"), tag ("SYMTAB_SYMBOL"),
+ chain_next ("%h.next"), chain_prev ("%h.previous")))
+ symtab_node
{
+public:
/* Type of the symbol. */
ENUM_BITFIELD (symtab_type) type : 8;
@@ -111,8 +113,8 @@ struct GTY(()) symtab_node_base
tree decl;
/* Linked list of symbol table entries starting with symtab_nodes. */
- symtab_node next;
- symtab_node previous;
+ 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
@@ -123,11 +125,11 @@ struct GTY(()) symtab_node_base
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;
+ 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;
+ symtab_node *same_comdat_group;
/* Vectors of referring and referenced entities. */
struct ipa_ref_list ref_list;
@@ -252,25 +254,19 @@ struct GTY(()) cgraph_clone_info
/* The cgraph data structure.
Each function decl has assigned cgraph_node listing callees and callers. */
-struct GTY(()) cgraph_node {
- struct symtab_node_base symbol;
+struct GTY((tag ("SYMTAB_FUNCTION"))) cgraph_node : public symtab_node {
+public:
struct cgraph_edge *callees;
struct cgraph_edge *callers;
/* List of edges representing indirect calls with a yet undetermined
callee. */
struct cgraph_edge *indirect_calls;
/* For nested functions points to function the node is nested in. */
- struct cgraph_node *
- GTY ((nested_ptr (union symtab_node_def, "(struct cgraph_node *)(%h)", "(symtab_node)%h")))
- origin;
+ struct cgraph_node *origin;
/* Points to first nested function, if any. */
- struct cgraph_node *
- GTY ((nested_ptr (union symtab_node_def, "(struct cgraph_node *)(%h)", "(symtab_node)%h")))
- nested;
+ struct cgraph_node *nested;
/* Pointer to the next function with same origin, if any. */
- struct cgraph_node *
- GTY ((nested_ptr (union symtab_node_def, "(struct cgraph_node *)(%h)", "(symtab_node)%h")))
- next_nested;
+ struct cgraph_node *next_nested;
/* Pointer to the next clone. */
struct cgraph_node *next_sibling_clone;
struct cgraph_node *prev_sibling_clone;
@@ -302,6 +298,8 @@ struct GTY(()) cgraph_node {
int uid;
/* ID assigned by the profiling. */
unsigned int profile_id;
+ /* Time profiler: first run of function. */
+ int tp_first_run;
/* Set when decl is an abstract function pointed to by the
ABSTRACT_DECL_ORIGIN of a reachable function. */
@@ -518,9 +516,8 @@ typedef struct cgraph_edge *cgraph_edge_p;
/* The varpool data structure.
Each static variable decl has assigned varpool_node. */
-struct GTY(()) varpool_node {
- struct symtab_node_base symbol;
-
+class GTY((tag ("SYMTAB_VARIABLE"))) varpool_node : public symtab_node {
+public:
/* Set when variable is scheduled to be assembled. */
unsigned output : 1;
};
@@ -536,24 +533,14 @@ struct GTY(()) asm_node {
int order;
};
-/* Symbol table entry. */
-union GTY((desc ("%h.symbol.type"), chain_next ("%h.symbol.next"),
- chain_prev ("%h.symbol.previous"))) symtab_node_def {
- struct symtab_node_base GTY ((tag ("SYMTAB_SYMBOL"))) symbol;
- /* To access the following fields,
- use the use dyn_cast or as_a to obtain the concrete type. */
- struct cgraph_node GTY ((tag ("SYMTAB_FUNCTION"))) x_function;
- struct varpool_node GTY ((tag ("SYMTAB_VARIABLE"))) x_variable;
-};
-
/* 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_def *p)
+is_a_helper <cgraph_node>::test (symtab_node *p)
{
- return p->symbol.type == SYMTAB_FUNCTION;
+ return p->type == SYMTAB_FUNCTION;
}
/* Report whether or not THIS symtab node is a vriable, aka varpool_node. */
@@ -561,12 +548,12 @@ is_a_helper <cgraph_node>::test (symtab_node_def *p)
template <>
template <>
inline bool
-is_a_helper <varpool_node>::test (symtab_node_def *p)
+is_a_helper <varpool_node>::test (symtab_node *p)
{
- return p->symbol.type == SYMTAB_VARIABLE;
+ return p->type == SYMTAB_VARIABLE;
}
-extern GTY(()) symtab_node symtab_nodes;
+extern GTY(()) symtab_node *symtab_nodes;
extern GTY(()) int cgraph_n_nodes;
extern GTY(()) int cgraph_max_uid;
extern GTY(()) int cgraph_edge_max_uid;
@@ -597,37 +584,37 @@ extern GTY(()) int symtab_order;
extern bool cpp_implicit_aliases_done;
/* In symtab.c */
-void symtab_register_node (symtab_node);
-void symtab_unregister_node (symtab_node);
-void symtab_remove_node (symtab_node);
-symtab_node symtab_get_node (const_tree);
-symtab_node symtab_node_for_asm (const_tree asmname);
-const char * symtab_node_asm_name (symtab_node);
-const char * symtab_node_name (symtab_node);
-void symtab_insert_node_to_hashtable (symtab_node);
-void symtab_add_to_same_comdat_group (symtab_node, symtab_node);
-void symtab_dissolve_same_comdat_group_list (symtab_node node);
+void symtab_register_node (symtab_node *);
+void symtab_unregister_node (symtab_node *);
+void symtab_remove_node (symtab_node *);
+symtab_node *symtab_get_node (const_tree);
+symtab_node *symtab_node_for_asm (const_tree asmname);
+const char * symtab_node_asm_name (symtab_node *);
+const char * symtab_node_name (symtab_node *);
+void symtab_insert_node_to_hashtable (symtab_node *);
+void symtab_add_to_same_comdat_group (symtab_node *, symtab_node *);
+void symtab_dissolve_same_comdat_group_list (symtab_node *node);
void dump_symtab (FILE *);
void debug_symtab (void);
-void dump_symtab_node (FILE *, symtab_node);
-void debug_symtab_node (symtab_node);
-void dump_symtab_base (FILE *, symtab_node);
+void dump_symtab_node (FILE *, symtab_node *);
+void debug_symtab_node (symtab_node *);
+void dump_symtab_base (FILE *, symtab_node *);
void verify_symtab (void);
-void verify_symtab_node (symtab_node);
-bool verify_symtab_base (symtab_node);
-bool symtab_used_from_object_file_p (symtab_node);
+void verify_symtab_node (symtab_node *);
+bool verify_symtab_base (symtab_node *);
+bool symtab_used_from_object_file_p (symtab_node *);
void symtab_make_decl_local (tree);
-symtab_node symtab_alias_ultimate_target (symtab_node,
+symtab_node *symtab_alias_ultimate_target (symtab_node *,
enum availability *avail = NULL);
-bool symtab_resolve_alias (symtab_node node, symtab_node target);
-void fixup_same_cpp_alias_visibility (symtab_node node, symtab_node target);
-bool symtab_for_node_and_aliases (symtab_node,
- bool (*) (symtab_node, void *),
+bool symtab_resolve_alias (symtab_node *node, symtab_node *target);
+void fixup_same_cpp_alias_visibility (symtab_node *node, symtab_node *target);
+bool symtab_for_node_and_aliases (symtab_node *,
+ bool (*) (symtab_node *, void *),
void *,
bool);
-symtab_node symtab_nonoverwritable_alias (symtab_node);
-enum availability symtab_node_availability (symtab_node);
-bool symtab_semantically_equivalent_p (symtab_node, symtab_node);
+symtab_node *symtab_nonoverwritable_alias (symtab_node *);
+enum availability symtab_node_availability (symtab_node *);
+bool symtab_semantically_equivalent_p (symtab_node *, symtab_node *);
/* In cgraph.c */
void dump_cgraph (FILE *);
@@ -742,6 +729,7 @@ void cgraph_speculative_call_info (struct cgraph_edge *,
struct cgraph_edge *&,
struct cgraph_edge *&,
struct ipa_ref *&);
+extern bool gimple_check_call_matching_types (gimple, tree, bool);
/* In cgraphunit.c */
struct asm_node *add_asm_node (tree);
@@ -752,7 +740,7 @@ void compile (void);
void init_cgraph (void);
bool cgraph_process_new_functions (void);
void cgraph_process_same_body_aliases (void);
-void fixup_same_cpp_alias_visibility (symtab_node, symtab_node target, tree);
+void fixup_same_cpp_alias_visibility (symtab_node *, symtab_node *target, tree);
/* 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);
@@ -856,23 +844,23 @@ bool varpool_for_node_and_aliases (struct varpool_node *,
void *, bool);
void varpool_add_new_variable (tree);
void symtab_initialize_asm_name_hash (void);
-void symtab_prevail_in_asm_name_hash (symtab_node node);
+void symtab_prevail_in_asm_name_hash (symtab_node *node);
void varpool_remove_initializer (struct varpool_node *);
/* Return callgraph node for given symbol and check it is a function. */
static inline struct cgraph_node *
-cgraph (symtab_node node)
+cgraph (symtab_node *node)
{
- gcc_checking_assert (!node || node->symbol.type == SYMTAB_FUNCTION);
+ gcc_checking_assert (!node || node->type == SYMTAB_FUNCTION);
return (struct cgraph_node *)node;
}
/* Return varpool node for given symbol and check it is a variable. */
static inline struct varpool_node *
-varpool (symtab_node node)
+varpool (symtab_node *node)
{
- gcc_checking_assert (!node || node->symbol.type == SYMTAB_VARIABLE);
+ gcc_checking_assert (!node || node->type == SYMTAB_VARIABLE);
return (struct varpool_node *)node;
}
@@ -896,41 +884,41 @@ varpool_get_node (const_tree decl)
static inline const char *
cgraph_node_asm_name (struct cgraph_node *node)
{
- return symtab_node_asm_name ((symtab_node)node);
+ return symtab_node_asm_name (node);
}
/* Return asm name of varpool node. */
static inline const char *
-varpool_node_asm_name(struct varpool_node *node)
+varpool_node_asm_name (struct varpool_node *node)
{
- return symtab_node_asm_name ((symtab_node)node);
+ return symtab_node_asm_name (node);
}
/* Return name of cgraph node. */
static inline const char *
-cgraph_node_name(struct cgraph_node *node)
+cgraph_node_name (struct cgraph_node *node)
{
- return symtab_node_name ((symtab_node)node);
+ return symtab_node_name (node);
}
/* Return name of varpool node. */
static inline const char *
-varpool_node_name(struct varpool_node *node)
+varpool_node_name (struct varpool_node *node)
{
- return symtab_node_name ((symtab_node)node);
+ return symtab_node_name (node);
}
/* Walk all symbols. */
#define FOR_EACH_SYMBOL(node) \
- for ((node) = symtab_nodes; (node); (node) = (node)->symbol.next)
+ for ((node) = symtab_nodes; (node); (node) = (node)->next)
/* Return first variable. */
static inline struct varpool_node *
varpool_first_variable (void)
{
- symtab_node node;
- for (node = symtab_nodes; node; node = node->symbol.next)
+ symtab_node *node;
+ for (node = symtab_nodes; node; node = node->next)
if (varpool_node *vnode = dyn_cast <varpool_node> (node))
return vnode;
return NULL;
@@ -940,8 +928,8 @@ varpool_first_variable (void)
static inline struct varpool_node *
varpool_next_variable (struct varpool_node *node)
{
- symtab_node node1 = (symtab_node) node->symbol.next;
- for (; node1; node1 = node1->symbol.next)
+ symtab_node *node1 = node->next;
+ for (; node1; node1 = node1->next)
if (varpool_node *vnode1 = dyn_cast <varpool_node> (node1))
return vnode1;
return NULL;
@@ -956,11 +944,11 @@ varpool_next_variable (struct varpool_node *node)
static inline struct varpool_node *
varpool_first_static_initializer (void)
{
- symtab_node node;
- for (node = symtab_nodes; node; node = node->symbol.next)
+ symtab_node *node;
+ for (node = symtab_nodes; node; node = node->next)
{
varpool_node *vnode = dyn_cast <varpool_node> (node);
- if (vnode && DECL_INITIAL (node->symbol.decl))
+ if (vnode && DECL_INITIAL (node->decl))
return vnode;
}
return NULL;
@@ -970,11 +958,11 @@ varpool_first_static_initializer (void)
static inline struct varpool_node *
varpool_next_static_initializer (struct varpool_node *node)
{
- symtab_node node1 = (symtab_node) node->symbol.next;
- for (; node1; node1 = node1->symbol.next)
+ symtab_node *node1 = node->next;
+ for (; node1; node1 = node1->next)
{
varpool_node *vnode1 = dyn_cast <varpool_node> (node1);
- if (vnode1 && DECL_INITIAL (node1->symbol.decl))
+ if (vnode1 && DECL_INITIAL (node1->decl))
return vnode1;
}
return NULL;
@@ -989,11 +977,11 @@ varpool_next_static_initializer (struct varpool_node *node)
static inline struct varpool_node *
varpool_first_defined_variable (void)
{
- symtab_node node;
- for (node = symtab_nodes; node; node = node->symbol.next)
+ symtab_node *node;
+ for (node = symtab_nodes; node; node = node->next)
{
varpool_node *vnode = dyn_cast <varpool_node> (node);
- if (vnode && vnode->symbol.definition)
+ if (vnode && vnode->definition)
return vnode;
}
return NULL;
@@ -1003,11 +991,11 @@ varpool_first_defined_variable (void)
static inline struct varpool_node *
varpool_next_defined_variable (struct varpool_node *node)
{
- symtab_node node1 = (symtab_node) node->symbol.next;
- for (; node1; node1 = node1->symbol.next)
+ symtab_node *node1 = node->next;
+ for (; node1; node1 = node1->next)
{
varpool_node *vnode1 = dyn_cast <varpool_node> (node1);
- if (vnode1 && vnode1->symbol.definition)
+ if (vnode1 && vnode1->definition)
return vnode1;
}
return NULL;
@@ -1021,11 +1009,11 @@ varpool_next_defined_variable (struct varpool_node *node)
static inline struct cgraph_node *
cgraph_first_defined_function (void)
{
- symtab_node node;
- for (node = symtab_nodes; node; node = node->symbol.next)
+ symtab_node *node;
+ for (node = symtab_nodes; node; node = node->next)
{
cgraph_node *cn = dyn_cast <cgraph_node> (node);
- if (cn && cn->symbol.definition)
+ if (cn && cn->definition)
return cn;
}
return NULL;
@@ -1035,11 +1023,11 @@ cgraph_first_defined_function (void)
static inline struct cgraph_node *
cgraph_next_defined_function (struct cgraph_node *node)
{
- symtab_node node1 = (symtab_node) node->symbol.next;
- for (; node1; node1 = node1->symbol.next)
+ symtab_node *node1 = node->next;
+ for (; node1; node1 = node1->next)
{
cgraph_node *cn1 = dyn_cast <cgraph_node> (node1);
- if (cn1 && cn1->symbol.definition)
+ if (cn1 && cn1->definition)
return cn1;
}
return NULL;
@@ -1054,8 +1042,8 @@ cgraph_next_defined_function (struct cgraph_node *node)
static inline struct cgraph_node *
cgraph_first_function (void)
{
- symtab_node node;
- for (node = symtab_nodes; node; node = node->symbol.next)
+ symtab_node *node;
+ for (node = symtab_nodes; node; node = node->next)
if (cgraph_node *cn = dyn_cast <cgraph_node> (node))
return cn;
return NULL;
@@ -1065,8 +1053,8 @@ cgraph_first_function (void)
static inline struct cgraph_node *
cgraph_next_function (struct cgraph_node *node)
{
- symtab_node node1 = (symtab_node) node->symbol.next;
- for (; node1; node1 = node1->symbol.next)
+ symtab_node *node1 = node->next;
+ for (; node1; node1 = node1->next)
if (cgraph_node *cn1 = dyn_cast <cgraph_node> (node1))
return cn1;
return NULL;
@@ -1085,15 +1073,15 @@ cgraph_next_function (struct cgraph_node *node)
static inline bool
cgraph_function_with_gimple_body_p (struct cgraph_node *node)
{
- return node->symbol.definition && !node->thunk.thunk_p && !node->symbol.alias;
+ return node->definition && !node->thunk.thunk_p && !node->alias;
}
/* Return first function with body defined. */
static inline struct cgraph_node *
cgraph_first_function_with_gimple_body (void)
{
- symtab_node node;
- for (node = symtab_nodes; node; node = node->symbol.next)
+ symtab_node *node;
+ for (node = symtab_nodes; node; node = node->next)
{
cgraph_node *cn = dyn_cast <cgraph_node> (node);
if (cn && cgraph_function_with_gimple_body_p (cn))
@@ -1106,8 +1094,8 @@ cgraph_first_function_with_gimple_body (void)
static inline struct cgraph_node *
cgraph_next_function_with_gimple_body (struct cgraph_node *node)
{
- symtab_node node1 = node->symbol.next;
- for (; node1; node1 = node1->symbol.next)
+ symtab_node *node1 = node->next;
+ for (; node1; node1 = node1->next)
{
cgraph_node *cn1 = dyn_cast <cgraph_node> (node1);
if (cn1 && cgraph_function_with_gimple_body_p (cn1))
@@ -1259,12 +1247,12 @@ static inline bool
cgraph_only_called_directly_or_aliased_p (struct cgraph_node *node)
{
gcc_assert (!node->global.inlined_to);
- return (!node->symbol.force_output && !node->symbol.address_taken
- && !node->symbol.used_from_other_partition
- && !DECL_VIRTUAL_P (node->symbol.decl)
- && !DECL_STATIC_CONSTRUCTOR (node->symbol.decl)
- && !DECL_STATIC_DESTRUCTOR (node->symbol.decl)
- && !node->symbol.externally_visible);
+ return (!node->force_output && !node->address_taken
+ && !node->used_from_other_partition
+ && !DECL_VIRTUAL_P (node->decl)
+ && !DECL_STATIC_CONSTRUCTOR (node->decl)
+ && !DECL_STATIC_DESTRUCTOR (node->decl)
+ && !node->externally_visible);
}
/* Return true when function NODE can be removed from callgraph
@@ -1273,14 +1261,14 @@ cgraph_only_called_directly_or_aliased_p (struct cgraph_node *node)
static inline bool
varpool_can_remove_if_no_refs (struct varpool_node *node)
{
- if (DECL_EXTERNAL (node->symbol.decl))
+ if (DECL_EXTERNAL (node->decl))
return true;
- return (!node->symbol.force_output && !node->symbol.used_from_other_partition
- && ((DECL_COMDAT (node->symbol.decl)
- && !node->symbol.forced_by_abi
- && !symtab_used_from_object_file_p ((symtab_node) node))
- || !node->symbol.externally_visible
- || DECL_HAS_VALUE_EXPR_P (node->symbol.decl)));
+ return (!node->force_output && !node->used_from_other_partition
+ && ((DECL_COMDAT (node->decl)
+ && !node->forced_by_abi
+ && !symtab_used_from_object_file_p (node))
+ || !node->externally_visible
+ || DECL_HAS_VALUE_EXPR_P (node->decl)));
}
/* Return true when all references to VNODE must be visible in ipa_ref_list.
@@ -1291,10 +1279,10 @@ varpool_can_remove_if_no_refs (struct varpool_node *node)
static inline bool
varpool_all_refs_explicit_p (struct varpool_node *vnode)
{
- return (vnode->symbol.definition
- && !vnode->symbol.externally_visible
- && !vnode->symbol.used_from_other_partition
- && !vnode->symbol.force_output);
+ return (vnode->definition
+ && !vnode->externally_visible
+ && !vnode->used_from_other_partition
+ && !vnode->force_output);
}
/* Constant pool accessor function. */
@@ -1305,11 +1293,11 @@ htab_t constant_pool_htab (void);
/* Return node that alias N is aliasing. */
-static inline symtab_node
-symtab_alias_target (symtab_node n)
+static inline symtab_node *
+symtab_alias_target (symtab_node *n)
{
struct ipa_ref *ref;
- ipa_ref_list_reference_iterate (&n->symbol.ref_list, 0, ref);
+ ipa_ref_list_reference_iterate (&n->ref_list, 0, ref);
gcc_checking_assert (ref->use == IPA_REF_ALIAS);
return ref->referred;
}
@@ -1317,13 +1305,13 @@ symtab_alias_target (symtab_node n)
static inline struct cgraph_node *
cgraph_alias_target (struct cgraph_node *n)
{
- return dyn_cast <cgraph_node> (symtab_alias_target ((symtab_node) n));
+ return dyn_cast <cgraph_node> (symtab_alias_target (n));
}
static inline struct varpool_node *
varpool_alias_target (struct varpool_node *n)
{
- return dyn_cast <varpool_node> (symtab_alias_target ((symtab_node) n));
+ return dyn_cast <varpool_node> (symtab_alias_target (n));
}
/* Given NODE, walk the alias chain to return the function NODE is alias of.
@@ -1336,7 +1324,7 @@ cgraph_function_or_thunk_node (struct cgraph_node *node,
{
struct cgraph_node *n;
- n = dyn_cast <cgraph_node> (symtab_alias_ultimate_target ((symtab_node)node,
+ n = dyn_cast <cgraph_node> (symtab_alias_ultimate_target (node,
availability));
if (!n && availability)
*availability = AVAIL_NOT_AVAILABLE;
@@ -1352,7 +1340,7 @@ varpool_variable_node (struct varpool_node *node,
{
struct varpool_node *n;
- n = dyn_cast <varpool_node> (symtab_alias_ultimate_target ((symtab_node)node,
+ n = dyn_cast <varpool_node> (symtab_alias_ultimate_target (node,
availability));
if (!n && availability)
*availability = AVAIL_NOT_AVAILABLE;
@@ -1365,9 +1353,9 @@ cgraph_edge_recursive_p (struct cgraph_edge *e)
{
struct cgraph_node *callee = cgraph_function_or_thunk_node (e->callee, NULL);
if (e->caller->global.inlined_to)
- return e->caller->global.inlined_to->symbol.decl == callee->symbol.decl;
+ return e->caller->global.inlined_to->decl == callee->decl;
else
- return e->caller->symbol.decl == callee->symbol.decl;
+ return e->caller->decl == callee->decl;
}
/* Return true if the TM_CLONE bit is set for a given FNDECL. */
@@ -1386,7 +1374,7 @@ decl_is_tm_clone (const_tree fndecl)
static inline void
cgraph_mark_force_output_node (struct cgraph_node *node)
{
- node->symbol.force_output = 1;
+ node->force_output = 1;
gcc_checking_assert (!node->global.inlined_to);
}
@@ -1394,11 +1382,11 @@ cgraph_mark_force_output_node (struct cgraph_node *node)
or abstract function kept for debug info purposes only. */
static inline bool
-symtab_real_symbol_p (symtab_node node)
+symtab_real_symbol_p (symtab_node *node)
{
struct cgraph_node *cnode;
- if (DECL_ABSTRACT (node->symbol.decl))
+ if (DECL_ABSTRACT (node->decl))
return false;
if (!is_a <cgraph_node> (node))
return true;
@@ -1411,12 +1399,12 @@ symtab_real_symbol_p (symtab_node node)
/* Return true if NODE can be discarded by linker from the binary. */
static inline bool
-symtab_can_be_discarded (symtab_node node)
+symtab_can_be_discarded (symtab_node *node)
{
- return (DECL_EXTERNAL (node->symbol.decl)
- || (DECL_ONE_ONLY (node->symbol.decl)
- && node->symbol.resolution != LDPR_PREVAILING_DEF
- && node->symbol.resolution != LDPR_PREVAILING_DEF_IRONLY
- && node->symbol.resolution != LDPR_PREVAILING_DEF_IRONLY_EXP));
+ return (DECL_EXTERNAL (node->decl)
+ || (DECL_ONE_ONLY (node->decl)
+ && node->resolution != LDPR_PREVAILING_DEF
+ && node->resolution != LDPR_PREVAILING_DEF_IRONLY
+ && node->resolution != LDPR_PREVAILING_DEF_IRONLY_EXP));
}
#endif /* GCC_CGRAPH_H */
diff --git a/gcc/cgraphbuild.c b/gcc/cgraphbuild.c
index 98fd12cbb13..87e06e37cbe 100644
--- a/gcc/cgraphbuild.c
+++ b/gcc/cgraphbuild.c
@@ -23,12 +23,10 @@ along with GCC; see the file COPYING3. If not see
#include "coretypes.h"
#include "tm.h"
#include "tree.h"
-#include "tree-ssa.h"
+#include "gimple.h"
#include "langhooks.h"
#include "pointer-set.h"
-#include "cgraph.h"
#include "intl.h"
-#include "gimple.h"
#include "tree-pass.h"
#include "ipa-utils.h"
#include "except.h"
@@ -76,16 +74,16 @@ record_reference (tree *tp, int *walk_subtrees, void *data)
struct cgraph_node *node = cgraph_get_create_real_symbol_node (decl);
if (!ctx->only_vars)
cgraph_mark_address_taken_node (node);
- ipa_record_reference ((symtab_node)ctx->varpool_node,
- (symtab_node)node,
+ ipa_record_reference (ctx->varpool_node,
+ node,
IPA_REF_ADDR, NULL);
}
if (TREE_CODE (decl) == VAR_DECL)
{
struct varpool_node *vnode = varpool_node_for_decl (decl);
- ipa_record_reference ((symtab_node)ctx->varpool_node,
- (symtab_node)vnode,
+ ipa_record_reference (ctx->varpool_node,
+ vnode,
IPA_REF_ADDR, NULL);
}
*walk_subtrees = 0;
@@ -123,8 +121,8 @@ record_type_list (struct cgraph_node *node, tree list)
if (TREE_CODE (type) == VAR_DECL)
{
struct varpool_node *vnode = varpool_node_for_decl (type);
- ipa_record_reference ((symtab_node)node,
- (symtab_node)vnode,
+ ipa_record_reference (node,
+ vnode,
IPA_REF_ADDR, NULL);
}
}
@@ -139,12 +137,12 @@ record_eh_tables (struct cgraph_node *node, struct function *fun)
{
eh_region i;
- if (DECL_FUNCTION_PERSONALITY (node->symbol.decl))
+ if (DECL_FUNCTION_PERSONALITY (node->decl))
{
struct cgraph_node *per_node;
- per_node = cgraph_get_create_real_symbol_node (DECL_FUNCTION_PERSONALITY (node->symbol.decl));
- ipa_record_reference ((symtab_node)node, (symtab_node)per_node, IPA_REF_ADDR, NULL);
+ per_node = cgraph_get_create_real_symbol_node (DECL_FUNCTION_PERSONALITY (node->decl));
+ ipa_record_reference (node, per_node, IPA_REF_ADDR, NULL);
cgraph_mark_address_taken_node (per_node);
}
@@ -225,8 +223,8 @@ mark_address (gimple stmt, tree addr, void *data)
{
struct cgraph_node *node = cgraph_get_create_real_symbol_node (addr);
cgraph_mark_address_taken_node (node);
- ipa_record_reference ((symtab_node)data,
- (symtab_node)node,
+ ipa_record_reference ((symtab_node *)data,
+ node,
IPA_REF_ADDR, stmt);
}
else if (addr && TREE_CODE (addr) == VAR_DECL
@@ -234,8 +232,8 @@ mark_address (gimple stmt, tree addr, void *data)
{
struct varpool_node *vnode = varpool_node_for_decl (addr);
- ipa_record_reference ((symtab_node)data,
- (symtab_node)vnode,
+ ipa_record_reference ((symtab_node *)data,
+ vnode,
IPA_REF_ADDR, stmt);
}
@@ -254,8 +252,8 @@ mark_load (gimple stmt, tree t, void *data)
directly manipulated in the code. Pretend that it's an address. */
struct cgraph_node *node = cgraph_get_create_real_symbol_node (t);
cgraph_mark_address_taken_node (node);
- ipa_record_reference ((symtab_node)data,
- (symtab_node)node,
+ ipa_record_reference ((symtab_node *)data,
+ node,
IPA_REF_ADDR, stmt);
}
else if (t && TREE_CODE (t) == VAR_DECL
@@ -263,8 +261,8 @@ mark_load (gimple stmt, tree t, void *data)
{
struct varpool_node *vnode = varpool_node_for_decl (t);
- ipa_record_reference ((symtab_node)data,
- (symtab_node)vnode,
+ ipa_record_reference ((symtab_node *)data,
+ vnode,
IPA_REF_LOAD, stmt);
}
return false;
@@ -281,8 +279,8 @@ mark_store (gimple stmt, tree t, void *data)
{
struct varpool_node *vnode = varpool_node_for_decl (t);
- ipa_record_reference ((symtab_node)data,
- (symtab_node)vnode,
+ ipa_record_reference ((symtab_node *)data,
+ vnode,
IPA_REF_STORE, stmt);
}
return false;
@@ -339,21 +337,21 @@ build_cgraph_edges (void)
&& gimple_omp_parallel_child_fn (stmt))
{
tree fn = gimple_omp_parallel_child_fn (stmt);
- ipa_record_reference ((symtab_node)node,
- (symtab_node)cgraph_get_create_real_symbol_node (fn),
+ ipa_record_reference (node,
+ cgraph_get_create_real_symbol_node (fn),
IPA_REF_ADDR, stmt);
}
if (gimple_code (stmt) == GIMPLE_OMP_TASK)
{
tree fn = gimple_omp_task_child_fn (stmt);
if (fn)
- ipa_record_reference ((symtab_node)node,
- (symtab_node) cgraph_get_create_real_symbol_node (fn),
+ ipa_record_reference (node,
+ cgraph_get_create_real_symbol_node (fn),
IPA_REF_ADDR, stmt);
fn = gimple_omp_task_copy_fn (stmt);
if (fn)
- ipa_record_reference ((symtab_node)node,
- (symtab_node)cgraph_get_create_real_symbol_node (fn),
+ ipa_record_reference (node,
+ cgraph_get_create_real_symbol_node (fn),
IPA_REF_ADDR, stmt);
}
}
@@ -393,8 +391,8 @@ const pass_data pass_data_build_cgraph_edges =
class pass_build_cgraph_edges : public gimple_opt_pass
{
public:
- pass_build_cgraph_edges(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_build_cgraph_edges, ctxt)
+ pass_build_cgraph_edges (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_build_cgraph_edges, ctxt)
{}
/* opt_pass methods: */
@@ -439,7 +437,7 @@ rebuild_cgraph_edges (void)
gimple_stmt_iterator gsi;
cgraph_node_remove_callees (node);
- ipa_remove_all_references (&node->symbol.ref_list);
+ ipa_remove_all_references (&node->ref_list);
node->count = ENTRY_BLOCK_PTR->count;
@@ -487,7 +485,7 @@ cgraph_rebuild_references (void)
int i;
/* Keep speculative references for further cgraph edge expansion. */
- for (i = 0; ipa_ref_list_reference_iterate (&node->symbol.ref_list, i, ref);)
+ for (i = 0; ipa_ref_list_reference_iterate (&node->ref_list, i, ref);)
if (!ref->speculative)
ipa_remove_reference (ref);
else
@@ -525,12 +523,12 @@ const pass_data pass_data_rebuild_cgraph_edges =
class pass_rebuild_cgraph_edges : public gimple_opt_pass
{
public:
- pass_rebuild_cgraph_edges(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_rebuild_cgraph_edges, ctxt)
+ pass_rebuild_cgraph_edges (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_rebuild_cgraph_edges, ctxt)
{}
/* opt_pass methods: */
- opt_pass * clone () { return new pass_rebuild_cgraph_edges (ctxt_); }
+ opt_pass * clone () { return new pass_rebuild_cgraph_edges (m_ctxt); }
unsigned int execute () { return rebuild_cgraph_edges (); }
}; // class pass_rebuild_cgraph_edges
@@ -549,7 +547,7 @@ remove_cgraph_callee_edges (void)
{
struct cgraph_node *node = cgraph_get_node (current_function_decl);
cgraph_node_remove_callees (node);
- ipa_remove_all_references (&node->symbol.ref_list);
+ ipa_remove_all_references (&node->ref_list);
return 0;
}
@@ -573,13 +571,13 @@ const pass_data pass_data_remove_cgraph_callee_edges =
class pass_remove_cgraph_callee_edges : public gimple_opt_pass
{
public:
- pass_remove_cgraph_callee_edges(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_remove_cgraph_callee_edges, ctxt)
+ pass_remove_cgraph_callee_edges (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_remove_cgraph_callee_edges, ctxt)
{}
/* opt_pass methods: */
opt_pass * clone () {
- return new pass_remove_cgraph_callee_edges (ctxt_);
+ return new pass_remove_cgraph_callee_edges (m_ctxt);
}
unsigned int execute () { return remove_cgraph_callee_edges (); }
diff --git a/gcc/cgraphclones.c b/gcc/cgraphclones.c
index e1aa120dce4..f91fcfc6fd4 100644
--- a/gcc/cgraphclones.c
+++ b/gcc/cgraphclones.c
@@ -69,8 +69,10 @@ along with GCC; see the file COPYING3. If not see
#include "coretypes.h"
#include "tm.h"
#include "tree.h"
+#include "gimple.h"
#include "rtl.h"
-#include "tree-ssa.h"
+#include "bitmap.h"
+#include "tree-cfg.h"
#include "tree-inline.h"
#include "langhooks.h"
#include "pointer-set.h"
@@ -79,13 +81,11 @@ along with GCC; see the file COPYING3. If not see
#include "ggc.h"
#include "debug.h"
#include "target.h"
-#include "cgraph.h"
#include "diagnostic.h"
#include "params.h"
#include "intl.h"
#include "function.h"
#include "ipa-prop.h"
-#include "gimple.h"
#include "tree-iterator.h"
#include "tree-dump.h"
#include "gimple-pretty-print.h"
@@ -187,19 +187,19 @@ cgraph_clone_node (struct cgraph_node *n, tree decl, gcov_type count, int freq,
gcov_type count_scale;
unsigned i;
- new_node->symbol.decl = decl;
- symtab_register_node ((symtab_node)new_node);
+ new_node->decl = decl;
+ symtab_register_node (new_node);
new_node->origin = n->origin;
- new_node->symbol.lto_file_data = n->symbol.lto_file_data;
+ new_node->lto_file_data = n->lto_file_data;
if (new_node->origin)
{
new_node->next_nested = new_node->origin->nested;
new_node->origin->nested = new_node;
}
- new_node->symbol.analyzed = n->symbol.analyzed;
- new_node->symbol.definition = n->symbol.definition;
+ new_node->analyzed = n->analyzed;
+ new_node->definition = n->definition;
new_node->local = n->local;
- new_node->symbol.externally_visible = false;
+ new_node->externally_visible = false;
new_node->local.local = true;
new_node->global = n->global;
new_node->global.inlined_to = new_inlined_to;
@@ -208,6 +208,7 @@ cgraph_clone_node (struct cgraph_node *n, tree decl, gcov_type count, int freq,
new_node->frequency = n->frequency;
new_node->clone = n->clone;
new_node->clone.tree_map = NULL;
+ new_node->tp_first_run = n->tp_first_run;
if (n->count)
{
if (new_node->count > n->count)
@@ -239,7 +240,7 @@ cgraph_clone_node (struct cgraph_node *n, tree decl, gcov_type count, int freq,
for (e = n->indirect_calls; e; e = e->next_callee)
cgraph_clone_edge (e, new_node, e->call_stmt, e->lto_stmt_uid,
count_scale, freq, update_original);
- ipa_clone_references ((symtab_node)new_node, &n->symbol.ref_list);
+ ipa_clone_references (new_node, &n->ref_list);
new_node->next_sibling_clone = n->clones;
if (n->clones)
@@ -277,6 +278,111 @@ clone_function_name (tree decl, const char *suffix)
return get_identifier (tmp_name);
}
+/* Build variant of function type ORIG_TYPE skipping ARGS_TO_SKIP and the
+ return value if SKIP_RETURN is true. */
+
+static tree
+build_function_type_skip_args (tree orig_type, bitmap args_to_skip,
+ bool skip_return)
+{
+ tree new_type = NULL;
+ tree args, new_args = NULL, t;
+ tree new_reversed;
+ int i = 0;
+
+ for (args = TYPE_ARG_TYPES (orig_type); args && args != void_list_node;
+ args = TREE_CHAIN (args), i++)
+ if (!args_to_skip || !bitmap_bit_p (args_to_skip, i))
+ new_args = tree_cons (NULL_TREE, TREE_VALUE (args), new_args);
+
+ new_reversed = nreverse (new_args);
+ if (args)
+ {
+ if (new_reversed)
+ TREE_CHAIN (new_args) = void_list_node;
+ else
+ new_reversed = void_list_node;
+ }
+
+ /* Use copy_node to preserve as much as possible from original type
+ (debug info, attribute lists etc.)
+ Exception is METHOD_TYPEs must have THIS argument.
+ When we are asked to remove it, we need to build new FUNCTION_TYPE
+ instead. */
+ if (TREE_CODE (orig_type) != METHOD_TYPE
+ || !args_to_skip
+ || !bitmap_bit_p (args_to_skip, 0))
+ {
+ new_type = build_distinct_type_copy (orig_type);
+ TYPE_ARG_TYPES (new_type) = new_reversed;
+ }
+ else
+ {
+ new_type
+ = build_distinct_type_copy (build_function_type (TREE_TYPE (orig_type),
+ new_reversed));
+ TYPE_CONTEXT (new_type) = TYPE_CONTEXT (orig_type);
+ }
+
+ if (skip_return)
+ TREE_TYPE (new_type) = void_type_node;
+
+ /* This is a new type, not a copy of an old type. Need to reassociate
+ variants. We can handle everything except the main variant lazily. */
+ t = TYPE_MAIN_VARIANT (orig_type);
+ if (t != orig_type)
+ {
+ t = build_function_type_skip_args (t, args_to_skip, skip_return);
+ TYPE_MAIN_VARIANT (new_type) = t;
+ TYPE_NEXT_VARIANT (new_type) = TYPE_NEXT_VARIANT (t);
+ TYPE_NEXT_VARIANT (t) = new_type;
+ }
+ else
+ {
+ TYPE_MAIN_VARIANT (new_type) = new_type;
+ TYPE_NEXT_VARIANT (new_type) = NULL;
+ }
+
+ return new_type;
+}
+
+/* Build variant of function decl ORIG_DECL skipping ARGS_TO_SKIP and the
+ return value if SKIP_RETURN is true.
+
+ Arguments from DECL_ARGUMENTS list can't be removed now, since they are
+ linked by TREE_CHAIN directly. The caller is responsible for eliminating
+ them when they are being duplicated (i.e. copy_arguments_for_versioning). */
+
+static tree
+build_function_decl_skip_args (tree orig_decl, bitmap args_to_skip,
+ bool skip_return)
+{
+ tree new_decl = copy_node (orig_decl);
+ tree new_type;
+
+ new_type = TREE_TYPE (orig_decl);
+ if (prototype_p (new_type)
+ || (skip_return && !VOID_TYPE_P (TREE_TYPE (new_type))))
+ new_type
+ = build_function_type_skip_args (new_type, args_to_skip, skip_return);
+ TREE_TYPE (new_decl) = new_type;
+
+ /* For declarations setting DECL_VINDEX (i.e. methods)
+ we expect first argument to be THIS pointer. */
+ if (args_to_skip && bitmap_bit_p (args_to_skip, 0))
+ DECL_VINDEX (new_decl) = NULL_TREE;
+
+ /* When signature changes, we need to clear builtin info. */
+ if (DECL_BUILT_IN (new_decl)
+ && args_to_skip
+ && !bitmap_empty_p (args_to_skip))
+ {
+ DECL_BUILT_IN_CLASS (new_decl) = NOT_BUILT_IN;
+ DECL_FUNCTION_CODE (new_decl) = (enum built_in_function) 0;
+ }
+ return new_decl;
+}
+
/* Create callgraph node clone with new declaration. The actual body will
be copied later at compilation stage.
@@ -290,7 +396,7 @@ cgraph_create_virtual_clone (struct cgraph_node *old_node,
bitmap args_to_skip,
const char * suffix)
{
- tree old_decl = old_node->symbol.decl;
+ tree old_decl = old_node->decl;
struct cgraph_node *new_node = NULL;
tree new_decl;
size_t len, i;
@@ -336,16 +442,16 @@ cgraph_create_virtual_clone (struct cgraph_node *old_node,
that is not weak also.
??? We cannot use COMDAT linkage because there is no
ABI support for this. */
- DECL_EXTERNAL (new_node->symbol.decl) = 0;
+ DECL_EXTERNAL (new_node->decl) = 0;
if (DECL_ONE_ONLY (old_decl))
- DECL_SECTION_NAME (new_node->symbol.decl) = NULL;
- DECL_COMDAT_GROUP (new_node->symbol.decl) = 0;
- TREE_PUBLIC (new_node->symbol.decl) = 0;
- DECL_COMDAT (new_node->symbol.decl) = 0;
- DECL_WEAK (new_node->symbol.decl) = 0;
- DECL_VIRTUAL_P (new_node->symbol.decl) = 0;
- DECL_STATIC_CONSTRUCTOR (new_node->symbol.decl) = 0;
- DECL_STATIC_DESTRUCTOR (new_node->symbol.decl) = 0;
+ DECL_SECTION_NAME (new_node->decl) = NULL;
+ DECL_COMDAT_GROUP (new_node->decl) = 0;
+ TREE_PUBLIC (new_node->decl) = 0;
+ DECL_COMDAT (new_node->decl) = 0;
+ DECL_WEAK (new_node->decl) = 0;
+ DECL_VIRTUAL_P (new_node->decl) = 0;
+ DECL_STATIC_CONSTRUCTOR (new_node->decl) = 0;
+ DECL_STATIC_DESTRUCTOR (new_node->decl) = 0;
new_node->clone.tree_map = tree_map;
new_node->clone.args_to_skip = args_to_skip;
@@ -355,9 +461,9 @@ cgraph_create_virtual_clone (struct cgraph_node *old_node,
&& !DECL_WEAK (old_decl)
&& !DECL_COMDAT (old_decl))
|| in_lto_p)
- new_node->symbol.unique_name = true;
+ new_node->unique_name = true;
FOR_EACH_VEC_SAFE_ELT (tree_map, i, map)
- ipa_maybe_record_reference ((symtab_node) new_node, map->new_tree,
+ ipa_maybe_record_reference (new_node, map->new_tree,
IPA_REF_ADDR, NULL);
if (!args_to_skip)
new_node->clone.combined_args_to_skip = old_node->clone.combined_args_to_skip;
@@ -369,7 +475,7 @@ cgraph_create_virtual_clone (struct cgraph_node *old_node,
struct cgraph_node *orig_node;
for (orig_node = old_node; orig_node->clone_of; orig_node = orig_node->clone_of)
;
- for (arg = DECL_ARGUMENTS (orig_node->symbol.decl);
+ for (arg = DECL_ARGUMENTS (orig_node->decl);
arg; arg = DECL_CHAIN (arg), oldi++)
{
if (bitmap_bit_p (old_node->clone.combined_args_to_skip, oldi))
@@ -385,7 +491,7 @@ cgraph_create_virtual_clone (struct cgraph_node *old_node,
}
else
new_node->clone.combined_args_to_skip = args_to_skip;
- new_node->symbol.externally_visible = 0;
+ new_node->externally_visible = 0;
new_node->local.local = 1;
new_node->lowered = true;
@@ -404,7 +510,7 @@ cgraph_find_replacement_node (struct cgraph_node *node)
for (next_inline_clone = node->clones;
next_inline_clone
- && next_inline_clone->symbol.decl != node->symbol.decl;
+ && next_inline_clone->decl != node->decl;
next_inline_clone = next_inline_clone->next_sibling_clone)
;
@@ -631,8 +737,8 @@ update_call_expr (struct cgraph_node *new_version)
/* Update the call expr on the edges to call the new version. */
for (e = new_version->callers; e; e = e->next_caller)
{
- struct function *inner_function = DECL_STRUCT_FUNCTION (e->caller->symbol.decl);
- gimple_call_set_fndecl (e->call_stmt, new_version->symbol.decl);
+ struct function *inner_function = DECL_STRUCT_FUNCTION (e->caller->decl);
+ gimple_call_set_fndecl (e->call_stmt, new_version->decl);
maybe_clean_eh_stmt_fn (inner_function, e->call_stmt);
}
}
@@ -663,11 +769,11 @@ cgraph_copy_node_for_versioning (struct cgraph_node *old_version,
new_version = cgraph_create_node (new_decl);
- new_version->symbol.analyzed = old_version->symbol.analyzed;
- new_version->symbol.definition = old_version->symbol.definition;
+ new_version->analyzed = old_version->analyzed;
+ new_version->definition = old_version->definition;
new_version->local = old_version->local;
- new_version->symbol.externally_visible = false;
- new_version->local.local = new_version->symbol.definition;
+ new_version->externally_visible = false;
+ new_version->local.local = new_version->definition;
new_version->global = old_version->global;
new_version->rtl = old_version->rtl;
new_version->count = old_version->count;
@@ -728,7 +834,7 @@ cgraph_function_versioning (struct cgraph_node *old_version_node,
basic_block new_entry_block,
const char *clone_name)
{
- tree old_decl = old_version_node->symbol.decl;
+ tree old_decl = old_version_node->decl;
struct cgraph_node *new_version_node = NULL;
tree new_decl;
@@ -750,8 +856,8 @@ cgraph_function_versioning (struct cgraph_node *old_version_node,
SET_DECL_RTL (new_decl, NULL);
/* When the old decl was a con-/destructor make sure the clone isn't. */
- DECL_STATIC_CONSTRUCTOR(new_decl) = 0;
- DECL_STATIC_DESTRUCTOR(new_decl) = 0;
+ DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
+ DECL_STATIC_DESTRUCTOR (new_decl) = 0;
/* Create the new version's call-graph node.
and update the edges of the new node. */
@@ -768,9 +874,9 @@ cgraph_function_versioning (struct cgraph_node *old_version_node,
that is not weak also.
??? We cannot use COMDAT linkage because there is no
ABI support for this. */
- symtab_make_decl_local (new_version_node->symbol.decl);
- DECL_VIRTUAL_P (new_version_node->symbol.decl) = 0;
- new_version_node->symbol.externally_visible = 0;
+ symtab_make_decl_local (new_version_node->decl);
+ DECL_VIRTUAL_P (new_version_node->decl) = 0;
+ new_version_node->externally_visible = 0;
new_version_node->local.local = 1;
new_version_node->lowered = true;
/* Clones of global symbols or symbols with unique names are unique. */
@@ -779,7 +885,7 @@ cgraph_function_versioning (struct cgraph_node *old_version_node,
&& !DECL_WEAK (old_decl)
&& !DECL_COMDAT (old_decl))
|| in_lto_p)
- new_version_node->symbol.unique_name = true;
+ new_version_node->unique_name = true;
/* Update the call_expr on the edges to call the new version node. */
update_call_expr (new_version_node);
@@ -794,18 +900,18 @@ static void
cgraph_materialize_clone (struct cgraph_node *node)
{
bitmap_obstack_initialize (NULL);
- node->former_clone_of = node->clone_of->symbol.decl;
+ node->former_clone_of = node->clone_of->decl;
if (node->clone_of->former_clone_of)
node->former_clone_of = node->clone_of->former_clone_of;
/* Copy the OLD_VERSION_NODE function tree to the new version. */
- tree_function_versioning (node->clone_of->symbol.decl, node->symbol.decl,
+ tree_function_versioning (node->clone_of->decl, node->decl,
node->clone.tree_map, true,
node->clone.args_to_skip, false,
NULL, NULL);
if (cgraph_dump_file)
{
- dump_function_to_file (node->clone_of->symbol.decl, cgraph_dump_file, dump_flags);
- dump_function_to_file (node->symbol.decl, cgraph_dump_file, dump_flags);
+ dump_function_to_file (node->clone_of->decl, cgraph_dump_file, dump_flags);
+ dump_function_to_file (node->decl, cgraph_dump_file, dump_flags);
}
/* Function is no longer clone. */
@@ -817,11 +923,11 @@ cgraph_materialize_clone (struct cgraph_node *node)
node->clone_of->clones = node->next_sibling_clone;
node->next_sibling_clone = NULL;
node->prev_sibling_clone = NULL;
- if (!node->clone_of->symbol.analyzed && !node->clone_of->clones)
+ if (!node->clone_of->analyzed && !node->clone_of->clones)
{
cgraph_release_function_body (node->clone_of);
cgraph_node_remove_callees (node->clone_of);
- ipa_remove_all_references (&node->clone_of->symbol.ref_list);
+ ipa_remove_all_references (&node->clone_of->ref_list);
}
node->clone_of = NULL;
bitmap_obstack_release (NULL);
@@ -854,12 +960,12 @@ cgraph_materialize_all_clones (void)
stabilized = true;
FOR_EACH_FUNCTION (node)
{
- if (node->clone_of && node->symbol.decl != node->clone_of->symbol.decl
- && !gimple_has_body_p (node->symbol.decl))
+ if (node->clone_of && node->decl != node->clone_of->decl
+ && !gimple_has_body_p (node->decl))
{
if (!node->clone_of->clone_of)
cgraph_get_body (node->clone_of);
- if (gimple_has_body_p (node->clone_of->symbol.decl))
+ if (gimple_has_body_p (node->clone_of->decl))
{
if (cgraph_dump_file)
{
@@ -903,13 +1009,13 @@ cgraph_materialize_all_clones (void)
}
}
FOR_EACH_FUNCTION (node)
- if (!node->symbol.analyzed && node->callees)
+ if (!node->analyzed && node->callees)
{
cgraph_node_remove_callees (node);
- ipa_remove_all_references (&node->symbol.ref_list);
+ ipa_remove_all_references (&node->ref_list);
}
else
- ipa_clear_stmts_in_references ((symtab_node)node);
+ ipa_clear_stmts_in_references (node);
if (cgraph_dump_file)
fprintf (cgraph_dump_file, "Materialization Call site updates done.\n");
#ifdef ENABLE_CHECKING
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 1644ca9eea9..c3a8967e843 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -164,6 +164,10 @@ along with GCC; see the file COPYING3. If not see
#include "tree.h"
#include "output.h"
#include "rtl.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-cfg.h"
+#include "tree-into-ssa.h"
#include "tree-ssa.h"
#include "tree-inline.h"
#include "langhooks.h"
@@ -173,14 +177,12 @@ along with GCC; see the file COPYING3. If not see
#include "ggc.h"
#include "debug.h"
#include "target.h"
-#include "cgraph.h"
#include "diagnostic.h"
#include "params.h"
#include "fibheap.h"
#include "intl.h"
#include "function.h"
#include "ipa-prop.h"
-#include "gimple.h"
#include "tree-iterator.h"
#include "tree-pass.h"
#include "tree-dump.h"
@@ -223,27 +225,27 @@ static GTY (()) tree vtable_entry_type;
either outside this translation unit, something magic in the system
configury */
bool
-decide_is_symbol_needed (symtab_node node)
+decide_is_symbol_needed (symtab_node *node)
{
- tree decl = node->symbol.decl;
+ tree decl = node->decl;
/* Double check that no one output the function into assembly file
early. */
gcc_checking_assert (!DECL_ASSEMBLER_NAME_SET_P (decl)
|| !TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)));
- if (!node->symbol.definition)
+ if (!node->definition)
return false;
if (DECL_EXTERNAL (decl))
return false;
/* If the user told us it is used, then it must be so. */
- if (node->symbol.force_output)
+ if (node->force_output)
return true;
/* ABI forced symbols are needed when they are external. */
- if (node->symbol.forced_by_abi && TREE_PUBLIC (decl))
+ if (node->forced_by_abi && TREE_PUBLIC (decl))
return true;
/* Keep constructors, destructors and virtual functions. */
@@ -261,18 +263,18 @@ decide_is_symbol_needed (symtab_node node)
/* Head of the queue of nodes to be processed while building callgraph */
-static symtab_node first = (symtab_node)(void *)1;
+static symtab_node *first = (symtab_node *)(void *)1;
/* Add NODE to queue starting at FIRST.
The queue is linked via AUX pointers and terminated by pointer to 1. */
static void
-enqueue_node (symtab_node node)
+enqueue_node (symtab_node *node)
{
- if (node->symbol.aux)
+ if (node->aux)
return;
gcc_checking_assert (first);
- node->symbol.aux = first;
+ node->aux = first;
first = node;
}
@@ -296,7 +298,7 @@ cgraph_process_new_functions (void)
for (csi = csi_start (cgraph_new_nodes); !csi_end_p (csi); csi_next (&csi))
{
node = csi_node (csi);
- fndecl = node->symbol.decl;
+ fndecl = node->decl;
switch (cgraph_state)
{
case CGRAPH_STATE_CONSTRUCTION:
@@ -306,7 +308,7 @@ cgraph_process_new_functions (void)
cgraph_finalize_function (fndecl, false);
output = true;
cgraph_call_function_insertion_hooks (node);
- enqueue_node ((symtab_node) node);
+ enqueue_node (node);
break;
case CGRAPH_STATE_IPA:
@@ -316,7 +318,7 @@ cgraph_process_new_functions (void)
cgraph but not on this function. */
gimple_register_cfg_hooks ();
- if (!node->symbol.analyzed)
+ if (!node->analyzed)
analyze_function (node);
push_cfun (DECL_STRUCT_FUNCTION (fndecl));
if (cgraph_state == CGRAPH_STATE_IPA_SSA
@@ -372,25 +374,25 @@ cgraph_reset_node (struct cgraph_node *node)
memset (&node->local, 0, sizeof (node->local));
memset (&node->global, 0, sizeof (node->global));
memset (&node->rtl, 0, sizeof (node->rtl));
- node->symbol.analyzed = false;
- node->symbol.definition = false;
- node->symbol.alias = false;
- node->symbol.weakref = false;
- node->symbol.cpp_implicit_alias = false;
+ node->analyzed = false;
+ node->definition = false;
+ node->alias = false;
+ node->weakref = false;
+ node->cpp_implicit_alias = false;
cgraph_node_remove_callees (node);
- ipa_remove_all_references (&node->symbol.ref_list);
+ ipa_remove_all_references (&node->ref_list);
}
/* Return true when there are references to NODE. */
static bool
-referred_to_p (symtab_node node)
+referred_to_p (symtab_node *node)
{
struct ipa_ref *ref;
/* See if there are any references at all. */
- if (ipa_ref_list_referring_iterate (&node->symbol.ref_list, 0, ref))
+ if (ipa_ref_list_referring_iterate (&node->ref_list, 0, ref))
return true;
/* For functions check also calls. */
cgraph_node *cn = dyn_cast <cgraph_node> (node);
@@ -409,7 +411,7 @@ cgraph_finalize_function (tree decl, bool no_collect)
{
struct cgraph_node *node = cgraph_get_create_node (decl);
- if (node->symbol.definition)
+ if (node->definition)
{
/* Nested functions should only be defined once. */
gcc_assert (!DECL_CONTEXT (decl)
@@ -419,7 +421,7 @@ cgraph_finalize_function (tree decl, bool no_collect)
}
notice_global_symbol (decl);
- node->symbol.definition = true;
+ node->definition = true;
node->lowered = DECL_STRUCT_FUNCTION (decl)->cfg != NULL;
/* With -fkeep-inline-functions we are keeping all inline functions except
@@ -428,7 +430,7 @@ cgraph_finalize_function (tree decl, bool no_collect)
&& DECL_DECLARED_INLINE_P (decl)
&& !DECL_EXTERNAL (decl)
&& !DECL_DISREGARD_INLINE_LIMITS (decl))
- node->symbol.force_output = 1;
+ node->force_output = 1;
/* When not optimizing, also output the static functions. (see
PR24561), but don't do so for always_inline functions, functions
@@ -436,13 +438,13 @@ cgraph_finalize_function (tree decl, bool no_collect)
in the original implementation and it is unclear whether we want
to change the behavior here. */
if ((!optimize
- && !node->symbol.cpp_implicit_alias
+ && !node->cpp_implicit_alias
&& !DECL_DISREGARD_INLINE_LIMITS (decl)
&& !DECL_DECLARED_INLINE_P (decl)
&& !(DECL_CONTEXT (decl)
&& TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL))
&& !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
- node->symbol.force_output = 1;
+ node->force_output = 1;
/* If we've not yet emitted decl, tell the debug info about it. */
if (!TREE_ASM_WRITTEN (decl))
@@ -456,9 +458,9 @@ cgraph_finalize_function (tree decl, bool no_collect)
ggc_collect ();
if (cgraph_state == CGRAPH_STATE_CONSTRUCTION
- && (decide_is_symbol_needed ((symtab_node) node)
- || referred_to_p ((symtab_node)node)))
- enqueue_node ((symtab_node)node);
+ && (decide_is_symbol_needed (node)
+ || referred_to_p (node)))
+ enqueue_node (node);
}
/* Add the function FNDECL to the call graph.
@@ -500,8 +502,8 @@ cgraph_add_new_function (tree fndecl, bool lowered)
analyzing and compilation. */
node = cgraph_get_create_node (fndecl);
node->local.local = false;
- node->symbol.definition = true;
- node->symbol.force_output = true;
+ node->definition = true;
+ node->force_output = true;
if (!lowered && cgraph_state == CGRAPH_STATE_EXPANSION)
{
push_cfun (DECL_STRUCT_FUNCTION (fndecl));
@@ -527,7 +529,7 @@ cgraph_add_new_function (tree fndecl, bool lowered)
node = cgraph_create_node (fndecl);
if (lowered)
node->lowered = true;
- node->symbol.definition = true;
+ node->definition = true;
analyze_function (node);
push_cfun (DECL_STRUCT_FUNCTION (fndecl));
gimple_register_cfg_hooks ();
@@ -588,7 +590,7 @@ output_asm_statements (void)
static void
analyze_function (struct cgraph_node *node)
{
- tree decl = node->symbol.decl;
+ tree decl = node->decl;
location_t saved_loc = input_location;
input_location = DECL_SOURCE_LOCATION (decl);
@@ -599,14 +601,14 @@ analyze_function (struct cgraph_node *node)
if (!expand_thunk (node, false))
{
node->thunk.alias = NULL;
- node->symbol.analyzed = true;
+ node->analyzed = true;
return;
}
node->thunk.alias = NULL;
}
- if (node->symbol.alias)
+ if (node->alias)
symtab_resolve_alias
- ((symtab_node) node, (symtab_node) cgraph_get_node (node->symbol.alias_target));
+ (node, cgraph_get_node (node->alias_target));
else if (node->dispatcher_function)
{
/* Generate the dispatcher body of multi-versioned functions. */
@@ -626,7 +628,7 @@ analyze_function (struct cgraph_node *node)
{
push_cfun (DECL_STRUCT_FUNCTION (decl));
- assign_assembler_name_if_neeeded (node->symbol.decl);
+ assign_assembler_name_if_neeeded (node->decl);
/* Make sure to gimplify bodies only once. During analyzing a
function we lower it, which will require gimplified nested
@@ -640,7 +642,7 @@ analyze_function (struct cgraph_node *node)
if (!node->lowered)
{
if (node->nested)
- lower_nested_functions (node->symbol.decl);
+ lower_nested_functions (node->decl);
gcc_assert (!node->nested);
gimple_register_cfg_hooks ();
@@ -655,7 +657,7 @@ analyze_function (struct cgraph_node *node)
pop_cfun ();
}
- node->symbol.analyzed = true;
+ node->analyzed = true;
input_location = saved_loc;
}
@@ -669,14 +671,14 @@ analyze_function (struct cgraph_node *node)
void
cgraph_process_same_body_aliases (void)
{
- symtab_node node;
+ symtab_node *node;
FOR_EACH_SYMBOL (node)
- if (node->symbol.cpp_implicit_alias && !node->symbol.analyzed)
+ if (node->cpp_implicit_alias && !node->analyzed)
symtab_resolve_alias
(node,
- TREE_CODE (node->symbol.alias_target) == VAR_DECL
- ? (symtab_node)varpool_node_for_decl (node->symbol.alias_target)
- : (symtab_node)cgraph_get_create_node (node->symbol.alias_target));
+ TREE_CODE (node->alias_target) == VAR_DECL
+ ? (symtab_node *)varpool_node_for_decl (node->alias_target)
+ : (symtab_node *)cgraph_get_create_node (node->alias_target));
cpp_implicit_aliases_done = true;
}
@@ -732,20 +734,20 @@ process_function_and_variable_attributes (struct cgraph_node *first,
for (node = cgraph_first_function (); node != first;
node = cgraph_next_function (node))
{
- tree decl = node->symbol.decl;
+ tree decl = node->decl;
if (DECL_PRESERVE_P (decl))
cgraph_mark_force_output_node (node);
else if (lookup_attribute ("externally_visible", DECL_ATTRIBUTES (decl)))
{
- if (! TREE_PUBLIC (node->symbol.decl))
- warning_at (DECL_SOURCE_LOCATION (node->symbol.decl), OPT_Wattributes,
+ if (! TREE_PUBLIC (node->decl))
+ warning_at (DECL_SOURCE_LOCATION (node->decl), OPT_Wattributes,
"%<externally_visible%>"
" attribute have effect only on public objects");
}
if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl))
- && (node->symbol.definition && !node->symbol.alias))
+ && (node->definition && !node->alias))
{
- warning_at (DECL_SOURCE_LOCATION (node->symbol.decl), OPT_Wattributes,
+ warning_at (DECL_SOURCE_LOCATION (node->decl), OPT_Wattributes,
"%<weakref%> attribute ignored"
" because function is defined");
DECL_WEAK (decl) = 0;
@@ -765,24 +767,24 @@ process_function_and_variable_attributes (struct cgraph_node *first,
for (vnode = varpool_first_variable (); vnode != first_var;
vnode = varpool_next_variable (vnode))
{
- tree decl = vnode->symbol.decl;
+ tree decl = vnode->decl;
if (DECL_EXTERNAL (decl)
&& DECL_INITIAL (decl))
varpool_finalize_decl (decl);
if (DECL_PRESERVE_P (decl))
- vnode->symbol.force_output = true;
+ vnode->force_output = true;
else if (lookup_attribute ("externally_visible", DECL_ATTRIBUTES (decl)))
{
- if (! TREE_PUBLIC (vnode->symbol.decl))
- warning_at (DECL_SOURCE_LOCATION (vnode->symbol.decl), OPT_Wattributes,
+ if (! TREE_PUBLIC (vnode->decl))
+ warning_at (DECL_SOURCE_LOCATION (vnode->decl), OPT_Wattributes,
"%<externally_visible%>"
" attribute have effect only on public objects");
}
if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl))
- && vnode->symbol.definition
+ && vnode->definition
&& DECL_INITIAL (decl))
{
- warning_at (DECL_SOURCE_LOCATION (vnode->symbol.decl), OPT_Wattributes,
+ warning_at (DECL_SOURCE_LOCATION (vnode->decl), OPT_Wattributes,
"%<weakref%> attribute ignored"
" because variable is initialized");
DECL_WEAK (decl) = 0;
@@ -804,21 +806,21 @@ varpool_finalize_decl (tree decl)
gcc_assert (TREE_STATIC (decl) || DECL_EXTERNAL (decl));
- if (node->symbol.definition)
+ if (node->definition)
return;
notice_global_symbol (decl);
- node->symbol.definition = true;
+ node->definition = true;
if (TREE_THIS_VOLATILE (decl) || DECL_PRESERVE_P (decl)
/* Traditionally we do not eliminate static variables when not
optimizing and when not doing toplevel reoder. */
- || (!flag_toplevel_reorder && !DECL_COMDAT (node->symbol.decl)
- && !DECL_ARTIFICIAL (node->symbol.decl)))
- node->symbol.force_output = true;
+ || (!flag_toplevel_reorder && !DECL_COMDAT (node->decl)
+ && !DECL_ARTIFICIAL (node->decl)))
+ node->force_output = true;
if (cgraph_state == CGRAPH_STATE_CONSTRUCTION
- && (decide_is_symbol_needed ((symtab_node) node)
- || referred_to_p ((symtab_node)node)))
- enqueue_node ((symtab_node)node);
+ && (decide_is_symbol_needed (node)
+ || referred_to_p (node)))
+ enqueue_node (node);
if (cgraph_state >= CGRAPH_STATE_IPA_SSA)
varpool_analyze_node (node);
/* Some frontends produce various interface variables after compilation
@@ -850,19 +852,19 @@ walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets,
dump_possible_polymorphic_call_targets
(cgraph_dump_file, edge);
- for (i = 0; i < targets.length(); i++)
+ for (i = 0; i < targets.length (); i++)
{
/* Do not bother to mark virtual methods in anonymous namespace;
either we will find use of virtual table defining it, or it is
unused. */
- if (targets[i]->symbol.definition
+ if (targets[i]->definition
&& TREE_CODE
- (TREE_TYPE (targets[i]->symbol.decl))
+ (TREE_TYPE (targets[i]->decl))
== METHOD_TYPE
&& !type_in_anonymous_namespace_p
(method_class_type
- (TREE_TYPE (targets[i]->symbol.decl))))
- enqueue_node ((symtab_node) targets[i]);
+ (TREE_TYPE (targets[i]->decl))))
+ enqueue_node (targets[i]);
}
}
@@ -872,7 +874,7 @@ walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets,
make the edge direct. */
if (final)
{
- if (targets.length() <= 1)
+ if (targets.length () <= 1)
{
cgraph_node *target;
if (targets.length () == 1)
@@ -918,7 +920,8 @@ analyze_functions (void)
struct varpool_node *first_handled_var = first_analyzed_var;
struct pointer_set_t *reachable_call_targets = pointer_set_create ();
- symtab_node node, next;
+ symtab_node *node;
+ symtab_node *next;
int i;
struct ipa_ref *ref;
bool changed = true;
@@ -932,7 +935,7 @@ analyze_functions (void)
C++ FE is confused about the COMDAT groups being right. */
if (cpp_implicit_aliases_done)
FOR_EACH_SYMBOL (node)
- if (node->symbol.cpp_implicit_alias)
+ if (node->cpp_implicit_alias)
fixup_same_cpp_alias_visibility (node, symtab_alias_target (node));
if (optimize && flag_devirtualize)
build_type_inheritance_graph ();
@@ -947,8 +950,8 @@ analyze_functions (void)
/* First identify the trivially needed symbols. */
for (node = symtab_nodes;
- node != (symtab_node)first_analyzed
- && node != (symtab_node)first_analyzed_var; node = node->symbol.next)
+ node != first_analyzed
+ && node != first_analyzed_var; node = node->next)
{
if (decide_is_symbol_needed (node))
{
@@ -961,8 +964,8 @@ analyze_functions (void)
if (!changed && cgraph_dump_file)
fprintf (cgraph_dump_file, "\n");
}
- if (node == (symtab_node)first_analyzed
- || node == (symtab_node)first_analyzed_var)
+ if (node == first_analyzed
+ || node == first_analyzed_var)
break;
}
cgraph_process_new_functions ();
@@ -974,22 +977,22 @@ analyze_functions (void)
/* Lower representation, build callgraph edges and references for all trivially
needed symbols and all symbols referred by them. */
- while (first != (symtab_node)(void *)1)
+ while (first != (symtab_node *)(void *)1)
{
changed = true;
node = first;
- first = (symtab_node)first->symbol.aux;
+ first = (symtab_node *)first->aux;
cgraph_node *cnode = dyn_cast <cgraph_node> (node);
- if (cnode && cnode->symbol.definition)
+ if (cnode && cnode->definition)
{
struct cgraph_edge *edge;
- tree decl = cnode->symbol.decl;
+ tree decl = cnode->decl;
/* ??? It is possible to create extern inline function
and later using weak alias attribute to kill its body.
See gcc.c-torture/compile/20011119-1.c */
if (!DECL_STRUCT_FUNCTION (decl)
- && !cnode->symbol.alias
+ && !cnode->alias
&& !cnode->thunk.thunk_p
&& !cnode->dispatcher_function)
{
@@ -998,12 +1001,12 @@ analyze_functions (void)
continue;
}
- if (!cnode->symbol.analyzed)
+ if (!cnode->analyzed)
analyze_function (cnode);
for (edge = cnode->callees; edge; edge = edge->next_callee)
- if (edge->callee->symbol.definition)
- enqueue_node ((symtab_node)edge->callee);
+ if (edge->callee->definition)
+ enqueue_node (edge->callee);
if (optimize && flag_devirtualize)
{
struct cgraph_edge *next;
@@ -1031,20 +1034,20 @@ analyze_functions (void)
else
{
varpool_node *vnode = dyn_cast <varpool_node> (node);
- if (vnode && vnode->symbol.definition && !vnode->symbol.analyzed)
+ if (vnode && vnode->definition && !vnode->analyzed)
varpool_analyze_node (vnode);
}
- if (node->symbol.same_comdat_group)
+ if (node->same_comdat_group)
{
- symtab_node next;
- for (next = node->symbol.same_comdat_group;
+ symtab_node *next;
+ for (next = node->same_comdat_group;
next != node;
- next = next->symbol.same_comdat_group)
+ next = next->same_comdat_group)
enqueue_node (next);
}
- for (i = 0; ipa_ref_list_reference_iterate (&node->symbol.ref_list, i, ref); i++)
- if (ref->referred->symbol.definition)
+ for (i = 0; ipa_ref_list_reference_iterate (&node->ref_list, i, ref); i++)
+ if (ref->referred->definition)
enqueue_node (ref->referred);
cgraph_process_new_functions ();
}
@@ -1063,11 +1066,11 @@ analyze_functions (void)
fprintf (cgraph_dump_file, "\nRemoving unused symbols:");
for (node = symtab_nodes;
- node != (symtab_node)first_handled
- && node != (symtab_node)first_handled_var; node = next)
+ node != first_handled
+ && node != first_handled_var; node = next)
{
- next = node->symbol.next;
- if (!node->symbol.aux && !referred_to_p (node))
+ next = node->next;
+ if (!node->aux && !referred_to_p (node))
{
if (cgraph_dump_file)
fprintf (cgraph_dump_file, " %s", symtab_node_name (node));
@@ -1076,22 +1079,22 @@ analyze_functions (void)
}
if (cgraph_node *cnode = dyn_cast <cgraph_node> (node))
{
- tree decl = node->symbol.decl;
+ tree decl = node->decl;
- if (cnode->symbol.definition && !gimple_has_body_p (decl)
- && !cnode->symbol.alias
+ if (cnode->definition && !gimple_has_body_p (decl)
+ && !cnode->alias
&& !cnode->thunk.thunk_p)
cgraph_reset_node (cnode);
- gcc_assert (!cnode->symbol.definition || cnode->thunk.thunk_p
- || cnode->symbol.alias
+ gcc_assert (!cnode->definition || cnode->thunk.thunk_p
+ || cnode->alias
|| gimple_has_body_p (decl));
- gcc_assert (cnode->symbol.analyzed == cnode->symbol.definition);
+ gcc_assert (cnode->analyzed == cnode->definition);
}
- node->symbol.aux = NULL;
+ node->aux = NULL;
}
- for (;node; node = node->symbol.next)
- node->symbol.aux = NULL;
+ for (;node; node = node->next)
+ node->aux = NULL;
first_analyzed = cgraph_first_function ();
first_analyzed_var = varpool_first_variable ();
if (cgraph_dump_file)
@@ -1123,7 +1126,7 @@ handle_alias_pairs (void)
for (i = 0; alias_pairs && alias_pairs->iterate (i, &p);)
{
- symtab_node target_node = symtab_node_for_asm (p->target);
+ symtab_node *target_node = symtab_node_for_asm (p->target);
/* Weakrefs with target not defined in current unit are easy to handle:
they behave just as external variables except we need to note the
@@ -1131,12 +1134,12 @@ handle_alias_pairs (void)
if (!target_node
&& lookup_attribute ("weakref", DECL_ATTRIBUTES (p->decl)) != NULL)
{
- symtab_node node = symtab_get_node (p->decl);
+ symtab_node *node = symtab_get_node (p->decl);
if (node)
{
- node->symbol.alias_target = p->target;
- node->symbol.weakref = true;
- node->symbol.alias = true;
+ node->alias_target = p->target;
+ node->weakref = true;
+ node->alias = true;
}
alias_pairs->unordered_remove (i);
continue;
@@ -1144,19 +1147,19 @@ handle_alias_pairs (void)
else if (!target_node)
{
error ("%q+D aliased to undefined symbol %qE", p->decl, p->target);
- symtab_node node = symtab_get_node (p->decl);
+ symtab_node *node = symtab_get_node (p->decl);
if (node)
- node->symbol.alias = false;
+ node->alias = false;
alias_pairs->unordered_remove (i);
continue;
}
- if (DECL_EXTERNAL (target_node->symbol.decl)
+ if (DECL_EXTERNAL (target_node->decl)
/* We use local aliases for C++ thunks to force the tailcall
to bind locally. This is a hack - to keep it working do
the following (which is not strictly correct). */
- && (! TREE_CODE (target_node->symbol.decl) == FUNCTION_DECL
- || ! DECL_VIRTUAL_P (target_node->symbol.decl))
+ && (! TREE_CODE (target_node->decl) == FUNCTION_DECL
+ || ! DECL_VIRTUAL_P (target_node->decl))
&& ! lookup_attribute ("weakref", DECL_ATTRIBUTES (p->decl)))
{
error ("%q+D aliased to external symbol %qE",
@@ -1167,15 +1170,15 @@ handle_alias_pairs (void)
&& target_node && is_a <cgraph_node> (target_node))
{
struct cgraph_node *src_node = cgraph_get_node (p->decl);
- if (src_node && src_node->symbol.definition)
+ if (src_node && src_node->definition)
cgraph_reset_node (src_node);
- cgraph_create_function_alias (p->decl, target_node->symbol.decl);
+ cgraph_create_function_alias (p->decl, target_node->decl);
alias_pairs->unordered_remove (i);
}
else if (TREE_CODE (p->decl) == VAR_DECL
&& target_node && is_a <varpool_node> (target_node))
{
- varpool_create_variable_alias (p->decl, target_node->symbol.decl);
+ varpool_create_variable_alias (p->decl, target_node->decl);
alias_pairs->unordered_remove (i);
}
else
@@ -1183,7 +1186,7 @@ handle_alias_pairs (void)
error ("%q+D alias in between function and variable is not supported",
p->decl);
warning (0, "%q+D aliased declaration",
- target_node->symbol.decl);
+ target_node->decl);
alias_pairs->unordered_remove (i);
}
}
@@ -1206,34 +1209,34 @@ mark_functions_to_output (void)
FOR_EACH_FUNCTION (node)
{
- tree decl = node->symbol.decl;
+ tree decl = node->decl;
- gcc_assert (!node->process || node->symbol.same_comdat_group);
+ gcc_assert (!node->process || node->same_comdat_group);
if (node->process)
continue;
/* We need to output all local functions that are used and not
always inlined, as well as those that are reachable from
outside the current compilation unit. */
- if (node->symbol.analyzed
+ if (node->analyzed
&& !node->thunk.thunk_p
- && !node->symbol.alias
+ && !node->alias
&& !node->global.inlined_to
&& !TREE_ASM_WRITTEN (decl)
&& !DECL_EXTERNAL (decl))
{
node->process = 1;
- if (node->symbol.same_comdat_group)
+ if (node->same_comdat_group)
{
struct cgraph_node *next;
- for (next = cgraph (node->symbol.same_comdat_group);
+ for (next = cgraph (node->same_comdat_group);
next != node;
- next = cgraph (next->symbol.same_comdat_group))
- if (!next->thunk.thunk_p && !next->symbol.alias)
+ next = cgraph (next->same_comdat_group))
+ if (!next->thunk.thunk_p && !next->alias)
next->process = 1;
}
}
- else if (node->symbol.same_comdat_group)
+ else if (node->same_comdat_group)
{
#ifdef ENABLE_CHECKING
check_same_comdat_groups = true;
@@ -1248,8 +1251,8 @@ mark_functions_to_output (void)
/* FIXME: in ltrans unit when offline copy is outside partition but inline copies
are inside partition, we can end up not removing the body since we no longer
have analyzed node pointing to it. */
- && !node->symbol.in_other_partition
- && !node->symbol.alias
+ && !node->in_other_partition
+ && !node->alias
&& !node->clones
&& !DECL_EXTERNAL (decl))
{
@@ -1259,7 +1262,7 @@ mark_functions_to_output (void)
#endif
gcc_assert (node->global.inlined_to
|| !gimple_has_body_p (decl)
- || node->symbol.in_other_partition
+ || node->in_other_partition
|| node->clones
|| DECL_ARTIFICIAL (decl)
|| DECL_EXTERNAL (decl));
@@ -1270,16 +1273,16 @@ mark_functions_to_output (void)
#ifdef ENABLE_CHECKING
if (check_same_comdat_groups)
FOR_EACH_FUNCTION (node)
- if (node->symbol.same_comdat_group && !node->process)
+ if (node->same_comdat_group && !node->process)
{
- tree decl = node->symbol.decl;
+ tree decl = node->decl;
if (!node->global.inlined_to
&& gimple_has_body_p (decl)
/* FIXME: in an ltrans unit when the offline copy is outside a
partition but inline copies are inside a partition, we can
end up not removing the body since we no longer have an
analyzed node pointing to it. */
- && !node->symbol.in_other_partition
+ && !node->in_other_partition
&& !node->clones
&& !DECL_EXTERNAL (decl))
{
@@ -1449,8 +1452,8 @@ expand_thunk (struct cgraph_node *node, bool output_asm_thunks)
HOST_WIDE_INT fixed_offset = node->thunk.fixed_offset;
HOST_WIDE_INT virtual_value = node->thunk.virtual_value;
tree virtual_offset = NULL;
- tree alias = node->callees->callee->symbol.decl;
- tree thunk_fndecl = node->symbol.decl;
+ tree alias = node->callees->callee->decl;
+ tree thunk_fndecl = node->decl;
tree a;
@@ -1502,7 +1505,7 @@ expand_thunk (struct cgraph_node *node, bool output_asm_thunks)
set_cfun (NULL);
TREE_ASM_WRITTEN (thunk_fndecl) = 1;
node->thunk.thunk_p = false;
- node->symbol.analyzed = false;
+ node->analyzed = false;
}
else
{
@@ -1688,20 +1691,20 @@ assemble_thunks_and_aliases (struct cgraph_node *node)
}
else
e = e->next_caller;
- for (i = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list,
+ for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list,
i, ref); i++)
if (ref->use == IPA_REF_ALIAS)
{
struct cgraph_node *alias = ipa_ref_referring_node (ref);
- bool saved_written = TREE_ASM_WRITTEN (node->symbol.decl);
+ bool saved_written = TREE_ASM_WRITTEN (node->decl);
/* Force assemble_alias to really output the alias this time instead
of buffering it in same alias pairs. */
- TREE_ASM_WRITTEN (node->symbol.decl) = 1;
- do_assemble_alias (alias->symbol.decl,
- DECL_ASSEMBLER_NAME (node->symbol.decl));
+ TREE_ASM_WRITTEN (node->decl) = 1;
+ do_assemble_alias (alias->decl,
+ DECL_ASSEMBLER_NAME (node->decl));
assemble_thunks_and_aliases (alias);
- TREE_ASM_WRITTEN (node->symbol.decl) = saved_written;
+ TREE_ASM_WRITTEN (node->decl) = saved_written;
}
}
@@ -1710,7 +1713,7 @@ assemble_thunks_and_aliases (struct cgraph_node *node)
static void
expand_function (struct cgraph_node *node)
{
- tree decl = node->symbol.decl;
+ tree decl = node->decl;
location_t saved_loc;
/* We ought to not compile any inline clones. */
@@ -1815,7 +1818,7 @@ expand_function (struct cgraph_node *node)
/* Eliminate all call edges. This is important so the GIMPLE_CALL no longer
points to the dead function body. */
cgraph_node_remove_callees (node);
- ipa_remove_all_references (&node->symbol.ref_list);
+ ipa_remove_all_references (&node->ref_list);
}
@@ -1903,9 +1906,9 @@ output_in_order (void)
FOR_EACH_DEFINED_FUNCTION (pf)
{
- if (pf->process && !pf->thunk.thunk_p && !pf->symbol.alias)
+ if (pf->process && !pf->thunk.thunk_p && !pf->alias)
{
- i = pf->symbol.order;
+ i = pf->order;
gcc_assert (nodes[i].kind == ORDER_UNDEFINED);
nodes[i].kind = ORDER_FUNCTION;
nodes[i].u.f = pf;
@@ -1913,9 +1916,9 @@ output_in_order (void)
}
FOR_EACH_DEFINED_VARIABLE (pv)
- if (!DECL_EXTERNAL (pv->symbol.decl))
+ if (!DECL_EXTERNAL (pv->decl))
{
- i = pv->symbol.order;
+ i = pv->order;
gcc_assert (nodes[i].kind == ORDER_UNDEFINED);
nodes[i].kind = ORDER_VAR;
nodes[i].u.v = pv;
@@ -2046,11 +2049,11 @@ get_alias_symbol (tree decl)
static void
output_weakrefs (void)
{
- symtab_node node;
+ symtab_node *node;
FOR_EACH_SYMBOL (node)
- if (node->symbol.alias
- && !TREE_ASM_WRITTEN (node->symbol.decl)
- && node->symbol.weakref)
+ if (node->alias
+ && !TREE_ASM_WRITTEN (node->decl)
+ && node->weakref)
{
tree target;
@@ -2059,18 +2062,18 @@ output_weakrefs (void)
alias.
When alias target is defined, we need to fetch it from symtab reference,
otherwise it is pointed to by alias_target. */
- if (node->symbol.alias_target)
- target = (DECL_P (node->symbol.alias_target)
- ? DECL_ASSEMBLER_NAME (node->symbol.alias_target)
- : node->symbol.alias_target);
- else if (node->symbol.analyzed)
- target = DECL_ASSEMBLER_NAME (symtab_alias_target (node)->symbol.decl);
+ if (node->alias_target)
+ target = (DECL_P (node->alias_target)
+ ? DECL_ASSEMBLER_NAME (node->alias_target)
+ : node->alias_target);
+ else if (node->analyzed)
+ target = DECL_ASSEMBLER_NAME (symtab_alias_target (node)->decl);
else
{
gcc_unreachable ();
- target = get_alias_symbol (node->symbol.decl);
+ target = get_alias_symbol (node->decl);
}
- do_assemble_alias (node->symbol.decl, target);
+ do_assemble_alias (node->decl, target);
}
}
@@ -2168,17 +2171,17 @@ compile (void)
level by physically rewritting the IL. At the moment we can only redirect
calls, so we need infrastructure for renaming references as well. */
#ifndef ASM_OUTPUT_WEAKREF
- symtab_node node;
+ symtab_node *node;
FOR_EACH_SYMBOL (node)
- if (node->symbol.alias
- && lookup_attribute ("weakref", DECL_ATTRIBUTES (node->symbol.decl)))
+ if (node->alias
+ && lookup_attribute ("weakref", DECL_ATTRIBUTES (node->decl)))
{
IDENTIFIER_TRANSPARENT_ALIAS
- (DECL_ASSEMBLER_NAME (node->symbol.decl)) = 1;
- TREE_CHAIN (DECL_ASSEMBLER_NAME (node->symbol.decl))
- = (node->symbol.alias_target ? node->symbol.alias_target
- : DECL_ASSEMBLER_NAME (symtab_alias_target (node)->symbol.decl));
+ (DECL_ASSEMBLER_NAME (node->decl)) = 1;
+ TREE_CHAIN (DECL_ASSEMBLER_NAME (node->decl))
+ = (node->alias_target ? node->alias_target
+ : DECL_ASSEMBLER_NAME (symtab_alias_target (node)->decl));
}
#endif
@@ -2213,7 +2216,7 @@ compile (void)
FOR_EACH_DEFINED_FUNCTION (node)
if (node->global.inlined_to
- || gimple_has_body_p (node->symbol.decl))
+ || gimple_has_body_p (node->decl))
{
error_found = true;
dump_cgraph_node (stderr, node);
diff --git a/gcc/chkp-builtins.def b/gcc/chkp-builtins.def
new file mode 100644
index 00000000000..d19b5418a36
--- /dev/null
+++ b/gcc/chkp-builtins.def
@@ -0,0 +1,73 @@
+/* This file contains the definitions and documentation for the
+ builtins used in the GNU compiler.
+ Copyright (C) 2013 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 macros:
+
+ DEF_BUILTIN_STUB(ENUM, NAME)
+ DEF_CHKP_BUILTIN(ENUM, NAME, TYPE, ATTRS)
+
+ See builtins.def for details. */
+
+/* Following builtins are used by compiler for Pointer Bounds Checker
+ instrumentation. Currently these generic builtins are not
+ implemented and target has to provide his own version. See
+ builtin_chkp_function target hook documentation for more details. */
+DEF_BUILTIN_STUB (BUILT_IN_CHKP_BNDMK, "__chkp_bndmk")
+DEF_BUILTIN_STUB (BUILT_IN_CHKP_BNDSTX, "__chkp_bndstx")
+DEF_BUILTIN_STUB (BUILT_IN_CHKP_BNDCL, "__chkp_bndcl")
+DEF_BUILTIN_STUB (BUILT_IN_CHKP_BNDCU, "__chkp_bndcu")
+DEF_BUILTIN_STUB (BUILT_IN_CHKP_BNDLDX, "__chkp_bndldx")
+DEF_BUILTIN_STUB (BUILT_IN_CHKP_BNDRET, "__chkp_bndret")
+DEF_BUILTIN_STUB (BUILT_IN_CHKP_INTERSECT, "__chkp_intersect")
+DEF_BUILTIN_STUB (BUILT_IN_CHKP_ARG_BND, "__chkp_arg_bnd")
+DEF_BUILTIN_STUB (BUILT_IN_CHKP_SIZEOF, "__chkp_sizeof")
+DEF_BUILTIN_STUB (BUILT_IN_CHKP_EXTRACT_LOWER, "__chkp_extract_lower")
+DEF_BUILTIN_STUB (BUILT_IN_CHKP_EXTRACT_UPPER, "__chkp_extract_upper")
+DEF_BUILTIN_STUB (BUILT_IN_CHKP_NARROW, "__chkp_narrow")
+
+/* Pointer Bounds Checker builtins for users. Only
+ BUILT_IN_CHKP_SET_PTR_BOUNDS may be redefined
+ by target. Other builtins calls are expanded
+ in the Pointer Bounds Checker pass. */
+DEF_CHKP_BUILTIN (BUILT_IN_CHKP_SET_PTR_BOUNDS, "__bnd_set_ptr_bounds", BT_FN_PTR_CONST_PTR_SIZE, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_CHKP_BUILTIN (BUILT_IN_CHKP_INIT_PTR_BOUNDS, "__bnd_init_ptr_bounds", BT_FN_PTR_CONST_PTR, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_CHKP_BUILTIN (BUILT_IN_CHKP_NULL_PTR_BOUNDS, "__bnd_null_ptr_bounds", BT_FN_PTR_CONST_PTR, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_CHKP_BUILTIN (BUILT_IN_CHKP_COPY_PTR_BOUNDS, "__bnd_copy_ptr_bounds", BT_FN_PTR_CONST_PTR_CONST_PTR, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_CHKP_BUILTIN (BUILT_IN_CHKP_NARROW_PTR_BOUNDS, "__bnd_narrow_ptr_bounds", BT_FN_PTR_CONST_PTR_CONST_PTR_SIZE, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_CHKP_BUILTIN (BUILT_IN_CHKP_STORE_PTR_BOUNDS, "__bnd_store_ptr_bounds", BT_FN_VOID_PTRPTR_CONST_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_CHKP_BUILTIN (BUILT_IN_CHKP_CHECK_PTR_LBOUNDS, "__bnd_chk_ptr_lbounds", BT_FN_VOID_CONST_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_CHKP_BUILTIN (BUILT_IN_CHKP_CHECK_PTR_UBOUNDS, "__bnd_chk_ptr_ubounds", BT_FN_VOID_CONST_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_CHKP_BUILTIN (BUILT_IN_CHKP_CHECK_PTR_BOUNDS, "__bnd_chk_ptr_bounds", BT_FN_VOID_CONST_PTR_SIZE, ATTR_NOTHROW_LEAF_LIST)
+DEF_CHKP_BUILTIN (BUILT_IN_CHKP_GET_PTR_LBOUND, "__bnd_get_ptr_lbound", BT_FN_CONST_PTR_CONST_PTR, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_CHKP_BUILTIN (BUILT_IN_CHKP_GET_PTR_UBOUND, "__bnd_get_ptr_ubound", BT_FN_CONST_PTR_CONST_PTR, ATTR_CONST_NOTHROW_LEAF_LIST)
+
+/* Pointer Bounds Checker specific versions of string functions. */
+DEF_CHKP_BUILTIN (BUILT_IN_CHKP_MEMCPY_NOBND, "chkp_memcpy_nobnd", BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_RET1_NOTHROW_NONNULL_LEAF)
+DEF_CHKP_BUILTIN (BUILT_IN_CHKP_MEMCPY_NOCHK, "chkp_memcpy_nochk", BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_RET1_NOTHROW_NONNULL_LEAF)
+DEF_CHKP_BUILTIN (BUILT_IN_CHKP_MEMCPY_NOBND_NOCHK, "chkp_memcpy_nobnd_nochk", BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_RET1_NOTHROW_NONNULL_LEAF)
+DEF_CHKP_BUILTIN (BUILT_IN_CHKP_MEMMOVE_NOBND, "chkp_memmove_nobnd", BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_RET1_NOTHROW_NONNULL_LEAF)
+DEF_CHKP_BUILTIN (BUILT_IN_CHKP_MEMMOVE_NOCHK, "chkp_memmove_nochk", BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_RET1_NOTHROW_NONNULL_LEAF)
+DEF_CHKP_BUILTIN (BUILT_IN_CHKP_MEMMOVE_NOBND_NOCHK, "chkp_memmove_nobnd_nochk", BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_RET1_NOTHROW_NONNULL_LEAF)
+DEF_CHKP_BUILTIN (BUILT_IN_CHKP_MEMPCPY_NOBND, "chkp_mempcpy_nobnd", BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
+DEF_CHKP_BUILTIN (BUILT_IN_CHKP_MEMPCPY_NOCHK, "chkp_mempcpy_nochk", BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
+DEF_CHKP_BUILTIN (BUILT_IN_CHKP_MEMPCPY_NOBND_NOCHK, "chkp_mempcpy_nobnd_nochk", BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
+DEF_CHKP_BUILTIN (BUILT_IN_CHKP_MEMSET_NOBND, "chkp_memset_nobnd", BT_FN_PTR_PTR_INT_SIZE, ATTR_RET1_NOTHROW_NONNULL_LEAF)
+DEF_CHKP_BUILTIN (BUILT_IN_CHKP_MEMSET_NOCHK, "chkp_memset_nochk", BT_FN_PTR_PTR_INT_SIZE, ATTR_RET1_NOTHROW_NONNULL_LEAF)
+DEF_CHKP_BUILTIN (BUILT_IN_CHKP_MEMSET_NOBND_NOCHK, "chkp_memset_nobnd_nochk", BT_FN_PTR_PTR_INT_SIZE, ATTR_RET1_NOTHROW_NONNULL_LEAF)
diff --git a/gcc/cilk-builtins.def b/gcc/cilk-builtins.def
new file mode 100644
index 00000000000..8634194d722
--- /dev/null
+++ b/gcc/cilk-builtins.def
@@ -0,0 +1,33 @@
+/* This file contains the definitions and documentation for the
+ Cilk Plus builtins used in the GNU compiler.
+ Copyright (C) 2013 Free Software Foundation, Inc.
+
+ Contributed by Balaji V. Iyer <balaji.v.iyer@intel.com>
+ Intel Corporation.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+DEF_CILK_BUILTIN_STUB (BUILT_IN_CILK_ENTER_FRAME, "__cilkrts_enter_frame_1")
+DEF_CILK_BUILTIN_STUB (BUILT_IN_CILK_ENTER_FRAME_FAST,
+ "__cilkrts_enter_frame_fast_1")
+DEF_CILK_BUILTIN_STUB (BUILT_IN_CILK_DETACH, "__cilkrts_detach")
+DEF_CILK_BUILTIN_STUB (BUILT_IN_CILK_RETHROW, "__cilkrts_rethrow")
+DEF_CILK_BUILTIN_STUB (BUILT_IN_CILK_SYNCHED, "__cilkrts_synched")
+DEF_CILK_BUILTIN_STUB (BUILT_IN_CILK_SYNC, "__cilkrts_sync")
+DEF_CILK_BUILTIN_STUB (BUILT_IN_CILK_LEAVE_FRAME, "__cilkrts_leave_frame")
+DEF_CILK_BUILTIN_STUB (BUILT_IN_CILK_POP_FRAME, "__cilkrts_pop_frame")
+DEF_CILK_BUILTIN_STUB (BUILT_IN_CILK_SAVE_FP, "__cilkrts_save_fp_ctrl_state")
diff --git a/gcc/cilk-common.c b/gcc/cilk-common.c
new file mode 100644
index 00000000000..ca178c00cd3
--- /dev/null
+++ b/gcc/cilk-common.c
@@ -0,0 +1,484 @@
+/* This file is part of the Intel(R) Cilk(TM) Plus support
+ This file contains the CilkPlus Intrinsics
+ Copyright (C) 2013 Free Software Foundation, Inc.
+ Contributed by Balaji V. Iyer <balaji.v.iyer@intel.com>,
+ Intel Corporation
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have 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 "tree.h"
+#include "langhooks.h"
+#include "expr.h"
+#include "optabs.h"
+#include "recog.h"
+#include "tree-iterator.h"
+#include "gimple.h"
+#include "cilk.h"
+
+/* This structure holds all the important fields of the internal structures,
+ internal built-in functions, and Cilk-specific data types. Explanation of
+ all the these fielsd are given in cilk.h. */
+tree cilk_trees[(int) CILK_TI_MAX];
+
+/* Returns the value in structure FRAME pointed by the FIELD_NUMBER
+ (e.g. X.y).
+ FIELD_NUMBER is an index to the structure FRAME_PTR. For details
+ about these fields, refer to cilk_trees structure in cilk.h and
+ cilk_init_builtins function in this file. Returns a TREE that is the type
+ of the field represented by FIELD_NUMBER. If VOLATIL parameter is set
+ to true then the returning field is set as volatile. */
+
+tree
+cilk_dot (tree frame, int field_number, bool volatil)
+{
+ tree field = cilk_trees[field_number];
+ field = fold_build3 (COMPONENT_REF, TREE_TYPE (field), frame, field,
+ NULL_TREE);
+ TREE_THIS_VOLATILE (field) = volatil;
+ return field;
+}
+
+/* Returns the address of a field in FRAME_PTR, pointed by FIELD_NUMBER.
+ (e.g. (&X)->y). Please see cilk_dot function for explanation of the
+ FIELD_NUMBER. Returns a tree that is the type of the field represented
+ by FIELD_NUMBER. If VOLATIL parameter is set to true then the returning
+ field is set as volatile. */
+
+tree
+cilk_arrow (tree frame_ptr, int field_number, bool volatil)
+{
+ return cilk_dot (fold_build1 (INDIRECT_REF,
+ TREE_TYPE (TREE_TYPE (frame_ptr)), frame_ptr),
+ field_number, volatil);
+}
+
+
+/* This function will add FIELD of type TYPE to a defined built-in
+ structure. *NAME is the name of the field to be added. */
+
+static tree
+add_field (const char *name, tree type, tree fields)
+{
+ tree t = get_identifier (name);
+ tree field = build_decl (BUILTINS_LOCATION, FIELD_DECL, t, type);
+ TREE_CHAIN (field) = fields;
+ return field;
+}
+
+/* This function will define a built-in function of NAME, of type FNTYPE and
+ register it under the built-in function code CODE. If PUBLISH is set then
+ the declaration is pushed into the declaration list. CODE is the index
+ to the cilk_trees array. *NAME is the name of the function to be added. */
+
+static tree
+install_builtin (const char *name, tree fntype, enum built_in_function code,
+ bool publish)
+{
+ tree fndecl = build_fn_decl (name, fntype);
+ DECL_BUILT_IN_CLASS (fndecl) = BUILT_IN_NORMAL;
+ DECL_FUNCTION_CODE (fndecl) = code;
+ if (publish)
+ {
+ tree t = lang_hooks.decls.pushdecl (fndecl);
+ if (t)
+ fndecl = t;
+ }
+ set_builtin_decl (code, fndecl, true);
+ return fndecl;
+}
+
+/* Creates and initializes all the built-in Cilk keywords functions and three
+ structures: __cilkrts_stack_frame, __cilkrts_pedigree and __cilkrts_worker.
+ Detailed information about __cilkrts_stack_frame and
+ __cilkrts_worker structures are given in libcilkrts/include/internal/abi.h.
+ __cilkrts_pedigree is described in libcilkrts/include/cilk/common.h. */
+
+void
+cilk_init_builtins (void)
+{
+ /* Now build the following __cilkrts_pedigree struct:
+ struct __cilkrts_pedigree {
+ uint64_t rank;
+ struct __cilkrts_pedigree *parent;
+ } */
+
+ tree pedigree_type = lang_hooks.types.make_type (RECORD_TYPE);
+ tree pedigree_ptr = build_pointer_type (pedigree_type);
+ tree field = add_field ("rank", uint64_type_node, NULL_TREE);
+ cilk_trees[CILK_TI_PEDIGREE_RANK] = field;
+ field = add_field ("parent", pedigree_ptr, field);
+ cilk_trees[CILK_TI_PEDIGREE_PARENT] = field;
+ finish_builtin_struct (pedigree_type, "__cilkrts_pedigree_GCC", field,
+ NULL_TREE);
+ lang_hooks.types.register_builtin_type (pedigree_type,
+ "__cilkrts_pedigree_t");
+ cilk_pedigree_type_decl = pedigree_type;
+
+ /* Build the Cilk Stack Frame:
+ struct __cilkrts_stack_frame {
+ uint32_t flags;
+ uint32_t size;
+ struct __cilkrts_stack_frame *call_parent;
+ __cilkrts_worker *worker;
+ void *except_data;
+ void *ctx[4];
+ uint32_t mxcsr;
+ uint16_t fpcsr;
+ uint16_t reserved;
+ __cilkrts_pedigree pedigree;
+ }; */
+
+ tree frame = lang_hooks.types.make_type (RECORD_TYPE);
+ tree frame_ptr = build_pointer_type (frame);
+ tree worker_type = lang_hooks.types.make_type (RECORD_TYPE);
+ tree worker_ptr = build_pointer_type (worker_type);
+ tree s_type_node = build_int_cst (size_type_node, 4);
+
+ tree flags = add_field ("flags", uint32_type_node, NULL_TREE);
+ tree size = add_field ("size", uint32_type_node, flags);
+ tree parent = add_field ("call_parent", frame_ptr, size);
+ tree worker = add_field ("worker", worker_ptr, parent);
+ tree except = add_field ("except_data", frame_ptr, worker);
+ tree context = add_field ("ctx",
+ build_array_type (ptr_type_node,
+ build_index_type (s_type_node)),
+ except);
+ tree mxcsr = add_field ("mxcsr", uint32_type_node, context);
+ tree fpcsr = add_field ("fpcsr", uint16_type_node, mxcsr);
+ tree reserved = add_field ("reserved", uint16_type_node, fpcsr);
+ tree pedigree = add_field ("pedigree", pedigree_type, reserved);
+
+ /* Now add them to a common structure whose fields are #defined to something
+ that is used at a later stage. */
+ cilk_trees[CILK_TI_FRAME_FLAGS] = flags;
+ cilk_trees[CILK_TI_FRAME_PARENT] = parent;
+ cilk_trees[CILK_TI_FRAME_WORKER] = worker;
+ cilk_trees[CILK_TI_FRAME_EXCEPTION] = except;
+ cilk_trees[CILK_TI_FRAME_CONTEXT] = context;
+ /* We don't care about reserved, so no need to store it in cilk_trees. */
+ cilk_trees[CILK_TI_FRAME_PEDIGREE] = pedigree;
+ TREE_ADDRESSABLE (frame) = 1;
+
+ finish_builtin_struct (frame, "__cilkrts_st_frame_GCC", pedigree, NULL_TREE);
+ cilk_frame_type_decl = frame;
+ lang_hooks.types.register_builtin_type (frame, "__cilkrts_frame_t");
+
+ cilk_frame_ptr_type_decl = build_qualified_type (frame_ptr,
+ TYPE_QUAL_VOLATILE);
+ /* Now let's do the following worker struct:
+
+ struct __cilkrts_worker {
+ __cilkrts_stack_frame *volatile *volatile tail;
+ __cilkrts_stack_frame *volatile *volatile head;
+ __cilkrts_stack_frame *volatile *volatile exc;
+ __cilkrts_stack_frame *volatile *volatile protected_tail;
+ __cilkrts_stack_frame *volatile *ltq_limit;
+ int32_t self;
+ global_state_t *g;
+ local_state *l;
+ cilkred_map *reducer_map;
+ __cilkrts_stack_frame *current_stack_frame;
+ void *reserved;
+ __cilkrts_worker_sysdep_state *sysdep;
+ __cilkrts_pedigree pedigree;
+ } */
+
+ tree fptr_volatil_type = build_qualified_type (frame_ptr, TYPE_QUAL_VOLATILE);
+ tree fptr_volatile_ptr = build_pointer_type (fptr_volatil_type);
+ tree fptr_vol_ptr_vol = build_qualified_type (fptr_volatile_ptr,
+ TYPE_QUAL_VOLATILE);
+ tree g = lang_hooks.types.make_type (RECORD_TYPE);
+ finish_builtin_struct (g, "__cilkrts_global_state", NULL_TREE, NULL_TREE);
+ tree l = lang_hooks.types.make_type (RECORD_TYPE);
+ finish_builtin_struct (l, "__cilkrts_local_state", NULL_TREE, NULL_TREE);
+ tree sysdep_t = lang_hooks.types.make_type (RECORD_TYPE);
+ finish_builtin_struct (sysdep_t, "__cilkrts_worker_sysdep_state", NULL_TREE,
+ NULL_TREE);
+
+ field = add_field ("tail", fptr_vol_ptr_vol, NULL_TREE);
+ cilk_trees[CILK_TI_WORKER_TAIL] = field;
+ field = add_field ("head", fptr_vol_ptr_vol, field);
+ field = add_field ("exc", fptr_vol_ptr_vol, field);
+ field = add_field ("protected_tail", fptr_vol_ptr_vol, field);
+ field = add_field ("ltq_limit", fptr_volatile_ptr, field);
+ field = add_field ("self", integer_type_node, field);
+ field = add_field ("g", build_pointer_type (g), field);
+ field = add_field ("l", build_pointer_type (g), field);
+ field = add_field ("reducer_map", ptr_type_node, field);
+ field = add_field ("current_stack_frame", frame_ptr, field);
+ cilk_trees[CILK_TI_WORKER_CUR] = field;
+ field = add_field ("saved_protected_tail", fptr_volatile_ptr, field);
+ field = add_field ("sysdep", build_pointer_type (sysdep_t), field);
+ field = add_field ("pedigree", pedigree_type, field);
+ cilk_trees[CILK_TI_WORKER_PEDIGREE] = field;
+ finish_builtin_struct (worker_type, "__cilkrts_worker_GCC", field,
+ NULL_TREE);
+
+ tree fptr_arglist = tree_cons (NULL_TREE, frame_ptr, void_list_node);
+ tree fptr_fun = build_function_type (void_type_node, fptr_arglist);
+
+ /* void __cilkrts_enter_frame_1 (__cilkrts_stack_frame *); */
+ cilk_enter_fndecl = install_builtin ("__cilkrts_enter_frame_1", fptr_fun,
+ BUILT_IN_CILK_ENTER_FRAME, false);
+
+ /* void __cilkrts_enter_frame_fast_1 (__cilkrts_stack_frame *); */
+ cilk_enter_fast_fndecl =
+ install_builtin ("__cilkrts_enter_frame_fast_1", fptr_fun,
+ BUILT_IN_CILK_ENTER_FRAME_FAST, false);
+
+ /* void __cilkrts_pop_frame (__cilkrts_stack_frame *); */
+ cilk_pop_fndecl = install_builtin ("__cilkrts_pop_frame", fptr_fun,
+ BUILT_IN_CILK_POP_FRAME, false);
+
+ /* void __cilkrts_leave_frame (__cilkrts_stack_frame *); */
+ cilk_leave_fndecl = install_builtin ("__cilkrts_leave_frame", fptr_fun,
+ BUILT_IN_CILK_LEAVE_FRAME, false);
+
+ /* void __cilkrts_sync (__cilkrts_stack_frame *); */
+ cilk_sync_fndecl = install_builtin ("__cilkrts_sync", fptr_fun,
+ BUILT_IN_CILK_SYNC, false);
+
+ /* void __cilkrts_detach (__cilkrts_stack_frame *); */
+ cilk_detach_fndecl = install_builtin ("__cilkrts_detach", fptr_fun,
+ BUILT_IN_CILK_DETACH, false);
+
+ /* __cilkrts_rethrow (struct stack_frame *); */
+ cilk_rethrow_fndecl = install_builtin ("__cilkrts_rethrow", fptr_fun,
+ BUILT_IN_CILK_RETHROW, false);
+
+ /* __cilkrts_save_fp_ctrl_state (__cilkrts_stack_frame *); */
+ cilk_save_fp_fndecl = install_builtin ("__cilkrts_save_fp_ctrl_state",
+ fptr_fun, BUILT_IN_CILK_SAVE_FP,
+ false);
+}
+
+/* Get the appropriate frame arguments for CALL that is of type CALL_EXPR. */
+
+static tree
+get_frame_arg (tree call)
+{
+ tree arg, argtype;
+
+ gcc_assert (call_expr_nargs (call) >= 1);
+
+ arg = CALL_EXPR_ARG (call, 0);
+ argtype = TREE_TYPE (arg);
+ gcc_assert (TREE_CODE (argtype) == POINTER_TYPE);
+
+ argtype = TREE_TYPE (argtype);
+
+ gcc_assert (!lang_hooks.types_compatible_p
+ || lang_hooks.types_compatible_p (argtype, cilk_frame_type_decl));
+
+ /* If it is passed in as an address, then just use the value directly
+ since the function is inlined. */
+ if (TREE_CODE (arg) == INDIRECT_REF || TREE_CODE (arg) == ADDR_EXPR)
+ return TREE_OPERAND (arg, 0);
+ return arg;
+}
+
+/* Expands the __cilkrts_pop_frame function call stored in EXP. */
+
+void
+expand_builtin_cilk_pop_frame (tree exp)
+{
+ tree frame = get_frame_arg (exp);
+ tree parent = cilk_dot (frame, CILK_TI_FRAME_PARENT, 0);
+
+ tree clear_parent = build2 (MODIFY_EXPR, void_type_node, parent,
+ build_int_cst (TREE_TYPE (parent), 0));
+ expand_expr (clear_parent, const0_rtx, VOIDmode, EXPAND_NORMAL);
+
+ /* During LTO, the is_cilk_function flag gets cleared.
+ If __cilkrts_pop_frame is called, then this definitely must be a
+ cilk function. */
+ if (cfun)
+ cfun->is_cilk_function = 1;
+}
+
+/* Expands the cilk_detach function call stored in EXP. */
+
+void
+expand_builtin_cilk_detach (tree exp)
+{
+ rtx insn;
+ tree fptr = get_frame_arg (exp);
+
+ if (fptr == NULL_TREE)
+ return;
+
+ tree parent = cilk_dot (fptr, CILK_TI_FRAME_PARENT, 0);
+ tree worker = cilk_dot (fptr, CILK_TI_FRAME_WORKER, 0);
+ tree tail = cilk_dot (worker, CILK_TI_WORKER_TAIL, 1);
+
+ rtx wreg = expand_expr (worker, NULL_RTX, Pmode, EXPAND_NORMAL);
+ if (GET_CODE (wreg) != REG)
+ wreg = copy_to_reg (wreg);
+ rtx preg = expand_expr (parent, NULL_RTX, Pmode, EXPAND_NORMAL);
+
+ /* TMP <- WORKER.TAIL
+ *TMP <- PARENT
+ TMP <- TMP + 1
+ WORKER.TAIL <- TMP */
+
+ HOST_WIDE_INT worker_tail_offset =
+ tree_low_cst (DECL_FIELD_OFFSET (cilk_trees[CILK_TI_WORKER_TAIL]), 0) +
+ tree_low_cst (DECL_FIELD_BIT_OFFSET (cilk_trees[CILK_TI_WORKER_TAIL]), 0) /
+ BITS_PER_UNIT;
+ rtx tmem0 = gen_rtx_MEM (Pmode,
+ plus_constant (Pmode, wreg, worker_tail_offset));
+ set_mem_attributes (tmem0, tail, 0);
+ MEM_NOTRAP_P (tmem0) = 1;
+ gcc_assert (MEM_VOLATILE_P (tmem0));
+ rtx treg = copy_to_mode_reg (Pmode, tmem0);
+ rtx tmem1 = gen_rtx_MEM (Pmode, treg);
+ set_mem_attributes (tmem1, TREE_TYPE (TREE_TYPE (tail)), 0);
+ MEM_NOTRAP_P (tmem1) = 1;
+ emit_move_insn (tmem1, preg);
+ emit_move_insn (treg, plus_constant (Pmode, treg, GET_MODE_SIZE (Pmode)));
+
+ /* There is a release barrier (st8.rel, membar #StoreStore,
+ sfence, lwsync, etc.) between the two stores. On x86
+ normal volatile stores have proper semantics; the sfence
+ would only be needed for nontemporal stores (which we
+ could generate using the storent optab, for no benefit
+ in this case).
+
+ The predicate may return false even for a REG if this is
+ the limited release operation that only stores 0. */
+ enum insn_code icode = direct_optab_handler (sync_lock_release_optab, Pmode);
+ if (icode != CODE_FOR_nothing
+ && insn_data[icode].operand[1].predicate (treg, Pmode)
+ && (insn = GEN_FCN (icode) (tmem0, treg)) != NULL_RTX)
+ emit_insn (insn);
+ else
+ emit_move_insn (tmem0, treg);
+
+ /* The memory barrier inserted above should not prevent
+ the load of flags from being moved before the stores,
+ but in practice it does because it is implemented with
+ unspec_volatile. In-order RISC machines should
+ explicitly load flags earlier. */
+
+ tree flags = cilk_dot (fptr, CILK_TI_FRAME_FLAGS, 0);
+ expand_expr (build2 (MODIFY_EXPR, void_type_node, flags,
+ build2 (BIT_IOR_EXPR, TREE_TYPE (flags), flags,
+ build_int_cst (TREE_TYPE (flags),
+ CILK_FRAME_DETACHED))),
+ const0_rtx, VOIDmode, EXPAND_NORMAL);
+}
+
+/* Returns a setjmp CALL_EXPR with FRAME->context as its parameter. */
+
+tree
+cilk_call_setjmp (tree frame)
+{
+ tree c = cilk_dot (frame, CILK_TI_FRAME_CONTEXT, false);
+ c = build1 (ADDR_EXPR, build_pointer_type (ptr_type_node), c);
+ return build_call_expr (builtin_decl_implicit (BUILT_IN_SETJMP), 1, c);
+}
+
+/* This function will expand the _Cilk_sync keyword. */
+
+static tree
+expand_cilk_sync (void)
+{
+ tree frame = cfun->cilk_frame_decl;
+
+ /* Cilk_sync is converted to the following code:
+
+ sf.pedigree = sf.worker->pedigree;
+ if (frame.flags & CILK_FRAME_UNSYNCHED)
+ {
+ __cilkrts_save_fp_state (&sf);
+ if (!builtin_setjmp (sf.ctx)
+ __cilkrts_sync (&sf);
+ else
+ if (sf.flags & CILK_FRAME_EXCEPTING)
+ __cilkrts_rethrow (&sf);
+ }
+ sf.worker->pedigree.rank = sf.worker->pedigree.rank + 1; */
+
+ tree flags = cilk_dot (frame, CILK_TI_FRAME_FLAGS, false);
+
+ tree unsynched = fold_build2 (BIT_AND_EXPR, TREE_TYPE (flags), flags,
+ build_int_cst (TREE_TYPE (flags),
+ CILK_FRAME_UNSYNCHED));
+
+ unsynched = fold_build2 (NE_EXPR, TREE_TYPE (unsynched), unsynched,
+ build_int_cst (TREE_TYPE (unsynched), 0));
+
+ tree frame_addr = build1 (ADDR_EXPR, cilk_frame_ptr_type_decl, frame);
+
+ /* Check if exception (0x10) bit is set in the sf->flags. */
+ tree except_flag = fold_build2 (BIT_AND_EXPR, TREE_TYPE (flags), flags,
+ build_int_cst (TREE_TYPE (flags),
+ CILK_FRAME_EXCEPTING));
+ except_flag = fold_build2 (NE_EXPR, TREE_TYPE (except_flag), except_flag,
+ build_int_cst (TREE_TYPE (except_flag), 0));
+
+ /* If the exception flag is set then call the __cilkrts_rethrow (&sf). */
+ tree except_cond = fold_build3 (COND_EXPR, void_type_node, except_flag,
+ build_call_expr (cilk_rethrow_fndecl, 1,
+ frame_addr),
+ build_empty_stmt (EXPR_LOCATION (unsynched)));
+
+ tree sync_expr = build_call_expr (cilk_sync_fndecl, 1, frame_addr);
+ tree setjmp_expr = cilk_call_setjmp (frame);
+ setjmp_expr = fold_build2 (EQ_EXPR, TREE_TYPE (setjmp_expr), setjmp_expr,
+ build_int_cst (TREE_TYPE (setjmp_expr), 0));
+
+ setjmp_expr = fold_build3 (COND_EXPR, void_type_node, setjmp_expr,
+ sync_expr, except_cond);
+ tree sync_list = alloc_stmt_list ();
+ append_to_statement_list (build_call_expr (cilk_save_fp_fndecl, 1,
+ frame_addr), &sync_list);
+ append_to_statement_list (setjmp_expr, &sync_list);
+ tree sync = fold_build3 (COND_EXPR, void_type_node, unsynched, sync_list,
+ build_empty_stmt (EXPR_LOCATION (unsynched)));
+ tree parent_pedigree = cilk_dot (frame, CILK_TI_FRAME_PEDIGREE, false);
+ tree worker = cilk_dot (frame, CILK_TI_FRAME_WORKER, false);
+ tree worker_pedigree = cilk_arrow (worker, CILK_TI_WORKER_PEDIGREE, false);
+ tree assign_pedigree = fold_build2 (MODIFY_EXPR, void_type_node,
+ parent_pedigree, worker_pedigree);
+ tree w_ped_rank = cilk_dot (unshare_expr (worker_pedigree),
+ CILK_TI_PEDIGREE_RANK, false);
+ tree incr_ped_rank = fold_build2 (PLUS_EXPR, TREE_TYPE (w_ped_rank),
+ w_ped_rank,
+ build_one_cst (TREE_TYPE (w_ped_rank)));
+ incr_ped_rank = fold_build2 (MODIFY_EXPR, void_type_node, w_ped_rank,
+ incr_ped_rank);
+ tree ret_sync_exp = alloc_stmt_list ();
+ append_to_statement_list (assign_pedigree, &ret_sync_exp);
+ append_to_statement_list (sync, &ret_sync_exp);
+ append_to_statement_list (incr_ped_rank, &ret_sync_exp);
+ return ret_sync_exp;
+}
+
+/* Gimplifies the cilk_sync expression passed in *EXPR_P. Returns GS_ALL_DONE
+ when finished. */
+
+void
+gimplify_cilk_sync (tree *expr_p, gimple_seq *pre_p)
+{
+ tree sync_expr = expand_cilk_sync ();
+ *expr_p = NULL_TREE;
+ gimplify_and_add (sync_expr, pre_p);
+}
diff --git a/gcc/cilk.h b/gcc/cilk.h
new file mode 100644
index 00000000000..99b4d782af4
--- /dev/null
+++ b/gcc/cilk.h
@@ -0,0 +1,102 @@
+/* This file is part of the Intel(R) Cilk(TM) Plus support
+ This file contains Cilk Support files.
+ Copyright (C) 2013 Free Software Foundation, Inc.
+ Contributed by Balaji V. Iyer <balaji.v.iyer@intel.com>,
+ Intel Corporation
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ GCC is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have 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_CILK_H
+#define GCC_CILK_H
+
+/* Frame status bits known to compiler. */
+#define CILK_FRAME_UNSYNCHED 0x02
+#define CILK_FRAME_DETACHED 0x04
+#define CILK_FRAME_EXCEPTING 0x10
+#define CILK_FRAME_VERSION (1 << 24)
+
+enum cilk_tree_index {
+/* All the built-in functions for Cilk keywords. */
+ CILK_TI_F_WORKER = 0, /* __cilkrts_get_worker (). */
+ CILK_TI_F_SYNC, /* __cilkrts_sync (). */
+ CILK_TI_F_DETACH, /* __cilkrts_detach (...). */
+ CILK_TI_F_ENTER, /* __cilkrts_enter_frame (...). */
+ CILK_TI_F_ENTER_FAST, /* __cilkrts_enter_frame_fast (.). */
+ CILK_TI_F_LEAVE, /* __cilkrts_leave_frame (...). */
+ CILK_TI_F_POP, /* __cilkrts_pop_frame (...). */
+ CILK_TI_F_RETHROW, /* __cilkrts_rethrow (...). */
+ CILK_TI_F_SAVE_FP, /* __cilkrts_save_fp_ctrl_state (...). */
+ /* __cilkrts_stack_frame struct fields. */
+ CILK_TI_FRAME_FLAGS, /* stack_frame->flags. */
+ CILK_TI_FRAME_PARENT, /* stack_frame->parent. */
+ CILK_TI_FRAME_WORKER, /* stack_frame->worker. */
+ CILK_TI_FRAME_EXCEPTION, /* stack_frame->except_data. */
+ CILK_TI_FRAME_CONTEXT, /* stack_frame->context[4]. */
+ CILK_TI_FRAME_PEDIGREE, /* stack_frame->pedigree. */
+
+ /* __cilkrts_worker struct fields. */
+ CILK_TI_WORKER_CUR, /* worker->current_stack_frame. */
+ CILK_TI_WORKER_TAIL, /* worker->tail. */
+ CILK_TI_WORKER_PEDIGREE, /* worker->pedigree. */
+
+ /* __cilkrts_pedigree struct fields. */
+ CILK_TI_PEDIGREE_RANK, /* pedigree->rank. */
+ CILK_TI_PEDIGREE_PARENT, /* pedigree->parent. */
+
+ /* Types. */
+ CILK_TI_FRAME_TYPE, /* struct __cilkrts_stack_frame. */
+ CILK_TI_FRAME_PTR, /* __cilkrts_stack_frame *. */
+ CILK_TI_WORKER_TYPE, /* struct __cilkrts_worker. */
+ CILK_TI_PEDIGREE_TYPE, /* struct __cilkrts_pedigree. */
+ CILK_TI_MAX
+};
+
+extern GTY (()) tree cilk_trees[CILK_TI_MAX];
+
+#define cilk_worker_fndecl cilk_trees[CILK_TI_F_WORKER]
+#define cilk_sync_fndecl cilk_trees[CILK_TI_F_SYNC]
+#define cilk_synched_fndecl cilk_trees[CILK_TI_F_SYNCED]
+#define cilk_detach_fndecl cilk_trees[CILK_TI_F_DETACH]
+#define cilk_enter_fndecl cilk_trees[CILK_TI_F_ENTER]
+#define cilk_enter_fast_fndecl cilk_trees[CILK_TI_F_ENTER_FAST]
+#define cilk_leave_fndecl cilk_trees[CILK_TI_F_LEAVE]
+#define cilk_rethrow_fndecl cilk_trees[CILK_TI_F_RETHROW]
+#define cilk_pop_fndecl cilk_trees[CILK_TI_F_POP]
+#define cilk_save_fp_fndecl cilk_trees[CILK_TI_F_SAVE_FP]
+
+#define cilk_worker_type_fndecl cilk_trees[CILK_TI_WORKER_TYPE]
+#define cilk_frame_type_decl cilk_trees[CILK_TI_FRAME_TYPE]
+#define cilk_frame_ptr_type_decl cilk_trees[CILK_TI_FRAME_PTR]
+#define cilk_pedigree_type_decl cilk_trees[CILK_TI_PEDIGREE_TYPE]
+
+extern void expand_builtin_cilk_detach (tree);
+extern void expand_builtin_cilk_pop_frame (tree);
+extern tree cilk_arrow (tree, int, bool);
+extern tree cilk_dot (tree, int, bool);
+extern void cilk_init_builtins (void);
+extern void gimplify_cilk_sync (tree *, gimple_seq *);
+extern tree cilk_call_setjmp (tree);
+/* Returns true if Cilk Plus is enabled and if F->cilk_frame_decl is not
+ NULL_TREE. */
+
+inline bool
+fn_contains_cilk_spawn_p (function *f)
+{
+ return (flag_enable_cilkplus
+ && (f->calls_cilk_spawn || f->cilk_frame_decl != NULL_TREE));
+}
+#endif
diff --git a/gcc/collect2.c b/gcc/collect2.c
index 43b9defafd8..84cf6b476e4 100644
--- a/gcc/collect2.c
+++ b/gcc/collect2.c
@@ -602,7 +602,7 @@ is_ctor_dtor (const char *s)
{
if (ch == p->name[0]
&& (!p->two_underscores || ((s - orig_s) >= 2))
- && strncmp(s, p->name, p->len) == 0)
+ && strncmp (s, p->name, p->len) == 0)
{
return p->ret;
}
@@ -777,7 +777,7 @@ maybe_run_lto_and_relink (char **lto_ld_argv, char **object_lst,
plus number of partitions. */
for (lto_ld_argv_size = 0; lto_ld_argv[lto_ld_argv_size]; lto_ld_argv_size++)
;
- out_lto_ld_argv = XCNEWVEC(char *, num_files + lto_ld_argv_size + 1);
+ out_lto_ld_argv = XCNEWVEC (char *, num_files + lto_ld_argv_size + 1);
out_lto_ld_argv_size = 0;
/* After running the LTO back end, we will relink, substituting
@@ -1644,9 +1644,9 @@ main (int argc, char **argv)
"%d destructors found\n",
destructors.number),
destructors.number);
- notice_translated (ngettext("%d frame table found\n",
- "%d frame tables found\n",
- frame_tables.number),
+ notice_translated (ngettext ("%d frame table found\n",
+ "%d frame tables found\n",
+ frame_tables.number),
frame_tables.number);
}
@@ -1698,7 +1698,7 @@ main (int argc, char **argv)
sort_ids (&constructors);
sort_ids (&destructors);
- maybe_unlink(output_file);
+ maybe_unlink (output_file);
outf = fopen (c_file, "w");
if (outf == (FILE *) 0)
fatal_error ("fopen %s: %m", c_file);
@@ -1812,8 +1812,8 @@ collect_wait (const char *prog, struct pex_obj *pex)
{
int sig = WTERMSIG (status);
error ("%s terminated with signal %d [%s]%s",
- prog, sig, strsignal(sig),
- WCOREDUMP(status) ? ", core dumped" : "");
+ prog, sig, strsignal (sig),
+ WCOREDUMP (status) ? ", core dumped" : "");
exit (FATAL_EXIT_CODE);
}
@@ -2255,8 +2255,8 @@ write_c_file_stat (FILE *stream, const char *name ATTRIBUTE_UNUSED)
if (shared_obj)
{
- COLLECT_SHARED_INIT_FUNC(stream, initname);
- COLLECT_SHARED_FINI_FUNC(stream, fininame);
+ COLLECT_SHARED_INIT_FUNC (stream, initname);
+ COLLECT_SHARED_FINI_FUNC (stream, fininame);
}
}
@@ -2727,16 +2727,16 @@ scan_libraries (const char *prog_name)
#if defined (EXTENDED_COFF)
-# define GCC_SYMBOLS(X) (SYMHEADER(X).isymMax + SYMHEADER(X).iextMax)
+# define GCC_SYMBOLS(X) (SYMHEADER (X).isymMax + SYMHEADER (X).iextMax)
# define GCC_SYMENT SYMR
# define GCC_OK_SYMBOL(X) ((X).st == stProc || (X).st == stGlobal)
# define GCC_SYMINC(X) (1)
-# define GCC_SYMZERO(X) (SYMHEADER(X).isymMax)
-# define GCC_CHECK_HDR(X) (PSYMTAB(X) != 0)
+# define GCC_SYMZERO(X) (SYMHEADER (X).isymMax)
+# define GCC_CHECK_HDR(X) (PSYMTAB (X) != 0)
#else
-# define GCC_SYMBOLS(X) (HEADER(ldptr).f_nsyms)
+# define GCC_SYMBOLS(X) (HEADER (ldptr).f_nsyms)
# define GCC_SYMENT SYMENT
# if defined (C_WEAKEXT)
# define GCC_OK_SYMBOL(X) \
@@ -2994,7 +2994,7 @@ scan_prog_file (const char *prog_name, scanpass which_pass,
while (ldclose (ldptr) == FAILURE);
#else
/* Otherwise we simply close ldptr. */
- (void) ldclose(ldptr);
+ (void) ldclose (ldptr);
#endif
}
#endif /* OBJECT_FORMAT_COFF */
@@ -3014,7 +3014,7 @@ resolve_lib_name (const char *name)
if (libpaths[i]->max_len > l)
l = libpaths[i]->max_len;
- lib_buf = XNEWVEC (char, l + strlen(name) + 10);
+ lib_buf = XNEWVEC (char, l + strlen (name) + 10);
for (i = 0; libpaths[i]; i++)
{
@@ -3025,7 +3025,7 @@ resolve_lib_name (const char *name)
may contain directories both with trailing DIR_SEPARATOR and
without it. */
const char *p = "";
- if (!IS_DIR_SEPARATOR (list->prefix[strlen(list->prefix)-1]))
+ if (!IS_DIR_SEPARATOR (list->prefix[strlen (list->prefix)-1]))
p = "/";
for (j = 0; j < 2; j++)
{
diff --git a/gcc/combine-stack-adj.c b/gcc/combine-stack-adj.c
index be47665ebc0..5ca131f346a 100644
--- a/gcc/combine-stack-adj.c
+++ b/gcc/combine-stack-adj.c
@@ -663,8 +663,8 @@ const pass_data pass_data_stack_adjustments =
class pass_stack_adjustments : public rtl_opt_pass
{
public:
- pass_stack_adjustments(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_stack_adjustments, ctxt)
+ pass_stack_adjustments (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_stack_adjustments, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/combine.c b/gcc/combine.c
index 335d3ddd6cd..13f5e29e3d6 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -735,7 +735,7 @@ do_SUBST (rtx *into, rtx newval)
buf->next = undobuf.undos, undobuf.undos = buf;
}
-#define SUBST(INTO, NEWVAL) do_SUBST(&(INTO), (NEWVAL))
+#define SUBST(INTO, NEWVAL) do_SUBST (&(INTO), (NEWVAL))
/* Similar to SUBST, but NEWVAL is an int expression. Note that substitution
for the value of a HOST_WIDE_INT value (including CONST_INT) is
@@ -763,7 +763,7 @@ do_SUBST_INT (int *into, int newval)
buf->next = undobuf.undos, undobuf.undos = buf;
}
-#define SUBST_INT(INTO, NEWVAL) do_SUBST_INT(&(INTO), (NEWVAL))
+#define SUBST_INT(INTO, NEWVAL) do_SUBST_INT (&(INTO), (NEWVAL))
/* Similar to SUBST, but just substitute the mode. This is used when
changing the mode of a pseudo-register, so that any other
@@ -792,7 +792,7 @@ do_SUBST_MODE (rtx *into, enum machine_mode newval)
buf->next = undobuf.undos, undobuf.undos = buf;
}
-#define SUBST_MODE(INTO, NEWVAL) do_SUBST_MODE(&(INTO), (NEWVAL))
+#define SUBST_MODE(INTO, NEWVAL) do_SUBST_MODE (&(INTO), (NEWVAL))
#ifndef HAVE_cc0
/* Similar to SUBST, but NEWVAL is a LOG_LINKS expression. */
@@ -1197,8 +1197,8 @@ combine_instructions (rtx f, unsigned int nregs)
INSN_COST (insn) = insn_rtx_cost (PATTERN (insn),
optimize_this_for_speed_p);
if (dump_file)
- fprintf(dump_file, "insn_cost %d: %d\n",
- INSN_UID (insn), INSN_COST (insn));
+ fprintf (dump_file, "insn_cost %d: %d\n",
+ INSN_UID (insn), INSN_COST (insn));
}
}
@@ -2328,7 +2328,7 @@ can_change_dest_mode (rtx x, int added_sets, enum machine_mode mode)
{
unsigned int regno;
- if (!REG_P(x))
+ if (!REG_P (x))
return false;
regno = REGNO (x);
@@ -3693,29 +3693,42 @@ try_combine (rtx i3, rtx i2, rtx i1, rtx i0, int *new_direct_jump_p,
&& ! (contains_muldiv (SET_SRC (XVECEXP (newpat, 0, 0)))
&& contains_muldiv (SET_SRC (XVECEXP (newpat, 0, 1)))))
{
+ rtx set0 = XVECEXP (newpat, 0, 0);
+ rtx set1 = XVECEXP (newpat, 0, 1);
+
/* Normally, it doesn't matter which of the two is done first,
but the one that references cc0 can't be the second, and
one which uses any regs/memory set in between i2 and i3 can't
- be first. */
- if (!use_crosses_set_p (SET_SRC (XVECEXP (newpat, 0, 1)),
- DF_INSN_LUID (i2))
+ be first. The PARALLEL might also have been pre-existing in i3,
+ so we need to make sure that we won't wrongly hoist a SET to i2
+ that would conflict with a death note present in there. */
+ if (!use_crosses_set_p (SET_SRC (set1), DF_INSN_LUID (i2))
+ && !(REG_P (SET_DEST (set1))
+ && find_reg_note (i2, REG_DEAD, SET_DEST (set1)))
+ && !(GET_CODE (SET_DEST (set1)) == SUBREG
+ && find_reg_note (i2, REG_DEAD,
+ SUBREG_REG (SET_DEST (set1))))
#ifdef HAVE_cc0
- && !reg_referenced_p (cc0_rtx, XVECEXP (newpat, 0, 0))
+ && !reg_referenced_p (cc0_rtx, set0)
#endif
)
{
- newi2pat = XVECEXP (newpat, 0, 1);
- newpat = XVECEXP (newpat, 0, 0);
+ newi2pat = set1;
+ newpat = set0;
}
- else if (!use_crosses_set_p (SET_SRC (XVECEXP (newpat, 0, 0)),
- DF_INSN_LUID (i2))
+ else if (!use_crosses_set_p (SET_SRC (set0), DF_INSN_LUID (i2))
+ && !(REG_P (SET_DEST (set0))
+ && find_reg_note (i2, REG_DEAD, SET_DEST (set0)))
+ && !(GET_CODE (SET_DEST (set0)) == SUBREG
+ && find_reg_note (i2, REG_DEAD,
+ SUBREG_REG (SET_DEST (set0))))
#ifdef HAVE_cc0
- && !reg_referenced_p (cc0_rtx, XVECEXP (newpat, 0, 1))
+ && !reg_referenced_p (cc0_rtx, set1)
#endif
)
{
- newi2pat = XVECEXP (newpat, 0, 0);
- newpat = XVECEXP (newpat, 0, 1);
+ newi2pat = set0;
+ newpat = set1;
}
else
{
@@ -4261,9 +4274,8 @@ try_combine (rtx i3, rtx i2, rtx i1, rtx i0, int *new_direct_jump_p,
}
/* Update reg_stat[].nonzero_bits et al for any changes that may have
- been made to this insn. The order of
- set_nonzero_bits_and_sign_copies() is important. Because newi2pat
- can affect nonzero_bits of newpat */
+ been made to this insn. The order is important, because newi2pat
+ can affect nonzero_bits of newpat. */
if (newi2pat)
note_stores (newi2pat, set_nonzero_bits_and_sign_copies, NULL);
note_stores (newpat, set_nonzero_bits_and_sign_copies, NULL);
@@ -4279,17 +4291,17 @@ try_combine (rtx i3, rtx i2, rtx i1, rtx i0, int *new_direct_jump_p,
df_insn_rescan (undobuf.other_insn);
}
- if (i0 && !(NOTE_P(i0) && (NOTE_KIND (i0) == NOTE_INSN_DELETED)))
+ if (i0 && !(NOTE_P (i0) && (NOTE_KIND (i0) == NOTE_INSN_DELETED)))
{
if (dump_file)
{
- fprintf (dump_file, "modifying insn i1 ");
+ fprintf (dump_file, "modifying insn i0 ");
dump_insn_slim (dump_file, i0);
}
df_insn_rescan (i0);
}
- if (i1 && !(NOTE_P(i1) && (NOTE_KIND (i1) == NOTE_INSN_DELETED)))
+ if (i1 && !(NOTE_P (i1) && (NOTE_KIND (i1) == NOTE_INSN_DELETED)))
{
if (dump_file)
{
@@ -4299,7 +4311,7 @@ try_combine (rtx i3, rtx i2, rtx i1, rtx i0, int *new_direct_jump_p,
df_insn_rescan (i1);
}
- if (i2 && !(NOTE_P(i2) && (NOTE_KIND (i2) == NOTE_INSN_DELETED)))
+ if (i2 && !(NOTE_P (i2) && (NOTE_KIND (i2) == NOTE_INSN_DELETED)))
{
if (dump_file)
{
@@ -4309,7 +4321,7 @@ try_combine (rtx i3, rtx i2, rtx i1, rtx i0, int *new_direct_jump_p,
df_insn_rescan (i2);
}
- if (i3 && !(NOTE_P(i3) && (NOTE_KIND (i3) == NOTE_INSN_DELETED)))
+ if (i3 && !(NOTE_P (i3) && (NOTE_KIND (i3) == NOTE_INSN_DELETED)))
{
if (dump_file)
{
@@ -4321,7 +4333,6 @@ try_combine (rtx i3, rtx i2, rtx i1, rtx i0, int *new_direct_jump_p,
/* Set new_direct_jump_p if a new return or simple jump instruction
has been created. Adjust the CFG accordingly. */
-
if (returnjump_p (i3) || any_uncondjump_p (i3))
{
*new_direct_jump_p = 1;
@@ -11015,7 +11026,7 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
this shift are known to be zero for both inputs and if the type of
comparison is compatible with the shift. */
if (GET_CODE (op0) == GET_CODE (op1)
- && HWI_COMPUTABLE_MODE_P (GET_MODE(op0))
+ && HWI_COMPUTABLE_MODE_P (GET_MODE (op0))
&& ((GET_CODE (op0) == ROTATE && (code == NE || code == EQ))
|| ((GET_CODE (op0) == LSHIFTRT || GET_CODE (op0) == ASHIFT)
&& (code != GT && code != LT && code != GE && code != LE))
@@ -13677,7 +13688,7 @@ distribute_notes (rtx notes, rtx from_insn, rtx i3, rtx i2, rtx elim_i2,
}
if (place2)
- add_reg_note (place2, REG_NOTE_KIND (note), XEXP (note, 0));
+ add_shallow_copy_of_reg_note (place2, note);
}
}
@@ -13875,8 +13886,8 @@ const pass_data pass_data_combine =
class pass_combine : public rtl_opt_pass
{
public:
- pass_combine(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_combine, ctxt)
+ pass_combine (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_combine, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/common.opt b/gcc/common.opt
index 202e169d281..d5971df6418 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -913,6 +913,10 @@ fcheck-data-deps
Common Report Var(flag_check_data_deps)
Compare the results of several data dependence analyzers.
+fcheck-new
+Common Var(flag_check_new)
+Check the return value of new in C++
+
fcombine-stack-adjustments
Common Report Var(flag_combine_stack_adjustments) Optimization
Looks for opportunities to reduce stack adjustments and stack references.
@@ -1588,8 +1592,8 @@ Common Joined RejectNegative Var(common_deferred_options) Defer
-fopt-info[-<type>=filename] Dump compiler optimization details
foptimize-register-move
-Common Report Var(flag_regmove) Optimization
-Do the full register move optimization pass
+Common Ignore
+Does nothing. Preserved for backward compatibility.
foptimize-sibling-calls
Common Report Var(flag_optimize_sibling_calls) Optimization
@@ -1726,8 +1730,12 @@ Common Report Var(flag_pcc_struct_return,0) Optimization
Return small aggregates in registers
fregmove
-Common Report Var(flag_regmove) Optimization
-Enables a register move optimization
+Common Ignore
+Does nothing. Preserved for backward compatibility.
+
+flive-range-shrinkage
+Common Report Var(flag_live_range_shrinkage) Init(0) Optimization
+Relief of register pressure through live range shrinkage
frename-registers
Common Report Var(flag_rename_registers) Init(2) Optimization
@@ -2100,6 +2108,12 @@ foptimize-strlen
Common Report Var(flag_optimize_strlen) Optimization
Enable string length optimizations on trees
+fisolate-erroneous-paths
+Common Report Var(flag_isolate_erroneous_paths) Optimization
+Detect paths which trigger erroneous or undefined behaviour. Isolate those
+paths from the main control flow and turn the statement with erroneous or
+undefined behaviour into a trap.
+
ftree-loop-distribution
Common Report Var(flag_tree_loop_distribution) Optimization
Enable loop distribution on trees
@@ -2267,8 +2281,8 @@ Common Report Var(flag_tree_vectorize) Optimization
Enable vectorization on trees
ftree-vectorizer-verbose=
-Common RejectNegative Joined UInteger Var(common_deferred_options) Defer
--ftree-vectorizer-verbose=<number> This switch is deprecated. Use -fopt-info instead.
+Common Joined RejectNegative Ignore
+Does nothing. Preserved for backward compatibility.
ftree-loop-vectorize
Common Report Var(flag_tree_loop_vectorize) Optimization
@@ -2278,13 +2292,33 @@ ftree-slp-vectorize
Common Report Var(flag_tree_slp_vectorize) Optimization
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)
+Specifies the cost model for vectorization
+
+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)
+
fvect-cost-model
-Common Report Var(flag_vect_cost_model) Optimization
-Enable use of cost model in vectorization
+Common RejectNegative Alias(fvect-cost-model=,dynamic)
+Enables the dynamic vectorizer cost model. Preserved for backward compatibility.
+
+fno-vect-cost-model
+Common RejectNegative Alias(fvect-cost-model=,unlimited)
+Enables the unlimited vectorizer cost model. Preserved for backward compatibility.
ftree-vect-loop-version
-Common Report Var(flag_tree_vect_loop_version) Init(1) Optimization
-Enable loop versioning when doing loop vectorization on trees
+Common Ignore
+Does nothing. Preserved for backward compatibility.
ftree-scev-cprop
Common Report Var(flag_tree_scev_cprop) Init(1) Optimization
@@ -2388,13 +2422,17 @@ Common JoinedOrMissing
Generate debug information in default extended format
gno-pubnames
-Common RejectNegative Var(debug_generate_pub_sections, 0) Init(-1)
+Common Negative(gpubnames) Var(debug_generate_pub_sections, 0) Init(-1)
Don't generate DWARF pubnames and pubtypes sections.
gpubnames
-Common RejectNegative Var(debug_generate_pub_sections, 1)
+Common Negative(ggnu-pubnames) Var(debug_generate_pub_sections, 1)
Generate DWARF pubnames and pubtypes sections.
+ggnu-pubnames
+Common Negative(gno-pubnames) Var(debug_generate_pub_sections, 2)
+Generate DWARF pubnames and pubtypes sections with GNU extensions.
+
gno-record-gcc-switches
Common RejectNegative Var(dwarf_record_gcc_switches,0) Init(1)
Don't record gcc command line switches in DWARF DW_AT_producer.
diff --git a/gcc/common/config/arc/arc-common.c b/gcc/common/config/arc/arc-common.c
new file mode 100644
index 00000000000..36e60ebc9d8
--- /dev/null
+++ b/gcc/common/config/arc/arc-common.c
@@ -0,0 +1,117 @@
+/* Common hooks for Synopsys DesignWare ARC
+ Copyright (C) 1994, 1995, 1997, 1998, 2007-2013
+ Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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-core.h"
+#include "tm.h"
+#include "common/common-target.h"
+#include "opts.h"
+#include "flags.h"
+
+static void
+arc_option_init_struct (struct gcc_options *opts)
+{
+ opts->x_flag_no_common = 255; /* Mark as not user-initialized. */
+
+ /* Which cpu we're compiling for (A5, ARC600, ARC601, ARC700). */
+ arc_cpu = PROCESSOR_NONE;
+}
+
+/* Set default optimization options. */
+/* The conditions are incomplete, so we rely on the evaluation order here,
+ which goes from first to last, i.e. the last match prevails. */
+/* ??? But this trick only works for reject_negative options. Approximate
+ missing option combination. */
+#define OPT_LEVELS_3_PLUS_SPEED_ONLY OPT_LEVELS_3_PLUS
+static const struct default_options arc_option_optimization_table[] =
+ {
+ { OPT_LEVELS_1_PLUS, OPT_fomit_frame_pointer, NULL, 1 },
+ { OPT_LEVELS_ALL, OPT_mRcq, NULL, 1 },
+ { OPT_LEVELS_ALL, OPT_mRcw, NULL, 1 },
+ { OPT_LEVELS_ALL, OPT_msize_level_, NULL, 1 },
+ { OPT_LEVELS_3_PLUS_SPEED_ONLY, OPT_msize_level_, NULL, 0 },
+ { OPT_LEVELS_SIZE, OPT_msize_level_, NULL, 3 },
+ { OPT_LEVELS_3_PLUS_SPEED_ONLY, OPT_malign_call, NULL, 1 },
+ { OPT_LEVELS_ALL, OPT_mearly_cbranchsi, NULL, 1 },
+ { OPT_LEVELS_ALL, OPT_mbbit_peephole, NULL, 1 },
+ { OPT_LEVELS_SIZE, OPT_mq_class, NULL, 1 },
+ { OPT_LEVELS_SIZE, OPT_mcase_vector_pcrel, NULL, 1 },
+ { OPT_LEVELS_SIZE, OPT_mcompact_casesi, NULL, 1 },
+ { OPT_LEVELS_NONE, 0, NULL, 0 }
+ };
+
+/* Process options. */
+static bool
+arc_handle_option (struct gcc_options *opts, struct gcc_options *opts_set,
+ const struct cl_decoded_option *decoded,
+ location_t loc)
+{
+ size_t code = decoded->opt_index;
+ int value = decoded->value;
+
+ switch (code)
+ {
+ static int mcpu_seen = PROCESSOR_NONE;
+ case OPT_mcpu_:
+ /* N.B., at this point arc_cpu has already been set to its new value by
+ our caller, so comparing arc_cpu with PROCESSOR_NONE is pointless. */
+
+ if (mcpu_seen != PROCESSOR_NONE && mcpu_seen != value)
+ warning_at (loc, 0, "multiple -mcpu= options specified.");
+ mcpu_seen = value;
+
+ switch (value)
+ {
+ case PROCESSOR_A5:
+ case PROCESSOR_ARC600:
+ case PROCESSOR_ARC700:
+ if (! (opts_set->x_target_flags & MASK_BARREL_SHIFTER) )
+ opts->x_target_flags |= MASK_BARREL_SHIFTER;
+ break;
+ case PROCESSOR_ARC601:
+ if (! (opts_set->x_target_flags & MASK_BARREL_SHIFTER) )
+ opts->x_target_flags &= ~MASK_BARREL_SHIFTER;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ }
+
+ return true;
+}
+
+#define TARGET_OPTION_INIT_STRUCT arc_option_init_struct
+#define TARGET_OPTION_OPTIMIZATION_TABLE arc_option_optimization_table
+#define TARGET_HANDLE_OPTION arc_handle_option
+
+#define DEFAULT_NO_SDATA (TARGET_SDATA_DEFAULT ? 0 : MASK_NO_SDATA_SET)
+
+/* We default to ARC700, which has the barrel shifter enabled. */
+#define TARGET_DEFAULT_TARGET_FLAGS \
+ (MASK_BARREL_SHIFTER|MASK_VOLATILE_CACHE_SET|DEFAULT_NO_SDATA)
+
+
+#include "common/common-target-def.h"
+
+struct gcc_targetm_common targetm_common = TARGETM_COMMON_INITIALIZER;
diff --git a/gcc/common/config/i386/i386-common.c b/gcc/common/config/i386/i386-common.c
index 8ca74b9be49..341637b4a10 100644
--- a/gcc/common/config/i386/i386-common.c
+++ b/gcc/common/config/i386/i386-common.c
@@ -811,7 +811,6 @@ ix86_option_init_struct (struct gcc_options *opts)
opts->x_flag_pcc_struct_return = 2;
opts->x_flag_asynchronous_unwind_tables = 2;
- opts->x_flag_vect_cost_model = 1;
}
/* On the x86 -fsplit-stack and -fstack-protector both use the same
diff --git a/gcc/common/config/m32r/m32r-common.c b/gcc/common/config/m32r/m32r-common.c
index 1a0df406306..f8df5a847fd 100644
--- a/gcc/common/config/m32r/m32r-common.c
+++ b/gcc/common/config/m32r/m32r-common.c
@@ -29,7 +29,6 @@
static const struct default_options m32r_option_optimization_table[] =
{
{ OPT_LEVELS_1_PLUS, OPT_fomit_frame_pointer, NULL, 1 },
- { OPT_LEVELS_1_PLUS, OPT_fregmove, NULL, 1 },
{ OPT_LEVELS_NONE, 0, NULL, 0 }
};
diff --git a/gcc/common/config/mmix/mmix-common.c b/gcc/common/config/mmix/mmix-common.c
index ebc89480240..54acb4d892b 100644
--- a/gcc/common/config/mmix/mmix-common.c
+++ b/gcc/common/config/mmix/mmix-common.c
@@ -28,7 +28,6 @@ along with GCC; see the file COPYING3. If not see
static const struct default_options mmix_option_optimization_table[] =
{
- { OPT_LEVELS_1_PLUS, OPT_fregmove, NULL, 1 },
{ OPT_LEVELS_2_PLUS, OPT_fomit_frame_pointer, NULL, 1 },
{ OPT_LEVELS_NONE, 0, NULL, 0 }
};
diff --git a/gcc/common/config/nds32/nds32-common.c b/gcc/common/config/nds32/nds32-common.c
new file mode 100644
index 00000000000..f82f725af14
--- /dev/null
+++ b/gcc/common/config/nds32/nds32-common.c
@@ -0,0 +1,117 @@
+/* Common hooks of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ You should have 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-core.h"
+#include "tm.h"
+#include "common/common-target.h"
+#include "common/common-target-def.h"
+#include "opts.h"
+#include "flags.h"
+
+/* ------------------------------------------------------------------------ */
+
+/* Implement TARGET_HANDLE_OPTION. */
+static bool
+nds32_handle_option (struct gcc_options *opts ATTRIBUTE_UNUSED,
+ struct gcc_options *opts_set ATTRIBUTE_UNUSED,
+ const struct cl_decoded_option *decoded,
+ location_t loc)
+{
+ size_t code = decoded->opt_index;
+ int value = decoded->value;
+
+ switch (code)
+ {
+ case OPT_misr_vector_size_:
+ /* Check the valid vector size: 4 or 16. */
+ if (value != 4 && value != 16)
+ {
+ error_at (loc, "for the option -misr-vector-size=X, the valid X "
+ "must be: 4 or 16");
+ return false;
+ }
+
+ return true;
+
+ case OPT_mcache_block_size_:
+ /* Check valid value: 4 8 16 32 64 128 256 512. */
+ if (exact_log2 (value) < 2 || exact_log2 (value) > 9)
+ {
+ error_at (loc, "for the option -mcache-block-size=X, the valid X "
+ "must be: 4, 8, 16, 32, 64, 128, 256, or 512");
+ return false;
+ }
+
+ return true;
+
+ default:
+ return true;
+ }
+}
+
+/* ------------------------------------------------------------------------ */
+
+/* Implement TARGET_OPTION_OPTIMIZATION_TABLE. */
+static const struct default_options nds32_option_optimization_table[] =
+{
+ /* Enable -fomit-frame-pointer by default at -O1 or higher. */
+ { OPT_LEVELS_1_PLUS, OPT_fomit_frame_pointer, NULL, 1 },
+ /* Enable -mv3push by default at -Os, but it is useless under V2 ISA. */
+ { OPT_LEVELS_SIZE, OPT_mv3push, NULL, 1 },
+
+ { OPT_LEVELS_NONE, 0, NULL, 0 }
+};
+
+/* ------------------------------------------------------------------------ */
+
+/* Run-time Target Specification. */
+
+/* Default enable
+ TARGET_GP_DIRECT: Generate gp-imply instruction.
+ TARGET_16_BIT : Generate 16/32 bit mixed length instruction.
+ TARGET_PERF_EXT : Generate performance extention instrcution.
+ TARGET_CMOV : Generate conditional move instruction. */
+#undef TARGET_DEFAULT_TARGET_FLAGS
+#define TARGET_DEFAULT_TARGET_FLAGS \
+ (MASK_GP_DIRECT \
+ | MASK_16_BIT \
+ | MASK_PERF_EXT \
+ | MASK_CMOV)
+
+#undef TARGET_HANDLE_OPTION
+#define TARGET_HANDLE_OPTION nds32_handle_option
+
+#undef TARGET_OPTION_OPTIMIZATION_TABLE
+#define TARGET_OPTION_OPTIMIZATION_TABLE nds32_option_optimization_table
+
+
+/* Defining the Output Assembler Language. */
+
+#undef TARGET_EXCEPT_UNWIND_INFO
+#define TARGET_EXCEPT_UNWIND_INFO sjlj_except_unwind_info
+
+/* ------------------------------------------------------------------------ */
+
+struct gcc_targetm_common targetm_common = TARGETM_COMMON_INITIALIZER;
+
+/* ------------------------------------------------------------------------ */
diff --git a/gcc/compare-elim.c b/gcc/compare-elim.c
index 19cf524b1f9..847c89128b4 100644
--- a/gcc/compare-elim.c
+++ b/gcc/compare-elim.c
@@ -247,7 +247,7 @@ class find_comparison_dom_walker : public dom_walker
{
public:
find_comparison_dom_walker (cdi_direction direction)
- : dom_walker(direction) {}
+ : dom_walker (direction) {}
virtual void before_dom_children (basic_block);
};
@@ -673,8 +673,8 @@ const pass_data pass_data_compare_elim_after_reload =
class pass_compare_elim_after_reload : public rtl_opt_pass
{
public:
- pass_compare_elim_after_reload(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_compare_elim_after_reload, ctxt)
+ pass_compare_elim_after_reload (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_compare_elim_after_reload, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/config.gcc b/gcc/config.gcc
index 605efc0e090..6c62a64d25d 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -324,6 +324,9 @@ alpha*-*-*)
am33_2.0-*-linux*)
cpu_type=mn10300
;;
+arc*-*-*)
+ cpu_type=arc
+ ;;
arm*-*-*)
cpu_type=arm
extra_headers="mmintrin.h arm_neon.h"
@@ -418,6 +421,10 @@ mips*-*-*)
extra_headers="loongson.h"
extra_options="${extra_options} g.opt mips/mips-tables.opt"
;;
+nds32*)
+ cpu_type=nds32
+ extra_headers="nds32_intrinsic.h"
+ ;;
picochip-*-*)
cpu_type=picochip
;;
@@ -462,6 +469,7 @@ sh[123456789lbe]*-*-* | sh-*-*)
cpu_type=sh
need_64bit_hwint=yes
extra_options="${extra_options} fused-madd.opt"
+ extra_objs="${extra_objs} sh_treg_combine.o sh-mem.o"
;;
v850*-*-*)
cpu_type=v850
@@ -838,7 +846,7 @@ case ${target} in
*) echo 'Unknown thread configuration for VxWorks'; exit 1 ;;
esac
;;
-*-*-elf)
+*-*-elf|arc*-*-elf*)
# Assume that newlib is being used and so __cxa_atexit is provided.
default_use_cxa_atexit=yes
use_gcc_stdint=wrap
@@ -925,6 +933,54 @@ alpha*-dec-*vms*)
tm_file="${tm_file} vms/vms.h alpha/vms.h"
tmake_file="${tmake_file} alpha/t-vms"
;;
+arc*-*-elf*)
+ extra_headers="arc-simd.h"
+ tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file}"
+ tmake_file="arc/t-arc-newlib arc/t-arc"
+ case x"${with_cpu}" in
+ xarc600|xarc601|xarc700)
+ target_cpu_default="TARGET_CPU_$with_cpu"
+ ;;
+ esac
+ 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_defines="DRIVER_ENDIAN_SELF_SPECS=\\\"%{!EL:%{!mlittle-endian:-mbig-endian}}\\\" ${tm_defines}"
+ esac
+ ;;
+arc*-*-linux-uclibc*)
+ extra_headers="arc-simd.h"
+ tm_file="dbxelf.h elfos.h gnu-user.h linux.h glibc-stdint.h ${tm_file}"
+ tmake_file="${tmake_file} arc/t-arc-uClibc arc/t-arc"
+ tm_defines="${tm_defines} TARGET_SDATA_DEFAULT=0"
+ tm_defines="${tm_defines} TARGET_MMEDIUM_CALLS_DEFAULT=1"
+ case x"${with_cpu}" in
+ xarc600|xarc601|xarc700)
+ target_cpu_default="TARGET_CPU_$with_cpu"
+ ;;
+ esac
+ 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_defines="DRIVER_ENDIAN_SELF_SPECS=\\\"%{!EL:%{!mlittle-endian:-mbig-endian}}\\\" ${tm_defines}"
+ esac
+ ;;
arm-wrs-vxworks)
tm_file="elfos.h arm/elf.h arm/aout.h ${tm_file} vx-common.h vxworks.h arm/vxworks.h"
extra_options="${extra_options} arm/vxworks.opt"
@@ -1113,7 +1169,6 @@ hppa*64*-*-linux*)
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-linux"
gas=yes gnu_ld=yes
need_64bit_hwint=yes
;;
@@ -2040,6 +2095,18 @@ msp430*-*-*)
target_has_targetm_common=no
tmake_file="${tmake_file} msp430/t-msp430"
;;
+nds32le-*-*)
+ target_cpu_default="0"
+ tm_defines="${tm_defines}"
+ tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file}"
+ tmake_file="nds32/t-mlibs"
+ ;;
+nds32be-*-*)
+ target_cpu_default="0|MASK_BIG_ENDIAN"
+ tm_defines="${tm_defines} TARGET_BIG_ENDIAN_DEFAULT=1"
+ tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file}"
+ tmake_file="nds32/t-mlibs"
+ ;;
pdp11-*-*)
tm_file="${tm_file} newlib-stdint.h"
use_gcc_stdint=wrap
@@ -2147,6 +2214,7 @@ powerpc*-*-linux*)
tm_file="${tm_file} dbxelf.h elfos.h freebsd-spec.h rs6000/sysv4.h"
extra_options="${extra_options} rs6000/sysv4.opt"
tmake_file="rs6000/t-fprules rs6000/t-ppcos ${tmake_file} rs6000/t-ppccomm"
+ extra_objs="$extra_objs rs6000-linux.o"
case ${target} in
powerpc*le-*-*)
tm_file="${tm_file} rs6000/sysv4le.h" ;;
@@ -3338,6 +3406,17 @@ case "${target}" in
done
;;
+ arc*-*-*) # was: arc*-*-linux-uclibc)
+ supported_defaults="cpu"
+ case $with_cpu in
+ arc600|arc601|arc700)
+ ;;
+ *) echo "Unknown cpu type"
+ exit 1
+ ;;
+ esac
+ ;;
+
arm*-*-*)
supported_defaults="arch cpu float tune fpu abi mode tls"
for which in cpu tune; do
@@ -3437,6 +3516,43 @@ case "${target}" in
if test "x$with_arch" != x && test "x$with_cpu" != x; then
echo "Warning: --with-arch overrides --with-cpu=$with_cpu" 1>&2
fi
+
+ # Add extra multilibs
+ if test "x$with_multilib_list" != x; then
+ arm_multilibs=`echo $with_multilib_list | sed -e 's/,/ /g'`
+ for arm_multilib in ${arm_multilibs}; do
+ case ${arm_multilib} in
+ aprofile)
+ # Note that arm/t-aprofile is a
+ # stand-alone make file fragment to be
+ # used only with itself. We do not
+ # specifically use the
+ # TM_MULTILIB_OPTION framework because
+ # this shorthand is more
+ # pragmatic. Additionally it is 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=aprofile" 1>&2
+ exit 1
+ fi
+ tmake_file="${tmake_file} arm/t-aprofile"
+ break
+ ;;
+ default)
+ ;;
+ *)
+ echo "Error: --with-multilib-list=${with_multilib_list} not supported." 1>&2
+ exit 1
+ ;;
+ esac
+ done
+ fi
;;
fr*-*-*linux*)
@@ -3655,6 +3771,39 @@ case "${target}" in
esac
;;
+ nds32*-*-*)
+ supported_defaults="arch nds32_lib"
+
+ # process --with-arch
+ case "${with_arch}" in
+ "" | v2 | v3 | v3m)
+ # OK
+ ;;
+ *)
+ echo "Cannot accept --with-arch=$with_arch, available values are: v2 v3 v3m" 1>&2
+ exit 1
+ ;;
+ esac
+
+ # process --with-nds32-lib
+ case "${with_nds32_lib}" in
+ "")
+ # the default library is newlib
+ with_nds32_lib=newlib
+ ;;
+ newlib)
+ # OK
+ ;;
+ mculib)
+ # OK
+ ;;
+ *)
+ echo "Cannot accept --with-nds32-lib=$with_nds32_lib, available values are: newlib mculib" 1>&2
+ exit 1
+ ;;
+ esac
+ ;;
+
powerpc*-*-* | rs6000-*-*)
supported_defaults="cpu cpu_32 cpu_64 float tune tune_32 tune_64"
diff --git a/gcc/config.in b/gcc/config.in
index 44f9a320c27..7bb5be8fdf1 100644
--- a/gcc/config.in
+++ b/gcc/config.in
@@ -1717,12 +1717,6 @@
#endif
-/* Define to 1 if your C compiler doesn't accept -c and -o together. */
-#ifndef USED_FOR_TARGET
-#undef NO_MINUS_C_MINUS_O
-#endif
-
-
/* Define to the address where bug reports for this package should be sent. */
#ifndef USED_FOR_TARGET
#undef PACKAGE_BUGREPORT
diff --git a/gcc/config/aarch64/aarch64-builtins.c b/gcc/config/aarch64/aarch64-builtins.c
index 6816b9cfdaa..0df5b3b0d77 100644
--- a/gcc/config/aarch64/aarch64-builtins.c
+++ b/gcc/config/aarch64/aarch64-builtins.c
@@ -989,6 +989,8 @@ aarch64_simd_expand_args (rtx target, int icode, int have_retval,
switch (thisarg)
{
case SIMD_ARG_COPY_TO_REG:
+ if (POINTER_TYPE_P (TREE_TYPE (arg[argc])))
+ op[argc] = convert_memory_address (Pmode, op[argc]);
/*gcc_assert (GET_MODE (op[argc]) == mode[argc]); */
if (!(*insn_data[icode].operand[argc + have_retval].predicate)
(op[argc], mode[argc]))
diff --git a/gcc/config/aarch64/aarch64-simd-builtins.def b/gcc/config/aarch64/aarch64-simd-builtins.def
index 35897f39395..c18b150a1f5 100644
--- a/gcc/config/aarch64/aarch64-simd-builtins.def
+++ b/gcc/config/aarch64/aarch64-simd-builtins.def
@@ -45,7 +45,7 @@
BUILTIN_VDQF (UNOP, sqrt, 2)
BUILTIN_VD_BHSI (BINOP, addp, 0)
VAR1 (UNOP, addp, 0, di)
- VAR1 (UNOP, clz, 2, v4si)
+ BUILTIN_VDQ_BHSI (UNOP, clz, 2)
BUILTIN_VALL (GETLANE, get_lane, 0)
VAR1 (GETLANE, get_lane, 0, di)
diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md
index f13cd5b7cdb..a747ee8d7ba 100644
--- a/gcc/config/aarch64/aarch64-simd.md
+++ b/gcc/config/aarch64/aarch64-simd.md
@@ -238,80 +238,6 @@
none"
(const_string "none"))
-
-; The "neon_type" attribute is used by the AArch32 backend. Below is a mapping
-; from "simd_type" to "neon_type".
-
-(define_attr "neon_type"
- "neon_int_1,neon_int_2,neon_int_3,neon_int_4,neon_int_5,neon_vqneg_vqabs,
- neon_vmov,neon_vaba,neon_vsma,neon_vaba_qqq,
- neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,neon_mul_qqq_8_16_32_ddd_32,
- neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar,
- neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,neon_mla_qqq_8_16,
- neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long,
- neon_mla_qqq_32_qqd_32_scalar,neon_mul_ddd_16_scalar_32_16_long_scalar,
- neon_mul_qqd_32_scalar,neon_mla_ddd_16_scalar_qdd_32_16_long_scalar,
- neon_shift_1,neon_shift_2,neon_shift_3,neon_vshl_ddd,
- neon_vqshl_vrshl_vqrshl_qqq,neon_vsra_vrsra,neon_fp_vadd_ddd_vabs_dd,
- neon_fp_vadd_qqq_vabs_qq,neon_fp_vsum,neon_fp_vmul_ddd,neon_fp_vmul_qqd,
- neon_fp_vmla_ddd,neon_fp_vmla_qqq,neon_fp_vmla_ddd_scalar,
- neon_fp_vmla_qqq_scalar,neon_fp_vrecps_vrsqrts_ddd,
- neon_fp_vrecps_vrsqrts_qqq,neon_bp_simple,neon_bp_2cycle,neon_bp_3cycle,
- neon_ldr,neon_str,neon_vld1_1_2_regs,neon_vld1_3_4_regs,
- neon_vld2_2_regs_vld1_vld2_all_lanes,neon_vld2_4_regs,neon_vld3_vld4,
- neon_vst1_1_2_regs_vst2_2_regs,neon_vst1_3_4_regs,
- neon_vst2_4_regs_vst3_vst4,neon_vst3_vst4,neon_vld1_vld2_lane,
- neon_vld3_vld4_lane,neon_vst1_vst2_lane,neon_vst3_vst4_lane,
- neon_vld3_vld4_all_lanes,neon_mcr,neon_mcr_2_mcrr,neon_mrc,neon_mrrc,
- neon_ldm_2,neon_stm_2,none,unknown"
- (cond [
- (eq_attr "simd_type" "simd_dup") (const_string "neon_bp_simple")
- (eq_attr "simd_type" "simd_movgp") (const_string "neon_bp_simple")
- (eq_attr "simd_type" "simd_add,simd_logic,simd_logic_imm") (const_string "neon_int_1")
- (eq_attr "simd_type" "simd_negabs,simd_addlv") (const_string "neon_int_3")
- (eq_attr "simd_type" "simd_addn,simd_addn2,simd_addl,simd_sat_add,simd_sat_negabs") (const_string "neon_int_4")
- (eq_attr "simd_type" "simd_move") (const_string "neon_vmov")
- (eq_attr "simd_type" "simd_ins") (const_string "neon_mcr")
- (and (eq_attr "simd_type" "simd_mul,simd_sat_mul") (eq_attr "simd_mode" "V8QI,V4HI")) (const_string "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long")
- (and (eq_attr "simd_type" "simd_mul,simd_sat_mul") (eq_attr "simd_mode" "V2SI,V8QI,V16QI,V2SI")) (const_string "neon_mul_qqq_8_16_32_ddd_32")
- (and (eq_attr "simd_type" "simd_mull,simd_sat_mull") (eq_attr "simd_mode" "V8QI,V16QI,V4HI,V8HI")) (const_string "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long")
- (and (eq_attr "simd_type" "simd_mull,simd_sat_mull") (eq_attr "simd_mode" "V2SI,V4SI,V2DI")) (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")
- (and (eq_attr "simd_type" "simd_mla,simd_sat_mlal") (eq_attr "simd_mode" "V8QI,V4HI")) (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
- (and (eq_attr "simd_type" "simd_mla,simd_sat_mlal") (eq_attr "simd_mode" "V2SI")) (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")
- (and (eq_attr "simd_type" "simd_mla,simd_sat_mlal") (eq_attr "simd_mode" "V16QI,V8HI")) (const_string "neon_mla_qqq_8_16")
- (and (eq_attr "simd_type" "simd_mla,simd_sat_mlal") (eq_attr "simd_mode" "V4SI")) (const_string "neon_mla_qqq_32_qqd_32_scalar")
- (and (eq_attr "simd_type" "simd_mlal") (eq_attr "simd_mode" "V8QI,V16QI,V4HI,V8HI")) (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
- (and (eq_attr "simd_type" "simd_mlal") (eq_attr "simd_mode" "V2SI,V4SI,V2DI")) (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")
- (and (eq_attr "simd_type" "simd_fmla") (eq_attr "simd_mode" "V2SF")) (const_string "neon_fp_vmla_ddd")
- (and (eq_attr "simd_type" "simd_fmla") (eq_attr "simd_mode" "V4SF,V2DF")) (const_string "neon_fp_vmla_qqq")
- (and (eq_attr "simd_type" "simd_fmla_elt") (eq_attr "simd_mode" "V2SF")) (const_string "neon_fp_vmla_ddd_scalar")
- (and (eq_attr "simd_type" "simd_fmla_elt") (eq_attr "simd_mode" "V4SF,V2DF")) (const_string "neon_fp_vmla_qqq_scalar")
- (and (eq_attr "simd_type" "simd_fmul,simd_fmul_elt,simd_fdiv,simd_fsqrt") (eq_attr "simd_mode" "V2SF")) (const_string "neon_fp_vmul_ddd")
- (and (eq_attr "simd_type" "simd_fmul,simd_fmul_elt,simd_fdiv,simd_fsqrt") (eq_attr "simd_mode" "V4SF,V2DF")) (const_string "neon_fp_vmul_qqd")
- (and (eq_attr "simd_type" "simd_fadd") (eq_attr "simd_mode" "V2SF")) (const_string "neon_fp_vadd_ddd_vabs_dd")
- (and (eq_attr "simd_type" "simd_fadd") (eq_attr "simd_mode" "V4SF,V2DF")) (const_string "neon_fp_vadd_qqq_vabs_qq")
- (and (eq_attr "simd_type" "simd_fnegabs,simd_fminmax,simd_fminmaxv") (eq_attr "simd_mode" "V2SF")) (const_string "neon_fp_vadd_ddd_vabs_dd")
- (and (eq_attr "simd_type" "simd_fnegabs,simd_fminmax,simd_fminmaxv") (eq_attr "simd_mode" "V4SF,V2DF")) (const_string "neon_fp_vadd_qqq_vabs_qq")
- (and (eq_attr "simd_type" "simd_shift,simd_shift_acc") (eq_attr "simd_mode" "V8QI,V4HI,V2SI")) (const_string "neon_vshl_ddd")
- (and (eq_attr "simd_type" "simd_shift,simd_shift_acc") (eq_attr "simd_mode" "V16QI,V8HI,V4SI,V2DI")) (const_string "neon_shift_3")
- (eq_attr "simd_type" "simd_minmax,simd_minmaxv") (const_string "neon_int_5")
- (eq_attr "simd_type" "simd_shiftn_imm,simd_shiftn2_imm,simd_shiftl_imm,") (const_string "neon_shift_1")
- (eq_attr "simd_type" "simd_load1,simd_load2") (const_string "neon_vld1_1_2_regs")
- (eq_attr "simd_type" "simd_load3,simd_load3") (const_string "neon_vld1_3_4_regs")
- (eq_attr "simd_type" "simd_load1r,simd_load2r,simd_load3r,simd_load4r") (const_string "neon_vld2_2_regs_vld1_vld2_all_lanes")
- (eq_attr "simd_type" "simd_load1s,simd_load2s") (const_string "neon_vld1_vld2_lane")
- (eq_attr "simd_type" "simd_load3s,simd_load4s") (const_string "neon_vld3_vld4_lane")
- (eq_attr "simd_type" "simd_store1,simd_store2") (const_string "neon_vst1_1_2_regs_vst2_2_regs")
- (eq_attr "simd_type" "simd_store3,simd_store4") (const_string "neon_vst1_3_4_regs")
- (eq_attr "simd_type" "simd_store1s,simd_store2s") (const_string "neon_vst1_vst2_lane")
- (eq_attr "simd_type" "simd_store3s,simd_store4s") (const_string "neon_vst3_vst4_lane")
- (and (eq_attr "simd_type" "simd_frecpe,simd_frecps") (eq_attr "simd_mode" "V2SF")) (const_string "neon_fp_vrecps_vrsqrts_ddd")
- (and (eq_attr "simd_type" "simd_frecpe,simd_frecps") (eq_attr "simd_mode" "V4SF,V2DF")) (const_string "neon_fp_vrecps_vrsqrts_qqq")
- (eq_attr "simd_type" "none") (const_string "none")
- ]
- (const_string "unknown")))
-
-
(define_expand "mov<mode>"
[(set (match_operand:VALL 0 "aarch64_simd_nonimmediate_operand" "")
(match_operand:VALL 1 "aarch64_simd_general_operand" ""))]
@@ -343,6 +269,7 @@
dup\\t%0.<Vtype>, %<vw>1
dup\\t%0.<Vtype>, %1.<Vetype>[0]"
[(set_attr "simd_type" "simd_dupgp, simd_dup")
+ (set_attr "type" "neon_from_gp<q>, neon_dup<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -352,6 +279,7 @@
"TARGET_SIMD"
"dup\\t%0.<Vtype>, %1.<Vetype>[0]"
[(set_attr "simd_type" "simd_dup")
+ (set_attr "type" "neon_dup<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -365,6 +293,7 @@
"TARGET_SIMD"
"dup\\t%0.<Vtype>, %1.<Vetype>[%2]"
[(set_attr "simd_type" "simd_dup")
+ (set_attr "type" "neon_dup<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -378,6 +307,7 @@
"TARGET_SIMD"
"dup\\t%0.<Vtype>, %1.<Vetype>[%2]"
[(set_attr "simd_type" "simd_dup")
+ (set_attr "type" "neon_dup<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -405,6 +335,9 @@
}
}
[(set_attr "simd_type" "simd_load1,simd_store1,simd_move,simd_movgp,simd_insgp,simd_move,simd_move_imm")
+ (set_attr "type" "neon_load1_1reg<q>, neon_store1_1reg<q>,\
+ neon_logic<q>, neon_to_gp<q>, neon_from_gp<q>,\
+ mov_reg, neon_move<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -436,6 +369,9 @@
}
}
[(set_attr "simd_type" "simd_load1,simd_store1,simd_move,simd_movgp,simd_insgp,simd_move,simd_move_imm")
+ (set_attr "type" "neon_load1_1reg<q>, neon_store1_1reg<q>,\
+ neon_logic<q>, multiple, multiple, multiple,\
+ neon_move<q>")
(set_attr "simd_mode" "<MODE>")
(set_attr "length" "4,4,4,8,8,8,4")]
)
@@ -516,6 +452,7 @@
"TARGET_SIMD && reload_completed"
"umov\t%0, %1.d[0]"
[(set_attr "simd_type" "simd_movgp")
+ (set_attr "type" "neon_to_gp<q>")
(set_attr "simd_mode" "<MODE>")
(set_attr "length" "4")
])
@@ -528,6 +465,7 @@
"TARGET_SIMD && reload_completed"
"umov\t%0, %1.d[1]"
[(set_attr "simd_type" "simd_movgp")
+ (set_attr "type" "neon_to_gp<q>")
(set_attr "simd_mode" "<MODE>")
(set_attr "length" "4")
])
@@ -539,6 +477,7 @@
"TARGET_SIMD"
"orn\t%0.<Vbtype>, %2.<Vbtype>, %1.<Vbtype>"
[(set_attr "simd_type" "simd_logic")
+ (set_attr "type" "neon_logic<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -549,6 +488,7 @@
"TARGET_SIMD"
"bic\t%0.<Vbtype>, %2.<Vbtype>, %1.<Vbtype>"
[(set_attr "simd_type" "simd_logic")
+ (set_attr "type" "neon_logic<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -559,6 +499,7 @@
"TARGET_SIMD"
"add\t%0.<Vtype>, %1.<Vtype>, %2.<Vtype>"
[(set_attr "simd_type" "simd_add")
+ (set_attr "type" "neon_add<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -569,6 +510,7 @@
"TARGET_SIMD"
"sub\t%0.<Vtype>, %1.<Vtype>, %2.<Vtype>"
[(set_attr "simd_type" "simd_add")
+ (set_attr "type" "neon_sub<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -579,6 +521,7 @@
"TARGET_SIMD"
"mul\t%0.<Vtype>, %1.<Vtype>, %2.<Vtype>"
[(set_attr "simd_type" "simd_mul")
+ (set_attr "type" "neon_mul_<Vetype><q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -593,6 +536,7 @@
"TARGET_SIMD"
"<f>mul\\t%0.<Vtype>, %3.<Vtype>, %1.<Vetype>[%2]"
[(set_attr "simd_type" "simd_<f>mul_elt")
+ (set_attr "type" "neon<fp>_mul_<Vetype>_scalar<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -607,6 +551,7 @@
"TARGET_SIMD"
"<f>mul\\t%0.<Vtype>, %3.<Vtype>, %1.<Vetype>[%2]"
[(set_attr "simd_type" "simd_<f>mul_elt")
+ (set_attr "type" "neon<fp>_mul_<Vetype>_scalar<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -619,6 +564,7 @@
"TARGET_SIMD"
"fmul\\t%0.2d, %1.2d, %2.d[0]"
[(set_attr "simd_type" "simd_fmul_elt")
+ (set_attr "type" "neon_fp_mul_d_scalar_q")
(set_attr "simd_mode" "V2DF")]
)
@@ -632,6 +578,7 @@
"TARGET_SIMD"
"fmul\\t%0.2d, %3.2d, %1.d[%2]"
[(set_attr "simd_type" "simd_fmul_elt")
+ (set_attr "type" "neon_fp_mul_d_scalar_q")
(set_attr "simd_mode" "V2DF")]
)
@@ -641,6 +588,7 @@
"TARGET_SIMD"
"neg\t%0.<Vtype>, %1.<Vtype>"
[(set_attr "simd_type" "simd_negabs")
+ (set_attr "type" "neon_neg<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -650,6 +598,7 @@
"TARGET_SIMD"
"abs\t%0.<Vtype>, %1.<Vtype>"
[(set_attr "simd_type" "simd_negabs")
+ (set_attr "type" "neon_abs<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -661,6 +610,7 @@
"TARGET_SIMD"
"sabd\t%0.<Vtype>, %1.<Vtype>, %2.<Vtype>"
[(set_attr "simd_type" "simd_abd")
+ (set_attr "type" "neon_abd<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -673,6 +623,7 @@
"TARGET_SIMD"
"saba\t%0.<Vtype>, %1.<Vtype>, %2.<Vtype>"
[(set_attr "simd_type" "simd_abd")
+ (set_attr "type" "neon_arith_acc<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -684,6 +635,7 @@
"TARGET_SIMD"
"fabd\t%0.<Vtype>, %1.<Vtype>, %2.<Vtype>"
[(set_attr "simd_type" "simd_fabd")
+ (set_attr "type" "neon_fp_abd_<Vetype><q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -695,6 +647,7 @@
"TARGET_SIMD"
"fabd\t%<s>0, %<s>1, %<s>2"
[(set_attr "simd_type" "simd_fabd")
+ (set_attr "type" "neon_fp_abd_<Vetype><q>")
(set_attr "mode" "<MODE>")]
)
@@ -705,6 +658,7 @@
"TARGET_SIMD"
"and\t%0.<Vbtype>, %1.<Vbtype>, %2.<Vbtype>"
[(set_attr "simd_type" "simd_logic")
+ (set_attr "type" "neon_logic<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -715,6 +669,7 @@
"TARGET_SIMD"
"orr\t%0.<Vbtype>, %1.<Vbtype>, %2.<Vbtype>"
[(set_attr "simd_type" "simd_logic")
+ (set_attr "type" "neon_logic<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -725,6 +680,7 @@
"TARGET_SIMD"
"eor\t%0.<Vbtype>, %1.<Vbtype>, %2.<Vbtype>"
[(set_attr "simd_type" "simd_logic")
+ (set_attr "type" "neon_logic<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -734,6 +690,7 @@
"TARGET_SIMD"
"not\t%0.<Vbtype>, %1.<Vbtype>"
[(set_attr "simd_type" "simd_logic")
+ (set_attr "type" "neon_logic<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -747,6 +704,7 @@
"TARGET_SIMD"
"ins\t%0.<Vetype>[%p2], %w1";
[(set_attr "simd_type" "simd_insgp")
+ (set_attr "type" "neon_from_gp<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -757,6 +715,7 @@
"TARGET_SIMD"
"ushr\t%0.<Vtype>, %1.<Vtype>, %2"
[(set_attr "simd_type" "simd_shift_imm")
+ (set_attr "type" "neon_shift_imm<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -767,6 +726,7 @@
"TARGET_SIMD"
"sshr\t%0.<Vtype>, %1.<Vtype>, %2"
[(set_attr "simd_type" "simd_shift_imm")
+ (set_attr "type" "neon_shift_imm<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -777,6 +737,7 @@
"TARGET_SIMD"
"shl\t%0.<Vtype>, %1.<Vtype>, %2"
[(set_attr "simd_type" "simd_shift_imm")
+ (set_attr "type" "neon_shift_imm<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -787,6 +748,7 @@
"TARGET_SIMD"
"sshl\t%0.<Vtype>, %1.<Vtype>, %2.<Vtype>"
[(set_attr "simd_type" "simd_shift")
+ (set_attr "type" "neon_shift_reg<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -798,6 +760,7 @@
"TARGET_SIMD"
"ushl\t%0.<Vtype>, %1.<Vtype>, %2.<Vtype>"
[(set_attr "simd_type" "simd_shift")
+ (set_attr "type" "neon_shift_reg<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -809,6 +772,7 @@
"TARGET_SIMD"
"sshl\t%0.<Vtype>, %1.<Vtype>, %2.<Vtype>"
[(set_attr "simd_type" "simd_shift")
+ (set_attr "type" "neon_shift_reg<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -1016,6 +980,7 @@
"TARGET_SIMD"
"ins\t%0.d[%p2], %1";
[(set_attr "simd_type" "simd_insgp")
+ (set_attr "type" "neon_from_gp")
(set_attr "simd_mode" "V2DI")]
)
@@ -1042,6 +1007,7 @@
"TARGET_SIMD"
"ins\t%0.<Vetype>[%p2], %1.<Vetype>[0]";
[(set_attr "simd_type" "simd_ins")
+ (set_attr "type" "neon_ins<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -1067,6 +1033,7 @@
"TARGET_SIMD"
"mla\t%0.<Vtype>, %2.<Vtype>, %3.<Vtype>"
[(set_attr "simd_type" "simd_mla")
+ (set_attr "type" "neon_mla_<Vetype><q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -1083,6 +1050,7 @@
"TARGET_SIMD"
"mla\t%0.<Vtype>, %3.<Vtype>, %1.<Vtype>[%2]"
[(set_attr "simd_type" "simd_mla")
+ (set_attr "type" "neon_mla_<Vetype>_scalar<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -1099,6 +1067,7 @@
"TARGET_SIMD"
"mla\t%0.<Vtype>, %3.<Vtype>, %1.<Vtype>[%2]"
[(set_attr "simd_type" "simd_mla")
+ (set_attr "type" "neon_mla_<Vetype>_scalar<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -1110,6 +1079,7 @@
"TARGET_SIMD"
"mls\t%0.<Vtype>, %2.<Vtype>, %3.<Vtype>"
[(set_attr "simd_type" "simd_mla")
+ (set_attr "type" "neon_mla_<Vetype><q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -1126,6 +1096,7 @@
"TARGET_SIMD"
"mls\t%0.<Vtype>, %3.<Vtype>, %1.<Vtype>[%2]"
[(set_attr "simd_type" "simd_mla")
+ (set_attr "type" "neon_mla_<Vetype>_scalar<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -1142,6 +1113,7 @@
"TARGET_SIMD"
"mls\t%0.<Vtype>, %3.<Vtype>, %1.<Vtype>[%2]"
[(set_attr "simd_type" "simd_mla")
+ (set_attr "type" "neon_mla_<Vetype>_scalar<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -1153,6 +1125,7 @@
"TARGET_SIMD"
"<su><maxmin>\t%0.<Vtype>, %1.<Vtype>, %2.<Vtype>"
[(set_attr "simd_type" "simd_minmax")
+ (set_attr "type" "neon_minmax<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -1169,7 +1142,7 @@
fmov\\t%d0, %1
dup\\t%d0, %1"
[(set_attr "v8type" "*,fmov,*")
- (set_attr "type" "*,fmov,*")
+ (set_attr "type" "neon_dup<q>,fmov,neon_dup<q>")
(set_attr "simd_type" "simd_dup,*,simd_dup")
(set_attr "simd_mode" "<MODE>")
(set_attr "simd" "yes,*,yes")
@@ -1191,6 +1164,7 @@
ins\\t%0.d[1], %1.d[0]
ins\\t%0.d[1], %1"
[(set_attr "simd_type" "simd_ins,simd_ins")
+ (set_attr "type" "neon_ins")
(set_attr "simd_mode" "<MODE>")
(set_attr "length" "4")]
)
@@ -1215,6 +1189,7 @@
"TARGET_SIMD"
"xtn\\t%0.<Vntype>, %1.<Vtype>"
[(set_attr "simd_type" "simd_shiftn_imm")
+ (set_attr "type" "neon_shift_imm_narrow_q")
(set_attr "simd_mode" "<MODE>")]
)
@@ -1242,6 +1217,7 @@
"TARGET_SIMD"
"xtn\\t%0.<Vntype>, %1.<Vtype>\;xtn2\\t%0.<V2ntype>, %2.<Vtype>"
[(set_attr "simd_type" "simd_shiftn2_imm")
+ (set_attr "type" "multiple")
(set_attr "simd_mode" "<MODE>")
(set_attr "length" "8")]
)
@@ -1257,6 +1233,7 @@
"TARGET_SIMD"
"<su>shll %0.<Vwtype>, %1.<Vhalftype>, 0"
[(set_attr "simd_type" "simd_shiftl_imm")
+ (set_attr "type" "neon_shift_imm_long")
(set_attr "simd_mode" "<MODE>")]
)
@@ -1269,6 +1246,7 @@
"TARGET_SIMD"
"<su>shll2 %0.<Vwtype>, %1.<Vtype>, 0"
[(set_attr "simd_type" "simd_shiftl_imm")
+ (set_attr "type" "neon_shift_imm_long")
(set_attr "simd_mode" "<MODE>")]
)
@@ -1312,6 +1290,7 @@
"TARGET_SIMD"
"<su>mlal\t%0.<Vwtype>, %2.<Vhalftype>, %4.<Vhalftype>"
[(set_attr "simd_type" "simd_mlal")
+ (set_attr "type" "neon_mla_<Vetype>_long")
(set_attr "simd_mode" "<MODE>")]
)
@@ -1329,6 +1308,7 @@
"TARGET_SIMD"
"<su>mlal2\t%0.<Vwtype>, %2.<Vtype>, %4.<Vtype>"
[(set_attr "simd_type" "simd_mlal")
+ (set_attr "type" "neon_mla_<Vetype>_long")
(set_attr "simd_mode" "<MODE>")]
)
@@ -1346,6 +1326,7 @@
"TARGET_SIMD"
"<su>mlsl\t%0.<Vwtype>, %2.<Vhalftype>, %4.<Vhalftype>"
[(set_attr "simd_type" "simd_mlal")
+ (set_attr "type" "neon_mla_<Vetype>_long")
(set_attr "simd_mode" "<MODE>")]
)
@@ -1363,6 +1344,7 @@
"TARGET_SIMD"
"<su>mlsl2\t%0.<Vwtype>, %2.<Vtype>, %4.<Vtype>"
[(set_attr "simd_type" "simd_mlal")
+ (set_attr "type" "neon_mla_<Vetype>_long")
(set_attr "simd_mode" "<MODE>")]
)
@@ -1378,6 +1360,7 @@
"TARGET_SIMD"
"<su>mlal\t%0.<Vwtype>, %1.<Vtype>, %2.<Vtype>"
[(set_attr "simd_type" "simd_mlal")
+ (set_attr "type" "neon_mla_<Vetype>_long")
(set_attr "simd_mode" "<MODE>")]
)
@@ -1393,6 +1376,7 @@
"TARGET_SIMD"
"<su>mlsl\t%0.<Vwtype>, %2.<Vtype>, %3.<Vtype>"
[(set_attr "simd_type" "simd_mlal")
+ (set_attr "type" "neon_mla_<Vetype>_long")
(set_attr "simd_mode" "<MODE>")]
)
@@ -1407,6 +1391,7 @@
"TARGET_SIMD"
"<su>mull\\t%0.<Vwtype>, %1.<Vhalftype>, %2.<Vhalftype>"
[(set_attr "simd_type" "simd_mull")
+ (set_attr "type" "neon_mul_<Vetype>_long")
(set_attr "simd_mode" "<MODE>")]
)
@@ -1435,6 +1420,7 @@
"TARGET_SIMD"
"<su>mull2\\t%0.<Vwtype>, %1.<Vtype>, %2.<Vtype>"
[(set_attr "simd_type" "simd_mull")
+ (set_attr "type" "neon_mul_<Vetype>_long")
(set_attr "simd_mode" "<MODE>")]
)
@@ -1485,6 +1471,7 @@
"TARGET_SIMD"
"fadd\\t%0.<Vtype>, %1.<Vtype>, %2.<Vtype>"
[(set_attr "simd_type" "simd_fadd")
+ (set_attr "type" "neon_fp_addsub_<Vetype><q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -1495,6 +1482,7 @@
"TARGET_SIMD"
"fsub\\t%0.<Vtype>, %1.<Vtype>, %2.<Vtype>"
[(set_attr "simd_type" "simd_fadd")
+ (set_attr "type" "neon_fp_addsub_<Vetype><q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -1505,6 +1493,7 @@
"TARGET_SIMD"
"fmul\\t%0.<Vtype>, %1.<Vtype>, %2.<Vtype>"
[(set_attr "simd_type" "simd_fmul")
+ (set_attr "type" "neon_fp_mul_<Vetype><q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -1515,6 +1504,7 @@
"TARGET_SIMD"
"fdiv\\t%0.<Vtype>, %1.<Vtype>, %2.<Vtype>"
[(set_attr "simd_type" "simd_fdiv")
+ (set_attr "type" "neon_fp_div_<Vetype><q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -1524,6 +1514,7 @@
"TARGET_SIMD"
"fneg\\t%0.<Vtype>, %1.<Vtype>"
[(set_attr "simd_type" "simd_fnegabs")
+ (set_attr "type" "neon_fp_neg_<Vetype><q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -1533,6 +1524,7 @@
"TARGET_SIMD"
"fabs\\t%0.<Vtype>, %1.<Vtype>"
[(set_attr "simd_type" "simd_fnegabs")
+ (set_attr "type" "neon_fp_abs_<Vetype><q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -1544,6 +1536,7 @@
"TARGET_SIMD"
"fmla\\t%0.<Vtype>, %1.<Vtype>, %2.<Vtype>"
[(set_attr "simd_type" "simd_fmla")
+ (set_attr "type" "neon_fp_mla_<Vetype><q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -1559,6 +1552,7 @@
"TARGET_SIMD"
"fmla\\t%0.<Vtype>, %3.<Vtype>, %1.<Vtype>[%2]"
[(set_attr "simd_type" "simd_fmla_elt")
+ (set_attr "type" "neon_fp_mla_<Vetype>_scalar<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -1574,6 +1568,7 @@
"TARGET_SIMD"
"fmla\\t%0.<Vtype>, %3.<Vtype>, %1.<Vtype>[%2]"
[(set_attr "simd_type" "simd_fmla_elt")
+ (set_attr "type" "neon_fp_mla_<Vetype>_scalar<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -1587,6 +1582,7 @@
"TARGET_SIMD"
"fmla\\t%0.2d, %2.2d, %1.2d[0]"
[(set_attr "simd_type" "simd_fmla_elt")
+ (set_attr "type" "neon_fp_mla_d_scalar_q")
(set_attr "simd_mode" "V2DF")]
)
@@ -1601,6 +1597,7 @@
"TARGET_SIMD"
"fmla\\t%0.2d, %3.2d, %1.2d[%2]"
[(set_attr "simd_type" "simd_fmla_elt")
+ (set_attr "type" "neon_fp_mla_d_scalar_q")
(set_attr "simd_mode" "V2DF")]
)
@@ -1614,6 +1611,7 @@
"TARGET_SIMD"
"fmls\\t%0.<Vtype>, %1.<Vtype>, %2.<Vtype>"
[(set_attr "simd_type" "simd_fmla")
+ (set_attr "type" "neon_fp_mla_<Vetype><q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -1630,6 +1628,7 @@
"TARGET_SIMD"
"fmls\\t%0.<Vtype>, %3.<Vtype>, %1.<Vtype>[%2]"
[(set_attr "simd_type" "simd_fmla_elt")
+ (set_attr "type" "neon_fp_mla_<Vetype>_scalar<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -1646,6 +1645,7 @@
"TARGET_SIMD"
"fmls\\t%0.<Vtype>, %3.<Vtype>, %1.<Vtype>[%2]"
[(set_attr "simd_type" "simd_fmla_elt")
+ (set_attr "type" "neon_fp_mla_<Vetype>_scalar<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -1660,6 +1660,7 @@
"TARGET_SIMD"
"fmls\\t%0.2d, %2.2d, %1.2d[0]"
[(set_attr "simd_type" "simd_fmla_elt")
+ (set_attr "type" "neon_fp_mla_d_scalar_q")
(set_attr "simd_mode" "V2DF")]
)
@@ -1675,6 +1676,7 @@
"TARGET_SIMD"
"fmls\\t%0.2d, %3.2d, %1.2d[%2]"
[(set_attr "simd_type" "simd_fmla_elt")
+ (set_attr "type" "neon_fp_mla_d_scalar_q")
(set_attr "simd_mode" "V2DF")]
)
@@ -1687,6 +1689,7 @@
"TARGET_SIMD"
"frint<frint_suffix>\\t%0.<Vtype>, %1.<Vtype>"
[(set_attr "simd_type" "simd_frint")
+ (set_attr "type" "neon_fp_round_<Vetype><q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -1700,6 +1703,7 @@
"TARGET_SIMD"
"fcvt<frint_suffix><su>\\t%0.<Vtype>, %1.<Vtype>"
[(set_attr "simd_type" "simd_fcvti")
+ (set_attr "type" "neon_fp_to_int_<Vetype><q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -1733,6 +1737,7 @@
"TARGET_SIMD"
"<su_optab>cvtf\\t%0.<Vtype>, %1.<Vtype>"
[(set_attr "simd_type" "simd_icvtf")
+ (set_attr "type" "neon_int_to_fp_<Vetype><q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -1752,6 +1757,7 @@
"TARGET_SIMD"
"fcvtl\\t%0.2d, %1.2s"
[(set_attr "simd_type" "simd_fcvtl")
+ (set_attr "type" "neon_fp_cvt_widen_s")
(set_attr "simd_mode" "V2DF")]
)
@@ -1762,6 +1768,7 @@
"TARGET_SIMD"
"fcvtl\\t%0.2d, %1.2s"
[(set_attr "simd_type" "simd_fcvtl")
+ (set_attr "type" "neon_fp_cvt_widen_s")
(set_attr "simd_mode" "V2DF")]
)
@@ -1775,6 +1782,7 @@
"TARGET_SIMD"
"fcvtl2\\t%0.2d, %1.4s"
[(set_attr "simd_type" "simd_fcvtl")
+ (set_attr "type" "neon_fp_cvt_widen_s")
(set_attr "simd_mode" "V2DF")]
)
@@ -1787,6 +1795,7 @@
"TARGET_SIMD"
"fcvtn\\t%0.2s, %1.2d"
[(set_attr "simd_type" "simd_fcvtl")
+ (set_attr "type" "neon_fp_cvt_narrow_d_q")
(set_attr "simd_mode" "V2SF")]
)
@@ -1799,6 +1808,7 @@
"TARGET_SIMD"
"fcvtn2\\t%0.4s, %2.2d"
[(set_attr "simd_type" "simd_fcvtl")
+ (set_attr "type" "neon_fp_cvt_narrow_d_q")
(set_attr "simd_mode" "V4SF")]
)
@@ -1846,6 +1856,7 @@
"TARGET_SIMD"
"fmls\\t%0.<Vtype>, %2.<Vtype>, %3.<Vtype>"
[(set_attr "simd_type" "simd_fmla")
+ (set_attr "type" "neon_fp_mla_<Vetype>_scalar<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -1870,6 +1881,7 @@
"TARGET_SIMD"
"f<maxmin>nm\\t%0.<Vtype>, %1.<Vtype>, %2.<Vtype>"
[(set_attr "simd_type" "simd_fminmax")
+ (set_attr "type" "neon_fp_minmax_<Vetype><q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -1881,6 +1893,7 @@
"TARGET_SIMD"
"<maxmin_uns_op>\\t%0.<Vtype>, %1.<Vtype>, %2.<Vtype>"
[(set_attr "simd_type" "simd_fminmax")
+ (set_attr "type" "neon_fp_minmax_<Vetype><q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -1893,6 +1906,7 @@
"TARGET_SIMD"
"addv\\t%<Vetype>0, %1.<Vtype>"
[(set_attr "simd_type" "simd_addv")
+ (set_attr "type" "neon_reduc_add<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -1903,6 +1917,7 @@
"TARGET_SIMD"
"addp\\t%d0, %1.2d"
[(set_attr "simd_type" "simd_addv")
+ (set_attr "type" "neon_reduc_add_q")
(set_attr "simd_mode" "V2DI")]
)
@@ -1913,6 +1928,7 @@
"TARGET_SIMD"
"addp\\t%0.2s, %1.2s, %1.2s"
[(set_attr "simd_type" "simd_addv")
+ (set_attr "type" "neon_reduc_add")
(set_attr "simd_mode" "V2SI")]
)
@@ -1923,6 +1939,7 @@
"TARGET_SIMD"
"faddp\\t%<Vetype>0, %1.<Vtype>"
[(set_attr "simd_type" "simd_fadd")
+ (set_attr "type" "neon_fp_reduc_add_<Vetype><q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -1933,6 +1950,7 @@
"TARGET_SIMD"
"faddp\\t%0.4s, %1.4s, %1.4s"
[(set_attr "simd_type" "simd_fadd")
+ (set_attr "type" "neon_fp_reduc_add_s_q")
(set_attr "simd_mode" "V4SF")]
)
@@ -1954,6 +1972,7 @@
"TARGET_SIMD"
"clz\\t%0.<Vtype>, %1.<Vtype>"
[(set_attr "simd_type" "simd_cls")
+ (set_attr "type" "neon_cls<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -1966,6 +1985,7 @@
"TARGET_SIMD"
"<maxmin_uns_op>v\\t%<Vetype>0, %1.<Vtype>"
[(set_attr "simd_type" "simd_minmaxv")
+ (set_attr "type" "neon_reduc_minmax<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -1976,6 +1996,7 @@
"TARGET_SIMD"
"<maxmin_uns_op>p\\t%d0, %1.2d"
[(set_attr "simd_type" "simd_minmaxv")
+ (set_attr "type" "neon_reduc_minmax_q")
(set_attr "simd_mode" "V2DI")]
)
@@ -1986,6 +2007,7 @@
"TARGET_SIMD"
"<maxmin_uns_op>p\\t%0.2s, %1.2s, %1.2s"
[(set_attr "simd_type" "simd_minmaxv")
+ (set_attr "type" "neon_reduc_minmax")
(set_attr "simd_mode" "V2SI")]
)
@@ -1996,6 +2018,7 @@
"TARGET_SIMD"
"<maxmin_uns_op>p\\t%<Vetype>0, %1.<Vtype>"
[(set_attr "simd_type" "simd_fminmaxv")
+ (set_attr "type" "neon_fp_reduc_minmax_<Vetype><q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -2006,6 +2029,7 @@
"TARGET_SIMD"
"<maxmin_uns_op>v\\t%s0, %1.4s"
[(set_attr "simd_type" "simd_fminmaxv")
+ (set_attr "type" "neon_fp_reduc_minmax_s_q")
(set_attr "simd_mode" "V4SF")]
)
@@ -2041,6 +2065,8 @@
bsl\\t%0.<Vbtype>, %2.<Vbtype>, %3.<Vbtype>
bit\\t%0.<Vbtype>, %2.<Vbtype>, %1.<Vbtype>
bif\\t%0.<Vbtype>, %3.<Vbtype>, %1.<Vbtype>"
+ [(set_attr "simd_mode" "<MODE>")
+ (set_attr "type" "neon_bsl<q>")]
)
(define_expand "aarch64_simd_bsl<mode>"
@@ -2406,6 +2432,7 @@
"TARGET_SIMD"
"smov\\t%<GPI:w>0, %1.<VDQQH:Vetype>[%2]"
[(set_attr "simd_type" "simd_movgp")
+ (set_attr "type" "neon_to_gp<q>")
(set_attr "simd_mode" "<VDQQH:MODE>")]
)
@@ -2418,6 +2445,7 @@
"TARGET_SIMD"
"umov\\t%w0, %1.<Vetype>[%2]"
[(set_attr "simd_type" "simd_movgp")
+ (set_attr "type" "neon_to_gp<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -2433,6 +2461,7 @@
umov\\t%<vwcore>0, %1.<Vetype>[%2]
dup\\t%<Vetype>0, %1.<Vetype>[%2]"
[(set_attr "simd_type" "simd_movgp, simd_dup")
+ (set_attr "type" "neon_to_gp<q>, neon_dup<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -2557,6 +2586,7 @@
"TARGET_SIMD"
"mov\\t%0.8b, %1.8b"
[(set_attr "simd_type" "simd_move")
+ (set_attr "type" "neon_move<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -2571,7 +2601,9 @@
{
aarch64_split_simd_combine (operands[0], operands[1], operands[2]);
DONE;
-})
+}
+[(set_attr "type" "multiple")]
+)
(define_expand "aarch64_simd_combine<mode>"
[(set (match_operand:<VDBL> 0 "register_operand" "=&w")
@@ -2582,11 +2614,13 @@
emit_insn (gen_move_lo_quad_<Vdbl> (operands[0], operands[1]));
emit_insn (gen_move_hi_quad_<Vdbl> (operands[0], operands[2]));
DONE;
- })
+ }
+[(set_attr "type" "multiple")]
+)
;; <su><addsub>l<q>.
-(define_insn "aarch64_<ANY_EXTEND:su><ADDSUB:optab>l2<mode>_internal"
+(define_insn "aarch64_<ANY_EXTEND:su><ADDSUB:optab>l<mode>_hi_internal"
[(set (match_operand:<VWIDE> 0 "register_operand" "=w")
(ADDSUB:<VWIDE> (ANY_EXTEND:<VWIDE> (vec_select:<VHALF>
(match_operand:VQW 1 "register_operand" "w")
@@ -2595,11 +2629,28 @@
(match_operand:VQW 2 "register_operand" "w")
(match_dup 3)))))]
"TARGET_SIMD"
- "<ANY_EXTEND:su><ADDSUB:optab>l2 %0.<Vwtype>, %1.<Vtype>, %2.<Vtype>"
+ "<ANY_EXTEND:su><ADDSUB:optab>l2\t%0.<Vwtype>, %1.<Vtype>, %2.<Vtype>"
+ [(set_attr "simd_type" "simd_addl")
+ (set_attr "type" "neon_<ADDSUB:optab>_long")
+ (set_attr "simd_mode" "<MODE>")]
+)
+
+(define_insn "aarch64_<ANY_EXTEND:su><ADDSUB:optab>l<mode>_lo_internal"
+ [(set (match_operand:<VWIDE> 0 "register_operand" "=w")
+ (ADDSUB:<VWIDE> (ANY_EXTEND:<VWIDE> (vec_select:<VHALF>
+ (match_operand:VQW 1 "register_operand" "w")
+ (match_operand:VQW 3 "vect_par_cnst_lo_half" "")))
+ (ANY_EXTEND:<VWIDE> (vec_select:<VHALF>
+ (match_operand:VQW 2 "register_operand" "w")
+ (match_dup 3)))))]
+ "TARGET_SIMD"
+ "<ANY_EXTEND:su><ADDSUB:optab>l\t%0.<Vwtype>, %1.<Vhalftype>, %2.<Vhalftype>"
[(set_attr "simd_type" "simd_addl")
+ (set_attr "type" "neon_<ADDSUB:optab>_long")
(set_attr "simd_mode" "<MODE>")]
)
+
(define_expand "aarch64_saddl2<mode>"
[(match_operand:<VWIDE> 0 "register_operand" "=w")
(match_operand:VQW 1 "register_operand" "w")
@@ -2607,8 +2658,8 @@
"TARGET_SIMD"
{
rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, true);
- emit_insn (gen_aarch64_saddl2<mode>_internal (operands[0], operands[1],
- operands[2], p));
+ emit_insn (gen_aarch64_saddl<mode>_hi_internal (operands[0], operands[1],
+ operands[2], p));
DONE;
})
@@ -2619,8 +2670,8 @@
"TARGET_SIMD"
{
rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, true);
- emit_insn (gen_aarch64_uaddl2<mode>_internal (operands[0], operands[1],
- operands[2], p));
+ emit_insn (gen_aarch64_uaddl<mode>_hi_internal (operands[0], operands[1],
+ operands[2], p));
DONE;
})
@@ -2631,7 +2682,7 @@
"TARGET_SIMD"
{
rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, true);
- emit_insn (gen_aarch64_ssubl2<mode>_internal (operands[0], operands[1],
+ emit_insn (gen_aarch64_ssubl<mode>_hi_internal (operands[0], operands[1],
operands[2], p));
DONE;
})
@@ -2643,7 +2694,7 @@
"TARGET_SIMD"
{
rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, true);
- emit_insn (gen_aarch64_usubl2<mode>_internal (operands[0], operands[1],
+ emit_insn (gen_aarch64_usubl<mode>_hi_internal (operands[0], operands[1],
operands[2], p));
DONE;
})
@@ -2657,6 +2708,7 @@
"TARGET_SIMD"
"<ANY_EXTEND:su><ADDSUB:optab>l %0.<Vwtype>, %1.<Vtype>, %2.<Vtype>"
[(set_attr "simd_type" "simd_addl")
+ (set_attr "type" "neon_<ADDSUB:optab>_long")
(set_attr "simd_mode" "<MODE>")]
)
@@ -2670,6 +2722,7 @@
"TARGET_SIMD"
"<ANY_EXTEND:su><ADDSUB:optab>w\\t%0.<Vwtype>, %1.<Vwtype>, %2.<Vtype>"
[(set_attr "simd_type" "simd_addl")
+ (set_attr "type" "neon_<ADDSUB:optab>_widen")
(set_attr "simd_mode" "<MODE>")]
)
@@ -2683,6 +2736,7 @@
"TARGET_SIMD"
"<ANY_EXTEND:su><ADDSUB:optab>w2\\t%0.<Vwtype>, %1.<Vwtype>, %2.<Vtype>"
[(set_attr "simd_type" "simd_addl")
+ (set_attr "type" "neon_<ADDSUB:optab>_widen")
(set_attr "simd_mode" "<MODE>")]
)
@@ -2745,6 +2799,7 @@
"TARGET_SIMD"
"<sur>h<addsub>\\t%0.<Vtype>, %1.<Vtype>, %2.<Vtype>"
[(set_attr "simd_type" "simd_add")
+ (set_attr "type" "neon_<addsub>_halve<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -2758,6 +2813,7 @@
"TARGET_SIMD"
"<sur><addsub>hn\\t%0.<Vntype>, %1.<Vtype>, %2.<Vtype>"
[(set_attr "simd_type" "simd_addn")
+ (set_attr "type" "neon_<addsub>_halve_narrow_q")
(set_attr "simd_mode" "<MODE>")]
)
@@ -2770,6 +2826,7 @@
"TARGET_SIMD"
"<sur><addsub>hn2\\t%0.<V2ntype>, %2.<Vtype>, %3.<Vtype>"
[(set_attr "simd_type" "simd_addn2")
+ (set_attr "type" "neon_<addsub>_halve_narrow_q")
(set_attr "simd_mode" "<MODE>")]
)
@@ -2783,6 +2840,7 @@
"TARGET_SIMD"
"pmul\\t%0.<Vtype>, %1.<Vtype>, %2.<Vtype>"
[(set_attr "simd_type" "simd_mul")
+ (set_attr "type" "neon_mul_<Vetype><q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -2795,6 +2853,7 @@
"TARGET_SIMD"
"<su_optab><optab>\\t%<v>0<Vmtype>, %<v>1<Vmtype>, %<v>2<Vmtype>"
[(set_attr "simd_type" "simd_add")
+ (set_attr "type" "neon_<optab><q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -2808,6 +2867,7 @@
"TARGET_SIMD"
"<sur>qadd\\t%<v>0<Vmtype>, %<v>2<Vmtype>"
[(set_attr "simd_type" "simd_sat_add")
+ (set_attr "type" "neon_qadd<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -2820,6 +2880,7 @@
"TARGET_SIMD"
"sqxtun\\t%<vn2>0<Vmntype>, %<v>1<Vmtype>"
[(set_attr "simd_type" "simd_sat_shiftn_imm")
+ (set_attr "type" "neon_sat_shift_imm_narrow_q")
(set_attr "simd_mode" "<MODE>")]
)
@@ -2832,6 +2893,7 @@
"TARGET_SIMD"
"<sur>qxtn\\t%<vn2>0<Vmntype>, %<v>1<Vmtype>"
[(set_attr "simd_type" "simd_sat_shiftn_imm")
+ (set_attr "type" "neon_sat_shift_imm_narrow_q")
(set_attr "simd_mode" "<MODE>")]
)
@@ -2844,6 +2906,7 @@
"TARGET_SIMD"
"s<optab>\\t%<v>0<Vmtype>, %<v>1<Vmtype>"
[(set_attr "simd_type" "simd_sat_negabs")
+ (set_attr "type" "neon_<optab><q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -2858,6 +2921,7 @@
"TARGET_SIMD"
"sq<r>dmulh\\t%<v>0<Vmtype>, %<v>1<Vmtype>, %<v>2<Vmtype>"
[(set_attr "simd_type" "simd_sat_mul")
+ (set_attr "type" "neon_sat_mul_<Vetype><q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -2876,6 +2940,7 @@
aarch64_simd_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<VCOND>mode));
return \"sq<r>dmulh\\t%0.<Vtype>, %1.<Vtype>, %2.<Vetype>[%3]\";"
[(set_attr "simd_type" "simd_sat_mul")
+ (set_attr "type" "neon_sat_mul_<Vetype>_scalar<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -2892,6 +2957,7 @@
aarch64_simd_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<VCONQ>mode));
return \"sq<r>dmulh\\t%0.<Vtype>, %1.<Vtype>, %2.<Vetype>[%3]\";"
[(set_attr "simd_type" "simd_sat_mul")
+ (set_attr "type" "neon_sat_mul_<Vetype>_scalar<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -2908,6 +2974,7 @@
aarch64_simd_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<VCONQ>mode));
return \"sq<r>dmulh\\t%<v>0, %<v>1, %2.<v>[%3]\";"
[(set_attr "simd_type" "simd_sat_mul")
+ (set_attr "type" "neon_sat_mul_<Vetype>_scalar<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -2927,6 +2994,7 @@
"TARGET_SIMD"
"sqdml<SBINQOPS:as>l\\t%<vw2>0<Vmwtype>, %<v>2<Vmtype>, %<v>3<Vmtype>"
[(set_attr "simd_type" "simd_sat_mlal")
+ (set_attr "type" "neon_sat_mla_<Vetype>_long")
(set_attr "simd_mode" "<MODE>")]
)
@@ -2950,6 +3018,7 @@
"TARGET_SIMD"
"sqdml<SBINQOPS:as>l\\t%<vw2>0<Vmwtype>, %<v>2<Vmtype>, %3.<Vetype>[%4]"
[(set_attr "simd_type" "simd_sat_mlal")
+ (set_attr "type" "neon_sat_mla_<Vetype>_scalar_long")
(set_attr "simd_mode" "<MODE>")]
)
@@ -2970,6 +3039,7 @@
"TARGET_SIMD"
"sqdml<SBINQOPS:as>l\\t%<vw2>0<Vmwtype>, %<v>2<Vmtype>, %3.<Vetype>[%4]"
[(set_attr "simd_type" "simd_sat_mlal")
+ (set_attr "type" "neon_sat_mla_<Vetype>_scalar_long")
(set_attr "simd_mode" "<MODE>")]
)
@@ -3050,6 +3120,7 @@
"TARGET_SIMD"
"sqdml<SBINQOPS:as>l\\t%<vw2>0<Vmwtype>, %<v>2<Vmtype>, %3.<Vetype>[0]"
[(set_attr "simd_type" "simd_sat_mlal")
+ (set_attr "type" "neon_sat_mla_<Vetype>_scalar_long")
(set_attr "simd_mode" "<MODE>")]
)
@@ -3073,6 +3144,7 @@
"TARGET_SIMD"
"sqdml<SBINQOPS:as>l2\\t%<vw2>0<Vmwtype>, %<v>2<Vmtype>, %<v>3<Vmtype>"
[(set_attr "simd_type" "simd_sat_mlal")
+ (set_attr "type" "neon_sat_mla_<Vetype>_scalar_long")
(set_attr "simd_mode" "<MODE>")]
)
@@ -3124,6 +3196,7 @@
"TARGET_SIMD"
"sqdml<SBINQOPS:as>l2\\t%<vw2>0<Vmwtype>, %<v>2<Vmtype>, %3.<Vetype>[%4]"
[(set_attr "simd_type" "simd_sat_mlal")
+ (set_attr "type" "neon_sat_mla_<Vetype>_scalar_long")
(set_attr "simd_mode" "<MODE>")]
)
@@ -3208,6 +3281,7 @@
"TARGET_SIMD"
"sqdml<SBINQOPS:as>l2\\t%<vw2>0<Vmwtype>, %<v>2<Vmtype>, %3.<Vetype>[0]"
[(set_attr "simd_type" "simd_sat_mlal")
+ (set_attr "type" "neon_sat_mla_<Vetype>_scalar_long")
(set_attr "simd_mode" "<MODE>")]
)
@@ -3253,6 +3327,7 @@
"TARGET_SIMD"
"sqdmull\\t%<vw2>0<Vmwtype>, %<v>1<Vmtype>, %<v>2<Vmtype>"
[(set_attr "simd_type" "simd_sat_mul")
+ (set_attr "type" "neon_sat_mul_<Vetype>_long")
(set_attr "simd_mode" "<MODE>")]
)
@@ -3274,6 +3349,7 @@
"TARGET_SIMD"
"sqdmull\\t%<vw2>0<Vmwtype>, %<v>1<Vmtype>, %2.<Vetype>[%3]"
[(set_attr "simd_type" "simd_sat_mul")
+ (set_attr "type" "neon_sat_mul_<Vetype>_scalar_long")
(set_attr "simd_mode" "<MODE>")]
)
@@ -3292,6 +3368,7 @@
"TARGET_SIMD"
"sqdmull\\t%<vw2>0<Vmwtype>, %<v>1<Vmtype>, %2.<Vetype>[%3]"
[(set_attr "simd_type" "simd_sat_mul")
+ (set_attr "type" "neon_sat_mul_<Vetype>_scalar_long")
(set_attr "simd_mode" "<MODE>")]
)
@@ -3337,6 +3414,7 @@
"TARGET_SIMD"
"sqdmull\\t%<vw2>0<Vmwtype>, %<v>1<Vmtype>, %2.<Vetype>[0]"
[(set_attr "simd_type" "simd_sat_mul")
+ (set_attr "type" "neon_sat_mul_<Vetype>_scalar_long")
(set_attr "simd_mode" "<MODE>")]
)
@@ -3361,6 +3439,7 @@
"TARGET_SIMD"
"sqdmull2\\t%<vw2>0<Vmwtype>, %<v>1<Vmtype>, %<v>2<Vmtype>"
[(set_attr "simd_type" "simd_sat_mul")
+ (set_attr "type" "neon_sat_mul_<Vetype>_scalar_long")
(set_attr "simd_mode" "<MODE>")]
)
@@ -3396,6 +3475,7 @@
"TARGET_SIMD"
"sqdmull2\\t%<vw2>0<Vmwtype>, %<v>1<Vmtype>, %2.<Vetype>[%3]"
[(set_attr "simd_type" "simd_sat_mul")
+ (set_attr "type" "neon_sat_mul_<Vetype>_scalar_long")
(set_attr "simd_mode" "<MODE>")]
)
@@ -3447,6 +3527,7 @@
"TARGET_SIMD"
"sqdmull2\\t%<vw2>0<Vmwtype>, %<v>1<Vmtype>, %2.<Vetype>[0]"
[(set_attr "simd_type" "simd_sat_mul")
+ (set_attr "type" "neon_sat_mul_<Vetype>_scalar_long")
(set_attr "simd_mode" "<MODE>")]
)
@@ -3473,6 +3554,7 @@
"TARGET_SIMD"
"<sur>shl\\t%<v>0<Vmtype>, %<v>1<Vmtype>, %<v>2<Vmtype>";
[(set_attr "simd_type" "simd_shift")
+ (set_attr "type" "neon_shift_reg<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -3488,6 +3570,7 @@
"TARGET_SIMD"
"<sur>q<r>shl\\t%<v>0<Vmtype>, %<v>1<Vmtype>, %<v>2<Vmtype>";
[(set_attr "simd_type" "simd_sat_shift")
+ (set_attr "type" "neon_sat_shift_reg<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -3510,6 +3593,7 @@
return \"<sur>shll\\t%0.<Vwtype>, %1.<Vtype>, %2\";
}"
[(set_attr "simd_type" "simd_shift_imm")
+ (set_attr "type" "neon_shift_imm_long")
(set_attr "simd_mode" "<MODE>")]
)
@@ -3532,6 +3616,7 @@
return \"<sur>shll2\\t%0.<Vwtype>, %1.<Vtype>, %2\";
}"
[(set_attr "simd_type" "simd_shift_imm")
+ (set_attr "type" "neon_shift_imm_long")
(set_attr "simd_mode" "<MODE>")]
)
@@ -3548,6 +3633,7 @@
aarch64_simd_const_bounds (operands[2], 1, bit_width + 1);
return \"<sur>shr\\t%<v>0<Vmtype>, %<v>1<Vmtype>, %2\";"
[(set_attr "simd_type" "simd_shift_imm")
+ (set_attr "type" "neon_sat_shift_imm<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -3565,6 +3651,7 @@
aarch64_simd_const_bounds (operands[3], 1, bit_width + 1);
return \"<sur>sra\\t%<v>0<Vmtype>, %<v>2<Vmtype>, %3\";"
[(set_attr "simd_type" "simd_shift_imm_acc")
+ (set_attr "type" "neon_shift_acc<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -3583,6 +3670,7 @@
bit_width - <VSLRI:offsetlr> + 1);
return \"s<lr>i\\t%<v>0<Vmtype>, %<v>2<Vmtype>, %3\";"
[(set_attr "simd_type" "simd_shift_imm")
+ (set_attr "type" "neon_shift_imm<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -3599,6 +3687,7 @@
aarch64_simd_const_bounds (operands[2], 0, bit_width);
return \"<sur>qshl<u>\\t%<v>0<Vmtype>, %<v>1<Vmtype>, %2\";"
[(set_attr "simd_type" "simd_sat_shift_imm")
+ (set_attr "type" "neon_sat_shift_imm<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -3616,6 +3705,7 @@
aarch64_simd_const_bounds (operands[2], 1, bit_width + 1);
return \"<sur>q<r>shr<u>n\\t%<vn2>0<Vmntype>, %<v>1<Vmtype>, %2\";"
[(set_attr "simd_type" "simd_sat_shiftn_imm")
+ (set_attr "type" "neon_sat_shift_imm_narrow_q")
(set_attr "simd_mode" "<MODE>")]
)
@@ -3636,6 +3726,7 @@
cm<n_optab>\t%<v>0<Vmtype>, %<v><cmp_1><Vmtype>, %<v><cmp_2><Vmtype>
cm<optab>\t%<v>0<Vmtype>, %<v>1<Vmtype>, #0"
[(set_attr "simd_type" "simd_cmp")
+ (set_attr "type" "neon_compare<q>, neon_compare_zero<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -3666,6 +3757,7 @@
DONE;
}
[(set_attr "simd_type" "simd_cmp")
+ (set_attr "type" "neon_compare, neon_compare_zero, multiple")
(set_attr "simd_mode" "DI")]
)
@@ -3681,6 +3773,7 @@
"TARGET_SIMD"
"cm<n_optab>\t%<v>0<Vmtype>, %<v><cmp_1><Vmtype>, %<v><cmp_2><Vmtype>"
[(set_attr "simd_type" "simd_cmp")
+ (set_attr "type" "neon_compare<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -3710,6 +3803,7 @@
DONE;
}
[(set_attr "simd_type" "simd_cmp")
+ (set_attr "type" "neon_compare, neon_compare_zero")
(set_attr "simd_mode" "DI")]
)
@@ -3726,6 +3820,7 @@
"TARGET_SIMD"
"cmtst\t%<v>0<Vmtype>, %<v>1<Vmtype>, %<v>2<Vmtype>"
[(set_attr "simd_type" "simd_cmp")
+ (set_attr "type" "neon_tst<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -3757,6 +3852,7 @@
DONE;
}
[(set_attr "simd_type" "simd_cmp")
+ (set_attr "type" "neon_tst")
(set_attr "simd_mode" "DI")]
)
@@ -3774,6 +3870,7 @@
fcm<n_optab>\t%<v>0<Vmtype>, %<v><cmp_1><Vmtype>, %<v><cmp_2><Vmtype>
fcm<optab>\t%<v>0<Vmtype>, %<v>1<Vmtype>, 0"
[(set_attr "simd_type" "simd_fcmp")
+ (set_attr "type" "neon_fp_compare_<Vetype><q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -3791,6 +3888,7 @@
"TARGET_SIMD"
"fac<n_optab>\t%<v>0<Vmtype>, %<v><cmp_1><Vmtype>, %<v><cmp_2><Vmtype>"
[(set_attr "simd_type" "simd_fcmp")
+ (set_attr "type" "neon_fp_compare_<Vetype><q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -3805,6 +3903,7 @@
"TARGET_SIMD"
"addp\t%<v>0<Vmtype>, %<v>1<Vmtype>, %<v>2<Vmtype>"
[(set_attr "simd_type" "simd_add")
+ (set_attr "type" "neon_reduc_add<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -3816,6 +3915,7 @@
"TARGET_SIMD"
"addp\t%d0, %1.2d"
[(set_attr "simd_type" "simd_add")
+ (set_attr "type" "neon_reduc_add")
(set_attr "simd_mode" "DI")]
)
@@ -3827,6 +3927,7 @@
"TARGET_SIMD"
"fsqrt\\t%0.<Vtype>, %1.<Vtype>"
[(set_attr "simd_type" "simd_fsqrt")
+ (set_attr "type" "neon_fp_sqrt_<Vetype><q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -3840,6 +3941,7 @@
"TARGET_SIMD"
"ld2\\t{%S0.<Vtype> - %T0.<Vtype>}, %1"
[(set_attr "simd_type" "simd_load2")
+ (set_attr "type" "neon_load2_2reg<q>")
(set_attr "simd_mode" "<MODE>")])
(define_insn "vec_store_lanesoi<mode>"
@@ -3850,6 +3952,7 @@
"TARGET_SIMD"
"st2\\t{%S1.<Vtype> - %T1.<Vtype>}, %0"
[(set_attr "simd_type" "simd_store2")
+ (set_attr "type" "neon_store2_2reg<q>")
(set_attr "simd_mode" "<MODE>")])
(define_insn "vec_load_lanesci<mode>"
@@ -3860,6 +3963,7 @@
"TARGET_SIMD"
"ld3\\t{%S0.<Vtype> - %U0.<Vtype>}, %1"
[(set_attr "simd_type" "simd_load3")
+ (set_attr "type" "neon_load3_3reg<q>")
(set_attr "simd_mode" "<MODE>")])
(define_insn "vec_store_lanesci<mode>"
@@ -3870,6 +3974,7 @@
"TARGET_SIMD"
"st3\\t{%S1.<Vtype> - %U1.<Vtype>}, %0"
[(set_attr "simd_type" "simd_store3")
+ (set_attr "type" "neon_store3_3reg<q>")
(set_attr "simd_mode" "<MODE>")])
(define_insn "vec_load_lanesxi<mode>"
@@ -3880,6 +3985,7 @@
"TARGET_SIMD"
"ld4\\t{%S0.<Vtype> - %V0.<Vtype>}, %1"
[(set_attr "simd_type" "simd_load4")
+ (set_attr "type" "neon_load4_4reg<q>")
(set_attr "simd_mode" "<MODE>")])
(define_insn "vec_store_lanesxi<mode>"
@@ -3890,6 +3996,7 @@
"TARGET_SIMD"
"st4\\t{%S1.<Vtype> - %V1.<Vtype>}, %0"
[(set_attr "simd_type" "simd_store4")
+ (set_attr "type" "neon_store4_4reg<q>")
(set_attr "simd_mode" "<MODE>")])
;; Reload patterns for AdvSIMD register list operands.
@@ -3923,6 +4030,8 @@
}
}
[(set_attr "simd_type" "simd_move,simd_store<nregs>,simd_load<nregs>")
+ (set_attr "type" "neon_move,neon_store<nregs>_<nregs>reg_q,\
+ neon_load<nregs>_<nregs>reg_q")
(set (attr "length") (symbol_ref "aarch64_simd_attr_length_move (insn)"))
(set_attr "simd_mode" "<MODE>")])
@@ -4007,6 +4116,7 @@
"TARGET_SIMD"
"ld2\\t{%S0.<Vtype> - %T0.<Vtype>}, %1"
[(set_attr "simd_type" "simd_load2")
+ (set_attr "type" "neon_load2_2reg<q>")
(set_attr "simd_mode" "<MODE>")])
(define_insn "aarch64_ld2<mode>_dreg"
@@ -4024,6 +4134,7 @@
"TARGET_SIMD"
"ld1\\t{%S0.1d - %T0.1d}, %1"
[(set_attr "simd_type" "simd_load2")
+ (set_attr "type" "neon_load1_2reg<q>")
(set_attr "simd_mode" "<MODE>")])
(define_insn "aarch64_ld3<mode>_dreg"
@@ -4046,6 +4157,7 @@
"TARGET_SIMD"
"ld3\\t{%S0.<Vtype> - %U0.<Vtype>}, %1"
[(set_attr "simd_type" "simd_load3")
+ (set_attr "type" "neon_load3_3reg<q>")
(set_attr "simd_mode" "<MODE>")])
(define_insn "aarch64_ld3<mode>_dreg"
@@ -4068,6 +4180,7 @@
"TARGET_SIMD"
"ld1\\t{%S0.1d - %U0.1d}, %1"
[(set_attr "simd_type" "simd_load3")
+ (set_attr "type" "neon_load1_3reg<q>")
(set_attr "simd_mode" "<MODE>")])
(define_insn "aarch64_ld4<mode>_dreg"
@@ -4095,6 +4208,7 @@
"TARGET_SIMD"
"ld4\\t{%S0.<Vtype> - %V0.<Vtype>}, %1"
[(set_attr "simd_type" "simd_load4")
+ (set_attr "type" "neon_load4_4reg<q>")
(set_attr "simd_mode" "<MODE>")])
(define_insn "aarch64_ld4<mode>_dreg"
@@ -4122,6 +4236,7 @@
"TARGET_SIMD"
"ld1\\t{%S0.1d - %V0.1d}, %1"
[(set_attr "simd_type" "simd_load4")
+ (set_attr "type" "neon_load1_4reg<q>")
(set_attr "simd_mode" "<MODE>")])
(define_expand "aarch64_ld<VSTRUCT:nregs><VDC:mode>"
@@ -4237,6 +4352,7 @@
"TARGET_SIMD"
"tbl\\t%0.<Vtype>, {%1.16b}, %2.<Vtype>"
[(set_attr "simd_type" "simd_tbl")
+ (set_attr "type" "neon_tbl1<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -4250,6 +4366,7 @@
"TARGET_SIMD"
"tbl\\t%0.16b, {%S1.16b - %T1.16b}, %2.16b"
[(set_attr "simd_type" "simd_tbl")
+ (set_attr "type" "neon_tbl2_q")
(set_attr "simd_mode" "V16QI")]
)
@@ -4265,7 +4382,9 @@
{
aarch64_split_combinev16qi (operands);
DONE;
-})
+}
+[(set_attr "type" "multiple")]
+)
(define_insn "aarch64_<PERMUTE:perm_insn><PERMUTE:perm_hilo><mode>"
[(set (match_operand:VALL 0 "register_operand" "=w")
@@ -4275,6 +4394,7 @@
"TARGET_SIMD"
"<PERMUTE:perm_insn><PERMUTE:perm_hilo>\\t%0.<Vtype>, %1.<Vtype>, %2.<Vtype>"
[(set_attr "simd_type" "simd_<PERMUTE:perm_insn>")
+ (set_attr "type" "neon_permute<q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -4286,6 +4406,7 @@
"TARGET_SIMD"
"st2\\t{%S1.<Vtype> - %T1.<Vtype>}, %0"
[(set_attr "simd_type" "simd_store2")
+ (set_attr "type" "neon_store2_2reg")
(set_attr "simd_mode" "<MODE>")])
(define_insn "aarch64_st2<mode>_dreg"
@@ -4296,6 +4417,7 @@
"TARGET_SIMD"
"st1\\t{%S1.1d - %T1.1d}, %0"
[(set_attr "simd_type" "simd_store2")
+ (set_attr "type" "neon_store1_2reg")
(set_attr "simd_mode" "<MODE>")])
(define_insn "aarch64_st3<mode>_dreg"
@@ -4306,6 +4428,7 @@
"TARGET_SIMD"
"st3\\t{%S1.<Vtype> - %U1.<Vtype>}, %0"
[(set_attr "simd_type" "simd_store3")
+ (set_attr "type" "neon_store3_3reg")
(set_attr "simd_mode" "<MODE>")])
(define_insn "aarch64_st3<mode>_dreg"
@@ -4316,6 +4439,7 @@
"TARGET_SIMD"
"st1\\t{%S1.1d - %U1.1d}, %0"
[(set_attr "simd_type" "simd_store3")
+ (set_attr "type" "neon_store1_3reg")
(set_attr "simd_mode" "<MODE>")])
(define_insn "aarch64_st4<mode>_dreg"
@@ -4326,6 +4450,7 @@
"TARGET_SIMD"
"st4\\t{%S1.<Vtype> - %V1.<Vtype>}, %0"
[(set_attr "simd_type" "simd_store4")
+ (set_attr "type" "neon_store4_4reg")
(set_attr "simd_mode" "<MODE>")])
(define_insn "aarch64_st4<mode>_dreg"
@@ -4336,6 +4461,7 @@
"TARGET_SIMD"
"st1\\t{%S1.1d - %V1.1d}, %0"
[(set_attr "simd_type" "simd_store4")
+ (set_attr "type" "neon_store1_4reg")
(set_attr "simd_mode" "<MODE>")])
(define_expand "aarch64_st<VSTRUCT:nregs><VDC:mode>"
@@ -4415,6 +4541,7 @@
"TARGET_SIMD"
"ld1r\\t{%0.<Vtype>}, %1"
[(set_attr "simd_type" "simd_load1r")
+ (set_attr "type" "neon_load1_all_lanes")
(set_attr "simd_mode" "<MODE>")])
(define_insn "aarch64_frecpe<mode>"
@@ -4424,6 +4551,7 @@
"TARGET_SIMD"
"frecpe\\t%0.<Vtype>, %1.<Vtype>"
[(set_attr "simd_type" "simd_frecpe")
+ (set_attr "type" "neon_fp_recpe_<Vetype><q>")
(set_attr "simd_mode" "<MODE>")]
)
@@ -4434,6 +4562,7 @@
"TARGET_SIMD"
"frecp<FRECP:frecp_suffix>\\t%<s>0, %<s>1"
[(set_attr "simd_type" "simd_frecp<FRECP:frecp_suffix>")
+ (set_attr "type" "neon_fp_recp<FRECP:frecp_suffix>_<GPF:Vetype><GPF:q>")
(set_attr "mode" "<MODE>")]
)
@@ -4445,6 +4574,7 @@
"TARGET_SIMD"
"frecps\\t%<v>0<Vmtype>, %<v>1<Vmtype>, %<v>2<Vmtype>"
[(set_attr "simd_type" "simd_frecps")
+ (set_attr "type" "neon_fp_recps_<Vetype><q>")
(set_attr "simd_mode" "<MODE>")]
)
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index e8ae20ad3d2..8458cac34f2 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -109,6 +109,7 @@ enum aarch64_code_model aarch64_cmodel;
#define TARGET_HAVE_TLS 1
#endif
+static bool aarch64_lra_p (void);
static bool aarch64_composite_type_p (const_tree, enum machine_mode);
static bool aarch64_vfp_is_call_or_return_candidate (enum machine_mode,
const_tree,
@@ -2065,9 +2066,9 @@ aarch64_expand_prologue (void)
emit_insn (gen_add2_insn (stack_pointer_rtx, op0));
aarch64_set_frame_expr (gen_rtx_SET
(Pmode, stack_pointer_rtx,
- gen_rtx_PLUS (Pmode,
- stack_pointer_rtx,
- GEN_INT (-frame_size))));
+ plus_constant (Pmode,
+ stack_pointer_rtx,
+ -frame_size)));
}
else if (frame_size > 0)
{
@@ -2151,9 +2152,9 @@ aarch64_expand_prologue (void)
GEN_INT (fp_offset)));
aarch64_set_frame_expr (gen_rtx_SET
(Pmode, hard_frame_pointer_rtx,
- gen_rtx_PLUS (Pmode,
- stack_pointer_rtx,
- GEN_INT (fp_offset))));
+ plus_constant (Pmode,
+ stack_pointer_rtx,
+ fp_offset)));
RTX_FRAME_RELATED_P (insn) = 1;
insn = emit_insn (gen_stack_tie (stack_pointer_rtx,
hard_frame_pointer_rtx));
@@ -2349,9 +2350,9 @@ aarch64_expand_epilogue (bool for_sibcall)
emit_insn (gen_add2_insn (stack_pointer_rtx, op0));
aarch64_set_frame_expr (gen_rtx_SET
(Pmode, stack_pointer_rtx,
- gen_rtx_PLUS (Pmode,
- stack_pointer_rtx,
- GEN_INT (frame_size))));
+ plus_constant (Pmode,
+ stack_pointer_rtx,
+ frame_size)));
}
else if (frame_size > 0)
{
@@ -2373,10 +2374,10 @@ aarch64_expand_epilogue (bool for_sibcall)
}
}
- aarch64_set_frame_expr (gen_rtx_SET (Pmode, stack_pointer_rtx,
- gen_rtx_PLUS (Pmode,
- stack_pointer_rtx,
- GEN_INT (offset))));
+ aarch64_set_frame_expr (gen_rtx_SET (Pmode, stack_pointer_rtx,
+ plus_constant (Pmode,
+ stack_pointer_rtx,
+ offset)));
}
emit_use (gen_rtx_REG (DImode, LR_REGNUM));
@@ -3439,6 +3440,32 @@ aarch64_print_operand (FILE *f, rtx x, char code)
{
switch (code)
{
+ /* An integer or symbol address without a preceding # sign. */
+ case 'c':
+ switch (GET_CODE (x))
+ {
+ case CONST_INT:
+ fprintf (f, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
+ break;
+
+ case SYMBOL_REF:
+ output_addr_const (f, x);
+ break;
+
+ case CONST:
+ if (GET_CODE (XEXP (x, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF)
+ {
+ output_addr_const (f, x);
+ break;
+ }
+ /* Fall through. */
+
+ default:
+ output_operand_lossage ("Unsupported operand for code '%c'", code);
+ }
+ break;
+
case 'e':
/* Print the sign/zero-extend size as a character 8->b, 16->h, 32->w. */
{
@@ -3857,13 +3884,6 @@ aarch64_print_operand_address (FILE *f, rtx x)
output_addr_const (f, x);
}
-void
-aarch64_function_profiler (FILE *f ATTRIBUTE_UNUSED,
- int labelno ATTRIBUTE_UNUSED)
-{
- sorry ("function profiling");
-}
-
bool
aarch64_label_mentioned_p (rtx x)
{
@@ -3910,7 +3930,7 @@ aarch64_regno_regclass (unsigned regno)
if (regno == FRAME_POINTER_REGNUM
|| regno == ARG_POINTER_REGNUM)
- return CORE_REGS;
+ return POINTER_REGS;
if (FP_REGNUM_P (regno))
return FP_LO_REGNUM_P (regno) ? FP_LO_REGS : FP_REGS;
@@ -4013,7 +4033,11 @@ aarch64_legitimize_reload_address (rtx *x_p,
cst = force_const_mem (xmode, cst);
/* Reload high part into base reg, leaving the low part
- in the mem instruction. */
+ in the mem instruction.
+ Note that replacing this gen_rtx_PLUS with plus_constant is
+ wrong in this case because we rely on the
+ (plus (plus reg c1) c2) structure being preserved so that
+ XEXP (*p, 0) in push_reload below uses the correct term. */
x = gen_rtx_PLUS (xmode,
gen_rtx_PLUS (xmode, XEXP (x, 0), cst),
GEN_INT (low));
@@ -4034,20 +4058,6 @@ aarch64_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x,
enum machine_mode mode,
secondary_reload_info *sri)
{
- /* Address expressions of the form PLUS (SP, large_offset) need two
- scratch registers, one for the constant, and one for holding a
- copy of SP, since SP cannot be used on the RHS of an add-reg
- instruction. */
- if (mode == DImode
- && GET_CODE (x) == PLUS
- && XEXP (x, 0) == stack_pointer_rtx
- && CONST_INT_P (XEXP (x, 1))
- && !aarch64_uimm12_shift (INTVAL (XEXP (x, 1))))
- {
- sri->icode = CODE_FOR_reload_sp_immediate;
- return NO_REGS;
- }
-
/* Without the TARGET_SIMD instructions we cannot move a Q register
to a Q register directly. We need a scratch. */
if (REG_P (x) && (mode == TFmode || mode == TImode) && mode == GET_MODE (x)
@@ -4239,15 +4249,42 @@ aarch64_class_max_nregs (reg_class_t regclass, enum machine_mode mode)
static reg_class_t
aarch64_preferred_reload_class (rtx x, reg_class_t regclass)
{
- if (regclass == POINTER_REGS || regclass == STACK_REG)
+ if (regclass == POINTER_REGS)
return GENERAL_REGS;
+ if (regclass == STACK_REG)
+ {
+ if (REG_P(x)
+ && reg_class_subset_p (REGNO_REG_CLASS (REGNO (x)), POINTER_REGS))
+ return regclass;
+
+ return NO_REGS;
+ }
+
/* If it's an integer immediate that MOVI can't handle, then
FP_REGS is not an option, so we return NO_REGS instead. */
if (CONST_INT_P (x) && reg_class_subset_p (regclass, FP_REGS)
&& !aarch64_simd_imm_scalar_p (x, GET_MODE (x)))
return NO_REGS;
+ /* Register eliminiation can result in a request for
+ SP+constant->FP_REGS. We cannot support such operations which
+ use SP as source and an FP_REG as destination, so reject out
+ right now. */
+ if (! reg_class_subset_p (regclass, GENERAL_REGS) && GET_CODE (x) == PLUS)
+ {
+ rtx lhs = XEXP (x, 0);
+
+ /* Look through a possible SUBREG introduced by ILP32. */
+ if (GET_CODE (lhs) == SUBREG)
+ lhs = SUBREG_REG (lhs);
+
+ gcc_assert (REG_P (lhs));
+ gcc_assert (reg_class_subset_p (REGNO_REG_CLASS (REGNO (lhs)),
+ POINTER_REGS));
+ return NO_REGS;
+ }
+
return regclass;
}
@@ -4296,7 +4333,7 @@ aarch64_output_casesi (rtx *operands)
{
char buf[100];
char label[100];
- rtx diff_vec = PATTERN (next_active_insn (operands[2]));
+ rtx diff_vec = PATTERN (NEXT_INSN (operands[2]));
int index;
static const char *const patterns[4][2] =
{
@@ -6092,6 +6129,13 @@ aapcs_vfp_sub_candidate (const_tree type, enum machine_mode *modep)
return -1;
}
+/* Return true if we use LRA instead of reload pass. */
+static bool
+aarch64_lra_p (void)
+{
+ return aarch64_lra_flag;
+}
+
/* Return TRUE if the type, as described by TYPE and MODE, is a composite
type as described in AAPCS64 \S 4.3. This includes aggregate, union and
array types. The C99 floating-point complex types are also considered
@@ -7162,10 +7206,10 @@ aarch64_emit_store_exclusive (enum machine_mode mode, rtx bval,
static void
aarch64_emit_unlikely_jump (rtx insn)
{
- rtx very_unlikely = GEN_INT (REG_BR_PROB_BASE / 100 - 1);
+ int very_unlikely = REG_BR_PROB_BASE / 100 - 1;
insn = emit_jump_insn (insn);
- add_reg_note (insn, REG_BR_PROB, very_unlikely);
+ add_int_reg_note (insn, REG_BR_PROB, very_unlikely);
}
/* Expand a compare and swap pattern. */
@@ -8268,6 +8312,9 @@ aarch64_vectorize_vec_perm_const_ok (enum machine_mode vmode,
#undef TARGET_LIBGCC_CMP_RETURN_MODE
#define TARGET_LIBGCC_CMP_RETURN_MODE aarch64_libgcc_cmp_return_mode
+#undef TARGET_LRA_P
+#define TARGET_LRA_P aarch64_lra_p
+
#undef TARGET_MANGLE_TYPE
#define TARGET_MANGLE_TYPE aarch64_mangle_type
diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
index d8012f88049..7a80e96385f 100644
--- a/gcc/config/aarch64/aarch64.h
+++ b/gcc/config/aarch64/aarch64.h
@@ -739,7 +739,7 @@ do { \
: reverse_condition (CODE))
#define CLZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) \
- ((VALUE) = ((MODE) == SImode ? 32 : 64), 2)
+ ((VALUE) = GET_MODE_UNIT_BITSIZE (MODE))
#define CTZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) \
((VALUE) = ((MODE) == SImode ? 32 : 64), 2)
@@ -783,8 +783,22 @@ do { \
#define PRINT_OPERAND_ADDRESS(STREAM, X) \
aarch64_print_operand_address (STREAM, X)
-#define FUNCTION_PROFILER(STREAM, LABELNO) \
- aarch64_function_profiler (STREAM, LABELNO)
+#define MCOUNT_NAME "_mcount"
+
+#define NO_PROFILE_COUNTERS 1
+
+/* Emit rtl for profiling. Output assembler code to FILE
+ to call "_mcount" for profiling a function entry. */
+#define PROFILE_HOOK(LABEL) \
+{ \
+ rtx fun,lr; \
+ lr = get_hard_reg_initial_val (Pmode, LR_REGNUM); \
+ fun = gen_rtx_SYMBOL_REF (Pmode, MCOUNT_NAME); \
+ emit_library_call (fun, LCT_NORMAL, VOIDmode, 1, lr, Pmode); \
+}
+
+/* All the work done in PROFILE_HOOK, but still required. */
+#define FUNCTION_PROFILER(STREAM, LABELNO) do { } while (0)
/* For some reason, the Linux headers think they know how to define
these macros. They don't!!! */
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index 797c9f422c4..758be47420e 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -789,7 +789,7 @@
case 8:
return "dup\t%0.<Vallxd>, %w1";
case 9:
- return "dup\t%0, %1.<v>[0]";
+ return "dup\t%<Vetype>0, %1.<v>[0]";
default:
gcc_unreachable ();
}
@@ -1033,7 +1033,7 @@
stp\\t%1, %H1, %0"
[(set_attr "v8type" "logic,move2,fmovi2f,fmovf2i,fconst,fconst,fpsimd_load,fpsimd_store,fpsimd_load2,fpsimd_store2")
(set_attr "type" "logic_reg,multiple,f_mcr,f_mrc,fconstd,fconstd,\
- f_loadd,f_stored,neon_ldm_2,neon_stm_2")
+ f_loadd,f_stored,neon_load1_2reg,neon_store1_2reg")
(set_attr "mode" "DF,DF,DF,DF,DF,DF,TF,TF,DF,DF")
(set_attr "length" "4,8,8,8,4,4,4,4,4,4")
(set_attr "fp" "*,*,yes,yes,*,yes,yes,yes,*,*")
@@ -1098,7 +1098,7 @@
GET_MODE_SIZE (<MODE>mode)))"
"ldp\\t%<w>0, %<w>2, %1"
[(set_attr "v8type" "fpsimd_load2")
- (set_attr "type" "neon_ldm_2")
+ (set_attr "type" "neon_load1_2reg<q>")
(set_attr "mode" "<MODE>")]
)
@@ -1115,7 +1115,7 @@
GET_MODE_SIZE (<MODE>mode)))"
"stp\\t%<w>1, %<w>3, %0"
[(set_attr "v8type" "fpsimd_store2")
- (set_attr "type" "neon_stm_2")
+ (set_attr "type" "neon_store1_2reg<q>")
(set_attr "mode" "<MODE>")]
)
@@ -1365,7 +1365,7 @@
(plus:GPI (mult:GPI
(match_operand:GPI 1 "register_operand" "r")
(match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))
- (match_operand:GPI 3 "register_operand" "rk"))
+ (match_operand:GPI 3 "register_operand" "r"))
(const_int 0)))
(set (match_operand:GPI 0 "register_operand" "=r")
(plus:GPI (mult:GPI (match_dup 1) (match_dup 2))
@@ -1380,7 +1380,7 @@
(define_insn "*subs_mul_imm_<mode>"
[(set (reg:CC_NZ CC_REGNUM)
(compare:CC_NZ
- (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
+ (minus:GPI (match_operand:GPI 1 "register_operand" "r")
(mult:GPI
(match_operand:GPI 2 "register_operand" "r")
(match_operand:QI 3 "aarch64_pwr_2_<mode>" "n")))
@@ -1500,7 +1500,7 @@
)
(define_insn "*add_<shift>_<mode>"
- [(set (match_operand:GPI 0 "register_operand" "=rk")
+ [(set (match_operand:GPI 0 "register_operand" "=r")
(plus:GPI (ASHIFT:GPI (match_operand:GPI 1 "register_operand" "r")
(match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
(match_operand:GPI 3 "register_operand" "r")))]
@@ -1513,7 +1513,7 @@
;; zero_extend version of above
(define_insn "*add_<shift>_si_uxtw"
- [(set (match_operand:DI 0 "register_operand" "=rk")
+ [(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI
(plus:SI (ASHIFT:SI (match_operand:SI 1 "register_operand" "r")
(match_operand:QI 2 "aarch64_shift_imm_si" "n"))
@@ -1526,7 +1526,7 @@
)
(define_insn "*add_mul_imm_<mode>"
- [(set (match_operand:GPI 0 "register_operand" "=rk")
+ [(set (match_operand:GPI 0 "register_operand" "=r")
(plus:GPI (mult:GPI (match_operand:GPI 1 "register_operand" "r")
(match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))
(match_operand:GPI 3 "register_operand" "r")))]
@@ -1873,7 +1873,7 @@
)
(define_insn "*sub_<shift>_<mode>"
- [(set (match_operand:GPI 0 "register_operand" "=rk")
+ [(set (match_operand:GPI 0 "register_operand" "=r")
(minus:GPI (match_operand:GPI 3 "register_operand" "r")
(ASHIFT:GPI
(match_operand:GPI 1 "register_operand" "r")
@@ -1887,7 +1887,7 @@
;; zero_extend version of above
(define_insn "*sub_<shift>_si_uxtw"
- [(set (match_operand:DI 0 "register_operand" "=rk")
+ [(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI
(minus:SI (match_operand:SI 3 "register_operand" "r")
(ASHIFT:SI
@@ -1901,7 +1901,7 @@
)
(define_insn "*sub_mul_imm_<mode>"
- [(set (match_operand:GPI 0 "register_operand" "=rk")
+ [(set (match_operand:GPI 0 "register_operand" "=r")
(minus:GPI (match_operand:GPI 3 "register_operand" "r")
(mult:GPI
(match_operand:GPI 1 "register_operand" "r")
@@ -1915,7 +1915,7 @@
;; zero_extend version of above
(define_insn "*sub_mul_imm_si_uxtw"
- [(set (match_operand:DI 0 "register_operand" "=rk")
+ [(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI
(minus:SI (match_operand:SI 3 "register_operand" "r")
(mult:SI
@@ -3955,38 +3955,6 @@
;; Reload support
;; -------------------------------------------------------------------
-;; Reload SP+imm where imm cannot be handled by a single ADD instruction.
-;; Must load imm into a scratch register and copy SP to the dest reg before
-;; adding, since SP cannot be used as a source register in an ADD
-;; instruction.
-(define_expand "reload_sp_immediate"
- [(parallel [(set (match_operand:DI 0 "register_operand" "=r")
- (match_operand:DI 1 "" ""))
- (clobber (match_operand:TI 2 "register_operand" "=&r"))])]
- ""
- {
- rtx sp = XEXP (operands[1], 0);
- rtx val = XEXP (operands[1], 1);
- unsigned regno = REGNO (operands[2]);
- rtx scratch = operands[1];
- gcc_assert (GET_CODE (operands[1]) == PLUS);
- gcc_assert (sp == stack_pointer_rtx);
- gcc_assert (CONST_INT_P (val));
-
- /* It is possible that one of the registers we got for operands[2]
- might coincide with that of operands[0] (which is why we made
- it TImode). Pick the other one to use as our scratch. */
- if (regno == REGNO (operands[0]))
- regno++;
- scratch = gen_rtx_REG (DImode, regno);
-
- emit_move_insn (scratch, val);
- emit_move_insn (operands[0], sp);
- emit_insn (gen_adddi3 (operands[0], operands[0], scratch));
- DONE;
- }
-)
-
(define_expand "aarch64_reload_mov<mode>"
[(set (match_operand:TX 0 "register_operand" "=w")
(match_operand:TX 1 "register_operand" "w"))
diff --git a/gcc/config/aarch64/aarch64.opt b/gcc/config/aarch64/aarch64.opt
index 8ff6ca12592..3b3e6c3b94d 100644
--- a/gcc/config/aarch64/aarch64.opt
+++ b/gcc/config/aarch64/aarch64.opt
@@ -103,6 +103,10 @@ mabi=
Target RejectNegative Joined Enum(aarch64_abi) Var(aarch64_abi) Init(AARCH64_ABI_DEFAULT)
-mabi=ABI Generate code that conforms to the specified ABI
+mlra
+Target Report Var(aarch64_lra_flag) Init(1) Save
+Use LRA instead of reload (transitional)
+
Enum
Name(aarch64_abi) Type(int)
Known AArch64 ABIs (for use with the -mabi= option):
diff --git a/gcc/config/aarch64/arm_neon.h b/gcc/config/aarch64/arm_neon.h
index cb5860206a1..c33e4a963b7 100644
--- a/gcc/config/aarch64/arm_neon.h
+++ b/gcc/config/aarch64/arm_neon.h
@@ -634,6 +634,12 @@ vadd_f32 (float32x2_t __a, float32x2_t __b)
return __a + __b;
}
+__extension__ static __inline float64x1_t __attribute__ ((__always_inline__))
+vadd_f64 (float64x1_t __a, float64x1_t __b)
+{
+ return __a + __b;
+}
+
__extension__ static __inline uint8x8_t __attribute__ ((__always_inline__))
vadd_u8 (uint8x8_t __a, uint8x8_t __b)
{
@@ -1204,6 +1210,12 @@ vdiv_f32 (float32x2_t __a, float32x2_t __b)
return __a / __b;
}
+__extension__ static __inline float64x1_t __attribute__ ((__always_inline__))
+vdiv_f64 (float64x1_t __a, float64x1_t __b)
+{
+ return __a / __b;
+}
+
__extension__ static __inline float32x4_t __attribute__ ((__always_inline__))
vdivq_f32 (float32x4_t __a, float32x4_t __b)
{
@@ -1824,6 +1836,12 @@ vsub_f32 (float32x2_t __a, float32x2_t __b)
return __a - __b;
}
+__extension__ static __inline float64x1_t __attribute__ ((__always_inline__))
+vsub_f64 (float64x1_t __a, float64x1_t __b)
+{
+ return __a - __b;
+}
+
__extension__ static __inline uint8x8_t __attribute__ ((__always_inline__))
vsub_u8 (uint8x8_t __a, uint8x8_t __b)
{
@@ -5140,138 +5158,6 @@ vclsq_s32 (int32x4_t a)
return result;
}
-__extension__ static __inline int8x8_t __attribute__ ((__always_inline__))
-vclz_s8 (int8x8_t a)
-{
- int8x8_t result;
- __asm__ ("clz %0.8b,%1.8b"
- : "=w"(result)
- : "w"(a)
- : /* No clobbers */);
- return result;
-}
-
-__extension__ static __inline int16x4_t __attribute__ ((__always_inline__))
-vclz_s16 (int16x4_t a)
-{
- int16x4_t result;
- __asm__ ("clz %0.4h,%1.4h"
- : "=w"(result)
- : "w"(a)
- : /* No clobbers */);
- return result;
-}
-
-__extension__ static __inline int32x2_t __attribute__ ((__always_inline__))
-vclz_s32 (int32x2_t a)
-{
- int32x2_t result;
- __asm__ ("clz %0.2s,%1.2s"
- : "=w"(result)
- : "w"(a)
- : /* No clobbers */);
- return result;
-}
-
-__extension__ static __inline uint8x8_t __attribute__ ((__always_inline__))
-vclz_u8 (uint8x8_t a)
-{
- uint8x8_t result;
- __asm__ ("clz %0.8b,%1.8b"
- : "=w"(result)
- : "w"(a)
- : /* No clobbers */);
- return result;
-}
-
-__extension__ static __inline uint16x4_t __attribute__ ((__always_inline__))
-vclz_u16 (uint16x4_t a)
-{
- uint16x4_t result;
- __asm__ ("clz %0.4h,%1.4h"
- : "=w"(result)
- : "w"(a)
- : /* No clobbers */);
- return result;
-}
-
-__extension__ static __inline uint32x2_t __attribute__ ((__always_inline__))
-vclz_u32 (uint32x2_t a)
-{
- uint32x2_t result;
- __asm__ ("clz %0.2s,%1.2s"
- : "=w"(result)
- : "w"(a)
- : /* No clobbers */);
- return result;
-}
-
-__extension__ static __inline int8x16_t __attribute__ ((__always_inline__))
-vclzq_s8 (int8x16_t a)
-{
- int8x16_t result;
- __asm__ ("clz %0.16b,%1.16b"
- : "=w"(result)
- : "w"(a)
- : /* No clobbers */);
- return result;
-}
-
-__extension__ static __inline int16x8_t __attribute__ ((__always_inline__))
-vclzq_s16 (int16x8_t a)
-{
- int16x8_t result;
- __asm__ ("clz %0.8h,%1.8h"
- : "=w"(result)
- : "w"(a)
- : /* No clobbers */);
- return result;
-}
-
-__extension__ static __inline int32x4_t __attribute__ ((__always_inline__))
-vclzq_s32 (int32x4_t a)
-{
- int32x4_t result;
- __asm__ ("clz %0.4s,%1.4s"
- : "=w"(result)
- : "w"(a)
- : /* No clobbers */);
- return result;
-}
-
-__extension__ static __inline uint8x16_t __attribute__ ((__always_inline__))
-vclzq_u8 (uint8x16_t a)
-{
- uint8x16_t result;
- __asm__ ("clz %0.16b,%1.16b"
- : "=w"(result)
- : "w"(a)
- : /* No clobbers */);
- return result;
-}
-
-__extension__ static __inline uint16x8_t __attribute__ ((__always_inline__))
-vclzq_u16 (uint16x8_t a)
-{
- uint16x8_t result;
- __asm__ ("clz %0.8h,%1.8h"
- : "=w"(result)
- : "w"(a)
- : /* No clobbers */);
- return result;
-}
-
-__extension__ static __inline uint32x4_t __attribute__ ((__always_inline__))
-vclzq_u32 (uint32x4_t a)
-{
- uint32x4_t result;
- __asm__ ("clz %0.4s,%1.4s"
- : "=w"(result)
- : "w"(a)
- : /* No clobbers */);
- return result;
-}
-
__extension__ static __inline poly8x8_t __attribute__ ((__always_inline__))
vcnt_p8 (poly8x8_t a)
{
@@ -5556,7 +5442,7 @@ static float32x2_t vdup_n_f32 (float32_t);
__extension__ \
({ \
int64_t a_ = (a); \
- int64_t result; \
+ float64_t result; \
__asm__ ("scvtf %d0,%d1,%2" \
: "=w"(result) \
: "w"(a_), "i"(b) \
@@ -5568,7 +5454,7 @@ static float32x2_t vdup_n_f32 (float32_t);
__extension__ \
({ \
uint64_t a_ = (a); \
- uint64_t result; \
+ float64_t result; \
__asm__ ("ucvtf %d0,%d1,%2" \
: "=w"(result) \
: "w"(a_), "i"(b) \
@@ -5580,7 +5466,7 @@ static float32x2_t vdup_n_f32 (float32_t);
__extension__ \
({ \
float64_t a_ = (a); \
- float64_t result; \
+ int64_t result; \
__asm__ ("fcvtzs %d0,%d1,%2" \
: "=w"(result) \
: "w"(a_), "i"(b) \
@@ -5592,7 +5478,7 @@ static float32x2_t vdup_n_f32 (float32_t);
__extension__ \
({ \
float64_t a_ = (a); \
- float64_t result; \
+ uint64_t result; \
__asm__ ("fcvtzu %d0,%d1,%2" \
: "=w"(result) \
: "w"(a_), "i"(b) \
@@ -5700,7 +5586,7 @@ static float32x2_t vdup_n_f32 (float32_t);
__extension__ \
({ \
int32_t a_ = (a); \
- int32_t result; \
+ float32_t result; \
__asm__ ("scvtf %s0,%s1,%2" \
: "=w"(result) \
: "w"(a_), "i"(b) \
@@ -5712,7 +5598,7 @@ static float32x2_t vdup_n_f32 (float32_t);
__extension__ \
({ \
uint32_t a_ = (a); \
- uint32_t result; \
+ float32_t result; \
__asm__ ("ucvtf %s0,%s1,%2" \
: "=w"(result) \
: "w"(a_), "i"(b) \
@@ -5724,7 +5610,7 @@ static float32x2_t vdup_n_f32 (float32_t);
__extension__ \
({ \
float32_t a_ = (a); \
- float32_t result; \
+ int32_t result; \
__asm__ ("fcvtzs %s0,%s1,%2" \
: "=w"(result) \
: "w"(a_), "i"(b) \
@@ -5736,7 +5622,7 @@ static float32x2_t vdup_n_f32 (float32_t);
__extension__ \
({ \
float32_t a_ = (a); \
- float32_t result; \
+ uint32_t result; \
__asm__ ("fcvtzu %s0,%s1,%2" \
: "=w"(result) \
: "w"(a_), "i"(b) \
@@ -9785,115 +9671,6 @@ vmvnq_u32 (uint32x4_t a)
return result;
}
-__extension__ static __inline float32x2_t __attribute__ ((__always_inline__))
-vneg_f32 (float32x2_t a)
-{
- float32x2_t result;
- __asm__ ("fneg %0.2s,%1.2s"
- : "=w"(result)
- : "w"(a)
- : /* No clobbers */);
- return result;
-}
-
-__extension__ static __inline int8x8_t __attribute__ ((__always_inline__))
-vneg_s8 (int8x8_t a)
-{
- int8x8_t result;
- __asm__ ("neg %0.8b,%1.8b"
- : "=w"(result)
- : "w"(a)
- : /* No clobbers */);
- return result;
-}
-
-__extension__ static __inline int16x4_t __attribute__ ((__always_inline__))
-vneg_s16 (int16x4_t a)
-{
- int16x4_t result;
- __asm__ ("neg %0.4h,%1.4h"
- : "=w"(result)
- : "w"(a)
- : /* No clobbers */);
- return result;
-}
-
-__extension__ static __inline int32x2_t __attribute__ ((__always_inline__))
-vneg_s32 (int32x2_t a)
-{
- int32x2_t result;
- __asm__ ("neg %0.2s,%1.2s"
- : "=w"(result)
- : "w"(a)
- : /* No clobbers */);
- return result;
-}
-
-__extension__ static __inline float32x4_t __attribute__ ((__always_inline__))
-vnegq_f32 (float32x4_t a)
-{
- float32x4_t result;
- __asm__ ("fneg %0.4s,%1.4s"
- : "=w"(result)
- : "w"(a)
- : /* No clobbers */);
- return result;
-}
-
-__extension__ static __inline float64x2_t __attribute__ ((__always_inline__))
-vnegq_f64 (float64x2_t a)
-{
- float64x2_t result;
- __asm__ ("fneg %0.2d,%1.2d"
- : "=w"(result)
- : "w"(a)
- : /* No clobbers */);
- return result;
-}
-
-__extension__ static __inline int8x16_t __attribute__ ((__always_inline__))
-vnegq_s8 (int8x16_t a)
-{
- int8x16_t result;
- __asm__ ("neg %0.16b,%1.16b"
- : "=w"(result)
- : "w"(a)
- : /* No clobbers */);
- return result;
-}
-
-__extension__ static __inline int16x8_t __attribute__ ((__always_inline__))
-vnegq_s16 (int16x8_t a)
-{
- int16x8_t result;
- __asm__ ("neg %0.8h,%1.8h"
- : "=w"(result)
- : "w"(a)
- : /* No clobbers */);
- return result;
-}
-
-__extension__ static __inline int32x4_t __attribute__ ((__always_inline__))
-vnegq_s32 (int32x4_t a)
-{
- int32x4_t result;
- __asm__ ("neg %0.4s,%1.4s"
- : "=w"(result)
- : "w"(a)
- : /* No clobbers */);
- return result;
-}
-
-__extension__ static __inline int64x2_t __attribute__ ((__always_inline__))
-vnegq_s64 (int64x2_t a)
-{
- int64x2_t result;
- __asm__ ("neg %0.2d,%1.2d"
- : "=w"(result)
- : "w"(a)
- : /* No clobbers */);
- return result;
-}
__extension__ static __inline int16x4_t __attribute__ ((__always_inline__))
vpadal_s8 (int16x4_t a, int8x8_t b)
@@ -14927,16 +14704,19 @@ __LD4_LANE_FUNC (uint64x2x4_t, uint64_t, 2d, d, u64, q)
#define __ST2_LANE_FUNC(intype, ptrtype, regsuffix, \
lnsuffix, funcsuffix, Q) \
+ typedef struct { ptrtype __x[2]; } __ST2_LANE_STRUCTURE_##intype; \
__extension__ static __inline void \
__attribute__ ((__always_inline__)) \
- vst2 ## Q ## _lane_ ## funcsuffix (const ptrtype *ptr, \
+ vst2 ## Q ## _lane_ ## funcsuffix (ptrtype *ptr, \
intype b, const int c) \
{ \
+ __ST2_LANE_STRUCTURE_##intype *__p = \
+ (__ST2_LANE_STRUCTURE_##intype *)ptr; \
__asm__ ("ld1 {v16." #regsuffix ", v17." #regsuffix "}, %1\n\t" \
"st2 {v16." #lnsuffix ", v17." #lnsuffix "}[%2], %0\n\t" \
- : "=Q"(*(intype *) ptr) \
+ : "=Q"(*__p) \
: "Q"(b), "i"(c) \
- : "memory", "v16", "v17"); \
+ : "v16", "v17"); \
}
__ST2_LANE_FUNC (int8x8x2_t, int8_t, 8b, b, s8,)
@@ -14966,16 +14746,19 @@ __ST2_LANE_FUNC (uint64x2x2_t, uint64_t, 2d, d, u64, q)
#define __ST3_LANE_FUNC(intype, ptrtype, regsuffix, \
lnsuffix, funcsuffix, Q) \
+ typedef struct { ptrtype __x[3]; } __ST3_LANE_STRUCTURE_##intype; \
__extension__ static __inline void \
__attribute__ ((__always_inline__)) \
- vst3 ## Q ## _lane_ ## funcsuffix (const ptrtype *ptr, \
+ vst3 ## Q ## _lane_ ## funcsuffix (ptrtype *ptr, \
intype b, const int c) \
{ \
+ __ST3_LANE_STRUCTURE_##intype *__p = \
+ (__ST3_LANE_STRUCTURE_##intype *)ptr; \
__asm__ ("ld1 {v16." #regsuffix " - v18." #regsuffix "}, %1\n\t" \
"st3 {v16." #lnsuffix " - v18." #lnsuffix "}[%2], %0\n\t" \
- : "=Q"(*(intype *) ptr) \
+ : "=Q"(*__p) \
: "Q"(b), "i"(c) \
- : "memory", "v16", "v17", "v18"); \
+ : "v16", "v17", "v18"); \
}
__ST3_LANE_FUNC (int8x8x3_t, int8_t, 8b, b, s8,)
@@ -15005,16 +14788,19 @@ __ST3_LANE_FUNC (uint64x2x3_t, uint64_t, 2d, d, u64, q)
#define __ST4_LANE_FUNC(intype, ptrtype, regsuffix, \
lnsuffix, funcsuffix, Q) \
+ typedef struct { ptrtype __x[4]; } __ST4_LANE_STRUCTURE_##intype; \
__extension__ static __inline void \
__attribute__ ((__always_inline__)) \
- vst4 ## Q ## _lane_ ## funcsuffix (const ptrtype *ptr, \
+ vst4 ## Q ## _lane_ ## funcsuffix (ptrtype *ptr, \
intype b, const int c) \
{ \
+ __ST4_LANE_STRUCTURE_##intype *__p = \
+ (__ST4_LANE_STRUCTURE_##intype *)ptr; \
__asm__ ("ld1 {v16." #regsuffix " - v19." #regsuffix "}, %1\n\t" \
"st4 {v16." #lnsuffix " - v19." #lnsuffix "}[%2], %0\n\t" \
- : "=Q"(*(intype *) ptr) \
+ : "=Q"(*__p) \
: "Q"(b), "i"(c) \
- : "memory", "v16", "v17", "v18", "v19"); \
+ : "v16", "v17", "v18", "v19"); \
}
__ST4_LANE_FUNC (int8x8x4_t, int8_t, 8b, b, s8,)
@@ -15859,7 +15645,7 @@ vtbx1_s8 (int8x8_t r, int8x8_t tab, int8x8_t idx)
"cmhs %0.8b, %3.8b, %0.8b\n\t"
"tbl %1.8b, {%2.16b}, %3.8b\n\t"
"bsl %0.8b, %4.8b, %1.8b\n\t"
- : "+w"(result), "=w"(tmp1)
+ : "+w"(result), "=&w"(tmp1)
: "w"(temp), "w"(idx), "w"(r)
: /* No clobbers */);
return result;
@@ -15875,7 +15661,7 @@ vtbx1_u8 (uint8x8_t r, uint8x8_t tab, uint8x8_t idx)
"cmhs %0.8b, %3.8b, %0.8b\n\t"
"tbl %1.8b, {%2.16b}, %3.8b\n\t"
"bsl %0.8b, %4.8b, %1.8b\n\t"
- : "+w"(result), "=w"(tmp1)
+ : "+w"(result), "=&w"(tmp1)
: "w"(temp), "w"(idx), "w"(r)
: /* No clobbers */);
return result;
@@ -15891,7 +15677,7 @@ vtbx1_p8 (poly8x8_t r, poly8x8_t tab, uint8x8_t idx)
"cmhs %0.8b, %3.8b, %0.8b\n\t"
"tbl %1.8b, {%2.16b}, %3.8b\n\t"
"bsl %0.8b, %4.8b, %1.8b\n\t"
- : "+w"(result), "=w"(tmp1)
+ : "+w"(result), "=&w"(tmp1)
: "w"(temp), "w"(idx), "w"(r)
: /* No clobbers */);
return result;
@@ -15946,7 +15732,7 @@ vtbx3_s8 (int8x8_t r, int8x8x3_t tab, int8x8_t idx)
"cmhs %0.8b, %3.8b, %0.8b\n\t"
"tbl %1.8b, {v16.16b - v17.16b}, %3.8b\n\t"
"bsl %0.8b, %4.8b, %1.8b\n\t"
- : "+w"(result), "=w"(tmp1)
+ : "+w"(result), "=&w"(tmp1)
: "Q"(temp), "w"(idx), "w"(r)
: "v16", "v17", "memory");
return result;
@@ -15965,7 +15751,7 @@ vtbx3_u8 (uint8x8_t r, uint8x8x3_t tab, uint8x8_t idx)
"cmhs %0.8b, %3.8b, %0.8b\n\t"
"tbl %1.8b, {v16.16b - v17.16b}, %3.8b\n\t"
"bsl %0.8b, %4.8b, %1.8b\n\t"
- : "+w"(result), "=w"(tmp1)
+ : "+w"(result), "=&w"(tmp1)
: "Q"(temp), "w"(idx), "w"(r)
: "v16", "v17", "memory");
return result;
@@ -15984,7 +15770,7 @@ vtbx3_p8 (poly8x8_t r, poly8x8x3_t tab, uint8x8_t idx)
"cmhs %0.8b, %3.8b, %0.8b\n\t"
"tbl %1.8b, {v16.16b - v17.16b}, %3.8b\n\t"
"bsl %0.8b, %4.8b, %1.8b\n\t"
- : "+w"(result), "=w"(tmp1)
+ : "+w"(result), "=&w"(tmp1)
: "Q"(temp), "w"(idx), "w"(r)
: "v16", "v17", "memory");
return result;
@@ -18025,6 +17811,80 @@ vcltzd_f64 (float64_t __a)
return __a < 0.0 ? -1ll : 0ll;
}
+/* vclz. */
+
+__extension__ static __inline int8x8_t __attribute__ ((__always_inline__))
+vclz_s8 (int8x8_t __a)
+{
+ return __builtin_aarch64_clzv8qi (__a);
+}
+
+__extension__ static __inline int16x4_t __attribute__ ((__always_inline__))
+vclz_s16 (int16x4_t __a)
+{
+ return __builtin_aarch64_clzv4hi (__a);
+}
+
+__extension__ static __inline int32x2_t __attribute__ ((__always_inline__))
+vclz_s32 (int32x2_t __a)
+{
+ return __builtin_aarch64_clzv2si (__a);
+}
+
+__extension__ static __inline uint8x8_t __attribute__ ((__always_inline__))
+vclz_u8 (uint8x8_t __a)
+{
+ return (uint8x8_t)__builtin_aarch64_clzv8qi ((int8x8_t)__a);
+}
+
+__extension__ static __inline uint16x4_t __attribute__ ((__always_inline__))
+vclz_u16 (uint16x4_t __a)
+{
+ return (uint16x4_t)__builtin_aarch64_clzv4hi ((int16x4_t)__a);
+}
+
+__extension__ static __inline uint32x2_t __attribute__ ((__always_inline__))
+vclz_u32 (uint32x2_t __a)
+{
+ return (uint32x2_t)__builtin_aarch64_clzv2si ((int32x2_t)__a);
+}
+
+__extension__ static __inline int8x16_t __attribute__ ((__always_inline__))
+vclzq_s8 (int8x16_t __a)
+{
+ return __builtin_aarch64_clzv16qi (__a);
+}
+
+__extension__ static __inline int16x8_t __attribute__ ((__always_inline__))
+vclzq_s16 (int16x8_t __a)
+{
+ return __builtin_aarch64_clzv8hi (__a);
+}
+
+__extension__ static __inline int32x4_t __attribute__ ((__always_inline__))
+vclzq_s32 (int32x4_t __a)
+{
+ return __builtin_aarch64_clzv4si (__a);
+}
+
+__extension__ static __inline uint8x16_t __attribute__ ((__always_inline__))
+vclzq_u8 (uint8x16_t __a)
+{
+ return (uint8x16_t)__builtin_aarch64_clzv16qi ((int8x16_t)__a);
+}
+
+__extension__ static __inline uint16x8_t __attribute__ ((__always_inline__))
+vclzq_u16 (uint16x8_t __a)
+{
+ return (uint16x8_t)__builtin_aarch64_clzv8hi ((int16x8_t)__a);
+}
+
+__extension__ static __inline uint32x4_t __attribute__ ((__always_inline__))
+vclzq_u32 (uint32x4_t __a)
+{
+ return (uint32x4_t)__builtin_aarch64_clzv4si ((int32x4_t)__a);
+}
+
/* vcvt (double -> float). */
__extension__ static __inline float32x2_t __attribute__ ((__always_inline__))
@@ -21241,6 +21101,80 @@ vmulq_laneq_u32 (uint32x4_t __a, uint32x4_t __b, const int __lane)
return __a * __aarch64_vgetq_lane_u32 (__b, __lane);
}
+/* vneg */
+
+__extension__ static __inline float32x2_t __attribute__ ((__always_inline__))
+vneg_f32 (float32x2_t __a)
+{
+ return -__a;
+}
+
+__extension__ static __inline float64x1_t __attribute__ ((__always_inline__))
+vneg_f64 (float64x1_t __a)
+{
+ return -__a;
+}
+
+__extension__ static __inline int8x8_t __attribute__ ((__always_inline__))
+vneg_s8 (int8x8_t __a)
+{
+ return -__a;
+}
+
+__extension__ static __inline int16x4_t __attribute__ ((__always_inline__))
+vneg_s16 (int16x4_t __a)
+{
+ return -__a;
+}
+
+__extension__ static __inline int32x2_t __attribute__ ((__always_inline__))
+vneg_s32 (int32x2_t __a)
+{
+ return -__a;
+}
+
+__extension__ static __inline int64x1_t __attribute__ ((__always_inline__))
+vneg_s64 (int64x1_t __a)
+{
+ return -__a;
+}
+
+__extension__ static __inline float32x4_t __attribute__ ((__always_inline__))
+vnegq_f32 (float32x4_t __a)
+{
+ return -__a;
+}
+
+__extension__ static __inline float64x2_t __attribute__ ((__always_inline__))
+vnegq_f64 (float64x2_t __a)
+{
+ return -__a;
+}
+
+__extension__ static __inline int8x16_t __attribute__ ((__always_inline__))
+vnegq_s8 (int8x16_t __a)
+{
+ return -__a;
+}
+
+__extension__ static __inline int16x8_t __attribute__ ((__always_inline__))
+vnegq_s16 (int16x8_t __a)
+{
+ return -__a;
+}
+
+__extension__ static __inline int32x4_t __attribute__ ((__always_inline__))
+vnegq_s32 (int32x4_t __a)
+{
+ return -__a;
+}
+
+__extension__ static __inline int64x2_t __attribute__ ((__always_inline__))
+vnegq_s64 (int64x2_t __a)
+{
+ return -__a;
+}
+
/* vqabs */
__extension__ static __inline int64x2_t __attribute__ ((__always_inline__))
diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md
index ec8d813fa3f..50bdac9b6a8 100644
--- a/gcc/config/aarch64/iterators.md
+++ b/gcc/config/aarch64/iterators.md
@@ -351,6 +351,7 @@
(V2SI "s") (V4SI "s")
(V2DI "d") (V2SF "s")
(V4SF "s") (V2DF "d")
+ (SF "s") (DF "d")
(QI "b") (HI "h")
(SI "s") (DI "d")])
@@ -566,6 +567,24 @@
(V2SF "f") (V4SF "f")
(V2DF "f") (DF "f")])
+;; Defined to '_fp' for types whose element type is a float type.
+(define_mode_attr fp [(V8QI "") (V16QI "")
+ (V4HI "") (V8HI "")
+ (V2SI "") (V4SI "")
+ (DI "") (V2DI "")
+ (V2SF "_fp") (V4SF "_fp")
+ (V2DF "_fp") (DF "_fp")
+ (SF "_fp")])
+
+;; Defined to '_q' for 128-bit types.
+(define_mode_attr q [(V8QI "") (V16QI "_q")
+ (V4HI "") (V8HI "_q")
+ (V2SI "") (V4SI "_q")
+ (DI "") (V2DI "_q")
+ (V2SF "") (V4SF "_q")
+ (V2DF "_q")
+ (QI "") (HI "") (SI "") (DI "") (SF "") (DF "")])
+
;; -------------------------------------------------------------------
;; Code Iterators
;; -------------------------------------------------------------------
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
index a05c42ad4b7..e39fc7731e6 100644
--- a/gcc/config/alpha/alpha.c
+++ b/gcc/config/alpha/alpha.c
@@ -49,7 +49,7 @@ along with GCC; see the file COPYING3. If not see
#include "langhooks.h"
#include "splay-tree.h"
#include "gimple.h"
-#include "tree-flow.h"
+#include "gimple-ssa.h"
#include "tree-ssanames.h"
#include "tree-stdarg.h"
#include "tm-constrs.h"
@@ -4228,12 +4228,12 @@ alpha_expand_builtin_vector_binop (rtx (*gen) (rtx, rtx, rtx),
static void
emit_unlikely_jump (rtx cond, rtx label)
{
- rtx very_unlikely = GEN_INT (REG_BR_PROB_BASE / 100 - 1);
+ int very_unlikely = REG_BR_PROB_BASE / 100 - 1;
rtx x;
x = gen_rtx_IF_THEN_ELSE (VOIDmode, cond, label, pc_rtx);
x = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, x));
- add_reg_note (x, REG_BR_PROB, very_unlikely);
+ add_int_reg_note (x, REG_BR_PROB, very_unlikely);
}
/* A subroutine of the atomic operation splitters. Emit a load-locked
diff --git a/gcc/config/alpha/x-alpha b/gcc/config/alpha/x-alpha
index ecca70424af..2b22e5e3253 100644
--- a/gcc/config/alpha/x-alpha
+++ b/gcc/config/alpha/x-alpha
@@ -1,3 +1,3 @@
-driver-alpha.o: $(srcdir)/config/alpha/driver-alpha.c \
- $(CONFIG_H) $(SYSTEM_H)
- $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
+driver-alpha.o: $(srcdir)/config/alpha/driver-alpha.c
+ $(COMPILE) $<
+ $(POSTCOMPILE)
diff --git a/gcc/config/arc/arc-modes.def b/gcc/config/arc/arc-modes.def
new file mode 100644
index 00000000000..8c738dda497
--- /dev/null
+++ b/gcc/config/arc/arc-modes.def
@@ -0,0 +1,37 @@
+/* Definitions of target machine for GNU compiler, Synopsys DesignWare ARC cpu.
+ Copyright (C) 2002, 2007-2013 Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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/>. */
+
+/* Some insns set all condition code flags, some only set the ZNC flags, and
+ some only set the ZN flags. */
+
+CC_MODE (CC_ZN);
+CC_MODE (CC_Z);
+CC_MODE (CC_C);
+CC_MODE (CC_FP_GT);
+CC_MODE (CC_FP_GE);
+CC_MODE (CC_FP_ORD);
+CC_MODE (CC_FP_UNEQ);
+CC_MODE (CC_FPX);
+
+/* Vector modes. */
+VECTOR_MODES (INT, 4); /* V4QI V2HI */
+VECTOR_MODES (INT, 8); /* V8QI V4HI V2SI */
+VECTOR_MODES (INT, 16); /* V16QI V8HI V4SI V2DI */
diff --git a/gcc/config/arc/arc-opts.h b/gcc/config/arc/arc-opts.h
new file mode 100644
index 00000000000..5933e9fbbcd
--- /dev/null
+++ b/gcc/config/arc/arc-opts.h
@@ -0,0 +1,28 @@
+/* GCC option-handling definitions for the Synopsys DesignWare ARC architecture.
+
+ Copyright (C) 2007-2013 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/>. */
+
+enum processor_type
+{
+ PROCESSOR_NONE,
+ PROCESSOR_A5,
+ PROCESSOR_ARC600,
+ PROCESSOR_ARC601,
+ PROCESSOR_ARC700
+};
diff --git a/gcc/config/arc/arc-protos.h b/gcc/config/arc/arc-protos.h
new file mode 100644
index 00000000000..0939bc04bb4
--- /dev/null
+++ b/gcc/config/arc/arc-protos.h
@@ -0,0 +1,118 @@
+/* Definitions of target machine for GNU compiler, Synopsys DesignWare ARC cpu.
+ Copyright (C) 2000, 2007-2013 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/>. */
+
+#ifdef RTX_CODE
+
+extern enum machine_mode arc_select_cc_mode (enum rtx_code, rtx, rtx);
+
+/* Define the function that build the compare insn for scc, bcc and mov*cc. */
+extern struct rtx_def *gen_compare_reg (rtx, enum machine_mode);
+
+/* Declarations for various fns used in the .md file. */
+extern void arc_output_function_epilogue (FILE *, HOST_WIDE_INT, int);
+extern const char *output_shift (rtx *);
+extern bool compact_sda_memory_operand (rtx op,enum machine_mode mode);
+extern bool arc_double_limm_p (rtx);
+extern void arc_print_operand (FILE *, rtx, int);
+extern void arc_print_operand_address (FILE *, rtx);
+extern void arc_final_prescan_insn (rtx, rtx *, int);
+extern void arc_set_default_type_attributes(tree type);
+extern const char *arc_output_libcall (const char *);
+extern bool prepare_extend_operands (rtx *operands, enum rtx_code code,
+ enum machine_mode omode);
+extern int arc_output_addsi (rtx *operands, bool, bool);
+extern int arc_output_commutative_cond_exec (rtx *operands, bool);
+extern bool arc_expand_movmem (rtx *operands);
+extern bool prepare_move_operands (rtx *operands, enum machine_mode mode);
+extern void emit_shift (enum rtx_code, rtx, rtx, rtx);
+#endif /* RTX_CODE */
+
+#ifdef TREE_CODE
+extern enum arc_function_type arc_compute_function_type (struct function *);
+#endif /* TREE_CODE */
+
+
+extern void arc_init (void);
+extern unsigned int arc_compute_frame_size (int);
+extern bool arc_ccfsm_branch_deleted_p (void);
+extern void arc_ccfsm_record_branch_deleted (void);
+
+extern rtx arc_legitimize_pic_address (rtx, rtx);
+void arc_asm_output_aligned_decl_local (FILE *, tree, const char *,
+ unsigned HOST_WIDE_INT,
+ unsigned HOST_WIDE_INT,
+ unsigned HOST_WIDE_INT);
+extern rtx arc_return_addr_rtx (int , rtx);
+extern bool check_if_valid_regno_const (rtx *, int);
+extern bool check_if_valid_sleep_operand (rtx *, int);
+extern bool arc_legitimate_constant_p (enum machine_mode, rtx);
+extern bool arc_legitimate_pc_offset_p (rtx);
+extern bool arc_legitimate_pic_addr_p (rtx);
+extern void emit_pic_move (rtx *, enum machine_mode);
+extern bool arc_raw_symbolic_reference_mentioned_p (rtx, bool);
+extern bool arc_legitimate_pic_operand_p (rtx);
+extern bool arc_is_longcall_p (rtx);
+extern bool arc_is_shortcall_p (rtx);
+extern bool arc_profile_call (rtx callee);
+extern bool valid_brcc_with_delay_p (rtx *);
+extern bool small_data_pattern (rtx , enum machine_mode);
+extern rtx arc_rewrite_small_data (rtx);
+extern bool arc_ccfsm_cond_exec_p (void);
+struct secondary_reload_info;
+extern int arc_register_move_cost (enum machine_mode, enum reg_class,
+ enum reg_class);
+extern rtx disi_highpart (rtx);
+extern int arc_adjust_insn_length (rtx, int, bool);
+extern int arc_corereg_hazard (rtx, rtx);
+extern int arc_hazard (rtx, rtx);
+extern int arc_write_ext_corereg (rtx);
+extern rtx gen_acc1 (void);
+extern rtx gen_acc2 (void);
+extern rtx gen_mlo (void);
+extern rtx gen_mhi (void);
+extern bool arc_branch_size_unknown_p (void);
+struct arc_ccfsm;
+extern void arc_ccfsm_record_condition (rtx, bool, rtx, struct arc_ccfsm *);
+extern void arc_expand_prologue (void);
+extern void arc_expand_epilogue (int);
+extern void arc_init_expanders (void);
+extern int arc_check_millicode (rtx op, int offset, int load_p);
+extern int arc_get_unalign (void);
+extern void arc_clear_unalign (void);
+extern void arc_toggle_unalign (void);
+extern void split_addsi (rtx *);
+extern void split_subsi (rtx *);
+extern void arc_pad_return (void);
+extern rtx arc_split_move (rtx *);
+extern int arc_verify_short (rtx insn, int unalign, int);
+extern const char *arc_short_long (rtx insn, const char *, const char *);
+extern rtx arc_regno_use_in (unsigned int, rtx);
+extern int arc_attr_type (rtx);
+extern bool arc_scheduling_not_expected (void);
+extern bool arc_sets_cc_p (rtx insn);
+extern int arc_label_align (rtx label);
+extern bool arc_need_delay (rtx insn);
+extern bool arc_text_label (rtx);
+extern int arc_decl_pretend_args (tree decl);
+extern bool arc_short_comparison_p (rtx, int);
+extern bool arc_epilogue_uses (int regno);
+/* insn-attrtab.c doesn't include reload.h, which declares regno_clobbered_p. */
+extern int regno_clobbered_p (unsigned int, rtx, enum machine_mode, int);
+extern int arc_return_slot_offset (void);
+extern bool arc_legitimize_reload_address (rtx *, enum machine_mode, int, int);
diff --git a/gcc/config/arc/arc-simd.h b/gcc/config/arc/arc-simd.h
new file mode 100644
index 00000000000..2e15a912baa
--- /dev/null
+++ b/gcc/config/arc/arc-simd.h
@@ -0,0 +1,186 @@
+/* Synopsys DesignWare ARC SIMD include file.
+ Copyright (C) 2007-2013 Free Software Foundation, Inc.
+ Written by Saurabh Verma (saurabh.verma@celunite.com) on behalf os Synopsys
+ 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/>. */
+
+/* As a special exception, if you include this header file into source
+ files compiled by GCC, this header file does not by itself cause
+ the resulting executable to be covered by the GNU General Public
+ License. This exception does not however invalidate any other
+ reasons why the executable file might be covered by the GNU General
+ Public License. */
+
+#ifndef _ARC_SIMD_H
+#define _ARC_SIMD_H 1
+
+#ifndef __ARC_SIMD__
+#error Use the "-msimd" flag to enable ARC SIMD support
+#endif
+
+/* I0-I7 registers. */
+#define _IREG_I0 0
+#define _IREG_I1 1
+#define _IREG_I2 2
+#define _IREG_I3 3
+#define _IREG_I4 4
+#define _IREG_I5 5
+#define _IREG_I6 6
+#define _IREG_I7 7
+
+/* DMA configuration registers. */
+#define _DMA_REG_DR0 0
+#define _DMA_SDM_SRC_ADR_REG _DMA_REG_DR0
+#define _DMA_SDM_DEST_ADR_REG _DMA_REG_DR0
+
+#define _DMA_REG_DR1 1
+#define _DMA_SDM_STRIDE_REG _DMA_REG_DR1
+
+#define _DMA_REG_DR2 2
+#define _DMA_BLK_REG _DMA_REG_DR2
+
+#define _DMA_REG_DR3 3
+#define _DMA_LOC_REG _DMA_REG_DR3
+
+#define _DMA_REG_DR4 4
+#define _DMA_SYS_SRC_ADR_REG _DMA_REG_DR4
+#define _DMA_SYS_DEST_ADR_REG _DMA_REG_DR4
+
+#define _DMA_REG_DR5 5
+#define _DMA_SYS_STRIDE_REG _DMA_REG_DR5
+
+#define _DMA_REG_DR6 6
+#define _DMA_CFG_REG _DMA_REG_DR6
+
+#define _DMA_REG_DR7 7
+#define _DMA_FT_BASE_ADR_REG _DMA_REG_DR7
+
+/* Predefined types used in vector instructions. */
+typedef int __v4si __attribute__((vector_size(16)));
+typedef short __v8hi __attribute__((vector_size(16)));
+
+/* Synonyms */
+#define _vaddaw __builtin_arc_vaddaw
+#define _vaddw __builtin_arc_vaddw
+#define _vavb __builtin_arc_vavb
+#define _vavrb __builtin_arc_vavrb
+#define _vdifaw __builtin_arc_vdifaw
+#define _vdifw __builtin_arc_vdifw
+#define _vmaxaw __builtin_arc_vmaxaw
+#define _vmaxw __builtin_arc_vmaxw
+#define _vminaw __builtin_arc_vminaw
+#define _vminw __builtin_arc_vminw
+#define _vmulaw __builtin_arc_vmulaw
+#define _vmulfaw __builtin_arc_vmulfaw
+#define _vmulfw __builtin_arc_vmulfw
+#define _vmulw __builtin_arc_vmulw
+#define _vsubaw __builtin_arc_vsubaw
+#define _vsubw __builtin_arc_vsubw
+#define _vsummw __builtin_arc_vsummw
+#define _vand __builtin_arc_vand
+#define _vandaw __builtin_arc_vandaw
+#define _vbic __builtin_arc_vbic
+#define _vbicaw __builtin_arc_vbicaw
+#define _vor __builtin_arc_vor
+#define _vxor __builtin_arc_vxor
+#define _vxoraw __builtin_arc_vxoraw
+#define _veqw __builtin_arc_veqw
+#define _vlew __builtin_arc_vlew
+#define _vltw __builtin_arc_vltw
+#define _vnew __builtin_arc_vnew
+#define _vmr1aw __builtin_arc_vmr1aw
+#define _vmr1w __builtin_arc_vmr1w
+#define _vmr2aw __builtin_arc_vmr2aw
+#define _vmr2w __builtin_arc_vmr2w
+#define _vmr3aw __builtin_arc_vmr3aw
+#define _vmr3w __builtin_arc_vmr3w
+#define _vmr4aw __builtin_arc_vmr4aw
+#define _vmr4w __builtin_arc_vmr4w
+#define _vmr5aw __builtin_arc_vmr5aw
+#define _vmr5w __builtin_arc_vmr5w
+#define _vmr6aw __builtin_arc_vmr6aw
+#define _vmr6w __builtin_arc_vmr6w
+#define _vmr7aw __builtin_arc_vmr7aw
+#define _vmr7w __builtin_arc_vmr7w
+#define _vmrb __builtin_arc_vmrb
+#define _vh264f __builtin_arc_vh264f
+#define _vh264ft __builtin_arc_vh264ft
+#define _vh264fw __builtin_arc_vh264fw
+#define _vvc1f __builtin_arc_vvc1f
+#define _vvc1ft __builtin_arc_vvc1ft
+#define _vbaddw __builtin_arc_vbaddw
+#define _vbmaxw __builtin_arc_vbmaxw
+#define _vbminw __builtin_arc_vbminw
+#define _vbmulaw __builtin_arc_vbmulaw
+#define _vbmulfw __builtin_arc_vbmulfw
+#define _vbmulw __builtin_arc_vbmulw
+#define _vbrsubw __builtin_arc_vbrsubw
+#define _vbsubw __builtin_arc_vbsubw
+#define _vasrw __builtin_arc_vasrw
+#define _vsr8 __builtin_arc_vsr8
+#define _vsr8aw __builtin_arc_vsr8aw
+#define _vasrrwi __builtin_arc_vasrrwi
+#define _vasrsrwi __builtin_arc_vasrsrwi
+#define _vasrwi __builtin_arc_vasrwi
+#define _vasrpwbi __builtin_arc_vasrpwbi
+#define _vasrrpwbi __builtin_arc_vasrrpwbi
+#define _vsr8awi __builtin_arc_vsr8awi
+#define _vsr8i __builtin_arc_vsr8i
+#define _vmvaw __builtin_arc_vmvaw
+#define _vmvw __builtin_arc_vmvw
+#define _vmvzw __builtin_arc_vmvzw
+#define _vd6tapf __builtin_arc_vd6tapf
+#define _vmovaw __builtin_arc_vmovaw
+#define _vmovw __builtin_arc_vmovw
+#define _vmovzw __builtin_arc_vmovzw
+#define _vabsaw __builtin_arc_vabsaw
+#define _vabsw __builtin_arc_vabsw
+#define _vaddsuw __builtin_arc_vaddsuw
+#define _vsignw __builtin_arc_vsignw
+#define _vexch1 __builtin_arc_vexch1
+#define _vexch2 __builtin_arc_vexch2
+#define _vexch4 __builtin_arc_vexch4
+#define _vupbaw __builtin_arc_vupbaw
+#define _vupbw __builtin_arc_vupbw
+#define _vupsbaw __builtin_arc_vupsbaw
+#define _vupsbw __builtin_arc_vupsbw
+#define _vdirun __builtin_arc_vdirun
+#define _vdorun __builtin_arc_vdorun
+#define _vdiwr __builtin_arc_vdiwr
+#define _vdowr __builtin_arc_vdowr
+#define _vrec __builtin_arc_vrec
+#define _vrun __builtin_arc_vrun
+#define _vrecrun __builtin_arc_vrecrun
+#define _vendrec __builtin_arc_vendrec
+#define _vld32wh __builtin_arc_vld32wh
+#define _vld32wl __builtin_arc_vld32wl
+#define _vld64 __builtin_arc_vld64
+#define _vld32 __builtin_arc_vld32
+#define _vld64w __builtin_arc_vld64w
+#define _vld128 __builtin_arc_vld128
+#define _vst128 __builtin_arc_vst128
+#define _vst64 __builtin_arc_vst64
+#define _vst16_n __builtin_arc_vst16_n
+#define _vst32_n __builtin_arc_vst32_n
+#define _vinti __builtin_arc_vinti
+
+/* Additional synonyms to ease programming. */
+#define _setup_dma_in_channel_reg _vdiwr
+#define _setup_dma_out_channel_reg _vdowr
+
+#endif /* _ARC_SIMD_H */
diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
new file mode 100644
index 00000000000..7b1853b7f9b
--- /dev/null
+++ b/gcc/config/arc/arc.c
@@ -0,0 +1,9242 @@
+/* Subroutines used for code generation on the Synopsys DesignWare ARC cpu.
+ Copyright (C) 1994, 1995, 1997, 2004, 2007-2013
+ Free Software Foundation, Inc.
+
+ Sources derived from work done by Sankhya Technologies (www.sankhya.com) on
+ behalf of Synopsys Inc.
+
+ Position Independent Code support added,Code cleaned up,
+ Comments and Support For ARC700 instructions added by
+ Saurabh Verma (saurabh.verma@codito.com)
+ Ramana Radhakrishnan(ramana.radhakrishnan@codito.com)
+
+ Fixing ABI inconsistencies, optimizations for ARC600 / ARC700 pipelines,
+ profiling support added by Joern Rennecke <joern.rennecke@embecosm.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 "tree.h"
+#include "rtl.h"
+#include "regs.h"
+#include "hard-reg-set.h"
+#include "real.h"
+#include "insn-config.h"
+#include "conditions.h"
+#include "insn-flags.h"
+#include "function.h"
+#include "toplev.h"
+#include "ggc.h"
+#include "tm_p.h"
+#include "target.h"
+#include "output.h"
+#include "insn-attr.h"
+#include "flags.h"
+#include "expr.h"
+#include "recog.h"
+#include "debug.h"
+#include "diagnostic.h"
+#include "insn-codes.h"
+#include "langhooks.h"
+#include "optabs.h"
+#include "tm-constrs.h"
+#include "reload.h" /* For operands_match_p */
+#include "df.h"
+#include "tree-pass.h"
+#include "context.h"
+#include "pass_manager.h"
+
+/* Which cpu we're compiling for (A5, ARC600, ARC601, ARC700). */
+static const char *arc_cpu_string = "";
+
+/* ??? Loads can handle any constant, stores can only handle small ones. */
+/* OTOH, LIMMs cost extra, so their usefulness is limited. */
+#define RTX_OK_FOR_OFFSET_P(MODE, X) \
+(GET_CODE (X) == CONST_INT \
+ && SMALL_INT_RANGE (INTVAL (X), (GET_MODE_SIZE (MODE) - 1) & -4, \
+ (INTVAL (X) & (GET_MODE_SIZE (MODE) - 1) & 3 \
+ ? 0 \
+ : -(-GET_MODE_SIZE (MODE) | -4) >> 1)))
+
+#define LEGITIMATE_OFFSET_ADDRESS_P(MODE, X, INDEX, STRICT) \
+(GET_CODE (X) == PLUS \
+ && RTX_OK_FOR_BASE_P (XEXP (X, 0), (STRICT)) \
+ && ((INDEX && RTX_OK_FOR_INDEX_P (XEXP (X, 1), (STRICT)) \
+ && GET_MODE_SIZE ((MODE)) <= 4) \
+ || RTX_OK_FOR_OFFSET_P (MODE, XEXP (X, 1))))
+
+#define LEGITIMATE_SCALED_ADDRESS_P(MODE, X, STRICT) \
+(GET_CODE (X) == PLUS \
+ && GET_CODE (XEXP (X, 0)) == MULT \
+ && RTX_OK_FOR_INDEX_P (XEXP (XEXP (X, 0), 0), (STRICT)) \
+ && GET_CODE (XEXP (XEXP (X, 0), 1)) == CONST_INT \
+ && ((GET_MODE_SIZE (MODE) == 2 && INTVAL (XEXP (XEXP (X, 0), 1)) == 2) \
+ || (GET_MODE_SIZE (MODE) == 4 && INTVAL (XEXP (XEXP (X, 0), 1)) == 4)) \
+ && (RTX_OK_FOR_BASE_P (XEXP (X, 1), (STRICT)) \
+ || (flag_pic ? CONST_INT_P (XEXP (X, 1)) : CONSTANT_P (XEXP (X, 1)))))
+
+#define LEGITIMATE_SMALL_DATA_ADDRESS_P(X) \
+ (GET_CODE (X) == PLUS \
+ && (REG_P (XEXP ((X), 0)) && REGNO (XEXP ((X), 0)) == SDATA_BASE_REGNUM) \
+ && ((GET_CODE (XEXP((X),1)) == SYMBOL_REF \
+ && SYMBOL_REF_SMALL_P (XEXP ((X), 1))) \
+ || (GET_CODE (XEXP ((X), 1)) == CONST \
+ && GET_CODE (XEXP (XEXP ((X), 1), 0)) == PLUS \
+ && GET_CODE (XEXP (XEXP (XEXP ((X), 1), 0), 0)) == SYMBOL_REF \
+ && SYMBOL_REF_SMALL_P (XEXP (XEXP (XEXP ((X), 1), 0), 0)) \
+ && GET_CODE (XEXP(XEXP (XEXP ((X), 1), 0), 1)) == CONST_INT)))
+
+/* Array of valid operand punctuation characters. */
+char arc_punct_chars[256];
+
+/* State used by arc_ccfsm_advance to implement conditional execution. */
+struct GTY (()) arc_ccfsm
+{
+ int state;
+ int cc;
+ rtx cond;
+ rtx target_insn;
+ int target_label;
+};
+
+#define arc_ccfsm_current cfun->machine->ccfsm_current
+
+#define ARC_CCFSM_BRANCH_DELETED_P(STATE) \
+ ((STATE)->state == 1 || (STATE)->state == 2)
+
+/* Indicate we're conditionalizing insns now. */
+#define ARC_CCFSM_RECORD_BRANCH_DELETED(STATE) \
+ ((STATE)->state += 2)
+
+#define ARC_CCFSM_COND_EXEC_P(STATE) \
+ ((STATE)->state == 3 || (STATE)->state == 4 || (STATE)->state == 5 \
+ || current_insn_predicate)
+
+/* Check if INSN has a 16 bit opcode considering struct arc_ccfsm *STATE. */
+#define CCFSM_ISCOMPACT(INSN,STATE) \
+ (ARC_CCFSM_COND_EXEC_P (STATE) \
+ ? (get_attr_iscompact (INSN) == ISCOMPACT_TRUE \
+ || get_attr_iscompact (INSN) == ISCOMPACT_TRUE_LIMM) \
+ : get_attr_iscompact (INSN) != ISCOMPACT_FALSE)
+
+/* Likewise, but also consider that INSN might be in a delay slot of JUMP. */
+#define CCFSM_DBR_ISCOMPACT(INSN,JUMP,STATE) \
+ ((ARC_CCFSM_COND_EXEC_P (STATE) \
+ || (JUMP_P (JUMP) \
+ && INSN_ANNULLED_BRANCH_P (JUMP) \
+ && (TARGET_AT_DBR_CONDEXEC || INSN_FROM_TARGET_P (INSN)))) \
+ ? (get_attr_iscompact (INSN) == ISCOMPACT_TRUE \
+ || get_attr_iscompact (INSN) == ISCOMPACT_TRUE_LIMM) \
+ : get_attr_iscompact (INSN) != ISCOMPACT_FALSE)
+
+/* The maximum number of insns skipped which will be conditionalised if
+ possible. */
+/* When optimizing for speed:
+ Let p be the probability that the potentially skipped insns need to
+ be executed, pn the cost of a correctly predicted non-taken branch,
+ mt the cost of a mis/non-predicted taken branch,
+ mn mispredicted non-taken, pt correctly predicted taken ;
+ costs expressed in numbers of instructions like the ones considered
+ skipping.
+ Unfortunately we don't have a measure of predictability - this
+ is linked to probability only in that in the no-eviction-scenario
+ there is a lower bound 1 - 2 * min (p, 1-p), and a somewhat larger
+ value that can be assumed *if* the distribution is perfectly random.
+ A predictability of 1 is perfectly plausible not matter what p is,
+ because the decision could be dependent on an invocation parameter
+ of the program.
+ For large p, we want MAX_INSNS_SKIPPED == pn/(1-p) + mt - pn
+ For small p, we want MAX_INSNS_SKIPPED == pt
+
+ When optimizing for size:
+ We want to skip insn unless we could use 16 opcodes for the
+ non-conditionalized insn to balance the branch length or more.
+ Performance can be tie-breaker. */
+/* If the potentially-skipped insns are likely to be executed, we'll
+ generally save one non-taken branch
+ o
+ this to be no less than the 1/p */
+#define MAX_INSNS_SKIPPED 3
+
+/* The values of unspec's first field. */
+enum {
+ ARC_UNSPEC_PLT = 3,
+ ARC_UNSPEC_GOT,
+ ARC_UNSPEC_GOTOFF
+} ;
+
+
+enum arc_builtins {
+ ARC_BUILTIN_NOP = 2,
+ ARC_BUILTIN_NORM = 3,
+ ARC_BUILTIN_NORMW = 4,
+ ARC_BUILTIN_SWAP = 5,
+ ARC_BUILTIN_BRK = 6,
+ ARC_BUILTIN_DIVAW = 7,
+ ARC_BUILTIN_EX = 8,
+ ARC_BUILTIN_MUL64 = 9,
+ ARC_BUILTIN_MULU64 = 10,
+ ARC_BUILTIN_RTIE = 11,
+ ARC_BUILTIN_SYNC = 12,
+ ARC_BUILTIN_CORE_READ = 13,
+ ARC_BUILTIN_CORE_WRITE = 14,
+ ARC_BUILTIN_FLAG = 15,
+ ARC_BUILTIN_LR = 16,
+ ARC_BUILTIN_SR = 17,
+ ARC_BUILTIN_SLEEP = 18,
+ ARC_BUILTIN_SWI = 19,
+ ARC_BUILTIN_TRAP_S = 20,
+ ARC_BUILTIN_UNIMP_S = 21,
+ ARC_BUILTIN_ALIGNED = 22,
+
+ /* Sentinel to mark start of simd builtins. */
+ ARC_SIMD_BUILTIN_BEGIN = 1000,
+
+ ARC_SIMD_BUILTIN_VADDAW = 1001,
+ ARC_SIMD_BUILTIN_VADDW = 1002,
+ ARC_SIMD_BUILTIN_VAVB = 1003,
+ ARC_SIMD_BUILTIN_VAVRB = 1004,
+ ARC_SIMD_BUILTIN_VDIFAW = 1005,
+ ARC_SIMD_BUILTIN_VDIFW = 1006,
+ ARC_SIMD_BUILTIN_VMAXAW = 1007,
+ ARC_SIMD_BUILTIN_VMAXW = 1008,
+ ARC_SIMD_BUILTIN_VMINAW = 1009,
+ ARC_SIMD_BUILTIN_VMINW = 1010,
+ ARC_SIMD_BUILTIN_VMULAW = 1011,
+ ARC_SIMD_BUILTIN_VMULFAW = 1012,
+ ARC_SIMD_BUILTIN_VMULFW = 1013,
+ ARC_SIMD_BUILTIN_VMULW = 1014,
+ ARC_SIMD_BUILTIN_VSUBAW = 1015,
+ ARC_SIMD_BUILTIN_VSUBW = 1016,
+ ARC_SIMD_BUILTIN_VSUMMW = 1017,
+ ARC_SIMD_BUILTIN_VAND = 1018,
+ ARC_SIMD_BUILTIN_VANDAW = 1019,
+ ARC_SIMD_BUILTIN_VBIC = 1020,
+ ARC_SIMD_BUILTIN_VBICAW = 1021,
+ ARC_SIMD_BUILTIN_VOR = 1022,
+ ARC_SIMD_BUILTIN_VXOR = 1023,
+ ARC_SIMD_BUILTIN_VXORAW = 1024,
+ ARC_SIMD_BUILTIN_VEQW = 1025,
+ ARC_SIMD_BUILTIN_VLEW = 1026,
+ ARC_SIMD_BUILTIN_VLTW = 1027,
+ ARC_SIMD_BUILTIN_VNEW = 1028,
+ ARC_SIMD_BUILTIN_VMR1AW = 1029,
+ ARC_SIMD_BUILTIN_VMR1W = 1030,
+ ARC_SIMD_BUILTIN_VMR2AW = 1031,
+ ARC_SIMD_BUILTIN_VMR2W = 1032,
+ ARC_SIMD_BUILTIN_VMR3AW = 1033,
+ ARC_SIMD_BUILTIN_VMR3W = 1034,
+ ARC_SIMD_BUILTIN_VMR4AW = 1035,
+ ARC_SIMD_BUILTIN_VMR4W = 1036,
+ ARC_SIMD_BUILTIN_VMR5AW = 1037,
+ ARC_SIMD_BUILTIN_VMR5W = 1038,
+ ARC_SIMD_BUILTIN_VMR6AW = 1039,
+ ARC_SIMD_BUILTIN_VMR6W = 1040,
+ ARC_SIMD_BUILTIN_VMR7AW = 1041,
+ ARC_SIMD_BUILTIN_VMR7W = 1042,
+ ARC_SIMD_BUILTIN_VMRB = 1043,
+ ARC_SIMD_BUILTIN_VH264F = 1044,
+ ARC_SIMD_BUILTIN_VH264FT = 1045,
+ ARC_SIMD_BUILTIN_VH264FW = 1046,
+ ARC_SIMD_BUILTIN_VVC1F = 1047,
+ ARC_SIMD_BUILTIN_VVC1FT = 1048,
+
+ /* Va, Vb, rlimm instructions. */
+ ARC_SIMD_BUILTIN_VBADDW = 1050,
+ ARC_SIMD_BUILTIN_VBMAXW = 1051,
+ ARC_SIMD_BUILTIN_VBMINW = 1052,
+ ARC_SIMD_BUILTIN_VBMULAW = 1053,
+ ARC_SIMD_BUILTIN_VBMULFW = 1054,
+ ARC_SIMD_BUILTIN_VBMULW = 1055,
+ ARC_SIMD_BUILTIN_VBRSUBW = 1056,
+ ARC_SIMD_BUILTIN_VBSUBW = 1057,
+
+ /* Va, Vb, Ic instructions. */
+ ARC_SIMD_BUILTIN_VASRW = 1060,
+ ARC_SIMD_BUILTIN_VSR8 = 1061,
+ ARC_SIMD_BUILTIN_VSR8AW = 1062,
+
+ /* Va, Vb, u6 instructions. */
+ ARC_SIMD_BUILTIN_VASRRWi = 1065,
+ ARC_SIMD_BUILTIN_VASRSRWi = 1066,
+ ARC_SIMD_BUILTIN_VASRWi = 1067,
+ ARC_SIMD_BUILTIN_VASRPWBi = 1068,
+ ARC_SIMD_BUILTIN_VASRRPWBi = 1069,
+ ARC_SIMD_BUILTIN_VSR8AWi = 1070,
+ ARC_SIMD_BUILTIN_VSR8i = 1071,
+
+ /* Va, Vb, u8 (simm) instructions. */
+ ARC_SIMD_BUILTIN_VMVAW = 1075,
+ ARC_SIMD_BUILTIN_VMVW = 1076,
+ ARC_SIMD_BUILTIN_VMVZW = 1077,
+ ARC_SIMD_BUILTIN_VD6TAPF = 1078,
+
+ /* Va, rlimm, u8 (simm) instructions. */
+ ARC_SIMD_BUILTIN_VMOVAW = 1080,
+ ARC_SIMD_BUILTIN_VMOVW = 1081,
+ ARC_SIMD_BUILTIN_VMOVZW = 1082,
+
+ /* Va, Vb instructions. */
+ ARC_SIMD_BUILTIN_VABSAW = 1085,
+ ARC_SIMD_BUILTIN_VABSW = 1086,
+ ARC_SIMD_BUILTIN_VADDSUW = 1087,
+ ARC_SIMD_BUILTIN_VSIGNW = 1088,
+ ARC_SIMD_BUILTIN_VEXCH1 = 1089,
+ ARC_SIMD_BUILTIN_VEXCH2 = 1090,
+ ARC_SIMD_BUILTIN_VEXCH4 = 1091,
+ ARC_SIMD_BUILTIN_VUPBAW = 1092,
+ ARC_SIMD_BUILTIN_VUPBW = 1093,
+ ARC_SIMD_BUILTIN_VUPSBAW = 1094,
+ ARC_SIMD_BUILTIN_VUPSBW = 1095,
+
+ ARC_SIMD_BUILTIN_VDIRUN = 1100,
+ ARC_SIMD_BUILTIN_VDORUN = 1101,
+ ARC_SIMD_BUILTIN_VDIWR = 1102,
+ ARC_SIMD_BUILTIN_VDOWR = 1103,
+
+ ARC_SIMD_BUILTIN_VREC = 1105,
+ ARC_SIMD_BUILTIN_VRUN = 1106,
+ ARC_SIMD_BUILTIN_VRECRUN = 1107,
+ ARC_SIMD_BUILTIN_VENDREC = 1108,
+
+ ARC_SIMD_BUILTIN_VLD32WH = 1110,
+ ARC_SIMD_BUILTIN_VLD32WL = 1111,
+ ARC_SIMD_BUILTIN_VLD64 = 1112,
+ ARC_SIMD_BUILTIN_VLD32 = 1113,
+ ARC_SIMD_BUILTIN_VLD64W = 1114,
+ ARC_SIMD_BUILTIN_VLD128 = 1115,
+ ARC_SIMD_BUILTIN_VST128 = 1116,
+ ARC_SIMD_BUILTIN_VST64 = 1117,
+
+ ARC_SIMD_BUILTIN_VST16_N = 1120,
+ ARC_SIMD_BUILTIN_VST32_N = 1121,
+
+ ARC_SIMD_BUILTIN_VINTI = 1201,
+
+ ARC_SIMD_BUILTIN_END
+};
+
+/* A nop is needed between a 4 byte insn that sets the condition codes and
+ a branch that uses them (the same isn't true for an 8 byte insn that sets
+ the condition codes). Set by arc_ccfsm_advance. Used by
+ arc_print_operand. */
+
+static int get_arc_condition_code (rtx);
+
+static tree arc_handle_interrupt_attribute (tree *, tree, tree, int, bool *);
+
+/* Initialized arc_attribute_table to NULL since arc doesnot have any
+ machine specific supported attributes. */
+const struct attribute_spec arc_attribute_table[] =
+{
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
+ affects_type_identity } */
+ { "interrupt", 1, 1, true, false, false, arc_handle_interrupt_attribute, true },
+ /* Function calls made to this symbol must be done indirectly, because
+ it may lie outside of the 21/25 bit addressing range of a normal function
+ call. */
+ { "long_call", 0, 0, false, true, true, NULL, false },
+ /* Whereas these functions are always known to reside within the 25 bit
+ addressing range of unconditionalized bl. */
+ { "medium_call", 0, 0, false, true, true, NULL, false },
+ /* And these functions are always known to reside within the 21 bit
+ addressing range of blcc. */
+ { "short_call", 0, 0, false, true, true, NULL, false },
+ { NULL, 0, 0, false, false, false, NULL, false }
+};
+static int arc_comp_type_attributes (const_tree, const_tree);
+static void arc_file_start (void);
+static void arc_internal_label (FILE *, const char *, unsigned long);
+static void arc_output_mi_thunk (FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT,
+ tree);
+static int arc_address_cost (rtx, enum machine_mode, addr_space_t, bool);
+static void arc_encode_section_info (tree decl, rtx rtl, int first);
+
+static void arc_init_builtins (void);
+static rtx arc_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
+
+static int branch_dest (rtx);
+
+static void arc_output_pic_addr_const (FILE *, rtx, int);
+void emit_pic_move (rtx *, enum machine_mode);
+bool arc_legitimate_pic_operand_p (rtx);
+static bool arc_function_ok_for_sibcall (tree, tree);
+static rtx arc_function_value (const_tree, const_tree, bool);
+const char * output_shift (rtx *);
+static void arc_reorg (void);
+static bool arc_in_small_data_p (const_tree);
+
+static void arc_init_reg_tables (void);
+static bool arc_return_in_memory (const_tree, const_tree);
+static void arc_init_simd_builtins (void);
+static bool arc_vector_mode_supported_p (enum machine_mode);
+
+static bool arc_can_use_doloop_p (double_int, double_int, unsigned int, bool);
+static const char *arc_invalid_within_doloop (const_rtx);
+
+static void output_short_suffix (FILE *file);
+
+static bool arc_frame_pointer_required (void);
+
+/* Implements target hook vector_mode_supported_p. */
+
+static bool
+arc_vector_mode_supported_p (enum machine_mode mode)
+{
+ if (!TARGET_SIMD_SET)
+ return false;
+
+ if ((mode == V4SImode)
+ || (mode == V8HImode))
+ return true;
+
+ return false;
+}
+
+
+/* TARGET_PRESERVE_RELOAD_P is still awaiting patch re-evaluation / review. */
+static bool arc_preserve_reload_p (rtx in) ATTRIBUTE_UNUSED;
+static rtx arc_delegitimize_address (rtx);
+static bool arc_can_follow_jump (const_rtx follower, const_rtx followee);
+
+static rtx frame_insn (rtx);
+static void arc_function_arg_advance (cumulative_args_t, enum machine_mode,
+ const_tree, bool);
+static rtx arc_legitimize_address_0 (rtx, rtx, enum machine_mode mode);
+
+static void arc_finalize_pic (void);
+
+/* initialize the GCC target structure. */
+#undef TARGET_COMP_TYPE_ATTRIBUTES
+#define TARGET_COMP_TYPE_ATTRIBUTES arc_comp_type_attributes
+#undef TARGET_ASM_FILE_START
+#define TARGET_ASM_FILE_START arc_file_start
+#undef TARGET_ATTRIBUTE_TABLE
+#define TARGET_ATTRIBUTE_TABLE arc_attribute_table
+#undef TARGET_ASM_INTERNAL_LABEL
+#define TARGET_ASM_INTERNAL_LABEL arc_internal_label
+#undef TARGET_RTX_COSTS
+#define TARGET_RTX_COSTS arc_rtx_costs
+#undef TARGET_ADDRESS_COST
+#define TARGET_ADDRESS_COST arc_address_cost
+
+#undef TARGET_ENCODE_SECTION_INFO
+#define TARGET_ENCODE_SECTION_INFO arc_encode_section_info
+
+#undef TARGET_CANNOT_FORCE_CONST_MEM
+#define TARGET_CANNOT_FORCE_CONST_MEM arc_cannot_force_const_mem
+
+#undef TARGET_INIT_BUILTINS
+#define TARGET_INIT_BUILTINS arc_init_builtins
+
+#undef TARGET_EXPAND_BUILTIN
+#define TARGET_EXPAND_BUILTIN arc_expand_builtin
+
+#undef TARGET_ASM_OUTPUT_MI_THUNK
+#define TARGET_ASM_OUTPUT_MI_THUNK arc_output_mi_thunk
+
+#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
+#define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_const_tree_hwi_hwi_const_tree_true
+
+#undef TARGET_FUNCTION_OK_FOR_SIBCALL
+#define TARGET_FUNCTION_OK_FOR_SIBCALL arc_function_ok_for_sibcall
+
+#undef TARGET_MACHINE_DEPENDENT_REORG
+#define TARGET_MACHINE_DEPENDENT_REORG arc_reorg
+
+#undef TARGET_IN_SMALL_DATA_P
+#define TARGET_IN_SMALL_DATA_P arc_in_small_data_p
+
+#undef TARGET_PROMOTE_FUNCTION_MODE
+#define TARGET_PROMOTE_FUNCTION_MODE \
+ default_promote_function_mode_always_promote
+
+#undef TARGET_PROMOTE_PROTOTYPES
+#define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
+
+#undef TARGET_RETURN_IN_MEMORY
+#define TARGET_RETURN_IN_MEMORY arc_return_in_memory
+#undef TARGET_PASS_BY_REFERENCE
+#define TARGET_PASS_BY_REFERENCE arc_pass_by_reference
+
+#undef TARGET_SETUP_INCOMING_VARARGS
+#define TARGET_SETUP_INCOMING_VARARGS arc_setup_incoming_varargs
+
+#undef TARGET_ARG_PARTIAL_BYTES
+#define TARGET_ARG_PARTIAL_BYTES arc_arg_partial_bytes
+
+#undef TARGET_MUST_PASS_IN_STACK
+#define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
+
+#undef TARGET_FUNCTION_VALUE
+#define TARGET_FUNCTION_VALUE arc_function_value
+
+#undef TARGET_SCHED_ADJUST_PRIORITY
+#define TARGET_SCHED_ADJUST_PRIORITY arc_sched_adjust_priority
+
+#undef TARGET_VECTOR_MODE_SUPPORTED_P
+#define TARGET_VECTOR_MODE_SUPPORTED_P arc_vector_mode_supported_p
+
+#undef TARGET_CAN_USE_DOLOOP_P
+#define TARGET_CAN_USE_DOLOOP_P arc_can_use_doloop_p
+
+#undef TARGET_INVALID_WITHIN_DOLOOP
+#define TARGET_INVALID_WITHIN_DOLOOP arc_invalid_within_doloop
+
+#undef TARGET_PRESERVE_RELOAD_P
+#define TARGET_PRESERVE_RELOAD_P arc_preserve_reload_p
+
+#undef TARGET_CAN_FOLLOW_JUMP
+#define TARGET_CAN_FOLLOW_JUMP arc_can_follow_jump
+
+#undef TARGET_DELEGITIMIZE_ADDRESS
+#define TARGET_DELEGITIMIZE_ADDRESS arc_delegitimize_address
+
+/* Usually, we will be able to scale anchor offsets.
+ When this fails, we want LEGITIMIZE_ADDRESS to kick in. */
+#undef TARGET_MIN_ANCHOR_OFFSET
+#define TARGET_MIN_ANCHOR_OFFSET (-1024)
+#undef TARGET_MAX_ANCHOR_OFFSET
+#define TARGET_MAX_ANCHOR_OFFSET (1020)
+
+#undef TARGET_SECONDARY_RELOAD
+#define TARGET_SECONDARY_RELOAD arc_secondary_reload
+
+#define TARGET_OPTION_OVERRIDE arc_override_options
+
+#define TARGET_CONDITIONAL_REGISTER_USAGE arc_conditional_register_usage
+
+#define TARGET_TRAMPOLINE_INIT arc_initialize_trampoline
+
+#define TARGET_TRAMPOLINE_ADJUST_ADDRESS arc_trampoline_adjust_address
+
+#define TARGET_CAN_ELIMINATE arc_can_eliminate
+
+#define TARGET_FRAME_POINTER_REQUIRED arc_frame_pointer_required
+
+#define TARGET_FUNCTION_ARG arc_function_arg
+
+#define TARGET_FUNCTION_ARG_ADVANCE arc_function_arg_advance
+
+#define TARGET_LEGITIMATE_CONSTANT_P arc_legitimate_constant_p
+
+#define TARGET_LEGITIMATE_ADDRESS_P arc_legitimate_address_p
+
+#define TARGET_MODE_DEPENDENT_ADDRESS_P arc_mode_dependent_address_p
+
+#define TARGET_LEGITIMIZE_ADDRESS arc_legitimize_address
+
+#define TARGET_ADJUST_INSN_LENGTH arc_adjust_insn_length
+
+#define TARGET_INSN_LENGTH_PARAMETERS arc_insn_length_parameters
+
+#define TARGET_LRA_P arc_lra_p
+#define TARGET_REGISTER_PRIORITY arc_register_priority
+/* Stores with scaled offsets have different displacement ranges. */
+#define TARGET_DIFFERENT_ADDR_DISPLACEMENT_P hook_bool_void_true
+#define TARGET_SPILL_CLASS arc_spill_class
+
+#include "target-def.h"
+
+#undef TARGET_ASM_ALIGNED_HI_OP
+#define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
+#undef TARGET_ASM_ALIGNED_SI_OP
+#define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
+
+/* Try to keep the (mov:DF _, reg) as early as possible so
+ that the d<add/sub/mul>h-lr insns appear together and can
+ use the peephole2 pattern. */
+
+static int
+arc_sched_adjust_priority (rtx insn, int priority)
+{
+ rtx set = single_set (insn);
+ if (set
+ && GET_MODE (SET_SRC(set)) == DFmode
+ && GET_CODE (SET_SRC(set)) == REG)
+ {
+ /* Incrementing priority by 20 (empirically derived). */
+ return priority + 20;
+ }
+
+ return priority;
+}
+
+static reg_class_t
+arc_secondary_reload (bool in_p, rtx x, reg_class_t cl, enum machine_mode,
+ secondary_reload_info *)
+{
+ if (cl == DOUBLE_REGS)
+ return GENERAL_REGS;
+
+ /* The loop counter register can be stored, but not loaded directly. */
+ if ((cl == LPCOUNT_REG || cl == WRITABLE_CORE_REGS)
+ && in_p && MEM_P (x))
+ return GENERAL_REGS;
+ return NO_REGS;
+}
+
+static unsigned arc_ifcvt (void);
+
+namespace {
+
+const pass_data pass_data_arc_ifcvt =
+{
+ RTL_PASS,
+ "arc_ifcvt", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
+ false, /* has_gate */
+ true, /* has_execute */
+ TV_IFCVT2, /* tv_id */
+ 0, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ TODO_df_finish /* todo_flags_finish */
+};
+
+class pass_arc_ifcvt : public rtl_opt_pass
+{
+public:
+ pass_arc_ifcvt(gcc::context *ctxt)
+ : rtl_opt_pass(pass_data_arc_ifcvt, ctxt)
+ {}
+
+ /* opt_pass methods: */
+ opt_pass * clone () { return new pass_arc_ifcvt (m_ctxt); }
+ unsigned int execute () { return arc_ifcvt (); }
+};
+
+} // anon namespace
+
+rtl_opt_pass *
+make_pass_arc_ifcvt (gcc::context *ctxt)
+{
+ return new pass_arc_ifcvt (ctxt);
+}
+
+/* Called by OVERRIDE_OPTIONS to initialize various things. */
+
+void
+arc_init (void)
+{
+ enum attr_tune tune_dflt = TUNE_NONE;
+
+ if (TARGET_A5)
+ {
+ arc_cpu_string = "A5";
+ }
+ else if (TARGET_ARC600)
+ {
+ arc_cpu_string = "ARC600";
+ tune_dflt = TUNE_ARC600;
+ }
+ else if (TARGET_ARC601)
+ {
+ arc_cpu_string = "ARC601";
+ tune_dflt = TUNE_ARC600;
+ }
+ else if (TARGET_ARC700)
+ {
+ arc_cpu_string = "ARC700";
+ tune_dflt = TUNE_ARC700_4_2_STD;
+ }
+ else
+ gcc_unreachable ();
+ if (arc_tune == TUNE_NONE)
+ arc_tune = tune_dflt;
+ /* Note: arc_multcost is only used in rtx_cost if speed is true. */
+ if (arc_multcost < 0)
+ switch (arc_tune)
+ {
+ case TUNE_ARC700_4_2_STD:
+ /* latency 7;
+ max throughput (1 multiply + 4 other insns) / 5 cycles. */
+ arc_multcost = COSTS_N_INSNS (4);
+ if (TARGET_NOMPY_SET)
+ arc_multcost = COSTS_N_INSNS (30);
+ break;
+ case TUNE_ARC700_4_2_XMAC:
+ /* latency 5;
+ max throughput (1 multiply + 2 other insns) / 3 cycles. */
+ arc_multcost = COSTS_N_INSNS (3);
+ if (TARGET_NOMPY_SET)
+ arc_multcost = COSTS_N_INSNS (30);
+ break;
+ case TUNE_ARC600:
+ if (TARGET_MUL64_SET)
+ {
+ arc_multcost = COSTS_N_INSNS (4);
+ break;
+ }
+ /* Fall through. */
+ default:
+ arc_multcost = COSTS_N_INSNS (30);
+ break;
+ }
+
+ /* Support mul64 generation only for A5 and ARC600. */
+ if (TARGET_MUL64_SET && TARGET_ARC700)
+ error ("-mmul64 not supported for ARC700");
+
+ /* MPY instructions valid only for ARC700. */
+ if (TARGET_NOMPY_SET && !TARGET_ARC700)
+ error ("-mno-mpy supported only for ARC700");
+
+ /* mul/mac instructions only for ARC600. */
+ if (TARGET_MULMAC_32BY16_SET && !(TARGET_ARC600 || TARGET_ARC601))
+ error ("-mmul32x16 supported only for ARC600 or ARC601");
+
+ if (!TARGET_DPFP && TARGET_DPFP_DISABLE_LRSR)
+ error ("-mno-dpfp-lrsr suppforted only with -mdpfp");
+
+ /* FPX-1. No fast and compact together. */
+ if ((TARGET_DPFP_FAST_SET && TARGET_DPFP_COMPACT_SET)
+ || (TARGET_SPFP_FAST_SET && TARGET_SPFP_COMPACT_SET))
+ error ("FPX fast and compact options cannot be specified together");
+
+ /* FPX-2. No fast-spfp for arc600 or arc601. */
+ if (TARGET_SPFP_FAST_SET && (TARGET_ARC600 || TARGET_ARC601))
+ error ("-mspfp_fast not available on ARC600 or ARC601");
+
+ /* FPX-3. No FPX extensions on pre-ARC600 cores. */
+ if ((TARGET_DPFP || TARGET_SPFP)
+ && !(TARGET_ARC600 || TARGET_ARC601 || TARGET_ARC700))
+ error ("FPX extensions not available on pre-ARC600 cores");
+
+ /* Warn for unimplemented PIC in pre-ARC700 cores, and disable flag_pic. */
+ if (flag_pic && !TARGET_ARC700)
+ {
+ warning (DK_WARNING, "PIC is not supported for %s. Generating non-PIC code only..", arc_cpu_string);
+ flag_pic = 0;
+ }
+
+ arc_init_reg_tables ();
+
+ /* Initialize array for PRINT_OPERAND_PUNCT_VALID_P. */
+ memset (arc_punct_chars, 0, sizeof (arc_punct_chars));
+ arc_punct_chars['#'] = 1;
+ arc_punct_chars['*'] = 1;
+ arc_punct_chars['?'] = 1;
+ arc_punct_chars['!'] = 1;
+ arc_punct_chars['^'] = 1;
+ arc_punct_chars['&'] = 1;
+
+ if (optimize > 1 && !TARGET_NO_COND_EXEC)
+ {
+ /* There are two target-independent ifcvt passes, and arc_reorg may do
+ one or more arc_ifcvt calls. */
+ opt_pass *pass_arc_ifcvt_4 = make_pass_arc_ifcvt (g);
+ struct register_pass_info arc_ifcvt4_info
+ = { pass_arc_ifcvt_4, "dbr", 1, PASS_POS_INSERT_AFTER };
+ struct register_pass_info arc_ifcvt5_info
+ = { pass_arc_ifcvt_4->clone (), "shorten", 1, PASS_POS_INSERT_BEFORE };
+
+ register_pass (&arc_ifcvt4_info);
+ register_pass (&arc_ifcvt5_info);
+ }
+}
+
+/* Check ARC options, generate derived target attributes. */
+
+static void
+arc_override_options (void)
+{
+ if (arc_cpu == PROCESSOR_NONE)
+ arc_cpu = PROCESSOR_ARC700;
+
+ if (arc_size_opt_level == 3)
+ optimize_size = 1;
+
+ if (flag_pic)
+ target_flags |= MASK_NO_SDATA_SET;
+
+ if (flag_no_common == 255)
+ flag_no_common = !TARGET_NO_SDATA_SET;
+
+ /* TARGET_COMPACT_CASESI needs the "q" register class. */ \
+ if (TARGET_MIXED_CODE)
+ TARGET_Q_CLASS = 1;
+ if (!TARGET_Q_CLASS)
+ TARGET_COMPACT_CASESI = 0;
+ if (TARGET_COMPACT_CASESI)
+ TARGET_CASE_VECTOR_PC_RELATIVE = 1;
+
+ /* These need to be done at start up. It's convenient to do them here. */
+ arc_init ();
+}
+
+/* The condition codes of the ARC, and the inverse function. */
+/* For short branches, the "c" / "nc" names are not defined in the ARC
+ Programmers manual, so we have to use "lo" / "hs"" instead. */
+static const char *arc_condition_codes[] =
+{
+ "al", 0, "eq", "ne", "p", "n", "lo", "hs", "v", "nv",
+ "gt", "le", "ge", "lt", "hi", "ls", "pnz", 0
+};
+
+enum arc_cc_code_index
+{
+ ARC_CC_AL, ARC_CC_EQ = ARC_CC_AL+2, ARC_CC_NE, ARC_CC_P, ARC_CC_N,
+ ARC_CC_C, ARC_CC_NC, ARC_CC_V, ARC_CC_NV,
+ ARC_CC_GT, ARC_CC_LE, ARC_CC_GE, ARC_CC_LT, ARC_CC_HI, ARC_CC_LS, ARC_CC_PNZ,
+ ARC_CC_LO = ARC_CC_C, ARC_CC_HS = ARC_CC_NC
+};
+
+#define ARC_INVERSE_CONDITION_CODE(X) ((X) ^ 1)
+
+/* Returns the index of the ARC condition code string in
+ `arc_condition_codes'. COMPARISON should be an rtx like
+ `(eq (...) (...))'. */
+
+static int
+get_arc_condition_code (rtx comparison)
+{
+ switch (GET_MODE (XEXP (comparison, 0)))
+ {
+ case CCmode:
+ case SImode: /* For BRcc. */
+ switch (GET_CODE (comparison))
+ {
+ case EQ : return ARC_CC_EQ;
+ case NE : return ARC_CC_NE;
+ case GT : return ARC_CC_GT;
+ case LE : return ARC_CC_LE;
+ case GE : return ARC_CC_GE;
+ case LT : return ARC_CC_LT;
+ case GTU : return ARC_CC_HI;
+ case LEU : return ARC_CC_LS;
+ case LTU : return ARC_CC_LO;
+ case GEU : return ARC_CC_HS;
+ default : gcc_unreachable ();
+ }
+ case CC_ZNmode:
+ switch (GET_CODE (comparison))
+ {
+ case EQ : return ARC_CC_EQ;
+ case NE : return ARC_CC_NE;
+ case GE: return ARC_CC_P;
+ case LT: return ARC_CC_N;
+ case GT : return ARC_CC_PNZ;
+ default : gcc_unreachable ();
+ }
+ case CC_Zmode:
+ switch (GET_CODE (comparison))
+ {
+ case EQ : return ARC_CC_EQ;
+ case NE : return ARC_CC_NE;
+ default : gcc_unreachable ();
+ }
+ case CC_Cmode:
+ switch (GET_CODE (comparison))
+ {
+ case LTU : return ARC_CC_C;
+ case GEU : return ARC_CC_NC;
+ default : gcc_unreachable ();
+ }
+ case CC_FP_GTmode:
+ if (TARGET_ARGONAUT_SET && TARGET_SPFP)
+ switch (GET_CODE (comparison))
+ {
+ case GT : return ARC_CC_N;
+ case UNLE: return ARC_CC_P;
+ default : gcc_unreachable ();
+ }
+ else
+ switch (GET_CODE (comparison))
+ {
+ case GT : return ARC_CC_HI;
+ case UNLE : return ARC_CC_LS;
+ default : gcc_unreachable ();
+ }
+ case CC_FP_GEmode:
+ /* Same for FPX and non-FPX. */
+ switch (GET_CODE (comparison))
+ {
+ case GE : return ARC_CC_HS;
+ case UNLT : return ARC_CC_LO;
+ default : gcc_unreachable ();
+ }
+ case CC_FP_UNEQmode:
+ switch (GET_CODE (comparison))
+ {
+ case UNEQ : return ARC_CC_EQ;
+ case LTGT : return ARC_CC_NE;
+ default : gcc_unreachable ();
+ }
+ case CC_FP_ORDmode:
+ switch (GET_CODE (comparison))
+ {
+ case UNORDERED : return ARC_CC_C;
+ case ORDERED : return ARC_CC_NC;
+ default : gcc_unreachable ();
+ }
+ case CC_FPXmode:
+ switch (GET_CODE (comparison))
+ {
+ case EQ : return ARC_CC_EQ;
+ case NE : return ARC_CC_NE;
+ case UNORDERED : return ARC_CC_C;
+ case ORDERED : return ARC_CC_NC;
+ case LTGT : return ARC_CC_HI;
+ case UNEQ : return ARC_CC_LS;
+ default : gcc_unreachable ();
+ }
+ default : gcc_unreachable ();
+ }
+ /*NOTREACHED*/
+ return (42);
+}
+
+/* Return true if COMPARISON has a short form that can accomodate OFFSET. */
+
+bool
+arc_short_comparison_p (rtx comparison, int offset)
+{
+ gcc_assert (ARC_CC_NC == ARC_CC_HS);
+ gcc_assert (ARC_CC_C == ARC_CC_LO);
+ switch (get_arc_condition_code (comparison))
+ {
+ case ARC_CC_EQ: case ARC_CC_NE:
+ return offset >= -512 && offset <= 506;
+ case ARC_CC_GT: case ARC_CC_LE: case ARC_CC_GE: case ARC_CC_LT:
+ case ARC_CC_HI: case ARC_CC_LS: case ARC_CC_LO: case ARC_CC_HS:
+ return offset >= -64 && offset <= 58;
+ default:
+ return false;
+ }
+}
+
+/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
+ return the mode to be used for the comparison. */
+
+enum machine_mode
+arc_select_cc_mode (enum rtx_code op, rtx x, rtx y)
+{
+ enum machine_mode mode = GET_MODE (x);
+ rtx x1;
+
+ /* For an operation that sets the condition codes as a side-effect, the
+ C and V flags is not set as for cmp, so we can only use comparisons where
+ this doesn't matter. (For LT and GE we can use "mi" and "pl"
+ instead.) */
+ /* ??? We could use "pnz" for greater than zero, however, we could then
+ get into trouble because the comparison could not be reversed. */
+ if (GET_MODE_CLASS (mode) == MODE_INT
+ && y == const0_rtx
+ && (op == EQ || op == NE
+ || ((op == LT || op == GE) && GET_MODE_SIZE (GET_MODE (x) <= 4))))
+ return CC_ZNmode;
+
+ /* add.f for if (a+b) */
+ if (mode == SImode
+ && GET_CODE (y) == NEG
+ && (op == EQ || op == NE))
+ return CC_ZNmode;
+
+ /* Check if this is a test suitable for bxor.f . */
+ if (mode == SImode && (op == EQ || op == NE) && CONST_INT_P (y)
+ && ((INTVAL (y) - 1) & INTVAL (y)) == 0
+ && INTVAL (y))
+ return CC_Zmode;
+
+ /* Check if this is a test suitable for add / bmsk.f . */
+ if (mode == SImode && (op == EQ || op == NE) && CONST_INT_P (y)
+ && GET_CODE (x) == AND && CONST_INT_P ((x1 = XEXP (x, 1)))
+ && ((INTVAL (x1) + 1) & INTVAL (x1)) == 0
+ && (~INTVAL (x1) | INTVAL (y)) < 0
+ && (~INTVAL (x1) | INTVAL (y)) > -0x800)
+ return CC_Zmode;
+
+ if (GET_MODE (x) == SImode && (op == LTU || op == GEU)
+ && GET_CODE (x) == PLUS
+ && (rtx_equal_p (XEXP (x, 0), y) || rtx_equal_p (XEXP (x, 1), y)))
+ return CC_Cmode;
+
+ if (TARGET_ARGONAUT_SET
+ && ((mode == SFmode && TARGET_SPFP) || (mode == DFmode && TARGET_DPFP)))
+ switch (op)
+ {
+ case EQ: case NE: case UNEQ: case LTGT: case ORDERED: case UNORDERED:
+ return CC_FPXmode;
+ case LT: case UNGE: case GT: case UNLE:
+ return CC_FP_GTmode;
+ case LE: case UNGT: case GE: case UNLT:
+ return CC_FP_GEmode;
+ default: gcc_unreachable ();
+ }
+ else if (GET_MODE_CLASS (mode) == MODE_FLOAT && TARGET_OPTFPE)
+ switch (op)
+ {
+ case EQ: case NE: return CC_Zmode;
+ case LT: case UNGE:
+ case GT: case UNLE: return CC_FP_GTmode;
+ case LE: case UNGT:
+ case GE: case UNLT: return CC_FP_GEmode;
+ case UNEQ: case LTGT: return CC_FP_UNEQmode;
+ case ORDERED: case UNORDERED: return CC_FP_ORDmode;
+ default: gcc_unreachable ();
+ }
+
+ return CCmode;
+}
+
+/* Vectors to keep interesting information about registers where it can easily
+ be got. We use to use the actual mode value as the bit number, but there
+ is (or may be) more than 32 modes now. Instead we use two tables: one
+ indexed by hard register number, and one indexed by mode. */
+
+/* The purpose of arc_mode_class is to shrink the range of modes so that
+ they all fit (as bit numbers) in a 32-bit word (again). Each real mode is
+ mapped into one arc_mode_class mode. */
+
+enum arc_mode_class {
+ C_MODE,
+ S_MODE, D_MODE, T_MODE, O_MODE,
+ SF_MODE, DF_MODE, TF_MODE, OF_MODE,
+ V_MODE
+};
+
+/* Modes for condition codes. */
+#define C_MODES (1 << (int) C_MODE)
+
+/* Modes for single-word and smaller quantities. */
+#define S_MODES ((1 << (int) S_MODE) | (1 << (int) SF_MODE))
+
+/* Modes for double-word and smaller quantities. */
+#define D_MODES (S_MODES | (1 << (int) D_MODE) | (1 << DF_MODE))
+
+/* Mode for 8-byte DF values only. */
+#define DF_MODES (1 << DF_MODE)
+
+/* Modes for quad-word and smaller quantities. */
+#define T_MODES (D_MODES | (1 << (int) T_MODE) | (1 << (int) TF_MODE))
+
+/* Modes for 128-bit vectors. */
+#define V_MODES (1 << (int) V_MODE)
+
+/* Value is 1 if register/mode pair is acceptable on arc. */
+
+unsigned int arc_hard_regno_mode_ok[] = {
+ T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES,
+ T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES,
+ T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, D_MODES,
+ D_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES,
+
+ /* ??? Leave these as S_MODES for now. */
+ S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES,
+ DF_MODES, 0, DF_MODES, 0, S_MODES, S_MODES, S_MODES, S_MODES,
+ S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES,
+ S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, C_MODES, S_MODES,
+
+ V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES,
+ V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES,
+ V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES,
+ V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES,
+
+ V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES,
+ V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES,
+ V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES,
+ V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES,
+
+ S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES,
+ S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES
+};
+
+unsigned int arc_mode_class [NUM_MACHINE_MODES];
+
+enum reg_class arc_regno_reg_class[FIRST_PSEUDO_REGISTER];
+
+enum reg_class
+arc_preferred_reload_class (rtx, enum reg_class cl)
+{
+ if ((cl) == CHEAP_CORE_REGS || (cl) == WRITABLE_CORE_REGS)
+ return GENERAL_REGS;
+ return cl;
+}
+
+/* Initialize the arc_mode_class array. */
+
+static void
+arc_init_reg_tables (void)
+{
+ int i;
+
+ for (i = 0; i < NUM_MACHINE_MODES; i++)
+ {
+ switch (GET_MODE_CLASS (i))
+ {
+ case MODE_INT:
+ case MODE_PARTIAL_INT:
+ case MODE_COMPLEX_INT:
+ if (GET_MODE_SIZE (i) <= 4)
+ arc_mode_class[i] = 1 << (int) S_MODE;
+ else if (GET_MODE_SIZE (i) == 8)
+ arc_mode_class[i] = 1 << (int) D_MODE;
+ else if (GET_MODE_SIZE (i) == 16)
+ arc_mode_class[i] = 1 << (int) T_MODE;
+ else if (GET_MODE_SIZE (i) == 32)
+ arc_mode_class[i] = 1 << (int) O_MODE;
+ else
+ arc_mode_class[i] = 0;
+ break;
+ case MODE_FLOAT:
+ case MODE_COMPLEX_FLOAT:
+ if (GET_MODE_SIZE (i) <= 4)
+ arc_mode_class[i] = 1 << (int) SF_MODE;
+ else if (GET_MODE_SIZE (i) == 8)
+ arc_mode_class[i] = 1 << (int) DF_MODE;
+ else if (GET_MODE_SIZE (i) == 16)
+ arc_mode_class[i] = 1 << (int) TF_MODE;
+ else if (GET_MODE_SIZE (i) == 32)
+ arc_mode_class[i] = 1 << (int) OF_MODE;
+ else
+ arc_mode_class[i] = 0;
+ break;
+ case MODE_VECTOR_INT:
+ arc_mode_class [i] = (1<< (int) V_MODE);
+ break;
+ case MODE_CC:
+ default:
+ /* mode_class hasn't been initialized yet for EXTRA_CC_MODES, so
+ we must explicitly check for them here. */
+ if (i == (int) CCmode || i == (int) CC_ZNmode || i == (int) CC_Zmode
+ || i == (int) CC_Cmode
+ || i == CC_FP_GTmode || i == CC_FP_GEmode || i == CC_FP_ORDmode)
+ arc_mode_class[i] = 1 << (int) C_MODE;
+ else
+ arc_mode_class[i] = 0;
+ break;
+ }
+ }
+}
+
+/* Core registers 56..59 are used for multiply extension options.
+ The dsp option uses r56 and r57, these are then named acc1 and acc2.
+ acc1 is the highpart, and acc2 the lowpart, so which register gets which
+ number depends on endianness.
+ The mul64 multiplier options use r57 for mlo, r58 for mmid and r59 for mhi.
+ Because mlo / mhi form a 64 bit value, we use different gcc internal
+ register numbers to make them form a register pair as the gcc internals
+ know it. mmid gets number 57, if still available, and mlo / mhi get
+ number 58 and 59, depending on endianness. We use DBX_REGISTER_NUMBER
+ to map this back. */
+ char rname56[5] = "r56";
+ char rname57[5] = "r57";
+ char rname58[5] = "r58";
+ char rname59[5] = "r59";
+
+static void
+arc_conditional_register_usage (void)
+{
+ int regno;
+ int i;
+ int fix_start = 60, fix_end = 55;
+
+ if (TARGET_MUL64_SET)
+ {
+ fix_start = 57;
+ fix_end = 59;
+
+ /* We don't provide a name for mmed. In rtl / assembly resource lists,
+ you are supposed to refer to it as mlo & mhi, e.g
+ (zero_extract:SI (reg:DI 58) (const_int 32) (16)) .
+ In an actual asm instruction, you are of course use mmed.
+ The point of avoiding having a separate register for mmed is that
+ this way, we don't have to carry clobbers of that reg around in every
+ isntruction that modifies mlo and/or mhi. */
+ strcpy (rname57, "");
+ strcpy (rname58, TARGET_BIG_ENDIAN ? "mhi" : "mlo");
+ strcpy (rname59, TARGET_BIG_ENDIAN ? "mlo" : "mhi");
+ }
+ if (TARGET_MULMAC_32BY16_SET)
+ {
+ fix_start = 56;
+ fix_end = fix_end > 57 ? fix_end : 57;
+ strcpy (rname56, TARGET_BIG_ENDIAN ? "acc1" : "acc2");
+ strcpy (rname57, TARGET_BIG_ENDIAN ? "acc2" : "acc1");
+ }
+ for (regno = fix_start; regno <= fix_end; regno++)
+ {
+ if (!fixed_regs[regno])
+ warning (0, "multiply option implies r%d is fixed", regno);
+ fixed_regs [regno] = call_used_regs[regno] = 1;
+ }
+ if (TARGET_Q_CLASS)
+ {
+ reg_alloc_order[2] = 12;
+ reg_alloc_order[3] = 13;
+ reg_alloc_order[4] = 14;
+ reg_alloc_order[5] = 15;
+ reg_alloc_order[6] = 1;
+ reg_alloc_order[7] = 0;
+ reg_alloc_order[8] = 4;
+ reg_alloc_order[9] = 5;
+ reg_alloc_order[10] = 6;
+ reg_alloc_order[11] = 7;
+ reg_alloc_order[12] = 8;
+ reg_alloc_order[13] = 9;
+ reg_alloc_order[14] = 10;
+ reg_alloc_order[15] = 11;
+ }
+ if (TARGET_SIMD_SET)
+ {
+ int i;
+ for (i = ARC_FIRST_SIMD_VR_REG; i <= ARC_LAST_SIMD_VR_REG; i++)
+ reg_alloc_order [i] = i;
+ for (i = ARC_FIRST_SIMD_DMA_CONFIG_REG;
+ i <= ARC_LAST_SIMD_DMA_CONFIG_REG; i++)
+ reg_alloc_order [i] = i;
+ }
+ /* For Arctangent-A5 / ARC600, lp_count may not be read in an instruction
+ following immediately after another one setting it to a new value.
+ There was some discussion on how to enforce scheduling constraints for
+ processors with missing interlocks on the gcc mailing list:
+ http://gcc.gnu.org/ml/gcc/2008-05/msg00021.html .
+ However, we can't actually use this approach, because for ARC the
+ delay slot scheduling pass is active, which runs after
+ machine_dependent_reorg. */
+ if (TARGET_ARC600)
+ CLEAR_HARD_REG_BIT (reg_class_contents[SIBCALL_REGS], LP_COUNT);
+ else if (!TARGET_ARC700)
+ fixed_regs[LP_COUNT] = 1;
+ for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+ if (!call_used_regs[regno])
+ CLEAR_HARD_REG_BIT (reg_class_contents[SIBCALL_REGS], regno);
+ for (regno = 32; regno < 60; regno++)
+ if (!fixed_regs[regno])
+ SET_HARD_REG_BIT (reg_class_contents[WRITABLE_CORE_REGS], regno);
+ if (TARGET_ARC700)
+ {
+ for (regno = 32; regno <= 60; regno++)
+ CLEAR_HARD_REG_BIT (reg_class_contents[CHEAP_CORE_REGS], regno);
+
+ /* If they have used -ffixed-lp_count, make sure it takes
+ effect. */
+ if (fixed_regs[LP_COUNT])
+ {
+ CLEAR_HARD_REG_BIT (reg_class_contents[LPCOUNT_REG], LP_COUNT);
+ CLEAR_HARD_REG_BIT (reg_class_contents[SIBCALL_REGS], LP_COUNT);
+ CLEAR_HARD_REG_BIT (reg_class_contents[WRITABLE_CORE_REGS], LP_COUNT);
+
+ /* Instead of taking out SF_MODE like below, forbid it outright. */
+ arc_hard_regno_mode_ok[60] = 0;
+ }
+ else
+ arc_hard_regno_mode_ok[60] = 1 << (int) S_MODE;
+ }
+
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ {
+ if (i < 29)
+ {
+ if (TARGET_Q_CLASS && ((i <= 3) || ((i >= 12) && (i <= 15))))
+ arc_regno_reg_class[i] = ARCOMPACT16_REGS;
+ else
+ arc_regno_reg_class[i] = GENERAL_REGS;
+ }
+ else if (i < 60)
+ arc_regno_reg_class[i]
+ = (fixed_regs[i]
+ ? (TEST_HARD_REG_BIT (reg_class_contents[CHEAP_CORE_REGS], i)
+ ? CHEAP_CORE_REGS : ALL_CORE_REGS)
+ : ((TARGET_ARC700
+ && TEST_HARD_REG_BIT (reg_class_contents[CHEAP_CORE_REGS], i))
+ ? CHEAP_CORE_REGS : WRITABLE_CORE_REGS));
+ else
+ arc_regno_reg_class[i] = NO_REGS;
+ }
+
+ /* ARCOMPACT16_REGS is empty, if TARGET_Q_CLASS has not been activated. */
+ if (!TARGET_Q_CLASS)
+ {
+ CLEAR_HARD_REG_SET(reg_class_contents [ARCOMPACT16_REGS]);
+ CLEAR_HARD_REG_SET(reg_class_contents [AC16_BASE_REGS]);
+ }
+
+ gcc_assert (FIRST_PSEUDO_REGISTER >= 144);
+
+ /* Handle Special Registers. */
+ arc_regno_reg_class[29] = LINK_REGS; /* ilink1 register. */
+ arc_regno_reg_class[30] = LINK_REGS; /* ilink2 register. */
+ arc_regno_reg_class[31] = LINK_REGS; /* blink register. */
+ arc_regno_reg_class[60] = LPCOUNT_REG;
+ arc_regno_reg_class[61] = NO_REGS; /* CC_REG: must be NO_REGS. */
+ arc_regno_reg_class[62] = GENERAL_REGS;
+
+ if (TARGET_DPFP)
+ {
+ for (i = 40; i < 44; ++i)
+ {
+ arc_regno_reg_class[i] = DOUBLE_REGS;
+
+ /* Unless they want us to do 'mov d1, 0x00000000' make sure
+ no attempt is made to use such a register as a destination
+ operand in *movdf_insn. */
+ if (!TARGET_ARGONAUT_SET)
+ {
+ /* Make sure no 'c', 'w', 'W', or 'Rac' constraint is
+ interpreted to mean they can use D1 or D2 in their insn. */
+ CLEAR_HARD_REG_BIT(reg_class_contents[CHEAP_CORE_REGS ], i);
+ CLEAR_HARD_REG_BIT(reg_class_contents[ALL_CORE_REGS ], i);
+ CLEAR_HARD_REG_BIT(reg_class_contents[WRITABLE_CORE_REGS ], i);
+ CLEAR_HARD_REG_BIT(reg_class_contents[MPY_WRITABLE_CORE_REGS], i);
+ }
+ }
+ }
+ else
+ {
+ /* Disable all DOUBLE_REGISTER settings,
+ if not generating DPFP code. */
+ arc_regno_reg_class[40] = ALL_REGS;
+ arc_regno_reg_class[41] = ALL_REGS;
+ arc_regno_reg_class[42] = ALL_REGS;
+ arc_regno_reg_class[43] = ALL_REGS;
+
+ arc_hard_regno_mode_ok[40] = 0;
+ arc_hard_regno_mode_ok[42] = 0;
+
+ CLEAR_HARD_REG_SET(reg_class_contents [DOUBLE_REGS]);
+ }
+
+ if (TARGET_SIMD_SET)
+ {
+ gcc_assert (ARC_FIRST_SIMD_VR_REG == 64);
+ gcc_assert (ARC_LAST_SIMD_VR_REG == 127);
+
+ for (i = ARC_FIRST_SIMD_VR_REG; i <= ARC_LAST_SIMD_VR_REG; i++)
+ arc_regno_reg_class [i] = SIMD_VR_REGS;
+
+ gcc_assert (ARC_FIRST_SIMD_DMA_CONFIG_REG == 128);
+ gcc_assert (ARC_FIRST_SIMD_DMA_CONFIG_IN_REG == 128);
+ gcc_assert (ARC_FIRST_SIMD_DMA_CONFIG_OUT_REG == 136);
+ gcc_assert (ARC_LAST_SIMD_DMA_CONFIG_REG == 143);
+
+ for (i = ARC_FIRST_SIMD_DMA_CONFIG_REG;
+ i <= ARC_LAST_SIMD_DMA_CONFIG_REG; i++)
+ arc_regno_reg_class [i] = SIMD_DMA_CONFIG_REGS;
+ }
+
+ /* pc : r63 */
+ arc_regno_reg_class[PROGRAM_COUNTER_REGNO] = GENERAL_REGS;
+}
+
+/* Handle an "interrupt" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+arc_handle_interrupt_attribute (tree *, tree name, tree args, int,
+ bool *no_add_attrs)
+{
+ gcc_assert (args);
+
+ tree value = TREE_VALUE (args);
+
+ if (TREE_CODE (value) != STRING_CST)
+ {
+ warning (OPT_Wattributes,
+ "argument of %qE attribute is not a string constant",
+ name);
+ *no_add_attrs = true;
+ }
+ else if (strcmp (TREE_STRING_POINTER (value), "ilink1")
+ && strcmp (TREE_STRING_POINTER (value), "ilink2"))
+ {
+ warning (OPT_Wattributes,
+ "argument of %qE attribute is not \"ilink1\" or \"ilink2\"",
+ name);
+ *no_add_attrs = true;
+ }
+ return NULL_TREE;
+}
+
+/* Return zero if TYPE1 and TYPE are incompatible, one if they are compatible,
+ and two if they are nearly compatible (which causes a warning to be
+ generated). */
+
+static int
+arc_comp_type_attributes (const_tree type1,
+ const_tree type2)
+{
+ int l1, l2, m1, m2, s1, s2;
+
+ /* Check for mismatch of non-default calling convention. */
+ if (TREE_CODE (type1) != FUNCTION_TYPE)
+ return 1;
+
+ /* Check for mismatched call attributes. */
+ l1 = lookup_attribute ("long_call", TYPE_ATTRIBUTES (type1)) != NULL;
+ l2 = lookup_attribute ("long_call", TYPE_ATTRIBUTES (type2)) != NULL;
+ m1 = lookup_attribute ("medium_call", TYPE_ATTRIBUTES (type1)) != NULL;
+ m2 = lookup_attribute ("medium_call", TYPE_ATTRIBUTES (type2)) != NULL;
+ s1 = lookup_attribute ("short_call", TYPE_ATTRIBUTES (type1)) != NULL;
+ s2 = lookup_attribute ("short_call", TYPE_ATTRIBUTES (type2)) != NULL;
+
+ /* Only bother to check if an attribute is defined. */
+ if (l1 | l2 | m1 | m2 | s1 | s2)
+ {
+ /* If one type has an attribute, the other must have the same attribute. */
+ if ((l1 != l2) || (m1 != m2) || (s1 != s2))
+ return 0;
+
+ /* Disallow mixed attributes. */
+ if (l1 + m1 + s1 > 1)
+ return 0;
+ }
+
+
+ return 1;
+}
+
+/* Set the default attributes for TYPE. */
+
+void
+arc_set_default_type_attributes (tree type ATTRIBUTE_UNUSED)
+{
+ gcc_unreachable();
+}
+
+/* Misc. utilities. */
+
+/* X and Y are two things to compare using CODE. Emit the compare insn and
+ return the rtx for the cc reg in the proper mode. */
+
+rtx
+gen_compare_reg (rtx comparison, enum machine_mode omode)
+{
+ enum rtx_code code = GET_CODE (comparison);
+ rtx x = XEXP (comparison, 0);
+ rtx y = XEXP (comparison, 1);
+ rtx tmp, cc_reg;
+ enum machine_mode mode, cmode;
+
+
+ cmode = GET_MODE (x);
+ if (cmode == VOIDmode)
+ cmode = GET_MODE (y);
+ gcc_assert (cmode == SImode || cmode == SFmode || cmode == DFmode);
+ if (cmode == SImode)
+ {
+ if (!register_operand (x, SImode))
+ {
+ if (register_operand (y, SImode))
+ {
+ tmp = x;
+ x = y;
+ y = tmp;
+ code = swap_condition (code);
+ }
+ else
+ x = copy_to_mode_reg (SImode, x);
+ }
+ if (GET_CODE (y) == SYMBOL_REF && flag_pic)
+ y = copy_to_mode_reg (SImode, y);
+ }
+ else
+ {
+ x = force_reg (cmode, x);
+ y = force_reg (cmode, y);
+ }
+ mode = SELECT_CC_MODE (code, x, y);
+
+ cc_reg = gen_rtx_REG (mode, CC_REG);
+
+ /* ??? FIXME (x-y)==0, as done by both cmpsfpx_raw and
+ cmpdfpx_raw, is not a correct comparison for floats:
+ http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
+ */
+ if (TARGET_ARGONAUT_SET
+ && ((cmode == SFmode && TARGET_SPFP) || (cmode == DFmode && TARGET_DPFP)))
+ {
+ switch (code)
+ {
+ case NE: case EQ: case LT: case UNGE: case LE: case UNGT:
+ case UNEQ: case LTGT: case ORDERED: case UNORDERED:
+ break;
+ case GT: case UNLE: case GE: case UNLT:
+ code = swap_condition (code);
+ tmp = x;
+ x = y;
+ y = tmp;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ if (cmode == SFmode)
+ {
+ emit_insn (gen_cmpsfpx_raw (x, y));
+ }
+ else /* DFmode */
+ {
+ /* Accepts Dx regs directly by insns. */
+ emit_insn (gen_cmpdfpx_raw (x, y));
+ }
+
+ if (mode != CC_FPXmode)
+ emit_insn (gen_rtx_SET (VOIDmode, cc_reg,
+ gen_rtx_COMPARE (mode,
+ gen_rtx_REG (CC_FPXmode, 61),
+ const0_rtx)));
+ }
+ else if (GET_MODE_CLASS (cmode) == MODE_FLOAT && TARGET_OPTFPE)
+ {
+ rtx op0 = gen_rtx_REG (cmode, 0);
+ rtx op1 = gen_rtx_REG (cmode, GET_MODE_SIZE (cmode) / UNITS_PER_WORD);
+
+ switch (code)
+ {
+ case NE: case EQ: case GT: case UNLE: case GE: case UNLT:
+ case UNEQ: case LTGT: case ORDERED: case UNORDERED:
+ break;
+ case LT: case UNGE: case LE: case UNGT:
+ code = swap_condition (code);
+ tmp = x;
+ x = y;
+ y = tmp;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ if (currently_expanding_to_rtl)
+ {
+ emit_move_insn (op0, x);
+ emit_move_insn (op1, y);
+ }
+ else
+ {
+ gcc_assert (rtx_equal_p (op0, x));
+ gcc_assert (rtx_equal_p (op1, y));
+ }
+ emit_insn (gen_cmp_float (cc_reg, gen_rtx_COMPARE (mode, op0, op1)));
+ }
+ else
+ emit_insn (gen_rtx_SET (omode, cc_reg,
+ gen_rtx_COMPARE (mode, x, y)));
+ return gen_rtx_fmt_ee (code, omode, cc_reg, const0_rtx);
+}
+
+/* Return true if VALUE, a const_double, will fit in a limm (4 byte number).
+ We assume the value can be either signed or unsigned. */
+
+bool
+arc_double_limm_p (rtx value)
+{
+ HOST_WIDE_INT low, high;
+
+ gcc_assert (GET_CODE (value) == CONST_DOUBLE);
+
+ if (TARGET_DPFP)
+ return true;
+
+ low = CONST_DOUBLE_LOW (value);
+ high = CONST_DOUBLE_HIGH (value);
+
+ if (low & 0x80000000)
+ {
+ return (((unsigned HOST_WIDE_INT) low <= 0xffffffff && high == 0)
+ || (((low & - (unsigned HOST_WIDE_INT) 0x80000000)
+ == - (unsigned HOST_WIDE_INT) 0x80000000)
+ && high == -1));
+ }
+ else
+ {
+ return (unsigned HOST_WIDE_INT) low <= 0x7fffffff && high == 0;
+ }
+}
+
+/* Do any needed setup for a variadic function. For the ARC, we must
+ create a register parameter block, and then copy any anonymous arguments
+ in registers to memory.
+
+ CUM has not been updated for the last named argument which has type TYPE
+ and mode MODE, and we rely on this fact. */
+
+static void
+arc_setup_incoming_varargs (cumulative_args_t args_so_far,
+ enum machine_mode mode, tree type,
+ int *pretend_size, int no_rtl)
+{
+ int first_anon_arg;
+ CUMULATIVE_ARGS next_cum;
+
+ /* We must treat `__builtin_va_alist' as an anonymous arg. */
+
+ next_cum = *get_cumulative_args (args_so_far);
+ arc_function_arg_advance (pack_cumulative_args (&next_cum), mode, type, 1);
+ first_anon_arg = next_cum;
+
+ if (first_anon_arg < MAX_ARC_PARM_REGS)
+ {
+ /* First anonymous (unnamed) argument is in a reg. */
+
+ /* Note that first_reg_offset < MAX_ARC_PARM_REGS. */
+ int first_reg_offset = first_anon_arg;
+
+ if (!no_rtl)
+ {
+ rtx regblock
+ = gen_rtx_MEM (BLKmode, plus_constant (Pmode, arg_pointer_rtx,
+ FIRST_PARM_OFFSET (0)));
+ move_block_from_reg (first_reg_offset, regblock,
+ MAX_ARC_PARM_REGS - first_reg_offset);
+ }
+
+ *pretend_size
+ = ((MAX_ARC_PARM_REGS - first_reg_offset ) * UNITS_PER_WORD);
+ }
+}
+
+/* Cost functions. */
+
+/* Provide the costs of an addressing mode that contains ADDR.
+ If ADDR is not a valid address, its cost is irrelevant. */
+
+int
+arc_address_cost (rtx addr, enum machine_mode, addr_space_t, bool speed)
+{
+ switch (GET_CODE (addr))
+ {
+ case REG :
+ return speed || satisfies_constraint_Rcq (addr) ? 0 : 1;
+ case PRE_INC: case PRE_DEC: case POST_INC: case POST_DEC:
+ case PRE_MODIFY: case POST_MODIFY:
+ return !speed;
+
+ case LABEL_REF :
+ case SYMBOL_REF :
+ case CONST :
+ /* Most likely needs a LIMM. */
+ return COSTS_N_INSNS (1);
+
+ case PLUS :
+ {
+ register rtx plus0 = XEXP (addr, 0);
+ register rtx plus1 = XEXP (addr, 1);
+
+ if (GET_CODE (plus0) != REG
+ && (GET_CODE (plus0) != MULT
+ || !CONST_INT_P (XEXP (plus0, 1))
+ || (INTVAL (XEXP (plus0, 1)) != 2
+ && INTVAL (XEXP (plus0, 1)) != 4)))
+ break;
+
+ switch (GET_CODE (plus1))
+ {
+ case CONST_INT :
+ return (!RTX_OK_FOR_OFFSET_P (SImode, plus1)
+ ? COSTS_N_INSNS (1)
+ : speed
+ ? 0
+ : (satisfies_constraint_Rcq (plus0)
+ && satisfies_constraint_O (plus1))
+ ? 0
+ : 1);
+ case REG:
+ return (speed < 1 ? 0
+ : (satisfies_constraint_Rcq (plus0)
+ && satisfies_constraint_Rcq (plus1))
+ ? 0 : 1);
+ case CONST :
+ case SYMBOL_REF :
+ case LABEL_REF :
+ return COSTS_N_INSNS (1);
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+
+ return 4;
+}
+
+/* Emit instruction X with the frame related bit set. */
+
+static rtx
+frame_insn (rtx x)
+{
+ x = emit_insn (x);
+ RTX_FRAME_RELATED_P (x) = 1;
+ return x;
+}
+
+/* Emit a frame insn to move SRC to DST. */
+
+static rtx
+frame_move (rtx dst, rtx src)
+{
+ return frame_insn (gen_rtx_SET (VOIDmode, dst, src));
+}
+
+/* Like frame_move, but add a REG_INC note for REG if ADDR contains an
+ auto increment address, or is zero. */
+
+static rtx
+frame_move_inc (rtx dst, rtx src, rtx reg, rtx addr)
+{
+ rtx insn = frame_move (dst, src);
+
+ if (!addr
+ || GET_CODE (addr) == PRE_DEC || GET_CODE (addr) == POST_INC
+ || GET_CODE (addr) == PRE_MODIFY || GET_CODE (addr) == POST_MODIFY)
+ add_reg_note (insn, REG_INC, reg);
+ return insn;
+}
+
+/* Emit a frame insn which adjusts a frame address register REG by OFFSET. */
+
+static rtx
+frame_add (rtx reg, HOST_WIDE_INT offset)
+{
+ gcc_assert ((offset & 0x3) == 0);
+ if (!offset)
+ return NULL_RTX;
+ return frame_move (reg, plus_constant (Pmode, reg, offset));
+}
+
+/* Emit a frame insn which adjusts stack pointer by OFFSET. */
+
+static rtx
+frame_stack_add (HOST_WIDE_INT offset)
+{
+ return frame_add (stack_pointer_rtx, offset);
+}
+
+/* Traditionally, we push saved registers first in the prologue,
+ then we allocate the rest of the frame - and reverse in the epilogue.
+ This has still its merits for ease of debugging, or saving code size
+ or even execution time if the stack frame is so large that some accesses
+ can't be encoded anymore with offsets in the instruction code when using
+ a different scheme.
+ Also, it would be a good starting point if we got instructions to help
+ with register save/restore.
+
+ However, often stack frames are small, and the pushing / popping has
+ some costs:
+ - the stack modification prevents a lot of scheduling.
+ - frame allocation / deallocation needs extra instructions.
+ - unless we know that we compile ARC700 user code, we need to put
+ a memory barrier after frame allocation / before deallocation to
+ prevent interrupts clobbering our data in the frame.
+ In particular, we don't have any such guarantees for library functions,
+ which tend to, on the other hand, to have small frames.
+
+ Thus, for small frames, we'd like to use a different scheme:
+ - The frame is allocated in full with the first prologue instruction,
+ and deallocated in full with the last epilogue instruction.
+ Thus, the instructions in-betwen can be freely scheduled.
+ - If the function has no outgoing arguments on the stack, we can allocate
+ one register save slot at the top of the stack. This register can then
+ be saved simultanously with frame allocation, and restored with
+ frame deallocation.
+ This register can be picked depending on scheduling considerations,
+ although same though should go into having some set of registers
+ to be potentially lingering after a call, and others to be available
+ immediately - i.e. in the absence of interprocedual optimization, we
+ can use an ABI-like convention for register allocation to reduce
+ stalls after function return. */
+/* Function prologue/epilogue handlers. */
+
+/* ARCompact stack frames look like:
+
+ Before call After call
+ high +-----------------------+ +-----------------------+
+ mem | reg parm save area | | reg parm save area |
+ | only created for | | only created for |
+ | variable arg fns | | variable arg fns |
+ AP +-----------------------+ +-----------------------+
+ | return addr register | | return addr register |
+ | (if required) | | (if required) |
+ +-----------------------+ +-----------------------+
+ | | | |
+ | reg save area | | reg save area |
+ | | | |
+ +-----------------------+ +-----------------------+
+ | frame pointer | | frame pointer |
+ | (if required) | | (if required) |
+ FP +-----------------------+ +-----------------------+
+ | | | |
+ | local/temp variables | | local/temp variables |
+ | | | |
+ +-----------------------+ +-----------------------+
+ | | | |
+ | arguments on stack | | arguments on stack |
+ | | | |
+ SP +-----------------------+ +-----------------------+
+ | reg parm save area |
+ | only created for |
+ | variable arg fns |
+ AP +-----------------------+
+ | return addr register |
+ | (if required) |
+ +-----------------------+
+ | |
+ | reg save area |
+ | |
+ +-----------------------+
+ | frame pointer |
+ | (if required) |
+ FP +-----------------------+
+ | |
+ | local/temp variables |
+ | |
+ +-----------------------+
+ | |
+ | arguments on stack |
+ low | |
+ mem SP +-----------------------+
+
+Notes:
+1) The "reg parm save area" does not exist for non variable argument fns.
+ The "reg parm save area" can be eliminated completely if we created our
+ own va-arc.h, but that has tradeoffs as well (so it's not done). */
+
+/* Structure to be filled in by arc_compute_frame_size with register
+ save masks, and offsets for the current function. */
+struct GTY (()) arc_frame_info
+{
+ unsigned int total_size; /* # bytes that the entire frame takes up. */
+ unsigned int extra_size; /* # bytes of extra stuff. */
+ unsigned int pretend_size; /* # bytes we push and pretend caller did. */
+ unsigned int args_size; /* # bytes that outgoing arguments take up. */
+ unsigned int reg_size; /* # bytes needed to store regs. */
+ unsigned int var_size; /* # bytes that variables take up. */
+ unsigned int reg_offset; /* Offset from new sp to store regs. */
+ unsigned int gmask; /* Mask of saved gp registers. */
+ int initialized; /* Nonzero if frame size already calculated. */
+ short millicode_start_reg;
+ short millicode_end_reg;
+ bool save_return_addr;
+};
+
+/* Defining data structures for per-function information. */
+
+typedef struct GTY (()) machine_function
+{
+ enum arc_function_type fn_type;
+ struct arc_frame_info frame_info;
+ /* To keep track of unalignment caused by short insns. */
+ int unalign;
+ int force_short_suffix; /* Used when disgorging return delay slot insns. */
+ const char *size_reason;
+ struct arc_ccfsm ccfsm_current;
+ /* Map from uid to ccfsm state during branch shortening. */
+ rtx ccfsm_current_insn;
+ char arc_reorg_started;
+ char prescan_initialized;
+} machine_function;
+
+/* Type of function DECL.
+
+ The result is cached. To reset the cache at the end of a function,
+ call with DECL = NULL_TREE. */
+
+enum arc_function_type
+arc_compute_function_type (struct function *fun)
+{
+ tree decl = fun->decl;
+ tree a;
+ enum arc_function_type fn_type = fun->machine->fn_type;
+
+ if (fn_type != ARC_FUNCTION_UNKNOWN)
+ return fn_type;
+
+ /* Assume we have a normal function (not an interrupt handler). */
+ fn_type = ARC_FUNCTION_NORMAL;
+
+ /* Now see if this is an interrupt handler. */
+ for (a = DECL_ATTRIBUTES (decl);
+ a;
+ a = TREE_CHAIN (a))
+ {
+ tree name = TREE_PURPOSE (a), args = TREE_VALUE (a);
+
+ if (name == get_identifier ("interrupt")
+ && list_length (args) == 1
+ && TREE_CODE (TREE_VALUE (args)) == STRING_CST)
+ {
+ tree value = TREE_VALUE (args);
+
+ if (!strcmp (TREE_STRING_POINTER (value), "ilink1"))
+ fn_type = ARC_FUNCTION_ILINK1;
+ else if (!strcmp (TREE_STRING_POINTER (value), "ilink2"))
+ fn_type = ARC_FUNCTION_ILINK2;
+ else
+ gcc_unreachable ();
+ break;
+ }
+ }
+
+ return fun->machine->fn_type = fn_type;
+}
+
+#define FRAME_POINTER_MASK (1 << (FRAME_POINTER_REGNUM))
+#define RETURN_ADDR_MASK (1 << (RETURN_ADDR_REGNUM))
+
+/* Tell prologue and epilogue if register REGNO should be saved / restored.
+ The return address and frame pointer are treated separately.
+ Don't consider them here.
+ Addition for pic: The gp register needs to be saved if the current
+ function changes it to access gotoff variables.
+ FIXME: This will not be needed if we used some arbitrary register
+ instead of r26.
+*/
+#define MUST_SAVE_REGISTER(regno, interrupt_p) \
+(((regno) != RETURN_ADDR_REGNUM && (regno) != FRAME_POINTER_REGNUM \
+ && (df_regs_ever_live_p (regno) && (!call_used_regs[regno] || interrupt_p))) \
+ || (flag_pic && crtl->uses_pic_offset_table \
+ && regno == PIC_OFFSET_TABLE_REGNUM) )
+
+#define MUST_SAVE_RETURN_ADDR \
+ (cfun->machine->frame_info.save_return_addr)
+
+/* Return non-zero if there are registers to be saved or loaded using
+ millicode thunks. We can only use consecutive sequences starting
+ with r13, and not going beyond r25.
+ GMASK is a bitmask of registers to save. This function sets
+ FRAME->millicod_start_reg .. FRAME->millicode_end_reg to the range
+ of registers to be saved / restored with a millicode call. */
+
+static int
+arc_compute_millicode_save_restore_regs (unsigned int gmask,
+ struct arc_frame_info *frame)
+{
+ int regno;
+
+ int start_reg = 13, end_reg = 25;
+
+ for (regno = start_reg; regno <= end_reg && (gmask & (1L << regno));)
+ regno++;
+ end_reg = regno - 1;
+ /* There is no point in using millicode thunks if we don't save/restore
+ at least three registers. For non-leaf functions we also have the
+ blink restore. */
+ if (regno - start_reg >= 3 - (crtl->is_leaf == 0))
+ {
+ frame->millicode_start_reg = 13;
+ frame->millicode_end_reg = regno - 1;
+ return 1;
+ }
+ return 0;
+}
+
+/* Return the bytes needed to compute the frame pointer from the current
+ stack pointer.
+
+ SIZE is the size needed for local variables. */
+
+unsigned int
+arc_compute_frame_size (int size) /* size = # of var. bytes allocated. */
+{
+ int regno;
+ unsigned int total_size, var_size, args_size, pretend_size, extra_size;
+ unsigned int reg_size, reg_offset;
+ unsigned int gmask;
+ enum arc_function_type fn_type;
+ int interrupt_p;
+ struct arc_frame_info *frame_info = &cfun->machine->frame_info;
+
+ size = ARC_STACK_ALIGN (size);
+
+ /* 1) Size of locals and temporaries */
+ var_size = size;
+
+ /* 2) Size of outgoing arguments */
+ args_size = crtl->outgoing_args_size;
+
+ /* 3) Calculate space needed for saved registers.
+ ??? We ignore the extension registers for now. */
+
+ /* See if this is an interrupt handler. Call used registers must be saved
+ for them too. */
+
+ reg_size = 0;
+ gmask = 0;
+ fn_type = arc_compute_function_type (cfun);
+ interrupt_p = ARC_INTERRUPT_P (fn_type);
+
+ for (regno = 0; regno <= 31; regno++)
+ {
+ if (MUST_SAVE_REGISTER (regno, interrupt_p))
+ {
+ reg_size += UNITS_PER_WORD;
+ gmask |= 1 << regno;
+ }
+ }
+
+ /* 4) Space for back trace data structure.
+ <return addr reg size> (if required) + <fp size> (if required). */
+ frame_info->save_return_addr
+ = (!crtl->is_leaf || df_regs_ever_live_p (RETURN_ADDR_REGNUM));
+ /* Saving blink reg in case of leaf function for millicode thunk calls. */
+ if (optimize_size && !TARGET_NO_MILLICODE_THUNK_SET)
+ {
+ if (arc_compute_millicode_save_restore_regs (gmask, frame_info))
+ frame_info->save_return_addr = true;
+ }
+
+ extra_size = 0;
+ if (MUST_SAVE_RETURN_ADDR)
+ extra_size = 4;
+ if (frame_pointer_needed)
+ extra_size += 4;
+
+ /* 5) Space for variable arguments passed in registers */
+ pretend_size = crtl->args.pretend_args_size;
+
+ /* Ensure everything before the locals is aligned appropriately. */
+ {
+ unsigned int extra_plus_reg_size;
+ unsigned int extra_plus_reg_size_aligned;
+
+ extra_plus_reg_size = extra_size + reg_size;
+ extra_plus_reg_size_aligned = ARC_STACK_ALIGN(extra_plus_reg_size);
+ reg_size = extra_plus_reg_size_aligned - extra_size;
+ }
+
+ /* Compute total frame size. */
+ total_size = var_size + args_size + extra_size + pretend_size + reg_size;
+
+ total_size = ARC_STACK_ALIGN (total_size);
+
+ /* Compute offset of register save area from stack pointer:
+ A5 Frame: pretend_size <blink> reg_size <fp> var_size args_size <--sp
+ */
+ reg_offset = (total_size - (pretend_size + reg_size + extra_size)
+ + (frame_pointer_needed ? 4 : 0));
+
+ /* Save computed information. */
+ frame_info->total_size = total_size;
+ frame_info->extra_size = extra_size;
+ frame_info->pretend_size = pretend_size;
+ frame_info->var_size = var_size;
+ frame_info->args_size = args_size;
+ frame_info->reg_size = reg_size;
+ frame_info->reg_offset = reg_offset;
+ frame_info->gmask = gmask;
+ frame_info->initialized = reload_completed;
+
+ /* Ok, we're done. */
+ return total_size;
+}
+
+/* Common code to save/restore registers. */
+/* BASE_REG is the base register to use for addressing and to adjust.
+ GMASK is a bitmask of general purpose registers to save/restore.
+ epilogue_p 0: prologue 1:epilogue 2:epilogue, sibling thunk
+ If *FIRST_OFFSET is non-zero, add it first to BASE_REG - preferably
+ using a pre-modify for the first memory access. *FIRST_OFFSET is then
+ zeroed. */
+
+static void
+arc_save_restore (rtx base_reg,
+ unsigned int gmask, int epilogue_p, int *first_offset)
+{
+ unsigned int offset = 0;
+ int regno;
+ struct arc_frame_info *frame = &cfun->machine->frame_info;
+ rtx sibthunk_insn = NULL_RTX;
+
+ if (gmask)
+ {
+ /* Millicode thunks implementation:
+ Generates calls to millicodes for registers starting from r13 to r25
+ Present Limitations:
+ - Only one range supported. The remaining regs will have the ordinary
+ st and ld instructions for store and loads. Hence a gmask asking
+ to store r13-14, r16-r25 will only generate calls to store and
+ load r13 to r14 while store and load insns will be generated for
+ r16 to r25 in the prologue and epilogue respectively.
+
+ - Presently library only supports register ranges starting from r13.
+ */
+ if (epilogue_p == 2 || frame->millicode_end_reg > 14)
+ {
+ int start_call = frame->millicode_start_reg;
+ int end_call = frame->millicode_end_reg;
+ int n_regs = end_call - start_call + 1;
+ int i = 0, r, off = 0;
+ rtx insn;
+ rtx ret_addr = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM);
+
+ if (*first_offset)
+ {
+ /* "reg_size" won't be more than 127 . */
+ gcc_assert (epilogue_p || abs (*first_offset <= 127));
+ frame_add (base_reg, *first_offset);
+ *first_offset = 0;
+ }
+ insn = gen_rtx_PARALLEL
+ (VOIDmode, rtvec_alloc ((epilogue_p == 2) + n_regs + 1));
+ if (epilogue_p == 2)
+ i += 2;
+ else
+ XVECEXP (insn, 0, n_regs) = gen_rtx_CLOBBER (VOIDmode, ret_addr);
+ for (r = start_call; r <= end_call; r++, off += UNITS_PER_WORD, i++)
+ {
+ rtx reg = gen_rtx_REG (SImode, r);
+ rtx mem
+ = gen_frame_mem (SImode, plus_constant (Pmode, base_reg, off));
+
+ if (epilogue_p)
+ XVECEXP (insn, 0, i) = gen_rtx_SET (VOIDmode, reg, mem);
+ else
+ XVECEXP (insn, 0, i) = gen_rtx_SET (VOIDmode, mem, reg);
+ gmask = gmask & ~(1L << r);
+ }
+ if (epilogue_p == 2)
+ sibthunk_insn = insn;
+ else
+ frame_insn (insn);
+ offset += off;
+ }
+
+ for (regno = 0; regno <= 31; regno++)
+ {
+ if ((gmask & (1L << regno)) != 0)
+ {
+ rtx reg = gen_rtx_REG (SImode, regno);
+ rtx addr, mem;
+
+ if (*first_offset)
+ {
+ gcc_assert (!offset);
+ addr = plus_constant (Pmode, base_reg, *first_offset);
+ addr = gen_rtx_PRE_MODIFY (Pmode, base_reg, addr);
+ *first_offset = 0;
+ }
+ else
+ {
+ gcc_assert (SMALL_INT (offset));
+ addr = plus_constant (Pmode, base_reg, offset);
+ }
+ mem = gen_frame_mem (SImode, addr);
+ if (epilogue_p)
+ frame_move_inc (reg, mem, base_reg, addr);
+ else
+ frame_move_inc (mem, reg, base_reg, addr);
+ offset += UNITS_PER_WORD;
+ } /* if */
+ } /* for */
+ }/* if */
+ if (sibthunk_insn)
+ {
+ rtx r12 = gen_rtx_REG (Pmode, 12);
+
+ frame_insn (gen_rtx_SET (VOIDmode, r12, GEN_INT (offset)));
+ XVECEXP (sibthunk_insn, 0, 0) = ret_rtx;
+ XVECEXP (sibthunk_insn, 0, 1)
+ = gen_rtx_SET (VOIDmode, stack_pointer_rtx,
+ gen_rtx_PLUS (Pmode, stack_pointer_rtx, r12));
+ sibthunk_insn = emit_jump_insn (sibthunk_insn);
+ RTX_FRAME_RELATED_P (sibthunk_insn) = 1;
+ }
+} /* arc_save_restore */
+
+
+int arc_return_address_regs[4]
+ = {0, RETURN_ADDR_REGNUM, ILINK1_REGNUM, ILINK2_REGNUM};
+
+/* Set up the stack and frame pointer (if desired) for the function. */
+
+void
+arc_expand_prologue (void)
+{
+ int size = get_frame_size ();
+ unsigned int gmask = cfun->machine->frame_info.gmask;
+ /* unsigned int frame_pointer_offset;*/
+ unsigned int frame_size_to_allocate;
+ /* (FIXME: The first store will use a PRE_MODIFY; this will usually be r13.
+ Change the stack layout so that we rather store a high register with the
+ PRE_MODIFY, thus enabling more short insn generation.) */
+ int first_offset = 0;
+
+ size = ARC_STACK_ALIGN (size);
+
+ /* Compute/get total frame size. */
+ size = (!cfun->machine->frame_info.initialized
+ ? arc_compute_frame_size (size)
+ : cfun->machine->frame_info.total_size);
+
+ if (flag_stack_usage_info)
+ current_function_static_stack_size = size;
+
+ /* Keep track of frame size to be allocated. */
+ frame_size_to_allocate = size;
+
+ /* These cases shouldn't happen. Catch them now. */
+ gcc_assert (!(size == 0 && gmask));
+
+ /* Allocate space for register arguments if this is a variadic function. */
+ if (cfun->machine->frame_info.pretend_size != 0)
+ {
+ /* Ensure pretend_size is maximum of 8 * word_size. */
+ gcc_assert (cfun->machine->frame_info.pretend_size <= 32);
+
+ frame_stack_add (-(HOST_WIDE_INT)cfun->machine->frame_info.pretend_size);
+ frame_size_to_allocate -= cfun->machine->frame_info.pretend_size;
+ }
+
+ /* The home-grown ABI says link register is saved first. */
+ if (MUST_SAVE_RETURN_ADDR)
+ {
+ rtx ra = gen_rtx_REG (SImode, RETURN_ADDR_REGNUM);
+ rtx mem = gen_frame_mem (Pmode, gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx));
+
+ frame_move_inc (mem, ra, stack_pointer_rtx, 0);
+ frame_size_to_allocate -= UNITS_PER_WORD;
+
+ } /* MUST_SAVE_RETURN_ADDR */
+
+ /* Save any needed call-saved regs (and call-used if this is an
+ interrupt handler) for ARCompact ISA. */
+ if (cfun->machine->frame_info.reg_size)
+ {
+ first_offset = -cfun->machine->frame_info.reg_size;
+ /* N.B. FRAME_POINTER_MASK and RETURN_ADDR_MASK are cleared in gmask. */
+ arc_save_restore (stack_pointer_rtx, gmask, 0, &first_offset);
+ frame_size_to_allocate -= cfun->machine->frame_info.reg_size;
+ }
+
+
+ /* Save frame pointer if needed. */
+ if (frame_pointer_needed)
+ {
+ rtx addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
+ GEN_INT (-UNITS_PER_WORD + first_offset));
+ rtx mem = gen_frame_mem (Pmode, gen_rtx_PRE_MODIFY (Pmode,
+ stack_pointer_rtx,
+ addr));
+ frame_move_inc (mem, frame_pointer_rtx, stack_pointer_rtx, 0);
+ frame_size_to_allocate -= UNITS_PER_WORD;
+ first_offset = 0;
+ frame_move (frame_pointer_rtx, stack_pointer_rtx);
+ }
+
+ /* ??? We don't handle the case where the saved regs are more than 252
+ bytes away from sp. This can be handled by decrementing sp once, saving
+ the regs, and then decrementing it again. The epilogue doesn't have this
+ problem as the `ld' insn takes reg+limm values (though it would be more
+ efficient to avoid reg+limm). */
+
+ frame_size_to_allocate -= first_offset;
+ /* Allocate the stack frame. */
+ if (frame_size_to_allocate > 0)
+ frame_stack_add ((HOST_WIDE_INT) 0 - frame_size_to_allocate);
+
+ /* Setup the gp register, if needed. */
+ if (crtl->uses_pic_offset_table)
+ arc_finalize_pic ();
+}
+
+/* Do any necessary cleanup after a function to restore stack, frame,
+ and regs. */
+
+void
+arc_expand_epilogue (int sibcall_p)
+{
+ int size = get_frame_size ();
+ enum arc_function_type fn_type = arc_compute_function_type (cfun);
+
+ size = ARC_STACK_ALIGN (size);
+ size = (!cfun->machine->frame_info.initialized
+ ? arc_compute_frame_size (size)
+ : cfun->machine->frame_info.total_size);
+
+ unsigned int pretend_size = cfun->machine->frame_info.pretend_size;
+ unsigned int frame_size;
+ unsigned int size_to_deallocate;
+ int restored;
+ int can_trust_sp_p = !cfun->calls_alloca;
+ int first_offset = 0;
+ int millicode_p = cfun->machine->frame_info.millicode_end_reg > 0;
+
+ size_to_deallocate = size;
+
+ frame_size = size - (pretend_size +
+ cfun->machine->frame_info.reg_size +
+ cfun->machine->frame_info.extra_size);
+
+ /* ??? There are lots of optimizations that can be done here.
+ EG: Use fp to restore regs if it's closer.
+ Maybe in time we'll do them all. For now, always restore regs from
+ sp, but don't restore sp if we don't have to. */
+
+ if (!can_trust_sp_p)
+ gcc_assert (frame_pointer_needed);
+
+ /* Restore stack pointer to the beginning of saved register area for
+ ARCompact ISA. */
+ if (frame_size)
+ {
+ if (frame_pointer_needed)
+ frame_move (stack_pointer_rtx, frame_pointer_rtx);
+ else
+ first_offset = frame_size;
+ size_to_deallocate -= frame_size;
+ }
+ else if (!can_trust_sp_p)
+ frame_stack_add (-frame_size);
+
+
+ /* Restore any saved registers. */
+ if (frame_pointer_needed)
+ {
+ rtx addr = gen_rtx_POST_INC (Pmode, stack_pointer_rtx);
+
+ frame_move_inc (frame_pointer_rtx, gen_frame_mem (Pmode, addr),
+ stack_pointer_rtx, 0);
+ size_to_deallocate -= UNITS_PER_WORD;
+ }
+
+ /* Load blink after the calls to thunk calls in case of optimize size. */
+ if (millicode_p)
+ {
+ int sibthunk_p = (!sibcall_p
+ && fn_type == ARC_FUNCTION_NORMAL
+ && !cfun->machine->frame_info.pretend_size);
+
+ gcc_assert (!(cfun->machine->frame_info.gmask
+ & (FRAME_POINTER_MASK | RETURN_ADDR_MASK)));
+ arc_save_restore (stack_pointer_rtx,
+ cfun->machine->frame_info.gmask,
+ 1 + sibthunk_p, &first_offset);
+ if (sibthunk_p)
+ goto epilogue_done;
+ }
+ /* If we are to restore registers, and first_offset would require
+ a limm to be encoded in a PRE_MODIFY, yet we can add it with a
+ fast add to the stack pointer, do this now. */
+ if ((!SMALL_INT (first_offset)
+ && cfun->machine->frame_info.gmask
+ && ((TARGET_ARC700 && !optimize_size)
+ ? first_offset <= 0x800
+ : satisfies_constraint_C2a (GEN_INT (first_offset))))
+ /* Also do this if we have both gprs and return
+ address to restore, and they both would need a LIMM. */
+ || (MUST_SAVE_RETURN_ADDR
+ && !SMALL_INT ((cfun->machine->frame_info.reg_size + first_offset) >> 2)
+ && cfun->machine->frame_info.gmask))
+ {
+ frame_stack_add (first_offset);
+ first_offset = 0;
+ }
+ if (MUST_SAVE_RETURN_ADDR)
+ {
+ rtx ra = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM);
+ int ra_offs = cfun->machine->frame_info.reg_size + first_offset;
+ rtx addr = plus_constant (Pmode, stack_pointer_rtx, ra_offs);
+
+ /* If the load of blink would need a LIMM, but we can add
+ the offset quickly to sp, do the latter. */
+ if (!SMALL_INT (ra_offs >> 2)
+ && !cfun->machine->frame_info.gmask
+ && ((TARGET_ARC700 && !optimize_size)
+ ? ra_offs <= 0x800
+ : satisfies_constraint_C2a (GEN_INT (ra_offs))))
+ {
+ size_to_deallocate -= ra_offs - first_offset;
+ first_offset = 0;
+ frame_stack_add (ra_offs);
+ ra_offs = 0;
+ addr = stack_pointer_rtx;
+ }
+ /* See if we can combine the load of the return address with the
+ final stack adjustment.
+ We need a separate load if there are still registers to
+ restore. We also want a separate load if the combined insn
+ would need a limm, but a separate load doesn't. */
+ if (ra_offs
+ && !cfun->machine->frame_info.gmask
+ && (SMALL_INT (ra_offs) || !SMALL_INT (ra_offs >> 2)))
+ {
+ addr = gen_rtx_PRE_MODIFY (Pmode, stack_pointer_rtx, addr);
+ first_offset = 0;
+ size_to_deallocate -= cfun->machine->frame_info.reg_size;
+ }
+ else if (!ra_offs && size_to_deallocate == UNITS_PER_WORD)
+ {
+ addr = gen_rtx_POST_INC (Pmode, addr);
+ size_to_deallocate = 0;
+ }
+ frame_move_inc (ra, gen_frame_mem (Pmode, addr), stack_pointer_rtx, addr);
+ }
+
+ if (!millicode_p)
+ {
+ if (cfun->machine->frame_info.reg_size)
+ arc_save_restore (stack_pointer_rtx,
+ /* The zeroing of these two bits is unnecessary, but leave this in for clarity. */
+ cfun->machine->frame_info.gmask
+ & ~(FRAME_POINTER_MASK | RETURN_ADDR_MASK), 1, &first_offset);
+ }
+
+
+ /* The rest of this function does the following:
+ ARCompact : handle epilogue_delay, restore sp (phase-2), return
+ */
+
+ /* Keep track of how much of the stack pointer we've restored.
+ It makes the following a lot more readable. */
+ size_to_deallocate += first_offset;
+ restored = size - size_to_deallocate;
+
+ if (size > restored)
+ frame_stack_add (size - restored);
+ /* Emit the return instruction. */
+ if (sibcall_p == FALSE)
+ emit_jump_insn (gen_simple_return ());
+ epilogue_done:
+ if (!TARGET_EPILOGUE_CFI)
+ {
+ rtx insn;
+
+ for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+ RTX_FRAME_RELATED_P (insn) = 0;
+ }
+}
+
+/* Return the offset relative to the stack pointer where the return address
+ is stored, or -1 if it is not stored. */
+
+int
+arc_return_slot_offset ()
+{
+ struct arc_frame_info *afi = &cfun->machine->frame_info;
+
+ return (afi->save_return_addr
+ ? afi->total_size - afi->pretend_size - afi->extra_size : -1);
+}
+
+/* PIC */
+
+/* Emit special PIC prologues and epilogues. */
+/* If the function has any GOTOFF relocations, then the GOTBASE
+ register has to be setup in the prologue
+ The instruction needed at the function start for setting up the
+ GOTBASE register is
+ add rdest, pc,
+ ----------------------------------------------------------
+ The rtl to be emitted for this should be:
+ set (reg basereg)
+ (plus (reg pc)
+ (const (unspec (symref _DYNAMIC) 3)))
+ ---------------------------------------------------------- */
+
+static void
+arc_finalize_pic (void)
+{
+ rtx pat;
+ rtx baseptr_rtx = gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM);
+
+ if (crtl->uses_pic_offset_table == 0)
+ return;
+
+ gcc_assert (flag_pic != 0);
+
+ pat = gen_rtx_SYMBOL_REF (Pmode, "_DYNAMIC");
+ pat = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, pat), ARC_UNSPEC_GOT);
+ pat = gen_rtx_CONST (Pmode, pat);
+
+ pat = gen_rtx_SET (VOIDmode, baseptr_rtx, pat);
+
+ emit_insn (pat);
+}
+
+/* !TARGET_BARREL_SHIFTER support. */
+/* Emit a shift insn to set OP0 to OP1 shifted by OP2; CODE specifies what
+ kind of shift. */
+
+void
+emit_shift (enum rtx_code code, rtx op0, rtx op1, rtx op2)
+{
+ rtx shift = gen_rtx_fmt_ee (code, SImode, op1, op2);
+ rtx pat
+ = ((shift4_operator (shift, SImode) ? gen_shift_si3 : gen_shift_si3_loop)
+ (op0, op1, op2, shift));
+ emit_insn (pat);
+}
+
+/* Output the assembler code for doing a shift.
+ We go to a bit of trouble to generate efficient code as the ARC601 only has
+ single bit shifts. This is taken from the h8300 port. We only have one
+ mode of shifting and can't access individual bytes like the h8300 can, so
+ this is greatly simplified (at the expense of not generating hyper-
+ efficient code).
+
+ This function is not used if the variable shift insns are present. */
+
+/* FIXME: This probably can be done using a define_split in arc.md.
+ Alternately, generate rtx rather than output instructions. */
+
+const char *
+output_shift (rtx *operands)
+{
+ /* static int loopend_lab;*/
+ rtx shift = operands[3];
+ enum machine_mode mode = GET_MODE (shift);
+ enum rtx_code code = GET_CODE (shift);
+ const char *shift_one;
+
+ gcc_assert (mode == SImode);
+
+ switch (code)
+ {
+ case ASHIFT: shift_one = "add %0,%1,%1"; break;
+ case ASHIFTRT: shift_one = "asr %0,%1"; break;
+ case LSHIFTRT: shift_one = "lsr %0,%1"; break;
+ default: gcc_unreachable ();
+ }
+
+ if (GET_CODE (operands[2]) != CONST_INT)
+ {
+ output_asm_insn ("and.f lp_count,%2, 0x1f", operands);
+ goto shiftloop;
+ }
+ else
+ {
+ int n;
+
+ n = INTVAL (operands[2]);
+
+ /* Only consider the lower 5 bits of the shift count. */
+ n = n & 0x1f;
+
+ /* First see if we can do them inline. */
+ /* ??? We could get better scheduling & shorter code (using short insns)
+ by using splitters. Alas, that'd be even more verbose. */
+ if (code == ASHIFT && n <= 9 && n > 2
+ && dest_reg_operand (operands[4], SImode))
+ {
+ output_asm_insn ("mov %4,0\n\tadd3 %0,%4,%1", operands);
+ for (n -=3 ; n >= 3; n -= 3)
+ output_asm_insn ("add3 %0,%4,%0", operands);
+ if (n == 2)
+ output_asm_insn ("add2 %0,%4,%0", operands);
+ else if (n)
+ output_asm_insn ("add %0,%0,%0", operands);
+ }
+ else if (n <= 4)
+ {
+ while (--n >= 0)
+ {
+ output_asm_insn (shift_one, operands);
+ operands[1] = operands[0];
+ }
+ }
+ /* See if we can use a rotate/and. */
+ else if (n == BITS_PER_WORD - 1)
+ {
+ switch (code)
+ {
+ case ASHIFT :
+ output_asm_insn ("and %0,%1,1\n\tror %0,%0", operands);
+ break;
+ case ASHIFTRT :
+ /* The ARC doesn't have a rol insn. Use something else. */
+ output_asm_insn ("add.f 0,%1,%1\n\tsbc %0,%0,%0", operands);
+ break;
+ case LSHIFTRT :
+ /* The ARC doesn't have a rol insn. Use something else. */
+ output_asm_insn ("add.f 0,%1,%1\n\trlc %0,0", operands);
+ break;
+ default:
+ break;
+ }
+ }
+ else if (n == BITS_PER_WORD - 2 && dest_reg_operand (operands[4], SImode))
+ {
+ switch (code)
+ {
+ case ASHIFT :
+ output_asm_insn ("and %0,%1,3\n\tror %0,%0\n\tror %0,%0", operands);
+ break;
+ case ASHIFTRT :
+#if 1 /* Need some scheduling comparisons. */
+ output_asm_insn ("add.f %4,%1,%1\n\tsbc %0,%0,%0\n\t"
+ "add.f 0,%4,%4\n\trlc %0,%0", operands);
+#else
+ output_asm_insn ("add.f %4,%1,%1\n\tbxor %0,%4,31\n\t"
+ "sbc.f %0,%0,%4\n\trlc %0,%0", operands);
+#endif
+ break;
+ case LSHIFTRT :
+#if 1
+ output_asm_insn ("add.f %4,%1,%1\n\trlc %0,0\n\t"
+ "add.f 0,%4,%4\n\trlc %0,%0", operands);
+#else
+ output_asm_insn ("add.f %0,%1,%1\n\trlc.f %0,0\n\t"
+ "and %0,%0,1\n\trlc %0,%0", operands);
+#endif
+ break;
+ default:
+ break;
+ }
+ }
+ else if (n == BITS_PER_WORD - 3 && code == ASHIFT)
+ output_asm_insn ("and %0,%1,7\n\tror %0,%0\n\tror %0,%0\n\tror %0,%0",
+ operands);
+ /* Must loop. */
+ else
+ {
+ operands[2] = GEN_INT (n);
+ output_asm_insn ("mov.f lp_count, %2", operands);
+
+ shiftloop:
+ {
+ output_asm_insn ("lpnz\t2f", operands);
+ output_asm_insn (shift_one, operands);
+ output_asm_insn ("nop", operands);
+ fprintf (asm_out_file, "2:\t%s end single insn loop\n",
+ ASM_COMMENT_START);
+ }
+ }
+ }
+
+ return "";
+}
+
+/* Nested function support. */
+
+/* Directly store VALUE into memory object BLOCK at OFFSET. */
+
+static void
+emit_store_direct (rtx block, int offset, int value)
+{
+ emit_insn (gen_store_direct (adjust_address (block, SImode, offset),
+ force_reg (SImode,
+ gen_int_mode (value, SImode))));
+}
+
+/* Emit RTL insns to initialize the variable parts of a trampoline.
+ FNADDR is an RTX for the address of the function's pure code.
+ CXT is an RTX for the static chain value for the function. */
+/* With potentially multiple shared objects loaded, and multiple stacks
+ present for multiple thereds where trampolines might reside, a simple
+ range check will likely not suffice for the profiler to tell if a callee
+ is a trampoline. We a speedier check by making the trampoline start at
+ an address that is not 4-byte aligned.
+ A trampoline looks like this:
+
+ nop_s 0x78e0
+entry:
+ ld_s r12,[pcl,12] 0xd403
+ ld r11,[pcl,12] 0x170c 700b
+ j_s [r12] 0x7c00
+ nop_s 0x78e0
+
+ The fastest trampoline to execute for trampolines within +-8KB of CTX
+ would be:
+ add2 r11,pcl,s12
+ j [limm] 0x20200f80 limm
+ and that would also be faster to write to the stack by computing the offset
+ from CTX to TRAMP at compile time. However, it would really be better to
+ get rid of the high cost of cache invalidation when generating trampolines,
+ which requires that the code part of trampolines stays constant, and
+ additionally either
+ - making sure that no executable code but trampolines is on the stack,
+ no icache entries linger for the area of the stack from when before the
+ stack was allocated, and allocating trampolines in trampoline-only
+ cache lines
+ or
+ - allocate trampolines fram a special pool of pre-allocated trampolines. */
+
+static void
+arc_initialize_trampoline (rtx tramp, tree fndecl, rtx cxt)
+{
+ rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
+
+ emit_store_direct (tramp, 0, TARGET_BIG_ENDIAN ? 0x78e0d403 : 0xd40378e0);
+ emit_store_direct (tramp, 4, TARGET_BIG_ENDIAN ? 0x170c700b : 0x700b170c);
+ emit_store_direct (tramp, 8, TARGET_BIG_ENDIAN ? 0x7c0078e0 : 0x78e07c00);
+ emit_move_insn (adjust_address (tramp, SImode, 12), fnaddr);
+ emit_move_insn (adjust_address (tramp, SImode, 16), cxt);
+ emit_insn (gen_flush_icache (adjust_address (tramp, SImode, 0)));
+}
+
+/* Allow the profiler to easily distinguish trampolines from normal
+ functions. */
+
+static rtx
+arc_trampoline_adjust_address (rtx addr)
+{
+ return plus_constant (Pmode, addr, 2);
+}
+
+/* This is set briefly to 1 when we output a ".as" address modifer, and then
+ reset when we output the scaled address. */
+static int output_scaled = 0;
+
+/* Print operand X (an rtx) in assembler syntax to file FILE.
+ CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
+ For `%' followed by punctuation, CODE is the punctuation and X is null. */
+/* In final.c:output_asm_insn:
+ 'l' : label
+ 'a' : address
+ 'c' : constant address if CONSTANT_ADDRESS_P
+ 'n' : negative
+ Here:
+ 'Z': log2(x+1)-1
+ 'z': log2
+ 'M': log2(~x)
+ '#': condbranch delay slot suffix
+ '*': jump delay slot suffix
+ '?' : nonjump-insn suffix for conditional execution or short instruction
+ '!' : jump / call suffix for conditional execution or short instruction
+ '`': fold constant inside unary o-perator, re-recognize, and emit.
+ 'd'
+ 'D'
+ 'R': Second word
+ 'S'
+ 'B': Branch comparison operand - suppress sda reference
+ 'H': Most significant word
+ 'L': Least significant word
+ 'A': ASCII decimal representation of floating point value
+ 'U': Load/store update or scaling indicator
+ 'V': cache bypass indicator for volatile
+ 'P'
+ 'F'
+ '^'
+ 'O': Operator
+ 'o': original symbol - no @ prepending. */
+
+void
+arc_print_operand (FILE *file, rtx x, int code)
+{
+ switch (code)
+ {
+ case 'Z':
+ if (GET_CODE (x) == CONST_INT)
+ fprintf (file, "%d",exact_log2(INTVAL (x) + 1) - 1 );
+ else
+ output_operand_lossage ("invalid operand to %%Z code");
+
+ return;
+
+ case 'z':
+ if (GET_CODE (x) == CONST_INT)
+ fprintf (file, "%d",exact_log2(INTVAL (x)) );
+ else
+ output_operand_lossage ("invalid operand to %%z code");
+
+ return;
+
+ case 'M':
+ if (GET_CODE (x) == CONST_INT)
+ fprintf (file, "%d",exact_log2(~INTVAL (x)) );
+ else
+ output_operand_lossage ("invalid operand to %%M code");
+
+ return;
+
+ case '#' :
+ /* Conditional branches depending on condition codes.
+ Note that this is only for branches that were known to depend on
+ condition codes before delay slot scheduling;
+ out-of-range brcc / bbit expansions should use '*'.
+ This distinction is important because of the different
+ allowable delay slot insns and the output of the delay suffix
+ for TARGET_AT_DBR_COND_EXEC. */
+ case '*' :
+ /* Unconditional branches / branches not depending on condition codes.
+ This could also be a CALL_INSN.
+ Output the appropriate delay slot suffix. */
+ if (final_sequence && XVECLEN (final_sequence, 0) != 1)
+ {
+ rtx jump = XVECEXP (final_sequence, 0, 0);
+ rtx delay = XVECEXP (final_sequence, 0, 1);
+
+ /* For TARGET_PAD_RETURN we might have grabbed the delay insn. */
+ if (INSN_DELETED_P (delay))
+ return;
+ if (JUMP_P (jump) && INSN_ANNULLED_BRANCH_P (jump))
+ fputs (INSN_FROM_TARGET_P (delay) ? ".d"
+ : TARGET_AT_DBR_CONDEXEC && code == '#' ? ".d"
+ : get_attr_type (jump) == TYPE_RETURN && code == '#' ? ""
+ : ".nd",
+ file);
+ else
+ fputs (".d", file);
+ }
+ return;
+ case '?' : /* with leading "." */
+ case '!' : /* without leading "." */
+ /* This insn can be conditionally executed. See if the ccfsm machinery
+ says it should be conditionalized.
+ If it shouldn't, we'll check the compact attribute if this insn
+ has a short variant, which may be used depending on code size and
+ alignment considerations. */
+ if (current_insn_predicate)
+ arc_ccfsm_current.cc
+ = get_arc_condition_code (current_insn_predicate);
+ if (ARC_CCFSM_COND_EXEC_P (&arc_ccfsm_current))
+ {
+ /* Is this insn in a delay slot sequence? */
+ if (!final_sequence || XVECLEN (final_sequence, 0) < 2
+ || current_insn_predicate
+ || CALL_P (XVECEXP (final_sequence, 0, 0))
+ || simplejump_p (XVECEXP (final_sequence, 0, 0)))
+ {
+ /* This insn isn't in a delay slot sequence, or conditionalized
+ independently of its position in a delay slot. */
+ fprintf (file, "%s%s",
+ code == '?' ? "." : "",
+ arc_condition_codes[arc_ccfsm_current.cc]);
+ /* If this is a jump, there are still short variants. However,
+ only beq_s / bne_s have the same offset range as b_s,
+ and the only short conditional returns are jeq_s and jne_s. */
+ if (code == '!'
+ && (arc_ccfsm_current.cc == ARC_CC_EQ
+ || arc_ccfsm_current.cc == ARC_CC_NE
+ || 0 /* FIXME: check if branch in 7 bit range. */))
+ output_short_suffix (file);
+ }
+ else if (code == '!') /* Jump with delay slot. */
+ fputs (arc_condition_codes[arc_ccfsm_current.cc], file);
+ else /* An Instruction in a delay slot of a jump or call. */
+ {
+ rtx jump = XVECEXP (final_sequence, 0, 0);
+ rtx insn = XVECEXP (final_sequence, 0, 1);
+
+ /* If the insn is annulled and is from the target path, we need
+ to inverse the condition test. */
+ if (JUMP_P (jump) && INSN_ANNULLED_BRANCH_P (jump))
+ {
+ if (INSN_FROM_TARGET_P (insn))
+ fprintf (file, "%s%s",
+ code == '?' ? "." : "",
+ arc_condition_codes[ARC_INVERSE_CONDITION_CODE (arc_ccfsm_current.cc)]);
+ else
+ fprintf (file, "%s%s",
+ code == '?' ? "." : "",
+ arc_condition_codes[arc_ccfsm_current.cc]);
+ if (arc_ccfsm_current.state == 5)
+ arc_ccfsm_current.state = 0;
+ }
+ else
+ /* This insn is executed for either path, so don't
+ conditionalize it at all. */
+ output_short_suffix (file);
+
+ }
+ }
+ else
+ output_short_suffix (file);
+ return;
+ case'`':
+ /* FIXME: fold constant inside unary operator, re-recognize, and emit. */
+ gcc_unreachable ();
+ case 'd' :
+ fputs (arc_condition_codes[get_arc_condition_code (x)], file);
+ return;
+ case 'D' :
+ fputs (arc_condition_codes[ARC_INVERSE_CONDITION_CODE
+ (get_arc_condition_code (x))],
+ file);
+ return;
+ case 'R' :
+ /* Write second word of DImode or DFmode reference,
+ register or memory. */
+ if (GET_CODE (x) == REG)
+ fputs (reg_names[REGNO (x)+1], file);
+ else if (GET_CODE (x) == MEM)
+ {
+ fputc ('[', file);
+
+ /* Handle possible auto-increment. For PRE_INC / PRE_DEC /
+ PRE_MODIFY, we will have handled the first word already;
+ For POST_INC / POST_DEC / POST_MODIFY, the access to the
+ first word will be done later. In either case, the access
+ to the first word will do the modify, and we only have
+ to add an offset of four here. */
+ if (GET_CODE (XEXP (x, 0)) == PRE_INC
+ || GET_CODE (XEXP (x, 0)) == PRE_DEC
+ || GET_CODE (XEXP (x, 0)) == PRE_MODIFY
+ || GET_CODE (XEXP (x, 0)) == POST_INC
+ || GET_CODE (XEXP (x, 0)) == POST_DEC
+ || GET_CODE (XEXP (x, 0)) == POST_MODIFY)
+ output_address (plus_constant (Pmode, XEXP (XEXP (x, 0), 0), 4));
+ else if (output_scaled)
+ {
+ rtx addr = XEXP (x, 0);
+ int size = GET_MODE_SIZE (GET_MODE (x));
+
+ output_address (plus_constant (Pmode, XEXP (addr, 0),
+ ((INTVAL (XEXP (addr, 1)) + 4)
+ >> (size == 2 ? 1 : 2))));
+ output_scaled = 0;
+ }
+ else
+ output_address (plus_constant (Pmode, XEXP (x, 0), 4));
+ fputc (']', file);
+ }
+ else
+ output_operand_lossage ("invalid operand to %%R code");
+ return;
+ case 'S' :
+ /* FIXME: remove %S option. */
+ break;
+ case 'B' /* Branch or other LIMM ref - must not use sda references. */ :
+ if (CONSTANT_P (x))
+ {
+ output_addr_const (file, x);
+ return;
+ }
+ break;
+ case 'H' :
+ case 'L' :
+ if (GET_CODE (x) == REG)
+ {
+ /* L = least significant word, H = most significant word. */
+ if ((WORDS_BIG_ENDIAN != 0) ^ (code == 'L'))
+ fputs (reg_names[REGNO (x)], file);
+ else
+ fputs (reg_names[REGNO (x)+1], file);
+ }
+ else if (GET_CODE (x) == CONST_INT
+ || GET_CODE (x) == CONST_DOUBLE)
+ {
+ rtx first, second;
+
+ split_double (x, &first, &second);
+
+ if((WORDS_BIG_ENDIAN) == 0)
+ fprintf (file, "0x%08lx",
+ code == 'L' ? INTVAL (first) : INTVAL (second));
+ else
+ fprintf (file, "0x%08lx",
+ code == 'L' ? INTVAL (second) : INTVAL (first));
+
+
+ }
+ else
+ output_operand_lossage ("invalid operand to %%H/%%L code");
+ return;
+ case 'A' :
+ {
+ char str[30];
+
+ gcc_assert (GET_CODE (x) == CONST_DOUBLE
+ && GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT);
+
+ real_to_decimal (str, CONST_DOUBLE_REAL_VALUE (x), sizeof (str), 0, 1);
+ fprintf (file, "%s", str);
+ return;
+ }
+ case 'U' :
+ /* Output a load/store with update indicator if appropriate. */
+ if (GET_CODE (x) == MEM)
+ {
+ rtx addr = XEXP (x, 0);
+ switch (GET_CODE (addr))
+ {
+ case PRE_INC: case PRE_DEC: case PRE_MODIFY:
+ fputs (".a", file); break;
+ case POST_INC: case POST_DEC: case POST_MODIFY:
+ fputs (".ab", file); break;
+ case PLUS:
+ /* Are we using a scaled index? */
+ if (GET_CODE (XEXP (addr, 0)) == MULT)
+ fputs (".as", file);
+ /* Can we use a scaled offset? */
+ else if (CONST_INT_P (XEXP (addr, 1))
+ && GET_MODE_SIZE (GET_MODE (x)) > 1
+ && (!(INTVAL (XEXP (addr, 1))
+ & (GET_MODE_SIZE (GET_MODE (x)) - 1) & 3))
+ /* Does it make a difference? */
+ && !SMALL_INT_RANGE(INTVAL (XEXP (addr, 1)),
+ GET_MODE_SIZE (GET_MODE (x)) - 2, 0))
+ {
+ fputs (".as", file);
+ output_scaled = 1;
+ }
+ break;
+ case REG:
+ break;
+ default:
+ gcc_assert (CONSTANT_P (addr)); break;
+ }
+ }
+ else
+ output_operand_lossage ("invalid operand to %%U code");
+ return;
+ case 'V' :
+ /* Output cache bypass indicator for a load/store insn. Volatile memory
+ refs are defined to use the cache bypass mechanism. */
+ if (GET_CODE (x) == MEM)
+ {
+ if (MEM_VOLATILE_P (x) && !TARGET_VOLATILE_CACHE_SET )
+ fputs (".di", file);
+ }
+ else
+ output_operand_lossage ("invalid operand to %%V code");
+ return;
+ /* plt code. */
+ case 'P':
+ case 0 :
+ /* Do nothing special. */
+ break;
+ case 'F':
+ fputs (reg_names[REGNO (x)]+1, file);
+ return;
+ case '^':
+ /* This punctuation character is needed because label references are
+ printed in the output template using %l. This is a front end
+ character, and when we want to emit a '@' before it, we have to use
+ this '^'. */
+
+ fputc('@',file);
+ return;
+ case 'O':
+ /* Output an operator. */
+ switch (GET_CODE (x))
+ {
+ case PLUS: fputs ("add", file); return;
+ case SS_PLUS: fputs ("adds", file); return;
+ case AND: fputs ("and", file); return;
+ case IOR: fputs ("or", file); return;
+ case XOR: fputs ("xor", file); return;
+ case MINUS: fputs ("sub", file); return;
+ case SS_MINUS: fputs ("subs", file); return;
+ case ASHIFT: fputs ("asl", file); return;
+ case ASHIFTRT: fputs ("asr", file); return;
+ case LSHIFTRT: fputs ("lsr", file); return;
+ case ROTATERT: fputs ("ror", file); return;
+ case MULT: fputs ("mpy", file); return;
+ case ABS: fputs ("abs", file); return; /* Unconditional. */
+ case NEG: fputs ("neg", file); return;
+ case SS_NEG: fputs ("negs", file); return;
+ case NOT: fputs ("not", file); return; /* Unconditional. */
+ case ZERO_EXTEND:
+ fputs ("ext", file); /* bmsk allows predication. */
+ goto size_suffix;
+ case SIGN_EXTEND: /* Unconditional. */
+ fputs ("sex", file);
+ size_suffix:
+ switch (GET_MODE (XEXP (x, 0)))
+ {
+ case QImode: fputs ("b", file); return;
+ case HImode: fputs ("w", file); return;
+ default: break;
+ }
+ break;
+ case SS_TRUNCATE:
+ if (GET_MODE (x) != HImode)
+ break;
+ fputs ("sat16", file);
+ default: break;
+ }
+ output_operand_lossage ("invalid operand to %%O code"); return;
+ case 'o':
+ if (GET_CODE (x) == SYMBOL_REF)
+ {
+ assemble_name (file, XSTR (x, 0));
+ return;
+ }
+ break;
+ case '&':
+ if (TARGET_ANNOTATE_ALIGN && cfun->machine->size_reason)
+ fprintf (file, "; unalign: %d", cfun->machine->unalign);
+ return;
+ default :
+ /* Unknown flag. */
+ output_operand_lossage ("invalid operand output code");
+ }
+
+ switch (GET_CODE (x))
+ {
+ case REG :
+ fputs (reg_names[REGNO (x)], file);
+ break;
+ case MEM :
+ {
+ rtx addr = XEXP (x, 0);
+ int size = GET_MODE_SIZE (GET_MODE (x));
+
+ fputc ('[', file);
+
+ switch (GET_CODE (addr))
+ {
+ case PRE_INC: case POST_INC:
+ output_address (plus_constant (Pmode, XEXP (addr, 0), size)); break;
+ case PRE_DEC: case POST_DEC:
+ output_address (plus_constant (Pmode, XEXP (addr, 0), -size));
+ break;
+ case PRE_MODIFY: case POST_MODIFY:
+ output_address (XEXP (addr, 1)); break;
+ case PLUS:
+ if (output_scaled)
+ {
+ output_address (plus_constant (Pmode, XEXP (addr, 0),
+ (INTVAL (XEXP (addr, 1))
+ >> (size == 2 ? 1 : 2))));
+ output_scaled = 0;
+ }
+ else
+ output_address (addr);
+ break;
+ default:
+ if (flag_pic && CONSTANT_ADDRESS_P (addr))
+ arc_output_pic_addr_const (file, addr, code);
+ else
+ output_address (addr);
+ break;
+ }
+ fputc (']', file);
+ break;
+ }
+ case CONST_DOUBLE :
+ /* We handle SFmode constants here as output_addr_const doesn't. */
+ if (GET_MODE (x) == SFmode)
+ {
+ REAL_VALUE_TYPE d;
+ long l;
+
+ REAL_VALUE_FROM_CONST_DOUBLE (d, x);
+ REAL_VALUE_TO_TARGET_SINGLE (d, l);
+ fprintf (file, "0x%08lx", l);
+ break;
+ }
+ /* Fall through. Let output_addr_const deal with it. */
+ default :
+ if (flag_pic)
+ arc_output_pic_addr_const (file, x, code);
+ else
+ {
+ /* FIXME: Dirty way to handle @var@sda+const. Shd be handled
+ with asm_output_symbol_ref */
+ if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS)
+ {
+ x = XEXP (x, 0);
+ output_addr_const (file, XEXP (x, 0));
+ if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF && SYMBOL_REF_SMALL_P (XEXP (x, 0)))
+ fprintf (file, "@sda");
+
+ if (GET_CODE (XEXP (x, 1)) != CONST_INT
+ || INTVAL (XEXP (x, 1)) >= 0)
+ fprintf (file, "+");
+ output_addr_const (file, XEXP (x, 1));
+ }
+ else
+ output_addr_const (file, x);
+ }
+ if (GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_SMALL_P (x))
+ fprintf (file, "@sda");
+ break;
+ }
+}
+
+/* Print a memory address as an operand to reference that memory location. */
+
+void
+arc_print_operand_address (FILE *file , rtx addr)
+{
+ register rtx base, index = 0;
+
+ switch (GET_CODE (addr))
+ {
+ case REG :
+ fputs (reg_names[REGNO (addr)], file);
+ break;
+ case SYMBOL_REF :
+ output_addr_const (file, addr);
+ if (SYMBOL_REF_SMALL_P (addr))
+ fprintf (file, "@sda");
+ break;
+ case PLUS :
+ if (GET_CODE (XEXP (addr, 0)) == MULT)
+ index = XEXP (XEXP (addr, 0), 0), base = XEXP (addr, 1);
+ else if (CONST_INT_P (XEXP (addr, 0)))
+ index = XEXP (addr, 0), base = XEXP (addr, 1);
+ else
+ base = XEXP (addr, 0), index = XEXP (addr, 1);
+
+ gcc_assert (OBJECT_P (base));
+ arc_print_operand_address (file, base);
+ if (CONSTANT_P (base) && CONST_INT_P (index))
+ fputc ('+', file);
+ else
+ fputc (',', file);
+ gcc_assert (OBJECT_P (index));
+ arc_print_operand_address (file, index);
+ break;
+ case CONST:
+ {
+ rtx c = XEXP (addr, 0);
+
+ gcc_assert (GET_CODE (XEXP (c, 0)) == SYMBOL_REF);
+ gcc_assert (GET_CODE (XEXP (c, 1)) == CONST_INT);
+
+ output_address(XEXP(addr,0));
+
+ break;
+ }
+ case PRE_INC :
+ case PRE_DEC :
+ /* We shouldn't get here as we've lost the mode of the memory object
+ (which says how much to inc/dec by. */
+ gcc_unreachable ();
+ break;
+ default :
+ if (flag_pic)
+ arc_output_pic_addr_const (file, addr, 0);
+ else
+ output_addr_const (file, addr);
+ break;
+ }
+}
+
+/* Called via walk_stores. DATA points to a hash table we can use to
+ establish a unique SYMBOL_REF for each counter, which corresponds to
+ a caller-callee pair.
+ X is a store which we want to examine for an UNSPEC_PROF, which
+ would be an address loaded into a register, or directly used in a MEM.
+ If we found an UNSPEC_PROF, if we encounter a new counter the first time,
+ write out a description and a data allocation for a 32 bit counter.
+ Also, fill in the appropriate symbol_ref into each UNSPEC_PROF instance. */
+
+static void
+write_profile_sections (rtx dest ATTRIBUTE_UNUSED, rtx x, void *data)
+{
+ rtx *srcp, src;
+ htab_t htab = (htab_t) data;
+ rtx *slot;
+
+ if (GET_CODE (x) != SET)
+ return;
+ srcp = &SET_SRC (x);
+ if (MEM_P (*srcp))
+ srcp = &XEXP (*srcp, 0);
+ else if (MEM_P (SET_DEST (x)))
+ srcp = &XEXP (SET_DEST (x), 0);
+ src = *srcp;
+ if (GET_CODE (src) != CONST)
+ return;
+ src = XEXP (src, 0);
+ if (GET_CODE (src) != UNSPEC || XINT (src, 1) != UNSPEC_PROF)
+ return;
+
+ gcc_assert (XVECLEN (src, 0) == 3);
+ if (!htab_elements (htab))
+ {
+ output_asm_insn (".section .__arc_profile_desc, \"a\"\n"
+ "\t.long %0 + 1\n",
+ &XVECEXP (src, 0, 0));
+ }
+ slot = (rtx *) htab_find_slot (htab, src, INSERT);
+ if (*slot == HTAB_EMPTY_ENTRY)
+ {
+ static int count_nr;
+ char buf[24];
+ rtx count;
+
+ *slot = src;
+ sprintf (buf, "__prof_count%d", count_nr++);
+ count = gen_rtx_SYMBOL_REF (Pmode, xstrdup (buf));
+ XVECEXP (src, 0, 2) = count;
+ output_asm_insn (".section\t.__arc_profile_desc, \"a\"\n"
+ "\t.long\t%1\n"
+ "\t.section\t.__arc_profile_counters, \"aw\"\n"
+ "\t.type\t%o2, @object\n"
+ "\t.size\t%o2, 4\n"
+ "%o2:\t.zero 4",
+ &XVECEXP (src, 0, 0));
+ *srcp = count;
+ }
+ else
+ *srcp = XVECEXP (*slot, 0, 2);
+}
+
+/* Hash function for UNSPEC_PROF htab. Use both the caller's name and
+ the callee's name (if known). */
+
+static hashval_t
+unspec_prof_hash (const void *x)
+{
+ const_rtx u = (const_rtx) x;
+ const_rtx s1 = XVECEXP (u, 0, 1);
+
+ return (htab_hash_string (XSTR (XVECEXP (u, 0, 0), 0))
+ ^ (s1->code == SYMBOL_REF ? htab_hash_string (XSTR (s1, 0)) : 0));
+}
+
+/* Equality function for UNSPEC_PROF htab. Two pieces of UNSPEC_PROF rtl
+ shall refer to the same counter if both caller name and callee rtl
+ are identical. */
+
+static int
+unspec_prof_htab_eq (const void *x, const void *y)
+{
+ const_rtx u0 = (const_rtx) x;
+ const_rtx u1 = (const_rtx) y;
+ const_rtx s01 = XVECEXP (u0, 0, 1);
+ const_rtx s11 = XVECEXP (u1, 0, 1);
+
+ return (!strcmp (XSTR (XVECEXP (u0, 0, 0), 0),
+ XSTR (XVECEXP (u1, 0, 0), 0))
+ && rtx_equal_p (s01, s11));
+}
+
+/* Conditional execution support.
+
+ This is based on the ARM port but for now is much simpler.
+
+ A finite state machine takes care of noticing whether or not instructions
+ can be conditionally executed, and thus decrease execution time and code
+ size by deleting branch instructions. The fsm is controlled by
+ arc_ccfsm_advance (called by arc_final_prescan_insn), and controls the
+ actions of PRINT_OPERAND. The patterns in the .md file for the branch
+ insns also have a hand in this. */
+/* The way we leave dealing with non-anulled or annull-false delay slot
+ insns to the consumer is awkward. */
+
+/* The state of the fsm controlling condition codes are:
+ 0: normal, do nothing special
+ 1: don't output this insn
+ 2: don't output this insn
+ 3: make insns conditional
+ 4: make insns conditional
+ 5: make insn conditional (only for outputting anulled delay slot insns)
+
+ special value for cfun->machine->uid_ccfsm_state:
+ 6: return with but one insn before it since function start / call
+
+ State transitions (state->state by whom, under what condition):
+ 0 -> 1 arc_ccfsm_advance, if insn is a conditional branch skipping over
+ some instructions.
+ 0 -> 2 arc_ccfsm_advance, if insn is a conditional branch followed
+ by zero or more non-jump insns and an unconditional branch with
+ the same target label as the condbranch.
+ 1 -> 3 branch patterns, after having not output the conditional branch
+ 2 -> 4 branch patterns, after having not output the conditional branch
+ 0 -> 5 branch patterns, for anulled delay slot insn.
+ 3 -> 0 ASM_OUTPUT_INTERNAL_LABEL, if the `target' label is reached
+ (the target label has CODE_LABEL_NUMBER equal to
+ arc_ccfsm_target_label).
+ 4 -> 0 arc_ccfsm_advance, if `target' unconditional branch is reached
+ 3 -> 1 arc_ccfsm_advance, finding an 'else' jump skipping over some insns.
+ 5 -> 0 when outputting the delay slot insn
+
+ If the jump clobbers the conditions then we use states 2 and 4.
+
+ A similar thing can be done with conditional return insns.
+
+ We also handle separating branches from sets of the condition code.
+ This is done here because knowledge of the ccfsm state is required,
+ we may not be outputting the branch. */
+
+/* arc_final_prescan_insn calls arc_ccfsm_advance to adjust arc_ccfsm_current,
+ before letting final output INSN. */
+
+static void
+arc_ccfsm_advance (rtx insn, struct arc_ccfsm *state)
+{
+ /* BODY will hold the body of INSN. */
+ register rtx body;
+
+ /* This will be 1 if trying to repeat the trick (ie: do the `else' part of
+ an if/then/else), and things need to be reversed. */
+ int reverse = 0;
+
+ /* If we start with a return insn, we only succeed if we find another one. */
+ int seeking_return = 0;
+
+ /* START_INSN will hold the insn from where we start looking. This is the
+ first insn after the following code_label if REVERSE is true. */
+ rtx start_insn = insn;
+
+ /* Type of the jump_insn. Brcc insns don't affect ccfsm changes,
+ since they don't rely on a cmp preceding the. */
+ enum attr_type jump_insn_type;
+
+ /* Allow -mdebug-ccfsm to turn this off so we can see how well it does.
+ We can't do this in macro FINAL_PRESCAN_INSN because its called from
+ final_scan_insn which has `optimize' as a local. */
+ if (optimize < 2 || TARGET_NO_COND_EXEC)
+ return;
+
+ /* Ignore notes and labels. */
+ if (!INSN_P (insn))
+ return;
+ body = PATTERN (insn);
+ /* If in state 4, check if the target branch is reached, in order to
+ change back to state 0. */
+ if (state->state == 4)
+ {
+ if (insn == state->target_insn)
+ {
+ state->target_insn = NULL;
+ state->state = 0;
+ }
+ return;
+ }
+
+ /* If in state 3, it is possible to repeat the trick, if this insn is an
+ unconditional branch to a label, and immediately following this branch
+ is the previous target label which is only used once, and the label this
+ branch jumps to is not too far off. Or in other words "we've done the
+ `then' part, see if we can do the `else' part." */
+ if (state->state == 3)
+ {
+ if (simplejump_p (insn))
+ {
+ start_insn = next_nonnote_insn (start_insn);
+ if (GET_CODE (start_insn) == BARRIER)
+ {
+ /* ??? Isn't this always a barrier? */
+ start_insn = next_nonnote_insn (start_insn);
+ }
+ if (GET_CODE (start_insn) == CODE_LABEL
+ && CODE_LABEL_NUMBER (start_insn) == state->target_label
+ && LABEL_NUSES (start_insn) == 1)
+ reverse = TRUE;
+ else
+ return;
+ }
+ else if (GET_CODE (body) == SIMPLE_RETURN)
+ {
+ start_insn = next_nonnote_insn (start_insn);
+ if (GET_CODE (start_insn) == BARRIER)
+ start_insn = next_nonnote_insn (start_insn);
+ if (GET_CODE (start_insn) == CODE_LABEL
+ && CODE_LABEL_NUMBER (start_insn) == state->target_label
+ && LABEL_NUSES (start_insn) == 1)
+ {
+ reverse = TRUE;
+ seeking_return = 1;
+ }
+ else
+ return;
+ }
+ else
+ return;
+ }
+
+ if (GET_CODE (insn) != JUMP_INSN
+ || GET_CODE (PATTERN (insn)) == ADDR_VEC
+ || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
+ return;
+
+ /* We can't predicate BRCC or loop ends.
+ Also, when generating PIC code, and considering a medium range call,
+ we can't predicate the call. */
+ jump_insn_type = get_attr_type (insn);
+ if (jump_insn_type == TYPE_BRCC
+ || jump_insn_type == TYPE_BRCC_NO_DELAY_SLOT
+ || jump_insn_type == TYPE_LOOP_END
+ || (jump_insn_type == TYPE_CALL && !get_attr_predicable (insn)))
+ return;
+
+ /* This jump might be paralleled with a clobber of the condition codes,
+ the jump should always come first. */
+ if (GET_CODE (body) == PARALLEL && XVECLEN (body, 0) > 0)
+ body = XVECEXP (body, 0, 0);
+
+ if (reverse
+ || (GET_CODE (body) == SET && GET_CODE (SET_DEST (body)) == PC
+ && GET_CODE (SET_SRC (body)) == IF_THEN_ELSE))
+ {
+ int insns_skipped = 0, fail = FALSE, succeed = FALSE;
+ /* Flag which part of the IF_THEN_ELSE is the LABEL_REF. */
+ int then_not_else = TRUE;
+ /* Nonzero if next insn must be the target label. */
+ int next_must_be_target_label_p;
+ rtx this_insn = start_insn, label = 0;
+
+ /* Register the insn jumped to. */
+ if (reverse)
+ {
+ if (!seeking_return)
+ label = XEXP (SET_SRC (body), 0);
+ }
+ else if (GET_CODE (XEXP (SET_SRC (body), 1)) == LABEL_REF)
+ label = XEXP (XEXP (SET_SRC (body), 1), 0);
+ else if (GET_CODE (XEXP (SET_SRC (body), 2)) == LABEL_REF)
+ {
+ label = XEXP (XEXP (SET_SRC (body), 2), 0);
+ then_not_else = FALSE;
+ }
+ else if (GET_CODE (XEXP (SET_SRC (body), 1)) == SIMPLE_RETURN)
+ seeking_return = 1;
+ else if (GET_CODE (XEXP (SET_SRC (body), 2)) == SIMPLE_RETURN)
+ {
+ seeking_return = 1;
+ then_not_else = FALSE;
+ }
+ else
+ gcc_unreachable ();
+
+ /* If this is a non-annulled branch with a delay slot, there is
+ no need to conditionalize the delay slot. */
+ if (NEXT_INSN (PREV_INSN (insn)) != insn
+ && state->state == 0 && !INSN_ANNULLED_BRANCH_P (insn))
+ {
+ this_insn = NEXT_INSN (this_insn);
+ gcc_assert (NEXT_INSN (NEXT_INSN (PREV_INSN (start_insn)))
+ == NEXT_INSN (this_insn));
+ }
+ /* See how many insns this branch skips, and what kind of insns. If all
+ insns are okay, and the label or unconditional branch to the same
+ label is not too far away, succeed. */
+ for (insns_skipped = 0, next_must_be_target_label_p = FALSE;
+ !fail && !succeed && insns_skipped < MAX_INSNS_SKIPPED;
+ insns_skipped++)
+ {
+ rtx scanbody;
+
+ this_insn = next_nonnote_insn (this_insn);
+ if (!this_insn)
+ break;
+
+ if (next_must_be_target_label_p)
+ {
+ if (GET_CODE (this_insn) == BARRIER)
+ continue;
+ if (GET_CODE (this_insn) == CODE_LABEL
+ && this_insn == label)
+ {
+ state->state = 1;
+ succeed = TRUE;
+ }
+ else
+ fail = TRUE;
+ break;
+ }
+
+ scanbody = PATTERN (this_insn);
+
+ switch (GET_CODE (this_insn))
+ {
+ case CODE_LABEL:
+ /* Succeed if it is the target label, otherwise fail since
+ control falls in from somewhere else. */
+ if (this_insn == label)
+ {
+ state->state = 1;
+ succeed = TRUE;
+ }
+ else
+ fail = TRUE;
+ break;
+
+ case BARRIER:
+ /* Succeed if the following insn is the target label.
+ Otherwise fail.
+ If return insns are used then the last insn in a function
+ will be a barrier. */
+ next_must_be_target_label_p = TRUE;
+ break;
+
+ case CALL_INSN:
+ /* Can handle a call insn if there are no insns after it.
+ IE: The next "insn" is the target label. We don't have to
+ worry about delay slots as such insns are SEQUENCE's inside
+ INSN's. ??? It is possible to handle such insns though. */
+ if (get_attr_cond (this_insn) == COND_CANUSE)
+ next_must_be_target_label_p = TRUE;
+ else
+ fail = TRUE;
+ break;
+
+ case JUMP_INSN:
+ /* If this is an unconditional branch to the same label, succeed.
+ If it is to another label, do nothing. If it is conditional,
+ fail. */
+ /* ??? Probably, the test for the SET and the PC are
+ unnecessary. */
+
+ if (GET_CODE (scanbody) == SET
+ && GET_CODE (SET_DEST (scanbody)) == PC)
+ {
+ if (GET_CODE (SET_SRC (scanbody)) == LABEL_REF
+ && XEXP (SET_SRC (scanbody), 0) == label && !reverse)
+ {
+ state->state = 2;
+ succeed = TRUE;
+ }
+ else if (GET_CODE (SET_SRC (scanbody)) == IF_THEN_ELSE)
+ fail = TRUE;
+ else if (get_attr_cond (this_insn) != COND_CANUSE)
+ fail = TRUE;
+ }
+ else if (GET_CODE (scanbody) == SIMPLE_RETURN
+ && seeking_return)
+ {
+ state->state = 2;
+ succeed = TRUE;
+ }
+ else if (GET_CODE (scanbody) == PARALLEL)
+ {
+ if (get_attr_cond (this_insn) != COND_CANUSE)
+ fail = TRUE;
+ }
+ break;
+
+ case INSN:
+ /* We can only do this with insns that can use the condition
+ codes (and don't set them). */
+ if (GET_CODE (scanbody) == SET
+ || GET_CODE (scanbody) == PARALLEL)
+ {
+ if (get_attr_cond (this_insn) != COND_CANUSE)
+ fail = TRUE;
+ }
+ /* We can't handle other insns like sequences. */
+ else
+ fail = TRUE;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (succeed)
+ {
+ if ((!seeking_return) && (state->state == 1 || reverse))
+ state->target_label = CODE_LABEL_NUMBER (label);
+ else if (seeking_return || state->state == 2)
+ {
+ while (this_insn && GET_CODE (PATTERN (this_insn)) == USE)
+ {
+ this_insn = next_nonnote_insn (this_insn);
+
+ gcc_assert (!this_insn ||
+ (GET_CODE (this_insn) != BARRIER
+ && GET_CODE (this_insn) != CODE_LABEL));
+ }
+ if (!this_insn)
+ {
+ /* Oh dear! we ran off the end, give up. */
+ extract_insn_cached (insn);
+ state->state = 0;
+ state->target_insn = NULL;
+ return;
+ }
+ state->target_insn = this_insn;
+ }
+ else
+ gcc_unreachable ();
+
+ /* If REVERSE is true, ARM_CURRENT_CC needs to be inverted from
+ what it was. */
+ if (!reverse)
+ {
+ state->cond = XEXP (SET_SRC (body), 0);
+ state->cc = get_arc_condition_code (XEXP (SET_SRC (body), 0));
+ }
+
+ if (reverse || then_not_else)
+ state->cc = ARC_INVERSE_CONDITION_CODE (state->cc);
+ }
+
+ /* Restore recog_operand. Getting the attributes of other insns can
+ destroy this array, but final.c assumes that it remains intact
+ across this call; since the insn has been recognized already we
+ call insn_extract direct. */
+ extract_insn_cached (insn);
+ }
+}
+
+/* Record that we are currently outputting label NUM with prefix PREFIX.
+ It it's the label we're looking for, reset the ccfsm machinery.
+
+ Called from ASM_OUTPUT_INTERNAL_LABEL. */
+
+static void
+arc_ccfsm_at_label (const char *prefix, int num, struct arc_ccfsm *state)
+{
+ if (state->state == 3 && state->target_label == num
+ && !strcmp (prefix, "L"))
+ {
+ state->state = 0;
+ state->target_insn = NULL_RTX;
+ }
+}
+
+/* We are considering a conditional branch with the condition COND.
+ Check if we want to conditionalize a delay slot insn, and if so modify
+ the ccfsm state accordingly.
+ REVERSE says branch will branch when the condition is false. */
+void
+arc_ccfsm_record_condition (rtx cond, bool reverse, rtx jump,
+ struct arc_ccfsm *state)
+{
+ rtx seq_insn = NEXT_INSN (PREV_INSN (jump));
+ if (!state)
+ state = &arc_ccfsm_current;
+
+ gcc_assert (state->state == 0);
+ if (seq_insn != jump)
+ {
+ rtx insn = XVECEXP (PATTERN (seq_insn), 0, 1);
+
+ if (!INSN_DELETED_P (insn)
+ && INSN_ANNULLED_BRANCH_P (jump)
+ && (TARGET_AT_DBR_CONDEXEC || INSN_FROM_TARGET_P (insn)))
+ {
+ state->cond = cond;
+ state->cc = get_arc_condition_code (cond);
+ if (!reverse)
+ arc_ccfsm_current.cc
+ = ARC_INVERSE_CONDITION_CODE (state->cc);
+ rtx pat = PATTERN (insn);
+ if (GET_CODE (pat) == COND_EXEC)
+ gcc_assert ((INSN_FROM_TARGET_P (insn)
+ ? ARC_INVERSE_CONDITION_CODE (state->cc) : state->cc)
+ == get_arc_condition_code (XEXP (pat, 0)));
+ else
+ state->state = 5;
+ }
+ }
+}
+
+/* Update *STATE as we would when we emit INSN. */
+
+static void
+arc_ccfsm_post_advance (rtx insn, struct arc_ccfsm *state)
+{
+ enum attr_type type;
+
+ if (LABEL_P (insn))
+ arc_ccfsm_at_label ("L", CODE_LABEL_NUMBER (insn), state);
+ else if (JUMP_P (insn)
+ && GET_CODE (PATTERN (insn)) != ADDR_VEC
+ && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC
+ && ((type = get_attr_type (insn)) == TYPE_BRANCH
+ || (type == TYPE_UNCOND_BRANCH
+ /* ??? Maybe should also handle TYPE_RETURN here,
+ but we don't have a testcase for that. */
+ && ARC_CCFSM_BRANCH_DELETED_P (state))))
+ {
+ if (ARC_CCFSM_BRANCH_DELETED_P (state))
+ ARC_CCFSM_RECORD_BRANCH_DELETED (state);
+ else
+ {
+ rtx src = SET_SRC (PATTERN (insn));
+ arc_ccfsm_record_condition (XEXP (src, 0), XEXP (src, 1) == pc_rtx,
+ insn, state);
+ }
+ }
+ else if (arc_ccfsm_current.state == 5)
+ arc_ccfsm_current.state = 0;
+}
+
+/* Return true if the current insn, which is a conditional branch, is to be
+ deleted. */
+
+bool
+arc_ccfsm_branch_deleted_p (void)
+{
+ return ARC_CCFSM_BRANCH_DELETED_P (&arc_ccfsm_current);
+}
+
+/* Record a branch isn't output because subsequent insns can be
+ conditionalized. */
+
+void
+arc_ccfsm_record_branch_deleted (void)
+{
+ ARC_CCFSM_RECORD_BRANCH_DELETED (&arc_ccfsm_current);
+}
+
+/* During insn output, indicate if the current insn is predicated. */
+
+bool
+arc_ccfsm_cond_exec_p (void)
+{
+ return (cfun->machine->prescan_initialized
+ && ARC_CCFSM_COND_EXEC_P (&arc_ccfsm_current));
+}
+
+/* Like next_active_insn, but return NULL if we find an ADDR_(DIFF_)VEC,
+ and look inside SEQUENCEs. */
+
+static rtx
+arc_next_active_insn (rtx insn, struct arc_ccfsm *statep)
+{
+ rtx pat;
+
+ do
+ {
+ if (statep)
+ arc_ccfsm_post_advance (insn, statep);
+ insn = NEXT_INSN (insn);
+ if (!insn || BARRIER_P (insn))
+ return NULL_RTX;
+ if (statep)
+ arc_ccfsm_advance (insn, statep);
+ }
+ while (NOTE_P (insn)
+ || (cfun->machine->arc_reorg_started
+ && LABEL_P (insn) && !label_to_alignment (insn))
+ || (NONJUMP_INSN_P (insn)
+ && (GET_CODE (PATTERN (insn)) == USE
+ || GET_CODE (PATTERN (insn)) == CLOBBER)));
+ if (!LABEL_P (insn))
+ {
+ gcc_assert (INSN_P (insn));
+ pat = PATTERN (insn);
+ if (GET_CODE (pat) == ADDR_VEC || GET_CODE (pat) == ADDR_DIFF_VEC)
+ return NULL_RTX;
+ if (GET_CODE (pat) == SEQUENCE)
+ return XVECEXP (pat, 0, 0);
+ }
+ return insn;
+}
+
+/* When deciding if an insn should be output short, we want to know something
+ about the following insns:
+ - if another insn follows which we know we can output as a short insn
+ before an alignment-sensitive point, we can output this insn short:
+ the decision about the eventual alignment can be postponed.
+ - if a to-be-aligned label comes next, we should output this insn such
+ as to get / preserve 4-byte alignment.
+ - if a likely branch without delay slot insn, or a call with an immediately
+ following short insn comes next, we should out output this insn such as to
+ get / preserve 2 mod 4 unalignment.
+ - do the same for a not completely unlikely branch with a short insn
+ following before any other branch / label.
+ - in order to decide if we are actually looking at a branch, we need to
+ call arc_ccfsm_advance.
+ - in order to decide if we are looking at a short insn, we should know
+ if it is conditionalized. To a first order of approximation this is
+ the case if the state from arc_ccfsm_advance from before this insn
+ indicates the insn is conditionalized. However, a further refinement
+ could be to not conditionalize an insn if the destination register(s)
+ is/are dead in the non-executed case. */
+/* Return non-zero if INSN should be output as a short insn. UNALIGN is
+ zero if the current insn is aligned to a 4-byte-boundary, two otherwise.
+ If CHECK_ATTR is greater than 0, check the iscompact attribute first. */
+
+int
+arc_verify_short (rtx insn, int, int check_attr)
+{
+ enum attr_iscompact iscompact;
+ struct machine_function *machine;
+
+ if (check_attr > 0)
+ {
+ iscompact = get_attr_iscompact (insn);
+ if (iscompact == ISCOMPACT_FALSE)
+ return 0;
+ }
+ machine = cfun->machine;
+
+ if (machine->force_short_suffix >= 0)
+ return machine->force_short_suffix;
+
+ return (get_attr_length (insn) & 2) != 0;
+}
+
+/* When outputting an instruction (alternative) that can potentially be short,
+ output the short suffix if the insn is in fact short, and update
+ cfun->machine->unalign accordingly. */
+
+static void
+output_short_suffix (FILE *file)
+{
+ rtx insn = current_output_insn;
+
+ if (arc_verify_short (insn, cfun->machine->unalign, 1))
+ {
+ fprintf (file, "_s");
+ cfun->machine->unalign ^= 2;
+ }
+ /* Restore recog_operand. */
+ extract_insn_cached (insn);
+}
+
+/* Implement FINAL_PRESCAN_INSN. */
+
+void
+arc_final_prescan_insn (rtx insn, rtx *opvec ATTRIBUTE_UNUSED,
+ int noperands ATTRIBUTE_UNUSED)
+{
+ if (TARGET_DUMPISIZE)
+ fprintf (asm_out_file, "\n; at %04x\n", INSN_ADDRESSES (INSN_UID (insn)));
+
+ /* Output a nop if necessary to prevent a hazard.
+ Don't do this for delay slots: inserting a nop would
+ alter semantics, and the only time we would find a hazard is for a
+ call function result - and in that case, the hazard is spurious to
+ start with. */
+ if (PREV_INSN (insn)
+ && PREV_INSN (NEXT_INSN (insn)) == insn
+ && arc_hazard (prev_real_insn (insn), insn))
+ {
+ current_output_insn =
+ emit_insn_before (gen_nop (), NEXT_INSN (PREV_INSN (insn)));
+ final_scan_insn (current_output_insn, asm_out_file, optimize, 1, NULL);
+ current_output_insn = insn;
+ }
+ /* Restore extraction data which might have been clobbered by arc_hazard. */
+ extract_constrain_insn_cached (insn);
+
+ if (!cfun->machine->prescan_initialized)
+ {
+ /* Clear lingering state from branch shortening. */
+ memset (&arc_ccfsm_current, 0, sizeof arc_ccfsm_current);
+ cfun->machine->prescan_initialized = 1;
+ }
+ arc_ccfsm_advance (insn, &arc_ccfsm_current);
+
+ cfun->machine->size_reason = 0;
+}
+
+/* Given FROM and TO register numbers, say whether this elimination is allowed.
+ Frame pointer elimination is automatically handled.
+
+ All eliminations are permissible. If we need a frame
+ pointer, we must eliminate ARG_POINTER_REGNUM into
+ FRAME_POINTER_REGNUM and not into STACK_POINTER_REGNUM. */
+
+static bool
+arc_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
+{
+ return to == FRAME_POINTER_REGNUM || !arc_frame_pointer_required ();
+}
+
+/* Define the offset between two registers, one to be eliminated, and
+ the other its replacement, at the start of a routine. */
+
+int
+arc_initial_elimination_offset (int from, int to)
+{
+ if (! cfun->machine->frame_info.initialized)
+ arc_compute_frame_size (get_frame_size ());
+
+ if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
+ {
+ return (cfun->machine->frame_info.extra_size
+ + cfun->machine->frame_info.reg_size);
+ }
+
+ if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
+ {
+ return (cfun->machine->frame_info.total_size
+ - cfun->machine->frame_info.pretend_size);
+ }
+
+ if ((from == FRAME_POINTER_REGNUM) && (to == STACK_POINTER_REGNUM))
+ {
+ return (cfun->machine->frame_info.total_size
+ - (cfun->machine->frame_info.pretend_size
+ + cfun->machine->frame_info.extra_size
+ + cfun->machine->frame_info.reg_size));
+ }
+
+ gcc_unreachable ();
+}
+
+static bool
+arc_frame_pointer_required (void)
+{
+ return cfun->calls_alloca;
+}
+
+
+/* Return the destination address of a branch. */
+
+int
+branch_dest (rtx branch)
+{
+ rtx pat = PATTERN (branch);
+ rtx dest = (GET_CODE (pat) == PARALLEL
+ ? SET_SRC (XVECEXP (pat, 0, 0)) : SET_SRC (pat));
+ int dest_uid;
+
+ if (GET_CODE (dest) == IF_THEN_ELSE)
+ dest = XEXP (dest, XEXP (dest, 1) == pc_rtx ? 2 : 1);
+
+ dest = XEXP (dest, 0);
+ dest_uid = INSN_UID (dest);
+
+ return INSN_ADDRESSES (dest_uid);
+}
+
+
+/* Implement TARGET_ENCODE_SECTION_INFO hook. */
+
+static void
+arc_encode_section_info (tree decl, rtx rtl, int first)
+{
+ /* For sdata, SYMBOL_FLAG_LOCAL and SYMBOL_FLAG_FUNCTION.
+ This clears machine specific flags, so has to come first. */
+ default_encode_section_info (decl, rtl, first);
+
+ /* Check if it is a function, and whether it has the
+ [long/medium/short]_call attribute specified. */
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ {
+ rtx symbol = XEXP (rtl, 0);
+ int flags = SYMBOL_REF_FLAGS (symbol);
+
+ tree attr = (TREE_TYPE (decl) != error_mark_node
+ ? TYPE_ATTRIBUTES (TREE_TYPE (decl)) : NULL_TREE);
+ tree long_call_attr = lookup_attribute ("long_call", attr);
+ tree medium_call_attr = lookup_attribute ("medium_call", attr);
+ tree short_call_attr = lookup_attribute ("short_call", attr);
+
+ if (long_call_attr != NULL_TREE)
+ flags |= SYMBOL_FLAG_LONG_CALL;
+ else if (medium_call_attr != NULL_TREE)
+ flags |= SYMBOL_FLAG_MEDIUM_CALL;
+ else if (short_call_attr != NULL_TREE)
+ flags |= SYMBOL_FLAG_SHORT_CALL;
+
+ SYMBOL_REF_FLAGS (symbol) = flags;
+ }
+}
+
+/* This is how to output a definition of an internal numbered label where
+ PREFIX is the class of label and NUM is the number within the class. */
+
+static void arc_internal_label (FILE *stream, const char *prefix, unsigned long labelno)
+{
+ if (cfun)
+ arc_ccfsm_at_label (prefix, labelno, &arc_ccfsm_current);
+ default_internal_label (stream, prefix, labelno);
+}
+
+/* Set the cpu type and print out other fancy things,
+ at the top of the file. */
+
+static void arc_file_start (void)
+{
+ default_file_start ();
+ fprintf (asm_out_file, "\t.cpu %s\n", arc_cpu_string);
+}
+
+/* Cost functions. */
+
+/* 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. */
+
+static bool
+arc_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
+ int *total, bool speed)
+{
+ switch (code)
+ {
+ /* Small integers are as cheap as registers. */
+ case CONST_INT:
+ {
+ bool nolimm = false; /* Can we do without long immediate? */
+ bool fast = false; /* Is the result available immediately? */
+ bool condexec = false; /* Does this allow conditiobnal execution? */
+ bool compact = false; /* Is a 16 bit opcode available? */
+ /* CONDEXEC also implies that we can have an unconditional
+ 3-address operation. */
+
+ nolimm = compact = condexec = false;
+ if (UNSIGNED_INT6 (INTVAL (x)))
+ nolimm = condexec = compact = true;
+ else
+ {
+ if (SMALL_INT (INTVAL (x)))
+ nolimm = fast = true;
+ switch (outer_code)
+ {
+ case AND: /* bclr, bmsk, ext[bw] */
+ if (satisfies_constraint_Ccp (x) /* bclr */
+ || satisfies_constraint_C1p (x) /* bmsk */)
+ nolimm = fast = condexec = compact = true;
+ break;
+ case IOR: /* bset */
+ if (satisfies_constraint_C0p (x)) /* bset */
+ nolimm = fast = condexec = compact = true;
+ break;
+ case XOR:
+ if (satisfies_constraint_C0p (x)) /* bxor */
+ nolimm = fast = condexec = true;
+ break;
+ case SET:
+ if (satisfies_constraint_Crr (x)) /* ror b,u6 */
+ nolimm = true;
+ default:
+ break;
+ }
+ }
+ /* FIXME: Add target options to attach a small cost if
+ condexec / compact is not true. */
+ if (nolimm)
+ {
+ *total = 0;
+ return true;
+ }
+ }
+ /* FALLTHRU */
+
+ /* 4 byte values can be fetched as immediate constants -
+ let's give that the cost of an extra insn. */
+ case CONST:
+ case LABEL_REF:
+ case SYMBOL_REF:
+ *total = COSTS_N_INSNS (1);
+ return true;
+
+ case CONST_DOUBLE:
+ {
+ rtx high, low;
+
+ if (TARGET_DPFP)
+ {
+ *total = COSTS_N_INSNS (1);
+ return true;
+ }
+ /* FIXME: correct the order of high,low */
+ split_double (x, &high, &low);
+ *total = COSTS_N_INSNS (!SMALL_INT (INTVAL (high))
+ + !SMALL_INT (INTVAL (low)));
+ return true;
+ }
+
+ /* Encourage synth_mult to find a synthetic multiply when reasonable.
+ If we need more than 12 insns to do a multiply, then go out-of-line,
+ since the call overhead will be < 10% of the cost of the multiply. */
+ case ASHIFT:
+ case ASHIFTRT:
+ case LSHIFTRT:
+ if (TARGET_BARREL_SHIFTER)
+ {
+ /* If we want to shift a constant, we need a LIMM. */
+ /* ??? when the optimizers want to know if a constant should be
+ hoisted, they ask for the cost of the constant. OUTER_CODE is
+ insufficient context for shifts since we don't know which operand
+ we are looking at. */
+ if (CONSTANT_P (XEXP (x, 0)))
+ {
+ *total += (COSTS_N_INSNS (2)
+ + rtx_cost (XEXP (x, 1), (enum rtx_code) code, 0, speed));
+ return true;
+ }
+ *total = COSTS_N_INSNS (1);
+ }
+ else if (GET_CODE (XEXP (x, 1)) != CONST_INT)
+ *total = COSTS_N_INSNS (16);
+ else
+ {
+ *total = COSTS_N_INSNS (INTVAL (XEXP ((x), 1)));
+ /* ??? want_to_gcse_p can throw negative shift counts at us,
+ and then panics when it gets a negative cost as result.
+ Seen for gcc.c-torture/compile/20020710-1.c -Os . */
+ if (*total < 0)
+ *total = 0;
+ }
+ return false;
+
+ case DIV:
+ case UDIV:
+ if (speed)
+ *total = COSTS_N_INSNS(30);
+ else
+ *total = COSTS_N_INSNS(1);
+ return false;
+
+ case MULT:
+ if ((TARGET_DPFP && GET_MODE (x) == DFmode))
+ *total = COSTS_N_INSNS (1);
+ else if (speed)
+ *total= arc_multcost;
+ /* We do not want synth_mult sequences when optimizing
+ for size. */
+ else if (TARGET_MUL64_SET || (TARGET_ARC700 && !TARGET_NOMPY_SET))
+ *total = COSTS_N_INSNS (1);
+ else
+ *total = COSTS_N_INSNS (2);
+ return false;
+ case PLUS:
+ if (GET_CODE (XEXP (x, 0)) == MULT
+ && _2_4_8_operand (XEXP (XEXP (x, 0), 1), VOIDmode))
+ {
+ *total += (rtx_cost (XEXP (x, 1), PLUS, 0, speed)
+ + rtx_cost (XEXP (XEXP (x, 0), 0), PLUS, 1, speed));
+ return true;
+ }
+ return false;
+ case MINUS:
+ if (GET_CODE (XEXP (x, 1)) == MULT
+ && _2_4_8_operand (XEXP (XEXP (x, 1), 1), VOIDmode))
+ {
+ *total += (rtx_cost (XEXP (x, 0), PLUS, 0, speed)
+ + rtx_cost (XEXP (XEXP (x, 1), 0), PLUS, 1, speed));
+ return true;
+ }
+ return false;
+ case COMPARE:
+ {
+ rtx op0 = XEXP (x, 0);
+ rtx op1 = XEXP (x, 1);
+
+ if (GET_CODE (op0) == ZERO_EXTRACT && op1 == const0_rtx
+ && XEXP (op0, 1) == const1_rtx)
+ {
+ /* btst / bbit0 / bbit1:
+ Small integers and registers are free; everything else can
+ be put in a register. */
+ *total = (rtx_cost (XEXP (op0, 0), SET, 1, speed)
+ + rtx_cost (XEXP (op0, 2), SET, 1, speed));
+ return true;
+ }
+ if (GET_CODE (op0) == AND && op1 == const0_rtx
+ && satisfies_constraint_C1p (XEXP (op0, 1)))
+ {
+ /* bmsk.f */
+ *total = rtx_cost (XEXP (op0, 0), SET, 1, speed);
+ return true;
+ }
+ /* add.f */
+ if (GET_CODE (op1) == NEG)
+ {
+ /* op0 might be constant, the inside of op1 is rather
+ unlikely to be so. So swapping the operands might lower
+ the cost. */
+ *total = (rtx_cost (op0, PLUS, 1, speed)
+ + rtx_cost (XEXP (op1, 0), PLUS, 0, speed));
+ }
+ return false;
+ }
+ case EQ: case NE:
+ if (outer_code == IF_THEN_ELSE
+ && GET_CODE (XEXP (x, 0)) == ZERO_EXTRACT
+ && XEXP (x, 1) == const0_rtx
+ && XEXP (XEXP (x, 0), 1) == const1_rtx)
+ {
+ /* btst / bbit0 / bbit1:
+ Small integers and registers are free; everything else can
+ be put in a register. */
+ rtx op0 = XEXP (x, 0);
+
+ *total = (rtx_cost (XEXP (op0, 0), SET, 1, speed)
+ + rtx_cost (XEXP (op0, 2), SET, 1, speed));
+ return true;
+ }
+ /* Fall through. */
+ /* scc_insn expands into two insns. */
+ case GTU: case GEU: case LEU:
+ if (GET_MODE (x) == SImode)
+ *total += COSTS_N_INSNS (1);
+ return false;
+ case LTU: /* might use adc. */
+ if (GET_MODE (x) == SImode)
+ *total += COSTS_N_INSNS (1) - 1;
+ return false;
+ default:
+ return false;
+ }
+}
+
+/* Return true if ADDR is an address that needs to be expressed as an
+ explicit sum of pcl + offset. */
+
+bool
+arc_legitimate_pc_offset_p (rtx addr)
+{
+ if (GET_CODE (addr) != CONST)
+ return false;
+ addr = XEXP (addr, 0);
+ if (GET_CODE (addr) == PLUS)
+ {
+ if (GET_CODE (XEXP (addr, 1)) != CONST_INT)
+ return false;
+ addr = XEXP (addr, 0);
+ }
+ return (GET_CODE (addr) == UNSPEC
+ && XVECLEN (addr, 0) == 1
+ && XINT (addr, 1) == ARC_UNSPEC_GOT
+ && GET_CODE (XVECEXP (addr, 0, 0)) == SYMBOL_REF);
+}
+
+/* Return true if ADDR is a valid pic address.
+ A valid pic address on arc should look like
+ const (unspec (SYMBOL_REF/LABEL) (ARC_UNSPEC_GOTOFF/ARC_UNSPEC_GOT)) */
+
+bool
+arc_legitimate_pic_addr_p (rtx addr)
+{
+ if (GET_CODE (addr) == LABEL_REF)
+ return true;
+ if (GET_CODE (addr) != CONST)
+ return false;
+
+ addr = XEXP (addr, 0);
+
+
+ if (GET_CODE (addr) == PLUS)
+ {
+ if (GET_CODE (XEXP (addr, 1)) != CONST_INT)
+ return false;
+ addr = XEXP (addr, 0);
+ }
+
+ if (GET_CODE (addr) != UNSPEC
+ || XVECLEN (addr, 0) != 1)
+ return false;
+
+ /* Must be @GOT or @GOTOFF. */
+ if (XINT (addr, 1) != ARC_UNSPEC_GOT
+ && XINT (addr, 1) != ARC_UNSPEC_GOTOFF)
+ return false;
+
+ if (GET_CODE (XVECEXP (addr, 0, 0)) != SYMBOL_REF
+ && GET_CODE (XVECEXP (addr, 0, 0)) != LABEL_REF)
+ return false;
+
+ return true;
+}
+
+
+
+/* Return true if OP contains a symbol reference. */
+
+static bool
+symbolic_reference_mentioned_p (rtx op)
+{
+ register const char *fmt;
+ register int i;
+
+ if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF)
+ return true;
+
+ fmt = GET_RTX_FORMAT (GET_CODE (op));
+ for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
+ {
+ if (fmt[i] == 'E')
+ {
+ register int j;
+
+ for (j = XVECLEN (op, i) - 1; j >= 0; j--)
+ if (symbolic_reference_mentioned_p (XVECEXP (op, i, j)))
+ return true;
+ }
+
+ else if (fmt[i] == 'e' && symbolic_reference_mentioned_p (XEXP (op, i)))
+ return true;
+ }
+
+ return false;
+}
+
+/* Return true if OP contains a SYMBOL_REF that is not wrapped in an unspec.
+ If SKIP_LOCAL is true, skip symbols that bind locally.
+ This is used further down in this file, and, without SKIP_LOCAL,
+ in the addsi3 / subsi3 expanders when generating PIC code. */
+
+bool
+arc_raw_symbolic_reference_mentioned_p (rtx op, bool skip_local)
+{
+ register const char *fmt;
+ register int i;
+
+ if (GET_CODE(op) == UNSPEC)
+ return false;
+
+ if (GET_CODE (op) == SYMBOL_REF)
+ {
+ tree decl = SYMBOL_REF_DECL (op);
+ return !skip_local || !decl || !default_binds_local_p (decl);
+ }
+
+ fmt = GET_RTX_FORMAT (GET_CODE (op));
+ for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
+ {
+ if (fmt[i] == 'E')
+ {
+ register int j;
+
+ for (j = XVECLEN (op, i) - 1; j >= 0; j--)
+ if (arc_raw_symbolic_reference_mentioned_p (XVECEXP (op, i, j),
+ skip_local))
+ return true;
+ }
+
+ else if (fmt[i] == 'e'
+ && arc_raw_symbolic_reference_mentioned_p (XEXP (op, i),
+ skip_local))
+ return true;
+ }
+
+ return false;
+}
+
+/* Legitimize a pic address reference in ORIG.
+ The return value is the legitimated address.
+ If OLDX is non-zero, it is the target to assign the address to first. */
+
+rtx
+arc_legitimize_pic_address (rtx orig, rtx oldx)
+{
+ rtx addr = orig;
+ rtx pat = orig;
+ rtx base;
+
+ if (oldx == orig)
+ oldx = NULL;
+
+ if (GET_CODE (addr) == LABEL_REF)
+ ; /* Do nothing. */
+ else if (GET_CODE (addr) == SYMBOL_REF
+ && (CONSTANT_POOL_ADDRESS_P (addr)
+ || SYMBOL_REF_LOCAL_P (addr)))
+ {
+ /* This symbol may be referenced via a displacement from the PIC
+ base address (@GOTOFF). */
+
+ /* FIXME: if we had a way to emit pc-relative adds that don't
+ create a GOT entry, we could do without the use of the gp register. */
+ crtl->uses_pic_offset_table = 1;
+ pat = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), ARC_UNSPEC_GOTOFF);
+ pat = gen_rtx_CONST (Pmode, pat);
+ pat = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, pat);
+
+ if (oldx == NULL)
+ oldx = gen_reg_rtx (Pmode);
+
+ if (oldx != 0)
+ {
+ emit_move_insn (oldx, pat);
+ pat = oldx;
+ }
+
+ }
+ else if (GET_CODE (addr) == SYMBOL_REF)
+ {
+ /* This symbol must be referenced via a load from the
+ Global Offset Table (@GOTPC). */
+
+ pat = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), ARC_UNSPEC_GOT);
+ pat = gen_rtx_CONST (Pmode, pat);
+ pat = gen_const_mem (Pmode, pat);
+
+ if (oldx == 0)
+ oldx = gen_reg_rtx (Pmode);
+
+ emit_move_insn (oldx, pat);
+ pat = oldx;
+ }
+ else
+ {
+ if (GET_CODE (addr) == CONST)
+ {
+ addr = XEXP (addr, 0);
+ if (GET_CODE (addr) == UNSPEC)
+ {
+ /* Check that the unspec is one of the ones we generate? */
+ }
+ else
+ gcc_assert (GET_CODE (addr) == PLUS);
+ }
+
+ if (GET_CODE (addr) == PLUS)
+ {
+ rtx op0 = XEXP (addr, 0), op1 = XEXP (addr, 1);
+
+ /* Check first to see if this is a constant offset from a @GOTOFF
+ symbol reference. */
+ if ((GET_CODE (op0) == LABEL_REF
+ || (GET_CODE (op0) == SYMBOL_REF
+ && (CONSTANT_POOL_ADDRESS_P (op0)
+ || SYMBOL_REF_LOCAL_P (op0))))
+ && GET_CODE (op1) == CONST_INT)
+ {
+ /* FIXME: like above, could do without gp reference. */
+ crtl->uses_pic_offset_table = 1;
+ pat
+ = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op0), ARC_UNSPEC_GOTOFF);
+ pat = gen_rtx_PLUS (Pmode, pat, op1);
+ pat = gen_rtx_CONST (Pmode, pat);
+ pat = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, pat);
+
+ if (oldx != 0)
+ {
+ emit_move_insn (oldx, pat);
+ pat = oldx;
+ }
+ }
+ else
+ {
+ base = arc_legitimize_pic_address (XEXP (addr, 0), oldx);
+ pat = arc_legitimize_pic_address (XEXP (addr, 1),
+ base == oldx ? NULL_RTX : oldx);
+
+ if (GET_CODE (pat) == CONST_INT)
+ pat = plus_constant (Pmode, base, INTVAL (pat));
+ else
+ {
+ if (GET_CODE (pat) == PLUS && CONSTANT_P (XEXP (pat, 1)))
+ {
+ base = gen_rtx_PLUS (Pmode, base, XEXP (pat, 0));
+ pat = XEXP (pat, 1);
+ }
+ pat = gen_rtx_PLUS (Pmode, base, pat);
+ }
+ }
+ }
+ }
+
+ return pat;
+}
+
+/* Output address constant X to FILE, taking PIC into account. */
+
+void
+arc_output_pic_addr_const (FILE * file, rtx x, int code)
+{
+ char buf[256];
+
+ restart:
+ switch (GET_CODE (x))
+ {
+ case PC:
+ if (flag_pic)
+ putc ('.', file);
+ else
+ gcc_unreachable ();
+ break;
+
+ case SYMBOL_REF:
+ output_addr_const (file, x);
+
+ /* Local functions do not get references through the PLT. */
+ if (code == 'P' && ! SYMBOL_REF_LOCAL_P (x))
+ fputs ("@plt", file);
+ break;
+
+ case LABEL_REF:
+ ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (XEXP (x, 0)));
+ assemble_name (file, buf);
+ break;
+
+ case CODE_LABEL:
+ ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
+ assemble_name (file, buf);
+ break;
+
+ case CONST_INT:
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
+ break;
+
+ case CONST:
+ arc_output_pic_addr_const (file, XEXP (x, 0), code);
+ break;
+
+ case CONST_DOUBLE:
+ if (GET_MODE (x) == VOIDmode)
+ {
+ /* We can use %d if the number is one word and positive. */
+ if (CONST_DOUBLE_HIGH (x))
+ fprintf (file, HOST_WIDE_INT_PRINT_DOUBLE_HEX,
+ CONST_DOUBLE_HIGH (x), CONST_DOUBLE_LOW (x));
+ else if (CONST_DOUBLE_LOW (x) < 0)
+ fprintf (file, HOST_WIDE_INT_PRINT_HEX, CONST_DOUBLE_LOW (x));
+ else
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC, CONST_DOUBLE_LOW (x));
+ }
+ else
+ /* We can't handle floating point constants;
+ PRINT_OPERAND must handle them. */
+ output_operand_lossage ("floating constant misused");
+ break;
+
+ case PLUS:
+ /* FIXME: Not needed here. */
+ /* Some assemblers need integer constants to appear last (eg masm). */
+ if (GET_CODE (XEXP (x, 0)) == CONST_INT)
+ {
+ arc_output_pic_addr_const (file, XEXP (x, 1), code);
+ fprintf (file, "+");
+ arc_output_pic_addr_const (file, XEXP (x, 0), code);
+ }
+ else if (GET_CODE (XEXP (x, 1)) == CONST_INT)
+ {
+ arc_output_pic_addr_const (file, XEXP (x, 0), code);
+ if (INTVAL (XEXP (x, 1)) >= 0)
+ fprintf (file, "+");
+ arc_output_pic_addr_const (file, XEXP (x, 1), code);
+ }
+ else
+ gcc_unreachable();
+ break;
+
+ case MINUS:
+ /* Avoid outputting things like x-x or x+5-x,
+ since some assemblers can't handle that. */
+ x = simplify_subtraction (x);
+ if (GET_CODE (x) != MINUS)
+ goto restart;
+
+ arc_output_pic_addr_const (file, XEXP (x, 0), code);
+ fprintf (file, "-");
+ if (GET_CODE (XEXP (x, 1)) == CONST_INT
+ && INTVAL (XEXP (x, 1)) < 0)
+ {
+ fprintf (file, "(");
+ arc_output_pic_addr_const (file, XEXP (x, 1), code);
+ fprintf (file, ")");
+ }
+ else
+ arc_output_pic_addr_const (file, XEXP (x, 1), code);
+ break;
+
+ case ZERO_EXTEND:
+ case SIGN_EXTEND:
+ arc_output_pic_addr_const (file, XEXP (x, 0), code);
+ break;
+
+
+ case UNSPEC:
+ gcc_assert (XVECLEN (x, 0) == 1);
+ if (XINT (x, 1) == ARC_UNSPEC_GOT)
+ fputs ("pcl,", file);
+ arc_output_pic_addr_const (file, XVECEXP (x, 0, 0), code);
+ switch (XINT (x, 1))
+ {
+ case ARC_UNSPEC_GOT:
+ fputs ("@gotpc", file);
+ break;
+ case ARC_UNSPEC_GOTOFF:
+ fputs ("@gotoff", file);
+ break;
+ case ARC_UNSPEC_PLT:
+ fputs ("@plt", file);
+ break;
+ default:
+ output_operand_lossage ("invalid UNSPEC as operand: %d", XINT (x,1));
+ break;
+ }
+ break;
+
+ default:
+ output_operand_lossage ("invalid expression as operand");
+ }
+}
+
+#define SYMBOLIC_CONST(X) \
+(GET_CODE (X) == SYMBOL_REF \
+ || GET_CODE (X) == LABEL_REF \
+ || (GET_CODE (X) == CONST && symbolic_reference_mentioned_p (X)))
+
+/* Emit insns to move operands[1] into operands[0]. */
+
+void
+emit_pic_move (rtx *operands, enum machine_mode)
+{
+ rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
+
+ if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1]))
+ operands[1] = force_reg (Pmode, operands[1]);
+ else
+ operands[1] = arc_legitimize_pic_address (operands[1], temp);
+}
+
+
+/* The function returning the number of words, at the beginning of an
+ argument, must be put in registers. The returned value must be
+ zero for arguments that are passed entirely in registers or that
+ are entirely pushed on the stack.
+
+ On some machines, certain arguments must be passed partially in
+ registers and partially in memory. On these machines, typically
+ the first N words of arguments are passed in registers, and the
+ rest on the stack. If a multi-word argument (a `double' or a
+ structure) crosses that boundary, its first few words must be
+ passed in registers and the rest must be pushed. This function
+ tells the compiler when this occurs, and how many of the words
+ should go in registers.
+
+ `FUNCTION_ARG' for these arguments should return the first register
+ to be used by the caller for this argument; likewise
+ `FUNCTION_INCOMING_ARG', for the called function.
+
+ The function is used to implement macro FUNCTION_ARG_PARTIAL_NREGS. */
+
+/* If REGNO is the least arg reg available then what is the total number of arg
+ regs available. */
+#define GPR_REST_ARG_REGS(REGNO) \
+ ((REGNO) <= MAX_ARC_PARM_REGS ? MAX_ARC_PARM_REGS - (REGNO) : 0 )
+
+/* Since arc parm regs are contiguous. */
+#define ARC_NEXT_ARG_REG(REGNO) ( (REGNO) + 1 )
+
+/* Implement TARGET_ARG_PARTIAL_BYTES. */
+
+static int
+arc_arg_partial_bytes (cumulative_args_t cum_v, enum machine_mode mode,
+ tree type, bool named ATTRIBUTE_UNUSED)
+{
+ CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
+ int bytes = (mode == BLKmode
+ ? int_size_in_bytes (type) : (int) GET_MODE_SIZE (mode));
+ int words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
+ int arg_num = *cum;
+ int ret;
+
+ arg_num = ROUND_ADVANCE_CUM (arg_num, mode, type);
+ ret = GPR_REST_ARG_REGS (arg_num);
+
+ /* ICEd at function.c:2361, and ret is copied to data->partial */
+ ret = (ret >= words ? 0 : ret * UNITS_PER_WORD);
+
+ return ret;
+}
+
+
+
+/* This function is used to control a function argument is passed in a
+ register, and which register.
+
+ The arguments are CUM, of type CUMULATIVE_ARGS, which summarizes
+ (in a way defined by INIT_CUMULATIVE_ARGS and FUNCTION_ARG_ADVANCE)
+ all of the previous arguments so far passed in registers; MODE, the
+ machine mode of the argument; TYPE, the data type of the argument
+ as a tree node or 0 if that is not known (which happens for C
+ support library functions); and NAMED, which is 1 for an ordinary
+ argument and 0 for nameless arguments that correspond to `...' in
+ the called function's prototype.
+
+ The returned value should either be a `reg' RTX for the hard
+ register in which to pass the argument, or zero to pass the
+ argument on the stack.
+
+ For machines like the Vax and 68000, where normally all arguments
+ are pushed, zero suffices as a definition.
+
+ The usual way to make the ANSI library `stdarg.h' work on a machine
+ where some arguments are usually passed in registers, is to cause
+ nameless arguments to be passed on the stack instead. This is done
+ by making the function return 0 whenever NAMED is 0.
+
+ You may use the macro `MUST_PASS_IN_STACK (MODE, TYPE)' in the
+ definition of this function to determine if this argument is of a
+ type that must be passed in the stack. If `REG_PARM_STACK_SPACE'
+ is not defined and the function returns non-zero for such an
+ argument, the compiler will abort. If `REG_PARM_STACK_SPACE' is
+ defined, the argument will be computed in the stack and then loaded
+ into a register.
+
+ The function is used to implement macro FUNCTION_ARG. */
+/* On the ARC the first MAX_ARC_PARM_REGS args are normally in registers
+ and the rest are pushed. */
+
+static rtx
+arc_function_arg (cumulative_args_t cum_v, enum machine_mode mode,
+ const_tree type ATTRIBUTE_UNUSED, bool named ATTRIBUTE_UNUSED)
+{
+ CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
+ int arg_num = *cum;
+ rtx ret;
+ const char *debstr ATTRIBUTE_UNUSED;
+
+ arg_num = ROUND_ADVANCE_CUM (arg_num, mode, type);
+ /* Return a marker for use in the call instruction. */
+ if (mode == VOIDmode)
+ {
+ ret = const0_rtx;
+ debstr = "<0>";
+ }
+ else if (GPR_REST_ARG_REGS (arg_num) > 0)
+ {
+ ret = gen_rtx_REG (mode, arg_num);
+ debstr = reg_names [arg_num];
+ }
+ else
+ {
+ ret = NULL_RTX;
+ debstr = "memory";
+ }
+ return ret;
+}
+
+/* The function to update the summarizer variable *CUM to advance past
+ an argument in the argument list. The values MODE, TYPE and NAMED
+ describe that argument. Once this is done, the variable *CUM is
+ suitable for analyzing the *following* argument with
+ `FUNCTION_ARG', etc.
+
+ This function need not do anything if the argument in question was
+ passed on the stack. The compiler knows how to track the amount of
+ stack space used for arguments without any special help.
+
+ The function is used to implement macro FUNCTION_ARG_ADVANCE. */
+/* For the ARC: the cum set here is passed on to function_arg where we
+ look at its value and say which reg to use. Strategy: advance the
+ regnumber here till we run out of arg regs, then set *cum to last
+ reg. In function_arg, since *cum > last arg reg we would return 0
+ and thus the arg will end up on the stack. For straddling args of
+ course function_arg_partial_nregs will come into play. */
+
+static void
+arc_function_arg_advance (cumulative_args_t cum_v, enum machine_mode mode,
+ const_tree type, bool named ATTRIBUTE_UNUSED)
+{
+ CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
+ int bytes = (mode == BLKmode
+ ? int_size_in_bytes (type) : (int) GET_MODE_SIZE (mode));
+ int words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
+ int i;
+
+ if (words)
+ *cum = ROUND_ADVANCE_CUM (*cum, mode, type);
+ for (i = 0; i < words; i++)
+ *cum = ARC_NEXT_ARG_REG (*cum);
+
+}
+
+/* Define how to find the value returned by a function.
+ VALTYPE is the data type of the value (as a tree).
+ If the precise function being called is known, FN_DECL_OR_TYPE is its
+ FUNCTION_DECL; otherwise, FN_DECL_OR_TYPE is its type. */
+
+static rtx
+arc_function_value (const_tree valtype,
+ const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
+ bool outgoing ATTRIBUTE_UNUSED)
+{
+ enum machine_mode mode = TYPE_MODE (valtype);
+ int unsignedp ATTRIBUTE_UNUSED;
+
+ unsignedp = TYPE_UNSIGNED (valtype);
+ if (INTEGRAL_TYPE_P (valtype) || TREE_CODE (valtype) == OFFSET_TYPE)
+ PROMOTE_MODE (mode, unsignedp, valtype);
+ return gen_rtx_REG (mode, 0);
+}
+
+/* Returns the return address that is used by builtin_return_address. */
+
+rtx
+arc_return_addr_rtx (int count, ATTRIBUTE_UNUSED rtx frame)
+{
+ if (count != 0)
+ return const0_rtx;
+
+ return get_hard_reg_initial_val (Pmode , RETURN_ADDR_REGNUM);
+}
+
+/* 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. */
+
+bool
+arc_legitimate_pic_operand_p (rtx x)
+{
+ return !arc_raw_symbolic_reference_mentioned_p (x, true);
+}
+
+/* Determine if a given RTX is a valid constant. We already know this
+ satisfies CONSTANT_P. */
+
+bool
+arc_legitimate_constant_p (enum machine_mode, rtx x)
+{
+ if (!flag_pic)
+ return true;
+
+ switch (GET_CODE (x))
+ {
+ case CONST:
+ x = XEXP (x, 0);
+
+ if (GET_CODE (x) == PLUS)
+ {
+ if (GET_CODE (XEXP (x, 1)) != CONST_INT)
+ return false;
+ x = XEXP (x, 0);
+ }
+
+ /* Only some unspecs are valid as "constants". */
+ if (GET_CODE (x) == UNSPEC)
+ switch (XINT (x, 1))
+ {
+ case ARC_UNSPEC_PLT:
+ case ARC_UNSPEC_GOTOFF:
+ case ARC_UNSPEC_GOT:
+ case UNSPEC_PROF:
+ return true;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ /* We must have drilled down to a symbol. */
+ if (arc_raw_symbolic_reference_mentioned_p (x, false))
+ return false;
+
+ /* Return true. */
+ break;
+
+ case LABEL_REF:
+ case SYMBOL_REF:
+ return false;
+
+ default:
+ break;
+ }
+
+ /* Otherwise we handle everything else in the move patterns. */
+ return true;
+}
+
+static bool
+arc_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
+{
+ if (RTX_OK_FOR_BASE_P (x, strict))
+ return true;
+ if (LEGITIMATE_OFFSET_ADDRESS_P (mode, x, TARGET_INDEXED_LOADS, strict))
+ return true;
+ if (LEGITIMATE_SCALED_ADDRESS_P (mode, x, strict))
+ return true;
+ if (LEGITIMATE_SMALL_DATA_ADDRESS_P (x))
+ return true;
+ if (GET_CODE (x) == CONST_INT && LARGE_INT (INTVAL (x)))
+ return true;
+ if ((GET_MODE_SIZE (mode) != 16)
+ && (GET_CODE (x) == SYMBOL_REF
+ || GET_CODE (x) == LABEL_REF
+ || GET_CODE (x) == CONST))
+ {
+ if (!flag_pic || arc_legitimate_pic_addr_p (x))
+ return true;
+ }
+ if ((GET_CODE (x) == PRE_DEC || GET_CODE (x) == PRE_INC
+ || GET_CODE (x) == POST_DEC || GET_CODE (x) == POST_INC)
+ && RTX_OK_FOR_BASE_P (XEXP (x, 0), strict))
+ return true;
+ /* We're restricted here by the `st' insn. */
+ if ((GET_CODE (x) == PRE_MODIFY || GET_CODE (x) == POST_MODIFY)
+ && GET_CODE (XEXP ((x), 1)) == PLUS
+ && rtx_equal_p (XEXP ((x), 0), XEXP (XEXP (x, 1), 0))
+ && LEGITIMATE_OFFSET_ADDRESS_P (QImode, XEXP (x, 1),
+ TARGET_AUTO_MODIFY_REG, strict))
+ return true;
+ return false;
+}
+
+/* Return true iff ADDR (a legitimate address expression)
+ has an effect that depends on the machine mode it is used for. */
+
+static bool
+arc_mode_dependent_address_p (const_rtx addr, addr_space_t)
+{
+ /* SYMBOL_REF is not mode dependent: it is either a small data reference,
+ which is valid for loads and stores, or a limm offset, which is valid for
+ loads. */
+ /* Scaled indices are scaled by the access mode; likewise for scaled
+ offsets, which are needed for maximum offset stores. */
+ if (GET_CODE (addr) == PLUS
+ && (GET_CODE (XEXP ((addr), 0)) == MULT
+ || (CONST_INT_P (XEXP ((addr), 1))
+ && !SMALL_INT (INTVAL (XEXP ((addr), 1))))))
+ return true;
+ return false;
+}
+
+/* Determine if it's legal to put X into the constant pool. */
+
+static bool
+arc_cannot_force_const_mem (enum machine_mode mode, rtx x)
+{
+ return !arc_legitimate_constant_p (mode, x);
+}
+
+
+/* Generic function to define a builtin. */
+#define def_mbuiltin(MASK, NAME, TYPE, CODE) \
+ do \
+ { \
+ if (MASK) \
+ add_builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, NULL, NULL_TREE); \
+ } \
+ while (0)
+
+
+static void
+arc_init_builtins (void)
+{
+ tree endlink = void_list_node;
+
+ tree void_ftype_void
+ = build_function_type (void_type_node,
+ endlink);
+
+ tree int_ftype_int
+ = build_function_type (integer_type_node,
+ tree_cons (NULL_TREE, integer_type_node, endlink));
+
+ tree pcvoid_type_node
+ = build_pointer_type (build_qualified_type (void_type_node, TYPE_QUAL_CONST));
+ tree int_ftype_pcvoid_int
+ = build_function_type (integer_type_node,
+ tree_cons (NULL_TREE, pcvoid_type_node,
+ tree_cons (NULL_TREE, integer_type_node,
+ endlink)));
+
+ tree int_ftype_short_int
+ = build_function_type (integer_type_node,
+ tree_cons (NULL_TREE, short_integer_type_node, endlink));
+
+ tree void_ftype_int_int
+ = build_function_type (void_type_node,
+ tree_cons (NULL_TREE, integer_type_node,
+ tree_cons (NULL_TREE, integer_type_node, endlink)));
+ tree void_ftype_usint_usint
+ = build_function_type (void_type_node,
+ tree_cons (NULL_TREE, long_unsigned_type_node,
+ tree_cons (NULL_TREE, long_unsigned_type_node, endlink)));
+
+ tree int_ftype_int_int
+ = build_function_type (integer_type_node,
+ tree_cons (NULL_TREE, integer_type_node,
+ tree_cons (NULL_TREE, integer_type_node, endlink)));
+
+ tree usint_ftype_usint
+ = build_function_type (long_unsigned_type_node,
+ tree_cons (NULL_TREE, long_unsigned_type_node, endlink));
+
+ tree void_ftype_usint
+ = build_function_type (void_type_node,
+ tree_cons (NULL_TREE, long_unsigned_type_node, endlink));
+
+ /* Add the builtins. */
+ def_mbuiltin (1,"__builtin_arc_nop", void_ftype_void, ARC_BUILTIN_NOP);
+ def_mbuiltin (TARGET_NORM, "__builtin_arc_norm", int_ftype_int, ARC_BUILTIN_NORM);
+ def_mbuiltin (TARGET_NORM, "__builtin_arc_normw", int_ftype_short_int, ARC_BUILTIN_NORMW);
+ def_mbuiltin (TARGET_SWAP, "__builtin_arc_swap", int_ftype_int, ARC_BUILTIN_SWAP);
+ def_mbuiltin (TARGET_MUL64_SET,"__builtin_arc_mul64", void_ftype_int_int, ARC_BUILTIN_MUL64);
+ def_mbuiltin (TARGET_MUL64_SET,"__builtin_arc_mulu64", void_ftype_usint_usint, ARC_BUILTIN_MULU64);
+ def_mbuiltin (1,"__builtin_arc_rtie", void_ftype_void, ARC_BUILTIN_RTIE);
+ def_mbuiltin (TARGET_ARC700,"__builtin_arc_sync", void_ftype_void, ARC_BUILTIN_SYNC);
+ def_mbuiltin ((TARGET_EA_SET),"__builtin_arc_divaw", int_ftype_int_int, ARC_BUILTIN_DIVAW);
+ def_mbuiltin (1,"__builtin_arc_brk", void_ftype_void, ARC_BUILTIN_BRK);
+ def_mbuiltin (1,"__builtin_arc_flag", void_ftype_usint, ARC_BUILTIN_FLAG);
+ def_mbuiltin (1,"__builtin_arc_sleep", void_ftype_usint, ARC_BUILTIN_SLEEP);
+ def_mbuiltin (1,"__builtin_arc_swi", void_ftype_void, ARC_BUILTIN_SWI);
+ def_mbuiltin (1,"__builtin_arc_core_read", usint_ftype_usint, ARC_BUILTIN_CORE_READ);
+ def_mbuiltin (1,"__builtin_arc_core_write", void_ftype_usint_usint, ARC_BUILTIN_CORE_WRITE);
+ def_mbuiltin (1,"__builtin_arc_lr", usint_ftype_usint, ARC_BUILTIN_LR);
+ def_mbuiltin (1,"__builtin_arc_sr", void_ftype_usint_usint, ARC_BUILTIN_SR);
+ def_mbuiltin (TARGET_ARC700,"__builtin_arc_trap_s", void_ftype_usint, ARC_BUILTIN_TRAP_S);
+ def_mbuiltin (TARGET_ARC700,"__builtin_arc_unimp_s", void_ftype_void, ARC_BUILTIN_UNIMP_S);
+ def_mbuiltin (1,"__builtin_arc_aligned", int_ftype_pcvoid_int, ARC_BUILTIN_ALIGNED);
+
+ if (TARGET_SIMD_SET)
+ arc_init_simd_builtins ();
+}
+
+static rtx arc_expand_simd_builtin (tree, rtx, rtx, enum machine_mode, int);
+
+/* Expand an expression EXP that calls a built-in function,
+ with result going to TARGET if that's convenient
+ (and in mode MODE if that's convenient).
+ SUBTARGET may be used as the target for computing one of EXP's operands.
+ IGNORE is nonzero if the value is to be ignored. */
+
+static rtx
+arc_expand_builtin (tree exp,
+ rtx target,
+ rtx subtarget,
+ enum machine_mode mode,
+ int ignore)
+{
+ tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
+ tree arg0;
+ tree arg1;
+ rtx op0;
+ rtx op1;
+ int fcode = DECL_FUNCTION_CODE (fndecl);
+ int icode;
+ enum machine_mode mode0;
+ enum machine_mode mode1;
+
+ if (fcode > ARC_SIMD_BUILTIN_BEGIN && fcode < ARC_SIMD_BUILTIN_END)
+ return arc_expand_simd_builtin (exp, target, subtarget, mode, ignore);
+
+ switch (fcode)
+ {
+ case ARC_BUILTIN_NOP:
+ emit_insn (gen_nop ());
+ return NULL_RTX;
+
+ case ARC_BUILTIN_NORM:
+ icode = CODE_FOR_clrsbsi2;
+ arg0 = CALL_EXPR_ARG (exp, 0);
+ op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
+ mode0 = insn_data[icode].operand[1].mode;
+ target = gen_reg_rtx (SImode);
+
+ if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
+ op0 = copy_to_mode_reg (mode0, op0);
+
+ emit_insn (gen_clrsbsi2 (target, op0));
+ return target;
+
+ case ARC_BUILTIN_NORMW:
+
+ /* FIXME : This should all be HImode, not SImode. */
+ icode = CODE_FOR_normw;
+ arg0 = CALL_EXPR_ARG (exp, 0);
+ op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
+ mode0 = insn_data[icode].operand[1].mode;
+ target = gen_reg_rtx (SImode);
+
+ if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
+ op0 = copy_to_mode_reg (mode0, convert_to_mode (mode0, op0,0));
+
+ emit_insn (gen_normw (target, op0));
+ return target;
+
+ case ARC_BUILTIN_MUL64:
+ icode = CODE_FOR_mul64;
+ arg0 = CALL_EXPR_ARG (exp, 0);
+ arg1 = CALL_EXPR_ARG (exp, 1);
+ op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
+ op1 = expand_expr (arg1, NULL_RTX, VOIDmode, EXPAND_NORMAL);
+
+ mode0 = insn_data[icode].operand[0].mode;
+ mode1 = insn_data[icode].operand[1].mode;
+
+ if (! (*insn_data[icode].operand[0].predicate) (op0, mode0))
+ op0 = copy_to_mode_reg (mode0, op0);
+
+ if (! (*insn_data[icode].operand[1].predicate) (op1, mode1))
+ op1 = copy_to_mode_reg (mode1, op1);
+
+ emit_insn (gen_mul64 (op0,op1));
+ return NULL_RTX;
+
+ case ARC_BUILTIN_MULU64:
+ icode = CODE_FOR_mulu64;
+ arg0 = CALL_EXPR_ARG (exp, 0);
+ arg1 = CALL_EXPR_ARG (exp, 1);
+ op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
+ op1 = expand_expr (arg1, NULL_RTX, VOIDmode, EXPAND_NORMAL);
+
+ mode0 = insn_data[icode].operand[0].mode;
+ mode1 = insn_data[icode].operand[1].mode;
+
+ if (! (*insn_data[icode].operand[0].predicate) (op0, mode0))
+ op0 = copy_to_mode_reg (mode0, op0);
+
+ if (! (*insn_data[icode].operand[0].predicate) (op1, mode1))
+ op1 = copy_to_mode_reg (mode1, op1);
+
+ emit_insn (gen_mulu64 (op0,op1));
+ return NULL_RTX;
+
+ case ARC_BUILTIN_RTIE:
+ icode = CODE_FOR_rtie;
+ emit_insn (gen_rtie (const1_rtx));
+ return NULL_RTX;
+
+ case ARC_BUILTIN_SYNC:
+ icode = CODE_FOR_sync;
+ emit_insn (gen_sync (const1_rtx));
+ return NULL_RTX;
+
+ case ARC_BUILTIN_SWAP:
+ icode = CODE_FOR_swap;
+ arg0 = CALL_EXPR_ARG (exp, 0);
+ op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
+ mode0 = insn_data[icode].operand[1].mode;
+ target = gen_reg_rtx (SImode);
+
+ if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
+ op0 = copy_to_mode_reg (mode0, op0);
+
+ emit_insn (gen_swap (target, op0));
+ return target;
+
+ case ARC_BUILTIN_DIVAW:
+ icode = CODE_FOR_divaw;
+ arg0 = CALL_EXPR_ARG (exp, 0);
+ arg1 = CALL_EXPR_ARG (exp, 1);
+
+ op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
+ op1 = expand_expr (arg1, NULL_RTX, VOIDmode, EXPAND_NORMAL);
+ target = gen_reg_rtx (SImode);
+
+ mode0 = insn_data[icode].operand[0].mode;
+ mode1 = insn_data[icode].operand[1].mode;
+
+ if (! (*insn_data[icode].operand[0].predicate) (op0, mode0))
+ op0 = copy_to_mode_reg (mode0, op0);
+
+ if (! (*insn_data[icode].operand[1].predicate) (op1, mode1))
+ op1 = copy_to_mode_reg (mode1, op1);
+
+ emit_insn (gen_divaw (target, op0, op1));
+ return target;
+
+ case ARC_BUILTIN_BRK:
+ icode = CODE_FOR_brk;
+ emit_insn (gen_brk (const1_rtx));
+ return NULL_RTX;
+
+ case ARC_BUILTIN_SLEEP:
+ icode = CODE_FOR_sleep;
+ arg0 = CALL_EXPR_ARG (exp, 0);
+
+ fold (arg0);
+
+ op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
+ mode0 = insn_data[icode].operand[1].mode;
+
+ emit_insn (gen_sleep (op0));
+ return NULL_RTX;
+
+ case ARC_BUILTIN_SWI:
+ icode = CODE_FOR_swi;
+ emit_insn (gen_swi (const1_rtx));
+ return NULL_RTX;
+
+ case ARC_BUILTIN_FLAG:
+ icode = CODE_FOR_flag;
+ arg0 = CALL_EXPR_ARG (exp, 0);
+ op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
+ mode0 = insn_data[icode].operand[0].mode;
+
+ if (! (*insn_data[icode].operand[0].predicate) (op0, mode0))
+ op0 = copy_to_mode_reg (mode0, op0);
+
+ emit_insn (gen_flag (op0));
+ return NULL_RTX;
+
+ case ARC_BUILTIN_CORE_READ:
+ icode = CODE_FOR_core_read;
+ arg0 = CALL_EXPR_ARG (exp, 0);
+ target = gen_reg_rtx (SImode);
+
+ fold (arg0);
+
+ op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
+ mode0 = insn_data[icode].operand[1].mode;
+
+ emit_insn (gen_core_read (target, op0));
+ return target;
+
+ case ARC_BUILTIN_CORE_WRITE:
+ icode = CODE_FOR_core_write;
+ arg0 = CALL_EXPR_ARG (exp, 0);
+ arg1 = CALL_EXPR_ARG (exp, 1);
+
+ fold (arg1);
+
+ op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
+ op1 = expand_expr (arg1, NULL_RTX, VOIDmode, EXPAND_NORMAL);
+
+ mode0 = insn_data[icode].operand[0].mode;
+ mode1 = insn_data[icode].operand[1].mode;
+
+ emit_insn (gen_core_write (op0, op1));
+ return NULL_RTX;
+
+ case ARC_BUILTIN_LR:
+ icode = CODE_FOR_lr;
+ arg0 = CALL_EXPR_ARG (exp, 0);
+ target = gen_reg_rtx (SImode);
+
+ fold (arg0);
+
+ op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
+ mode0 = insn_data[icode].operand[1].mode;
+
+ emit_insn (gen_lr (target, op0));
+ return target;
+
+ case ARC_BUILTIN_SR:
+ icode = CODE_FOR_sr;
+ arg0 = CALL_EXPR_ARG (exp, 0);
+ arg1 = CALL_EXPR_ARG (exp, 1);
+
+ fold (arg1);
+
+ op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
+ op1 = expand_expr (arg1, NULL_RTX, VOIDmode, EXPAND_NORMAL);
+
+ mode0 = insn_data[icode].operand[0].mode;
+ mode1 = insn_data[icode].operand[1].mode;
+
+ emit_insn (gen_sr (op0, op1));
+ return NULL_RTX;
+
+ case ARC_BUILTIN_TRAP_S:
+ icode = CODE_FOR_trap_s;
+ arg0 = CALL_EXPR_ARG (exp, 0);
+
+ fold (arg0);
+
+ op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
+ mode0 = insn_data[icode].operand[1].mode;
+
+ /* We don't give an error for non-cost values here because
+ we still want to allow things to be fixed up by later inlining /
+ constant folding / dead code elimination. */
+ if (CONST_INT_P (op0) && !satisfies_constraint_L (op0))
+ {
+ /* Keep this message in sync with the one in arc.md:trap_s,
+ because *.md files don't get scanned by exgettext. */
+ error ("operand to trap_s should be an unsigned 6-bit value");
+ }
+ emit_insn (gen_trap_s (op0));
+ return NULL_RTX;
+
+ case ARC_BUILTIN_UNIMP_S:
+ icode = CODE_FOR_unimp_s;
+ emit_insn (gen_unimp_s (const1_rtx));
+ return NULL_RTX;
+
+ case ARC_BUILTIN_ALIGNED:
+ /* __builtin_arc_aligned (void* val, int alignval) */
+ arg0 = CALL_EXPR_ARG (exp, 0);
+ arg1 = CALL_EXPR_ARG (exp, 1);
+ fold (arg1);
+ op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
+ op1 = expand_expr (arg1, NULL_RTX, VOIDmode, EXPAND_NORMAL);
+ target = gen_reg_rtx (SImode);
+
+ if (!CONST_INT_P (op1))
+ {
+ /* If we can't fold the alignment to a constant integer
+ whilst optimizing, this is probably a user error. */
+ if (optimize)
+ warning (0, "__builtin_arc_aligned with non-constant alignment");
+ }
+ else
+ {
+ HOST_WIDE_INT alignTest = INTVAL (op1);
+ /* Check alignTest is positive, and a power of two. */
+ if (alignTest <= 0 || alignTest != (alignTest & -alignTest))
+ {
+ error ("invalid alignment value for __builtin_arc_aligned");
+ return NULL_RTX;
+ }
+
+ if (CONST_INT_P (op0))
+ {
+ HOST_WIDE_INT pnt = INTVAL (op0);
+
+ if ((pnt & (alignTest - 1)) == 0)
+ return const1_rtx;
+ }
+ else
+ {
+ unsigned align = get_pointer_alignment (arg0);
+ unsigned numBits = alignTest * BITS_PER_UNIT;
+
+ if (align && align >= numBits)
+ return const1_rtx;
+ /* Another attempt to ascertain alignment. Check the type
+ we are pointing to. */
+ if (POINTER_TYPE_P (TREE_TYPE (arg0))
+ && TYPE_ALIGN (TREE_TYPE (TREE_TYPE (arg0))) >= numBits)
+ return const1_rtx;
+ }
+ }
+
+ /* Default to false. */
+ return const0_rtx;
+
+ default:
+ break;
+ }
+
+ /* @@@ Should really do something sensible here. */
+ return NULL_RTX;
+}
+
+/* Returns true if the operands[opno] is a valid compile-time constant to be
+ used as register number in the code for builtins. Else it flags an error
+ and returns false. */
+
+bool
+check_if_valid_regno_const (rtx *operands, int opno)
+{
+
+ switch (GET_CODE (operands[opno]))
+ {
+ case SYMBOL_REF :
+ case CONST :
+ case CONST_INT :
+ return true;
+ default:
+ error ("register number must be a compile-time constant. Try giving higher optimization levels");
+ break;
+ }
+ return false;
+}
+
+/* Check that after all the constant folding, whether the operand to
+ __builtin_arc_sleep is an unsigned int of 6 bits. If not, flag an error. */
+
+bool
+check_if_valid_sleep_operand (rtx *operands, int opno)
+{
+ switch (GET_CODE (operands[opno]))
+ {
+ case CONST :
+ case CONST_INT :
+ if( UNSIGNED_INT6 (INTVAL (operands[opno])))
+ return true;
+ default:
+ fatal_error("operand for sleep instruction must be an unsigned 6 bit compile-time constant");
+ break;
+ }
+ return false;
+}
+
+/* Return true if it is ok to make a tail-call to DECL. */
+
+static bool
+arc_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED,
+ tree exp ATTRIBUTE_UNUSED)
+{
+ /* Never tailcall from an ISR routine - it needs a special exit sequence. */
+ if (ARC_INTERRUPT_P (arc_compute_function_type (cfun)))
+ return false;
+
+ /* Everything else is ok. */
+ return true;
+}
+
+/* Output code to add DELTA to the first argument, and then jump
+ to FUNCTION. Used for C++ multiple inheritance. */
+
+static void
+arc_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
+ HOST_WIDE_INT delta,
+ HOST_WIDE_INT vcall_offset,
+ tree function)
+{
+ int mi_delta = delta;
+ const char *const mi_op = mi_delta < 0 ? "sub" : "add";
+ int shift = 0;
+ int this_regno
+ = aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function) ? 1 : 0;
+ rtx fnaddr;
+
+ if (mi_delta < 0)
+ mi_delta = - mi_delta;
+
+ /* Add DELTA. When possible use a plain add, otherwise load it into
+ a register first. */
+
+ while (mi_delta != 0)
+ {
+ if ((mi_delta & (3 << shift)) == 0)
+ shift += 2;
+ else
+ {
+ asm_fprintf (file, "\t%s\t%s, %s, %d\n",
+ mi_op, reg_names[this_regno], reg_names[this_regno],
+ mi_delta & (0xff << shift));
+ mi_delta &= ~(0xff << shift);
+ shift += 8;
+ }
+ }
+
+ /* If needed, add *(*THIS + VCALL_OFFSET) to THIS. */
+ if (vcall_offset != 0)
+ {
+ /* ld r12,[this] --> temp = *this
+ add r12,r12,vcall_offset --> temp = *(*this + vcall_offset)
+ ld r12,[r12]
+ add this,this,r12 --> this+ = *(*this + vcall_offset) */
+ asm_fprintf (file, "\tld\t%s, [%s]\n",
+ ARC_TEMP_SCRATCH_REG, reg_names[this_regno]);
+ asm_fprintf (file, "\tadd\t%s, %s, %ld\n",
+ ARC_TEMP_SCRATCH_REG, ARC_TEMP_SCRATCH_REG, vcall_offset);
+ asm_fprintf (file, "\tld\t%s, [%s]\n",
+ ARC_TEMP_SCRATCH_REG, ARC_TEMP_SCRATCH_REG);
+ asm_fprintf (file, "\tadd\t%s, %s, %s\n", reg_names[this_regno],
+ reg_names[this_regno], ARC_TEMP_SCRATCH_REG);
+ }
+
+ fnaddr = XEXP (DECL_RTL (function), 0);
+
+ if (arc_is_longcall_p (fnaddr))
+ fputs ("\tj\t", file);
+ else
+ fputs ("\tb\t", file);
+ assemble_name (file, XSTR (fnaddr, 0));
+ fputc ('\n', file);
+}
+
+/* Return true if a 32 bit "long_call" should be generated for
+ this calling SYM_REF. We generate a long_call if the function:
+
+ a. has an __attribute__((long call))
+ or b. the -mlong-calls command line switch has been specified
+
+ However we do not generate a long call if the function has an
+ __attribute__ ((short_call)) or __attribute__ ((medium_call))
+
+ This function will be called by C fragments contained in the machine
+ description file. */
+
+bool
+arc_is_longcall_p (rtx sym_ref)
+{
+ if (GET_CODE (sym_ref) != SYMBOL_REF)
+ return false;
+
+ return (SYMBOL_REF_LONG_CALL_P (sym_ref)
+ || (TARGET_LONG_CALLS_SET
+ && !SYMBOL_REF_SHORT_CALL_P (sym_ref)
+ && !SYMBOL_REF_MEDIUM_CALL_P (sym_ref)));
+
+}
+
+/* Likewise for short calls. */
+
+bool
+arc_is_shortcall_p (rtx sym_ref)
+{
+ if (GET_CODE (sym_ref) != SYMBOL_REF)
+ return false;
+
+ return (SYMBOL_REF_SHORT_CALL_P (sym_ref)
+ || (!TARGET_LONG_CALLS_SET && !TARGET_MEDIUM_CALLS
+ && !SYMBOL_REF_LONG_CALL_P (sym_ref)
+ && !SYMBOL_REF_MEDIUM_CALL_P (sym_ref)));
+
+}
+
+/* Emit profiling code for calling CALLEE. Return true if a special
+ call pattern needs to be generated. */
+
+bool
+arc_profile_call (rtx callee)
+{
+ rtx from = XEXP (DECL_RTL (current_function_decl), 0);
+
+ if (TARGET_UCB_MCOUNT)
+ /* Profiling is done by instrumenting the callee. */
+ return false;
+
+ if (CONSTANT_P (callee))
+ {
+ rtx count_ptr
+ = gen_rtx_CONST (Pmode,
+ gen_rtx_UNSPEC (Pmode,
+ gen_rtvec (3, from, callee,
+ CONST0_RTX (Pmode)),
+ UNSPEC_PROF));
+ rtx counter = gen_rtx_MEM (SImode, count_ptr);
+ /* ??? The increment would better be done atomically, but as there is
+ no proper hardware support, that would be too expensive. */
+ emit_move_insn (counter,
+ force_reg (SImode, plus_constant (SImode, counter, 1)));
+ return false;
+ }
+ else
+ {
+ rtx count_list_ptr
+ = gen_rtx_CONST (Pmode,
+ gen_rtx_UNSPEC (Pmode,
+ gen_rtvec (3, from, CONST0_RTX (Pmode),
+ CONST0_RTX (Pmode)),
+ UNSPEC_PROF));
+ emit_move_insn (gen_rtx_REG (Pmode, 8), count_list_ptr);
+ emit_move_insn (gen_rtx_REG (Pmode, 9), callee);
+ return true;
+ }
+}
+
+/* Worker function for TARGET_RETURN_IN_MEMORY. */
+
+static bool
+arc_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
+{
+ if (AGGREGATE_TYPE_P (type) || TREE_ADDRESSABLE (type))
+ return true;
+ else
+ {
+ HOST_WIDE_INT size = int_size_in_bytes (type);
+ return (size == -1 || size > 8);
+ }
+}
+
+
+/* This was in rtlanal.c, and can go in there when we decide we want
+ to submit the change for inclusion in the GCC tree. */
+/* Like note_stores, but allow the callback to have side effects on the rtl
+ (like the note_stores of yore):
+ Call FUN on each register or MEM that is stored into or clobbered by X.
+ (X would be the pattern of an insn). DATA is an arbitrary pointer,
+ ignored by note_stores, but passed to FUN.
+ FUN may alter parts of the RTL.
+
+ FUN receives three arguments:
+ 1. the REG, MEM, CC0 or PC being stored in or clobbered,
+ 2. the SET or CLOBBER rtx that does the store,
+ 3. the pointer DATA provided to note_stores.
+
+ If the item being stored in or clobbered is a SUBREG of a hard register,
+ the SUBREG will be passed. */
+
+/* For now. */ static
+void
+walk_stores (rtx x, void (*fun) (rtx, rtx, void *), void *data)
+{
+ int i;
+
+ if (GET_CODE (x) == COND_EXEC)
+ x = COND_EXEC_CODE (x);
+
+ if (GET_CODE (x) == SET || GET_CODE (x) == CLOBBER)
+ {
+ rtx dest = SET_DEST (x);
+
+ while ((GET_CODE (dest) == SUBREG
+ && (!REG_P (SUBREG_REG (dest))
+ || REGNO (SUBREG_REG (dest)) >= FIRST_PSEUDO_REGISTER))
+ || GET_CODE (dest) == ZERO_EXTRACT
+ || GET_CODE (dest) == STRICT_LOW_PART)
+ dest = XEXP (dest, 0);
+
+ /* If we have a PARALLEL, SET_DEST is a list of EXPR_LIST expressions,
+ each of whose first operand is a register. */
+ if (GET_CODE (dest) == PARALLEL)
+ {
+ for (i = XVECLEN (dest, 0) - 1; i >= 0; i--)
+ if (XEXP (XVECEXP (dest, 0, i), 0) != 0)
+ (*fun) (XEXP (XVECEXP (dest, 0, i), 0), x, data);
+ }
+ else
+ (*fun) (dest, x, data);
+ }
+
+ else if (GET_CODE (x) == PARALLEL)
+ for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
+ walk_stores (XVECEXP (x, 0, i), fun, data);
+}
+
+static bool
+arc_pass_by_reference (cumulative_args_t ca_v ATTRIBUTE_UNUSED,
+ enum machine_mode mode ATTRIBUTE_UNUSED,
+ const_tree type,
+ bool named ATTRIBUTE_UNUSED)
+{
+ return (type != 0
+ && (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST
+ || TREE_ADDRESSABLE (type)));
+}
+
+/* Implement TARGET_CAN_USE_DOLOOP_P. */
+
+static bool
+arc_can_use_doloop_p (double_int iterations, double_int,
+ unsigned int loop_depth, bool entered_at_top)
+{
+ if (loop_depth > 1)
+ return false;
+ /* Setting up the loop with two sr instructions costs 6 cycles. */
+ if (TARGET_ARC700
+ && !entered_at_top
+ && iterations.high == 0
+ && iterations.low > 0
+ && iterations.low <= (flag_pic ? 6 : 3))
+ return false;
+ return true;
+}
+
+/* NULL if INSN insn is valid within a low-overhead loop.
+ Otherwise return why doloop cannot be applied. */
+
+static const char *
+arc_invalid_within_doloop (const_rtx insn)
+{
+ if (CALL_P (insn))
+ return "Function call in the loop.";
+ return NULL;
+}
+
+static int arc_reorg_in_progress = 0;
+
+/* ARC's machince specific reorg function. */
+
+static void
+arc_reorg (void)
+{
+ rtx insn, pattern;
+ rtx pc_target;
+ long offset;
+ int changed;
+
+ cfun->machine->arc_reorg_started = 1;
+ arc_reorg_in_progress = 1;
+
+ /* Emit special sections for profiling. */
+ if (crtl->profile)
+ {
+ section *save_text_section;
+ rtx insn;
+ int size = get_max_uid () >> 4;
+ htab_t htab = htab_create (size, unspec_prof_hash, unspec_prof_htab_eq,
+ NULL);
+
+ save_text_section = in_section;
+ for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+ if (NONJUMP_INSN_P (insn))
+ walk_stores (PATTERN (insn), write_profile_sections, htab);
+ if (htab_elements (htab))
+ in_section = 0;
+ switch_to_section (save_text_section);
+ htab_delete (htab);
+ }
+
+ /* Link up loop ends with their loop start. */
+ {
+ for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+ if (GET_CODE (insn) == JUMP_INSN
+ && recog_memoized (insn) == CODE_FOR_doloop_end_i)
+ {
+ rtx top_label
+ = XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (insn), 0, 0)), 1), 0);
+ rtx num = GEN_INT (CODE_LABEL_NUMBER (top_label));
+ rtx lp, prev = prev_nonnote_insn (top_label);
+ rtx lp_simple = NULL_RTX;
+ rtx next = NULL_RTX;
+ rtx op0 = XEXP (XVECEXP (PATTERN (insn), 0, 1), 0);
+ HOST_WIDE_INT loop_end_id
+ = -INTVAL (XEXP (XVECEXP (PATTERN (insn), 0, 4), 0));
+ int seen_label = 0;
+
+ for (lp = prev;
+ (lp && NONJUMP_INSN_P (lp)
+ && recog_memoized (lp) != CODE_FOR_doloop_begin_i);
+ lp = prev_nonnote_insn (lp))
+ ;
+ if (!lp || !NONJUMP_INSN_P (lp)
+ || dead_or_set_regno_p (lp, LP_COUNT))
+ {
+ for (prev = next = insn, lp = NULL_RTX ; prev || next;)
+ {
+ if (prev)
+ {
+ if (NONJUMP_INSN_P (prev)
+ && recog_memoized (prev) == CODE_FOR_doloop_begin_i
+ && (INTVAL (XEXP (XVECEXP (PATTERN (prev), 0, 5), 0))
+ == loop_end_id))
+ {
+ lp = prev;
+ break;
+ }
+ else if (LABEL_P (prev))
+ seen_label = 1;
+ prev = prev_nonnote_insn (prev);
+ }
+ if (next)
+ {
+ if (NONJUMP_INSN_P (next)
+ && recog_memoized (next) == CODE_FOR_doloop_begin_i
+ && (INTVAL (XEXP (XVECEXP (PATTERN (next), 0, 5), 0))
+ == loop_end_id))
+ {
+ lp = next;
+ break;
+ }
+ next = next_nonnote_insn (next);
+ }
+ }
+ prev = NULL_RTX;
+ }
+ else
+ lp_simple = lp;
+ if (lp && !dead_or_set_regno_p (lp, LP_COUNT))
+ {
+ rtx begin_cnt = XEXP (XVECEXP (PATTERN (lp), 0 ,3), 0);
+ if (INTVAL (XEXP (XVECEXP (PATTERN (lp), 0, 4), 0)))
+ /* The loop end insn has been duplicated. That can happen
+ when there is a conditional block at the very end of
+ the loop. */
+ goto failure;
+ /* If Register allocation failed to allocate to the right
+ register, There is no point into teaching reload to
+ fix this up with reloads, as that would cost more
+ than using an ordinary core register with the
+ doloop_fallback pattern. */
+ if ((true_regnum (op0) != LP_COUNT || !REG_P (begin_cnt))
+ /* Likewise, if the loop setup is evidently inside the loop,
+ we loose. */
+ || (!lp_simple && lp != next && !seen_label))
+ {
+ remove_insn (lp);
+ goto failure;
+ }
+ /* It is common that the optimizers copy the loop count from
+ another register, and doloop_begin_i is stuck with the
+ source of the move. Making doloop_begin_i only accept "l"
+ is nonsentical, as this then makes reload evict the pseudo
+ used for the loop end. The underlying cause is that the
+ optimizers don't understand that the register allocation for
+ doloop_begin_i should be treated as part of the loop.
+ Try to work around this problem by verifying the previous
+ move exists. */
+ if (true_regnum (begin_cnt) != LP_COUNT)
+ {
+ rtx mov, set, note;
+
+ for (mov = prev_nonnote_insn (lp); mov;
+ mov = prev_nonnote_insn (mov))
+ {
+ if (!NONJUMP_INSN_P (mov))
+ mov = 0;
+ else if ((set = single_set (mov))
+ && rtx_equal_p (SET_SRC (set), begin_cnt)
+ && rtx_equal_p (SET_DEST (set), op0))
+ break;
+ }
+ if (mov)
+ {
+ XEXP (XVECEXP (PATTERN (lp), 0 ,3), 0) = op0;
+ note = find_regno_note (lp, REG_DEAD, REGNO (begin_cnt));
+ if (note)
+ remove_note (lp, note);
+ }
+ else
+ {
+ remove_insn (lp);
+ goto failure;
+ }
+ }
+ XEXP (XVECEXP (PATTERN (insn), 0, 4), 0) = num;
+ XEXP (XVECEXP (PATTERN (lp), 0, 4), 0) = num;
+ if (next == lp)
+ XEXP (XVECEXP (PATTERN (lp), 0, 6), 0) = const2_rtx;
+ else if (!lp_simple)
+ XEXP (XVECEXP (PATTERN (lp), 0, 6), 0) = const1_rtx;
+ else if (prev != lp)
+ {
+ remove_insn (lp);
+ add_insn_after (lp, prev, NULL);
+ }
+ if (!lp_simple)
+ {
+ XEXP (XVECEXP (PATTERN (lp), 0, 7), 0)
+ = gen_rtx_LABEL_REF (Pmode, top_label);
+ add_reg_note (lp, REG_LABEL_OPERAND, top_label);
+ LABEL_NUSES (top_label)++;
+ }
+ /* We can avoid tedious loop start / end setting for empty loops
+ be merely setting the loop count to its final value. */
+ if (next_active_insn (top_label) == insn)
+ {
+ rtx lc_set
+ = gen_rtx_SET (VOIDmode,
+ XEXP (XVECEXP (PATTERN (lp), 0, 3), 0),
+ const0_rtx);
+
+ lc_set = emit_insn_before (lc_set, insn);
+ delete_insn (lp);
+ delete_insn (insn);
+ insn = lc_set;
+ }
+ /* If the loop is non-empty with zero length, we can't make it
+ a zero-overhead loop. That can happen for empty asms. */
+ else
+ {
+ rtx scan;
+
+ for (scan = top_label;
+ (scan && scan != insn
+ && (!NONJUMP_INSN_P (scan) || !get_attr_length (scan)));
+ scan = NEXT_INSN (scan));
+ if (scan == insn)
+ {
+ remove_insn (lp);
+ goto failure;
+ }
+ }
+ }
+ else
+ {
+ /* Sometimes the loop optimizer makes a complete hash of the
+ loop. If it were only that the loop is not entered at the
+ top, we could fix this up by setting LP_START with SR .
+ However, if we can't find the loop begin were it should be,
+ chances are that it does not even dominate the loop, but is
+ inside the loop instead. Using SR there would kill
+ performance.
+ We use the doloop_fallback pattern here, which executes
+ in two cycles on the ARC700 when predicted correctly. */
+ failure:
+ if (!REG_P (op0))
+ {
+ rtx op3 = XEXP (XVECEXP (PATTERN (insn), 0, 5), 0);
+
+ emit_insn_before (gen_move_insn (op3, op0), insn);
+ PATTERN (insn)
+ = gen_doloop_fallback_m (op3, JUMP_LABEL (insn), op0);
+ }
+ else
+ XVEC (PATTERN (insn), 0)
+ = gen_rtvec (2, XVECEXP (PATTERN (insn), 0, 0),
+ XVECEXP (PATTERN (insn), 0, 1));
+ INSN_CODE (insn) = -1;
+ }
+ }
+ }
+
+/* FIXME: should anticipate ccfsm action, generate special patterns for
+ to-be-deleted branches that have no delay slot and have at least the
+ length of the size increase forced on other insns that are conditionalized.
+ This can also have an insn_list inside that enumerates insns which are
+ not actually conditionalized because the destinations are dead in the
+ not-execute case.
+ Could also tag branches that we want to be unaligned if they get no delay
+ slot, or even ones that we don't want to do delay slot sheduling for
+ because we can unalign them.
+
+ However, there are cases when conditional execution is only possible after
+ delay slot scheduling:
+
+ - If a delay slot is filled with a nocond/set insn from above, the previous
+ basic block can become elegible for conditional execution.
+ - If a delay slot is filled with a nocond insn from the fall-through path,
+ the branch with that delay slot can become eligble for conditional
+ execution (however, with the same sort of data flow analysis that dbr
+ does, we could have figured out before that we don't need to
+ conditionalize this insn.)
+ - If a delay slot insn is filled with an insn from the target, the
+ target label gets its uses decremented (even deleted if falling to zero),
+ thus possibly creating more condexec opportunities there.
+ Therefore, we should still be prepared to apply condexec optimization on
+ non-prepared branches if the size increase of conditionalized insns is no
+ more than the size saved from eliminating the branch. An invocation option
+ could also be used to reserve a bit of extra size for condbranches so that
+ this'll work more often (could also test in arc_reorg if the block is
+ 'close enough' to be eligible for condexec to make this likely, and
+ estimate required size increase). */
+ /* Generate BRcc insns, by combining cmp and Bcc insns wherever possible. */
+ if (TARGET_NO_BRCC_SET)
+ return;
+
+ do
+ {
+ init_insn_lengths();
+ changed = 0;
+
+ if (optimize > 1 && !TARGET_NO_COND_EXEC)
+ {
+ arc_ifcvt ();
+ unsigned int flags = pass_data_arc_ifcvt.todo_flags_finish;
+ df_finish_pass ((flags & TODO_df_verify) != 0);
+ }
+
+ /* Call shorten_branches to calculate the insn lengths. */
+ shorten_branches (get_insns());
+ cfun->machine->ccfsm_current_insn = NULL_RTX;
+
+ if (!INSN_ADDRESSES_SET_P())
+ fatal_error ("Insn addresses not set after shorten_branches");
+
+ for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+ {
+ rtx label;
+ enum attr_type insn_type;
+
+ /* If a non-jump insn (or a casesi jump table), continue. */
+ if (GET_CODE (insn) != JUMP_INSN ||
+ GET_CODE (PATTERN (insn)) == ADDR_VEC
+ || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
+ continue;
+
+ /* If we already have a brcc, note if it is suitable for brcc_s.
+ Be a bit generous with the brcc_s range so that we can take
+ advantage of any code shortening from delay slot scheduling. */
+ if (recog_memoized (insn) == CODE_FOR_cbranchsi4_scratch)
+ {
+ rtx pat = PATTERN (insn);
+ rtx op = XEXP (SET_SRC (XVECEXP (pat, 0, 0)), 0);
+ rtx *ccp = &XEXP (XVECEXP (pat, 0, 1), 0);
+
+ offset = branch_dest (insn) - INSN_ADDRESSES (INSN_UID (insn));
+ if ((offset >= -140 && offset < 140)
+ && rtx_equal_p (XEXP (op, 1), const0_rtx)
+ && compact_register_operand (XEXP (op, 0), VOIDmode)
+ && equality_comparison_operator (op, VOIDmode))
+ PUT_MODE (*ccp, CC_Zmode);
+ else if (GET_MODE (*ccp) == CC_Zmode)
+ PUT_MODE (*ccp, CC_ZNmode);
+ continue;
+ }
+ if ((insn_type = get_attr_type (insn)) == TYPE_BRCC
+ || insn_type == TYPE_BRCC_NO_DELAY_SLOT)
+ continue;
+
+ /* OK. so we have a jump insn. */
+ /* We need to check that it is a bcc. */
+ /* Bcc => set (pc) (if_then_else ) */
+ pattern = PATTERN (insn);
+ if (GET_CODE (pattern) != SET
+ || GET_CODE (SET_SRC (pattern)) != IF_THEN_ELSE
+ || ANY_RETURN_P (XEXP (SET_SRC (pattern), 1)))
+ continue;
+
+ /* Now check if the jump is beyond the s9 range. */
+ if (find_reg_note (insn, REG_CROSSING_JUMP, NULL_RTX))
+ continue;
+ offset = branch_dest (insn) - INSN_ADDRESSES (INSN_UID (insn));
+
+ if(offset > 253 || offset < -254)
+ continue;
+
+ pc_target = SET_SRC (pattern);
+
+ /* Now go back and search for the set cc insn. */
+
+ label = XEXP (pc_target, 1);
+
+ {
+ rtx pat, scan, link_insn = NULL;
+
+ for (scan = PREV_INSN (insn);
+ scan && GET_CODE (scan) != CODE_LABEL;
+ scan = PREV_INSN (scan))
+ {
+ if (! INSN_P (scan))
+ continue;
+ pat = PATTERN (scan);
+ if (GET_CODE (pat) == SET
+ && cc_register (SET_DEST (pat), VOIDmode))
+ {
+ link_insn = scan;
+ break;
+ }
+ }
+ if (! link_insn)
+ continue;
+ else
+ /* Check if this is a data dependency. */
+ {
+ rtx op, cc_clob_rtx, op0, op1, brcc_insn, note;
+ rtx cmp0, cmp1;
+
+ /* Ok this is the set cc. copy args here. */
+ op = XEXP (pc_target, 0);
+
+ op0 = cmp0 = XEXP (SET_SRC (pat), 0);
+ op1 = cmp1 = XEXP (SET_SRC (pat), 1);
+ if (GET_CODE (op0) == ZERO_EXTRACT
+ && XEXP (op0, 1) == const1_rtx
+ && (GET_CODE (op) == EQ
+ || GET_CODE (op) == NE))
+ {
+ /* btst / b{eq,ne} -> bbit{0,1} */
+ op0 = XEXP (cmp0, 0);
+ op1 = XEXP (cmp0, 2);
+ }
+ else if (!register_operand (op0, VOIDmode)
+ || !general_operand (op1, VOIDmode))
+ continue;
+ /* Be careful not to break what cmpsfpx_raw is
+ trying to create for checking equality of
+ single-precision floats. */
+ else if (TARGET_SPFP
+ && GET_MODE (op0) == SFmode
+ && GET_MODE (op1) == SFmode)
+ continue;
+
+ /* None of the two cmp operands should be set between the
+ cmp and the branch. */
+ if (reg_set_between_p (op0, link_insn, insn))
+ continue;
+
+ if (reg_set_between_p (op1, link_insn, insn))
+ continue;
+
+ /* Since the MODE check does not work, check that this is
+ CC reg's last set location before insn, and also no
+ instruction between the cmp and branch uses the
+ condition codes. */
+ if ((reg_set_between_p (SET_DEST (pat), link_insn, insn))
+ || (reg_used_between_p (SET_DEST (pat), link_insn, insn)))
+ continue;
+
+ /* CC reg should be dead after insn. */
+ if (!find_regno_note (insn, REG_DEAD, CC_REG))
+ continue;
+
+ op = gen_rtx_fmt_ee (GET_CODE (op),
+ GET_MODE (op), cmp0, cmp1);
+ /* If we create a LIMM where there was none before,
+ we only benefit if we can avoid a scheduling bubble
+ for the ARC600. Otherwise, we'd only forgo chances
+ at short insn generation, and risk out-of-range
+ branches. */
+ if (!brcc_nolimm_operator (op, VOIDmode)
+ && !long_immediate_operand (op1, VOIDmode)
+ && (TARGET_ARC700
+ || next_active_insn (link_insn) != insn))
+ continue;
+
+ /* Emit bbit / brcc (or brcc_s if possible).
+ CC_Zmode indicates that brcc_s is possible. */
+
+ if (op0 != cmp0)
+ cc_clob_rtx = gen_rtx_REG (CC_ZNmode, CC_REG);
+ else if ((offset >= -140 && offset < 140)
+ && rtx_equal_p (op1, const0_rtx)
+ && compact_register_operand (op0, VOIDmode)
+ && (GET_CODE (op) == EQ
+ || GET_CODE (op) == NE))
+ cc_clob_rtx = gen_rtx_REG (CC_Zmode, CC_REG);
+ else
+ cc_clob_rtx = gen_rtx_REG (CCmode, CC_REG);
+
+ brcc_insn
+ = gen_rtx_IF_THEN_ELSE (VOIDmode, op, label, pc_rtx);
+ brcc_insn = gen_rtx_SET (VOIDmode, pc_rtx, brcc_insn);
+ cc_clob_rtx = gen_rtx_CLOBBER (VOIDmode, cc_clob_rtx);
+ brcc_insn
+ = gen_rtx_PARALLEL
+ (VOIDmode, gen_rtvec (2, brcc_insn, cc_clob_rtx));
+ brcc_insn = emit_jump_insn_before (brcc_insn, insn);
+
+ JUMP_LABEL (brcc_insn) = JUMP_LABEL (insn);
+ note = find_reg_note (insn, REG_BR_PROB, 0);
+ if (note)
+ {
+ XEXP (note, 1) = REG_NOTES (brcc_insn);
+ REG_NOTES (brcc_insn) = note;
+ }
+ note = find_reg_note (link_insn, REG_DEAD, op0);
+ if (note)
+ {
+ remove_note (link_insn, note);
+ XEXP (note, 1) = REG_NOTES (brcc_insn);
+ REG_NOTES (brcc_insn) = note;
+ }
+ note = find_reg_note (link_insn, REG_DEAD, op1);
+ if (note)
+ {
+ XEXP (note, 1) = REG_NOTES (brcc_insn);
+ REG_NOTES (brcc_insn) = note;
+ }
+
+ changed = 1;
+
+ /* Delete the bcc insn. */
+ set_insn_deleted (insn);
+
+ /* Delete the cmp insn. */
+ set_insn_deleted (link_insn);
+
+ }
+ }
+ }
+ /* Clear out insn_addresses. */
+ INSN_ADDRESSES_FREE ();
+
+ } while (changed);
+
+ if (INSN_ADDRESSES_SET_P())
+ fatal_error ("insn addresses not freed");
+
+ arc_reorg_in_progress = 0;
+}
+
+ /* Check if the operands are valid for BRcc.d generation
+ Valid Brcc.d patterns are
+ Brcc.d b, c, s9
+ Brcc.d b, u6, s9
+
+ For cc={GT, LE, GTU, LEU}, u6=63 can not be allowed,
+ since they are encoded by the assembler as {GE, LT, HS, LS} 64, which
+ does not have a delay slot
+
+ Assumed precondition: Second operand is either a register or a u6 value. */
+
+bool
+valid_brcc_with_delay_p (rtx *operands)
+{
+ if (optimize_size && GET_MODE (operands[4]) == CC_Zmode)
+ return false;
+ return brcc_nolimm_operator (operands[0], VOIDmode);
+}
+
+/* ??? Hack. This should no really be here. See PR32143. */
+static bool
+arc_decl_anon_ns_mem_p (const_tree decl)
+{
+ while (1)
+ {
+ if (decl == NULL_TREE || decl == error_mark_node)
+ return false;
+ if (TREE_CODE (decl) == NAMESPACE_DECL
+ && DECL_NAME (decl) == NULL_TREE)
+ return true;
+ /* Classes and namespaces inside anonymous namespaces have
+ TREE_PUBLIC == 0, so we can shortcut the search. */
+ else if (TYPE_P (decl))
+ return (TREE_PUBLIC (TYPE_NAME (decl)) == 0);
+ else if (TREE_CODE (decl) == NAMESPACE_DECL)
+ return (TREE_PUBLIC (decl) == 0);
+ else
+ decl = DECL_CONTEXT (decl);
+ }
+}
+
+/* Implement TARGET_IN_SMALL_DATA_P. Return true if it would be safe to
+ access DECL using %gp_rel(...)($gp). */
+
+static bool
+arc_in_small_data_p (const_tree decl)
+{
+ HOST_WIDE_INT size;
+
+ if (TREE_CODE (decl) == STRING_CST || TREE_CODE (decl) == FUNCTION_DECL)
+ return false;
+
+
+ /* We don't yet generate small-data references for -mabicalls. See related
+ -G handling in override_options. */
+ if (TARGET_NO_SDATA_SET)
+ return false;
+
+ if (TREE_CODE (decl) == VAR_DECL && DECL_SECTION_NAME (decl) != 0)
+ {
+ const char *name;
+
+ /* Reject anything that isn't in a known small-data section. */
+ name = TREE_STRING_POINTER (DECL_SECTION_NAME (decl));
+ if (strcmp (name, ".sdata") != 0 && strcmp (name, ".sbss") != 0)
+ return false;
+
+ /* If a symbol is defined externally, the assembler will use the
+ usual -G rules when deciding how to implement macros. */
+ if (!DECL_EXTERNAL (decl))
+ return true;
+ }
+ /* Only global variables go into sdata section for now. */
+ else if (1)
+ {
+ /* Don't put constants into the small data section: we want them
+ to be in ROM rather than RAM. */
+ if (TREE_CODE (decl) != VAR_DECL)
+ return false;
+
+ if (TREE_READONLY (decl)
+ && !TREE_SIDE_EFFECTS (decl)
+ && (!DECL_INITIAL (decl) || TREE_CONSTANT (DECL_INITIAL (decl))))
+ return false;
+
+ /* TREE_PUBLIC might change after the first call, because of the patch
+ for PR19238. */
+ if (default_binds_local_p_1 (decl, 1)
+ || arc_decl_anon_ns_mem_p (decl))
+ return false;
+
+ /* To ensure -mvolatile-cache works
+ ld.di does not have a gp-relative variant. */
+ if (TREE_THIS_VOLATILE (decl))
+ return false;
+ }
+
+ /* Disable sdata references to weak variables. */
+ if (DECL_WEAK (decl))
+ return false;
+
+ size = int_size_in_bytes (TREE_TYPE (decl));
+
+/* if (AGGREGATE_TYPE_P (TREE_TYPE (decl))) */
+/* return false; */
+
+ /* Allow only <=4B long data types into sdata. */
+ return (size > 0 && size <= 4);
+}
+
+/* Return true if X is a small data address that can be rewritten
+ as a gp+symref. */
+
+static bool
+arc_rewrite_small_data_p (rtx x)
+{
+ if (GET_CODE (x) == CONST)
+ x = XEXP (x, 0);
+
+ if (GET_CODE (x) == PLUS)
+ {
+ if (GET_CODE (XEXP (x, 1)) == CONST_INT)
+ x = XEXP (x, 0);
+ }
+
+ return (GET_CODE (x) == SYMBOL_REF
+ && SYMBOL_REF_SMALL_P(x));
+}
+
+/* A for_each_rtx callback, used by arc_rewrite_small_data. */
+
+static int
+arc_rewrite_small_data_1 (rtx *loc, void *data)
+{
+ if (arc_rewrite_small_data_p (*loc))
+ {
+ rtx top;
+
+ gcc_assert (SDATA_BASE_REGNUM == PIC_OFFSET_TABLE_REGNUM);
+ *loc = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, *loc);
+ if (loc == data)
+ return -1;
+ top = *(rtx*) data;
+ if (GET_CODE (top) == MEM && &XEXP (top, 0) == loc)
+ ; /* OK. */
+ else if (GET_CODE (top) == MEM
+ && GET_CODE (XEXP (top, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (top, 0), 0)) == MULT)
+ *loc = force_reg (Pmode, *loc);
+ else
+ gcc_unreachable ();
+ return -1;
+ }
+
+ if (GET_CODE (*loc) == PLUS
+ && rtx_equal_p (XEXP (*loc, 0), pic_offset_table_rtx))
+ return -1;
+
+ return 0;
+}
+
+/* If possible, rewrite OP so that it refers to small data using
+ explicit relocations. */
+
+rtx
+arc_rewrite_small_data (rtx op)
+{
+ op = copy_insn (op);
+ for_each_rtx (&op, arc_rewrite_small_data_1, &op);
+ return op;
+}
+
+/* A for_each_rtx callback for small_data_pattern. */
+
+static int
+small_data_pattern_1 (rtx *loc, void *data ATTRIBUTE_UNUSED)
+{
+ if (GET_CODE (*loc) == PLUS
+ && rtx_equal_p (XEXP (*loc, 0), pic_offset_table_rtx))
+ return -1;
+
+ return arc_rewrite_small_data_p (*loc);
+}
+
+/* Return true if OP refers to small data symbols directly, not through
+ a PLUS. */
+
+bool
+small_data_pattern (rtx op, enum machine_mode)
+{
+ return (GET_CODE (op) != SEQUENCE
+ && for_each_rtx (&op, small_data_pattern_1, 0));
+}
+
+/* Return true if OP is an acceptable memory operand for ARCompact
+ 16-bit gp-relative load instructions.
+ op shd look like : [r26, symref@sda]
+ i.e. (mem (plus (reg 26) (symref with smalldata flag set))
+ */
+/* volatile cache option still to be handled. */
+
+bool
+compact_sda_memory_operand (rtx op, enum machine_mode mode)
+{
+ rtx addr;
+ int size;
+
+ /* Eliminate non-memory operations. */
+ if (GET_CODE (op) != MEM)
+ return false;
+
+ if (mode == VOIDmode)
+ mode = GET_MODE (op);
+
+ size = GET_MODE_SIZE (mode);
+
+ /* dword operations really put out 2 instructions, so eliminate them. */
+ if (size > UNITS_PER_WORD)
+ return false;
+
+ /* Decode the address now. */
+ addr = XEXP (op, 0);
+
+ return LEGITIMATE_SMALL_DATA_ADDRESS_P (addr);
+}
+
+/* Implement ASM_OUTPUT_ALIGNED_DECL_LOCAL. */
+
+void
+arc_asm_output_aligned_decl_local (FILE * stream, tree decl, const char * name,
+ unsigned HOST_WIDE_INT size,
+ unsigned HOST_WIDE_INT align,
+ unsigned HOST_WIDE_INT globalize_p)
+{
+ int in_small_data = arc_in_small_data_p (decl);
+
+ if (in_small_data)
+ switch_to_section (get_named_section (NULL, ".sbss", 0));
+ /* named_section (0,".sbss",0); */
+ else
+ switch_to_section (bss_section);
+
+ if (globalize_p)
+ (*targetm.asm_out.globalize_label) (stream, name);
+
+ ASM_OUTPUT_ALIGN (stream, floor_log2 ((align) / BITS_PER_UNIT));
+ ASM_OUTPUT_TYPE_DIRECTIVE (stream, name, "object");
+ ASM_OUTPUT_SIZE_DIRECTIVE (stream, name, size);
+ ASM_OUTPUT_LABEL (stream, name);
+
+ if (size != 0)
+ ASM_OUTPUT_SKIP (stream, size);
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/* SIMD builtins support. */
+enum simd_insn_args_type {
+ Va_Vb_Vc,
+ Va_Vb_rlimm,
+ Va_Vb_Ic,
+ Va_Vb_u6,
+ Va_Vb_u8,
+ Va_rlimm_u8,
+
+ Va_Vb,
+
+ void_rlimm,
+ void_u6,
+
+ Da_u3_rlimm,
+ Da_rlimm_rlimm,
+
+ Va_Ib_u8,
+ void_Va_Ib_u8,
+
+ Va_Vb_Ic_u8,
+ void_Va_u3_Ib_u8
+};
+
+struct builtin_description
+{
+ enum simd_insn_args_type args_type;
+ const enum insn_code icode;
+ const char * const name;
+ const enum arc_builtins code;
+};
+
+static const struct builtin_description arc_simd_builtin_desc_list[] =
+{
+ /* VVV builtins go first. */
+#define SIMD_BUILTIN(type, code, string, builtin) \
+ { type,CODE_FOR_##code, "__builtin_arc_" string, \
+ ARC_SIMD_BUILTIN_##builtin },
+
+ SIMD_BUILTIN (Va_Vb_Vc, vaddaw_insn, "vaddaw", VADDAW)
+ SIMD_BUILTIN (Va_Vb_Vc, vaddw_insn, "vaddw", VADDW)
+ SIMD_BUILTIN (Va_Vb_Vc, vavb_insn, "vavb", VAVB)
+ SIMD_BUILTIN (Va_Vb_Vc, vavrb_insn, "vavrb", VAVRB)
+ SIMD_BUILTIN (Va_Vb_Vc, vdifaw_insn, "vdifaw", VDIFAW)
+ SIMD_BUILTIN (Va_Vb_Vc, vdifw_insn, "vdifw", VDIFW)
+ SIMD_BUILTIN (Va_Vb_Vc, vmaxaw_insn, "vmaxaw", VMAXAW)
+ SIMD_BUILTIN (Va_Vb_Vc, vmaxw_insn, "vmaxw", VMAXW)
+ SIMD_BUILTIN (Va_Vb_Vc, vminaw_insn, "vminaw", VMINAW)
+ SIMD_BUILTIN (Va_Vb_Vc, vminw_insn, "vminw", VMINW)
+ SIMD_BUILTIN (Va_Vb_Vc, vmulaw_insn, "vmulaw", VMULAW)
+ SIMD_BUILTIN (Va_Vb_Vc, vmulfaw_insn, "vmulfaw", VMULFAW)
+ SIMD_BUILTIN (Va_Vb_Vc, vmulfw_insn, "vmulfw", VMULFW)
+ SIMD_BUILTIN (Va_Vb_Vc, vmulw_insn, "vmulw", VMULW)
+ SIMD_BUILTIN (Va_Vb_Vc, vsubaw_insn, "vsubaw", VSUBAW)
+ SIMD_BUILTIN (Va_Vb_Vc, vsubw_insn, "vsubw", VSUBW)
+ SIMD_BUILTIN (Va_Vb_Vc, vsummw_insn, "vsummw", VSUMMW)
+ SIMD_BUILTIN (Va_Vb_Vc, vand_insn, "vand", VAND)
+ SIMD_BUILTIN (Va_Vb_Vc, vandaw_insn, "vandaw", VANDAW)
+ SIMD_BUILTIN (Va_Vb_Vc, vbic_insn, "vbic", VBIC)
+ SIMD_BUILTIN (Va_Vb_Vc, vbicaw_insn, "vbicaw", VBICAW)
+ SIMD_BUILTIN (Va_Vb_Vc, vor_insn, "vor", VOR)
+ SIMD_BUILTIN (Va_Vb_Vc, vxor_insn, "vxor", VXOR)
+ SIMD_BUILTIN (Va_Vb_Vc, vxoraw_insn, "vxoraw", VXORAW)
+ SIMD_BUILTIN (Va_Vb_Vc, veqw_insn, "veqw", VEQW)
+ SIMD_BUILTIN (Va_Vb_Vc, vlew_insn, "vlew", VLEW)
+ SIMD_BUILTIN (Va_Vb_Vc, vltw_insn, "vltw", VLTW)
+ SIMD_BUILTIN (Va_Vb_Vc, vnew_insn, "vnew", VNEW)
+ SIMD_BUILTIN (Va_Vb_Vc, vmr1aw_insn, "vmr1aw", VMR1AW)
+ SIMD_BUILTIN (Va_Vb_Vc, vmr1w_insn, "vmr1w", VMR1W)
+ SIMD_BUILTIN (Va_Vb_Vc, vmr2aw_insn, "vmr2aw", VMR2AW)
+ SIMD_BUILTIN (Va_Vb_Vc, vmr2w_insn, "vmr2w", VMR2W)
+ SIMD_BUILTIN (Va_Vb_Vc, vmr3aw_insn, "vmr3aw", VMR3AW)
+ SIMD_BUILTIN (Va_Vb_Vc, vmr3w_insn, "vmr3w", VMR3W)
+ SIMD_BUILTIN (Va_Vb_Vc, vmr4aw_insn, "vmr4aw", VMR4AW)
+ SIMD_BUILTIN (Va_Vb_Vc, vmr4w_insn, "vmr4w", VMR4W)
+ SIMD_BUILTIN (Va_Vb_Vc, vmr5aw_insn, "vmr5aw", VMR5AW)
+ SIMD_BUILTIN (Va_Vb_Vc, vmr5w_insn, "vmr5w", VMR5W)
+ SIMD_BUILTIN (Va_Vb_Vc, vmr6aw_insn, "vmr6aw", VMR6AW)
+ SIMD_BUILTIN (Va_Vb_Vc, vmr6w_insn, "vmr6w", VMR6W)
+ SIMD_BUILTIN (Va_Vb_Vc, vmr7aw_insn, "vmr7aw", VMR7AW)
+ SIMD_BUILTIN (Va_Vb_Vc, vmr7w_insn, "vmr7w", VMR7W)
+ SIMD_BUILTIN (Va_Vb_Vc, vmrb_insn, "vmrb", VMRB)
+ SIMD_BUILTIN (Va_Vb_Vc, vh264f_insn, "vh264f", VH264F)
+ SIMD_BUILTIN (Va_Vb_Vc, vh264ft_insn, "vh264ft", VH264FT)
+ SIMD_BUILTIN (Va_Vb_Vc, vh264fw_insn, "vh264fw", VH264FW)
+ SIMD_BUILTIN (Va_Vb_Vc, vvc1f_insn, "vvc1f", VVC1F)
+ SIMD_BUILTIN (Va_Vb_Vc, vvc1ft_insn, "vvc1ft", VVC1FT)
+
+ SIMD_BUILTIN (Va_Vb_rlimm, vbaddw_insn, "vbaddw", VBADDW)
+ SIMD_BUILTIN (Va_Vb_rlimm, vbmaxw_insn, "vbmaxw", VBMAXW)
+ SIMD_BUILTIN (Va_Vb_rlimm, vbminw_insn, "vbminw", VBMINW)
+ SIMD_BUILTIN (Va_Vb_rlimm, vbmulaw_insn, "vbmulaw", VBMULAW)
+ SIMD_BUILTIN (Va_Vb_rlimm, vbmulfw_insn, "vbmulfw", VBMULFW)
+ SIMD_BUILTIN (Va_Vb_rlimm, vbmulw_insn, "vbmulw", VBMULW)
+ SIMD_BUILTIN (Va_Vb_rlimm, vbrsubw_insn, "vbrsubw", VBRSUBW)
+ SIMD_BUILTIN (Va_Vb_rlimm, vbsubw_insn, "vbsubw", VBSUBW)
+
+ /* Va, Vb, Ic instructions. */
+ SIMD_BUILTIN (Va_Vb_Ic, vasrw_insn, "vasrw", VASRW)
+ SIMD_BUILTIN (Va_Vb_Ic, vsr8_insn, "vsr8", VSR8)
+ SIMD_BUILTIN (Va_Vb_Ic, vsr8aw_insn, "vsr8aw", VSR8AW)
+
+ /* Va, Vb, u6 instructions. */
+ SIMD_BUILTIN (Va_Vb_u6, vasrrwi_insn, "vasrrwi", VASRRWi)
+ SIMD_BUILTIN (Va_Vb_u6, vasrsrwi_insn, "vasrsrwi", VASRSRWi)
+ SIMD_BUILTIN (Va_Vb_u6, vasrwi_insn, "vasrwi", VASRWi)
+ SIMD_BUILTIN (Va_Vb_u6, vasrpwbi_insn, "vasrpwbi", VASRPWBi)
+ SIMD_BUILTIN (Va_Vb_u6, vasrrpwbi_insn,"vasrrpwbi", VASRRPWBi)
+ SIMD_BUILTIN (Va_Vb_u6, vsr8awi_insn, "vsr8awi", VSR8AWi)
+ SIMD_BUILTIN (Va_Vb_u6, vsr8i_insn, "vsr8i", VSR8i)
+
+ /* Va, Vb, u8 (simm) instructions. */
+ SIMD_BUILTIN (Va_Vb_u8, vmvaw_insn, "vmvaw", VMVAW)
+ SIMD_BUILTIN (Va_Vb_u8, vmvw_insn, "vmvw", VMVW)
+ SIMD_BUILTIN (Va_Vb_u8, vmvzw_insn, "vmvzw", VMVZW)
+ SIMD_BUILTIN (Va_Vb_u8, vd6tapf_insn, "vd6tapf", VD6TAPF)
+
+ /* Va, rlimm, u8 (simm) instructions. */
+ SIMD_BUILTIN (Va_rlimm_u8, vmovaw_insn, "vmovaw", VMOVAW)
+ SIMD_BUILTIN (Va_rlimm_u8, vmovw_insn, "vmovw", VMOVW)
+ SIMD_BUILTIN (Va_rlimm_u8, vmovzw_insn, "vmovzw", VMOVZW)
+
+ /* Va, Vb instructions. */
+ SIMD_BUILTIN (Va_Vb, vabsaw_insn, "vabsaw", VABSAW)
+ SIMD_BUILTIN (Va_Vb, vabsw_insn, "vabsw", VABSW)
+ SIMD_BUILTIN (Va_Vb, vaddsuw_insn, "vaddsuw", VADDSUW)
+ SIMD_BUILTIN (Va_Vb, vsignw_insn, "vsignw", VSIGNW)
+ SIMD_BUILTIN (Va_Vb, vexch1_insn, "vexch1", VEXCH1)
+ SIMD_BUILTIN (Va_Vb, vexch2_insn, "vexch2", VEXCH2)
+ SIMD_BUILTIN (Va_Vb, vexch4_insn, "vexch4", VEXCH4)
+ SIMD_BUILTIN (Va_Vb, vupbaw_insn, "vupbaw", VUPBAW)
+ SIMD_BUILTIN (Va_Vb, vupbw_insn, "vupbw", VUPBW)
+ SIMD_BUILTIN (Va_Vb, vupsbaw_insn, "vupsbaw", VUPSBAW)
+ SIMD_BUILTIN (Va_Vb, vupsbw_insn, "vupsbw", VUPSBW)
+
+ /* DIb, rlimm, rlimm instructions. */
+ SIMD_BUILTIN (Da_rlimm_rlimm, vdirun_insn, "vdirun", VDIRUN)
+ SIMD_BUILTIN (Da_rlimm_rlimm, vdorun_insn, "vdorun", VDORUN)
+
+ /* DIb, limm, rlimm instructions. */
+ SIMD_BUILTIN (Da_u3_rlimm, vdiwr_insn, "vdiwr", VDIWR)
+ SIMD_BUILTIN (Da_u3_rlimm, vdowr_insn, "vdowr", VDOWR)
+
+ /* rlimm instructions. */
+ SIMD_BUILTIN (void_rlimm, vrec_insn, "vrec", VREC)
+ SIMD_BUILTIN (void_rlimm, vrun_insn, "vrun", VRUN)
+ SIMD_BUILTIN (void_rlimm, vrecrun_insn, "vrecrun", VRECRUN)
+ SIMD_BUILTIN (void_rlimm, vendrec_insn, "vendrec", VENDREC)
+
+ /* Va, [Ib,u8] instructions. */
+ SIMD_BUILTIN (Va_Vb_Ic_u8, vld32wh_insn, "vld32wh", VLD32WH)
+ SIMD_BUILTIN (Va_Vb_Ic_u8, vld32wl_insn, "vld32wl", VLD32WL)
+ SIMD_BUILTIN (Va_Vb_Ic_u8, vld64_insn, "vld64", VLD64)
+ SIMD_BUILTIN (Va_Vb_Ic_u8, vld32_insn, "vld32", VLD32)
+
+ SIMD_BUILTIN (Va_Ib_u8, vld64w_insn, "vld64w", VLD64W)
+ SIMD_BUILTIN (Va_Ib_u8, vld128_insn, "vld128", VLD128)
+ SIMD_BUILTIN (void_Va_Ib_u8, vst128_insn, "vst128", VST128)
+ SIMD_BUILTIN (void_Va_Ib_u8, vst64_insn, "vst64", VST64)
+
+ /* Va, [Ib, u8] instructions. */
+ SIMD_BUILTIN (void_Va_u3_Ib_u8, vst16_n_insn, "vst16_n", VST16_N)
+ SIMD_BUILTIN (void_Va_u3_Ib_u8, vst32_n_insn, "vst32_n", VST32_N)
+
+ SIMD_BUILTIN (void_u6, vinti_insn, "vinti", VINTI)
+};
+
+static void
+arc_init_simd_builtins (void)
+{
+ int i;
+ tree endlink = void_list_node;
+ tree V8HI_type_node = build_vector_type_for_mode (intHI_type_node, V8HImode);
+
+ tree v8hi_ftype_v8hi_v8hi
+ = build_function_type (V8HI_type_node,
+ tree_cons (NULL_TREE, V8HI_type_node,
+ tree_cons (NULL_TREE, V8HI_type_node,
+ endlink)));
+ tree v8hi_ftype_v8hi_int
+ = build_function_type (V8HI_type_node,
+ tree_cons (NULL_TREE, V8HI_type_node,
+ tree_cons (NULL_TREE, integer_type_node,
+ endlink)));
+
+ tree v8hi_ftype_v8hi_int_int
+ = build_function_type (V8HI_type_node,
+ tree_cons (NULL_TREE, V8HI_type_node,
+ tree_cons (NULL_TREE, integer_type_node,
+ tree_cons (NULL_TREE,
+ integer_type_node,
+ endlink))));
+
+ tree void_ftype_v8hi_int_int
+ = build_function_type (void_type_node,
+ tree_cons (NULL_TREE, V8HI_type_node,
+ tree_cons (NULL_TREE, integer_type_node,
+ tree_cons (NULL_TREE,
+ integer_type_node,
+ endlink))));
+
+ tree void_ftype_v8hi_int_int_int
+ = (build_function_type
+ (void_type_node,
+ tree_cons (NULL_TREE, V8HI_type_node,
+ tree_cons (NULL_TREE, integer_type_node,
+ tree_cons (NULL_TREE, integer_type_node,
+ tree_cons (NULL_TREE,
+ integer_type_node,
+ endlink))))));
+
+ tree v8hi_ftype_int_int
+ = build_function_type (V8HI_type_node,
+ tree_cons (NULL_TREE, integer_type_node,
+ tree_cons (NULL_TREE, integer_type_node,
+ endlink)));
+
+ tree void_ftype_int_int
+ = build_function_type (void_type_node,
+ tree_cons (NULL_TREE, integer_type_node,
+ tree_cons (NULL_TREE, integer_type_node,
+ endlink)));
+
+ tree void_ftype_int
+ = build_function_type (void_type_node,
+ tree_cons (NULL_TREE, integer_type_node, endlink));
+
+ tree v8hi_ftype_v8hi
+ = build_function_type (V8HI_type_node, tree_cons (NULL_TREE, V8HI_type_node,
+ endlink));
+
+ /* These asserts have been introduced to ensure that the order of builtins
+ does not get messed up, else the initialization goes wrong. */
+ gcc_assert (arc_simd_builtin_desc_list [0].args_type == Va_Vb_Vc);
+ for (i=0; arc_simd_builtin_desc_list [i].args_type == Va_Vb_Vc; i++)
+ def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list[i].name,
+ v8hi_ftype_v8hi_v8hi, arc_simd_builtin_desc_list[i].code);
+
+ gcc_assert (arc_simd_builtin_desc_list [i].args_type == Va_Vb_rlimm);
+ for (; arc_simd_builtin_desc_list [i].args_type == Va_Vb_rlimm; i++)
+ def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list[i].name,
+ v8hi_ftype_v8hi_int, arc_simd_builtin_desc_list[i].code);
+
+ gcc_assert (arc_simd_builtin_desc_list [i].args_type == Va_Vb_Ic);
+ for (; arc_simd_builtin_desc_list [i].args_type == Va_Vb_Ic; i++)
+ def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list[i].name,
+ v8hi_ftype_v8hi_int, arc_simd_builtin_desc_list[i].code);
+
+ gcc_assert (arc_simd_builtin_desc_list [i].args_type == Va_Vb_u6);
+ for (; arc_simd_builtin_desc_list [i].args_type == Va_Vb_u6; i++)
+ def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list[i].name,
+ v8hi_ftype_v8hi_int, arc_simd_builtin_desc_list[i].code);
+
+ gcc_assert (arc_simd_builtin_desc_list [i].args_type == Va_Vb_u8);
+ for (; arc_simd_builtin_desc_list [i].args_type == Va_Vb_u8; i++)
+ def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list[i].name,
+ v8hi_ftype_v8hi_int, arc_simd_builtin_desc_list[i].code);
+
+ gcc_assert (arc_simd_builtin_desc_list [i].args_type == Va_rlimm_u8);
+ for (; arc_simd_builtin_desc_list [i].args_type == Va_rlimm_u8; i++)
+ def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list[i].name,
+ v8hi_ftype_int_int, arc_simd_builtin_desc_list[i].code);
+
+ gcc_assert (arc_simd_builtin_desc_list [i].args_type == Va_Vb);
+ for (; arc_simd_builtin_desc_list [i].args_type == Va_Vb; i++)
+ def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list[i].name,
+ v8hi_ftype_v8hi, arc_simd_builtin_desc_list[i].code);
+
+ gcc_assert (arc_simd_builtin_desc_list [i].args_type == Da_rlimm_rlimm);
+ for (; arc_simd_builtin_desc_list [i].args_type == Da_rlimm_rlimm; i++)
+ def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list [i].name,
+ void_ftype_int_int, arc_simd_builtin_desc_list[i].code);
+
+ gcc_assert (arc_simd_builtin_desc_list [i].args_type == Da_u3_rlimm);
+ for (; arc_simd_builtin_desc_list [i].args_type == Da_u3_rlimm; i++)
+ def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list[i].name,
+ void_ftype_int_int, arc_simd_builtin_desc_list[i].code);
+
+ gcc_assert (arc_simd_builtin_desc_list [i].args_type == void_rlimm);
+ for (; arc_simd_builtin_desc_list [i].args_type == void_rlimm; i++)
+ def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list[i].name,
+ void_ftype_int, arc_simd_builtin_desc_list[i].code);
+
+ gcc_assert (arc_simd_builtin_desc_list [i].args_type == Va_Vb_Ic_u8);
+ for (; arc_simd_builtin_desc_list [i].args_type == Va_Vb_Ic_u8; i++)
+ def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list[i].name,
+ v8hi_ftype_v8hi_int_int, arc_simd_builtin_desc_list[i].code);
+
+ gcc_assert (arc_simd_builtin_desc_list [i].args_type == Va_Ib_u8);
+ for (; arc_simd_builtin_desc_list [i].args_type == Va_Ib_u8; i++)
+ def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list[i].name,
+ v8hi_ftype_int_int, arc_simd_builtin_desc_list[i].code);
+
+ gcc_assert (arc_simd_builtin_desc_list [i].args_type == void_Va_Ib_u8);
+ for (; arc_simd_builtin_desc_list [i].args_type == void_Va_Ib_u8; i++)
+ def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list [i].name,
+ void_ftype_v8hi_int_int, arc_simd_builtin_desc_list[i].code);
+
+ gcc_assert (arc_simd_builtin_desc_list [i].args_type == void_Va_u3_Ib_u8);
+ for (; arc_simd_builtin_desc_list [i].args_type == void_Va_u3_Ib_u8; i++)
+ def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list[i].name,
+ void_ftype_v8hi_int_int_int,
+ arc_simd_builtin_desc_list[i].code);
+
+ gcc_assert (arc_simd_builtin_desc_list [i].args_type == void_u6);
+ for (; arc_simd_builtin_desc_list [i].args_type == void_u6; i++)
+ def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list[i].name,
+ void_ftype_int, arc_simd_builtin_desc_list[i].code);
+
+ gcc_assert(i == ARRAY_SIZE (arc_simd_builtin_desc_list));
+}
+
+/* Helper function of arc_expand_builtin; has the same parameters,
+ except that EXP is now known to be a call to a simd builtin. */
+
+static rtx
+arc_expand_simd_builtin (tree exp,
+ rtx target,
+ rtx subtarget ATTRIBUTE_UNUSED,
+ enum machine_mode mode ATTRIBUTE_UNUSED,
+ int ignore ATTRIBUTE_UNUSED)
+{
+ tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
+ tree arg0;
+ tree arg1;
+ tree arg2;
+ tree arg3;
+ rtx op0;
+ rtx op1;
+ rtx op2;
+ rtx op3;
+ rtx op4;
+ rtx pat;
+ unsigned int i;
+ int fcode = DECL_FUNCTION_CODE (fndecl);
+ int icode;
+ enum machine_mode mode0;
+ enum machine_mode mode1;
+ enum machine_mode mode2;
+ enum machine_mode mode3;
+ enum machine_mode mode4;
+ const struct builtin_description * d;
+
+ for (i = 0, d = arc_simd_builtin_desc_list;
+ i < ARRAY_SIZE (arc_simd_builtin_desc_list); i++, d++)
+ if (d->code == (const enum arc_builtins) fcode)
+ break;
+
+ /* We must get an entry here. */
+ gcc_assert (i < ARRAY_SIZE (arc_simd_builtin_desc_list));
+
+ switch (d->args_type)
+ {
+ case Va_Vb_rlimm:
+ icode = d->icode;
+ arg0 = CALL_EXPR_ARG (exp, 0);
+ arg1 = CALL_EXPR_ARG (exp, 1);
+ op0 = expand_expr (arg0, NULL_RTX, V8HImode, EXPAND_NORMAL);
+ op1 = expand_expr (arg1, NULL_RTX, SImode, EXPAND_NORMAL);
+
+ target = gen_reg_rtx (V8HImode);
+ mode0 = insn_data[icode].operand[1].mode;
+ mode1 = insn_data[icode].operand[2].mode;
+
+ if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
+ op0 = copy_to_mode_reg (mode0, op0);
+
+ if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
+ op1 = copy_to_mode_reg (mode1, op1);
+
+ pat = GEN_FCN (icode) (target, op0, op1);
+ if (! pat)
+ return 0;
+
+ emit_insn (pat);
+ return target;
+
+ case Va_Vb_u6:
+ case Va_Vb_u8:
+ icode = d->icode;
+ arg0 = CALL_EXPR_ARG (exp, 0);
+ arg1 = CALL_EXPR_ARG (exp, 1);
+ op0 = expand_expr (arg0, NULL_RTX, V8HImode, EXPAND_NORMAL);
+ op1 = expand_expr (arg1, NULL_RTX, SImode, EXPAND_NORMAL);
+
+ target = gen_reg_rtx (V8HImode);
+ mode0 = insn_data[icode].operand[1].mode;
+ mode1 = insn_data[icode].operand[2].mode;
+
+ if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
+ op0 = copy_to_mode_reg (mode0, op0);
+
+ if (! (*insn_data[icode].operand[2].predicate) (op1, mode1)
+ || (d->args_type == Va_Vb_u6 && !UNSIGNED_INT6 (INTVAL (op1)))
+ || (d->args_type == Va_Vb_u8 && !UNSIGNED_INT8 (INTVAL (op1))))
+ error ("operand 2 of %s instruction should be an unsigned %d-bit value",
+ d->name,
+ (d->args_type == Va_Vb_u6)? 6: 8);
+
+ pat = GEN_FCN (icode) (target, op0, op1);
+ if (! pat)
+ return 0;
+
+ emit_insn (pat);
+ return target;
+
+ case Va_rlimm_u8:
+ icode = d->icode;
+ arg0 = CALL_EXPR_ARG (exp, 0);
+ arg1 = CALL_EXPR_ARG (exp, 1);
+ op0 = expand_expr (arg0, NULL_RTX, SImode, EXPAND_NORMAL);
+ op1 = expand_expr (arg1, NULL_RTX, SImode, EXPAND_NORMAL);
+
+ target = gen_reg_rtx (V8HImode);
+ mode0 = insn_data[icode].operand[1].mode;
+ mode1 = insn_data[icode].operand[2].mode;
+
+ if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
+ op0 = copy_to_mode_reg (mode0, op0);
+
+ if ( (!(*insn_data[icode].operand[2].predicate) (op1, mode1))
+ || !(UNSIGNED_INT8 (INTVAL (op1))))
+ error ("operand 2 of %s instruction should be an unsigned 8-bit value",
+ d->name);
+
+ pat = GEN_FCN (icode) (target, op0, op1);
+ if (! pat)
+ return 0;
+
+ emit_insn (pat);
+ return target;
+
+ case Va_Vb_Ic:
+ icode = d->icode;
+ arg0 = CALL_EXPR_ARG (exp, 0);
+ arg1 = CALL_EXPR_ARG (exp, 1);
+ op0 = expand_expr (arg0, NULL_RTX, V8HImode, EXPAND_NORMAL);
+ op1 = expand_expr (arg1, NULL_RTX, SImode, EXPAND_NORMAL);
+ op2 = gen_rtx_REG (V8HImode, ARC_FIRST_SIMD_VR_REG);
+
+ target = gen_reg_rtx (V8HImode);
+ mode0 = insn_data[icode].operand[1].mode;
+ mode1 = insn_data[icode].operand[2].mode;
+
+ if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
+ op0 = copy_to_mode_reg (mode0, op0);
+
+ if ( (!(*insn_data[icode].operand[2].predicate) (op1, mode1))
+ || !(UNSIGNED_INT3 (INTVAL (op1))))
+ error ("operand 2 of %s instruction should be an unsigned 3-bit value (I0-I7)",
+ d->name);
+
+ pat = GEN_FCN (icode) (target, op0, op1, op2);
+ if (! pat)
+ return 0;
+
+ emit_insn (pat);
+ return target;
+
+ case Va_Vb_Vc:
+ icode = d->icode;
+ arg0 = CALL_EXPR_ARG (exp, 0);
+ arg1 = CALL_EXPR_ARG (exp, 1);
+ op0 = expand_expr (arg0, NULL_RTX, V8HImode, EXPAND_NORMAL);
+ op1 = expand_expr (arg1, NULL_RTX, V8HImode, EXPAND_NORMAL);
+
+ target = gen_reg_rtx (V8HImode);
+ mode0 = insn_data[icode].operand[1].mode;
+ mode1 = insn_data[icode].operand[2].mode;
+
+ if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
+ op0 = copy_to_mode_reg (mode0, op0);
+
+ if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
+ op1 = copy_to_mode_reg (mode1, op1);
+
+ pat = GEN_FCN (icode) (target, op0, op1);
+ if (! pat)
+ return 0;
+
+ emit_insn (pat);
+ return target;
+
+ case Va_Vb:
+ icode = d->icode;
+ arg0 = CALL_EXPR_ARG (exp, 0);
+ op0 = expand_expr (arg0, NULL_RTX, V8HImode, EXPAND_NORMAL);
+
+ target = gen_reg_rtx (V8HImode);
+ mode0 = insn_data[icode].operand[1].mode;
+
+ if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
+ op0 = copy_to_mode_reg (mode0, op0);
+
+ pat = GEN_FCN (icode) (target, op0);
+ if (! pat)
+ return 0;
+
+ emit_insn (pat);
+ return target;
+
+ case Da_rlimm_rlimm:
+ icode = d->icode;
+ arg0 = CALL_EXPR_ARG (exp, 0);
+ arg1 = CALL_EXPR_ARG (exp, 1);
+ op0 = expand_expr (arg0, NULL_RTX, SImode, EXPAND_NORMAL);
+ op1 = expand_expr (arg1, NULL_RTX, SImode, EXPAND_NORMAL);
+
+
+ if (icode == CODE_FOR_vdirun_insn)
+ target = gen_rtx_REG (SImode, 131);
+ else if (icode == CODE_FOR_vdorun_insn)
+ target = gen_rtx_REG (SImode, 139);
+ else
+ gcc_unreachable ();
+
+ mode0 = insn_data[icode].operand[1].mode;
+ mode1 = insn_data[icode].operand[2].mode;
+
+ if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
+ op0 = copy_to_mode_reg (mode0, op0);
+
+ if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
+ op1 = copy_to_mode_reg (mode1, op1);
+
+
+ pat = GEN_FCN (icode) (target, op0, op1);
+ if (! pat)
+ return 0;
+
+ emit_insn (pat);
+ return NULL_RTX;
+
+ case Da_u3_rlimm:
+ icode = d->icode;
+ arg0 = CALL_EXPR_ARG (exp, 0);
+ arg1 = CALL_EXPR_ARG (exp, 1);
+ op0 = expand_expr (arg0, NULL_RTX, SImode, EXPAND_NORMAL);
+ op1 = expand_expr (arg1, NULL_RTX, SImode, EXPAND_NORMAL);
+
+
+ if (! (GET_CODE (op0) == CONST_INT)
+ || !(UNSIGNED_INT3 (INTVAL (op0))))
+ error ("operand 1 of %s instruction should be an unsigned 3-bit value (DR0-DR7)",
+ d->name);
+
+ mode1 = insn_data[icode].operand[1].mode;
+
+ if (icode == CODE_FOR_vdiwr_insn)
+ target = gen_rtx_REG (SImode,
+ ARC_FIRST_SIMD_DMA_CONFIG_IN_REG + INTVAL (op0));
+ else if (icode == CODE_FOR_vdowr_insn)
+ target = gen_rtx_REG (SImode,
+ ARC_FIRST_SIMD_DMA_CONFIG_OUT_REG + INTVAL (op0));
+ else
+ gcc_unreachable ();
+
+ if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
+ op1 = copy_to_mode_reg (mode1, op1);
+
+ pat = GEN_FCN (icode) (target, op1);
+ if (! pat)
+ return 0;
+
+ emit_insn (pat);
+ return NULL_RTX;
+
+ case void_u6:
+ icode = d->icode;
+ arg0 = CALL_EXPR_ARG (exp, 0);
+
+ fold (arg0);
+
+ op0 = expand_expr (arg0, NULL_RTX, SImode, EXPAND_NORMAL);
+ mode0 = insn_data[icode].operand[0].mode;
+
+ /* op0 should be u6. */
+ if (! (*insn_data[icode].operand[0].predicate) (op0, mode0)
+ || !(UNSIGNED_INT6 (INTVAL (op0))))
+ error ("operand of %s instruction should be an unsigned 6-bit value",
+ d->name);
+
+ pat = GEN_FCN (icode) (op0);
+ if (! pat)
+ return 0;
+
+ emit_insn (pat);
+ return NULL_RTX;
+
+ case void_rlimm:
+ icode = d->icode;
+ arg0 = CALL_EXPR_ARG (exp, 0);
+
+ fold (arg0);
+
+ op0 = expand_expr (arg0, NULL_RTX, SImode, EXPAND_NORMAL);
+ mode0 = insn_data[icode].operand[0].mode;
+
+ if (! (*insn_data[icode].operand[0].predicate) (op0, mode0))
+ op0 = copy_to_mode_reg (mode0, op0);
+
+ pat = GEN_FCN (icode) (op0);
+ if (! pat)
+ return 0;
+
+ emit_insn (pat);
+ return NULL_RTX;
+
+ case Va_Vb_Ic_u8:
+ {
+ rtx src_vreg;
+ icode = d->icode;
+ arg0 = CALL_EXPR_ARG (exp, 0); /* source vreg */
+ arg1 = CALL_EXPR_ARG (exp, 1); /* [I]0-7 */
+ arg2 = CALL_EXPR_ARG (exp, 2); /* u8 */
+
+ src_vreg = expand_expr (arg0, NULL_RTX, V8HImode, EXPAND_NORMAL);
+ op0 = expand_expr (arg1, NULL_RTX, SImode, EXPAND_NORMAL); /* [I]0-7 */
+ op1 = expand_expr (arg2, NULL_RTX, SImode, EXPAND_NORMAL); /* u8 */
+ op2 = gen_rtx_REG (V8HImode, ARC_FIRST_SIMD_VR_REG); /* VR0 */
+
+ /* target <- src vreg */
+ emit_insn (gen_move_insn (target, src_vreg));
+
+ /* target <- vec_concat: target, mem(Ib, u8) */
+ mode0 = insn_data[icode].operand[3].mode;
+ mode1 = insn_data[icode].operand[1].mode;
+
+ if ( (!(*insn_data[icode].operand[3].predicate) (op0, mode0))
+ || !(UNSIGNED_INT3 (INTVAL (op0))))
+ error ("operand 1 of %s instruction should be an unsigned 3-bit value (I0-I7)",
+ d->name);
+
+ if ( (!(*insn_data[icode].operand[1].predicate) (op1, mode1))
+ || !(UNSIGNED_INT8 (INTVAL (op1))))
+ error ("operand 2 of %s instruction should be an unsigned 8-bit value",
+ d->name);
+
+ pat = GEN_FCN (icode) (target, op1, op2, op0);
+ if (! pat)
+ return 0;
+
+ emit_insn (pat);
+ return target;
+ }
+
+ case void_Va_Ib_u8:
+ icode = d->icode;
+ arg0 = CALL_EXPR_ARG (exp, 0); /* src vreg */
+ arg1 = CALL_EXPR_ARG (exp, 1); /* [I]0-7 */
+ arg2 = CALL_EXPR_ARG (exp, 2); /* u8 */
+
+ op0 = gen_rtx_REG (V8HImode, ARC_FIRST_SIMD_VR_REG); /* VR0 */
+ op1 = expand_expr (arg1, NULL_RTX, SImode, EXPAND_NORMAL); /* I[0-7] */
+ op2 = expand_expr (arg2, NULL_RTX, SImode, EXPAND_NORMAL); /* u8 */
+ op3 = expand_expr (arg0, NULL_RTX, V8HImode, EXPAND_NORMAL); /* Vdest */
+
+ mode0 = insn_data[icode].operand[0].mode;
+ mode1 = insn_data[icode].operand[1].mode;
+ mode2 = insn_data[icode].operand[2].mode;
+ mode3 = insn_data[icode].operand[3].mode;
+
+ if ( (!(*insn_data[icode].operand[1].predicate) (op1, mode1))
+ || !(UNSIGNED_INT3 (INTVAL (op1))))
+ error ("operand 2 of %s instruction should be an unsigned 3-bit value (I0-I7)",
+ d->name);
+
+ if ( (!(*insn_data[icode].operand[2].predicate) (op2, mode2))
+ || !(UNSIGNED_INT8 (INTVAL (op2))))
+ error ("operand 3 of %s instruction should be an unsigned 8-bit value",
+ d->name);
+
+ if (!(*insn_data[icode].operand[3].predicate) (op3, mode3))
+ op3 = copy_to_mode_reg (mode3, op3);
+
+ pat = GEN_FCN (icode) (op0, op1, op2, op3);
+ if (! pat)
+ return 0;
+
+ emit_insn (pat);
+ return NULL_RTX;
+
+ case Va_Ib_u8:
+ icode = d->icode;
+ arg0 = CALL_EXPR_ARG (exp, 0); /* dest vreg */
+ arg1 = CALL_EXPR_ARG (exp, 1); /* [I]0-7 */
+
+ op0 = gen_rtx_REG (V8HImode, ARC_FIRST_SIMD_VR_REG); /* VR0 */
+ op1 = expand_expr (arg0, NULL_RTX, SImode, EXPAND_NORMAL); /* I[0-7] */
+ op2 = expand_expr (arg1, NULL_RTX, SImode, EXPAND_NORMAL); /* u8 */
+
+ /* target <- src vreg */
+ target = gen_reg_rtx (V8HImode);
+
+ /* target <- vec_concat: target, mem(Ib, u8) */
+ mode0 = insn_data[icode].operand[1].mode;
+ mode1 = insn_data[icode].operand[2].mode;
+ mode2 = insn_data[icode].operand[3].mode;
+
+ if ( (!(*insn_data[icode].operand[2].predicate) (op1, mode1))
+ || !(UNSIGNED_INT3 (INTVAL (op1))))
+ error ("operand 1 of %s instruction should be an unsigned 3-bit value (I0-I7)",
+ d->name);
+
+ if ( (!(*insn_data[icode].operand[3].predicate) (op2, mode2))
+ || !(UNSIGNED_INT8 (INTVAL (op2))))
+ error ("operand 2 of %s instruction should be an unsigned 8-bit value",
+ d->name);
+
+ pat = GEN_FCN (icode) (target, op0, op1, op2);
+ if (! pat)
+ return 0;
+
+ emit_insn (pat);
+ return target;
+
+ case void_Va_u3_Ib_u8:
+ icode = d->icode;
+ arg0 = CALL_EXPR_ARG (exp, 0); /* source vreg */
+ arg1 = CALL_EXPR_ARG (exp, 1); /* u3 */
+ arg2 = CALL_EXPR_ARG (exp, 2); /* [I]0-7 */
+ arg3 = CALL_EXPR_ARG (exp, 3); /* u8 */
+
+ op0 = expand_expr (arg3, NULL_RTX, SImode, EXPAND_NORMAL); /* u8 */
+ op1 = gen_rtx_REG (V8HImode, ARC_FIRST_SIMD_VR_REG); /* VR */
+ op2 = expand_expr (arg2, NULL_RTX, SImode, EXPAND_NORMAL); /* [I]0-7 */
+ op3 = expand_expr (arg0, NULL_RTX, V8HImode, EXPAND_NORMAL);/* vreg to be stored */
+ op4 = expand_expr (arg1, NULL_RTX, SImode, EXPAND_NORMAL); /* vreg 0-7 subreg no. */
+
+ mode0 = insn_data[icode].operand[0].mode;
+ mode2 = insn_data[icode].operand[2].mode;
+ mode3 = insn_data[icode].operand[3].mode;
+ mode4 = insn_data[icode].operand[4].mode;
+
+ /* Do some correctness checks for the operands. */
+ if ( (!(*insn_data[icode].operand[0].predicate) (op0, mode0))
+ || !(UNSIGNED_INT8 (INTVAL (op0))))
+ error ("operand 4 of %s instruction should be an unsigned 8-bit value (0-255)",
+ d->name);
+
+ if ( (!(*insn_data[icode].operand[2].predicate) (op2, mode2))
+ || !(UNSIGNED_INT3 (INTVAL (op2))))
+ error ("operand 3 of %s instruction should be an unsigned 3-bit value (I0-I7)",
+ d->name);
+
+ if (!(*insn_data[icode].operand[3].predicate) (op3, mode3))
+ op3 = copy_to_mode_reg (mode3, op3);
+
+ if ( (!(*insn_data[icode].operand[4].predicate) (op4, mode4))
+ || !(UNSIGNED_INT3 (INTVAL (op4))))
+ error ("operand 2 of %s instruction should be an unsigned 3-bit value (subreg 0-7)",
+ d->name);
+ else if (icode == CODE_FOR_vst32_n_insn
+ && ((INTVAL(op4) % 2 ) != 0))
+ error ("operand 2 of %s instruction should be an even 3-bit value (subreg 0,2,4,6)",
+ d->name);
+
+ pat = GEN_FCN (icode) (op0, op1, op2, op3, op4);
+ if (! pat)
+ return 0;
+
+ emit_insn (pat);
+ return NULL_RTX;
+
+ default:
+ gcc_unreachable ();
+ }
+ return NULL_RTX;
+}
+
+static bool
+arc_preserve_reload_p (rtx in)
+{
+ return (GET_CODE (in) == PLUS
+ && RTX_OK_FOR_BASE_P (XEXP (in, 0), true)
+ && CONST_INT_P (XEXP (in, 1))
+ && !((INTVAL (XEXP (in, 1)) & 511)));
+}
+
+int
+arc_register_move_cost (enum machine_mode,
+ enum reg_class from_class, enum reg_class to_class)
+{
+ /* The ARC600 has no bypass for extension registers, hence a nop might be
+ needed to be inserted after a write so that reads are safe. */
+ if (TARGET_ARC600)
+ {
+ if (to_class == MPY_WRITABLE_CORE_REGS)
+ return 3;
+ /* Instructions modifying LP_COUNT need 4 additional cycles before
+ the register will actually contain the value. */
+ else if (to_class == LPCOUNT_REG)
+ return 6;
+ else if (to_class == WRITABLE_CORE_REGS)
+ return 6;
+ }
+
+ /* The ARC700 stalls for 3 cycles when *reading* from lp_count. */
+ if (TARGET_ARC700
+ && (from_class == LPCOUNT_REG || from_class == ALL_CORE_REGS
+ || from_class == WRITABLE_CORE_REGS))
+ return 8;
+
+ /* Force an attempt to 'mov Dy,Dx' to spill. */
+ if (TARGET_ARC700 && TARGET_DPFP
+ && from_class == DOUBLE_REGS && to_class == DOUBLE_REGS)
+ return 100;
+
+ return 2;
+}
+
+/* Emit code for an addsi3 instruction with OPERANDS.
+ COND_P indicates if this will use conditional execution.
+ Return the length of the instruction.
+ If OUTPUT_P is false, don't actually output the instruction, just return
+ its length. */
+int
+arc_output_addsi (rtx *operands, bool cond_p, bool output_p)
+{
+ char format[32];
+
+ int match = operands_match_p (operands[0], operands[1]);
+ int match2 = operands_match_p (operands[0], operands[2]);
+ int intval = (REG_P (operands[2]) ? 1
+ : CONST_INT_P (operands[2]) ? INTVAL (operands[2]) : 0xbadc057);
+ int neg_intval = -intval;
+ int short_0 = satisfies_constraint_Rcq (operands[0]);
+ int short_p = (!cond_p && short_0 && satisfies_constraint_Rcq (operands[1]));
+ int ret = 0;
+
+#define ADDSI_OUTPUT1(FORMAT) do {\
+ if (output_p) \
+ output_asm_insn (FORMAT, operands);\
+ return ret; \
+} while (0)
+#define ADDSI_OUTPUT(LIST) do {\
+ if (output_p) \
+ sprintf LIST;\
+ ADDSI_OUTPUT1 (format);\
+ return ret; \
+} while (0)
+
+ /* First try to emit a 16 bit insn. */
+ ret = 2;
+ if (!cond_p
+ /* If we are actually about to output this insn, don't try a 16 bit
+ variant if we already decided that we don't want that
+ (I.e. we upsized this insn to align some following insn.)
+ E.g. add_s r0,sp,70 is 16 bit, but add r0,sp,70 requires a LIMM -
+ but add1 r0,sp,35 doesn't. */
+ && (!output_p || (get_attr_length (current_output_insn) & 2)))
+ {
+ if (short_p
+ && (REG_P (operands[2])
+ ? (match || satisfies_constraint_Rcq (operands[2]))
+ : (unsigned) intval <= (match ? 127 : 7)))
+ ADDSI_OUTPUT1 ("add%? %0,%1,%2");
+ if (short_0 && REG_P (operands[1]) && match2)
+ ADDSI_OUTPUT1 ("add%? %0,%2,%1");
+ if ((short_0 || REGNO (operands[0]) == STACK_POINTER_REGNUM)
+ && REGNO (operands[1]) == STACK_POINTER_REGNUM && !(intval & ~124))
+ ADDSI_OUTPUT1 ("add%? %0,%1,%2");
+
+ if ((short_p && (unsigned) neg_intval <= (match ? 31 : 7))
+ || (REGNO (operands[0]) == STACK_POINTER_REGNUM
+ && match && !(neg_intval & ~124)))
+ ADDSI_OUTPUT1 ("sub%? %0,%1,%n2");
+ }
+
+ /* Now try to emit a 32 bit insn without long immediate. */
+ ret = 4;
+ if (!match && match2 && REG_P (operands[1]))
+ ADDSI_OUTPUT1 ("add%? %0,%2,%1");
+ if (match || !cond_p)
+ {
+ int limit = (match && !cond_p) ? 0x7ff : 0x3f;
+ int range_factor = neg_intval & intval;
+ int shift;
+
+ if (intval == -1 << 31)
+ ADDSI_OUTPUT1 ("bxor%? %0,%1,31");
+
+ /* If we can use a straight add / sub instead of a {add,sub}[123] of
+ same size, do, so - the insn latency is lower. */
+ /* -0x800 is a 12-bit constant for add /add3 / sub / sub3, but
+ 0x800 is not. */
+ if ((intval >= 0 && intval <= limit)
+ || (intval == -0x800 && limit == 0x7ff))
+ ADDSI_OUTPUT1 ("add%? %0,%1,%2");
+ else if ((intval < 0 && neg_intval <= limit)
+ || (intval == 0x800 && limit == 0x7ff))
+ ADDSI_OUTPUT1 ("sub%? %0,%1,%n2");
+ shift = range_factor >= 8 ? 3 : (range_factor >> 1);
+ gcc_assert (shift == 0 || shift == 1 || shift == 2 || shift == 3);
+ gcc_assert ((((1 << shift) - 1) & intval) == 0);
+ if (((intval < 0 && intval != -0x4000)
+ /* sub[123] is slower than add_s / sub, only use it if it
+ avoids a long immediate. */
+ && neg_intval <= limit << shift)
+ || (intval == 0x4000 && limit == 0x7ff))
+ ADDSI_OUTPUT ((format, "sub%d%%? %%0,%%1,%d",
+ shift, neg_intval >> shift));
+ else if ((intval >= 0 && intval <= limit << shift)
+ || (intval == -0x4000 && limit == 0x7ff))
+ ADDSI_OUTPUT ((format, "add%d%%? %%0,%%1,%d", shift, intval >> shift));
+ }
+ /* Try to emit a 16 bit opcode with long immediate. */
+ ret = 6;
+ if (short_p && match)
+ ADDSI_OUTPUT1 ("add%? %0,%1,%S2");
+
+ /* We have to use a 32 bit opcode, and with a long immediate. */
+ ret = 8;
+ ADDSI_OUTPUT1 (intval < 0 ? "sub%? %0,%1,%n2" : "add%? %0,%1,%S2");
+}
+
+/* Emit code for an commutative_cond_exec instruction with OPERANDS.
+ Return the length of the instruction.
+ If OUTPUT_P is false, don't actually output the instruction, just return
+ its length. */
+int
+arc_output_commutative_cond_exec (rtx *operands, bool output_p)
+{
+ enum rtx_code commutative_op = GET_CODE (operands[3]);
+ const char *pat = NULL;
+
+ /* Canonical rtl should not have a constant in the first operand position. */
+ gcc_assert (!CONSTANT_P (operands[1]));
+
+ switch (commutative_op)
+ {
+ case AND:
+ if (satisfies_constraint_C1p (operands[2]))
+ pat = "bmsk%? %0,%1,%Z2";
+ else if (satisfies_constraint_Ccp (operands[2]))
+ pat = "bclr%? %0,%1,%M2";
+ else if (satisfies_constraint_CnL (operands[2]))
+ pat = "bic%? %0,%1,%n2-1";
+ break;
+ case IOR:
+ if (satisfies_constraint_C0p (operands[2]))
+ pat = "bset%? %0,%1,%z2";
+ break;
+ case XOR:
+ if (satisfies_constraint_C0p (operands[2]))
+ pat = "bxor%? %0,%1,%z2";
+ break;
+ case PLUS:
+ return arc_output_addsi (operands, true, output_p);
+ default: break;
+ }
+ if (output_p)
+ output_asm_insn (pat ? pat : "%O3.%d5 %0,%1,%2", operands);
+ if (pat || REG_P (operands[2]) || satisfies_constraint_L (operands[2]))
+ return 4;
+ return 8;
+}
+
+/* Helper function of arc_expand_movmem. ADDR points to a chunk of memory.
+ Emit code and return an potentially modified address such that offsets
+ up to SIZE are can be added to yield a legitimate address.
+ if REUSE is set, ADDR is a register that may be modified. */
+
+static rtx
+force_offsettable (rtx addr, HOST_WIDE_INT size, bool reuse)
+{
+ rtx base = addr;
+ rtx offs = const0_rtx;
+
+ if (GET_CODE (base) == PLUS)
+ {
+ offs = XEXP (base, 1);
+ base = XEXP (base, 0);
+ }
+ if (!REG_P (base)
+ || (REGNO (base) != STACK_POINTER_REGNUM
+ && REGNO_PTR_FRAME_P (REGNO (addr)))
+ || !CONST_INT_P (offs) || !SMALL_INT (INTVAL (offs))
+ || !SMALL_INT (INTVAL (offs) + size))
+ {
+ if (reuse)
+ emit_insn (gen_add2_insn (addr, offs));
+ else
+ addr = copy_to_mode_reg (Pmode, addr);
+ }
+ return addr;
+}
+
+/* Like move_by_pieces, but take account of load latency,
+ and actual offset ranges.
+ Return true on success. */
+
+bool
+arc_expand_movmem (rtx *operands)
+{
+ rtx dst = operands[0];
+ rtx src = operands[1];
+ rtx dst_addr, src_addr;
+ HOST_WIDE_INT size;
+ int align = INTVAL (operands[3]);
+ unsigned n_pieces;
+ int piece = align;
+ rtx store[2];
+ rtx tmpx[2];
+ int i;
+
+ if (!CONST_INT_P (operands[2]))
+ return false;
+ size = INTVAL (operands[2]);
+ /* move_by_pieces_ninsns is static, so we can't use it. */
+ if (align >= 4)
+ n_pieces = (size + 2) / 4U + (size & 1);
+ else if (align == 2)
+ n_pieces = (size + 1) / 2U;
+ else
+ n_pieces = size;
+ if (n_pieces >= (unsigned int) (optimize_size ? 3 : 15))
+ return false;
+ if (piece > 4)
+ piece = 4;
+ dst_addr = force_offsettable (XEXP (operands[0], 0), size, 0);
+ src_addr = force_offsettable (XEXP (operands[1], 0), size, 0);
+ store[0] = store[1] = NULL_RTX;
+ tmpx[0] = tmpx[1] = NULL_RTX;
+ for (i = 0; size > 0; i ^= 1, size -= piece)
+ {
+ rtx tmp;
+ enum machine_mode mode;
+
+ if (piece > size)
+ piece = size & -size;
+ mode = smallest_mode_for_size (piece * BITS_PER_UNIT, MODE_INT);
+ /* If we don't re-use temporaries, the scheduler gets carried away,
+ and the register pressure gets unnecessarily high. */
+ if (0 && tmpx[i] && GET_MODE (tmpx[i]) == mode)
+ tmp = tmpx[i];
+ else
+ tmpx[i] = tmp = gen_reg_rtx (mode);
+ dst_addr = force_offsettable (dst_addr, piece, 1);
+ src_addr = force_offsettable (src_addr, piece, 1);
+ if (store[i])
+ emit_insn (store[i]);
+ emit_move_insn (tmp, change_address (src, mode, src_addr));
+ store[i] = gen_move_insn (change_address (dst, mode, dst_addr), tmp);
+ dst_addr = plus_constant (Pmode, dst_addr, piece);
+ src_addr = plus_constant (Pmode, src_addr, piece);
+ }
+ if (store[i])
+ emit_insn (store[i]);
+ if (store[i^1])
+ emit_insn (store[i^1]);
+ return true;
+}
+
+/* Prepare operands for move in MODE. Return true iff the move has
+ been emitted. */
+
+bool
+prepare_move_operands (rtx *operands, enum machine_mode mode)
+{
+ /* We used to do this only for MODE_INT Modes, but addresses to floating
+ point variables may well be in the small data section. */
+ if (1)
+ {
+ if (!TARGET_NO_SDATA_SET && small_data_pattern (operands[0], Pmode))
+ operands[0] = arc_rewrite_small_data (operands[0]);
+ else if (mode == SImode && flag_pic && SYMBOLIC_CONST (operands[1]))
+ {
+ emit_pic_move (operands, SImode);
+
+ /* Disable any REG_EQUALs associated with the symref
+ otherwise the optimization pass undoes the work done
+ here and references the variable directly. */
+ }
+ else if (GET_CODE (operands[0]) != MEM
+ && !TARGET_NO_SDATA_SET
+ && small_data_pattern (operands[1], Pmode))
+ {
+ /* This is to take care of address calculations involving sdata
+ variables. */
+ operands[1] = arc_rewrite_small_data (operands[1]);
+
+ emit_insn (gen_rtx_SET (mode, operands[0],operands[1]));
+ /* ??? This note is useless, since it only restates the set itself.
+ We should rather use the original SYMBOL_REF. However, there is
+ the problem that we are lying to the compiler about these
+ SYMBOL_REFs to start with. symbol@sda should be encoded specially
+ so that we can tell it apart from an actual symbol. */
+ set_unique_reg_note (get_last_insn (), REG_EQUAL, operands[1]);
+
+ /* Take care of the REG_EQUAL note that will be attached to mark the
+ output reg equal to the initial symbol_ref after this code is
+ executed. */
+ emit_move_insn (operands[0], operands[0]);
+ return true;
+ }
+ }
+
+ if (MEM_P (operands[0])
+ && !(reload_in_progress || reload_completed))
+ {
+ operands[1] = force_reg (mode, operands[1]);
+ if (!move_dest_operand (operands[0], mode))
+ {
+ rtx addr = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
+ /* This is like change_address_1 (operands[0], mode, 0, 1) ,
+ except that we can't use that function because it is static. */
+ rtx pat = change_address (operands[0], mode, addr);
+ MEM_COPY_ATTRIBUTES (pat, operands[0]);
+ operands[0] = pat;
+ }
+ if (!cse_not_expected)
+ {
+ rtx pat = XEXP (operands[0], 0);
+
+ pat = arc_legitimize_address_0 (pat, pat, mode);
+ if (pat)
+ {
+ pat = change_address (operands[0], mode, pat);
+ MEM_COPY_ATTRIBUTES (pat, operands[0]);
+ operands[0] = pat;
+ }
+ }
+ }
+
+ if (MEM_P (operands[1]) && !cse_not_expected)
+ {
+ rtx pat = XEXP (operands[1], 0);
+
+ pat = arc_legitimize_address_0 (pat, pat, mode);
+ if (pat)
+ {
+ pat = change_address (operands[1], mode, pat);
+ MEM_COPY_ATTRIBUTES (pat, operands[1]);
+ operands[1] = pat;
+ }
+ }
+
+ return false;
+}
+
+/* Prepare OPERANDS for an extension using CODE to OMODE.
+ Return true iff the move has been emitted. */
+
+bool
+prepare_extend_operands (rtx *operands, enum rtx_code code,
+ enum machine_mode omode)
+{
+ if (!TARGET_NO_SDATA_SET && small_data_pattern (operands[1], Pmode))
+ {
+ /* This is to take care of address calculations involving sdata
+ variables. */
+ operands[1]
+ = gen_rtx_fmt_e (code, omode, arc_rewrite_small_data (operands[1]));
+ emit_insn (gen_rtx_SET (omode, operands[0], operands[1]));
+ set_unique_reg_note (get_last_insn (), REG_EQUAL, operands[1]);
+
+ /* Take care of the REG_EQUAL note that will be attached to mark the
+ output reg equal to the initial extension after this code is
+ executed. */
+ emit_move_insn (operands[0], operands[0]);
+ return true;
+ }
+ return false;
+}
+
+/* Output a library call to a function called FNAME that has been arranged
+ to be local to any dso. */
+
+const char *
+arc_output_libcall (const char *fname)
+{
+ unsigned len = strlen (fname);
+ static char buf[64];
+
+ gcc_assert (len < sizeof buf - 35);
+ if (TARGET_LONG_CALLS_SET
+ || (TARGET_MEDIUM_CALLS && arc_ccfsm_cond_exec_p ()))
+ {
+ if (flag_pic)
+ sprintf (buf, "add r12,pcl,@%s-(.&-4)\n\tjl%%!%%* [r12]", fname);
+ else
+ sprintf (buf, "jl%%! @%s", fname);
+ }
+ else
+ sprintf (buf, "bl%%!%%* @%s", fname);
+ return buf;
+}
+
+/* Return the SImode highpart of the DImode value IN. */
+
+rtx
+disi_highpart (rtx in)
+{
+ return simplify_gen_subreg (SImode, in, DImode, TARGET_BIG_ENDIAN ? 0 : 4);
+}
+
+/* Called by arc600_corereg_hazard via for_each_rtx.
+ If a hazard is found, return a conservative estimate of the required
+ length adjustment to accomodate a nop. */
+
+static int
+arc600_corereg_hazard_1 (rtx *xp, void *data)
+{
+ rtx x = *xp;
+ rtx dest;
+ rtx pat = (rtx) data;
+
+ switch (GET_CODE (x))
+ {
+ case SET: case POST_INC: case POST_DEC: case PRE_INC: case PRE_DEC:
+ break;
+ default:
+ /* This is also fine for PRE/POST_MODIFY, because they contain a SET. */
+ return 0;
+ }
+ dest = XEXP (x, 0);
+ /* Check if this sets a an extension register. N.B. we use 61 for the
+ condition codes, which is definitely not an extension register. */
+ if (REG_P (dest) && REGNO (dest) >= 32 && REGNO (dest) < 61
+ /* Check if the same register is used by the PAT. */
+ && (refers_to_regno_p
+ (REGNO (dest),
+ REGNO (dest) + (GET_MODE_SIZE (GET_MODE (dest)) + 3) / 4U, pat, 0)))
+ return 4;
+
+ return 0;
+}
+
+/* Return length adjustment for INSN.
+ For ARC600:
+ A write to a core reg greater or equal to 32 must not be immediately
+ followed by a use. Anticipate the length requirement to insert a nop
+ between PRED and SUCC to prevent a hazard. */
+
+static int
+arc600_corereg_hazard (rtx pred, rtx succ)
+{
+ if (!TARGET_ARC600)
+ return 0;
+ /* If SUCC is a doloop_end_i with a preceding label, we must output a nop
+ in front of SUCC anyway, so there will be separation between PRED and
+ SUCC. */
+ if (recog_memoized (succ) == CODE_FOR_doloop_end_i
+ && LABEL_P (prev_nonnote_insn (succ)))
+ return 0;
+ if (recog_memoized (succ) == CODE_FOR_doloop_begin_i)
+ return 0;
+ if (GET_CODE (PATTERN (pred)) == SEQUENCE)
+ pred = XVECEXP (PATTERN (pred), 0, 1);
+ if (GET_CODE (PATTERN (succ)) == SEQUENCE)
+ succ = XVECEXP (PATTERN (succ), 0, 0);
+ if (recog_memoized (pred) == CODE_FOR_mulsi_600
+ || recog_memoized (pred) == CODE_FOR_umul_600
+ || recog_memoized (pred) == CODE_FOR_mac_600
+ || recog_memoized (pred) == CODE_FOR_mul64_600
+ || recog_memoized (pred) == CODE_FOR_mac64_600
+ || recog_memoized (pred) == CODE_FOR_umul64_600
+ || recog_memoized (pred) == CODE_FOR_umac64_600)
+ return 0;
+ return for_each_rtx (&PATTERN (pred), arc600_corereg_hazard_1,
+ PATTERN (succ));
+}
+
+/* For ARC600:
+ A write to a core reg greater or equal to 32 must not be immediately
+ followed by a use. Anticipate the length requirement to insert a nop
+ between PRED and SUCC to prevent a hazard. */
+
+int
+arc_hazard (rtx pred, rtx succ)
+{
+ if (!TARGET_ARC600)
+ return 0;
+ if (!pred || !INSN_P (pred) || !succ || !INSN_P (succ))
+ return 0;
+ /* We might have a CALL to a non-returning function before a loop end.
+ ??? Although the manual says that's OK (the target is outside the loop,
+ and the loop counter unused there), the assembler barfs on this, so we
+ must instert a nop before such a call too. */
+ if (recog_memoized (succ) == CODE_FOR_doloop_end_i
+ && (JUMP_P (pred) || CALL_P (pred)
+ || GET_CODE (PATTERN (pred)) == SEQUENCE))
+ return 4;
+ return arc600_corereg_hazard (pred, succ);
+}
+
+/* Return length adjustment for INSN. */
+
+int
+arc_adjust_insn_length (rtx insn, int len, bool)
+{
+ if (!INSN_P (insn))
+ return len;
+ /* We already handle sequences by ignoring the delay sequence flag. */
+ if (GET_CODE (PATTERN (insn)) == SEQUENCE)
+ return len;
+
+ /* It is impossible to jump to the very end of a Zero-Overhead Loop, as
+ the ZOL mechanism only triggers when advancing to the end address,
+ so if there's a label at the end of a ZOL, we need to insert a nop.
+ The ARC600 ZOL also has extra restrictions on jumps at the end of a
+ loop. */
+ if (recog_memoized (insn) == CODE_FOR_doloop_end_i)
+ {
+ rtx prev = prev_nonnote_insn (insn);
+
+ return ((LABEL_P (prev)
+ || (TARGET_ARC600
+ && (JUMP_P (prev)
+ || CALL_P (prev) /* Could be a noreturn call. */
+ || (NONJUMP_INSN_P (prev)
+ && GET_CODE (PATTERN (prev)) == SEQUENCE))))
+ ? len + 4 : len);
+ }
+
+ /* Check for return with but one preceding insn since function
+ start / call. */
+ if (TARGET_PAD_RETURN
+ && JUMP_P (insn)
+ && GET_CODE (PATTERN (insn)) != ADDR_VEC
+ && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC
+ && get_attr_type (insn) == TYPE_RETURN)
+ {
+ rtx prev = prev_active_insn (insn);
+
+ if (!prev || !(prev = prev_active_insn (prev))
+ || ((NONJUMP_INSN_P (prev)
+ && GET_CODE (PATTERN (prev)) == SEQUENCE)
+ ? CALL_ATTR (XVECEXP (PATTERN (prev), 0, 0), NON_SIBCALL)
+ : CALL_ATTR (prev, NON_SIBCALL)))
+ return len + 4;
+ }
+ if (TARGET_ARC600)
+ {
+ rtx succ = next_real_insn (insn);
+
+ /* One the ARC600, a write to an extension register must be separated
+ from a read. */
+ if (succ && INSN_P (succ))
+ len += arc600_corereg_hazard (insn, succ);
+ }
+
+ /* Restore extracted operands - otherwise splitters like the addsi3_mixed one
+ can go awry. */
+ extract_constrain_insn_cached (insn);
+
+ return len;
+}
+
+/* Values for length_sensitive. */
+enum
+{
+ ARC_LS_NONE,// Jcc
+ ARC_LS_25, // 25 bit offset, B
+ ARC_LS_21, // 21 bit offset, Bcc
+ ARC_LS_U13,// 13 bit unsigned offset, LP
+ ARC_LS_10, // 10 bit offset, B_s, Beq_s, Bne_s
+ ARC_LS_9, // 9 bit offset, BRcc
+ ARC_LS_8, // 8 bit offset, BRcc_s
+ ARC_LS_U7, // 7 bit unsigned offset, LPcc
+ ARC_LS_7 // 7 bit offset, Bcc_s
+};
+
+/* While the infrastructure patch is waiting for review, duplicate the
+ struct definitions, to allow this file to compile. */
+#if 1
+typedef struct
+{
+ unsigned align_set;
+ /* Cost as a branch / call target or call return address. */
+ int target_cost;
+ int fallthrough_cost;
+ int branch_cost;
+ int length;
+ /* 0 for not length sensitive, 1 for largest offset range,
+ * 2 for next smaller etc. */
+ unsigned length_sensitive : 8;
+ bool enabled;
+} insn_length_variant_t;
+
+typedef struct insn_length_parameters_s
+{
+ int align_unit_log;
+ int align_base_log;
+ int max_variants;
+ int (*get_variants) (rtx, int, bool, bool, insn_length_variant_t *);
+} insn_length_parameters_t;
+
+static void
+arc_insn_length_parameters (insn_length_parameters_t *ilp) ATTRIBUTE_UNUSED;
+#endif
+
+static int
+arc_get_insn_variants (rtx insn, int len, bool, bool target_p,
+ insn_length_variant_t *ilv)
+{
+ if (!NONDEBUG_INSN_P (insn))
+ return 0;
+ enum attr_type type;
+ /* shorten_branches doesn't take optimize_size into account yet for the
+ get_variants mechanism, so turn this off for now. */
+ if (optimize_size)
+ return 0;
+ if (GET_CODE (PATTERN (insn)) == SEQUENCE)
+ {
+ /* The interaction of a short delay slot insn with a short branch is
+ too weird for shorten_branches to piece together, so describe the
+ entire SEQUENCE. */
+ rtx pat, inner;
+ if (TARGET_UPSIZE_DBR
+ && get_attr_length (XVECEXP ((pat = PATTERN (insn)), 0, 1)) <= 2
+ && (((type = get_attr_type (inner = XVECEXP (pat, 0, 0)))
+ == TYPE_UNCOND_BRANCH)
+ || type == TYPE_BRANCH)
+ && get_attr_delay_slot_filled (inner) == DELAY_SLOT_FILLED_YES)
+ {
+ int n_variants
+ = arc_get_insn_variants (inner, get_attr_length (inner), true,
+ target_p, ilv+1);
+ /* The short variant gets split into a higher-cost aligned
+ and a lower cost unaligned variant. */
+ gcc_assert (n_variants);
+ gcc_assert (ilv[1].length_sensitive == ARC_LS_7
+ || ilv[1].length_sensitive == ARC_LS_10);
+ gcc_assert (ilv[1].align_set == 3);
+ ilv[0] = ilv[1];
+ ilv[0].align_set = 1;
+ ilv[0].branch_cost += 1;
+ ilv[1].align_set = 2;
+ n_variants++;
+ for (int i = 0; i < n_variants; i++)
+ ilv[i].length += 2;
+ /* In case an instruction with aligned size is wanted, and
+ the short variants are unavailable / too expensive, add
+ versions of long branch + long delay slot. */
+ for (int i = 2, end = n_variants; i < end; i++, n_variants++)
+ {
+ ilv[n_variants] = ilv[i];
+ ilv[n_variants].length += 2;
+ }
+ return n_variants;
+ }
+ return 0;
+ }
+ insn_length_variant_t *first_ilv = ilv;
+ type = get_attr_type (insn);
+ bool delay_filled
+ = (get_attr_delay_slot_filled (insn) == DELAY_SLOT_FILLED_YES);
+ int branch_align_cost = delay_filled ? 0 : 1;
+ int branch_unalign_cost = delay_filled ? 0 : TARGET_UNALIGN_BRANCH ? 0 : 1;
+ /* If the previous instruction is an sfunc call, this insn is always
+ a target, even though the middle-end is unaware of this. */
+ bool force_target = false;
+ rtx prev = prev_active_insn (insn);
+ if (prev && arc_next_active_insn (prev, 0) == insn
+ && ((NONJUMP_INSN_P (prev) && GET_CODE (PATTERN (prev)) == SEQUENCE)
+ ? CALL_ATTR (XVECEXP (PATTERN (prev), 0, 0), NON_SIBCALL)
+ : (CALL_ATTR (prev, NON_SIBCALL)
+ && NEXT_INSN (PREV_INSN (prev)) == prev)))
+ force_target = true;
+
+ switch (type)
+ {
+ case TYPE_BRCC:
+ /* Short BRCC only comes in no-delay-slot version, and without limm */
+ if (!delay_filled)
+ {
+ ilv->align_set = 3;
+ ilv->length = 2;
+ ilv->branch_cost = 1;
+ ilv->enabled = (len == 2);
+ ilv->length_sensitive = ARC_LS_8;
+ ilv++;
+ }
+ /* Fall through. */
+ case TYPE_BRCC_NO_DELAY_SLOT:
+ /* doloop_fallback* patterns are TYPE_BRCC_NO_DELAY_SLOT for
+ (delay slot) scheduling purposes, but they are longer. */
+ if (GET_CODE (PATTERN (insn)) == PARALLEL
+ && GET_CODE (XVECEXP (PATTERN (insn), 0, 1)) == SET)
+ return 0;
+ /* Standard BRCC: 4 bytes, or 8 bytes with limm. */
+ ilv->length = ((type == TYPE_BRCC) ? 4 : 8);
+ ilv->align_set = 3;
+ ilv->branch_cost = branch_align_cost;
+ ilv->enabled = (len <= ilv->length);
+ ilv->length_sensitive = ARC_LS_9;
+ if ((target_p || force_target)
+ || (!delay_filled && TARGET_UNALIGN_BRANCH))
+ {
+ ilv[1] = *ilv;
+ ilv->align_set = 1;
+ ilv++;
+ ilv->align_set = 2;
+ ilv->target_cost = 1;
+ ilv->branch_cost = branch_unalign_cost;
+ }
+ ilv++;
+
+ rtx op, op0;
+ op = XEXP (SET_SRC (XVECEXP (PATTERN (insn), 0, 0)), 0);
+ op0 = XEXP (op, 0);
+
+ if (GET_CODE (op0) == ZERO_EXTRACT
+ && satisfies_constraint_L (XEXP (op0, 2)))
+ op0 = XEXP (op0, 0);
+ if (satisfies_constraint_Rcq (op0))
+ {
+ ilv->length = ((type == TYPE_BRCC) ? 6 : 10);
+ ilv->align_set = 3;
+ ilv->branch_cost = 1 + branch_align_cost;
+ ilv->fallthrough_cost = 1;
+ ilv->enabled = true;
+ ilv->length_sensitive = ARC_LS_21;
+ if (!delay_filled && TARGET_UNALIGN_BRANCH)
+ {
+ ilv[1] = *ilv;
+ ilv->align_set = 1;
+ ilv++;
+ ilv->align_set = 2;
+ ilv->branch_cost = 1 + branch_unalign_cost;
+ }
+ ilv++;
+ }
+ ilv->length = ((type == TYPE_BRCC) ? 8 : 12);
+ ilv->align_set = 3;
+ ilv->branch_cost = 1 + branch_align_cost;
+ ilv->fallthrough_cost = 1;
+ ilv->enabled = true;
+ ilv->length_sensitive = ARC_LS_21;
+ if ((target_p || force_target)
+ || (!delay_filled && TARGET_UNALIGN_BRANCH))
+ {
+ ilv[1] = *ilv;
+ ilv->align_set = 1;
+ ilv++;
+ ilv->align_set = 2;
+ ilv->target_cost = 1;
+ ilv->branch_cost = 1 + branch_unalign_cost;
+ }
+ ilv++;
+ break;
+
+ case TYPE_SFUNC:
+ ilv->length = 12;
+ goto do_call;
+ case TYPE_CALL_NO_DELAY_SLOT:
+ ilv->length = 8;
+ goto do_call;
+ case TYPE_CALL:
+ ilv->length = 4;
+ ilv->length_sensitive
+ = GET_CODE (PATTERN (insn)) == COND_EXEC ? ARC_LS_21 : ARC_LS_25;
+ do_call:
+ ilv->align_set = 3;
+ ilv->fallthrough_cost = branch_align_cost;
+ ilv->enabled = true;
+ if ((target_p || force_target)
+ || (!delay_filled && TARGET_UNALIGN_BRANCH))
+ {
+ ilv[1] = *ilv;
+ ilv->align_set = 1;
+ ilv++;
+ ilv->align_set = 2;
+ ilv->target_cost = 1;
+ ilv->fallthrough_cost = branch_unalign_cost;
+ }
+ ilv++;
+ break;
+ case TYPE_UNCOND_BRANCH:
+ /* Strictly speaking, this should be ARC_LS_10 for equality comparisons,
+ but that makes no difference at the moment. */
+ ilv->length_sensitive = ARC_LS_7;
+ ilv[1].length_sensitive = ARC_LS_25;
+ goto do_branch;
+ case TYPE_BRANCH:
+ ilv->length_sensitive = ARC_LS_10;
+ ilv[1].length_sensitive = ARC_LS_21;
+ do_branch:
+ ilv->align_set = 3;
+ ilv->length = 2;
+ ilv->branch_cost = branch_align_cost;
+ ilv->enabled = (len == ilv->length);
+ ilv++;
+ ilv->length = 4;
+ ilv->align_set = 3;
+ ilv->branch_cost = branch_align_cost;
+ ilv->enabled = true;
+ if ((target_p || force_target)
+ || (!delay_filled && TARGET_UNALIGN_BRANCH))
+ {
+ ilv[1] = *ilv;
+ ilv->align_set = 1;
+ ilv++;
+ ilv->align_set = 2;
+ ilv->target_cost = 1;
+ ilv->branch_cost = branch_unalign_cost;
+ }
+ ilv++;
+ break;
+ case TYPE_JUMP:
+ return 0;
+ default:
+ /* For every short insn, there is generally also a long insn.
+ trap_s is an exception. */
+ if ((len & 2) == 0 || recog_memoized (insn) == CODE_FOR_trap_s)
+ return 0;
+ ilv->align_set = 3;
+ ilv->length = len;
+ ilv->enabled = 1;
+ ilv++;
+ ilv->align_set = 3;
+ ilv->length = len + 2;
+ ilv->enabled = 1;
+ if (target_p || force_target)
+ {
+ ilv[1] = *ilv;
+ ilv->align_set = 1;
+ ilv++;
+ ilv->align_set = 2;
+ ilv->target_cost = 1;
+ }
+ ilv++;
+ }
+ /* If the previous instruction is an sfunc call, this insn is always
+ a target, even though the middle-end is unaware of this.
+ Therefore, if we have a call predecessor, transfer the target cost
+ to the fallthrough and branch costs. */
+ if (force_target)
+ {
+ for (insn_length_variant_t *p = first_ilv; p < ilv; p++)
+ {
+ p->fallthrough_cost += p->target_cost;
+ p->branch_cost += p->target_cost;
+ p->target_cost = 0;
+ }
+ }
+
+ return ilv - first_ilv;
+}
+
+static void
+arc_insn_length_parameters (insn_length_parameters_t *ilp)
+{
+ ilp->align_unit_log = 1;
+ ilp->align_base_log = 1;
+ ilp->max_variants = 7;
+ ilp->get_variants = arc_get_insn_variants;
+}
+
+/* Return a copy of COND from *STATEP, inverted if that is indicated by the
+ CC field of *STATEP. */
+
+static rtx
+arc_get_ccfsm_cond (struct arc_ccfsm *statep, bool reverse)
+{
+ rtx cond = statep->cond;
+ int raw_cc = get_arc_condition_code (cond);
+ if (reverse)
+ raw_cc = ARC_INVERSE_CONDITION_CODE (raw_cc);
+
+ if (statep->cc == raw_cc)
+ return copy_rtx (cond);
+
+ gcc_assert (ARC_INVERSE_CONDITION_CODE (raw_cc) == statep->cc);
+
+ enum machine_mode ccm = GET_MODE (XEXP (cond, 0));
+ enum rtx_code code = reverse_condition (GET_CODE (cond));
+ if (code == UNKNOWN || ccm == CC_FP_GTmode || ccm == CC_FP_GEmode)
+ code = reverse_condition_maybe_unordered (GET_CODE (cond));
+
+ return gen_rtx_fmt_ee (code, GET_MODE (cond),
+ copy_rtx (XEXP (cond, 0)), copy_rtx (XEXP (cond, 1)));
+}
+
+/* Use the ccfsm machinery to do if conversion. */
+
+static unsigned
+arc_ifcvt (void)
+{
+ struct arc_ccfsm *statep = &cfun->machine->ccfsm_current;
+ basic_block merge_bb = 0;
+
+ memset (statep, 0, sizeof *statep);
+ for (rtx insn = get_insns (); insn; insn = next_insn (insn))
+ {
+ arc_ccfsm_advance (insn, statep);
+
+ switch (statep->state)
+ {
+ case 0:
+ if (JUMP_P (insn))
+ merge_bb = 0;
+ break;
+ case 1: case 2:
+ {
+ /* Deleted branch. */
+ gcc_assert (!merge_bb);
+ merge_bb = BLOCK_FOR_INSN (insn);
+ basic_block succ_bb
+ = BLOCK_FOR_INSN (NEXT_INSN (NEXT_INSN (PREV_INSN (insn))));
+ arc_ccfsm_post_advance (insn, statep);
+ gcc_assert (!IN_RANGE (statep->state, 1, 2));
+ rtx seq = NEXT_INSN (PREV_INSN (insn));
+ if (seq != insn)
+ {
+ rtx slot = XVECEXP (PATTERN (seq), 0, 1);
+ rtx pat = PATTERN (slot);
+ if (INSN_ANNULLED_BRANCH_P (insn))
+ {
+ rtx cond
+ = arc_get_ccfsm_cond (statep, INSN_FROM_TARGET_P (slot));
+ pat = gen_rtx_COND_EXEC (VOIDmode, cond, pat);
+ }
+ if (!validate_change (seq, &PATTERN (seq), pat, 0))
+ gcc_unreachable ();
+ PUT_CODE (slot, NOTE);
+ NOTE_KIND (slot) = NOTE_INSN_DELETED;
+ if (merge_bb && succ_bb)
+ merge_blocks (merge_bb, succ_bb);
+ }
+ else if (merge_bb && succ_bb)
+ {
+ set_insn_deleted (insn);
+ merge_blocks (merge_bb, succ_bb);
+ }
+ else
+ {
+ PUT_CODE (insn, NOTE);
+ NOTE_KIND (insn) = NOTE_INSN_DELETED;
+ }
+ continue;
+ }
+ case 3:
+ if (LABEL_P (insn)
+ && statep->target_label == CODE_LABEL_NUMBER (insn))
+ {
+ arc_ccfsm_post_advance (insn, statep);
+ basic_block succ_bb = BLOCK_FOR_INSN (insn);
+ if (merge_bb && succ_bb)
+ merge_blocks (merge_bb, succ_bb);
+ else if (--LABEL_NUSES (insn) == 0)
+ {
+ const char *name = LABEL_NAME (insn);
+ PUT_CODE (insn, NOTE);
+ NOTE_KIND (insn) = NOTE_INSN_DELETED_LABEL;
+ NOTE_DELETED_LABEL_NAME (insn) = name;
+ }
+ merge_bb = 0;
+ continue;
+ }
+ /* Fall through. */
+ case 4: case 5:
+ if (!NONDEBUG_INSN_P (insn))
+ break;
+
+ /* Conditionalized insn. */
+
+ rtx prev, pprev, *patp, pat, cond;
+
+ /* If this is a delay slot insn in a non-annulled branch,
+ don't conditionalize it. N.B., this should be fine for
+ conditional return too. However, don't do this for
+ unconditional branches, as these would be encountered when
+ processing an 'else' part. */
+ prev = PREV_INSN (insn);
+ pprev = PREV_INSN (prev);
+ if (pprev && NEXT_INSN (NEXT_INSN (pprev)) == NEXT_INSN (insn)
+ && JUMP_P (prev) && get_attr_cond (prev) == COND_USE
+ && !INSN_ANNULLED_BRANCH_P (prev))
+ break;
+
+ patp = &PATTERN (insn);
+ pat = *patp;
+ cond = arc_get_ccfsm_cond (statep, INSN_FROM_TARGET_P (insn));
+ if (NONJUMP_INSN_P (insn) || CALL_P (insn))
+ {
+ /* ??? don't conditionalize if all side effects are dead
+ in the not-execute case. */
+
+ /* For commutative operators, we generally prefer to have
+ the first source match the destination. */
+ if (GET_CODE (pat) == SET)
+ {
+ rtx src = SET_SRC (pat);
+
+ if (COMMUTATIVE_P (src))
+ {
+ rtx src0 = XEXP (src, 0);
+ rtx src1 = XEXP (src, 1);
+ rtx dst = SET_DEST (pat);
+
+ if (rtx_equal_p (src1, dst) && !rtx_equal_p (src0, dst)
+ /* Leave add_n alone - the canonical form is to
+ have the complex summand first. */
+ && REG_P (src0))
+ pat = gen_rtx_SET (VOIDmode, dst,
+ gen_rtx_fmt_ee (GET_CODE (src),
+ GET_MODE (src),
+ src1, src0));
+ }
+ }
+
+ /* dwarf2out.c:dwarf2out_frame_debug_expr doesn't know
+ what to do with COND_EXEC. */
+ if (RTX_FRAME_RELATED_P (insn))
+ {
+ /* If this is the delay slot insn of an anulled branch,
+ dwarf2out.c:scan_trace understands the anulling semantics
+ without the COND_EXEC. */
+ gcc_assert
+ (pprev && NEXT_INSN (NEXT_INSN (pprev)) == NEXT_INSN (insn)
+ && JUMP_P (prev) && get_attr_cond (prev) == COND_USE
+ && INSN_ANNULLED_BRANCH_P (prev));
+ rtx note = alloc_reg_note (REG_FRAME_RELATED_EXPR, pat,
+ REG_NOTES (insn));
+ validate_change (insn, &REG_NOTES (insn), note, 1);
+ }
+ pat = gen_rtx_COND_EXEC (VOIDmode, cond, pat);
+ }
+ else if (simplejump_p (insn))
+ {
+ patp = &SET_SRC (pat);
+ pat = gen_rtx_IF_THEN_ELSE (VOIDmode, cond, *patp, pc_rtx);
+ }
+ else if (JUMP_P (insn) && ANY_RETURN_P (PATTERN (insn)))
+ {
+ pat = gen_rtx_IF_THEN_ELSE (VOIDmode, cond, pat, pc_rtx);
+ pat = gen_rtx_SET (VOIDmode, pc_rtx, pat);
+ }
+ else
+ gcc_unreachable ();
+ validate_change (insn, patp, pat, 1);
+ if (!apply_change_group ())
+ gcc_unreachable ();
+ if (JUMP_P (insn))
+ {
+ rtx next = next_nonnote_insn (insn);
+ if (GET_CODE (next) == BARRIER)
+ delete_insn (next);
+ if (statep->state == 3)
+ continue;
+ }
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ arc_ccfsm_post_advance (insn, statep);
+ }
+ return 0;
+}
+
+/* For ARC600: If a write to a core reg >=32 appears in a delay slot
+ (other than of a forward brcc), it creates a hazard when there is a read
+ of the same register at the branch target. We can't know what is at the
+ branch target of calls, and for branches, we don't really know before the
+ end of delay slot scheduling, either. Not only can individual instruction
+ be hoisted out into a delay slot, a basic block can also be emptied this
+ way, and branch and/or fall through targets be redirected. Hence we don't
+ want such writes in a delay slot. */
+/* Called by arc_write_ext_corereg via for_each_rtx. */
+
+static int
+write_ext_corereg_1 (rtx *xp, void *data ATTRIBUTE_UNUSED)
+{
+ rtx x = *xp;
+ rtx dest;
+
+ switch (GET_CODE (x))
+ {
+ case SET: case POST_INC: case POST_DEC: case PRE_INC: case PRE_DEC:
+ break;
+ default:
+ /* This is also fine for PRE/POST_MODIFY, because they contain a SET. */
+ return 0;
+ }
+ dest = XEXP (x, 0);
+ if (REG_P (dest) && REGNO (dest) >= 32 && REGNO (dest) < 61)
+ return 1;
+ return 0;
+}
+
+/* Return nonzreo iff INSN writes to an extension core register. */
+
+int
+arc_write_ext_corereg (rtx insn)
+{
+ return for_each_rtx (&PATTERN (insn), write_ext_corereg_1, 0);
+}
+
+/* This is like the hook, but returns NULL when it can't / won't generate
+ a legitimate address. */
+
+static rtx
+arc_legitimize_address_0 (rtx x, rtx oldx ATTRIBUTE_UNUSED,
+ enum machine_mode mode)
+{
+ rtx addr, inner;
+
+ if (flag_pic && SYMBOLIC_CONST (x))
+ (x) = arc_legitimize_pic_address (x, 0);
+ addr = x;
+ if (GET_CODE (addr) == CONST)
+ addr = XEXP (addr, 0);
+ if (GET_CODE (addr) == PLUS
+ && CONST_INT_P (XEXP (addr, 1))
+ && ((GET_CODE (XEXP (addr, 0)) == SYMBOL_REF
+ && !SYMBOL_REF_FUNCTION_P (XEXP (addr, 0)))
+ || (REG_P (XEXP (addr, 0))
+ && (INTVAL (XEXP (addr, 1)) & 252))))
+ {
+ HOST_WIDE_INT offs, upper;
+ int size = GET_MODE_SIZE (mode);
+
+ offs = INTVAL (XEXP (addr, 1));
+ upper = (offs + 256 * size) & ~511 * size;
+ inner = plus_constant (Pmode, XEXP (addr, 0), upper);
+#if 0 /* ??? this produces worse code for EEMBC idctrn01 */
+ if (GET_CODE (x) == CONST)
+ inner = gen_rtx_CONST (Pmode, inner);
+#endif
+ addr = plus_constant (Pmode, force_reg (Pmode, inner), offs - upper);
+ x = addr;
+ }
+ else if (GET_CODE (addr) == SYMBOL_REF && !SYMBOL_REF_FUNCTION_P (addr))
+ x = force_reg (Pmode, x);
+ if (memory_address_p ((enum machine_mode) mode, x))
+ return x;
+ return NULL_RTX;
+}
+
+static rtx
+arc_legitimize_address (rtx orig_x, rtx oldx, enum machine_mode mode)
+{
+ rtx new_x = arc_legitimize_address_0 (orig_x, oldx, mode);
+
+ if (new_x)
+ return new_x;
+ return orig_x;
+}
+
+static rtx
+arc_delegitimize_address_0 (rtx x)
+{
+ rtx u, gp;
+
+ if (GET_CODE (x) == CONST && GET_CODE (u = XEXP (x, 0)) == UNSPEC)
+ {
+ if (XINT (u, 1) == ARC_UNSPEC_GOT)
+ return XVECEXP (u, 0, 0);
+ }
+ else if (GET_CODE (x) == PLUS
+ && ((REG_P (gp = XEXP (x, 0))
+ && REGNO (gp) == PIC_OFFSET_TABLE_REGNUM)
+ || (GET_CODE (gp) == CONST
+ && GET_CODE (u = XEXP (gp, 0)) == UNSPEC
+ && XINT (u, 1) == ARC_UNSPEC_GOT
+ && GET_CODE (XVECEXP (u, 0, 0)) == SYMBOL_REF
+ && !strcmp (XSTR (XVECEXP (u, 0, 0), 0), "_DYNAMIC")))
+ && GET_CODE (XEXP (x, 1)) == CONST
+ && GET_CODE (u = XEXP (XEXP (x, 1), 0)) == UNSPEC
+ && XINT (u, 1) == ARC_UNSPEC_GOTOFF)
+ return XVECEXP (u, 0, 0);
+ else if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == PLUS
+ && ((REG_P (gp = XEXP (XEXP (x, 0), 1))
+ && REGNO (gp) == PIC_OFFSET_TABLE_REGNUM)
+ || (GET_CODE (gp) == CONST
+ && GET_CODE (u = XEXP (gp, 0)) == UNSPEC
+ && XINT (u, 1) == ARC_UNSPEC_GOT
+ && GET_CODE (XVECEXP (u, 0, 0)) == SYMBOL_REF
+ && !strcmp (XSTR (XVECEXP (u, 0, 0), 0), "_DYNAMIC")))
+ && GET_CODE (XEXP (x, 1)) == CONST
+ && GET_CODE (u = XEXP (XEXP (x, 1), 0)) == UNSPEC
+ && XINT (u, 1) == ARC_UNSPEC_GOTOFF)
+ return gen_rtx_PLUS (GET_MODE (x), XEXP (XEXP (x, 0), 0),
+ XVECEXP (u, 0, 0));
+ else if (GET_CODE (x) == PLUS
+ && (u = arc_delegitimize_address_0 (XEXP (x, 1))))
+ return gen_rtx_PLUS (GET_MODE (x), XEXP (x, 0), u);
+ return NULL_RTX;
+}
+
+static rtx
+arc_delegitimize_address (rtx x)
+{
+ rtx orig_x = x = delegitimize_mem_from_attrs (x);
+ if (GET_CODE (x) == MEM)
+ x = XEXP (x, 0);
+ x = arc_delegitimize_address_0 (x);
+ if (x)
+ {
+ if (MEM_P (orig_x))
+ x = replace_equiv_address_nv (orig_x, x);
+ return x;
+ }
+ return orig_x;
+}
+
+/* Return a REG rtx for acc1. N.B. the gcc-internal representation may
+ differ from the hardware register number in order to allow the generic
+ code to correctly split the concatenation of acc1 and acc2. */
+
+rtx
+gen_acc1 (void)
+{
+ return gen_rtx_REG (SImode, TARGET_BIG_ENDIAN ? 56: 57);
+}
+
+/* Return a REG rtx for acc2. N.B. the gcc-internal representation may
+ differ from the hardware register number in order to allow the generic
+ code to correctly split the concatenation of acc1 and acc2. */
+
+rtx
+gen_acc2 (void)
+{
+ return gen_rtx_REG (SImode, TARGET_BIG_ENDIAN ? 57: 56);
+}
+
+/* Return a REG rtx for mlo. N.B. the gcc-internal representation may
+ differ from the hardware register number in order to allow the generic
+ code to correctly split the concatenation of mhi and mlo. */
+
+rtx
+gen_mlo (void)
+{
+ return gen_rtx_REG (SImode, TARGET_BIG_ENDIAN ? 59: 58);
+}
+
+/* Return a REG rtx for mhi. N.B. the gcc-internal representation may
+ differ from the hardware register number in order to allow the generic
+ code to correctly split the concatenation of mhi and mlo. */
+
+rtx
+gen_mhi (void)
+{
+ return gen_rtx_REG (SImode, TARGET_BIG_ENDIAN ? 58: 59);
+}
+
+/* FIXME: a parameter should be added, and code added to final.c,
+ to reproduce this functionality in shorten_branches. */
+#if 0
+/* Return nonzero iff BRANCH should be unaligned if possible by upsizing
+ a previous instruction. */
+int
+arc_unalign_branch_p (rtx branch)
+{
+ rtx note;
+
+ if (!TARGET_UNALIGN_BRANCH)
+ return 0;
+ /* Do not do this if we have a filled delay slot. */
+ if (get_attr_delay_slot_filled (branch) == DELAY_SLOT_FILLED_YES
+ && !INSN_DELETED_P (NEXT_INSN (branch)))
+ return 0;
+ note = find_reg_note (branch, REG_BR_PROB, 0);
+ return (!note
+ || (arc_unalign_prob_threshold && !br_prob_note_reliable_p (note))
+ || INTVAL (XEXP (note, 0)) < arc_unalign_prob_threshold);
+}
+#endif
+
+/* When estimating sizes during arc_reorg, when optimizing for speed, there
+ are three reasons why we need to consider branches to be length 6:
+ - annull-false delay slot insns are implemented using conditional execution,
+ thus preventing short insn formation where used.
+ - for ARC600: annul-true delay slot insns are implemented where possible
+ using conditional execution, preventing short insn formation where used.
+ - for ARC700: likely or somewhat likely taken branches are made long and
+ unaligned if possible to avoid branch penalty. */
+
+bool
+arc_branch_size_unknown_p (void)
+{
+ return !optimize_size && arc_reorg_in_progress;
+}
+
+/* We are about to output a return insn. Add padding if necessary to avoid
+ a mispredict. A return could happen immediately after the function
+ start, but after a call we know that there will be at least a blink
+ restore. */
+
+void
+arc_pad_return (void)
+{
+ rtx insn = current_output_insn;
+ rtx prev = prev_active_insn (insn);
+ int want_long;
+
+ if (!prev)
+ {
+ fputs ("\tnop_s\n", asm_out_file);
+ cfun->machine->unalign ^= 2;
+ want_long = 1;
+ }
+ /* If PREV is a sequence, we know it must be a branch / jump or a tailcall,
+ because after a call, we'd have to restore blink first. */
+ else if (GET_CODE (PATTERN (prev)) == SEQUENCE)
+ return;
+ else
+ {
+ want_long = (get_attr_length (prev) == 2);
+ prev = prev_active_insn (prev);
+ }
+ if (!prev
+ || ((NONJUMP_INSN_P (prev) && GET_CODE (PATTERN (prev)) == SEQUENCE)
+ ? CALL_ATTR (XVECEXP (PATTERN (prev), 0, 0), NON_SIBCALL)
+ : CALL_ATTR (prev, NON_SIBCALL)))
+ {
+ if (want_long)
+ cfun->machine->size_reason
+ = "call/return and return/return must be 6 bytes apart to avoid mispredict";
+ else if (TARGET_UNALIGN_BRANCH && cfun->machine->unalign)
+ {
+ cfun->machine->size_reason
+ = "Long unaligned jump avoids non-delay slot penalty";
+ want_long = 1;
+ }
+ /* Disgorge delay insn, if there is any, and it may be moved. */
+ if (final_sequence
+ /* ??? Annulled would be OK if we can and do conditionalize
+ the delay slot insn accordingly. */
+ && !INSN_ANNULLED_BRANCH_P (insn)
+ && (get_attr_cond (insn) != COND_USE
+ || !reg_set_p (gen_rtx_REG (CCmode, CC_REG),
+ XVECEXP (final_sequence, 0, 1))))
+ {
+ prev = XVECEXP (final_sequence, 0, 1);
+ gcc_assert (!prev_real_insn (insn)
+ || !arc_hazard (prev_real_insn (insn), prev));
+ cfun->machine->force_short_suffix = !want_long;
+ rtx save_pred = current_insn_predicate;
+ final_scan_insn (prev, asm_out_file, optimize, 1, NULL);
+ cfun->machine->force_short_suffix = -1;
+ INSN_DELETED_P (prev) = 1;
+ current_output_insn = insn;
+ current_insn_predicate = save_pred;
+ }
+ else if (want_long)
+ fputs ("\tnop\n", asm_out_file);
+ else
+ {
+ fputs ("\tnop_s\n", asm_out_file);
+ cfun->machine->unalign ^= 2;
+ }
+ }
+ return;
+}
+
+/* The usual; we set up our machine_function data. */
+
+static struct machine_function *
+arc_init_machine_status (void)
+{
+ struct machine_function *machine;
+ machine = ggc_alloc_cleared_machine_function ();
+ machine->fn_type = ARC_FUNCTION_UNKNOWN;
+ machine->force_short_suffix = -1;
+
+ return machine;
+}
+
+/* Implements INIT_EXPANDERS. We just set up to call the above
+ function. */
+
+void
+arc_init_expanders (void)
+{
+ init_machine_status = arc_init_machine_status;
+}
+
+/* Check if OP is a proper parallel of a millicode call pattern. OFFSET
+ indicates a number of elements to ignore - that allows to have a
+ sibcall pattern that starts with (return). LOAD_P is zero for store
+ multiple (for prologues), and one for load multiples (for epilogues),
+ and two for load multiples where no final clobber of blink is required.
+ We also skip the first load / store element since this is supposed to
+ be checked in the instruction pattern. */
+
+int
+arc_check_millicode (rtx op, int offset, int load_p)
+{
+ int len = XVECLEN (op, 0) - offset;
+ int i;
+
+ if (load_p == 2)
+ {
+ if (len < 2 || len > 13)
+ return 0;
+ load_p = 1;
+ }
+ else
+ {
+ rtx elt = XVECEXP (op, 0, --len);
+
+ if (GET_CODE (elt) != CLOBBER
+ || !REG_P (XEXP (elt, 0))
+ || REGNO (XEXP (elt, 0)) != RETURN_ADDR_REGNUM
+ || len < 3 || len > 13)
+ return 0;
+ }
+ for (i = 1; i < len; i++)
+ {
+ rtx elt = XVECEXP (op, 0, i + offset);
+ rtx reg, mem, addr;
+
+ if (GET_CODE (elt) != SET)
+ return 0;
+ mem = XEXP (elt, load_p);
+ reg = XEXP (elt, 1-load_p);
+ if (!REG_P (reg) || REGNO (reg) != 13U+i || !MEM_P (mem))
+ return 0;
+ addr = XEXP (mem, 0);
+ if (GET_CODE (addr) != PLUS
+ || !rtx_equal_p (stack_pointer_rtx, XEXP (addr, 0))
+ || !CONST_INT_P (XEXP (addr, 1)) || INTVAL (XEXP (addr, 1)) != i*4)
+ return 0;
+ }
+ return 1;
+}
+
+/* Accessor functions for cfun->machine->unalign. */
+
+int
+arc_get_unalign (void)
+{
+ return cfun->machine->unalign;
+}
+
+void
+arc_clear_unalign (void)
+{
+ if (cfun)
+ cfun->machine->unalign = 0;
+}
+
+void
+arc_toggle_unalign (void)
+{
+ cfun->machine->unalign ^= 2;
+}
+
+/* Operands 0..2 are the operands of a addsi which uses a 12 bit
+ constant in operand 2, but which would require a LIMM because of
+ operand mismatch.
+ operands 3 and 4 are new SET_SRCs for operands 0. */
+
+void
+split_addsi (rtx *operands)
+{
+ int val = INTVAL (operands[2]);
+
+ /* Try for two short insns first. Lengths being equal, we prefer
+ expansions with shorter register lifetimes. */
+ if (val > 127 && val <= 255
+ && satisfies_constraint_Rcq (operands[0]))
+ {
+ operands[3] = operands[2];
+ operands[4] = gen_rtx_PLUS (SImode, operands[0], operands[1]);
+ }
+ else
+ {
+ operands[3] = operands[1];
+ operands[4] = gen_rtx_PLUS (SImode, operands[0], operands[2]);
+ }
+}
+
+/* Operands 0..2 are the operands of a subsi which uses a 12 bit
+ constant in operand 1, but which would require a LIMM because of
+ operand mismatch.
+ operands 3 and 4 are new SET_SRCs for operands 0. */
+
+void
+split_subsi (rtx *operands)
+{
+ int val = INTVAL (operands[1]);
+
+ /* Try for two short insns first. Lengths being equal, we prefer
+ expansions with shorter register lifetimes. */
+ if (satisfies_constraint_Rcq (operands[0])
+ && satisfies_constraint_Rcq (operands[2]))
+ {
+ if (val >= -31 && val <= 127)
+ {
+ operands[3] = gen_rtx_NEG (SImode, operands[2]);
+ operands[4] = gen_rtx_PLUS (SImode, operands[0], operands[1]);
+ return;
+ }
+ else if (val >= 0 && val < 255)
+ {
+ operands[3] = operands[1];
+ operands[4] = gen_rtx_MINUS (SImode, operands[0], operands[2]);
+ return;
+ }
+ }
+ /* If the destination is not an ARCompact16 register, we might
+ still have a chance to make a short insn if the source is;
+ we need to start with a reg-reg move for this. */
+ operands[3] = operands[2];
+ operands[4] = gen_rtx_MINUS (SImode, operands[1], operands[0]);
+}
+
+/* Handle DOUBLE_REGS uses.
+ Operand 0: destination register
+ Operand 1: source register */
+
+static rtx
+arc_process_double_reg_moves (rtx *operands)
+{
+ rtx dest = operands[0];
+ rtx src = operands[1];
+ rtx val;
+
+ enum usesDxState { none, srcDx, destDx, maxDx };
+ enum usesDxState state = none;
+
+ if (refers_to_regno_p (40, 44, src, 0))
+ state = srcDx;
+ if (refers_to_regno_p (40, 44, dest, 0))
+ {
+ /* Via arc_register_move_cost, we should never see D,D moves. */
+ gcc_assert (state == none);
+ state = destDx;
+ }
+
+ if (state == none)
+ return NULL_RTX;
+
+ start_sequence ();
+
+ if (state == srcDx)
+ {
+ /* Without the LR insn, we need to split this into a
+ sequence of insns which will use the DEXCLx and DADDHxy
+ insns to be able to read the Dx register in question. */
+ if (TARGET_DPFP_DISABLE_LRSR)
+ {
+ /* gen *movdf_insn_nolrsr */
+ rtx set = gen_rtx_SET (VOIDmode, dest, src);
+ rtx use1 = gen_rtx_USE (VOIDmode, const1_rtx);
+ emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, set, use1)));
+ }
+ else
+ {
+ /* When we have 'mov D, r' or 'mov D, D' then get the target
+ register pair for use with LR insn. */
+ rtx destHigh = simplify_gen_subreg(SImode, dest, DFmode, 4);
+ rtx destLow = simplify_gen_subreg(SImode, dest, DFmode, 0);
+
+ /* Produce the two LR insns to get the high and low parts. */
+ emit_insn (gen_rtx_SET (VOIDmode,
+ destHigh,
+ gen_rtx_UNSPEC_VOLATILE (Pmode, gen_rtvec (1, src),
+ VUNSPEC_LR_HIGH)));
+ emit_insn (gen_rtx_SET (VOIDmode,
+ destLow,
+ gen_rtx_UNSPEC_VOLATILE (Pmode, gen_rtvec (1, src),
+ VUNSPEC_LR)));
+ }
+ }
+ else if (state == destDx)
+ {
+ /* When we have 'mov r, D' or 'mov D, D' and we have access to the
+ LR insn get the target register pair. */
+ rtx srcHigh = simplify_gen_subreg(SImode, src, DFmode, 4);
+ rtx srcLow = simplify_gen_subreg(SImode, src, DFmode, 0);
+
+ emit_insn (gen_rtx_UNSPEC_VOLATILE (Pmode,
+ gen_rtvec (3, dest, srcHigh, srcLow),
+ VUNSPEC_DEXCL_NORES));
+
+ }
+ else
+ gcc_unreachable ();
+
+ val = get_insns ();
+ end_sequence ();
+ return val;
+}
+
+/* operands 0..1 are the operands of a 64 bit move instruction.
+ split it into two moves with operands 2/3 and 4/5. */
+
+rtx
+arc_split_move (rtx *operands)
+{
+ enum machine_mode mode = GET_MODE (operands[0]);
+ int i;
+ int swap = 0;
+ rtx xop[4];
+ rtx val;
+
+ if (TARGET_DPFP)
+ {
+ val = arc_process_double_reg_moves (operands);
+ if (val)
+ return val;
+ }
+
+ for (i = 0; i < 2; i++)
+ {
+ if (MEM_P (operands[i]) && auto_inc_p (XEXP (operands[i], 0)))
+ {
+ rtx addr = XEXP (operands[i], 0);
+ rtx r, o;
+ enum rtx_code code;
+
+ gcc_assert (!reg_overlap_mentioned_p (operands[0], addr));
+ switch (GET_CODE (addr))
+ {
+ case PRE_DEC: o = GEN_INT (-8); goto pre_modify;
+ case PRE_INC: o = GEN_INT (8); goto pre_modify;
+ case PRE_MODIFY: o = XEXP (XEXP (addr, 1), 1);
+ pre_modify:
+ code = PRE_MODIFY;
+ break;
+ case POST_DEC: o = GEN_INT (-8); goto post_modify;
+ case POST_INC: o = GEN_INT (8); goto post_modify;
+ case POST_MODIFY: o = XEXP (XEXP (addr, 1), 1);
+ post_modify:
+ code = POST_MODIFY;
+ swap = 2;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ r = XEXP (addr, 0);
+ xop[0+i] = adjust_automodify_address_nv
+ (operands[i], SImode,
+ gen_rtx_fmt_ee (code, Pmode, r,
+ gen_rtx_PLUS (Pmode, r, o)),
+ 0);
+ xop[2+i] = adjust_automodify_address_nv
+ (operands[i], SImode, plus_constant (Pmode, r, 4), 4);
+ }
+ else
+ {
+ xop[0+i] = operand_subword (operands[i], 0, 0, mode);
+ xop[2+i] = operand_subword (operands[i], 1, 0, mode);
+ }
+ }
+ if (reg_overlap_mentioned_p (xop[0], xop[3]))
+ {
+ swap = 2;
+ gcc_assert (!reg_overlap_mentioned_p (xop[2], xop[1]));
+ }
+ operands[2+swap] = xop[0];
+ operands[3+swap] = xop[1];
+ operands[4-swap] = xop[2];
+ operands[5-swap] = xop[3];
+
+ start_sequence ();
+ emit_insn (gen_rtx_SET (VOIDmode, operands[2], operands[3]));
+ emit_insn (gen_rtx_SET (VOIDmode, operands[4], operands[5]));
+ val = get_insns ();
+ end_sequence ();
+
+ return val;
+}
+
+/* Select between the instruction output templates s_tmpl (for short INSNs)
+ and l_tmpl (for long INSNs). */
+
+const char *
+arc_short_long (rtx insn, const char *s_tmpl, const char *l_tmpl)
+{
+ int is_short = arc_verify_short (insn, cfun->machine->unalign, -1);
+
+ extract_constrain_insn_cached (insn);
+ return is_short ? s_tmpl : l_tmpl;
+}
+
+/* Searches X for any reference to REGNO, returning the rtx of the
+ reference found if any. Otherwise, returns NULL_RTX. */
+
+rtx
+arc_regno_use_in (unsigned int regno, rtx x)
+{
+ const char *fmt;
+ int i, j;
+ rtx tem;
+
+ if (REG_P (x) && refers_to_regno_p (regno, regno+1, x, (rtx *) 0))
+ return x;
+
+ fmt = GET_RTX_FORMAT (GET_CODE (x));
+ for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
+ {
+ if (fmt[i] == 'e')
+ {
+ if ((tem = regno_use_in (regno, XEXP (x, i))))
+ return tem;
+ }
+ else if (fmt[i] == 'E')
+ for (j = XVECLEN (x, i) - 1; j >= 0; j--)
+ if ((tem = regno_use_in (regno , XVECEXP (x, i, j))))
+ return tem;
+ }
+
+ return NULL_RTX;
+}
+
+/* Return the integer value of the "type" attribute for INSN, or -1 if
+ INSN can't have attributes. */
+
+int
+arc_attr_type (rtx insn)
+{
+ if (NONJUMP_INSN_P (insn)
+ ? (GET_CODE (PATTERN (insn)) == USE
+ || GET_CODE (PATTERN (insn)) == CLOBBER)
+ : JUMP_P (insn)
+ ? (GET_CODE (PATTERN (insn)) == ADDR_VEC
+ || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
+ : !CALL_P (insn))
+ return -1;
+ return get_attr_type (insn);
+}
+
+/* Return true if insn sets the condition codes. */
+
+bool
+arc_sets_cc_p (rtx insn)
+{
+ if (NONJUMP_INSN_P (insn) && GET_CODE (PATTERN (insn)) == SEQUENCE)
+ insn = XVECEXP (PATTERN (insn), 0, XVECLEN (PATTERN (insn), 0) - 1);
+ return arc_attr_type (insn) == TYPE_COMPARE;
+}
+
+/* Return true if INSN is an instruction with a delay slot we may want
+ to fill. */
+
+bool
+arc_need_delay (rtx insn)
+{
+ rtx next;
+
+ if (!flag_delayed_branch)
+ return false;
+ /* The return at the end of a function needs a delay slot. */
+ if (NONJUMP_INSN_P (insn) && GET_CODE (PATTERN (insn)) == USE
+ && (!(next = next_active_insn (insn))
+ || ((!NONJUMP_INSN_P (next) || GET_CODE (PATTERN (next)) != SEQUENCE)
+ && arc_attr_type (next) == TYPE_RETURN))
+ && (!TARGET_PAD_RETURN
+ || (prev_active_insn (insn)
+ && prev_active_insn (prev_active_insn (insn))
+ && prev_active_insn (prev_active_insn (prev_active_insn (insn))))))
+ return true;
+ if (NONJUMP_INSN_P (insn)
+ ? (GET_CODE (PATTERN (insn)) == USE
+ || GET_CODE (PATTERN (insn)) == CLOBBER
+ || GET_CODE (PATTERN (insn)) == SEQUENCE)
+ : JUMP_P (insn)
+ ? (GET_CODE (PATTERN (insn)) == ADDR_VEC
+ || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
+ : !CALL_P (insn))
+ return false;
+ return num_delay_slots (insn) != 0;
+}
+
+/* Return true if the scheduling pass(es) has/have already run,
+ i.e. where possible, we should try to mitigate high latencies
+ by different instruction selection. */
+
+bool
+arc_scheduling_not_expected (void)
+{
+ return cfun->machine->arc_reorg_started;
+}
+
+/* Oddly enough, sometimes we get a zero overhead loop that branch
+ shortening doesn't think is a loop - observed with compile/pr24883.c
+ -O3 -fomit-frame-pointer -funroll-loops. Make sure to include the
+ alignment visible for branch shortening (we actually align the loop
+ insn before it, but that is equivalent since the loop insn is 4 byte
+ long.) */
+
+int
+arc_label_align (rtx label)
+{
+ int loop_align = LOOP_ALIGN (LABEL);
+
+ if (loop_align > align_labels_log)
+ {
+ rtx prev = prev_nonnote_insn (label);
+
+ if (prev && NONJUMP_INSN_P (prev)
+ && GET_CODE (PATTERN (prev)) == PARALLEL
+ && recog_memoized (prev) == CODE_FOR_doloop_begin_i)
+ return loop_align;
+ }
+ /* Code has a minimum p2 alignment of 1, which we must restore after an
+ ADDR_DIFF_VEC. */
+ if (align_labels_log < 1)
+ {
+ rtx next = next_nonnote_nondebug_insn (label);
+ if (INSN_P (next) && recog_memoized (next) >= 0)
+ return 1;
+ }
+ return align_labels_log;
+}
+
+/* Return true if LABEL is in executable code. */
+
+bool
+arc_text_label (rtx label)
+{
+ rtx next;
+
+ /* ??? We use deleted labels like they were still there, see
+ gcc.c-torture/compile/20000326-2.c . */
+ gcc_assert (GET_CODE (label) == CODE_LABEL
+ || (GET_CODE (label) == NOTE
+ && NOTE_KIND (label) == NOTE_INSN_DELETED_LABEL));
+ next = next_nonnote_insn (label);
+ if (next)
+ return (!JUMP_TABLE_DATA_P (next)
+ || GET_CODE (PATTERN (next)) != ADDR_VEC);
+ else if (!PREV_INSN (label))
+ /* ??? sometimes text labels get inserted very late, see
+ gcc.dg/torture/stackalign/comp-goto-1.c */
+ return true;
+ return false;
+}
+
+/* Return the size of the pretend args for DECL. */
+
+int
+arc_decl_pretend_args (tree decl)
+{
+ /* struct function is in DECL_STRUCT_FUNCTION (decl), but no
+ pretend_args there... See PR38391. */
+ gcc_assert (decl == current_function_decl);
+ return crtl->args.pretend_args_size;
+}
+
+/* Without this, gcc.dg/tree-prof/bb-reorg.c fails to assemble
+ when compiling with -O2 -freorder-blocks-and-partition -fprofile-use
+ -D_PROFILE_USE; delay branch scheduling then follows a REG_CROSSING_JUMP
+ to redirect two breqs. */
+
+static bool
+arc_can_follow_jump (const_rtx follower, const_rtx followee)
+{
+ /* ??? get_attr_type is declared to take an rtx. */
+ union { const_rtx c; rtx r; } u;
+
+ u.c = follower;
+ if (find_reg_note (followee, REG_CROSSING_JUMP, NULL_RTX))
+ switch (get_attr_type (u.r))
+ {
+ case TYPE_BRCC:
+ case TYPE_BRCC_NO_DELAY_SLOT:
+ return false;
+ default:
+ return true;
+ }
+ return true;
+}
+
+/* Implement EPILOGUE__USES.
+ Return true if REGNO should be added to the deemed uses of the epilogue.
+
+ We use the return address
+ arc_return_address_regs[arc_compute_function_type (cfun)] .
+ But also, we have to make sure all the register restore instructions
+ are known to be live in interrupt functions. */
+
+bool
+arc_epilogue_uses (int regno)
+{
+ if (reload_completed)
+ {
+ if (ARC_INTERRUPT_P (cfun->machine->fn_type))
+ {
+ if (!fixed_regs[regno])
+ return true;
+ return regno == arc_return_address_regs[cfun->machine->fn_type];
+ }
+ else
+ return regno == RETURN_ADDR_REGNUM;
+ }
+ else
+ return regno == arc_return_address_regs[arc_compute_function_type (cfun)];
+}
+
+#ifndef TARGET_NO_LRA
+#define TARGET_NO_LRA !TARGET_LRA
+#endif
+
+static bool
+arc_lra_p (void)
+{
+ return !TARGET_NO_LRA;
+}
+
+/* ??? Should we define TARGET_REGISTER_PRIORITY? We might perfer to use
+ Rcq registers, because some insn are shorter with them. OTOH we already
+ have separate alternatives for this purpose, and other insns don't
+ mind, so maybe we should rather prefer the other registers?
+ We need more data, and we can only get that if we allow people to
+ try all options. */
+static int
+arc_register_priority (int r)
+{
+ switch (arc_lra_priority_tag)
+ {
+ case ARC_LRA_PRIORITY_NONE:
+ return 0;
+ case ARC_LRA_PRIORITY_NONCOMPACT:
+ return ((((r & 7) ^ 4) - 4) & 15) != r;
+ case ARC_LRA_PRIORITY_COMPACT:
+ return ((((r & 7) ^ 4) - 4) & 15) == r;
+ default:
+ gcc_unreachable ();
+ }
+}
+
+static reg_class_t
+arc_spill_class (reg_class_t /* orig_class */, enum machine_mode)
+{
+ return GENERAL_REGS;
+}
+
+bool
+arc_legitimize_reload_address (rtx *p, enum machine_mode mode, int opnum,
+ int itype)
+{
+ rtx x = *p;
+ enum reload_type type = (enum reload_type) itype;
+
+ if (GET_CODE (x) == PLUS
+ && CONST_INT_P (XEXP (x, 1))
+ && (RTX_OK_FOR_BASE_P (XEXP (x, 0), true)
+ || (REG_P (XEXP (x, 0))
+ && reg_equiv_constant (REGNO (XEXP (x, 0))))))
+ {
+ int scale = GET_MODE_SIZE (mode);
+ int shift;
+ rtx index_rtx = XEXP (x, 1);
+ HOST_WIDE_INT offset = INTVAL (index_rtx), offset_base;
+ rtx reg, sum, sum2;
+
+ if (scale > 4)
+ scale = 4;
+ if ((scale-1) & offset)
+ scale = 1;
+ shift = scale >> 1;
+ offset_base = (offset + (256 << shift)) & (-512 << shift);
+ /* Sometimes the normal form does not suit DImode. We
+ could avoid that by using smaller ranges, but that
+ would give less optimized code when SImode is
+ prevalent. */
+ if (GET_MODE_SIZE (mode) + offset - offset_base <= (256 << shift))
+ {
+ int regno;
+
+ reg = XEXP (x, 0);
+ regno = REGNO (reg);
+ sum2 = sum = plus_constant (Pmode, reg, offset_base);
+
+ if (reg_equiv_constant (regno))
+ {
+ sum2 = plus_constant (Pmode, reg_equiv_constant (regno),
+ offset_base);
+ if (GET_CODE (sum2) == PLUS)
+ sum2 = gen_rtx_CONST (Pmode, sum2);
+ }
+ *p = gen_rtx_PLUS (Pmode, sum, GEN_INT (offset - offset_base));
+ push_reload (sum2, NULL_RTX, &XEXP (*p, 0), NULL,
+ BASE_REG_CLASS, Pmode, VOIDmode, 0, 0, opnum,
+ type);
+ return true;
+ }
+ }
+ /* We must re-recognize what we created before. */
+ else if (GET_CODE (x) == PLUS
+ && GET_CODE (XEXP (x, 0)) == PLUS
+ && CONST_INT_P (XEXP (XEXP (x, 0), 1))
+ && REG_P (XEXP (XEXP (x, 0), 0))
+ && CONST_INT_P (XEXP (x, 1)))
+ {
+ /* Because this address is so complex, we know it must have
+ been created by LEGITIMIZE_RELOAD_ADDRESS before; thus,
+ it is already unshared, and needs no further unsharing. */
+ push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
+ BASE_REG_CLASS, Pmode, VOIDmode, 0, 0, opnum, type);
+ return true;
+ }
+ return false;
+}
+
+struct gcc_target targetm = TARGET_INITIALIZER;
+
+#include "gt-arc.h"
diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
new file mode 100644
index 00000000000..cc49c553c55
--- /dev/null
+++ b/gcc/config/arc/arc.h
@@ -0,0 +1,1700 @@
+/* Definitions of target machine for GNU compiler, Synopsys DesignWare ARC cpu.
+ Copyright (C) 1994, 1995, 1997, 1998, 2007-2013
+ Free Software Foundation, Inc.
+
+ Sources derived from work done by Sankhya Technologies (www.sankhya.com) on
+ behalf of Synopsys Inc.
+
+ Position Independent Code support added,Code cleaned up,
+ Comments and Support For ARC700 instructions added by
+ Saurabh Verma (saurabh.verma@codito.com)
+ Ramana Radhakrishnan(ramana.radhakrishnan@codito.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_ARC_H
+#define GCC_ARC_H
+
+/* Things to do:
+
+ - incscc, decscc?
+
+*/
+
+#define SYMBOL_FLAG_SHORT_CALL (SYMBOL_FLAG_MACH_DEP << 0)
+#define SYMBOL_FLAG_MEDIUM_CALL (SYMBOL_FLAG_MACH_DEP << 1)
+#define SYMBOL_FLAG_LONG_CALL (SYMBOL_FLAG_MACH_DEP << 2)
+
+/* Check if this symbol has a long_call attribute in its declaration */
+#define SYMBOL_REF_LONG_CALL_P(X) \
+ ((SYMBOL_REF_FLAGS (X) & SYMBOL_FLAG_LONG_CALL) != 0)
+
+/* Check if this symbol has a medium_call attribute in its declaration */
+#define SYMBOL_REF_MEDIUM_CALL_P(X) \
+ ((SYMBOL_REF_FLAGS (X) & SYMBOL_FLAG_MEDIUM_CALL) != 0)
+
+/* Check if this symbol has a short_call attribute in its declaration */
+#define SYMBOL_REF_SHORT_CALL_P(X) \
+ ((SYMBOL_REF_FLAGS (X) & SYMBOL_FLAG_SHORT_CALL) != 0)
+
+#undef ASM_SPEC
+#undef LINK_SPEC
+#undef STARTFILE_SPEC
+#undef ENDFILE_SPEC
+#undef SIZE_TYPE
+#undef PTRDIFF_TYPE
+#undef WCHAR_TYPE
+#undef WCHAR_TYPE_SIZE
+#undef ASM_APP_ON
+#undef ASM_APP_OFF
+#undef CC1_SPEC
+
+/* Names to predefine in the preprocessor for this target machine. */
+#define TARGET_CPU_CPP_BUILTINS() \
+ do { \
+ builtin_define ("__arc__"); \
+ if (TARGET_A5) \
+ builtin_define ("__A5__"); \
+ else if (TARGET_ARC600) \
+ { \
+ builtin_define ("__A6__"); \
+ builtin_define ("__ARC600__"); \
+ } \
+ else if (TARGET_ARC601) \
+ { \
+ builtin_define ("__ARC601__"); \
+ } \
+ else if (TARGET_ARC700) \
+ { \
+ builtin_define ("__A7__"); \
+ builtin_define ("__ARC700__"); \
+ } \
+ if (TARGET_NORM) \
+ { \
+ builtin_define ("__ARC_NORM__");\
+ builtin_define ("__Xnorm"); \
+ } \
+ if (TARGET_MUL64_SET) \
+ builtin_define ("__ARC_MUL64__");\
+ if (TARGET_MULMAC_32BY16_SET) \
+ builtin_define ("__ARC_MUL32BY16__");\
+ if (TARGET_SIMD_SET) \
+ builtin_define ("__ARC_SIMD__"); \
+ if (TARGET_BARREL_SHIFTER) \
+ builtin_define ("__Xbarrel_shifter");\
+ builtin_assert ("cpu=arc"); \
+ builtin_assert ("machine=arc"); \
+ builtin_define (TARGET_BIG_ENDIAN \
+ ? "__BIG_ENDIAN__" : "__LITTLE_ENDIAN__"); \
+ if (TARGET_BIG_ENDIAN) \
+ builtin_define ("__big_endian__"); \
+} while(0)
+
+#if DEFAULT_LIBC == LIBC_UCLIBC
+
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ GNU_USER_TARGET_OS_CPP_BUILTINS (); \
+ } \
+ while (0)
+#endif
+
+/* Match the macros used in the assembler. */
+#define CPP_SPEC "\
+%{msimd:-D__Xsimd} %{mno-mpy:-D__Xno_mpy} %{mswap:-D__Xswap} \
+%{mmin-max:-D__Xmin_max} %{mEA:-D__Xea} \
+%{mspfp*:-D__Xspfp} %{mdpfp*:-D__Xdpfp} \
+%{mmac-d16:-D__Xxmac_d16} %{mmac-24:-D__Xxmac_24} \
+%{mdsp-packa:-D__Xdsp_packa} %{mcrc:-D__Xcrc} %{mdvbf:-D__Xdvbf} \
+%{mtelephony:-D__Xtelephony} %{mxy:-D__Xxy} %{mmul64: -D__Xmult32} \
+%{mlock:-D__Xlock} %{mswape:-D__Xswape} %{mrtsc:-D__Xrtsc} \
+"
+
+#define CC1_SPEC "\
+%{EB:%{EL:%emay not use both -EB and -EL}} \
+%{EB:-mbig-endian} %{EL:-mlittle-endian} \
+"
+
+#define ASM_DEFAULT "-mARC700 -mEA"
+
+#define ASM_SPEC "\
+%{mbig-endian|EB:-EB} %{EL} \
+%{mcpu=A5|mcpu=a5|mA5:-mA5} \
+%{mcpu=ARC600:-mARC600} \
+%{mcpu=ARC601:-mARC601} \
+%{mcpu=ARC700:-mARC700} \
+%{mcpu=ARC700:-mEA} \
+%{!mcpu=*:" ASM_DEFAULT "} \
+%{mbarrel-shifter} %{mno-mpy} %{mmul64} %{mmul32x16:-mdsp-packa} %{mnorm} \
+%{mswap} %{mEA} %{mmin-max} %{mspfp*} %{mdpfp*} \
+%{msimd} \
+%{mmac-d16} %{mmac-24} %{mdsp-packa} %{mcrc} %{mdvbf} %{mtelephony} %{mxy} \
+%{mcpu=ARC700|!mcpu=*:%{mlock}} \
+%{mcpu=ARC700|!mcpu=*:%{mswape}} \
+%{mcpu=ARC700|!mcpu=*:%{mrtsc}} \
+"
+
+#if DEFAULT_LIBC == LIBC_UCLIBC
+/* Note that the default is to link against dynamic libraries, if they are
+ available. Override with -static. */
+#define LINK_SPEC "%{h*} \
+ %{static:-Bstatic} \
+ %{symbolic:-Bsymbolic} \
+ %{rdynamic:-export-dynamic}\
+ -dynamic-linker /lib/ld-uClibc.so.0 \
+ -X %{mbig-endian:-EB} \
+ %{EB} %{EL} \
+ %{marclinux*} \
+ %{!marclinux*: %{pg|p|profile:-marclinux_prof;: -marclinux}} \
+ %{!z:-z max-page-size=0x2000 -z common-page-size=0x2000} \
+ %{shared:-shared}"
+/* Like the standard LINK_COMMAND_SPEC, but add %G when building
+ a shared library with -nostdlib, so that the hidden functions of libgcc
+ will be incorporated.
+ N.B., we don't want a plain -lgcc, as this would lead to re-exporting
+ non-hidden functions, so we have to consider libgcc_s.so.* first, which in
+ turn should be wrapped with --as-needed. */
+#define LINK_COMMAND_SPEC "\
+%{!fsyntax-only:%{!c:%{!M:%{!MM:%{!E:%{!S:\
+ %(linker) %l " LINK_PIE_SPEC "%X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} %{r}\
+ %{s} %{t} %{u*} %{x} %{z} %{Z} %{!A:%{!nostdlib:%{!nostartfiles:%S}}}\
+ %{static:} %{L*} %(mfwrap) %(link_libgcc) %o\
+ %{fopenmp|ftree-parallelize-loops=*:%:include(libgomp.spec)%(link_gomp)}\
+ %(mflib)\
+ %{fprofile-arcs|fprofile-generate|coverage:-lgcov}\
+ %{!nostdlib:%{!nodefaultlibs:%(link_ssp) %(link_gcc_c_sequence)}}\
+ %{!A:%{!nostdlib:%{!nostartfiles:%E}}} %{T*} }}}}}}"
+
+#else
+#define LINK_SPEC "%{mbig-endian:-EB} %{EB} %{EL}\
+ %{pg|p:-marcelf_prof;mA7|mARC700|mcpu=arc700|mcpu=ARC700: -marcelf}"
+#endif
+
+#if DEFAULT_LIBC != LIBC_UCLIBC
+#define STARTFILE_SPEC "%{!shared:crt0.o%s} crti%O%s %{pg|p:crtg.o%s} crtbegin.o%s"
+#else
+#define STARTFILE_SPEC "%{!shared:%{!mkernel:crt1.o%s}} crti.o%s \
+ %{!shared:%{pg|p|profile:crtg.o%s} crtbegin.o%s} %{shared:crtbeginS.o%s}"
+
+#endif
+
+#if DEFAULT_LIBC != LIBC_UCLIBC
+#define ENDFILE_SPEC "%{pg|p:crtgend.o%s} crtend.o%s crtn%O%s"
+#else
+#define ENDFILE_SPEC "%{!shared:%{pg|p|profile:crtgend.o%s} crtend.o%s} \
+ %{shared:crtendS.o%s} crtn.o%s"
+
+#endif
+
+#if DEFAULT_LIBC == LIBC_UCLIBC
+#undef LIB_SPEC
+#define LIB_SPEC \
+ "%{pthread:-lpthread} \
+ %{shared:-lc} \
+ %{!shared:%{pg|p|profile:-lgmon -u profil --defsym __profil=profil} -lc}"
+#define TARGET_ASM_FILE_END file_end_indicate_exec_stack
+#else
+#undef LIB_SPEC
+/* -lc_p not present for arc-elf32-* : ashwin */
+#define LIB_SPEC "%{!shared:%{g*:-lg} %{pg|p:-lgmon} -lc}"
+#endif
+
+#ifndef DRIVER_ENDIAN_SELF_SPECS
+#define DRIVER_ENDIAN_SELF_SPECS ""
+#endif
+#ifndef TARGET_SDATA_DEFAULT
+#define TARGET_SDATA_DEFAULT 1
+#endif
+#ifndef TARGET_MMEDIUM_CALLS_DEFAULT
+#define TARGET_MMEDIUM_CALLS_DEFAULT 0
+#endif
+
+#define DRIVER_SELF_SPECS DRIVER_ENDIAN_SELF_SPECS \
+ "%{mARC5|mA5: -mcpu=A5 %<mARC5 %<mA5}" \
+ "%{mARC600|mA6: -mcpu=ARC600 %<mARC600 %<mA6}" \
+ "%{mARC601: -mcpu=ARC601 %<mARC601}" \
+ "%{mARC700|mA7: -mcpu=ARC700 %<mARC700 %<mA7}" \
+ "%{mbarrel_shifte*: -mbarrel-shifte%* %<mbarrel_shifte*}" \
+ "%{mEA: -mea %<mEA}" \
+ "%{mspfp_*: -mspfp-%* %<mspfp_*}" \
+ "%{mdpfp_*: -mdpfp-%* %<mdpfp_*}" \
+ "%{mdsp_pack*: -mdsp-pack%* %<mdsp_pack*}" \
+ "%{mmac_*: -mmac-%* %<mmac_*}" \
+ "%{multcost=*: -mmultcost=%* %<multcost=*}"
+
+/* Run-time compilation parameters selecting different hardware subsets. */
+
+#define TARGET_MIXED_CODE (TARGET_MIXED_CODE_SET)
+
+#define TARGET_SPFP (TARGET_SPFP_FAST_SET || TARGET_SPFP_COMPACT_SET)
+#define TARGET_DPFP (TARGET_DPFP_FAST_SET || TARGET_DPFP_COMPACT_SET)
+
+#define SUBTARGET_SWITCHES
+
+/* Instruction set characteristics.
+ These are internal macros, set by the appropriate -m option. */
+
+/* Non-zero means the cpu supports norm instruction. This flag is set by
+ default for A7, and only for pre A7 cores when -mnorm is given. */
+#define TARGET_NORM (TARGET_ARC700 || TARGET_NORM_SET)
+/* Indicate if an optimized floating point emulation library is available. */
+#define TARGET_OPTFPE \
+ (TARGET_ARC700 \
+ /* We need a barrel shifter and NORM. */ \
+ || (TARGET_ARC600 && TARGET_NORM_SET))
+
+/* Non-zero means the cpu supports swap instruction. This flag is set by
+ default for A7, and only for pre A7 cores when -mswap is given. */
+#define TARGET_SWAP (TARGET_ARC700 || TARGET_SWAP_SET)
+
+/* Provide some macros for size / scheduling features of the ARC700, so
+ that we can pick & choose features if we get a new cpu family member. */
+
+/* Should we try to unalign likely taken branches without a delay slot. */
+#define TARGET_UNALIGN_BRANCH (TARGET_ARC700 && !optimize_size)
+
+/* Should we upsize short delayed branches with a short delay insn? */
+#define TARGET_UPSIZE_DBR (TARGET_ARC700 && !optimize_size)
+
+/* Should we add padding before a return insn to avoid mispredict? */
+#define TARGET_PAD_RETURN (TARGET_ARC700 && !optimize_size)
+
+/* For an anulled-true delay slot insn for a delayed branch, should we only
+ use conditional execution? */
+#define TARGET_AT_DBR_CONDEXEC (!TARGET_ARC700)
+
+#define TARGET_A5 (arc_cpu == PROCESSOR_A5)
+#define TARGET_ARC600 (arc_cpu == PROCESSOR_ARC600)
+#define TARGET_ARC601 (arc_cpu == PROCESSOR_ARC601)
+#define TARGET_ARC700 (arc_cpu == PROCESSOR_ARC700)
+
+/* Recast the cpu class to be the cpu attribute. */
+#define arc_cpu_attr ((enum attr_cpu)arc_cpu)
+
+#ifndef MULTILIB_DEFAULTS
+#define MULTILIB_DEFAULTS { "mARC700" }
+#endif
+
+/* Target machine storage layout. */
+
+/* We want zero_extract to mean the same
+ no matter what the byte endianness is. */
+#define BITS_BIG_ENDIAN 0
+
+/* Define this if most significant byte of a word is the lowest numbered. */
+#define BYTES_BIG_ENDIAN (TARGET_BIG_ENDIAN)
+
+/* Define this if most significant word of a multiword number is the lowest
+ numbered. */
+#define WORDS_BIG_ENDIAN (TARGET_BIG_ENDIAN)
+
+/* Number of bits in an addressable storage unit. */
+#define BITS_PER_UNIT 8
+
+/* Width in bits of a "word", which is the contents of a machine register.
+ Note that this is not necessarily the width of data type `int';
+ if using 16-bit ints on a 68000, this would still be 32.
+ But on a machine with 16-bit registers, this would be 16. */
+#define BITS_PER_WORD 32
+
+/* Width of a word, in units (bytes). */
+#define UNITS_PER_WORD 4
+
+/* Define this macro if it is advisable to hold scalars in registers
+ in a wider mode than that declared by the program. In such cases,
+ the value is constrained to be within the bounds of the declared
+ type, but kept valid in the wider mode. The signedness of the
+ extension may differ from that of the type. */
+#define PROMOTE_MODE(MODE,UNSIGNEDP,TYPE) \
+if (GET_MODE_CLASS (MODE) == MODE_INT \
+ && GET_MODE_SIZE (MODE) < UNITS_PER_WORD) \
+{ \
+ (MODE) = SImode; \
+}
+
+/* Width in bits of a pointer.
+ See also the macro `Pmode' defined below. */
+#define POINTER_SIZE 32
+
+/* Allocation boundary (in *bits*) for storing arguments in argument list. */
+#define PARM_BOUNDARY 32
+
+/* Boundary (in *bits*) on which stack pointer should be aligned. */
+/* TOCHECK: Changed from 64 to 32 */
+#define STACK_BOUNDARY 32
+
+/* ALIGN FRAMES on word boundaries. */
+#define ARC_STACK_ALIGN(LOC) \
+ (((LOC) + STACK_BOUNDARY / BITS_PER_UNIT - 1) & -STACK_BOUNDARY/BITS_PER_UNIT)
+
+/* Allocation boundary (in *bits*) for the code of a function. */
+#define FUNCTION_BOUNDARY 32
+
+/* Alignment of field after `int : 0' in a structure. */
+#define EMPTY_FIELD_BOUNDARY 32
+
+/* Every structure's size must be a multiple of this. */
+#define STRUCTURE_SIZE_BOUNDARY 8
+
+/* A bitfield declared as `int' forces `int' alignment for the struct. */
+#define PCC_BITFIELD_TYPE_MATTERS 1
+
+/* An expression for the alignment of a structure field FIELD if the
+ alignment computed in the usual way (including applying of
+ `BIGGEST_ALIGNMENT' and `BIGGEST_FIELD_ALIGNMENT' to the
+ alignment) is COMPUTED. It overrides alignment only if the field
+ alignment has not been set by the `__attribute__ ((aligned (N)))'
+ construct.
+*/
+
+#define ADJUST_FIELD_ALIGN(FIELD, COMPUTED) \
+(TYPE_MODE (strip_array_types (TREE_TYPE (FIELD))) == DFmode \
+ ? MIN ((COMPUTED), 32) : (COMPUTED))
+
+
+
+/* No data type wants to be aligned rounder than this. */
+/* This is bigger than currently necessary for the ARC. If 8 byte floats are
+ ever added it's not clear whether they'll need such alignment or not. For
+ now we assume they will. We can always relax it if necessary but the
+ reverse isn't true. */
+/* TOCHECK: Changed from 64 to 32 */
+#define BIGGEST_ALIGNMENT 32
+
+/* The best alignment to use in cases where we have a choice. */
+#define FASTEST_ALIGNMENT 32
+
+/* Make strings word-aligned so strcpy from constants will be faster. */
+#define CONSTANT_ALIGNMENT(EXP, ALIGN) \
+ ((TREE_CODE (EXP) == STRING_CST \
+ && (ALIGN) < FASTEST_ALIGNMENT) \
+ ? FASTEST_ALIGNMENT : (ALIGN))
+
+
+/* Make arrays of chars word-aligned for the same reasons. */
+#define LOCAL_ALIGNMENT(TYPE, ALIGN) \
+ (TREE_CODE (TYPE) == ARRAY_TYPE \
+ && TYPE_MODE (TREE_TYPE (TYPE)) == QImode \
+ && (ALIGN) < FASTEST_ALIGNMENT ? FASTEST_ALIGNMENT : (ALIGN))
+
+#define DATA_ALIGNMENT(TYPE, ALIGN) \
+ (TREE_CODE (TYPE) == ARRAY_TYPE \
+ && TYPE_MODE (TREE_TYPE (TYPE)) == QImode \
+ && arc_size_opt_level < 3 \
+ && (ALIGN) < FASTEST_ALIGNMENT ? FASTEST_ALIGNMENT : (ALIGN))
+
+/* Set this nonzero if move instructions will actually fail to work
+ when given unaligned data. */
+/* On the ARC the lower address bits are masked to 0 as necessary. The chip
+ won't croak when given an unaligned address, but the insn will still fail
+ to produce the correct result. */
+#define STRICT_ALIGNMENT 1
+
+/* Layout of source language data types. */
+
+#define SHORT_TYPE_SIZE 16
+#define INT_TYPE_SIZE 32
+#define LONG_TYPE_SIZE 32
+#define LONG_LONG_TYPE_SIZE 64
+#define FLOAT_TYPE_SIZE 32
+#define DOUBLE_TYPE_SIZE 64
+#define LONG_DOUBLE_TYPE_SIZE 64
+
+/* Define this as 1 if `char' should by default be signed; else as 0. */
+#define DEFAULT_SIGNED_CHAR 0
+
+#define SIZE_TYPE "long unsigned int"
+#define PTRDIFF_TYPE "long int"
+#define WCHAR_TYPE "int"
+#define WCHAR_TYPE_SIZE 32
+
+
+/* ashwin : shifted from arc.c:102 */
+#define PROGRAM_COUNTER_REGNO 63
+
+/* Standard register usage. */
+
+/* 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.
+
+ Registers 61, 62, and 63 are not really registers and we needn't treat
+ them as such. We still need a register for the condition code and
+ argument pointer. */
+
+/* r63 is pc, r64-r127 = simd vregs, r128-r143 = simd dma config regs
+ r144, r145 = lp_start, lp_end
+ and therefore the pseudo registers start from r146. */
+#define FIRST_PSEUDO_REGISTER 146
+
+/* 1 for registers that have pervasive standard uses
+ and are not available for the register allocator.
+
+ 0-28 - general purpose registers
+ 29 - ilink1 (interrupt link register)
+ 30 - ilink2 (interrupt link register)
+ 31 - blink (branch link register)
+ 32-59 - reserved for extensions
+ 60 - LP_COUNT
+ 61 - condition code
+ 62 - argument pointer
+ 63 - program counter
+
+ FWIW, this is how the 61-63 encodings are used by the hardware:
+ 61 - reserved
+ 62 - long immediate data indicator
+ 63 - PCL (program counter aligned to 32 bit, read-only)
+
+ The general purpose registers are further broken down into:
+
+ 0-7 - arguments/results
+ 8-12 - call used (r11 - static chain pointer)
+ 13-25 - call saved
+ 26 - global pointer
+ 27 - frame pointer
+ 28 - stack pointer
+ 29 - ilink1
+ 30 - ilink2
+ 31 - return address register
+
+ By default, the extension registers are not available. */
+/* Present implementations only have VR0-VR23 only. */
+/* ??? FIXME: r27 and r31 should not be fixed registers. */
+#define FIXED_REGISTERS \
+{ 0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 1, 1, 1, 1, 1, 1, \
+ \
+ 1, 1, 1, 1, 1, 1, 1, 1, \
+ 0, 0, 0, 0, 1, 1, 1, 1, \
+ 1, 1, 1, 1, 1, 1, 1, 1, \
+ 1, 1, 1, 1, 0, 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, \
+ 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, \
+ \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ 1, 1}
+
+/* 1 for registers not available across function calls.
+ These must include the FIXED_REGISTERS and also any
+ registers that can be used without being saved.
+ The latter must include the registers where values are returned
+ and the register where structure-value addresses are passed.
+ Aside from that, you can include as many other registers as you like. */
+#define CALL_USED_REGISTERS \
+{ \
+ 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, 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, \
+ \
+ 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, \
+ \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ 1, 1}
+
+/* If defined, an initializer for a vector of integers, containing the
+ numbers of hard registers in the order in which GCC should
+ prefer to use them (from most preferred to least). */
+#define REG_ALLOC_ORDER \
+{ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, \
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, \
+ 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, \
+ 27, 28, 29, 30, 31, 63}
+
+/* Return number of consecutive hard regs needed starting at reg REGNO
+ to hold something of mode MODE.
+ This is ordinarily the length in words of a value of mode MODE
+ but can be less for certain modes in special long registers. */
+#define HARD_REGNO_NREGS(REGNO, MODE) \
+((GET_MODE_SIZE (MODE) == 16 \
+ && REGNO >= ARC_FIRST_SIMD_VR_REG && REGNO <= ARC_LAST_SIMD_VR_REG) ? 1 \
+ : (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
+
+/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. */
+extern unsigned int arc_hard_regno_mode_ok[];
+extern unsigned int arc_mode_class[];
+#define HARD_REGNO_MODE_OK(REGNO, MODE) \
+((arc_hard_regno_mode_ok[REGNO] & arc_mode_class[MODE]) != 0)
+
+/* A C expression that is nonzero if it is desirable to choose
+ register allocation so as to avoid move instructions between a
+ value of mode MODE1 and a value of mode MODE2.
+
+ If `HARD_REGNO_MODE_OK (R, MODE1)' and `HARD_REGNO_MODE_OK (R,
+ MODE2)' are ever different for any R, then `MODES_TIEABLE_P (MODE1,
+ MODE2)' must be zero. */
+
+/* Tie QI/HI/SI modes together. */
+#define MODES_TIEABLE_P(MODE1, MODE2) \
+(GET_MODE_CLASS (MODE1) == MODE_INT \
+ && GET_MODE_CLASS (MODE2) == MODE_INT \
+ && GET_MODE_SIZE (MODE1) <= UNITS_PER_WORD \
+ && GET_MODE_SIZE (MODE2) <= UNITS_PER_WORD)
+
+/* Internal macros to classify a register number as to whether it's a
+ general purpose register for compact insns (r0-r3,r12-r15), or
+ stack pointer (r28). */
+
+#define COMPACT_GP_REG_P(REGNO) \
+ (((signed)(REGNO) >= 0 && (REGNO) <= 3) || ((REGNO) >= 12 && (REGNO) <= 15))
+#define SP_REG_P(REGNO) ((REGNO) == 28)
+
+
+
+/* Register classes and constants. */
+
+/* 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.
+
+ For any two classes, it is very desirable that there be another
+ class that represents their union.
+
+ It is important that any condition codes have class NO_REGS.
+ See `register_operand'. */
+
+enum reg_class
+{
+ NO_REGS,
+ R0_REGS, /* 'x' */
+ GP_REG, /* 'Rgp' */
+ FP_REG, /* 'f' */
+ SP_REGS, /* 'b' */
+ LPCOUNT_REG, /* 'l' */
+ LINK_REGS, /* 'k' */
+ DOUBLE_REGS, /* D0, D1 */
+ SIMD_VR_REGS, /* VR00-VR63 */
+ SIMD_DMA_CONFIG_REGS, /* DI0-DI7,DO0-DO7 */
+ ARCOMPACT16_REGS, /* 'q' */
+ AC16_BASE_REGS, /* 'e' */
+ SIBCALL_REGS, /* "Rsc" */
+ GENERAL_REGS, /* 'r' */
+ MPY_WRITABLE_CORE_REGS, /* 'W' */
+ WRITABLE_CORE_REGS, /* 'w' */
+ CHEAP_CORE_REGS, /* 'c' */
+ ALL_CORE_REGS, /* 'Rac' */
+ ALL_REGS,
+ LIM_REG_CLASSES
+};
+
+#define N_REG_CLASSES (int) LIM_REG_CLASSES
+
+/* Give names of register classes as strings for dump file. */
+#define REG_CLASS_NAMES \
+{ \
+ "NO_REGS", \
+ "R0_REGS", \
+ "GP_REG", \
+ "FP_REG", \
+ "SP_REGS", \
+ "LPCOUNT_REG", \
+ "LINK_REGS", \
+ "DOUBLE_REGS", \
+ "SIMD_VR_REGS", \
+ "SIMD_DMA_CONFIG_REGS", \
+ "ARCOMPACT16_REGS", \
+ "AC16_BASE_REGS", \
+ "SIBCALL_REGS", \
+ "GENERAL_REGS", \
+ "MPY_WRITABLE_CORE_REGS", \
+ "WRITABLE_CORE_REGS", \
+ "CHEAP_CORE_REGS", \
+ "ALL_CORE_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. */
+
+#define REG_CLASS_CONTENTS \
+{ \
+ {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* No Registers */ \
+ {0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'x', r0 register , r0 */ \
+ {0x04000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'Rgp', Global Pointer, r26 */ \
+ {0x08000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'f', Frame Pointer, r27 */ \
+ {0x10000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'b', Stack Pointer, r28 */ \
+ {0x00000000, 0x10000000, 0x00000000, 0x00000000, 0x00000000}, /* 'l', LPCOUNT Register, r60 */ \
+ {0xe0000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'k', LINK Registers, r29-r31 */ \
+ {0x00000000, 0x00000f00, 0x00000000, 0x00000000, 0x00000000}, /* 'D', D1, D2 Registers */ \
+ {0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000}, /* 'V', VR00-VR63 Registers */ \
+ {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000ffff}, /* 'V', DI0-7,DO0-7 Registers */ \
+ {0x0000f00f, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'q', r0-r3, r12-r15 */ \
+ {0x1000f00f, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'e', r0-r3, r12-r15, sp */ \
+ {0x1c001fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* "Rsc", r0-r12 */ \
+ {0x9fffffff, 0xc0000000, 0x00000000, 0x00000000, 0x00000000}, /* 'r', r0-r28, blink, ap and pcl */ \
+ {0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'W', r0-r31 */ \
+ /* Include ap / pcl in WRITABLE_CORE_REGS for sake of symmetry. As these \
+ registers are fixed, it does not affect the literal meaning of the \
+ constraints, but it makes it a superset of GENERAL_REGS, thus \
+ enabling some operations that would otherwise not be possible. */ \
+ {0xffffffff, 0xd0000000, 0x00000000, 0x00000000, 0x00000000}, /* 'w', r0-r31, r60 */ \
+ {0xffffffff, 0xdfffffff, 0x00000000, 0x00000000, 0x00000000}, /* 'c', r0-r60, ap, pcl */ \
+ {0xffffffff, 0xdfffffff, 0x00000000, 0x00000000, 0x00000000}, /* 'Rac', r0-r60, ap, pcl */ \
+ {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0003ffff} /* All Registers */ \
+}
+
+/* Local macros to mark the first and last regs of different classes. */
+#define ARC_FIRST_SIMD_VR_REG 64
+#define ARC_LAST_SIMD_VR_REG 127
+
+#define ARC_FIRST_SIMD_DMA_CONFIG_REG 128
+#define ARC_FIRST_SIMD_DMA_CONFIG_IN_REG 128
+#define ARC_FIRST_SIMD_DMA_CONFIG_OUT_REG 136
+#define ARC_LAST_SIMD_DMA_CONFIG_REG 143
+
+/* 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. */
+
+extern enum reg_class arc_regno_reg_class[];
+
+#define REGNO_REG_CLASS(REGNO) (arc_regno_reg_class[REGNO])
+
+/* The class value for valid index registers. An index register is
+ one used in an address where its value is either multiplied by
+ a scale factor or added to another register (as well as added to a
+ displacement). */
+
+#define INDEX_REG_CLASS (TARGET_MIXED_CODE ? ARCOMPACT16_REGS : GENERAL_REGS)
+
+/* The class value for valid base registers. A base register is one used in
+ an address which is the register value plus a displacement. */
+
+#define BASE_REG_CLASS (TARGET_MIXED_CODE ? AC16_BASE_REGS : GENERAL_REGS)
+
+/* 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 local-alloc.c. */
+#define REGNO_OK_FOR_BASE_P(REGNO) \
+((REGNO) < 29 || ((REGNO) == ARG_POINTER_REGNUM) || ((REGNO) == 63) ||\
+ (unsigned) reg_renumber[REGNO] < 29)
+
+#define REGNO_OK_FOR_INDEX_P(REGNO) REGNO_OK_FOR_BASE_P(REGNO)
+
+/* Given an rtx X being reloaded into a reg required to be
+ in class CLASS, return the class of reg to actually use.
+ In general this is just CLASS; but on some machines
+ in some cases it is preferable to use a more restrictive class. */
+
+#define PREFERRED_RELOAD_CLASS(X, CLASS) \
+ arc_preferred_reload_class((X), (CLASS))
+
+ extern enum reg_class arc_preferred_reload_class (rtx, enum reg_class);
+
+/* Return the maximum number of consecutive registers
+ needed to represent mode MODE in a register of class CLASS. */
+
+#define CLASS_MAX_NREGS(CLASS, MODE) \
+(( GET_MODE_SIZE (MODE) == 16 && CLASS == SIMD_VR_REGS) ? 1: \
+((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
+
+#define SMALL_INT(X) ((unsigned) ((X) + 0x100) < 0x200)
+#define SMALL_INT_RANGE(X, OFFSET, SHIFT) \
+ ((unsigned) (((X) >> (SHIFT)) + 0x100) \
+ < 0x200 - ((unsigned) (OFFSET) >> (SHIFT)))
+#define SIGNED_INT12(X) ((unsigned) ((X) + 0x800) < 0x1000)
+#define LARGE_INT(X) \
+(((X) < 0) \
+ ? (X) >= (-(HOST_WIDE_INT) 0x7fffffff - 1) \
+ : (unsigned HOST_WIDE_INT) (X) <= (unsigned HOST_WIDE_INT) 0xffffffff)
+#define UNSIGNED_INT3(X) ((unsigned) (X) < 0x8)
+#define UNSIGNED_INT5(X) ((unsigned) (X) < 0x20)
+#define UNSIGNED_INT6(X) ((unsigned) (X) < 0x40)
+#define UNSIGNED_INT7(X) ((unsigned) (X) < 0x80)
+#define UNSIGNED_INT8(X) ((unsigned) (X) < 0x100)
+#define IS_ONE(X) ((X) == 1)
+#define IS_ZERO(X) ((X) == 0)
+
+/* Stack layout and stack pointer usage. */
+
+/* Define this macro if pushing a word onto the stack moves the stack
+ pointer to a smaller address. */
+#define STACK_GROWS_DOWNWARD
+
+/* Define this 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
+
+/* Offset within stack frame to start allocating local variables at.
+ If FRAME_GROWS_DOWNWARD, this is the offset to the END of the
+ first local allocated. Otherwise, it is the offset to the BEGINNING
+ of the first local allocated. */
+#define STARTING_FRAME_OFFSET 0
+
+/* Offset from the stack pointer register to the first location at which
+ outgoing arguments are placed. */
+#define STACK_POINTER_OFFSET (0)
+
+/* Offset of first parameter from the argument pointer register value. */
+#define FIRST_PARM_OFFSET(FNDECL) (0)
+
+/* A C expression whose value is RTL representing the address in a
+ stack frame where the pointer to the caller's frame is stored.
+ Assume that FRAMEADDR is an RTL expression for the address of the
+ stack frame itself.
+
+ If you don't define this macro, the default is to return the value
+ of FRAMEADDR--that is, the stack frame address is also the address
+ of the stack word that points to the previous frame. */
+/* ??? unfinished */
+/*define DYNAMIC_CHAIN_ADDRESS (FRAMEADDR)*/
+
+/* A C expression whose value is RTL representing the value of the
+ return address for the frame COUNT steps up from the current frame.
+ FRAMEADDR is the frame pointer of the COUNT frame, or the frame
+ pointer of the COUNT - 1 frame if `RETURN_ADDR_IN_PREVIOUS_FRAME'
+ is defined. */
+/* The current return address is in r31. The return address of anything
+ farther back is at [%fp,4]. */
+
+#define RETURN_ADDR_RTX(COUNT, FRAME) \
+arc_return_addr_rtx(COUNT,FRAME)
+
+/* Register to use for pushing function arguments. */
+#define STACK_POINTER_REGNUM 28
+
+/* Base register for access to local variables of the function. */
+#define FRAME_POINTER_REGNUM 27
+
+/* Base register for access to arguments of the function. This register
+ will be eliminated into either fp or sp. */
+#define ARG_POINTER_REGNUM 62
+
+#define RETURN_ADDR_REGNUM 31
+
+/* TODO - check usage of STATIC_CHAIN_REGNUM with a testcase */
+/* Register in which static-chain is passed to a function. This must
+ not be a register used by the prologue. */
+#define STATIC_CHAIN_REGNUM 11
+
+/* Function argument passing. */
+
+/* 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. */
+#define ACCUMULATE_OUTGOING_ARGS 1
+
+/* 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. */
+#define CUMULATIVE_ARGS int
+
+/* 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,INDIRECT,N_NAMED_ARGS) \
+((CUM) = 0)
+
+/* The number of registers used for parameter passing. Local to this file. */
+#define MAX_ARC_PARM_REGS 8
+
+/* 1 if N is a possible register number for function argument passing. */
+#define FUNCTION_ARG_REGNO_P(N) \
+((unsigned) (N) < MAX_ARC_PARM_REGS)
+
+/* The ROUND_ADVANCE* macros are local to this file. */
+/* Round SIZE up to a word boundary. */
+#define ROUND_ADVANCE(SIZE) \
+(((SIZE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
+
+/* Round arg MODE/TYPE up to the next word boundary. */
+#define ROUND_ADVANCE_ARG(MODE, TYPE) \
+((MODE) == BLKmode \
+ ? ROUND_ADVANCE (int_size_in_bytes (TYPE)) \
+ : ROUND_ADVANCE (GET_MODE_SIZE (MODE)))
+
+#define ARC_FUNCTION_ARG_BOUNDARY(MODE,TYPE) PARM_BOUNDARY
+/* Round CUM up to the necessary point for argument MODE/TYPE. */
+/* N.B. Vectors have alignment exceeding BIGGEST_ALIGNMENT.
+ ARC_FUNCTION_ARG_BOUNDARY reduces this to no more than 32 bit. */
+#define ROUND_ADVANCE_CUM(CUM, MODE, TYPE) \
+ ((((CUM) - 1) | (ARC_FUNCTION_ARG_BOUNDARY ((MODE), (TYPE)) - 1)/BITS_PER_WORD)\
+ + 1)
+
+/* Return boolean indicating arg of type TYPE and mode MODE will be passed in
+ a reg. This includes arguments that have to be passed by reference as the
+ pointer to them is passed in a reg if one is available (and that is what
+ we're given).
+ When passing arguments NAMED is always 1. When receiving arguments NAMED
+ is 1 for each argument except the last in a stdarg/varargs function. In
+ a stdarg function we want to treat the last named arg as named. In a
+ varargs function we want to treat the last named arg (which is
+ `__builtin_va_alist') as unnamed.
+ This macro is only used in this file. */
+#define PASS_IN_REG_P(CUM, MODE, TYPE) \
+((CUM) < MAX_ARC_PARM_REGS)
+
+
+/* Function results. */
+
+/* Define how to find the value returned by a library function
+ assuming the value has mode MODE. */
+#define LIBCALL_VALUE(MODE) gen_rtx_REG (MODE, 0)
+
+/* 1 if N is a possible register number for a function value
+ as seen by the caller. */
+/* ??? What about r1 in DI/DF values. */
+#define FUNCTION_VALUE_REGNO_P(N) ((N) == 0)
+
+/* Tell GCC to use RETURN_IN_MEMORY. */
+#define DEFAULT_PCC_STRUCT_RETURN 0
+
+/* Register in which address to store a structure value
+ is passed to a function, or 0 to use `invisible' first argument. */
+#define STRUCT_VALUE 0
+
+/* 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. */
+#define EXIT_IGNORE_STACK 0
+
+#define EPILOGUE_USES(REGNO) arc_epilogue_uses ((REGNO))
+
+/* 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.
+
+ We have two registers that can be eliminated on the ARC. First, the
+ argument pointer register can always be eliminated in favor of the stack
+ pointer register or frame pointer register. Secondly, the frame pointer
+ register can often be eliminated in favor of the stack pointer register.
+*/
+
+#define ELIMINABLE_REGS \
+{{ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
+ {ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \
+ {FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}}
+
+/* Define the offset between two registers, one to be eliminated, and the other
+ its replacement, at the start of a routine. */
+extern int arc_initial_elimination_offset(int from, int to);
+#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
+ (OFFSET) = arc_initial_elimination_offset ((FROM), (TO))
+
+/* Output assembler code to FILE to increment profiler label # LABELNO
+ for profiling a function entry.
+ We actually emit the profiler code at the call site, so leave this one
+ empty. */
+#define FUNCTION_PROFILER(FILE, LABELNO) \
+ if (TARGET_UCB_MCOUNT) \
+ fprintf (FILE, "\t%s\n", arc_output_libcall ("__mcount"))
+
+#define NO_PROFILE_COUNTERS 1
+
+/* Trampolines. */
+
+/* Length in units of the trampoline for entering a nested function. */
+#define TRAMPOLINE_SIZE 20
+
+/* Alignment required for a trampoline in bits . */
+/* For actual data alignment we just need 32, no more than the stack;
+ however, to reduce cache coherency issues, we want to make sure that
+ trampoline instructions always appear the same in any given cache line. */
+#define TRAMPOLINE_ALIGNMENT 256
+
+/* Library calls. */
+
+/* Addressing modes, and classification of registers for them. */
+
+/* Maximum number of registers that can appear in a valid memory address. */
+/* The `ld' insn allows 2, but the `st' insn only allows 1. */
+#define MAX_REGS_PER_ADDRESS 1
+
+/* We have pre inc/dec (load/store with update). */
+#define HAVE_PRE_INCREMENT 1
+#define HAVE_PRE_DECREMENT 1
+#define HAVE_POST_INCREMENT 1
+#define HAVE_POST_DECREMENT 1
+#define HAVE_PRE_MODIFY_DISP 1
+#define HAVE_POST_MODIFY_DISP 1
+#define HAVE_PRE_MODIFY_REG 1
+#define HAVE_POST_MODIFY_REG 1
+/* ??? should also do PRE_MODIFY_REG / POST_MODIFY_REG, but that requires
+ a special predicate for the memory operand of stores, like for the SH. */
+
+/* Recognize any constant value that is a valid address. */
+#define CONSTANT_ADDRESS_P(X) \
+(flag_pic?arc_legitimate_pic_addr_p (X): \
+(GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF \
+ || GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST))
+
+/* Is the argument a const_int rtx, containing an exact power of 2 */
+#define IS_POWEROF2_P(X) (! ( (X) & ((X) - 1)) && (X))
+
+/* 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 *_NONSTRICT definition accepts all pseudo regs; the other rejects
+ them unless they have been allocated suitable hard regs.
+
+ 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. */
+
+/* Nonzero if X is a hard reg that can be used as an index
+ or if it is a pseudo reg. */
+#define REG_OK_FOR_INDEX_P_NONSTRICT(X) \
+((unsigned) REGNO (X) >= FIRST_PSEUDO_REGISTER || \
+ (unsigned) REGNO (X) < 29 || \
+ (unsigned) REGNO (X) == 63 || \
+ (unsigned) REGNO (X) == ARG_POINTER_REGNUM)
+/* Nonzero if X is a hard reg that can be used as a base reg
+ or if it is a pseudo reg. */
+#define REG_OK_FOR_BASE_P_NONSTRICT(X) \
+((unsigned) REGNO (X) >= FIRST_PSEUDO_REGISTER || \
+ (unsigned) REGNO (X) < 29 || \
+ (unsigned) REGNO (X) == 63 || \
+ (unsigned) REGNO (X) == ARG_POINTER_REGNUM)
+
+/* Nonzero if X is a hard reg that can be used as an index. */
+#define REG_OK_FOR_INDEX_P_STRICT(X) REGNO_OK_FOR_INDEX_P (REGNO (X))
+/* Nonzero if X is a hard reg that can be used as a base reg. */
+#define REG_OK_FOR_BASE_P_STRICT(X) REGNO_OK_FOR_BASE_P (REGNO (X))
+
+/* GO_IF_LEGITIMATE_ADDRESS 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 `ld' insn allows [reg],[reg+shimm],[reg+limm],[reg+reg],[limm]
+ but the `st' insn only allows [reg],[reg+shimm],[limm].
+ The only thing we can do is only allow the most strict case `st' and hope
+ other parts optimize out the restrictions for `ld'. */
+
+#define RTX_OK_FOR_BASE_P(X, STRICT) \
+(REG_P (X) \
+ && ((STRICT) ? REG_OK_FOR_BASE_P_STRICT (X) : REG_OK_FOR_BASE_P_NONSTRICT (X)))
+
+#define RTX_OK_FOR_INDEX_P(X, STRICT) \
+(REG_P (X) \
+ && ((STRICT) ? REG_OK_FOR_INDEX_P_STRICT (X) : REG_OK_FOR_INDEX_P_NONSTRICT (X)))
+
+/* A C compound statement that attempts to replace X, which is an address
+ that needs reloading, with a valid memory address for an operand of
+ mode MODE. WIN is a C statement label elsewhere in the code.
+
+ We try to get a normal form
+ of the address. That will allow inheritance of the address reloads. */
+
+#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_LEVELS,WIN) \
+ do { \
+ if (arc_legitimize_reload_address (&(X), (MODE), (OPNUM), (TYPE))) \
+ goto WIN; \
+ } while (0)
+
+/* Reading lp_count for anything but the lp instruction is very slow on the
+ ARC700. */
+#define DONT_REALLOC(REGNO,MODE) \
+ (TARGET_ARC700 && (REGNO) == 60)
+
+
+/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
+ return the mode to be used for the comparison. */
+/*extern enum machine_mode arc_select_cc_mode ();*/
+#define SELECT_CC_MODE(OP, X, Y) \
+arc_select_cc_mode (OP, X, Y)
+
+/* Return non-zero if SELECT_CC_MODE will never return MODE for a
+ floating point inequality comparison. */
+#define REVERSIBLE_CC_MODE(MODE) 1 /*???*/
+
+/* Costs. */
+
+/* Compute extra cost of moving data between one register class
+ and another. */
+#define REGISTER_MOVE_COST(MODE, CLASS, TO_CLASS) \
+ arc_register_move_cost ((MODE), (CLASS), (TO_CLASS))
+
+/* Compute the cost of moving data between registers and memory. */
+/* Memory is 3 times as expensive as registers.
+ ??? Is that the right way to look at it? */
+#define MEMORY_MOVE_COST(MODE,CLASS,IN) \
+(GET_MODE_SIZE (MODE) <= UNITS_PER_WORD ? 6 : 12)
+
+/* The cost of a branch insn. */
+/* ??? What's the right value here? Branches are certainly more
+ expensive than reg->reg moves. */
+#define BRANCH_COST(speed_p, predictable_p) 2
+
+/* Scc sets the destination to 1 and then conditionally zeroes it.
+ Best case, ORed SCCs can be made into clear - condset - condset.
+ But it could also end up as five insns. So say it costs four on
+ average.
+ These extra instructions - and the second comparison - will also be
+ an extra cost if the first comparison would have been decisive.
+ So get an average saving, with a probability of the first branch
+ beging decisive of p0, we want:
+ p0 * (branch_cost - 4) > (1 - p0) * 5
+ ??? We don't get to see that probability to evaluate, so we can
+ only wildly guess that it might be 50%.
+ ??? The compiler also lacks the notion of branch predictability. */
+#define LOGICAL_OP_NON_SHORT_CIRCUIT \
+ (BRANCH_COST (optimize_function_for_speed_p (cfun), \
+ false) > 9)
+
+/* Nonzero if access to memory by bytes is slow and undesirable.
+ For RISC chips, it means that access to memory by bytes is no
+ better than access by words when possible, so grab a whole word
+ and maybe make use of that. */
+#define SLOW_BYTE_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. */
+/* On the ARC, calling through registers is slow. */
+#define NO_FUNCTION_CSE
+
+/* Section selection. */
+/* WARNING: These section names also appear in dwarfout.c. */
+
+#define TEXT_SECTION_ASM_OP "\t.section\t.text"
+#define DATA_SECTION_ASM_OP "\t.section\t.data"
+
+#define BSS_SECTION_ASM_OP "\t.section\t.bss"
+#define SDATA_SECTION_ASM_OP "\t.section\t.sdata"
+#define SBSS_SECTION_ASM_OP "\t.section\t.sbss"
+
+/* Expression whose value is a string, including spacing, containing the
+ assembler operation to identify the following data as initialization/termination
+ code. If not defined, GCC will assume such a section does not exist. */
+#define INIT_SECTION_ASM_OP "\t.section\t.init"
+#define FINI_SECTION_ASM_OP "\t.section\t.fini"
+
+/* Define this macro if jump tables (for tablejump insns) should be
+ output in the text section, along with the assembler instructions.
+ Otherwise, the readonly data section is used.
+ This macro is irrelevant if there is no separate readonly data section. */
+#define JUMP_TABLES_IN_TEXT_SECTION (flag_pic || CASE_VECTOR_PC_RELATIVE)
+
+/* For DWARF. Marginally different than default so output is "prettier"
+ (and consistent with above). */
+#define PUSHSECTION_FORMAT "\t%s %s\n"
+
+/* Tell crtstuff.c we're using ELF. */
+#define OBJECT_FORMAT_ELF
+
+/* PIC */
+
+/* The register number of the register used to address a table of static
+ data addresses in memory. In some cases this register is defined by a
+ processor's ``application binary interface'' (ABI). When this macro
+ is defined, RTL is generated for this register once, as with the stack
+ pointer and frame pointer registers. If this macro is not defined, it
+ is up to the machine-dependent files to allocate such a register (if
+ necessary). */
+#define PIC_OFFSET_TABLE_REGNUM 26
+
+/* Define this macro if the register defined by PIC_OFFSET_TABLE_REGNUM is
+ clobbered by calls. Do not define this macro if PIC_OFFSET_TABLE_REGNUM
+ is not defined. */
+/* This register is call-saved on the ARC. */
+/*#define PIC_OFFSET_TABLE_REG_CALL_CLOBBERED*/
+
+/* A C expression that is nonzero if X is a legitimate immediate
+ operand on the target machine when generating position independent code.
+ You can assume that X satisfies CONSTANT_P, so you need not
+ check this. You can also assume `flag_pic' is true, so you need not
+ check it either. You need not define this macro if all constants
+ (including SYMBOL_REF) can be immediate operands when generating
+ position independent code. */
+#define LEGITIMATE_PIC_OPERAND_P(X) (arc_legitimate_pic_operand_p(X))
+
+/* PIC and small data don't mix on ARC because they use the same register. */
+#define SDATA_BASE_REGNUM 26
+
+#define ASM_PREFERRED_EH_DATA_FORMAT(CODE, GLOBAL) \
+ (flag_pic \
+ ? (GLOBAL ? DW_EH_PE_indirect : 0) | DW_EH_PE_pcrel | DW_EH_PE_sdata4 \
+ : DW_EH_PE_absptr)
+
+/* Control the assembler format that we output. */
+
+/* A C string constant describing how to begin a comment in the target
+ assembler language. The compiler assumes that the comment will
+ end at the end of the line. */
+/* Gas needs this to be "#" in order to recognize line directives. */
+#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 ""
+
+/* Output to assembler file text saying following lines
+ no longer contain unusual constructs. */
+#define ASM_APP_OFF ""
+
+/* Globalizing directive for a label. */
+#define GLOBAL_ASM_OP "\t.global\t"
+
+/* This is how to output an assembler line defining a `char' constant. */
+#define ASM_OUTPUT_CHAR(FILE, VALUE) \
+( fprintf (FILE, "\t.byte\t"), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+/* This is how to output an assembler line defining a `short' constant. */
+#define ASM_OUTPUT_SHORT(FILE, VALUE) \
+( fprintf (FILE, "\t.hword\t"), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+/* This is how to output an assembler line defining an `int' constant.
+ We also handle symbol output here. Code addresses must be right shifted
+ by 2 because that's how the jump instruction wants them. */
+#define ASM_OUTPUT_INT(FILE, VALUE) \
+do { \
+ fprintf (FILE, "\t.word\t"); \
+ if (GET_CODE (VALUE) == LABEL_REF) \
+ { \
+ fprintf (FILE, "%%st(@"); \
+ output_addr_const (FILE, (VALUE)); \
+ fprintf (FILE, ")"); \
+ } \
+ else \
+ output_addr_const (FILE, (VALUE)); \
+ fprintf (FILE, "\n"); \
+} while (0)
+
+/* This is how to output an assembler line defining a `float' constant. */
+#define ASM_OUTPUT_FLOAT(FILE, VALUE) \
+{ \
+ long t; \
+ char str[30]; \
+ REAL_VALUE_TO_TARGET_SINGLE ((VALUE), t); \
+ REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", str); \
+ fprintf (FILE, "\t.word\t0x%lx %s %s\n", \
+ t, ASM_COMMENT_START, str); \
+}
+
+/* This is how to output an assembler line defining a `double' constant. */
+#define ASM_OUTPUT_DOUBLE(FILE, VALUE) \
+{ \
+ long t[2]; \
+ char str[30]; \
+ REAL_VALUE_TO_TARGET_DOUBLE ((VALUE), t); \
+ REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", str); \
+ fprintf (FILE, "\t.word\t0x%lx %s %s\n\t.word\t0x%lx\n", \
+ t[0], ASM_COMMENT_START, str, t[1]); \
+}
+
+/* This is how to output the definition of a user-level label named NAME,
+ such as the label on a static function or variable NAME. */
+#define ASM_OUTPUT_LABEL(FILE, NAME) \
+do { assemble_name (FILE, NAME); fputs (":\n", FILE); } while (0)
+
+#define ASM_NAME_P(NAME) ( NAME[0]=='*')
+
+/* This is how to output a reference to a user-level label named NAME.
+ `assemble_name' uses this. */
+/* We work around a dwarfout.c deficiency by watching for labels from it and
+ not adding the '_' prefix. There is a comment in
+ dwarfout.c that says it should be using ASM_OUTPUT_INTERNAL_LABEL. */
+#define ASM_OUTPUT_LABELREF(FILE, NAME1) \
+do { \
+ const char *NAME; \
+ NAME = (*targetm.strip_name_encoding)(NAME1); \
+ if ((NAME)[0] == '.' && (NAME)[1] == 'L') \
+ fprintf (FILE, "%s", NAME); \
+ else \
+ { \
+ if (!ASM_NAME_P (NAME1)) \
+ fprintf (FILE, "%s", user_label_prefix); \
+ fprintf (FILE, "%s", NAME); \
+ } \
+} while (0)
+
+/* This is how to output a reference to a symbol_ref / label_ref as
+ (part of) an operand. To disambiguate from register names like
+ a1 / a2 / status etc, symbols are preceded by '@'. */
+#define ASM_OUTPUT_SYMBOL_REF(FILE,SYM) \
+ ASM_OUTPUT_LABEL_REF ((FILE), XSTR ((SYM), 0))
+#define ASM_OUTPUT_LABEL_REF(FILE,STR) \
+ do \
+ { \
+ fputc ('@', file); \
+ assemble_name ((FILE), (STR)); \
+ } \
+ while (0)
+
+/* Store in OUTPUT a string (made with alloca) containing
+ an assembler-name for a local static variable named NAME.
+ LABELNO is an integer which is different for each call. */
+#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \
+( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \
+ sprintf ((OUTPUT), "%s.%d", (NAME), (LABELNO)))
+
+/* 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). */
+
+#undef TYPE_OPERAND_FMT
+#define TYPE_OPERAND_FMT "@%s"
+
+/* A C string containing the appropriate assembler directive to
+ specify the size of a symbol, without any arguments. On systems
+ that use ELF, the default (in `config/elfos.h') is `"\t.size\t"';
+ on other systems, the default is not to define this macro. */
+#undef SIZE_ASM_OP
+#define SIZE_ASM_OP "\t.size\t"
+
+/* Assembler pseudo-op to equate one value with another. */
+/* ??? This is needed because dwarfout.c provides a default definition too
+ late for defaults.h (which contains the default definition of ASM_OTPUT_DEF
+ that we use). */
+#ifdef SET_ASM_OP
+#undef SET_ASM_OP
+#endif
+#define SET_ASM_OP "\t.set\t"
+
+extern char rname56[], rname57[], rname58[], rname59[];
+/* How to refer to registers in assembler output.
+ This sequence is indexed by compiler's hard-register-number (see above). */
+#define REGISTER_NAMES \
+{ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", \
+ "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", \
+ "r24", "r25", "gp", "fp", "sp", "ilink1", "ilink2", "blink", \
+ "r32", "r33", "r34", "r35", "r36", "r37", "r38", "r39", \
+ "d1", "d1", "d2", "d2", "r44", "r45", "r46", "r47", \
+ "r48", "r49", "r50", "r51", "r52", "r53", "r54", "r55", \
+ rname56,rname57,rname58,rname59,"lp_count", "cc", "ap", "pcl", \
+ "vr0", "vr1", "vr2", "vr3", "vr4", "vr5", "vr6", "vr7", \
+ "vr8", "vr9", "vr10", "vr11", "vr12", "vr13", "vr14", "vr15", \
+ "vr16", "vr17", "vr18", "vr19", "vr20", "vr21", "vr22", "vr23", \
+ "vr24", "vr25", "vr26", "vr27", "vr28", "vr29", "vr30", "vr31", \
+ "vr32", "vr33", "vr34", "vr35", "vr36", "vr37", "vr38", "vr39", \
+ "vr40", "vr41", "vr42", "vr43", "vr44", "vr45", "vr46", "vr47", \
+ "vr48", "vr49", "vr50", "vr51", "vr52", "vr53", "vr54", "vr55", \
+ "vr56", "vr57", "vr58", "vr59", "vr60", "vr61", "vr62", "vr63", \
+ "dr0", "dr1", "dr2", "dr3", "dr4", "dr5", "dr6", "dr7", \
+ "dr0", "dr1", "dr2", "dr3", "dr4", "dr5", "dr6", "dr7", \
+ "lp_start", "lp_end" \
+}
+
+/* Entry to the insn conditionalizer. */
+#define FINAL_PRESCAN_INSN(INSN, OPVEC, NOPERANDS) \
+ arc_final_prescan_insn (INSN, OPVEC, NOPERANDS)
+
+/* A C expression which evaluates to true if CODE is a valid
+ punctuation character for use in the `PRINT_OPERAND' macro. */
+extern char arc_punct_chars[];
+#define PRINT_OPERAND_PUNCT_VALID_P(CHAR) \
+arc_punct_chars[(unsigned char) (CHAR)]
+
+/* Print operand X (an rtx) in assembler syntax to file FILE.
+ CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
+ For `%' followed by punctuation, CODE is the punctuation and X is null. */
+#define PRINT_OPERAND(FILE, X, CODE) \
+arc_print_operand (FILE, X, CODE)
+
+/* A C compound statement to output to stdio stream STREAM the
+ assembler syntax for an instruction operand that is a memory
+ reference whose address is ADDR. ADDR is an RTL expression.
+
+ On some machines, the syntax for a symbolic address depends on
+ the section that the address refers to. On these machines,
+ define the macro `ENCODE_SECTION_INFO' to store the information
+ into the `symbol_ref', and then check for it here. */
+#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \
+arc_print_operand_address (FILE, ADDR)
+
+/* This is how to output an element of a case-vector that is absolute. */
+#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
+do { \
+ char label[30]; \
+ ASM_GENERATE_INTERNAL_LABEL (label, "L", VALUE); \
+ fprintf (FILE, "\t.word "); \
+ assemble_name (FILE, label); \
+ fprintf(FILE, "\n"); \
+} while (0)
+
+/* This is how to output an element of a case-vector that is relative. */
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
+do { \
+ char label[30]; \
+ ASM_GENERATE_INTERNAL_LABEL (label, "L", VALUE); \
+ switch (GET_MODE (BODY)) \
+ { \
+ case QImode: fprintf (FILE, "\t.byte "); break; \
+ case HImode: fprintf (FILE, "\t.hword "); break; \
+ case SImode: fprintf (FILE, "\t.word "); break; \
+ default: gcc_unreachable (); \
+ } \
+ assemble_name (FILE, label); \
+ fprintf (FILE, "-"); \
+ ASM_GENERATE_INTERNAL_LABEL (label, "L", REL); \
+ assemble_name (FILE, label); \
+ if (TARGET_COMPACT_CASESI) \
+ fprintf (FILE, " + %d", 4 + arc_get_unalign ()); \
+ fprintf(FILE, "\n"); \
+} while (0)
+
+/* ADDR_DIFF_VECs are in the text section and thus can affect the
+ current alignment. */
+#define ASM_OUTPUT_CASE_END(FILE, NUM, JUMPTABLE) \
+ do \
+ { \
+ if (GET_CODE (PATTERN (JUMPTABLE)) == ADDR_DIFF_VEC \
+ && ((GET_MODE_SIZE (GET_MODE (PATTERN (JUMPTABLE))) \
+ * XVECLEN (PATTERN (JUMPTABLE), 1) + 1) \
+ & 2)) \
+ arc_toggle_unalign (); \
+ } \
+ while (0)
+
+#define JUMP_ALIGN(LABEL) (arc_size_opt_level < 2 ? 2 : 0)
+#define LABEL_ALIGN_AFTER_BARRIER(LABEL) \
+ (JUMP_ALIGN(LABEL) \
+ ? JUMP_ALIGN(LABEL) \
+ : GET_CODE (PATTERN (prev_active_insn (LABEL))) == ADDR_DIFF_VEC \
+ ? 1 : 0)
+/* The desired alignment for the location counter at the beginning
+ of a loop. */
+/* On the ARC, align loops to 4 byte boundaries unless doing all-out size
+ optimization. */
+#define LOOP_ALIGN JUMP_ALIGN
+
+#define LABEL_ALIGN(LABEL) (arc_label_align (LABEL))
+
+/* This is how to output an assembler line
+ that says to advance the location counter
+ to a multiple of 2**LOG bytes. */
+#define ASM_OUTPUT_ALIGN(FILE,LOG) \
+do { \
+ if ((LOG) != 0) fprintf (FILE, "\t.align %d\n", 1 << (LOG)); \
+ if ((LOG) > 1) \
+ arc_clear_unalign (); \
+} while (0)
+
+/* ASM_OUTPUT_ALIGNED_DECL_LOCAL (STREAM, DECL, NAME, SIZE, ALIGNMENT)
+ Define this macro when you need to see the variable's decl in order to
+ chose what to output. */
+#define ASM_OUTPUT_ALIGNED_DECL_LOCAL(STREAM, DECL, NAME, SIZE, ALIGNMENT) \
+ arc_asm_output_aligned_decl_local (STREAM, DECL, NAME, SIZE, ALIGNMENT, 0)
+
+/* To translate the return value of arc_function_type into a register number
+ to jump through for function return. */
+extern int arc_return_address_regs[4];
+
+/* Debugging information. */
+
+/* Generate DBX and DWARF debugging information. */
+#ifdef DBX_DEBUGGING_INFO
+#undef DBX_DEBUGGING_INFO
+#endif
+#define DBX_DEBUGGING_INFO
+
+#ifdef DWARF2_DEBUGGING_INFO
+#undef DWARF2_DEBUGGING_INFO
+#endif
+#define DWARF2_DEBUGGING_INFO
+
+/* Prefer STABS (for now). */
+#undef PREFERRED_DEBUGGING_TYPE
+#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
+
+/* How to renumber registers for dbx and gdb. */
+#define DBX_REGISTER_NUMBER(REGNO) \
+ ((TARGET_MULMAC_32BY16_SET && (REGNO) >= 56 && (REGNO) <= 57) \
+ ? ((REGNO) ^ !TARGET_BIG_ENDIAN) \
+ : (TARGET_MUL64_SET && (REGNO) >= 57 && (REGNO) <= 59) \
+ ? ((REGNO) == 57 \
+ ? 58 /* MMED */ \
+ : ((REGNO) & 1) ^ TARGET_BIG_ENDIAN \
+ ? 59 /* MHI */ \
+ : 57 + !!TARGET_MULMAC_32BY16_SET) /* MLO */ \
+ : (REGNO))
+
+#define DWARF_FRAME_REGNUM(REG) (REG)
+
+#define DWARF_FRAME_RETURN_COLUMN DWARF_FRAME_REGNUM (31)
+
+#define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (Pmode, 31)
+
+/* Frame info. */
+
+/* Define this macro to 0 if your target supports DWARF 2 frame unwind
+ information, but it does not yet work with exception handling. */
+/* N.B. the below test is valid in an #if, but not in a C expression. */
+#if DEFAULT_LIBC == LIBC_UCLIBC
+#define DWARF2_UNWIND_INFO 1
+#else
+#define DWARF2_UNWIND_INFO 0
+#endif
+
+#define EH_RETURN_DATA_REGNO(N) \
+ ((N) < 4 ? (N) : INVALID_REGNUM)
+
+/* Turn off splitting of long stabs. */
+#define DBX_CONTIN_LENGTH 0
+
+/* Miscellaneous. */
+
+/* Specify the machine mode that this machine uses
+ for the index in the tablejump instruction.
+ If we have pc relative case vectors, we start the case vector shortening
+ with QImode. */
+#define CASE_VECTOR_MODE \
+ ((optimize && (CASE_VECTOR_PC_RELATIVE || flag_pic)) ? QImode : Pmode)
+
+/* Define as C expression which evaluates to nonzero if the tablejump
+ instruction expects the table to contain offsets from the address of the
+ table.
+ Do not define this if the table should contain absolute addresses. */
+#define CASE_VECTOR_PC_RELATIVE TARGET_CASE_VECTOR_PC_RELATIVE
+
+#define CASE_VECTOR_SHORTEN_MODE(MIN_OFFSET, MAX_OFFSET, BODY) \
+ CASE_VECTOR_SHORTEN_MODE_1 \
+ (MIN_OFFSET, TARGET_COMPACT_CASESI ? MAX_OFFSET + 6 : MAX_OFFSET, BODY)
+
+#define CASE_VECTOR_SHORTEN_MODE_1(MIN_OFFSET, MAX_OFFSET, BODY) \
+((MIN_OFFSET) >= 0 && (MAX_OFFSET) <= 255 \
+ ? (ADDR_DIFF_VEC_FLAGS (BODY).offset_unsigned = 1, QImode) \
+ : (MIN_OFFSET) >= -128 && (MAX_OFFSET) <= 127 \
+ ? (ADDR_DIFF_VEC_FLAGS (BODY).offset_unsigned = 0, QImode) \
+ : (MIN_OFFSET) >= 0 && (MAX_OFFSET) <= 65535 \
+ ? (ADDR_DIFF_VEC_FLAGS (BODY).offset_unsigned = 1, HImode) \
+ : (MIN_OFFSET) >= -32768 && (MAX_OFFSET) <= 32767 \
+ ? (ADDR_DIFF_VEC_FLAGS (BODY).offset_unsigned = 0, HImode) \
+ : SImode)
+
+#define ADDR_VEC_ALIGN(VEC_INSN) \
+ (exact_log2 (GET_MODE_SIZE (GET_MODE (PATTERN (VEC_INSN)))))
+#undef ASM_OUTPUT_BEFORE_CASE_LABEL
+#define ASM_OUTPUT_BEFORE_CASE_LABEL(FILE, PREFIX, NUM, TABLE) \
+ ASM_OUTPUT_ALIGN ((FILE), ADDR_VEC_ALIGN (TABLE));
+
+#define INSN_LENGTH_ALIGNMENT(INSN) \
+ ((JUMP_P (INSN) \
+ && GET_CODE (PATTERN (INSN)) == ADDR_DIFF_VEC \
+ && GET_MODE (PATTERN (INSN)) == QImode) \
+ ? 0 : length_unit_log)
+
+/* Define if operations between registers always perform the operation
+ on the full register even if a narrower mode is specified. */
+#define WORD_REGISTER_OPERATIONS
+
+/* Define if loading in MODE, an integral mode narrower than BITS_PER_WORD
+ will either zero-extend or sign-extend. The value of this macro should
+ be the code that says which one of the two operations is implicitly
+ done, NIL if none. */
+#define LOAD_EXTEND_OP(MODE) ZERO_EXTEND
+
+
+/* Max number of bytes we can move from memory to memory
+ in one reasonably fast instruction. */
+#define MOVE_MAX 4
+
+/* Let the movmem expander handle small block moves. */
+#define MOVE_BY_PIECES_P(LEN, ALIGN) 0
+#define CAN_MOVE_BY_PIECES(SIZE, ALIGN) \
+ (move_by_pieces_ninsns (SIZE, ALIGN, MOVE_MAX_PIECES + 1) \
+ < (unsigned int) MOVE_RATIO (!optimize_size))
+
+/* Undo the effects of the movmem pattern presence on STORE_BY_PIECES_P . */
+#define MOVE_RATIO(SPEED) ((SPEED) ? 15 : 3)
+
+/* Define this to be nonzero if shift instructions ignore all but the low-order
+ few bits. Changed from 1 to 0 for rotate pattern testcases
+ (e.g. 20020226-1.c). This change truncates the upper 27 bits of a word
+ while rotating a word. Came to notice through a combine phase
+ optimization viz. a << (32-b) is equivalent to a << (-b).
+*/
+#define SHIFT_COUNT_TRUNCATED 0
+
+/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
+ is done just by pretending it is already truncated. */
+#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
+
+/* We assume that the store-condition-codes instructions store 0 for false
+ and some other value for true. This is the value stored for true. */
+#define STORE_FLAG_VALUE 1
+
+/* 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. */
+/* ARCompact has full 32-bit pointers. */
+#define Pmode SImode
+
+/* A function address in a call instruction. */
+#define FUNCTION_MODE SImode
+
+/* Define the information needed to generate branch and scc insns. This is
+ stored from the compare operation. Note that we can't use "rtx" here
+ since it hasn't been defined! */
+extern struct rtx_def *arc_compare_op0, *arc_compare_op1;
+
+/* ARC function types. */
+enum arc_function_type {
+ ARC_FUNCTION_UNKNOWN, ARC_FUNCTION_NORMAL,
+ /* These are interrupt handlers. The name corresponds to the register
+ name that contains the return address. */
+ ARC_FUNCTION_ILINK1, ARC_FUNCTION_ILINK2
+};
+#define ARC_INTERRUPT_P(TYPE) \
+((TYPE) == ARC_FUNCTION_ILINK1 || (TYPE) == ARC_FUNCTION_ILINK2)
+
+/* Compute the type of a function from its DECL. Needed for EPILOGUE_USES. */
+struct function;
+extern enum arc_function_type arc_compute_function_type (struct function *);
+
+/* Called by crtstuff.c to make calls to function FUNCTION that are defined in
+ SECTION_OP, and then to switch back to text section. */
+#undef CRT_CALL_STATIC_FUNCTION
+#define CRT_CALL_STATIC_FUNCTION(SECTION_OP, FUNC) \
+ asm (SECTION_OP "\n\t" \
+ "bl @" USER_LABEL_PREFIX #FUNC "\n" \
+ TEXT_SECTION_ASM_OP);
+
+/* This macro expands to the name of the scratch register r12, used for
+ temporary calculations according to the ABI. */
+#define ARC_TEMP_SCRATCH_REG "r12"
+
+/* The C++ compiler must use one bit to indicate whether the function
+ that will be called through a pointer-to-member-function is
+ virtual. Normally, we assume that the low-order bit of a function
+ pointer must always be zero. Then, by ensuring that the
+ vtable_index is odd, we can distinguish which variant of the union
+ is in use. But, on some platforms function pointers can be odd,
+ and so this doesn't work. In that case, we use the low-order bit
+ of the `delta' field, and shift the remainder of the `delta' field
+ to the left. We needed to do this for A4 because the address was always
+ shifted and thus could be odd. */
+#define TARGET_PTRMEMFUNC_VBIT_LOCATION \
+ (ptrmemfunc_vbit_in_pfn)
+
+#define INSN_SETS_ARE_DELAYED(X) \
+ (GET_CODE (X) == INSN \
+ && GET_CODE (PATTERN (X)) != SEQUENCE \
+ && GET_CODE (PATTERN (X)) != USE \
+ && GET_CODE (PATTERN (X)) != CLOBBER \
+ && (get_attr_type (X) == TYPE_CALL || get_attr_type (X) == TYPE_SFUNC))
+
+#define INSN_REFERENCES_ARE_DELAYED(insn) INSN_SETS_ARE_DELAYED (insn)
+
+#define CALL_ATTR(X, NAME) \
+ ((CALL_P (X) || NONJUMP_INSN_P (X)) \
+ && GET_CODE (PATTERN (X)) != USE \
+ && GET_CODE (PATTERN (X)) != CLOBBER \
+ && get_attr_is_##NAME (X) == IS_##NAME##_YES) \
+
+#define REVERSE_CONDITION(CODE,MODE) \
+ (((MODE) == CC_FP_GTmode || (MODE) == CC_FP_GEmode \
+ || (MODE) == CC_FP_UNEQmode || (MODE) == CC_FP_ORDmode \
+ || (MODE) == CC_FPXmode) \
+ ? reverse_condition_maybe_unordered ((CODE)) \
+ : reverse_condition ((CODE)))
+
+#define ADJUST_INSN_LENGTH(X, LENGTH) \
+ ((LENGTH) \
+ = (GET_CODE (PATTERN (X)) == SEQUENCE \
+ ? ((LENGTH) \
+ + arc_adjust_insn_length (XVECEXP (PATTERN (X), 0, 0), \
+ get_attr_length (XVECEXP (PATTERN (X), \
+ 0, 0)), \
+ true) \
+ - get_attr_length (XVECEXP (PATTERN (X), 0, 0)) \
+ + arc_adjust_insn_length (XVECEXP (PATTERN (X), 0, 1), \
+ get_attr_length (XVECEXP (PATTERN (X), \
+ 0, 1)), \
+ true) \
+ - get_attr_length (XVECEXP (PATTERN (X), 0, 1))) \
+ : arc_adjust_insn_length ((X), (LENGTH), false)))
+
+#define IS_ASM_LOGICAL_LINE_SEPARATOR(C,STR) ((C) == '`')
+
+#define INIT_EXPANDERS arc_init_expanders ()
+
+#define CFA_FRAME_BASE_OFFSET(FUNDECL) (-arc_decl_pretend_args ((FUNDECL)))
+
+#define ARG_POINTER_CFA_OFFSET(FNDECL) \
+ (FIRST_PARM_OFFSET (FNDECL) + arc_decl_pretend_args ((FNDECL)))
+
+enum
+{
+ ARC_LRA_PRIORITY_NONE, ARC_LRA_PRIORITY_NONCOMPACT, ARC_LRA_PRIORITY_COMPACT
+};
+
+/* The define_cond_exec construct is rather crude, as we can't have
+ different ones with different conditions apply to different sets
+ of instructions. We can't use an attribute test inside the condition,
+ because that would lead to infinite recursion as the attribute test
+ needs to recognize the insn. So, instead we have a clause for
+ the pattern condition of all sfunc patterns which is only relevant for
+ the predicated varaint. */
+#define SFUNC_CHECK_PREDICABLE \
+ (GET_CODE (PATTERN (insn)) != COND_EXEC || !flag_pic || !TARGET_MEDIUM_CALLS)
+
+#endif /* GCC_ARC_H */
diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
new file mode 100644
index 00000000000..baf347876be
--- /dev/null
+++ b/gcc/config/arc/arc.md
@@ -0,0 +1,5164 @@
+;; Machine description of the Synopsys DesignWare ARC cpu for GNU C compiler
+;; Copyright (C) 1994, 1997, 1999, 2006-2013
+;; Free Software Foundation, Inc.
+
+;; Sources derived from work done by Sankhya Technologies (www.sankhya.com) on
+;; behalf of Synopsys Inc.
+
+;; Position Independent Code support added,Code cleaned up,
+;; Comments and Support For ARC700 instructions added by
+;; Saurabh Verma (saurabh.verma@codito.com)
+;; Ramana Radhakrishnan(ramana.radhakrishnan@codito.com)
+;;
+;; Profiling support and performance improvements by
+;; Joern Rennecke (joern.rennecke@embecosm.com)
+;;
+;; Support for DSP multiply instructions and mul64
+;; instructions for ARC600; and improvements in flag setting
+;; instructions by
+;; Muhammad Khurram Riaz (Khurram.Riaz@arc.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/>.
+
+;; See file "rtl.def" for documentation on define_insn, match_*, et. al.
+
+;; <op> dest, src Two operand instruction's syntax
+;; <op> dest, src1, src2 Three operand instruction's syntax
+
+;; ARC and ARCompact PREDICATES:
+;;
+;; comparison_operator LT, GT, LE, GE, LTU, GTU, LEU, GEU, EQ, NE
+;; memory_operand memory [m]
+;; immediate_operand immediate constant [IKLMNOP]
+;; register_operand register [rq]
+;; general_operand register, memory, constant [rqmIKLMNOP]
+
+;; Note that the predicates are only used when selecting a pattern
+;; to determine if an operand is valid.
+
+;; The constraints then select which of the possible valid operands
+;; is present (and guide register selection). The actual assembly
+;; instruction is then selected on the basis of the constraints.
+
+;; ARC and ARCompact CONSTRAINTS:
+;;
+;; b stack pointer r28
+;; f frame pointer r27
+;; Rgp global pointer r26
+;; g general reg, memory, constant
+;; m memory
+;; p memory address
+;; q registers commonly used in
+;; 16-bit insns r0-r3, r12-r15
+;; c core registers r0-r60, ap, pcl
+;; r general registers r0-r28, blink, ap, pcl
+;;
+;; H fp 16-bit constant
+;; I signed 12-bit immediate (for ARCompact)
+;; K unsigned 3-bit immediate (for ARCompact)
+;; L unsigned 6-bit immediate (for ARCompact)
+;; M unsinged 5-bit immediate (for ARCompact)
+;; O unsinged 7-bit immediate (for ARCompact)
+;; P unsinged 8-bit immediate (for ARCompact)
+;; N constant '1' (for ARCompact)
+
+
+;; TODO:
+;; -> prefetch instruction
+
+;; -----------------------------------------------------------------------------
+
+;; Include DFA scheduluers
+(include ("arc600.md"))
+(include ("arc700.md"))
+
+;; Predicates
+
+(include ("predicates.md"))
+(include ("constraints.md"))
+;; -----------------------------------------------------------------------------
+
+;; UNSPEC Usage:
+;; ~~~~~~~~~~~~
+;; -----------------------------------------------------------------------------
+;; Symbolic name Value Desc.
+;; -----------------------------------------------------------------------------
+;; UNSPEC_PLT 3 symbol to be referenced through the PLT
+;; UNSPEC_GOT 4 symbol to be rerenced through the GOT
+;; UNSPEC_GOTOFF 5 Local symbol.To be referenced relative to the
+;; GOTBASE.(Referenced as @GOTOFF)
+;; ----------------------------------------------------------------------------
+
+
+(define_constants
+ [(UNSPEC_SWAP 13) ; swap generation through builtins. candidate for scheduling
+ (UNSPEC_MUL64 14) ; mul64 generation through builtins. candidate for scheduling
+ (UNSPEC_MULU64 15) ; mulu64 generation through builtins. candidate for scheduling
+ (UNSPEC_DIVAW 16) ; divaw generation through builtins. candidate for scheduling
+ (UNSPEC_DIRECT 17)
+ (UNSPEC_PROF 18) ; profile callgraph counter
+ (UNSPEC_LP 19) ; to set LP_END
+ (UNSPEC_CASESI 20)
+ (VUNSPEC_RTIE 17) ; blockage insn for rtie generation
+ (VUNSPEC_SYNC 18) ; blockage insn for sync generation
+ (VUNSPEC_BRK 19) ; blockage insn for brk generation
+ (VUNSPEC_FLAG 20) ; blockage insn for flag generation
+ (VUNSPEC_SLEEP 21) ; blockage insn for sleep generation
+ (VUNSPEC_SWI 22) ; blockage insn for swi generation
+ (VUNSPEC_CORE_READ 23) ; blockage insn for reading a core register
+ (VUNSPEC_CORE_WRITE 24) ; blockage insn for writing to a core register
+ (VUNSPEC_LR 25) ; blockage insn for reading an auxiliary register
+ (VUNSPEC_SR 26) ; blockage insn for writing to an auxiliary register
+ (VUNSPEC_TRAP_S 27) ; blockage insn for trap_s generation
+ (VUNSPEC_UNIMP_S 28) ; blockage insn for unimp_s generation
+
+ (R0_REG 0)
+ (R1_REG 1)
+ (R2_REG 2)
+ (R3_REG 3)
+ (R12_REG 12)
+ (SP_REG 28)
+ (ILINK1_REGNUM 29)
+ (ILINK2_REGNUM 30)
+ (RETURN_ADDR_REGNUM 31)
+ (MUL64_OUT_REG 58)
+
+ (VUNSPEC_DEXCL 32) ; blockage insn for reading an auxiliary register without LR support
+ (VUNSPEC_DEXCL_NORES 33) ; blockage insn for reading an auxiliary register without LR support
+ (VUNSPEC_LR_HIGH 34) ; blockage insn for reading an auxiliary register
+
+ (LP_COUNT 60)
+ (CC_REG 61)
+ (LP_START 144)
+ (LP_END 145)
+ ]
+)
+
+(define_attr "is_sfunc" "no,yes" (const_string "no"))
+
+;; Insn type. Used to default other attribute values.
+; While the attribute is_sfunc is set for any call of a special function,
+; the instruction type sfunc is used only for the special call sequence
+; that loads the (pc-relative) function address into r12 and then calls
+; via r12.
+
+(define_attr "type"
+ "move,load,store,cmove,unary,binary,compare,shift,uncond_branch,jump,branch,
+ brcc,brcc_no_delay_slot,call,sfunc,call_no_delay_slot,
+ multi,umulti, two_cycle_core,lr,sr,divaw,loop_setup,loop_end,return,
+ misc,spfp,dpfp_mult,dpfp_addsub,mulmac_600,cc_arith,
+ simd_vload, simd_vload128, simd_vstore, simd_vmove, simd_vmove_else_zero,
+ simd_vmove_with_acc, simd_varith_1cycle, simd_varith_2cycle,
+ simd_varith_with_acc, simd_vlogic, simd_vlogic_with_acc,
+ simd_vcompare, simd_vpermute, simd_vpack, simd_vpack_with_acc,
+ simd_valign, simd_valign_with_acc, simd_vcontrol,
+ simd_vspecial_3cycle, simd_vspecial_4cycle, simd_dma"
+ (cond [(eq_attr "is_sfunc" "yes")
+ (cond [(match_test "!TARGET_LONG_CALLS_SET && (!TARGET_MEDIUM_CALLS || GET_CODE (PATTERN (insn)) != COND_EXEC)") (const_string "call")
+ (match_test "flag_pic") (const_string "sfunc")]
+ (const_string "call_no_delay_slot"))]
+ (const_string "binary")))
+
+;; The following three attributes are mixed case so that they can be
+;; used conveniently with the CALL_ATTR macro.
+(define_attr "is_CALL" "no,yes"
+ (cond [(eq_attr "is_sfunc" "yes") (const_string "yes")
+ (eq_attr "type" "call,call_no_delay_slot") (const_string "yes")]
+ (const_string "no")))
+
+(define_attr "is_SIBCALL" "no,yes" (const_string "no"))
+
+(define_attr "is_NON_SIBCALL" "no,yes"
+ (cond [(eq_attr "is_SIBCALL" "yes") (const_string "no")
+ (eq_attr "is_CALL" "yes") (const_string "yes")]
+ (const_string "no")))
+
+
+;; Attribute describing the processor
+(define_attr "cpu" "none,A5,ARC600,ARC700"
+ (const (symbol_ref "arc_cpu_attr")))
+
+;; true for compact instructions (those with _s suffix)
+;; "maybe" means compact unless we conditionalize the insn.
+(define_attr "iscompact" "true,maybe,true_limm,maybe_limm,false"
+ (cond [(eq_attr "type" "sfunc")
+ (const_string "maybe")]
+ (const_string "false")))
+
+
+; Is there an instruction that we are actually putting into the delay slot?
+(define_attr "delay_slot_filled" "no,yes"
+ (cond [(match_test "NEXT_INSN (PREV_INSN (insn)) == insn")
+ (const_string "no")
+ (match_test "!TARGET_AT_DBR_CONDEXEC
+ && JUMP_P (insn)
+ && INSN_ANNULLED_BRANCH_P (insn)
+ && !INSN_FROM_TARGET_P (NEXT_INSN (insn))")
+ (const_string "no")]
+ (const_string "yes")))
+
+; Is a delay slot present for purposes of shorten_branches?
+; We have to take the length of this insn into account for forward branches
+; even if we don't put the insn actually into a delay slot.
+(define_attr "delay_slot_present" "no,yes"
+ (cond [(match_test "NEXT_INSN (PREV_INSN (insn)) == insn")
+ (const_string "no")]
+ (const_string "yes")))
+
+; We can't use get_attr_length (NEXT_INSN (insn)) because this gives the
+; length of a different insn with the same uid.
+(define_attr "delay_slot_length" ""
+ (cond [(match_test "NEXT_INSN (PREV_INSN (insn)) == insn")
+ (const_int 0)]
+ (symbol_ref "get_attr_length (NEXT_INSN (PREV_INSN (insn)))
+ - get_attr_length (insn)")))
+
+
+(define_attr "enabled" "no,yes" (const_string "yes"))
+
+(define_attr "predicable" "no,yes" (const_string "no"))
+;; if 'predicable' were not so brain-dead, we would specify:
+;; (cond [(eq_attr "cond" "!canuse") (const_string "no")
+;; (eq_attr "iscompact" "maybe") (const_string "no")]
+;; (const_string "yes"))
+;; and then for everything but calls, we could just set the cond attribute.
+
+;; Condition codes: this one is used by final_prescan_insn to speed up
+;; conditionalizing instructions. It saves having to scan the rtl to see if
+;; it uses or alters the condition codes.
+
+;; USE: This insn uses the condition codes (eg: a conditional branch).
+;; CANUSE: This insn can use the condition codes (for conditional execution).
+;; SET: All condition codes are set by this insn.
+;; SET_ZN: the Z and N flags are set by this insn.
+;; SET_ZNC: the Z, N, and C flags are set by this insn.
+;; CLOB: The condition codes are set to unknown values by this insn.
+;; NOCOND: This insn can't use and doesn't affect the condition codes.
+
+(define_attr "cond" "use,canuse,canuse_limm,canuse_limm_add,set,set_zn,clob,nocond"
+ (cond
+ [(and (eq_attr "predicable" "yes")
+ (eq_attr "is_sfunc" "no")
+ (eq_attr "delay_slot_filled" "no"))
+ (const_string "canuse")
+
+ (eq_attr "type" "call")
+ (cond [(eq_attr "delay_slot_filled" "yes") (const_string "nocond")
+ (match_test "!flag_pic") (const_string "canuse_limm")]
+ (const_string "nocond"))
+
+ (eq_attr "iscompact" "maybe,false")
+ (cond [ (and (eq_attr "type" "move")
+ (match_operand 1 "immediate_operand" ""))
+ (if_then_else
+ (ior (match_operand 1 "u6_immediate_operand" "")
+ (match_operand 1 "long_immediate_operand" ""))
+ (const_string "canuse")
+ (const_string "canuse_limm"))
+
+ (eq_attr "type" "binary")
+ (cond [(ne (symbol_ref "REGNO (operands[0])")
+ (symbol_ref "REGNO (operands[1])"))
+ (const_string "nocond")
+ (match_operand 2 "register_operand" "")
+ (const_string "canuse")
+ (match_operand 2 "u6_immediate_operand" "")
+ (const_string "canuse")
+ (match_operand 2 "long_immediate_operand" "")
+ (const_string "canuse")
+ (match_operand 2 "const_int_operand" "")
+ (const_string "canuse_limm")]
+ (const_string "nocond"))
+
+ (eq_attr "type" "compare")
+ (const_string "set")
+
+ (eq_attr "type" "cmove,branch")
+ (const_string "use")
+
+ (eq_attr "is_sfunc" "yes")
+ (cond [(match_test "(TARGET_MEDIUM_CALLS
+ && !TARGET_LONG_CALLS_SET
+ && flag_pic)")
+ (const_string "canuse_limm_add")
+ (match_test "(TARGET_MEDIUM_CALLS
+ && !TARGET_LONG_CALLS_SET)")
+ (const_string "canuse_limm")]
+ (const_string "canuse"))
+
+ ]
+
+ (const_string "nocond"))]
+
+ (cond [(eq_attr "type" "compare")
+ (const_string "set")
+
+ (eq_attr "type" "cmove,branch")
+ (const_string "use")
+
+ ]
+
+ (const_string "nocond"))))
+
+/* ??? Having all these patterns gives ifcvt more freedom to generate
+ inefficient code. It seem to operate on the premise that
+ register-register copies and registers are free. I see better code
+ with -fno-if-convert now than without. */
+(define_cond_exec
+ [(match_operator 0 "proper_comparison_operator"
+ [(reg CC_REG) (const_int 0)])]
+ "true"
+ "")
+
+;; Length (in # of bytes, long immediate constants counted too).
+;; ??? There's a nasty interaction between the conditional execution fsm
+;; and insn lengths: insns with shimm values cannot be conditionally executed.
+(define_attr "length" ""
+ (cond
+ [(eq_attr "iscompact" "true,maybe")
+ (cond
+ [(eq_attr "type" "sfunc")
+ (cond [(match_test "GET_CODE (PATTERN (insn)) == COND_EXEC")
+ (const_int 12)]
+ (const_int 10))
+ (match_test "GET_CODE (PATTERN (insn)) == COND_EXEC") (const_int 4)]
+ (const_int 2))
+
+ (eq_attr "iscompact" "true_limm,maybe_limm")
+ (const_int 6)
+
+ (eq_attr "type" "load")
+ (if_then_else
+ (match_operand 1 "long_immediate_loadstore_operand" "")
+ (const_int 8) (const_int 4))
+
+ (eq_attr "type" "store")
+ (if_then_else
+ (ior (match_operand 0 "long_immediate_loadstore_operand" "")
+ (match_operand 1 "immediate_operand" ""))
+ (const_int 8) (const_int 4))
+
+ (eq_attr "type" "move,unary")
+ (cond
+ [(match_operand 1 "u6_immediate_operand" "") (const_int 4)
+ (match_operand 1 "register_operand" "") (const_int 4)
+ (match_operand 1 "long_immediate_operand" "") (const_int 8)
+ (match_test "GET_CODE (PATTERN (insn)) == COND_EXEC") (const_int 8)]
+ (const_int 4))
+
+ (and (eq_attr "type" "shift")
+ (match_operand 1 "immediate_operand"))
+ (const_int 8)
+ (eq_attr "type" "binary,shift")
+ (if_then_else
+ (ior (match_operand 2 "long_immediate_operand" "")
+ (and (ne (symbol_ref "REGNO (operands[0])")
+ (symbol_ref "REGNO (operands[1])"))
+ (eq (match_operand 2 "u6_immediate_operand" "")
+ (const_int 0))))
+
+ (const_int 8) (const_int 4))
+
+ (eq_attr "type" "cmove")
+ (if_then_else (match_operand 1 "register_operand" "")
+ (const_int 4) (const_int 8))
+
+ (eq_attr "type" "call_no_delay_slot") (const_int 8)
+ ]
+
+ (const_int 4))
+)
+
+;; The length here is the length of a single asm. Unfortunately it might be
+;; 4 or 8 so we must allow for 8. That's ok though. How often will users
+;; lament asm's not being put in delay slots?
+;;
+(define_asm_attributes
+ [(set_attr "length" "8")
+ (set_attr "type" "multi")
+ (set_attr "cond" "clob") ])
+
+;; Delay slots.
+;; The first two cond clauses and the default are necessary for correctness;
+;; the remaining cond clause is mainly an optimization, as otherwise nops
+;; would be inserted; however, if we didn't do this optimization, we would
+;; have to be more conservative in our length calculations.
+
+(define_attr "in_delay_slot" "false,true"
+ (cond [(eq_attr "type" "uncond_branch,jump,branch,
+ call,sfunc,call_no_delay_slot,
+ brcc, brcc_no_delay_slot,loop_setup,loop_end")
+ (const_string "false")
+ (match_test "arc_write_ext_corereg (insn)")
+ (const_string "false")
+ (gt (symbol_ref "arc_hazard (prev_active_insn (insn),
+ next_active_insn (insn))")
+ (symbol_ref "(arc_hazard (prev_active_insn (insn), insn)
+ + arc_hazard (insn, next_active_insn (insn)))"))
+ (const_string "false")
+ (eq_attr "iscompact" "maybe") (const_string "true")
+ ]
+
+ (if_then_else (eq_attr "length" "2,4")
+ (const_string "true")
+ (const_string "false"))))
+
+; must not put an insn inside that refers to blink.
+(define_attr "in_call_delay_slot" "false,true"
+ (cond [(eq_attr "in_delay_slot" "false")
+ (const_string "false")
+ (match_test "arc_regno_use_in (RETURN_ADDR_REGNUM, PATTERN (insn))")
+ (const_string "false")]
+ (const_string "true")))
+
+(define_attr "in_sfunc_delay_slot" "false,true"
+ (cond [(eq_attr "in_call_delay_slot" "false")
+ (const_string "false")
+ (match_test "arc_regno_use_in (12, PATTERN (insn))")
+ (const_string "false")]
+ (const_string "true")))
+
+;; Instructions that we can put into a delay slot and conditionalize.
+(define_attr "cond_delay_insn" "no,yes"
+ (cond [(eq_attr "cond" "!canuse") (const_string "no")
+ (eq_attr "type" "call,branch,uncond_branch,jump,brcc")
+ (const_string "no")
+ (eq_attr "length" "2,4") (const_string "yes")]
+ (const_string "no")))
+
+(define_attr "in_ret_delay_slot" "no,yes"
+ (cond [(eq_attr "in_delay_slot" "false")
+ (const_string "no")
+ (match_test "regno_clobbered_p
+ (arc_return_address_regs
+ [arc_compute_function_type (cfun)],
+ insn, SImode, 1)")
+ (const_string "no")]
+ (const_string "yes")))
+
+(define_attr "cond_ret_delay_insn" "no,yes"
+ (cond [(eq_attr "in_ret_delay_slot" "no") (const_string "no")
+ (eq_attr "cond_delay_insn" "no") (const_string "no")]
+ (const_string "yes")))
+
+(define_attr "annul_ret_delay_insn" "no,yes"
+ (cond [(eq_attr "cond_ret_delay_insn" "yes") (const_string "yes")
+ (match_test "TARGET_AT_DBR_CONDEXEC") (const_string "no")
+ (eq_attr "type" "!call,branch,uncond_branch,jump,brcc,return,sfunc")
+ (const_string "yes")]
+ (const_string "no")))
+
+
+;; Delay slot definition for ARCompact ISA
+;; ??? FIXME:
+;; When outputting an annul-true insn elegible for cond-exec
+;; in a cbranch delay slot, unless optimizing for size, we use cond-exec
+;; for ARC600; we could also use this for ARC700 if the branch can't be
+;; unaligned and is at least somewhat likely (add parameter for this).
+
+(define_delay (eq_attr "type" "call")
+ [(eq_attr "in_call_delay_slot" "true")
+ (eq_attr "in_call_delay_slot" "true")
+ (nil)])
+
+(define_delay (and (match_test "!TARGET_AT_DBR_CONDEXEC")
+ (eq_attr "type" "brcc"))
+ [(eq_attr "in_delay_slot" "true")
+ (eq_attr "in_delay_slot" "true")
+ (nil)])
+
+(define_delay (and (match_test "TARGET_AT_DBR_CONDEXEC")
+ (eq_attr "type" "brcc"))
+ [(eq_attr "in_delay_slot" "true")
+ (nil)
+ (nil)])
+
+(define_delay
+ (eq_attr "type" "return")
+ [(eq_attr "in_ret_delay_slot" "yes")
+ (eq_attr "annul_ret_delay_insn" "yes")
+ (eq_attr "cond_ret_delay_insn" "yes")])
+
+;; For ARC600, unexposing the delay sloy incurs a penalty also in the
+;; non-taken case, so the only meaningful way to have an annull-true
+;; filled delay slot is to conditionalize the delay slot insn.
+(define_delay (and (match_test "TARGET_AT_DBR_CONDEXEC")
+ (eq_attr "type" "branch,uncond_branch,jump")
+ (match_test "!optimize_size"))
+ [(eq_attr "in_delay_slot" "true")
+ (eq_attr "cond_delay_insn" "yes")
+ (eq_attr "cond_delay_insn" "yes")])
+
+;; For ARC700, anything goes for annulled-true insns, since there is no
+;; penalty for the unexposed delay slot when the branch is not taken,
+;; however, we must avoid things that have a delay slot themselvese to
+;; avoid confusing gcc.
+(define_delay (and (match_test "!TARGET_AT_DBR_CONDEXEC")
+ (eq_attr "type" "branch,uncond_branch,jump")
+ (match_test "!optimize_size"))
+ [(eq_attr "in_delay_slot" "true")
+ (eq_attr "type" "!call,branch,uncond_branch,jump,brcc,return,sfunc")
+ (eq_attr "cond_delay_insn" "yes")])
+
+;; -mlongcall -fpic sfuncs use r12 to load the function address
+(define_delay (eq_attr "type" "sfunc")
+ [(eq_attr "in_sfunc_delay_slot" "true")
+ (eq_attr "in_sfunc_delay_slot" "true")
+ (nil)])
+;; ??? need to use a working strategy for canuse_limm:
+;; - either canuse_limm is not eligible for delay slots, and has no
+;; delay slots, or arc_reorg has to treat them as nocond, or it has to
+;; somehow modify them to become inelegible for delay slots if a decision
+;; is made that makes conditional execution required.
+
+(define_attr "tune" "none,arc600,arc700_4_2_std,arc700_4_2_xmac"
+ (const
+ (cond [(symbol_ref "arc_tune == TUNE_ARC600")
+ (const_string "arc600")
+ (symbol_ref "arc_tune == TUNE_ARC700_4_2_STD")
+ (const_string "arc700_4_2_std")
+ (symbol_ref "arc_tune == TUNE_ARC700_4_2_XMAC")
+ (const_string "arc700_4_2_xmac")]
+ (const_string "none"))))
+
+(define_attr "tune_arc700" "false,true"
+ (if_then_else (eq_attr "tune" "arc700_4_2_std, arc700_4_2_xmac")
+ (const_string "true")
+ (const_string "false")))
+
+;; Move instructions.
+(define_expand "movqi"
+ [(set (match_operand:QI 0 "move_dest_operand" "")
+ (match_operand:QI 1 "general_operand" ""))]
+ ""
+ "if (prepare_move_operands (operands, QImode)) DONE;")
+
+; In order to allow the ccfsm machinery to do its work, the leading compact
+; alternatives say 'canuse' - there is another alternative that will match
+; when the condition codes are used.
+; Rcq won't match if the condition is actually used; to avoid a spurious match
+; via q, q is inactivated as constraint there.
+; Likewise, the length of an alternative that might be shifted to conditional
+; execution must reflect this, lest out-of-range branches are created.
+; The iscompact attribute allows the epilogue expander to know for which
+; insns it should lengthen the return insn.
+(define_insn "*movqi_insn"
+ [(set (match_operand:QI 0 "move_dest_operand" "=Rcq,Rcq#q,w, w,w,???w, w,Rcq,S,!*x,r,m,???m")
+ (match_operand:QI 1 "move_src_operand" "cL,cP,Rcq#q,cL,I,?Rac,?i,T,Rcq,Usd,m,c,?Rac"))]
+ "register_operand (operands[0], QImode)
+ || register_operand (operands[1], QImode)"
+ "@
+ mov%? %0,%1%&
+ mov%? %0,%1%&
+ mov%? %0,%1%&
+ mov%? %0,%1
+ mov%? %0,%1
+ mov%? %0,%1
+ mov%? %0,%S1
+ ldb%? %0,%1%&
+ stb%? %1,%0%&
+ ldb%? %0,%1%&
+ ldb%U1%V1 %0,%1
+ stb%U0%V0 %1,%0
+ stb%U0%V0 %1,%0"
+ [(set_attr "type" "move,move,move,move,move,move,move,load,store,load,load,store,store")
+ (set_attr "iscompact" "maybe,maybe,maybe,false,false,false,false,true,true,true,false,false,false")
+ (set_attr "predicable" "yes,no,yes,yes,no,yes,yes,no,no,no,no,no,no")])
+
+(define_expand "movhi"
+ [(set (match_operand:HI 0 "move_dest_operand" "")
+ (match_operand:HI 1 "general_operand" ""))]
+ ""
+ "if (prepare_move_operands (operands, HImode)) DONE;")
+
+(define_insn "*movhi_insn"
+ [(set (match_operand:HI 0 "move_dest_operand" "=Rcq,Rcq#q,w, w,w,???w,Rcq#q,w,Rcq,S,r,m,???m,VUsc")
+ (match_operand:HI 1 "move_src_operand" "cL,cP,Rcq#q,cL,I,?Rac, ?i,?i,T,Rcq,m,c,?Rac,i"))]
+ "register_operand (operands[0], HImode)
+ || register_operand (operands[1], HImode)
+ || (CONSTANT_P (operands[1])
+ /* Don't use a LIMM that we could load with a single insn - we loose
+ delay-slot filling opportunities. */
+ && !satisfies_constraint_I (operands[1])
+ && satisfies_constraint_Usc (operands[0]))"
+ "@
+ mov%? %0,%1%&
+ mov%? %0,%1%&
+ mov%? %0,%1%&
+ mov%? %0,%1
+ mov%? %0,%1
+ mov%? %0,%1
+ mov%? %0,%S1%&
+ mov%? %0,%S1
+ ldw%? %0,%1%&
+ stw%? %1,%0%&
+ ldw%U1%V1 %0,%1
+ stw%U0%V0 %1,%0
+ stw%U0%V0 %1,%0
+ stw%U0%V0 %S1,%0"
+ [(set_attr "type" "move,move,move,move,move,move,move,move,load,store,load,store,store,store")
+ (set_attr "iscompact" "maybe,maybe,maybe,false,false,false,maybe_limm,false,true,true,false,false,false,false")
+ (set_attr "predicable" "yes,no,yes,yes,no,yes,yes,yes,no,no,no,no,no,no")])
+
+(define_expand "movsi"
+ [(set (match_operand:SI 0 "move_dest_operand" "")
+ (match_operand:SI 1 "general_operand" ""))]
+ ""
+ "if (prepare_move_operands (operands, SImode)) DONE;")
+
+; In order to allow the ccfsm machinery to do its work, the leading compact
+; alternatives say 'canuse' - there is another alternative that will match
+; when the condition codes are used.
+; Rcq won't match if the condition is actually used; to avoid a spurious match
+; via q, q is inactivated as constraint there.
+; Likewise, the length of an alternative that might be shifted to conditional
+; execution must reflect this, lest out-of-range branches are created.
+; the iscompact attribute allows the epilogue expander to know for which
+; insns it should lengthen the return insn.
+; N.B. operand 1 of alternative 7 expands into pcl,symbol@gotpc .
+(define_insn "*movsi_insn"
+ [(set (match_operand:SI 0 "move_dest_operand" "=Rcq,Rcq#q,w, w,w, w,???w, ?w, w,Rcq#q, w,Rcq, S,Us<,RcqRck,!*x,r,m,???m,VUsc")
+ (match_operand:SI 1 "move_src_operand" " cL,cP,Rcq#q,cL,I,Crr,?Rac,Cpc,Clb,?Cal,?Cal,T,Rcq,RcqRck,Us>,Usd,m,c,?Rac,C32"))]
+ "register_operand (operands[0], SImode)
+ || register_operand (operands[1], SImode)
+ || (CONSTANT_P (operands[1])
+ /* Don't use a LIMM that we could load with a single insn - we loose
+ delay-slot filling opportunities. */
+ && !satisfies_constraint_I (operands[1])
+ && satisfies_constraint_Usc (operands[0]))"
+ "@
+ mov%? %0,%1%& ;0
+ mov%? %0,%1%& ;1
+ mov%? %0,%1%& ;2
+ mov%? %0,%1 ;3
+ mov%? %0,%1 ;4
+ ror %0,((%1*2+1) & 0x3f) ;5
+ mov%? %0,%1 ;6
+ add %0,%S1 ;7
+ * return arc_get_unalign () ? \"add %0,pcl,%1-.+2\" : \"add %0,pcl,%1-.\";
+ mov%? %0,%S1%& ;9
+ mov%? %0,%S1 ;10
+ ld%? %0,%1%& ;11
+ st%? %1,%0%& ;12
+ * return arc_short_long (insn, \"push%? %1%&\", \"st%U0 %1,%0%&\");
+ * return arc_short_long (insn, \"pop%? %0%&\", \"ld%U1 %0,%1%&\");
+ ld%? %0,%1%& ;15
+ ld%U1%V1 %0,%1 ;16
+ st%U0%V0 %1,%0 ;17
+ st%U0%V0 %1,%0 ;18
+ st%U0%V0 %S1,%0 ;19"
+ [(set_attr "type" "move,move,move,move,move,two_cycle_core,move,binary,binary,move,move,load,store,store,load,load,load,store,store,store")
+ (set_attr "iscompact" "maybe,maybe,maybe,false,false,false,false,false,false,maybe_limm,false,true,true,true,true,true,false,false,false,false")
+ ; Use default length for iscompact to allow for COND_EXEC. But set length
+ ; of Crr to 4.
+ (set_attr "length" "*,*,*,4,4,4,4,8,8,*,8,*,*,*,*,*,*,*,*,8")
+ (set_attr "predicable" "yes,no,yes,yes,no,no,yes,no,no,yes,yes,no,no,no,no,no,no,no,no,no")])
+
+;; Sometimes generated by the epilogue code. We don't want to
+;; recognize these addresses in general, because the limm is costly,
+;; and we can't use them for stores. */
+(define_insn "*movsi_pre_mod"
+ [(set (match_operand:SI 0 "register_operand" "=w")
+ (mem:SI (pre_modify
+ (reg:SI SP_REG)
+ (plus:SI (reg:SI SP_REG)
+ (match_operand 1 "immediate_operand" "Cal")))))]
+ "reload_completed"
+ "ld.a %0,[sp,%1]"
+ [(set_attr "type" "load")
+ (set_attr "length" "8")])
+
+;; Store a value to directly to memory. The location might also be cached.
+;; Since the cached copy can cause a write-back at unpredictable times,
+;; we first write cached, then we write uncached.
+(define_insn "store_direct"
+ [(set (match_operand:SI 0 "move_dest_operand" "=m")
+ (unspec:SI [(match_operand:SI 1 "register_operand" "c")]
+ UNSPEC_DIRECT))]
+ ""
+ "st%U0 %1,%0\;st%U0.di %1,%0"
+ [(set_attr "type" "store")])
+
+(define_insn_and_split "*movsi_set_cc_insn"
+ [(set (match_operand:CC_ZN 2 "cc_set_register" "")
+ (match_operator 3 "zn_compare_operator"
+ [(match_operand:SI 1 "nonmemory_operand" "cI,cL,Cal") (const_int 0)]))
+ (set (match_operand:SI 0 "register_operand" "=w,w,w")
+ (match_dup 1))]
+ ""
+ "mov%?.f %0,%S1"
+ ; splitting to 'tst' allows short insns and combination into brcc.
+ "reload_completed && operands_match_p (operands[0], operands[1])"
+ [(set (match_dup 2) (match_dup 3))]
+ ""
+ [(set_attr "type" "compare")
+ (set_attr "predicable" "no,yes,yes")
+ (set_attr "cond" "set_zn")
+ (set_attr "length" "4,4,8")])
+
+(define_insn "unary_comparison"
+ [(set (match_operand:CC_ZN 0 "cc_set_register" "")
+ (match_operator 3 "zn_compare_operator"
+ [(match_operator:SI 2 "unary_operator"
+ [(match_operand:SI 1 "register_operand" "c")])
+ (const_int 0)]))]
+ ""
+ "%O2.f 0,%1"
+ [(set_attr "type" "compare")
+ (set_attr "cond" "set_zn")])
+
+
+; this pattern is needed by combiner for cases like if (c=(~b)) { ... }
+(define_insn "*unary_comparison_result_used"
+ [(set (match_operand 2 "cc_register" "")
+ (match_operator 4 "zn_compare_operator"
+ [(match_operator:SI 3 "unary_operator"
+ [(match_operand:SI 1 "register_operand" "c")])
+ (const_int 0)]))
+ (set (match_operand:SI 0 "register_operand" "=w")
+ (match_dup 3))]
+ ""
+ "%O3.f %0,%1"
+ [(set_attr "type" "compare")
+ (set_attr "cond" "set_zn")
+ (set_attr "length" "4")])
+
+(define_insn "*tst"
+ [(set
+ (match_operand 0 "cc_register" "")
+ (match_operator 3 "zn_compare_operator"
+ [(and:SI
+ (match_operand:SI 1 "register_operand"
+ "%Rcq,Rcq, c, c, c, c, c, c")
+ (match_operand:SI 2 "nonmemory_operand"
+ " Rcq,C0p,cI,cL,C1p,Ccp,CnL,Cal"))
+ (const_int 0)]))]
+ "(register_operand (operands[1], SImode)
+ && nonmemory_operand (operands[2], SImode))
+ || (memory_operand (operands[1], SImode)
+ && satisfies_constraint_Cux (operands[2]))"
+ "*
+ switch (which_alternative)
+ {
+ case 0: case 2: case 3: case 7:
+ return \"tst%? %1,%2\";
+ case 1:
+ return \"btst%? %1,%z2\";
+ case 4:
+ return \"bmsk%?.f 0,%1,%Z2%&\";
+ case 5:
+ return \"bclr%?.f 0,%1,%M2%&\";
+ case 6:
+ return \"bic%?.f 0,%1,%n2-1\";
+ default:
+ gcc_unreachable ();
+ }
+ "
+ [(set_attr "iscompact" "maybe,maybe,false,false,false,false,false,false")
+ (set_attr "type" "compare")
+ (set_attr "length" "*,*,4,4,4,4,4,8")
+ (set_attr "predicable" "no,yes,no,yes,no,no,no,yes")
+ (set_attr "cond" "set_zn")])
+
+(define_insn "*commutative_binary_comparison"
+ [(set (match_operand:CC_ZN 0 "cc_set_register" "")
+ (match_operator 5 "zn_compare_operator"
+ [(match_operator:SI 4 "commutative_operator"
+ [(match_operand:SI 1 "register_operand" "%c,c,c")
+ (match_operand:SI 2 "nonmemory_operand" "cL,I,?Cal")])
+ (const_int 0)]))
+ (clobber (match_scratch:SI 3 "=X,1,X"))]
+ ""
+ "%O4.f 0,%1,%2"
+ [(set_attr "type" "compare")
+ (set_attr "cond" "set_zn")
+ (set_attr "length" "4,4,8")])
+
+; for flag setting 'add' instructions like if (a+b) { ...}
+; the combiner needs this pattern
+(define_insn "*addsi_compare"
+ [(set (reg:CC_ZN CC_REG)
+ (compare:CC_ZN (match_operand:SI 0 "register_operand" "c")
+ (neg:SI (match_operand:SI 1 "register_operand" "c"))))]
+ ""
+ "add.f 0,%0,%1"
+ [(set_attr "cond" "set")
+ (set_attr "type" "compare")
+ (set_attr "length" "4")])
+
+; for flag setting 'add' instructions like if (a+b < a) { ...}
+; the combiner needs this pattern
+(define_insn "addsi_compare_2"
+ [(set (reg:CC_C CC_REG)
+ (compare:CC_C (plus:SI (match_operand:SI 0 "register_operand" "c,c")
+ (match_operand:SI 1 "nonmemory_operand" "cL,Cal"))
+ (match_dup 0)))]
+ ""
+ "add.f 0,%0,%1"
+ [(set_attr "cond" "set")
+ (set_attr "type" "compare")
+ (set_attr "length" "4,8")])
+
+(define_insn "*addsi_compare_3"
+ [(set (reg:CC_C CC_REG)
+ (compare:CC_C (plus:SI (match_operand:SI 0 "register_operand" "c")
+ (match_operand:SI 1 "register_operand" "c"))
+ (match_dup 1)))]
+ ""
+ "add.f 0,%0,%1"
+ [(set_attr "cond" "set")
+ (set_attr "type" "compare")
+ (set_attr "length" "4")])
+
+; this pattern is needed by combiner for cases like if (c=a+b) { ... }
+(define_insn "*commutative_binary_comparison_result_used"
+ [(set (match_operand 3 "cc_register" "")
+ (match_operator 5 "zn_compare_operator"
+ ; We can accept any commutative operator except mult because
+ ; our 'w' class below could try to use LP_COUNT.
+ [(match_operator:SI 4 "commutative_operator_sans_mult"
+ [(match_operand:SI 1 "register_operand" "c,0,c")
+ (match_operand:SI 2 "nonmemory_operand" "cL,I,?Cal")])
+ (const_int 0)]))
+ (set (match_operand:SI 0 "register_operand" "=w,w,w")
+ (match_dup 4))]
+ ""
+ "%O4.f %0,%1,%2 ; non-mult commutative"
+ [(set_attr "type" "compare,compare,compare")
+ (set_attr "cond" "set_zn,set_zn,set_zn")
+ (set_attr "length" "4,4,8")])
+
+; a MULT-specific version of this pattern to avoid touching the
+; LP_COUNT register
+(define_insn "*commutative_binary_mult_comparison_result_used"
+ [(set (match_operand 3 "cc_register" "")
+ (match_operator 5 "zn_compare_operator"
+ [(match_operator:SI 4 "mult_operator"
+ [(match_operand:SI 1 "register_operand" "c,0,c")
+ (match_operand:SI 2 "nonmemory_operand" "cL,I,?Cal")])
+ (const_int 0)]))
+ ; Make sure to use the W class to not touch LP_COUNT.
+ (set (match_operand:SI 0 "register_operand" "=W,W,W")
+ (match_dup 4))]
+ "TARGET_ARC700"
+ "%O4.f %0,%1,%2 ; mult commutative"
+ [(set_attr "type" "compare,compare,compare")
+ (set_attr "cond" "set_zn,set_zn,set_zn")
+ (set_attr "length" "4,4,8")])
+
+; this pattern is needed by combiner for cases like if (c=a<<b) { ... }
+(define_insn "*noncommutative_binary_comparison_result_used"
+ [(set (match_operand 3 "cc_register" "")
+ (match_operator 5 "zn_compare_operator"
+ [(match_operator:SI 4 "noncommutative_operator"
+ [(match_operand:SI 1 "register_operand" "c,0,c")
+ (match_operand:SI 2 "nonmemory_operand" "cL,I,?Cal")])
+ (const_int 0)]))
+ (set (match_operand:SI 0 "register_operand" "=w,w,w")
+ (match_dup 4 ))]
+ "TARGET_BARREL_SHIFTER || GET_CODE (operands[4]) == MINUS"
+ "%O4.f %0,%1,%2"
+ [(set_attr "type" "compare,compare,compare")
+ (set_attr "cond" "set_zn,set_zn,set_zn")
+ (set_attr "length" "4,4,8")])
+
+(define_insn "*noncommutative_binary_comparison"
+ [(set (match_operand:CC_ZN 0 "cc_set_register" "")
+ (match_operator 5 "zn_compare_operator"
+ [(match_operator:SI 4 "noncommutative_operator"
+ [(match_operand:SI 1 "register_operand" "c,c,c")
+ (match_operand:SI 2 "nonmemory_operand" "cL,I,?Cal")])
+ (const_int 0)]))
+ (clobber (match_scratch:SI 3 "=X,1,X"))]
+ "TARGET_BARREL_SHIFTER || GET_CODE (operands[4]) == MINUS"
+ "%O4.f 0,%1,%2"
+ [(set_attr "type" "compare")
+ (set_attr "cond" "set_zn")
+ (set_attr "length" "4,4,8")])
+
+(define_expand "bic_f_zn"
+ [(parallel
+ [(set (reg:CC_ZN CC_REG)
+ (compare:CC_ZN
+ (and:SI (match_operand:SI 1 "register_operand" "")
+ (not:SI (match_operand:SI 2 "nonmemory_operand" "")))
+ (const_int 0)))
+ (set (match_operand:SI 0 "register_operand" "")
+ (and:SI (match_dup 1) (not:SI (match_dup 2))))])]
+ "")
+
+(define_insn "*bic_f"
+ [(set (match_operand 3 "cc_register" "=Rcc,Rcc,Rcc")
+ (match_operator 4 "zn_compare_operator"
+ [(and:SI (match_operand:SI 1 "register_operand" "c,0,c")
+ (not:SI
+ (match_operand:SI 2 "nonmemory_operand" "cL,I,?Cal")))
+ (const_int 0)]))
+ (set (match_operand:SI 0 "register_operand" "=w,w,w")
+ (and:SI (match_dup 1) (not:SI (match_dup 2))))]
+ ""
+ "bic.f %0,%1,%2"
+ [(set_attr "type" "compare,compare,compare")
+ (set_attr "cond" "set_zn,set_zn,set_zn")
+ (set_attr "length" "4,4,8")])
+
+(define_expand "movdi"
+ [(set (match_operand:DI 0 "move_dest_operand" "")
+ (match_operand:DI 1 "general_operand" ""))]
+ ""
+ "
+{
+ /* Everything except mem = const or mem = mem can be done easily. */
+
+ if (GET_CODE (operands[0]) == MEM)
+ operands[1] = force_reg (DImode, operands[1]);
+}")
+
+(define_insn_and_split "*movdi_insn"
+ [(set (match_operand:DI 0 "move_dest_operand" "=w,w,r,m")
+ (match_operand:DI 1 "move_double_src_operand" "c,Hi,m,c"))]
+ "register_operand (operands[0], DImode)
+ || register_operand (operands[1], DImode)"
+ "*
+{
+ switch (which_alternative)
+ {
+ default:
+ case 0 :
+ /* We normally copy the low-numbered register first. However, if
+ the first register operand 0 is the same as the second register of
+ operand 1, we must copy in the opposite order. */
+ if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
+ return \"mov%? %R0,%R1\;mov%? %0,%1\";
+ else
+ return \"mov%? %0,%1\;mov%? %R0,%R1\";
+ case 1 :
+ return \"mov%? %L0,%L1\;mov%? %H0,%H1\";
+ case 2 :
+ /* If the low-address word is used in the address, we must load it
+ last. Otherwise, load it first. Note that we cannot have
+ auto-increment in that case since the address register is known to be
+ dead. */
+ if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
+ operands [1], 0))
+ return \"ld%V1 %R0,%R1\;ld%V1 %0,%1\";
+ else switch (GET_CODE (XEXP(operands[1], 0)))
+ {
+ case POST_MODIFY: case POST_INC: case POST_DEC:
+ return \"ld%V1 %R0,%R1\;ld%U1%V1 %0,%1\";
+ case PRE_MODIFY: case PRE_INC: case PRE_DEC:
+ return \"ld%U1%V1 %0,%1\;ld%V1 %R0,%R1\";
+ default:
+ return \"ld%U1%V1 %0,%1\;ld%U1%V1 %R0,%R1\";
+ }
+ case 3 :
+ switch (GET_CODE (XEXP(operands[0], 0)))
+ {
+ case POST_MODIFY: case POST_INC: case POST_DEC:
+ return \"st%V0 %R1,%R0\;st%U0%V0 %1,%0\";
+ case PRE_MODIFY: case PRE_INC: case PRE_DEC:
+ return \"st%U0%V0 %1,%0\;st%V0 %R1,%R0\";
+ default:
+ return \"st%U0%V0 %1,%0\;st%U0%V0 %R1,%R0\";
+ }
+ }
+}"
+ "&& reload_completed && optimize"
+ [(set (match_dup 2) (match_dup 3)) (set (match_dup 4) (match_dup 5))]
+ "arc_split_move (operands);"
+ [(set_attr "type" "move,move,load,store")
+ ;; ??? The ld/st values could be 4 if it's [reg,bignum].
+ (set_attr "length" "8,16,16,16")])
+
+
+;; Floating point move insns.
+
+(define_expand "movsf"
+ [(set (match_operand:SF 0 "general_operand" "")
+ (match_operand:SF 1 "general_operand" ""))]
+ ""
+ "if (prepare_move_operands (operands, SFmode)) DONE;")
+
+(define_insn "*movsf_insn"
+ [(set (match_operand:SF 0 "move_dest_operand" "=w,w,r,m")
+ (match_operand:SF 1 "move_src_operand" "c,E,m,c"))]
+ "register_operand (operands[0], SFmode)
+ || register_operand (operands[1], SFmode)"
+ "@
+ mov%? %0,%1
+ mov%? %0,%1 ; %A1
+ ld%U1%V1 %0,%1
+ st%U0%V0 %1,%0"
+ [(set_attr "type" "move,move,load,store")
+ (set_attr "predicable" "yes,yes,no,no")])
+
+(define_expand "movdf"
+ [(set (match_operand:DF 0 "nonimmediate_operand" "")
+ (match_operand:DF 1 "general_operand" ""))]
+ ""
+ "if (prepare_move_operands (operands, DFmode)) DONE;")
+
+(define_insn "*movdf_insn"
+ [(set (match_operand:DF 0 "move_dest_operand" "=D,r,c,c,r,m")
+ (match_operand:DF 1 "move_double_src_operand" "r,D,c,E,m,c"))]
+ "register_operand (operands[0], DFmode) || register_operand (operands[1], DFmode)"
+ "#"
+ [(set_attr "type" "move,move,move,move,load,store")
+ (set_attr "predicable" "no,no,yes,yes,no,no")
+ ;; ??? The ld/st values could be 16 if it's [reg,bignum].
+ (set_attr "length" "4,16,8,16,16,16")])
+
+(define_split
+ [(set (match_operand:DF 0 "move_dest_operand" "")
+ (match_operand:DF 1 "move_double_src_operand" ""))]
+ "reload_completed"
+ [(match_dup 2)]
+ "operands[2] = arc_split_move (operands);")
+
+(define_insn_and_split "*movdf_insn_nolrsr"
+ [(set (match_operand:DF 0 "register_operand" "=r")
+ (match_operand:DF 1 "arc_double_register_operand" "D"))
+ (use (match_operand:SI 2 "" "N")) ; aka const1_rtx
+ ]
+ "TARGET_DPFP && TARGET_DPFP_DISABLE_LRSR"
+ "#"
+ "&& 1"
+ [
+ ; mov r0, 0
+ (set (match_dup 0) (match_dup 3))
+
+ ; daddh?? r1, r0, r0
+ (parallel [
+ (set (match_dup 1) (plus:DF (match_dup 1) (match_dup 0)))
+ (use (const_int 1))
+ (use (const_int 1))
+ (use (match_dup 0)) ; used to block can_combine_p
+ (set (match_dup 0) (plus:DF (match_dup 1) (match_dup 0))) ; r1 in op 0
+ ])
+
+ ; We have to do this twice, once to read the value into R0 and
+ ; second time to put back the contents which the first DEXCLx
+ ; will have overwritten
+ ; dexcl2 r0, r1, r0
+ (set (match_dup 4) ; aka r0result
+ ; aka DF, r1, r0
+ (unspec_volatile:SI [(match_dup 1) (match_dup 5) (match_dup 4)] VUNSPEC_DEXCL ))
+ ; Generate the second, which makes sure operand5 and operand4 values
+ ; are put back in the Dx register properly.
+ (unspec_volatile:SI [(match_dup 1) (match_dup 5) (match_dup 4)] VUNSPEC_DEXCL_NORES )
+
+ ; Note: we cannot use a (clobber (match_scratch)) here because
+ ; the combine pass will end up replacing uses of it with 0
+ ]
+ "operands[3] = CONST0_RTX (DFmode);
+ operands[4] = simplify_gen_subreg (SImode, operands[0], DFmode, 0);
+ operands[5] = simplify_gen_subreg (SImode, operands[0], DFmode, 4);"
+ [(set_attr "type" "move")])
+
+;; Load/Store with update instructions.
+;;
+;; Some of these we can get by using pre-decrement or pre-increment, but the
+;; hardware can also do cases where the increment is not the size of the
+;; object.
+;;
+;; In all these cases, we use operands 0 and 1 for the register being
+;; incremented because those are the operands that local-alloc will
+;; tie and these are the pair most likely to be tieable (and the ones
+;; that will benefit the most).
+;;
+;; We use match_operator here because we need to know whether the memory
+;; object is volatile or not.
+
+
+;; Note: loadqi_update has no 16-bit variant
+(define_insn "*loadqi_update"
+ [(set (match_operand:QI 3 "dest_reg_operand" "=r,r")
+ (match_operator:QI 4 "load_update_operand"
+ [(match_operand:SI 1 "register_operand" "0,0")
+ (match_operand:SI 2 "nonmemory_operand" "rI,Cal")]))
+ (set (match_operand:SI 0 "dest_reg_operand" "=r,r")
+ (plus:SI (match_dup 1) (match_dup 2)))]
+ ""
+ "ldb.a%V4 %3,[%0,%S2]"
+ [(set_attr "type" "load,load")
+ (set_attr "length" "4,8")])
+
+(define_insn "*load_zeroextendqisi_update"
+ [(set (match_operand:SI 3 "dest_reg_operand" "=r,r")
+ (zero_extend:SI (match_operator:QI 4 "load_update_operand"
+ [(match_operand:SI 1 "register_operand" "0,0")
+ (match_operand:SI 2 "nonmemory_operand" "rI,Cal")])))
+ (set (match_operand:SI 0 "dest_reg_operand" "=r,r")
+ (plus:SI (match_dup 1) (match_dup 2)))]
+ ""
+ "ldb.a%V4 %3,[%0,%S2]"
+ [(set_attr "type" "load,load")
+ (set_attr "length" "4,8")])
+
+(define_insn "*load_signextendqisi_update"
+ [(set (match_operand:SI 3 "dest_reg_operand" "=r,r")
+ (sign_extend:SI (match_operator:QI 4 "load_update_operand"
+ [(match_operand:SI 1 "register_operand" "0,0")
+ (match_operand:SI 2 "nonmemory_operand" "rI,Cal")])))
+ (set (match_operand:SI 0 "dest_reg_operand" "=r,r")
+ (plus:SI (match_dup 1) (match_dup 2)))]
+ ""
+ "ldb.x.a%V4 %3,[%0,%S2]"
+ [(set_attr "type" "load,load")
+ (set_attr "length" "4,8")])
+
+(define_insn "*storeqi_update"
+ [(set (match_operator:QI 4 "store_update_operand"
+ [(match_operand:SI 1 "register_operand" "0")
+ (match_operand:SI 2 "short_immediate_operand" "I")])
+ (match_operand:QI 3 "register_operand" "c"))
+ (set (match_operand:SI 0 "dest_reg_operand" "=w")
+ (plus:SI (match_dup 1) (match_dup 2)))]
+ ""
+ "stb.a%V4 %3,[%0,%2]"
+ [(set_attr "type" "store")
+ (set_attr "length" "4")])
+
+;; ??? pattern may have to be re-written
+;; Note: no 16-bit variant for this pattern
+(define_insn "*loadhi_update"
+ [(set (match_operand:HI 3 "dest_reg_operand" "=r,r")
+ (match_operator:HI 4 "load_update_operand"
+ [(match_operand:SI 1 "register_operand" "0,0")
+ (match_operand:SI 2 "nonmemory_operand" "rI,Cal")]))
+ (set (match_operand:SI 0 "dest_reg_operand" "=w,w")
+ (plus:SI (match_dup 1) (match_dup 2)))]
+ ""
+ "ldw.a%V4 %3,[%0,%S2]"
+ [(set_attr "type" "load,load")
+ (set_attr "length" "4,8")])
+
+(define_insn "*load_zeroextendhisi_update"
+ [(set (match_operand:SI 3 "dest_reg_operand" "=r,r")
+ (zero_extend:SI (match_operator:HI 4 "load_update_operand"
+ [(match_operand:SI 1 "register_operand" "0,0")
+ (match_operand:SI 2 "nonmemory_operand" "rI,Cal")])))
+ (set (match_operand:SI 0 "dest_reg_operand" "=r,r")
+ (plus:SI (match_dup 1) (match_dup 2)))]
+ ""
+ "ldw.a%V4 %3,[%0,%S2]"
+ [(set_attr "type" "load,load")
+ (set_attr "length" "4,8")])
+
+;; Note: no 16-bit variant for this instruction
+(define_insn "*load_signextendhisi_update"
+ [(set (match_operand:SI 3 "dest_reg_operand" "=r,r")
+ (sign_extend:SI (match_operator:HI 4 "load_update_operand"
+ [(match_operand:SI 1 "register_operand" "0,0")
+ (match_operand:SI 2 "nonmemory_operand" "rI,Cal")])))
+ (set (match_operand:SI 0 "dest_reg_operand" "=w,w")
+ (plus:SI (match_dup 1) (match_dup 2)))]
+ ""
+ "ldw.x.a%V4 %3,[%0,%S2]"
+ [(set_attr "type" "load,load")
+ (set_attr "length" "4,8")])
+
+(define_insn "*storehi_update"
+ [(set (match_operator:HI 4 "store_update_operand"
+ [(match_operand:SI 1 "register_operand" "0")
+ (match_operand:SI 2 "short_immediate_operand" "I")])
+ (match_operand:HI 3 "register_operand" "c"))
+ (set (match_operand:SI 0 "dest_reg_operand" "=w")
+ (plus:SI (match_dup 1) (match_dup 2)))]
+ ""
+ "stw.a%V4 %3,[%0,%2]"
+ [(set_attr "type" "store")
+ (set_attr "length" "4")])
+
+;; No 16-bit variant for this instruction pattern
+(define_insn "*loadsi_update"
+ [(set (match_operand:SI 3 "dest_reg_operand" "=r,r")
+ (match_operator:SI 4 "load_update_operand"
+ [(match_operand:SI 1 "register_operand" "0,0")
+ (match_operand:SI 2 "nonmemory_operand" "rI,Cal")]))
+ (set (match_operand:SI 0 "dest_reg_operand" "=w,w")
+ (plus:SI (match_dup 1) (match_dup 2)))]
+ ""
+ "ld.a%V4 %3,[%0,%S2]"
+ [(set_attr "type" "load,load")
+ (set_attr "length" "4,8")])
+
+(define_insn "*storesi_update"
+ [(set (match_operator:SI 4 "store_update_operand"
+ [(match_operand:SI 1 "register_operand" "0")
+ (match_operand:SI 2 "short_immediate_operand" "I")])
+ (match_operand:SI 3 "register_operand" "c"))
+ (set (match_operand:SI 0 "dest_reg_operand" "=w")
+ (plus:SI (match_dup 1) (match_dup 2)))]
+ ""
+ "st.a%V4 %3,[%0,%2]"
+ [(set_attr "type" "store")
+ (set_attr "length" "4")])
+
+(define_insn "*loadsf_update"
+ [(set (match_operand:SF 3 "dest_reg_operand" "=r,r")
+ (match_operator:SF 4 "load_update_operand"
+ [(match_operand:SI 1 "register_operand" "0,0")
+ (match_operand:SI 2 "nonmemory_operand" "rI,Cal")]))
+ (set (match_operand:SI 0 "dest_reg_operand" "=w,w")
+ (plus:SI (match_dup 1) (match_dup 2)))]
+ ""
+ "ld.a%V4 %3,[%0,%S2]"
+ [(set_attr "type" "load,load")
+ (set_attr "length" "4,8")])
+
+(define_insn "*storesf_update"
+ [(set (match_operator:SF 4 "store_update_operand"
+ [(match_operand:SI 1 "register_operand" "0")
+ (match_operand:SI 2 "short_immediate_operand" "I")])
+ (match_operand:SF 3 "register_operand" "c"))
+ (set (match_operand:SI 0 "dest_reg_operand" "=w")
+ (plus:SI (match_dup 1) (match_dup 2)))]
+ ""
+ "st.a%V4 %3,[%0,%2]"
+ [(set_attr "type" "store")
+ (set_attr "length" "4")])
+
+;; Conditional move instructions.
+
+(define_expand "movsicc"
+ [(set (match_operand:SI 0 "dest_reg_operand" "")
+ (if_then_else:SI (match_operand 1 "comparison_operator" "")
+ (match_operand:SI 2 "nonmemory_operand" "")
+ (match_operand:SI 3 "register_operand" "")))]
+ ""
+ "operands[1] = gen_compare_reg (operands[1], VOIDmode);")
+
+
+(define_expand "movdicc"
+ [(set (match_operand:DI 0 "dest_reg_operand" "")
+ (if_then_else:DI(match_operand 1 "comparison_operator" "")
+ (match_operand:DI 2 "nonmemory_operand" "")
+ (match_operand:DI 3 "register_operand" "")))]
+ ""
+ "operands[1] = gen_compare_reg (operands[1], VOIDmode);")
+
+
+(define_expand "movsfcc"
+ [(set (match_operand:SF 0 "dest_reg_operand" "")
+ (if_then_else:SF (match_operand 1 "comparison_operator" "")
+ (match_operand:SF 2 "nonmemory_operand" "")
+ (match_operand:SF 3 "register_operand" "")))]
+ ""
+ "operands[1] = gen_compare_reg (operands[1], VOIDmode);")
+
+(define_expand "movdfcc"
+ [(set (match_operand:DF 0 "dest_reg_operand" "")
+ (if_then_else:DF (match_operand 1 "comparison_operator" "")
+ (match_operand:DF 2 "nonmemory_operand" "")
+ (match_operand:DF 3 "register_operand" "")))]
+ ""
+ "operands[1] = gen_compare_reg (operands[1], VOIDmode);")
+
+(define_insn "*movsicc_insn"
+ [(set (match_operand:SI 0 "dest_reg_operand" "=w,w")
+ (if_then_else:SI (match_operator 3 "proper_comparison_operator"
+ [(match_operand 4 "cc_register" "") (const_int 0)])
+ (match_operand:SI 1 "nonmemory_operand" "cL,Cal")
+ (match_operand:SI 2 "register_operand" "0,0")))]
+ ""
+{
+ if (rtx_equal_p (operands[1], const0_rtx) && GET_CODE (operands[3]) == NE
+ && satisfies_constraint_Rcq (operands[0]))
+ return "sub%?.ne %0,%0,%0";
+ /* ??? might be good for speed on ARC600 too, *if* properly scheduled. */
+ if ((TARGET_ARC700 || optimize_size)
+ && rtx_equal_p (operands[1], constm1_rtx)
+ && GET_CODE (operands[3]) == LTU)
+ return "sbc.cs %0,%0,%0";
+ return "mov.%d3 %0,%S1";
+}
+ [(set_attr "type" "cmove,cmove")
+ (set_attr "length" "4,8")])
+
+; Try to generate more short moves, and/or less limms, by substituting a
+; conditional move with a conditional sub.
+(define_peephole2
+ [(set (match_operand:SI 0 "compact_register_operand")
+ (match_operand:SI 1 "const_int_operand"))
+ (set (match_dup 0)
+ (if_then_else:SI (match_operator 3 "proper_comparison_operator"
+ [(match_operand 4 "cc_register" "") (const_int 0)])
+ (match_operand:SI 2 "const_int_operand" "")
+ (match_dup 0)))]
+ "!satisfies_constraint_P (operands[1])
+ && satisfies_constraint_P (operands[2])
+ && UNSIGNED_INT6 (INTVAL (operands[2]) - INTVAL (operands[1]))"
+ [(set (match_dup 0) (match_dup 2))
+ (cond_exec
+ (match_dup 3)
+ (set (match_dup 0)
+ (plus:SI (match_dup 0) (match_dup 1))))]
+ "operands[3] = gen_rtx_fmt_ee (REVERSE_CONDITION (GET_CODE (operands[3]),
+ GET_MODE (operands[4])),
+ VOIDmode, operands[4], const0_rtx);
+ operands[1] = GEN_INT (INTVAL (operands[1]) - INTVAL (operands[2]));")
+
+(define_insn "*movdicc_insn"
+ [(set (match_operand:DI 0 "dest_reg_operand" "=&w,w")
+ (if_then_else:DI (match_operator 3 "proper_comparison_operator"
+ [(match_operand 4 "cc_register" "") (const_int 0)])
+ (match_operand:DI 1 "nonmemory_operand" "c,i")
+ (match_operand:DI 2 "register_operand" "0,0")))]
+ ""
+ "*
+{
+ switch (which_alternative)
+ {
+ default:
+ case 0 :
+ /* We normally copy the low-numbered register first. However, if
+ the first register operand 0 is the same as the second register of
+ operand 1, we must copy in the opposite order. */
+ if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
+ return \"mov.%d3 %R0,%R1\;mov.%d3 %0,%1\";
+ else
+ return \"mov.%d3 %0,%1\;mov.%d3 %R0,%R1\";
+ case 1 :
+ return \"mov.%d3 %L0,%L1\;mov.%d3 %H0,%H1\";
+
+
+ }
+}"
+ [(set_attr "type" "cmove,cmove")
+ (set_attr "length" "8,16")])
+
+
+(define_insn "*movsfcc_insn"
+ [(set (match_operand:SF 0 "dest_reg_operand" "=w,w")
+ (if_then_else:SF (match_operator 3 "proper_comparison_operator"
+ [(match_operand 4 "cc_register" "") (const_int 0)])
+ (match_operand:SF 1 "nonmemory_operand" "c,E")
+ (match_operand:SF 2 "register_operand" "0,0")))]
+ ""
+ "@
+ mov.%d3 %0,%1
+ mov.%d3 %0,%1 ; %A1"
+ [(set_attr "type" "cmove,cmove")])
+
+(define_insn "*movdfcc_insn"
+ [(set (match_operand:DF 0 "dest_reg_operand" "=w,w")
+ (if_then_else:DF (match_operator 1 "proper_comparison_operator"
+ [(match_operand 4 "cc_register" "") (const_int 0)])
+ (match_operand:DF 2 "nonmemory_operand" "c,E")
+ (match_operand:DF 3 "register_operand" "0,0")))]
+ ""
+ "*
+{
+ switch (which_alternative)
+ {
+ default:
+ case 0 :
+ /* We normally copy the low-numbered register first. However, if
+ the first register operand 0 is the same as the second register of
+ operand 1, we must copy in the opposite order. */
+ if (REGNO (operands[0]) == REGNO (operands[2]) + 1)
+ return \"mov.%d1 %R0,%R2\;mov.%d1 %0,%2\";
+ else
+ return \"mov.%d1 %0,%2\;mov.%d1 %R0,%R2\";
+ case 1 :
+ return \"mov.%d1 %L0,%L2\;mov.%d1 %H0,%H2; %A2 \";
+
+ }
+}"
+ [(set_attr "type" "cmove,cmove")
+ (set_attr "length" "8,16")])
+
+
+(define_insn "*zero_extendqihi2_i"
+ [(set (match_operand:HI 0 "dest_reg_operand" "=Rcq,Rcq#q,Rcw,w,r")
+ (zero_extend:HI (match_operand:QI 1 "nonvol_nonimm_operand" "0,Rcq#q,0,c,m")))]
+ ""
+ "@
+ extb%? %0,%1%&
+ extb%? %0,%1%&
+ bmsk%? %0,%1,7
+ extb %0,%1
+ ldb%U1 %0,%1"
+ [(set_attr "type" "unary,unary,unary,unary,load")
+ (set_attr "iscompact" "maybe,true,false,false,false")
+ (set_attr "predicable" "no,no,yes,no,no")])
+
+(define_expand "zero_extendqihi2"
+ [(set (match_operand:HI 0 "dest_reg_operand" "")
+ (zero_extend:HI (match_operand:QI 1 "nonvol_nonimm_operand" "")))]
+ ""
+ "if (prepare_extend_operands (operands, ZERO_EXTEND, HImode)) DONE;"
+)
+
+(define_insn "*zero_extendqisi2_ac"
+ [(set (match_operand:SI 0 "dest_reg_operand" "=Rcq,Rcq#q,Rcw,w,qRcq,!*x,r")
+ (zero_extend:SI (match_operand:QI 1 "nonvol_nonimm_operand" "0,Rcq#q,0,c,T,Usd,m")))]
+ ""
+ "@
+ extb%? %0,%1%&
+ extb%? %0,%1%&
+ bmsk%? %0,%1,7
+ extb %0,%1
+ ldb%? %0,%1%&
+ ldb%? %0,%1%&
+ ldb%U1 %0,%1"
+ [(set_attr "type" "unary,unary,unary,unary,load,load,load")
+ (set_attr "iscompact" "maybe,true,false,false,true,true,false")
+ (set_attr "predicable" "no,no,yes,no,no,no,no")])
+
+(define_expand "zero_extendqisi2"
+ [(set (match_operand:SI 0 "dest_reg_operand" "")
+ (zero_extend:SI (match_operand:QI 1 "nonvol_nonimm_operand" "")))]
+ ""
+ "if (prepare_extend_operands (operands, ZERO_EXTEND, SImode)) DONE;"
+)
+
+(define_insn "*zero_extendhisi2_i"
+ [(set (match_operand:SI 0 "dest_reg_operand" "=Rcq,q,Rcw,w,!x,Rcqq,r")
+ (zero_extend:SI (match_operand:HI 1 "nonvol_nonimm_operand" "0,q,0,c,Usd,Usd,m")))]
+ ""
+ "@
+ extw%? %0,%1%&
+ extw%? %0,%1%&
+ bmsk%? %0,%1,15
+ extw %0,%1
+ ldw%? %0,%1%&
+ ldw%U1 %0,%1
+ ldw%U1%V1 %0,%1"
+ [(set_attr "type" "unary,unary,unary,unary,load,load,load")
+ (set_attr "iscompact" "maybe,true,false,false,true,false,false")
+ (set_attr "predicable" "no,no,yes,no,no,no,no")])
+
+
+(define_expand "zero_extendhisi2"
+ [(set (match_operand:SI 0 "dest_reg_operand" "")
+ (zero_extend:SI (match_operand:HI 1 "nonvol_nonimm_operand" "")))]
+ ""
+ "if (prepare_extend_operands (operands, ZERO_EXTEND, SImode)) DONE;"
+)
+
+;; Sign extension instructions.
+
+(define_insn "*extendqihi2_i"
+ [(set (match_operand:HI 0 "dest_reg_operand" "=Rcqq,r,r")
+ (sign_extend:HI (match_operand:QI 1 "nonvol_nonimm_operand" "Rcqq,r,m")))]
+ ""
+ "@
+ sexb%? %0,%1%&
+ sexb %0,%1
+ ldb.x%U1 %0,%1"
+ [(set_attr "type" "unary,unary,load")
+ (set_attr "iscompact" "true,false,false")])
+
+
+(define_expand "extendqihi2"
+ [(set (match_operand:HI 0 "dest_reg_operand" "")
+ (sign_extend:HI (match_operand:QI 1 "nonvol_nonimm_operand" "")))]
+ ""
+ "if (prepare_extend_operands (operands, SIGN_EXTEND, HImode)) DONE;"
+)
+
+(define_insn "*extendqisi2_ac"
+ [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,w,r")
+ (sign_extend:SI (match_operand:QI 1 "nonvol_nonimm_operand" "Rcqq,c,m")))]
+ ""
+ "@
+ sexb%? %0,%1%&
+ sexb %0,%1
+ ldb.x%U1 %0,%1"
+ [(set_attr "type" "unary,unary,load")
+ (set_attr "iscompact" "true,false,false")])
+
+(define_expand "extendqisi2"
+ [(set (match_operand:SI 0 "dest_reg_operand" "")
+ (sign_extend:SI (match_operand:QI 1 "nonvol_nonimm_operand" "")))]
+ ""
+ "if (prepare_extend_operands (operands, SIGN_EXTEND, SImode)) DONE;"
+)
+
+(define_insn "*extendhisi2_i"
+ [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,w,r")
+ (sign_extend:SI (match_operand:HI 1 "nonvol_nonimm_operand" "Rcqq,c,m")))]
+ ""
+ "@
+ sexw%? %0,%1%&
+ sexw %0,%1
+ ldw.x%U1%V1 %0,%1"
+ [(set_attr "type" "unary,unary,load")
+ (set_attr "iscompact" "true,false,false")])
+
+(define_expand "extendhisi2"
+ [(set (match_operand:SI 0 "dest_reg_operand" "")
+ (sign_extend:SI (match_operand:HI 1 "nonvol_nonimm_operand" "")))]
+ ""
+ "if (prepare_extend_operands (operands, SIGN_EXTEND, SImode)) DONE;"
+)
+
+;; Unary arithmetic insns
+
+;; We allow constant operands to enable late constant propagation, but it is
+;; not worth while to have more than one dedicated alternative to output them -
+;; if we are really worried about getting these the maximum benefit of all
+;; the available alternatives, we should add an extra pass to fold such
+;; operations to movsi.
+
+;; Absolute instructions
+
+(define_insn "*abssi2_mixed"
+ [(set (match_operand:SI 0 "compact_register_operand" "=q")
+ (abs:SI (match_operand:SI 1 "compact_register_operand" "q")))]
+ "TARGET_MIXED_CODE"
+ "abs%? %0,%1%&"
+ [(set_attr "type" "two_cycle_core")
+ (set_attr "iscompact" "true")])
+
+(define_insn "abssi2"
+ [(set (match_operand:SI 0 "dest_reg_operand" "=Rcq#q,w,w")
+ (abs:SI (match_operand:SI 1 "nonmemory_operand" "Rcq#q,cL,Cal")))]
+ ""
+ "abs%? %0,%1%&"
+ [(set_attr "type" "two_cycle_core")
+ (set_attr "length" "*,4,8")
+ (set_attr "iscompact" "true,false,false")])
+
+;; Maximum and minimum insns
+
+(define_insn "smaxsi3"
+ [(set (match_operand:SI 0 "dest_reg_operand" "=Rcw, w, w")
+ (smax:SI (match_operand:SI 1 "register_operand" "%0, c, c")
+ (match_operand:SI 2 "nonmemory_operand" "cL,cL,Cal")))]
+ ""
+ "max%? %0,%1,%2"
+ [(set_attr "type" "two_cycle_core")
+ (set_attr "length" "4,4,8")
+ (set_attr "predicable" "yes,no,no")]
+)
+
+(define_insn "sminsi3"
+ [(set (match_operand:SI 0 "dest_reg_operand" "=Rcw, w, w")
+ (smin:SI (match_operand:SI 1 "register_operand" "%0, c, c")
+ (match_operand:SI 2 "nonmemory_operand" "cL,cL,Cal")))]
+ ""
+ "min%? %0,%1,%2"
+ [(set_attr "type" "two_cycle_core")
+ (set_attr "length" "4,4,8")
+ (set_attr "predicable" "yes,no,no")]
+)
+
+;; Arithmetic instructions.
+
+; We say an insn can be conditionalized if this doesn't introduce a long
+; immediate. We set the type such that we still have good scheduling if the
+; insn is conditionalized.
+; ??? It would make sense to allow introduction of long immediates, but
+; we'd need to communicate to the ccfsm machinery the extra cost.
+; The alternatives in the constraints still serve three purposes:
+; - estimate insn size assuming conditional execution
+; - guide reload to re-order the second and third operand to get a better fit.
+; - give tentative insn type to guide scheduling
+; N.B. "%" for commutativity doesn't help when there is another matching
+; (but longer) alternative.
+; We avoid letting this pattern use LP_COUNT as a register by specifying
+; register class 'W' instead of 'w'.
+(define_insn_and_split "*addsi3_mixed"
+ ;; 0 1 2 3 4 5 6 7 8 9 a b c d e f 10
+ [(set (match_operand:SI 0 "dest_reg_operand" "=Rcq#q,Rcq,Rcw,Rcw,Rcq,Rcb,Rcq, Rcw, Rcqq,Rcqq, W, W,W, W,Rcqq,Rcw, W")
+ (plus:SI (match_operand:SI 1 "register_operand" "%0, c, 0, c, 0, 0,Rcb, 0, Rcqq, 0, c, c,0, 0, 0, 0, c")
+ (match_operand:SI 2 "nonmemory_operand" "cL, 0, cL, 0,CL2,Csp,CM4,cCca,RcqqK, cO,cLCmL,Cca,I,C2a, Cal,Cal,Cal")))]
+ ""
+{
+ arc_output_addsi (operands, arc_ccfsm_cond_exec_p (), true);
+ return "";
+}
+ "&& reload_completed && get_attr_length (insn) == 8
+ && satisfies_constraint_I (operands[2])
+ && GET_CODE (PATTERN (insn)) != COND_EXEC"
+ [(set (match_dup 0) (match_dup 3)) (set (match_dup 0) (match_dup 4))]
+ "split_addsi (operands);"
+ [(set_attr "type" "*,*,*,*,two_cycle_core,two_cycle_core,*,two_cycle_core,*,*,*,two_cycle_core,*,two_cycle_core,*,*,*")
+ (set (attr "iscompact")
+ (cond [(match_test "~arc_output_addsi (operands, false, false) & 2")
+ (const_string "false")
+ (match_operand 2 "long_immediate_operand" "")
+ (const_string "maybe_limm")]
+ (const_string "maybe")))
+ (set_attr "length" "*,*,4,4,*,*,*,4,*,*,4,4,4,4,*,8,8")
+ (set_attr "predicable" "no,no,yes,yes,no,no,no,yes,no,no,no,no,no,no,no,yes,no")
+ (set_attr "cond" "canuse,canuse,canuse,canuse,canuse,canuse,nocond,canuse,nocond,nocond,nocond,nocond,canuse_limm,canuse_limm,canuse,canuse,nocond")
+])
+
+;; ARC700/ARC600 multiply
+;; SI <- SI * SI
+
+(define_expand "mulsi3"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "")
+ (mult:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "nonmemory_operand" "")))]
+ ""
+{
+ if (TARGET_ARC700 && !TARGET_NOMPY_SET)
+ {
+ if (!register_operand (operands[0], SImode))
+ {
+ rtx result = gen_reg_rtx (SImode);
+
+ emit_insn (gen_mulsi3 (result, operands[1], operands[2]));
+ emit_move_insn (operands[0], result);
+ DONE;
+ }
+ }
+ else if (TARGET_MUL64_SET)
+ {
+ emit_insn (gen_mulsi_600 (operands[1], operands[2],
+ gen_mlo (), gen_mhi ()));
+ emit_move_insn (operands[0], gen_mlo ());
+ DONE;
+ }
+ else if (TARGET_MULMAC_32BY16_SET)
+ {
+ if (immediate_operand (operands[2], SImode)
+ && INTVAL (operands[2]) >= 0
+ && INTVAL (operands[2]) <= 65535)
+ {
+ emit_insn (gen_umul_600 (operands[1], operands[2],
+ gen_acc2 (), gen_acc1 ()));
+ emit_move_insn (operands[0], gen_acc2 ());
+ DONE;
+ }
+ operands[2] = force_reg (SImode, operands[2]);
+ emit_insn (gen_umul_600 (operands[1], operands[2],
+ gen_acc2 (), gen_acc1 ()));
+ emit_insn (gen_mac_600 (operands[1], operands[2],
+ gen_acc2 (), gen_acc1 ()));
+ emit_move_insn (operands[0], gen_acc2 ());
+ DONE;
+ }
+ else
+ {
+ emit_move_insn (gen_rtx_REG (SImode, R0_REG), operands[1]);
+ emit_move_insn (gen_rtx_REG (SImode, R1_REG), operands[2]);
+ emit_insn (gen_mulsi3_600_lib ());
+ emit_move_insn (operands[0], gen_rtx_REG (SImode, R0_REG));
+ DONE;
+ }
+})
+
+; mululw conditional execution without a LIMM clobbers an input register;
+; we'd need a different pattern to describe this.
+; To make the conditional execution valid for the LIMM alternative, we
+; have to emit the LIMM before the register operand.
+(define_insn "umul_600"
+ [(set (match_operand:SI 2 "acc2_operand" "")
+ (mult:SI (match_operand:SI 0 "register_operand" "c,c,c")
+ (zero_extract:SI (match_operand:SI 1 "nonmemory_operand"
+ "c,L,Cal")
+ (const_int 16)
+ (const_int 0))))
+ (clobber (match_operand:SI 3 "acc1_operand" ""))]
+ "TARGET_MULMAC_32BY16_SET"
+ "@mululw 0, %0, %1
+ mululw 0, %0, %1
+ mululw%? 0, %1, %0"
+ [(set_attr "length" "4,4,8")
+ (set_attr "type" "mulmac_600, mulmac_600, mulmac_600")
+ (set_attr "predicable" "no, no, yes")
+ (set_attr "cond" "nocond, canuse_limm, canuse")])
+
+(define_insn "mac_600"
+ [(set (match_operand:SI 2 "acc2_operand" "")
+ (plus:SI
+ (mult:SI (match_operand:SI 0 "register_operand" "c,c,c")
+ (ashift:SI
+ (zero_extract:SI (match_operand:SI 1 "nonmemory_operand" "c,L,Cal")
+ (const_int 16)
+ (const_int 16))
+ (const_int 16)))
+ (match_dup 2)))
+ (clobber (match_operand:SI 3 "acc1_operand" ""))]
+ "TARGET_MULMAC_32BY16_SET"
+ "machlw%? 0, %0, %1"
+ [(set_attr "length" "4,4,8")
+ (set_attr "type" "mulmac_600, mulmac_600, mulmac_600")
+ (set_attr "predicable" "no, no, yes")
+ (set_attr "cond" "nocond, canuse_limm, canuse")])
+
+(define_insn "mulsi_600"
+ [(set (match_operand:SI 2 "mlo_operand" "")
+ (mult:SI (match_operand:SI 0 "register_operand" "Rcq#q,c,c,%c")
+ (match_operand:SI 1 "nonmemory_operand" "Rcq#q,cL,I,Cal")))
+ (clobber (match_operand:SI 3 "mhi_operand" ""))]
+ "TARGET_MUL64_SET"
+; The assembler mis-assembles mul64 / mulu64 with "I" constraint constants,
+; using a machine code pattern that only allows "L" constraint constants.
+; "mul64%? \t0, %0, %1%&"
+{
+ if (satisfies_constraint_I (operands[1])
+ && !satisfies_constraint_L (operands[1]))
+ {
+ /* MUL64 <0,>b,s12 00101bbb10000100 0BBBssssssSSSSSS */
+ int n = true_regnum (operands[0]);
+ int i = INTVAL (operands[1]);
+ asm_fprintf (asm_out_file, "\t.short %d`", 0x2884 + ((n & 7) << 8));
+ asm_fprintf (asm_out_file, "\t.short %d`",
+ ((i & 0x3f) << 6) + ((i >> 6) & 0x3f) + ((n & 070) << 9));
+ return "; mul64%? \t0, %0, %1%&";
+ }
+ return "mul64%? \t0, %0, %1%&";
+}
+ [(set_attr "length" "*,4,4,8")
+ (set_attr "iscompact" "maybe,false,false,false")
+ (set_attr "type" "multi,multi,multi,multi")
+ (set_attr "predicable" "yes,yes,no,yes")
+ (set_attr "cond" "canuse,canuse,canuse_limm,canuse")])
+
+; If we compile without an mul option enabled, but link with libraries
+; for a mul option, we'll see clobbers of multiplier output registers.
+; There is also an implementation using norm that clobbers the loop registers.
+(define_insn "mulsi3_600_lib"
+ [(set (reg:SI R0_REG)
+ (mult:SI (reg:SI R0_REG) (reg:SI R1_REG)))
+ (clobber (reg:SI RETURN_ADDR_REGNUM))
+ (clobber (reg:SI R1_REG))
+ (clobber (reg:SI R2_REG))
+ (clobber (reg:SI R3_REG))
+ (clobber (reg:DI MUL64_OUT_REG))
+ (clobber (reg:SI LP_COUNT))
+ (clobber (reg:SI LP_START))
+ (clobber (reg:SI LP_END))
+ (clobber (reg:CC CC_REG))]
+ "!TARGET_MUL64_SET && !TARGET_MULMAC_32BY16_SET
+ && (!TARGET_ARC700 || TARGET_NOMPY_SET)
+ && SFUNC_CHECK_PREDICABLE"
+ "*return arc_output_libcall (\"__mulsi3\");"
+ [(set_attr "is_sfunc" "yes")
+ (set_attr "predicable" "yes")])
+
+(define_insn "mulsidi_600"
+ [(set (reg:DI MUL64_OUT_REG)
+ (mult:DI (sign_extend:DI
+ (match_operand:SI 0 "register_operand" "Rcq#q,c,c,%c"))
+ (sign_extend:DI
+; assembler issue for "I", see mulsi_600
+; (match_operand:SI 1 "register_operand" "Rcq#q,cL,I,Cal"))))]
+ (match_operand:SI 1 "register_operand" "Rcq#q,cL,L,C32"))))]
+ "TARGET_MUL64_SET"
+ "mul64%? \t0, %0, %1%&"
+ [(set_attr "length" "*,4,4,8")
+ (set_attr "iscompact" "maybe,false,false,false")
+ (set_attr "type" "multi,multi,multi,multi")
+ (set_attr "predicable" "yes,yes,no,yes")
+ (set_attr "cond" "canuse,canuse,canuse_limm,canuse")])
+
+(define_insn "umulsidi_600"
+ [(set (reg:DI MUL64_OUT_REG)
+ (mult:DI (zero_extend:DI
+ (match_operand:SI 0 "register_operand" "c,c,%c"))
+ (sign_extend:DI
+; assembler issue for "I", see mulsi_600
+; (match_operand:SI 1 "register_operand" "cL,I,Cal"))))]
+ (match_operand:SI 1 "register_operand" "cL,L,C32"))))]
+ "TARGET_MUL64_SET"
+ "mulu64%? \t0, %0, %1%&"
+ [(set_attr "length" "4,4,8")
+ (set_attr "iscompact" "false")
+ (set_attr "type" "umulti")
+ (set_attr "predicable" "yes,no,yes")
+ (set_attr "cond" "canuse,canuse_limm,canuse")])
+
+; ARC700 mpy* instructions: This is a multi-cycle extension, and thus 'w'
+; may not be used as destination constraint.
+
+; The result of mpy and mpyu is the same except for flag setting (if enabled),
+; but mpyu is faster for the standard multiplier.
+; Note: we must make sure LP_COUNT is not one of the destination
+; registers, since it cannot be the destination of a multi-cycle insn
+; like MPY or MPYU.
+(define_insn "mulsi3_700"
+ [(set (match_operand:SI 0 "mpy_dest_reg_operand" "=Rcr,r,r,Rcr,r")
+ (mult:SI (match_operand:SI 1 "register_operand" " 0,c,0,0,c")
+ (match_operand:SI 2 "nonmemory_operand" "cL,cL,I,Cal,Cal")))]
+"TARGET_ARC700 && !TARGET_NOMPY_SET"
+ "mpyu%? %0,%1,%2"
+ [(set_attr "length" "4,4,4,8,8")
+ (set_attr "type" "umulti")
+ (set_attr "predicable" "yes,no,no,yes,no")
+ (set_attr "cond" "canuse,nocond,canuse_limm,canuse,nocond")])
+
+(define_expand "mulsidi3"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "")
+ (mult:DI (sign_extend:DI(match_operand:SI 1 "register_operand" ""))
+ (sign_extend:DI(match_operand:SI 2 "nonmemory_operand" ""))))]
+ "(TARGET_ARC700 && !TARGET_NOMPY_SET)
+ || TARGET_MUL64_SET
+ || TARGET_MULMAC_32BY16_SET"
+"
+{
+ if (TARGET_ARC700 && !TARGET_NOMPY_SET)
+ {
+ operands[2] = force_reg (SImode, operands[2]);
+ if (!register_operand (operands[0], DImode))
+ {
+ rtx result = gen_reg_rtx (DImode);
+
+ operands[2] = force_reg (SImode, operands[2]);
+ emit_insn (gen_mulsidi3 (result, operands[1], operands[2]));
+ emit_move_insn (operands[0], result);
+ DONE;
+ }
+ }
+ else if (TARGET_MUL64_SET)
+ {
+ operands[2] = force_reg (SImode, operands[2]);
+ emit_insn (gen_mulsidi_600 (operands[1], operands[2]));
+ emit_move_insn (operands[0], gen_rtx_REG (DImode, MUL64_OUT_REG));
+ DONE;
+ }
+ else if (TARGET_MULMAC_32BY16_SET)
+ {
+ rtx result_hi = gen_highpart(SImode, operands[0]);
+ rtx result_low = gen_lowpart(SImode, operands[0]);
+
+ emit_insn (gen_mul64_600 (operands[1], operands[2]));
+ emit_insn (gen_mac64_600 (result_hi, operands[1], operands[2]));
+ emit_move_insn (result_low, gen_acc2 ());
+ DONE;
+ }
+}")
+
+(define_insn "mul64_600"
+ [(set (reg:DI 56)
+ (mult:DI (sign_extend:DI (match_operand:SI 0 "register_operand"
+ "c,c,c"))
+ (zero_extract:DI (match_operand:SI 1 "nonmemory_operand"
+ "c,L,Cal")
+ (const_int 16)
+ (const_int 0))))
+ ]
+ "TARGET_MULMAC_32BY16_SET"
+ "mullw%? 0, %0, %1"
+ [(set_attr "length" "4,4,8")
+ (set_attr "type" "mulmac_600")
+ (set_attr "predicable" "no,no,yes")
+ (set_attr "cond" "nocond, canuse_limm, canuse")])
+
+
+;; ??? check if this is canonical rtl
+(define_insn "mac64_600"
+ [(set (reg:DI 56)
+ (plus:DI
+ (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "c,c,c"))
+ (ashift:DI
+ (sign_extract:DI (match_operand:SI 2 "nonmemory_operand" "c,L,Cal")
+ (const_int 16) (const_int 16))
+ (const_int 16)))
+ (reg:DI 56)))
+ (set (match_operand:SI 0 "register_operand" "=w,w,w")
+ (zero_extract:SI
+ (plus:DI
+ (mult:DI (sign_extend:DI (match_dup 1))
+ (ashift:DI
+ (sign_extract:DI (match_dup 2)
+ (const_int 16) (const_int 16))
+ (const_int 16)))
+ (reg:DI 56))
+ (const_int 32) (const_int 32)))]
+ "TARGET_MULMAC_32BY16_SET"
+ "machlw%? %0, %1, %2"
+ [(set_attr "length" "4,4,8")
+ (set_attr "type" "mulmac_600")
+ (set_attr "predicable" "no,no,yes")
+ (set_attr "cond" "nocond, canuse_limm, canuse")])
+
+
+;; DI <- DI(signed SI) * DI(signed SI)
+(define_insn_and_split "mulsidi3_700"
+ [(set (match_operand:DI 0 "register_operand" "=&r")
+ (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%c"))
+ (sign_extend:DI (match_operand:SI 2 "register_operand" "cL"))))]
+ "TARGET_ARC700 && !TARGET_NOMPY_SET"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+{
+ int hi = TARGET_BIG_ENDIAN ? 0 : UNITS_PER_WORD;
+ int lo = TARGET_BIG_ENDIAN ? UNITS_PER_WORD : 0;
+ rtx l0 = simplify_gen_subreg (word_mode, operands[0], DImode, lo);
+ rtx h0 = simplify_gen_subreg (word_mode, operands[0], DImode, hi);
+ emit_insn (gen_mulsi3_highpart (h0, operands[1], operands[2]));
+ emit_insn (gen_mulsi3_700 (l0, operands[1], operands[2]));
+ DONE;
+}
+ [(set_attr "type" "multi")
+ (set_attr "length" "8")])
+
+(define_insn "mulsi3_highpart"
+ [(set (match_operand:SI 0 "register_operand" "=Rcr,r,Rcr,r")
+ (truncate:SI
+ (lshiftrt:DI
+ (mult:DI
+ (sign_extend:DI (match_operand:SI 1 "register_operand" "%0,c, 0,c"))
+ (sign_extend:DI (match_operand:SI 2 "extend_operand" "c,c, s,s")))
+ (const_int 32))))]
+ "TARGET_ARC700 && !TARGET_NOMPY_SET"
+ "mpyh%? %0,%1,%2"
+ [(set_attr "length" "4,4,8,8")
+ (set_attr "type" "multi")
+ (set_attr "predicable" "yes,no,yes,no")
+ (set_attr "cond" "canuse,nocond,canuse,nocond")])
+
+; Note that mpyhu has the same latency as mpy / mpyh,
+; thus we use the type multi.
+(define_insn "*umulsi3_highpart_i"
+ [(set (match_operand:SI 0 "register_operand" "=Rcr,r,Rcr,r")
+ (truncate:SI
+ (lshiftrt:DI
+ (mult:DI
+ (zero_extend:DI (match_operand:SI 1 "register_operand" "%0,c, 0,c"))
+ (zero_extend:DI (match_operand:SI 2 "extend_operand" "c,c, s,s")))
+ (const_int 32))))]
+ "TARGET_ARC700 && !TARGET_NOMPY_SET"
+ "mpyhu%? %0,%1,%2"
+ [(set_attr "length" "4,4,8,8")
+ (set_attr "type" "multi")
+ (set_attr "predicable" "yes,no,yes,no")
+ (set_attr "cond" "canuse,nocond,canuse,nocond")])
+
+; Implementations include additional labels for umulsidi3, so we got all
+; the same clobbers - plus one for the result low part. */
+(define_insn "umulsi3_highpart_600_lib_le"
+ [(set (reg:SI R1_REG)
+ (truncate:SI
+ (lshiftrt:DI
+ (mult:DI (zero_extend:DI (reg:SI R0_REG))
+ (zero_extend:DI (reg:SI R1_REG)))
+ (const_int 32))))
+ (clobber (reg:SI RETURN_ADDR_REGNUM))
+ (clobber (reg:SI R0_REG))
+ (clobber (reg:DI R2_REG))
+ (clobber (reg:SI R12_REG))
+ (clobber (reg:DI MUL64_OUT_REG))
+ (clobber (reg:CC CC_REG))]
+ "!TARGET_BIG_ENDIAN
+ && !TARGET_MUL64_SET && !TARGET_MULMAC_32BY16_SET
+ && (!TARGET_ARC700 || TARGET_NOMPY_SET)
+ && SFUNC_CHECK_PREDICABLE"
+ "*return arc_output_libcall (\"__umulsi3_highpart\");"
+ [(set_attr "is_sfunc" "yes")
+ (set_attr "predicable" "yes")])
+
+(define_insn "umulsi3_highpart_600_lib_be"
+ [(set (reg:SI R0_REG)
+ (truncate:SI
+ (lshiftrt:DI
+ (mult:DI (zero_extend:DI (reg:SI R0_REG))
+ (zero_extend:DI (reg:SI R1_REG)))
+ (const_int 32))))
+ (clobber (reg:SI RETURN_ADDR_REGNUM))
+ (clobber (reg:SI R1_REG))
+ (clobber (reg:DI R2_REG))
+ (clobber (reg:SI R12_REG))
+ (clobber (reg:DI MUL64_OUT_REG))
+ (clobber (reg:CC CC_REG))]
+ "TARGET_BIG_ENDIAN
+ && !TARGET_MUL64_SET && !TARGET_MULMAC_32BY16_SET
+ && (!TARGET_ARC700 || TARGET_NOMPY_SET)
+ && SFUNC_CHECK_PREDICABLE"
+ "*return arc_output_libcall (\"__umulsi3_highpart\");"
+ [(set_attr "is_sfunc" "yes")
+ (set_attr "predicable" "yes")])
+
+;; (zero_extend:DI (const_int)) leads to internal errors in combine, so we
+;; need a separate pattern for immediates
+;; ??? This is fine for combine, but not for reload.
+(define_insn "umulsi3_highpart_int"
+ [(set (match_operand:SI 0 "register_operand" "=Rcr, r, r,Rcr, r")
+ (truncate:SI
+ (lshiftrt:DI
+ (mult:DI
+ (zero_extend:DI (match_operand:SI 1 "register_operand" " 0, c, 0, 0, c"))
+ (match_operand:DI 2 "immediate_usidi_operand" "L, L, I, Cal, Cal"))
+ (const_int 32))))]
+ "TARGET_ARC700 && !TARGET_NOMPY_SET"
+ "mpyhu%? %0,%1,%2"
+ [(set_attr "length" "4,4,4,8,8")
+ (set_attr "type" "multi")
+ (set_attr "predicable" "yes,no,no,yes,no")
+ (set_attr "cond" "canuse,nocond,canuse_limm,canuse,nocond")])
+
+(define_expand "umulsi3_highpart"
+ [(set (match_operand:SI 0 "general_operand" "")
+ (truncate:SI
+ (lshiftrt:DI
+ (mult:DI
+ (zero_extend:DI (match_operand:SI 1 "register_operand" ""))
+ (zero_extend:DI (match_operand:SI 2 "nonmemory_operand" "")))
+ (const_int 32))))]
+ "TARGET_ARC700 || (!TARGET_MUL64_SET && !TARGET_MULMAC_32BY16_SET)"
+ "
+{
+ rtx target = operands[0];
+
+ if (!TARGET_ARC700 || TARGET_NOMPY_SET)
+ {
+ emit_move_insn (gen_rtx_REG (SImode, 0), operands[1]);
+ emit_move_insn (gen_rtx_REG (SImode, 1), operands[2]);
+ if (TARGET_BIG_ENDIAN)
+ emit_insn (gen_umulsi3_highpart_600_lib_be ());
+ else
+ emit_insn (gen_umulsi3_highpart_600_lib_le ());
+ emit_move_insn (target, gen_rtx_REG (SImode, 0));
+ DONE;
+ }
+
+ if (!register_operand (target, SImode))
+ target = gen_reg_rtx (SImode);
+
+ if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0)
+ operands[2] = simplify_const_unary_operation (ZERO_EXTEND, DImode,
+ operands[2], SImode);
+ else if (!immediate_operand (operands[2], SImode))
+ operands[2] = gen_rtx_ZERO_EXTEND (DImode, operands[2]);
+ emit_insn (gen_umulsi3_highpart_int (target, operands[1], operands[2]));
+ if (target != operands[0])
+ emit_move_insn (operands[0], target);
+ DONE;
+}")
+
+(define_expand "umulsidi3"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "")
+ (mult:DI (zero_extend:DI(match_operand:SI 1 "register_operand" ""))
+ (zero_extend:DI(match_operand:SI 2 "nonmemory_operand" ""))))]
+ ""
+{
+ if (TARGET_ARC700 && !TARGET_NOMPY_SET)
+ {
+ operands[2] = force_reg (SImode, operands[2]);
+ if (!register_operand (operands[0], DImode))
+ {
+ rtx result = gen_reg_rtx (DImode);
+
+ emit_insn (gen_umulsidi3 (result, operands[1], operands[2]));
+ emit_move_insn (operands[0], result);
+ DONE;
+ }
+ }
+ else if (TARGET_MUL64_SET)
+ {
+ operands[2] = force_reg (SImode, operands[2]);
+ emit_insn (gen_umulsidi_600 (operands[1], operands[2]));
+ emit_move_insn (operands[0], gen_rtx_REG (DImode, MUL64_OUT_REG));
+ DONE;
+ }
+ else if (TARGET_MULMAC_32BY16_SET)
+ {
+ rtx result_hi = gen_reg_rtx (SImode);
+ rtx result_low = gen_reg_rtx (SImode);
+
+ result_hi = gen_highpart(SImode , operands[0]);
+ result_low = gen_lowpart(SImode , operands[0]);
+
+ emit_insn (gen_umul64_600 (operands[1], operands[2]));
+ emit_insn (gen_umac64_600 (result_hi, operands[1], operands[2]));
+ emit_move_insn (result_low, gen_acc2 ());
+ DONE;
+ }
+ else
+ {
+ emit_move_insn (gen_rtx_REG (SImode, R0_REG), operands[1]);
+ emit_move_insn (gen_rtx_REG (SImode, R1_REG), operands[2]);
+ emit_insn (gen_umulsidi3_600_lib ());
+ emit_move_insn (operands[0], gen_rtx_REG (DImode, R0_REG));
+ DONE;
+ }
+})
+
+(define_insn "umul64_600"
+ [(set (reg:DI 56)
+ (mult:DI (zero_extend:DI (match_operand:SI 0 "register_operand"
+ "c,c,c"))
+ (zero_extract:DI (match_operand:SI 1 "nonmemory_operand"
+ "c,L,Cal")
+ (const_int 16)
+ (const_int 0))))
+ ]
+ "TARGET_MULMAC_32BY16_SET"
+ "@mululw 0, %0, %1
+ mululw 0, %0, %1
+ mululw%? 0, %1, %0"
+ [(set_attr "length" "4,4,8")
+ (set_attr "type" "mulmac_600")
+ (set_attr "predicable" "no,no,yes")
+ (set_attr "cond" "nocond, canuse_limm, canuse")])
+
+
+(define_insn "umac64_600"
+ [(set (reg:DI 56)
+ (plus:DI
+ (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "c,c,c"))
+ (ashift:DI
+ (zero_extract:DI (match_operand:SI 2 "nonmemory_operand" "c,L,Cal")
+ (const_int 16) (const_int 16))
+ (const_int 16)))
+ (reg:DI 56)))
+ (set (match_operand:SI 0 "register_operand" "=w,w,w")
+ (zero_extract:SI
+ (plus:DI
+ (mult:DI (zero_extend:DI (match_dup 1))
+ (ashift:DI
+ (zero_extract:DI (match_dup 2)
+ (const_int 16) (const_int 16))
+ (const_int 16)))
+ (reg:DI 56))
+ (const_int 32) (const_int 32)))]
+ "TARGET_MULMAC_32BY16_SET"
+ "machulw%? %0, %1, %2"
+ [(set_attr "length" "4,4,8")
+ (set_attr "type" "mulmac_600")
+ (set_attr "predicable" "no,no,yes")
+ (set_attr "cond" "nocond, canuse_limm, canuse")])
+
+
+
+;; DI <- DI(unsigned SI) * DI(unsigned SI)
+(define_insn_and_split "umulsidi3_700"
+ [(set (match_operand:DI 0 "dest_reg_operand" "=&r")
+ (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%c"))
+ (zero_extend:DI (match_operand:SI 2 "register_operand" "c"))))]
+;; (zero_extend:DI (match_operand:SI 2 "register_operand" "rL"))))]
+ "TARGET_ARC700 && !TARGET_NOMPY_SET"
+ "#"
+ "reload_completed"
+ [(const_int 0)]
+{
+ int hi = !TARGET_BIG_ENDIAN;
+ int lo = !hi;
+ rtx l0 = operand_subword (operands[0], lo, 0, DImode);
+ rtx h0 = operand_subword (operands[0], hi, 0, DImode);
+ emit_insn (gen_umulsi3_highpart (h0, operands[1], operands[2]));
+ emit_insn (gen_mulsi3_700 (l0, operands[1], operands[2]));
+ DONE;
+}
+ [(set_attr "type" "umulti")
+ (set_attr "length" "8")])
+
+(define_insn "umulsidi3_600_lib"
+ [(set (reg:DI R0_REG)
+ (mult:DI (zero_extend:DI (reg:SI R0_REG))
+ (zero_extend:DI (reg:SI R1_REG))))
+ (clobber (reg:SI RETURN_ADDR_REGNUM))
+ (clobber (reg:DI R2_REG))
+ (clobber (reg:SI R12_REG))
+ (clobber (reg:DI MUL64_OUT_REG))
+ (clobber (reg:CC CC_REG))]
+ "!TARGET_MUL64_SET && !TARGET_MULMAC_32BY16_SET
+ && (!TARGET_ARC700 || TARGET_NOMPY_SET)
+ && SFUNC_CHECK_PREDICABLE"
+ "*return arc_output_libcall (\"__umulsidi3\");"
+ [(set_attr "is_sfunc" "yes")
+ (set_attr "predicable" "yes")])
+
+(define_peephole2
+ [(parallel
+ [(set (reg:DI R0_REG)
+ (mult:DI (zero_extend:DI (reg:SI R0_REG))
+ (zero_extend:DI (reg:SI R1_REG))))
+ (clobber (reg:SI RETURN_ADDR_REGNUM))
+ (clobber (reg:DI R2_REG))
+ (clobber (reg:SI R12_REG))
+ (clobber (reg:DI MUL64_OUT_REG))
+ (clobber (reg:CC CC_REG))])]
+ "!TARGET_MUL64_SET && !TARGET_MULMAC_32BY16_SET
+ && (!TARGET_ARC700 || TARGET_NOMPY_SET)
+ && peep2_regno_dead_p (1, TARGET_BIG_ENDIAN ? R1_REG : R0_REG)"
+ [(pc)]
+{
+ if (TARGET_BIG_ENDIAN)
+ emit_insn (gen_umulsi3_highpart_600_lib_be ());
+ else
+ emit_insn (gen_umulsi3_highpart_600_lib_le ());
+ DONE;
+})
+
+(define_expand "addsi3"
+ [(set (match_operand:SI 0 "dest_reg_operand" "")
+ (plus:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "nonmemory_operand" "")))]
+ ""
+ "if (flag_pic && arc_raw_symbolic_reference_mentioned_p (operands[2], false))
+ {
+ operands[2]=force_reg(SImode, operands[2]);
+ }
+ else if (!TARGET_NO_SDATA_SET && small_data_pattern (operands[2], Pmode))
+ {
+ operands[2] = force_reg (SImode, arc_rewrite_small_data (operands[2]));
+ }
+
+ ")
+
+(define_expand "adddi3"
+ [(parallel [(set (match_operand:DI 0 "dest_reg_operand" "")
+ (plus:DI (match_operand:DI 1 "register_operand" "")
+ (match_operand:DI 2 "nonmemory_operand" "")))
+ (clobber (reg:CC CC_REG))])]
+ ""
+{
+ if (TARGET_EXPAND_ADDDI)
+ {
+ rtx l0 = gen_lowpart (SImode, operands[0]);
+ rtx h0 = disi_highpart (operands[0]);
+ rtx l1 = gen_lowpart (SImode, operands[1]);
+ rtx h1 = disi_highpart (operands[1]);
+ rtx l2 = gen_lowpart (SImode, operands[2]);
+ rtx h2 = disi_highpart (operands[2]);
+ rtx cc_c = gen_rtx_REG (CC_Cmode, CC_REG);
+
+ if (CONST_INT_P (h2) && INTVAL (h2) < 0 && SIGNED_INT12 (INTVAL (h2)))
+ {
+ emit_insn (gen_sub_f (l0, l1, gen_int_mode (-INTVAL (l2), SImode)));
+ emit_insn (gen_sbc (h0, h1,
+ gen_int_mode (-INTVAL (h2) - (l1 != 0), SImode),
+ cc_c));
+ DONE;
+ }
+ emit_insn (gen_add_f (l0, l1, l2));
+ emit_insn (gen_adc (h0, h1, h2));
+ DONE;
+ }
+})
+
+; This assumes that there can be no strictly partial overlap between
+; operands[1] and operands[2].
+(define_insn_and_split "*adddi3_i"
+ [(set (match_operand:DI 0 "dest_reg_operand" "=&w,w,w")
+ (plus:DI (match_operand:DI 1 "register_operand" "%c,0,c")
+ (match_operand:DI 2 "nonmemory_operand" "ci,ci,!i")))
+ (clobber (reg:CC CC_REG))]
+ ""
+ "#"
+ "reload_completed"
+ [(const_int 0)]
+{
+ int hi = !TARGET_BIG_ENDIAN;
+ int lo = !hi;
+ rtx l0 = operand_subword (operands[0], lo, 0, DImode);
+ rtx h0 = operand_subword (operands[0], hi, 0, DImode);
+ rtx l1 = operand_subword (operands[1], lo, 0, DImode);
+ rtx h1 = operand_subword (operands[1], hi, 0, DImode);
+ rtx l2 = operand_subword (operands[2], lo, 0, DImode);
+ rtx h2 = operand_subword (operands[2], hi, 0, DImode);
+
+
+ if (l2 == const0_rtx)
+ {
+ if (!rtx_equal_p (l0, l1) && !rtx_equal_p (l0, h1))
+ emit_move_insn (l0, l1);
+ emit_insn (gen_addsi3 (h0, h1, h2));
+ if (!rtx_equal_p (l0, l1) && rtx_equal_p (l0, h1))
+ emit_move_insn (l0, l1);
+ DONE;
+ }
+ if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0
+ && INTVAL (operands[2]) >= -0x7fffffff)
+ {
+ emit_insn (gen_subdi3_i (operands[0], operands[1],
+ GEN_INT (-INTVAL (operands[2]))));
+ DONE;
+ }
+ if (rtx_equal_p (l0, h1))
+ {
+ if (h2 != const0_rtx)
+ emit_insn (gen_addsi3 (h0, h1, h2));
+ else if (!rtx_equal_p (h0, h1))
+ emit_move_insn (h0, h1);
+ emit_insn (gen_add_f (l0, l1, l2));
+ emit_insn
+ (gen_rtx_COND_EXEC
+ (VOIDmode,
+ gen_rtx_LTU (VOIDmode, gen_rtx_REG (CC_Cmode, CC_REG), GEN_INT (0)),
+ gen_rtx_SET (VOIDmode, h0, plus_constant (SImode, h0, 1))));
+ DONE;
+ }
+ emit_insn (gen_add_f (l0, l1, l2));
+ emit_insn (gen_adc (h0, h1, h2));
+ DONE;
+}
+ [(set_attr "cond" "clob")
+ (set_attr "type" "binary")
+ (set_attr "length" "16,16,20")])
+
+(define_insn "add_f"
+ [(set (reg:CC_C CC_REG)
+ (compare:CC_C
+ (plus:SI (match_operand:SI 1 "register_operand" "c,0,c")
+ (match_operand:SI 2 "nonmemory_operand" "cL,I,cCal"))
+ (match_dup 1)))
+ (set (match_operand:SI 0 "dest_reg_operand" "=w,Rcw,w")
+ (plus:SI (match_dup 1) (match_dup 2)))]
+ ""
+ "add.f %0,%1,%2"
+ [(set_attr "cond" "set")
+ (set_attr "type" "compare")
+ (set_attr "length" "4,4,8")])
+
+(define_insn "*add_f_2"
+ [(set (reg:CC_C CC_REG)
+ (compare:CC_C
+ (plus:SI (match_operand:SI 1 "register_operand" "c,0,c")
+ (match_operand:SI 2 "nonmemory_operand" "cL,I,cCal"))
+ (match_dup 2)))
+ (set (match_operand:SI 0 "dest_reg_operand" "=w,Rcw,w")
+ (plus:SI (match_dup 1) (match_dup 2)))]
+ ""
+ "add.f %0,%1,%2"
+ [(set_attr "cond" "set")
+ (set_attr "type" "compare")
+ (set_attr "length" "4,4,8")])
+
+; w/c/c comes first (rather than w/0/C_0) to prevent the middle-end
+; needlessly prioritizing the matching constraint.
+; Rcw/0/C_0 comes before w/c/L so that the lower latency conditional
+; execution is used where possible.
+(define_insn_and_split "adc"
+ [(set (match_operand:SI 0 "dest_reg_operand" "=w,Rcw,w,Rcw,w")
+ (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REG) (const_int 0))
+ (match_operand:SI 1 "nonmemory_operand"
+ "%c,0,c,0,cCal"))
+ (match_operand:SI 2 "nonmemory_operand" "c,C_0,L,I,cCal")))]
+ "register_operand (operands[1], SImode)
+ || register_operand (operands[2], SImode)"
+ "@
+ adc %0,%1,%2
+ add.cs %0,%1,1
+ adc %0,%1,%2
+ adc %0,%1,%2
+ adc %0,%1,%2"
+ ; if we have a bad schedule after sched2, split.
+ "reload_completed
+ && !optimize_size && TARGET_ARC700
+ && arc_scheduling_not_expected ()
+ && arc_sets_cc_p (prev_nonnote_insn (insn))
+ /* If next comes a return or other insn that needs a delay slot,
+ expect the adc to get into the delay slot. */
+ && next_nonnote_insn (insn)
+ && !arc_need_delay (next_nonnote_insn (insn))
+ /* Restore operands before emitting. */
+ && (extract_insn_cached (insn), 1)"
+ [(set (match_dup 0) (match_dup 3))
+ (cond_exec
+ (ltu (reg:CC_C CC_REG) (const_int 0))
+ (set (match_dup 0) (plus:SI (match_dup 0) (const_int 1))))]
+ "operands[3] = simplify_gen_binary (PLUS, SImode, operands[1], operands[2]);"
+ [(set_attr "cond" "use")
+ (set_attr "type" "cc_arith")
+ (set_attr "length" "4,4,4,4,8")])
+
+; combiner-splitter cmp / scc -> cmp / adc
+(define_split
+ [(set (match_operand:SI 0 "dest_reg_operand" "")
+ (gtu:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "register_operand" "")))
+ (clobber (reg CC_REG))]
+ ""
+ [(set (reg:CC_C CC_REG) (compare:CC_C (match_dup 2) (match_dup 1)))
+ (set (match_dup 0) (ltu:SI (reg:CC_C CC_REG) (const_int 0)))])
+
+; combine won't work when an intermediate result is used later...
+; add %0,%1,%2 ` cmp %0,%[12] -> add.f %0,%1,%2
+(define_peephole2
+ [(set (match_operand:SI 0 "dest_reg_operand" "")
+ (plus:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "nonmemory_operand" "")))
+ (set (reg:CC_C CC_REG)
+ (compare:CC_C (match_dup 0)
+ (match_operand:SI 3 "nonmemory_operand" "")))]
+ "rtx_equal_p (operands[1], operands[3])
+ || rtx_equal_p (operands[2], operands[3])"
+ [(parallel
+ [(set (reg:CC_C CC_REG)
+ (compare:CC_C (plus:SI (match_dup 1) (match_dup 2)) (match_dup 1)))
+ (set (match_dup 0)
+ (plus:SI (match_dup 1) (match_dup 2)))])])
+
+; ??? need to delve into combine to find out why this is not useful.
+; We'd like to be able to grok various C idioms for carry bit usage.
+;(define_insn "*adc_0"
+; [(set (match_operand:SI 0 "dest_reg_operand" "=w")
+; (plus:SI (ltu:SI (reg:CC_C CC_REG) (const_int 0))
+; (match_operand:SI 1 "register_operand" "c")))]
+; ""
+; "adc %0,%1,0"
+; [(set_attr "cond" "use")
+; (set_attr "type" "cc_arith")
+; (set_attr "length" "4")])
+;
+;(define_split
+; [(set (match_operand:SI 0 "dest_reg_operand" "=w")
+; (plus:SI (gtu:SI (match_operand:SI 1 "register_operand" "c")
+; (match_operand:SI 2 "register_operand" "c"))
+; (match_operand:SI 3 "register_operand" "c")))
+; (clobber (reg CC_REG))]
+; ""
+; [(set (reg:CC_C CC_REG) (compare:CC_C (match_dup 2) (match_dup 1)))
+; (set (match_dup 0)
+; (plus:SI (ltu:SI (reg:CC_C CC_REG) (const_int 0))
+; (match_dup 3)))])
+
+(define_expand "subsi3"
+ [(set (match_operand:SI 0 "dest_reg_operand" "")
+ (minus:SI (match_operand:SI 1 "nonmemory_operand" "")
+ (match_operand:SI 2 "nonmemory_operand" "")))]
+ ""
+ "
+{
+ int c = 1;
+
+ if (!register_operand (operands[2], SImode))
+ {
+ operands[1] = force_reg (SImode, operands[1]);
+ c = 2;
+ }
+ if (flag_pic && arc_raw_symbolic_reference_mentioned_p (operands[c], false))
+ operands[c] = force_reg (SImode, operands[c]);
+ else if (!TARGET_NO_SDATA_SET && small_data_pattern (operands[c], Pmode))
+ operands[c] = force_reg (SImode, arc_rewrite_small_data (operands[c]));
+}")
+
+; the casesi expander might generate a sub of zero, so we have to recognize it.
+; combine should make such an insn go away.
+(define_insn_and_split "subsi3_insn"
+ [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,Rcw,Rcw,w,w,w, w, w, w")
+ (minus:SI (match_operand:SI 1 "nonmemory_operand" "0, 0, cL,c,L,I,Cal,Cal, c")
+ (match_operand:SI 2 "nonmemory_operand" "Rcqq, c, 0,c,c,0, 0, c,Cal")))]
+ "register_operand (operands[1], SImode)
+ || register_operand (operands[2], SImode)"
+ "@
+ sub%? %0,%1,%2%&
+ sub%? %0,%1,%2
+ rsub%? %0,%2,%1
+ sub %0,%1,%2
+ rsub %0,%2,%1
+ rsub %0,%2,%1
+ rsub%? %0,%2,%1
+ rsub %0,%2,%1
+ sub %0,%1,%2"
+ "reload_completed && get_attr_length (insn) == 8
+ && satisfies_constraint_I (operands[1])
+ && GET_CODE (PATTERN (insn)) != COND_EXEC"
+ [(set (match_dup 0) (match_dup 3)) (set (match_dup 0) (match_dup 4))]
+ "split_subsi (operands);"
+ [(set_attr "iscompact" "maybe,false,false,false,false,false,false,false, false")
+ (set_attr "length" "*,4,4,4,4,4,8,8,8")
+ (set_attr "predicable" "yes,yes,yes,no,no,no,yes,no,no")
+ (set_attr "cond" "canuse,canuse,canuse,nocond,nocond,canuse_limm,canuse,nocond,nocond")])
+
+(define_expand "subdi3"
+ [(parallel [(set (match_operand:DI 0 "dest_reg_operand" "")
+ (minus:DI (match_operand:DI 1 "nonmemory_operand" "")
+ (match_operand:DI 2 "nonmemory_operand" "")))
+ (clobber (reg:CC CC_REG))])]
+ ""
+{
+ if (!register_operand (operands[2], DImode))
+ operands[1] = force_reg (DImode, operands[1]);
+ if (TARGET_EXPAND_ADDDI)
+ {
+ rtx l0 = gen_lowpart (SImode, operands[0]);
+ rtx h0 = disi_highpart (operands[0]);
+ rtx l1 = gen_lowpart (SImode, operands[1]);
+ rtx h1 = disi_highpart (operands[1]);
+ rtx l2 = gen_lowpart (SImode, operands[2]);
+ rtx h2 = disi_highpart (operands[2]);
+ rtx cc_c = gen_rtx_REG (CC_Cmode, CC_REG);
+
+ emit_insn (gen_sub_f (l0, l1, l2));
+ emit_insn (gen_sbc (h0, h1, h2, cc_c));
+ DONE;
+ }
+})
+
+(define_insn_and_split "subdi3_i"
+ [(set (match_operand:DI 0 "dest_reg_operand" "=&w,w,w,w,w")
+ (minus:DI (match_operand:DI 1 "nonmemory_operand" "ci,0,ci,c,!i")
+ (match_operand:DI 2 "nonmemory_operand" "ci,ci,0,!i,c")))
+ (clobber (reg:CC CC_REG))]
+ "register_operand (operands[1], DImode)
+ || register_operand (operands[2], DImode)"
+ "#"
+ "reload_completed"
+ [(const_int 0)]
+{
+ int hi = !TARGET_BIG_ENDIAN;
+ int lo = !hi;
+ rtx l0 = operand_subword (operands[0], lo, 0, DImode);
+ rtx h0 = operand_subword (operands[0], hi, 0, DImode);
+ rtx l1 = operand_subword (operands[1], lo, 0, DImode);
+ rtx h1 = operand_subword (operands[1], hi, 0, DImode);
+ rtx l2 = operand_subword (operands[2], lo, 0, DImode);
+ rtx h2 = operand_subword (operands[2], hi, 0, DImode);
+
+ if (rtx_equal_p (l0, h1) || rtx_equal_p (l0, h2))
+ {
+ h1 = simplify_gen_binary (MINUS, SImode, h1, h2);
+ if (!rtx_equal_p (h0, h1))
+ emit_insn (gen_rtx_SET (VOIDmode, h0, h1));
+ emit_insn (gen_sub_f (l0, l1, l2));
+ emit_insn
+ (gen_rtx_COND_EXEC
+ (VOIDmode,
+ gen_rtx_LTU (VOIDmode, gen_rtx_REG (CC_Cmode, CC_REG), GEN_INT (0)),
+ gen_rtx_SET (VOIDmode, h0, plus_constant (SImode, h0, -1))));
+ DONE;
+ }
+ emit_insn (gen_sub_f (l0, l1, l2));
+ emit_insn (gen_sbc (h0, h1, h2, gen_rtx_REG (CCmode, CC_REG)));
+ DONE;
+}
+ [(set_attr "cond" "clob")
+ (set_attr "length" "16,16,16,20,20")])
+
+(define_insn "*sbc_0"
+ [(set (match_operand:SI 0 "dest_reg_operand" "=w")
+ (minus:SI (match_operand:SI 1 "register_operand" "c")
+ (ltu:SI (match_operand:CC_C 2 "cc_use_register")
+ (const_int 0))))]
+ ""
+ "sbc %0,%1,0"
+ [(set_attr "cond" "use")
+ (set_attr "type" "cc_arith")
+ (set_attr "length" "4")])
+
+; w/c/c comes first (rather than Rcw/0/C_0) to prevent the middle-end
+; needlessly prioritizing the matching constraint.
+; Rcw/0/C_0 comes before w/c/L so that the lower latency conditional execution
+; is used where possible.
+(define_insn_and_split "sbc"
+ [(set (match_operand:SI 0 "dest_reg_operand" "=w,Rcw,w,Rcw,w")
+ (minus:SI (minus:SI (match_operand:SI 1 "nonmemory_operand"
+ "c,0,c,0,cCal")
+ (ltu:SI (match_operand:CC_C 3 "cc_use_register")
+ (const_int 0)))
+ (match_operand:SI 2 "nonmemory_operand" "c,C_0,L,I,cCal")))]
+ "register_operand (operands[1], SImode)
+ || register_operand (operands[2], SImode)"
+ "@
+ sbc %0,%1,%2
+ sub.cs %0,%1,1
+ sbc %0,%1,%2
+ sbc %0,%1,%2
+ sbc %0,%1,%2"
+ ; if we have a bad schedule after sched2, split.
+ "reload_completed
+ && !optimize_size && TARGET_ARC700
+ && arc_scheduling_not_expected ()
+ && arc_sets_cc_p (prev_nonnote_insn (insn))
+ /* If next comes a return or other insn that needs a delay slot,
+ expect the adc to get into the delay slot. */
+ && next_nonnote_insn (insn)
+ && !arc_need_delay (next_nonnote_insn (insn))
+ /* Restore operands before emitting. */
+ && (extract_insn_cached (insn), 1)"
+ [(set (match_dup 0) (match_dup 4))
+ (cond_exec
+ (ltu (reg:CC_C CC_REG) (const_int 0))
+ (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1))))]
+ "operands[4] = simplify_gen_binary (MINUS, SImode, operands[1], operands[2]);"
+ [(set_attr "cond" "use")
+ (set_attr "type" "cc_arith")
+ (set_attr "length" "4,4,4,4,8")])
+
+(define_insn "sub_f"
+ [(set (reg:CC CC_REG)
+ (compare:CC (match_operand:SI 1 "nonmemory_operand" " c,L,0,I,c,Cal")
+ (match_operand:SI 2 "nonmemory_operand" "cL,c,I,0,Cal,c")))
+ (set (match_operand:SI 0 "dest_reg_operand" "=w,w,Rcw,Rcw,w,w")
+ (minus:SI (match_dup 1) (match_dup 2)))]
+ "register_operand (operands[1], SImode)
+ || register_operand (operands[2], SImode)"
+ "@
+ sub.f %0,%1,%2
+ rsub.f %0,%2,%1
+ sub.f %0,%1,%2
+ rsub.f %0,%2,%1
+ sub.f %0,%1,%2
+ sub.f %0,%1,%2"
+ [(set_attr "type" "compare")
+ (set_attr "length" "4,4,4,4,8,8")])
+
+; combine won't work when an intermediate result is used later...
+; add %0,%1,%2 ` cmp %0,%[12] -> add.f %0,%1,%2
+(define_peephole2
+ [(set (reg:CC CC_REG)
+ (compare:CC (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "nonmemory_operand" "")))
+ (set (match_operand:SI 0 "dest_reg_operand" "")
+ (minus:SI (match_dup 1) (match_dup 2)))]
+ ""
+ [(parallel
+ [(set (reg:CC CC_REG) (compare:CC (match_dup 1) (match_dup 2)))
+ (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])])
+
+(define_peephole2
+ [(set (reg:CC CC_REG)
+ (compare:CC (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "nonmemory_operand" "")))
+ (set (match_operand 3 "" "") (match_operand 4 "" ""))
+ (set (match_operand:SI 0 "dest_reg_operand" "")
+ (minus:SI (match_dup 1) (match_dup 2)))]
+ "!reg_overlap_mentioned_p (operands[3], operands[1])
+ && !reg_overlap_mentioned_p (operands[3], operands[2])
+ && !reg_overlap_mentioned_p (operands[0], operands[4])
+ && !reg_overlap_mentioned_p (operands[0], operands[3])"
+ [(parallel
+ [(set (reg:CC CC_REG) (compare:CC (match_dup 1) (match_dup 2)))
+ (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
+ (set (match_dup 3) (match_dup 4))])
+
+(define_insn "*add_n"
+ [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,Rcw,W,W,w,w")
+ (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "Rcqq,c,c,c,c,c")
+ (match_operand:SI 2 "_2_4_8_operand" ""))
+ (match_operand:SI 3 "nonmemory_operand" "0,0,c,?Cal,?c,??Cal")))]
+ ""
+ "add%z2%? %0,%3,%1%&"
+ [(set_attr "type" "shift")
+ (set_attr "length" "*,4,4,8,4,8")
+ (set_attr "predicable" "yes,yes,no,no,no,no")
+ (set_attr "cond" "canuse,canuse,nocond,nocond,nocond,nocond")
+ (set_attr "iscompact" "maybe,false,false,false,false,false")])
+
+;; N.B. sub[123] has the operands of the MINUS in the opposite order from
+;; what synth_mult likes.
+(define_insn "*sub_n"
+ [(set (match_operand:SI 0 "dest_reg_operand" "=Rcw,w,w")
+ (minus:SI (match_operand:SI 1 "nonmemory_operand" "0,c,?Cal")
+ (mult:SI (match_operand:SI 2 "register_operand" "c,c,c")
+ (match_operand:SI 3 "_2_4_8_operand" ""))))]
+ ""
+ "sub%z3%? %0,%1,%2"
+ [(set_attr "type" "shift")
+ (set_attr "length" "4,4,8")
+ (set_attr "predicable" "yes,no,no")
+ (set_attr "cond" "canuse,nocond,nocond")
+ (set_attr "iscompact" "false")])
+
+; ??? check if combine matches this.
+(define_insn "*bset"
+ [(set (match_operand:SI 0 "dest_reg_operand" "=Rcw,w,w")
+ (ior:SI (ashift:SI (const_int 1)
+ (match_operand:SI 1 "nonmemory_operand" "cL,cL,c"))
+ (match_operand:SI 2 "nonmemory_operand" "0,c,Cal")))]
+ ""
+ "bset%? %0,%2,%1"
+ [(set_attr "length" "4,4,8")
+ (set_attr "predicable" "yes,no,no")
+ (set_attr "cond" "canuse,nocond,nocond")]
+)
+
+; ??? check if combine matches this.
+(define_insn "*bxor"
+ [(set (match_operand:SI 0 "dest_reg_operand" "=Rcw,w,w")
+ (xor:SI (ashift:SI (const_int 1)
+ (match_operand:SI 1 "nonmemory_operand" "cL,cL,c"))
+ (match_operand:SI 2 "nonmemory_operand" "0,c,Cal")))]
+ ""
+ "bxor%? %0,%2,%1"
+ [(set_attr "length" "4,4,8")
+ (set_attr "predicable" "yes,no,no")
+ (set_attr "cond" "canuse,nocond,nocond")]
+)
+
+; ??? check if combine matches this.
+(define_insn "*bclr"
+ [(set (match_operand:SI 0 "dest_reg_operand" "=Rcw,w,w")
+ (and:SI (not:SI (ashift:SI (const_int 1)
+ (match_operand:SI 1 "nonmemory_operand" "cL,cL,c")))
+ (match_operand:SI 2 "nonmemory_operand" "0,c,Cal")))]
+ ""
+ "bclr%? %0,%2,%1"
+ [(set_attr "length" "4,4,8")
+ (set_attr "predicable" "yes,no,no")
+ (set_attr "cond" "canuse,nocond,nocond")]
+)
+
+; ??? FIXME: find combine patterns for bmsk.
+
+;;Following are the define_insns added for the purpose of peephole2's
+
+; see also iorsi3 for use with constant bit number.
+(define_insn "*bset_insn"
+ [(set (match_operand:SI 0 "dest_reg_operand" "=Rcw,w,w")
+ (ior:SI (match_operand:SI 1 "nonmemory_operand" "0,c,Cal")
+ (ashift:SI (const_int 1)
+ (match_operand:SI 2 "nonmemory_operand" "cL,cL,c"))) ) ]
+ ""
+ "@
+ bset%? %0,%1,%2 ;;peep2, constr 1
+ bset %0,%1,%2 ;;peep2, constr 2
+ bset %0,%S1,%2 ;;peep2, constr 3"
+ [(set_attr "length" "4,4,8")
+ (set_attr "predicable" "yes,no,no")
+ (set_attr "cond" "canuse,nocond,nocond")]
+)
+
+; see also xorsi3 for use with constant bit number.
+(define_insn "*bxor_insn"
+ [(set (match_operand:SI 0 "dest_reg_operand" "=Rcw,w,w")
+ (xor:SI (match_operand:SI 1 "nonmemory_operand" "0,c,Cal")
+ (ashift:SI (const_int 1)
+ (match_operand:SI 2 "nonmemory_operand" "cL,cL,c"))) ) ]
+ ""
+ "@
+ bxor%? %0,%1,%2
+ bxor %0,%1,%2
+ bxor %0,%S1,%2"
+ [(set_attr "length" "4,4,8")
+ (set_attr "predicable" "yes,no,no")
+ (set_attr "cond" "canuse,nocond,nocond")]
+)
+
+; see also andsi3 for use with constant bit number.
+(define_insn "*bclr_insn"
+ [(set (match_operand:SI 0 "dest_reg_operand" "=Rcw,w,w")
+ (and:SI (not:SI (ashift:SI (const_int 1)
+ (match_operand:SI 2 "nonmemory_operand" "cL,rL,r")))
+ (match_operand:SI 1 "nonmemory_operand" "0,c,Cal")))]
+ ""
+ "@
+ bclr%? %0,%1,%2
+ bclr %0,%1,%2
+ bclr %0,%S1,%2"
+ [(set_attr "length" "4,4,8")
+ (set_attr "predicable" "yes,no,no")
+ (set_attr "cond" "canuse,nocond,nocond")]
+)
+
+; see also andsi3 for use with constant bit number.
+(define_insn "*bmsk_insn"
+ [(set (match_operand:SI 0 "dest_reg_operand" "=Rcw,w,w")
+ (and:SI (match_operand:SI 1 "nonmemory_operand" "0,c,Cal")
+ (plus:SI (ashift:SI (const_int 1)
+ (plus:SI (match_operand:SI 2 "nonmemory_operand" "rL,rL,r")
+ (const_int 1)))
+ (const_int -1))))]
+ ""
+ "@
+ bmsk%? %0,%S1,%2
+ bmsk %0,%1,%2
+ bmsk %0,%S1,%2"
+ [(set_attr "length" "4,4,8")
+ (set_attr "predicable" "yes,no,no")
+ (set_attr "cond" "canuse,nocond,nocond")]
+)
+
+;;Instructions added for peephole2s end
+
+;; Boolean instructions.
+
+(define_expand "andsi3"
+ [(set (match_operand:SI 0 "dest_reg_operand" "")
+ (and:SI (match_operand:SI 1 "nonimmediate_operand" "")
+ (match_operand:SI 2 "nonmemory_operand" "")))]
+ ""
+ "if (!satisfies_constraint_Cux (operands[2]))
+ operands[1] = force_reg (SImode, operands[1]);
+ else if (!TARGET_NO_SDATA_SET && small_data_pattern (operands[1], Pmode))
+ operands[1] = arc_rewrite_small_data (operands[1]);")
+
+(define_insn "andsi3_i"
+ [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,Rcq,Rcqq,Rcqq,Rcqq,Rcw,Rcw,Rcw,Rcw,Rcw,Rcw, w, w, w, w,w,Rcw, w, W")
+ (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,Rcq, 0, 0,Rcqq, 0, c, 0, 0, 0, 0, c, c, c, c,0, 0, c, o")
+ (match_operand:SI 2 "nonmemory_operand" " Rcqq, 0, C1p, Ccp, Cux, cL, 0,C1p,Ccp,CnL, I, Lc,C1p,Ccp,CnL,I,Cal,Cal,Cux")))]
+ "(register_operand (operands[1], SImode)
+ && nonmemory_operand (operands[2], SImode))
+ || (memory_operand (operands[1], SImode)
+ && satisfies_constraint_Cux (operands[2]))"
+ "*
+{
+ switch (which_alternative)
+ {
+ case 0: case 5: case 10: case 11: case 15: case 16: case 17:
+ return \"and%? %0,%1,%2%&\";
+ case 1: case 6:
+ return \"and%? %0,%2,%1%&\";
+ case 2: case 7: case 12:
+ return \"bmsk%? %0,%1,%Z2%&\";
+ case 3: case 8: case 13:
+ return \"bclr%? %0,%1,%M2%&\";
+ case 4:
+ return (INTVAL (operands[2]) == 0xff
+ ? \"extb%? %0,%1%&\" : \"extw%? %0,%1%&\");
+ case 9: case 14: return \"bic%? %0,%1,%n2-1\";
+ case 18:
+ if (TARGET_BIG_ENDIAN)
+ {
+ rtx xop[2];
+
+ xop[0] = operands[0];
+ xop[1] = adjust_address (operands[1], QImode,
+ INTVAL (operands[2]) == 0xff ? 3 : 2);
+ output_asm_insn (INTVAL (operands[2]) == 0xff
+ ? \"ldb %0,%1\" : \"ldw %0,%1\",
+ xop);
+ return \"\";
+ }
+ return INTVAL (operands[2]) == 0xff ? \"ldb %0,%1\" : \"ldw %0,%1\";
+ default:
+ gcc_unreachable ();
+ }
+}"
+ [(set_attr "iscompact" "maybe,maybe,maybe,maybe,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false")
+ (set_attr "type" "binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,load")
+ (set_attr "length" "*,*,*,*,*,4,4,4,4,4,4,4,4,4,4,4,8,8,*")
+ (set_attr "predicable" "no,no,no,no,no,yes,yes,yes,yes,yes,no,no,no,no,no,no,yes,no,no")
+ (set_attr "cond" "canuse,canuse,canuse,canuse,nocond,canuse,canuse,canuse,canuse,canuse,canuse_limm,nocond,nocond,nocond,nocond,canuse_limm,canuse,nocond,nocond")])
+
+; combiner splitter, pattern found in ldtoa.c .
+; and op3,op0,op1 / cmp op3,op2 -> add op3,op0,op4 / bmsk.f 0,op3,op1
+(define_split
+ [(set (reg:CC_Z CC_REG)
+ (compare:CC_Z (and:SI (match_operand:SI 0 "register_operand" "")
+ (match_operand 1 "const_int_operand" ""))
+ (match_operand 2 "const_int_operand" "")))
+ (clobber (match_operand:SI 3 "register_operand" ""))]
+ "((INTVAL (operands[1]) + 1) & INTVAL (operands[1])) == 0"
+ [(set (match_dup 3)
+ (plus:SI (match_dup 0) (match_dup 4)))
+ (set (reg:CC_Z CC_REG)
+ (compare:CC_Z (and:SI (match_dup 3) (match_dup 1))
+ (const_int 0)))]
+ "operands[4] = GEN_INT ( -(~INTVAL (operands[1]) | INTVAL (operands[2])));")
+
+;;bic define_insn that allows limm to be the first operand
+(define_insn "*bicsi3_insn"
+ [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,Rcw,Rcw,Rcw,w,w,w")
+ (and:SI (not:SI (match_operand:SI 1 "nonmemory_operand" "Rcqq,Lc,I,Cal,Lc,Cal,c"))
+ (match_operand:SI 2 "nonmemory_operand" "0,0,0,0,c,c,Cal")))]
+ ""
+ "@
+ bic%? %0, %2, %1%& ;;constraint 0
+ bic%? %0,%2,%1 ;;constraint 1
+ bic %0,%2,%1 ;;constraint 2, FIXME: will it ever get generated ???
+ bic%? %0,%2,%S1 ;;constraint 3, FIXME: will it ever get generated ???
+ bic %0,%2,%1 ;;constraint 4
+ bic %0,%2,%S1 ;;constraint 5, FIXME: will it ever get generated ???
+ bic %0,%S2,%1 ;;constraint 6"
+ [(set_attr "length" "*,4,4,8,4,8,8")
+ (set_attr "iscompact" "maybe, false, false, false, false, false, false")
+ (set_attr "predicable" "no,yes,no,yes,no,no,no")
+ (set_attr "cond" "canuse,canuse,canuse_limm,canuse,nocond,nocond,nocond")])
+
+(define_insn "iorsi3"
+ [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,Rcq,Rcqq,Rcw,Rcw,Rcw,Rcw,w, w,w,Rcw, w")
+ (ior:SI (match_operand:SI 1 "nonmemory_operand" "% 0,Rcq, 0, 0, c, 0, 0, c, c,0, 0, c")
+ (match_operand:SI 2 "nonmemory_operand" "Rcqq, 0, C0p, cL, 0,C0p, I,cL,C0p,I,Cal,Cal")))]
+ ""
+ "*
+ switch (which_alternative)
+ {
+ case 0: case 3: case 6: case 7: case 9: case 10: case 11:
+ return \"or%? %0,%1,%2%&\";
+ case 1: case 4:
+ return \"or%? %0,%2,%1%&\";
+ case 2: case 5: case 8:
+ return \"bset%? %0,%1,%z2%&\";
+ default:
+ gcc_unreachable ();
+ }"
+ [(set_attr "iscompact" "maybe,maybe,maybe,false,false,false,false,false,false,false,false,false")
+ (set_attr "length" "*,*,*,4,4,4,4,4,4,4,8,8")
+ (set_attr "predicable" "no,no,no,yes,yes,yes,no,no,no,no,yes,no")
+ (set_attr "cond" "canuse,canuse,canuse,canuse,canuse,canuse,canuse_limm,nocond,nocond,canuse_limm,canuse,nocond")])
+
+(define_insn "xorsi3"
+ [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,Rcq,Rcw,Rcw,Rcw,Rcw, w, w,w, w, w")
+ (xor:SI (match_operand:SI 1 "register_operand" "%0, Rcq, 0, c, 0, 0, c, c,0, 0, c")
+ (match_operand:SI 2 "nonmemory_operand" " Rcqq, 0, cL, 0,C0p, I,cL,C0p,I,Cal,Cal")))]
+ ""
+ "*
+ switch (which_alternative)
+ {
+ case 0: case 2: case 5: case 6: case 8: case 9: case 10:
+ return \"xor%? %0,%1,%2%&\";
+ case 1: case 3:
+ return \"xor%? %0,%2,%1%&\";
+ case 4: case 7:
+ return \"bxor%? %0,%1,%z2\";
+ default:
+ gcc_unreachable ();
+ }
+ "
+ [(set_attr "iscompact" "maybe,maybe,false,false,false,false,false,false,false,false,false")
+ (set_attr "type" "binary")
+ (set_attr "length" "*,*,4,4,4,4,4,4,4,8,8")
+ (set_attr "predicable" "no,no,yes,yes,yes,no,no,no,no,yes,no")
+ (set_attr "cond" "canuse,canuse,canuse,canuse,canuse,canuse_limm,nocond,nocond,canuse_limm,canuse,nocond")])
+
+(define_insn "negsi2"
+ [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,Rcqq,Rcw,w")
+ (neg:SI (match_operand:SI 1 "register_operand" "0,Rcqq,0,c")))]
+ ""
+ "neg%? %0,%1%&"
+ [(set_attr "type" "unary")
+ (set_attr "iscompact" "maybe,true,false,false")
+ (set_attr "predicable" "no,no,yes,no")])
+
+(define_insn "one_cmplsi2"
+ [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,w")
+ (not:SI (match_operand:SI 1 "register_operand" "Rcqq,c")))]
+ ""
+ "not%? %0,%1%&"
+ [(set_attr "type" "unary,unary")
+ (set_attr "iscompact" "true,false")])
+
+(define_insn_and_split "one_cmpldi2"
+ [(set (match_operand:DI 0 "dest_reg_operand" "=q,w")
+ (not:DI (match_operand:DI 1 "register_operand" "q,c")))]
+ ""
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 2) (not:SI (match_dup 3)))
+ (set (match_dup 4) (not:SI (match_dup 5)))]
+{
+ int swap = (true_regnum (operands[0]) == true_regnum (operands[1]) + 1);
+
+ operands[2] = operand_subword (operands[0], 0+swap, 0, DImode);
+ operands[3] = operand_subword (operands[1], 0+swap, 0, DImode);
+ operands[4] = operand_subword (operands[0], 1-swap, 0, DImode);
+ operands[5] = operand_subword (operands[1], 1-swap, 0, DImode);
+}
+ [(set_attr "type" "unary,unary")
+ (set_attr "cond" "nocond,nocond")
+ (set_attr "length" "4,8")])
+
+;; Shift instructions.
+
+(define_expand "ashlsi3"
+ [(set (match_operand:SI 0 "dest_reg_operand" "")
+ (ashift:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "nonmemory_operand" "")))]
+ ""
+ "
+{
+ if (!TARGET_BARREL_SHIFTER)
+ {
+ emit_shift (ASHIFT, operands[0], operands[1], operands[2]);
+ DONE;
+ }
+}")
+
+(define_expand "ashrsi3"
+ [(set (match_operand:SI 0 "dest_reg_operand" "")
+ (ashiftrt:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "nonmemory_operand" "")))]
+ ""
+ "
+{
+ if (!TARGET_BARREL_SHIFTER)
+ {
+ emit_shift (ASHIFTRT, operands[0], operands[1], operands[2]);
+ DONE;
+ }
+}")
+
+(define_expand "lshrsi3"
+ [(set (match_operand:SI 0 "dest_reg_operand" "")
+ (lshiftrt:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "nonmemory_operand" "")))]
+ ""
+ "
+{
+ if (!TARGET_BARREL_SHIFTER)
+ {
+ emit_shift (LSHIFTRT, operands[0], operands[1], operands[2]);
+ DONE;
+ }
+}")
+
+(define_insn "shift_si3"
+ [(set (match_operand:SI 0 "dest_reg_operand" "=r")
+ (match_operator:SI 3 "shift4_operator"
+ [(match_operand:SI 1 "register_operand" "0")
+ (match_operand:SI 2 "const_int_operand" "n")]))
+ (clobber (match_scratch:SI 4 "=&r"))
+ (clobber (reg:CC CC_REG))
+ ]
+ "!TARGET_BARREL_SHIFTER"
+ "* return output_shift (operands);"
+ [(set_attr "type" "shift")
+ (set_attr "length" "16")])
+
+(define_insn "shift_si3_loop"
+ [(set (match_operand:SI 0 "dest_reg_operand" "=r,r")
+ (match_operator:SI 3 "shift_operator"
+ [(match_operand:SI 1 "register_operand" "0,0")
+ (match_operand:SI 2 "nonmemory_operand" "rn,Cal")]))
+ (clobber (match_scratch:SI 4 "=X,X"))
+ (clobber (reg:SI LP_COUNT))
+ (clobber (reg:SI LP_START))
+ (clobber (reg:SI LP_END))
+ (clobber (reg:CC CC_REG))
+ ]
+ "!TARGET_BARREL_SHIFTER"
+ "* return output_shift (operands);"
+ [(set_attr "type" "shift")
+ (set_attr "length" "16,20")])
+
+; asl, asr, lsr patterns:
+; There is no point in including an 'I' alternative since only the lowest 5
+; bits are used for the shift. OTOH Cal can be useful if the shift amount
+; is defined in an external symbol, as we don't have special relocations
+; to truncate a symbol in a u6 immediate; but that's rather exotic, so only
+; provide one alternatice for this, without condexec support.
+(define_insn "*ashlsi3_insn"
+ [(set (match_operand:SI 0 "dest_reg_operand" "=Rcq,Rcqq,Rcqq,Rcw, w, w")
+ (ashift:SI (match_operand:SI 1 "nonmemory_operand" "!0,Rcqq, 0, 0, c,cCal")
+ (match_operand:SI 2 "nonmemory_operand" "K, K,RcqqM, cL,cL,cCal")))]
+ "TARGET_BARREL_SHIFTER
+ && (register_operand (operands[1], SImode)
+ || register_operand (operands[2], SImode))"
+ "asl%? %0,%1,%2%&"
+ [(set_attr "type" "shift")
+ (set_attr "iscompact" "maybe,maybe,maybe,false,false,false")
+ (set_attr "predicable" "no,no,no,yes,no,no")
+ (set_attr "cond" "canuse,nocond,canuse,canuse,nocond,nocond")])
+
+(define_insn "*ashrsi3_insn"
+ [(set (match_operand:SI 0 "dest_reg_operand" "=Rcq,Rcqq,Rcqq,Rcw, w, w")
+ (ashiftrt:SI (match_operand:SI 1 "nonmemory_operand" "!0,Rcqq, 0, 0, c,cCal")
+ (match_operand:SI 2 "nonmemory_operand" "K, K,RcqqM, cL,cL,cCal")))]
+ "TARGET_BARREL_SHIFTER
+ && (register_operand (operands[1], SImode)
+ || register_operand (operands[2], SImode))"
+ "asr%? %0,%1,%2%&"
+ [(set_attr "type" "shift")
+ (set_attr "iscompact" "maybe,maybe,maybe,false,false,false")
+ (set_attr "predicable" "no,no,no,yes,no,no")
+ (set_attr "cond" "canuse,nocond,canuse,canuse,nocond,nocond")])
+
+(define_insn "*lshrsi3_insn"
+ [(set (match_operand:SI 0 "dest_reg_operand" "=Rcq,Rcqq,Rcqq,Rcw, w, w")
+ (lshiftrt:SI (match_operand:SI 1 "nonmemory_operand" "!0,Rcqq, 0, 0, c,cCal")
+ (match_operand:SI 2 "nonmemory_operand" "N, N,RcqqM, cL,cL,cCal")))]
+ "TARGET_BARREL_SHIFTER
+ && (register_operand (operands[1], SImode)
+ || register_operand (operands[2], SImode))"
+ "*return (which_alternative <= 1 && !arc_ccfsm_cond_exec_p ()
+ ? \"lsr%? %0,%1%&\" : \"lsr%? %0,%1,%2%&\");"
+ [(set_attr "type" "shift")
+ (set_attr "iscompact" "maybe,maybe,maybe,false,false,false")
+ (set_attr "predicable" "no,no,no,yes,no,no")
+ (set_attr "cond" "canuse,nocond,canuse,canuse,nocond,nocond")])
+
+(define_insn "rotrsi3"
+ [(set (match_operand:SI 0 "dest_reg_operand" "=Rcw, w, w")
+ (rotatert:SI (match_operand:SI 1 "register_operand" " 0,cL,cCal")
+ (match_operand:SI 2 "nonmemory_operand" "cL,cL,cCal")))]
+ "TARGET_BARREL_SHIFTER"
+ "ror%? %0,%1,%2"
+ [(set_attr "type" "shift,shift,shift")
+ (set_attr "predicable" "yes,no,no")
+ (set_attr "length" "4,4,8")])
+
+;; Compare / branch instructions.
+
+(define_expand "cbranchsi4"
+ [(set (reg:CC CC_REG)
+ (compare:CC (match_operand:SI 1 "nonmemory_operand" "")
+ (match_operand:SI 2 "nonmemory_operand" "")))
+ (set (pc)
+ (if_then_else
+ (match_operator 0 "ordered_comparison_operator" [(reg CC_REG)
+ (const_int 0)])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
+ ""
+{
+ gcc_assert (XEXP (operands[0], 0) == operands[1]);
+ gcc_assert (XEXP (operands[0], 1) == operands[2]);
+ operands[0] = gen_compare_reg (operands[0], VOIDmode);
+ emit_jump_insn (gen_branch_insn (operands[3], operands[0]));
+ DONE;
+})
+
+;; ??? Could add a peephole to generate compare with swapped operands and
+;; modifed cc user if second, but not first operand is a compact register.
+(define_insn "cmpsi_cc_insn_mixed"
+ [(set (reg:CC CC_REG)
+ (compare:CC (match_operand:SI 0 "register_operand" "Rcq#q,c,c, qRcq, c")
+ (match_operand:SI 1 "nonmemory_operand" "cO,cI,cL, Cal, Cal")))]
+ ""
+ "cmp%? %0,%B1%&"
+ [(set_attr "type" "compare")
+ (set_attr "iscompact" "true,false,false,true_limm,false")
+ (set_attr "predicable" "no,no,yes,no,yes")
+ (set_attr "cond" "set")
+ (set_attr "length" "*,4,4,*,8")])
+
+(define_insn "*cmpsi_cc_zn_insn"
+ [(set (reg:CC_ZN CC_REG)
+ (compare:CC_ZN (match_operand:SI 0 "register_operand" "qRcq,c")
+ (const_int 0)))]
+ ""
+ "tst%? %0,%0%&"
+ [(set_attr "type" "compare,compare")
+ (set_attr "iscompact" "true,false")
+ (set_attr "predicable" "no,yes")
+ (set_attr "cond" "set_zn")
+ (set_attr "length" "*,4")])
+
+; combiner pattern observed for unwind-dw2-fde.c:linear_search_fdes.
+(define_insn "*btst"
+ [(set (reg:CC_ZN CC_REG)
+ (compare:CC_ZN
+ (zero_extract:SI (match_operand:SI 0 "register_operand" "Rcqq,c")
+ (const_int 1)
+ (match_operand:SI 1 "nonmemory_operand" "L,Lc"))
+ (const_int 0)))]
+ ""
+ "btst%? %0,%1"
+ [(set_attr "iscompact" "true,false")
+ (set_attr "predicable" "no,yes")
+ (set_attr "cond" "set")
+ (set_attr "type" "compare")
+ (set_attr "length" "*,4")])
+
+; combine suffers from 'simplifications' that replace a one-bit zero
+; extract with a shift if it can prove that the upper bits are zero.
+; arc_reorg sees the code after sched2, which can have caused our
+; inputs to be clobbered even if they were not clobbered before.
+; Therefore, add a third way to convert btst / b{eq,ne} to bbit{0,1}
+; OTOH, this is somewhat marginal, and can leat to out-of-range
+; bbit (i.e. bad scheduling) and missed conditional execution,
+; so make this an option.
+(define_peephole2
+ [(set (reg:CC_ZN CC_REG)
+ (compare:CC_ZN
+ (zero_extract:SI (match_operand:SI 0 "register_operand" "")
+ (const_int 1)
+ (match_operand:SI 1 "nonmemory_operand" ""))
+ (const_int 0)))
+ (set (pc)
+ (if_then_else (match_operator 3 "equality_comparison_operator"
+ [(reg:CC_ZN CC_REG) (const_int 0)])
+ (label_ref (match_operand 2 "" ""))
+ (pc)))]
+ "TARGET_BBIT_PEEPHOLE && peep2_regno_dead_p (2, CC_REG)"
+ [(parallel [(set (pc)
+ (if_then_else
+ (match_op_dup 3
+ [(zero_extract:SI (match_dup 0)
+ (const_int 1) (match_dup 1))
+ (const_int 0)])
+ (label_ref (match_dup 2))
+ (pc)))
+ (clobber (reg:CC_ZN CC_REG))])])
+
+(define_insn "*cmpsi_cc_z_insn"
+ [(set (reg:CC_Z CC_REG)
+ (compare:CC_Z (match_operand:SI 0 "register_operand" "qRcq,c")
+ (match_operand:SI 1 "p2_immediate_operand" "O,n")))]
+ ""
+ "@
+ cmp%? %0,%1%&
+ bxor.f 0,%0,%z1"
+ [(set_attr "type" "compare,compare")
+ (set_attr "iscompact" "true,false")
+ (set_attr "cond" "set,set_zn")
+ (set_attr "length" "*,4")])
+
+(define_insn "*cmpsi_cc_c_insn"
+ [(set (reg:CC_C CC_REG)
+ (compare:CC_C (match_operand:SI 0 "register_operand" "Rcqq, c,Rcqq, c")
+ (match_operand:SI 1 "nonmemory_operand" "cO, cI, Cal,Cal")))]
+ ""
+ "cmp%? %0,%S1%&"
+ [(set_attr "type" "compare")
+ (set_attr "iscompact" "true,false,true_limm,false")
+ (set_attr "cond" "set")
+ (set_attr "length" "*,4,*,8")])
+
+;; Next come the scc insns.
+
+(define_expand "cstoresi4"
+ [(set (reg:CC CC_REG)
+ (compare:CC (match_operand:SI 2 "nonmemory_operand" "")
+ (match_operand:SI 3 "nonmemory_operand" "")))
+ (set (match_operand:SI 0 "dest_reg_operand" "")
+ (match_operator:SI 1 "ordered_comparison_operator" [(reg CC_REG)
+ (const_int 0)]))]
+ ""
+{
+ gcc_assert (XEXP (operands[1], 0) == operands[2]);
+ gcc_assert (XEXP (operands[1], 1) == operands[3]);
+ operands[1] = gen_compare_reg (operands[1], SImode);
+ emit_insn (gen_scc_insn (operands[0], operands[1]));
+ DONE;
+})
+
+(define_mode_iterator SDF [SF DF])
+
+(define_expand "cstore<mode>4"
+ [(set (reg:CC CC_REG)
+ (compare:CC (match_operand:SDF 2 "register_operand" "")
+ (match_operand:SDF 3 "register_operand" "")))
+ (set (match_operand:SI 0 "dest_reg_operand" "")
+ (match_operator:SI 1 "comparison_operator" [(reg CC_REG)
+ (const_int 0)]))]
+
+ "TARGET_OPTFPE"
+{
+ gcc_assert (XEXP (operands[1], 0) == operands[2]);
+ gcc_assert (XEXP (operands[1], 1) == operands[3]);
+ operands[1] = gen_compare_reg (operands[1], SImode);
+ emit_insn (gen_scc_insn (operands[0], operands[1]));
+ DONE;
+})
+
+; We need a separate expander for this lest we loose the mode of CC_REG
+; when match_operator substitutes the literal operand into the comparison.
+(define_expand "scc_insn"
+ [(set (match_operand:SI 0 "dest_reg_operand" "=w") (match_operand:SI 1 ""))])
+
+(define_insn_and_split "*scc_insn"
+ [(set (match_operand:SI 0 "dest_reg_operand" "=w")
+ (match_operator:SI 1 "proper_comparison_operator" [(reg CC_REG) (const_int 0)]))]
+ ""
+ "#"
+ "reload_completed"
+ [(set (match_dup 0) (const_int 1))
+ (cond_exec
+ (match_dup 1)
+ (set (match_dup 0) (const_int 0)))]
+{
+ operands[1]
+ = gen_rtx_fmt_ee (REVERSE_CONDITION (GET_CODE (operands[1]),
+ GET_MODE (XEXP (operands[1], 0))),
+ VOIDmode,
+ XEXP (operands[1], 0), XEXP (operands[1], 1));
+}
+ [(set_attr "type" "unary")])
+
+;; ??? At least for ARC600, we should use sbc b,b,s12 if we want a value
+;; that is one lower if the carry flag is set.
+
+;; ??? Look up negscc insn. See pa.md for example.
+(define_insn "*neg_scc_insn"
+ [(set (match_operand:SI 0 "dest_reg_operand" "=w")
+ (neg:SI (match_operator:SI 1 "proper_comparison_operator"
+ [(reg CC_REG) (const_int 0)])))]
+ ""
+ "mov %0,-1\;sub.%D1 %0,%0,%0"
+ [(set_attr "type" "unary")
+ (set_attr "length" "8")])
+
+(define_insn "*not_scc_insn"
+ [(set (match_operand:SI 0 "dest_reg_operand" "=w")
+ (not:SI (match_operator:SI 1 "proper_comparison_operator"
+ [(reg CC_REG) (const_int 0)])))]
+ ""
+ "mov %0,1\;sub.%d1 %0,%0,%0"
+ [(set_attr "type" "unary")
+ (set_attr "length" "8")])
+
+; cond_exec patterns
+(define_insn "*movsi_ne"
+ [(cond_exec
+ (ne (match_operand:CC_Z 2 "cc_use_register" "Rcc,Rcc,Rcc") (const_int 0))
+ (set (match_operand:SI 0 "dest_reg_operand" "=Rcq#q,w,w")
+ (match_operand:SI 1 "nonmemory_operand" "C_0,Lc,?Cal")))]
+ ""
+ "@
+ * current_insn_predicate = 0; return \"sub%?.ne %0,%0,%0%&\";
+ mov.ne %0,%1
+ mov.ne %0,%S1"
+ [(set_attr "type" "cmove,cmove,cmove")
+ (set_attr "iscompact" "true,false,false")
+ (set_attr "length" "2,4,8")])
+
+(define_insn "*movsi_cond_exec"
+ [(cond_exec
+ (match_operator 3 "proper_comparison_operator"
+ [(match_operand 2 "cc_register" "Rcc,Rcc") (const_int 0)])
+ (set (match_operand:SI 0 "dest_reg_operand" "=w,w")
+ (match_operand:SI 1 "nonmemory_operand" "Lc,?Cal")))]
+ ""
+ "mov.%d3 %0,%S1"
+ [(set_attr "type" "cmove")
+ (set_attr "length" "4,8")])
+
+(define_insn "*commutative_cond_exec"
+ [(cond_exec
+ (match_operator 5 "proper_comparison_operator"
+ [(match_operand 4 "cc_register" "Rcc,Rcc") (const_int 0)])
+ (set (match_operand:SI 0 "dest_reg_operand" "=w,w")
+ (match_operator:SI 3 "commutative_operator"
+ [(match_operand:SI 1 "register_operand" "%0,0")
+ (match_operand:SI 2 "nonmemory_operand" "cL,?Cal")])))]
+ ""
+{
+ arc_output_commutative_cond_exec (operands, true);
+ return "";
+}
+ [(set_attr "cond" "use")
+ (set_attr "type" "cmove")
+ (set_attr_alternative "length"
+ [(const_int 4)
+ (cond
+ [(eq (symbol_ref "arc_output_commutative_cond_exec (operands, false)")
+ (const_int 4))
+ (const_int 4)]
+ (const_int 8))])])
+
+(define_insn "*sub_cond_exec"
+ [(cond_exec
+ (match_operator 4 "proper_comparison_operator"
+ [(match_operand 3 "cc_register" "Rcc,Rcc,Rcc") (const_int 0)])
+ (set (match_operand:SI 0 "dest_reg_operand" "=w,w,w")
+ (minus:SI (match_operand:SI 1 "nonmemory_operand" "0,cL,Cal")
+ (match_operand:SI 2 "nonmemory_operand" "cL,0,0"))))]
+ ""
+ "@
+ sub.%d4 %0,%1,%2
+ rsub.%d4 %0,%2,%1
+ rsub.%d4 %0,%2,%1"
+ [(set_attr "cond" "use")
+ (set_attr "type" "cmove")
+ (set_attr "length" "4,4,8")])
+
+(define_insn "*noncommutative_cond_exec"
+ [(cond_exec
+ (match_operator 5 "proper_comparison_operator"
+ [(match_operand 4 "cc_register" "Rcc,Rcc") (const_int 0)])
+ (set (match_operand:SI 0 "dest_reg_operand" "=w,w")
+ (match_operator:SI 3 "noncommutative_operator"
+ [(match_operand:SI 1 "register_operand" "0,0")
+ (match_operand:SI 2 "nonmemory_operand" "cL,Cal")])))]
+ ""
+ "%O3.%d5 %0,%1,%2"
+ [(set_attr "cond" "use")
+ (set_attr "type" "cmove")
+ (set_attr "length" "4,8")])
+
+;; These control RTL generation for conditional jump insns
+;; Match both normal and inverted jump.
+
+; We need a separate expander for this lest we loose the mode of CC_REG
+; when match_operator substitutes the literal operand into the comparison.
+(define_expand "branch_insn"
+ [(set (pc)
+ (if_then_else (match_operand 1 "" "")
+ (label_ref (match_operand 0 "" ""))
+ (pc)))])
+
+; When estimating sizes during arc_reorg, when optimizing for speed, there
+; are three reasons why we need to consider branches to be length 6:
+; - annull-false delay slot insns are implemented using conditional execution,
+; thus preventing short insn formation where used.
+; - for ARC600: annull-true delay slot isnns are implemented where possile
+; using conditional execution, preventing short insn formation where used.
+; - for ARC700: likely or somewhat likely taken branches are made long and
+; unaligned if possible to avoid branch penalty.
+(define_insn "*branch_insn"
+ [(set (pc)
+ (if_then_else (match_operator 1 "proper_comparison_operator"
+ [(reg CC_REG) (const_int 0)])
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+{
+ if (arc_ccfsm_branch_deleted_p ())
+ {
+ arc_ccfsm_record_branch_deleted ();
+ return \"; branch deleted, next insns conditionalized\";
+ }
+ else
+ {
+ arc_ccfsm_record_condition (operands[1], false, insn, 0);
+ if (get_attr_length (insn) == 2)
+ return \"b%d1%? %^%l0%&\";
+ else
+ return \"b%d1%# %^%l0\";
+ }
+}"
+ [(set_attr "type" "branch")
+ (set
+ (attr "length")
+ (cond [
+ (eq_attr "delay_slot_filled" "yes")
+ (const_int 4)
+
+ (ne
+ (if_then_else
+ (match_operand 1 "equality_comparison_operator" "")
+ (ior (lt (minus (match_dup 0) (pc)) (const_int -512))
+ (gt (minus (match_dup 0) (pc))
+ (minus (const_int 506)
+ (symbol_ref "get_attr_delay_slot_length (insn)"))))
+ (ior (match_test "!arc_short_comparison_p (operands[1], -64)")
+ (lt (minus (match_dup 0) (pc)) (const_int -64))
+ (gt (minus (match_dup 0) (pc))
+ (minus (const_int 58)
+ (symbol_ref "get_attr_delay_slot_length (insn)")))))
+ (const_int 0))
+ (const_int 4)]
+ (const_int 2)))
+
+ (set (attr "iscompact")
+ (cond [(match_test "get_attr_length (insn) == 2") (const_string "true")]
+ (const_string "false")))])
+
+(define_insn "*rev_branch_insn"
+ [(set (pc)
+ (if_then_else (match_operator 1 "proper_comparison_operator"
+ [(reg CC_REG) (const_int 0)])
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ "REVERSIBLE_CC_MODE (GET_MODE (XEXP (operands[1], 0)))"
+ "*
+{
+ if (arc_ccfsm_branch_deleted_p ())
+ {
+ arc_ccfsm_record_branch_deleted ();
+ return \"; branch deleted, next insns conditionalized\";
+ }
+ else
+ {
+ arc_ccfsm_record_condition (operands[1], true, insn, 0);
+ if (get_attr_length (insn) == 2)
+ return \"b%D1%? %^%l0\";
+ else
+ return \"b%D1%# %^%l0\";
+ }
+}"
+ [(set_attr "type" "branch")
+ (set
+ (attr "length")
+ (cond [
+ (eq_attr "delay_slot_filled" "yes")
+ (const_int 4)
+
+ (ne
+ (if_then_else
+ (match_operand 1 "equality_comparison_operator" "")
+ (ior (lt (minus (match_dup 0) (pc)) (const_int -512))
+ (gt (minus (match_dup 0) (pc))
+ (minus (const_int 506)
+ (symbol_ref "get_attr_delay_slot_length (insn)"))))
+ (ior (match_test "!arc_short_comparison_p (operands[1], -64)")
+ (lt (minus (match_dup 0) (pc)) (const_int -64))
+ (gt (minus (match_dup 0) (pc))
+ (minus (const_int 58)
+ (symbol_ref "get_attr_delay_slot_length (insn)")))))
+ (const_int 0))
+ (const_int 4)]
+ (const_int 2)))
+
+ (set (attr "iscompact")
+ (cond [(match_test "get_attr_length (insn) == 2") (const_string "true")]
+ (const_string "false")))])
+
+;; Unconditional and other jump instructions.
+
+(define_expand "jump"
+ [(set (pc) (label_ref (match_operand 0 "" "")))]
+ ""
+ "")
+
+(define_insn "jump_i"
+ [(set (pc) (label_ref (match_operand 0 "" "")))]
+ "!TARGET_LONG_CALLS_SET || !find_reg_note (insn, REG_CROSSING_JUMP, NULL_RTX)"
+ "b%!%* %^%l0%&"
+ [(set_attr "type" "uncond_branch")
+ (set (attr "iscompact")
+ (if_then_else (match_test "get_attr_length (insn) == 2")
+ (const_string "true") (const_string "false")))
+ (set_attr "cond" "canuse")
+ (set (attr "length")
+ (cond [
+ ; In arc_reorg we just guesstimate; might be more or less than 4.
+ (match_test "arc_branch_size_unknown_p ()")
+ (const_int 4)
+
+ (eq_attr "delay_slot_filled" "yes")
+ (const_int 4)
+
+ (match_test "find_reg_note (insn, REG_CROSSING_JUMP, NULL_RTX)")
+ (const_int 4)
+
+ (ior (lt (minus (match_dup 0) (pc)) (const_int -512))
+ (gt (minus (match_dup 0) (pc))
+ (minus (const_int 506)
+ (symbol_ref "get_attr_delay_slot_length (insn)"))))
+ (const_int 4)]
+ (const_int 2)))])
+
+(define_insn "indirect_jump"
+ [(set (pc) (match_operand:SI 0 "nonmemory_operand" "L,I,Cal,Rcqq,r"))]
+ ""
+ "j%!%* [%0]%&"
+ [(set_attr "type" "jump")
+ (set_attr "iscompact" "false,false,false,maybe,false")
+ (set_attr "cond" "canuse,canuse_limm,canuse,canuse,canuse")])
+
+;; Implement a switch statement.
+
+(define_expand "casesi"
+ [(set (match_dup 5)
+ (minus:SI (match_operand:SI 0 "register_operand" "")
+ (match_operand:SI 1 "nonmemory_operand" "")))
+ (set (reg:CC CC_REG)
+ (compare:CC (match_dup 5)
+ (match_operand:SI 2 "nonmemory_operand" "")))
+ (set (pc)
+ (if_then_else (gtu (reg:CC CC_REG)
+ (const_int 0))
+ (label_ref (match_operand 4 "" ""))
+ (pc)))
+ (set (match_dup 6)
+ (unspec:SI [(match_operand 3 "" "")
+ (match_dup 5) (match_dup 7)] UNSPEC_CASESI))
+ (parallel [(set (pc) (match_dup 6)) (use (match_dup 7))])]
+ ""
+ "
+{
+ rtx x;
+
+ operands[5] = gen_reg_rtx (SImode);
+ operands[6] = gen_reg_rtx (SImode);
+ operands[7] = operands[3];
+ emit_insn (gen_subsi3 (operands[5], operands[0], operands[1]));
+ emit_insn (gen_cmpsi_cc_insn_mixed (operands[5], operands[2]));
+ x = gen_rtx_GTU (VOIDmode, gen_rtx_REG (CCmode, CC_REG), const0_rtx);
+ x = gen_rtx_IF_THEN_ELSE (VOIDmode, x,
+ gen_rtx_LABEL_REF (VOIDmode, operands[4]), pc_rtx);
+ emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, x));
+ if (TARGET_COMPACT_CASESI)
+ {
+ emit_jump_insn (gen_casesi_compact_jump (operands[5], operands[7]));
+ }
+ else
+ {
+ operands[3] = gen_rtx_LABEL_REF (VOIDmode, operands[3]);
+ if (flag_pic || !cse_not_expected)
+ operands[3] = force_reg (Pmode, operands[3]);
+ emit_insn (gen_casesi_load (operands[6],
+ operands[3], operands[5], operands[7]));
+ if (CASE_VECTOR_PC_RELATIVE || flag_pic)
+ emit_insn (gen_addsi3 (operands[6], operands[6], operands[3]));
+ emit_jump_insn (gen_casesi_jump (operands[6], operands[7]));
+ }
+ DONE;
+}")
+
+(define_insn "casesi_load"
+ [(set (match_operand:SI 0 "register_operand" "=Rcq,r,r")
+ (unspec:SI [(match_operand:SI 1 "nonmemory_operand" "Rcq,c,Cal")
+ (match_operand:SI 2 "register_operand" "Rcq,c,c")
+ (label_ref (match_operand 3 "" ""))] UNSPEC_CASESI))]
+ ""
+ "*
+{
+ rtx diff_vec = PATTERN (next_nonnote_insn (operands[3]));
+
+ if (GET_CODE (diff_vec) != ADDR_DIFF_VEC)
+ {
+ gcc_assert (GET_CODE (diff_vec) == ADDR_VEC);
+ gcc_assert (GET_MODE (diff_vec) == SImode);
+ gcc_assert (!CASE_VECTOR_PC_RELATIVE && !flag_pic);
+ }
+
+ switch (GET_MODE (diff_vec))
+ {
+ case SImode:
+ return \"ld.as %0,[%1,%2]%&\";
+ case HImode:
+ if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
+ return \"ldw.as %0,[%1,%2]\";
+ return \"ldw.x.as %0,[%1,%2]\";
+ case QImode:
+ if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
+ return \"ldb%? %0,[%1,%2]%&\";
+ return \"ldb.x %0,[%1,%2]\";
+ default:
+ gcc_unreachable ();
+ }
+}"
+ [(set_attr "type" "load")
+ (set_attr_alternative "iscompact"
+ [(cond
+ [(ne (symbol_ref "GET_MODE (PATTERN (next_nonnote_insn (operands[3])))")
+ (symbol_ref "QImode"))
+ (const_string "false")
+ (match_test "!ADDR_DIFF_VEC_FLAGS (PATTERN (next_nonnote_insn (operands[3]))).offset_unsigned")
+ (const_string "false")]
+ (const_string "true"))
+ (const_string "false")
+ (const_string "false")])
+ (set_attr_alternative "length"
+ [(cond
+ [(eq_attr "iscompact" "false") (const_int 4)]
+ (const_int 2))
+ (const_int 4)
+ (const_int 8)])])
+
+; Unlike the canonical tablejump, this pattern always uses a jump address,
+; even for CASE_VECTOR_PC_RELATIVE.
+(define_insn "casesi_jump"
+ [(set (pc) (match_operand:SI 0 "register_operand" "Cal,Rcqq,c"))
+ (use (label_ref (match_operand 1 "" "")))]
+ ""
+ "j%!%* [%0]%&"
+ [(set_attr "type" "jump")
+ (set_attr "iscompact" "false,maybe,false")
+ (set_attr "cond" "canuse")])
+
+(define_insn "casesi_compact_jump"
+ [(set (pc)
+ (unspec:SI [(match_operand:SI 0 "register_operand" "c,q")]
+ UNSPEC_CASESI))
+ (use (label_ref (match_operand 1 "" "")))
+ (clobber (match_scratch:SI 2 "=q,0"))]
+ "TARGET_COMPACT_CASESI"
+ "*
+{
+ rtx diff_vec = PATTERN (next_nonnote_insn (operands[1]));
+ int unalign = arc_get_unalign ();
+ rtx xop[3];
+ const char *s;
+
+ xop[0] = operands[0];
+ xop[2] = operands[2];
+ gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
+
+ switch (GET_MODE (diff_vec))
+ {
+ case SImode:
+ /* Max length can be 12 in this case, but this is OK because
+ 2 of these are for alignment, and are anticipated in the length
+ of the ADDR_DIFF_VEC. */
+ if (unalign && !satisfies_constraint_Rcq (xop[0]))
+ s = \"add2 %2,pcl,%0\n\tld_s%2,[%2,12]\";
+ else if (unalign)
+ s = \"add_s %2,%0,2\n\tld.as %2,[pcl,%2]\";
+ else
+ s = \"add %2,%0,2\n\tld.as %2,[pcl,%2]\";
+ arc_clear_unalign ();
+ break;
+ case HImode:
+ if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
+ {
+ if (satisfies_constraint_Rcq (xop[0]))
+ {
+ s = \"add_s %2,%0,%1\n\tldw.as %2,[pcl,%2]\";
+ xop[1] = GEN_INT ((10 - unalign) / 2U);
+ }
+ else
+ {
+ s = \"add1 %2,pcl,%0\n\tldw_s %2,[%2,%1]\";
+ xop[1] = GEN_INT (10 + unalign);
+ }
+ }
+ else
+ {
+ if (satisfies_constraint_Rcq (xop[0]))
+ {
+ s = \"add_s %2,%0,%1\n\tldw.x.as %2,[pcl,%2]\";
+ xop[1] = GEN_INT ((10 - unalign) / 2U);
+ }
+ else
+ {
+ s = \"add1 %2,pcl,%0\n\tldw_s.x %2,[%2,%1]\";
+ xop[1] = GEN_INT (10 + unalign);
+ }
+ }
+ arc_toggle_unalign ();
+ break;
+ case QImode:
+ if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
+ {
+ if ((rtx_equal_p (xop[2], xop[0])
+ || find_reg_note (insn, REG_DEAD, xop[0]))
+ && satisfies_constraint_Rcq (xop[0]))
+ {
+ s = \"add_s %0,%0,pcl\n\tldb_s %2,[%0,%1]\";
+ xop[1] = GEN_INT (8 + unalign);
+ }
+ else
+ {
+ s = \"add %2,%0,pcl\n\tldb_s %2,[%2,%1]\";
+ xop[1] = GEN_INT (10 + unalign);
+ arc_toggle_unalign ();
+ }
+ }
+ else if ((rtx_equal_p (xop[0], xop[2])
+ || find_reg_note (insn, REG_DEAD, xop[0]))
+ && satisfies_constraint_Rcq (xop[0]))
+ {
+ s = \"add_s %0,%0,%1\n\tldb.x %2,[pcl,%0]\";
+ xop[1] = GEN_INT (10 - unalign);
+ arc_toggle_unalign ();
+ }
+ else
+ {
+ /* ??? Length is 12. */
+ s = \"add %2,%0,%1\n\tldb.x %2,[pcl,%2]\";
+ xop[1] = GEN_INT (8 + unalign);
+ }
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ output_asm_insn (s, xop);
+ return \"add_s %2,%2,pcl\n\tj_s%* [%2]\";
+}"
+ [(set_attr "length" "10")
+ (set_attr "type" "jump")
+ (set_attr "iscompact" "true")
+ (set_attr "cond" "nocond")])
+
+(define_expand "call"
+ ;; operands[1] is stack_size_rtx
+ ;; operands[2] is next_arg_register
+ [(parallel [(call (match_operand:SI 0 "call_operand" "")
+ (match_operand 1 "" ""))
+ (clobber (reg:SI 31))])]
+ ""
+ "{
+ rtx callee;
+
+ gcc_assert (MEM_P (operands[0]));
+ callee = XEXP (operands[0], 0);
+ if (crtl->profile && arc_profile_call (callee))
+ {
+ emit_call_insn (gen_call_prof (gen_rtx_SYMBOL_REF (Pmode,
+ \"_mcount_call\"),
+ operands[1]));
+ DONE;
+ }
+ /* This is to decide if we should generate indirect calls by loading the
+ 32 bit address of the callee into a register before performing the
+ branch and link - this exposes cse opportunities.
+ Also, in weird cases like compile/20010107-1.c, we may get a PLUS. */
+ if (GET_CODE (callee) != REG
+ && (GET_CODE (callee) == PLUS || arc_is_longcall_p (callee)))
+ XEXP (operands[0], 0) = force_reg (Pmode, callee);
+ }
+")
+
+
+; Rcq, which is used in alternative 0, checks for conditional execution.
+; At instruction output time, if it doesn't match and we end up with
+; alternative 1 ("q"), that means that we can't use the short form.
+(define_insn "*call_i"
+ [(call (mem:SI (match_operand:SI 0
+ "call_address_operand" "Rcq,q,c,Cbp,Cbr,L,I,Cal"))
+ (match_operand 1 "" ""))
+ (clobber (reg:SI 31))]
+ ""
+ "@
+ jl%!%* [%0]%&
+ jl%!%* [%0]%&
+ jl%!%* [%0]
+ bl%!%* %P0
+ bl%!%* %P0
+ jl%!%* %S0
+ jl%* %S0
+ jl%! %S0"
+ [(set_attr "type" "call,call,call,call,call,call,call,call_no_delay_slot")
+ (set_attr "iscompact" "maybe,false,*,*,*,*,*,*")
+ (set_attr "predicable" "no,no,yes,yes,no,yes,no,yes")
+ (set_attr "length" "*,*,4,4,4,4,4,8")])
+
+(define_insn "call_prof"
+ [(call (mem:SI (match_operand:SI 0 "symbolic_operand" "Cbr,Cal"))
+ (match_operand 1 "" ""))
+ (clobber (reg:SI 31))
+ (use (reg:SI 8))
+ (use (reg:SI 9))]
+ ""
+ "@
+ bl%!%* %P0;2
+ jl%! %^%S0"
+ [(set_attr "type" "call,call_no_delay_slot")
+ (set_attr "predicable" "yes,yes")
+ (set_attr "length" "4,8")])
+
+(define_expand "call_value"
+ ;; operand 2 is stack_size_rtx
+ ;; operand 3 is next_arg_register
+ [(parallel [(set (match_operand 0 "dest_reg_operand" "=r")
+ (call (match_operand:SI 1 "call_operand" "")
+ (match_operand 2 "" "")))
+ (clobber (reg:SI 31))])]
+ ""
+ "
+ {
+ rtx callee;
+
+ gcc_assert (MEM_P (operands[1]));
+ callee = XEXP (operands[1], 0);
+ if (crtl->profile && arc_profile_call (callee))
+ {
+ emit_call_insn (gen_call_value_prof (operands[0],
+ gen_rtx_SYMBOL_REF (Pmode,
+ \"_mcount_call\"),
+ operands[2]));
+ DONE;
+ }
+ /* See the comment in define_expand \"call\". */
+ if (GET_CODE (callee) != REG
+ && (GET_CODE (callee) == PLUS || arc_is_longcall_p (callee)))
+ XEXP (operands[1], 0) = force_reg (Pmode, callee);
+ }")
+
+
+; Rcq, which is used in alternative 0, checks for conditional execution.
+; At instruction output time, if it doesn't match and we end up with
+; alternative 1 ("q"), that means that we can't use the short form.
+(define_insn "*call_value_i"
+ [(set (match_operand 0 "dest_reg_operand" "=Rcq,q,w, w, w,w,w, w")
+ (call (mem:SI (match_operand:SI 1
+ "call_address_operand" "Rcq,q,c,Cbp,Cbr,L,I,Cal"))
+ (match_operand 2 "" "")))
+ (clobber (reg:SI 31))]
+ ""
+ "@
+ jl%!%* [%1]%&
+ jl%!%* [%1]%&
+ jl%!%* [%1]
+ bl%!%* %P1;1
+ bl%!%* %P1;1
+ jl%!%* %S1
+ jl%* %S1
+ jl%! %S1"
+ [(set_attr "type" "call,call,call,call,call,call,call,call_no_delay_slot")
+ (set_attr "iscompact" "maybe,false,*,*,*,*,*,*")
+ (set_attr "predicable" "no,no,yes,yes,no,yes,no,yes")
+ (set_attr "length" "*,*,4,4,4,4,4,8")])
+
+; There is a bl_s instruction (16 bit opcode branch-and-link), but we can't
+; use it for lack of inter-procedural branch shortening.
+; Link-time relaxation would help...
+
+
+(define_insn "call_value_prof"
+ [(set (match_operand 0 "dest_reg_operand" "=r,r")
+ (call (mem:SI (match_operand:SI 1 "symbolic_operand" "Cbr,Cal"))
+ (match_operand 2 "" "")))
+ (clobber (reg:SI 31))
+ (use (reg:SI 8))
+ (use (reg:SI 9))]
+ ""
+ "@
+ bl%!%* %P1;1
+ jl%! %^%S1"
+ [(set_attr "type" "call,call_no_delay_slot")
+ (set_attr "predicable" "yes,yes")
+ (set_attr "length" "4,8")])
+
+(define_insn "nop"
+ [(const_int 0)]
+ ""
+ "nop%?"
+ [(set_attr "type" "misc")
+ (set_attr "iscompact" "true")
+ (set_attr "cond" "canuse")
+ (set_attr "length" "2")])
+
+;; Special pattern to flush the icache.
+;; ??? Not sure what to do here. Some ARC's are known to support this.
+
+(define_insn "flush_icache"
+ [(unspec_volatile [(match_operand:SI 0 "memory_operand" "m")] 0)]
+ ""
+ "* return \"\";"
+ [(set_attr "type" "misc")])
+
+;; Split up troublesome insns for better scheduling.
+
+;; Peepholes go at the end.
+;;asl followed by add can be replaced by an add{1,2,3}
+;; Three define_peepholes have been added for this optimization
+;; ??? This used to target non-canonical rtl. Now we use add_n, which
+;; can be generated by combine. Check if these peepholes still provide
+;; any benefit.
+
+;; -------------------------------------------------------------
+;; Pattern 1 : r0 = r1 << {i}
+;; r3 = r4/INT + r0 ;;and commutative
+;; ||
+;; \/
+;; add{i} r3,r4/INT,r1
+;; -------------------------------------------------------------
+;; ??? This should be covered by combine, alas, at times combine gets
+;; too clever for it's own good: when the shifted input is known to be
+;; either 0 or 1, the operation will be made into an if-then-else, and
+;; thus fail to match the add_n pattern. Example: _mktm_r, line 85 in
+;; newlib/libc/time/mktm_r.c .
+
+(define_peephole2
+ [(set (match_operand:SI 0 "dest_reg_operand" "")
+ (ashift:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "const_int_operand" "")))
+ (set (match_operand:SI 3 "dest_reg_operand" "")
+ (plus:SI (match_operand:SI 4 "nonmemory_operand" "")
+ (match_operand:SI 5 "nonmemory_operand" "")))]
+ "(INTVAL (operands[2]) == 1
+ || INTVAL (operands[2]) == 2
+ || INTVAL (operands[2]) == 3)
+ && (true_regnum (operands[4]) == true_regnum (operands[0])
+ || true_regnum (operands[5]) == true_regnum (operands[0]))
+ && (peep2_reg_dead_p (2, operands[0]) || (true_regnum (operands[3]) == true_regnum (operands[0])))"
+ ;; the preparation statements take care to put proper operand in operands[4]
+ ;; operands[4] will always contain the correct operand. This is added to satisfy commutativity
+ [(set (match_dup 3)
+ (plus:SI (mult:SI (match_dup 1)
+ (match_dup 2))
+ (match_dup 4)))]
+ "if (true_regnum (operands[4]) == true_regnum (operands[0]))
+ operands[4] = operands[5];
+ operands[2] = GEN_INT (1 << INTVAL (operands[2]));"
+)
+
+;; -------------------------------------------------------------
+;; Pattern 1 : r0 = r1 << {i}
+;; r3 = r4 - r0
+;; ||
+;; \/
+;; sub{i} r3,r4,r1
+;; -------------------------------------------------------------
+;; ??? This should be covered by combine, alas, at times combine gets
+;; too clever for it's own good: when the shifted input is known to be
+;; either 0 or 1, the operation will be made into an if-then-else, and
+;; thus fail to match the sub_n pattern. Example: __ieee754_yn, line 239 in
+;; newlib/libm/math/e_jn.c .
+
+(define_peephole2
+ [(set (match_operand:SI 0 "dest_reg_operand" "")
+ (ashift:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "const_int_operand" "")))
+ (set (match_operand:SI 3 "dest_reg_operand" "")
+ (minus:SI (match_operand:SI 4 "nonmemory_operand" "")
+ (match_dup 0)))]
+ "(INTVAL (operands[2]) == 1
+ || INTVAL (operands[2]) == 2
+ || INTVAL (operands[2]) == 3)
+ && (peep2_reg_dead_p (2, operands[0])
+ || (true_regnum (operands[3]) == true_regnum (operands[0])))"
+ [(set (match_dup 3)
+ (minus:SI (match_dup 4)
+ (mult:SI (match_dup 1)
+ (match_dup 2))))]
+ "operands[2] = GEN_INT (1 << INTVAL (operands[2]));"
+)
+
+
+
+; When using the high single bit, the result of a multiply is either
+; the original number or zero. But MPY costs 4 cycles, which we
+; can replace with the 2 cycles for the pair of TST_S and ADD.NE.
+(define_peephole2
+ [(set (match_operand:SI 0 "dest_reg_operand" "")
+ (lshiftrt:SI (match_operand:SI 1 "register_operand" "")
+ (const_int 31)))
+ (set (match_operand:SI 4 "register_operand" "")
+ (mult:SI (match_operand:SI 2 "register_operand")
+ (match_operand:SI 3 "nonmemory_operand" "")))]
+ "TARGET_ARC700 && !TARGET_NOMPY_SET
+ && (rtx_equal_p (operands[0], operands[2])
+ || rtx_equal_p (operands[0], operands[3]))
+ && peep2_regno_dead_p (0, CC_REG)
+ && (rtx_equal_p (operands[0], operands[4])
+ || (peep2_reg_dead_p (2, operands[0])
+ && peep2_reg_dead_p (1, operands[4])))"
+ [(parallel [(set (reg:CC_Z CC_REG)
+ (compare:CC_Z (lshiftrt:SI (match_dup 1) (const_int 31))
+ (const_int 0)))
+ (set (match_dup 4) (lshiftrt:SI (match_dup 1) (const_int 31)))])
+ (cond_exec
+ (ne (reg:CC_Z CC_REG) (const_int 0))
+ (set (match_dup 4) (match_dup 5)))]
+{
+ if (!rtx_equal_p (operands[0], operands[2]))
+ operands[5] = operands[2];
+ else if (!rtx_equal_p (operands[0], operands[3]))
+ operands[5] = operands[3];
+ else
+ operands[5] = operands[4]; /* Actually a no-op... presumably rare. */
+})
+
+(define_peephole2
+ [(set (match_operand:SI 0 "dest_reg_operand" "")
+ (lshiftrt:SI (match_operand:SI 1 "register_operand" "")
+ (const_int 31)))
+ (set (match_operand:SI 4 "register_operand" "")
+ (mult:SI (match_operand:SI 2 "register_operand")
+ (match_operand:SI 3 "nonmemory_operand" "")))]
+ "TARGET_ARC700 && !TARGET_NOMPY_SET
+ && (rtx_equal_p (operands[0], operands[2])
+ || rtx_equal_p (operands[0], operands[3]))
+ && peep2_regno_dead_p (2, CC_REG)"
+ [(parallel [(set (reg:CC_Z CC_REG)
+ (compare:CC_Z (lshiftrt:SI (match_dup 1) (const_int 31))
+ (const_int 0)))
+ (set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 31)))])
+ (set (match_dup 4) (match_dup 5))
+ (cond_exec
+ (eq (reg:CC_Z CC_REG) (const_int 0))
+ (set (match_dup 4) (const_int 0)))]
+ "operands[5] = operands[rtx_equal_p (operands[0], operands[2]) ? 3 : 2];")
+
+;; Instructions generated through builtins
+
+(define_insn "clrsbsi2"
+ [(set (match_operand:SI 0 "dest_reg_operand" "=w,w")
+ (clrsb:SI (match_operand:SI 1 "general_operand" "cL,Cal")))]
+ "TARGET_NORM"
+ "@
+ norm \t%0, %1
+ norm \t%0, %S1"
+ [(set_attr "length" "4,8")
+ (set_attr "type" "two_cycle_core,two_cycle_core")])
+
+(define_insn "norm_f"
+ [(set (match_operand:SI 0 "dest_reg_operand" "=w,w")
+ (clrsb:SI (match_operand:SI 1 "general_operand" "cL,Cal")))
+ (set (reg:CC_ZN CC_REG)
+ (compare:CC_ZN (match_dup 1) (const_int 0)))]
+ "TARGET_NORM"
+ "@
+ norm.f\t%0, %1
+ norm.f\t%0, %S1"
+ [(set_attr "length" "4,8")
+ (set_attr "type" "two_cycle_core,two_cycle_core")])
+
+(define_insn_and_split "clrsbhi2"
+ [(set (match_operand:HI 0 "dest_reg_operand" "=w,w")
+ (clrsb:HI (match_operand:HI 1 "general_operand" "cL,Cal")))]
+ "TARGET_NORM"
+ "#"
+ "reload_completed"
+ [(set (match_dup 0) (zero_extend:SI (clrsb:HI (match_dup 1))))]
+ "operands[0] = simplify_gen_subreg (SImode, operands[0], HImode, 0);")
+
+(define_insn "normw"
+ [(set (match_operand:SI 0 "dest_reg_operand" "=w,w")
+ (zero_extend:SI
+ (clrsb:HI (match_operand:HI 1 "general_operand" "cL,Cal"))))]
+ "TARGET_NORM"
+ "@
+ normw \t%0, %1
+ normw \t%0, %S1"
+ [(set_attr "length" "4,8")
+ (set_attr "type" "two_cycle_core,two_cycle_core")])
+
+(define_expand "clzsi2"
+ [(set (match_operand:SI 0 "dest_reg_operand" "")
+ (clz:SI (match_operand:SI 1 "register_operand" "")))]
+ "TARGET_NORM"
+{
+ emit_insn (gen_norm_f (operands[0], operands[1]));
+ emit_insn
+ (gen_rtx_COND_EXEC
+ (VOIDmode,
+ gen_rtx_LT (VOIDmode, gen_rtx_REG (CC_ZNmode, CC_REG), const0_rtx),
+ gen_rtx_SET (VOIDmode, operands[0], const0_rtx)));
+ emit_insn
+ (gen_rtx_COND_EXEC
+ (VOIDmode,
+ gen_rtx_GE (VOIDmode, gen_rtx_REG (CC_ZNmode, CC_REG), const0_rtx),
+ gen_rtx_SET (VOIDmode, operands[0],
+ plus_constant (SImode, operands[0], 1))));
+ DONE;
+})
+
+(define_expand "ctzsi2"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (ctz:SI (match_operand:SI 1 "register_operand" "")))]
+ "TARGET_NORM"
+{
+ rtx temp = operands[0];
+
+ if (reg_overlap_mentioned_p (temp, operands[1])
+ || (REGNO (temp) < FIRST_PSEUDO_REGISTER
+ && !TEST_HARD_REG_BIT (reg_class_contents[GENERAL_REGS],
+ REGNO (temp))))
+ temp = gen_reg_rtx (SImode);
+ emit_insn (gen_addsi3 (temp, operands[1], constm1_rtx));
+ emit_insn (gen_bic_f_zn (temp, temp, operands[1]));
+ emit_insn (gen_clrsbsi2 (temp, temp));
+ emit_insn
+ (gen_rtx_COND_EXEC
+ (VOIDmode,
+ gen_rtx_LT (VOIDmode, gen_rtx_REG (CC_ZNmode, CC_REG), const0_rtx),
+ gen_rtx_SET (VOIDmode, operands[0], GEN_INT (32))));
+ emit_insn
+ (gen_rtx_COND_EXEC
+ (VOIDmode,
+ gen_rtx_GE (VOIDmode, gen_rtx_REG (CC_ZNmode, CC_REG), const0_rtx),
+ gen_rtx_SET (VOIDmode, operands[0],
+ gen_rtx_MINUS (SImode, GEN_INT (31), temp))));
+ DONE;
+})
+
+
+(define_insn "swap"
+ [(set (match_operand:SI 0 "dest_reg_operand" "=w,w,w")
+ (unspec:SI [(match_operand:SI 1 "general_operand" "L,Cal,c")]
+ UNSPEC_SWAP))]
+ "TARGET_SWAP"
+ "@
+ swap \t%0, %1
+ swap \t%0, %S1
+ swap \t%0, %1"
+ [(set_attr "length" "4,8,4")
+ (set_attr "type" "two_cycle_core,two_cycle_core,two_cycle_core")])
+
+;; FIXME: an intrinsic for multiply is daft. Can we remove this?
+(define_insn "mul64"
+ [(unspec [(match_operand:SI 0 "general_operand" "q,r,r,%r")
+ (match_operand:SI 1 "general_operand" "q,rL,I,Cal")]
+ UNSPEC_MUL64)]
+ "TARGET_MUL64_SET"
+ "@
+ mul64%? \t0, %0, %1%&
+ mul64%? \t0, %0, %1
+ mul64 \t0, %0, %1
+ mul64%? \t0, %0, %S1"
+ [(set_attr "length" "2,4,4,8")
+ (set_attr "iscompact" "true,false,false,false")
+ (set_attr "type" "binary,binary,binary,binary")
+ (set_attr "cond" "canuse,canuse, nocond, canuse")])
+
+(define_insn "mulu64"
+ [(unspec [(match_operand:SI 0 "general_operand" "%r,r,r,r")
+ (match_operand:SI 1 "general_operand" "rL,I,r,Cal")]
+ UNSPEC_MULU64)]
+ "TARGET_MUL64_SET"
+ "@
+ mulu64%? \t0, %0, %1
+ mulu64 \t0, %0, %1
+ mulu64 \t0, %0, %1
+ mulu64%? \t0, %0, %S1"
+ [(set_attr "length" "4,4,4,8")
+ (set_attr "type" "binary,binary,binary,binary")
+ (set_attr "cond" "canuse,nocond,nocond,canuse")])
+
+(define_insn "divaw"
+ [(set (match_operand:SI 0 "dest_reg_operand" "=&w,&w,&w")
+ (unspec:SI [(div:SI (match_operand:SI 1 "general_operand" "r,Cal,r")
+ (match_operand:SI 2 "general_operand" "r,r,Cal"))]
+ UNSPEC_DIVAW))]
+ "TARGET_ARC700 || TARGET_EA_SET"
+ "@
+ divaw \t%0, %1, %2
+ divaw \t%0, %S1, %2
+ divaw \t%0, %1, %S2"
+ [(set_attr "length" "4,8,8")
+ (set_attr "type" "divaw,divaw,divaw")])
+
+(define_insn "flag"
+ [(unspec_volatile [(match_operand:SI 0 "nonmemory_operand" "rL,I,Cal")]
+ VUNSPEC_FLAG)]
+ ""
+ "@
+ flag%? %0
+ flag %0
+ flag%? %S0"
+ [(set_attr "length" "4,4,8")
+ (set_attr "type" "misc,misc,misc")
+ (set_attr "predicable" "yes,no,yes")
+ (set_attr "cond" "clob,clob,clob")])
+
+(define_insn "brk"
+ [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "N")]
+ VUNSPEC_BRK)]
+ ""
+ "brk"
+ [(set_attr "length" "4")
+ (set_attr "type" "misc")])
+
+(define_insn "rtie"
+ [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "N")]
+ VUNSPEC_RTIE)]
+ ""
+ "rtie"
+ [(set_attr "length" "4")
+ (set_attr "type" "misc")
+ (set_attr "cond" "clob")])
+
+(define_insn "sync"
+ [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "N")]
+ VUNSPEC_SYNC)]
+ ""
+ "sync"
+ [(set_attr "length" "4")
+ (set_attr "type" "misc")])
+
+(define_insn "swi"
+ [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "N")]
+ VUNSPEC_SWI)]
+ ""
+ "*
+{
+ if(TARGET_ARC700)
+ return \"trap0\";
+ else
+ return \"swi\";
+}"
+ [(set_attr "length" "4")
+ (set_attr "type" "misc")])
+
+
+(define_insn "sleep"
+ [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "L")]
+ VUNSPEC_SLEEP)]
+ "check_if_valid_sleep_operand(operands,0)"
+ "sleep %0"
+ [(set_attr "length" "4")
+ (set_attr "type" "misc")])
+
+(define_insn "core_read"
+ [(set (match_operand:SI 0 "dest_reg_operand" "=r,r")
+ (unspec_volatile:SI [(match_operand:SI 1 "general_operand" "Hn,!r")]
+ VUNSPEC_CORE_READ))]
+ ""
+ "*
+ if (check_if_valid_regno_const (operands, 1))
+ return \"mov \t%0, r%1\";
+ return \"mov \t%0, r%1\";
+ "
+ [(set_attr "length" "4")
+ (set_attr "type" "unary")])
+
+(define_insn "core_write"
+ [(unspec_volatile [(match_operand:SI 0 "general_operand" "r,r")
+ (match_operand:SI 1 "general_operand" "Hn,!r")]
+ VUNSPEC_CORE_WRITE)]
+ ""
+ "*
+ if (check_if_valid_regno_const (operands, 1))
+ return \"mov \tr%1, %0\";
+ return \"mov \tr%1, %0\";
+ "
+ [(set_attr "length" "4")
+ (set_attr "type" "unary")])
+
+(define_insn "lr"
+ [(set (match_operand:SI 0 "dest_reg_operand" "=r,r,r,r")
+ (unspec_volatile:SI [(match_operand:SI 1 "general_operand" "I,HCal,r,D")]
+ VUNSPEC_LR))]
+ ""
+ "lr\t%0, [%1]"
+ [(set_attr "length" "4,8,4,8")
+ (set_attr "type" "lr,lr,lr,lr")])
+
+(define_insn "sr"
+ [(unspec_volatile [(match_operand:SI 0 "general_operand" "Cal,r,r,r")
+ (match_operand:SI 1 "general_operand" "Ir,I,HCal,r")]
+ VUNSPEC_SR)]
+ ""
+ "sr\t%S0, [%1]"
+ [(set_attr "length" "8,4,8,4")
+ (set_attr "type" "sr,sr,sr,sr")])
+
+(define_insn "trap_s"
+ [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "L,Cal")]
+ VUNSPEC_TRAP_S)]
+ "TARGET_ARC700"
+{
+ if (which_alternative == 0)
+ {
+ arc_toggle_unalign ();
+ return \"trap_s %0\";
+ }
+
+ /* Keep this message in sync with the one in arc.c:arc_expand_builtin,
+ because *.md files do not get scanned by exgettext. */
+ fatal_error (\"operand to trap_s should be an unsigned 6-bit value\");
+}
+ [(set_attr "length" "2")
+ (set_attr "type" "misc")])
+
+(define_insn "unimp_s"
+ [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "N")]
+ VUNSPEC_UNIMP_S)]
+ "TARGET_ARC700"
+ "unimp_s"
+ [(set_attr "length" "4")
+ (set_attr "type" "misc")])
+
+;; End of instructions generated through builtins
+
+; Since the demise of REG_N_SETS as reliable data readily available to the
+; target, it is no longer possible to find out
+; in the prologue / epilogue expanders how many times blink is set.
+; Using df_regs_ever_live_p to decide if blink needs saving means that
+; any explicit use of blink will cause it to be saved; hence we cannot
+; represent the blink use in return / sibcall instructions themselves, and
+; instead have to show it in EPILOGUE_USES and must explicitly
+; forbid instructions that change blink in the return / sibcall delay slot.
+(define_expand "sibcall"
+ [(parallel [(call (match_operand 0 "memory_operand" "")
+ (match_operand 1 "general_operand" ""))
+ (simple_return)
+ (use (match_operand 2 "" ""))])]
+ ""
+ "
+ {
+ rtx callee = XEXP (operands[0], 0);
+
+ if (operands[2] == NULL_RTX)
+ operands[2] = const0_rtx;
+ if (crtl->profile && arc_profile_call (callee))
+ {
+ emit_insn (gen_sibcall_prof
+ (gen_rtx_SYMBOL_REF (Pmode, \"_mcount_call\"),
+ operands[1], operands[2]));
+ DONE;
+ }
+ if (GET_CODE (callee) != REG
+ && (GET_CODE (callee) == PLUS || arc_is_longcall_p (callee)))
+ XEXP (operands[0], 0) = force_reg (Pmode, callee);
+ }"
+)
+
+(define_expand "sibcall_value"
+ [(parallel [(set (match_operand 0 "dest_reg_operand" "")
+ (call (match_operand 1 "memory_operand" "")
+ (match_operand 2 "general_operand" "")))
+ (simple_return)
+ (use (match_operand 3 "" ""))])]
+ ""
+ "
+ {
+ rtx callee = XEXP (operands[1], 0);
+
+ if (operands[3] == NULL_RTX)
+ operands[3] = const0_rtx;
+ if (crtl->profile && arc_profile_call (XEXP (operands[1], 0)))
+ {
+ emit_insn (gen_sibcall_value_prof
+ (operands[0], gen_rtx_SYMBOL_REF (Pmode, \"_mcount_call\"),
+ operands[2], operands[3]));
+ DONE;
+ }
+ if (GET_CODE (callee) != REG && arc_is_longcall_p (callee))
+ XEXP (operands[1], 0) = force_reg (Pmode, callee);
+ }"
+)
+
+(define_insn "*sibcall_insn"
+ [(call (mem:SI (match_operand:SI 0 "call_address_operand"
+ "Cbp,Cbr,Rs5,Rsc,Cal"))
+ (match_operand 1 "" ""))
+ (simple_return)
+ (use (match_operand 2 "" ""))]
+ ""
+ "@
+ b%!%* %P0
+ b%!%* %P0
+ j%!%* [%0]%&
+ j%!%* [%0]
+ j%! %P0"
+ [(set_attr "type" "call,call,call,call,call_no_delay_slot")
+ (set_attr "predicable" "yes,no,no,yes,yes")
+ (set_attr "iscompact" "false,false,maybe,false,false")
+ (set_attr "is_SIBCALL" "yes")]
+)
+
+(define_insn "*sibcall_value_insn"
+ [(set (match_operand 0 "dest_reg_operand" "")
+ (call (mem:SI (match_operand:SI 1 "call_address_operand"
+ "Cbp,Cbr,Rs5,Rsc,Cal"))
+ (match_operand 2 "" "")))
+ (simple_return)
+ (use (match_operand 3 "" ""))]
+ ""
+ "@
+ b%!%* %P1
+ b%!%* %P1
+ j%!%* [%1]%&
+ j%!%* [%1]
+ j%! %P1"
+ [(set_attr "type" "call,call,call,call,call_no_delay_slot")
+ (set_attr "predicable" "yes,no,no,yes,yes")
+ (set_attr "iscompact" "false,false,maybe,false,false")
+ (set_attr "is_SIBCALL" "yes")]
+)
+
+(define_insn "sibcall_prof"
+ [(call (mem:SI (match_operand:SI 0 "call_address_operand" "Cbr,Cal"))
+ (match_operand 1 "" ""))
+ (simple_return)
+ (use (match_operand 2 "" ""))
+ (use (reg:SI 8))
+ (use (reg:SI 9))]
+ ""
+ "@
+ b%!%* %P0;2
+ j%! %^%S0;2"
+ [(set_attr "type" "call,call_no_delay_slot")
+ (set_attr "predicable" "yes")
+ (set_attr "is_SIBCALL" "yes")]
+)
+
+(define_insn "sibcall_value_prof"
+ [(set (match_operand 0 "dest_reg_operand" "")
+ (call (mem:SI (match_operand:SI 1 "call_address_operand" "Cbr,Cal"))
+ (match_operand 2 "" "")))
+ (simple_return)
+ (use (match_operand 3 "" ""))
+ (use (reg:SI 8))
+ (use (reg:SI 9))]
+ ""
+ "@
+ b%!%* %P1;1
+ j%! %^%S1;1"
+ [(set_attr "type" "call,call_no_delay_slot")
+ (set_attr "predicable" "yes")
+ (set_attr "is_SIBCALL" "yes")]
+)
+
+(define_expand "prologue"
+ [(pc)]
+ ""
+{
+ arc_expand_prologue ();
+ DONE;
+})
+
+(define_expand "epilogue"
+ [(pc)]
+ ""
+{
+ arc_expand_epilogue (0);
+ DONE;
+})
+
+(define_expand "sibcall_epilogue"
+ [(pc)]
+ ""
+{
+ arc_expand_epilogue (1);
+ DONE;
+})
+
+; Since the demise of REG_N_SETS, it is no longer possible to find out
+; in the prologue / epilogue expanders how many times blink is set.
+; Using df_regs_ever_live_p to decide if blink needs saving means that
+; any explicit use of blink will cause it to be saved; hence we cannot
+; represent the blink use in return / sibcall instructions themselves, and
+; instead have to show it in EPILOGUE_USES and must explicitly
+; forbid instructions that change blink in the return / sibcall delay slot.
+(define_insn "simple_return"
+ [(simple_return)]
+ "reload_completed"
+{
+ rtx reg
+ = gen_rtx_REG (Pmode,
+ arc_return_address_regs[arc_compute_function_type (cfun)]);
+
+ if (TARGET_PAD_RETURN)
+ arc_pad_return ();
+ output_asm_insn (\"j%!%* [%0]%&\", &reg);
+ return \"\";
+}
+ [(set_attr "type" "return")
+ ; predicable won't help here since the canonical rtl looks different
+ ; for branches.
+ (set_attr "cond" "canuse")
+ (set (attr "iscompact")
+ (cond [(eq (symbol_ref "arc_compute_function_type (cfun)")
+ (symbol_ref "ARC_FUNCTION_NORMAL"))
+ (const_string "maybe")]
+ (const_string "false")))
+ (set (attr "length")
+ (cond [(ne (symbol_ref "arc_compute_function_type (cfun)")
+ (symbol_ref "ARC_FUNCTION_NORMAL"))
+ (const_int 4)]
+ (const_int 2)))])
+
+(define_insn "p_return_i"
+ [(set (pc)
+ (if_then_else (match_operator 0 "proper_comparison_operator"
+ [(reg CC_REG) (const_int 0)])
+ (simple_return) (pc)))]
+ "reload_completed"
+{
+ rtx xop[2];
+ xop[0] = operands[0];
+ xop[1]
+ = gen_rtx_REG (Pmode,
+ arc_return_address_regs[arc_compute_function_type (cfun)]);
+
+ if (TARGET_PAD_RETURN)
+ arc_pad_return ();
+ output_asm_insn (\"j%d0%!%# [%1]%&\", xop);
+ /* record the condition in case there is a delay insn. */
+ arc_ccfsm_record_condition (xop[0], false, insn, 0);
+ return \"\";
+}
+ [(set_attr "type" "return")
+ (set_attr "cond" "use")
+ (set (attr "iscompact")
+ (cond [(eq (symbol_ref "arc_compute_function_type (cfun)")
+ (symbol_ref "ARC_FUNCTION_NORMAL"))
+ (const_string "maybe")]
+ (const_string "false")))
+ (set (attr "length")
+ (cond [(ne (symbol_ref "arc_compute_function_type (cfun)")
+ (symbol_ref "ARC_FUNCTION_NORMAL"))
+ (const_int 4)
+ (not (match_operand 0 "equality_comparison_operator" ""))
+ (const_int 4)
+ (eq_attr "delay_slot_filled" "yes")
+ (const_int 4)]
+ (const_int 2)))])
+
+(define_insn_and_split "eh_return"
+ [(eh_return)
+ (use (match_operand:SI 0 "move_src_operand" "rC32,mCalCpc"))
+ (clobber (match_scratch:SI 1 "=X,r"))
+ (clobber (match_scratch:SI 2 "=&r,r"))]
+ ""
+ "#"
+ "reload_completed"
+ [(set (match_dup 2) (match_dup 0))]
+{
+ int offs = arc_return_slot_offset ();
+
+ if (offs < 0)
+ operands[2] = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM);
+ else
+ {
+ if (!register_operand (operands[0], Pmode)
+ && !satisfies_constraint_C32 (operands[0]))
+ {
+ emit_move_insn (operands[1], operands[0]);
+ operands[0] = operands[1];
+ }
+ rtx addr = plus_constant (Pmode, stack_pointer_rtx, offs);
+ if (!strict_memory_address_p (Pmode, addr))
+ {
+ emit_move_insn (operands[2], addr);
+ addr = operands[2];
+ }
+ operands[2] = gen_frame_mem (Pmode, addr);
+ }
+}
+ [(set_attr "length" "12")])
+
+;; ??? #ifdefs in function.c require the presence of this pattern, with a
+;; non-constant predicate.
+(define_expand "return"
+ [(return)]
+ "optimize < 0")
+
+ ;; Comment in final.c (insn_current_reference_address) says
+ ;; forward branch addresses are calculated from the next insn after branch
+ ;; and for backward branches, it is calculated from the branch insn start.
+ ;; The shortening logic here is tuned to accomodate this behaviour
+;; ??? This should be grokked by the ccfsm machinery.
+(define_insn "cbranchsi4_scratch"
+ [(set (pc)
+ (if_then_else (match_operator 0 "proper_comparison_operator"
+ [(match_operand:SI 1 "register_operand" "c,c, c")
+ (match_operand:SI 2 "nonmemory_operand" "L,c,?Cal")])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))
+ (clobber (match_operand 4 "cc_register" ""))]
+ "(reload_completed
+ || (TARGET_EARLY_CBRANCHSI
+ && brcc_nolimm_operator (operands[0], VOIDmode)))
+ && !find_reg_note (insn, REG_CROSSING_JUMP, NULL_RTX)"
+ "*
+ switch (get_attr_length (insn))
+ {
+ case 2: return \"br%d0%? %1, %2, %^%l3%&\";
+ case 4: return \"br%d0%* %1, %B2, %^%l3\";
+ case 8: if (!brcc_nolimm_operator (operands[0], VOIDmode))
+ return \"br%d0%* %1, %B2, %^%l3\";
+ case 6: case 10:
+ case 12:return \"cmp%? %1, %B2\\n\\tb%d0%* %^%l3%&;br%d0 out of range\";
+ default: fprintf (stderr, \"unexpected length %d\\n\", get_attr_length (insn)); fflush (stderr); gcc_unreachable ();
+ }
+ "
+ [(set_attr "cond" "clob, clob, clob")
+ (set (attr "type")
+ (if_then_else
+ (match_test "valid_brcc_with_delay_p (operands)")
+ (const_string "brcc")
+ (const_string "brcc_no_delay_slot")))
+ ; For forward branches, we need to account not only for the distance to
+ ; the target, but also the difference between pcl and pc, the instruction
+ ; length, and any delay insn, if present.
+ (set
+ (attr "length")
+ (cond ; the outer cond does a test independent of branch shortening.
+ [(match_operand 0 "brcc_nolimm_operator" "")
+ (cond
+ [(and (match_operand:CC_Z 4 "cc_register")
+ (eq_attr "delay_slot_filled" "no")
+ (ge (minus (match_dup 3) (pc)) (const_int -128))
+ (le (minus (match_dup 3) (pc))
+ (minus (const_int 122)
+ (symbol_ref "get_attr_delay_slot_length (insn)"))))
+ (const_int 2)
+ (and (ge (minus (match_dup 3) (pc)) (const_int -256))
+ (le (minus (match_dup 3) (pc))
+ (minus (const_int 244)
+ (symbol_ref "get_attr_delay_slot_length (insn)"))))
+ (const_int 4)
+ (match_operand:SI 1 "compact_register_operand" "")
+ (const_int 6)]
+ (const_int 8))]
+ (cond [(and (ge (minus (match_dup 3) (pc)) (const_int -256))
+ (le (minus (match_dup 3) (pc)) (const_int 244)))
+ (const_int 8)
+ (match_operand:SI 1 "compact_register_operand" "")
+ (const_int 10)]
+ (const_int 12))))
+ (set (attr "iscompact")
+ (if_then_else (match_test "get_attr_length (insn) & 2")
+ (const_string "true") (const_string "false")))])
+
+; combiner pattern observed for unwind-dw2-fde.c:linear_search_fdes.
+(define_insn "*bbit"
+ [(set (pc)
+ (if_then_else
+ (match_operator 3 "equality_comparison_operator"
+ [(zero_extract:SI (match_operand:SI 1 "register_operand" "Rcqq,c")
+ (const_int 1)
+ (match_operand:SI 2 "nonmemory_operand" "L,Lc"))
+ (const_int 0)])
+ (label_ref (match_operand 0 "" ""))
+ (pc)))
+ (clobber (reg:CC_ZN CC_REG))]
+ "!find_reg_note (insn, REG_CROSSING_JUMP, NULL_RTX)"
+{
+ switch (get_attr_length (insn))
+ {
+ case 4: return (GET_CODE (operands[3]) == EQ
+ ? \"bbit0%* %1,%2,%0\" : \"bbit1%* %1,%2,%0\");
+ case 6:
+ case 8: return \"btst%? %1,%2\n\tb%d3%* %0; bbit out of range\";
+ default: gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "brcc")
+ (set_attr "cond" "clob")
+ (set (attr "length")
+ (cond [(and (ge (minus (match_dup 0) (pc)) (const_int -254))
+ (le (minus (match_dup 0) (pc))
+ (minus (const_int 248)
+ (symbol_ref "get_attr_delay_slot_length (insn)"))))
+ (const_int 4)
+ (eq (symbol_ref "which_alternative") (const_int 0))
+ (const_int 6)]
+ (const_int 8)))
+ (set (attr "iscompact")
+ (if_then_else (match_test "get_attr_length (insn) == 6")
+ (const_string "true") (const_string "false")))])
+
+; ??? When testing a bit from a DImode register, combine creates a
+; zero_extract in DImode. This goes via an AND with a DImode constant,
+; so can only be observed on 64 bit hosts.
+(define_insn_and_split "*bbit_di"
+ [(set (pc)
+ (if_then_else
+ (match_operator 3 "equality_comparison_operator"
+ [(zero_extract:DI (match_operand:SI 1 "register_operand" "Rcqq,c")
+ (const_int 1)
+ (match_operand 2 "immediate_operand" "L,L"))
+ (const_int 0)])
+ (label_ref (match_operand 0 "" ""))
+ (pc)))
+ (clobber (reg:CC_ZN CC_REG))]
+ "!find_reg_note (insn, REG_CROSSING_JUMP, NULL_RTX)"
+ "#"
+ ""
+ [(parallel
+ [(set (pc) (if_then_else (match_dup 3) (label_ref (match_dup 0)) (pc)))
+ (clobber (reg:CC_ZN CC_REG))])]
+{
+ rtx xtr;
+
+ xtr = gen_rtx_ZERO_EXTRACT (SImode, operands[1], const1_rtx, operands[2]);
+ operands[3] = gen_rtx_fmt_ee (GET_CODE (operands[3]), GET_MODE (operands[3]),
+ xtr, const0_rtx);
+})
+
+; operand 0 is the loop count pseudo register
+; operand 1 is the loop end pattern
+(define_expand "doloop_begin"
+ [(use (match_operand 0 "register_operand" ""))
+ (use (match_operand 1 "" ""))]
+ ""
+{
+ /* Using the INSN_UID of the loop end pattern to identify it causes
+ trouble with -fcompare-debug, so allocate a debug-independent
+ id instead. We use negative numbers so that we can use the same
+ slot in doloop_end_i where we later store a CODE_LABEL_NUMBER, and
+ still be able to tell what kind of number this is. */
+ static HOST_WIDE_INT loop_end_id = 0;
+
+ rtx id = GEN_INT (--loop_end_id);
+ XEXP (XVECEXP (PATTERN (operands[1]), 0, 4), 0) = id;
+ emit_insn (gen_doloop_begin_i (operands[0], const0_rtx, id,
+ const0_rtx, const0_rtx));
+ DONE;
+})
+
+; ??? can't describe the insn properly as then the optimizers try to
+; hoist the SETs.
+;(define_insn "doloop_begin_i"
+; [(set (reg:SI LP_START) (pc))
+; (set (reg:SI LP_END) (unspec:SI [(pc)] UNSPEC_LP))
+; (use (match_operand 0 "const_int_operand" "n"))]
+; ""
+; "lp .L__GCC__LP%0"
+;)
+
+; The operands of doloop_end_i are also read / written by arc_reorg with
+; XVECEXP (PATTERN (lp, 0, N), so if you want to change the pattern, you
+; might have to adjust arc_reorg.
+; operands 0 / 2 are supplied by the expander, 1, 3 and 4 are filled in
+; by arc_reorg. arc_reorg might also alter operand 0.
+;
+; N in XVECEXP PATTERN (lp, 0 N)
+; V rtl purpose
+; 0 unspec UNSPEC_LP identify pattern
+; 1 clobber LP_START show LP_START is set
+; 2 clobber LP_END show LP_END is set
+; 3 use operand0 loop count pseudo register
+; 4 use operand1 before arc_reorg: -id
+; after : CODE_LABEL_NUMBER of loop top label
+; 5 use operand2 INSN_UID of loop end insn
+; 6 use operand3 loop setup not at start (1 above, 2 below)
+; 7 use operand4 LABEL_REF of top label, if not
+; immediately following
+; If operand1 is still zero after arc_reorg, this is an orphaned loop
+; instruction that was not at the start of the loop.
+; There is no point is reloading this insn - then lp_count would still not
+; be available for the loop end.
+(define_insn "doloop_begin_i"
+ [(unspec:SI [(pc)] UNSPEC_LP)
+ (clobber (reg:SI LP_START))
+ (clobber (reg:SI LP_END))
+ (use (match_operand:SI 0 "register_operand" "l,l,????*X"))
+ (use (match_operand 1 "const_int_operand" "n,n,C_0"))
+ (use (match_operand 2 "const_int_operand" "n,n,X"))
+ (use (match_operand 3 "const_int_operand" "C_0,n,X"))
+ (use (match_operand 4 "const_int_operand" "C_0,X,X"))]
+ ""
+{
+ rtx scan;
+ int len, size = 0;
+ int n_insns = 0;
+ rtx loop_start = operands[4];
+
+ if (CONST_INT_P (loop_start))
+ loop_start = NULL_RTX;
+ /* Size implications of the alignment will be taken care of by the
+ alignment inserted at the loop start. */
+ if (LOOP_ALIGN (0) && INTVAL (operands[1]))
+ {
+ asm_fprintf (asm_out_file, "\t.p2align %d\\n", LOOP_ALIGN (0));
+ arc_clear_unalign ();
+ }
+ if (!INTVAL (operands[1]))
+ return "; LITTLE LOST LOOP";
+ if (loop_start && flag_pic)
+ {
+ /* ??? Can do better for when a scratch register
+ is known. But that would require extra testing. */
+ arc_clear_unalign ();
+ return ".p2align 2\;push_s r0\;add r0,pcl,%4-.+2\;sr r0,[2]; LP_START\;add r0,pcl,.L__GCC__LP%1-.+2\;sr r0,[3]; LP_END\;pop_s r0";
+ }
+ /* Check if the loop end is in range to be set by the lp instruction. */
+ size = INTVAL (operands[3]) < 2 ? 0 : 2048;
+ for (scan = insn; scan && size < 2048; scan = NEXT_INSN (scan))
+ {
+ if (!INSN_P (scan))
+ continue;
+ if (recog_memoized (scan) == CODE_FOR_doloop_end_i
+ && (XEXP (XVECEXP (PATTERN (scan), 0, 4), 0)
+ == XEXP (XVECEXP (PATTERN (insn), 0, 4), 0)))
+ break;
+ len = get_attr_length (scan);
+ size += len;
+ }
+ /* Try to verify that there are at least three instruction fetches
+ between the loop setup and the first encounter of the loop end. */
+ for (scan = NEXT_INSN (insn); scan && n_insns < 3; scan = NEXT_INSN (scan))
+ {
+ if (!INSN_P (scan))
+ continue;
+ if (GET_CODE (PATTERN (scan)) == SEQUENCE)
+ scan = XVECEXP (PATTERN (scan), 0, 0);
+ if (JUMP_P (scan))
+ {
+ if (recog_memoized (scan) != CODE_FOR_doloop_end_i)
+ {
+ n_insns += 2;
+ if (simplejump_p (scan))
+ {
+ scan = XEXP (SET_SRC (PATTERN (scan)), 0);
+ continue;
+ }
+ if (JUMP_LABEL (scan)
+ /* JUMP_LABEL might be simple_return instead if an insn. */
+ && (!INSN_P (JUMP_LABEL (scan))
+ || (!next_active_insn (JUMP_LABEL (scan))
+ || (recog_memoized (next_active_insn (JUMP_LABEL (scan)))
+ != CODE_FOR_doloop_begin_i)))
+ && (!next_active_insn (NEXT_INSN (PREV_INSN (scan)))
+ || (recog_memoized
+ (next_active_insn (NEXT_INSN (PREV_INSN (scan))))
+ != CODE_FOR_doloop_begin_i)))
+ n_insns++;
+ }
+ break;
+ }
+ len = get_attr_length (scan);
+ /* Size estimation of asms assumes that each line which is nonempty
+ codes an insn, and that each has a long immediate. For minimum insn
+ count, assume merely that a nonempty asm has at least one insn. */
+ if (GET_CODE (PATTERN (scan)) == ASM_INPUT
+ || asm_noperands (PATTERN (scan)) >= 0)
+ n_insns += (len != 0);
+ else
+ n_insns += (len > 4 ? 2 : (len ? 1 : 0));
+ }
+ if (LOOP_ALIGN (0))
+ {
+ asm_fprintf (asm_out_file, "\t.p2align %d\\n", LOOP_ALIGN (0));
+ arc_clear_unalign ();
+ }
+ gcc_assert (n_insns || GET_CODE (next_nonnote_insn (insn)) == CODE_LABEL);
+ if (size >= 2048 || (TARGET_ARC600 && n_insns == 1) || loop_start)
+ {
+ if (flag_pic)
+ {
+ /* ??? Can do better for when a scratch register
+ is known. But that would require extra testing. */
+ arc_clear_unalign ();
+ return ".p2align 2\;push_s r0\;add r0,pcl,24\;sr r0,[2]; LP_START\;add r0,pcl,.L__GCC__LP%1-.+2\;sr r0,[3]; LP_END\;pop_s r0";
+ }
+ output_asm_insn ((size < 2048
+ ? "lp .L__GCC__LP%1" : "sr .L__GCC__LP%1,[3]; LP_END"),
+ operands);
+ output_asm_insn (loop_start
+ ? "sr %4,[2]; LP_START" : "sr 0f,[2]; LP_START",
+ operands);
+ if (TARGET_ARC600 && n_insns < 1)
+ output_asm_insn ("nop", operands);
+ return (TARGET_ARC600 && n_insns < 3) ? "nop_s\;nop_s\;0:" : "0:";
+ }
+ else if (TARGET_ARC600 && n_insns < 3)
+ {
+ /* At least four instructions are needed between the setting of LP_COUNT
+ and the loop end - but the lp instruction qualifies as one. */
+ rtx prev = prev_nonnote_insn (insn);
+
+ if (!INSN_P (prev) || dead_or_set_regno_p (prev, LP_COUNT))
+ output_asm_insn ("nop", operands);
+ }
+ return "lp .L__GCC__LP%1";
+}
+ [(set_attr "type" "loop_setup")
+ (set_attr_alternative "length"
+; FIXME: length is usually 4, but we need branch shortening
+; to get this right.
+; [(if_then_else (match_test "TARGET_ARC600") (const_int 16) (const_int 4))
+ [(if_then_else (match_test "flag_pic") (const_int 24) (const_int 16))
+ (if_then_else (match_test "flag_pic") (const_int 28) (const_int 16))
+ (const_int 0)])]
+ ;; ??? we should really branch shorten this insn, but then we'd
+ ;; need a proper label first. N.B. the end label can not only go out
+ ;; of range when it is far away, but also when it precedes the loop -
+ ;; which, unfortunately, it sometimes does, when the loop "optimizer"
+ ;; messes things up.
+)
+
+; operand 0 is the loop count pseudo register
+; operand 1 is the label to jump to at the top of the loop
+; Use this for the ARC600 and ARC700. For ARCtangent-A5, this is unsafe
+; without further checking for nearby branches etc., and without proper
+; annotation of shift patterns that clobber lp_count
+; ??? ARC600 might want to check if the loop has few iteration and only a
+; single insn - loop setup is expensive then.
+(define_expand "doloop_end"
+ [(use (match_operand 0 "register_operand" ""))
+ (use (label_ref (match_operand 1 "" "")))]
+ "TARGET_ARC600 || TARGET_ARC700"
+{
+ /* We could do smaller bivs with biv widening, and wider bivs by having
+ a high-word counter in an outer loop - but punt on this for now. */
+ if (GET_MODE (operands[0]) != SImode)
+ FAIL;
+ emit_jump_insn (gen_doloop_end_i (operands[0], operands[1], const0_rtx));
+ DONE;
+})
+
+(define_insn_and_split "doloop_end_i"
+ [(set (pc)
+ (if_then_else (ne (match_operand:SI 0 "shouldbe_register_operand" "+l,*c,*m")
+ (const_int 1))
+ (label_ref (match_operand 1 "" ""))
+ (pc)))
+ (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))
+ (use (reg:SI LP_START))
+ (use (reg:SI LP_END))
+ (use (match_operand 2 "const_int_operand" "n,???Cn0,???X"))
+ (clobber (match_scratch:SI 3 "=X,X,&????r"))]
+ ""
+ "*
+{
+ rtx prev = prev_nonnote_insn (insn);
+
+ /* If there is an immediately preceding label, we must output a nop,
+ lest a branch to that label will fall out of the loop.
+ ??? We could try to avoid this by claiming to have a delay slot if there
+ is a preceding label, and outputting the delay slot insn instead, if
+ present.
+ Or we could have some optimization that changes the source edge to update
+ the loop count and jump to the loop start instead. */
+ /* For ARC600, we must also prevent jumps inside the loop and jumps where
+ the loop counter value is live at the target from being directly at the
+ loop end. Being sure that the loop counter is dead at the target is
+ too much hair - we can't rely on data flow information at this point -
+ so insert a nop for all branches.
+ The ARC600 also can't read the loop counter in the last insn of a loop. */
+ if (LABEL_P (prev))
+ output_asm_insn (\"nop%?\", operands);
+ return \"\\n.L__GCC__LP%2: ; loop end, start is %1\";
+}"
+ "&& memory_operand (operands[0], SImode)"
+ [(pc)]
+{
+ emit_move_insn (operands[3], operands[0]);
+ emit_jump_insn (gen_doloop_fallback_m (operands[3], operands[1], operands[0]));
+ DONE;
+}
+ [(set_attr "type" "loop_end")
+ (set (attr "length")
+ (if_then_else (match_test "LABEL_P (prev_nonnote_insn (insn))")
+ (const_int 4) (const_int 0)))]
+)
+
+; This pattern is generated by arc_reorg when there is no recognizable
+; loop start.
+(define_insn "*doloop_fallback"
+ [(set (pc) (if_then_else (ne (match_operand:SI 0 "register_operand" "+r,!w")
+ (const_int 1))
+ (label_ref (match_operand 1 "" ""))
+ (pc)))
+ (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))]
+ ; avoid fooling the loop optimizer into assuming this is a special insn.
+ "reload_completed"
+ "*return get_attr_length (insn) == 8
+ ? \"brne.d %0,1,%1\;sub %0,%0,1\"
+ : \"breq %0,1,0f\;b.d %1\;sub %0,%0,1\\n0:\";"
+ [(set (attr "length")
+ (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -256))
+ (le (minus (match_dup 1) (pc)) (const_int 244)))
+ (const_int 8) (const_int 12)))
+ (set_attr "type" "brcc_no_delay_slot")
+ (set_attr "cond" "nocond")]
+)
+
+; reload can't make output reloads for jump insns, so we have to do this by hand.
+(define_insn "doloop_fallback_m"
+ [(set (pc) (if_then_else (ne (match_operand:SI 0 "register_operand" "+&r")
+ (const_int 1))
+ (label_ref (match_operand 1 "" ""))
+ (pc)))
+ (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))
+ (set (match_operand:SI 2 "memory_operand" "=m")
+ (plus:SI (match_dup 0) (const_int -1)))]
+ ; avoid fooling the loop optimizer into assuming this is a special insn.
+ "reload_completed"
+ "*return get_attr_length (insn) == 12
+ ? \"sub %0,%0,1\;brne.d %0,0,%1\;st%U2%V2 %0,%2\"
+ : \"sub %0,%0,1\;breq %0,0,0f\;b.d %1\\n0:\tst%U2%V2 %0,%2\";"
+ [(set (attr "length")
+ (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -252))
+ (le (minus (match_dup 1) (pc)) (const_int 244)))
+ (const_int 12) (const_int 16)))
+ (set_attr "type" "brcc_no_delay_slot")
+ (set_attr "cond" "nocond")]
+)
+
+(define_expand "movmemsi"
+ [(match_operand:BLK 0 "" "")
+ (match_operand:BLK 1 "" "")
+ (match_operand:SI 2 "nonmemory_operand" "")
+ (match_operand 3 "immediate_operand" "")]
+ ""
+ "if (arc_expand_movmem (operands)) DONE; else FAIL;")
+
+;; Close http://gcc.gnu.org/bugzilla/show_bug.cgi?id=35803 if this works
+;; to the point that we can generate cmove instructions.
+(define_expand "cbranch<mode>4"
+ [(set (reg:CC CC_REG)
+ (compare:CC (match_operand:SDF 1 "register_operand" "")
+ (match_operand:SDF 2 "register_operand" "")))
+ (set (pc)
+ (if_then_else
+ (match_operator 0 "comparison_operator" [(reg CC_REG)
+ (const_int 0)])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
+
+ "TARGET_OPTFPE"
+{
+ gcc_assert (XEXP (operands[0], 0) == operands[1]);
+ gcc_assert (XEXP (operands[0], 1) == operands[2]);
+ operands[0] = gen_compare_reg (operands[0], VOIDmode);
+ emit_jump_insn (gen_branch_insn (operands[3], operands[0]));
+ DONE;
+})
+
+(define_expand "cmp_float"
+ [(parallel [(set (match_operand 0 "") (match_operand 1 ""))
+ (clobber (reg:SI RETURN_ADDR_REGNUM))
+ (clobber (reg:SI R12_REG))])]
+ ""
+ "")
+
+(define_mode_iterator OPTFPE_CMP [CC_Z CC_FP_GT CC_FP_GE CC_FP_UNEQ CC_FP_ORD])
+(define_mode_attr cmp [(CC_Z "eq") (CC_FP_GT "gt") (CC_FP_GE "ge")
+ (CC_FP_UNEQ "uneq") (CC_FP_ORD "ord")])
+
+(define_insn "*cmpsf_<cmp>"
+ [(set (reg:OPTFPE_CMP CC_REG) (compare:OPTFPE_CMP (reg:SF 0) (reg:SF 1)))
+ (clobber (reg:SI RETURN_ADDR_REGNUM))
+ (clobber (reg:SI R12_REG))]
+ "TARGET_OPTFPE && (!TARGET_ARGONAUT_SET || !TARGET_SPFP)
+ && SFUNC_CHECK_PREDICABLE"
+ "*return arc_output_libcall (\"__<cmp>sf2\");"
+ [(set_attr "is_sfunc" "yes")
+ (set_attr "predicable" "yes")])
+
+;; N.B. for "*cmpdf_ord":
+;; double precision fpx sets bit 31 for NaNs. We need bit 51 set
+;; for the floating point emulation to recognize the NaN.
+(define_insn "*cmpdf_<cmp>"
+ [(set (reg:OPTFPE_CMP CC_REG) (compare:OPTFPE_CMP (reg:DF 0) (reg:DF 2)))
+ (clobber (reg:SI RETURN_ADDR_REGNUM))
+ (clobber (reg:SI R12_REG))]
+ "TARGET_OPTFPE && (!TARGET_ARGONAUT_SET || !TARGET_DPFP)
+ && SFUNC_CHECK_PREDICABLE"
+ "*return arc_output_libcall (\"__<cmp>df2\");"
+ [(set_attr "is_sfunc" "yes")
+ (set_attr "predicable" "yes")])
+
+(define_insn "abssf2"
+ [(set (match_operand:SF 0 "dest_reg_operand" "=Rcq#q,Rcw,w")
+ (abs:SF (match_operand:SF 1 "register_operand" "0, 0,c")))]
+ ""
+ "bclr%? %0,%1,31%&"
+ [(set_attr "type" "unary")
+ (set_attr "iscompact" "maybe,false,false")
+ (set_attr "length" "2,4,4")
+ (set_attr "predicable" "no,yes,no")])
+
+(define_insn "negsf2"
+ [(set (match_operand:SF 0 "dest_reg_operand" "=Rcw,w")
+ (neg:SF (match_operand:SF 1 "register_operand" "0,c")))]
+ ""
+ "bxor%? %0,%1,31"
+ [(set_attr "type" "unary")
+ (set_attr "predicable" "yes,no")])
+
+;; ??? Should this use arc_output_libcall and set is_sfunc?
+(define_insn "*millicode_thunk_st"
+ [(match_parallel 0 "millicode_store_operation"
+ [(set (mem:SI (reg:SI SP_REG)) (reg:SI 13))])]
+ ""
+{
+ output_asm_insn ("bl%* __st_r13_to_%0",
+ &SET_SRC (XVECEXP (operands[0], 0,
+ XVECLEN (operands[0], 0) - 2)));
+ return "";
+}
+ [(set_attr "type" "call")])
+
+(define_insn "*millicode_thunk_ld"
+ [(match_parallel 0 "millicode_load_clob_operation"
+ [(set (reg:SI 13) (mem:SI (reg:SI SP_REG)))])]
+ ""
+{
+ output_asm_insn ("bl%* __ld_r13_to_%0",
+ &SET_DEST (XVECEXP (operands[0], 0,
+ XVECLEN (operands[0], 0) - 2)));
+ return "";
+}
+ [(set_attr "type" "call")])
+
+; the sibthunk restores blink, so we use the return rtx.
+(define_insn "*millicode_sibthunk_ld"
+ [(match_parallel 0 "millicode_load_operation"
+ [(return)
+ (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (reg:SI 12)))
+ (set (reg:SI 13) (mem:SI (reg:SI SP_REG)))])]
+ ""
+{
+ output_asm_insn ("b%* __ld_r13_to_%0_ret",
+ &SET_DEST (XVECEXP (operands[0], 0,
+ XVECLEN (operands[0], 0) - 1)));
+ return "";
+}
+ [(set_attr "type" "call")
+ (set_attr "is_SIBCALL" "yes")])
+
+;; If hardware floating point is available, don't define a negdf pattern;
+;; it would be something like:
+;;(define_insn "negdf2"
+;; [(set (match_operand:DF 0 "register_operand" "=w,w,D,?r")
+;; (neg:DF (match_operand:DF 1 "register_operand" "0,c,D,D")))
+;; (clobber (match_scratch:DF 2 "=X,X,X,X,D1"))]
+;; ""
+;; "@
+;; bxor%? %H0,%H1,31
+;; bxor %H0,%H1,31 ` mov %L0,%L1
+;; drsubh%F0%F1 0,0,0
+;; drsubh%F2%F1 %H0,0,0 ` dexcl%F2 %L0,%H0,%L0"
+;; [(set_attr "type" "unary,unary,dpfp_addsub,dpfp_addsub")
+;; (set_attr "iscompact" "false,false,false,false")
+;; (set_attr "length" "4,4,8,12")
+;; (set_attr "cond" "canuse,nocond,nocond,nocond")])
+;; and this suffers from always requiring a long immediate when using
+;; the floating point hardware.
+;; We then want the sub[sd]f patterns to be used, so that we can load the
+;; constant zero efficiently into a register when we want to do the
+;; computation using the floating point hardware. There should be a special
+;; subdf alternative that matches a zero operand 1, which then can allow
+;; to use bxor to flip the high bit of an integer register.
+;; ??? we actually can't use the floating point hardware for neg, because
+;; this would not work right for -0. OTOH optabs.c has already code
+;; to synthesyze negate by flipping the sign bit.
+
+
+;; include the arc-FPX instructions
+(include "fpx.md")
+
+(include "simdext.md")
diff --git a/gcc/config/arc/arc.opt b/gcc/config/arc/arc.opt
new file mode 100644
index 00000000000..26e0de43fda
--- /dev/null
+++ b/gcc/config/arc/arc.opt
@@ -0,0 +1,390 @@
+; Options for the Synopsys DesignWare ARC port of the compiler
+;
+; Copyright (C) 2005, 2007-2013 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/arc/arc-opts.h
+
+mbig-endian
+Target Report RejectNegative Mask(BIG_ENDIAN)
+Compile code for big endian mode
+
+mlittle-endian
+Target Report RejectNegative InverseMask(BIG_ENDIAN)
+Compile code for little endian mode. This is the default
+
+mno-cond-exec
+Target Report RejectNegative Mask(NO_COND_EXEC)
+Disable ARCompact specific pass to generate conditional execution instructions
+
+mA5
+Target Report
+Generate ARCompact 32-bit code for ARCtangent-A5 processor
+
+mA6
+Target Report
+Generate ARCompact 32-bit code for ARC600 processor
+
+mARC600
+Target Report
+Same as -mA6
+
+mARC601
+Target Report
+Generate ARCompact 32-bit code for ARC601 processor
+
+mA7
+Target Report
+Generate ARCompact 32-bit code for ARC700 processor
+
+mARC700
+Target Report
+Same as -mA7
+
+mmixed-code
+Target Report Mask(MIXED_CODE_SET)
+Tweak register allocation to help 16-bit instruction generation
+; originally this was:
+;Generate ARCompact 16-bit instructions intermixed with 32-bit instructions for ARCtangent-A5 and higher processors
+; but we do that without -mmixed-code, too, it's just a different instruction
+; count / size tradeoff.
+
+; We use an explict definition for the negative form because that is the
+; actually interesting option, and we want that to have its own comment.
+mvolatile-cache
+Target Report RejectNegative Mask(VOLATILE_CACHE_SET)
+Use ordinarily cached memory accesses for volatile references
+
+mno-volatile-cache
+Target Report RejectNegative InverseMask(VOLATILE_CACHE_SET)
+Enable cache bypass for volatile references
+
+mbarrel-shifter
+Target Report Mask(BARREL_SHIFTER)
+Generate instructions supported by barrel shifter
+
+mnorm
+Target Report Mask(NORM_SET)
+Generate norm instruction
+
+mswap
+Target Report Mask(SWAP_SET)
+Generate swap instruction
+
+mmul64
+Target Report Mask(MUL64_SET)
+Generate mul64 and mulu64 instructions
+
+mno-mpy
+Target Report Mask(NOMPY_SET)
+Do not generate mpy instructions for ARC700
+
+mea
+Target Report Mask(EA_SET)
+Generate Extended arithmetic instructions. Currently only divaw, adds, subs and sat16 are supported
+
+msoft-float
+Target Report Mask(0)
+Dummy flag. This is the default unless FPX switches are provided explicitly
+
+mlong-calls
+Target Report Mask(LONG_CALLS_SET)
+Generate call insns as register indirect calls
+
+mno-brcc
+Target Report Mask(NO_BRCC_SET)
+Do no generate BRcc instructions in arc_reorg.
+
+msdata
+Target Report InverseMask(NO_SDATA_SET)
+Generate sdata references. This is the default, unless you compile for PIC.
+
+mno-millicode
+Target Report Mask(NO_MILLICODE_THUNK_SET)
+Do not generate millicode thunks (needed only with -Os)
+
+mspfp
+Target Report Mask(SPFP_COMPACT_SET)
+FPX: Generate Single Precision FPX (compact) instructions.
+
+mspfp-compact
+Target Report Mask(SPFP_COMPACT_SET) MaskExists
+FPX: Generate Single Precision FPX (compact) instructions.
+
+mspfp-fast
+Target Report Mask(SPFP_FAST_SET)
+FPX: Generate Single Precision FPX (fast) instructions.
+
+margonaut
+Target Report Mask(ARGONAUT_SET)
+FPX: Enable Argonaut ARC CPU Double Precision Floating Point extensions.
+
+mdpfp
+Target Report Mask(DPFP_COMPACT_SET)
+FPX: Generate Double Precision FPX (compact) instructions.
+
+mdpfp-compact
+Target Report Mask(DPFP_COMPACT_SET) MaskExists
+FPX: Generate Double Precision FPX (compact) instructions.
+
+mdpfp-fast
+Target Report Mask(DPFP_FAST_SET)
+FPX: Generate Double Precision FPX (fast) instructions.
+
+mno-dpfp-lrsr
+Target Report Mask(DPFP_DISABLE_LRSR)
+Disable LR and SR instructions from using FPX extension aux registers.
+
+msimd
+Target Report Mask(SIMD_SET)
+Enable generation of ARC SIMD instructions via target-specific builtins.
+
+mcpu=
+Target RejectNegative Joined Var(arc_cpu) Enum(processor_type) Init(PROCESSOR_NONE)
+-mcpu=CPU Compile code for ARC variant CPU
+
+Enum
+Name(processor_type) Type(enum processor_type)
+
+EnumValue
+Enum(processor_type) String(A5) Value(PROCESSOR_A5)
+
+EnumValue
+Enum(processor_type) String(ARC600) Value(PROCESSOR_ARC600)
+
+EnumValue
+Enum(processor_type) String(ARC601) Value(PROCESSOR_ARC601)
+
+EnumValue
+Enum(processor_type) String(ARC700) Value(PROCESSOR_ARC700)
+
+msize-level=
+Target RejectNegative Joined UInteger Var(arc_size_opt_level) Init(-1)
+size optimization level: 0:none 1:opportunistic 2: regalloc 3:drop align, -Os
+
+misize
+Target Report Var(TARGET_DUMPISIZE)
+Annotate assembler instructions with estimated addresses
+
+mmultcost=
+Target RejectNegative Joined UInteger Var(arc_multcost) Init(-1)
+Cost to assume for a multiply instruction, with 4 being equal to a normal insn.
+
+mtune=ARC600
+Target RejectNegative Var(arc_tune, TUNE_ARC600)
+Tune for ARC600 cpu.
+
+mtune=ARC601
+Target RejectNegative Var(arc_tune, TUNE_ARC600)
+Tune for ARC601 cpu.
+
+mtune=ARC700
+Target RejectNegative Var(arc_tune, TUNE_ARC700_4_2_STD)
+Tune for ARC700 R4.2 Cpu with standard multiplier block.
+
+mtune=ARC700-xmac
+Target RejectNegative Var(arc_tune, TUNE_ARC700_4_2_XMAC)
+Tune for ARC700 R4.2 Cpu with XMAC block.
+
+mtune=ARC725D
+Target RejectNegative Var(arc_tune, TUNE_ARC700_4_2_XMAC)
+Tune for ARC700 R4.2 Cpu with XMAC block.
+
+mtune=ARC750D
+Target RejectNegative Var(arc_tune, TUNE_ARC700_4_2_XMAC)
+Tune for ARC700 R4.2 Cpu with XMAC block.
+
+mindexed-loads
+Target Var(TARGET_INDEXED_LOADS)
+Enable the use of indexed loads
+
+mauto-modify-reg
+Target Var(TARGET_AUTO_MODIFY_REG)
+Enable the use of pre/post modify with register displacement.
+
+mmul32x16
+Target Report Mask(MULMAC_32BY16_SET)
+Generate 32x16 multiply and mac instructions
+
+; the initializer is supposed to be: Init(REG_BR_PROB_BASE/2) ,
+; alas, basic-block.h is not included in options.c .
+munalign-prob-threshold=
+Target RejectNegative Joined UInteger Var(arc_unalign_prob_threshold) Init(10000/2)
+Set probability threshold for unaligning branches
+
+mmedium-calls
+Target Var(TARGET_MEDIUM_CALLS) Init(TARGET_MMEDIUM_CALLS_DEFAULT)
+Don't use less than 25 bit addressing range for calls.
+
+mannotate-align
+Target Var(TARGET_ANNOTATE_ALIGN)
+Explain what alignment considerations lead to the decision to make an insn short or long.
+
+malign-call
+Target Var(TARGET_ALIGN_CALL)
+Do alignment optimizations for call instructions.
+
+mRcq
+Target Var(TARGET_Rcq)
+Enable Rcq constraint handling - most short code generation depends on this.
+
+mRcw
+Target Var(TARGET_Rcw)
+Enable Rcw constraint handling - ccfsm condexec mostly depends on this.
+
+mearly-cbranchsi
+Target Var(TARGET_EARLY_CBRANCHSI)
+Enable pre-reload use of cbranchsi pattern
+
+mbbit-peephole
+Target Var(TARGET_BBIT_PEEPHOLE)
+Enable bbit peephole2
+
+mcase-vector-pcrel
+Target Var(TARGET_CASE_VECTOR_PC_RELATIVE)
+Use pc-relative switch case tables - this enables case table shortening.
+
+mcompact-casesi
+Target Var(TARGET_COMPACT_CASESI)
+Enable compact casesi pattern
+
+mq-class
+Target Var(TARGET_Q_CLASS)
+Enable 'q' instruction alternatives.
+
+mexpand-adddi
+Target Var(TARGET_EXPAND_ADDDI)
+Expand adddi3 and subdi3 at rtl generation time into add.f / adc etc.
+
+
+; Flags used by the assembler, but for which we define preprocessor
+; macro symbols as well.
+mcrc
+Target Report
+Enable variable polynomial CRC extension
+
+mdsp-packa
+Target Report
+Enable DSP 3.1 Pack A extensions
+
+mdvbf
+Target Report
+Enable dual viterbi butterfly extension
+
+mmac-d16
+Target Report Undocumented
+
+mmac-24
+Target Report Undocumented
+
+mtelephony
+Target Report RejectNegative
+Enable Dual and Single Operand Instructions for Telephony
+
+mxy
+Target Report
+Enable XY Memory extension (DSP version 3)
+
+; ARC700 4.10 extension instructions
+mlock
+Target Report
+Enable Locked Load/Store Conditional extension
+
+mswape
+Target Report
+Enable swap byte ordering extension instruction
+
+mrtsc
+Target Report
+Enable 64-bit Time-Stamp Counter extension instruction
+
+mno-epilogue-cfi
+Target Report RejectNegative InverseMask(EPILOGUE_CFI)
+Disable generation of cfi for epilogues.
+
+mepilogue-cfi
+Target RejectNegative Mask(EPILOGUE_CFI)
+Enable generation of cfi for epilogues.
+
+EB
+Target
+Pass -EB option through to linker.
+
+EL
+Target
+Pass -EL option through to linker.
+
+marclinux
+target
+Pass -marclinux option through to linker.
+
+marclinux_prof
+target
+Pass -marclinux_prof option through to linker.
+
+;; lra is still unproven for ARC, so allow to fall back to reload with -mno-lra.
+;Target InverseMask(NO_LRA)
+mlra
+; lra still won't allow to configure libgcc; see PR rtl-optimization/55464.
+; so don't enable by default.
+Target Mask(LRA)
+Enable lra
+
+mlra-priority-none
+Target RejectNegative Var(arc_lra_priority_tag, ARC_LRA_PRIORITY_NONE)
+Don't indicate any priority with TARGET_REGISTER_PRIORITY
+
+mlra-priority-compact
+Target RejectNegative Var(arc_lra_prioritytag, ARC_LRA_PRIORITY_COMPACT)
+Indicate priority for r0..r3 / r12..r15 with TARGET_REGISTER_PRIORITY
+
+mlra-priority-noncompact
+Target RejectNegative Var(arc_lra_prioritytag, ARC_LRA_PRIORITY_NONCOMPACT)
+Reduce priority for r0..r3 / r12..r15 with TARGET_REGISTER_PRIORITY
+
+mucb-mcount
+Target Report Var(TARGET_UCB_MCOUNT)
+instrument with mcount calls as in the ucb code
+
+; backward-compatibility aliases, translated by DRIVER_SELF_SPECS
+
+mEA
+Target
+
+multcost=
+Target RejectNegative Joined
+
+; Unfortunately, listing the full option name gives us clashes
+; with OPT_opt_name being claimed for both opt_name and opt-name,
+; so we leave out the last character or more.
+mbarrel_shifte
+Target Joined
+
+mspfp_
+Target Joined
+
+mdpfp_
+Target Joined
+
+mdsp_pack
+Target Joined
+
+mmac_
+Target Joined
+
diff --git a/gcc/config/arc/arc600.md b/gcc/config/arc/arc600.md
new file mode 100644
index 00000000000..f5665178322
--- /dev/null
+++ b/gcc/config/arc/arc600.md
@@ -0,0 +1,63 @@
+;; DFA scheduling description of the Synopsys DesignWare ARC600 cpu
+;; for GNU C compiler
+;; Copyright (C) 2007-2013 Free Software Foundation, Inc.
+;; Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+;; on behalf of Synopsys 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_automaton "ARC600")
+
+(define_cpu_unit "issue_600" "ARC600")
+(define_cpu_unit "mul64_600" "ARC600")
+
+; latency from flag-setting insns to branches is 3.
+(define_insn_reservation "compare_600" 3
+ (and (eq_attr "tune" "arc600")
+ (eq_attr "type" "compare"))
+ "issue_600")
+
+(define_insn_reservation "load_DI_600" 4
+ (and (eq_attr "tune" "arc600")
+ (eq_attr "type" "load")
+ (match_operand:DI 0 "" ""))
+ "issue_600")
+
+(define_insn_reservation "load_600" 3
+ (and (eq_attr "tune" "arc600")
+ (eq_attr "type" "load")
+ (not (match_operand:DI 0 "" "")))
+ "issue_600")
+
+(define_insn_reservation "mul_600_fast" 3
+ (and (eq_attr "tune" "arc600")
+ (match_test "arc_multcost < COSTS_N_INSNS (7)")
+ (eq_attr "type" "multi,umulti"))
+ "mul64_600*3")
+
+(define_insn_reservation "mul_600_slow" 8
+ (and (eq_attr "tune" "arc600")
+ (match_test "arc_multcost >= COSTS_N_INSNS (7)")
+ (eq_attr "type" "multi,umulti"))
+ "mul64_600*8")
+
+(define_insn_reservation "mul_mac_600" 3
+ (and (eq_attr "tune" "arc600")
+ (eq_attr "type" "mulmac_600"))
+ "nothing*3")
+
+(define_bypass 1 "mul_mac_600" "mul_mac_600")
diff --git a/gcc/config/arc/arc700.md b/gcc/config/arc/arc700.md
new file mode 100644
index 00000000000..b5cb68a9bbf
--- /dev/null
+++ b/gcc/config/arc/arc700.md
@@ -0,0 +1,170 @@
+;; DFA scheduling description of the Synopsys DesignWare ARC700 cpu
+;; for GNU C compiler
+;; Comments and Support For ARC700 instructions added by
+;; Saurabh Verma (saurabh.verma@codito.com)
+;; Ramana Radhakrishnan(ramana.radhakrishnan@codito.com)
+;; Factoring out and improvement of ARC700 Scheduling by
+;; Joern Rennecke (joern.rennecke@embecosm.com)
+;; Copyright (C) 2006-2013 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_automaton "ARC700")
+
+;; aux to be added here
+(define_cpu_unit "core, dmp, write_port, dmp_write_port, multiplier, issue, blockage, simd_unit" "ARC700")
+
+(define_insn_reservation "core_insn_DI" 2
+ (and (eq_attr "tune_arc700" "true")
+ (eq_attr "type" "unary, move, cmove, binary")
+ (match_operand:DI 0 "" ""))
+ "issue+core, issue+core+write_port, write_port")
+
+(define_insn_reservation "lr" 2
+ (and (eq_attr "tune_arc700" "true")
+ (eq_attr "type" "lr"))
+ "issue+blockage, blockage*2, write_port")
+
+(define_insn_reservation "sr" 1
+ (and (eq_attr "tune_arc700" "true")
+ (eq_attr "type" "sr"))
+ "issue+dmp_write_port+blockage, blockage*9")
+
+(define_insn_reservation "core_insn" 1
+ (and (eq_attr "tune_arc700" "true")
+ (eq_attr "type" "unary, move, binary"))
+ "issue+core, nothing, write_port")
+
+(define_insn_reservation "cmove" 1
+ (and (eq_attr "tune_arc700" "true")
+ (eq_attr "type" "cmove"))
+ "issue+core, nothing, write_port")
+
+(define_insn_reservation "cc_arith" 1
+ (and (eq_attr "tune_arc700" "true")
+ (eq_attr "type" "cc_arith"))
+ "issue+core, nothing, write_port")
+
+(define_insn_reservation "two_cycle_core_insn" 2
+ (and (eq_attr "tune_arc700" "true")
+ (eq_attr "type" "two_cycle_core"))
+ "issue+core, nothing, write_port")
+
+(define_insn_reservation "divaw_insn" 2
+ (and (eq_attr "tune_arc700" "true")
+ (eq_attr "type" "divaw"))
+ "issue+core, nothing, write_port")
+
+(define_insn_reservation "shift_insn" 2
+ (and (eq_attr "tune_arc700" "true")
+ (eq_attr "type" "shift"))
+ "issue+core, nothing, write_port")
+
+; Latency from flag setters to arithmetic with carry is 3.
+(define_insn_reservation "compare_700" 3
+ (and (eq_attr "tune_arc700" "true")
+ (eq_attr "type" "compare"))
+ "issue+core, nothing, write_port")
+
+; Assume here the branch is predicted correctly and has a delay slot insn
+; or is properly unaligned.
+(define_insn_reservation "branch_700" 1
+ (and (eq_attr "tune_arc700" "true")
+ (eq_attr "type" "compare"))
+ "issue+core, nothing, write_port")
+
+; TODOs: is this correct ??
+(define_insn_reservation "multi_DI" 10
+ (and (eq_attr "tune_arc700" "true")
+ (eq_attr "type" "multi")
+ (match_operand:DI 0 "" ""))
+ "issue+multiplier, multiplier*2,issue+multiplier, multiplier*2,
+ nothing,write_port,nothing*2, write_port")
+
+(define_insn_reservation "umulti_DI" 9
+ (and (eq_attr "tune_arc700" "true")
+ (eq_attr "type" "umulti")
+ (match_operand:DI 0 "" ""))
+ "issue+multiplier, multiplier,issue+multiplier, multiplier*2,
+ write_port,nothing*3, write_port")
+
+(define_insn_reservation "umulti_xmac" 5
+ (and (eq_attr "tune_arc700" "true")
+ (eq_attr "type" "umulti"))
+ "issue+multiplier, multiplier, nothing*3, write_port")
+
+; latency of mpyu is lower than mpy / mpyh / mpyhu
+(define_insn_reservation "umulti_std" 6
+ (and (eq_attr "tune_arc700" "true")
+ (eq_attr "type" "umulti"))
+ "issue+multiplier, multiplier*3, nothing*2, write_port")
+
+;; arc700 xmac multiplier
+(define_insn_reservation "multi_xmac" 5
+ (and (eq_attr "tune" "arc700_4_2_xmac")
+ (eq_attr "type" "multi"))
+ "issue+multiplier,multiplier,nothing*3,write_port")
+
+; arc700 standard multiplier
+(define_insn_reservation "multi_std" 7
+ (and (eq_attr "tune" "arc700_4_2_std")
+ (eq_attr "type" "multi"))
+ "issue+multiplier,multiplier*4,nothing*2,write_port")
+
+;(define_insn_reservation "multi_SI" 7
+; (eq_attr "type" "multi")
+; "issue+multiplier, multiplier*2, nothing*4, write_port")
+
+; There is no multiplier -> multiplier bypass except for the
+; mac -> mac dependency on the accumulator.
+
+; divaw -> divaw latency is 1 cycle
+(define_bypass 1 "divaw_insn" "divaw_insn")
+
+(define_bypass 1 "compare_700" "branch_700,core_insn,data_store,data_load")
+
+; we could shedule the cmove immediately after the compare, but then
+; the cmove would have higher latency... so just keep the cmove apart
+; from the compare.
+(define_bypass 2 "compare_700" "cmove")
+
+; no functional unit runs when blockage is reserved
+(exclusion_set "blockage" "core, multiplier")
+
+(define_insn_reservation "data_load_DI" 4
+ (and (eq_attr "tune_arc700" "true")
+ (eq_attr "type" "load")
+ (match_operand:DI 0 "" ""))
+ "issue+dmp, issue+dmp, dmp_write_port, dmp_write_port")
+
+(define_insn_reservation "data_load" 3
+ (and (eq_attr "tune_arc700" "true")
+ (eq_attr "type" "load")
+ (not (match_operand:DI 0 "" "")))
+ "issue+dmp, nothing, dmp_write_port")
+
+(define_insn_reservation "data_store_DI" 2
+ (and (eq_attr "tune_arc700" "true")
+ (eq_attr "type" "store")
+ (match_operand:DI 0 "" ""))
+ "issue+dmp_write_port, issue+dmp_write_port")
+
+(define_insn_reservation "data_store" 1
+ (and (eq_attr "tune_arc700" "true")
+ (eq_attr "type" "store")
+ (not (match_operand:DI 0 "" "")))
+ "issue+dmp_write_port")
diff --git a/gcc/config/arc/constraints.md b/gcc/config/arc/constraints.md
new file mode 100644
index 00000000000..088013bbdb7
--- /dev/null
+++ b/gcc/config/arc/constraints.md
@@ -0,0 +1,399 @@
+;; Constraint definitions for Synopsys DesignWare ARC.
+;; Copyright (C) 2007-2013 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/>.
+
+;; Register constraints
+
+; Most instructions accept arbitrary core registers for their inputs, even
+; if the core register in question cannot be written to, like the multiply
+; result registers of the ARCtangent-A5 and ARC600 .
+; First, define a class for core registers that can be read cheaply. This
+; is most or all core registers for ARC600, but only r0-r31 for ARC700
+(define_register_constraint "c" "CHEAP_CORE_REGS"
+ "core register @code{r0}-@code{r31}, @code{ap},@code{pcl}")
+
+; All core regs - e.g. for when we must have a way to reload a register.
+(define_register_constraint "Rac" "ALL_CORE_REGS"
+ "core register @code{r0}-@code{r60}, @code{ap},@code{pcl}")
+
+; Some core registers (.e.g lp_count) aren't general registers because they
+; can't be used as the destination of a multi-cycle operation like
+; load and/or multiply, yet they are still writable in the sense that
+; register-register moves and single-cycle arithmetic (e.g "add", "and",
+; but not "mpy") can write to them.
+(define_register_constraint "w" "WRITABLE_CORE_REGS"
+ "writable core register: @code{r0}-@code{r31}, @code{r60}, nonfixed core register")
+
+(define_register_constraint "W" "MPY_WRITABLE_CORE_REGS"
+ "writable core register except @code{LP_COUNT} (@code{r60}): @code{r0}-@code{r31}, nonfixed core register")
+
+(define_register_constraint "l" "LPCOUNT_REG"
+ "@internal
+ Loop count register @code{r60}")
+
+(define_register_constraint "x" "R0_REGS"
+ "@code{R0} register.")
+
+(define_register_constraint "Rgp" "GP_REG"
+ "@internal
+ Global Pointer register @code{r26}")
+
+(define_register_constraint "f" "FP_REG"
+ "@internal
+ Frame Pointer register @code{r27}")
+
+(define_register_constraint "b" "SP_REGS"
+ "@internal
+ Stack Pointer register @code{r28}")
+
+(define_register_constraint "k" "LINK_REGS"
+ "@internal
+ Link Registers @code{ilink1}:@code{r29}, @code{ilink2}:@code{r30},
+ @code{blink}:@code{r31},")
+
+(define_register_constraint "q" "ARCOMPACT16_REGS"
+ "Registers usable in ARCompact 16-bit instructions: @code{r0}-@code{r3},
+ @code{r12}-@code{r15}")
+
+(define_register_constraint "e" "AC16_BASE_REGS"
+ "Registers usable as base-regs of memory addresses in ARCompact 16-bit memory
+ instructions: @code{r0}-@code{r3}, @code{r12}-@code{r15}, @code{sp}")
+
+(define_register_constraint "D" "DOUBLE_REGS"
+ "ARC FPX (dpfp) 64-bit registers. @code{D0}, @code{D1}")
+
+(define_register_constraint "d" "SIMD_DMA_CONFIG_REGS"
+ "@internal
+ ARC SIMD DMA configuration registers @code{di0}-@code{di7},
+ @code{do0}-@code{do7}")
+
+(define_register_constraint "v" "SIMD_VR_REGS"
+ "ARC SIMD 128-bit registers @code{VR0}-@code{VR23}")
+
+; We could allow call-saved registers for sibling calls if we restored them
+; in the delay slot of the call. However, that would not allow to adjust the
+; stack pointer afterwards, so the call-saved register would have to be
+; restored from a call-used register that was just loaded with the value
+; before. So sticking to call-used registers for sibcalls will likely
+; generate better code overall.
+(define_register_constraint "Rsc" "SIBCALL_REGS"
+ "@internal
+ Sibling call register")
+
+;; Integer constraints
+
+(define_constraint "I"
+ "@internal
+ A signed 12-bit integer constant."
+ (and (match_code "const_int")
+ (match_test "SIGNED_INT12 (ival)")))
+
+(define_constraint "K"
+ "@internal
+ A 3-bit unsigned integer constant"
+ (and (match_code "const_int")
+ (match_test "UNSIGNED_INT3 (ival)")))
+
+(define_constraint "L"
+ "@internal
+ A 6-bit unsigned integer constant"
+ (and (match_code "const_int")
+ (match_test "UNSIGNED_INT6 (ival)")))
+
+(define_constraint "CnL"
+ "@internal
+ One's complement of a 6-bit unsigned integer constant"
+ (and (match_code "const_int")
+ (match_test "UNSIGNED_INT6 (~ival)")))
+
+(define_constraint "CmL"
+ "@internal
+ Two's complement of a 6-bit unsigned integer constant"
+ (and (match_code "const_int")
+ (match_test "UNSIGNED_INT6 (-ival)")))
+
+(define_constraint "M"
+ "@internal
+ A 5-bit unsigned integer constant"
+ (and (match_code "const_int")
+ (match_test "UNSIGNED_INT5 (ival)")))
+
+(define_constraint "N"
+ "@internal
+ Integer constant 1"
+ (and (match_code "const_int")
+ (match_test "IS_ONE (ival)")))
+
+(define_constraint "O"
+ "@internal
+ A 7-bit unsigned integer constant"
+ (and (match_code "const_int")
+ (match_test "UNSIGNED_INT7 (ival)")))
+
+(define_constraint "P"
+ "@internal
+ An 8-bit unsigned integer constant"
+ (and (match_code "const_int")
+ (match_test "UNSIGNED_INT8 (ival)")))
+
+(define_constraint "C_0"
+ "@internal
+ Zero"
+ (and (match_code "const_int")
+ (match_test "ival == 0")))
+
+(define_constraint "Cn0"
+ "@internal
+ Negative or zero"
+ (and (match_code "const_int")
+ (match_test "ival <= 0")))
+
+(define_constraint "Cca"
+ "@internal
+ Conditional or three-address add / sub constant"
+ (and (match_code "const_int")
+ (match_test "ival == -1 << 31
+ || (ival >= -0x1f8 && ival <= 0x1f8
+ && ((ival >= 0 ? ival : -ival)
+ <= 0x3f * (ival & -ival)))")))
+
+; intersection of "O" and "Cca".
+(define_constraint "CL2"
+ "@internal
+ A 6-bit unsigned integer constant times 2"
+ (and (match_code "const_int")
+ (match_test "!(ival & ~126)")))
+
+(define_constraint "CM4"
+ "@internal
+ A 5-bit unsigned integer constant times 4"
+ (and (match_code "const_int")
+ (match_test "!(ival & ~124)")))
+
+(define_constraint "Csp"
+ "@internal
+ A valid stack pointer offset for a short add"
+ (and (match_code "const_int")
+ (match_test "!(ival & ~124) || !(-ival & ~124)")))
+
+(define_constraint "C2a"
+ "@internal
+ Unconditional two-address add / sub constant"
+ (and (match_code "const_int")
+ (match_test "ival == -1 << 31
+ || (ival >= -0x4000 && ival <= 0x4000
+ && ((ival >= 0 ? ival : -ival)
+ <= 0x7ff * (ival & -ival)))")))
+
+(define_constraint "C0p"
+ "@internal
+ power of two"
+ (and (match_code "const_int")
+ (match_test "IS_POWEROF2_P (ival)")))
+
+(define_constraint "C1p"
+ "@internal
+ constant such that x+1 is a power of two, and x != 0"
+ (and (match_code "const_int")
+ (match_test "ival && IS_POWEROF2_P (ival + 1)")))
+
+(define_constraint "Ccp"
+ "@internal
+ constant such that ~x (one's Complement) is a power of two"
+ (and (match_code "const_int")
+ (match_test "IS_POWEROF2_P (~ival)")))
+
+(define_constraint "Cux"
+ "@internal
+ constant such that AND gives an unsigned extension"
+ (and (match_code "const_int")
+ (match_test "ival == 0xff || ival == 0xffff")))
+
+(define_constraint "Crr"
+ "@internal
+ constant that can be loaded with ror b,u6"
+ (and (match_code "const_int")
+ (match_test "(ival & ~0x8000001f) == 0 && !arc_ccfsm_cond_exec_p ()")))
+
+;; Floating-point constraints
+
+(define_constraint "G"
+ "@internal
+ A 32-bit constant double value"
+ (and (match_code "const_double")
+ (match_test "arc_double_limm_p (op)")))
+
+(define_constraint "H"
+ "@internal
+ All const_double values (including 64-bit values)"
+ (and (match_code "const_double")
+ (match_test "1")))
+
+;; Memory constraints
+(define_memory_constraint "T"
+ "@internal
+ A valid memory operand for ARCompact load instructions"
+ (and (match_code "mem")
+ (match_test "compact_load_memory_operand (op, VOIDmode)")))
+
+(define_memory_constraint "S"
+ "@internal
+ A valid memory operand for ARCompact store instructions"
+ (and (match_code "mem")
+ (match_test "compact_store_memory_operand (op, VOIDmode)")))
+
+(define_memory_constraint "Usd"
+ "@internal
+ A valid _small-data_ memory operand for ARCompact instructions"
+ (and (match_code "mem")
+ (match_test "compact_sda_memory_operand (op, VOIDmode)")))
+
+(define_memory_constraint "Usc"
+ "@internal
+ A valid memory operand for storing constants"
+ (and (match_code "mem")
+ (match_test "!CONSTANT_P (XEXP (op,0))")
+;; ??? the assembler rejects stores of immediates to small data.
+ (match_test "!compact_sda_memory_operand (op, VOIDmode)")))
+
+(define_memory_constraint "Us<"
+ "@internal
+ Stack pre-decrement"
+ (and (match_code "mem")
+ (match_test "GET_CODE (XEXP (op, 0)) == PRE_DEC")
+ (match_test "REG_P (XEXP (XEXP (op, 0), 0))")
+ (match_test "REGNO (XEXP (XEXP (op, 0), 0)) == SP_REG")))
+
+(define_memory_constraint "Us>"
+ "@internal
+ Stack post-increment"
+ (and (match_code "mem")
+ (match_test "GET_CODE (XEXP (op, 0)) == POST_INC")
+ (match_test "REG_P (XEXP (XEXP (op, 0), 0))")
+ (match_test "REGNO (XEXP (XEXP (op, 0), 0)) == SP_REG")))
+
+;; General constraints
+
+(define_constraint "Cbr"
+ "Branch destination"
+ (ior (and (match_code "symbol_ref")
+ (match_test "!arc_is_longcall_p (op)"))
+ (match_code "label_ref")))
+
+(define_constraint "Cbp"
+ "predicable branch/call destination"
+ (ior (and (match_code "symbol_ref")
+ (match_test "arc_is_shortcall_p (op)"))
+ (match_code "label_ref")))
+
+(define_constraint "Cpc"
+ "pc-relative constant"
+ (match_test "arc_legitimate_pc_offset_p (op)"))
+
+(define_constraint "Clb"
+ "label"
+ (and (match_code "label_ref")
+ (match_test "arc_text_label (XEXP (op, 0))")))
+
+(define_constraint "Cal"
+ "constant for arithmetic/logical operations"
+ (match_test "immediate_operand (op, VOIDmode) && !arc_legitimate_pc_offset_p (op)"))
+
+(define_constraint "C32"
+ "32 bit constant for arithmetic/logical operations"
+ (match_test "immediate_operand (op, VOIDmode)
+ && !arc_legitimate_pc_offset_p (op)
+ && !satisfies_constraint_I (op)"))
+
+; Note that the 'cryptic' register constraints will not make reload use the
+; associated class to reload into, but this will not penalize reloading of any
+; other operands, or using an alternate part of the same alternative.
+
+; Rcq is different in three important ways from a register class constraint:
+; - It does not imply a register class, hence reload will not use it to drive
+; reloads.
+; - It matches even when there is no register class to describe its accepted
+; set; not having such a set again lessens the impact on register allocation.
+; - It won't match when the instruction is conditionalized by the ccfsm.
+(define_constraint "Rcq"
+ "@internal
+ Cryptic q - for short insn generation while not affecting register allocation
+ Registers usable in ARCompact 16-bit instructions: @code{r0}-@code{r3},
+ @code{r12}-@code{r15}"
+ (and (match_code "REG")
+ (match_test "TARGET_Rcq
+ && !arc_ccfsm_cond_exec_p ()
+ && ((((REGNO (op) & 7) ^ 4) - 4) & 15) == REGNO (op)")))
+
+; If we need a reload, we generally want to steer reload to use three-address
+; alternatives in preference of two-address alternatives, unless the
+; three-address alternative introduces a LIMM that is unnecessary for the
+; two-address alternative.
+(define_constraint "Rcw"
+ "@internal
+ Cryptic w - for use in early alternatives with matching constraint"
+ (and (match_code "REG")
+ (match_test
+ "TARGET_Rcw
+ && REGNO (op) < FIRST_PSEUDO_REGISTER
+ && TEST_HARD_REG_BIT (reg_class_contents[WRITABLE_CORE_REGS],
+ REGNO (op))")))
+
+(define_constraint "Rcr"
+ "@internal
+ Cryptic r - for use in early alternatives with matching constraint"
+ (and (match_code "REG")
+ (match_test
+ "TARGET_Rcw
+ && REGNO (op) < FIRST_PSEUDO_REGISTER
+ && TEST_HARD_REG_BIT (reg_class_contents[GENERAL_REGS],
+ REGNO (op))")))
+
+(define_constraint "Rcb"
+ "@internal
+ Stack Pointer register @code{r28} - do not reload into its class"
+ (and (match_code "REG")
+ (match_test "REGNO (op) == 28")))
+
+(define_constraint "Rck"
+ "@internal
+ blink (usful for push_s / pop_s)"
+ (and (match_code "REG")
+ (match_test "REGNO (op) == 31")))
+
+(define_constraint "Rs5"
+ "@internal
+ sibcall register - only allow one of the five available 16 bit isnsn.
+ Registers usable in ARCompact 16-bit instructions: @code{r0}-@code{r3},
+ @code{r12}"
+ (and (match_code "REG")
+ (match_test "!arc_ccfsm_cond_exec_p ()")
+ (ior (match_test "(unsigned) REGNO (op) <= 3")
+ (match_test "REGNO (op) == 12"))))
+
+(define_constraint "Rcc"
+ "@internal
+ Condition Codes"
+ (and (match_code "REG") (match_test "cc_register (op, VOIDmode)")))
+
+
+(define_constraint "Q"
+ "@internal
+ Integer constant zero"
+ (and (match_code "const_int")
+ (match_test "IS_ZERO (ival)")))
diff --git a/gcc/config/arc/fpx.md b/gcc/config/arc/fpx.md
new file mode 100644
index 00000000000..10a5dcd3b66
--- /dev/null
+++ b/gcc/config/arc/fpx.md
@@ -0,0 +1,674 @@
+;; Machine description of the Synopsys DesignWare ARC cpu Floating Point
+;; extensions for GNU C compiler
+;; Copyright (C) 2007-2013 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/>.
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; TODOs:
+;; dpfp blocks?
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Scheduler descriptions for the fpx instructions
+(define_insn_reservation "spfp_compact" 3
+ (and (match_test "TARGET_SPFP_COMPACT_SET")
+ (eq_attr "type" "spfp"))
+ "issue+core, nothing*2, write_port")
+
+(define_insn_reservation "spfp_fast" 6
+ (and (match_test "TARGET_SPFP_FAST_SET")
+ (eq_attr "type" "spfp"))
+ "issue+core, nothing*5, write_port")
+
+(define_insn_reservation "dpfp_compact_mult" 7
+ (and (match_test "TARGET_DPFP_COMPACT_SET")
+ (eq_attr "type" "dpfp_mult"))
+ "issue+core, nothing*6, write_port")
+
+(define_insn_reservation "dpfp_compact_addsub" 5
+ (and (match_test "TARGET_DPFP_COMPACT_SET")
+ (eq_attr "type" "dpfp_addsub"))
+ "issue+core, nothing*4, write_port")
+
+(define_insn_reservation "dpfp_fast" 5
+ (and (match_test "TARGET_DPFP_FAST_SET")
+ (eq_attr "type" "dpfp_mult,dpfp_addsub"))
+ "issue+core, nothing*4, write_port")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define_insn "addsf3"
+ [(set (match_operand:SF 0 "register_operand" "=r,r,r,r,r ")
+ (plus:SF (match_operand:SF 1 "nonmemory_operand" "0,r,GCal,r,0")
+ (match_operand:SF 2 "nonmemory_operand" "I,rL,r,GCal,LrCal")))]
+; "(TARGET_ARC700 || TARGET_ARC600) && TARGET_SPFP_SET";Add flag for float
+ "TARGET_SPFP"
+ "@
+ fadd %0,%1,%2
+ fadd %0,%1,%2
+ fadd %0,%S1,%2
+ fadd %0,%1,%S2
+ fadd%? %0,%1,%S2"
+ [(set_attr "type" "spfp")
+ (set_attr "length" "4,4,8,8,8")])
+
+(define_insn "subsf3"
+ [(set (match_operand:SF 0 "register_operand" "=r,r,r,r,r ")
+ (minus:SF (match_operand:SF 1 "nonmemory_operand" "r,0,GCal,r,0")
+ (match_operand:SF 2 "nonmemory_operand" "rL,I,r,GCal,LrCal")))]
+ ;"(TARGET_ARC700 || TARGET_ARC600) && TARGET_SPFP_SET";Add flag for float
+ "TARGET_SPFP"
+ "@
+ fsub %0,%1,%2
+ fsub %0,%1,%2
+ fsub %0,%S1,%2
+ fsub %0,%1,%S2
+ fsub%? %0,%1,%S2"
+ [(set_attr "type" "spfp")
+ (set_attr "length" "4,4,8,8,8")])
+
+(define_insn "mulsf3"
+ [(set (match_operand:SF 0 "register_operand" "=r,r,r,r,r ")
+ (mult:SF (match_operand:SF 1 "nonmemory_operand" "r,0,GCal,r,0")
+ (match_operand:SF 2 "nonmemory_operand" "rL,I,r,GCal,LrCal")))]
+; "(TARGET_ARC700 || TARGET_ARC600) && TARGET_SPFP_SET" ;Add flag for float
+ "TARGET_SPFP"
+ "@
+ fmul %0,%1,%2
+ fmul %0,%1,%2
+ fmul %0,%S1,%2
+ fmul %0,%1,%S2
+ fmul%? %0,%1,%S2"
+ [(set_attr "type" "spfp")
+ (set_attr "length" "4,4,8,8,8")])
+
+
+;; For comparisons, we can avoid storing the top half of the result into
+;; a register since '.f' lets us set the Z bit for the conditional
+;; branch insns.
+
+;; ??? FIXME (x-y)==0 is not a correct comparison for floats:
+;; http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
+(define_insn "cmpsfpx_raw"
+ [(set (reg:CC_FPX 61)
+ (compare:CC_FPX (match_operand:SF 0 "register_operand" "r")
+ (match_operand:SF 1 "register_operand" "r")))]
+ "TARGET_ARGONAUT_SET && TARGET_SPFP"
+ "fsub.f 0,%0,%1"
+ [(set_attr "type" "spfp")
+ (set_attr "length" "4")])
+
+;; ??? FIXME (x-y)==0 is not a correct comparison for floats:
+;; http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
+;; ??? FIXME we claim to clobber operand 2, yet the two numbers appended
+;; to the actual instructions are incorrect. The result of the d*subh
+;; insn is stored in the Dx register specified by that first number.
+(define_insn "cmpdfpx_raw"
+ [(set (reg:CC_FPX 61)
+ (compare:CC_FPX (match_operand:DF 0 "nonmemory_operand" "D,r")
+ (match_operand:DF 1 "nonmemory_operand" "r,D")))
+ (clobber (match_scratch:DF 2 "=D,D"))]
+ "TARGET_ARGONAUT_SET && TARGET_DPFP"
+ "@
+ dsubh%F0%F1.f 0,%H2,%L2
+ drsubh%F0%F2.f 0,%H1,%L1"
+ [(set_attr "type" "dpfp_addsub")
+ (set_attr "length" "4")])
+
+;; ??? FIXME subtraction is not a correct comparison for floats:
+;; http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
+(define_insn "*cmpfpx_gt"
+ [(set (reg:CC_FP_GT 61) (compare:CC_FP_GT (reg:CC_FPX 61) (const_int 0)))]
+ "TARGET_ARGONAUT_SET"
+ "cmp.ls pcl,pcl"
+ [(set_attr "type" "compare")
+ (set_attr "length" "4")])
+
+;; ??? FIXME subtraction is not a correct comparison for floats:
+;; http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
+(define_insn "*cmpfpx_ge"
+ [(set (reg:CC_FP_GE 61) (compare:CC_FP_GE (reg:CC_FPX 61) (const_int 0)))]
+ "TARGET_ARGONAUT_SET"
+ "rcmp.pnz pcl,0"
+ [(set_attr "type" "compare")
+ (set_attr "length" "4")])
+
+;; DPFP instructions begin...
+
+;; op0_reg = D1_reg.low
+(define_insn "*lr_double_lower"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec_volatile:SI [(match_operand:DF 1 "arc_double_register_operand" "D")] VUNSPEC_LR ))]
+ "TARGET_DPFP && !TARGET_DPFP_DISABLE_LRSR"
+"lr %0, [%1l] ; *lr_double_lower"
+[(set_attr "length" "8")
+(set_attr "type" "lr")]
+)
+
+(define_insn "*lr_double_higher"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec_volatile:SI [(match_operand:DF 1 "arc_double_register_operand" "D")] VUNSPEC_LR_HIGH ))]
+ "TARGET_DPFP && !TARGET_DPFP_DISABLE_LRSR"
+"lr %0, [%1h] ; *lr_double_higher"
+[(set_attr "length" "8")
+(set_attr "type" "lr")]
+)
+
+
+(define_insn "*dexcl_3op_peep2_insn"
+ [(set (match_operand:SI 0 "dest_reg_operand" "=r") ; not register_operand, to accept SUBREG
+ (unspec_volatile:SI [
+ (match_operand:DF 1 "arc_double_register_operand" "D")
+ (match_operand:SI 2 "shouldbe_register_operand" "r") ; r1
+ (match_operand:SI 3 "shouldbe_register_operand" "r") ; r0
+ ] VUNSPEC_DEXCL ))
+ ]
+ "TARGET_DPFP"
+ "dexcl%F1 %0, %2, %3"
+ [(set_attr "type" "move")
+ (set_attr "length" "4")]
+)
+
+;; version which will not overwrite operand0
+(define_insn "*dexcl_3op_peep2_insn_nores"
+ [ (unspec_volatile:SI [
+ (match_operand:DF 0 "arc_double_register_operand" "D")
+ (match_operand:SI 1 "shouldbe_register_operand" "r") ; r1
+ (match_operand:SI 2 "shouldbe_register_operand" "r") ; r0
+ ] VUNSPEC_DEXCL_NORES )
+ ]
+ "TARGET_DPFP"
+ "dexcl%F0 0, %1, %2"
+ [(set_attr "type" "move")
+ (set_attr "length" "4")]
+)
+
+;; dexcl a,b,c pattern generated by the peephole2 above
+(define_insn "*dexcl_3op_peep2_insn_lr"
+ [(parallel [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec_volatile:SI [(match_operand:DF 1 "arc_double_register_operand" "=D")] VUNSPEC_LR ))
+ (set (match_dup 1) (match_operand:DF 2 "register_operand" "r"))]
+ )
+ ]
+ "TARGET_DPFP && !TARGET_DPFP_DISABLE_LRSR"
+ "dexcl%F1 %0, %H2, %L2"
+ [(set_attr "type" "move")
+ (set_attr "length" "4")]
+)
+
+
+;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; doubles support for ARC
+;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; D0 = D1+{reg_pair}2
+;; (define_expand "adddf3"
+;; [(set (match_operand:DF 0 "arc_double_register_operand" "")
+;; (plus:DF (match_operand:DF 1 "arc_double_register_operand" "")
+;; (match_operand:DF 2 "nonmemory_operand" "")))]
+;; "TARGET_DPFP"
+;; " "
+;; )
+;; daddh{0}{1} 0, {reg_pair}2.hi, {reg_pair}2.lo
+;; OR
+;; daddh{0}{1} 0, reg3, limm2.lo
+(define_expand "adddf3"
+ [(set (match_operand:DF 0 "arc_double_register_operand" "")
+ (plus:DF (match_operand:DF 1 "arc_double_register_operand" "")
+ (match_operand:DF 2 "nonmemory_operand" "")))
+ ]
+ "TARGET_DPFP"
+ " if (GET_CODE (operands[2]) == CONST_DOUBLE)
+ {
+ rtx high, low, tmp;
+ split_double (operands[2], &low, &high);
+ tmp = force_reg (SImode, high);
+ emit_insn(gen_adddf3_insn(operands[0], operands[1], operands[2],tmp,const0_rtx));
+ }
+ else
+ emit_insn(gen_adddf3_insn(operands[0], operands[1], operands[2],const1_rtx,const1_rtx));
+ DONE;
+ "
+)
+
+;; daddh{0}{1} 0, {reg_pair}2.hi, {reg_pair}2.lo /* operand 4 = 1*/
+;; OR
+;; daddh{0}{1} 0, reg3, limm2.lo /* operand 4 = 0 */
+;;
+(define_insn "adddf3_insn"
+ [(set (match_operand:DF 0 "arc_double_register_operand" "=D,D")
+ (plus:DF (match_operand:DF 1 "arc_double_register_operand" "D,D")
+ (match_operand:DF 2 "nonmemory_operand" "!r,G")))
+ (use (match_operand:SI 3 "" "N,r"))
+ (use (match_operand:SI 4 "" "N,Q"))
+ ; Prevent can_combine_p from combining muldf3_insn patterns with
+ ; different USE pairs.
+ (use (match_dup 2))
+ ]
+ "TARGET_DPFP &&
+ !(GET_CODE(operands[2]) == CONST_DOUBLE && GET_CODE(operands[3]) == CONST_INT)"
+ "@
+ daddh%F0%F1 0,%H2,%L2
+ daddh%F0%F1 0,%3,%L2"
+ [(set_attr "type" "dpfp_addsub")
+ (set_attr "length" "4,8")])
+
+;; dmulh{0}{1} 0, {reg_pair}2.hi, {reg_pair}2.lo
+;; OR
+;; dmulh{0}{1} 0, reg3, limm2.lo
+(define_expand "muldf3"
+ [(set (match_operand:DF 0 "arc_double_register_operand" "")
+ (mult:DF (match_operand:DF 1 "arc_double_register_operand" "")
+ (match_operand:DF 2 "nonmemory_operand" "")))]
+"TARGET_DPFP"
+" if (GET_CODE (operands[2]) == CONST_DOUBLE)
+ {
+ rtx high, low, tmp;
+ split_double (operands[2], &low, &high);
+ tmp = force_reg (SImode, high);
+ emit_insn(gen_muldf3_insn(operands[0], operands[1], operands[2],tmp,const0_rtx));
+ }
+ else
+ emit_insn(gen_muldf3_insn(operands[0], operands[1], operands[2],const1_rtx,const1_rtx));
+
+ DONE;
+ ")
+
+
+;; dmulh{0}{1} 0, {reg_pair}2.hi, {reg_pair}2.lo /* operand 4 = 1*/
+;; OR
+;; dmulh{0}{1} 0, reg3, limm2.lo /* operand 4 = 0*/
+(define_insn "muldf3_insn"
+ [(set (match_operand:DF 0 "arc_double_register_operand" "=D,D")
+ (mult:DF (match_operand:DF 1 "arc_double_register_operand" "D,D")
+ (match_operand:DF 2 "nonmemory_operand" "!r,G")))
+ (use (match_operand:SI 3 "" "N,!r"))
+ (use (match_operand:SI 4 "" "N,Q"))
+ ; Prevent can_combine_p from combining muldf3_insn patterns with
+ ; different USE pairs.
+ (use (match_dup 2))
+ ]
+ "TARGET_DPFP &&
+ !(GET_CODE(operands[2]) == CONST_DOUBLE && GET_CODE(operands[3]) == CONST_INT)"
+ "@
+ dmulh%F0%F1 0,%H2,%L2
+ dmulh%F0%F1 0,%3, %L2"
+ [(set_attr "type" "dpfp_mult")
+ (set_attr "length" "4,8")])
+
+;; dsubh{0}{1} 0, {reg_pair}2.hi, {reg_pair}2.lo
+;; OR
+;; dsubh{0}{1} 0, reg3, limm2.lo
+;; OR
+;; drsubh{0}{2} 0, {reg_pair}1.hi, {reg_pair}1.lo
+;; OR
+;; drsubh{0}{2} 0, reg3, limm1.lo
+(define_expand "subdf3"
+ [(set (match_operand:DF 0 "arc_double_register_operand" "")
+ (minus:DF (match_operand:DF 1 "nonmemory_operand" "")
+ (match_operand:DF 2 "nonmemory_operand" "")))]
+"TARGET_DPFP"
+" if (GET_CODE (operands[1]) == CONST_DOUBLE || GET_CODE (operands[2]) == CONST_DOUBLE)
+ {
+ rtx high, low, tmp;
+ int const_index = ((GET_CODE (operands[1]) == CONST_DOUBLE) ? 1: 2);
+ split_double (operands[const_index], &low, &high);
+ tmp = force_reg (SImode, high);
+ emit_insn(gen_subdf3_insn(operands[0], operands[1], operands[2],tmp,const0_rtx));
+ }
+ else
+ emit_insn(gen_subdf3_insn(operands[0], operands[1], operands[2],const1_rtx,const1_rtx));
+
+ DONE;
+ "
+)
+
+;; dsubh{0}{1} 0, {reg_pair}2.hi, {reg_pair}2.lo /* operand 4 = 1 */
+;; OR
+;; dsubh{0}{1} 0, reg3, limm2.lo /* operand 4 = 0*/
+;; OR
+;; drsubh{0}{2} 0, {reg_pair}1.hi, {reg_pair}1.lo /* operand 4 = 1 */
+;; OR
+;; drsubh{0}{2} 0, reg3, limm1.lo /* operand 4 = 0*/
+(define_insn "subdf3_insn"
+ [(set (match_operand:DF 0 "arc_double_register_operand" "=D,D,D,D")
+ (minus:DF (match_operand:DF 1 "nonmemory_operand" "D,D,!r,G")
+ (match_operand:DF 2 "nonmemory_operand" "!r,G,D,D")))
+ (use (match_operand:SI 3 "" "N,r,N,r"))
+ (use (match_operand:SI 4 "" "N,Q,N,Q"))
+ ; Prevent can_combine_p from combining muldf3_insn patterns with
+ ; different USE pairs.
+ (use (match_dup 2))]
+ "TARGET_DPFP &&
+ !(GET_CODE(operands[2]) == CONST_DOUBLE && GET_CODE(operands[3]) == CONST_INT) &&
+ !(GET_CODE(operands[1]) == CONST_DOUBLE && GET_CODE(operands[3]) == CONST_INT)"
+ "@
+ dsubh%F0%F1 0,%H2,%L2
+ dsubh%F0%F1 0,%3,%L2
+ drsubh%F0%F2 0,%H1,%L1
+ drsubh%F0%F2 0,%3,%L1"
+ [(set_attr "type" "dpfp_addsub")
+ (set_attr "length" "4,8,4,8")])
+
+;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; ;; Peephole for following conversion
+;; ;; D0 = D2<op>{reg_pair}3
+;; ;; {reg_pair}5 = D0
+;; ;; D0 = {reg_pair}6
+;; ;; |
+;; ;; V
+;; ;; _________________________________________________________
+;; ;; / D0 = D2 <op> {regpair3_or_limmreg34}
+;; ;; ---- + {reg_pair}5.hi = ( D2<op>{regpair3_or_limmreg34} ).hi
+;; ;; | \_________________________________________________________
+;; ;; |
+;; ;; | ________________________________________________________
+;; ;; | / {reg_pair}5.lo = ( D2<op>{regpair3_or_limmreg34} ).lo
+;; ;; +-----+ D0 = {reg_pair}6
+;; ;; \ _________________________________________________________
+;; ;; ||
+;; ;; ||
+;; ;; \/
+;; ;; d<op>{0}{2}h {reg_pair}5.hi, {regpair3_or_limmreg34}.lo, {regpair3_or_limmreg34}.hi
+;; ;; dexcl{0} {reg_pair}5.lo, {reg_pair}6.lo, {reg_pair}6.hi
+;; ;; -----------------------------------------------------------------------------------------
+;; ;; where <op> is one of {+,*,-}
+;; ;; <opname> is {add,mult,sub}
+;; ;;
+;; ;; NOTE: For rsub insns D2 and {regpair3_or_limmreg34} get interchanged as
+;; ;; {regpair2_or_limmreg24} and D3
+;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; (define_peephole2
+;; [(parallel [(set (match_operand:DF 0 "register_operand" "")
+;; (match_operator:DF 1 "arc_dpfp_operator" [(match_operand:DF 2 "nonmemory_operand" "")
+;; (match_operand:DF 3 "nonmemory_operand" "")]))
+;; (use (match_operand:SI 4 "" ""))])
+;; (set (match_operand:DF 5 "register_operand" "")
+;; (match_dup 0))
+;; (set (match_dup 0)
+;; (match_operand:DF 6 "register_operand" ""))
+;; ]
+;; "TARGET_DPFP"
+;; [
+;; (parallel [(set (match_dup 0)
+;; (match_op_dup:DF 1 [(match_dup 2)
+;; (match_dup 3)]))
+;; (use (match_dup 4))
+;; (set (match_dup 5)
+;; (match_op_dup:DF 1 [(match_dup 2)
+;; (match_dup 3)]))])
+;; (parallel [
+;; ;; (set (subreg:SI (match_dup 5) 0)
+;; (set (match_dup 7)
+;; (unspec_volatile [(match_dup 0)] VUNSPEC_LR ))
+;; (set (match_dup 0) (match_dup 6))]
+;; )
+;; ]
+;; "operands[7] = simplify_gen_subreg(SImode,operands[5],DFmode,0);"
+;; )
+;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Peephole for following conversion
+;; D0 = D2<op>{reg_pair}3
+;; {reg_pair}6 = D0
+;; D0 = {reg_pair}7
+;; |
+;; V
+;; _________________________________________________________
+;; / D0 = D2 <op> {regpair3_or_limmreg34}
+;; ---- + {reg_pair}6.hi = ( D2<op>{regpair3_or_limmreg34} ).hi
+;; | \_________________________________________________________
+;; |
+;; | ________________________________________________________
+;; | / {reg_pair}6.lo = ( D2<op>{regpair3_or_limmreg34} ).lo
+;; +-----+ D0 = {reg_pair}7
+;; \ _________________________________________________________
+;; ||
+;; ||
+;; \/
+;; d<op>{0}{2}h {reg_pair}6.hi, {regpair3_or_limmreg34}.lo, {regpair3_or_limmreg34}.hi
+;; dexcl{0} {reg_pair}6.lo, {reg_pair}7.lo, {reg_pair}7.hi
+;; -----------------------------------------------------------------------------------------
+;; where <op> is one of {+,*,-}
+;; <opname> is {add,mult,sub}
+;;
+;; NOTE: For rsub insns D2 and {regpair3_or_limmreg34} get interchanged as
+;; {regpair2_or_limmreg24} and D3
+;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(define_peephole2
+ [(parallel [(set (match_operand:DF 0 "register_operand" "")
+ (match_operator:DF 1 "arc_dpfp_operator" [(match_operand:DF 2 "nonmemory_operand" "")
+ (match_operand:DF 3 "nonmemory_operand" "")]))
+ (use (match_operand:SI 4 "" ""))
+ (use (match_operand:SI 5 "" ""))
+ (use (match_operand:SI 6 "" ""))])
+ (set (match_operand:DF 7 "register_operand" "")
+ (match_dup 0))
+ (set (match_dup 0)
+ (match_operand:DF 8 "register_operand" ""))
+ ]
+ "TARGET_DPFP && !TARGET_DPFP_DISABLE_LRSR"
+ [
+ (parallel [(set (match_dup 0)
+ (match_op_dup:DF 1 [(match_dup 2)
+ (match_dup 3)]))
+ (use (match_dup 4))
+ (use (match_dup 5))
+ (set (match_dup 7)
+ (match_op_dup:DF 1 [(match_dup 2)
+ (match_dup 3)]))])
+ (parallel [
+;; (set (subreg:SI (match_dup 7) 0)
+ (set (match_dup 9)
+ (unspec_volatile:SI [(match_dup 0)] VUNSPEC_LR ))
+ (set (match_dup 0) (match_dup 8))]
+ )
+ ]
+ "operands[9] = simplify_gen_subreg(SImode,operands[7],DFmode,0);"
+ )
+
+;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; ;; Peephole to generate d<opname>{ij}h a,b,c instructions
+;; ;; D0 = D2<op>{reg_pair}3
+;; ;; {reg_pair}5 = D0
+;; ;; |
+;; ;; V
+;; ;; __________________________________________
+;; ;; / D0 = D2 <op> {regpair3_or_limmreg34}
+;; ;; ---- + {reg_pair}5.hi = ( D2<op>{regpair3_or_limmreg34} ).hi
+;; ;; | \__________________________________________
+;; ;; |
+;; ;; + --- {reg_pair}5.lo = ( D2<op>{regpair3_or_limmreg34} ).lo
+;; ;; ||
+;; ;; ||
+;; ;; \/
+;; ;; d<op>{0}{2}h {reg_pair}4.hi, {regpair3_or_limmreg34}.lo, {regpair3_or_limmreg34}.hi
+;; ;; lr {reg_pair}4.lo, {D2l}
+;; ;; ----------------------------------------------------------------------------------------
+;; ;; where <op> is one of {+,*,-}
+;; ;; <opname> is {add,mult,sub}
+;; ;;
+;; ;; NOTE: For rsub insns D2 and {regpair3_or_limmreg34} get interchanged as
+;; ;; {regpair2_or_limmreg24} and D3
+;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; (define_peephole2
+;; [(parallel [(set (match_operand:DF 0 "register_operand" "")
+;; (match_operator:DF 1 "arc_dpfp_operator" [(match_operand:DF 2 "nonmemory_operand" "")
+;; (match_operand:DF 3 "nonmemory_operand" "")]))
+;; (use (match_operand:SI 4 "" ""))])
+;; (set (match_operand:DF 5 "register_operand" "")
+;; (match_dup 0))
+;; ]
+;; "TARGET_DPFP"
+;; [
+;; (parallel [(set (match_dup 0)
+;; (match_op_dup:DF 1 [(match_dup 2)
+;; (match_dup 3)]))
+;; (use (match_dup 4))
+;; (set (match_dup 5)
+;; (match_op_dup:DF 1 [(match_dup 2)
+;; (match_dup 3)]))])
+;; ; (set (subreg:SI (match_dup 5) 0)
+;; (set (match_dup 6)
+;; (unspec_volatile [(match_dup 0)] VUNSPEC_LR ))
+;; ]
+;; "operands[6] = simplify_gen_subreg(SImode,operands[5],DFmode,0);"
+;; )
+;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Peephole to generate d<opname>{ij}h a,b,c instructions
+;; D0 = D2<op>{reg_pair}3
+;; {reg_pair}6 = D0
+;; |
+;; V
+;; __________________________________________
+;; / D0 = D2 <op> {regpair3_or_limmreg34}
+;; ---- + {reg_pair}6.hi = ( D2<op>{regpair3_or_limmreg34} ).hi
+;; | \__________________________________________
+;; |
+;; + --- {reg_pair}6.lo = ( D2<op>{regpair3_or_limmreg34} ).lo
+;; ||
+;; ||
+;; \/
+;; d<op>{0}{2}h {reg_pair}4.hi, {regpair3_or_limmreg34}.lo, {regpair3_or_limmreg34}.hi
+;; lr {reg_pair}4.lo, {D2l}
+;; ----------------------------------------------------------------------------------------
+;; where <op> is one of {+,*,-}
+;; <opname> is {add,mult,sub}
+;;
+;; NOTE: For rsub insns D2 and {regpair3_or_limmreg34} get interchanged as
+;; {regpair2_or_limmreg24} and D3
+;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(define_peephole2
+ [(parallel [(set (match_operand:DF 0 "register_operand" "")
+ (match_operator:DF 1 "arc_dpfp_operator" [(match_operand:DF 2 "nonmemory_operand" "")
+ (match_operand:DF 3 "nonmemory_operand" "")]))
+ (use (match_operand:SI 4 "" ""))
+ (use (match_operand:SI 5 "" ""))
+ (use (match_operand:SI 6 "" ""))])
+ (set (match_operand:DF 7 "register_operand" "")
+ (match_dup 0))
+ ]
+ "TARGET_DPFP && !TARGET_DPFP_DISABLE_LRSR"
+ [
+ (parallel [(set (match_dup 0)
+ (match_op_dup:DF 1 [(match_dup 2)
+ (match_dup 3)]))
+ (use (match_dup 4))
+ (use (match_dup 5))
+ (set (match_dup 7)
+ (match_op_dup:DF 1 [(match_dup 2)
+ (match_dup 3)]))])
+; (set (subreg:SI (match_dup 7) 0)
+ (set (match_dup 8)
+ (unspec_volatile:SI [(match_dup 0)] VUNSPEC_LR ))
+ ]
+ "operands[8] = simplify_gen_subreg(SImode,operands[7],DFmode,0);"
+ )
+
+;; ;; _______________________________________________________
+;; ;; / D0 = D1 + {regpair2_or_limmreg23}
+;; ;; + {reg_pair}4.hi = ( D1 + {regpair2_or_limmreg23} ).hi
+;; ;; \_______________________________________________________
+;; (define_insn "*daddh_peep2_insn"
+;; [(parallel [(set (match_operand:DF 0 "arc_double_register_operand" "=D,D")
+;; (plus:DF (match_operand:DF 1 "arc_double_register_operand" "D,D")
+;; (match_operand:DF 2 "nonmemory_operand" "r,G")))
+;; (use (match_operand:SI 3 "" "N,r"))
+;; (set (match_operand:DF 4 "register_operand" "=r,r")
+;; (plus:DF (match_dup 1)
+;; (match_dup 2)))])]
+;; "TARGET_DPFP"
+;; "@
+;; daddh%F0%F1 %H4, %H2, %L2
+;; daddh%F0%F1 %H4, %3, %L2"
+;; [(set_attr "type" "dpfp_addsub")
+;; (set_attr "length" "4,8")]
+;; )
+;; _______________________________________________________
+;; / D0 = D1 + {regpair2_or_limmreg23}
+;; + {reg_pair}5.hi = ( D1 + {regpair2_or_limmreg23} ).hi
+;; \_______________________________________________________
+(define_insn "*daddh_peep2_insn"
+ [(parallel [(set (match_operand:DF 0 "arc_double_register_operand" "=D,D")
+ (plus:DF (match_operand:DF 1 "arc_double_register_operand" "D,D")
+ (match_operand:DF 2 "nonmemory_operand" "r,G")))
+ (use (match_operand:SI 3 "" "N,r"))
+ (use (match_operand:SI 4 "" "N,Q"))
+ (use (match_operand:SI 5 "" ""))
+ (set (match_operand:DF 6 "register_operand" "=r,r")
+ (plus:DF (match_dup 1)
+ (match_dup 2)))])]
+ "TARGET_DPFP &&
+ !(GET_CODE(operands[2]) == CONST_DOUBLE && GET_CODE(operands[3]) == CONST_INT)"
+ "@
+ daddh%F0%F1 %H6, %H2, %L2
+ daddh%F0%F1 %H6, %3, %L2"
+ [(set_attr "type" "dpfp_addsub")
+ (set_attr "length" "4,8")]
+)
+
+;; _______________________________________________________
+;; / D0 = D1 * {regpair2_or_limmreg23}
+;; + {reg_pair}5.hi = ( D1 * {regpair2_or_limmreg23} ).hi
+;; \_______________________________________________________
+(define_insn "*dmulh_peep2_insn"
+ [(parallel [(set (match_operand:DF 0 "arc_double_register_operand" "=D,D")
+ (mult:DF (match_operand:DF 1 "arc_double_register_operand" "D,D")
+ (match_operand:DF 2 "nonmemory_operand" "r,G")))
+ (use (match_operand:SI 3 "" "N,r"))
+ (use (match_operand:SI 4 "" "N,Q"))
+ (use (match_operand:SI 5 "" ""))
+ (set (match_operand:DF 6 "register_operand" "=r,r")
+ (mult:DF (match_dup 1)
+ (match_dup 2)))])]
+ "TARGET_DPFP &&
+ !(GET_CODE(operands[2]) == CONST_DOUBLE && GET_CODE(operands[3]) == CONST_INT)"
+ "@
+ dmulh%F0%F1 %H6, %H2, %L2
+ dmulh%F0%F1 %H6, %3, %L2"
+ [(set_attr "type" "dpfp_mult")
+ (set_attr "length" "4,8")]
+)
+
+;; _______________________________________________________
+;; / D0 = D1 - {regpair2_or_limmreg23}
+;; + {reg_pair}5.hi = ( D1 - {regpair2_or_limmreg23} ).hi
+;; \_______________________________________________________
+;; OR
+;; _______________________________________________________
+;; / D0 = {regpair1_or_limmreg13} - D2
+;; + {reg_pair}5.hi = ( {regpair1_or_limmreg13} ).hi - D2
+;; \_______________________________________________________
+(define_insn "*dsubh_peep2_insn"
+ [(parallel [(set (match_operand:DF 0 "arc_double_register_operand" "=D,D,D,D")
+ (minus:DF (match_operand:DF 1 "nonmemory_operand" "D,D,r,G")
+ (match_operand:DF 2 "nonmemory_operand" "r,G,D,D")))
+ (use (match_operand:SI 3 "" "N,r,N,r"))
+ (use (match_operand:SI 4 "" "N,Q,N,Q"))
+ (use (match_operand:SI 5 "" ""))
+ (set (match_operand:DF 6 "register_operand" "=r,r,r,r")
+ (minus:DF (match_dup 1)
+ (match_dup 2)))])]
+ "TARGET_DPFP &&
+ !(GET_CODE(operands[2]) == CONST_DOUBLE && GET_CODE(operands[3]) == CONST_INT) &&
+ !(GET_CODE(operands[1]) == CONST_DOUBLE && GET_CODE(operands[3]) == CONST_INT)"
+ "@
+ dsubh%F0%F1 %H6, %H2, %L2
+ dsubh%F0%F1 %H6, %3, %L2
+ drsubh%F0%F2 %H6, %H1, %L1
+ drsubh%F0%F2 %H6, %3, %L1"
+ [(set_attr "type" "dpfp_addsub")
+ (set_attr "length" "4,8,4,8")]
+)
diff --git a/gcc/config/arc/predicates.md b/gcc/config/arc/predicates.md
new file mode 100644
index 00000000000..241fb23ee36
--- /dev/null
+++ b/gcc/config/arc/predicates.md
@@ -0,0 +1,807 @@
+;; Predicate definitions for Synopsys DesignWare ARC.
+;; Copyright (C) 2007-2013 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_predicate "dest_reg_operand"
+ (match_code "reg,subreg")
+{
+ rtx op0 = op;
+
+ if (GET_CODE (op0) == SUBREG)
+ op0 = SUBREG_REG (op0);
+ if (REG_P (op0) && REGNO (op0) < FIRST_PSEUDO_REGISTER
+ && TEST_HARD_REG_BIT (reg_class_contents[ALL_CORE_REGS],
+ REGNO (op0))
+ && !TEST_HARD_REG_BIT (reg_class_contents[WRITABLE_CORE_REGS],
+ REGNO (op0)))
+ return 0;
+ return register_operand (op, mode);
+})
+
+(define_predicate "mpy_dest_reg_operand"
+ (match_code "reg,subreg")
+{
+ rtx op0 = op;
+
+ if (GET_CODE (op0) == SUBREG)
+ op0 = SUBREG_REG (op0);
+ if (REG_P (op0) && REGNO (op0) < FIRST_PSEUDO_REGISTER
+ && TEST_HARD_REG_BIT (reg_class_contents[ALL_CORE_REGS],
+ REGNO (op0))
+ /* Make sure the destination register is not LP_COUNT. */
+ && !TEST_HARD_REG_BIT (reg_class_contents[MPY_WRITABLE_CORE_REGS],
+ REGNO (op0)))
+ return 0;
+ return register_operand (op, mode);
+})
+
+
+;; Returns 1 if OP is a symbol reference.
+(define_predicate "symbolic_operand"
+ (match_code "symbol_ref, label_ref, const")
+)
+
+;; Acceptable arguments to the call insn.
+(define_predicate "call_address_operand"
+ (ior (match_code "const_int, reg")
+ (match_operand 0 "symbolic_operand")
+ (match_test "CONSTANT_P (op)
+ && arc_legitimate_constant_p (VOIDmode, op)"))
+)
+
+(define_predicate "call_operand"
+ (and (match_code "mem")
+ (match_test "call_address_operand (XEXP (op, 0), mode)"))
+)
+
+;; Return true if OP is a unsigned 6-bit immediate (u6) value.
+(define_predicate "u6_immediate_operand"
+ (and (match_code "const_int")
+ (match_test "UNSIGNED_INT6 (INTVAL (op))"))
+)
+
+;; Return true if OP is a short immediate (shimm) value.
+(define_predicate "short_immediate_operand"
+ (and (match_code "const_int")
+ (match_test "SMALL_INT (INTVAL (op))"))
+)
+
+(define_predicate "p2_immediate_operand"
+ (and (match_code "const_int")
+ (match_test "((INTVAL (op) - 1) & INTVAL (op)) == 0")
+ (match_test "INTVAL (op)"))
+)
+
+;; Return true if OP will require a long immediate (limm) value.
+;; This is currently only used when calculating length attributes.
+(define_predicate "long_immediate_operand"
+ (match_code "symbol_ref, label_ref, const, const_double, const_int")
+{
+ switch (GET_CODE (op))
+ {
+ case SYMBOL_REF :
+ case LABEL_REF :
+ case CONST :
+ return 1;
+ case CONST_INT :
+ return !SIGNED_INT12 (INTVAL (op));
+ case CONST_DOUBLE :
+ /* These can happen because large unsigned 32 bit constants are
+ represented this way (the multiplication patterns can cause these
+ to be generated). They also occur for SFmode values. */
+ return 1;
+ default:
+ break;
+ }
+ return 0;
+}
+)
+
+;; Return true if OP is a MEM that when used as a load or store address will
+;; require an 8 byte insn.
+;; Load and store instructions don't allow the same possibilities but they're
+;; similar enough that this one function will do.
+;; This is currently only used when calculating length attributes. */
+(define_predicate "long_immediate_loadstore_operand"
+ (match_code "mem")
+{
+ int size = GET_MODE_SIZE (GET_MODE (op));
+
+ op = XEXP (op, 0);
+ switch (GET_CODE (op))
+ {
+ case SYMBOL_REF :
+ case LABEL_REF :
+ case CONST :
+ return 1;
+ case CONST_INT :
+ /* This must be handled as "st c,[limm]". Ditto for load.
+ Technically, the assembler could translate some possibilities to
+ "st c,[limm/2 + limm/2]" if limm/2 will fit in a shimm, but we don't
+ assume that it does. */
+ return 1;
+ case CONST_DOUBLE :
+ /* These can happen because large unsigned 32 bit constants are
+ represented this way (the multiplication patterns can cause these
+ to be generated). They also occur for SFmode values. */
+ return 1;
+ case REG :
+ return 0;
+ case PLUS :
+ {
+ rtx x = XEXP (op, 1);
+
+ if (GET_CODE (x) == CONST)
+ {
+ x = XEXP (x, 0);
+ if (GET_CODE (x) == PLUS)
+ x = XEXP (x, 0);
+ }
+ if (CONST_INT_P (x))
+ return (!SMALL_INT (INTVAL (x))
+ && (size <= 1 || size > 4
+ || (INTVAL (x) & (size - 1)) != 0
+ || !SMALL_INT (INTVAL (x) / size)));
+ else if (GET_CODE (x) == SYMBOL_REF)
+ return TARGET_NO_SDATA_SET || !SYMBOL_REF_SMALL_P (x);
+ return 0;
+ }
+ default:
+ break;
+ }
+ return 0;
+}
+)
+
+;; Return true if OP is any of R0-R3,R12-R15 for ARCompact 16-bit
+;; instructions
+(define_predicate "compact_register_operand"
+ (match_code "reg, subreg")
+ {
+ if ((GET_MODE (op) != mode) && (mode != VOIDmode))
+ return 0;
+
+ return (GET_CODE (op) == REG)
+ && (REGNO (op) >= FIRST_PSEUDO_REGISTER
+ || COMPACT_GP_REG_P (REGNO (op))) ;
+ }
+)
+
+;; Return true if OP is an acceptable memory operand for ARCompact
+;; 16-bit load instructions.
+(define_predicate "compact_load_memory_operand"
+ (match_code "mem")
+{
+ rtx addr, plus0, plus1;
+ int size, off;
+
+ /* Eliminate non-memory operations. */
+ if (GET_CODE (op) != MEM)
+ return 0;
+
+ /* .di instructions have no 16-bit form. */
+ if (MEM_VOLATILE_P (op) && !TARGET_VOLATILE_CACHE_SET)
+ return 0;
+
+ if (mode == VOIDmode)
+ mode = GET_MODE (op);
+
+ size = GET_MODE_SIZE (mode);
+
+ /* dword operations really put out 2 instructions, so eliminate them. */
+ if (size > UNITS_PER_WORD)
+ return 0;
+
+ /* Decode the address now. */
+ addr = XEXP (op, 0);
+ switch (GET_CODE (addr))
+ {
+ case REG:
+ return (REGNO (addr) >= FIRST_PSEUDO_REGISTER
+ || COMPACT_GP_REG_P (REGNO (addr))
+ || (SP_REG_P (REGNO (addr)) && (size != 2)));
+ /* Reverting for the moment since ldw_s does not have sp as a valid
+ parameter. */
+ case PLUS:
+ plus0 = XEXP (addr, 0);
+ plus1 = XEXP (addr, 1);
+
+ if ((GET_CODE (plus0) == REG)
+ && ((REGNO (plus0) >= FIRST_PSEUDO_REGISTER)
+ || COMPACT_GP_REG_P (REGNO (plus0)))
+ && ((GET_CODE (plus1) == REG)
+ && ((REGNO (plus1) >= FIRST_PSEUDO_REGISTER)
+ || COMPACT_GP_REG_P (REGNO (plus1)))))
+ {
+ return 1;
+ }
+
+ if ((GET_CODE (plus0) == REG)
+ && ((REGNO (plus0) >= FIRST_PSEUDO_REGISTER)
+ || COMPACT_GP_REG_P (REGNO (plus0)))
+ && (GET_CODE (plus1) == CONST_INT))
+ {
+ off = INTVAL (plus1);
+
+ /* Negative offset is not supported in 16-bit load/store insns. */
+ if (off < 0)
+ return 0;
+
+ switch (size)
+ {
+ case 1:
+ return (off < 32);
+ case 2:
+ return ((off < 64) && (off % 2 == 0));
+ case 4:
+ return ((off < 128) && (off % 4 == 0));
+ }
+ }
+
+ if ((GET_CODE (plus0) == REG)
+ && ((REGNO (plus0) >= FIRST_PSEUDO_REGISTER)
+ || SP_REG_P (REGNO (plus0)))
+ && (GET_CODE (plus1) == CONST_INT))
+ {
+ off = INTVAL (plus1);
+ return ((size != 2) && (off >= 0 && off < 128) && (off % 4 == 0));
+ }
+ default:
+ break ;
+ /* TODO: 'gp' and 'pcl' are to supported as base address operand
+ for 16-bit load instructions. */
+ }
+ return 0;
+
+}
+)
+
+;; Return true if OP is an acceptable memory operand for ARCompact
+;; 16-bit store instructions
+(define_predicate "compact_store_memory_operand"
+ (match_code "mem")
+{
+ rtx addr, plus0, plus1;
+ int size, off;
+
+ if (mode == VOIDmode)
+ mode = GET_MODE (op);
+
+ /* .di instructions have no 16-bit form. */
+ if (MEM_VOLATILE_P (op) && !TARGET_VOLATILE_CACHE_SET)
+ return 0;
+
+ size = GET_MODE_SIZE (mode);
+
+ /* dword operations really put out 2 instructions, so eliminate them. */
+ if (size > UNITS_PER_WORD)
+ return 0;
+
+ /* Decode the address now. */
+ addr = XEXP (op, 0);
+ switch (GET_CODE (addr))
+ {
+ case REG:
+ return (REGNO (addr) >= FIRST_PSEUDO_REGISTER
+ || COMPACT_GP_REG_P (REGNO (addr))
+ || (SP_REG_P (REGNO (addr)) && (size != 2)));
+ /* stw_s does not support SP as a parameter. */
+ case PLUS:
+ plus0 = XEXP (addr, 0);
+ plus1 = XEXP (addr, 1);
+
+ if ((GET_CODE (plus0) == REG)
+ && ((REGNO (plus0) >= FIRST_PSEUDO_REGISTER)
+ || COMPACT_GP_REG_P (REGNO (plus0)))
+ && (GET_CODE (plus1) == CONST_INT))
+ {
+ off = INTVAL (plus1);
+
+ /* Negative offset is not supported in 16-bit load/store insns. */
+ if (off < 0)
+ return 0;
+
+ switch (size)
+ {
+ case 1:
+ return (off < 32);
+ case 2:
+ return ((off < 64) && (off % 2 == 0));
+ case 4:
+ return ((off < 128) && (off % 4 == 0));
+ }
+ }
+
+ if ((GET_CODE (plus0) == REG)
+ && ((REGNO (plus0) >= FIRST_PSEUDO_REGISTER)
+ || SP_REG_P (REGNO (plus0)))
+ && (GET_CODE (plus1) == CONST_INT))
+ {
+ off = INTVAL (plus1);
+
+ return ((size != 2) && (off >= 0 && off < 128) && (off % 4 == 0));
+ }
+ default:
+ break;
+ }
+ return 0;
+ }
+)
+
+;; Return true if OP is an acceptable argument for a single word
+;; move source.
+(define_predicate "move_src_operand"
+ (match_code "symbol_ref, label_ref, const, const_int, const_double, reg, subreg, mem")
+{
+ switch (GET_CODE (op))
+ {
+ case SYMBOL_REF :
+ case LABEL_REF :
+ case CONST :
+ return (!flag_pic || arc_legitimate_pic_operand_p(op));
+ case CONST_INT :
+ return (LARGE_INT (INTVAL (op)));
+ case CONST_DOUBLE :
+ /* We can handle DImode integer constants in SImode if the value
+ (signed or unsigned) will fit in 32 bits. This is needed because
+ large unsigned 32 bit constants are represented as CONST_DOUBLEs. */
+ if (mode == SImode)
+ return arc_double_limm_p (op);
+ /* We can handle 32 bit floating point constants. */
+ if (mode == SFmode)
+ return GET_MODE (op) == SFmode;
+ return 0;
+ case REG :
+ return register_operand (op, mode);
+ case SUBREG :
+ /* (subreg (mem ...) ...) can occur here if the inner part was once a
+ pseudo-reg and is now a stack slot. */
+ if (GET_CODE (SUBREG_REG (op)) == MEM)
+ return address_operand (XEXP (SUBREG_REG (op), 0), mode);
+ else
+ return register_operand (op, mode);
+ case MEM :
+ return address_operand (XEXP (op, 0), mode);
+ default :
+ return 0;
+ }
+}
+)
+
+;; Return true if OP is an acceptable argument for a double word
+;; move source.
+(define_predicate "move_double_src_operand"
+ (match_code "reg, subreg, mem, const_int, const_double")
+{
+ switch (GET_CODE (op))
+ {
+ case REG :
+ return register_operand (op, mode);
+ case SUBREG :
+ /* (subreg (mem ...) ...) can occur here if the inner part was once a
+ pseudo-reg and is now a stack slot. */
+ if (GET_CODE (SUBREG_REG (op)) == MEM)
+ return move_double_src_operand (SUBREG_REG (op), mode);
+ else
+ return register_operand (op, mode);
+ case MEM :
+ return address_operand (XEXP (op, 0), mode);
+ case CONST_INT :
+ case CONST_DOUBLE :
+ return 1;
+ default :
+ return 0;
+ }
+}
+)
+
+;; Return true if OP is an acceptable argument for a move destination.
+(define_predicate "move_dest_operand"
+ (match_code "reg, subreg, mem")
+{
+ switch (GET_CODE (op))
+ {
+ case REG :
+ /* Program Counter register cannot be the target of a move. It is
+ a readonly register. */
+ if (REGNO (op) == PROGRAM_COUNTER_REGNO)
+ return 0;
+ else if (TARGET_MULMAC_32BY16_SET
+ && (REGNO (op) == 56 || REGNO(op) == 57))
+ return 0;
+ else if (TARGET_MUL64_SET
+ && (REGNO (op) == 57 || REGNO(op) == 58 || REGNO(op) == 59 ))
+ return 0;
+ else
+ return dest_reg_operand (op, mode);
+ case SUBREG :
+ /* (subreg (mem ...) ...) can occur here if the inner part was once a
+ pseudo-reg and is now a stack slot. */
+ if (GET_CODE (SUBREG_REG (op)) == MEM)
+ return address_operand (XEXP (SUBREG_REG (op), 0), mode);
+ else
+ return dest_reg_operand (op, mode);
+ case MEM :
+ {
+ rtx addr = XEXP (op, 0);
+
+ if (GET_CODE (addr) == PLUS
+ && (GET_CODE (XEXP (addr, 0)) == MULT
+ || (!CONST_INT_P (XEXP (addr, 1))
+ && (TARGET_NO_SDATA_SET
+ || GET_CODE (XEXP (addr, 1)) != SYMBOL_REF
+ || !SYMBOL_REF_SMALL_P (XEXP (addr, 1))))))
+ return 0;
+ if ((GET_CODE (addr) == PRE_MODIFY || GET_CODE (addr) == POST_MODIFY)
+ && (GET_CODE (XEXP (addr, 1)) != PLUS
+ || !CONST_INT_P (XEXP (XEXP (addr, 1), 1))))
+ return 0;
+ return address_operand (addr, mode);
+ }
+ default :
+ return 0;
+ }
+
+}
+)
+
+;; Return true if OP is valid load with update operand.
+(define_predicate "load_update_operand"
+ (match_code "mem")
+{
+ if (GET_CODE (op) != MEM
+ || GET_MODE (op) != mode)
+ return 0;
+ op = XEXP (op, 0);
+ if (GET_CODE (op) != PLUS
+ || GET_MODE (op) != Pmode
+ || !register_operand (XEXP (op, 0), Pmode)
+ || !nonmemory_operand (XEXP (op, 1), Pmode))
+ return 0;
+ return 1;
+
+}
+)
+
+;; Return true if OP is valid store with update operand.
+(define_predicate "store_update_operand"
+ (match_code "mem")
+{
+ if (GET_CODE (op) != MEM
+ || GET_MODE (op) != mode)
+ return 0;
+ op = XEXP (op, 0);
+ if (GET_CODE (op) != PLUS
+ || GET_MODE (op) != Pmode
+ || !register_operand (XEXP (op, 0), Pmode)
+ || !(GET_CODE (XEXP (op, 1)) == CONST_INT
+ && SMALL_INT (INTVAL (XEXP (op, 1)))))
+ return 0;
+ return 1;
+}
+)
+
+;; Return true if OP is a non-volatile non-immediate operand.
+;; Volatile memory refs require a special "cache-bypass" instruction
+;; and only the standard movXX patterns are set up to handle them.
+(define_predicate "nonvol_nonimm_operand"
+ (and (match_code "subreg, reg, mem")
+ (match_test "(GET_CODE (op) != MEM || !MEM_VOLATILE_P (op)) && nonimmediate_operand (op, mode)"))
+)
+
+;; Return 1 if OP is a comparison operator valid for the mode of CC.
+;; This allows the use of MATCH_OPERATOR to recognize all the branch insns.
+
+(define_predicate "proper_comparison_operator"
+ (match_code "eq, ne, le, lt, ge, gt, leu, ltu, geu, gtu, unordered, ordered, uneq, unge, ungt, unle, unlt, ltgt")
+{
+ enum rtx_code code = GET_CODE (op);
+
+ if (!COMPARISON_P (op))
+ return 0;
+
+ /* After generic flag-setting insns, we can use eq / ne / pl / mi / pnz .
+ There are some creative uses for hi / ls after shifts, but these are
+ hard to understand for the compiler and could be at best the target of
+ a peephole. */
+ switch (GET_MODE (XEXP (op, 0)))
+ {
+ case CC_ZNmode:
+ return (code == EQ || code == NE || code == GE || code == LT
+ || code == GT);
+ case CC_Zmode:
+ return code == EQ || code == NE;
+ case CC_Cmode:
+ return code == LTU || code == GEU;
+ case CC_FP_GTmode:
+ return code == GT || code == UNLE;
+ case CC_FP_GEmode:
+ return code == GE || code == UNLT;
+ case CC_FP_ORDmode:
+ return code == ORDERED || code == UNORDERED;
+ case CC_FP_UNEQmode:
+ return code == UNEQ || code == LTGT;
+ case CC_FPXmode:
+ return (code == EQ || code == NE || code == UNEQ || code == LTGT
+ || code == ORDERED || code == UNORDERED);
+
+ case CCmode:
+ case SImode: /* Used for BRcc. */
+ return 1;
+ /* From combiner. */
+ case QImode: case HImode: case DImode: case SFmode: case DFmode:
+ return 0;
+ default:
+ gcc_unreachable ();
+ }
+})
+
+(define_predicate "equality_comparison_operator"
+ (match_code "eq, ne"))
+
+(define_predicate "brcc_nolimm_operator"
+ (ior (match_test "REG_P (XEXP (op, 1))")
+ (and (match_code "eq, ne, lt, ge, ltu, geu")
+ (match_test "u6_immediate_operand (XEXP (op, 1), SImode)"))
+ (and (match_code "le, gt, leu, gtu")
+ (match_test "UNSIGNED_INT6 (INTVAL (XEXP (op, 1)) + 1)"))))
+
+;; Return TRUE if this is the condition code register, if we aren't given
+;; a mode, accept any CCmode register
+(define_special_predicate "cc_register"
+ (match_code "reg")
+{
+ if (mode == VOIDmode)
+ {
+ mode = GET_MODE (op);
+ if (GET_MODE_CLASS (mode) != MODE_CC)
+ return FALSE;
+ }
+
+ if (mode == GET_MODE (op) && GET_CODE (op) == REG && REGNO (op) == CC_REG)
+ return TRUE;
+
+ return FALSE;
+})
+
+;; Return TRUE if this is the condition code register; if we aren't given
+;; a mode, accept any CCmode register. If we are given a mode, accept
+;; modes that set a subset of flags.
+(define_special_predicate "cc_set_register"
+ (match_code "reg")
+{
+ enum machine_mode rmode = GET_MODE (op);
+
+ if (mode == VOIDmode)
+ {
+ mode = rmode;
+ if (GET_MODE_CLASS (mode) != MODE_CC)
+ return FALSE;
+ }
+
+ if (REGNO (op) != 61)
+ return FALSE;
+ if (mode == rmode
+ || (mode == CC_ZNmode && rmode == CC_Zmode)
+ || (mode == CCmode && rmode == CC_Zmode)
+ || (mode == CCmode && rmode == CC_ZNmode)
+ || (mode == CCmode && rmode == CC_Cmode))
+ return TRUE;
+
+ return FALSE;
+})
+
+; Accept CC_REG in modes which provide the flags needed for MODE. */
+(define_special_predicate "cc_use_register"
+ (match_code "reg")
+{
+ if (REGNO (op) != CC_REG)
+ return 0;
+ if (GET_MODE (op) == mode)
+ return 1;
+ switch (mode)
+ {
+ case CC_Zmode:
+ if (GET_MODE (op) == CC_ZNmode)
+ return 1;
+ /* Fall through. */
+ case CC_ZNmode: case CC_Cmode:
+ return GET_MODE (op) == CCmode;
+ default:
+ gcc_unreachable ();
+ }
+})
+
+(define_special_predicate "zn_compare_operator"
+ (match_code "compare")
+{
+ return GET_MODE (op) == CC_ZNmode || GET_MODE (op) == CC_Zmode;
+})
+
+;; Return true if OP is a shift operator.
+(define_predicate "shift_operator"
+ (match_code "ashiftrt, lshiftrt, ashift")
+)
+
+;; Return true if OP is a left shift operator that can be implemented in
+;; four insn words or less without a barrel shifter or multiplier.
+(define_predicate "shiftl4_operator"
+ (and (match_code "ashift")
+ (match_test "const_int_operand (XEXP (op, 1), VOIDmode) ")
+ (match_test "UINTVAL (XEXP (op, 1)) <= 9U
+ || INTVAL (XEXP (op, 1)) == 29
+ || INTVAL (XEXP (op, 1)) == 30
+ || INTVAL (XEXP (op, 1)) == 31")))
+
+;; Return true if OP is a right shift operator that can be implemented in
+;; four insn words or less without a barrel shifter or multiplier.
+(define_predicate "shiftr4_operator"
+ (and (match_code "ashiftrt, lshiftrt")
+ (match_test "const_int_operand (XEXP (op, 1), VOIDmode) ")
+ (match_test "UINTVAL (XEXP (op, 1)) <= 4U
+ || INTVAL (XEXP (op, 1)) == 30
+ || INTVAL (XEXP (op, 1)) == 31")))
+
+;; Return true if OP is a shift operator that can be implemented in
+;; four insn words or less without a barrel shifter or multiplier.
+(define_predicate "shift4_operator"
+ (ior (match_operand 0 "shiftl4_operator")
+ (match_operand 0 "shiftr4_operator")))
+
+(define_predicate "mult_operator"
+ (and (match_code "mult") (match_test "TARGET_ARC700 && !TARGET_NOMPY_SET"))
+)
+
+(define_predicate "commutative_operator"
+ (ior (match_code "plus,ior,xor,and")
+ (match_operand 0 "mult_operator")
+ (and (match_code "ss_plus")
+ (match_test "TARGET_ARC700 || TARGET_EA_SET")))
+)
+
+(define_predicate "commutative_operator_sans_mult"
+ (ior (match_code "plus,ior,xor,and")
+ (and (match_code "ss_plus")
+ (match_test "TARGET_ARC700 || TARGET_EA_SET")))
+)
+
+(define_predicate "noncommutative_operator"
+ (ior (match_code "minus,ashift,ashiftrt,lshiftrt,rotatert")
+ (and (match_code "ss_minus")
+ (match_test "TARGET_ARC700 || TARGET_EA_SET")))
+)
+
+(define_predicate "unary_operator"
+ (ior (match_code "abs,neg,not,sign_extend,zero_extend")
+ (and (ior (match_code "ss_neg")
+ (and (match_code "ss_truncate")
+ (match_test "GET_MODE (XEXP (op, 0)) == HImode")))
+ (match_test "TARGET_ARC700 || TARGET_EA_SET")))
+)
+
+(define_predicate "_2_4_8_operand"
+ (and (match_code "const_int")
+ (match_test "INTVAL (op) == 2 || INTVAL (op) == 4 || INTVAL (op) == 8"))
+)
+
+(define_predicate "arc_double_register_operand"
+ (match_code "reg")
+{
+ if ((GET_MODE (op) != mode) && (mode != VOIDmode))
+ return 0;
+
+ return (GET_CODE (op) == REG
+ && (REGNO (op) >= FIRST_PSEUDO_REGISTER
+ || REGNO_REG_CLASS (REGNO (op)) == DOUBLE_REGS));
+})
+
+(define_predicate "shouldbe_register_operand"
+ (match_code "reg,subreg,mem")
+{
+ return ((reload_in_progress || reload_completed)
+ ? general_operand : register_operand) (op, mode);
+})
+
+(define_predicate "vector_register_operand"
+ (match_code "reg")
+{
+ if ((GET_MODE (op) != mode) && (mode != VOIDmode))
+ return 0;
+
+ return (GET_CODE (op) == REG
+ && (REGNO (op) >= FIRST_PSEUDO_REGISTER
+ || REGNO_REG_CLASS (REGNO (op)) == SIMD_VR_REGS));
+})
+
+(define_predicate "vector_register_or_memory_operand"
+ ( ior (match_code "reg")
+ (match_code "mem"))
+{
+ if ((GET_MODE (op) != mode) && (mode != VOIDmode))
+ return 0;
+
+ if ((GET_CODE (op) == MEM)
+ && (mode == V8HImode)
+ && GET_CODE (XEXP (op,0)) == REG)
+ return 1;
+
+ return (GET_CODE (op) == REG
+ && (REGNO (op) >= FIRST_PSEUDO_REGISTER
+ || REGNO_REG_CLASS (REGNO (op)) == SIMD_VR_REGS));
+})
+
+(define_predicate "arc_dpfp_operator"
+ (match_code "plus, mult,minus")
+)
+
+(define_predicate "arc_simd_dma_register_operand"
+ (match_code "reg")
+{
+ if ((GET_MODE (op) != mode) && (mode != VOIDmode))
+ return 0;
+
+ return (GET_CODE (op) == REG
+ && (REGNO (op) >= FIRST_PSEUDO_REGISTER
+ || REGNO_REG_CLASS (REGNO (op)) == SIMD_DMA_CONFIG_REGS));
+})
+
+(define_predicate "acc1_operand"
+ (and (match_code "reg")
+ (match_test "REGNO (op) == (TARGET_BIG_ENDIAN ? 56 : 57)")))
+
+(define_predicate "acc2_operand"
+ (and (match_code "reg")
+ (match_test "REGNO (op) == (TARGET_BIG_ENDIAN ? 57 : 56)")))
+
+(define_predicate "mlo_operand"
+ (and (match_code "reg")
+ (match_test "REGNO (op) == (TARGET_BIG_ENDIAN ? 59 : 58)")))
+
+(define_predicate "mhi_operand"
+ (and (match_code "reg")
+ (match_test "REGNO (op) == (TARGET_BIG_ENDIAN ? 58 : 59)")))
+
+(define_predicate "extend_operand"
+ (ior (match_test "register_operand (op, mode)")
+ (and (match_test "immediate_operand (op, mode)")
+ (not (match_test "const_int_operand (op, mode)")))))
+
+(define_predicate "millicode_store_operation"
+ (match_code "parallel")
+{
+ return arc_check_millicode (op, 0, 0);
+})
+
+(define_predicate "millicode_load_operation"
+ (match_code "parallel")
+{
+ return arc_check_millicode (op, 2, 2);
+})
+
+(define_predicate "millicode_load_clob_operation"
+ (match_code "parallel")
+{
+ return arc_check_millicode (op, 0, 1);
+})
+
+(define_special_predicate "immediate_usidi_operand"
+ (if_then_else
+ (match_code "const_int")
+ (match_test "INTVAL (op) >= 0")
+ (and (match_test "const_double_operand (op, mode)")
+ (match_test "CONST_DOUBLE_HIGH (op) == 0"))))
diff --git a/gcc/config/arc/simdext.md b/gcc/config/arc/simdext.md
new file mode 100644
index 00000000000..65dbafd50ec
--- /dev/null
+++ b/gcc/config/arc/simdext.md
@@ -0,0 +1,1292 @@
+;; Machine description of the Synopsys DesignWare ARC cpu for GNU C compiler
+;; Copyright (C) 2007-2013 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_constants
+ [
+ ;; Va, Vb, Vc builtins
+ (UNSPEC_ARC_SIMD_VADDAW 1000)
+ (UNSPEC_ARC_SIMD_VADDW 1001)
+ (UNSPEC_ARC_SIMD_VAVB 1002)
+ (UNSPEC_ARC_SIMD_VAVRB 1003)
+ (UNSPEC_ARC_SIMD_VDIFAW 1004)
+ (UNSPEC_ARC_SIMD_VDIFW 1005)
+ (UNSPEC_ARC_SIMD_VMAXAW 1006)
+ (UNSPEC_ARC_SIMD_VMAXW 1007)
+ (UNSPEC_ARC_SIMD_VMINAW 1008)
+ (UNSPEC_ARC_SIMD_VMINW 1009)
+ (UNSPEC_ARC_SIMD_VMULAW 1010)
+ (UNSPEC_ARC_SIMD_VMULFAW 1011)
+ (UNSPEC_ARC_SIMD_VMULFW 1012)
+ (UNSPEC_ARC_SIMD_VMULW 1013)
+ (UNSPEC_ARC_SIMD_VSUBAW 1014)
+ (UNSPEC_ARC_SIMD_VSUBW 1015)
+ (UNSPEC_ARC_SIMD_VSUMMW 1016)
+ (UNSPEC_ARC_SIMD_VAND 1017)
+ (UNSPEC_ARC_SIMD_VANDAW 1018)
+ (UNSPEC_ARC_SIMD_VBIC 1019)
+ (UNSPEC_ARC_SIMD_VBICAW 1020)
+ (UNSPEC_ARC_SIMD_VOR 1021)
+ (UNSPEC_ARC_SIMD_VXOR 1022)
+ (UNSPEC_ARC_SIMD_VXORAW 1023)
+ (UNSPEC_ARC_SIMD_VEQW 1024)
+ (UNSPEC_ARC_SIMD_VLEW 1025)
+ (UNSPEC_ARC_SIMD_VLTW 1026)
+ (UNSPEC_ARC_SIMD_VNEW 1027)
+ (UNSPEC_ARC_SIMD_VMR1AW 1028)
+ (UNSPEC_ARC_SIMD_VMR1W 1029)
+ (UNSPEC_ARC_SIMD_VMR2AW 1030)
+ (UNSPEC_ARC_SIMD_VMR2W 1031)
+ (UNSPEC_ARC_SIMD_VMR3AW 1032)
+ (UNSPEC_ARC_SIMD_VMR3W 1033)
+ (UNSPEC_ARC_SIMD_VMR4AW 1034)
+ (UNSPEC_ARC_SIMD_VMR4W 1035)
+ (UNSPEC_ARC_SIMD_VMR5AW 1036)
+ (UNSPEC_ARC_SIMD_VMR5W 1037)
+ (UNSPEC_ARC_SIMD_VMR6AW 1038)
+ (UNSPEC_ARC_SIMD_VMR6W 1039)
+ (UNSPEC_ARC_SIMD_VMR7AW 1040)
+ (UNSPEC_ARC_SIMD_VMR7W 1041)
+ (UNSPEC_ARC_SIMD_VMRB 1042)
+ (UNSPEC_ARC_SIMD_VH264F 1043)
+ (UNSPEC_ARC_SIMD_VH264FT 1044)
+ (UNSPEC_ARC_SIMD_VH264FW 1045)
+ (UNSPEC_ARC_SIMD_VVC1F 1046)
+ (UNSPEC_ARC_SIMD_VVC1FT 1047)
+ ;; Va, Vb, rc/limm builtins
+ (UNSPEC_ARC_SIMD_VBADDW 1050)
+ (UNSPEC_ARC_SIMD_VBMAXW 1051)
+ (UNSPEC_ARC_SIMD_VBMINW 1052)
+ (UNSPEC_ARC_SIMD_VBMULAW 1053)
+ (UNSPEC_ARC_SIMD_VBMULFW 1054)
+ (UNSPEC_ARC_SIMD_VBMULW 1055)
+ (UNSPEC_ARC_SIMD_VBRSUBW 1056)
+ (UNSPEC_ARC_SIMD_VBSUBW 1057)
+
+ ;; Va, Vb, Ic builtins
+ (UNSPEC_ARC_SIMD_VASRW 1060)
+ (UNSPEC_ARC_SIMD_VSR8 1061)
+ (UNSPEC_ARC_SIMD_VSR8AW 1062)
+
+ ;; Va, Vb, Ic builtins
+ (UNSPEC_ARC_SIMD_VASRRWi 1065)
+ (UNSPEC_ARC_SIMD_VASRSRWi 1066)
+ (UNSPEC_ARC_SIMD_VASRWi 1067)
+ (UNSPEC_ARC_SIMD_VASRPWBi 1068)
+ (UNSPEC_ARC_SIMD_VASRRPWBi 1069)
+ (UNSPEC_ARC_SIMD_VSR8AWi 1070)
+ (UNSPEC_ARC_SIMD_VSR8i 1071)
+
+ ;; Va, Vb, u8 (simm) builtins
+ (UNSPEC_ARC_SIMD_VMVAW 1075)
+ (UNSPEC_ARC_SIMD_VMVW 1076)
+ (UNSPEC_ARC_SIMD_VMVZW 1077)
+ (UNSPEC_ARC_SIMD_VD6TAPF 1078)
+
+ ;; Va, rlimm, u8 (simm) builtins
+ (UNSPEC_ARC_SIMD_VMOVAW 1080)
+ (UNSPEC_ARC_SIMD_VMOVW 1081)
+ (UNSPEC_ARC_SIMD_VMOVZW 1082)
+
+ ;; Va, Vb builtins
+ (UNSPEC_ARC_SIMD_VABSAW 1085)
+ (UNSPEC_ARC_SIMD_VABSW 1086)
+ (UNSPEC_ARC_SIMD_VADDSUW 1087)
+ (UNSPEC_ARC_SIMD_VSIGNW 1088)
+ (UNSPEC_ARC_SIMD_VEXCH1 1089)
+ (UNSPEC_ARC_SIMD_VEXCH2 1090)
+ (UNSPEC_ARC_SIMD_VEXCH4 1091)
+ (UNSPEC_ARC_SIMD_VUPBAW 1092)
+ (UNSPEC_ARC_SIMD_VUPBW 1093)
+ (UNSPEC_ARC_SIMD_VUPSBAW 1094)
+ (UNSPEC_ARC_SIMD_VUPSBW 1095)
+
+ (UNSPEC_ARC_SIMD_VDIRUN 1100)
+ (UNSPEC_ARC_SIMD_VDORUN 1101)
+ (UNSPEC_ARC_SIMD_VDIWR 1102)
+ (UNSPEC_ARC_SIMD_VDOWR 1103)
+
+ (UNSPEC_ARC_SIMD_VREC 1105)
+ (UNSPEC_ARC_SIMD_VRUN 1106)
+ (UNSPEC_ARC_SIMD_VRECRUN 1107)
+ (UNSPEC_ARC_SIMD_VENDREC 1108)
+
+ (UNSPEC_ARC_SIMD_VCAST 1200)
+ (UNSPEC_ARC_SIMD_VINTI 1201)
+ ]
+)
+
+;; Scheduler descriptions for the simd instructions
+(define_insn_reservation "simd_lat_0_insn" 1
+ (eq_attr "type" "simd_dma, simd_vstore, simd_vcontrol")
+ "issue+simd_unit")
+
+(define_insn_reservation "simd_lat_1_insn" 2
+ (eq_attr "type" "simd_vcompare, simd_vlogic,
+ simd_vmove_else_zero, simd_varith_1cycle")
+ "issue+simd_unit, nothing")
+
+(define_insn_reservation "simd_lat_2_insn" 3
+ (eq_attr "type" "simd_valign, simd_vpermute,
+ simd_vpack, simd_varith_2cycle")
+ "issue+simd_unit, nothing*2")
+
+(define_insn_reservation "simd_lat_3_insn" 4
+ (eq_attr "type" "simd_valign_with_acc, simd_vpack_with_acc,
+ simd_vlogic_with_acc, simd_vload128,
+ simd_vmove_with_acc, simd_vspecial_3cycle,
+ simd_varith_with_acc")
+ "issue+simd_unit, nothing*3")
+
+(define_insn_reservation "simd_lat_4_insn" 5
+ (eq_attr "type" "simd_vload, simd_vmove, simd_vspecial_4cycle")
+ "issue+simd_unit, nothing*4")
+
+(define_expand "movv8hi"
+ [(set (match_operand:V8HI 0 "general_operand" "")
+ (match_operand:V8HI 1 "general_operand" ""))]
+ ""
+ "
+{
+ /* Everything except mem = const or mem = mem can be done easily. */
+
+ if (GET_CODE (operands[0]) == MEM && GET_CODE(operands[1]) == MEM)
+ operands[1] = force_reg (V8HImode, operands[1]);
+}")
+
+;; This pattern should appear before the movv8hi_insn pattern
+(define_insn "vld128_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (mem:V8HI (plus:SI (zero_extend:SI (vec_select:HI (match_operand:V8HI 1 "vector_register_operand" "v")
+ (parallel [(match_operand:SI 2 "immediate_operand" "L")])))
+ (match_operand:SI 3 "immediate_operand" "P"))))]
+ "TARGET_SIMD_SET"
+ "vld128 %0, [i%2, %3]"
+ [(set_attr "type" "simd_vload128")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")]
+)
+
+(define_insn "vst128_insn"
+ [(set (mem:V8HI (plus:SI (zero_extend:SI (vec_select:HI (match_operand:V8HI 0 "vector_register_operand" "v")
+ (parallel [(match_operand:SI 1 "immediate_operand" "L")])))
+ (match_operand:SI 2 "immediate_operand" "P")))
+ (match_operand:V8HI 3 "vector_register_operand" "=v"))]
+ "TARGET_SIMD_SET"
+ "vst128 %3, [i%1, %2]"
+ [(set_attr "type" "simd_vstore")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")]
+)
+
+(define_insn "vst64_insn"
+ [(set (mem:V4HI (plus:SI (zero_extend:SI (vec_select:HI (match_operand:V8HI 0 "vector_register_operand" "v")
+ (parallel [(match_operand:SI 1 "immediate_operand" "L")])))
+ (match_operand:SI 2 "immediate_operand" "P")))
+ (vec_select:V4HI (match_operand:V8HI 3 "vector_register_operand" "=v")
+ (parallel [(const_int 0)])))]
+ "TARGET_SIMD_SET"
+ "vst64 %3, [i%1, %2]"
+ [(set_attr "type" "simd_vstore")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")]
+)
+
+(define_insn "movv8hi_insn"
+ [(set (match_operand:V8HI 0 "vector_register_or_memory_operand" "=v,m,v")
+ (match_operand:V8HI 1 "vector_register_or_memory_operand" "m,v,v"))]
+ "TARGET_SIMD_SET && !(GET_CODE (operands[0]) == MEM && GET_CODE(operands[1]) == MEM)"
+ "@
+ vld128r %0, %1
+ vst128r %1, %0
+ vmvzw %0,%1,0xffff"
+ [(set_attr "type" "simd_vload128,simd_vstore,simd_vmove_else_zero")
+ (set_attr "length" "8,8,4")
+ (set_attr "cond" "nocond, nocond, nocond")])
+
+(define_insn "movti_insn"
+ [(set (match_operand:TI 0 "vector_register_or_memory_operand" "=v,m,v")
+ (match_operand:TI 1 "vector_register_or_memory_operand" "m,v,v"))]
+ ""
+ "@
+ vld128r %0, %1
+ vst128r %1, %0
+ vmvzw %0,%1,0xffff"
+ [(set_attr "type" "simd_vload128,simd_vstore,simd_vmove_else_zero")
+ (set_attr "length" "8,8,4")
+ (set_attr "cond" "nocond, nocond, nocond")])
+
+;; (define_insn "*movv8hi_insn_rr"
+;; [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+;; (match_operand:V8HI 1 "vector_register_operand" "v"))]
+;; ""
+;; "mov reg,reg"
+;; [(set_attr "length" "8")
+;; (set_attr "type" "move")])
+
+;; (define_insn "*movv8_out"
+;; [(set (match_operand:V8HI 0 "memory_operand" "=m")
+;; (match_operand:V8HI 1 "vector_register_operand" "v"))]
+;; ""
+;; "mov out"
+;; [(set_attr "length" "8")
+;; (set_attr "type" "move")])
+
+
+;; (define_insn "addv8hi3"
+;; [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+;; (plus:V8HI (match_operand:V8HI 1 "vector_register_operand" "v")
+;; (match_operand:V8HI 2 "vector_register_operand" "v")))]
+;; "TARGET_SIMD_SET"
+;; "vaddw %0, %1, %2"
+;; [(set_attr "length" "8")
+;; (set_attr "cond" "nocond")])
+
+;; (define_insn "vaddw_insn"
+;; [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+;; (unspec [(match_operand:V8HI 1 "vector_register_operand" "v")
+;; (match_operand:V8HI 2 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VADDW))]
+;; "TARGET_SIMD_SET"
+;; "vaddw %0, %1, %2"
+;; [(set_attr "length" "8")
+;; (set_attr "cond" "nocond")])
+
+;; V V V Insns
+(define_insn "vaddaw_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:V8HI 2 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VADDAW))]
+ "TARGET_SIMD_SET"
+ "vaddaw %0, %1, %2"
+ [(set_attr "type" "simd_varith_with_acc")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vaddw_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:V8HI 2 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VADDW))]
+ "TARGET_SIMD_SET"
+ "vaddw %0, %1, %2"
+ [(set_attr "type" "simd_varith_1cycle")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vavb_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:V8HI 2 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VAVB))]
+ "TARGET_SIMD_SET"
+ "vavb %0, %1, %2"
+ [(set_attr "type" "simd_varith_1cycle")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vavrb_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:V8HI 2 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VAVRB))]
+ "TARGET_SIMD_SET"
+ "vavrb %0, %1, %2"
+ [(set_attr "type" "simd_varith_1cycle")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vdifaw_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:V8HI 2 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VDIFAW))]
+ "TARGET_SIMD_SET"
+ "vdifaw %0, %1, %2"
+ [(set_attr "type" "simd_varith_with_acc")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vdifw_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:V8HI 2 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VDIFW))]
+ "TARGET_SIMD_SET"
+ "vdifw %0, %1, %2"
+ [(set_attr "type" "simd_varith_1cycle")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vmaxaw_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:V8HI 2 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VMAXAW))]
+ "TARGET_SIMD_SET"
+ "vmaxaw %0, %1, %2"
+ [(set_attr "type" "simd_varith_with_acc")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vmaxw_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:V8HI 2 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VMAXW))]
+ "TARGET_SIMD_SET"
+ "vmaxw %0, %1, %2"
+ [(set_attr "type" "simd_varith_1cycle")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vminaw_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:V8HI 2 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VMINAW))]
+ "TARGET_SIMD_SET"
+ "vminaw %0, %1, %2"
+ [(set_attr "type" "simd_varith_with_acc")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vminw_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:V8HI 2 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VMINW))]
+ "TARGET_SIMD_SET"
+ "vminw %0, %1, %2"
+ [(set_attr "type" "simd_varith_1cycle")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vmulaw_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:V8HI 2 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VMULAW))]
+ "TARGET_SIMD_SET"
+ "vmulaw %0, %1, %2"
+ [(set_attr "type" "simd_varith_with_acc")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vmulfaw_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:V8HI 2 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VMULFAW))]
+ "TARGET_SIMD_SET"
+ "vmulfaw %0, %1, %2"
+ [(set_attr "type" "simd_varith_with_acc")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vmulfw_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:V8HI 2 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VMULFW))]
+ "TARGET_SIMD_SET"
+ "vmulfw %0, %1, %2"
+ [(set_attr "type" "simd_varith_2cycle")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vmulw_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:V8HI 2 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VMULW))]
+ "TARGET_SIMD_SET"
+ "vmulw %0, %1, %2"
+ [(set_attr "type" "simd_varith_2cycle")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vsubaw_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:V8HI 2 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VSUBAW))]
+ "TARGET_SIMD_SET"
+ "vsubaw %0, %1, %2"
+ [(set_attr "type" "simd_varith_with_acc")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vsubw_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:V8HI 2 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VSUBW))]
+ "TARGET_SIMD_SET"
+ "vsubw %0, %1, %2"
+ [(set_attr "type" "simd_varith_1cycle")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vsummw_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:V8HI 2 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VSUMMW))]
+ "TARGET_SIMD_SET"
+ "vsummw %0, %1, %2"
+ [(set_attr "type" "simd_varith_2cycle")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vand_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:V8HI 2 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VAND))]
+ "TARGET_SIMD_SET"
+ "vand %0, %1, %2"
+ [(set_attr "type" "simd_vlogic")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vandaw_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:V8HI 2 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VANDAW))]
+ "TARGET_SIMD_SET"
+ "vandaw %0, %1, %2"
+ [(set_attr "type" "simd_vlogic_with_acc")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vbic_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:V8HI 2 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VBIC))]
+ "TARGET_SIMD_SET"
+ "vbic %0, %1, %2"
+ [(set_attr "type" "simd_vlogic")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vbicaw_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:V8HI 2 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VBICAW))]
+ "TARGET_SIMD_SET"
+ "vbicaw %0, %1, %2"
+ [(set_attr "type" "simd_vlogic_with_acc")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vor_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:V8HI 2 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VOR))]
+ "TARGET_SIMD_SET"
+ "vor %0, %1, %2"
+ [(set_attr "type" "simd_vlogic")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vxor_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:V8HI 2 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VXOR))]
+ "TARGET_SIMD_SET"
+ "vxor %0, %1, %2"
+ [(set_attr "type" "simd_vlogic")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vxoraw_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:V8HI 2 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VXORAW))]
+ "TARGET_SIMD_SET"
+ "vxoraw %0, %1, %2"
+ [(set_attr "type" "simd_vlogic_with_acc")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "veqw_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:V8HI 2 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VEQW))]
+ "TARGET_SIMD_SET"
+ "veqw %0, %1, %2"
+ [(set_attr "type" "simd_vcompare")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vlew_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:V8HI 2 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VLEW))]
+ "TARGET_SIMD_SET"
+ "vlew %0, %1, %2"
+ [(set_attr "type" "simd_vcompare")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vltw_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:V8HI 2 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VLTW))]
+ "TARGET_SIMD_SET"
+ "vltw %0, %1, %2"
+ [(set_attr "type" "simd_vcompare")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vnew_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:V8HI 2 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VNEW))]
+ "TARGET_SIMD_SET"
+ "vnew %0, %1, %2"
+ [(set_attr "type" "simd_vcompare")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vmr1aw_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:V8HI 2 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VMR1AW))]
+ "TARGET_SIMD_SET"
+ "vmr1aw %0, %1, %2"
+ [(set_attr "type" "simd_valign_with_acc")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vmr1w_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:V8HI 2 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VMR1W))]
+ "TARGET_SIMD_SET"
+ "vmr1w %0, %1, %2"
+ [(set_attr "type" "simd_valign")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vmr2aw_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:V8HI 2 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VMR2AW))]
+ "TARGET_SIMD_SET"
+ "vmr2aw %0, %1, %2"
+ [(set_attr "type" "simd_valign_with_acc")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vmr2w_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:V8HI 2 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VMR2W))]
+ "TARGET_SIMD_SET"
+ "vmr2w %0, %1, %2"
+ [(set_attr "type" "simd_valign")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vmr3aw_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:V8HI 2 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VMR3AW))]
+ "TARGET_SIMD_SET"
+ "vmr3aw %0, %1, %2"
+ [(set_attr "type" "simd_valign_with_acc")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vmr3w_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:V8HI 2 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VMR3W))]
+ "TARGET_SIMD_SET"
+ "vmr3w %0, %1, %2"
+ [(set_attr "type" "simd_valign")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vmr4aw_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:V8HI 2 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VMR4AW))]
+ "TARGET_SIMD_SET"
+ "vmr4aw %0, %1, %2"
+ [(set_attr "type" "simd_valign_with_acc")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vmr4w_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:V8HI 2 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VMR4W))]
+ "TARGET_SIMD_SET"
+ "vmr4w %0, %1, %2"
+ [(set_attr "type" "simd_valign")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vmr5aw_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:V8HI 2 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VMR5AW))]
+ "TARGET_SIMD_SET"
+ "vmr5aw %0, %1, %2"
+ [(set_attr "type" "simd_valign_with_acc")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vmr5w_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:V8HI 2 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VMR5W))]
+ "TARGET_SIMD_SET"
+ "vmr5w %0, %1, %2"
+ [(set_attr "type" "simd_valign")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vmr6aw_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:V8HI 2 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VMR6AW))]
+ "TARGET_SIMD_SET"
+ "vmr6aw %0, %1, %2"
+ [(set_attr "type" "simd_valign_with_acc")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vmr6w_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:V8HI 2 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VMR6W))]
+ "TARGET_SIMD_SET"
+ "vmr6w %0, %1, %2"
+ [(set_attr "type" "simd_valign")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vmr7aw_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:V8HI 2 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VMR7AW))]
+ "TARGET_SIMD_SET"
+ "vmr7aw %0, %1, %2"
+ [(set_attr "type" "simd_valign_with_acc")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vmr7w_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:V8HI 2 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VMR7W))]
+ "TARGET_SIMD_SET"
+ "vmr7w %0, %1, %2"
+ [(set_attr "type" "simd_valign")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vmrb_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:V8HI 2 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VMRB))]
+ "TARGET_SIMD_SET"
+ "vmrb %0, %1, %2"
+ [(set_attr "type" "simd_valign")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vh264f_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:V8HI 2 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VH264F))]
+ "TARGET_SIMD_SET"
+ "vh264f %0, %1, %2"
+ [(set_attr "type" "simd_vspecial_3cycle")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vh264ft_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:V8HI 2 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VH264FT))]
+ "TARGET_SIMD_SET"
+ "vh264ft %0, %1, %2"
+ [(set_attr "type" "simd_vspecial_3cycle")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vh264fw_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:V8HI 2 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VH264FW))]
+ "TARGET_SIMD_SET"
+ "vh264fw %0, %1, %2"
+ [(set_attr "type" "simd_vspecial_3cycle")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vvc1f_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:V8HI 2 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VVC1F))]
+ "TARGET_SIMD_SET"
+ "vvc1f %0, %1, %2"
+ [(set_attr "type" "simd_vspecial_3cycle")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vvc1ft_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:V8HI 2 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VVC1FT))]
+ "TARGET_SIMD_SET"
+ "vvc1ft %0, %1, %2"
+ [(set_attr "type" "simd_vspecial_3cycle")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+
+
+;;---
+;; V V r/limm Insns
+
+;; (define_insn "vbaddw_insn"
+;; [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+;; (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+;; (match_operand:SI 2 "nonmemory_operand" "rCal")] UNSPEC_ARC_SIMD_VBADDW))]
+;; "TARGET_SIMD_SET"
+;; "vbaddw %0, %1, %2"
+;; [(set_attr "length" "4")
+;; (set_attr "cond" "nocond")])
+
+(define_insn "vbaddw_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:SI 2 "nonmemory_operand" "r")] UNSPEC_ARC_SIMD_VBADDW))]
+ "TARGET_SIMD_SET"
+ "vbaddw %0, %1, %2"
+ [(set_attr "type" "simd_varith_1cycle")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vbmaxw_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:SI 2 "nonmemory_operand" "r")] UNSPEC_ARC_SIMD_VBMAXW))]
+ "TARGET_SIMD_SET"
+ "vbmaxw %0, %1, %2"
+ [(set_attr "type" "simd_varith_1cycle")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vbminw_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:SI 2 "nonmemory_operand" "r")] UNSPEC_ARC_SIMD_VBMINW))]
+ "TARGET_SIMD_SET"
+ "vbminw %0, %1, %2"
+ [(set_attr "type" "simd_varith_1cycle")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vbmulaw_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:SI 2 "nonmemory_operand" "r")] UNSPEC_ARC_SIMD_VBMULAW))]
+ "TARGET_SIMD_SET"
+ "vbmulaw %0, %1, %2"
+ [(set_attr "type" "simd_varith_with_acc")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vbmulfw_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:SI 2 "nonmemory_operand" "r")] UNSPEC_ARC_SIMD_VBMULFW))]
+ "TARGET_SIMD_SET"
+ "vbmulfw %0, %1, %2"
+ [(set_attr "type" "simd_varith_2cycle")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vbmulw_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:SI 2 "nonmemory_operand" "r")] UNSPEC_ARC_SIMD_VBMULW))]
+ "TARGET_SIMD_SET"
+ "vbmulw %0, %1, %2"
+ [(set_attr "type" "simd_varith_2cycle")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vbrsubw_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:SI 2 "nonmemory_operand" "r")] UNSPEC_ARC_SIMD_VBRSUBW))]
+ "TARGET_SIMD_SET"
+ "vbrsubw %0, %1, %2"
+ [(set_attr "type" "simd_varith_1cycle")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vbsubw_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:SI 2 "nonmemory_operand" "r")] UNSPEC_ARC_SIMD_VBSUBW))]
+ "TARGET_SIMD_SET"
+ "vbsubw %0, %1, %2"
+ [(set_attr "type" "simd_varith_1cycle")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+; Va, Vb, Ic instructions
+
+; Va, Vb, u6 instructions
+(define_insn "vasrrwi_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:SI 2 "immediate_operand" "L")] UNSPEC_ARC_SIMD_VASRRWi))]
+ "TARGET_SIMD_SET"
+ "vasrrwi %0, %1, %2"
+ [(set_attr "type" "simd_varith_2cycle")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vasrsrwi_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:SI 2 "immediate_operand" "L")] UNSPEC_ARC_SIMD_VASRSRWi))]
+ "TARGET_SIMD_SET"
+ "vasrsrwi %0, %1, %2"
+ [(set_attr "type" "simd_varith_2cycle")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vasrwi_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:SI 2 "immediate_operand" "L")] UNSPEC_ARC_SIMD_VASRWi))]
+ "TARGET_SIMD_SET"
+ "vasrwi %0, %1, %2"
+ [(set_attr "type" "simd_varith_1cycle")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vasrpwbi_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:SI 2 "immediate_operand" "L")] UNSPEC_ARC_SIMD_VASRPWBi))]
+ "TARGET_SIMD_SET"
+ "vasrpwbi %0, %1, %2"
+ [(set_attr "type" "simd_vpack")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vasrrpwbi_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:SI 2 "immediate_operand" "L")] UNSPEC_ARC_SIMD_VASRRPWBi))]
+ "TARGET_SIMD_SET"
+ "vasrrpwbi %0, %1, %2"
+ [(set_attr "type" "simd_vpack")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vsr8awi_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:SI 2 "immediate_operand" "L")] UNSPEC_ARC_SIMD_VSR8AWi))]
+ "TARGET_SIMD_SET"
+ "vsr8awi %0, %1, %2"
+ [(set_attr "type" "simd_valign_with_acc")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vsr8i_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:SI 2 "immediate_operand" "L")] UNSPEC_ARC_SIMD_VSR8i))]
+ "TARGET_SIMD_SET"
+ "vsr8i %0, %1, %2"
+ [(set_attr "type" "simd_valign")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+;; Va, Vb, u8 (simm) insns
+
+(define_insn "vmvaw_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:SI 2 "immediate_operand" "P")] UNSPEC_ARC_SIMD_VMVAW))]
+ "TARGET_SIMD_SET"
+ "vmvaw %0, %1, %2"
+ [(set_attr "type" "simd_vmove_with_acc")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vmvw_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:SI 2 "immediate_operand" "P")] UNSPEC_ARC_SIMD_VMVW))]
+ "TARGET_SIMD_SET"
+ "vmvw %0, %1, %2"
+ [(set_attr "type" "simd_vmove")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vmvzw_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:SI 2 "immediate_operand" "P")] UNSPEC_ARC_SIMD_VMVZW))]
+ "TARGET_SIMD_SET"
+ "vmvzw %0, %1, %2"
+ [(set_attr "type" "simd_vmove_else_zero")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vd6tapf_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:SI 2 "immediate_operand" "P")] UNSPEC_ARC_SIMD_VD6TAPF))]
+ "TARGET_SIMD_SET"
+ "vd6tapf %0, %1, %2"
+ [(set_attr "type" "simd_vspecial_4cycle")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+;; Va, rlimm, u8 (simm) insns
+(define_insn "vmovaw_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:SI 1 "nonmemory_operand" "r")
+ (match_operand:SI 2 "immediate_operand" "P")] UNSPEC_ARC_SIMD_VMOVAW))]
+ "TARGET_SIMD_SET"
+ "vmovaw %0, %1, %2"
+ [(set_attr "type" "simd_vmove_with_acc")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vmovw_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:SI 1 "nonmemory_operand" "r")
+ (match_operand:SI 2 "immediate_operand" "P")] UNSPEC_ARC_SIMD_VMOVW))]
+ "TARGET_SIMD_SET"
+ "vmovw %0, %1, %2"
+ [(set_attr "type" "simd_vmove")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vmovzw_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:SI 1 "nonmemory_operand" "r")
+ (match_operand:SI 2 "immediate_operand" "P")] UNSPEC_ARC_SIMD_VMOVZW))]
+ "TARGET_SIMD_SET"
+ "vmovzw %0, %1, %2"
+ [(set_attr "type" "simd_vmove_else_zero")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+;; Va, rlimm, Ic insns
+(define_insn "vsr8_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:SI 2 "immediate_operand" "K")
+ (match_operand:V8HI 3 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VSR8))]
+ "TARGET_SIMD_SET"
+ "vsr8 %0, %1, i%2"
+ [(set_attr "type" "simd_valign")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vasrw_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:SI 2 "immediate_operand" "K")
+ (match_operand:V8HI 3 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VASRW))]
+ "TARGET_SIMD_SET"
+ "vasrw %0, %1, i%2"
+ [(set_attr "type" "simd_varith_1cycle")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vsr8aw_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")
+ (match_operand:SI 2 "immediate_operand" "K")
+ (match_operand:V8HI 3 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VSR8AW))]
+ "TARGET_SIMD_SET"
+ "vsr8aw %0, %1, i%2"
+ [(set_attr "type" "simd_valign_with_acc")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+;; Va, Vb insns
+(define_insn "vabsaw_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VABSAW))]
+ "TARGET_SIMD_SET"
+ "vabsaw %0, %1"
+ [(set_attr "type" "simd_varith_with_acc")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vabsw_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VABSW))]
+ "TARGET_SIMD_SET"
+ "vabsw %0, %1"
+ [(set_attr "type" "simd_varith_1cycle")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vaddsuw_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VADDSUW))]
+ "TARGET_SIMD_SET"
+ "vaddsuw %0, %1"
+ [(set_attr "type" "simd_varith_1cycle")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vsignw_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VSIGNW))]
+ "TARGET_SIMD_SET"
+ "vsignw %0, %1"
+ [(set_attr "type" "simd_varith_1cycle")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vexch1_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VEXCH1))]
+ "TARGET_SIMD_SET"
+ "vexch1 %0, %1"
+ [(set_attr "type" "simd_vpermute")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vexch2_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VEXCH2))]
+ "TARGET_SIMD_SET"
+ "vexch2 %0, %1"
+ [(set_attr "type" "simd_vpermute")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vexch4_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VEXCH4))]
+ "TARGET_SIMD_SET"
+ "vexch4 %0, %1"
+ [(set_attr "type" "simd_vpermute")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vupbaw_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VUPBAW))]
+ "TARGET_SIMD_SET"
+ "vupbaw %0, %1"
+ [(set_attr "type" "simd_vpack_with_acc")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vupbw_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VUPBW))]
+ "TARGET_SIMD_SET"
+ "vupbw %0, %1"
+ [(set_attr "type" "simd_vpack")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vupsbaw_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VUPSBAW))]
+ "TARGET_SIMD_SET"
+ "vupsbaw %0, %1"
+ [(set_attr "type" "simd_vpack_with_acc")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vupsbw_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VUPSBW))]
+ "TARGET_SIMD_SET"
+ "vupsbw %0, %1"
+ [(set_attr "type" "simd_vpack")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+; DMA setup instructions
+(define_insn "vdirun_insn"
+ [(set (match_operand:SI 0 "arc_simd_dma_register_operand" "=d")
+ (unspec_volatile:SI [(match_operand:SI 1 "nonmemory_operand" "r")
+ (match_operand:SI 2 "nonmemory_operand" "r")] UNSPEC_ARC_SIMD_VDIRUN))]
+ "TARGET_SIMD_SET"
+ "vdirun %1, %2"
+ [(set_attr "type" "simd_dma")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vdorun_insn"
+ [(set (match_operand:SI 0 "arc_simd_dma_register_operand" "=d")
+ (unspec_volatile:SI [(match_operand:SI 1 "nonmemory_operand" "r")
+ (match_operand:SI 2 "nonmemory_operand" "r")] UNSPEC_ARC_SIMD_VDORUN))]
+ "TARGET_SIMD_SET"
+ "vdorun %1, %2"
+ [(set_attr "type" "simd_dma")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vdiwr_insn"
+ [(set (match_operand:SI 0 "arc_simd_dma_register_operand" "=d,d")
+ (unspec_volatile:SI [(match_operand:SI 1 "nonmemory_operand" "r,Cal")] UNSPEC_ARC_SIMD_VDIWR))]
+ "TARGET_SIMD_SET"
+ "vdiwr %0, %1"
+ [(set_attr "type" "simd_dma")
+ (set_attr "length" "4,8")
+ (set_attr "cond" "nocond,nocond")])
+
+(define_insn "vdowr_insn"
+ [(set (match_operand:SI 0 "arc_simd_dma_register_operand" "=d,d")
+ (unspec_volatile:SI [(match_operand:SI 1 "nonmemory_operand" "r,Cal")] UNSPEC_ARC_SIMD_VDOWR))]
+ "TARGET_SIMD_SET"
+ "vdowr %0, %1"
+ [(set_attr "type" "simd_dma")
+ (set_attr "length" "4,8")
+ (set_attr "cond" "nocond,nocond")])
+
+;; vector record and run instructions
+(define_insn "vrec_insn"
+ [(unspec_volatile [(match_operand:SI 0 "nonmemory_operand" "r")] UNSPEC_ARC_SIMD_VREC)]
+ "TARGET_SIMD_SET"
+ "vrec %0"
+ [(set_attr "type" "simd_vcontrol")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vrun_insn"
+ [(unspec_volatile [(match_operand:SI 0 "nonmemory_operand" "r")] UNSPEC_ARC_SIMD_VRUN)]
+ "TARGET_SIMD_SET"
+ "vrun %0"
+ [(set_attr "type" "simd_vcontrol")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vrecrun_insn"
+ [(unspec_volatile [(match_operand:SI 0 "nonmemory_operand" "r")] UNSPEC_ARC_SIMD_VRECRUN)]
+ "TARGET_SIMD_SET"
+ "vrecrun %0"
+ [(set_attr "type" "simd_vcontrol")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vendrec_insn"
+ [(unspec_volatile [(match_operand:SI 0 "nonmemory_operand" "r")] UNSPEC_ARC_SIMD_VENDREC)]
+ "TARGET_SIMD_SET"
+ "vendrec %S0"
+ [(set_attr "type" "simd_vcontrol")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vld32wh_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (vec_concat:V8HI (zero_extend:V4HI (mem:V4QI (plus:SI (match_operand:SI 1 "immediate_operand" "P")
+ (zero_extend: SI (vec_select:HI (match_operand:V8HI 2 "vector_register_operand" "v")
+ (parallel [(match_operand:SI 3 "immediate_operand" "L")]))))))
+ (vec_select:V4HI (match_dup 0)
+ (parallel [(const_int 0)]))))]
+ "TARGET_SIMD_SET"
+ "vld32wh %0, [i%3,%1]"
+ [(set_attr "type" "simd_vload")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vld32wl_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (vec_concat:V8HI (vec_select:V4HI (match_dup 0)
+ (parallel [(const_int 1)]))
+ (zero_extend:V4HI (mem:V4QI (plus:SI (match_operand:SI 1 "immediate_operand" "P")
+ (zero_extend: SI (vec_select:HI (match_operand:V8HI 2 "vector_register_operand" "v")
+ (parallel [(match_operand:SI 3 "immediate_operand" "L")])))))) ))]
+ "TARGET_SIMD_SET"
+ "vld32wl %0, [i%3,%1]"
+ [(set_attr "type" "simd_vload")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vld64w_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (zero_extend:V8HI (mem:V4HI (plus:SI (zero_extend:SI (vec_select:HI (match_operand:V8HI 1 "vector_register_operand" "v")
+ (parallel [(match_operand:SI 2 "immediate_operand" "L")])))
+ (match_operand:SI 3 "immediate_operand" "P")))))]
+ "TARGET_SIMD_SET"
+ "vld64w %0, [i%2, %3]"
+ [(set_attr "type" "simd_vload")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")]
+)
+
+(define_insn "vld64_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (vec_concat:V8HI (vec_select:V4HI (match_dup 0)
+ (parallel [(const_int 1)]))
+ (mem:V4HI (plus:SI (match_operand:SI 1 "immediate_operand" "P")
+ (zero_extend: SI (vec_select:HI (match_operand:V8HI 2 "vector_register_operand" "v")
+ (parallel [(match_operand:SI 3 "immediate_operand" "L")]))))) ))]
+ "TARGET_SIMD_SET"
+ "vld64 %0, [i%3,%1]"
+ [(set_attr "type" "simd_vload")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vld32_insn"
+ [(set (match_operand:V8HI 0 "vector_register_operand" "=v")
+ (vec_concat:V8HI (vec_select:V4HI (match_dup 0)
+ (parallel [(const_int 1)]))
+ (vec_concat:V4HI (vec_select:V2HI (match_dup 0)
+ (parallel [(const_int 1)]))
+ (mem:V2HI (plus:SI (match_operand:SI 1 "immediate_operand" "P")
+ (zero_extend: SI (vec_select:HI (match_operand:V8HI 2 "vector_register_operand" "v")
+ (parallel [(match_operand:SI 3 "immediate_operand" "L")])))))) ))]
+ "TARGET_SIMD_SET"
+ "vld32 %0, [i%3,%1]"
+ [(set_attr "type" "simd_vload")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vst16_n_insn"
+ [(set (mem:HI (plus:SI (match_operand:SI 0 "immediate_operand" "P")
+ (zero_extend: SI (vec_select:HI (match_operand:V8HI 1 "vector_register_operand" "v")
+ (parallel [(match_operand:SI 2 "immediate_operand" "L")])))))
+ (vec_select:HI (match_operand:V8HI 3 "vector_register_operand" "v")
+ (parallel [(match_operand:SI 4 "immediate_operand" "L")])))]
+ "TARGET_SIMD_SET"
+ "vst16_%4 %3,[i%2, %0]"
+ [(set_attr "type" "simd_vstore")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+(define_insn "vst32_n_insn"
+ [(set (mem:SI (plus:SI (match_operand:SI 0 "immediate_operand" "P")
+ (zero_extend: SI (vec_select:HI (match_operand:V8HI 1 "vector_register_operand" "v")
+ (parallel [(match_operand:SI 2 "immediate_operand" "L")])))))
+ (vec_select:SI (unspec:V4SI [(match_operand:V8HI 3 "vector_register_operand" "v")] UNSPEC_ARC_SIMD_VCAST)
+ (parallel [(match_operand:SI 4 "immediate_operand" "L")])))]
+ "TARGET_SIMD_SET"
+ "vst32_%4 %3,[i%2, %0]"
+ [(set_attr "type" "simd_vstore")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
+
+;; SIMD unit interrupt
+(define_insn "vinti_insn"
+ [(unspec_volatile [(match_operand:SI 0 "nonmemory_operand" "L")] UNSPEC_ARC_SIMD_VINTI)]
+ "TARGET_SIMD_SET"
+ "vinti %0"
+ [(set_attr "type" "simd_vcontrol")
+ (set_attr "length" "4")
+ (set_attr "cond" "nocond")])
diff --git a/gcc/config/arc/t-arc-newlib b/gcc/config/arc/t-arc-newlib
new file mode 100644
index 00000000000..b70b139e478
--- /dev/null
+++ b/gcc/config/arc/t-arc-newlib
@@ -0,0 +1,38 @@
+# GCC Makefile fragment for Synopsys DesignWare ARC with newlib.
+
+# Copyright (C) 2007-2013 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/>.
+
+# Selecting -mA5 uses the same functional multilib files/libraries
+# as get used for -mARC600 aka -mA6.
+MULTILIB_OPTIONS=mcpu=ARC600/mcpu=ARC601 mmul64/mmul32x16 mnorm
+MULTILIB_DIRNAMES=arc600 arc601 mul64 mul32x16 norm
+#
+# Aliases:
+MULTILIB_MATCHES = mcpu?ARC600=mcpu?arc600
+MULTILIB_MATCHES += mcpu?ARC600=mARC600
+MULTILIB_MATCHES += mcpu?ARC600=mA6
+MULTILIB_MATCHES += mcpu?ARC600=mA5
+MULTILIB_MATCHES += mcpu?ARC600=mno-mpy
+MULTILIB_MATCHES += mcpu?ARC601=mcpu?arc601
+MULTILIB_MATCHES += EL=mlittle-endian
+MULTILIB_MATCHES += EB=mbig-endian
+#
+# These don't make sense for the ARC700 default target:
+MULTILIB_EXCEPTIONS=mmul64* mmul32x16* mnorm*
+# And neither of the -mmul* options make sense without -mnorm:
+MULTILIB_EXCLUSIONS=mARC600/mmul64/!mnorm mcpu=ARC601/mmul64/!mnorm mARC600/mmul32x16/!mnorm
diff --git a/gcc/config/arc/t-arc-uClibc b/gcc/config/arc/t-arc-uClibc
new file mode 100644
index 00000000000..23baf7c0dd3
--- /dev/null
+++ b/gcc/config/arc/t-arc-uClibc
@@ -0,0 +1,20 @@
+# GCC Makefile fragment for Synopsys DesignWare ARC with uClibc
+
+# Copyright (C) 2007-2013 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/>.
+
+MULTILIB_EXTRA_OPTS = mno-sdata
diff --git a/gcc/config/arm/aarch-common-protos.h b/gcc/config/arm/aarch-common-protos.h
index 97768fce0ca..841f544e83d 100644
--- a/gcc/config/arm/aarch-common-protos.h
+++ b/gcc/config/arm/aarch-common-protos.h
@@ -1,5 +1,4 @@
-/* Function prototypes for instruction scheduling dependeoncy routines,
- defined in aarch-common.c
+/* Functions and structures shared between arm and aarch64.
Copyright (C) 1991-2013 Free Software Foundation, Inc.
Contributed by ARM Ltd.
@@ -33,4 +32,102 @@ extern int arm_no_early_alu_shift_value_dep (rtx, rtx);
extern int arm_no_early_mul_dep (rtx, rtx);
extern int arm_no_early_store_addr_dep (rtx, rtx);
+/* RTX cost table definitions. These are used when tuning for speed rather
+ than for size and should reflect the _additional_ cost over the cost
+ of the fastest instruction in the machine, which is COSTS_N_INSNS (1).
+ Therefore it's okay for some costs to be 0.
+ Costs may not have a negative value. */
+struct alu_cost_table
+{
+ const int arith; /* ADD/SUB. */
+ const int logical; /* AND/ORR/EOR/BIC, etc. */
+ const int shift; /* Simple shift. */
+ const int shift_reg; /* Simple shift by reg. */
+ const int arith_shift; /* Additional when arith also shifts... */
+ const int arith_shift_reg; /* ... and when the shift is by a reg. */
+ const int log_shift; /* Additional when logic also shifts... */
+ const int log_shift_reg; /* ... and when the shift is by a reg. */
+ const int extnd; /* Zero/sign extension. */
+ const int extnd_arith; /* Extend and arith. */
+ const int bfi; /* Bit-field insert. */
+ const int bfx; /* Bit-field extraction. */
+ const int clz; /* Count Leading Zeros. */
+ const int non_exec; /* Extra cost when not executing insn. */
+ const bool non_exec_costs_exec; /* True if non-execution must add the exec
+ cost. */
+};
+
+struct mult_cost_table
+{
+ const int simple;
+ const int flag_setting; /* Additional cost if multiply sets flags. */
+ const int extend;
+ const int add;
+ const int extend_add;
+ const int idiv;
+};
+
+/* Calculations of LDM costs are complex. We assume an initial cost
+ (ldm_1st) which will load the number of registers mentioned in
+ ldm_regs_per_insn_1st registers; then each additional
+ ldm_regs_per_insn_subsequent registers cost one more insn.
+ Similarly for STM operations.
+ Therefore the ldm_regs_per_insn_1st/stm_regs_per_insn_1st and
+ ldm_regs_per_insn_subsequent/stm_regs_per_insn_subsequent fields indicate
+ the number of registers loaded/stored and are expressed by a simple integer
+ and not by a COSTS_N_INSNS (N) expression.
+ */
+struct mem_cost_table
+{
+ const int load;
+ const int load_sign_extend; /* Additional to load cost. */
+ const int ldrd; /* Cost of LDRD. */
+ const int ldm_1st;
+ const int ldm_regs_per_insn_1st;
+ const int ldm_regs_per_insn_subsequent;
+ const int loadf; /* SFmode. */
+ const int loadd; /* DFmode. */
+ const int load_unaligned; /* Extra for unaligned loads. */
+ const int store;
+ const int strd;
+ const int stm_1st;
+ const int stm_regs_per_insn_1st;
+ const int stm_regs_per_insn_subsequent;
+ const int storef; /* SFmode. */
+ const int stored; /* DFmode. */
+ const int store_unaligned; /* Extra for unaligned stores. */
+};
+
+struct fp_cost_table
+{
+ const int div;
+ const int mult;
+ const int mult_addsub; /* Non-fused. */
+ const int fma; /* Fused. */
+ const int addsub;
+ const int fpconst; /* Immediate. */
+ const int neg; /* NEG and ABS. */
+ const int compare;
+ const int widen; /* Widen to this size. */
+ const int narrow; /* Narrow from this size. */
+ const int toint;
+ const int fromint;
+ const int roundint; /* V8 round to integral, remains FP format. */
+};
+
+struct vector_cost_table
+{
+ const int alu;
+};
+
+struct cpu_cost_table
+{
+ const struct alu_cost_table alu;
+ const struct mult_cost_table mult[2]; /* SImode and DImode. */
+ const struct mem_cost_table ldst;
+ const struct fp_cost_table fp[2]; /* SFmode and DFmode. */
+ const struct vector_cost_table vect;
+};
+
+
#endif /* GCC_AARCH_COMMON_PROTOS_H */
diff --git a/gcc/config/arm/aarch-common.c b/gcc/config/arm/aarch-common.c
index 69366af9bd5..201e581a4a6 100644
--- a/gcc/config/arm/aarch-common.c
+++ b/gcc/config/arm/aarch-common.c
@@ -21,9 +21,6 @@
<http://www.gnu.org/licenses/>. */
-/* Return nonzero if the CONSUMER instruction (a load) does need
- PRODUCER's value to calculate the address. */
-
#include "config.h"
#include "system.h"
#include "coretypes.h"
@@ -34,27 +31,139 @@
#include "c-family/c-common.h"
#include "rtl.h"
-int
-arm_early_load_addr_dep (rtx producer, rtx consumer)
+typedef struct
+{
+ rtx_code search_code;
+ rtx search_result;
+ bool find_any_shift;
+} search_term;
+
+/* Return TRUE if X is either an arithmetic shift left, or
+ is a multiplication by a power of two. */
+static bool
+arm_rtx_shift_left_p (rtx x)
+{
+ enum rtx_code code = GET_CODE (x);
+
+ if (code == MULT && CONST_INT_P (XEXP (x, 1))
+ && exact_log2 (INTVAL (XEXP (x, 1))) > 0)
+ return true;
+
+ if (code == ASHIFT)
+ return true;
+
+ return false;
+}
+
+static rtx_code shift_rtx_codes[] =
+ { ASHIFT, ROTATE, ASHIFTRT, LSHIFTRT,
+ ROTATERT, ZERO_EXTEND, SIGN_EXTEND };
+
+/* Callback function for arm_find_sub_rtx_with_code.
+ DATA is safe to treat as a SEARCH_TERM, ST. This will
+ hold a SEARCH_CODE. PATTERN is checked to see if it is an
+ RTX with that code. If it is, write SEARCH_RESULT in ST
+ and return 1. Otherwise, or if we have been passed a NULL_RTX
+ return 0. If ST.FIND_ANY_SHIFT then we are interested in
+ anything which can reasonably be described as a SHIFT RTX. */
+static int
+arm_find_sub_rtx_with_search_term (rtx *pattern, void *data)
{
- rtx value = PATTERN (producer);
- rtx addr = PATTERN (consumer);
-
- if (GET_CODE (value) == COND_EXEC)
- value = COND_EXEC_CODE (value);
- if (GET_CODE (value) == PARALLEL)
- value = XVECEXP (value, 0, 0);
- value = XEXP (value, 0);
- if (GET_CODE (addr) == COND_EXEC)
- addr = COND_EXEC_CODE (addr);
- if (GET_CODE (addr) == PARALLEL)
+ search_term *st = (search_term *) data;
+ rtx_code pattern_code;
+ int found = 0;
+
+ gcc_assert (pattern);
+ gcc_assert (st);
+
+ /* Poorly formed patterns can really ruin our day. */
+ if (*pattern == NULL_RTX)
+ return 0;
+
+ pattern_code = GET_CODE (*pattern);
+
+ if (st->find_any_shift)
{
- if (GET_CODE (XVECEXP (addr, 0, 0)) == RETURN)
- addr = XVECEXP (addr, 0, 1);
+ unsigned i = 0;
+
+ /* Left shifts might have been canonicalized to a MULT of some
+ power of two. Make sure we catch them. */
+ if (arm_rtx_shift_left_p (*pattern))
+ found = 1;
else
- addr = XVECEXP (addr, 0, 0);
+ for (i = 0; i < ARRAY_SIZE (shift_rtx_codes); i++)
+ if (pattern_code == shift_rtx_codes[i])
+ found = 1;
+ }
+
+ if (pattern_code == st->search_code)
+ found = 1;
+
+ if (found)
+ st->search_result = *pattern;
+
+ return found;
+}
+
+/* Traverse PATTERN looking for a sub-rtx with RTX_CODE CODE. */
+static rtx
+arm_find_sub_rtx_with_code (rtx pattern, rtx_code code, bool find_any_shift)
+{
+ search_term st;
+ int result = 0;
+
+ gcc_assert (pattern != NULL_RTX);
+ st.search_code = code;
+ st.search_result = NULL_RTX;
+ st.find_any_shift = find_any_shift;
+ result = for_each_rtx (&pattern, arm_find_sub_rtx_with_search_term, &st);
+ if (result)
+ return st.search_result;
+ else
+ return NULL_RTX;
+}
+
+/* Traverse PATTERN looking for any sub-rtx which looks like a shift. */
+static rtx
+arm_find_shift_sub_rtx (rtx pattern)
+{
+ return arm_find_sub_rtx_with_code (pattern, ASHIFT, true);
+}
+
+/* PRODUCER and CONSUMER are two potentially dependant RTX. PRODUCER
+ (possibly) contains a SET which will provide a result we can access
+ using the SET_DEST macro. We will place the RTX which would be
+ written by PRODUCER in SET_SOURCE.
+ Similarly, CONSUMER (possibly) contains a SET which has an operand
+ we can access using SET_SRC. We place this operand in
+ SET_DESTINATION.
+
+ Return nonzero if we found the SET RTX we expected. */
+static int
+arm_get_set_operands (rtx producer, rtx consumer,
+ rtx *set_source, rtx *set_destination)
+{
+ rtx set_producer = arm_find_sub_rtx_with_code (producer, SET, false);
+ rtx set_consumer = arm_find_sub_rtx_with_code (consumer, SET, false);
+
+ if (set_producer && set_consumer)
+ {
+ *set_source = SET_DEST (set_producer);
+ *set_destination = SET_SRC (set_consumer);
+ return 1;
}
- addr = XEXP (addr, 1);
+ return 0;
+}
+
+/* Return nonzero if the CONSUMER instruction (a load) does need
+ PRODUCER's value to calculate the address. */
+int
+arm_early_load_addr_dep (rtx producer, rtx consumer)
+{
+ rtx value, addr;
+
+ if (!arm_get_set_operands (producer, consumer, &value, &addr))
+ return 0;
return reg_overlap_mentioned_p (value, addr);
}
@@ -62,88 +171,56 @@ arm_early_load_addr_dep (rtx producer, rtx consumer)
/* Return nonzero if the CONSUMER instruction (an ALU op) does not
have an early register shift value or amount dependency on the
result of PRODUCER. */
-
int
arm_no_early_alu_shift_dep (rtx producer, rtx consumer)
{
- rtx value = PATTERN (producer);
- rtx op = PATTERN (consumer);
+ rtx value, op;
rtx early_op;
- if (GET_CODE (value) == COND_EXEC)
- value = COND_EXEC_CODE (value);
- if (GET_CODE (value) == PARALLEL)
- value = XVECEXP (value, 0, 0);
- value = XEXP (value, 0);
- if (GET_CODE (op) == COND_EXEC)
- op = COND_EXEC_CODE (op);
- if (GET_CODE (op) == PARALLEL)
- op = XVECEXP (op, 0, 0);
- op = XEXP (op, 1);
-
- early_op = XEXP (op, 0);
- /* This is either an actual independent shift, or a shift applied to
- the first operand of another operation. We want the whole shift
- operation. */
- if (REG_P (early_op))
- early_op = op;
-
- return !reg_overlap_mentioned_p (value, early_op);
+ if (!arm_get_set_operands (producer, consumer, &value, &op))
+ return 0;
+
+ if ((early_op = arm_find_shift_sub_rtx (op)))
+ {
+ if (REG_P (early_op))
+ early_op = op;
+
+ return !reg_overlap_mentioned_p (value, early_op);
+ }
+
+ return 0;
}
/* Return nonzero if the CONSUMER instruction (an ALU op) does not
have an early register shift value dependency on the result of
PRODUCER. */
-
int
arm_no_early_alu_shift_value_dep (rtx producer, rtx consumer)
{
- rtx value = PATTERN (producer);
- rtx op = PATTERN (consumer);
+ rtx value, op;
rtx early_op;
- if (GET_CODE (value) == COND_EXEC)
- value = COND_EXEC_CODE (value);
- if (GET_CODE (value) == PARALLEL)
- value = XVECEXP (value, 0, 0);
- value = XEXP (value, 0);
- if (GET_CODE (op) == COND_EXEC)
- op = COND_EXEC_CODE (op);
- if (GET_CODE (op) == PARALLEL)
- op = XVECEXP (op, 0, 0);
- op = XEXP (op, 1);
-
- early_op = XEXP (op, 0);
-
- /* This is either an actual independent shift, or a shift applied to
- the first operand of another operation. We want the value being
- shifted, in either case. */
- if (!REG_P (early_op))
- early_op = XEXP (early_op, 0);
-
- return !reg_overlap_mentioned_p (value, early_op);
+ if (!arm_get_set_operands (producer, consumer, &value, &op))
+ return 0;
+
+ if ((early_op = arm_find_shift_sub_rtx (op)))
+ /* We want to check the value being shifted. */
+ if (!reg_overlap_mentioned_p (value, XEXP (early_op, 0)))
+ return 1;
+
+ return 0;
}
/* Return nonzero if the CONSUMER (a mul or mac op) does not
have an early register mult dependency on the result of
PRODUCER. */
-
int
arm_no_early_mul_dep (rtx producer, rtx consumer)
{
- rtx value = PATTERN (producer);
- rtx op = PATTERN (consumer);
-
- if (GET_CODE (value) == COND_EXEC)
- value = COND_EXEC_CODE (value);
- if (GET_CODE (value) == PARALLEL)
- value = XVECEXP (value, 0, 0);
- value = XEXP (value, 0);
- if (GET_CODE (op) == COND_EXEC)
- op = COND_EXEC_CODE (op);
- if (GET_CODE (op) == PARALLEL)
- op = XVECEXP (op, 0, 0);
- op = XEXP (op, 1);
+ rtx value, op;
+
+ if (!arm_get_set_operands (producer, consumer, &value, &op))
+ return 0;
if (GET_CODE (op) == PLUS || GET_CODE (op) == MINUS)
{
@@ -162,19 +239,17 @@ arm_no_early_mul_dep (rtx producer, rtx consumer)
int
arm_no_early_store_addr_dep (rtx producer, rtx consumer)
{
- rtx value = PATTERN (producer);
- rtx addr = PATTERN (consumer);
-
- if (GET_CODE (value) == COND_EXEC)
- value = COND_EXEC_CODE (value);
- if (GET_CODE (value) == PARALLEL)
- value = XVECEXP (value, 0, 0);
- value = XEXP (value, 0);
- if (GET_CODE (addr) == COND_EXEC)
- addr = COND_EXEC_CODE (addr);
- if (GET_CODE (addr) == PARALLEL)
- addr = XVECEXP (addr, 0, 0);
- addr = XEXP (addr, 0);
+ rtx value = arm_find_sub_rtx_with_code (producer, SET, false);
+ rtx addr = arm_find_sub_rtx_with_code (consumer, SET, false);
+
+ if (value)
+ value = SET_DEST (value);
+
+ if (addr)
+ addr = SET_DEST (addr);
+
+ if (!value || !addr)
+ return 0;
return !reg_overlap_mentioned_p (value, addr);
}
diff --git a/gcc/config/arm/arm-cores.def b/gcc/config/arm/arm-cores.def
index 3d59fa6f5a9..79e2e87b72b 100644
--- a/gcc/config/arm/arm-cores.def
+++ b/gcc/config/arm/arm-cores.def
@@ -125,11 +125,11 @@ ARM_CORE("arm1156t2-s", arm1156t2s, 6T2, FL_LDSCHED, v6t2)
ARM_CORE("arm1156t2f-s", arm1156t2fs, 6T2, FL_LDSCHED | FL_VFPV2, v6t2)
ARM_CORE("generic-armv7-a", genericv7a, 7A, FL_LDSCHED, cortex)
ARM_CORE("cortex-a5", cortexa5, 7A, FL_LDSCHED, cortex_a5)
-ARM_CORE("cortex-a7", cortexa7, 7A, FL_LDSCHED | FL_THUMB_DIV | FL_ARM_DIV, cortex)
+ARM_CORE("cortex-a7", cortexa7, 7A, FL_LDSCHED | FL_THUMB_DIV | FL_ARM_DIV, cortex_a7)
ARM_CORE("cortex-a8", cortexa8, 7A, FL_LDSCHED, cortex)
ARM_CORE("cortex-a9", cortexa9, 7A, FL_LDSCHED, cortex_a9)
ARM_CORE("cortex-a15", cortexa15, 7A, FL_LDSCHED | FL_THUMB_DIV | FL_ARM_DIV, cortex_a15)
-ARM_CORE("cortex-a53", cortexa53, 8A, FL_LDSCHED, cortex_a5)
+ARM_CORE("cortex-a53", cortexa53, 8A, FL_LDSCHED, cortex)
ARM_CORE("cortex-r4", cortexr4, 7R, FL_LDSCHED, cortex)
ARM_CORE("cortex-r4f", cortexr4f, 7R, FL_LDSCHED, cortex)
ARM_CORE("cortex-r5", cortexr5, 7R, FL_LDSCHED | FL_ARM_DIV, cortex)
diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
index f694dfdaae2..944cf100d9a 100644
--- a/gcc/config/arm/arm-protos.h
+++ b/gcc/config/arm/arm-protos.h
@@ -246,9 +246,12 @@ struct cpu_vec_costs {
#ifdef RTX_CODE
/* This needs to be here because we need RTX_CODE and similar. */
+struct cpu_cost_table;
+
struct tune_params
{
bool (*rtx_costs) (rtx, RTX_CODE, RTX_CODE, int *, bool);
+ const struct cpu_cost_table *insn_extra_cost;
bool (*sched_adjust_cost) (rtx, rtx, rtx, int *);
int constant_limit;
/* Maximum number of instructions to conditionalise. */
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 2166001a1ec..5c534407461 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -68,6 +68,7 @@ struct four_ints
};
/* Forward function declarations. */
+static bool arm_lra_p (void);
static bool arm_needs_doubleword_align (enum machine_mode, const_tree);
static int arm_compute_static_chain_stack_bytes (void);
static arm_stack_offsets *arm_get_frame_offsets (void);
@@ -94,13 +95,11 @@ static bool arm_print_operand_punct_valid_p (unsigned char code);
static const char *fp_const_from_val (REAL_VALUE_TYPE *);
static arm_cc get_arm_condition_code (rtx);
static HOST_WIDE_INT int_log2 (HOST_WIDE_INT);
-static rtx is_jump_table (rtx);
static const char *output_multi_immediate (rtx *, const char *, const char *,
int, HOST_WIDE_INT);
static const char *shift_op (rtx, HOST_WIDE_INT *);
static struct machine_function *arm_init_machine_status (void);
static void thumb_exit (FILE *, int);
-static rtx is_jump_table (rtx);
static HOST_WIDE_INT get_jump_table_size (rtx);
static Mnode *move_minipool_fix_forward_ref (Mnode *, Mnode *, HOST_WIDE_INT);
static Mnode *add_minipool_forward_ref (Mfix *);
@@ -338,6 +337,9 @@ static const struct attribute_spec arm_attribute_table[] =
#undef TARGET_LEGITIMIZE_ADDRESS
#define TARGET_LEGITIMIZE_ADDRESS arm_legitimize_address
+#undef TARGET_LRA_P
+#define TARGET_LRA_P arm_lra_p
+
#undef TARGET_ATTRIBUTE_TABLE
#define TARGET_ATTRIBUTE_TABLE arm_attribute_table
@@ -665,6 +667,8 @@ static const struct attribute_spec arm_attribute_table[] =
#undef MAX_INSN_PER_IT_BLOCK
#define MAX_INSN_PER_IT_BLOCK (arm_restrict_it ? 1 : 4)
+#undef TARGET_CAN_USE_DOLOOP_P
+#define TARGET_CAN_USE_DOLOOP_P can_use_doloop_if_innermost
struct gcc_target targetm = TARGET_INITIALIZER;
@@ -945,10 +949,415 @@ struct cpu_vec_costs arm_default_vec_cost = {
1, /* cond_not_taken_branch_cost. */
};
+
+const struct cpu_cost_table generic_extra_costs =
+{
+ /* ALU */
+ {
+ 0, /* Arith. */
+ 0, /* Logical. */
+ 0, /* Shift. */
+ COSTS_N_INSNS (1), /* Shift_reg. */
+ 0, /* Arith_shift. */
+ COSTS_N_INSNS (1), /* Arith_shift_reg. */
+ 0, /* Log_shift. */
+ COSTS_N_INSNS (1), /* Log_shift_reg. */
+ 0, /* Extend. */
+ COSTS_N_INSNS (1), /* Extend_arith. */
+ 0, /* Bfi. */
+ 0, /* Bfx. */
+ 0, /* Clz. */
+ COSTS_N_INSNS (1), /* non_exec. */
+ false /* non_exec_costs_exec. */
+ },
+ /* MULT SImode */
+ {
+ {
+ COSTS_N_INSNS (2), /* Simple. */
+ COSTS_N_INSNS (1), /* Flag_setting. */
+ COSTS_N_INSNS (2), /* Extend. */
+ COSTS_N_INSNS (3), /* Add. */
+ COSTS_N_INSNS (3), /* Extend_add. */
+ COSTS_N_INSNS (8) /* Idiv. */
+ },
+ /* MULT DImode */
+ {
+ 0, /* Simple (N/A). */
+ 0, /* Flag_setting (N/A). */
+ COSTS_N_INSNS (2), /* Extend. */
+ 0, /* Add (N/A). */
+ COSTS_N_INSNS (3), /* Extend_add. */
+ 0 /* Idiv (N/A). */
+ }
+ },
+ /* LD/ST */
+ {
+ COSTS_N_INSNS (2), /* Load. */
+ COSTS_N_INSNS (2), /* Load_sign_extend. */
+ COSTS_N_INSNS (3), /* Ldrd. */
+ COSTS_N_INSNS (2), /* Ldm_1st. */
+ 1, /* Ldm_regs_per_insn_1st. */
+ 1, /* Ldm_regs_per_insn_subsequent. */
+ COSTS_N_INSNS (2), /* Loadf. */
+ COSTS_N_INSNS (3), /* Loadd. */
+ COSTS_N_INSNS (1), /* Load_unaligned. */
+ COSTS_N_INSNS (2), /* Store. */
+ COSTS_N_INSNS (3), /* Strd. */
+ COSTS_N_INSNS (2), /* Stm_1st. */
+ 1, /* Stm_regs_per_insn_1st. */
+ 1, /* Stm_regs_per_insn_subsequent. */
+ COSTS_N_INSNS (2), /* Storef. */
+ COSTS_N_INSNS (3), /* Stored. */
+ COSTS_N_INSNS (1) /* Store_unaligned. */
+ },
+ {
+ /* FP SFmode */
+ {
+ COSTS_N_INSNS (7), /* Div. */
+ COSTS_N_INSNS (2), /* Mult. */
+ COSTS_N_INSNS (3), /* Mult_addsub. */
+ COSTS_N_INSNS (3), /* Fma. */
+ COSTS_N_INSNS (1), /* Addsub. */
+ 0, /* Fpconst. */
+ 0, /* Neg. */
+ 0, /* Compare. */
+ 0, /* Widen. */
+ 0, /* Narrow. */
+ 0, /* Toint. */
+ 0, /* Fromint. */
+ 0 /* Roundint. */
+ },
+ /* FP DFmode */
+ {
+ COSTS_N_INSNS (15), /* Div. */
+ COSTS_N_INSNS (5), /* Mult. */
+ COSTS_N_INSNS (7), /* Mult_addsub. */
+ COSTS_N_INSNS (7), /* Fma. */
+ COSTS_N_INSNS (3), /* Addsub. */
+ 0, /* Fpconst. */
+ 0, /* Neg. */
+ 0, /* Compare. */
+ 0, /* Widen. */
+ 0, /* Narrow. */
+ 0, /* Toint. */
+ 0, /* Fromint. */
+ 0 /* Roundint. */
+ }
+ },
+ /* Vector */
+ {
+ COSTS_N_INSNS (1) /* Alu. */
+ }
+};
+
+
+const struct cpu_cost_table cortexa9_extra_costs =
+{
+ /* ALU */
+ {
+ 0, /* Arith. */
+ 0, /* Logical. */
+ 0, /* Shift. */
+ COSTS_N_INSNS (1), /* Shift_reg. */
+ COSTS_N_INSNS (1), /* Arith_shift. */
+ COSTS_N_INSNS (2), /* Arith_shift_reg. */
+ 0, /* Log_shift. */
+ COSTS_N_INSNS (1), /* Log_shift_reg. */
+ COSTS_N_INSNS (1), /* Extend. */
+ COSTS_N_INSNS (2), /* Extend_arith. */
+ COSTS_N_INSNS (1), /* Bfi. */
+ COSTS_N_INSNS (1), /* Bfx. */
+ 0, /* Clz. */
+ 0, /* non_exec. */
+ true /* non_exec_costs_exec. */
+ },
+ {
+ /* MULT SImode */
+ {
+ COSTS_N_INSNS (3), /* Simple. */
+ COSTS_N_INSNS (3), /* Flag_setting. */
+ COSTS_N_INSNS (2), /* Extend. */
+ COSTS_N_INSNS (3), /* Add. */
+ COSTS_N_INSNS (2), /* Extend_add. */
+ COSTS_N_INSNS (30) /* Idiv. No HW div on Cortex A9. */
+ },
+ /* MULT DImode */
+ {
+ 0, /* Simple (N/A). */
+ 0, /* Flag_setting (N/A). */
+ COSTS_N_INSNS (4), /* Extend. */
+ 0, /* Add (N/A). */
+ COSTS_N_INSNS (4), /* Extend_add. */
+ 0 /* Idiv (N/A). */
+ }
+ },
+ /* LD/ST */
+ {
+ COSTS_N_INSNS (2), /* Load. */
+ COSTS_N_INSNS (2), /* Load_sign_extend. */
+ COSTS_N_INSNS (2), /* Ldrd. */
+ COSTS_N_INSNS (2), /* Ldm_1st. */
+ 1, /* Ldm_regs_per_insn_1st. */
+ 2, /* Ldm_regs_per_insn_subsequent. */
+ COSTS_N_INSNS (5), /* Loadf. */
+ COSTS_N_INSNS (5), /* Loadd. */
+ COSTS_N_INSNS (1), /* Load_unaligned. */
+ COSTS_N_INSNS (2), /* Store. */
+ COSTS_N_INSNS (2), /* Strd. */
+ COSTS_N_INSNS (2), /* Stm_1st. */
+ 1, /* Stm_regs_per_insn_1st. */
+ 2, /* Stm_regs_per_insn_subsequent. */
+ COSTS_N_INSNS (1), /* Storef. */
+ COSTS_N_INSNS (1), /* Stored. */
+ COSTS_N_INSNS (1) /* Store_unaligned. */
+ },
+ {
+ /* FP SFmode */
+ {
+ COSTS_N_INSNS (14), /* Div. */
+ COSTS_N_INSNS (4), /* Mult. */
+ COSTS_N_INSNS (7), /* Mult_addsub. */
+ COSTS_N_INSNS (30), /* Fma. */
+ COSTS_N_INSNS (3), /* Addsub. */
+ COSTS_N_INSNS (1), /* Fpconst. */
+ COSTS_N_INSNS (1), /* Neg. */
+ COSTS_N_INSNS (3), /* Compare. */
+ COSTS_N_INSNS (3), /* Widen. */
+ COSTS_N_INSNS (3), /* Narrow. */
+ COSTS_N_INSNS (3), /* Toint. */
+ COSTS_N_INSNS (3), /* Fromint. */
+ COSTS_N_INSNS (3) /* Roundint. */
+ },
+ /* FP DFmode */
+ {
+ COSTS_N_INSNS (24), /* Div. */
+ COSTS_N_INSNS (5), /* Mult. */
+ COSTS_N_INSNS (8), /* Mult_addsub. */
+ COSTS_N_INSNS (30), /* Fma. */
+ COSTS_N_INSNS (3), /* Addsub. */
+ COSTS_N_INSNS (1), /* Fpconst. */
+ COSTS_N_INSNS (1), /* Neg. */
+ COSTS_N_INSNS (3), /* Compare. */
+ COSTS_N_INSNS (3), /* Widen. */
+ COSTS_N_INSNS (3), /* Narrow. */
+ COSTS_N_INSNS (3), /* Toint. */
+ COSTS_N_INSNS (3), /* Fromint. */
+ COSTS_N_INSNS (3) /* Roundint. */
+ }
+ },
+ /* Vector */
+ {
+ COSTS_N_INSNS (1) /* Alu. */
+ }
+};
+
+
+const struct cpu_cost_table cortexa7_extra_costs =
+{
+ /* ALU */
+ {
+ 0, /* Arith. */
+ 0, /* Logical. */
+ COSTS_N_INSNS (1), /* Shift. */
+ COSTS_N_INSNS (1), /* Shift_reg. */
+ COSTS_N_INSNS (1), /* Arith_shift. */
+ COSTS_N_INSNS (1), /* Arith_shift_reg. */
+ COSTS_N_INSNS (1), /* Log_shift. */
+ COSTS_N_INSNS (1), /* Log_shift_reg. */
+ COSTS_N_INSNS (1), /* Extend. */
+ COSTS_N_INSNS (1), /* Extend_arith. */
+ COSTS_N_INSNS (1), /* Bfi. */
+ COSTS_N_INSNS (1), /* Bfx. */
+ COSTS_N_INSNS (1), /* Clz. */
+ 0, /* non_exec. */
+ true /* non_exec_costs_exec. */
+ },
+
+ {
+ /* MULT SImode */
+ {
+ 0, /* Simple. */
+ COSTS_N_INSNS (1), /* Flag_setting. */
+ COSTS_N_INSNS (1), /* Extend. */
+ COSTS_N_INSNS (1), /* Add. */
+ COSTS_N_INSNS (1), /* Extend_add. */
+ COSTS_N_INSNS (7) /* Idiv. */
+ },
+ /* MULT DImode */
+ {
+ 0, /* Simple (N/A). */
+ 0, /* Flag_setting (N/A). */
+ COSTS_N_INSNS (1), /* Extend. */
+ 0, /* Add. */
+ COSTS_N_INSNS (2), /* Extend_add. */
+ 0 /* Idiv (N/A). */
+ }
+ },
+ /* LD/ST */
+ {
+ COSTS_N_INSNS (1), /* Load. */
+ COSTS_N_INSNS (1), /* Load_sign_extend. */
+ COSTS_N_INSNS (3), /* Ldrd. */
+ COSTS_N_INSNS (1), /* Ldm_1st. */
+ 1, /* Ldm_regs_per_insn_1st. */
+ 2, /* Ldm_regs_per_insn_subsequent. */
+ COSTS_N_INSNS (2), /* Loadf. */
+ COSTS_N_INSNS (2), /* Loadd. */
+ COSTS_N_INSNS (1), /* Load_unaligned. */
+ COSTS_N_INSNS (1), /* Store. */
+ COSTS_N_INSNS (3), /* Strd. */
+ COSTS_N_INSNS (1), /* Stm_1st. */
+ 1, /* Stm_regs_per_insn_1st. */
+ 2, /* Stm_regs_per_insn_subsequent. */
+ COSTS_N_INSNS (2), /* Storef. */
+ COSTS_N_INSNS (2), /* Stored. */
+ COSTS_N_INSNS (1) /* Store_unaligned. */
+ },
+ {
+ /* FP SFmode */
+ {
+ COSTS_N_INSNS (15), /* Div. */
+ COSTS_N_INSNS (3), /* Mult. */
+ COSTS_N_INSNS (7), /* Mult_addsub. */
+ COSTS_N_INSNS (7), /* Fma. */
+ COSTS_N_INSNS (3), /* Addsub. */
+ COSTS_N_INSNS (3), /* Fpconst. */
+ COSTS_N_INSNS (3), /* Neg. */
+ COSTS_N_INSNS (3), /* Compare. */
+ COSTS_N_INSNS (3), /* Widen. */
+ COSTS_N_INSNS (3), /* Narrow. */
+ COSTS_N_INSNS (3), /* Toint. */
+ COSTS_N_INSNS (3), /* Fromint. */
+ COSTS_N_INSNS (3) /* Roundint. */
+ },
+ /* FP DFmode */
+ {
+ COSTS_N_INSNS (30), /* Div. */
+ COSTS_N_INSNS (6), /* Mult. */
+ COSTS_N_INSNS (10), /* Mult_addsub. */
+ COSTS_N_INSNS (7), /* Fma. */
+ COSTS_N_INSNS (3), /* Addsub. */
+ COSTS_N_INSNS (3), /* Fpconst. */
+ COSTS_N_INSNS (3), /* Neg. */
+ COSTS_N_INSNS (3), /* Compare. */
+ COSTS_N_INSNS (3), /* Widen. */
+ COSTS_N_INSNS (3), /* Narrow. */
+ COSTS_N_INSNS (3), /* Toint. */
+ COSTS_N_INSNS (3), /* Fromint. */
+ COSTS_N_INSNS (3) /* Roundint. */
+ }
+ },
+ /* Vector */
+ {
+ COSTS_N_INSNS (1) /* Alu. */
+ }
+};
+
+const struct cpu_cost_table cortexa15_extra_costs =
+{
+ /* ALU */
+ {
+ COSTS_N_INSNS (1), /* Arith. */
+ COSTS_N_INSNS (1), /* Logical. */
+ COSTS_N_INSNS (1), /* Shift. */
+ COSTS_N_INSNS (1), /* Shift_reg. */
+ COSTS_N_INSNS (1), /* Arith_shift. */
+ COSTS_N_INSNS (1), /* Arith_shift_reg. */
+ COSTS_N_INSNS (1), /* Log_shift. */
+ COSTS_N_INSNS (1), /* Log_shift_reg. */
+ COSTS_N_INSNS (1), /* Extend. */
+ COSTS_N_INSNS (2), /* Extend_arith. */
+ COSTS_N_INSNS (2), /* Bfi. */
+ COSTS_N_INSNS (1), /* Bfx. */
+ COSTS_N_INSNS (1), /* Clz. */
+ COSTS_N_INSNS (1), /* non_exec. */
+ true /* non_exec_costs_exec. */
+ },
+ /* MULT SImode */
+ {
+ {
+ COSTS_N_INSNS (3), /* Simple. */
+ COSTS_N_INSNS (4), /* Flag_setting. */
+ COSTS_N_INSNS (3), /* Extend. */
+ COSTS_N_INSNS (4), /* Add. */
+ COSTS_N_INSNS (4), /* Extend_add. */
+ COSTS_N_INSNS (19) /* Idiv. */
+ },
+ /* MULT DImode */
+ {
+ 0, /* Simple (N/A). */
+ 0, /* Flag_setting (N/A). */
+ COSTS_N_INSNS (4), /* Extend. */
+ 0, /* Add (N/A). */
+ COSTS_N_INSNS (6), /* Extend_add. */
+ 0 /* Idiv (N/A). */
+ }
+ },
+ /* LD/ST */
+ {
+ COSTS_N_INSNS (4), /* Load. */
+ COSTS_N_INSNS (4), /* Load_sign_extend. */
+ COSTS_N_INSNS (4), /* Ldrd. */
+ COSTS_N_INSNS (5), /* Ldm_1st. */
+ 1, /* Ldm_regs_per_insn_1st. */
+ 2, /* Ldm_regs_per_insn_subsequent. */
+ COSTS_N_INSNS (5), /* Loadf. */
+ COSTS_N_INSNS (5), /* Loadd. */
+ COSTS_N_INSNS (1), /* Load_unaligned. */
+ COSTS_N_INSNS (1), /* Store. */
+ COSTS_N_INSNS (1), /* Strd. */
+ COSTS_N_INSNS (2), /* Stm_1st. */
+ 1, /* Stm_regs_per_insn_1st. */
+ 2, /* Stm_regs_per_insn_subsequent. */
+ COSTS_N_INSNS (1), /* Storef. */
+ COSTS_N_INSNS (1), /* Stored. */
+ COSTS_N_INSNS (1) /* Store_unaligned. */
+ },
+ {
+ /* FP SFmode */
+ {
+ COSTS_N_INSNS (18), /* Div. */
+ COSTS_N_INSNS (5), /* Mult. */
+ COSTS_N_INSNS (3), /* Mult_addsub. */
+ COSTS_N_INSNS (13), /* Fma. */
+ COSTS_N_INSNS (5), /* Addsub. */
+ COSTS_N_INSNS (5), /* Fpconst. */
+ COSTS_N_INSNS (3), /* Neg. */
+ COSTS_N_INSNS (3), /* Compare. */
+ COSTS_N_INSNS (3), /* Widen. */
+ COSTS_N_INSNS (3), /* Narrow. */
+ COSTS_N_INSNS (3), /* Toint. */
+ COSTS_N_INSNS (3), /* Fromint. */
+ COSTS_N_INSNS (3) /* Roundint. */
+ },
+ /* FP DFmode */
+ {
+ COSTS_N_INSNS (32), /* Div. */
+ COSTS_N_INSNS (5), /* Mult. */
+ COSTS_N_INSNS (3), /* Mult_addsub. */
+ COSTS_N_INSNS (13), /* Fma. */
+ COSTS_N_INSNS (5), /* Addsub. */
+ COSTS_N_INSNS (3), /* Fpconst. */
+ COSTS_N_INSNS (3), /* Neg. */
+ COSTS_N_INSNS (3), /* Compare. */
+ COSTS_N_INSNS (3), /* Widen. */
+ COSTS_N_INSNS (3), /* Narrow. */
+ COSTS_N_INSNS (3), /* Toint. */
+ COSTS_N_INSNS (3), /* Fromint. */
+ COSTS_N_INSNS (3) /* Roundint. */
+ }
+ },
+ /* Vector */
+ {
+ COSTS_N_INSNS (1) /* Alu. */
+ }
+};
+
const struct tune_params arm_slowmul_tune =
{
arm_slowmul_rtx_costs,
NULL,
+ NULL,
3, /* Constant limit. */
5, /* Max cond insns. */
ARM_PREFETCH_NOT_BENEFICIAL,
@@ -964,6 +1373,7 @@ const struct tune_params arm_fastmul_tune =
{
arm_fastmul_rtx_costs,
NULL,
+ NULL,
1, /* Constant limit. */
5, /* Max cond insns. */
ARM_PREFETCH_NOT_BENEFICIAL,
@@ -982,6 +1392,7 @@ const struct tune_params arm_strongarm_tune =
{
arm_fastmul_rtx_costs,
NULL,
+ NULL,
1, /* Constant limit. */
3, /* Max cond insns. */
ARM_PREFETCH_NOT_BENEFICIAL,
@@ -996,6 +1407,7 @@ const struct tune_params arm_strongarm_tune =
const struct tune_params arm_xscale_tune =
{
arm_xscale_rtx_costs,
+ NULL,
xscale_sched_adjust_cost,
2, /* Constant limit. */
3, /* Max cond insns. */
@@ -1012,6 +1424,7 @@ const struct tune_params arm_9e_tune =
{
arm_9e_rtx_costs,
NULL,
+ NULL,
1, /* Constant limit. */
5, /* Max cond insns. */
ARM_PREFETCH_NOT_BENEFICIAL,
@@ -1027,6 +1440,7 @@ const struct tune_params arm_v6t2_tune =
{
arm_9e_rtx_costs,
NULL,
+ NULL,
1, /* Constant limit. */
5, /* Max cond insns. */
ARM_PREFETCH_NOT_BENEFICIAL,
@@ -1042,6 +1456,7 @@ const struct tune_params arm_v6t2_tune =
const struct tune_params arm_cortex_tune =
{
arm_9e_rtx_costs,
+ &generic_extra_costs,
NULL,
1, /* Constant limit. */
5, /* Max cond insns. */
@@ -1054,9 +1469,26 @@ const struct tune_params arm_cortex_tune =
false /* Prefer Neon for 64-bits bitops. */
};
+const struct tune_params arm_cortex_a7_tune =
+{
+ arm_9e_rtx_costs,
+ &cortexa7_extra_costs,
+ NULL,
+ 1, /* Constant limit. */
+ 5, /* Max cond insns. */
+ ARM_PREFETCH_NOT_BENEFICIAL,
+ false, /* Prefer constant pool. */
+ arm_default_branch_cost,
+ false, /* Prefer LDRD/STRD. */
+ {true, true}, /* Prefer non short circuit. */
+ &arm_default_vec_cost, /* Vectorizer costs. */
+ false /* Prefer Neon for 64-bits bitops. */
+};
+
const struct tune_params arm_cortex_a15_tune =
{
arm_9e_rtx_costs,
+ &cortexa15_extra_costs,
NULL,
1, /* Constant limit. */
2, /* Max cond insns. */
@@ -1076,6 +1508,7 @@ const struct tune_params arm_cortex_a5_tune =
{
arm_9e_rtx_costs,
NULL,
+ NULL,
1, /* Constant limit. */
1, /* Max cond insns. */
ARM_PREFETCH_NOT_BENEFICIAL,
@@ -1090,6 +1523,7 @@ const struct tune_params arm_cortex_a5_tune =
const struct tune_params arm_cortex_a9_tune =
{
arm_9e_rtx_costs,
+ &cortexa9_extra_costs,
cortex_a9_sched_adjust_cost,
1, /* Constant limit. */
5, /* Max cond insns. */
@@ -1108,6 +1542,7 @@ const struct tune_params arm_v6m_tune =
{
arm_9e_rtx_costs,
NULL,
+ NULL,
1, /* Constant limit. */
5, /* Max cond insns. */
ARM_PREFETCH_NOT_BENEFICIAL,
@@ -1122,6 +1557,7 @@ const struct tune_params arm_v6m_tune =
const struct tune_params arm_fa726te_tune =
{
arm_9e_rtx_costs,
+ NULL,
fa726te_sched_adjust_cost,
1, /* Constant limit. */
5, /* Max cond insns. */
@@ -4971,6 +5407,12 @@ arm_init_cumulative_args (CUMULATIVE_ARGS *pcum, tree fntype,
}
}
+/* Return true if we use LRA instead of reload pass. */
+static bool
+arm_lra_p (void)
+{
+ return arm_lra_flag;
+}
/* Return true if mode/type need doubleword alignment. */
static bool
@@ -7015,7 +7457,11 @@ arm_legitimize_reload_address (rtx *p,
return false;
/* Reload the high part into a base reg; leave the low part
- in the mem. */
+ in the mem.
+ Note that replacing this gen_rtx_PLUS with plus_constant is
+ wrong in this case because we rely on the
+ (plus (plus reg c1) c2) structure being preserved so that
+ XEXP (*p, 0) in push_reload below uses the correct term. */
*p = gen_rtx_PLUS (GET_MODE (*p),
gen_rtx_PLUS (GET_MODE (*p), XEXP (*p, 0),
GEN_INT (high)),
@@ -8287,18 +8733,1708 @@ arm_size_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
}
}
+/* Helper function for arm_rtx_costs. If the operand is a valid shift
+ operand, then return the operand that is being shifted. If the shift
+ is not by a constant, then set SHIFT_REG to point to the operand.
+ Return NULL if OP is not a shifter operand. */
+static rtx
+shifter_op_p (rtx op, rtx *shift_reg)
+{
+ enum rtx_code code = GET_CODE (op);
+
+ if (code == MULT && CONST_INT_P (XEXP (op, 1))
+ && exact_log2 (INTVAL (XEXP (op, 1))) > 0)
+ return XEXP (op, 0);
+ else if (code == ROTATE && CONST_INT_P (XEXP (op, 1)))
+ return XEXP (op, 0);
+ else if (code == ROTATERT || code == ASHIFT || code == LSHIFTRT
+ || code == ASHIFTRT)
+ {
+ if (!CONST_INT_P (XEXP (op, 1)))
+ *shift_reg = XEXP (op, 1);
+ return XEXP (op, 0);
+ }
+
+ return NULL;
+}
+
+static bool
+arm_unspec_cost (rtx x, enum rtx_code /* outer_code */, bool speed_p, int *cost)
+{
+ const struct cpu_cost_table *extra_cost = current_tune->insn_extra_cost;
+ gcc_assert (GET_CODE (x) == UNSPEC);
+
+ switch (XINT (x, 1))
+ {
+ case UNSPEC_UNALIGNED_LOAD:
+ /* We can only do unaligned loads into the integer unit, and we can't
+ use LDM or LDRD. */
+ *cost = COSTS_N_INSNS (ARM_NUM_REGS (GET_MODE (x)));
+ if (speed_p)
+ *cost += (ARM_NUM_REGS (GET_MODE (x)) * extra_cost->ldst.load
+ + extra_cost->ldst.load_unaligned);
+
+#ifdef NOT_YET
+ *cost += arm_address_cost (XEXP (XVECEXP (x, 0, 0), 0), GET_MODE (x),
+ ADDR_SPACE_GENERIC, speed_p);
+#endif
+ return true;
+
+ case UNSPEC_UNALIGNED_STORE:
+ *cost = COSTS_N_INSNS (ARM_NUM_REGS (GET_MODE (x)));
+ if (speed_p)
+ *cost += (ARM_NUM_REGS (GET_MODE (x)) * extra_cost->ldst.store
+ + extra_cost->ldst.store_unaligned);
+
+ *cost += rtx_cost (XVECEXP (x, 0, 0), UNSPEC, 0, speed_p);
+#ifdef NOT_YET
+ *cost += arm_address_cost (XEXP (XVECEXP (x, 0, 0), 0), GET_MODE (x),
+ ADDR_SPACE_GENERIC, speed_p);
+#endif
+ return true;
+
+ case UNSPEC_VRINTZ:
+ case UNSPEC_VRINTP:
+ case UNSPEC_VRINTM:
+ case UNSPEC_VRINTR:
+ case UNSPEC_VRINTX:
+ case UNSPEC_VRINTA:
+ *cost = COSTS_N_INSNS (1);
+ if (speed_p)
+ *cost += extra_cost->fp[GET_MODE (x) == DFmode].roundint;
+
+ return true;
+ default:
+ *cost = COSTS_N_INSNS (2);
+ break;
+ }
+ return false;
+}
+
+/* Cost of a libcall. We assume one insn per argument, an amount for the
+ call (one insn for -Os) and then one for processing the result. */
+#define LIBCALL_COST(N) COSTS_N_INSNS (N + (speed_p ? 18 : 2))
+
+/* RTX costs. Make an estimate of the cost of executing the operation
+ X, which is contained with an operation with code OUTER_CODE.
+ SPEED_P indicates whether the cost desired is the performance cost,
+ or the size cost. The estimate is stored in COST and the return
+ value is TRUE if the cost calculation is final, or FALSE if the
+ caller should recurse through the operands of X to add additional
+ costs.
+
+ We currently make no attempt to model the size savings of Thumb-2
+ 16-bit instructions. At the normal points in compilation where
+ this code is called we have no measure of whether the condition
+ flags are live or not, and thus no realistic way to determine what
+ the size will eventually be. */
+static bool
+arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
+ const struct cpu_cost_table *extra_cost,
+ int *cost, bool speed_p)
+{
+ enum machine_mode mode = GET_MODE (x);
+
+ if (TARGET_THUMB1)
+ {
+ if (speed_p)
+ *cost = thumb1_rtx_costs (x, code, outer_code);
+ else
+ *cost = thumb1_size_rtx_costs (x, code, outer_code);
+ return true;
+ }
+
+ switch (code)
+ {
+ case SET:
+ *cost = 0;
+ if (REG_P (SET_SRC (x))
+ && REG_P (SET_DEST (x)))
+ {
+ /* Assume that most copies can be done with a single insn,
+ unless we don't have HW FP, in which case everything
+ larger than word mode will require two insns. */
+ *cost = COSTS_N_INSNS (((!TARGET_HARD_FLOAT
+ && GET_MODE_SIZE (mode) > 4)
+ || mode == DImode)
+ ? 2 : 1);
+ /* Conditional register moves can be encoded
+ in 16 bits in Thumb mode. */
+ if (!speed_p && TARGET_THUMB && outer_code == COND_EXEC)
+ *cost >>= 1;
+ }
+
+ if (CONST_INT_P (SET_SRC (x)))
+ {
+ /* Handle CONST_INT here, since the value doesn't have a mode
+ and we would otherwise be unable to work out the true cost. */
+ *cost = rtx_cost (SET_DEST (x), SET, 0, speed_p);
+ mode = GET_MODE (SET_DEST (x));
+ outer_code = SET;
+ /* Slightly lower the cost of setting a core reg to a constant.
+ This helps break up chains and allows for better scheduling. */
+ if (REG_P (SET_DEST (x))
+ && REGNO (SET_DEST (x)) <= LR_REGNUM)
+ *cost -= 1;
+ x = SET_SRC (x);
+ /* Immediate moves with an immediate in the range [0, 255] can be
+ encoded in 16 bits in Thumb mode. */
+ if (!speed_p && TARGET_THUMB && GET_MODE (x) == SImode
+ && INTVAL (x) >= 0 && INTVAL (x) <=255)
+ *cost >>= 1;
+ goto const_int_cost;
+ }
+
+ return false;
+
+ case MEM:
+ /* A memory access costs 1 insn if the mode is small, or the address is
+ a single register, otherwise it costs one insn per word. */
+ if (REG_P (XEXP (x, 0)))
+ *cost = COSTS_N_INSNS (1);
+ else if (flag_pic
+ && GET_CODE (XEXP (x, 0)) == PLUS
+ && will_be_in_index_register (XEXP (XEXP (x, 0), 1)))
+ /* This will be split into two instructions.
+ See arm.md:calculate_pic_address. */
+ *cost = COSTS_N_INSNS (2);
+ else
+ *cost = COSTS_N_INSNS (ARM_NUM_REGS (mode));
+
+ /* For speed optimizations, add the costs of the address and
+ accessing memory. */
+ if (speed_p)
+#ifdef NOT_YET
+ *cost += (extra_cost->ldst.load
+ + arm_address_cost (XEXP (x, 0), mode,
+ ADDR_SPACE_GENERIC, speed_p));
+#else
+ *cost += extra_cost->ldst.load;
+#endif
+ return true;
+
+ case PARALLEL:
+ {
+ /* Calculations of LDM costs are complex. We assume an initial cost
+ (ldm_1st) which will load the number of registers mentioned in
+ ldm_regs_per_insn_1st registers; then each additional
+ ldm_regs_per_insn_subsequent registers cost one more insn. The
+ formula for N regs is thus:
+
+ ldm_1st + COSTS_N_INSNS ((max (N - ldm_regs_per_insn_1st, 0)
+ + ldm_regs_per_insn_subsequent - 1)
+ / ldm_regs_per_insn_subsequent).
+
+ Additional costs may also be added for addressing. A similar
+ formula is used for STM. */
+
+ bool is_ldm = load_multiple_operation (x, SImode);
+ bool is_stm = store_multiple_operation (x, SImode);
+
+ *cost = COSTS_N_INSNS (1);
+
+ if (is_ldm || is_stm)
+ {
+ if (speed_p)
+ {
+ HOST_WIDE_INT nregs = XVECLEN (x, 0);
+ HOST_WIDE_INT regs_per_insn_1st = is_ldm
+ ? extra_cost->ldst.ldm_regs_per_insn_1st
+ : extra_cost->ldst.stm_regs_per_insn_1st;
+ HOST_WIDE_INT regs_per_insn_sub = is_ldm
+ ? extra_cost->ldst.ldm_regs_per_insn_subsequent
+ : extra_cost->ldst.stm_regs_per_insn_subsequent;
+
+ *cost += regs_per_insn_1st
+ + COSTS_N_INSNS (((MAX (nregs - regs_per_insn_1st, 0))
+ + regs_per_insn_sub - 1)
+ / regs_per_insn_sub);
+ return true;
+ }
+
+ }
+ return false;
+ }
+ case DIV:
+ case UDIV:
+ if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT
+ && (mode == SFmode || !TARGET_VFP_SINGLE))
+ *cost = COSTS_N_INSNS (speed_p
+ ? extra_cost->fp[mode != SFmode].div : 1);
+ else if (mode == SImode && TARGET_IDIV)
+ *cost = COSTS_N_INSNS (speed_p ? extra_cost->mult[0].idiv : 1);
+ else
+ *cost = LIBCALL_COST (2);
+ return false; /* All arguments must be in registers. */
+
+ case MOD:
+ case UMOD:
+ *cost = LIBCALL_COST (2);
+ return false; /* All arguments must be in registers. */
+
+ case ROTATE:
+ if (mode == SImode && REG_P (XEXP (x, 1)))
+ {
+ *cost = (COSTS_N_INSNS (2)
+ + rtx_cost (XEXP (x, 0), code, 0, speed_p));
+ if (speed_p)
+ *cost += extra_cost->alu.shift_reg;
+ return true;
+ }
+ /* Fall through */
+ case ROTATERT:
+ case ASHIFT:
+ case LSHIFTRT:
+ case ASHIFTRT:
+ if (mode == DImode && CONST_INT_P (XEXP (x, 1)))
+ {
+ *cost = (COSTS_N_INSNS (3)
+ + rtx_cost (XEXP (x, 0), code, 0, speed_p));
+ if (speed_p)
+ *cost += 2 * extra_cost->alu.shift;
+ return true;
+ }
+ else if (mode == SImode)
+ {
+ *cost = (COSTS_N_INSNS (1)
+ + rtx_cost (XEXP (x, 0), code, 0, speed_p));
+ /* Slightly disparage register shifts at -Os, but not by much. */
+ if (!CONST_INT_P (XEXP (x, 1)))
+ *cost += (speed_p ? extra_cost->alu.shift_reg : 1
+ + rtx_cost (XEXP (x, 1), code, 1, speed_p));
+ return true;
+ }
+ else if (GET_MODE_CLASS (mode) == MODE_INT
+ && GET_MODE_SIZE (mode) < 4)
+ {
+ if (code == ASHIFT)
+ {
+ *cost = (COSTS_N_INSNS (1)
+ + rtx_cost (XEXP (x, 0), code, 0, speed_p));
+ /* Slightly disparage register shifts at -Os, but not by
+ much. */
+ if (!CONST_INT_P (XEXP (x, 1)))
+ *cost += (speed_p ? extra_cost->alu.shift_reg : 1
+ + rtx_cost (XEXP (x, 1), code, 1, speed_p));
+ }
+ else if (code == LSHIFTRT || code == ASHIFTRT)
+ {
+ if (arm_arch_thumb2 && CONST_INT_P (XEXP (x, 1)))
+ {
+ /* Can use SBFX/UBFX. */
+ *cost = COSTS_N_INSNS (1);
+ if (speed_p)
+ *cost += extra_cost->alu.bfx;
+ *cost += rtx_cost (XEXP (x, 0), code, 0, speed_p);
+ }
+ else
+ {
+ *cost = COSTS_N_INSNS (2);
+ *cost += rtx_cost (XEXP (x, 0), code, 0, speed_p);
+ if (speed_p)
+ {
+ if (CONST_INT_P (XEXP (x, 1)))
+ *cost += 2 * extra_cost->alu.shift;
+ else
+ *cost += (extra_cost->alu.shift
+ + extra_cost->alu.shift_reg);
+ }
+ else
+ /* Slightly disparage register shifts. */
+ *cost += !CONST_INT_P (XEXP (x, 1));
+ }
+ }
+ else /* Rotates. */
+ {
+ *cost = COSTS_N_INSNS (3 + !CONST_INT_P (XEXP (x, 1)));
+ *cost += rtx_cost (XEXP (x, 0), code, 0, speed_p);
+ if (speed_p)
+ {
+ if (CONST_INT_P (XEXP (x, 1)))
+ *cost += (2 * extra_cost->alu.shift
+ + extra_cost->alu.log_shift);
+ else
+ *cost += (extra_cost->alu.shift
+ + extra_cost->alu.shift_reg
+ + extra_cost->alu.log_shift_reg);
+ }
+ }
+ return true;
+ }
+
+ *cost = LIBCALL_COST (2);
+ return false;
+
+ case MINUS:
+ if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT
+ && (mode == SFmode || !TARGET_VFP_SINGLE))
+ {
+ *cost = COSTS_N_INSNS (1);
+ if (GET_CODE (XEXP (x, 0)) == MULT
+ || GET_CODE (XEXP (x, 1)) == MULT)
+ {
+ rtx mul_op0, mul_op1, sub_op;
+
+ if (speed_p)
+ *cost += extra_cost->fp[mode != SFmode].mult_addsub;
+
+ if (GET_CODE (XEXP (x, 0)) == MULT)
+ {
+ mul_op0 = XEXP (XEXP (x, 0), 0);
+ mul_op1 = XEXP (XEXP (x, 0), 1);
+ sub_op = XEXP (x, 1);
+ }
+ else
+ {
+ mul_op0 = XEXP (XEXP (x, 1), 0);
+ mul_op1 = XEXP (XEXP (x, 1), 1);
+ sub_op = XEXP (x, 0);
+ }
+
+ /* The first operand of the multiply may be optionally
+ negated. */
+ if (GET_CODE (mul_op0) == NEG)
+ mul_op0 = XEXP (mul_op0, 0);
+
+ *cost += (rtx_cost (mul_op0, code, 0, speed_p)
+ + rtx_cost (mul_op1, code, 0, speed_p)
+ + rtx_cost (sub_op, code, 0, speed_p));
+
+ return true;
+ }
+
+ if (speed_p)
+ *cost += extra_cost->fp[mode != SFmode].addsub;
+ return false;
+ }
+
+ if (mode == SImode)
+ {
+ rtx shift_by_reg = NULL;
+ rtx shift_op;
+ rtx non_shift_op;
+
+ *cost = COSTS_N_INSNS (1);
+
+ shift_op = shifter_op_p (XEXP (x, 0), &shift_by_reg);
+ if (shift_op == NULL)
+ {
+ shift_op = shifter_op_p (XEXP (x, 1), &shift_by_reg);
+ non_shift_op = XEXP (x, 0);
+ }
+ else
+ non_shift_op = XEXP (x, 1);
+
+ if (shift_op != NULL)
+ {
+ if (shift_by_reg != NULL)
+ {
+ if (speed_p)
+ *cost += extra_cost->alu.arith_shift_reg;
+ *cost += rtx_cost (shift_by_reg, code, 0, speed_p);
+ }
+ else if (speed_p)
+ *cost += extra_cost->alu.arith_shift;
+
+ *cost += (rtx_cost (shift_op, code, 0, speed_p)
+ + rtx_cost (non_shift_op, code, 0, speed_p));
+ return true;
+ }
+
+ if (arm_arch_thumb2
+ && GET_CODE (XEXP (x, 1)) == MULT)
+ {
+ /* MLS. */
+ if (speed_p)
+ *cost += extra_cost->mult[0].add;
+ *cost += (rtx_cost (XEXP (x, 0), MINUS, 0, speed_p)
+ + rtx_cost (XEXP (XEXP (x, 1), 0), MULT, 0, speed_p)
+ + rtx_cost (XEXP (XEXP (x, 1), 1), MULT, 1, speed_p));
+ return true;
+ }
+
+ if (CONST_INT_P (XEXP (x, 0)))
+ {
+ int insns = arm_gen_constant (MINUS, SImode, NULL_RTX,
+ INTVAL (XEXP (x, 0)), NULL_RTX,
+ NULL_RTX, 1, 0);
+ *cost = COSTS_N_INSNS (insns);
+ if (speed_p)
+ *cost += insns * extra_cost->alu.arith;
+ *cost += rtx_cost (XEXP (x, 1), code, 1, speed_p);
+ return true;
+ }
+
+ return false;
+ }
+
+ if (GET_MODE_CLASS (mode) == MODE_INT
+ && GET_MODE_SIZE (mode) < 4)
+ {
+ /* Slightly disparage, as we might need to widen the result. */
+ *cost = 1 + COSTS_N_INSNS (1);
+ if (speed_p)
+ *cost += extra_cost->alu.arith;
+
+ if (CONST_INT_P (XEXP (x, 0)))
+ {
+ *cost += rtx_cost (XEXP (x, 1), code, 1, speed_p);
+ return true;
+ }
+
+ return false;
+ }
+
+ if (mode == DImode)
+ {
+ *cost = COSTS_N_INSNS (2);
+
+ if (GET_CODE (XEXP (x, 0)) == ZERO_EXTEND)
+ {
+ rtx op1 = XEXP (x, 1);
+
+ if (speed_p)
+ *cost += 2 * extra_cost->alu.arith;
+
+ if (GET_CODE (op1) == ZERO_EXTEND)
+ *cost += rtx_cost (XEXP (op1, 0), ZERO_EXTEND, 0, speed_p);
+ else
+ *cost += rtx_cost (op1, MINUS, 1, speed_p);
+ *cost += rtx_cost (XEXP (XEXP (x, 0), 0), ZERO_EXTEND,
+ 0, speed_p);
+ return true;
+ }
+ else if (GET_CODE (XEXP (x, 0)) == SIGN_EXTEND)
+ {
+ if (speed_p)
+ *cost += extra_cost->alu.arith + extra_cost->alu.arith_shift;
+ *cost += (rtx_cost (XEXP (XEXP (x, 0), 0), SIGN_EXTEND,
+ 0, speed_p)
+ + rtx_cost (XEXP (x, 1), MINUS, 1, speed_p));
+ return true;
+ }
+ else if (GET_CODE (XEXP (x, 1)) == ZERO_EXTEND
+ || GET_CODE (XEXP (x, 1)) == SIGN_EXTEND)
+ {
+ if (speed_p)
+ *cost += (extra_cost->alu.arith
+ + (GET_CODE (XEXP (x, 1)) == ZERO_EXTEND
+ ? extra_cost->alu.arith
+ : extra_cost->alu.arith_shift));
+ *cost += (rtx_cost (XEXP (x, 0), MINUS, 0, speed_p)
+ + rtx_cost (XEXP (XEXP (x, 1), 0),
+ GET_CODE (XEXP (x, 1)), 0, speed_p));
+ return true;
+ }
+
+ if (speed_p)
+ *cost += 2 * extra_cost->alu.arith;
+ return false;
+ }
+
+ /* Vector mode? */
+
+ *cost = LIBCALL_COST (2);
+ return false;
+
+ case PLUS:
+ if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT
+ && (mode == SFmode || !TARGET_VFP_SINGLE))
+ {
+ *cost = COSTS_N_INSNS (1);
+ if (GET_CODE (XEXP (x, 0)) == MULT)
+ {
+ rtx mul_op0, mul_op1, add_op;
+
+ if (speed_p)
+ *cost += extra_cost->fp[mode != SFmode].mult_addsub;
+
+ mul_op0 = XEXP (XEXP (x, 0), 0);
+ mul_op1 = XEXP (XEXP (x, 0), 1);
+ add_op = XEXP (x, 1);
+
+ *cost += (rtx_cost (mul_op0, code, 0, speed_p)
+ + rtx_cost (mul_op1, code, 0, speed_p)
+ + rtx_cost (add_op, code, 0, speed_p));
+
+ return true;
+ }
+
+ if (speed_p)
+ *cost += extra_cost->fp[mode != SFmode].addsub;
+ return false;
+ }
+ else if (GET_MODE_CLASS (mode) == MODE_FLOAT)
+ {
+ *cost = LIBCALL_COST (2);
+ return false;
+ }
+
+ if (GET_MODE_CLASS (mode) == MODE_INT
+ && GET_MODE_SIZE (mode) < 4)
+ {
+ /* Narrow modes can be synthesized in SImode, but the range
+ of useful sub-operations is limited. */
+ if (CONST_INT_P (XEXP (x, 1)))
+ {
+ int insns = arm_gen_constant (PLUS, SImode, NULL_RTX,
+ INTVAL (XEXP (x, 1)), NULL_RTX,
+ NULL_RTX, 1, 0);
+ *cost = COSTS_N_INSNS (insns);
+ if (speed_p)
+ *cost += insns * extra_cost->alu.arith;
+ /* Slightly penalize a narrow operation as the result may
+ need widening. */
+ *cost += 1 + rtx_cost (XEXP (x, 0), PLUS, 0, speed_p);
+ return true;
+ }
+
+ /* Slightly penalize a narrow operation as the result may
+ need widening. */
+ *cost = 1 + COSTS_N_INSNS (1);
+ if (speed_p)
+ *cost += extra_cost->alu.arith;
+
+ return false;
+ }
+
+ if (mode == SImode)
+ {
+ rtx shift_op, shift_reg;
+
+ *cost = COSTS_N_INSNS (1);
+ if (TARGET_INT_SIMD
+ && (GET_CODE (XEXP (x, 0)) == ZERO_EXTEND
+ || GET_CODE (XEXP (x, 0)) == SIGN_EXTEND))
+ {
+ /* UXTA[BH] or SXTA[BH]. */
+ if (speed_p)
+ *cost += extra_cost->alu.extnd_arith;
+ *cost += (rtx_cost (XEXP (XEXP (x, 0), 0), ZERO_EXTEND, 0,
+ speed_p)
+ + rtx_cost (XEXP (x, 1), PLUS, 0, speed_p));
+ return true;
+ }
+
+ shift_reg = NULL;
+ shift_op = shifter_op_p (XEXP (x, 0), &shift_reg);
+ if (shift_op != NULL)
+ {
+ if (shift_reg)
+ {
+ if (speed_p)
+ *cost += extra_cost->alu.arith_shift_reg;
+ *cost += rtx_cost (shift_reg, ASHIFT, 1, speed_p);
+ }
+ else if (speed_p)
+ *cost += extra_cost->alu.arith_shift;
+
+ *cost += (rtx_cost (shift_op, ASHIFT, 0, speed_p)
+ + rtx_cost (XEXP (x, 1), PLUS, 1, speed_p));
+ return true;
+ }
+ if (GET_CODE (XEXP (x, 0)) == MULT)
+ {
+ rtx mul_op = XEXP (x, 0);
+
+ *cost = COSTS_N_INSNS (1);
+
+ if (TARGET_DSP_MULTIPLY
+ && ((GET_CODE (XEXP (mul_op, 0)) == SIGN_EXTEND
+ && (GET_CODE (XEXP (mul_op, 1)) == SIGN_EXTEND
+ || (GET_CODE (XEXP (mul_op, 1)) == ASHIFTRT
+ && CONST_INT_P (XEXP (XEXP (mul_op, 1), 1))
+ && INTVAL (XEXP (XEXP (mul_op, 1), 1)) == 16)))
+ || (GET_CODE (XEXP (mul_op, 0)) == ASHIFTRT
+ && CONST_INT_P (XEXP (XEXP (mul_op, 0), 1))
+ && INTVAL (XEXP (XEXP (mul_op, 0), 1)) == 16
+ && (GET_CODE (XEXP (mul_op, 1)) == SIGN_EXTEND
+ || (GET_CODE (XEXP (mul_op, 1)) == ASHIFTRT
+ && CONST_INT_P (XEXP (XEXP (mul_op, 1), 1))
+ && (INTVAL (XEXP (XEXP (mul_op, 1), 1))
+ == 16))))))
+ {
+ /* SMLA[BT][BT]. */
+ if (speed_p)
+ *cost += extra_cost->mult[0].extend_add;
+ *cost += (rtx_cost (XEXP (XEXP (mul_op, 0), 0),
+ SIGN_EXTEND, 0, speed_p)
+ + rtx_cost (XEXP (XEXP (mul_op, 1), 0),
+ SIGN_EXTEND, 0, speed_p)
+ + rtx_cost (XEXP (x, 1), PLUS, 1, speed_p));
+ return true;
+ }
+
+ if (speed_p)
+ *cost += extra_cost->mult[0].add;
+ *cost += (rtx_cost (XEXP (mul_op, 0), MULT, 0, speed_p)
+ + rtx_cost (XEXP (mul_op, 1), MULT, 1, speed_p)
+ + rtx_cost (XEXP (x, 1), PLUS, 1, speed_p));
+ return true;
+ }
+ if (CONST_INT_P (XEXP (x, 1)))
+ {
+ int insns = arm_gen_constant (PLUS, SImode, NULL_RTX,
+ INTVAL (XEXP (x, 1)), NULL_RTX,
+ NULL_RTX, 1, 0);
+ *cost = COSTS_N_INSNS (insns);
+ if (speed_p)
+ *cost += insns * extra_cost->alu.arith;
+ *cost += rtx_cost (XEXP (x, 0), PLUS, 0, speed_p);
+ return true;
+ }
+ return false;
+ }
+
+ if (mode == DImode)
+ {
+ if (arm_arch3m
+ && GET_CODE (XEXP (x, 0)) == MULT
+ && ((GET_CODE (XEXP (XEXP (x, 0), 0)) == ZERO_EXTEND
+ && GET_CODE (XEXP (XEXP (x, 0), 1)) == ZERO_EXTEND)
+ || (GET_CODE (XEXP (XEXP (x, 0), 0)) == SIGN_EXTEND
+ && GET_CODE (XEXP (XEXP (x, 0), 1)) == SIGN_EXTEND)))
+ {
+ *cost = COSTS_N_INSNS (1);
+ if (speed_p)
+ *cost += extra_cost->mult[1].extend_add;
+ *cost += (rtx_cost (XEXP (XEXP (XEXP (x, 0), 0), 0),
+ ZERO_EXTEND, 0, speed_p)
+ + rtx_cost (XEXP (XEXP (XEXP (x, 0), 1), 0),
+ ZERO_EXTEND, 0, speed_p)
+ + rtx_cost (XEXP (x, 1), PLUS, 1, speed_p));
+ return true;
+ }
+
+ *cost = COSTS_N_INSNS (2);
+
+ if (GET_CODE (XEXP (x, 0)) == ZERO_EXTEND
+ || GET_CODE (XEXP (x, 0)) == SIGN_EXTEND)
+ {
+ if (speed_p)
+ *cost += (extra_cost->alu.arith
+ + (GET_CODE (XEXP (x, 0)) == ZERO_EXTEND
+ ? extra_cost->alu.arith
+ : extra_cost->alu.arith_shift));
+
+ *cost += (rtx_cost (XEXP (XEXP (x, 0), 0), ZERO_EXTEND, 0,
+ speed_p)
+ + rtx_cost (XEXP (x, 1), PLUS, 1, speed_p));
+ return true;
+ }
+
+ if (speed_p)
+ *cost += 2 * extra_cost->alu.arith;
+ return false;
+ }
+
+ /* Vector mode? */
+ *cost = LIBCALL_COST (2);
+ return false;
+
+ case AND: case XOR: case IOR:
+ if (mode == SImode)
+ {
+ enum rtx_code subcode = GET_CODE (XEXP (x, 0));
+ rtx op0 = XEXP (x, 0);
+ rtx shift_op, shift_reg;
+
+ *cost = COSTS_N_INSNS (1);
+
+ if (subcode == NOT
+ && (code == AND
+ || (code == IOR && TARGET_THUMB2)))
+ op0 = XEXP (op0, 0);
+
+ shift_reg = NULL;
+ shift_op = shifter_op_p (op0, &shift_reg);
+ if (shift_op != NULL)
+ {
+ if (shift_reg)
+ {
+ if (speed_p)
+ *cost += extra_cost->alu.log_shift_reg;
+ *cost += rtx_cost (shift_reg, ASHIFT, 1, speed_p);
+ }
+ else if (speed_p)
+ *cost += extra_cost->alu.log_shift;
+
+ *cost += (rtx_cost (shift_op, ASHIFT, 0, speed_p)
+ + rtx_cost (XEXP (x, 1), code, 1, speed_p));
+ return true;
+ }
+
+ if (CONST_INT_P (XEXP (x, 1)))
+ {
+ int insns = arm_gen_constant (code, SImode, NULL_RTX,
+ INTVAL (XEXP (x, 1)), NULL_RTX,
+ NULL_RTX, 1, 0);
+
+ *cost = COSTS_N_INSNS (insns);
+ if (speed_p)
+ *cost += insns * extra_cost->alu.logical;
+ *cost += rtx_cost (op0, code, 0, speed_p);
+ return true;
+ }
+
+ if (speed_p)
+ *cost += extra_cost->alu.logical;
+ *cost += (rtx_cost (op0, code, 0, speed_p)
+ + rtx_cost (XEXP (x, 1), code, 1, speed_p));
+ return true;
+ }
+
+ if (mode == DImode)
+ {
+ rtx op0 = XEXP (x, 0);
+ enum rtx_code subcode = GET_CODE (op0);
+
+ *cost = COSTS_N_INSNS (2);
+
+ if (subcode == NOT
+ && (code == AND
+ || (code == IOR && TARGET_THUMB2)))
+ op0 = XEXP (op0, 0);
+
+ if (GET_CODE (op0) == ZERO_EXTEND)
+ {
+ if (speed_p)
+ *cost += 2 * extra_cost->alu.logical;
+
+ *cost += (rtx_cost (XEXP (op0, 0), ZERO_EXTEND, 0, speed_p)
+ + rtx_cost (XEXP (x, 1), code, 0, speed_p));
+ return true;
+ }
+ else if (GET_CODE (op0) == SIGN_EXTEND)
+ {
+ if (speed_p)
+ *cost += extra_cost->alu.logical + extra_cost->alu.log_shift;
+
+ *cost += (rtx_cost (XEXP (op0, 0), SIGN_EXTEND, 0, speed_p)
+ + rtx_cost (XEXP (x, 1), code, 0, speed_p));
+ return true;
+ }
+
+ if (speed_p)
+ *cost += 2 * extra_cost->alu.logical;
+
+ return true;
+ }
+ /* Vector mode? */
+
+ *cost = LIBCALL_COST (2);
+ return false;
+
+ case MULT:
+ if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT
+ && (mode == SFmode || !TARGET_VFP_SINGLE))
+ {
+ rtx op0 = XEXP (x, 0);
+
+ *cost = COSTS_N_INSNS (1);
+
+ if (GET_CODE (op0) == NEG)
+ op0 = XEXP (op0, 0);
+
+ if (speed_p)
+ *cost += extra_cost->fp[mode != SFmode].mult;
+
+ *cost += (rtx_cost (op0, MULT, 0, speed_p)
+ + rtx_cost (XEXP (x, 1), MULT, 1, speed_p));
+ return true;
+ }
+ else if (GET_MODE_CLASS (mode) == MODE_FLOAT)
+ {
+ *cost = LIBCALL_COST (2);
+ return false;
+ }
+
+ if (mode == SImode)
+ {
+ *cost = COSTS_N_INSNS (1);
+ if (TARGET_DSP_MULTIPLY
+ && ((GET_CODE (XEXP (x, 0)) == SIGN_EXTEND
+ && (GET_CODE (XEXP (x, 1)) == SIGN_EXTEND
+ || (GET_CODE (XEXP (x, 1)) == ASHIFTRT
+ && CONST_INT_P (XEXP (XEXP (x, 1), 1))
+ && INTVAL (XEXP (XEXP (x, 1), 1)) == 16)))
+ || (GET_CODE (XEXP (x, 0)) == ASHIFTRT
+ && CONST_INT_P (XEXP (XEXP (x, 0), 1))
+ && INTVAL (XEXP (XEXP (x, 0), 1)) == 16
+ && (GET_CODE (XEXP (x, 1)) == SIGN_EXTEND
+ || (GET_CODE (XEXP (x, 1)) == ASHIFTRT
+ && CONST_INT_P (XEXP (XEXP (x, 1), 1))
+ && (INTVAL (XEXP (XEXP (x, 1), 1))
+ == 16))))))
+ {
+ /* SMUL[TB][TB]. */
+ if (speed_p)
+ *cost += extra_cost->mult[0].extend;
+ *cost += (rtx_cost (XEXP (x, 0), SIGN_EXTEND, 0, speed_p)
+ + rtx_cost (XEXP (x, 1), SIGN_EXTEND, 0, speed_p));
+ return true;
+ }
+ if (speed_p)
+ *cost += extra_cost->mult[0].simple;
+ return false;
+ }
+
+ if (mode == DImode)
+ {
+ if (arm_arch3m
+ && ((GET_CODE (XEXP (x, 0)) == ZERO_EXTEND
+ && GET_CODE (XEXP (x, 1)) == ZERO_EXTEND)
+ || (GET_CODE (XEXP (x, 0)) == SIGN_EXTEND
+ && GET_CODE (XEXP (x, 1)) == SIGN_EXTEND)))
+ {
+ *cost = COSTS_N_INSNS (1);
+ if (speed_p)
+ *cost += extra_cost->mult[1].extend;
+ *cost += (rtx_cost (XEXP (XEXP (x, 0), 0),
+ ZERO_EXTEND, 0, speed_p)
+ + rtx_cost (XEXP (XEXP (x, 1), 0),
+ ZERO_EXTEND, 0, speed_p));
+ return true;
+ }
+
+ *cost = LIBCALL_COST (2);
+ return false;
+ }
+
+ /* Vector mode? */
+ *cost = LIBCALL_COST (2);
+ return false;
+
+ case NEG:
+ if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT
+ && (mode == SFmode || !TARGET_VFP_SINGLE))
+ {
+ *cost = COSTS_N_INSNS (1);
+ if (speed_p)
+ *cost += extra_cost->fp[mode != SFmode].neg;
+
+ return false;
+ }
+ else if (GET_MODE_CLASS (mode) == MODE_FLOAT)
+ {
+ *cost = LIBCALL_COST (1);
+ return false;
+ }
+
+ if (mode == SImode)
+ {
+ if (GET_CODE (XEXP (x, 0)) == ABS)
+ {
+ *cost = COSTS_N_INSNS (2);
+ /* Assume the non-flag-changing variant. */
+ if (speed_p)
+ *cost += (extra_cost->alu.log_shift
+ + extra_cost->alu.arith_shift);
+ *cost += rtx_cost (XEXP (XEXP (x, 0), 0), ABS, 0, speed_p);
+ return true;
+ }
+
+ if (GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == RTX_COMPARE
+ || GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == RTX_COMM_COMPARE)
+ {
+ *cost = COSTS_N_INSNS (2);
+ /* No extra cost for MOV imm and MVN imm. */
+ /* If the comparison op is using the flags, there's no further
+ cost, otherwise we need to add the cost of the comparison. */
+ if (!(REG_P (XEXP (XEXP (x, 0), 0))
+ && REGNO (XEXP (XEXP (x, 0), 0)) == CC_REGNUM
+ && XEXP (XEXP (x, 0), 1) == const0_rtx))
+ {
+ *cost += (COSTS_N_INSNS (1)
+ + rtx_cost (XEXP (XEXP (x, 0), 0), COMPARE, 0,
+ speed_p)
+ + rtx_cost (XEXP (XEXP (x, 0), 1), COMPARE, 1,
+ speed_p));
+ if (speed_p)
+ *cost += extra_cost->alu.arith;
+ }
+ return true;
+ }
+ *cost = COSTS_N_INSNS (1);
+ if (speed_p)
+ *cost += extra_cost->alu.arith;
+ return false;
+ }
+
+ if (GET_MODE_CLASS (mode) == MODE_INT
+ && GET_MODE_SIZE (mode) < 4)
+ {
+ /* Slightly disparage, as we might need an extend operation. */
+ *cost = 1 + COSTS_N_INSNS (1);
+ if (speed_p)
+ *cost += extra_cost->alu.arith;
+ return false;
+ }
+
+ if (mode == DImode)
+ {
+ *cost = COSTS_N_INSNS (2);
+ if (speed_p)
+ *cost += 2 * extra_cost->alu.arith;
+ return false;
+ }
+
+ /* Vector mode? */
+ *cost = LIBCALL_COST (1);
+ return false;
+
+ case NOT:
+ if (mode == SImode)
+ {
+ rtx shift_op;
+ rtx shift_reg = NULL;
+
+ *cost = COSTS_N_INSNS (1);
+ shift_op = shifter_op_p (XEXP (x, 0), &shift_reg);
+
+ if (shift_op)
+ {
+ if (shift_reg != NULL)
+ {
+ if (speed_p)
+ *cost += extra_cost->alu.log_shift_reg;
+ *cost += rtx_cost (shift_reg, ASHIFT, 1, speed_p);
+ }
+ else if (speed_p)
+ *cost += extra_cost->alu.log_shift;
+ *cost += rtx_cost (shift_op, ASHIFT, 0, speed_p);
+ return true;
+ }
+
+ if (speed_p)
+ *cost += extra_cost->alu.logical;
+ return false;
+ }
+ if (mode == DImode)
+ {
+ *cost = COSTS_N_INSNS (2);
+ return false;
+ }
+
+ /* Vector mode? */
+
+ *cost += LIBCALL_COST (1);
+ return false;
+
+ case IF_THEN_ELSE:
+ {
+ if (GET_CODE (XEXP (x, 1)) == PC || GET_CODE (XEXP (x, 2)) == PC)
+ {
+ *cost = COSTS_N_INSNS (4);
+ return true;
+ }
+ int op1cost = rtx_cost (XEXP (x, 1), SET, 1, speed_p);
+ int op2cost = rtx_cost (XEXP (x, 2), SET, 1, speed_p);
+
+ *cost = rtx_cost (XEXP (x, 0), IF_THEN_ELSE, 0, speed_p);
+ /* Assume that if one arm of the if_then_else is a register,
+ that it will be tied with the result and eliminate the
+ conditional insn. */
+ if (REG_P (XEXP (x, 1)))
+ *cost += op2cost;
+ else if (REG_P (XEXP (x, 2)))
+ *cost += op1cost;
+ else
+ {
+ if (speed_p)
+ {
+ if (extra_cost->alu.non_exec_costs_exec)
+ *cost += op1cost + op2cost + extra_cost->alu.non_exec;
+ else
+ *cost += MAX (op1cost, op2cost) + extra_cost->alu.non_exec;
+ }
+ else
+ *cost += op1cost + op2cost;
+ }
+ }
+ return true;
+
+ case COMPARE:
+ if (cc_register (XEXP (x, 0), VOIDmode) && XEXP (x, 1) == const0_rtx)
+ *cost = 0;
+ else
+ {
+ enum machine_mode op0mode;
+ /* We'll mostly assume that the cost of a compare is the cost of the
+ LHS. However, there are some notable exceptions. */
+
+ /* Floating point compares are never done as side-effects. */
+ op0mode = GET_MODE (XEXP (x, 0));
+ if (TARGET_HARD_FLOAT && GET_MODE_CLASS (op0mode) == MODE_FLOAT
+ && (op0mode == SFmode || !TARGET_VFP_SINGLE))
+ {
+ *cost = COSTS_N_INSNS (1);
+ if (speed_p)
+ *cost += extra_cost->fp[op0mode != SFmode].compare;
+
+ if (XEXP (x, 1) == CONST0_RTX (op0mode))
+ {
+ *cost += rtx_cost (XEXP (x, 0), code, 0, speed_p);
+ return true;
+ }
+
+ return false;
+ }
+ else if (GET_MODE_CLASS (op0mode) == MODE_FLOAT)
+ {
+ *cost = LIBCALL_COST (2);
+ return false;
+ }
+
+ /* DImode compares normally take two insns. */
+ if (op0mode == DImode)
+ {
+ *cost = COSTS_N_INSNS (2);
+ if (speed_p)
+ *cost += 2 * extra_cost->alu.arith;
+ return false;
+ }
+
+ if (op0mode == SImode)
+ {
+ rtx shift_op;
+ rtx shift_reg;
+
+ if (XEXP (x, 1) == const0_rtx
+ && !(REG_P (XEXP (x, 0))
+ || (GET_CODE (XEXP (x, 0)) == SUBREG
+ && REG_P (SUBREG_REG (XEXP (x, 0))))))
+ {
+ *cost = rtx_cost (XEXP (x, 0), COMPARE, 0, speed_p);
+
+ /* Multiply operations that set the flags are often
+ significantly more expensive. */
+ if (speed_p
+ && GET_CODE (XEXP (x, 0)) == MULT
+ && !power_of_two_operand (XEXP (XEXP (x, 0), 1), mode))
+ *cost += extra_cost->mult[0].flag_setting;
+
+ if (speed_p
+ && GET_CODE (XEXP (x, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT
+ && !power_of_two_operand (XEXP (XEXP (XEXP (x, 0),
+ 0), 1), mode))
+ *cost += extra_cost->mult[0].flag_setting;
+ return true;
+ }
+
+ shift_reg = NULL;
+ shift_op = shifter_op_p (XEXP (x, 0), &shift_reg);
+ if (shift_op != NULL)
+ {
+ *cost = COSTS_N_INSNS (1);
+ if (shift_reg != NULL)
+ {
+ *cost += rtx_cost (shift_reg, ASHIFT, 1, speed_p);
+ if (speed_p)
+ *cost += extra_cost->alu.arith_shift_reg;
+ }
+ else if (speed_p)
+ *cost += extra_cost->alu.arith_shift;
+ *cost += (rtx_cost (shift_op, ASHIFT, 0, speed_p)
+ + rtx_cost (XEXP (x, 1), COMPARE, 1, speed_p));
+ return true;
+ }
+
+ *cost = COSTS_N_INSNS (1);
+ if (speed_p)
+ *cost += extra_cost->alu.arith;
+ if (CONST_INT_P (XEXP (x, 1))
+ && const_ok_for_op (INTVAL (XEXP (x, 1)), COMPARE))
+ {
+ *cost += rtx_cost (XEXP (x, 0), COMPARE, 0, speed_p);
+ return true;
+ }
+ return false;
+ }
+
+ /* Vector mode? */
+
+ *cost = LIBCALL_COST (2);
+ return false;
+ }
+ return true;
+
+ case EQ:
+ case NE:
+ case LT:
+ case LE:
+ case GT:
+ case GE:
+ case LTU:
+ case LEU:
+ case GEU:
+ case GTU:
+ case ORDERED:
+ case UNORDERED:
+ case UNEQ:
+ case UNLE:
+ case UNLT:
+ case UNGE:
+ case UNGT:
+ case LTGT:
+ if (outer_code == SET)
+ {
+ /* Is it a store-flag operation? */
+ if (REG_P (XEXP (x, 0)) && REGNO (XEXP (x, 0)) == CC_REGNUM
+ && XEXP (x, 1) == const0_rtx)
+ {
+ /* Thumb also needs an IT insn. */
+ *cost = COSTS_N_INSNS (TARGET_THUMB ? 3 : 2);
+ return true;
+ }
+ if (XEXP (x, 1) == const0_rtx)
+ {
+ switch (code)
+ {
+ case LT:
+ /* LSR Rd, Rn, #31. */
+ *cost = COSTS_N_INSNS (1);
+ if (speed_p)
+ *cost += extra_cost->alu.shift;
+ break;
+
+ case EQ:
+ /* RSBS T1, Rn, #0
+ ADC Rd, Rn, T1. */
+
+ case NE:
+ /* SUBS T1, Rn, #1
+ SBC Rd, Rn, T1. */
+ *cost = COSTS_N_INSNS (2);
+ break;
+
+ case LE:
+ /* RSBS T1, Rn, Rn, LSR #31
+ ADC Rd, Rn, T1. */
+ *cost = COSTS_N_INSNS (2);
+ if (speed_p)
+ *cost += extra_cost->alu.arith_shift;
+ break;
+
+ case GT:
+ /* RSB Rd, Rn, Rn, ASR #1
+ LSR Rd, Rd, #31. */
+ *cost = COSTS_N_INSNS (2);
+ if (speed_p)
+ *cost += (extra_cost->alu.arith_shift
+ + extra_cost->alu.shift);
+ break;
+
+ case GE:
+ /* ASR Rd, Rn, #31
+ ADD Rd, Rn, #1. */
+ *cost = COSTS_N_INSNS (2);
+ if (speed_p)
+ *cost += extra_cost->alu.shift;
+ break;
+
+ default:
+ /* Remaining cases are either meaningless or would take
+ three insns anyway. */
+ *cost = COSTS_N_INSNS (3);
+ break;
+ }
+ *cost += rtx_cost (XEXP (x, 0), code, 0, speed_p);
+ return true;
+ }
+ else
+ {
+ *cost = COSTS_N_INSNS (TARGET_THUMB ? 4 : 3);
+ if (CONST_INT_P (XEXP (x, 1))
+ && const_ok_for_op (INTVAL (XEXP (x, 1)), COMPARE))
+ {
+ *cost += rtx_cost (XEXP (x, 0), code, 0, speed_p);
+ return true;
+ }
+
+ return false;
+ }
+ }
+ /* Not directly inside a set. If it involves the condition code
+ register it must be the condition for a branch, cond_exec or
+ I_T_E operation. Since the comparison is performed elsewhere
+ this is just the control part which has no additional
+ cost. */
+ else if (REG_P (XEXP (x, 0)) && REGNO (XEXP (x, 0)) == CC_REGNUM
+ && XEXP (x, 1) == const0_rtx)
+ {
+ *cost = 0;
+ return true;
+ }
+ return false;
+
+ case ABS:
+ if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT
+ && (mode == SFmode || !TARGET_VFP_SINGLE))
+ {
+ *cost = COSTS_N_INSNS (1);
+ if (speed_p)
+ *cost += extra_cost->fp[mode != SFmode].neg;
+
+ return false;
+ }
+ else if (GET_MODE_CLASS (mode) == MODE_FLOAT)
+ {
+ *cost = LIBCALL_COST (1);
+ return false;
+ }
+
+ if (mode == SImode)
+ {
+ *cost = COSTS_N_INSNS (1);
+ if (speed_p)
+ *cost += extra_cost->alu.log_shift + extra_cost->alu.arith_shift;
+ return false;
+ }
+ /* Vector mode? */
+ *cost = LIBCALL_COST (1);
+ return false;
+
+ case SIGN_EXTEND:
+ if ((arm_arch4 || GET_MODE (XEXP (x, 0)) == SImode)
+ && MEM_P (XEXP (x, 0)))
+ {
+ *cost = rtx_cost (XEXP (x, 0), code, 0, speed_p);
+
+ if (mode == DImode)
+ *cost += COSTS_N_INSNS (1);
+
+ if (!speed_p)
+ return true;
+
+ if (GET_MODE (XEXP (x, 0)) == SImode)
+ *cost += extra_cost->ldst.load;
+ else
+ *cost += extra_cost->ldst.load_sign_extend;
+
+ if (mode == DImode)
+ *cost += extra_cost->alu.shift;
+
+ return true;
+ }
+
+ /* Widening from less than 32-bits requires an extend operation. */
+ if (GET_MODE (XEXP (x, 0)) != SImode && arm_arch6)
+ {
+ /* We have SXTB/SXTH. */
+ *cost = COSTS_N_INSNS (1);
+ *cost += rtx_cost (XEXP (x, 0), code, 0, speed_p);
+ if (speed_p)
+ *cost += extra_cost->alu.extnd;
+ }
+ else if (GET_MODE (XEXP (x, 0)) != SImode)
+ {
+ /* Needs two shifts. */
+ *cost = COSTS_N_INSNS (2);
+ *cost += rtx_cost (XEXP (x, 0), code, 0, speed_p);
+ if (speed_p)
+ *cost += 2 * extra_cost->alu.shift;
+ }
+
+ /* Widening beyond 32-bits requires one more insn. */
+ if (mode == DImode)
+ {
+ *cost += COSTS_N_INSNS (1);
+ if (speed_p)
+ *cost += extra_cost->alu.shift;
+ }
+
+ return true;
+
+ case ZERO_EXTEND:
+ if ((arm_arch4
+ || GET_MODE (XEXP (x, 0)) == SImode
+ || GET_MODE (XEXP (x, 0)) == QImode)
+ && MEM_P (XEXP (x, 0)))
+ {
+ *cost = rtx_cost (XEXP (x, 0), code, 0, speed_p);
+
+ if (mode == DImode)
+ *cost += COSTS_N_INSNS (1); /* No speed penalty. */
+
+ return true;
+ }
+
+ /* Widening from less than 32-bits requires an extend operation. */
+ if (GET_MODE (XEXP (x, 0)) == QImode)
+ {
+ /* UXTB can be a shorter instruction in Thumb2, but it might
+ be slower than the AND Rd, Rn, #255 alternative. When
+ optimizing for speed it should never be slower to use
+ AND, and we don't really model 16-bit vs 32-bit insns
+ here. */
+ *cost = COSTS_N_INSNS (1);
+ if (speed_p)
+ *cost += extra_cost->alu.logical;
+ }
+ else if (GET_MODE (XEXP (x, 0)) != SImode && arm_arch6)
+ {
+ /* We have UXTB/UXTH. */
+ *cost = COSTS_N_INSNS (1);
+ *cost += rtx_cost (XEXP (x, 0), code, 0, speed_p);
+ if (speed_p)
+ *cost += extra_cost->alu.extnd;
+ }
+ else if (GET_MODE (XEXP (x, 0)) != SImode)
+ {
+ /* Needs two shifts. It's marginally preferable to use
+ shifts rather than two BIC instructions as the second
+ shift may merge with a subsequent insn as a shifter
+ op. */
+ *cost = COSTS_N_INSNS (2);
+ *cost += rtx_cost (XEXP (x, 0), code, 0, speed_p);
+ if (speed_p)
+ *cost += 2 * extra_cost->alu.shift;
+ }
+
+ /* Widening beyond 32-bits requires one more insn. */
+ if (mode == DImode)
+ {
+ *cost += COSTS_N_INSNS (1); /* No speed penalty. */
+ }
+
+ return true;
+
+ case CONST_INT:
+ *cost = 0;
+ /* CONST_INT has no mode, so we cannot tell for sure how many
+ insns are really going to be needed. The best we can do is
+ look at the value passed. If it fits in SImode, then assume
+ that's the mode it will be used for. Otherwise assume it
+ will be used in DImode. */
+ if (INTVAL (x) == trunc_int_for_mode (INTVAL (x), SImode))
+ mode = SImode;
+ else
+ mode = DImode;
+
+ /* Avoid blowing up in arm_gen_constant (). */
+ if (!(outer_code == PLUS
+ || outer_code == AND
+ || outer_code == IOR
+ || outer_code == XOR
+ || outer_code == MINUS))
+ outer_code = SET;
+
+ const_int_cost:
+ if (mode == SImode)
+ {
+ *cost += 0;
+ *cost += COSTS_N_INSNS (arm_gen_constant (outer_code, SImode, NULL,
+ INTVAL (x), NULL, NULL,
+ 0, 0));
+ /* Extra costs? */
+ }
+ else
+ {
+ *cost += COSTS_N_INSNS (arm_gen_constant
+ (outer_code, SImode, NULL,
+ trunc_int_for_mode (INTVAL (x), SImode),
+ NULL, NULL, 0, 0)
+ + arm_gen_constant (outer_code, SImode, NULL,
+ INTVAL (x) >> 32, NULL,
+ NULL, 0, 0));
+ /* Extra costs? */
+ }
+
+ return true;
+
+ case CONST:
+ case LABEL_REF:
+ case SYMBOL_REF:
+ if (speed_p)
+ {
+ if (arm_arch_thumb2 && !flag_pic)
+ *cost = COSTS_N_INSNS (2);
+ else
+ *cost = COSTS_N_INSNS (1) + extra_cost->ldst.load;
+ }
+ else
+ *cost = COSTS_N_INSNS (2);
+
+ if (flag_pic)
+ {
+ *cost += COSTS_N_INSNS (1);
+ if (speed_p)
+ *cost += extra_cost->alu.arith;
+ }
+
+ return true;
+
+ case CONST_FIXED:
+ *cost = COSTS_N_INSNS (4);
+ /* Fixme. */
+ return true;
+
+ case CONST_DOUBLE:
+ if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT
+ && (mode == SFmode || !TARGET_VFP_SINGLE))
+ {
+ if (vfp3_const_double_rtx (x))
+ {
+ *cost = COSTS_N_INSNS (1);
+ if (speed_p)
+ *cost += extra_cost->fp[mode == DFmode].fpconst;
+ return true;
+ }
+
+ if (speed_p)
+ {
+ *cost = COSTS_N_INSNS (1);
+ if (mode == DFmode)
+ *cost += extra_cost->ldst.loadd;
+ else
+ *cost += extra_cost->ldst.loadf;
+ }
+ else
+ *cost = COSTS_N_INSNS (2 + (mode == DFmode));
+
+ return true;
+ }
+ *cost = COSTS_N_INSNS (4);
+ return true;
+
+ case CONST_VECTOR:
+ /* Fixme. */
+ if (TARGET_NEON
+ && TARGET_HARD_FLOAT
+ && (VALID_NEON_DREG_MODE (mode) || VALID_NEON_QREG_MODE (mode))
+ && neon_immediate_valid_for_move (x, mode, NULL, NULL))
+ *cost = COSTS_N_INSNS (1);
+ else
+ *cost = COSTS_N_INSNS (4);
+ return true;
+
+ case HIGH:
+ case LO_SUM:
+ *cost = COSTS_N_INSNS (1);
+ /* When optimizing for size, we prefer constant pool entries to
+ MOVW/MOVT pairs, so bump the cost of these slightly. */
+ if (!speed_p)
+ *cost += 1;
+ return true;
+
+ case CLZ:
+ *cost = COSTS_N_INSNS (1);
+ if (speed_p)
+ *cost += extra_cost->alu.clz;
+ return false;
+
+ case SMIN:
+ if (XEXP (x, 1) == const0_rtx)
+ {
+ *cost = COSTS_N_INSNS (1);
+ if (speed_p)
+ *cost += extra_cost->alu.log_shift;
+ *cost += rtx_cost (XEXP (x, 0), code, 0, speed_p);
+ return true;
+ }
+ /* Fall through. */
+ case SMAX:
+ case UMIN:
+ case UMAX:
+ *cost = COSTS_N_INSNS (2);
+ return false;
+
+ case TRUNCATE:
+ if (GET_CODE (XEXP (x, 0)) == ASHIFTRT
+ && CONST_INT_P (XEXP (XEXP (x, 0), 1))
+ && INTVAL (XEXP (XEXP (x, 0), 1)) == 32
+ && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT
+ && ((GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == SIGN_EXTEND
+ && GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)) == SIGN_EXTEND)
+ || (GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == ZERO_EXTEND
+ && (GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1))
+ == ZERO_EXTEND))))
+ {
+ *cost = COSTS_N_INSNS (1);
+ if (speed_p)
+ *cost += extra_cost->mult[1].extend;
+ *cost += (rtx_cost (XEXP (XEXP (XEXP (x, 0), 0), 0), ZERO_EXTEND, 0,
+ speed_p)
+ + rtx_cost (XEXP (XEXP (XEXP (x, 0), 0), 1), ZERO_EXTEND,
+ 0, speed_p));
+ return true;
+ }
+ *cost = LIBCALL_COST (1);
+ return false;
+
+ case UNSPEC:
+ return arm_unspec_cost (x, outer_code, speed_p, cost);
+
+ case PC:
+ /* Reading the PC is like reading any other register. Writing it
+ is more expensive, but we take that into account elsewhere. */
+ *cost = 0;
+ return true;
+
+ case ZERO_EXTRACT:
+ /* TODO: Simple zero_extract of bottom bits using AND. */
+ /* Fall through. */
+ case SIGN_EXTRACT:
+ if (arm_arch6
+ && mode == SImode
+ && CONST_INT_P (XEXP (x, 1))
+ && CONST_INT_P (XEXP (x, 2)))
+ {
+ *cost = COSTS_N_INSNS (1);
+ if (speed_p)
+ *cost += extra_cost->alu.bfx;
+ *cost += rtx_cost (XEXP (x, 0), code, 0, speed_p);
+ return true;
+ }
+ /* Without UBFX/SBFX, need to resort to shift operations. */
+ *cost = COSTS_N_INSNS (2);
+ if (speed_p)
+ *cost += 2 * extra_cost->alu.shift;
+ *cost += rtx_cost (XEXP (x, 0), ASHIFT, 0, speed_p);
+ return true;
+
+ case FLOAT_EXTEND:
+ if (TARGET_HARD_FLOAT)
+ {
+ *cost = COSTS_N_INSNS (1);
+ if (speed_p)
+ *cost += extra_cost->fp[mode == DFmode].widen;
+ if (!TARGET_FPU_ARMV8
+ && GET_MODE (XEXP (x, 0)) == HFmode)
+ {
+ /* Pre v8, widening HF->DF is a two-step process, first
+ widening to SFmode. */
+ *cost += COSTS_N_INSNS (1);
+ if (speed_p)
+ *cost += extra_cost->fp[0].widen;
+ }
+ *cost += rtx_cost (XEXP (x, 0), code, 0, speed_p);
+ return true;
+ }
+
+ *cost = LIBCALL_COST (1);
+ return false;
+
+ case FLOAT_TRUNCATE:
+ if (TARGET_HARD_FLOAT)
+ {
+ *cost = COSTS_N_INSNS (1);
+ if (speed_p)
+ *cost += extra_cost->fp[mode == DFmode].narrow;
+ *cost += rtx_cost (XEXP (x, 0), code, 0, speed_p);
+ return true;
+ /* Vector modes? */
+ }
+ *cost = LIBCALL_COST (1);
+ return false;
+
+ case FIX:
+ case UNSIGNED_FIX:
+ if (TARGET_HARD_FLOAT)
+ {
+ if (GET_MODE_CLASS (mode) == MODE_INT)
+ {
+ *cost = COSTS_N_INSNS (1);
+ if (speed_p)
+ *cost += extra_cost->fp[GET_MODE (XEXP (x, 0)) == DFmode].toint;
+ /* Strip of the 'cost' of rounding towards zero. */
+ if (GET_CODE (XEXP (x, 0)) == FIX)
+ *cost += rtx_cost (XEXP (XEXP (x, 0), 0), code, 0, speed_p);
+ else
+ *cost += rtx_cost (XEXP (x, 0), code, 0, speed_p);
+ /* ??? Increase the cost to deal with transferring from
+ FP -> CORE registers? */
+ return true;
+ }
+ else if (GET_MODE_CLASS (mode) == MODE_FLOAT
+ && TARGET_FPU_ARMV8)
+ {
+ *cost = COSTS_N_INSNS (1);
+ if (speed_p)
+ *cost += extra_cost->fp[mode == DFmode].roundint;
+ return false;
+ }
+ /* Vector costs? */
+ }
+ *cost = LIBCALL_COST (1);
+ return false;
+
+ case FLOAT:
+ case UNSIGNED_FLOAT:
+ if (TARGET_HARD_FLOAT)
+ {
+ /* ??? Increase the cost to deal with transferring from CORE
+ -> FP registers? */
+ *cost = COSTS_N_INSNS (1);
+ if (speed_p)
+ *cost += extra_cost->fp[mode == DFmode].fromint;
+ return false;
+ }
+ *cost = LIBCALL_COST (1);
+ return false;
+
+ case CALL:
+ *cost = COSTS_N_INSNS (1);
+ return true;
+
+ case ASM_OPERANDS:
+ /* Just a guess. Cost one insn per input. */
+ *cost = COSTS_N_INSNS (ASM_OPERANDS_INPUT_LENGTH (x));
+ return true;
+
+ default:
+ if (mode != VOIDmode)
+ *cost = COSTS_N_INSNS (ARM_NUM_REGS (mode));
+ else
+ *cost = COSTS_N_INSNS (4); /* Who knows? */
+ return false;
+ }
+}
+
/* RTX costs when optimizing for size. */
static bool
arm_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
int *total, bool speed)
{
- if (!speed)
- return arm_size_rtx_costs (x, (enum rtx_code) code,
- (enum rtx_code) outer_code, total);
+ bool result;
+
+ if (TARGET_OLD_RTX_COSTS
+ || (!current_tune->insn_extra_cost && !TARGET_NEW_GENERIC_COSTS))
+ {
+ /* Old way. (Deprecated.) */
+ if (!speed)
+ result = arm_size_rtx_costs (x, (enum rtx_code) code,
+ (enum rtx_code) outer_code, total);
+ else
+ result = current_tune->rtx_costs (x, (enum rtx_code) code,
+ (enum rtx_code) outer_code, total,
+ speed);
+ }
else
- return current_tune->rtx_costs (x, (enum rtx_code) code,
+ {
+ /* New way. */
+ if (current_tune->insn_extra_cost)
+ result = arm_new_rtx_costs (x, (enum rtx_code) code,
+ (enum rtx_code) outer_code,
+ current_tune->insn_extra_cost,
+ total, speed);
+ /* TARGET_NEW_GENERIC_COSTS && !TARGET_OLD_RTX_COSTS
+ && current_tune->insn_extra_cost != NULL */
+ else
+ result = arm_new_rtx_costs (x, (enum rtx_code) code,
(enum rtx_code) outer_code,
- total, speed);
+ &generic_extra_costs, total, speed);
+ }
+
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ print_rtl_single (dump_file, x);
+ fprintf (dump_file, "\n%s cost: %d (%s)\n", speed ? "Hot" : "Cold",
+ *total, result ? "final" : "partial");
+ }
+ return result;
}
/* RTX costs for cores with a slow MUL implementation. Thumb-2 is not
@@ -13333,23 +15469,6 @@ Mfix * minipool_fix_tail;
/* The fix entry for the current minipool, once it has been placed. */
Mfix * minipool_barrier;
-/* Determines if INSN is the start of a jump table. Returns the end
- of the TABLE or NULL_RTX. */
-static rtx
-is_jump_table (rtx insn)
-{
- rtx table;
-
- if (jump_to_label_p (insn)
- && ((table = next_active_insn (JUMP_LABEL (insn)))
- == next_active_insn (insn))
- && table != NULL
- && JUMP_TABLE_DATA_P (table))
- return table;
-
- return NULL_RTX;
-}
-
#ifndef JUMP_TABLES_IN_TEXT_SECTION
#define JUMP_TABLES_IN_TEXT_SECTION 0
#endif
@@ -13958,8 +16077,7 @@ create_fix_barrier (Mfix *fix, HOST_WIDE_INT max_address)
count += get_attr_length (from);
/* If there is a jump table, add its length. */
- tmp = is_jump_table (from);
- if (tmp != NULL)
+ if (tablejump_p (from, NULL, &tmp))
{
count += get_jump_table_size (tmp);
@@ -14565,7 +16683,7 @@ arm_reorg (void)
/* If the insn is a vector jump, add the size of the table
and skip the table. */
- if ((table = is_jump_table (insn)) != NULL)
+ if (tablejump_p (insn, NULL, &table))
{
address += get_jump_table_size (table);
insn = table;
@@ -17659,8 +19777,8 @@ arm_emit_ldrd_pop (unsigned long saved_regs_mask)
mem = gen_frame_mem (DImode, stack_pointer_rtx);
tmp = gen_rtx_SET (DImode, gen_rtx_REG (DImode, j), mem);
- RTX_FRAME_RELATED_P (tmp) = 1;
tmp = emit_insn (tmp);
+ RTX_FRAME_RELATED_P (tmp) = 1;
/* Generate dwarf info. */
@@ -17688,8 +19806,8 @@ arm_emit_ldrd_pop (unsigned long saved_regs_mask)
mem = gen_frame_mem (SImode, stack_pointer_rtx);
tmp = gen_rtx_SET (SImode, gen_rtx_REG (SImode, j), mem);
- RTX_FRAME_RELATED_P (tmp) = 1;
tmp = emit_insn (tmp);
+ RTX_FRAME_RELATED_P (tmp) = 1;
/* Generate dwarf info. */
REG_NOTES (tmp) = alloc_reg_note (REG_CFA_RESTORE,
@@ -17713,8 +19831,9 @@ arm_emit_ldrd_pop (unsigned long saved_regs_mask)
plus_constant (Pmode,
stack_pointer_rtx,
offset));
- RTX_FRAME_RELATED_P (tmp) = 1;
- emit_insn (tmp);
+ tmp = emit_insn (tmp);
+ arm_add_cfa_adjust_cfa_note (tmp, offset,
+ stack_pointer_rtx, stack_pointer_rtx);
offset = 0;
}
@@ -17737,6 +19856,8 @@ arm_emit_ldrd_pop (unsigned long saved_regs_mask)
gen_rtx_REG (SImode, PC_REGNUM),
NULL_RTX);
REG_NOTES (par) = dwarf;
+ arm_add_cfa_adjust_cfa_note (par, UNITS_PER_WORD,
+ stack_pointer_rtx, stack_pointer_rtx);
}
}
@@ -24409,6 +26530,7 @@ arm_expand_epilogue_apcs_frame (bool really_return)
num_regs = bit_count (saved_regs_mask);
if ((offsets->outgoing_args != (1 + num_regs)) || cfun->calls_alloca)
{
+ emit_insn (gen_blockage ());
/* Unwind the stack to just below the saved registers. */
emit_insn (gen_addsi3 (stack_pointer_rtx,
hard_frame_pointer_rtx,
@@ -25352,7 +27474,7 @@ arm_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
{
/* Output ".word .LTHUNKn-7-.LTHUNKPCn". */
rtx tem = XEXP (DECL_RTL (function), 0);
- tem = gen_rtx_PLUS (GET_MODE (tem), tem, GEN_INT (-7));
+ tem = plus_constant (GET_MODE (tem), tem, -7);
tem = gen_rtx_MINUS (GET_MODE (tem),
tem,
gen_rtx_SYMBOL_REF (Pmode,
@@ -26103,13 +28225,14 @@ arm_unwind_emit (FILE * asm_out_file, rtx insn)
for (note = REG_NOTES (insn); note ; note = XEXP (note, 1))
{
- pat = XEXP (note, 0);
switch (REG_NOTE_KIND (note))
{
case REG_FRAME_RELATED_EXPR:
+ pat = XEXP (note, 0);
goto found;
case REG_CFA_REGISTER:
+ pat = XEXP (note, 0);
if (pat == NULL)
{
pat = PATTERN (insn);
@@ -26470,7 +28593,7 @@ arm_output_iwmmxt_tinsr (rtx *operands)
const char *
thumb1_output_casesi (rtx *operands)
{
- rtx diff_vec = PATTERN (next_active_insn (operands[0]));
+ rtx diff_vec = PATTERN (NEXT_INSN (operands[0]));
gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
@@ -26493,7 +28616,7 @@ thumb1_output_casesi (rtx *operands)
const char *
thumb2_output_casesi (rtx *operands)
{
- rtx diff_vec = PATTERN (next_active_insn (operands[2]));
+ rtx diff_vec = PATTERN (NEXT_INSN (operands[2]));
gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
@@ -27028,10 +29151,10 @@ arm_emit_store_exclusive (enum machine_mode mode, rtx bval, rtx rval,
static void
emit_unlikely_jump (rtx insn)
{
- rtx very_unlikely = GEN_INT (REG_BR_PROB_BASE / 100 - 1);
+ int very_unlikely = REG_BR_PROB_BASE / 100 - 1;
insn = emit_jump_insn (insn);
- add_reg_note (insn, REG_BR_PROB, very_unlikely);
+ add_int_reg_note (insn, REG_BR_PROB, very_unlikely);
}
/* Expand a compare and swap pattern. */
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index b094cff0d7e..3726201dd4f 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -252,6 +252,103 @@
; initialized by arm_option_override()
(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
+; YES if the "type" attribute assigned to the insn denotes an
+; Advanced SIMD instruction, NO otherwise.
+(define_attr "is_neon_type" "yes,no"
+ (if_then_else (eq_attr "type"
+ "neon_add, neon_add_q, neon_add_widen, neon_add_long,\
+ neon_qadd, neon_qadd_q, neon_add_halve, neon_add_halve_q,\
+ neon_add_halve_narrow_q,\
+ neon_sub, neon_sub_q, neon_sub_widen, neon_sub_long, neon_qsub,\
+ neon_qsub_q, neon_sub_halve, neon_sub_halve_q,\
+ neon_sub_halve_narrow_q,\
+ neon_abs, neon_abs_q, neon_neg, neon_neg_q, neon_qneg,\
+ neon_qneg_q, neon_qabs, neon_qabs_q, neon_abd, neon_abd_q,\
+ neon_abd_long, neon_minmax, neon_minmax_q, neon_compare,\
+ neon_compare_q, neon_compare_zero, neon_compare_zero_q,\
+ neon_arith_acc, neon_arith_acc_q, neon_reduc_add,\
+ neon_reduc_add_q, neon_reduc_add_long, neon_reduc_add_acc,\
+ neon_reduc_add_acc_q, neon_reduc_minmax, neon_reduc_minmax_q,\
+ neon_logic, neon_logic_q, neon_tst, neon_tst_q,\
+ neon_shift_imm, neon_shift_imm_q, neon_shift_imm_narrow_q,\
+ neon_shift_imm_long, neon_shift_reg, neon_shift_reg_q,\
+ neon_shift_acc, neon_shift_acc_q, neon_sat_shift_imm,\
+ neon_sat_shift_imm_q, neon_sat_shift_imm_narrow_q,\
+ neon_sat_shift_reg, neon_sat_shift_reg_q,\
+ neon_ins, neon_ins_q, neon_move, neon_move_q, neon_move_narrow_q,\
+ neon_permute, neon_permute_q, neon_zip, neon_zip_q, neon_tbl1,\
+ neon_tbl1_q, neon_tbl2, neon_tbl2_q, neon_tbl3, neon_tbl3_q,\
+ neon_tbl4, neon_tbl4_q, neon_bsl, neon_bsl_q, neon_cls,\
+ neon_cls_q, neon_cnt, neon_cnt_q, neon_dup, neon_dup_q,\
+ neon_ext, neon_ext_q, neon_rbit, neon_rbit_q,\
+ neon_rev, neon_rev_q, neon_mul_b, neon_mul_b_q, neon_mul_h,\
+ neon_mul_h_q, neon_mul_s, neon_mul_s_q, neon_mul_b_long,\
+ neon_mul_h_long, neon_mul_s_long, neon_mul_h_scalar,\
+ neon_mul_h_scalar_q, neon_mul_s_scalar, neon_mul_s_scalar_q,\
+ neon_mul_h_scalar_long, neon_mul_s_scalar_long, neon_sat_mul_b,\
+ neon_sat_mul_b_q, neon_sat_mul_h, neon_sat_mul_h_q,\
+ neon_sat_mul_s, neon_sat_mul_s_q, neon_sat_mul_b_long,\
+ neon_sat_mul_h_long, neon_sat_mul_s_long, neon_sat_mul_h_scalar,\
+ neon_sat_mul_h_scalar_q, neon_sat_mul_s_scalar,\
+ neon_sat_mul_s_scalar_q, neon_sat_mul_h_scalar_long,\
+ neon_sat_mul_s_scalar_long, neon_mla_b, neon_mla_b_q, neon_mla_h,\
+ neon_mla_h_q, neon_mla_s, neon_mla_s_q, neon_mla_b_long,\
+ neon_mla_h_long, neon_mla_s_long, neon_mla_h_scalar,\
+ neon_mla_h_scalar_q, neon_mla_s_scalar, neon_mla_s_scalar_q,\
+ neon_mla_h_scalar_long, neon_mla_s_scalar_long,\
+ neon_sat_mla_b_long, neon_sat_mla_h_long,\
+ neon_sat_mla_s_long, neon_sat_mla_h_scalar_long,\
+ neon_sat_mla_s_scalar_long,\
+ neon_to_gp, neon_to_gp_q, neon_from_gp, neon_from_gp_q,\
+ neon_ldr, neon_load1_1reg, neon_load1_1reg_q, neon_load1_2reg,\
+ neon_load1_2reg_q, neon_load1_3reg, neon_load1_3reg_q,\
+ neon_load1_4reg, neon_load1_4reg_q, neon_load1_all_lanes,\
+ neon_load1_all_lanes_q, neon_load1_one_lane, neon_load1_one_lane_q,\
+ neon_load2_2reg, neon_load2_2reg_q, neon_load2_4reg,\
+ neon_load2_4reg_q, neon_load2_all_lanes, neon_load2_all_lanes_q,\
+ neon_load2_one_lane, neon_load2_one_lane_q,\
+ neon_load3_3reg, neon_load3_3reg_q, neon_load3_all_lanes,\
+ neon_load3_all_lanes_q, neon_load3_one_lane, neon_load3_one_lane_q,\
+ neon_load4_4reg, neon_load4_4reg_q, neon_load4_all_lanes,\
+ neon_load4_all_lanes_q, neon_load4_one_lane, neon_load4_one_lane_q,\
+ neon_str, neon_store1_1reg, neon_store1_1reg_q, neon_store1_2reg,\
+ neon_store1_2reg_q, neon_store1_3reg, neon_store1_3reg_q,\
+ neon_store1_4reg, neon_store1_4reg_q, neon_store1_one_lane,\
+ neon_store1_one_lane_q, neon_store2_2reg, neon_store2_2reg_q,\
+ neon_store2_4reg, neon_store2_4reg_q, neon_store2_one_lane,\
+ neon_store2_one_lane_q, neon_store3_3reg, neon_store3_3reg_q,\
+ neon_store3_one_lane, neon_store3_one_lane_q, neon_store4_4reg,\
+ neon_store4_4reg_q, neon_store4_one_lane, neon_store4_one_lane_q,\
+ neon_fp_abd_s, neon_fp_abd_s_q, neon_fp_abd_d, neon_fp_abd_d_q,\
+ neon_fp_addsub_s, neon_fp_addsub_s_q, neon_fp_addsub_d,\
+ neon_fp_addsub_d_q, neon_fp_compare_s, neon_fp_compare_s_q,\
+ neon_fp_compare_d, neon_fp_compare_d_q, neon_fp_minmax_s,\
+ neon_fp_minmax_s_q, neon_fp_minmax_d, neon_fp_minmax_d_q,\
+ neon_fp_reduc_add_s, neon_fp_reduc_add_s_q, neon_fp_reduc_add_d,\
+ neon_fp_reduc_add_d_q, neon_fp_reduc_minmax_s,
+ neon_fp_reduc_minmax_s_q, neon_fp_reduc_minmax_d,\
+ neon_fp_reduc_minmax_d_q,\
+ neon_fp_cvt_narrow_s_q, neon_fp_cvt_narrow_d_q,\
+ neon_fp_cvt_widen_h, neon_fp_cvt_widen_s, neon_fp_to_int_s,\
+ neon_fp_to_int_s_q, neon_int_to_fp_s, neon_int_to_fp_s_q,\
+ neon_fp_round_s, neon_fp_round_s_q, neon_fp_recpe_s,\
+ neon_fp_recpe_s_q,\
+ neon_fp_recpe_d, neon_fp_recpe_d_q, neon_fp_recps_s,\
+ neon_fp_recps_s_q, neon_fp_recps_d, neon_fp_recps_d_q,\
+ neon_fp_recpx_s, neon_fp_recpx_s_q, neon_fp_recpx_d,\
+ neon_fp_recpx_d_q, neon_fp_rsqrte_s, neon_fp_rsqrte_s_q,\
+ neon_fp_rsqrte_d, neon_fp_rsqrte_d_q, neon_fp_rsqrts_s,\
+ neon_fp_rsqrts_s_q, neon_fp_rsqrts_d, neon_fp_rsqrts_d_q,\
+ neon_fp_mul_s, neon_fp_mul_s_q, neon_fp_mul_s_scalar,\
+ neon_fp_mul_s_scalar_q, neon_fp_mul_d, neon_fp_mul_d_q,\
+ neon_fp_mul_d_scalar_q, neon_fp_mla_s, neon_fp_mla_s_q,\
+ neon_fp_mla_s_scalar, neon_fp_mla_s_scalar_q, neon_fp_mla_d,\
+ neon_fp_mla_d_q, neon_fp_mla_d_scalar_q, neon_fp_sqrt_s,\
+ neon_fp_sqrt_s_q, neon_fp_sqrt_d, neon_fp_sqrt_d_q,\
+ neon_fp_div_s, neon_fp_div_s_q, neon_fp_div_d, neon_fp_div_d_q")
+ (const_string "yes")
+ (const_string "no")))
+
; condition codes: this one is used by final_prescan_insn to speed up
; conditionalizing instructions. It saves having to scan the rtl to see if
; it uses or alters the condition codes.
@@ -277,32 +374,7 @@
(ior (eq_attr "is_thumb1" "yes")
(eq_attr "type" "call"))
(const_string "clob")
- (if_then_else (eq_attr "type"
- "!neon_int_1, neon_int_2, neon_int_3, neon_int_4, neon_int_5,\
- neon_vqneg_vqabs, neon_vmov, neon_vaba, neon_vsma, neon_vaba_qqq,\
- neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
- neon_mul_qqq_8_16_32_ddd_32,\
- neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar,\
- neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
- neon_mla_qqq_8_16,\
- neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long,\
- neon_mla_qqq_32_qqd_32_scalar,\
- neon_mul_ddd_16_scalar_32_16_long_scalar, neon_mul_qqd_32_scalar,\
- neon_mla_ddd_16_scalar_qdd_32_16_long_scalar, neon_shift_1,\
- neon_shift_2, neon_shift_3, neon_vshl_ddd,\
- neon_vqshl_vrshl_vqrshl_qqq, neon_vsra_vrsra,\
- neon_fp_vadd_ddd_vabs_dd, neon_fp_vadd_qqq_vabs_qq, neon_fp_vsum,\
- neon_fp_vmul_ddd, neon_fp_vmul_qqd, neon_fp_vmla_ddd,\
- neon_fp_vmla_qqq, neon_fp_vmla_ddd_scalar, neon_fp_vmla_qqq_scalar,\
- neon_fp_vrecps_vrsqrts_ddd, neon_fp_vrecps_vrsqrts_qqq,\
- neon_bp_simple, neon_bp_2cycle, neon_bp_3cycle, neon_ldr, neon_str,\
- neon_vld1_1_2_regs, neon_vld1_3_4_regs,\
- neon_vld2_2_regs_vld1_vld2_all_lanes, neon_vld2_4_regs,\
- neon_vld3_vld4, neon_vst1_1_2_regs_vst2_2_regs, neon_vst1_3_4_regs,\
- neon_vst2_4_regs_vst3_vst4, neon_vst3_vst4, neon_vld1_vld2_lane,\
- neon_vld3_vld4_lane, neon_vst1_vst2_lane, neon_vst3_vst4_lane,\
- neon_vld3_vld4_all_lanes, neon_mcr, neon_mcr_2_mcrr, neon_mrc,\
- neon_mrrc, neon_ldm_2, neon_stm_2")
+ (if_then_else (eq_attr "is_neon_type" "no")
(const_string "nocond")
(const_string "unconditional"))))
@@ -2162,7 +2234,8 @@
gen_highpart_mode (SImode, DImode, operands[2]));
}"
- [(set_attr "type" "neon_int_1,neon_int_1,multiple,multiple,multiple,multiple,neon_int_1,neon_int_1")
+ [(set_attr "type" "neon_logic,neon_logic,multiple,multiple,\
+ multiple,multiple,neon_logic,neon_logic")
(set_attr "arch" "neon_for_64bits,neon_for_64bits,*,*,*,*,
avoid_neon_for_64bits,avoid_neon_for_64bits")
(set_attr "length" "*,*,8,8,8,8,*,*")
@@ -3012,7 +3085,8 @@
gen_highpart_mode (SImode, DImode, operands[2]));
}"
- [(set_attr "type" "neon_int_1,neon_int_1,multiple,multiple,multiple,multiple,neon_int_1,neon_int_1")
+ [(set_attr "type" "neon_logic,neon_logic,multiple,multiple,multiple,\
+ multiple,neon_logic,neon_logic")
(set_attr "length" "*,*,8,8,8,8,*,*")
(set_attr "arch" "neon_for_64bits,neon_for_64bits,*,*,*,*,avoid_neon_for_64bits,avoid_neon_for_64bits")]
)
@@ -3194,7 +3268,7 @@
}"
[(set_attr "length" "*,8,8,8,8,*")
- (set_attr "type" "neon_int_1,multiple,multiple,multiple,multiple,neon_int_1")
+ (set_attr "type" "neon_logic,multiple,multiple,multiple,multiple,neon_logic")
(set_attr "arch" "neon_for_64bits,*,*,*,*,avoid_neon_for_64bits")]
)
@@ -3867,26 +3941,13 @@
"
)
-(define_insn_and_split "arm_ashldi3_1bit"
+(define_insn "arm_ashldi3_1bit"
[(set (match_operand:DI 0 "s_register_operand" "=r,&r")
(ashift:DI (match_operand:DI 1 "s_register_operand" "0,r")
(const_int 1)))
(clobber (reg:CC CC_REGNUM))]
"TARGET_32BIT"
- "#" ; "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
- "&& reload_completed"
- [(parallel [(set (reg:CC CC_REGNUM)
- (compare:CC (ashift:SI (match_dup 1) (const_int 1))
- (const_int 0)))
- (set (match_dup 0) (ashift:SI (match_dup 1) (const_int 1)))])
- (set (match_dup 2) (plus:SI (plus:SI (match_dup 3) (match_dup 3))
- (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
- {
- operands[2] = gen_highpart (SImode, operands[0]);
- operands[0] = gen_lowpart (SImode, operands[0]);
- operands[3] = gen_highpart (SImode, operands[1]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- }
+ "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
[(set_attr "conds" "clob")
(set_attr "length" "8")
(set_attr "type" "multiple")]
@@ -3964,43 +4025,18 @@
"
)
-(define_insn_and_split "arm_ashrdi3_1bit"
+(define_insn "arm_ashrdi3_1bit"
[(set (match_operand:DI 0 "s_register_operand" "=r,&r")
(ashiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
(const_int 1)))
(clobber (reg:CC CC_REGNUM))]
"TARGET_32BIT"
- "#" ; "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
- "&& reload_completed"
- [(parallel [(set (reg:CC CC_REGNUM)
- (compare:CC (ashiftrt:SI (match_dup 3) (const_int 1))
- (const_int 0)))
- (set (match_dup 2) (ashiftrt:SI (match_dup 3) (const_int 1)))])
- (set (match_dup 0) (unspec:SI [(match_dup 1)
- (reg:CC_C CC_REGNUM)]
- UNSPEC_RRX))]
- {
- operands[2] = gen_highpart (SImode, operands[0]);
- operands[0] = gen_lowpart (SImode, operands[0]);
- operands[3] = gen_highpart (SImode, operands[1]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- }
+ "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
[(set_attr "conds" "clob")
(set_attr "length" "8")
(set_attr "type" "multiple")]
)
-(define_insn "*rrx"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")
- (reg:CC_C CC_REGNUM)]
- UNSPEC_RRX))]
- "TARGET_32BIT"
- "mov\\t%0, %1, rrx"
- [(set_attr "conds" "use")
- (set_attr "type" "mov_shift")]
-)
-
(define_expand "ashrsi3"
[(set (match_operand:SI 0 "s_register_operand" "")
(ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
@@ -4070,27 +4106,13 @@
"
)
-(define_insn_and_split "arm_lshrdi3_1bit"
+(define_insn "arm_lshrdi3_1bit"
[(set (match_operand:DI 0 "s_register_operand" "=r,&r")
(lshiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
(const_int 1)))
(clobber (reg:CC CC_REGNUM))]
"TARGET_32BIT"
- "#" ; "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
- "&& reload_completed"
- [(parallel [(set (reg:CC CC_REGNUM)
- (compare:CC (lshiftrt:SI (match_dup 3) (const_int 1))
- (const_int 0)))
- (set (match_dup 2) (lshiftrt:SI (match_dup 3) (const_int 1)))])
- (set (match_dup 0) (unspec:SI [(match_dup 1)
- (reg:CC_C CC_REGNUM)]
- UNSPEC_RRX))]
- {
- operands[2] = gen_highpart (SImode, operands[0]);
- operands[0] = gen_lowpart (SImode, operands[0]);
- operands[3] = gen_highpart (SImode, operands[1]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- }
+ "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
[(set_attr "conds" "clob")
(set_attr "length" "8")
(set_attr "type" "multiple")]
@@ -4183,21 +4205,6 @@
(set_attr "type" "alu_shift_reg,alu_shift_imm,alu_shift_imm,alu_shift_reg")]
)
-(define_insn "*shiftsi3_compare"
- [(set (reg:CC CC_REGNUM)
- (compare:CC (match_operator:SI 3 "shift_operator"
- [(match_operand:SI 1 "s_register_operand" "r,r")
- (match_operand:SI 2 "arm_rhs_operand" "M,r")])
- (const_int 0)))
- (set (match_operand:SI 0 "s_register_operand" "=r,r")
- (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
- "TARGET_32BIT"
- "* return arm_output_shift(operands, 1);"
- [(set_attr "conds" "set")
- (set_attr "shift" "1")
- (set_attr "type" "alus_shift_imm,alus_shift_reg")]
-)
-
(define_insn "*shiftsi3_compare0"
[(set (reg:CC_NOOV CC_REGNUM)
(compare:CC_NOOV (match_operator:SI 3 "shift_operator"
@@ -4989,7 +4996,7 @@
}"
[(set_attr "length" "*,8,8,*")
(set_attr "predicable" "no,yes,yes,no")
- (set_attr "type" "neon_int_1,multiple,multiple,neon_int_1")
+ (set_attr "type" "neon_move,multiple,multiple,neon_move")
(set_attr "arch" "neon_for_64bits,*,*,avoid_neon_for_64bits")]
)
diff --git a/gcc/config/arm/arm.opt b/gcc/config/arm/arm.opt
index b9ae2b09682..9b740386ca3 100644
--- a/gcc/config/arm/arm.opt
+++ b/gcc/config/arm/arm.opt
@@ -143,6 +143,10 @@ mfpu=
Target RejectNegative Joined Enum(arm_fpu) Var(arm_fpu_index)
Specify the name of the target floating point hardware/format
+mlra
+Target Report Var(arm_lra_flag) Init(0) Save
+Use LRA instead of reload (transitional)
+
mhard-float
Target RejectNegative Alias(mfloat-abi=, hard) Undocumented
@@ -243,6 +247,14 @@ mrestrict-it
Target Report Var(arm_restrict_it) Init(2)
Generate IT blocks appropriate for ARMv8.
+mold-rtx-costs
+Target Report Mask(OLD_RTX_COSTS)
+Use the old RTX costing tables (transitional).
+
+mnew-generic-costs
+Target Report Mask(NEW_GENERIC_COSTS)
+Use the new generic RTX cost tables if new core-specific cost table not available (transitional).
+
mfix-cortex-m3-ldrd
Target Report Var(fix_cm3_ldrd) Init(2)
Avoid overlapping destination and address registers on LDRD instructions
diff --git a/gcc/config/arm/cortex-a15-neon.md b/gcc/config/arm/cortex-a15-neon.md
index 6eb8268321a..ebb6b66f782 100644
--- a/gcc/config/arm/cortex-a15-neon.md
+++ b/gcc/config/arm/cortex-a15-neon.md
@@ -17,6 +17,199 @@
;; along with GCC; see the file COPYING3. If not see
;; <http://www.gnu.org/licenses/>.
+(define_attr "cortex_a15_neon_type"
+ "neon_abd, neon_abd_q, neon_arith_acc, neon_arith_acc_q,
+ neon_arith_basic, neon_arith_complex,
+ neon_reduc_add_acc, neon_multiply, neon_multiply_q,
+ neon_multiply_long, neon_mla, neon_mla_q, neon_mla_long,
+ neon_sat_mla_long, neon_shift_acc, neon_shift_imm_basic,\
+ neon_shift_imm_complex,
+ neon_shift_reg_basic, neon_shift_reg_basic_q, neon_shift_reg_complex,
+ neon_shift_reg_complex_q, neon_fp_negabs, neon_fp_arith,
+ neon_fp_arith_q, neon_fp_cvt_int,
+ neon_fp_cvt_int_q, neon_fp_cvt16, neon_fp_minmax, neon_fp_mul,
+ neon_fp_mul_q, neon_fp_mla, neon_fp_mla_q, neon_fp_recpe_rsqrte,
+ neon_fp_recpe_rsqrte_q, neon_bitops, neon_bitops_q, neon_from_gp,
+ neon_from_gp_q, neon_move, neon_tbl3_tbl4, neon_zip_q, neon_to_gp,
+ neon_load_a, neon_load_b, neon_load_c, neon_load_d, neon_load_e,
+ neon_load_f, neon_store_a, neon_store_b, neon_store_c, neon_store_d,
+ neon_store_e, neon_store_f, neon_store_g, neon_store_h,
+ unknown"
+ (cond [
+ (eq_attr "type" "neon_abd, neon_abd_long")
+ (const_string "neon_abd")
+ (eq_attr "type" "neon_abd_q")
+ (const_string "neon_abd_q")
+ (eq_attr "type" "neon_arith_acc, neon_reduc_add_acc,\
+ neon_reduc_add_acc_q")
+ (const_string "neon_arith_acc")
+ (eq_attr "type" "neon_arith_acc_q")
+ (const_string "neon_arith_acc_q")
+ (eq_attr "type" "neon_add, neon_add_q, neon_add_long,\
+ neon_add_widen, neon_neg, neon_neg_q,\
+ neon_reduc_add, neon_reduc_add_q,\
+ neon_reduc_add_long, neon_sub, neon_sub_q,\
+ neon_sub_long, neon_sub_widen, neon_logic,\
+ neon_logic_q, neon_tst, neon_tst_q")
+ (const_string "neon_arith_basic")
+ (eq_attr "type" "neon_abs, neon_abs_q, neon_add_halve_narrow_q,\
+ neon_add_halve, neon_add_halve_q,\
+ neon_sub_halve, neon_sub_halve_q, neon_qabs,\
+ neon_qabs_q, neon_qadd, neon_qadd_q, neon_qneg,\
+ neon_qneg_q, neon_qsub, neon_qsub_q,\
+ neon_sub_halve_narrow_q,\
+ neon_compare, neon_compare_q,\
+ neon_compare_zero, neon_compare_zero_q,\
+ neon_minmax, neon_minmax_q, neon_reduc_minmax,\
+ neon_reduc_minmax_q")
+ (const_string "neon_arith_complex")
+
+ (eq_attr "type" "neon_mul_b, neon_mul_h, neon_mul_s,\
+ neon_mul_h_scalar, neon_mul_s_scalar,\
+ neon_sat_mul_b, neon_sat_mul_h,\
+ neon_sat_mul_s, neon_sat_mul_h_scalar,\
+ neon_sat_mul_s_scalar,\
+ neon_mul_b_long, neon_mul_h_long,\
+ neon_mul_s_long,\
+ neon_mul_h_scalar_long, neon_mul_s_scalar_long,\
+ neon_sat_mul_b_long, neon_sat_mul_h_long,\
+ neon_sat_mul_s_long, neon_sat_mul_h_scalar_long,\
+ neon_sat_mul_s_scalar_long")
+ (const_string "neon_multiply")
+ (eq_attr "type" "neon_mul_b_q, neon_mul_h_q, neon_mul_s_q,\
+ neon_mul_h_scalar_q, neon_mul_s_scalar_q,\
+ neon_sat_mul_b_q, neon_sat_mul_h_q,\
+ neon_sat_mul_s_q, neon_sat_mul_h_scalar_q,\
+ neon_sat_mul_s_scalar_q")
+ (const_string "neon_multiply_q")
+ (eq_attr "type" "neon_mla_b, neon_mla_h, neon_mla_s,\
+ neon_mla_h_scalar, neon_mla_s_scalar,\
+ neon_mla_b_long, neon_mla_h_long,\
+ neon_mla_s_long,\
+ neon_mla_h_scalar_long, neon_mla_s_scalar_long")
+ (const_string "neon_mla")
+ (eq_attr "type" "neon_mla_b_q, neon_mla_h_q, neon_mla_s_q,\
+ neon_mla_h_scalar_q, neon_mla_s_scalar_q")
+ (const_string "neon_mla_q")
+ (eq_attr "type" "neon_sat_mla_b_long, neon_sat_mla_h_long,\
+ neon_sat_mla_s_long, neon_sat_mla_h_scalar_long,\
+ neon_sat_mla_s_scalar_long")
+ (const_string "neon_sat_mla_long")
+
+ (eq_attr "type" "neon_shift_acc, neon_shift_acc_q")
+ (const_string "neon_shift_acc")
+ (eq_attr "type" "neon_shift_imm, neon_shift_imm_q,\
+ neon_shift_imm_narrow_q, neon_shift_imm_long")
+ (const_string "neon_shift_imm_basic")
+ (eq_attr "type" "neon_sat_shift_imm, neon_sat_shift_imm_q,\
+ neon_sat_shift_imm_narrow_q")
+ (const_string "neon_shift_imm_complex")
+ (eq_attr "type" "neon_shift_reg")
+ (const_string "neon_shift_reg_basic")
+ (eq_attr "type" "neon_shift_reg_q")
+ (const_string "neon_shift_reg_basic_q")
+ (eq_attr "type" "neon_sat_shift_reg")
+ (const_string "neon_shift_reg_complex")
+ (eq_attr "type" "neon_sat_shift_reg_q")
+ (const_string "neon_shift_reg_complex_q")
+
+ (eq_attr "type" "neon_fp_neg_s, neon_fp_neg_s_q,\
+ neon_fp_abs_s, neon_fp_abs_s_q")
+ (const_string "neon_fp_negabs")
+ (eq_attr "type" "neon_fp_addsub_s, neon_fp_abd_s,\
+ neon_fp_reduc_add_s, neon_fp_compare_s,\
+ neon_fp_minmax_s, neon_fp_minmax_s_q,\
+ neon_fp_reduc_minmax_s, neon_fp_reduc_minmax_s_q")
+ (const_string "neon_fp_arith")
+ (eq_attr "type" "neon_fp_addsub_s_q, neon_fp_abd_s_q,\
+ neon_fp_reduc_add_s_q, neon_fp_compare_s_q")
+ (const_string "neon_fp_arith_q")
+ (eq_attr "type" "neon_fp_to_int_s, neon_int_to_fp_s")
+ (const_string "neon_fp_cvt_int")
+ (eq_attr "type" "neon_fp_to_int_s_q, neon_int_to_fp_s_q")
+ (const_string "neon_fp_cvt_int_q")
+ (eq_attr "type" "neon_fp_cvt_narrow_s_q, neon_fp_cvt_widen_h")
+ (const_string "neon_fp_cvt16")
+ (eq_attr "type" "neon_fp_mul_s, neon_fp_mul_s_scalar")
+ (const_string "neon_fp_mul")
+ (eq_attr "type" "neon_fp_mul_s_q, neon_fp_mul_s_scalar_q")
+ (const_string "neon_fp_mul_q")
+ (eq_attr "type" "neon_fp_mla_s, neon_fp_mla_s_scalar")
+ (const_string "neon_fp_mla")
+ (eq_attr "type" "neon_fp_mla_s_q, neon_fp_mla_s_scalar_q")
+ (const_string "neon_fp_mla_q")
+ (eq_attr "type" "neon_fp_recpe_s, neon_fp_rsqrte_s")
+ (const_string "neon_fp_recpe_rsqrte")
+ (eq_attr "type" "neon_fp_recpe_s_q, neon_fp_rsqrte_s_q")
+ (const_string "neon_fp_recpe_rsqrte_q")
+
+ (eq_attr "type" "neon_bsl, neon_cls, neon_cnt,\
+ neon_rev, neon_permute,\
+ neon_tbl1, neon_tbl2, neon_zip,\
+ neon_dup, neon_dup_q, neon_ext, neon_ext_q,\
+ neon_move, neon_move_q, neon_move_narrow_q")
+ (const_string "neon_bitops")
+ (eq_attr "type" "neon_bsl_q, neon_cls_q, neon_cnt_q,\
+ neon_rev_q, neon_permute_q")
+ (const_string "neon_bitops_q")
+ (eq_attr "type" "neon_from_gp")
+ (const_string "neon_from_gp")
+ (eq_attr "type" "neon_from_gp_q")
+ (const_string "neon_from_gp_q")
+ (eq_attr "type" "neon_tbl3, neon_tbl4")
+ (const_string "neon_tbl3_tbl4")
+ (eq_attr "type" "neon_zip_q")
+ (const_string "neon_zip_q")
+ (eq_attr "type" "neon_to_gp, neon_to_gp_q")
+ (const_string "neon_to_gp")
+
+ (eq_attr "type" "f_loads, f_loadd,\
+ neon_load1_1reg, neon_load1_1reg_q,\
+ neon_load1_2reg, neon_load1_2reg_q")
+ (const_string "neon_load_a")
+ (eq_attr "type" "neon_load1_3reg, neon_load1_3reg_q,\
+ neon_load1_4reg, neon_load1_4reg_q")
+ (const_string "neon_load_b")
+ (eq_attr "type" "neon_load1_one_lane, neon_load1_one_lane_q,\
+ neon_load1_all_lanes, neon_load1_all_lanes_q,\
+ neon_load2_2reg, neon_load2_2reg_q,\
+ neon_load2_all_lanes, neon_load2_all_lanes_q")
+ (const_string "neon_load_c")
+ (eq_attr "type" "neon_load2_4reg, neon_load2_4reg_q,\
+ neon_load3_3reg, neon_load3_3reg_q,\
+ neon_load3_one_lane, neon_load3_one_lane_q,\
+ neon_load4_4reg, neon_load4_4reg_q")
+ (const_string "neon_load_d")
+ (eq_attr "type" "neon_load2_one_lane, neon_load2_one_lane_q,\
+ neon_load3_all_lanes, neon_load3_all_lanes_q,\
+ neon_load4_all_lanes, neon_load4_all_lanes_q")
+ (const_string "neon_load_e")
+ (eq_attr "type" "neon_load4_one_lane, neon_load4_one_lane_q")
+ (const_string "neon_load_f")
+
+ (eq_attr "type" "f_stores, f_stored,\
+ neon_store1_1reg, neon_store1_1reg_q")
+ (const_string "neon_store_a")
+ (eq_attr "type" "neon_store1_2reg, neon_store1_2reg_q")
+ (const_string "neon_store_b")
+ (eq_attr "type" "neon_store1_3reg, neon_store1_3reg_q")
+ (const_string "neon_store_c")
+ (eq_attr "type" "neon_store1_4reg, neon_store1_4reg_q")
+ (const_string "neon_store_d")
+ (eq_attr "type" "neon_store1_one_lane, neon_store1_one_lane_q,\
+ neon_store2_one_lane, neon_store2_one_lane_q")
+ (const_string "neon_store_e")
+ (eq_attr "type" "neon_store2_2reg, neon_store2_2reg_q,\
+ neon_store3_one_lane, neon_store3_one_lane_q,\
+ neon_store4_one_lane, neon_store4_one_lane_q")
+ (const_string "neon_store_f")
+ (eq_attr "type" "neon_store2_4reg, neon_store2_4reg_q,\
+ neon_store4_4reg, neon_store4_4reg_q")
+ (const_string "neon_store_g")
+ (eq_attr "type" "neon_store3_3reg, neon_store3_3reg_q")
+ (const_string "neon_store_h")]
+ (const_string "unknown")))
+
(define_automaton "cortex_a15_neon")
;; Dispatch unit.
@@ -91,348 +284,316 @@
(define_reservation "ca15_cx_perm" "ca15_cx_ij|ca15_cx_ik")
(define_reservation "ca15_cx_perm_2" "ca15_cx_ij+ca15_cx_ik")
-(define_insn_reservation "cortex_a15_neon_int_1" 5
- (and (eq_attr "tune" "cortexa15")
- (eq_attr "type" "neon_int_1"))
- "ca15_issue1,ca15_cx_ialu")
+;; Integer Arithmetic Instructions.
-(define_insn_reservation "cortex_a15_neon_int_2" 5
+(define_insn_reservation "cortex_a15_neon_abd" 5
(and (eq_attr "tune" "cortexa15")
- (eq_attr "type" "neon_int_2"))
+ (eq_attr "cortex_a15_neon_type" "neon_abd"))
"ca15_issue1,ca15_cx_ialu")
-(define_insn_reservation "cortex_a15_neon_int_3" 5
+(define_insn_reservation "cortex_a15_neon_abd_q" 5
(and (eq_attr "tune" "cortexa15")
- (eq_attr "type" "neon_int_3"))
- "ca15_issue1,ca15_cx_ialu")
+ (eq_attr "cortex_a15_neon_type" "neon_abd_q"))
+ "ca15_issue2,ca15_cx_ialu*2")
-(define_insn_reservation "cortex_a15_neon_int_4" 5
+(define_insn_reservation "cortex_a15_neon_aba" 7
(and (eq_attr "tune" "cortexa15")
- (eq_attr "type" "neon_int_4"))
- "ca15_issue1,ca15_cx_ialu")
+ (eq_attr "cortex_a15_neon_type" "neon_arith_acc"))
+ "ca15_issue1,ca15_cx_ialu_with_acc")
-(define_insn_reservation "cortex_a15_neon_int_5" 5
+(define_insn_reservation "cortex_a15_neon_aba_q" 8
(and (eq_attr "tune" "cortexa15")
- (eq_attr "type" "neon_int_5"))
- "ca15_issue1,ca15_cx_ialu")
+ (eq_attr "cortex_a15_neon_type" "neon_arith_acc_q"))
+ "ca15_issue2,ca15_cx_ialu_with_acc*2")
-(define_insn_reservation "cortex_a15_neon_vqneg_vqabs" 5
+(define_insn_reservation "cortex_a15_neon_arith_basic" 4
(and (eq_attr "tune" "cortexa15")
- (eq_attr "type" "neon_vqneg_vqabs"))
+ (eq_attr "cortex_a15_neon_type" "neon_arith_basic"))
"ca15_issue1,ca15_cx_ialu")
-(define_insn_reservation "cortex_a15_neon_vmov" 5
+(define_insn_reservation "cortex_a15_neon_arith_complex" 5
(and (eq_attr "tune" "cortexa15")
- (eq_attr "type" "neon_vmov"))
+ (eq_attr "cortex_a15_neon_type" "neon_arith_complex"))
"ca15_issue1,ca15_cx_ialu")
-(define_insn_reservation "cortex_a15_neon_vaba" 7
- (and (eq_attr "tune" "cortexa15")
- (eq_attr "type" "neon_vaba"))
- "ca15_issue1,ca15_cx_ialu_with_acc")
-
-(define_insn_reservation "cortex_a15_neon_vaba_qqq" 8
- (and (eq_attr "tune" "cortexa15")
- (eq_attr "type" "neon_vaba_qqq"))
- "ca15_issue2,ca15_cx_ialu_with_acc*2")
+;; Integer Multiply Instructions.
-(define_insn_reservation
- "cortex_a15_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long" 6
+(define_insn_reservation "cortex_a15_neon_multiply" 6
(and (eq_attr "tune" "cortexa15")
- (eq_attr "type" "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long"))
+ (eq_attr "cortex_a15_neon_type" "neon_multiply"))
"ca15_issue1,ca15_cx_imac")
-(define_insn_reservation "cortex_a15_neon_mul_qqq_8_16_32_ddd_32" 7
+(define_insn_reservation "cortex_a15_neon_multiply_q" 7
(and (eq_attr "tune" "cortexa15")
- (eq_attr "type" "neon_mul_qqq_8_16_32_ddd_32"))
- "ca15_issue1,ca15_cx_imac*2")
+ (eq_attr "cortex_a15_neon_type" "neon_multiply_q"))
+ "ca15_issue2,ca15_cx_imac*2")
-(define_insn_reservation
- "cortex_a15_neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar" 7
+(define_insn_reservation "cortex_a15_neon_mla" 6
(and (eq_attr "tune" "cortexa15")
- (eq_attr "type"
- "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar"))
- "ca15_issue1,ca15_cx_imac*2")
-
-(define_insn_reservation
- "cortex_a15_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long" 6
- (and (eq_attr "tune" "cortexa15")
- (eq_attr "type"
- "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long"))
+ (eq_attr "cortex_a15_neon_type" "neon_mla"))
"ca15_issue1,ca15_cx_imac")
-(define_insn_reservation
- "cortex_a15_neon_mla_qqq_8_16" 7
+(define_insn_reservation "cortex_a15_neon_mla_q" 7
(and (eq_attr "tune" "cortexa15")
- (eq_attr "type"
- "neon_mla_qqq_8_16"))
+ (eq_attr "cortex_a15_neon_type" "neon_mla_q"))
"ca15_issue1,ca15_cx_imac*2")
-(define_insn_reservation
- "cortex_a15_neon_mla_ddd_32_qqd_16_ddd_32_scalar_\
- qdd_64_32_lotype_qdd_64_32_long" 7
+(define_insn_reservation "cortex_a15_neon_sat_mla_long" 6
(and (eq_attr "tune" "cortexa15")
- (eq_attr "type" "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long"))
+ (eq_attr "cortex_a15_neon_type" "neon_sat_mla_long"))
"ca15_issue1,ca15_cx_imac")
-(define_insn_reservation
- "cortex_a15_neon_mla_qqq_32_qqd_32_scalar" 7
- (and (eq_attr "tune" "cortexa15")
- (eq_attr "type" "neon_mla_qqq_32_qqd_32_scalar"))
- "ca15_issue1,ca15_cx_imac*2")
+;; Integer Shift Instructions.
(define_insn_reservation
- "cortex_a15_neon_mul_ddd_16_scalar_32_16_long_scalar" 6
+ "cortex_a15_neon_shift_acc" 7
(and (eq_attr "tune" "cortexa15")
- (eq_attr "type" "neon_mul_ddd_16_scalar_32_16_long_scalar"))
- "ca15_issue1,ca15_cx_imac")
-
-(define_insn_reservation
- "cortex_a15_neon_mul_qqd_32_scalar" 7
- (and (eq_attr "tune" "cortexa15")
- (eq_attr "type" "neon_mul_qqd_32_scalar"))
- "ca15_issue1,ca15_cx_imac*2")
+ (eq_attr "cortex_a15_neon_type" "neon_shift_acc"))
+ "ca15_issue1,ca15_cx_ishf_with_acc")
(define_insn_reservation
- "cortex_a15_neon_mla_ddd_16_scalar_qdd_32_16_long_scalar" 6
+ "cortex_a15_neon_shift_imm_basic" 4
(and (eq_attr "tune" "cortexa15")
- (eq_attr "type" "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar"))
- "ca15_issue1,ca15_cx_imac")
+ (eq_attr "cortex_a15_neon_type" "neon_shift_imm_basic"))
+ "ca15_issue1,ca15_cx_ik+ca15_cx_ishf")
(define_insn_reservation
- "cortex_a15_neon_shift_1" 5
+ "cortex_a15_neon_shift_imm_complex" 5
(and (eq_attr "tune" "cortexa15")
- (eq_attr "type" "neon_shift_1"))
+ (eq_attr "cortex_a15_neon_type" "neon_shift_imm_complex"))
"ca15_issue1,ca15_cx_ik+ca15_cx_ishf")
(define_insn_reservation
- "cortex_a15_neon_shift_2" 5
+ "cortex_a15_neon_shift_reg_basic" 4
(and (eq_attr "tune" "cortexa15")
- (eq_attr "type" "neon_shift_2"))
+ (eq_attr "cortex_a15_neon_type" "neon_shift_reg_basic"))
"ca15_issue1,ca15_cx_ik+ca15_cx_ishf")
(define_insn_reservation
- "cortex_a15_neon_shift_3" 6
+ "cortex_a15_neon_shift_reg_basic_q" 5
(and (eq_attr "tune" "cortexa15")
- (eq_attr "type" "neon_shift_3"))
- "ca15_issue2,(ca15_cx_ik+ca15_cx_ishf)*2")
+ (eq_attr "cortex_a15_neon_type" "neon_shift_reg_basic_q"))
+ "ca15_issue2,(ca15_cx_ik+ca15_cx_ishf*2)")
(define_insn_reservation
- "cortex_a15_neon_vshl_ddd" 5
+ "cortex_a15_neon_shift_reg_complex" 5
(and (eq_attr "tune" "cortexa15")
- (eq_attr "type" "neon_vshl_ddd"))
- "ca15_issue1,ca15_cx_ik+ca15_cx_ishf")
+ (eq_attr "cortex_a15_neon_type" "neon_shift_reg_complex"))
+ "ca15_issue2,ca15_cx_ik+ca15_cx_ishf")
(define_insn_reservation
- "cortex_a15_neon_vqshl_vrshl_vqrshl_qqq" 6
+ "cortex_a15_neon_shift_reg_complex_q" 6
(and (eq_attr "tune" "cortexa15")
- (eq_attr "type" "neon_vqshl_vrshl_vqrshl_qqq"))
+ (eq_attr "cortex_a15_neon_type" "neon_shift_reg_complex_q"))
"ca15_issue2,(ca15_cx_ik+ca15_cx_ishf)*2")
+;; Floating Point Instructions.
+
(define_insn_reservation
- "cortex_a15_neon_vsra_vrsra" 7
+ "cortex_a15_neon_fp_negabs" 4
(and (eq_attr "tune" "cortexa15")
- (eq_attr "type" "neon_vsra_vrsra"))
- "ca15_issue1,ca15_cx_ishf_with_acc")
+ (eq_attr "cortex_a15_neon_type" "neon_fp_negabs"))
+ "ca15_issue1,ca15_cx_falu")
(define_insn_reservation
- "cortex_a15_neon_fp_vadd_ddd_vabs_dd" 6
+ "cortex_a15_neon_fp_arith" 6
(and (eq_attr "tune" "cortexa15")
- (eq_attr "type" "neon_fp_vadd_ddd_vabs_dd"))
+ (eq_attr "cortex_a15_neon_type" "neon_fp_arith"))
"ca15_issue1,ca15_cx_falu")
(define_insn_reservation
- "cortex_a15_neon_fp_vadd_qqq_vabs_qq" 7
+ "cortex_a15_neon_fp_arith_q" 6
(and (eq_attr "tune" "cortexa15")
- (eq_attr "type" "neon_fp_vadd_qqq_vabs_qq"))
+ (eq_attr "cortex_a15_neon_type" "neon_fp_arith_q"))
"ca15_issue2,ca15_cx_falu_2")
(define_insn_reservation
- "cortex_a15_neon_fp_vmul_ddd" 5
+ "cortex_a15_neon_fp_cvt_int" 6
(and (eq_attr "tune" "cortexa15")
- (eq_attr "type" "neon_fp_vmul_ddd"))
- "ca15_issue1,ca15_cx_fmul")
+ (eq_attr "cortex_a15_neon_type" "neon_fp_cvt_int"))
+ "ca15_issue1,ca15_cx_falu+ca15_cx_ishf")
(define_insn_reservation
- "cortex_a15_neon_fp_vmul_qqd" 6
+ "cortex_a15_neon_fp_cvt_int_q" 6
(and (eq_attr "tune" "cortexa15")
- (eq_attr "type" "neon_fp_vmul_qqd"))
- "ca15_issue2,ca15_cx_fmul_2")
+ (eq_attr "cortex_a15_neon_type" "neon_fp_cvt_int_q"))
+ "ca15_issue2,(ca15_cx_falu+ca15_cx_ishf)*2")
(define_insn_reservation
- "cortex_a15_neon_fp_vmla_ddd" 9
+ "cortex_a15_neon_fp_cvt16" 10
(and (eq_attr "tune" "cortexa15")
- (eq_attr "type" "neon_fp_vmla_ddd"))
- "ca15_issue1,ca15_cx_fmac")
+ (eq_attr "cortex_a15_neon_type" "neon_fp_cvt16"))
+ "ca15_issue3,(ca15_cx_falu+ca15_cx_ishf)*2+ca15_cx_falu")
(define_insn_reservation
- "cortex_a15_neon_fp_vmla_qqq" 11
+ "cortex_a15_neon_fp_mul" 5
(and (eq_attr "tune" "cortexa15")
- (eq_attr "type" "neon_fp_vmla_qqq"))
- "ca15_issue2,ca15_cx_fmac_2")
+ (eq_attr "cortex_a15_neon_type" "neon_fp_mul"))
+ "ca15_issue1,ca15_cx_fmul")
(define_insn_reservation
- "cortex_a15_neon_fp_vmla_ddd_scalar" 9
+ "cortex_a15_neon_fp_mul_q" 5
(and (eq_attr "tune" "cortexa15")
- (eq_attr "type" "neon_fp_vmla_ddd_scalar"))
- "ca15_issue1,ca15_cx_fmac")
+ (eq_attr "cortex_a15_neon_type" "neon_fp_mul_q"))
+ "ca15_issue2,ca15_cx_fmul_2")
(define_insn_reservation
- "cortex_a15_neon_fp_vmla_qqq_scalar" 11
+ "cortex_a15_neon_fp_mla" 9
(and (eq_attr "tune" "cortexa15")
- (eq_attr "type" "neon_fp_vmla_qqq_scalar"))
- "ca15_issue2,ca15_cx_fmac_2")
+ (eq_attr "cortex_a15_neon_type" "neon_fp_mla"))
+ "ca15_issue1,ca15_cx_fmul")
(define_insn_reservation
- "cortex_a15_neon_fp_vrecps_vrsqrts_ddd" 9
+ "cortex_a15_neon_fp_mla_q" 9
(and (eq_attr "tune" "cortexa15")
- (eq_attr "type" "neon_fp_vrecps_vrsqrts_ddd"))
- "ca15_issue1,ca15_cx_fmac")
+ (eq_attr "cortex_a15_neon_type" "neon_fp_mla_q"))
+ "ca15_issue2,ca15_cx_fmul_2")
(define_insn_reservation
- "cortex_a15_neon_fp_vrecps_vrsqrts_qqq" 11
+ "cortex_a15_neon_fp_recps_rsqrte" 9
(and (eq_attr "tune" "cortexa15")
- (eq_attr "type" "neon_fp_vrecps_vrsqrts_qqq"))
- "ca15_issue2,ca15_cx_fmac_2")
+ (eq_attr "cortex_a15_neon_type" "neon_fp_recpe_rsqrte"))
+ "ca15_issue1,ca15_cx_fmac")
(define_insn_reservation
- "cortex_a15_neon_bp_simple" 4
+ "cortex_a15_neon_fp_recps_rsqrte_q" 9
(and (eq_attr "tune" "cortexa15")
- (eq_attr "type" "neon_bp_simple"))
- "ca15_issue3,ca15_ls+ca15_cx_perm_2,ca15_cx_perm")
+ (eq_attr "cortex_a15_neon_type" "neon_fp_recpe_rsqrte_q"))
+ "ca15_issue2,ca15_cx_fmac_2")
+
+;; Miscelaaneous Instructions.
(define_insn_reservation
- "cortex_a15_neon_bp_2cycle" 4
+ "cortex_a15_neon_bitops" 4
(and (eq_attr "tune" "cortexa15")
- (eq_attr "type" "neon_bp_2cycle"))
+ (eq_attr "cortex_a15_neon_type" "neon_bitops"))
"ca15_issue1,ca15_cx_perm")
(define_insn_reservation
- "cortex_a15_neon_bp_3cycle" 7
+ "cortex_a15_neon_bitops_q" 4
(and (eq_attr "tune" "cortexa15")
- (eq_attr "type" "neon_bp_3cycle"))
- "ca15_issue3,ca15_cx_ialu+ca15_cx_perm_2,ca15_cx_perm")
+ (eq_attr "cortex_a15_neon_type" "neon_bitops_q"))
+ "ca15_issue2,ca15_cx_perm_2")
(define_insn_reservation
- "cortex_a15_neon_vld1_1_2_regs" 7
+ "cortex_a15_neon_from_gp" 9
(and (eq_attr "tune" "cortexa15")
- (eq_attr "type" "neon_vld1_1_2_regs"))
- "ca15_issue2,ca15_ls,ca15_ldr")
+ (eq_attr "cortex_a15_neon_type" "neon_from_gp"))
+ "ca15_issue2,ca15_ls1+ca15_ls2+ca15_cx_perm")
(define_insn_reservation
- "cortex_a15_neon_vld1_3_4_regs" 8
+ "cortex_a15_neon_from_gp_q" 9
(and (eq_attr "tune" "cortexa15")
- (eq_attr "type" "neon_vld1_3_4_regs"))
- "ca15_issue3,ca15_ls1+ca15_ls2,ca15_ldr,ca15_ldr")
+ (eq_attr "cortex_a15_neon_type" "neon_from_gp_q"))
+ "ca15_issue2,ca15_ls1+ca15_ls2+ca15_cx_perm_2")
(define_insn_reservation
- "cortex_a15_neon_vld2_2_regs_vld1_vld2_all_lanes" 9
+ "cortex_a15_neon_tbl3_tbl4" 7
(and (eq_attr "tune" "cortexa15")
- (eq_attr "type" "neon_vld2_2_regs_vld1_vld2_all_lanes"))
- "ca15_issue3,ca15_ls,ca15_ldr")
+ (eq_attr "cortex_a15_neon_type" "neon_tbl3_tbl4"))
+ "ca15_issue2,ca15_cx_perm_2")
(define_insn_reservation
- "cortex_a15_neon_vld2_4_regs" 12
+ "cortex_a15_neon_zip_q" 7
(and (eq_attr "tune" "cortexa15")
- (eq_attr "type" "neon_vld2_4_regs"))
- "ca15_issue3,ca15_issue3+ca15_ls1+ca15_ls2,ca15_ldr*2")
+ (eq_attr "cortex_a15_neon_type" "neon_zip_q"))
+ "ca15_issue3,ca15_cx_perm*3")
(define_insn_reservation
- "cortex_a15_neon_vld3_vld4" 12
+ "cortex_a15_neon_to_gp" 7
(and (eq_attr "tune" "cortexa15")
- (eq_attr "type" "neon_vld3_vld4"))
- "ca15_issue3,ca15_issue3+ca15_ls1+ca15_ls2,ca15_ldr*2")
+ (eq_attr "cortex_a15_neon_type" "neon_to_gp"))
+ "ca15_issue2,ca15_ls1+ca15_ls2")
-(define_insn_reservation
- "cortex_a15_neon_vst1_1_2_regs_vst2_2_regs" 0
- (and (eq_attr "tune" "cortexa15")
- (eq_attr "type" "neon_vst1_1_2_regs_vst2_2_regs"))
- "ca15_issue3,ca15_issue3+ca15_cx_perm+ca15_ls1+ca15_ls2,ca15_str*2")
+;; Load Instructions.
(define_insn_reservation
- "cortex_a15_neon_vst1_3_4_regs" 0
+ "cortex_a15_neon_load_a" 6
(and (eq_attr "tune" "cortexa15")
- (eq_attr "type" "neon_vst1_3_4_regs"))
- "ca15_issue3,ca15_issue3+ca15_ls1+ca15_ls2,ca15_str*3")
+ (eq_attr "cortex_a15_neon_type" "neon_load_a"))
+ "ca15_issue1,ca15_ls,ca15_ldr")
(define_insn_reservation
- "cortex_a15_neon_vst2_4_regs_vst3_vst4" 0
+ "cortex_a15_neon_load_b" 7
(and (eq_attr "tune" "cortexa15")
- (eq_attr "type" "neon_vst2_4_regs_vst3_vst4"))
- "ca15_issue3,ca15_issue3+ca15_cx_perm_2+ca15_ls1+ca15_ls2,\
- ca15_issue3+ca15_str,ca15_str*3")
+ (eq_attr "cortex_a15_neon_type" "neon_load_b"))
+ "ca15_issue2,ca15_ls1+ca15_ls2,ca15_ldr,ca15_ldr")
(define_insn_reservation
- "cortex_a15_neon_vst3_vst4" 0
+ "cortex_a15_neon_load_c" 9
(and (eq_attr "tune" "cortexa15")
- (eq_attr "type" "neon_vst3_vst4"))
- "ca15_issue3,ca15_issue3+ca15_cx_perm_2+ca15_ls1+ca15_ls2,ca15_str*4")
+ (eq_attr "cortex_a15_neon_type" "neon_load_c"))
+ "ca15_issue2,ca15_ls1+ca15_ls2,ca15_ldr,ca15_ldr")
(define_insn_reservation
- "cortex_a15_neon_vld1_vld2_lane" 9
+ "cortex_a15_neon_load_d" 11
(and (eq_attr "tune" "cortexa15")
- (eq_attr "type" "neon_vld1_vld2_lane"))
- "ca15_issue3,ca15_ls,ca15_ldr")
+ (eq_attr "cortex_a15_neon_type" "neon_load_d"))
+ "ca15_issue1,ca15_issue3+ca15_ls1+ca15_ls2,ca15_ldr*2")
(define_insn_reservation
- "cortex_a15_neon_vld3_vld4_lane" 10
+ "cortex_a15_neon_load_e" 9
(and (eq_attr "tune" "cortexa15")
- (eq_attr "type" "neon_vld3_vld4_lane"))
- "ca15_issue3,ca15_issue3+ca15_ls,ca15_issue3+ca15_ldr")
+ (eq_attr "cortex_a15_neon_type" "neon_load_e"))
+ "ca15_issue3+ca15_ls1+ca15_ls2,ca15_ldr*2")
(define_insn_reservation
- "cortex_a15_neon_vst1_vst2_lane" 0
+ "cortex_a15_neon_load_f" 11
(and (eq_attr "tune" "cortexa15")
- (eq_attr "type" "neon_vst1_vst2_lane"))
- "ca15_issue3,ca15_cx_perm+ca15_ls,ca15_str")
+ (eq_attr "cortex_a15_neon_type" "neon_load_f"))
+ "ca15_issue3,ca15_issue3+ca15_ls1+ca15_ls2,ca15_ldr*2")
+
+;; Store Instructions.
(define_insn_reservation
- "cortex_a15_neon_vst3_vst4_lane" 0
+ "cortex_a15_neon_store_a" 0
(and (eq_attr "tune" "cortexa15")
- (eq_attr "type" "neon_vst3_vst4_lane"))
- "ca15_issue3,ca15_issue3+ca15_cx_perm+ca15_ls1+ca15_ls2,ca15_str*2")
+ (eq_attr "cortex_a15_neon_type" "neon_store_a"))
+ "ca15_issue1,ca15_ls1+ca15_ls2,ca15_str")
(define_insn_reservation
- "cortex_a15_neon_vld3_vld4_all_lanes" 11
+ "cortex_a15_neon_store_b" 0
(and (eq_attr "tune" "cortexa15")
- (eq_attr "type" "neon_vld3_vld4_all_lanes"))
- "ca15_issue3,ca15_issue3+ca15_ls,ca15_ldr")
+ (eq_attr "cortex_a15_neon_type" "neon_store_b"))
+ "ca15_issue2,ca15_ls1+ca15_ls2,ca15_str*2")
(define_insn_reservation
- "cortex_a15_neon_ldm_2" 20
+ "cortex_a15_neon_store_c" 0
(and (eq_attr "tune" "cortexa15")
- (eq_attr "type" "neon_ldm_2"))
- "ca15_issue3*6")
+ (eq_attr "cortex_a15_neon_type" "neon_store_c"))
+ "ca15_issue3,ca15_ls1+ca15_ls2,ca15_str*3")
(define_insn_reservation
- "cortex_a15_neon_stm_2" 0
+ "cortex_a15_neon_store_d" 0
(and (eq_attr "tune" "cortexa15")
- (eq_attr "type" "neon_stm_2"))
- "ca15_issue3*6")
+ (eq_attr "cortex_a15_neon_type" "neon_store_d"))
+ "ca15_issue3,ca15_issue1,ca15_ls1+ca15_ls2,ca15_str*4")
(define_insn_reservation
- "cortex_a15_neon_mcr" 6
+ "cortex_a15_neon_store_e" 0
(and (eq_attr "tune" "cortexa15")
- (eq_attr "type" "neon_mcr"))
- "ca15_issue2,ca15_ls,ca15_cx_perm")
+ (eq_attr "cortex_a15_neon_type" "neon_store_e"))
+ "ca15_issue2,ca15_ls1+ca15_ls2,ca15_str+ca15_cx_perm")
(define_insn_reservation
- "cortex_a15_neon_mcr_2_mcrr" 6
+ "cortex_a15_neon_store_f" 0
(and (eq_attr "tune" "cortexa15")
- (eq_attr "type" "neon_mcr_2_mcrr"))
- "ca15_issue2,ca15_ls1+ca15_ls2")
+ (eq_attr "cortex_a15_neon_type" "neon_store_f"))
+ "ca15_issue3,ca15_ls1+ca15_ls2,ca15_str*2+ca15_cx_perm")
(define_insn_reservation
- "cortex_a15_neon_mrc" 5
+ "cortex_a15_neon_store_g" 0
(and (eq_attr "tune" "cortexa15")
- (eq_attr "type" "neon_mrc"))
- "ca15_issue1,ca15_ls")
+ (eq_attr "cortex_a15_neon_type" "neon_store_g"))
+ "ca15_issue3,ca15_issue3+ca15_cx_perm+ca15_ls1+ca15_ls2,ca15_str*2")
(define_insn_reservation
- "cortex_a15_neon_mrrc" 6
+ "cortex_a15_neon_store_h" 0
(and (eq_attr "tune" "cortexa15")
- (eq_attr "type" "neon_mrrc"))
- "ca15_issue2,ca15_ls1+ca15_ls2")
+ (eq_attr "cortex_a15_neon_type" "neon_store_h"))
+ "ca15_issue3,ca15_issue2+ca15_cx_perm+ca15_ls1+ca15_ls2,ca15_str*2")
+
+;; VFP Operations.
(define_insn_reservation "cortex_a15_vfp_const" 4
(and (eq_attr "tune" "cortexa15")
@@ -494,6 +655,11 @@
(eq_attr "type" "fmov"))
"ca15_issue1,ca15_cx_perm")
+(define_insn_reservation "cortex_a15_vfp_to_from_gp" 5
+ (and (eq_attr "tune" "cortexa15")
+ (eq_attr "type" "f_mcr, f_mcrr, f_mrc, f_mrrc"))
+ "ca15_issue1,ca15_ls1+ca15_ls2")
+
(define_insn_reservation "cortex_a15_vfp_ariths" 7
(and (eq_attr "tune" "cortexa15")
(eq_attr "type" "ffariths"))
@@ -509,663 +675,3 @@
(eq_attr "type" "fdivd, fsqrtd"))
"ca15_issue1,ca15_cx_ik")
-;; Define bypasses.
-(define_bypass 5 "cortex_a15_neon_mcr_2_mcrr"
- "cortex_a15_neon_int_1,\
- cortex_a15_neon_int_4,\
- cortex_a15_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mul_qqq_8_16_32_ddd_32,\
- cortex_a15_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mla_qqq_8_16,\
- cortex_a15_neon_fp_vadd_ddd_vabs_dd,\
- cortex_a15_neon_fp_vadd_qqq_vabs_qq,\
- cortex_a15_neon_fp_vmla_ddd,\
- cortex_a15_neon_fp_vmla_qqq,\
- cortex_a15_neon_fp_vrecps_vrsqrts_ddd,\
- cortex_a15_neon_fp_vrecps_vrsqrts_qqq")
-
-(define_bypass 5 "cortex_a15_neon_mcr"
- "cortex_a15_neon_int_1,\
- cortex_a15_neon_int_4,\
- cortex_a15_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mul_qqq_8_16_32_ddd_32,\
- cortex_a15_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mla_qqq_8_16,\
- cortex_a15_neon_fp_vadd_ddd_vabs_dd,\
- cortex_a15_neon_fp_vadd_qqq_vabs_qq,\
- cortex_a15_neon_fp_vmla_ddd,\
- cortex_a15_neon_fp_vmla_qqq,\
- cortex_a15_neon_fp_vrecps_vrsqrts_ddd,\
- cortex_a15_neon_fp_vrecps_vrsqrts_qqq")
-
-(define_bypass 10 "cortex_a15_neon_vld3_vld4_all_lanes"
- "cortex_a15_neon_int_1,\
- cortex_a15_neon_int_4,\
- cortex_a15_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mul_qqq_8_16_32_ddd_32,\
- cortex_a15_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mla_qqq_8_16,\
- cortex_a15_neon_fp_vadd_ddd_vabs_dd,\
- cortex_a15_neon_fp_vadd_qqq_vabs_qq,\
- cortex_a15_neon_fp_vmla_ddd,\
- cortex_a15_neon_fp_vmla_qqq,\
- cortex_a15_neon_fp_vrecps_vrsqrts_ddd,\
- cortex_a15_neon_fp_vrecps_vrsqrts_qqq")
-
-(define_bypass 9 "cortex_a15_neon_vld3_vld4_lane"
- "cortex_a15_neon_int_1,\
- cortex_a15_neon_int_4,\
- cortex_a15_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mul_qqq_8_16_32_ddd_32,\
- cortex_a15_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mla_qqq_8_16,\
- cortex_a15_neon_fp_vadd_ddd_vabs_dd,\
- cortex_a15_neon_fp_vadd_qqq_vabs_qq,\
- cortex_a15_neon_fp_vmla_ddd,\
- cortex_a15_neon_fp_vmla_qqq,\
- cortex_a15_neon_fp_vrecps_vrsqrts_ddd,\
- cortex_a15_neon_fp_vrecps_vrsqrts_qqq")
-
-(define_bypass 8 "cortex_a15_neon_vld1_vld2_lane"
- "cortex_a15_neon_int_1,\
- cortex_a15_neon_int_4,\
- cortex_a15_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mul_qqq_8_16_32_ddd_32,\
- cortex_a15_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mla_qqq_8_16,\
- cortex_a15_neon_fp_vadd_ddd_vabs_dd,\
- cortex_a15_neon_fp_vadd_qqq_vabs_qq,\
- cortex_a15_neon_fp_vmla_ddd,\
- cortex_a15_neon_fp_vmla_qqq,\
- cortex_a15_neon_fp_vrecps_vrsqrts_ddd,\
- cortex_a15_neon_fp_vrecps_vrsqrts_qqq")
-
-(define_bypass 11 "cortex_a15_neon_vld3_vld4"
- "cortex_a15_neon_int_1,\
- cortex_a15_neon_int_4,\
- cortex_a15_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mul_qqq_8_16_32_ddd_32,\
- cortex_a15_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mla_qqq_8_16,\
- cortex_a15_neon_fp_vadd_ddd_vabs_dd,\
- cortex_a15_neon_fp_vadd_qqq_vabs_qq,\
- cortex_a15_neon_fp_vmla_ddd,\
- cortex_a15_neon_fp_vmla_qqq,\
- cortex_a15_neon_fp_vrecps_vrsqrts_ddd,\
- cortex_a15_neon_fp_vrecps_vrsqrts_qqq")
-
-(define_bypass 11 "cortex_a15_neon_vld2_4_regs"
- "cortex_a15_neon_int_1,\
- cortex_a15_neon_int_4,\
- cortex_a15_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mul_qqq_8_16_32_ddd_32,\
- cortex_a15_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mla_qqq_8_16,\
- cortex_a15_neon_fp_vadd_ddd_vabs_dd,\
- cortex_a15_neon_fp_vadd_qqq_vabs_qq,\
- cortex_a15_neon_fp_vmla_ddd,\
- cortex_a15_neon_fp_vmla_qqq,\
- cortex_a15_neon_fp_vrecps_vrsqrts_ddd,\
- cortex_a15_neon_fp_vrecps_vrsqrts_qqq")
-
-(define_bypass 8 "cortex_a15_neon_vld2_2_regs_vld1_vld2_all_lanes"
- "cortex_a15_neon_int_1,\
- cortex_a15_neon_int_4,\
- cortex_a15_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mul_qqq_8_16_32_ddd_32,\
- cortex_a15_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mla_qqq_8_16,\
- cortex_a15_neon_fp_vadd_ddd_vabs_dd,\
- cortex_a15_neon_fp_vadd_qqq_vabs_qq,\
- cortex_a15_neon_fp_vmla_ddd,\
- cortex_a15_neon_fp_vmla_qqq,\
- cortex_a15_neon_fp_vrecps_vrsqrts_ddd,\
- cortex_a15_neon_fp_vrecps_vrsqrts_qqq")
-
-(define_bypass 7 "cortex_a15_neon_vld1_3_4_regs"
- "cortex_a15_neon_int_1,\
- cortex_a15_neon_int_4,\
- cortex_a15_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mul_qqq_8_16_32_ddd_32,\
- cortex_a15_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mla_qqq_8_16,\
- cortex_a15_neon_fp_vadd_ddd_vabs_dd,\
- cortex_a15_neon_fp_vadd_qqq_vabs_qq,\
- cortex_a15_neon_fp_vmla_ddd,\
- cortex_a15_neon_fp_vmla_qqq,\
- cortex_a15_neon_fp_vrecps_vrsqrts_ddd,\
- cortex_a15_neon_fp_vrecps_vrsqrts_qqq")
-
-(define_bypass 6 "cortex_a15_neon_vld1_1_2_regs"
- "cortex_a15_neon_int_1,\
- cortex_a15_neon_int_4,\
- cortex_a15_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mul_qqq_8_16_32_ddd_32,\
- cortex_a15_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mla_qqq_8_16,\
- cortex_a15_neon_fp_vadd_ddd_vabs_dd,\
- cortex_a15_neon_fp_vadd_qqq_vabs_qq,\
- cortex_a15_neon_fp_vmla_ddd,\
- cortex_a15_neon_fp_vmla_qqq,\
- cortex_a15_neon_fp_vrecps_vrsqrts_ddd,\
- cortex_a15_neon_fp_vrecps_vrsqrts_qqq")
-
-(define_bypass 6 "cortex_a15_neon_bp_3cycle"
- "cortex_a15_neon_int_1,\
- cortex_a15_neon_int_4,\
- cortex_a15_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mul_qqq_8_16_32_ddd_32,\
- cortex_a15_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mla_qqq_8_16,\
- cortex_a15_neon_fp_vadd_ddd_vabs_dd,\
- cortex_a15_neon_fp_vadd_qqq_vabs_qq,\
- cortex_a15_neon_fp_vmla_ddd,\
- cortex_a15_neon_fp_vmla_qqq,\
- cortex_a15_neon_fp_vrecps_vrsqrts_ddd,\
- cortex_a15_neon_fp_vrecps_vrsqrts_qqq")
-
-(define_bypass 3 "cortex_a15_neon_bp_2cycle"
- "cortex_a15_neon_int_1,\
- cortex_a15_neon_int_4,\
- cortex_a15_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mul_qqq_8_16_32_ddd_32,\
- cortex_a15_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mla_qqq_8_16,\
- cortex_a15_neon_fp_vadd_ddd_vabs_dd,\
- cortex_a15_neon_fp_vadd_qqq_vabs_qq,\
- cortex_a15_neon_fp_vmla_ddd,\
- cortex_a15_neon_fp_vmla_qqq,\
- cortex_a15_neon_fp_vrecps_vrsqrts_ddd,\
- cortex_a15_neon_fp_vrecps_vrsqrts_qqq")
-
-(define_bypass 3 "cortex_a15_neon_bp_simple"
- "cortex_a15_neon_int_1,\
- cortex_a15_neon_int_4,\
- cortex_a15_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mul_qqq_8_16_32_ddd_32,\
- cortex_a15_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mla_qqq_8_16,\
- cortex_a15_neon_fp_vadd_ddd_vabs_dd,\
- cortex_a15_neon_fp_vadd_qqq_vabs_qq,\
- cortex_a15_neon_fp_vmla_ddd,\
- cortex_a15_neon_fp_vmla_qqq,\
- cortex_a15_neon_fp_vrecps_vrsqrts_ddd,\
- cortex_a15_neon_fp_vrecps_vrsqrts_qqq")
-
-(define_bypass 10 "cortex_a15_neon_fp_vrecps_vrsqrts_qqq"
- "cortex_a15_neon_int_1,\
- cortex_a15_neon_int_4,\
- cortex_a15_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mul_qqq_8_16_32_ddd_32,\
- cortex_a15_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mla_qqq_8_16,\
- cortex_a15_neon_fp_vadd_ddd_vabs_dd,\
- cortex_a15_neon_fp_vadd_qqq_vabs_qq,\
- cortex_a15_neon_fp_vmla_ddd,\
- cortex_a15_neon_fp_vmla_qqq,\
- cortex_a15_neon_fp_vrecps_vrsqrts_ddd,\
- cortex_a15_neon_fp_vrecps_vrsqrts_qqq")
-
-(define_bypass 8 "cortex_a15_neon_fp_vrecps_vrsqrts_ddd"
- "cortex_a15_neon_int_1,\
- cortex_a15_neon_int_4,\
- cortex_a15_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mul_qqq_8_16_32_ddd_32,\
- cortex_a15_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mla_qqq_8_16,\
- cortex_a15_neon_fp_vadd_ddd_vabs_dd,\
- cortex_a15_neon_fp_vadd_qqq_vabs_qq,\
- cortex_a15_neon_fp_vmla_ddd,\
- cortex_a15_neon_fp_vmla_qqq,\
- cortex_a15_neon_fp_vrecps_vrsqrts_ddd,\
- cortex_a15_neon_fp_vrecps_vrsqrts_qqq")
-
-(define_bypass 10 "cortex_a15_neon_fp_vmla_qqq_scalar"
- "cortex_a15_neon_int_1,\
- cortex_a15_neon_int_4,\
- cortex_a15_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mul_qqq_8_16_32_ddd_32,\
- cortex_a15_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mla_qqq_8_16,\
- cortex_a15_neon_fp_vadd_ddd_vabs_dd,\
- cortex_a15_neon_fp_vadd_qqq_vabs_qq,\
- cortex_a15_neon_fp_vmla_ddd,\
- cortex_a15_neon_fp_vmla_qqq,\
- cortex_a15_neon_fp_vrecps_vrsqrts_ddd,\
- cortex_a15_neon_fp_vrecps_vrsqrts_qqq")
-
-(define_bypass 8 "cortex_a15_neon_fp_vmla_ddd_scalar"
- "cortex_a15_neon_int_1,\
- cortex_a15_neon_int_4,\
- cortex_a15_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mul_qqq_8_16_32_ddd_32,\
- cortex_a15_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mla_qqq_8_16,\
- cortex_a15_neon_fp_vadd_ddd_vabs_dd,\
- cortex_a15_neon_fp_vadd_qqq_vabs_qq,\
- cortex_a15_neon_fp_vmla_ddd,\
- cortex_a15_neon_fp_vmla_qqq,\
- cortex_a15_neon_fp_vrecps_vrsqrts_ddd,\
- cortex_a15_neon_fp_vrecps_vrsqrts_qqq")
-
-(define_bypass 10 "cortex_a15_neon_fp_vmla_qqq"
- "cortex_a15_neon_int_1,\
- cortex_a15_neon_int_4,\
- cortex_a15_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mul_qqq_8_16_32_ddd_32,\
- cortex_a15_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mla_qqq_8_16,\
- cortex_a15_neon_fp_vadd_ddd_vabs_dd,\
- cortex_a15_neon_fp_vadd_qqq_vabs_qq,\
- cortex_a15_neon_fp_vmla_ddd,\
- cortex_a15_neon_fp_vmla_qqq,\
- cortex_a15_neon_fp_vrecps_vrsqrts_ddd,\
- cortex_a15_neon_fp_vrecps_vrsqrts_qqq")
-
-(define_bypass 8 "cortex_a15_neon_fp_vmla_ddd"
- "cortex_a15_neon_int_1,\
- cortex_a15_neon_int_4,\
- cortex_a15_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mul_qqq_8_16_32_ddd_32,\
- cortex_a15_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mla_qqq_8_16,\
- cortex_a15_neon_fp_vadd_ddd_vabs_dd,\
- cortex_a15_neon_fp_vadd_qqq_vabs_qq,\
- cortex_a15_neon_fp_vmla_ddd,\
- cortex_a15_neon_fp_vmla_qqq,\
- cortex_a15_neon_fp_vrecps_vrsqrts_ddd,\
- cortex_a15_neon_fp_vrecps_vrsqrts_qqq")
-
-(define_bypass 5 "cortex_a15_neon_fp_vmul_qqd"
- "cortex_a15_neon_int_1,\
- cortex_a15_neon_int_4,\
- cortex_a15_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mul_qqq_8_16_32_ddd_32,\
- cortex_a15_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mla_qqq_8_16,\
- cortex_a15_neon_fp_vadd_ddd_vabs_dd,\
- cortex_a15_neon_fp_vadd_qqq_vabs_qq,\
- cortex_a15_neon_fp_vmla_ddd,\
- cortex_a15_neon_fp_vmla_qqq,\
- cortex_a15_neon_fp_vrecps_vrsqrts_ddd,\
- cortex_a15_neon_fp_vrecps_vrsqrts_qqq")
-
-(define_bypass 4 "cortex_a15_neon_fp_vmul_ddd"
- "cortex_a15_neon_int_1,\
- cortex_a15_neon_int_4,\
- cortex_a15_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mul_qqq_8_16_32_ddd_32,\
- cortex_a15_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mla_qqq_8_16,\
- cortex_a15_neon_fp_vadd_ddd_vabs_dd,\
- cortex_a15_neon_fp_vadd_qqq_vabs_qq,\
- cortex_a15_neon_fp_vmla_ddd,\
- cortex_a15_neon_fp_vmla_qqq,\
- cortex_a15_neon_fp_vrecps_vrsqrts_ddd,\
- cortex_a15_neon_fp_vrecps_vrsqrts_qqq")
-
-(define_bypass 6 "cortex_a15_neon_fp_vadd_qqq_vabs_qq"
- "cortex_a15_neon_int_1,\
- cortex_a15_neon_int_4,\
- cortex_a15_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mul_qqq_8_16_32_ddd_32,\
- cortex_a15_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mla_qqq_8_16,\
- cortex_a15_neon_fp_vadd_ddd_vabs_dd,\
- cortex_a15_neon_fp_vadd_qqq_vabs_qq,\
- cortex_a15_neon_fp_vmla_ddd,\
- cortex_a15_neon_fp_vmla_qqq,\
- cortex_a15_neon_fp_vrecps_vrsqrts_ddd,\
- cortex_a15_neon_fp_vrecps_vrsqrts_qqq")
-
-(define_bypass 5 "cortex_a15_neon_fp_vadd_ddd_vabs_dd"
- "cortex_a15_neon_int_1,\
- cortex_a15_neon_int_4,\
- cortex_a15_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mul_qqq_8_16_32_ddd_32,\
- cortex_a15_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mla_qqq_8_16,\
- cortex_a15_neon_fp_vadd_ddd_vabs_dd,\
- cortex_a15_neon_fp_vadd_qqq_vabs_qq,\
- cortex_a15_neon_fp_vmla_ddd,\
- cortex_a15_neon_fp_vmla_qqq,\
- cortex_a15_neon_fp_vrecps_vrsqrts_ddd,\
- cortex_a15_neon_fp_vrecps_vrsqrts_qqq")
-
-(define_bypass 6 "cortex_a15_neon_vsra_vrsra"
- "cortex_a15_neon_int_1,\
- cortex_a15_neon_int_4,\
- cortex_a15_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mul_qqq_8_16_32_ddd_32,\
- cortex_a15_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mla_qqq_8_16,\
- cortex_a15_neon_fp_vadd_ddd_vabs_dd,\
- cortex_a15_neon_fp_vadd_qqq_vabs_qq,\
- cortex_a15_neon_fp_vmla_ddd,\
- cortex_a15_neon_fp_vmla_qqq,\
- cortex_a15_neon_fp_vrecps_vrsqrts_ddd,\
- cortex_a15_neon_fp_vrecps_vrsqrts_qqq")
-
-(define_bypass 5 "cortex_a15_neon_vqshl_vrshl_vqrshl_qqq"
- "cortex_a15_neon_int_1,\
- cortex_a15_neon_int_4,\
- cortex_a15_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mul_qqq_8_16_32_ddd_32,\
- cortex_a15_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mla_qqq_8_16,\
- cortex_a15_neon_fp_vadd_ddd_vabs_dd,\
- cortex_a15_neon_fp_vadd_qqq_vabs_qq,\
- cortex_a15_neon_fp_vmla_ddd,\
- cortex_a15_neon_fp_vmla_qqq,\
- cortex_a15_neon_fp_vrecps_vrsqrts_ddd,\
- cortex_a15_neon_fp_vrecps_vrsqrts_qqq")
-
-(define_bypass 4 "cortex_a15_neon_vshl_ddd"
- "cortex_a15_neon_int_1,\
- cortex_a15_neon_int_4,\
- cortex_a15_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mul_qqq_8_16_32_ddd_32,\
- cortex_a15_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mla_qqq_8_16,\
- cortex_a15_neon_fp_vadd_ddd_vabs_dd,\
- cortex_a15_neon_fp_vadd_qqq_vabs_qq,\
- cortex_a15_neon_fp_vmla_ddd,\
- cortex_a15_neon_fp_vmla_qqq,\
- cortex_a15_neon_fp_vrecps_vrsqrts_ddd,\
- cortex_a15_neon_fp_vrecps_vrsqrts_qqq")
-
-(define_bypass 5 "cortex_a15_neon_shift_3"
- "cortex_a15_neon_int_1,\
- cortex_a15_neon_int_4,\
- cortex_a15_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mul_qqq_8_16_32_ddd_32,\
- cortex_a15_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mla_qqq_8_16,\
- cortex_a15_neon_fp_vadd_ddd_vabs_dd,\
- cortex_a15_neon_fp_vadd_qqq_vabs_qq,\
- cortex_a15_neon_fp_vmla_ddd,\
- cortex_a15_neon_fp_vmla_qqq,\
- cortex_a15_neon_fp_vrecps_vrsqrts_ddd,\
- cortex_a15_neon_fp_vrecps_vrsqrts_qqq")
-
-(define_bypass 4 "cortex_a15_neon_shift_2"
- "cortex_a15_neon_int_1,\
- cortex_a15_neon_int_4,\
- cortex_a15_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mul_qqq_8_16_32_ddd_32,\
- cortex_a15_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mla_qqq_8_16,\
- cortex_a15_neon_fp_vadd_ddd_vabs_dd,\
- cortex_a15_neon_fp_vadd_qqq_vabs_qq,\
- cortex_a15_neon_fp_vmla_ddd,\
- cortex_a15_neon_fp_vmla_qqq,\
- cortex_a15_neon_fp_vrecps_vrsqrts_ddd,\
- cortex_a15_neon_fp_vrecps_vrsqrts_qqq")
-
-(define_bypass 4 "cortex_a15_neon_shift_1"
- "cortex_a15_neon_int_1,\
- cortex_a15_neon_int_4,\
- cortex_a15_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mul_qqq_8_16_32_ddd_32,\
- cortex_a15_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mla_qqq_8_16,\
- cortex_a15_neon_fp_vadd_ddd_vabs_dd,\
- cortex_a15_neon_fp_vadd_qqq_vabs_qq,\
- cortex_a15_neon_fp_vmla_ddd,\
- cortex_a15_neon_fp_vmla_qqq,\
- cortex_a15_neon_fp_vrecps_vrsqrts_ddd,\
- cortex_a15_neon_fp_vrecps_vrsqrts_qqq")
-
-(define_bypass 5 "cortex_a15_neon_mla_ddd_16_scalar_qdd_32_16_long_scalar"
- "cortex_a15_neon_int_1,\
- cortex_a15_neon_int_4,\
- cortex_a15_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mul_qqq_8_16_32_ddd_32,\
- cortex_a15_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mla_qqq_8_16,\
- cortex_a15_neon_fp_vadd_ddd_vabs_dd,\
- cortex_a15_neon_fp_vadd_qqq_vabs_qq,\
- cortex_a15_neon_fp_vmla_ddd,\
- cortex_a15_neon_fp_vmla_qqq,\
- cortex_a15_neon_fp_vrecps_vrsqrts_ddd,\
- cortex_a15_neon_fp_vrecps_vrsqrts_qqq")
-
-(define_bypass 6 "cortex_a15_neon_mul_qqd_32_scalar"
- "cortex_a15_neon_int_1,\
- cortex_a15_neon_int_4,\
- cortex_a15_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mul_qqq_8_16_32_ddd_32,\
- cortex_a15_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mla_qqq_8_16,\
- cortex_a15_neon_fp_vadd_ddd_vabs_dd,\
- cortex_a15_neon_fp_vadd_qqq_vabs_qq,\
- cortex_a15_neon_fp_vmla_ddd,\
- cortex_a15_neon_fp_vmla_qqq,\
- cortex_a15_neon_fp_vrecps_vrsqrts_ddd,\
- cortex_a15_neon_fp_vrecps_vrsqrts_qqq")
-
-(define_bypass 5 "cortex_a15_neon_mul_ddd_16_scalar_32_16_long_scalar"
- "cortex_a15_neon_int_1,\
- cortex_a15_neon_int_4,\
- cortex_a15_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mul_qqq_8_16_32_ddd_32,\
- cortex_a15_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mla_qqq_8_16,\
- cortex_a15_neon_fp_vadd_ddd_vabs_dd,\
- cortex_a15_neon_fp_vadd_qqq_vabs_qq,\
- cortex_a15_neon_fp_vmla_ddd,\
- cortex_a15_neon_fp_vmla_qqq,\
- cortex_a15_neon_fp_vrecps_vrsqrts_ddd,\
- cortex_a15_neon_fp_vrecps_vrsqrts_qqq")
-
-(define_bypass 6 "cortex_a15_neon_mla_qqq_32_qqd_32_scalar"
- "cortex_a15_neon_int_1,\
- cortex_a15_neon_int_4,\
- cortex_a15_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mul_qqq_8_16_32_ddd_32,\
- cortex_a15_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mla_qqq_8_16,\
- cortex_a15_neon_fp_vadd_ddd_vabs_dd,\
- cortex_a15_neon_fp_vadd_qqq_vabs_qq,\
- cortex_a15_neon_fp_vmla_ddd,\
- cortex_a15_neon_fp_vmla_qqq,\
- cortex_a15_neon_fp_vrecps_vrsqrts_ddd,\
- cortex_a15_neon_fp_vrecps_vrsqrts_qqq")
-
-(define_bypass 6 "cortex_a15_neon_mla_qqq_8_16"
- "cortex_a15_neon_int_1,\
- cortex_a15_neon_int_4,\
- cortex_a15_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mul_qqq_8_16_32_ddd_32,\
- cortex_a15_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mla_qqq_8_16,\
- cortex_a15_neon_fp_vadd_ddd_vabs_dd,\
- cortex_a15_neon_fp_vadd_qqq_vabs_qq,\
- cortex_a15_neon_fp_vmla_ddd,\
- cortex_a15_neon_fp_vmla_qqq,\
- cortex_a15_neon_fp_vrecps_vrsqrts_ddd,\
- cortex_a15_neon_fp_vrecps_vrsqrts_qqq")
-
-(define_bypass 5 "cortex_a15_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long"
- "cortex_a15_neon_int_1,\
- cortex_a15_neon_int_4,\
- cortex_a15_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mul_qqq_8_16_32_ddd_32,\
- cortex_a15_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mla_qqq_8_16,\
- cortex_a15_neon_fp_vadd_ddd_vabs_dd,\
- cortex_a15_neon_fp_vadd_qqq_vabs_qq,\
- cortex_a15_neon_fp_vmla_ddd,\
- cortex_a15_neon_fp_vmla_qqq,\
- cortex_a15_neon_fp_vrecps_vrsqrts_ddd,\
- cortex_a15_neon_fp_vrecps_vrsqrts_qqq")
-
-(define_bypass 6
- "cortex_a15_neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar"
- "cortex_a15_neon_int_1,\
- cortex_a15_neon_int_4,\
- cortex_a15_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mul_qqq_8_16_32_ddd_32,\
- cortex_a15_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mla_qqq_8_16,\
- cortex_a15_neon_fp_vadd_ddd_vabs_dd,\
- cortex_a15_neon_fp_vadd_qqq_vabs_qq,\
- cortex_a15_neon_fp_vmla_ddd,\
- cortex_a15_neon_fp_vmla_qqq,\
- cortex_a15_neon_fp_vrecps_vrsqrts_ddd,\
- cortex_a15_neon_fp_vrecps_vrsqrts_qqq")
-
-(define_bypass 6 "cortex_a15_neon_mul_qqq_8_16_32_ddd_32"
- "cortex_a15_neon_int_1,\
- cortex_a15_neon_int_4,\
- cortex_a15_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mul_qqq_8_16_32_ddd_32,\
- cortex_a15_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mla_qqq_8_16,\
- cortex_a15_neon_fp_vadd_ddd_vabs_dd,\
- cortex_a15_neon_fp_vadd_qqq_vabs_qq,\
- cortex_a15_neon_fp_vmla_ddd,\
- cortex_a15_neon_fp_vmla_qqq,\
- cortex_a15_neon_fp_vrecps_vrsqrts_ddd,\
- cortex_a15_neon_fp_vrecps_vrsqrts_qqq")
-
-(define_bypass 5 "cortex_a15_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long"
- "cortex_a15_neon_int_1,\
- cortex_a15_neon_int_4,\
- cortex_a15_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mul_qqq_8_16_32_ddd_32,\
- cortex_a15_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mla_qqq_8_16,\
- cortex_a15_neon_fp_vadd_ddd_vabs_dd,\
- cortex_a15_neon_fp_vadd_qqq_vabs_qq,\
- cortex_a15_neon_fp_vmla_ddd,\
- cortex_a15_neon_fp_vmla_qqq,\
- cortex_a15_neon_fp_vrecps_vrsqrts_ddd,\
- cortex_a15_neon_fp_vrecps_vrsqrts_qqq")
-
-(define_bypass 7 "cortex_a15_neon_vaba_qqq"
- "cortex_a15_neon_int_1,\
- cortex_a15_neon_int_4,\
- cortex_a15_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mul_qqq_8_16_32_ddd_32,\
- cortex_a15_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mla_qqq_8_16,\
- cortex_a15_neon_fp_vadd_ddd_vabs_dd,\
- cortex_a15_neon_fp_vadd_qqq_vabs_qq,\
- cortex_a15_neon_fp_vmla_ddd,\
- cortex_a15_neon_fp_vmla_qqq,\
- cortex_a15_neon_fp_vrecps_vrsqrts_ddd,\
- cortex_a15_neon_fp_vrecps_vrsqrts_qqq")
-
-(define_bypass 6 "cortex_a15_neon_vaba"
- "cortex_a15_neon_int_1,\
- cortex_a15_neon_int_4,\
- cortex_a15_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mul_qqq_8_16_32_ddd_32,\
- cortex_a15_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mla_qqq_8_16,\
- cortex_a15_neon_fp_vadd_ddd_vabs_dd,\
- cortex_a15_neon_fp_vadd_qqq_vabs_qq,\
- cortex_a15_neon_fp_vmla_ddd,\
- cortex_a15_neon_fp_vmla_qqq,\
- cortex_a15_neon_fp_vrecps_vrsqrts_ddd,\
- cortex_a15_neon_fp_vrecps_vrsqrts_qqq")
-
-(define_bypass 4 "cortex_a15_neon_vmov"
- "cortex_a15_neon_int_1,\
- cortex_a15_neon_int_4,\
- cortex_a15_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mul_qqq_8_16_32_ddd_32,\
- cortex_a15_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mla_qqq_8_16,\
- cortex_a15_neon_fp_vadd_ddd_vabs_dd,\
- cortex_a15_neon_fp_vadd_qqq_vabs_qq,\
- cortex_a15_neon_fp_vmla_ddd,\
- cortex_a15_neon_fp_vmla_qqq,\
- cortex_a15_neon_fp_vrecps_vrsqrts_ddd,\
- cortex_a15_neon_fp_vrecps_vrsqrts_qqq")
-
-(define_bypass 4 "cortex_a15_neon_vqneg_vqabs"
- "cortex_a15_neon_int_1,\
- cortex_a15_neon_int_4,\
- cortex_a15_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mul_qqq_8_16_32_ddd_32,\
- cortex_a15_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mla_qqq_8_16,\
- cortex_a15_neon_fp_vadd_ddd_vabs_dd,\
- cortex_a15_neon_fp_vadd_qqq_vabs_qq,\
- cortex_a15_neon_fp_vmla_ddd,\
- cortex_a15_neon_fp_vmla_qqq,\
- cortex_a15_neon_fp_vrecps_vrsqrts_ddd,\
- cortex_a15_neon_fp_vrecps_vrsqrts_qqq")
-
-(define_bypass 4 "cortex_a15_neon_int_5"
- "cortex_a15_neon_int_1,\
- cortex_a15_neon_int_4,\
- cortex_a15_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mul_qqq_8_16_32_ddd_32,\
- cortex_a15_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mla_qqq_8_16,\
- cortex_a15_neon_fp_vadd_ddd_vabs_dd,\
- cortex_a15_neon_fp_vadd_qqq_vabs_qq,\
- cortex_a15_neon_fp_vmla_ddd,\
- cortex_a15_neon_fp_vmla_qqq,\
- cortex_a15_neon_fp_vrecps_vrsqrts_ddd,\
- cortex_a15_neon_fp_vrecps_vrsqrts_qqq")
-
-(define_bypass 4 "cortex_a15_neon_int_4"
- "cortex_a15_neon_int_1,\
- cortex_a15_neon_int_4,\
- cortex_a15_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mul_qqq_8_16_32_ddd_32,\
- cortex_a15_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mla_qqq_8_16,\
- cortex_a15_neon_fp_vadd_ddd_vabs_dd,\
- cortex_a15_neon_fp_vadd_qqq_vabs_qq,\
- cortex_a15_neon_fp_vmla_ddd,\
- cortex_a15_neon_fp_vmla_qqq,\
- cortex_a15_neon_fp_vrecps_vrsqrts_ddd,\
- cortex_a15_neon_fp_vrecps_vrsqrts_qqq")
-
-(define_bypass 4 "cortex_a15_neon_int_3"
- "cortex_a15_neon_int_1,\
- cortex_a15_neon_int_4,\
- cortex_a15_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mul_qqq_8_16_32_ddd_32,\
- cortex_a15_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mla_qqq_8_16,\
- cortex_a15_neon_fp_vadd_ddd_vabs_dd,\
- cortex_a15_neon_fp_vadd_qqq_vabs_qq,\
- cortex_a15_neon_fp_vmla_ddd,\
- cortex_a15_neon_fp_vmla_qqq,\
- cortex_a15_neon_fp_vrecps_vrsqrts_ddd,\
- cortex_a15_neon_fp_vrecps_vrsqrts_qqq")
-
-(define_bypass 4 "cortex_a15_neon_int_2"
- "cortex_a15_neon_int_1,\
- cortex_a15_neon_int_4,\
- cortex_a15_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mul_qqq_8_16_32_ddd_32,\
- cortex_a15_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mla_qqq_8_16,\
- cortex_a15_neon_fp_vadd_ddd_vabs_dd,\
- cortex_a15_neon_fp_vadd_qqq_vabs_qq,\
- cortex_a15_neon_fp_vmla_ddd,\
- cortex_a15_neon_fp_vmla_qqq,\
- cortex_a15_neon_fp_vrecps_vrsqrts_ddd,\
- cortex_a15_neon_fp_vrecps_vrsqrts_qqq")
-
-(define_bypass 4 "cortex_a15_neon_int_1"
- "cortex_a15_neon_int_1,\
- cortex_a15_neon_int_4,\
- cortex_a15_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mul_qqq_8_16_32_ddd_32,\
- cortex_a15_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a15_neon_mla_qqq_8_16,\
- cortex_a15_neon_fp_vadd_ddd_vabs_dd,\
- cortex_a15_neon_fp_vadd_qqq_vabs_qq,\
- cortex_a15_neon_fp_vmla_ddd,\
- cortex_a15_neon_fp_vmla_qqq,\
- cortex_a15_neon_fp_vrecps_vrsqrts_ddd,\
- cortex_a15_neon_fp_vrecps_vrsqrts_qqq")
-
diff --git a/gcc/config/arm/cortex-a7.md b/gcc/config/arm/cortex-a7.md
index a72a88d90af..7db6c5b24fb 100644
--- a/gcc/config/arm/cortex-a7.md
+++ b/gcc/config/arm/cortex-a7.md
@@ -20,6 +20,45 @@
;; along with GCC; see the file COPYING3. If not see
;; <http://www.gnu.org/licenses/>.
+(define_attr "cortex_a7_neon_type"
+ "neon_mul, neon_mla, neon_other"
+ (cond [
+ (eq_attr "type" "neon_mul_b, neon_mul_b_q,\
+ neon_mul_h, neon_mul_h_q,\
+ neon_mul_s, neon_mul_s_q,\
+ neon_mul_b_long, neon_mul_h_long,\
+ neon_mul_s_long, neon_mul_h_scalar,\
+ neon_mul_h_scalar_q, neon_mul_s_scalar,\
+ neon_mul_s_scalar_q, neon_mul_h_scalar_long,\
+ neon_mul_s_scalar_long,\
+ neon_sat_mul_b, neon_sat_mul_b_q,\
+ neon_sat_mul_h, neon_sat_mul_h_q,\
+ neon_sat_mul_s, neon_sat_mul_s_q,\
+ neon_sat_mul_b_long, neon_sat_mul_h_long,\
+ neon_sat_mul_s_long,\
+ neon_sat_mul_h_scalar, neon_sat_mul_h_scalar_q,\
+ neon_sat_mul_s_scalar, neon_sat_mul_s_scalar_q,\
+ neon_sat_mul_h_scalar_long,\
+ neon_sat_mul_s_scalar_long,\
+ neon_fp_mul_s, neon_fp_mul_s_q,\
+ neon_fp_mul_s_scalar, neon_fp_mul_s_scalar_q")
+ (const_string "neon_mul")
+ (eq_attr "type" "neon_mla_b, neon_mla_b_q, neon_mla_h,\
+ neon_mla_h_q, neon_mla_s, neon_mla_s_q,\
+ neon_mla_b_long, neon_mla_h_long,\
+ neon_mla_s_long,\
+ neon_mla_h_scalar, neon_mla_h_scalar_q,\
+ neon_mla_s_scalar, neon_mla_s_scalar_q,\
+ neon_mla_h_scalar_long, neon_mla_s_scalar_long,\
+ neon_sat_mla_b_long, neon_sat_mla_h_long,\
+ neon_sat_mla_s_long,\
+ neon_sat_mla_h_scalar_long,\
+ neon_sat_mla_s_scalar_long,\
+ neon_fp_mla_s, neon_fp_mla_s_q,\
+ neon_fp_mla_s_scalar, neon_fp_mla_s_scalar_q")
+ (const_string "neon_mla")]
+ (const_string "neon_other")))
+
(define_automaton "cortex_a7")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -227,14 +266,7 @@
(define_insn_reservation "cortex_a7_neon_mul" 4
(and (eq_attr "tune" "cortexa7")
- (eq_attr "type"
- "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
- neon_mul_qqq_8_16_32_ddd_32,\
- neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar,\
- neon_mul_ddd_16_scalar_32_16_long_scalar,\
- neon_mul_qqd_32_scalar,\
- neon_fp_vmul_ddd,\
- neon_fp_vmul_qqd"))
+ (eq_attr "cortex_a7_neon_type" "neon_mul"))
"(cortex_a7_both+cortex_a7_fpmul_pipe)*2")
(define_insn_reservation "cortex_a7_fpmacs" 8
@@ -244,16 +276,7 @@
(define_insn_reservation "cortex_a7_neon_mla" 8
(and (eq_attr "tune" "cortexa7")
- (eq_attr "type"
- "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
- neon_mla_qqq_8_16,\
- neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long,\
- neon_mla_qqq_32_qqd_32_scalar,\
- neon_mla_ddd_16_scalar_qdd_32_16_long_scalar,\
- neon_fp_vmla_ddd,\
- neon_fp_vmla_qqq,\
- neon_fp_vmla_ddd_scalar,\
- neon_fp_vmla_qqq_scalar"))
+ (eq_attr "cortex_a7_neon_type" "neon_mla"))
"cortex_a7_both+cortex_a7_fpmul_pipe")
(define_bypass 4 "cortex_a7_fpmacs,cortex_a7_neon_mla"
@@ -366,21 +389,6 @@
(define_insn_reservation "cortex_a7_neon" 4
(and (eq_attr "tune" "cortexa7")
- (eq_attr "type"
- "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
- neon_mul_qqq_8_16_32_ddd_32,\
- neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar,\
- neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
- neon_mla_qqq_8_16,\
- neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long,\
- neon_mla_qqq_32_qqd_32_scalar,\
- neon_mul_ddd_16_scalar_32_16_long_scalar,\
- neon_mul_qqd_32_scalar,\
- neon_mla_ddd_16_scalar_qdd_32_16_long_scalar,\
- neon_fp_vmul_ddd,\
- neon_fp_vmul_qqd,\
- neon_fp_vmla_ddd,\
- neon_fp_vmla_qqq,\
- neon_fp_vmla_ddd_scalar,\
- neon_fp_vmla_qqq_scalar"))
+ (and (eq_attr "is_neon_type" "yes")
+ (eq_attr "cortex_a7_neon_type" "neon_other")))
"cortex_a7_both*2")
diff --git a/gcc/config/arm/cortex-a8-neon.md b/gcc/config/arm/cortex-a8-neon.md
index b7773891669..6adfd136569 100644
--- a/gcc/config/arm/cortex-a8-neon.md
+++ b/gcc/config/arm/cortex-a8-neon.md
@@ -18,6 +18,221 @@
;; along with GCC; see the file COPYING3. If not see
;; <http://www.gnu.org/licenses/>.
+(define_attr "cortex_a8_neon_type"
+ "neon_int_1,neon_int_2,neon_int_3,neon_int_4,neon_int_5,neon_vqneg_vqabs,
+ neon_bit_ops_q,
+ neon_vaba,neon_vaba_qqq, neon_vmov,
+ neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,neon_mul_qqq_8_16_32_ddd_32,
+ neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar,
+ neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,neon_mla_qqq_8_16,
+ neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long,
+ neon_mla_qqq_32_qqd_32_scalar,neon_mul_ddd_16_scalar_32_16_long_scalar,
+ neon_mul_qqd_32_scalar,neon_mla_ddd_16_scalar_qdd_32_16_long_scalar,
+ neon_shift_1,neon_shift_2,neon_shift_3,
+ neon_vqshl_vrshl_vqrshl_qqq,neon_vsra_vrsra,neon_fp_vadd_ddd_vabs_dd,
+ neon_fp_vadd_qqq_vabs_qq,neon_fp_vsum,neon_fp_vmul_ddd,neon_fp_vmul_qqd,
+ neon_fp_vmla_ddd,neon_fp_vmla_qqq,neon_fp_vmla_ddd_scalar,
+ neon_fp_vmla_qqq_scalar,neon_fp_vrecps_vrsqrts_ddd,
+ neon_fp_vrecps_vrsqrts_qqq,neon_bp_simple,neon_bp_2cycle,neon_bp_3cycle,
+ neon_ldr,neon_str,neon_vld1_1_2_regs,neon_vld1_3_4_regs,
+ neon_vld2_2_regs_vld1_vld2_all_lanes,neon_vld2_4_regs,neon_vld3_vld4,
+ neon_vst1_1_2_regs_vst2_2_regs,neon_vst1_3_4_regs,
+ neon_vst2_4_regs_vst3_vst4,neon_vld1_vld2_lane,
+ neon_vld3_vld4_lane,neon_vst1_vst2_lane,neon_vst3_vst4_lane,
+ neon_vld3_vld4_all_lanes,neon_mcr,neon_mcr_2_mcrr,neon_mrc,neon_mrrc,
+ neon_ldm_2,neon_stm_2,none,unknown"
+ (cond [
+ (eq_attr "type" "neon_logic, neon_logic_q,\
+ neon_bsl, neon_cls, neon_cnt,\
+ neon_add, neon_add_q")
+ (const_string "neon_int_1")
+ (eq_attr "type" "neon_add_widen, neon_sub_widen,\
+ neon_sub, neon_sub_q")
+ (const_string "neon_int_2")
+ (eq_attr "type" "neon_neg, neon_neg_q,\
+ neon_reduc_add, neon_reduc_add_q,\
+ neon_reduc_add_long,\
+ neon_add_long, neon_sub_long")
+ (const_string "neon_int_3")
+ (eq_attr "type" "neon_abs, neon_abs_q,
+ neon_compare_zero, neon_compare_zero_q,\
+ neon_add_halve_narrow_q,\
+ neon_sub_halve_narrow_q,\
+ neon_add_halve, neon_add_halve_q,\
+ neon_qadd, neon_qadd_q,\
+ neon_tst, neon_tst_q")
+ (const_string "neon_int_4")
+ (eq_attr "type" "neon_abd_long, neon_sub_halve, neon_sub_halve_q,\
+ neon_qsub, neon_qsub_q,\
+ neon_abd, neon_abd_q,\
+ neon_compare, neon_compare_q,\
+ neon_minmax, neon_minmax_q, neon_reduc_minmax,\
+ neon_reduc_minmax_q")
+ (const_string "neon_int_5")
+ (eq_attr "type" "neon_qneg, neon_qneg_q, neon_qabs, neon_qabs_q")
+ (const_string "neon_vqneg_vqabs")
+ (eq_attr "type" "neon_move, neon_move_q")
+ (const_string "neon_vmov")
+ (eq_attr "type" "neon_bsl_q, neon_cls_q, neon_cnt_q")
+ (const_string "neon_bit_ops_q")
+ (eq_attr "type" "neon_arith_acc, neon_reduc_add_acc")
+ (const_string "neon_vaba")
+ (eq_attr "type" "neon_arith_acc_q")
+ (const_string "neon_vaba_qqq")
+ (eq_attr "type" "neon_shift_imm, neon_shift_imm_q,\
+ neon_shift_imm_long, neon_shift_imm_narrow_q,\
+ neon_shift_reg")
+ (const_string "neon_shift_1")
+ (eq_attr "type" "neon_sat_shift_imm, neon_sat_shift_imm_q,
+ neon_sat_shift_imm_narrow_q,\
+ neon_sat_shift_reg")
+ (const_string "neon_shift_2")
+ (eq_attr "type" "neon_shift_reg_q")
+ (const_string "neon_shift_3")
+ (eq_attr "type" "neon_sat_shift_reg_q")
+ (const_string "neon_vqshl_vrshl_vqrshl_qqq")
+ (eq_attr "type" "neon_shift_acc, neon_shift_acc_q")
+ (const_string "neon_vsra_vrsra")
+ (eq_attr "type" "neon_mul_b, neon_mul_h,\
+ neon_mul_b_long, neon_mul_h_long,\
+ neon_sat_mul_b, neon_sat_mul_h,\
+ neon_sat_mul_b_long, neon_sat_mul_h_long")
+ (const_string
+ "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long")
+ (eq_attr "type" "neon_mul_b_q, neon_mul_h_q,\
+ neon_sat_mul_b_q, neon_sat_mul_h_q")
+ (const_string "neon_mul_qqq_8_16_32_ddd_32")
+ (eq_attr "type" "neon_mul_s, neon_mul_s_long,\
+ neon_sat_mul_s, neon_sat_mul_s_long,\
+ neon_mul_h_scalar_q, neon_sat_mul_h_scalar_q,\
+ neon_mul_s_scalar, neon_sat_mul_s_scalar,\
+ neon_mul_s_scalar_long,\
+ neon_sat_mul_s_scalar_long")
+ (const_string
+ "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")
+ (eq_attr "type" "neon_mla_b, neon_mla_h,\
+ neon_mla_b_long, neon_mla_h_long,\
+ neon_sat_mla_b_long, neon_sat_mla_h_long,\
+ neon_sat_mla_h_scalar_long")
+ (const_string
+ "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
+ (eq_attr "type" "neon_mla_b_q, neon_mla_h_q")
+ (const_string "neon_mla_qqq_8_16")
+ (eq_attr "type" "neon_mla_s, neon_mla_s_long,\
+ neon_sat_mla_s_long,\
+ neon_mla_h_scalar_q, neon_mla_s_scalar,\
+ neon_mla_s_scalar_long,\
+ neon_sat_mla_s_scalar_long")
+ (const_string
+ "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")
+ (eq_attr "type" "neon_mla_s_q, neon_mla_s_scalar_q")
+ (const_string "neon_mla_qqq_32_qqd_32_scalar")
+ (eq_attr "type" "neon_mul_h_scalar, neon_sat_mul_h_scalar,\
+ neon_mul_h_scalar_long,\
+ neon_sat_mul_h_scalar_long")
+ (const_string
+ "neon_mul_ddd_16_scalar_32_16_long_scalar")
+ (eq_attr "type" "neon_mul_s_q, neon_sat_mul_s_q,\
+ neon_mul_s_scalar_q")
+ (const_string "neon_mul_qqd_32_scalar")
+ (eq_attr "type" "neon_mla_h_scalar, neon_mla_h_scalar_long")
+ (const_string
+ "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar")
+ (eq_attr "type" "neon_fp_abd_s, neon_fp_abs_s, neon_fp_neg_s,\
+ neon_fp_addsub_s, neon_fp_compare_s,\
+ neon_fp_minmax_s, neon_fp_mul_s,\
+ neon_fp_recpe_s, neon_fp_rsqrte_s,\
+ neon_fp_to_int_s, neon_int_to_fp_s")
+ (const_string "neon_fp_vadd_ddd_vabs_dd")
+ (eq_attr "type" "neon_fp_abd_s_q, neon_fp_abs_s_q,\
+ neon_fp_neg_s_q,\
+ neon_fp_addsub_s_q, neon_fp_compare_s_q,\
+ neon_fp_minmax_s_q, neon_fp_mul_s_q,\
+ neon_fp_recpe_s_q, neon_fp_rsqrte_s_q,\
+ neon_fp_to_int_s_q, neon_int_to_fp_s_q")
+ (const_string "neon_fp_vadd_qqq_vabs_qq")
+ (eq_attr "type" "neon_fp_reduc_add_s, neon_fp_reduc_minmax_s,\
+ neon_fp_reduc_add_s_q, neon_fp_reduc_minmax_s_q")
+ (const_string "neon_fp_vsum")
+ (eq_attr "type" "neon_fp_mul_s_scalar")
+ (const_string "neon_fp_vmul_ddd")
+ (eq_attr "type" "neon_fp_mul_s_scalar_q")
+ (const_string "neon_fp_vmul_qqd")
+ (eq_attr "type" "neon_fp_mla_s")
+ (const_string "neon_fp_vmla_ddd")
+ (eq_attr "type" "neon_fp_mla_s_q")
+ (const_string "neon_fp_vmla_qqq")
+ (eq_attr "type" "neon_fp_mla_s_scalar")
+ (const_string "neon_fp_vmla_ddd_scalar")
+ (eq_attr "type" "neon_fp_mla_s_scalar_q")
+ (const_string "neon_fp_vmla_qqq_scalar")
+ (eq_attr "type" "neon_fp_recps_s, neon_fp_rsqrts_s")
+ (const_string "neon_fp_vrecps_vrsqrts_ddd")
+ (eq_attr "type" "neon_fp_recps_s_q, neon_fp_rsqrts_s_q")
+ (const_string "neon_fp_vrecps_vrsqrts_qqq")
+ (eq_attr "type" "neon_move_narrow_q, neon_dup,\
+ neon_dup_q, neon_permute, neon_zip,\
+ neon_ext, neon_rev, neon_rev_q")
+ (const_string "neon_bp_simple")
+ (eq_attr "type" "neon_permute_q, neon_ext_q, neon_tbl1, neon_tbl2")
+ (const_string "neon_bp_2cycle")
+ (eq_attr "type" "neon_zip_q, neon_tbl3, neon_tbl4")
+ (const_string "neon_bp_3cycle")
+ (eq_attr "type" "neon_ldr")
+ (const_string "neon_ldr")
+ (eq_attr "type" "neon_str")
+ (const_string "neon_str")
+ (eq_attr "type" "neon_load1_1reg, neon_load1_1reg_q,\
+ neon_load1_2reg, neon_load1_2reg_q,\
+ neon_load2_2reg, neon_load2_2reg_q")
+ (const_string "neon_vld1_1_2_regs")
+ (eq_attr "type" "neon_load1_3reg, neon_load1_3reg_q,\
+ neon_load1_4reg, neon_load1_4reg_q")
+ (const_string "neon_vld1_3_4_regs")
+ (eq_attr "type" "neon_load1_all_lanes, neon_load1_all_lanes_q,\
+ neon_load2_all_lanes, neon_load2_all_lanes_q")
+ (const_string
+ "neon_vld2_2_regs_vld1_vld2_all_lanes")
+ (eq_attr "type" "neon_load3_all_lanes, neon_load3_all_lanes_q,\
+ neon_load4_all_lanes, neon_load4_all_lanes_q,\
+ neon_load2_4reg, neon_load2_4reg_q")
+ (const_string "neon_vld2_4_regs")
+ (eq_attr "type" "neon_load3_3reg, neon_load3_3reg_q,\
+ neon_load4_4reg, neon_load4_4reg_q")
+ (const_string "neon_vld3_vld4")
+ (eq_attr "type" "f_loads, f_loadd, f_stores, f_stored,\
+ neon_load1_one_lane, neon_load1_one_lane_q,\
+ neon_load2_one_lane, neon_load2_one_lane_q")
+ (const_string "neon_vld1_vld2_lane")
+ (eq_attr "type" "neon_load3_one_lane, neon_load3_one_lane_q,\
+ neon_load4_one_lane, neon_load4_one_lane_q")
+ (const_string "neon_vld3_vld4_lane")
+ (eq_attr "type" "neon_store1_1reg, neon_store1_1reg_q,\
+ neon_store1_2reg, neon_store1_2reg_q,\
+ neon_store2_2reg, neon_store2_2reg_q")
+ (const_string "neon_vst1_1_2_regs_vst2_2_regs")
+ (eq_attr "type" "neon_store1_3reg, neon_store1_3reg_q,\
+ neon_store1_4reg, neon_store1_4reg_q")
+ (const_string "neon_vst1_3_4_regs")
+ (eq_attr "type" "neon_store2_4reg, neon_store2_4reg_q,\
+ neon_store3_3reg, neon_store3_3reg_q,\
+ neon_store4_4reg, neon_store4_4reg_q")
+ (const_string "neon_vst2_4_regs_vst3_vst4")
+ (eq_attr "type" "neon_store1_one_lane, neon_store1_one_lane_q,\
+ neon_store2_one_lane, neon_store2_one_lane_q")
+ (const_string "neon_vst1_vst2_lane")
+ (eq_attr "type" "neon_store3_one_lane, neon_store3_one_lane_q,\
+ neon_store4_one_lane, neon_store4_one_lane_q")
+ (const_string "neon_vst3_vst4_lane")
+ (eq_attr "type" "neon_from_gp, f_mcr")
+ (const_string "neon_mcr")
+ (eq_attr "type" "neon_from_gp_q, f_mcrr")
+ (const_string "neon_mcr_2_mcrr")
+ (eq_attr "type" "neon_to_gp, f_mrc")
+ (const_string "neon_mrc")
+ (eq_attr "type" "neon_to_gp_q, f_mrrc")
+ (const_string "neon_mrrc")]
+ (const_string "unknown")))
(define_automaton "cortex_a8_neon")
@@ -184,62 +399,62 @@
(define_insn_reservation "cortex_a8_neon_mrc" 20
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_mrc"))
+ (eq_attr "cortex_a8_neon_type" "neon_mrc"))
"cortex_a8_neon_ls")
(define_insn_reservation "cortex_a8_neon_mrrc" 21
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_mrrc"))
+ (eq_attr "cortex_a8_neon_type" "neon_mrrc"))
"cortex_a8_neon_ls_2")
-;; The remainder of this file is auto-generated by neon-schedgen.
+;; Arithmetic Operations
;; Instructions using this reservation read their source operands at N2, and
;; produce a result at N3.
(define_insn_reservation "cortex_a8_neon_int_1" 3
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_int_1"))
+ (eq_attr "cortex_a8_neon_type" "neon_int_1"))
"cortex_a8_neon_dp")
;; Instructions using this reservation read their (D|Q)m operands at N1,
;; their (D|Q)n operands at N2, and produce a result at N3.
(define_insn_reservation "cortex_a8_neon_int_2" 3
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_int_2"))
+ (eq_attr "cortex_a8_neon_type" "neon_int_2"))
"cortex_a8_neon_dp")
;; Instructions using this reservation read their source operands at N1, and
;; produce a result at N3.
(define_insn_reservation "cortex_a8_neon_int_3" 3
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_int_3"))
+ (eq_attr "cortex_a8_neon_type" "neon_int_3"))
"cortex_a8_neon_dp")
;; Instructions using this reservation read their source operands at N2, and
;; produce a result at N4.
(define_insn_reservation "cortex_a8_neon_int_4" 4
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_int_4"))
+ (eq_attr "cortex_a8_neon_type" "neon_int_4"))
"cortex_a8_neon_dp")
;; Instructions using this reservation read their (D|Q)m operands at N1,
;; their (D|Q)n operands at N2, and produce a result at N4.
(define_insn_reservation "cortex_a8_neon_int_5" 4
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_int_5"))
+ (eq_attr "cortex_a8_neon_type" "neon_int_5"))
"cortex_a8_neon_dp")
;; Instructions using this reservation read their source operands at N1, and
;; produce a result at N4.
(define_insn_reservation "cortex_a8_neon_vqneg_vqabs" 4
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_vqneg_vqabs"))
+ (eq_attr "cortex_a8_neon_type" "neon_vqneg_vqabs"))
"cortex_a8_neon_dp")
;; Instructions using this reservation produce a result at N3.
(define_insn_reservation "cortex_a8_neon_vmov" 3
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_vmov"))
+ (eq_attr "cortex_a8_neon_type" "neon_vmov"))
"cortex_a8_neon_dp")
;; Instructions using this reservation read their (D|Q)n operands at N2,
@@ -247,7 +462,7 @@
;; produce a result at N6.
(define_insn_reservation "cortex_a8_neon_vaba" 6
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_vaba"))
+ (eq_attr "cortex_a8_neon_type" "neon_vaba"))
"cortex_a8_neon_dp")
;; Instructions using this reservation read their (D|Q)n operands at N2,
@@ -255,35 +470,39 @@
;; produce a result at N6 on cycle 2.
(define_insn_reservation "cortex_a8_neon_vaba_qqq" 7
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_vaba_qqq"))
+ (eq_attr "cortex_a8_neon_type" "neon_vaba_qqq"))
"cortex_a8_neon_dp_2")
-;; Instructions using this reservation read their (D|Q)m operands at N1,
-;; their (D|Q)d operands at N3, and produce a result at N6.
-(define_insn_reservation "cortex_a8_neon_vsma" 6
+;; Instructions using this reservation read their source operands at N2, and
+;; produce a result at N3 on cycle 2.
+(define_insn_reservation "cortex_a8_neon_bit_ops_q" 4
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_vsma"))
- "cortex_a8_neon_dp")
+ (eq_attr "cortex_a8_neon_type" "neon_bit_ops_q"))
+ "cortex_a8_neon_dp_2")
+
+;; Integer Multiply/Accumulate Operations
;; Instructions using this reservation read their source operands at N2, and
;; produce a result at N6.
(define_insn_reservation "cortex_a8_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long" 6
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long"))
+ (eq_attr "cortex_a8_neon_type"
+ "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long"))
"cortex_a8_neon_dp")
;; Instructions using this reservation read their source operands at N2, and
;; produce a result at N6 on cycle 2.
(define_insn_reservation "cortex_a8_neon_mul_qqq_8_16_32_ddd_32" 7
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_mul_qqq_8_16_32_ddd_32"))
+ (eq_attr "cortex_a8_neon_type" "neon_mul_qqq_8_16_32_ddd_32"))
"cortex_a8_neon_dp_2")
;; Instructions using this reservation read their (D|Q)n operands at N2,
;; their (D|Q)m operands at N1, and produce a result at N6 on cycle 2.
(define_insn_reservation "cortex_a8_neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar" 7
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar"))
+ (eq_attr "cortex_a8_neon_type"
+ "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar"))
"cortex_a8_neon_dp_2")
;; Instructions using this reservation read their (D|Q)n operands at N2,
@@ -291,7 +510,8 @@
;; produce a result at N6.
(define_insn_reservation "cortex_a8_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long" 6
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long"))
+ (eq_attr "cortex_a8_neon_type"
+ "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long"))
"cortex_a8_neon_dp")
;; Instructions using this reservation read their (D|Q)n operands at N2,
@@ -299,7 +519,7 @@
;; produce a result at N6 on cycle 2.
(define_insn_reservation "cortex_a8_neon_mla_qqq_8_16" 7
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_mla_qqq_8_16"))
+ (eq_attr "cortex_a8_neon_type" "neon_mla_qqq_8_16"))
"cortex_a8_neon_dp_2")
;; Instructions using this reservation read their (D|Q)n operands at N2,
@@ -307,7 +527,8 @@
;; produce a result at N6 on cycle 2.
(define_insn_reservation "cortex_a8_neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long" 7
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long"))
+ (eq_attr "cortex_a8_neon_type"
+ "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long"))
"cortex_a8_neon_dp_2")
;; Instructions using this reservation read their (D|Q)n operands at N2,
@@ -315,21 +536,22 @@
;; produce a result at N6 on cycle 4.
(define_insn_reservation "cortex_a8_neon_mla_qqq_32_qqd_32_scalar" 9
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_mla_qqq_32_qqd_32_scalar"))
+ (eq_attr "cortex_a8_neon_type" "neon_mla_qqq_32_qqd_32_scalar"))
"cortex_a8_neon_dp_4")
;; Instructions using this reservation read their (D|Q)n operands at N2,
;; their (D|Q)m operands at N1, and produce a result at N6.
(define_insn_reservation "cortex_a8_neon_mul_ddd_16_scalar_32_16_long_scalar" 6
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_mul_ddd_16_scalar_32_16_long_scalar"))
+ (eq_attr "cortex_a8_neon_type"
+ "neon_mul_ddd_16_scalar_32_16_long_scalar"))
"cortex_a8_neon_dp")
;; Instructions using this reservation read their (D|Q)n operands at N2,
;; their (D|Q)m operands at N1, and produce a result at N6 on cycle 4.
(define_insn_reservation "cortex_a8_neon_mul_qqd_32_scalar" 9
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_mul_qqd_32_scalar"))
+ (eq_attr "cortex_a8_neon_type" "neon_mul_qqd_32_scalar"))
"cortex_a8_neon_dp_4")
;; Instructions using this reservation read their (D|Q)n operands at N2,
@@ -337,84 +559,82 @@
;; produce a result at N6.
(define_insn_reservation "cortex_a8_neon_mla_ddd_16_scalar_qdd_32_16_long_scalar" 6
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar"))
+ (eq_attr "cortex_a8_neon_type"
+ "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar"))
"cortex_a8_neon_dp")
+;; Shift Operations
+
;; Instructions using this reservation read their source operands at N1, and
;; produce a result at N3.
(define_insn_reservation "cortex_a8_neon_shift_1" 3
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_shift_1"))
+ (eq_attr "cortex_a8_neon_type" "neon_shift_1"))
"cortex_a8_neon_dp")
;; Instructions using this reservation read their source operands at N1, and
;; produce a result at N4.
(define_insn_reservation "cortex_a8_neon_shift_2" 4
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_shift_2"))
+ (eq_attr "cortex_a8_neon_type" "neon_shift_2"))
"cortex_a8_neon_dp")
;; Instructions using this reservation read their source operands at N1, and
;; produce a result at N3 on cycle 2.
(define_insn_reservation "cortex_a8_neon_shift_3" 4
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_shift_3"))
+ (eq_attr "cortex_a8_neon_type" "neon_shift_3"))
"cortex_a8_neon_dp_2")
;; Instructions using this reservation read their source operands at N1, and
-;; produce a result at N1.
-(define_insn_reservation "cortex_a8_neon_vshl_ddd" 1
- (and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_vshl_ddd"))
- "cortex_a8_neon_dp")
-
-;; Instructions using this reservation read their source operands at N1, and
;; produce a result at N4 on cycle 2.
(define_insn_reservation "cortex_a8_neon_vqshl_vrshl_vqrshl_qqq" 5
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_vqshl_vrshl_vqrshl_qqq"))
+ (eq_attr "cortex_a8_neon_type" "neon_vqshl_vrshl_vqrshl_qqq"))
"cortex_a8_neon_dp_2")
;; Instructions using this reservation read their (D|Q)m operands at N1,
;; their (D|Q)d operands at N3, and produce a result at N6.
(define_insn_reservation "cortex_a8_neon_vsra_vrsra" 6
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_vsra_vrsra"))
+ (eq_attr "cortex_a8_neon_type" "neon_vsra_vrsra"))
"cortex_a8_neon_dp")
+;; Floating point Operations
+
;; Instructions using this reservation read their source operands at N2, and
;; produce a result at N5.
(define_insn_reservation "cortex_a8_neon_fp_vadd_ddd_vabs_dd" 5
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_fp_vadd_ddd_vabs_dd"))
- "cortex_a8_neon_fadd")
+ (eq_attr "cortex_a8_neon_type" "neon_fp_vadd_ddd_vabs_dd"))
+ "cortex_a8_neon_fadd")
;; Instructions using this reservation read their source operands at N2, and
;; produce a result at N5 on cycle 2.
(define_insn_reservation "cortex_a8_neon_fp_vadd_qqq_vabs_qq" 6
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_fp_vadd_qqq_vabs_qq"))
+ (eq_attr "cortex_a8_neon_type" "neon_fp_vadd_qqq_vabs_qq"))
"cortex_a8_neon_fadd_2")
;; Instructions using this reservation read their source operands at N1, and
;; produce a result at N5.
(define_insn_reservation "cortex_a8_neon_fp_vsum" 5
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_fp_vsum"))
+ (eq_attr "cortex_a8_neon_type" "neon_fp_vsum"))
"cortex_a8_neon_fadd")
;; Instructions using this reservation read their (D|Q)n operands at N2,
;; their (D|Q)m operands at N1, and produce a result at N5.
(define_insn_reservation "cortex_a8_neon_fp_vmul_ddd" 5
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_fp_vmul_ddd"))
+ (eq_attr "cortex_a8_neon_type" "neon_fp_vmul_ddd"))
"cortex_a8_neon_dp")
;; Instructions using this reservation read their (D|Q)n operands at N2,
;; their (D|Q)m operands at N1, and produce a result at N5 on cycle 2.
(define_insn_reservation "cortex_a8_neon_fp_vmul_qqd" 6
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_fp_vmul_qqd"))
+ (eq_attr "cortex_a8_neon_type" "neon_fp_vmul_qqd"))
"cortex_a8_neon_dp_2")
;; Instructions using this reservation read their (D|Q)n operands at N2,
@@ -422,7 +642,7 @@
;; produce a result at N9.
(define_insn_reservation "cortex_a8_neon_fp_vmla_ddd" 9
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_fp_vmla_ddd"))
+ (eq_attr "cortex_a8_neon_type" "neon_fp_vmla_ddd"))
"cortex_a8_neon_fmul_then_fadd")
;; Instructions using this reservation read their (D|Q)n operands at N2,
@@ -430,7 +650,7 @@
;; produce a result at N9 on cycle 2.
(define_insn_reservation "cortex_a8_neon_fp_vmla_qqq" 10
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_fp_vmla_qqq"))
+ (eq_attr "cortex_a8_neon_type" "neon_fp_vmla_qqq"))
"cortex_a8_neon_fmul_then_fadd_2")
;; Instructions using this reservation read their (D|Q)n operands at N2,
@@ -438,7 +658,7 @@
;; produce a result at N9.
(define_insn_reservation "cortex_a8_neon_fp_vmla_ddd_scalar" 9
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_fp_vmla_ddd_scalar"))
+ (eq_attr "cortex_a8_neon_type" "neon_fp_vmla_ddd_scalar"))
"cortex_a8_neon_fmul_then_fadd")
;; Instructions using this reservation read their (D|Q)n operands at N2,
@@ -446,152 +666,148 @@
;; produce a result at N9 on cycle 2.
(define_insn_reservation "cortex_a8_neon_fp_vmla_qqq_scalar" 10
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_fp_vmla_qqq_scalar"))
+ (eq_attr "cortex_a8_neon_type" "neon_fp_vmla_qqq_scalar"))
"cortex_a8_neon_fmul_then_fadd_2")
;; Instructions using this reservation read their source operands at N2, and
;; produce a result at N9.
(define_insn_reservation "cortex_a8_neon_fp_vrecps_vrsqrts_ddd" 9
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_fp_vrecps_vrsqrts_ddd"))
+ (eq_attr "cortex_a8_neon_type" "neon_fp_vrecps_vrsqrts_ddd"))
"cortex_a8_neon_fmul_then_fadd")
;; Instructions using this reservation read their source operands at N2, and
;; produce a result at N9 on cycle 2.
(define_insn_reservation "cortex_a8_neon_fp_vrecps_vrsqrts_qqq" 10
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_fp_vrecps_vrsqrts_qqq"))
+ (eq_attr "type" "neon_fp_recps_s_q, neon_fp_rsqrts_s_q"))
"cortex_a8_neon_fmul_then_fadd_2")
+;; Permute operations.
+
;; Instructions using this reservation read their source operands at N1, and
;; produce a result at N2.
(define_insn_reservation "cortex_a8_neon_bp_simple" 2
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_bp_simple"))
+ (eq_attr "cortex_a8_neon_type" "neon_bp_simple"))
"cortex_a8_neon_perm")
;; Instructions using this reservation read their source operands at N1, and
;; produce a result at N2 on cycle 2.
(define_insn_reservation "cortex_a8_neon_bp_2cycle" 3
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_bp_2cycle"))
+ (eq_attr "cortex_a8_neon_type" "neon_bp_2cycle"))
"cortex_a8_neon_perm_2")
;; Instructions using this reservation read their source operands at N1, and
;; produce a result at N2 on cycle 3.
(define_insn_reservation "cortex_a8_neon_bp_3cycle" 4
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_bp_3cycle"))
+ (eq_attr "cortex_a8_neon_type" "neon_bp_3cycle"))
"cortex_a8_neon_perm_3")
+;; Load Operations.
+
;; Instructions using this reservation produce a result at N1.
(define_insn_reservation "cortex_a8_neon_ldr" 1
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_ldr"))
+ (eq_attr "cortex_a8_neon_type" "neon_ldr"))
"cortex_a8_neon_ls")
;; Instructions using this reservation read their source operands at N1.
(define_insn_reservation "cortex_a8_neon_str" 0
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_str"))
+ (eq_attr "cortex_a8_neon_type" "neon_str"))
"cortex_a8_neon_ls")
;; Instructions using this reservation produce a result at N1 on cycle 2.
(define_insn_reservation "cortex_a8_neon_vld1_1_2_regs" 2
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_vld1_1_2_regs"))
+ (eq_attr "cortex_a8_neon_type" "neon_vld1_1_2_regs"))
"cortex_a8_neon_ls_2")
;; Instructions using this reservation produce a result at N1 on cycle 3.
(define_insn_reservation "cortex_a8_neon_vld1_3_4_regs" 3
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_vld1_3_4_regs"))
+ (eq_attr "cortex_a8_neon_type" "neon_vld1_3_4_regs"))
"cortex_a8_neon_ls_3")
;; Instructions using this reservation produce a result at N2 on cycle 2.
(define_insn_reservation "cortex_a8_neon_vld2_2_regs_vld1_vld2_all_lanes" 3
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_vld2_2_regs_vld1_vld2_all_lanes"))
+ (eq_attr "cortex_a8_neon_type" "neon_vld2_2_regs_vld1_vld2_all_lanes"))
"cortex_a8_neon_ls_2")
;; Instructions using this reservation produce a result at N2 on cycle 3.
(define_insn_reservation "cortex_a8_neon_vld2_4_regs" 4
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_vld2_4_regs"))
+ (eq_attr "cortex_a8_neon_type" "neon_vld2_4_regs"))
"cortex_a8_neon_ls_3")
;; Instructions using this reservation produce a result at N2 on cycle 4.
(define_insn_reservation "cortex_a8_neon_vld3_vld4" 5
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_vld3_vld4"))
+ (eq_attr "cortex_a8_neon_type" "neon_vld3_vld4"))
"cortex_a8_neon_ls_4")
+;; Store operations.
+
;; Instructions using this reservation read their source operands at N1.
(define_insn_reservation "cortex_a8_neon_vst1_1_2_regs_vst2_2_regs" 0
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_vst1_1_2_regs_vst2_2_regs"))
+ (eq_attr "cortex_a8_neon_type" "neon_vst1_1_2_regs_vst2_2_regs"))
"cortex_a8_neon_ls_2")
;; Instructions using this reservation read their source operands at N1.
(define_insn_reservation "cortex_a8_neon_vst1_3_4_regs" 0
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_vst1_3_4_regs"))
+ (eq_attr "cortex_a8_neon_type" "neon_vst1_3_4_regs"))
"cortex_a8_neon_ls_3")
;; Instructions using this reservation read their source operands at N1.
(define_insn_reservation "cortex_a8_neon_vst2_4_regs_vst3_vst4" 0
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_vst2_4_regs_vst3_vst4"))
- "cortex_a8_neon_ls_4")
-
-;; Instructions using this reservation read their source operands at N1.
-(define_insn_reservation "cortex_a8_neon_vst3_vst4" 0
- (and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_vst3_vst4"))
+ (eq_attr "cortex_a8_neon_type" "neon_vst2_4_regs_vst3_vst4"))
"cortex_a8_neon_ls_4")
;; Instructions using this reservation read their source operands at N1, and
;; produce a result at N2 on cycle 3.
(define_insn_reservation "cortex_a8_neon_vld1_vld2_lane" 4
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_vld1_vld2_lane"))
+ (eq_attr "cortex_a8_neon_type" "neon_vld1_vld2_lane"))
"cortex_a8_neon_ls_3")
;; Instructions using this reservation read their source operands at N1, and
;; produce a result at N2 on cycle 5.
(define_insn_reservation "cortex_a8_neon_vld3_vld4_lane" 6
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_vld3_vld4_lane"))
+ (eq_attr "cortex_a8_neon_type" "neon_vld3_vld4_lane"))
"cortex_a8_neon_ls_5")
;; Instructions using this reservation read their source operands at N1.
(define_insn_reservation "cortex_a8_neon_vst1_vst2_lane" 0
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_vst1_vst2_lane"))
+ (eq_attr "cortex_a8_neon_type" "neon_vst1_vst2_lane"))
"cortex_a8_neon_ls_2")
;; Instructions using this reservation read their source operands at N1.
(define_insn_reservation "cortex_a8_neon_vst3_vst4_lane" 0
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_vst3_vst4_lane"))
+ (eq_attr "cortex_a8_neon_type" "neon_vst3_vst4_lane"))
"cortex_a8_neon_ls_3")
-;; Instructions using this reservation produce a result at N2 on cycle 2.
-(define_insn_reservation "cortex_a8_neon_vld3_vld4_all_lanes" 3
- (and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_vld3_vld4_all_lanes"))
- "cortex_a8_neon_ls_3")
+;; Register Transfer Operations
;; Instructions using this reservation produce a result at N2.
(define_insn_reservation "cortex_a8_neon_mcr" 2
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_mcr"))
+ (eq_attr "cortex_a8_neon_type" "neon_mcr"))
"cortex_a8_neon_perm")
;; Instructions using this reservation produce a result at N2.
(define_insn_reservation "cortex_a8_neon_mcr_2_mcrr" 2
(and (eq_attr "tune" "cortexa8")
- (eq_attr "type" "neon_mcr_2_mcrr"))
+ (eq_attr "cortex_a8_neon_type" "neon_mcr_2_mcrr"))
"cortex_a8_neon_perm_2")
;; Exceptions to the default latencies.
@@ -599,6 +815,7 @@
(define_bypass 1 "cortex_a8_neon_mcr_2_mcrr"
"cortex_a8_neon_int_1,\
cortex_a8_neon_int_4,\
+ cortex_a8_neon_bit_ops_q,\
cortex_a8_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a8_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a8_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -613,20 +830,7 @@
(define_bypass 1 "cortex_a8_neon_mcr"
"cortex_a8_neon_int_1,\
cortex_a8_neon_int_4,\
- cortex_a8_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a8_neon_mul_qqq_8_16_32_ddd_32,\
- cortex_a8_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a8_neon_mla_qqq_8_16,\
- cortex_a8_neon_fp_vadd_ddd_vabs_dd,\
- cortex_a8_neon_fp_vadd_qqq_vabs_qq,\
- cortex_a8_neon_fp_vmla_ddd,\
- cortex_a8_neon_fp_vmla_qqq,\
- cortex_a8_neon_fp_vrecps_vrsqrts_ddd,\
- cortex_a8_neon_fp_vrecps_vrsqrts_qqq")
-
-(define_bypass 2 "cortex_a8_neon_vld3_vld4_all_lanes"
- "cortex_a8_neon_int_1,\
- cortex_a8_neon_int_4,\
+ cortex_a8_neon_bit_ops_q,\
cortex_a8_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a8_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a8_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -641,6 +845,7 @@
(define_bypass 5 "cortex_a8_neon_vld3_vld4_lane"
"cortex_a8_neon_int_1,\
cortex_a8_neon_int_4,\
+ cortex_a8_neon_bit_ops_q,\
cortex_a8_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a8_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a8_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -655,6 +860,7 @@
(define_bypass 3 "cortex_a8_neon_vld1_vld2_lane"
"cortex_a8_neon_int_1,\
cortex_a8_neon_int_4,\
+ cortex_a8_neon_bit_ops_q,\
cortex_a8_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a8_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a8_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -669,6 +875,7 @@
(define_bypass 4 "cortex_a8_neon_vld3_vld4"
"cortex_a8_neon_int_1,\
cortex_a8_neon_int_4,\
+ cortex_a8_neon_bit_ops_q,\
cortex_a8_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a8_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a8_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -683,6 +890,7 @@
(define_bypass 3 "cortex_a8_neon_vld2_4_regs"
"cortex_a8_neon_int_1,\
cortex_a8_neon_int_4,\
+ cortex_a8_neon_bit_ops_q,\
cortex_a8_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a8_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a8_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -697,6 +905,7 @@
(define_bypass 2 "cortex_a8_neon_vld2_2_regs_vld1_vld2_all_lanes"
"cortex_a8_neon_int_1,\
cortex_a8_neon_int_4,\
+ cortex_a8_neon_bit_ops_q,\
cortex_a8_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a8_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a8_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -711,6 +920,7 @@
(define_bypass 2 "cortex_a8_neon_vld1_3_4_regs"
"cortex_a8_neon_int_1,\
cortex_a8_neon_int_4,\
+ cortex_a8_neon_bit_ops_q,\
cortex_a8_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a8_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a8_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -725,6 +935,7 @@
(define_bypass 1 "cortex_a8_neon_vld1_1_2_regs"
"cortex_a8_neon_int_1,\
cortex_a8_neon_int_4,\
+ cortex_a8_neon_bit_ops_q,\
cortex_a8_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a8_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a8_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -739,6 +950,7 @@
(define_bypass 0 "cortex_a8_neon_ldr"
"cortex_a8_neon_int_1,\
cortex_a8_neon_int_4,\
+ cortex_a8_neon_bit_ops_q,\
cortex_a8_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a8_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a8_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -753,6 +965,7 @@
(define_bypass 3 "cortex_a8_neon_bp_3cycle"
"cortex_a8_neon_int_1,\
cortex_a8_neon_int_4,\
+ cortex_a8_neon_bit_ops_q,\
cortex_a8_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a8_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a8_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -767,6 +980,7 @@
(define_bypass 2 "cortex_a8_neon_bp_2cycle"
"cortex_a8_neon_int_1,\
cortex_a8_neon_int_4,\
+ cortex_a8_neon_bit_ops_q,\
cortex_a8_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a8_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a8_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -781,6 +995,7 @@
(define_bypass 1 "cortex_a8_neon_bp_simple"
"cortex_a8_neon_int_1,\
cortex_a8_neon_int_4,\
+ cortex_a8_neon_bit_ops_q,\
cortex_a8_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a8_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a8_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -795,6 +1010,7 @@
(define_bypass 9 "cortex_a8_neon_fp_vrecps_vrsqrts_qqq"
"cortex_a8_neon_int_1,\
cortex_a8_neon_int_4,\
+ cortex_a8_neon_bit_ops_q,\
cortex_a8_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a8_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a8_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -809,6 +1025,7 @@
(define_bypass 8 "cortex_a8_neon_fp_vrecps_vrsqrts_ddd"
"cortex_a8_neon_int_1,\
cortex_a8_neon_int_4,\
+ cortex_a8_neon_bit_ops_q,\
cortex_a8_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a8_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a8_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -823,6 +1040,7 @@
(define_bypass 9 "cortex_a8_neon_fp_vmla_qqq_scalar"
"cortex_a8_neon_int_1,\
cortex_a8_neon_int_4,\
+ cortex_a8_neon_bit_ops_q,\
cortex_a8_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a8_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a8_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -837,6 +1055,7 @@
(define_bypass 8 "cortex_a8_neon_fp_vmla_ddd_scalar"
"cortex_a8_neon_int_1,\
cortex_a8_neon_int_4,\
+ cortex_a8_neon_bit_ops_q,\
cortex_a8_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a8_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a8_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -851,6 +1070,7 @@
(define_bypass 9 "cortex_a8_neon_fp_vmla_qqq"
"cortex_a8_neon_int_1,\
cortex_a8_neon_int_4,\
+ cortex_a8_neon_bit_ops_q,\
cortex_a8_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a8_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a8_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -865,6 +1085,7 @@
(define_bypass 8 "cortex_a8_neon_fp_vmla_ddd"
"cortex_a8_neon_int_1,\
cortex_a8_neon_int_4,\
+ cortex_a8_neon_bit_ops_q,\
cortex_a8_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a8_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a8_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -879,6 +1100,7 @@
(define_bypass 5 "cortex_a8_neon_fp_vmul_qqd"
"cortex_a8_neon_int_1,\
cortex_a8_neon_int_4,\
+ cortex_a8_neon_bit_ops_q,\
cortex_a8_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a8_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a8_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -893,6 +1115,7 @@
(define_bypass 4 "cortex_a8_neon_fp_vmul_ddd"
"cortex_a8_neon_int_1,\
cortex_a8_neon_int_4,\
+ cortex_a8_neon_bit_ops_q,\
cortex_a8_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a8_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a8_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -907,6 +1130,7 @@
(define_bypass 4 "cortex_a8_neon_fp_vsum"
"cortex_a8_neon_int_1,\
cortex_a8_neon_int_4,\
+ cortex_a8_neon_bit_ops_q,\
cortex_a8_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a8_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a8_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -921,6 +1145,7 @@
(define_bypass 5 "cortex_a8_neon_fp_vadd_qqq_vabs_qq"
"cortex_a8_neon_int_1,\
cortex_a8_neon_int_4,\
+ cortex_a8_neon_bit_ops_q,\
cortex_a8_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a8_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a8_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -935,6 +1160,7 @@
(define_bypass 4 "cortex_a8_neon_fp_vadd_ddd_vabs_dd"
"cortex_a8_neon_int_1,\
cortex_a8_neon_int_4,\
+ cortex_a8_neon_bit_ops_q,\
cortex_a8_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a8_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a8_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -949,6 +1175,7 @@
(define_bypass 5 "cortex_a8_neon_vsra_vrsra"
"cortex_a8_neon_int_1,\
cortex_a8_neon_int_4,\
+ cortex_a8_neon_bit_ops_q,\
cortex_a8_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a8_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a8_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -963,20 +1190,7 @@
(define_bypass 4 "cortex_a8_neon_vqshl_vrshl_vqrshl_qqq"
"cortex_a8_neon_int_1,\
cortex_a8_neon_int_4,\
- cortex_a8_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a8_neon_mul_qqq_8_16_32_ddd_32,\
- cortex_a8_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a8_neon_mla_qqq_8_16,\
- cortex_a8_neon_fp_vadd_ddd_vabs_dd,\
- cortex_a8_neon_fp_vadd_qqq_vabs_qq,\
- cortex_a8_neon_fp_vmla_ddd,\
- cortex_a8_neon_fp_vmla_qqq,\
- cortex_a8_neon_fp_vrecps_vrsqrts_ddd,\
- cortex_a8_neon_fp_vrecps_vrsqrts_qqq")
-
-(define_bypass 0 "cortex_a8_neon_vshl_ddd"
- "cortex_a8_neon_int_1,\
- cortex_a8_neon_int_4,\
+ cortex_a8_neon_bit_ops_q,\
cortex_a8_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a8_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a8_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -991,6 +1205,7 @@
(define_bypass 3 "cortex_a8_neon_shift_3"
"cortex_a8_neon_int_1,\
cortex_a8_neon_int_4,\
+ cortex_a8_neon_bit_ops_q,\
cortex_a8_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a8_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a8_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -1005,6 +1220,7 @@
(define_bypass 3 "cortex_a8_neon_shift_2"
"cortex_a8_neon_int_1,\
cortex_a8_neon_int_4,\
+ cortex_a8_neon_bit_ops_q,\
cortex_a8_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a8_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a8_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -1019,6 +1235,7 @@
(define_bypass 2 "cortex_a8_neon_shift_1"
"cortex_a8_neon_int_1,\
cortex_a8_neon_int_4,\
+ cortex_a8_neon_bit_ops_q,\
cortex_a8_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a8_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a8_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -1033,6 +1250,7 @@
(define_bypass 5 "cortex_a8_neon_mla_ddd_16_scalar_qdd_32_16_long_scalar"
"cortex_a8_neon_int_1,\
cortex_a8_neon_int_4,\
+ cortex_a8_neon_bit_ops_q,\
cortex_a8_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a8_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a8_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -1047,6 +1265,7 @@
(define_bypass 8 "cortex_a8_neon_mul_qqd_32_scalar"
"cortex_a8_neon_int_1,\
cortex_a8_neon_int_4,\
+ cortex_a8_neon_bit_ops_q,\
cortex_a8_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a8_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a8_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -1061,6 +1280,7 @@
(define_bypass 5 "cortex_a8_neon_mul_ddd_16_scalar_32_16_long_scalar"
"cortex_a8_neon_int_1,\
cortex_a8_neon_int_4,\
+ cortex_a8_neon_bit_ops_q,\
cortex_a8_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a8_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a8_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -1075,6 +1295,7 @@
(define_bypass 8 "cortex_a8_neon_mla_qqq_32_qqd_32_scalar"
"cortex_a8_neon_int_1,\
cortex_a8_neon_int_4,\
+ cortex_a8_neon_bit_ops_q,\
cortex_a8_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a8_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a8_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -1089,6 +1310,7 @@
(define_bypass 6 "cortex_a8_neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long"
"cortex_a8_neon_int_1,\
cortex_a8_neon_int_4,\
+ cortex_a8_neon_bit_ops_q,\
cortex_a8_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a8_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a8_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -1103,6 +1325,7 @@
(define_bypass 6 "cortex_a8_neon_mla_qqq_8_16"
"cortex_a8_neon_int_1,\
cortex_a8_neon_int_4,\
+ cortex_a8_neon_bit_ops_q,\
cortex_a8_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a8_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a8_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -1117,6 +1340,7 @@
(define_bypass 5 "cortex_a8_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long"
"cortex_a8_neon_int_1,\
cortex_a8_neon_int_4,\
+ cortex_a8_neon_bit_ops_q,\
cortex_a8_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a8_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a8_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -1131,6 +1355,7 @@
(define_bypass 6 "cortex_a8_neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar"
"cortex_a8_neon_int_1,\
cortex_a8_neon_int_4,\
+ cortex_a8_neon_bit_ops_q,\
cortex_a8_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a8_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a8_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -1145,6 +1370,7 @@
(define_bypass 6 "cortex_a8_neon_mul_qqq_8_16_32_ddd_32"
"cortex_a8_neon_int_1,\
cortex_a8_neon_int_4,\
+ cortex_a8_neon_bit_ops_q,\
cortex_a8_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a8_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a8_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -1159,20 +1385,7 @@
(define_bypass 5 "cortex_a8_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long"
"cortex_a8_neon_int_1,\
cortex_a8_neon_int_4,\
- cortex_a8_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a8_neon_mul_qqq_8_16_32_ddd_32,\
- cortex_a8_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a8_neon_mla_qqq_8_16,\
- cortex_a8_neon_fp_vadd_ddd_vabs_dd,\
- cortex_a8_neon_fp_vadd_qqq_vabs_qq,\
- cortex_a8_neon_fp_vmla_ddd,\
- cortex_a8_neon_fp_vmla_qqq,\
- cortex_a8_neon_fp_vrecps_vrsqrts_ddd,\
- cortex_a8_neon_fp_vrecps_vrsqrts_qqq")
-
-(define_bypass 5 "cortex_a8_neon_vsma"
- "cortex_a8_neon_int_1,\
- cortex_a8_neon_int_4,\
+ cortex_a8_neon_bit_ops_q,\
cortex_a8_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a8_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a8_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -1187,6 +1400,7 @@
(define_bypass 6 "cortex_a8_neon_vaba_qqq"
"cortex_a8_neon_int_1,\
cortex_a8_neon_int_4,\
+ cortex_a8_neon_bit_ops_q,\
cortex_a8_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a8_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a8_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -1201,6 +1415,7 @@
(define_bypass 5 "cortex_a8_neon_vaba"
"cortex_a8_neon_int_1,\
cortex_a8_neon_int_4,\
+ cortex_a8_neon_bit_ops_q,\
cortex_a8_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a8_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a8_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -1212,9 +1427,10 @@
cortex_a8_neon_fp_vrecps_vrsqrts_ddd,\
cortex_a8_neon_fp_vrecps_vrsqrts_qqq")
-(define_bypass 2 "cortex_a8_neon_vmov"
+(define_bypass 3 "cortex_a8_neon_bit_ops_q"
"cortex_a8_neon_int_1,\
cortex_a8_neon_int_4,\
+ cortex_a8_neon_bit_ops_q,\
cortex_a8_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a8_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a8_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -1229,6 +1445,7 @@
(define_bypass 3 "cortex_a8_neon_vqneg_vqabs"
"cortex_a8_neon_int_1,\
cortex_a8_neon_int_4,\
+ cortex_a8_neon_bit_ops_q,\
cortex_a8_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a8_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a8_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -1243,6 +1460,7 @@
(define_bypass 3 "cortex_a8_neon_int_5"
"cortex_a8_neon_int_1,\
cortex_a8_neon_int_4,\
+ cortex_a8_neon_bit_ops_q,\
cortex_a8_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a8_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a8_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -1257,6 +1475,7 @@
(define_bypass 3 "cortex_a8_neon_int_4"
"cortex_a8_neon_int_1,\
cortex_a8_neon_int_4,\
+ cortex_a8_neon_bit_ops_q,\
cortex_a8_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a8_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a8_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -1271,6 +1490,7 @@
(define_bypass 2 "cortex_a8_neon_int_3"
"cortex_a8_neon_int_1,\
cortex_a8_neon_int_4,\
+ cortex_a8_neon_bit_ops_q,\
cortex_a8_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a8_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a8_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -1285,6 +1505,7 @@
(define_bypass 2 "cortex_a8_neon_int_2"
"cortex_a8_neon_int_1,\
cortex_a8_neon_int_4,\
+ cortex_a8_neon_bit_ops_q,\
cortex_a8_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a8_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a8_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -1299,6 +1520,7 @@
(define_bypass 2 "cortex_a8_neon_int_1"
"cortex_a8_neon_int_1,\
cortex_a8_neon_int_4,\
+ cortex_a8_neon_bit_ops_q,\
cortex_a8_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a8_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a8_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
diff --git a/gcc/config/arm/cortex-a9-neon.md b/gcc/config/arm/cortex-a9-neon.md
index 2c9d5db5bd8..cd6b7a4fd36 100644
--- a/gcc/config/arm/cortex-a9-neon.md
+++ b/gcc/config/arm/cortex-a9-neon.md
@@ -19,6 +19,220 @@
;; along with GCC; see the file COPYING3. If not see
;; <http://www.gnu.org/licenses/>.
+(define_attr "cortex_a9_neon_type"
+ "neon_int_1,neon_int_2,neon_int_3,neon_int_4,neon_int_5,neon_vqneg_vqabs,
+ neon_bit_ops_q,
+ neon_vaba,neon_vaba_qqq, neon_vmov,
+ neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,neon_mul_qqq_8_16_32_ddd_32,
+ neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar,
+ neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,neon_mla_qqq_8_16,
+ neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long,
+ neon_mla_qqq_32_qqd_32_scalar,neon_mul_ddd_16_scalar_32_16_long_scalar,
+ neon_mul_qqd_32_scalar,neon_mla_ddd_16_scalar_qdd_32_16_long_scalar,
+ neon_shift_1,neon_shift_2,neon_shift_3,
+ neon_vqshl_vrshl_vqrshl_qqq,neon_vsra_vrsra,neon_fp_vadd_ddd_vabs_dd,
+ neon_fp_vadd_qqq_vabs_qq,neon_fp_vsum,neon_fp_vmul_ddd,neon_fp_vmul_qqd,
+ neon_fp_vmla_ddd,neon_fp_vmla_qqq,neon_fp_vmla_ddd_scalar,
+ neon_fp_vmla_qqq_scalar,neon_fp_vrecps_vrsqrts_ddd,
+ neon_fp_vrecps_vrsqrts_qqq,neon_bp_simple,neon_bp_2cycle,neon_bp_3cycle,
+ neon_ldr,neon_str,neon_vld1_1_2_regs,neon_vld1_3_4_regs,
+ neon_vld2_2_regs_vld1_vld2_all_lanes,neon_vld2_4_regs,neon_vld3_vld4,
+ neon_vst1_1_2_regs_vst2_2_regs,neon_vst1_3_4_regs,
+ neon_vst2_4_regs_vst3_vst4,neon_vld1_vld2_lane,
+ neon_vld3_vld4_lane,neon_vst1_vst2_lane,neon_vst3_vst4_lane,
+ neon_vld3_vld4_all_lanes,neon_mcr,neon_mcr_2_mcrr,neon_mrc,neon_mrrc,
+ neon_ldm_2,neon_stm_2,none,unknown"
+ (cond [
+ (eq_attr "type" "neon_logic, neon_logic_q,\
+ neon_bsl, neon_cls, neon_cnt,\
+ neon_add, neon_add_q")
+ (const_string "neon_int_1")
+ (eq_attr "type" "neon_add_widen, neon_sub_widen,\
+ neon_sub, neon_sub_q")
+ (const_string "neon_int_2")
+ (eq_attr "type" "neon_neg, neon_neg_q,\
+ neon_reduc_add, neon_reduc_add_q,\
+ neon_reduc_add_long,\
+ neon_add_long, neon_sub_long")
+ (const_string "neon_int_3")
+ (eq_attr "type" "neon_abs, neon_abs_q,
+ neon_compare_zero, neon_compare_zero_q,\
+ neon_add_halve_narrow_q,\
+ neon_sub_halve_narrow_q,\
+ neon_add_halve, neon_add_halve_q,\
+ neon_qadd, neon_qadd_q,\
+ neon_tst, neon_tst_q")
+ (const_string "neon_int_4")
+ (eq_attr "type" "neon_abd_long, neon_sub_halve, neon_sub_halve_q,\
+ neon_qsub, neon_qsub_q,\
+ neon_abd, neon_abd_q,\
+ neon_compare, neon_compare_q,\
+ neon_minmax, neon_minmax_q, neon_reduc_minmax,\
+ neon_reduc_minmax_q")
+ (const_string "neon_int_5")
+ (eq_attr "type" "neon_qneg, neon_qneg_q, neon_qabs, neon_qabs_q")
+ (const_string "neon_vqneg_vqabs")
+ (eq_attr "type" "neon_move, neon_move_q")
+ (const_string "neon_vmov")
+ (eq_attr "type" "neon_bsl_q, neon_cls_q, neon_cnt_q")
+ (const_string "neon_bit_ops_q")
+ (eq_attr "type" "neon_arith_acc, neon_reduc_add_acc")
+ (const_string "neon_vaba")
+ (eq_attr "type" "neon_arith_acc_q")
+ (const_string "neon_vaba_qqq")
+ (eq_attr "type" "neon_shift_imm, neon_shift_imm_q,\
+ neon_shift_imm_long, neon_shift_imm_narrow_q,\
+ neon_shift_reg")
+ (const_string "neon_shift_1")
+ (eq_attr "type" "neon_sat_shift_imm, neon_sat_shift_imm_q,
+ neon_sat_shift_imm_narrow_q,\
+ neon_sat_shift_reg")
+ (const_string "neon_shift_2")
+ (eq_attr "type" "neon_shift_reg_q")
+ (const_string "neon_shift_3")
+ (eq_attr "type" "neon_sat_shift_reg_q")
+ (const_string "neon_vqshl_vrshl_vqrshl_qqq")
+ (eq_attr "type" "neon_shift_acc, neon_shift_acc_q")
+ (const_string "neon_vsra_vrsra")
+ (eq_attr "type" "neon_mul_b, neon_mul_h,\
+ neon_mul_b_long, neon_mul_h_long,\
+ neon_sat_mul_b, neon_sat_mul_h,\
+ neon_sat_mul_b_long, neon_sat_mul_h_long")
+ (const_string
+ "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long")
+ (eq_attr "type" "neon_mul_b_q, neon_mul_h_q,\
+ neon_sat_mul_b_q, neon_sat_mul_h_q")
+ (const_string "neon_mul_qqq_8_16_32_ddd_32")
+ (eq_attr "type" "neon_mul_s, neon_mul_s_long,\
+ neon_sat_mul_s, neon_sat_mul_s_long,\
+ neon_mul_h_scalar_q, neon_sat_mul_h_scalar_q,\
+ neon_mul_s_scalar, neon_sat_mul_s_scalar,\
+ neon_mul_s_scalar_long,\
+ neon_sat_mul_s_scalar_long")
+ (const_string
+ "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")
+ (eq_attr "type" "neon_mla_b, neon_mla_h,\
+ neon_mla_b_long, neon_mla_h_long,\
+ neon_sat_mla_b_long, neon_sat_mla_h_long,\
+ neon_sat_mla_h_scalar_long")
+ (const_string
+ "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
+ (eq_attr "type" "neon_mla_b_q, neon_mla_h_q")
+ (const_string "neon_mla_qqq_8_16")
+ (eq_attr "type" "neon_mla_s, neon_mla_s_long,\
+ neon_sat_mla_s_long,\
+ neon_mla_h_scalar_q, neon_mla_s_scalar,\
+ neon_mla_s_scalar_long,\
+ neon_sat_mla_s_scalar_long")
+ (const_string
+ "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")
+ (eq_attr "type" "neon_mla_s_q, neon_mla_s_scalar_q")
+ (const_string "neon_mla_qqq_32_qqd_32_scalar")
+ (eq_attr "type" "neon_mul_h_scalar, neon_sat_mul_h_scalar,\
+ neon_mul_h_scalar_long,\
+ neon_sat_mul_h_scalar_long")
+ (const_string
+ "neon_mul_ddd_16_scalar_32_16_long_scalar")
+ (eq_attr "type" "neon_mul_s_q, neon_sat_mul_s_q,\
+ neon_mul_s_scalar_q")
+ (const_string "neon_mul_qqd_32_scalar")
+ (eq_attr "type" "neon_mla_h_scalar, neon_mla_h_scalar_long")
+ (const_string
+ "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar")
+ (eq_attr "type" "neon_fp_abd_s, neon_fp_abs_s, neon_fp_neg_s,\
+ neon_fp_addsub_s, neon_fp_compare_s,\
+ neon_fp_minmax_s, neon_fp_mul_s,\
+ neon_fp_recpe_s, neon_fp_rsqrte_s,\
+ neon_fp_to_int_s, neon_int_to_fp_s")
+ (const_string "neon_fp_vadd_ddd_vabs_dd")
+ (eq_attr "type" "neon_fp_abd_s_q, neon_fp_abs_s_q,\
+ neon_fp_neg_s_q,\
+ neon_fp_addsub_s_q, neon_fp_compare_s_q,\
+ neon_fp_minmax_s_q, neon_fp_mul_s_q,\
+ neon_fp_recpe_s_q, neon_fp_rsqrte_s_q,\
+ neon_fp_to_int_s_q, neon_int_to_fp_s_q")
+ (const_string "neon_fp_vadd_qqq_vabs_qq")
+ (eq_attr "type" "neon_fp_reduc_add_s, neon_fp_reduc_minmax_s,\
+ neon_fp_reduc_add_s_q, neon_fp_reduc_minmax_s_q")
+ (const_string "neon_fp_vsum")
+ (eq_attr "type" "neon_fp_mul_s_scalar")
+ (const_string "neon_fp_vmul_ddd")
+ (eq_attr "type" "neon_fp_mul_s_scalar_q")
+ (const_string "neon_fp_vmul_qqd")
+ (eq_attr "type" "neon_fp_mla_s")
+ (const_string "neon_fp_vmla_ddd")
+ (eq_attr "type" "neon_fp_mla_s_q")
+ (const_string "neon_fp_vmla_qqq")
+ (eq_attr "type" "neon_fp_mla_s_scalar")
+ (const_string "neon_fp_vmla_ddd_scalar")
+ (eq_attr "type" "neon_fp_mla_s_scalar_q")
+ (const_string "neon_fp_vmla_qqq_scalar")
+ (eq_attr "type" "neon_fp_recps_s, neon_fp_rsqrts_s")
+ (const_string "neon_fp_vrecps_vrsqrts_ddd")
+ (eq_attr "type" "neon_fp_recps_s_q, neon_fp_rsqrts_s_q")
+ (const_string "neon_fp_vrecps_vrsqrts_qqq")
+ (eq_attr "type" "neon_move_narrow_q, neon_dup,\
+ neon_dup_q, neon_permute, neon_zip,\
+ neon_ext, neon_rev, neon_rev_q")
+ (const_string "neon_bp_simple")
+ (eq_attr "type" "neon_permute_q, neon_ext_q, neon_tbl1, neon_tbl2")
+ (const_string "neon_bp_2cycle")
+ (eq_attr "type" "neon_zip_q, neon_tbl3, neon_tbl4")
+ (const_string "neon_bp_3cycle")
+ (eq_attr "type" "neon_ldr")
+ (const_string "neon_ldr")
+ (eq_attr "type" "neon_str")
+ (const_string "neon_str")
+ (eq_attr "type" "neon_load1_1reg, neon_load1_1reg_q,\
+ neon_load1_2reg, neon_load1_2reg_q,\
+ neon_load2_2reg, neon_load2_2reg_q")
+ (const_string "neon_vld1_1_2_regs")
+ (eq_attr "type" "neon_load1_3reg, neon_load1_3reg_q,\
+ neon_load1_4reg, neon_load1_4reg_q")
+ (const_string "neon_vld1_3_4_regs")
+ (eq_attr "type" "neon_load1_all_lanes, neon_load1_all_lanes_q,\
+ neon_load2_all_lanes, neon_load2_all_lanes_q")
+ (const_string
+ "neon_vld2_2_regs_vld1_vld2_all_lanes")
+ (eq_attr "type" "neon_load3_all_lanes, neon_load3_all_lanes_q,\
+ neon_load4_all_lanes, neon_load4_all_lanes_q,\
+ neon_load2_4reg, neon_load2_4reg_q")
+ (const_string "neon_vld2_4_regs")
+ (eq_attr "type" "neon_load3_3reg, neon_load3_3reg_q,\
+ neon_load4_4reg, neon_load4_4reg_q")
+ (const_string "neon_vld3_vld4")
+ (eq_attr "type" "neon_load1_one_lane, neon_load1_one_lane_q,\
+ neon_load2_one_lane, neon_load2_one_lane_q")
+ (const_string "neon_vld1_vld2_lane")
+ (eq_attr "type" "neon_load3_one_lane, neon_load3_one_lane_q,\
+ neon_load4_one_lane, neon_load4_one_lane_q")
+ (const_string "neon_vld3_vld4_lane")
+ (eq_attr "type" "neon_store1_1reg, neon_store1_1reg_q,\
+ neon_store1_2reg, neon_store1_2reg_q,\
+ neon_store2_2reg, neon_store2_2reg_q")
+ (const_string "neon_vst1_1_2_regs_vst2_2_regs")
+ (eq_attr "type" "neon_store1_3reg, neon_store1_3reg_q,\
+ neon_store1_4reg, neon_store1_4reg_q")
+ (const_string "neon_vst1_3_4_regs")
+ (eq_attr "type" "neon_store2_4reg, neon_store2_4reg_q,\
+ neon_store3_3reg, neon_store3_3reg_q,\
+ neon_store4_4reg, neon_store4_4reg_q")
+ (const_string "neon_vst2_4_regs_vst3_vst4")
+ (eq_attr "type" "neon_store1_one_lane, neon_store1_one_lane_q,\
+ neon_store2_one_lane, neon_store2_one_lane_q")
+ (const_string "neon_vst1_vst2_lane")
+ (eq_attr "type" "neon_store3_one_lane, neon_store3_one_lane_q,\
+ neon_store4_one_lane, neon_store4_one_lane_q")
+ (const_string "neon_vst3_vst4_lane")
+ (eq_attr "type" "neon_from_gp")
+ (const_string "neon_mcr")
+ (eq_attr "type" "neon_from_gp_q")
+ (const_string "neon_mcr_2_mcrr")
+ (eq_attr "type" "neon_to_gp")
+ (const_string "neon_mrc")
+ (eq_attr "type" "neon_to_gp_q")
+ (const_string "neon_mrrc")]
+ (const_string "unknown")))
(define_automaton "cortex_a9_neon")
@@ -105,74 +319,71 @@
cortex_a9_neon_issue_fadd,\
cortex_a9_neon_issue_fadd")
-
;; NEON -> core transfers.
(define_insn_reservation "ca9_neon_mrc" 1
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_mrc"))
+ (eq_attr "cortex_a9_neon_type" "neon_mrc"))
"ca9_issue_vfp_neon + cortex_a9_neon_mcr")
(define_insn_reservation "ca9_neon_mrrc" 1
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_mrrc"))
+ (eq_attr "cortex_a9_neon_type" "neon_mrrc"))
"ca9_issue_vfp_neon + cortex_a9_neon_mcr")
-;; The remainder of this file is auto-generated by neon-schedgen.
-
;; Instructions using this reservation read their source operands at N2, and
;; produce a result at N3.
(define_insn_reservation "cortex_a9_neon_int_1" 3
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_int_1"))
+ (eq_attr "cortex_a9_neon_type" "neon_int_1"))
"cortex_a9_neon_dp")
;; Instructions using this reservation read their (D|Q)m operands at N1,
;; their (D|Q)n operands at N2, and produce a result at N3.
(define_insn_reservation "cortex_a9_neon_int_2" 3
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_int_2"))
+ (eq_attr "cortex_a9_neon_type" "neon_int_2"))
"cortex_a9_neon_dp")
;; Instructions using this reservation read their source operands at N1, and
;; produce a result at N3.
(define_insn_reservation "cortex_a9_neon_int_3" 3
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_int_3"))
- "cortex_a9_neon_dp")
+ (eq_attr "cortex_a9_neon_type" "neon_int_3"))
+ "cortex_a9_neon_dp")
;; Instructions using this reservation read their source operands at N2, and
;; produce a result at N4.
(define_insn_reservation "cortex_a9_neon_int_4" 4
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_int_4"))
+ (eq_attr "cortex_a9_neon_type" "neon_int_4"))
"cortex_a9_neon_dp")
;; Instructions using this reservation read their (D|Q)m operands at N1,
;; their (D|Q)n operands at N2, and produce a result at N4.
(define_insn_reservation "cortex_a9_neon_int_5" 4
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_int_5"))
+ (eq_attr "cortex_a9_neon_type" "neon_int_5"))
"cortex_a9_neon_dp")
;; Instructions using this reservation read their source operands at N1, and
;; produce a result at N4.
(define_insn_reservation "cortex_a9_neon_vqneg_vqabs" 4
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_vqneg_vqabs"))
- "cortex_a9_neon_dp")
+ (eq_attr "cortex_a9_neon_type" "neon_vqneg_vqabs"))
+ "cortex_a9_neon_dp")
;; Instructions using this reservation produce a result at N3.
(define_insn_reservation "cortex_a9_neon_vmov" 3
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_vmov"))
- "cortex_a9_neon_dp")
+ (eq_attr "cortex_a9_neon_type" "neon_vmov"))
+ "cortex_a8_neon_dp")
;; Instructions using this reservation read their (D|Q)n operands at N2,
;; their (D|Q)m operands at N1, their (D|Q)d operands at N3, and
;; produce a result at N6.
(define_insn_reservation "cortex_a9_neon_vaba" 6
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_vaba"))
+ (eq_attr "cortex_a9_neon_type" "neon_vaba"))
"cortex_a9_neon_dp")
;; Instructions using this reservation read their (D|Q)n operands at N2,
@@ -180,35 +391,35 @@
;; produce a result at N6 on cycle 2.
(define_insn_reservation "cortex_a9_neon_vaba_qqq" 7
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_vaba_qqq"))
+ (eq_attr "cortex_a9_neon_type" "neon_vaba_qqq"))
"cortex_a9_neon_dp_2")
-;; Instructions using this reservation read their (D|Q)m operands at N1,
-;; their (D|Q)d operands at N3, and produce a result at N6.
-(define_insn_reservation "cortex_a9_neon_vsma" 6
+;; Instructions using this reservation read their source operands at N2, and
+;; produce a result at N3 on cycle 2.
+(define_insn_reservation "cortex_a9_neon_bit_ops_q" 4
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_vsma"))
- "cortex_a9_neon_dp")
+ (eq_attr "cortex_a9_neon_type" "neon_bit_ops_q"))
+ "cortex_a9_neon_dp_2")
;; Instructions using this reservation read their source operands at N2, and
;; produce a result at N6.
(define_insn_reservation "cortex_a9_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long" 6
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long"))
+ (eq_attr "cortex_a9_neon_type" "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long"))
"cortex_a9_neon_dp")
;; Instructions using this reservation read their source operands at N2, and
;; produce a result at N6 on cycle 2.
(define_insn_reservation "cortex_a9_neon_mul_qqq_8_16_32_ddd_32" 7
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_mul_qqq_8_16_32_ddd_32"))
+ (eq_attr "cortex_a9_neon_type" "neon_mul_qqq_8_16_32_ddd_32"))
"cortex_a9_neon_dp_2")
;; Instructions using this reservation read their (D|Q)n operands at N2,
;; their (D|Q)m operands at N1, and produce a result at N6 on cycle 2.
(define_insn_reservation "cortex_a9_neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar" 7
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar"))
+ (eq_attr "cortex_a9_neon_type" "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar"))
"cortex_a9_neon_dp_2")
;; Instructions using this reservation read their (D|Q)n operands at N2,
@@ -216,7 +427,7 @@
;; produce a result at N6.
(define_insn_reservation "cortex_a9_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long" 6
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long"))
+ (eq_attr "cortex_a9_neon_type" "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long"))
"cortex_a9_neon_dp")
;; Instructions using this reservation read their (D|Q)n operands at N2,
@@ -224,7 +435,7 @@
;; produce a result at N6 on cycle 2.
(define_insn_reservation "cortex_a9_neon_mla_qqq_8_16" 7
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_mla_qqq_8_16"))
+ (eq_attr "cortex_a9_neon_type" "neon_mla_qqq_8_16"))
"cortex_a9_neon_dp_2")
;; Instructions using this reservation read their (D|Q)n operands at N2,
@@ -232,7 +443,7 @@
;; produce a result at N6 on cycle 2.
(define_insn_reservation "cortex_a9_neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long" 7
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long"))
+ (eq_attr "cortex_a9_neon_type" "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long"))
"cortex_a9_neon_dp_2")
;; Instructions using this reservation read their (D|Q)n operands at N2,
@@ -240,21 +451,21 @@
;; produce a result at N6 on cycle 4.
(define_insn_reservation "cortex_a9_neon_mla_qqq_32_qqd_32_scalar" 9
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_mla_qqq_32_qqd_32_scalar"))
+ (eq_attr "cortex_a9_neon_type" "neon_mla_qqq_32_qqd_32_scalar"))
"cortex_a9_neon_dp_4")
;; Instructions using this reservation read their (D|Q)n operands at N2,
;; their (D|Q)m operands at N1, and produce a result at N6.
(define_insn_reservation "cortex_a9_neon_mul_ddd_16_scalar_32_16_long_scalar" 6
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_mul_ddd_16_scalar_32_16_long_scalar"))
+ (eq_attr "cortex_a9_neon_type" "neon_mul_ddd_16_scalar_32_16_long_scalar"))
"cortex_a9_neon_dp")
;; Instructions using this reservation read their (D|Q)n operands at N2,
;; their (D|Q)m operands at N1, and produce a result at N6 on cycle 4.
(define_insn_reservation "cortex_a9_neon_mul_qqd_32_scalar" 9
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_mul_qqd_32_scalar"))
+ (eq_attr "cortex_a9_neon_type" "neon_mul_qqd_32_scalar"))
"cortex_a9_neon_dp_4")
;; Instructions using this reservation read their (D|Q)n operands at N2,
@@ -262,84 +473,77 @@
;; produce a result at N6.
(define_insn_reservation "cortex_a9_neon_mla_ddd_16_scalar_qdd_32_16_long_scalar" 6
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar"))
+ (eq_attr "cortex_a9_neon_type" "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar"))
"cortex_a9_neon_dp")
;; Instructions using this reservation read their source operands at N1, and
;; produce a result at N3.
(define_insn_reservation "cortex_a9_neon_shift_1" 3
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_shift_1"))
+ (eq_attr "cortex_a9_neon_type" "neon_shift_1"))
"cortex_a9_neon_dp")
;; Instructions using this reservation read their source operands at N1, and
;; produce a result at N4.
(define_insn_reservation "cortex_a9_neon_shift_2" 4
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_shift_2"))
+ (eq_attr "cortex_a9_neon_type" "neon_shift_2"))
"cortex_a9_neon_dp")
;; Instructions using this reservation read their source operands at N1, and
;; produce a result at N3 on cycle 2.
(define_insn_reservation "cortex_a9_neon_shift_3" 4
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_shift_3"))
+ (eq_attr "cortex_a9_neon_type" "neon_shift_3"))
"cortex_a9_neon_dp_2")
;; Instructions using this reservation read their source operands at N1, and
-;; produce a result at N1.
-(define_insn_reservation "cortex_a9_neon_vshl_ddd" 1
- (and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_vshl_ddd"))
- "cortex_a9_neon_dp")
-
-;; Instructions using this reservation read their source operands at N1, and
;; produce a result at N4 on cycle 2.
(define_insn_reservation "cortex_a9_neon_vqshl_vrshl_vqrshl_qqq" 5
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_vqshl_vrshl_vqrshl_qqq"))
+ (eq_attr "cortex_a9_neon_type" "neon_vqshl_vrshl_vqrshl_qqq"))
"cortex_a9_neon_dp_2")
;; Instructions using this reservation read their (D|Q)m operands at N1,
;; their (D|Q)d operands at N3, and produce a result at N6.
(define_insn_reservation "cortex_a9_neon_vsra_vrsra" 6
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_vsra_vrsra"))
+ (eq_attr "cortex_a9_neon_type" "neon_vsra_vrsra"))
"cortex_a9_neon_dp")
;; Instructions using this reservation read their source operands at N2, and
;; produce a result at N5.
(define_insn_reservation "cortex_a9_neon_fp_vadd_ddd_vabs_dd" 5
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_fp_vadd_ddd_vabs_dd"))
+ (eq_attr "cortex_a9_neon_type" "neon_fp_vadd_ddd_vabs_dd"))
"cortex_a9_neon_fadd")
;; Instructions using this reservation read their source operands at N2, and
;; produce a result at N5 on cycle 2.
(define_insn_reservation "cortex_a9_neon_fp_vadd_qqq_vabs_qq" 6
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_fp_vadd_qqq_vabs_qq"))
+ (eq_attr "cortex_a9_neon_type" "neon_fp_vadd_qqq_vabs_qq"))
"cortex_a9_neon_fadd_2")
;; Instructions using this reservation read their source operands at N1, and
;; produce a result at N5.
(define_insn_reservation "cortex_a9_neon_fp_vsum" 5
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_fp_vsum"))
+ (eq_attr "cortex_a9_neon_type" "neon_fp_vsum"))
"cortex_a9_neon_fadd")
;; Instructions using this reservation read their (D|Q)n operands at N2,
;; their (D|Q)m operands at N1, and produce a result at N5.
(define_insn_reservation "cortex_a9_neon_fp_vmul_ddd" 5
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_fp_vmul_ddd"))
+ (eq_attr "cortex_a9_neon_type" "neon_fp_vmul_ddd"))
"cortex_a9_neon_dp")
;; Instructions using this reservation read their (D|Q)n operands at N2,
;; their (D|Q)m operands at N1, and produce a result at N5 on cycle 2.
(define_insn_reservation "cortex_a9_neon_fp_vmul_qqd" 6
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_fp_vmul_qqd"))
+ (eq_attr "cortex_a9_neon_type" "neon_fp_vmul_qqd"))
"cortex_a9_neon_dp_2")
;; Instructions using this reservation read their (D|Q)n operands at N2,
@@ -347,7 +551,7 @@
;; produce a result at N9.
(define_insn_reservation "cortex_a9_neon_fp_vmla_ddd" 9
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_fp_vmla_ddd"))
+ (eq_attr "cortex_a9_neon_type" "neon_fp_vmla_ddd"))
"cortex_a9_neon_fmul_then_fadd")
;; Instructions using this reservation read their (D|Q)n operands at N2,
@@ -355,7 +559,7 @@
;; produce a result at N9 on cycle 2.
(define_insn_reservation "cortex_a9_neon_fp_vmla_qqq" 10
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_fp_vmla_qqq"))
+ (eq_attr "cortex_a9_neon_type" "neon_fp_vmla_qqq"))
"cortex_a9_neon_fmul_then_fadd_2")
;; Instructions using this reservation read their (D|Q)n operands at N2,
@@ -363,7 +567,7 @@
;; produce a result at N9.
(define_insn_reservation "cortex_a9_neon_fp_vmla_ddd_scalar" 9
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_fp_vmla_ddd_scalar"))
+ (eq_attr "cortex_a9_neon_type" "neon_fp_vmla_ddd_scalar"))
"cortex_a9_neon_fmul_then_fadd")
;; Instructions using this reservation read their (D|Q)n operands at N2,
@@ -371,152 +575,146 @@
;; produce a result at N9 on cycle 2.
(define_insn_reservation "cortex_a9_neon_fp_vmla_qqq_scalar" 10
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_fp_vmla_qqq_scalar"))
+ (eq_attr "cortex_a9_neon_type" "neon_fp_vmla_qqq_scalar"))
"cortex_a9_neon_fmul_then_fadd_2")
;; Instructions using this reservation read their source operands at N2, and
;; produce a result at N9.
(define_insn_reservation "cortex_a9_neon_fp_vrecps_vrsqrts_ddd" 9
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_fp_vrecps_vrsqrts_ddd"))
+ (eq_attr "cortex_a9_neon_type" "neon_fp_vrecps_vrsqrts_ddd"))
"cortex_a9_neon_fmul_then_fadd")
;; Instructions using this reservation read their source operands at N2, and
;; produce a result at N9 on cycle 2.
(define_insn_reservation "cortex_a9_neon_fp_vrecps_vrsqrts_qqq" 10
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_fp_vrecps_vrsqrts_qqq"))
+ (eq_attr "cortex_a9_neon_type" "neon_fp_vrecps_vrsqrts_qqq"))
"cortex_a9_neon_fmul_then_fadd_2")
;; Instructions using this reservation read their source operands at N1, and
;; produce a result at N2.
(define_insn_reservation "cortex_a9_neon_bp_simple" 2
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_bp_simple"))
+ (eq_attr "cortex_a9_neon_type" "neon_bp_simple"))
"cortex_a9_neon_perm")
;; Instructions using this reservation read their source operands at N1, and
;; produce a result at N2 on cycle 2.
(define_insn_reservation "cortex_a9_neon_bp_2cycle" 3
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_bp_2cycle"))
+ (eq_attr "cortex_a9_neon_type" "neon_bp_2cycle"))
"cortex_a9_neon_perm_2")
;; Instructions using this reservation read their source operands at N1, and
;; produce a result at N2 on cycle 3.
(define_insn_reservation "cortex_a9_neon_bp_3cycle" 4
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_bp_3cycle"))
+ (eq_attr "cortex_a9_neon_type" "neon_bp_3cycle"))
"cortex_a9_neon_perm_3")
;; Instructions using this reservation produce a result at N1.
(define_insn_reservation "cortex_a9_neon_ldr" 1
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_ldr"))
+ (eq_attr "cortex_a9_neon_type" "neon_ldr"))
"cortex_a9_neon_ls")
;; Instructions using this reservation read their source operands at N1.
(define_insn_reservation "cortex_a9_neon_str" 0
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_str"))
+ (eq_attr "cortex_a9_neon_type" "neon_str"))
"cortex_a9_neon_ls")
;; Instructions using this reservation produce a result at N1 on cycle 2.
(define_insn_reservation "cortex_a9_neon_vld1_1_2_regs" 2
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_vld1_1_2_regs"))
+ (eq_attr "cortex_a9_neon_type" "neon_vld1_1_2_regs"))
"cortex_a9_neon_ls_2")
;; Instructions using this reservation produce a result at N1 on cycle 3.
(define_insn_reservation "cortex_a9_neon_vld1_3_4_regs" 3
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_vld1_3_4_regs"))
+ (eq_attr "cortex_a9_neon_type" "neon_vld1_3_4_regs"))
"cortex_a9_neon_ls_3")
;; Instructions using this reservation produce a result at N2 on cycle 2.
(define_insn_reservation "cortex_a9_neon_vld2_2_regs_vld1_vld2_all_lanes" 3
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_vld2_2_regs_vld1_vld2_all_lanes"))
+ (eq_attr "cortex_a9_neon_type" "neon_vld2_2_regs_vld1_vld2_all_lanes"))
"cortex_a9_neon_ls_2")
;; Instructions using this reservation produce a result at N2 on cycle 3.
(define_insn_reservation "cortex_a9_neon_vld2_4_regs" 4
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_vld2_4_regs"))
+ (eq_attr "cortex_a9_neon_type" "neon_vld2_4_regs"))
"cortex_a9_neon_ls_3")
;; Instructions using this reservation produce a result at N2 on cycle 4.
(define_insn_reservation "cortex_a9_neon_vld3_vld4" 5
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_vld3_vld4"))
+ (eq_attr "cortex_a9_neon_type" "neon_vld3_vld4"))
"cortex_a9_neon_ls_4")
;; Instructions using this reservation read their source operands at N1.
(define_insn_reservation "cortex_a9_neon_vst1_1_2_regs_vst2_2_regs" 0
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_vst1_1_2_regs_vst2_2_regs"))
+ (eq_attr "cortex_a9_neon_type" "neon_vst1_1_2_regs_vst2_2_regs"))
"cortex_a9_neon_ls_2")
;; Instructions using this reservation read their source operands at N1.
(define_insn_reservation "cortex_a9_neon_vst1_3_4_regs" 0
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_vst1_3_4_regs"))
+ (eq_attr "cortex_a9_neon_type" "neon_vst1_3_4_regs"))
"cortex_a9_neon_ls_3")
;; Instructions using this reservation read their source operands at N1.
(define_insn_reservation "cortex_a9_neon_vst2_4_regs_vst3_vst4" 0
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_vst2_4_regs_vst3_vst4"))
- "cortex_a9_neon_ls_4")
-
-;; Instructions using this reservation read their source operands at N1.
-(define_insn_reservation "cortex_a9_neon_vst3_vst4" 0
- (and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_vst3_vst4"))
+ (eq_attr "cortex_a9_neon_type" "neon_vst2_4_regs_vst3_vst4"))
"cortex_a9_neon_ls_4")
;; Instructions using this reservation read their source operands at N1, and
;; produce a result at N2 on cycle 3.
(define_insn_reservation "cortex_a9_neon_vld1_vld2_lane" 4
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_vld1_vld2_lane"))
+ (eq_attr "cortex_a9_neon_type" "neon_vld1_vld2_lane"))
"cortex_a9_neon_ls_3")
;; Instructions using this reservation read their source operands at N1, and
;; produce a result at N2 on cycle 5.
(define_insn_reservation "cortex_a9_neon_vld3_vld4_lane" 6
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_vld3_vld4_lane"))
+ (eq_attr "cortex_a9_neon_type" "neon_vld3_vld4_lane"))
"cortex_a9_neon_ls_5")
;; Instructions using this reservation read their source operands at N1.
(define_insn_reservation "cortex_a9_neon_vst1_vst2_lane" 0
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_vst1_vst2_lane"))
+ (eq_attr "cortex_a9_neon_type" "neon_vst1_vst2_lane"))
"cortex_a9_neon_ls_2")
;; Instructions using this reservation read their source operands at N1.
(define_insn_reservation "cortex_a9_neon_vst3_vst4_lane" 0
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_vst3_vst4_lane"))
+ (eq_attr "cortex_a9_neon_type" "neon_vst3_vst4_lane"))
"cortex_a9_neon_ls_3")
;; Instructions using this reservation produce a result at N2 on cycle 2.
(define_insn_reservation "cortex_a9_neon_vld3_vld4_all_lanes" 3
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_vld3_vld4_all_lanes"))
+ (eq_attr "cortex_a9_neon_type" "neon_vld3_vld4_all_lanes"))
"cortex_a9_neon_ls_3")
;; Instructions using this reservation produce a result at N2.
(define_insn_reservation "cortex_a9_neon_mcr" 2
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_mcr"))
+ (eq_attr "cortex_a9_neon_type" "neon_mcr"))
"cortex_a9_neon_perm")
;; Instructions using this reservation produce a result at N2.
(define_insn_reservation "cortex_a9_neon_mcr_2_mcrr" 2
(and (eq_attr "tune" "cortexa9")
- (eq_attr "type" "neon_mcr_2_mcrr"))
+ (eq_attr "cortex_a9_neon_type" "neon_mcr_2_mcrr"))
"cortex_a9_neon_perm_2")
;; Exceptions to the default latencies.
@@ -524,6 +722,7 @@
(define_bypass 1 "cortex_a9_neon_mcr_2_mcrr"
"cortex_a9_neon_int_1,\
cortex_a9_neon_int_4,\
+ cortex_a9_neon_bit_ops_q,\
cortex_a9_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a9_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a9_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -538,6 +737,7 @@
(define_bypass 1 "cortex_a9_neon_mcr"
"cortex_a9_neon_int_1,\
cortex_a9_neon_int_4,\
+ cortex_a9_neon_bit_ops_q,\
cortex_a9_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a9_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a9_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -552,6 +752,7 @@
(define_bypass 2 "cortex_a9_neon_vld3_vld4_all_lanes"
"cortex_a9_neon_int_1,\
cortex_a9_neon_int_4,\
+ cortex_a9_neon_bit_ops_q,\
cortex_a9_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a9_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a9_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -566,6 +767,7 @@
(define_bypass 5 "cortex_a9_neon_vld3_vld4_lane"
"cortex_a9_neon_int_1,\
cortex_a9_neon_int_4,\
+ cortex_a9_neon_bit_ops_q,\
cortex_a9_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a9_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a9_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -580,6 +782,7 @@
(define_bypass 3 "cortex_a9_neon_vld1_vld2_lane"
"cortex_a9_neon_int_1,\
cortex_a9_neon_int_4,\
+ cortex_a9_neon_bit_ops_q,\
cortex_a9_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a9_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a9_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -594,6 +797,7 @@
(define_bypass 4 "cortex_a9_neon_vld3_vld4"
"cortex_a9_neon_int_1,\
cortex_a9_neon_int_4,\
+ cortex_a9_neon_bit_ops_q,\
cortex_a9_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a9_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a9_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -608,6 +812,7 @@
(define_bypass 3 "cortex_a9_neon_vld2_4_regs"
"cortex_a9_neon_int_1,\
cortex_a9_neon_int_4,\
+ cortex_a9_neon_bit_ops_q,\
cortex_a9_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a9_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a9_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -622,6 +827,7 @@
(define_bypass 2 "cortex_a9_neon_vld2_2_regs_vld1_vld2_all_lanes"
"cortex_a9_neon_int_1,\
cortex_a9_neon_int_4,\
+ cortex_a9_neon_bit_ops_q,\
cortex_a9_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a9_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a9_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -636,6 +842,7 @@
(define_bypass 2 "cortex_a9_neon_vld1_3_4_regs"
"cortex_a9_neon_int_1,\
cortex_a9_neon_int_4,\
+ cortex_a9_neon_bit_ops_q,\
cortex_a9_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a9_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a9_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -650,6 +857,7 @@
(define_bypass 1 "cortex_a9_neon_vld1_1_2_regs"
"cortex_a9_neon_int_1,\
cortex_a9_neon_int_4,\
+ cortex_a9_neon_bit_ops_q,\
cortex_a9_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a9_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a9_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -664,6 +872,7 @@
(define_bypass 0 "cortex_a9_neon_ldr"
"cortex_a9_neon_int_1,\
cortex_a9_neon_int_4,\
+ cortex_a9_neon_bit_ops_q,\
cortex_a9_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a9_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a9_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -678,6 +887,7 @@
(define_bypass 3 "cortex_a9_neon_bp_3cycle"
"cortex_a9_neon_int_1,\
cortex_a9_neon_int_4,\
+ cortex_a9_neon_bit_ops_q,\
cortex_a9_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a9_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a9_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -692,6 +902,7 @@
(define_bypass 2 "cortex_a9_neon_bp_2cycle"
"cortex_a9_neon_int_1,\
cortex_a9_neon_int_4,\
+ cortex_a9_neon_bit_ops_q,\
cortex_a9_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a9_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a9_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -706,6 +917,7 @@
(define_bypass 1 "cortex_a9_neon_bp_simple"
"cortex_a9_neon_int_1,\
cortex_a9_neon_int_4,\
+ cortex_a9_neon_bit_ops_q,\
cortex_a9_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a9_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a9_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -720,6 +932,7 @@
(define_bypass 9 "cortex_a9_neon_fp_vrecps_vrsqrts_qqq"
"cortex_a9_neon_int_1,\
cortex_a9_neon_int_4,\
+ cortex_a9_neon_bit_ops_q,\
cortex_a9_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a9_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a9_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -734,6 +947,7 @@
(define_bypass 8 "cortex_a9_neon_fp_vrecps_vrsqrts_ddd"
"cortex_a9_neon_int_1,\
cortex_a9_neon_int_4,\
+ cortex_a9_neon_bit_ops_q,\
cortex_a9_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a9_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a9_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -748,6 +962,7 @@
(define_bypass 9 "cortex_a9_neon_fp_vmla_qqq_scalar"
"cortex_a9_neon_int_1,\
cortex_a9_neon_int_4,\
+ cortex_a9_neon_bit_ops_q,\
cortex_a9_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a9_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a9_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -762,6 +977,7 @@
(define_bypass 8 "cortex_a9_neon_fp_vmla_ddd_scalar"
"cortex_a9_neon_int_1,\
cortex_a9_neon_int_4,\
+ cortex_a9_neon_bit_ops_q,\
cortex_a9_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a9_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a9_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -776,6 +992,7 @@
(define_bypass 9 "cortex_a9_neon_fp_vmla_qqq"
"cortex_a9_neon_int_1,\
cortex_a9_neon_int_4,\
+ cortex_a9_neon_bit_ops_q,\
cortex_a9_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a9_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a9_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -790,6 +1007,7 @@
(define_bypass 8 "cortex_a9_neon_fp_vmla_ddd"
"cortex_a9_neon_int_1,\
cortex_a9_neon_int_4,\
+ cortex_a9_neon_bit_ops_q,\
cortex_a9_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a9_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a9_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -804,6 +1022,7 @@
(define_bypass 5 "cortex_a9_neon_fp_vmul_qqd"
"cortex_a9_neon_int_1,\
cortex_a9_neon_int_4,\
+ cortex_a9_neon_bit_ops_q,\
cortex_a9_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a9_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a9_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -818,6 +1037,7 @@
(define_bypass 4 "cortex_a9_neon_fp_vmul_ddd"
"cortex_a9_neon_int_1,\
cortex_a9_neon_int_4,\
+ cortex_a9_neon_bit_ops_q,\
cortex_a9_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a9_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a9_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -832,6 +1052,7 @@
(define_bypass 4 "cortex_a9_neon_fp_vsum"
"cortex_a9_neon_int_1,\
cortex_a9_neon_int_4,\
+ cortex_a9_neon_bit_ops_q,\
cortex_a9_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a9_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a9_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -846,6 +1067,7 @@
(define_bypass 5 "cortex_a9_neon_fp_vadd_qqq_vabs_qq"
"cortex_a9_neon_int_1,\
cortex_a9_neon_int_4,\
+ cortex_a9_neon_bit_ops_q,\
cortex_a9_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a9_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a9_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -860,6 +1082,7 @@
(define_bypass 4 "cortex_a9_neon_fp_vadd_ddd_vabs_dd"
"cortex_a9_neon_int_1,\
cortex_a9_neon_int_4,\
+ cortex_a9_neon_bit_ops_q,\
cortex_a9_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a9_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a9_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -874,6 +1097,7 @@
(define_bypass 5 "cortex_a9_neon_vsra_vrsra"
"cortex_a9_neon_int_1,\
cortex_a9_neon_int_4,\
+ cortex_a9_neon_bit_ops_q,\
cortex_a9_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a9_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a9_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -888,20 +1112,7 @@
(define_bypass 4 "cortex_a9_neon_vqshl_vrshl_vqrshl_qqq"
"cortex_a9_neon_int_1,\
cortex_a9_neon_int_4,\
- cortex_a9_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a9_neon_mul_qqq_8_16_32_ddd_32,\
- cortex_a9_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
- cortex_a9_neon_mla_qqq_8_16,\
- cortex_a9_neon_fp_vadd_ddd_vabs_dd,\
- cortex_a9_neon_fp_vadd_qqq_vabs_qq,\
- cortex_a9_neon_fp_vmla_ddd,\
- cortex_a9_neon_fp_vmla_qqq,\
- cortex_a9_neon_fp_vrecps_vrsqrts_ddd,\
- cortex_a9_neon_fp_vrecps_vrsqrts_qqq")
-
-(define_bypass 0 "cortex_a9_neon_vshl_ddd"
- "cortex_a9_neon_int_1,\
- cortex_a9_neon_int_4,\
+ cortex_a9_neon_bit_ops_q,\
cortex_a9_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a9_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a9_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -916,6 +1127,7 @@
(define_bypass 3 "cortex_a9_neon_shift_3"
"cortex_a9_neon_int_1,\
cortex_a9_neon_int_4,\
+ cortex_a9_neon_bit_ops_q,\
cortex_a9_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a9_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a9_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -930,6 +1142,7 @@
(define_bypass 3 "cortex_a9_neon_shift_2"
"cortex_a9_neon_int_1,\
cortex_a9_neon_int_4,\
+ cortex_a9_neon_bit_ops_q,\
cortex_a9_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a9_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a9_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -944,6 +1157,7 @@
(define_bypass 2 "cortex_a9_neon_shift_1"
"cortex_a9_neon_int_1,\
cortex_a9_neon_int_4,\
+ cortex_a9_neon_bit_ops_q,\
cortex_a9_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a9_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a9_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -958,6 +1172,7 @@
(define_bypass 5 "cortex_a9_neon_mla_ddd_16_scalar_qdd_32_16_long_scalar"
"cortex_a9_neon_int_1,\
cortex_a9_neon_int_4,\
+ cortex_a9_neon_bit_ops_q,\
cortex_a9_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a9_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a9_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -972,6 +1187,7 @@
(define_bypass 8 "cortex_a9_neon_mul_qqd_32_scalar"
"cortex_a9_neon_int_1,\
cortex_a9_neon_int_4,\
+ cortex_a9_neon_bit_ops_q,\
cortex_a9_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a9_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a9_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -986,6 +1202,7 @@
(define_bypass 5 "cortex_a9_neon_mul_ddd_16_scalar_32_16_long_scalar"
"cortex_a9_neon_int_1,\
cortex_a9_neon_int_4,\
+ cortex_a9_neon_bit_ops_q,\
cortex_a9_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a9_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a9_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -1000,6 +1217,7 @@
(define_bypass 8 "cortex_a9_neon_mla_qqq_32_qqd_32_scalar"
"cortex_a9_neon_int_1,\
cortex_a9_neon_int_4,\
+ cortex_a9_neon_bit_ops_q,\
cortex_a9_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a9_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a9_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -1014,6 +1232,7 @@
(define_bypass 6 "cortex_a9_neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long"
"cortex_a9_neon_int_1,\
cortex_a9_neon_int_4,\
+ cortex_a9_neon_bit_ops_q,\
cortex_a9_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a9_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a9_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -1028,6 +1247,7 @@
(define_bypass 6 "cortex_a9_neon_mla_qqq_8_16"
"cortex_a9_neon_int_1,\
cortex_a9_neon_int_4,\
+ cortex_a9_neon_bit_ops_q,\
cortex_a9_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a9_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a9_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -1042,6 +1262,7 @@
(define_bypass 5 "cortex_a9_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long"
"cortex_a9_neon_int_1,\
cortex_a9_neon_int_4,\
+ cortex_a9_neon_bit_ops_q,\
cortex_a9_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a9_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a9_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -1056,6 +1277,7 @@
(define_bypass 6 "cortex_a9_neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar"
"cortex_a9_neon_int_1,\
cortex_a9_neon_int_4,\
+ cortex_a9_neon_bit_ops_q,\
cortex_a9_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a9_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a9_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -1070,6 +1292,7 @@
(define_bypass 6 "cortex_a9_neon_mul_qqq_8_16_32_ddd_32"
"cortex_a9_neon_int_1,\
cortex_a9_neon_int_4,\
+ cortex_a9_neon_bit_ops_q,\
cortex_a9_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a9_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a9_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -1084,6 +1307,7 @@
(define_bypass 5 "cortex_a9_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long"
"cortex_a9_neon_int_1,\
cortex_a9_neon_int_4,\
+ cortex_a9_neon_bit_ops_q,\
cortex_a9_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a9_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a9_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -1095,9 +1319,10 @@
cortex_a9_neon_fp_vrecps_vrsqrts_ddd,\
cortex_a9_neon_fp_vrecps_vrsqrts_qqq")
-(define_bypass 5 "cortex_a9_neon_vsma"
+(define_bypass 6 "cortex_a9_neon_vaba_qqq"
"cortex_a9_neon_int_1,\
cortex_a9_neon_int_4,\
+ cortex_a9_neon_bit_ops_q,\
cortex_a9_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a9_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a9_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -1109,9 +1334,10 @@
cortex_a9_neon_fp_vrecps_vrsqrts_ddd,\
cortex_a9_neon_fp_vrecps_vrsqrts_qqq")
-(define_bypass 6 "cortex_a9_neon_vaba_qqq"
+(define_bypass 5 "cortex_a9_neon_vaba"
"cortex_a9_neon_int_1,\
cortex_a9_neon_int_4,\
+ cortex_a9_neon_bit_ops_q,\
cortex_a9_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a9_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a9_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -1123,9 +1349,10 @@
cortex_a9_neon_fp_vrecps_vrsqrts_ddd,\
cortex_a9_neon_fp_vrecps_vrsqrts_qqq")
-(define_bypass 5 "cortex_a9_neon_vaba"
+(define_bypass 2 "cortex_a9_neon_vmov"
"cortex_a9_neon_int_1,\
cortex_a9_neon_int_4,\
+ cortex_a9_neon_bit_ops_q,\
cortex_a9_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a9_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a9_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -1137,9 +1364,10 @@
cortex_a9_neon_fp_vrecps_vrsqrts_ddd,\
cortex_a9_neon_fp_vrecps_vrsqrts_qqq")
-(define_bypass 2 "cortex_a9_neon_vmov"
+(define_bypass 3 "cortex_a9_neon_bit_ops_q"
"cortex_a9_neon_int_1,\
cortex_a9_neon_int_4,\
+ cortex_a9_neon_bit_ops_q,\
cortex_a9_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a9_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a9_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -1154,6 +1382,7 @@
(define_bypass 3 "cortex_a9_neon_vqneg_vqabs"
"cortex_a9_neon_int_1,\
cortex_a9_neon_int_4,\
+ cortex_a9_neon_bit_ops_q,\
cortex_a9_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a9_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a9_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -1168,6 +1397,7 @@
(define_bypass 3 "cortex_a9_neon_int_5"
"cortex_a9_neon_int_1,\
cortex_a9_neon_int_4,\
+ cortex_a9_neon_bit_ops_q,\
cortex_a9_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a9_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a9_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -1182,6 +1412,7 @@
(define_bypass 3 "cortex_a9_neon_int_4"
"cortex_a9_neon_int_1,\
cortex_a9_neon_int_4,\
+ cortex_a9_neon_bit_ops_q,\
cortex_a9_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a9_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a9_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -1196,6 +1427,7 @@
(define_bypass 2 "cortex_a9_neon_int_3"
"cortex_a9_neon_int_1,\
cortex_a9_neon_int_4,\
+ cortex_a9_neon_bit_ops_q,\
cortex_a9_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a9_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a9_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -1210,6 +1442,7 @@
(define_bypass 2 "cortex_a9_neon_int_2"
"cortex_a9_neon_int_1,\
cortex_a9_neon_int_4,\
+ cortex_a9_neon_bit_ops_q,\
cortex_a9_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a9_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a9_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
@@ -1224,6 +1457,7 @@
(define_bypass 2 "cortex_a9_neon_int_1"
"cortex_a9_neon_int_1,\
cortex_a9_neon_int_4,\
+ cortex_a9_neon_bit_ops_q,\
cortex_a9_neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
cortex_a9_neon_mul_qqq_8_16_32_ddd_32,\
cortex_a9_neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
diff --git a/gcc/config/arm/iterators.md b/gcc/config/arm/iterators.md
index c7d7079b9de..38777b89a87 100644
--- a/gcc/config/arm/iterators.md
+++ b/gcc/config/arm/iterators.md
@@ -355,6 +355,12 @@
(DI "64") (V2DI "64")
(V2SF "32") (V4SF "32")])
+(define_mode_attr V_elem_ch [(V8QI "b") (V16QI "b")
+ (V4HI "h") (V8HI "h")
+ (V2SI "s") (V4SI "s")
+ (DI "d") (V2DI "d")
+ (V2SF "s") (V4SF "s")])
+
;; Element sizes for duplicating ARM registers to all elements of a vector.
(define_mode_attr VD_dup [(V8QI "8") (V4HI "16") (V2SI "32") (V2SF "32")])
@@ -452,6 +458,14 @@
(define_mode_attr vfp_type [(SF "s") (DF "d")])
(define_mode_attr vfp_double_cond [(SF "") (DF "&& TARGET_VFP_DOUBLE")])
+;; Mode attribute used to build the "type" attribute.
+(define_mode_attr q [(V8QI "") (V16QI "_q")
+ (V4HI "") (V8HI "_q")
+ (V2SI "") (V4SI "_q")
+ (V2SF "") (V4SF "_q")
+ (DI "") (V2DI "_q")
+ (DF "") (V2DF "_q")])
+
;;----------------------------------------------------------------------------
;; Code attributes
;;----------------------------------------------------------------------------
@@ -460,6 +474,10 @@
(define_code_attr VQH_mnem [(plus "vadd") (smin "vmin") (smax "vmax")
(umin "vmin") (umax "vmax")])
+;; Type attributes for vqh_ops and vqhs_ops iterators.
+(define_code_attr VQH_type [(plus "add") (smin "minmax") (smax "minmax")
+ (umin "minmax") (umax "minmax")])
+
;; Signs of above, where relevant.
(define_code_attr VQH_sign [(plus "i") (smin "s") (smax "s") (umin "u")
(umax "u")])
diff --git a/gcc/config/arm/neon-schedgen.ml b/gcc/config/arm/neon-schedgen.ml
deleted file mode 100644
index b3699563d48..00000000000
--- a/gcc/config/arm/neon-schedgen.ml
+++ /dev/null
@@ -1,543 +0,0 @@
-(* Emission of the core of the Cortex-A8 NEON scheduling description.
- Copyright (C) 2007-2013 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/>.
-*)
-
-(* This scheduling description generator works as follows.
- - Each group of instructions has source and destination requirements
- specified and a list of cores supported. This is then filtered
- and per core scheduler descriptions are generated out.
- The reservations generated are prefixed by the name of the
- core and the check is performed on the basis of what the tuning
- string is. Running this will generate Neon scheduler descriptions
- for all cores supported.
-
- The source requirements may be specified using
- Source (the stage at which all source operands not otherwise
- described are read), Source_m (the stage at which Rm operands are
- read), Source_n (likewise for Rn) and Source_d (likewise for Rd).
- - For each group of instructions the earliest stage where a source
- operand may be required is calculated.
- - Each group of instructions is selected in turn as a producer.
- The latencies between this group and every other group are then
- calculated, yielding up to four values for each combination:
- 1. Producer -> consumer Rn latency
- 2. Producer -> consumer Rm latency
- 3. Producer -> consumer Rd (as a source) latency
- 4. Producer -> consumer worst-case latency.
- Value 4 is calculated from the destination availability requirements
- of the consumer and the earliest source availability requirements
- of the producer.
- - The largest Value 4 calculated for the current producer is the
- worse-case latency, L, for that instruction group. This value is written
- out in a define_insn_reservation for the producer group.
- - For each producer and consumer pair, the latencies calculated above
- are collated. The average (of up to four values) is calculated and
- if this average is different from the worst-case latency, an
- unguarded define_bypass construction is issued for that pair.
- (For each pair only one define_bypass construction will be emitted,
- and at present we do not emit specific guards.)
-*)
-
-let find_with_result fn lst =
- let rec scan = function
- [] -> raise Not_found
- | l::ls ->
- match fn l with
- Some result -> result
- | _ -> scan ls in
- scan lst
-
-let n1 = 1 and n2 = 2 and n3 = 3 and n4 = 4 and n5 = 5 and n6 = 6
- and n7 = 7 and n8 = 8 and n9 = 9
-
-type availability = Source of int
- | Source_n of int
- | Source_m of int
- | Source_d of int
- | Dest of int
- | Dest_n_after of int * int
-
-type guard = Guard_none | Guard_only_m | Guard_only_n | Guard_only_d
-
-(* Reservation behaviors. All but the last row here correspond to one
- pipeline each. Each constructor will correspond to one
- define_reservation. *)
-type reservation =
- Mul | Mul_2cycle | Mul_4cycle
-| Shift | Shift_2cycle
-| ALU | ALU_2cycle
-| Fmul | Fmul_2cycle
-| Fadd | Fadd_2cycle
-(* | VFP *)
-| Permute of int
-| Ls of int
-| Fmul_then_fadd | Fmul_then_fadd_2
-
-type core = CortexA8 | CortexA9
-let allCores = [CortexA8; CortexA9]
-let coreStr = function
- CortexA8 -> "cortex_a8"
- | CortexA9 -> "cortex_a9"
-
-let tuneStr = function
- CortexA8 -> "cortexa8"
- | CortexA9 -> "cortexa9"
-
-
-(* This table must be kept as short as possible by conflating
- entries with the same availability behavior.
-
- First components: instruction group names
- Second components: availability requirements, in the order in which
- they should appear in the comments in the .md file.
- Third components: reservation info
- Fourth components: List of supported cores.
-*)
-let availability_table = [
- (* NEON integer ALU instructions. *)
- (* vbit vbif vbsl vorr vbic vnot vcls vclz vcnt vadd vand vorr
- veor vbic vorn ddd qqq *)
- "neon_int_1", [Source n2; Dest n3], ALU, allCores;
- (* vadd vsub qqd vsub ddd qqq *)
- "neon_int_2", [Source_m n1; Source_n n2; Dest n3], ALU, allCores;
- (* vsum vneg dd qq vadd vsub qdd *)
- "neon_int_3", [Source n1; Dest n3], ALU, allCores;
- (* vabs vceqz vcgez vcbtz vclez vcltz vadh vradh vsbh vrsbh dqq *)
- (* vhadd vrhadd vqadd vtst ddd qqq *)
- "neon_int_4", [Source n2; Dest n4], ALU, allCores;
- (* vabd qdd vhsub vqsub vabd vceq vcge vcgt vmax vmin vfmx vfmn ddd ddd *)
- "neon_int_5", [Source_m n1; Source_n n2; Dest n4], ALU, allCores;
- (* vqneg vqabs dd qq *)
- "neon_vqneg_vqabs", [Source n1; Dest n4], ALU, allCores;
- (* vmov vmvn *)
- "neon_vmov", [Dest n3], ALU, allCores;
- (* vaba *)
- "neon_vaba", [Source_n n2; Source_m n1; Source_d n3; Dest n6], ALU, allCores;
- "neon_vaba_qqq",
- [Source_n n2; Source_m n1; Source_d n3; Dest_n_after (1, n6)],
- ALU_2cycle, allCores;
- (* vsma *)
- "neon_vsma", [Source_m n1; Source_d n3; Dest n6], ALU, allCores;
-
- (* NEON integer multiply instructions. *)
- (* vmul, vqdmlh, vqrdmlh *)
- (* vmul, vqdmul, qdd 16/8 long 32/16 long *)
- "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long", [Source n2; Dest n6],
- Mul, allCores;
- "neon_mul_qqq_8_16_32_ddd_32", [Source n2; Dest_n_after (1, n6)],
- Mul_2cycle, allCores;
- (* vmul, vqdmul again *)
- "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar",
- [Source_n n2; Source_m n1; Dest_n_after (1, n6)], Mul_2cycle, allCores;
- (* vmla, vmls *)
- "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long",
- [Source_n n2; Source_m n2; Source_d n3; Dest n6], Mul, allCores;
- "neon_mla_qqq_8_16",
- [Source_n n2; Source_m n2; Source_d n3; Dest_n_after (1, n6)],
- Mul_2cycle, allCores;
- "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long",
- [Source_n n2; Source_m n1; Source_d n3; Dest_n_after (1, n6)],
- Mul_2cycle, allCores;
- "neon_mla_qqq_32_qqd_32_scalar",
- [Source_n n2; Source_m n1; Source_d n3; Dest_n_after (3, n6)],
- Mul_4cycle, allCores;
- (* vmul, vqdmulh, vqrdmulh *)
- (* vmul, vqdmul *)
- "neon_mul_ddd_16_scalar_32_16_long_scalar",
- [Source_n n2; Source_m n1; Dest n6], Mul, allCores;
- "neon_mul_qqd_32_scalar",
- [Source_n n2; Source_m n1; Dest_n_after (3, n6)], Mul_4cycle, allCores;
- (* vmla, vmls *)
- (* vmla, vmla, vqdmla, vqdmls *)
- "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar",
- [Source_n n2; Source_m n1; Source_d n3; Dest n6], Mul, allCores;
-
- (* NEON integer shift instructions. *)
- (* vshr/vshl immediate, vshr_narrow, vshl_vmvh, vsli_vsri_ddd *)
- "neon_shift_1", [Source n1; Dest n3], Shift, allCores;
- (* vqshl, vrshr immediate; vqshr, vqmov, vrshr, vqrshr narrow, allCores;
- vqshl_vrshl_vqrshl_ddd *)
- "neon_shift_2", [Source n1; Dest n4], Shift, allCores;
- (* vsli, vsri and vshl for qqq *)
- "neon_shift_3", [Source n1; Dest_n_after (1, n3)], Shift_2cycle, allCores;
- "neon_vshl_ddd", [Source n1; Dest n1], Shift, allCores;
- "neon_vqshl_vrshl_vqrshl_qqq", [Source n1; Dest_n_after (1, n4)],
- Shift_2cycle, allCores;
- "neon_vsra_vrsra", [Source_m n1; Source_d n3; Dest n6], Shift, allCores;
-
- (* NEON floating-point instructions. *)
- (* vadd, vsub, vabd, vmul, vceq, vcge, vcgt, vcage, vcagt, vmax, vmin *)
- (* vabs, vneg, vceqz, vcgez, vcgtz, vclez, vcltz, vrecpe, vrsqrte, vcvt *)
- "neon_fp_vadd_ddd_vabs_dd", [Source n2; Dest n5], Fadd, allCores;
- "neon_fp_vadd_qqq_vabs_qq", [Source n2; Dest_n_after (1, n5)],
- Fadd_2cycle, allCores;
- (* vsum, fvmx, vfmn *)
- "neon_fp_vsum", [Source n1; Dest n5], Fadd, allCores;
- "neon_fp_vmul_ddd", [Source_n n2; Source_m n1; Dest n5], Fmul, allCores;
- "neon_fp_vmul_qqd", [Source_n n2; Source_m n1; Dest_n_after (1, n5)],
- Fmul_2cycle, allCores;
- (* vmla, vmls *)
- "neon_fp_vmla_ddd",
- [Source_n n2; Source_m n2; Source_d n3; Dest n9], Fmul_then_fadd, allCores;
- "neon_fp_vmla_qqq",
- [Source_n n2; Source_m n2; Source_d n3; Dest_n_after (1, n9)],
- Fmul_then_fadd_2, allCores;
- "neon_fp_vmla_ddd_scalar",
- [Source_n n2; Source_m n1; Source_d n3; Dest n9], Fmul_then_fadd, allCores;
- "neon_fp_vmla_qqq_scalar",
- [Source_n n2; Source_m n1; Source_d n3; Dest_n_after (1, n9)],
- Fmul_then_fadd_2, allCores;
- "neon_fp_vrecps_vrsqrts_ddd", [Source n2; Dest n9], Fmul_then_fadd, allCores;
- "neon_fp_vrecps_vrsqrts_qqq", [Source n2; Dest_n_after (1, n9)],
- Fmul_then_fadd_2, allCores;
-
- (* NEON byte permute instructions. *)
- (* vmov; vtrn and vswp for dd; vzip for dd; vuzp for dd; vrev; vext for dd *)
- "neon_bp_simple", [Source n1; Dest n2], Permute 1, allCores;
- (* vswp for qq; vext for qqq; vtbl with {Dn} or {Dn, Dn1}, allCores;
- similarly for vtbx *)
- "neon_bp_2cycle", [Source n1; Dest_n_after (1, n2)], Permute 2, allCores;
- (* all the rest *)
- "neon_bp_3cycle", [Source n1; Dest_n_after (2, n2)], Permute 3, allCores;
-
- (* NEON load/store instructions. *)
- "neon_ldr", [Dest n1], Ls 1, allCores;
- "neon_str", [Source n1], Ls 1, allCores;
- "neon_vld1_1_2_regs", [Dest_n_after (1, n1)], Ls 2, allCores;
- "neon_vld1_3_4_regs", [Dest_n_after (2, n1)], Ls 3, allCores;
- "neon_vld2_2_regs_vld1_vld2_all_lanes", [Dest_n_after (1, n2)], Ls 2, allCores;
- "neon_vld2_4_regs", [Dest_n_after (2, n2)], Ls 3, allCores;
- "neon_vld3_vld4", [Dest_n_after (3, n2)], Ls 4, allCores;
- "neon_vst1_1_2_regs_vst2_2_regs", [Source n1], Ls 2, allCores;
- "neon_vst1_3_4_regs", [Source n1], Ls 3, allCores;
- "neon_vst2_4_regs_vst3_vst4", [Source n1], Ls 4, allCores;
- "neon_vst3_vst4", [Source n1], Ls 4, allCores;
- "neon_vld1_vld2_lane", [Source n1; Dest_n_after (2, n2)], Ls 3, allCores;
- "neon_vld3_vld4_lane", [Source n1; Dest_n_after (4, n2)], Ls 5, allCores;
- "neon_vst1_vst2_lane", [Source n1], Ls 2, allCores;
- "neon_vst3_vst4_lane", [Source n1], Ls 3, allCores;
- "neon_vld3_vld4_all_lanes", [Dest_n_after (1, n2)], Ls 3, allCores;
-
- (* NEON register transfer instructions. *)
- "neon_mcr", [Dest n2], Permute 1, allCores;
- "neon_mcr_2_mcrr", [Dest n2], Permute 2, allCores;
- (* MRC instructions are in the .tpl file. *)
-]
-
-(* Augment the tuples in the availability table with an extra component
- that describes the earliest stage where a source operand may be
- required. (It is also possible that an entry in the table has no
- source requirements.) *)
-let calculate_sources =
- List.map (fun (name, avail, res, cores) ->
- let earliest_stage =
- List.fold_left
- (fun cur -> fun info ->
- match info with
- Source stage
- | Source_n stage
- | Source_m stage
- | Source_d stage ->
- (match cur with
- None -> Some stage
- | Some stage' when stage < stage' -> Some stage
- | _ -> cur)
- | _ -> cur) None avail
- in
- (name, avail, res, earliest_stage))
-
-(* Find the stage, if any, at the end of which a group produces a result. *)
-let find_dest (attr, avail, _, _) =
- try
- find_with_result
- (fun av -> match av with
- Dest st -> Some (Some st)
- | Dest_n_after (after, st) -> Some (Some (after + st))
- | _ -> None) avail
- with Not_found -> None
-
-(* Find the worst-case latency between a producer and a consumer. *)
-let worst_case_latency producer (_, _, _, earliest_required) =
- let dest = find_dest producer in
- match earliest_required, dest with
- None, _ ->
- (* The consumer doesn't have any source requirements. *)
- None
- | _, None ->
- (* The producer doesn't produce any results (e.g. a store insn). *)
- None
- | Some consumed, Some produced -> Some (produced - consumed + 1)
-
-(* Helper function for below. *)
-let latency_calc f producer (_, avail, _, _) =
- try
- let source_avail = find_with_result f avail in
- match find_dest producer with
- None ->
- (* The producer does not produce a result. *)
- Some 0
- | Some produced ->
- let latency = produced - source_avail + 1 in
- (* Latencies below zero are raised to zero since we don't have
- delay slots. *)
- if latency < 0 then Some 0 else Some latency
- with Not_found -> None
-
-(* Find any Rm latency between a producer and a consumer. If no
- Rm source requirement is explicitly specified for the consumer,
- return "positive infinity". Also return "positive infinity" if
- the latency matches the supplied worst-case latency for this
- producer. *)
-let get_m_latency producer consumer =
- match latency_calc (fun av -> match av with Source_m stage -> Some stage
- | _ -> None) producer consumer
- with None -> [] | Some latency -> [(Guard_only_m, latency)]
-
-(* Likewise for Rn. *)
-let get_n_latency producer consumer =
- match latency_calc (fun av -> match av with Source_n stage -> Some stage
- | _ -> None) producer consumer
- with None -> [] | Some latency -> [(Guard_only_n, latency)]
-
-(* Likewise for Rd. *)
-let get_d_latency producer consumer =
- match
- latency_calc (fun av -> match av with Source_d stage -> Some stage
- | _ -> None) producer consumer
- with None -> [] | Some latency -> [(Guard_only_d, latency)]
-
-(* Given a producer and a consumer, work out the latency of the producer
- to the consumer in each of the four cases (availability information
- permitting) identified at the top of this file. Return the
- consumer, the worst-case unguarded latency and any guarded latencies. *)
-let calculate_latencies producer consumer =
- let worst = worst_case_latency producer consumer in
- let m_latency = get_m_latency producer consumer in
- let n_latency = get_n_latency producer consumer in
- let d_latency = get_d_latency producer consumer in
- (consumer, worst, m_latency @ n_latency @ d_latency)
-
-(* Helper function for below. *)
-let pick_latency largest worst guards =
- let guards =
- match worst with
- None -> guards
- | Some worst -> (Guard_none, worst) :: guards
- in
- if List.length guards = 0 then None else
- let total_latency =
- List.fold_left (fun acc -> fun (_, latency) -> acc + latency) 0 guards
- in
- let average_latency = (float_of_int total_latency) /.
- (float_of_int (List.length guards)) in
- let rounded_latency = int_of_float (ceil average_latency) in
- if rounded_latency = largest then None
- else Some (Guard_none, rounded_latency)
-
-(* Collate all bypasses for a particular producer as required in
- worst_case_latencies_and_bypasses. (By this stage there is a maximum
- of one bypass from this producer to any particular consumer listed
- in LATENCIES.) Use a hash table to collate bypasses with the
- same latency and guard. *)
-let collate_bypasses (producer_name, _, _, _) largest latencies core =
- let ht = Hashtbl.create 42 in
- let keys = ref [] in
- List.iter (
- fun ((consumer, _, _, _), worst, guards) ->
- (* Find out which latency to use. Ignoring latencies that match
- the *overall* worst-case latency for this producer (which will
- be in define_insn_reservation), we have to examine:
- 1. the latency with no guard between this producer and this
- consumer; and
- 2. any guarded latency. *)
- let guard_latency_opt = pick_latency largest worst guards in
- match guard_latency_opt with
- None -> ()
- | Some (guard, latency) ->
- begin
- (if (try ignore (Hashtbl.find ht (guard, latency)); false
- with Not_found -> true) then
- keys := (guard, latency) :: !keys);
- Hashtbl.add ht (guard, latency) ((coreStr core) ^ "_" ^ consumer)
- end
- ) latencies;
- (* The hash table now has bypasses collated so that ones with the
- same latency and guard have the same keys. Walk through all the
- keys, extract the associated bypasses, and concatenate the names
- of the consumers for each bypass. *)
- List.map (
- fun ((guard, latency) as key) ->
- let consumers = Hashtbl.find_all ht key in
- (producer_name,
- String.concat ",\\\n " consumers,
- latency,
- guard)
- ) !keys
-
-(* For every producer, find the worst-case latency between it and
- *any* consumer. Also determine (if such a thing exists) the
- lowest-latency bypass from each producer to each consumer. Group
- the output in such a way that all bypasses with the same producer
- and latency are together, and so that bypasses with the worst-case
- latency are ignored. *)
-let worst_case_latencies_and_bypasses core =
- let rec f (worst_acc, bypasses_acc) prev xs =
- match xs with
- [] -> (worst_acc, bypasses_acc)
- | ((producer_name, producer_avail, res_string, _) as producer)::next ->
- (* For this particular producer, work out the latencies between
- it and every consumer. *)
- let latencies =
- List.fold_left (fun acc -> fun consumer ->
- (calculate_latencies producer consumer) :: acc)
- [] (prev @ xs)
- in
- (* Now work out what the overall worst case latency was for this
- particular producer. *)
- match latencies with
- [] -> assert false
- | _ ->
- let comp_fn (_, l1, _) (_, l2, _) =
- if l1 > l2 then -1 else if l1 = l2 then 0 else 1
- in
- let largest =
- match List.hd (List.sort comp_fn latencies) with
- (_, None, _) -> 0 (* Producer has no consumers. *)
- | (_, Some worst, _) -> worst
- in
- (* Having got the largest latency, collect all bypasses for
- this producer and filter out those with that larger
- latency. Record the others for later emission. *)
- let bypasses = collate_bypasses producer largest latencies core in
- (* Go on to process remaining producers, having noted
- the result for this one. *)
- f ((producer_name, producer_avail, largest,
- res_string) :: worst_acc,
- bypasses @ bypasses_acc)
- (prev @ [producer]) next
- in
- f ([], []) []
-
-(* Emit a helpful comment for a define_insn_reservation. *)
-let write_comment producer avail =
- let seen_source = ref false in
- let describe info =
- let read = if !seen_source then "" else "read " in
- match info with
- Source stage ->
- seen_source := true;
- Printf.printf "%stheir source operands at N%d" read stage
- | Source_n stage ->
- seen_source := true;
- Printf.printf "%stheir (D|Q)n operands at N%d" read stage
- | Source_m stage ->
- seen_source := true;
- Printf.printf "%stheir (D|Q)m operands at N%d" read stage
- | Source_d stage ->
- Printf.printf "%stheir (D|Q)d operands at N%d" read stage
- | Dest stage ->
- Printf.printf "produce a result at N%d" stage
- | Dest_n_after (after, stage) ->
- Printf.printf "produce a result at N%d on cycle %d" stage (after + 1)
- in
- Printf.printf ";; Instructions using this reservation ";
- let rec f infos x =
- let sep = if x mod 2 = 1 then "" else "\n;;" in
- match infos with
- [] -> assert false
- | [info] -> describe info; Printf.printf ".\n"
- | info::(_::[] as infos) ->
- describe info; Printf.printf ", and%s " sep; f infos (x+1)
- | info::infos -> describe info; Printf.printf ",%s " sep; f infos (x+1)
- in
- f avail 0
-
-
-(* Emit a define_insn_reservation for each producer. The latency
- written in will be its worst-case latency. *)
-let emit_insn_reservations core =
- let corestring = coreStr core in
- let tunestring = tuneStr core
- in List.iter (
- fun (producer, avail, latency, reservation) ->
- write_comment producer avail;
- Printf.printf "(define_insn_reservation \"%s_%s\" %d\n"
- corestring producer latency;
- Printf.printf " (and (eq_attr \"tune\" \"%s\")\n" tunestring;
- Printf.printf " (eq_attr \"type\" \"%s\"))\n" producer;
- let str =
- match reservation with
- Mul -> "dp" | Mul_2cycle -> "dp_2" | Mul_4cycle -> "dp_4"
- | Shift -> "dp" | Shift_2cycle -> "dp_2"
- | ALU -> "dp" | ALU_2cycle -> "dp_2"
- | Fmul -> "dp" | Fmul_2cycle -> "dp_2"
- | Fadd -> "fadd" | Fadd_2cycle -> "fadd_2"
- | Ls 1 -> "ls"
- | Ls n -> "ls_" ^ (string_of_int n)
- | Permute 1 -> "perm"
- | Permute n -> "perm_" ^ (string_of_int n)
- | Fmul_then_fadd -> "fmul_then_fadd"
- | Fmul_then_fadd_2 -> "fmul_then_fadd_2"
- in
- Printf.printf " \"%s_neon_%s\")\n\n" corestring str
- )
-
-(* Given a guard description, return the name of the C function to
- be used as the guard for define_bypass. *)
-let guard_fn g =
- match g with
- Guard_only_m -> "arm_neon_only_m_dependency"
- | Guard_only_n -> "arm_neon_only_n_dependency"
- | Guard_only_d -> "arm_neon_only_d_dependency"
- | Guard_none -> assert false
-
-(* Emit a define_bypass for each bypass. *)
-let emit_bypasses core =
- List.iter (
- fun (producer, consumers, latency, guard) ->
- Printf.printf "(define_bypass %d \"%s_%s\"\n"
- latency (coreStr core) producer;
-
- if guard = Guard_none then
- Printf.printf " \"%s\")\n\n" consumers
- else
- begin
- Printf.printf " \"%s\"\n" consumers;
- Printf.printf " \"%s\")\n\n" (guard_fn guard)
- end
- )
-
-
-let calculate_per_core_availability_table core availability_table =
- let table = calculate_sources availability_table in
- let worst_cases, bypasses = worst_case_latencies_and_bypasses core table in
- emit_insn_reservations core (List.rev worst_cases);
- Printf.printf ";; Exceptions to the default latencies.\n\n";
- emit_bypasses core bypasses
-
-let calculate_core_availability_table core availability_table =
-let filter_core = List.filter (fun (_, _, _, cores)
- -> List.exists ((=) core) cores)
-in calculate_per_core_availability_table core (filter_core availability_table)
-
-
-(* Program entry point. *)
-let main =
- List.map (fun core -> calculate_core_availability_table
- core availability_table) allCores
diff --git a/gcc/config/arm/neon.md b/gcc/config/arm/neon.md
index ae83dba5f89..b2ac45e65f9 100644
--- a/gcc/config/arm/neon.md
+++ b/gcc/config/arm/neon.md
@@ -60,8 +60,9 @@
default: return output_move_double (operands, true, NULL);
}
}
- [(set_attr "type" "neon_int_1,f_stored,neon_vmov,f_loadd,neon_mrrc,\
- neon_mcr_2_mcrr,mov_reg,load2,store2")
+ [(set_attr "type" "neon_move<q>,neon_store1_1reg,neon_move<q>,\
+ neon_load1_1reg, neon_to_gp<q>,neon_from_gp<q>,mov_reg,\
+ neon_load1_2reg, neon_store1_2reg")
(set_attr "length" "4,4,4,4,4,4,8,8,8")
(set_attr "arm_pool_range" "*,*,*,1020,*,*,*,1020,*")
(set_attr "thumb2_pool_range" "*,*,*,1018,*,*,*,1018,*")
@@ -104,8 +105,9 @@
default: return output_move_quad (operands);
}
}
- [(set_attr "type" "neon_int_1,neon_stm_2,neon_vmov,neon_ldm_2,\
- neon_mrrc,neon_mcr_2_mcrr,mov_reg,load4,store4")
+ [(set_attr "type" "neon_move_q,neon_store2_2reg_q,neon_move_q,\
+ neon_load2_2reg_q,neon_to_gp_q,neon_from_gp_q,\
+ mov_reg,neon_load1_4reg,neon_store1_4reg")
(set_attr "length" "4,8,4,8,8,8,16,8,16")
(set_attr "arm_pool_range" "*,*,*,1020,*,*,*,1020,*")
(set_attr "thumb2_pool_range" "*,*,*,1018,*,*,*,1018,*")
@@ -149,7 +151,7 @@
default: gcc_unreachable ();
}
}
- [(set_attr "type" "neon_int_1,neon_stm_2,neon_ldm_2")
+ [(set_attr "type" "neon_move_q,neon_store2_2reg_q,neon_load2_2reg_q")
(set (attr "length") (symbol_ref "arm_attr_length_move_neon (insn)"))])
(define_split
@@ -257,7 +259,7 @@
UNSPEC_MISALIGNED_ACCESS))]
"TARGET_NEON && !BYTES_BIG_ENDIAN && unaligned_access"
"vst1.<V_sz_elem>\t{%P1}, %A0"
- [(set_attr "type" "neon_vst1_1_2_regs_vst2_2_regs")])
+ [(set_attr "type" "neon_store1_1reg<q>")])
(define_insn "*movmisalign<mode>_neon_load"
[(set (match_operand:VDX 0 "s_register_operand" "=w")
@@ -266,7 +268,7 @@
UNSPEC_MISALIGNED_ACCESS))]
"TARGET_NEON && !BYTES_BIG_ENDIAN && unaligned_access"
"vld1.<V_sz_elem>\t{%P0}, %A1"
- [(set_attr "type" "neon_vld1_1_2_regs")])
+ [(set_attr "type" "neon_load1_1reg<q>")])
(define_insn "*movmisalign<mode>_neon_store"
[(set (match_operand:VQX 0 "neon_permissive_struct_operand" "=Um")
@@ -274,7 +276,7 @@
UNSPEC_MISALIGNED_ACCESS))]
"TARGET_NEON && !BYTES_BIG_ENDIAN && unaligned_access"
"vst1.<V_sz_elem>\t{%q1}, %A0"
- [(set_attr "type" "neon_vst1_1_2_regs_vst2_2_regs")])
+ [(set_attr "type" "neon_store1_1reg<q>")])
(define_insn "*movmisalign<mode>_neon_load"
[(set (match_operand:VQX 0 "s_register_operand" "=w")
@@ -283,7 +285,7 @@
UNSPEC_MISALIGNED_ACCESS))]
"TARGET_NEON && !BYTES_BIG_ENDIAN && unaligned_access"
"vld1.<V_sz_elem>\t{%q0}, %A1"
- [(set_attr "type" "neon_vld1_1_2_regs")])
+ [(set_attr "type" "neon_store1_1reg<q>")])
(define_insn "vec_set<mode>_internal"
[(set (match_operand:VD 0 "s_register_operand" "=w,w")
@@ -304,7 +306,7 @@
else
return "vmov.<V_sz_elem>\t%P0[%c2], %1";
}
- [(set_attr "type" "neon_vld1_vld2_lane,neon_mcr")])
+ [(set_attr "type" "neon_load1_all_lanes<q>,neon_from_gp<q>")])
(define_insn "vec_set<mode>_internal"
[(set (match_operand:VQ 0 "s_register_operand" "=w,w")
@@ -332,7 +334,7 @@
else
return "vmov.<V_sz_elem>\t%P0[%c2], %1";
}
- [(set_attr "type" "neon_vld1_vld2_lane,neon_mcr")]
+ [(set_attr "type" "neon_load1_all_lanes<q>,neon_from_gp<q>")]
)
(define_insn "vec_setv2di_internal"
@@ -354,7 +356,7 @@
else
return "vmov\t%P0, %Q1, %R1";
}
- [(set_attr "type" "neon_vld1_1_2_regs,neon_mcr_2_mcrr")]
+ [(set_attr "type" "neon_load1_all_lanes_q,neon_from_gp_q")]
)
(define_expand "vec_set<mode>"
@@ -388,7 +390,7 @@
else
return "vmov.<V_uf_sclr>\t%0, %P1[%c2]";
}
- [(set_attr "type" "neon_vst1_vst2_lane,neon_bp_simple")]
+ [(set_attr "type" "neon_store1_one_lane<q>,neon_to_gp<q>")]
)
(define_insn "vec_extract<mode>"
@@ -414,7 +416,7 @@
else
return "vmov.<V_uf_sclr>\t%0, %P1[%c2]";
}
- [(set_attr "type" "neon_vst1_vst2_lane,neon_bp_simple")]
+ [(set_attr "type" "neon_store1_one_lane<q>,neon_to_gp<q>")]
)
(define_insn "vec_extractv2di"
@@ -433,7 +435,7 @@
else
return "vmov\t%Q0, %R0, %P1 @ v2di";
}
- [(set_attr "type" "neon_vst1_vst2_lane,neon_int_1")]
+ [(set_attr "type" "neon_store1_one_lane_q,neon_to_gp_q")]
)
(define_expand "vec_init<mode>"
@@ -458,10 +460,8 @@
"vadd.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
[(set (attr "type")
(if_then_else (match_test "<Is_float_mode>")
- (if_then_else (match_test "<Is_d_reg>")
- (const_string "neon_fp_vadd_ddd_vabs_dd")
- (const_string "neon_fp_vadd_qqq_vabs_qq"))
- (const_string "neon_int_1")))]
+ (const_string "neon_fp_addsub_s<q>")
+ (const_string "neon_add<q>")))]
)
(define_insn "adddi3_neon"
@@ -483,7 +483,8 @@
default: gcc_unreachable ();
}
}
- [(set_attr "type" "neon_int_1,*,*,neon_int_1,*,*,*")
+ [(set_attr "type" "neon_add,multiple,multiple,neon_add,\
+ multiple,multiple,multiple")
(set_attr "conds" "*,clob,clob,*,clob,clob,clob")
(set_attr "length" "*,8,8,*,8,8,8")
(set_attr "arch" "neon_for_64bits,*,*,avoid_neon_for_64bits,*,*,*")]
@@ -497,10 +498,8 @@
"vsub.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
[(set (attr "type")
(if_then_else (match_test "<Is_float_mode>")
- (if_then_else (match_test "<Is_d_reg>")
- (const_string "neon_fp_vadd_ddd_vabs_dd")
- (const_string "neon_fp_vadd_qqq_vabs_qq"))
- (const_string "neon_int_2")))]
+ (const_string "neon_fp_addsub_s<q>")
+ (const_string "neon_sub<q>")))]
)
(define_insn "subdi3_neon"
@@ -520,75 +519,48 @@
default: gcc_unreachable ();
}
}
- [(set_attr "type" "neon_int_2,*,*,*,neon_int_2")
+ [(set_attr "type" "neon_sub,multiple,multiple,multiple,neon_sub")
(set_attr "conds" "*,clob,clob,clob,*")
(set_attr "length" "*,8,8,8,*")
(set_attr "arch" "neon_for_64bits,*,*,*,avoid_neon_for_64bits")]
)
(define_insn "*mul<mode>3_neon"
- [(set (match_operand:VDQ 0 "s_register_operand" "=w")
- (mult:VDQ (match_operand:VDQ 1 "s_register_operand" "w")
- (match_operand:VDQ 2 "s_register_operand" "w")))]
+ [(set (match_operand:VDQW 0 "s_register_operand" "=w")
+ (mult:VDQW (match_operand:VDQW 1 "s_register_operand" "w")
+ (match_operand:VDQW 2 "s_register_operand" "w")))]
"TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)"
"vmul.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
[(set (attr "type")
(if_then_else (match_test "<Is_float_mode>")
- (if_then_else (match_test "<Is_d_reg>")
- (const_string "neon_fp_vadd_ddd_vabs_dd")
- (const_string "neon_fp_vadd_qqq_vabs_qq"))
- (if_then_else (match_test "<Is_d_reg>")
- (if_then_else
- (match_test "<Scalar_mul_8_16>")
- (const_string "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long")
- (const_string "neon_mul_qqq_8_16_32_ddd_32"))
- (if_then_else (match_test "<Scalar_mul_8_16>")
- (const_string "neon_mul_qqq_8_16_32_ddd_32")
- (const_string "neon_mul_qqq_8_16_32_ddd_32")))))]
+ (const_string "neon_fp_mul_s<q>")
+ (const_string "neon_mul_<V_elem_ch><q>")))]
)
(define_insn "mul<mode>3add<mode>_neon"
- [(set (match_operand:VDQ 0 "s_register_operand" "=w")
- (plus:VDQ (mult:VDQ (match_operand:VDQ 2 "s_register_operand" "w")
- (match_operand:VDQ 3 "s_register_operand" "w"))
- (match_operand:VDQ 1 "s_register_operand" "0")))]
+ [(set (match_operand:VDQW 0 "s_register_operand" "=w")
+ (plus:VDQW (mult:VDQW (match_operand:VDQW 2 "s_register_operand" "w")
+ (match_operand:VDQW 3 "s_register_operand" "w"))
+ (match_operand:VDQW 1 "s_register_operand" "0")))]
"TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)"
"vmla.<V_if_elem>\t%<V_reg>0, %<V_reg>2, %<V_reg>3"
[(set (attr "type")
(if_then_else (match_test "<Is_float_mode>")
- (if_then_else (match_test "<Is_d_reg>")
- (const_string "neon_fp_vmla_ddd")
- (const_string "neon_fp_vmla_qqq"))
- (if_then_else (match_test "<Is_d_reg>")
- (if_then_else
- (match_test "<Scalar_mul_8_16>")
- (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
- (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long"))
- (if_then_else (match_test "<Scalar_mul_8_16>")
- (const_string "neon_mla_qqq_8_16")
- (const_string "neon_mla_qqq_32_qqd_32_scalar")))))]
+ (const_string "neon_fp_mla_s<q>")
+ (const_string "neon_mla_<V_elem_ch><q>")))]
)
(define_insn "mul<mode>3neg<mode>add<mode>_neon"
- [(set (match_operand:VDQ 0 "s_register_operand" "=w")
- (minus:VDQ (match_operand:VDQ 1 "s_register_operand" "0")
- (mult:VDQ (match_operand:VDQ 2 "s_register_operand" "w")
- (match_operand:VDQ 3 "s_register_operand" "w"))))]
+ [(set (match_operand:VDQW 0 "s_register_operand" "=w")
+ (minus:VDQW (match_operand:VDQW 1 "s_register_operand" "0")
+ (mult:VDQW (match_operand:VDQW 2 "s_register_operand" "w")
+ (match_operand:VDQW 3 "s_register_operand" "w"))))]
"TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)"
"vmls.<V_if_elem>\t%<V_reg>0, %<V_reg>2, %<V_reg>3"
[(set (attr "type")
(if_then_else (match_test "<Is_float_mode>")
- (if_then_else (match_test "<Is_d_reg>")
- (const_string "neon_fp_vmla_ddd")
- (const_string "neon_fp_vmla_qqq"))
- (if_then_else (match_test "<Is_d_reg>")
- (if_then_else
- (match_test "<Scalar_mul_8_16>")
- (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
- (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long"))
- (if_then_else (match_test "<Scalar_mul_8_16>")
- (const_string "neon_mla_qqq_8_16")
- (const_string "neon_mla_qqq_32_qqd_32_scalar")))))]
+ (const_string "neon_fp_mla_s<q>")
+ (const_string "neon_mla_<V_elem_ch><q>")))]
)
;; Fused multiply-accumulate
@@ -603,10 +575,7 @@
(match_operand:VCVTF 3 "register_operand" "0")))]
"TARGET_NEON && TARGET_FMA && flag_unsafe_math_optimizations"
"vfma%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
- [(set (attr "type")
- (if_then_else (match_test "<Is_d_reg>")
- (const_string "neon_fp_vmla_ddd")
- (const_string "neon_fp_vmla_qqq")))]
+ [(set_attr "type" "neon_fp_mla_s<q>")]
)
(define_insn "fma<VCVTF:mode>4_intrinsic"
@@ -616,10 +585,7 @@
(match_operand:VCVTF 3 "register_operand" "0")))]
"TARGET_NEON && TARGET_FMA"
"vfma%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
- [(set (attr "type")
- (if_then_else (match_test "<Is_d_reg>")
- (const_string "neon_fp_vmla_ddd")
- (const_string "neon_fp_vmla_qqq")))]
+ [(set_attr "type" "neon_fp_mla_s<q>")]
)
(define_insn "*fmsub<VCVTF:mode>4"
@@ -629,10 +595,7 @@
(match_operand:VCVTF 3 "register_operand" "0")))]
"TARGET_NEON && TARGET_FMA && flag_unsafe_math_optimizations"
"vfms%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
- [(set (attr "type")
- (if_then_else (match_test "<Is_d_reg>")
- (const_string "neon_fp_vmla_ddd")
- (const_string "neon_fp_vmla_qqq")))]
+ [(set_attr "type" "neon_fp_mla_s<q>")]
)
(define_insn "fmsub<VCVTF:mode>4_intrinsic"
@@ -642,10 +605,7 @@
(match_operand:VCVTF 3 "register_operand" "0")))]
"TARGET_NEON && TARGET_FMA"
"vfms%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
- [(set (attr "type")
- (if_then_else (match_test "<Is_d_reg>")
- (const_string "neon_fp_vmla_ddd")
- (const_string "neon_fp_vmla_qqq")))]
+ [(set_attr "type" "neon_fp_mla_s<q>")]
)
(define_insn "neon_vrint<NEON_VRINT:nvrint_variant><VCVTF:mode>"
@@ -655,10 +615,7 @@
NEON_VRINT))]
"TARGET_NEON && TARGET_FPU_ARMV8"
"vrint<nvrint_variant>%?.f32\\t%<V_reg>0, %<V_reg>1"
- [(set (attr "type")
- (if_then_else (match_test "<Is_d_reg>")
- (const_string "neon_fp_vadd_ddd_vabs_dd")
- (const_string "neon_fp_vadd_qqq_vabs_qq")))]
+ [(set_attr "type" "neon_fp_round_<V_elem_ch><q>")]
)
(define_insn "ior<mode>3"
@@ -675,7 +632,7 @@
default: gcc_unreachable ();
}
}
- [(set_attr "type" "neon_int_1")]
+ [(set_attr "type" "neon_logic<q>")]
)
;; The concrete forms of the Neon immediate-logic instructions are vbic and
@@ -697,7 +654,7 @@
default: gcc_unreachable ();
}
}
- [(set_attr "type" "neon_int_1")]
+ [(set_attr "type" "neon_logic<q>")]
)
(define_insn "orn<mode>3_neon"
@@ -706,7 +663,7 @@
(match_operand:VDQ 1 "s_register_operand" "w")))]
"TARGET_NEON"
"vorn\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
- [(set_attr "type" "neon_int_1")]
+ [(set_attr "type" "neon_logic<q>")]
)
;; TODO: investigate whether we should disable
@@ -744,7 +701,7 @@
DONE;
}
}"
- [(set_attr "type" "neon_int_1,*,*,*")
+ [(set_attr "type" "neon_logic,multiple,multiple,multiple")
(set_attr "length" "*,16,8,8")
(set_attr "arch" "any,a,t2,t2")]
)
@@ -755,7 +712,7 @@
(match_operand:VDQ 1 "s_register_operand" "w")))]
"TARGET_NEON"
"vbic\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
- [(set_attr "type" "neon_int_1")]
+ [(set_attr "type" "neon_logic<q>")]
)
;; Compare to *anddi_notdi_di.
@@ -768,7 +725,7 @@
vbic\t%P0, %P1, %P2
#
#"
- [(set_attr "type" "neon_int_1,*,*")
+ [(set_attr "type" "neon_logic,multiple,multiple")
(set_attr "length" "*,8,8")]
)
@@ -778,7 +735,7 @@
(match_operand:VDQ 2 "s_register_operand" "w")))]
"TARGET_NEON"
"veor\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
- [(set_attr "type" "neon_int_1")]
+ [(set_attr "type" "neon_logic<q>")]
)
(define_insn "one_cmpl<mode>2"
@@ -786,7 +743,7 @@
(not:VDQ (match_operand:VDQ 1 "s_register_operand" "w")))]
"TARGET_NEON"
"vmvn\t%<V_reg>0, %<V_reg>1"
- [(set_attr "type" "neon_int_1")]
+ [(set_attr "type" "neon_move<q>")]
)
(define_insn "abs<mode>2"
@@ -796,10 +753,8 @@
"vabs.<V_s_elem>\t%<V_reg>0, %<V_reg>1"
[(set (attr "type")
(if_then_else (match_test "<Is_float_mode>")
- (if_then_else (match_test "<Is_d_reg>")
- (const_string "neon_fp_vadd_ddd_vabs_dd")
- (const_string "neon_fp_vadd_qqq_vabs_qq"))
- (const_string "neon_int_3")))]
+ (const_string "neon_fp_abs_s<q>")
+ (const_string "neon_abs<q>")))]
)
(define_insn "neg<mode>2"
@@ -809,10 +764,8 @@
"vneg.<V_s_elem>\t%<V_reg>0, %<V_reg>1"
[(set (attr "type")
(if_then_else (match_test "<Is_float_mode>")
- (if_then_else (match_test "<Is_d_reg>")
- (const_string "neon_fp_vadd_ddd_vabs_dd")
- (const_string "neon_fp_vadd_qqq_vabs_qq"))
- (const_string "neon_int_3")))]
+ (const_string "neon_fp_neg_s<q>")
+ (const_string "neon_neg<q>")))]
)
(define_insn "negdi2_neon"
@@ -822,7 +775,8 @@
(clobber (reg:CC CC_REGNUM))]
"TARGET_NEON"
"#"
- [(set_attr "length" "8")]
+ [(set_attr "length" "8")
+ (set_attr "type" "multiple")]
)
; Split negdi2_neon for vfp registers
@@ -860,7 +814,7 @@
(match_operand:VDQIW 2 "s_register_operand" "w")))]
"TARGET_NEON"
"vmin.<V_u_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
- [(set_attr "type" "neon_int_5")]
+ [(set_attr "type" "neon_minmax<q>")]
)
(define_insn "*umax<mode>3_neon"
@@ -869,7 +823,7 @@
(match_operand:VDQIW 2 "s_register_operand" "w")))]
"TARGET_NEON"
"vmax.<V_u_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
- [(set_attr "type" "neon_int_5")]
+ [(set_attr "type" "neon_minmax<q>")]
)
(define_insn "*smin<mode>3_neon"
@@ -880,8 +834,8 @@
"vmin.<V_s_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
[(set (attr "type")
(if_then_else (match_test "<Is_float_mode>")
- (const_string "neon_fp_vadd_ddd_vabs_dd")
- (const_string "neon_int_5")))]
+ (const_string "neon_fp_minmax_s<q>")
+ (const_string "neon_minmax<q>")))]
)
(define_insn "*smax<mode>3_neon"
@@ -892,8 +846,8 @@
"vmax.<V_s_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
[(set (attr "type")
(if_then_else (match_test "<Is_float_mode>")
- (const_string "neon_fp_vadd_ddd_vabs_dd")
- (const_string "neon_int_5")))]
+ (const_string "neon_fp_minmax_s<q>")
+ (const_string "neon_minmax<q>")))]
)
; TODO: V2DI shifts are current disabled because there are bugs in the
@@ -916,10 +870,7 @@
default: gcc_unreachable ();
}
}
- [(set (attr "type")
- (if_then_else (match_test "<Is_d_reg>")
- (const_string "neon_vshl_ddd")
- (const_string "neon_shift_3")))]
+ [(set_attr "type" "neon_shift_reg<q>, neon_shift_imm<q>")]
)
(define_insn "vashr<mode>3_imm"
@@ -932,10 +883,7 @@
<MODE>mode, VALID_NEON_QREG_MODE (<MODE>mode),
false);
}
- [(set (attr "type")
- (if_then_else (match_test "<Is_d_reg>")
- (const_string "neon_vshl_ddd")
- (const_string "neon_shift_3")))]
+ [(set_attr "type" "neon_shift_imm<q>")]
)
(define_insn "vlshr<mode>3_imm"
@@ -948,10 +896,7 @@
<MODE>mode, VALID_NEON_QREG_MODE (<MODE>mode),
false);
}
- [(set (attr "type")
- (if_then_else (match_test "<Is_d_reg>")
- (const_string "neon_vshl_ddd")
- (const_string "neon_shift_3")))]
+ [(set_attr "type" "neon_shift_imm<q>")]
)
; Used for implementing logical shift-right, which is a left-shift by a negative
@@ -966,10 +911,7 @@
UNSPEC_ASHIFT_SIGNED))]
"TARGET_NEON"
"vshl.<V_s_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
- [(set (attr "type")
- (if_then_else (match_test "<Is_d_reg>")
- (const_string "neon_vshl_ddd")
- (const_string "neon_shift_3")))]
+ [(set_attr "type" "neon_shift_reg<q>")]
)
; Used for implementing logical shift-right, which is a left-shift by a negative
@@ -982,10 +924,7 @@
UNSPEC_ASHIFT_UNSIGNED))]
"TARGET_NEON"
"vshl.<V_u_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
- [(set (attr "type")
- (if_then_else (match_test "<Is_d_reg>")
- (const_string "neon_vshl_ddd")
- (const_string "neon_shift_3")))]
+ [(set_attr "type" "neon_shift_reg<q>")]
)
(define_expand "vashr<mode>3"
@@ -1037,7 +976,7 @@
"@
vld1.32\t{%P0[0]}, %A1
vmov.32\t%P0[0], %1"
- [(set_attr "type" "neon_vld1_vld2_lane,neon_mcr")]
+ [(set_attr "type" "neon_load1_1reg,neon_from_gp")]
)
(define_insn "ashldi3_neon_noclobber"
@@ -1050,7 +989,7 @@
"@
vshl.u64\t%P0, %P1, %2
vshl.u64\t%P0, %P1, %P2"
- [(set_attr "type" "neon_vshl_ddd,neon_vshl_ddd")]
+ [(set_attr "type" "neon_shift_imm, neon_shift_reg")]
)
(define_insn_and_split "ashldi3_neon"
@@ -1101,7 +1040,8 @@
DONE;
}"
[(set_attr "arch" "neon_for_64bits,neon_for_64bits,*,*,avoid_neon_for_64bits,avoid_neon_for_64bits")
- (set_attr "opt" "*,*,speed,speed,*,*")]
+ (set_attr "opt" "*,*,speed,speed,*,*")
+ (set_attr "type" "multiple")]
)
; The shift amount needs to be negated for right-shifts
@@ -1112,7 +1052,7 @@
UNSPEC_ASHIFT_SIGNED))]
"TARGET_NEON && reload_completed"
"vshl.s64\t%P0, %P1, %P2"
- [(set_attr "type" "neon_vshl_ddd")]
+ [(set_attr "type" "neon_shift_reg")]
)
; The shift amount needs to be negated for right-shifts
@@ -1123,7 +1063,7 @@
UNSPEC_ASHIFT_UNSIGNED))]
"TARGET_NEON && reload_completed"
"vshl.u64\t%P0, %P1, %P2"
- [(set_attr "type" "neon_vshl_ddd")]
+ [(set_attr "type" "neon_shift_reg")]
)
(define_insn "ashrdi3_neon_imm_noclobber"
@@ -1133,7 +1073,7 @@
"TARGET_NEON && reload_completed
&& INTVAL (operands[2]) > 0 && INTVAL (operands[2]) <= 64"
"vshr.s64\t%P0, %P1, %2"
- [(set_attr "type" "neon_vshl_ddd")]
+ [(set_attr "type" "neon_shift_imm")]
)
(define_insn "lshrdi3_neon_imm_noclobber"
@@ -1143,7 +1083,7 @@
"TARGET_NEON && reload_completed
&& INTVAL (operands[2]) > 0 && INTVAL (operands[2]) <= 64"
"vshr.u64\t%P0, %P1, %2"
- [(set_attr "type" "neon_vshl_ddd")]
+ [(set_attr "type" "neon_shift_imm")]
)
;; ashrdi3_neon
@@ -1202,7 +1142,8 @@
DONE;
}"
[(set_attr "arch" "neon_for_64bits,neon_for_64bits,*,*,avoid_neon_for_64bits,avoid_neon_for_64bits")
- (set_attr "opt" "*,*,speed,speed,*,*")]
+ (set_attr "opt" "*,*,speed,speed,*,*")
+ (set_attr "type" "multiple")]
)
;; Widening operations
@@ -1214,7 +1155,7 @@
(match_operand:<V_widen> 2 "s_register_operand" "w")))]
"TARGET_NEON"
"vaddw.<V_s_elem>\t%q0, %q2, %P1"
- [(set_attr "type" "neon_int_3")]
+ [(set_attr "type" "neon_add_widen")]
)
(define_insn "widen_usum<mode>3"
@@ -1224,7 +1165,7 @@
(match_operand:<V_widen> 2 "s_register_operand" "w")))]
"TARGET_NEON"
"vaddw.<V_u_elem>\t%q0, %q2, %P1"
- [(set_attr "type" "neon_int_3")]
+ [(set_attr "type" "neon_add_widen")]
)
;; VEXT can be used to synthesize coarse whole-vector shifts with 8-bit
@@ -1308,9 +1249,7 @@
"TARGET_NEON"
"<VQH_mnem>.<VQH_sign>32\t%P0, %e1, %f1"
[(set_attr "vqh_mnem" "<VQH_mnem>")
- (set (attr "type")
- (if_then_else (eq_attr "vqh_mnem" "vadd")
- (const_string "neon_int_1") (const_string "neon_int_5")))]
+ (set_attr "type" "neon_reduc_<VQH_type>_q")]
)
(define_insn "quad_halves_<code>v4sf"
@@ -1323,9 +1262,7 @@
"TARGET_NEON && flag_unsafe_math_optimizations"
"<VQH_mnem>.f32\t%P0, %e1, %f1"
[(set_attr "vqh_mnem" "<VQH_mnem>")
- (set (attr "type")
- (if_then_else (eq_attr "vqh_mnem" "vadd")
- (const_string "neon_int_1") (const_string "neon_int_5")))]
+ (set_attr "type" "neon_fp_reduc_<VQH_type>_s_q")]
)
(define_insn "quad_halves_<code>v8hi"
@@ -1340,9 +1277,7 @@
"TARGET_NEON"
"<VQH_mnem>.<VQH_sign>16\t%P0, %e1, %f1"
[(set_attr "vqh_mnem" "<VQH_mnem>")
- (set (attr "type")
- (if_then_else (eq_attr "vqh_mnem" "vadd")
- (const_string "neon_int_1") (const_string "neon_int_5")))]
+ (set_attr "type" "neon_reduc_<VQH_type>_q")]
)
(define_insn "quad_halves_<code>v16qi"
@@ -1361,9 +1296,7 @@
"TARGET_NEON"
"<VQH_mnem>.<VQH_sign>8\t%P0, %e1, %f1"
[(set_attr "vqh_mnem" "<VQH_mnem>")
- (set (attr "type")
- (if_then_else (eq_attr "vqh_mnem" "vadd")
- (const_string "neon_int_1") (const_string "neon_int_5")))]
+ (set_attr "type" "neon_reduc_<VQH_type>_q")]
)
(define_expand "move_hi_quad_<mode>"
@@ -1422,7 +1355,7 @@
UNSPEC_VPADD))]
"TARGET_NEON && !BYTES_BIG_ENDIAN"
"vadd.i64\t%e0, %e1, %f1"
- [(set_attr "type" "neon_int_1")]
+ [(set_attr "type" "neon_add_q")]
)
;; NEON does not distinguish between signed and unsigned addition except on
@@ -1548,10 +1481,8 @@
;; Assume this schedules like vadd.
[(set (attr "type")
(if_then_else (match_test "<Is_float_mode>")
- (if_then_else (match_test "<Is_d_reg>")
- (const_string "neon_fp_vadd_ddd_vabs_dd")
- (const_string "neon_fp_vadd_qqq_vabs_qq"))
- (const_string "neon_int_1")))]
+ (const_string "neon_fp_reduc_add_s<q>")
+ (const_string "neon_reduc_add<q>")))]
)
(define_insn "neon_vpsmin<mode>"
@@ -1561,11 +1492,10 @@
UNSPEC_VPSMIN))]
"TARGET_NEON"
"vpmin.<V_s_elem>\t%P0, %P1, %P2"
- ;; Assume this schedules like vmin.
[(set (attr "type")
(if_then_else (match_test "<Is_float_mode>")
- (const_string "neon_fp_vadd_ddd_vabs_dd")
- (const_string "neon_int_5")))]
+ (const_string "neon_fp_reduc_minmax_s<q>")
+ (const_string "neon_reduc_minmax<q>")))]
)
(define_insn "neon_vpsmax<mode>"
@@ -1575,11 +1505,10 @@
UNSPEC_VPSMAX))]
"TARGET_NEON"
"vpmax.<V_s_elem>\t%P0, %P1, %P2"
- ;; Assume this schedules like vmax.
[(set (attr "type")
(if_then_else (match_test "<Is_float_mode>")
- (const_string "neon_fp_vadd_ddd_vabs_dd")
- (const_string "neon_int_5")))]
+ (const_string "neon_fp_reduc_minmax_s<q>")
+ (const_string "neon_reduc_minmax<q>")))]
)
(define_insn "neon_vpumin<mode>"
@@ -1589,8 +1518,7 @@
UNSPEC_VPUMIN))]
"TARGET_NEON"
"vpmin.<V_u_elem>\t%P0, %P1, %P2"
- ;; Assume this schedules like umin.
- [(set_attr "type" "neon_int_5")]
+ [(set_attr "type" "neon_reduc_minmax<q>")]
)
(define_insn "neon_vpumax<mode>"
@@ -1600,8 +1528,7 @@
UNSPEC_VPUMAX))]
"TARGET_NEON"
"vpmax.<V_u_elem>\t%P0, %P1, %P2"
- ;; Assume this schedules like umax.
- [(set_attr "type" "neon_int_5")]
+ [(set_attr "type" "neon_reduc_minmax<q>")]
)
;; Saturating arithmetic
@@ -1618,7 +1545,7 @@
(match_operand:VD 2 "s_register_operand" "w")))]
"TARGET_NEON"
"vqadd.<V_s_elem>\t%P0, %P1, %P2"
- [(set_attr "type" "neon_int_4")]
+ [(set_attr "type" "neon_qadd<q>")]
)
(define_insn "*us_add<mode>_neon"
@@ -1627,7 +1554,7 @@
(match_operand:VD 2 "s_register_operand" "w")))]
"TARGET_NEON"
"vqadd.<V_u_elem>\t%P0, %P1, %P2"
- [(set_attr "type" "neon_int_4")]
+ [(set_attr "type" "neon_qadd<q>")]
)
(define_insn "*ss_sub<mode>_neon"
@@ -1636,7 +1563,7 @@
(match_operand:VD 2 "s_register_operand" "w")))]
"TARGET_NEON"
"vqsub.<V_s_elem>\t%P0, %P1, %P2"
- [(set_attr "type" "neon_int_5")]
+ [(set_attr "type" "neon_qsub<q>")]
)
(define_insn "*us_sub<mode>_neon"
@@ -1645,7 +1572,7 @@
(match_operand:VD 2 "s_register_operand" "w")))]
"TARGET_NEON"
"vqsub.<V_u_elem>\t%P0, %P1, %P2"
- [(set_attr "type" "neon_int_5")]
+ [(set_attr "type" "neon_qsub<q>")]
)
;; Conditional instructions. These are comparisons with conditional moves for
@@ -1939,10 +1866,8 @@
"vadd.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
[(set (attr "type")
(if_then_else (match_test "<Is_float_mode>")
- (if_then_else (match_test "<Is_d_reg>")
- (const_string "neon_fp_vadd_ddd_vabs_dd")
- (const_string "neon_fp_vadd_qqq_vabs_qq"))
- (const_string "neon_int_1")))]
+ (const_string "neon_fp_addsub_s<q>")
+ (const_string "neon_add<q>")))]
)
; operand 3 represents in bits:
@@ -1957,7 +1882,7 @@
UNSPEC_VADDL))]
"TARGET_NEON"
"vaddl.%T3%#<V_sz_elem>\t%q0, %P1, %P2"
- [(set_attr "type" "neon_int_3")]
+ [(set_attr "type" "neon_add_long")]
)
(define_insn "neon_vaddw<mode>"
@@ -1968,7 +1893,7 @@
UNSPEC_VADDW))]
"TARGET_NEON"
"vaddw.%T3%#<V_sz_elem>\t%q0, %q1, %P2"
- [(set_attr "type" "neon_int_2")]
+ [(set_attr "type" "neon_add_widen")]
)
; vhadd and vrhadd.
@@ -1981,7 +1906,7 @@
UNSPEC_VHADD))]
"TARGET_NEON"
"v%O3hadd.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
- [(set_attr "type" "neon_int_4")]
+ [(set_attr "type" "neon_add_halve_q")]
)
(define_insn "neon_vqadd<mode>"
@@ -1992,7 +1917,7 @@
UNSPEC_VQADD))]
"TARGET_NEON"
"vqadd.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
- [(set_attr "type" "neon_int_4")]
+ [(set_attr "type" "neon_qadd<q>")]
)
(define_insn "neon_vaddhn<mode>"
@@ -2003,7 +1928,7 @@
UNSPEC_VADDHN))]
"TARGET_NEON"
"v%O3addhn.<V_if_elem>\t%P0, %q1, %q2"
- [(set_attr "type" "neon_int_4")]
+ [(set_attr "type" "neon_add_halve_narrow_q")]
)
;; We cannot replace this unspec with mul<mode>3 because of the odd
@@ -2018,17 +1943,8 @@
"vmul.%F3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
[(set (attr "type")
(if_then_else (match_test "<Is_float_mode>")
- (if_then_else (match_test "<Is_d_reg>")
- (const_string "neon_fp_vadd_ddd_vabs_dd")
- (const_string "neon_fp_vadd_qqq_vabs_qq"))
- (if_then_else (match_test "<Is_d_reg>")
- (if_then_else
- (match_test "<Scalar_mul_8_16>")
- (const_string "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long")
- (const_string "neon_mul_qqq_8_16_32_ddd_32"))
- (if_then_else (match_test "<Scalar_mul_8_16>")
- (const_string "neon_mul_qqq_8_16_32_ddd_32")
- (const_string "neon_mul_qqq_8_16_32_ddd_32")))))]
+ (const_string "neon_fp_mul_s<q>")
+ (const_string "neon_mul_<V_elem_ch><q>")))]
)
(define_expand "neon_vmla<mode>"
@@ -2077,26 +1993,17 @@
; Used for intrinsics when flag_unsafe_math_optimizations is false.
(define_insn "neon_vmla<mode>_unspec"
- [(set (match_operand:VDQ 0 "s_register_operand" "=w")
- (unspec:VDQ [(match_operand:VDQ 1 "s_register_operand" "0")
- (match_operand:VDQ 2 "s_register_operand" "w")
- (match_operand:VDQ 3 "s_register_operand" "w")]
+ [(set (match_operand:VDQW 0 "s_register_operand" "=w")
+ (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "0")
+ (match_operand:VDQW 2 "s_register_operand" "w")
+ (match_operand:VDQW 3 "s_register_operand" "w")]
UNSPEC_VMLA))]
"TARGET_NEON"
"vmla.<V_if_elem>\t%<V_reg>0, %<V_reg>2, %<V_reg>3"
[(set (attr "type")
(if_then_else (match_test "<Is_float_mode>")
- (if_then_else (match_test "<Is_d_reg>")
- (const_string "neon_fp_vmla_ddd")
- (const_string "neon_fp_vmla_qqq"))
- (if_then_else (match_test "<Is_d_reg>")
- (if_then_else
- (match_test "<Scalar_mul_8_16>")
- (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
- (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long"))
- (if_then_else (match_test "<Scalar_mul_8_16>")
- (const_string "neon_mla_qqq_8_16")
- (const_string "neon_mla_qqq_32_qqd_32_scalar")))))]
+ (const_string "neon_fp_mla_s<q>")
+ (const_string "neon_mla_<V_elem_ch><q>")))]
)
(define_insn "neon_vmlal<mode>"
@@ -2108,10 +2015,7 @@
UNSPEC_VMLAL))]
"TARGET_NEON"
"vmlal.%T4%#<V_sz_elem>\t%q0, %P2, %P3"
- [(set (attr "type")
- (if_then_else (match_test "<Scalar_mul_8_16>")
- (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
- (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
+ [(set_attr "type" "neon_mla_<V_elem_ch>_long")]
)
(define_expand "neon_vmls<mode>"
@@ -2134,27 +2038,17 @@
; Used for intrinsics when flag_unsafe_math_optimizations is false.
(define_insn "neon_vmls<mode>_unspec"
- [(set (match_operand:VDQ 0 "s_register_operand" "=w")
- (unspec:VDQ [(match_operand:VDQ 1 "s_register_operand" "0")
- (match_operand:VDQ 2 "s_register_operand" "w")
- (match_operand:VDQ 3 "s_register_operand" "w")]
+ [(set (match_operand:VDQW 0 "s_register_operand" "=w")
+ (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "0")
+ (match_operand:VDQW 2 "s_register_operand" "w")
+ (match_operand:VDQW 3 "s_register_operand" "w")]
UNSPEC_VMLS))]
"TARGET_NEON"
"vmls.<V_if_elem>\t%<V_reg>0, %<V_reg>2, %<V_reg>3"
[(set (attr "type")
(if_then_else (match_test "<Is_float_mode>")
- (if_then_else (match_test "<Is_d_reg>")
- (const_string "neon_fp_vmla_ddd")
- (const_string "neon_fp_vmla_qqq"))
- (if_then_else (match_test "<Is_d_reg>")
- (if_then_else
- (match_test "<Scalar_mul_8_16>")
- (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
- (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long"))
- (if_then_else
- (match_test "<Scalar_mul_8_16>")
- (const_string "neon_mla_qqq_8_16")
- (const_string "neon_mla_qqq_32_qqd_32_scalar")))))]
+ (const_string "neon_fp_mla_s<q>")
+ (const_string "neon_mla_<V_elem_ch><q>")))]
)
(define_insn "neon_vmlsl<mode>"
@@ -2166,10 +2060,7 @@
UNSPEC_VMLSL))]
"TARGET_NEON"
"vmlsl.%T4%#<V_sz_elem>\t%q0, %P2, %P3"
- [(set (attr "type")
- (if_then_else (match_test "<Scalar_mul_8_16>")
- (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
- (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
+ [(set_attr "type" "neon_mla_<V_elem_ch>_long")]
)
(define_insn "neon_vqdmulh<mode>"
@@ -2180,14 +2071,7 @@
UNSPEC_VQDMULH))]
"TARGET_NEON"
"vq%O3dmulh.<V_s_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
- [(set (attr "type")
- (if_then_else (match_test "<Is_d_reg>")
- (if_then_else (match_test "<Scalar_mul_8_16>")
- (const_string "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long")
- (const_string "neon_mul_qqq_8_16_32_ddd_32"))
- (if_then_else (match_test "<Scalar_mul_8_16>")
- (const_string "neon_mul_qqq_8_16_32_ddd_32")
- (const_string "neon_mul_qqq_8_16_32_ddd_32"))))]
+ [(set_attr "type" "neon_sat_mul_<V_elem_ch><q>")]
)
(define_insn "neon_vqdmlal<mode>"
@@ -2199,10 +2083,7 @@
UNSPEC_VQDMLAL))]
"TARGET_NEON"
"vqdmlal.<V_s_elem>\t%q0, %P2, %P3"
- [(set (attr "type")
- (if_then_else (match_test "<Scalar_mul_8_16>")
- (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
- (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
+ [(set_attr "type" "neon_sat_mla_<V_elem_ch>_long")]
)
(define_insn "neon_vqdmlsl<mode>"
@@ -2214,10 +2095,7 @@
UNSPEC_VQDMLSL))]
"TARGET_NEON"
"vqdmlsl.<V_s_elem>\t%q0, %P2, %P3"
- [(set (attr "type")
- (if_then_else (match_test "<Scalar_mul_8_16>")
- (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
- (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
+ [(set_attr "type" "neon_sat_mla_<V_elem_ch>_long")]
)
(define_insn "neon_vmull<mode>"
@@ -2228,10 +2106,7 @@
UNSPEC_VMULL))]
"TARGET_NEON"
"vmull.%T3%#<V_sz_elem>\t%q0, %P1, %P2"
- [(set (attr "type")
- (if_then_else (match_test "<Scalar_mul_8_16>")
- (const_string "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long")
- (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")))]
+ [(set_attr "type" "neon_mul_<V_elem_ch>_long")]
)
(define_insn "neon_vqdmull<mode>"
@@ -2242,10 +2117,7 @@
UNSPEC_VQDMULL))]
"TARGET_NEON"
"vqdmull.<V_s_elem>\t%q0, %P1, %P2"
- [(set (attr "type")
- (if_then_else (match_test "<Scalar_mul_8_16>")
- (const_string "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long")
- (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")))]
+ [(set_attr "type" "neon_sat_mul_<V_elem_ch>_long")]
)
(define_expand "neon_vsub<mode>"
@@ -2274,10 +2146,8 @@
"vsub.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
[(set (attr "type")
(if_then_else (match_test "<Is_float_mode>")
- (if_then_else (match_test "<Is_d_reg>")
- (const_string "neon_fp_vadd_ddd_vabs_dd")
- (const_string "neon_fp_vadd_qqq_vabs_qq"))
- (const_string "neon_int_2")))]
+ (const_string "neon_fp_addsub_s<q>")
+ (const_string "neon_sub<q>")))]
)
(define_insn "neon_vsubl<mode>"
@@ -2288,7 +2158,7 @@
UNSPEC_VSUBL))]
"TARGET_NEON"
"vsubl.%T3%#<V_sz_elem>\t%q0, %P1, %P2"
- [(set_attr "type" "neon_int_2")]
+ [(set_attr "type" "neon_sub_long")]
)
(define_insn "neon_vsubw<mode>"
@@ -2299,7 +2169,7 @@
UNSPEC_VSUBW))]
"TARGET_NEON"
"vsubw.%T3%#<V_sz_elem>\t%q0, %q1, %P2"
- [(set_attr "type" "neon_int_2")]
+ [(set_attr "type" "neon_sub_widen")]
)
(define_insn "neon_vqsub<mode>"
@@ -2310,7 +2180,7 @@
UNSPEC_VQSUB))]
"TARGET_NEON"
"vqsub.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
- [(set_attr "type" "neon_int_5")]
+ [(set_attr "type" "neon_qsub<q>")]
)
(define_insn "neon_vhsub<mode>"
@@ -2321,7 +2191,7 @@
UNSPEC_VHSUB))]
"TARGET_NEON"
"vhsub.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
- [(set_attr "type" "neon_int_5")]
+ [(set_attr "type" "neon_sub_halve<q>")]
)
(define_insn "neon_vsubhn<mode>"
@@ -2332,7 +2202,7 @@
UNSPEC_VSUBHN))]
"TARGET_NEON"
"v%O3subhn.<V_if_elem>\t%P0, %q1, %q2"
- [(set_attr "type" "neon_int_4")]
+ [(set_attr "type" "neon_sub_halve_narrow_q")]
)
(define_insn "neon_vceq<mode>"
@@ -2348,10 +2218,10 @@
vceq.<V_if_elem>\t%<V_reg>0, %<V_reg>1, #0"
[(set (attr "type")
(if_then_else (match_test "<Is_float_mode>")
- (if_then_else (match_test "<Is_d_reg>")
- (const_string "neon_fp_vadd_ddd_vabs_dd")
- (const_string "neon_fp_vadd_qqq_vabs_qq"))
- (const_string "neon_int_5")))]
+ (const_string "neon_fp_compare_s<q>")
+ (if_then_else (match_operand 2 "zero_operand")
+ (const_string "neon_compare_zero<q>")
+ (const_string "neon_compare<q>"))))]
)
(define_insn "neon_vcge<mode>"
@@ -2367,10 +2237,10 @@
vcge.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, #0"
[(set (attr "type")
(if_then_else (match_test "<Is_float_mode>")
- (if_then_else (match_test "<Is_d_reg>")
- (const_string "neon_fp_vadd_ddd_vabs_dd")
- (const_string "neon_fp_vadd_qqq_vabs_qq"))
- (const_string "neon_int_5")))]
+ (const_string "neon_fp_compare_s<q>")
+ (if_then_else (match_operand 2 "zero_operand")
+ (const_string "neon_compare_zero<q>")
+ (const_string "neon_compare<q>"))))]
)
(define_insn "neon_vcgeu<mode>"
@@ -2382,7 +2252,7 @@
UNSPEC_VCGEU))]
"TARGET_NEON"
"vcge.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
- [(set_attr "type" "neon_int_5")]
+ [(set_attr "type" "neon_compare<q>")]
)
(define_insn "neon_vcgt<mode>"
@@ -2398,10 +2268,10 @@
vcgt.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, #0"
[(set (attr "type")
(if_then_else (match_test "<Is_float_mode>")
- (if_then_else (match_test "<Is_d_reg>")
- (const_string "neon_fp_vadd_ddd_vabs_dd")
- (const_string "neon_fp_vadd_qqq_vabs_qq"))
- (const_string "neon_int_5")))]
+ (const_string "neon_fp_compare_s<q>")
+ (if_then_else (match_operand 2 "zero_operand")
+ (const_string "neon_compare_zero<q>")
+ (const_string "neon_compare<q>"))))]
)
(define_insn "neon_vcgtu<mode>"
@@ -2413,7 +2283,7 @@
UNSPEC_VCGTU))]
"TARGET_NEON"
"vcgt.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
- [(set_attr "type" "neon_int_5")]
+ [(set_attr "type" "neon_compare<q>")]
)
;; VCLE and VCLT only support comparisons with immediate zero (register
@@ -2430,10 +2300,10 @@
"vcle.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, #0"
[(set (attr "type")
(if_then_else (match_test "<Is_float_mode>")
- (if_then_else (match_test "<Is_d_reg>")
- (const_string "neon_fp_vadd_ddd_vabs_dd")
- (const_string "neon_fp_vadd_qqq_vabs_qq"))
- (const_string "neon_int_5")))]
+ (const_string "neon_fp_compare_s<q>")
+ (if_then_else (match_operand 2 "zero_operand")
+ (const_string "neon_compare_zero<q>")
+ (const_string "neon_compare<q>"))))]
)
(define_insn "neon_vclt<mode>"
@@ -2447,10 +2317,10 @@
"vclt.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, #0"
[(set (attr "type")
(if_then_else (match_test "<Is_float_mode>")
- (if_then_else (match_test "<Is_d_reg>")
- (const_string "neon_fp_vadd_ddd_vabs_dd")
- (const_string "neon_fp_vadd_qqq_vabs_qq"))
- (const_string "neon_int_5")))]
+ (const_string "neon_fp_compare_s<q>")
+ (if_then_else (match_operand 2 "zero_operand")
+ (const_string "neon_compare_zero<q>")
+ (const_string "neon_compare<q>"))))]
)
(define_insn "neon_vcage<mode>"
@@ -2461,10 +2331,7 @@
UNSPEC_VCAGE))]
"TARGET_NEON"
"vacge.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
- [(set (attr "type")
- (if_then_else (match_test "<Is_d_reg>")
- (const_string "neon_fp_vadd_ddd_vabs_dd")
- (const_string "neon_fp_vadd_qqq_vabs_qq")))]
+ [(set_attr "type" "neon_fp_compare_s<q>")]
)
(define_insn "neon_vcagt<mode>"
@@ -2475,10 +2342,7 @@
UNSPEC_VCAGT))]
"TARGET_NEON"
"vacgt.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
- [(set (attr "type")
- (if_then_else (match_test "<Is_d_reg>")
- (const_string "neon_fp_vadd_ddd_vabs_dd")
- (const_string "neon_fp_vadd_qqq_vabs_qq")))]
+ [(set_attr "type" "neon_fp_compare_s<q>")]
)
(define_insn "neon_vtst<mode>"
@@ -2489,7 +2353,7 @@
UNSPEC_VTST))]
"TARGET_NEON"
"vtst.<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
- [(set_attr "type" "neon_int_4")]
+ [(set_attr "type" "neon_tst<q>")]
)
(define_insn "neon_vabd<mode>"
@@ -2502,10 +2366,8 @@
"vabd.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
[(set (attr "type")
(if_then_else (match_test "<Is_float_mode>")
- (if_then_else (match_test "<Is_d_reg>")
- (const_string "neon_fp_vadd_ddd_vabs_dd")
- (const_string "neon_fp_vadd_qqq_vabs_qq"))
- (const_string "neon_int_5")))]
+ (const_string "neon_fp_abd_s<q>")
+ (const_string "neon_abd<q>")))]
)
(define_insn "neon_vabdl<mode>"
@@ -2516,7 +2378,7 @@
UNSPEC_VABDL))]
"TARGET_NEON"
"vabdl.%T3%#<V_sz_elem>\t%q0, %P1, %P2"
- [(set_attr "type" "neon_int_5")]
+ [(set_attr "type" "neon_abd_long")]
)
(define_insn "neon_vaba<mode>"
@@ -2528,9 +2390,7 @@
(match_operand:VDQIW 1 "s_register_operand" "0")))]
"TARGET_NEON"
"vaba.%T4%#<V_sz_elem>\t%<V_reg>0, %<V_reg>2, %<V_reg>3"
- [(set (attr "type")
- (if_then_else (match_test "<Is_d_reg>")
- (const_string "neon_vaba") (const_string "neon_vaba_qqq")))]
+ [(set_attr "type" "neon_arith_acc<q>")]
)
(define_insn "neon_vabal<mode>"
@@ -2542,7 +2402,7 @@
(match_operand:<V_widen> 1 "s_register_operand" "0")))]
"TARGET_NEON"
"vabal.%T4%#<V_sz_elem>\t%q0, %P2, %P3"
- [(set_attr "type" "neon_vaba")]
+ [(set_attr "type" "neon_arith_acc<q>")]
)
(define_insn "neon_vmax<mode>"
@@ -2555,10 +2415,8 @@
"vmax.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
[(set (attr "type")
(if_then_else (match_test "<Is_float_mode>")
- (if_then_else (match_test "<Is_d_reg>")
- (const_string "neon_fp_vadd_ddd_vabs_dd")
- (const_string "neon_fp_vadd_qqq_vabs_qq"))
- (const_string "neon_int_5")))]
+ (const_string "neon_fp_minmax_s<q>")
+ (const_string "neon_minmax<q>")))]
)
(define_insn "neon_vmin<mode>"
@@ -2571,10 +2429,8 @@
"vmin.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
[(set (attr "type")
(if_then_else (match_test "<Is_float_mode>")
- (if_then_else (match_test "<Is_d_reg>")
- (const_string "neon_fp_vadd_ddd_vabs_dd")
- (const_string "neon_fp_vadd_qqq_vabs_qq"))
- (const_string "neon_int_5")))]
+ (const_string "neon_fp_minmax_s<q>")
+ (const_string "neon_minmax<q>")))]
)
(define_expand "neon_vpadd<mode>"
@@ -2596,8 +2452,7 @@
UNSPEC_VPADDL))]
"TARGET_NEON"
"vpaddl.%T2%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1"
- ;; Assume this schedules like vaddl.
- [(set_attr "type" "neon_int_3")]
+ [(set_attr "type" "neon_reduc_add_long")]
)
(define_insn "neon_vpadal<mode>"
@@ -2608,8 +2463,7 @@
UNSPEC_VPADAL))]
"TARGET_NEON"
"vpadal.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>2"
- ;; Assume this schedules like vpadd.
- [(set_attr "type" "neon_int_1")]
+ [(set_attr "type" "neon_reduc_add_acc")]
)
(define_insn "neon_vpmax<mode>"
@@ -2620,11 +2474,10 @@
UNSPEC_VPMAX))]
"TARGET_NEON"
"vpmax.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
- ;; Assume this schedules like vmax.
[(set (attr "type")
(if_then_else (match_test "<Is_float_mode>")
- (const_string "neon_fp_vadd_ddd_vabs_dd")
- (const_string "neon_int_5")))]
+ (const_string "neon_fp_reduc_minmax_s<q>")
+ (const_string "neon_reduc_minmax<q>")))]
)
(define_insn "neon_vpmin<mode>"
@@ -2635,11 +2488,10 @@
UNSPEC_VPMIN))]
"TARGET_NEON"
"vpmin.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
- ;; Assume this schedules like vmin.
[(set (attr "type")
(if_then_else (match_test "<Is_float_mode>")
- (const_string "neon_fp_vadd_ddd_vabs_dd")
- (const_string "neon_int_5")))]
+ (const_string "neon_fp_reduc_minmax_s<q>")
+ (const_string "neon_reduc_minmax<q>")))]
)
(define_insn "neon_vrecps<mode>"
@@ -2650,10 +2502,7 @@
UNSPEC_VRECPS))]
"TARGET_NEON"
"vrecps.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
- [(set (attr "type")
- (if_then_else (match_test "<Is_d_reg>")
- (const_string "neon_fp_vrecps_vrsqrts_ddd")
- (const_string "neon_fp_vrecps_vrsqrts_qqq")))]
+ [(set_attr "type" "neon_fp_recps_s<q>")]
)
(define_insn "neon_vrsqrts<mode>"
@@ -2664,10 +2513,7 @@
UNSPEC_VRSQRTS))]
"TARGET_NEON"
"vrsqrts.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
- [(set (attr "type")
- (if_then_else (match_test "<Is_d_reg>")
- (const_string "neon_fp_vrecps_vrsqrts_ddd")
- (const_string "neon_fp_vrecps_vrsqrts_qqq")))]
+ [(set_attr "type" "neon_fp_rsqrts_s<q>")]
)
(define_expand "neon_vabs<mode>"
@@ -2687,7 +2533,7 @@
UNSPEC_VQABS))]
"TARGET_NEON"
"vqabs.<V_s_elem>\t%<V_reg>0, %<V_reg>1"
- [(set_attr "type" "neon_vqneg_vqabs")]
+ [(set_attr "type" "neon_qabs<q>")]
)
(define_expand "neon_vneg<mode>"
@@ -2707,7 +2553,7 @@
UNSPEC_VQNEG))]
"TARGET_NEON"
"vqneg.<V_s_elem>\t%<V_reg>0, %<V_reg>1"
- [(set_attr "type" "neon_vqneg_vqabs")]
+ [(set_attr "type" "neon_qneg<q>")]
)
(define_insn "neon_vcls<mode>"
@@ -2717,7 +2563,7 @@
UNSPEC_VCLS))]
"TARGET_NEON"
"vcls.<V_s_elem>\t%<V_reg>0, %<V_reg>1"
- [(set_attr "type" "neon_int_1")]
+ [(set_attr "type" "neon_cls<q>")]
)
(define_insn "clz<mode>2"
@@ -2725,7 +2571,7 @@
(clz:VDQIW (match_operand:VDQIW 1 "s_register_operand" "w")))]
"TARGET_NEON"
"vclz.<V_if_elem>\t%<V_reg>0, %<V_reg>1"
- [(set_attr "type" "neon_int_1")]
+ [(set_attr "type" "neon_cnt<q>")]
)
(define_expand "neon_vclz<mode>"
@@ -2743,7 +2589,7 @@
(popcount:VE (match_operand:VE 1 "s_register_operand" "w")))]
"TARGET_NEON"
"vcnt.<V_sz_elem>\t%<V_reg>0, %<V_reg>1"
- [(set_attr "type" "neon_int_1")]
+ [(set_attr "type" "neon_cnt<q>")]
)
(define_expand "neon_vcnt<mode>"
@@ -2763,10 +2609,7 @@
UNSPEC_VRECPE))]
"TARGET_NEON"
"vrecpe.<V_u_elem>\t%<V_reg>0, %<V_reg>1"
- [(set (attr "type")
- (if_then_else (match_test "<Is_d_reg>")
- (const_string "neon_fp_vadd_ddd_vabs_dd")
- (const_string "neon_fp_vadd_qqq_vabs_qq")))]
+ [(set_attr "type" "neon_fp_recpe_s<q>")]
)
(define_insn "neon_vrsqrte<mode>"
@@ -2776,10 +2619,7 @@
UNSPEC_VRSQRTE))]
"TARGET_NEON"
"vrsqrte.<V_u_elem>\t%<V_reg>0, %<V_reg>1"
- [(set (attr "type")
- (if_then_else (match_test "<Is_d_reg>")
- (const_string "neon_fp_vadd_ddd_vabs_dd")
- (const_string "neon_fp_vadd_qqq_vabs_qq")))]
+ [(set_attr "type" "neon_fp_rsqrte_s<q>")]
)
(define_expand "neon_vmvn<mode>"
@@ -2808,7 +2648,7 @@
}
return "vmov.s<V_sz_elem>\t%0, %P1[%c2]";
}
- [(set_attr "type" "neon_bp_simple")]
+ [(set_attr "type" "neon_to_gp")]
)
(define_insn "neon_vget_lane<mode>_zext_internal"
@@ -2827,7 +2667,7 @@
}
return "vmov.u<V_sz_elem>\t%0, %P1[%c2]";
}
- [(set_attr "type" "neon_bp_simple")]
+ [(set_attr "type" "neon_to_gp")]
)
(define_insn "neon_vget_lane<mode>_sext_internal"
@@ -2854,7 +2694,7 @@
return "";
}
- [(set_attr "type" "neon_bp_simple")]
+ [(set_attr "type" "neon_to_gp_q")]
)
(define_insn "neon_vget_lane<mode>_zext_internal"
@@ -2881,7 +2721,7 @@
return "";
}
- [(set_attr "type" "neon_bp_simple")]
+ [(set_attr "type" "neon_to_gp_q")]
)
(define_expand "neon_vget_lane<mode>"
@@ -3013,8 +2853,7 @@
(vec_duplicate:VX (match_operand:<V_elem> 1 "s_register_operand" "r")))]
"TARGET_NEON"
"vdup.<V_sz_elem>\t%<V_reg>0, %1"
- ;; Assume this schedules like vmov.
- [(set_attr "type" "neon_bp_simple")]
+ [(set_attr "type" "neon_from_gp<q>")]
)
(define_insn "neon_vdup_n<mode>"
@@ -3024,8 +2863,7 @@
"@
vdup.<V_sz_elem>\t%<V_reg>0, %1
vdup.<V_sz_elem>\t%<V_reg>0, %y1"
- ;; Assume this schedules like vmov.
- [(set_attr "type" "neon_bp_simple")]
+ [(set_attr "type" "neon_from_gp<q>,neon_dup<q>")]
)
(define_expand "neon_vdup_ndi"
@@ -3046,7 +2884,7 @@
vmov\t%e0, %Q1, %R1\;vmov\t%f0, %Q1, %R1
vmov\t%e0, %P1\;vmov\t%f0, %P1"
[(set_attr "length" "8")
- (set_attr "type" "neon_bp_simple")]
+ (set_attr "type" "multiple")]
)
(define_insn "neon_vdup_lane<mode>_internal"
@@ -3068,8 +2906,7 @@
else
return "vdup.<V_sz_elem>\t%q0, %P1[%c2]";
}
- ;; Assume this schedules like vmov.
- [(set_attr "type" "neon_bp_simple")]
+ [(set_attr "type" "neon_dup<q>")]
)
(define_expand "neon_vdup_lane<mode>"
@@ -3124,10 +2961,7 @@
(set (match_dup 1) (match_dup 0))]
"TARGET_NEON && reload_completed"
"vswp\t%<V_reg>0, %<V_reg>1"
- [(set (attr "type")
- (if_then_else (match_test "<Is_d_reg>")
- (const_string "neon_bp_simple")
- (const_string "neon_bp_2cycle")))]
+ [(set_attr "type" "neon_permute<q>")]
)
;; In this insn, operand 1 should be low, and operand 2 the high part of the
@@ -3149,7 +2983,9 @@
{
neon_split_vcombine (operands);
DONE;
-})
+}
+[(set_attr "type" "multiple")]
+)
(define_expand "neon_vget_high<mode>"
[(match_operand:<V_HALF> 0 "s_register_operand")
@@ -3178,10 +3014,7 @@
(float:<V_CVTTO> (match_operand:VCVTI 1 "s_register_operand" "w")))]
"TARGET_NEON && !flag_rounding_math"
"vcvt.f32.s32\t%<V_reg>0, %<V_reg>1"
- [(set (attr "type")
- (if_then_else (match_test "<Is_d_reg>")
- (const_string "neon_fp_vadd_ddd_vabs_dd")
- (const_string "neon_fp_vadd_qqq_vabs_qq")))]
+ [(set_attr "type" "neon_int_to_fp_<V_elem_ch><q>")]
)
(define_insn "floatuns<mode><V_cvtto>2"
@@ -3189,10 +3022,7 @@
(unsigned_float:<V_CVTTO> (match_operand:VCVTI 1 "s_register_operand" "w")))]
"TARGET_NEON && !flag_rounding_math"
"vcvt.f32.u32\t%<V_reg>0, %<V_reg>1"
- [(set (attr "type")
- (if_then_else (match_test "<Is_d_reg>")
- (const_string "neon_fp_vadd_ddd_vabs_dd")
- (const_string "neon_fp_vadd_qqq_vabs_qq")))]
+ [(set_attr "type" "neon_int_to_fp_<V_elem_ch><q>")]
)
(define_insn "fix_trunc<mode><V_cvtto>2"
@@ -3200,10 +3030,7 @@
(fix:<V_CVTTO> (match_operand:VCVTF 1 "s_register_operand" "w")))]
"TARGET_NEON"
"vcvt.s32.f32\t%<V_reg>0, %<V_reg>1"
- [(set (attr "type")
- (if_then_else (match_test "<Is_d_reg>")
- (const_string "neon_fp_vadd_ddd_vabs_dd")
- (const_string "neon_fp_vadd_qqq_vabs_qq")))]
+ [(set_attr "type" "neon_fp_to_int_<V_elem_ch><q>")]
)
(define_insn "fixuns_trunc<mode><V_cvtto>2"
@@ -3211,10 +3038,7 @@
(unsigned_fix:<V_CVTTO> (match_operand:VCVTF 1 "s_register_operand" "w")))]
"TARGET_NEON"
"vcvt.u32.f32\t%<V_reg>0, %<V_reg>1"
- [(set (attr "type")
- (if_then_else (match_test "<Is_d_reg>")
- (const_string "neon_fp_vadd_ddd_vabs_dd")
- (const_string "neon_fp_vadd_qqq_vabs_qq")))]
+ [(set_attr "type" "neon_fp_to_int_<V_elem_ch><q>")]
)
(define_insn "neon_vcvt<mode>"
@@ -3224,10 +3048,7 @@
UNSPEC_VCVT))]
"TARGET_NEON"
"vcvt.%T2%#32.f32\t%<V_reg>0, %<V_reg>1"
- [(set (attr "type")
- (if_then_else (match_test "<Is_d_reg>")
- (const_string "neon_fp_vadd_ddd_vabs_dd")
- (const_string "neon_fp_vadd_qqq_vabs_qq")))]
+ [(set_attr "type" "neon_fp_to_int_<V_elem_ch><q>")]
)
(define_insn "neon_vcvt<mode>"
@@ -3237,10 +3058,7 @@
UNSPEC_VCVT))]
"TARGET_NEON"
"vcvt.f32.%T2%#32\t%<V_reg>0, %<V_reg>1"
- [(set (attr "type")
- (if_then_else (match_test "<Is_d_reg>")
- (const_string "neon_fp_vadd_ddd_vabs_dd")
- (const_string "neon_fp_vadd_qqq_vabs_qq")))]
+ [(set_attr "type" "neon_int_to_fp_<V_elem_ch><q>")]
)
(define_insn "neon_vcvtv4sfv4hf"
@@ -3249,7 +3067,7 @@
UNSPEC_VCVT))]
"TARGET_NEON && TARGET_FP16"
"vcvt.f32.f16\t%q0, %P1"
- [(set_attr "type" "neon_fp_vadd_ddd_vabs_dd")]
+ [(set_attr "type" "neon_fp_cvt_widen_h")]
)
(define_insn "neon_vcvtv4hfv4sf"
@@ -3258,7 +3076,7 @@
UNSPEC_VCVT))]
"TARGET_NEON && TARGET_FP16"
"vcvt.f16.f32\t%P0, %q1"
- [(set_attr "type" "neon_fp_vadd_ddd_vabs_dd")]
+ [(set_attr "type" "neon_fp_cvt_narrow_s_q")]
)
(define_insn "neon_vcvt_n<mode>"
@@ -3272,10 +3090,7 @@
neon_const_bounds (operands[2], 1, 33);
return "vcvt.%T3%#32.f32\t%<V_reg>0, %<V_reg>1, %2";
}
- [(set (attr "type")
- (if_then_else (match_test "<Is_d_reg>")
- (const_string "neon_fp_vadd_ddd_vabs_dd")
- (const_string "neon_fp_vadd_qqq_vabs_qq")))]
+ [(set_attr "type" "neon_fp_to_int_<V_elem_ch><q>")]
)
(define_insn "neon_vcvt_n<mode>"
@@ -3289,10 +3104,7 @@
neon_const_bounds (operands[2], 1, 33);
return "vcvt.f32.%T3%#32\t%<V_reg>0, %<V_reg>1, %2";
}
- [(set (attr "type")
- (if_then_else (match_test "<Is_d_reg>")
- (const_string "neon_fp_vadd_ddd_vabs_dd")
- (const_string "neon_fp_vadd_qqq_vabs_qq")))]
+ [(set_attr "type" "neon_int_to_fp_<V_elem_ch><q>")]
)
(define_insn "neon_vmovn<mode>"
@@ -3302,7 +3114,7 @@
UNSPEC_VMOVN))]
"TARGET_NEON"
"vmovn.<V_if_elem>\t%P0, %q1"
- [(set_attr "type" "neon_bp_simple")]
+ [(set_attr "type" "neon_shift_imm_narrow_q")]
)
(define_insn "neon_vqmovn<mode>"
@@ -3312,7 +3124,7 @@
UNSPEC_VQMOVN))]
"TARGET_NEON"
"vqmovn.%T2%#<V_sz_elem>\t%P0, %q1"
- [(set_attr "type" "neon_shift_2")]
+ [(set_attr "type" "neon_sat_shift_imm_narrow_q")]
)
(define_insn "neon_vqmovun<mode>"
@@ -3322,7 +3134,7 @@
UNSPEC_VQMOVUN))]
"TARGET_NEON"
"vqmovun.<V_s_elem>\t%P0, %q1"
- [(set_attr "type" "neon_shift_2")]
+ [(set_attr "type" "neon_sat_shift_imm_narrow_q")]
)
(define_insn "neon_vmovl<mode>"
@@ -3332,7 +3144,7 @@
UNSPEC_VMOVL))]
"TARGET_NEON"
"vmovl.%T2%#<V_sz_elem>\t%q0, %P1"
- [(set_attr "type" "neon_shift_1")]
+ [(set_attr "type" "neon_shift_imm_long")]
)
(define_insn "neon_vmul_lane<mode>"
@@ -3350,10 +3162,8 @@
}
[(set (attr "type")
(if_then_else (match_test "<Is_float_mode>")
- (const_string "neon_fp_vmul_ddd")
- (if_then_else (match_test "<Scalar_mul_8_16>")
- (const_string "neon_mul_ddd_16_scalar_32_16_long_scalar")
- (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar"))))]
+ (const_string "neon_fp_mul_s_scalar<q>")
+ (const_string "neon_mul_<V_elem_ch>_scalar<q>")))]
)
(define_insn "neon_vmul_lane<mode>"
@@ -3371,10 +3181,8 @@
}
[(set (attr "type")
(if_then_else (match_test "<Is_float_mode>")
- (const_string "neon_fp_vmul_qqd")
- (if_then_else (match_test "<Scalar_mul_8_16>")
- (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")
- (const_string "neon_mul_qqd_32_scalar"))))]
+ (const_string "neon_fp_mul_s_scalar<q>")
+ (const_string "neon_mul_<V_elem_ch>_scalar<q>")))]
)
(define_insn "neon_vmull_lane<mode>"
@@ -3390,10 +3198,7 @@
neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
return "vmull.%T4%#<V_sz_elem>\t%q0, %P1, %P2[%c3]";
}
- [(set (attr "type")
- (if_then_else (match_test "<Scalar_mul_8_16>")
- (const_string "neon_mul_ddd_16_scalar_32_16_long_scalar")
- (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")))]
+ [(set_attr "type" "neon_mul_<V_elem_ch>_scalar_long")]
)
(define_insn "neon_vqdmull_lane<mode>"
@@ -3409,10 +3214,7 @@
neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
return "vqdmull.<V_s_elem>\t%q0, %P1, %P2[%c3]";
}
- [(set (attr "type")
- (if_then_else (match_test "<Scalar_mul_8_16>")
- (const_string "neon_mul_ddd_16_scalar_32_16_long_scalar")
- (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")))]
+ [(set_attr "type" "neon_sat_mul_<V_elem_ch>_scalar_long")]
)
(define_insn "neon_vqdmulh_lane<mode>"
@@ -3428,10 +3230,7 @@
neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
return "vq%O4dmulh.%T4%#<V_sz_elem>\t%q0, %q1, %P2[%c3]";
}
- [(set (attr "type")
- (if_then_else (match_test "<Scalar_mul_8_16>")
- (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")
- (const_string "neon_mul_qqd_32_scalar")))]
+ [(set_attr "type" "neon_sat_mul_<V_elem_ch>_scalar_q")]
)
(define_insn "neon_vqdmulh_lane<mode>"
@@ -3447,10 +3246,7 @@
neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
return "vq%O4dmulh.%T4%#<V_sz_elem>\t%P0, %P1, %P2[%c3]";
}
- [(set (attr "type")
- (if_then_else (match_test "<Scalar_mul_8_16>")
- (const_string "neon_mul_ddd_16_scalar_32_16_long_scalar")
- (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")))]
+ [(set_attr "type" "neon_sat_mul_<V_elem_ch>_scalar_q")]
)
(define_insn "neon_vmla_lane<mode>"
@@ -3469,10 +3265,8 @@
}
[(set (attr "type")
(if_then_else (match_test "<Is_float_mode>")
- (const_string "neon_fp_vmla_ddd_scalar")
- (if_then_else (match_test "<Scalar_mul_8_16>")
- (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar")
- (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long"))))]
+ (const_string "neon_fp_mla_s_scalar<q>")
+ (const_string "neon_mla_<V_elem_ch>_scalar<q>")))]
)
(define_insn "neon_vmla_lane<mode>"
@@ -3491,10 +3285,8 @@
}
[(set (attr "type")
(if_then_else (match_test "<Is_float_mode>")
- (const_string "neon_fp_vmla_qqq_scalar")
- (if_then_else (match_test "<Scalar_mul_8_16>")
- (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")
- (const_string "neon_mla_qqq_32_qqd_32_scalar"))))]
+ (const_string "neon_fp_mla_s_scalar<q>")
+ (const_string "neon_mla_<V_elem_ch>_scalar<q>")))]
)
(define_insn "neon_vmlal_lane<mode>"
@@ -3511,10 +3303,7 @@
neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
return "vmlal.%T5%#<V_sz_elem>\t%q0, %P2, %P3[%c4]";
}
- [(set (attr "type")
- (if_then_else (match_test "<Scalar_mul_8_16>")
- (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar")
- (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
+ [(set_attr "type" "neon_mla_<V_elem_ch>_scalar_long")]
)
(define_insn "neon_vqdmlal_lane<mode>"
@@ -3531,10 +3320,7 @@
neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
return "vqdmlal.<V_s_elem>\t%q0, %P2, %P3[%c4]";
}
- [(set (attr "type")
- (if_then_else (match_test "<Scalar_mul_8_16>")
- (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar")
- (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
+ [(set_attr "type" "neon_sat_mla_<V_elem_ch>_scalar_long")]
)
(define_insn "neon_vmls_lane<mode>"
@@ -3553,10 +3339,8 @@
}
[(set (attr "type")
(if_then_else (match_test "<Is_float_mode>")
- (const_string "neon_fp_vmla_ddd_scalar")
- (if_then_else (match_test "<Scalar_mul_8_16>")
- (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar")
- (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long"))))]
+ (const_string "neon_fp_mla_s_scalar<q>")
+ (const_string "neon_mla_<V_elem_ch>_scalar<q>")))]
)
(define_insn "neon_vmls_lane<mode>"
@@ -3575,10 +3359,8 @@
}
[(set (attr "type")
(if_then_else (match_test "<Is_float_mode>")
- (const_string "neon_fp_vmla_qqq_scalar")
- (if_then_else (match_test "<Scalar_mul_8_16>")
- (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")
- (const_string "neon_mla_qqq_32_qqd_32_scalar"))))]
+ (const_string "neon_fp_mla_s_scalar<q>")
+ (const_string "neon_mla_<V_elem_ch>_scalar<q>")))]
)
(define_insn "neon_vmlsl_lane<mode>"
@@ -3595,10 +3377,7 @@
neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
return "vmlsl.%T5%#<V_sz_elem>\t%q0, %P2, %P3[%c4]";
}
- [(set (attr "type")
- (if_then_else (match_test "<Scalar_mul_8_16>")
- (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar")
- (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
+ [(set_attr "type" "neon_mla_<V_elem_ch>_scalar_long")]
)
(define_insn "neon_vqdmlsl_lane<mode>"
@@ -3615,10 +3394,7 @@
neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode));
return "vqdmlsl.<V_s_elem>\t%q0, %P2, %P3[%c4]";
}
- [(set (attr "type")
- (if_then_else (match_test "<Scalar_mul_8_16>")
- (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar")
- (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))]
+ [(set_attr "type" "neon_sat_mla_<V_elem_ch>_scalar_long")]
)
; FIXME: For the "_n" multiply/multiply-accumulate insns, we copy a value in a
@@ -3843,10 +3619,7 @@
neon_const_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode));
return "vext.<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2, %3";
}
- [(set (attr "type")
- (if_then_else (match_test "<Is_d_reg>")
- (const_string "neon_bp_simple")
- (const_string "neon_bp_2cycle")))]
+ [(set_attr "type" "neon_ext<q>")]
)
(define_insn "neon_vrev64<mode>"
@@ -3856,7 +3629,7 @@
UNSPEC_VREV64))]
"TARGET_NEON"
"vrev64.<V_sz_elem>\t%<V_reg>0, %<V_reg>1"
- [(set_attr "type" "neon_bp_simple")]
+ [(set_attr "type" "neon_rev<q>")]
)
(define_insn "neon_vrev32<mode>"
@@ -3866,7 +3639,7 @@
UNSPEC_VREV32))]
"TARGET_NEON"
"vrev32.<V_sz_elem>\t%<V_reg>0, %<V_reg>1"
- [(set_attr "type" "neon_bp_simple")]
+ [(set_attr "type" "neon_rev<q>")]
)
(define_insn "neon_vrev16<mode>"
@@ -3876,7 +3649,7 @@
UNSPEC_VREV16))]
"TARGET_NEON"
"vrev16.<V_sz_elem>\t%<V_reg>0, %<V_reg>1"
- [(set_attr "type" "neon_bp_simple")]
+ [(set_attr "type" "neon_rev<q>")]
)
; vbsl_* intrinsics may compile to any of vbsl/vbif/vbit depending on register
@@ -3898,7 +3671,7 @@
vbsl\t%<V_reg>0, %<V_reg>2, %<V_reg>3
vbit\t%<V_reg>0, %<V_reg>2, %<V_reg>1
vbif\t%<V_reg>0, %<V_reg>3, %<V_reg>1"
- [(set_attr "type" "neon_int_1")]
+ [(set_attr "type" "neon_bsl<q>")]
)
(define_expand "neon_vbsl<mode>"
@@ -3921,10 +3694,7 @@
UNSPEC_VSHL))]
"TARGET_NEON"
"v%O3shl.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
- [(set (attr "type")
- (if_then_else (match_test "<Is_d_reg>")
- (const_string "neon_vshl_ddd")
- (const_string "neon_shift_3")))]
+ [(set_attr "type" "neon_shift_imm<q>")]
)
(define_insn "neon_vqshl<mode>"
@@ -3935,10 +3705,7 @@
UNSPEC_VQSHL))]
"TARGET_NEON"
"vq%O3shl.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
- [(set (attr "type")
- (if_then_else (match_test "<Is_d_reg>")
- (const_string "neon_shift_2")
- (const_string "neon_vqshl_vrshl_vqrshl_qqq")))]
+ [(set_attr "type" "neon_sat_shift_imm<q>")]
)
(define_insn "neon_vshr_n<mode>"
@@ -3952,7 +3719,7 @@
neon_const_bounds (operands[2], 1, neon_element_bits (<MODE>mode) + 1);
return "v%O3shr.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %2";
}
- [(set_attr "type" "neon_shift_1")]
+ [(set_attr "type" "neon_shift_imm<q>")]
)
(define_insn "neon_vshrn_n<mode>"
@@ -3966,7 +3733,7 @@
neon_const_bounds (operands[2], 1, neon_element_bits (<MODE>mode) / 2 + 1);
return "v%O3shrn.<V_if_elem>\t%P0, %q1, %2";
}
- [(set_attr "type" "neon_shift_1")]
+ [(set_attr "type" "neon_shift_imm_narrow_q")]
)
(define_insn "neon_vqshrn_n<mode>"
@@ -3980,7 +3747,7 @@
neon_const_bounds (operands[2], 1, neon_element_bits (<MODE>mode) / 2 + 1);
return "vq%O3shrn.%T3%#<V_sz_elem>\t%P0, %q1, %2";
}
- [(set_attr "type" "neon_shift_2")]
+ [(set_attr "type" "neon_sat_shift_imm_narrow_q")]
)
(define_insn "neon_vqshrun_n<mode>"
@@ -3994,7 +3761,7 @@
neon_const_bounds (operands[2], 1, neon_element_bits (<MODE>mode) / 2 + 1);
return "vq%O3shrun.%T3%#<V_sz_elem>\t%P0, %q1, %2";
}
- [(set_attr "type" "neon_shift_2")]
+ [(set_attr "type" "neon_sat_shift_imm_narrow_q")]
)
(define_insn "neon_vshl_n<mode>"
@@ -4008,7 +3775,7 @@
neon_const_bounds (operands[2], 0, neon_element_bits (<MODE>mode));
return "vshl.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %2";
}
- [(set_attr "type" "neon_shift_1")]
+ [(set_attr "type" "neon_shift_imm<q>")]
)
(define_insn "neon_vqshl_n<mode>"
@@ -4022,7 +3789,7 @@
neon_const_bounds (operands[2], 0, neon_element_bits (<MODE>mode));
return "vqshl.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %2";
}
- [(set_attr "type" "neon_shift_2")]
+ [(set_attr "type" "neon_sat_shift_imm<q>")]
)
(define_insn "neon_vqshlu_n<mode>"
@@ -4036,7 +3803,7 @@
neon_const_bounds (operands[2], 0, neon_element_bits (<MODE>mode));
return "vqshlu.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %2";
}
- [(set_attr "type" "neon_shift_2")]
+ [(set_attr "type" "neon_sat_shift_imm<q>")]
)
(define_insn "neon_vshll_n<mode>"
@@ -4051,7 +3818,7 @@
neon_const_bounds (operands[2], 0, neon_element_bits (<MODE>mode) + 1);
return "vshll.%T3%#<V_sz_elem>\t%q0, %P1, %2";
}
- [(set_attr "type" "neon_shift_1")]
+ [(set_attr "type" "neon_shift_imm_long")]
)
(define_insn "neon_vsra_n<mode>"
@@ -4066,7 +3833,7 @@
neon_const_bounds (operands[3], 1, neon_element_bits (<MODE>mode) + 1);
return "v%O4sra.%T4%#<V_sz_elem>\t%<V_reg>0, %<V_reg>2, %3";
}
- [(set_attr "type" "neon_vsra_vrsra")]
+ [(set_attr "type" "neon_shift_acc<q>")]
)
(define_insn "neon_vsri_n<mode>"
@@ -4080,10 +3847,7 @@
neon_const_bounds (operands[3], 1, neon_element_bits (<MODE>mode) + 1);
return "vsri.<V_sz_elem>\t%<V_reg>0, %<V_reg>2, %3";
}
- [(set (attr "type")
- (if_then_else (match_test "<Is_d_reg>")
- (const_string "neon_shift_1")
- (const_string "neon_shift_3")))]
+ [(set_attr "type" "neon_shift_reg<q>")]
)
(define_insn "neon_vsli_n<mode>"
@@ -4097,10 +3861,7 @@
neon_const_bounds (operands[3], 0, neon_element_bits (<MODE>mode));
return "vsli.<V_sz_elem>\t%<V_reg>0, %<V_reg>2, %3";
}
- [(set (attr "type")
- (if_then_else (match_test "<Is_d_reg>")
- (const_string "neon_shift_1")
- (const_string "neon_shift_3")))]
+ [(set_attr "type" "neon_shift_reg<q>")]
)
(define_insn "neon_vtbl1v8qi"
@@ -4110,7 +3871,7 @@
UNSPEC_VTBL))]
"TARGET_NEON"
"vtbl.8\t%P0, {%P1}, %P2"
- [(set_attr "type" "neon_bp_2cycle")]
+ [(set_attr "type" "neon_tbl1")]
)
(define_insn "neon_vtbl2v8qi"
@@ -4131,7 +3892,7 @@
return "";
}
- [(set_attr "type" "neon_bp_2cycle")]
+ [(set_attr "type" "neon_tbl2")]
)
(define_insn "neon_vtbl3v8qi"
@@ -4153,7 +3914,7 @@
return "";
}
- [(set_attr "type" "neon_bp_3cycle")]
+ [(set_attr "type" "neon_tbl3")]
)
(define_insn "neon_vtbl4v8qi"
@@ -4176,7 +3937,7 @@
return "";
}
- [(set_attr "type" "neon_bp_3cycle")]
+ [(set_attr "type" "neon_tbl4")]
)
;; These three are used by the vec_perm infrastructure for V16QImode.
@@ -4207,7 +3968,9 @@
part2 = simplify_subreg (V8QImode, op2, V16QImode, ofs);
emit_insn (gen_neon_vtbl2v8qi (part0, op1, part2));
DONE;
-})
+}
+ [(set_attr "type" "multiple")]
+)
(define_insn_and_split "neon_vtbl2v16qi"
[(set (match_operand:V16QI 0 "s_register_operand" "=&w")
@@ -4236,7 +3999,9 @@
part2 = simplify_subreg (V8QImode, op2, V16QImode, ofs);
emit_insn (gen_neon_vtbl2v8qi (part0, op1, part2));
DONE;
-})
+}
+ [(set_attr "type" "multiple")]
+)
;; ??? Logically we should extend the regular neon_vcombine pattern to
;; handle quad-word input modes, producing octa-word output modes. But
@@ -4254,7 +4019,9 @@
{
neon_split_vcombine (operands);
DONE;
-})
+}
+[(set_attr "type" "multiple")]
+)
(define_insn "neon_vtbx1v8qi"
[(set (match_operand:V8QI 0 "s_register_operand" "=w")
@@ -4264,7 +4031,7 @@
UNSPEC_VTBX))]
"TARGET_NEON"
"vtbx.8\t%P0, {%P2}, %P3"
- [(set_attr "type" "neon_bp_2cycle")]
+ [(set_attr "type" "neon_tbl1")]
)
(define_insn "neon_vtbx2v8qi"
@@ -4286,7 +4053,7 @@
return "";
}
- [(set_attr "type" "neon_bp_2cycle")]
+ [(set_attr "type" "neon_tbl2")]
)
(define_insn "neon_vtbx3v8qi"
@@ -4309,7 +4076,7 @@
return "";
}
- [(set_attr "type" "neon_bp_3cycle")]
+ [(set_attr "type" "neon_tbl3")]
)
(define_insn "neon_vtbx4v8qi"
@@ -4333,7 +4100,7 @@
return "";
}
- [(set_attr "type" "neon_bp_3cycle")]
+ [(set_attr "type" "neon_tbl4")]
)
(define_expand "neon_vtrn<mode>_internal"
@@ -4359,10 +4126,7 @@
UNSPEC_VTRN2))]
"TARGET_NEON"
"vtrn.<V_sz_elem>\t%<V_reg>0, %<V_reg>2"
- [(set (attr "type")
- (if_then_else (match_test "<Is_d_reg>")
- (const_string "neon_bp_simple")
- (const_string "neon_bp_3cycle")))]
+ [(set_attr "type" "neon_permute<q>")]
)
(define_expand "neon_vtrn<mode>"
@@ -4399,10 +4163,7 @@
UNSPEC_VZIP2))]
"TARGET_NEON"
"vzip.<V_sz_elem>\t%<V_reg>0, %<V_reg>2"
- [(set (attr "type")
- (if_then_else (match_test "<Is_d_reg>")
- (const_string "neon_bp_simple")
- (const_string "neon_bp_3cycle")))]
+ [(set_attr "type" "neon_zip<q>")]
)
(define_expand "neon_vzip<mode>"
@@ -4439,10 +4200,7 @@
UNSPEC_VUZP2))]
"TARGET_NEON"
"vuzp.<V_sz_elem>\t%<V_reg>0, %<V_reg>2"
- [(set (attr "type")
- (if_then_else (match_test "<Is_d_reg>")
- (const_string "neon_bp_simple")
- (const_string "neon_bp_3cycle")))]
+ [(set_attr "type" "neon_zip<q>")]
)
(define_expand "neon_vuzp<mode>"
@@ -4558,7 +4316,7 @@
UNSPEC_VLD1))]
"TARGET_NEON"
"vld1.<V_sz_elem>\t%h0, %A1"
- [(set_attr "type" "neon_vld1_1_2_regs")]
+ [(set_attr "type" "neon_load1_1reg<q>")]
)
(define_insn "neon_vld1_lane<mode>"
@@ -4578,10 +4336,7 @@
else
return "vld1.<V_sz_elem>\t{%P0[%c3]}, %A1";
}
- [(set (attr "type")
- (if_then_else (eq (const_string "<V_mode_nunits>") (const_int 2))
- (const_string "neon_vld1_1_2_regs")
- (const_string "neon_vld1_vld2_lane")))]
+ [(set_attr "type" "neon_load1_one_lane<q>")]
)
(define_insn "neon_vld1_lane<mode>"
@@ -4609,10 +4364,7 @@
else
return "vld1.<V_sz_elem>\t{%P0[%c3]}, %A1";
}
- [(set (attr "type")
- (if_then_else (eq (const_string "<V_mode_nunits>") (const_int 2))
- (const_string "neon_vld1_1_2_regs")
- (const_string "neon_vld1_vld2_lane")))]
+ [(set_attr "type" "neon_load1_one_lane<q>")]
)
(define_insn "neon_vld1_dup<mode>"
@@ -4620,7 +4372,7 @@
(vec_duplicate:VD (match_operand:<V_elem> 1 "neon_struct_operand" "Um")))]
"TARGET_NEON"
"vld1.<V_sz_elem>\t{%P0[]}, %A1"
- [(set_attr "type" "neon_vld2_2_regs_vld1_vld2_all_lanes")]
+ [(set_attr "type" "neon_load1_all_lanes<q>")]
)
;; Special case for DImode. Treat it exactly like a simple load.
@@ -4639,7 +4391,7 @@
{
return "vld1.<V_sz_elem>\t{%e0[], %f0[]}, %A1";
}
- [(set_attr "type" "neon_vld2_2_regs_vld1_vld2_all_lanes")]
+ [(set_attr "type" "neon_load1_all_lanes<q>")]
)
(define_insn_and_split "neon_vld1_dupv2di"
@@ -4656,7 +4408,7 @@
DONE;
}
[(set_attr "length" "8")
- (set_attr "type" "neon_vld2_2_regs_vld1_vld2_all_lanes")]
+ (set_attr "type" "neon_load1_all_lanes_q")]
)
(define_expand "vec_store_lanes<mode><mode>"
@@ -4671,7 +4423,7 @@
UNSPEC_VST1))]
"TARGET_NEON"
"vst1.<V_sz_elem>\t%h1, %A0"
- [(set_attr "type" "neon_vst1_1_2_regs_vst2_2_regs")])
+ [(set_attr "type" "neon_store1_1reg<q>")])
(define_insn "neon_vst1_lane<mode>"
[(set (match_operand:<V_elem> 0 "neon_struct_operand" "=Um")
@@ -4690,10 +4442,8 @@
else
return "vst1.<V_sz_elem>\t{%P1[%c2]}, %A0";
}
- [(set (attr "type")
- (if_then_else (eq (const_string "<V_mode_nunits>") (const_int 1))
- (const_string "neon_vst1_1_2_regs_vst2_2_regs")
- (const_string "neon_vst1_vst2_lane")))])
+ [(set_attr "type" "neon_store1_one_lane<q>")]
+)
(define_insn "neon_vst1_lane<mode>"
[(set (match_operand:<V_elem> 0 "neon_struct_operand" "=Um")
@@ -4720,7 +4470,7 @@
else
return "vst1.<V_sz_elem>\t{%P1[%c2]}, %A0";
}
- [(set_attr "type" "neon_vst1_vst2_lane")]
+ [(set_attr "type" "neon_store1_one_lane<q>")]
)
(define_expand "vec_load_lanesti<mode>"
@@ -4744,8 +4494,8 @@
}
[(set (attr "type")
(if_then_else (eq (const_string "<V_sz_elem>") (const_string "64"))
- (const_string "neon_vld1_1_2_regs")
- (const_string "neon_vld2_2_regs_vld1_vld2_all_lanes")))]
+ (const_string "neon_load1_2reg<q>")
+ (const_string "neon_load2_2reg<q>")))]
)
(define_expand "vec_load_lanesoi<mode>"
@@ -4762,7 +4512,7 @@
UNSPEC_VLD2))]
"TARGET_NEON"
"vld2.<V_sz_elem>\t%h0, %A1"
- [(set_attr "type" "neon_vld2_2_regs_vld1_vld2_all_lanes")])
+ [(set_attr "type" "neon_load2_2reg_q")])
(define_insn "neon_vld2_lane<mode>"
[(set (match_operand:TI 0 "s_register_operand" "=w")
@@ -4786,7 +4536,7 @@
output_asm_insn ("vld2.<V_sz_elem>\t{%P0[%c3], %P1[%c3]}, %A2", ops);
return "";
}
- [(set_attr "type" "neon_vld1_vld2_lane")]
+ [(set_attr "type" "neon_load2_one_lane<q>")]
)
(define_insn "neon_vld2_lane<mode>"
@@ -4816,7 +4566,7 @@
output_asm_insn ("vld2.<V_sz_elem>\t{%P0[%c3], %P1[%c3]}, %A2", ops);
return "";
}
- [(set_attr "type" "neon_vld1_vld2_lane")]
+ [(set_attr "type" "neon_load2_one_lane<q>")]
)
(define_insn "neon_vld2_dup<mode>"
@@ -4833,8 +4583,8 @@
}
[(set (attr "type")
(if_then_else (gt (const_string "<V_mode_nunits>") (const_string "1"))
- (const_string "neon_vld2_2_regs_vld1_vld2_all_lanes")
- (const_string "neon_vld1_1_2_regs")))]
+ (const_string "neon_load2_all_lanes<q>")
+ (const_string "neon_load1_1reg<q>")))]
)
(define_expand "vec_store_lanesti<mode>"
@@ -4858,8 +4608,8 @@
}
[(set (attr "type")
(if_then_else (eq (const_string "<V_sz_elem>") (const_string "64"))
- (const_string "neon_vst1_1_2_regs_vst2_2_regs")
- (const_string "neon_vst1_1_2_regs_vst2_2_regs")))]
+ (const_string "neon_store1_2reg<q>")
+ (const_string "neon_store2_one_lane<q>")))]
)
(define_expand "vec_store_lanesoi<mode>"
@@ -4876,7 +4626,7 @@
UNSPEC_VST2))]
"TARGET_NEON"
"vst2.<V_sz_elem>\t%h1, %A0"
- [(set_attr "type" "neon_vst1_1_2_regs_vst2_2_regs")]
+ [(set_attr "type" "neon_store2_4reg<q>")]
)
(define_insn "neon_vst2_lane<mode>"
@@ -4901,7 +4651,7 @@
output_asm_insn ("vst2.<V_sz_elem>\t{%P1[%c3], %P2[%c3]}, %A0", ops);
return "";
}
- [(set_attr "type" "neon_vst1_vst2_lane")]
+ [(set_attr "type" "neon_store2_one_lane<q>")]
)
(define_insn "neon_vst2_lane<mode>"
@@ -4931,7 +4681,7 @@
output_asm_insn ("vst2.<V_sz_elem>\t{%P1[%c3], %P2[%c3]}, %A0", ops);
return "";
}
- [(set_attr "type" "neon_vst1_vst2_lane")]
+ [(set_attr "type" "neon_store2_one_lane<q>")]
)
(define_expand "vec_load_lanesei<mode>"
@@ -4955,8 +4705,8 @@
}
[(set (attr "type")
(if_then_else (eq (const_string "<V_sz_elem>") (const_string "64"))
- (const_string "neon_vld1_1_2_regs")
- (const_string "neon_vld3_vld4")))]
+ (const_string "neon_load1_3reg<q>")
+ (const_string "neon_load3_3reg<q>")))]
)
(define_expand "vec_load_lanesci<mode>"
@@ -5000,7 +4750,7 @@
output_asm_insn ("vld3.<V_sz_elem>\t{%P0, %P1, %P2}, %A3", ops);
return "";
}
- [(set_attr "type" "neon_vld3_vld4")]
+ [(set_attr "type" "neon_load3_3reg<q>")]
)
(define_insn "neon_vld3qb<mode>"
@@ -5020,7 +4770,7 @@
output_asm_insn ("vld3.<V_sz_elem>\t{%P0, %P1, %P2}, %A3", ops);
return "";
}
- [(set_attr "type" "neon_vld3_vld4")]
+ [(set_attr "type" "neon_load3_3reg<q>")]
)
(define_insn "neon_vld3_lane<mode>"
@@ -5047,7 +4797,7 @@
ops);
return "";
}
- [(set_attr "type" "neon_vld3_vld4_lane")]
+ [(set_attr "type" "neon_load3_one_lane<q>")]
)
(define_insn "neon_vld3_lane<mode>"
@@ -5079,7 +4829,7 @@
ops);
return "";
}
- [(set_attr "type" "neon_vld3_vld4_lane")]
+ [(set_attr "type" "neon_load3_one_lane<q>")]
)
(define_insn "neon_vld3_dup<mode>"
@@ -5105,8 +4855,8 @@
}
[(set (attr "type")
(if_then_else (gt (const_string "<V_mode_nunits>") (const_string "1"))
- (const_string "neon_vld3_vld4_all_lanes")
- (const_string "neon_vld1_1_2_regs")))])
+ (const_string "neon_load3_all_lanes<q>")
+ (const_string "neon_load1_1reg<q>")))])
(define_expand "vec_store_lanesei<mode>"
[(set (match_operand:EI 0 "neon_struct_operand")
@@ -5129,8 +4879,8 @@
}
[(set (attr "type")
(if_then_else (eq (const_string "<V_sz_elem>") (const_string "64"))
- (const_string "neon_vst1_1_2_regs_vst2_2_regs")
- (const_string "neon_vst2_4_regs_vst3_vst4")))])
+ (const_string "neon_store1_3reg<q>")
+ (const_string "neon_store3_one_lane<q>")))])
(define_expand "vec_store_lanesci<mode>"
[(match_operand:CI 0 "neon_struct_operand")
@@ -5173,7 +4923,7 @@
output_asm_insn ("vst3.<V_sz_elem>\t{%P1, %P2, %P3}, %A0", ops);
return "";
}
- [(set_attr "type" "neon_vst2_4_regs_vst3_vst4")]
+ [(set_attr "type" "neon_store3_3reg<q>")]
)
(define_insn "neon_vst3qb<mode>"
@@ -5192,7 +4942,7 @@
output_asm_insn ("vst3.<V_sz_elem>\t{%P1, %P2, %P3}, %A0", ops);
return "";
}
- [(set_attr "type" "neon_vst2_4_regs_vst3_vst4")]
+ [(set_attr "type" "neon_store3_3reg<q>")]
)
(define_insn "neon_vst3_lane<mode>"
@@ -5219,7 +4969,7 @@
ops);
return "";
}
- [(set_attr "type" "neon_vst3_vst4_lane")]
+ [(set_attr "type" "neon_store3_one_lane<q>")]
)
(define_insn "neon_vst3_lane<mode>"
@@ -5251,7 +5001,8 @@
ops);
return "";
}
-[(set_attr "type" "neon_vst3_vst4_lane")])
+ [(set_attr "type" "neon_store3_one_lane<q>")]
+)
(define_expand "vec_load_lanesoi<mode>"
[(set (match_operand:OI 0 "s_register_operand")
@@ -5274,8 +5025,8 @@
}
[(set (attr "type")
(if_then_else (eq (const_string "<V_sz_elem>") (const_string "64"))
- (const_string "neon_vld1_1_2_regs")
- (const_string "neon_vld3_vld4")))]
+ (const_string "neon_load1_4reg<q>")
+ (const_string "neon_load4_4reg<q>")))]
)
(define_expand "vec_load_lanesxi<mode>"
@@ -5320,7 +5071,7 @@
output_asm_insn ("vld4.<V_sz_elem>\t{%P0, %P1, %P2, %P3}, %A4", ops);
return "";
}
- [(set_attr "type" "neon_vld3_vld4")]
+ [(set_attr "type" "neon_load4_4reg<q>")]
)
(define_insn "neon_vld4qb<mode>"
@@ -5341,7 +5092,7 @@
output_asm_insn ("vld4.<V_sz_elem>\t{%P0, %P1, %P2, %P3}, %A4", ops);
return "";
}
- [(set_attr "type" "neon_vld3_vld4")]
+ [(set_attr "type" "neon_load4_4reg<q>")]
)
(define_insn "neon_vld4_lane<mode>"
@@ -5369,7 +5120,7 @@
ops);
return "";
}
- [(set_attr "type" "neon_vld3_vld4_lane")]
+ [(set_attr "type" "neon_load4_one_lane<q>")]
)
(define_insn "neon_vld4_lane<mode>"
@@ -5402,7 +5153,7 @@
ops);
return "";
}
- [(set_attr "type" "neon_vld3_vld4_lane")]
+ [(set_attr "type" "neon_load4_one_lane<q>")]
)
(define_insn "neon_vld4_dup<mode>"
@@ -5430,8 +5181,8 @@
}
[(set (attr "type")
(if_then_else (gt (const_string "<V_mode_nunits>") (const_string "1"))
- (const_string "neon_vld3_vld4_all_lanes")
- (const_string "neon_vld1_1_2_regs")))]
+ (const_string "neon_load4_all_lanes<q>")
+ (const_string "neon_load1_1reg<q>")))]
)
(define_expand "vec_store_lanesoi<mode>"
@@ -5455,8 +5206,8 @@
}
[(set (attr "type")
(if_then_else (eq (const_string "<V_sz_elem>") (const_string "64"))
- (const_string "neon_vst1_1_2_regs_vst2_2_regs")
- (const_string "neon_vst2_4_regs_vst3_vst4")))]
+ (const_string "neon_store1_4reg<q>")
+ (const_string "neon_store4_4reg<q>")))]
)
(define_expand "vec_store_lanesxi<mode>"
@@ -5501,7 +5252,7 @@
output_asm_insn ("vst4.<V_sz_elem>\t{%P1, %P2, %P3, %P4}, %A0", ops);
return "";
}
- [(set_attr "type" "neon_vst2_4_regs_vst3_vst4")]
+ [(set_attr "type" "neon_store4_4reg<q>")]
)
(define_insn "neon_vst4qb<mode>"
@@ -5521,7 +5272,7 @@
output_asm_insn ("vst4.<V_sz_elem>\t{%P1, %P2, %P3, %P4}, %A0", ops);
return "";
}
- [(set_attr "type" "neon_vst2_4_regs_vst3_vst4")]
+ [(set_attr "type" "neon_store4_4reg<q>")]
)
(define_insn "neon_vst4_lane<mode>"
@@ -5549,7 +5300,7 @@
ops);
return "";
}
- [(set_attr "type" "neon_vst3_vst4_lane")]
+ [(set_attr "type" "neon_store4_one_lane<q>")]
)
(define_insn "neon_vst4_lane<mode>"
@@ -5582,7 +5333,7 @@
ops);
return "";
}
- [(set_attr "type" "neon_vst3_vst4_lane")]
+ [(set_attr "type" "neon_store4_4reg<q>")]
)
(define_expand "neon_vand<mode>"
@@ -5647,7 +5398,7 @@
(match_operand:VU 2 "vect_par_constant_low" ""))))]
"TARGET_NEON && !BYTES_BIG_ENDIAN"
"vmovl.<US><V_sz_elem> %q0, %e1"
- [(set_attr "type" "neon_shift_1")]
+ [(set_attr "type" "neon_shift_imm_long")]
)
(define_insn "neon_vec_unpack<US>_hi_<mode>"
@@ -5657,7 +5408,7 @@
(match_operand:VU 2 "vect_par_constant_high" ""))))]
"TARGET_NEON && !BYTES_BIG_ENDIAN"
"vmovl.<US><V_sz_elem> %q0, %f1"
- [(set_attr "type" "neon_shift_1")]
+ [(set_attr "type" "neon_shift_imm_long")]
)
(define_expand "vec_unpack<US>_hi_<mode>"
@@ -5707,7 +5458,7 @@
(match_dup 2)))))]
"TARGET_NEON && !BYTES_BIG_ENDIAN"
"vmull.<US><V_sz_elem> %q0, %e1, %e3"
- [(set_attr "type" "neon_shift_1")]
+ [(set_attr "type" "neon_mul_<V_elem_ch>_long")]
)
(define_expand "vec_widen_<US>mult_lo_<mode>"
@@ -5741,7 +5492,7 @@
(match_dup 2)))))]
"TARGET_NEON && !BYTES_BIG_ENDIAN"
"vmull.<US><V_sz_elem> %q0, %f1, %f3"
- [(set_attr "type" "neon_shift_1")]
+ [(set_attr "type" "neon_mul_<V_elem_ch>_long")]
)
(define_expand "vec_widen_<US>mult_hi_<mode>"
@@ -5774,7 +5525,7 @@
{
return "vshll.<US><V_sz_elem> %q0, %P1, %2";
}
- [(set_attr "type" "neon_shift_1")]
+ [(set_attr "type" "neon_shift_imm_long")]
)
(define_expand "vec_widen_<US>shiftl_lo_<mode>"
@@ -5810,7 +5561,7 @@
(SE:<V_widen> (match_operand:VDI 1 "register_operand" "w")))]
"TARGET_NEON"
"vmovl.<US><V_sz_elem> %q0, %P1"
- [(set_attr "type" "neon_shift_1")]
+ [(set_attr "type" "neon_move")]
)
(define_expand "vec_unpack<US>_lo_<mode>"
@@ -5847,7 +5598,7 @@
(match_operand:VDI 2 "register_operand" "w"))))]
"TARGET_NEON"
"vmull.<US><V_sz_elem> %q0, %P1, %P2"
- [(set_attr "type" "neon_shift_1")]
+ [(set_attr "type" "neon_mul_<V_elem_ch>_long")]
)
(define_expand "vec_widen_<US>mult_hi_<mode>"
@@ -5921,7 +5672,7 @@
(match_operand:VN 2 "register_operand" "w"))))]
"TARGET_NEON && !BYTES_BIG_ENDIAN"
"vmovn.i<V_sz_elem>\t%e0, %q1\;vmovn.i<V_sz_elem>\t%f0, %q2"
- [(set_attr "type" "neon_shift_1")
+ [(set_attr "type" "multiple")
(set_attr "length" "8")]
)
@@ -5931,7 +5682,7 @@
(truncate:<V_narrow> (match_operand:VN 1 "register_operand" "w")))]
"TARGET_NEON && !BYTES_BIG_ENDIAN"
"vmovn.i<V_sz_elem>\t%P0, %q1"
- [(set_attr "type" "neon_shift_1")]
+ [(set_attr "type" "neon_move_narrow_q")]
)
(define_expand "vec_pack_trunc_<mode>"
@@ -5956,10 +5707,8 @@
"vabd.<V_s_elem> %<V_reg>0, %<V_reg>1, %<V_reg>2"
[(set (attr "type")
(if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
- (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
- (const_string "neon_fp_vadd_ddd_vabs_dd")
- (const_string "neon_fp_vadd_qqq_vabs_qq"))
- (const_string "neon_int_5")))]
+ (const_string "neon_fp_abd_s<q>")
+ (const_string "neon_abd<q>")))]
)
(define_insn "neon_vabd<mode>_3"
@@ -5971,10 +5720,8 @@
"vabd.<V_if_elem> %<V_reg>0, %<V_reg>1, %<V_reg>2"
[(set (attr "type")
(if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
- (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
- (const_string "neon_fp_vadd_ddd_vabs_dd")
- (const_string "neon_fp_vadd_qqq_vabs_qq"))
- (const_string "neon_int_5")))]
+ (const_string "neon_fp_abd_s<q>")
+ (const_string "neon_abd<q>")))]
)
;; Copy from core-to-neon regs, then extend, not vice-versa
diff --git a/gcc/config/arm/t-aprofile b/gcc/config/arm/t-aprofile
new file mode 100644
index 00000000000..ce45d4d210a
--- /dev/null
+++ b/gcc/config/arm/t-aprofile
@@ -0,0 +1,177 @@
+# Copyright (C) 2012-2013 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 a target makefile fragment that attempts to get
+# multilibs built for the range of CPU's, FPU's and ABI's that
+# are relevant for the A-profile architecture. It should
+# not be used in conjunction with another make file fragment and
+# assumes --with-arch, --with-cpu, --with-fpu, --with-float, --with-mode
+# have their default values during the configure step. We enforce
+# this during the top-level configury.
+
+MULTILIB_OPTIONS =
+MULTILIB_DIRNAMES =
+MULTILIB_EXCEPTIONS =
+MULTILIB_MATCHES =
+MULTILIB_REUSE =
+
+# We have the following hierachy:
+# ISA: A32 (.) or T32 (thumb)
+# Architecture: ARMv7-A (v7-a), ARMv7VE (v7ve), or ARMv8-A (v8-a).
+# FPU: VFPv3-D16 (fpv3), NEONv1 (simdv1), VFPv4-D16 (fpv4),
+# NEON-VFPV4 (simdvfpv4), NEON for ARMv8 (simdv8), or None (.).
+# Float-abi: Soft (.), softfp (softfp), or hard (hardfp).
+
+# We use the option -mcpu=cortex-a7 because we do not yet have march=armv7ve
+# or march=armv7a+virt as a command line option for the compiler.
+MULTILIB_OPTIONS += mthumb
+MULTILIB_DIRNAMES += thumb
+
+MULTILIB_OPTIONS += march=armv7-a/mcpu=cortex-a7/march=armv8-a
+MULTILIB_DIRNAMES += v7-a v7ve v8-a
+
+MULTILIB_OPTIONS += mfpu=vfpv3-d16/mfpu=neon/mfpu=vfpv4-d16/mfpu=neon-vfpv4/mfpu=neon-fp-armv8
+MULTILIB_DIRNAMES += fpv3 simdv1 fpv4 simdvfpv4 simdv8
+
+MULTILIB_OPTIONS += mfloat-abi=softfp/mfloat-abi=hard
+MULTILIB_DIRNAMES += softfp hard
+
+# We don't build no-float libraries with an FPU.
+MULTILIB_EXCEPTIONS += *mfpu=vfpv3-d16
+MULTILIB_EXCEPTIONS += *mfpu=neon
+MULTILIB_EXCEPTIONS += *mfpu=vfpv4-d16
+MULTILIB_EXCEPTIONS += *mfpu=neon-vfpv4
+MULTILIB_EXCEPTIONS += *mfpu=neon-fp-armv8
+
+# We don't build libraries requiring an FPU at the CPU/Arch/ISA level.
+MULTILIB_EXCEPTIONS += mfloat-abi=*
+MULTILIB_EXCEPTIONS += mfpu=*
+MULTILIB_EXCEPTIONS += mthumb/mfloat-abi=*
+MULTILIB_EXCEPTIONS += mthumb/mfpu=*
+MULTILIB_EXCEPTIONS += *march=armv7-a/mfloat-abi=*
+MULTILIB_EXCEPTIONS += *mcpu=cortex-a7/mfloat-abi=*
+MULTILIB_EXCEPTIONS += *march=armv8-a/mfloat-abi=*
+
+# Ensure the correct FPU variants apply to the correct base architectures.
+MULTILIB_EXCEPTIONS += *mcpu=cortex-a7/*mfpu=vfpv3-d16*
+MULTILIB_EXCEPTIONS += *mcpu=cortex-a7/*mfpu=neon/*
+MULTILIB_EXCEPTIONS += *march=armv8-a/*mfpu=vfpv3-d16*
+MULTILIB_EXCEPTIONS += *march=armv8-a/*mfpu=neon/*
+MULTILIB_EXCEPTIONS += *march=armv7-a/*mfpu=vfpv4-d16*
+MULTILIB_EXCEPTIONS += *march=armv7-a/*mfpu=neon-vfpv4*
+MULTILIB_EXCEPTIONS += *march=armv8-a/*mfpu=vfpv4-d16*
+MULTILIB_EXCEPTIONS += *march=armv8-a/*mfpu=neon-vfpv4*
+MULTILIB_EXCEPTIONS += *march=armv7-a/*mfpu=neon-fp-armv8*
+MULTILIB_EXCEPTIONS += *mcpu=cortex-a7/*mfpu=neon-fp-armv8*
+
+# CPU Matches
+MULTILIB_MATCHES += march?armv7-a=mcpu?cortex-a8
+MULTILIB_MATCHES += march?armv7-a=mcpu?cortex-a9
+MULTILIB_MATCHES += march?armv7-a=mcpu?cortex-a5
+MULTILIB_MATCHES += mcpu?cortex-a7=mcpu?cortex-a15
+MULTILIB_MATCHES += march?armv8-a=mcpu?cortex-a53
+
+# FPU matches
+MULTILIB_MATCHES += mfpu?vfpv3-d16=mfpu?vfpv3
+MULTILIB_MATCHES += mfpu?vfpv3-d16=mfpu?vfpv3-fp16
+MULTILIB_MATCHES += mfpu?vfpv3-d16=mfpu?vfpv3-fp16-d16
+MULTILIB_MATCHES += mfpu?vfpv4-d16=mfpu?vfpv4
+MULTILIB_MATCHES += mfpu?neon-fp-armv8=mfpu?crypto-neon-fp-armv8
+
+
+# Map all requests for vfpv3 with a later CPU to vfpv3-d16 v7-a.
+# So if new CPUs are added above at the newer architecture levels,
+# do something to map them below here.
+# We take the approach of mapping down to v7-a regardless of what
+# the fp option is if the integer architecture brings things down.
+# This applies to any similar combination at the v7ve and v8-a arch
+# levels.
+
+MULTILIB_REUSE += march.armv7-a/mfpu.vfpv3-d16/mfloat-abi.hard=mcpu.cortex-a7/mfpu.vfpv3-d16/mfloat-abi.hard
+MULTILIB_REUSE += march.armv7-a/mfpu.vfpv3-d16/mfloat-abi.softfp=mcpu.cortex-a7/mfpu.vfpv3-d16/mfloat-abi.softfp
+MULTILIB_REUSE += march.armv7-a/mfpu.vfpv3-d16/mfloat-abi.hard=march.armv8-a/mfpu.vfpv3-d16/mfloat-abi.hard
+MULTILIB_REUSE += march.armv7-a/mfpu.vfpv3-d16/mfloat-abi.softfp=march.armv8-a/mfpu.vfpv3-d16/mfloat-abi.softfp
+MULTILIB_REUSE += march.armv7-a/mfpu.vfpv3-d16/mfloat-abi.hard=march.armv7-a/mfpu.vfpv4-d16/mfloat-abi.hard
+MULTILIB_REUSE += march.armv7-a/mfpu.vfpv3-d16/mfloat-abi.softfp=march.armv7-a/mfpu.vfpv4-d16/mfloat-abi.softfp
+MULTILIB_REUSE += march.armv7-a/mfpu.vfpv3-d16/mfloat-abi.hard=march.armv7-a/mfpu.fp-armv8/mfloat-abi.hard
+MULTILIB_REUSE += march.armv7-a/mfpu.vfpv3-d16/mfloat-abi.softfp=march.armv7-a/mfpu.fp-armv8/mfloat-abi.softfp
+MULTILIB_REUSE += march.armv7-a/mfpu.vfpv3-d16/mfloat-abi.hard=march.armv7-a/mfpu.vfpv4/mfloat-abi.hard
+MULTILIB_REUSE += march.armv7-a/mfpu.vfpv3-d16/mfloat-abi.softfp=march.armv7-a/mfpu.vfpv4/mfloat-abi.softfp
+
+
+MULTILIB_REUSE += march.armv7-a/mfpu.neon/mfloat-abi.hard=mcpu.cortex-a7/mfpu.neon/mfloat-abi.hard
+MULTILIB_REUSE += march.armv7-a/mfpu.neon/mfloat-abi.softfp=mcpu.cortex-a7/mfpu.neon/mfloat-abi.softfp
+MULTILIB_REUSE += march.armv7-a/mfpu.neon/mfloat-abi.hard=march.armv8-a/mfpu.neon/mfloat-abi.hard
+MULTILIB_REUSE += march.armv7-a/mfpu.neon/mfloat-abi.softfp=march.armv8-a/mfpu.neon/mfloat-abi.softfp
+MULTILIB_REUSE += march.armv7-a/mfpu.neon/mfloat-abi.hard=march.armv7-a/mfpu.neon-vfpv4/mfloat-abi.hard
+MULTILIB_REUSE += march.armv7-a/mfpu.neon/mfloat-abi.softfp=march.armv7-a/mfpu.neon-vfpv4/mfloat-abi.softfp
+MULTILIB_REUSE += march.armv7-a/mfpu.neon/mfloat-abi.hard=march.armv7-a/mfpu.neon-fp-armv8/mfloat-abi.hard
+MULTILIB_REUSE += march.armv7-a/mfpu.neon/mfloat-abi.softfp=march.armv7-a/mfpu.neon-fp-armv8/mfloat-abi.softfp
+
+
+MULTILIB_REUSE += mcpu.cortex-a7/mfpu.vfpv4-d16/mfloat-abi.hard=mcpu.cortex-a7/mfpu.fp-armv8/mfloat-abi.hard
+MULTILIB_REUSE += mcpu.cortex-a7/mfpu.vfpv4-d16/mfloat-abi.softfp=mcpu.cortex-a7/mfpu.fp-armv8/mfloat-abi.softfp
+MULTILIB_REUSE += mcpu.cortex-a7/mfpu.vfpv4-d16/mfloat-abi.hard=march.armv8-a/mfpu.vfpv4/mfloat-abi.hard
+MULTILIB_REUSE += mcpu.cortex-a7/mfpu.vfpv4-d16/mfloat-abi.softfp=march.armv8-a/mfpu.vfpv4/mfloat-abi.softfp
+MULTILIB_REUSE += mcpu.cortex-a7/mfpu.vfpv4-d16/mfloat-abi.hard=march.armv8-a/mfpu.vfpv4-d16/mfloat-abi.hard
+MULTILIB_REUSE += mcpu.cortex-a7/mfpu.vfpv4-d16/mfloat-abi.softfp=march.armv8-a/mfpu.vfpv4-d16/mfloat-abi.softfp
+
+
+MULTILIB_REUSE += mcpu.cortex-a7/mfpu.neon-vfpv4/mfloat-abi.hard=march.armv8-a/mfpu.neon-vfpv4/mfloat-abi.hard
+MULTILIB_REUSE += mcpu.cortex-a7/mfpu.neon-vfpv4/mfloat-abi.softfp=march.armv8-a/mfpu.neon-vfpv4/mfloat-abi.softfp
+MULTILIB_REUSE += mcpu.cortex-a7/mfpu.neon-vfpv4/mfloat-abi.hard=mcpu.cortex-a7/mfpu.neon-fp-armv8/mfloat-abi.hard
+MULTILIB_REUSE += mcpu.cortex-a7/mfpu.neon-vfpv4/mfloat-abi.softfp=mcpu.cortex-a7/mfpu.neon-fp-armv8/mfloat-abi.softfp
+
+
+
+# And again for mthumb.
+
+MULTILIB_REUSE += mthumb/march.armv7-a/mfpu.vfpv3-d16/mfloat-abi.hard=mthumb/mcpu.cortex-a7/mfpu.vfpv3-d16/mfloat-abi.hard
+MULTILIB_REUSE += mthumb/march.armv7-a/mfpu.vfpv3-d16/mfloat-abi.softfp=mthumb/mcpu.cortex-a7/mfpu.vfpv3-d16/mfloat-abi.softfp
+MULTILIB_REUSE += mthumb/march.armv7-a/mfpu.vfpv3-d16/mfloat-abi.hard=mthumb/march.armv8-a/mfpu.vfpv3-d16/mfloat-abi.hard
+MULTILIB_REUSE += mthumb/march.armv7-a/mfpu.vfpv3-d16/mfloat-abi.softfp=mthumb/march.armv8-a/mfpu.vfpv3-d16/mfloat-abi.softfp
+MULTILIB_REUSE += mthumb/march.armv7-a/mfpu.vfpv3-d16/mfloat-abi.hard=mthumb/march.armv7-a/mfpu.vfpv4-d16/mfloat-abi.hard
+MULTILIB_REUSE += mthumb/march.armv7-a/mfpu.vfpv3-d16/mfloat-abi.softfp=mthumb/march.armv7-a/mfpu.vfpv4-d16/mfloat-abi.softfp
+MULTILIB_REUSE += mthumb/march.armv7-a/mfpu.vfpv3-d16/mfloat-abi.hard=mthumb/march.armv7-a/mfpu.fp-armv8/mfloat-abi.hard
+MULTILIB_REUSE += mthumb/march.armv7-a/mfpu.vfpv3-d16/mfloat-abi.softfp=mthumb/march.armv7-a/mfpu.fp-armv8/mfloat-abi.softfp
+MULTILIB_REUSE += mthumb/march.armv7-a/mfpu.vfpv3-d16/mfloat-abi.hard=mthumb/march.armv7-a/mfpu.vfpv4/mfloat-abi.hard
+MULTILIB_REUSE += mthumb/march.armv7-a/mfpu.vfpv3-d16/mfloat-abi.softfp=mthumb/march.armv7-a/mfpu.vfpv4/mfloat-abi.softfp
+
+
+MULTILIB_REUSE += mthumb/march.armv7-a/mfpu.neon/mfloat-abi.hard=mthumb/mcpu.cortex-a7/mfpu.neon/mfloat-abi.hard
+MULTILIB_REUSE += mthumb/march.armv7-a/mfpu.neon/mfloat-abi.softfp=mthumb/mcpu.cortex-a7/mfpu.neon/mfloat-abi.softfp
+MULTILIB_REUSE += mthumb/march.armv7-a/mfpu.neon/mfloat-abi.hard=mthumb/march.armv8-a/mfpu.neon/mfloat-abi.hard
+MULTILIB_REUSE += mthumb/march.armv7-a/mfpu.neon/mfloat-abi.softfp=mthumb/march.armv8-a/mfpu.neon/mfloat-abi.softfp
+MULTILIB_REUSE += mthumb/march.armv7-a/mfpu.neon/mfloat-abi.hard=mthumb/march.armv7-a/mfpu.neon-vfpv4/mfloat-abi.hard
+MULTILIB_REUSE += mthumb/march.armv7-a/mfpu.neon/mfloat-abi.softfp=mthumb/march.armv7-a/mfpu.neon-vfpv4/mfloat-abi.softfp
+MULTILIB_REUSE += mthumb/march.armv7-a/mfpu.neon/mfloat-abi.hard=mthumb/march.armv7-a/mfpu.neon-fp-armv8/mfloat-abi.hard
+MULTILIB_REUSE += mthumb/march.armv7-a/mfpu.neon/mfloat-abi.softfp=mthumb/march.armv7-a/mfpu.neon-fp-armv8/mfloat-abi.softfp
+
+
+MULTILIB_REUSE += mthumb/mcpu.cortex-a7/mfpu.vfpv4-d16/mfloat-abi.hard=mthumb/mcpu.cortex-a7/mfpu.fp-armv8/mfloat-abi.hard
+MULTILIB_REUSE += mthumb/mcpu.cortex-a7/mfpu.vfpv4-d16/mfloat-abi.softfp=mthumb/mcpu.cortex-a7/mfpu.fp-armv8/mfloat-abi.softfp
+MULTILIB_REUSE += mthumb/mcpu.cortex-a7/mfpu.vfpv4-d16/mfloat-abi.hard=mthumb/march.armv8-a/mfpu.vfpv4/mfloat-abi.hard
+MULTILIB_REUSE += mthumb/mcpu.cortex-a7/mfpu.vfpv4-d16/mfloat-abi.softfp=mthumb/march.armv8-a/mfpu.vfpv4/mfloat-abi.softfp
+MULTILIB_REUSE += mthumb/mcpu.cortex-a7/mfpu.vfpv4-d16/mfloat-abi.hard=mthumb/march.armv8-a/mfpu.vfpv4-d16/mfloat-abi.hard
+MULTILIB_REUSE += mthumb/mcpu.cortex-a7/mfpu.vfpv4-d16/mfloat-abi.softfp=mthumb/march.armv8-a/mfpu.vfpv4-d16/mfloat-abi.softfp
+
+
+MULTILIB_REUSE += mthumb/mcpu.cortex-a7/mfpu.neon-vfpv4/mfloat-abi.hard=mthumb/march.armv8-a/mfpu.neon-vfpv4/mfloat-abi.hard
+MULTILIB_REUSE += mthumb/mcpu.cortex-a7/mfpu.neon-vfpv4/mfloat-abi.softfp=mthumb/march.armv8-a/mfpu.neon-vfpv4/mfloat-abi.softfp
+MULTILIB_REUSE += mthumb/mcpu.cortex-a7/mfpu.neon-vfpv4/mfloat-abi.hard=mthumb/mcpu.cortex-a7/mfpu.neon-fp-armv8/mfloat-abi.hard
+MULTILIB_REUSE += mthumb/mcpu.cortex-a7/mfpu.neon-vfpv4/mfloat-abi.softfp=mthumb/mcpu.cortex-a7/mfpu.neon-fp-armv8/mfloat-abi.softfp
diff --git a/gcc/config/arm/thumb2.md b/gcc/config/arm/thumb2.md
index 3b5944a014a..b8b49fe7aee 100644
--- a/gcc/config/arm/thumb2.md
+++ b/gcc/config/arm/thumb2.md
@@ -1449,11 +1449,7 @@
;; knows what to generate.
(define_expand "doloop_end"
[(use (match_operand 0 "" "")) ; loop pseudo
- (use (match_operand 1 "" "")) ; iterations; zero if unknown
- (use (match_operand 2 "" "")) ; max iterations
- (use (match_operand 3 "" "")) ; loop level
- (use (match_operand 4 "" "")) ; label
- (use (match_operand 5 "" ""))] ; flag: 1 if loop entered at top, else 0
+ (use (match_operand 1 "" ""))] ; label
"TARGET_32BIT"
"
{
@@ -1472,10 +1468,6 @@
rtx insn;
rtx cmp;
- /* Only use this on innermost loops. */
- if (INTVAL (operands[3]) > 1)
- FAIL;
-
if (GET_MODE (operands[0]) != SImode)
FAIL;
@@ -1488,7 +1480,7 @@
cmp = XVECEXP (PATTERN (insn), 0, 0);
cc_reg = SET_DEST (cmp);
bcomp = gen_rtx_NE (VOIDmode, cc_reg, const0_rtx);
- loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [4]);
+ loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [1]);
emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
loc_ref, pc_rtx)));
diff --git a/gcc/config/arm/types.md b/gcc/config/arm/types.md
index 7a96438fd48..1c4b9e33c7e 100644
--- a/gcc/config/arm/types.md
+++ b/gcc/config/arm/types.md
@@ -227,68 +227,298 @@
;
; The classification below is for NEON instructions.
;
-; neon_bp_2cycle
-; neon_bp_3cycle
-; neon_bp_simple
-; neon_fp_vadd_ddd_vabs_dd
-; neon_fp_vadd_qqq_vabs_qq
-; neon_fp_vmla_ddd_scalar
-; neon_fp_vmla_ddd
-; neon_fp_vmla_qqq_scalar
-; neon_fp_vmla_qqq
-; neon_fp_vmul_ddd
-; neon_fp_vmul_qqd
-; neon_fp_vrecps_vrsqrts_ddd
-; neon_fp_vrecps_vrsqrts_qqq
-; neon_fp_vsum
-; neon_int_1
-; neon_int_2
-; neon_int_3
-; neon_int_4
-; neon_int_5
-; neon_ldm_2
+; neon_add
+; neon_add_q
+; neon_add_widen
+; neon_add_long
+; neon_qadd
+; neon_qadd_q
+; neon_add_halve
+; neon_add_halve_q
+; neon_add_halve_narrow_q
+; neon_sub
+; neon_sub_q
+; neon_sub_widen
+; neon_sub_long
+; neon_qsub
+; neon_qsub_q
+; neon_sub_halve
+; neon_sub_halve_q
+; neon_sub_halve_narrow_q
+; neon_abs
+; neon_abs_q
+; neon_neg
+; neon_neg_q
+; neon_qneg
+; neon_qneg_q
+; neon_qabs
+; neon_qabs_q
+; neon_abd
+; neon_abd_q
+; neon_abd_long
+; neon_minmax
+; neon_minmax_q
+; neon_compare
+; neon_compare_q
+; neon_compare_zero
+; neon_compare_zero_q
+; neon_arith_acc
+; neon_arith_acc_q
+; neon_reduc_add
+; neon_reduc_add_q
+; neon_reduc_add_long
+; neon_reduc_add_acc
+; neon_reduc_add_acc_q
+; neon_reduc_minmax
+; neon_reduc_minmax_q
+; neon_logic
+; neon_logic_q
+; neon_tst
+; neon_tst_q
+; neon_shift_imm
+; neon_shift_imm_q
+; neon_shift_imm_narrow_q
+; neon_shift_imm_long
+; neon_shift_reg
+; neon_shift_reg_q
+; neon_shift_acc
+; neon_shift_acc_q
+; neon_sat_shift_imm
+; neon_sat_shift_imm_q
+; neon_sat_shift_imm_narrow_q
+; neon_sat_shift_reg
+; neon_sat_shift_reg_q
+; neon_ins
+; neon_ins_q
+; neon_move
+; neon_move_q
+; neon_move_narrow_q
+; neon_permute
+; neon_permute_q
+; neon_zip
+; neon_zip_q
+; neon_tbl1
+; neon_tbl1_q
+; neon_tbl2
+; neon_tbl2_q
+; neon_tbl3
+; neon_tbl3_q
+; neon_tbl4
+; neon_tbl4_q
+; neon_bsl
+; neon_bsl_q
+; neon_cls
+; neon_cls_q
+; neon_cnt
+; neon_cnt_q
+; neon_ext
+; neon_ext_q
+; neon_rbit
+; neon_rbit_q
+; neon_rev
+; neon_rev_q
+; neon_mul_b
+; neon_mul_b_q
+; neon_mul_h
+; neon_mul_h_q
+; neon_mul_s
+; neon_mul_s_q
+; neon_mul_b_long
+; neon_mul_h_long
+; neon_mul_s_long
+; neon_mul_h_scalar
+; neon_mul_h_scalar_q
+; neon_mul_s_scalar
+; neon_mul_s_scalar_q
+; neon_mul_h_scalar_long
+; neon_mul_s_scalar_long
+; neon_sat_mul_b
+; neon_sat_mul_b_q
+; neon_sat_mul_h
+; neon_sat_mul_h_q
+; neon_sat_mul_s
+; neon_sat_mul_s_q
+; neon_sat_mul_b_long
+; neon_sat_mul_h_long
+; neon_sat_mul_s_long
+; neon_sat_mul_h_scalar
+; neon_sat_mul_h_scalar_q
+; neon_sat_mul_s_scalar
+; neon_sat_mul_s_scalar_q
+; neon_sat_mul_h_scalar_long
+; neon_sat_mul_s_scalar_long
+; neon_mla_b
+; neon_mla_b_q
+; neon_mla_h
+; neon_mla_h_q
+; neon_mla_s
+; neon_mla_s_q
+; neon_mla_b_long
+; neon_mla_h_long
+; neon_mla_s_long
+; neon_mla_h_scalar
+; neon_mla_h_scalar_q
+; neon_mla_s_scalar
+; neon_mla_s_scalar_q
+; neon_mla_h_scalar_long
+; neon_mla_s_scalar_long
+; neon_sat_mla_b_long
+; neon_sat_mla_h_long
+; neon_sat_mla_s_long
+; neon_sat_mla_h_scalar_long
+; neon_sat_mla_s_scalar_long
+; neon_to_gp
+; neon_to_gp_q
+; neon_from_gp
+; neon_from_gp_q
; neon_ldr
-; neon_mcr_2_mcrr
-; neon_mcr
-; neon_mla_ddd_16_scalar_qdd_32_16_long_scalar
-; neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long
-; neon_mla_ddd_8_16_qdd_16_8_long_32_16_long
-; neon_mla_qqq_32_qqd_32_scalar
-; neon_mla_qqq_8_16
-; neon_mrc
-; neon_mrrc
-; neon_mul_ddd_16_scalar_32_16_long_scalar
-; neon_mul_ddd_8_16_qdd_16_8_long_32_16_long
-; neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar
-; neon_mul_qqd_32_scalar
-; neon_mul_qqq_8_16_32_ddd_32
-; neon_shift_1
-; neon_shift_2
-; neon_shift_3
-; neon_stm_2
+; neon_load1_1reg
+; neon_load1_1reg_q
+; neon_load1_2reg
+; neon_load1_2reg_q
+; neon_load1_3reg
+; neon_load1_3reg_q
+; neon_load1_4reg
+; neon_load1_4reg_q
+; neon_load1_all_lanes
+; neon_load1_all_lanes_q
+; neon_load1_one_lane
+; neon_load1_one_lane_q
+; neon_load2_2reg
+; neon_load2_2reg_q
+; neon_load2_4reg
+; neon_load2_4reg_q
+; neon_load2_all_lanes
+; neon_load2_all_lanes_q
+; neon_load2_one_lane
+; neon_load2_one_lane_q
+; neon_load3_3reg
+; neon_load3_3reg_q
+; neon_load3_all_lanes
+; neon_load3_all_lanes_q
+; neon_load3_one_lane
+; neon_load3_one_lane_q
+; neon_load4_4reg
+; neon_load4_4reg_q
+; neon_load4_all_lanes
+; neon_load4_all_lanes_q
+; neon_load4_one_lane
+; neon_load4_one_lane_q
; neon_str
-; neon_vaba_qqq
-; neon_vaba
-; neon_vld1_1_2_regs
-; neon_vld1_3_4_regs
-; neon_vld1_vld2_lane
-; neon_vld2_2_regs_vld1_vld2_all_lanes
-; neon_vld2_4_regs
-; neon_vld3_vld4_all_lanes
-; neon_vld3_vld4_lane
-; neon_vld3_vld4
-; neon_vmov
-; neon_vqneg_vqabs
-; neon_vqshl_vrshl_vqrshl_qqq
-; neon_vshl_ddd
-; neon_vsma
-; neon_vsra_vrsra
-; neon_vst1_1_2_regs_vst2_2_regs
-; neon_vst1_3_4_regs
-; neon_vst1_vst2_lane
-; neon_vst2_4_regs_vst3_vst4
-; neon_vst3_vst4_lane
-; neon_vst3_vst4
+; neon_store1_1reg
+; neon_store1_1reg_q
+; neon_store1_2reg
+; neon_store1_2reg_q
+; neon_store1_3reg
+; neon_store1_3reg_q
+; neon_store1_4reg
+; neon_store1_4reg_q
+; neon_store1_one_lane
+; neon_store1_one_lane_q
+; neon_store2_2reg
+; neon_store2_2reg_q
+; neon_store2_4reg
+; neon_store2_4reg_q
+; neon_store2_one_lane
+; neon_store2_one_lane_q
+; neon_store3_3reg
+; neon_store3_3reg_q
+; neon_store3_one_lane
+; neon_store3_one_lane_q
+; neon_store4_4reg
+; neon_store4_4reg_q
+; neon_store4_one_lane
+; neon_store4_one_lane_q
+; neon_fp_abs_s
+; neon_fp_abs_s_q
+; neon_fp_abs_d
+; neon_fp_abs_d_q
+; neon_fp_neg_s
+; neon_fp_neg_s_q
+; neon_fp_neg_d
+; neon_fp_neg_d_q
+; neon_fp_abd_s
+; neon_fp_abd_s_q
+; neon_fp_abd_d
+; neon_fp_abd_d_q
+; neon_fp_addsub_s
+; neon_fp_addsub_s_q
+; neon_fp_addsub_d
+; neon_fp_addsub_d_q
+; neon_fp_compare_s
+; neon_fp_compare_s_q
+; neon_fp_compare_d
+; neon_fp_compare_d_q
+; neon_fp_minmax_s
+; neon_fp_minmax_s_q
+; neon_fp_minmax_d
+; neon_fp_minmax_d_q
+; neon_fp_reduc_add_s
+; neon_fp_reduc_add_s_q
+; neon_fp_reduc_add_d
+; neon_fp_reduc_add_d_q
+; neon_fp_reduc_minmax_s
+; neon_fp_reduc_minmax_s_q
+; neon_fp_reduc_minmax_d
+; neon_fp_reduc_minmax_d_q
+; neon_fp_cvt_narrow_s_q
+; neon_fp_cvt_narrow_d_q
+; neon_fp_cvt_widen_h
+; neon_fp_cvt_widen_s
+; neon_fp_to_int_s
+; neon_fp_to_int_s_q
+; neon_fp_to_int_d
+; neon_fp_to_int_d_q
+; neon_int_to_fp_s
+; neon_int_to_fp_s_q
+; neon_int_to_fp_d
+; neon_int_to_fp_d_q
+; neon_fp_round_s
+; neon_fp_round_s_q
+; neon_fp_round_d
+; neon_fp_round_d_q
+; neon_fp_recpe_s
+; neon_fp_recpe_s_q
+; neon_fp_recpe_d
+; neon_fp_recpe_d_q
+; neon_fp_recps_s
+; neon_fp_recps_s_q
+; neon_fp_recps_d
+; neon_fp_recps_d_q
+; neon_fp_recpx_s
+; neon_fp_recpx_s_q
+; neon_fp_recpx_d
+; neon_fp_recpx_d_q
+; neon_fp_rsqrte_s
+; neon_fp_rsqrte_s_q
+; neon_fp_rsqrte_d
+; neon_fp_rsqrte_d_q
+; neon_fp_rsqrts_s
+; neon_fp_rsqrts_s_q
+; neon_fp_rsqrts_d
+; neon_fp_rsqrts_d_q
+; neon_fp_mul_s
+; neon_fp_mul_s_q
+; neon_fp_mul_s_scalar
+; neon_fp_mul_s_scalar_q
+; neon_fp_mul_d
+; neon_fp_mul_d_q
+; neon_fp_mul_d_scalar_q
+; neon_fp_mla_s
+; neon_fp_mla_s_q
+; neon_fp_mla_s_scalar
+; neon_fp_mla_s_scalar_q
+; neon_fp_mla_d
+; neon_fp_mla_d_q
+; neon_fp_mla_d_scalar_q
+; neon_fp_sqrt_s
+; neon_fp_sqrt_s_q
+; neon_fp_sqrt_d
+; neon_fp_sqrt_d_q
+; neon_fp_div_s
+; neon_fp_div_s_q
+; neon_fp_div_d
+; neon_fp_div_d_q
(define_attr "type"
"adc_imm,\
@@ -481,69 +711,332 @@
wmmx_wunpckih,\
wmmx_wunpckil,\
wmmx_wxor,\
- neon_bp_2cycle,\
- neon_bp_3cycle,\
- neon_bp_simple,\
- neon_fp_vadd_ddd_vabs_dd,\
- neon_fp_vadd_qqq_vabs_qq,\
- neon_fp_vmla_ddd_scalar,\
- neon_fp_vmla_ddd,\
- neon_fp_vmla_qqq_scalar,\
- neon_fp_vmla_qqq,\
- neon_fp_vmul_ddd,\
- neon_fp_vmul_qqd,\
- neon_fp_vrecps_vrsqrts_ddd,\
- neon_fp_vrecps_vrsqrts_qqq,\
- neon_fp_vsum,\
- neon_int_1,\
- neon_int_2,\
- neon_int_3,\
- neon_int_4,\
- neon_int_5,\
- neon_ldm_2,\
+\
+ neon_add,\
+ neon_add_q,\
+ neon_add_widen,\
+ neon_add_long,\
+ neon_qadd,\
+ neon_qadd_q,\
+ neon_add_halve,\
+ neon_add_halve_q,\
+ neon_add_halve_narrow_q,\
+\
+ neon_sub,\
+ neon_sub_q,\
+ neon_sub_widen,\
+ neon_sub_long,\
+ neon_qsub,\
+ neon_qsub_q,\
+ neon_sub_halve,\
+ neon_sub_halve_q,\
+ neon_sub_halve_narrow_q,\
+\
+ neon_abs,\
+ neon_abs_q,\
+ neon_neg,\
+ neon_neg_q,\
+ neon_qneg,\
+ neon_qneg_q,\
+ neon_qabs,\
+ neon_qabs_q,\
+ neon_abd,\
+ neon_abd_q,\
+ neon_abd_long,\
+\
+ neon_minmax,\
+ neon_minmax_q,\
+ neon_compare,\
+ neon_compare_q,\
+ neon_compare_zero,\
+ neon_compare_zero_q,\
+\
+ neon_arith_acc,\
+ neon_arith_acc_q,\
+ neon_reduc_add,\
+ neon_reduc_add_q,\
+ neon_reduc_add_long,\
+ neon_reduc_add_acc,\
+ neon_reduc_add_acc_q,\
+ neon_reduc_minmax,\
+ neon_reduc_minmax_q,\
+ neon_logic,\
+ neon_logic_q,\
+ neon_tst,\
+ neon_tst_q,\
+\
+ neon_shift_imm,\
+ neon_shift_imm_q,\
+ neon_shift_imm_narrow_q,\
+ neon_shift_imm_long,\
+ neon_shift_reg,\
+ neon_shift_reg_q,\
+ neon_shift_acc,\
+ neon_shift_acc_q,\
+ neon_sat_shift_imm,\
+ neon_sat_shift_imm_q,\
+ neon_sat_shift_imm_narrow_q,\
+ neon_sat_shift_reg,\
+ neon_sat_shift_reg_q,\
+\
+ neon_ins,\
+ neon_ins_q,\
+ neon_move,\
+ neon_move_q,\
+ neon_move_narrow_q,\
+ neon_permute,\
+ neon_permute_q,\
+ neon_zip,\
+ neon_zip_q,\
+ neon_tbl1,\
+ neon_tbl1_q,\
+ neon_tbl2,\
+ neon_tbl2_q,\
+ neon_tbl3,\
+ neon_tbl3_q,\
+ neon_tbl4,\
+ neon_tbl4_q,\
+\
+ neon_bsl,\
+ neon_bsl_q,\
+ neon_cls,\
+ neon_cls_q,\
+ neon_cnt,\
+ neon_cnt_q,\
+ neon_dup,\
+ neon_dup_q,\
+ neon_ext,\
+ neon_ext_q,\
+ neon_rbit,\
+ neon_rbit_q,\
+ neon_rev,\
+ neon_rev_q,\
+\
+ neon_mul_b,\
+ neon_mul_b_q,\
+ neon_mul_h,\
+ neon_mul_h_q,\
+ neon_mul_s,\
+ neon_mul_s_q,\
+ neon_mul_b_long,\
+ neon_mul_h_long,\
+ neon_mul_s_long,\
+ neon_mul_h_scalar,\
+ neon_mul_h_scalar_q,\
+ neon_mul_s_scalar,\
+ neon_mul_s_scalar_q,\
+ neon_mul_h_scalar_long,\
+ neon_mul_s_scalar_long,\
+\
+ neon_sat_mul_b,\
+ neon_sat_mul_b_q,\
+ neon_sat_mul_h,\
+ neon_sat_mul_h_q,\
+ neon_sat_mul_s,\
+ neon_sat_mul_s_q,\
+ neon_sat_mul_b_long,\
+ neon_sat_mul_h_long,\
+ neon_sat_mul_s_long,\
+ neon_sat_mul_h_scalar,\
+ neon_sat_mul_h_scalar_q,\
+ neon_sat_mul_s_scalar,\
+ neon_sat_mul_s_scalar_q,\
+ neon_sat_mul_h_scalar_long,\
+ neon_sat_mul_s_scalar_long,\
+\
+ neon_mla_b,\
+ neon_mla_b_q,\
+ neon_mla_h,\
+ neon_mla_h_q,\
+ neon_mla_s,\
+ neon_mla_s_q,\
+ neon_mla_b_long,\
+ neon_mla_h_long,\
+ neon_mla_s_long,\
+ neon_mla_h_scalar,\
+ neon_mla_h_scalar_q,\
+ neon_mla_s_scalar,\
+ neon_mla_s_scalar_q,\
+ neon_mla_h_scalar_long,\
+ neon_mla_s_scalar_long,\
+\
+ neon_sat_mla_b_long,\
+ neon_sat_mla_h_long,\
+ neon_sat_mla_s_long,\
+ neon_sat_mla_h_scalar_long,\
+ neon_sat_mla_s_scalar_long,\
+\
+ neon_to_gp,\
+ neon_to_gp_q,\
+ neon_from_gp,\
+ neon_from_gp_q,\
+\
neon_ldr,\
- neon_mcr_2_mcrr,\
- neon_mcr,\
- neon_mla_ddd_16_scalar_qdd_32_16_long_scalar,\
- neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long,\
- neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
- neon_mla_qqq_32_qqd_32_scalar,\
- neon_mla_qqq_8_16,\
- neon_mrc,\
- neon_mrrc,\
- neon_mul_ddd_16_scalar_32_16_long_scalar,\
- neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
- neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar,\
- neon_mul_qqd_32_scalar,\
- neon_mul_qqq_8_16_32_ddd_32,\
- neon_shift_1,\
- neon_shift_2,\
- neon_shift_3,\
- neon_stm_2,\
+ neon_load1_1reg,\
+ neon_load1_1reg_q,\
+ neon_load1_2reg,\
+ neon_load1_2reg_q,\
+ neon_load1_3reg,\
+ neon_load1_3reg_q,\
+ neon_load1_4reg,\
+ neon_load1_4reg_q,\
+ neon_load1_all_lanes,\
+ neon_load1_all_lanes_q,\
+ neon_load1_one_lane,\
+ neon_load1_one_lane_q,\
+\
+ neon_load2_2reg,\
+ neon_load2_2reg_q,\
+ neon_load2_4reg,\
+ neon_load2_4reg_q,\
+ neon_load2_all_lanes,\
+ neon_load2_all_lanes_q,\
+ neon_load2_one_lane,\
+ neon_load2_one_lane_q,\
+\
+ neon_load3_3reg,\
+ neon_load3_3reg_q,\
+ neon_load3_all_lanes,\
+ neon_load3_all_lanes_q,\
+ neon_load3_one_lane,\
+ neon_load3_one_lane_q,\
+\
+ neon_load4_4reg,\
+ neon_load4_4reg_q,\
+ neon_load4_all_lanes,\
+ neon_load4_all_lanes_q,\
+ neon_load4_one_lane,\
+ neon_load4_one_lane_q,\
+\
neon_str,\
- neon_vaba_qqq,\
- neon_vaba,\
- neon_vld1_1_2_regs,\
- neon_vld1_3_4_regs,\
- neon_vld1_vld2_lane,\
- neon_vld2_2_regs_vld1_vld2_all_lanes,\
- neon_vld2_4_regs,\
- neon_vld3_vld4_all_lanes,\
- neon_vld3_vld4_lane,\
- neon_vld3_vld4,\
- neon_vmov,\
- neon_vqneg_vqabs,\
- neon_vqshl_vrshl_vqrshl_qqq,\
- neon_vshl_ddd,\
- neon_vsma,\
- neon_vsra_vrsra,\
- neon_vst1_1_2_regs_vst2_2_regs,\
- neon_vst1_3_4_regs,\
- neon_vst1_vst2_lane,\
- neon_vst2_4_regs_vst3_vst4,\
- neon_vst3_vst4_lane,\
- neon_vst3_vst4"
- (const_string "untyped"))
+ neon_store1_1reg,\
+ neon_store1_1reg_q,\
+ neon_store1_2reg,\
+ neon_store1_2reg_q,\
+ neon_store1_3reg,\
+ neon_store1_3reg_q,\
+ neon_store1_4reg,\
+ neon_store1_4reg_q,\
+ neon_store1_one_lane,\
+ neon_store1_one_lane_q,\
+\
+ neon_store2_2reg,\
+ neon_store2_2reg_q,\
+ neon_store2_4reg,\
+ neon_store2_4reg_q,\
+ neon_store2_one_lane,\
+ neon_store2_one_lane_q,\
+\
+ neon_store3_3reg,\
+ neon_store3_3reg_q,\
+ neon_store3_one_lane,\
+ neon_store3_one_lane_q,\
+\
+ neon_store4_4reg,\
+ neon_store4_4reg_q,\
+ neon_store4_one_lane,\
+ neon_store4_one_lane_q,\
+\
+ neon_fp_abs_s,\
+ neon_fp_abs_s_q,\
+ neon_fp_abs_d,\
+ neon_fp_abs_d_q,\
+ neon_fp_neg_s,\
+ neon_fp_neg_s_q,\
+ neon_fp_neg_d,\
+ neon_fp_neg_d_q,\
+\
+ neon_fp_abd_s,\
+ neon_fp_abd_s_q,\
+ neon_fp_abd_d,\
+ neon_fp_abd_d_q,\
+ neon_fp_addsub_s,\
+ neon_fp_addsub_s_q,\
+ neon_fp_addsub_d,\
+ neon_fp_addsub_d_q,\
+ neon_fp_compare_s,\
+ neon_fp_compare_s_q,\
+ neon_fp_compare_d,\
+ neon_fp_compare_d_q,\
+ neon_fp_minmax_s,\
+ neon_fp_minmax_s_q,\
+ neon_fp_minmax_d,\
+ neon_fp_minmax_d_q,\
+\
+ neon_fp_reduc_add_s,\
+ neon_fp_reduc_add_s_q,\
+ neon_fp_reduc_add_d,\
+ neon_fp_reduc_add_d_q,\
+ neon_fp_reduc_minmax_s,\
+ neon_fp_reduc_minmax_s_q,\
+ neon_fp_reduc_minmax_d,\
+ neon_fp_reduc_minmax_d_q,\
+\
+ neon_fp_cvt_narrow_s_q,\
+ neon_fp_cvt_narrow_d_q,\
+ neon_fp_cvt_widen_h,\
+ neon_fp_cvt_widen_s,\
+\
+ neon_fp_to_int_s,\
+ neon_fp_to_int_s_q,\
+ neon_fp_to_int_d,\
+ neon_fp_to_int_d_q,\
+ neon_int_to_fp_s,\
+ neon_int_to_fp_s_q,\
+ neon_int_to_fp_d,\
+ neon_int_to_fp_d_q,\
+ neon_fp_round_s,\
+ neon_fp_round_s_q,\
+ neon_fp_round_d,\
+ neon_fp_round_d_q,\
+\
+ neon_fp_recpe_s,\
+ neon_fp_recpe_s_q,\
+ neon_fp_recpe_d,\
+ neon_fp_recpe_d_q,\
+ neon_fp_recps_s,\
+ neon_fp_recps_s_q,\
+ neon_fp_recps_d,\
+ neon_fp_recps_d_q,\
+ neon_fp_recpx_s,\
+ neon_fp_recpx_s_q,\
+ neon_fp_recpx_d,\
+ neon_fp_recpx_d_q,\
+\
+ neon_fp_rsqrte_s,\
+ neon_fp_rsqrte_s_q,\
+ neon_fp_rsqrte_d,\
+ neon_fp_rsqrte_d_q,\
+ neon_fp_rsqrts_s,\
+ neon_fp_rsqrts_s_q,\
+ neon_fp_rsqrts_d,\
+ neon_fp_rsqrts_d_q,\
+\
+ neon_fp_mul_s,\
+ neon_fp_mul_s_q,\
+ neon_fp_mul_s_scalar,\
+ neon_fp_mul_s_scalar_q,\
+ neon_fp_mul_d,\
+ neon_fp_mul_d_q,\
+ neon_fp_mul_d_scalar_q,\
+\
+ neon_fp_mla_s,\
+ neon_fp_mla_s_q,\
+ neon_fp_mla_s_scalar,\
+ neon_fp_mla_s_scalar_q,\
+ neon_fp_mla_d,\
+ neon_fp_mla_d_q,\
+ neon_fp_mla_d_scalar_q,\
+\
+ neon_fp_sqrt_s,\
+ neon_fp_sqrt_s_q,\
+ neon_fp_sqrt_d,\
+ neon_fp_sqrt_d_q,\
+ neon_fp_div_s,\
+ neon_fp_div_s_q,\
+ neon_fp_div_d,\
+ neon_fp_div_d_q"
+ (const_string "untyped"))
; Is this an (integer side) multiply with a 32-bit (or smaller) result?
(define_attr "mul32" "no,yes"
diff --git a/gcc/config/arm/unspecs.md b/gcc/config/arm/unspecs.md
index c43a6a6c696..508603cf6c8 100644
--- a/gcc/config/arm/unspecs.md
+++ b/gcc/config/arm/unspecs.md
@@ -83,8 +83,6 @@
; FPSCR rounding mode and signal inexactness.
UNSPEC_VRINTA ; Represent a float to integral float rounding
; towards nearest, ties away from zero.
- UNSPEC_RRX ; Rotate Right with Extend shifts register right
- ; by one place, with Carry flag shifted into bit[31].
])
(define_c_enum "unspec" [
diff --git a/gcc/config/arm/vfp.md b/gcc/config/arm/vfp.md
index 0b10c130d70..22b63251a87 100644
--- a/gcc/config/arm/vfp.md
+++ b/gcc/config/arm/vfp.md
@@ -260,7 +260,7 @@
}
"
[(set_attr "conds" "unconditional")
- (set_attr "type" "neon_vld1_1_2_regs,neon_vst1_1_2_regs_vst2_2_regs,\
+ (set_attr "type" "neon_load1_1reg,neon_store1_1reg,\
load1,store1,fmov,mov_reg,f_mcr,f_mrc,multiple")
(set_attr "length" "4,4,4,4,4,4,4,4,8")]
)
diff --git a/gcc/config/avr/avr-log.c b/gcc/config/avr/avr-log.c
index 9e538e60124..87fa14d7006 100644
--- a/gcc/config/avr/avr-log.c
+++ b/gcc/config/avr/avr-log.c
@@ -49,8 +49,6 @@
C: enum rtx_code
m: enum machine_mode
R: enum reg_class
- D: double_int (signed decimal)
- X: double_int (unsigned hex)
L: insn list
H: location_t
@@ -138,45 +136,6 @@ avr_log_set_caller_f (const char *caller)
}
-/* Copy-paste from double-int.c:double_int_split_digit (it's static there).
- Splits last digit of *CST (taken as unsigned) in BASE and returns it. */
-
-static unsigned
-avr_double_int_pop_digit (double_int *cst, unsigned base)
-{
- double_int drem;
-
- *cst = cst->udivmod (double_int::from_uhwi (base), (int) FLOOR_DIV_EXPR,
- &drem);
-
- return (unsigned) drem.to_uhwi();
-}
-
-
-/* Dump VAL as hex value to FILE. */
-
-static void
-avr_dump_double_int_hex (FILE *file, double_int val)
-{
- unsigned digit[4];
-
- digit[0] = avr_double_int_pop_digit (&val, 1 << 16);
- digit[1] = avr_double_int_pop_digit (&val, 1 << 16);
- digit[2] = avr_double_int_pop_digit (&val, 1 << 16);
- digit[3] = avr_double_int_pop_digit (&val, 1 << 16);
-
- fprintf (file, "0x");
-
- if (digit[3] | digit[2])
- fprintf (file, "%04x%04x", digit[3], digit[2]);
-
- if (digit[3] | digit[2] | digit[1] | digit[0])
- fprintf (file, "%04x%04x", digit[1], digit[0]);
- else
- fprintf (file, "0");
-}
-
-
/* Worker function implementing the %-codes and forwarding to
respective print/dump function. */
@@ -231,14 +190,6 @@ avr_log_vadump (FILE *file, const char *fmt, va_list ap)
fprintf (file, "%d", va_arg (ap, int));
break;
- case 'D':
- dump_double_int (file, va_arg (ap, double_int), false);
- break;
-
- case 'X':
- avr_dump_double_int_hex (file, va_arg (ap, double_int));
- break;
-
case 'x':
fprintf (file, "%x", va_arg (ap, int));
break;
diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c
index f6d88856bec..e7e1c2f138b 100644
--- a/gcc/config/avr/avr.c
+++ b/gcc/config/avr/avr.c
@@ -11365,26 +11365,12 @@ avr_expand_delay_cycles (rtx operands0)
}
-/* Return VAL * BASE + DIGIT. BASE = 0 is shortcut for BASE = 2^{32} */
-
-static double_int
-avr_double_int_push_digit (double_int val, int base,
- unsigned HOST_WIDE_INT digit)
-{
- val = 0 == base
- ? val.llshift (32, 64)
- : val * double_int::from_uhwi (base);
-
- return val + double_int::from_uhwi (digit);
-}
-
-
/* Compute the image of x under f, i.e. perform x --> f(x) */
static int
-avr_map (double_int f, int x)
+avr_map (unsigned int f, int x)
{
- return 0xf & f.lrshift (4*x, 64).to_uhwi ();
+ return x < 8 ? (f >> (4 * x)) & 0xf : 0;
}
@@ -11409,7 +11395,7 @@ enum
};
static unsigned
-avr_map_metric (double_int a, int mode)
+avr_map_metric (unsigned int a, int mode)
{
unsigned i, metric = 0;
@@ -11442,7 +11428,8 @@ avr_map_metric (double_int a, int mode)
bool
avr_has_nibble_0xf (rtx ival)
{
- return 0 != avr_map_metric (rtx_to_double_int (ival), MAP_MASK_PREIMAGE_F);
+ unsigned int map = UINTVAL (ival) & GET_MODE_MASK (SImode);
+ return 0 != avr_map_metric (map, MAP_MASK_PREIMAGE_F);
}
@@ -11476,7 +11463,7 @@ typedef struct
int cost;
/* The composition F o G^-1 (*, arg) for some function F */
- double_int map;
+ unsigned int map;
/* For debug purpose only */
const char *str;
@@ -11484,21 +11471,21 @@ typedef struct
static const avr_map_op_t avr_map_op[] =
{
- { LROTATE_EXPR, 0, 0x76543210, 0, { 0, 0 }, "id" },
- { LROTATE_EXPR, 1, 0x07654321, 2, { 0, 0 }, "<<<" },
- { LROTATE_EXPR, 2, 0x10765432, 4, { 0, 0 }, "<<<" },
- { LROTATE_EXPR, 3, 0x21076543, 4, { 0, 0 }, "<<<" },
- { LROTATE_EXPR, 4, 0x32107654, 1, { 0, 0 }, "<<<" },
- { LROTATE_EXPR, 5, 0x43210765, 3, { 0, 0 }, "<<<" },
- { LROTATE_EXPR, 6, 0x54321076, 5, { 0, 0 }, "<<<" },
- { LROTATE_EXPR, 7, 0x65432107, 3, { 0, 0 }, "<<<" },
- { RSHIFT_EXPR, 1, 0x6543210c, 1, { 0, 0 }, ">>" },
- { RSHIFT_EXPR, 1, 0x7543210c, 1, { 0, 0 }, ">>" },
- { RSHIFT_EXPR, 2, 0x543210cc, 2, { 0, 0 }, ">>" },
- { RSHIFT_EXPR, 2, 0x643210cc, 2, { 0, 0 }, ">>" },
- { RSHIFT_EXPR, 2, 0x743210cc, 2, { 0, 0 }, ">>" },
- { LSHIFT_EXPR, 1, 0xc7654321, 1, { 0, 0 }, "<<" },
- { LSHIFT_EXPR, 2, 0xcc765432, 2, { 0, 0 }, "<<" }
+ { LROTATE_EXPR, 0, 0x76543210, 0, 0, "id" },
+ { LROTATE_EXPR, 1, 0x07654321, 2, 0, "<<<" },
+ { LROTATE_EXPR, 2, 0x10765432, 4, 0, "<<<" },
+ { LROTATE_EXPR, 3, 0x21076543, 4, 0, "<<<" },
+ { LROTATE_EXPR, 4, 0x32107654, 1, 0, "<<<" },
+ { LROTATE_EXPR, 5, 0x43210765, 3, 0, "<<<" },
+ { LROTATE_EXPR, 6, 0x54321076, 5, 0, "<<<" },
+ { LROTATE_EXPR, 7, 0x65432107, 3, 0, "<<<" },
+ { RSHIFT_EXPR, 1, 0x6543210c, 1, 0, ">>" },
+ { RSHIFT_EXPR, 1, 0x7543210c, 1, 0, ">>" },
+ { RSHIFT_EXPR, 2, 0x543210cc, 2, 0, ">>" },
+ { RSHIFT_EXPR, 2, 0x643210cc, 2, 0, ">>" },
+ { RSHIFT_EXPR, 2, 0x743210cc, 2, 0, ">>" },
+ { LSHIFT_EXPR, 1, 0xc7654321, 1, 0, "<<" },
+ { LSHIFT_EXPR, 2, 0xcc765432, 2, 0, "<<" }
};
@@ -11507,12 +11494,12 @@ static const avr_map_op_t avr_map_op[] =
If result.cost < 0 then such a decomposition does not exist. */
static avr_map_op_t
-avr_map_decompose (double_int f, const avr_map_op_t *g, bool val_const_p)
+avr_map_decompose (unsigned int f, const avr_map_op_t *g, bool val_const_p)
{
int i;
bool val_used_p = 0 != avr_map_metric (f, MAP_MASK_PREIMAGE_F);
avr_map_op_t f_ginv = *g;
- double_int ginv = double_int::from_uhwi (g->ginv);
+ unsigned int ginv = g->ginv;
f_ginv.cost = -1;
@@ -11532,7 +11519,7 @@ avr_map_decompose (double_int f, const avr_map_op_t *g, bool val_const_p)
return f_ginv;
}
- f_ginv.map = avr_double_int_push_digit (f_ginv.map, 16, x);
+ f_ginv.map = (f_ginv.map << 4) + x;
}
/* Step 2: Compute the cost of the operations.
@@ -11557,7 +11544,7 @@ avr_map_decompose (double_int f, const avr_map_op_t *g, bool val_const_p)
are mapped to 0 and used operands are reloaded to xop[0]. */
xop[0] = all_regs_rtx[24];
- xop[1] = gen_int_mode (f_ginv.map.to_uhwi (), SImode);
+ xop[1] = gen_int_mode (f_ginv.map, SImode);
xop[2] = all_regs_rtx[25];
xop[3] = val_used_p ? xop[0] : const0_rtx;
@@ -11584,7 +11571,7 @@ avr_map_decompose (double_int f, const avr_map_op_t *g, bool val_const_p)
is different to its source position. */
static void
-avr_move_bits (rtx *xop, double_int map, bool fixp_p, int *plen)
+avr_move_bits (rtx *xop, unsigned int map, bool fixp_p, int *plen)
{
int bit_dest, b;
@@ -11637,7 +11624,7 @@ avr_move_bits (rtx *xop, double_int map, bool fixp_p, int *plen)
const char*
avr_out_insert_bits (rtx *op, int *plen)
{
- double_int map = rtx_to_double_int (op[1]);
+ unsigned int map = UINTVAL (op[1]) & GET_MODE_MASK (SImode);
unsigned mask_fixed;
bool fixp_p = true;
rtx xop[4];
@@ -11651,9 +11638,7 @@ avr_out_insert_bits (rtx *op, int *plen)
if (plen)
*plen = 0;
else if (flag_print_asm_name)
- fprintf (asm_out_file,
- ASM_COMMENT_START "map = 0x%08" HOST_LONG_FORMAT "x\n",
- map.to_uhwi () & GET_MODE_MASK (SImode));
+ fprintf (asm_out_file, ASM_COMMENT_START "map = 0x%08x\n", map);
/* If MAP has fixed points it might be better to initialize the result
with the bits to be inserted instead of moving all bits by hand. */
@@ -12228,7 +12213,7 @@ avr_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED, tree *arg,
tree tval = arg[2];
tree tmap;
tree map_type = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (fndecl)));
- double_int map;
+ unsigned int map;
bool changed = false;
unsigned i;
avr_map_op_t best_g;
@@ -12241,8 +12226,8 @@ avr_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED, tree *arg,
break;
}
- map = tree_to_double_int (arg[0]);
- tmap = double_int_to_tree (map_type, map);
+ tmap = double_int_to_tree (map_type, tree_to_double_int (arg[0]));
+ map = TREE_INT_CST_LOW (tmap);
if (TREE_CODE (tval) != INTEGER_CST
&& 0 == avr_map_metric (map, MAP_MASK_PREIMAGE_F))
@@ -12308,7 +12293,7 @@ avr_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED, tree *arg,
/* Try to decomposing map to reduce overall cost. */
if (avr_log.builtin)
- avr_edump ("\n%?: %X\n%?: ROL cost: ", map);
+ avr_edump ("\n%?: %x\n%?: ROL cost: ", map);
best_g = avr_map_op[0];
best_g.cost = 1000;
@@ -12333,7 +12318,7 @@ avr_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED, tree *arg,
/* Apply operation G to the 2nd argument. */
if (avr_log.builtin)
- avr_edump ("%?: using OP(%s%d, %X) cost %d\n",
+ avr_edump ("%?: using OP(%s%d, %x) cost %d\n",
best_g.str, best_g.arg, best_g.map, best_g.cost);
/* Do right-shifts arithmetically: They copy the MSB instead of
@@ -12346,7 +12331,8 @@ avr_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED, tree *arg,
/* Use map o G^-1 instead of original map to undo the effect of G. */
- tmap = double_int_to_tree (map_type, best_g.map);
+ tmap = double_int_to_tree (map_type,
+ double_int::from_uhwi (best_g.map));
return build_call_expr (fndecl, 3, tmap, tbits, tval);
} /* AVR_BUILTIN_INSERT_BITS */
diff --git a/gcc/config/bfin/bfin-modes.def b/gcc/config/bfin/bfin-modes.def
index cf03a1a7e0d..da0303c8446 100644
--- a/gcc/config/bfin/bfin-modes.def
+++ b/gcc/config/bfin/bfin-modes.def
@@ -19,7 +19,7 @@
<http://www.gnu.org/licenses/>. */
/* PDImode for the 40-bit accumulators. */
-PARTIAL_INT_MODE (DI);
+PARTIAL_INT_MODE (DI, 40, PDI);
/* Two of those - covering both accumulators for vector multiplications. */
VECTOR_MODE (INT, PDI, 2);
diff --git a/gcc/config/bfin/bfin.c b/gcc/config/bfin/bfin.c
index 18457f8f7b6..bd677f88bab 100644
--- a/gcc/config/bfin/bfin.c
+++ b/gcc/config/bfin/bfin.c
@@ -2438,7 +2438,7 @@ cbranch_predicted_taken_p (rtx insn)
if (x)
{
- int pred_val = INTVAL (XEXP (x, 0));
+ int pred_val = XINT (x, 0);
return pred_val >= REG_BR_PROB_BASE / 2;
}
@@ -3366,6 +3366,22 @@ find_prev_insn_start (rtx insn)
return insn;
}
+/* Implement TARGET_CAN_USE_DOLOOP_P. */
+
+static bool
+bfin_can_use_doloop_p (double_int, double_int iterations_max,
+ unsigned int, bool)
+{
+ /* Due to limitations in the hardware (an initial loop count of 0
+ does not loop 2^32 times) we must avoid to generate a hardware
+ loops when we cannot rule out this case. */
+ if (!flag_unsafe_loop_optimizations
+ && (iterations_max.high != 0
+ || iterations_max.low >= 0xFFFFFFFF))
+ return false;
+ return true;
+}
+
/* Increment the counter for the number of loop instructions in the
current function. */
@@ -5810,4 +5826,7 @@ bfin_conditional_register_usage (void)
#undef TARGET_DELAY_VARTRACK
#define TARGET_DELAY_VARTRACK true
+#undef TARGET_CAN_USE_DOLOOP_P
+#define TARGET_CAN_USE_DOLOOP_P bfin_can_use_doloop_p
+
struct gcc_target targetm = TARGET_INITIALIZER;
diff --git a/gcc/config/bfin/bfin.md b/gcc/config/bfin/bfin.md
index 278ac602b09..e3bc6363f4a 100644
--- a/gcc/config/bfin/bfin.md
+++ b/gcc/config/bfin/bfin.md
@@ -1929,35 +1929,25 @@
;; Hardware loop
; operand 0 is the loop count pseudo register
-; operand 1 is the number of loop iterations or 0 if it is unknown
-; operand 2 is the maximum number of loop iterations
-; operand 3 is the number of levels of enclosed loops
-; operand 4 is the label to jump to at the top of the loop
-; operand 5 indicates if the loop is entered at the top
+; operand 1 is the label to jump to at the top of the loop
(define_expand "doloop_end"
[(parallel [(set (pc) (if_then_else
(ne (match_operand:SI 0 "" "")
(const_int 1))
- (label_ref (match_operand 4 "" ""))
+ (label_ref (match_operand 1 "" ""))
(pc)))
(set (match_dup 0)
(plus:SI (match_dup 0)
(const_int -1)))
(unspec [(const_int 0)] UNSPEC_LSETUP_END)
- (clobber (match_operand 5 ""))])] ; match_scratch
+ (clobber (match_dup 2))])] ; match_scratch
""
{
/* The loop optimizer doesn't check the predicates... */
if (GET_MODE (operands[0]) != SImode)
FAIL;
- /* Due to limitations in the hardware (an initial loop count of 0
- does not loop 2^32 times) we must avoid to generate a hardware
- loops when we cannot rule out this case. */
- if (!flag_unsafe_loop_optimizations
- && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) >= 0xFFFFFFFF)
- FAIL;
bfin_hardware_loop ();
- operands[5] = gen_rtx_SCRATCH (SImode);
+ operands[2] = gen_rtx_SCRATCH (SImode);
})
(define_insn "loop_end"
diff --git a/gcc/config/bfin/uclinux.h b/gcc/config/bfin/uclinux.h
index 63cba99cec6..848515c1bbc 100644
--- a/gcc/config/bfin/uclinux.h
+++ b/gcc/config/bfin/uclinux.h
@@ -32,14 +32,6 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
%{mfast-fp:-lbffastfp} %G %L %{mfast-fp:-lbffastfp} %G \
"
-/* Like the definition in gcc.c, but for purposes of uClinux, every link is
- static. */
-#define MFWRAP_SPEC " %{fmudflap|fmudflapth: \
- --wrap=malloc --wrap=free --wrap=calloc --wrap=realloc\
- --wrap=mmap --wrap=munmap --wrap=alloca\
- %{fmudflapth: --wrap=pthread_create\
-}} %{fmudflap|fmudflapth: --wrap=main}"
-
#undef TARGET_SUPPORTS_SYNC_CALLS
#define TARGET_SUPPORTS_SYNC_CALLS 1
diff --git a/gcc/config/c6x/c6x.md b/gcc/config/c6x/c6x.md
index e1c6f9aabab..d7606965cde 100644
--- a/gcc/config/c6x/c6x.md
+++ b/gcc/config/c6x/c6x.md
@@ -1421,27 +1421,23 @@
;; -------------------------------------------------------------------------
; operand 0 is the loop count pseudo register
-; operand 1 is the number of loop iterations or 0 if it is unknown
-; operand 2 is the maximum number of loop iterations
-; operand 3 is the number of levels of enclosed loops
-; operand 4 is the label to jump to at the top of the loop
-; operand 5 indicates if the loop is entered at the top
+; operand 1 is the label to jump to at the top of the loop
(define_expand "doloop_end"
[(parallel [(set (pc) (if_then_else
(ne (match_operand:SI 0 "" "")
(const_int 1))
- (label_ref (match_operand 4 "" ""))
+ (label_ref (match_operand 1 "" ""))
(pc)))
(set (match_dup 0)
(plus:SI (match_dup 0)
(const_int -1)))
- (clobber (match_operand 5 ""))])] ; match_scratch
+ (clobber (match_dup 2))])] ; match_scratch
"TARGET_INSNS_64PLUS && optimize"
{
/* The loop optimizer doesn't check the predicates... */
if (GET_MODE (operands[0]) != SImode)
FAIL;
- operands[5] = gen_rtx_SCRATCH (SImode);
+ operands[2] = gen_rtx_SCRATCH (SImode);
})
(define_insn "mvilc"
diff --git a/gcc/config/cris/cris.c b/gcc/config/cris/cris.c
index a9117d76611..7432251b950 100644
--- a/gcc/config/cris/cris.c
+++ b/gcc/config/cris/cris.c
@@ -1989,17 +1989,14 @@ cris_emit_trap_for_misalignment (rtx mem)
/* This will yield a btstq without a separate register used, usually -
with the exception for PRE hoisting the "and" but not the branch
- around the trap: see gcc.dg/target/cris/sync-3s.c. */
+ around the trap: see testsuite/gcc.target/cris/sync-3s.c. */
andop = gen_rtx_AND (Pmode, reg, GEN_INT (natural_alignment - 1));
emit_cmp_and_jump_insns (force_reg (SImode, andop), const0_rtx, EQ,
NULL_RTX, Pmode, 1, ok_label);
jmp = get_last_insn ();
gcc_assert (JUMP_P (jmp));
- /* While this isn't mudflap, it is a similar kind of assertion.
- If PRED_MUDFLAP stops working, use something else or introduce a
- more suitable assertion predication type. */
- predict_insn_def (jmp, PRED_MUDFLAP, TAKEN);
+ predict_insn_def (jmp, PRED_NORETURN, TAKEN);
expand_builtin_trap ();
emit_label (ok_label);
}
diff --git a/gcc/config/cris/t-elfmulti b/gcc/config/cris/t-elfmulti
index f4dfb85081e..aff60fc3ed1 100644
--- a/gcc/config/cris/t-elfmulti
+++ b/gcc/config/cris/t-elfmulti
@@ -16,9 +16,10 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-MULTILIB_OPTIONS = march=v10/march=v32
-MULTILIB_DIRNAMES = v10 v32
+MULTILIB_OPTIONS = march=v8/march=v10/march=v32
+MULTILIB_DIRNAMES = v8 v10 v32
MULTILIB_MATCHES = \
+ march?v8=mcpu?v8 \
march?v10=mcpu?etrax100lx \
march?v10=mcpu?ng \
march?v10=march?etrax100lx \
diff --git a/gcc/config/darwin-protos.h b/gcc/config/darwin-protos.h
index 36d16b9e57a..fe43ef39aeb 100644
--- a/gcc/config/darwin-protos.h
+++ b/gcc/config/darwin-protos.h
@@ -26,6 +26,7 @@ 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
diff --git a/gcc/config/darwin.c b/gcc/config/darwin.c
index ab48558127e..fc7a9a8f99e 100644
--- a/gcc/config/darwin.c
+++ b/gcc/config/darwin.c
@@ -45,6 +45,7 @@ along with GCC; see the file COPYING3. If not see
#include "df.h"
#include "debug.h"
#include "obstack.h"
+#include "gimple.h"
#include "lto-streamer.h"
/* Darwin supports a feature called fix-and-continue, which is used
@@ -405,6 +406,19 @@ machopic_output_function_base_name (FILE *file)
fprintf (file, "L%d$pb", current_pic_label_num);
}
+char curr_picbasename[32];
+
+const char *
+machopic_get_function_picbase (void)
+{
+ /* If dynamic-no-pic is on, we should not get here. */
+ gcc_assert (!MACHO_DYNAMIC_NO_PIC_P);
+
+ update_pic_label_number_if_needed ();
+ snprintf (curr_picbasename, 32, "L%d$pb", current_pic_label_num);
+ return (const char *) curr_picbasename;
+}
+
bool
machopic_should_output_picbase_label (void)
{
diff --git a/gcc/config/frv/frv.c b/gcc/config/frv/frv.c
index b0e8c91c93d..bcd55111434 100644
--- a/gcc/config/frv/frv.c
+++ b/gcc/config/frv/frv.c
@@ -2643,7 +2643,7 @@ frv_print_operand_jump_hint (rtx insn)
rtx note;
rtx labelref;
int ret;
- HOST_WIDE_INT prob = -1;
+ int prob = -1;
enum { UNKNOWN, BACKWARD, FORWARD } jump_type = UNKNOWN;
gcc_assert (JUMP_P (insn));
@@ -2669,7 +2669,7 @@ frv_print_operand_jump_hint (rtx insn)
else
{
- prob = INTVAL (XEXP (note, 0));
+ prob = XINT (note, 0);
ret = ((prob >= (REG_BR_PROB_BASE / 2))
? FRV_JUMP_LIKELY
: FRV_JUMP_NOT_LIKELY);
@@ -2690,10 +2690,10 @@ frv_print_operand_jump_hint (rtx insn)
}
fprintf (stderr,
- "%s: uid %ld, %s, probability = %ld, max prob. = %ld, hint = %d\n",
+ "%s: uid %ld, %s, probability = %d, max prob. = %d, hint = %d\n",
IDENTIFIER_POINTER (DECL_NAME (current_function_decl)),
- (long)INSN_UID (insn), direction, (long)prob,
- (long)REG_BR_PROB_BASE, ret);
+ (long)INSN_UID (insn), direction, prob,
+ REG_BR_PROB_BASE, ret);
}
#endif
@@ -3094,7 +3094,7 @@ frv_init_cumulative_args (CUMULATIVE_ARGS *cum,
{
tree ret_type = TREE_TYPE (fntype);
fprintf (stderr, " return=%s,",
- tree_code_name[ (int)TREE_CODE (ret_type) ]);
+ get_tree_code_name (TREE_CODE (ret_type)));
}
if (libname && GET_CODE (libname) == SYMBOL_REF)
diff --git a/gcc/config/i386/bdver3.md b/gcc/config/i386/bdver3.md
index 52418b5e5c9..421a3d1b30e 100644
--- a/gcc/config/i386/bdver3.md
+++ b/gcc/config/i386/bdver3.md
@@ -34,20 +34,22 @@
(define_cpu_unit "bdver3-decode0" "bdver3")
(define_cpu_unit "bdver3-decode1" "bdver3")
-(define_cpu_unit "bdver3-decodev" "bdver3")
+(define_cpu_unit "bdver3-decode2" "bdver3")
+(define_cpu_unit "bdver3-decode3" "bdver3")
;; Double decoded instructions take two cycles whereas
;; direct instructions take one cycle.
-;; Therefore four direct instructions can be decoded by
-;; two decoders in two cycles.
;; Vectorpath instructions are single issue instructions.
-;; So, we have separate unit for vector instructions.
-(exclusion_set "bdver3-decodev" "bdver3-decode0,bdver3-decode1")
+;; So, we engage all units vector instructions.
+(define_reservation "bdver3-vector" "bdver3-decode0+bdver3-decode1+bdver3-decode2+bdver3-decode3")
+
+;; Direct instructions can be issued to any of the four decoders
+(define_reservation "bdver3-direct" "(bdver3-decode0|bdver3-decode1|bdver3-decode2|bdver3-decode3)")
-(define_reservation "bdver3-vector" "bdver3-decodev")
-(define_reservation "bdver3-direct" "(bdver3-decode0|bdver3-decode1)")
;; Double instructions take two cycles to decode.
-(define_reservation "bdver3-double" "(bdver3-decode0|bdver3-decode1)*2")
+(define_reservation "bdver3-double" "(bdver3-decode0,bdver3-decode0)|
+ (bdver3-decode1,bdver3-decode1)| (bdver3-decode2,bdver3-decode2)|
+ (bdver3-decode3,bdver3-decode3)")
(define_cpu_unit "bdver3-ieu0" "bdver3_ieu")
(define_cpu_unit "bdver3-ieu1" "bdver3_ieu")
diff --git a/gcc/config/i386/constraints.md b/gcc/config/i386/constraints.md
index 92e0c053fac..7289ae493b0 100644
--- a/gcc/config/i386/constraints.md
+++ b/gcc/config/i386/constraints.md
@@ -18,7 +18,7 @@
;; <http://www.gnu.org/licenses/>.
;;; Unused letters:
-;;; B H T
+;;; H
;;; h j
;; Integer register constraints.
@@ -91,6 +91,9 @@
(define_register_constraint "x" "TARGET_SSE ? SSE_REGS : NO_REGS"
"Any SSE register.")
+(define_register_constraint "B" "TARGET_MPX ? BND_REGS : NO_REGS"
+ "@internal Any bound register.")
+
;; We use the Y prefix to denote any number of conditional register sets:
;; z First SSE register.
;; i SSE2 inter-unit moves to SSE register enabled
@@ -232,3 +235,25 @@
to fit that range (for immediate operands in zero-extending x86-64
instructions)."
(match_operand 0 "x86_64_zext_immediate_operand"))
+
+;; T prefix is used for different address constraints
+;; v - VSIB address
+;; s - address with no segment register
+;; i - address with no index and no rip
+;; b - address with no base and no rip
+
+(define_address_constraint "Tv"
+ "VSIB address operand"
+ (match_operand 0 "vsib_address_operand"))
+
+(define_address_constraint "Ts"
+ "Address operand without segment register"
+ (match_operand 0 "address_no_seg_operand"))
+
+(define_address_constraint "Ti"
+ "MPX address operand without index"
+ (match_operand 0 "address_mpx_no_index_operand"))
+
+(define_address_constraint "Tb"
+ "MPX address operand without base"
+ (match_operand 0 "address_mpx_no_base_operand"))
diff --git a/gcc/config/i386/i386-builtin-types.def b/gcc/config/i386/i386-builtin-types.def
index 314f3e888d8..c866170bde8 100644
--- a/gcc/config/i386/i386-builtin-types.def
+++ b/gcc/config/i386/i386-builtin-types.def
@@ -227,6 +227,7 @@ DEF_FUNCTION_TYPE (VOID, PCVOID)
DEF_FUNCTION_TYPE (VOID, PVOID)
DEF_FUNCTION_TYPE (VOID, UINT64)
DEF_FUNCTION_TYPE (VOID, UNSIGNED)
+DEF_FUNCTION_TYPE (VOID, PUSHORT)
DEF_FUNCTION_TYPE (INT, PUSHORT)
DEF_FUNCTION_TYPE (INT, PUNSIGNED)
DEF_FUNCTION_TYPE (INT, PULONGLONG)
diff --git a/gcc/config/i386/i386-c.c b/gcc/config/i386/i386-c.c
index 2e764e79987..1c053b1e51e 100644
--- a/gcc/config/i386/i386-c.c
+++ b/gcc/config/i386/i386-c.c
@@ -141,6 +141,10 @@ ix86_target_macros_internal (HOST_WIDE_INT isa_flag,
def_or_undef (parse_in, "__corei7");
def_or_undef (parse_in, "__corei7__");
break;
+ case PROCESSOR_COREI7_AVX:
+ def_or_undef (parse_in, "__corei7_avx");
+ def_or_undef (parse_in, "__corei7_avx__");
+ break;
case PROCESSOR_HASWELL:
def_or_undef (parse_in, "__core_avx2");
def_or_undef (parse_in, "__core_avx2__");
@@ -238,6 +242,9 @@ ix86_target_macros_internal (HOST_WIDE_INT isa_flag,
case PROCESSOR_COREI7:
def_or_undef (parse_in, "__tune_corei7__");
break;
+ case PROCESSOR_COREI7_AVX:
+ def_or_undef (parse_in, "__tune_corei7_avx__");
+ break;
case PROCESSOR_HASWELL:
def_or_undef (parse_in, "__tune_core_avx2__");
break;
@@ -358,6 +365,8 @@ ix86_target_macros_internal (HOST_WIDE_INT isa_flag,
def_or_undef (parse_in, "__SSE_MATH__");
if ((fpmath & FPMATH_SSE) && (isa_flag & OPTION_MASK_ISA_SSE2))
def_or_undef (parse_in, "__SSE2_MATH__");
+ if (isa_flag & OPTION_MASK_ISA_MPX)
+ def_or_undef (parse_in, "__MPX__");
}
@@ -368,7 +377,7 @@ ix86_target_macros_internal (HOST_WIDE_INT isa_flag,
static bool
ix86_pragma_target_parse (tree args, tree pop_target)
{
- tree prev_tree = build_target_option_node ();
+ tree prev_tree = build_target_option_node (&global_options);
tree cur_tree;
struct cl_target_option *prev_opt;
struct cl_target_option *cur_opt;
@@ -388,7 +397,8 @@ ix86_pragma_target_parse (tree args, tree pop_target)
}
else
{
- cur_tree = ix86_valid_target_attribute_tree (args);
+ cur_tree = ix86_valid_target_attribute_tree (args, &global_options,
+ &global_options_set);
if (!cur_tree || cur_tree == error_mark_node)
{
cl_target_option_restore (&global_options,
@@ -464,6 +474,9 @@ ix86_target_macros (void)
builtin_define_std ("i386");
}
+ if (!TARGET_80387)
+ cpp_define (parse_in, "_SOFT_FLOAT");
+
if (TARGET_LONG_DOUBLE_64)
cpp_define (parse_in, "__LONG_DOUBLE_64__");
diff --git a/gcc/config/i386/i386-modes.def b/gcc/config/i386/i386-modes.def
index e0b8fc826ab..a73730e08e2 100644
--- a/gcc/config/i386/i386-modes.def
+++ b/gcc/config/i386/i386-modes.def
@@ -87,6 +87,9 @@ VECTOR_MODE (INT, DI, 1); /* V1DI */
VECTOR_MODE (INT, SI, 1); /* V1SI */
VECTOR_MODE (INT, QI, 2); /* V2QI */
+POINTER_BOUNDS_MODE (BND32, 8);
+POINTER_BOUNDS_MODE (BND64, 16);
+
INT_MODE (OI, 32);
INT_MODE (XI, 64);
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index 3ab2f3a2ac8..fdf9d5804df 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -143,6 +143,7 @@ extern void ix86_split_lshr (rtx *, rtx, enum machine_mode);
extern rtx ix86_find_base_term (rtx);
extern bool ix86_check_movabs (rtx, int);
extern void ix86_split_idivmod (enum machine_mode, rtx[], bool);
+extern bool ix86_emit_cfi ();
extern rtx assign_386_stack_local (enum machine_mode, enum ix86_stack_slot);
extern int ix86_attr_length_immediate_default (rtx, bool);
@@ -220,7 +221,9 @@ extern int ix86_constant_alignment (tree, 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);
+extern tree ix86_valid_target_attribute_tree (tree,
+ struct gcc_options *,
+ struct gcc_options *);
extern unsigned int ix86_get_callcvt (const_tree);
#endif
@@ -238,6 +241,9 @@ 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_bnd_prefixed_insn_p (rtx);
/* In i386-c.c */
extern void ix86_target_macros (void);
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 46c37d800d2..8b8cdfae681 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -61,7 +61,6 @@ along with GCC; see the file COPYING3. If not see
#include "diagnostic.h"
#include "dumpfile.h"
#include "tree-pass.h"
-#include "tree-flow.h"
#include "context.h"
#include "pass_manager.h"
@@ -1834,8 +1833,9 @@ const struct processor_costs *ix86_cost = &pentium_cost;
#define m_P4_NOCONA (m_PENT4 | m_NOCONA)
#define m_CORE2 (1<<PROCESSOR_CORE2)
#define m_COREI7 (1<<PROCESSOR_COREI7)
+#define m_COREI7_AVX (1<<PROCESSOR_COREI7_AVX)
#define m_HASWELL (1<<PROCESSOR_HASWELL)
-#define m_CORE_ALL (m_CORE2 | m_COREI7 | m_HASWELL)
+#define m_CORE_ALL (m_CORE2 | m_COREI7 | m_COREI7_AVX | m_HASWELL)
#define m_ATOM (1<<PROCESSOR_ATOM)
#define m_SLM (1<<PROCESSOR_SLM)
@@ -1898,18 +1898,6 @@ static unsigned int initial_ix86_arch_features[X86_ARCH_LAST] = {
~m_386,
};
-static const unsigned int x86_accumulate_outgoing_args
- = m_PPRO | m_P4_NOCONA | m_ATOM | m_SLM | m_CORE_ALL | m_AMD_MULTIPLE | m_GENERIC;
-
-static const unsigned int x86_arch_always_fancy_math_387
- = m_PENT | m_PPRO | m_P4_NOCONA | m_CORE_ALL | m_ATOM | m_SLM | m_AMD_MULTIPLE | m_GENERIC;
-
-static const unsigned int x86_avx256_split_unaligned_load
- = m_COREI7 | m_GENERIC;
-
-static const unsigned int x86_avx256_split_unaligned_store
- = m_COREI7 | m_BDVER | m_GENERIC;
-
/* In case the average insn count for single function invocation is
lower than this constant, emit fast (but longer) prologue and
epilogue code. */
@@ -1956,6 +1944,8 @@ enum reg_class const regclass_map[FIRST_PSEUDO_REGISTER] =
/* Mask registers. */
MASK_REGS, MASK_EVEX_REGS, MASK_EVEX_REGS, MASK_EVEX_REGS,
MASK_EVEX_REGS, MASK_EVEX_REGS, MASK_EVEX_REGS, MASK_EVEX_REGS,
+ /* MPX bound registers */
+ BND_REGS, BND_REGS, BND_REGS, BND_REGS,
};
/* The "default" register map used in 32bit mode. */
@@ -1972,6 +1962,7 @@ int const dbx_register_map[FIRST_PSEUDO_REGISTER] =
-1, -1, -1, -1, -1, -1, -1, -1, /* AVX-512 registers 16-23*/
-1, -1, -1, -1, -1, -1, -1, -1, /* AVX-512 registers 24-31*/
93, 94, 95, 96, 97, 98, 99, 100, /* Mask registers */
+ 101, 102, 103, 104, /* bound registers */
};
/* The "default" register map used in 64bit mode. */
@@ -1988,6 +1979,7 @@ int const dbx64_register_map[FIRST_PSEUDO_REGISTER] =
67, 68, 69, 70, 71, 72, 73, 74, /* AVX-512 registers 16-23 */
75, 76, 77, 78, 79, 80, 81, 82, /* AVX-512 registers 24-31 */
118, 119, 120, 121, 122, 123, 124, 125, /* Mask registers */
+ 126, 127, 128, 129, /* bound registers */
};
/* Define the register numbers to be used in Dwarf debugging information.
@@ -2056,6 +2048,7 @@ int const svr4_dbx_register_map[FIRST_PSEUDO_REGISTER] =
-1, -1, -1, -1, -1, -1, -1, -1, /* AVX-512 registers 16-23*/
-1, -1, -1, -1, -1, -1, -1, -1, /* AVX-512 registers 24-31*/
93, 94, 95, 96, 97, 98, 99, 100, /* Mask registers */
+ -1, -1, -1, -1, /* bound registers */
};
/* Define parameter passing and return registers. */
@@ -2248,12 +2241,16 @@ enum ix86_function_specific_strings
static char *ix86_target_string (HOST_WIDE_INT, int, const char *,
const char *, enum fpmath_unit, bool);
-static void ix86_function_specific_save (struct cl_target_option *);
-static void ix86_function_specific_restore (struct cl_target_option *);
+static void ix86_function_specific_save (struct cl_target_option *,
+ struct gcc_options *opts);
+static void ix86_function_specific_restore (struct gcc_options *opts,
+ struct cl_target_option *);
static void ix86_function_specific_print (FILE *, int,
struct cl_target_option *);
static bool ix86_valid_target_attribute_p (tree, tree, tree, int);
static bool ix86_valid_target_attribute_inner_p (tree, char *[],
+ struct gcc_options *,
+ struct gcc_options *,
struct gcc_options *);
static bool ix86_can_inline_p (tree, tree);
static void ix86_set_current_function (tree);
@@ -2303,6 +2300,8 @@ static const struct ptt processor_target_table[PROCESSOR_max] =
{&core_cost, 16, 10, 16, 10, 16},
/* Core i7 */
{&core_cost, 16, 10, 16, 10, 16},
+ /* Core i7 avx */
+ {&core_cost, 16, 10, 16, 10, 16},
/* Core avx2 */
{&core_cost, 16, 10, 16, 10, 16},
{&generic_cost, 16, 10, 16, 10, 16},
@@ -2332,6 +2331,7 @@ static const char *const cpu_names[TARGET_CPU_DEFAULT_max] =
"nocona",
"core2",
"corei7",
+ "corei7-avx",
"core-avx2",
"atom",
"slm",
@@ -2478,6 +2478,7 @@ ix86_target_string (HOST_WIDE_INT isa, int flags, const char *arch,
{ "-mrtm", OPTION_MASK_ISA_RTM },
{ "-mxsave", OPTION_MASK_ISA_XSAVE },
{ "-mxsaveopt", OPTION_MASK_ISA_XSAVEOPT },
+ { "-mmpx", OPTION_MASK_ISA_MPX },
};
/* Flag options. */
@@ -2917,11 +2918,13 @@ set_ix86_tune_features (enum processor_type ix86_tune, bool dump)
attributes. */
static void
-ix86_option_override_internal (bool main_args_p)
+ix86_option_override_internal (bool main_args_p,
+ struct gcc_options *opts,
+ struct gcc_options *opts_set)
{
int i;
- unsigned int ix86_arch_mask, ix86_tune_mask;
- const bool ix86_tune_specified = (ix86_tune_string != NULL);
+ unsigned int ix86_arch_mask;
+ const bool ix86_tune_specified = (opts->x_ix86_tune_string != NULL);
const char *prefix;
const char *suffix;
const char *sw;
@@ -2970,6 +2973,7 @@ ix86_option_override_internal (bool main_args_p)
#define PTA_AVX512ER (HOST_WIDE_INT_1 << 41)
#define PTA_AVX512PF (HOST_WIDE_INT_1 << 42)
#define PTA_AVX512CD (HOST_WIDE_INT_1 << 43)
+#define PTA_MPX (HOST_WIDE_INT_1 << 44)
/* if this reaches 64, need to widen struct pta flags below */
@@ -3016,12 +3020,12 @@ ix86_option_override_internal (bool main_args_p)
{"corei7", PROCESSOR_COREI7, CPU_COREI7,
PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3 | PTA_SSSE3
| PTA_SSE4_1 | PTA_SSE4_2 | PTA_CX16 | PTA_POPCNT | PTA_FXSR},
- {"corei7-avx", PROCESSOR_COREI7, CPU_COREI7,
+ {"corei7-avx", PROCESSOR_COREI7_AVX, CPU_COREI7,
PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3
| PTA_SSSE3 | PTA_SSE4_1 | PTA_SSE4_2 | PTA_AVX
| PTA_CX16 | PTA_POPCNT | PTA_AES | PTA_PCLMUL
| PTA_FXSR | PTA_XSAVE | PTA_XSAVEOPT},
- {"core-avx-i", PROCESSOR_COREI7, CPU_COREI7,
+ {"core-avx-i", PROCESSOR_COREI7_AVX, CPU_COREI7,
PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3
| PTA_SSSE3 | PTA_SSE4_1 | PTA_SSE4_2 | PTA_AVX
| PTA_CX16 | PTA_POPCNT | PTA_AES | PTA_PCLMUL | PTA_FSGSBASE
@@ -3098,7 +3102,7 @@ ix86_option_override_internal (bool main_args_p)
{"bdver3", PROCESSOR_BDVER3, CPU_BDVER3,
PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3
| PTA_SSE4A | PTA_CX16 | PTA_ABM | PTA_SSSE3 | PTA_SSE4_1
- | PTA_SSE4_2 | PTA_AES | PTA_PCLMUL | PTA_AVX
+ | PTA_SSE4_2 | PTA_AES | PTA_PCLMUL | PTA_AVX | PTA_FMA4
| PTA_XOP | PTA_LWP | PTA_BMI | PTA_TBM | PTA_F16C
| PTA_FMA | PTA_PRFCHW | PTA_FXSR | PTA_XSAVE
| PTA_XSAVEOPT | PTA_FSGSBASE},
@@ -3153,8 +3157,8 @@ ix86_option_override_internal (bool main_args_p)
/* Turn off both OPTION_MASK_ABI_64 and OPTION_MASK_ABI_X32 if
TARGET_64BIT_DEFAULT is true and TARGET_64BIT is false. */
- if (TARGET_64BIT_DEFAULT && !TARGET_64BIT)
- ix86_isa_flags &= ~(OPTION_MASK_ABI_64 | OPTION_MASK_ABI_X32);
+ if (TARGET_64BIT_DEFAULT && !TARGET_64BIT_P (opts->x_ix86_isa_flags))
+ opts->x_ix86_isa_flags &= ~(OPTION_MASK_ABI_64 | OPTION_MASK_ABI_X32);
#ifdef TARGET_BI_ARCH
else
{
@@ -3163,32 +3167,32 @@ ix86_option_override_internal (bool main_args_p)
is on and OPTION_MASK_ABI_X32 is off. We turn off
OPTION_MASK_ABI_64 if OPTION_MASK_ABI_X32 is turned on by
-mx32. */
- if (TARGET_X32)
- ix86_isa_flags &= ~OPTION_MASK_ABI_64;
+ if (TARGET_X32_P (opts->x_ix86_isa_flags))
+ opts->x_ix86_isa_flags &= ~OPTION_MASK_ABI_64;
#else
/* When TARGET_BI_ARCH == 2, by default, OPTION_MASK_ABI_X32 is
on and OPTION_MASK_ABI_64 is off. We turn off
OPTION_MASK_ABI_X32 if OPTION_MASK_ABI_64 is turned on by
-m64. */
- if (TARGET_LP64)
- ix86_isa_flags &= ~OPTION_MASK_ABI_X32;
+ if (TARGET_LP64_P (opts->x_ix86_isa_flags))
+ opts->x_ix86_isa_flags &= ~OPTION_MASK_ABI_X32;
#endif
}
#endif
- if (TARGET_X32)
+ if (TARGET_X32_P (opts->x_ix86_isa_flags))
{
/* Always turn on OPTION_MASK_ISA_64BIT and turn off
OPTION_MASK_ABI_64 for TARGET_X32. */
- ix86_isa_flags |= OPTION_MASK_ISA_64BIT;
- ix86_isa_flags &= ~OPTION_MASK_ABI_64;
+ opts->x_ix86_isa_flags |= OPTION_MASK_ISA_64BIT;
+ opts->x_ix86_isa_flags &= ~OPTION_MASK_ABI_64;
}
- else if (TARGET_LP64)
+ else if (TARGET_LP64_P (opts->x_ix86_isa_flags))
{
/* Always turn on OPTION_MASK_ISA_64BIT and turn off
OPTION_MASK_ABI_X32 for TARGET_LP64. */
- ix86_isa_flags |= OPTION_MASK_ISA_64BIT;
- ix86_isa_flags &= ~OPTION_MASK_ABI_X32;
+ opts->x_ix86_isa_flags |= OPTION_MASK_ISA_64BIT;
+ opts->x_ix86_isa_flags &= ~OPTION_MASK_ABI_X32;
}
#ifdef SUBTARGET_OVERRIDE_OPTIONS
@@ -3200,138 +3204,144 @@ ix86_option_override_internal (bool main_args_p)
#endif
/* -fPIC is the default for x86_64. */
- if (TARGET_MACHO && TARGET_64BIT)
- flag_pic = 2;
+ if (TARGET_MACHO && TARGET_64BIT_P (opts->x_ix86_isa_flags))
+ opts->x_flag_pic = 2;
/* Need to check -mtune=generic first. */
- if (ix86_tune_string)
+ if (opts->x_ix86_tune_string)
{
- if (!strcmp (ix86_tune_string, "generic")
- || !strcmp (ix86_tune_string, "i686")
+ if (!strcmp (opts->x_ix86_tune_string, "generic")
+ || !strcmp (opts->x_ix86_tune_string, "i686")
/* As special support for cross compilers we read -mtune=native
as -mtune=generic. With native compilers we won't see the
-mtune=native, as it was changed by the driver. */
- || !strcmp (ix86_tune_string, "native"))
+ || !strcmp (opts->x_ix86_tune_string, "native"))
{
- ix86_tune_string = "generic";
+ opts->x_ix86_tune_string = "generic";
}
/* If this call is for setting the option attribute, allow the
generic that was previously set. */
else if (!main_args_p
- && !strcmp (ix86_tune_string, "generic"))
+ && !strcmp (opts->x_ix86_tune_string, "generic"))
;
- else if (!strncmp (ix86_tune_string, "generic", 7))
+ else if (!strncmp (opts->x_ix86_tune_string, "generic", 7))
error ("bad value (%s) for %stune=%s %s",
- ix86_tune_string, prefix, suffix, sw);
- else if (!strcmp (ix86_tune_string, "x86-64"))
+ opts->x_ix86_tune_string, prefix, suffix, sw);
+ else if (!strcmp (opts->x_ix86_tune_string, "x86-64"))
warning (OPT_Wdeprecated, "%stune=x86-64%s is deprecated; use "
"%stune=k8%s or %stune=generic%s instead as appropriate",
prefix, suffix, prefix, suffix, prefix, suffix);
}
else
{
- if (ix86_arch_string)
- ix86_tune_string = ix86_arch_string;
- if (!ix86_tune_string)
+ if (opts->x_ix86_arch_string)
+ opts->x_ix86_tune_string = opts->x_ix86_arch_string;
+ if (!opts->x_ix86_tune_string)
{
- ix86_tune_string = cpu_names[TARGET_CPU_DEFAULT];
+ opts->x_ix86_tune_string = cpu_names[TARGET_CPU_DEFAULT];
ix86_tune_defaulted = 1;
}
- /* ix86_tune_string is set to ix86_arch_string or defaulted. We
- need to use a sensible tune option. */
- if (!strcmp (ix86_tune_string, "generic")
- || !strcmp (ix86_tune_string, "x86-64")
- || !strcmp (ix86_tune_string, "i686"))
+ /* opts->x_ix86_tune_string is set to opts->x_ix86_arch_string
+ or defaulted. We need to use a sensible tune option. */
+ if (!strcmp (opts->x_ix86_tune_string, "generic")
+ || !strcmp (opts->x_ix86_tune_string, "x86-64")
+ || !strcmp (opts->x_ix86_tune_string, "i686"))
{
- ix86_tune_string = "generic";
+ opts->x_ix86_tune_string = "generic";
}
}
- if (ix86_stringop_alg == rep_prefix_8_byte && !TARGET_64BIT)
+ if (opts->x_ix86_stringop_alg == rep_prefix_8_byte
+ && !TARGET_64BIT_P (opts->x_ix86_isa_flags))
{
/* rep; movq isn't available in 32-bit code. */
error ("-mstringop-strategy=rep_8byte not supported for 32-bit code");
- ix86_stringop_alg = no_stringop;
+ opts->x_ix86_stringop_alg = no_stringop;
}
- if (!ix86_arch_string)
- ix86_arch_string = TARGET_64BIT ? "x86-64" : SUBTARGET32_DEFAULT_CPU;
+ if (!opts->x_ix86_arch_string)
+ opts->x_ix86_arch_string
+ = TARGET_64BIT_P (opts->x_ix86_isa_flags)
+ ? "x86-64" : SUBTARGET32_DEFAULT_CPU;
else
ix86_arch_specified = 1;
- if (global_options_set.x_ix86_pmode)
+ if (opts_set->x_ix86_pmode)
{
- if ((TARGET_LP64 && ix86_pmode == PMODE_SI)
- || (!TARGET_64BIT && ix86_pmode == PMODE_DI))
+ if ((TARGET_LP64_P (opts->x_ix86_isa_flags)
+ && opts->x_ix86_pmode == PMODE_SI)
+ || (!TARGET_64BIT_P (opts->x_ix86_isa_flags)
+ && opts->x_ix86_pmode == PMODE_DI))
error ("address mode %qs not supported in the %s bit mode",
- TARGET_64BIT ? "short" : "long",
- TARGET_64BIT ? "64" : "32");
+ TARGET_64BIT_P (opts->x_ix86_isa_flags) ? "short" : "long",
+ TARGET_64BIT_P (opts->x_ix86_isa_flags) ? "64" : "32");
}
else
- ix86_pmode = TARGET_LP64 ? PMODE_DI : PMODE_SI;
+ opts->x_ix86_pmode = TARGET_LP64_P (opts->x_ix86_isa_flags)
+ ? PMODE_DI : PMODE_SI;
- if (!global_options_set.x_ix86_abi)
- ix86_abi = DEFAULT_ABI;
+ if (!opts_set->x_ix86_abi)
+ opts->x_ix86_abi = DEFAULT_ABI;
/* For targets using ms ABI enable ms-extensions, if not
explicit turned off. For non-ms ABI we turn off this
option. */
- if (!global_options_set.x_flag_ms_extensions)
- flag_ms_extensions = (MS_ABI == DEFAULT_ABI);
+ if (!opts_set->x_flag_ms_extensions)
+ opts->x_flag_ms_extensions = (MS_ABI == DEFAULT_ABI);
- if (global_options_set.x_ix86_cmodel)
+ if (opts_set->x_ix86_cmodel)
{
- switch (ix86_cmodel)
+ switch (opts->x_ix86_cmodel)
{
case CM_SMALL:
case CM_SMALL_PIC:
- if (flag_pic)
- ix86_cmodel = CM_SMALL_PIC;
- if (!TARGET_64BIT)
+ if (opts->x_flag_pic)
+ opts->x_ix86_cmodel = CM_SMALL_PIC;
+ if (!TARGET_64BIT_P (opts->x_ix86_isa_flags))
error ("code model %qs not supported in the %s bit mode",
"small", "32");
break;
case CM_MEDIUM:
case CM_MEDIUM_PIC:
- if (flag_pic)
- ix86_cmodel = CM_MEDIUM_PIC;
- if (!TARGET_64BIT)
+ if (opts->x_flag_pic)
+ opts->x_ix86_cmodel = CM_MEDIUM_PIC;
+ if (!TARGET_64BIT_P (opts->x_ix86_isa_flags))
error ("code model %qs not supported in the %s bit mode",
"medium", "32");
- else if (TARGET_X32)
+ else if (TARGET_X32_P (opts->x_ix86_isa_flags))
error ("code model %qs not supported in x32 mode",
"medium");
break;
case CM_LARGE:
case CM_LARGE_PIC:
- if (flag_pic)
- ix86_cmodel = CM_LARGE_PIC;
- if (!TARGET_64BIT)
+ if (opts->x_flag_pic)
+ opts->x_ix86_cmodel = CM_LARGE_PIC;
+ if (!TARGET_64BIT_P (opts->x_ix86_isa_flags))
error ("code model %qs not supported in the %s bit mode",
"large", "32");
- else if (TARGET_X32)
+ else if (TARGET_X32_P (opts->x_ix86_isa_flags))
error ("code model %qs not supported in x32 mode",
"large");
break;
case CM_32:
- if (flag_pic)
+ if (opts->x_flag_pic)
error ("code model %s does not support PIC mode", "32");
- if (TARGET_64BIT)
+ if (TARGET_64BIT_P (opts->x_ix86_isa_flags))
error ("code model %qs not supported in the %s bit mode",
"32", "64");
break;
case CM_KERNEL:
- if (flag_pic)
+ if (opts->x_flag_pic)
{
error ("code model %s does not support PIC mode", "kernel");
- ix86_cmodel = CM_32;
+ opts->x_ix86_cmodel = CM_32;
}
- if (!TARGET_64BIT)
+ if (!TARGET_64BIT_P (opts->x_ix86_isa_flags))
error ("code model %qs not supported in the %s bit mode",
"kernel", "32");
break;
@@ -3346,191 +3356,195 @@ ix86_option_override_internal (bool main_args_p)
use of rip-relative addressing. This eliminates fixups that
would otherwise be needed if this object is to be placed in a
DLL, and is essentially just as efficient as direct addressing. */
- if (TARGET_64BIT && (TARGET_RDOS || TARGET_PECOFF))
- ix86_cmodel = CM_MEDIUM_PIC, flag_pic = 1;
- else if (TARGET_64BIT)
- ix86_cmodel = flag_pic ? CM_SMALL_PIC : CM_SMALL;
+ if (TARGET_64BIT_P (opts->x_ix86_isa_flags)
+ && (TARGET_RDOS || TARGET_PECOFF))
+ opts->x_ix86_cmodel = CM_MEDIUM_PIC, opts->x_flag_pic = 1;
+ else if (TARGET_64BIT_P (opts->x_ix86_isa_flags))
+ opts->x_ix86_cmodel = opts->x_flag_pic ? CM_SMALL_PIC : CM_SMALL;
else
- ix86_cmodel = CM_32;
+ opts->x_ix86_cmodel = CM_32;
}
- if (TARGET_MACHO && ix86_asm_dialect == ASM_INTEL)
+ if (TARGET_MACHO && opts->x_ix86_asm_dialect == ASM_INTEL)
{
error ("-masm=intel not supported in this configuration");
- ix86_asm_dialect = ASM_ATT;
+ opts->x_ix86_asm_dialect = ASM_ATT;
}
- if ((TARGET_64BIT != 0) != ((ix86_isa_flags & OPTION_MASK_ISA_64BIT) != 0))
+ if ((TARGET_64BIT_P (opts->x_ix86_isa_flags) != 0)
+ != ((opts->x_ix86_isa_flags & OPTION_MASK_ISA_64BIT) != 0))
sorry ("%i-bit mode not compiled in",
- (ix86_isa_flags & OPTION_MASK_ISA_64BIT) ? 64 : 32);
+ (opts->x_ix86_isa_flags & OPTION_MASK_ISA_64BIT) ? 64 : 32);
for (i = 0; i < pta_size; i++)
- if (! strcmp (ix86_arch_string, processor_alias_table[i].name))
+ if (! strcmp (opts->x_ix86_arch_string, processor_alias_table[i].name))
{
ix86_schedule = processor_alias_table[i].schedule;
ix86_arch = processor_alias_table[i].processor;
/* Default cpu tuning to the architecture. */
ix86_tune = ix86_arch;
- if (TARGET_64BIT && !(processor_alias_table[i].flags & PTA_64BIT))
+ if (TARGET_64BIT_P (opts->x_ix86_isa_flags)
+ && !(processor_alias_table[i].flags & PTA_64BIT))
error ("CPU you selected does not support x86-64 "
"instruction set");
if (processor_alias_table[i].flags & PTA_MMX
- && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_MMX))
- ix86_isa_flags |= OPTION_MASK_ISA_MMX;
+ && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_MMX))
+ opts->x_ix86_isa_flags |= OPTION_MASK_ISA_MMX;
if (processor_alias_table[i].flags & PTA_3DNOW
- && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_3DNOW))
- ix86_isa_flags |= OPTION_MASK_ISA_3DNOW;
+ && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_3DNOW))
+ opts->x_ix86_isa_flags |= OPTION_MASK_ISA_3DNOW;
if (processor_alias_table[i].flags & PTA_3DNOW_A
- && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_3DNOW_A))
- ix86_isa_flags |= OPTION_MASK_ISA_3DNOW_A;
+ && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_3DNOW_A))
+ opts->x_ix86_isa_flags |= OPTION_MASK_ISA_3DNOW_A;
if (processor_alias_table[i].flags & PTA_SSE
- && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_SSE))
- ix86_isa_flags |= OPTION_MASK_ISA_SSE;
+ && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_SSE))
+ opts->x_ix86_isa_flags |= OPTION_MASK_ISA_SSE;
if (processor_alias_table[i].flags & PTA_SSE2
- && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_SSE2))
- ix86_isa_flags |= OPTION_MASK_ISA_SSE2;
+ && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_SSE2))
+ opts->x_ix86_isa_flags |= OPTION_MASK_ISA_SSE2;
if (processor_alias_table[i].flags & PTA_SSE3
- && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_SSE3))
- ix86_isa_flags |= OPTION_MASK_ISA_SSE3;
+ && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_SSE3))
+ opts->x_ix86_isa_flags |= OPTION_MASK_ISA_SSE3;
if (processor_alias_table[i].flags & PTA_SSSE3
- && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_SSSE3))
- ix86_isa_flags |= OPTION_MASK_ISA_SSSE3;
+ && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_SSSE3))
+ opts->x_ix86_isa_flags |= OPTION_MASK_ISA_SSSE3;
if (processor_alias_table[i].flags & PTA_SSE4_1
- && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_SSE4_1))
- ix86_isa_flags |= OPTION_MASK_ISA_SSE4_1;
+ && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_SSE4_1))
+ opts->x_ix86_isa_flags |= OPTION_MASK_ISA_SSE4_1;
if (processor_alias_table[i].flags & PTA_SSE4_2
- && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_SSE4_2))
- ix86_isa_flags |= OPTION_MASK_ISA_SSE4_2;
+ && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_SSE4_2))
+ opts->x_ix86_isa_flags |= OPTION_MASK_ISA_SSE4_2;
if (processor_alias_table[i].flags & PTA_AVX
- && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_AVX))
- ix86_isa_flags |= OPTION_MASK_ISA_AVX;
+ && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_AVX))
+ opts->x_ix86_isa_flags |= OPTION_MASK_ISA_AVX;
if (processor_alias_table[i].flags & PTA_AVX2
- && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_AVX2))
- ix86_isa_flags |= OPTION_MASK_ISA_AVX2;
+ && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_AVX2))
+ opts->x_ix86_isa_flags |= OPTION_MASK_ISA_AVX2;
if (processor_alias_table[i].flags & PTA_FMA
- && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_FMA))
- ix86_isa_flags |= OPTION_MASK_ISA_FMA;
+ && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_FMA))
+ opts->x_ix86_isa_flags |= OPTION_MASK_ISA_FMA;
if (processor_alias_table[i].flags & PTA_SSE4A
- && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_SSE4A))
- ix86_isa_flags |= OPTION_MASK_ISA_SSE4A;
+ && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_SSE4A))
+ opts->x_ix86_isa_flags |= OPTION_MASK_ISA_SSE4A;
if (processor_alias_table[i].flags & PTA_FMA4
- && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_FMA4))
- ix86_isa_flags |= OPTION_MASK_ISA_FMA4;
+ && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_FMA4))
+ opts->x_ix86_isa_flags |= OPTION_MASK_ISA_FMA4;
if (processor_alias_table[i].flags & PTA_XOP
- && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_XOP))
- ix86_isa_flags |= OPTION_MASK_ISA_XOP;
+ && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_XOP))
+ opts->x_ix86_isa_flags |= OPTION_MASK_ISA_XOP;
if (processor_alias_table[i].flags & PTA_LWP
- && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_LWP))
- ix86_isa_flags |= OPTION_MASK_ISA_LWP;
+ && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_LWP))
+ opts->x_ix86_isa_flags |= OPTION_MASK_ISA_LWP;
if (processor_alias_table[i].flags & PTA_ABM
- && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_ABM))
- ix86_isa_flags |= OPTION_MASK_ISA_ABM;
+ && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_ABM))
+ opts->x_ix86_isa_flags |= OPTION_MASK_ISA_ABM;
if (processor_alias_table[i].flags & PTA_BMI
- && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_BMI))
- ix86_isa_flags |= OPTION_MASK_ISA_BMI;
+ && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_BMI))
+ opts->x_ix86_isa_flags |= OPTION_MASK_ISA_BMI;
if (processor_alias_table[i].flags & (PTA_LZCNT | PTA_ABM)
- && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_LZCNT))
- ix86_isa_flags |= OPTION_MASK_ISA_LZCNT;
+ && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_LZCNT))
+ opts->x_ix86_isa_flags |= OPTION_MASK_ISA_LZCNT;
if (processor_alias_table[i].flags & PTA_TBM
- && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_TBM))
- ix86_isa_flags |= OPTION_MASK_ISA_TBM;
+ && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_TBM))
+ opts->x_ix86_isa_flags |= OPTION_MASK_ISA_TBM;
if (processor_alias_table[i].flags & PTA_BMI2
- && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_BMI2))
- ix86_isa_flags |= OPTION_MASK_ISA_BMI2;
+ && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_BMI2))
+ opts->x_ix86_isa_flags |= OPTION_MASK_ISA_BMI2;
if (processor_alias_table[i].flags & PTA_CX16
- && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_CX16))
- ix86_isa_flags |= OPTION_MASK_ISA_CX16;
+ && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_CX16))
+ opts->x_ix86_isa_flags |= OPTION_MASK_ISA_CX16;
if (processor_alias_table[i].flags & (PTA_POPCNT | PTA_ABM)
- && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_POPCNT))
- ix86_isa_flags |= OPTION_MASK_ISA_POPCNT;
- if (!(TARGET_64BIT && (processor_alias_table[i].flags & PTA_NO_SAHF))
- && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_SAHF))
- ix86_isa_flags |= OPTION_MASK_ISA_SAHF;
+ && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_POPCNT))
+ opts->x_ix86_isa_flags |= OPTION_MASK_ISA_POPCNT;
+ if (!(TARGET_64BIT_P (opts->x_ix86_isa_flags)
+ && (processor_alias_table[i].flags & PTA_NO_SAHF))
+ && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_SAHF))
+ opts->x_ix86_isa_flags |= OPTION_MASK_ISA_SAHF;
if (processor_alias_table[i].flags & PTA_MOVBE
- && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_MOVBE))
- ix86_isa_flags |= OPTION_MASK_ISA_MOVBE;
+ && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_MOVBE))
+ opts->x_ix86_isa_flags |= OPTION_MASK_ISA_MOVBE;
if (processor_alias_table[i].flags & PTA_AES
- && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_AES))
- ix86_isa_flags |= OPTION_MASK_ISA_AES;
+ && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_AES))
+ opts->x_ix86_isa_flags |= OPTION_MASK_ISA_AES;
if (processor_alias_table[i].flags & PTA_PCLMUL
- && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_PCLMUL))
- ix86_isa_flags |= OPTION_MASK_ISA_PCLMUL;
+ && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_PCLMUL))
+ opts->x_ix86_isa_flags |= OPTION_MASK_ISA_PCLMUL;
if (processor_alias_table[i].flags & PTA_FSGSBASE
- && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_FSGSBASE))
- ix86_isa_flags |= OPTION_MASK_ISA_FSGSBASE;
+ && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_FSGSBASE))
+ opts->x_ix86_isa_flags |= OPTION_MASK_ISA_FSGSBASE;
if (processor_alias_table[i].flags & PTA_RDRND
- && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_RDRND))
- ix86_isa_flags |= OPTION_MASK_ISA_RDRND;
+ && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_RDRND))
+ opts->x_ix86_isa_flags |= OPTION_MASK_ISA_RDRND;
if (processor_alias_table[i].flags & PTA_F16C
- && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_F16C))
- ix86_isa_flags |= OPTION_MASK_ISA_F16C;
+ && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_F16C))
+ opts->x_ix86_isa_flags |= OPTION_MASK_ISA_F16C;
if (processor_alias_table[i].flags & PTA_RTM
- && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_RTM))
- ix86_isa_flags |= OPTION_MASK_ISA_RTM;
+ && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_RTM))
+ opts->x_ix86_isa_flags |= OPTION_MASK_ISA_RTM;
if (processor_alias_table[i].flags & PTA_HLE
- && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_HLE))
- ix86_isa_flags |= OPTION_MASK_ISA_HLE;
+ && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_HLE))
+ opts->x_ix86_isa_flags |= OPTION_MASK_ISA_HLE;
if (processor_alias_table[i].flags & PTA_PRFCHW
- && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_PRFCHW))
- ix86_isa_flags |= OPTION_MASK_ISA_PRFCHW;
+ && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_PRFCHW))
+ opts->x_ix86_isa_flags |= OPTION_MASK_ISA_PRFCHW;
if (processor_alias_table[i].flags & PTA_RDSEED
- && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_RDSEED))
- ix86_isa_flags |= OPTION_MASK_ISA_RDSEED;
+ && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_RDSEED))
+ opts->x_ix86_isa_flags |= OPTION_MASK_ISA_RDSEED;
if (processor_alias_table[i].flags & PTA_ADX
- && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_ADX))
- ix86_isa_flags |= OPTION_MASK_ISA_ADX;
+ && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_ADX))
+ opts->x_ix86_isa_flags |= OPTION_MASK_ISA_ADX;
if (processor_alias_table[i].flags & PTA_FXSR
- && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_FXSR))
- ix86_isa_flags |= OPTION_MASK_ISA_FXSR;
+ && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_FXSR))
+ opts->x_ix86_isa_flags |= OPTION_MASK_ISA_FXSR;
if (processor_alias_table[i].flags & PTA_XSAVE
- && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_XSAVE))
- ix86_isa_flags |= OPTION_MASK_ISA_XSAVE;
+ && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_XSAVE))
+ opts->x_ix86_isa_flags |= OPTION_MASK_ISA_XSAVE;
if (processor_alias_table[i].flags & PTA_XSAVEOPT
- && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_XSAVEOPT))
- ix86_isa_flags |= OPTION_MASK_ISA_XSAVEOPT;
+ && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_XSAVEOPT))
+ opts->x_ix86_isa_flags |= OPTION_MASK_ISA_XSAVEOPT;
if (processor_alias_table[i].flags & PTA_AVX512F
- && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_AVX512F))
- ix86_isa_flags |= OPTION_MASK_ISA_AVX512F;
+ && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_AVX512F))
+ opts->x_ix86_isa_flags |= OPTION_MASK_ISA_AVX512F;
if (processor_alias_table[i].flags & PTA_AVX512ER
- && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_AVX512ER))
- ix86_isa_flags |= OPTION_MASK_ISA_AVX512ER;
+ && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_AVX512ER))
+ opts->x_ix86_isa_flags |= OPTION_MASK_ISA_AVX512ER;
if (processor_alias_table[i].flags & PTA_AVX512PF
- && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_AVX512PF))
- ix86_isa_flags |= OPTION_MASK_ISA_AVX512PF;
+ && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_AVX512PF))
+ opts->x_ix86_isa_flags |= OPTION_MASK_ISA_AVX512PF;
if (processor_alias_table[i].flags & PTA_AVX512CD
- && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_AVX512CD))
- ix86_isa_flags |= OPTION_MASK_ISA_AVX512CD;
+ && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_AVX512CD))
+ opts->x_ix86_isa_flags |= OPTION_MASK_ISA_AVX512CD;
if (processor_alias_table[i].flags & (PTA_PREFETCH_SSE | PTA_SSE))
x86_prefetch_sse = true;
break;
}
- if (!strcmp (ix86_arch_string, "generic"))
+ if (!strcmp (opts->x_ix86_arch_string, "generic"))
error ("generic CPU can be used only for %stune=%s %s",
prefix, suffix, sw);
- else if (!strncmp (ix86_arch_string, "generic", 7) || i == pta_size)
+ else if (!strncmp (opts->x_ix86_arch_string, "generic", 7) || i == pta_size)
error ("bad value (%s) for %sarch=%s %s",
- ix86_arch_string, prefix, suffix, sw);
+ opts->x_ix86_arch_string, prefix, suffix, sw);
ix86_arch_mask = 1u << ix86_arch;
for (i = 0; i < X86_ARCH_LAST; ++i)
ix86_arch_features[i] = !!(initial_ix86_arch_features[i] & ix86_arch_mask);
for (i = 0; i < pta_size; i++)
- if (! strcmp (ix86_tune_string, processor_alias_table[i].name))
+ if (! strcmp (opts->x_ix86_tune_string, processor_alias_table[i].name))
{
ix86_schedule = processor_alias_table[i].schedule;
ix86_tune = processor_alias_table[i].processor;
- if (TARGET_64BIT)
+ if (TARGET_64BIT_P (opts->x_ix86_isa_flags))
{
if (!(processor_alias_table[i].flags & PTA_64BIT))
{
if (ix86_tune_defaulted)
{
- ix86_tune_string = "x86-64";
+ opts->x_ix86_tune_string = "x86-64";
for (i = 0; i < pta_size; i++)
- if (! strcmp (ix86_tune_string,
+ if (! strcmp (opts->x_ix86_tune_string,
processor_alias_table[i].name))
break;
ix86_schedule = processor_alias_table[i].schedule;
@@ -3554,9 +3568,9 @@ ix86_option_override_internal (bool main_args_p)
if (ix86_tune_specified && i == pta_size)
error ("bad value (%s) for %stune=%s %s",
- ix86_tune_string, prefix, suffix, sw);
+ opts->x_ix86_tune_string, prefix, suffix, sw);
- set_ix86_tune_features (ix86_tune, ix86_dump_tunes);
+ set_ix86_tune_features (ix86_tune, opts->x_ix86_dump_tunes);
#ifndef USE_IX86_FRAME_POINTER
#define USE_IX86_FRAME_POINTER 0
@@ -3568,27 +3582,29 @@ ix86_option_override_internal (bool main_args_p)
/* Set the default values for switches whose default depends on TARGET_64BIT
in case they weren't overwritten by command line options. */
- if (TARGET_64BIT)
+ if (TARGET_64BIT_P (opts->x_ix86_isa_flags))
{
- if (optimize >= 1 && !global_options_set.x_flag_omit_frame_pointer)
- flag_omit_frame_pointer = !USE_X86_64_FRAME_POINTER;
- if (flag_asynchronous_unwind_tables == 2)
- flag_unwind_tables = flag_asynchronous_unwind_tables = 1;
- if (flag_pcc_struct_return == 2)
- flag_pcc_struct_return = 0;
+ if (opts->x_optimize >= 1 && !opts_set->x_flag_omit_frame_pointer)
+ opts->x_flag_omit_frame_pointer = !USE_X86_64_FRAME_POINTER;
+ if (opts->x_flag_asynchronous_unwind_tables == 2)
+ opts->x_flag_unwind_tables
+ = opts->x_flag_asynchronous_unwind_tables = 1;
+ if (opts->x_flag_pcc_struct_return == 2)
+ opts->x_flag_pcc_struct_return = 0;
}
else
{
- if (optimize >= 1 && !global_options_set.x_flag_omit_frame_pointer)
- flag_omit_frame_pointer = !(USE_IX86_FRAME_POINTER || optimize_size);
- if (flag_asynchronous_unwind_tables == 2)
- flag_asynchronous_unwind_tables = !USE_IX86_FRAME_POINTER;
- if (flag_pcc_struct_return == 2)
- flag_pcc_struct_return = DEFAULT_PCC_STRUCT_RETURN;
+ if (opts->x_optimize >= 1 && !opts_set->x_flag_omit_frame_pointer)
+ opts->x_flag_omit_frame_pointer
+ = !(USE_IX86_FRAME_POINTER || opts->x_optimize_size);
+ if (opts->x_flag_asynchronous_unwind_tables == 2)
+ opts->x_flag_asynchronous_unwind_tables = !USE_IX86_FRAME_POINTER;
+ if (opts->x_flag_pcc_struct_return == 2)
+ opts->x_flag_pcc_struct_return = DEFAULT_PCC_STRUCT_RETURN;
}
ix86_tune_cost = processor_target_table[ix86_tune].cost;
- if (optimize_size)
+ if (opts->x_optimize_size)
ix86_cost = &ix86_size_cost;
else
ix86_cost = ix86_tune_cost;
@@ -3597,148 +3613,160 @@ ix86_option_override_internal (bool main_args_p)
init_machine_status = ix86_init_machine_status;
/* Validate -mregparm= value. */
- if (global_options_set.x_ix86_regparm)
+ if (opts_set->x_ix86_regparm)
{
- if (TARGET_64BIT)
+ if (TARGET_64BIT_P (opts->x_ix86_isa_flags))
warning (0, "-mregparm is ignored in 64-bit mode");
- if (ix86_regparm > REGPARM_MAX)
+ if (opts->x_ix86_regparm > REGPARM_MAX)
{
error ("-mregparm=%d is not between 0 and %d",
- ix86_regparm, REGPARM_MAX);
- ix86_regparm = 0;
+ opts->x_ix86_regparm, REGPARM_MAX);
+ opts->x_ix86_regparm = 0;
}
}
- if (TARGET_64BIT)
- ix86_regparm = REGPARM_MAX;
+ if (TARGET_64BIT_P (opts->x_ix86_isa_flags))
+ opts->x_ix86_regparm = REGPARM_MAX;
/* Default align_* from the processor table. */
- if (align_loops == 0)
+ if (opts->x_align_loops == 0)
{
- align_loops = processor_target_table[ix86_tune].align_loop;
+ opts->x_align_loops = processor_target_table[ix86_tune].align_loop;
align_loops_max_skip = processor_target_table[ix86_tune].align_loop_max_skip;
}
- if (align_jumps == 0)
+ if (opts->x_align_jumps == 0)
{
- align_jumps = processor_target_table[ix86_tune].align_jump;
+ opts->x_align_jumps = processor_target_table[ix86_tune].align_jump;
align_jumps_max_skip = processor_target_table[ix86_tune].align_jump_max_skip;
}
- if (align_functions == 0)
+ if (opts->x_align_functions == 0)
{
- align_functions = processor_target_table[ix86_tune].align_func;
+ opts->x_align_functions = processor_target_table[ix86_tune].align_func;
}
/* Provide default for -mbranch-cost= value. */
- if (!global_options_set.x_ix86_branch_cost)
- ix86_branch_cost = ix86_cost->branch_cost;
+ if (!opts_set->x_ix86_branch_cost)
+ opts->x_ix86_branch_cost = ix86_cost->branch_cost;
- if (TARGET_64BIT)
+ if (TARGET_64BIT_P (opts->x_ix86_isa_flags))
{
- target_flags |= TARGET_SUBTARGET64_DEFAULT & ~target_flags_explicit;
+ opts->x_target_flags
+ |= TARGET_SUBTARGET64_DEFAULT & ~opts_set->x_target_flags;
/* Enable by default the SSE and MMX builtins. Do allow the user to
explicitly disable any of these. In particular, disabling SSE and
MMX for kernel code is extremely useful. */
if (!ix86_arch_specified)
- ix86_isa_flags
+ opts->x_ix86_isa_flags
|= ((OPTION_MASK_ISA_SSE2 | OPTION_MASK_ISA_SSE | OPTION_MASK_ISA_MMX
- | TARGET_SUBTARGET64_ISA_DEFAULT) & ~ix86_isa_flags_explicit);
+ | TARGET_SUBTARGET64_ISA_DEFAULT)
+ & ~opts->x_ix86_isa_flags_explicit);
- if (TARGET_RTD)
+ if (TARGET_RTD_P (opts->x_target_flags))
warning (0, "%srtd%s is ignored in 64bit mode", prefix, suffix);
}
else
{
- target_flags |= TARGET_SUBTARGET32_DEFAULT & ~target_flags_explicit;
+ opts->x_target_flags
+ |= TARGET_SUBTARGET32_DEFAULT & ~opts_set->x_target_flags;
if (!ix86_arch_specified)
- ix86_isa_flags
- |= TARGET_SUBTARGET32_ISA_DEFAULT & ~ix86_isa_flags_explicit;
+ opts->x_ix86_isa_flags
+ |= TARGET_SUBTARGET32_ISA_DEFAULT & ~opts->x_ix86_isa_flags_explicit;
/* i386 ABI does not specify red zone. It still makes sense to use it
when programmer takes care to stack from being destroyed. */
- if (!(target_flags_explicit & MASK_NO_RED_ZONE))
- target_flags |= MASK_NO_RED_ZONE;
+ if (!(opts_set->x_target_flags & MASK_NO_RED_ZONE))
+ opts->x_target_flags |= MASK_NO_RED_ZONE;
}
/* Keep nonleaf frame pointers. */
- if (flag_omit_frame_pointer)
- target_flags &= ~MASK_OMIT_LEAF_FRAME_POINTER;
- else if (TARGET_OMIT_LEAF_FRAME_POINTER)
- flag_omit_frame_pointer = 1;
+ if (opts->x_flag_omit_frame_pointer)
+ opts->x_target_flags &= ~MASK_OMIT_LEAF_FRAME_POINTER;
+ else if (TARGET_OMIT_LEAF_FRAME_POINTER_P (opts->x_target_flags))
+ opts->x_flag_omit_frame_pointer = 1;
/* If we're doing fast math, we don't care about comparison order
wrt NaNs. This lets us use a shorter comparison sequence. */
- if (flag_finite_math_only)
- target_flags &= ~MASK_IEEE_FP;
+ if (opts->x_flag_finite_math_only)
+ opts->x_target_flags &= ~MASK_IEEE_FP;
/* If the architecture always has an FPU, turn off NO_FANCY_MATH_387,
since the insns won't need emulation. */
- if (x86_arch_always_fancy_math_387 & ix86_arch_mask)
- target_flags &= ~MASK_NO_FANCY_MATH_387;
+ if (ix86_tune_features [X86_TUNE_ALWAYS_FANCY_MATH_387])
+ opts->x_target_flags &= ~MASK_NO_FANCY_MATH_387;
/* Likewise, if the target doesn't have a 387, or we've specified
software floating point, don't use 387 inline intrinsics. */
- if (!TARGET_80387)
- target_flags |= MASK_NO_FANCY_MATH_387;
+ if (!TARGET_80387_P (opts->x_target_flags))
+ opts->x_target_flags |= MASK_NO_FANCY_MATH_387;
/* Turn on MMX builtins for -msse. */
- if (TARGET_SSE)
- ix86_isa_flags |= OPTION_MASK_ISA_MMX & ~ix86_isa_flags_explicit;
+ if (TARGET_SSE_P (opts->x_ix86_isa_flags))
+ opts->x_ix86_isa_flags
+ |= OPTION_MASK_ISA_MMX & ~opts->x_ix86_isa_flags_explicit;
/* Enable SSE prefetch. */
- if (TARGET_SSE || (TARGET_PRFCHW && !TARGET_3DNOW))
+ if (TARGET_SSE_P (opts->x_ix86_isa_flags)
+ || (TARGET_PRFCHW && !TARGET_3DNOW_P (opts->x_ix86_isa_flags)))
x86_prefetch_sse = true;
/* Enable prefetch{,w} instructions for -m3dnow. */
- if (TARGET_3DNOW)
- ix86_isa_flags |= OPTION_MASK_ISA_PRFCHW & ~ix86_isa_flags_explicit;
+ if (TARGET_3DNOW_P (opts->x_ix86_isa_flags))
+ opts->x_ix86_isa_flags
+ |= OPTION_MASK_ISA_PRFCHW & ~opts->x_ix86_isa_flags_explicit;
/* Enable popcnt instruction for -msse4.2 or -mabm. */
- if (TARGET_SSE4_2 || TARGET_ABM)
- ix86_isa_flags |= OPTION_MASK_ISA_POPCNT & ~ix86_isa_flags_explicit;
+ if (TARGET_SSE4_2_P (opts->x_ix86_isa_flags)
+ || TARGET_ABM_P (opts->x_ix86_isa_flags))
+ opts->x_ix86_isa_flags
+ |= OPTION_MASK_ISA_POPCNT & ~opts->x_ix86_isa_flags_explicit;
/* Enable lzcnt instruction for -mabm. */
- if (TARGET_ABM)
- ix86_isa_flags |= OPTION_MASK_ISA_LZCNT & ~ix86_isa_flags_explicit;
+ if (TARGET_ABM_P(opts->x_ix86_isa_flags))
+ opts->x_ix86_isa_flags
+ |= OPTION_MASK_ISA_LZCNT & ~opts->x_ix86_isa_flags_explicit;
/* Validate -mpreferred-stack-boundary= value or default it to
PREFERRED_STACK_BOUNDARY_DEFAULT. */
ix86_preferred_stack_boundary = PREFERRED_STACK_BOUNDARY_DEFAULT;
- if (global_options_set.x_ix86_preferred_stack_boundary_arg)
+ if (opts_set->x_ix86_preferred_stack_boundary_arg)
{
- int min = (TARGET_64BIT ? (TARGET_SSE ? 4 : 3) : 2);
+ int min = (TARGET_64BIT_P (opts->x_ix86_isa_flags)
+ ? (TARGET_SSE_P (opts->x_ix86_isa_flags) ? 4 : 3) : 2);
int max = (TARGET_SEH ? 4 : 12);
- if (ix86_preferred_stack_boundary_arg < min
- || ix86_preferred_stack_boundary_arg > max)
+ if (opts->x_ix86_preferred_stack_boundary_arg < min
+ || opts->x_ix86_preferred_stack_boundary_arg > max)
{
if (min == max)
error ("-mpreferred-stack-boundary is not supported "
"for this target");
else
error ("-mpreferred-stack-boundary=%d is not between %d and %d",
- ix86_preferred_stack_boundary_arg, min, max);
+ opts->x_ix86_preferred_stack_boundary_arg, min, max);
}
else
ix86_preferred_stack_boundary
- = (1 << ix86_preferred_stack_boundary_arg) * BITS_PER_UNIT;
+ = (1 << opts->x_ix86_preferred_stack_boundary_arg) * BITS_PER_UNIT;
}
/* Set the default value for -mstackrealign. */
- if (ix86_force_align_arg_pointer == -1)
- ix86_force_align_arg_pointer = STACK_REALIGN_DEFAULT;
+ if (opts->x_ix86_force_align_arg_pointer == -1)
+ opts->x_ix86_force_align_arg_pointer = STACK_REALIGN_DEFAULT;
ix86_default_incoming_stack_boundary = PREFERRED_STACK_BOUNDARY;
/* Validate -mincoming-stack-boundary= value or default it to
MIN_STACK_BOUNDARY/PREFERRED_STACK_BOUNDARY. */
ix86_incoming_stack_boundary = ix86_default_incoming_stack_boundary;
- if (global_options_set.x_ix86_incoming_stack_boundary_arg)
+ if (opts_set->x_ix86_incoming_stack_boundary_arg)
{
- if (ix86_incoming_stack_boundary_arg < (TARGET_64BIT ? 4 : 2)
+ if (ix86_incoming_stack_boundary_arg
+ < (TARGET_64BIT_P (opts->x_ix86_isa_flags) ? 4 : 2)
|| ix86_incoming_stack_boundary_arg > 12)
error ("-mincoming-stack-boundary=%d is not between %d and 12",
- ix86_incoming_stack_boundary_arg, TARGET_64BIT ? 4 : 2);
+ ix86_incoming_stack_boundary_arg,
+ TARGET_64BIT_P (opts->x_ix86_isa_flags) ? 4 : 2);
else
{
ix86_user_incoming_stack_boundary
@@ -3749,36 +3777,50 @@ ix86_option_override_internal (bool main_args_p)
}
/* Accept -msseregparm only if at least SSE support is enabled. */
- if (TARGET_SSEREGPARM
- && ! TARGET_SSE)
+ if (TARGET_SSEREGPARM_P (opts->x_target_flags)
+ && ! TARGET_SSE_P (opts->x_ix86_isa_flags))
error ("%ssseregparm%s used without SSE enabled", prefix, suffix);
- if (global_options_set.x_ix86_fpmath)
+ if (opts_set->x_ix86_fpmath)
{
- if (ix86_fpmath & FPMATH_SSE)
+ if (opts->x_ix86_fpmath & FPMATH_SSE)
{
- if (!TARGET_SSE)
+ if (!TARGET_SSE_P (opts->x_ix86_isa_flags))
{
warning (0, "SSE instruction set disabled, using 387 arithmetics");
- ix86_fpmath = FPMATH_387;
+ opts->x_ix86_fpmath = FPMATH_387;
}
- else if ((ix86_fpmath & FPMATH_387) && !TARGET_80387)
+ else if ((opts->x_ix86_fpmath & FPMATH_387)
+ && !TARGET_80387_P (opts->x_target_flags))
{
warning (0, "387 instruction set disabled, using SSE arithmetics");
- ix86_fpmath = FPMATH_SSE;
+ opts->x_ix86_fpmath = FPMATH_SSE;
}
}
}
+ /* For all chips supporting SSE2, -mfpmath=sse performs better than
+ fpmath=387. The second is however default at many targets since the
+ extra 80bit precision of temporaries is considered to be part of ABI.
+ Overwrite the default at least for -ffast-math.
+ TODO: -mfpmath=both seems to produce same performing code with bit
+ smaller binaries. It is however not clear if register allocation is
+ ready for this setting.
+ Also -mfpmath=387 is overall a lot more compact (bout 4-5%) than SSE
+ codegen. We may switch to 387 with -ffast-math for size optimized
+ functions. */
+ else if (fast_math_flags_set_p (&global_options)
+ && TARGET_SSE2_P (opts->x_ix86_isa_flags))
+ ix86_fpmath = FPMATH_SSE;
else
- ix86_fpmath = TARGET_FPMATH_DEFAULT;
+ opts->x_ix86_fpmath = TARGET_FPMATH_DEFAULT_P (opts->x_ix86_isa_flags);
/* If the i387 is disabled, then do not return values in it. */
- if (!TARGET_80387)
- target_flags &= ~MASK_FLOAT_RETURNS;
+ if (!TARGET_80387_P (opts->x_target_flags))
+ opts->x_target_flags &= ~MASK_FLOAT_RETURNS;
/* Use external vectorized library in vectorizing intrinsics. */
- if (global_options_set.x_ix86_veclibabi_type)
- switch (ix86_veclibabi_type)
+ if (opts_set->x_ix86_veclibabi_type)
+ switch (opts->x_ix86_veclibabi_type)
{
case ix86_veclibabi_type_svml:
ix86_veclib_handler = ix86_veclibabi_svml;
@@ -3792,39 +3834,21 @@ ix86_option_override_internal (bool main_args_p)
gcc_unreachable ();
}
- ix86_tune_mask = 1u << ix86_tune;
- if ((!USE_IX86_FRAME_POINTER
- || (x86_accumulate_outgoing_args & ix86_tune_mask))
- && !(target_flags_explicit & MASK_ACCUMULATE_OUTGOING_ARGS)
- && !optimize_size)
- target_flags |= MASK_ACCUMULATE_OUTGOING_ARGS;
-
- /* ??? Unwind info is not correct around the CFG unless either a frame
- pointer is present or M_A_O_A is set. Fixing this requires rewriting
- unwind info generation to be aware of the CFG and propagating states
- around edges. */
- if ((flag_unwind_tables || flag_asynchronous_unwind_tables
- || flag_exceptions || flag_non_call_exceptions)
- && flag_omit_frame_pointer
- && !(target_flags & MASK_ACCUMULATE_OUTGOING_ARGS))
- {
- if (target_flags_explicit & MASK_ACCUMULATE_OUTGOING_ARGS)
- warning (0, "unwind tables currently require either a frame pointer "
- "or %saccumulate-outgoing-args%s for correctness",
- prefix, suffix);
- target_flags |= MASK_ACCUMULATE_OUTGOING_ARGS;
- }
+ if (ix86_tune_features [X86_TUNE_ACCUMULATE_OUTGOING_ARGS]
+ && !(opts_set->x_target_flags & MASK_ACCUMULATE_OUTGOING_ARGS)
+ && !opts->x_optimize_size)
+ opts->x_target_flags |= MASK_ACCUMULATE_OUTGOING_ARGS;
/* 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. */
- if (TARGET_STACK_PROBE
- && !(target_flags & MASK_ACCUMULATE_OUTGOING_ARGS))
+ if (TARGET_STACK_PROBE_P (opts->x_target_flags)
+ && !(opts->x_target_flags & MASK_ACCUMULATE_OUTGOING_ARGS))
{
- if (target_flags_explicit & MASK_ACCUMULATE_OUTGOING_ARGS)
+ if (opts_set->x_target_flags & MASK_ACCUMULATE_OUTGOING_ARGS)
warning (0, "stack probing requires %saccumulate-outgoing-args%s "
"for correctness", prefix, suffix);
- target_flags |= MASK_ACCUMULATE_OUTGOING_ARGS;
+ opts->x_target_flags |= MASK_ACCUMULATE_OUTGOING_ARGS;
}
/* Figure out what ASM_GENERATE_INTERNAL_LABEL builds as a prefix. */
@@ -3839,38 +3863,38 @@ ix86_option_override_internal (bool main_args_p)
/* When scheduling description is not available, disable scheduler pass
so it won't slow down the compilation and make x87 code slower. */
if (!TARGET_SCHEDULE)
- flag_schedule_insns_after_reload = flag_schedule_insns = 0;
+ opts->x_flag_schedule_insns_after_reload = opts->x_flag_schedule_insns = 0;
maybe_set_param_value (PARAM_SIMULTANEOUS_PREFETCHES,
ix86_tune_cost->simultaneous_prefetches,
- global_options.x_param_values,
- global_options_set.x_param_values);
+ opts->x_param_values,
+ opts_set->x_param_values);
maybe_set_param_value (PARAM_L1_CACHE_LINE_SIZE,
ix86_tune_cost->prefetch_block,
- global_options.x_param_values,
- global_options_set.x_param_values);
+ opts->x_param_values,
+ opts_set->x_param_values);
maybe_set_param_value (PARAM_L1_CACHE_SIZE,
ix86_tune_cost->l1_cache_size,
- global_options.x_param_values,
- global_options_set.x_param_values);
+ opts->x_param_values,
+ opts_set->x_param_values);
maybe_set_param_value (PARAM_L2_CACHE_SIZE,
ix86_tune_cost->l2_cache_size,
- global_options.x_param_values,
- global_options_set.x_param_values);
+ opts->x_param_values,
+ opts_set->x_param_values);
/* Enable sw prefetching at -O3 for CPUS that prefetching is helpful. */
- if (flag_prefetch_loop_arrays < 0
+ if (opts->x_flag_prefetch_loop_arrays < 0
&& HAVE_prefetch
- && (optimize >= 3 || flag_profile_use)
+ && (opts->x_optimize >= 3 || opts->x_flag_profile_use)
&& TARGET_SOFTWARE_PREFETCHING_BENEFICIAL)
- flag_prefetch_loop_arrays = 1;
+ opts->x_flag_prefetch_loop_arrays = 1;
/* If using typedef char *va_list, signal that __builtin_va_start (&ap, 0)
- can be optimized to ap = __builtin_next_arg (0). */
- if (!TARGET_64BIT && !flag_split_stack)
+ can be opts->x_optimized to ap = __builtin_next_arg (0). */
+ if (!TARGET_64BIT_P (opts->x_ix86_isa_flags) && !opts->x_flag_split_stack)
targetm.expand_builtin_va_start = NULL;
- if (TARGET_64BIT)
+ if (TARGET_64BIT_P (opts->x_ix86_isa_flags))
{
ix86_gen_leave = gen_leave_rex64;
if (Pmode == DImode)
@@ -3916,56 +3940,56 @@ ix86_option_override_internal (bool main_args_p)
#ifdef USE_IX86_CLD
/* Use -mcld by default for 32-bit code if configured with --enable-cld. */
- if (!TARGET_64BIT)
- target_flags |= MASK_CLD & ~target_flags_explicit;
+ if (!TARGET_64BIT_P (opts->x_ix86_isa_flags))
+ opts->x_target_flags |= MASK_CLD & ~opts_set->x_target_flags;
#endif
- if (!TARGET_64BIT && flag_pic)
+ if (!TARGET_64BIT_P (opts->x_ix86_isa_flags) && opts->x_flag_pic)
{
- if (flag_fentry > 0)
+ if (opts->x_flag_fentry > 0)
sorry ("-mfentry isn%'t supported for 32-bit in combination "
"with -fpic");
- flag_fentry = 0;
+ opts->x_flag_fentry = 0;
}
else if (TARGET_SEH)
{
- if (flag_fentry == 0)
+ if (opts->x_flag_fentry == 0)
sorry ("-mno-fentry isn%'t compatible with SEH");
- flag_fentry = 1;
+ opts->x_flag_fentry = 1;
}
- else if (flag_fentry < 0)
+ else if (opts->x_flag_fentry < 0)
{
#if defined(PROFILE_BEFORE_PROLOGUE)
- flag_fentry = 1;
+ opts->x_flag_fentry = 1;
#else
- flag_fentry = 0;
+ opts->x_flag_fentry = 0;
#endif
}
- /* When not optimize for size, enable vzeroupper optimization for
+ /* When not opts->x_optimize for size, enable vzeroupper optimization for
TARGET_AVX with -fexpensive-optimizations and split 32-byte
AVX unaligned load/store. */
- if (!optimize_size)
+ if (!opts->x_optimize_size)
{
if (flag_expensive_optimizations
- && !(target_flags_explicit & MASK_VZEROUPPER))
- target_flags |= MASK_VZEROUPPER;
- if ((x86_avx256_split_unaligned_load & ix86_tune_mask)
- && !(target_flags_explicit & MASK_AVX256_SPLIT_UNALIGNED_LOAD))
- target_flags |= MASK_AVX256_SPLIT_UNALIGNED_LOAD;
- if ((x86_avx256_split_unaligned_store & ix86_tune_mask)
- && !(target_flags_explicit & MASK_AVX256_SPLIT_UNALIGNED_STORE))
- target_flags |= MASK_AVX256_SPLIT_UNALIGNED_STORE;
+ && !(opts_set->x_target_flags & MASK_VZEROUPPER))
+ opts->x_target_flags |= MASK_VZEROUPPER;
+ if (!ix86_tune_features[X86_TUNE_SSE_UNALIGNED_LOAD_OPTIMAL]
+ && !(opts_set->x_target_flags & MASK_AVX256_SPLIT_UNALIGNED_LOAD))
+ opts->x_target_flags |= MASK_AVX256_SPLIT_UNALIGNED_LOAD;
+ if (!ix86_tune_features[X86_TUNE_SSE_UNALIGNED_STORE_OPTIMAL]
+ && !(opts_set->x_target_flags & MASK_AVX256_SPLIT_UNALIGNED_STORE))
+ opts->x_target_flags |= MASK_AVX256_SPLIT_UNALIGNED_STORE;
/* Enable 128-bit AVX instruction generation
for the auto-vectorizer. */
if (TARGET_AVX128_OPTIMAL
- && !(target_flags_explicit & MASK_PREFER_AVX128))
- target_flags |= MASK_PREFER_AVX128;
+ && !(opts_set->x_target_flags & MASK_PREFER_AVX128))
+ opts->x_target_flags |= MASK_PREFER_AVX128;
}
- if (ix86_recip_name)
+ if (opts->x_ix86_recip_name)
{
- char *p = ASTRDUP (ix86_recip_name);
+ char *p = ASTRDUP (opts->x_ix86_recip_name);
char *q;
unsigned int mask, i;
bool invert;
@@ -4000,45 +4024,46 @@ ix86_option_override_internal (bool main_args_p)
}
}
- recip_mask_explicit |= mask;
+ opts->x_recip_mask_explicit |= mask;
if (invert)
- recip_mask &= ~mask;
+ opts->x_recip_mask &= ~mask;
else
- recip_mask |= mask;
+ opts->x_recip_mask |= mask;
}
}
- if (TARGET_RECIP)
- recip_mask |= RECIP_MASK_ALL & ~recip_mask_explicit;
- else if (target_flags_explicit & MASK_RECIP)
- recip_mask &= ~(RECIP_MASK_ALL & ~recip_mask_explicit);
+ if (TARGET_RECIP_P (opts->x_target_flags))
+ opts->x_recip_mask |= RECIP_MASK_ALL & ~opts->x_recip_mask_explicit;
+ else if (opts_set->x_target_flags & MASK_RECIP)
+ opts->x_recip_mask &= ~(RECIP_MASK_ALL & ~opts->x_recip_mask_explicit);
/* Default long double to 64-bit for Bionic. */
if (TARGET_HAS_BIONIC
- && !(target_flags_explicit & MASK_LONG_DOUBLE_64))
- target_flags |= MASK_LONG_DOUBLE_64;
+ && !(opts_set->x_target_flags & MASK_LONG_DOUBLE_64))
+ opts->x_target_flags |= MASK_LONG_DOUBLE_64;
/* Save the initial options in case the user does function specific
options. */
if (main_args_p)
target_option_default_node = target_option_current_node
- = build_target_option_node ();
+ = build_target_option_node (opts);
/* Handle stack protector */
- if (!global_options_set.x_ix86_stack_protector_guard)
- ix86_stack_protector_guard = TARGET_HAS_BIONIC ? SSP_GLOBAL : SSP_TLS;
+ if (!opts_set->x_ix86_stack_protector_guard)
+ opts->x_ix86_stack_protector_guard
+ = TARGET_HAS_BIONIC ? SSP_GLOBAL : SSP_TLS;
/* Handle -mmemcpy-strategy= and -mmemset-strategy= */
- if (ix86_tune_memcpy_strategy)
+ if (opts->x_ix86_tune_memcpy_strategy)
{
- char *str = xstrdup (ix86_tune_memcpy_strategy);
+ char *str = xstrdup (opts->x_ix86_tune_memcpy_strategy);
ix86_parse_stringop_strategy_string (str, false);
free (str);
}
- if (ix86_tune_memset_strategy)
+ if (opts->x_ix86_tune_memset_strategy)
{
- char *str = xstrdup (ix86_tune_memset_strategy);
+ char *str = xstrdup (opts->x_ix86_tune_memset_strategy);
ix86_parse_stringop_strategy_string (str, true);
free (str);
}
@@ -4055,7 +4080,7 @@ ix86_option_override (void)
1, PASS_POS_INSERT_AFTER
};
- ix86_option_override_internal (true);
+ ix86_option_override_internal (true, &global_options, &global_options_set);
/* This needs to be done at start up. It's convenient to do it here. */
@@ -4134,13 +4159,19 @@ ix86_conditional_register_usage (void)
for (i = FIRST_MASK_REG; i <= LAST_MASK_REG; i++)
fixed_regs[i] = call_used_regs[i] = 1, reg_names[i] = "";
}
+
+ /* If MPX is disabled, squash the registers. */
+ if (! TARGET_MPX)
+ for (i = FIRST_BND_REG; i <= LAST_BND_REG; i++)
+ fixed_regs[i] = call_used_regs[i] = 1, reg_names[i] = "";
}
/* Save the current options */
static void
-ix86_function_specific_save (struct cl_target_option *ptr)
+ix86_function_specific_save (struct cl_target_option *ptr,
+ struct gcc_options *opts)
{
ptr->arch = ix86_arch;
ptr->schedule = ix86_schedule;
@@ -4148,9 +4179,9 @@ ix86_function_specific_save (struct cl_target_option *ptr)
ptr->branch_cost = ix86_branch_cost;
ptr->tune_defaulted = ix86_tune_defaulted;
ptr->arch_specified = ix86_arch_specified;
- ptr->x_ix86_isa_flags_explicit = ix86_isa_flags_explicit;
- ptr->ix86_target_flags_explicit = target_flags_explicit;
- ptr->x_recip_mask_explicit = recip_mask_explicit;
+ ptr->x_ix86_isa_flags_explicit = opts->x_ix86_isa_flags_explicit;
+ ptr->x_ix86_target_flags_explicit = opts->x_ix86_target_flags_explicit;
+ ptr->x_recip_mask_explicit = opts->x_recip_mask_explicit;
/* The fields are char but the variables are not; make sure the
values fit in the fields. */
@@ -4163,7 +4194,8 @@ ix86_function_specific_save (struct cl_target_option *ptr)
/* Restore the current options */
static void
-ix86_function_specific_restore (struct cl_target_option *ptr)
+ix86_function_specific_restore (struct gcc_options *opts,
+ struct cl_target_option *ptr)
{
enum processor_type old_tune = ix86_tune;
enum processor_type old_arch = ix86_arch;
@@ -4173,12 +4205,12 @@ ix86_function_specific_restore (struct cl_target_option *ptr)
ix86_arch = (enum processor_type) ptr->arch;
ix86_schedule = (enum attr_cpu) ptr->schedule;
ix86_tune = (enum processor_type) ptr->tune;
- ix86_branch_cost = ptr->branch_cost;
+ opts->x_ix86_branch_cost = ptr->branch_cost;
ix86_tune_defaulted = ptr->tune_defaulted;
ix86_arch_specified = ptr->arch_specified;
- ix86_isa_flags_explicit = ptr->x_ix86_isa_flags_explicit;
- target_flags_explicit = ptr->ix86_target_flags_explicit;
- recip_mask_explicit = ptr->x_recip_mask_explicit;
+ opts->x_ix86_isa_flags_explicit = ptr->x_ix86_isa_flags_explicit;
+ opts->x_ix86_target_flags_explicit = ptr->x_ix86_target_flags_explicit;
+ opts->x_recip_mask_explicit = ptr->x_recip_mask_explicit;
/* Recreate the arch feature tests if the arch changed */
if (old_arch != ix86_arch)
@@ -4234,6 +4266,8 @@ ix86_function_specific_print (FILE *file, int indent,
static bool
ix86_valid_target_attribute_inner_p (tree args, char *p_strings[],
+ struct gcc_options *opts,
+ struct gcc_options *opts_set,
struct gcc_options *enum_opts_set)
{
char *next_optstr;
@@ -4350,7 +4384,8 @@ ix86_valid_target_attribute_inner_p (tree args, char *p_strings[],
for (; args; args = TREE_CHAIN (args))
if (TREE_VALUE (args)
&& !ix86_valid_target_attribute_inner_p (TREE_VALUE (args),
- p_strings, enum_opts_set))
+ p_strings, opts, opts_set,
+ enum_opts_set))
ret = false;
return ret;
@@ -4433,7 +4468,7 @@ ix86_valid_target_attribute_inner_p (tree args, char *p_strings[],
struct cl_decoded_option decoded;
generate_option (opt, NULL, opt_set_p, CL_TARGET, &decoded);
- ix86_handle_option (&global_options, &global_options_set,
+ ix86_handle_option (opts, opts_set,
&decoded, input_location);
}
@@ -4443,9 +4478,9 @@ ix86_valid_target_attribute_inner_p (tree args, char *p_strings[],
opt_set_p = !opt_set_p;
if (opt_set_p)
- target_flags |= mask;
+ opts->x_target_flags |= mask;
else
- target_flags &= ~mask;
+ opts->x_target_flags &= ~mask;
}
else if (type == ix86_opt_str)
@@ -4466,7 +4501,7 @@ ix86_valid_target_attribute_inner_p (tree args, char *p_strings[],
arg_ok = opt_enum_arg_to_value (opt, p + opt_len, &value, CL_TARGET);
if (arg_ok)
- set_option (&global_options, enum_opts_set, opt, value,
+ set_option (opts, enum_opts_set, opt, value,
p + opt_len, DK_UNSPECIFIED, input_location,
global_dc);
else
@@ -4486,11 +4521,13 @@ ix86_valid_target_attribute_inner_p (tree args, char *p_strings[],
/* Return a TARGET_OPTION_NODE tree of the target options listed or NULL. */
tree
-ix86_valid_target_attribute_tree (tree args)
+ix86_valid_target_attribute_tree (tree args,
+ struct gcc_options *opts,
+ struct gcc_options *opts_set)
{
const char *orig_arch_string = ix86_arch_string;
const char *orig_tune_string = ix86_tune_string;
- enum fpmath_unit orig_fpmath_set = global_options_set.x_ix86_fpmath;
+ enum fpmath_unit orig_fpmath_set = opts_set->x_ix86_fpmath;
int orig_tune_defaulted = ix86_tune_defaulted;
int orig_arch_specified = ix86_arch_specified;
char *option_strings[IX86_FUNCTION_SPECIFIC_MAX] = { NULL, NULL };
@@ -4503,16 +4540,16 @@ ix86_valid_target_attribute_tree (tree args)
memset (&enum_opts_set, 0, sizeof (enum_opts_set));
/* Process each of the options on the chain. */
- if (! ix86_valid_target_attribute_inner_p (args, option_strings,
- &enum_opts_set))
+ if (! ix86_valid_target_attribute_inner_p (args, option_strings, opts,
+ opts_set, &enum_opts_set))
return error_mark_node;
/* If the changed options are different from the default, rerun
ix86_option_override_internal, and then save the options away.
The string options are are attribute options, and will be undone
when we copy the save structure. */
- if (ix86_isa_flags != def->x_ix86_isa_flags
- || target_flags != def->x_target_flags
+ if (opts->x_ix86_isa_flags != def->x_ix86_isa_flags
+ || opts->x_target_flags != def->x_target_flags
|| option_strings[IX86_FUNCTION_SPECIFIC_ARCH]
|| option_strings[IX86_FUNCTION_SPECIFIC_TUNE]
|| enum_opts_set.x_ix86_fpmath)
@@ -4520,37 +4557,38 @@ ix86_valid_target_attribute_tree (tree args)
/* If we are using the default tune= or arch=, undo the string assigned,
and use the default. */
if (option_strings[IX86_FUNCTION_SPECIFIC_ARCH])
- ix86_arch_string = option_strings[IX86_FUNCTION_SPECIFIC_ARCH];
+ opts->x_ix86_arch_string = option_strings[IX86_FUNCTION_SPECIFIC_ARCH];
else if (!orig_arch_specified)
- ix86_arch_string = NULL;
+ opts->x_ix86_arch_string = NULL;
if (option_strings[IX86_FUNCTION_SPECIFIC_TUNE])
- ix86_tune_string = option_strings[IX86_FUNCTION_SPECIFIC_TUNE];
+ opts->x_ix86_tune_string = option_strings[IX86_FUNCTION_SPECIFIC_TUNE];
else if (orig_tune_defaulted)
- ix86_tune_string = NULL;
+ opts->x_ix86_tune_string = NULL;
/* If fpmath= is not set, and we now have sse2 on 32-bit, use it. */
if (enum_opts_set.x_ix86_fpmath)
- global_options_set.x_ix86_fpmath = (enum fpmath_unit) 1;
- else if (!TARGET_64BIT && TARGET_SSE)
+ opts_set->x_ix86_fpmath = (enum fpmath_unit) 1;
+ else if (!TARGET_64BIT_P (opts->x_ix86_isa_flags)
+ && TARGET_SSE_P (opts->x_ix86_isa_flags))
{
- ix86_fpmath = (enum fpmath_unit) (FPMATH_SSE | FPMATH_387);
- global_options_set.x_ix86_fpmath = (enum fpmath_unit) 1;
+ opts->x_ix86_fpmath = (enum fpmath_unit) (FPMATH_SSE | FPMATH_387);
+ opts_set->x_ix86_fpmath = (enum fpmath_unit) 1;
}
/* Do any overrides, such as arch=xxx, or tune=xxx support. */
- ix86_option_override_internal (false);
+ ix86_option_override_internal (false, opts, opts_set);
/* Add any builtin functions with the new isa if any. */
- ix86_add_new_builtins (ix86_isa_flags);
+ ix86_add_new_builtins (opts->x_ix86_isa_flags);
/* Save the current options unless we are validating options for
#pragma. */
- t = build_target_option_node ();
+ t = build_target_option_node (opts);
- ix86_arch_string = orig_arch_string;
- ix86_tune_string = orig_tune_string;
- global_options_set.x_ix86_fpmath = orig_fpmath_set;
+ opts->x_ix86_arch_string = orig_arch_string;
+ opts->x_ix86_tune_string = orig_tune_string;
+ opts_set->x_ix86_fpmath = orig_fpmath_set;
/* Free up memory allocated to hold the strings */
for (i = 0; i < IX86_FUNCTION_SPECIFIC_MAX; i++)
@@ -4568,7 +4606,8 @@ ix86_valid_target_attribute_p (tree fndecl,
tree args,
int ARG_UNUSED (flags))
{
- struct cl_target_option cur_target;
+ struct gcc_options func_options;
+ tree new_target, new_optimize;
bool ret = true;
/* attribute((target("default"))) does nothing, beyond
@@ -4579,21 +4618,31 @@ ix86_valid_target_attribute_p (tree fndecl,
&& strcmp (TREE_STRING_POINTER (TREE_VALUE (args)), "default") == 0)
return true;
- tree old_optimize = build_optimization_node ();
- tree new_target, new_optimize;
+ tree old_optimize = build_optimization_node (&global_options);
+
+ /* Get the optimization options of the current function. */
tree func_optimize = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl);
+
+ if (!func_optimize)
+ func_optimize = old_optimize;
- /* If the function changed the optimization levels as well as setting target
- options, start with the optimizations specified. */
- if (func_optimize && func_optimize != old_optimize)
- cl_optimization_restore (&global_options,
- TREE_OPTIMIZATION (func_optimize));
+ /* Init func_options. */
+ memset (&func_options, 0, sizeof (func_options));
+ init_options_struct (&func_options, NULL);
+ lang_hooks.init_options_struct (&func_options);
+
+ cl_optimization_restore (&func_options,
+ TREE_OPTIMIZATION (func_optimize));
+
+ /* Initialize func_options to the default before its target options can
+ be set. */
+ cl_target_option_restore (&func_options,
+ TREE_TARGET_OPTION (target_option_default_node));
+
+ new_target = ix86_valid_target_attribute_tree (args, &func_options,
+ &global_options_set);
- /* The target attributes may also change some optimization flags, so update
- the optimization options if necessary. */
- cl_target_option_save (&cur_target, &global_options);
- new_target = ix86_valid_target_attribute_tree (args);
- new_optimize = build_optimization_node ();
+ new_optimize = build_optimization_node (&func_options);
if (new_target == error_mark_node)
ret = false;
@@ -4606,12 +4655,6 @@ ix86_valid_target_attribute_p (tree fndecl,
DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl) = new_optimize;
}
- cl_target_option_restore (&global_options, &cur_target);
-
- if (old_optimize != new_optimize)
- cl_optimization_restore (&global_options,
- TREE_OPTIMIZATION (old_optimize));
-
return ret;
}
@@ -7367,9 +7410,15 @@ ix86_function_value_regno_p (const unsigned int regno)
switch (regno)
{
case AX_REG:
+ case DX_REG:
return true;
+ case DI_REG:
+ case SI_REG:
+ return TARGET_64BIT && ix86_abi != MS_ABI;
- case FIRST_FLOAT_REG:
+ /* Complex values are returned in %st(0)/%st(1) pair. */
+ case ST0_REG:
+ case ST1_REG:
/* TODO: The function should depend on current function ABI but
builtins.c would need updating then. Therefore we use the
default ABI. */
@@ -7377,10 +7426,12 @@ ix86_function_value_regno_p (const unsigned int regno)
return false;
return TARGET_FLOAT_RETURNS_IN_80387;
- case FIRST_SSE_REG:
+ /* Complex values are returned in %xmm0/%xmm1 pair. */
+ case XMM0_REG:
+ case XMM1_REG:
return TARGET_SSE;
- case FIRST_MMX_REG:
+ case MM0_REG:
if (TARGET_MACHO || TARGET_64BIT)
return false;
return TARGET_MMX;
@@ -8835,7 +8886,7 @@ ix86_code_end (void)
xops[0] = gen_rtx_REG (Pmode, regno);
xops[1] = gen_rtx_MEM (Pmode, stack_pointer_rtx);
output_asm_insn ("mov%z0\t{%1, %0|%0, %1}", xops);
- fputs ("\tret\n", asm_out_file);
+ output_asm_insn ("%!ret", NULL);
final_end_function ();
init_insn_lengths ();
free_after_compilation (cfun);
@@ -8893,7 +8944,7 @@ output_set_got (rtx dest, rtx label)
xops[2] = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (name));
xops[2] = gen_rtx_MEM (QImode, xops[2]);
- output_asm_insn ("call\t%X2", xops);
+ output_asm_insn ("%!call\t%X2", xops);
#if TARGET_MACHO
/* Output the Mach-O "canonical" pic base label name ("Lxx$pb") here.
@@ -10606,8 +10657,12 @@ ix86_expand_prologue (void)
if (STACK_CHECK_MOVING_SP)
{
- ix86_adjust_stack_and_probe (allocate);
- allocate = 0;
+ if (!(crtl->is_leaf && !cfun->calls_alloca
+ && allocate <= PROBE_INTERVAL))
+ {
+ ix86_adjust_stack_and_probe (allocate);
+ allocate = 0;
+ }
}
else
{
@@ -10617,9 +10672,26 @@ ix86_expand_prologue (void)
size = 0x80000000 - STACK_CHECK_PROTECT - 1;
if (TARGET_STACK_PROBE)
- ix86_emit_probe_stack_range (0, size + STACK_CHECK_PROTECT);
+ {
+ if (crtl->is_leaf && !cfun->calls_alloca)
+ {
+ if (size > PROBE_INTERVAL)
+ ix86_emit_probe_stack_range (0, size);
+ }
+ else
+ ix86_emit_probe_stack_range (0, size + STACK_CHECK_PROTECT);
+ }
else
- ix86_emit_probe_stack_range (STACK_CHECK_PROTECT, size);
+ {
+ if (crtl->is_leaf && !cfun->calls_alloca)
+ {
+ if (size > PROBE_INTERVAL && size > STACK_CHECK_PROTECT)
+ ix86_emit_probe_stack_range (STACK_CHECK_PROTECT,
+ size - STACK_CHECK_PROTECT);
+ }
+ else
+ ix86_emit_probe_stack_range (STACK_CHECK_PROTECT, size);
+ }
}
}
@@ -11511,8 +11583,8 @@ ix86_expand_split_stack_prologue (void)
JUMP_LABEL (jump_insn) = label;
/* Mark the jump as very likely to be taken. */
- add_reg_note (jump_insn, REG_BR_PROB,
- GEN_INT (REG_BR_PROB_BASE - REG_BR_PROB_BASE / 100));
+ add_int_reg_note (jump_insn, REG_BR_PROB,
+ REG_BR_PROB_BASE - REG_BR_PROB_BASE / 100);
if (split_stack_fn == NULL_RTX)
split_stack_fn = gen_rtx_SYMBOL_REF (Pmode, "__morestack");
@@ -14069,8 +14141,6 @@ put_condition_code (enum rtx_code code, enum machine_mode mode, bool reverse,
Those same assemblers have the same but opposite lossage on cmov. */
if (mode == CCmode)
suffix = fp ? "nbe" : "a";
- else if (mode == CCCmode)
- suffix = "b";
else
gcc_unreachable ();
break;
@@ -14092,8 +14162,12 @@ put_condition_code (enum rtx_code code, enum machine_mode mode, bool reverse,
}
break;
case LTU:
- gcc_assert (mode == CCmode || mode == CCCmode);
- suffix = "b";
+ if (mode == CCmode)
+ suffix = "b";
+ else if (mode == CCCmode)
+ suffix = "c";
+ else
+ gcc_unreachable ();
break;
case GE:
switch (mode)
@@ -14113,20 +14187,20 @@ put_condition_code (enum rtx_code code, enum machine_mode mode, bool reverse,
}
break;
case GEU:
- /* ??? As above. */
- gcc_assert (mode == CCmode || mode == CCCmode);
- suffix = fp ? "nb" : "ae";
+ if (mode == CCmode)
+ suffix = fp ? "nb" : "ae";
+ else if (mode == CCCmode)
+ suffix = "nc";
+ else
+ gcc_unreachable ();
break;
case LE:
gcc_assert (mode == CCmode || mode == CCGCmode || mode == CCNOmode);
suffix = "le";
break;
case LEU:
- /* ??? As above. */
if (mode == CCmode)
suffix = "be";
- else if (mode == CCCmode)
- suffix = fp ? "nb" : "ae";
else
gcc_unreachable ();
break;
@@ -14244,7 +14318,7 @@ print_reg (rtx x, int code, FILE *file)
case 8:
case 4:
case 12:
- if (! ANY_FP_REG_P (x))
+ if (! ANY_FP_REG_P (x) && ! ANY_BND_REG_P (x))
putc (code == 8 && TARGET_64BIT ? 'r' : 'e', file);
/* FALLTHRU */
case 16:
@@ -14367,6 +14441,7 @@ get_some_local_dynamic_name (void)
~ -- print "i" if TARGET_AVX2, "f" otherwise.
@ -- print a segment register of thread base pointer load
^ -- print addr32 prefix if TARGET_64BIT and Pmode != word_mode
+ ! -- print MPX prefix for jxx/call/ret instructions if required.
*/
void
@@ -14808,7 +14883,7 @@ ix86_print_operand (FILE *file, rtx x, int code)
x = find_reg_note (current_output_insn, REG_BR_PROB, 0);
if (x)
{
- int pred_val = INTVAL (XEXP (x, 0));
+ int pred_val = XINT (x, 0);
if (pred_val < REG_BR_PROB_BASE * 45 / 100
|| pred_val > REG_BR_PROB_BASE * 55 / 100)
@@ -14861,6 +14936,11 @@ ix86_print_operand (FILE *file, rtx x, int code)
fputs ("addr32 ", file);
return;
+ case '!':
+ if (ix86_bnd_prefixed_insn_p (NULL_RTX))
+ fputs ("bnd ", file);
+ return;
+
default:
output_operand_lossage ("invalid operand code '%c'", code);
}
@@ -15003,7 +15083,7 @@ static bool
ix86_print_operand_punct_valid_p (unsigned char code)
{
return (code == '@' || code == '*' || code == '+' || code == '&'
- || code == ';' || code == '~' || code == '^');
+ || code == ';' || code == '~' || code == '^' || code == '!');
}
/* Print a memory operand whose address is ADDR. */
@@ -15033,6 +15113,25 @@ ix86_print_operand_address (FILE *file, rtx addr)
ok = ix86_decompose_address (XVECEXP (addr, 0, 0), &parts);
code = 'q';
}
+ else if (GET_CODE (addr) == UNSPEC && XINT (addr, 1) == UNSPEC_BNDMK_ADDR)
+ {
+ ok = ix86_decompose_address (XVECEXP (addr, 0, 1), &parts);
+ gcc_assert (parts.base == NULL_RTX || parts.index == NULL_RTX);
+ if (parts.base != NULL_RTX)
+ {
+ parts.index = parts.base;
+ parts.scale = 1;
+ }
+ parts.base = XVECEXP (addr, 0, 0);
+ addr = XVECEXP (addr, 0, 0);
+ }
+ else if (GET_CODE (addr) == UNSPEC && XINT (addr, 1) == UNSPEC_BNDLDX_ADDR)
+ {
+ ok = ix86_decompose_address (XVECEXP (addr, 0, 0), &parts);
+ gcc_assert (parts.index == NULL_RTX);
+ parts.index = XVECEXP (addr, 0, 1);
+ addr = XVECEXP (addr, 0, 0);
+ }
else
ok = ix86_decompose_address (addr, &parts);
@@ -15609,7 +15708,7 @@ ix86_avx_u128_mode_needed (rtx insn)
rtx arg = XEXP (XEXP (link, 0), 0);
if (ix86_check_avx256_register (&arg, NULL))
- return AVX_U128_ANY;
+ return AVX_U128_DIRTY;
}
}
@@ -15729,8 +15828,8 @@ ix86_avx_u128_mode_after (int mode, rtx insn)
{
bool avx_reg256_found = false;
note_stores (pat, ix86_check_avx256_stores, &avx_reg256_found);
- if (!avx_reg256_found)
- return AVX_U128_CLEAN;
+
+ return avx_reg256_found ? AVX_U128_DIRTY : AVX_U128_CLEAN;
}
/* Otherwise, return current mode. Remember that if insn
@@ -16457,8 +16556,8 @@ ix86_avx256_split_vector_move_misalign (rtx op0, rtx op1)
gcc_unreachable ();
case V32QImode:
extract = gen_avx_vextractf128v32qi;
- load_unaligned = gen_avx_loaddqu256;
- store_unaligned = gen_avx_storedqu256;
+ load_unaligned = gen_avx_loaddquv32qi;
+ store_unaligned = gen_avx_storedquv32qi;
mode = V16QImode;
break;
case V8SFmode:
@@ -16486,6 +16585,12 @@ ix86_avx256_split_vector_move_misalign (rtx op0, rtx op1)
r = gen_rtx_VEC_CONCAT (GET_MODE (op0), r, m);
emit_move_insn (op0, r);
}
+ /* Normal *mov<mode>_internal pattern will handle
+ unaligned loads just fine if misaligned_operand
+ is true, and without the UNSPEC it can be combined
+ with arithmetic instructions. */
+ else if (misaligned_operand (op1, GET_MODE (op1)))
+ emit_insn (gen_rtx_SET (VOIDmode, op0, op1));
else
emit_insn (load_unaligned (op0, op1));
}
@@ -16560,11 +16665,68 @@ ix86_avx256_split_vector_move_misalign (rtx op0, rtx op1)
void
ix86_expand_vector_move_misalign (enum machine_mode mode, rtx operands[])
{
- rtx op0, op1, m;
+ rtx op0, op1, orig_op0 = NULL_RTX, m;
+ rtx (*load_unaligned) (rtx, rtx);
+ rtx (*store_unaligned) (rtx, rtx);
op0 = operands[0];
op1 = operands[1];
+ if (GET_MODE_SIZE (mode) == 64)
+ {
+ switch (GET_MODE_CLASS (mode))
+ {
+ case MODE_VECTOR_INT:
+ case MODE_INT:
+ if (GET_MODE (op0) != V16SImode)
+ {
+ if (!MEM_P (op0))
+ {
+ orig_op0 = op0;
+ op0 = gen_reg_rtx (V16SImode);
+ }
+ else
+ op0 = gen_lowpart (V16SImode, op0);
+ }
+ op1 = gen_lowpart (V16SImode, op1);
+ /* FALLTHRU */
+
+ case MODE_VECTOR_FLOAT:
+ switch (GET_MODE (op0))
+ {
+ default:
+ gcc_unreachable ();
+ case V16SImode:
+ load_unaligned = gen_avx512f_loaddquv16si;
+ store_unaligned = gen_avx512f_storedquv16si;
+ break;
+ case V16SFmode:
+ load_unaligned = gen_avx512f_loadups512;
+ store_unaligned = gen_avx512f_storeups512;
+ break;
+ case V8DFmode:
+ load_unaligned = gen_avx512f_loadupd512;
+ store_unaligned = gen_avx512f_storeupd512;
+ break;
+ }
+
+ if (MEM_P (op1))
+ emit_insn (load_unaligned (op0, op1));
+ else if (MEM_P (op0))
+ emit_insn (store_unaligned (op0, op1));
+ else
+ gcc_unreachable ();
+ if (orig_op0)
+ emit_move_insn (orig_op0, gen_lowpart (GET_MODE (orig_op0), op0));
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ return;
+ }
+
if (TARGET_AVX
&& GET_MODE_SIZE (mode) == 32)
{
@@ -16572,12 +16734,23 @@ ix86_expand_vector_move_misalign (enum machine_mode mode, rtx operands[])
{
case MODE_VECTOR_INT:
case MODE_INT:
- op0 = gen_lowpart (V32QImode, op0);
+ if (GET_MODE (op0) != V32QImode)
+ {
+ if (!MEM_P (op0))
+ {
+ orig_op0 = op0;
+ op0 = gen_reg_rtx (V32QImode);
+ }
+ else
+ op0 = gen_lowpart (V32QImode, op0);
+ }
op1 = gen_lowpart (V32QImode, op1);
/* FALLTHRU */
case MODE_VECTOR_FLOAT:
ix86_avx256_split_vector_move_misalign (op0, op1);
+ if (orig_op0)
+ emit_move_insn (orig_op0, gen_lowpart (GET_MODE (orig_op0), op0));
break;
default:
@@ -16589,15 +16762,30 @@ ix86_expand_vector_move_misalign (enum machine_mode mode, rtx operands[])
if (MEM_P (op1))
{
+ /* Normal *mov<mode>_internal pattern will handle
+ unaligned loads just fine if misaligned_operand
+ is true, and without the UNSPEC it can be combined
+ with arithmetic instructions. */
+ if (TARGET_AVX
+ && (GET_MODE_CLASS (mode) == MODE_VECTOR_INT
+ || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT)
+ && misaligned_operand (op1, GET_MODE (op1)))
+ emit_insn (gen_rtx_SET (VOIDmode, op0, op1));
/* ??? If we have typed data, then it would appear that using
movdqu is the only way to get unaligned data loaded with
integer type. */
- if (TARGET_SSE2 && GET_MODE_CLASS (mode) == MODE_VECTOR_INT)
+ else if (TARGET_SSE2 && GET_MODE_CLASS (mode) == MODE_VECTOR_INT)
{
- op0 = gen_lowpart (V16QImode, op0);
+ if (GET_MODE (op0) != V16QImode)
+ {
+ orig_op0 = op0;
+ op0 = gen_reg_rtx (V16QImode);
+ }
op1 = gen_lowpart (V16QImode, op1);
/* We will eventually emit movups based on insn attributes. */
- emit_insn (gen_sse2_loaddqu (op0, op1));
+ emit_insn (gen_sse2_loaddquv16qi (op0, op1));
+ if (orig_op0)
+ emit_move_insn (orig_op0, gen_lowpart (GET_MODE (orig_op0), op0));
}
else if (TARGET_SSE2 && mode == V2DFmode)
{
@@ -16640,29 +16828,42 @@ ix86_expand_vector_move_misalign (enum machine_mode mode, rtx operands[])
}
else
{
+ rtx t;
+
if (TARGET_AVX
|| TARGET_SSE_UNALIGNED_LOAD_OPTIMAL
|| TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL
|| optimize_insn_for_size_p ())
{
- op0 = gen_lowpart (V4SFmode, op0);
+ if (GET_MODE (op0) != V4SFmode)
+ {
+ orig_op0 = op0;
+ op0 = gen_reg_rtx (V4SFmode);
+ }
op1 = gen_lowpart (V4SFmode, op1);
emit_insn (gen_sse_loadups (op0, op1));
+ if (orig_op0)
+ emit_move_insn (orig_op0,
+ gen_lowpart (GET_MODE (orig_op0), op0));
return;
}
+ if (mode != V4SFmode)
+ t = gen_reg_rtx (V4SFmode);
+ else
+ t = op0;
+
if (TARGET_SSE_PARTIAL_REG_DEPENDENCY)
- emit_move_insn (op0, CONST0_RTX (mode));
+ emit_move_insn (t, CONST0_RTX (V4SFmode));
else
- emit_clobber (op0);
-
- if (mode != V4SFmode)
- op0 = gen_lowpart (V4SFmode, op0);
+ emit_clobber (t);
m = adjust_address (op1, V2SFmode, 0);
- emit_insn (gen_sse_loadlps (op0, op0, m));
+ emit_insn (gen_sse_loadlps (t, t, m));
m = adjust_address (op1, V2SFmode, 8);
- emit_insn (gen_sse_loadhps (op0, op0, m));
+ emit_insn (gen_sse_loadhps (t, t, m));
+ if (mode != V4SFmode)
+ emit_move_insn (op0, gen_lowpart (mode, t));
}
}
else if (MEM_P (op0))
@@ -16672,7 +16873,7 @@ ix86_expand_vector_move_misalign (enum machine_mode mode, rtx operands[])
op0 = gen_lowpart (V16QImode, op0);
op1 = gen_lowpart (V16QImode, op1);
/* We will eventually emit movups based on insn attributes. */
- emit_insn (gen_sse2_storedqu (op0, op1));
+ emit_insn (gen_sse2_storedquv16qi (op0, op1));
}
else if (TARGET_SSE2 && mode == V2DFmode)
{
@@ -16811,8 +17012,10 @@ ix86_fixup_binary_operands (enum rtx_code code, enum machine_mode mode,
src2 = force_reg (mode, src2);
src1 = src2;
}
- else
+ else if (rtx_equal_p (dst, src1))
src2 = force_reg (mode, src2);
+ else
+ src1 = force_reg (mode, src1);
}
/* If the destination is memory, and we do not have matching source
@@ -17162,6 +17365,14 @@ ix86_split_idivmod (enum machine_mode mode, rtx operands[],
emit_label (end_label);
}
+/* Whether it is OK to emit CFI directives when emitting asm code. */
+
+bool
+ix86_emit_cfi ()
+{
+ return dwarf2out_do_cfi_asm ();
+}
+
#define LEA_MAX_STALL (3)
#define LEA_SEARCH_THRESHOLD (LEA_MAX_STALL << 1)
@@ -18780,12 +18991,7 @@ ix86_cc_mode (enum rtx_code code, rtx op0, rtx op1)
return CCmode;
case GTU: /* CF=0 & ZF=0 */
case LEU: /* CF=1 | ZF=1 */
- /* Detect overflow checks. They need just the carry flag. */
- if (GET_CODE (op0) == MINUS
- && rtx_equal_p (op1, XEXP (op0, 0)))
- return CCCmode;
- else
- return CCmode;
+ return CCmode;
/* Codes possibly doable only with sign flag when
comparing against zero. */
case GE: /* SF=OF or SF=0 */
@@ -19454,7 +19660,7 @@ ix86_split_fp_branch (enum rtx_code code, rtx op1, rtx op2,
gen_rtx_IF_THEN_ELSE (VOIDmode,
condition, target1, target2)));
if (split_branch_probability >= 0)
- add_reg_note (i, REG_BR_PROB, GEN_INT (split_branch_probability));
+ add_int_reg_note (i, REG_BR_PROB, split_branch_probability);
}
void
@@ -20306,6 +20512,7 @@ ix86_expand_sse_movcc (rtx dest, rtx cmp, rtx op_true, rtx op_false)
else
{
rtx (*gen) (rtx, rtx, rtx, rtx) = NULL;
+ rtx d = dest;
if (!nonimmediate_operand (op_true, mode))
op_true = force_reg (mode, op_true);
@@ -20329,7 +20536,8 @@ ix86_expand_sse_movcc (rtx dest, rtx cmp, rtx op_true, rtx op_false)
if (TARGET_SSE4_1)
{
gen = gen_sse4_1_pblendvb;
- dest = gen_lowpart (V16QImode, dest);
+ if (mode != V16QImode)
+ d = gen_reg_rtx (V16QImode);
op_false = gen_lowpart (V16QImode, op_false);
op_true = gen_lowpart (V16QImode, op_true);
cmp = gen_lowpart (V16QImode, cmp);
@@ -20350,7 +20558,8 @@ ix86_expand_sse_movcc (rtx dest, rtx cmp, rtx op_true, rtx op_false)
if (TARGET_AVX2)
{
gen = gen_avx2_pblendvb;
- dest = gen_lowpart (V32QImode, dest);
+ if (mode != V32QImode)
+ d = gen_reg_rtx (V32QImode);
op_false = gen_lowpart (V32QImode, op_false);
op_true = gen_lowpart (V32QImode, op_true);
cmp = gen_lowpart (V32QImode, cmp);
@@ -20361,7 +20570,11 @@ ix86_expand_sse_movcc (rtx dest, rtx cmp, rtx op_true, rtx op_false)
}
if (gen != NULL)
- emit_insn (gen (dest, op_false, op_true, cmp));
+ {
+ emit_insn (gen (d, op_false, op_true, cmp));
+ if (d != dest)
+ emit_move_insn (dest, gen_lowpart (GET_MODE (dest), d));
+ }
else
{
op_true = force_reg (mode, op_true);
@@ -20682,8 +20895,7 @@ ix86_expand_int_vcond (rtx operands[])
else
{
gcc_assert (GET_MODE_SIZE (data_mode) == GET_MODE_SIZE (mode));
- x = ix86_expand_sse_cmp (gen_lowpart (mode, operands[0]),
- code, cop0, cop1,
+ x = ix86_expand_sse_cmp (gen_reg_rtx (mode), code, cop0, cop1,
operands[1+negate], operands[2-negate]);
x = gen_lowpart (data_mode, x);
}
@@ -20702,7 +20914,7 @@ ix86_expand_vec_perm (rtx operands[])
rtx op0 = operands[1];
rtx op1 = operands[2];
rtx mask = operands[3];
- rtx t1, t2, t3, t4, vt, vt2, vec[32];
+ rtx t1, t2, t3, t4, t5, t6, t7, t8, vt, vt2, vec[32];
enum machine_mode mode = GET_MODE (op0);
enum machine_mode maskmode = GET_MODE (mask);
int w, e, i;
@@ -20770,7 +20982,7 @@ ix86_expand_vec_perm (rtx operands[])
/* Continue as if V8SImode (resp. V32QImode) was used initially. */
operands[3] = mask = t1;
- target = gen_lowpart (mode, target);
+ target = gen_reg_rtx (mode);
op0 = gen_lowpart (mode, op0);
op1 = gen_lowpart (mode, op1);
}
@@ -20782,7 +20994,12 @@ ix86_expand_vec_perm (rtx operands[])
the high bits of the shuffle elements. No need for us to
perform an AND ourselves. */
if (one_operand_shuffle)
- emit_insn (gen_avx2_permvarv8si (target, op0, mask));
+ {
+ emit_insn (gen_avx2_permvarv8si (target, op0, mask));
+ if (target != operands[0])
+ emit_move_insn (operands[0],
+ gen_lowpart (GET_MODE (operands[0]), target));
+ }
else
{
t1 = gen_reg_rtx (V8SImode);
@@ -20855,13 +21072,13 @@ ix86_expand_vec_perm (rtx operands[])
stands for other 12 bytes. */
/* The bit whether element is from the same lane or the other
lane is bit 4, so shift it up by 3 to the MSB position. */
- emit_insn (gen_ashlv4di3 (gen_lowpart (V4DImode, t1),
- gen_lowpart (V4DImode, mask),
+ t5 = gen_reg_rtx (V4DImode);
+ emit_insn (gen_ashlv4di3 (t5, gen_lowpart (V4DImode, mask),
GEN_INT (3)));
/* Clear MSB bits from the mask just in case it had them set. */
emit_insn (gen_avx2_andnotv32qi3 (t2, vt, mask));
/* After this t1 will have MSB set for elements from other lane. */
- emit_insn (gen_xorv32qi3 (t1, t1, vt2));
+ emit_insn (gen_xorv32qi3 (t1, gen_lowpart (V32QImode, t5), vt2));
/* Clear bits other than MSB. */
emit_insn (gen_andv32qi3 (t1, t1, vt));
/* Or in the lower bits from mask into t3. */
@@ -20870,8 +21087,8 @@ ix86_expand_vec_perm (rtx operands[])
lane. */
emit_insn (gen_xorv32qi3 (t1, t1, vt));
/* Swap 128-bit lanes in t3. */
- emit_insn (gen_avx2_permv4di_1 (gen_lowpart (V4DImode, t3),
- gen_lowpart (V4DImode, t3),
+ t6 = gen_reg_rtx (V4DImode);
+ emit_insn (gen_avx2_permv4di_1 (t6, gen_lowpart (V4DImode, t3),
const2_rtx, GEN_INT (3),
const0_rtx, const1_rtx));
/* And or in the lower bits from mask into t1. */
@@ -20881,15 +21098,20 @@ ix86_expand_vec_perm (rtx operands[])
/* Each of these shuffles will put 0s in places where
element from the other 128-bit lane is needed, otherwise
will shuffle in the requested value. */
- emit_insn (gen_avx2_pshufbv32qi3 (t3, op0, t3));
+ emit_insn (gen_avx2_pshufbv32qi3 (t3, op0,
+ gen_lowpart (V32QImode, t6)));
emit_insn (gen_avx2_pshufbv32qi3 (t1, op0, t1));
/* For t3 the 128-bit lanes are swapped again. */
- emit_insn (gen_avx2_permv4di_1 (gen_lowpart (V4DImode, t3),
- gen_lowpart (V4DImode, t3),
+ t7 = gen_reg_rtx (V4DImode);
+ emit_insn (gen_avx2_permv4di_1 (t7, gen_lowpart (V4DImode, t3),
const2_rtx, GEN_INT (3),
const0_rtx, const1_rtx));
/* And oring both together leads to the result. */
- emit_insn (gen_iorv32qi3 (target, t1, t3));
+ emit_insn (gen_iorv32qi3 (target, t1,
+ gen_lowpart (V32QImode, t7)));
+ if (target != operands[0])
+ emit_move_insn (operands[0],
+ gen_lowpart (GET_MODE (operands[0]), target));
return;
}
@@ -20897,20 +21119,22 @@ ix86_expand_vec_perm (rtx operands[])
/* Similarly to the above one_operand_shuffle code,
just for repeated twice for each operand. merge_two:
code will merge the two results together. */
- emit_insn (gen_avx2_pshufbv32qi3 (t4, op0, t3));
- emit_insn (gen_avx2_pshufbv32qi3 (t3, op1, t3));
+ emit_insn (gen_avx2_pshufbv32qi3 (t4, op0,
+ gen_lowpart (V32QImode, t6)));
+ emit_insn (gen_avx2_pshufbv32qi3 (t3, op1,
+ gen_lowpart (V32QImode, t6)));
emit_insn (gen_avx2_pshufbv32qi3 (t2, op0, t1));
emit_insn (gen_avx2_pshufbv32qi3 (t1, op1, t1));
- emit_insn (gen_avx2_permv4di_1 (gen_lowpart (V4DImode, t4),
- gen_lowpart (V4DImode, t4),
+ t7 = gen_reg_rtx (V4DImode);
+ emit_insn (gen_avx2_permv4di_1 (t7, gen_lowpart (V4DImode, t4),
const2_rtx, GEN_INT (3),
const0_rtx, const1_rtx));
- emit_insn (gen_avx2_permv4di_1 (gen_lowpart (V4DImode, t3),
- gen_lowpart (V4DImode, t3),
+ t8 = gen_reg_rtx (V4DImode);
+ emit_insn (gen_avx2_permv4di_1 (t8, gen_lowpart (V4DImode, t3),
const2_rtx, GEN_INT (3),
const0_rtx, const1_rtx));
- emit_insn (gen_iorv32qi3 (t4, t2, t4));
- emit_insn (gen_iorv32qi3 (t3, t1, t3));
+ emit_insn (gen_iorv32qi3 (t4, t2, gen_lowpart (V32QImode, t7)));
+ emit_insn (gen_iorv32qi3 (t3, t1, gen_lowpart (V32QImode, t8)));
t1 = t4;
t2 = t3;
goto merge_two;
@@ -20979,15 +21203,24 @@ ix86_expand_vec_perm (rtx operands[])
/* The actual shuffle operations all operate on V16QImode. */
op0 = gen_lowpart (V16QImode, op0);
op1 = gen_lowpart (V16QImode, op1);
- target = gen_lowpart (V16QImode, target);
if (TARGET_XOP)
{
+ if (GET_MODE (target) != V16QImode)
+ target = gen_reg_rtx (V16QImode);
emit_insn (gen_xop_pperm (target, op0, op1, mask));
+ if (target != operands[0])
+ emit_move_insn (operands[0],
+ gen_lowpart (GET_MODE (operands[0]), target));
}
else if (one_operand_shuffle)
{
+ if (GET_MODE (target) != V16QImode)
+ target = gen_reg_rtx (V16QImode);
emit_insn (gen_ssse3_pshufbv16qi3 (target, op0, mask));
+ if (target != operands[0])
+ emit_move_insn (operands[0],
+ gen_lowpart (GET_MODE (operands[0]), target));
}
else
{
@@ -21027,7 +21260,9 @@ ix86_expand_vec_perm (rtx operands[])
mask = expand_simple_binop (maskmode, AND, mask, vt,
NULL_RTX, 0, OPTAB_DIRECT);
- xops[0] = gen_lowpart (mode, operands[0]);
+ if (GET_MODE (target) != mode)
+ target = gen_reg_rtx (mode);
+ xops[0] = target;
xops[1] = gen_lowpart (mode, t2);
xops[2] = gen_lowpart (mode, t1);
xops[3] = gen_rtx_EQ (maskmode, mask, vt);
@@ -21035,6 +21270,9 @@ ix86_expand_vec_perm (rtx operands[])
xops[5] = vt;
ok = ix86_expand_int_vcond (xops);
gcc_assert (ok);
+ if (target != operands[0])
+ emit_move_insn (operands[0],
+ gen_lowpart (GET_MODE (operands[0]), target));
}
}
@@ -21113,10 +21351,10 @@ ix86_expand_sse_unpack (rtx dest, rtx src, bool unsigned_p, bool high_p)
else if (high_p)
{
/* Shift higher 8 bytes to lower 8 bytes. */
- tmp = gen_reg_rtx (imode);
- emit_insn (gen_sse2_lshrv1ti3 (gen_lowpart (V1TImode, tmp),
- gen_lowpart (V1TImode, src),
+ tmp = gen_reg_rtx (V1TImode);
+ emit_insn (gen_sse2_lshrv1ti3 (tmp, gen_lowpart (V1TImode, src),
GEN_INT (64)));
+ tmp = gen_lowpart (imode, tmp);
}
else
tmp = src;
@@ -21157,7 +21395,9 @@ ix86_expand_sse_unpack (rtx dest, rtx src, bool unsigned_p, bool high_p)
tmp = ix86_expand_sse_cmp (gen_reg_rtx (imode), GT, CONST0_RTX (imode),
src, pc_rtx, pc_rtx);
- emit_insn (unpack (gen_lowpart (imode, dest), src, tmp));
+ rtx tmp2 = gen_reg_rtx (imode);
+ emit_insn (unpack (tmp2, src, tmp));
+ emit_move_insn (dest, gen_lowpart (GET_MODE (dest), tmp2));
}
}
@@ -21961,7 +22201,7 @@ predict_jump (int prob)
{
rtx insn = get_last_insn ();
gcc_assert (JUMP_P (insn));
- add_reg_note (insn, REG_BR_PROB, GEN_INT (prob));
+ add_int_reg_note (insn, REG_BR_PROB, prob);
}
/* Helper function for the string operations below. Dest VARIABLE whether
@@ -22034,10 +22274,25 @@ counter_mode (rtx count_exp)
return SImode;
}
-/* When SRCPTR is non-NULL, output simple loop to move memory
- pointer to SRCPTR to DESTPTR via chunks of MODE unrolled UNROLL times,
- overall size is COUNT specified in bytes. When SRCPTR is NULL, output the
- equivalent loop to set memory by VALUE (supposed to be in MODE).
+/* Copy the address to a Pmode register. This is used for x32 to
+ truncate DImode TLS address to a SImode register. */
+
+static rtx
+ix86_copy_addr_to_reg (rtx addr)
+{
+ if (GET_MODE (addr) == Pmode)
+ return copy_addr_to_reg (addr);
+ else
+ {
+ gcc_assert (GET_MODE (addr) == DImode && Pmode == SImode);
+ return gen_rtx_SUBREG (SImode, copy_to_mode_reg (DImode, addr), 0);
+ }
+}
+
+/* When ISSETMEM is FALSE, output simple loop to move memory pointer to SRCPTR
+ to DESTPTR via chunks of MODE unrolled UNROLL times, overall size is COUNT
+ specified in bytes. When ISSETMEM is TRUE, output the equivalent loop to set
+ memory by VALUE (supposed to be in MODE).
The size is rounded down to whole number of chunk size moved at once.
SRCMEM and DESTMEM provide MEMrtx to feed proper aliasing info. */
@@ -22047,7 +22302,7 @@ static void
expand_set_or_movmem_via_loop (rtx destmem, rtx srcmem,
rtx destptr, rtx srcptr, rtx value,
rtx count, enum machine_mode mode, int unroll,
- int expected_size)
+ int expected_size, bool issetmem)
{
rtx out_label, top_label, iter, tmp;
enum machine_mode iter_mode = counter_mode (count);
@@ -22083,7 +22338,7 @@ expand_set_or_movmem_via_loop (rtx destmem, rtx srcmem,
destmem = offset_address (destmem, tmp, piece_size_n);
destmem = adjust_address (destmem, mode, 0);
- if (srcmem)
+ if (!issetmem)
{
srcmem = offset_address (srcmem, copy_rtx (tmp), piece_size_n);
srcmem = adjust_address (srcmem, mode, 0);
@@ -22163,7 +22418,7 @@ expand_set_or_movmem_via_loop (rtx destmem, rtx srcmem,
true, OPTAB_LIB_WIDEN);
if (tmp != destptr)
emit_move_insn (destptr, tmp);
- if (srcptr)
+ if (!issetmem)
{
tmp = expand_simple_binop (Pmode, PLUS, srcptr, iter, srcptr,
true, OPTAB_LIB_WIDEN);
@@ -22173,96 +22428,85 @@ expand_set_or_movmem_via_loop (rtx destmem, rtx srcmem,
emit_label (out_label);
}
-/* Output "rep; mov" instruction.
- Arguments have same meaning as for previous function */
+/* Output "rep; mov" or "rep; stos" instruction depending on ISSETMEM argument.
+ When ISSETMEM is true, arguments SRCMEM and SRCPTR are ignored.
+ When ISSETMEM is false, arguments VALUE and ORIG_VALUE are ignored.
+ For setmem case, VALUE is a promoted to a wider size ORIG_VALUE.
+ ORIG_VALUE is the original value passed to memset to fill the memory with.
+ Other arguments have same meaning as for previous function. */
+
static void
-expand_movmem_via_rep_mov (rtx destmem, rtx srcmem,
- rtx destptr, rtx srcptr,
+expand_set_or_movmem_via_rep (rtx destmem, rtx srcmem,
+ rtx destptr, rtx srcptr, rtx value, rtx orig_value,
rtx count,
- enum machine_mode mode)
+ enum machine_mode mode, bool issetmem)
{
rtx destexp;
rtx srcexp;
rtx countreg;
HOST_WIDE_INT rounded_count;
- /* If the size is known, it is shorter to use rep movs. */
- if (mode == QImode && CONST_INT_P (count)
- && !(INTVAL (count) & 3))
+ /* If possible, it is shorter to use rep movs.
+ TODO: Maybe it is better to move this logic to decide_alg. */
+ if (mode == QImode && CONST_INT_P (count) && !(INTVAL (count) & 3)
+ && (!issetmem || orig_value == const0_rtx))
mode = SImode;
if (destptr != XEXP (destmem, 0) || GET_MODE (destmem) != BLKmode)
destmem = adjust_automodify_address_nv (destmem, BLKmode, destptr, 0);
- if (srcptr != XEXP (srcmem, 0) || GET_MODE (srcmem) != BLKmode)
- srcmem = adjust_automodify_address_nv (srcmem, BLKmode, srcptr, 0);
- countreg = ix86_zero_extend_to_Pmode (scale_counter (count, GET_MODE_SIZE (mode)));
+
+ countreg = ix86_zero_extend_to_Pmode (scale_counter (count,
+ GET_MODE_SIZE (mode)));
if (mode != QImode)
{
destexp = gen_rtx_ASHIFT (Pmode, countreg,
GEN_INT (exact_log2 (GET_MODE_SIZE (mode))));
destexp = gen_rtx_PLUS (Pmode, destexp, destptr);
- srcexp = gen_rtx_ASHIFT (Pmode, countreg,
- GEN_INT (exact_log2 (GET_MODE_SIZE (mode))));
- srcexp = gen_rtx_PLUS (Pmode, srcexp, srcptr);
}
else
- {
- destexp = gen_rtx_PLUS (Pmode, destptr, countreg);
- srcexp = gen_rtx_PLUS (Pmode, srcptr, countreg);
- }
- if (CONST_INT_P (count))
+ destexp = gen_rtx_PLUS (Pmode, destptr, countreg);
+ if ((!issetmem || orig_value == const0_rtx) && CONST_INT_P (count))
{
rounded_count = (INTVAL (count)
& ~((HOST_WIDE_INT) GET_MODE_SIZE (mode) - 1));
destmem = shallow_copy_rtx (destmem);
- srcmem = shallow_copy_rtx (srcmem);
set_mem_size (destmem, rounded_count);
- set_mem_size (srcmem, rounded_count);
- }
- else
- {
- if (MEM_SIZE_KNOWN_P (destmem))
- clear_mem_size (destmem);
- if (MEM_SIZE_KNOWN_P (srcmem))
- clear_mem_size (srcmem);
}
- emit_insn (gen_rep_mov (destptr, destmem, srcptr, srcmem, countreg,
- destexp, srcexp));
-}
-
-/* Output "rep; stos" instruction.
- Arguments have same meaning as for previous function */
-static void
-expand_setmem_via_rep_stos (rtx destmem, rtx destptr, rtx value,
- rtx count, enum machine_mode mode,
- rtx orig_value)
-{
- rtx destexp;
- rtx countreg;
- HOST_WIDE_INT rounded_count;
+ else if (MEM_SIZE_KNOWN_P (destmem))
+ clear_mem_size (destmem);
- if (destptr != XEXP (destmem, 0) || GET_MODE (destmem) != BLKmode)
- destmem = adjust_automodify_address_nv (destmem, BLKmode, destptr, 0);
- value = force_reg (mode, gen_lowpart (mode, value));
- countreg = ix86_zero_extend_to_Pmode (scale_counter (count, GET_MODE_SIZE (mode)));
- if (mode != QImode)
+ if (issetmem)
{
- destexp = gen_rtx_ASHIFT (Pmode, countreg,
- GEN_INT (exact_log2 (GET_MODE_SIZE (mode))));
- destexp = gen_rtx_PLUS (Pmode, destexp, destptr);
+ value = force_reg (mode, gen_lowpart (mode, value));
+ emit_insn (gen_rep_stos (destptr, countreg, destmem, value, destexp));
}
else
- destexp = gen_rtx_PLUS (Pmode, destptr, countreg);
- if (orig_value == const0_rtx && CONST_INT_P (count))
{
- rounded_count = (INTVAL (count)
- & ~((HOST_WIDE_INT) GET_MODE_SIZE (mode) - 1));
- destmem = shallow_copy_rtx (destmem);
- set_mem_size (destmem, rounded_count);
+ if (srcptr != XEXP (srcmem, 0) || GET_MODE (srcmem) != BLKmode)
+ srcmem = adjust_automodify_address_nv (srcmem, BLKmode, srcptr, 0);
+ if (mode != QImode)
+ {
+ srcexp = gen_rtx_ASHIFT (Pmode, countreg,
+ GEN_INT (exact_log2 (GET_MODE_SIZE (mode))));
+ srcexp = gen_rtx_PLUS (Pmode, srcexp, srcptr);
+ }
+ else
+ srcexp = gen_rtx_PLUS (Pmode, srcptr, countreg);
+ if (CONST_INT_P (count))
+ {
+ rounded_count = (INTVAL (count)
+ & ~((HOST_WIDE_INT) GET_MODE_SIZE (mode) - 1));
+ srcmem = shallow_copy_rtx (srcmem);
+ set_mem_size (srcmem, rounded_count);
+ }
+ else
+ {
+ if (MEM_SIZE_KNOWN_P (srcmem))
+ clear_mem_size (srcmem);
+ }
+ emit_insn (gen_rep_mov (destptr, destmem, srcptr, srcmem, countreg,
+ destexp, srcexp));
}
- else if (MEM_SIZE_KNOWN_P (destmem))
- clear_mem_size (destmem);
- emit_insn (gen_rep_stos (destptr, countreg, destmem, value, destexp));
}
/* This function emits moves to copy SIZE_TO_MOVE bytes from SRCMEM to
@@ -22365,7 +22609,7 @@ expand_movmem_epilogue (rtx destmem, rtx srcmem,
count = expand_simple_binop (GET_MODE (count), AND, count, GEN_INT (max_size - 1),
count, 1, OPTAB_DIRECT);
expand_set_or_movmem_via_loop (destmem, srcmem, destptr, srcptr, NULL,
- count, QImode, 1, 4);
+ count, QImode, 1, 4, false);
return;
}
@@ -22450,6 +22694,59 @@ expand_movmem_epilogue (rtx destmem, rtx srcmem,
}
}
+/* This function emits moves to fill SIZE_TO_MOVE bytes starting from DESTMEM
+ with value PROMOTED_VAL.
+ SRC is passed by pointer to be updated on return.
+ Return value is updated DST. */
+static rtx
+emit_memset (rtx destmem, rtx destptr, rtx promoted_val,
+ HOST_WIDE_INT size_to_move)
+{
+ rtx dst = destmem, adjust;
+ enum insn_code code;
+ enum machine_mode move_mode;
+ int piece_size, i;
+
+ /* Find the widest mode in which we could perform moves.
+ Start with the biggest power of 2 less than SIZE_TO_MOVE and half
+ it until move of such size is supported. */
+ move_mode = GET_MODE (promoted_val);
+ if (move_mode == VOIDmode)
+ move_mode = QImode;
+ if (size_to_move < GET_MODE_SIZE (move_mode))
+ {
+ move_mode = mode_for_size (size_to_move * BITS_PER_UNIT, MODE_INT, 0);
+ promoted_val = gen_lowpart (move_mode, promoted_val);
+ }
+ piece_size = GET_MODE_SIZE (move_mode);
+ code = optab_handler (mov_optab, move_mode);
+ gcc_assert (code != CODE_FOR_nothing && promoted_val != NULL_RTX);
+
+ dst = adjust_automodify_address_nv (dst, move_mode, destptr, 0);
+
+ /* Emit moves. We'll need SIZE_TO_MOVE/PIECE_SIZES moves. */
+ gcc_assert (size_to_move % piece_size == 0);
+ adjust = GEN_INT (piece_size);
+ for (i = 0; i < size_to_move; i += piece_size)
+ {
+ if (piece_size <= GET_MODE_SIZE (word_mode))
+ {
+ emit_insn (gen_strset (destptr, dst, promoted_val));
+ continue;
+ }
+
+ emit_insn (GEN_FCN (code) (dst, promoted_val));
+
+ emit_move_insn (destptr,
+ gen_rtx_PLUS (Pmode, copy_rtx (destptr), adjust));
+
+ dst = adjust_automodify_address_nv (dst, move_mode, destptr,
+ piece_size);
+ }
+
+ /* Update DST rtx. */
+ return dst;
+}
/* Output code to set at most count & (max_size - 1) bytes starting by DEST. */
static void
expand_setmem_epilogue_via_loop (rtx destmem, rtx destptr, rtx value,
@@ -22460,66 +22757,35 @@ expand_setmem_epilogue_via_loop (rtx destmem, rtx destptr, rtx value,
GEN_INT (max_size - 1), count, 1, OPTAB_DIRECT);
expand_set_or_movmem_via_loop (destmem, NULL, destptr, NULL,
gen_lowpart (QImode, value), count, QImode,
- 1, max_size / 2);
+ 1, max_size / 2, true);
}
/* Output code to set at most count & (max_size - 1) bytes starting by DEST. */
static void
-expand_setmem_epilogue (rtx destmem, rtx destptr, rtx value, rtx count, int max_size)
+expand_setmem_epilogue (rtx destmem, rtx destptr, rtx value, rtx vec_value,
+ rtx count, int max_size)
{
rtx dest;
if (CONST_INT_P (count))
{
HOST_WIDE_INT countval = INTVAL (count);
- int offset = 0;
+ HOST_WIDE_INT epilogue_size = countval % max_size;
+ int i;
- if ((countval & 0x10) && max_size > 16)
- {
- if (TARGET_64BIT)
- {
- dest = adjust_automodify_address_nv (destmem, DImode, destptr, offset);
- emit_insn (gen_strset (destptr, dest, value));
- dest = adjust_automodify_address_nv (destmem, DImode, destptr, offset + 8);
- emit_insn (gen_strset (destptr, dest, value));
- }
- else
- gcc_unreachable ();
- offset += 16;
- }
- if ((countval & 0x08) && max_size > 8)
+ /* For now MAX_SIZE should be a power of 2. This assert could be
+ relaxed, but it'll require a bit more complicated epilogue
+ expanding. */
+ gcc_assert ((max_size & (max_size - 1)) == 0);
+ for (i = max_size; i >= 1; i >>= 1)
{
- if (TARGET_64BIT)
- {
- dest = adjust_automodify_address_nv (destmem, DImode, destptr, offset);
- emit_insn (gen_strset (destptr, dest, value));
- }
- else
+ if (epilogue_size & i)
{
- dest = adjust_automodify_address_nv (destmem, SImode, destptr, offset);
- emit_insn (gen_strset (destptr, dest, value));
- dest = adjust_automodify_address_nv (destmem, SImode, destptr, offset + 4);
- emit_insn (gen_strset (destptr, dest, value));
+ if (vec_value && i > GET_MODE_SIZE (GET_MODE (value)))
+ destmem = emit_memset (destmem, destptr, vec_value, i);
+ else
+ destmem = emit_memset (destmem, destptr, value, i);
}
- offset += 8;
- }
- if ((countval & 0x04) && max_size > 4)
- {
- dest = adjust_automodify_address_nv (destmem, SImode, destptr, offset);
- emit_insn (gen_strset (destptr, dest, gen_lowpart (SImode, value)));
- offset += 4;
- }
- if ((countval & 0x02) && max_size > 2)
- {
- dest = adjust_automodify_address_nv (destmem, HImode, destptr, offset);
- emit_insn (gen_strset (destptr, dest, gen_lowpart (HImode, value)));
- offset += 2;
- }
- if ((countval & 0x01) && max_size > 1)
- {
- dest = adjust_automodify_address_nv (destmem, QImode, destptr, offset);
- emit_insn (gen_strset (destptr, dest, gen_lowpart (QImode, value)));
- offset += 1;
}
return;
}
@@ -22591,13 +22857,16 @@ expand_setmem_epilogue (rtx destmem, rtx destptr, rtx value, rtx count, int max_
}
}
-/* Copy enough from DEST to SRC to align DEST known to by aligned by ALIGN to
- DESIRED_ALIGNMENT.
+/* Depending on ISSETMEM, copy enough from SRCMEM to DESTMEM or set enough to
+ DESTMEM to align it to DESIRED_ALIGNMENT. Original alignment is ALIGN.
+ Depending on ISSETMEM, either arguments SRCMEM/SRCPTR or VALUE/VEC_VALUE are
+ ignored.
Return value is updated DESTMEM. */
static rtx
-expand_movmem_prologue (rtx destmem, rtx srcmem,
- rtx destptr, rtx srcptr, rtx count,
- int align, int desired_alignment)
+expand_set_or_movmem_prologue (rtx destmem, rtx srcmem,
+ rtx destptr, rtx srcptr, rtx value,
+ rtx vec_value, rtx count, int align,
+ int desired_alignment, bool issetmem)
{
int i;
for (i = 1; i < desired_alignment; i <<= 1)
@@ -22605,7 +22874,15 @@ expand_movmem_prologue (rtx destmem, rtx srcmem,
if (align <= i)
{
rtx label = ix86_expand_aligntest (destptr, i, false);
- destmem = emit_memmov (destmem, &srcmem, destptr, srcptr, i);
+ if (issetmem)
+ {
+ if (vec_value && i > GET_MODE_SIZE (GET_MODE (value)))
+ destmem = emit_memset (destmem, destptr, vec_value, i);
+ else
+ destmem = emit_memset (destmem, destptr, value, i);
+ }
+ else
+ destmem = emit_memmov (destmem, &srcmem, destptr, srcptr, i);
ix86_adjust_counter (count, i);
emit_label (label);
LABEL_NUSES (label) = 1;
@@ -22615,191 +22892,482 @@ expand_movmem_prologue (rtx destmem, rtx srcmem,
return destmem;
}
-/* Copy enough from DST to SRC to align DST known to DESIRED_ALIGN.
- ALIGN_BYTES is how many bytes need to be copied.
- The function updates DST and SRC, namely, it sets proper alignment.
- DST is returned via return value, SRC is updated via pointer SRCP. */
-static rtx
-expand_constant_movmem_prologue (rtx dst, rtx *srcp, rtx destreg, rtx srcreg,
- int desired_align, int align_bytes)
-{
- rtx src = *srcp;
- rtx orig_dst = dst;
- rtx orig_src = src;
- int piece_size = 1;
- int copied_bytes = 0;
- int src_align_bytes = get_mem_align_offset (src, desired_align * BITS_PER_UNIT);
- if (src_align_bytes >= 0)
- src_align_bytes = desired_align - src_align_bytes;
+/* Test if COUNT&SIZE is nonzero and if so, expand movme
+ or setmem sequence that is valid for SIZE..2*SIZE-1 bytes
+ and jump to DONE_LABEL. */
+static void
+expand_small_movmem_or_setmem (rtx destmem, rtx srcmem,
+ rtx destptr, rtx srcptr,
+ rtx value, rtx vec_value,
+ rtx count, int size,
+ rtx done_label, bool issetmem)
+{
+ rtx label = ix86_expand_aligntest (count, size, false);
+ enum machine_mode mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 1);
+ rtx modesize;
+ int n;
- for (piece_size = 1;
- piece_size <= desired_align && copied_bytes < align_bytes;
- piece_size <<= 1)
+ /* If we do not have vector value to copy, we must reduce size. */
+ if (issetmem)
{
- if (align_bytes & piece_size)
+ if (!vec_value)
{
- dst = emit_memmov (dst, &src, destreg, srcreg, piece_size);
- copied_bytes += piece_size;
+ if (GET_MODE (value) == VOIDmode && size > 8)
+ mode = Pmode;
+ else if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (value)))
+ mode = GET_MODE (value);
}
+ else
+ mode = GET_MODE (vec_value), value = vec_value;
}
-
- if (MEM_ALIGN (dst) < (unsigned int) desired_align * BITS_PER_UNIT)
- set_mem_align (dst, desired_align * BITS_PER_UNIT);
- if (src_align_bytes >= 0)
+ else
+ {
+ /* Choose appropriate vector mode. */
+ if (size >= 32)
+ mode = TARGET_AVX ? V32QImode : TARGET_SSE ? V16QImode : DImode;
+ else if (size >= 16)
+ mode = TARGET_SSE ? V16QImode : DImode;
+ srcmem = change_address (srcmem, mode, srcptr);
+ }
+ destmem = change_address (destmem, mode, destptr);
+ modesize = GEN_INT (GET_MODE_SIZE (mode));
+ gcc_assert (GET_MODE_SIZE (mode) <= size);
+ for (n = 0; n * GET_MODE_SIZE (mode) < size; n++)
{
- unsigned int src_align;
- for (src_align = desired_align; src_align >= 2; src_align >>= 1)
+ if (issetmem)
+ emit_move_insn (destmem, gen_lowpart (mode, value));
+ else
{
- if ((src_align_bytes & (src_align - 1))
- == (align_bytes & (src_align - 1)))
- break;
+ emit_move_insn (destmem, srcmem);
+ srcmem = offset_address (srcmem, modesize, GET_MODE_SIZE (mode));
}
- if (src_align > (unsigned int) desired_align)
- src_align = desired_align;
- if (MEM_ALIGN (src) < src_align * BITS_PER_UNIT)
- set_mem_align (src, src_align * BITS_PER_UNIT);
+ destmem = offset_address (destmem, modesize, GET_MODE_SIZE (mode));
}
- if (MEM_SIZE_KNOWN_P (orig_dst))
- set_mem_size (dst, MEM_SIZE (orig_dst) - align_bytes);
- if (MEM_SIZE_KNOWN_P (orig_src))
- set_mem_size (src, MEM_SIZE (orig_src) - align_bytes);
- *srcp = src;
- return dst;
+
+ destmem = offset_address (destmem, count, 1);
+ destmem = offset_address (destmem, GEN_INT (-size - GET_MODE_SIZE (mode)),
+ GET_MODE_SIZE (mode));
+ if (issetmem)
+ emit_move_insn (destmem, gen_lowpart (mode, value));
+ else
+ {
+ srcmem = offset_address (srcmem, count, 1);
+ srcmem = offset_address (srcmem, GEN_INT (-size - GET_MODE_SIZE (mode)),
+ GET_MODE_SIZE (mode));
+ emit_move_insn (destmem, srcmem);
+ }
+ emit_jump_insn (gen_jump (done_label));
+ emit_barrier ();
+
+ emit_label (label);
+ LABEL_NUSES (label) = 1;
}
-/* Set enough from DEST to align DEST known to by aligned by ALIGN to
- DESIRED_ALIGNMENT. */
+/* Handle small memcpy (up to SIZE that is supposed to be small power of 2.
+ and get ready for the main memcpy loop by copying iniital DESIRED_ALIGN-ALIGN
+ bytes and last SIZE bytes adjusitng DESTPTR/SRCPTR/COUNT in a way we can
+ proceed with an loop copying SIZE bytes at once. Do moves in MODE.
+ DONE_LABEL is a label after the whole copying sequence. The label is created
+ on demand if *DONE_LABEL is NULL.
+ MIN_SIZE is minimal size of block copied. This value gets adjusted for new
+ bounds after the initial copies.
+
+ DESTMEM/SRCMEM are memory expressions pointing to the copies block,
+ DESTPTR/SRCPTR are pointers to the block. DYNAMIC_CHECK indicate whether
+ we will dispatch to a library call for large blocks.
+
+ In pseudocode we do:
+
+ if (COUNT < SIZE)
+ {
+ Assume that SIZE is 4. Bigger sizes are handled analogously
+ if (COUNT & 4)
+ {
+ copy 4 bytes from SRCPTR to DESTPTR
+ copy 4 bytes from SRCPTR + COUNT - 4 to DESTPTR + COUNT - 4
+ goto done_label
+ }
+ if (!COUNT)
+ goto done_label;
+ copy 1 byte from SRCPTR to DESTPTR
+ if (COUNT & 2)
+ {
+ copy 2 bytes from SRCPTR to DESTPTR
+ copy 2 bytes from SRCPTR + COUNT - 2 to DESTPTR + COUNT - 2
+ }
+ }
+ else
+ {
+ copy at least DESIRED_ALIGN-ALIGN bytes from SRCPTR to DESTPTR
+ copy SIZE bytes from SRCPTR + COUNT - SIZE to DESTPTR + COUNT -SIZE
+
+ OLD_DESPTR = DESTPTR;
+ Align DESTPTR up to DESIRED_ALIGN
+ SRCPTR += DESTPTR - OLD_DESTPTR
+ COUNT -= DEST_PTR - OLD_DESTPTR
+ if (DYNAMIC_CHECK)
+ Round COUNT down to multiple of SIZE
+ << optional caller supplied zero size guard is here >>
+ << optional caller suppplied dynamic check is here >>
+ << caller supplied main copy loop is here >>
+ }
+ done_label:
+ */
static void
-expand_setmem_prologue (rtx destmem, rtx destptr, rtx value, rtx count,
- int align, int desired_alignment)
-{
- if (align <= 1 && desired_alignment > 1)
- {
- rtx label = ix86_expand_aligntest (destptr, 1, false);
- destmem = change_address (destmem, QImode, destptr);
- emit_insn (gen_strset (destptr, destmem, gen_lowpart (QImode, value)));
- ix86_adjust_counter (count, 1);
+expand_set_or_movmem_prologue_epilogue_by_misaligned_moves (rtx destmem, rtx srcmem,
+ rtx *destptr, rtx *srcptr,
+ enum machine_mode mode,
+ rtx value, rtx vec_value,
+ rtx *count,
+ rtx *done_label,
+ int size,
+ int desired_align,
+ int align,
+ unsigned HOST_WIDE_INT *min_size,
+ bool dynamic_check,
+ bool issetmem)
+{
+ rtx loop_label = NULL, label;
+ int n;
+ rtx modesize;
+ int prolog_size = 0;
+ rtx mode_value;
+
+ /* Chose proper value to copy. */
+ if (issetmem && VECTOR_MODE_P (mode))
+ mode_value = vec_value;
+ else
+ mode_value = value;
+ gcc_assert (GET_MODE_SIZE (mode) <= size);
+
+ /* See if block is big or small, handle small blocks. */
+ if (!CONST_INT_P (*count) && *min_size < (unsigned HOST_WIDE_INT)size)
+ {
+ int size2 = size;
+ loop_label = gen_label_rtx ();
+
+ if (!*done_label)
+ *done_label = gen_label_rtx ();
+
+ emit_cmp_and_jump_insns (*count, GEN_INT (size2), GE, 0, GET_MODE (*count),
+ 1, loop_label);
+ size2 >>= 1;
+
+ /* Handle sizes > 3. */
+ for (;size2 > 2; size2 >>= 1)
+ expand_small_movmem_or_setmem (destmem, srcmem,
+ *destptr, *srcptr,
+ value, vec_value,
+ *count,
+ size2, *done_label, issetmem);
+ /* Nothing to copy? Jump to DONE_LABEL if so */
+ emit_cmp_and_jump_insns (*count, const0_rtx, EQ, 0, GET_MODE (*count),
+ 1, *done_label);
+
+ /* Do a byte copy. */
+ destmem = change_address (destmem, QImode, *destptr);
+ if (issetmem)
+ emit_move_insn (destmem, gen_lowpart (QImode, value));
+ else
+ {
+ srcmem = change_address (srcmem, QImode, *srcptr);
+ emit_move_insn (destmem, srcmem);
+ }
+
+ /* Handle sizes 2 and 3. */
+ label = ix86_expand_aligntest (*count, 2, false);
+ destmem = change_address (destmem, HImode, *destptr);
+ destmem = offset_address (destmem, *count, 1);
+ destmem = offset_address (destmem, GEN_INT (-2), 2);
+ if (issetmem)
+ emit_move_insn (destmem, gen_lowpart (HImode, value));
+ else
+ {
+ srcmem = change_address (srcmem, HImode, *srcptr);
+ srcmem = offset_address (srcmem, *count, 1);
+ srcmem = offset_address (srcmem, GEN_INT (-2), 2);
+ emit_move_insn (destmem, srcmem);
+ }
+
emit_label (label);
LABEL_NUSES (label) = 1;
+ emit_jump_insn (gen_jump (*done_label));
+ emit_barrier ();
}
- if (align <= 2 && desired_alignment > 2)
+ else
+ gcc_assert (*min_size >= (unsigned HOST_WIDE_INT)size
+ || UINTVAL (*count) >= (unsigned HOST_WIDE_INT)size);
+
+ /* Start memcpy for COUNT >= SIZE. */
+ if (loop_label)
{
- rtx label = ix86_expand_aligntest (destptr, 2, false);
- destmem = change_address (destmem, HImode, destptr);
- emit_insn (gen_strset (destptr, destmem, gen_lowpart (HImode, value)));
- ix86_adjust_counter (count, 2);
- emit_label (label);
- LABEL_NUSES (label) = 1;
+ emit_label (loop_label);
+ LABEL_NUSES (loop_label) = 1;
}
- if (align <= 4 && desired_alignment > 4)
+
+ /* Copy first desired_align bytes. */
+ if (!issetmem)
+ srcmem = change_address (srcmem, mode, *srcptr);
+ destmem = change_address (destmem, mode, *destptr);
+ modesize = GEN_INT (GET_MODE_SIZE (mode));
+ for (n = 0; prolog_size < desired_align - align; n++)
{
- rtx label = ix86_expand_aligntest (destptr, 4, false);
- destmem = change_address (destmem, SImode, destptr);
- emit_insn (gen_strset (destptr, destmem, gen_lowpart (SImode, value)));
- ix86_adjust_counter (count, 4);
- emit_label (label);
- LABEL_NUSES (label) = 1;
+ if (issetmem)
+ emit_move_insn (destmem, mode_value);
+ else
+ {
+ emit_move_insn (destmem, srcmem);
+ srcmem = offset_address (srcmem, modesize, GET_MODE_SIZE (mode));
+ }
+ destmem = offset_address (destmem, modesize, GET_MODE_SIZE (mode));
+ prolog_size += GET_MODE_SIZE (mode);
+ }
+
+
+ /* Copy last SIZE bytes. */
+ destmem = offset_address (destmem, *count, 1);
+ destmem = offset_address (destmem,
+ GEN_INT (-size - prolog_size),
+ 1);
+ if (issetmem)
+ emit_move_insn (destmem, mode_value);
+ else
+ {
+ srcmem = offset_address (srcmem, *count, 1);
+ srcmem = offset_address (srcmem,
+ GEN_INT (-size - prolog_size),
+ 1);
+ emit_move_insn (destmem, srcmem);
+ }
+ for (n = 1; n * GET_MODE_SIZE (mode) < size; n++)
+ {
+ destmem = offset_address (destmem, modesize, 1);
+ if (issetmem)
+ emit_move_insn (destmem, mode_value);
+ else
+ {
+ srcmem = offset_address (srcmem, modesize, 1);
+ emit_move_insn (destmem, srcmem);
+ }
+ }
+
+ /* Align destination. */
+ if (desired_align > 1 && desired_align > align)
+ {
+ rtx saveddest = *destptr;
+
+ gcc_assert (desired_align <= size);
+ /* Align destptr up, place it to new register. */
+ *destptr = expand_simple_binop (GET_MODE (*destptr), PLUS, *destptr,
+ GEN_INT (prolog_size),
+ NULL_RTX, 1, OPTAB_DIRECT);
+ *destptr = expand_simple_binop (GET_MODE (*destptr), AND, *destptr,
+ GEN_INT (-desired_align),
+ *destptr, 1, OPTAB_DIRECT);
+ /* See how many bytes we skipped. */
+ saveddest = expand_simple_binop (GET_MODE (*destptr), MINUS, saveddest,
+ *destptr,
+ saveddest, 1, OPTAB_DIRECT);
+ /* Adjust srcptr and count. */
+ if (!issetmem)
+ *srcptr = expand_simple_binop (GET_MODE (*srcptr), MINUS, *srcptr, saveddest,
+ *srcptr, 1, OPTAB_DIRECT);
+ *count = expand_simple_binop (GET_MODE (*count), PLUS, *count,
+ saveddest, *count, 1, OPTAB_DIRECT);
+ /* We copied at most size + prolog_size. */
+ if (*min_size > (unsigned HOST_WIDE_INT)(size + prolog_size))
+ *min_size = (*min_size - size) & ~(unsigned HOST_WIDE_INT)(size - 1);
+ else
+ *min_size = 0;
+
+ /* Our loops always round down the bock size, but for dispatch to library
+ we need precise value. */
+ if (dynamic_check)
+ *count = expand_simple_binop (GET_MODE (*count), AND, *count,
+ GEN_INT (-size), *count, 1, OPTAB_DIRECT);
+ }
+ else
+ {
+ gcc_assert (prolog_size == 0);
+ /* Decrease count, so we won't end up copying last word twice. */
+ if (!CONST_INT_P (*count))
+ *count = expand_simple_binop (GET_MODE (*count), PLUS, *count,
+ constm1_rtx, *count, 1, OPTAB_DIRECT);
+ else
+ *count = GEN_INT ((UINTVAL (*count) - 1) & ~(unsigned HOST_WIDE_INT)(size - 1));
+ if (*min_size)
+ *min_size = (*min_size - 1) & ~(unsigned HOST_WIDE_INT)(size - 1);
}
- gcc_assert (desired_alignment <= 8);
}
-/* Set enough from DST to align DST known to by aligned by ALIGN to
- DESIRED_ALIGN. ALIGN_BYTES is how many bytes need to be stored. */
+
+/* This function is like the previous one, except here we know how many bytes
+ need to be copied. That allows us to update alignment not only of DST, which
+ is returned, but also of SRC, which is passed as a pointer for that
+ reason. */
static rtx
-expand_constant_setmem_prologue (rtx dst, rtx destreg, rtx value,
- int desired_align, int align_bytes)
+expand_set_or_movmem_constant_prologue (rtx dst, rtx *srcp, rtx destreg,
+ rtx srcreg, rtx value, rtx vec_value,
+ int desired_align, int align_bytes,
+ bool issetmem)
{
- int off = 0;
+ rtx src = NULL;
rtx orig_dst = dst;
- if (align_bytes & 1)
- {
- dst = adjust_automodify_address_nv (dst, QImode, destreg, 0);
- off = 1;
- emit_insn (gen_strset (destreg, dst,
- gen_lowpart (QImode, value)));
- }
- if (align_bytes & 2)
+ rtx orig_src = NULL;
+ int piece_size = 1;
+ int copied_bytes = 0;
+
+ if (!issetmem)
{
- dst = adjust_automodify_address_nv (dst, HImode, destreg, off);
- if (MEM_ALIGN (dst) < 2 * BITS_PER_UNIT)
- set_mem_align (dst, 2 * BITS_PER_UNIT);
- off = 2;
- emit_insn (gen_strset (destreg, dst,
- gen_lowpart (HImode, value)));
+ gcc_assert (srcp != NULL);
+ src = *srcp;
+ orig_src = src;
}
- if (align_bytes & 4)
+
+ for (piece_size = 1;
+ piece_size <= desired_align && copied_bytes < align_bytes;
+ piece_size <<= 1)
{
- dst = adjust_automodify_address_nv (dst, SImode, destreg, off);
- if (MEM_ALIGN (dst) < 4 * BITS_PER_UNIT)
- set_mem_align (dst, 4 * BITS_PER_UNIT);
- off = 4;
- emit_insn (gen_strset (destreg, dst,
- gen_lowpart (SImode, value)));
+ if (align_bytes & piece_size)
+ {
+ if (issetmem)
+ {
+ if (vec_value && piece_size > GET_MODE_SIZE (GET_MODE (value)))
+ dst = emit_memset (dst, destreg, vec_value, piece_size);
+ else
+ dst = emit_memset (dst, destreg, value, piece_size);
+ }
+ else
+ dst = emit_memmov (dst, &src, destreg, srcreg, piece_size);
+ copied_bytes += piece_size;
+ }
}
- dst = adjust_automodify_address_nv (dst, BLKmode, destreg, off);
if (MEM_ALIGN (dst) < (unsigned int) desired_align * BITS_PER_UNIT)
set_mem_align (dst, desired_align * BITS_PER_UNIT);
if (MEM_SIZE_KNOWN_P (orig_dst))
set_mem_size (dst, MEM_SIZE (orig_dst) - align_bytes);
+
+ if (!issetmem)
+ {
+ int src_align_bytes = get_mem_align_offset (src, desired_align
+ * BITS_PER_UNIT);
+ if (src_align_bytes >= 0)
+ src_align_bytes = desired_align - src_align_bytes;
+ if (src_align_bytes >= 0)
+ {
+ unsigned int src_align;
+ for (src_align = desired_align; src_align >= 2; src_align >>= 1)
+ {
+ if ((src_align_bytes & (src_align - 1))
+ == (align_bytes & (src_align - 1)))
+ break;
+ }
+ if (src_align > (unsigned int) desired_align)
+ src_align = desired_align;
+ if (MEM_ALIGN (src) < src_align * BITS_PER_UNIT)
+ set_mem_align (src, src_align * BITS_PER_UNIT);
+ }
+ if (MEM_SIZE_KNOWN_P (orig_src))
+ set_mem_size (src, MEM_SIZE (orig_src) - align_bytes);
+ *srcp = src;
+ }
+
return dst;
}
-/* Given COUNT and EXPECTED_SIZE, decide on codegen of string operation. */
-static enum stringop_alg
-decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size, bool memset,
- int *dynamic_check, bool *noalign)
+/* Return true if ALG can be used in current context.
+ Assume we expand memset if MEMSET is true. */
+static bool
+alg_usable_p (enum stringop_alg alg, bool memset)
{
- const struct stringop_algs * algs;
- bool optimize_for_speed;
+ if (alg == no_stringop)
+ return false;
+ if (alg == vector_loop)
+ return TARGET_SSE || TARGET_AVX;
/* Algorithms using the rep prefix want at least edi and ecx;
additionally, memset wants eax and memcpy wants esi. Don't
consider such algorithms if the user has appropriated those
registers for their own purposes. */
- bool rep_prefix_usable = !(fixed_regs[CX_REG] || fixed_regs[DI_REG]
- || (memset
- ? fixed_regs[AX_REG] : fixed_regs[SI_REG]));
- *noalign = false;
+ if (alg == rep_prefix_1_byte
+ || alg == rep_prefix_4_byte
+ || alg == rep_prefix_8_byte)
+ return !(fixed_regs[CX_REG] || fixed_regs[DI_REG]
+ || (memset ? fixed_regs[AX_REG] : fixed_regs[SI_REG]));
+ return true;
+}
-#define ALG_USABLE_P(alg) (rep_prefix_usable \
- || (alg != rep_prefix_1_byte \
- && alg != rep_prefix_4_byte \
- && alg != rep_prefix_8_byte))
+/* Given COUNT and EXPECTED_SIZE, decide on codegen of string operation. */
+static enum stringop_alg
+decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size,
+ unsigned HOST_WIDE_INT min_size, unsigned HOST_WIDE_INT max_size,
+ bool memset, bool zero_memset, int *dynamic_check, bool *noalign)
+{
+ const struct stringop_algs * algs;
+ bool optimize_for_speed;
+ int max = -1;
const struct processor_costs *cost;
+ int i;
+ bool any_alg_usable_p = false;
+
+ *noalign = false;
+ *dynamic_check = -1;
/* Even if the string operation call is cold, we still might spend a lot
of time processing large blocks. */
if (optimize_function_for_size_p (cfun)
|| (optimize_insn_for_size_p ()
- && expected_size != -1 && expected_size < 256))
+ && (max_size < 256
+ || (expected_size != -1 && expected_size < 256))))
optimize_for_speed = false;
else
optimize_for_speed = true;
cost = optimize_for_speed ? ix86_cost : &ix86_size_cost;
-
- *dynamic_check = -1;
if (memset)
algs = &cost->memset[TARGET_64BIT != 0];
else
algs = &cost->memcpy[TARGET_64BIT != 0];
- if (ix86_stringop_alg != no_stringop && ALG_USABLE_P (ix86_stringop_alg))
+
+ /* See maximal size for user defined algorithm. */
+ for (i = 0; i < MAX_STRINGOP_ALGS; i++)
+ {
+ enum stringop_alg candidate = algs->size[i].alg;
+ bool usable = alg_usable_p (candidate, memset);
+ any_alg_usable_p |= usable;
+
+ if (candidate != libcall && candidate && usable)
+ max = algs->size[i].max;
+ }
+
+ /* If expected size is not known but max size is small enough
+ so inline version is a win, set expected size into
+ the range. */
+ if (max > 1 && (unsigned HOST_WIDE_INT)max >= max_size && expected_size == -1)
+ expected_size = min_size / 2 + max_size / 2;
+
+ /* If user specified the algorithm, honnor it if possible. */
+ if (ix86_stringop_alg != no_stringop
+ && alg_usable_p (ix86_stringop_alg, memset))
return ix86_stringop_alg;
/* rep; movq or rep; movl is the smallest variant. */
else if (!optimize_for_speed)
{
- if (!count || (count & 3))
- return rep_prefix_usable ? rep_prefix_1_byte : loop_1_byte;
+ *noalign = true;
+ if (!count || (count & 3) || (memset && !zero_memset))
+ return alg_usable_p (rep_prefix_1_byte, memset)
+ ? rep_prefix_1_byte : loop_1_byte;
else
- return rep_prefix_usable ? rep_prefix_4_byte : loop;
+ return alg_usable_p (rep_prefix_4_byte, memset)
+ ? rep_prefix_4_byte : loop;
}
- /* Very tiny blocks are best handled via the loop, REP is expensive to setup.
- */
+ /* Very tiny blocks are best handled via the loop, REP is expensive to
+ setup. */
else if (expected_size != -1 && expected_size < 4)
return loop_1_byte;
else if (expected_size != -1)
{
- unsigned int i;
enum stringop_alg alg = libcall;
+ bool alg_noalign = false;
for (i = 0; i < MAX_STRINGOP_ALGS; i++)
{
/* We get here if the algorithms that were not libcall-based
@@ -22812,8 +23380,11 @@ decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size, bool memset,
{
enum stringop_alg candidate = algs->size[i].alg;
- if (candidate != libcall && ALG_USABLE_P (candidate))
- alg = candidate;
+ if (candidate != libcall && alg_usable_p (candidate, memset))
+ {
+ alg = candidate;
+ alg_noalign = algs->size[i].noalign;
+ }
/* Honor TARGET_INLINE_ALL_STRINGOPS by picking
last non-libcall inline algorithm. */
if (TARGET_INLINE_ALL_STRINGOPS)
@@ -22822,17 +23393,19 @@ decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size, bool memset,
but we are still forced to inline, run the heuristic below
that will pick code for medium sized blocks. */
if (alg != libcall)
- return alg;
+ {
+ *noalign = alg_noalign;
+ return alg;
+ }
break;
}
- else if (ALG_USABLE_P (candidate))
+ else if (alg_usable_p (candidate, memset))
{
*noalign = algs->size[i].noalign;
return candidate;
}
}
}
- gcc_assert (TARGET_INLINE_ALL_STRINGOPS || !rep_prefix_usable);
}
/* When asked to inline the call anyway, try to pick meaningful choice.
We look for maximal size of block that is faster to copy by hand and
@@ -22842,22 +23415,11 @@ decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size, bool memset,
If this turns out to be bad, we might simply specify the preferred
choice in ix86_costs. */
if ((TARGET_INLINE_ALL_STRINGOPS || TARGET_INLINE_STRINGOPS_DYNAMICALLY)
- && (algs->unknown_size == libcall || !ALG_USABLE_P (algs->unknown_size)))
+ && (algs->unknown_size == libcall
+ || !alg_usable_p (algs->unknown_size, memset)))
{
- int max = -1;
enum stringop_alg alg;
- int i;
- bool any_alg_usable_p = true;
- for (i = 0; i < MAX_STRINGOP_ALGS; i++)
- {
- enum stringop_alg candidate = algs->size[i].alg;
- any_alg_usable_p = any_alg_usable_p && ALG_USABLE_P (candidate);
-
- if (candidate != libcall && candidate
- && ALG_USABLE_P (candidate))
- max = algs->size[i].max;
- }
/* If there aren't any usable algorithms, then recursing on
smaller sizes isn't going to find anything. Just return the
simple byte-at-a-time copy loop. */
@@ -22870,15 +23432,16 @@ decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size, bool memset,
}
if (max == -1)
max = 4096;
- alg = decide_alg (count, max / 2, memset, dynamic_check, noalign);
+ alg = decide_alg (count, max / 2, min_size, max_size, memset,
+ zero_memset, dynamic_check, noalign);
gcc_assert (*dynamic_check == -1);
gcc_assert (alg != libcall);
if (TARGET_INLINE_STRINGOPS_DYNAMICALLY)
*dynamic_check = max;
return alg;
}
- return ALG_USABLE_P (algs->unknown_size) ? algs->unknown_size : libcall;
-#undef ALG_USABLE_P
+ return (alg_usable_p (algs->unknown_size, memset)
+ ? algs->unknown_size : libcall);
}
/* Decide on alignment. We know that the operand is already aligned to ALIGN
@@ -22915,341 +23478,6 @@ decide_alignment (int align,
return desired_align;
}
-/* Expand string move (memcpy) operation. Use i386 string operations
- when profitable. expand_setmem contains similar code. The code
- depends upon architecture, block size and alignment, but always has
- the same overall structure:
-
- 1) Prologue guard: Conditional that jumps up to epilogues for small
- blocks that can be handled by epilogue alone. This is faster
- but also needed for correctness, since prologue assume the block
- is larger than the desired alignment.
-
- Optional dynamic check for size and libcall for large
- blocks is emitted here too, with -minline-stringops-dynamically.
-
- 2) Prologue: copy first few bytes in order to get destination
- aligned to DESIRED_ALIGN. It is emitted only when ALIGN is less
- than DESIRED_ALIGN and up to DESIRED_ALIGN - ALIGN bytes can be
- copied. We emit either a jump tree on power of two sized
- blocks, or a byte loop.
-
- 3) Main body: the copying loop itself, copying in SIZE_NEEDED chunks
- with specified algorithm.
-
- 4) Epilogue: code copying tail of the block that is too small to be
- handled by main body (or up to size guarded by prologue guard). */
-
-bool
-ix86_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp,
- rtx expected_align_exp, rtx expected_size_exp)
-{
- rtx destreg;
- rtx srcreg;
- rtx label = NULL;
- rtx tmp;
- rtx jump_around_label = NULL;
- HOST_WIDE_INT align = 1;
- unsigned HOST_WIDE_INT count = 0;
- HOST_WIDE_INT expected_size = -1;
- int size_needed = 0, epilogue_size_needed;
- int desired_align = 0, align_bytes = 0;
- enum stringop_alg alg;
- int dynamic_check;
- bool need_zero_guard = false;
- bool noalign;
- enum machine_mode move_mode = VOIDmode;
- int unroll_factor = 1;
-
- if (CONST_INT_P (align_exp))
- align = INTVAL (align_exp);
- /* i386 can do misaligned access on reasonably increased cost. */
- if (CONST_INT_P (expected_align_exp)
- && INTVAL (expected_align_exp) > align)
- align = INTVAL (expected_align_exp);
- /* ALIGN is the minimum of destination and source alignment, but we care here
- just about destination alignment. */
- else if (MEM_ALIGN (dst) > (unsigned HOST_WIDE_INT) align * BITS_PER_UNIT)
- align = MEM_ALIGN (dst) / BITS_PER_UNIT;
-
- if (CONST_INT_P (count_exp))
- count = expected_size = INTVAL (count_exp);
- if (CONST_INT_P (expected_size_exp) && count == 0)
- expected_size = INTVAL (expected_size_exp);
-
- /* Make sure we don't need to care about overflow later on. */
- if (count > ((unsigned HOST_WIDE_INT) 1 << 30))
- return false;
-
- /* Step 0: Decide on preferred algorithm, desired alignment and
- size of chunks to be copied by main loop. */
- alg = decide_alg (count, expected_size, false, &dynamic_check, &noalign);
- if (alg == libcall)
- return false;
- gcc_assert (alg != no_stringop);
-
- if (!count)
- count_exp = copy_to_mode_reg (GET_MODE (count_exp), count_exp);
- destreg = copy_addr_to_reg (XEXP (dst, 0));
- srcreg = copy_addr_to_reg (XEXP (src, 0));
-
- unroll_factor = 1;
- move_mode = word_mode;
- switch (alg)
- {
- case libcall:
- case no_stringop:
- case last_alg:
- gcc_unreachable ();
- case loop_1_byte:
- need_zero_guard = true;
- move_mode = QImode;
- break;
- case loop:
- need_zero_guard = true;
- break;
- case unrolled_loop:
- need_zero_guard = true;
- unroll_factor = (TARGET_64BIT ? 4 : 2);
- break;
- case vector_loop:
- need_zero_guard = true;
- unroll_factor = 4;
- /* Find the widest supported mode. */
- move_mode = word_mode;
- while (optab_handler (mov_optab, GET_MODE_WIDER_MODE (move_mode))
- != CODE_FOR_nothing)
- move_mode = GET_MODE_WIDER_MODE (move_mode);
-
- /* Find the corresponding vector mode with the same size as MOVE_MODE.
- MOVE_MODE is an integer mode at the moment (SI, DI, TI, etc.). */
- if (GET_MODE_SIZE (move_mode) > GET_MODE_SIZE (word_mode))
- {
- int nunits = GET_MODE_SIZE (move_mode) / GET_MODE_SIZE (word_mode);
- move_mode = mode_for_vector (word_mode, nunits);
- if (optab_handler (mov_optab, move_mode) == CODE_FOR_nothing)
- move_mode = word_mode;
- }
- gcc_assert (optab_handler (mov_optab, move_mode) != CODE_FOR_nothing);
- break;
- case rep_prefix_8_byte:
- move_mode = DImode;
- break;
- case rep_prefix_4_byte:
- move_mode = SImode;
- break;
- case rep_prefix_1_byte:
- move_mode = QImode;
- break;
- }
- size_needed = GET_MODE_SIZE (move_mode) * unroll_factor;
- epilogue_size_needed = size_needed;
-
- desired_align = decide_alignment (align, alg, expected_size, move_mode);
- if (!TARGET_ALIGN_STRINGOPS || noalign)
- align = desired_align;
-
- /* Step 1: Prologue guard. */
-
- /* Alignment code needs count to be in register. */
- if (CONST_INT_P (count_exp) && desired_align > align)
- {
- if (INTVAL (count_exp) > desired_align
- && INTVAL (count_exp) > size_needed)
- {
- align_bytes
- = get_mem_align_offset (dst, desired_align * BITS_PER_UNIT);
- if (align_bytes <= 0)
- align_bytes = 0;
- else
- align_bytes = desired_align - align_bytes;
- }
- if (align_bytes == 0)
- count_exp = force_reg (counter_mode (count_exp), count_exp);
- }
- gcc_assert (desired_align >= 1 && align >= 1);
-
- /* Ensure that alignment prologue won't copy past end of block. */
- if (size_needed > 1 || (desired_align > 1 && desired_align > align))
- {
- epilogue_size_needed = MAX (size_needed - 1, desired_align - align);
- /* Epilogue always copies COUNT_EXP & EPILOGUE_SIZE_NEEDED bytes.
- Make sure it is power of 2. */
- epilogue_size_needed = 1 << (floor_log2 (epilogue_size_needed) + 1);
-
- if (count)
- {
- if (count < (unsigned HOST_WIDE_INT)epilogue_size_needed)
- {
- /* If main algorithm works on QImode, no epilogue is needed.
- For small sizes just don't align anything. */
- if (size_needed == 1)
- desired_align = align;
- else
- goto epilogue;
- }
- }
- else
- {
- label = gen_label_rtx ();
- emit_cmp_and_jump_insns (count_exp,
- GEN_INT (epilogue_size_needed),
- LTU, 0, counter_mode (count_exp), 1, label);
- if (expected_size == -1 || expected_size < epilogue_size_needed)
- predict_jump (REG_BR_PROB_BASE * 60 / 100);
- else
- predict_jump (REG_BR_PROB_BASE * 20 / 100);
- }
- }
-
- /* Emit code to decide on runtime whether library call or inline should be
- used. */
- if (dynamic_check != -1)
- {
- if (CONST_INT_P (count_exp))
- {
- if (UINTVAL (count_exp) >= (unsigned HOST_WIDE_INT)dynamic_check)
- {
- emit_block_move_via_libcall (dst, src, count_exp, false);
- count_exp = const0_rtx;
- goto epilogue;
- }
- }
- else
- {
- rtx hot_label = gen_label_rtx ();
- jump_around_label = gen_label_rtx ();
- emit_cmp_and_jump_insns (count_exp, GEN_INT (dynamic_check - 1),
- LEU, 0, GET_MODE (count_exp), 1, hot_label);
- predict_jump (REG_BR_PROB_BASE * 90 / 100);
- emit_block_move_via_libcall (dst, src, count_exp, false);
- emit_jump (jump_around_label);
- emit_label (hot_label);
- }
- }
-
- /* Step 2: Alignment prologue. */
-
- if (desired_align > align)
- {
- if (align_bytes == 0)
- {
- /* Except for the first move in epilogue, we no longer know
- constant offset in aliasing info. It don't seems to worth
- the pain to maintain it for the first move, so throw away
- the info early. */
- src = change_address (src, BLKmode, srcreg);
- dst = change_address (dst, BLKmode, destreg);
- dst = expand_movmem_prologue (dst, src, destreg, srcreg, count_exp, align,
- desired_align);
- }
- else
- {
- /* If we know how many bytes need to be stored before dst is
- sufficiently aligned, maintain aliasing info accurately. */
- dst = expand_constant_movmem_prologue (dst, &src, destreg, srcreg,
- desired_align, align_bytes);
- count_exp = plus_constant (counter_mode (count_exp),
- count_exp, -align_bytes);
- count -= align_bytes;
- }
- if (need_zero_guard
- && (count < (unsigned HOST_WIDE_INT) size_needed
- || (align_bytes == 0
- && count < ((unsigned HOST_WIDE_INT) size_needed
- + desired_align - align))))
- {
- /* It is possible that we copied enough so the main loop will not
- execute. */
- gcc_assert (size_needed > 1);
- if (label == NULL_RTX)
- label = gen_label_rtx ();
- emit_cmp_and_jump_insns (count_exp,
- GEN_INT (size_needed),
- LTU, 0, counter_mode (count_exp), 1, label);
- if (expected_size == -1
- || expected_size < (desired_align - align) / 2 + size_needed)
- predict_jump (REG_BR_PROB_BASE * 20 / 100);
- else
- predict_jump (REG_BR_PROB_BASE * 60 / 100);
- }
- }
- if (label && size_needed == 1)
- {
- emit_label (label);
- LABEL_NUSES (label) = 1;
- label = NULL;
- epilogue_size_needed = 1;
- }
- else if (label == NULL_RTX)
- epilogue_size_needed = size_needed;
-
- /* Step 3: Main loop. */
-
- switch (alg)
- {
- case libcall:
- case no_stringop:
- case last_alg:
- gcc_unreachable ();
- case loop_1_byte:
- case loop:
- case unrolled_loop:
- case vector_loop:
- expand_set_or_movmem_via_loop (dst, src, destreg, srcreg, NULL,
- count_exp, move_mode, unroll_factor,
- expected_size);
- break;
- case rep_prefix_8_byte:
- case rep_prefix_4_byte:
- case rep_prefix_1_byte:
- expand_movmem_via_rep_mov (dst, src, destreg, srcreg, count_exp,
- move_mode);
- break;
- }
- /* Adjust properly the offset of src and dest memory for aliasing. */
- if (CONST_INT_P (count_exp))
- {
- src = adjust_automodify_address_nv (src, BLKmode, srcreg,
- (count / size_needed) * size_needed);
- dst = adjust_automodify_address_nv (dst, BLKmode, destreg,
- (count / size_needed) * size_needed);
- }
- else
- {
- src = change_address (src, BLKmode, srcreg);
- dst = change_address (dst, BLKmode, destreg);
- }
-
- /* Step 4: Epilogue to copy the remaining bytes. */
- epilogue:
- if (label)
- {
- /* When the main loop is done, COUNT_EXP might hold original count,
- while we want to copy only COUNT_EXP & SIZE_NEEDED bytes.
- Epilogue code will actually copy COUNT_EXP & EPILOGUE_SIZE_NEEDED
- bytes. Compensate if needed. */
-
- if (size_needed < epilogue_size_needed)
- {
- tmp =
- expand_simple_binop (counter_mode (count_exp), AND, count_exp,
- GEN_INT (size_needed - 1), count_exp, 1,
- OPTAB_DIRECT);
- if (tmp != count_exp)
- emit_move_insn (count_exp, tmp);
- }
- emit_label (label);
- LABEL_NUSES (label) = 1;
- }
-
- if (count_exp != const0_rtx && epilogue_size_needed > 1)
- expand_movmem_epilogue (dst, src, destreg, srcreg, count_exp,
- epilogue_size_needed);
- if (jump_around_label)
- emit_label (jump_around_label);
- return true;
-}
/* Helper function for memcpy. For QImode value 0xXY produce
0xXYXYXYXY of wide specified by MODE. This is essentially
@@ -23263,9 +23491,9 @@ promote_duplicated_reg (enum machine_mode mode, rtx val)
rtx tmp;
int nops = mode == DImode ? 3 : 2;
- gcc_assert (mode == SImode || mode == DImode);
+ gcc_assert (mode == SImode || mode == DImode || val == const0_rtx);
if (val == const0_rtx)
- return copy_to_mode_reg (mode, const0_rtx);
+ return copy_to_mode_reg (mode, CONST0_RTX (mode));
if (CONST_INT_P (val))
{
HOST_WIDE_INT v = INTVAL (val) & 255;
@@ -23327,7 +23555,8 @@ promote_duplicated_reg (enum machine_mode mode, rtx val)
be needed by main loop copying SIZE_NEEDED chunks and prologue getting
alignment from ALIGN to DESIRED_ALIGN. */
static rtx
-promote_duplicated_reg_to_size (rtx val, int size_needed, int desired_align, int align)
+promote_duplicated_reg_to_size (rtx val, int size_needed, int desired_align,
+ int align)
{
rtx promoted_val;
@@ -23344,14 +23573,55 @@ promote_duplicated_reg_to_size (rtx val, int size_needed, int desired_align, int
return promoted_val;
}
-/* Expand string clear operation (bzero). Use i386 string operations when
- profitable. See expand_movmem comment for explanation of individual
- steps performed. */
-bool
-ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp,
- rtx expected_align_exp, rtx expected_size_exp)
+/* Expand string move (memcpy) ot store (memset) operation. Use i386 string
+ operations when profitable. The code depends upon architecture, block size
+ and alignment, but always has one of the following overall structures:
+
+ Aligned move sequence:
+
+ 1) Prologue guard: Conditional that jumps up to epilogues for small
+ blocks that can be handled by epilogue alone. This is faster
+ but also needed for correctness, since prologue assume the block
+ is larger than the desired alignment.
+
+ Optional dynamic check for size and libcall for large
+ blocks is emitted here too, with -minline-stringops-dynamically.
+
+ 2) Prologue: copy first few bytes in order to get destination
+ aligned to DESIRED_ALIGN. It is emitted only when ALIGN is less
+ than DESIRED_ALIGN and up to DESIRED_ALIGN - ALIGN bytes can be
+ copied. We emit either a jump tree on power of two sized
+ blocks, or a byte loop.
+
+ 3) Main body: the copying loop itself, copying in SIZE_NEEDED chunks
+ with specified algorithm.
+
+ 4) Epilogue: code copying tail of the block that is too small to be
+ handled by main body (or up to size guarded by prologue guard).
+
+ Misaligned move sequence
+
+ 1) missaligned move prologue/epilogue containing:
+ a) Prologue handling small memory blocks and jumping to done_label
+ (skipped if blocks are known to be large enough)
+ b) Signle move copying first DESIRED_ALIGN-ALIGN bytes if alignment is
+ needed by single possibly misaligned move
+ (skipped if alignment is not needed)
+ c) Copy of last SIZE_NEEDED bytes by possibly misaligned moves
+
+ 2) Zero size guard dispatching to done_label, if needed
+
+ 3) dispatch to library call, if needed,
+
+ 3) Main body: the copying loop itself, copying in SIZE_NEEDED chunks
+ with specified algorithm. */
+static bool
+ix86_expand_set_or_movmem (rtx dst, rtx src, rtx count_exp, rtx val_exp,
+ rtx align_exp, rtx expected_align_exp,
+ rtx expected_size_exp, bool issetmem)
{
rtx destreg;
+ rtx srcreg = NULL;
rtx label = NULL;
rtx tmp;
rtx jump_around_label = NULL;
@@ -23362,12 +23632,17 @@ ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp,
int desired_align = 0, align_bytes = 0;
enum stringop_alg alg;
rtx promoted_val = NULL;
+ rtx vec_promoted_val = NULL;
bool force_loopy_epilogue = false;
int dynamic_check;
bool need_zero_guard = false;
bool noalign;
enum machine_mode move_mode = VOIDmode;
- int unroll_factor;
+ int unroll_factor = 1;
+ /* TODO: Once vlaue ranges are available, fill in proper data. */
+ unsigned HOST_WIDE_INT min_size = 0;
+ unsigned HOST_WIDE_INT max_size = -1;
+ bool misaligned_prologue_used = false;
if (CONST_INT_P (align_exp))
align = INTVAL (align_exp);
@@ -23375,8 +23650,14 @@ ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp,
if (CONST_INT_P (expected_align_exp)
&& INTVAL (expected_align_exp) > align)
align = INTVAL (expected_align_exp);
+ /* ALIGN is the minimum of destination and source alignment, but we care here
+ just about destination alignment. */
+ else if (!issetmem
+ && MEM_ALIGN (dst) > (unsigned HOST_WIDE_INT) align * BITS_PER_UNIT)
+ align = MEM_ALIGN (dst) / BITS_PER_UNIT;
+
if (CONST_INT_P (count_exp))
- count = expected_size = INTVAL (count_exp);
+ min_size = max_size = count = expected_size = INTVAL (count_exp);
if (CONST_INT_P (expected_size_exp) && count == 0)
expected_size = INTVAL (expected_size_exp);
@@ -23386,31 +23667,62 @@ ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp,
/* Step 0: Decide on preferred algorithm, desired alignment and
size of chunks to be copied by main loop. */
-
- alg = decide_alg (count, expected_size, true, &dynamic_check, &noalign);
+ alg = decide_alg (count, expected_size, min_size, max_size, issetmem,
+ issetmem && val_exp == const0_rtx,
+ &dynamic_check, &noalign);
if (alg == libcall)
return false;
gcc_assert (alg != no_stringop);
+ /* For now vector-version of memset is generated only for memory zeroing, as
+ creating of promoted vector value is very cheap in this case. */
+ if (issetmem && alg == vector_loop && val_exp != const0_rtx)
+ alg = unrolled_loop;
+
if (!count)
- count_exp = copy_to_mode_reg (counter_mode (count_exp), count_exp);
- destreg = copy_addr_to_reg (XEXP (dst, 0));
+ count_exp = copy_to_mode_reg (GET_MODE (count_exp), count_exp);
+ destreg = ix86_copy_addr_to_reg (XEXP (dst, 0));
+ if (!issetmem)
+ srcreg = ix86_copy_addr_to_reg (XEXP (src, 0));
- move_mode = word_mode;
unroll_factor = 1;
+ move_mode = word_mode;
switch (alg)
{
case libcall:
case no_stringop:
case last_alg:
gcc_unreachable ();
+ case loop_1_byte:
+ need_zero_guard = true;
+ move_mode = QImode;
+ break;
case loop:
need_zero_guard = true;
break;
- case vector_loop:
case unrolled_loop:
need_zero_guard = true;
+ unroll_factor = (TARGET_64BIT ? 4 : 2);
+ break;
+ case vector_loop:
+ need_zero_guard = true;
unroll_factor = 4;
+ /* Find the widest supported mode. */
+ move_mode = word_mode;
+ while (optab_handler (mov_optab, GET_MODE_WIDER_MODE (move_mode))
+ != CODE_FOR_nothing)
+ move_mode = GET_MODE_WIDER_MODE (move_mode);
+
+ /* Find the corresponding vector mode with the same size as MOVE_MODE.
+ MOVE_MODE is an integer mode at the moment (SI, DI, TI, etc.). */
+ if (GET_MODE_SIZE (move_mode) > GET_MODE_SIZE (word_mode))
+ {
+ int nunits = GET_MODE_SIZE (move_mode) / GET_MODE_SIZE (word_mode);
+ move_mode = mode_for_vector (word_mode, nunits);
+ if (optab_handler (mov_optab, move_mode) == CODE_FOR_nothing)
+ move_mode = word_mode;
+ }
+ gcc_assert (optab_handler (mov_optab, move_mode) != CODE_FOR_nothing);
break;
case rep_prefix_8_byte:
move_mode = DImode;
@@ -23421,10 +23733,6 @@ ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp,
case rep_prefix_1_byte:
move_mode = QImode;
break;
- case loop_1_byte:
- need_zero_guard = true;
- move_mode = QImode;
- break;
}
size_needed = GET_MODE_SIZE (move_mode) * unroll_factor;
epilogue_size_needed = size_needed;
@@ -23449,24 +23757,82 @@ ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp,
align_bytes = desired_align - align_bytes;
}
if (align_bytes == 0)
- {
- enum machine_mode mode = SImode;
- if (TARGET_64BIT && (count & ~0xffffffff))
- mode = DImode;
- count_exp = force_reg (mode, count_exp);
- }
+ count_exp = force_reg (counter_mode (count_exp), count_exp);
}
+ gcc_assert (desired_align >= 1 && align >= 1);
+
+ /* Misaligned move sequences handle both prologue and epilogue at once.
+ Default code generation results in a smaller code for large alignments
+ and also avoids redundant job when sizes are known precisely. */
+ misaligned_prologue_used
+ = (TARGET_MISALIGNED_MOVE_STRING_PRO_EPILOGUES
+ && MAX (desired_align, epilogue_size_needed) <= 32
+ && desired_align <= epilogue_size_needed
+ && ((desired_align > align && !align_bytes)
+ || (!count && epilogue_size_needed > 1)));
+
/* Do the cheap promotion to allow better CSE across the
main loop and epilogue (ie one load of the big constant in the
- front of all code. */
- if (CONST_INT_P (val_exp))
- promoted_val = promote_duplicated_reg_to_size (val_exp, size_needed,
- desired_align, align);
+ front of all code.
+ For now the misaligned move sequences do not have fast path
+ without broadcasting. */
+ if (issetmem && ((CONST_INT_P (val_exp) || misaligned_prologue_used)))
+ {
+ if (alg == vector_loop)
+ {
+ gcc_assert (val_exp == const0_rtx);
+ vec_promoted_val = promote_duplicated_reg (move_mode, val_exp);
+ promoted_val = promote_duplicated_reg_to_size (val_exp,
+ GET_MODE_SIZE (word_mode),
+ desired_align, align);
+ }
+ else
+ {
+ promoted_val = promote_duplicated_reg_to_size (val_exp, size_needed,
+ desired_align, align);
+ }
+ }
+ /* Misaligned move sequences handles both prologues and epilogues at once.
+ Default code generation results in smaller code for large alignments and
+ also avoids redundant job when sizes are known precisely. */
+ if (misaligned_prologue_used)
+ {
+ /* Misaligned move prologue handled small blocks by itself. */
+ expand_set_or_movmem_prologue_epilogue_by_misaligned_moves
+ (dst, src, &destreg, &srcreg,
+ move_mode, promoted_val, vec_promoted_val,
+ &count_exp,
+ &jump_around_label,
+ desired_align < align
+ ? MAX (desired_align, epilogue_size_needed) : epilogue_size_needed,
+ desired_align, align, &min_size, dynamic_check, issetmem);
+ if (!issetmem)
+ src = change_address (src, BLKmode, srcreg);
+ dst = change_address (dst, BLKmode, destreg);
+ set_mem_align (dst, desired_align * BITS_PER_UNIT);
+ epilogue_size_needed = 0;
+ if (need_zero_guard && !min_size)
+ {
+ /* It is possible that we copied enough so the main loop will not
+ execute. */
+ gcc_assert (size_needed > 1);
+ if (jump_around_label == NULL_RTX)
+ jump_around_label = gen_label_rtx ();
+ emit_cmp_and_jump_insns (count_exp,
+ GEN_INT (size_needed),
+ LTU, 0, counter_mode (count_exp), 1, jump_around_label);
+ if (expected_size == -1
+ || expected_size < (desired_align - align) / 2 + size_needed)
+ predict_jump (REG_BR_PROB_BASE * 20 / 100);
+ else
+ predict_jump (REG_BR_PROB_BASE * 60 / 100);
+ }
+ }
/* Ensure that alignment prologue won't copy past end of block. */
- if (size_needed > 1 || (desired_align > 1 && desired_align > align))
+ else if (size_needed > 1 || (desired_align > 1 && desired_align > align))
{
epilogue_size_needed = MAX (size_needed - 1, desired_align - align);
- /* Epilogue always copies COUNT_EXP & (EPILOGUE_SIZE_NEEDED - 1) bytes.
+ /* Epilogue always copies COUNT_EXP & EPILOGUE_SIZE_NEEDED bytes.
Make sure it is power of 2. */
epilogue_size_needed = 1 << (floor_log2 (epilogue_size_needed) + 1);
@@ -23474,8 +23840,8 @@ ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp,
promoting mode. This mean that if the promoted VAL is not constant,
we might not use it in the epilogue and have to use byte
loop variant. */
- if (epilogue_size_needed > 2 && !promoted_val)
- force_loopy_epilogue = true;
+ if (issetmem && epilogue_size_needed > 2 && !promoted_val)
+ force_loopy_epilogue = true;
if (count)
{
if (count < (unsigned HOST_WIDE_INT)epilogue_size_needed)
@@ -23488,61 +23854,96 @@ ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp,
goto epilogue;
}
}
- else
+ else if (min_size < (unsigned HOST_WIDE_INT)epilogue_size_needed)
{
+ gcc_assert (max_size >= (unsigned HOST_WIDE_INT)epilogue_size_needed);
label = gen_label_rtx ();
emit_cmp_and_jump_insns (count_exp,
GEN_INT (epilogue_size_needed),
LTU, 0, counter_mode (count_exp), 1, label);
- if (expected_size == -1 || expected_size <= epilogue_size_needed)
+ if (expected_size == -1 || expected_size < epilogue_size_needed)
predict_jump (REG_BR_PROB_BASE * 60 / 100);
else
predict_jump (REG_BR_PROB_BASE * 20 / 100);
}
}
+
+ /* Emit code to decide on runtime whether library call or inline should be
+ used. */
if (dynamic_check != -1)
{
- rtx hot_label = gen_label_rtx ();
- jump_around_label = gen_label_rtx ();
- emit_cmp_and_jump_insns (count_exp, GEN_INT (dynamic_check - 1),
- LEU, 0, counter_mode (count_exp), 1, hot_label);
- predict_jump (REG_BR_PROB_BASE * 90 / 100);
- set_storage_via_libcall (dst, count_exp, val_exp, false);
- emit_jump (jump_around_label);
- emit_label (hot_label);
+ if (!issetmem && CONST_INT_P (count_exp))
+ {
+ if (UINTVAL (count_exp) >= (unsigned HOST_WIDE_INT)dynamic_check)
+ {
+ emit_block_move_via_libcall (dst, src, count_exp, false);
+ count_exp = const0_rtx;
+ goto epilogue;
+ }
+ }
+ else
+ {
+ rtx hot_label = gen_label_rtx ();
+ jump_around_label = gen_label_rtx ();
+ emit_cmp_and_jump_insns (count_exp, GEN_INT (dynamic_check - 1),
+ LEU, 0, GET_MODE (count_exp), 1, hot_label);
+ predict_jump (REG_BR_PROB_BASE * 90 / 100);
+ if (issetmem)
+ set_storage_via_libcall (dst, count_exp, val_exp, false);
+ else
+ emit_block_move_via_libcall (dst, src, count_exp, false);
+ emit_jump (jump_around_label);
+ emit_label (hot_label);
+ }
}
/* Step 2: Alignment prologue. */
-
/* Do the expensive promotion once we branched off the small blocks. */
- if (!promoted_val)
+ if (issetmem && !promoted_val)
promoted_val = promote_duplicated_reg_to_size (val_exp, size_needed,
desired_align, align);
- gcc_assert (desired_align >= 1 && align >= 1);
- if (desired_align > align)
+ if (desired_align > align && !misaligned_prologue_used)
{
if (align_bytes == 0)
{
- /* Except for the first move in epilogue, we no longer know
+ /* Except for the first move in prologue, we no longer know
constant offset in aliasing info. It don't seems to worth
the pain to maintain it for the first move, so throw away
the info early. */
dst = change_address (dst, BLKmode, destreg);
- expand_setmem_prologue (dst, destreg, promoted_val, count_exp, align,
- desired_align);
+ if (!issetmem)
+ src = change_address (src, BLKmode, srcreg);
+ dst = expand_set_or_movmem_prologue (dst, src, destreg, srcreg,
+ promoted_val, vec_promoted_val,
+ count_exp, align, desired_align,
+ issetmem);
+ /* At most desired_align - align bytes are copied. */
+ if (min_size < (unsigned)(desired_align - align))
+ min_size = 0;
+ else
+ min_size -= desired_align - align;
}
else
{
/* If we know how many bytes need to be stored before dst is
sufficiently aligned, maintain aliasing info accurately. */
- dst = expand_constant_setmem_prologue (dst, destreg, promoted_val,
- desired_align, align_bytes);
+ dst = expand_set_or_movmem_constant_prologue (dst, &src, destreg,
+ srcreg,
+ promoted_val,
+ vec_promoted_val,
+ desired_align,
+ align_bytes,
+ issetmem);
+
count_exp = plus_constant (counter_mode (count_exp),
count_exp, -align_bytes);
count -= align_bytes;
+ min_size -= align_bytes;
+ max_size -= align_bytes;
}
if (need_zero_guard
+ && !min_size
&& (count < (unsigned HOST_WIDE_INT) size_needed
|| (align_bytes == 0
&& count < ((unsigned HOST_WIDE_INT) size_needed
@@ -23568,10 +23969,11 @@ ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp,
emit_label (label);
LABEL_NUSES (label) = 1;
label = NULL;
- promoted_val = val_exp;
epilogue_size_needed = 1;
+ if (issetmem)
+ promoted_val = val_exp;
}
- else if (label == NULL_RTX)
+ else if (label == NULL_RTX && !misaligned_prologue_used)
epilogue_size_needed = size_needed;
/* Step 3: Main loop. */
@@ -23584,38 +23986,45 @@ ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp,
gcc_unreachable ();
case loop_1_byte:
case loop:
- case vector_loop:
case unrolled_loop:
- expand_set_or_movmem_via_loop (dst, NULL, destreg, NULL, promoted_val,
+ expand_set_or_movmem_via_loop (dst, src, destreg, srcreg, promoted_val,
count_exp, move_mode, unroll_factor,
- expected_size);
+ expected_size, issetmem);
break;
- case rep_prefix_8_byte:
- expand_setmem_via_rep_stos (dst, destreg, promoted_val, count_exp,
- DImode, val_exp);
+ case vector_loop:
+ expand_set_or_movmem_via_loop (dst, src, destreg, srcreg,
+ vec_promoted_val, count_exp, move_mode,
+ unroll_factor, expected_size, issetmem);
break;
+ case rep_prefix_8_byte:
case rep_prefix_4_byte:
- expand_setmem_via_rep_stos (dst, destreg, promoted_val, count_exp,
- SImode, val_exp);
- break;
case rep_prefix_1_byte:
- expand_setmem_via_rep_stos (dst, destreg, promoted_val, count_exp,
- QImode, val_exp);
+ expand_set_or_movmem_via_rep (dst, src, destreg, srcreg, promoted_val,
+ val_exp, count_exp, move_mode, issetmem);
break;
}
/* Adjust properly the offset of src and dest memory for aliasing. */
if (CONST_INT_P (count_exp))
- dst = adjust_automodify_address_nv (dst, BLKmode, destreg,
- (count / size_needed) * size_needed);
+ {
+ if (!issetmem)
+ src = adjust_automodify_address_nv (src, BLKmode, srcreg,
+ (count / size_needed) * size_needed);
+ dst = adjust_automodify_address_nv (dst, BLKmode, destreg,
+ (count / size_needed) * size_needed);
+ }
else
- dst = change_address (dst, BLKmode, destreg);
+ {
+ if (!issetmem)
+ src = change_address (src, BLKmode, srcreg);
+ dst = change_address (dst, BLKmode, destreg);
+ }
/* Step 4: Epilogue to copy the remaining bytes. */
-
+ epilogue:
if (label)
{
/* When the main loop is done, COUNT_EXP might hold original count,
- while we want to copy only COUNT_EXP & SIZE_NEEDED bytes.
+ while we want to copy only COUNT_EXP & SIZE_NEEDED bytes.
Epilogue code will actually copy COUNT_EXP & EPILOGUE_SIZE_NEEDED
bytes. Compensate if needed. */
@@ -23631,21 +24040,47 @@ ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp,
emit_label (label);
LABEL_NUSES (label) = 1;
}
- epilogue:
+
if (count_exp != const0_rtx && epilogue_size_needed > 1)
{
if (force_loopy_epilogue)
expand_setmem_epilogue_via_loop (dst, destreg, val_exp, count_exp,
epilogue_size_needed);
else
- expand_setmem_epilogue (dst, destreg, promoted_val, count_exp,
- epilogue_size_needed);
+ {
+ if (issetmem)
+ expand_setmem_epilogue (dst, destreg, promoted_val,
+ vec_promoted_val, count_exp,
+ epilogue_size_needed);
+ else
+ expand_movmem_epilogue (dst, src, destreg, srcreg, count_exp,
+ epilogue_size_needed);
+ }
}
if (jump_around_label)
emit_label (jump_around_label);
return true;
}
+/* Wrapper for ix86_expand_set_or_movmem for memcpy case. */
+bool
+ix86_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp,
+ rtx expected_align_exp, rtx expected_size_exp)
+{
+ return ix86_expand_set_or_movmem (dst, src, count_exp, NULL, align_exp,
+ expected_align_exp, expected_size_exp, false);
+}
+
+/* Wrapper for ix86_expand_set_or_movmem for memset case. */
+bool
+ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp,
+ rtx expected_align_exp, rtx expected_size_exp)
+{
+ return ix86_expand_set_or_movmem (dst, NULL, count_exp, val_exp, align_exp,
+ expected_align_exp, expected_size_exp, true);
+}
+
+
/* Expand the appropriate insns for doing strlen if not just doing
repnz; scasb
@@ -24010,13 +24445,13 @@ ix86_output_call_insn (rtx insn, rtx call_op)
if (SIBLING_CALL_P (insn))
{
if (direct_p)
- xasm = "jmp\t%P0";
+ xasm = "%!jmp\t%P0";
/* SEH epilogue detection requires the indirect branch case
to include REX.W. */
else if (TARGET_SEH)
- xasm = "rex.W jmp %A0";
+ xasm = "%!rex.W jmp %A0";
else
- xasm = "jmp\t%A0";
+ xasm = "%!jmp\t%A0";
output_asm_insn (xasm, &call_op);
return "";
@@ -24053,9 +24488,9 @@ ix86_output_call_insn (rtx insn, rtx call_op)
}
if (direct_p)
- xasm = "call\t%P0";
+ xasm = "%!call\t%P0";
else
- xasm = "call\t%A0";
+ xasm = "%!call\t%A0";
output_asm_insn (xasm, &call_op);
@@ -24118,6 +24553,42 @@ ix86_instantiate_decls (void)
instantiate_decl_rtl (s->rtl);
}
+/* Check whether x86 address PARTS is a pc-relative address. */
+
+static bool
+rip_relative_addr_p (struct ix86_address *parts)
+{
+ rtx base, index, disp;
+
+ base = parts->base;
+ index = parts->index;
+ disp = parts->disp;
+
+ if (disp && !base && !index)
+ {
+ if (TARGET_64BIT)
+ {
+ rtx symbol = disp;
+
+ if (GET_CODE (disp) == CONST)
+ symbol = XEXP (disp, 0);
+ if (GET_CODE (symbol) == PLUS
+ && CONST_INT_P (XEXP (symbol, 1)))
+ symbol = XEXP (symbol, 0);
+
+ if (GET_CODE (symbol) == LABEL_REF
+ || (GET_CODE (symbol) == SYMBOL_REF
+ && SYMBOL_REF_TLS_MODEL (symbol) == 0)
+ || (GET_CODE (symbol) == UNSPEC
+ && (XINT (symbol, 1) == UNSPEC_GOTPCREL
+ || XINT (symbol, 1) == UNSPEC_PCREL
+ || XINT (symbol, 1) == UNSPEC_GOTNTPOFF)))
+ return true;
+ }
+ }
+ return false;
+}
+
/* Calculate the length of the memory address in the instruction encoding.
Includes addr32 prefix, does not include the one-byte modrm, opcode,
or other prefixes. We never generate addr32 prefix for LEA insn. */
@@ -24189,25 +24660,8 @@ memory_address_length (rtx addr, bool lea)
else if (disp && !base && !index)
{
len += 4;
- if (TARGET_64BIT)
- {
- rtx symbol = disp;
-
- if (GET_CODE (disp) == CONST)
- symbol = XEXP (disp, 0);
- if (GET_CODE (symbol) == PLUS
- && CONST_INT_P (XEXP (symbol, 1)))
- symbol = XEXP (symbol, 0);
-
- if (GET_CODE (symbol) != LABEL_REF
- && (GET_CODE (symbol) != SYMBOL_REF
- || SYMBOL_REF_TLS_MODEL (symbol) != 0)
- && (GET_CODE (symbol) != UNSPEC
- || (XINT (symbol, 1) != UNSPEC_GOTPCREL
- && XINT (symbol, 1) != UNSPEC_PCREL
- && XINT (symbol, 1) != UNSPEC_GOTNTPOFF)))
- len++;
- }
+ if (rip_relative_addr_p (&parts))
+ len++;
}
else
{
@@ -24389,23 +24843,26 @@ ix86_issue_rate (void)
case PROCESSOR_SLM:
case PROCESSOR_K6:
case PROCESSOR_BTVER2:
+ case PROCESSOR_PENTIUM4:
+ case PROCESSOR_NOCONA:
return 2;
case PROCESSOR_PENTIUMPRO:
- case PROCESSOR_PENTIUM4:
- case PROCESSOR_CORE2:
- case PROCESSOR_COREI7:
- case PROCESSOR_HASWELL:
case PROCESSOR_ATHLON:
case PROCESSOR_K8:
case PROCESSOR_AMDFAM10:
- case PROCESSOR_NOCONA:
case PROCESSOR_GENERIC:
+ case PROCESSOR_BTVER1:
+ return 3;
+
case PROCESSOR_BDVER1:
case PROCESSOR_BDVER2:
case PROCESSOR_BDVER3:
- case PROCESSOR_BTVER1:
- return 3;
+ case PROCESSOR_CORE2:
+ case PROCESSOR_COREI7:
+ case PROCESSOR_COREI7_AVX:
+ case PROCESSOR_HASWELL:
+ return 4;
default:
return 1;
@@ -24663,10 +25120,15 @@ ix86_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
case PROCESSOR_BDVER3:
case PROCESSOR_BTVER1:
case PROCESSOR_BTVER2:
- case PROCESSOR_ATOM:
case PROCESSOR_GENERIC:
memory = get_attr_memory (insn);
+ /* Stack engine allows to execute push&pop instructions in parall. */
+ if (((insn_type == TYPE_PUSH || insn_type == TYPE_POP)
+ && (dep_insn_type == TYPE_PUSH || dep_insn_type == TYPE_POP))
+ && (ix86_tune != PROCESSOR_ATHLON && ix86_tune != PROCESSOR_K8))
+ return 0;
+
/* Show ability of reorder buffer to hide latency of load by executing
in parallel with previous instruction in case
previous instruction is not needed to compute the address. */
@@ -24693,6 +25155,30 @@ ix86_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
}
break;
+ case PROCESSOR_CORE2:
+ case PROCESSOR_COREI7:
+ case PROCESSOR_COREI7_AVX:
+ case PROCESSOR_HASWELL:
+ memory = get_attr_memory (insn);
+
+ /* Stack engine allows to execute push&pop instructions in parall. */
+ if ((insn_type == TYPE_PUSH || insn_type == TYPE_POP)
+ && (dep_insn_type == TYPE_PUSH || dep_insn_type == TYPE_POP))
+ return 0;
+
+ /* Show ability of reorder buffer to hide latency of load by executing
+ in parallel with previous instruction in case
+ previous instruction is not needed to compute the address. */
+ if ((memory == MEMORY_LOAD || memory == MEMORY_BOTH)
+ && !ix86_agi_dependent (dep_insn, insn))
+ {
+ if (cost >= 4)
+ cost -= 4;
+ else
+ cost = 0;
+ }
+ break;
+
case PROCESSOR_SLM:
if (!reload_completed)
return cost;
@@ -24748,8 +25234,16 @@ ia32_multipass_dfa_lookahead (void)
case PROCESSOR_K6:
return 1;
+ case PROCESSOR_BDVER1:
+ case PROCESSOR_BDVER2:
+ case PROCESSOR_BDVER3:
+ /* We use lookahead value 4 for BD both before and after reload
+ schedules. Plan is to have value 8 included for O3. */
+ return 4;
+
case PROCESSOR_CORE2:
case PROCESSOR_COREI7:
+ case PROCESSOR_COREI7_AVX:
case PROCESSOR_HASWELL:
case PROCESSOR_ATOM:
case PROCESSOR_SLM:
@@ -24766,6 +25260,119 @@ ia32_multipass_dfa_lookahead (void)
}
}
+/* Return true if target platform supports macro-fusion. */
+
+static bool
+ix86_macro_fusion_p ()
+{
+ return TARGET_FUSE_CMP_AND_BRANCH;
+}
+
+/* Check whether current microarchitecture support macro fusion
+ for insn pair "CONDGEN + CONDJMP". Refer to
+ "Intel Architectures Optimization Reference Manual". */
+
+static bool
+ix86_macro_fusion_pair_p (rtx condgen, rtx condjmp)
+{
+ rtx src, dest;
+ rtx single_set = single_set (condgen);
+ enum rtx_code ccode;
+ rtx compare_set = NULL_RTX, test_if, cond;
+ rtx alu_set = NULL_RTX, addr = NULL_RTX;
+
+ if (get_attr_type (condgen) != TYPE_TEST
+ && get_attr_type (condgen) != TYPE_ICMP
+ && get_attr_type (condgen) != TYPE_INCDEC
+ && get_attr_type (condgen) != TYPE_ALU)
+ return false;
+
+ if (single_set == NULL_RTX
+ && !TARGET_FUSE_ALU_AND_BRANCH)
+ return false;
+
+ if (single_set != NULL_RTX)
+ compare_set = single_set;
+ else
+ {
+ int i;
+ rtx pat = PATTERN (condgen);
+ for (i = 0; i < XVECLEN (pat, 0); i++)
+ if (GET_CODE (XVECEXP (pat, 0, i)) == SET)
+ {
+ rtx set_src = SET_SRC (XVECEXP (pat, 0, i));
+ if (GET_CODE (set_src) == COMPARE)
+ compare_set = XVECEXP (pat, 0, i);
+ else
+ alu_set = XVECEXP (pat, 0, i);
+ }
+ }
+ if (compare_set == NULL_RTX)
+ return false;
+ src = SET_SRC (compare_set);
+ if (GET_CODE (src) != COMPARE)
+ return false;
+
+ /* Macro-fusion for cmp/test MEM-IMM + conditional jmp is not
+ supported. */
+ if ((MEM_P (XEXP (src, 0))
+ && CONST_INT_P (XEXP (src, 1)))
+ || (MEM_P (XEXP (src, 1))
+ && CONST_INT_P (XEXP (src, 0))))
+ return false;
+
+ /* No fusion for RIP-relative address. */
+ if (MEM_P (XEXP (src, 0)))
+ addr = XEXP (XEXP (src, 0), 0);
+ else if (MEM_P (XEXP (src, 1)))
+ addr = XEXP (XEXP (src, 1), 0);
+
+ if (addr) {
+ ix86_address parts;
+ int ok = ix86_decompose_address (addr, &parts);
+ gcc_assert (ok);
+
+ if (rip_relative_addr_p (&parts))
+ return false;
+ }
+
+ test_if = SET_SRC (pc_set (condjmp));
+ cond = XEXP (test_if, 0);
+ ccode = GET_CODE (cond);
+ /* Check whether conditional jump use Sign or Overflow Flags. */
+ if (!TARGET_FUSE_CMP_AND_BRANCH_SOFLAGS
+ && (ccode == GE
+ || ccode == GT
+ || ccode == LE
+ || ccode == LT))
+ return false;
+
+ /* Return true for TYPE_TEST and TYPE_ICMP. */
+ if (get_attr_type (condgen) == TYPE_TEST
+ || get_attr_type (condgen) == TYPE_ICMP)
+ return true;
+
+ /* The following is the case that macro-fusion for alu + jmp. */
+ if (!TARGET_FUSE_ALU_AND_BRANCH || !alu_set)
+ return false;
+
+ /* No fusion for alu op with memory destination operand. */
+ dest = SET_DEST (alu_set);
+ if (MEM_P (dest))
+ return false;
+
+ /* Macro-fusion for inc/dec + unsigned conditional jump is not
+ supported. */
+ if (get_attr_type (condgen) == TYPE_INCDEC
+ && (ccode == GEU
+ || ccode == GTU
+ || ccode == LEU
+ || ccode == LTU))
+ return false;
+
+ return true;
+}
+
/* Try to reorder ready list to take advantage of Atom pipelined IMUL
execution. It is applied if
(1) IMUL instruction is on the top of list;
@@ -25390,6 +25997,7 @@ ix86_sched_init_global (FILE *dump ATTRIBUTE_UNUSED,
{
case PROCESSOR_CORE2:
case PROCESSOR_COREI7:
+ case PROCESSOR_COREI7_AVX:
case PROCESSOR_HASWELL:
/* Do not perform multipass scheduling for pre-reload schedule
to save compile time. */
@@ -26387,6 +26995,11 @@ enum ix86_builtins
IX86_BUILTIN_LFENCE,
IX86_BUILTIN_PAUSE,
+ IX86_BUILTIN_FNSTENV,
+ IX86_BUILTIN_FLDENV,
+ IX86_BUILTIN_FNSTSW,
+ IX86_BUILTIN_FNCLEX,
+
IX86_BUILTIN_BSRSI,
IX86_BUILTIN_BSRDI,
IX86_BUILTIN_RDPMC,
@@ -27363,6 +27976,12 @@ static const struct builtin_description bdesc_special_args[] =
{ ~OPTION_MASK_ISA_64BIT, CODE_FOR_nothing, "__builtin_ia32_rdtscp", IX86_BUILTIN_RDTSCP, UNKNOWN, (int) UINT64_FTYPE_PUNSIGNED },
{ ~OPTION_MASK_ISA_64BIT, CODE_FOR_pause, "__builtin_ia32_pause", IX86_BUILTIN_PAUSE, UNKNOWN, (int) VOID_FTYPE_VOID },
+ /* 80387 (for use internally for atomic compound assignment). */
+ { 0, CODE_FOR_fnstenv, "__builtin_ia32_fnstenv", IX86_BUILTIN_FNSTENV, UNKNOWN, (int) VOID_FTYPE_PVOID },
+ { 0, CODE_FOR_fldenv, "__builtin_ia32_fldenv", IX86_BUILTIN_FLDENV, UNKNOWN, (int) VOID_FTYPE_PCVOID },
+ { 0, CODE_FOR_fnstsw, "__builtin_ia32_fnstsw", IX86_BUILTIN_FNSTSW, UNKNOWN, (int) VOID_FTYPE_PUSHORT },
+ { 0, CODE_FOR_fnclex, "__builtin_ia32_fnclex", IX86_BUILTIN_FNCLEX, UNKNOWN, (int) VOID_FTYPE_VOID },
+
/* MMX */
{ OPTION_MASK_ISA_MMX, CODE_FOR_mmx_emms, "__builtin_ia32_emms", IX86_BUILTIN_EMMS, UNKNOWN, (int) VOID_FTYPE_VOID },
@@ -27400,13 +28019,13 @@ static const struct builtin_description bdesc_special_args[] =
{ OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_lfence, "__builtin_ia32_lfence", IX86_BUILTIN_LFENCE, UNKNOWN, (int) VOID_FTYPE_VOID },
{ OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_mfence, 0, IX86_BUILTIN_MFENCE, UNKNOWN, (int) VOID_FTYPE_VOID },
{ OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_storeupd, "__builtin_ia32_storeupd", IX86_BUILTIN_STOREUPD, UNKNOWN, (int) VOID_FTYPE_PDOUBLE_V2DF },
- { OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_storedqu, "__builtin_ia32_storedqu", IX86_BUILTIN_STOREDQU, UNKNOWN, (int) VOID_FTYPE_PCHAR_V16QI },
+ { OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_storedquv16qi, "__builtin_ia32_storedqu", IX86_BUILTIN_STOREDQU, UNKNOWN, (int) VOID_FTYPE_PCHAR_V16QI },
{ OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_movntv2df, "__builtin_ia32_movntpd", IX86_BUILTIN_MOVNTPD, UNKNOWN, (int) VOID_FTYPE_PDOUBLE_V2DF },
{ OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_movntv2di, "__builtin_ia32_movntdq", IX86_BUILTIN_MOVNTDQ, UNKNOWN, (int) VOID_FTYPE_PV2DI_V2DI },
{ OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_movntisi, "__builtin_ia32_movnti", IX86_BUILTIN_MOVNTI, UNKNOWN, (int) VOID_FTYPE_PINT_INT },
{ OPTION_MASK_ISA_SSE2 | OPTION_MASK_ISA_64BIT, CODE_FOR_sse2_movntidi, "__builtin_ia32_movnti64", IX86_BUILTIN_MOVNTI64, UNKNOWN, (int) VOID_FTYPE_PLONGLONG_LONGLONG },
{ OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_loadupd, "__builtin_ia32_loadupd", IX86_BUILTIN_LOADUPD, UNKNOWN, (int) V2DF_FTYPE_PCDOUBLE },
- { OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_loaddqu, "__builtin_ia32_loaddqu", IX86_BUILTIN_LOADDQU, UNKNOWN, (int) V16QI_FTYPE_PCCHAR },
+ { OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_loaddquv16qi, "__builtin_ia32_loaddqu", IX86_BUILTIN_LOADDQU, UNKNOWN, (int) V16QI_FTYPE_PCCHAR },
{ OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_loadhpd_exp, "__builtin_ia32_loadhpd", IX86_BUILTIN_LOADHPD, UNKNOWN, (int) V2DF_FTYPE_V2DF_PCDOUBLE },
{ OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_loadlpd_exp, "__builtin_ia32_loadlpd", IX86_BUILTIN_LOADLPD, UNKNOWN, (int) V2DF_FTYPE_V2DF_PCDOUBLE },
@@ -27435,8 +28054,8 @@ static const struct builtin_description bdesc_special_args[] =
{ OPTION_MASK_ISA_AVX, CODE_FOR_avx_loadups256, "__builtin_ia32_loadups256", IX86_BUILTIN_LOADUPS256, UNKNOWN, (int) V8SF_FTYPE_PCFLOAT },
{ OPTION_MASK_ISA_AVX, CODE_FOR_avx_storeupd256, "__builtin_ia32_storeupd256", IX86_BUILTIN_STOREUPD256, UNKNOWN, (int) VOID_FTYPE_PDOUBLE_V4DF },
{ OPTION_MASK_ISA_AVX, CODE_FOR_avx_storeups256, "__builtin_ia32_storeups256", IX86_BUILTIN_STOREUPS256, UNKNOWN, (int) VOID_FTYPE_PFLOAT_V8SF },
- { OPTION_MASK_ISA_AVX, CODE_FOR_avx_loaddqu256, "__builtin_ia32_loaddqu256", IX86_BUILTIN_LOADDQU256, UNKNOWN, (int) V32QI_FTYPE_PCCHAR },
- { OPTION_MASK_ISA_AVX, CODE_FOR_avx_storedqu256, "__builtin_ia32_storedqu256", IX86_BUILTIN_STOREDQU256, UNKNOWN, (int) VOID_FTYPE_PCHAR_V32QI },
+ { OPTION_MASK_ISA_AVX, CODE_FOR_avx_loaddquv32qi, "__builtin_ia32_loaddqu256", IX86_BUILTIN_LOADDQU256, UNKNOWN, (int) V32QI_FTYPE_PCCHAR },
+ { OPTION_MASK_ISA_AVX, CODE_FOR_avx_storedquv32qi, "__builtin_ia32_storedqu256", IX86_BUILTIN_STOREDQU256, UNKNOWN, (int) VOID_FTYPE_PCHAR_V32QI },
{ OPTION_MASK_ISA_AVX, CODE_FOR_avx_lddqu256, "__builtin_ia32_lddqu256", IX86_BUILTIN_LDDQU256, UNKNOWN, (int) V32QI_FTYPE_PCCHAR },
{ OPTION_MASK_ISA_AVX, CODE_FOR_avx_movntv4di, "__builtin_ia32_movntdq256", IX86_BUILTIN_MOVNTDQ256, UNKNOWN, (int) VOID_FTYPE_PV4DI_V4DI },
@@ -27705,7 +28324,7 @@ static const struct builtin_description bdesc_args[] =
{ OPTION_MASK_ISA_SSE2 | OPTION_MASK_ISA_64BIT, CODE_FOR_sse2_cvtsd2siq, "__builtin_ia32_cvtsd2si64", IX86_BUILTIN_CVTSD2SI64, UNKNOWN, (int) INT64_FTYPE_V2DF },
{ OPTION_MASK_ISA_SSE2 | OPTION_MASK_ISA_64BIT, CODE_FOR_sse2_cvttsd2siq, "__builtin_ia32_cvttsd2si64", IX86_BUILTIN_CVTTSD2SI64, UNKNOWN, (int) INT64_FTYPE_V2DF },
- { OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_cvtps2dq, "__builtin_ia32_cvtps2dq", IX86_BUILTIN_CVTPS2DQ, UNKNOWN, (int) V4SI_FTYPE_V4SF },
+ { OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_fix_notruncv4sfv4si, "__builtin_ia32_cvtps2dq", IX86_BUILTIN_CVTPS2DQ, UNKNOWN, (int) V4SI_FTYPE_V4SF },
{ OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_cvtps2pd, "__builtin_ia32_cvtps2pd", IX86_BUILTIN_CVTPS2PD, UNKNOWN, (int) V2DF_FTYPE_V4SF },
{ OPTION_MASK_ISA_SSE2, CODE_FOR_fix_truncv4sfv4si2, "__builtin_ia32_cvttps2dq", IX86_BUILTIN_CVTTPS2DQ, UNKNOWN, (int) V4SI_FTYPE_V4SF },
@@ -28053,7 +28672,7 @@ static const struct builtin_description bdesc_args[] =
{ OPTION_MASK_ISA_AVX, CODE_FOR_floatv4siv4df2, "__builtin_ia32_cvtdq2pd256", IX86_BUILTIN_CVTDQ2PD256, UNKNOWN, (int) V4DF_FTYPE_V4SI },
{ OPTION_MASK_ISA_AVX, CODE_FOR_floatv8siv8sf2, "__builtin_ia32_cvtdq2ps256", IX86_BUILTIN_CVTDQ2PS256, UNKNOWN, (int) V8SF_FTYPE_V8SI },
{ OPTION_MASK_ISA_AVX, CODE_FOR_avx_cvtpd2ps256, "__builtin_ia32_cvtpd2ps256", IX86_BUILTIN_CVTPD2PS256, UNKNOWN, (int) V4SF_FTYPE_V4DF },
- { OPTION_MASK_ISA_AVX, CODE_FOR_avx_cvtps2dq256, "__builtin_ia32_cvtps2dq256", IX86_BUILTIN_CVTPS2DQ256, UNKNOWN, (int) V8SI_FTYPE_V8SF },
+ { OPTION_MASK_ISA_AVX, CODE_FOR_avx_fix_notruncv8sfv8si, "__builtin_ia32_cvtps2dq256", IX86_BUILTIN_CVTPS2DQ256, UNKNOWN, (int) V8SI_FTYPE_V8SF },
{ OPTION_MASK_ISA_AVX, CODE_FOR_avx_cvtps2pd256, "__builtin_ia32_cvtps2pd256", IX86_BUILTIN_CVTPS2PD256, UNKNOWN, (int) V4DF_FTYPE_V4SF },
{ OPTION_MASK_ISA_AVX, CODE_FOR_fix_truncv4dfv4si2, "__builtin_ia32_cvttpd2dq256", IX86_BUILTIN_CVTTPD2DQ256, UNKNOWN, (int) V4SI_FTYPE_V4DF },
{ OPTION_MASK_ISA_AVX, CODE_FOR_avx_cvtpd2dq256, "__builtin_ia32_cvtpd2dq256", IX86_BUILTIN_CVTPD2DQ256, UNKNOWN, (int) V4SI_FTYPE_V4DF },
@@ -29222,7 +29841,8 @@ get_builtin_code_for_version (tree decl, tree *predicate_list)
if (strstr (attrs_str, "arch=") != NULL)
{
cl_target_option_save (&cur_target, &global_options);
- target_node = ix86_valid_target_attribute_tree (attrs);
+ target_node = ix86_valid_target_attribute_tree (attrs, &global_options,
+ &global_options_set);
gcc_assert (target_node);
new_target = TREE_TARGET_OPTION (target_node);
@@ -29240,6 +29860,10 @@ get_builtin_code_for_version (tree decl, tree *predicate_list)
arg_str = "corei7";
priority = P_PROC_SSE4_2;
break;
+ case PROCESSOR_COREI7_AVX:
+ arg_str = "corei7-avx";
+ priority = P_PROC_SSE4_2;
+ break;
case PROCESSOR_ATOM:
arg_str = "atom";
priority = P_PROC_SSSE3;
@@ -29812,7 +30436,7 @@ ix86_get_function_versions_dispatcher (void *decl)
while (default_version_info != NULL)
{
if (is_function_default_version
- (default_version_info->this_node->symbol.decl))
+ (default_version_info->this_node->decl))
break;
default_version_info = default_version_info->next;
}
@@ -29842,7 +30466,7 @@ ix86_get_function_versions_dispatcher (void *decl)
struct cgraph_function_version_info *dispatcher_version_info = NULL;
/* Right now, the dispatching is done via ifunc. */
- dispatch_decl = make_dispatcher_decl (default_node->symbol.decl);
+ dispatch_decl = make_dispatcher_decl (default_node->decl);
dispatcher_node = cgraph_get_create_node (dispatch_decl);
gcc_assert (dispatcher_node != NULL);
@@ -29850,7 +30474,7 @@ ix86_get_function_versions_dispatcher (void *decl)
dispatcher_version_info
= insert_new_cgraph_node_version (dispatcher_node);
dispatcher_version_info->next = default_version_info;
- dispatcher_node->symbol.definition = 1;
+ dispatcher_node->definition = 1;
/* Set the dispatcher for all the versions. */
it_v = default_version_info;
@@ -29863,7 +30487,7 @@ ix86_get_function_versions_dispatcher (void *decl)
else
#endif
{
- error_at (DECL_SOURCE_LOCATION (default_node->symbol.decl),
+ error_at (DECL_SOURCE_LOCATION (default_node->decl),
"multiversioning needs ifunc which is not supported "
"on this target");
}
@@ -30002,13 +30626,13 @@ ix86_generate_version_dispatcher_body (void *node_p)
return node_version_info->dispatcher_resolver;
/* The first version in the chain corresponds to the default version. */
- default_ver_decl = node_version_info->next->this_node->symbol.decl;
+ default_ver_decl = node_version_info->next->this_node->decl;
/* node is going to be an alias, so remove the finalized bit. */
- node->symbol.definition = false;
+ node->definition = false;
resolver_decl = make_resolver_func (default_ver_decl,
- node->symbol.decl, &empty_bb);
+ node->decl, &empty_bb);
node_version_info->dispatcher_resolver = resolver_decl;
@@ -30025,10 +30649,10 @@ ix86_generate_version_dispatcher_body (void *node_p)
not. This happens for methods in derived classes that override
virtual methods in base classes but are not explicitly marked as
virtual. */
- if (DECL_VINDEX (versn->symbol.decl))
+ if (DECL_VINDEX (versn->decl))
sorry ("Virtual function multiversioning not supported");
- fn_ver_vec.safe_push (versn->symbol.decl);
+ fn_ver_vec.safe_push (versn->decl);
}
dispatch_function_versions (resolver_decl, &fn_ver_vec, &empty_bb);
@@ -31575,8 +32199,8 @@ ix86_expand_args_builtin (const struct builtin_description *d,
}
else
{
- target = gen_reg_rtx (rmode);
- real_target = simplify_gen_subreg (tmode, target, rmode, 0);
+ real_target = gen_reg_rtx (tmode);
+ target = simplify_gen_subreg (rmode, real_target, tmode, 0);
}
for (i = 0; i < nargs; i++)
@@ -32319,6 +32943,10 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
case IX86_BUILTIN_FXRSTOR:
case IX86_BUILTIN_FXSAVE64:
case IX86_BUILTIN_FXRSTOR64:
+ case IX86_BUILTIN_FNSTENV:
+ case IX86_BUILTIN_FLDENV:
+ case IX86_BUILTIN_FNSTSW:
+ mode0 = BLKmode;
switch (fcode)
{
case IX86_BUILTIN_FXSAVE:
@@ -32333,6 +32961,16 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
case IX86_BUILTIN_FXRSTOR64:
icode = CODE_FOR_fxrstor64;
break;
+ case IX86_BUILTIN_FNSTENV:
+ icode = CODE_FOR_fnstenv;
+ break;
+ case IX86_BUILTIN_FLDENV:
+ icode = CODE_FOR_fldenv;
+ break;
+ case IX86_BUILTIN_FNSTSW:
+ icode = CODE_FOR_fnstsw;
+ mode0 = HImode;
+ break;
default:
gcc_unreachable ();
}
@@ -32345,7 +32983,7 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
op0 = convert_memory_address (Pmode, op0);
op0 = copy_addr_to_reg (op0);
}
- op0 = gen_rtx_MEM (BLKmode, op0);
+ op0 = gen_rtx_MEM (mode0, op0);
pat = GEN_FCN (icode) (op0);
if (pat)
@@ -34015,6 +34653,7 @@ ix86_class_likely_spilled_p (reg_class_t rclass)
case SSE_FIRST_REG:
case FP_TOP_REG:
case FP_SECOND_REG:
+ case BND_REGS:
return true;
default:
@@ -34363,6 +35002,8 @@ ix86_hard_regno_mode_ok (int regno, enum machine_mode mode)
return VALID_FP_MODE_P (mode);
if (MASK_REGNO_P (regno))
return VALID_MASK_REG_MODE (mode);
+ if (BND_REGNO_P (regno))
+ return VALID_BND_REG_MODE (mode);
if (SSE_REGNO_P (regno))
{
/* We implement the move patterns for all vector modes into and
@@ -34739,7 +35380,7 @@ ix86_rtx_costs (rtx x, int code_i, int outer_code_i, int opno, int *total,
rtx sub;
gcc_assert (FLOAT_MODE_P (mode));
- gcc_assert (TARGET_FMA || TARGET_FMA4);
+ gcc_assert (TARGET_FMA || TARGET_FMA4 || TARGET_AVX512F);
/* ??? SSE scalar/vector cost should be used here. */
/* ??? Bald assumption that fma has the same cost as fmul. */
@@ -35176,6 +35817,10 @@ x86_order_regs_for_local_alloc (void)
for (i = FIRST_MASK_REG; i <= LAST_MASK_REG; i++)
reg_alloc_order [pos++] = i;
+ /* MPX bound registers. */
+ for (i = FIRST_BND_REG; i <= LAST_BND_REG; i++)
+ reg_alloc_order [pos++] = i;
+
/* x87 registers. */
if (TARGET_SSE_MATH)
for (i = FIRST_STACK_REG; i <= LAST_STACK_REG; i++)
@@ -36292,8 +36937,9 @@ ix86_expand_vector_init_duplicate (bool mmx_ok, enum machine_mode mode,
emit_move_insn (tmp1, gen_lowpart (SImode, val));
/* Insert the SImode value as low element of a V4SImode vector. */
- tmp2 = gen_lowpart (V4SImode, dperm.op0);
+ tmp2 = gen_reg_rtx (V4SImode);
emit_insn (gen_vec_setv4si_0 (tmp2, CONST0_RTX (V4SImode), tmp1));
+ emit_move_insn (dperm.op0, gen_lowpart (mode, tmp2));
ok = (expand_vec_perm_1 (&dperm)
|| expand_vec_perm_broadcast_1 (&dperm));
@@ -36323,9 +36969,10 @@ ix86_expand_vector_init_duplicate (bool mmx_ok, enum machine_mode mode,
NULL_RTX, 1, OPTAB_LIB_WIDEN);
val = expand_simple_binop (wsmode, IOR, val, x, x, 1, OPTAB_LIB_WIDEN);
- x = gen_lowpart (wvmode, target);
+ x = gen_reg_rtx (wvmode);
ok = ix86_expand_vector_init_duplicate (mmx_ok, wvmode, x, val);
gcc_assert (ok);
+ emit_move_insn (target, gen_lowpart (GET_MODE (target), x));
return ok;
}
@@ -37200,8 +37847,9 @@ ix86_expand_vector_set (bool mmx_ok, rtx target, rtx val, int elt)
else
{
/* For SSE1, we have to reuse the V4SF code. */
- ix86_expand_vector_set (false, gen_lowpart (V4SFmode, target),
- gen_lowpart (SFmode, val), elt);
+ rtx t = gen_reg_rtx (V4SFmode);
+ ix86_expand_vector_set (false, t, gen_lowpart (SFmode, val), elt);
+ emit_move_insn (target, gen_lowpart (mode, t));
}
return;
@@ -37519,7 +38167,7 @@ ix86_expand_vector_extract (bool mmx_ok, rtx target, rtx vec, int elt)
static void
emit_reduc_half (rtx dest, rtx src, int i)
{
- rtx tem;
+ rtx tem, d = dest;
switch (GET_MODE (src))
{
case V4SFmode:
@@ -37536,8 +38184,8 @@ emit_reduc_half (rtx dest, rtx src, int i)
case V8HImode:
case V4SImode:
case V2DImode:
- tem = gen_sse2_lshrv1ti3 (gen_lowpart (V1TImode, dest),
- gen_lowpart (V1TImode, src),
+ d = gen_reg_rtx (V1TImode);
+ tem = gen_sse2_lshrv1ti3 (d, gen_lowpart (V1TImode, src),
GEN_INT (i / 2));
break;
case V8SFmode:
@@ -37558,19 +38206,26 @@ emit_reduc_half (rtx dest, rtx src, int i)
case V8SImode:
case V4DImode:
if (i == 256)
- tem = gen_avx2_permv2ti (gen_lowpart (V4DImode, dest),
- gen_lowpart (V4DImode, src),
- gen_lowpart (V4DImode, src),
- const1_rtx);
+ {
+ if (GET_MODE (dest) != V4DImode)
+ d = gen_reg_rtx (V4DImode);
+ tem = gen_avx2_permv2ti (d, gen_lowpart (V4DImode, src),
+ gen_lowpart (V4DImode, src),
+ const1_rtx);
+ }
else
- tem = gen_avx2_lshrv2ti3 (gen_lowpart (V2TImode, dest),
- gen_lowpart (V2TImode, src),
- GEN_INT (i / 2));
+ {
+ d = gen_reg_rtx (V2TImode);
+ tem = gen_avx2_lshrv2ti3 (d, gen_lowpart (V2TImode, src),
+ GEN_INT (i / 2));
+ }
break;
default:
gcc_unreachable ();
}
emit_insn (tem);
+ if (d != dest)
+ emit_move_insn (dest, gen_lowpart (GET_MODE (dest), d));
}
/* Expand a vector reduction. FN is the binary pattern to reduce;
@@ -38217,6 +38872,7 @@ static rtx
ix86_expand_sse_compare_and_jump (enum rtx_code code, rtx op0, rtx op1,
bool swap_operands)
{
+ enum machine_mode fpcmp_mode = ix86_fp_compare_mode (code);
rtx label, tmp;
if (swap_operands)
@@ -38227,9 +38883,9 @@ ix86_expand_sse_compare_and_jump (enum rtx_code code, rtx op0, rtx op1,
}
label = gen_label_rtx ();
- tmp = gen_rtx_REG (CCFPUmode, FLAGS_REG);
+ tmp = gen_rtx_REG (fpcmp_mode, FLAGS_REG);
emit_insn (gen_rtx_SET (VOIDmode, tmp,
- gen_rtx_COMPARE (CCFPUmode, op0, op1)));
+ gen_rtx_COMPARE (fpcmp_mode, op0, op1)));
tmp = gen_rtx_fmt_ee (code, VOIDmode, tmp, const0_rtx);
tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
gen_rtx_LABEL_REF (VOIDmode, label), pc_rtx);
@@ -39062,6 +39718,8 @@ expand_vec_perm_blend (struct expand_vec_perm_d *d)
emit_insn (gen_sse4_1_pblendvb (target, op0, op1, vperm));
else
emit_insn (gen_avx2_pblendvb (target, op0, op1, vperm));
+ if (target != d->target)
+ emit_move_insn (d->target, gen_lowpart (d->vmode, target));
return true;
}
@@ -39071,7 +39729,7 @@ expand_vec_perm_blend (struct expand_vec_perm_d *d)
/* FALLTHRU */
do_subreg:
- target = gen_lowpart (vmode, target);
+ target = gen_reg_rtx (vmode);
op0 = gen_lowpart (vmode, op0);
op1 = gen_lowpart (vmode, op1);
break;
@@ -39125,7 +39783,7 @@ expand_vec_perm_blend (struct expand_vec_perm_d *d)
vmode = V32QImode;
nelt = 32;
- target = gen_lowpart (vmode, target);
+ target = gen_reg_rtx (vmode);
op0 = gen_lowpart (vmode, op0);
op1 = gen_lowpart (vmode, op1);
goto finish_pblendvb;
@@ -39158,6 +39816,8 @@ expand_vec_perm_blend (struct expand_vec_perm_d *d)
x = gen_rtx_VEC_MERGE (vmode, op1, op0, GEN_INT (mask));
x = gen_rtx_SET (VOIDmode, target, x);
emit_insn (x);
+ if (target != d->target)
+ emit_move_insn (d->target, gen_lowpart (d->vmode, target));
return true;
}
@@ -39263,13 +39923,17 @@ expand_vec_perm_pshufb (struct expand_vec_perm_d *d)
/* Use vperm2i128 insn. The pattern uses
V4DImode instead of V2TImode. */
- target = gen_lowpart (V4DImode, d->target);
+ target = d->target;
+ if (d->vmode != V4DImode)
+ target = gen_reg_rtx (V4DImode);
op0 = gen_lowpart (V4DImode, d->op0);
op1 = gen_lowpart (V4DImode, d->op1);
rperm[0]
= GEN_INT (((d->perm[0] & (nelt / 2)) ? 1 : 0)
|| ((d->perm[nelt / 2] & (nelt / 2)) ? 2 : 0));
emit_insn (gen_avx2_permv2ti (target, op0, op1, rperm[0]));
+ if (target != d->target)
+ emit_move_insn (d->target, gen_lowpart (d->vmode, target));
return true;
}
return false;
@@ -39304,9 +39968,15 @@ expand_vec_perm_pshufb (struct expand_vec_perm_d *d)
perm[i] = (d->perm[i * nelt / 4] * 4 / nelt) & 3;
if (d->testing_p)
return true;
- return expand_vselect (gen_lowpart (V4DImode, d->target),
- gen_lowpart (V4DImode, d->op0),
- perm, 4, false);
+ target = gen_reg_rtx (V4DImode);
+ if (expand_vselect (target, gen_lowpart (V4DImode, d->op0),
+ perm, 4, false))
+ {
+ emit_move_insn (d->target,
+ gen_lowpart (d->vmode, target));
+ return true;
+ }
+ return false;
}
/* Next see if vpermd can be used. */
@@ -39358,7 +40028,9 @@ expand_vec_perm_pshufb (struct expand_vec_perm_d *d)
gen_rtvec_v (GET_MODE_NUNITS (vmode), rperm));
vperm = force_reg (vmode, vperm);
- target = gen_lowpart (vmode, d->target);
+ target = d->target;
+ if (d->vmode != vmode)
+ target = gen_reg_rtx (vmode);
op0 = gen_lowpart (vmode, d->op0);
if (d->one_operand_p)
{
@@ -39376,6 +40048,8 @@ expand_vec_perm_pshufb (struct expand_vec_perm_d *d)
op1 = gen_lowpart (vmode, d->op1);
emit_insn (gen_xop_pperm (target, op0, op1, vperm));
}
+ if (target != d->target)
+ emit_move_insn (d->target, gen_lowpart (d->vmode, target));
return true;
}
@@ -39575,7 +40249,8 @@ expand_vec_perm_palignr (struct expand_vec_perm_d *d)
unsigned i, nelt = d->nelt;
unsigned min, max;
bool in_order, ok;
- rtx shift;
+ rtx shift, target;
+ struct expand_vec_perm_d dcopy;
/* Even with AVX, palignr only operates on 128-bit vectors. */
if (!TARGET_SSSE3 || GET_MODE_SIZE (d->vmode) != 16)
@@ -39598,29 +40273,33 @@ expand_vec_perm_palignr (struct expand_vec_perm_d *d)
if (d->testing_p)
return true;
+ dcopy = *d;
shift = GEN_INT (min * GET_MODE_BITSIZE (GET_MODE_INNER (d->vmode)));
- emit_insn (gen_ssse3_palignrti (gen_lowpart (TImode, d->target),
- gen_lowpart (TImode, d->op1),
+ target = gen_reg_rtx (TImode);
+ emit_insn (gen_ssse3_palignrti (target, gen_lowpart (TImode, d->op1),
gen_lowpart (TImode, d->op0), shift));
- d->op0 = d->op1 = d->target;
- d->one_operand_p = true;
+ dcopy.op0 = dcopy.op1 = gen_lowpart (d->vmode, target);
+ dcopy.one_operand_p = true;
in_order = true;
for (i = 0; i < nelt; ++i)
{
- unsigned e = d->perm[i] - min;
+ unsigned e = dcopy.perm[i] - min;
if (e != i)
in_order = false;
- d->perm[i] = e;
+ dcopy.perm[i] = e;
}
/* Test for the degenerate case where the alignment by itself
produces the desired permutation. */
if (in_order)
- return true;
+ {
+ emit_move_insn (d->target, dcopy.op0);
+ return true;
+ }
- ok = expand_vec_perm_1 (d);
+ ok = expand_vec_perm_1 (&dcopy);
gcc_assert (ok);
return ok;
@@ -39874,10 +40553,10 @@ expand_vec_perm_interleave2 (struct expand_vec_perm_d *d)
else
dfinal.perm[i] = e;
}
- dfinal.op0 = gen_reg_rtx (dfinal.vmode);
+ dremap.target = gen_reg_rtx (dremap.vmode);
+ dfinal.op0 = gen_lowpart (dfinal.vmode, dremap.target);
dfinal.op1 = dfinal.op0;
dfinal.one_operand_p = true;
- dremap.target = dfinal.op0;
/* Test if the final remap can be done with a single insn. For V4SFmode or
V4SImode this *will* succeed. For V8HImode or V16QImode it may not. */
@@ -39894,7 +40573,6 @@ expand_vec_perm_interleave2 (struct expand_vec_perm_d *d)
if (dremap.vmode != dfinal.vmode)
{
- dremap.target = gen_lowpart (dremap.vmode, dremap.target);
dremap.op0 = gen_lowpart (dremap.vmode, dremap.op0);
dremap.op1 = gen_lowpart (dremap.vmode, dremap.op1);
}
@@ -40345,8 +41023,12 @@ expand_vec_perm_pshufb2 (struct expand_vec_perm_d *d)
op = gen_lowpart (V16QImode, d->op1);
emit_insn (gen_ssse3_pshufbv16qi3 (h, op, vperm));
- op = gen_lowpart (V16QImode, d->target);
+ op = d->target;
+ if (d->vmode != V16QImode)
+ op = gen_reg_rtx (V16QImode);
emit_insn (gen_iorv16qi3 (op, l, h));
+ if (op != d->target)
+ emit_move_insn (d->target, gen_lowpart (d->vmode, op));
return true;
}
@@ -40412,8 +41094,12 @@ expand_vec_perm_vpshufb2_vpermq (struct expand_vec_perm_d *d)
op = gen_lowpart (V32QImode, d->op0);
emit_insn (gen_avx2_pshufbv32qi3 (l, op, vperm));
- op = gen_lowpart (V32QImode, d->target);
+ op = d->target;
+ if (d->vmode != V32QImode)
+ op = gen_reg_rtx (V32QImode);
emit_insn (gen_iorv32qi3 (op, l, gen_lowpart (V32QImode, hp)));
+ if (op != d->target)
+ emit_move_insn (d->target, gen_lowpart (d->vmode, op));
return true;
}
@@ -40489,10 +41175,11 @@ expand_vec_perm_vpshufb2_vpermq_even_odd (struct expand_vec_perm_d *d)
emit_insn (gen_iorv32qi3 (ior, l, h));
/* Permute the V4DImode quarters using { 0, 2, 1, 3 } permutation. */
- op = gen_lowpart (V4DImode, d->target);
+ op = gen_reg_rtx (V4DImode);
ior = gen_lowpart (V4DImode, ior);
emit_insn (gen_avx2_permv4di_1 (op, ior, const0_rtx, const2_rtx,
const1_rtx, GEN_INT (3)));
+ emit_move_insn (d->target, gen_lowpart (d->vmode, op));
return true;
}
@@ -40503,7 +41190,7 @@ expand_vec_perm_vpshufb2_vpermq_even_odd (struct expand_vec_perm_d *d)
static bool
expand_vec_perm_even_odd_1 (struct expand_vec_perm_d *d, unsigned odd)
{
- rtx t1, t2, t3;
+ rtx t1, t2, t3, t4, t5;
switch (d->vmode)
{
@@ -40615,10 +41302,17 @@ expand_vec_perm_even_odd_1 (struct expand_vec_perm_d *d, unsigned odd)
{
struct expand_vec_perm_d d_copy = *d;
d_copy.vmode = V4DFmode;
- d_copy.target = gen_lowpart (V4DFmode, d->target);
+ d_copy.target = gen_reg_rtx (V4DFmode);
d_copy.op0 = gen_lowpart (V4DFmode, d->op0);
d_copy.op1 = gen_lowpart (V4DFmode, d->op1);
- return expand_vec_perm_even_odd_1 (&d_copy, odd);
+ if (expand_vec_perm_even_odd_1 (&d_copy, odd))
+ {
+ if (!d->testing_p)
+ emit_move_insn (d->target,
+ gen_lowpart (V4DImode, d_copy.target));
+ return true;
+ }
+ return false;
}
t1 = gen_reg_rtx (V4DImode);
@@ -40641,44 +41335,51 @@ expand_vec_perm_even_odd_1 (struct expand_vec_perm_d *d, unsigned odd)
{
struct expand_vec_perm_d d_copy = *d;
d_copy.vmode = V8SFmode;
- d_copy.target = gen_lowpart (V8SFmode, d->target);
+ d_copy.target = gen_reg_rtx (V8SFmode);
d_copy.op0 = gen_lowpart (V8SFmode, d->op0);
d_copy.op1 = gen_lowpart (V8SFmode, d->op1);
- return expand_vec_perm_even_odd_1 (&d_copy, odd);
+ if (expand_vec_perm_even_odd_1 (&d_copy, odd))
+ {
+ if (!d->testing_p)
+ emit_move_insn (d->target,
+ gen_lowpart (V8SImode, d_copy.target));
+ return true;
+ }
+ return false;
}
t1 = gen_reg_rtx (V8SImode);
t2 = gen_reg_rtx (V8SImode);
+ t3 = gen_reg_rtx (V4DImode);
+ t4 = gen_reg_rtx (V4DImode);
+ t5 = gen_reg_rtx (V4DImode);
/* Shuffle the lanes around into
{ 0 1 2 3 8 9 a b } and { 4 5 6 7 c d e f }. */
- emit_insn (gen_avx2_permv2ti (gen_lowpart (V4DImode, t1),
- gen_lowpart (V4DImode, d->op0),
+ emit_insn (gen_avx2_permv2ti (t3, gen_lowpart (V4DImode, d->op0),
gen_lowpart (V4DImode, d->op1),
GEN_INT (0x20)));
- emit_insn (gen_avx2_permv2ti (gen_lowpart (V4DImode, t2),
- gen_lowpart (V4DImode, d->op0),
+ emit_insn (gen_avx2_permv2ti (t4, gen_lowpart (V4DImode, d->op0),
gen_lowpart (V4DImode, d->op1),
GEN_INT (0x31)));
/* Swap the 2nd and 3rd position in each lane into
{ 0 2 1 3 8 a 9 b } and { 4 6 5 7 c e d f }. */
- emit_insn (gen_avx2_pshufdv3 (t1, t1,
+ emit_insn (gen_avx2_pshufdv3 (t1, gen_lowpart (V8SImode, t3),
GEN_INT (2 * 4 + 1 * 16 + 3 * 64)));
- emit_insn (gen_avx2_pshufdv3 (t2, t2,
+ emit_insn (gen_avx2_pshufdv3 (t2, gen_lowpart (V8SImode, t4),
GEN_INT (2 * 4 + 1 * 16 + 3 * 64)));
/* Now an vpunpck[lh]qdq will produce
{ 0 2 4 6 8 a c e } resp. { 1 3 5 7 9 b d f }. */
if (odd)
- t3 = gen_avx2_interleave_highv4di (gen_lowpart (V4DImode, d->target),
- gen_lowpart (V4DImode, t1),
+ t3 = gen_avx2_interleave_highv4di (t5, gen_lowpart (V4DImode, t1),
gen_lowpart (V4DImode, t2));
else
- t3 = gen_avx2_interleave_lowv4di (gen_lowpart (V4DImode, d->target),
- gen_lowpart (V4DImode, t1),
+ t3 = gen_avx2_interleave_lowv4di (t5, gen_lowpart (V4DImode, t1),
gen_lowpart (V4DImode, t2));
emit_insn (t3);
+ emit_move_insn (d->target, gen_lowpart (V8SImode, t5));
break;
default:
@@ -40716,7 +41417,7 @@ expand_vec_perm_broadcast_1 (struct expand_vec_perm_d *d)
unsigned elt = d->perm[0], nelt2 = d->nelt / 2;
enum machine_mode vmode = d->vmode;
unsigned char perm2[4];
- rtx op0 = d->op0;
+ rtx op0 = d->op0, dest;
bool ok;
switch (vmode)
@@ -40762,9 +41463,11 @@ expand_vec_perm_broadcast_1 (struct expand_vec_perm_d *d)
while (vmode != V4SImode);
memset (perm2, elt, 4);
- ok = expand_vselect (gen_lowpart (V4SImode, d->target), op0, perm2, 4,
- d->testing_p);
+ dest = gen_reg_rtx (V4SImode);
+ ok = expand_vselect (dest, op0, perm2, 4, d->testing_p);
gcc_assert (ok);
+ if (!d->testing_p)
+ emit_move_insn (d->target, gen_lowpart (d->vmode, dest));
return true;
case V32QImode:
@@ -40906,8 +41609,12 @@ expand_vec_perm_vpshufb4_vpermq2 (struct expand_vec_perm_d *d)
}
gcc_assert (l[0] && l[1]);
- op = gen_lowpart (V32QImode, d->target);
+ op = d->target;
+ if (d->vmode != V32QImode)
+ op = gen_reg_rtx (V32QImode);
emit_insn (gen_iorv32qi3 (op, l[0], l[1]));
+ if (op != d->target)
+ emit_move_insn (d->target, gen_lowpart (d->vmode, op));
return true;
}
@@ -41475,7 +42182,9 @@ ix86_expand_mul_widen_hilo (rtx dest, rtx op1, rtx op2,
op1, op2, NULL_RTX, uns_p, OPTAB_DIRECT);
gcc_assert (t1 && t2);
- ix86_expand_vec_interleave (gen_lowpart (mode, dest), t1, t2, high_p);
+ t3 = gen_reg_rtx (mode);
+ ix86_expand_vec_interleave (t3, t1, t2, high_p);
+ emit_move_insn (dest, gen_lowpart (wmode, t3));
break;
case V16QImode:
@@ -41496,14 +42205,14 @@ ix86_expand_mul_widen_hilo (rtx dest, rtx op1, rtx op2,
void
ix86_expand_sse2_mulv4si3 (rtx op0, rtx op1, rtx op2)
{
- rtx res_1, res_2;
+ rtx res_1, res_2, res_3, res_4;
res_1 = gen_reg_rtx (V4SImode);
res_2 = gen_reg_rtx (V4SImode);
- ix86_expand_mul_widen_evenodd (gen_lowpart (V2DImode, res_1),
- op1, op2, true, false);
- ix86_expand_mul_widen_evenodd (gen_lowpart (V2DImode, res_2),
- op1, op2, true, true);
+ res_3 = gen_reg_rtx (V2DImode);
+ res_4 = gen_reg_rtx (V2DImode);
+ ix86_expand_mul_widen_evenodd (res_3, op1, op2, true, false);
+ ix86_expand_mul_widen_evenodd (res_4, op1, op2, true, true);
/* Move the results in element 2 down to element 1; we don't care
what goes in elements 2 and 3. Then we can merge the parts
@@ -41517,9 +42226,11 @@ ix86_expand_sse2_mulv4si3 (rtx op0, rtx op1, rtx op2)
In both cases the cost of the reformatting stall was too high
and the overall sequence slower. */
- emit_insn (gen_sse2_pshufd_1 (res_1, res_1, const0_rtx, const2_rtx,
+ emit_insn (gen_sse2_pshufd_1 (res_1, gen_lowpart (V4SImode, res_3),
+ const0_rtx, const2_rtx,
const0_rtx, const0_rtx));
- emit_insn (gen_sse2_pshufd_1 (res_2, res_2, const0_rtx, const2_rtx,
+ emit_insn (gen_sse2_pshufd_1 (res_2, gen_lowpart (V4SImode, res_4),
+ const0_rtx, const2_rtx,
const0_rtx, const0_rtx));
res_1 = emit_insn (gen_vec_interleave_lowv4si (op0, res_1, res_2));
@@ -41608,6 +42319,68 @@ ix86_expand_sse2_mulvxdi3 (rtx op0, rtx op1, rtx op2)
gen_rtx_MULT (mode, op1, op2));
}
+/* Return 1 if control tansfer instruction INSN
+ should be encoded with bnd prefix.
+ If insn is NULL then return 1 when control
+ transfer instructions should be prefixed with
+ bnd by default for current function. */
+
+bool
+ix86_bnd_prefixed_insn_p (rtx insn ATTRIBUTE_UNUSED)
+{
+ return false;
+}
+
+/* Calculate integer abs() using only SSE2 instructions. */
+
+void
+ix86_expand_sse2_abs (rtx target, rtx input)
+{
+ enum machine_mode mode = GET_MODE (target);
+ rtx tmp0, tmp1, x;
+
+ switch (mode)
+ {
+ /* For 32-bit signed integer X, the best way to calculate the absolute
+ value of X is (((signed) X >> (W-1)) ^ X) - ((signed) X >> (W-1)). */
+ case V4SImode:
+ tmp0 = expand_simple_binop (mode, ASHIFTRT, input,
+ GEN_INT (GET_MODE_BITSIZE
+ (GET_MODE_INNER (mode)) - 1),
+ NULL, 0, OPTAB_DIRECT);
+ tmp1 = expand_simple_binop (mode, XOR, tmp0, input,
+ NULL, 0, OPTAB_DIRECT);
+ x = expand_simple_binop (mode, MINUS, tmp1, tmp0,
+ target, 0, OPTAB_DIRECT);
+ break;
+
+ /* For 16-bit signed integer X, the best way to calculate the absolute
+ value of X is max (X, -X), as SSE2 provides the PMAXSW insn. */
+ case V8HImode:
+ tmp0 = expand_unop (mode, neg_optab, input, NULL_RTX, 0);
+
+ x = expand_simple_binop (mode, SMAX, tmp0, input,
+ target, 0, OPTAB_DIRECT);
+ break;
+
+ /* For 8-bit signed integer X, the best way to calculate the absolute
+ value of X is min ((unsigned char) X, (unsigned char) (-X)),
+ as SSE2 provides the PMINUB insn. */
+ case V16QImode:
+ tmp0 = expand_unop (mode, neg_optab, input, NULL_RTX, 0);
+
+ x = expand_simple_binop (V16QImode, UMIN, tmp0, input,
+ target, 0, OPTAB_DIRECT);
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ if (x != target)
+ emit_move_insn (target, x);
+}
+
/* Expand an insert into a vector register through pinsr insn.
Return true if successful. */
@@ -41676,12 +42449,17 @@ ix86_expand_pinsr (rtx *operands)
return false;
}
- dst = gen_lowpart (dstmode, dst);
+ rtx d = dst;
+ if (GET_MODE (dst) != dstmode)
+ d = gen_reg_rtx (dstmode);
src = gen_lowpart (srcmode, src);
pos /= size;
- emit_insn (pinsr (dst, dst, src, GEN_INT (1 << pos)));
+ emit_insn (pinsr (d, gen_lowpart (dstmode, dst), src,
+ GEN_INT (1 << pos)));
+ if (d != dst)
+ emit_move_insn (dst, gen_lowpart (GET_MODE (dst), d));
return true;
}
@@ -42736,20 +43514,17 @@ ix86_add_stmt_cost (void *data, int count, enum vect_cost_for_stmt kind,
unsigned *cost = (unsigned *) data;
unsigned retval = 0;
- if (flag_vect_cost_model)
- {
- tree vectype = stmt_info ? stmt_vectype (stmt_info) : NULL_TREE;
- int stmt_cost = ix86_builtin_vectorization_cost (kind, vectype, misalign);
+ tree vectype = stmt_info ? stmt_vectype (stmt_info) : NULL_TREE;
+ int stmt_cost = ix86_builtin_vectorization_cost (kind, vectype, misalign);
- /* Statements in an inner loop relative to the loop being
- vectorized are weighted more heavily. The value here is
- arbitrary and could potentially be improved with analysis. */
- if (where == vect_body && stmt_info && stmt_in_inner_loop_p (stmt_info))
- count *= 50; /* FIXME. */
+ /* Statements in an inner loop relative to the loop being
+ vectorized are weighted more heavily. The value here is
+ arbitrary and could potentially be improved with analysis. */
+ if (where == vect_body && stmt_info && stmt_in_inner_loop_p (stmt_info))
+ count *= 50; /* FIXME. */
- retval = (unsigned) (count * stmt_cost);
- cost[where] += retval;
- }
+ retval = (unsigned) (count * stmt_cost);
+ cost[where] += retval;
return retval;
}
@@ -42806,6 +43581,115 @@ ix86_memmodel_check (unsigned HOST_WIDE_INT val)
return val;
}
+/* Implement TARGET_FLOAT_EXCEPTIONS_ROUNDING_SUPPORTED_P. */
+
+static bool
+ix86_float_exceptions_rounding_supported_p (void)
+{
+ /* For x87 floating point with standard excess precision handling,
+ there is no adddf3 pattern (since x87 floating point only has
+ XFmode operations) so the default hook implementation gets this
+ wrong. */
+ return TARGET_80387 || TARGET_SSE_MATH;
+}
+
+/* Implement TARGET_ATOMIC_ASSIGN_EXPAND_FENV. */
+
+static void
+ix86_atomic_assign_expand_fenv (tree *hold, tree *clear, tree *update)
+{
+ if (!TARGET_80387 && !TARGET_SSE_MATH)
+ return;
+ tree exceptions_var = create_tmp_var (integer_type_node, NULL);
+ if (TARGET_80387)
+ {
+ tree fenv_index_type = build_index_type (size_int (6));
+ tree fenv_type = build_array_type (unsigned_type_node, fenv_index_type);
+ tree fenv_var = create_tmp_var (fenv_type, NULL);
+ mark_addressable (fenv_var);
+ tree fenv_ptr = build_pointer_type (fenv_type);
+ tree fenv_addr = build1 (ADDR_EXPR, fenv_ptr, fenv_var);
+ fenv_addr = fold_convert (ptr_type_node, fenv_addr);
+ tree fnstenv = ix86_builtins[IX86_BUILTIN_FNSTENV];
+ tree fldenv = ix86_builtins[IX86_BUILTIN_FLDENV];
+ tree fnstsw = ix86_builtins[IX86_BUILTIN_FNSTSW];
+ tree fnclex = ix86_builtins[IX86_BUILTIN_FNCLEX];
+ tree hold_fnstenv = build_call_expr (fnstenv, 1, fenv_addr);
+ tree hold_fnclex = build_call_expr (fnclex, 0);
+ *hold = build2 (COMPOUND_EXPR, void_type_node, hold_fnstenv,
+ hold_fnclex);
+ *clear = build_call_expr (fnclex, 0);
+ tree sw_var = create_tmp_var (short_unsigned_type_node, NULL);
+ mark_addressable (sw_var);
+ tree su_ptr = build_pointer_type (short_unsigned_type_node);
+ tree sw_addr = build1 (ADDR_EXPR, su_ptr, sw_var);
+ tree fnstsw_call = build_call_expr (fnstsw, 1, sw_addr);
+ tree exceptions_x87 = fold_convert (integer_type_node, sw_var);
+ tree update_mod = build2 (MODIFY_EXPR, integer_type_node,
+ exceptions_var, exceptions_x87);
+ *update = build2 (COMPOUND_EXPR, integer_type_node,
+ fnstsw_call, update_mod);
+ tree update_fldenv = build_call_expr (fldenv, 1, fenv_addr);
+ *update = build2 (COMPOUND_EXPR, void_type_node, *update, update_fldenv);
+ }
+ if (TARGET_SSE_MATH)
+ {
+ tree mxcsr_orig_var = create_tmp_var (unsigned_type_node, NULL);
+ tree mxcsr_mod_var = create_tmp_var (unsigned_type_node, NULL);
+ tree stmxcsr = ix86_builtins[IX86_BUILTIN_STMXCSR];
+ tree ldmxcsr = ix86_builtins[IX86_BUILTIN_LDMXCSR];
+ tree stmxcsr_hold_call = build_call_expr (stmxcsr, 0);
+ tree hold_assign_orig = build2 (MODIFY_EXPR, unsigned_type_node,
+ mxcsr_orig_var, stmxcsr_hold_call);
+ tree hold_mod_val = build2 (BIT_IOR_EXPR, unsigned_type_node,
+ mxcsr_orig_var,
+ build_int_cst (unsigned_type_node, 0x1f80));
+ hold_mod_val = build2 (BIT_AND_EXPR, unsigned_type_node, hold_mod_val,
+ build_int_cst (unsigned_type_node, 0xffffffc0));
+ tree hold_assign_mod = build2 (MODIFY_EXPR, unsigned_type_node,
+ mxcsr_mod_var, hold_mod_val);
+ tree ldmxcsr_hold_call = build_call_expr (ldmxcsr, 1, mxcsr_mod_var);
+ tree hold_all = build2 (COMPOUND_EXPR, unsigned_type_node,
+ hold_assign_orig, hold_assign_mod);
+ hold_all = build2 (COMPOUND_EXPR, void_type_node, hold_all,
+ ldmxcsr_hold_call);
+ if (*hold)
+ *hold = build2 (COMPOUND_EXPR, void_type_node, *hold, hold_all);
+ else
+ *hold = hold_all;
+ tree ldmxcsr_clear_call = build_call_expr (ldmxcsr, 1, mxcsr_mod_var);
+ if (*clear)
+ *clear = build2 (COMPOUND_EXPR, void_type_node, *clear,
+ ldmxcsr_clear_call);
+ else
+ *clear = ldmxcsr_clear_call;
+ tree stxmcsr_update_call = build_call_expr (stmxcsr, 0);
+ tree exceptions_sse = fold_convert (integer_type_node,
+ stxmcsr_update_call);
+ if (*update)
+ {
+ tree exceptions_mod = build2 (BIT_IOR_EXPR, integer_type_node,
+ exceptions_var, exceptions_sse);
+ tree exceptions_assign = build2 (MODIFY_EXPR, integer_type_node,
+ exceptions_var, exceptions_mod);
+ *update = build2 (COMPOUND_EXPR, integer_type_node, *update,
+ exceptions_assign);
+ }
+ else
+ *update = build2 (MODIFY_EXPR, integer_type_node,
+ exceptions_var, exceptions_sse);
+ tree ldmxcsr_update_call = build_call_expr (ldmxcsr, 1, mxcsr_orig_var);
+ *update = build2 (COMPOUND_EXPR, void_type_node, *update,
+ ldmxcsr_update_call);
+ }
+ tree atomic_feraiseexcept
+ = builtin_decl_implicit (BUILT_IN_ATOMIC_FERAISEEXCEPT);
+ tree atomic_feraiseexcept_call = build_call_expr (atomic_feraiseexcept,
+ 1, exceptions_var);
+ *update = build2 (COMPOUND_EXPR, void_type_node, *update,
+ atomic_feraiseexcept_call);
+}
+
/* Initialize the GCC target structure. */
#undef TARGET_RETURN_IN_MEMORY
#define TARGET_RETURN_IN_MEMORY ix86_return_in_memory
@@ -42906,6 +43790,10 @@ ix86_memmodel_check (unsigned HOST_WIDE_INT val)
#undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD
#define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD \
ia32_multipass_dfa_lookahead
+#undef TARGET_SCHED_MACRO_FUSION_P
+#define TARGET_SCHED_MACRO_FUSION_P ix86_macro_fusion_p
+#undef TARGET_SCHED_MACRO_FUSION_PAIR_P
+#define TARGET_SCHED_MACRO_FUSION_PAIR_P ix86_macro_fusion_pair_p
#undef TARGET_FUNCTION_OK_FOR_SIBCALL
#define TARGET_FUNCTION_OK_FOR_SIBCALL ix86_function_ok_for_sibcall
@@ -42913,6 +43801,9 @@ ix86_memmodel_check (unsigned HOST_WIDE_INT val)
#undef TARGET_MEMMODEL_CHECK
#define TARGET_MEMMODEL_CHECK ix86_memmodel_check
+#undef TARGET_ATOMIC_ASSIGN_EXPAND_FENV
+#define TARGET_ATOMIC_ASSIGN_EXPAND_FENV ix86_atomic_assign_expand_fenv
+
#ifdef HAVE_AS_TLS
#undef TARGET_HAVE_TLS
#define TARGET_HAVE_TLS true
@@ -43178,6 +44069,10 @@ ix86_memmodel_check (unsigned HOST_WIDE_INT val)
#undef TARGET_SPILL_CLASS
#define TARGET_SPILL_CLASS ix86_spill_class
+#undef TARGET_FLOAT_EXCEPTIONS_ROUNDING_SUPPORTED_P
+#define TARGET_FLOAT_EXCEPTIONS_ROUNDING_SUPPORTED_P \
+ ix86_float_exceptions_rounding_supported_p
+
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-i386.h"
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 440844e7735..123e3faed4b 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -40,53 +40,101 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
/* Redefines for option macros. */
#define TARGET_64BIT TARGET_ISA_64BIT
+#define TARGET_64BIT_P(x) TARGET_ISA_64BIT_P(x)
#define TARGET_MMX TARGET_ISA_MMX
+#define TARGET_MMX_P(x) TARGET_ISA_MMX_P(x)
#define TARGET_3DNOW TARGET_ISA_3DNOW
+#define TARGET_3DNOW_P(x) TARGET_ISA_3DNOW_P(x)
#define TARGET_3DNOW_A TARGET_ISA_3DNOW_A
+#define TARGET_3DNOW_A_P(x) TARGET_ISA_3DNOW_A_P(x)
#define TARGET_SSE TARGET_ISA_SSE
+#define TARGET_SSE_P(x) TARGET_ISA_SSE_P(x)
#define TARGET_SSE2 TARGET_ISA_SSE2
+#define TARGET_SSE2_P(x) TARGET_ISA_SSE2_P(x)
#define TARGET_SSE3 TARGET_ISA_SSE3
+#define TARGET_SSE3_P(x) TARGET_ISA_SSE3_P(x)
#define TARGET_SSSE3 TARGET_ISA_SSSE3
+#define TARGET_SSSE3_P(x) TARGET_ISA_SSSE3_P(x)
#define TARGET_SSE4_1 TARGET_ISA_SSE4_1
+#define TARGET_SSE4_1_P(x) TARGET_ISA_SSE4_1_P(x)
#define TARGET_SSE4_2 TARGET_ISA_SSE4_2
+#define TARGET_SSE4_2_P(x) TARGET_ISA_SSE4_2_P(x)
#define TARGET_AVX TARGET_ISA_AVX
+#define TARGET_AVX_P(x) TARGET_ISA_AVX_P(x)
#define TARGET_AVX2 TARGET_ISA_AVX2
-#define TARGET_AVX512F TARGET_ISA_AVX512F
-#define TARGET_AVX512PF TARGET_ISA_AVX512PF
-#define TARGET_AVX512ER TARGET_ISA_AVX512ER
-#define TARGET_AVX512CD TARGET_ISA_AVX512CD
+#define TARGET_AVX2_P(x) TARGET_ISA_AVX2_P(x)
+#define TARGET_AVX512F TARGET_ISA_AVX512F
+#define TARGET_AVX512F_P(x) TARGET_ISA_AVX512F_P(x)
+#define TARGET_AVX512PF TARGET_ISA_AVX512PF
+#define TARGET_AVX512PF_P(x) TARGET_ISA_AVX512PF_P(x)
+#define TARGET_AVX512ER TARGET_ISA_AVX512ER
+#define TARGET_AVX512ER_P(x) TARGET_ISA_AVX512ER_P(x)
+#define TARGET_AVX512CD TARGET_ISA_AVX512CD
+#define TARGET_AVX512CD_P(x) TARGET_ISA_AVX512CD_P(x)
#define TARGET_FMA TARGET_ISA_FMA
+#define TARGET_FMA_P(x) TARGET_ISA_FMA_P(x)
#define TARGET_SSE4A TARGET_ISA_SSE4A
+#define TARGET_SSE4A_P(x) TARGET_ISA_SSE4A_P(x)
#define TARGET_FMA4 TARGET_ISA_FMA4
+#define TARGET_FMA4_P(x) TARGET_ISA_FMA4_P(x)
#define TARGET_XOP TARGET_ISA_XOP
+#define TARGET_XOP_P(x) TARGET_ISA_XOP_P(x)
#define TARGET_LWP TARGET_ISA_LWP
+#define TARGET_LWP_P(x) TARGET_ISA_LWP_P(x)
#define TARGET_ROUND TARGET_ISA_ROUND
#define TARGET_ABM TARGET_ISA_ABM
+#define TARGET_ABM_P(x) TARGET_ISA_ABM_P(x)
#define TARGET_BMI TARGET_ISA_BMI
+#define TARGET_BMI_P(x) TARGET_ISA_BMI_P(x)
#define TARGET_BMI2 TARGET_ISA_BMI2
+#define TARGET_BMI2_P(x) TARGET_ISA_BMI2_P(x)
#define TARGET_LZCNT TARGET_ISA_LZCNT
+#define TARGET_LZCNT_P(x) TARGET_ISA_LZCNT_P(x)
#define TARGET_TBM TARGET_ISA_TBM
+#define TARGET_TBM_P(x) TARGET_ISA_TBM_P(x)
#define TARGET_POPCNT TARGET_ISA_POPCNT
+#define TARGET_POPCNT_P(x) TARGET_ISA_POPCNT_P(x)
#define TARGET_SAHF TARGET_ISA_SAHF
+#define TARGET_SAHF_P(x) TARGET_ISA_SAHF_P(x)
#define TARGET_MOVBE TARGET_ISA_MOVBE
+#define TARGET_MOVBE_P(x) TARGET_ISA_MOVBE_P(x)
#define TARGET_CRC32 TARGET_ISA_CRC32
+#define TARGET_CRC32_P(x) TARGET_ISA_CRC32_P(x)
#define TARGET_AES TARGET_ISA_AES
+#define TARGET_AES_P(x) TARGET_ISA_AES_P(x)
#define TARGET_PCLMUL TARGET_ISA_PCLMUL
-#define TARGET_CMPXCHG16B TARGET_ISA_CX16
+#define TARGET_PCLMUL_P(x) TARGET_ISA_PCLMUL_P(x)
+#define TARGET_CMPXCHG16B TARGET_ISA_CX16
+#define TARGET_CMPXCHG16B_P(x) TARGET_ISA_CX16_P(x)
#define TARGET_FSGSBASE TARGET_ISA_FSGSBASE
+#define TARGET_FSGSBASE_P(x) TARGET_ISA_FSGSBASE_P(x)
#define TARGET_RDRND TARGET_ISA_RDRND
+#define TARGET_RDRND_P(x) TARGET_ISA_RDRND_P(x)
#define TARGET_F16C TARGET_ISA_F16C
-#define TARGET_RTM TARGET_ISA_RTM
+#define TARGET_F16C_P(x) TARGET_ISA_F16C_P(x)
+#define TARGET_RTM TARGET_ISA_RTM
+#define TARGET_RTM_P(x) TARGET_ISA_RTM_P(x)
#define TARGET_HLE TARGET_ISA_HLE
+#define TARGET_HLE_P(x) TARGET_ISA_HLE_P(x)
#define TARGET_RDSEED TARGET_ISA_RDSEED
+#define TARGET_RDSEED_P(x) TARGET_ISA_RDSEED_P(x)
#define TARGET_PRFCHW TARGET_ISA_PRFCHW
+#define TARGET_PRFCHW_P(x) TARGET_ISA_PRFCHW_P(x)
#define TARGET_ADX TARGET_ISA_ADX
+#define TARGET_ADX_P(x) TARGET_ISA_ADX_P(x)
#define TARGET_FXSR TARGET_ISA_FXSR
+#define TARGET_FXSR_P(x) TARGET_ISA_FXSR_P(x)
#define TARGET_XSAVE TARGET_ISA_XSAVE
+#define TARGET_XSAVE_P(x) TARGET_ISA_XSAVE_P(x)
#define TARGET_XSAVEOPT TARGET_ISA_XSAVEOPT
+#define TARGET_XSAVEOPT_P(x) TARGET_ISA_XSAVEOPT_P(x)
+#define TARGET_MPX TARGET_ISA_MPX
+#define TARGET_MPX_P(x) TARGET_ISA_MPX_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)
/* SSE4.1 defines round instructions */
#define OPTION_MASK_ISA_ROUND OPTION_MASK_ISA_SSE4_1
@@ -212,7 +260,13 @@ extern const struct processor_costs ix86_size_cost;
(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
+
#define TARGET_FLOAT_RETURNS_IN_80387 TARGET_FLOAT_RETURNS
+#define TARGET_FLOAT_RETURNS_IN_80387_P(x) TARGET_FLOAT_RETURNS_P(x)
/* 64bit Sledgehammer mode. For libgcc2 we make sure this is a
compile-time constant. */
@@ -250,6 +304,7 @@ extern const struct processor_costs ix86_size_cost;
#define TARGET_NOCONA (ix86_tune == PROCESSOR_NOCONA)
#define TARGET_CORE2 (ix86_tune == PROCESSOR_CORE2)
#define TARGET_COREI7 (ix86_tune == PROCESSOR_COREI7)
+#define TARGET_COREI7_AVX (ix86_tune == PROCESSOR_COREI7_AVX)
#define TARGET_HASWELL (ix86_tune == PROCESSOR_HASWELL)
#define TARGET_GENERIC (ix86_tune == PROCESSOR_GENERIC)
#define TARGET_AMDFAM10 (ix86_tune == PROCESSOR_AMDFAM10)
@@ -298,6 +353,8 @@ extern unsigned char ix86_tune_features[X86_TUNE_LAST];
#define TARGET_PROMOTE_QImode ix86_tune_features[X86_TUNE_PROMOTE_QIMODE]
#define TARGET_FAST_PREFIX ix86_tune_features[X86_TUNE_FAST_PREFIX]
#define TARGET_SINGLE_STRINGOP ix86_tune_features[X86_TUNE_SINGLE_STRINGOP]
+#define TARGET_MISALIGNED_MOVE_STRING_PRO_EPILOGUES \
+ ix86_tune_features[X86_TUNE_MISALIGNED_MOVE_STRING_PRO_EPILOGUES]
#define TARGET_QIMODE_MATH ix86_tune_features[X86_TUNE_QIMODE_MATH]
#define TARGET_HIMODE_MATH ix86_tune_features[X86_TUNE_HIMODE_MATH]
#define TARGET_PROMOTE_QI_REGS ix86_tune_features[X86_TUNE_PROMOTE_QI_REGS]
@@ -359,8 +416,17 @@ extern unsigned char ix86_tune_features[X86_TUNE_LAST];
ix86_tune_features[X86_TUNE_USE_VECTOR_FP_CONVERTS]
#define TARGET_USE_VECTOR_CONVERTS \
ix86_tune_features[X86_TUNE_USE_VECTOR_CONVERTS]
+#define TARGET_FUSE_CMP_AND_BRANCH_32 \
+ ix86_tune_features[X86_TUNE_FUSE_CMP_AND_BRANCH_32]
+#define TARGET_FUSE_CMP_AND_BRANCH_64 \
+ ix86_tune_features[X86_TUNE_FUSE_CMP_AND_BRANCH_64]
#define TARGET_FUSE_CMP_AND_BRANCH \
- ix86_tune_features[X86_TUNE_FUSE_CMP_AND_BRANCH]
+ (TARGET_64BIT ? TARGET_FUSE_CMP_AND_BRANCH_64 \
+ : TARGET_FUSE_CMP_AND_BRANCH_32)
+#define TARGET_FUSE_CMP_AND_BRANCH_SOFLAGS \
+ ix86_tune_features[X86_TUNE_FUSE_CMP_AND_BRANCH_SOFLAGS]
+#define TARGET_FUSE_ALU_AND_BRANCH \
+ ix86_tune_features[X86_TUNE_FUSE_ALU_AND_BRANCH]
#define TARGET_OPT_AGU ix86_tune_features[X86_TUNE_OPT_AGU]
#define TARGET_VECTORIZE_DOUBLE \
ix86_tune_features[X86_TUNE_VECTORIZE_DOUBLE]
@@ -557,6 +623,7 @@ enum target_cpu_default
TARGET_CPU_DEFAULT_nocona,
TARGET_CPU_DEFAULT_core2,
TARGET_CPU_DEFAULT_corei7,
+ TARGET_CPU_DEFAULT_corei7_avx,
TARGET_CPU_DEFAULT_haswell,
TARGET_CPU_DEFAULT_atom,
TARGET_CPU_DEFAULT_slm,
@@ -891,7 +958,7 @@ enum target_cpu_default
eliminated during reloading in favor of either the stack or frame
pointer. */
-#define FIRST_PSEUDO_REGISTER 77
+#define FIRST_PSEUDO_REGISTER 81
/* Number of hardware registers that go into the DWARF-2 unwind info.
If not defined, equals FIRST_PSEUDO_REGISTER. */
@@ -923,7 +990,9 @@ enum target_cpu_default
/*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 }
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+/* b0, b1, b2, b3*/ \
+ 0, 0, 0, 0 }
/* 1 for registers not available across function calls.
These must include the FIXED_REGISTERS and also any
@@ -957,7 +1026,9 @@ enum target_cpu_default
/*xmm24,xmm25,xmm26,xmm27,xmm28,xmm29,xmm30,xmm31*/ \
6, 6, 6, 6, 6, 6, 6, 6, \
/* k0, k1, k2, k3, k4, k5, k6, k7*/ \
- 1, 1, 1, 1, 1, 1, 1, 1 }
+ 1, 1, 1, 1, 1, 1, 1, 1, \
+/* b0, b1, b2, b3*/ \
+ 1, 1, 1, 1 }
/* Order in which to allocate registers. Each register must be
listed once, even those in FIXED_REGISTERS. List frame pointer
@@ -973,7 +1044,8 @@ enum target_cpu_default
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, 76 }
+ 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, \
+ 78, 79, 80 }
/* ADJUST_REG_ALLOC_ORDER is a macro which permits reg_alloc_order
to be rearranged based on a particular function. When using sse math,
@@ -995,6 +1067,7 @@ enum target_cpu_default
#define HARD_REGNO_NREGS(REGNO, MODE) \
(STACK_REGNO_P (REGNO) || SSE_REGNO_P (REGNO) || MMX_REGNO_P (REGNO) \
+ || BND_REGNO_P (REGNO) \
? (COMPLEX_MODE_P (MODE) ? 2 : 1) \
: ((MODE) == XFmode \
? (TARGET_64BIT ? 2 : 3) \
@@ -1044,6 +1117,9 @@ enum target_cpu_default
|| (MODE) == V2SImode || (MODE) == SImode \
|| (MODE) == V4HImode || (MODE) == V8QImode)
+#define VALID_BND_REG_MODE(MODE) \
+ (TARGET_64BIT ? (MODE) == BND64mode : (MODE) == BND32mode)
+
#define VALID_DFP_MODE_P(MODE) \
((MODE) == SDmode || (MODE) == DDmode || (MODE) == TDmode)
@@ -1150,6 +1226,9 @@ enum target_cpu_default
#define FIRST_MASK_REG (LAST_EXT_REX_SSE_REG + 1) /*69*/
#define LAST_MASK_REG (FIRST_MASK_REG + 7) /*76*/
+#define FIRST_BND_REG (LAST_MASK_REG + 1) /*77*/
+#define LAST_BND_REG (FIRST_BND_REG + 3) /*80*/
+
/* Override this in other tm.h files to cope with various OS lossage
requiring a frame pointer. */
#ifndef SUBTARGET_FRAME_POINTER_REQUIRED
@@ -1230,6 +1309,7 @@ enum reg_class
SSE_FIRST_REG,
SSE_REGS,
EVEX_SSE_REGS,
+ BND_REGS,
ALL_SSE_REGS,
MMX_REGS,
FP_TOP_SSE_REGS,
@@ -1287,6 +1367,7 @@ enum reg_class
"SSE_FIRST_REG", \
"SSE_REGS", \
"EVEX_SSE_REGS", \
+ "BND_REGS", \
"ALL_SSE_REGS", \
"MMX_REGS", \
"FP_TOP_SSE_REGS", \
@@ -1306,37 +1387,38 @@ enum reg_class
TARGET_CONDITIONAL_REGISTER_USAGE. */
#define REG_CLASS_CONTENTS \
-{ { 0x00, 0x0, 0x0 }, \
- { 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 */ \
- { 0x0f, 0x0, 0x0 }, /* Q_REGS */ \
- { 0x1100f0, 0x1fe0, 0x0 }, /* NON_Q_REGS */ \
- { 0x7f, 0x1fe0, 0x0 }, /* INDEX_REGS */ \
- { 0x1100ff, 0x0, 0x0 }, /* LEGACY_REGS */ \
- { 0x07, 0x0, 0x0 }, /* CLOBBERED_REGS */ \
- { 0x1100ff, 0x1fe0, 0x0 }, /* GENERAL_REGS */ \
- { 0x100, 0x0, 0x0 }, /* FP_TOP_REG */ \
- { 0x0200, 0x0, 0x0 }, /* FP_SECOND_REG */ \
- { 0xff00, 0x0, 0x0 }, /* FLOAT_REGS */ \
- { 0x200000, 0x0, 0x0 }, /* SSE_FIRST_REG */ \
-{ 0x1fe00000, 0x1fe000, 0x0 }, /* SSE_REGS */ \
- { 0x0,0xffe00000, 0x1f }, /* EVEX_SSE_REGS */ \
-{ 0x1fe00000,0xffffe000, 0x1f }, /* ALL_SSE_REGS */ \
-{ 0xe0000000, 0x1f, 0x0 }, /* MMX_REGS */ \
-{ 0x1fe00100,0xffffe000, 0x1f }, /* FP_TOP_SSE_REG */ \
-{ 0x1fe00200,0xffffe000, 0x1f }, /* FP_SECOND_SSE_REG */ \
-{ 0x1fe0ff00,0xffffe000, 0x1f }, /* FLOAT_SSE_REGS */ \
-{ 0x11ffff, 0x1fe0, 0x0 }, /* FLOAT_INT_REGS */ \
-{ 0x1ff100ff,0xffffffe0, 0x1f }, /* INT_SSE_REGS */ \
-{ 0x1ff1ffff,0xffffffe0, 0x1f }, /* FLOAT_INT_SSE_REGS */ \
- { 0x0, 0x0,0x1fc0 }, /* MASK_EVEX_REGS */ \
- { 0x0, 0x0,0x1fe0 }, /* MASK_REGS */ \
-{ 0xffffffff,0xffffffff,0x1fff } \
+{ { 0x00, 0x0, 0x0 }, \
+ { 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 */ \
+ { 0x0f, 0x0, 0x0 }, /* Q_REGS */ \
+ { 0x1100f0, 0x1fe0, 0x0 }, /* NON_Q_REGS */ \
+ { 0x7f, 0x1fe0, 0x0 }, /* INDEX_REGS */ \
+ { 0x1100ff, 0x0, 0x0 }, /* LEGACY_REGS */ \
+ { 0x07, 0x0, 0x0 }, /* CLOBBERED_REGS */ \
+ { 0x1100ff, 0x1fe0, 0x0 }, /* GENERAL_REGS */ \
+ { 0x100, 0x0, 0x0 }, /* FP_TOP_REG */ \
+ { 0x0200, 0x0, 0x0 }, /* FP_SECOND_REG */ \
+ { 0xff00, 0x0, 0x0 }, /* FLOAT_REGS */ \
+ { 0x200000, 0x0, 0x0 }, /* SSE_FIRST_REG */ \
+{ 0x1fe00000, 0x1fe000, 0x0 }, /* SSE_REGS */ \
+ { 0x0,0xffe00000, 0x1f }, /* EVEX_SSE_REGS */ \
+ { 0x0, 0x0,0x1e000 }, /* BND_REGS */ \
+{ 0x1fe00000,0xffffe000, 0x1f }, /* ALL_SSE_REGS */ \
+{ 0xe0000000, 0x1f, 0x0 }, /* MMX_REGS */ \
+{ 0x1fe00100,0xffffe000, 0x1f }, /* FP_TOP_SSE_REG */ \
+{ 0x1fe00200,0xffffe000, 0x1f }, /* FP_SECOND_SSE_REG */ \
+{ 0x1fe0ff00,0xffffe000, 0x1f }, /* FLOAT_SSE_REGS */ \
+{ 0x11ffff, 0x1fe0, 0x0 }, /* FLOAT_INT_REGS */ \
+{ 0x1ff100ff,0xffffffe0, 0x1f }, /* INT_SSE_REGS */ \
+{ 0x1ff1ffff,0xffffffe0, 0x1f }, /* FLOAT_INT_SSE_REGS */ \
+ { 0x0, 0x0, 0x1fc0 }, /* MASK_EVEX_REGS */ \
+ { 0x0, 0x0, 0x1fe0 }, /* MASK_REGS */ \
+{ 0xffffffff,0xffffffff, 0x1fff } \
}
/* The same information, inverted:
@@ -1412,6 +1494,9 @@ enum reg_class
#define CC_REG_P(X) (REG_P (X) && CC_REGNO_P (REGNO (X)))
#define CC_REGNO_P(X) ((X) == FLAGS_REG || (X) == FPSR_REG)
+#define BND_REGNO_P(N) IN_RANGE ((N), FIRST_BND_REG, LAST_BND_REG)
+#define ANY_BND_REG_P(X) (REG_P (X) && BND_REGNO_P (REGNO (X)))
+
/* The class value for index registers, and the one for base regs. */
#define INDEX_REG_CLASS INDEX_REGS
@@ -1492,13 +1577,26 @@ enum reg_class
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 becuase 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 grouw with accumulation. Is that because accumulated args
+ unwind info became unnecesarily bloated?
64-bit MS ABI seem to require 16 byte alignment everywhere except for
- function prologue and apilogue. This is not possible without
- ACCUMULATE_OUTGOING_ARGS. */
+ function prologue and epilogue. This is not possible without
+ ACCUMULATE_OUTGOING_ARGS.
+
+ 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. */
#define ACCUMULATE_OUTGOING_ARGS \
- (TARGET_ACCUMULATE_OUTGOING_ARGS || TARGET_64BIT_MS_ABI)
+ ((TARGET_ACCUMULATE_OUTGOING_ARGS && optimize_function_for_speed_p (cfun)) \
+ || TARGET_STACK_PROBE || TARGET_64BIT_MS_ABI)
/* If defined, a C expression whose value is nonzero when we want to use PUSH
instructions to pass outgoing arguments. */
@@ -1843,6 +1941,9 @@ do { \
between pointers and any other objects of this machine mode. */
#define Pmode (ix86_pmode == PMODE_DI ? DImode : SImode)
+/* Specify the machine mode that bounds have. */
+#define BNDmode (ix86_pmode == PMODE_DI ? BND64mode : BND32mode)
+
/* 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
@@ -1953,7 +2054,8 @@ do { \
"xmm20", "xmm21", "xmm22", "xmm23", \
"xmm24", "xmm25", "xmm26", "xmm27", \
"xmm28", "xmm29", "xmm30", "xmm31", \
- "k0", "k1", "k2", "k3", "k4", "k5", "k6", "k7" }
+ "k0", "k1", "k2", "k3", "k4", "k5", "k6", "k7", \
+ "bnd0", "bnd1", "bnd2", "bnd3" }
#define REGISTER_NAMES HI_REGISTER_NAMES
@@ -2138,6 +2240,7 @@ enum processor_type
PROCESSOR_NOCONA,
PROCESSOR_CORE2,
PROCESSOR_COREI7,
+ PROCESSOR_COREI7_AVX,
PROCESSOR_HASWELL,
PROCESSOR_GENERIC,
PROCESSOR_AMDFAM10,
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index e009bc96fc2..a37fa64a03e 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -63,6 +63,7 @@
;; ~ -- print "i" if TARGET_AVX2, "f" otherwise.
;; @ -- print a segment register of thread base pointer load
;; ^ -- print addr32 prefix if TARGET_64BIT and Pmode != word_mode
+;; ! -- print MPX prefix for jxx/call/ret instructions if required.
(define_c_enum "unspec" [
;; Relocation specifiers
@@ -178,6 +179,16 @@
;; For BMI2 support
UNSPEC_PDEP
UNSPEC_PEXT
+
+ UNSPEC_BNDMK
+ UNSPEC_BNDMK_ADDR
+ UNSPEC_BNDSTX
+ UNSPEC_BNDLDX
+ UNSPEC_BNDLDX_ADDR
+ UNSPEC_BNDCL
+ UNSPEC_BNDCU
+ UNSPEC_BNDCN
+ UNSPEC_MPX_FENCE
])
(define_c_enum "unspecv" [
@@ -211,6 +222,12 @@
UNSPECV_XSAVEOPT
UNSPECV_XSAVEOPT64
+ ;; For atomic compound assignments.
+ UNSPECV_FNSTENV
+ UNSPECV_FLDENV
+ UNSPECV_FNSTSW
+ UNSPECV_FNCLEX
+
;; For RDRAND support
UNSPECV_RDRAND
@@ -336,6 +353,8 @@
(MASK5_REG 74)
(MASK6_REG 75)
(MASK7_REG 76)
+ (BND0_REG 77)
+ (BND1_REG 78)
])
;; Insns whose names begin with "x86_" are emitted by gen_FOO calls
@@ -369,7 +388,8 @@
ssecvt,ssecvt1,sseicvt,sseins,
sseshuf,sseshuf1,ssemuladd,sse4arg,
lwp,mskmov,msklog,
- mmx,mmxmov,mmxadd,mmxmul,mmxcmp,mmxcvt,mmxshft"
+ mmx,mmxmov,mmxadd,mmxmul,mmxcmp,mmxcvt,mmxshft,
+ mpxmov,mpxmk,mpxchk,mpxld,mpxst"
(const_string "other"))
;; Main data type used by the insn
@@ -398,7 +418,8 @@
;; The (bounding maximum) length of an instruction immediate.
(define_attr "length_immediate" ""
(cond [(eq_attr "type" "incdec,setcc,icmov,str,lea,other,multi,idiv,leave,
- bitmanip,imulx,msklog,mskmov")
+ bitmanip,imulx,msklog,mskmov,mpxmk,mpxmov,mpxchk,
+ mpxld,mpxst")
(const_int 0)
(eq_attr "unit" "i387,sse,mmx")
(const_int 0)
@@ -453,13 +474,17 @@
(const_int 0)
(and (eq_attr "unit" "sse") (eq_attr "mode" "SF,DF"))
(const_int 1)
+ (and (eq_attr "type" "ibr,call,callv")
+ (match_test "ix86_bnd_prefixed_insn_p (insn)"))
+ (const_int 1)
]
(const_int 0)))
;; Set when 0f opcode prefix is used.
(define_attr "prefix_0f" ""
(if_then_else
- (ior (eq_attr "type" "imovx,setcc,icmov,bitmanip,msklog,mskmov")
+ (ior (eq_attr "type" "imovx,setcc,icmov,bitmanip,msklog,mskmov,
+ mpxmk,mpxmov,mpxchk,mpxld,mpxst")
(eq_attr "unit" "sse,mmx"))
(const_int 1)
(const_int 0)))
@@ -562,12 +587,19 @@
]
(const_int 1)))
+;; When this attribute is set, calculate total insn length from
+;; length_nobnd attribute, prefixed with eventual bnd prefix byte
+(define_attr "length_nobnd" "" (const_int 0))
+
;; The (bounding maximum) length of an instruction in bytes.
;; ??? fistp and frndint are in fact fldcw/{fistp,frndint}/fldcw sequences.
;; Later we may want to split them and compute proper length as for
;; other insns.
(define_attr "length" ""
- (cond [(eq_attr "type" "other,multi,fistp,frndint")
+ (cond [(eq_attr "length_nobnd" "!0")
+ (plus (symbol_ref ("ix86_bnd_prefixed_insn_p (insn)"))
+ (attr "length_nobnd"))
+ (eq_attr "type" "other,multi,fistp,frndint")
(const_int 16)
(eq_attr "type" "fcmp")
(const_int 4)
@@ -608,12 +640,16 @@
(define_attr "memory" "none,load,store,both,unknown"
(cond [(eq_attr "type" "other,multi,str,lwp")
(const_string "unknown")
- (eq_attr "type" "lea,fcmov,fpspc")
+ (eq_attr "type" "lea,fcmov,fpspc,mpxmk,mpxchk")
(const_string "none")
(eq_attr "type" "fistp,leave")
(const_string "both")
(eq_attr "type" "frndint")
(const_string "load")
+ (eq_attr "type" "mpxld")
+ (const_string "load")
+ (eq_attr "type" "mpxst")
+ (const_string "store")
(eq_attr "type" "push")
(if_then_else (match_operand 1 "memory_operand")
(const_string "both")
@@ -659,7 +695,7 @@
fmov,fcmp,fsgn,
sse,ssemov,ssecmp,ssecomi,ssecvt,ssecvt1,sseicvt,
sselog1,sseshuf1,sseadd1,sseiadd1,sseishft1,
- mmx,mmxmov,mmxcmp,mmxcvt,mskmov,msklog")
+ mmx,mmxmov,mmxcmp,mmxcvt,mskmov,msklog,mpxmov")
(match_operand 2 "memory_operand"))
(const_string "load")
(and (eq_attr "type" "icmov,ssemuladd,sse4arg")
@@ -746,6 +782,8 @@
(define_code_iterator sat_plusminus [ss_plus us_plus ss_minus us_minus])
+(define_code_iterator multdiv [mult div])
+
;; Base name for define_insn
(define_code_attr plusminus_insn
[(plus "add") (ss_plus "ssadd") (us_plus "usadd")
@@ -757,6 +795,8 @@
(minus "sub") (ss_minus "subs") (us_minus "subus")])
(define_code_attr plusminus_carry_mnemonic
[(plus "adc") (minus "sbb")])
+(define_code_attr multdiv_mnemonic
+ [(mult "mul") (div "div")])
;; Mark commutative operators as such in constraints.
(define_code_attr comm [(plus "%") (ss_plus "%") (us_plus "%")
@@ -779,6 +819,7 @@
;; Mapping of logic operators
(define_code_iterator any_logic [and ior xor])
(define_code_iterator any_or [ior xor])
+(define_code_iterator fpint_logic [and xor])
;; Base name for insn mnemonic.
(define_code_attr logic [(and "and") (ior "or") (xor "xor")])
@@ -826,6 +867,15 @@
(define_code_attr s [(sign_extend "s") (zero_extend "u")])
(define_code_attr u_bool [(sign_extend "false") (zero_extend "true")])
+;; Used in signed and unsigned truncations.
+(define_code_iterator any_truncate [ss_truncate truncate us_truncate])
+;; Instruction suffix for truncations.
+(define_code_attr trunsuffix [(ss_truncate "s") (truncate "") (us_truncate "us")])
+
+;; Used in signed and unsigned fix.
+(define_code_iterator any_fix [fix unsigned_fix])
+(define_code_attr fixsuffix [(fix "") (unsigned_fix "u")])
+
;; All integer modes.
(define_mode_iterator SWI1248x [QI HI SI DI])
@@ -884,6 +934,21 @@
(define_mode_iterator DWIH [(SI "!TARGET_64BIT")
(DI "TARGET_64BIT")])
+;; Bound modes.
+(define_mode_iterator BND [(BND32 "!TARGET_LP64")
+ (BND64 "TARGET_LP64")])
+
+;; Pointer mode corresponding to bound mode.
+(define_mode_attr bnd_ptr [(BND32 "SI") (BND64 "DI")])
+
+;; MPX check types
+(define_int_iterator BNDCHECK [UNSPEC_BNDCL UNSPEC_BNDCU UNSPEC_BNDCN])
+
+;; Check name
+(define_int_attr bndcheck [(UNSPEC_BNDCL "cl")
+ (UNSPEC_BNDCU "cu")
+ (UNSPEC_BNDCN "cn")])
+
;; Instruction suffix for integer modes.
(define_mode_attr imodesuffix [(QI "b") (HI "w") (SI "l") (DI "q")])
@@ -1610,7 +1675,7 @@
split_double_mode (DImode, &operands[1], 1, &operands[2], &operands[3]);
operands[1] = gen_lowpart (DImode, operands[2]);
- operands[2] = gen_rtx_MEM (SImode, gen_rtx_PLUS (DImode, stack_pointer_rtx,
+ operands[2] = gen_rtx_MEM (SImode, gen_rtx_PLUS (Pmode, stack_pointer_rtx,
GEN_INT (4)));
})
@@ -1627,7 +1692,7 @@
split_double_mode (DImode, &operands[1], 1, &operands[2], &operands[3]);
operands[1] = gen_lowpart (DImode, operands[2]);
- operands[2] = gen_rtx_MEM (SImode, gen_rtx_PLUS (DImode, stack_pointer_rtx,
+ operands[2] = gen_rtx_MEM (SImode, gen_rtx_PLUS (Pmode, stack_pointer_rtx,
GEN_INT (4)));
})
@@ -1948,11 +2013,10 @@
return "pxor\t%0, %0";
case TYPE_MMXMOV:
-#ifndef HAVE_AS_IX86_INTERUNIT_MOVQ
/* Handle broken assemblers that require movd instead of movq. */
- if (GENERAL_REG_P (operands[0]) || GENERAL_REG_P (operands[1]))
+ if (!HAVE_AS_IX86_INTERUNIT_MOVQ
+ && (GENERAL_REG_P (operands[0]) || GENERAL_REG_P (operands[1])))
return "movd\t{%1, %0|%0, %1}";
-#endif
return "movq\t{%1, %0|%0, %1}";
case TYPE_SSELOG1:
@@ -1965,11 +2029,10 @@
switch (get_attr_mode (insn))
{
case MODE_DI:
-#ifndef HAVE_AS_IX86_INTERUNIT_MOVQ
/* Handle broken assemblers that require movd instead of movq. */
- if (GENERAL_REG_P (operands[0]) || GENERAL_REG_P (operands[1]))
+ if (!HAVE_AS_IX86_INTERUNIT_MOVQ
+ && (GENERAL_REG_P (operands[0]) || GENERAL_REG_P (operands[1])))
return "%vmovd\t{%1, %0|%0, %1}";
-#endif
return "%vmovq\t{%1, %0|%0, %1}";
case MODE_TI:
return "%vmovdqa\t{%1, %0|%0, %1}";
@@ -2293,9 +2356,12 @@
;; For loads of Q_REG to NONQ_REG we use full sized moves except for partial
;; register stall machines with, where we use QImode instructions, since
;; partial register stall can be caused there. Then we use movzx.
+
(define_insn "*movqi_internal"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=q,q ,q ,r,r ,?r,m ,Yk,Yk,r")
- (match_operand:QI 1 "general_operand" "q ,qn,qm,q,rn,qm,qn,r ,Yk,Yk"))]
+ [(set (match_operand:QI 0 "nonimmediate_operand"
+ "=q,q ,q ,r,r ,?r,m ,Yk,Yk,r")
+ (match_operand:QI 1 "general_operand"
+ "q ,qn,qm,q,rn,qm,qn,r ,Yk,Yk"))]
"!(MEM_P (operands[0]) && MEM_P (operands[1]))"
{
switch (get_attr_type (insn))
@@ -2882,12 +2948,11 @@
return "movlpd\t{%1, %0|%0, %1}";
case MODE_DI:
-#ifndef HAVE_AS_IX86_INTERUNIT_MOVQ
/* Handle broken assemblers that require movd instead of movq. */
- if (GENERAL_REG_P (operands[0]) || GENERAL_REG_P (operands[1]))
+ if (!HAVE_AS_IX86_INTERUNIT_MOVQ
+ && (GENERAL_REG_P (operands[0]) || GENERAL_REG_P (operands[1])))
return "%vmovd\t{%1, %0|%0, %1}";
-#endif
- return "%vmovq\t{%1, %0|%0, %1}";
+ return "%vmovq\t{%1, %0|%0, %1}";
default:
gcc_unreachable ();
@@ -5116,6 +5181,61 @@
emit_move_insn (operands[0], CONST0_RTX (<ssevecmode>mode));
})
+;; Break partial reg stall for cvtsd2ss.
+
+(define_peephole2
+ [(set (match_operand:SF 0 "register_operand")
+ (float_truncate:SF
+ (match_operand:DF 1 "nonimmediate_operand")))]
+ "TARGET_SSE2 && TARGET_SSE_MATH
+ && TARGET_SSE_PARTIAL_REG_DEPENDENCY
+ && optimize_function_for_speed_p (cfun)
+ && SSE_REG_P (operands[0])
+ && (!SSE_REG_P (operands[1])
+ || REGNO (operands[0]) != REGNO (operands[1]))"
+ [(set (match_dup 0)
+ (vec_merge:V4SF
+ (vec_duplicate:V4SF
+ (float_truncate:V2SF
+ (match_dup 1)))
+ (match_dup 0)
+ (const_int 1)))]
+{
+ operands[0] = simplify_gen_subreg (V4SFmode, operands[0],
+ SFmode, 0);
+ operands[1] = simplify_gen_subreg (V2DFmode, operands[1],
+ DFmode, 0);
+ emit_move_insn (operands[0], CONST0_RTX (V4SFmode));
+})
+
+;; Break partial reg stall for cvtss2sd.
+
+(define_peephole2
+ [(set (match_operand:DF 0 "register_operand")
+ (float_extend:DF
+ (match_operand:SF 1 "nonimmediate_operand")))]
+ "TARGET_SSE2 && TARGET_SSE_MATH
+ && TARGET_SSE_PARTIAL_REG_DEPENDENCY
+ && optimize_function_for_speed_p (cfun)
+ && SSE_REG_P (operands[0])
+ && (!SSE_REG_P (operands[1])
+ || REGNO (operands[0]) != REGNO (operands[1]))"
+ [(set (match_dup 0)
+ (vec_merge:V2DF
+ (float_extend:V2DF
+ (vec_select:V2SF
+ (match_dup 1)
+ (parallel [(const_int 0) (const_int 1)])))
+ (match_dup 0)
+ (const_int 1)))]
+{
+ operands[0] = simplify_gen_subreg (V2DFmode, operands[0],
+ DFmode, 0);
+ operands[1] = simplify_gen_subreg (V4SFmode, operands[1],
+ SFmode, 0);
+ emit_move_insn (operands[0], CONST0_RTX (V2DFmode));
+})
+
;; Avoid store forwarding (partial memory) stall penalty
;; by passing DImode value through XMM registers. */
@@ -5280,7 +5400,7 @@
(define_insn_and_split "*lea<mode>"
[(set (match_operand:SWI48 0 "register_operand" "=r")
- (match_operand:SWI48 1 "lea_address_operand" "p"))]
+ (match_operand:SWI48 1 "address_no_seg_operand" "Ts"))]
""
{
if (SImode_address_operand (operands[1], VOIDmode))
@@ -6422,7 +6542,7 @@
(set_attr "use_carry" "1")
(set_attr "mode" "<MODE>")])
-;; Overflow setting add and subtract instructions
+;; Overflow setting add instructions
(define_insn "*add<mode>3_cconly_overflow"
[(set (reg:CCC FLAGS_REG)
@@ -6437,43 +6557,31 @@
[(set_attr "type" "alu")
(set_attr "mode" "<MODE>")])
-(define_insn "*sub<mode>3_cconly_overflow"
- [(set (reg:CCC FLAGS_REG)
- (compare:CCC
- (minus:SWI
- (match_operand:SWI 0 "nonimmediate_operand" "<r>m,<r>")
- (match_operand:SWI 1 "<general_operand>" "<r><i>,<r>m"))
- (match_dup 0)))]
- ""
- "cmp{<imodesuffix>}\t{%1, %0|%0, %1}"
- [(set_attr "type" "icmp")
- (set_attr "mode" "<MODE>")])
-
-(define_insn "*<plusminus_insn><mode>3_cc_overflow"
+(define_insn "*add<mode>3_cc_overflow"
[(set (reg:CCC FLAGS_REG)
(compare:CCC
- (plusminus:SWI
- (match_operand:SWI 1 "nonimmediate_operand" "<comm>0,0")
+ (plus:SWI
+ (match_operand:SWI 1 "nonimmediate_operand" "%0,0")
(match_operand:SWI 2 "<general_operand>" "<r><i>,<r>m"))
(match_dup 1)))
(set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>")
- (plusminus:SWI (match_dup 1) (match_dup 2)))]
- "ix86_binary_operator_ok (<CODE>, <MODE>mode, operands)"
- "<plusminus_mnemonic>{<imodesuffix>}\t{%2, %0|%0, %2}"
+ (plus:SWI (match_dup 1) (match_dup 2)))]
+ "ix86_binary_operator_ok (PLUS, <MODE>mode, operands)"
+ "add{<imodesuffix>}\t{%2, %0|%0, %2}"
[(set_attr "type" "alu")
(set_attr "mode" "<MODE>")])
-(define_insn "*<plusminus_insn>si3_zext_cc_overflow"
+(define_insn "*addsi3_zext_cc_overflow"
[(set (reg:CCC FLAGS_REG)
(compare:CCC
- (plusminus:SI
- (match_operand:SI 1 "nonimmediate_operand" "<comm>0")
+ (plus:SI
+ (match_operand:SI 1 "nonimmediate_operand" "%0")
(match_operand:SI 2 "x86_64_general_operand" "rme"))
(match_dup 1)))
(set (match_operand:DI 0 "register_operand" "=r")
- (zero_extend:DI (plusminus:SI (match_dup 1) (match_dup 2))))]
- "TARGET_64BIT && ix86_binary_operator_ok (<CODE>, SImode, operands)"
- "<plusminus_mnemonic>{l}\t{%2, %k0|%k0, %2}"
+ (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
+ "TARGET_64BIT && ix86_binary_operator_ok (PLUS, SImode, operands)"
+ "add{l}\t{%2, %k0|%k0, %2}"
[(set_attr "type" "alu")
(set_attr "mode" "SI")])
@@ -7764,8 +7872,7 @@
(parallel [(set (match_dup 0)
(and:HI (match_dup 0)
(match_dup 1)))
- (clobber (reg:CC FLAGS_REG))])]
- "")
+ (clobber (reg:CC FLAGS_REG))])])
;; Turn *anddi_1 into *andsi_1_zext if possible.
(define_split
@@ -8190,7 +8297,8 @@
(not:SWI12
(xor:SWI12
(match_operand:SWI12 1 "register_operand" "0,Yk")
- (match_operand:SWI12 2 "register_operand" "r,Yk"))))]
+ (match_operand:SWI12 2 "register_operand" "r,Yk"))))
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_AVX512F"
"@
#
@@ -8204,15 +8312,15 @@
(not:SWI12
(xor:SWI12
(match_dup 0)
- (match_operand:SWI12 1 "general_reg_operand"))))]
+ (match_operand:SWI12 1 "general_reg_operand"))))
+ (clobber (reg:CC FLAGS_REG))]
"TARGET_AVX512F && reload_completed"
[(parallel [(set (match_dup 0)
(xor:HI (match_dup 0)
(match_dup 1)))
(clobber (reg:CC FLAGS_REG))])
(set (match_dup 0)
- (not:HI (match_dup 0)))]
- "")
+ (not:HI (match_dup 0)))])
(define_insn "kortestzhi"
[(set (reg:CCZ FLAGS_REG)
@@ -10679,10 +10787,10 @@
(label_ref (match_operand 0))
(pc)))]
""
- "%+j%C1\t%l0"
+ "%!%+j%C1\t%l0"
[(set_attr "type" "ibr")
(set_attr "modrm" "0")
- (set (attr "length")
+ (set (attr "length_nobnd")
(if_then_else (and (ge (minus (match_dup 0) (pc))
(const_int -126))
(lt (minus (match_dup 0) (pc))
@@ -10697,10 +10805,10 @@
(pc)
(label_ref (match_operand 0))))]
""
- "%+j%c1\t%l0"
+ "%!%+j%c1\t%l0"
[(set_attr "type" "ibr")
(set_attr "modrm" "0")
- (set (attr "length")
+ (set (attr "length_nobnd")
(if_then_else (and (ge (minus (match_dup 0) (pc))
(const_int -126))
(lt (minus (match_dup 0) (pc))
@@ -11163,9 +11271,9 @@
[(set (pc)
(label_ref (match_operand 0)))]
""
- "jmp\t%l0"
+ "%!jmp\t%l0"
[(set_attr "type" "ibr")
- (set (attr "length")
+ (set (attr "length_nobnd")
(if_then_else (and (ge (minus (match_dup 0) (pc))
(const_int -126))
(lt (minus (match_dup 0) (pc))
@@ -11185,7 +11293,7 @@
(define_insn "*indirect_jump"
[(set (pc) (match_operand:W 0 "indirect_branch_operand" "rw"))]
""
- "jmp\t%A0"
+ "%!jmp\t%A0"
[(set_attr "type" "ibr")
(set_attr "length_immediate" "0")])
@@ -11234,7 +11342,7 @@
[(set (pc) (match_operand:W 0 "indirect_branch_operand" "rw"))
(use (label_ref (match_operand 1)))]
""
- "jmp\t%A0"
+ "%!jmp\t%A0"
[(set_attr "type" "ibr")
(set_attr "length_immediate" "0")])
@@ -11621,8 +11729,8 @@
(define_insn "simple_return_internal"
[(simple_return)]
"reload_completed"
- "ret"
- [(set_attr "length" "1")
+ "%!ret"
+ [(set_attr "length_nobnd" "1")
(set_attr "atom_unit" "jeu")
(set_attr "length_immediate" "0")
(set_attr "modrm" "0")])
@@ -11634,7 +11742,12 @@
[(simple_return)
(unspec [(const_int 0)] UNSPEC_REP)]
"reload_completed"
- "rep%; ret"
+{
+ if (ix86_bnd_prefixed_insn_p (insn))
+ return "%!ret";
+
+ return "rep%; ret";
+}
[(set_attr "length" "2")
(set_attr "atom_unit" "jeu")
(set_attr "length_immediate" "0")
@@ -11645,8 +11758,8 @@
[(simple_return)
(use (match_operand:SI 0 "const_int_operand"))]
"reload_completed"
- "ret\t%0"
- [(set_attr "length" "3")
+ "%!ret\t%0"
+ [(set_attr "length_nobnd" "3")
(set_attr "atom_unit" "jeu")
(set_attr "length_immediate" "2")
(set_attr "modrm" "0")])
@@ -11655,7 +11768,7 @@
[(simple_return)
(use (match_operand:SI 0 "register_operand" "r"))]
"reload_completed"
- "jmp\t%A0"
+ "%!jmp\t%A0"
[(set_attr "type" "ibr")
(set_attr "length_immediate" "0")])
@@ -17517,7 +17630,7 @@
[(prefetch (match_operand 0 "address_operand")
(match_operand:SI 1 "const_int_operand")
(match_operand:SI 2 "const_int_operand"))]
- "TARGET_PREFETCH_SSE || TARGET_PRFCHW"
+ "TARGET_PREFETCH_SSE || TARGET_PRFCHW || TARGET_AVX512PF"
{
bool write = INTVAL (operands[1]) != 0;
int locality = INTVAL (operands[2]);
@@ -17528,7 +17641,9 @@
supported by SSE counterpart or the SSE prefetch is not available
(K6 machines). Otherwise use SSE prefetch as it allows specifying
of locality. */
- if (TARGET_PRFCHW && (write || !TARGET_PREFETCH_SSE))
+ if (TARGET_AVX512PF && write)
+ operands[2] = const1_rtx;
+ else if (TARGET_PRFCHW && (write || !TARGET_PREFETCH_SSE))
operands[2] = GEN_INT (3);
else
operands[1] = const0_rtx;
@@ -17571,6 +17686,18 @@
(symbol_ref "memory_address_length (operands[0], false)"))
(set_attr "memory" "none")])
+(define_insn "*prefetch_avx512pf_<mode>"
+ [(prefetch (match_operand:P 0 "address_operand" "p")
+ (const_int 1)
+ (const_int 1))]
+ "TARGET_AVX512PF"
+ "prefetchwt1\t%a0";
+ [(set_attr "type" "sse")
+ (set_attr "prefix" "evex")
+ (set (attr "length_address")
+ (symbol_ref "memory_address_length (operands[0], false)"))
+ (set_attr "memory" "none")])
+
(define_expand "stack_protect_set"
[(match_operand 0 "memory_operand")
(match_operand 1 "memory_operand")]
@@ -17893,6 +18020,71 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
+;; Floating-point instructions for atomic compound assignments
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+; Clobber all floating-point registers on environment save and restore
+; to ensure that the TOS value saved at fnstenv is valid after fldenv.
+(define_insn "fnstenv"
+ [(set (match_operand:BLK 0 "memory_operand" "=m")
+ (unspec_volatile:BLK [(const_int 0)] UNSPECV_FNSTENV))
+ (clobber (reg:HI FPCR_REG))
+ (clobber (reg:XF ST0_REG))
+ (clobber (reg:XF ST1_REG))
+ (clobber (reg:XF ST2_REG))
+ (clobber (reg:XF ST3_REG))
+ (clobber (reg:XF ST4_REG))
+ (clobber (reg:XF ST5_REG))
+ (clobber (reg:XF ST6_REG))
+ (clobber (reg:XF ST7_REG))]
+ "TARGET_80387"
+ "fnstenv\t%0"
+ [(set_attr "type" "other")
+ (set_attr "memory" "store")
+ (set (attr "length")
+ (symbol_ref "ix86_attr_length_address_default (insn) + 2"))])
+
+(define_insn "fldenv"
+ [(unspec_volatile [(match_operand:BLK 0 "memory_operand" "m")]
+ UNSPECV_FLDENV)
+ (clobber (reg:CCFP FPSR_REG))
+ (clobber (reg:HI FPCR_REG))
+ (clobber (reg:XF ST0_REG))
+ (clobber (reg:XF ST1_REG))
+ (clobber (reg:XF ST2_REG))
+ (clobber (reg:XF ST3_REG))
+ (clobber (reg:XF ST4_REG))
+ (clobber (reg:XF ST5_REG))
+ (clobber (reg:XF ST6_REG))
+ (clobber (reg:XF ST7_REG))]
+ "TARGET_80387"
+ "fldenv\t%0"
+ [(set_attr "type" "other")
+ (set_attr "memory" "load")
+ (set (attr "length")
+ (symbol_ref "ix86_attr_length_address_default (insn) + 2"))])
+
+(define_insn "fnstsw"
+ [(set (match_operand:HI 0 "memory_operand" "=m")
+ (unspec_volatile:HI [(const_int 0)] UNSPECV_FNSTSW))]
+ "TARGET_80387"
+ "fnstsw\t%0"
+ [(set_attr "type" "other")
+ (set_attr "memory" "store")
+ (set (attr "length")
+ (symbol_ref "ix86_attr_length_address_default (insn) + 2"))])
+
+(define_insn "fnclex"
+ [(unspec_volatile [(const_int 0)] UNSPECV_FNCLEX)]
+ "TARGET_80387"
+ "fnclex"
+ [(set_attr "type" "other")
+ (set_attr "memory" "none")
+ (set_attr "length" "2")])
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
;; LWP instructions
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -18118,6 +18310,131 @@
[(set_attr "type" "other")
(set_attr "length" "3")])
+;; MPX instructions
+
+(define_expand "<mode>_mk"
+ [(set (match_operand:BND 0 "register_operand")
+ (unspec:BND
+ [(mem:<bnd_ptr>
+ (match_par_dup 3
+ [(match_operand:<bnd_ptr> 1 "register_operand")
+ (match_operand:<bnd_ptr> 2 "address_mpx_no_base_operand")]))]
+ UNSPEC_BNDMK))]
+ "TARGET_MPX"
+{
+ operands[3] = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, operands[1],
+ operands[2]),
+ UNSPEC_BNDMK_ADDR);
+})
+
+(define_insn "*<mode>_mk"
+ [(set (match_operand:BND 0 "register_operand" "=B")
+ (unspec:BND
+ [(match_operator:<bnd_ptr> 3 "bnd_mem_operator"
+ [(unspec:<bnd_ptr>
+ [(match_operand:<bnd_ptr> 1 "register_operand" "r")
+ (match_operand:<bnd_ptr> 2 "address_mpx_no_base_operand" "Tb")]
+ UNSPEC_BNDMK_ADDR)])]
+ UNSPEC_BNDMK))]
+ "TARGET_MPX"
+ "bndmk\t{%3, %0|%0, %3}"
+ [(set_attr "type" "mpxmk")])
+
+(define_expand "mov<mode>"
+ [(set (match_operand:BND 0 "general_operand")
+ (match_operand:BND 1 "general_operand"))]
+ "TARGET_MPX"
+{
+ ix86_expand_move (<MODE>mode, operands);DONE;
+})
+
+(define_insn "*mov<mode>_internal_mpx"
+ [(set (match_operand:BND 0 "nonimmediate_operand" "=B,m")
+ (match_operand:BND 1 "general_operand" "Bm,B"))]
+ "TARGET_MPX"
+ "bndmov\t{%1, %0|%0, %1}"
+ [(set_attr "type" "mpxmov")])
+
+(define_expand "<mode>_<bndcheck>"
+ [(parallel [(unspec [(match_operand:BND 0 "register_operand")
+ (match_operand:<bnd_ptr> 1 "address_no_seg_operand")] BNDCHECK)
+ (set (match_dup 2)
+ (unspec:BLK [(match_dup 2)] UNSPEC_MPX_FENCE))])]
+ "TARGET_MPX"
+{
+ operands[2] = gen_rtx_MEM (BLKmode, operands[1]);
+ MEM_VOLATILE_P (operands[2]) = 1;
+})
+
+(define_insn "*<mode>_<bndcheck>"
+ [(parallel [(unspec [(match_operand:BND 0 "register_operand" "B")
+ (match_operand:<bnd_ptr> 1 "address_no_seg_operand" "Ts")] BNDCHECK)
+ (set (match_operand:BLK 2 "bnd_mem_operator")
+ (unspec:BLK [(match_dup 2)] UNSPEC_MPX_FENCE))])]
+ "TARGET_MPX"
+ "bnd<bndcheck>\t{%a1, %0|%0, %a1}"
+ [(set_attr "type" "mpxchk")])
+
+(define_expand "<mode>_ldx"
+ [(parallel [(set:BND (match_operand:BND 0 "register_operand")
+ (unspec:BND
+ [(mem:<bnd_ptr>
+ (match_par_dup 3
+ [(match_operand:<bnd_ptr> 1 "address_mpx_no_index_operand")
+ (match_operand:<bnd_ptr> 2 "register_operand")]))]
+ UNSPEC_BNDLDX))
+ (use (mem:BLK (match_dup 1)))])]
+ "TARGET_MPX"
+{
+ operands[3] = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, operands[1],
+ operands[2]),
+ UNSPEC_BNDLDX_ADDR);
+})
+
+(define_insn "*<mode>_ldx"
+ [(parallel [(set:BND (match_operand:BND 0 "register_operand" "=B")
+ (unspec:BND
+ [(match_operator:<bnd_ptr> 3 "bnd_mem_operator"
+ [(unspec:<bnd_ptr>
+ [(match_operand:<bnd_ptr> 1 "address_mpx_no_index_operand" "Ti")
+ (match_operand:<bnd_ptr> 2 "register_operand" "l")]
+ UNSPEC_BNDLDX_ADDR)])]
+ UNSPEC_BNDLDX))
+ (use (mem:BLK (match_dup 1)))])]
+ "TARGET_MPX"
+ "bndldx\t{%3, %0|%0, %3}"
+ [(set_attr "type" "mpxld")])
+
+(define_expand "<mode>_stx"
+ [(parallel [(unspec [(mem:<bnd_ptr>
+ (match_par_dup 3
+ [(match_operand:<bnd_ptr> 0 "address_mpx_no_index_operand")
+ (match_operand:<bnd_ptr> 1 "register_operand")]))
+ (match_operand:BND 2 "register_operand")] UNSPEC_BNDSTX)
+ (set (match_dup 4)
+ (unspec:BLK [(match_dup 4)] UNSPEC_MPX_FENCE))])]
+ "TARGET_MPX"
+{
+ operands[3] = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, operands[0],
+ operands[1]),
+ UNSPEC_BNDLDX_ADDR);
+ operands[4] = gen_rtx_MEM (BLKmode, operands[0]);
+ MEM_VOLATILE_P (operands[4]) = 1;
+})
+
+(define_insn "*<mode>_stx"
+ [(parallel [(unspec [(match_operator:<bnd_ptr> 3 "bnd_mem_operator"
+ [(unspec:<bnd_ptr>
+ [(match_operand:<bnd_ptr> 0 "address_mpx_no_index_operand" "Ti")
+ (match_operand:<bnd_ptr> 1 "register_operand" "l")]
+ UNSPEC_BNDLDX_ADDR)])
+ (match_operand:BND 2 "register_operand" "B")] UNSPEC_BNDSTX)
+ (set (match_operand:BLK 4 "bnd_mem_operator")
+ (unspec:BLK [(match_dup 4)] UNSPEC_MPX_FENCE))])]
+ "TARGET_MPX"
+ "bndstx\t{%2, %3|%3, %2}"
+ [(set_attr "type" "mpxst")])
+
(include "mmx.md")
(include "sse.md")
(include "sync.md")
diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
index 5495c295f57..1a1b8abefdc 100644
--- a/gcc/config/i386/i386.opt
+++ b/gcc/config/i386/i386.opt
@@ -61,9 +61,13 @@ TargetSave
HOST_WIDE_INT x_ix86_isa_flags_explicit
;; which flags were passed by the user
-TargetSave
+Variable
int ix86_target_flags_explicit
+;; which flags were passed by the user
+TargetSave
+HOST_WIDE_INT x_ix86_target_flags_explicit
+
;; whether -mtune was not specified
TargetSave
unsigned char tune_defaulted
@@ -665,6 +669,10 @@ mrtm
Target Report Mask(ISA_RTM) Var(ix86_isa_flags) Save
Support RTM built-in functions and code generation
+mmpx
+Target Report Mask(ISA_MPX) Var(ix86_isa_flags) Save
+Support MPX 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
diff --git a/gcc/config/i386/mmx.md b/gcc/config/i386/mmx.md
index 17e24999258..cc0db3a9d06 100644
--- a/gcc/config/i386/mmx.md
+++ b/gcc/config/i386/mmx.md
@@ -99,11 +99,10 @@
return "pxor\t%0, %0";
case TYPE_MMXMOV:
-#ifndef HAVE_AS_IX86_INTERUNIT_MOVQ
/* Handle broken assemblers that require movd instead of movq. */
- if (GENERAL_REG_P (operands[0]) || GENERAL_REG_P (operands[1]))
+ if (!HAVE_AS_IX86_INTERUNIT_MOVQ
+ && (GENERAL_REG_P (operands[0]) || GENERAL_REG_P (operands[1])))
return "movd\t{%1, %0|%0, %1}";
-#endif
return "movq\t{%1, %0|%0, %1}";
case TYPE_SSECVT:
@@ -119,15 +118,13 @@
switch (get_attr_mode (insn))
{
case MODE_DI:
-#ifndef HAVE_AS_IX86_INTERUNIT_MOVQ
/* Handle broken assemblers that require movd instead of movq. */
- if (GENERAL_REG_P (operands[0]) || GENERAL_REG_P (operands[1]))
+ if (!HAVE_AS_IX86_INTERUNIT_MOVQ
+ && (GENERAL_REG_P (operands[0]) || GENERAL_REG_P (operands[1])))
return "%vmovd\t{%1, %0|%0, %1}";
-#endif
return "%vmovq\t{%1, %0|%0, %1}";
case MODE_TI:
return "%vmovdqa\t{%1, %0|%0, %1}";
-
case MODE_XI:
return "vmovdqa64\t{%g1, %g0|%g0, %g1}";
diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
index 18f425c4b87..e5dd90cfad2 100644
--- a/gcc/config/i386/predicates.md
+++ b/gcc/config/i386/predicates.md
@@ -752,16 +752,66 @@
(and (match_code "const_int")
(match_test "IN_RANGE (INTVAL (op), 6, 7)")))
+;; Match 8 to 9.
+(define_predicate "const_8_to_9_operand"
+ (and (match_code "const_int")
+ (match_test "IN_RANGE (INTVAL (op), 8, 9)")))
+
;; Match 8 to 11.
(define_predicate "const_8_to_11_operand"
(and (match_code "const_int")
(match_test "IN_RANGE (INTVAL (op), 8, 11)")))
+;; Match 8 to 15.
+(define_predicate "const_8_to_15_operand"
+ (and (match_code "const_int")
+ (match_test "IN_RANGE (INTVAL (op), 8, 15)")))
+
+;; Match 10 to 11.
+(define_predicate "const_10_to_11_operand"
+ (and (match_code "const_int")
+ (match_test "IN_RANGE (INTVAL (op), 10, 11)")))
+
+;; Match 12 to 13.
+(define_predicate "const_12_to_13_operand"
+ (and (match_code "const_int")
+ (match_test "IN_RANGE (INTVAL (op), 12, 13)")))
+
;; Match 12 to 15.
(define_predicate "const_12_to_15_operand"
(and (match_code "const_int")
(match_test "IN_RANGE (INTVAL (op), 12, 15)")))
+;; Match 14 to 15.
+(define_predicate "const_14_to_15_operand"
+ (and (match_code "const_int")
+ (match_test "IN_RANGE (INTVAL (op), 14, 15)")))
+
+;; Match 16 to 19.
+(define_predicate "const_16_to_19_operand"
+ (and (match_code "const_int")
+ (match_test "IN_RANGE (INTVAL (op), 16, 19)")))
+
+;; Match 16 to 31.
+(define_predicate "const_16_to_31_operand"
+ (and (match_code "const_int")
+ (match_test "IN_RANGE (INTVAL (op), 16, 31)")))
+
+;; Match 20 to 23.
+(define_predicate "const_20_to_23_operand"
+ (and (match_code "const_int")
+ (match_test "IN_RANGE (INTVAL (op), 20, 23)")))
+
+;; Match 24 to 27.
+(define_predicate "const_24_to_27_operand"
+ (and (match_code "const_int")
+ (match_test "IN_RANGE (INTVAL (op), 24, 27)")))
+
+;; Match 28 to 31.
+(define_predicate "const_28_to_31_operand"
+ (and (match_code "const_int")
+ (match_test "IN_RANGE (INTVAL (op), 28, 31)")))
+
;; True if this is a constant appropriate for an increment or decrement.
(define_predicate "incdec_operand"
(match_code "const_int")
@@ -862,10 +912,14 @@
(ior (match_operand 0 "register_operand")
(match_operand 0 "const0_operand")))
+;; Return true for RTX codes that force SImode address.
+(define_predicate "SImode_address_operand"
+ (match_code "subreg,zero_extend,and"))
+
;; Return true if op if a valid address for LEA, and does not contain
;; a segment override. Defined as a special predicate to allow
;; mode-less const_int operands pass to address_operand.
-(define_special_predicate "lea_address_operand"
+(define_special_predicate "address_no_seg_operand"
(match_operand 0 "address_operand")
{
struct ix86_address parts;
@@ -876,10 +930,6 @@
return parts.seg == SEG_DEFAULT;
})
-;; Return true for RTX codes that force SImode address.
-(define_predicate "SImode_address_operand"
- (match_code "subreg,zero_extend,and"))
-
;; Return true if op if a valid base register, displacement or
;; sum of base register and displacement for VSIB addressing.
(define_predicate "vsib_address_operand"
@@ -922,9 +972,74 @@
return true;
})
+;; Return true if op is valid MPX address operand without base
+(define_predicate "address_mpx_no_base_operand"
+ (match_operand 0 "address_operand")
+{
+ struct ix86_address parts;
+ int ok;
+
+ ok = ix86_decompose_address (op, &parts);
+ gcc_assert (ok);
+
+ if (parts.index && parts.base)
+ return false;
+
+ if (parts.seg != SEG_DEFAULT)
+ return false;
+
+ /* Do not support (%rip). */
+ if (parts.disp && flag_pic && TARGET_64BIT
+ && SYMBOLIC_CONST (parts.disp))
+ {
+ if (GET_CODE (parts.disp) != CONST
+ || GET_CODE (XEXP (parts.disp, 0)) != PLUS
+ || GET_CODE (XEXP (XEXP (parts.disp, 0), 0)) != UNSPEC
+ || !CONST_INT_P (XEXP (XEXP (parts.disp, 0), 1))
+ || (XINT (XEXP (XEXP (parts.disp, 0), 0), 1) != UNSPEC_DTPOFF
+ && XINT (XEXP (XEXP (parts.disp, 0), 0), 1) != UNSPEC_NTPOFF))
+ return false;
+ }
+
+ return true;
+})
+
+;; Return true if op is valid MPX address operand without index
+(define_predicate "address_mpx_no_index_operand"
+ (match_operand 0 "address_operand")
+{
+ struct ix86_address parts;
+ int ok;
+
+ ok = ix86_decompose_address (op, &parts);
+ gcc_assert (ok);
+
+ if (parts.index)
+ return false;
+
+ if (parts.seg != SEG_DEFAULT)
+ return false;
+
+ /* Do not support (%rip). */
+ if (parts.disp && flag_pic && TARGET_64BIT
+ && SYMBOLIC_CONST (parts.disp)
+ && (GET_CODE (parts.disp) != CONST
+ || GET_CODE (XEXP (parts.disp, 0)) != PLUS
+ || GET_CODE (XEXP (XEXP (parts.disp, 0), 0)) != UNSPEC
+ || !CONST_INT_P (XEXP (XEXP (parts.disp, 0), 1))
+ || (XINT (XEXP (XEXP (parts.disp, 0), 0), 1) != UNSPEC_DTPOFF
+ && XINT (XEXP (XEXP (parts.disp, 0), 0), 1) != UNSPEC_NTPOFF)))
+ return false;
+
+ return true;
+})
+
(define_predicate "vsib_mem_operator"
(match_code "mem"))
+(define_predicate "bnd_mem_operator"
+ (match_code "mem"))
+
;; Return true if the rtx is known to be at least 32 bits aligned.
(define_predicate "aligned_operand"
(match_operand 0 "general_operand")
@@ -1332,3 +1447,9 @@
(define_predicate "general_vector_operand"
(ior (match_operand 0 "nonimmediate_operand")
(match_code "const_vector")))
+
+;; Return true if OP is either -1 constant or stored in register.
+(define_predicate "register_or_constm1_operand"
+ (ior (match_operand 0 "register_operand")
+ (and (match_code "const_int")
+ (match_test "op == constm1_rtx"))))
diff --git a/gcc/config/i386/rtemself.h b/gcc/config/i386/rtemself.h
index 08ef18ccec5..087179191cb 100644
--- a/gcc/config/i386/rtemself.h
+++ b/gcc/config/i386/rtemself.h
@@ -26,7 +26,15 @@ along with GCC; see the file COPYING3. If not see
builtin_define ("__rtems__"); \
builtin_define ("__USE_INIT_FINI__"); \
builtin_assert ("system=rtems"); \
- if (!TARGET_80387) \
- builtin_define ("_SOFT_FLOAT"); \
} \
while (0)
+
+#undef LONG_DOUBLE_TYPE_SIZE
+#define LONG_DOUBLE_TYPE_SIZE (TARGET_80387 ? 80 : 64)
+
+#undef LIBGCC2_LONG_DOUBLE_TYPE_SIZE
+#ifdef _SOFT_FLOAT
+#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 64
+#else
+#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 80
+#endif
diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
index 9d9469e2c62..7bb2d7795f6 100644
--- a/gcc/config/i386/sse.md
+++ b/gcc/config/i386/sse.md
@@ -83,6 +83,35 @@
UNSPEC_VPERMTI
UNSPEC_GATHER
UNSPEC_VSIBADDR
+
+ ;; For AVX512F support
+ UNSPEC_VPERMI2
+ UNSPEC_VPERMT2
+ UNSPEC_UNSIGNED_FIX_NOTRUNC
+ UNSPEC_UNSIGNED_PCMP
+ UNSPEC_TESTM
+ UNSPEC_TESTNM
+ UNSPEC_SCATTER
+ UNSPEC_RCP14
+ UNSPEC_RSQRT14
+ UNSPEC_FIXUPIMM
+ UNSPEC_SCALEF
+ UNSPEC_VTERNLOG
+ UNSPEC_GETEXP
+ UNSPEC_GETMANT
+ UNSPEC_ALIGN
+ UNSPEC_CONFLICT
+ UNSPEC_MASKED_EQ
+ UNSPEC_MASKED_GT
+
+ ;; For AVX512PF support
+ UNSPEC_GATHER_PREFETCH
+ UNSPEC_SCATTER_PREFETCH
+
+ ;; For AVX512ER support
+ UNSPEC_EXP2
+ UNSPEC_RCP28
+ UNSPEC_RSQRT28
])
(define_c_enum "unspecv" [
@@ -97,22 +126,22 @@
;; All vector modes including V?TImode, used in move patterns.
(define_mode_iterator VMOVE
- [(V32QI "TARGET_AVX") V16QI
- (V16HI "TARGET_AVX") V8HI
- (V8SI "TARGET_AVX") V4SI
- (V4DI "TARGET_AVX") V2DI
+ [(V64QI "TARGET_AVX512F") (V32QI "TARGET_AVX") V16QI
+ (V32HI "TARGET_AVX512F") (V16HI "TARGET_AVX") V8HI
+ (V16SI "TARGET_AVX512F") (V8SI "TARGET_AVX") V4SI
+ (V8DI "TARGET_AVX512F") (V4DI "TARGET_AVX") V2DI
(V2TI "TARGET_AVX") V1TI
- (V8SF "TARGET_AVX") V4SF
- (V4DF "TARGET_AVX") V2DF])
+ (V16SF "TARGET_AVX512F") (V8SF "TARGET_AVX") V4SF
+ (V8DF "TARGET_AVX512F") (V4DF "TARGET_AVX") V2DF])
;; All vector modes
(define_mode_iterator V
[(V32QI "TARGET_AVX") V16QI
(V16HI "TARGET_AVX") V8HI
- (V8SI "TARGET_AVX") V4SI
- (V4DI "TARGET_AVX") V2DI
- (V8SF "TARGET_AVX") V4SF
- (V4DF "TARGET_AVX") (V2DF "TARGET_SSE2")])
+ (V16SI "TARGET_AVX512F") (V8SI "TARGET_AVX") V4SI
+ (V8DI "TARGET_AVX512F") (V4DI "TARGET_AVX") V2DI
+ (V16SF "TARGET_AVX512F") (V8SF "TARGET_AVX") V4SF
+ (V8DF "TARGET_AVX512F") (V4DF "TARGET_AVX") (V2DF "TARGET_SSE2")])
;; All 128bit vector modes
(define_mode_iterator V_128
@@ -122,19 +151,44 @@
(define_mode_iterator V_256
[V32QI V16HI V8SI V4DI V8SF V4DF])
+;; All 512bit vector modes
+(define_mode_iterator V_512 [V64QI V32HI V16SI V8DI V16SF V8DF])
+
+;; All 256bit and 512bit vector modes
+(define_mode_iterator V_256_512
+ [V32QI V16HI V8SI V4DI V8SF V4DF
+ (V64QI "TARGET_AVX512F") (V32HI "TARGET_AVX512F") (V16SI "TARGET_AVX512F")
+ (V8DI "TARGET_AVX512F") (V16SF "TARGET_AVX512F") (V8DF "TARGET_AVX512F")])
+
;; All vector float modes
(define_mode_iterator VF
+ [(V16SF "TARGET_AVX512F") (V8SF "TARGET_AVX") V4SF
+ (V8DF "TARGET_AVX512F") (V4DF "TARGET_AVX") (V2DF "TARGET_SSE2")])
+
+;; 128- and 256-bit float vector modes
+(define_mode_iterator VF_128_256
[(V8SF "TARGET_AVX") V4SF
(V4DF "TARGET_AVX") (V2DF "TARGET_SSE2")])
;; All SFmode vector float modes
(define_mode_iterator VF1
+ [(V16SF "TARGET_AVX512F") (V8SF "TARGET_AVX") V4SF])
+
+;; 128- and 256-bit SF vector modes
+(define_mode_iterator VF1_128_256
[(V8SF "TARGET_AVX") V4SF])
;; All DFmode vector float modes
(define_mode_iterator VF2
+ [(V8DF "TARGET_AVX512F") (V4DF "TARGET_AVX") V2DF])
+
+;; 128- and 256-bit DF vector modes
+(define_mode_iterator VF2_128_256
[(V4DF "TARGET_AVX") V2DF])
+(define_mode_iterator VF2_512_256
+ [(V8DF "TARGET_AVX512F") (V4DF "TARGET_AVX")])
+
;; All 128bit vector float modes
(define_mode_iterator VF_128
[V4SF (V2DF "TARGET_SSE2")])
@@ -143,9 +197,14 @@
(define_mode_iterator VF_256
[V8SF V4DF])
+;; All 512bit vector float modes
+(define_mode_iterator VF_512
+ [V16SF V8DF])
+
;; All vector integer modes
(define_mode_iterator VI
- [(V32QI "TARGET_AVX") V16QI
+ [(V16SI "TARGET_AVX512F") (V8DI "TARGET_AVX512F")
+ (V32QI "TARGET_AVX") V16QI
(V16HI "TARGET_AVX") V8HI
(V8SI "TARGET_AVX") V4SI
(V4DI "TARGET_AVX") V2DI])
@@ -153,16 +212,20 @@
(define_mode_iterator VI_AVX2
[(V32QI "TARGET_AVX2") V16QI
(V16HI "TARGET_AVX2") V8HI
- (V8SI "TARGET_AVX2") V4SI
- (V4DI "TARGET_AVX2") V2DI])
+ (V16SI "TARGET_AVX512F") (V8SI "TARGET_AVX2") V4SI
+ (V8DI "TARGET_AVX512F") (V4DI "TARGET_AVX2") V2DI])
;; All QImode vector integer modes
(define_mode_iterator VI1
[(V32QI "TARGET_AVX") V16QI])
+(define_mode_iterator VI_UNALIGNED_LOADSTORE
+ [(V32QI "TARGET_AVX") V16QI
+ (V16SI "TARGET_AVX512F") (V8DI "TARGET_AVX512F")])
+
;; All DImode vector integer modes
(define_mode_iterator VI8
- [(V4DI "TARGET_AVX") V2DI])
+ [(V8DI "TARGET_AVX512F") (V4DI "TARGET_AVX") V2DI])
(define_mode_iterator VI1_AVX2
[(V32QI "TARGET_AVX2") V16QI])
@@ -170,12 +233,36 @@
(define_mode_iterator VI2_AVX2
[(V16HI "TARGET_AVX2") V8HI])
+(define_mode_iterator VI2_AVX512F
+ [(V32HI "TARGET_AVX512F") (V16HI "TARGET_AVX2") V8HI])
+
+(define_mode_iterator VI4_AVX
+ [(V8SI "TARGET_AVX") V4SI])
+
(define_mode_iterator VI4_AVX2
[(V8SI "TARGET_AVX2") V4SI])
+(define_mode_iterator VI4_AVX512F
+ [(V16SI "TARGET_AVX512F") (V8SI "TARGET_AVX2") V4SI])
+
+(define_mode_iterator VI48_AVX512F
+ [(V16SI "TARGET_AVX512F") (V8SI "TARGET_AVX2") V4SI
+ (V8DI "TARGET_AVX512F")])
+
(define_mode_iterator VI8_AVX2
[(V4DI "TARGET_AVX2") V2DI])
+(define_mode_iterator VI8_AVX2_AVX512F
+ [(V8DI "TARGET_AVX512F") (V4DI "TARGET_AVX2") V2DI])
+
+;; All V8D* modes
+(define_mode_iterator V8FI
+ [V8DF V8DI])
+
+;; All V16S* modes
+(define_mode_iterator V16FI
+ [V16SF V16SI])
+
;; ??? We should probably use TImode instead.
(define_mode_iterator VIMAX_AVX2
[(V2TI "TARGET_AVX2") V1TI])
@@ -192,6 +279,17 @@
[(V16HI "TARGET_AVX2") V8HI
(V8SI "TARGET_AVX2") V4SI])
+(define_mode_iterator VI124_AVX2_48_AVX512F
+ [(V32QI "TARGET_AVX2") V16QI
+ (V16HI "TARGET_AVX2") V8HI
+ (V16SI "TARGET_AVX512F") (V8SI "TARGET_AVX2") V4SI
+ (V8DI "TARGET_AVX512F")])
+
+(define_mode_iterator VI124_AVX512F
+ [(V32QI "TARGET_AVX2") V16QI
+ (V32HI "TARGET_AVX512F") (V16HI "TARGET_AVX2") V8HI
+ (V16SI "TARGET_AVX512F") (V8SI "TARGET_AVX2") V4SI])
+
(define_mode_iterator VI124_AVX2
[(V32QI "TARGET_AVX2") V16QI
(V16HI "TARGET_AVX2") V8HI
@@ -202,9 +300,14 @@
(V8SI "TARGET_AVX2") V4SI
(V4DI "TARGET_AVX2") V2DI])
-(define_mode_iterator VI48_AVX2
- [(V8SI "TARGET_AVX2") V4SI
- (V4DI "TARGET_AVX2") V2DI])
+(define_mode_iterator VI248_AVX2_8_AVX512F
+ [(V16HI "TARGET_AVX2") V8HI
+ (V8SI "TARGET_AVX2") V4SI
+ (V8DI "TARGET_AVX512F") (V4DI "TARGET_AVX2") V2DI])
+
+(define_mode_iterator VI48_AVX2_48_AVX512F
+ [(V16SI "TARGET_AVX512F") (V8SI "TARGET_AVX2") V4SI
+ (V8DI "TARGET_AVX512F") (V4DI "TARGET_AVX2") V2DI])
(define_mode_iterator V48_AVX2
[V4SF V2DF
@@ -212,11 +315,18 @@
(V4SI "TARGET_AVX2") (V2DI "TARGET_AVX2")
(V8SI "TARGET_AVX2") (V4DI "TARGET_AVX2")])
+(define_mode_attr sse2_avx_avx512f
+ [(V16QI "sse2") (V32QI "avx") (V64QI "avx512f")
+ (V4SI "sse2") (V8SI "avx") (V16SI "avx512f")
+ (V8DI "avx512f")
+ (V16SF "avx512f") (V8SF "avx") (V4SF "avx")
+ (V8DF "avx512f") (V4DF "avx") (V2DF "avx")])
+
(define_mode_attr sse2_avx2
[(V16QI "sse2") (V32QI "avx2")
(V8HI "sse2") (V16HI "avx2")
- (V4SI "sse2") (V8SI "avx2")
- (V2DI "sse2") (V4DI "avx2")
+ (V4SI "sse2") (V8SI "avx2") (V16SI "avx512f")
+ (V2DI "sse2") (V4DI "avx2") (V8DI "avx512f")
(V1TI "sse2") (V2TI "avx2")])
(define_mode_attr ssse3_avx2
@@ -229,7 +339,7 @@
(define_mode_attr sse4_1_avx2
[(V16QI "sse4_1") (V32QI "avx2")
(V8HI "sse4_1") (V16HI "avx2")
- (V4SI "sse4_1") (V8SI "avx2")
+ (V4SI "sse4_1") (V8SI "avx2") (V16SI "avx512f")
(V2DI "sse4_1") (V4DI "avx2")])
(define_mode_attr avx_avx2
@@ -244,6 +354,12 @@
(V4SI "vec") (V8SI "avx2")
(V2DI "vec") (V4DI "avx2")])
+(define_mode_attr avx2_avx512f
+ [(V4SI "avx2") (V8SI "avx2") (V16SI "avx512f")
+ (V2DI "avx2") (V4DI "avx2") (V8DI "avx512f")
+ (V8SF "avx2") (V16SF "avx512f")
+ (V4DF "avx2") (V8DF "avx512f")])
+
(define_mode_attr shuffletype
[(V16SF "f") (V16SI "i") (V8DF "f") (V8DI "i")
(V8SF "f") (V8SI "i") (V4DF "f") (V4DI "i")
@@ -251,8 +367,12 @@
(V32QI "i") (V16HI "u") (V16QI "i") (V8HI "i")
(V64QI "i") (V1TI "i") (V2TI "i")])
+(define_mode_attr ssequartermode
+ [(V16SF "V4SF") (V8DF "V2DF") (V16SI "V4SI") (V8DI "V2DI")])
+
(define_mode_attr ssedoublemode
- [(V16HI "V16SI") (V8HI "V8SI") (V4HI "V4SI")
+ [(V16SF "V32SF") (V16SI "V32SI") (V8DI "V16DI") (V8DF "V16DF")
+ (V16HI "V16SI") (V8HI "V8SI") (V4HI "V4SI")
(V32QI "V32HI") (V16QI "V16HI")])
(define_mode_attr ssebytemode
@@ -264,7 +384,10 @@
;; All 256bit vector integer modes
(define_mode_iterator VI_256 [V32QI V16HI V8SI V4DI])
-;; Random 128bit vector integer mode combinations
+;; All 512bit vector integer modes
+(define_mode_iterator VI_512 [V64QI V32HI V16SI V8DI])
+
+;; Various 128bit vector integer mode combinations
(define_mode_iterator VI12_128 [V16QI V8HI])
(define_mode_iterator VI14_128 [V16QI V4SI])
(define_mode_iterator VI124_128 [V16QI V8HI V4SI])
@@ -273,36 +396,49 @@
(define_mode_iterator VI248_128 [V8HI V4SI V2DI])
(define_mode_iterator VI48_128 [V4SI V2DI])
-;; Random 256bit vector integer mode combinations
-(define_mode_iterator VI124_256 [V32QI V16HI V8SI])
+;; Various 256bit and 512 vector integer mode combinations
+(define_mode_iterator VI124_256_48_512
+ [V32QI V16HI V8SI (V8DI "TARGET_AVX512F") (V16SI "TARGET_AVX512F")])
(define_mode_iterator VI48_256 [V8SI V4DI])
+(define_mode_iterator VI48_512 [V16SI V8DI])
;; Int-float size matches
(define_mode_iterator VI4F_128 [V4SI V4SF])
(define_mode_iterator VI8F_128 [V2DI V2DF])
(define_mode_iterator VI4F_256 [V8SI V8SF])
(define_mode_iterator VI8F_256 [V4DI V4DF])
+(define_mode_iterator VI8F_256_512
+ [V4DI V4DF (V8DI "TARGET_AVX512F") (V8DF "TARGET_AVX512F")])
+(define_mode_iterator VI48F_256_512
+ [V8SI V8SF
+ (V16SI "TARGET_AVX512F") (V16SF "TARGET_AVX512F")
+ (V8DI "TARGET_AVX512F") (V8DF "TARGET_AVX512F")])
+(define_mode_iterator VI48F_512 [V16SI V16SF V8DI V8DF])
;; Mapping from float mode to required SSE level
(define_mode_attr sse
[(SF "sse") (DF "sse2")
(V4SF "sse") (V2DF "sse2")
- (V8SF "avx") (V4DF "avx")])
+ (V16SF "avx512f") (V8SF "avx")
+ (V8DF "avx512f") (V4DF "avx")])
(define_mode_attr sse2
- [(V16QI "sse2") (V32QI "avx")
- (V2DI "sse2") (V4DI "avx")])
+ [(V16QI "sse2") (V32QI "avx") (V64QI "avx512f")
+ (V2DI "sse2") (V4DI "avx") (V8DI "avx512f")])
(define_mode_attr sse3
[(V16QI "sse3") (V32QI "avx")])
(define_mode_attr sse4_1
[(V4SF "sse4_1") (V2DF "sse4_1")
- (V8SF "avx") (V4DF "avx")])
+ (V8SF "avx") (V4DF "avx")
+ (V8DF "avx512f")])
(define_mode_attr avxsizesuffix
- [(V32QI "256") (V16HI "256") (V8SI "256") (V4DI "256")
+ [(V64QI "512") (V32HI "512") (V16SI "512") (V8DI "512")
+ (V32QI "256") (V16HI "256") (V8SI "256") (V4DI "256")
(V16QI "") (V8HI "") (V4SI "") (V2DI "")
+ (V16SF "512") (V8DF "512")
(V8SF "256") (V4DF "256")
(V4SF "") (V2DF "")])
@@ -316,17 +452,29 @@
(V4SF "V4SF") (V2DF "V2DF")
(TI "TI")])
+;; Mapping of vector modes to corresponding mask size
+(define_mode_attr avx512fmaskmode
+ [(V16QI "HI")
+ (V16HI "HI") (V8HI "QI")
+ (V16SI "HI") (V8SI "QI") (V4SI "QI")
+ (V8DI "QI") (V4DI "QI") (V2DI "QI")
+ (V16SF "HI") (V8SF "QI") (V4SF "QI")
+ (V8DF "QI") (V4DF "QI") (V2DF "QI")])
+
;; Mapping of vector float modes to an integer mode of the same size
(define_mode_attr sseintvecmode
- [(V8SF "V8SI") (V4DF "V4DI")
- (V4SF "V4SI") (V2DF "V2DI")
- (V8SI "V8SI") (V4DI "V4DI")
- (V4SI "V4SI") (V2DI "V2DI")
- (V16HI "V16HI") (V8HI "V8HI")
+ [(V16SF "V16SI") (V8DF "V8DI")
+ (V8SF "V8SI") (V4DF "V4DI")
+ (V4SF "V4SI") (V2DF "V2DI")
+ (V16SI "V16SI") (V8DI "V8DI")
+ (V8SI "V8SI") (V4DI "V4DI")
+ (V4SI "V4SI") (V2DI "V2DI")
+ (V16HI "V16HI") (V8HI "V8HI")
(V32QI "V32QI") (V16QI "V16QI")])
(define_mode_attr sseintvecmodelower
- [(V8SF "v8si") (V4DF "v4di")
+ [(V16SF "v16si")
+ (V8SF "v8si") (V4DF "v4di")
(V4SF "v4si") (V2DF "v2di")
(V8SI "v8si") (V4DI "v4di")
(V4SI "v4si") (V2DI "v2di")
@@ -342,15 +490,19 @@
;; Mapping of vector modes to a vector mode of half size
(define_mode_attr ssehalfvecmode
- [(V32QI "V16QI") (V16HI "V8HI") (V8SI "V4SI") (V4DI "V2DI")
- (V16QI "V8QI") (V8HI "V4HI") (V4SI "V2SI")
- (V8SF "V4SF") (V4DF "V2DF")
- (V4SF "V2SF")])
+ [(V64QI "V32QI") (V32HI "V16HI") (V16SI "V8SI") (V8DI "V4DI")
+ (V32QI "V16QI") (V16HI "V8HI") (V8SI "V4SI") (V4DI "V2DI")
+ (V16QI "V8QI") (V8HI "V4HI") (V4SI "V2SI")
+ (V16SF "V8SF") (V8DF "V4DF")
+ (V8SF "V4SF") (V4DF "V2DF")
+ (V4SF "V2SF")])
;; Mapping of vector modes ti packed single mode of the same size
(define_mode_attr ssePSmode
- [(V32QI "V8SF") (V16QI "V4SF")
- (V16HI "V8SF") (V8HI "V4SF")
+ [(V16SI "V16SF") (V8DF "V16SF")
+ (V16SF "V16SF") (V8DI "V16SF")
+ (V64QI "V16SF") (V32QI "V8SF") (V16QI "V4SF")
+ (V32HI "V16SF") (V16HI "V8SF") (V8HI "V4SF")
(V8SI "V8SF") (V4SI "V4SF")
(V4DI "V8SF") (V2DI "V4SF")
(V2TI "V8SF") (V1TI "V4SF")
@@ -359,10 +511,21 @@
;; Mapping of vector modes back to the scalar modes
(define_mode_attr ssescalarmode
- [(V32QI "QI") (V16HI "HI") (V8SI "SI") (V4DI "DI")
- (V16QI "QI") (V8HI "HI") (V4SI "SI") (V2DI "DI")
- (V8SF "SF") (V4DF "DF")
- (V4SF "SF") (V2DF "DF")])
+ [(V64QI "QI") (V32QI "QI") (V16QI "QI")
+ (V32HI "HI") (V16HI "HI") (V8HI "HI")
+ (V16SI "SI") (V8SI "SI") (V4SI "SI")
+ (V8DI "DI") (V4DI "DI") (V2DI "DI")
+ (V16SF "SF") (V8SF "SF") (V4SF "SF")
+ (V8DF "DF") (V4DF "DF") (V2DF "DF")])
+
+;; Mapping of vector modes to the 128bit modes
+(define_mode_attr ssexmmmode
+ [(V64QI "V16QI") (V32QI "V16QI") (V16QI "V16QI")
+ (V32HI "V8HI") (V16HI "V8HI") (V8HI "V8HI")
+ (V16SI "V4SI") (V8SI "V4SI") (V4SI "V4SI")
+ (V8DI "V2DI") (V4DI "V2DI") (V2DI "V2DI")
+ (V16SF "V4SF") (V8SF "V4SF") (V4SF "V4SF")
+ (V8DF "V2DF") (V4DF "V2DF") (V2DF "V2DF")])
;; Pointer size override for scalar modes (Intel asm dialect)
(define_mode_attr iptr
@@ -374,8 +537,10 @@
;; Number of scalar elements in each vector type
(define_mode_attr ssescalarnum
- [(V32QI "32") (V16HI "16") (V8SI "8") (V4DI "4")
+ [(V64QI "64") (V16SI "16") (V8DI "8")
+ (V32QI "32") (V16HI "16") (V8SI "8") (V4DI "4")
(V16QI "16") (V8HI "8") (V4SI "4") (V2DI "2")
+ (V16SF "16") (V8DF "8")
(V8SF "8") (V4DF "4")
(V4SF "4") (V2DF "2")])
@@ -388,10 +553,12 @@
;; SSE prefix for integer vector modes
(define_mode_attr sseintprefix
- [(V2DI "p") (V2DF "")
- (V4DI "p") (V4DF "")
- (V4SI "p") (V4SF "")
- (V8SI "p") (V8SF "")])
+ [(V2DI "p") (V2DF "")
+ (V4DI "p") (V4DF "")
+ (V8DI "p") (V8DF "")
+ (V4SI "p") (V4SF "")
+ (V8SI "p") (V8SF "")
+ (V16SI "p") (V16SF "")])
;; SSE scalar suffix for vector modes
(define_mode_attr ssescalarmodesuffix
@@ -404,11 +571,13 @@
;; Pack/unpack vector modes
(define_mode_attr sseunpackmode
[(V16QI "V8HI") (V8HI "V4SI") (V4SI "V2DI")
- (V32QI "V16HI") (V16HI "V8SI") (V8SI "V4DI")])
+ (V32QI "V16HI") (V16HI "V8SI") (V8SI "V4DI")
+ (V32HI "V16SI") (V64QI "V32HI") (V16SI "V8DI")])
(define_mode_attr ssepackmode
[(V8HI "V16QI") (V4SI "V8HI") (V2DI "V4SI")
- (V16HI "V32QI") (V8SI "V16HI") (V4DI "V8SI")])
+ (V16HI "V32QI") (V8SI "V16HI") (V4DI "V8SI")
+ (V32HI "V64QI") (V16SI "V32HI") (V8DI "V16SI")])
;; Mapping of the max integer size for xop rotate immediate constraint
(define_mode_attr sserotatemax
@@ -421,9 +590,11 @@
(define_code_attr extsuffix [(sign_extend "sx") (zero_extend "zx")])
;; i128 for integer vectors and TARGET_AVX2, f128 otherwise.
+;; i64x4 or f64x4 for 512bit modes.
(define_mode_attr i128
- [(V8SF "f128") (V4DF "f128") (V32QI "%~128") (V16HI "%~128")
- (V8SI "%~128") (V4DI "%~128")])
+ [(V16SF "f64x4") (V8SF "f128") (V8DF "f64x4") (V4DF "f128")
+ (V64QI "i64x4") (V32QI "%~128") (V32HI "i64x4") (V16HI "%~128")
+ (V16SI "i64x4") (V8SI "%~128") (V8DI "i64x4") (V4DI "%~128")])
;; Mix-n-match
(define_mode_iterator AVX256MODE2P [V8SI V8SF V4DF])
@@ -432,6 +603,10 @@
(define_mode_attr blendbits
[(V8SF "255") (V4SF "15") (V4DF "15") (V2DF "3")])
+;; Mapping suffixes for broadcast
+(define_mode_attr bcstscalarsuff
+ [(V16SI "d") (V16SF "ss") (V8DI "q") (V8DF "sd")])
+
;; Patterns whose name begins with "sse{,2,3}_" are invoked by intrinsics.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -571,6 +746,18 @@
]
(const_string "<sseinsnmode>")))])
+(define_insn "avx512f_blendm<mode>"
+ [(set (match_operand:VI48F_512 0 "register_operand" "=v")
+ (vec_merge:VI48F_512
+ (match_operand:VI48F_512 2 "nonimmediate_operand" "vm")
+ (match_operand:VI48F_512 1 "register_operand" "v")
+ (match_operand:<avx512fmaskmode> 3 "register_operand" "k")))]
+ "TARGET_AVX512F"
+ "v<sseintprefix>blendm<ssemodesuffix>\t{%2, %1, %0%{%3%}|%0%{%3%}, %1, %2}"
+ [(set_attr "type" "ssemov")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<sseinsnmode>")])
+
(define_insn "sse2_movq128"
[(set (match_operand:V2DI 0 "register_operand" "=x")
(vec_concat:V2DI
@@ -613,10 +800,13 @@
gen_rtx_SUBREG (SImode, operands[1], 4)));
emit_insn (gen_vec_interleave_lowv4si (operands[0], operands[0],
operands[2]));
- }
+ }
else if (memory_operand (operands[1], DImode))
- emit_insn (gen_vec_concatv2di (gen_lowpart (V2DImode, operands[0]),
- operands[1], const0_rtx));
+ {
+ rtx tmp = gen_reg_rtx (V2DImode);
+ emit_insn (gen_vec_concatv2di (tmp, operands[1], const0_rtx));
+ emit_move_insn (operands[0], gen_lowpart (V4SImode, tmp));
+ }
else
gcc_unreachable ();
})
@@ -665,12 +855,13 @@
(define_insn "<sse>_loadu<ssemodesuffix><avxsizesuffix>"
[(set (match_operand:VF 0 "register_operand" "=v")
(unspec:VF
- [(match_operand:VF 1 "memory_operand" "m")]
+ [(match_operand:VF 1 "nonimmediate_operand" "vm")]
UNSPEC_LOADU))]
"TARGET_SSE"
{
switch (get_attr_mode (insn))
{
+ case MODE_V16SF:
case MODE_V8SF:
case MODE_V4SF:
return "%vmovups\t{%1, %0|%0, %1}";
@@ -694,12 +885,13 @@
(define_insn "<sse>_storeu<ssemodesuffix><avxsizesuffix>"
[(set (match_operand:VF 0 "memory_operand" "=m")
(unspec:VF
- [(match_operand:VF 1 "register_operand" "x")]
+ [(match_operand:VF 1 "register_operand" "v")]
UNSPEC_STOREU))]
"TARGET_SSE"
{
switch (get_attr_mode (insn))
{
+ case MODE_V16SF:
case MODE_V8SF:
case MODE_V4SF:
return "%vmovups\t{%1, %0|%0, %1}";
@@ -721,10 +913,11 @@
]
(const_string "<MODE>")))])
-(define_insn "<sse2>_loaddqu<avxsizesuffix>"
- [(set (match_operand:VI1 0 "register_operand" "=v")
- (unspec:VI1 [(match_operand:VI1 1 "memory_operand" "m")]
- UNSPEC_LOADU))]
+(define_insn "<sse2_avx_avx512f>_loaddqu<mode>"
+ [(set (match_operand:VI_UNALIGNED_LOADSTORE 0 "register_operand" "=v")
+ (unspec:VI_UNALIGNED_LOADSTORE
+ [(match_operand:VI_UNALIGNED_LOADSTORE 1 "nonimmediate_operand" "vm")]
+ UNSPEC_LOADU))]
"TARGET_SSE2"
{
switch (get_attr_mode (insn))
@@ -732,6 +925,11 @@
case MODE_V8SF:
case MODE_V4SF:
return "%vmovups\t{%1, %0|%0, %1}";
+ case MODE_XI:
+ if (<MODE>mode == V8DImode)
+ return "vmovdqu64\t{%1, %0|%0, %1}";
+ else
+ return "vmovdqu32\t{%1, %0|%0, %1}";
default:
return "%vmovdqu\t{%1, %0|%0, %1}";
}
@@ -754,10 +952,11 @@
]
(const_string "<sseinsnmode>")))])
-(define_insn "<sse2>_storedqu<avxsizesuffix>"
- [(set (match_operand:VI1 0 "memory_operand" "=m")
- (unspec:VI1 [(match_operand:VI1 1 "register_operand" "v")]
- UNSPEC_STOREU))]
+(define_insn "<sse2_avx_avx512f>_storedqu<mode>"
+ [(set (match_operand:VI_UNALIGNED_LOADSTORE 0 "memory_operand" "=m")
+ (unspec:VI_UNALIGNED_LOADSTORE
+ [(match_operand:VI_UNALIGNED_LOADSTORE 1 "register_operand" "v")]
+ UNSPEC_STOREU))]
"TARGET_SSE2"
{
switch (get_attr_mode (insn))
@@ -765,6 +964,11 @@
case MODE_V8SF:
case MODE_V4SF:
return "%vmovups\t{%1, %0|%0, %1}";
+ case MODE_XI:
+ if (<MODE>mode == V8DImode)
+ return "vmovdqu64\t{%1, %0|%0, %1}";
+ else
+ return "vmovdqu32\t{%1, %0|%0, %1}";
default:
return "%vmovdqu\t{%1, %0|%0, %1}";
}
@@ -821,8 +1025,9 @@
(define_insn "<sse>_movnt<mode>"
[(set (match_operand:VF 0 "memory_operand" "=m")
- (unspec:VF [(match_operand:VF 1 "register_operand" "x")]
- UNSPEC_MOVNT))]
+ (unspec:VF
+ [(match_operand:VF 1 "register_operand" "v")]
+ UNSPEC_MOVNT))]
"TARGET_SSE"
"%vmovnt<ssemodesuffix>\t{%1, %0|%0, %1}"
[(set_attr "type" "ssemov")
@@ -831,7 +1036,7 @@
(define_insn "<sse2>_movnt<mode>"
[(set (match_operand:VI8 0 "memory_operand" "=m")
- (unspec:VI8 [(match_operand:VI8 1 "register_operand" "x")]
+ (unspec:VI8 [(match_operand:VI8 1 "register_operand" "v")]
UNSPEC_MOVNT))]
"TARGET_SSE2"
"%vmovntdq\t{%1, %0|%0, %1}"
@@ -852,9 +1057,9 @@
(define_mode_iterator STORENT_MODE
[(DI "TARGET_SSE2 && TARGET_64BIT") (SI "TARGET_SSE2")
(SF "TARGET_SSE4A") (DF "TARGET_SSE4A")
- (V4DI "TARGET_AVX") (V2DI "TARGET_SSE2")
- (V8SF "TARGET_AVX") V4SF
- (V4DF "TARGET_AVX") (V2DF "TARGET_SSE2")])
+ (V8DI "TARGET_AVX512F") (V4DI "TARGET_AVX") (V2DI "TARGET_SSE2")
+ (V16SF "TARGET_AVX512F") (V8SF "TARGET_AVX") V4SF
+ (V8DF "TARGET_AVX512F") (V4DF "TARGET_AVX") (V2DF "TARGET_SSE2")])
(define_expand "storent<mode>"
[(set (match_operand:STORENT_MODE 0 "memory_operand")
@@ -877,10 +1082,10 @@
"ix86_expand_fp_absneg_operator (<CODE>, <MODE>mode, operands); DONE;")
(define_insn_and_split "*absneg<mode>2"
- [(set (match_operand:VF 0 "register_operand" "=x,x,x,x")
+ [(set (match_operand:VF 0 "register_operand" "=x,x,v,v")
(match_operator:VF 3 "absneg_operator"
- [(match_operand:VF 1 "nonimmediate_operand" "0, xm,x, m")]))
- (use (match_operand:VF 2 "nonimmediate_operand" "xm,0, xm,x"))]
+ [(match_operand:VF 1 "nonimmediate_operand" "0, xm, v, m")]))
+ (use (match_operand:VF 2 "nonimmediate_operand" "xm, 0, vm,v"))]
"TARGET_SSE"
"#"
"&& reload_completed"
@@ -962,10 +1167,10 @@
"ix86_fixup_binary_operands_no_copy (MULT, <MODE>mode, operands);")
(define_insn "*mul<mode>3"
- [(set (match_operand:VF 0 "register_operand" "=x,x")
+ [(set (match_operand:VF 0 "register_operand" "=x,v")
(mult:VF
- (match_operand:VF 1 "nonimmediate_operand" "%0,x")
- (match_operand:VF 2 "nonimmediate_operand" "xm,xm")))]
+ (match_operand:VF 1 "nonimmediate_operand" "%0,v")
+ (match_operand:VF 2 "nonimmediate_operand" "xm,vm")))]
"TARGET_SSE && ix86_binary_operator_ok (MULT, <MODE>mode, operands)"
"@
mul<ssemodesuffix>\t{%2, %0|%0, %2}
@@ -976,21 +1181,22 @@
(set_attr "btver2_decode" "direct,double")
(set_attr "mode" "<MODE>")])
-(define_insn "<sse>_vmmul<mode>3"
+(define_insn "<sse>_vm<multdiv_mnemonic><mode>3"
[(set (match_operand:VF_128 0 "register_operand" "=x,v")
(vec_merge:VF_128
- (mult:VF_128
+ (multdiv:VF_128
(match_operand:VF_128 1 "register_operand" "0,v")
(match_operand:VF_128 2 "nonimmediate_operand" "xm,vm"))
(match_dup 1)
(const_int 1)))]
"TARGET_SSE"
"@
- mul<ssescalarmodesuffix>\t{%2, %0|%0, %<iptr>2}
- vmul<ssescalarmodesuffix>\t{%2, %1, %0|%0, %1, %<iptr>2}"
+ <multdiv_mnemonic><ssescalarmodesuffix>\t{%2, %0|%0, %<iptr>2}
+ v<multdiv_mnemonic><ssescalarmodesuffix>\t{%2, %1, %0|%0, %1, %<iptr>2}"
[(set_attr "isa" "noavx,avx")
- (set_attr "type" "ssemul")
- (set_attr "prefix" "orig,vex")
+ (set_attr "type" "sse<multdiv_mnemonic>")
+ (set_attr "prefix" "orig,maybe_evex")
+ (set_attr "btver2_decode" "direct,double")
(set_attr "mode" "<ssescalarmode>")])
(define_expand "div<mode>3"
@@ -1033,28 +1239,10 @@
(set_attr "prefix" "orig,vex")
(set_attr "mode" "<MODE>")])
-(define_insn "<sse>_vmdiv<mode>3"
- [(set (match_operand:VF_128 0 "register_operand" "=x,v")
- (vec_merge:VF_128
- (div:VF_128
- (match_operand:VF_128 1 "register_operand" "0,v")
- (match_operand:VF_128 2 "nonimmediate_operand" "xm,vm"))
- (match_dup 1)
- (const_int 1)))]
- "TARGET_SSE"
- "@
- div<ssescalarmodesuffix>\t{%2, %0|%0, %<iptr>2}
- vdiv<ssescalarmodesuffix>\t{%2, %1, %0|%0, %1, %<iptr>2}"
- [(set_attr "isa" "noavx,avx")
- (set_attr "type" "ssediv")
- (set_attr "prefix" "orig,vex")
- (set_attr "btver2_decode" "direct,double")
- (set_attr "mode" "<ssescalarmode>")])
-
(define_insn "<sse>_rcp<mode>2"
- [(set (match_operand:VF1 0 "register_operand" "=x")
- (unspec:VF1
- [(match_operand:VF1 1 "nonimmediate_operand" "xm")] UNSPEC_RCP))]
+ [(set (match_operand:VF1_128_256 0 "register_operand" "=x")
+ (unspec:VF1_128_256
+ [(match_operand:VF1_128_256 1 "nonimmediate_operand" "xm")] UNSPEC_RCP))]
"TARGET_SSE"
"%vrcpps\t{%1, %0|%0, %1}"
[(set_attr "type" "sse")
@@ -1081,6 +1269,32 @@
(set_attr "prefix" "orig,vex")
(set_attr "mode" "SF")])
+(define_insn "rcp14<mode>"
+ [(set (match_operand:VF_512 0 "register_operand" "=v")
+ (unspec:VF_512
+ [(match_operand:VF_512 1 "nonimmediate_operand" "vm")]
+ UNSPEC_RCP14))]
+ "TARGET_AVX512F"
+ "vrcp14<ssemodesuffix>\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sse")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "srcp14<mode>"
+ [(set (match_operand:VF_128 0 "register_operand" "=v")
+ (vec_merge:VF_128
+ (unspec:VF_128
+ [(match_operand:VF_128 1 "register_operand" "v")
+ (match_operand:VF_128 2 "nonimmediate_operand" "vm")]
+ UNSPEC_RCP14)
+ (match_dup 1)
+ (const_int 1)))]
+ "TARGET_AVX512F"
+ "vrcp14<ssescalarmodesuffix>\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "sse")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<MODE>")])
+
(define_expand "sqrt<mode>2"
[(set (match_operand:VF2 0 "register_operand")
(sqrt:VF2 (match_operand:VF2 1 "nonimmediate_operand")))]
@@ -1132,9 +1346,9 @@
(set_attr "mode" "<ssescalarmode>")])
(define_expand "rsqrt<mode>2"
- [(set (match_operand:VF1 0 "register_operand")
- (unspec:VF1
- [(match_operand:VF1 1 "nonimmediate_operand")] UNSPEC_RSQRT))]
+ [(set (match_operand:VF1_128_256 0 "register_operand")
+ (unspec:VF1_128_256
+ [(match_operand:VF1_128_256 1 "nonimmediate_operand")] UNSPEC_RSQRT))]
"TARGET_SSE_MATH"
{
ix86_emit_swsqrtsf (operands[0], operands[1], <MODE>mode, true);
@@ -1142,15 +1356,41 @@
})
(define_insn "<sse>_rsqrt<mode>2"
- [(set (match_operand:VF1 0 "register_operand" "=x")
- (unspec:VF1
- [(match_operand:VF1 1 "nonimmediate_operand" "xm")] UNSPEC_RSQRT))]
+ [(set (match_operand:VF1_128_256 0 "register_operand" "=x")
+ (unspec:VF1_128_256
+ [(match_operand:VF1_128_256 1 "nonimmediate_operand" "xm")] UNSPEC_RSQRT))]
"TARGET_SSE"
"%vrsqrtps\t{%1, %0|%0, %1}"
[(set_attr "type" "sse")
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "<MODE>")])
+(define_insn "rsqrt14<mode>"
+ [(set (match_operand:VF_512 0 "register_operand" "=v")
+ (unspec:VF_512
+ [(match_operand:VF_512 1 "nonimmediate_operand" "vm")]
+ UNSPEC_RSQRT14))]
+ "TARGET_AVX512F"
+ "vrsqrt14<ssemodesuffix>\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sse")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "rsqrt14<mode>"
+ [(set (match_operand:VF_128 0 "register_operand" "=v")
+ (vec_merge:VF_128
+ (unspec:VF_128
+ [(match_operand:VF_128 1 "register_operand" "v")
+ (match_operand:VF_128 2 "nonimmediate_operand" "vm")]
+ UNSPEC_RSQRT14)
+ (match_dup 1)
+ (const_int 1)))]
+ "TARGET_AVX512F"
+ "vrsqrt14<ssescalarmodesuffix>\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "sse")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<MODE>")])
+
(define_insn "sse_vmrsqrtv4sf2"
[(set (match_operand:V4SF 0 "register_operand" "=x,x")
(vec_merge:V4SF
@@ -1239,10 +1479,10 @@
;; presence of -0.0 and NaN.
(define_insn "*ieee_smin<mode>3"
- [(set (match_operand:VF 0 "register_operand" "=x,x")
+ [(set (match_operand:VF 0 "register_operand" "=v,v")
(unspec:VF
- [(match_operand:VF 1 "register_operand" "0,x")
- (match_operand:VF 2 "nonimmediate_operand" "xm,xm")]
+ [(match_operand:VF 1 "register_operand" "0,v")
+ (match_operand:VF 2 "nonimmediate_operand" "vm,vm")]
UNSPEC_IEEE_MIN))]
"TARGET_SSE"
"@
@@ -1254,10 +1494,10 @@
(set_attr "mode" "<MODE>")])
(define_insn "*ieee_smax<mode>3"
- [(set (match_operand:VF 0 "register_operand" "=x,x")
+ [(set (match_operand:VF 0 "register_operand" "=v,v")
(unspec:VF
- [(match_operand:VF 1 "register_operand" "0,x")
- (match_operand:VF 2 "nonimmediate_operand" "xm,xm")]
+ [(match_operand:VF 1 "register_operand" "0,v")
+ (match_operand:VF 2 "nonimmediate_operand" "vm,vm")]
UNSPEC_IEEE_MAX))]
"TARGET_SSE"
"@
@@ -1536,6 +1776,15 @@
(set_attr "prefix_rep" "1,*")
(set_attr "mode" "V4SF")])
+(define_expand "reduc_splus_v8df"
+ [(match_operand:V8DF 0 "register_operand")
+ (match_operand:V8DF 1 "register_operand")]
+ "TARGET_AVX512F"
+{
+ ix86_expand_reduc (gen_addv8df3, operands[0], operands[1]);
+ DONE;
+})
+
(define_expand "reduc_splus_v4df"
[(match_operand:V4DF 0 "register_operand")
(match_operand:V4DF 1 "register_operand")]
@@ -1558,6 +1807,15 @@
DONE;
})
+(define_expand "reduc_splus_v16sf"
+ [(match_operand:V16SF 0 "register_operand")
+ (match_operand:V16SF 1 "register_operand")]
+ "TARGET_AVX512F"
+{
+ ix86_expand_reduc (gen_addv16sf3, operands[0], operands[1]);
+ DONE;
+})
+
(define_expand "reduc_splus_v8sf"
[(match_operand:V8SF 0 "register_operand")
(match_operand:V8SF 1 "register_operand")]
@@ -1593,7 +1851,9 @@
[(V32QI "TARGET_AVX2") (V16HI "TARGET_AVX2")
(V8SI "TARGET_AVX2") (V4DI "TARGET_AVX2")
(V8SF "TARGET_AVX") (V4DF "TARGET_AVX")
- (V4SF "TARGET_SSE")])
+ (V4SF "TARGET_SSE") (V16SI "TARGET_AVX512F")
+ (V8DI "TARGET_AVX512F") (V16SF "TARGET_AVX512F")
+ (V8DF "TARGET_AVX512F")])
(define_expand "reduc_<code>_<mode>"
[(smaxmin:REDUC_SMINMAX_MODE
@@ -1606,6 +1866,16 @@
})
(define_expand "reduc_<code>_<mode>"
+ [(umaxmin:VI48_512
+ (match_operand:VI48_512 0 "register_operand")
+ (match_operand:VI48_512 1 "register_operand"))]
+ "TARGET_AVX512F"
+{
+ ix86_expand_reduc (gen_<code><mode>3, operands[0], operands[1]);
+ DONE;
+})
+
+(define_expand "reduc_<code>_<mode>"
[(umaxmin:VI_256
(match_operand:VI_256 0 "register_operand")
(match_operand:VI_256 1 "register_operand"))]
@@ -1632,10 +1902,10 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define_insn "avx_cmp<mode>3"
- [(set (match_operand:VF 0 "register_operand" "=x")
- (unspec:VF
- [(match_operand:VF 1 "register_operand" "x")
- (match_operand:VF 2 "nonimmediate_operand" "xm")
+ [(set (match_operand:VF_128_256 0 "register_operand" "=x")
+ (unspec:VF_128_256
+ [(match_operand:VF_128_256 1 "register_operand" "x")
+ (match_operand:VF_128_256 2 "nonimmediate_operand" "xm")
(match_operand:SI 3 "const_0_to_31_operand" "n")]
UNSPEC_PCMP))]
"TARGET_AVX"
@@ -1663,10 +1933,10 @@
(set_attr "mode" "<ssescalarmode>")])
(define_insn "*<sse>_maskcmp<mode>3_comm"
- [(set (match_operand:VF 0 "register_operand" "=x,x")
- (match_operator:VF 3 "sse_comparison_operator"
- [(match_operand:VF 1 "register_operand" "%0,x")
- (match_operand:VF 2 "nonimmediate_operand" "xm,xm")]))]
+ [(set (match_operand:VF_128_256 0 "register_operand" "=x,x")
+ (match_operator:VF_128_256 3 "sse_comparison_operator"
+ [(match_operand:VF_128_256 1 "register_operand" "%0,x")
+ (match_operand:VF_128_256 2 "nonimmediate_operand" "xm,xm")]))]
"TARGET_SSE
&& GET_RTX_CLASS (GET_CODE (operands[3])) == RTX_COMM_COMPARE"
"@
@@ -1679,10 +1949,10 @@
(set_attr "mode" "<MODE>")])
(define_insn "<sse>_maskcmp<mode>3"
- [(set (match_operand:VF 0 "register_operand" "=x,x")
- (match_operator:VF 3 "sse_comparison_operator"
- [(match_operand:VF 1 "register_operand" "0,x")
- (match_operand:VF 2 "nonimmediate_operand" "xm,xm")]))]
+ [(set (match_operand:VF_128_256 0 "register_operand" "=x,x")
+ (match_operator:VF_128_256 3 "sse_comparison_operator"
+ [(match_operand:VF_128_256 1 "register_operand" "0,x")
+ (match_operand:VF_128_256 2 "nonimmediate_operand" "xm,xm")]))]
"TARGET_SSE"
"@
cmp%D3<ssemodesuffix>\t{%2, %0|%0, %2}
@@ -1711,14 +1981,74 @@
(set_attr "prefix" "orig,vex")
(set_attr "mode" "<ssescalarmode>")])
+(define_mode_attr cmp_imm_predicate
+ [(V16SF "const_0_to_31_operand") (V8DF "const_0_to_31_operand")
+ (V16SI "const_0_to_7_operand") (V8DI "const_0_to_7_operand")])
+
+(define_insn "avx512f_cmp<mode>3"
+ [(set (match_operand:<avx512fmaskmode> 0 "register_operand" "=k")
+ (unspec:<avx512fmaskmode>
+ [(match_operand:VI48F_512 1 "register_operand" "v")
+ (match_operand:VI48F_512 2 "nonimmediate_operand" "vm")
+ (match_operand:SI 3 "<cmp_imm_predicate>" "n")]
+ UNSPEC_PCMP))]
+ "TARGET_AVX512F"
+ "v<sseintprefix>cmp<ssemodesuffix>\t{%3, %2, %1, %0|%0, %1, %2, %3}"
+ [(set_attr "type" "ssecmp")
+ (set_attr "length_immediate" "1")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<sseinsnmode>")])
+
+(define_insn "avx512f_ucmp<mode>3"
+ [(set (match_operand:<avx512fmaskmode> 0 "register_operand" "=k")
+ (unspec:<avx512fmaskmode>
+ [(match_operand:VI48_512 1 "register_operand" "v")
+ (match_operand:VI48_512 2 "nonimmediate_operand" "vm")
+ (match_operand:SI 3 "const_0_to_7_operand" "n")]
+ UNSPEC_UNSIGNED_PCMP))]
+ "TARGET_AVX512F"
+ "vpcmpu<ssemodesuffix>\t{%3, %2, %1, %0|%0, %1, %2, %3}"
+ [(set_attr "type" "ssecmp")
+ (set_attr "length_immediate" "1")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<sseinsnmode>")])
+
+(define_insn "avx512f_vmcmp<mode>3"
+ [(set (match_operand:<avx512fmaskmode> 0 "register_operand" "=k")
+ (and:<avx512fmaskmode>
+ (unspec:<avx512fmaskmode>
+ [(match_operand:VF_128 1 "register_operand" "v")
+ (match_operand:VF_128 2 "nonimmediate_operand" "vm")
+ (match_operand:SI 3 "const_0_to_31_operand" "n")]
+ UNSPEC_PCMP)
+ (const_int 1)))]
+ "TARGET_AVX512F"
+ "vcmp<ssescalarmodesuffix>\t{%3, %2, %1, %0|%0, %1, %2, %3}"
+ [(set_attr "type" "ssecmp")
+ (set_attr "length_immediate" "1")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<ssescalarmode>")])
+
+(define_insn "avx512f_maskcmp<mode>3"
+ [(set (match_operand:<avx512fmaskmode> 0 "register_operand" "=k")
+ (match_operator:<avx512fmaskmode> 3 "sse_comparison_operator"
+ [(match_operand:VF 1 "register_operand" "v")
+ (match_operand:VF 2 "nonimmediate_operand" "vm")]))]
+ "TARGET_SSE"
+ "vcmp%D3<ssemodesuffix>\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "ssecmp")
+ (set_attr "length_immediate" "1")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<sseinsnmode>")])
+
(define_insn "<sse>_comi"
[(set (reg:CCFP FLAGS_REG)
(compare:CCFP
(vec_select:MODEF
- (match_operand:<ssevecmode> 0 "register_operand" "x")
+ (match_operand:<ssevecmode> 0 "register_operand" "v")
(parallel [(const_int 0)]))
(vec_select:MODEF
- (match_operand:<ssevecmode> 1 "nonimmediate_operand" "xm")
+ (match_operand:<ssevecmode> 1 "nonimmediate_operand" "vm")
(parallel [(const_int 0)]))))]
"SSE_FLOAT_MODE_P (<MODE>mode)"
"%vcomi<ssemodesuffix>\t{%1, %0|%0, %<iptr>1}"
@@ -1735,10 +2065,10 @@
[(set (reg:CCFPU FLAGS_REG)
(compare:CCFPU
(vec_select:MODEF
- (match_operand:<ssevecmode> 0 "register_operand" "x")
+ (match_operand:<ssevecmode> 0 "register_operand" "v")
(parallel [(const_int 0)]))
(vec_select:MODEF
- (match_operand:<ssevecmode> 1 "nonimmediate_operand" "xm")
+ (match_operand:<ssevecmode> 1 "nonimmediate_operand" "vm")
(parallel [(const_int 0)]))))]
"SSE_FLOAT_MODE_P (<MODE>mode)"
"%vucomi<ssemodesuffix>\t{%1, %0|%0, %<iptr>1}"
@@ -1751,6 +2081,23 @@
(const_string "0")))
(set_attr "mode" "<MODE>")])
+(define_expand "vcond<V_512:mode><VF_512:mode>"
+ [(set (match_operand:V_512 0 "register_operand")
+ (if_then_else:V_512
+ (match_operator 3 ""
+ [(match_operand:VF_512 4 "nonimmediate_operand")
+ (match_operand:VF_512 5 "nonimmediate_operand")])
+ (match_operand:V_512 1 "general_operand")
+ (match_operand:V_512 2 "general_operand")))]
+ "TARGET_AVX512F
+ && (GET_MODE_NUNITS (<V_512:MODE>mode)
+ == GET_MODE_NUNITS (<VF_512:MODE>mode))"
+{
+ bool ok = ix86_expand_fp_vcond (operands);
+ gcc_assert (ok);
+ DONE;
+})
+
(define_expand "vcond<V_256:mode><VF_256:mode>"
[(set (match_operand:V_256 0 "register_operand")
(if_then_else:V_256
@@ -1792,11 +2139,11 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define_insn "<sse>_andnot<mode>3"
- [(set (match_operand:VF 0 "register_operand" "=x,x")
+ [(set (match_operand:VF 0 "register_operand" "=x,v")
(and:VF
(not:VF
- (match_operand:VF 1 "register_operand" "0,x"))
- (match_operand:VF 2 "nonimmediate_operand" "xm,xm")))]
+ (match_operand:VF 1 "register_operand" "0,v"))
+ (match_operand:VF 2 "nonimmediate_operand" "xm,vm")))]
"TARGET_SSE"
{
static char buf[32];
@@ -1825,12 +2172,19 @@
gcc_unreachable ();
}
+ /* There is no vandnp[sd]. Use vpandnq. */
+ if (GET_MODE_SIZE (<MODE>mode) == 64)
+ {
+ suffix = "q";
+ ops = "vpandn%s\t{%%2, %%1, %%0|%%0, %%1, %%2}";
+ }
+
snprintf (buf, sizeof (buf), ops, suffix);
return buf;
}
[(set_attr "isa" "noavx,avx")
(set_attr "type" "sselog")
- (set_attr "prefix" "orig,vex")
+ (set_attr "prefix" "orig,maybe_evex")
(set (attr "mode")
(cond [(match_test "TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL")
(const_string "<ssePSmode>")
@@ -1842,13 +2196,21 @@
(const_string "<MODE>")))])
(define_expand "<code><mode>3"
- [(set (match_operand:VF 0 "register_operand")
- (any_logic:VF
- (match_operand:VF 1 "nonimmediate_operand")
- (match_operand:VF 2 "nonimmediate_operand")))]
+ [(set (match_operand:VF_128_256 0 "register_operand")
+ (any_logic:VF_128_256
+ (match_operand:VF_128_256 1 "nonimmediate_operand")
+ (match_operand:VF_128_256 2 "nonimmediate_operand")))]
"TARGET_SSE"
"ix86_fixup_binary_operands_no_copy (<CODE>, <MODE>mode, operands);")
+(define_expand "<code><mode>3"
+ [(set (match_operand:VF_512 0 "register_operand")
+ (fpint_logic:VF_512
+ (match_operand:VF_512 1 "nonimmediate_operand")
+ (match_operand:VF_512 2 "nonimmediate_operand")))]
+ "TARGET_AVX512F"
+ "ix86_fixup_binary_operands_no_copy (<CODE>, <MODE>mode, operands);")
+
(define_insn "*<code><mode>3"
[(set (match_operand:VF 0 "register_operand" "=x,v")
(any_logic:VF
@@ -1882,12 +2244,19 @@
gcc_unreachable ();
}
+ /* There is no v<logic>p[sd]. Use vp<logic>q. */
+ if (GET_MODE_SIZE (<MODE>mode) == 64)
+ {
+ suffix = "q";
+ ops = "vp<logic>%s\t{%%2, %%1, %%0|%%0, %%1, %%2}";
+ }
+
snprintf (buf, sizeof (buf), ops, suffix);
return buf;
}
[(set_attr "isa" "noavx,avx")
(set_attr "type" "sselog")
- (set_attr "prefix" "orig,vex")
+ (set_attr "prefix" "orig,maybe_evex")
(set (attr "mode")
(cond [(match_test "TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL")
(const_string "<ssePSmode>")
@@ -2105,6 +2474,23 @@
]
(const_string "TI")))])
+;; There are no floating point xor for V16SF and V8DF in avx512f
+;; but we need them for negation. Instead we use int versions of
+;; xor. Maybe there could be a better way to do that.
+
+(define_mode_attr avx512flogicsuff
+ [(V16SF "d") (V8DF "q")])
+
+(define_insn "avx512f_<logic><mode>"
+ [(set (match_operand:VF_512 0 "register_operand" "=v")
+ (fpint_logic:VF_512
+ (match_operand:VF_512 1 "register_operand" "v")
+ (match_operand:VF_512 2 "nonimmediate_operand" "vm")))]
+ "TARGET_AVX512F"
+ "vp<logic><avx512flogicsuff>\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "prefix" "evex")])
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; FMA floating point multiply/accumulate instructions. These include
@@ -2113,9 +2499,22 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; The standard names for scalar FMA are only available with SSE math enabled.
-(define_mode_iterator FMAMODEM [(SF "TARGET_SSE_MATH")
- (DF "TARGET_SSE_MATH")
- V4SF V2DF V8SF V4DF])
+;; CPUID bit AVX512F enables evex encoded scalar and 512-bit fma. It doesn't
+;; care about FMA bit, so we enable fma for TARGET_AVX512F even when TARGET_FMA
+;; and TARGET_FMA4 are both false.
+;; TODO: In theory AVX512F does not automatically imply FMA, and without FMA
+;; one must force the EVEX encoding of the fma insns. Ideally we'd improve
+;; GAS to allow proper prefix selection. However, for the moment all hardware
+;; that supports AVX512F also supports FMA so we can ignore this for now.
+(define_mode_iterator FMAMODEM
+ [(SF "TARGET_SSE_MATH && (TARGET_FMA || TARGET_FMA4 || TARGET_AVX512F)")
+ (DF "TARGET_SSE_MATH && (TARGET_FMA || TARGET_FMA4 || TARGET_AVX512F)")
+ (V4SF "TARGET_FMA || TARGET_FMA4")
+ (V2DF "TARGET_FMA || TARGET_FMA4")
+ (V8SF "TARGET_FMA || TARGET_FMA4")
+ (V4DF "TARGET_FMA || TARGET_FMA4")
+ (V16SF "TARGET_AVX512F")
+ (V8DF "TARGET_AVX512F")])
(define_expand "fma<mode>4"
[(set (match_operand:FMAMODEM 0 "register_operand")
@@ -2123,7 +2522,7 @@
(match_operand:FMAMODEM 1 "nonimmediate_operand")
(match_operand:FMAMODEM 2 "nonimmediate_operand")
(match_operand:FMAMODEM 3 "nonimmediate_operand")))]
- "TARGET_FMA || TARGET_FMA4")
+ "")
(define_expand "fms<mode>4"
[(set (match_operand:FMAMODEM 0 "register_operand")
@@ -2131,7 +2530,7 @@
(match_operand:FMAMODEM 1 "nonimmediate_operand")
(match_operand:FMAMODEM 2 "nonimmediate_operand")
(neg:FMAMODEM (match_operand:FMAMODEM 3 "nonimmediate_operand"))))]
- "TARGET_FMA || TARGET_FMA4")
+ "")
(define_expand "fnma<mode>4"
[(set (match_operand:FMAMODEM 0 "register_operand")
@@ -2139,7 +2538,7 @@
(neg:FMAMODEM (match_operand:FMAMODEM 1 "nonimmediate_operand"))
(match_operand:FMAMODEM 2 "nonimmediate_operand")
(match_operand:FMAMODEM 3 "nonimmediate_operand")))]
- "TARGET_FMA || TARGET_FMA4")
+ "")
(define_expand "fnms<mode>4"
[(set (match_operand:FMAMODEM 0 "register_operand")
@@ -2147,10 +2546,17 @@
(neg:FMAMODEM (match_operand:FMAMODEM 1 "nonimmediate_operand"))
(match_operand:FMAMODEM 2 "nonimmediate_operand")
(neg:FMAMODEM (match_operand:FMAMODEM 3 "nonimmediate_operand"))))]
- "TARGET_FMA || TARGET_FMA4")
+ "")
;; The builtins for intrinsics are not constrained by SSE math enabled.
-(define_mode_iterator FMAMODE [SF DF V4SF V2DF V8SF V4DF])
+(define_mode_iterator FMAMODE [(SF "TARGET_FMA || TARGET_FMA4 || TARGET_AVX512F")
+ (DF "TARGET_FMA || TARGET_FMA4 || TARGET_AVX512F")
+ (V4SF "TARGET_FMA || TARGET_FMA4")
+ (V2DF "TARGET_FMA || TARGET_FMA4")
+ (V8SF "TARGET_FMA || TARGET_FMA4")
+ (V4DF "TARGET_FMA || TARGET_FMA4")
+ (V16SF "TARGET_AVX512F")
+ (V8DF "TARGET_AVX512F")])
(define_expand "fma4i_fmadd_<mode>"
[(set (match_operand:FMAMODE 0 "register_operand")
@@ -2158,7 +2564,7 @@
(match_operand:FMAMODE 1 "nonimmediate_operand")
(match_operand:FMAMODE 2 "nonimmediate_operand")
(match_operand:FMAMODE 3 "nonimmediate_operand")))]
- "TARGET_FMA || TARGET_FMA4")
+ "")
(define_insn "*fma_fmadd_<mode>"
[(set (match_operand:FMAMODE 0 "register_operand" "=v,v,v,x,x")
@@ -2166,7 +2572,7 @@
(match_operand:FMAMODE 1 "nonimmediate_operand" "%0, 0, v, x,x")
(match_operand:FMAMODE 2 "nonimmediate_operand" "vm, v,vm, x,m")
(match_operand:FMAMODE 3 "nonimmediate_operand" " v,vm, 0,xm,x")))]
- "TARGET_FMA || TARGET_FMA4"
+ ""
"@
vfmadd132<ssemodesuffix>\t{%2, %3, %0|%0, %3, %2}
vfmadd213<ssemodesuffix>\t{%3, %2, %0|%0, %2, %3}
@@ -2177,14 +2583,14 @@
(set_attr "type" "ssemuladd")
(set_attr "mode" "<MODE>")])
-(define_insn "*fma_fmsub_<mode>"
+(define_insn "fma_fmsub_<mode>"
[(set (match_operand:FMAMODE 0 "register_operand" "=v,v,v,x,x")
(fma:FMAMODE
(match_operand:FMAMODE 1 "nonimmediate_operand" "%0, 0, v, x,x")
(match_operand:FMAMODE 2 "nonimmediate_operand" "vm, v,vm, x,m")
(neg:FMAMODE
(match_operand:FMAMODE 3 "nonimmediate_operand" " v,vm, 0,xm,x"))))]
- "TARGET_FMA || TARGET_FMA4"
+ ""
"@
vfmsub132<ssemodesuffix>\t{%2, %3, %0|%0, %3, %2}
vfmsub213<ssemodesuffix>\t{%3, %2, %0|%0, %2, %3}
@@ -2195,14 +2601,14 @@
(set_attr "type" "ssemuladd")
(set_attr "mode" "<MODE>")])
-(define_insn "*fma_fnmadd_<mode>"
+(define_insn "fma_fnmadd_<mode>"
[(set (match_operand:FMAMODE 0 "register_operand" "=v,v,v,x,x")
(fma:FMAMODE
(neg:FMAMODE
(match_operand:FMAMODE 1 "nonimmediate_operand" "%0, 0, v, x,x"))
(match_operand:FMAMODE 2 "nonimmediate_operand" "vm, v,vm, x,m")
(match_operand:FMAMODE 3 "nonimmediate_operand" " v,vm, 0,xm,x")))]
- "TARGET_FMA || TARGET_FMA4"
+ ""
"@
vfnmadd132<ssemodesuffix>\t{%2, %3, %0|%0, %3, %2}
vfnmadd213<ssemodesuffix>\t{%3, %2, %0|%0, %2, %3}
@@ -2221,7 +2627,7 @@
(match_operand:FMAMODE 2 "nonimmediate_operand" "vm, v,vm, x,m")
(neg:FMAMODE
(match_operand:FMAMODE 3 "nonimmediate_operand" " v,vm, 0,xm,x"))))]
- "TARGET_FMA || TARGET_FMA4"
+ ""
"@
vfnmsub132<ssemodesuffix>\t{%2, %3, %0|%0, %3, %2}
vfnmsub213<ssemodesuffix>\t{%3, %2, %0|%0, %2, %3}
@@ -2250,7 +2656,7 @@
(match_operand:VF 2 "nonimmediate_operand")
(match_operand:VF 3 "nonimmediate_operand")]
UNSPEC_FMADDSUB))]
- "TARGET_FMA || TARGET_FMA4")
+ "TARGET_FMA || TARGET_FMA4 || TARGET_AVX512F")
(define_insn "*fma_fmaddsub_<mode>"
[(set (match_operand:VF 0 "register_operand" "=v,v,v,x,x")
@@ -2259,7 +2665,7 @@
(match_operand:VF 2 "nonimmediate_operand" "vm, v,vm, x,m")
(match_operand:VF 3 "nonimmediate_operand" " v,vm, 0,xm,x")]
UNSPEC_FMADDSUB))]
- "TARGET_FMA || TARGET_FMA4"
+ "(TARGET_FMA || TARGET_FMA4 || TARGET_AVX512F)"
"@
vfmaddsub132<ssemodesuffix>\t{%2, %3, %0|%0, %3, %2}
vfmaddsub213<ssemodesuffix>\t{%3, %2, %0|%0, %2, %3}
@@ -2278,7 +2684,7 @@
(neg:VF
(match_operand:VF 3 "nonimmediate_operand" " v,vm, 0,xm,x"))]
UNSPEC_FMADDSUB))]
- "TARGET_FMA || TARGET_FMA4"
+ "(TARGET_FMA || TARGET_FMA4 || TARGET_AVX512F)"
"@
vfmsubadd132<ssemodesuffix>\t{%2, %3, %0|%0, %3, %2}
vfmsubadd213<ssemodesuffix>\t{%3, %2, %0|%0, %2, %3}
@@ -2312,7 +2718,7 @@
(match_operand:VF_128 3 "nonimmediate_operand" " v,vm"))
(match_dup 1)
(const_int 1)))]
- "TARGET_FMA"
+ "TARGET_FMA || TARGET_AVX512F"
"@
vfmadd132<ssescalarmodesuffix>\t{%2, %3, %0|%0, %<iptr>3, %<iptr>2}
vfmadd213<ssescalarmodesuffix>\t{%3, %2, %0|%0, %<iptr>2, %<iptr>3}"
@@ -2329,7 +2735,7 @@
(match_operand:VF_128 3 "nonimmediate_operand" " v,vm")))
(match_dup 1)
(const_int 1)))]
- "TARGET_FMA"
+ "TARGET_FMA || TARGET_AVX512F"
"@
vfmsub132<ssescalarmodesuffix>\t{%2, %3, %0|%0, %<iptr>3, %<iptr>2}
vfmsub213<ssescalarmodesuffix>\t{%3, %2, %0|%0, %<iptr>2, %<iptr>3}"
@@ -2346,7 +2752,7 @@
(match_operand:VF_128 3 "nonimmediate_operand" " v,vm"))
(match_dup 1)
(const_int 1)))]
- "TARGET_FMA"
+ "TARGET_FMA || TARGET_AVX512F"
"@
vfnmadd132<ssescalarmodesuffix>\t{%2, %3, %0|%0, %<iptr>3, %<iptr>2}
vfnmadd213<ssescalarmodesuffix>\t{%3, %2, %0|%0, %<iptr>2, %<iptr>3}"
@@ -2364,7 +2770,7 @@
(match_operand:VF_128 3 "nonimmediate_operand" " v,vm")))
(match_dup 1)
(const_int 1)))]
- "TARGET_FMA"
+ "TARGET_FMA || TARGET_AVX512F"
"@
vfnmsub132<ssescalarmodesuffix>\t{%2, %3, %0|%0, %<iptr>3, %<iptr>2}
vfnmsub213<ssescalarmodesuffix>\t{%3, %2, %0|%0, %<iptr>2, %<iptr>3}"
@@ -2506,7 +2912,7 @@
(set_attr "amdfam10_decode" "vector,double,*")
(set_attr "bdver1_decode" "double,direct,*")
(set_attr "btver2_decode" "double,double,double")
- (set_attr "prefix" "orig,orig,vex")
+ (set_attr "prefix" "orig,orig,maybe_evex")
(set_attr "mode" "SF")])
(define_insn "sse_cvtsi2ssq"
@@ -2529,7 +2935,7 @@
(set_attr "btver2_decode" "double,double,double")
(set_attr "length_vex" "*,*,4")
(set_attr "prefix_rex" "1,1,*")
- (set_attr "prefix" "orig,orig,vex")
+ (set_attr "prefix" "orig,orig,maybe_evex")
(set_attr "mode" "SF")])
(define_insn "sse_cvtss2si"
@@ -2580,7 +2986,7 @@
(define_insn "sse_cvtss2siq_2"
[(set (match_operand:DI 0 "register_operand" "=r,r")
- (unspec:DI [(match_operand:SF 1 "nonimmediate_operand" "x,m")]
+ (unspec:DI [(match_operand:SF 1 "nonimmediate_operand" "v,m")]
UNSPEC_FIX_NOTRUNC))]
"TARGET_SSE && TARGET_64BIT"
"%vcvtss2si{q}\t{%1, %0|%0, %k1}"
@@ -2624,6 +3030,34 @@
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "DI")])
+(define_insn "cvtusi2<ssescalarmodesuffix>32"
+ [(set (match_operand:VF_128 0 "register_operand" "=v")
+ (vec_merge:VF_128
+ (vec_duplicate:VF_128
+ (unsigned_float:<ssescalarmode>
+ (match_operand:SI 2 "nonimmediate_operand" "rm")))
+ (match_operand:VF_128 1 "register_operand" "v")
+ (const_int 1)))]
+ "TARGET_AVX512F"
+ "vcvtusi2<ssescalarmodesuffix>\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "sseicvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<ssescalarmode>")])
+
+(define_insn "cvtusi2<ssescalarmodesuffix>64"
+ [(set (match_operand:VF_128 0 "register_operand" "=v")
+ (vec_merge:VF_128
+ (vec_duplicate:VF_128
+ (unsigned_float:<ssescalarmode>
+ (match_operand:DI 2 "nonimmediate_operand" "rm")))
+ (match_operand:VF_128 1 "register_operand" "v")
+ (const_int 1)))]
+ "TARGET_AVX512F && TARGET_64BIT"
+ "vcvtusi2<ssescalarmodesuffix>\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "sseicvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<ssescalarmode>")])
+
(define_insn "float<sseintvecmodelower><mode>2"
[(set (match_operand:VF1 0 "register_operand" "=v")
(float:VF1
@@ -2634,6 +3068,16 @@
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "<sseinsnmode>")])
+(define_insn "ufloatv16siv16sf2"
+ [(set (match_operand:V16SF 0 "register_operand" "=v")
+ (unsigned_float:V16SF
+ (match_operand:V16SI 1 "nonimmediate_operand" "vm")))]
+ "TARGET_AVX512F"
+ "vcvtudq2ps\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "V16SF")])
+
(define_expand "floatuns<sseintvecmodelower><mode>2"
[(match_operand:VF1 0 "register_operand")
(match_operand:<sseintvecmode> 1 "register_operand")]
@@ -2643,20 +3087,16 @@
DONE;
})
-(define_insn "avx_cvtps2dq256"
- [(set (match_operand:V8SI 0 "register_operand" "=x")
- (unspec:V8SI [(match_operand:V8SF 1 "nonimmediate_operand" "xm")]
- UNSPEC_FIX_NOTRUNC))]
- "TARGET_AVX"
- "vcvtps2dq\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssecvt")
- (set_attr "prefix" "vex")
- (set_attr "mode" "OI")])
-(define_insn "sse2_cvtps2dq"
- [(set (match_operand:V4SI 0 "register_operand" "=x")
- (unspec:V4SI [(match_operand:V4SF 1 "nonimmediate_operand" "xm")]
- UNSPEC_FIX_NOTRUNC))]
+;; For <sse2_avx_avx512f>_fix_notrunc<sf2simodelower><mode> insn pattern
+(define_mode_attr sf2simodelower
+ [(V16SI "v16sf") (V8SI "v8sf") (V4SI "v4sf")])
+
+(define_insn "<sse2_avx_avx512f>_fix_notrunc<sf2simodelower><mode>"
+ [(set (match_operand:VI4_AVX 0 "register_operand" "=v")
+ (unspec:VI4_AVX
+ [(match_operand:<ssePSmode> 1 "nonimmediate_operand" "vm")]
+ UNSPEC_FIX_NOTRUNC))]
"TARGET_SSE2"
"%vcvtps2dq\t{%1, %0|%0, %1}"
[(set_attr "type" "ssecvt")
@@ -2666,7 +3106,39 @@
(const_string "*")
(const_string "1")))
(set_attr "prefix" "maybe_vex")
- (set_attr "mode" "TI")])
+ (set_attr "mode" "<sseinsnmode>")])
+
+(define_insn "avx512f_fix_notruncv16sfv16si"
+ [(set (match_operand:V16SI 0 "register_operand" "=v")
+ (unspec:V16SI
+ [(match_operand:V16SF 1 "nonimmediate_operand" "vm")]
+ UNSPEC_FIX_NOTRUNC))]
+ "TARGET_AVX512F"
+ "vcvtps2dq\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "XI")])
+
+(define_insn "avx512f_ufix_notruncv16sfv16si"
+ [(set (match_operand:V16SI 0 "register_operand" "=v")
+ (unspec:V16SI
+ [(match_operand:V16SF 1 "nonimmediate_operand" "vm")]
+ UNSPEC_UNSIGNED_FIX_NOTRUNC))]
+ "TARGET_AVX512F"
+ "vcvtps2udq\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "XI")])
+
+(define_insn "<fixsuffix>fix_truncv16sfv16si2"
+ [(set (match_operand:V16SI 0 "register_operand" "=v")
+ (any_fix:V16SI
+ (match_operand:V16SF 1 "nonimmediate_operand" "vm")))]
+ "TARGET_AVX512F"
+ "vcvttps2<fixsuffix>dq\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "XI")])
(define_insn "fix_truncv8sfv8si2"
[(set (match_operand:V8SI 0 "register_operand" "=x")
@@ -2772,11 +3244,11 @@
(set_attr "mode" "DF")])
(define_insn "sse2_cvtsi2sdq"
- [(set (match_operand:V2DF 0 "register_operand" "=x,x,x")
+ [(set (match_operand:V2DF 0 "register_operand" "=x,x,v")
(vec_merge:V2DF
(vec_duplicate:V2DF
(float:DF (match_operand:DI 2 "nonimmediate_operand" "r,m,rm")))
- (match_operand:V2DF 1 "register_operand" "0,0,x")
+ (match_operand:V2DF 1 "register_operand" "0,0,v")
(const_int 1)))]
"TARGET_SSE2 && TARGET_64BIT"
"@
@@ -2790,14 +3262,114 @@
(set_attr "bdver1_decode" "double,direct,*")
(set_attr "length_vex" "*,*,4")
(set_attr "prefix_rex" "1,1,*")
- (set_attr "prefix" "orig,orig,vex")
+ (set_attr "prefix" "orig,orig,maybe_evex")
(set_attr "mode" "DF")])
+(define_insn "avx512f_vcvtss2usi"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI
+ [(vec_select:SF
+ (match_operand:V4SF 1 "nonimmediate_operand" "vm")
+ (parallel [(const_int 0)]))]
+ UNSPEC_UNSIGNED_FIX_NOTRUNC))]
+ "TARGET_AVX512F"
+ "vcvtss2usi\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sseicvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "SI")])
+
+(define_insn "avx512f_vcvtss2usiq"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (unspec:DI
+ [(vec_select:SF
+ (match_operand:V4SF 1 "nonimmediate_operand" "vm")
+ (parallel [(const_int 0)]))]
+ UNSPEC_UNSIGNED_FIX_NOTRUNC))]
+ "TARGET_AVX512F && TARGET_64BIT"
+ "vcvtss2usi\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sseicvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "DI")])
+
+(define_insn "avx512f_vcvttss2usi"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unsigned_fix:SI
+ (vec_select:SF
+ (match_operand:V4SF 1 "nonimmediate_operand" "vm")
+ (parallel [(const_int 0)]))))]
+ "TARGET_AVX512F"
+ "vcvttss2usi\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sseicvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "SI")])
+
+(define_insn "avx512f_vcvttss2usiq"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (unsigned_fix:DI
+ (vec_select:SF
+ (match_operand:V4SF 1 "nonimmediate_operand" "vm")
+ (parallel [(const_int 0)]))))]
+ "TARGET_AVX512F && TARGET_64BIT"
+ "vcvttss2usi\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sseicvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "DI")])
+
+(define_insn "avx512f_vcvtsd2usi"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI
+ [(vec_select:DF
+ (match_operand:V2DF 1 "nonimmediate_operand" "vm")
+ (parallel [(const_int 0)]))]
+ UNSPEC_UNSIGNED_FIX_NOTRUNC))]
+ "TARGET_AVX512F"
+ "vcvtsd2usi\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sseicvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "SI")])
+
+(define_insn "avx512f_vcvtsd2usiq"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (unspec:DI
+ [(vec_select:DF
+ (match_operand:V2DF 1 "nonimmediate_operand" "vm")
+ (parallel [(const_int 0)]))]
+ UNSPEC_UNSIGNED_FIX_NOTRUNC))]
+ "TARGET_AVX512F && TARGET_64BIT"
+ "vcvtsd2usi\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sseicvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "DI")])
+
+(define_insn "avx512f_vcvttsd2usi"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unsigned_fix:SI
+ (vec_select:DF
+ (match_operand:V2DF 1 "nonimmediate_operand" "vm")
+ (parallel [(const_int 0)]))))]
+ "TARGET_AVX512F"
+ "vcvttsd2usi\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sseicvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "SI")])
+
+(define_insn "avx512f_vcvttsd2usiq"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (unsigned_fix:DI
+ (vec_select:DF
+ (match_operand:V2DF 1 "nonimmediate_operand" "vm")
+ (parallel [(const_int 0)]))))]
+ "TARGET_AVX512F && TARGET_64BIT"
+ "vcvttsd2usi\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sseicvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "DI")])
+
(define_insn "sse2_cvtsd2si"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(unspec:SI
[(vec_select:DF
- (match_operand:V2DF 1 "nonimmediate_operand" "x,m")
+ (match_operand:V2DF 1 "nonimmediate_operand" "v,m")
(parallel [(const_int 0)]))]
UNSPEC_FIX_NOTRUNC))]
"TARGET_SSE2"
@@ -2828,7 +3400,7 @@
[(set (match_operand:DI 0 "register_operand" "=r,r")
(unspec:DI
[(vec_select:DF
- (match_operand:V2DF 1 "nonimmediate_operand" "x,m")
+ (match_operand:V2DF 1 "nonimmediate_operand" "v,m")
(parallel [(const_int 0)]))]
UNSPEC_FIX_NOTRUNC))]
"TARGET_SSE2 && TARGET_64BIT"
@@ -2858,7 +3430,7 @@
[(set (match_operand:SI 0 "register_operand" "=r,r")
(fix:SI
(vec_select:DF
- (match_operand:V2DF 1 "nonimmediate_operand" "x,m")
+ (match_operand:V2DF 1 "nonimmediate_operand" "v,m")
(parallel [(const_int 0)]))))]
"TARGET_SSE2"
"%vcvttsd2si\t{%1, %0|%0, %q1}"
@@ -2875,7 +3447,7 @@
[(set (match_operand:DI 0 "register_operand" "=r,r")
(fix:DI
(vec_select:DF
- (match_operand:V2DF 1 "nonimmediate_operand" "x,m")
+ (match_operand:V2DF 1 "nonimmediate_operand" "v,m")
(parallel [(const_int 0)]))))]
"TARGET_SSE2 && TARGET_64BIT"
"%vcvttsd2si{q}\t{%1, %0|%0, %q1}"
@@ -2887,14 +3459,44 @@
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "DI")])
-(define_insn "floatv4siv4df2"
- [(set (match_operand:V4DF 0 "register_operand" "=x")
- (float:V4DF (match_operand:V4SI 1 "nonimmediate_operand" "xm")))]
+;; For float<si2dfmode><mode>2 insn pattern
+(define_mode_attr si2dfmode
+ [(V8DF "V8SI") (V4DF "V4SI")])
+(define_mode_attr si2dfmodelower
+ [(V8DF "v8si") (V4DF "v4si")])
+
+(define_insn "float<si2dfmodelower><mode>2"
+ [(set (match_operand:VF2_512_256 0 "register_operand" "=v")
+ (float:VF2_512_256 (match_operand:<si2dfmode> 1 "nonimmediate_operand" "vm")))]
"TARGET_AVX"
"vcvtdq2pd\t{%1, %0|%0, %1}"
[(set_attr "type" "ssecvt")
- (set_attr "prefix" "vex")
- (set_attr "mode" "V4DF")])
+ (set_attr "prefix" "maybe_vex")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "ufloatv8siv8df"
+ [(set (match_operand:V8DF 0 "register_operand" "=v")
+ (unsigned_float:V8DF (match_operand:V8SI 1 "nonimmediate_operand" "vm")))]
+ "TARGET_AVX512F"
+ "vcvtudq2pd\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "V8DF")])
+
+(define_insn "avx512f_cvtdq2pd512_2"
+ [(set (match_operand:V8DF 0 "register_operand" "=v")
+ (float:V8DF
+ (vec_select:V8SI
+ (match_operand:V16SI 1 "nonimmediate_operand" "vm")
+ (parallel [(const_int 0) (const_int 1)
+ (const_int 2) (const_int 3)
+ (const_int 4) (const_int 5)
+ (const_int 6) (const_int 7)]))))]
+ "TARGET_AVX"
+ "vcvtdq2pd\t{%t1, %0|%0, %t1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "V8DF")])
(define_insn "avx_cvtdq2pd256_2"
[(set (match_operand:V4DF 0 "register_operand" "=x")
@@ -2921,6 +3523,16 @@
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "V2DF")])
+(define_insn "avx512f_cvtpd2dq512"
+ [(set (match_operand:V8SI 0 "register_operand" "=v")
+ (unspec:V8SI [(match_operand:V8DF 1 "nonimmediate_operand" "vm")]
+ UNSPEC_FIX_NOTRUNC))]
+ "TARGET_AVX512F"
+ "vcvtpd2dq\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "OI")])
+
(define_insn "avx_cvtpd2dq256"
[(set (match_operand:V4SI 0 "register_operand" "=x")
(unspec:V4SI [(match_operand:V4DF 1 "nonimmediate_operand" "xm")]
@@ -2984,6 +3596,26 @@
(set_attr "athlon_decode" "vector")
(set_attr "bdver1_decode" "double")])
+(define_insn "avx512f_ufix_notruncv8dfv8si"
+ [(set (match_operand:V8SI 0 "register_operand" "=v")
+ (unspec:V8SI
+ [(match_operand:V8DF 1 "nonimmediate_operand" "vm")]
+ UNSPEC_UNSIGNED_FIX_NOTRUNC))]
+ "TARGET_AVX512F"
+ "vcvtpd2udq\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "OI")])
+
+(define_insn "<fixsuffix>fix_truncv8dfv8si2"
+ [(set (match_operand:V8SI 0 "register_operand" "=v")
+ (any_fix:V8SI (match_operand:V8DF 1 "nonimmediate_operand" "vm")))]
+ "TARGET_AVX512F"
+ "vcvttpd2<fixsuffix>dq\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "OI")])
+
(define_insn "fix_truncv4dfv4si2"
[(set (match_operand:V4SI 0 "register_operand" "=x")
(fix:V4SI (match_operand:V4DF 1 "nonimmediate_operand" "xm")))]
@@ -3085,6 +3717,16 @@
(set_attr "prefix" "orig,orig,vex")
(set_attr "mode" "DF")])
+(define_insn "avx512f_cvtpd2ps512"
+ [(set (match_operand:V8SF 0 "register_operand" "=v")
+ (float_truncate:V8SF
+ (match_operand:V8DF 1 "nonimmediate_operand" "vm")))]
+ "TARGET_AVX512F"
+ "vcvtpd2ps\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "V8SF")])
+
(define_insn "avx_cvtpd2ps256"
[(set (match_operand:V4SF 0 "register_operand" "=x")
(float_truncate:V4SF
@@ -3126,15 +3768,19 @@
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "V4SF")])
-(define_insn "avx_cvtps2pd256"
- [(set (match_operand:V4DF 0 "register_operand" "=x")
- (float_extend:V4DF
- (match_operand:V4SF 1 "nonimmediate_operand" "xm")))]
+;; For <sse2_avx_avx512f>_cvtps2pd<avxsizesuffix> insn pattern
+(define_mode_attr sf2dfmode
+ [(V8DF "V8SF") (V4DF "V4SF")])
+
+(define_insn "<sse2_avx_avx512f>_cvtps2pd<avxsizesuffix>"
+ [(set (match_operand:VF2_512_256 0 "register_operand" "=v")
+ (float_extend:VF2_512_256
+ (match_operand:<sf2dfmode> 1 "nonimmediate_operand" "vm")))]
"TARGET_AVX"
"vcvtps2pd\t{%1, %0|%0, %1}"
[(set_attr "type" "ssecvt")
- (set_attr "prefix" "vex")
- (set_attr "mode" "V4DF")])
+ (set_attr "prefix" "maybe_vex")
+ (set_attr "mode" "<MODE>")])
(define_insn "*avx_cvtps2pd256_2"
[(set (match_operand:V4DF 0 "register_operand" "=x")
@@ -3149,6 +3795,21 @@
(set_attr "prefix" "vex")
(set_attr "mode" "V4DF")])
+(define_insn "vec_unpacks_lo_v16sf"
+ [(set (match_operand:V8DF 0 "register_operand" "=v")
+ (float_extend:V8DF
+ (vec_select:V8SF
+ (match_operand:V16SF 1 "nonimmediate_operand" "vm")
+ (parallel [(const_int 0) (const_int 1)
+ (const_int 2) (const_int 3)
+ (const_int 4) (const_int 5)
+ (const_int 6) (const_int 7)]))))]
+ "TARGET_AVX512F"
+ "vcvtps2pd\t{%t1, %0|%0, %t1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "V8DF")])
+
(define_insn "sse2_cvtps2pd"
[(set (match_operand:V2DF 0 "register_operand" "=x")
(float_extend:V2DF
@@ -3193,6 +3854,20 @@
"TARGET_AVX"
"operands[2] = gen_reg_rtx (V4SFmode);")
+(define_expand "vec_unpacks_hi_v16sf"
+ [(set (match_dup 2)
+ (vec_select:V8SF
+ (match_operand:V16SF 1 "nonimmediate_operand")
+ (parallel [(const_int 8) (const_int 9)
+ (const_int 10) (const_int 11)
+ (const_int 12) (const_int 13)
+ (const_int 14) (const_int 15)])))
+ (set (match_operand:V8DF 0 "register_operand")
+ (float_extend:V8DF
+ (match_dup 2)))]
+"TARGET_AVX512F"
+"operands[2] = gen_reg_rtx (V8SFmode);")
+
(define_expand "vec_unpacks_lo_v4sf"
[(set (match_operand:V2DF 0 "register_operand")
(float_extend:V2DF
@@ -3211,11 +3886,12 @@
"TARGET_AVX")
(define_mode_attr sseunpackfltmode
- [(V8HI "V4SF") (V4SI "V2DF") (V16HI "V8SF") (V8SI "V4DF")])
+ [(V8HI "V4SF") (V4SI "V2DF") (V16HI "V8SF")
+ (V8SI "V4DF") (V32HI "V16SF") (V16SI "V8DF")])
(define_expand "vec_unpacks_float_hi_<mode>"
[(match_operand:<sseunpackfltmode> 0 "register_operand")
- (match_operand:VI2_AVX2 1 "register_operand")]
+ (match_operand:VI2_AVX512F 1 "register_operand")]
"TARGET_SSE2"
{
rtx tmp = gen_reg_rtx (<sseunpackmode>mode);
@@ -3228,7 +3904,7 @@
(define_expand "vec_unpacks_float_lo_<mode>"
[(match_operand:<sseunpackfltmode> 0 "register_operand")
- (match_operand:VI2_AVX2 1 "register_operand")]
+ (match_operand:VI2_AVX512F 1 "register_operand")]
"TARGET_SSE2"
{
rtx tmp = gen_reg_rtx (<sseunpackmode>mode);
@@ -3241,7 +3917,7 @@
(define_expand "vec_unpacku_float_hi_<mode>"
[(match_operand:<sseunpackfltmode> 0 "register_operand")
- (match_operand:VI2_AVX2 1 "register_operand")]
+ (match_operand:VI2_AVX512F 1 "register_operand")]
"TARGET_SSE2"
{
rtx tmp = gen_reg_rtx (<sseunpackmode>mode);
@@ -3254,7 +3930,7 @@
(define_expand "vec_unpacku_float_lo_<mode>"
[(match_operand:<sseunpackfltmode> 0 "register_operand")
- (match_operand:VI2_AVX2 1 "register_operand")]
+ (match_operand:VI2_AVX512F 1 "register_operand")]
"TARGET_SSE2"
{
rtx tmp = gen_reg_rtx (<sseunpackmode>mode);
@@ -3308,6 +3984,31 @@
(const_int 2) (const_int 3)]))))]
"TARGET_AVX")
+(define_expand "vec_unpacks_float_hi_v16si"
+ [(set (match_dup 2)
+ (vec_select:V8SI
+ (match_operand:V16SI 1 "nonimmediate_operand")
+ (parallel [(const_int 8) (const_int 9)
+ (const_int 10) (const_int 11)
+ (const_int 12) (const_int 13)
+ (const_int 14) (const_int 15)])))
+ (set (match_operand:V8DF 0 "register_operand")
+ (float:V8DF
+ (match_dup 2)))]
+ "TARGET_AVX512F"
+ "operands[2] = gen_reg_rtx (V8SImode);")
+
+(define_expand "vec_unpacks_float_lo_v16si"
+ [(set (match_operand:V8DF 0 "register_operand")
+ (float:V8DF
+ (vec_select:V8SI
+ (match_operand:V16SI 1 "nonimmediate_operand")
+ (parallel [(const_int 0) (const_int 1)
+ (const_int 2) (const_int 3)
+ (const_int 4) (const_int 5)
+ (const_int 6) (const_int 7)]))))]
+ "TARGET_AVX512F")
+
(define_expand "vec_unpacku_float_hi_v4si"
[(set (match_dup 5)
(vec_select:V4SI
@@ -3425,21 +4126,21 @@
DONE;
})
-(define_expand "vec_pack_trunc_v4df"
+(define_expand "vec_pack_trunc_<mode>"
[(set (match_dup 3)
- (float_truncate:V4SF
- (match_operand:V4DF 1 "nonimmediate_operand")))
+ (float_truncate:<sf2dfmode>
+ (match_operand:VF2_512_256 1 "nonimmediate_operand")))
(set (match_dup 4)
- (float_truncate:V4SF
- (match_operand:V4DF 2 "nonimmediate_operand")))
- (set (match_operand:V8SF 0 "register_operand")
- (vec_concat:V8SF
+ (float_truncate:<sf2dfmode>
+ (match_operand:VF2_512_256 2 "nonimmediate_operand")))
+ (set (match_operand:<ssePSmode> 0 "register_operand")
+ (vec_concat:<ssePSmode>
(match_dup 3)
(match_dup 4)))]
"TARGET_AVX"
{
- operands[3] = gen_reg_rtx (V4SFmode);
- operands[4] = gen_reg_rtx (V4SFmode);
+ operands[3] = gen_reg_rtx (<sf2dfmode>mode);
+ operands[4] = gen_reg_rtx (<sf2dfmode>mode);
})
(define_expand "vec_pack_trunc_v2df"
@@ -3470,6 +4171,23 @@
DONE;
})
+(define_expand "vec_pack_sfix_trunc_v8df"
+ [(match_operand:V16SI 0 "register_operand")
+ (match_operand:V8DF 1 "nonimmediate_operand")
+ (match_operand:V8DF 2 "nonimmediate_operand")]
+ "TARGET_AVX512F"
+{
+ rtx r1, r2;
+
+ r1 = gen_reg_rtx (V8SImode);
+ r2 = gen_reg_rtx (V8SImode);
+
+ emit_insn (gen_fix_truncv8dfv8si2 (r1, operands[1]));
+ emit_insn (gen_fix_truncv8dfv8si2 (r2, operands[2]));
+ emit_insn (gen_avx_vec_concatv16si (operands[0], r1, r2));
+ DONE;
+})
+
(define_expand "vec_pack_sfix_trunc_v4df"
[(match_operand:V8SI 0 "register_operand")
(match_operand:V4DF 1 "nonimmediate_operand")
@@ -3493,7 +4211,7 @@
(match_operand:V2DF 2 "nonimmediate_operand")]
"TARGET_SSE2"
{
- rtx tmp0, tmp1;
+ rtx tmp0, tmp1, tmp2;
if (TARGET_AVX && !TARGET_PREFER_AVX128)
{
@@ -3507,24 +4225,25 @@
{
tmp0 = gen_reg_rtx (V4SImode);
tmp1 = gen_reg_rtx (V4SImode);
+ tmp2 = gen_reg_rtx (V2DImode);
emit_insn (gen_sse2_cvttpd2dq (tmp0, operands[1]));
emit_insn (gen_sse2_cvttpd2dq (tmp1, operands[2]));
- emit_insn
- (gen_vec_interleave_lowv2di (gen_lowpart (V2DImode, operands[0]),
- gen_lowpart (V2DImode, tmp0),
- gen_lowpart (V2DImode, tmp1)));
+ emit_insn (gen_vec_interleave_lowv2di (tmp2,
+ gen_lowpart (V2DImode, tmp0),
+ gen_lowpart (V2DImode, tmp1)));
+ emit_move_insn (operands[0], gen_lowpart (V4SImode, tmp2));
}
DONE;
})
(define_mode_attr ssepackfltmode
- [(V4DF "V8SI") (V2DF "V4SI")])
+ [(V8DF "V16SI") (V4DF "V8SI") (V2DF "V4SI")])
(define_expand "vec_pack_ufix_trunc_<mode>"
[(match_operand:<ssepackfltmode> 0 "register_operand")
- (match_operand:VF2 1 "register_operand")
- (match_operand:VF2 2 "register_operand")]
+ (match_operand:VF2_128_256 1 "register_operand")
+ (match_operand:VF2_128_256 2 "register_operand")]
"TARGET_SSE2"
{
rtx tmp[7];
@@ -3574,7 +4293,7 @@
(match_operand:V2DF 2 "nonimmediate_operand")]
"TARGET_SSE2"
{
- rtx tmp0, tmp1;
+ rtx tmp0, tmp1, tmp2;
if (TARGET_AVX && !TARGET_PREFER_AVX128)
{
@@ -3588,13 +4307,14 @@
{
tmp0 = gen_reg_rtx (V4SImode);
tmp1 = gen_reg_rtx (V4SImode);
+ tmp2 = gen_reg_rtx (V2DImode);
emit_insn (gen_sse2_cvtpd2dq (tmp0, operands[1]));
emit_insn (gen_sse2_cvtpd2dq (tmp1, operands[2]));
- emit_insn
- (gen_vec_interleave_lowv2di (gen_lowpart (V2DImode, operands[0]),
- gen_lowpart (V2DImode, tmp0),
- gen_lowpart (V2DImode, tmp1)));
+ emit_insn (gen_vec_interleave_lowv2di (tmp2,
+ gen_lowpart (V2DImode, tmp0),
+ gen_lowpart (V2DImode, tmp1)));
+ emit_move_insn (operands[0], gen_lowpart (V4SImode, tmp2));
}
DONE;
})
@@ -3695,6 +4415,26 @@
(set_attr "prefix" "orig,vex,orig,vex,maybe_vex")
(set_attr "mode" "V4SF,V4SF,V2SF,V2SF,V2SF")])
+(define_insn "avx512f_unpckhps512"
+ [(set (match_operand:V16SF 0 "register_operand" "=v")
+ (vec_select:V16SF
+ (vec_concat:V32SF
+ (match_operand:V16SF 1 "register_operand" "v")
+ (match_operand:V16SF 2 "nonimmediate_operand" "vm"))
+ (parallel [(const_int 2) (const_int 18)
+ (const_int 3) (const_int 19)
+ (const_int 6) (const_int 22)
+ (const_int 7) (const_int 23)
+ (const_int 10) (const_int 26)
+ (const_int 11) (const_int 27)
+ (const_int 14) (const_int 30)
+ (const_int 15) (const_int 31)])))]
+ "TARGET_AVX512F"
+ "vunpckhps\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "V16SF")])
+
;; Recall that the 256-bit unpck insns only shuffle within their lanes.
(define_insn "avx_unpckhps256"
[(set (match_operand:V8SF 0 "register_operand" "=x")
@@ -3763,6 +4503,26 @@
(set_attr "prefix" "orig,vex")
(set_attr "mode" "V4SF")])
+(define_insn "avx512f_unpcklps512"
+ [(set (match_operand:V16SF 0 "register_operand" "=v")
+ (vec_select:V16SF
+ (vec_concat:V32SF
+ (match_operand:V16SF 1 "register_operand" "v")
+ (match_operand:V16SF 2 "nonimmediate_operand" "vm"))
+ (parallel [(const_int 0) (const_int 16)
+ (const_int 1) (const_int 17)
+ (const_int 4) (const_int 20)
+ (const_int 5) (const_int 21)
+ (const_int 8) (const_int 24)
+ (const_int 9) (const_int 25)
+ (const_int 12) (const_int 28)
+ (const_int 13) (const_int 29)])))]
+ "TARGET_AVX512F"
+ "vunpcklps\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "V16SF")])
+
;; Recall that the 256-bit unpck insns only shuffle within their lanes.
(define_insn "avx_unpcklps256"
[(set (match_operand:V8SF 0 "register_operand" "=x")
@@ -3866,6 +4626,26 @@
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "V4SF")])
+(define_insn "avx512f_movshdup512"
+ [(set (match_operand:V16SF 0 "register_operand" "=v")
+ (vec_select:V16SF
+ (vec_concat:V32SF
+ (match_operand:V16SF 1 "nonimmediate_operand" "vm")
+ (match_dup 1))
+ (parallel [(const_int 1) (const_int 1)
+ (const_int 3) (const_int 3)
+ (const_int 5) (const_int 5)
+ (const_int 7) (const_int 7)
+ (const_int 9) (const_int 9)
+ (const_int 11) (const_int 11)
+ (const_int 13) (const_int 13)
+ (const_int 15) (const_int 15)])))]
+ "TARGET_AVX512F"
+ "vmovshdup\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sse")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "V16SF")])
+
(define_insn "avx_movsldup256"
[(set (match_operand:V8SF 0 "register_operand" "=x")
(vec_select:V8SF
@@ -3899,6 +4679,26 @@
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "V4SF")])
+(define_insn "avx512f_movsldup512"
+ [(set (match_operand:V16SF 0 "register_operand" "=v")
+ (vec_select:V16SF
+ (vec_concat:V32SF
+ (match_operand:V16SF 1 "nonimmediate_operand" "vm")
+ (match_dup 1))
+ (parallel [(const_int 0) (const_int 0)
+ (const_int 2) (const_int 2)
+ (const_int 4) (const_int 4)
+ (const_int 6) (const_int 6)
+ (const_int 8) (const_int 8)
+ (const_int 10) (const_int 10)
+ (const_int 12) (const_int 12)
+ (const_int 14) (const_int 14)])))]
+ "TARGET_AVX512F"
+ "vmovsldup\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sse")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "V16SF")])
+
(define_expand "avx_shufps256"
[(match_operand:V8SF 0 "register_operand")
(match_operand:V8SF 1 "register_operand")
@@ -4128,8 +4928,8 @@
(set_attr "mode" "SF")])
(define_insn "avx2_vec_dup<mode>"
- [(set (match_operand:VF1 0 "register_operand" "=x")
- (vec_duplicate:VF1
+ [(set (match_operand:VF1_128_256 0 "register_operand" "=x")
+ (vec_duplicate:VF1_128_256
(vec_select:SF
(match_operand:V4SF 1 "register_operand" "x")
(parallel [(const_int 0)]))))]
@@ -4428,6 +5228,86 @@
operands[1] = adjust_address (operands[1], SFmode, INTVAL (operands[2]) * 4);
})
+(define_insn "avx512f_vextract<shuffletype>32x4_1"
+ [(set (match_operand:<ssequartermode> 0 "nonimmediate_operand" "=vm")
+ (vec_select:<ssequartermode>
+ (match_operand:V16FI 1 "register_operand" "v")
+ (parallel [(match_operand 2 "const_0_to_15_operand")
+ (match_operand 3 "const_0_to_15_operand")
+ (match_operand 4 "const_0_to_15_operand")
+ (match_operand 5 "const_0_to_15_operand")])))]
+ "TARGET_AVX512F && (INTVAL (operands[2]) = INTVAL (operands[3]) - 1)
+ && (INTVAL (operands[3]) = INTVAL (operands[4]) - 1)
+ && (INTVAL (operands[4]) = INTVAL (operands[5]) - 1)"
+{
+ operands[2] = GEN_INT ((INTVAL (operands[2])) >> 2);
+ return "vextract<shuffletype>32x4\t{%2, %1, %0|%0, %1, %2}";
+}
+ [(set_attr "type" "sselog")
+ (set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
+ (set (attr "memory")
+ (if_then_else (match_test "MEM_P (operands[0])")
+ (const_string "store")
+ (const_string "none")))
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<sseinsnmode>")])
+
+(define_split
+ [(set (match_operand:<ssehalfvecmode> 0 "nonimmediate_operand")
+ (vec_select:<ssehalfvecmode>
+ (match_operand:V8FI 1 "nonimmediate_operand")
+ (parallel [(const_int 0) (const_int 1)
+ (const_int 2) (const_int 3)])))]
+ "TARGET_AVX512F && !(MEM_P (operands[0]) && MEM_P (operands[1]))
+ && reload_completed"
+ [(const_int 0)]
+{
+ rtx op1 = operands[1];
+ if (REG_P (op1))
+ op1 = gen_rtx_REG (<ssehalfvecmode>mode, REGNO (op1));
+ else
+ op1 = gen_lowpart (<ssehalfvecmode>mode, op1);
+ emit_move_insn (operands[0], op1);
+ DONE;
+})
+
+(define_insn "vec_extract_lo_<mode>"
+ [(set (match_operand:<ssehalfvecmode> 0 "nonimmediate_operand" "=vm")
+ (vec_select:<ssehalfvecmode>
+ (match_operand:V8FI 1 "nonimmediate_operand" "vm")
+ (parallel [(const_int 0) (const_int 1)
+ (const_int 2) (const_int 3)])))]
+ "TARGET_AVX512F && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+ "#"
+ [(set_attr "type" "sselog")
+ (set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
+ (set (attr "memory")
+ (if_then_else (match_test "MEM_P (operands[0])")
+ (const_string "store")
+ (const_string "none")))
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<sseinsnmode>")])
+
+(define_insn "vec_extract_hi_<mode>"
+ [(set (match_operand:<ssehalfvecmode> 0 "nonimmediate_operand" "=vm")
+ (vec_select:<ssehalfvecmode>
+ (match_operand:V8FI 1 "register_operand" "v")
+ (parallel [(const_int 4) (const_int 5)
+ (const_int 6) (const_int 7)])))]
+ "TARGET_AVX512F"
+ "vextract<shuffletype>64x4\t{$0x1, %1, %0|%0, %1, 0x1}"
+ [(set_attr "type" "sselog")
+ (set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
+ (set (attr "memory")
+ (if_then_else (match_test "MEM_P (operands[0])")
+ (const_string "store")
+ (const_string "none")))
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<sseinsnmode>")])
+
(define_expand "avx_vextractf128<mode>"
[(match_operand:<ssehalfvecmode> 0 "nonimmediate_operand")
(match_operand:V_256 1 "register_operand")
@@ -4453,6 +5333,45 @@
})
(define_insn_and_split "vec_extract_lo_<mode>"
+ [(set (match_operand:<ssehalfvecmode> 0 "nonimmediate_operand" "=v,m")
+ (vec_select:<ssehalfvecmode>
+ (match_operand:V16FI 1 "nonimmediate_operand" "vm,v")
+ (parallel [(const_int 0) (const_int 1)
+ (const_int 2) (const_int 3)
+ (const_int 4) (const_int 5)
+ (const_int 6) (const_int 7)])))]
+ "TARGET_AVX512F && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+{
+ rtx op1 = operands[1];
+ if (REG_P (op1))
+ op1 = gen_rtx_REG (<ssehalfvecmode>mode, REGNO (op1));
+ else
+ op1 = gen_lowpart (<ssehalfvecmode>mode, op1);
+ emit_move_insn (operands[0], op1);
+ DONE;
+})
+
+(define_insn "vec_extract_hi_<mode>"
+ [(set (match_operand:<ssehalfvecmode> 0 "nonimmediate_operand" "=v,m")
+ (vec_select:<ssehalfvecmode>
+ (match_operand:V16FI 1 "nonimmediate_operand" "v,v")
+ (parallel [(const_int 8) (const_int 9)
+ (const_int 10) (const_int 11)
+ (const_int 12) (const_int 13)
+ (const_int 14) (const_int 15)])))]
+ "TARGET_AVX512F"
+ "vextracti64x4\t{$0x1, %1, %0|%0, %1, 0x1}"
+ [(set_attr "type" "sselog")
+ (set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
+ (set_attr "memory" "none,store")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "XI")])
+
+(define_insn_and_split "vec_extract_lo_<mode>"
[(set (match_operand:<ssehalfvecmode> 0 "nonimmediate_operand" "=x,m")
(vec_select:<ssehalfvecmode>
(match_operand:VI8F_256 1 "nonimmediate_operand" "xm,x")
@@ -4514,6 +5433,50 @@
(set_attr "prefix" "vex")
(set_attr "mode" "<sseinsnmode>")])
+(define_insn_and_split "vec_extract_lo_v32hi"
+ [(set (match_operand:V16HI 0 "nonimmediate_operand" "=v,m")
+ (vec_select:V16HI
+ (match_operand:V32HI 1 "nonimmediate_operand" "vm,v")
+ (parallel [(const_int 0) (const_int 1)
+ (const_int 2) (const_int 3)
+ (const_int 4) (const_int 5)
+ (const_int 6) (const_int 7)
+ (const_int 8) (const_int 9)
+ (const_int 10) (const_int 11)
+ (const_int 12) (const_int 13)
+ (const_int 14) (const_int 15)])))]
+ "TARGET_AVX512F && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 0) (match_dup 1))]
+{
+ if (REG_P (operands[1]))
+ operands[1] = gen_rtx_REG (V16HImode, REGNO (operands[1]));
+ else
+ operands[1] = adjust_address (operands[1], V16HImode, 0);
+})
+
+(define_insn "vec_extract_hi_v32hi"
+ [(set (match_operand:V16HI 0 "nonimmediate_operand" "=v,m")
+ (vec_select:V16HI
+ (match_operand:V32HI 1 "nonimmediate_operand" "v,v")
+ (parallel [(const_int 16) (const_int 17)
+ (const_int 18) (const_int 19)
+ (const_int 20) (const_int 21)
+ (const_int 22) (const_int 23)
+ (const_int 24) (const_int 25)
+ (const_int 26) (const_int 27)
+ (const_int 28) (const_int 29)
+ (const_int 30) (const_int 31)])))]
+ "TARGET_AVX512F"
+ "vextracti64x4\t{$0x1, %1, %0|%0, %1, 0x1}"
+ [(set_attr "type" "sselog")
+ (set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
+ (set_attr "memory" "none,store")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "XI")])
+
(define_insn_and_split "vec_extract_lo_v16hi"
[(set (match_operand:V8HI 0 "nonimmediate_operand" "=x,m")
(vec_select:V8HI
@@ -4550,6 +5513,66 @@
(set_attr "prefix" "vex")
(set_attr "mode" "OI")])
+(define_insn_and_split "vec_extract_lo_v64qi"
+ [(set (match_operand:V32QI 0 "nonimmediate_operand" "=v,m")
+ (vec_select:V32QI
+ (match_operand:V64QI 1 "nonimmediate_operand" "vm,v")
+ (parallel [(const_int 0) (const_int 1)
+ (const_int 2) (const_int 3)
+ (const_int 4) (const_int 5)
+ (const_int 6) (const_int 7)
+ (const_int 8) (const_int 9)
+ (const_int 10) (const_int 11)
+ (const_int 12) (const_int 13)
+ (const_int 14) (const_int 15)
+ (const_int 16) (const_int 17)
+ (const_int 18) (const_int 19)
+ (const_int 20) (const_int 21)
+ (const_int 22) (const_int 23)
+ (const_int 24) (const_int 25)
+ (const_int 26) (const_int 27)
+ (const_int 28) (const_int 29)
+ (const_int 30) (const_int 31)])))]
+ "TARGET_AVX512F && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 0) (match_dup 1))]
+{
+ if (REG_P (operands[1]))
+ operands[1] = gen_rtx_REG (V32QImode, REGNO (operands[1]));
+ else
+ operands[1] = adjust_address (operands[1], V32QImode, 0);
+})
+
+(define_insn "vec_extract_hi_v64qi"
+ [(set (match_operand:V32QI 0 "nonimmediate_operand" "=v,m")
+ (vec_select:V32QI
+ (match_operand:V64QI 1 "nonimmediate_operand" "v,v")
+ (parallel [(const_int 32) (const_int 33)
+ (const_int 34) (const_int 35)
+ (const_int 36) (const_int 37)
+ (const_int 38) (const_int 39)
+ (const_int 40) (const_int 41)
+ (const_int 42) (const_int 43)
+ (const_int 44) (const_int 45)
+ (const_int 46) (const_int 47)
+ (const_int 48) (const_int 49)
+ (const_int 50) (const_int 51)
+ (const_int 52) (const_int 53)
+ (const_int 54) (const_int 55)
+ (const_int 56) (const_int 57)
+ (const_int 58) (const_int 59)
+ (const_int 60) (const_int 61)
+ (const_int 62) (const_int 63)])))]
+ "TARGET_AVX512F"
+ "vextracti64x4\t{$0x1, %1, %0|%0, %1, 0x1}"
+ [(set_attr "type" "sselog")
+ (set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
+ (set_attr "memory" "none,store")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "XI")])
+
(define_insn_and_split "vec_extract_lo_v32qi"
[(set (match_operand:V16QI 0 "nonimmediate_operand" "=x,m")
(vec_select:V16QI
@@ -4598,10 +5621,10 @@
(define_mode_iterator VEC_EXTRACT_MODE
[(V32QI "TARGET_AVX") V16QI
(V16HI "TARGET_AVX") V8HI
- (V8SI "TARGET_AVX") V4SI
- (V4DI "TARGET_AVX") V2DI
- (V8SF "TARGET_AVX") V4SF
- (V4DF "TARGET_AVX") V2DF])
+ (V16SI "TARGET_AVX512F") (V8SI "TARGET_AVX") V4SI
+ (V8DI "TARGET_AVX512F") (V4DI "TARGET_AVX") V2DI
+ (V16SF "TARGET_AVX512F") (V8SF "TARGET_AVX") V4SF
+ (V8DF "TARGET_AVX512F") (V4DF "TARGET_AVX") V2DF])
(define_expand "vec_extract<mode>"
[(match_operand:<ssescalarmode> 0 "register_operand")
@@ -4620,6 +5643,22 @@
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(define_insn "avx512f_unpckhpd512"
+ [(set (match_operand:V8DF 0 "register_operand" "=v")
+ (vec_select:V8DF
+ (vec_concat:V16DF
+ (match_operand:V8DF 1 "nonimmediate_operand" "v")
+ (match_operand:V8DF 2 "nonimmediate_operand" "vm"))
+ (parallel [(const_int 1) (const_int 9)
+ (const_int 3) (const_int 11)
+ (const_int 5) (const_int 13)
+ (const_int 7) (const_int 15)])))]
+ "TARGET_AVX512F"
+ "vunpckhpd\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "V8DF")])
+
;; Recall that the 256-bit unpck insns only shuffle within their lanes.
(define_insn "avx_unpckhpd256"
[(set (match_operand:V4DF 0 "register_operand" "=x")
@@ -4700,6 +5739,48 @@
(set_attr "prefix" "orig,vex,maybe_vex,orig,vex,maybe_vex")
(set_attr "mode" "V2DF,V2DF,DF,V1DF,V1DF,V1DF")])
+(define_expand "avx512f_movddup512"
+ [(set (match_operand:V8DF 0 "register_operand")
+ (vec_select:V8DF
+ (vec_concat:V16DF
+ (match_operand:V8DF 1 "nonimmediate_operand")
+ (match_dup 1))
+ (parallel [(const_int 0) (const_int 8)
+ (const_int 2) (const_int 10)
+ (const_int 4) (const_int 12)
+ (const_int 6) (const_int 14)])))]
+ "TARGET_AVX512F")
+
+(define_expand "avx512f_unpcklpd512"
+ [(set (match_operand:V8DF 0 "register_operand")
+ (vec_select:V8DF
+ (vec_concat:V16DF
+ (match_operand:V8DF 1 "register_operand")
+ (match_operand:V8DF 2 "nonimmediate_operand"))
+ (parallel [(const_int 0) (const_int 8)
+ (const_int 2) (const_int 10)
+ (const_int 4) (const_int 12)
+ (const_int 6) (const_int 14)])))]
+ "TARGET_AVX512F")
+
+(define_insn "*avx512f_unpcklpd512"
+ [(set (match_operand:V8DF 0 "register_operand" "=v,v")
+ (vec_select:V8DF
+ (vec_concat:V16DF
+ (match_operand:V8DF 1 "nonimmediate_operand" "vm, v")
+ (match_operand:V8DF 2 "nonimmediate_operand" "1 ,vm"))
+ (parallel [(const_int 0) (const_int 8)
+ (const_int 2) (const_int 10)
+ (const_int 4) (const_int 12)
+ (const_int 6) (const_int 14)])))]
+ "TARGET_AVX512F"
+ "@
+ vmovddup\t{%1, %0|%0, %1}
+ vunpcklpd\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "V8DF")])
+
;; Recall that the 256-bit unpck insns only shuffle within their lanes.
(define_expand "avx_movddup256"
[(set (match_operand:V4DF 0 "register_operand")
@@ -4832,6 +5913,218 @@
operands[1] = adjust_address (operands[1], DFmode, INTVAL (operands[2]) * 8);
})
+(define_insn "avx512f_vmscalef<mode>"
+ [(set (match_operand:VF_128 0 "register_operand" "=v")
+ (vec_merge:VF_128
+ (unspec:VF_128 [(match_operand:VF_128 1 "register_operand" "v")
+ (match_operand:VF_128 2 "nonimmediate_operand" "vm")]
+ UNSPEC_SCALEF)
+ (match_dup 1)
+ (const_int 1)))]
+ "TARGET_AVX512F"
+ "%vscalef<ssescalarmodesuffix>\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "prefix" "evex")
+ (set_attr "mode" "<ssescalarmode>")])
+
+(define_insn "avx512f_scalef<mode>"
+ [(set (match_operand:VF_512 0 "register_operand" "=v")
+ (unspec:VF_512 [(match_operand:VF_512 1 "register_operand" "v")
+ (match_operand:VF_512 2 "nonimmediate_operand" "vm")]
+ UNSPEC_SCALEF))]
+ "TARGET_AVX512F"
+ "%vscalef<ssemodesuffix>\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "prefix" "evex")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "avx512f_vternlog<mode>"
+ [(set (match_operand:VI48_512 0 "register_operand" "=v")
+ (unspec:VI48_512
+ [(match_operand:VI48_512 1 "register_operand" "0")
+ (match_operand:VI48_512 2 "register_operand" "v")
+ (match_operand:VI48_512 3 "nonimmediate_operand" "vm")
+ (match_operand:SI 4 "const_0_to_255_operand")]
+ UNSPEC_VTERNLOG))]
+ "TARGET_AVX512F"
+ "vpternlog<ssemodesuffix>\t{%4, %3, %2, %0|%0, %2, %3, %4}"
+ [(set_attr "type" "sselog")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<sseinsnmode>")])
+
+(define_insn "avx512f_getexp<mode>"
+ [(set (match_operand:VF_512 0 "register_operand" "=v")
+ (unspec:VF_512 [(match_operand:VF_512 1 "nonimmediate_operand" "vm")]
+ UNSPEC_GETEXP))]
+ "TARGET_AVX512F"
+ "vgetexp<ssemodesuffix>\t{%1, %0|%0, %1}";
+ [(set_attr "prefix" "evex")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "avx512f_sgetexp<mode>"
+ [(set (match_operand:VF_128 0 "register_operand" "=v")
+ (vec_merge:VF_128
+ (unspec:VF_128 [(match_operand:VF_128 1 "register_operand" "v")
+ (match_operand:VF_128 2 "nonimmediate_operand" "vm")]
+ UNSPEC_GETEXP)
+ (match_dup 1)
+ (const_int 1)))]
+ "TARGET_AVX512F"
+ "vgetexp<ssescalarmodesuffix>\t{%2, %1, %0|%0, %1, %2}";
+ [(set_attr "prefix" "evex")
+ (set_attr "mode" "<ssescalarmode>")])
+
+(define_insn "avx512f_align<mode>"
+ [(set (match_operand:VI48_512 0 "register_operand" "=v")
+ (unspec:VI48_512 [(match_operand:VI48_512 1 "register_operand" "v")
+ (match_operand:VI48_512 2 "nonimmediate_operand" "vm")
+ (match_operand:SI 3 "const_0_to_255_operand")]
+ UNSPEC_ALIGN))]
+ "TARGET_AVX512F"
+ "valign<ssemodesuffix>\t{%3, %2, %1, %0|%0, %1, %2, %3}";
+ [(set_attr "prefix" "evex")
+ (set_attr "mode" "<sseinsnmode>")])
+
+(define_insn "avx512f_fixupimm<mode>"
+ [(set (match_operand:VF_512 0 "register_operand" "=v")
+ (unspec:VF_512
+ [(match_operand:VF_512 1 "register_operand" "0")
+ (match_operand:VF_512 2 "register_operand" "v")
+ (match_operand:<sseintvecmode> 3 "nonimmediate_operand" "vm")
+ (match_operand:SI 4 "const_0_to_255_operand")]
+ UNSPEC_FIXUPIMM))]
+ "TARGET_AVX512F"
+ "vfixupimm<ssemodesuffix>\t{%4, %3, %2, %0|%0, %2, %3, %4}";
+ [(set_attr "prefix" "evex")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "avx512f_sfixupimm<mode>"
+ [(set (match_operand:VF_128 0 "register_operand" "=v")
+ (vec_merge:VF_128
+ (unspec:VF_128
+ [(match_operand:VF_128 1 "register_operand" "0")
+ (match_operand:VF_128 2 "register_operand" "v")
+ (match_operand:<sseintvecmode> 3 "nonimmediate_operand" "vm")
+ (match_operand:SI 4 "const_0_to_255_operand")]
+ UNSPEC_FIXUPIMM)
+ (match_dup 1)
+ (const_int 1)))]
+ "TARGET_AVX512F"
+ "vfixupimm<ssescalarmodesuffix>\t{%4, %3, %2, %0|%0, %2, %3, %4}";
+ [(set_attr "prefix" "evex")
+ (set_attr "mode" "<ssescalarmode>")])
+
+(define_insn "avx512f_rndscale<mode>"
+ [(set (match_operand:VF_512 0 "register_operand" "=v")
+ (unspec:VF_512
+ [(match_operand:VF_512 1 "nonimmediate_operand" "vm")
+ (match_operand:SI 2 "const_0_to_255_operand")]
+ UNSPEC_ROUND))]
+ "TARGET_AVX512F"
+ "vrndscale<ssemodesuffix>\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "length_immediate" "1")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "avx512f_rndscale<mode>"
+ [(set (match_operand:VF_128 0 "register_operand" "=v")
+ (vec_merge:VF_128
+ (unspec:VF_128
+ [(match_operand:VF_128 1 "register_operand" "v")
+ (match_operand:VF_128 2 "nonimmediate_operand" "vm")
+ (match_operand:SI 3 "const_0_to_255_operand")]
+ UNSPEC_ROUND)
+ (match_dup 1)
+ (const_int 1)))]
+ "TARGET_AVX512F"
+ "vrndscale<ssescalarmodesuffix>\t{%3, %2, %1, %0|%0, %1, %2, %3}"
+ [(set_attr "length_immediate" "1")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<MODE>")])
+
+;; One bit in mask selects 2 elements.
+(define_insn "avx512f_shufps512_1"
+ [(set (match_operand:V16SF 0 "register_operand" "=v")
+ (vec_select:V16SF
+ (vec_concat:V32SF
+ (match_operand:V16SF 1 "register_operand" "v")
+ (match_operand:V16SF 2 "nonimmediate_operand" "vm"))
+ (parallel [(match_operand 3 "const_0_to_3_operand")
+ (match_operand 4 "const_0_to_3_operand")
+ (match_operand 5 "const_16_to_19_operand")
+ (match_operand 6 "const_16_to_19_operand")
+ (match_operand 7 "const_4_to_7_operand")
+ (match_operand 8 "const_4_to_7_operand")
+ (match_operand 9 "const_20_to_23_operand")
+ (match_operand 10 "const_20_to_23_operand")
+ (match_operand 11 "const_8_to_11_operand")
+ (match_operand 12 "const_8_to_11_operand")
+ (match_operand 13 "const_24_to_27_operand")
+ (match_operand 14 "const_24_to_27_operand")
+ (match_operand 15 "const_12_to_15_operand")
+ (match_operand 16 "const_12_to_15_operand")
+ (match_operand 17 "const_28_to_31_operand")
+ (match_operand 18 "const_28_to_31_operand")])))]
+ "TARGET_AVX512F
+ && (INTVAL (operands[3]) == (INTVAL (operands[7]) - 4)
+ && INTVAL (operands[4]) == (INTVAL (operands[8]) - 4)
+ && INTVAL (operands[5]) == (INTVAL (operands[9]) - 4)
+ && INTVAL (operands[6]) == (INTVAL (operands[10]) - 4)
+ && INTVAL (operands[3]) == (INTVAL (operands[11]) - 8)
+ && INTVAL (operands[4]) == (INTVAL (operands[12]) - 8)
+ && INTVAL (operands[5]) == (INTVAL (operands[13]) - 8)
+ && INTVAL (operands[6]) == (INTVAL (operands[14]) - 8)
+ && INTVAL (operands[3]) == (INTVAL (operands[15]) - 12)
+ && INTVAL (operands[4]) == (INTVAL (operands[16]) - 12)
+ && INTVAL (operands[5]) == (INTVAL (operands[17]) - 12)
+ && INTVAL (operands[6]) == (INTVAL (operands[18]) - 12))"
+{
+ int mask;
+ mask = INTVAL (operands[3]);
+ mask |= INTVAL (operands[4]) << 2;
+ mask |= (INTVAL (operands[5]) - 16) << 4;
+ mask |= (INTVAL (operands[6]) - 16) << 6;
+ operands[3] = GEN_INT (mask);
+
+ return "vshufps\t{%3, %2, %1, %0|%0, %1, %2, %3}";
+}
+ [(set_attr "type" "sselog")
+ (set_attr "length_immediate" "1")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "V16SF")])
+
+(define_insn "avx512f_shufpd512_1"
+ [(set (match_operand:V8DF 0 "register_operand" "=v")
+ (vec_select:V8DF
+ (vec_concat:V16DF
+ (match_operand:V8DF 1 "register_operand" "v")
+ (match_operand:V8DF 2 "nonimmediate_operand" "vm"))
+ (parallel [(match_operand 3 "const_0_to_1_operand")
+ (match_operand 4 "const_8_to_9_operand")
+ (match_operand 5 "const_2_to_3_operand")
+ (match_operand 6 "const_10_to_11_operand")
+ (match_operand 7 "const_4_to_5_operand")
+ (match_operand 8 "const_12_to_13_operand")
+ (match_operand 9 "const_6_to_7_operand")
+ (match_operand 10 "const_14_to_15_operand")])))]
+ "TARGET_AVX512F"
+{
+ int mask;
+ mask = INTVAL (operands[3]);
+ mask |= (INTVAL (operands[4]) - 8) << 1;
+ mask |= (INTVAL (operands[5]) - 2) << 2;
+ mask |= (INTVAL (operands[6]) - 10) << 3;
+ mask |= (INTVAL (operands[7]) - 4) << 4;
+ mask |= (INTVAL (operands[8]) - 12) << 5;
+ mask |= (INTVAL (operands[9]) - 6) << 6;
+ mask |= (INTVAL (operands[10]) - 14) << 7;
+ operands[3] = GEN_INT (mask);
+
+ return "vshufpd\t{%3, %2, %1, %0|%0, %1, %2, %3}";
+}
+ [(set_attr "type" "sselog")
+ (set_attr "length_immediate" "1")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "V8DF")])
+
(define_expand "avx_shufpd256"
[(match_operand:V4DF 0 "register_operand")
(match_operand:V4DF 1 "register_operand")
@@ -4905,6 +6198,22 @@
(set_attr "prefix" "vex")
(set_attr "mode" "OI")])
+(define_insn "avx512f_interleave_highv8di"
+ [(set (match_operand:V8DI 0 "register_operand" "=v")
+ (vec_select:V8DI
+ (vec_concat:V16DI
+ (match_operand:V8DI 1 "register_operand" "v")
+ (match_operand:V8DI 2 "nonimmediate_operand" "vm"))
+ (parallel [(const_int 1) (const_int 9)
+ (const_int 3) (const_int 11)
+ (const_int 5) (const_int 13)
+ (const_int 7) (const_int 15)])))]
+ "TARGET_AVX512F"
+ "vpunpckhqdq\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "XI")])
+
(define_insn "vec_interleave_highv2di"
[(set (match_operand:V2DI 0 "register_operand" "=x,x")
(vec_select:V2DI
@@ -4939,6 +6248,22 @@
(set_attr "prefix" "vex")
(set_attr "mode" "OI")])
+(define_insn "avx512f_interleave_lowv8di"
+ [(set (match_operand:V8DI 0 "register_operand" "=v")
+ (vec_select:V8DI
+ (vec_concat:V16DI
+ (match_operand:V8DI 1 "register_operand" "v")
+ (match_operand:V8DI 2 "nonimmediate_operand" "vm"))
+ (parallel [(const_int 0) (const_int 8)
+ (const_int 2) (const_int 10)
+ (const_int 4) (const_int 12)
+ (const_int 6) (const_int 14)])))]
+ "TARGET_AVX512F"
+ "vpunpcklqdq\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "XI")])
+
(define_insn "vec_interleave_lowv2di"
[(set (match_operand:V2DI 0 "register_operand" "=x,x")
(vec_select:V2DI
@@ -5282,6 +6607,64 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
+;; Parallel integer down-conversion operations
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define_mode_iterator PMOV_DST_MODE [V16QI V16HI V8SI V8HI])
+(define_mode_attr pmov_src_mode
+ [(V16QI "V16SI") (V16HI "V16SI") (V8SI "V8DI") (V8HI "V8DI")])
+(define_mode_attr pmov_src_lower
+ [(V16QI "v16si") (V16HI "v16si") (V8SI "v8di") (V8HI "v8di")])
+(define_mode_attr pmov_suff
+ [(V16QI "db") (V16HI "dw") (V8SI "qd") (V8HI "qw")])
+
+(define_insn "*avx512f_<code><pmov_src_lower><mode>2"
+ [(set (match_operand:PMOV_DST_MODE 0 "nonimmediate_operand" "=v,m")
+ (any_truncate:PMOV_DST_MODE
+ (match_operand:<pmov_src_mode> 1 "register_operand" "v,v")))]
+ "TARGET_AVX512F"
+ "vpmov<trunsuffix><pmov_suff>\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssemov")
+ (set_attr "memory" "none,store")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<sseinsnmode>")])
+
+(define_insn "*avx512f_<code>v8div16qi2"
+ [(set (match_operand:V16QI 0 "register_operand" "=v")
+ (vec_concat:V16QI
+ (any_truncate:V8QI
+ (match_operand:V8DI 1 "register_operand" "v"))
+ (const_vector:V8QI [(const_int 0) (const_int 0)
+ (const_int 0) (const_int 0)
+ (const_int 0) (const_int 0)
+ (const_int 0) (const_int 0)])))]
+ "TARGET_AVX512F"
+ "vpmov<trunsuffix>qb\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssemov")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "TI")])
+
+(define_insn "*avx512f_<code>v8div16qi2_store"
+ [(set (match_operand:V16QI 0 "memory_operand" "=m")
+ (vec_concat:V16QI
+ (any_truncate:V8QI
+ (match_operand:V8DI 1 "register_operand" "v"))
+ (vec_select:V8QI
+ (match_dup 0)
+ (parallel [(const_int 8) (const_int 9)
+ (const_int 10) (const_int 11)
+ (const_int 12) (const_int 13)
+ (const_int 14) (const_int 15)]))))]
+ "TARGET_AVX512F"
+ "vpmov<trunsuffix>qb\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssemov")
+ (set_attr "memory" "store")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "TI")])
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
;; Parallel integral arithmetic
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -5404,6 +6787,51 @@
(set_attr "prefix" "orig,vex")
(set_attr "mode" "<sseinsnmode>")])
+(define_expand "vec_widen_umult_even_v16si"
+ [(set (match_operand:V8DI 0 "register_operand")
+ (mult:V8DI
+ (zero_extend:V8DI
+ (vec_select:V8SI
+ (match_operand:V16SI 1 "nonimmediate_operand")
+ (parallel [(const_int 0) (const_int 2)
+ (const_int 4) (const_int 6)
+ (const_int 8) (const_int 10)
+ (const_int 12) (const_int 14)])))
+ (zero_extend:V8DI
+ (vec_select:V8SI
+ (match_operand:V16SI 2 "nonimmediate_operand")
+ (parallel [(const_int 0) (const_int 2)
+ (const_int 4) (const_int 6)
+ (const_int 8) (const_int 10)
+ (const_int 12) (const_int 14)])))))]
+ "TARGET_AVX512F"
+ "ix86_fixup_binary_operands_no_copy (MULT, V16SImode, operands);")
+
+(define_insn "*vec_widen_umult_even_v16si"
+ [(set (match_operand:V8DI 0 "register_operand" "=v")
+ (mult:V8DI
+ (zero_extend:V8DI
+ (vec_select:V8SI
+ (match_operand:V16SI 1 "nonimmediate_operand" "%v")
+ (parallel [(const_int 0) (const_int 2)
+ (const_int 4) (const_int 6)
+ (const_int 8) (const_int 10)
+ (const_int 12) (const_int 14)])))
+ (zero_extend:V8DI
+ (vec_select:V8SI
+ (match_operand:V16SI 2 "nonimmediate_operand" "vm")
+ (parallel [(const_int 0) (const_int 2)
+ (const_int 4) (const_int 6)
+ (const_int 8) (const_int 10)
+ (const_int 12) (const_int 14)])))))]
+ "TARGET_AVX512F && ix86_binary_operator_ok (MULT, V16SImode, operands)"
+ "vpmuludq\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "isa" "avx512f")
+ (set_attr "type" "sseimul")
+ (set_attr "prefix_extra" "1")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "XI")])
+
(define_expand "vec_widen_umult_even_v8si"
[(set (match_operand:V4DI 0 "register_operand")
(mult:V4DI
@@ -5474,6 +6902,51 @@
(set_attr "prefix" "orig,vex")
(set_attr "mode" "TI")])
+(define_expand "vec_widen_smult_even_v16si"
+ [(set (match_operand:V8DI 0 "register_operand")
+ (mult:V8DI
+ (sign_extend:V8DI
+ (vec_select:V8SI
+ (match_operand:V16SI 1 "nonimmediate_operand")
+ (parallel [(const_int 0) (const_int 2)
+ (const_int 4) (const_int 6)
+ (const_int 8) (const_int 10)
+ (const_int 12) (const_int 14)])))
+ (sign_extend:V8DI
+ (vec_select:V8SI
+ (match_operand:V16SI 2 "nonimmediate_operand")
+ (parallel [(const_int 0) (const_int 2)
+ (const_int 4) (const_int 6)
+ (const_int 8) (const_int 10)
+ (const_int 12) (const_int 14)])))))]
+ "TARGET_AVX512F"
+ "ix86_fixup_binary_operands_no_copy (MULT, V16SImode, operands);")
+
+(define_insn "*vec_widen_smult_even_v16si"
+ [(set (match_operand:V8DI 0 "register_operand" "=v")
+ (mult:V8DI
+ (sign_extend:V8DI
+ (vec_select:V8SI
+ (match_operand:V16SI 1 "nonimmediate_operand" "%v")
+ (parallel [(const_int 0) (const_int 2)
+ (const_int 4) (const_int 6)
+ (const_int 8) (const_int 10)
+ (const_int 12) (const_int 14)])))
+ (sign_extend:V8DI
+ (vec_select:V8SI
+ (match_operand:V16SI 2 "nonimmediate_operand" "vm")
+ (parallel [(const_int 0) (const_int 2)
+ (const_int 4) (const_int 6)
+ (const_int 8) (const_int 10)
+ (const_int 12) (const_int 14)])))))]
+ "TARGET_AVX512F && ix86_binary_operator_ok (MULT, V16SImode, operands)"
+ "vpmuldq\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "isa" "avx512f")
+ (set_attr "type" "sseimul")
+ (set_attr "prefix_extra" "1")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "XI")])
+
(define_expand "vec_widen_smult_even_v8si"
[(set (match_operand:V4DI 0 "register_operand")
(mult:V4DI
@@ -5505,8 +6978,7 @@
(const_int 4) (const_int 6)])))))]
"TARGET_AVX2 && ix86_binary_operator_ok (MULT, V8SImode, operands)"
"vpmuldq\t{%2, %1, %0|%0, %1, %2}"
- [(set_attr "isa" "avx")
- (set_attr "type" "sseimul")
+ [(set_attr "type" "sseimul")
(set_attr "prefix_extra" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "OI")])
@@ -5679,10 +7151,10 @@
(set_attr "mode" "TI")])
(define_expand "mul<mode>3"
- [(set (match_operand:VI4_AVX2 0 "register_operand")
- (mult:VI4_AVX2
- (match_operand:VI4_AVX2 1 "general_vector_operand")
- (match_operand:VI4_AVX2 2 "general_vector_operand")))]
+ [(set (match_operand:VI4_AVX512F 0 "register_operand")
+ (mult:VI4_AVX512F
+ (match_operand:VI4_AVX512F 1 "general_vector_operand")
+ (match_operand:VI4_AVX512F 2 "general_vector_operand")))]
"TARGET_SSE2"
{
if (TARGET_SSE4_1)
@@ -5701,10 +7173,10 @@
})
(define_insn "*<sse4_1_avx2>_mul<mode>3"
- [(set (match_operand:VI4_AVX2 0 "register_operand" "=x,v")
- (mult:VI4_AVX2
- (match_operand:VI4_AVX2 1 "nonimmediate_operand" "%0,v")
- (match_operand:VI4_AVX2 2 "nonimmediate_operand" "xm,vm")))]
+ [(set (match_operand:VI4_AVX512F 0 "register_operand" "=x,v")
+ (mult:VI4_AVX512F
+ (match_operand:VI4_AVX512F 1 "nonimmediate_operand" "%0,v")
+ (match_operand:VI4_AVX512F 2 "nonimmediate_operand" "xm,vm")))]
"TARGET_SSE4_1 && ix86_binary_operator_ok (MULT, <MODE>mode, operands)"
"@
pmulld\t{%2, %0|%0, %2}
@@ -5717,9 +7189,10 @@
(set_attr "mode" "<sseinsnmode>")])
(define_expand "mul<mode>3"
- [(set (match_operand:VI8_AVX2 0 "register_operand")
- (mult:VI8_AVX2 (match_operand:VI8_AVX2 1 "register_operand")
- (match_operand:VI8_AVX2 2 "register_operand")))]
+ [(set (match_operand:VI8_AVX2_AVX512F 0 "register_operand")
+ (mult:VI8_AVX2_AVX512F
+ (match_operand:VI8_AVX2_AVX512F 1 "register_operand")
+ (match_operand:VI8_AVX2_AVX512F 2 "register_operand")))]
"TARGET_SSE2"
{
ix86_expand_sse2_mulvxdi3 (operands[0], operands[1], operands[2]);
@@ -5766,8 +7239,8 @@
(define_expand "vec_widen_<s>mult_odd_<mode>"
[(match_operand:<sseunpackmode> 0 "register_operand")
(any_extend:<sseunpackmode>
- (match_operand:VI4_AVX2 1 "general_vector_operand"))
- (match_operand:VI4_AVX2 2 "general_vector_operand")]
+ (match_operand:VI4_AVX512F 1 "general_vector_operand"))
+ (match_operand:VI4_AVX512F 2 "general_vector_operand")]
"TARGET_SSE2"
{
ix86_expand_mul_widen_evenodd (operands[0], operands[1], operands[2],
@@ -5825,9 +7298,9 @@
(set_attr "mode" "<sseinsnmode>")])
(define_insn "<shift_insn><mode>3"
- [(set (match_operand:VI248_AVX2 0 "register_operand" "=x,v")
+ [(set (match_operand:VI248_AVX2 0 "register_operand" "=x,x")
(any_lshift:VI248_AVX2
- (match_operand:VI248_AVX2 1 "register_operand" "0,v")
+ (match_operand:VI248_AVX2 1 "register_operand" "0,x")
(match_operand:SI 2 "nonmemory_operand" "xN,xN")))]
"TARGET_SSE2"
"@
@@ -5843,15 +7316,33 @@
(set_attr "prefix" "orig,vex")
(set_attr "mode" "<sseinsnmode>")])
+(define_insn "<shift_insn><mode>3"
+ [(set (match_operand:VI48_512 0 "register_operand" "=v,v")
+ (any_lshift:VI48_512
+ (match_operand:VI48_512 1 "register_operand" "v,m")
+ (match_operand:SI 2 "nonmemory_operand" "vN,N")))]
+ "TARGET_AVX512F"
+ "vp<vshift><ssemodesuffix>\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "isa" "avx512f")
+ (set_attr "type" "sseishft")
+ (set (attr "length_immediate")
+ (if_then_else (match_operand 2 "const_int_operand")
+ (const_string "1")
+ (const_string "0")))
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<sseinsnmode>")])
+
(define_expand "vec_shl_<mode>"
- [(set (match_operand:VI_128 0 "register_operand")
+ [(set (match_dup 3)
(ashift:V1TI
(match_operand:VI_128 1 "register_operand")
- (match_operand:SI 2 "const_0_to_255_mul_8_operand")))]
+ (match_operand:SI 2 "const_0_to_255_mul_8_operand")))
+ (set (match_operand:VI_128 0 "register_operand") (match_dup 4))]
"TARGET_SSE2"
{
- operands[0] = gen_lowpart (V1TImode, operands[0]);
operands[1] = gen_lowpart (V1TImode, operands[1]);
+ operands[3] = gen_reg_rtx (V1TImode);
+ operands[4] = gen_lowpart (<MODE>mode, operands[3]);
})
(define_insn "<sse2_avx2>_ashl<mode>3"
@@ -5881,14 +7372,16 @@
(set_attr "mode" "<sseinsnmode>")])
(define_expand "vec_shr_<mode>"
- [(set (match_operand:VI_128 0 "register_operand")
+ [(set (match_dup 3)
(lshiftrt:V1TI
(match_operand:VI_128 1 "register_operand")
- (match_operand:SI 2 "const_0_to_255_mul_8_operand")))]
+ (match_operand:SI 2 "const_0_to_255_mul_8_operand")))
+ (set (match_operand:VI_128 0 "register_operand") (match_dup 4))]
"TARGET_SSE2"
{
- operands[0] = gen_lowpart (V1TImode, operands[0]);
operands[1] = gen_lowpart (V1TImode, operands[1]);
+ operands[3] = gen_reg_rtx (V1TImode);
+ operands[4] = gen_lowpart (<MODE>mode, operands[3]);
})
(define_insn "<sse2_avx2>_lshr<mode>3"
@@ -5918,25 +7411,44 @@
(set_attr "prefix" "orig,vex")
(set_attr "mode" "<sseinsnmode>")])
+(define_insn "avx512f_<rotate>v<mode>"
+ [(set (match_operand:VI48_512 0 "register_operand" "=v")
+ (any_rotate:VI48_512
+ (match_operand:VI48_512 1 "register_operand" "v")
+ (match_operand:VI48_512 2 "nonimmediate_operand" "vm")))]
+ "TARGET_AVX512F"
+ "vp<rotate>v<ssemodesuffix>\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "prefix" "evex")
+ (set_attr "mode" "<sseinsnmode>")])
+
+(define_insn "avx512f_<rotate><mode>"
+ [(set (match_operand:VI48_512 0 "register_operand" "=v")
+ (any_rotate:VI48_512
+ (match_operand:VI48_512 1 "nonimmediate_operand" "vm")
+ (match_operand:SI 2 "const_0_to_255_operand")))]
+ "TARGET_AVX512F"
+ "vp<rotate><ssemodesuffix>\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "prefix" "evex")
+ (set_attr "mode" "<sseinsnmode>")])
(define_expand "<code><mode>3"
- [(set (match_operand:VI124_256 0 "register_operand")
- (maxmin:VI124_256
- (match_operand:VI124_256 1 "nonimmediate_operand")
- (match_operand:VI124_256 2 "nonimmediate_operand")))]
+ [(set (match_operand:VI124_256_48_512 0 "register_operand")
+ (maxmin:VI124_256_48_512
+ (match_operand:VI124_256_48_512 1 "nonimmediate_operand")
+ (match_operand:VI124_256_48_512 2 "nonimmediate_operand")))]
"TARGET_AVX2"
"ix86_fixup_binary_operands_no_copy (<CODE>, <MODE>mode, operands);")
(define_insn "*avx2_<code><mode>3"
- [(set (match_operand:VI124_256 0 "register_operand" "=v")
- (maxmin:VI124_256
- (match_operand:VI124_256 1 "nonimmediate_operand" "%v")
- (match_operand:VI124_256 2 "nonimmediate_operand" "vm")))]
+ [(set (match_operand:VI124_256_48_512 0 "register_operand" "=v")
+ (maxmin:VI124_256_48_512
+ (match_operand:VI124_256_48_512 1 "nonimmediate_operand" "%v")
+ (match_operand:VI124_256_48_512 2 "nonimmediate_operand" "vm")))]
"TARGET_AVX2 && ix86_binary_operator_ok (<CODE>, <MODE>mode, operands)"
"vp<maxmin_int><ssemodesuffix>\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "sseiadd")
(set_attr "prefix_extra" "1")
- (set_attr "prefix" "vex")
+ (set_attr "prefix" "maybe_evex")
(set_attr "mode" "OI")])
(define_expand "<code><mode>3"
@@ -6151,6 +7663,28 @@
(set_attr "prefix" "vex")
(set_attr "mode" "OI")])
+(define_expand "avx512f_eq<mode>3"
+ [(set (match_operand:<avx512fmaskmode> 0 "register_operand")
+ (unspec:<avx512fmaskmode>
+ [(match_operand:VI48_512 1 "register_operand")
+ (match_operand:VI48_512 2 "nonimmediate_operand")]
+ UNSPEC_MASKED_EQ))]
+ "TARGET_AVX512F"
+ "ix86_fixup_binary_operands_no_copy (EQ, <MODE>mode, operands);")
+
+(define_insn "avx512f_eq<mode>3_1"
+ [(set (match_operand:<avx512fmaskmode> 0 "register_operand" "=k")
+ (unspec:<avx512fmaskmode>
+ [(match_operand:VI48_512 1 "register_operand" "%v")
+ (match_operand:VI48_512 2 "nonimmediate_operand" "vm")]
+ UNSPEC_MASKED_EQ))]
+ "TARGET_AVX512F && ix86_binary_operator_ok (EQ, <MODE>mode, operands)"
+ "vpcmpeq<ssemodesuffix>\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "ssecmp")
+ (set_attr "prefix_extra" "1")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<sseinsnmode>")])
+
(define_insn "*sse4_1_eqv2di3"
[(set (match_operand:V2DI 0 "register_operand" "=x,x")
(eq:V2DI
@@ -6225,6 +7759,18 @@
(set_attr "prefix" "vex")
(set_attr "mode" "OI")])
+(define_insn "avx512f_gt<mode>3"
+ [(set (match_operand:<avx512fmaskmode> 0 "register_operand" "=k")
+ (unspec:<avx512fmaskmode>
+ [(match_operand:VI48_512 1 "register_operand" "v")
+ (match_operand:VI48_512 2 "nonimmediate_operand" "vm")] UNSPEC_MASKED_GT))]
+ "TARGET_AVX512F"
+ "vpcmpgt<ssemodesuffix>\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "ssecmp")
+ (set_attr "prefix_extra" "1")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<sseinsnmode>")])
+
(define_insn "sse2_gt<mode>3"
[(set (match_operand:VI124_128 0 "register_operand" "=x,x")
(gt:VI124_128
@@ -6240,6 +7786,23 @@
(set_attr "prefix" "orig,vex")
(set_attr "mode" "TI")])
+(define_expand "vcond<V_512:mode><VI_512:mode>"
+ [(set (match_operand:V_512 0 "register_operand")
+ (if_then_else:V_512
+ (match_operator 3 ""
+ [(match_operand:VI_512 4 "nonimmediate_operand")
+ (match_operand:VI_512 5 "general_operand")])
+ (match_operand:V_512 1)
+ (match_operand:V_512 2)))]
+ "TARGET_AVX512F
+ && (GET_MODE_NUNITS (<V_512:MODE>mode)
+ == GET_MODE_NUNITS (<VI_512:MODE>mode))"
+{
+ bool ok = ix86_expand_int_vcond (operands);
+ gcc_assert (ok);
+ DONE;
+})
+
(define_expand "vcond<V_256:mode><VI_256:mode>"
[(set (match_operand:V_256 0 "register_operand")
(if_then_else:V_256
@@ -6289,6 +7852,23 @@
DONE;
})
+(define_expand "vcondu<V_512:mode><VI_512:mode>"
+ [(set (match_operand:V_512 0 "register_operand")
+ (if_then_else:V_512
+ (match_operator 3 ""
+ [(match_operand:VI_512 4 "nonimmediate_operand")
+ (match_operand:VI_512 5 "nonimmediate_operand")])
+ (match_operand:V_512 1 "general_operand")
+ (match_operand:V_512 2 "general_operand")))]
+ "TARGET_AVX512F
+ && (GET_MODE_NUNITS (<V_512:MODE>mode)
+ == GET_MODE_NUNITS (<VI_512:MODE>mode))"
+{
+ bool ok = ix86_expand_int_vcond (operands);
+ gcc_assert (ok);
+ DONE;
+})
+
(define_expand "vcondu<V_256:mode><VI_256:mode>"
[(set (match_operand:V_256 0 "register_operand")
(if_then_else:V_256
@@ -6342,7 +7922,9 @@
[V16QI V8HI V4SI V2DI V4SF V2DF
(V32QI "TARGET_AVX2") (V16HI "TARGET_AVX2")
(V8SI "TARGET_AVX2") (V4DI "TARGET_AVX2")
- (V8SF "TARGET_AVX2") (V4DF "TARGET_AVX2")])
+ (V8SF "TARGET_AVX2") (V4DF "TARGET_AVX2")
+ (V16SF "TARGET_AVX512F") (V8DF "TARGET_AVX512F")
+ (V16SI "TARGET_AVX512F") (V8DI "TARGET_AVX512F")])
(define_expand "vec_perm<mode>"
[(match_operand:VEC_PERM_AVX2 0 "register_operand")
@@ -6361,7 +7943,9 @@
(V16QI "TARGET_SSE2") (V8HI "TARGET_SSE2")
(V8SF "TARGET_AVX") (V4DF "TARGET_AVX")
(V8SI "TARGET_AVX") (V4DI "TARGET_AVX")
- (V32QI "TARGET_AVX2") (V16HI "TARGET_AVX2")])
+ (V32QI "TARGET_AVX2") (V16HI "TARGET_AVX2")
+ (V16SI "TARGET_AVX512F") (V8DI "TARGET_AVX512F")
+ (V16SF "TARGET_AVX512F") (V8DF "TARGET_AVX512F")])
(define_expand "vec_perm_const<mode>"
[(match_operand:VEC_PERM_CONST 0 "register_operand")
@@ -6411,12 +7995,18 @@
(match_operand:VI 2 "nonimmediate_operand" "xm,vm")))]
"TARGET_SSE"
{
- static char buf[32];
+ static char buf[64];
const char *ops;
const char *tmp;
switch (get_attr_mode (insn))
{
+ case MODE_XI:
+ gcc_assert (TARGET_AVX512F);
+
+ tmp = "pandn<ssemodesuffix>";
+ break;
+
case MODE_OI:
gcc_assert (TARGET_AVX2);
case MODE_TI:
@@ -6496,12 +8086,17 @@
"TARGET_SSE
&& ix86_binary_operator_ok (<CODE>, <MODE>mode, operands)"
{
- static char buf[32];
+ static char buf[64];
const char *ops;
const char *tmp;
switch (get_attr_mode (insn))
{
+ case MODE_XI:
+ gcc_assert (TARGET_AVX512F);
+ tmp = "p<logic><ssemodesuffix>";
+ break;
+
case MODE_OI:
gcc_assert (TARGET_AVX2);
case MODE_TI:
@@ -6510,6 +8105,8 @@
tmp = "p<logic>";
break;
+ case MODE_V16SF:
+ gcc_assert (TARGET_AVX512F);
case MODE_V8SF:
gcc_assert (TARGET_AVX);
case MODE_V4SF:
@@ -6562,6 +8159,28 @@
]
(const_string "<sseinsnmode>")))])
+(define_insn "avx512f_testm<mode>3"
+ [(set (match_operand:<avx512fmaskmode> 0 "register_operand" "=k")
+ (unspec:<avx512fmaskmode>
+ [(match_operand:VI48_512 1 "register_operand" "v")
+ (match_operand:VI48_512 2 "nonimmediate_operand" "vm")]
+ UNSPEC_TESTM))]
+ "TARGET_AVX512F"
+ "vptestm<ssemodesuffix>\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "prefix" "evex")
+ (set_attr "mode" "<sseinsnmode>")])
+
+(define_insn "avx512f_testnm<mode>3"
+ [(set (match_operand:<avx512fmaskmode> 0 "register_operand" "=k")
+ (unspec:<avx512fmaskmode>
+ [(match_operand:VI48_512 1 "register_operand" "v")
+ (match_operand:VI48_512 2 "nonimmediate_operand" "vm")]
+ UNSPEC_TESTNM))]
+ "TARGET_AVX512CD"
+ "%vptestnm<ssemodesuffix>\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "prefix" "evex")
+ (set_attr "mode" "<sseinsnmode>")])
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Parallel integral element swizzling
@@ -6570,8 +8189,8 @@
(define_expand "vec_pack_trunc_<mode>"
[(match_operand:<ssepackmode> 0 "register_operand")
- (match_operand:VI248_AVX2 1 "register_operand")
- (match_operand:VI248_AVX2 2 "register_operand")]
+ (match_operand:VI248_AVX2_8_AVX512F 1 "register_operand")
+ (match_operand:VI248_AVX2_8_AVX512F 2 "register_operand")]
"TARGET_SSE2"
{
rtx op1 = gen_lowpart (<ssepackmode>mode, operands[1]);
@@ -6831,6 +8450,27 @@
(set_attr "prefix" "vex")
(set_attr "mode" "OI")])
+(define_insn "avx512f_interleave_highv16si"
+ [(set (match_operand:V16SI 0 "register_operand" "=v")
+ (vec_select:V16SI
+ (vec_concat:V32SI
+ (match_operand:V16SI 1 "register_operand" "v")
+ (match_operand:V16SI 2 "nonimmediate_operand" "vm"))
+ (parallel [(const_int 2) (const_int 18)
+ (const_int 3) (const_int 19)
+ (const_int 6) (const_int 22)
+ (const_int 7) (const_int 23)
+ (const_int 10) (const_int 26)
+ (const_int 11) (const_int 27)
+ (const_int 14) (const_int 30)
+ (const_int 15) (const_int 31)])))]
+ "TARGET_AVX512F"
+ "vpunpckhdq\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "XI")])
+
+
(define_insn "vec_interleave_highv4si"
[(set (match_operand:V4SI 0 "register_operand" "=x,x")
(vec_select:V4SI
@@ -6865,6 +8505,26 @@
(set_attr "prefix" "vex")
(set_attr "mode" "OI")])
+(define_insn "avx512f_interleave_lowv16si"
+ [(set (match_operand:V16SI 0 "register_operand" "=v")
+ (vec_select:V16SI
+ (vec_concat:V32SI
+ (match_operand:V16SI 1 "register_operand" "v")
+ (match_operand:V16SI 2 "nonimmediate_operand" "vm"))
+ (parallel [(const_int 0) (const_int 16)
+ (const_int 1) (const_int 17)
+ (const_int 4) (const_int 20)
+ (const_int 5) (const_int 21)
+ (const_int 8) (const_int 24)
+ (const_int 9) (const_int 25)
+ (const_int 12) (const_int 28)
+ (const_int 13) (const_int 29)])))]
+ "TARGET_AVX512F"
+ "vpunpckldq\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "XI")])
+
(define_insn "vec_interleave_lowv4si"
[(set (match_operand:V4SI 0 "register_operand" "=x,x")
(vec_select:V4SI
@@ -6891,12 +8551,13 @@
{
rtx t1 = gen_reg_rtx (<MODE>mode);
rtx t2 = gen_reg_rtx (<MODE>mode);
+ rtx t3 = gen_reg_rtx (V4DImode);
emit_insn (gen_avx2_interleave_low<mode> (t1, operands[1], operands[2]));
emit_insn (gen_avx2_interleave_high<mode> (t2, operands[1], operands[2]));
- emit_insn (gen_avx2_permv2ti
- (gen_lowpart (V4DImode, operands[0]),
- gen_lowpart (V4DImode, t1),
- gen_lowpart (V4DImode, t2), GEN_INT (1 + (3 << 4))));
+ emit_insn (gen_avx2_permv2ti (t3, gen_lowpart (V4DImode, t1),
+ gen_lowpart (V4DImode, t2),
+ GEN_INT (1 + (3 << 4))));
+ emit_move_insn (operands[0], gen_lowpart (<MODE>mode, t3));
DONE;
})
@@ -6908,12 +8569,13 @@
{
rtx t1 = gen_reg_rtx (<MODE>mode);
rtx t2 = gen_reg_rtx (<MODE>mode);
+ rtx t3 = gen_reg_rtx (V4DImode);
emit_insn (gen_avx2_interleave_low<mode> (t1, operands[1], operands[2]));
emit_insn (gen_avx2_interleave_high<mode> (t2, operands[1], operands[2]));
- emit_insn (gen_avx2_permv2ti
- (gen_lowpart (V4DImode, operands[0]),
- gen_lowpart (V4DImode, t1),
- gen_lowpart (V4DImode, t2), GEN_INT (0 + (2 << 4))));
+ emit_insn (gen_avx2_permv2ti (t3, gen_lowpart (V4DImode, t1),
+ gen_lowpart (V4DImode, t2),
+ GEN_INT (0 + (2 << 4))));
+ emit_move_insn (operands[0], gen_lowpart (<MODE>mode, t3));
DONE;
})
@@ -6983,6 +8645,198 @@
(set_attr "prefix" "orig,orig,vex,vex")
(set_attr "mode" "TI")])
+(define_insn "avx512f_vinsert<shuffletype>32x4_1"
+ [(set (match_operand:V16FI 0 "register_operand" "=v")
+ (vec_merge:V16FI
+ (match_operand:V16FI 1 "register_operand" "v")
+ (vec_duplicate:V16FI
+ (match_operand:<ssequartermode> 2 "nonimmediate_operand" "vm"))
+ (match_operand:SI 3 "const_int_operand" "n")))]
+ "TARGET_AVX512F"
+{
+ int mask;
+ if (INTVAL (operands[3]) == 0xFFF)
+ mask = 0;
+ else if ( INTVAL (operands[3]) == 0xF0FF)
+ mask = 1;
+ else if ( INTVAL (operands[3]) == 0xFF0F)
+ mask = 2;
+ else if ( INTVAL (operands[3]) == 0xFFF0)
+ mask = 3;
+ else
+ gcc_unreachable ();
+
+ operands[3] = GEN_INT (mask);
+
+ return "vinsert<shuffletype>32x4\t{%3, %2, %1, %0|%0, %1, %2, %3}";
+}
+ [(set_attr "type" "sselog")
+ (set_attr "length_immediate" "1")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<sseinsnmode>")])
+
+(define_insn "vec_set_lo_<mode>"
+ [(set (match_operand:V8FI 0 "register_operand" "=v")
+ (vec_concat:V8FI
+ (match_operand:<ssehalfvecmode> 2 "nonimmediate_operand" "vm")
+ (vec_select:<ssehalfvecmode>
+ (match_operand:V8FI 1 "register_operand" "v")
+ (parallel [(const_int 4) (const_int 5)
+ (const_int 6) (const_int 7)]))))]
+ "TARGET_AVX512F"
+ "vinsert<shuffletype>64x4\t{$0x0, %2, %1, %0|%0, %1, %2, $0x0}"
+ [(set_attr "type" "sselog")
+ (set_attr "length_immediate" "1")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "XI")])
+
+(define_insn "vec_set_hi_<mode>"
+ [(set (match_operand:V8FI 0 "register_operand" "=v")
+ (vec_concat:V8FI
+ (match_operand:<ssehalfvecmode> 2 "nonimmediate_operand" "vm")
+ (vec_select:<ssehalfvecmode>
+ (match_operand:V8FI 1 "register_operand" "v")
+ (parallel [(const_int 0) (const_int 1)
+ (const_int 2) (const_int 3)]))))]
+ "TARGET_AVX512F"
+ "vinsert<shuffletype>64x4\t{$0x1, %2, %1, %0|%0, %1, %2, $0x1}"
+ [(set_attr "type" "sselog")
+ (set_attr "length_immediate" "1")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "XI")])
+
+(define_insn "avx512f_shuf_<shuffletype>64x2_1"
+ [(set (match_operand:V8FI 0 "register_operand" "=v")
+ (vec_select:V8FI
+ (vec_concat:<ssedoublemode>
+ (match_operand:V8FI 1 "register_operand" "v")
+ (match_operand:V8FI 2 "nonimmediate_operand" "vm"))
+ (parallel [(match_operand 3 "const_0_to_7_operand")
+ (match_operand 4 "const_0_to_7_operand")
+ (match_operand 5 "const_0_to_7_operand")
+ (match_operand 6 "const_0_to_7_operand")
+ (match_operand 7 "const_8_to_15_operand")
+ (match_operand 8 "const_8_to_15_operand")
+ (match_operand 9 "const_8_to_15_operand")
+ (match_operand 10 "const_8_to_15_operand")])))]
+ "TARGET_AVX512F
+ && (INTVAL (operands[3]) == (INTVAL (operands[4]) - 1)
+ && INTVAL (operands[5]) == (INTVAL (operands[6]) - 1)
+ && INTVAL (operands[7]) == (INTVAL (operands[8]) - 1)
+ && INTVAL (operands[9]) == (INTVAL (operands[10]) - 1))"
+{
+ int mask;
+ mask = INTVAL (operands[3]) / 2;
+ mask |= INTVAL (operands[5]) / 2 << 2;
+ mask |= (INTVAL (operands[7]) - 8) / 2 << 4;
+ mask |= (INTVAL (operands[9]) - 8) / 2 << 6;
+ operands[3] = GEN_INT (mask);
+
+ return "vshuf<shuffletype>64x2\t{%3, %2, %1, %0|%0, %1, %2, %3}";
+}
+ [(set_attr "type" "sselog")
+ (set_attr "length_immediate" "1")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<sseinsnmode>")])
+
+(define_insn "avx512f_shuf_<shuffletype>32x4_1"
+ [(set (match_operand:V16FI 0 "register_operand" "=v")
+ (vec_select:V16FI
+ (vec_concat:<ssedoublemode>
+ (match_operand:V16FI 1 "register_operand" "v")
+ (match_operand:V16FI 2 "nonimmediate_operand" "vm"))
+ (parallel [(match_operand 3 "const_0_to_15_operand")
+ (match_operand 4 "const_0_to_15_operand")
+ (match_operand 5 "const_0_to_15_operand")
+ (match_operand 6 "const_0_to_15_operand")
+ (match_operand 7 "const_0_to_15_operand")
+ (match_operand 8 "const_0_to_15_operand")
+ (match_operand 9 "const_0_to_15_operand")
+ (match_operand 10 "const_0_to_15_operand")
+ (match_operand 11 "const_16_to_31_operand")
+ (match_operand 12 "const_16_to_31_operand")
+ (match_operand 13 "const_16_to_31_operand")
+ (match_operand 14 "const_16_to_31_operand")
+ (match_operand 15 "const_16_to_31_operand")
+ (match_operand 16 "const_16_to_31_operand")
+ (match_operand 17 "const_16_to_31_operand")
+ (match_operand 18 "const_16_to_31_operand")])))]
+ "TARGET_AVX512F
+ && (INTVAL (operands[3]) == (INTVAL (operands[4]) - 1)
+ && INTVAL (operands[3]) == (INTVAL (operands[5]) - 2)
+ && INTVAL (operands[3]) == (INTVAL (operands[6]) - 3)
+ && INTVAL (operands[7]) == (INTVAL (operands[8]) - 1)
+ && INTVAL (operands[7]) == (INTVAL (operands[9]) - 2)
+ && INTVAL (operands[7]) == (INTVAL (operands[10]) - 3)
+ && INTVAL (operands[11]) == (INTVAL (operands[12]) - 1)
+ && INTVAL (operands[11]) == (INTVAL (operands[13]) - 2)
+ && INTVAL (operands[11]) == (INTVAL (operands[14]) - 3)
+ && INTVAL (operands[15]) == (INTVAL (operands[16]) - 1)
+ && INTVAL (operands[15]) == (INTVAL (operands[17]) - 2)
+ && INTVAL (operands[15]) == (INTVAL (operands[18]) - 3))"
+{
+ int mask;
+ mask = INTVAL (operands[3]) / 4;
+ mask |= INTVAL (operands[7]) / 4 << 2;
+ mask |= (INTVAL (operands[11]) - 16) / 4 << 4;
+ mask |= (INTVAL (operands[15]) - 16) / 4 << 6;
+ operands[3] = GEN_INT (mask);
+
+ return "vshuf<shuffletype>32x4\t{%3, %2, %1, %0|%0, %1, %2, %3}";
+}
+ [(set_attr "type" "sselog")
+ (set_attr "length_immediate" "1")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<sseinsnmode>")])
+
+(define_insn "avx512f_pshufd_1"
+ [(set (match_operand:V16SI 0 "register_operand" "=v")
+ (vec_select:V16SI
+ (match_operand:V16SI 1 "nonimmediate_operand" "vm")
+ (parallel [(match_operand 2 "const_0_to_3_operand")
+ (match_operand 3 "const_0_to_3_operand")
+ (match_operand 4 "const_0_to_3_operand")
+ (match_operand 5 "const_0_to_3_operand")
+ (match_operand 6 "const_4_to_7_operand")
+ (match_operand 7 "const_4_to_7_operand")
+ (match_operand 8 "const_4_to_7_operand")
+ (match_operand 9 "const_4_to_7_operand")
+ (match_operand 10 "const_8_to_11_operand")
+ (match_operand 11 "const_8_to_11_operand")
+ (match_operand 12 "const_8_to_11_operand")
+ (match_operand 13 "const_8_to_11_operand")
+ (match_operand 14 "const_12_to_15_operand")
+ (match_operand 15 "const_12_to_15_operand")
+ (match_operand 16 "const_12_to_15_operand")
+ (match_operand 17 "const_12_to_15_operand")])))]
+ "TARGET_AVX512F
+ && INTVAL (operands[2]) + 4 == INTVAL (operands[6])
+ && INTVAL (operands[3]) + 4 == INTVAL (operands[7])
+ && INTVAL (operands[4]) + 4 == INTVAL (operands[8])
+ && INTVAL (operands[5]) + 4 == INTVAL (operands[9])
+ && INTVAL (operands[2]) + 8 == INTVAL (operands[10])
+ && INTVAL (operands[3]) + 8 == INTVAL (operands[11])
+ && INTVAL (operands[4]) + 8 == INTVAL (operands[12])
+ && INTVAL (operands[5]) + 8 == INTVAL (operands[13])
+ && INTVAL (operands[2]) + 12 == INTVAL (operands[14])
+ && INTVAL (operands[3]) + 12 == INTVAL (operands[15])
+ && INTVAL (operands[4]) + 12 == INTVAL (operands[16])
+ && INTVAL (operands[5]) + 12 == INTVAL (operands[17])"
+{
+ int mask = 0;
+ mask |= INTVAL (operands[2]) << 0;
+ mask |= INTVAL (operands[3]) << 2;
+ mask |= INTVAL (operands[4]) << 4;
+ mask |= INTVAL (operands[5]) << 6;
+ operands[2] = GEN_INT (mask);
+
+ return "vpshufd\t{%2, %1, %0|%0, %1, %2}";
+}
+ [(set_attr "type" "sselog1")
+ (set_attr "prefix" "evex")
+ (set_attr "length_immediate" "1")
+ (set_attr "mode" "XI")])
+
(define_expand "avx2_pshufdv3"
[(match_operand:V8SI 0 "register_operand")
(match_operand:V8SI 1 "nonimmediate_operand")
@@ -7635,7 +9489,7 @@
"@
pinsrq\t{$1, %2, %0|%0, %2, 1}
vpinsrq\t{$1, %2, %1, %0|%0, %1, %2, 1}
- %vmovd\t{%1, %0|%0, %1}
+ * return HAVE_AS_IX86_INTERUNIT_MOVQ ? \"%vmovq\t{%1, %0|%0, %1}\" : \"%vmovd\t{%1, %0|%0, %1}\";
%vmovq\t{%1, %0|%0, %1}
movq2dq\t{%1, %0|%0, %1}
punpcklqdq\t{%2, %0|%0, %2}
@@ -7657,25 +9511,25 @@
(define_expand "vec_unpacks_lo_<mode>"
[(match_operand:<sseunpackmode> 0 "register_operand")
- (match_operand:VI124_AVX2 1 "register_operand")]
+ (match_operand:VI124_AVX512F 1 "register_operand")]
"TARGET_SSE2"
"ix86_expand_sse_unpack (operands[0], operands[1], false, false); DONE;")
(define_expand "vec_unpacks_hi_<mode>"
[(match_operand:<sseunpackmode> 0 "register_operand")
- (match_operand:VI124_AVX2 1 "register_operand")]
+ (match_operand:VI124_AVX512F 1 "register_operand")]
"TARGET_SSE2"
"ix86_expand_sse_unpack (operands[0], operands[1], false, true); DONE;")
(define_expand "vec_unpacku_lo_<mode>"
[(match_operand:<sseunpackmode> 0 "register_operand")
- (match_operand:VI124_AVX2 1 "register_operand")]
+ (match_operand:VI124_AVX512F 1 "register_operand")]
"TARGET_SSE2"
"ix86_expand_sse_unpack (operands[0], operands[1], true, false); DONE;")
(define_expand "vec_unpacku_hi_<mode>"
[(match_operand:<sseunpackmode> 0 "register_operand")
- (match_operand:VI124_AVX2 1 "register_operand")]
+ (match_operand:VI124_AVX512F 1 "register_operand")]
"TARGET_SSE2"
"ix86_expand_sse_unpack (operands[0], operands[1], true, true); DONE;")
@@ -7747,7 +9601,7 @@
(define_insn "<sse>_movmsk<ssemodesuffix><avxsizesuffix>"
[(set (match_operand:SI 0 "register_operand" "=r")
(unspec:SI
- [(match_operand:VF 1 "register_operand" "x")]
+ [(match_operand:VF_128_256 1 "register_operand" "x")]
UNSPEC_MOVMSK))]
"TARGET_SSE"
"%vmovmsk<ssemodesuffix>\t{%1, %0|%0, %1}"
@@ -8427,10 +10281,10 @@
(set (attr "prefix_rex") (symbol_ref "x86_extended_reg_mentioned_p (insn)"))
(set_attr "mode" "DI")])
-(define_insn "abs<mode>2"
- [(set (match_operand:VI124_AVX2 0 "register_operand" "=v")
- (abs:VI124_AVX2
- (match_operand:VI124_AVX2 1 "nonimmediate_operand" "vm")))]
+(define_insn "*abs<mode>2"
+ [(set (match_operand:VI124_AVX2_48_AVX512F 0 "register_operand" "=v")
+ (abs:VI124_AVX2_48_AVX512F
+ (match_operand:VI124_AVX2_48_AVX512F 1 "nonimmediate_operand" "vm")))]
"TARGET_SSSE3"
"%vpabs<ssemodesuffix>\t{%1, %0|%0, %1}"
[(set_attr "type" "sselog1")
@@ -8439,6 +10293,19 @@
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "<sseinsnmode>")])
+(define_expand "abs<mode>2"
+ [(set (match_operand:VI124_AVX2_48_AVX512F 0 "register_operand")
+ (abs:VI124_AVX2_48_AVX512F
+ (match_operand:VI124_AVX2_48_AVX512F 1 "nonimmediate_operand")))]
+ "TARGET_SSE2"
+{
+ if (!TARGET_SSSE3)
+ {
+ ix86_expand_sse2_abs (operands[0], operands[1]);
+ DONE;
+ }
+})
+
(define_insn "abs<mode>2"
[(set (match_operand:MMXMODEI 0 "register_operand" "=y")
(abs:MMXMODEI
@@ -8537,10 +10404,10 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define_insn "<sse4_1>_blend<ssemodesuffix><avxsizesuffix>"
- [(set (match_operand:VF 0 "register_operand" "=x,x")
- (vec_merge:VF
- (match_operand:VF 2 "nonimmediate_operand" "xm,xm")
- (match_operand:VF 1 "register_operand" "0,x")
+ [(set (match_operand:VF_128_256 0 "register_operand" "=x,x")
+ (vec_merge:VF_128_256
+ (match_operand:VF_128_256 2 "nonimmediate_operand" "xm,xm")
+ (match_operand:VF_128_256 1 "register_operand" "0,x")
(match_operand:SI 3 "const_0_to_<blendbits>_operand")))]
"TARGET_SSE4_1"
"@
@@ -8555,11 +10422,11 @@
(set_attr "mode" "<MODE>")])
(define_insn "<sse4_1>_blendv<ssemodesuffix><avxsizesuffix>"
- [(set (match_operand:VF 0 "register_operand" "=x,x")
- (unspec:VF
- [(match_operand:VF 1 "register_operand" "0,x")
- (match_operand:VF 2 "nonimmediate_operand" "xm,xm")
- (match_operand:VF 3 "register_operand" "Yz,x")]
+ [(set (match_operand:VF_128_256 0 "register_operand" "=x,x")
+ (unspec:VF_128_256
+ [(match_operand:VF_128_256 1 "register_operand" "0,x")
+ (match_operand:VF_128_256 2 "nonimmediate_operand" "xm,xm")
+ (match_operand:VF_128_256 3 "register_operand" "Yz,x")]
UNSPEC_BLENDV))]
"TARGET_SSE4_1"
"@
@@ -8575,10 +10442,10 @@
(set_attr "mode" "<MODE>")])
(define_insn "<sse4_1>_dp<ssemodesuffix><avxsizesuffix>"
- [(set (match_operand:VF 0 "register_operand" "=x,x")
- (unspec:VF
- [(match_operand:VF 1 "nonimmediate_operand" "%0,x")
- (match_operand:VF 2 "nonimmediate_operand" "xm,xm")
+ [(set (match_operand:VF_128_256 0 "register_operand" "=x,x")
+ (unspec:VF_128_256
+ [(match_operand:VF_128_256 1 "nonimmediate_operand" "%0,x")
+ (match_operand:VF_128_256 2 "nonimmediate_operand" "xm,xm")
(match_operand:SI 3 "const_0_to_255_operand" "n,n")]
UNSPEC_DP))]
"TARGET_SSE4_1"
@@ -8773,6 +10640,16 @@
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "TI")])
+(define_insn "avx512f_<code>v16qiv16si2"
+ [(set (match_operand:V16SI 0 "register_operand" "=v")
+ (any_extend:V16SI
+ (match_operand:V16QI 1 "nonimmediate_operand" "vm")))]
+ "TARGET_AVX512F"
+ "vpmov<extsuffix>bd\t{%1, %0|%0, %q1}"
+ [(set_attr "type" "ssemov")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "XI")])
+
(define_insn "avx2_<code>v8qiv8si2"
[(set (match_operand:V8SI 0 "register_operand" "=x")
(any_extend:V8SI
@@ -8803,6 +10680,16 @@
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "TI")])
+(define_insn "avx512f_<code>v16hiv16si2"
+ [(set (match_operand:V16SI 0 "register_operand" "=v")
+ (any_extend:V16SI
+ (match_operand:V16HI 1 "nonimmediate_operand" "vm")))]
+ "TARGET_AVX512F"
+ "vpmov<extsuffix>wd\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssemov")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "XI")])
+
(define_insn "avx2_<code>v8hiv8si2"
[(set (match_operand:V8SI 0 "register_operand" "=x")
(any_extend:V8SI
@@ -8828,6 +10715,21 @@
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "TI")])
+(define_insn "avx512f_<code>v8qiv8di2"
+ [(set (match_operand:V8DI 0 "register_operand" "=v")
+ (any_extend:V8DI
+ (vec_select:V8QI
+ (match_operand:V16QI 1 "nonimmediate_operand" "vm")
+ (parallel [(const_int 0) (const_int 1)
+ (const_int 2) (const_int 3)
+ (const_int 4) (const_int 5)
+ (const_int 6) (const_int 7)]))))]
+ "TARGET_AVX512F"
+ "vpmov<extsuffix>bq\t{%1, %0|%0, %k1}"
+ [(set_attr "type" "ssemov")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "XI")])
+
(define_insn "avx2_<code>v4qiv4di2"
[(set (match_operand:V4DI 0 "register_operand" "=x")
(any_extend:V4DI
@@ -8855,6 +10757,16 @@
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "TI")])
+(define_insn "avx512f_<code>v8hiv8di2"
+ [(set (match_operand:V8DI 0 "register_operand" "=v")
+ (any_extend:V8DI
+ (match_operand:V8HI 1 "nonimmediate_operand" "vm")))]
+ "TARGET_AVX512F"
+ "vpmov<extsuffix>wq\t{%1, %0|%0, %q1}"
+ [(set_attr "type" "ssemov")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "XI")])
+
(define_insn "avx2_<code>v4hiv4di2"
[(set (match_operand:V4DI 0 "register_operand" "=x")
(any_extend:V4DI
@@ -8882,6 +10794,16 @@
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "TI")])
+(define_insn "avx512f_<code>v8siv8di2"
+ [(set (match_operand:V8DI 0 "register_operand" "=v")
+ (any_extend:V8DI
+ (match_operand:V8SI 1 "nonimmediate_operand" "vm")))]
+ "TARGET_AVX512F"
+ "vpmov<extsuffix>dq\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssemov")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "XI")])
+
(define_insn "avx2_<code>v4siv4di2"
[(set (match_operand:V4DI 0 "register_operand" "=x")
(any_extend:V4DI
@@ -8909,8 +10831,8 @@
;; setting FLAGS_REG. But it is not a really compare instruction.
(define_insn "avx_vtest<ssemodesuffix><avxsizesuffix>"
[(set (reg:CC FLAGS_REG)
- (unspec:CC [(match_operand:VF 0 "register_operand" "x")
- (match_operand:VF 1 "nonimmediate_operand" "xm")]
+ (unspec:CC [(match_operand:VF_128_256 0 "register_operand" "x")
+ (match_operand:VF_128_256 1 "nonimmediate_operand" "xm")]
UNSPEC_VTESTP))]
"TARGET_AVX"
"vtest<ssemodesuffix>\t{%1, %0|%0, %1}"
@@ -8947,9 +10869,9 @@
(set_attr "mode" "TI")])
(define_insn "<sse4_1>_round<ssemodesuffix><avxsizesuffix>"
- [(set (match_operand:VF 0 "register_operand" "=x")
- (unspec:VF
- [(match_operand:VF 1 "nonimmediate_operand" "xm")
+ [(set (match_operand:VF_128_256 0 "register_operand" "=x")
+ (unspec:VF_128_256
+ [(match_operand:VF_128_256 1 "nonimmediate_operand" "xm")
(match_operand:SI 2 "const_0_to_15_operand" "n")]
UNSPEC_ROUND))]
"TARGET_ROUND"
@@ -8967,7 +10889,7 @@
(define_expand "<sse4_1>_round<ssemodesuffix>_sfix<avxsizesuffix>"
[(match_operand:<sseintvecmode> 0 "register_operand")
- (match_operand:VF1 1 "nonimmediate_operand")
+ (match_operand:VF1_128_256 1 "nonimmediate_operand")
(match_operand:SI 2 "const_0_to_15_operand")]
"TARGET_ROUND"
{
@@ -8981,6 +10903,16 @@
DONE;
})
+(define_expand "avx512f_roundpd512"
+ [(match_operand:V8DF 0 "register_operand")
+ (match_operand:V8DF 1 "nonimmediate_operand")
+ (match_operand:SI 2 "const_0_to_15_operand")]
+ "TARGET_AVX512F"
+{
+ emit_insn (gen_avx512f_rndscalev8df (operands[0], operands[1], operands[2]));
+ DONE;
+})
+
(define_expand "<sse4_1>_round<ssemodesuffix>_vec_pack_sfix<avxsizesuffix>"
[(match_operand:<ssepackfltmode> 0 "register_operand")
(match_operand:VF2 1 "nonimmediate_operand")
@@ -9076,7 +11008,7 @@
(define_expand "round<mode>2_sfix"
[(match_operand:<sseintvecmode> 0 "register_operand")
- (match_operand:VF1 1 "register_operand")]
+ (match_operand:VF1_128_256 1 "register_operand")]
"TARGET_ROUND && !flag_trapping_math"
{
rtx tmp = gen_reg_rtx (<MODE>mode);
@@ -9508,6 +11440,178 @@
(set_attr "btver2_decode" "vector,vector,vector,vector")
(set_attr "mode" "TI")])
+(define_expand "avx512pf_gatherpf<mode>"
+ [(unspec
+ [(match_operand:<avx512fmaskmode> 0 "register_or_constm1_operand")
+ (mem:<ssescalarmode>
+ (match_par_dup 5
+ [(match_operand 2 "vsib_address_operand")
+ (match_operand:VI48_512 1 "register_operand")
+ (match_operand:SI 3 "const1248_operand")]))
+ (match_operand:SI 4 "const_0_to_1_operand")]
+ UNSPEC_GATHER_PREFETCH)]
+ "TARGET_AVX512PF"
+{
+ operands[5]
+ = gen_rtx_UNSPEC (Pmode, gen_rtvec (3, operands[2], operands[1],
+ operands[3]), UNSPEC_VSIBADDR);
+})
+
+(define_insn "*avx512pf_gatherpf<mode>_mask"
+ [(unspec
+ [(match_operand:<avx512fmaskmode> 0 "register_operand" "k")
+ (match_operator:<ssescalarmode> 5 "vsib_mem_operator"
+ [(unspec:P
+ [(match_operand:P 2 "vsib_address_operand" "Tv")
+ (match_operand:VI48_512 1 "register_operand" "v")
+ (match_operand:SI 3 "const1248_operand" "n")]
+ UNSPEC_VSIBADDR)])
+ (match_operand:SI 4 "const_0_to_1_operand" "n")]
+ UNSPEC_GATHER_PREFETCH)]
+ "TARGET_AVX512PF"
+{
+ switch (INTVAL (operands[4]))
+ {
+ case 0:
+ return "vgatherpf0<ssemodesuffix>ps\t{%5%{%0%}|%5%{%0%}}";
+ case 1:
+ return "vgatherpf1<ssemodesuffix>ps\t{%5%{%0%}|%5%{%0%}}";
+ default:
+ gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "sse")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "XI")])
+
+(define_insn "*avx512pf_gatherpf<mode>"
+ [(unspec
+ [(const_int -1)
+ (match_operator:<ssescalarmode> 4 "vsib_mem_operator"
+ [(unspec:P
+ [(match_operand:P 1 "vsib_address_operand" "Tv")
+ (match_operand:VI48_512 0 "register_operand" "v")
+ (match_operand:SI 2 "const1248_operand" "n")]
+ UNSPEC_VSIBADDR)])
+ (match_operand:SI 3 "const_0_to_1_operand" "n")]
+ UNSPEC_GATHER_PREFETCH)]
+ "TARGET_AVX512PF"
+{
+ switch (INTVAL (operands[3]))
+ {
+ case 0:
+ return "vgatherpf0<ssemodesuffix>ps\t{%4|%4}";
+ case 1:
+ return "vgatherpf1<ssemodesuffix>ps\t{%4|%4}";
+ default:
+ gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "sse")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "XI")])
+
+(define_expand "avx512pf_scatterpf<mode>"
+ [(unspec
+ [(match_operand:<avx512fmaskmode> 0 "register_or_constm1_operand")
+ (mem:<ssescalarmode>
+ (match_par_dup 5
+ [(match_operand 2 "vsib_address_operand")
+ (match_operand:VI48_512 1 "register_operand")
+ (match_operand:SI 3 "const1248_operand")]))
+ (match_operand:SI 4 "const_0_to_1_operand")]
+ UNSPEC_SCATTER_PREFETCH)]
+ "TARGET_AVX512PF"
+{
+ operands[5]
+ = gen_rtx_UNSPEC (Pmode, gen_rtvec (3, operands[2], operands[1],
+ operands[3]), UNSPEC_VSIBADDR);
+})
+
+(define_insn "*avx512pf_scatterpf<mode>_mask"
+ [(unspec
+ [(match_operand:<avx512fmaskmode> 0 "register_operand" "k")
+ (match_operator:<ssescalarmode> 5 "vsib_mem_operator"
+ [(unspec:P
+ [(match_operand:P 2 "vsib_address_operand" "Tv")
+ (match_operand:VI48_512 1 "register_operand" "v")
+ (match_operand:SI 3 "const1248_operand" "n")]
+ UNSPEC_VSIBADDR)])
+ (match_operand:SI 4 "const_0_to_1_operand" "n")]
+ UNSPEC_SCATTER_PREFETCH)]
+ "TARGET_AVX512PF"
+{
+ switch (INTVAL (operands[4]))
+ {
+ case 0:
+ return "vscatterpf0<ssemodesuffix>ps\t{%5%{%0%}|%5%{%0%}}";
+ case 1:
+ return "vscatterpf1<ssemodesuffix>ps\t{%5%{%0%}|%5%{%0%}}";
+ default:
+ gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "sse")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "XI")])
+
+(define_insn "*avx512pf_scatterpf<mode>"
+ [(unspec
+ [(const_int -1)
+ (match_operator:<ssescalarmode> 4 "vsib_mem_operator"
+ [(unspec:P
+ [(match_operand:P 1 "vsib_address_operand" "Tv")
+ (match_operand:VI48_512 0 "register_operand" "v")
+ (match_operand:SI 2 "const1248_operand" "n")]
+ UNSPEC_VSIBADDR)])
+ (match_operand:SI 3 "const_0_to_1_operand" "n")]
+ UNSPEC_SCATTER_PREFETCH)]
+ "TARGET_AVX512PF"
+{
+ switch (INTVAL (operands[3]))
+ {
+ case 0:
+ return "vscatterpf0<ssemodesuffix>ps\t{%4|%4}";
+ case 1:
+ return "vscatterpf1<ssemodesuffix>ps\t{%4|%4}";
+ default:
+ gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "sse")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "XI")])
+
+(define_insn "*avx512er_exp2<mode>"
+ [(set (match_operand:VF_512 0 "register_operand" "=v")
+ (unspec:VF_512
+ [(match_operand:VF_512 1 "nonimmediate_operand" "vm")]
+ UNSPEC_EXP2))]
+ "TARGET_AVX512ER"
+ "vexp2<ssemodesuffix>\t{%1, %0|%0, %1}"
+ [(set_attr "prefix" "evex")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "*avx512er_rcp28<mode>"
+ [(set (match_operand:VF_512 0 "register_operand" "=v")
+ (unspec:VF_512
+ [(match_operand:VF_512 1 "nonimmediate_operand" "vm")]
+ UNSPEC_RCP28))]
+ "TARGET_AVX512ER"
+ "vrcp28<ssemodesuffix>\t{%1, %0|%0, %1}"
+ [(set_attr "prefix" "evex")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "avx512er_rsqrt28<mode>"
+ [(set (match_operand:VF_512 0 "register_operand" "=v")
+ (unspec:VF_512
+ [(match_operand:VF_512 1 "nonimmediate_operand" "vm")]
+ UNSPEC_RSQRT28))]
+ "TARGET_AVX512ER"
+ "vrsqrt28<ssemodesuffix>\t{%1, %0|%0, %1}"
+ [(set_attr "prefix" "evex")
+ (set_attr "mode" "<MODE>")])
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; XOP instructions
@@ -10055,6 +12159,13 @@
})
(define_expand "vlshr<mode>3"
+ [(set (match_operand:VI48_512 0 "register_operand")
+ (lshiftrt:VI48_512
+ (match_operand:VI48_512 1 "register_operand")
+ (match_operand:VI48_512 2 "nonimmediate_operand")))]
+ "TARGET_AVX512F")
+
+(define_expand "vlshr<mode>3"
[(set (match_operand:VI48_256 0 "register_operand")
(lshiftrt:VI48_256
(match_operand:VI48_256 1 "register_operand")
@@ -10089,6 +12200,12 @@
}
})
+(define_expand "vashrv16si3"
+ [(set (match_operand:V16SI 0 "register_operand")
+ (ashiftrt:V16SI (match_operand:V16SI 1 "register_operand")
+ (match_operand:V16SI 2 "nonimmediate_operand")))]
+ "TARGET_AVX512F")
+
(define_expand "vashrv8si3"
[(set (match_operand:V8SI 0 "register_operand")
(ashiftrt:V8SI (match_operand:V8SI 1 "register_operand")
@@ -10122,6 +12239,13 @@
})
(define_expand "vashl<mode>3"
+ [(set (match_operand:VI48_512 0 "register_operand")
+ (ashift:VI48_512
+ (match_operand:VI48_512 1 "register_operand")
+ (match_operand:VI48_512 2 "nonimmediate_operand")))]
+ "TARGET_AVX512F")
+
+(define_expand "vashl<mode>3"
[(set (match_operand:VI48_256 0 "register_operand")
(ashift:VI48_256
(match_operand:VI48_256 1 "register_operand")
@@ -10341,10 +12465,10 @@
(set_attr "mode" "TI")])
(define_insn "xop_vpermil2<mode>3"
- [(set (match_operand:VF 0 "register_operand" "=x")
- (unspec:VF
- [(match_operand:VF 1 "register_operand" "x")
- (match_operand:VF 2 "nonimmediate_operand" "%x")
+ [(set (match_operand:VF_128_256 0 "register_operand" "=x")
+ (unspec:VF_128_256
+ [(match_operand:VF_128_256 1 "register_operand" "x")
+ (match_operand:VF_128_256 2 "nonimmediate_operand" "%x")
(match_operand:<sseintvecmode> 3 "nonimmediate_operand" "xm")
(match_operand:SI 4 "const_0_to_3_operand" "n")]
UNSPEC_VPERMIL2))]
@@ -10506,17 +12630,11 @@
(set_attr "btver2_decode" "vector")
(set_attr "mode" "OI")])
-(define_mode_attr AVXTOSSEMODE
- [(V4DI "V2DI") (V2DI "V2DI")
- (V8SI "V4SI") (V4SI "V4SI")
- (V16HI "V8HI") (V8HI "V8HI")
- (V32QI "V16QI") (V16QI "V16QI")])
-
(define_insn "avx2_pbroadcast<mode>"
[(set (match_operand:VI 0 "register_operand" "=x")
(vec_duplicate:VI
(vec_select:<ssescalarmode>
- (match_operand:<AVXTOSSEMODE> 1 "nonimmediate_operand" "xm")
+ (match_operand:<ssexmmmode> 1 "nonimmediate_operand" "xm")
(parallel [(const_int 0)]))))]
"TARGET_AVX2"
"vpbroadcast<ssemodesuffix>\t{%1, %0|%0, %<iptr>1}"
@@ -10540,37 +12658,37 @@
(set_attr "prefix" "vex")
(set_attr "mode" "<sseinsnmode>")])
-(define_insn "avx2_permvar<mode>"
- [(set (match_operand:VI4F_256 0 "register_operand" "=v")
- (unspec:VI4F_256
- [(match_operand:VI4F_256 1 "nonimmediate_operand" "vm")
- (match_operand:V8SI 2 "register_operand" "v")]
+(define_insn "<avx2_avx512f>_permvar<mode>"
+ [(set (match_operand:VI48F_256_512 0 "register_operand" "=v")
+ (unspec:VI48F_256_512
+ [(match_operand:VI48F_256_512 1 "nonimmediate_operand" "vm")
+ (match_operand:<sseintvecmode> 2 "register_operand" "v")]
UNSPEC_VPERMVAR))]
"TARGET_AVX2"
"vperm<ssemodesuffix>\t{%1, %2, %0|%0, %2, %1}"
[(set_attr "type" "sselog")
(set_attr "prefix" "vex")
- (set_attr "mode" "OI")])
+ (set_attr "mode" "<sseinsnmode>")])
-(define_expand "avx2_perm<mode>"
- [(match_operand:VI8F_256 0 "register_operand")
- (match_operand:VI8F_256 1 "nonimmediate_operand")
+(define_expand "<avx2_avx512f>_perm<mode>"
+ [(match_operand:VI8F_256_512 0 "register_operand")
+ (match_operand:VI8F_256_512 1 "nonimmediate_operand")
(match_operand:SI 2 "const_0_to_255_operand")]
"TARGET_AVX2"
{
int mask = INTVAL (operands[2]);
- emit_insn (gen_avx2_perm<mode>_1 (operands[0], operands[1],
- GEN_INT ((mask >> 0) & 3),
- GEN_INT ((mask >> 2) & 3),
- GEN_INT ((mask >> 4) & 3),
- GEN_INT ((mask >> 6) & 3)));
+ emit_insn (gen_<avx2_avx512f>_perm<mode>_1 (operands[0], operands[1],
+ GEN_INT ((mask >> 0) & 3),
+ GEN_INT ((mask >> 2) & 3),
+ GEN_INT ((mask >> 4) & 3),
+ GEN_INT ((mask >> 6) & 3)));
DONE;
})
-(define_insn "avx2_perm<mode>_1"
- [(set (match_operand:VI8F_256 0 "register_operand" "=v")
- (vec_select:VI8F_256
- (match_operand:VI8F_256 1 "nonimmediate_operand" "vm")
+(define_insn "<avx2_avx512f>_perm<mode>_1"
+ [(set (match_operand:VI8F_256_512 0 "register_operand" "=v")
+ (vec_select:VI8F_256_512
+ (match_operand:VI8F_256_512 1 "nonimmediate_operand" "vm")
(parallel [(match_operand 2 "const_0_to_3_operand")
(match_operand 3 "const_0_to_3_operand")
(match_operand 4 "const_0_to_3_operand")
@@ -10633,6 +12751,62 @@
(set_attr "isa" "*,avx2,noavx2")
(set_attr "mode" "V8SF")])
+(define_insn "avx512f_vec_dup<mode>"
+ [(set (match_operand:VI48F_512 0 "register_operand" "=v")
+ (vec_duplicate:VI48F_512
+ (vec_select:<ssescalarmode>
+ (match_operand:<ssexmmmode> 1 "nonimmediate_operand" "vm")
+ (parallel [(const_int 0)]))))]
+ "TARGET_AVX512F"
+ "v<sseintprefix>broadcast<bcstscalarsuff>\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssemov")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<sseinsnmode>")])
+
+(define_insn "avx512f_broadcast<mode>"
+ [(set (match_operand:V16FI 0 "register_operand" "=v,v")
+ (vec_duplicate:V16FI
+ (match_operand:<ssexmmmode> 1 "nonimmediate_operand" "v,m")))]
+ "TARGET_AVX512F"
+ "@
+ vshuf<shuffletype>32x4\t{$0x0, %g1, %g1, %0|%0, %g1, %g1, 0x0}
+ vbroadcast<shuffletype>32x4\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssemov")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<sseinsnmode>")])
+
+(define_insn "avx512f_broadcast<mode>"
+ [(set (match_operand:V8FI 0 "register_operand" "=v,v")
+ (vec_duplicate:V8FI
+ (match_operand:<ssehalfvecmode> 1 "nonimmediate_operand" "v,m")))]
+ "TARGET_AVX512F"
+ "@
+ vshuf<shuffletype>64x2\t{$0x44, %g1, %g1, %0|%0, %g1, %g1, 0x44}
+ vbroadcast<shuffletype>64x4\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssemov")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<sseinsnmode>")])
+
+(define_insn "avx512f_vec_dup_gpr<mode>"
+ [(set (match_operand:VI48_512 0 "register_operand" "=v")
+ (vec_duplicate:VI48_512
+ (match_operand:<ssescalarmode> 1 "register_operand" "r")))]
+ "TARGET_AVX512F && (<MODE>mode != V8DImode || TARGET_64BIT)"
+ "vpbroadcast<bcstscalarsuff>\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssemov")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<sseinsnmode>")])
+
+(define_insn "avx512f_vec_dup_mem<mode>"
+ [(set (match_operand:VI48F_512 0 "register_operand" "=v")
+ (vec_duplicate:VI48F_512
+ (match_operand:<ssescalarmode> 1 "nonimmediate_operand" "vm")))]
+ "TARGET_AVX512F"
+ "v<sseintprefix>broadcast<bcstscalarsuff>\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssemov")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<sseinsnmode>")])
+
(define_insn "avx2_vbroadcasti128_<mode>"
[(set (match_operand:VI_256 0 "register_operand" "=x")
(vec_concat:VI_256
@@ -10672,6 +12846,28 @@
(set_attr "prefix" "vex")
(set_attr "mode" "<sseinsnmode>")])
+(define_insn "avx512cd_maskb_vec_dupv8di"
+ [(set (match_operand:V8DI 0 "register_operand" "=v")
+ (vec_duplicate:V8DI
+ (zero_extend:DI
+ (match_operand:QI 1 "register_operand" "k"))))]
+ "TARGET_AVX512CD"
+ "vpbroadcastmb2q\t{%1, %0|%0, %1}"
+ [(set_attr "type" "mskmov")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "XI")])
+
+(define_insn "avx512cd_maskw_vec_dupv16si"
+ [(set (match_operand:V16SI 0 "register_operand" "=v")
+ (vec_duplicate:V16SI
+ (zero_extend:SI
+ (match_operand:HI 1 "register_operand" "k"))))]
+ "TARGET_AVX512CD"
+ "vpbroadcastmw2d\t{%1, %0|%0, %1}"
+ [(set_attr "type" "mskmov")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "XI")])
+
;; Recognize broadcast as a vec_select as produced by builtin_vec_perm.
;; If it so happens that the input is in memory, use vbroadcast.
;; Otherwise use vpermilp (and in the case of 256-bit modes, vperm2f128).
@@ -10746,7 +12942,7 @@
elt * GET_MODE_SIZE (<ssescalarmode>mode));
})
-(define_expand "avx_vpermil<mode>"
+(define_expand "<sse2_avx_avx512f>_vpermil<mode>"
[(set (match_operand:VF2 0 "register_operand")
(vec_select:VF2
(match_operand:VF2 1 "nonimmediate_operand")
@@ -10756,19 +12952,18 @@
int mask = INTVAL (operands[2]);
rtx perm[<ssescalarnum>];
- perm[0] = GEN_INT (mask & 1);
- perm[1] = GEN_INT ((mask >> 1) & 1);
- if (<MODE>mode == V4DFmode)
+ int i;
+ for (i = 0; i < <ssescalarnum>; i = i + 2)
{
- perm[2] = GEN_INT (((mask >> 2) & 1) + 2);
- perm[3] = GEN_INT (((mask >> 3) & 1) + 2);
+ perm[i] = GEN_INT (((mask >> i) & 1) + i);
+ perm[i + 1] = GEN_INT (((mask >> (i + 1)) & 1) + i);
}
operands[2]
= gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (<ssescalarnum>, perm));
})
-(define_expand "avx_vpermil<mode>"
+(define_expand "<sse2_avx_avx512f>_vpermil<mode>"
[(set (match_operand:VF1 0 "register_operand")
(vec_select:VF1
(match_operand:VF1 1 "nonimmediate_operand")
@@ -10778,23 +12973,20 @@
int mask = INTVAL (operands[2]);
rtx perm[<ssescalarnum>];
- perm[0] = GEN_INT (mask & 3);
- perm[1] = GEN_INT ((mask >> 2) & 3);
- perm[2] = GEN_INT ((mask >> 4) & 3);
- perm[3] = GEN_INT ((mask >> 6) & 3);
- if (<MODE>mode == V8SFmode)
+ int i;
+ for (i = 0; i < <ssescalarnum>; i = i + 4)
{
- perm[4] = GEN_INT ((mask & 3) + 4);
- perm[5] = GEN_INT (((mask >> 2) & 3) + 4);
- perm[6] = GEN_INT (((mask >> 4) & 3) + 4);
- perm[7] = GEN_INT (((mask >> 6) & 3) + 4);
+ perm[i] = GEN_INT (((mask >> 0) & 3) + i);
+ perm[i + 1] = GEN_INT (((mask >> 2) & 3) + i);
+ perm[i + 2] = GEN_INT (((mask >> 4) & 3) + i);
+ perm[i + 3] = GEN_INT (((mask >> 6) & 3) + i);
}
operands[2]
= gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (<ssescalarnum>, perm));
})
-(define_insn "*avx_vpermilp<mode>"
+(define_insn "*<sse2_avx_avx512f>_vpermilp<mode>"
[(set (match_operand:VF 0 "register_operand" "=v")
(vec_select:VF
(match_operand:VF 1 "nonimmediate_operand" "vm")
@@ -10811,9 +13003,9 @@
(set_attr "prefix_extra" "1")
(set_attr "length_immediate" "1")
(set_attr "prefix" "vex")
- (set_attr "mode" "<MODE>")])
+ (set_attr "mode" "<sseinsnmode>")])
-(define_insn "avx_vpermilvar<mode>3"
+(define_insn "<sse2_avx_avx512f>_vpermilvar<mode>3"
[(set (match_operand:VF 0 "register_operand" "=v")
(unspec:VF
[(match_operand:VF 1 "register_operand" "v")
@@ -10823,9 +13015,35 @@
"vpermil<ssemodesuffix>\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "sselog")
(set_attr "prefix_extra" "1")
- (set_attr "prefix" "vex")
(set_attr "btver2_decode" "vector")
- (set_attr "mode" "<MODE>")])
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "<sseinsnmode>")])
+
+(define_insn "avx512f_vpermi2var<mode>3"
+ [(set (match_operand:VI48F_512 0 "register_operand" "=v")
+ (unspec:VI48F_512
+ [(match_operand:VI48F_512 1 "register_operand" "v")
+ (match_operand:<sseintvecmode> 2 "register_operand" "0")
+ (match_operand:VI48F_512 3 "nonimmediate_operand" "vm")]
+ UNSPEC_VPERMI2))]
+ "TARGET_AVX512F"
+ "vpermi2<ssemodesuffix>\t{%3, %1, %0|%0, %1, %3}"
+ [(set_attr "type" "sselog")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<sseinsnmode>")])
+
+(define_insn "avx512f_vpermt2var<mode>3"
+ [(set (match_operand:VI48F_512 0 "register_operand" "=v")
+ (unspec:VI48F_512
+ [(match_operand:<sseintvecmode> 1 "register_operand" "v")
+ (match_operand:VI48F_512 2 "register_operand" "0")
+ (match_operand:VI48F_512 3 "nonimmediate_operand" "vm")]
+ UNSPEC_VPERMT2))]
+ "TARGET_AVX512F"
+ "vpermt2<ssemodesuffix>\t{%3, %1, %0|%0, %1, %3}"
+ [(set_attr "type" "sselog")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<sseinsnmode>")])
(define_expand "avx_vperm2f128<mode>3"
[(set (match_operand:AVX256MODE2P 0 "register_operand")
@@ -11159,6 +13377,15 @@
DONE;
})
+(define_expand "vec_init<mode>"
+ [(match_operand:VI48F_512 0 "register_operand")
+ (match_operand 1)]
+ "TARGET_AVX512F"
+{
+ ix86_expand_vector_init (false, operands[0], operands[1]);
+ DONE;
+})
+
(define_expand "avx2_extracti128"
[(match_operand:V2DI 0 "nonimmediate_operand")
(match_operand:V4DI 1 "register_operand")
@@ -11208,31 +13435,36 @@
DONE;
})
-(define_insn "avx2_ashrv<mode>"
- [(set (match_operand:VI4_AVX2 0 "register_operand" "=v")
- (ashiftrt:VI4_AVX2
- (match_operand:VI4_AVX2 1 "register_operand" "v")
- (match_operand:VI4_AVX2 2 "nonimmediate_operand" "vm")))]
+(define_insn "<avx2_avx512f>_ashrv<mode>"
+ [(set (match_operand:VI48_AVX512F 0 "register_operand" "=v")
+ (ashiftrt:VI48_AVX512F
+ (match_operand:VI48_AVX512F 1 "register_operand" "v")
+ (match_operand:VI48_AVX512F 2 "nonimmediate_operand" "vm")))]
"TARGET_AVX2"
- "vpsravd\t{%2, %1, %0|%0, %1, %2}"
+ "vpsrav<ssemodesuffix>\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "sseishft")
- (set_attr "prefix" "vex")
+ (set_attr "prefix" "maybe_evex")
(set_attr "mode" "<sseinsnmode>")])
-(define_insn "avx2_<shift_insn>v<mode>"
- [(set (match_operand:VI48_AVX2 0 "register_operand" "=v")
- (any_lshift:VI48_AVX2
- (match_operand:VI48_AVX2 1 "register_operand" "v")
- (match_operand:VI48_AVX2 2 "nonimmediate_operand" "vm")))]
+(define_insn "<avx2_avx512f>_<shift_insn>v<mode>"
+ [(set (match_operand:VI48_AVX2_48_AVX512F 0 "register_operand" "=v")
+ (any_lshift:VI48_AVX2_48_AVX512F
+ (match_operand:VI48_AVX2_48_AVX512F 1 "register_operand" "v")
+ (match_operand:VI48_AVX2_48_AVX512F 2 "nonimmediate_operand" "vm")))]
"TARGET_AVX2"
"vp<vshift>v<ssemodesuffix>\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "sseishft")
- (set_attr "prefix" "vex")
+ (set_attr "prefix" "maybe_evex")
(set_attr "mode" "<sseinsnmode>")])
+;; For avx_vec_concat<mode> insn pattern
+(define_mode_attr concat_tg_mode
+ [(V32QI "t") (V16HI "t") (V8SI "t") (V4DI "t") (V8SF "t") (V4DF "t")
+ (V64QI "g") (V32HI "g") (V16SI "g") (V8DI "g") (V16SF "g") (V8DF "g")])
+
(define_insn "avx_vec_concat<mode>"
- [(set (match_operand:V_256 0 "register_operand" "=x,x")
- (vec_concat:V_256
+ [(set (match_operand:V_256_512 0 "register_operand" "=x,x")
+ (vec_concat:V_256_512
(match_operand:<ssehalfvecmode> 1 "register_operand" "x,x")
(match_operand:<ssehalfvecmode> 2 "vector_move_operand" "xm,C")))]
"TARGET_AVX"
@@ -11240,16 +13472,24 @@
switch (which_alternative)
{
case 0:
- return "vinsert<i128>\t{$0x1, %2, %t1, %0|%0, %t1, %2, 0x1}";
+ return "vinsert<i128>\t{$0x1, %2, %<concat_tg_mode>1, %0|%0, %<concat_tg_mode>1, %2, 0x1}";
case 1:
switch (get_attr_mode (insn))
{
+ case MODE_V16SF:
+ return "vmovaps\t{%1, %t0|%t0, %1}";
+ case MODE_V8DF:
+ return "vmovapd\t{%1, %t0|%t0, %1}";
case MODE_V8SF:
return "vmovaps\t{%1, %x0|%x0, %1}";
case MODE_V4DF:
return "vmovapd\t{%1, %x0|%x0, %1}";
- default:
+ case MODE_XI:
+ return "vmovdqa\t{%1, %t0|%t0, %1}";
+ case MODE_OI:
return "vmovdqa\t{%1, %x0|%x0, %1}";
+ default:
+ gcc_unreachable ();
}
default:
gcc_unreachable ();
@@ -11258,7 +13498,7 @@
[(set_attr "type" "sselog,ssemov")
(set_attr "prefix_extra" "1,*")
(set_attr "length_immediate" "1,*")
- (set_attr "prefix" "vex")
+ (set_attr "prefix" "maybe_evex")
(set_attr "mode" "<sseinsnmode>")])
(define_insn "vcvtph2ps"
@@ -11295,6 +13535,16 @@
(set_attr "btver2_decode" "double")
(set_attr "mode" "V8SF")])
+(define_insn "avx512f_vcvtph2ps512"
+ [(set (match_operand:V16SF 0 "register_operand" "=v")
+ (unspec:V16SF [(match_operand:V16HI 1 "nonimmediate_operand" "vm")]
+ UNSPEC_VCVTPH2PS))]
+ "TARGET_AVX512F"
+ "vcvtph2ps\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "V16SF")])
+
(define_expand "vcvtps2ph"
[(set (match_operand:V8HI 0 "register_operand")
(vec_concat:V8HI
@@ -11341,24 +13591,37 @@
(set_attr "btver2_decode" "vector")
(set_attr "mode" "V8SF")])
+(define_insn "avx512f_vcvtps2ph512"
+ [(set (match_operand:V16HI 0 "nonimmediate_operand" "=vm")
+ (unspec:V16HI [(match_operand:V16SF 1 "register_operand" "v")
+ (match_operand:SI 2 "const_0_to_255_operand" "N")]
+ UNSPEC_VCVTPS2PH))]
+ "TARGET_AVX512F"
+ "vcvtps2ph\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "V16SF")])
+
;; For gather* insn patterns
(define_mode_iterator VEC_GATHER_MODE
[V2DI V2DF V4DI V4DF V4SI V4SF V8SI V8SF])
(define_mode_attr VEC_GATHER_IDXSI
- [(V2DI "V4SI") (V2DF "V4SI")
- (V4DI "V4SI") (V4DF "V4SI")
- (V4SI "V4SI") (V4SF "V4SI")
- (V8SI "V8SI") (V8SF "V8SI")])
+ [(V2DI "V4SI") (V4DI "V4SI") (V8DI "V8SI")
+ (V2DF "V4SI") (V4DF "V4SI") (V8DF "V8SI")
+ (V4SI "V4SI") (V8SI "V8SI") (V16SI "V16SI")
+ (V4SF "V4SI") (V8SF "V8SI") (V16SF "V16SI")])
+
(define_mode_attr VEC_GATHER_IDXDI
- [(V2DI "V2DI") (V2DF "V2DI")
- (V4DI "V4DI") (V4DF "V4DI")
- (V4SI "V2DI") (V4SF "V2DI")
- (V8SI "V4DI") (V8SF "V4DI")])
+ [(V2DI "V2DI") (V4DI "V4DI") (V8DI "V8DI")
+ (V2DF "V2DI") (V4DF "V4DI") (V8DF "V8DI")
+ (V4SI "V2DI") (V8SI "V4DI") (V16SI "V8DI")
+ (V4SF "V2DI") (V8SF "V4DI") (V16SF "V8DI")])
+
(define_mode_attr VEC_GATHER_SRCDI
- [(V2DI "V2DI") (V2DF "V2DF")
- (V4DI "V4DI") (V4DF "V4DF")
- (V4SI "V4SI") (V4SF "V4SF")
- (V8SI "V4SI") (V8SF "V4SF")])
+ [(V2DI "V2DI") (V4DI "V4DI") (V8DI "V8DI")
+ (V2DF "V2DF") (V4DF "V4DF") (V8DF "V8DF")
+ (V4SI "V4SI") (V8SI "V4SI") (V16SI "V8SI")
+ (V4SF "V4SF") (V8SF "V4SF") (V16SF "V8SF")])
(define_expand "avx2_gathersi<mode>"
[(parallel [(set (match_operand:VEC_GATHER_MODE 0 "register_operand")
@@ -11387,7 +13650,7 @@
[(match_operand:VEC_GATHER_MODE 2 "register_operand" "0")
(match_operator:<ssescalarmode> 7 "vsib_mem_operator"
[(unspec:P
- [(match_operand:P 3 "vsib_address_operand" "p")
+ [(match_operand:P 3 "vsib_address_operand" "Tv")
(match_operand:<VEC_GATHER_IDXSI> 4 "register_operand" "x")
(match_operand:SI 6 "const1248_operand" "n")]
UNSPEC_VSIBADDR)])
@@ -11407,7 +13670,7 @@
[(pc)
(match_operator:<ssescalarmode> 6 "vsib_mem_operator"
[(unspec:P
- [(match_operand:P 2 "vsib_address_operand" "p")
+ [(match_operand:P 2 "vsib_address_operand" "Tv")
(match_operand:<VEC_GATHER_IDXSI> 3 "register_operand" "x")
(match_operand:SI 5 "const1248_operand" "n")]
UNSPEC_VSIBADDR)])
@@ -11449,7 +13712,7 @@
[(match_operand:<VEC_GATHER_SRCDI> 2 "register_operand" "0")
(match_operator:<ssescalarmode> 7 "vsib_mem_operator"
[(unspec:P
- [(match_operand:P 3 "vsib_address_operand" "p")
+ [(match_operand:P 3 "vsib_address_operand" "Tv")
(match_operand:<VEC_GATHER_IDXDI> 4 "register_operand" "x")
(match_operand:SI 6 "const1248_operand" "n")]
UNSPEC_VSIBADDR)])
@@ -11469,7 +13732,7 @@
[(pc)
(match_operator:<ssescalarmode> 6 "vsib_mem_operator"
[(unspec:P
- [(match_operand:P 2 "vsib_address_operand" "p")
+ [(match_operand:P 2 "vsib_address_operand" "Tv")
(match_operand:<VEC_GATHER_IDXDI> 3 "register_operand" "x")
(match_operand:SI 5 "const1248_operand" "n")]
UNSPEC_VSIBADDR)])
@@ -11494,7 +13757,7 @@
[(match_operand:<VEC_GATHER_SRCDI> 2 "register_operand" "0")
(match_operator:<ssescalarmode> 7 "vsib_mem_operator"
[(unspec:P
- [(match_operand:P 3 "vsib_address_operand" "p")
+ [(match_operand:P 3 "vsib_address_operand" "Tv")
(match_operand:<VEC_GATHER_IDXDI> 4 "register_operand" "x")
(match_operand:SI 6 "const1248_operand" "n")]
UNSPEC_VSIBADDR)])
@@ -11517,7 +13780,7 @@
[(pc)
(match_operator:<ssescalarmode> 6 "vsib_mem_operator"
[(unspec:P
- [(match_operand:P 2 "vsib_address_operand" "p")
+ [(match_operand:P 2 "vsib_address_operand" "Tv")
(match_operand:<VEC_GATHER_IDXDI> 3 "register_operand" "x")
(match_operand:SI 5 "const1248_operand" "n")]
UNSPEC_VSIBADDR)])
@@ -11532,3 +13795,241 @@
[(set_attr "type" "ssemov")
(set_attr "prefix" "vex")
(set_attr "mode" "<sseinsnmode>")])
+
+(define_expand "avx512f_gathersi<mode>"
+ [(parallel [(set (match_operand:VI48F_512 0 "register_operand")
+ (unspec:VI48F_512
+ [(match_operand:VI48F_512 1 "register_operand")
+ (match_operand:<avx512fmaskmode> 4 "register_operand")
+ (mem:<ssescalarmode>
+ (match_par_dup 6
+ [(match_operand 2 "vsib_address_operand")
+ (match_operand:<VEC_GATHER_IDXSI> 3 "register_operand")
+ (match_operand:SI 5 "const1248_operand")]))]
+ UNSPEC_GATHER))
+ (clobber (match_scratch:<avx512fmaskmode> 7))])]
+ "TARGET_AVX512F"
+{
+ operands[6]
+ = gen_rtx_UNSPEC (Pmode, gen_rtvec (3, operands[2], operands[3],
+ operands[5]), UNSPEC_VSIBADDR);
+})
+
+(define_insn "*avx512f_gathersi<mode>"
+ [(set (match_operand:VI48F_512 0 "register_operand" "=&v")
+ (unspec:VI48F_512
+ [(match_operand:VI48F_512 1 "register_operand" "0")
+ (match_operand:<avx512fmaskmode> 7 "register_operand" "2")
+ (match_operator:<ssescalarmode> 6 "vsib_mem_operator"
+ [(unspec:P
+ [(match_operand:P 4 "vsib_address_operand" "Tv")
+ (match_operand:<VEC_GATHER_IDXSI> 3 "register_operand" "v")
+ (match_operand:SI 5 "const1248_operand" "n")]
+ UNSPEC_VSIBADDR)])]
+ UNSPEC_GATHER))
+ (clobber (match_scratch:<avx512fmaskmode> 2 "=&k"))]
+ "TARGET_AVX512F"
+ "v<sseintprefix>gatherd<ssemodesuffix>\t{%6, %0%{%2%}|%0%{%2%}, %g6}"
+ [(set_attr "type" "ssemov")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<sseinsnmode>")])
+
+(define_insn "*avx512f_gathersi<mode>_2"
+ [(set (match_operand:VI48F_512 0 "register_operand" "=&v")
+ (unspec:VI48F_512
+ [(pc)
+ (match_operand:<avx512fmaskmode> 6 "register_operand" "1")
+ (match_operator:<ssescalarmode> 5 "vsib_mem_operator"
+ [(unspec:P
+ [(match_operand:P 3 "vsib_address_operand" "Tv")
+ (match_operand:<VEC_GATHER_IDXSI> 2 "register_operand" "v")
+ (match_operand:SI 4 "const1248_operand" "n")]
+ UNSPEC_VSIBADDR)])]
+ UNSPEC_GATHER))
+ (clobber (match_scratch:<avx512fmaskmode> 1 "=&k"))]
+ "TARGET_AVX512F"
+ "v<sseintprefix>gatherd<ssemodesuffix>\t{%5, %0%{%1%}|%0%{%1%}, %g5}"
+ [(set_attr "type" "ssemov")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<sseinsnmode>")])
+
+
+(define_expand "avx512f_gatherdi<mode>"
+ [(parallel [(set (match_operand:VI48F_512 0 "register_operand")
+ (unspec:VI48F_512
+ [(match_operand:<VEC_GATHER_SRCDI> 1 "register_operand")
+ (match_operand:QI 4 "register_operand")
+ (mem:<ssescalarmode>
+ (match_par_dup 6
+ [(match_operand 2 "vsib_address_operand")
+ (match_operand:<VEC_GATHER_IDXDI> 3 "register_operand")
+ (match_operand:SI 5 "const1248_operand")]))]
+ UNSPEC_GATHER))
+ (clobber (match_scratch:QI 7))])]
+ "TARGET_AVX512F"
+{
+ operands[6]
+ = gen_rtx_UNSPEC (Pmode, gen_rtvec (3, operands[2], operands[3],
+ operands[5]), UNSPEC_VSIBADDR);
+})
+
+(define_insn "*avx512f_gatherdi<mode>"
+ [(set (match_operand:VI48F_512 0 "register_operand" "=&v")
+ (unspec:VI48F_512
+ [(match_operand:<VEC_GATHER_SRCDI> 1 "register_operand" "0")
+ (match_operand:QI 7 "register_operand" "2")
+ (match_operator:<ssescalarmode> 6 "vsib_mem_operator"
+ [(unspec:P
+ [(match_operand:P 4 "vsib_address_operand" "Tv")
+ (match_operand:<VEC_GATHER_IDXDI> 3 "register_operand" "v")
+ (match_operand:SI 5 "const1248_operand" "n")]
+ UNSPEC_VSIBADDR)])]
+ UNSPEC_GATHER))
+ (clobber (match_scratch:QI 2 "=&k"))]
+ "TARGET_AVX512F"
+ "v<sseintprefix>gatherq<ssemodesuffix>\t{%6, %1%{%2%}|%1%{%2%}, %g6}"
+ [(set_attr "type" "ssemov")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<sseinsnmode>")])
+
+(define_insn "*avx512f_gatherdi<mode>_2"
+ [(set (match_operand:VI48F_512 0 "register_operand" "=&v")
+ (unspec:VI48F_512
+ [(pc)
+ (match_operand:QI 6 "register_operand" "1")
+ (match_operator:<ssescalarmode> 5 "vsib_mem_operator"
+ [(unspec:P
+ [(match_operand:P 3 "vsib_address_operand" "Tv")
+ (match_operand:<VEC_GATHER_IDXDI> 2 "register_operand" "v")
+ (match_operand:SI 4 "const1248_operand" "n")]
+ UNSPEC_VSIBADDR)])]
+ UNSPEC_GATHER))
+ (clobber (match_scratch:QI 1 "=&k"))]
+ "TARGET_AVX512F"
+{
+ if (<MODE>mode != <VEC_GATHER_SRCDI>mode)
+ return "v<sseintprefix>gatherq<ssemodesuffix>\t{%5, %t0%{%1%}|%t0%{%1%}, %g5}";
+ return "v<sseintprefix>gatherq<ssemodesuffix>\t{%5, %0%{%1%}|%0%{%1%}, %g5}";
+}
+ [(set_attr "type" "ssemov")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<sseinsnmode>")])
+
+(define_expand "avx512f_scattersi<mode>"
+ [(parallel [(set (mem:VI48F_512
+ (match_par_dup 5
+ [(match_operand 0 "vsib_address_operand")
+ (match_operand:<VEC_GATHER_IDXSI> 2 "register_operand")
+ (match_operand:SI 4 "const1248_operand")]))
+ (unspec:VI48F_512
+ [(match_operand:<avx512fmaskmode> 1 "register_operand")
+ (match_operand:VI48F_512 3 "register_operand")]
+ UNSPEC_SCATTER))
+ (clobber (match_scratch:<avx512fmaskmode> 6))])]
+ "TARGET_AVX512F"
+{
+ operands[5]
+ = gen_rtx_UNSPEC (Pmode, gen_rtvec (3, operands[0], operands[2],
+ operands[4]), UNSPEC_VSIBADDR);
+})
+
+(define_insn "*avx512f_scattersi<mode>"
+ [(set (match_operator:VI48F_512 5 "vsib_mem_operator"
+ [(unspec:P
+ [(match_operand:P 0 "vsib_address_operand" "Tv")
+ (match_operand:<VEC_GATHER_IDXSI> 2 "register_operand" "v")
+ (match_operand:SI 4 "const1248_operand" "n")]
+ UNSPEC_VSIBADDR)])
+ (unspec:VI48F_512
+ [(match_operand:<avx512fmaskmode> 6 "register_operand" "1")
+ (match_operand:VI48F_512 3 "register_operand" "v")]
+ UNSPEC_SCATTER))
+ (clobber (match_scratch:<avx512fmaskmode> 1 "=&k"))]
+ "TARGET_AVX512F"
+ "v<sseintprefix>scatterd<ssemodesuffix>\t{%3, %5%{%1%}|%5%{%1%}, %3}"
+ [(set_attr "type" "ssemov")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<sseinsnmode>")])
+
+(define_expand "avx512f_scatterdi<mode>"
+ [(parallel [(set (mem:VI48F_512
+ (match_par_dup 5
+ [(match_operand 0 "vsib_address_operand")
+ (match_operand:V8DI 2 "register_operand")
+ (match_operand:SI 4 "const1248_operand")]))
+ (unspec:VI48F_512
+ [(match_operand:QI 1 "register_operand")
+ (match_operand:<VEC_GATHER_SRCDI> 3 "register_operand")]
+ UNSPEC_SCATTER))
+ (clobber (match_scratch:QI 6))])]
+ "TARGET_AVX512F"
+{
+ operands[5]
+ = gen_rtx_UNSPEC (Pmode, gen_rtvec (3, operands[0], operands[2],
+ operands[4]), UNSPEC_VSIBADDR);
+})
+
+(define_insn "*avx512f_scatterdi<mode>"
+ [(set (match_operator:VI48F_512 5 "vsib_mem_operator"
+ [(unspec:P
+ [(match_operand:P 0 "vsib_address_operand" "Tv")
+ (match_operand:V8DI 2 "register_operand" "v")
+ (match_operand:SI 4 "const1248_operand" "n")]
+ UNSPEC_VSIBADDR)])
+ (unspec:VI48F_512
+ [(match_operand:QI 6 "register_operand" "1")
+ (match_operand:<VEC_GATHER_SRCDI> 3 "register_operand" "v")]
+ UNSPEC_SCATTER))
+ (clobber (match_scratch:QI 1 "=&k"))]
+ "TARGET_AVX512F"
+ "v<sseintprefix>scatterq<ssemodesuffix>\t{%3, %5%{%1%}|%5%{%1%}, %3}"
+ [(set_attr "type" "ssemov")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<sseinsnmode>")])
+
+(define_insn "avx512f_getmant<mode>"
+ [(set (match_operand:VF_512 0 "register_operand" "=v")
+ (unspec:VF_512
+ [(match_operand:VF_512 1 "nonimmediate_operand" "vm")
+ (match_operand:SI 2 "const_0_to_15_operand")]
+ UNSPEC_GETMANT))]
+ "TARGET_AVX512F"
+ "vgetmant<ssemodesuffix>\t{%2, %1, %0|%0, %1, %2}";
+ [(set_attr "prefix" "evex")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "avx512f_getmant<mode>"
+ [(set (match_operand:VF_128 0 "register_operand" "=v")
+ (vec_merge:VF_128
+ (unspec:VF_128
+ [(match_operand:VF_128 1 "register_operand" "v")
+ (match_operand:VF_128 2 "nonimmediate_operand" "vm")
+ (match_operand:SI 3 "const_0_to_15_operand")]
+ UNSPEC_GETMANT)
+ (match_dup 1)
+ (const_int 1)))]
+ "TARGET_AVX512F"
+ "vgetmant<ssescalarmodesuffix>\t{%3, %2, %1, %0|%0, %1, %2, %3}";
+ [(set_attr "prefix" "evex")
+ (set_attr "mode" "<ssescalarmode>")])
+
+(define_insn "clz<mode>2"
+ [(set (match_operand:VI48_512 0 "register_operand" "=v")
+ (clz:VI48_512
+ (match_operand:VI48_512 1 "nonimmediate_operand" "vm")))]
+ "TARGET_AVX512CD"
+ "vplzcnt<ssemodesuffix>\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sse")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<sseinsnmode>")])
+
+(define_insn "conflict<mode>"
+ [(set (match_operand:VI48_512 0 "register_operand" "=v")
+ (unspec:VI48_512
+ [(match_operand:VI48_512 1 "nonimmediate_operand" "vm")]
+ UNSPEC_CONFLICT))]
+ "TARGET_AVX512CD"
+ "vpconflict<ssemodesuffix>\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sse")
+ (set_attr "prefix" "evex")
+ (set_attr "mode" "<sseinsnmode>")])
diff --git a/gcc/config/i386/sync.md b/gcc/config/i386/sync.md
index 9e5835662e1..8408a2bfe43 100644
--- a/gcc/config/i386/sync.md
+++ b/gcc/config/i386/sync.md
@@ -430,10 +430,21 @@
const char *xchg = "xchg{<imodesuffix>}\t%%<regprefix>bx, %5";
if (swap)
- output_asm_insn (xchg, operands);
+ {
+ output_asm_insn (xchg, operands);
+ if (ix86_emit_cfi ())
+ {
+ output_asm_insn (".cfi_remember_state", operands);
+ output_asm_insn (".cfi_register\t%%<regprefix>bx, %5", operands);
+ }
+ }
output_asm_insn ("lock{%;} %K7cmpxchg<doublemodesuffix>b\t%2", operands);
if (swap)
- output_asm_insn (xchg, operands);
+ {
+ output_asm_insn (xchg, operands);
+ if (ix86_emit_cfi ())
+ output_asm_insn (".cfi_restore_state", operands);
+ }
return "";
})
diff --git a/gcc/config/i386/t-i386 b/gcc/config/i386/t-i386
index 07624cc575e..1a76c4152f6 100644
--- a/gcc/config/i386/t-i386
+++ b/gcc/config/i386/t-i386
@@ -16,22 +16,9 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-i386.o: $(CONFIG_H) $(SYSTEM_H) coretypes.h dumpfile.h $(TM_H) \
- $(RTL_H) $(TREE_H) $(TM_P_H) $(REGS_H) hard-reg-set.h \
- $(REAL_H) insn-config.h conditions.h output.h insn-codes.h \
- $(INSN_ATTR_H) $(FLAGS_H) $(C_COMMON_H) except.h $(FUNCTION_H) \
- $(RECOG_H) $(EXPR_H) $(OPTABS_H) toplev.h $(BASIC_BLOCK_H) \
- $(GGC_H) $(TARGET_H) $(TARGET_DEF_H) langhooks.h $(CGRAPH_H) \
- $(TREE_GIMPLE_H) $(DWARF2_H) $(DF_H) tm-constrs.h $(PARAMS_H) \
- i386-builtin-types.inc debug.h dwarf2out.h sbitmap.h $(FIBHEAP_H) \
- $(OPTS_H) $(DIAGNOSTIC_H) $(COMMON_TARGET_H) $(CONTEXT_H) $(PASS_MANAGER_H)
-
-i386-c.o: $(srcdir)/config/i386/i386-c.c \
- $(srcdir)/config/i386/i386-protos.h $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(TREE_H) $(TM_P_H) $(FLAGS_H) $(C_COMMON_H) $(GGC_H) \
- $(TARGET_H) $(TARGET_DEF_H) $(CPPLIB_H) $(C_PRAGMA_H)
- $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
- $(srcdir)/config/i386/i386-c.c
+i386-c.o: $(srcdir)/config/i386/i386-c.c i386-builtin-types.inc
+ $(COMPILE) $<
+ $(POSTCOMPILE)
i386-builtin-types.inc: s-i386-bt ; @true
diff --git a/gcc/config/i386/t-rtems b/gcc/config/i386/t-rtems
index 6161ec10090..fef4c22e9c1 100644
--- a/gcc/config/i386/t-rtems
+++ b/gcc/config/i386/t-rtems
@@ -17,11 +17,10 @@
# <http://www.gnu.org/licenses/>.
#
-MULTILIB_OPTIONS = mtune=i486/mtune=pentium/mtune=pentiumpro \
-msoft-float
+MULTILIB_OPTIONS = mtune=i486/mtune=pentium/mtune=pentiumpro msoft-float
MULTILIB_DIRNAMES= m486 mpentium mpentiumpro soft-float
-MULTILIB_MATCHES = msoft-float=mno-m80387
-MULTILIB_MATCHES += mtune?pentium=mtune?k6 mtune?pentiumpro=mtune?mathlon
+MULTILIB_MATCHES = msoft-float=mno-80387
+MULTILIB_MATCHES += mtune?pentium=mtune?k6 mtune?pentiumpro=mtune?athlon
MULTILIB_EXCEPTIONS = \
mtune=pentium/*msoft-float* \
mtune=pentiumpro/*msoft-float*
diff --git a/gcc/config/i386/winnt.c b/gcc/config/i386/winnt.c
index 8cf6b3c527a..94155d89a7f 100644
--- a/gcc/config/i386/winnt.c
+++ b/gcc/config/i386/winnt.c
@@ -35,6 +35,7 @@ along with GCC; see the file COPYING3. If not see
#include "ggc.h"
#include "target.h"
#include "except.h"
+#include "gimple.h"
#include "lto-streamer.h"
/* i386/PE specific attribute support.
@@ -1178,10 +1179,10 @@ i386_pe_seh_unwind_emit (FILE *asm_out_file, rtx insn)
for (note = REG_NOTES (insn); note ; note = XEXP (note, 1))
{
- pat = XEXP (note, 0);
switch (REG_NOTE_KIND (note))
{
case REG_FRAME_RELATED_EXPR:
+ pat = XEXP (note, 0);
goto found;
case REG_CFA_DEF_CFA:
@@ -1195,6 +1196,7 @@ i386_pe_seh_unwind_emit (FILE *asm_out_file, rtx insn)
gcc_unreachable ();
case REG_CFA_ADJUST_CFA:
+ pat = XEXP (note, 0);
if (pat == NULL)
{
pat = PATTERN (insn);
@@ -1206,6 +1208,7 @@ i386_pe_seh_unwind_emit (FILE *asm_out_file, rtx insn)
break;
case REG_CFA_OFFSET:
+ pat = XEXP (note, 0);
if (pat == NULL)
pat = single_set (insn);
seh_cfa_offset (asm_out_file, seh, pat);
diff --git a/gcc/config/i386/x-darwin b/gcc/config/i386/x-darwin
index f0196bac41d..4967d695ce9 100644
--- a/gcc/config/i386/x-darwin
+++ b/gcc/config/i386/x-darwin
@@ -1,4 +1,3 @@
-host-i386-darwin.o : $(srcdir)/config/i386/host-i386-darwin.c \
- $(CONFIG_H) $(SYSTEM_H) coretypes.h hosthooks.h $(HOSTHOOKS_DEF_H) \
- config/host-darwin.h
- $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
+host-i386-darwin.o : $(srcdir)/config/i386/host-i386-darwin.c
+ $(COMPILE) $<
+ $(POSTCOMPILE)
diff --git a/gcc/config/i386/x-i386 b/gcc/config/i386/x-i386
index 2bf8fed5db5..1f3db1d19cf 100644
--- a/gcc/config/i386/x-i386
+++ b/gcc/config/i386/x-i386
@@ -1,4 +1,3 @@
-driver-i386.o : $(srcdir)/config/i386/driver-i386.c \
- $(srcdir)/config/i386/cpuid.h \
- $(CONFIG_H) $(SYSTEM_H) $(TM_H) coretypes.h
- $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
+driver-i386.o : $(srcdir)/config/i386/driver-i386.c
+ $(COMPILE) $<
+ $(POSTCOMPILE)
diff --git a/gcc/config/i386/x86-tune.def b/gcc/config/i386/x86-tune.def
index fc19df19d79..23879f9ec18 100644
--- a/gcc/config/i386/x86-tune.def
+++ b/gcc/config/i386/x86-tune.def
@@ -18,213 +18,488 @@ 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/>. */
-/* X86_TUNE_USE_LEAVE: Leave does not affect Nocona SPEC2000 results
- negatively, so enabling for Generic64 seems like good code size
- tradeoff. We can't enable it for 32bit generic because it does not
- work well with PPro base chips. */
-DEF_TUNE (X86_TUNE_USE_LEAVE, "use_leave",
- m_386 | m_CORE_ALL | m_K6_GEODE | m_AMD_MULTIPLE | m_GENERIC)
-DEF_TUNE (X86_TUNE_PUSH_MEMORY, "push_memory",
- m_386 | m_P4_NOCONA | m_CORE_ALL | m_K6_GEODE | m_AMD_MULTIPLE
+/* Tuning for a given CPU XXXX consists of:
+ - adding new CPU into:
+ - adding PROCESSOR_XXX to processor_type (in i386.h)
+ - possibly adding XXX into CPU attribute in i386.md
+ - adding XXX to processor_alias_table (in i386.c)
+ - introducing ix86_XXX_cost in i386.c
+ - Stringop generation table can be build based on test_stringop
+ - script (once rest of tuning is complete)
+ - designing a scheduler model in
+ - XXXX.md file
+ - Updating ix86_issue_rate and ix86_adjust_cost in i386.md
+ - possibly updating ia32_multipass_dfa_lookahead, ix86_sched_reorder
+ and ix86_sched_init_global if those tricks are needed.
+ - Tunning the flags bellow. Those are split into sections and each
+ section is very roughly ordered by importance. */
+
+/*****************************************************************************/
+/* Scheduling flags. */
+/*****************************************************************************/
+
+/* X86_TUNE_SCHEDULE: Enable scheduling. */
+DEF_TUNE (X86_TUNE_SCHEDULE, "schedule",
+ m_PENT | m_PPRO | m_CORE_ALL | m_ATOM | m_SLM | m_K6_GEODE
+ | m_AMD_MULTIPLE | m_GENERIC)
+
+/* X86_TUNE_PARTIAL_REG_DEPENDENCY: Enable more register renaming
+ on modern chips. Preffer stores affecting whole integer register
+ over partial stores. For example preffer MOVZBL or MOVQ to load 8bit
+ value over movb. */
+DEF_TUNE (X86_TUNE_PARTIAL_REG_DEPENDENCY, "partial_reg_dependency",
+ m_P4_NOCONA | m_CORE_ALL | m_ATOM | m_SLM | m_AMD_MULTIPLE
| m_GENERIC)
-DEF_TUNE (X86_TUNE_ZERO_EXTEND_WITH_AND, "zero_extend_with_and", m_486 | m_PENT)
-DEF_TUNE (X86_TUNE_UNROLL_STRLEN, "unroll_strlen",
- m_486 | m_PENT | m_PPRO | m_ATOM | m_SLM | m_CORE_ALL | m_K6
- | m_AMD_MULTIPLE | m_GENERIC)
-/* X86_TUNE_BRANCH_PREDICTION_HINTS: Branch hints were put in P4 based
- on simulation result. But after P4 was made, no performance benefit
- was observed with branch hints. It also increases the code size.
- As a result, icc never generates branch hints. */
-DEF_TUNE (X86_TUNE_BRANCH_PREDICTION_HINTS, "branch_prediction_hints", 0)
-DEF_TUNE (X86_TUNE_DOUBLE_WITH_ADD, "double_with_add", ~m_386)
-DEF_TUNE (X86_TUNE_USE_SAHF, "use_sahf",
- m_PPRO | m_P4_NOCONA | m_CORE_ALL | m_ATOM | m_SLM | m_K6_GEODE
- | m_K8 | m_AMDFAM10 | m_BDVER | m_BTVER | m_GENERIC)
+
+/* X86_TUNE_SSE_PARTIAL_REG_DEPENDENCY: This knob promotes all store
+ destinations to be 128bit to allow register renaming on 128bit SSE units,
+ but usually results in one extra microop on 64bit SSE units.
+ Experimental results shows that disabling this option on P4 brings over 20%
+ SPECfp regression, while enabling it on K8 brings roughly 2.4% regression
+ that can be partly masked by careful scheduling of moves. */
+DEF_TUNE (X86_TUNE_SSE_PARTIAL_REG_DEPENDENCY, "sse_partial_reg_dependency",
+ m_PPRO | m_P4_NOCONA | m_CORE_ALL | m_ATOM | m_SLM | m_AMDFAM10
+ | m_BDVER | m_GENERIC)
+
+/* X86_TUNE_SSE_SPLIT_REGS: Set for machines where the type and dependencies
+ are resolved on SSE register parts instead of whole registers, so we may
+ maintain just lower part of scalar values in proper format leaving the
+ upper part undefined. */
+DEF_TUNE (X86_TUNE_SSE_SPLIT_REGS, "sse_split_regs", m_ATHLON_K8)
+
+/* X86_TUNE_PARTIAL_FLAG_REG_STALL: this flag disables use of of flags
+ set by instructions affecting just some flags (in particular shifts).
+ This is because Core2 resolves dependencies on whole flags register
+ and such sequences introduce false dependency on previous instruction
+ setting full flags.
+
+ The flags does not affect generation of INC and DEC that is controlled
+ by X86_TUNE_USE_INCDEC.
+
+ This flag may be dropped from generic once core2-corei5 machines are
+ rare enough. */
+DEF_TUNE (X86_TUNE_PARTIAL_FLAG_REG_STALL, "partial_flag_reg_stall",
+ m_CORE2 | m_GENERIC)
+
/* X86_TUNE_MOVX: Enable to zero extend integer registers to avoid
partial dependencies. */
DEF_TUNE (X86_TUNE_MOVX, "movx",
m_PPRO | m_P4_NOCONA | m_CORE_ALL | m_ATOM | m_SLM | m_GEODE
| m_AMD_MULTIPLE | m_GENERIC)
-/* X86_TUNE_PARTIAL_REG_STALL: We probably ought to watch for partial
- register stalls on Generic32 compilation setting as well. However
- in current implementation the partial register stalls are not eliminated
- very well - they can be introduced via subregs synthesized by combine
- and can happen in caller/callee saving sequences. */
-DEF_TUNE (X86_TUNE_PARTIAL_REG_STALL, "partial_reg_stall", m_PPRO)
-DEF_TUNE (X86_TUNE_PARTIAL_FLAG_REG_STALL, "partial_flag_reg_stall",
- m_CORE_ALL | m_GENERIC)
-/* X86_TUNE_LCP_STALL: Avoid an expensive length-changing prefix stall
- * on 16-bit immediate moves into memory on Core2 and Corei7. */
-DEF_TUNE (X86_TUNE_LCP_STALL, "lcp_stall", m_CORE_ALL | m_GENERIC)
-DEF_TUNE (X86_TUNE_USE_HIMODE_FIOP, "use_himode_fiop",
- m_386 | m_486 | m_K6_GEODE)
-DEF_TUNE (X86_TUNE_USE_SIMODE_FIOP, "use_simode_fiop",
- ~(m_PENT | m_PPRO | m_CORE_ALL | m_ATOM
- | m_SLM | m_AMD_MULTIPLE | m_GENERIC))
-DEF_TUNE (X86_TUNE_USE_MOV0, "use_mov0", m_K6)
-DEF_TUNE (X86_TUNE_USE_CLTD, "use_cltd", ~(m_PENT | m_ATOM | m_SLM | m_K6))
-/* X86_TUNE_USE_XCHGB: Use xchgb %rh,%rl instead of rolw/rorw $8,rx. */
-DEF_TUNE (X86_TUNE_USE_XCHGB, "use_xchgb", m_PENT4)
-DEF_TUNE (X86_TUNE_SPLIT_LONG_MOVES, "split_long_moves", m_PPRO)
-DEF_TUNE (X86_TUNE_READ_MODIFY_WRITE, "read_modify_write", ~m_PENT)
-DEF_TUNE (X86_TUNE_READ_MODIFY, "read_modify", ~(m_PENT | m_PPRO))
-DEF_TUNE (X86_TUNE_PROMOTE_QIMODE, "promote_qimode",
- m_386 | m_486 | m_PENT | m_CORE_ALL | m_ATOM | m_SLM
- | m_K6_GEODE | m_AMD_MULTIPLE | m_GENERIC)
-DEF_TUNE (X86_TUNE_FAST_PREFIX, "fast_prefix", ~(m_386 | m_486 | m_PENT))
-DEF_TUNE (X86_TUNE_SINGLE_STRINGOP, "single_stringop", m_386 | m_P4_NOCONA)
-DEF_TUNE (X86_TUNE_QIMODE_MATH, "qimode_math", ~0)
-/* X86_TUNE_HIMODE_MATH: On PPro this flag is meant to avoid partial
- register stalls. Just like X86_TUNE_PARTIAL_REG_STALL this option
- might be considered for Generic32 if our scheme for avoiding partial
- stalls was more effective. */
-DEF_TUNE (X86_TUNE_HIMODE_MATH, "himode_math", ~m_PPRO)
-DEF_TUNE (X86_TUNE_PROMOTE_QI_REGS, "promote_qi_regs", 0)
-DEF_TUNE (X86_TUNE_PROMOTE_HI_REGS, "promote_hi_regs", m_PPRO)
-/* X86_TUNE_SINGLE_POP: Enable if single pop insn is preferred
- over esp addition. */
-DEF_TUNE (X86_TUNE_SINGLE_POP, "single_pop", m_386 | m_486 | m_PENT | m_PPRO)
-/* X86_TUNE_DOUBLE_POP: Enable if double pop insn is preferred
- over esp addition. */
-DEF_TUNE (X86_TUNE_DOUBLE_POP, "double_pop", m_PENT)
+
+/* X86_TUNE_MEMORY_MISMATCH_STALL: Avoid partial stores that are followed by
+ full sized loads. */
+DEF_TUNE (X86_TUNE_MEMORY_MISMATCH_STALL, "memory_mismatch_stall",
+ m_P4_NOCONA | m_CORE_ALL | m_ATOM | m_SLM | m_AMD_MULTIPLE | m_GENERIC)
+
+/* X86_TUNE_FUSE_CMP_AND_BRANCH_32: Fuse compare with a subsequent
+ conditional jump instruction for 32 bit TARGET.
+ FIXME: revisit for generic. */
+DEF_TUNE (X86_TUNE_FUSE_CMP_AND_BRANCH_32, "fuse_cmp_and_branch_32",
+ m_CORE_ALL | m_BDVER)
+
+/* X86_TUNE_FUSE_CMP_AND_BRANCH_64: Fuse compare with a subsequent
+ conditional jump instruction for TARGET_64BIT.
+ FIXME: revisit for generic. */
+DEF_TUNE (X86_TUNE_FUSE_CMP_AND_BRANCH_64, "fuse_cmp_and_branch_64",
+ m_COREI7 | m_COREI7_AVX | m_HASWELL | m_BDVER)
+
+/* X86_TUNE_FUSE_CMP_AND_BRANCH_SOFLAGS: Fuse compare with a
+ subsequent conditional jump instruction when the condition jump
+ check sign flag (SF) or overflow flag (OF). */
+DEF_TUNE (X86_TUNE_FUSE_CMP_AND_BRANCH_SOFLAGS, "fuse_cmp_and_branch_soflags",
+ m_COREI7 | m_COREI7_AVX | m_HASWELL | m_BDVER)
+
+/* X86_TUNE_FUSE_ALU_AND_BRANCH: Fuse alu with a subsequent conditional
+ jump instruction when the alu instruction produces the CCFLAG consumed by
+ the conditional jump instruction. */
+DEF_TUNE (X86_TUNE_FUSE_ALU_AND_BRANCH, "fuse_alu_and_branch",
+ m_COREI7_AVX | m_HASWELL)
+
+/* X86_TUNE_REASSOC_INT_TO_PARALLEL: Try to produce parallel computations
+ during reassociation of integer computation. */
+DEF_TUNE (X86_TUNE_REASSOC_INT_TO_PARALLEL, "reassoc_int_to_parallel",
+ m_ATOM)
+
+/* X86_TUNE_REASSOC_FP_TO_PARALLEL: Try to produce parallel computations
+ during reassociation of fp computation. */
+DEF_TUNE (X86_TUNE_REASSOC_FP_TO_PARALLEL, "reassoc_fp_to_parallel",
+ m_ATOM | m_SLM | m_HASWELL | m_BDVER1 | m_BDVER2 | m_GENERIC)
+
+/*****************************************************************************/
+/* Function prologue, epilogue and function calling sequences. */
+/*****************************************************************************/
+
+/* X86_TUNE_ACCUMULATE_OUTGOING_ARGS: Allocate stack space for outgoing
+ arguments in prologue/epilogue instead of separately for each call
+ by push/pop instructions.
+ This increase code size by about 5% in 32bit mode, less so in 64bit mode
+ because parameters are passed in registers. It is considerable
+ win for targets without stack engine that prevents multple push operations
+ to happen in parallel.
+
+ FIXME: the flags is incorrectly enabled for amdfam10, Bulldozer,
+ Bobcat and Generic. This is because disabling it causes large
+ regression on mgrid due to IRA limitation leading to unecessary
+ use of the frame pointer in 32bit mode. */
+DEF_TUNE (X86_TUNE_ACCUMULATE_OUTGOING_ARGS, "accumulate_outgoing_args",
+ m_PPRO | m_P4_NOCONA | m_ATOM | m_SLM | m_AMD_MULTIPLE | m_GENERIC)
+
+/* X86_TUNE_PROLOGUE_USING_MOVE: Do not use push/pop in prologues that are
+ considered on critical path. */
+DEF_TUNE (X86_TUNE_PROLOGUE_USING_MOVE, "prologue_using_move",
+ m_PPRO | m_ATHLON_K8)
+
+/* X86_TUNE_PROLOGUE_USING_MOVE: Do not use push/pop in epilogues that are
+ considered on critical path. */
+DEF_TUNE (X86_TUNE_EPILOGUE_USING_MOVE, "epilogue_using_move",
+ m_PPRO | m_ATHLON_K8)
+
+/* X86_TUNE_USE_LEAVE: Use "leave" instruction in epilogues where it fits. */
+DEF_TUNE (X86_TUNE_USE_LEAVE, "use_leave",
+ m_386 | m_CORE_ALL | m_K6_GEODE | m_AMD_MULTIPLE | m_GENERIC)
+
+/* X86_TUNE_PUSH_MEMORY: Enable generation of "push mem" instructions.
+ Some chips, like 486 and Pentium works faster with separate load
+ and push instructions. */
+DEF_TUNE (X86_TUNE_PUSH_MEMORY, "push_memory",
+ m_386 | m_P4_NOCONA | m_CORE_ALL | m_K6_GEODE | m_AMD_MULTIPLE
+ | m_GENERIC)
+
/* X86_TUNE_SINGLE_PUSH: Enable if single push insn is preferred
over esp subtraction. */
DEF_TUNE (X86_TUNE_SINGLE_PUSH, "single_push", m_386 | m_486 | m_PENT
| m_K6_GEODE)
+
/* X86_TUNE_DOUBLE_PUSH. Enable if double push insn is preferred
over esp subtraction. */
DEF_TUNE (X86_TUNE_DOUBLE_PUSH, "double_push", m_PENT | m_K6_GEODE)
+
+/* X86_TUNE_SINGLE_POP: Enable if single pop insn is preferred
+ over esp addition. */
+DEF_TUNE (X86_TUNE_SINGLE_POP, "single_pop", m_386 | m_486 | m_PENT | m_PPRO)
+
+/* X86_TUNE_DOUBLE_POP: Enable if double pop insn is preferred
+ over esp addition. */
+DEF_TUNE (X86_TUNE_DOUBLE_POP, "double_pop", m_PENT)
+
+/*****************************************************************************/
+/* Branch predictor tuning */
+/*****************************************************************************/
+
+/* X86_TUNE_PAD_SHORT_FUNCTION: Make every function to be at least 4
+ instructions long. */
+DEF_TUNE (X86_TUNE_PAD_SHORT_FUNCTION, "pad_short_function", m_ATOM)
+
+/* X86_TUNE_PAD_RETURNS: Place NOP before every RET that is a destination
+ of conditional jump or directly preceded by other jump instruction.
+ This is important for AND K8-AMDFAM10 because the branch prediction
+ architecture expect at most one jump per 2 byte window. Failing to
+ pad returns leads to misaligned return stack. */
+DEF_TUNE (X86_TUNE_PAD_RETURNS, "pad_returns",
+ m_ATHLON_K8 | m_AMDFAM10 | m_GENERIC)
+
+/* X86_TUNE_FOUR_JUMP_LIMIT: Some CPU cores are not able to predict more
+ than 4 branch instructions in the 16 byte window. */
+DEF_TUNE (X86_TUNE_FOUR_JUMP_LIMIT, "four_jump_limit",
+ m_PPRO | m_P4_NOCONA | m_ATOM | m_SLM | m_ATHLON_K8 | m_AMDFAM10)
+
+/*****************************************************************************/
+/* Integer instruction selection tuning */
+/*****************************************************************************/
+
+/* X86_TUNE_SOFTWARE_PREFETCHING_BENEFICIAL: Enable software prefetching
+ at -O3. For the moment, the prefetching seems badly tuned for Intel
+ chips. */
+DEF_TUNE (X86_TUNE_SOFTWARE_PREFETCHING_BENEFICIAL, "software_prefetching_beneficial",
+ m_K6_GEODE | m_AMD_MULTIPLE)
+
+/* X86_TUNE_LCP_STALL: Avoid an expensive length-changing prefix stall
+ on 16-bit immediate moves into memory on Core2 and Corei7. */
+DEF_TUNE (X86_TUNE_LCP_STALL, "lcp_stall", m_CORE_ALL | m_GENERIC)
+
+/* X86_TUNE_READ_MODIFY: Enable use of read-modify instructions such
+ as "add mem, reg". */
+DEF_TUNE (X86_TUNE_READ_MODIFY, "read_modify", ~(m_PENT | m_PPRO))
+
+/* X86_TUNE_USE_INCDEC: Enable use of inc/dec instructions. */
+DEF_TUNE (X86_TUNE_USE_INCDEC, "use_incdec",
+ ~(m_P4_NOCONA | m_CORE_ALL | m_ATOM | m_SLM | m_GENERIC))
+
/* X86_TUNE_INTEGER_DFMODE_MOVES: Enable if integer moves are preferred
for DFmode copies */
DEF_TUNE (X86_TUNE_INTEGER_DFMODE_MOVES, "integer_dfmode_moves",
~(m_PPRO | m_P4_NOCONA | m_CORE_ALL | m_ATOM | m_SLM
| m_GEODE | m_AMD_MULTIPLE | m_GENERIC))
-DEF_TUNE (X86_TUNE_PARTIAL_REG_DEPENDENCY, "partial_reg_dependency",
- m_P4_NOCONA | m_CORE_ALL | m_ATOM | m_SLM | m_AMD_MULTIPLE
- | m_GENERIC)
-/* X86_TUNE_SSE_PARTIAL_REG_DEPENDENCY: In the Generic model we have a
- conflict here in between PPro/Pentium4 based chips that thread 128bit
- SSE registers as single units versus K8 based chips that divide SSE
- registers to two 64bit halves. This knob promotes all store destinations
- to be 128bit to allow register renaming on 128bit SSE units, but usually
- results in one extra microop on 64bit SSE units. Experimental results
- shows that disabling this option on P4 brings over 20% SPECfp regression,
- while enabling it on K8 brings roughly 2.4% regression that can be partly
- masked by careful scheduling of moves. */
-DEF_TUNE (X86_TUNE_SSE_PARTIAL_REG_DEPENDENCY, "sse_partial_reg_dependency",
- m_PPRO | m_P4_NOCONA | m_CORE_ALL | m_ATOM | m_SLM | m_AMDFAM10
- | m_BDVER | m_GENERIC)
+
+/* X86_TUNE_OPT_AGU: Optimize for Address Generation Unit. This flag
+ will impact LEA instruction selection. */
+DEF_TUNE (X86_TUNE_OPT_AGU, "opt_agu", m_ATOM | m_SLM)
+
+/* X86_TUNE_SLOW_IMUL_IMM32_MEM: Imul of 32-bit constant and memory is
+ vector path on AMD machines.
+ FIXME: Do we need to enable this for core? */
+DEF_TUNE (X86_TUNE_SLOW_IMUL_IMM32_MEM, "slow_imul_imm32_mem",
+ m_K8 | m_AMDFAM10)
+
+/* X86_TUNE_SLOW_IMUL_IMM8: Imul of 8-bit constant is vector path on AMD
+ machines.
+ FIXME: Do we need to enable this for core? */
+DEF_TUNE (X86_TUNE_SLOW_IMUL_IMM8, "slow_imul_imm8",
+ m_K8 | m_AMDFAM10)
+
+/* X86_TUNE_AVOID_MEM_OPND_FOR_CMOVE: Try to avoid memory operands for
+ a conditional move. */
+DEF_TUNE (X86_TUNE_AVOID_MEM_OPND_FOR_CMOVE, "avoid_mem_opnd_for_cmove",
+ m_ATOM | m_SLM)
+
+/* X86_TUNE_SINGLE_STRINGOP: Enable use of single string operations, such
+ as MOVS and STOS (without a REP prefix) to move/set sequences of bytes. */
+DEF_TUNE (X86_TUNE_SINGLE_STRINGOP, "single_stringop", m_386 | m_P4_NOCONA)
+
+/* X86_TUNE_MISALIGNED_MOVE_STRING_PRO_EPILOGUES: Enable generation of
+ compact prologues and epilogues by issuing a misaligned moves. This
+ requires target to handle misaligned moves and partial memory stalls
+ reasonably well.
+ FIXME: This may actualy be a win on more targets than listed here. */
+DEF_TUNE (X86_TUNE_MISALIGNED_MOVE_STRING_PRO_EPILOGUES,
+ "misaligned_move_string_pro_epilogues",
+ m_386 | m_486 | m_CORE_ALL | m_AMD_MULTIPLE | m_GENERIC)
+
+/* X86_TUNE_USE_SAHF: Controls use of SAHF. */
+DEF_TUNE (X86_TUNE_USE_SAHF, "use_sahf",
+ m_PPRO | m_P4_NOCONA | m_CORE_ALL | m_ATOM | m_SLM | m_K6_GEODE
+ | m_K8 | m_AMDFAM10 | m_BDVER | m_BTVER | m_GENERIC)
+
+/* X86_TUNE_USE_CLTD: Controls use of CLTD and CTQO instructions. */
+DEF_TUNE (X86_TUNE_USE_CLTD, "use_cltd", ~(m_PENT | m_ATOM | m_SLM | m_K6))
+
+/* X86_TUNE_USE_BT: Enable use of BT (bit test) instructions. */
+DEF_TUNE (X86_TUNE_USE_BT, "use_bt",
+ m_CORE_ALL | m_ATOM | m_SLM | m_AMD_MULTIPLE | m_GENERIC)
+
+/*****************************************************************************/
+/* 387 instruction selection tuning */
+/*****************************************************************************/
+
+/* X86_TUNE_USE_HIMODE_FIOP: Enables use of x87 instructions with 16bit
+ integer operand.
+ FIXME: Why this is disabled for modern chips? */
+DEF_TUNE (X86_TUNE_USE_HIMODE_FIOP, "use_himode_fiop",
+ m_386 | m_486 | m_K6_GEODE)
+
+/* X86_TUNE_USE_SIMODE_FIOP: Enables use of x87 instructions with 32bit
+ integer operand. */
+DEF_TUNE (X86_TUNE_USE_SIMODE_FIOP, "use_simode_fiop",
+ ~(m_PENT | m_PPRO | m_CORE_ALL | m_ATOM
+ | m_SLM | m_AMD_MULTIPLE | m_GENERIC))
+
+/* X86_TUNE_USE_FFREEP: Use freep instruction instead of fstp. */
+DEF_TUNE (X86_TUNE_USE_FFREEP, "use_ffreep", m_AMD_MULTIPLE)
+
+/* X86_TUNE_EXT_80387_CONSTANTS: Use fancy 80387 constants, such as PI. */
+DEF_TUNE (X86_TUNE_EXT_80387_CONSTANTS, "ext_80387_constants",
+ m_PPRO | m_P4_NOCONA | m_CORE_ALL | m_ATOM | m_SLM | m_K6_GEODE
+ | m_ATHLON_K8 | m_GENERIC)
+
+/*****************************************************************************/
+/* SSE instruction selection tuning */
+/*****************************************************************************/
+
+/* X86_TUNE_VECTORIZE_DOUBLE: Enable double precision vector
+ instructions. */
+DEF_TUNE (X86_TUNE_VECTORIZE_DOUBLE, "vectorize_double", ~m_ATOM)
+
+/* X86_TUNE_GENERAL_REGS_SSE_SPILL: Try to spill general regs to SSE
+ regs instead of memory. */
+DEF_TUNE (X86_TUNE_GENERAL_REGS_SSE_SPILL, "general_regs_sse_spill",
+ m_CORE_ALL)
+
+/* X86_TUNE_SSE_UNALIGNED_LOAD_OPTIMAL: Use movups for misaligned loads instead
+ of a sequence loading registers by parts. */
DEF_TUNE (X86_TUNE_SSE_UNALIGNED_LOAD_OPTIMAL, "sse_unaligned_load_optimal",
- m_COREI7 | m_AMDFAM10 | m_BDVER | m_BTVER | m_SLM)
+ m_COREI7 | m_COREI7_AVX | m_AMDFAM10 | m_BDVER | m_BTVER | m_SLM | m_GENERIC)
+
+/* X86_TUNE_SSE_UNALIGNED_STORE_OPTIMAL: Use movups for misaligned stores instead
+ of a sequence loading registers by parts. */
DEF_TUNE (X86_TUNE_SSE_UNALIGNED_STORE_OPTIMAL, "sse_unaligned_store_optimal",
- m_COREI7 | m_BDVER | m_SLM)
+ m_COREI7 | m_COREI7_AVX | m_BDVER | m_SLM | m_GENERIC)
+
+/* Use packed single precision instructions where posisble. I.e. movups instead
+ of movupd. */
DEF_TUNE (X86_TUNE_SSE_PACKED_SINGLE_INSN_OPTIMAL, "sse_packed_single_insn_optimal",
m_BDVER)
-/* X86_TUNE_SSE_SPLIT_REGS: Set for machines where the type and dependencies
- are resolved on SSE register parts instead of whole registers, so we may
- maintain just lower part of scalar values in proper format leaving the
- upper part undefined. */
-DEF_TUNE (X86_TUNE_SSE_SPLIT_REGS, "sse_split_regs", m_ATHLON_K8)
-DEF_TUNE (X86_TUNE_SSE_TYPELESS_STORES, "sse_typeless_stores", m_AMD_MULTIPLE)
-DEF_TUNE (X86_TUNE_SSE_LOAD0_BY_PXOR, "sse_load0_by_pxor", m_PPRO | m_P4_NOCONA)
-DEF_TUNE (X86_TUNE_MEMORY_MISMATCH_STALL, "memory_mismatch_stall",
- m_P4_NOCONA | m_CORE_ALL | m_ATOM | m_SLM | m_AMD_MULTIPLE | m_GENERIC)
-DEF_TUNE (X86_TUNE_PROLOGUE_USING_MOVE, "prologue_using_move",
- m_PPRO | m_ATHLON_K8)
-DEF_TUNE (X86_TUNE_EPILOGUE_USING_MOVE, "epilogue_using_move",
- m_PPRO | m_ATHLON_K8)
-DEF_TUNE (X86_TUNE_SHIFT1, "shift1", ~m_486)
-DEF_TUNE (X86_TUNE_USE_FFREEP, "use_ffreep", m_AMD_MULTIPLE)
+
+/* X86_TUNE_SSE_TYPELESS_STORES: Always movaps/movups for 128bit stores. */
+DEF_TUNE (X86_TUNE_SSE_TYPELESS_STORES, "sse_typeless_stores",
+ m_AMD_MULTIPLE | m_CORE_ALL | m_GENERIC)
+
+/* X86_TUNE_SSE_LOAD0_BY_PXOR: Always use pxor to load0 as opposed to
+ xorps/xorpd and other variants. */
+DEF_TUNE (X86_TUNE_SSE_LOAD0_BY_PXOR, "sse_load0_by_pxor",
+ m_PPRO | m_P4_NOCONA | m_CORE_ALL | m_BDVER | m_BTVER | m_GENERIC)
+
+/* X86_TUNE_INTER_UNIT_MOVES_TO_VEC: Enable moves in from integer
+ to SSE registers. If disabled, the moves will be done by storing
+ the value to memory and reloading. */
DEF_TUNE (X86_TUNE_INTER_UNIT_MOVES_TO_VEC, "inter_unit_moves_to_vec",
~(m_AMD_MULTIPLE | m_GENERIC))
+
+/* X86_TUNE_INTER_UNIT_MOVES_TO_VEC: Enable moves in from SSE
+ to integer registers. If disabled, the moves will be done by storing
+ the value to memory and reloading. */
DEF_TUNE (X86_TUNE_INTER_UNIT_MOVES_FROM_VEC, "inter_unit_moves_from_vec",
~m_ATHLON_K8)
+
+/* X86_TUNE_INTER_UNIT_CONVERSIONS: Enable float<->integer conversions
+ to use both SSE and integer registers at a same time.
+ FIXME: revisit importance of this for generic. */
DEF_TUNE (X86_TUNE_INTER_UNIT_CONVERSIONS, "inter_unit_conversions",
- ~(m_AMDFAM10 | m_BDVER ))
-/* X86_TUNE_FOUR_JUMP_LIMIT: Some CPU cores are not able to predict more
- than 4 branch instructions in the 16 byte window. */
-DEF_TUNE (X86_TUNE_FOUR_JUMP_LIMIT, "four_jump_limit",
- m_PPRO | m_P4_NOCONA | m_CORE_ALL | m_ATOM | m_SLM| m_AMD_MULTIPLE
- | m_GENERIC)
-DEF_TUNE (X86_TUNE_SCHEDULE, "schedule",
- m_PENT | m_PPRO | m_CORE_ALL | m_ATOM | m_SLM | m_K6_GEODE
- | m_AMD_MULTIPLE | m_GENERIC)
-DEF_TUNE (X86_TUNE_USE_BT, "use_bt",
- m_CORE_ALL | m_ATOM | m_SLM | m_AMD_MULTIPLE | m_GENERIC)
-DEF_TUNE (X86_TUNE_USE_INCDEC, "use_incdec",
- ~(m_P4_NOCONA | m_CORE_ALL | m_ATOM | m_SLM | m_GENERIC))
-DEF_TUNE (X86_TUNE_PAD_RETURNS, "pad_returns",
- m_CORE_ALL | m_AMD_MULTIPLE | m_GENERIC)
-DEF_TUNE (X86_TUNE_PAD_SHORT_FUNCTION, "pad_short_function", m_ATOM)
-DEF_TUNE (X86_TUNE_EXT_80387_CONSTANTS, "ext_80387_constants",
- m_PPRO | m_P4_NOCONA | m_CORE_ALL | m_ATOM | m_SLM | m_K6_GEODE
- | m_ATHLON_K8 | m_GENERIC)
-DEF_TUNE (X86_TUNE_AVOID_VECTOR_DECODE, "avoid_vector_decode",
- m_CORE_ALL | m_K8 | m_GENERIC)
+ ~(m_AMDFAM10 | m_BDVER))
+
+/* X86_TUNE_SPLIT_MEM_OPND_FOR_FP_CONVERTS: Try to split memory operand for
+ fp converts to destination register. */
+DEF_TUNE (X86_TUNE_SPLIT_MEM_OPND_FOR_FP_CONVERTS, "split_mem_opnd_for_fp_converts",
+ m_SLM)
+
+/* X86_TUNE_USE_VECTOR_FP_CONVERTS: Prefer vector packed SSE conversion
+ from FP to FP. This form of instructions avoids partial write to the
+ destination. */
+DEF_TUNE (X86_TUNE_USE_VECTOR_FP_CONVERTS, "use_vector_fp_converts",
+ m_AMDFAM10)
+
+/* X86_TUNE_USE_VECTOR_CONVERTS: Prefer vector packed SSE conversion
+ from integer to FP. */
+DEF_TUNE (X86_TUNE_USE_VECTOR_CONVERTS, "use_vector_converts", m_AMDFAM10)
+
+/*****************************************************************************/
+/* AVX instruction selection tuning (some of SSE flags affects AVX, too) */
+/*****************************************************************************/
+
+/* X86_TUNE_AVX256_UNALIGNED_LOAD_OPTIMAL: if true, unaligned loads are
+ split. */
+DEF_TUNE (X86_TUNE_AVX256_UNALIGNED_LOAD_OPTIMAL, "256_unaligned_load_optimal",
+ ~(m_COREI7 | m_GENERIC))
+
+/* X86_TUNE_AVX256_UNALIGNED_STORE_OPTIMAL: if true, unaligned loads are
+ split. */
+DEF_TUNE (X86_TUNE_AVX256_UNALIGNED_STORE_OPTIMAL, "256_unaligned_load_optimal",
+ ~(m_COREI7 | m_BDVER | m_GENERIC))
+
+/* X86_TUNE_AVX128_OPTIMAL: Enable 128-bit AVX instruction generation for
+ the auto-vectorizer. */
+DEF_TUNE (X86_TUNE_AVX128_OPTIMAL, "avx128_optimal", m_BDVER | m_BTVER2)
+
+/*****************************************************************************/
+/* Historical relics: tuning flags that helps a specific old CPU designs */
+/*****************************************************************************/
+
+/* X86_TUNE_DOUBLE_WITH_ADD: Use add instead of sal to double value in
+ an integer register. */
+DEF_TUNE (X86_TUNE_DOUBLE_WITH_ADD, "double_with_add", ~m_386)
+
+/* X86_TUNE_ALWAYS_FANCY_MATH_387: controls use of fancy 387 operations,
+ such as fsqrt, fprem, fsin, fcos, fsincos etc.
+ Should be enabled for all targets that always has coprocesor. */
+DEF_TUNE (X86_TUNE_ALWAYS_FANCY_MATH_387, "always_fancy_math_387",
+ ~(m_386 | m_486))
+
+/* X86_TUNE_UNROLL_STRLEN: Produce (quite lame) unrolled sequence for
+ inline strlen. This affects only -minline-all-stringops mode. By
+ default we always dispatch to a library since our internal strlen
+ is bad. */
+DEF_TUNE (X86_TUNE_UNROLL_STRLEN, "unroll_strlen", ~m_386)
+
+/* X86_TUNE_SHIFT1: Enables use of short encoding of "sal reg" instead of
+ longer "sal $1, reg". */
+DEF_TUNE (X86_TUNE_SHIFT1, "shift1", ~m_486)
+
+/* X86_TUNE_ZERO_EXTEND_WITH_AND: Use AND instruction instead
+ of mozbl/movwl. */
+DEF_TUNE (X86_TUNE_ZERO_EXTEND_WITH_AND, "zero_extend_with_and", m_486 | m_PENT)
+
/* X86_TUNE_PROMOTE_HIMODE_IMUL: Modern CPUs have same latency for HImode
and SImode multiply, but 386 and 486 do HImode multiply faster. */
DEF_TUNE (X86_TUNE_PROMOTE_HIMODE_IMUL, "promote_himode_imul",
~(m_386 | m_486))
-/* X86_TUNE_SLOW_IMUL_IMM32_MEM: Imul of 32-bit constant and memory is
- vector path on AMD machines. */
-DEF_TUNE (X86_TUNE_SLOW_IMUL_IMM32_MEM, "slow_imul_imm32_mem",
- m_CORE_ALL | m_K8 | m_AMDFAM10 | m_BDVER | m_BTVER | m_GENERIC)
-/* X86_TUNE_SLOW_IMUL_IMM8: Imul of 8-bit constant is vector path on AMD
- machines. */
-DEF_TUNE (X86_TUNE_SLOW_IMUL_IMM8, "slow_imul_imm8",
- m_CORE_ALL | m_K8 | m_AMDFAM10 | m_BDVER | m_BTVER | m_GENERIC)
+
+/* X86_TUNE_FAST_PREFIX: Enable demoting some 32bit or 64bit arithmetic
+ into 16bit/8bit when resulting sequence is shorter. For example
+ for "and $-65536, reg" to 16bit store of 0. */
+DEF_TUNE (X86_TUNE_FAST_PREFIX, "fast_prefix", ~(m_386 | m_486 | m_PENT))
+
+/* X86_TUNE_READ_MODIFY_WRITE: Enable use of read modify write instructions
+ such as "add $1, mem". */
+DEF_TUNE (X86_TUNE_READ_MODIFY_WRITE, "read_modify_write", ~m_PENT)
+
/* X86_TUNE_MOVE_M1_VIA_OR: On pentiums, it is faster to load -1 via OR
than a MOV. */
DEF_TUNE (X86_TUNE_MOVE_M1_VIA_OR, "move_m1_via_or", m_PENT)
+
/* X86_TUNE_NOT_UNPAIRABLE: NOT is not pairable on Pentium, while XOR is,
but one byte longer. */
DEF_TUNE (X86_TUNE_NOT_UNPAIRABLE, "not_unpairable", m_PENT)
+
+/* X86_TUNE_PARTIAL_REG_STALL: Pentium pro, unlike later chips, handled
+ use of partial registers by renaming. This improved performance of 16bit
+ code where upper halves of registers are not used. It also leads to
+ an penalty whenever a 16bit store is followed by 32bit use. This flag
+ disables production of such sequences in common cases.
+ See also X86_TUNE_HIMODE_MATH.
+
+ In current implementation the partial register stalls are not eliminated
+ very well - they can be introduced via subregs synthesized by combine
+ and can happen in caller/callee saving sequences. */
+DEF_TUNE (X86_TUNE_PARTIAL_REG_STALL, "partial_reg_stall", m_PPRO)
+
+/* X86_TUNE_PROMOTE_QIMODE: When it is cheap, turn 8bit arithmetic to
+ corresponding 32bit arithmetic. */
+DEF_TUNE (X86_TUNE_PROMOTE_QIMODE, "promote_qimode",
+ ~m_PPRO)
+
+/* X86_TUNE_PROMOTE_HI_REGS: Same, but for 16bit artihmetic. Again we avoid
+ partial register stalls on PentiumPro targets. */
+DEF_TUNE (X86_TUNE_PROMOTE_HI_REGS, "promote_hi_regs", m_PPRO)
+
+/* X86_TUNE_HIMODE_MATH: Enable use of 16bit arithmetic.
+ On PPro this flag is meant to avoid partial register stalls. */
+DEF_TUNE (X86_TUNE_HIMODE_MATH, "himode_math", ~m_PPRO)
+
+/* X86_TUNE_SPLIT_LONG_MOVES: Avoid instructions moving immediates
+ directly to memory. */
+DEF_TUNE (X86_TUNE_SPLIT_LONG_MOVES, "split_long_moves", m_PPRO)
+
+/* X86_TUNE_USE_XCHGB: Use xchgb %rh,%rl instead of rolw/rorw $8,rx. */
+DEF_TUNE (X86_TUNE_USE_XCHGB, "use_xchgb", m_PENT4)
+
+/* X86_TUNE_USE_MOV0: Use "mov $0, reg" instead of "xor reg, reg" to clear
+ integer register. */
+DEF_TUNE (X86_TUNE_USE_MOV0, "use_mov0", m_K6)
+
/* X86_TUNE_NOT_VECTORMODE: On AMD K6, NOT is vector decoded with memory
operand that cannot be represented using a modRM byte. The XOR
replacement is long decoded, so this split helps here as well. */
DEF_TUNE (X86_TUNE_NOT_VECTORMODE, "not_vectormode", m_K6)
-/* X86_TUNE_USE_VECTOR_FP_CONVERTS: Prefer vector packed SSE conversion
- from FP to FP. */
-DEF_TUNE (X86_TUNE_USE_VECTOR_FP_CONVERTS, "use_vector_fp_converts",
- m_CORE_ALL | m_AMDFAM10 | m_GENERIC)
-/* X86_TUNE_USE_VECTOR_CONVERTS: Prefer vector packed SSE conversion
- from integer to FP. */
-DEF_TUNE (X86_TUNE_USE_VECTOR_CONVERTS, "use_vector_converts", m_AMDFAM10)
-/* X86_TUNE_FUSE_CMP_AND_BRANCH: Fuse a compare or test instruction
- with a subsequent conditional jump instruction into a single
- compare-and-branch uop. */
-DEF_TUNE (X86_TUNE_FUSE_CMP_AND_BRANCH, "fuse_cmp_and_branch", m_BDVER)
-/* X86_TUNE_OPT_AGU: Optimize for Address Generation Unit. This flag
- will impact LEA instruction selection. */
-DEF_TUNE (X86_TUNE_OPT_AGU, "opt_agu", m_ATOM | m_SLM)
-/* X86_TUNE_VECTORIZE_DOUBLE: Enable double precision vector
- instructions. */
-DEF_TUNE (X86_TUNE_VECTORIZE_DOUBLE, "vectorize_double", ~m_ATOM)
-/* X86_TUNE_SOFTWARE_PREFETCHING_BENEFICIAL: Enable software prefetching
- at -O3. For the moment, the prefetching seems badly tuned for Intel
- chips. */
-DEF_TUNE (X86_TUNE_SOFTWARE_PREFETCHING_BENEFICIAL, "software_prefetching_beneficial",
- m_K6_GEODE | m_AMD_MULTIPLE)
-/* X86_TUNE_AVX128_OPTIMAL: Enable 128-bit AVX instruction generation for
- the auto-vectorizer. */
-DEF_TUNE (X86_TUNE_AVX128_OPTIMAL, "avx128_optimal", m_BDVER | m_BTVER2)
-/* X86_TUNE_REASSOC_INT_TO_PARALLEL: Try to produce parallel computations
- during reassociation of integer computation. */
-DEF_TUNE (X86_TUNE_REASSOC_INT_TO_PARALLEL, "reassoc_int_to_parallel",
- m_ATOM)
-/* X86_TUNE_REASSOC_FP_TO_PARALLEL: Try to produce parallel computations
- during reassociation of fp computation. */
-DEF_TUNE (X86_TUNE_REASSOC_FP_TO_PARALLEL, "reassoc_fp_to_parallel",
- m_ATOM | m_SLM | m_HASWELL | m_BDVER1 | m_BDVER2)
-/* X86_TUNE_GENERAL_REGS_SSE_SPILL: Try to spill general regs to SSE
- regs instead of memory. */
-DEF_TUNE (X86_TUNE_GENERAL_REGS_SSE_SPILL, "general_regs_sse_spill",
- m_CORE_ALL)
-/* X86_TUNE_AVOID_MEM_OPND_FOR_CMOVE: Try to avoid memory operands for
- a conditional move. */
-DEF_TUNE (X86_TUNE_AVOID_MEM_OPND_FOR_CMOVE, "avoid_mem_opnd_for_cmove",
- m_ATOM | m_SLM)
-/* X86_TUNE_SPLIT_MEM_OPND_FOR_FP_CONVERTS: Try to split memory operand for
- fp converts to destination register. */
-DEF_TUNE (X86_TUNE_SPLIT_MEM_OPND_FOR_FP_CONVERTS, "split_mem_opnd_for_fp_converts",
- m_SLM)
+
+/* X86_TUNE_AVOID_VECTOR_DECODE: Enable splitters that avoid vector decoded
+ forms of instructions on K8 targets. */
+DEF_TUNE (X86_TUNE_AVOID_VECTOR_DECODE, "avoid_vector_decode",
+ m_K8)
+
+/*****************************************************************************/
+/* This never worked well before. */
+/*****************************************************************************/
+
+/* X86_TUNE_BRANCH_PREDICTION_HINTS: Branch hints were put in P4 based
+ on simulation result. But after P4 was made, no performance benefit
+ was observed with branch hints. It also increases the code size.
+ As a result, icc never generates branch hints. */
+DEF_TUNE (X86_TUNE_BRANCH_PREDICTION_HINTS, "branch_prediction_hints", 0)
+
+/* X86_TUNE_QIMODE_MATH: Enable use of 8bit arithmetic. */
+DEF_TUNE (X86_TUNE_QIMODE_MATH, "qimode_math", ~0)
+
+/* X86_TUNE_PROMOTE_QI_REGS: This enables generic code that promotes all 8bit
+ arithmetic to 32bit via PROMOTE_MODE macro. This code generation scheme
+ is usually used for RISC targets. */
+DEF_TUNE (X86_TUNE_PROMOTE_QI_REGS, "promote_qi_regs", 0)
diff --git a/gcc/config/ia64/hpux.h b/gcc/config/ia64/hpux.h
index ca592e4bc26..517132c8e63 100644
--- a/gcc/config/ia64/hpux.h
+++ b/gcc/config/ia64/hpux.h
@@ -92,7 +92,7 @@ do { \
#undef LIB_SPEC
#define LIB_SPEC \
"%{!shared: \
- %{mt|pthread:%{fopenmp:-lrt} -lpthread} \
+ %{mt|pthread:%{fopenmp|ftree-parallelize-loops=*:-lrt} -lpthread} \
%{p:%{!mlp64:-L/usr/lib/hpux32/libp} \
%{mlp64:-L/usr/lib/hpux64/libp} -lprof} \
%{pg:%{!mlp64:-L/usr/lib/hpux32/libp} \
diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c
index a128b19c7ca..1bf3e2fe928 100644
--- a/gcc/config/ia64/ia64.c
+++ b/gcc/config/ia64/ia64.c
@@ -620,6 +620,8 @@ static const struct attribute_spec ia64_attribute_table[] =
#undef TARGET_TRAMPOLINE_INIT
#define TARGET_TRAMPOLINE_INIT ia64_trampoline_init
+#undef TARGET_CAN_USE_DOLOOP_P
+#define TARGET_CAN_USE_DOLOOP_P can_use_doloop_if_innermost
#undef TARGET_INVALID_WITHIN_DOLOOP
#define TARGET_INVALID_WITHIN_DOLOOP hook_constcharptr_const_rtx_null
@@ -1754,7 +1756,7 @@ ia64_expand_compare (rtx *expr, rtx *op0, rtx *op1)
else if (TARGET_HPUX && GET_MODE (*op0) == TFmode)
{
enum qfcmp_magic {
- QCMP_INV = 1, /* Raise FP_INVALID on SNaN as a side effect. */
+ QCMP_INV = 1, /* Raise FP_INVALID on NaNs as a side effect. */
QCMP_UNORD = 2,
QCMP_EQ = 4,
QCMP_LT = 8,
@@ -1768,21 +1770,27 @@ ia64_expand_compare (rtx *expr, rtx *op0, rtx *op1)
switch (code)
{
/* 1 = equal, 0 = not equal. Equality operators do
- not raise FP_INVALID when given an SNaN operand. */
+ not raise FP_INVALID when given a NaN operand. */
case EQ: magic = QCMP_EQ; ncode = NE; break;
case NE: magic = QCMP_EQ; ncode = EQ; break;
/* isunordered() from C99. */
case UNORDERED: magic = QCMP_UNORD; ncode = NE; break;
case ORDERED: magic = QCMP_UNORD; ncode = EQ; break;
/* Relational operators raise FP_INVALID when given
- an SNaN operand. */
+ a NaN operand. */
case LT: magic = QCMP_LT |QCMP_INV; ncode = NE; break;
case LE: magic = QCMP_LT|QCMP_EQ|QCMP_INV; ncode = NE; break;
case GT: magic = QCMP_GT |QCMP_INV; ncode = NE; break;
case GE: magic = QCMP_GT|QCMP_EQ|QCMP_INV; ncode = NE; break;
- /* FUTURE: Implement UNEQ, UNLT, UNLE, UNGT, UNGE, LTGT.
- Expanders for buneq etc. weuld have to be added to ia64.md
- for this to be useful. */
+ /* Unordered relational operators do not raise FP_INVALID
+ when given a NaN operand. */
+ case UNLT: magic = QCMP_LT |QCMP_UNORD; ncode = NE; break;
+ case UNLE: magic = QCMP_LT|QCMP_EQ|QCMP_UNORD; ncode = NE; break;
+ case UNGT: magic = QCMP_GT |QCMP_UNORD; ncode = NE; break;
+ case UNGE: magic = QCMP_GT|QCMP_EQ|QCMP_UNORD; ncode = NE; break;
+ /* Not supported. */
+ case UNEQ:
+ case LTGT:
default: gcc_unreachable ();
}
@@ -3200,61 +3208,54 @@ gen_fr_restore_x (rtx dest, rtx src, rtx offset ATTRIBUTE_UNUSED)
#define BACKING_STORE_SIZE(N) ((N) > 0 ? ((N) + (N)/63 + 1) * 8 : 0)
/* Emit code to probe a range of stack addresses from FIRST to FIRST+SIZE,
- inclusive. These are offsets from the current stack pointer. SOL is the
- size of local registers. ??? This clobbers r2 and r3. */
+ inclusive. These are offsets from the current stack pointer. BS_SIZE
+ is the size of the backing store. ??? This clobbers r2 and r3. */
static void
-ia64_emit_probe_stack_range (HOST_WIDE_INT first, HOST_WIDE_INT size, int sol)
+ia64_emit_probe_stack_range (HOST_WIDE_INT first, HOST_WIDE_INT size,
+ int bs_size)
{
- /* On the IA-64 there is a second stack in memory, namely the Backing Store
- of the Register Stack Engine. We also need to probe it after checking
- that the 2 stacks don't overlap. */
- const int bs_size = BACKING_STORE_SIZE (sol);
rtx r2 = gen_rtx_REG (Pmode, GR_REG (2));
rtx r3 = gen_rtx_REG (Pmode, GR_REG (3));
-
- /* Detect collision of the 2 stacks if necessary. */
- if (bs_size > 0 || size > 0)
- {
- rtx p6 = gen_rtx_REG (BImode, PR_REG (6));
-
- emit_insn (gen_bsp_value (r3));
- emit_move_insn (r2, GEN_INT (-(first + size)));
-
- /* Compare current value of BSP and SP registers. */
- emit_insn (gen_rtx_SET (VOIDmode, p6,
- gen_rtx_fmt_ee (LTU, BImode,
- r3, stack_pointer_rtx)));
-
- /* Compute the address of the probe for the Backing Store (which grows
- towards higher addresses). We probe only at the first offset of
- the next page because some OS (eg Linux/ia64) only extend the
- backing store when this specific address is hit (but generate a SEGV
- on other address). Page size is the worst case (4KB). The reserve
- size is at least 4096 - (96 + 2) * 8 = 3312 bytes, which is enough.
- Also compute the address of the last probe for the memory stack
- (which grows towards lower addresses). */
- emit_insn (gen_rtx_SET (VOIDmode, r3, plus_constant (Pmode, r3, 4095)));
- emit_insn (gen_rtx_SET (VOIDmode, r2,
- gen_rtx_PLUS (Pmode, stack_pointer_rtx, r2)));
-
- /* Compare them and raise SEGV if the former has topped the latter. */
- emit_insn (gen_rtx_COND_EXEC (VOIDmode,
- gen_rtx_fmt_ee (NE, VOIDmode, p6,
- const0_rtx),
- gen_rtx_SET (VOIDmode, p6,
- gen_rtx_fmt_ee (GEU, BImode,
- r3, r2))));
- emit_insn (gen_rtx_SET (VOIDmode,
- gen_rtx_ZERO_EXTRACT (DImode, r3, GEN_INT (12),
- const0_rtx),
- const0_rtx));
- emit_insn (gen_rtx_COND_EXEC (VOIDmode,
- gen_rtx_fmt_ee (NE, VOIDmode, p6,
- const0_rtx),
- gen_rtx_TRAP_IF (VOIDmode, const1_rtx,
- GEN_INT (11))));
- }
+ rtx p6 = gen_rtx_REG (BImode, PR_REG (6));
+
+ /* On the IA-64 there is a second stack in memory, namely the Backing Store
+ of the Register Stack Engine. We also need to probe it after checking
+ that the 2 stacks don't overlap. */
+ emit_insn (gen_bsp_value (r3));
+ emit_move_insn (r2, GEN_INT (-(first + size)));
+
+ /* Compare current value of BSP and SP registers. */
+ emit_insn (gen_rtx_SET (VOIDmode, p6,
+ gen_rtx_fmt_ee (LTU, BImode,
+ r3, stack_pointer_rtx)));
+
+ /* Compute the address of the probe for the Backing Store (which grows
+ towards higher addresses). We probe only at the first offset of
+ the next page because some OS (eg Linux/ia64) only extend the
+ backing store when this specific address is hit (but generate a SEGV
+ on other address). Page size is the worst case (4KB). The reserve
+ size is at least 4096 - (96 + 2) * 8 = 3312 bytes, which is enough.
+ Also compute the address of the last probe for the memory stack
+ (which grows towards lower addresses). */
+ emit_insn (gen_rtx_SET (VOIDmode, r3, plus_constant (Pmode, r3, 4095)));
+ emit_insn (gen_rtx_SET (VOIDmode, r2,
+ gen_rtx_PLUS (Pmode, stack_pointer_rtx, r2)));
+
+ /* Compare them and raise SEGV if the former has topped the latter. */
+ emit_insn (gen_rtx_COND_EXEC (VOIDmode,
+ gen_rtx_fmt_ee (NE, VOIDmode, p6, const0_rtx),
+ gen_rtx_SET (VOIDmode, p6,
+ gen_rtx_fmt_ee (GEU, BImode,
+ r3, r2))));
+ emit_insn (gen_rtx_SET (VOIDmode,
+ gen_rtx_ZERO_EXTRACT (DImode, r3, GEN_INT (12),
+ const0_rtx),
+ const0_rtx));
+ emit_insn (gen_rtx_COND_EXEC (VOIDmode,
+ gen_rtx_fmt_ee (NE, VOIDmode, p6, const0_rtx),
+ gen_rtx_TRAP_IF (VOIDmode, const1_rtx,
+ GEN_INT (11))));
/* Probe the Backing Store if necessary. */
if (bs_size > 0)
@@ -3438,10 +3439,23 @@ ia64_expand_prologue (void)
current_function_static_stack_size = current_frame_info.total_size;
if (flag_stack_check == STATIC_BUILTIN_STACK_CHECK)
- ia64_emit_probe_stack_range (STACK_CHECK_PROTECT,
- current_frame_info.total_size,
- current_frame_info.n_input_regs
- + current_frame_info.n_local_regs);
+ {
+ HOST_WIDE_INT size = current_frame_info.total_size;
+ int bs_size = BACKING_STORE_SIZE (current_frame_info.n_input_regs
+ + current_frame_info.n_local_regs);
+
+ if (crtl->is_leaf && !cfun->calls_alloca)
+ {
+ if (size > PROBE_INTERVAL && size > STACK_CHECK_PROTECT)
+ ia64_emit_probe_stack_range (STACK_CHECK_PROTECT,
+ size - STACK_CHECK_PROTECT,
+ bs_size);
+ else if (size + bs_size > STACK_CHECK_PROTECT)
+ ia64_emit_probe_stack_range (STACK_CHECK_PROTECT, 0, bs_size);
+ }
+ else if (size + bs_size > 0)
+ ia64_emit_probe_stack_range (STACK_CHECK_PROTECT, size, bs_size);
+ }
if (dump_file)
{
@@ -5277,6 +5291,9 @@ ia64_print_operand (FILE * file, rtx x, int code)
case UNGE:
str = "nlt";
break;
+ case UNEQ:
+ case LTGT:
+ gcc_unreachable ();
default:
str = GET_RTX_NAME (GET_CODE (x));
break;
@@ -5454,7 +5471,7 @@ ia64_print_operand (FILE * file, rtx x, int code)
x = find_reg_note (current_output_insn, REG_BR_PROB, 0);
if (x)
{
- int pred_val = INTVAL (XEXP (x, 0));
+ int pred_val = XINT (x, 0);
/* Guess top and bottom 10% statically predicted. */
if (pred_val < REG_BR_PROB_BASE / 50
diff --git a/gcc/config/ia64/ia64.md b/gcc/config/ia64/ia64.md
index a26774d7a07..4d9d4e0129f 100644
--- a/gcc/config/ia64/ia64.md
+++ b/gcc/config/ia64/ia64.md
@@ -3956,18 +3956,11 @@
(define_expand "doloop_end"
[(use (match_operand 0 "" "")) ; loop pseudo
- (use (match_operand 1 "" "")) ; iterations; zero if unknown
- (use (match_operand 2 "" "")) ; max iterations
- (use (match_operand 3 "" "")) ; loop level
- (use (match_operand 4 "" "")) ; label
- (use (match_operand 5 "" ""))] ; flag: 1 if loop entered at top, else 0
+ (use (match_operand 1 "" ""))] ; label
""
{
- /* Only use cloop on innermost loops. */
- if (INTVAL (operands[3]) > 1)
- FAIL;
emit_jump_insn (gen_doloop_end_internal (gen_rtx_REG (DImode, AR_LC_REGNUM),
- operands[4]));
+ operands[1]));
DONE;
})
diff --git a/gcc/config/ia64/predicates.md b/gcc/config/ia64/predicates.md
index adfb15ff7b7..af7bc8ee4c2 100644
--- a/gcc/config/ia64/predicates.md
+++ b/gcc/config/ia64/predicates.md
@@ -568,9 +568,15 @@
(match_test "op == CONST0_RTX (GET_MODE (op))"))))
;; Return 1 if OP is a valid comparison operator for "cbranch" instructions.
+;; If we're assuming that FP operations cannot generate user-visible traps,
+;; then we can use the FP unordered-signaling instructions to implement the
+;; FP unordered-quiet comparison predicates.
(define_predicate "ia64_cbranch_operator"
- (ior (match_operand 0 "ordered_comparison_operator")
- (match_code "ordered,unordered")))
+ (if_then_else (match_test "flag_trapping_math")
+ (ior (match_operand 0 "ordered_comparison_operator")
+ (match_code "ordered,unordered"))
+ (and (match_operand 0 "comparison_operator")
+ (not (match_code "uneq,ltgt")))))
;; True if this is a comparison operator, which accepts a normal 8-bit
;; signed immediate operand.
diff --git a/gcc/config/iq2000/iq2000.c b/gcc/config/iq2000/iq2000.c
index 7e19366ae93..da6f757d6f9 100644
--- a/gcc/config/iq2000/iq2000.c
+++ b/gcc/config/iq2000/iq2000.c
@@ -1104,8 +1104,8 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,
tree ret_type = TREE_TYPE (fntype);
fprintf (stderr, ", fntype code = %s, ret code = %s\n",
- tree_code_name[(int)TREE_CODE (fntype)],
- tree_code_name[(int)TREE_CODE (ret_type)]);
+ get_tree_code_name (TREE_CODE (fntype)),
+ get_tree_code_name (TREE_CODE (ret_type)));
}
}
diff --git a/gcc/config/iq2000/iq2000.md b/gcc/config/iq2000/iq2000.md
index 9e61cdd5bfc..7a516c1b508 100644
--- a/gcc/config/iq2000/iq2000.md
+++ b/gcc/config/iq2000/iq2000.md
@@ -1398,9 +1398,8 @@
(plus:SI (match_operand:SI 0 "register_operand" "d")
(label_ref:SI (match_operand 1 "" ""))))
(use (label_ref:SI (match_dup 1)))]
- "!(Pmode == DImode) && next_active_insn (insn) != 0
- && GET_CODE (PATTERN (next_active_insn (insn))) == ADDR_DIFF_VEC
- && PREV_INSN (next_active_insn (insn)) == operands[1]"
+ "!(Pmode == DImode) && NEXT_INSN (operands[1]) != 0
+ && GET_CODE (PATTERN (NEXT_INSN (operands[1]))) == ADDR_DIFF_VEC"
"*
{
return \"j\\t%0\";
diff --git a/gcc/config/m32c/m32c-modes.def b/gcc/config/m32c/m32c-modes.def
index 2050c91a009..ad266fbc851 100644
--- a/gcc/config/m32c/m32c-modes.def
+++ b/gcc/config/m32c/m32c-modes.def
@@ -22,7 +22,7 @@
/*INT_MODE (PI, 3);*/
/* 24-bit pointers, in 32-bit units */
-PARTIAL_INT_MODE (SI);
+PARTIAL_INT_MODE (SI, 24, PSI);
/* 48-bit MULEX result */
/* INT_MODE (MI, 6); */
diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
index 5e3236fa8de..7035504bfe3 100644
--- a/gcc/config/m68k/m68k.c
+++ b/gcc/config/m68k/m68k.c
@@ -4209,6 +4209,13 @@ notice_update_cc (rtx exp, rtx insn)
&& cc_status.value2
&& reg_overlap_mentioned_p (cc_status.value1, cc_status.value2))
cc_status.value2 = 0;
+ /* Check for PRE_DEC in dest modifying a register used in src. */
+ if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM
+ && GET_CODE (XEXP (cc_status.value1, 0)) == PRE_DEC
+ && cc_status.value2
+ && reg_overlap_mentioned_p (XEXP (XEXP (cc_status.value1, 0), 0),
+ cc_status.value2))
+ cc_status.value2 = 0;
if (((cc_status.value1 && FP_REG_P (cc_status.value1))
|| (cc_status.value2 && FP_REG_P (cc_status.value2))))
cc_status.flags = CC_IN_68881;
diff --git a/gcc/config/mcore/t-mcore b/gcc/config/mcore/t-mcore
index 92fefb1cc9b..e5f37ee741b 100644
--- a/gcc/config/mcore/t-mcore
+++ b/gcc/config/mcore/t-mcore
@@ -16,9 +16,6 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-# We have values for float.h.
-CROSS_FLOAT_H = $(srcdir)/config/mcore/gfloat.h
-
# If support for -m4align is ever re-enabled then comment out the
# following line and uncomment the multilib lines below.
diff --git a/gcc/config/mep/mep.c b/gcc/config/mep/mep.c
index a5b7e6c68be..e67540a5611 100644
--- a/gcc/config/mep/mep.c
+++ b/gcc/config/mep/mep.c
@@ -3962,7 +3962,7 @@ mep_validate_vliw (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
static int gave_array_note = 0;
static const char * given_type = NULL;
- given_type = tree_code_name[TREE_CODE (*node)];
+ given_type = get_tree_code_name (TREE_CODE (*node));
if (TREE_CODE (*node) == POINTER_TYPE)
given_type = "pointers";
if (TREE_CODE (*node) == ARRAY_TYPE)
@@ -5103,7 +5103,7 @@ mep_emit_doloop (rtx *operands, int is_end)
tag = GEN_INT (cfun->machine->doloop_tags - 1);
if (is_end)
- emit_jump_insn (gen_doloop_end_internal (operands[0], operands[4], tag));
+ emit_jump_insn (gen_doloop_end_internal (operands[0], operands[1], tag));
else
emit_insn (gen_doloop_begin_internal (operands[0], operands[0], tag));
}
@@ -7280,6 +7280,8 @@ mep_asm_init_sections (void)
#define TARGET_TRAMPOLINE_INIT mep_trampoline_init
#undef TARGET_LEGITIMATE_CONSTANT_P
#define TARGET_LEGITIMATE_CONSTANT_P mep_legitimate_constant_p
+#undef TARGET_CAN_USE_DOLOOP_P
+#define TARGET_CAN_USE_DOLOOP_P can_use_doloop_if_innermost
struct gcc_target targetm = TARGET_INITIALIZER;
diff --git a/gcc/config/mep/mep.md b/gcc/config/mep/mep.md
index 3f09a235241..42542eab8bd 100644
--- a/gcc/config/mep/mep.md
+++ b/gcc/config/mep/mep.md
@@ -2076,14 +2076,9 @@
(define_expand "doloop_begin"
[(use (match_operand 0 "register_operand" ""))
- (use (match_operand:QI 1 "const_int_operand" ""))
- (use (match_operand:QI 2 "const_int_operand" ""))
- (use (match_operand:QI 3 "const_int_operand" ""))
- (use (match_operand 4 "" ""))]
+ (use (match_operand 1 "" ""))]
"!profile_arc_flag && TARGET_OPT_REPEAT"
- "if (INTVAL (operands[3]) > 1)
- FAIL;
- mep_emit_doloop (operands, 0);
+ "mep_emit_doloop (operands, 0);
DONE;
")
@@ -2112,15 +2107,9 @@
(define_expand "doloop_end"
[(use (match_operand 0 "nonimmediate_operand" ""))
- (use (match_operand:QI 1 "const_int_operand" ""))
- (use (match_operand:QI 2 "const_int_operand" ""))
- (use (match_operand:QI 3 "const_int_operand" ""))
- (use (label_ref (match_operand 4 "" "")))
- (use (match_operand 5 "" ""))]
+ (use (label_ref (match_operand 1 "" "")))]
"!profile_arc_flag && TARGET_OPT_REPEAT"
- "if (INTVAL (operands[3]) > 1)
- FAIL;
- if (GET_CODE (operands[0]) == REG && GET_MODE (operands[0]) != SImode)
+ "if (GET_CODE (operands[0]) == REG && GET_MODE (operands[0]) != SImode)
FAIL;
mep_emit_doloop (operands, 1);
DONE;
diff --git a/gcc/config/microblaze/microblaze.md b/gcc/config/microblaze/microblaze.md
index 40d27393619..8a526f1d2f8 100644
--- a/gcc/config/microblaze/microblaze.md
+++ b/gcc/config/microblaze/microblaze.md
@@ -1798,9 +1798,8 @@
(plus:SI (match_operand:SI 0 "register_operand" "d")
(label_ref:SI (match_operand 1 "" ""))))
(use (label_ref:SI (match_dup 1)))]
- "next_active_insn (insn) != 0
- && GET_CODE (PATTERN (next_active_insn (insn))) == ADDR_DIFF_VEC
- && PREV_INSN (next_active_insn (insn)) == operands[1]
+ "NEXT_INSN (operands[1]) != 0
+ && GET_CODE (PATTERN (NEXT_INSN (operands[1]))) == ADDR_DIFF_VEC
&& flag_pic"
{
output_asm_insn ("addk\t%0,%0,r20",operands);
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 5993aabe578..c1d8f3a0ade 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -3796,6 +3796,18 @@ mips_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
return true;
}
}
+ /* (AND (NOT op0) (NOT op1) is a nor operation that can be done in
+ a single instruction. */
+ if (!TARGET_MIPS16
+ && GET_CODE (XEXP (x, 0)) == NOT
+ && GET_CODE (XEXP (x, 1)) == NOT)
+ {
+ cost = GET_MODE_SIZE (mode) > UNITS_PER_WORD ? 2 : 1;
+ *total = (COSTS_N_INSNS (cost)
+ + set_src_cost (XEXP (XEXP (x, 0), 0), speed)
+ + set_src_cost (XEXP (XEXP (x, 1), 0), speed));
+ return true;
+ }
/* Fall through. */
@@ -10982,8 +10994,17 @@ mips_expand_prologue (void)
if (flag_stack_usage_info)
current_function_static_stack_size = size;
- if (flag_stack_check == STATIC_BUILTIN_STACK_CHECK && size)
- mips_emit_probe_stack_range (STACK_CHECK_PROTECT, size);
+ if (flag_stack_check == STATIC_BUILTIN_STACK_CHECK)
+ {
+ if (crtl->is_leaf && !cfun->calls_alloca)
+ {
+ if (size > PROBE_INTERVAL && size > STACK_CHECK_PROTECT)
+ mips_emit_probe_stack_range (STACK_CHECK_PROTECT,
+ size - STACK_CHECK_PROTECT);
+ }
+ else if (size > 0)
+ mips_emit_probe_stack_range (STACK_CHECK_PROTECT, size);
+ }
/* Save the registers. Allocate up to MIPS_MAX_FIRST_STACK_STEP
bytes beforehand; this is enough to cover the register save area
diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h
index af7eeee6682..c4a2a4a6862 100644
--- a/gcc/config/mips/mips.h
+++ b/gcc/config/mips/mips.h
@@ -972,6 +972,11 @@ struct mips_cpu_info {
|| TARGET_SMARTMIPS) \
&& !TARGET_MIPS16)
+/* ISA has the WSBH (word swap bytes within halfwords) instruction.
+ 64-bit targets also provide DSBH and DSHD. */
+#define ISA_HAS_WSBH ((ISA_MIPS32R2 || ISA_MIPS64R2) \
+ && !TARGET_MIPS16)
+
/* ISA has data prefetch instructions. This controls use of 'pref'. */
#define ISA_HAS_PREFETCH ((ISA_MIPS4 \
|| TARGET_LOONGSON_2EF \
diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md
index 0cda169224f..3554beb3033 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -74,6 +74,11 @@
UNSPEC_STORE_LEFT
UNSPEC_STORE_RIGHT
+ ;; Integer operations that are too cumbersome to describe directly.
+ UNSPEC_WSBH
+ UNSPEC_DSBH
+ UNSPEC_DSHD
+
;; Floating-point moves.
UNSPEC_LOAD_LOW
UNSPEC_LOAD_HIGH
@@ -5358,6 +5363,56 @@
}
[(set_attr "type" "shift")
(set_attr "mode" "<MODE>")])
+
+(define_insn "bswaphi2"
+ [(set (match_operand:HI 0 "register_operand" "=d")
+ (bswap:HI (match_operand:HI 1 "register_operand" "d")))]
+ "ISA_HAS_WSBH"
+ "wsbh\t%0,%1"
+ [(set_attr "type" "shift")])
+
+(define_insn_and_split "bswapsi2"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (bswap:SI (match_operand:SI 1 "register_operand" "d")))]
+ "ISA_HAS_WSBH && ISA_HAS_ROR"
+ "#"
+ ""
+ [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_WSBH))
+ (set (match_dup 0) (rotatert:SI (match_dup 0) (const_int 16)))]
+ ""
+ [(set_attr "insn_count" "2")])
+
+(define_insn_and_split "bswapdi2"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (bswap:DI (match_operand:DI 1 "register_operand" "d")))]
+ "TARGET_64BIT && ISA_HAS_WSBH"
+ "#"
+ ""
+ [(set (match_dup 0) (unspec:DI [(match_dup 1)] UNSPEC_DSBH))
+ (set (match_dup 0) (unspec:DI [(match_dup 0)] UNSPEC_DSHD))]
+ ""
+ [(set_attr "insn_count" "2")])
+
+(define_insn "wsbh"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (unspec:SI [(match_operand:SI 1 "register_operand" "d")] UNSPEC_WSBH))]
+ "ISA_HAS_WSBH"
+ "wsbh\t%0,%1"
+ [(set_attr "type" "shift")])
+
+(define_insn "dsbh"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (unspec:DI [(match_operand:DI 1 "register_operand" "d")] UNSPEC_DSBH))]
+ "TARGET_64BIT && ISA_HAS_WSBH"
+ "dsbh\t%0,%1"
+ [(set_attr "type" "shift")])
+
+(define_insn "dshd"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (unspec:DI [(match_operand:DI 1 "register_operand" "d")] UNSPEC_DSHD))]
+ "TARGET_64BIT && ISA_HAS_WSBH"
+ "dshd\t%0,%1"
+ [(set_attr "type" "shift")])
;;
;; ....................
diff --git a/gcc/config/mips/mti-linux.h b/gcc/config/mips/mti-linux.h
index 96dcac4dfb3..194fd1da723 100644
--- a/gcc/config/mips/mti-linux.h
+++ b/gcc/config/mips/mti-linux.h
@@ -20,7 +20,7 @@ along with GCC; see the file COPYING3. If not see
/* This target is a multilib target, specify the sysroot paths. */
#undef SYSROOT_SUFFIX_SPEC
#define SYSROOT_SUFFIX_SPEC \
- "%{mips32:/mips32}%{mips64:/mips64}%{mips64r2:/mips64r2}%{mips16:/mips16}%{mmicromips:/micromips}%{mabi=64:/64}%{mel|EL:/el}%{msoft-float:/sof}%{mnan=2008:/nan2008}"
+ "%{mips32:/mips32}%{mips64:/mips64}%{mips64r2:/mips64r2}%{mips16:/mips16}%{mmicromips:/micromips}%{mabi=64:/64}%{mel|EL:/el}%{msoft-float:/sof}%{mfp64:/fp64}%{mnan=2008:/nan2008}"
#undef DRIVER_SELF_SPECS
#define DRIVER_SELF_SPECS \
diff --git a/gcc/config/mips/t-mti-elf b/gcc/config/mips/t-mti-elf
index 4aec70cb807..f2c714b9331 100644
--- a/gcc/config/mips/t-mti-elf
+++ b/gcc/config/mips/t-mti-elf
@@ -19,8 +19,8 @@
# The default build is mips32r2, hard-float big-endian. Add mips32,
# soft-float, and little-endian variations.
-MULTILIB_OPTIONS = mips32/mips64/mips64r2 mips16/mmicromips mabi=64 EL msoft-float/mnan=2008
-MULTILIB_DIRNAMES = mips32 mips64 mips64r2 mips16 micromips 64 el sof nan2008
+MULTILIB_OPTIONS = mips32/mips64/mips64r2 mips16/mmicromips mabi=64 EL msoft-float/mfp64 mnan=2008
+MULTILIB_DIRNAMES = mips32 mips64 mips64r2 mips16 micromips 64 el sof fp64 nan2008
MULTILIB_MATCHES = EL=mel EB=meb
# The 64 bit ABI is not supported on the mips32 architecture.
@@ -37,6 +37,14 @@ MULTILIB_EXCEPTIONS += *mips64*/*mips16*
MULTILIB_EXCEPTIONS += *mips16/mabi=64*
# We only want micromips for mips32r2 architecture.
-MULTILIB_EXCEPTIONS += *mips64*/mmicromips*
MULTILIB_EXCEPTIONS += *mips32/mmicromips*
+MULTILIB_EXCEPTIONS += *mips64*/mmicromips*
MULTILIB_EXCEPTIONS += *mmicromips/mabi=64*
+
+# We do not want nan2008 libraries for soft-float.
+MULTILIB_EXCEPTIONS += *msoft-float*/*mnan=2008*
+
+# -mfp64 libraries are only built for mips32r2 and not in mips16 mode.
+MULTILIB_EXCEPTIONS += *mips32/*mfp64*
+MULTILIB_EXCEPTIONS += *mips64*/*mfp64*
+MULTILIB_EXCEPTIONS += *mips16*/*mfp64*
diff --git a/gcc/config/mips/t-mti-linux b/gcc/config/mips/t-mti-linux
index 4aec70cb807..f2c714b9331 100644
--- a/gcc/config/mips/t-mti-linux
+++ b/gcc/config/mips/t-mti-linux
@@ -19,8 +19,8 @@
# The default build is mips32r2, hard-float big-endian. Add mips32,
# soft-float, and little-endian variations.
-MULTILIB_OPTIONS = mips32/mips64/mips64r2 mips16/mmicromips mabi=64 EL msoft-float/mnan=2008
-MULTILIB_DIRNAMES = mips32 mips64 mips64r2 mips16 micromips 64 el sof nan2008
+MULTILIB_OPTIONS = mips32/mips64/mips64r2 mips16/mmicromips mabi=64 EL msoft-float/mfp64 mnan=2008
+MULTILIB_DIRNAMES = mips32 mips64 mips64r2 mips16 micromips 64 el sof fp64 nan2008
MULTILIB_MATCHES = EL=mel EB=meb
# The 64 bit ABI is not supported on the mips32 architecture.
@@ -37,6 +37,14 @@ MULTILIB_EXCEPTIONS += *mips64*/*mips16*
MULTILIB_EXCEPTIONS += *mips16/mabi=64*
# We only want micromips for mips32r2 architecture.
-MULTILIB_EXCEPTIONS += *mips64*/mmicromips*
MULTILIB_EXCEPTIONS += *mips32/mmicromips*
+MULTILIB_EXCEPTIONS += *mips64*/mmicromips*
MULTILIB_EXCEPTIONS += *mmicromips/mabi=64*
+
+# We do not want nan2008 libraries for soft-float.
+MULTILIB_EXCEPTIONS += *msoft-float*/*mnan=2008*
+
+# -mfp64 libraries are only built for mips32r2 and not in mips16 mode.
+MULTILIB_EXCEPTIONS += *mips32/*mfp64*
+MULTILIB_EXCEPTIONS += *mips64*/*mfp64*
+MULTILIB_EXCEPTIONS += *mips16*/*mfp64*
diff --git a/gcc/config/mmix/mmix.c b/gcc/config/mmix/mmix.c
index bd37067dfc4..34b4fea7503 100644
--- a/gcc/config/mmix/mmix.c
+++ b/gcc/config/mmix/mmix.c
@@ -1531,7 +1531,7 @@ mmix_print_operand (FILE *stream, rtx x, int code)
if (TARGET_BRANCH_PREDICT)
{
x = find_reg_note (current_output_insn, REG_BR_PROB, 0);
- if (x && INTVAL (XEXP (x, 0)) > REG_BR_PROB_BASE / 2)
+ if (x && XINT (x, 0) > REG_BR_PROB_BASE / 2)
putc ('P', stream);
}
return;
diff --git a/gcc/config/moxie/uclinux.h b/gcc/config/moxie/uclinux.h
index 85c65f257ce..fb8c92542b5 100644
--- a/gcc/config/moxie/uclinux.h
+++ b/gcc/config/moxie/uclinux.h
@@ -30,13 +30,5 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define TARGET_OS_CPP_BUILTINS() GNU_USER_TARGET_OS_CPP_BUILTINS()
-/* Like the definition in gcc.c, but for purposes of uClinux, every link is
- static. */
-#define MFWRAP_SPEC " %{fmudflap|fmudflapth: \
- --wrap=malloc --wrap=free --wrap=calloc --wrap=realloc\
- --wrap=mmap --wrap=munmap --wrap=alloca\
- %{fmudflapth: --wrap=pthread_create\
-}} %{fmudflap|fmudflapth: --wrap=main}"
-
#undef TARGET_LIBC_HAS_FUNCTION
#define TARGET_LIBC_HAS_FUNCTION no_c99_libc_has_function
diff --git a/gcc/config/msp430/msp430-modes.def b/gcc/config/msp430/msp430-modes.def
index 9e7b70127fd..4e94a6df597 100644
--- a/gcc/config/msp430/msp430-modes.def
+++ b/gcc/config/msp430/msp430-modes.def
@@ -1,3 +1,3 @@
/* 20-bit address */
-PARTIAL_INT_MODE (SI);
+PARTIAL_INT_MODE (SI, 20, PSI);
diff --git a/gcc/config/msp430/msp430-protos.h b/gcc/config/msp430/msp430-protos.h
index f116855ecae..61402e59f38 100644
--- a/gcc/config/msp430/msp430-protos.h
+++ b/gcc/config/msp430/msp430-protos.h
@@ -35,6 +35,7 @@ void msp430_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree, int);
int msp430_initial_elimination_offset (int, int);
bool msp430_is_interrupt_func (void);
const char * msp430x_logical_shift_right (rtx);
+const char * msp430_mcu_name (void);
bool msp430_modes_tieable_p (enum machine_mode, enum machine_mode);
void msp430_output_labelref (FILE *, const char *);
void msp430_register_pragmas (void);
diff --git a/gcc/config/msp430/msp430.c b/gcc/config/msp430/msp430.c
index 9384d32457a..1ebb583c1ed 100644
--- a/gcc/config/msp430/msp430.c
+++ b/gcc/config/msp430/msp430.c
@@ -109,15 +109,114 @@ msp430_handle_option (struct gcc_options *opts ATTRIBUTE_UNUSED,
#undef TARGET_OPTION_OVERRIDE
#define TARGET_OPTION_OVERRIDE msp430_option_override
+/* This list provides a set of known MCU names that support the MSP430X
+ ISA. The list has been provided by TI and should be kept in sync with
+ the ones in:
+
+ gcc/config/msp430/t-msp430
+ gas/config/tc-msp430.c
+
+ FIXME: We ought to read the names in from a file at run, rather
+ than having them built in like this. Also such a file should be
+ shared with gas. */
+
+static const char * msp430x_names [] =
+{
+ "cc430f5123", "cc430f5125", "cc430f5133", "cc430f5135", "cc430f5137",
+ "cc430f5143", "cc430f5145", "cc430f5147", "cc430f6125", "cc430f6126",
+ "cc430f6127", "cc430f6135", "cc430f6137", "cc430f6143", "cc430f6145",
+ "cc430f6147", "msp430bt5190", "msp430cg4616", "msp430cg4617", "msp430cg4618",
+ "msp430cg4619", "msp430f2416", "msp430f2417", "msp430f2418", "msp430f2419",
+ "msp430f2616", "msp430f2617", "msp430f2618", "msp430f2619", "msp430f4616",
+ "msp430f46161", "msp430f4617", "msp430f46171", "msp430f4618", "msp430f46181",
+ "msp430f4619", "msp430f46191", "msp430f47126", "msp430f47127", "msp430f47163",
+ "msp430f47166", "msp430f47167", "msp430f47173", "msp430f47176", "msp430f47177",
+ "msp430f47183", "msp430f47186", "msp430f47187", "msp430f47193", "msp430f47196",
+ "msp430f47197", "msp430f5131", "msp430f5132", "msp430f5151", "msp430f5152",
+ "msp430f5171", "msp430f5172", "msp430f5212", "msp430f5213", "msp430f5214",
+ "msp430f5217", "msp430f5218", "msp430f5219", "msp430f5222", "msp430f5223",
+ "msp430f5224", "msp430f5227", "msp430f5228", "msp430f5229", "msp430f5304",
+ "msp430f5308", "msp430f5309", "msp430f5310", "msp430f5324", "msp430f5325",
+ "msp430f5326", "msp430f5327", "msp430f5328", "msp430f5329", "msp430f5333",
+ "msp430f5335", "msp430f5336", "msp430f5338", "msp430f5340", "msp430f5341",
+ "msp430f5342", "msp430f5358", "msp430f5359", "msp430f5418", "msp430f5418a",
+ "msp430f5419", "msp430f5419a", "msp430f5435", "msp430f5435a", "msp430f5436",
+ "msp430f5436a", "msp430f5437", "msp430f5437a", "msp430f5438", "msp430f5438a",
+ "msp430f5500", "msp430f5501", "msp430f5502", "msp430f5503", "msp430f5504",
+ "msp430f5505", "msp430f5506", "msp430f5507", "msp430f5508", "msp430f5509",
+ "msp430f5510", "msp430f5513", "msp430f5514", "msp430f5515", "msp430f5517",
+ "msp430f5519", "msp430f5521", "msp430f5522", "msp430f5524", "msp430f5525",
+ "msp430f5526", "msp430f5527", "msp430f5528", "msp430f5529", "msp430f5630",
+ "msp430f5631", "msp430f5632", "msp430f5633", "msp430f5634", "msp430f5635",
+ "msp430f5636", "msp430f5637", "msp430f5638", "msp430f5658", "msp430f5659",
+ "msp430f6433", "msp430f6435", "msp430f6436", "msp430f6438", "msp430f6458",
+ "msp430f6459", "msp430f6630", "msp430f6631", "msp430f6632", "msp430f6633",
+ "msp430f6634", "msp430f6635", "msp430f6636", "msp430f6637", "msp430f6638",
+ "msp430f6658", "msp430f6659", "msp430f6720", "msp430f6721", "msp430f6723",
+ "msp430f6724", "msp430f6725", "msp430f6726", "msp430f6730", "msp430f6731",
+ "msp430f6733", "msp430f6734", "msp430f6735", "msp430f6736", "msp430f6745",
+ "msp430f67451", "msp430f6746", "msp430f67461", "msp430f6747", "msp430f67471",
+ "msp430f6748", "msp430f67481", "msp430f6749", "msp430f67491", "msp430f6765",
+ "msp430f67651", "msp430f6766", "msp430f67661", "msp430f6767", "msp430f67671",
+ "msp430f6768", "msp430f67681", "msp430f6769", "msp430f67691", "msp430f6775",
+ "msp430f67751", "msp430f6776", "msp430f67761", "msp430f6777", "msp430f67771",
+ "msp430f6778", "msp430f67781", "msp430f6779", "msp430f67791", "msp430fg4616",
+ "msp430fg4617", "msp430fg4618", "msp430fg4619", "msp430fr5720", "msp430fr5721",
+ "msp430fr5722", "msp430fr5723", "msp430fr5724", "msp430fr5725", "msp430fr5726",
+ "msp430fr5727", "msp430fr5728", "msp430fr5729", "msp430fr5730", "msp430fr5731",
+ "msp430fr5732", "msp430fr5733", "msp430fr5734", "msp430fr5735", "msp430fr5736",
+ "msp430fr5737", "msp430fr5738", "msp430fr5739", "msp430fr5949", "msp430fr5969",
+ "msp430sl5438a","msp430x241x", "msp430x26x", "msp430x461x1", "msp430x46x",
+ "msp430x471x3", "msp430x471x6", "msp430x471x7", "msp430xg46x"
+};
+
+/* Generate a C preprocessor symbol based upon the MCU selected by the user.
+ If a specific MCU has not been selected then return a generic symbol instead. */
+
+const char *
+msp430_mcu_name (void)
+{
+ if (target_cpu)
+ {
+ unsigned int i;
+ static char mcu_name [64];
+
+ snprintf (mcu_name, sizeof (mcu_name) - 1, "__%s__", target_cpu);
+ for (i = strlen (mcu_name); i--;)
+ mcu_name[i] = TOUPPER (mcu_name[i]);
+ return mcu_name;
+ }
+
+ return msp430x ? "__MSP430XGENERIC__" : "__MSP430GENERIC__";
+}
+
static void
msp430_option_override (void)
{
init_machine_status = msp430_init_machine_status;
- if (target_cpu
- && (strstr (target_cpu, "430x")
- || strstr (target_cpu, "430X")))
- msp430x = true;
+ if (target_cpu)
+ {
+ unsigned i;
+
+ for (i = ARRAY_SIZE (msp430x_names); i--;)
+ if (strcasecmp (target_cpu, msp430x_names[i]) == 0)
+ {
+ msp430x = true;
+ break;
+ }
+ /* Note - it is not an error if we did not recognize the MCU
+ name. The msp430x_names array only contains those MCU names
+ which are currently known to use the MSP430X ISA. There are
+ lots of other MCUs which just use the MSP430 ISA. */
+
+ /* We also recognise two generic MCU 430X names. They do not
+ appear in the msp430x_names table as we want to be able to
+ generate special C preprocessor defines for them. */
+ if (strcasecmp (target_cpu, "msp430x") == 0
+ || strcasecmp (target_cpu, "msp430xv2") == 0)
+ msp430x = true;
+ }
if (TARGET_LARGE && !msp430x)
error ("-mlarge requires a 430X-compatible -mmcu=");
@@ -1291,7 +1390,7 @@ msp430_expand_epilogue (int is_eh)
if (cfun->machine->need_to_save [10])
{
/* Check for a helper function. */
- helper_n = 7; /* for when the loop below never sees a match. */
+ helper_n = 7; /* For when the loop below never sees a match. */
for (i = 9; i >= 4; i--)
if (!cfun->machine->need_to_save [i])
{
@@ -1354,7 +1453,7 @@ msp430_expand_epilogue (int is_eh)
&& ! is_critical_func ()
&& crtl->args.pretend_args_size == 0
/* Calling the helper takes as many bytes as the POP;RET sequence. */
- && helper_n != 1
+ && helper_n > 1
&& !is_eh)
{
emit_insn (gen_epilogue_helper (GEN_INT (helper_n)));
@@ -1494,7 +1593,7 @@ msp430_expand_helper (rtx *operands, const char *helper_name, bool const_variant
/* Note that the INTVAL is limited in value and length by the conditional above. */
int len = strlen (helper_name) + 4;
helper_const = (char *) xmalloc (len);
- snprintf (helper_const, len, "%s_%ld", helper_name, (int) INTVAL (operands[2]));
+ snprintf (helper_const, len, "%s_%d", helper_name, (int) INTVAL (operands[2]));
}
emit_move_insn (gen_rtx_REG (arg1mode, 12),
@@ -1722,12 +1821,10 @@ msp430_output_labelref (FILE *file, const char *name)
fputs (name, file);
}
-#undef TARGET_PRINT_OPERAND
-#define TARGET_PRINT_OPERAND msp430_print_operand
+/* Common code for msp430_print_operand... */
-/* Common code for msp430_print_operand(). */
static void
-msp430_print_operand_raw (FILE * file, rtx op, int letter ATTRIBUTE_UNUSED)
+msp430_print_operand_raw (FILE * file, rtx op)
{
int i;
@@ -1759,6 +1856,45 @@ msp430_print_operand_raw (FILE * file, rtx op, int letter ATTRIBUTE_UNUSED)
}
}
+#undef TARGET_PRINT_OPERAND_ADDRESS
+#define TARGET_PRINT_OPERAND_ADDRESS msp430_print_operand_addr
+
+/* Output to stdio stream FILE the assembler syntax for an
+ instruction operand that is a memory reference whose address
+ is ADDR. */
+
+static void
+msp430_print_operand_addr (FILE * file, rtx addr)
+{
+ switch (GET_CODE (addr))
+ {
+ case PLUS:
+ msp430_print_operand_raw (file, XEXP (addr, 1));
+ gcc_assert (REG_P (XEXP (addr, 0)));
+ fprintf (file, "(%s)", reg_names [REGNO (XEXP (addr, 0))]);
+ return;
+
+ case REG:
+ fprintf (file, "@");
+ break;
+
+ case CONST:
+ case CONST_INT:
+ case SYMBOL_REF:
+ case LABEL_REF:
+ fprintf (file, "&");
+ break;
+
+ default:
+ break;
+ }
+
+ msp430_print_operand_raw (file, addr);
+}
+
+#undef TARGET_PRINT_OPERAND
+#define TARGET_PRINT_OPERAND msp430_print_operand
+
static void
msp430_print_operand (FILE * file, rtx op, int letter)
{
@@ -1803,7 +1939,7 @@ msp430_print_operand (FILE * file, rtx op, int letter)
case GT: fprintf (file, "GE"); break;
case LE: fprintf (file, "L"); break;
default:
- msp430_print_operand_raw (file, op, letter);
+ msp430_print_operand_raw (file, op);
break;
}
return;
@@ -1815,7 +1951,7 @@ msp430_print_operand (FILE * file, rtx op, int letter)
case GT: fprintf (file, "L"); break;
case LE: fprintf (file, "GE"); break;
default:
- msp430_print_operand_raw (file, op, letter);
+ msp430_print_operand_raw (file, op);
break;
}
return;
@@ -1897,38 +2033,18 @@ msp430_print_operand (FILE * file, rtx op, int letter)
fprintf (file, "%d",
msp430_initial_elimination_offset (ARG_POINTER_REGNUM, STACK_POINTER_REGNUM)
- 2);
- return ;
+ return;
}
switch (GET_CODE (op))
{
case REG:
- msp430_print_operand_raw (file, op, letter);
+ msp430_print_operand_raw (file, op);
break;
case MEM:
addr = XEXP (op, 0);
- switch (GET_CODE (addr))
- {
- case REG:
- fprintf (file, "@%s", reg_names [REGNO (addr)]);
- break;
- case PLUS:
- msp430_print_operand_raw (file, XEXP (addr, 1), letter);
- fprintf (file, "(%s)", reg_names [REGNO (XEXP (addr, 0))]);
- break;
- case CONST:
- case CONST_INT:
- case SYMBOL_REF:
- case LABEL_REF:
- fprintf (file, "&");
- msp430_print_operand_raw (file, addr, letter);
- break;
-
- default:
- print_rtl (file, addr);
- break;
- }
+ msp430_print_operand_addr (file, addr);
break;
case CONST_INT:
@@ -1937,7 +2053,7 @@ msp430_print_operand (FILE * file, rtx op, int letter)
case LABEL_REF:
if (letter == 0)
fprintf (file, "#");
- msp430_print_operand_raw (file, op, letter);
+ msp430_print_operand_raw (file, op);
break;
case EQ: fprintf (file, "EQ"); break;
@@ -1951,7 +2067,6 @@ msp430_print_operand (FILE * file, rtx op, int letter)
print_rtl (file, op);
break;
}
-
}
diff --git a/gcc/config/msp430/msp430.h b/gcc/config/msp430/msp430.h
index f5289b551e3..953c6387e99 100644
--- a/gcc/config/msp430/msp430.h
+++ b/gcc/config/msp430/msp430.h
@@ -31,6 +31,7 @@ extern bool msp430x;
{ \
builtin_define ("NO_TRAMPOLINES"); \
builtin_define ("__MSP430__"); \
+ builtin_define (msp430_mcu_name ()); \
if (msp430x) \
{ \
builtin_define ("__MSP430X__"); \
@@ -70,10 +71,11 @@ extern bool msp430x;
%{msim:-lsim} \
%{!msim:-lnosys} \
--end-group \
-%{!T*: %{msim: %{mlarge:%Tmsp430xl-sim.ld}%{!mlarge:%Tmsp430-sim.ld}}%{!msim:%Tmsp430.ld}} \
+%{!T*:%{!msim:%{mmcu=*:--script=%*/memory.ld --script=%*/peripherals.ld}}} \
+%{!T*:%{!msim:%{!mmcu=*:%Tmsp430.ld}}} \
+%{!T*:%{msim:%{mlarge:%Tmsp430xl-sim.ld}%{!mlarge:%Tmsp430-sim.ld}}} \
"
-
/* Storage Layout */
#define BITS_BIG_ENDIAN 0
diff --git a/gcc/config/msp430/msp430.md b/gcc/config/msp430/msp430.md
index a258867e532..22a3953bf97 100644
--- a/gcc/config/msp430/msp430.md
+++ b/gcc/config/msp430/msp430.md
@@ -190,8 +190,8 @@
)
(define_expand "movsi"
- [(set (match_operand:SI 0 "nonimmediate_operand" "")
- (match_operand:SI 1 "general_operand" ""))]
+ [(set (match_operand:SI 0 "nonimmediate_operand")
+ (match_operand:SI 1 "general_operand"))]
""
""
)
@@ -230,7 +230,7 @@
[(set (match_operand:PSI 0 "register_operand" "=r")
(subreg:PSI (match_operand:SI 1 "register_operand" "r") 0))]
"TARGET_LARGE"
- "PUSH.W %H1 { PUSH.W %1 { POPM.A #1, %0"
+ "PUSH.W\t%H1 { PUSH.W %L1 { POPM.A #1, %0 ; Move reg-pair %L1:%H1 into pointer %0"
)
;;------------------------------------------------------------
@@ -326,8 +326,8 @@
]
""
"@
- ADD %2, %1 ; cy
- ADD%X0 %2, %1 ; cy"
+ ADD\t%2, %1 ; cy
+ ADD%X0\t%2, %1 ; cy"
)
(define_insn "addhi3_cy_i"
@@ -341,8 +341,8 @@
]
""
"@
- ADD %2, %1 ; cy
- ADD%X0 %2, %1 ; cy"
+ ADD\t%2, %1 ; cy
+ ADD%X0\t%2, %1 ; cy"
)
; Version of addhi that adds the carry, for SImode adds.
@@ -354,8 +354,8 @@
]
""
"@
- ADDC %2, %1
- ADDC%X0 %2, %1"
+ ADDC\t%2, %1
+ ADDC%X0\t%2, %1"
)
; Split an SImode add into two HImode adds, keeping track of the carry
@@ -621,9 +621,30 @@
stored in the stack slot will be the value *after* the
stack pointer has been decremented. So allow for that
here. */
- return \"PUSHM.A #1, %1 { ADDX.W #4, @r1 { POPX.W %0 { POPX.W %H0\";
+ return \"PUSHM.A\t#1, %1 { ADDX.W #4, @r1 { POPX.W %L0 { POPX.W %H0 ; get stack pointer into %L0:%H0\";
+ else
+ return \"PUSHM.A\t#1, %1 { POPX.W %L0 { POPX.W %H0 ; move pointer in %1 into reg-pair %L0:%H0\";
+ "
+)
+
+;; We also need to be able to sign-extend pointer types (eg ptrdiff_t).
+;; Since (we assume) pushing a 20-bit value onto the stack zero-extends
+;; it, we use a different method here.
+
+(define_insn "extendpsisi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (sign_extend:SI (match_operand:PSI 1 "register_operand" "r")))]
+ "TARGET_LARGE"
+ "*
+ /* The intention here is that we copy the bottom 16-bits of
+ %1 into %L0 (zeroing the top four bits). Then we copy the
+ entire 20-bits of %1 into %H0 and then arithmetically shift
+ it right by 16 bits, to get the top four bits of the pointer
+ sign-extended in %H0. */
+ if (REGNO (operands[0]) == REGNO (operands[1]))
+ return \"MOVX.A\t%1, %H0 { MOV.W %1, %L0 { RPT #16 { RRAX.A %H0 ; sign extend pointer in %1 into %L0:%H0\";
else
- return \"PUSHM.A #1, %1 { POPX.W %0 { POPX.W %H0\";
+ return \"MOV.W \t%1, %L0 { MOVX.A %1, %H0 { RPT #16 { RRAX.A %H0 ; sign extend pointer in %1 into %L0:%H0\";
"
)
@@ -926,7 +947,7 @@
(define_expand "call"
[(call:HI (match_operand 0 "")
- (match_operand 1 ""))]
+ (match_operand 1 ""))]
""
""
)
@@ -966,7 +987,7 @@
;; placeholder should get expanded into a regular-type epilogue that
;; also does the EH return.
(define_expand "eh_return"
- [(match_operand:HI 0 "" "")]
+ [(match_operand:HI 0 "")]
""
"msp430_expand_eh_return (operands[0]);
emit_jump_insn (gen_msp430_eh_epilogue ());
@@ -1272,3 +1293,19 @@
""
"BIS.W\t%0, %O0(SP)"
)
+
+;; For some reason GCC is generating (set (reg) (and (neg (reg)) (int)))
+;; very late on in the compilation and not splitting it into separate
+;; instructions, so we provide a pattern to support it here.
+(define_insn "andneghi3"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (and:HI (neg:HI (match_operand:HI 1 "register_operand" "r"))
+ (match_operand 2 "immediate_operand" "n")))]
+ ""
+ "*
+ if (REGNO (operands[0]) != REGNO (operands[1]))
+ return \"MOV.W\t%1, %0 { SUB.W #0, %0 { AND.W %2, %0\";
+ else
+ return \"SUB.W\t#0, %0 { AND.W %2, %0\";
+ "
+ )
diff --git a/gcc/config/msp430/t-msp430 b/gcc/config/msp430/t-msp430
index c7048378da4..895810ff7e6 100644
--- a/gcc/config/msp430/t-msp430
+++ b/gcc/config/msp430/t-msp430
@@ -26,14 +26,243 @@ MULTILIB_DIRNAMES = 430x large
# Match msp430X with msp430x.
MULTILIB_MATCHES = mmcu?msp430x=mmcu?msp430X
-# each supported MCU needs a line like this:
-# MULTILIB_MATCHES += mmcu?msp430x123=mmcu?msp430x
-
-# The only way I figured this out was to hack the script to SHOW me
-# what it's doing. It's non-obvious, but it matches the directory
-# structure of the multilib tree, but using the options, not the
-# directory names. A shell CASE statement is generated from these, so
-# the usual CASE wildcards are supported.
+# each supported X or Xv2 MCU needs a line like this:
+# MULTILIB_MATCHES += mmcu?msp430x=mmcu?xxxxxxxxxx
+
+# NB/ This list should be kept in sync with the ones in:
+# gcc/config/msp430/msp430.c
+# gas/config/tc-msp430.c
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430xv2
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430cg4616
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430cg4617
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430cg4618
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430cg4619
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f2416
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f2417
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f2418
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f2419
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f2616
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f2617
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f2618
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f2619
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f47126
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f47127
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f47163
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f47173
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f47183
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f47193
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f47166
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f47176
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f47186
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f47196
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f47167
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f47177
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f47187
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f47197
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f46161
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f46171
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f46181
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f46191
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f4616
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f4617
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f4618
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f4619
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430fg4616
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430fg4617
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430fg4618
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430fg4619
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5418
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5419
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5435
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5436
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5437
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5438
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5418a
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5419a
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5435a
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5436a
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5437a
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5438a
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5212
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5213
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5214
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5217
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5218
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5219
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5222
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5223
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5224
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5227
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5228
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5229
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5304
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5308
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5309
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5310
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5340
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5341
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5342
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5324
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5325
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5326
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5327
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5328
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5329
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5500
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5501
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5502
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5503
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5504
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5505
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5506
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5507
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5508
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5509
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5510
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5513
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5514
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5515
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5517
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5519
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5521
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5522
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5524
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5525
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5526
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5527
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5528
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5529
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?cc430f5133
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?cc430f5135
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?cc430f5137
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?cc430f6125
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?cc430f6126
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?cc430f6127
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?cc430f6135
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?cc430f6137
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?cc430f5123
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?cc430f5125
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?cc430f5143
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?cc430f5145
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?cc430f5147
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?cc430f6143
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?cc430f6145
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?cc430f6147
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5333
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5335
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5336
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5338
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5630
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5631
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5632
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5633
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5634
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5635
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5636
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5637
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5638
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f6433
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f6435
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f6436
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f6438
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f6630
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f6631
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f6632
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f6633
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f6634
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f6635
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f6636
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f6637
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f6638
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5358
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5359
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5658
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5659
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f6458
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f6459
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f6658
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f6659
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5131
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5151
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5171
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5132
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5152
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f5172
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f6720
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f6721
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f6723
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f6724
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f6725
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f6726
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f6730
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f6731
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f6733
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f6734
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f6735
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f6736
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f67451
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f67651
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f67751
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f67461
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f67661
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f67761
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f67471
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f67671
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f67771
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f67481
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f67681
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f67781
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f67491
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f67691
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f67791
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f6745
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f6765
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f6775
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f6746
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f6766
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f6776
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f6747
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f6767
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f6777
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f6748
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f6768
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f6778
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f6749
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f6769
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430f6779
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430fr5720
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430fr5721
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430fr5722
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430fr5723
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430fr5724
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430fr5725
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430fr5726
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430fr5727
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430fr5728
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430fr5729
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430fr5730
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430fr5731
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430fr5732
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430fr5733
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430fr5734
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430fr5735
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430fr5736
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430fr5737
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430fr5738
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430fr5739
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430bt5190
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430fr5949
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430fr5969
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430sl5438a
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430x241x
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430x26x
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430x461x1
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430x46x
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430x471x3
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430x471x6
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430x471x7
+MULTILIB_MATCHES += mmcu?msp430x=mmcu?msp430xg46x
+
MULTILIB_EXCEPTIONS = mlarge
diff --git a/gcc/config/nds32/constants.md b/gcc/config/nds32/constants.md
new file mode 100644
index 00000000000..03a21dba1b2
--- /dev/null
+++ b/gcc/config/nds32/constants.md
@@ -0,0 +1,46 @@
+;; Constant defintions of Andes NDS32 cpu for GNU compiler
+;; Copyright (C) 2012-2013 Free Software Foundation, Inc.
+;; Contributed by Andes Technology Corporation.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 3, or (at your
+;; option) any later version.
+;;
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+;; License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3. If not see
+;; <http://www.gnu.org/licenses/>.
+
+
+;; Register numbers.
+(define_constants
+ [(R8_REGNUM 8)
+ (TA_REGNUM 15)
+ (FP_REGNUM 28)
+ (GP_REGNUM 29)
+ (LP_REGNUM 30)
+ (SP_REGNUM 31)
+ ])
+
+
+;; The unspec_volatile operation index.
+(define_c_enum "unspec_volatile_element" [
+ UNSPEC_VOLATILE_FUNC_RETURN
+ UNSPEC_VOLATILE_ISYNC
+ UNSPEC_VOLATILE_ISB
+ UNSPEC_VOLATILE_MFSR
+ UNSPEC_VOLATILE_MFUSR
+ UNSPEC_VOLATILE_MTSR
+ UNSPEC_VOLATILE_MTUSR
+ UNSPEC_VOLATILE_SETGIE_EN
+ UNSPEC_VOLATILE_SETGIE_DIS
+])
+
+;; ------------------------------------------------------------------------
diff --git a/gcc/config/nds32/constraints.md b/gcc/config/nds32/constraints.md
new file mode 100644
index 00000000000..b4ae6c7258c
--- /dev/null
+++ b/gcc/config/nds32/constraints.md
@@ -0,0 +1,254 @@
+;; Constraint definitions of Andes NDS32 cpu for GNU compiler
+;; Copyright (C) 2012-2013 Free Software Foundation, Inc.
+;; Contributed by Andes Technology Corporation.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 3, or (at your
+;; option) any later version.
+;;
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+;; License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3. If not see
+;; <http://www.gnu.org/licenses/>.
+
+;; Check 16.8.7 Defining Machine-Specific Constraints for detail.
+
+;; NO contrains can be prefixed with: E F V X g i m n o p r s
+;; Machine-dependent integer: I J K L M N O P
+;; Machine-dependent floating: G H
+
+
+(define_register_constraint "w" "(TARGET_ISA_V3 || TARGET_ISA_V3M) ? LOW_REGS : NO_REGS"
+ "LOW register class $r0 ~ $r7 constraint for V3/V3M ISA")
+
+(define_register_constraint "l" "LOW_REGS"
+ "LOW register class $r0 ~ $r7")
+
+(define_register_constraint "d" "MIDDLE_REGS"
+ "MIDDLE register class $r0 ~ $r11, $r16 ~ $r19")
+
+(define_register_constraint "h" "HIGH_REGS"
+ "HIGH register class $r12 ~ $r14, $r20 ~ $r31")
+
+
+(define_register_constraint "t" "R15_TA_REG"
+ "Temporary Assist register $ta (i.e. $r15)")
+
+(define_register_constraint "k" "STACK_REG"
+ "Stack register $sp")
+
+
+(define_constraint "Iu03"
+ "Unsigned immediate 3-bit value"
+ (and (match_code "const_int")
+ (match_test "ival < (1 << 3) && ival >= 0")))
+
+(define_constraint "In03"
+ "Negative immediate 3-bit value in the range of -7 to 0"
+ (and (match_code "const_int")
+ (match_test "IN_RANGE (ival, -7, 0)")))
+
+(define_constraint "Iu04"
+ "Unsigned immediate 4-bit value"
+ (and (match_code "const_int")
+ (match_test "ival < (1 << 4) && ival >= 0")))
+
+(define_constraint "Is05"
+ "Signed immediate 5-bit value"
+ (and (match_code "const_int")
+ (match_test "ival < (1 << 4) && ival >= -(1 << 4)")))
+
+(define_constraint "Iu05"
+ "Unsigned immediate 5-bit value"
+ (and (match_code "const_int")
+ (match_test "ival < (1 << 5) && ival >= 0")))
+
+(define_constraint "In05"
+ "Negative immediate 5-bit value in the range of -31 to 0"
+ (and (match_code "const_int")
+ (match_test "IN_RANGE (ival, -31, 0)")))
+
+;; Ip05 is special and dedicated for v3 movpi45 instruction.
+;; movpi45 has imm5u field but the range is 16 ~ 47.
+(define_constraint "Ip05"
+ "Unsigned immediate 5-bit value for movpi45 instruction with range 16-47"
+ (and (match_code "const_int")
+ (match_test "ival < ((1 << 5) + 16)
+ && ival >= (0 + 16)
+ && (TARGET_ISA_V3 || TARGET_ISA_V3M)")))
+
+(define_constraint "Iu06"
+ "Unsigned immediate 6-bit value constraint for addri36.sp instruction"
+ (and (match_code "const_int")
+ (match_test "ival < (1 << 6)
+ && ival >= 0
+ && (ival % 4 == 0)
+ && (TARGET_ISA_V3 || TARGET_ISA_V3M)")))
+
+(define_constraint "Iu08"
+ "Unsigned immediate 8-bit value"
+ (and (match_code "const_int")
+ (match_test "ival < (1 << 8) && ival >= 0")))
+
+(define_constraint "Iu09"
+ "Unsigned immediate 9-bit value"
+ (and (match_code "const_int")
+ (match_test "ival < (1 << 9) && ival >= 0")))
+
+
+(define_constraint "Is10"
+ "Signed immediate 10-bit value"
+ (and (match_code "const_int")
+ (match_test "ival < (1 << 9) && ival >= -(1 << 9)")))
+
+(define_constraint "Is11"
+ "Signed immediate 11-bit value"
+ (and (match_code "const_int")
+ (match_test "ival < (1 << 10) && ival >= -(1 << 10)")))
+
+
+(define_constraint "Is15"
+ "Signed immediate 15-bit value"
+ (and (match_code "const_int")
+ (match_test "ival < (1 << 14) && ival >= -(1 << 14)")))
+
+(define_constraint "Iu15"
+ "Unsigned immediate 15-bit value"
+ (and (match_code "const_int")
+ (match_test "ival < (1 << 15) && ival >= 0")))
+
+
+;; Ic15 is special and dedicated for performance extension
+;; 'bclr' (single-bit-clear) instruction.
+;; It is used in andsi3 pattern and recognized for the immediate
+;; which is NOT in the range of imm15u but OK for 'bclr' instruction.
+;; (If the immediate value IS in the range of imm15u,
+;; we can directly use 'andi' instruction.)
+(define_constraint "Ic15"
+ "A constant which is not in the range of imm15u but ok for bclr instruction"
+ (and (match_code "const_int")
+ (match_test "(ival & 0xffff8000) && nds32_can_use_bclr_p (ival)")))
+
+;; Ie15 is special and dedicated for performance extension
+;; 'bset' (single-bit-set) instruction.
+;; It is used in iorsi3 pattern and recognized for the immediate
+;; which is NOT in the range of imm15u but OK for 'bset' instruction.
+;; (If the immediate value IS in the range of imm15u,
+;; we can directly use 'ori' instruction.)
+(define_constraint "Ie15"
+ "A constant which is not in the range of imm15u but ok for bset instruction"
+ (and (match_code "const_int")
+ (match_test "(ival & 0xffff8000) && nds32_can_use_bset_p (ival)")))
+
+;; It15 is special and dedicated for performance extension
+;; 'btgl' (single-bit-toggle) instruction.
+;; It is used in xorsi3 pattern and recognized for the immediate
+;; which is NOT in the range of imm15u but OK for 'btgl' instruction.
+;; (If the immediate value IS in the range of imm15u,
+;; we can directly use 'xori' instruction.)
+(define_constraint "It15"
+ "A constant which is not in the range of imm15u but ok for btgl instruction"
+ (and (match_code "const_int")
+ (match_test "(ival & 0xffff8000) && nds32_can_use_btgl_p (ival)")))
+
+
+;; Ii15 is special and dedicated for v3 isa
+;; 'bitci' (bit-clear-immediate) instruction.
+;; It is used in andsi3 pattern and recognized for the immediate whose
+;; (~ival) value is in the range of imm15u and OK for 'bitci' instruction.
+;; For example, 'andi $r0,$r0,0xfffffffc' can be presented
+; with 'bitci $r0,$r0,3'.
+(define_constraint "Ii15"
+ "A constant whose compliment value is in the range of imm15u
+ and ok for bitci instruction"
+ (and (match_code "const_int")
+ (match_test "nds32_can_use_bitci_p (ival)")))
+
+
+(define_constraint "Is16"
+ "Signed immediate 16-bit value"
+ (and (match_code "const_int")
+ (match_test "ival < (1 << 15) && ival >= -(1 << 15)")))
+
+(define_constraint "Is17"
+ "Signed immediate 17-bit value"
+ (and (match_code "const_int")
+ (match_test "ival < (1 << 16) && ival >= -(1 << 16)")))
+
+
+(define_constraint "Is19"
+ "Signed immediate 19-bit value"
+ (and (match_code "const_int")
+ (match_test "ival < (1 << 18) && ival >= -(1 << 18)")))
+
+
+(define_constraint "Is20"
+ "Signed immediate 20-bit value"
+ (and (match_code "const_int")
+ (match_test "ival < (1 << 19) && ival >= -(1 << 19)")))
+
+
+(define_constraint "Ihig"
+ "The immediate value that can be simply set high 20-bit"
+ (and (match_code "const_int")
+ (match_test "(ival != 0) && ((ival & 0xfff) == 0)")))
+
+(define_constraint "Izeb"
+ "The immediate value 0xff"
+ (and (match_code "const_int")
+ (match_test "(ival == 0xff)")))
+
+(define_constraint "Izeh"
+ "The immediate value 0xffff"
+ (and (match_code "const_int")
+ (match_test "(ival == 0xffff)")))
+
+(define_constraint "Ixls"
+ "The immediate value 0x01"
+ (and (match_code "const_int")
+ (match_test "TARGET_PERF_EXT && (ival == 0x1)")))
+
+(define_constraint "Ix11"
+ "The immediate value 0x7ff"
+ (and (match_code "const_int")
+ (match_test "TARGET_PERF_EXT && (ival == 0x7ff)")))
+
+(define_constraint "Ibms"
+ "The immediate value with power of 2"
+ (and (match_code "const_int")
+ (match_test "(TARGET_ISA_V3 || TARGET_ISA_V3M)
+ && (IN_RANGE (exact_log2 (ival), 0, 7))")))
+
+(define_constraint "Ifex"
+ "The immediate value with power of 2 minus 1"
+ (and (match_code "const_int")
+ (match_test "(TARGET_ISA_V3 || TARGET_ISA_V3M)
+ && (IN_RANGE (exact_log2 (ival + 1), 1, 8))")))
+
+
+(define_memory_constraint "U33"
+ "Memory constraint for 333 format"
+ (and (match_code "mem")
+ (match_test "nds32_mem_format (op) == ADDRESS_LO_REG_IMM3U")))
+
+(define_memory_constraint "U45"
+ "Memory constraint for 45 format"
+ (and (match_code "mem")
+ (match_test "(nds32_mem_format (op) == ADDRESS_REG)
+ && (GET_MODE (op) == SImode)")))
+
+(define_memory_constraint "U37"
+ "Memory constraint for 37 format"
+ (and (match_code "mem")
+ (match_test "(nds32_mem_format (op) == ADDRESS_SP_IMM7U
+ || nds32_mem_format (op) == ADDRESS_FP_IMM7U)
+ && (GET_MODE (op) == SImode)")))
+
+;; ------------------------------------------------------------------------
diff --git a/gcc/config/nds32/iterators.md b/gcc/config/nds32/iterators.md
new file mode 100644
index 00000000000..6ec519618a9
--- /dev/null
+++ b/gcc/config/nds32/iterators.md
@@ -0,0 +1,55 @@
+;; Code and mode itertator and attribute definitions
+;; of Andes NDS32 cpu for GNU compiler
+;; Copyright (C) 2012-2013 Free Software Foundation, Inc.
+;; Contributed by Andes Technology Corporation.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 3, or (at your
+;; option) any later version.
+;;
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+;; License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3. If not see
+;; <http://www.gnu.org/licenses/>.
+
+;;----------------------------------------------------------------------------
+;; Mode iterators.
+;;----------------------------------------------------------------------------
+
+;; A list of integer modes that are up to one word long.
+(define_mode_iterator QIHISI [QI HI SI])
+
+;; A list of integer modes that are up to one half-word long.
+(define_mode_iterator QIHI [QI HI])
+
+;; A list of the modes that are up to double-word long.
+(define_mode_iterator DIDF [DI DF])
+
+
+;;----------------------------------------------------------------------------
+;; Mode attributes.
+;;----------------------------------------------------------------------------
+
+(define_mode_attr size [(QI "b") (HI "h") (SI "w")])
+
+(define_mode_attr byte [(QI "1") (HI "2") (SI "4")])
+
+
+;;----------------------------------------------------------------------------
+;; Code iterators.
+;;----------------------------------------------------------------------------
+
+
+;;----------------------------------------------------------------------------
+;; Code attributes.
+;;----------------------------------------------------------------------------
+
+
+;;----------------------------------------------------------------------------
diff --git a/gcc/config/nds32/nds32-doubleword.md b/gcc/config/nds32/nds32-doubleword.md
new file mode 100644
index 00000000000..4bfede4236a
--- /dev/null
+++ b/gcc/config/nds32/nds32-doubleword.md
@@ -0,0 +1,251 @@
+;; DImode/DFmode patterns description of Andes NDS32 cpu for GNU compiler
+;; Copyright (C) 2012-2013 Free Software Foundation, Inc.
+;; Contributed by Andes Technology Corporation.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 3, or (at your
+;; option) any later version.
+;;
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+;; License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3. If not see
+;; <http://www.gnu.org/licenses/>.
+
+
+;; -------------------------------------------------------------
+;; Move DImode/DFmode instructions.
+;; -------------------------------------------------------------
+
+
+(define_expand "movdi"
+ [(set (match_operand:DI 0 "general_operand" "")
+ (match_operand:DI 1 "general_operand" ""))]
+ ""
+{
+ /* Need to force register if mem <- !reg. */
+ if (MEM_P (operands[0]) && !REG_P (operands[1]))
+ operands[1] = force_reg (DImode, operands[1]);
+})
+
+(define_expand "movdf"
+ [(set (match_operand:DF 0 "general_operand" "")
+ (match_operand:DF 1 "general_operand" ""))]
+ ""
+{
+ /* Need to force register if mem <- !reg. */
+ if (MEM_P (operands[0]) && !REG_P (operands[1]))
+ operands[1] = force_reg (DFmode, operands[1]);
+})
+
+
+(define_insn "move_<mode>"
+ [(set (match_operand:DIDF 0 "nonimmediate_operand" "=r, r, r, m")
+ (match_operand:DIDF 1 "general_operand" " r, i, m, r"))]
+ ""
+{
+ rtx addr;
+ rtx otherops[5];
+
+ switch (which_alternative)
+ {
+ case 0:
+ return "movd44\t%0, %1";
+
+ case 1:
+ /* reg <- const_int, we ask gcc to split instruction. */
+ return "#";
+
+ case 2:
+ /* Refer to nds32_legitimate_address_p() in nds32.c,
+ we only allow "reg", "symbol_ref", "const", and "reg + const_int"
+ as address rtx for DImode/DFmode memory access. */
+ addr = XEXP (operands[1], 0);
+
+ otherops[0] = gen_rtx_REG (SImode, REGNO (operands[0]));
+ otherops[1] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
+ otherops[2] = addr;
+
+ if (REG_P (addr))
+ {
+ /* (reg) <- (mem (reg)) */
+ output_asm_insn ("lmw.bi\t%0, [%2], %1, 0", otherops);
+ }
+ else if (GET_CODE (addr) == PLUS)
+ {
+ /* (reg) <- (mem (plus (reg) (const_int))) */
+ rtx op0 = XEXP (addr, 0);
+ rtx op1 = XEXP (addr, 1);
+
+ if (REG_P (op0))
+ {
+ otherops[2] = op0;
+ otherops[3] = op1;
+ otherops[4] = gen_int_mode (INTVAL (op1) + 4, SImode);
+ }
+ else
+ {
+ otherops[2] = op1;
+ otherops[3] = op0;
+ otherops[4] = gen_int_mode (INTVAL (op0) + 4, SImode);
+ }
+
+ /* To avoid base overwrite when REGNO(%0) == REGNO(%2). */
+ if (REGNO (otherops[0]) != REGNO (otherops[2]))
+ {
+ output_asm_insn ("lwi\t%0, [%2 + (%3)]", otherops);
+ output_asm_insn ("lwi\t%1, [%2 + (%4)]", otherops);
+ }
+ else
+ {
+ output_asm_insn ("lwi\t%1, [%2 + (%4)]", otherops);
+ output_asm_insn ("lwi\t%0,[ %2 + (%3)]", otherops);
+ }
+ }
+ else
+ {
+ /* (reg) <- (mem (symbol_ref ...))
+ (reg) <- (mem (const ...)) */
+ output_asm_insn ("lwi.gp\t%0, [ + %2]", otherops);
+ output_asm_insn ("lwi.gp\t%1, [ + %2 + 4]", otherops);
+ }
+
+ /* We have already used output_asm_insn() by ourself,
+ so return an empty string. */
+ return "";
+
+ case 3:
+ /* Refer to nds32_legitimate_address_p() in nds32.c,
+ we only allow "reg", "symbol_ref", "const", and "reg + const_int"
+ as address rtx for DImode/DFmode memory access. */
+ addr = XEXP (operands[0], 0);
+
+ otherops[0] = gen_rtx_REG (SImode, REGNO (operands[1]));
+ otherops[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
+ otherops[2] = addr;
+
+ if (REG_P (addr))
+ {
+ /* (mem (reg)) <- (reg) */
+ output_asm_insn ("smw.bi\t%0, [%2], %1, 0", otherops);
+ }
+ else if (GET_CODE (addr) == PLUS)
+ {
+ /* (mem (plus (reg) (const_int))) <- (reg) */
+ rtx op0 = XEXP (addr, 0);
+ rtx op1 = XEXP (addr, 1);
+
+ if (REG_P (op0))
+ {
+ otherops[2] = op0;
+ otherops[3] = op1;
+ otherops[4] = gen_int_mode (INTVAL (op1) + 4, SImode);
+ }
+ else
+ {
+ otherops[2] = op1;
+ otherops[3] = op0;
+ otherops[4] = gen_int_mode (INTVAL (op0) + 4, SImode);
+ }
+
+ /* To avoid base overwrite when REGNO(%0) == REGNO(%2). */
+ if (REGNO (otherops[0]) != REGNO (otherops[2]))
+ {
+ output_asm_insn ("swi\t%0, [%2 + (%3)]", otherops);
+ output_asm_insn ("swi\t%1, [%2 + (%4)]", otherops);
+ }
+ else
+ {
+ output_asm_insn ("swi\t%1, [%2 + (%4)]", otherops);
+ output_asm_insn ("swi\t%0, [%2 + (%3)]", otherops);
+ }
+ }
+ else
+ {
+ /* (mem (symbol_ref ...)) <- (reg)
+ (mem (const ...)) <- (reg) */
+ output_asm_insn ("swi.gp\t%0, [ + %2]", otherops);
+ output_asm_insn ("swi.gp\t%1, [ + %2 + 4]", otherops);
+ }
+
+ /* We have already used output_asm_insn() by ourself,
+ so return an empty string. */
+ return "";
+
+ default:
+ gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "move,move,move,move")
+ (set_attr "length" " 4, 16, 8, 8")])
+
+(define_split
+ [(set (match_operand:DIDF 0 "register_operand" "")
+ (match_operand:DIDF 1 "const_double_operand" ""))]
+ "reload_completed"
+ [(set (match_dup 2) (match_dup 3))
+ (set (match_dup 4) (match_dup 5))]
+{
+ /* Construct lowpart rtx. */
+ operands[2] = gen_lowpart (SImode, operands[0]);
+ operands[3] = gen_lowpart (SImode, operands[1]);
+
+ /* Construct highpart rtx. */
+ /* Note that operands[1] can be VOIDmode constant,
+ so we need to use gen_highpart_mode().
+ Refer to gcc/emit-rtl.c for more information. */
+ operands[4] = gen_highpart (SImode, operands[0]);
+ operands[5] = gen_highpart_mode (SImode,
+ GET_MODE (operands[0]), operands[1]);
+
+ /* Actually we would like to create move behavior by ourself.
+ So that movsi expander could have chance to split large constant. */
+ emit_move_insn (operands[2], operands[3]);
+ emit_move_insn (operands[4], operands[5]);
+ DONE;
+})
+
+;; There is 'movd44' instruction for DImode/DFmode movement under V3/V3M ISA.
+;; We only need to split it under V2 ISA or none-16-bit code generation.
+(define_split
+ [(set (match_operand:DIDF 0 "register_operand" "")
+ (match_operand:DIDF 1 "register_operand" ""))]
+ "reload_completed
+ && (TARGET_ISA_V2 || !TARGET_16_BIT)"
+ [(set (match_dup 0) (match_dup 1))
+ (set (match_dup 2) (match_dup 3))]
+{
+ operands[2] = gen_highpart (SImode, operands[0]);
+ operands[3] = gen_highpart (SImode, operands[1]);
+ operands[0] = gen_lowpart (SImode, operands[0]);
+ operands[1] = gen_lowpart (SImode, operands[1]);
+
+ /* Handle a partial overlap. */
+ if (rtx_equal_p (operands[0], operands[3]))
+ {
+ rtx tmp0 = operands[0];
+ rtx tmp1 = operands[1];
+
+ operands[0] = operands[2];
+ operands[1] = operands[3];
+ operands[2] = tmp0;
+ operands[3] = tmp1;
+ }
+})
+
+;; -------------------------------------------------------------
+;; Boolean DImode instructions.
+;; -------------------------------------------------------------
+
+;; Nowadays, the generic code is supposed to split the DImode
+;; boolean operations and have good code generation.
+;; Unless we find out some bad cases, there is no need to
+;; define DImode boolean operations by ourself.
+
+;; -------------------------------------------------------------
diff --git a/gcc/config/nds32/nds32-intrinsic.md b/gcc/config/nds32/nds32-intrinsic.md
new file mode 100644
index 00000000000..4ee2d851023
--- /dev/null
+++ b/gcc/config/nds32/nds32-intrinsic.md
@@ -0,0 +1,97 @@
+;; Intrinsic patterns description of Andes NDS32 cpu for GNU compiler
+;; Copyright (C) 2012-2013 Free Software Foundation, Inc.
+;; Contributed by Andes Technology Corporation.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 3, or (at your
+;; option) any later version.
+;;
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+;; License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3. If not see
+;; <http://www.gnu.org/licenses/>.
+
+;; ------------------------------------------------------------------------
+
+;; Register Transfer.
+
+(define_insn "unspec_volatile_mfsr"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "i")] UNSPEC_VOLATILE_MFSR))]
+ ""
+ "mfsr\t%0, %V1"
+ [(set_attr "type" "misc")
+ (set_attr "length" "4")]
+)
+
+(define_insn "unspec_volatile_mfusr"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "i")] UNSPEC_VOLATILE_MFUSR))]
+ ""
+ "mfusr\t%0, %V1"
+ [(set_attr "type" "misc")
+ (set_attr "length" "4")]
+)
+
+(define_insn "unspec_volatile_mtsr"
+ [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")
+ (match_operand:SI 1 "immediate_operand" "i")] UNSPEC_VOLATILE_MTSR)]
+ ""
+ "mtsr\t%0, %V1"
+ [(set_attr "type" "misc")
+ (set_attr "length" "4")]
+)
+
+(define_insn "unspec_volatile_mtusr"
+ [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")
+ (match_operand:SI 1 "immediate_operand" "i")] UNSPEC_VOLATILE_MTUSR)]
+ ""
+ "mtusr\t%0, %V1"
+ [(set_attr "type" "misc")
+ (set_attr "length" "4")]
+)
+
+;; ------------------------------------------------------------------------
+
+;; Interrupt Instructions.
+
+(define_insn "unspec_volatile_setgie_en"
+ [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_SETGIE_EN)]
+ ""
+ "setgie.e"
+ [(set_attr "type" "misc")]
+)
+
+(define_insn "unspec_volatile_setgie_dis"
+ [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_SETGIE_DIS)]
+ ""
+ "setgie.d"
+ [(set_attr "type" "misc")]
+)
+
+;; ------------------------------------------------------------------------
+
+;; Cache Synchronization Instructions
+
+(define_insn "unspec_volatile_isync"
+ [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_VOLATILE_ISYNC)]
+ ""
+ "isync\t%0"
+ [(set_attr "type" "misc")]
+)
+
+(define_insn "unspec_volatile_isb"
+ [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_ISB)]
+ ""
+ "isb"
+ [(set_attr "type" "misc")]
+)
+
+;; ------------------------------------------------------------------------
diff --git a/gcc/config/nds32/nds32-modes.def b/gcc/config/nds32/nds32-modes.def
new file mode 100644
index 00000000000..9d32ada0ce8
--- /dev/null
+++ b/gcc/config/nds32/nds32-modes.def
@@ -0,0 +1,21 @@
+/* Extra machine modes of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>. */
+
+/* So far, there is no need to define any modes for nds32 target. */
diff --git a/gcc/config/nds32/nds32-multiple.md b/gcc/config/nds32/nds32-multiple.md
new file mode 100644
index 00000000000..da89a490d3a
--- /dev/null
+++ b/gcc/config/nds32/nds32-multiple.md
@@ -0,0 +1,410 @@
+;; Load/Store Multiple patterns description of Andes NDS32 cpu for GNU compiler
+;; Copyright (C) 2012-2013 Free Software Foundation, Inc.
+;; Contributed by Andes Technology Corporation.for NDS32.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 3, or (at your
+;; option) any later version.
+;;
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+;; License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3. If not see
+;; <http://www.gnu.org/licenses/>.
+
+
+;; Load Multiple Insns.
+;;
+;; operands[0] is the first of the consecutive registers.
+;; operands[1] is the first memory location.
+;; operands[2] is the number of consecutive registers.
+
+(define_expand "load_multiple"
+ [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
+ (match_operand:SI 1 "" ""))
+ (use (match_operand:SI 2 "" ""))])]
+ ""
+{
+ int maximum;
+
+ /* Because reduced-set regsiters has few registers
+ (r0~r5, r6~10, r15, r28~r31, where 'r15' and 'r28~r31' cannot
+ be used for register allocation),
+ using 8 registers for load_multiple may easily consume all of them.
+ It makes register allocation/spilling hard to work.
+ So we only allow maximum=4 registers for load_multiple
+ under reduced-set registers. */
+ if (TARGET_REDUCED_REGS)
+ maximum = 4;
+ else
+ maximum = 8;
+
+ /* Here are the conditions that must be all passed,
+ otherwise we have to FAIL this rtx generation:
+ 1. The number of consecutive registers must be integer.
+ 2. Maximum 4 or 8 registers for lmw.bi instruction
+ (based on this nds32-multiple.md design).
+ 3. Minimum 2 registers for lmw.bi instruction
+ (based on this nds32-multiple.md design).
+ 4. operands[0] must be register for sure.
+ 5. operands[1] must be memory for sure.
+ 6. Do not cross $r15 register because it is not allocatable. */
+ if (GET_CODE (operands[2]) != CONST_INT
+ || INTVAL (operands[2]) > maximum
+ || INTVAL (operands[2]) < 2
+ || GET_CODE (operands[0]) != REG
+ || GET_CODE (operands[1]) != MEM
+ || REGNO (operands[0]) + INTVAL (operands[2]) > TA_REGNUM)
+ FAIL;
+
+ /* For (mem addr), we force_reg on addr here,
+ so that nds32_expand_load_multiple can easily use it. */
+ operands[3] = nds32_expand_load_multiple (REGNO (operands[0]),
+ INTVAL (operands[2]),
+ force_reg (SImode,
+ XEXP (operands[1], 0)),
+ operands[1]);
+})
+
+;; Ordinary Load Multiple.
+
+(define_insn "*lmwsi8"
+ [(match_parallel 0 "nds32_load_multiple_operation"
+ [(set (match_operand:SI 2 "register_operand" "")
+ (mem:SI (match_operand:SI 1 "register_operand" "r")))
+ (set (match_operand:SI 3 "register_operand" "")
+ (mem:SI (plus:SI (match_dup 1) (const_int 4))))
+ (set (match_operand:SI 4 "register_operand" "")
+ (mem:SI (plus:SI (match_dup 1) (const_int 8))))
+ (set (match_operand:SI 5 "register_operand" "")
+ (mem:SI (plus:SI (match_dup 1) (const_int 12))))
+ (set (match_operand:SI 6 "register_operand" "")
+ (mem:SI (plus:SI (match_dup 1) (const_int 16))))
+ (set (match_operand:SI 7 "register_operand" "")
+ (mem:SI (plus:SI (match_dup 1) (const_int 20))))
+ (set (match_operand:SI 8 "register_operand" "")
+ (mem:SI (plus:SI (match_dup 1) (const_int 24))))
+ (set (match_operand:SI 9 "register_operand" "")
+ (mem:SI (plus:SI (match_dup 1) (const_int 28))))])]
+ "(XVECLEN (operands[0], 0) == 8)"
+ "lmw.bi\t%2, [%1], %9, 0x0"
+ [(set_attr "type" "load")
+ (set_attr "length" "4")]
+)
+
+(define_insn "*lmwsi7"
+ [(match_parallel 0 "nds32_load_multiple_operation"
+ [(set (match_operand:SI 2 "register_operand" "")
+ (mem:SI (match_operand:SI 1 "register_operand" "r")))
+ (set (match_operand:SI 3 "register_operand" "")
+ (mem:SI (plus:SI (match_dup 1) (const_int 4))))
+ (set (match_operand:SI 4 "register_operand" "")
+ (mem:SI (plus:SI (match_dup 1) (const_int 8))))
+ (set (match_operand:SI 5 "register_operand" "")
+ (mem:SI (plus:SI (match_dup 1) (const_int 12))))
+ (set (match_operand:SI 6 "register_operand" "")
+ (mem:SI (plus:SI (match_dup 1) (const_int 16))))
+ (set (match_operand:SI 7 "register_operand" "")
+ (mem:SI (plus:SI (match_dup 1) (const_int 20))))
+ (set (match_operand:SI 8 "register_operand" "")
+ (mem:SI (plus:SI (match_dup 1) (const_int 24))))])]
+ "(XVECLEN (operands[0], 0) == 7)"
+ "lmw.bi\t%2, [%1], %8, 0x0"
+ [(set_attr "type" "load")
+ (set_attr "length" "4")]
+)
+
+(define_insn "*lmwsi6"
+ [(match_parallel 0 "nds32_load_multiple_operation"
+ [(set (match_operand:SI 2 "register_operand" "")
+ (mem:SI (match_operand:SI 1 "register_operand" "r")))
+ (set (match_operand:SI 3 "register_operand" "")
+ (mem:SI (plus:SI (match_dup 1) (const_int 4))))
+ (set (match_operand:SI 4 "register_operand" "")
+ (mem:SI (plus:SI (match_dup 1) (const_int 8))))
+ (set (match_operand:SI 5 "register_operand" "")
+ (mem:SI (plus:SI (match_dup 1) (const_int 12))))
+ (set (match_operand:SI 6 "register_operand" "")
+ (mem:SI (plus:SI (match_dup 1) (const_int 16))))
+ (set (match_operand:SI 7 "register_operand" "")
+ (mem:SI (plus:SI (match_dup 1) (const_int 20))))])]
+ "(XVECLEN (operands[0], 0) == 6)"
+ "lmw.bi\t%2, [%1], %7, 0x0"
+ [(set_attr "type" "load")
+ (set_attr "length" "4")]
+)
+
+(define_insn "*lmwsi5"
+ [(match_parallel 0 "nds32_load_multiple_operation"
+ [(set (match_operand:SI 2 "register_operand" "")
+ (mem:SI (match_operand:SI 1 "register_operand" "r")))
+ (set (match_operand:SI 3 "register_operand" "")
+ (mem:SI (plus:SI (match_dup 1) (const_int 4))))
+ (set (match_operand:SI 4 "register_operand" "")
+ (mem:SI (plus:SI (match_dup 1) (const_int 8))))
+ (set (match_operand:SI 5 "register_operand" "")
+ (mem:SI (plus:SI (match_dup 1) (const_int 12))))
+ (set (match_operand:SI 6 "register_operand" "")
+ (mem:SI (plus:SI (match_dup 1) (const_int 16))))])]
+ "(XVECLEN (operands[0], 0) == 5)"
+ "lmw.bi\t%2, [%1], %6, 0x0"
+ [(set_attr "type" "load")
+ (set_attr "length" "4")]
+)
+
+(define_insn "*lmwsi4"
+ [(match_parallel 0 "nds32_load_multiple_operation"
+ [(set (match_operand:SI 2 "register_operand" "")
+ (mem:SI (match_operand:SI 1 "register_operand" "r")))
+ (set (match_operand:SI 3 "register_operand" "")
+ (mem:SI (plus:SI (match_dup 1) (const_int 4))))
+ (set (match_operand:SI 4 "register_operand" "")
+ (mem:SI (plus:SI (match_dup 1) (const_int 8))))
+ (set (match_operand:SI 5 "register_operand" "")
+ (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
+ "(XVECLEN (operands[0], 0) == 4)"
+ "lmw.bi\t%2, [%1], %5, 0x0"
+ [(set_attr "type" "load")
+ (set_attr "length" "4")]
+)
+
+(define_insn "*lmwsi3"
+ [(match_parallel 0 "nds32_load_multiple_operation"
+ [(set (match_operand:SI 2 "register_operand" "")
+ (mem:SI (match_operand:SI 1 "register_operand" "r")))
+ (set (match_operand:SI 3 "register_operand" "")
+ (mem:SI (plus:SI (match_dup 1) (const_int 4))))
+ (set (match_operand:SI 4 "register_operand" "")
+ (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
+ "(XVECLEN (operands[0], 0) == 3)"
+ "lmw.bi\t%2, [%1], %4, 0x0"
+ [(set_attr "type" "load")
+ (set_attr "length" "4")]
+)
+
+(define_insn "*lmwsi2"
+ [(match_parallel 0 "nds32_load_multiple_operation"
+ [(set (match_operand:SI 2 "register_operand" "")
+ (mem:SI (match_operand:SI 1 "register_operand" "r")))
+ (set (match_operand:SI 3 "register_operand" "")
+ (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
+ "(XVECLEN (operands[0], 0) == 2)"
+ "lmw.bi\t%2, [%1], %3, 0x0"
+ [(set_attr "type" "load")
+ (set_attr "length" "4")]
+)
+
+
+;; Store Multiple Insns.
+;;
+;; operands[0] is the first memory location.
+;; opernads[1] is the first of the consecutive registers.
+;; operands[2] is the number of consecutive registers.
+
+(define_expand "store_multiple"
+ [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
+ (match_operand:SI 1 "" ""))
+ (use (match_operand:SI 2 "" ""))])]
+ ""
+{
+ int maximum;
+
+ /* Because reduced-set regsiters has few registers
+ (r0~r5, r6~10, r15, r28~r31, where 'r15' and 'r28~r31' cannot
+ be used for register allocation),
+ using 8 registers for store_multiple may easily consume all of them.
+ It makes register allocation/spilling hard to work.
+ So we only allow maximum=4 registers for store_multiple
+ under reduced-set registers. */
+ if (TARGET_REDUCED_REGS)
+ maximum = 4;
+ else
+ maximum = 8;
+
+ /* Here are the conditions that must be all passed,
+ otherwise we have to FAIL this rtx generation:
+ 1. The number of consecutive registers must be integer.
+ 2. Maximum 4 or 8 registers for smw.bi instruction
+ (based on this nds32-multiple.md design).
+ 3. Minimum 2 registers for smw.bi instruction
+ (based on this nds32-multiple.md design).
+ 4. operands[0] must be memory for sure.
+ 5. operands[1] must be register for sure.
+ 6. Do not cross $r15 register because it is not allocatable. */
+ if (GET_CODE (operands[2]) != CONST_INT
+ || INTVAL (operands[2]) > maximum
+ || INTVAL (operands[2]) < 2
+ || GET_CODE (operands[0]) != MEM
+ || GET_CODE (operands[1]) != REG
+ || REGNO (operands[1]) + INTVAL (operands[2]) > TA_REGNUM)
+ FAIL;
+
+ /* For (mem addr), we force_reg on addr here,
+ so that nds32_expand_store_multiple can easily use it. */
+ operands[3] = nds32_expand_store_multiple (REGNO (operands[1]),
+ INTVAL (operands[2]),
+ force_reg (SImode,
+ XEXP (operands[0], 0)),
+ operands[0]);
+})
+
+;; Ordinary Store Multiple.
+
+(define_insn "*stmsi8"
+ [(match_parallel 0 "nds32_store_multiple_operation"
+ [(set (mem:SI (match_operand:SI 1 "register_operand" "r"))
+ (match_operand:SI 2 "register_operand" ""))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
+ (match_operand:SI 3 "register_operand" ""))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
+ (match_operand:SI 4 "register_operand" ""))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
+ (match_operand:SI 5 "register_operand" ""))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 16)))
+ (match_operand:SI 6 "register_operand" ""))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 20)))
+ (match_operand:SI 7 "register_operand" ""))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 24)))
+ (match_operand:SI 8 "register_operand" ""))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 28)))
+ (match_operand:SI 9 "register_operand" ""))])]
+ "(XVECLEN (operands[0], 0) == 8)"
+ "smw.bi\t%2, [%1], %9, 0x0"
+ [(set_attr "type" "store")
+ (set_attr "length" "4")]
+)
+
+(define_insn "*stmsi7"
+ [(match_parallel 0 "nds32_store_multiple_operation"
+ [(set (mem:SI (match_operand:SI 1 "register_operand" "r"))
+ (match_operand:SI 2 "register_operand" ""))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
+ (match_operand:SI 3 "register_operand" ""))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
+ (match_operand:SI 4 "register_operand" ""))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
+ (match_operand:SI 5 "register_operand" ""))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 16)))
+ (match_operand:SI 6 "register_operand" ""))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 20)))
+ (match_operand:SI 7 "register_operand" ""))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 24)))
+ (match_operand:SI 8 "register_operand" ""))])]
+ "(XVECLEN (operands[0], 0) == 7)"
+ "smw.bi\t%2, [%1], %8, 0x0"
+ [(set_attr "type" "store")
+ (set_attr "length" "4")]
+)
+
+(define_insn "*stmsi6"
+ [(match_parallel 0 "nds32_store_multiple_operation"
+ [(set (mem:SI (match_operand:SI 1 "register_operand" "r"))
+ (match_operand:SI 2 "register_operand" ""))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
+ (match_operand:SI 3 "register_operand" ""))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
+ (match_operand:SI 4 "register_operand" ""))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
+ (match_operand:SI 5 "register_operand" ""))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 16)))
+ (match_operand:SI 6 "register_operand" ""))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 20)))
+ (match_operand:SI 7 "register_operand" ""))])]
+ "(XVECLEN (operands[0], 0) == 6)"
+ "smw.bi\t%2, [%1], %7, 0x0"
+ [(set_attr "type" "store")
+ (set_attr "length" "4")]
+)
+
+(define_insn "*stmsi5"
+ [(match_parallel 0 "nds32_store_multiple_operation"
+ [(set (mem:SI (match_operand:SI 1 "register_operand" "r"))
+ (match_operand:SI 2 "register_operand" ""))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
+ (match_operand:SI 3 "register_operand" ""))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
+ (match_operand:SI 4 "register_operand" ""))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
+ (match_operand:SI 5 "register_operand" ""))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 16)))
+ (match_operand:SI 6 "register_operand" ""))])]
+ "(XVECLEN (operands[0], 0) == 5)"
+ "smw.bi\t%2, [%1], %6, 0x0"
+ [(set_attr "type" "store")
+ (set_attr "length" "4")]
+)
+
+(define_insn "*stmsi4"
+ [(match_parallel 0 "nds32_store_multiple_operation"
+ [(set (mem:SI (match_operand:SI 1 "register_operand" "r"))
+ (match_operand:SI 2 "register_operand" ""))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
+ (match_operand:SI 3 "register_operand" ""))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
+ (match_operand:SI 4 "register_operand" ""))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
+ (match_operand:SI 5 "register_operand" ""))])]
+ "(XVECLEN (operands[0], 0) == 4)"
+ "smw.bi\t%2, [%1], %5, 0x0"
+ [(set_attr "type" "store")
+ (set_attr "length" "4")]
+)
+
+(define_insn "*stmsi3"
+ [(match_parallel 0 "nds32_store_multiple_operation"
+ [(set (mem:SI (match_operand:SI 1 "register_operand" "r"))
+ (match_operand:SI 2 "register_operand" ""))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
+ (match_operand:SI 3 "register_operand" ""))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
+ (match_operand:SI 4 "register_operand" ""))])]
+ "(XVECLEN (operands[0], 0) == 3)"
+ "smw.bi\t%2, [%1], %4, 0x0"
+ [(set_attr "type" "store")
+ (set_attr "length" "4")]
+)
+
+(define_insn "*stmsi2"
+ [(match_parallel 0 "nds32_store_multiple_operation"
+ [(set (mem:SI (match_operand:SI 1 "register_operand" "r"))
+ (match_operand:SI 2 "register_operand" ""))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
+ (match_operand:SI 3 "register_operand" ""))])]
+ "(XVECLEN (operands[0], 0) == 2)"
+ "smw.bi\t%2, [%1], %3, 0x0"
+ [(set_attr "type" "store")
+ (set_attr "length" "4")]
+)
+
+;; Move a block of memory if it is word aligned and MORE than 2 words long.
+;; We could let this apply for blocks of less than this, but it clobbers so
+;; many registers that there is then probably a better way.
+;;
+;; operands[0] is the destination block of memory.
+;; operands[1] is the source block of memory.
+;; operands[2] is the number of bytes to move.
+;; operands[3] is the known shared alignment.
+
+(define_expand "movmemqi"
+ [(match_operand:BLK 0 "general_operand" "")
+ (match_operand:BLK 1 "general_operand" "")
+ (match_operand:SI 2 "const_int_operand" "")
+ (match_operand:SI 3 "const_int_operand" "")]
+ ""
+{
+ if (nds32_expand_movmemqi (operands[0],
+ operands[1],
+ operands[2],
+ operands[3]))
+ DONE;
+
+ FAIL;
+})
+
+;; ------------------------------------------------------------------------
diff --git a/gcc/config/nds32/nds32-opts.h b/gcc/config/nds32/nds32-opts.h
new file mode 100644
index 00000000000..b38672f0e2f
--- /dev/null
+++ b/gcc/config/nds32/nds32-opts.h
@@ -0,0 +1,35 @@
+/* Definitions for option handling of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ You should have 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 NDS32_OPTS_H
+#define NDS32_OPTS_H
+
+#define NDS32_DEFAULT_CACHE_BLOCK_SIZE 16
+#define NDS32_DEFAULT_ISR_VECTOR_SIZE (TARGET_ISA_V3 ? 4 : 16)
+
+/* The various ANDES ISA. */
+enum nds32_arch_type
+{
+ ARCH_V2,
+ ARCH_V3,
+ ARCH_V3M
+};
+
+#endif
diff --git a/gcc/config/nds32/nds32-peephole2.md b/gcc/config/nds32/nds32-peephole2.md
new file mode 100644
index 00000000000..dbe2d6c8a62
--- /dev/null
+++ b/gcc/config/nds32/nds32-peephole2.md
@@ -0,0 +1,25 @@
+;; define_peephole2 optimization patterns of Andes NDS32 cpu for GNU compiler
+;; Copyright (C) 2012-2013 Free Software Foundation, Inc.
+;; Contributed by Andes Technology Corporation.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 3, or (at your
+;; option) any later version.
+;;
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+;; License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3. If not see
+;; <http://www.gnu.org/licenses/>.
+
+
+;; Use define_peephole and define_peephole2 to handle possible
+;; target-specific optimization in this file.
+
+;; ------------------------------------------------------------------------
diff --git a/gcc/config/nds32/nds32-protos.h b/gcc/config/nds32/nds32-protos.h
new file mode 100644
index 00000000000..2bc405db0f4
--- /dev/null
+++ b/gcc/config/nds32/nds32-protos.h
@@ -0,0 +1,128 @@
+/* Prototypes for exported functions of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>. */
+
+
+/* ------------------------------------------------------------------------ */
+
+/* Defining Data Structures for Per-function Information. */
+
+extern void nds32_init_expanders (void);
+
+
+/* Register Usage. */
+
+/* -- How Values Fit in Registers. */
+
+extern int nds32_hard_regno_nregs (int, enum machine_mode);
+extern int nds32_hard_regno_mode_ok (int, enum machine_mode);
+
+
+/* Register Classes. */
+
+extern enum reg_class nds32_regno_reg_class (int);
+
+
+/* Stack Layout and Calling Conventions. */
+
+/* -- Basic Stack Layout. */
+
+extern rtx nds32_return_addr_rtx (int, rtx);
+
+/* -- Eliminating Frame Pointer and Arg Pointer. */
+
+extern HOST_WIDE_INT nds32_initial_elimination_offset (unsigned int,
+ unsigned int);
+
+/* -- Passing Arguments in Registers. */
+
+extern void nds32_init_cumulative_args (CUMULATIVE_ARGS *,
+ tree, rtx, tree, int);
+
+/* -- Function Entry and Exit. */
+
+extern void nds32_expand_prologue (void);
+extern void nds32_expand_epilogue (void);
+extern void nds32_expand_prologue_v3push (void);
+extern void nds32_expand_epilogue_v3pop (void);
+
+/* ------------------------------------------------------------------------ */
+
+/* Auxiliary functions for auxiliary macros in nds32.h. */
+
+extern bool nds32_ls_333_p (rtx, rtx, rtx, enum machine_mode);
+
+/* Auxiliary functions for expanding rtl used in nds32-multiple.md. */
+
+extern rtx nds32_expand_load_multiple (int, int, rtx, rtx);
+extern rtx nds32_expand_store_multiple (int, int, rtx, rtx);
+extern int nds32_expand_movmemqi (rtx, rtx, rtx, rtx);
+
+/* Auxiliary functions for multiple load/store predicate checking. */
+
+extern bool nds32_valid_multiple_load_store (rtx, bool);
+
+/* Auxiliary functions for stack operation predicate checking. */
+
+extern bool nds32_valid_stack_push_pop (rtx, bool);
+
+/* Auxiliary functions for bit operation detection. */
+
+extern int nds32_can_use_bclr_p (int);
+extern int nds32_can_use_bset_p (int);
+extern int nds32_can_use_btgl_p (int);
+
+extern int nds32_can_use_bitci_p (int);
+
+/* Auxiliary function for 'Computing the Length of an Insn'. */
+
+extern int nds32_adjust_insn_length (rtx, int);
+
+/* Auxiliary functions for FP_AS_GP detection. */
+
+extern bool nds32_symbol_load_store_p (rtx);
+extern int nds32_fp_as_gp_check_available (void);
+
+/* Auxiliary functions for jump table generation. */
+
+extern const char *nds32_output_casesi_pc_relative (rtx *);
+extern const char *nds32_output_casesi (rtx *);
+
+/* Auxiliary functions to identify 16 bit addresing mode. */
+
+extern enum nds32_16bit_address_type nds32_mem_format (rtx);
+
+/* Auxiliary functions to output assembly code. */
+
+extern const char *nds32_output_16bit_store (rtx *, int);
+extern const char *nds32_output_16bit_load (rtx *, int);
+extern const char *nds32_output_32bit_store (rtx *, int);
+extern const char *nds32_output_32bit_load (rtx *, int);
+extern const char *nds32_output_32bit_load_s (rtx *, int);
+
+/* Auxiliary functions to output stack push/pop instruction. */
+
+extern const char *nds32_output_stack_push (void);
+extern const char *nds32_output_stack_pop (void);
+
+/* Auxiliary functions to decide output alignment or not. */
+
+extern int nds32_target_alignment (rtx);
+
+/* ------------------------------------------------------------------------ */
diff --git a/gcc/config/nds32/nds32.c b/gcc/config/nds32/nds32.c
new file mode 100644
index 00000000000..2700a872360
--- /dev/null
+++ b/gcc/config/nds32/nds32.c
@@ -0,0 +1,5721 @@
+/* Subroutines used for code generation of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ You should have 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 "rtl.h"
+#include "regs.h"
+#include "hard-reg-set.h"
+#include "insn-config.h" /* Required by recog.h. */
+#include "conditions.h"
+#include "output.h"
+#include "insn-attr.h" /* For DFA state_t. */
+#include "insn-codes.h" /* For CODE_FOR_xxx. */
+#include "reload.h" /* For push_reload(). */
+#include "flags.h"
+#include "function.h"
+#include "expr.h"
+#include "recog.h"
+#include "diagnostic-core.h"
+#include "df.h"
+#include "tm_p.h"
+#include "tm-constrs.h"
+#include "optabs.h" /* For GEN_FCN. */
+#include "target.h"
+#include "target-def.h"
+#include "langhooks.h" /* For add_builtin_function(). */
+#include "ggc.h"
+
+/* ------------------------------------------------------------------------ */
+
+/* This file is divided into five parts:
+
+ PART 1: Auxiliary static variable definitions and
+ target hook static variable definitions.
+
+ PART 2: Auxiliary static function definitions.
+
+ PART 3: Implement target hook stuff definitions.
+
+ PART 4: Implemet extern function definitions,
+ the prototype is in nds32-protos.h.
+
+ PART 5: Initialize target hook structure and definitions. */
+
+/* ------------------------------------------------------------------------ */
+
+/* PART 1: Auxiliary static variable definitions and
+ target hook static variable definitions. */
+
+/* Refer to nds32.h, there are maximum 73 isr vectors in nds32 architecture.
+ 0 for reset handler with __attribute__((reset())),
+ 1-8 for exception handler with __attribute__((exception(1,...,8))),
+ and 9-72 for interrupt handler with __attribute__((interrupt(0,...,63))).
+ We use an array to record essential information for each vector. */
+static struct nds32_isr_info nds32_isr_vectors[NDS32_N_ISR_VECTORS];
+
+/* Define intrinsic register names.
+ Please refer to nds32_intrinsic.h file, the index is corresponding to
+ 'enum nds32_intrinsic_registers' data type values.
+ NOTE that the base value starting from 1024. */
+static const char * const nds32_intrinsic_register_names[] =
+{
+ "$PSW", "$IPSW", "$ITYPE", "$IPC"
+};
+
+/* Defining target-specific uses of __attribute__. */
+static const struct attribute_spec nds32_attribute_table[] =
+{
+ /* Syntax: { name, min_len, max_len, decl_required, type_required,
+ function_type_required, handler, affects_type_identity } */
+
+ /* The interrupt vid: [0-63]+ (actual vector number starts from 9 to 72). */
+ { "interrupt", 1, 64, false, false, false, NULL, false },
+ /* The exception vid: [1-8]+ (actual vector number starts from 1 to 8). */
+ { "exception", 1, 8, false, false, false, NULL, false },
+ /* Argument is user's interrupt numbers. The vector number is always 0. */
+ { "reset", 1, 1, false, false, false, NULL, false },
+
+ /* The attributes describing isr nested type. */
+ { "nested", 0, 0, false, false, false, NULL, false },
+ { "not_nested", 0, 0, false, false, false, NULL, false },
+ { "nested_ready", 0, 0, false, false, false, NULL, false },
+
+ /* The attributes describing isr register save scheme. */
+ { "save_all", 0, 0, false, false, false, NULL, false },
+ { "partial_save", 0, 0, false, false, false, NULL, false },
+
+ /* The attributes used by reset attribute. */
+ { "nmi", 1, 1, false, false, false, NULL, false },
+ { "warm", 1, 1, false, false, false, NULL, false },
+
+ /* The attribute telling no prologue/epilogue. */
+ { "naked", 0, 0, false, false, false, NULL, false },
+
+ /* The last attribute spec is set to be NULL. */
+ { NULL, 0, 0, false, false, false, NULL, false }
+};
+
+
+/* ------------------------------------------------------------------------ */
+
+/* PART 2: Auxiliary static function definitions. */
+
+/* Function to save and restore machine-specific function data. */
+static struct machine_function *
+nds32_init_machine_status (void)
+{
+ struct machine_function *machine;
+ machine = ggc_alloc_cleared_machine_function ();
+
+ /* Initially assume this function needs prologue/epilogue. */
+ machine->naked_p = 0;
+
+ /* Initially assume this function does NOT use fp_as_gp optimization. */
+ machine->fp_as_gp_p = 0;
+
+ return machine;
+}
+
+/* Function to compute stack frame size and
+ store into cfun->machine structure. */
+static void
+nds32_compute_stack_frame (void)
+{
+ int r;
+ int block_size;
+
+ /* Because nds32_compute_stack_frame() will be called from different place,
+ everytime we enter this function, we have to assume this function
+ needs prologue/epilogue. */
+ cfun->machine->naked_p = 0;
+
+ /* Get variadic arguments size to prepare pretend arguments and
+ push them into stack at prologue.
+ Currently, we do not push variadic arguments by ourself.
+ We have GCC handle all the works.
+ The caller will push all corresponding nameless arguments into stack,
+ and the callee is able to retrieve them without problems.
+ These variables are still preserved in case one day
+ we would like caller passing arguments with registers. */
+ cfun->machine->va_args_size = 0;
+ cfun->machine->va_args_first_regno = SP_REGNUM;
+ cfun->machine->va_args_last_regno = SP_REGNUM;
+
+ /* Get local variables, incoming variables, and temporary variables size.
+ Note that we need to make sure it is 8-byte alignment because
+ there may be no padding bytes if we are using LRA. */
+ cfun->machine->local_size = NDS32_ROUND_UP_DOUBLE_WORD (get_frame_size ());
+
+ /* Get outgoing arguments size. */
+ cfun->machine->out_args_size = crtl->outgoing_args_size;
+
+ /* If $fp value is required to be saved on stack, it needs 4 bytes space.
+ Check whether $fp is ever live. */
+ cfun->machine->fp_size = (df_regs_ever_live_p (FP_REGNUM)) ? 4 : 0;
+
+ /* If $gp value is required to be saved on stack, it needs 4 bytes space.
+ Check whether we are using PIC code genration. */
+ cfun->machine->gp_size = (flag_pic) ? 4 : 0;
+
+ /* If $lp value is required to be saved on stack, it needs 4 bytes space.
+ Check whether $lp is ever live. */
+ cfun->machine->lp_size = (df_regs_ever_live_p (LP_REGNUM)) ? 4 : 0;
+
+ /* Initially there is no padding bytes. */
+ cfun->machine->callee_saved_area_padding_bytes = 0;
+
+ /* Calculate the bytes of saving callee-saved registers on stack. */
+ cfun->machine->callee_saved_regs_size = 0;
+ cfun->machine->callee_saved_regs_first_regno = SP_REGNUM;
+ cfun->machine->callee_saved_regs_last_regno = SP_REGNUM;
+ /* Currently, there is no need to check $r28~$r31
+ because we will save them in another way. */
+ for (r = 0; r < 28; r++)
+ {
+ if (NDS32_REQUIRED_CALLEE_SAVED_P (r))
+ {
+ /* Mark the first required callee-saved register
+ (only need to set it once).
+ If first regno == SP_REGNUM, we can tell that
+ it is the first time to be here. */
+ if (cfun->machine->callee_saved_regs_first_regno == SP_REGNUM)
+ cfun->machine->callee_saved_regs_first_regno = r;
+ /* Mark the last required callee-saved register. */
+ cfun->machine->callee_saved_regs_last_regno = r;
+ }
+ }
+
+ /* Check if this function can omit prologue/epilogue code fragment.
+ If there is 'naked' attribute in this function,
+ we can set 'naked_p' flag to indicate that
+ we do not have to generate prologue/epilogue.
+ Or, if all the following conditions succeed,
+ we can set this function 'naked_p' as well:
+ condition 1: first_regno == last_regno == SP_REGNUM,
+ which means we do not have to save
+ any callee-saved registers.
+ condition 2: Both $lp and $fp are NOT live in this function,
+ which means we do not need to save them.
+ condition 3: There is no local_size, which means
+ we do not need to adjust $sp. */
+ if (lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl))
+ || (cfun->machine->callee_saved_regs_first_regno == SP_REGNUM
+ && cfun->machine->callee_saved_regs_last_regno == SP_REGNUM
+ && !df_regs_ever_live_p (FP_REGNUM)
+ && !df_regs_ever_live_p (LP_REGNUM)
+ && cfun->machine->local_size == 0))
+ {
+ /* Set this function 'naked_p' and
+ other functions can check this flag. */
+ cfun->machine->naked_p = 1;
+
+ /* No need to save $fp, $gp, and $lp.
+ We should set these value to be zero
+ so that nds32_initial_elimination_offset() can work properly. */
+ cfun->machine->fp_size = 0;
+ cfun->machine->gp_size = 0;
+ cfun->machine->lp_size = 0;
+
+ /* If stack usage computation is required,
+ we need to provide the static stack size. */
+ if (flag_stack_usage_info)
+ current_function_static_stack_size = 0;
+
+ /* No need to do following adjustment, return immediately. */
+ return;
+ }
+
+ /* Adjustment for v3push instructions:
+ If we are using v3push (push25/pop25) instructions,
+ we need to make sure Rb is $r6 and Re is
+ located on $r6, $r8, $r10, or $r14.
+ Some results above will be discarded and recomputed.
+ Note that it is only available under V3/V3M ISA. */
+ if (TARGET_V3PUSH)
+ {
+ /* Recompute:
+ cfun->machine->fp_size
+ cfun->machine->gp_size
+ cfun->machine->lp_size
+ cfun->machine->callee_saved_regs_first_regno
+ cfun->machine->callee_saved_regs_last_regno */
+
+ /* For v3push instructions, $fp, $gp, and $lp are always saved. */
+ cfun->machine->fp_size = 4;
+ cfun->machine->gp_size = 4;
+ cfun->machine->lp_size = 4;
+
+ /* Remember to set Rb = $r6. */
+ cfun->machine->callee_saved_regs_first_regno = 6;
+
+ if (cfun->machine->callee_saved_regs_last_regno <= 6)
+ {
+ /* Re = $r6 */
+ cfun->machine->callee_saved_regs_last_regno = 6;
+ }
+ else if (cfun->machine->callee_saved_regs_last_regno <= 8)
+ {
+ /* Re = $r8 */
+ cfun->machine->callee_saved_regs_last_regno = 8;
+ }
+ else if (cfun->machine->callee_saved_regs_last_regno <= 10)
+ {
+ /* Re = $r10 */
+ cfun->machine->callee_saved_regs_last_regno = 10;
+ }
+ else if (cfun->machine->callee_saved_regs_last_regno <= 14)
+ {
+ /* Re = $r14 */
+ cfun->machine->callee_saved_regs_last_regno = 14;
+ }
+ else if (cfun->machine->callee_saved_regs_last_regno == SP_REGNUM)
+ {
+ /* If last_regno is SP_REGNUM, which means
+ it is never changed, so set it to Re = $r6. */
+ cfun->machine->callee_saved_regs_last_regno = 6;
+ }
+ else
+ {
+ /* The program flow should not go here. */
+ gcc_unreachable ();
+ }
+ }
+
+ /* We have correctly set callee_saved_regs_first_regno
+ and callee_saved_regs_last_regno.
+ Initially, the callee_saved_regs_size is supposed to be 0.
+ As long as callee_saved_regs_last_regno is not SP_REGNUM,
+ we can update callee_saved_regs_size with new size. */
+ if (cfun->machine->callee_saved_regs_last_regno != SP_REGNUM)
+ {
+ /* Compute pushed size of callee-saved registers. */
+ cfun->machine->callee_saved_regs_size
+ = 4 * (cfun->machine->callee_saved_regs_last_regno
+ - cfun->machine->callee_saved_regs_first_regno
+ + 1);
+ }
+
+ /* Important: We need to make sure that
+ (va_args_size + fp_size + gp_size
+ + lp_size + callee_saved_regs_size)
+ is 8-byte alignment.
+ If it is not, calculate the padding bytes. */
+ block_size = cfun->machine->va_args_size
+ + cfun->machine->fp_size
+ + cfun->machine->gp_size
+ + cfun->machine->lp_size
+ + cfun->machine->callee_saved_regs_size;
+ if (!NDS32_DOUBLE_WORD_ALIGN_P (block_size))
+ {
+ cfun->machine->callee_saved_area_padding_bytes
+ = NDS32_ROUND_UP_DOUBLE_WORD (block_size) - block_size;
+ }
+
+ /* If stack usage computation is required,
+ we need to provide the static stack size. */
+ if (flag_stack_usage_info)
+ {
+ current_function_static_stack_size
+ = NDS32_ROUND_UP_DOUBLE_WORD (block_size)
+ + cfun->machine->local_size
+ + cfun->machine->out_args_size;
+ }
+}
+
+/* Function to create a parallel rtx pattern
+ which presents stack push multiple behavior.
+ The overall concept are:
+ "push registers to memory",
+ "adjust stack pointer". */
+static rtx
+nds32_gen_stack_push_multiple (rtx Rb, rtx Re,
+ rtx En4 ATTRIBUTE_UNUSED)
+{
+ int regno;
+ int extra_count;
+ int num_use_regs;
+ int par_index;
+ int offset;
+
+ rtx reg;
+ rtx mem;
+ rtx push_rtx;
+ rtx adjust_sp_rtx;
+ rtx parallel_insn;
+
+ /* We need to provide a customized rtx which contains
+ necessary information for data analysis,
+ so we create a parallel rtx like this:
+ (parallel [(set (mem (plus (reg:SI SP_REGNUM) (const_int -32)))
+ (reg:SI Rb))
+ (set (mem (plus (reg:SI SP_REGNUM) (const_int -28)))
+ (reg:SI Rb+1))
+ ...
+ (set (mem (plus (reg:SI SP_REGNUM) (const_int -16)))
+ (reg:SI Re))
+ (set (mem (plus (reg:SI SP_REGNUM) (const_int -12)))
+ (reg:SI FP_REGNUM))
+ (set (mem (plus (reg:SI SP_REGNUM) (const_int -8)))
+ (reg:SI GP_REGNUM))
+ (set (mem (plus (reg:SI SP_REGNUM) (const_int -4)))
+ (reg:SI LP_REGNUM))
+ (set (reg:SI SP_REGNUM)
+ (plus (reg:SI SP_REGNUM) (const_int -32)))]) */
+
+ /* Calculate the number of registers that will be pushed. */
+ extra_count = 0;
+ if (cfun->machine->fp_size)
+ extra_count++;
+ if (cfun->machine->gp_size)
+ extra_count++;
+ if (cfun->machine->lp_size)
+ extra_count++;
+ /* Note that Rb and Re may be SP_REGNUM. DO NOT count it in. */
+ if (REGNO (Rb) == SP_REGNUM && REGNO (Re) == SP_REGNUM)
+ num_use_regs = extra_count;
+ else
+ num_use_regs = REGNO (Re) - REGNO (Rb) + 1 + extra_count;
+
+ /* In addition to used registers,
+ we need one more space for (set sp sp-x) rtx. */
+ parallel_insn = gen_rtx_PARALLEL (VOIDmode,
+ rtvec_alloc (num_use_regs + 1));
+ par_index = 0;
+
+ /* Initialize offset and start to create push behavior. */
+ offset = -(num_use_regs * 4);
+
+ /* Create (set mem regX) from Rb, Rb+1 up to Re. */
+ for (regno = REGNO (Rb); regno <= (int) REGNO (Re); regno++)
+ {
+ /* Rb and Re may be SP_REGNUM.
+ We need to break this loop immediately. */
+ if (regno == SP_REGNUM)
+ break;
+
+ reg = gen_rtx_REG (SImode, regno);
+ mem = gen_frame_mem (SImode, plus_constant (Pmode,
+ stack_pointer_rtx,
+ offset));
+ push_rtx = gen_rtx_SET (VOIDmode, mem, reg);
+ XVECEXP (parallel_insn, 0, par_index) = push_rtx;
+ RTX_FRAME_RELATED_P (push_rtx) = 1;
+ offset = offset + 4;
+ par_index++;
+ }
+
+ /* Create (set mem fp), (set mem gp), and (set mem lp) if necessary. */
+ if (cfun->machine->fp_size)
+ {
+ reg = gen_rtx_REG (SImode, FP_REGNUM);
+ mem = gen_frame_mem (SImode, plus_constant (Pmode,
+ stack_pointer_rtx,
+ offset));
+ push_rtx = gen_rtx_SET (VOIDmode, mem, reg);
+ XVECEXP (parallel_insn, 0, par_index) = push_rtx;
+ RTX_FRAME_RELATED_P (push_rtx) = 1;
+ offset = offset + 4;
+ par_index++;
+ }
+ if (cfun->machine->gp_size)
+ {
+ reg = gen_rtx_REG (SImode, GP_REGNUM);
+ mem = gen_frame_mem (SImode, plus_constant (Pmode,
+ stack_pointer_rtx,
+ offset));
+ push_rtx = gen_rtx_SET (VOIDmode, mem, reg);
+ XVECEXP (parallel_insn, 0, par_index) = push_rtx;
+ RTX_FRAME_RELATED_P (push_rtx) = 1;
+ offset = offset + 4;
+ par_index++;
+ }
+ if (cfun->machine->lp_size)
+ {
+ reg = gen_rtx_REG (SImode, LP_REGNUM);
+ mem = gen_frame_mem (SImode, plus_constant (Pmode,
+ stack_pointer_rtx,
+ offset));
+ push_rtx = gen_rtx_SET (VOIDmode, mem, reg);
+ XVECEXP (parallel_insn, 0, par_index) = push_rtx;
+ RTX_FRAME_RELATED_P (push_rtx) = 1;
+ offset = offset + 4;
+ par_index++;
+ }
+
+ /* Create (set sp sp-x). */
+
+ /* We need to re-calculate the offset value again for adjustment. */
+ offset = -(num_use_regs * 4);
+ adjust_sp_rtx
+ = gen_rtx_SET (VOIDmode,
+ stack_pointer_rtx,
+ plus_constant (Pmode, stack_pointer_rtx, offset));
+ XVECEXP (parallel_insn, 0, par_index) = adjust_sp_rtx;
+ RTX_FRAME_RELATED_P (adjust_sp_rtx) = 1;
+
+ return parallel_insn;
+}
+
+/* Function to create a parallel rtx pattern
+ which presents stack pop multiple behavior.
+ The overall concept are:
+ "pop registers from memory",
+ "adjust stack pointer". */
+static rtx
+nds32_gen_stack_pop_multiple (rtx Rb, rtx Re,
+ rtx En4 ATTRIBUTE_UNUSED)
+{
+ int regno;
+ int extra_count;
+ int num_use_regs;
+ int par_index;
+ int offset;
+
+ rtx reg;
+ rtx mem;
+ rtx pop_rtx;
+ rtx adjust_sp_rtx;
+ rtx parallel_insn;
+
+ /* We need to provide a customized rtx which contains
+ necessary information for data analysis,
+ so we create a parallel rtx like this:
+ (parallel [(set (reg:SI Rb)
+ (mem (reg:SI SP_REGNUM)))
+ (set (reg:SI Rb+1)
+ (mem (plus (reg:SI SP_REGNUM) (const_int 4))))
+ ...
+ (set (reg:SI Re)
+ (mem (plus (reg:SI SP_REGNUM) (const_int 16))))
+ (set (reg:SI FP_REGNUM)
+ (mem (plus (reg:SI SP_REGNUM) (const_int 20))))
+ (set (reg:SI GP_REGNUM)
+ (mem (plus (reg:SI SP_REGNUM) (const_int 24))))
+ (set (reg:SI LP_REGNUM)
+ (mem (plus (reg:SI SP_REGNUM) (const_int 28))))
+ (set (reg:SI SP_REGNUM)
+ (plus (reg:SI SP_REGNUM) (const_int 32)))]) */
+
+ /* Calculate the number of registers that will be poped. */
+ extra_count = 0;
+ if (cfun->machine->fp_size)
+ extra_count++;
+ if (cfun->machine->gp_size)
+ extra_count++;
+ if (cfun->machine->lp_size)
+ extra_count++;
+ /* Note that Rb and Re may be SP_REGNUM. DO NOT count it in. */
+ if (REGNO (Rb) == SP_REGNUM && REGNO (Re) == SP_REGNUM)
+ num_use_regs = extra_count;
+ else
+ num_use_regs = REGNO (Re) - REGNO (Rb) + 1 + extra_count;
+
+ /* In addition to used registers,
+ we need one more space for (set sp sp+x) rtx. */
+ parallel_insn = gen_rtx_PARALLEL (VOIDmode,
+ rtvec_alloc (num_use_regs + 1));
+ par_index = 0;
+
+ /* Initialize offset and start to create pop behavior. */
+ offset = 0;
+
+ /* Create (set regX mem) from Rb, Rb+1 up to Re. */
+ for (regno = REGNO (Rb); regno <= (int) REGNO (Re); regno++)
+ {
+ /* Rb and Re may be SP_REGNUM.
+ We need to break this loop immediately. */
+ if (regno == SP_REGNUM)
+ break;
+
+ reg = gen_rtx_REG (SImode, regno);
+ mem = gen_frame_mem (SImode, plus_constant (Pmode,
+ stack_pointer_rtx,
+ offset));
+ pop_rtx = gen_rtx_SET (VOIDmode, reg, mem);
+ XVECEXP (parallel_insn, 0, par_index) = pop_rtx;
+ RTX_FRAME_RELATED_P (pop_rtx) = 1;
+ offset = offset + 4;
+ par_index++;
+ }
+
+ /* Create (set fp mem), (set gp mem), and (set lp mem) if necessary. */
+ if (cfun->machine->fp_size)
+ {
+ reg = gen_rtx_REG (SImode, FP_REGNUM);
+ mem = gen_frame_mem (SImode, plus_constant (Pmode,
+ stack_pointer_rtx,
+ offset));
+ pop_rtx = gen_rtx_SET (VOIDmode, reg, mem);
+ XVECEXP (parallel_insn, 0, par_index) = pop_rtx;
+ RTX_FRAME_RELATED_P (pop_rtx) = 1;
+ offset = offset + 4;
+ par_index++;
+ }
+ if (cfun->machine->gp_size)
+ {
+ reg = gen_rtx_REG (SImode, GP_REGNUM);
+ mem = gen_frame_mem (SImode, plus_constant (Pmode,
+ stack_pointer_rtx,
+ offset));
+ pop_rtx = gen_rtx_SET (VOIDmode, reg, mem);
+ XVECEXP (parallel_insn, 0, par_index) = pop_rtx;
+ RTX_FRAME_RELATED_P (pop_rtx) = 1;
+ offset = offset + 4;
+ par_index++;
+ }
+ if (cfun->machine->lp_size)
+ {
+ reg = gen_rtx_REG (SImode, LP_REGNUM);
+ mem = gen_frame_mem (SImode, plus_constant (Pmode,
+ stack_pointer_rtx,
+ offset));
+ pop_rtx = gen_rtx_SET (VOIDmode, reg, mem);
+ XVECEXP (parallel_insn, 0, par_index) = pop_rtx;
+ RTX_FRAME_RELATED_P (pop_rtx) = 1;
+ offset = offset + 4;
+ par_index++;
+ }
+
+ /* Create (set sp sp+x). */
+
+ /* The offset value is already in place. No need to re-calculate it. */
+ adjust_sp_rtx
+ = gen_rtx_SET (VOIDmode,
+ stack_pointer_rtx,
+ plus_constant (Pmode, stack_pointer_rtx, offset));
+ XVECEXP (parallel_insn, 0, par_index) = adjust_sp_rtx;
+ RTX_FRAME_RELATED_P (adjust_sp_rtx) = 1;
+
+ return parallel_insn;
+}
+
+/* Function to create a parallel rtx pattern
+ which presents stack v3push behavior.
+ The overall concept are:
+ "push registers to memory",
+ "adjust stack pointer". */
+static rtx
+nds32_gen_stack_v3push (rtx Rb,
+ rtx Re,
+ rtx En4 ATTRIBUTE_UNUSED,
+ rtx imm8u)
+{
+ int regno;
+ int num_use_regs;
+ int par_index;
+ int offset;
+
+ rtx reg;
+ rtx mem;
+ rtx push_rtx;
+ rtx adjust_sp_rtx;
+ rtx parallel_insn;
+
+ /* We need to provide a customized rtx which contains
+ necessary information for data analysis,
+ so we create a parallel rtx like this:
+ (parallel [
+ (set (mem (plus (reg:SI SP_REGNUM) (const_int -32)))
+ (reg:SI Rb))
+ (set (mem (plus (reg:SI SP_REGNUM) (const_int -28)))
+ (reg:SI Rb+1))
+ ...
+ (set (mem (plus (reg:SI SP_REGNUM) (const_int -16)))
+ (reg:SI Re))
+ (set (mem (plus (reg:SI SP_REGNUM) (const_int -12)))
+ (reg:SI FP_REGNUM))
+ (set (mem (plus (reg:SI SP_REGNUM) (const_int -8)))
+ (reg:SI GP_REGNUM))
+ (set (mem (plus (reg:SI SP_REGNUM) (const_int -4)))
+ (reg:SI LP_REGNUM))
+ (set (reg:SI SP_REGNUM)
+ (plus (reg:SI SP_REGNUM) (const_int -32-imm8u)))]) */
+
+ /* Calculate the number of registers that will be pushed.
+ Since $fp, $gp, and $lp is always pushed with v3push instruction,
+ we need to count these three registers.
+ Under v3push, Rb is $r6, while Re is $r6, $r8, $r10, or $r14.
+ So there is no need to worry about Rb=Re=SP_REGNUM case. */
+ num_use_regs = REGNO (Re) - REGNO (Rb) + 1 + 3;
+
+ /* In addition to used registers,
+ we need one more space for (set sp sp-x-imm8u) rtx. */
+ parallel_insn = gen_rtx_PARALLEL (VOIDmode,
+ rtvec_alloc (num_use_regs + 1));
+ par_index = 0;
+
+ /* Initialize offset and start to create push behavior. */
+ offset = -(num_use_regs * 4);
+
+ /* Create (set mem regX) from Rb, Rb+1 up to Re.
+ Under v3push, Rb is $r6, while Re is $r6, $r8, $r10, or $r14.
+ So there is no need to worry about Rb=Re=SP_REGNUM case. */
+ for (regno = REGNO (Rb); regno <= (int) REGNO (Re); regno++)
+ {
+ reg = gen_rtx_REG (SImode, regno);
+ mem = gen_frame_mem (SImode, plus_constant (Pmode,
+ stack_pointer_rtx,
+ offset));
+ push_rtx = gen_rtx_SET (VOIDmode, mem, reg);
+ XVECEXP (parallel_insn, 0, par_index) = push_rtx;
+ RTX_FRAME_RELATED_P (push_rtx) = 1;
+ offset = offset + 4;
+ par_index++;
+ }
+
+ /* Create (set mem fp). */
+ reg = gen_rtx_REG (SImode, FP_REGNUM);
+ mem = gen_frame_mem (SImode, plus_constant (Pmode,
+ stack_pointer_rtx,
+ offset));
+ push_rtx = gen_rtx_SET (VOIDmode, mem, reg);
+ XVECEXP (parallel_insn, 0, par_index) = push_rtx;
+ RTX_FRAME_RELATED_P (push_rtx) = 1;
+ offset = offset + 4;
+ par_index++;
+ /* Create (set mem gp). */
+ reg = gen_rtx_REG (SImode, GP_REGNUM);
+ mem = gen_frame_mem (SImode, plus_constant (Pmode,
+ stack_pointer_rtx,
+ offset));
+ push_rtx = gen_rtx_SET (VOIDmode, mem, reg);
+ XVECEXP (parallel_insn, 0, par_index) = push_rtx;
+ RTX_FRAME_RELATED_P (push_rtx) = 1;
+ offset = offset + 4;
+ par_index++;
+ /* Create (set mem lp). */
+ reg = gen_rtx_REG (SImode, LP_REGNUM);
+ mem = gen_frame_mem (SImode, plus_constant (Pmode,
+ stack_pointer_rtx,
+ offset));
+ push_rtx = gen_rtx_SET (VOIDmode, mem, reg);
+ XVECEXP (parallel_insn, 0, par_index) = push_rtx;
+ RTX_FRAME_RELATED_P (push_rtx) = 1;
+ offset = offset + 4;
+ par_index++;
+
+ /* Create (set sp sp-x-imm8u). */
+
+ /* We need to re-calculate the offset value again for adjustment. */
+ offset = -(num_use_regs * 4);
+ adjust_sp_rtx
+ = gen_rtx_SET (VOIDmode,
+ stack_pointer_rtx,
+ plus_constant (Pmode,
+ stack_pointer_rtx,
+ offset - INTVAL (imm8u)));
+ XVECEXP (parallel_insn, 0, par_index) = adjust_sp_rtx;
+ RTX_FRAME_RELATED_P (adjust_sp_rtx) = 1;
+
+ return parallel_insn;
+}
+
+/* Function to create a parallel rtx pattern
+ which presents stack v3pop behavior.
+ The overall concept are:
+ "pop registers from memory",
+ "adjust stack pointer". */
+static rtx
+nds32_gen_stack_v3pop (rtx Rb,
+ rtx Re,
+ rtx En4 ATTRIBUTE_UNUSED,
+ rtx imm8u)
+{
+ int regno;
+ int num_use_regs;
+ int par_index;
+ int offset;
+
+ rtx reg;
+ rtx mem;
+ rtx pop_rtx;
+ rtx adjust_sp_rtx;
+ rtx parallel_insn;
+
+ /* We need to provide a customized rtx which contains
+ necessary information for data analysis,
+ so we create a parallel rtx like this:
+ (parallel [(set (reg:SI Rb)
+ (mem (reg:SI SP_REGNUM)))
+ (set (reg:SI Rb+1)
+ (mem (plus (reg:SI SP_REGNUM) (const_int 4))))
+ ...
+ (set (reg:SI Re)
+ (mem (plus (reg:SI SP_REGNUM) (const_int 16))))
+ (set (reg:SI FP_REGNUM)
+ (mem (plus (reg:SI SP_REGNUM) (const_int 20))))
+ (set (reg:SI GP_REGNUM)
+ (mem (plus (reg:SI SP_REGNUM) (const_int 24))))
+ (set (reg:SI LP_REGNUM)
+ (mem (plus (reg:SI SP_REGNUM) (const_int 28))))
+ (set (reg:SI SP_REGNUM)
+ (plus (reg:SI SP_REGNUM) (const_int 32+imm8u)))]) */
+
+ /* Calculate the number of registers that will be poped.
+ Since $fp, $gp, and $lp is always poped with v3pop instruction,
+ we need to count these three registers.
+ Under v3push, Rb is $r6, while Re is $r6, $r8, $r10, or $r14.
+ So there is no need to worry about Rb=Re=SP_REGNUM case. */
+ num_use_regs = REGNO (Re) - REGNO (Rb) + 1 + 3;
+
+ /* In addition to used registers,
+ we need one more space for (set sp sp+x+imm8u) rtx. */
+ parallel_insn = gen_rtx_PARALLEL (VOIDmode,
+ rtvec_alloc (num_use_regs + 1));
+ par_index = 0;
+
+ /* Initialize offset and start to create pop behavior. */
+ offset = 0;
+
+ /* Create (set regX mem) from Rb, Rb+1 up to Re.
+ Under v3pop, Rb is $r6, while Re is $r6, $r8, $r10, or $r14.
+ So there is no need to worry about Rb=Re=SP_REGNUM case. */
+ for (regno = REGNO (Rb); regno <= (int) REGNO (Re); regno++)
+ {
+ reg = gen_rtx_REG (SImode, regno);
+ mem = gen_frame_mem (SImode, plus_constant (Pmode,
+ stack_pointer_rtx,
+ offset));
+ pop_rtx = gen_rtx_SET (VOIDmode, reg, mem);
+ XVECEXP (parallel_insn, 0, par_index) = pop_rtx;
+ RTX_FRAME_RELATED_P (pop_rtx) = 1;
+ offset = offset + 4;
+ par_index++;
+ }
+
+ /* Create (set fp mem). */
+ reg = gen_rtx_REG (SImode, FP_REGNUM);
+ mem = gen_frame_mem (SImode, plus_constant (Pmode,
+ stack_pointer_rtx,
+ offset));
+ pop_rtx = gen_rtx_SET (VOIDmode, reg, mem);
+ XVECEXP (parallel_insn, 0, par_index) = pop_rtx;
+ RTX_FRAME_RELATED_P (pop_rtx) = 1;
+ offset = offset + 4;
+ par_index++;
+ /* Create (set gp mem). */
+ reg = gen_rtx_REG (SImode, GP_REGNUM);
+ mem = gen_frame_mem (SImode, plus_constant (Pmode,
+ stack_pointer_rtx,
+ offset));
+ pop_rtx = gen_rtx_SET (VOIDmode, reg, mem);
+ XVECEXP (parallel_insn, 0, par_index) = pop_rtx;
+ RTX_FRAME_RELATED_P (pop_rtx) = 1;
+ offset = offset + 4;
+ par_index++;
+ /* Create (set lp mem ). */
+ reg = gen_rtx_REG (SImode, LP_REGNUM);
+ mem = gen_frame_mem (SImode, plus_constant (Pmode,
+ stack_pointer_rtx,
+ offset));
+ pop_rtx = gen_rtx_SET (VOIDmode, reg, mem);
+ XVECEXP (parallel_insn, 0, par_index) = pop_rtx;
+ RTX_FRAME_RELATED_P (pop_rtx) = 1;
+ offset = offset + 4;
+ par_index++;
+
+ /* Create (set sp sp+x+imm8u). */
+
+ /* The offset value is already in place. No need to re-calculate it. */
+ adjust_sp_rtx
+ = gen_rtx_SET (VOIDmode,
+ stack_pointer_rtx,
+ plus_constant (Pmode,
+ stack_pointer_rtx,
+ offset + INTVAL (imm8u)));
+ XVECEXP (parallel_insn, 0, par_index) = adjust_sp_rtx;
+ RTX_FRAME_RELATED_P (adjust_sp_rtx) = 1;
+
+ return parallel_insn;
+}
+
+/* A subroutine that checks multiple load and store
+ using consecutive registers.
+ OP is a parallel rtx we would like to check.
+ LOAD_P indicates whether we are checking load operation.
+ PAR_INDEX is starting element of parallel rtx.
+ FIRST_ELT_REGNO is used to tell starting register number.
+ COUNT helps us to check consecutive register numbers. */
+static bool
+nds32_consecutive_registers_load_store_p (rtx op,
+ bool load_p,
+ int par_index,
+ int first_elt_regno,
+ int count)
+{
+ int i;
+ int check_regno;
+ rtx elt;
+ rtx elt_reg;
+ rtx elt_mem;
+
+ for (i = 0; i < count; i++)
+ {
+ /* Pick up each element from parallel rtx. */
+ elt = XVECEXP (op, 0, i + par_index);
+
+ /* If this element is not a 'set' rtx, return false immediately. */
+ if (GET_CODE (elt) != SET)
+ return false;
+
+ /* Pick up reg and mem of this element. */
+ elt_reg = load_p ? SET_DEST (elt) : SET_SRC (elt);
+ elt_mem = load_p ? SET_SRC (elt) : SET_DEST (elt);
+
+ /* If elt_reg is not a expected reg rtx, return false. */
+ if (GET_CODE (elt_reg) != REG || GET_MODE (elt_reg) != SImode)
+ return false;
+ /* If elt_mem is not a expected mem rtx, return false. */
+ if (GET_CODE (elt_mem) != MEM || GET_MODE (elt_mem) != SImode)
+ return false;
+
+ /* The consecutive registers should be in (Rb,Rb+1...Re) order. */
+ check_regno = first_elt_regno + i;
+
+ /* If the register number is not continuous, return false. */
+ if (REGNO (elt_reg) != (unsigned int) check_regno)
+ return false;
+ }
+
+ return true;
+}
+
+/* A helper function to emit section head template. */
+static void
+nds32_emit_section_head_template (char section_name[],
+ char symbol_name[],
+ int align_value,
+ bool object_p)
+{
+ const char *flags_str;
+ const char *type_str;
+
+ flags_str = (object_p) ? "\"a\"" : "\"ax\"";
+ type_str = (object_p) ? "@object" : "@function";
+
+ fprintf (asm_out_file, "\t.section\t%s, %s\n", section_name, flags_str);
+ fprintf (asm_out_file, "\t.align\t%d\n", align_value);
+ fprintf (asm_out_file, "\t.global\t%s\n", symbol_name);
+ fprintf (asm_out_file, "\t.type\t%s, %s\n", symbol_name, type_str);
+ fprintf (asm_out_file, "%s:\n", symbol_name);
+}
+
+/* A helper function to emit section tail template. */
+static void
+nds32_emit_section_tail_template (char symbol_name[])
+{
+ fprintf (asm_out_file, "\t.size\t%s, .-%s\n", symbol_name, symbol_name);
+}
+
+/* Function to emit isr jump table section. */
+static void
+nds32_emit_isr_jmptbl_section (int vector_id)
+{
+ char section_name[100];
+ char symbol_name[100];
+
+ /* Prepare jmptbl section and symbol name. */
+ snprintf (section_name, sizeof (section_name),
+ ".nds32_jmptbl.%02d", vector_id);
+ snprintf (symbol_name, sizeof (symbol_name),
+ "_nds32_jmptbl_%02d", vector_id);
+
+ nds32_emit_section_head_template (section_name, symbol_name, 2, true);
+ fprintf (asm_out_file, "\t.word\t%s\n",
+ nds32_isr_vectors[vector_id].func_name);
+ nds32_emit_section_tail_template (symbol_name);
+}
+
+/* Function to emit isr vector section. */
+static void
+nds32_emit_isr_vector_section (int vector_id)
+{
+ unsigned int vector_number_offset = 0;
+ const char *c_str = "CATEGORY";
+ const char *sr_str = "SR";
+ const char *nt_str = "NT";
+ const char *vs_str = "VS";
+ char first_level_handler_name[100];
+ char section_name[100];
+ char symbol_name[100];
+
+ /* Set the vector number offset so that we can calculate
+ the value that user specifies in the attribute.
+ We also prepare the category string for first level handler name. */
+ switch (nds32_isr_vectors[vector_id].category)
+ {
+ case NDS32_ISR_INTERRUPT:
+ vector_number_offset = 9;
+ c_str = "i";
+ break;
+ case NDS32_ISR_EXCEPTION:
+ vector_number_offset = 0;
+ c_str = "e";
+ break;
+ case NDS32_ISR_NONE:
+ case NDS32_ISR_RESET:
+ /* Normally it should not be here. */
+ gcc_unreachable ();
+ break;
+ }
+
+ /* Prepare save reg string for first level handler name. */
+ switch (nds32_isr_vectors[vector_id].save_reg)
+ {
+ case NDS32_SAVE_ALL:
+ sr_str = "sa";
+ break;
+ case NDS32_PARTIAL_SAVE:
+ sr_str = "ps";
+ break;
+ }
+
+ /* Prepare nested type string for first level handler name. */
+ switch (nds32_isr_vectors[vector_id].nested_type)
+ {
+ case NDS32_NESTED:
+ nt_str = "ns";
+ break;
+ case NDS32_NOT_NESTED:
+ nt_str = "nn";
+ break;
+ case NDS32_NESTED_READY:
+ nt_str = "nr";
+ break;
+ }
+
+ /* Currently we have 4-byte or 16-byte size for each vector.
+ If it is 4-byte, the first level handler name has suffix string "_4b". */
+ vs_str = (nds32_isr_vector_size == 4) ? "_4b" : "";
+
+ /* Now we can create first level handler name. */
+ snprintf (first_level_handler_name, sizeof (first_level_handler_name),
+ "_nds32_%s_%s_%s%s", c_str, sr_str, nt_str, vs_str);
+
+ /* Prepare vector section and symbol name. */
+ snprintf (section_name, sizeof (section_name),
+ ".nds32_vector.%02d", vector_id);
+ snprintf (symbol_name, sizeof (symbol_name),
+ "_nds32_vector_%02d%s", vector_id, vs_str);
+
+
+ /* Everything is ready. We can start emit vector section content. */
+ nds32_emit_section_head_template (section_name, symbol_name,
+ floor_log2 (nds32_isr_vector_size), false);
+
+ /* According to the vector size, the instructions in the
+ vector section may be different. */
+ if (nds32_isr_vector_size == 4)
+ {
+ /* This block is for 4-byte vector size.
+ Hardware $VID support is necessary and only one instruction
+ is needed in vector section. */
+ fprintf (asm_out_file, "\tj\t%s ! jump to first level handler\n",
+ first_level_handler_name);
+ }
+ else
+ {
+ /* This block is for 16-byte vector size.
+ There is NO hardware $VID so that we need several instructions
+ such as pushing GPRs and preparing software vid at vector section.
+ For pushing GPRs, there are four variations for
+ 16-byte vector content and we have to handle each combination.
+ For preparing software vid, note that the vid need to
+ be substracted vector_number_offset. */
+ if (TARGET_REDUCED_REGS)
+ {
+ if (nds32_isr_vectors[vector_id].save_reg == NDS32_SAVE_ALL)
+ {
+ /* Case of reduced set registers and save_all attribute. */
+ fprintf (asm_out_file, "\t! reduced set regs + save_all\n");
+ fprintf (asm_out_file, "\tsmw.adm\t$r15, [$sp], $r15, 0xf\n");
+ fprintf (asm_out_file, "\tsmw.adm\t$r0, [$sp], $r10, 0x0\n");
+
+ }
+ else
+ {
+ /* Case of reduced set registers and partial_save attribute. */
+ fprintf (asm_out_file, "\t! reduced set regs + partial_save\n");
+ fprintf (asm_out_file, "\tsmw.adm\t$r15, [$sp], $r15, 0x2\n");
+ fprintf (asm_out_file, "\tsmw.adm\t$r0, [$sp], $r5, 0x0\n");
+ }
+ }
+ else
+ {
+ if (nds32_isr_vectors[vector_id].save_reg == NDS32_SAVE_ALL)
+ {
+ /* Case of full set registers and save_all attribute. */
+ fprintf (asm_out_file, "\t! full set regs + save_all\n");
+ fprintf (asm_out_file, "\tsmw.adm\t$r0, [$sp], $r27, 0xf\n");
+ }
+ else
+ {
+ /* Case of full set registers and partial_save attribute. */
+ fprintf (asm_out_file, "\t! full set regs + partial_save\n");
+ fprintf (asm_out_file, "\tsmw.adm\t$r15, [$sp], $r27, 0x2\n");
+ fprintf (asm_out_file, "\tsmw.adm\t$r0, [$sp], $r5, 0x0\n");
+ }
+ }
+
+ fprintf (asm_out_file, "\tmovi\t$r0, %d ! preparing software vid\n",
+ vector_id - vector_number_offset);
+ fprintf (asm_out_file, "\tj\t%s ! jump to first level handler\n",
+ first_level_handler_name);
+ }
+
+ nds32_emit_section_tail_template (symbol_name);
+}
+
+/* Function to emit isr reset handler content.
+ Including all jmptbl/vector references, jmptbl section,
+ vector section, nmi handler section, and warm handler section. */
+static void
+nds32_emit_isr_reset_content (void)
+{
+ unsigned int i;
+ unsigned int total_n_vectors;
+ const char *vs_str;
+ char reset_handler_name[100];
+ char section_name[100];
+ char symbol_name[100];
+
+ total_n_vectors = nds32_isr_vectors[0].total_n_vectors;
+ vs_str = (nds32_isr_vector_size == 4) ? "_4b" : "";
+
+ fprintf (asm_out_file, "\t! RESET HANDLER CONTENT - BEGIN !\n");
+
+ /* Create references in .rodata according to total number of vectors. */
+ fprintf (asm_out_file, "\t.section\t.rodata\n");
+ fprintf (asm_out_file, "\t.align\t2\n");
+
+ /* Emit jmptbl references. */
+ fprintf (asm_out_file, "\t ! references to jmptbl section entries\n");
+ for (i = 0; i < total_n_vectors; i++)
+ fprintf (asm_out_file, "\t.word\t_nds32_jmptbl_%02d\n", i);
+
+ /* Emit vector references. */
+ fprintf (asm_out_file, "\t ! references to vector section entries\n");
+ for (i = 0; i < total_n_vectors; i++)
+ fprintf (asm_out_file, "\t.word\t_nds32_vector_%02d%s\n", i, vs_str);
+
+ /* Emit jmptbl_00 section. */
+ snprintf (section_name, sizeof (section_name), ".nds32_jmptbl.00");
+ snprintf (symbol_name, sizeof (symbol_name), "_nds32_jmptbl_00");
+
+ fprintf (asm_out_file, "\t! ....................................\n");
+ nds32_emit_section_head_template (section_name, symbol_name, 2, true);
+ fprintf (asm_out_file, "\t.word\t%s\n",
+ nds32_isr_vectors[0].func_name);
+ nds32_emit_section_tail_template (symbol_name);
+
+ /* Emit vector_00 section. */
+ snprintf (section_name, sizeof (section_name), ".nds32_vector.00");
+ snprintf (symbol_name, sizeof (symbol_name), "_nds32_vector_00%s", vs_str);
+ snprintf (reset_handler_name, sizeof (reset_handler_name),
+ "_nds32_reset%s", vs_str);
+
+ fprintf (asm_out_file, "\t! ....................................\n");
+ nds32_emit_section_head_template (section_name, symbol_name,
+ floor_log2 (nds32_isr_vector_size), false);
+ fprintf (asm_out_file, "\tj\t%s ! jump to reset handler\n",
+ reset_handler_name);
+ nds32_emit_section_tail_template (symbol_name);
+
+ /* Emit nmi handler section. */
+ snprintf (section_name, sizeof (section_name), ".nds32_nmih");
+ snprintf (symbol_name, sizeof (symbol_name), "_nds32_nmih");
+
+ fprintf (asm_out_file, "\t! ....................................\n");
+ nds32_emit_section_head_template (section_name, symbol_name, 2, true);
+ fprintf (asm_out_file, "\t.word\t%s\n",
+ (strlen (nds32_isr_vectors[0].nmi_name) == 0)
+ ? "0"
+ : nds32_isr_vectors[0].nmi_name);
+ nds32_emit_section_tail_template (symbol_name);
+
+ /* Emit warm handler section. */
+ snprintf (section_name, sizeof (section_name), ".nds32_wrh");
+ snprintf (symbol_name, sizeof (symbol_name), "_nds32_wrh");
+
+ fprintf (asm_out_file, "\t! ....................................\n");
+ nds32_emit_section_head_template (section_name, symbol_name, 2, true);
+ fprintf (asm_out_file, "\t.word\t%s\n",
+ (strlen (nds32_isr_vectors[0].warm_name) == 0)
+ ? "0"
+ : nds32_isr_vectors[0].warm_name);
+ nds32_emit_section_tail_template (symbol_name);
+
+ fprintf (asm_out_file, "\t! RESET HANDLER CONTENT - END !\n");
+}
+
+/* Function for nds32_merge_decl_attributes() and nds32_insert_attributes()
+ to check if there are any conflict isr-specific attributes being set.
+ We need to check:
+ 1. Only 'save_all' or 'partial_save' in the attributes.
+ 2. Only 'nested', 'not_nested', or 'nested_ready' in the attributes.
+ 3. Only 'interrupt', 'exception', or 'reset' in the attributes. */
+static void
+nds32_check_isr_attrs_conflict (tree func_decl, tree func_attrs)
+{
+ int save_all_p, partial_save_p;
+ int nested_p, not_nested_p, nested_ready_p;
+ int intr_p, excp_p, reset_p;
+
+ /* Initialize variables. */
+ save_all_p = partial_save_p = 0;
+ nested_p = not_nested_p = nested_ready_p = 0;
+ intr_p = excp_p = reset_p = 0;
+
+ /* We must check at MOST one attribute to set save-reg. */
+ if (lookup_attribute ("save_all", func_attrs))
+ save_all_p = 1;
+ if (lookup_attribute ("partial_save", func_attrs))
+ partial_save_p = 1;
+
+ if ((save_all_p + partial_save_p) > 1)
+ error ("multiple save reg attributes to function %qD", func_decl);
+
+ /* We must check at MOST one attribute to set nested-type. */
+ if (lookup_attribute ("nested", func_attrs))
+ nested_p = 1;
+ if (lookup_attribute ("not_nested", func_attrs))
+ not_nested_p = 1;
+ if (lookup_attribute ("nested_ready", func_attrs))
+ nested_ready_p = 1;
+
+ if ((nested_p + not_nested_p + nested_ready_p) > 1)
+ error ("multiple nested types attributes to function %qD", func_decl);
+
+ /* We must check at MOST one attribute to
+ set interrupt/exception/reset. */
+ if (lookup_attribute ("interrupt", func_attrs))
+ intr_p = 1;
+ if (lookup_attribute ("exception", func_attrs))
+ excp_p = 1;
+ if (lookup_attribute ("reset", func_attrs))
+ reset_p = 1;
+
+ if ((intr_p + excp_p + reset_p) > 1)
+ error ("multiple interrupt attributes to function %qD", func_decl);
+}
+
+/* Function to construct isr vectors information array.
+ We DO NOT HAVE TO check if the attributes are valid
+ because those works are supposed to be done on
+ nds32_merge_decl_attributes() and nds32_insert_attributes(). */
+static void
+nds32_construct_isr_vectors_information (tree func_attrs,
+ const char *func_name)
+{
+ tree save_all, partial_save;
+ tree nested, not_nested, nested_ready;
+ tree intr, excp, reset;
+
+ save_all = lookup_attribute ("save_all", func_attrs);
+ partial_save = lookup_attribute ("partial_save", func_attrs);
+
+ nested = lookup_attribute ("nested", func_attrs);
+ not_nested = lookup_attribute ("not_nested", func_attrs);
+ nested_ready = lookup_attribute ("nested_ready", func_attrs);
+
+ intr = lookup_attribute ("interrupt", func_attrs);
+ excp = lookup_attribute ("exception", func_attrs);
+ reset = lookup_attribute ("reset", func_attrs);
+
+ /* If there is no interrupt/exception/reset, we can return immediately. */
+ if (!intr && !excp && !reset)
+ return;
+
+ /* If we are here, either we have interrupt/exception,
+ or reset attribute. */
+ if (intr || excp)
+ {
+ tree id_list;
+
+ /* Prepare id list so that we can traverse and set vector id. */
+ id_list = (intr) ? (TREE_VALUE (intr)) : (TREE_VALUE (excp));
+
+ while (id_list)
+ {
+ tree id;
+ int vector_id;
+ unsigned int vector_number_offset;
+
+ /* The way to handle interrupt or exception is the same,
+ we just need to take care of actual vector number.
+ For interrupt(0..63), the actual vector number is (9..72).
+ For exception(1..8), the actual vector number is (1..8). */
+ vector_number_offset = (intr) ? (9) : (0);
+
+ /* Pick up each vector id value. */
+ id = TREE_VALUE (id_list);
+ /* Add vector_number_offset to get actual vector number. */
+ vector_id = TREE_INT_CST_LOW (id) + vector_number_offset;
+
+ /* Enable corresponding vector and set function name. */
+ nds32_isr_vectors[vector_id].category = (intr)
+ ? (NDS32_ISR_INTERRUPT)
+ : (NDS32_ISR_EXCEPTION);
+ strcpy (nds32_isr_vectors[vector_id].func_name, func_name);
+
+ /* Set register saving scheme. */
+ if (save_all)
+ nds32_isr_vectors[vector_id].save_reg = NDS32_SAVE_ALL;
+ else if (partial_save)
+ nds32_isr_vectors[vector_id].save_reg = NDS32_PARTIAL_SAVE;
+
+ /* Set nested type. */
+ if (nested)
+ nds32_isr_vectors[vector_id].nested_type = NDS32_NESTED;
+ else if (not_nested)
+ nds32_isr_vectors[vector_id].nested_type = NDS32_NOT_NESTED;
+ else if (nested_ready)
+ nds32_isr_vectors[vector_id].nested_type = NDS32_NESTED_READY;
+
+ /* Advance to next id. */
+ id_list = TREE_CHAIN (id_list);
+ }
+ }
+ else
+ {
+ tree id_list;
+ tree id;
+ tree nmi, warm;
+
+ /* Deal with reset attribute. Its vector number is always 0. */
+ nds32_isr_vectors[0].category = NDS32_ISR_RESET;
+
+ /* Prepare id_list and identify id value so that
+ we can set total number of vectors. */
+ id_list = TREE_VALUE (reset);
+ id = TREE_VALUE (id_list);
+
+ /* The total vectors = interrupt + exception numbers + reset.
+ There are 8 exception and 1 reset in nds32 architecture. */
+ nds32_isr_vectors[0].total_n_vectors = TREE_INT_CST_LOW (id) + 8 + 1;
+ strcpy (nds32_isr_vectors[0].func_name, func_name);
+
+ /* Retrieve nmi and warm function. */
+ nmi = lookup_attribute ("nmi", func_attrs);
+ warm = lookup_attribute ("warm", func_attrs);
+
+ if (nmi != NULL_TREE)
+ {
+ tree nmi_func_list;
+ tree nmi_func;
+
+ nmi_func_list = TREE_VALUE (nmi);
+ nmi_func = TREE_VALUE (nmi_func_list);
+
+ /* Record nmi function name. */
+ strcpy (nds32_isr_vectors[0].nmi_name,
+ IDENTIFIER_POINTER (nmi_func));
+ }
+
+ if (warm != NULL_TREE)
+ {
+ tree warm_func_list;
+ tree warm_func;
+
+ warm_func_list = TREE_VALUE (warm);
+ warm_func = TREE_VALUE (warm_func_list);
+
+ /* Record warm function name. */
+ strcpy (nds32_isr_vectors[0].warm_name,
+ IDENTIFIER_POINTER (warm_func));
+ }
+ }
+}
+
+/* Function that may creates more instructions
+ for large value on adjusting stack pointer.
+
+ In nds32 target, 'addi' can be used for stack pointer
+ adjustment in prologue/epilogue stage.
+ However, sometimes there are too many local variables so that
+ the adjustment value is not able to be fit in the 'addi' instruction.
+ One solution is to move value into a register
+ and then use 'add' instruction.
+ In practice, we use TA_REGNUM ($r15) to accomplish this purpose.
+ Also, we need to return zero for sp adjustment so that
+ proglogue/epilogue knows there is no need to create 'addi' instruction. */
+static int
+nds32_force_addi_stack_int (int full_value)
+{
+ int adjust_value;
+
+ rtx tmp_reg;
+ rtx sp_adjust_insn;
+
+ if (!satisfies_constraint_Is15 (GEN_INT (full_value)))
+ {
+ /* The value is not able to fit in single addi instruction.
+ Create more instructions of moving value into a register
+ and then add stack pointer with it. */
+
+ /* $r15 is going to be temporary register to hold the value. */
+ tmp_reg = gen_rtx_REG (SImode, TA_REGNUM);
+
+ /* Create one more instruction to move value
+ into the temporary register. */
+ emit_move_insn (tmp_reg, GEN_INT (full_value));
+
+ /* Create new 'add' rtx. */
+ sp_adjust_insn = gen_addsi3 (stack_pointer_rtx,
+ stack_pointer_rtx,
+ tmp_reg);
+ /* Emit rtx into insn list and receive its transformed insn rtx. */
+ sp_adjust_insn = emit_insn (sp_adjust_insn);
+
+ /* At prologue, we need to tell GCC that this is frame related insn,
+ so that we can consider this instruction to output debug information.
+ If full_value is NEGATIVE, it means this function
+ is invoked by expand_prologue. */
+ if (full_value < 0)
+ {
+ /* Because (tmp_reg <- full_value) may be split into two
+ rtl patterns, we can not set its RTX_FRAME_RELATED_P.
+ We need to construct another (sp <- sp + full_value)
+ and then insert it into sp_adjust_insn's reg note to
+ represent a frame related expression.
+ GCC knows how to refer it and output debug information. */
+
+ rtx plus_rtx;
+ rtx set_rtx;
+
+ plus_rtx = plus_constant (Pmode, stack_pointer_rtx, full_value);
+ set_rtx = gen_rtx_SET (VOIDmode, stack_pointer_rtx, plus_rtx);
+ add_reg_note (sp_adjust_insn, REG_FRAME_RELATED_EXPR, set_rtx);
+
+ RTX_FRAME_RELATED_P (sp_adjust_insn) = 1;
+ }
+
+ /* We have used alternative way to adjust stack pointer value.
+ Return zero so that prologue/epilogue
+ will not generate other instructions. */
+ return 0;
+ }
+ else
+ {
+ /* The value is able to fit in addi instruction.
+ However, remember to make it to be positive value
+ because we want to return 'adjustment' result. */
+ adjust_value = (full_value < 0) ? (-full_value) : (full_value);
+
+ return adjust_value;
+ }
+}
+
+/* Return true if MODE/TYPE need double word alignment. */
+static bool
+nds32_needs_double_word_align (enum machine_mode mode, const_tree type)
+{
+ unsigned int align;
+
+ /* When 'type' is nonnull, there is no need to look at 'mode'. */
+ align = (type ? TYPE_ALIGN (type) : GET_MODE_ALIGNMENT (mode));
+
+ return (align > PARM_BOUNDARY);
+}
+
+/* Return true if FUNC is a naked function. */
+static bool nds32_naked_function_p (tree func)
+{
+ tree t;
+
+ if (TREE_CODE (func) != FUNCTION_DECL)
+ abort ();
+
+ t = lookup_attribute ("naked", DECL_ATTRIBUTES (func));
+
+ return (t != NULL_TREE);
+}
+
+/* Function that check if 'X' is a valid address register.
+ The variable 'STRICT' is very important to
+ make decision for register number.
+
+ STRICT : true
+ => We are in reload pass or after reload pass.
+ The register number should be strictly limited in general registers.
+
+ STRICT : false
+ => Before reload pass, we are free to use any register number. */
+static bool
+nds32_address_register_rtx_p (rtx x, bool strict)
+{
+ int regno;
+
+ if (GET_CODE (x) != REG)
+ return false;
+
+ regno = REGNO (x);
+
+ if (strict)
+ return REGNO_OK_FOR_BASE_P (regno);
+ else
+ return true;
+}
+
+/* Function that check if 'INDEX' is valid to be a index rtx for address.
+
+ OUTER_MODE : Machine mode of outer address rtx.
+ INDEX : Check if this rtx is valid to be a index for address.
+ STRICT : If it is true, we are in reload pass or after reload pass. */
+static bool
+nds32_legitimate_index_p (enum machine_mode outer_mode,
+ rtx index,
+ bool strict)
+{
+ int regno;
+ rtx op0;
+ rtx op1;
+
+ switch (GET_CODE (index))
+ {
+ case REG:
+ regno = REGNO (index);
+ /* If we are in reload pass or after reload pass,
+ we need to limit it to general register. */
+ if (strict)
+ return REGNO_OK_FOR_INDEX_P (regno);
+ else
+ return true;
+
+ case CONST_INT:
+ /* The alignment of the integer value is determined by 'outer_mode'. */
+ if (GET_MODE_SIZE (outer_mode) == 1)
+ {
+ /* Further check if the value is legal for the 'outer_mode'. */
+ if (!satisfies_constraint_Is15 (index))
+ return false;
+
+ /* Pass all test, the value is valid, return true. */
+ return true;
+ }
+ if (GET_MODE_SIZE (outer_mode) == 2
+ && NDS32_HALF_WORD_ALIGN_P (INTVAL (index)))
+ {
+ /* Further check if the value is legal for the 'outer_mode'. */
+ if (!satisfies_constraint_Is16 (index))
+ return false;
+
+ /* Pass all test, the value is valid, return true. */
+ return true;
+ }
+ if (GET_MODE_SIZE (outer_mode) == 4
+ && NDS32_SINGLE_WORD_ALIGN_P (INTVAL (index)))
+ {
+ /* Further check if the value is legal for the 'outer_mode'. */
+ if (!satisfies_constraint_Is17 (index))
+ return false;
+
+ /* Pass all test, the value is valid, return true. */
+ return true;
+ }
+ if (GET_MODE_SIZE (outer_mode) == 8
+ && NDS32_SINGLE_WORD_ALIGN_P (INTVAL (index)))
+ {
+ /* Further check if the value is legal for the 'outer_mode'. */
+ if (!satisfies_constraint_Is17 (gen_int_mode (INTVAL (index) + 4,
+ SImode)))
+ return false;
+
+ /* Pass all test, the value is valid, return true. */
+ return true;
+ }
+
+ return false;
+
+ case MULT:
+ op0 = XEXP (index, 0);
+ op1 = XEXP (index, 1);
+
+ if (REG_P (op0) && CONST_INT_P (op1))
+ {
+ int multiplier;
+ multiplier = INTVAL (op1);
+
+ /* We only allow (mult reg const_int_1)
+ or (mult reg const_int_2) or (mult reg const_int_4). */
+ if (multiplier != 1 && multiplier != 2 && multiplier != 4)
+ return false;
+
+ regno = REGNO (op0);
+ /* Limit it in general registers if we are
+ in reload pass or after reload pass. */
+ if(strict)
+ return REGNO_OK_FOR_INDEX_P (regno);
+ else
+ return true;
+ }
+
+ return false;
+
+ case ASHIFT:
+ op0 = XEXP (index, 0);
+ op1 = XEXP (index, 1);
+
+ if (REG_P (op0) && CONST_INT_P (op1))
+ {
+ int sv;
+ /* op1 is already the sv value for use to do left shift. */
+ sv = INTVAL (op1);
+
+ /* We only allow (ashift reg const_int_0)
+ or (ashift reg const_int_1) or (ashift reg const_int_2). */
+ if (sv != 0 && sv != 1 && sv !=2)
+ return false;
+
+ regno = REGNO (op0);
+ /* Limit it in general registers if we are
+ in reload pass or after reload pass. */
+ if(strict)
+ return REGNO_OK_FOR_INDEX_P (regno);
+ else
+ return true;
+ }
+
+ return false;
+
+ default:
+ return false;
+ }
+}
+
+/* Function to expand builtin function for
+ '[(unspec_volatile [(reg)])]'. */
+static rtx
+nds32_expand_builtin_null_ftype_reg (enum insn_code icode,
+ tree exp, rtx target)
+{
+ /* Mapping:
+ ops[0] <--> value0 <--> arg0 */
+ struct expand_operand ops[1];
+ tree arg0;
+ rtx value0;
+
+ /* Grab the incoming arguments and extract its rtx. */
+ arg0 = CALL_EXPR_ARG (exp, 0);
+ value0 = expand_normal (arg0);
+
+ /* Create operands. */
+ create_input_operand (&ops[0], value0, TYPE_MODE (TREE_TYPE (arg0)));
+
+ /* Emit new instruction. */
+ if (!maybe_expand_insn (icode, 1, ops))
+ error ("invalid argument to built-in function");
+
+ return target;
+}
+
+/* Function to expand builtin function for
+ '[(set (reg) (unspec_volatile [(imm)]))]'. */
+static rtx
+nds32_expand_builtin_reg_ftype_imm (enum insn_code icode,
+ tree exp, rtx target)
+{
+ /* Mapping:
+ ops[0] <--> target <--> exp
+ ops[1] <--> value0 <--> arg0 */
+ struct expand_operand ops[2];
+ tree arg0;
+ rtx value0;
+
+ /* Grab the incoming arguments and extract its rtx. */
+ arg0 = CALL_EXPR_ARG (exp, 0);
+ value0 = expand_normal (arg0);
+
+ /* Create operands. */
+ create_output_operand (&ops[0], target, TYPE_MODE (TREE_TYPE (exp)));
+ create_input_operand (&ops[1], value0, TYPE_MODE (TREE_TYPE (arg0)));
+
+ /* Emit new instruction. */
+ if (!maybe_expand_insn (icode, 2, ops))
+ error ("invalid argument to built-in function");
+
+ return target;
+}
+
+/* Function to expand builtin function for
+ '[(unspec_volatile [(reg) (imm)])]' pattern. */
+static rtx
+nds32_expand_builtin_null_ftype_reg_imm (enum insn_code icode,
+ tree exp, rtx target)
+{
+ /* Mapping:
+ ops[0] <--> value0 <--> arg0
+ ops[1] <--> value1 <--> arg1 */
+ struct expand_operand ops[2];
+ tree arg0, arg1;
+ rtx value0, value1;
+
+ /* Grab the incoming arguments and extract its rtx. */
+ arg0 = CALL_EXPR_ARG (exp, 0);
+ arg1 = CALL_EXPR_ARG (exp, 1);
+ value0 = expand_normal (arg0);
+ value1 = expand_normal (arg1);
+
+ /* Create operands. */
+ create_input_operand (&ops[0], value0, TYPE_MODE (TREE_TYPE (arg0)));
+ create_input_operand (&ops[1], value1, TYPE_MODE (TREE_TYPE (arg1)));
+
+ /* Emit new instruction. */
+ if (!maybe_expand_insn (icode, 2, ops))
+ error ("invalid argument to built-in function");
+
+ return target;
+}
+
+/* A helper function to return character based on byte size. */
+static char
+nds32_byte_to_size (int byte)
+{
+ switch (byte)
+ {
+ case 4:
+ return 'w';
+ case 2:
+ return 'h';
+ case 1:
+ return 'b';
+ default:
+ /* Normally it should not be here. */
+ gcc_unreachable ();
+ }
+}
+
+/* A helper function to check if this function should contain prologue. */
+static int
+nds32_have_prologue_p (void)
+{
+ int i;
+
+ for (i = 0; i < 28; i++)
+ if (NDS32_REQUIRED_CALLEE_SAVED_P (i))
+ return 1;
+
+ return (flag_pic
+ || NDS32_REQUIRED_CALLEE_SAVED_P (FP_REGNUM)
+ || NDS32_REQUIRED_CALLEE_SAVED_P (LP_REGNUM));
+}
+
+/* ------------------------------------------------------------------------ */
+
+/* PART 3: Implement target hook stuff definitions. */
+
+/* Register Classes. */
+
+static unsigned char
+nds32_class_max_nregs (reg_class_t rclass ATTRIBUTE_UNUSED,
+ enum machine_mode mode)
+{
+ /* Return the maximum number of consecutive registers
+ needed to represent "mode" in a register of "rclass". */
+ return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD);
+}
+
+static int
+nds32_register_priority (int hard_regno)
+{
+ /* Encourage to use r0-r7 for LRA when optimize for size. */
+ if (optimize_size && hard_regno < 8)
+ return 4;
+ return 3;
+}
+
+
+/* Stack Layout and Calling Conventions. */
+
+/* There are three kinds of pointer concepts using in GCC compiler:
+
+ frame pointer: A pointer to the first location of local variables.
+ stack pointer: A pointer to the top of a stack frame.
+ argument pointer: A pointer to the incoming arguments.
+
+ In nds32 target calling convention, we are using 8-byte alignment.
+ Besides, we would like to have each stack frame of a function includes:
+
+ [Block A]
+ 1. previous hard frame pointer
+ 2. return address
+ 3. callee-saved registers
+ 4. <padding bytes> (we will calculte in nds32_compute_stack_frame()
+ and save it at
+ cfun->machine->callee_saved_area_padding_bytes)
+
+ [Block B]
+ 1. local variables
+ 2. spilling location
+ 3. <padding bytes> (it will be calculated by GCC itself)
+ 4. incoming arguments
+ 5. <padding bytes> (it will be calculated by GCC itself)
+
+ [Block C]
+ 1. <padding bytes> (it will be calculated by GCC itself)
+ 2. outgoing arguments
+
+ We 'wrap' these blocks together with
+ hard frame pointer ($r28) and stack pointer ($r31).
+ By applying the basic frame/stack/argument pointers concept,
+ the layout of a stack frame shoule be like this:
+
+ | |
+ old stack pointer -> ----
+ | | \
+ | | saved arguments for
+ | | vararg functions
+ | | /
+ hard frame pointer -> --
+ & argument pointer | | \
+ | | previous hardware frame pointer
+ | | return address
+ | | callee-saved registers
+ | | /
+ frame pointer -> --
+ | | \
+ | | local variables
+ | | and incoming arguments
+ | | /
+ --
+ | | \
+ | | outgoing
+ | | arguments
+ | | /
+ stack pointer -> ----
+
+ $SFP and $AP are used to represent frame pointer and arguments pointer,
+ which will be both eliminated as hard frame pointer. */
+
+/* -- Eliminating Frame Pointer and Arg Pointer. */
+
+static bool nds32_can_eliminate (const int from_reg, const int to_reg)
+{
+ if (from_reg == ARG_POINTER_REGNUM && to_reg == STACK_POINTER_REGNUM)
+ return true;
+
+ if (from_reg == ARG_POINTER_REGNUM && to_reg == HARD_FRAME_POINTER_REGNUM)
+ return true;
+
+ if (from_reg == FRAME_POINTER_REGNUM && to_reg == STACK_POINTER_REGNUM)
+ return true;
+
+ if (from_reg == FRAME_POINTER_REGNUM && to_reg == HARD_FRAME_POINTER_REGNUM)
+ return true;
+
+ return false;
+}
+
+/* -- Passing Arguments in Registers. */
+
+static rtx
+nds32_function_arg (cumulative_args_t ca, enum machine_mode mode,
+ const_tree type, bool named)
+{
+ CUMULATIVE_ARGS *cum = get_cumulative_args (ca);
+
+ /* The last time this hook is called,
+ it is called with MODE == VOIDmode. */
+ if (mode == VOIDmode)
+ return NULL_RTX;
+
+ /* For nameless arguments, they are passed on the stack. */
+ if (!named)
+ return NULL_RTX;
+
+ /* If there are still registers available, return it. */
+ if (NDS32_ARG_PASS_IN_REG_P (cum->reg_offset, mode, type))
+ {
+ /* Pick up the next available register number. */
+ return gen_rtx_REG (mode,
+ NDS32_AVAILABLE_REGNUM_FOR_ARG (cum->reg_offset,
+ mode,
+ type));
+ }
+ else
+ {
+ /* No register available, return NULL_RTX.
+ The compiler will use stack to pass argument instead. */
+ return NULL_RTX;
+ }
+}
+
+static void
+nds32_function_arg_advance (cumulative_args_t ca, enum machine_mode mode,
+ const_tree type, bool named)
+{
+ CUMULATIVE_ARGS *cum = get_cumulative_args (ca);
+
+ /* Advance next register for use.
+ Only named argument could be advanced. */
+ if (named)
+ {
+ cum->reg_offset
+ = NDS32_AVAILABLE_REGNUM_FOR_ARG (cum->reg_offset, mode, type)
+ - NDS32_GPR_ARG_FIRST_REGNUM
+ + NDS32_NEED_N_REGS_FOR_ARG (mode, type);
+ }
+}
+
+static unsigned int
+nds32_function_arg_boundary (enum machine_mode mode, const_tree type)
+{
+ return (nds32_needs_double_word_align (mode, type)
+ ? NDS32_DOUBLE_WORD_ALIGNMENT
+ : PARM_BOUNDARY);
+}
+
+/* -- How Scalar Function Values Are Returned. */
+
+static rtx
+nds32_function_value (const_tree ret_type,
+ const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
+ bool outgoing ATTRIBUTE_UNUSED)
+{
+ enum machine_mode mode;
+ int unsignedp;
+
+ mode = TYPE_MODE (ret_type);
+ unsignedp = TYPE_UNSIGNED (ret_type);
+
+ mode = promote_mode (ret_type, mode, &unsignedp);
+
+ return gen_rtx_REG (mode, NDS32_GPR_RET_FIRST_REGNUM);
+}
+
+static rtx
+nds32_libcall_value (enum machine_mode mode,
+ const_rtx fun ATTRIBUTE_UNUSED)
+{
+ return gen_rtx_REG (mode, NDS32_GPR_RET_FIRST_REGNUM);
+}
+
+static bool
+nds32_function_value_regno_p (const unsigned int regno)
+{
+ return (regno == NDS32_GPR_RET_FIRST_REGNUM);
+}
+
+/* -- Function Entry and Exit. */
+
+/* The content produced from this function
+ will be placed before prologue body. */
+static void
+nds32_asm_function_prologue (FILE *file,
+ HOST_WIDE_INT size ATTRIBUTE_UNUSED)
+{
+ int r;
+ const char *func_name;
+ tree attrs;
+ tree name;
+
+ /* All stack frame information is supposed to be
+ already computed when expanding prologue.
+ The result is in cfun->machine.
+ DO NOT call nds32_compute_stack_frame() here
+ because it may corrupt the essential information. */
+
+ fprintf (file, "\t! BEGIN PROLOGUE\n");
+ fprintf (file, "\t! fp needed: %d\n", frame_pointer_needed);
+ fprintf (file, "\t! pretend_args: %d\n", cfun->machine->va_args_size);
+ fprintf (file, "\t! local_size: %d\n", cfun->machine->local_size);
+ fprintf (file, "\t! out_args_size: %d\n", cfun->machine->out_args_size);
+
+ /* Use df_regs_ever_live_p() to detect if the register
+ is ever used in the current function. */
+ fprintf (file, "\t! registers ever_live: ");
+ for (r = 0; r < 32; r++)
+ {
+ if (df_regs_ever_live_p (r))
+ fprintf (file, "%s, ", reg_names[r]);
+ }
+ fputc ('\n', file);
+
+ /* Display the attributes of this function. */
+ fprintf (file, "\t! function attributes: ");
+ /* GCC build attributes list with reverse order,
+ so we use nreverse() to make it looks like
+ the order that user specifies. */
+ attrs = nreverse (DECL_ATTRIBUTES (current_function_decl));
+
+ /* If there is no any attribute, print out "None". */
+ if (!attrs)
+ fprintf (file, "None");
+
+ /* If there are some attributes, try if we need to
+ construct isr vector information. */
+ func_name = IDENTIFIER_POINTER (DECL_NAME (current_function_decl));
+ nds32_construct_isr_vectors_information (attrs, func_name);
+
+ /* Display all attributes of this function. */
+ while (attrs)
+ {
+ name = TREE_PURPOSE (attrs);
+ fprintf (file, "%s ", IDENTIFIER_POINTER (name));
+
+ /* Pick up the next attribute. */
+ attrs = TREE_CHAIN (attrs);
+ }
+ fputc ('\n', file);
+}
+
+/* After rtl prologue has been expanded, this function is used. */
+static void
+nds32_asm_function_end_prologue (FILE *file)
+{
+ fprintf (file, "\t! END PROLOGUE\n");
+
+ /* If frame pointer is NOT needed and -mfp-as-gp is issued,
+ we can generate special directive: ".omit_fp_begin"
+ to guide linker doing fp-as-gp optimization.
+ However, for a naked function, which means
+ it should not have prologue/epilogue,
+ using fp-as-gp still requires saving $fp by push/pop behavior and
+ there is no benefit to use fp-as-gp on such small function.
+ So we need to make sure this function is NOT naked as well. */
+ if (!frame_pointer_needed
+ && !cfun->machine->naked_p
+ && cfun->machine->fp_as_gp_p)
+ {
+ fprintf (file, "\t! ----------------------------------------\n");
+ fprintf (file, "\t! Guide linker to do "
+ "link time optimization: fp-as-gp\n");
+ fprintf (file, "\t! We add one more instruction to "
+ "initialize $fp near to $gp location.\n");
+ fprintf (file, "\t! If linker fails to use fp-as-gp transformation,\n");
+ fprintf (file, "\t! this extra instruction should be "
+ "eliminated at link stage.\n");
+ fprintf (file, "\t.omit_fp_begin\n");
+ fprintf (file, "\tla\t$fp,_FP_BASE_\n");
+ fprintf (file, "\t! ----------------------------------------\n");
+ }
+}
+
+/* Before rtl epilogue has been expanded, this function is used. */
+static void
+nds32_asm_function_begin_epilogue (FILE *file)
+{
+ /* If frame pointer is NOT needed and -mfp-as-gp is issued,
+ we can generate special directive: ".omit_fp_end"
+ to claim fp-as-gp optimization range.
+ However, for a naked function,
+ which means it should not have prologue/epilogue,
+ using fp-as-gp still requires saving $fp by push/pop behavior and
+ there is no benefit to use fp-as-gp on such small function.
+ So we need to make sure this function is NOT naked as well. */
+ if (!frame_pointer_needed
+ && !cfun->machine->naked_p
+ && cfun->machine->fp_as_gp_p)
+ {
+ fprintf (file, "\t! ----------------------------------------\n");
+ fprintf (file, "\t! Claim the range of fp-as-gp "
+ "link time optimization\n");
+ fprintf (file, "\t.omit_fp_end\n");
+ fprintf (file, "\t! ----------------------------------------\n");
+ }
+
+ fprintf (file, "\t! BEGIN EPILOGUE\n");
+}
+
+/* The content produced from this function
+ will be placed after epilogue body. */
+static void
+nds32_asm_function_epilogue (FILE *file,
+ HOST_WIDE_INT size ATTRIBUTE_UNUSED)
+{
+ fprintf (file, "\t! END EPILOGUE\n");
+}
+
+static void
+nds32_asm_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
+ HOST_WIDE_INT delta,
+ HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED,
+ tree function)
+{
+ int this_regno;
+
+ /* Make sure unwind info is emitted for the thunk if needed. */
+ final_start_function (emit_barrier (), file, 1);
+
+ this_regno = (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function)
+ ? 1
+ : 0);
+
+ if (delta != 0)
+ {
+ if (satisfies_constraint_Is15 (GEN_INT (delta)))
+ {
+ fprintf (file, "\taddi\t$r%d, $r%d, %ld\n",
+ this_regno, this_regno, delta);
+ }
+ else if (satisfies_constraint_Is20 (GEN_INT (delta)))
+ {
+ fprintf (file, "\tmovi\t$ta, %ld\n", delta);
+ fprintf (file, "\tadd\t$r%d, $r%d, $ta\n", this_regno, this_regno);
+ }
+ else
+ {
+ fprintf (file, "\tsethi\t$ta, hi20(%ld)\n", delta);
+ fprintf (file, "\tori\t$ta, $ta, lo12(%ld)\n", delta);
+ fprintf (file, "\tadd\t$r%d, $r%d, $ta\n", this_regno, this_regno);
+ }
+ }
+
+ fprintf (file, "\tb\t");
+ assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0));
+ fprintf (file, "\n");
+
+ final_end_function ();
+}
+
+/* -- Permitting tail calls. */
+
+/* Determine whether we need to enable warning for function return check. */
+static bool
+nds32_warn_func_return (tree decl)
+{
+/* Naked functions are implemented entirely in assembly, including the
+ return sequence, so suppress warnings about this. */
+ return !nds32_naked_function_p (decl);
+}
+
+
+/* Implementing the Varargs Macros. */
+
+static bool
+nds32_strict_argument_naming (cumulative_args_t ca ATTRIBUTE_UNUSED)
+{
+ /* Return true so that all the named arguments for FUNCTION_ARG have named=1.
+ If return false, for the variadic function, all named arguments EXCEPT
+ the last are treated as named. */
+ return true;
+}
+
+
+/* Trampolines for Nested Functions. */
+
+static void
+nds32_asm_trampoline_template (FILE *f)
+{
+ if (TARGET_REDUCED_REGS)
+ {
+ /* Trampoline is not supported on reduced-set registers yet. */
+ sorry ("a nested function is not supported for reduced registers");
+ }
+ else
+ {
+ asm_fprintf (f, "\t! Trampoline code template\n");
+ asm_fprintf (f, "\t! This code fragment will be copied "
+ "into stack on demand\n");
+
+ asm_fprintf (f, "\tmfusr\t$r16,$pc\n");
+ asm_fprintf (f, "\tlwi\t$r15,[$r16 + 20] "
+ "! load nested function address\n");
+ asm_fprintf (f, "\tlwi\t$r16,[$r16 + 16] "
+ "! load chain_value\n");
+ asm_fprintf (f, "\tjr\t$r15\n");
+ }
+
+ /* Preserve space ($pc + 16) for saving chain_value,
+ nds32_trampoline_init will fill the value in this slot. */
+ asm_fprintf (f, "\t! space for saving chain_value\n");
+ assemble_aligned_integer (UNITS_PER_WORD, const0_rtx);
+
+ /* Preserve space ($pc + 20) for saving nested function address,
+ nds32_trampoline_init will fill the value in this slot. */
+ asm_fprintf (f, "\t! space for saving nested function address\n");
+ assemble_aligned_integer (UNITS_PER_WORD, const0_rtx);
+}
+
+/* Emit RTL insns to initialize the variable parts of a trampoline. */
+static void
+nds32_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
+{
+ int i;
+
+ /* Nested function address. */
+ rtx fnaddr;
+ /* The memory rtx that is going to
+ be filled with chain_value. */
+ rtx chain_value_mem;
+ /* The memory rtx that is going to
+ be filled with nested function address. */
+ rtx nested_func_mem;
+
+ /* Start address of trampoline code in stack, for doing cache sync. */
+ rtx sync_cache_addr;
+ /* Temporary register for sync instruction. */
+ rtx tmp_reg;
+ /* Instruction-cache sync instruction,
+ requesting an argument as starting address. */
+ rtx isync_insn;
+ /* For convenience reason of doing comparison. */
+ int tramp_align_in_bytes;
+
+ /* Trampoline is not supported on reduced-set registers yet. */
+ if (TARGET_REDUCED_REGS)
+ sorry ("a nested function is not supported for reduced registers");
+
+ /* STEP 1: Copy trampoline code template into stack,
+ fill up essential data into stack. */
+
+ /* Extract nested function address rtx. */
+ fnaddr = XEXP (DECL_RTL (fndecl), 0);
+
+ /* m_tramp is memory rtx that is going to be filled with trampoline code.
+ We have nds32_asm_trampoline_template() to emit template pattern. */
+ emit_block_move (m_tramp, assemble_trampoline_template (),
+ GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
+
+ /* After copying trampoline code into stack,
+ fill chain_value into stack. */
+ chain_value_mem = adjust_address (m_tramp, SImode, 16);
+ emit_move_insn (chain_value_mem, chain_value);
+ /* After copying trampoline code int stack,
+ fill nested function address into stack. */
+ nested_func_mem = adjust_address (m_tramp, SImode, 20);
+ emit_move_insn (nested_func_mem, fnaddr);
+
+ /* STEP 2: Sync instruction-cache. */
+
+ /* We have successfully filled trampoline code into stack.
+ However, in order to execute code in stack correctly,
+ we must sync instruction cache. */
+ sync_cache_addr = XEXP (m_tramp, 0);
+ tmp_reg = gen_reg_rtx (SImode);
+ isync_insn = gen_unspec_volatile_isync (tmp_reg);
+
+ /* Because nds32_cache_block_size is in bytes,
+ we get trampoline alignment in bytes for convenient comparison. */
+ tramp_align_in_bytes = TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT;
+
+ if (tramp_align_in_bytes >= nds32_cache_block_size
+ && (tramp_align_in_bytes % nds32_cache_block_size) == 0)
+ {
+ /* Under this condition, the starting address of trampoline
+ must be aligned to the starting address of each cache block
+ and we do not have to worry about cross-boundary issue. */
+ for (i = 0;
+ i < (TRAMPOLINE_SIZE + nds32_cache_block_size - 1)
+ / nds32_cache_block_size;
+ i++)
+ {
+ emit_move_insn (tmp_reg,
+ plus_constant (Pmode, sync_cache_addr,
+ nds32_cache_block_size * i));
+ emit_insn (isync_insn);
+ }
+ }
+ else if (TRAMPOLINE_SIZE > nds32_cache_block_size)
+ {
+ /* The starting address of trampoline code
+ may not be aligned to the cache block,
+ so the trampoline code may be across two cache block.
+ We need to sync the last element, which is 4-byte size,
+ of trampoline template. */
+ for (i = 0;
+ i < (TRAMPOLINE_SIZE + nds32_cache_block_size - 1)
+ / nds32_cache_block_size;
+ i++)
+ {
+ emit_move_insn (tmp_reg,
+ plus_constant (Pmode, sync_cache_addr,
+ nds32_cache_block_size * i));
+ emit_insn (isync_insn);
+ }
+
+ /* The last element of trampoline template is 4-byte size. */
+ emit_move_insn (tmp_reg,
+ plus_constant (Pmode, sync_cache_addr,
+ TRAMPOLINE_SIZE - 4));
+ emit_insn (isync_insn);
+ }
+ else
+ {
+ /* This is the simplest case.
+ Because TRAMPOLINE_SIZE is less than or
+ equal to nds32_cache_block_size,
+ we can just sync start address and
+ the last element of trampoline code. */
+
+ /* Sync starting address of tampoline code. */
+ emit_move_insn (tmp_reg, sync_cache_addr);
+ emit_insn (isync_insn);
+ /* Sync the last element, which is 4-byte size,
+ of trampoline template. */
+ emit_move_insn (tmp_reg,
+ plus_constant (Pmode, sync_cache_addr,
+ TRAMPOLINE_SIZE - 4));
+ emit_insn (isync_insn);
+ }
+
+ /* Set instruction serialization barrier
+ to guarantee the correct operations. */
+ emit_insn (gen_unspec_volatile_isb ());
+}
+
+
+/* Addressing Modes. */
+
+static bool
+nds32_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
+{
+ /* For (mem:DI addr) or (mem:DF addr) case,
+ we only allow 'addr' to be [reg], [symbol_ref],
+ [const], or [reg + const_int] pattern. */
+ if (mode == DImode || mode == DFmode)
+ {
+ /* Allow [Reg + const_int] addressing mode. */
+ if (GET_CODE (x) == PLUS)
+ {
+ if (nds32_address_register_rtx_p (XEXP (x, 0), strict)
+ && nds32_legitimate_index_p (mode, XEXP (x, 1), strict)
+ && CONST_INT_P (XEXP (x, 1)))
+ return true;
+
+ else if (nds32_address_register_rtx_p (XEXP (x, 1), strict)
+ && nds32_legitimate_index_p (mode, XEXP (x, 0), strict)
+ && CONST_INT_P (XEXP (x, 0)))
+ return true;
+ }
+
+ /* Now check [reg], [symbol_ref], and [const]. */
+ if (GET_CODE (x) != REG
+ && GET_CODE (x) != SYMBOL_REF
+ && GET_CODE (x) != CONST)
+ return false;
+ }
+
+ /* Check if 'x' is a valid address. */
+ switch (GET_CODE (x))
+ {
+ case REG:
+ /* (mem (reg A)) => [Ra] */
+ return nds32_address_register_rtx_p (x, strict);
+
+ case SYMBOL_REF:
+
+ if (!TARGET_GP_DIRECT
+ && (reload_completed
+ || reload_in_progress
+ || lra_in_progress))
+ return false;
+
+ /* (mem (symbol_ref A)) => [symbol_ref] */
+ return !currently_expanding_to_rtl;
+
+ case CONST:
+
+ if (!TARGET_GP_DIRECT
+ && (reload_completed
+ || reload_in_progress
+ || lra_in_progress))
+ return false;
+
+ /* (mem (const (...)))
+ => [ + const_addr ], where const_addr = symbol_ref + const_int */
+ if (GET_CODE (XEXP (x, 0)) == PLUS)
+ {
+ rtx plus_op = XEXP (x, 0);
+
+ rtx op0 = XEXP (plus_op, 0);
+ rtx op1 = XEXP (plus_op, 1);
+
+ if (GET_CODE (op0) == SYMBOL_REF && CONST_INT_P (op1))
+ return true;
+ else
+ return false;
+ }
+
+ return false;
+
+ case POST_MODIFY:
+ /* (mem (post_modify (reg) (plus (reg) (reg))))
+ => [Ra], Rb */
+ /* (mem (post_modify (reg) (plus (reg) (const_int))))
+ => [Ra], const_int */
+ if (GET_CODE (XEXP (x, 0)) == REG
+ && GET_CODE (XEXP (x, 1)) == PLUS)
+ {
+ rtx plus_op = XEXP (x, 1);
+
+ rtx op0 = XEXP (plus_op, 0);
+ rtx op1 = XEXP (plus_op, 1);
+
+ if (nds32_address_register_rtx_p (op0, strict)
+ && nds32_legitimate_index_p (mode, op1, strict))
+ return true;
+ else
+ return false;
+ }
+
+ return false;
+
+ case POST_INC:
+ case POST_DEC:
+ /* (mem (post_inc reg)) => [Ra], 1/2/4 */
+ /* (mem (post_dec reg)) => [Ra], -1/-2/-4 */
+ /* The 1/2/4 or -1/-2/-4 have been displayed in nds32.md.
+ We only need to deal with register Ra. */
+ if (nds32_address_register_rtx_p (XEXP (x, 0), strict))
+ return true;
+ else
+ return false;
+
+ case PLUS:
+ /* (mem (plus reg const_int))
+ => [Ra + imm] */
+ /* (mem (plus reg reg))
+ => [Ra + Rb] */
+ /* (mem (plus (mult reg const_int) reg))
+ => [Ra + Rb << sv] */
+ if (nds32_address_register_rtx_p (XEXP (x, 0), strict)
+ && nds32_legitimate_index_p (mode, XEXP (x, 1), strict))
+ return true;
+ else if (nds32_address_register_rtx_p (XEXP (x, 1), strict)
+ && nds32_legitimate_index_p (mode, XEXP (x, 0), strict))
+ return true;
+ else
+ return false;
+
+ case LO_SUM:
+ if (!TARGET_GP_DIRECT)
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+
+/* Describing Relative Costs of Operations. */
+
+static int nds32_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
+ reg_class_t from,
+ reg_class_t to)
+{
+ if (from == HIGH_REGS || to == HIGH_REGS)
+ return 6;
+
+ return 2;
+}
+
+static int nds32_memory_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
+ reg_class_t rclass ATTRIBUTE_UNUSED,
+ bool in ATTRIBUTE_UNUSED)
+{
+ return 8;
+}
+
+/* This target hook describes the relative costs of RTL expressions.
+ Return 'true' when all subexpressions of x have been processed.
+ Return 'false' to sum the costs of sub-rtx, plus cost of this operation.
+ Refer to gcc/rtlanal.c for more information. */
+static bool
+nds32_rtx_costs (rtx x,
+ int code,
+ int outer_code,
+ int opno ATTRIBUTE_UNUSED,
+ int *total,
+ bool speed)
+{
+ /* According to 'speed', goto suitable cost model section. */
+ if (speed)
+ goto performance_cost;
+ else
+ goto size_cost;
+
+
+performance_cost:
+ /* This is section for performance cost model. */
+
+ /* In gcc/rtl.h, the default value of COSTS_N_INSNS(N) is N*4.
+ We treat it as 4-cycle cost for each instruction
+ under performance consideration. */
+ switch (code)
+ {
+ case SET:
+ /* For 'SET' rtx, we need to return false
+ so that it can recursively calculate costs. */
+ return false;
+
+ case USE:
+ /* Used in combine.c as a marker. */
+ *total = 0;
+ break;
+
+ case MULT:
+ *total = COSTS_N_INSNS (5);
+ break;
+
+ case DIV:
+ case UDIV:
+ case MOD:
+ case UMOD:
+ *total = COSTS_N_INSNS (7);
+ break;
+
+ default:
+ *total = COSTS_N_INSNS (1);
+ break;
+ }
+
+ return true;
+
+
+size_cost:
+ /* This is section for size cost model. */
+
+ /* In gcc/rtl.h, the default value of COSTS_N_INSNS(N) is N*4.
+ We treat it as 4-byte cost for each instruction
+ under code size consideration. */
+ switch (code)
+ {
+ case SET:
+ /* For 'SET' rtx, we need to return false
+ so that it can recursively calculate costs. */
+ return false;
+
+ case USE:
+ /* Used in combine.c as a marker. */
+ *total = 0;
+ break;
+
+ case CONST_INT:
+ /* All instructions involving constant operation
+ need to be considered for cost evaluation. */
+ if (outer_code == SET)
+ {
+ /* (set X imm5s), use movi55, 2-byte cost.
+ (set X imm20s), use movi, 4-byte cost.
+ (set X BIG_INT), use sethi/ori, 8-byte cost. */
+ if (satisfies_constraint_Is05 (x))
+ *total = COSTS_N_INSNS (1) - 2;
+ else if (satisfies_constraint_Is20 (x))
+ *total = COSTS_N_INSNS (1);
+ else
+ *total = COSTS_N_INSNS (2);
+ }
+ else if (outer_code == PLUS || outer_code == MINUS)
+ {
+ /* Possible addi333/subi333 or subi45/addi45, 2-byte cost.
+ General case, cost 1 instruction with 4-byte. */
+ if (satisfies_constraint_Iu05 (x))
+ *total = COSTS_N_INSNS (1) - 2;
+ else
+ *total = COSTS_N_INSNS (1);
+ }
+ else if (outer_code == ASHIFT)
+ {
+ /* Possible slli333, 2-byte cost.
+ General case, cost 1 instruction with 4-byte. */
+ if (satisfies_constraint_Iu03 (x))
+ *total = COSTS_N_INSNS (1) - 2;
+ else
+ *total = COSTS_N_INSNS (1);
+ }
+ else if (outer_code == ASHIFTRT || outer_code == LSHIFTRT)
+ {
+ /* Possible srai45 or srli45, 2-byte cost.
+ General case, cost 1 instruction with 4-byte. */
+ if (satisfies_constraint_Iu05 (x))
+ *total = COSTS_N_INSNS (1) - 2;
+ else
+ *total = COSTS_N_INSNS (1);
+ }
+ else
+ {
+ /* For other cases, simply set it 4-byte cost. */
+ *total = COSTS_N_INSNS (1);
+ }
+ break;
+
+ case CONST_DOUBLE:
+ /* It requires high part and low part processing, set it 8-byte cost. */
+ *total = COSTS_N_INSNS (2);
+ break;
+
+ default:
+ /* For other cases, generally we set it 4-byte cost
+ and stop resurively traversing. */
+ *total = COSTS_N_INSNS (1);
+ break;
+ }
+
+ return true;
+}
+
+static int nds32_address_cost (rtx address,
+ enum machine_mode mode ATTRIBUTE_UNUSED,
+ addr_space_t as ATTRIBUTE_UNUSED,
+ bool speed)
+{
+ rtx plus0, plus1;
+ enum rtx_code code;
+
+ code = GET_CODE (address);
+
+ /* According to 'speed', goto suitable cost model section. */
+ if (speed)
+ goto performance_cost;
+ else
+ goto size_cost;
+
+performance_cost:
+ /* This is section for performance cost model. */
+
+ /* FALLTHRU, currently we use same cost model as size_cost. */
+
+size_cost:
+ /* This is section for size cost model. */
+
+ switch (code)
+ {
+ case POST_MODIFY:
+ case POST_INC:
+ case POST_DEC:
+ /* We encourage that rtx contains
+ POST_MODIFY/POST_INC/POST_DEC behavior. */
+ return 0;
+
+ case SYMBOL_REF:
+ /* We can have gp-relative load/store for symbol_ref.
+ Have it 4-byte cost. */
+ return COSTS_N_INSNS (1);
+
+ case CONST:
+ /* It is supposed to be the pattern (const (plus symbol_ref const_int)).
+ Have it 4-byte cost. */
+ return COSTS_N_INSNS (1);
+
+ case REG:
+ /* Simply return 4-byte costs. */
+ return COSTS_N_INSNS (1);
+
+ case PLUS:
+ /* We do not need to check if the address is a legitimate address,
+ because this hook is never called with an invalid address.
+ But we better check the range of
+ const_int value for cost, if it exists. */
+ plus0 = XEXP (address, 0);
+ plus1 = XEXP (address, 1);
+
+ if (REG_P (plus0) && CONST_INT_P (plus1))
+ {
+ /* If it is possible to be lwi333/swi333 form,
+ make it 2-byte cost. */
+ if (satisfies_constraint_Iu05 (plus1))
+ return (COSTS_N_INSNS (1) - 2);
+ else
+ return COSTS_N_INSNS (1);
+ }
+
+ /* For other 'plus' situation, make it cost 4-byte. */
+ return COSTS_N_INSNS (1);
+
+ default:
+ break;
+ }
+
+ return COSTS_N_INSNS (4);
+}
+
+
+/* Defining the Output Assembler Language. */
+
+/* -- The Overall Framework of an Assembler File. */
+
+static void
+nds32_asm_file_start (void)
+{
+ int i;
+
+ default_file_start ();
+
+ /* Tell assembler which ABI we are using. */
+ fprintf (asm_out_file, "\t! ABI version\n");
+ fprintf (asm_out_file, "\t.abi_2\n");
+
+ /* Tell assembler that this asm code is generated by compiler. */
+ fprintf (asm_out_file, "\t! This asm file is generated by compiler\n");
+ fprintf (asm_out_file, "\t.flag\tverbatim\n");
+ /* Give assembler the size of each vector for interrupt handler. */
+ fprintf (asm_out_file, "\t! This vector size directive is required "
+ "for checking inconsistency on interrupt handler\n");
+ fprintf (asm_out_file, "\t.vec_size\t%d\n", nds32_isr_vector_size);
+
+ /* If user enables '-mforce-fp-as-gp' or compiles programs with -Os,
+ the compiler may produce 'la $fp,_FP_BASE_' instruction
+ at prologue for fp-as-gp optimization.
+ We should emit weak reference of _FP_BASE_ to avoid undefined reference
+ in case user does not pass '--relax' option to linker. */
+ if (TARGET_FORCE_FP_AS_GP || optimize_size)
+ {
+ fprintf (asm_out_file, "\t! This weak reference is required to do "
+ "fp-as-gp link time optimization\n");
+ fprintf (asm_out_file, "\t.weak\t_FP_BASE_\n");
+ }
+ /* If user enables '-mex9', we should emit relaxation directive
+ to tell linker that this file is allowed to do ex9 optimization. */
+ if (TARGET_EX9)
+ {
+ fprintf (asm_out_file, "\t! This relaxation directive is required "
+ "to do ex9 link time optimization\n");
+ fprintf (asm_out_file, "\t.relax\tex9\n");
+ }
+
+ fprintf (asm_out_file, "\t! ------------------------------------\n");
+
+ if (TARGET_ISA_V2)
+ fprintf (asm_out_file, "\t! ISA family\t\t: %s\n", "V2");
+ if (TARGET_ISA_V3)
+ fprintf (asm_out_file, "\t! ISA family\t\t: %s\n", "V3");
+ if (TARGET_ISA_V3M)
+ fprintf (asm_out_file, "\t! ISA family\t\t: %s\n", "V3M");
+
+ fprintf (asm_out_file, "\t! Endian setting\t: %s\n",
+ ((TARGET_BIG_ENDIAN) ? "big-endian"
+ : "little-endian"));
+
+ fprintf (asm_out_file, "\t! ------------------------------------\n");
+
+ fprintf (asm_out_file, "\t! Use conditional move\t\t: %s\n",
+ ((TARGET_CMOV) ? "Yes"
+ : "No"));
+ fprintf (asm_out_file, "\t! Use performance extension\t: %s\n",
+ ((TARGET_PERF_EXT) ? "Yes"
+ : "No"));
+
+ fprintf (asm_out_file, "\t! ------------------------------------\n");
+
+ fprintf (asm_out_file, "\t! V3PUSH instructions\t: %s\n",
+ ((TARGET_V3PUSH) ? "Yes"
+ : "No"));
+ fprintf (asm_out_file, "\t! 16-bit instructions\t: %s\n",
+ ((TARGET_16_BIT) ? "Yes"
+ : "No"));
+ fprintf (asm_out_file, "\t! GP base access\t: %s\n",
+ ((TARGET_GP_DIRECT) ? "Yes"
+ : "No"));
+ fprintf (asm_out_file, "\t! Reduced registers set\t: %s\n",
+ ((TARGET_REDUCED_REGS) ? "Yes"
+ : "No"));
+
+ fprintf (asm_out_file, "\t! ------------------------------------\n");
+
+ if (optimize_size)
+ fprintf (asm_out_file, "\t! Optimization level\t: -Os\n");
+ else
+ fprintf (asm_out_file, "\t! Optimization level\t: -O%d\n", optimize);
+
+ fprintf (asm_out_file, "\t! ------------------------------------\n");
+
+ fprintf (asm_out_file, "\t! Cache block size\t: %d\n",
+ nds32_cache_block_size);
+
+ fprintf (asm_out_file, "\t! ------------------------------------\n");
+
+ /* Initialize isr vector information array before compiling functions. */
+ for (i = 0; i < NDS32_N_ISR_VECTORS; i++)
+ {
+ nds32_isr_vectors[i].category = NDS32_ISR_NONE;
+ strcpy (nds32_isr_vectors[i].func_name, "");
+ nds32_isr_vectors[i].save_reg = NDS32_PARTIAL_SAVE;
+ nds32_isr_vectors[i].nested_type = NDS32_NOT_NESTED;
+ nds32_isr_vectors[i].total_n_vectors = 0;
+ strcpy (nds32_isr_vectors[i].nmi_name, "");
+ strcpy (nds32_isr_vectors[i].warm_name, "");
+ }
+}
+
+static void
+nds32_asm_file_end (void)
+{
+ int i;
+
+ /* If all the vectors are NDS32_ISR_NONE, we can return immediately. */
+ for (i = 0; i < NDS32_N_ISR_VECTORS; i++)
+ if (nds32_isr_vectors[i].category != NDS32_ISR_NONE)
+ break;
+
+ if (i == NDS32_N_ISR_VECTORS)
+ return;
+
+ /* At least one vector is NOT NDS32_ISR_NONE,
+ we should output isr vector information. */
+ fprintf (asm_out_file, "\t! ------------------------------------\n");
+ fprintf (asm_out_file, "\t! The isr vector information:\n");
+ fprintf (asm_out_file, "\t! ------------------------------------\n");
+
+ /* Check reset handler first. Its vector number is always 0. */
+ if (nds32_isr_vectors[0].category == NDS32_ISR_RESET)
+ {
+ nds32_emit_isr_reset_content ();
+ fprintf (asm_out_file, "\t! ------------------------------------\n");
+ }
+
+ /* Check other vectors, starting from vector number 1. */
+ for (i = 1; i < NDS32_N_ISR_VECTORS; i++)
+ {
+ if (nds32_isr_vectors[i].category == NDS32_ISR_INTERRUPT
+ || nds32_isr_vectors[i].category == NDS32_ISR_EXCEPTION)
+ {
+ /* Found one vector which is interupt or exception.
+ Output its jmptbl and vector section content. */
+ fprintf (asm_out_file, "\t! interrupt/exception vector %02d\n", i);
+ fprintf (asm_out_file, "\t! ------------------------------------\n");
+ nds32_emit_isr_jmptbl_section (i);
+ fprintf (asm_out_file, "\t! ....................................\n");
+ nds32_emit_isr_vector_section (i);
+ fprintf (asm_out_file, "\t! ------------------------------------\n");
+ }
+ }
+
+ fprintf (asm_out_file, "\t! ------------------------------------\n");
+}
+
+/* -- Output and Generation of Labels. */
+
+static void
+nds32_asm_globalize_label (FILE *stream, const char *name)
+{
+ fputs ("\t.global\t", stream);
+ assemble_name (stream, name);
+ fputs ("\n", stream);
+}
+
+/* -- Output of Assembler Instructions. */
+
+static void
+nds32_print_operand (FILE *stream, rtx x, int code)
+{
+ int op_value;
+
+ switch (code)
+ {
+ case 0 :
+ /* Do nothing special. */
+ break;
+
+ case 'V':
+ /* 'x' is supposed to be CONST_INT, get the value. */
+ gcc_assert (CONST_INT_P (x));
+ op_value = INTVAL (x);
+
+ /* According to the Andes architecture,
+ the system/user register index range is 0 ~ 1023.
+ In order to avoid conflict between user-specified-integer value
+ and enum-specified-register value,
+ the 'enum nds32_intrinsic_registers' value
+ in nds32_intrinsic.h starts from 1024. */
+ if (op_value < 1024 && op_value >= 0)
+ {
+ /* If user gives integer value directly (0~1023),
+ we just print out the value. */
+ fprintf (stream, "%d", op_value);
+ }
+ else if (op_value < 0
+ || op_value >= ((int) ARRAY_SIZE (nds32_intrinsic_register_names)
+ + 1024))
+ {
+ /* The enum index value for array size is out of range. */
+ error ("intrinsic register index is out of range");
+ }
+ else
+ {
+ /* If user applies normal way with __NDS32_REG_XXX__ enum data,
+ we can print out register name. Remember to substract 1024. */
+ fprintf (stream, "%s",
+ nds32_intrinsic_register_names[op_value - 1024]);
+ }
+
+ /* No need to handle following process, so return immediately. */
+ return;
+
+ default :
+ /* Unknown flag. */
+ output_operand_lossage ("invalid operand output code");
+ break;
+ }
+
+ switch (GET_CODE (x))
+ {
+ case LABEL_REF:
+ case SYMBOL_REF:
+ output_addr_const (stream, x);
+ break;
+
+ case REG:
+ /* Forbid using static chain register ($r16)
+ on reduced-set registers configuration. */
+ if (TARGET_REDUCED_REGS
+ && REGNO (x) == STATIC_CHAIN_REGNUM)
+ sorry ("a nested function is not supported for reduced registers");
+
+ /* Normal cases, print out register name. */
+ fputs (reg_names[REGNO (x)], stream);
+ break;
+
+ case MEM:
+ output_address (XEXP (x, 0));
+ break;
+
+ case CODE_LABEL:
+ case CONST_INT:
+ case CONST:
+ output_addr_const (stream, x);
+ break;
+
+ default:
+ /* Generally, output_addr_const () is able to handle most cases.
+ We want to see what CODE could appear,
+ so we use gcc_unreachable() to stop it. */
+ debug_rtx (x);
+ gcc_unreachable ();
+ break;
+ }
+}
+
+static void
+nds32_print_operand_address (FILE *stream, rtx x)
+{
+ rtx op0, op1;
+
+ switch (GET_CODE (x))
+ {
+ case SYMBOL_REF:
+ case CONST:
+ /* [ + symbol_ref] */
+ /* [ + const_addr], where const_addr = symbol_ref + const_int */
+ fputs ("[ + ", stream);
+ output_addr_const (stream, x);
+ fputs ("]", stream);
+ break;
+
+ case REG:
+ /* Forbid using static chain register ($r16)
+ on reduced-set registers configuration. */
+ if (TARGET_REDUCED_REGS
+ && REGNO (x) == STATIC_CHAIN_REGNUM)
+ sorry ("a nested function is not supported for reduced registers");
+
+ /* [Ra] */
+ fprintf (stream, "[%s]", reg_names[REGNO (x)]);
+ break;
+
+ case PLUS:
+ op0 = XEXP (x, 0);
+ op1 = XEXP (x, 1);
+
+ /* Checking op0, forbid using static chain register ($r16)
+ on reduced-set registers configuration. */
+ if (TARGET_REDUCED_REGS
+ && REG_P (op0)
+ && REGNO (op0) == STATIC_CHAIN_REGNUM)
+ sorry ("a nested function is not supported for reduced registers");
+ /* Checking op1, forbid using static chain register ($r16)
+ on reduced-set registers configuration. */
+ if (TARGET_REDUCED_REGS
+ && REG_P (op1)
+ && REGNO (op1) == STATIC_CHAIN_REGNUM)
+ sorry ("a nested function is not supported for reduced registers");
+
+ if (REG_P (op0) && CONST_INT_P (op1))
+ {
+ /* [Ra + imm] */
+ fprintf (stream, "[%s + (%d)]",
+ reg_names[REGNO (op0)], (int)INTVAL (op1));
+ }
+ else if (REG_P (op0) && REG_P (op1))
+ {
+ /* [Ra + Rb] */
+ fprintf (stream, "[%s + %s]",
+ reg_names[REGNO (op0)], reg_names[REGNO (op1)]);
+ }
+ else if (GET_CODE (op0) == MULT && REG_P (op1))
+ {
+ /* [Ra + Rb << sv]
+ From observation, the pattern looks like:
+ (plus:SI (mult:SI (reg:SI 58)
+ (const_int 4 [0x4]))
+ (reg/f:SI 57)) */
+ int sv;
+
+ /* We need to set sv to output shift value. */
+ if (INTVAL (XEXP (op0, 1)) == 1)
+ sv = 0;
+ else if (INTVAL (XEXP (op0, 1)) == 2)
+ sv = 1;
+ else if (INTVAL (XEXP (op0, 1)) == 4)
+ sv = 2;
+ else
+ gcc_unreachable ();
+
+ fprintf (stream, "[%s + %s << %d]",
+ reg_names[REGNO (op1)],
+ reg_names[REGNO (XEXP (op0, 0))],
+ sv);
+ }
+ else
+ {
+ /* The control flow is not supposed to be here. */
+ debug_rtx (x);
+ gcc_unreachable ();
+ }
+
+ break;
+
+ case POST_MODIFY:
+ /* (post_modify (regA) (plus (regA) (regB)))
+ (post_modify (regA) (plus (regA) (const_int)))
+ We would like to extract
+ regA and regB (or const_int) from plus rtx. */
+ op0 = XEXP (XEXP (x, 1), 0);
+ op1 = XEXP (XEXP (x, 1), 1);
+
+ /* Checking op0, forbid using static chain register ($r16)
+ on reduced-set registers configuration. */
+ if (TARGET_REDUCED_REGS
+ && REG_P (op0)
+ && REGNO (op0) == STATIC_CHAIN_REGNUM)
+ sorry ("a nested function is not supported for reduced registers");
+ /* Checking op1, forbid using static chain register ($r16)
+ on reduced-set registers configuration. */
+ if (TARGET_REDUCED_REGS
+ && REG_P (op1)
+ && REGNO (op1) == STATIC_CHAIN_REGNUM)
+ sorry ("a nested function is not supported for reduced registers");
+
+ if (REG_P (op0) && REG_P (op1))
+ {
+ /* [Ra], Rb */
+ fprintf (stream, "[%s], %s",
+ reg_names[REGNO (op0)], reg_names[REGNO (op1)]);
+ }
+ else if (REG_P (op0) && CONST_INT_P (op1))
+ {
+ /* [Ra], imm */
+ fprintf (stream, "[%s], %d",
+ reg_names[REGNO (op0)], (int)INTVAL (op1));
+ }
+ else
+ {
+ /* The control flow is not supposed to be here. */
+ debug_rtx (x);
+ gcc_unreachable ();
+ }
+
+ break;
+
+ case POST_INC:
+ case POST_DEC:
+ op0 = XEXP (x, 0);
+
+ /* Checking op0, forbid using static chain register ($r16)
+ on reduced-set registers configuration. */
+ if (TARGET_REDUCED_REGS
+ && REG_P (op0)
+ && REGNO (op0) == STATIC_CHAIN_REGNUM)
+ sorry ("a nested function is not supported for reduced registers");
+
+ if (REG_P (op0))
+ {
+ /* "[Ra], 1/2/4" or "[Ra], -1/-2/-4"
+ The 1/2/4 or -1/-2/-4 have been displayed in nds32.md.
+ We only need to deal with register Ra. */
+ fprintf (stream, "[%s]", reg_names[REGNO (op0)]);
+ }
+ else
+ {
+ /* The control flow is not supposed to be here. */
+ debug_rtx (x);
+ gcc_unreachable ();
+ }
+
+ break;
+
+ default :
+ /* Generally, output_addr_const () is able to handle most cases.
+ We want to see what CODE could appear,
+ so we use gcc_unreachable() to stop it. */
+ debug_rtx (x);
+ gcc_unreachable ();
+ break;
+ }
+}
+
+
+/* Defining target-specific uses of __attribute__. */
+
+/* Add some checking after merging attributes. */
+static tree
+nds32_merge_decl_attributes (tree olddecl, tree newdecl)
+{
+ tree combined_attrs;
+
+ /* Create combined attributes. */
+ combined_attrs = merge_attributes (DECL_ATTRIBUTES (olddecl),
+ DECL_ATTRIBUTES (newdecl));
+
+ /* Sinc newdecl is acutally a duplicate of olddecl,
+ we can take olddecl for some operations. */
+ if (TREE_CODE (olddecl) == FUNCTION_DECL)
+ {
+ /* Check isr-specific attributes conflict. */
+ nds32_check_isr_attrs_conflict (olddecl, combined_attrs);
+ }
+
+ return combined_attrs;
+}
+
+/* Add some checking when inserting attributes. */
+static void
+nds32_insert_attributes (tree decl, tree *attributes)
+{
+ /* For function declaration, we need to check isr-specific attributes:
+ 1. Call nds32_check_isr_attrs_conflict() to check any conflict.
+ 2. Check valid integer value for interrupt/exception.
+ 3. Check valid integer value for reset.
+ 4. Check valid function for nmi/warm. */
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ {
+ tree func_attrs;
+ tree intr, excp, reset;
+
+ /* Pick up function attributes. */
+ func_attrs = *attributes;
+
+ /* 1. Call nds32_check_isr_attrs_conflict() to check any conflict. */
+ nds32_check_isr_attrs_conflict (decl, func_attrs);
+
+ /* Now we are starting to check valid id value
+ for interrupt/exception/reset.
+ Note that we ONLY check its validity here.
+ To construct isr vector information, it is still performed
+ by nds32_construct_isr_vectors_information(). */
+ intr = lookup_attribute ("interrupt", func_attrs);
+ excp = lookup_attribute ("exception", func_attrs);
+ reset = lookup_attribute ("reset", func_attrs);
+
+ if (intr || excp)
+ {
+ /* Deal with interrupt/exception. */
+ tree id_list;
+ unsigned int lower_bound, upper_bound;
+
+ /* The way to handle interrupt or exception is the same,
+ we just need to take care of actual vector number.
+ For interrupt(0..63), the actual vector number is (9..72).
+ For exception(1..8), the actual vector number is (1..8). */
+ lower_bound = (intr) ? (0) : (1);
+ upper_bound = (intr) ? (63) : (8);
+
+ /* Prepare id list so that we can traverse id value. */
+ id_list = (intr) ? (TREE_VALUE (intr)) : (TREE_VALUE (excp));
+
+ /* 2. Check valid integer value for interrupt/exception. */
+ while (id_list)
+ {
+ tree id;
+
+ /* Pick up each vector id value. */
+ id = TREE_VALUE (id_list);
+ /* Issue error if it is not a valid integer value. */
+ if (TREE_CODE (id) != INTEGER_CST
+ || TREE_INT_CST_LOW (id) < lower_bound
+ || TREE_INT_CST_LOW (id) > upper_bound)
+ error ("invalid id value for interrupt/exception attribute");
+
+ /* Advance to next id. */
+ id_list = TREE_CHAIN (id_list);
+ }
+ }
+ else if (reset)
+ {
+ /* Deal with reset. */
+ tree id_list;
+ tree id;
+ tree nmi, warm;
+ unsigned int lower_bound;
+ unsigned int upper_bound;
+
+ /* Prepare id_list and identify id value so that
+ we can check if total number of vectors is valid. */
+ id_list = TREE_VALUE (reset);
+ id = TREE_VALUE (id_list);
+
+ /* The maximum numbers for user's interrupt is 64. */
+ lower_bound = 0;
+ upper_bound = 64;
+
+ /* 3. Check valid integer value for reset. */
+ if (TREE_CODE (id) != INTEGER_CST
+ || TREE_INT_CST_LOW (id) < lower_bound
+ || TREE_INT_CST_LOW (id) > upper_bound)
+ error ("invalid id value for reset attribute");
+
+ /* 4. Check valid function for nmi/warm. */
+ nmi = lookup_attribute ("nmi", func_attrs);
+ warm = lookup_attribute ("warm", func_attrs);
+
+ if (nmi != NULL_TREE)
+ {
+ tree nmi_func_list;
+ tree nmi_func;
+
+ nmi_func_list = TREE_VALUE (nmi);
+ nmi_func = TREE_VALUE (nmi_func_list);
+
+ /* Issue error if it is not a valid nmi function. */
+ if (TREE_CODE (nmi_func) != IDENTIFIER_NODE)
+ error ("invalid nmi function for reset attribute");
+ }
+
+ if (warm != NULL_TREE)
+ {
+ tree warm_func_list;
+ tree warm_func;
+
+ warm_func_list = TREE_VALUE (warm);
+ warm_func = TREE_VALUE (warm_func_list);
+
+ /* Issue error if it is not a valid warm function. */
+ if (TREE_CODE (warm_func) != IDENTIFIER_NODE)
+ error ("invalid warm function for reset attribute");
+ }
+ }
+ else
+ {
+ /* No interrupt, exception, or reset attribute is set. */
+ return;
+ }
+ }
+}
+
+static bool
+nds32_option_pragma_parse (tree args ATTRIBUTE_UNUSED,
+ tree pop_target ATTRIBUTE_UNUSED)
+{
+ /* Currently, we do not parse any pragma target by ourself,
+ so just simply return false. */
+ return false;
+}
+
+static void
+nds32_option_override (void)
+{
+ /* After all the command options have been parsed,
+ we shall deal with some flags for changing compiler settings. */
+
+ /* At first, we check if we have to strictly
+ set some flags based on ISA family. */
+ if (TARGET_ISA_V2)
+ {
+ /* Under V2 ISA, we need to strictly disable TARGET_V3PUSH. */
+ target_flags &= ~MASK_V3PUSH;
+ }
+ if (TARGET_ISA_V3)
+ {
+ /* Under V3 ISA, currently nothing should be strictly set. */
+ }
+ if (TARGET_ISA_V3M)
+ {
+ /* Under V3M ISA, we need to strictly enable TARGET_REDUCED_REGS. */
+ target_flags |= MASK_REDUCED_REGS;
+ /* Under V3M ISA, we need to strictly disable TARGET_PERF_EXT. */
+ target_flags &= ~MASK_PERF_EXT;
+ }
+
+ /* See if we are using reduced-set registers:
+ $r0~$r5, $r6~$r10, $r15, $r28, $r29, $r30, $r31
+ If so, we must forbid using $r11~$r14, $r16~$r27. */
+ if (TARGET_REDUCED_REGS)
+ {
+ int r;
+
+ /* Prevent register allocator from
+ choosing it as doing register allocation. */
+ for (r = 11; r <= 14; r++)
+ fixed_regs[r] = call_used_regs[r] = 1;
+ for (r = 16; r <= 27; r++)
+ fixed_regs[r] = call_used_regs[r] = 1;
+ }
+
+ /* See if user explicitly would like to use fp-as-gp optimization.
+ If so, we must prevent $fp from being allocated
+ during register allocation. */
+ if (TARGET_FORCE_FP_AS_GP)
+ fixed_regs[FP_REGNUM] = call_used_regs[FP_REGNUM] = 1;
+
+ if (!TARGET_16_BIT)
+ {
+ /* Under no 16 bit ISA, we need to strictly disable TARGET_V3PUSH. */
+ target_flags &= ~MASK_V3PUSH;
+ }
+
+ /* Currently, we don't support PIC code generation yet. */
+ if (flag_pic)
+ sorry ("not support -fpic");
+}
+
+
+/* Miscellaneous Parameters. */
+
+static void
+nds32_init_builtins (void)
+{
+ tree pointer_type_node = build_pointer_type (integer_type_node);
+
+ tree void_ftype_void = build_function_type (void_type_node,
+ void_list_node);
+
+ tree void_ftype_pint = build_function_type_list (void_type_node,
+ pointer_type_node,
+ NULL_TREE);
+
+ tree int_ftype_int = build_function_type_list (integer_type_node,
+ integer_type_node,
+ NULL_TREE);
+
+ tree void_ftype_int_int = build_function_type_list (void_type_node,
+ integer_type_node,
+ integer_type_node,
+ NULL_TREE);
+
+ /* Cache. */
+ add_builtin_function ("__builtin_nds32_isync", void_ftype_pint,
+ NDS32_BUILTIN_ISYNC,
+ BUILT_IN_MD, NULL, NULL_TREE);
+ add_builtin_function ("__builtin_nds32_isb", void_ftype_void,
+ NDS32_BUILTIN_ISB,
+ BUILT_IN_MD, NULL, NULL_TREE);
+
+ /* Register Transfer. */
+ add_builtin_function ("__builtin_nds32_mfsr", int_ftype_int,
+ NDS32_BUILTIN_MFSR,
+ BUILT_IN_MD, NULL, NULL_TREE);
+ add_builtin_function ("__builtin_nds32_mfusr", int_ftype_int,
+ NDS32_BUILTIN_MFUSR,
+ BUILT_IN_MD, NULL, NULL_TREE);
+ add_builtin_function ("__builtin_nds32_mtsr", void_ftype_int_int,
+ NDS32_BUILTIN_MTSR,
+ BUILT_IN_MD, NULL, NULL_TREE);
+ add_builtin_function ("__builtin_nds32_mtusr", void_ftype_int_int,
+ NDS32_BUILTIN_MTUSR,
+ BUILT_IN_MD, NULL, NULL_TREE);
+
+ /* Interrupt. */
+ add_builtin_function ("__builtin_nds32_setgie_en", void_ftype_void,
+ NDS32_BUILTIN_SETGIE_EN,
+ BUILT_IN_MD, NULL, NULL_TREE);
+ add_builtin_function ("__builtin_nds32_setgie_dis", void_ftype_void,
+ NDS32_BUILTIN_SETGIE_DIS,
+ BUILT_IN_MD, NULL, NULL_TREE);
+}
+
+static rtx
+nds32_expand_builtin (tree exp,
+ rtx target,
+ rtx subtarget ATTRIBUTE_UNUSED,
+ enum machine_mode mode ATTRIBUTE_UNUSED,
+ int ignore ATTRIBUTE_UNUSED)
+{
+ tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
+
+ int fcode = DECL_FUNCTION_CODE (fndecl);
+
+ switch (fcode)
+ {
+ /* Cache. */
+ case NDS32_BUILTIN_ISYNC:
+ return nds32_expand_builtin_null_ftype_reg
+ (CODE_FOR_unspec_volatile_isync, exp, target);
+ case NDS32_BUILTIN_ISB:
+ /* Since there are no result and operands for isb instruciton,
+ we can simply emit this rtx. */
+ emit_insn (gen_unspec_volatile_isb ());
+ return target;
+
+ /* Register Transfer. */
+ case NDS32_BUILTIN_MFSR:
+ return nds32_expand_builtin_reg_ftype_imm
+ (CODE_FOR_unspec_volatile_mfsr, exp, target);
+ case NDS32_BUILTIN_MFUSR:
+ return nds32_expand_builtin_reg_ftype_imm
+ (CODE_FOR_unspec_volatile_mfusr, exp, target);
+ case NDS32_BUILTIN_MTSR:
+ return nds32_expand_builtin_null_ftype_reg_imm
+ (CODE_FOR_unspec_volatile_mtsr, exp, target);
+ case NDS32_BUILTIN_MTUSR:
+ return nds32_expand_builtin_null_ftype_reg_imm
+ (CODE_FOR_unspec_volatile_mtusr, exp, target);
+
+ /* Interrupt. */
+ case NDS32_BUILTIN_SETGIE_EN:
+ /* Since there are no result and operands for setgie.e instruciton,
+ we can simply emit this rtx. */
+ emit_insn (gen_unspec_volatile_setgie_en ());
+ return target;
+ case NDS32_BUILTIN_SETGIE_DIS:
+ /* Since there are no result and operands for setgie.d instruciton,
+ we can simply emit this rtx. */
+ emit_insn (gen_unspec_volatile_setgie_dis ());
+ return target;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ return NULL_RTX;
+}
+
+
+/* ------------------------------------------------------------------------ */
+
+/* PART 4: Implemet extern function definitions,
+ the prototype is in nds32-protos.h. */
+
+/* Defining Data Structures for Per-function Information. */
+
+void
+nds32_init_expanders (void)
+{
+ /* Arrange to initialize and mark the machine per-function status. */
+ init_machine_status = nds32_init_machine_status;
+}
+
+
+/* Register Usage. */
+
+/* -- How Values Fit in Registers. */
+
+int
+nds32_hard_regno_nregs (int regno ATTRIBUTE_UNUSED,
+ enum machine_mode mode)
+{
+ return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD);
+}
+
+int
+nds32_hard_regno_mode_ok (int regno, enum machine_mode mode)
+{
+ /* Restrict double-word quantities to even register pairs. */
+ if (HARD_REGNO_NREGS (regno, mode) == 1
+ || !((regno) & 1))
+ return 1;
+
+ return 0;
+}
+
+
+/* Register Classes. */
+
+enum reg_class
+nds32_regno_reg_class (int regno)
+{
+ /* Refer to nds32.h for more register class details. */
+
+ if (regno >= 0 && regno <= 7)
+ return LOW_REGS;
+ else if (regno >= 8 && regno <= 11)
+ return MIDDLE_REGS;
+ else if (regno >= 12 && regno <= 14)
+ return HIGH_REGS;
+ else if (regno == 15)
+ return R15_TA_REG;
+ else if (regno >= 16 && regno <= 19)
+ return MIDDLE_REGS;
+ else if (regno >= 20 && regno <= 31)
+ return HIGH_REGS;
+ else if (regno == 32 || regno == 33)
+ return FRAME_REGS;
+ else
+ return NO_REGS;
+}
+
+
+/* Stack Layout and Calling Conventions. */
+
+/* -- Basic Stack Layout. */
+
+rtx
+nds32_return_addr_rtx (int count,
+ rtx frameaddr ATTRIBUTE_UNUSED)
+{
+ /* There is no way to determine the return address
+ if frameaddr is the frame that has 'count' steps
+ up from current frame. */
+ if (count != 0)
+ return NULL_RTX;
+
+ /* If count == 0, it means we are at current frame,
+ the return address is $r30 ($lp). */
+ return get_hard_reg_initial_val (Pmode, LP_REGNUM);
+}
+
+/* -- Eliminating Frame Pointer and Arg Pointer. */
+
+HOST_WIDE_INT
+nds32_initial_elimination_offset (unsigned int from_reg, unsigned int to_reg)
+{
+ HOST_WIDE_INT offset;
+
+ /* Compute and setup stack frame size.
+ The result will be in cfun->machine. */
+ nds32_compute_stack_frame ();
+
+ /* Remember to consider
+ cfun->machine->callee_saved_area_padding_bytes
+ when calculating offset. */
+ if (from_reg == ARG_POINTER_REGNUM && to_reg == STACK_POINTER_REGNUM)
+ {
+ offset = (cfun->machine->fp_size
+ + cfun->machine->gp_size
+ + cfun->machine->lp_size
+ + cfun->machine->callee_saved_regs_size
+ + cfun->machine->callee_saved_area_padding_bytes
+ + cfun->machine->local_size
+ + cfun->machine->out_args_size);
+ }
+ else if (from_reg == ARG_POINTER_REGNUM
+ && to_reg == HARD_FRAME_POINTER_REGNUM)
+ {
+ offset = 0;
+ }
+ else if (from_reg == FRAME_POINTER_REGNUM
+ && to_reg == STACK_POINTER_REGNUM)
+ {
+ offset = (cfun->machine->local_size + cfun->machine->out_args_size);
+ }
+ else if (from_reg == FRAME_POINTER_REGNUM
+ && to_reg == HARD_FRAME_POINTER_REGNUM)
+ {
+ offset = (-1) * (cfun->machine->fp_size
+ + cfun->machine->gp_size
+ + cfun->machine->lp_size
+ + cfun->machine->callee_saved_regs_size
+ + cfun->machine->callee_saved_area_padding_bytes);
+ }
+ else
+ {
+ gcc_unreachable ();
+ }
+
+ return offset;
+}
+
+/* -- Passing Arguments in Registers. */
+
+void
+nds32_init_cumulative_args (CUMULATIVE_ARGS *cum,
+ tree fntype ATTRIBUTE_UNUSED,
+ rtx libname ATTRIBUTE_UNUSED,
+ tree fndecl ATTRIBUTE_UNUSED,
+ int n_named_args ATTRIBUTE_UNUSED)
+{
+ /* Initial available registers
+ (in offset, corresponding to NDS32_GPR_ARG_FIRST_REGNUM)
+ for passing arguments. */
+ cum->reg_offset = 0;
+}
+
+/* -- Function Entry and Exit. */
+
+/* Function for normal multiple push prologue. */
+void
+nds32_expand_prologue (void)
+{
+ int fp_adjust;
+ int sp_adjust;
+ int en4_const;
+
+ rtx Rb, Re;
+ rtx push_insn;
+ rtx fp_adjust_insn, sp_adjust_insn;
+
+ /* Before computing everything for stack frame size,
+ we check if it is still worth to use fp_as_gp optimization.
+ If it is, the 'df_regs_ever_live_p (FP_REGNUM)' will be set
+ so that $fp will be saved on stack. */
+ cfun->machine->fp_as_gp_p = nds32_fp_as_gp_check_available ();
+
+ /* Compute and setup stack frame size.
+ The result will be in cfun->machine. */
+ nds32_compute_stack_frame ();
+
+ /* If the function is 'naked',
+ we do not have to generate prologue code fragment. */
+ if (cfun->machine->naked_p)
+ return;
+
+ /* Get callee_first_regno and callee_last_regno. */
+ Rb = gen_rtx_REG (SImode, cfun->machine->callee_saved_regs_first_regno);
+ Re = gen_rtx_REG (SImode, cfun->machine->callee_saved_regs_last_regno);
+
+ /* push_insn = gen_stack_push_multiple(first_regno, last_regno),
+ the pattern 'stack_push_multiple' is implemented in nds32.md.
+ For En4 field, we have to calculate its constant value.
+ Refer to Andes ISA for more information. */
+ en4_const = 0;
+ if (cfun->machine->fp_size)
+ en4_const += 8;
+ if (cfun->machine->gp_size)
+ en4_const += 4;
+ if (cfun->machine->lp_size)
+ en4_const += 2;
+
+ /* If $fp, $gp, $lp, and all callee-save registers are NOT required
+ to be saved, we don't have to create multiple push instruction.
+ Otherwise, a multiple push instruction is needed. */
+ if (!(REGNO (Rb) == SP_REGNUM && REGNO (Re) == SP_REGNUM && en4_const == 0))
+ {
+ /* Create multiple push instruction rtx. */
+ push_insn = nds32_gen_stack_push_multiple (Rb, Re, GEN_INT (en4_const));
+ /* Emit rtx into instructions list and receive INSN rtx form. */
+ push_insn = emit_insn (push_insn);
+
+ /* The insn rtx 'push_insn' will change frame layout.
+ We need to use RTX_FRAME_RELATED_P so that GCC is able to
+ generate CFI (Call Frame Information) stuff. */
+ RTX_FRAME_RELATED_P (push_insn) = 1;
+ }
+
+ /* Check frame_pointer_needed to see
+ if we shall emit fp adjustment instruction. */
+ if (frame_pointer_needed)
+ {
+ /* adjust $fp = $sp + ($fp size) + ($gp size) + ($lp size)
+ + (4 * callee-saved-registers)
+ Note: No need to adjust
+ cfun->machine->callee_saved_area_padding_bytes,
+ because, at this point, stack pointer is just
+ at the position after push instruction. */
+ fp_adjust = cfun->machine->fp_size
+ + cfun->machine->gp_size
+ + cfun->machine->lp_size
+ + cfun->machine->callee_saved_regs_size;
+ fp_adjust_insn = gen_addsi3 (hard_frame_pointer_rtx,
+ stack_pointer_rtx,
+ GEN_INT (fp_adjust));
+ /* Emit rtx into instructions list and receive INSN rtx form. */
+ fp_adjust_insn = emit_insn (fp_adjust_insn);
+ }
+
+ /* Adjust $sp = $sp - local_size - out_args_size
+ - callee_saved_area_padding_bytes. */
+ sp_adjust = cfun->machine->local_size
+ + cfun->machine->out_args_size
+ + cfun->machine->callee_saved_area_padding_bytes;
+ /* sp_adjust value may be out of range of the addi instruction,
+ create alternative add behavior with TA_REGNUM if necessary,
+ using NEGATIVE value to tell that we are decreasing address. */
+ sp_adjust = nds32_force_addi_stack_int ( (-1) * sp_adjust);
+ if (sp_adjust)
+ {
+ /* Generate sp adjustment instruction if and only if sp_adjust != 0. */
+ sp_adjust_insn = gen_addsi3 (stack_pointer_rtx,
+ stack_pointer_rtx,
+ GEN_INT (-1 * sp_adjust));
+ /* Emit rtx into instructions list and receive INSN rtx form. */
+ sp_adjust_insn = emit_insn (sp_adjust_insn);
+
+ /* The insn rtx 'sp_adjust_insn' will change frame layout.
+ We need to use RTX_FRAME_RELATED_P so that GCC is able to
+ generate CFI (Call Frame Information) stuff. */
+ RTX_FRAME_RELATED_P (sp_adjust_insn) = 1;
+ }
+
+ /* Prevent the instruction scheduler from
+ moving instructions across the boundary. */
+ emit_insn (gen_blockage ());
+}
+
+/* Function for normal multiple pop epilogue. */
+void
+nds32_expand_epilogue (void)
+{
+ int sp_adjust;
+ int en4_const;
+
+ rtx Rb, Re;
+ rtx pop_insn;
+ rtx sp_adjust_insn;
+
+ /* Compute and setup stack frame size.
+ The result will be in cfun->machine. */
+ nds32_compute_stack_frame ();
+
+ /* Prevent the instruction scheduler from
+ moving instructions across the boundary. */
+ emit_insn (gen_blockage ());
+
+ /* If the function is 'naked', we do not have to generate
+ epilogue code fragment BUT 'ret' instruction. */
+ if (cfun->machine->naked_p)
+ {
+ /* Generate return instruction by using
+ unspec_volatile_func_return pattern.
+ Make sure this instruction is after gen_blockage().
+ NOTE that $lp will become 'live'
+ after this instruction has been emitted. */
+ emit_insn (gen_unspec_volatile_func_return ());
+ return;
+ }
+
+ if (frame_pointer_needed)
+ {
+ /* adjust $sp = $fp - ($fp size) - ($gp size) - ($lp size)
+ - (4 * callee-saved-registers)
+ Note: No need to adjust
+ cfun->machine->callee_saved_area_padding_bytes,
+ because we want to adjust stack pointer
+ to the position for pop instruction. */
+ sp_adjust = cfun->machine->fp_size
+ + cfun->machine->gp_size
+ + cfun->machine->lp_size
+ + cfun->machine->callee_saved_regs_size;
+ sp_adjust_insn = gen_addsi3 (stack_pointer_rtx,
+ hard_frame_pointer_rtx,
+ GEN_INT (-1 * sp_adjust));
+ /* Emit rtx into instructions list and receive INSN rtx form. */
+ sp_adjust_insn = emit_insn (sp_adjust_insn);
+ }
+ else
+ {
+ /* If frame pointer is NOT needed,
+ we cannot calculate the sp adjustment from frame pointer.
+ Instead, we calculate the adjustment by local_size,
+ out_args_size, and callee_saved_area_padding_bytes.
+ Notice that such sp adjustment value may be out of range,
+ so we have to deal with it as well. */
+
+ /* Adjust $sp = $sp + local_size + out_args_size
+ + callee_saved_area_padding_bytes. */
+ sp_adjust = cfun->machine->local_size
+ + cfun->machine->out_args_size
+ + cfun->machine->callee_saved_area_padding_bytes;
+ /* sp_adjust value may be out of range of the addi instruction,
+ create alternative add behavior with TA_REGNUM if necessary,
+ using POSITIVE value to tell that we are increasing address. */
+ sp_adjust = nds32_force_addi_stack_int (sp_adjust);
+ if (sp_adjust)
+ {
+ /* Generate sp adjustment instruction
+ if and only if sp_adjust != 0. */
+ sp_adjust_insn = gen_addsi3 (stack_pointer_rtx,
+ stack_pointer_rtx,
+ GEN_INT (sp_adjust));
+ /* Emit rtx into instructions list and receive INSN rtx form. */
+ sp_adjust_insn = emit_insn (sp_adjust_insn);
+ }
+ }
+
+ /* Get callee_first_regno and callee_last_regno. */
+ Rb = gen_rtx_REG (SImode, cfun->machine->callee_saved_regs_first_regno);
+ Re = gen_rtx_REG (SImode, cfun->machine->callee_saved_regs_last_regno);
+
+ /* pop_insn = gen_stack_pop_multiple(first_regno, last_regno),
+ the pattern 'stack_pop_multiple' is implementad in nds32.md.
+ For En4 field, we have to calculate its constant value.
+ Refer to Andes ISA for more information. */
+ en4_const = 0;
+ if (cfun->machine->fp_size)
+ en4_const += 8;
+ if (cfun->machine->gp_size)
+ en4_const += 4;
+ if (cfun->machine->lp_size)
+ en4_const += 2;
+
+ /* If $fp, $gp, $lp, and all callee-save registers are NOT required
+ to be saved, we don't have to create multiple pop instruction.
+ Otherwise, a multiple pop instruction is needed. */
+ if (!(REGNO (Rb) == SP_REGNUM && REGNO (Re) == SP_REGNUM && en4_const == 0))
+ {
+ /* Create multiple pop instruction rtx. */
+ pop_insn = nds32_gen_stack_pop_multiple (Rb, Re, GEN_INT (en4_const));
+ /* Emit pop instruction. */
+ emit_insn (pop_insn);
+ }
+
+ /* Generate return instruction by using
+ unspec_volatile_func_return pattern. */
+ emit_insn (gen_unspec_volatile_func_return ());
+}
+
+/* Function for v3push prologue. */
+void
+nds32_expand_prologue_v3push (void)
+{
+ int fp_adjust;
+ int sp_adjust;
+
+ rtx Rb, Re;
+ rtx push_insn;
+ rtx fp_adjust_insn, sp_adjust_insn;
+
+ /* Before computing everything for stack frame size,
+ we check if it is still worth to use fp_as_gp optimization.
+ If it is, the 'df_regs_ever_live_p (FP_REGNUM)' will be set
+ so that $fp will be saved on stack. */
+ cfun->machine->fp_as_gp_p = nds32_fp_as_gp_check_available ();
+
+ /* Compute and setup stack frame size.
+ The result will be in cfun->machine. */
+ nds32_compute_stack_frame ();
+
+ /* If the function is 'naked',
+ we do not have to generate prologue code fragment. */
+ if (cfun->machine->naked_p)
+ return;
+
+ /* Get callee_first_regno and callee_last_regno. */
+ Rb = gen_rtx_REG (SImode, cfun->machine->callee_saved_regs_first_regno);
+ Re = gen_rtx_REG (SImode, cfun->machine->callee_saved_regs_last_regno);
+
+ /* Calculate sp_adjust first to test if 'push25 Re,imm8u' is available,
+ where imm8u has to be 8-byte alignment. */
+ sp_adjust = cfun->machine->local_size
+ + cfun->machine->out_args_size
+ + cfun->machine->callee_saved_area_padding_bytes;
+
+ if (satisfies_constraint_Iu08 (GEN_INT (sp_adjust))
+ && NDS32_DOUBLE_WORD_ALIGN_P (sp_adjust))
+ {
+ /* We can use 'push25 Re,imm8u'. */
+
+ /* push_insn = gen_stack_v3push(last_regno, sp_adjust),
+ the pattern 'stack_v3push' is implemented in nds32.md.
+ The (const_int 14) means v3push always push { $fp $gp $lp }. */
+ push_insn = nds32_gen_stack_v3push (Rb, Re,
+ GEN_INT (14), GEN_INT (sp_adjust));
+ /* emit rtx into instructions list and receive INSN rtx form */
+ push_insn = emit_insn (push_insn);
+
+ /* The insn rtx 'push_insn' will change frame layout.
+ We need to use RTX_FRAME_RELATED_P so that GCC is able to
+ generate CFI (Call Frame Information) stuff. */
+ RTX_FRAME_RELATED_P (push_insn) = 1;
+
+ /* Check frame_pointer_needed to see
+ if we shall emit fp adjustment instruction. */
+ if (frame_pointer_needed)
+ {
+ /* adjust $fp = $sp + 4 ($fp size)
+ + 4 ($gp size)
+ + 4 ($lp size)
+ + (4 * n) (callee-saved registers)
+ + sp_adjust ('push25 Re,imm8u')
+ Note: Since we use 'push25 Re,imm8u',
+ the position of stack pointer is further
+ changed after push instruction.
+ Hence, we need to take sp_adjust value
+ into consideration. */
+ fp_adjust = cfun->machine->fp_size
+ + cfun->machine->gp_size
+ + cfun->machine->lp_size
+ + cfun->machine->callee_saved_regs_size
+ + sp_adjust;
+ fp_adjust_insn = gen_addsi3 (hard_frame_pointer_rtx,
+ stack_pointer_rtx,
+ GEN_INT (fp_adjust));
+ /* Emit rtx into instructions list and receive INSN rtx form. */
+ fp_adjust_insn = emit_insn (fp_adjust_insn);
+ }
+ }
+ else
+ {
+ /* We have to use 'push25 Re,0' and
+ expand one more instruction to adjust $sp later. */
+
+ /* push_insn = gen_stack_v3push(last_regno, sp_adjust),
+ the pattern 'stack_v3push' is implemented in nds32.md.
+ The (const_int 14) means v3push always push { $fp $gp $lp }. */
+ push_insn = nds32_gen_stack_v3push (Rb, Re,
+ GEN_INT (14), GEN_INT (0));
+ /* Emit rtx into instructions list and receive INSN rtx form. */
+ push_insn = emit_insn (push_insn);
+
+ /* The insn rtx 'push_insn' will change frame layout.
+ We need to use RTX_FRAME_RELATED_P so that GCC is able to
+ generate CFI (Call Frame Information) stuff. */
+ RTX_FRAME_RELATED_P (push_insn) = 1;
+
+ /* Check frame_pointer_needed to see
+ if we shall emit fp adjustment instruction. */
+ if (frame_pointer_needed)
+ {
+ /* adjust $fp = $sp + 4 ($fp size)
+ + 4 ($gp size)
+ + 4 ($lp size)
+ + (4 * n) (callee-saved registers)
+ Note: Since we use 'push25 Re,0',
+ the stack pointer is just at the position
+ after push instruction.
+ No need to take sp_adjust into consideration. */
+ fp_adjust = cfun->machine->fp_size
+ + cfun->machine->gp_size
+ + cfun->machine->lp_size
+ + cfun->machine->callee_saved_regs_size;
+ fp_adjust_insn = gen_addsi3 (hard_frame_pointer_rtx,
+ stack_pointer_rtx,
+ GEN_INT (fp_adjust));
+ /* Emit rtx into instructions list and receive INSN rtx form. */
+ fp_adjust_insn = emit_insn (fp_adjust_insn);
+ }
+
+ /* Because we use 'push25 Re,0',
+ we need to expand one more instruction to adjust $sp.
+ However, sp_adjust value may be out of range of the addi instruction,
+ create alternative add behavior with TA_REGNUM if necessary,
+ using NEGATIVE value to tell that we are decreasing address. */
+ sp_adjust = nds32_force_addi_stack_int ( (-1) * sp_adjust);
+ if (sp_adjust)
+ {
+ /* Generate sp adjustment instruction
+ if and only if sp_adjust != 0. */
+ sp_adjust_insn = gen_addsi3 (stack_pointer_rtx,
+ stack_pointer_rtx,
+ GEN_INT (-1 * sp_adjust));
+ /* Emit rtx into instructions list and receive INSN rtx form. */
+ sp_adjust_insn = emit_insn (sp_adjust_insn);
+
+ /* The insn rtx 'sp_adjust_insn' will change frame layout.
+ We need to use RTX_FRAME_RELATED_P so that GCC is able to
+ generate CFI (Call Frame Information) stuff. */
+ RTX_FRAME_RELATED_P (sp_adjust_insn) = 1;
+ }
+ }
+
+ /* Prevent the instruction scheduler from
+ moving instructions across the boundary. */
+ emit_insn (gen_blockage ());
+}
+
+/* Function for v3pop epilogue. */
+void
+nds32_expand_epilogue_v3pop (void)
+{
+ int sp_adjust;
+
+ rtx Rb, Re;
+ rtx pop_insn;
+ rtx sp_adjust_insn;
+
+ /* Compute and setup stack frame size.
+ The result will be in cfun->machine. */
+ nds32_compute_stack_frame ();
+
+ /* Prevent the instruction scheduler from
+ moving instructions across the boundary. */
+ emit_insn (gen_blockage ());
+
+ /* If the function is 'naked', we do not have to generate
+ epilogue code fragment BUT 'ret' instruction. */
+ if (cfun->machine->naked_p)
+ {
+ /* Generate return instruction by using
+ unspec_volatile_func_return pattern.
+ Make sure this instruction is after gen_blockage().
+ NOTE that $lp will become 'live'
+ after this instruction has been emitted. */
+ emit_insn (gen_unspec_volatile_func_return ());
+ return;
+ }
+
+ /* Get callee_first_regno and callee_last_regno. */
+ Rb = gen_rtx_REG (SImode, cfun->machine->callee_saved_regs_first_regno);
+ Re = gen_rtx_REG (SImode, cfun->machine->callee_saved_regs_last_regno);
+
+ /* Calculate sp_adjust first to test if 'pop25 Re,imm8u' is available,
+ where imm8u has to be 8-byte alignment. */
+ sp_adjust = cfun->machine->local_size
+ + cfun->machine->out_args_size
+ + cfun->machine->callee_saved_area_padding_bytes;
+
+ /* We have to consider alloca issue as well.
+ If the function does call alloca(), the stack pointer is not fixed.
+ In that case, we cannot use 'pop25 Re,imm8u' directly.
+ We have to caculate stack pointer from frame pointer
+ and then use 'pop25 Re,0'.
+ Of course, the frame_pointer_needed should be nonzero
+ if the function calls alloca(). */
+ if (satisfies_constraint_Iu08 (GEN_INT (sp_adjust))
+ && NDS32_DOUBLE_WORD_ALIGN_P (sp_adjust)
+ && !cfun->calls_alloca)
+ {
+ /* We can use 'pop25 Re,imm8u'. */
+
+ /* pop_insn = gen_stack_v3pop(last_regno, sp_adjust),
+ the pattern 'stack_v3pop' is implementad in nds32.md.
+ The (const_int 14) means v3pop always pop { $fp $gp $lp }. */
+ pop_insn = nds32_gen_stack_v3pop (Rb, Re,
+ GEN_INT (14), GEN_INT (sp_adjust));
+
+ /* Emit pop instruction. */
+ emit_insn (pop_insn);
+ }
+ else
+ {
+ /* We have to use 'pop25 Re,0', and prior to it,
+ we must expand one more instruction to adjust $sp. */
+
+ if (frame_pointer_needed)
+ {
+ /* adjust $sp = $fp - 4 ($fp size)
+ - 4 ($gp size)
+ - 4 ($lp size)
+ - (4 * n) (callee-saved registers)
+ Note: No need to adjust
+ cfun->machine->callee_saved_area_padding_bytes,
+ because we want to adjust stack pointer
+ to the position for pop instruction. */
+ sp_adjust = cfun->machine->fp_size
+ + cfun->machine->gp_size
+ + cfun->machine->lp_size
+ + cfun->machine->callee_saved_regs_size;
+ sp_adjust_insn = gen_addsi3 (stack_pointer_rtx,
+ hard_frame_pointer_rtx,
+ GEN_INT (-1 * sp_adjust));
+ /* Emit rtx into instructions list and receive INSN rtx form. */
+ sp_adjust_insn = emit_insn (sp_adjust_insn);
+ }
+ else
+ {
+ /* If frame pointer is NOT needed,
+ we cannot calculate the sp adjustment from frame pointer.
+ Instead, we calculate the adjustment by local_size,
+ out_args_size, and callee_saved_area_padding_bytes.
+ Notice that such sp adjustment value may be out of range,
+ so we have to deal with it as well. */
+
+ /* Adjust $sp = $sp + local_size + out_args_size
+ + callee_saved_area_padding_bytes. */
+ sp_adjust = cfun->machine->local_size
+ + cfun->machine->out_args_size
+ + cfun->machine->callee_saved_area_padding_bytes;
+ /* sp_adjust value may be out of range of the addi instruction,
+ create alternative add behavior with TA_REGNUM if necessary,
+ using POSITIVE value to tell that we are increasing address. */
+ sp_adjust = nds32_force_addi_stack_int (sp_adjust);
+ if (sp_adjust)
+ {
+ /* Generate sp adjustment instruction
+ if and only if sp_adjust != 0. */
+ sp_adjust_insn = gen_addsi3 (stack_pointer_rtx,
+ stack_pointer_rtx,
+ GEN_INT (sp_adjust));
+ /* Emit rtx into instructions list and receive INSN rtx form. */
+ sp_adjust_insn = emit_insn (sp_adjust_insn);
+ }
+ }
+
+ /* pop_insn = gen_stack_v3pop(last_regno, sp_adjust),
+ the pattern 'stack_v3pop' is implementad in nds32.md. */
+ /* The (const_int 14) means v3pop always pop { $fp $gp $lp }. */
+ pop_insn = nds32_gen_stack_v3pop (Rb, Re,
+ GEN_INT (14), GEN_INT (0));
+
+ /* Emit pop instruction. */
+ emit_insn (pop_insn);
+ }
+}
+
+/* ------------------------------------------------------------------------ */
+
+/* Function to test 333-form for load/store instructions.
+ This is auxiliary extern function for auxiliary macro in nds32.h.
+ Because it is a little complicated, we use function instead of macro. */
+bool
+nds32_ls_333_p (rtx rt, rtx ra, rtx imm, enum machine_mode mode)
+{
+ if (REGNO_REG_CLASS (REGNO (rt)) == LOW_REGS
+ && REGNO_REG_CLASS (REGNO (ra)) == LOW_REGS)
+ {
+ if (GET_MODE_SIZE (mode) == 4)
+ return satisfies_constraint_Iu05 (imm);
+
+ if (GET_MODE_SIZE (mode) == 2)
+ return satisfies_constraint_Iu04 (imm);
+
+ if (GET_MODE_SIZE (mode) == 1)
+ return satisfies_constraint_Iu03 (imm);
+ }
+
+ return false;
+}
+
+
+/* Functions to expand load_multiple and store_multiple.
+ They are auxiliary extern functions to help create rtx template.
+ Check nds32-multiple.md file for the patterns. */
+rtx
+nds32_expand_load_multiple (int base_regno, int count,
+ rtx base_addr, rtx basemem)
+{
+ int par_index;
+ int offset;
+ rtx result;
+ rtx new_addr, mem, reg;
+
+ /* Create the pattern that is presented in nds32-multiple.md. */
+
+ result = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
+
+ for (par_index = 0; par_index < count; par_index++)
+ {
+ offset = par_index * 4;
+ /* 4-byte for loading data to each register. */
+ new_addr = plus_constant (Pmode, base_addr, offset);
+ mem = adjust_automodify_address_nv (basemem, SImode,
+ new_addr, offset);
+ reg = gen_rtx_REG (SImode, base_regno + par_index);
+
+ XVECEXP (result, 0, par_index) = gen_rtx_SET (VOIDmode, reg, mem);
+ }
+
+ return result;
+}
+
+rtx
+nds32_expand_store_multiple (int base_regno, int count,
+ rtx base_addr, rtx basemem)
+{
+ int par_index;
+ int offset;
+ rtx result;
+ rtx new_addr, mem, reg;
+
+ /* Create the pattern that is presented in nds32-multiple.md. */
+
+ result = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
+
+ for (par_index = 0; par_index < count; par_index++)
+ {
+ offset = par_index * 4;
+ /* 4-byte for storing data to memory. */
+ new_addr = plus_constant (Pmode, base_addr, offset);
+ mem = adjust_automodify_address_nv (basemem, SImode,
+ new_addr, offset);
+ reg = gen_rtx_REG (SImode, base_regno + par_index);
+
+ XVECEXP (result, 0, par_index) = gen_rtx_SET (VOIDmode, mem, reg);
+ }
+
+ return result;
+}
+
+/* Function to move block memory content by
+ using load_multiple and store_multiple.
+ This is auxiliary extern function to help create rtx template.
+ Check nds32-multiple.md file for the patterns. */
+int
+nds32_expand_movmemqi (rtx dstmem, rtx srcmem, rtx total_bytes, rtx alignment)
+{
+ HOST_WIDE_INT in_words, out_words;
+ rtx dst_base_reg, src_base_reg;
+ int maximum_bytes;
+
+ /* Because reduced-set regsiters has few registers
+ (r0~r5, r6~10, r15, r28~r31, where 'r15' and 'r28~r31'
+ cannot be used for register allocation),
+ using 8 registers (32 bytes) for moving memory block
+ may easily consume all of them.
+ It makes register allocation/spilling hard to work.
+ So we only allow maximum=4 registers (16 bytes) for
+ moving memory block under reduced-set registers. */
+ if (TARGET_REDUCED_REGS)
+ maximum_bytes = 16;
+ else
+ maximum_bytes = 32;
+
+ /* 1. Total_bytes is integer for sure.
+ 2. Alignment is integer for sure.
+ 3. Maximum 4 or 8 registers, 4 * 4 = 16 bytes, 8 * 4 = 32 bytes.
+ 4. Requires (n * 4) block size.
+ 5. Requires 4-byte alignment. */
+ if (GET_CODE (total_bytes) != CONST_INT
+ || GET_CODE (alignment) != CONST_INT
+ || INTVAL (total_bytes) > maximum_bytes
+ || INTVAL (total_bytes) & 3
+ || INTVAL (alignment) & 3)
+ return 0;
+
+ dst_base_reg = copy_to_mode_reg (SImode, XEXP (dstmem, 0));
+ src_base_reg = copy_to_mode_reg (SImode, XEXP (srcmem, 0));
+
+ out_words = in_words = INTVAL (total_bytes) / UNITS_PER_WORD;
+
+ emit_insn (nds32_expand_load_multiple (0, in_words, src_base_reg, srcmem));
+ emit_insn (nds32_expand_store_multiple (0, out_words, dst_base_reg, dstmem));
+
+ /* Successfully create patterns, return 1. */
+ return 1;
+}
+
+/* Function to check whether the OP is a valid load/store operation.
+ This is a helper function for the predicates:
+ 'nds32_load_multiple_operation' and 'nds32_store_multiple_operation'
+ in predicates.md file.
+
+ The OP is supposed to be a parallel rtx.
+ For each element within this parallel rtx:
+ (set (reg) (mem addr)) is the form for load operation.
+ (set (mem addr) (reg)) is the form for store operation.
+ We have to extract reg and mem of every element and
+ check if the information is valid for multiple load/store operation. */
+bool
+nds32_valid_multiple_load_store (rtx op, bool load_p)
+{
+ int count;
+ int first_elt_regno;
+ rtx elt;
+
+ /* Get the counts of elements in the parallel rtx. */
+ count = XVECLEN (op, 0);
+ /* Pick up the first element. */
+ elt = XVECEXP (op, 0, 0);
+
+ /* Perform some quick check for the first element in the parallel rtx. */
+ if (GET_CODE (elt) != SET
+ || count <= 1
+ || count > 8)
+ return false;
+
+ /* Pick up regno of first element for further detail checking.
+ Note that the form is different between load and store operation. */
+ if (load_p)
+ {
+ if (GET_CODE (SET_DEST (elt)) != REG
+ || GET_CODE (SET_SRC (elt)) != MEM)
+ return false;
+
+ first_elt_regno = REGNO (SET_DEST (elt));
+ }
+ else
+ {
+ if (GET_CODE (SET_SRC (elt)) != REG
+ || GET_CODE (SET_DEST (elt)) != MEM)
+ return false;
+
+ first_elt_regno = REGNO (SET_SRC (elt));
+ }
+
+ /* Perform detail check for each element.
+ Refer to nds32-multiple.md for more information
+ about following checking.
+ The starting element of parallel rtx is index 0. */
+ if (!nds32_consecutive_registers_load_store_p (op, load_p, 0,
+ first_elt_regno,
+ count))
+ return false;
+
+ /* Pass all test, this is a valid rtx. */
+ return true;
+}
+
+/* Function to check whether the OP is a valid stack push/pop operation.
+ For a valid stack operation, it must satisfy following conditions:
+ 1. Consecutive registers push/pop operations.
+ 2. Valid $fp/$gp/$lp push/pop operations.
+ 3. The last element must be stack adjustment rtx.
+ See the prologue/epilogue implementation for details. */
+bool
+nds32_valid_stack_push_pop (rtx op, bool push_p)
+{
+ int index;
+ int total_count;
+ int rest_count;
+ int first_regno;
+ rtx elt;
+ rtx elt_reg;
+ rtx elt_mem;
+ rtx elt_plus;
+
+ /* Get the counts of elements in the parallel rtx. */
+ total_count = XVECLEN (op, 0);
+
+ /* Perform some quick check for that every element should be 'set'. */
+ for (index = 0; index < total_count; index++)
+ {
+ elt = XVECEXP (op, 0, index);
+ if (GET_CODE (elt) != SET)
+ return false;
+ }
+
+ /* For push operation, the parallel rtx looks like:
+ (parallel [(set (mem (plus (reg:SI SP_REGNUM) (const_int -32)))
+ (reg:SI Rb))
+ (set (mem (plus (reg:SI SP_REGNUM) (const_int -28)))
+ (reg:SI Rb+1))
+ ...
+ (set (mem (plus (reg:SI SP_REGNUM) (const_int -16)))
+ (reg:SI Re))
+ (set (mem (plus (reg:SI SP_REGNUM) (const_int -12)))
+ (reg:SI FP_REGNUM))
+ (set (mem (plus (reg:SI SP_REGNUM) (const_int -8)))
+ (reg:SI GP_REGNUM))
+ (set (mem (plus (reg:SI SP_REGNUM) (const_int -4)))
+ (reg:SI LP_REGNUM))
+ (set (reg:SI SP_REGNUM)
+ (plus (reg:SI SP_REGNUM) (const_int -32)))])
+
+ For pop operation, the parallel rtx looks like:
+ (parallel [(set (reg:SI Rb)
+ (mem (reg:SI SP_REGNUM)))
+ (set (reg:SI Rb+1)
+ (mem (plus (reg:SI SP_REGNUM) (const_int 4))))
+ ...
+ (set (reg:SI Re)
+ (mem (plus (reg:SI SP_REGNUM) (const_int 16))))
+ (set (reg:SI FP_REGNUM)
+ (mem (plus (reg:SI SP_REGNUM) (const_int 20))))
+ (set (reg:SI GP_REGNUM)
+ (mem (plus (reg:SI SP_REGNUM) (const_int 24))))
+ (set (reg:SI LP_REGNUM)
+ (mem (plus (reg:SI SP_REGNUM) (const_int 28))))
+ (set (reg:SI SP_REGNUM)
+ (plus (reg:SI SP_REGNUM) (const_int 32)))]) */
+
+ /* 1. Consecutive registers push/pop operations.
+ We need to calculate how many registers should be consecutive.
+ The $sp adjustment rtx, $fp push rtx, $gp push rtx,
+ and $lp push rtx are excluded. */
+
+ /* Exclude last $sp adjustment rtx. */
+ rest_count = total_count - 1;
+ /* Exclude $fp, $gp, and $lp if they are in the parallel rtx. */
+ if (cfun->machine->fp_size)
+ rest_count--;
+ if (cfun->machine->gp_size)
+ rest_count--;
+ if (cfun->machine->lp_size)
+ rest_count--;
+
+ if (rest_count > 0)
+ {
+ elt = XVECEXP (op, 0, 0);
+ /* Pick up register element. */
+ elt_reg = push_p ? SET_SRC (elt) : SET_DEST (elt);
+ first_regno = REGNO (elt_reg);
+
+ /* The 'push' operation is a kind of store operation.
+ The 'pop' operation is a kind of load operation.
+ Pass corresponding false/true as second argument (bool load_p).
+ The par_index is supposed to start with index 0. */
+ if (!nds32_consecutive_registers_load_store_p (op,
+ !push_p ? true : false,
+ 0,
+ first_regno,
+ rest_count))
+ return false;
+ }
+
+ /* 2. Valid $fp/$gp/$lp push/pop operations.
+ Remember to set start index for checking them. */
+
+ /* The rest_count is the start index for checking $fp/$gp/$lp. */
+ index = rest_count;
+ /* If index < 0, this parallel rtx is definitely
+ not a valid stack push/pop operation. */
+ if (index < 0)
+ return false;
+
+ /* Check $fp/$gp/$lp one by one.
+ We use 'push_p' to pick up reg rtx and mem rtx. */
+ if (cfun->machine->fp_size)
+ {
+ elt = XVECEXP (op, 0, index);
+ elt_mem = push_p ? SET_DEST (elt) : SET_SRC (elt);
+ elt_reg = push_p ? SET_SRC (elt) : SET_DEST (elt);
+ index++;
+
+ if (GET_CODE (elt_mem) != MEM
+ || GET_CODE (elt_reg) != REG
+ || REGNO (elt_reg) != FP_REGNUM)
+ return false;
+ }
+ if (cfun->machine->gp_size)
+ {
+ elt = XVECEXP (op, 0, index);
+ elt_mem = push_p ? SET_DEST (elt) : SET_SRC (elt);
+ elt_reg = push_p ? SET_SRC (elt) : SET_DEST (elt);
+ index++;
+
+ if (GET_CODE (elt_mem) != MEM
+ || GET_CODE (elt_reg) != REG
+ || REGNO (elt_reg) != GP_REGNUM)
+ return false;
+ }
+ if (cfun->machine->lp_size)
+ {
+ elt = XVECEXP (op, 0, index);
+ elt_mem = push_p ? SET_DEST (elt) : SET_SRC (elt);
+ elt_reg = push_p ? SET_SRC (elt) : SET_DEST (elt);
+ index++;
+
+ if (GET_CODE (elt_mem) != MEM
+ || GET_CODE (elt_reg) != REG
+ || REGNO (elt_reg) != LP_REGNUM)
+ return false;
+ }
+
+ /* 3. The last element must be stack adjustment rtx.
+ Its form of rtx should be:
+ (set (reg:SI SP_REGNUM)
+ (plus (reg:SI SP_REGNUM) (const_int X)))
+ The X could be positive or negative value. */
+
+ /* Pick up the last element. */
+ elt = XVECEXP (op, 0, total_count - 1);
+
+ /* Extract its destination and source rtx. */
+ elt_reg = SET_DEST (elt);
+ elt_plus = SET_SRC (elt);
+
+ /* Check this is (set (stack_reg) (plus stack_reg const)) pattern. */
+ if (GET_CODE (elt_reg) != REG
+ || GET_CODE (elt_plus) != PLUS
+ || REGNO (elt_reg) != SP_REGNUM)
+ return false;
+
+ /* Pass all test, this is a valid rtx. */
+ return true;
+}
+
+/* Computing the Length of an Insn.
+ Modifies the length assigned to instruction INSN.
+ LEN is the initially computed length of the insn. */
+int
+nds32_adjust_insn_length (rtx insn, int length)
+{
+ rtx src, dst;
+
+ switch (recog_memoized (insn))
+ {
+ case CODE_FOR_move_df:
+ case CODE_FOR_move_di:
+ /* Adjust length of movd44 to 2. */
+ src = XEXP (PATTERN (insn), 1);
+ dst = XEXP (PATTERN (insn), 0);
+
+ if (REG_P (src)
+ && REG_P (dst)
+ && (REGNO (src) % 2) == 0
+ && (REGNO (dst) % 2) == 0)
+ length = 2;
+ break;
+
+ default:
+ break;
+ }
+
+ return length;
+}
+
+
+/* Function to check if 'bclr' instruction can be used with IVAL. */
+int
+nds32_can_use_bclr_p (int ival)
+{
+ int one_bit_count;
+
+ /* Calculate the number of 1-bit of (~ival), if there is only one 1-bit,
+ it means the original ival has only one 0-bit,
+ So it is ok to perform 'bclr' operation. */
+
+ one_bit_count = popcount_hwi ((unsigned HOST_WIDE_INT) (~ival));
+
+ /* 'bclr' is a performance extension instruction. */
+ return (TARGET_PERF_EXT && (one_bit_count == 1));
+}
+
+/* Function to check if 'bset' instruction can be used with IVAL. */
+int
+nds32_can_use_bset_p (int ival)
+{
+ int one_bit_count;
+
+ /* Caculate the number of 1-bit of ival, if there is only one 1-bit,
+ it is ok to perform 'bset' operation. */
+
+ one_bit_count = popcount_hwi ((unsigned HOST_WIDE_INT) (ival));
+
+ /* 'bset' is a performance extension instruction. */
+ return (TARGET_PERF_EXT && (one_bit_count == 1));
+}
+
+/* Function to check if 'btgl' instruction can be used with IVAL. */
+int
+nds32_can_use_btgl_p (int ival)
+{
+ int one_bit_count;
+
+ /* Caculate the number of 1-bit of ival, if there is only one 1-bit,
+ it is ok to perform 'btgl' operation. */
+
+ one_bit_count = popcount_hwi ((unsigned HOST_WIDE_INT) (ival));
+
+ /* 'btgl' is a performance extension instruction. */
+ return (TARGET_PERF_EXT && (one_bit_count == 1));
+}
+
+/* Function to check if 'bitci' instruction can be used with IVAL. */
+int
+nds32_can_use_bitci_p (int ival)
+{
+ /* If we are using V3 ISA, we have 'bitci' instruction.
+ Try to see if we can present 'andi' semantic with
+ such 'bit-clear-immediate' operation.
+ For example, 'andi $r0,$r0,0xfffffffc' can be
+ presented with 'bitci $r0,$r0,3'. */
+ return (TARGET_ISA_V3
+ && (ival < 0)
+ && satisfies_constraint_Iu15 (gen_int_mode (~ival, SImode)));
+}
+
+
+/* Return true if is load/store with SYMBOL_REF addressing mode
+ and memory mode is SImode. */
+bool
+nds32_symbol_load_store_p (rtx insn)
+{
+ rtx mem_src = NULL_RTX;
+
+ switch (get_attr_type (insn))
+ {
+ case TYPE_LOAD:
+ mem_src = SET_SRC (PATTERN (insn));
+ break;
+ case TYPE_STORE:
+ mem_src = SET_DEST (PATTERN (insn));
+ break;
+ default:
+ break;
+ }
+
+ /* Find load/store insn with addressing mode is SYMBOL_REF. */
+ if (mem_src != NULL_RTX)
+ {
+ if ((GET_CODE (mem_src) == ZERO_EXTEND)
+ || (GET_CODE (mem_src) == SIGN_EXTEND))
+ mem_src = XEXP (mem_src, 0);
+
+ if ((GET_CODE (XEXP (mem_src, 0)) == SYMBOL_REF)
+ || (GET_CODE (XEXP (mem_src, 0)) == LO_SUM))
+ return true;
+ }
+
+ return false;
+}
+
+/* Function to determine whether it is worth to do fp_as_gp optimization.
+ Return 0: It is NOT worth to do fp_as_gp optimization.
+ Return 1: It is APPROXIMATELY worth to do fp_as_gp optimization.
+ Note that if it is worth to do fp_as_gp optimization,
+ we MUST set FP_REGNUM ever live in this function. */
+int
+nds32_fp_as_gp_check_available (void)
+{
+ /* If there exists ANY of following conditions,
+ we DO NOT perform fp_as_gp optimization:
+ 1. TARGET_FORBID_FP_AS_GP is set
+ regardless of the TARGET_FORCE_FP_AS_GP.
+ 2. User explicitly uses 'naked' attribute.
+ 3. Not optimize for size.
+ 4. Need frame pointer.
+ 5. If $fp is already required to be saved,
+ it means $fp is already choosen by register allocator.
+ Thus we better not to use it for fp_as_gp optimization.
+ 6. This function is a vararg function.
+ DO NOT apply fp_as_gp optimization on this function
+ because it may change and break stack frame.
+ 7. The epilogue is empty.
+ This happens when the function uses exit()
+ or its attribute is no_return.
+ In that case, compiler will not expand epilogue
+ so that we have no chance to output .omit_fp_end directive. */
+ if (TARGET_FORBID_FP_AS_GP
+ || lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl))
+ || !optimize_size
+ || frame_pointer_needed
+ || NDS32_REQUIRED_CALLEE_SAVED_P (FP_REGNUM)
+ || (cfun->stdarg == 1)
+ || (find_fallthru_edge (EXIT_BLOCK_PTR->preds) == NULL))
+ return 0;
+
+ /* Now we can check the possibility of using fp_as_gp optimization. */
+ if (TARGET_FORCE_FP_AS_GP)
+ {
+ /* User explicitly issues -mforce-fp-as-gp option. */
+ df_set_regs_ever_live (FP_REGNUM, 1);
+ return 1;
+ }
+ else
+ {
+ /* In the following we are going to evaluate whether
+ it is worth to do fp_as_gp optimization. */
+ int good_gain = 0;
+ int symbol_count = 0;
+
+ int threshold;
+ rtx insn;
+
+ /* We check if there already requires prologue.
+ Note that $gp will be saved in prologue for PIC code generation.
+ After that, we can set threshold by the existence of prologue.
+ Each fp-implied instruction will gain 2-byte code size
+ from gp-aware instruction, so we have following heuristics. */
+ if (flag_pic
+ || nds32_have_prologue_p ())
+ {
+ /* Have-prologue:
+ Compiler already intends to generate prologue content,
+ so the fp_as_gp optimization will only insert
+ 'la $fp,_FP_BASE_' instruction, which will be
+ converted into 4-byte instruction at link time.
+ The threshold is "3" symbol accesses, 2 + 2 + 2 > 4. */
+ threshold = 3;
+ }
+ else
+ {
+ /* None-prologue:
+ Compiler originally does not generate prologue content,
+ so the fp_as_gp optimization will NOT ONLY insert
+ 'la $fp,_FP_BASE' instruction, but also causes
+ push/pop instructions.
+ If we are using v3push (push25/pop25),
+ the threshold is "5" symbol accesses, 5*2 > 4 + 2 + 2;
+ If we are using normal push (smw/lmw),
+ the threshold is "5+2" symbol accesses 7*2 > 4 + 4 + 4. */
+ threshold = 5 + (TARGET_V3PUSH ? 0 : 2);
+ }
+
+ /* We would like to traverse every instruction in this function.
+ So we need to have push_topmost_sequence()/pop_topmost_sequence()
+ surrounding our for-loop evaluation. */
+ push_topmost_sequence ();
+ /* Counting the insn number which the addressing mode is symbol. */
+ for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+ {
+ if (single_set (insn) && nds32_symbol_load_store_p (insn))
+ symbol_count++;
+
+ if (symbol_count == threshold)
+ {
+ good_gain = 1;
+ break;
+ }
+ }
+ pop_topmost_sequence ();
+
+ /* Enable fp_as_gp optimization when potential gain is good enough. */
+ if (good_gain)
+ {
+ df_set_regs_ever_live (FP_REGNUM, 1);
+ return 1;
+ }
+ }
+
+ /* By default we return 0. */
+ return 0;
+}
+
+
+/* Function to generate PC relative jump table.
+ Refer to nds32.md for more details.
+
+ The following is the sample for the case that diff value
+ can be presented in '.short' size.
+
+ addi $r1, $r1, -(case_lower_bound)
+ slti $ta, $r1, (case_number)
+ beqz $ta, .L_skip_label
+
+ la $ta, .L35 ! get jump table address
+ lh $r1, [$ta + $r1 << 1] ! load symbol diff from jump table entry
+ addi $ta, $r1, $ta
+ jr5 $ta
+
+ ! jump table entry
+ L35:
+ .short .L25-.L35
+ .short .L26-.L35
+ .short .L27-.L35
+ .short .L28-.L35
+ .short .L29-.L35
+ .short .L30-.L35
+ .short .L31-.L35
+ .short .L32-.L35
+ .short .L33-.L35
+ .short .L34-.L35 */
+const char *
+nds32_output_casesi_pc_relative (rtx *operands)
+{
+ enum machine_mode mode;
+ rtx diff_vec;
+
+ diff_vec = PATTERN (next_active_insn (operands[1]));
+
+ gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
+
+ /* Step C: "t <-- operands[1]". */
+ output_asm_insn ("la\t$ta, %l1", operands);
+
+ /* Get the mode of each element in the difference vector. */
+ mode = GET_MODE (diff_vec);
+
+ /* Step D: "z <-- (mem (plus (operands[0] << m) t))",
+ where m is 0, 1, or 2 to load address-diff value from table. */
+ switch (mode)
+ {
+ case QImode:
+ output_asm_insn ("lb\t%2, [$ta + %0 << 0]", operands);
+ break;
+ case HImode:
+ output_asm_insn ("lh\t%2, [$ta + %0 << 1]", operands);
+ break;
+ case SImode:
+ output_asm_insn ("lw\t%2, [$ta + %0 << 2]", operands);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ /* Step E: "t <-- z + t".
+ Add table label_ref with address-diff value to
+ obtain target case address. */
+ output_asm_insn ("add\t$ta, %2, $ta", operands);
+
+ /* Step F: jump to target with register t. */
+ if (TARGET_16_BIT)
+ return "jr5\t$ta";
+ else
+ return "jr\t$ta";
+}
+
+/* Function to generate normal jump table. */
+const char *
+nds32_output_casesi (rtx *operands)
+{
+ /* Step C: "t <-- operands[1]". */
+ output_asm_insn ("la\t$ta, %l1", operands);
+
+ /* Step D: "z <-- (mem (plus (operands[0] << 2) t))". */
+ output_asm_insn ("lw\t%2, [$ta + %0 << 2]", operands);
+
+ /* No need to perform Step E, which is only used for
+ pc relative jump table. */
+
+ /* Step F: jump to target with register z. */
+ if (TARGET_16_BIT)
+ return "jr5\t%2";
+ else
+ return "jr\t%2";
+}
+
+
+/* Function to return memory format. */
+enum nds32_16bit_address_type
+nds32_mem_format (rtx op)
+{
+ enum machine_mode mode_test;
+ int val;
+ int regno;
+
+ if (!TARGET_16_BIT)
+ return ADDRESS_NOT_16BIT_FORMAT;
+
+ mode_test = GET_MODE (op);
+
+ op = XEXP (op, 0);
+
+ /* 45 format. */
+ if (GET_CODE (op) == REG && (mode_test == SImode))
+ return ADDRESS_REG;
+
+ /* 333 format for QI/HImode. */
+ if (GET_CODE (op) == REG && (REGNO (op) < R8_REGNUM))
+ return ADDRESS_LO_REG_IMM3U;
+
+ /* post_inc 333 format. */
+ if ((GET_CODE (op) == POST_INC) && (mode_test == SImode))
+ {
+ regno = REGNO(XEXP (op, 0));
+
+ if (regno < 8)
+ return ADDRESS_POST_INC_LO_REG_IMM3U;
+ }
+
+ /* post_inc 333 format. */
+ if ((GET_CODE (op) == POST_MODIFY)
+ && (mode_test == SImode)
+ && (REG_P (XEXP (XEXP (op, 1), 0)))
+ && (CONST_INT_P (XEXP (XEXP (op, 1), 1))))
+ {
+ regno = REGNO (XEXP (XEXP (op, 1), 0));
+ val = INTVAL (XEXP (XEXP (op, 1), 1));
+ if (regno < 8 && val < 32)
+ return ADDRESS_POST_INC_LO_REG_IMM3U;
+ }
+
+ if ((GET_CODE (op) == PLUS)
+ && (GET_CODE (XEXP (op, 0)) == REG)
+ && (GET_CODE (XEXP (op, 1)) == CONST_INT))
+ {
+ val = INTVAL (XEXP (op, 1));
+
+ regno = REGNO(XEXP (op, 0));
+
+ if (regno > 7
+ && regno != SP_REGNUM
+ && regno != FP_REGNUM)
+ return ADDRESS_NOT_16BIT_FORMAT;
+
+ switch (mode_test)
+ {
+ case QImode:
+ /* 333 format. */
+ if (val >= 0 && val < 8 && regno < 8)
+ return ADDRESS_LO_REG_IMM3U;
+ break;
+
+ case HImode:
+ /* 333 format. */
+ if (val >= 0 && val < 16 && (val % 2 == 0) && regno < 8)
+ return ADDRESS_LO_REG_IMM3U;
+ break;
+
+ case SImode:
+ case SFmode:
+ case DFmode:
+ /* fp imply 37 format. */
+ if ((regno == FP_REGNUM) &&
+ (val >= 0 && val < 512 && (val % 4 == 0)))
+ return ADDRESS_FP_IMM7U;
+ /* sp imply 37 format. */
+ else if ((regno == SP_REGNUM) &&
+ (val >= 0 && val < 512 && (val % 4 == 0)))
+ return ADDRESS_SP_IMM7U;
+ /* 333 format. */
+ else if (val >= 0 && val < 32 && (val % 4 == 0) && regno < 8)
+ return ADDRESS_LO_REG_IMM3U;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return ADDRESS_NOT_16BIT_FORMAT;
+}
+
+/* Output 16-bit store. */
+const char *
+nds32_output_16bit_store (rtx *operands, int byte)
+{
+ char pattern[100];
+ char size;
+ rtx code = XEXP (operands[0], 0);
+
+ size = nds32_byte_to_size (byte);
+
+ switch (nds32_mem_format (operands[0]))
+ {
+ case ADDRESS_REG:
+ operands[0] = code;
+ output_asm_insn ("swi450\t%1, [%0]", operands);
+ break;
+ case ADDRESS_LO_REG_IMM3U:
+ snprintf (pattern, sizeof (pattern), "s%ci333\t%%1, %%0", size);
+ output_asm_insn (pattern, operands);
+ break;
+ case ADDRESS_POST_INC_LO_REG_IMM3U:
+ snprintf (pattern, sizeof (pattern), "s%ci333.bi\t%%1, %%0", size);
+ output_asm_insn (pattern, operands);
+ break;
+ case ADDRESS_FP_IMM7U:
+ output_asm_insn ("swi37\t%1, %0", operands);
+ break;
+ case ADDRESS_SP_IMM7U:
+ /* Get immediate value and set back to operands[1]. */
+ operands[0] = XEXP (code, 1);
+ output_asm_insn ("swi37.sp\t%1, [ + (%0)]", operands);
+ break;
+ default:
+ break;
+ }
+
+ return "";
+}
+
+/* Output 16-bit load. */
+const char *
+nds32_output_16bit_load (rtx *operands, int byte)
+{
+ char pattern[100];
+ unsigned char size;
+ rtx code = XEXP (operands[1], 0);
+
+ size = nds32_byte_to_size (byte);
+
+ switch (nds32_mem_format (operands[1]))
+ {
+ case ADDRESS_REG:
+ operands[1] = code;
+ output_asm_insn ("lwi450\t%0, [%1]", operands);
+ break;
+ case ADDRESS_LO_REG_IMM3U:
+ snprintf (pattern, sizeof (pattern), "l%ci333\t%%0, %%1", size);
+ output_asm_insn (pattern, operands);
+ break;
+ case ADDRESS_POST_INC_LO_REG_IMM3U:
+ snprintf (pattern, sizeof (pattern), "l%ci333.bi\t%%0, %%1", size);
+ output_asm_insn (pattern, operands);
+ break;
+ case ADDRESS_FP_IMM7U:
+ output_asm_insn ("lwi37\t%0, %1", operands);
+ break;
+ case ADDRESS_SP_IMM7U:
+ /* Get immediate value and set back to operands[0]. */
+ operands[1] = XEXP (code, 1);
+ output_asm_insn ("lwi37.sp\t%0, [ + (%1)]", operands);
+ break;
+ default:
+ break;
+ }
+
+ return "";
+}
+
+/* Output 32-bit store. */
+const char *
+nds32_output_32bit_store (rtx *operands, int byte)
+{
+ char pattern[100];
+ unsigned char size;
+ rtx code = XEXP (operands[0], 0);
+
+ size = nds32_byte_to_size (byte);
+
+ switch (GET_CODE (code))
+ {
+ case REG:
+ /* (mem (reg X))
+ => access location by using register,
+ use "sbi / shi / swi" */
+ snprintf (pattern, sizeof (pattern), "s%ci\t%%1, %%0", size);
+ break;
+
+ case SYMBOL_REF:
+ case CONST:
+ /* (mem (symbol_ref X))
+ (mem (const (...)))
+ => access global variables,
+ use "sbi.gp / shi.gp / swi.gp" */
+ operands[0] = XEXP (operands[0], 0);
+ snprintf (pattern, sizeof (pattern), "s%ci.gp\t%%1, [ + %%0]", size);
+ break;
+
+ case POST_INC:
+ /* (mem (post_inc reg))
+ => access location by using register which will be post increment,
+ use "sbi.bi / shi.bi / swi.bi" */
+ snprintf (pattern, sizeof (pattern),
+ "s%ci.bi\t%%1, %%0, %d", size, byte);
+ break;
+
+ case POST_DEC:
+ /* (mem (post_dec reg))
+ => access location by using register which will be post decrement,
+ use "sbi.bi / shi.bi / swi.bi" */
+ snprintf (pattern, sizeof (pattern),
+ "s%ci.bi\t%%1, %%0, -%d", size, byte);
+ break;
+
+ case POST_MODIFY:
+ switch (GET_CODE (XEXP (XEXP (code, 1), 1)))
+ {
+ case REG:
+ case SUBREG:
+ /* (mem (post_modify (reg) (plus (reg) (reg))))
+ => access location by using register which will be
+ post modified with reg,
+ use "sb.bi/ sh.bi / sw.bi" */
+ snprintf (pattern, sizeof (pattern), "s%c.bi\t%%1, %%0", size);
+ break;
+ case CONST_INT:
+ /* (mem (post_modify (reg) (plus (reg) (const_int))))
+ => access location by using register which will be
+ post modified with const_int,
+ use "sbi.bi/ shi.bi / swi.bi" */
+ snprintf (pattern, sizeof (pattern), "s%ci.bi\t%%1, %%0", size);
+ break;
+ default:
+ abort ();
+ }
+ break;
+
+ case PLUS:
+ switch (GET_CODE (XEXP (code, 1)))
+ {
+ case REG:
+ case SUBREG:
+ /* (mem (plus reg reg)) or (mem (plus (mult reg const_int) reg))
+ => access location by adding two registers,
+ use "sb / sh / sw" */
+ snprintf (pattern, sizeof (pattern), "s%c\t%%1, %%0", size);
+ break;
+ case CONST_INT:
+ /* (mem (plus reg const_int))
+ => access location by adding one register with const_int,
+ use "sbi / shi / swi" */
+ snprintf (pattern, sizeof (pattern), "s%ci\t%%1, %%0", size);
+ break;
+ default:
+ abort ();
+ }
+ break;
+
+ case LO_SUM:
+ operands[2] = XEXP (code, 1);
+ operands[0] = XEXP (code, 0);
+ snprintf (pattern, sizeof (pattern),
+ "s%ci\t%%1, [%%0 + lo12(%%2)]", size);
+ break;
+
+ default:
+ abort ();
+ }
+
+ output_asm_insn (pattern, operands);
+ return "";
+}
+
+/* Output 32-bit load. */
+const char *
+nds32_output_32bit_load (rtx *operands, int byte)
+{
+ char pattern[100];
+ unsigned char size;
+ rtx code;
+
+ code = XEXP (operands[1], 0);
+
+ size = nds32_byte_to_size (byte);
+
+ switch (GET_CODE (code))
+ {
+ case REG:
+ /* (mem (reg X))
+ => access location by using register,
+ use "lbi / lhi / lwi" */
+ snprintf (pattern, sizeof (pattern), "l%ci\t%%0, %%1", size);
+ break;
+
+ case SYMBOL_REF:
+ case CONST:
+ /* (mem (symbol_ref X))
+ (mem (const (...)))
+ => access global variables,
+ use "lbi.gp / lhi.gp / lwi.gp" */
+ operands[1] = XEXP (operands[1], 0);
+ snprintf (pattern, sizeof (pattern), "l%ci.gp\t%%0, [ + %%1]", size);
+ break;
+
+ case POST_INC:
+ /* (mem (post_inc reg))
+ => access location by using register which will be post increment,
+ use "lbi.bi / lhi.bi / lwi.bi" */
+ snprintf (pattern, sizeof (pattern),
+ "l%ci.bi\t%%0, %%1, %d", size, byte);
+ break;
+
+ case POST_DEC:
+ /* (mem (post_dec reg))
+ => access location by using register which will be post decrement,
+ use "lbi.bi / lhi.bi / lwi.bi" */
+ snprintf (pattern, sizeof (pattern),
+ "l%ci.bi\t%%0, %%1, -%d", size, byte);
+ break;
+
+ case POST_MODIFY:
+ switch (GET_CODE (XEXP (XEXP (code, 1), 1)))
+ {
+ case REG:
+ case SUBREG:
+ /* (mem (post_modify (reg) (plus (reg) (reg))))
+ => access location by using register which will be
+ post modified with reg,
+ use "lb.bi/ lh.bi / lw.bi" */
+ snprintf (pattern, sizeof (pattern), "l%c.bi\t%%0, %%1", size);
+ break;
+ case CONST_INT:
+ /* (mem (post_modify (reg) (plus (reg) (const_int))))
+ => access location by using register which will be
+ post modified with const_int,
+ use "lbi.bi/ lhi.bi / lwi.bi" */
+ snprintf (pattern, sizeof (pattern), "l%ci.bi\t%%0, %%1", size);
+ break;
+ default:
+ abort ();
+ }
+ break;
+
+ case PLUS:
+ switch (GET_CODE (XEXP (code, 1)))
+ {
+ case REG:
+ case SUBREG:
+ /* (mem (plus reg reg)) or (mem (plus (mult reg const_int) reg))
+ use "lb / lh / lw" */
+ snprintf (pattern, sizeof (pattern), "l%c\t%%0, %%1", size);
+ break;
+ case CONST_INT:
+ /* (mem (plus reg const_int))
+ => access location by adding one register with const_int,
+ use "lbi / lhi / lwi" */
+ snprintf (pattern, sizeof (pattern), "l%ci\t%%0, %%1", size);
+ break;
+ default:
+ abort ();
+ }
+ break;
+
+ case LO_SUM:
+ operands[2] = XEXP (code, 1);
+ operands[1] = XEXP (code, 0);
+ snprintf (pattern, sizeof (pattern),
+ "l%ci\t%%0, [%%1 + lo12(%%2)]", size);
+ break;
+
+ default:
+ abort ();
+ }
+
+ output_asm_insn (pattern, operands);
+ return "";
+}
+
+/* Output 32-bit load with signed extension. */
+const char *
+nds32_output_32bit_load_s (rtx *operands, int byte)
+{
+ char pattern[100];
+ unsigned char size;
+ rtx code;
+
+ code = XEXP (operands[1], 0);
+
+ size = nds32_byte_to_size (byte);
+
+ switch (GET_CODE (code))
+ {
+ case REG:
+ /* (mem (reg X))
+ => access location by using register,
+ use "lbsi / lhsi" */
+ snprintf (pattern, sizeof (pattern), "l%csi\t%%0, %%1", size);
+ break;
+
+ case SYMBOL_REF:
+ case CONST:
+ /* (mem (symbol_ref X))
+ (mem (const (...)))
+ => access global variables,
+ use "lbsi.gp / lhsi.gp" */
+ operands[1] = XEXP (operands[1], 0);
+ snprintf (pattern, sizeof (pattern), "l%csi.gp\t%%0, [ + %%1]", size);
+ break;
+
+ case POST_INC:
+ /* (mem (post_inc reg))
+ => access location by using register which will be post increment,
+ use "lbsi.bi / lhsi.bi" */
+ snprintf (pattern, sizeof (pattern),
+ "l%csi.bi\t%%0, %%1, %d", size, byte);
+ break;
+
+ case POST_DEC:
+ /* (mem (post_dec reg))
+ => access location by using register which will be post decrement,
+ use "lbsi.bi / lhsi.bi" */
+ snprintf (pattern, sizeof (pattern),
+ "l%csi.bi\t%%0, %%1, -%d", size, byte);
+ break;
+
+ case POST_MODIFY:
+ switch (GET_CODE (XEXP (XEXP (code, 1), 1)))
+ {
+ case REG:
+ case SUBREG:
+ /* (mem (post_modify (reg) (plus (reg) (reg))))
+ => access location by using register which will be
+ post modified with reg,
+ use "lbs.bi/ lhs.bi" */
+ snprintf (pattern, sizeof (pattern), "l%cs.bi\t%%0, %%1", size);
+ break;
+ case CONST_INT:
+ /* (mem (post_modify (reg) (plus (reg) (const_int))))
+ => access location by using register which will be
+ post modified with const_int,
+ use "lbsi.bi/ lhsi.bi" */
+ snprintf (pattern, sizeof (pattern), "l%csi.bi\t%%0, %%1", size);
+ break;
+ default:
+ abort ();
+ }
+ break;
+
+ case PLUS:
+ switch (GET_CODE (XEXP (code, 1)))
+ {
+ case REG:
+ case SUBREG:
+ /* (mem (plus reg reg)) or (mem (plus (mult reg const_int) reg))
+ use "lbs / lhs" */
+ snprintf (pattern, sizeof (pattern), "l%cs\t%%0, %%1", size);
+ break;
+ case CONST_INT:
+ /* (mem (plus reg const_int))
+ => access location by adding one register with const_int,
+ use "lbsi / lhsi" */
+ snprintf (pattern, sizeof (pattern), "l%csi\t%%0, %%1", size);
+ break;
+ default:
+ abort ();
+ }
+ break;
+
+ case LO_SUM:
+ operands[2] = XEXP (code, 1);
+ operands[1] = XEXP (code, 0);
+ snprintf (pattern, sizeof (pattern),
+ "l%csi\t%%0, [%%1 + lo12(%%2)]", size);
+ break;
+
+ default:
+ abort ();
+ }
+
+ output_asm_insn (pattern, operands);
+ return "";
+}
+
+/* Function to output stack push operation.
+ We need to deal with normal stack push multiple or stack v3push. */
+const char *
+nds32_output_stack_push (void)
+{
+ /* A string pattern for output_asm_insn(). */
+ char pattern[100];
+ /* The operands array which will be used in output_asm_insn(). */
+ rtx operands[3];
+ /* Pick up callee-saved first regno and last regno for further use. */
+ int rb_regno = cfun->machine->callee_saved_regs_first_regno;
+ int re_regno = cfun->machine->callee_saved_regs_last_regno;
+
+ if (TARGET_V3PUSH)
+ {
+ /* For stack v3push:
+ operands[0]: Re
+ operands[1]: imm8u */
+
+ /* This variable is to check if 'push25 Re,imm8u' is available. */
+ int sp_adjust;
+
+ /* Set operands[0]. */
+ operands[0] = gen_rtx_REG (SImode, re_regno);
+
+ /* Check if we can generate 'push25 Re,imm8u',
+ otherwise, generate 'push25 Re,0'. */
+ sp_adjust = cfun->machine->local_size
+ + cfun->machine->out_args_size
+ + cfun->machine->callee_saved_area_padding_bytes;
+ if (satisfies_constraint_Iu08 (GEN_INT (sp_adjust))
+ && NDS32_DOUBLE_WORD_ALIGN_P (sp_adjust))
+ operands[1] = GEN_INT (sp_adjust);
+ else
+ operands[1] = GEN_INT (0);
+
+ /* Create assembly code pattern. */
+ snprintf (pattern, sizeof (pattern), "push25\t%%0, %%1");
+ }
+ else
+ {
+ /* For normal stack push multiple:
+ operands[0]: Rb
+ operands[1]: Re
+ operands[2]: En4 */
+
+ /* This variable is used to check if we only need to generate En4 field.
+ As long as Rb==Re=SP_REGNUM, we set this variable to 1. */
+ int push_en4_only_p = 0;
+
+ /* Set operands[0] and operands[1]. */
+ operands[0] = gen_rtx_REG (SImode, rb_regno);
+ operands[1] = gen_rtx_REG (SImode, re_regno);
+
+ /* 'smw.adm $sp,[$sp],$sp,0' means push nothing. */
+ if (!cfun->machine->fp_size
+ && !cfun->machine->gp_size
+ && !cfun->machine->lp_size
+ && REGNO (operands[0]) == SP_REGNUM
+ && REGNO (operands[1]) == SP_REGNUM)
+ {
+ /* No need to generate instruction. */
+ return "";
+ }
+ else
+ {
+ /* If Rb==Re=SP_REGNUM, we only need to generate En4 field. */
+ if (REGNO (operands[0]) == SP_REGNUM
+ && REGNO (operands[1]) == SP_REGNUM)
+ push_en4_only_p = 1;
+
+ /* Create assembly code pattern.
+ We need to handle the form: "Rb, Re, { $fp $gp $lp }". */
+ snprintf (pattern, sizeof (pattern),
+ "push.s\t%s{%s%s%s }",
+ push_en4_only_p ? "" : "%0, %1, ",
+ cfun->machine->fp_size ? " $fp" : "",
+ cfun->machine->gp_size ? " $gp" : "",
+ cfun->machine->lp_size ? " $lp" : "");
+ }
+ }
+
+ /* We use output_asm_insn() to output assembly code by ourself. */
+ output_asm_insn (pattern, operands);
+ return "";
+}
+
+/* Function to output stack pop operation.
+ We need to deal with normal stack pop multiple or stack v3pop. */
+const char *
+nds32_output_stack_pop (void)
+{
+ /* A string pattern for output_asm_insn(). */
+ char pattern[100];
+ /* The operands array which will be used in output_asm_insn(). */
+ rtx operands[3];
+ /* Pick up callee-saved first regno and last regno for further use. */
+ int rb_regno = cfun->machine->callee_saved_regs_first_regno;
+ int re_regno = cfun->machine->callee_saved_regs_last_regno;
+
+ if (TARGET_V3PUSH)
+ {
+ /* For stack v3pop:
+ operands[0]: Re
+ operands[1]: imm8u */
+
+ /* This variable is to check if 'pop25 Re,imm8u' is available. */
+ int sp_adjust;
+
+ /* Set operands[0]. */
+ operands[0] = gen_rtx_REG (SImode, re_regno);
+
+ /* Check if we can generate 'pop25 Re,imm8u',
+ otherwise, generate 'pop25 Re,0'.
+ We have to consider alloca issue as well.
+ If the function does call alloca(), the stack pointer is not fixed.
+ In that case, we cannot use 'pop25 Re,imm8u' directly.
+ We have to caculate stack pointer from frame pointer
+ and then use 'pop25 Re,0'. */
+ sp_adjust = cfun->machine->local_size
+ + cfun->machine->out_args_size
+ + cfun->machine->callee_saved_area_padding_bytes;
+ if (satisfies_constraint_Iu08 (GEN_INT (sp_adjust))
+ && NDS32_DOUBLE_WORD_ALIGN_P (sp_adjust)
+ && !cfun->calls_alloca)
+ operands[1] = GEN_INT (sp_adjust);
+ else
+ operands[1] = GEN_INT (0);
+
+ /* Create assembly code pattern. */
+ snprintf (pattern, sizeof (pattern), "pop25\t%%0, %%1");
+ }
+ else
+ {
+ /* For normal stack pop multiple:
+ operands[0]: Rb
+ operands[1]: Re
+ operands[2]: En4 */
+
+ /* This variable is used to check if we only need to generate En4 field.
+ As long as Rb==Re=SP_REGNUM, we set this variable to 1. */
+ int pop_en4_only_p = 0;
+
+ /* Set operands[0] and operands[1]. */
+ operands[0] = gen_rtx_REG (SImode, rb_regno);
+ operands[1] = gen_rtx_REG (SImode, re_regno);
+
+ /* 'lmw.bim $sp,[$sp],$sp,0' means pop nothing. */
+ if (!cfun->machine->fp_size
+ && !cfun->machine->gp_size
+ && !cfun->machine->lp_size
+ && REGNO (operands[0]) == SP_REGNUM
+ && REGNO (operands[1]) == SP_REGNUM)
+ {
+ /* No need to generate instruction. */
+ return "";
+ }
+ else
+ {
+ /* If Rb==Re=SP_REGNUM, we only need to generate En4 field. */
+ if (REGNO (operands[0]) == SP_REGNUM
+ && REGNO (operands[1]) == SP_REGNUM)
+ pop_en4_only_p = 1;
+
+ /* Create assembly code pattern.
+ We need to handle the form: "Rb, Re, { $fp $gp $lp }". */
+ snprintf (pattern, sizeof (pattern),
+ "pop.s\t%s{%s%s%s }",
+ pop_en4_only_p ? "" : "%0, %1, ",
+ cfun->machine->fp_size ? " $fp" : "",
+ cfun->machine->gp_size ? " $gp" : "",
+ cfun->machine->lp_size ? " $lp" : "");
+ }
+ }
+
+ /* We use output_asm_insn() to output assembly code by ourself. */
+ output_asm_insn (pattern, operands);
+ return "";
+}
+
+/* Return align 2 (log base 2) if the next instruction of LABEL is 4 byte. */
+int
+nds32_target_alignment (rtx label)
+{
+ rtx insn;
+
+ if (optimize_size)
+ return 0;
+
+ insn = next_active_insn (label);
+
+ if (insn == 0)
+ return 0;
+ else if ((get_attr_length (insn) % 4) == 0)
+ return 2;
+ else
+ return 0;
+}
+
+/* ------------------------------------------------------------------------ */
+
+/* PART 5: Initialize target hook structure and definitions. */
+
+/* Controlling the Compilation Driver. */
+
+
+/* Run-time Target Specification. */
+
+
+/* Defining Data Structures for Per-function Information. */
+
+
+/* Storage Layout. */
+
+#undef TARGET_PROMOTE_FUNCTION_MODE
+#define TARGET_PROMOTE_FUNCTION_MODE \
+ default_promote_function_mode_always_promote
+
+
+/* Layout of Source Language Data Types. */
+
+
+/* Register Usage. */
+
+/* -- Basic Characteristics of Registers. */
+
+/* -- Order of Allocation of Registers. */
+
+/* -- How Values Fit in Registers. */
+
+/* -- Handling Leaf Functions. */
+
+/* -- Registers That Form a Stack. */
+
+
+/* Register Classes. */
+
+#undef TARGET_CLASS_MAX_NREGS
+#define TARGET_CLASS_MAX_NREGS nds32_class_max_nregs
+
+#undef TARGET_LRA_P
+#define TARGET_LRA_P hook_bool_void_true
+
+#undef TARGET_REGISTER_PRIORITY
+#define TARGET_REGISTER_PRIORITY nds32_register_priority
+
+
+/* Obsolete Macros for Defining Constraints. */
+
+
+/* Stack Layout and Calling Conventions. */
+
+/* -- Basic Stack Layout. */
+
+/* -- Exception Handling Support. */
+
+/* -- Specifying How Stack Checking is Done. */
+
+/* -- Registers That Address the Stack Frame. */
+
+/* -- Eliminating Frame Pointer and Arg Pointer. */
+
+#undef TARGET_CAN_ELIMINATE
+#define TARGET_CAN_ELIMINATE nds32_can_eliminate
+
+/* -- Passing Function Arguments on the Stack. */
+
+/* -- Passing Arguments in Registers. */
+
+#undef TARGET_FUNCTION_ARG
+#define TARGET_FUNCTION_ARG nds32_function_arg
+
+#undef TARGET_FUNCTION_ARG_ADVANCE
+#define TARGET_FUNCTION_ARG_ADVANCE nds32_function_arg_advance
+
+#undef TARGET_FUNCTION_ARG_BOUNDARY
+#define TARGET_FUNCTION_ARG_BOUNDARY nds32_function_arg_boundary
+
+/* -- How Scalar Function Values Are Returned. */
+
+#undef TARGET_FUNCTION_VALUE
+#define TARGET_FUNCTION_VALUE nds32_function_value
+
+#undef TARGET_LIBCALL_VALUE
+#define TARGET_LIBCALL_VALUE nds32_libcall_value
+
+#undef TARGET_FUNCTION_VALUE_REGNO_P
+#define TARGET_FUNCTION_VALUE_REGNO_P nds32_function_value_regno_p
+
+/* -- How Large Values Are Returned. */
+
+/* -- Caller-Saves Register Allocation. */
+
+/* -- Function Entry and Exit. */
+
+#undef TARGET_ASM_FUNCTION_PROLOGUE
+#define TARGET_ASM_FUNCTION_PROLOGUE nds32_asm_function_prologue
+
+#undef TARGET_ASM_FUNCTION_END_PROLOGUE
+#define TARGET_ASM_FUNCTION_END_PROLOGUE nds32_asm_function_end_prologue
+
+#undef TARGET_ASM_FUNCTION_BEGIN_EPILOGUE
+#define TARGET_ASM_FUNCTION_BEGIN_EPILOGUE nds32_asm_function_begin_epilogue
+
+#undef TARGET_ASM_FUNCTION_EPILOGUE
+#define TARGET_ASM_FUNCTION_EPILOGUE nds32_asm_function_epilogue
+
+#undef TARGET_ASM_OUTPUT_MI_THUNK
+#define TARGET_ASM_OUTPUT_MI_THUNK nds32_asm_output_mi_thunk
+
+#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
+#define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall
+
+/* -- Generating Code for Profiling. */
+
+/* -- Permitting tail calls. */
+
+#undef TARGET_WARN_FUNC_RETURN
+#define TARGET_WARN_FUNC_RETURN nds32_warn_func_return
+
+/* Stack smashing protection. */
+
+
+/* Implementing the Varargs Macros. */
+
+#undef TARGET_STRICT_ARGUMENT_NAMING
+#define TARGET_STRICT_ARGUMENT_NAMING nds32_strict_argument_naming
+
+
+/* Trampolines for Nested Functions. */
+
+#undef TARGET_ASM_TRAMPOLINE_TEMPLATE
+#define TARGET_ASM_TRAMPOLINE_TEMPLATE nds32_asm_trampoline_template
+
+#undef TARGET_TRAMPOLINE_INIT
+#define TARGET_TRAMPOLINE_INIT nds32_trampoline_init
+
+
+/* Implicit Calls to Library Routines. */
+
+
+/* Addressing Modes. */
+
+#undef TARGET_LEGITIMATE_ADDRESS_P
+#define TARGET_LEGITIMATE_ADDRESS_P nds32_legitimate_address_p
+
+
+/* Anchored Addresses. */
+
+
+/* Condition Code Status. */
+
+/* -- Representation of condition codes using (cc0). */
+
+/* -- Representation of condition codes using registers. */
+
+/* -- Macros to control conditional execution. */
+
+
+/* Describing Relative Costs of Operations. */
+
+#undef TARGET_REGISTER_MOVE_COST
+#define TARGET_REGISTER_MOVE_COST nds32_register_move_cost
+
+#undef TARGET_MEMORY_MOVE_COST
+#define TARGET_MEMORY_MOVE_COST nds32_memory_move_cost
+
+#undef TARGET_RTX_COSTS
+#define TARGET_RTX_COSTS nds32_rtx_costs
+
+#undef TARGET_ADDRESS_COST
+#define TARGET_ADDRESS_COST nds32_address_cost
+
+
+/* Adjusting the Instruction Scheduler. */
+
+
+/* Dividing the Output into Sections (Texts, Data, . . . ). */
+
+
+/* Position Independent Code. */
+
+
+/* Defining the Output Assembler Language. */
+
+/* -- The Overall Framework of an Assembler File. */
+
+#undef TARGET_ASM_FILE_START
+#define TARGET_ASM_FILE_START nds32_asm_file_start
+#undef TARGET_ASM_FILE_END
+#define TARGET_ASM_FILE_END nds32_asm_file_end
+
+/* -- Output of Data. */
+
+#undef TARGET_ASM_ALIGNED_HI_OP
+#define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
+
+#undef TARGET_ASM_ALIGNED_SI_OP
+#define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
+
+/* -- Output of Uninitialized Variables. */
+
+/* -- Output and Generation of Labels. */
+
+#undef TARGET_ASM_GLOBALIZE_LABEL
+#define TARGET_ASM_GLOBALIZE_LABEL nds32_asm_globalize_label
+
+/* -- How Initialization Functions Are Handled. */
+
+/* -- Macros Controlling Initialization Routines. */
+
+/* -- Output of Assembler Instructions. */
+
+#undef TARGET_PRINT_OPERAND
+#define TARGET_PRINT_OPERAND nds32_print_operand
+#undef TARGET_PRINT_OPERAND_ADDRESS
+#define TARGET_PRINT_OPERAND_ADDRESS nds32_print_operand_address
+
+/* -- Output of Dispatch Tables. */
+
+/* -- Assembler Commands for Exception Regions. */
+
+/* -- Assembler Commands for Alignment. */
+
+
+/* Controlling Debugging Information Format. */
+
+/* -- Macros Affecting All Debugging Formats. */
+
+/* -- Specific Options for DBX Output. */
+
+/* -- Open-Ended Hooks for DBX Format. */
+
+/* -- File Names in DBX Format. */
+
+/* -- Macros for SDB and DWARF Output. */
+
+/* -- Macros for VMS Debug Format. */
+
+
+/* Cross Compilation and Floating Point. */
+
+
+/* Mode Switching Instructions. */
+
+
+/* Defining target-specific uses of __attribute__. */
+
+#undef TARGET_ATTRIBUTE_TABLE
+#define TARGET_ATTRIBUTE_TABLE nds32_attribute_table
+
+#undef TARGET_MERGE_DECL_ATTRIBUTES
+#define TARGET_MERGE_DECL_ATTRIBUTES nds32_merge_decl_attributes
+
+#undef TARGET_INSERT_ATTRIBUTES
+#define TARGET_INSERT_ATTRIBUTES nds32_insert_attributes
+
+#undef TARGET_OPTION_PRAGMA_PARSE
+#define TARGET_OPTION_PRAGMA_PARSE nds32_option_pragma_parse
+
+#undef TARGET_OPTION_OVERRIDE
+#define TARGET_OPTION_OVERRIDE nds32_option_override
+
+
+/* Emulating TLS. */
+
+
+/* Defining coprocessor specifics for MIPS targets. */
+
+
+/* Parameters for Precompiled Header Validity Checking. */
+
+
+/* C++ ABI parameters. */
+
+
+/* Adding support for named address spaces. */
+
+
+/* Miscellaneous Parameters. */
+
+#undef TARGET_INIT_BUILTINS
+#define TARGET_INIT_BUILTINS nds32_init_builtins
+
+#undef TARGET_EXPAND_BUILTIN
+#define TARGET_EXPAND_BUILTIN nds32_expand_builtin
+
+
+/* ------------------------------------------------------------------------ */
+
+/* Initialize the GCC target structure. */
+
+struct gcc_target targetm = TARGET_INITIALIZER;
+
+/* ------------------------------------------------------------------------ */
diff --git a/gcc/config/nds32/nds32.h b/gcc/config/nds32/nds32.h
new file mode 100644
index 00000000000..74f126cecc4
--- /dev/null
+++ b/gcc/config/nds32/nds32.h
@@ -0,0 +1,982 @@
+/* Definitions of target machine of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ You should have 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 following are auxiliary macros or structure declarations
+ that are used all over the nds32.c and nds32.h. */
+
+
+/* Computing the Length of an Insn. */
+#define ADJUST_INSN_LENGTH(INSN, LENGTH) \
+ (LENGTH = nds32_adjust_insn_length (INSN, LENGTH))
+
+/* Check instruction LS-37-FP-implied form.
+ Note: actually its immediate range is imm9u
+ since it is used for lwi37/swi37 instructions. */
+#define NDS32_LS_37_FP_P(rt, ra, imm) \
+ (REGNO_REG_CLASS (REGNO (rt)) == LOW_REGS \
+ && REGNO (ra) == FP_REGNUM \
+ && satisfies_constraint_Iu09 (imm))
+
+/* Check instruction LS-37-SP-implied form.
+ Note: actually its immediate range is imm9u
+ since it is used for lwi37/swi37 instructions. */
+#define NDS32_LS_37_SP_P(rt, ra, imm) \
+ (REGNO_REG_CLASS (REGNO (rt)) == LOW_REGS \
+ && REGNO (ra) == SP_REGNUM \
+ && satisfies_constraint_Iu09 (imm))
+
+
+/* Check load/store instruction form : Rt3, Ra3, imm3u. */
+#define NDS32_LS_333_P(rt, ra, imm, mode) nds32_ls_333_p (rt, ra, imm, mode)
+
+/* Check load/store instruction form : Rt4, Ra5, const_int_0.
+ Note: no need to check ra because Ra5 means it covers all registers. */
+#define NDS32_LS_450_P(rt, ra, imm) \
+ ((imm == const0_rtx) \
+ && (REGNO_REG_CLASS (REGNO (rt)) == LOW_REGS \
+ || REGNO_REG_CLASS (REGNO (rt)) == MIDDLE_REGS))
+
+/* Check instruction RRI-333-form. */
+#define NDS32_RRI_333_P(rt, ra, imm) \
+ (REGNO_REG_CLASS (REGNO (rt)) == LOW_REGS \
+ && REGNO_REG_CLASS (REGNO (ra)) == LOW_REGS \
+ && satisfies_constraint_Iu03 (imm))
+
+/* Check instruction RI-45-form. */
+#define NDS32_RI_45_P(rt, ra, imm) \
+ (REGNO (rt) == REGNO (ra) \
+ && (REGNO_REG_CLASS (REGNO (rt)) == LOW_REGS \
+ || REGNO_REG_CLASS (REGNO (rt)) == MIDDLE_REGS) \
+ && satisfies_constraint_Iu05 (imm))
+
+
+/* Check instruction RR-33-form. */
+#define NDS32_RR_33_P(rt, ra) \
+ (REGNO_REG_CLASS (REGNO (rt)) == LOW_REGS \
+ && REGNO_REG_CLASS (REGNO (ra)) == LOW_REGS)
+
+/* Check instruction RRR-333-form. */
+#define NDS32_RRR_333_P(rt, ra, rb) \
+ (REGNO_REG_CLASS (REGNO (rt)) == LOW_REGS \
+ && REGNO_REG_CLASS (REGNO (ra)) == LOW_REGS \
+ && REGNO_REG_CLASS (REGNO (rb)) == LOW_REGS)
+
+/* Check instruction RR-45-form.
+ Note: no need to check rb because Rb5 means it covers all registers. */
+#define NDS32_RR_45_P(rt, ra, rb) \
+ (REGNO (rt) == REGNO (ra) \
+ && (REGNO_REG_CLASS (REGNO (rt)) == LOW_REGS \
+ || REGNO_REG_CLASS (REGNO (rt)) == MIDDLE_REGS))
+
+/* Classifies address type to distinguish 16-bit/32-bit format. */
+enum nds32_16bit_address_type
+{
+ /* [reg]: 45 format address. */
+ ADDRESS_REG,
+ /* [lo_reg + imm3u]: 333 format address. */
+ ADDRESS_LO_REG_IMM3U,
+ /* post_inc [lo_reg + imm3u]: 333 format address. */
+ ADDRESS_POST_INC_LO_REG_IMM3U,
+ /* [$fp + imm7u]: fp imply address. */
+ ADDRESS_FP_IMM7U,
+ /* [$sp + imm7u]: sp imply address. */
+ ADDRESS_SP_IMM7U,
+ /* Other address format. */
+ ADDRESS_NOT_16BIT_FORMAT
+};
+
+
+/* ------------------------------------------------------------------------ */
+
+/* Define maximum numbers of registers for passing arguments. */
+#define NDS32_MAX_REGS_FOR_ARGS 6
+
+/* Define the register number for first argument. */
+#define NDS32_GPR_ARG_FIRST_REGNUM 0
+
+/* Define the register number for return value. */
+#define NDS32_GPR_RET_FIRST_REGNUM 0
+
+
+/* Define double word alignment bits. */
+#define NDS32_DOUBLE_WORD_ALIGNMENT 64
+
+/* Define alignment checking macros for convenience. */
+#define NDS32_HALF_WORD_ALIGN_P(value) (((value) & 0x01) == 0)
+#define NDS32_SINGLE_WORD_ALIGN_P(value) (((value) & 0x03) == 0)
+#define NDS32_DOUBLE_WORD_ALIGN_P(value) (((value) & 0x07) == 0)
+
+/* Round X up to the nearest double word. */
+#define NDS32_ROUND_UP_DOUBLE_WORD(value) (((value) + 7) & ~7)
+
+
+/* This macro is used to calculate the numbers of registers for
+ containing 'size' bytes of the argument.
+ The size of a register is a word in nds32 target.
+ So we use UNITS_PER_WORD to do the calculation. */
+#define NDS32_NEED_N_REGS_FOR_ARG(mode, type) \
+ ((mode == BLKmode) \
+ ? ((int_size_in_bytes (type) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) \
+ : ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
+
+/* This macro is used to return the register number for passing argument.
+ We need to obey the following rules:
+ 1. If it is required MORE THAN one register,
+ make sure the register number is a even value.
+ 2. If it is required ONLY one register,
+ the register number can be odd or even value. */
+#define NDS32_AVAILABLE_REGNUM_FOR_ARG(reg_offset, mode, type) \
+ ((NDS32_NEED_N_REGS_FOR_ARG (mode, type) > 1) \
+ ? (((reg_offset) + NDS32_GPR_ARG_FIRST_REGNUM + 1) & ~1) \
+ : ((reg_offset) + NDS32_GPR_ARG_FIRST_REGNUM))
+
+/* This macro is to check if there are still available registers
+ for passing argument. */
+#define NDS32_ARG_PASS_IN_REG_P(reg_offset, mode, type) \
+ (((reg_offset) < NDS32_MAX_REGS_FOR_ARGS) \
+ && ((reg_offset) + NDS32_NEED_N_REGS_FOR_ARG (mode, type) \
+ <= NDS32_MAX_REGS_FOR_ARGS))
+
+/* This macro is to check if the register is required to be saved on stack.
+ If call_used_regs[regno] == 0, regno is the callee-saved register.
+ If df_regs_ever_live_p(regno) == true, it is used in the current function.
+ As long as the register satisfies both criteria above,
+ it is required to be saved. */
+#define NDS32_REQUIRED_CALLEE_SAVED_P(regno) \
+ ((!call_used_regs[regno]) && (df_regs_ever_live_p (regno)))
+
+/* ------------------------------------------------------------------------ */
+
+/* A C structure for machine-specific, per-function data.
+ This is added to the cfun structure. */
+struct GTY(()) machine_function
+{
+ /* Number of bytes allocated on the stack for variadic args
+ if we want to push them into stack as pretend arguments by ourself. */
+ int va_args_size;
+ /* Number of bytes reserved on the stack for
+ local and temporary variables. */
+ int local_size;
+ /* Number of bytes allocated on the stack for outgoing arguments. */
+ int out_args_size;
+
+ /* Number of bytes on the stack for saving $fp. */
+ int fp_size;
+ /* Number of bytes on the stack for saving $gp. */
+ int gp_size;
+ /* Number of bytes on the stack for saving $lp. */
+ int lp_size;
+
+ /* Number of bytes on the stack for saving callee-saved registers. */
+ int callee_saved_regs_size;
+ /* The padding bytes in callee-saved area may be required. */
+ int callee_saved_area_padding_bytes;
+
+ /* The first required register that should be saved on stack
+ for va_args (one named argument + nameless arguments). */
+ int va_args_first_regno;
+ /* The last required register that should be saved on stack
+ for va_args (one named argument + nameless arguments). */
+ int va_args_last_regno;
+
+ /* The first required callee-saved register. */
+ int callee_saved_regs_first_regno;
+ /* The last required callee-saved register. */
+ int callee_saved_regs_last_regno;
+
+ /* Indicate that whether this function needs
+ prologue/epilogue code generation. */
+ int naked_p;
+ /* Indicate that whether this function
+ uses fp_as_gp optimization. */
+ int fp_as_gp_p;
+};
+
+/* A C structure that contains the arguments information. */
+typedef struct
+{
+ unsigned int reg_offset;
+} nds32_cumulative_args;
+
+/* ------------------------------------------------------------------------ */
+
+/* The following we define C-ISR related stuff.
+ In nds32 architecture, we have 73 vectors for interrupt/exception.
+ For each vector (except for vector 0, which is used for reset behavior),
+ we allow users to set its register saving scheme and interrupt level. */
+
+/* There are 73 vectors in nds32 architecture.
+ 0 for reset handler,
+ 1-8 for exception handler,
+ and 9-72 for interrupt handler.
+ We use an array, which is defined in nds32.c, to record
+ essential information for each vector. */
+#define NDS32_N_ISR_VECTORS 73
+
+/* Define possible isr category. */
+enum nds32_isr_category
+{
+ NDS32_ISR_NONE,
+ NDS32_ISR_INTERRUPT,
+ NDS32_ISR_EXCEPTION,
+ NDS32_ISR_RESET
+};
+
+/* Define isr register saving scheme. */
+enum nds32_isr_save_reg
+{
+ NDS32_SAVE_ALL,
+ NDS32_PARTIAL_SAVE
+};
+
+/* Define isr nested type. */
+enum nds32_isr_nested_type
+{
+ NDS32_NESTED,
+ NDS32_NOT_NESTED,
+ NDS32_NESTED_READY
+};
+
+/* Define structure to record isr information.
+ The isr vector array 'isr_vectors[]' with this structure
+ is defined in nds32.c. */
+struct nds32_isr_info
+{
+ /* The field to identify isr category.
+ It should be set to NDS32_ISR_NONE by default.
+ If user specifies a function as isr by using attribute,
+ this field will be set accordingly. */
+ enum nds32_isr_category category;
+
+ /* A string for the applied function name.
+ It should be set to empty string by default. */
+ char func_name[100];
+
+ /* The register saving scheme.
+ It should be set to NDS32_PARTIAL_SAVE by default
+ unless user specifies attribute to change it. */
+ enum nds32_isr_save_reg save_reg;
+
+ /* The nested type.
+ It should be set to NDS32_NOT_NESTED by default
+ unless user specifies attribute to change it. */
+ enum nds32_isr_nested_type nested_type;
+
+ /* Total vectors.
+ The total vectors = interrupt + exception numbers + reset.
+ It should be set to 0 by default.
+ This field is ONLY used in NDS32_ISR_RESET category. */
+ unsigned int total_n_vectors;
+
+ /* A string for nmi handler name.
+ It should be set to empty string by default.
+ This field is ONLY used in NDS32_ISR_RESET category. */
+ char nmi_name[100];
+
+ /* A string for warm handler name.
+ It should be set to empty string by default.
+ This field is ONLY used in NDS32_ISR_RESET category. */
+ char warm_name[100];
+};
+
+/* ------------------------------------------------------------------------ */
+
+/* Define code for all nds32 builtins. */
+enum nds32_builtins
+{
+ NDS32_BUILTIN_ISYNC,
+ NDS32_BUILTIN_ISB,
+ NDS32_BUILTIN_MFSR,
+ NDS32_BUILTIN_MFUSR,
+ NDS32_BUILTIN_MTSR,
+ NDS32_BUILTIN_MTUSR,
+ NDS32_BUILTIN_SETGIE_EN,
+ NDS32_BUILTIN_SETGIE_DIS
+};
+
+/* ------------------------------------------------------------------------ */
+
+#define TARGET_ISA_V2 (nds32_arch_option == ARCH_V2)
+#define TARGET_ISA_V3 (nds32_arch_option == ARCH_V3)
+#define TARGET_ISA_V3M (nds32_arch_option == ARCH_V3M)
+
+/* ------------------------------------------------------------------------ */
+
+/* Controlling the Compilation Driver. */
+
+#define OPTION_DEFAULT_SPECS \
+ {"arch", "%{!march=*:-march=%(VALUE)}" }
+
+#define CC1_SPEC \
+ ""
+
+#define ASM_SPEC \
+ " %{mbig-endian:-EB} %{mlittle-endian:-EL}"
+
+/* If user issues -mrelax, -mforce-fp-as-gp, or -mex9,
+ we need to pass '--relax' to linker.
+ Besides, for -mex9, we need to further pass '--mex9'. */
+#define LINK_SPEC \
+ " %{mbig-endian:-EB} %{mlittle-endian:-EL}" \
+ " %{mrelax|mforce-fp-as-gp|mex9:--relax}" \
+ " %{mex9:--mex9}"
+
+#define LIB_SPEC \
+ " -lc -lgloss"
+
+/* The option -mno-ctor-dtor can disable constructor/destructor feature
+ by applying different crt stuff. In the convention, crt0.o is the
+ startup file without constructor/destructor;
+ crt1.o, crti.o, crtbegin.o, crtend.o, and crtn.o are the
+ startup files with constructor/destructor.
+ Note that crt0.o, crt1.o, crti.o, and crtn.o are provided
+ by newlib/mculib/glibc/ublic, while crtbegin.o and crtend.o are
+ currently provided by GCC for nds32 target.
+
+ For nds32 target so far:
+ If -mno-ctor-dtor, we are going to link
+ "crt0.o [user objects]".
+ If general cases, we are going to link
+ "crt1.o crtbegin1.o [user objects] crtend1.o". */
+#define STARTFILE_SPEC \
+ " %{!mno-ctor-dtor:crt1.o%s;:crt0.o%s}" \
+ " %{!mno-ctor-dtor:crtbegin1.o%s}"
+#define ENDFILE_SPEC \
+ " %{!mno-ctor-dtor:crtend1.o%s}"
+
+/* The TARGET_BIG_ENDIAN_DEFAULT is defined if we configure gcc
+ with --target=nds32be-* setting.
+ Check gcc/config.gcc for more information.
+ In addition, currently we only have elf toolchain,
+ where mgp-direct is always the default. */
+#ifdef TARGET_BIG_ENDIAN_DEFAULT
+#define MULTILIB_DEFAULTS { "mbig-endian", "mgp-direct" }
+#else
+#define MULTILIB_DEFAULTS { "mlittle-endian", "mgp-direct" }
+#endif
+
+
+/* Run-time Target Specification. */
+
+#define TARGET_CPU_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define ("__nds32__"); \
+ \
+ if (TARGET_ISA_V2) \
+ builtin_define ("__NDS32_ISA_V2__"); \
+ if (TARGET_ISA_V3) \
+ builtin_define ("__NDS32_ISA_V3__"); \
+ if (TARGET_ISA_V3M) \
+ builtin_define ("__NDS32_ISA_V3M__"); \
+ \
+ if (TARGET_BIG_ENDIAN) \
+ builtin_define ("__big_endian__"); \
+ if (TARGET_REDUCED_REGS) \
+ builtin_define ("__NDS32_REDUCED_REGS__"); \
+ if (TARGET_CMOV) \
+ builtin_define ("__NDS32_CMOV__"); \
+ if (TARGET_PERF_EXT) \
+ builtin_define ("__NDS32_PERF_EXT__"); \
+ if (TARGET_16_BIT) \
+ builtin_define ("__NDS32_16_BIT__"); \
+ if (TARGET_GP_DIRECT) \
+ builtin_define ("__NDS32_GP_DIRECT__"); \
+ \
+ builtin_assert ("cpu=nds32"); \
+ builtin_assert ("machine=nds32"); \
+ } while (0)
+
+
+/* Defining Data Structures for Per-function Information. */
+
+/* This macro is called once per function,
+ before generation of any RTL has begun. */
+#define INIT_EXPANDERS nds32_init_expanders ()
+
+
+/* Storage Layout. */
+
+#define BITS_BIG_ENDIAN 0
+
+#define BYTES_BIG_ENDIAN (TARGET_BIG_ENDIAN)
+
+#define WORDS_BIG_ENDIAN (TARGET_BIG_ENDIAN)
+
+#define UNITS_PER_WORD 4
+
+#define PROMOTE_MODE(m, unsignedp, type) \
+ if (GET_MODE_CLASS (m) == MODE_INT && GET_MODE_SIZE (m) < UNITS_PER_WORD) \
+ { \
+ (m) = SImode; \
+ }
+
+#define PARM_BOUNDARY 32
+
+#define STACK_BOUNDARY 64
+
+#define FUNCTION_BOUNDARY 32
+
+#define BIGGEST_ALIGNMENT 64
+
+#define EMPTY_FIELD_BOUNDARY 32
+
+#define STRUCTURE_SIZE_BOUNDARY 8
+
+#define STRICT_ALIGNMENT 1
+
+#define PCC_BITFIELD_TYPE_MATTERS 1
+
+
+/* Layout of Source Language Data Types. */
+
+#define INT_TYPE_SIZE 32
+#define SHORT_TYPE_SIZE 16
+#define LONG_TYPE_SIZE 32
+#define LONG_LONG_TYPE_SIZE 64
+
+#define FLOAT_TYPE_SIZE 32
+#define DOUBLE_TYPE_SIZE 64
+#define LONG_DOUBLE_TYPE_SIZE 64
+
+#define DEFAULT_SIGNED_CHAR 1
+
+#define SIZE_TYPE "long unsigned int"
+#define PTRDIFF_TYPE "long int"
+#define WCHAR_TYPE "short unsigned int"
+#define WCHAR_TYPE_SIZE 16
+
+
+/* Register Usage. */
+
+/* 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. */
+#define FIRST_PSEUDO_REGISTER 34
+
+/* An initializer that says which registers are used for fixed
+ purposes all throughout the compiled code and are therefore
+ not available for general allocation.
+
+ $r28 : $fp
+ $r29 : $gp
+ $r30 : $lp
+ $r31 : $sp
+
+ caller-save registers: $r0 ~ $r5, $r16 ~ $r23
+ callee-save registers: $r6 ~ $r10, $r11 ~ $r14
+
+ reserved for assembler : $r15
+ reserved for other use : $r24, $r25, $r26, $r27 */
+#define FIXED_REGISTERS \
+{ /* r0 r1 r2 r3 r4 r5 r6 r7 */ \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ /* r8 r9 r10 r11 r12 r13 r14 r15 */ \
+ 0, 0, 0, 0, 0, 0, 0, 1, \
+ /* r16 r17 r18 r19 r20 r21 r22 r23 */ \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ /* r24 r25 r26 r27 r28 r29 r30 r31 */ \
+ 1, 1, 1, 1, 0, 1, 0, 1, \
+ /* ARG_POINTER:32 */ \
+ 1, \
+ /* FRAME_POINTER:33 */ \
+ 1 \
+}
+
+/* Identifies the registers that are not available for
+ general allocation of values that must live across
+ function calls -- so they are caller-save registers.
+
+ 0 : callee-save registers
+ 1 : caller-save registers */
+#define CALL_USED_REGISTERS \
+{ /* r0 r1 r2 r3 r4 r5 r6 r7 */ \
+ 1, 1, 1, 1, 1, 1, 0, 0, \
+ /* r8 r9 r10 r11 r12 r13 r14 r15 */ \
+ 0, 0, 0, 0, 0, 0, 0, 1, \
+ /* r16 r17 r18 r19 r20 r21 r22 r23 */ \
+ 1, 1, 1, 1, 1, 1, 1, 1, \
+ /* r24 r25 r26 r27 r28 r29 r30 r31 */ \
+ 1, 1, 1, 1, 0, 1, 0, 1, \
+ /* ARG_POINTER:32 */ \
+ 1, \
+ /* FRAME_POINTER:33 */ \
+ 1 \
+}
+
+/* In nds32 target, we have three levels of registers:
+ LOW_COST_REGS : $r0 ~ $r7
+ MIDDLE_COST_REGS : $r8 ~ $r11, $r16 ~ $r19
+ HIGH_COST_REGS : $r12 ~ $r14, $r20 ~ $r31 */
+#define REG_ALLOC_ORDER \
+{ \
+ 0, 1, 2, 3, 4, 5, 6, 7, \
+ 8, 9, 10, 11, 16, 17, 18, 19, \
+ 12, 13, 14, 15, 20, 21, 22, 23, \
+ 24, 25, 26, 27, 28, 29, 30, 31, \
+ 32, \
+ 33 \
+}
+
+/* Tell IRA to use the order we define rather than messing it up with its
+ own cost calculations. */
+#define HONOR_REG_ALLOC_ORDER
+
+/* The number of consecutive hard regs needed starting at
+ reg "regno" for holding a value of mode "mode". */
+#define HARD_REGNO_NREGS(regno, mode) nds32_hard_regno_nregs (regno, mode)
+
+/* Value is 1 if hard register "regno" can hold a value
+ of machine-mode "mode". */
+#define HARD_REGNO_MODE_OK(regno, mode) nds32_hard_regno_mode_ok (regno, mode)
+
+/* A C expression that is nonzero if a value of mode1
+ is accessible in mode2 without copying.
+ Define this macro to return nonzero in as many cases as possible
+ since doing so will allow GCC to perform better register allocation.
+ We can use general registers to tie QI/HI/SI modes together. */
+#define MODES_TIEABLE_P(mode1, mode2) \
+ (GET_MODE_CLASS (mode1) == MODE_INT \
+ && GET_MODE_CLASS (mode2) == MODE_INT \
+ && GET_MODE_SIZE (mode1) <= UNITS_PER_WORD \
+ && GET_MODE_SIZE (mode2) <= UNITS_PER_WORD)
+
+
+/* Register Classes. */
+
+/* In nds32 target, we have three levels of registers:
+ Low cost regsiters : $r0 ~ $r7
+ Middle cost registers : $r8 ~ $r11, $r16 ~ $r19
+ High cost registers : $r12 ~ $r14, $r20 ~ $r31
+
+ In practice, we have MIDDLE_REGS cover LOW_REGS register class contents
+ so that it provides more chance to use low cost registers. */
+enum reg_class
+{
+ NO_REGS,
+ R15_TA_REG,
+ STACK_REG,
+ LOW_REGS,
+ MIDDLE_REGS,
+ HIGH_REGS,
+ GENERAL_REGS,
+ FRAME_REGS,
+ ALL_REGS,
+ LIM_REG_CLASSES
+};
+
+#define N_REG_CLASSES (int) LIM_REG_CLASSES
+
+#define REG_CLASS_NAMES \
+{ \
+ "NO_REGS", \
+ "R15_TA_REG", \
+ "STACK_REG", \
+ "LOW_REGS", \
+ "MIDDLE_REGS", \
+ "HIGH_REGS", \
+ "GENERAL_REGS", \
+ "FRAME_REGS", \
+ "ALL_REGS" \
+}
+
+#define REG_CLASS_CONTENTS \
+{ \
+ {0x00000000, 0x00000000}, /* NO_REGS : */ \
+ {0x00008000, 0x00000000}, /* R15_TA_REG : 15 */ \
+ {0x80000000, 0x00000000}, /* STACK_REG : 31 */ \
+ {0x000000ff, 0x00000000}, /* LOW_REGS : 0-7 */ \
+ {0x000f0fff, 0x00000000}, /* MIDDLE_REGS : 0-11, 16-19 */ \
+ {0xfff07000, 0x00000000}, /* HIGH_REGS : 12-14, 20-31 */ \
+ {0xffffffff, 0x00000000}, /* GENERAL_REGS: 0-31 */ \
+ {0x00000000, 0x00000003}, /* FRAME_REGS : 32, 33 */ \
+ {0xffffffff, 0x00000003} /* ALL_REGS : 0-31, 32, 33 */ \
+}
+
+#define REGNO_REG_CLASS(regno) nds32_regno_reg_class (regno)
+
+#define BASE_REG_CLASS GENERAL_REGS
+#define INDEX_REG_CLASS GENERAL_REGS
+
+/* Return nonzero if it is suitable for use as a
+ base register in operand addresses.
+ So far, we return nonzero only if "num" is a hard reg
+ of the suitable class or a pseudo register which is
+ allocated to a suitable hard reg. */
+#define REGNO_OK_FOR_BASE_P(num) \
+ ((num) < 32 || (unsigned) reg_renumber[num] < 32)
+
+/* Return nonzero if it is suitable for use as a
+ index register in operand addresses.
+ So far, we return nonzero only if "num" is a hard reg
+ of the suitable class or a pseudo register which is
+ allocated to a suitable hard reg.
+ The difference between an index register and a base register is that
+ the index register may be scaled. */
+#define REGNO_OK_FOR_INDEX_P(num) \
+ ((num) < 32 || (unsigned) reg_renumber[num] < 32)
+
+
+/* Obsolete Macros for Defining Constraints. */
+
+
+/* Stack Layout and Calling Conventions. */
+
+#define STACK_GROWS_DOWNWARD
+
+#define FRAME_GROWS_DOWNWARD 1
+
+#define STARTING_FRAME_OFFSET 0
+
+#define STACK_POINTER_OFFSET 0
+
+#define FIRST_PARM_OFFSET(fundecl) 0
+
+#define RETURN_ADDR_RTX(count, frameaddr) \
+ nds32_return_addr_rtx (count, frameaddr)
+
+/* A C expression whose value is RTL representing the location
+ of the incoming return address at the beginning of any function
+ before the prologue.
+ If this RTL is REG, you should also define
+ DWARF_FRAME_RETURN_COLUMN to DWARF_FRAME_REGNUM (REGNO). */
+#define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (Pmode, LP_REGNUM)
+#define DWARF_FRAME_RETURN_COLUMN DWARF_FRAME_REGNUM (LP_REGNUM)
+
+#define STACK_POINTER_REGNUM SP_REGNUM
+
+#define FRAME_POINTER_REGNUM 33
+
+#define HARD_FRAME_POINTER_REGNUM FP_REGNUM
+
+#define ARG_POINTER_REGNUM 32
+
+#define STATIC_CHAIN_REGNUM 16
+
+#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 INITIAL_ELIMINATION_OFFSET(from_reg, to_reg, offset_var) \
+ (offset_var) = nds32_initial_elimination_offset (from_reg, to_reg)
+
+#define ACCUMULATE_OUTGOING_ARGS 1
+
+#define OUTGOING_REG_PARM_STACK_SPACE(fntype) 1
+
+#define CUMULATIVE_ARGS nds32_cumulative_args
+
+#define INIT_CUMULATIVE_ARGS(cum, fntype, libname, fndecl, n_named_args) \
+ nds32_init_cumulative_args (&cum, fntype, libname, fndecl, n_named_args)
+
+/* The REGNO is an unsigned integer but NDS32_GPR_ARG_FIRST_REGNUM may be 0.
+ We better cast REGNO into signed integer so that we can avoid
+ 'comparison of unsigned expression >= 0 is always true' warning. */
+#define FUNCTION_ARG_REGNO_P(regno) \
+ (((int) regno - NDS32_GPR_ARG_FIRST_REGNUM >= 0) \
+ && ((int) regno - NDS32_GPR_ARG_FIRST_REGNUM < NDS32_MAX_REGS_FOR_ARGS))
+
+#define DEFAULT_PCC_STRUCT_RETURN 0
+
+/* 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.
+ In nds32 target, the function epilogue recovers the
+ stack pointer from the frame. */
+#define EXIT_IGNORE_STACK 1
+
+#define FUNCTION_PROFILER(file, labelno) \
+ fprintf (file, "/* profiler %d */", (labelno))
+
+
+/* Implementing the Varargs Macros. */
+
+
+/* Trampolines for Nested Functions. */
+
+/* Giving A-function and B-function,
+ if B-function wants to call A-function's nested function,
+ we need to fill trampoline code into A-function's stack
+ so that B-function can execute the code in stack to indirectly
+ jump to (like 'trampoline' action) desired nested function.
+
+ The trampoline code for nds32 target must contains following parts:
+
+ 1. instructions (4 * 4 = 16 bytes):
+ get $pc first
+ load chain_value to static chain register via $pc
+ load nested function address to $r15 via $pc
+ jump to desired nested function via $r15
+ 2. data (4 * 2 = 8 bytes):
+ chain_value
+ nested function address
+
+ Please check nds32.c implementation for more information. */
+#define TRAMPOLINE_SIZE 24
+
+/* Because all instructions/data in trampoline template are 4-byte size,
+ we set trampoline alignment 8*4=32 bits. */
+#define TRAMPOLINE_ALIGNMENT 32
+
+
+/* Implicit Calls to Library Routines. */
+
+
+/* Addressing Modes. */
+
+/* We can use "LWI.bi Rt, [Ra], 4" to support post increment. */
+#define HAVE_POST_INCREMENT 1
+/* We can use "LWI.bi Rt, [Ra], -4" to support post decrement. */
+#define HAVE_POST_DECREMENT 1
+
+/* We have "LWI.bi Rt, [Ra], imm" instruction form. */
+#define HAVE_POST_MODIFY_DISP 1
+/* We have "LW.bi Rt, [Ra], Rb" instruction form. */
+#define HAVE_POST_MODIFY_REG 1
+
+#define CONSTANT_ADDRESS_P(x) (CONSTANT_P (x) && GET_CODE (x) != CONST_DOUBLE)
+
+#define MAX_REGS_PER_ADDRESS 2
+
+
+/* Anchored Addresses. */
+
+
+/* Condition Code Status. */
+
+
+/* Describing Relative Costs of Operations. */
+
+/* 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 : 0)
+
+#define SLOW_BYTE_ACCESS 1
+
+#define NO_FUNCTION_CSE
+
+
+/* Adjusting the Instruction Scheduler. */
+
+
+/* Dividing the Output into Sections (Texts, Data, . . . ). */
+
+#define TEXT_SECTION_ASM_OP "\t.text"
+#define DATA_SECTION_ASM_OP "\t.data"
+
+/* Currently, nds32 assembler does NOT handle '.bss' pseudo-op.
+ So we use '.section .bss' alternatively. */
+#define BSS_SECTION_ASM_OP "\t.section\t.bss"
+
+/* Define this macro to be an expression with a nonzero value if jump tables
+ (for tablejump insns) should be output in the text section,
+ along with the assembler instructions.
+ Otherwise, the readonly data section is used. */
+#define JUMP_TABLES_IN_TEXT_SECTION 1
+
+
+/* Position Independent Code. */
+
+
+/* Defining the Output Assembler Language. */
+
+#define ASM_COMMENT_START "!"
+
+#define ASM_APP_ON "! #APP"
+
+#define ASM_APP_OFF "! #NO_APP\n"
+
+#define ASM_OUTPUT_LABELREF(stream, name) \
+ asm_fprintf (stream, "%U%s", (*targetm.strip_name_encoding) (name))
+
+#define ASM_OUTPUT_SYMBOL_REF(stream, sym) \
+ assemble_name (stream, XSTR (sym, 0))
+
+#define ASM_OUTPUT_LABEL_REF(stream, buf) \
+ assemble_name (stream, buf)
+
+#define LOCAL_LABEL_PREFIX "."
+
+#define REGISTER_NAMES \
+{ \
+ "$r0", "$r1", "$r2", "$r3", "$r4", "$r5", "$r6", "$r7", \
+ "$r8", "$r9", "$r10", "$r11", "$r12", "$r13", "$r14", "$ta", \
+ "$r16", "$r17", "$r18", "$r19", "$r20", "$r21", "$r22", "$r23", \
+ "$r24", "$r25", "$r26", "$r27", "$fp", "$gp", "$lp", "$sp", \
+ "$AP", \
+ "$SFP" \
+}
+
+/* Output normal jump table entry. */
+#define ASM_OUTPUT_ADDR_VEC_ELT(stream, value) \
+ asm_fprintf (stream, "\t.word\t%LL%d\n", value)
+
+/* Output pc relative jump table entry. */
+#define ASM_OUTPUT_ADDR_DIFF_ELT(stream, body, value, rel) \
+ do \
+ { \
+ switch (GET_MODE (body)) \
+ { \
+ case QImode: \
+ asm_fprintf (stream, "\t.byte\t.L%d-.L%d\n", value, rel); \
+ break; \
+ case HImode: \
+ asm_fprintf (stream, "\t.short\t.L%d-.L%d\n", value, rel); \
+ break; \
+ case SImode: \
+ asm_fprintf (stream, "\t.word\t.L%d-.L%d\n", value, rel); \
+ break; \
+ default: \
+ gcc_unreachable(); \
+ } \
+ } while (0)
+
+/* We have to undef it first because elfos.h formerly define it
+ check gcc/config.gcc and gcc/config/elfos.h for more information. */
+#undef ASM_OUTPUT_CASE_LABEL
+#define ASM_OUTPUT_CASE_LABEL(stream, prefix, num, table) \
+ do \
+ { \
+ asm_fprintf (stream, "\t! Jump Table Begin\n"); \
+ (*targetm.asm_out.internal_label) (stream, prefix, num); \
+ } while (0)
+
+#define ASM_OUTPUT_CASE_END(stream, num, table) \
+ do \
+ { \
+ /* Because our jump table is in text section, \
+ we need to make sure 2-byte alignment after \
+ the jump table for instructions fetch. */ \
+ if (GET_MODE (PATTERN (table)) == QImode) \
+ ASM_OUTPUT_ALIGN (stream, 1); \
+ asm_fprintf (stream, "\t! Jump Table End\n"); \
+ } while (0)
+
+/* This macro is not documented yet.
+ But we do need it to make jump table vector aligned. */
+#define ADDR_VEC_ALIGN(JUMPTABLE) 2
+
+#define DWARF2_UNWIND_INFO 1
+
+#define JUMP_ALIGN(x) \
+ (align_jumps_log ? align_jumps_log : nds32_target_alignment (x))
+
+#define LOOP_ALIGN(x) \
+ (align_loops_log ? align_loops_log : nds32_target_alignment (x))
+
+#define LABEL_ALIGN(x) \
+ (align_labels_log ? align_labels_log : nds32_target_alignment (x))
+
+#define ASM_OUTPUT_ALIGN(stream, power) \
+ fprintf (stream, "\t.align\t%d\n", power)
+
+
+/* Controlling Debugging Information Format. */
+
+#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
+
+#define DWARF2_DEBUGGING_INFO 1
+
+#define DWARF2_ASM_LINE_DEBUG_INFO 1
+
+
+/* Cross Compilation and Floating Point. */
+
+
+/* Mode Switching Instructions. */
+
+
+/* Defining target-specific uses of __attribute__. */
+
+
+/* Emulating TLS. */
+
+
+/* Defining coprocessor specifics for MIPS targets. */
+
+
+/* Parameters for Precompiled Header Validity Checking. */
+
+
+/* C++ ABI parameters. */
+
+
+/* Adding support for named address spaces. */
+
+
+/* Miscellaneous Parameters. */
+
+/* This is the machine mode that elements of a jump-table should have. */
+#define CASE_VECTOR_MODE Pmode
+
+/* Return the preferred mode for and addr_diff_vec when the mininum
+ and maximum offset are known. */
+#define CASE_VECTOR_SHORTEN_MODE(min_offset, max_offset, body) \
+ ((min_offset < 0 || max_offset >= 0x2000 ) ? SImode \
+ : (max_offset >= 100) ? HImode \
+ : QImode)
+
+/* Generate pc relative jump table when -fpic or -Os. */
+#define CASE_VECTOR_PC_RELATIVE (flag_pic || optimize_size)
+
+/* Define this macro if operations between registers with integral mode
+ smaller than a word are always performed on the entire register. */
+#define WORD_REGISTER_OPERATIONS
+
+/* A C expression indicating when insns that read memory in mem_mode,
+ an integral mode narrower than a word, set the bits outside of mem_mode
+ to be either the sign-extension or the zero-extension of the data read. */
+#define LOAD_EXTEND_OP(MODE) ZERO_EXTEND
+
+/* The maximum number of bytes that a single instruction can move quickly
+ between memory and registers or between two memory locations. */
+#define MOVE_MAX 4
+
+/* A C expression that is nonzero if on this machine the number of bits
+ actually used for the count of a shift operation is equal to the number
+ of bits needed to represent the size of the object being shifted. */
+#define SHIFT_COUNT_TRUNCATED 1
+
+/* A C expression which is nonzero if on this machine it is safe to "convert"
+ an integer of 'inprec' bits to one of 'outprec' bits by merely operating
+ on it as if it had only 'outprec' bits. */
+#define TRULY_NOOP_TRUNCATION(outprec, inprec) 1
+
+/* A C expression describing the value returned by a comparison operator with
+ an integral mode and stored by a store-flag instruction ('cstoremode4')
+ when the condition is true. */
+#define STORE_FLAG_VALUE 1
+
+/* An alias for the machine mode for pointers. */
+#define Pmode SImode
+
+/* An alias for the machine mode used for memory references to functions
+ being called, in call RTL expressions. */
+#define FUNCTION_MODE SImode
+
+/* ------------------------------------------------------------------------ */
diff --git a/gcc/config/nds32/nds32.md b/gcc/config/nds32/nds32.md
new file mode 100644
index 00000000000..4a832eaf86b
--- /dev/null
+++ b/gcc/config/nds32/nds32.md
@@ -0,0 +1,2221 @@
+;; Machine description of Andes NDS32 cpu for GNU compiler
+;; Copyright (C) 2012-2013 Free Software Foundation, Inc.
+;; Contributed by Andes Technology Corporation.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 3, or (at your
+;; option) any later version.
+;;
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+;; License for more details.
+;;
+;; You should have 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 file "rtl.def" for documentation on define_insn, match_*, et. al.
+
+;; Include predicates definition.
+(include "predicates.md")
+
+;; Include constraints definition.
+(include "constraints.md")
+
+;; Include iterators definition.
+(include "iterators.md")
+
+;; Include pipelines definition.
+(include "pipelines.md")
+
+
+;; Include constants definition.
+(include "constants.md")
+
+
+;; Include intrinsic functions definition.
+(include "nds32-intrinsic.md")
+
+;; Include block move for nds32 multiple load/store behavior.
+(include "nds32-multiple.md")
+
+;; Include DImode/DFmode operations.
+(include "nds32-doubleword.md")
+
+;; Include peephole patterns.
+(include "nds32-peephole2.md")
+
+
+;; Insn type, it is used to default other attribute values.
+(define_attr "type"
+ "unknown,move,load,store,alu,compare,branch,call,misc"
+ (const_string "unknown"))
+
+
+;; Length, in bytes, default is 4-bytes.
+(define_attr "length" "" (const_int 4))
+
+
+;; Enabled, which is used to enable/disable insn alternatives.
+;; Note that we use length and TARGET_16_BIT here as criteria.
+;; If the instruction pattern already check TARGET_16_BIT to
+;; determine the length by itself, its enabled attribute should be
+;; always 1 to avoid the conflict with the settings here.
+(define_attr "enabled" ""
+ (cond [(and (eq_attr "length" "2")
+ (match_test "!TARGET_16_BIT"))
+ (const_int 0)]
+ (const_int 1)))
+
+
+;; ----------------------------------------------------------------------------
+
+
+;; Move instructions.
+
+;; For QImode and HImode, the immediate value can be fit in imm20s.
+;; So there is no need to split rtx for QI and HI patterns.
+
+(define_expand "movqi"
+ [(set (match_operand:QI 0 "general_operand" "")
+ (match_operand:QI 1 "general_operand" ""))]
+ ""
+{
+ /* Need to force register if mem <- !reg. */
+ if (MEM_P (operands[0]) && !REG_P (operands[1]))
+ operands[1] = force_reg (QImode, operands[1]);
+})
+
+(define_expand "movhi"
+ [(set (match_operand:HI 0 "general_operand" "")
+ (match_operand:HI 1 "general_operand" ""))]
+ ""
+{
+ /* Need to force register if mem <- !reg. */
+ if (MEM_P (operands[0]) && !REG_P (operands[1]))
+ operands[1] = force_reg (HImode, operands[1]);
+})
+
+(define_expand "movsi"
+ [(set (match_operand:SI 0 "general_operand" "")
+ (match_operand:SI 1 "general_operand" ""))]
+ ""
+{
+ /* Need to force register if mem <- !reg. */
+ if (MEM_P (operands[0]) && !REG_P (operands[1]))
+ operands[1] = force_reg (SImode, operands[1]);
+
+ /* If operands[1] is a large constant and cannot be performed
+ by a single instruction, we need to split it. */
+ if (CONST_INT_P (operands[1])
+ && !satisfies_constraint_Is20 (operands[1])
+ && !satisfies_constraint_Ihig (operands[1]))
+ {
+ rtx high20_rtx;
+ HOST_WIDE_INT low12_int;
+ rtx tmp_rtx;
+
+ tmp_rtx = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
+
+ high20_rtx = gen_int_mode ((INTVAL (operands[1]) >> 12) << 12, SImode);
+ low12_int = INTVAL (operands[1]) & 0xfff;
+
+ emit_move_insn (tmp_rtx, high20_rtx);
+ emit_move_insn (operands[0], plus_constant (SImode,
+ tmp_rtx,
+ low12_int));
+ DONE;
+ }
+})
+
+(define_insn "*mov<mode>"
+ [(set (match_operand:QIHISI 0 "nonimmediate_operand" "=r, r, U45, U33, U37, U45, m, l, l, l, d, r, d, r, r, r")
+ (match_operand:QIHISI 1 "nds32_move_operand" " r, r, l, l, l, d, r, U45, U33, U37, U45, m, Ip05, Is05, Is20, Ihig"))]
+ ""
+{
+ switch (which_alternative)
+ {
+ case 0:
+ return "mov55\t%0, %1";
+ case 1:
+ return "ori\t%0, %1, 0";
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ return nds32_output_16bit_store (operands, <byte>);
+ case 6:
+ return nds32_output_32bit_store (operands, <byte>);
+ case 7:
+ case 8:
+ case 9:
+ case 10:
+ return nds32_output_16bit_load (operands, <byte>);
+ case 11:
+ return nds32_output_32bit_load (operands, <byte>);
+ case 12:
+ return "movpi45\t%0, %1";
+ case 13:
+ return "movi55\t%0, %1";
+ case 14:
+ return "movi\t%0, %1";
+ case 15:
+ return "sethi\t%0, hi20(%1)";
+ default:
+ gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "alu,alu,store,store,store,store,store,load,load,load,load,load,alu,alu,alu,alu")
+ (set_attr "length" " 2, 4, 2, 2, 2, 2, 4, 2, 2, 2, 2, 4, 2, 2, 4, 4")])
+
+
+;; We use nds32_symbolic_operand to limit that only CONST/SYMBOL_REF/LABEL_REF
+;; are able to match such instruction template.
+(define_insn "*move_addr"
+ [(set (match_operand:SI 0 "register_operand" "=l, r")
+ (match_operand:SI 1 "nds32_symbolic_operand" " i, i"))]
+ ""
+ "la\t%0, %1"
+ [(set_attr "type" "move")
+ (set_attr "length" "8")])
+
+
+(define_insn "*sethi"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (high:SI (match_operand:SI 1 "nds32_symbolic_operand" " i")))]
+ ""
+ "sethi\t%0, hi20(%1)"
+ [(set_attr "type" "alu")
+ (set_attr "length" "4")])
+
+
+(define_insn "*lo_sum"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (lo_sum:SI (match_operand:SI 1 "register_operand" " r")
+ (match_operand:SI 2 "nds32_symbolic_operand" " i")))]
+ ""
+ "ori\t%0, %1, lo12(%2)"
+ [(set_attr "type" "alu")
+ (set_attr "length" "4")])
+
+
+;; ----------------------------------------------------------------------------
+
+;; Zero extension instructions.
+
+(define_insn "zero_extend<mode>si2"
+ [(set (match_operand:SI 0 "register_operand" "=l, r, l, *r")
+ (zero_extend:SI (match_operand:QIHI 1 "nonimmediate_operand" " l, r, U33, m")))]
+ ""
+{
+ switch (which_alternative)
+ {
+ case 0:
+ return "ze<size>33\t%0, %1";
+ case 1:
+ return "ze<size>\t%0, %1";
+ case 2:
+ return nds32_output_16bit_load (operands, <byte>);
+ case 3:
+ return nds32_output_32bit_load (operands, <byte>);
+
+ default:
+ gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "alu,alu,load,load")
+ (set_attr "length" " 2, 4, 2, 4")])
+
+
+;; Sign extension instructions.
+
+(define_insn "extend<mode>si2"
+ [(set (match_operand:SI 0 "register_operand" "=l, r, r")
+ (sign_extend:SI (match_operand:QIHI 1 "nonimmediate_operand" " l, r, m")))]
+ ""
+{
+ switch (which_alternative)
+ {
+ case 0:
+ return "se<size>33\t%0, %1";
+ case 1:
+ return "se<size>\t%0, %1";
+ case 2:
+ return nds32_output_32bit_load_s (operands, <byte>);
+
+ default:
+ gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "alu,alu,load")
+ (set_attr "length" " 2, 4, 4")])
+
+
+;; ----------------------------------------------------------------------------
+
+;; Arithmetic instructions.
+
+(define_insn "add<mode>3"
+ [(set (match_operand:QIHISI 0 "register_operand" "= d, l, d, l, d, l, k, l, r, r")
+ (plus:QIHISI (match_operand:QIHISI 1 "register_operand" " 0, l, 0, l, %0, l, 0, k, r, r")
+ (match_operand:QIHISI 2 "nds32_rimm15s_operand" " In05, In03, Iu05, Iu03, r, l, Is10, Iu06, Is15, r")))]
+ ""
+{
+ switch (which_alternative)
+ {
+ case 0:
+ /* addi Rt4,Rt4,-x ==> subi45 Rt4,x
+ where 0 <= x <= 31 */
+ operands[2] = gen_int_mode (-INTVAL (operands[2]), SImode);
+ return "subi45\t%0, %2";
+ case 1:
+ /* addi Rt3,Ra3,-x ==> subi333 Rt3,Ra3,x
+ where 0 <= x <= 7 */
+ operands[2] = gen_int_mode (-INTVAL (operands[2]), SImode);
+ return "subi333\t%0, %1, %2";
+ case 2:
+ return "addi45\t%0, %2";
+ case 3:
+ return "addi333\t%0, %1, %2";
+ case 4:
+ return "add45\t%0, %2";
+ case 5:
+ return "add333\t%0, %1, %2";
+ case 6:
+ return "addi10.sp\t%2";
+ case 7:
+ return "addri36.sp\t%0, %2";
+ case 8:
+ return "addi\t%0, %1, %2";
+ case 9:
+ return "add\t%0, %1, %2";
+
+ default:
+ gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "alu,alu,alu,alu,alu,alu,alu,alu,alu,alu")
+ (set_attr "length" " 2, 2, 2, 2, 2, 2, 2, 2, 4, 4")])
+
+(define_insn "sub<mode>3"
+ [(set (match_operand:QIHISI 0 "register_operand" "=d, l, r, r")
+ (minus:QIHISI (match_operand:QIHISI 1 "nds32_rimm15s_operand" " 0, l, Is15, r")
+ (match_operand:QIHISI 2 "register_operand" " r, l, r, r")))]
+ ""
+ "@
+ sub45\t%0, %2
+ sub333\t%0, %1, %2
+ subri\t%0, %2, %1
+ sub\t%0, %1, %2"
+ [(set_attr "type" "alu,alu,alu,alu")
+ (set_attr "length" " 2, 2, 4, 4")])
+
+
+;; GCC intends to simplify (plus (ashift ...) (reg))
+;; into (plus (mult ...) (reg)), so our matching pattern takes 'mult'
+;; and needs to ensure it is exact_log2 value.
+(define_insn "*add_slli"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI (mult:SI (match_operand:SI 1 "register_operand" " r")
+ (match_operand:SI 2 "immediate_operand" " i"))
+ (match_operand:SI 3 "register_operand" " r")))]
+ "TARGET_ISA_V3
+ && (exact_log2 (INTVAL (operands[2])) != -1)
+ && (exact_log2 (INTVAL (operands[2])) <= 31)"
+{
+ /* Get floor_log2 of the immediate value
+ so that we can generate 'add_slli' instruction. */
+ operands[2] = GEN_INT (floor_log2 (INTVAL (operands[2])));
+
+ return "add_slli\t%0, %3, %1, %2";
+}
+ [(set_attr "type" "alu")
+ (set_attr "length" "4")])
+
+(define_insn "*add_srli"
+ [(set (match_operand:SI 0 "register_operand" "= r")
+ (plus:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" " r")
+ (match_operand:SI 2 "immediate_operand" " Iu05"))
+ (match_operand:SI 3 "register_operand" " r")))]
+ "TARGET_ISA_V3"
+ "add_srli\t%0, %3, %1, %2"
+ [(set_attr "type" "alu")
+ (set_attr "length" "4")])
+
+
+;; GCC intends to simplify (minus (reg) (ashift ...))
+;; into (minus (reg) (mult ...)), so our matching pattern takes 'mult'
+;; and needs to ensure it is exact_log2 value.
+(define_insn "*sub_slli"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (minus:SI (match_operand:SI 1 "register_operand" " r")
+ (mult:SI (match_operand:SI 2 "register_operand" " r")
+ (match_operand:SI 3 "immediate_operand" " i"))))]
+ "TARGET_ISA_V3
+ && (exact_log2 (INTVAL (operands[3])) != -1)
+ && (exact_log2 (INTVAL (operands[3])) <= 31)"
+{
+ /* Get floor_log2 of the immediate value
+ so that we can generate 'sub_slli' instruction. */
+ operands[3] = GEN_INT (floor_log2 (INTVAL (operands[3])));
+
+ return "sub_slli\t%0, %1, %2, %3";
+}
+ [(set_attr "type" "alu")
+ (set_attr "length" "4")])
+
+(define_insn "*sub_srli"
+ [(set (match_operand:SI 0 "register_operand" "= r")
+ (minus:SI (match_operand:SI 1 "register_operand" " r")
+ (lshiftrt:SI (match_operand:SI 2 "register_operand" " r")
+ (match_operand:SI 3 "immediate_operand" " Iu05"))))]
+ "TARGET_ISA_V3"
+ "sub_srli\t%0, %1, %2, %3"
+ [(set_attr "type" "alu")
+ (set_attr "length" "4")])
+
+
+;; Multiplication instructions.
+
+(define_insn "mulsi3"
+ [(set (match_operand:SI 0 "register_operand" "= w, r")
+ (mult:SI (match_operand:SI 1 "register_operand" " %0, r")
+ (match_operand:SI 2 "register_operand" " w, r")))]
+ ""
+ "@
+ mul33\t%0, %2
+ mul\t%0, %1, %2"
+ [(set_attr "type" "alu,alu")
+ (set_attr "length" " 2, 4")])
+
+(define_insn "mulsidi3"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" " r"))
+ (sign_extend:DI (match_operand:SI 2 "register_operand" " r"))))]
+ "TARGET_ISA_V2 || TARGET_ISA_V3"
+ "mulsr64\t%0, %1, %2"
+ [(set_attr "type" "alu")
+ (set_attr "length" "4")])
+
+(define_insn "umulsidi3"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" " r"))
+ (zero_extend:DI (match_operand:SI 2 "register_operand" " r"))))]
+ "TARGET_ISA_V2 || TARGET_ISA_V3"
+ "mulr64\t%0, %1, %2"
+ [(set_attr "type" "alu")
+ (set_attr "length" "4")])
+
+
+;; Multiply-accumulate instructions.
+
+(define_insn "*maddr32_0"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI (match_operand:SI 3 "register_operand" " 0")
+ (mult:SI (match_operand:SI 1 "register_operand" " r")
+ (match_operand:SI 2 "register_operand" " r"))))]
+ ""
+ "maddr32\t%0, %1, %2"
+ [(set_attr "type" "alu")
+ (set_attr "length" "4")])
+
+(define_insn "*maddr32_1"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI (mult:SI (match_operand:SI 1 "register_operand" " r")
+ (match_operand:SI 2 "register_operand" " r"))
+ (match_operand:SI 3 "register_operand" " 0")))]
+ ""
+ "maddr32\t%0, %1, %2"
+ [(set_attr "type" "alu")
+ (set_attr "length" "4")])
+
+(define_insn "*msubr32"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (minus:SI (match_operand:SI 3 "register_operand" " 0")
+ (mult:SI (match_operand:SI 1 "register_operand" " r")
+ (match_operand:SI 2 "register_operand" " r"))))]
+ ""
+ "msubr32\t%0, %1, %2"
+ [(set_attr "type" "alu")
+ (set_attr "length" "4")])
+
+
+;; Div Instructions.
+
+(define_insn "divmodsi4"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (div:SI (match_operand:SI 1 "register_operand" " r")
+ (match_operand:SI 2 "register_operand" " r")))
+ (set (match_operand:SI 3 "register_operand" "=r")
+ (mod:SI (match_dup 1) (match_dup 2)))]
+ ""
+ "divsr\t%0, %3, %1, %2"
+ [(set_attr "type" "alu")
+ (set_attr "length" "4")])
+
+(define_insn "udivmodsi4"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (udiv:SI (match_operand:SI 1 "register_operand" " r")
+ (match_operand:SI 2 "register_operand" " r")))
+ (set (match_operand:SI 3 "register_operand" "=r")
+ (umod:SI (match_dup 1) (match_dup 2)))]
+ ""
+ "divr\t%0, %3, %1, %2"
+ [(set_attr "type" "alu")
+ (set_attr "length" "4")])
+
+
+;; ----------------------------------------------------------------------------
+
+;; Boolean instructions.
+;; Note: We define the DImode versions in nds32-doubleword.md.
+
+;; ----------------------------------------------------------------------------
+;; 'AND' operation
+;; ----------------------------------------------------------------------------
+
+(define_insn "bitc"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (and:SI (not:SI (match_operand:SI 1 "register_operand" " r"))
+ (match_operand:SI 2 "register_operand" " r")))]
+ "TARGET_ISA_V3"
+ "bitc\t%0, %2, %1"
+ [(set_attr "type" "alu")
+ (set_attr "length" "4")]
+)
+
+(define_insn "andsi3"
+ [(set (match_operand:SI 0 "register_operand" "= w, r, l, l, l, l, l, l, r, r, r, r, r")
+ (and:SI (match_operand:SI 1 "register_operand" " %0, r, l, l, l, l, 0, 0, r, r, r, r, r")
+ (match_operand:SI 2 "general_operand" " w, r, Izeb, Izeh, Ixls, Ix11, Ibms, Ifex, Izeb, Izeh, Iu15, Ii15, Ic15")))]
+ ""
+{
+ HOST_WIDE_INT mask = INTVAL (operands[2]);
+ int zero_position;
+
+ /* 16-bit andi instructions:
+ andi Rt3,Ra3,0xff -> zeb33 Rt3,Ra3
+ andi Rt3,Ra3,0xffff -> zeh33 Rt3,Ra3
+ andi Rt3,Ra3,0x01 -> xlsb33 Rt3,Ra3
+ andi Rt3,Ra3,0x7ff -> x11b33 Rt3,Ra3
+ andi Rt3,Rt3,2^imm3u -> bmski33 Rt3,imm3u
+ andi Rt3,Rt3,(2^(imm3u+1))-1 -> fexti33 Rt3,imm3u. */
+
+ switch (which_alternative)
+ {
+ case 0:
+ return "and33\t%0, %2";
+ case 1:
+ return "and\t%0, %1, %2";
+ case 2:
+ return "zeb33\t%0, %1";
+ case 3:
+ return "zeh33\t%0, %1";
+ case 4:
+ return "xlsb33\t%0, %1";
+ case 5:
+ return "x11b33\t%0, %1";
+ case 6:
+ operands[2] = GEN_INT (floor_log2 (mask));
+ return "bmski33\t%0, %2";
+ case 7:
+ operands[2] = GEN_INT (floor_log2 (mask + 1) - 1);
+ return "fexti33\t%0, %2";
+ case 8:
+ return "zeb\t%0, %1";
+ case 9:
+ return "zeh\t%0, %1";
+ case 10:
+ return "andi\t%0, %1, %2";
+ case 11:
+ operands[2] = GEN_INT (~mask);
+ return "bitci\t%0, %1, %2";
+ case 12:
+ /* If we reach this alternative,
+ it must pass the nds32_can_use_bclr_p() test,
+ so that we can guarantee there is only one 0-bit
+ within the immediate value. */
+ for (zero_position = 31; zero_position >= 0; zero_position--)
+ {
+ if ((INTVAL (operands[2]) & (1 << zero_position)) == 0)
+ {
+ /* Found the 0-bit position. */
+ operands[2] = GEN_INT (zero_position);
+ break;
+ }
+ }
+ return "bclr\t%0, %1, %2";
+
+ default:
+ gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "alu,alu,alu,alu,alu,alu,alu,alu,alu,alu,alu,alu,alu")
+ (set_attr "length" " 2, 4, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4")])
+
+(define_insn "*and_slli"
+ [(set (match_operand:SI 0 "register_operand" "= r")
+ (and:SI (ashift:SI (match_operand:SI 1 "register_operand" " r")
+ (match_operand:SI 2 "immediate_operand" " Iu05"))
+ (match_operand:SI 3 "register_operand" " r")))]
+ "TARGET_ISA_V3"
+ "and_slli\t%0, %3, %1, %2"
+ [(set_attr "type" "alu")
+ (set_attr "length" "4")])
+
+(define_insn "*and_srli"
+ [(set (match_operand:SI 0 "register_operand" "= r")
+ (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" " r")
+ (match_operand:SI 2 "immediate_operand" " Iu05"))
+ (match_operand:SI 3 "register_operand" " r")))]
+ "TARGET_ISA_V3"
+ "and_srli\t%0, %3, %1, %2"
+ [(set_attr "type" "alu")
+ (set_attr "length" "4")])
+
+
+;; ----------------------------------------------------------------------------
+;; 'OR' operation
+;; ----------------------------------------------------------------------------
+
+;; For V3/V3M ISA, we have 'or33' instruction.
+;; So we can identify 'or Rt3,Rt3,Ra3' case and set its length to be 2.
+(define_insn "iorsi3"
+ [(set (match_operand:SI 0 "register_operand" "= w, r, r, r")
+ (ior:SI (match_operand:SI 1 "register_operand" " %0, r, r, r")
+ (match_operand:SI 2 "general_operand" " w, r, Iu15, Ie15")))]
+ ""
+{
+ int one_position;
+
+ switch (which_alternative)
+ {
+ case 0:
+ return "or33\t%0, %2";
+ case 1:
+ return "or\t%0, %1, %2";
+ case 2:
+ return "ori\t%0, %1, %2";
+ case 3:
+ /* If we reach this alternative,
+ it must pass the nds32_can_use_bset_p() test,
+ so that we can guarantee there is only one 1-bit
+ within the immediate value. */
+ /* Use exact_log2() to search the 1-bit position. */
+ one_position = exact_log2 (INTVAL (operands[2]));
+ operands[2] = GEN_INT (one_position);
+ return "bset\t%0, %1, %2";
+
+ default:
+ gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "alu,alu,alu,alu")
+ (set_attr "length" " 2, 4, 4, 4")])
+
+(define_insn "*or_slli"
+ [(set (match_operand:SI 0 "register_operand" "= r")
+ (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" " r")
+ (match_operand:SI 2 "immediate_operand" " Iu05"))
+ (match_operand:SI 3 "register_operand" " r")))]
+ "TARGET_ISA_V3"
+ "or_slli\t%0, %3, %1, %2"
+ [(set_attr "type" "alu")
+ (set_attr "length" "4")])
+
+(define_insn "*or_srli"
+ [(set (match_operand:SI 0 "register_operand" "= r")
+ (ior:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" " r")
+ (match_operand:SI 2 "immediate_operand" " Iu05"))
+ (match_operand:SI 3 "register_operand" " r")))]
+ "TARGET_ISA_V3"
+ "or_srli\t%0, %3, %1, %2"
+ [(set_attr "type" "alu")
+ (set_attr "length" "4")])
+
+
+;; ----------------------------------------------------------------------------
+;; 'XOR' operation
+;; ----------------------------------------------------------------------------
+
+;; For V3/V3M ISA, we have 'xor33' instruction.
+;; So we can identify 'xor Rt3,Rt3,Ra3' case and set its length to be 2.
+(define_insn "xorsi3"
+ [(set (match_operand:SI 0 "register_operand" "= w, r, r, r")
+ (xor:SI (match_operand:SI 1 "register_operand" " %0, r, r, r")
+ (match_operand:SI 2 "general_operand" " w, r, Iu15, It15")))]
+ ""
+{
+ int one_position;
+
+ switch (which_alternative)
+ {
+ case 0:
+ return "xor33\t%0, %2";
+ case 1:
+ return "xor\t%0, %1, %2";
+ case 2:
+ return "xori\t%0, %1, %2";
+ case 3:
+ /* If we reach this alternative,
+ it must pass the nds32_can_use_btgl_p() test,
+ so that we can guarantee there is only one 1-bit
+ within the immediate value. */
+ /* Use exact_log2() to search the 1-bit position. */
+ one_position = exact_log2 (INTVAL (operands[2]));
+ operands[2] = GEN_INT (one_position);
+ return "btgl\t%0, %1, %2";
+
+ default:
+ gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "alu,alu,alu,alu")
+ (set_attr "length" " 2, 4, 4, 4")])
+
+(define_insn "*xor_slli"
+ [(set (match_operand:SI 0 "register_operand" "= r")
+ (xor:SI (ashift:SI (match_operand:SI 1 "register_operand" " r")
+ (match_operand:SI 2 "immediate_operand" " Iu05"))
+ (match_operand:SI 3 "register_operand" " r")))]
+ "TARGET_ISA_V3"
+ "xor_slli\t%0, %3, %1, %2"
+ [(set_attr "type" "alu")
+ (set_attr "length" "4")])
+
+(define_insn "*xor_srli"
+ [(set (match_operand:SI 0 "register_operand" "= r")
+ (xor:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" " r")
+ (match_operand:SI 2 "immediate_operand" " Iu05"))
+ (match_operand:SI 3 "register_operand" " r")))]
+ "TARGET_ISA_V3"
+ "xor_srli\t%0, %3, %1, %2"
+ [(set_attr "type" "alu")
+ (set_attr "length" "4")])
+
+;; Rotate Right Instructions.
+
+(define_insn "rotrsi3"
+ [(set (match_operand:SI 0 "register_operand" "= r, r")
+ (rotatert:SI (match_operand:SI 1 "register_operand" " r, r")
+ (match_operand:SI 2 "nonmemory_operand" " Iu05, r")))]
+ ""
+ "@
+ rotri\t%0, %1, %2
+ rotr\t%0, %1, %2"
+ [(set_attr "type" "alu,alu")
+ (set_attr "length" " 4, 4")])
+
+
+;; ----------------------------------------------------------------------------
+;; 'NEG' operation
+;; ----------------------------------------------------------------------------
+
+;; For V3/V3M ISA, we have 'neg33' instruction.
+;; So we can identify 'xor Rt3,Ra3' case and set its length to be 2.
+;; And for V2 ISA, there is NO 'neg33' instruction.
+;; The only option is to use 'subri A,B,0' (its semantic is 'A = 0 - B').
+(define_insn "negsi2"
+ [(set (match_operand:SI 0 "register_operand" "=w, r")
+ (neg:SI (match_operand:SI 1 "register_operand" " w, r")))]
+ ""
+ "@
+ neg33\t%0, %1
+ subri\t%0, %1, 0"
+ [(set_attr "type" "alu,alu")
+ (set_attr "length" " 2, 4")])
+
+
+;; ----------------------------------------------------------------------------
+;; 'ONE_COMPLIMENT' operation
+;; ----------------------------------------------------------------------------
+
+;; For V3/V3M ISA, we have 'not33' instruction.
+;; So we can identify 'not Rt3,Ra3' case and set its length to be 2.
+(define_insn "one_cmplsi2"
+ [(set (match_operand:SI 0 "register_operand" "=w, r")
+ (not:SI (match_operand:SI 1 "register_operand" " w, r")))]
+ ""
+ "@
+ not33\t%0, %1
+ nor\t%0, %1, %1"
+ [(set_attr "type" "alu,alu")
+ (set_attr "length" " 2, 4")])
+
+
+;; ----------------------------------------------------------------------------
+
+;; Shift instructions.
+
+(define_insn "ashlsi3"
+ [(set (match_operand:SI 0 "register_operand" "= l, r, r")
+ (ashift:SI (match_operand:SI 1 "register_operand" " l, r, r")
+ (match_operand:SI 2 "nonmemory_operand" " Iu03, Iu05, r")))]
+ ""
+ "@
+ slli333\t%0, %1, %2
+ slli\t%0, %1, %2
+ sll\t%0, %1, %2"
+ [(set_attr "type" "alu,alu,alu")
+ (set_attr "length" " 2, 4, 4")])
+
+(define_insn "ashrsi3"
+ [(set (match_operand:SI 0 "register_operand" "= d, r, r")
+ (ashiftrt:SI (match_operand:SI 1 "register_operand" " 0, r, r")
+ (match_operand:SI 2 "nonmemory_operand" " Iu05, Iu05, r")))]
+ ""
+ "@
+ srai45\t%0, %2
+ srai\t%0, %1, %2
+ sra\t%0, %1, %2"
+ [(set_attr "type" "alu,alu,alu")
+ (set_attr "length" " 2, 4, 4")])
+
+(define_insn "lshrsi3"
+ [(set (match_operand:SI 0 "register_operand" "= d, r, r")
+ (lshiftrt:SI (match_operand:SI 1 "register_operand" " 0, r, r")
+ (match_operand:SI 2 "nonmemory_operand" " Iu05, Iu05, r")))]
+ ""
+ "@
+ srli45\t%0, %2
+ srli\t%0, %1, %2
+ srl\t%0, %1, %2"
+ [(set_attr "type" "alu,alu,alu")
+ (set_attr "length" " 2, 4, 4")])
+
+
+;; ----------------------------------------------------------------------------
+
+;; ----------------------------------------------------------------------------
+;; Conditional Move patterns
+;; ----------------------------------------------------------------------------
+
+(define_expand "movsicc"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (if_then_else:SI (match_operand 1 "comparison_operator" "")
+ (match_operand:SI 2 "register_operand" "")
+ (match_operand:SI 3 "register_operand" "")))]
+ "TARGET_CMOV"
+{
+ if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
+ && GET_MODE (XEXP (operands[1], 0)) == SImode
+ && XEXP (operands[1], 1) == const0_rtx)
+ {
+ /* If the operands[1] rtx is already (eq X 0) or (ne X 0),
+ we have gcc generate original template rtx. */
+ goto create_template;
+ }
+ else
+ {
+ /* Since there is only 'slt'(Set when Less Than) instruction for
+ comparison in Andes ISA, the major strategy we use here is to
+ convert conditional move into 'LT + EQ' or 'LT + NE' rtx combination.
+ We design constraints properly so that the reload phase will assist
+ to make one source operand to use same register as result operand.
+ Then we can use cmovz/cmovn to catch the other source operand
+ which has different register. */
+ enum rtx_code code = GET_CODE (operands[1]);
+ enum rtx_code new_code = code;
+ rtx cmp_op0 = XEXP (operands[1], 0);
+ rtx cmp_op1 = XEXP (operands[1], 1);
+ rtx tmp;
+ int reverse = 0;
+
+ /* Main Goal: Use 'LT + EQ' or 'LT + NE' to target "then" part
+ Strategy : Reverse condition and swap comparison operands
+
+ For example:
+
+ a <= b ? P : Q (LE or LEU)
+ --> a > b ? Q : P (reverse condition)
+ --> b < a ? Q : P (swap comparison operands to achieve 'LT/LTU')
+
+ a >= b ? P : Q (GE or GEU)
+ --> a < b ? Q : P (reverse condition to achieve 'LT/LTU')
+
+ a < b ? P : Q (LT or LTU)
+ --> (NO NEED TO CHANGE, it is already 'LT/LTU')
+
+ a > b ? P : Q (GT or GTU)
+ --> b < a ? P : Q (swap comparison operands to achieve 'LT/LTU') */
+ switch (code)
+ {
+ case NE:
+ /* (a != b ? P : Q)
+ can be expressed as
+ (a == b ? Q : P)
+ so, fall through to reverse condition */
+ case GE: case GEU: case LE: case LEU:
+ new_code = reverse_condition (code);
+ reverse = 1;
+ break;
+ case EQ: case GT: case GTU: case LT: case LTU:
+ /* no need to reverse condition */
+ break;
+ default:
+ FAIL;
+ }
+
+ /* For '>' comparison operator, we swap operands
+ so that we can have 'LT/LTU' operator. */
+ if (new_code == GT || new_code == GTU)
+ {
+ tmp = cmp_op0;
+ cmp_op0 = cmp_op1;
+ cmp_op1 = tmp;
+
+ new_code = swap_condition (new_code);
+ }
+
+ /* Use a temporary register to store slt/slts result. */
+ tmp = gen_reg_rtx (SImode);
+
+ /* Split EQ and NE because we don't have direct comparison of EQ and NE.
+ If we don't split it, the conditional move transformation will fail
+ when producing (SET A (EQ B C)) or (SET A (NE B C)). */
+ if (new_code == EQ)
+ {
+ emit_insn (gen_xorsi3 (tmp, cmp_op0, cmp_op1));
+ emit_insn (gen_slt_compare (tmp, tmp, GEN_INT (1)));
+ }
+ else if (new_code == NE)
+ {
+ emit_insn (gen_xorsi3 (tmp, cmp_op0, cmp_op1));
+ emit_insn (gen_slt_compare (tmp, GEN_INT (0), tmp));
+ }
+ else
+ /* This emit_insn will create corresponding 'slt/slts' insturction. */
+ emit_insn (gen_rtx_SET (VOIDmode, tmp,
+ gen_rtx_fmt_ee (new_code, SImode,
+ cmp_op0, cmp_op1)));
+
+ /* Change comparison semantic into (eq X 0) or (ne X 0) behavior
+ so that cmovz or cmovn will be matched later.
+
+ For reverse condition cases, we want to create a semantic that:
+ (eq X 0) --> pick up "else" part
+ For normal cases, we want to create a semantic that:
+ (ne X 0) --> pick up "then" part
+
+ Later we will have cmovz/cmovn instruction pattern to
+ match corresponding behavior and output instruction. */
+ operands[1] = gen_rtx_fmt_ee (reverse ? EQ : NE,
+ VOIDmode, tmp, const0_rtx);
+ }
+
+create_template:
+ do {} while(0); /* dummy line */
+})
+
+(define_insn "cmovz"
+ [(set (match_operand:SI 0 "register_operand" "=r, r")
+ (if_then_else:SI (eq (match_operand:SI 1 "register_operand" " r, r")
+ (const_int 0))
+ (match_operand:SI 2 "register_operand" " r, 0")
+ (match_operand:SI 3 "register_operand" " 0, r")))]
+ "TARGET_CMOV"
+ "@
+ cmovz\t%0, %2, %1
+ cmovn\t%0, %3, %1"
+ [(set_attr "type" "move")
+ (set_attr "length" "4")])
+
+(define_insn "cmovn"
+ [(set (match_operand:SI 0 "register_operand" "=r, r")
+ (if_then_else:SI (ne (match_operand:SI 1 "register_operand" " r, r")
+ (const_int 0))
+ (match_operand:SI 2 "register_operand" " r, 0")
+ (match_operand:SI 3 "register_operand" " 0, r")))]
+ "TARGET_CMOV"
+ "@
+ cmovn\t%0, %2, %1
+ cmovz\t%0, %3, %1"
+ [(set_attr "type" "move")
+ (set_attr "length" "4")])
+
+
+;; ----------------------------------------------------------------------------
+;; Conditional Branch patterns
+;; ----------------------------------------------------------------------------
+
+(define_expand "cbranchsi4"
+ [(set (pc)
+ (if_then_else (match_operator 0 "comparison_operator"
+ [(match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "nds32_reg_constant_operand" "")])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
+ ""
+{
+ rtx tmp_reg;
+ enum rtx_code code;
+
+ code = GET_CODE (operands[0]);
+
+ /* If operands[2] is (const_int 0),
+ we can use beqz,bnez,bgtz,bgez,bltz,or blez instructions.
+ So we have gcc generate original template rtx. */
+ if (GET_CODE (operands[2]) == CONST_INT)
+ if (INTVAL (operands[2]) == 0)
+ if ((code != GTU)
+ && (code != GEU)
+ && (code != LTU)
+ && (code != LEU))
+ goto create_template;
+
+ /* For other comparison, NDS32 ISA only has slt (Set-on-Less-Than)
+ behavior for the comparison, we might need to generate other
+ rtx patterns to achieve same semantic. */
+ switch (code)
+ {
+ case GT:
+ case GTU:
+ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ /* GT reg_A, const_int => !(LT reg_A, const_int + 1) */
+ tmp_reg = gen_rtx_REG (SImode, TA_REGNUM);
+
+ /* We want to plus 1 into the integer value
+ of operands[2] to create 'slt' instruction.
+ This caculation is performed on the host machine,
+ which may be 64-bit integer.
+ So the meaning of caculation result may be
+ different from the 32-bit nds32 target.
+
+ For example:
+ 0x7fffffff + 0x1 -> 0x80000000,
+ this value is POSITIVE on 64-bit machine,
+ but the expected value on 32-bit nds32 target
+ should be NEGATIVE value.
+
+ Hence, instead of using GEN_INT(), we use gen_int_mode() to
+ explicitly create SImode constant rtx. */
+ operands[2] = gen_int_mode (INTVAL (operands[2]) + 1, SImode);
+
+ if (code == GT)
+ {
+ /* GT, use slts instruction */
+ emit_insn (gen_slts_compare (tmp_reg, operands[1], operands[2]));
+ }
+ else
+ {
+ /* GTU, use slt instruction */
+ emit_insn (gen_slt_compare (tmp_reg, operands[1], operands[2]));
+ }
+
+ PUT_CODE (operands[0], EQ);
+ operands[1] = tmp_reg;
+ operands[2] = const0_rtx;
+ emit_insn (gen_cbranchsi4 (operands[0], operands[1],
+ operands[2], operands[3]));
+
+ DONE;
+ }
+ else
+ {
+ /* GT reg_A, reg_B => LT reg_B, reg_A */
+ tmp_reg = gen_rtx_REG (SImode, TA_REGNUM);
+
+ if (code == GT)
+ {
+ /* GT, use slts instruction */
+ emit_insn (gen_slts_compare (tmp_reg, operands[2], operands[1]));
+ }
+ else
+ {
+ /* GTU, use slt instruction */
+ emit_insn (gen_slt_compare (tmp_reg, operands[2], operands[1]));
+ }
+
+ PUT_CODE (operands[0], NE);
+ operands[1] = tmp_reg;
+ operands[2] = const0_rtx;
+ emit_insn (gen_cbranchsi4 (operands[0], operands[1],
+ operands[2], operands[3]));
+
+ DONE;
+ }
+
+ case GE:
+ case GEU:
+ /* GE reg_A, reg_B => !(LT reg_A, reg_B) */
+ /* GE reg_A, const_int => !(LT reg_A, const_int) */
+ tmp_reg = gen_rtx_REG (SImode, TA_REGNUM);
+
+ if (code == GE)
+ {
+ /* GE, use slts instruction */
+ emit_insn (gen_slts_compare (tmp_reg, operands[1], operands[2]));
+ }
+ else
+ {
+ /* GEU, use slt instruction */
+ emit_insn (gen_slt_compare (tmp_reg, operands[1], operands[2]));
+ }
+
+ PUT_CODE (operands[0], EQ);
+ operands[1] = tmp_reg;
+ operands[2] = const0_rtx;
+ emit_insn (gen_cbranchsi4 (operands[0], operands[1],
+ operands[2], operands[3]));
+
+ DONE;
+
+ case LT:
+ case LTU:
+ /* LT reg_A, reg_B => LT reg_A, reg_B */
+ /* LT reg_A, const_int => LT reg_A, const_int */
+ tmp_reg = gen_rtx_REG (SImode, TA_REGNUM);
+
+ if (code == LT)
+ {
+ /* LT, use slts instruction */
+ emit_insn (gen_slts_compare (tmp_reg, operands[1], operands[2]));
+ }
+ else
+ {
+ /* LTU, use slt instruction */
+ emit_insn (gen_slt_compare (tmp_reg, operands[1], operands[2]));
+ }
+
+ PUT_CODE (operands[0], NE);
+ operands[1] = tmp_reg;
+ operands[2] = const0_rtx;
+ emit_insn (gen_cbranchsi4 (operands[0], operands[1],
+ operands[2], operands[3]));
+
+ DONE;
+
+ case LE:
+ case LEU:
+ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ /* LE reg_A, const_int => LT reg_A, const_int + 1 */
+ tmp_reg = gen_rtx_REG (SImode, TA_REGNUM);
+
+ /* Note that (le:SI X INT_MAX) is not the same as (lt:SI X INT_MIN).
+ We better have an assert here in case GCC does not properly
+ optimize it away. The INT_MAX here is 0x7fffffff for target. */
+ gcc_assert (code != LE || INTVAL (operands[2]) != 0x7fffffff);
+ operands[2] = gen_int_mode (INTVAL (operands[2]) + 1, SImode);
+
+ if (code == LE)
+ {
+ /* LE, use slts instruction */
+ emit_insn (gen_slts_compare (tmp_reg, operands[1], operands[2]));
+ }
+ else
+ {
+ /* LEU, use slt instruction */
+ emit_insn (gen_slt_compare (tmp_reg, operands[1], operands[2]));
+ }
+
+ PUT_CODE (operands[0], NE);
+ operands[1] = tmp_reg;
+ operands[2] = const0_rtx;
+ emit_insn (gen_cbranchsi4 (operands[0], operands[1],
+ operands[2], operands[3]));
+
+ DONE;
+ }
+ else
+ {
+ /* LE reg_A, reg_B => !(LT reg_B, reg_A) */
+ tmp_reg = gen_rtx_REG (SImode, TA_REGNUM);
+
+ if (code == LE)
+ {
+ /* LE, use slts instruction */
+ emit_insn (gen_slts_compare (tmp_reg, operands[2], operands[1]));
+ }
+ else
+ {
+ /* LEU, use slt instruction */
+ emit_insn (gen_slt_compare (tmp_reg, operands[2], operands[1]));
+ }
+
+ PUT_CODE (operands[0], EQ);
+ operands[1] = tmp_reg;
+ operands[2] = const0_rtx;
+ emit_insn (gen_cbranchsi4 (operands[0], operands[1],
+ operands[2], operands[3]));
+
+ DONE;
+ }
+
+ case EQ:
+ case NE:
+ /* NDS32 ISA has various form for eq/ne behavior no matter
+ what kind of the operand is.
+ So just generate original template rtx. */
+ goto create_template;
+
+ default:
+ FAIL;
+ }
+
+create_template:
+ do {} while(0); /* dummy line */
+})
+
+
+(define_insn "*cbranchsi4_equality_zero"
+ [(set (pc)
+ (if_then_else (match_operator 0 "nds32_equality_comparison_operator"
+ [(match_operand:SI 1 "register_operand" "t, l, r")
+ (const_int 0)])
+ (label_ref (match_operand 2 "" ""))
+ (pc)))]
+ ""
+{
+ enum rtx_code code;
+
+ code = GET_CODE (operands[0]);
+
+ /* This zero-comparison conditional branch has two forms:
+ 32-bit instruction => beqz/bnez imm16s << 1
+ 16-bit instruction => beqzs8/bnezs8/beqz38/bnez38 imm8s << 1
+
+ For 32-bit case,
+ we assume it is always reachable. (but check range -65500 ~ 65500)
+
+ For 16-bit case,
+ it must satisfy { 255 >= (label - pc) >= -256 } condition.
+ However, since the $pc for nds32 is at the beginning of the instruction,
+ we should leave some length space for current insn.
+ So we use range -250 ~ 250. */
+
+ switch (get_attr_length (insn))
+ {
+ case 2:
+ if (which_alternative == 0)
+ {
+ /* constraint: t */
+ return (code == EQ) ? "beqzs8\t%2" : "bnezs8\t%2";
+ }
+ else if (which_alternative == 1)
+ {
+ /* constraint: l */
+ return (code == EQ) ? "beqz38\t%1, %2" : "bnez38\t%1, %2";
+ }
+ else
+ {
+ /* constraint: r */
+ /* For which_alternative==2, it should not be here. */
+ gcc_unreachable ();
+ }
+ case 4:
+ /* including constraints: t, l, and r */
+ return (code == EQ) ? "beqz\t%1, %2" : "bnez\t%1, %2";
+ case 6:
+ if (which_alternative == 0)
+ {
+ /* constraint: t */
+ if (code == EQ)
+ {
+ /* beqzs8 .L0
+ =>
+ bnezs8 .LCB0
+ j .L0
+ .LCB0:
+ */
+ return "bnezs8\t.LCB%=\;j\t%2\n.LCB%=:";
+ }
+ else
+ {
+ /* bnezs8 .L0
+ =>
+ beqzs8 .LCB0
+ j .L0
+ .LCB0:
+ */
+ return "beqzs8\t.LCB%=\;j\t%2\n.LCB%=:";
+ }
+ }
+ else if (which_alternative == 1)
+ {
+ /* constraint: l */
+ if (code == EQ)
+ {
+ /* beqz38 $r0, .L0
+ =>
+ bnez38 $r0, .LCB0
+ j .L0
+ .LCB0:
+ */
+ return "bnez38\t%1, .LCB%=\;j\t%2\n.LCB%=:";
+ }
+ else
+ {
+ /* bnez38 $r0, .L0
+ =>
+ beqz38 $r0, .LCB0
+ j .L0
+ .LCB0:
+ */
+ return "beqz38\t%1, .LCB%=\;j\t%2\n.LCB%=:";
+ }
+ }
+ else
+ {
+ /* constraint: r */
+ /* For which_alternative==2, it should not be here. */
+ gcc_unreachable ();
+ }
+ case 8:
+ /* constraint: t, l, r. */
+ if (code == EQ)
+ {
+ /* beqz $r8, .L0
+ =>
+ bnez $r8, .LCB0
+ j .L0
+ .LCB0:
+ */
+ return "bnez\t%1, .LCB%=\;j\t%2\n.LCB%=:";
+ }
+ else
+ {
+ /* bnez $r8, .L0
+ =>
+ beqz $r8, .LCB0
+ j .L0
+ .LCB0:
+ */
+ return "beqz\t%1, .LCB%=\;j\t%2\n.LCB%=:";
+ }
+ default:
+ gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "branch")
+ (set_attr "enabled" "1")
+ (set_attr_alternative "length"
+ [
+ ;; Alternative 0
+ (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -250))
+ (le (minus (match_dup 2) (pc)) (const_int 250)))
+ (if_then_else (match_test "TARGET_16_BIT")
+ (const_int 2)
+ (const_int 4))
+ (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -65500))
+ (le (minus (match_dup 2) (pc)) (const_int 65500)))
+ (const_int 4)
+ (if_then_else (match_test "TARGET_16_BIT")
+ (const_int 6)
+ (const_int 8))))
+ ;; Alternative 1
+ (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -250))
+ (le (minus (match_dup 2) (pc)) (const_int 250)))
+ (if_then_else (match_test "TARGET_16_BIT")
+ (const_int 2)
+ (const_int 4))
+ (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -65500))
+ (le (minus (match_dup 2) (pc)) (const_int 65500)))
+ (const_int 4)
+ (if_then_else (match_test "TARGET_16_BIT")
+ (const_int 6)
+ (const_int 8))))
+ ;; Alternative 2
+ (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -65500))
+ (le (minus (match_dup 2) (pc)) (const_int 65500)))
+ (const_int 4)
+ (const_int 8))
+ ])])
+
+
+;; This pattern is dedicated to V2 ISA,
+;; because V2 DOES NOT HAVE beqc/bnec instruction.
+(define_insn "*cbranchsi4_equality_reg"
+ [(set (pc)
+ (if_then_else (match_operator 0 "nds32_equality_comparison_operator"
+ [(match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "nds32_reg_constant_operand" "r")])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
+ "TARGET_ISA_V2"
+{
+ enum rtx_code code;
+
+ code = GET_CODE (operands[0]);
+
+ /* This register-comparison conditional branch has one form:
+ 32-bit instruction => beq/bne imm14s << 1
+
+ For 32-bit case,
+ we assume it is always reachable. (but check range -16350 ~ 16350). */
+
+ switch (code)
+ {
+ case EQ:
+ /* r, r */
+ switch (get_attr_length (insn))
+ {
+ case 4:
+ return "beq\t%1, %2, %3";
+ case 8:
+ /* beq $r0, $r1, .L0
+ =>
+ bne $r0, $r1, .LCB0
+ j .L0
+ .LCB0:
+ */
+ return "bne\t%1, %2, .LCB%=\;j\t%3\n.LCB%=:";
+ default:
+ gcc_unreachable ();
+ }
+
+ case NE:
+ /* r, r */
+ switch (get_attr_length (insn))
+ {
+ case 4:
+ return "bne\t%1, %2, %3";
+ case 8:
+ /* bne $r0, $r1, .L0
+ =>
+ beq $r0, $r1, .LCB0
+ j .L0
+ .LCB0:
+ */
+ return "beq\t%1, %2, .LCB%=\;j\t%3\n.LCB%=:";
+ default:
+ gcc_unreachable ();
+ }
+
+ default:
+ gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "branch")
+ (set (attr "length")
+ (if_then_else (and (ge (minus (match_dup 3) (pc)) (const_int -16350))
+ (le (minus (match_dup 3) (pc)) (const_int 16350)))
+ (const_int 4)
+ (const_int 8)))])
+
+
+;; This pattern is dedicated to V3/V3M,
+;; because V3/V3M DO HAVE beqc/bnec instruction.
+(define_insn "*cbranchsi4_equality_reg_or_const_int"
+ [(set (pc)
+ (if_then_else (match_operator 0 "nds32_equality_comparison_operator"
+ [(match_operand:SI 1 "register_operand" "r, r")
+ (match_operand:SI 2 "nds32_reg_constant_operand" "r, Is11")])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
+ "TARGET_ISA_V3 || TARGET_ISA_V3M"
+{
+ enum rtx_code code;
+
+ code = GET_CODE (operands[0]);
+
+ /* This register-comparison conditional branch has one form:
+ 32-bit instruction => beq/bne imm14s << 1
+ 32-bit instruction => beqc/bnec imm8s << 1
+
+ For 32-bit case, we assume it is always reachable.
+ (but check range -16350 ~ 16350 and -250 ~ 250). */
+
+ switch (code)
+ {
+ case EQ:
+ if (which_alternative == 0)
+ {
+ /* r, r */
+ switch (get_attr_length (insn))
+ {
+ case 4:
+ return "beq\t%1, %2, %3";
+ case 8:
+ /* beq $r0, $r1, .L0
+ =>
+ bne $r0, $r1, .LCB0
+ j .L0
+ .LCB0:
+ */
+ return "bne\t%1, %2, .LCB%=\;j\t%3\n.LCB%=:";
+ default:
+ gcc_unreachable ();
+ }
+ }
+ else
+ {
+ /* r, Is11 */
+ switch (get_attr_length (insn))
+ {
+ case 4:
+ return "beqc\t%1, %2, %3";
+ case 8:
+ /* beqc $r0, constant, .L0
+ =>
+ bnec $r0, constant, .LCB0
+ j .L0
+ .LCB0:
+ */
+ return "bnec\t%1, %2, .LCB%=\;j\t%3\n.LCB%=:";
+ default:
+ gcc_unreachable ();
+ }
+ }
+ case NE:
+ if (which_alternative == 0)
+ {
+ /* r, r */
+ switch (get_attr_length (insn))
+ {
+ case 4:
+ return "bne\t%1, %2, %3";
+ case 8:
+ /* bne $r0, $r1, .L0
+ =>
+ beq $r0, $r1, .LCB0
+ j .L0
+ .LCB0:
+ */
+ return "beq\t%1, %2, .LCB%=\;j\t%3\n.LCB%=:";
+ default:
+ gcc_unreachable ();
+ }
+ }
+ else
+ {
+ /* r, Is11 */
+ switch (get_attr_length (insn))
+ {
+ case 4:
+ return "bnec\t%1, %2, %3";
+ case 8:
+ /* bnec $r0, constant, .L0
+ =>
+ beqc $r0, constant, .LCB0
+ j .L0
+ .LCB0:
+ */
+ return "beqc\t%1, %2, .LCB%=\;j\t%3\n.LCB%=:";
+ default:
+ gcc_unreachable ();
+ }
+ }
+ default:
+ gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "branch")
+ (set_attr_alternative "length"
+ [
+ ;; Alternative 0
+ (if_then_else (and (ge (minus (match_dup 3) (pc)) (const_int -16350))
+ (le (minus (match_dup 3) (pc)) (const_int 16350)))
+ (const_int 4)
+ (const_int 8))
+ ;; Alternative 1
+ (if_then_else (and (ge (minus (match_dup 3) (pc)) (const_int -250))
+ (le (minus (match_dup 3) (pc)) (const_int 250)))
+ (const_int 4)
+ (const_int 8))
+ ])])
+
+
+(define_insn "*cbranchsi4_greater_less_zero"
+ [(set (pc)
+ (if_then_else (match_operator 0 "nds32_greater_less_comparison_operator"
+ [(match_operand:SI 1 "register_operand" "r")
+ (const_int 0)])
+ (label_ref (match_operand 2 "" ""))
+ (pc)))]
+ ""
+{
+ enum rtx_code code;
+
+ code = GET_CODE (operands[0]);
+
+ /* This zero-greater-less-comparison conditional branch has one form:
+ 32-bit instruction => bgtz/bgez/bltz/blez imm16s << 1
+
+ For 32-bit case, we assume it is always reachable.
+ (but check range -65500 ~ 65500). */
+
+ if (get_attr_length (insn) == 8)
+ {
+ /* The branch target is too far to simply use one
+ bgtz/bgez/bltz/blez instruction.
+ We need to reverse condition and use 'j' to jump to the target. */
+ switch (code)
+ {
+ case GT:
+ /* bgtz $r8, .L0
+ =>
+ blez $r8, .LCB0
+ j .L0
+ .LCB0:
+ */
+ return "blez\t%1, .LCB%=\;j\t%2\n.LCB%=:";
+ case GE:
+ /* bgez $r8, .L0
+ =>
+ bltz $r8, .LCB0
+ j .L0
+ .LCB0:
+ */
+ return "bltz\t%1, .LCB%=\;j\t%2\n.LCB%=:";
+ case LT:
+ /* bltz $r8, .L0
+ =>
+ bgez $r8, .LCB0
+ j .L0
+ .LCB0:
+ */
+ return "bgez\t%1, .LCB%=\;j\t%2\n.LCB%=:";
+ case LE:
+ /* blez $r8, .L0
+ =>
+ bgtz $r8, .LCB0
+ j .L0
+ .LCB0:
+ */
+ return "bgtz\t%1, .LCB%=\;j\t%2\n.LCB%=:";
+ default:
+ gcc_unreachable ();
+ }
+ }
+
+ switch (code)
+ {
+ case GT:
+ return "bgtz\t%1, %2";
+ case GE:
+ return "bgez\t%1, %2";
+ case LT:
+ return "bltz\t%1, %2";
+ case LE:
+ return "blez\t%1, %2";
+ default:
+ gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "branch")
+ (set (attr "length")
+ (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -65500))
+ (le (minus (match_dup 2) (pc)) (const_int 65500)))
+ (const_int 4)
+ (const_int 8)))])
+
+
+(define_expand "cstoresi4"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (match_operator:SI 1 "comparison_operator"
+ [(match_operand:SI 2 "register_operand" "")
+ (match_operand:SI 3 "nonmemory_operand" "")]))]
+ ""
+{
+ rtx tmp_reg;
+ enum rtx_code code;
+
+ code = GET_CODE (operands[1]);
+
+ switch (code)
+ {
+ case EQ:
+ if (GET_CODE (operands[3]) == CONST_INT)
+ {
+ /* reg_R = (reg_A == const_int_B)
+ --> addi reg_C, reg_A, -const_int_B
+ slti reg_R, reg_C, const_int_1 */
+ tmp_reg = gen_reg_rtx (SImode);
+ operands[3] = gen_int_mode (-INTVAL (operands[3]), SImode);
+ /* If the integer value is not in the range of imm15s,
+ we need to force register first because our addsi3 pattern
+ only accept nds32_rimm15s_operand predicate. */
+ if (!satisfies_constraint_Is15 (operands[3]))
+ operands[3] = force_reg (SImode, operands[3]);
+ emit_insn (gen_addsi3 (tmp_reg, operands[2], operands[3]));
+ emit_insn (gen_slt_compare (operands[0], tmp_reg, const1_rtx));
+
+ DONE;
+ }
+ else
+ {
+ /* reg_R = (reg_A == reg_B)
+ --> xor reg_C, reg_A, reg_B
+ slti reg_R, reg_C, const_int_1 */
+ tmp_reg = gen_reg_rtx (SImode);
+ emit_insn (gen_xorsi3 (tmp_reg, operands[2], operands[3]));
+ emit_insn (gen_slt_compare (operands[0], tmp_reg, const1_rtx));
+
+ DONE;
+ }
+
+ case NE:
+ if (GET_CODE (operands[3]) == CONST_INT)
+ {
+ /* reg_R = (reg_A != const_int_B)
+ --> addi reg_C, reg_A, -const_int_B
+ slti reg_R, const_int_0, reg_C */
+ tmp_reg = gen_reg_rtx (SImode);
+ operands[3] = gen_int_mode (-INTVAL (operands[3]), SImode);
+ /* If the integer value is not in the range of imm15s,
+ we need to force register first because our addsi3 pattern
+ only accept nds32_rimm15s_operand predicate. */
+ if (!satisfies_constraint_Is15 (operands[3]))
+ operands[3] = force_reg (SImode, operands[3]);
+ emit_insn (gen_addsi3 (tmp_reg, operands[2], operands[3]));
+ emit_insn (gen_slt_compare (operands[0], const0_rtx, tmp_reg));
+
+ DONE;
+ }
+ else
+ {
+ /* reg_R = (reg_A != reg_B)
+ --> xor reg_C, reg_A, reg_B
+ slti reg_R, const_int_0, reg_C */
+ tmp_reg = gen_reg_rtx (SImode);
+ emit_insn (gen_xorsi3 (tmp_reg, operands[2], operands[3]));
+ emit_insn (gen_slt_compare (operands[0], const0_rtx, tmp_reg));
+
+ DONE;
+ }
+
+ case GT:
+ case GTU:
+ /* reg_R = (reg_A > reg_B) --> slt reg_R, reg_B, reg_A */
+ /* reg_R = (reg_A > const_int_B) --> slt reg_R, const_int_B, reg_A */
+ if (code == GT)
+ {
+ /* GT, use slts instruction */
+ emit_insn (gen_slts_compare (operands[0], operands[3], operands[2]));
+ }
+ else
+ {
+ /* GTU, use slt instruction */
+ emit_insn (gen_slt_compare (operands[0], operands[3], operands[2]));
+ }
+
+ DONE;
+
+ case GE:
+ case GEU:
+ if (GET_CODE (operands[3]) == CONST_INT)
+ {
+ /* reg_R = (reg_A >= const_int_B)
+ --> movi reg_C, const_int_B - 1
+ slt reg_R, reg_C, reg_A */
+ tmp_reg = gen_reg_rtx (SImode);
+
+ emit_insn (gen_movsi (tmp_reg,
+ gen_int_mode (INTVAL (operands[3]) - 1,
+ SImode)));
+ if (code == GE)
+ {
+ /* GE, use slts instruction */
+ emit_insn (gen_slts_compare (operands[0], tmp_reg, operands[2]));
+ }
+ else
+ {
+ /* GEU, use slt instruction */
+ emit_insn (gen_slt_compare (operands[0], tmp_reg, operands[2]));
+ }
+
+ DONE;
+ }
+ else
+ {
+ /* reg_R = (reg_A >= reg_B)
+ --> slt reg_R, reg_A, reg_B
+ xori reg_R, reg_R, const_int_1 */
+ if (code == GE)
+ {
+ /* GE, use slts instruction */
+ emit_insn (gen_slts_compare (operands[0],
+ operands[2], operands[3]));
+ }
+ else
+ {
+ /* GEU, use slt instruction */
+ emit_insn (gen_slt_compare (operands[0],
+ operands[2], operands[3]));
+ }
+
+ /* perform 'not' behavior */
+ emit_insn (gen_xorsi3 (operands[0], operands[0], const1_rtx));
+
+ DONE;
+ }
+
+ case LT:
+ case LTU:
+ /* reg_R = (reg_A < reg_B) --> slt reg_R, reg_A, reg_B */
+ /* reg_R = (reg_A < const_int_B) --> slt reg_R, reg_A, const_int_B */
+ if (code == LT)
+ {
+ /* LT, use slts instruction */
+ emit_insn (gen_slts_compare (operands[0], operands[2], operands[3]));
+ }
+ else
+ {
+ /* LTU, use slt instruction */
+ emit_insn (gen_slt_compare (operands[0], operands[2], operands[3]));
+ }
+
+ DONE;
+
+ case LE:
+ case LEU:
+ if (GET_CODE (operands[3]) == CONST_INT)
+ {
+ /* reg_R = (reg_A <= const_int_B)
+ --> movi reg_C, const_int_B + 1
+ slt reg_R, reg_A, reg_C */
+ tmp_reg = gen_reg_rtx (SImode);
+
+ emit_insn (gen_movsi (tmp_reg,
+ gen_int_mode (INTVAL (operands[3]) + 1,
+ SImode)));
+ if (code == LE)
+ {
+ /* LE, use slts instruction */
+ emit_insn (gen_slts_compare (operands[0], operands[2], tmp_reg));
+ }
+ else
+ {
+ /* LEU, use slt instruction */
+ emit_insn (gen_slt_compare (operands[0], operands[2], tmp_reg));
+ }
+
+ DONE;
+ }
+ else
+ {
+ /* reg_R = (reg_A <= reg_B) --> slt reg_R, reg_B, reg_A
+ xori reg_R, reg_R, const_int_1 */
+ if (code == LE)
+ {
+ /* LE, use slts instruction */
+ emit_insn (gen_slts_compare (operands[0],
+ operands[3], operands[2]));
+ }
+ else
+ {
+ /* LEU, use slt instruction */
+ emit_insn (gen_slt_compare (operands[0],
+ operands[3], operands[2]));
+ }
+
+ /* perform 'not' behavior */
+ emit_insn (gen_xorsi3 (operands[0], operands[0], const1_rtx));
+
+ DONE;
+ }
+
+
+ default:
+ gcc_unreachable ();
+ }
+})
+
+
+(define_insn "slts_compare"
+ [(set (match_operand:SI 0 "register_operand" "=t, t, r, r")
+ (lt:SI (match_operand:SI 1 "nonmemory_operand" " d, d, r, r")
+ (match_operand:SI 2 "nonmemory_operand" " r, Iu05, r, Is15")))]
+ ""
+ "@
+ slts45\t%1, %2
+ sltsi45\t%1, %2
+ slts\t%0, %1, %2
+ sltsi\t%0, %1, %2"
+ [(set_attr "type" "compare,compare,compare,compare")
+ (set_attr "length" " 2, 2, 4, 4")])
+
+(define_insn "slt_compare"
+ [(set (match_operand:SI 0 "register_operand" "=t, t, r, r")
+ (ltu:SI (match_operand:SI 1 "nonmemory_operand" " d, d, r, r")
+ (match_operand:SI 2 "nonmemory_operand" " r, Iu05, r, Is15")))]
+ ""
+ "@
+ slt45\t%1, %2
+ slti45\t%1, %2
+ slt\t%0, %1, %2
+ slti\t%0, %1, %2"
+ [(set_attr "type" "compare,compare,compare,compare")
+ (set_attr "length" " 2, 2, 4, 4")])
+
+
+;; ----------------------------------------------------------------------------
+
+;; Unconditional and other jump instructions.
+
+(define_insn "jump"
+ [(set (pc) (label_ref (match_operand 0 "" "")))]
+ ""
+{
+ /* This unconditional jump has two forms:
+ 32-bit instruction => j imm24s << 1
+ 16-bit instruction => j8 imm8s << 1
+
+ For 32-bit case,
+ we assume it is always reachable.
+ For 16-bit case,
+ it must satisfy { 255 >= (label - pc) >= -256 } condition.
+ However, since the $pc for nds32 is at the beginning of the instruction,
+ we should leave some length space for current insn.
+ So we use range -250 ~ 250. */
+ switch (get_attr_length (insn))
+ {
+ case 2:
+ return "j8\t%0";
+ case 4:
+ return "j\t%0";
+ default:
+ gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "branch")
+ (set_attr "enabled" "1")
+ (set (attr "length")
+ (if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -250))
+ (le (minus (match_dup 0) (pc)) (const_int 250)))
+ (if_then_else (match_test "TARGET_16_BIT")
+ (const_int 2)
+ (const_int 4))
+ (const_int 4)))])
+
+(define_insn "indirect_jump"
+ [(set (pc) (match_operand:SI 0 "register_operand" "r, r"))]
+ ""
+ "@
+ jr5\t%0
+ jr\t%0"
+ [(set_attr "type" "branch,branch")
+ (set_attr "length" " 2, 4")])
+
+;; Subroutine call instruction returning no value.
+;; operands[0]: It should be a mem RTX whose address is
+;; the the address of the function.
+;; operands[1]: It is the number of bytes of arguments pushed as a const_int.
+;; operands[2]: It is the number of registers used as operands.
+
+(define_expand "call"
+ [(parallel [(call (match_operand 0 "memory_operand" "")
+ (match_operand 1))
+ (clobber (reg:SI LP_REGNUM))])]
+ ""
+ ""
+)
+
+(define_insn "*call_register"
+ [(parallel [(call (mem (match_operand:SI 0 "register_operand" "r, r"))
+ (match_operand 1))
+ (clobber (reg:SI LP_REGNUM))])]
+ ""
+ "@
+ jral5\t%0
+ jral\t%0"
+ [(set_attr "type" "branch,branch")
+ (set_attr "length" " 2, 4")])
+
+(define_insn "*call_immediate"
+ [(parallel [(call (mem (match_operand:SI 0 "immediate_operand" "i"))
+ (match_operand 1))
+ (clobber (reg:SI LP_REGNUM))])]
+ ""
+ "jal\t%0"
+ [(set_attr "type" "branch")
+ (set_attr "length" "4")])
+
+
+;; Subroutine call instruction returning a value.
+;; operands[0]: It is the hard regiser in which the value is returned.
+;; The rest three operands are the same as the
+;; three operands of the 'call' instruction.
+;; (but with numbers increased by one)
+
+(define_expand "call_value"
+ [(parallel [(set (match_operand 0)
+ (call (match_operand 1 "memory_operand" "")
+ (match_operand 2)))
+ (clobber (reg:SI LP_REGNUM))])]
+ ""
+ ""
+)
+
+(define_insn "*call_value_register"
+ [(parallel [(set (match_operand 0)
+ (call (mem (match_operand:SI 1 "register_operand" "r, r"))
+ (match_operand 2)))
+ (clobber (reg:SI LP_REGNUM))])]
+ ""
+ "@
+ jral5\t%1
+ jral\t%1"
+ [(set_attr "type" "branch,branch")
+ (set_attr "length" " 2, 4")])
+
+(define_insn "*call_value_immediate"
+ [(parallel [(set (match_operand 0)
+ (call (mem (match_operand:SI 1 "immediate_operand" "i"))
+ (match_operand 2)))
+ (clobber (reg:SI LP_REGNUM))])]
+ ""
+ "jal\t%1"
+ [(set_attr "type" "branch")
+ (set_attr "length" "4")])
+
+
+;; prologue and epilogue.
+
+(define_expand "prologue" [(const_int 0)]
+ ""
+{
+ /* Note that only under V3/V3M ISA, we could use v3push prologue. */
+ if (TARGET_V3PUSH)
+ nds32_expand_prologue_v3push ();
+ else
+ nds32_expand_prologue ();
+ DONE;
+})
+
+(define_expand "epilogue" [(const_int 0)]
+ ""
+{
+ /* Note that only under V3/V3M ISA, we could use v3pop epilogue. */
+ if (TARGET_V3PUSH)
+ nds32_expand_epilogue_v3pop ();
+ else
+ nds32_expand_epilogue ();
+ DONE;
+})
+
+
+;; nop instruction.
+
+(define_insn "nop"
+ [(const_int 0)]
+ ""
+{
+ if (TARGET_16_BIT)
+ return "nop16";
+ else
+ return "nop";
+}
+ [(set_attr "type" "misc")
+ (set_attr "enabled" "1")
+ (set (attr "length")
+ (if_then_else (match_test "TARGET_16_BIT")
+ (const_int 2)
+ (const_int 4)))])
+
+
+;; ----------------------------------------------------------------------------
+;; Stack push/pop operations
+;; ----------------------------------------------------------------------------
+
+;; The pattern for stack push.
+;; Both stack_push_multiple and stack_v3push use the following pattern.
+;; So we need to use TARGET_V3PUSH to determine the instruction length.
+(define_insn "*stack_push"
+ [(match_parallel 0 "nds32_stack_push_operation"
+ [(set (mem:SI (plus:SI (reg:SI SP_REGNUM)
+ (match_operand:SI 1 "const_int_operand" "")))
+ (match_operand:SI 2 "register_operand" ""))
+ ])]
+ ""
+{
+ return nds32_output_stack_push ();
+}
+ [(set_attr "type" "misc")
+ (set_attr "enabled" "1")
+ (set (attr "length")
+ (if_then_else (match_test "TARGET_V3PUSH")
+ (const_int 2)
+ (const_int 4)))])
+
+
+;; The pattern for stack pop.
+;; Both stack_pop_multiple and stack_v3pop use the following pattern.
+;; So we need to use TARGET_V3PUSH to determine the instruction length.
+(define_insn "*stack_pop"
+ [(match_parallel 0 "nds32_stack_pop_operation"
+ [(set (match_operand:SI 1 "register_operand" "")
+ (mem:SI (reg:SI SP_REGNUM)))
+ ])]
+ ""
+{
+ return nds32_output_stack_pop ();
+}
+ [(set_attr "type" "misc")
+ (set_attr "enabled" "1")
+ (set (attr "length")
+ (if_then_else (match_test "TARGET_V3PUSH")
+ (const_int 2)
+ (const_int 4)))])
+
+
+;; ----------------------------------------------------------------------------
+;; unspec operation patterns
+;; ----------------------------------------------------------------------------
+
+;; In nds32 target, the 'ret5' instuction is actually 'jr5 $lp'.
+;; This pattern is designed to distinguish function return
+;; from general indirect_jump pattern so that we can directly
+;; generate 'ret5' for readability.
+
+(define_insn "unspec_volatile_func_return"
+ [(set (pc)
+ (unspec_volatile:SI [(reg:SI LP_REGNUM)] UNSPEC_VOLATILE_FUNC_RETURN))]
+ ""
+{
+ if (TARGET_16_BIT)
+ return "ret5";
+ else
+ return "ret";
+}
+ [(set_attr "type" "misc")
+ (set_attr "enabled" "1")
+ (set (attr "length")
+ (if_then_else (match_test "TARGET_16_BIT")
+ (const_int 2)
+ (const_int 4)))])
+
+
+;; ----------------------------------------------------------------------------
+;; Jump Table patterns
+;; ----------------------------------------------------------------------------
+;; Need to implement ASM_OUTPUT_ADDR_VEC_ELT (for normal jump table)
+;; or ASM_OUTPUT_ADDR_DIFF_ELT (for pc relative jump table) as well.
+;;
+;; operands[0]: The index to dispatch on.
+;; operands[1]: The lower bound for indices in the table.
+;; operands[2]: The total range of indices int the table.
+;; i.e. The largest index minus the smallest one.
+;; operands[3]: A label that precedes the table itself.
+;; operands[4]: A label to jump to if the index has a value outside the bounds.
+;;
+;; We need to create following sequences for jump table code generation:
+;; A) k <-- (plus (operands[0]) (-operands[1]))
+;; B) if (gtu k operands[2]) then goto operands[4]
+;; C) t <-- operands[3]
+;; D) z <-- (mem (plus (k << 0 or 1 or 2) t))
+;; E) z <-- t + z (NOTE: This is only required for pc relative jump table.)
+;; F) jump to target with register t or z
+;;
+;; The steps C, D, E, and F are performed by casesi_internal pattern.
+(define_expand "casesi"
+ [(match_operand:SI 0 "register_operand" "r") ; index to jump on
+ (match_operand:SI 1 "immediate_operand" "i") ; lower bound
+ (match_operand:SI 2 "immediate_operand" "i") ; total range
+ (match_operand:SI 3 "" "") ; table label
+ (match_operand:SI 4 "" "")] ; Out of range label
+ ""
+{
+ rtx add_tmp;
+ rtx reg, test;
+
+ /* Step A: "k <-- (plus (operands[0]) (-operands[1]))". */
+ if (operands[1] != const0_rtx)
+ {
+ reg = gen_reg_rtx (SImode);
+ add_tmp = gen_int_mode (-INTVAL (operands[1]), SImode);
+
+ /* If the integer value is not in the range of imm15s,
+ we need to force register first because our addsi3 pattern
+ only accept nds32_rimm15s_operand predicate. */
+ add_tmp = force_reg (SImode, add_tmp);
+
+ emit_insn (gen_addsi3 (reg, operands[0], add_tmp));
+ operands[0] = reg;
+ }
+
+ /* Step B: "if (gtu k operands[2]) then goto operands[4]". */
+ test = gen_rtx_GTU (VOIDmode, operands[0], operands[2]);
+ emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[2],
+ operands[4]));
+
+ operands[5] = gen_reg_rtx (SImode);
+ /* Step C, D, E, and F, using another temporary register operands[5]. */
+ emit_jump_insn (gen_casesi_internal (operands[0],
+ operands[3],
+ operands[5]));
+ DONE;
+})
+
+;; We are receiving operands from casesi pattern:
+;;
+;; operands[0]: The index that have been substracted with lower bound.
+;; operands[1]: A label that precedes the table itself.
+;; operands[2]: A temporary register to retrieve value in table.
+;;
+;; We need to perform steps C, D, E, and F:
+;;
+;; C) t <-- operands[1]
+;; D) z <-- (mem (plus (operands[0] << m) t))
+;; m is 2 for normal jump table.
+;; m is 0, 1, or 2 for pc relative jump table based on diff size.
+;; E) t <-- z + t (NOTE: This is only required for pc relative jump table.)
+;; F) Jump to target with register t or z.
+;;
+;; The USE in this pattern is needed to tell flow analysis that this is
+;; a CASESI insn. It has no other purpose.
+(define_insn "casesi_internal"
+ [(parallel [(set (pc)
+ (mem:SI (plus:SI (mult:SI (match_operand:SI 0 "register_operand" "r")
+ (const_int 4))
+ (label_ref (match_operand 1 "" "")))))
+ (use (label_ref (match_dup 1)))
+ (clobber (match_operand:SI 2 "register_operand" ""))
+ (clobber (reg:SI TA_REGNUM))])]
+ ""
+{
+ if (CASE_VECTOR_PC_RELATIVE)
+ return nds32_output_casesi_pc_relative (operands);
+ else
+ return nds32_output_casesi (operands);
+}
+ [(set_attr "length" "20")
+ (set_attr "type" "alu")])
+
+;; ----------------------------------------------------------------------------
+
+;; Performance Extension
+
+(define_insn "clzsi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (clz:SI (match_operand:SI 1 "register_operand" " r")))]
+ "TARGET_PERF_EXT"
+ "clz\t%0, %1"
+ [(set_attr "type" "alu")
+ (set_attr "length" "4")])
+
+(define_insn "smaxsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (smax:SI (match_operand:SI 1 "register_operand" " r")
+ (match_operand:SI 2 "register_operand" " r")))]
+ "TARGET_PERF_EXT"
+ "max\t%0, %1, %2"
+ [(set_attr "type" "alu")
+ (set_attr "length" "4")])
+
+(define_insn "sminsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (smin:SI (match_operand:SI 1 "register_operand" " r")
+ (match_operand:SI 2 "register_operand" " r")))]
+ "TARGET_PERF_EXT"
+ "min\t%0, %1, %2"
+ [(set_attr "type" "alu")
+ (set_attr "length" "4")])
+
+(define_insn "*btst"
+ [(set (match_operand:SI 0 "register_operand" "= r")
+ (zero_extract:SI (match_operand:SI 1 "register_operand" " r")
+ (const_int 1)
+ (match_operand:SI 2 "immediate_operand" " Iu05")))]
+ "TARGET_PERF_EXT"
+ "btst\t%0, %1, %2"
+ [(set_attr "type" "alu")
+ (set_attr "length" "4")])
+
+;; ----------------------------------------------------------------------------
diff --git a/gcc/config/nds32/nds32.opt b/gcc/config/nds32/nds32.opt
new file mode 100644
index 00000000000..b2b45bb3e02
--- /dev/null
+++ b/gcc/config/nds32/nds32.opt
@@ -0,0 +1,102 @@
+; Options of Andes NDS32 cpu for GNU compiler
+; Copyright (C) 2012-2013 Free Software Foundation, Inc.
+; Contributed by Andes Technology Corporation.
+;
+; This file is part of GCC.
+;
+; GCC is free software; you can redistribute it and/or modify it
+; under the terms of the GNU General Public License as published
+; by the Free Software Foundation; either version 3, or (at your
+; option) any later version.
+;
+; GCC is distributed in the hope that it will be useful, but WITHOUT
+; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+; License for more details.
+;
+; You should have 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/nds32/nds32-opts.h
+
+mbig-endian
+Target Report RejectNegative Negative(mlittle-endian) Mask(BIG_ENDIAN)
+Generate code in big-endian mode.
+
+mlittle-endian
+Target Report RejectNegative Negative(mbig-endian) InverseMask(BIG_ENDIAN)
+Generate code in little-endian mode.
+
+mreduced-regs
+Target Report RejectNegative Negative(mfull-regs) Mask(REDUCED_REGS)
+Use reduced-set registers for register allocation.
+
+mfull-regs
+Target Report RejectNegative Negative(mreduced-regs) InverseMask(REDUCED_REGS)
+Use full-set registers for register allocation.
+
+mcmov
+Target Report Mask(CMOV)
+Generate conditional move instructions.
+
+mperf-ext
+Target Report Mask(PERF_EXT)
+Generate performance extension instructions.
+
+mv3push
+Target Report Mask(V3PUSH)
+Generate v3 push25/pop25 instructions.
+
+m16-bit
+Target Report Mask(16_BIT)
+Generate 16-bit instructions.
+
+mgp-direct
+Target Report Mask(GP_DIRECT)
+Generate GP base instructions directly.
+
+misr-vector-size=
+Target RejectNegative Joined UInteger Var(nds32_isr_vector_size) Init(NDS32_DEFAULT_ISR_VECTOR_SIZE)
+Specify the size of each interrupt vector, which must be 4 or 16.
+
+mcache-block-size=
+Target RejectNegative Joined UInteger Var(nds32_cache_block_size) Init(NDS32_DEFAULT_CACHE_BLOCK_SIZE)
+Specify the size of each cache block, which must be a power of 2 between 4 and 512.
+
+march=
+Target RejectNegative Joined Enum(nds32_arch_type) Var(nds32_arch_option) Init(ARCH_V3)
+Specify the name of the target architecture.
+
+Enum
+Name(nds32_arch_type) Type(enum nds32_arch_type)
+
+EnumValue
+Enum(nds32_arch_type) String(v2) Value(ARCH_V2)
+
+EnumValue
+Enum(nds32_arch_type) String(v3) Value(ARCH_V3)
+
+EnumValue
+Enum(nds32_arch_type) String(v3m) Value(ARCH_V3M)
+
+mforce-fp-as-gp
+Target Report Mask(FORCE_FP_AS_GP)
+Prevent $fp being allocated during register allocation so that compiler is able to force performing fp-as-gp optimization.
+
+mforbid-fp-as-gp
+Target Report Mask(FORBID_FP_AS_GP)
+Forbid using $fp to access static and global variables. This option strictly forbids fp-as-gp optimization regardless of '-mforce-fp-as-gp'.
+
+mex9
+Target Report Mask(EX9)
+Use special directives to guide linker doing ex9 optimization.
+
+mctor-dtor
+Target Report
+Enable constructor/destructor feature.
+
+mrelax
+Target Report
+Guide linker to relax instructions.
diff --git a/gcc/config/nds32/nds32_intrinsic.h b/gcc/config/nds32/nds32_intrinsic.h
new file mode 100644
index 00000000000..33064a966ed
--- /dev/null
+++ b/gcc/config/nds32/nds32_intrinsic.h
@@ -0,0 +1,37 @@
+/* Intrinsic definitions of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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 _NDS32_INTRINSIC_H
+#define _NDS32_INTRINSIC_H
+
+enum nds32_intrinsic_registers
+{
+ __NDS32_REG_PSW__ = 1024,
+ __NDS32_REG_IPSW__,
+ __NDS32_REG_ITYPE__,
+ __NDS32_REG_IPC__
+};
+
+#endif /* nds32_intrinsic.h */
diff --git a/gcc/config/nds32/pipelines.md b/gcc/config/nds32/pipelines.md
new file mode 100644
index 00000000000..9c8c56bab83
--- /dev/null
+++ b/gcc/config/nds32/pipelines.md
@@ -0,0 +1,29 @@
+;; Pipeline descriptions of Andes NDS32 cpu for GNU compiler
+;; Copyright (C) 2012-2013 Free Software Foundation, Inc.
+;; Contributed by Andes Technology Corporation.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 3, or (at your
+;; option) any later version.
+;;
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+;; License for more details.
+;;
+;; You should have 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_automaton "nds32_machine")
+
+(define_cpu_unit "general_unit" "nds32_machine")
+
+(define_insn_reservation "simple_insn" 1
+ (eq_attr "type" "unknown,load,store,move,alu,compare,branch,call,misc")
+ "general_unit")
+
+;; ------------------------------------------------------------------------
diff --git a/gcc/config/nds32/predicates.md b/gcc/config/nds32/predicates.md
new file mode 100644
index 00000000000..df4eccdb891
--- /dev/null
+++ b/gcc/config/nds32/predicates.md
@@ -0,0 +1,92 @@
+;; Predicate definitions of Andes NDS32 cpu for GNU compiler
+;; Copyright (C) 2012-2013 Free Software Foundation, Inc.
+;; Contributed by Andes Technology Corporation.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 3, or (at your
+;; option) any later version.
+;;
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+;; License for more details.
+;;
+;; You should have 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_predicate "nds32_equality_comparison_operator"
+ (match_code "eq,ne"))
+
+(define_predicate "nds32_greater_less_comparison_operator"
+ (match_code "gt,ge,lt,le"))
+
+(define_special_predicate "nds32_logical_binary_operator"
+ (match_code "and,ior,xor"))
+
+(define_predicate "nds32_symbolic_operand"
+ (match_code "const,symbol_ref,label_ref"))
+
+(define_predicate "nds32_reg_constant_operand"
+ (ior (match_operand 0 "register_operand")
+ (match_operand 0 "const_int_operand")))
+
+(define_predicate "nds32_rimm15s_operand"
+ (ior (match_operand 0 "register_operand")
+ (and (match_operand 0 "const_int_operand")
+ (match_test "satisfies_constraint_Is15 (op)"))))
+
+(define_predicate "nds32_imm5u_operand"
+ (and (match_operand 0 "const_int_operand")
+ (match_test "satisfies_constraint_Iu05 (op)")))
+
+(define_predicate "nds32_move_operand"
+ (and (match_operand 0 "general_operand")
+ (not (match_code "high,const,symbol_ref,label_ref")))
+{
+ /* If the constant op does NOT satisfy Is20 nor Ihig,
+ we can not perform move behavior by a single instruction. */
+ if (CONST_INT_P (op)
+ && !satisfies_constraint_Is20 (op)
+ && !satisfies_constraint_Ihig (op))
+ return false;
+
+ return true;
+})
+
+(define_special_predicate "nds32_load_multiple_operation"
+ (match_code "parallel")
+{
+ /* To verify 'load' operation, pass 'true' for the second argument.
+ See the implementation in nds32.c for details. */
+ return nds32_valid_multiple_load_store (op, true);
+})
+
+(define_special_predicate "nds32_store_multiple_operation"
+ (match_code "parallel")
+{
+ /* To verify 'store' operation, pass 'false' for the second argument.
+ See the implementation in nds32.c for details. */
+ return nds32_valid_multiple_load_store (op, false);
+})
+
+(define_special_predicate "nds32_stack_push_operation"
+ (match_code "parallel")
+{
+ /* To verify 'push' operation, pass 'true' for the second argument.
+ See the implementation in nds32.c for details. */
+ return nds32_valid_stack_push_pop (op, true);
+})
+
+(define_special_predicate "nds32_stack_pop_operation"
+ (match_code "parallel")
+{
+ /* To verify 'pop' operation, pass 'false' for the second argument.
+ See the implementation in nds32.c for details. */
+ return nds32_valid_stack_push_pop (op, false);
+})
+
+;; ------------------------------------------------------------------------
diff --git a/gcc/config/nds32/t-mlibs b/gcc/config/nds32/t-mlibs
new file mode 100644
index 00000000000..ec546e48c1b
--- /dev/null
+++ b/gcc/config/nds32/t-mlibs
@@ -0,0 +1,38 @@
+# The multilib settings of Andes NDS32 cpu for GNU compiler
+# Copyright (C) 2012-2013 Free Software Foundation, Inc.
+# Contributed by Andes Technology Corporation.
+#
+# This file is part of GCC.
+#
+# GCC is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published
+# by the Free Software Foundation; either version 3, or (at your
+# option) any later version.
+#
+# GCC is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+# License for more details.
+#
+# You should have 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 need to build following multilibs combinations:
+#
+# 1. <None multilibs>
+# 2. -mlittle-endian
+# 3. -mbig-endian
+# 4. -mgp-direct
+# 5. -mno-gp-direct
+# 6. -mlittle-endian -mgp-direct
+# 7. -mlittle-endian -mno-gp-direct
+# 8. -mbig-endian -mgp-direct
+# 9. -mlittle-endian -mno-gp-direct
+#
+# We also define a macro MULTILIB_DEFAULTS in nds32.h that tells the
+# driver program which options are defaults for this target and thus
+# do not need to be handled specially.
+MULTILIB_OPTIONS = mlittle-endian/mbig-endian mgp-direct/mno-gp-direct
+
+# ------------------------------------------------------------------------
diff --git a/gcc/config/pa/pa-hpux11.h b/gcc/config/pa/pa-hpux11.h
index c217398729a..4da1b096a50 100644
--- a/gcc/config/pa/pa-hpux11.h
+++ b/gcc/config/pa/pa-hpux11.h
@@ -120,7 +120,8 @@ along with GCC; see the file COPYING3. If not see
#undef LIB_SPEC
#define LIB_SPEC \
"%{!shared:\
- %{fopenmp:%{static:-a archive_shared} -lrt %{static:-a archive}}\
+ %{fopenmp|ftree-parallelize-loops=*:%{static:-a archive_shared} -lrt\
+ %{static:-a archive}}\
%{mt|pthread:-lpthread} -lc\
%{static:%{!nolibdld:-a archive_shared -ldld -a archive -lc}\
%{!mt:%{!pthread:-a shared -lc -a archive}}}}\
diff --git a/gcc/config/pa/pa-linux.h b/gcc/config/pa/pa-linux.h
index fd4d22a7aad..c20c7ccd02f 100644
--- a/gcc/config/pa/pa-linux.h
+++ b/gcc/config/pa/pa-linux.h
@@ -22,6 +22,9 @@ along with GCC; see the file COPYING3. If not see
#define TARGET_OS_CPP_BUILTINS() \
do \
{ \
+ builtin_define ("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1"); \
+ builtin_define ("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2"); \
+ builtin_define ("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4"); \
GNU_USER_TARGET_OS_CPP_BUILTINS(); \
builtin_assert ("machine=bigendian"); \
} \
diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c
index b6f54108214..260830f00d7 100644
--- a/gcc/config/pa/pa.c
+++ b/gcc/config/pa/pa.c
@@ -513,6 +513,12 @@ pa_option_override (void)
write_symbols = NO_DEBUG;
}
+#ifdef AUTO_INC_DEC
+ /* FIXME: Disable auto increment and decrement processing until reload
+ is completed. See PR middle-end 56791. */
+ flag_auto_inc_dec = reload_completed;
+#endif
+
/* We only support the "big PIC" model now. And we always generate PIC
code when in 64bit mode. */
if (flag_pic == 1 || TARGET_64BIT)
diff --git a/gcc/config/pa/pa.md b/gcc/config/pa/pa.md
index 80c4d43401d..c990950f111 100644
--- a/gcc/config/pa/pa.md
+++ b/gcc/config/pa/pa.md
@@ -836,7 +836,7 @@
[(match_operand:SI 1 "reg_or_0_operand" "rM")
(match_operand:SI 2 "arith11_operand" "rI")]))]
""
- "{com%I2clr|cmp%I2clr},%B3 %2,%1,%0\;ldi 1,%0"
+ "{com%I2clr|cmp%I2clr},%B3 %2,%r1,%0\;ldi 1,%0"
[(set_attr "type" "binary")
(set_attr "length" "8")])
@@ -846,7 +846,7 @@
[(match_operand:DI 1 "reg_or_0_operand" "rM")
(match_operand:DI 2 "arith11_operand" "rI")]))]
"TARGET_64BIT"
- "cmp%I2clr,*%B3 %2,%1,%0\;ldi 1,%0"
+ "cmp%I2clr,*%B3 %2,%r1,%0\;ldi 1,%0"
[(set_attr "type" "binary")
(set_attr "length" "8")])
@@ -859,7 +859,7 @@
[(match_operand:SI 4 "reg_or_0_operand" "rM")
(match_operand:SI 5 "arith11_operand" "rI")])))]
""
- "{com%I2clr|cmp%I2clr},%S3 %2,%1,%%r0\;{com%I5clr|cmp%I5clr},%B6 %5,%4,%0\;ldi 1,%0"
+ "{com%I2clr|cmp%I2clr},%S3 %2,%r1,%%r0\;{com%I5clr|cmp%I5clr},%B6 %5,%r4,%0\;ldi 1,%0"
[(set_attr "type" "binary")
(set_attr "length" "12")])
@@ -872,7 +872,7 @@
[(match_operand:DI 4 "reg_or_0_operand" "rM")
(match_operand:DI 5 "arith11_operand" "rI")])))]
"TARGET_64BIT"
- "cmp%I2clr,*%S3 %2,%1,%%r0\;cmp%I5clr,*%B6 %5,%4,%0\;ldi 1,%0"
+ "cmp%I2clr,*%S3 %2,%r1,%%r0\;cmp%I5clr,*%B6 %5,%r4,%0\;ldi 1,%0"
[(set_attr "type" "binary")
(set_attr "length" "12")])
@@ -884,7 +884,7 @@
[(match_operand:SI 1 "reg_or_0_operand" "rM")
(match_operand:SI 2 "arith11_operand" "rI")])))]
""
- "{com%I2clr|cmp%I2clr},%B3 %2,%1,%0\;ldi -1,%0"
+ "{com%I2clr|cmp%I2clr},%B3 %2,%r1,%0\;ldi -1,%0"
[(set_attr "type" "binary")
(set_attr "length" "8")])
@@ -894,7 +894,7 @@
[(match_operand:DI 1 "reg_or_0_operand" "rM")
(match_operand:DI 2 "arith11_operand" "rI")])))]
"TARGET_64BIT"
- "cmp%I2clr,*%B3 %2,%1,%0\;ldi -1,%0"
+ "cmp%I2clr,*%B3 %2,%r1,%0\;ldi -1,%0"
[(set_attr "type" "binary")
(set_attr "length" "8")])
diff --git a/gcc/config/pa/pa64-hpux.h b/gcc/config/pa/pa64-hpux.h
index a3e21d3b6a0..9efc137c89e 100644
--- a/gcc/config/pa/pa64-hpux.h
+++ b/gcc/config/pa/pa64-hpux.h
@@ -58,19 +58,22 @@ along with GCC; see the file COPYING3. If not see
#if ((TARGET_DEFAULT | TARGET_CPU_DEFAULT) & MASK_GNU_LD)
#define LIB_SPEC \
"%{!shared:\
- %{!p:%{!pg:%{fopenmp:%{static:-a shared} -lrt %{static:-a archive}}\
+ %{!p:%{!pg:%{fopenmp|ftree-parallelize-loops=*:%{static:-a shared} -lrt\
+ %{static:-a archive}}\
%{mt|pthread:-lpthread} -lc\
%{static:%{!nolibdld:-a shared -ldld -a archive -lc}\
%{!mt:%{!pthread:-a shared -lc -a archive}}}}}\
%{p:%{!pg:%{static:%{!mhp-ld:-a shared}%{mhp-ld:-a archive_shared}}\
-lprof %{static:-a archive}\
- %{fopenmp:%{static:-a shared} -lrt %{static:-a archive}}\
+ %{fopenmp|ftree-parallelize-loops=*:%{static:-a shared} -lrt\
+ %{static:-a archive}}\
%{mt|pthread:-lpthread} -lc\
%{static:%{!nolibdld:-a shared -ldld -a archive -lc}\
%{!mt:%{!pthread:-a shared -lc -a archive}}}}}\
%{pg:%{static:%{!mhp-ld:-a shared}%{mhp-ld:-a archive_shared}}\
-lgprof %{static:-a archive}\
- %{fopenmp:%{static:-a shared} -lrt %{static:-a archive}}\
+ %{fopenmp|ftree-parallelize-loops=*:%{static:-a shared} -lrt\
+ %{static:-a archive}}\
%{mt|pthread:-lpthread} -lc\
%{static:%{!nolibdld:-a shared -ldld -a archive -lc}\
%{!mt:%{!pthread:-a shared -lc -a archive}}}}}\
@@ -78,19 +81,22 @@ along with GCC; see the file COPYING3. If not see
#else
#define LIB_SPEC \
"%{!shared:\
- %{!p:%{!pg:%{fopenmp:%{static:-a shared} -lrt %{static:-a archive}}\
+ %{!p:%{!pg:%{fopenmp|ftree-parallelize-loops=*:%{static:-a shared} -lrt\
+ %{static:-a archive}}\
%{mt|pthread:-lpthread} -lc\
%{static:%{!nolibdld:-a shared -ldld -a archive -lc}\
%{!mt:%{!pthread:-a shared -lc -a archive}}}}}\
%{p:%{!pg:%{static:%{mgnu-ld:-a shared}%{!mgnu-ld:-a archive_shared}}\
-lprof %{static:-a archive}\
- %{fopenmp:%{static:-a shared} -lrt %{static:-a archive}}\
+ %{fopenmp|ftree-parallelize-loops=*:%{static:-a shared} -lrt\
+ %{static:-a archive}}\
%{mt|pthread:-lpthread} -lc\
%{static:%{!nolibdld:-a shared -ldld -a archive -lc}\
%{!mt:%{!pthread:-a shared -lc -a archive}}}}}\
%{pg:%{static:%{mgnu-ld:-a shared}%{!mgnu-ld:-a archive_shared}}\
-lgprof %{static:-a archive}\
- %{fopenmp:%{static:-a shared} -lrt %{static:-a archive}}\
+ %{fopenmp|ftree-parallelize-loops=*:%{static:-a shared} -lrt\
+ %{static:-a archive}}\
%{mt|pthread:-lpthread} -lc\
%{static:%{!nolibdld:-a shared -ldld -a archive -lc}\
%{!mt:%{!pthread:-a shared -lc -a archive}}}}}\
diff --git a/gcc/config/pdp11/pdp11.c b/gcc/config/pdp11/pdp11.c
index a5658bfa06b..0a310c50d79 100644
--- a/gcc/config/pdp11/pdp11.c
+++ b/gcc/config/pdp11/pdp11.c
@@ -40,6 +40,7 @@ along with GCC; see the file COPYING3. If not see
#include "target-def.h"
#include "df.h"
#include "opts.h"
+#include "dbxout.h"
/* this is the current value returned by the macro FIRST_PARM_OFFSET
defined in tm.h */
diff --git a/gcc/config/picochip/picochip.c b/gcc/config/picochip/picochip.c
index e8575ace160..f10d1cea830 100644
--- a/gcc/config/picochip/picochip.c
+++ b/gcc/config/picochip/picochip.c
@@ -60,6 +60,7 @@ along with GCC; see the file COPYING3. If not, see
#include "timevar.h" /* For TV_SCHED2, in picochip_reorg. */
#include "libfuncs.h" /* For memcpy_libfuncs, etc. */
#include "df.h" /* For df_regs_ever_live_df_regs_ever_live_pp, etc. */
+#include "dbxout.h"
/* Target AE ISA information. */
diff --git a/gcc/config/rl78/constraints.md b/gcc/config/rl78/constraints.md
index bb0e40c6a32..1785c666cb3 100644
--- a/gcc/config/rl78/constraints.md
+++ b/gcc/config/rl78/constraints.md
@@ -62,11 +62,13 @@
Integer constant equal to 8."
(and (match_code "const_int")
(match_test "IN_RANGE (ival, 8, 8)")))
+
(define_constraint "Iv16"
"@internal
Integer constant equal to 16."
(and (match_code "const_int")
(match_test "IN_RANGE (ival, 16, 16)")))
+
(define_constraint "Iv24"
"@internal
Integer constant equal to 24."
@@ -78,11 +80,13 @@
Integer constant in the range 9 @dots{} 15 (for shifts)."
(and (match_code "const_int")
(match_test "IN_RANGE (ival, 9, 15)")))
+
(define_constraint "Is17"
"@internal
Integer constant in the range 17 @dots{} 23 (for shifts)."
(and (match_code "const_int")
(match_test "IN_RANGE (ival, 17, 23)")))
+
(define_constraint "Is25"
"@internal
Integer constant in the range 25 @dots{} 31 (for shifts)."
@@ -216,7 +220,7 @@
)
(define_memory_constraint "Wab"
"es:[addr]"
- (match_test "rl78_es_addr (op) && satisfies_constraint_Cab (rl78_es_base (op))
+ (match_test "(rl78_es_addr (op) && satisfies_constraint_Cab (rl78_es_base (op)))
|| satisfies_constraint_Cab (op)")
)
@@ -234,7 +238,7 @@
)
(define_memory_constraint "Wbc"
"es:word16[BC]"
- (match_test "rl78_es_addr (op) && satisfies_constraint_Cbc (rl78_es_base (op))
+ (match_test "(rl78_es_addr (op) && satisfies_constraint_Cbc (rl78_es_base (op)))
|| satisfies_constraint_Cbc (op)")
)
@@ -246,7 +250,7 @@
)
(define_memory_constraint "Wde"
"es:[DE]"
- (match_test "rl78_es_addr (op) && satisfies_constraint_Cde (rl78_es_base (op))
+ (match_test "(rl78_es_addr (op) && satisfies_constraint_Cde (rl78_es_base (op)))
|| satisfies_constraint_Cde (op)")
)
@@ -258,7 +262,7 @@
)
(define_memory_constraint "Wca"
"es:[AX..HL] for calls"
- (match_test "rl78_es_addr (op) && satisfies_constraint_Cca (rl78_es_base (op))
+ (match_test "(rl78_es_addr (op) && satisfies_constraint_Cca (rl78_es_base (op)))
|| satisfies_constraint_Cca (op)")
)
@@ -266,11 +270,11 @@
"[AX..HL,r8-r31] for calls"
(and (match_code "mem")
(and (match_code "reg" "0")
- (match_test "REGNO (XEXP (op, 0)) < 31")))
+ (match_test "REGNO (XEXP (op, 0)) < 32")))
)
(define_memory_constraint "Wcv"
- "es:[AX..HL,r8-r23] for calls"
- (match_test "rl78_es_addr (op) && satisfies_constraint_Ccv (rl78_es_base (op))
+ "es:[AX..HL,r8-r31] for calls"
+ (match_test "(rl78_es_addr (op) && satisfies_constraint_Ccv (rl78_es_base (op)))
|| satisfies_constraint_Ccv (op)")
)
@@ -288,7 +292,7 @@
)
(define_memory_constraint "Wd2"
"es:word16[DE]"
- (match_test "rl78_es_addr (op) && satisfies_constraint_Cd2 (rl78_es_base (op))
+ (match_test "(rl78_es_addr (op) && satisfies_constraint_Cd2 (rl78_es_base (op)))
|| satisfies_constraint_Cd2 (op)")
)
@@ -300,7 +304,7 @@
)
(define_memory_constraint "Whl"
"es:[HL]"
- (match_test "rl78_es_addr (op) && satisfies_constraint_Chl (rl78_es_base (op))
+ (match_test "(rl78_es_addr (op) && satisfies_constraint_Chl (rl78_es_base (op)))
|| satisfies_constraint_Chl (op)")
)
@@ -314,7 +318,7 @@
)
(define_memory_constraint "Wh1"
"es:byte8[HL]"
- (match_test "rl78_es_addr (op) && satisfies_constraint_Ch1 (rl78_es_base (op))
+ (match_test "(rl78_es_addr (op) && satisfies_constraint_Ch1 (rl78_es_base (op)))
|| satisfies_constraint_Ch1 (op)")
)
@@ -325,7 +329,7 @@
)
(define_memory_constraint "Whb"
"es:[HL+B]"
- (match_test "rl78_es_addr (op) && satisfies_constraint_Chb (rl78_es_base (op))
+ (match_test "(rl78_es_addr (op) && satisfies_constraint_Chb (rl78_es_base (op)))
|| satisfies_constraint_Chb (op)")
)
@@ -343,7 +347,7 @@
)
(define_memory_constraint "Ws1"
"es:word8[SP]"
- (match_test "rl78_es_addr (op) && satisfies_constraint_Cs1 (rl78_es_base (op))
+ (match_test "(rl78_es_addr (op) && satisfies_constraint_Cs1 (rl78_es_base (op)))
|| satisfies_constraint_Cs1 (op)")
)
diff --git a/gcc/config/rl78/rl78-expand.md b/gcc/config/rl78/rl78-expand.md
index 40c416251d3..863037d7eda 100644
--- a/gcc/config/rl78/rl78-expand.md
+++ b/gcc/config/rl78/rl78-expand.md
@@ -25,33 +25,25 @@
(match_operand:QI 1 "general_operand"))]
""
{
- if (MEM_P (operand0) && MEM_P (operand1))
- operands[1] = copy_to_mode_reg (QImode, operand1);
- if (rl78_far_p (operand0) && rl78_far_p (operand1))
- operands[1] = copy_to_mode_reg (QImode, operand1);
+ if (MEM_P (operands[0]) && MEM_P (operands[1]))
+ operands[1] = copy_to_mode_reg (QImode, operands[1]);
+ if (rl78_far_p (operands[0]) && rl78_far_p (operands[1]))
+ operands[1] = copy_to_mode_reg (QImode, operands[1]);
/* FIXME: Not sure how GCC can generate (SUBREG (SYMBOL_REF)),
but it does. Since this makes no sense, reject it here. */
- if (GET_CODE (operand1) == SUBREG
- && GET_CODE (XEXP (operand1, 0)) == SYMBOL_REF)
+ if (GET_CODE (operands[1]) == SUBREG
+ && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
FAIL;
/* Similarly for (SUBREG (CONST (PLUS (SYMBOL_REF)))).
cf. g++.dg/abi/packed.C. */
- if (GET_CODE (operand1) == SUBREG
- && GET_CODE (XEXP (operand1, 0)) == CONST
- && GET_CODE (XEXP (XEXP (operand1, 0), 0)) == PLUS
- && GET_CODE (XEXP (XEXP (XEXP (operand1, 0), 0), 0)) == SYMBOL_REF)
+ if (GET_CODE (operands[1]) == SUBREG
+ && GET_CODE (XEXP (operands[1], 0)) == CONST
+ && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (XEXP (operands[1], 0), 0), 0)) == SYMBOL_REF)
FAIL;
- /* Similarly for (SUBREG (CONST (PLUS (SYMBOL_REF)))).
- cf. g++.dg/abi/packed.C. */
- if (GET_CODE (operand1) == SUBREG
- && GET_CODE (XEXP (operand1, 0)) == CONST
- && GET_CODE (XEXP (XEXP (operand1, 0), 0)) == PLUS
- && GET_CODE (XEXP (XEXP (XEXP (operand1, 0), 0), 0)) == SYMBOL_REF)
- FAIL;
-
- if (CONST_INT_P (operand1) && ! IN_RANGE (INTVAL (operand1), (-1 << 8) + 1, (1 << 8) - 1))
+ if (CONST_INT_P (operands[1]) && ! IN_RANGE (INTVAL (operands[1]), (-1 << 8) + 1, (1 << 8) - 1))
FAIL;
}
)
@@ -61,21 +53,21 @@
(match_operand:HI 1 "general_operand"))]
""
{
- if (MEM_P (operand0) && MEM_P (operand1))
- operands[1] = copy_to_mode_reg (HImode, operand1);
- if (rl78_far_p (operand0) && rl78_far_p (operand1))
- operands[1] = copy_to_mode_reg (HImode, operand1);
+ if (MEM_P (operands[0]) && MEM_P (operands[1]))
+ operands[1] = copy_to_mode_reg (HImode, operands[1]);
+ if (rl78_far_p (operands[0]) && rl78_far_p (operands[1]))
+ operands[1] = copy_to_mode_reg (HImode, operands[1]);
/* FIXME: Not sure how GCC can generate (SUBREG (SYMBOL_REF)),
but it does. Since this makes no sense, reject it here. */
- if (GET_CODE (operand1) == SUBREG
- && GET_CODE (XEXP (operand1, 0)) == SYMBOL_REF)
+ if (GET_CODE (operands[1]) == SUBREG
+ && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
FAIL;
/* Similarly for (SUBREG (CONST (PLUS (SYMBOL_REF)))). */
- if (GET_CODE (operand1) == SUBREG
- && GET_CODE (XEXP (operand1, 0)) == CONST
- && GET_CODE (XEXP (XEXP (operand1, 0), 0)) == PLUS
- && GET_CODE (XEXP (XEXP (XEXP (operand1, 0), 0), 0)) == SYMBOL_REF)
+ if (GET_CODE (operands[1]) == SUBREG
+ && GET_CODE (XEXP (operands[1], 0)) == CONST
+ && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (XEXP (operands[1], 0), 0), 0)) == SYMBOL_REF)
FAIL;
}
)
diff --git a/gcc/config/rl78/rl78-real.md b/gcc/config/rl78/rl78-real.md
index 90b380a54e4..4cf65e147a0 100644
--- a/gcc/config/rl78/rl78-real.md
+++ b/gcc/config/rl78/rl78-real.md
@@ -312,7 +312,7 @@
call\t%A1"
)
-(define_insn "cbranchqi4_real_signed"
+(define_insn "*cbranchqi4_real_signed"
[(set (pc) (if_then_else
(match_operator 0 "rl78_cmp_operator_signed"
[(match_operand:QI 1 "general_operand" "A,A,A")
@@ -321,12 +321,11 @@
(pc)))]
"rl78_real_insns_ok ()"
"@
- cmp\t%1, %2 \;xor1 CY,%1.7\;not1 CY\;sk%c0 \;br\t!!%3
- cmp\t%1, %2 \;xor1 CY,%1.7\;sk%c0 \;br\t!!%3
- cmp\t%1, %2 \;xor1 CY,%1.7\;xor1 CY,%2.7\;sk%c0 \;br\t!!%3"
+ cmp\t%1, %2 \;xor1 CY,%1.7\;not1 CY\;sk%C0 \;br\t!!%3
+ cmp\t%1, %2 \;xor1 CY,%1.7\;sk%C0 \;br\t!!%3
+ cmp\t%1, %2 \;xor1 CY,%1.7\;xor1 CY,%2.7\;sk%C0 \;br\t!!%3"
)
-
(define_insn "*cbranchqi4_real"
[(set (pc) (if_then_else
(match_operator 0 "rl78_cmp_operator_real"
@@ -336,13 +335,13 @@
(pc)))]
"rl78_real_insns_ok ()"
"@
- cmp0\t%1 \;sk%c0 \;br\t!!%3
- cmp\t%1, %2 \;sk%c0 \;br\t!!%3
- cmp\t%1, %2 \;sk%c0 \;br\t!!%3
- cmp\t%1, %2 \;sk%c0 \;br\t!!%3"
+ cmp0\t%1 \;sk%C0 \;br\t!!%3
+ cmp\t%1, %2 \;sk%C0 \;br\t!!%3
+ cmp\t%1, %2 \;sk%C0 \;br\t!!%3
+ cmp\t%1, %2 \;sk%C0 \;br\t!!%3"
)
-(define_insn "cbranchhi4_real_signed"
+(define_insn "*cbranchhi4_real_signed"
[(set (pc) (if_then_else
(match_operator 0 "rl78_cmp_operator_signed"
[(match_operand:HI 1 "general_operand" "A,A,A,vR")
@@ -351,9 +350,9 @@
(pc)))]
"rl78_real_insns_ok ()"
"@
- cmpw\t%1, %2 \;xor1 CY,%Q1.7\;not1 CY\;sk%c0 \;br\t!!%3
- cmpw\t%1, %2 \;xor1 CY,%Q1.7\;sk%c0 \;br\t!!%3
- cmpw\t%1, %2 \;xor1 CY,%Q1.7\;xor1 CY,%Q2.7\;sk%c0 \;br\t!!%3
+ cmpw\t%1, %2 \;xor1 CY,%Q1.7\;not1 CY\;sk%C0 \;br\t!!%3
+ cmpw\t%1, %2 \;xor1 CY,%Q1.7\;sk%C0 \;br\t!!%3
+ cmpw\t%1, %2 \;xor1 CY,%Q1.7\;xor1 CY,%Q2.7\;sk%C0 \;br\t!!%3
%z0\t!!%3"
)
@@ -366,7 +365,7 @@
(pc)))]
"rl78_real_insns_ok ()"
"@
- cmpw\t%1, %2 \;sk%c0 \;br\t!!%3
+ cmpw\t%1, %2 \;sk%C0 \;br\t!!%3
%z0\t!!%3"
)
@@ -378,10 +377,10 @@
(pc)
(label_ref (match_operand 3 "" ""))))]
"rl78_real_insns_ok ()"
- "cmpw\t%1, %2 \;sk%c0 \;br\t!!%3"
+ "cmpw\t%1, %2 \;sk%C0 \;br\t!!%3"
)
-(define_insn "cbranchsi4_real_lt"
+(define_insn "*cbranchsi4_real_lt"
[(set (pc) (if_then_else
(lt (match_operand:SI 0 "general_operand" "U,vWabWhlWh1")
(const_int 0))
@@ -395,7 +394,7 @@
mov1 CY,%E0.7 \;sknc \;br\t!!%1"
)
-(define_insn "cbranchsi4_real_ge"
+(define_insn "*cbranchsi4_real_ge"
[(set (pc) (if_then_else
(ge (match_operand:SI 0 "general_operand" "U,vWabWhlWh1")
(const_int 0))
@@ -409,7 +408,7 @@
mov1 CY,%E0.7 \;skc \;br\t!!%1"
)
-(define_insn "cbranchsi4_real_signed"
+(define_insn "*cbranchsi4_real_signed"
[(set (pc) (if_then_else
(match_operator 0 "rl78_cmp_operator_signed"
[(match_operand:SI 1 "nonimmediate_operand" "vU,vU,vU")
@@ -420,12 +419,12 @@
]
"rl78_real_insns_ok ()"
"@
- movw ax,%H1 \;cmpw ax, %H2 \;xor1 CY,a.7\;not1 CY\; movw ax,%h1 \;sknz \;cmpw ax, %h2 \;sk%c0 \;br\t!!%3
- movw ax,%H1 \;cmpw ax, %H2 \;xor1 CY,a.7\; movw ax,%h1 \;sknz \;cmpw ax, %h2 \;sk%c0 \;br\t!!%3
- movw ax,%H1 \;cmpw ax, %H2 \;xor1 CY,a.7\;xor1 CY,%E2.7\;movw ax,%h1 \;sknz \;cmpw ax, %h2 \;sk%c0 \;br\t!!%3"
+ movw ax,%H1 \;cmpw ax, %H2 \;xor1 CY,a.7\;not1 CY\; movw ax,%h1 \;sknz \;cmpw ax, %h2 \;sk%C0 \;br\t!!%3
+ movw ax,%H1 \;cmpw ax, %H2 \;xor1 CY,a.7\; movw ax,%h1 \;sknz \;cmpw ax, %h2 \;sk%C0 \;br\t!!%3
+ movw ax,%H1 \;cmpw ax, %H2 \;xor1 CY,a.7\;xor1 CY,%E2.7\;movw ax,%h1 \;sknz \;cmpw ax, %h2 \;sk%C0 \;br\t!!%3"
)
-(define_insn "cbranchsi4_real"
+(define_insn "*cbranchsi4_real"
[(set (pc) (if_then_else
(match_operator 0 "rl78_cmp_operator_real"
[(match_operand:SI 1 "general_operand" "vUi")
@@ -435,7 +434,7 @@
(clobber (reg:HI AX_REG))
]
"rl78_real_insns_ok ()"
- "movw ax,%H1 \;cmpw ax, %H2 \;movw ax,%h1 \;sknz \;cmpw ax, %h2 \;sk%c0 \;br\t!!%3"
+ "movw ax,%H1 \;cmpw ax, %H2 \;movw ax,%h1 \;sknz \;cmpw ax, %h2 \;sk%C0 \;br\t!!%3"
)
;; Peephole to match:
@@ -491,26 +490,62 @@
;; in the peephole not matching and the optimization being missed.
(define_peephole2
- [(set (match_operand:QI 1 "register_operand") (reg:QI A_REG))
- (set (match_dup 1) (and:QI (match_dup 1) (match_operand 2 "immediate_operand")))
- (set (pc) (if_then_else (eq (match_dup 1) (const_int 0))
- (label_ref (match_operand 3 ""))
+ [(set (match_operand:QI 0 "register_operand") (reg:QI A_REG))
+ (set (match_dup 0) (and:QI (match_dup 0) (match_operand 1 "immediate_operand")))
+ (set (pc) (if_then_else (eq (match_dup 0) (const_int 0))
+ (label_ref (match_operand 2 ""))
+ (pc)))]
+ "peep2_regno_dead_p (3, REGNO (operands[0]))
+ && exact_log2 (INTVAL (operands[1])) >= 0"
+ [(set (pc) (if_then_else (eq (and (reg:QI A_REG) (match_dup 1)) (const_int 0))
+ (label_ref (match_dup 2))
(pc)))]
- "peep2_regno_dead_p (3, REGNO (operands[1]))
- && exact_log2 (INTVAL (operands[2])) >= 0"
- [(set (pc) (if_then_else (eq (and (reg:QI A_REG) (match_dup 2)) (const_int 0))
- (label_ref (match_dup 3)) (pc)))]
)
(define_peephole2
- [(set (match_operand:QI 1 "register_operand") (reg:QI A_REG))
- (set (match_dup 1) (and:QI (match_dup 1) (match_operand 2 "immediate_operand")))
- (set (pc) (if_then_else (ne (match_dup 1) (const_int 0))
- (label_ref (match_operand 3 ""))
+ [(set (match_operand:QI 0 "register_operand") (reg:QI A_REG))
+ (set (match_dup 0) (and:QI (match_dup 0) (match_operand 1 "immediate_operand")))
+ (set (pc) (if_then_else (ne (match_dup 0) (const_int 0))
+ (label_ref (match_operand 2 ""))
(pc)))]
- "peep2_regno_dead_p (3, REGNO (operands[1]))
- && exact_log2 (INTVAL (operands[2])) >= 0"
- [(set (pc) (if_then_else (ne (and (reg:QI A_REG) (match_dup 2)) (const_int 0))
- (label_ref (match_dup 3)) (pc)))]
+ "peep2_regno_dead_p (3, REGNO (operands[0]))
+ && exact_log2 (INTVAL (operands[1])) >= 0"
+ [(set (pc) (if_then_else (ne (and (reg:QI A_REG) (match_dup 1)) (const_int 0))
+ (label_ref (match_dup 2))
+ (pc)))]
+ )
+
+;; Eliminate needless register copies.
+(define_peephole2
+ [(set (match_operand:HI 0 "register_operand") (match_operand:HI 1 "register_operand"))
+ (set (match_operand:HI 2 "register_operand") (match_dup 0))]
+ "peep2_regno_dead_p (2, REGNO (operands[0]))
+ && (REGNO (operands[1]) < 8 || REGNO (operands[2]) < 8)"
+ [(set (match_dup 2) (match_dup 1))]
+ )
+
+;; Eliminate needless register copying when performing bit manipulations.
+(define_peephole2
+ [(set (match_operand:QI 0 "register_operand") (reg:QI A_REG))
+ (set (match_dup 0) (ior:QI (match_dup 0) (match_operand 1 "immediate_operand")))
+ (set (reg:QI A_REG) (match_dup 0))]
+ "peep2_regno_dead_p (3, REGNO (operands[0]))"
+ [(set (reg:QI A_REG) (ior:QI (reg:QI A_REG) (match_dup 1)))]
+ )
+
+(define_peephole2
+ [(set (match_operand:QI 0 "register_operand") (reg:QI A_REG))
+ (set (match_dup 0) (xor:QI (match_dup 0) (match_operand 1 "immediate_operand")))
+ (set (reg:QI A_REG) (match_dup 0))]
+ "peep2_regno_dead_p (3, REGNO (operands[0]))"
+ [(set (reg:QI A_REG) (xor:QI (reg:QI A_REG) (match_dup 1)))]
+ )
+
+(define_peephole2
+ [(set (match_operand:QI 0 "register_operand") (reg:QI A_REG))
+ (set (match_dup 0) (and:QI (match_dup 0) (match_operand 1 "immediate_operand")))
+ (set (reg:QI A_REG) (match_dup 0))]
+ "peep2_regno_dead_p (3, REGNO (operands[0]))"
+ [(set (reg:QI A_REG) (and:QI (reg:QI A_REG) (match_dup 1)))]
)
diff --git a/gcc/config/rl78/rl78-virt.md b/gcc/config/rl78/rl78-virt.md
index dc50e3b34e5..74affc519f9 100644
--- a/gcc/config/rl78/rl78-virt.md
+++ b/gcc/config/rl78/rl78-virt.md
@@ -312,7 +312,7 @@
[(set_attr "valloc" "op1")]
)
-(define_insn "cbranchqi4_virt_signed"
+(define_insn "*cbranchqi4_virt_signed"
[(set (pc) (if_then_else
(match_operator 0 "rl78_cmp_operator_signed"
[(match_operand:QI 1 "general_operand" "vim")
@@ -320,7 +320,7 @@
(label_ref (match_operand 3 "" ""))
(pc)))]
"rl78_virt_insns_ok ()"
- "v.cmp\t%1, %2\\n\tv.b%c0\t%3"
+ "v.cmp\t%1, %2\\n\tv.b%C0\t%3"
[(set_attr "valloc" "cmp")]
)
@@ -332,11 +332,11 @@
(label_ref (match_operand 3 "" ""))
(pc)))]
"rl78_virt_insns_ok ()"
- "v.cmp\t%1, %2\\n\tv.b%c0\t%3"
+ "v.cmp\t%1, %2\\n\tv.b%C0\t%3"
[(set_attr "valloc" "cmp")]
)
-(define_insn "cbranchhi4_virt_signed"
+(define_insn "*cbranchhi4_virt_signed"
[(set (pc) (if_then_else
(match_operator 0 "rl78_cmp_operator_signed"
[(match_operand:HI 1 "general_operand" "vim")
@@ -344,7 +344,7 @@
(label_ref (match_operand 3 "" ""))
(pc)))]
"rl78_virt_insns_ok ()"
- "v.cmpw\t%1, %2\\n\tv.b%c0\t%3"
+ "v.cmpw\t%1, %2\\n\tv.b%C0\t%3"
[(set_attr "valloc" "cmp")]
)
@@ -356,11 +356,11 @@
(label_ref (match_operand 3 "" ""))
(pc)))]
"rl78_virt_insns_ok ()"
- "v.cmpw\t%1, %2\\n\tv.b%c0\t%3"
+ "v.cmpw\t%1, %2\\n\tv.b%C0\t%3"
[(set_attr "valloc" "cmp")]
)
-(define_insn "cbranchsi4_virt"
+(define_insn "*cbranchsi4_virt"
[(set (pc) (if_then_else
(match_operator 0 "rl78_cmp_operator"
[(match_operand:SI 1 "general_operand" "vim")
@@ -370,7 +370,7 @@
(clobber (reg:HI AX_REG))
]
"rl78_virt_insns_ok ()"
- "v.cmpd\t%1, %2\\n\tv.b%c0\t%3"
+ "v.cmpd\t%1, %2\\n\tv.b%C0\t%3"
[(set_attr "valloc" "macax")]
)
diff --git a/gcc/config/rl78/rl78.c b/gcc/config/rl78/rl78.c
index 5902e1ecd8f..f071e31daf2 100644
--- a/gcc/config/rl78/rl78.c
+++ b/gcc/config/rl78/rl78.c
@@ -170,6 +170,9 @@ make_pass_rl78_devirt (gcc::context *ctxt)
return new pass_rl78_devirt (ctxt);
}
+/* Redundant move elimination pass. Must be run after the basic block
+ reordering pass for the best effect. */
+
static unsigned int
move_elim_pass (void)
{
@@ -314,7 +317,8 @@ rl78_option_override (void)
if (TARGET_ALLREGS)
{
int i;
- for (i=24; i<32; i++)
+
+ for (i = 24; i < 32; i++)
fixed_regs[i] = 0;
}
}
@@ -442,6 +446,7 @@ rl78_expand_movsi (rtx *operands)
}
}
+/* Generate code to move an SImode value. */
void
rl78_split_movsi (rtx *operands)
{
@@ -449,6 +454,7 @@ rl78_split_movsi (rtx *operands)
op00 = rl78_subreg (HImode, operands[0], SImode, 0);
op02 = rl78_subreg (HImode, operands[0], SImode, 2);
+
if (GET_CODE (operands[1]) == CONST
|| GET_CODE (operands[1]) == SYMBOL_REF)
{
@@ -481,7 +487,6 @@ rl78_split_movsi (rtx *operands)
}
}
-
/* Used by various two-operand expanders which cannot accept all
operands in the "far" namespace. Force some such operands into
registers so that each pattern has at most one far operand. */
@@ -555,6 +560,10 @@ need_to_save (unsigned int regno)
{
if (is_interrupt_func (cfun->decl))
{
+ /* We don't know what devirt will need */
+ if (regno < 8)
+ return true;
+
/* We don't need to save registers that have
been reserved for interrupt handlers. */
if (regno > 23)
@@ -696,6 +705,10 @@ characterize_address (rtx x, rtx *base, rtx *index, rtx *addend)
*index = NULL_RTX;
*addend = NULL_RTX;
+ if (GET_CODE (x) == UNSPEC
+ && XINT (x, 1) == UNS_ES_ADDR)
+ x = XVECEXP (x, 0, 1);
+
if (GET_CODE (x) == REG)
{
*base = x;
@@ -870,13 +883,17 @@ rl78_as_legitimate_address (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x,
bool strict ATTRIBUTE_UNUSED, addr_space_t as ATTRIBUTE_UNUSED)
{
rtx base, index, addend;
+ bool is_far_addr = false;
if (GET_CODE (x) == UNSPEC
&& XINT (x, 1) == UNS_ES_ADDR)
- x = XVECEXP (x, 0, 1);
+ {
+ x = XVECEXP (x, 0, 1);
+ is_far_addr = true;
+ }
if (as == ADDR_SPACE_GENERIC
- && GET_MODE (x) == SImode)
+ && (GET_MODE (x) == SImode || is_far_addr))
return false;
if (! characterize_address (x, &base, &index, &addend))
@@ -1062,16 +1079,19 @@ rl78_expand_prologue (void)
emit_move_insn (gen_rtx_REG (HImode, 0), gen_rtx_REG (HImode, i*2));
F (emit_insn (gen_push (gen_rtx_REG (HImode, 0))));
}
- else {
- int need_bank = i/4;
- if (need_bank != rb)
- {
- emit_insn (gen_sel_rb (GEN_INT (need_bank)));
- rb = need_bank;
- }
- F (emit_insn (gen_push (gen_rtx_REG (HImode, i*2))));
- }
+ else
+ {
+ int need_bank = i/4;
+
+ if (need_bank != rb)
+ {
+ emit_insn (gen_sel_rb (GEN_INT (need_bank)));
+ rb = need_bank;
+ }
+ F (emit_insn (gen_push (gen_rtx_REG (HImode, i*2))));
+ }
}
+
if (rb != 0)
emit_insn (gen_sel_rb (GEN_INT (0)));
@@ -1281,7 +1301,8 @@ rl78_function_arg_boundary (enum machine_mode mode ATTRIBUTE_UNUSED,
S - SADDR form of a real register
v - real register corresponding to a virtual register
m - minus - negative of CONST_INT value.
- c - inverse of a conditional (NE vs EQ for example)
+ C - inverse of a conditional (NE vs EQ for example)
+ C - complement of an integer
z - collapsed conditional
s - shift count mod 8
S - shift count mod 16
@@ -1535,37 +1556,37 @@ rl78_print_operand_1 (FILE * file, rtx op, int letter)
if (letter == 'z')
fprintf (file, "#comparison eliminated");
else
- fprintf (file, letter == 'c' ? "nc" : "c");
+ fprintf (file, letter == 'C' ? "nc" : "c");
break;
case LEU:
if (letter == 'z')
fprintf (file, "br");
else
- fprintf (file, letter == 'c' ? "h" : "nh");
+ fprintf (file, letter == 'C' ? "h" : "nh");
break;
case GEU:
if (letter == 'z')
fprintf (file, "br");
else
- fprintf (file, letter == 'c' ? "c" : "nc");
+ fprintf (file, letter == 'C' ? "c" : "nc");
break;
case GTU:
if (letter == 'z')
fprintf (file, "#comparison eliminated");
else
- fprintf (file, letter == 'c' ? "nh" : "h");
+ fprintf (file, letter == 'C' ? "nh" : "h");
break;
case EQ:
if (letter == 'z')
fprintf (file, "br");
else
- fprintf (file, letter == 'c' ? "nz" : "z");
+ fprintf (file, letter == 'C' ? "nz" : "z");
break;
case NE:
if (letter == 'z')
fprintf (file, "#comparison eliminated");
else
- fprintf (file, letter == 'c' ? "z" : "nz");
+ fprintf (file, letter == 'C' ? "z" : "nz");
break;
/* Note: these assume appropriate adjustments were made so that
@@ -1575,25 +1596,25 @@ rl78_print_operand_1 (FILE * file, rtx op, int letter)
if (letter == 'z')
fprintf (file, "#comparison eliminated");
else
- fprintf (file, letter == 'c' ? "nc" : "c");
+ fprintf (file, letter == 'C' ? "nc" : "c");
break;
case LE:
if (letter == 'z')
fprintf (file, "br");
else
- fprintf (file, letter == 'c' ? "h" : "nh");
+ fprintf (file, letter == 'C' ? "h" : "nh");
break;
case GE:
if (letter == 'z')
fprintf (file, "br");
else
- fprintf (file, letter == 'c' ? "c" : "nc");
+ fprintf (file, letter == 'C' ? "c" : "nc");
break;
case GT:
if (letter == 'z')
fprintf (file, "#comparison eliminated");
else
- fprintf (file, letter == 'c' ? "nh" : "h");
+ fprintf (file, letter == 'C' ? "nh" : "h");
break;
default:
@@ -1675,6 +1696,9 @@ rl78_peep_movhi_p (rtx *operands)
/* (set (op0) (op1))
(set (op2) (op3)) */
+ if (! rl78_virt_insns_ok ())
+ return false;
+
#if DEBUG_PEEP
fprintf (stderr, "\033[33m");
debug_rtx (operands[0]);
@@ -1870,8 +1894,8 @@ post-reload optimizers could operate on the real registers, but when I
tried that there were some issues building the target libraries.
During devirtualization, a simple register move optimizer is run. It
-would be better to run a full CSE/propogation pass on it through, or
-re-run regmove, but that has not yet been attempted.
+would be better to run a full CSE/propogation pass on it though, but
+that has not yet been attempted.
*/
#define DEBUG_ALLOC 0
@@ -1947,7 +1971,6 @@ get_content_index (rtx loc)
/* Return a string describing content INDEX in mode MODE.
WARNING: Can return a pointer to a static buffer. */
-
static const char *
get_content_name (unsigned char index, enum machine_mode mode)
{
@@ -2155,9 +2178,9 @@ insn_ok_now (rtx insn)
/* We need to detect far addresses that haven't been
converted to es/lo16 format. */
for (i=0; i<recog_data.n_operands; i++)
- if (GET_CODE (OP(i)) == MEM
- && GET_MODE (XEXP (OP(i), 0)) == SImode
- && GET_CODE (XEXP (OP(i), 0)) != UNSPEC)
+ if (GET_CODE (OP (i)) == MEM
+ && GET_MODE (XEXP (OP (i), 0)) == SImode
+ && GET_CODE (XEXP (OP (i), 0)) != UNSPEC)
return false;
return true;
@@ -2166,7 +2189,7 @@ insn_ok_now (rtx insn)
else
{
/* We need to re-recog the insn with virtual registers to get
- the operands */
+ the operands. */
cfun->machine->virt_insns_ok = 1;
if (recog (pattern, insn, 0) > -1)
{
@@ -2206,22 +2229,22 @@ insn_ok_now (rtx insn)
#endif
/* Registers into which we move the contents of virtual registers. */
-#define X gen_rtx_REG (QImode, 0)
-#define A gen_rtx_REG (QImode, 1)
-#define C gen_rtx_REG (QImode, 2)
-#define B gen_rtx_REG (QImode, 3)
-#define E gen_rtx_REG (QImode, 4)
-#define D gen_rtx_REG (QImode, 5)
-#define L gen_rtx_REG (QImode, 6)
-#define H gen_rtx_REG (QImode, 7)
-
-#define AX gen_rtx_REG (HImode, 0)
-#define BC gen_rtx_REG (HImode, 2)
-#define DE gen_rtx_REG (HImode, 4)
-#define HL gen_rtx_REG (HImode, 6)
+#define X gen_rtx_REG (QImode, X_REG)
+#define A gen_rtx_REG (QImode, A_REG)
+#define C gen_rtx_REG (QImode, C_REG)
+#define B gen_rtx_REG (QImode, B_REG)
+#define E gen_rtx_REG (QImode, E_REG)
+#define D gen_rtx_REG (QImode, D_REG)
+#define L gen_rtx_REG (QImode, L_REG)
+#define H gen_rtx_REG (QImode, H_REG)
+
+#define AX gen_rtx_REG (HImode, AX_REG)
+#define BC gen_rtx_REG (HImode, BC_REG)
+#define DE gen_rtx_REG (HImode, DE_REG)
+#define HL gen_rtx_REG (HImode, HL_REG)
/* Returns TRUE if R is a virtual register. */
-static bool
+static inline bool
is_virtual_register (rtx r)
{
return (GET_CODE (r) == REG
@@ -2364,6 +2387,7 @@ gen_and_emit_move (rtx to, rtx from, rtx where, bool before)
else
add_postponed_content_update (to, from);
}
+
return before ? to : from;
}
@@ -2382,7 +2406,9 @@ transcode_memory_rtx (rtx m, rtx newbase, rtx before)
if (GET_MODE (XEXP (m, 0)) == SImode)
{
+ rtx new_m;
rtx seg = rl78_hi8 (XEXP (m, 0));
+
#if DEBUG_ALLOC
fprintf (stderr, "setting ES:\n");
debug_rtx(seg);
@@ -2391,7 +2417,9 @@ transcode_memory_rtx (rtx m, rtx newbase, rtx before)
emit_insn_before (EM (gen_movqi_es (A)), before);
record_content (A, NULL_RTX);
- m = change_address (m, GET_MODE (m), rl78_lo16 (XEXP (m, 0)));
+ new_m = gen_rtx_MEM (GET_MODE (m), rl78_lo16 (XEXP (m, 0)));
+ MEM_COPY_ATTRIBUTES (new_m, m);
+ m = new_m;
need_es = 1;
}
@@ -2465,7 +2493,6 @@ transcode_memory_rtx (rtx m, rtx newbase, rtx before)
/* Copy SRC to accumulator (A or AX), placing any generated insns
before BEFORE. Returns accumulator RTX. */
-
static rtx
move_to_acc (int opno, rtx before)
{
@@ -2500,7 +2527,6 @@ force_into_acc (rtx src, rtx before)
/* Copy accumulator (A or AX) to DEST, placing any generated insns
after AFTER. Returns accumulator RTX. */
-
static rtx
move_from_acc (unsigned int opno, rtx after)
{
@@ -2515,7 +2541,6 @@ move_from_acc (unsigned int opno, rtx after)
/* Copy accumulator (A or AX) to REGNO, placing any generated insns
before BEFORE. Returns reg RTX. */
-
static rtx
move_acc_to_reg (rtx acc, int regno, rtx before)
{
@@ -2529,7 +2554,6 @@ move_acc_to_reg (rtx acc, int regno, rtx before)
/* Copy SRC to X, placing any generated insns before BEFORE.
Returns X RTX. */
-
static rtx
move_to_x (int opno, rtx before)
{
@@ -2544,16 +2568,15 @@ move_to_x (int opno, rtx before)
if (mode == QImode || ! is_virtual_register (OP (opno)))
{
OP (opno) = move_to_acc (opno, before);
- OP (opno) = move_acc_to_reg (OP(opno), X_REG, before);
+ OP (opno) = move_acc_to_reg (OP (opno), X_REG, before);
return reg;
}
return gen_and_emit_move (reg, src, before, true);
}
-/* Copy OP(opno) to H or HL, placing any generated insns before BEFORE.
+/* Copy OP (opno) to H or HL, placing any generated insns before BEFORE.
Returns H/HL RTX. */
-
static rtx
move_to_hl (int opno, rtx before)
{
@@ -2575,9 +2598,8 @@ move_to_hl (int opno, rtx before)
return gen_and_emit_move (reg, src, before, true);
}
-/* Copy OP(opno) to E or DE, placing any generated insns before BEFORE.
+/* Copy OP (opno) to E or DE, placing any generated insns before BEFORE.
Returns E/DE RTX. */
-
static rtx
move_to_de (int opno, rtx before)
{
@@ -2802,7 +2824,6 @@ rl78_alloc_physical_registers_op2 (rtx insn)
}
}
-
OP (0) = move_from_acc (0, insn);
tmp_id = get_max_insn_count ();
@@ -2838,7 +2859,6 @@ rl78_alloc_physical_registers_op2 (rtx insn)
}
/* Devirtualize an insn of the form SET (PC) (MEM/REG). */
-
static void
rl78_alloc_physical_registers_ro1 (rtx insn)
{
@@ -2852,7 +2872,6 @@ rl78_alloc_physical_registers_ro1 (rtx insn)
}
/* Devirtualize a compare insn. */
-
static void
rl78_alloc_physical_registers_cmp (rtx insn)
{
@@ -2864,13 +2883,13 @@ rl78_alloc_physical_registers_cmp (rtx insn)
OP (1) = transcode_memory_rtx (OP (1), DE, insn);
OP (2) = transcode_memory_rtx (OP (2), HL, insn);
- /* HI compares have to have OP(1) in AX, but QI
+ /* HI compares have to have OP (1) in AX, but QI
compares do not, so it is worth checking here. */
MAYBE_OK (insn);
- /* For an HImode compare, OP(1) must always be in AX.
- But if OP(1) is a REG (and not AX), then we can avoid
- a reload of OP(1) if we reload OP(2) into AX and invert
+ /* For an HImode compare, OP (1) must always be in AX.
+ But if OP (1) is a REG (and not AX), then we can avoid
+ a reload of OP (1) if we reload OP (2) into AX and invert
the comparison. */
if (REG_P (OP (1))
&& REGNO (OP (1)) != AX_REG
@@ -2946,7 +2965,6 @@ rl78_alloc_physical_registers_cmp (rtx insn)
}
/* Like op2, but AX = A op X. */
-
static void
rl78_alloc_physical_registers_umul (rtx insn)
{
@@ -3032,7 +3050,8 @@ rl78_alloc_address_registers_macax (rtx insn)
OP (op) = transcode_memory_rtx (OP (op), HL, insn);
if (op == 2
&& MEM_P (OP (op))
- && (REGNO (XEXP (OP (op), 0)) == SP_REG
+ && ((GET_CODE (XEXP (OP (op), 0)) == REG
+ && REGNO (XEXP (OP (op), 0)) == SP_REG)
|| (GET_CODE (XEXP (OP (op), 0)) == PLUS
&& REGNO (XEXP (XEXP (OP (op), 0), 0)) == SP_REG)))
{
@@ -3054,6 +3073,7 @@ rl78_alloc_address_registers_macax (rtx insn)
which ++;
}
}
+
MUST_BE_OK (insn);
}
@@ -3121,7 +3141,8 @@ rl78_alloc_physical_registers (void)
if (GET_CODE (pattern) != SET
&& GET_CODE (pattern) != CALL)
continue;
- if (GET_CODE (SET_SRC (pattern)) == ASM_OPERANDS)
+ if (GET_CODE (pattern) == SET
+ && GET_CODE (SET_SRC (pattern)) == ASM_OPERANDS)
continue;
valloc_method = get_attr_valloc (insn);
@@ -3176,6 +3197,7 @@ rl78_alloc_physical_registers (void)
else
process_postponed_content_update ();
}
+
#if DEBUG_ALLOC
fprintf (stderr, "\033[0m");
#endif
@@ -3544,6 +3566,16 @@ rl78_propogate_register_origins (void)
}
}
}
+ else if (GET_CODE (pat) == CLOBBER)
+ {
+ if (REG_P (XEXP (pat, 0)))
+ {
+ unsigned int reg = REGNO (XEXP (pat, 0));
+
+ origins[reg] = reg;
+ age[reg] = 0;
+ }
+ }
}
}
}
@@ -3693,6 +3725,7 @@ rl78_unwind_word_mode (void)
return HImode;
}
+
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-rl78.h"
diff --git a/gcc/config/rl78/rl78.h b/gcc/config/rl78/rl78.h
index 2dfa1da7d46..3a656de626c 100644
--- a/gcc/config/rl78/rl78.h
+++ b/gcc/config/rl78/rl78.h
@@ -52,6 +52,7 @@
#undef LINK_SPEC
#define LINK_SPEC "\
%{mrelax:-relax} \
+%{!r:--gc-sections} \
"
#undef LIB_SPEC
diff --git a/gcc/config/rl78/rl78.md b/gcc/config/rl78/rl78.md
index e1cbbb03eae..a43b41b472f 100644
--- a/gcc/config/rl78/rl78.md
+++ b/gcc/config/rl78/rl78.md
@@ -142,7 +142,7 @@
(define_insn "sel_rb"
[(unspec_volatile [(match_operand 0 "immediate_operand" "")] UNS_SET_RB)]
- ""
+ "!TARGET_G10"
"sel\trb%u0"
)
diff --git a/gcc/config/rs6000/aix.h b/gcc/config/rs6000/aix.h
index f81666a3b11..a11bd57284d 100644
--- a/gcc/config/rs6000/aix.h
+++ b/gcc/config/rs6000/aix.h
@@ -66,30 +66,6 @@
/* Because of the above, we must have gcc search itself to find libgcc.a. */
#define LINK_LIBGCC_SPECIAL_1
-#define MFWRAP_SPEC " %{static: %{fmudflap|fmudflapth: \
- -brename:malloc,__wrap_malloc -brename:__real_malloc,malloc \
- -brename:free,__wrap_free -brename:__real_free,free \
- -brename:calloc,__wrap_calloc -brename:__real_calloc,calloc \
- -brename:realloc,__wrap_realloc -brename:__real_realloc,realloc \
- -brename:mmap,__wrap_mmap -brename:__real_mmap,mmap \
- -brename:munmap,__wrap_munmap -brename:__real_munmap,munmap \
- -brename:alloca,__wrap_alloca -brename:__real_alloca,alloca \
-} %{fmudflapth: \
- -brename:pthread_create,__wrap_pthread_create \
- -brename:__real_pthread_create,pthread_create \
- -brename:pthread_join,__wrap_pthread_join \
- -brename:__real_pthread_join,pthread_join \
- -brename:pthread_exit,__wrap_pthread_exit \
- -brename:__real_pthread_exit,pthread_exit \
-}} %{fmudflap|fmudflapth: \
- -brename:main,__wrap_main -brename:__real_main,main \
-}"
-
-#define MFLIB_SPEC " %{fmudflap: -lmudflap \
- %{static:%(link_gcc_c_sequence) -lmudflap}} \
- %{fmudflapth: -lmudflapth -lpthread \
- %{static:%(link_gcc_c_sequence) -lmudflapth}} "
-
/* Names to predefine in the preprocessor for this target machine. */
#define TARGET_OS_AIX_CPP_BUILTINS() \
do \
diff --git a/gcc/config/rs6000/altivec.md b/gcc/config/rs6000/altivec.md
index 47a3a6894e1..9f4b6a4b392 100644
--- a/gcc/config/rs6000/altivec.md
+++ b/gcc/config/rs6000/altivec.md
@@ -59,6 +59,8 @@
UNSPEC_VSUMSWS
UNSPEC_VPERM
UNSPEC_VPERM_UNS
+ UNSPEC_VPERM_X
+ UNSPEC_VPERM_UNS_X
UNSPEC_VRFIN
UNSPEC_VCFUX
UNSPEC_VCFSX
@@ -649,7 +651,7 @@
convert_move (small_swap, swap, 0);
low_product = gen_reg_rtx (V4SImode);
- emit_insn (gen_vec_widen_umult_odd_v8hi (low_product, one, two));
+ emit_insn (gen_altivec_vmulouh (low_product, one, two));
high_product = gen_reg_rtx (V4SImode);
emit_insn (gen_altivec_vmsumuhm (high_product, one, small_swap, zero));
@@ -676,10 +678,18 @@
emit_insn (gen_vec_widen_smult_even_v8hi (even, operands[1], operands[2]));
emit_insn (gen_vec_widen_smult_odd_v8hi (odd, operands[1], operands[2]));
- emit_insn (gen_altivec_vmrghw (high, even, odd));
- emit_insn (gen_altivec_vmrglw (low, even, odd));
-
- emit_insn (gen_altivec_vpkuwum (operands[0], high, low));
+ if (BYTES_BIG_ENDIAN)
+ {
+ emit_insn (gen_altivec_vmrghw (high, even, odd));
+ emit_insn (gen_altivec_vmrglw (low, even, odd));
+ emit_insn (gen_altivec_vpkuwum (operands[0], high, low));
+ }
+ else
+ {
+ emit_insn (gen_altivec_vmrghw (high, odd, even));
+ emit_insn (gen_altivec_vmrglw (low, odd, even));
+ emit_insn (gen_altivec_vpkuwum (operands[0], low, high));
+ }
DONE;
}")
@@ -967,7 +977,111 @@
"vmrgow %0,%1,%2"
[(set_attr "type" "vecperm")])
-(define_insn "vec_widen_umult_even_v16qi"
+(define_expand "vec_widen_umult_even_v16qi"
+ [(use (match_operand:V8HI 0 "register_operand" ""))
+ (use (match_operand:V16QI 1 "register_operand" ""))
+ (use (match_operand:V16QI 2 "register_operand" ""))]
+ "TARGET_ALTIVEC"
+{
+ if (BYTES_BIG_ENDIAN)
+ emit_insn (gen_altivec_vmuleub (operands[0], operands[1], operands[2]));
+ else
+ emit_insn (gen_altivec_vmuloub (operands[0], operands[1], operands[2]));
+ DONE;
+})
+
+(define_expand "vec_widen_smult_even_v16qi"
+ [(use (match_operand:V8HI 0 "register_operand" ""))
+ (use (match_operand:V16QI 1 "register_operand" ""))
+ (use (match_operand:V16QI 2 "register_operand" ""))]
+ "TARGET_ALTIVEC"
+{
+ if (BYTES_BIG_ENDIAN)
+ emit_insn (gen_altivec_vmulesb (operands[0], operands[1], operands[2]));
+ else
+ emit_insn (gen_altivec_vmulosb (operands[0], operands[1], operands[2]));
+ DONE;
+})
+
+(define_expand "vec_widen_umult_even_v8hi"
+ [(use (match_operand:V4SI 0 "register_operand" ""))
+ (use (match_operand:V8HI 1 "register_operand" ""))
+ (use (match_operand:V8HI 2 "register_operand" ""))]
+ "TARGET_ALTIVEC"
+{
+ if (BYTES_BIG_ENDIAN)
+ emit_insn (gen_altivec_vmuleuh (operands[0], operands[1], operands[2]));
+ else
+ emit_insn (gen_altivec_vmulouh (operands[0], operands[1], operands[2]));
+ DONE;
+})
+
+(define_expand "vec_widen_smult_even_v8hi"
+ [(use (match_operand:V4SI 0 "register_operand" ""))
+ (use (match_operand:V8HI 1 "register_operand" ""))
+ (use (match_operand:V8HI 2 "register_operand" ""))]
+ "TARGET_ALTIVEC"
+{
+ if (BYTES_BIG_ENDIAN)
+ emit_insn (gen_altivec_vmulesh (operands[0], operands[1], operands[2]));
+ else
+ emit_insn (gen_altivec_vmulosh (operands[0], operands[1], operands[2]));
+ DONE;
+})
+
+(define_expand "vec_widen_umult_odd_v16qi"
+ [(use (match_operand:V8HI 0 "register_operand" ""))
+ (use (match_operand:V16QI 1 "register_operand" ""))
+ (use (match_operand:V16QI 2 "register_operand" ""))]
+ "TARGET_ALTIVEC"
+{
+ if (BYTES_BIG_ENDIAN)
+ emit_insn (gen_altivec_vmuloub (operands[0], operands[1], operands[2]));
+ else
+ emit_insn (gen_altivec_vmuleub (operands[0], operands[1], operands[2]));
+ DONE;
+})
+
+(define_expand "vec_widen_smult_odd_v16qi"
+ [(use (match_operand:V8HI 0 "register_operand" ""))
+ (use (match_operand:V16QI 1 "register_operand" ""))
+ (use (match_operand:V16QI 2 "register_operand" ""))]
+ "TARGET_ALTIVEC"
+{
+ if (BYTES_BIG_ENDIAN)
+ emit_insn (gen_altivec_vmulosb (operands[0], operands[1], operands[2]));
+ else
+ emit_insn (gen_altivec_vmulesb (operands[0], operands[1], operands[2]));
+ DONE;
+})
+
+(define_expand "vec_widen_umult_odd_v8hi"
+ [(use (match_operand:V4SI 0 "register_operand" ""))
+ (use (match_operand:V8HI 1 "register_operand" ""))
+ (use (match_operand:V8HI 2 "register_operand" ""))]
+ "TARGET_ALTIVEC"
+{
+ if (BYTES_BIG_ENDIAN)
+ emit_insn (gen_altivec_vmulouh (operands[0], operands[1], operands[2]));
+ else
+ emit_insn (gen_altivec_vmuleuh (operands[0], operands[1], operands[2]));
+ DONE;
+})
+
+(define_expand "vec_widen_smult_odd_v8hi"
+ [(use (match_operand:V4SI 0 "register_operand" ""))
+ (use (match_operand:V8HI 1 "register_operand" ""))
+ (use (match_operand:V8HI 2 "register_operand" ""))]
+ "TARGET_ALTIVEC"
+{
+ if (BYTES_BIG_ENDIAN)
+ emit_insn (gen_altivec_vmulosh (operands[0], operands[1], operands[2]));
+ else
+ emit_insn (gen_altivec_vmulesh (operands[0], operands[1], operands[2]));
+ DONE;
+})
+
+(define_insn "altivec_vmuleub"
[(set (match_operand:V8HI 0 "register_operand" "=v")
(unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")
(match_operand:V16QI 2 "register_operand" "v")]
@@ -976,43 +1090,25 @@
"vmuleub %0,%1,%2"
[(set_attr "type" "veccomplex")])
-(define_insn "vec_widen_smult_even_v16qi"
+(define_insn "altivec_vmuloub"
[(set (match_operand:V8HI 0 "register_operand" "=v")
(unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")
(match_operand:V16QI 2 "register_operand" "v")]
- UNSPEC_VMULESB))]
- "TARGET_ALTIVEC"
- "vmulesb %0,%1,%2"
- [(set_attr "type" "veccomplex")])
-
-(define_insn "vec_widen_umult_even_v8hi"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")]
- UNSPEC_VMULEUH))]
- "TARGET_ALTIVEC"
- "vmuleuh %0,%1,%2"
- [(set_attr "type" "veccomplex")])
-
-(define_insn "vec_widen_smult_even_v8hi"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")]
- UNSPEC_VMULESH))]
+ UNSPEC_VMULOUB))]
"TARGET_ALTIVEC"
- "vmulesh %0,%1,%2"
+ "vmuloub %0,%1,%2"
[(set_attr "type" "veccomplex")])
-(define_insn "vec_widen_umult_odd_v16qi"
+(define_insn "altivec_vmulesb"
[(set (match_operand:V8HI 0 "register_operand" "=v")
(unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")
(match_operand:V16QI 2 "register_operand" "v")]
- UNSPEC_VMULOUB))]
+ UNSPEC_VMULESB))]
"TARGET_ALTIVEC"
- "vmuloub %0,%1,%2"
+ "vmulesb %0,%1,%2"
[(set_attr "type" "veccomplex")])
-(define_insn "vec_widen_smult_odd_v16qi"
+(define_insn "altivec_vmulosb"
[(set (match_operand:V8HI 0 "register_operand" "=v")
(unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")
(match_operand:V16QI 2 "register_operand" "v")]
@@ -1021,7 +1117,16 @@
"vmulosb %0,%1,%2"
[(set_attr "type" "veccomplex")])
-(define_insn "vec_widen_umult_odd_v8hi"
+(define_insn "altivec_vmuleuh"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
+ (match_operand:V8HI 2 "register_operand" "v")]
+ UNSPEC_VMULEUH))]
+ "TARGET_ALTIVEC"
+ "vmuleuh %0,%1,%2"
+ [(set_attr "type" "veccomplex")])
+
+(define_insn "altivec_vmulouh"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
(match_operand:V8HI 2 "register_operand" "v")]
@@ -1030,7 +1135,16 @@
"vmulouh %0,%1,%2"
[(set_attr "type" "veccomplex")])
-(define_insn "vec_widen_smult_odd_v8hi"
+(define_insn "altivec_vmulesh"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
+ (match_operand:V8HI 2 "register_operand" "v")]
+ UNSPEC_VMULESH))]
+ "TARGET_ALTIVEC"
+ "vmulesh %0,%1,%2"
+ [(set_attr "type" "veccomplex")])
+
+(define_insn "altivec_vmulosh"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
(match_operand:V8HI 2 "register_operand" "v")]
@@ -1279,21 +1393,91 @@
"vrfiz %0,%1"
[(set_attr "type" "vecfloat")])
-(define_insn "altivec_vperm_<mode>"
+(define_insn_and_split "altivec_vperm_<mode>"
[(set (match_operand:VM 0 "register_operand" "=v")
(unspec:VM [(match_operand:VM 1 "register_operand" "v")
(match_operand:VM 2 "register_operand" "v")
(match_operand:V16QI 3 "register_operand" "v")]
+ UNSPEC_VPERM_X))]
+ "TARGET_ALTIVEC"
+ "#"
+ "!reload_in_progress && !reload_completed"
+ [(set (match_dup 0) (match_dup 4))]
+{
+ if (BYTES_BIG_ENDIAN)
+ operands[4] = gen_rtx_UNSPEC (<MODE>mode,
+ gen_rtvec (3, operands[1],
+ operands[2], operands[3]),
+ UNSPEC_VPERM);
+ else
+ {
+ /* We want to subtract from 31, but we can't vspltisb 31 since
+ it's out of range. -1 works as well because only the low-order
+ five bits of the permute control vector elements are used. */
+ rtx splat = gen_rtx_VEC_DUPLICATE (V16QImode,
+ gen_rtx_CONST_INT (QImode, -1));
+ rtx tmp = gen_reg_rtx (V16QImode);
+ emit_move_insn (tmp, splat);
+ rtx sel = gen_rtx_MINUS (V16QImode, tmp, operands[3]);
+ emit_move_insn (tmp, sel);
+ operands[4] = gen_rtx_UNSPEC (<MODE>mode,
+ gen_rtvec (3, operands[2],
+ operands[1], tmp),
+ UNSPEC_VPERM);
+ }
+}
+ [(set_attr "type" "vecperm")])
+
+(define_insn "*altivec_vperm_<mode>_internal"
+ [(set (match_operand:VM 0 "register_operand" "=v")
+ (unspec:VM [(match_operand:VM 1 "register_operand" "v")
+ (match_operand:VM 2 "register_operand" "v")
+ (match_operand:V16QI 3 "register_operand" "+v")]
UNSPEC_VPERM))]
"TARGET_ALTIVEC"
"vperm %0,%1,%2,%3"
[(set_attr "type" "vecperm")])
-(define_insn "altivec_vperm_<mode>_uns"
+(define_insn_and_split "altivec_vperm_<mode>_uns"
[(set (match_operand:VM 0 "register_operand" "=v")
(unspec:VM [(match_operand:VM 1 "register_operand" "v")
(match_operand:VM 2 "register_operand" "v")
(match_operand:V16QI 3 "register_operand" "v")]
+ UNSPEC_VPERM_UNS_X))]
+ "TARGET_ALTIVEC"
+ "#"
+ "!reload_in_progress && !reload_completed"
+ [(set (match_dup 0) (match_dup 4))]
+{
+ if (BYTES_BIG_ENDIAN)
+ operands[4] = gen_rtx_UNSPEC (<MODE>mode,
+ gen_rtvec (3, operands[1],
+ operands[2], operands[3]),
+ UNSPEC_VPERM_UNS);
+ else
+ {
+ /* We want to subtract from 31, but we can't vspltisb 31 since
+ it's out of range. -1 works as well because only the low-order
+ five bits of the permute control vector elements are used. */
+ rtx splat = gen_rtx_VEC_DUPLICATE (V16QImode,
+ gen_rtx_CONST_INT (QImode, -1));
+ rtx tmp = gen_reg_rtx (V16QImode);
+ emit_move_insn (tmp, splat);
+ rtx sel = gen_rtx_MINUS (V16QImode, tmp, operands[3]);
+ emit_move_insn (tmp, sel);
+ operands[4] = gen_rtx_UNSPEC (<MODE>mode,
+ gen_rtvec (3, operands[2],
+ operands[1], tmp),
+ UNSPEC_VPERM_UNS);
+ }
+}
+ [(set_attr "type" "vecperm")])
+
+(define_insn "*altivec_vperm_<mode>_uns_internal"
+ [(set (match_operand:VM 0 "register_operand" "=v")
+ (unspec:VM [(match_operand:VM 1 "register_operand" "v")
+ (match_operand:VM 2 "register_operand" "v")
+ (match_operand:V16QI 3 "register_operand" "+v")]
UNSPEC_VPERM_UNS))]
"TARGET_ALTIVEC"
"vperm %0,%1,%2,%3"
@@ -1306,7 +1490,12 @@
(match_operand:V16QI 3 "register_operand" "")]
UNSPEC_VPERM))]
"TARGET_ALTIVEC"
- "")
+{
+ if (!BYTES_BIG_ENDIAN) {
+ altivec_expand_vec_perm_le (operands);
+ DONE;
+ }
+})
(define_expand "vec_perm_constv16qi"
[(match_operand:V16QI 0 "register_operand" "")
@@ -1958,25 +2147,26 @@
rtx vzero = gen_reg_rtx (V8HImode);
rtx mask = gen_reg_rtx (V16QImode);
rtvec v = rtvec_alloc (16);
+ bool be = BYTES_BIG_ENDIAN;
emit_insn (gen_altivec_vspltish (vzero, const0_rtx));
- RTVEC_ELT (v, 0) = gen_rtx_CONST_INT (QImode, 16);
- RTVEC_ELT (v, 1) = gen_rtx_CONST_INT (QImode, 0);
- RTVEC_ELT (v, 2) = gen_rtx_CONST_INT (QImode, 16);
- RTVEC_ELT (v, 3) = gen_rtx_CONST_INT (QImode, 1);
- RTVEC_ELT (v, 4) = gen_rtx_CONST_INT (QImode, 16);
- RTVEC_ELT (v, 5) = gen_rtx_CONST_INT (QImode, 2);
- RTVEC_ELT (v, 6) = gen_rtx_CONST_INT (QImode, 16);
- RTVEC_ELT (v, 7) = gen_rtx_CONST_INT (QImode, 3);
- RTVEC_ELT (v, 8) = gen_rtx_CONST_INT (QImode, 16);
- RTVEC_ELT (v, 9) = gen_rtx_CONST_INT (QImode, 4);
- RTVEC_ELT (v, 10) = gen_rtx_CONST_INT (QImode, 16);
- RTVEC_ELT (v, 11) = gen_rtx_CONST_INT (QImode, 5);
- RTVEC_ELT (v, 12) = gen_rtx_CONST_INT (QImode, 16);
- RTVEC_ELT (v, 13) = gen_rtx_CONST_INT (QImode, 6);
- RTVEC_ELT (v, 14) = gen_rtx_CONST_INT (QImode, 16);
- RTVEC_ELT (v, 15) = gen_rtx_CONST_INT (QImode, 7);
+ RTVEC_ELT (v, 0) = gen_rtx_CONST_INT (QImode, be ? 16 : 7);
+ RTVEC_ELT (v, 1) = gen_rtx_CONST_INT (QImode, be ? 0 : 16);
+ RTVEC_ELT (v, 2) = gen_rtx_CONST_INT (QImode, be ? 16 : 6);
+ RTVEC_ELT (v, 3) = gen_rtx_CONST_INT (QImode, be ? 1 : 16);
+ RTVEC_ELT (v, 4) = gen_rtx_CONST_INT (QImode, be ? 16 : 5);
+ RTVEC_ELT (v, 5) = gen_rtx_CONST_INT (QImode, be ? 2 : 16);
+ RTVEC_ELT (v, 6) = gen_rtx_CONST_INT (QImode, be ? 16 : 4);
+ RTVEC_ELT (v, 7) = gen_rtx_CONST_INT (QImode, be ? 3 : 16);
+ RTVEC_ELT (v, 8) = gen_rtx_CONST_INT (QImode, be ? 16 : 3);
+ RTVEC_ELT (v, 9) = gen_rtx_CONST_INT (QImode, be ? 4 : 16);
+ RTVEC_ELT (v, 10) = gen_rtx_CONST_INT (QImode, be ? 16 : 2);
+ RTVEC_ELT (v, 11) = gen_rtx_CONST_INT (QImode, be ? 5 : 16);
+ RTVEC_ELT (v, 12) = gen_rtx_CONST_INT (QImode, be ? 16 : 1);
+ RTVEC_ELT (v, 13) = gen_rtx_CONST_INT (QImode, be ? 6 : 16);
+ RTVEC_ELT (v, 14) = gen_rtx_CONST_INT (QImode, be ? 16 : 0);
+ RTVEC_ELT (v, 15) = gen_rtx_CONST_INT (QImode, be ? 7 : 16);
emit_insn (gen_vec_initv16qi (mask, gen_rtx_PARALLEL (V16QImode, v)));
emit_insn (gen_vperm_v16qiv8hi (operands[0], operands[1], vzero, mask));
@@ -1993,25 +2183,26 @@
rtx vzero = gen_reg_rtx (V4SImode);
rtx mask = gen_reg_rtx (V16QImode);
rtvec v = rtvec_alloc (16);
+ bool be = BYTES_BIG_ENDIAN;
emit_insn (gen_altivec_vspltisw (vzero, const0_rtx));
- RTVEC_ELT (v, 0) = gen_rtx_CONST_INT (QImode, 16);
- RTVEC_ELT (v, 1) = gen_rtx_CONST_INT (QImode, 17);
- RTVEC_ELT (v, 2) = gen_rtx_CONST_INT (QImode, 0);
- RTVEC_ELT (v, 3) = gen_rtx_CONST_INT (QImode, 1);
- RTVEC_ELT (v, 4) = gen_rtx_CONST_INT (QImode, 16);
- RTVEC_ELT (v, 5) = gen_rtx_CONST_INT (QImode, 17);
- RTVEC_ELT (v, 6) = gen_rtx_CONST_INT (QImode, 2);
- RTVEC_ELT (v, 7) = gen_rtx_CONST_INT (QImode, 3);
- RTVEC_ELT (v, 8) = gen_rtx_CONST_INT (QImode, 16);
- RTVEC_ELT (v, 9) = gen_rtx_CONST_INT (QImode, 17);
- RTVEC_ELT (v, 10) = gen_rtx_CONST_INT (QImode, 4);
- RTVEC_ELT (v, 11) = gen_rtx_CONST_INT (QImode, 5);
- RTVEC_ELT (v, 12) = gen_rtx_CONST_INT (QImode, 16);
- RTVEC_ELT (v, 13) = gen_rtx_CONST_INT (QImode, 17);
- RTVEC_ELT (v, 14) = gen_rtx_CONST_INT (QImode, 6);
- RTVEC_ELT (v, 15) = gen_rtx_CONST_INT (QImode, 7);
+ RTVEC_ELT (v, 0) = gen_rtx_CONST_INT (QImode, be ? 16 : 7);
+ RTVEC_ELT (v, 1) = gen_rtx_CONST_INT (QImode, be ? 17 : 6);
+ RTVEC_ELT (v, 2) = gen_rtx_CONST_INT (QImode, be ? 0 : 17);
+ RTVEC_ELT (v, 3) = gen_rtx_CONST_INT (QImode, be ? 1 : 16);
+ RTVEC_ELT (v, 4) = gen_rtx_CONST_INT (QImode, be ? 16 : 5);
+ RTVEC_ELT (v, 5) = gen_rtx_CONST_INT (QImode, be ? 17 : 4);
+ RTVEC_ELT (v, 6) = gen_rtx_CONST_INT (QImode, be ? 2 : 17);
+ RTVEC_ELT (v, 7) = gen_rtx_CONST_INT (QImode, be ? 3 : 16);
+ RTVEC_ELT (v, 8) = gen_rtx_CONST_INT (QImode, be ? 16 : 3);
+ RTVEC_ELT (v, 9) = gen_rtx_CONST_INT (QImode, be ? 17 : 2);
+ RTVEC_ELT (v, 10) = gen_rtx_CONST_INT (QImode, be ? 4 : 17);
+ RTVEC_ELT (v, 11) = gen_rtx_CONST_INT (QImode, be ? 5 : 16);
+ RTVEC_ELT (v, 12) = gen_rtx_CONST_INT (QImode, be ? 16 : 1);
+ RTVEC_ELT (v, 13) = gen_rtx_CONST_INT (QImode, be ? 17 : 0);
+ RTVEC_ELT (v, 14) = gen_rtx_CONST_INT (QImode, be ? 6 : 17);
+ RTVEC_ELT (v, 15) = gen_rtx_CONST_INT (QImode, be ? 7 : 16);
emit_insn (gen_vec_initv16qi (mask, gen_rtx_PARALLEL (V16QImode, v)));
emit_insn (gen_vperm_v8hiv4si (operands[0], operands[1], vzero, mask));
@@ -2028,25 +2219,26 @@
rtx vzero = gen_reg_rtx (V8HImode);
rtx mask = gen_reg_rtx (V16QImode);
rtvec v = rtvec_alloc (16);
+ bool be = BYTES_BIG_ENDIAN;
emit_insn (gen_altivec_vspltish (vzero, const0_rtx));
- RTVEC_ELT (v, 0) = gen_rtx_CONST_INT (QImode, 16);
- RTVEC_ELT (v, 1) = gen_rtx_CONST_INT (QImode, 8);
- RTVEC_ELT (v, 2) = gen_rtx_CONST_INT (QImode, 16);
- RTVEC_ELT (v, 3) = gen_rtx_CONST_INT (QImode, 9);
- RTVEC_ELT (v, 4) = gen_rtx_CONST_INT (QImode, 16);
- RTVEC_ELT (v, 5) = gen_rtx_CONST_INT (QImode, 10);
- RTVEC_ELT (v, 6) = gen_rtx_CONST_INT (QImode, 16);
- RTVEC_ELT (v, 7) = gen_rtx_CONST_INT (QImode, 11);
- RTVEC_ELT (v, 8) = gen_rtx_CONST_INT (QImode, 16);
- RTVEC_ELT (v, 9) = gen_rtx_CONST_INT (QImode, 12);
- RTVEC_ELT (v, 10) = gen_rtx_CONST_INT (QImode, 16);
- RTVEC_ELT (v, 11) = gen_rtx_CONST_INT (QImode, 13);
- RTVEC_ELT (v, 12) = gen_rtx_CONST_INT (QImode, 16);
- RTVEC_ELT (v, 13) = gen_rtx_CONST_INT (QImode, 14);
- RTVEC_ELT (v, 14) = gen_rtx_CONST_INT (QImode, 16);
- RTVEC_ELT (v, 15) = gen_rtx_CONST_INT (QImode, 15);
+ RTVEC_ELT (v, 0) = gen_rtx_CONST_INT (QImode, be ? 16 : 15);
+ RTVEC_ELT (v, 1) = gen_rtx_CONST_INT (QImode, be ? 8 : 16);
+ RTVEC_ELT (v, 2) = gen_rtx_CONST_INT (QImode, be ? 16 : 14);
+ RTVEC_ELT (v, 3) = gen_rtx_CONST_INT (QImode, be ? 9 : 16);
+ RTVEC_ELT (v, 4) = gen_rtx_CONST_INT (QImode, be ? 16 : 13);
+ RTVEC_ELT (v, 5) = gen_rtx_CONST_INT (QImode, be ? 10 : 16);
+ RTVEC_ELT (v, 6) = gen_rtx_CONST_INT (QImode, be ? 16 : 12);
+ RTVEC_ELT (v, 7) = gen_rtx_CONST_INT (QImode, be ? 11 : 16);
+ RTVEC_ELT (v, 8) = gen_rtx_CONST_INT (QImode, be ? 16 : 11);
+ RTVEC_ELT (v, 9) = gen_rtx_CONST_INT (QImode, be ? 12 : 16);
+ RTVEC_ELT (v, 10) = gen_rtx_CONST_INT (QImode, be ? 16 : 10);
+ RTVEC_ELT (v, 11) = gen_rtx_CONST_INT (QImode, be ? 13 : 16);
+ RTVEC_ELT (v, 12) = gen_rtx_CONST_INT (QImode, be ? 16 : 9);
+ RTVEC_ELT (v, 13) = gen_rtx_CONST_INT (QImode, be ? 14 : 16);
+ RTVEC_ELT (v, 14) = gen_rtx_CONST_INT (QImode, be ? 16 : 8);
+ RTVEC_ELT (v, 15) = gen_rtx_CONST_INT (QImode, be ? 15 : 16);
emit_insn (gen_vec_initv16qi (mask, gen_rtx_PARALLEL (V16QImode, v)));
emit_insn (gen_vperm_v16qiv8hi (operands[0], operands[1], vzero, mask));
@@ -2063,25 +2255,26 @@
rtx vzero = gen_reg_rtx (V4SImode);
rtx mask = gen_reg_rtx (V16QImode);
rtvec v = rtvec_alloc (16);
+ bool be = BYTES_BIG_ENDIAN;
emit_insn (gen_altivec_vspltisw (vzero, const0_rtx));
- RTVEC_ELT (v, 0) = gen_rtx_CONST_INT (QImode, 16);
- RTVEC_ELT (v, 1) = gen_rtx_CONST_INT (QImode, 17);
- RTVEC_ELT (v, 2) = gen_rtx_CONST_INT (QImode, 8);
- RTVEC_ELT (v, 3) = gen_rtx_CONST_INT (QImode, 9);
- RTVEC_ELT (v, 4) = gen_rtx_CONST_INT (QImode, 16);
- RTVEC_ELT (v, 5) = gen_rtx_CONST_INT (QImode, 17);
- RTVEC_ELT (v, 6) = gen_rtx_CONST_INT (QImode, 10);
- RTVEC_ELT (v, 7) = gen_rtx_CONST_INT (QImode, 11);
- RTVEC_ELT (v, 8) = gen_rtx_CONST_INT (QImode, 16);
- RTVEC_ELT (v, 9) = gen_rtx_CONST_INT (QImode, 17);
- RTVEC_ELT (v, 10) = gen_rtx_CONST_INT (QImode, 12);
- RTVEC_ELT (v, 11) = gen_rtx_CONST_INT (QImode, 13);
- RTVEC_ELT (v, 12) = gen_rtx_CONST_INT (QImode, 16);
- RTVEC_ELT (v, 13) = gen_rtx_CONST_INT (QImode, 17);
- RTVEC_ELT (v, 14) = gen_rtx_CONST_INT (QImode, 14);
- RTVEC_ELT (v, 15) = gen_rtx_CONST_INT (QImode, 15);
+ RTVEC_ELT (v, 0) = gen_rtx_CONST_INT (QImode, be ? 16 : 15);
+ RTVEC_ELT (v, 1) = gen_rtx_CONST_INT (QImode, be ? 17 : 14);
+ RTVEC_ELT (v, 2) = gen_rtx_CONST_INT (QImode, be ? 8 : 17);
+ RTVEC_ELT (v, 3) = gen_rtx_CONST_INT (QImode, be ? 9 : 16);
+ RTVEC_ELT (v, 4) = gen_rtx_CONST_INT (QImode, be ? 16 : 13);
+ RTVEC_ELT (v, 5) = gen_rtx_CONST_INT (QImode, be ? 17 : 12);
+ RTVEC_ELT (v, 6) = gen_rtx_CONST_INT (QImode, be ? 10 : 17);
+ RTVEC_ELT (v, 7) = gen_rtx_CONST_INT (QImode, be ? 11 : 16);
+ RTVEC_ELT (v, 8) = gen_rtx_CONST_INT (QImode, be ? 16 : 11);
+ RTVEC_ELT (v, 9) = gen_rtx_CONST_INT (QImode, be ? 17 : 10);
+ RTVEC_ELT (v, 10) = gen_rtx_CONST_INT (QImode, be ? 12 : 17);
+ RTVEC_ELT (v, 11) = gen_rtx_CONST_INT (QImode, be ? 13 : 16);
+ RTVEC_ELT (v, 12) = gen_rtx_CONST_INT (QImode, be ? 16 : 9);
+ RTVEC_ELT (v, 13) = gen_rtx_CONST_INT (QImode, be ? 17 : 8);
+ RTVEC_ELT (v, 14) = gen_rtx_CONST_INT (QImode, be ? 14 : 17);
+ RTVEC_ELT (v, 15) = gen_rtx_CONST_INT (QImode, be ? 15 : 16);
emit_insn (gen_vec_initv16qi (mask, gen_rtx_PARALLEL (V16QImode, v)));
emit_insn (gen_vperm_v8hiv4si (operands[0], operands[1], vzero, mask));
@@ -2101,7 +2294,10 @@
emit_insn (gen_vec_widen_umult_even_v16qi (ve, operands[1], operands[2]));
emit_insn (gen_vec_widen_umult_odd_v16qi (vo, operands[1], operands[2]));
- emit_insn (gen_altivec_vmrghh (operands[0], ve, vo));
+ if (BYTES_BIG_ENDIAN)
+ emit_insn (gen_altivec_vmrghh (operands[0], ve, vo));
+ else
+ emit_insn (gen_altivec_vmrghh (operands[0], vo, ve));
DONE;
}")
@@ -2118,7 +2314,10 @@
emit_insn (gen_vec_widen_umult_even_v16qi (ve, operands[1], operands[2]));
emit_insn (gen_vec_widen_umult_odd_v16qi (vo, operands[1], operands[2]));
- emit_insn (gen_altivec_vmrglh (operands[0], ve, vo));
+ if (BYTES_BIG_ENDIAN)
+ emit_insn (gen_altivec_vmrglh (operands[0], ve, vo));
+ else
+ emit_insn (gen_altivec_vmrglh (operands[0], vo, ve));
DONE;
}")
@@ -2135,7 +2334,10 @@
emit_insn (gen_vec_widen_smult_even_v16qi (ve, operands[1], operands[2]));
emit_insn (gen_vec_widen_smult_odd_v16qi (vo, operands[1], operands[2]));
- emit_insn (gen_altivec_vmrghh (operands[0], ve, vo));
+ if (BYTES_BIG_ENDIAN)
+ emit_insn (gen_altivec_vmrghh (operands[0], ve, vo));
+ else
+ emit_insn (gen_altivec_vmrghh (operands[0], vo, ve));
DONE;
}")
@@ -2152,7 +2354,10 @@
emit_insn (gen_vec_widen_smult_even_v16qi (ve, operands[1], operands[2]));
emit_insn (gen_vec_widen_smult_odd_v16qi (vo, operands[1], operands[2]));
- emit_insn (gen_altivec_vmrglh (operands[0], ve, vo));
+ if (BYTES_BIG_ENDIAN)
+ emit_insn (gen_altivec_vmrglh (operands[0], ve, vo));
+ else
+ emit_insn (gen_altivec_vmrglh (operands[0], vo, ve));
DONE;
}")
@@ -2169,7 +2374,10 @@
emit_insn (gen_vec_widen_umult_even_v8hi (ve, operands[1], operands[2]));
emit_insn (gen_vec_widen_umult_odd_v8hi (vo, operands[1], operands[2]));
- emit_insn (gen_altivec_vmrghw (operands[0], ve, vo));
+ if (BYTES_BIG_ENDIAN)
+ emit_insn (gen_altivec_vmrghw (operands[0], ve, vo));
+ else
+ emit_insn (gen_altivec_vmrghw (operands[0], vo, ve));
DONE;
}")
@@ -2186,7 +2394,10 @@
emit_insn (gen_vec_widen_umult_even_v8hi (ve, operands[1], operands[2]));
emit_insn (gen_vec_widen_umult_odd_v8hi (vo, operands[1], operands[2]));
- emit_insn (gen_altivec_vmrglw (operands[0], ve, vo));
+ if (BYTES_BIG_ENDIAN)
+ emit_insn (gen_altivec_vmrglw (operands[0], ve, vo));
+ else
+ emit_insn (gen_altivec_vmrglw (operands[0], vo, ve));
DONE;
}")
@@ -2203,7 +2414,10 @@
emit_insn (gen_vec_widen_smult_even_v8hi (ve, operands[1], operands[2]));
emit_insn (gen_vec_widen_smult_odd_v8hi (vo, operands[1], operands[2]));
- emit_insn (gen_altivec_vmrghw (operands[0], ve, vo));
+ if (BYTES_BIG_ENDIAN)
+ emit_insn (gen_altivec_vmrghw (operands[0], ve, vo));
+ else
+ emit_insn (gen_altivec_vmrghw (operands[0], vo, ve));
DONE;
}")
@@ -2220,7 +2434,10 @@
emit_insn (gen_vec_widen_smult_even_v8hi (ve, operands[1], operands[2]));
emit_insn (gen_vec_widen_smult_odd_v8hi (vo, operands[1], operands[2]));
- emit_insn (gen_altivec_vmrglw (operands[0], ve, vo));
+ if (BYTES_BIG_ENDIAN)
+ emit_insn (gen_altivec_vmrglw (operands[0], ve, vo));
+ else
+ emit_insn (gen_altivec_vmrglw (operands[0], vo, ve));
DONE;
}")
diff --git a/gcc/config/rs6000/constraints.md b/gcc/config/rs6000/constraints.md
index fa53cbb9de7..4467b9e3d8b 100644
--- a/gcc/config/rs6000/constraints.md
+++ b/gcc/config/rs6000/constraints.md
@@ -52,29 +52,18 @@
"@internal")
;; Use w as a prefix to add VSX modes
-;; vector double (V2DF)
+;; any VSX register
+(define_register_constraint "wa" "rs6000_constraints[RS6000_CONSTRAINT_wa]"
+ "Any VSX register if the -mvsx option was used or NO_REGS.")
+
(define_register_constraint "wd" "rs6000_constraints[RS6000_CONSTRAINT_wd]"
- "@internal")
+ "VSX vector register to hold vector double data or NO_REGS.")
-;; vector float (V4SF)
(define_register_constraint "wf" "rs6000_constraints[RS6000_CONSTRAINT_wf]"
- "@internal")
-
-;; scalar double (DF)
-(define_register_constraint "ws" "rs6000_constraints[RS6000_CONSTRAINT_ws]"
- "@internal")
-
-;; TImode in VSX registers
-(define_register_constraint "wt" "rs6000_constraints[RS6000_CONSTRAINT_wt]"
- "@internal")
-
-;; any VSX register
-(define_register_constraint "wa" "rs6000_constraints[RS6000_CONSTRAINT_wa]"
- "@internal")
+ "VSX vector register to hold vector float data or NO_REGS.")
-;; Register constraints to simplify move patterns
(define_register_constraint "wg" "rs6000_constraints[RS6000_CONSTRAINT_wg]"
- "Floating point register if -mmfpgpr is used, or NO_REGS.")
+ "If -mmfpgpr was used, a floating point register or NO_REGS.")
(define_register_constraint "wl" "rs6000_constraints[RS6000_CONSTRAINT_wl]"
"Floating point register if the LFIWAX instruction is enabled or NO_REGS.")
@@ -82,23 +71,38 @@
(define_register_constraint "wm" "rs6000_constraints[RS6000_CONSTRAINT_wm]"
"VSX register if direct move instructions are enabled, or NO_REGS.")
+;; NO_REGs register constraint, used to merge mov{sd,sf}, since movsd can use
+;; direct move directly, and movsf can't to move between the register sets.
+;; There is a mode_attr that resolves to wm for SDmode and wn for SFmode
+(define_register_constraint "wn" "NO_REGS" "No register (NO_REGS).")
+
(define_register_constraint "wr" "rs6000_constraints[RS6000_CONSTRAINT_wr]"
"General purpose register if 64-bit instructions are enabled or NO_REGS.")
+(define_register_constraint "ws" "rs6000_constraints[RS6000_CONSTRAINT_ws]"
+ "VSX vector register to hold scalar double values or NO_REGS.")
+
+(define_register_constraint "wt" "rs6000_constraints[RS6000_CONSTRAINT_wt]"
+ "VSX vector register to hold 128 bit integer or NO_REGS.")
+
+(define_register_constraint "wu" "rs6000_constraints[RS6000_CONSTRAINT_wu]"
+ "Altivec register to use for float/32-bit int loads/stores or NO_REGS.")
+
(define_register_constraint "wv" "rs6000_constraints[RS6000_CONSTRAINT_wv]"
- "Altivec register if -mpower8-vector is used or NO_REGS.")
+ "Altivec register to use for double loads/stores or NO_REGS.")
+
+(define_register_constraint "ww" "rs6000_constraints[RS6000_CONSTRAINT_ww]"
+ "FP or VSX register to perform float operations under -mvsx or NO_REGS.")
(define_register_constraint "wx" "rs6000_constraints[RS6000_CONSTRAINT_wx]"
"Floating point register if the STFIWX instruction is enabled or NO_REGS.")
+(define_register_constraint "wy" "rs6000_constraints[RS6000_CONSTRAINT_wy]"
+ "VSX vector register to hold scalar float values or NO_REGS.")
+
(define_register_constraint "wz" "rs6000_constraints[RS6000_CONSTRAINT_wz]"
"Floating point register if the LFIWZX instruction is enabled or NO_REGS.")
-;; NO_REGs register constraint, used to merge mov{sd,sf}, since movsd can use
-;; direct move directly, and movsf can't to move between the register sets.
-;; There is a mode_attr that resolves to wm for SDmode and wn for SFmode
-(define_register_constraint "wn" "NO_REGS")
-
;; Lq/stq validates the address for load/store quad
(define_memory_constraint "wQ"
"Memory operand suitable for the load/store quad instructions"
diff --git a/gcc/config/rs6000/darwin.md b/gcc/config/rs6000/darwin.md
index 24e8cfaafe1..2f15c5389c6 100644
--- a/gcc/config/rs6000/darwin.md
+++ b/gcc/config/rs6000/darwin.md
@@ -260,7 +260,14 @@ You should have received a copy of the GNU General Public License
(unspec:SI [(match_operand:SI 0 "immediate_operand" "s")
(pc)] UNSPEC_LD_MPIC))]
"(DEFAULT_ABI == ABI_DARWIN) && flag_pic"
- "bcl 20,31,%0\\n%0:"
+{
+#if TARGET_MACHO
+ machopic_should_output_picbase_label (); /* Update for new func. */
+#else
+ gcc_unreachable ();
+#endif
+ return "bcl 20,31,%0\\n%0:";
+}
[(set_attr "type" "branch")
(set_attr "length" "4")])
@@ -269,7 +276,14 @@ You should have received a copy of the GNU General Public License
(unspec:DI [(match_operand:DI 0 "immediate_operand" "s")
(pc)] UNSPEC_LD_MPIC))]
"(DEFAULT_ABI == ABI_DARWIN) && flag_pic && TARGET_64BIT"
- "bcl 20,31,%0\\n%0:"
+{
+#if TARGET_MACHO
+ machopic_should_output_picbase_label (); /* Update for new func. */
+#else
+ gcc_unreachable ();
+#endif
+ return "bcl 20,31,%0\\n%0:";
+}
[(set_attr "type" "branch")
(set_attr "length" "4")])
@@ -370,3 +384,97 @@ You should have received a copy of the GNU General Public License
}
[(set_attr "type" "branch,branch")
(set_attr "length" "4,8")])
+
+(define_expand "reload_macho_picbase"
+ [(set (reg:SI 65)
+ (unspec [(match_operand 0 "" "")]
+ UNSPEC_RELD_MPIC))]
+ "(DEFAULT_ABI == ABI_DARWIN) && flag_pic"
+{
+ if (TARGET_32BIT)
+ emit_insn (gen_reload_macho_picbase_si (operands[0]));
+ else
+ emit_insn (gen_reload_macho_picbase_di (operands[0]));
+
+ DONE;
+})
+
+(define_insn "reload_macho_picbase_si"
+ [(set (reg:SI 65)
+ (unspec:SI [(match_operand:SI 0 "immediate_operand" "s")
+ (pc)] UNSPEC_RELD_MPIC))]
+ "(DEFAULT_ABI == ABI_DARWIN) && flag_pic"
+{
+#if TARGET_MACHO
+ if (machopic_should_output_picbase_label ())
+ {
+ static char tmp[64];
+ const char *cnam = machopic_get_function_picbase ();
+ snprintf (tmp, 64, "bcl 20,31,%s\\n%s:\\n%%0:", cnam, cnam);
+ return tmp;
+ }
+ else
+#else
+ gcc_unreachable ();
+#endif
+ return "bcl 20,31,%0\\n%0:";
+}
+ [(set_attr "type" "branch")
+ (set_attr "length" "4")])
+
+(define_insn "reload_macho_picbase_di"
+ [(set (reg:DI 65)
+ (unspec:DI [(match_operand:DI 0 "immediate_operand" "s")
+ (pc)] UNSPEC_RELD_MPIC))]
+ "(DEFAULT_ABI == ABI_DARWIN) && flag_pic && TARGET_64BIT"
+{
+#if TARGET_MACHO
+ if (machopic_should_output_picbase_label ())
+ {
+ static char tmp[64];
+ const char *cnam = machopic_get_function_picbase ();
+ snprintf (tmp, 64, "bcl 20,31,%s\\n%s:\\n%%0:", cnam, cnam);
+ return tmp;
+ }
+ else
+#else
+ gcc_unreachable ();
+#endif
+ return "bcl 20,31,%0\\n%0:";
+}
+ [(set_attr "type" "branch")
+ (set_attr "length" "4")])
+
+;; We need to restore the PIC register, at the site of nonlocal label.
+
+(define_insn_and_split "nonlocal_goto_receiver"
+ [(unspec_volatile [(const_int 0)] UNSPECV_NLGR)]
+ "TARGET_MACHO && flag_pic"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+{
+#if TARGET_MACHO
+ if (crtl->uses_pic_offset_table)
+ {
+ static unsigned n = 0;
+ rtx picrtx = gen_rtx_SYMBOL_REF (Pmode, MACHOPIC_FUNCTION_BASE_NAME);
+ rtx picreg = gen_rtx_REG (Pmode, RS6000_PIC_OFFSET_TABLE_REGNUM);
+ rtx tmplrtx;
+ char tmplab[20];
+
+ ASM_GENERATE_INTERNAL_LABEL(tmplab, "Lnlgr", ++n);
+ tmplrtx = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (tmplab));
+
+ emit_insn (gen_reload_macho_picbase (tmplrtx));
+ emit_move_insn (picreg, gen_rtx_REG (Pmode, LR_REGNO));
+ emit_insn (gen_macho_correct_pic (picreg, picreg, picrtx, tmplrtx));
+ }
+ else
+ /* Not using PIC reg, no reload needed. */
+ emit_note (NOTE_INSN_DELETED);
+#else
+ gcc_unreachable ();
+#endif
+ DONE;
+})
diff --git a/gcc/config/rs6000/linux.h b/gcc/config/rs6000/linux.h
index 2e5a56b3929..f7df111b57e 100644
--- a/gcc/config/rs6000/linux.h
+++ b/gcc/config/rs6000/linux.h
@@ -145,3 +145,9 @@
/* Static stack checking is supported by means of probes. */
#define STACK_CHECK_STATIC_BUILTIN 1
+
+/* Software floating point support for exceptions and rounding modes
+ depends on the C library in use. */
+#undef TARGET_FLOAT_EXCEPTIONS_ROUNDING_SUPPORTED_P
+#define TARGET_FLOAT_EXCEPTIONS_ROUNDING_SUPPORTED_P \
+ rs6000_linux_float_exceptions_rounding_supported_p
diff --git a/gcc/config/rs6000/linux64.h b/gcc/config/rs6000/linux64.h
index 439f53f2d23..c1adbd78a4d 100644
--- a/gcc/config/rs6000/linux64.h
+++ b/gcc/config/rs6000/linux64.h
@@ -558,3 +558,9 @@ extern int dot_symbols;
/* The default value isn't sufficient in 64-bit mode. */
#define STACK_CHECK_PROTECT (TARGET_64BIT ? 16 * 1024 : 12 * 1024)
+
+/* Software floating point support for exceptions and rounding modes
+ depends on the C library in use. */
+#undef TARGET_FLOAT_EXCEPTIONS_ROUNDING_SUPPORTED_P
+#define TARGET_FLOAT_EXCEPTIONS_ROUNDING_SUPPORTED_P \
+ rs6000_linux_float_exceptions_rounding_supported_p
diff --git a/gcc/config/rs6000/rs6000-builtin.def b/gcc/config/rs6000/rs6000-builtin.def
index 672604406d5..3dab7321cac 100644
--- a/gcc/config/rs6000/rs6000-builtin.def
+++ b/gcc/config/rs6000/rs6000-builtin.def
@@ -1209,9 +1209,9 @@ BU_VSX_1 (XVRSPIZ, "xvrspiz", CONST, vsx_btruncv4sf2)
BU_VSX_1 (XSRDPI, "xsrdpi", CONST, vsx_xsrdpi)
BU_VSX_1 (XSRDPIC, "xsrdpic", CONST, vsx_xsrdpic)
-BU_VSX_1 (XSRDPIM, "xsrdpim", CONST, vsx_floordf2)
-BU_VSX_1 (XSRDPIP, "xsrdpip", CONST, vsx_ceildf2)
-BU_VSX_1 (XSRDPIZ, "xsrdpiz", CONST, vsx_btruncdf2)
+BU_VSX_1 (XSRDPIM, "xsrdpim", CONST, floordf2)
+BU_VSX_1 (XSRDPIP, "xsrdpip", CONST, ceildf2)
+BU_VSX_1 (XSRDPIZ, "xsrdpiz", CONST, btruncdf2)
/* VSX predicate functions. */
BU_VSX_P (XVCMPEQSP_P, "xvcmpeqsp_p", CONST, vector_eq_v4sf_p)
diff --git a/gcc/config/rs6000/rs6000-cpus.def b/gcc/config/rs6000/rs6000-cpus.def
index c177512ddfd..548566eee8b 100644
--- a/gcc/config/rs6000/rs6000-cpus.def
+++ b/gcc/config/rs6000/rs6000-cpus.def
@@ -38,12 +38,13 @@
/* For ISA 2.06, don't add ISEL, since in general it isn't a win, but
altivec is a win so enable it. */
+ /* OPTION_MASK_VSX_TIMODE should be set, but disable it for now until
+ PR 58587 is fixed. */
#define ISA_2_6_MASKS_EMBEDDED (ISA_2_5_MASKS_EMBEDDED | OPTION_MASK_POPCNTD)
#define ISA_2_6_MASKS_SERVER (ISA_2_5_MASKS_SERVER \
| OPTION_MASK_POPCNTD \
| OPTION_MASK_ALTIVEC \
- | OPTION_MASK_VSX \
- | OPTION_MASK_VSX_TIMODE)
+ | OPTION_MASK_VSX)
/* For now, don't provide an embedded version of ISA 2.07. */
#define ISA_2_7_MASKS_SERVER (ISA_2_6_MASKS_SERVER \
@@ -182,7 +183,7 @@ RS6000_CPU ("power6x", PROCESSOR_POWER6, MASK_POWERPC64 | MASK_PPC_GPOPT
RS6000_CPU ("power7", PROCESSOR_POWER7, /* Don't add MASK_ISEL by default */
POWERPC_7400_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_MFCRF
| MASK_POPCNTB | MASK_FPRND | MASK_CMPB | MASK_DFP | MASK_POPCNTD
- | MASK_VSX | MASK_RECIP_PRECISION | MASK_VSX_TIMODE)
+ | MASK_VSX | MASK_RECIP_PRECISION)
RS6000_CPU ("power8", PROCESSOR_POWER8, MASK_POWERPC64 | ISA_2_7_MASKS_SERVER)
RS6000_CPU ("powerpc", PROCESSOR_POWERPC, 0)
RS6000_CPU ("powerpc64", PROCESSOR_POWERPC64, MASK_PPC_GFXOPT | MASK_POWERPC64)
diff --git a/gcc/config/rs6000/rs6000-linux.c b/gcc/config/rs6000/rs6000-linux.c
new file mode 100644
index 00000000000..17b51af7ead
--- /dev/null
+++ b/gcc/config/rs6000/rs6000-linux.c
@@ -0,0 +1,38 @@
+/* Functions for Linux on PowerPC.
+ Copyright (C) 2013 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 "rtl.h"
+#include "tm_p.h"
+
+/* Implement TARGET_FLOAT_EXCEPTIONS_ROUNDING_SUPPORTED_P. */
+
+bool
+rs6000_linux_float_exceptions_rounding_supported_p (void)
+{
+ /* glibc has support for exceptions and rounding modes for software
+ floating point. */
+ if (OPTION_GLIBC)
+ return true;
+ else
+ return TARGET_DF_INSN;
+}
diff --git a/gcc/config/rs6000/rs6000-modes.def b/gcc/config/rs6000/rs6000-modes.def
index 5124e1665d4..a77aa26e850 100644
--- a/gcc/config/rs6000/rs6000-modes.def
+++ b/gcc/config/rs6000/rs6000-modes.def
@@ -45,4 +45,4 @@ VECTOR_MODES (FLOAT, 32); /* V16HF V8SF V4DF */
/* Replacement for TImode that only is allowed in GPRs. We also use PTImode
for quad memory atomic operations to force getting an even/odd register
combination. */
-PARTIAL_INT_MODE (TI);
+PARTIAL_INT_MODE (TI, 128, PTI);
diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h
index 3ddabb81c39..d1d1737dca1 100644
--- a/gcc/config/rs6000/rs6000-protos.h
+++ b/gcc/config/rs6000/rs6000-protos.h
@@ -56,6 +56,7 @@ extern void paired_expand_vector_init (rtx, rtx);
extern void rs6000_expand_vector_set (rtx, rtx, int);
extern void rs6000_expand_vector_extract (rtx, rtx, int);
extern bool altivec_expand_vec_perm_const (rtx op[4]);
+extern void altivec_expand_vec_perm_le (rtx op[4]);
extern bool rs6000_expand_vec_perm_const (rtx op[4]);
extern void rs6000_expand_extract_even (rtx, rtx, rtx);
extern void rs6000_expand_interleave (rtx, rtx, rtx, bool);
@@ -122,8 +123,11 @@ extern rtx rs6000_longcall_ref (rtx);
extern void rs6000_fatal_bad_address (rtx);
extern rtx create_TOC_reference (rtx, rtx);
extern void rs6000_split_multireg_move (rtx, rtx);
+extern void rs6000_emit_le_vsx_move (rtx, rtx, enum machine_mode);
extern void rs6000_emit_move (rtx, rtx, enum machine_mode);
extern rtx rs6000_secondary_memory_needed_rtx (enum machine_mode);
+extern enum machine_mode rs6000_secondary_memory_needed_mode (enum
+ machine_mode);
extern rtx (*rs6000_legitimize_reload_address_ptr) (rtx, enum machine_mode,
int, int, int, int *);
extern bool rs6000_legitimate_offset_address_p (enum machine_mode, rtx,
@@ -208,4 +212,6 @@ void rs6000_final_prescan_insn (rtx, rtx *operand, int num_operands);
extern bool rs6000_hard_regno_mode_ok_p[][FIRST_PSEUDO_REGISTER];
extern unsigned char rs6000_class_max_nregs[][LIM_REG_CLASSES];
extern unsigned char rs6000_hard_regno_nregs[][FIRST_PSEUDO_REGISTER];
+
+extern bool rs6000_linux_float_exceptions_rounding_supported_p (void);
#endif /* rs6000-protos.h */
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 7ff0af907d9..8c8ee9fae0e 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -52,13 +52,14 @@
#include "cfgloop.h"
#include "sched-int.h"
#include "gimple.h"
-#include "tree-flow.h"
#include "intl.h"
#include "params.h"
#include "tm-constrs.h"
+#include "ira.h"
#include "opts.h"
#include "tree-vectorizer.h"
#include "dumpfile.h"
+#include "cgraph.h"
#if TARGET_XCOFF
#include "xcoffout.h" /* get declarations of xcoff_*_section_name */
#endif
@@ -189,9 +190,6 @@ unsigned char rs6000_hard_regno_nregs[NUM_MACHINE_MODES][FIRST_PSEUDO_REGISTER];
/* Map register number to register class. */
enum reg_class rs6000_regno_regclass[FIRST_PSEUDO_REGISTER];
-/* Reload functions based on the type and the vector unit. */
-static enum insn_code rs6000_vector_reload[NUM_MACHINE_MODES][2];
-
static int dbg_cost_ctrl;
/* Built in types. */
@@ -316,11 +314,77 @@ static enum rs6000_reg_type reg_class_to_reg_type[N_REG_CLASSES];
#define IS_FP_VECT_REG_TYPE(RTYPE) IN_RANGE(RTYPE, VSX_REG_TYPE, FPR_REG_TYPE)
-/* Direct moves to/from vsx/gpr registers that need an additional register to
- do the move. */
-static enum insn_code reload_fpr_gpr[NUM_MACHINE_MODES];
-static enum insn_code reload_gpr_vsx[NUM_MACHINE_MODES];
-static enum insn_code reload_vsx_gpr[NUM_MACHINE_MODES];
+
+/* Register classes we care about in secondary reload or go if legitimate
+ address. We only need to worry about GPR, FPR, and Altivec registers here,
+ along an ANY field that is the OR of the 3 register classes. */
+
+enum rs6000_reload_reg_type {
+ RELOAD_REG_GPR, /* General purpose registers. */
+ RELOAD_REG_FPR, /* Traditional floating point regs. */
+ RELOAD_REG_VMX, /* Altivec (VMX) registers. */
+ RELOAD_REG_ANY, /* OR of GPR, FPR, Altivec masks. */
+ N_RELOAD_REG
+};
+
+/* For setting up register classes, loop through the 3 register classes mapping
+ into real registers, and skip the ANY class, which is just an OR of the
+ bits. */
+#define FIRST_RELOAD_REG_CLASS RELOAD_REG_GPR
+#define LAST_RELOAD_REG_CLASS RELOAD_REG_VMX
+
+/* Map reload register type to a register in the register class. */
+struct reload_reg_map_type {
+ const char *name; /* Register class name. */
+ int reg; /* Register in the register class. */
+};
+
+static const struct reload_reg_map_type reload_reg_map[N_RELOAD_REG] = {
+ { "Gpr", FIRST_GPR_REGNO }, /* RELOAD_REG_GPR. */
+ { "Fpr", FIRST_FPR_REGNO }, /* RELOAD_REG_FPR. */
+ { "VMX", FIRST_ALTIVEC_REGNO }, /* RELOAD_REG_VMX. */
+ { "Any", -1 }, /* RELOAD_REG_ANY. */
+};
+
+/* Mask bits for each register class, indexed per mode. Historically the
+ compiler has been more restrictive which types can do PRE_MODIFY instead of
+ PRE_INC and PRE_DEC, so keep track of sepaate bits for these two. */
+typedef unsigned char addr_mask_type;
+
+#define RELOAD_REG_VALID 0x01 /* Mode valid in register.. */
+#define RELOAD_REG_MULTIPLE 0x02 /* Mode takes multiple registers. */
+#define RELOAD_REG_INDEXED 0x04 /* Reg+reg addressing. */
+#define RELOAD_REG_OFFSET 0x08 /* Reg+offset addressing. */
+#define RELOAD_REG_PRE_INCDEC 0x10 /* PRE_INC/PRE_DEC valid. */
+#define RELOAD_REG_PRE_MODIFY 0x20 /* PRE_MODIFY valid. */
+
+/* Register type masks based on the type, of valid addressing modes. */
+struct rs6000_reg_addr {
+ enum insn_code reload_load; /* INSN to reload for loading. */
+ enum insn_code reload_store; /* INSN to reload for storing. */
+ enum insn_code reload_fpr_gpr; /* INSN to move from FPR to GPR. */
+ enum insn_code reload_gpr_vsx; /* INSN to move from GPR to VSX. */
+ enum insn_code reload_vsx_gpr; /* INSN to move from VSX to GPR. */
+ addr_mask_type addr_mask[(int)N_RELOAD_REG]; /* Valid address masks. */
+};
+
+static struct rs6000_reg_addr reg_addr[NUM_MACHINE_MODES];
+
+/* Helper function to say whether a mode supports PRE_INC or PRE_DEC. */
+static inline bool
+mode_supports_pre_incdec_p (enum machine_mode mode)
+{
+ return ((reg_addr[mode].addr_mask[RELOAD_REG_ANY] & RELOAD_REG_PRE_INCDEC)
+ != 0);
+}
+
+/* Helper function to say whether a mode supports PRE_MODIFY. */
+static inline bool
+mode_supports_pre_modify_p (enum machine_mode mode)
+{
+ return ((reg_addr[mode].addr_mask[RELOAD_REG_ANY] & RELOAD_REG_PRE_MODIFY)
+ != 0);
+}
/* Target cpu costs. */
@@ -1491,6 +1555,9 @@ static const struct attribute_spec rs6000_attribute_table[] =
#undef TARGET_MODE_DEPENDENT_ADDRESS_P
#define TARGET_MODE_DEPENDENT_ADDRESS_P rs6000_mode_dependent_address_p
+#undef TARGET_LRA_P
+#define TARGET_LRA_P rs6000_lra_p
+
#undef TARGET_CAN_ELIMINATE
#define TARGET_CAN_ELIMINATE rs6000_can_eliminate
@@ -1526,6 +1593,9 @@ static const struct attribute_spec rs6000_attribute_table[] =
#undef TARGET_VECTORIZE_VEC_PERM_CONST_OK
#define TARGET_VECTORIZE_VEC_PERM_CONST_OK rs6000_vectorize_vec_perm_const_ok
+
+#undef TARGET_CAN_USE_DOLOOP_P
+#define TARGET_CAN_USE_DOLOOP_P can_use_doloop_if_innermost
/* Processor table. */
@@ -1624,19 +1694,28 @@ rs6000_hard_regno_mode_ok (int regno, enum machine_mode mode)
/* VSX registers that overlap the FPR registers are larger than for non-VSX
implementations. Don't allow an item to be split between a FP register
- and an Altivec register. */
- if (VECTOR_MEM_VSX_P (mode))
+ and an Altivec register. Allow TImode in all VSX registers if the user
+ asked for it. */
+ if (TARGET_VSX && VSX_REGNO_P (regno)
+ && (VECTOR_MEM_VSX_P (mode)
+ || (TARGET_VSX_SCALAR_FLOAT && mode == SFmode)
+ || (TARGET_VSX_SCALAR_DOUBLE && (mode == DFmode || mode == DImode))
+ || (TARGET_VSX_TIMODE && mode == TImode)))
{
if (FP_REGNO_P (regno))
return FP_REGNO_P (last_regno);
if (ALTIVEC_REGNO_P (regno))
- return ALTIVEC_REGNO_P (last_regno);
- }
+ {
+ if (mode == SFmode && !TARGET_UPPER_REGS_SF)
+ return 0;
- /* Allow TImode in all VSX registers if the user asked for it. */
- if (mode == TImode && TARGET_VSX_TIMODE && VSX_REGNO_P (regno))
- return 1;
+ if ((mode == DFmode || mode == DImode) && !TARGET_UPPER_REGS_DF)
+ return 0;
+
+ return ALTIVEC_REGNO_P (last_regno);
+ }
+ }
/* The GPRs can hold any mode, but values bigger than one register
cannot go past R31. */
@@ -1766,6 +1845,63 @@ rs6000_debug_reg_print (int first_regno, int last_regno, const char *reg_name)
}
}
+static const char *
+rs6000_debug_vector_unit (enum rs6000_vector v)
+{
+ const char *ret;
+
+ switch (v)
+ {
+ case VECTOR_NONE: ret = "none"; break;
+ case VECTOR_ALTIVEC: ret = "altivec"; break;
+ case VECTOR_VSX: ret = "vsx"; break;
+ case VECTOR_P8_VECTOR: ret = "p8_vector"; break;
+ case VECTOR_PAIRED: ret = "paired"; break;
+ case VECTOR_SPE: ret = "spe"; break;
+ case VECTOR_OTHER: ret = "other"; break;
+ default: ret = "unknown"; break;
+ }
+
+ return ret;
+}
+
+/* Print the address masks in a human readble fashion. */
+DEBUG_FUNCTION void
+rs6000_debug_print_mode (ssize_t m)
+{
+ ssize_t rc;
+
+ fprintf (stderr, "Mode: %-5s", GET_MODE_NAME (m));
+ for (rc = 0; rc < N_RELOAD_REG; rc++)
+ {
+ addr_mask_type mask = reg_addr[m].addr_mask[rc];
+ fprintf (stderr,
+ " %s: %c%c%c%c%c%c",
+ reload_reg_map[rc].name,
+ (mask & RELOAD_REG_VALID) != 0 ? 'v' : ' ',
+ (mask & RELOAD_REG_MULTIPLE) != 0 ? 'm' : ' ',
+ (mask & RELOAD_REG_INDEXED) != 0 ? 'i' : ' ',
+ (mask & RELOAD_REG_OFFSET) != 0 ? 'o' : ' ',
+ (mask & RELOAD_REG_PRE_INCDEC) != 0 ? '+' : ' ',
+ (mask & RELOAD_REG_PRE_MODIFY) != 0 ? '+' : ' ');
+ }
+
+ if (rs6000_vector_unit[m] != VECTOR_NONE
+ || rs6000_vector_mem[m] != VECTOR_NONE
+ || (reg_addr[m].reload_store != CODE_FOR_nothing)
+ || (reg_addr[m].reload_load != CODE_FOR_nothing))
+ {
+ fprintf (stderr,
+ " Vector-arith=%-10s Vector-mem=%-10s Reload=%c%c",
+ rs6000_debug_vector_unit (rs6000_vector_unit[m]),
+ rs6000_debug_vector_unit (rs6000_vector_mem[m]),
+ (reg_addr[m].reload_store != CODE_FOR_nothing) ? 's' : '*',
+ (reg_addr[m].reload_load != CODE_FOR_nothing) ? 'l' : '*');
+ }
+
+ fputs ("\n", stderr);
+}
+
#define DEBUG_FMT_ID "%-32s= "
#define DEBUG_FMT_D DEBUG_FMT_ID "%d\n"
#define DEBUG_FMT_WX DEBUG_FMT_ID "%#.12" HOST_WIDE_INT_PRINT "x: "
@@ -1789,17 +1925,6 @@ rs6000_debug_reg_global (void)
const char *cmodel_str;
struct cl_target_option cl_opts;
- /* Map enum rs6000_vector to string. */
- static const char *rs6000_debug_vector_unit[] = {
- "none",
- "altivec",
- "vsx",
- "p8_vector",
- "paired",
- "spe",
- "other"
- };
-
/* Modes we want tieable information on. */
static const enum machine_mode print_tieable_modes[] = {
QImode,
@@ -1891,8 +2016,11 @@ rs6000_debug_reg_global (void)
"wr reg_class = %s\n"
"ws reg_class = %s\n"
"wt reg_class = %s\n"
+ "wu reg_class = %s\n"
"wv reg_class = %s\n"
+ "ww reg_class = %s\n"
"wx reg_class = %s\n"
+ "wy reg_class = %s\n"
"wz reg_class = %s\n"
"\n",
reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_d]],
@@ -1907,28 +2035,18 @@ rs6000_debug_reg_global (void)
reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wr]],
reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_ws]],
reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wt]],
+ reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wu]],
reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wv]],
+ reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_ww]],
reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wx]],
+ reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wy]],
reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wz]]);
+ nl = "\n";
for (m = 0; m < NUM_MACHINE_MODES; ++m)
- if (rs6000_vector_unit[m] || rs6000_vector_mem[m]
- || (rs6000_vector_reload[m][0] != CODE_FOR_nothing)
- || (rs6000_vector_reload[m][1] != CODE_FOR_nothing))
- {
- nl = "\n";
- fprintf (stderr,
- "Vector mode: %-5s arithmetic: %-10s move: %-10s "
- "reload-out: %c reload-in: %c\n",
- GET_MODE_NAME (m),
- rs6000_debug_vector_unit[ rs6000_vector_unit[m] ],
- rs6000_debug_vector_unit[ rs6000_vector_mem[m] ],
- (rs6000_vector_reload[m][0] != CODE_FOR_nothing) ? 'y' : 'n',
- (rs6000_vector_reload[m][1] != CODE_FOR_nothing) ? 'y' : 'n');
- }
+ rs6000_debug_print_mode (m);
- if (nl)
- fputs (nl, stderr);
+ fputs ("\n", stderr);
for (m1 = 0; m1 < ARRAY_SIZE (print_tieable_modes); m1++)
{
@@ -2164,11 +2282,106 @@ rs6000_debug_reg_global (void)
(int)RS6000_BUILTIN_COUNT);
}
+
+/* Update the addr mask bits in reg_addr to help secondary reload and go if
+ legitimate address support to figure out the appropriate addressing to
+ use. */
+
+static void
+rs6000_setup_reg_addr_masks (void)
+{
+ ssize_t rc, reg, m, nregs;
+ addr_mask_type any_addr_mask, addr_mask;
+
+ for (m = 0; m < NUM_MACHINE_MODES; ++m)
+ {
+ /* SDmode is special in that we want to access it only via REG+REG
+ addressing on power7 and above, since we want to use the LFIWZX and
+ STFIWZX instructions to load it. */
+ bool indexed_only_p = (m == SDmode && TARGET_NO_SDMODE_STACK);
+
+ any_addr_mask = 0;
+ for (rc = FIRST_RELOAD_REG_CLASS; rc <= LAST_RELOAD_REG_CLASS; rc++)
+ {
+ addr_mask = 0;
+ reg = reload_reg_map[rc].reg;
+
+ /* Can mode values go in the GPR/FPR/Altivec registers? */
+ if (reg >= 0 && rs6000_hard_regno_mode_ok_p[m][reg])
+ {
+ nregs = rs6000_hard_regno_nregs[m][reg];
+ addr_mask |= RELOAD_REG_VALID;
+
+ /* Indicate if the mode takes more than 1 physical register. If
+ it takes a single register, indicate it can do REG+REG
+ addressing. */
+ if (nregs > 1 || m == BLKmode)
+ addr_mask |= RELOAD_REG_MULTIPLE;
+ else
+ addr_mask |= RELOAD_REG_INDEXED;
+
+ /* Figure out if we can do PRE_INC, PRE_DEC, or PRE_MODIFY
+ addressing. Restrict addressing on SPE for 64-bit types
+ because of the SUBREG hackery used to address 64-bit floats in
+ '32-bit' GPRs. To simplify secondary reload, don't allow
+ update forms on scalar floating point types that can go in the
+ upper registers. */
+
+ if (TARGET_UPDATE
+ && (rc == RELOAD_REG_GPR || rc == RELOAD_REG_FPR)
+ && GET_MODE_SIZE (m) <= 8
+ && !VECTOR_MODE_P (m)
+ && !COMPLEX_MODE_P (m)
+ && !indexed_only_p
+ && !(TARGET_E500_DOUBLE && GET_MODE_SIZE (m) == 8)
+ && !(m == DFmode && TARGET_UPPER_REGS_DF)
+ && !(m == SFmode && TARGET_UPPER_REGS_SF))
+ {
+ addr_mask |= RELOAD_REG_PRE_INCDEC;
+
+ /* PRE_MODIFY is more restricted than PRE_INC/PRE_DEC in that
+ we don't allow PRE_MODIFY for some multi-register
+ operations. */
+ switch (m)
+ {
+ default:
+ addr_mask |= RELOAD_REG_PRE_MODIFY;
+ break;
+
+ case DImode:
+ if (TARGET_POWERPC64)
+ addr_mask |= RELOAD_REG_PRE_MODIFY;
+ break;
+
+ case DFmode:
+ case DDmode:
+ if (TARGET_DF_INSN)
+ addr_mask |= RELOAD_REG_PRE_MODIFY;
+ break;
+ }
+ }
+ }
+
+ /* GPR and FPR registers can do REG+OFFSET addressing, except
+ possibly for SDmode. */
+ if ((addr_mask != 0) && !indexed_only_p
+ && (rc == RELOAD_REG_GPR || rc == RELOAD_REG_FPR))
+ addr_mask |= RELOAD_REG_OFFSET;
+
+ reg_addr[m].addr_mask[rc] = addr_mask;
+ any_addr_mask |= addr_mask;
+ }
+
+ reg_addr[m].addr_mask[RELOAD_REG_ANY] = any_addr_mask;
+ }
+}
+
+
/* Initialize the various global tables that are based on register size. */
static void
rs6000_init_hard_regno_mode_ok (bool global_init_p)
{
- int r, m, c;
+ ssize_t r, m, c;
int align64;
int align32;
@@ -2233,17 +2446,18 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
reg_class_to_reg_type[(int)ALTIVEC_REGS] = ALTIVEC_REG_TYPE;
}
- /* Precalculate vector information, this must be set up before the
- rs6000_hard_regno_nregs_internal below. */
- for (m = 0; m < NUM_MACHINE_MODES; ++m)
- {
- rs6000_vector_unit[m] = rs6000_vector_mem[m] = VECTOR_NONE;
- rs6000_vector_reload[m][0] = CODE_FOR_nothing;
- rs6000_vector_reload[m][1] = CODE_FOR_nothing;
- }
+ /* Precalculate the valid memory formats as well as the vector information,
+ this must be set up before the rs6000_hard_regno_nregs_internal calls
+ below. */
+ gcc_assert ((int)VECTOR_NONE == 0);
+ memset ((void *) &rs6000_vector_unit[0], '\0', sizeof (rs6000_vector_unit));
+ memset ((void *) &rs6000_vector_mem[0], '\0', sizeof (rs6000_vector_unit));
+
+ gcc_assert ((int)CODE_FOR_nothing == 0);
+ memset ((void *) &reg_addr[0], '\0', sizeof (reg_addr));
- for (c = 0; c < (int)(int)RS6000_CONSTRAINT_MAX; c++)
- rs6000_constraints[c] = NO_REGS;
+ gcc_assert ((int)NO_REGS == 0);
+ memset ((void *) &rs6000_constraints[0], '\0', sizeof (rs6000_constraints));
/* The VSX hardware allows native alignment for vectors, but control whether the compiler
believes it can use native alignment or still uses 128-bit alignment. */
@@ -2320,7 +2534,7 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
{
rs6000_vector_unit[DFmode] = VECTOR_VSX;
rs6000_vector_mem[DFmode]
- = (TARGET_VSX_SCALAR_MEMORY ? VECTOR_VSX : VECTOR_NONE);
+ = (TARGET_UPPER_REGS_DF ? VECTOR_VSX : VECTOR_NONE);
rs6000_vector_align[DFmode] = align64;
}
@@ -2334,7 +2548,34 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
/* TODO add SPE and paired floating point vector support. */
/* Register class constraints for the constraints that depend on compile
- switches. */
+ switches. When the VSX code was added, different constraints were added
+ based on the type (DFmode, V2DFmode, V4SFmode). For the vector types, all
+ of the VSX registers are used. The register classes for scalar floating
+ point types is set, based on whether we allow that type into the upper
+ (Altivec) registers. GCC has register classes to target the Altivec
+ registers for load/store operations, to select using a VSX memory
+ operation instead of the traditional floating point operation. The
+ constraints are:
+
+ d - Register class to use with traditional DFmode instructions.
+ f - Register class to use with traditional SFmode instructions.
+ v - Altivec register.
+ wa - Any VSX register.
+ wd - Preferred register class for V2DFmode.
+ wf - Preferred register class for V4SFmode.
+ wg - Float register for power6x move insns.
+ wl - Float register if we can do 32-bit signed int loads.
+ wm - VSX register for ISA 2.07 direct move operations.
+ wr - GPR if 64-bit mode is permitted.
+ ws - Register class to do ISA 2.06 DF operations.
+ wu - Altivec register for ISA 2.07 VSX SF/SI load/stores.
+ wv - Altivec register for ISA 2.06 VSX DF/DI load/stores.
+ wt - VSX register for TImode in VSX registers.
+ ww - Register class to do SF conversions in with VSX operations.
+ wx - Float register if we can do 32-bit int stores.
+ wy - Register class to do ISA 2.07 SF operations.
+ wz - Float register if we can do 32-bit unsigned int loads. */
+
if (TARGET_HARD_FLOAT && TARGET_FPRS)
rs6000_constraints[RS6000_CONSTRAINT_f] = FLOAT_REGS;
@@ -2343,19 +2584,20 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
if (TARGET_VSX)
{
- /* At present, we just use VSX_REGS, but we have different constraints
- based on the use, in case we want to fine tune the default register
- class used. wa = any VSX register, wf = register class to use for
- V4SF, wd = register class to use for V2DF, and ws = register classs to
- use for DF scalars. */
rs6000_constraints[RS6000_CONSTRAINT_wa] = VSX_REGS;
- rs6000_constraints[RS6000_CONSTRAINT_wf] = VSX_REGS;
rs6000_constraints[RS6000_CONSTRAINT_wd] = VSX_REGS;
- rs6000_constraints[RS6000_CONSTRAINT_ws] = (TARGET_VSX_SCALAR_MEMORY
- ? VSX_REGS
- : FLOAT_REGS);
+ rs6000_constraints[RS6000_CONSTRAINT_wf] = VSX_REGS;
+
if (TARGET_VSX_TIMODE)
rs6000_constraints[RS6000_CONSTRAINT_wt] = VSX_REGS;
+
+ if (TARGET_UPPER_REGS_DF)
+ {
+ rs6000_constraints[RS6000_CONSTRAINT_ws] = VSX_REGS;
+ rs6000_constraints[RS6000_CONSTRAINT_wv] = ALTIVEC_REGS;
+ }
+ else
+ rs6000_constraints[RS6000_CONSTRAINT_ws] = FLOAT_REGS;
}
/* Add conditional constraints based on various options, to allow us to
@@ -2375,8 +2617,19 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
if (TARGET_POWERPC64)
rs6000_constraints[RS6000_CONSTRAINT_wr] = GENERAL_REGS;
- if (TARGET_P8_VECTOR)
- rs6000_constraints[RS6000_CONSTRAINT_wv] = ALTIVEC_REGS;
+ if (TARGET_P8_VECTOR && TARGET_UPPER_REGS_SF)
+ {
+ rs6000_constraints[RS6000_CONSTRAINT_wu] = ALTIVEC_REGS;
+ rs6000_constraints[RS6000_CONSTRAINT_wy] = VSX_REGS;
+ rs6000_constraints[RS6000_CONSTRAINT_ww] = VSX_REGS;
+ }
+ else if (TARGET_P8_VECTOR)
+ {
+ rs6000_constraints[RS6000_CONSTRAINT_wy] = FLOAT_REGS;
+ rs6000_constraints[RS6000_CONSTRAINT_ww] = FLOAT_REGS;
+ }
+ else if (TARGET_VSX)
+ rs6000_constraints[RS6000_CONSTRAINT_ww] = FLOAT_REGS;
if (TARGET_STFIWX)
rs6000_constraints[RS6000_CONSTRAINT_wx] = FLOAT_REGS;
@@ -2384,112 +2637,104 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
if (TARGET_LFIWZX)
rs6000_constraints[RS6000_CONSTRAINT_wz] = FLOAT_REGS;
- /* Setup the direct move combinations. */
- for (m = 0; m < NUM_MACHINE_MODES; ++m)
- {
- reload_fpr_gpr[m] = CODE_FOR_nothing;
- reload_gpr_vsx[m] = CODE_FOR_nothing;
- reload_vsx_gpr[m] = CODE_FOR_nothing;
- }
-
/* Set up the reload helper and direct move functions. */
if (TARGET_VSX || TARGET_ALTIVEC)
{
if (TARGET_64BIT)
{
- rs6000_vector_reload[V16QImode][0] = CODE_FOR_reload_v16qi_di_store;
- rs6000_vector_reload[V16QImode][1] = CODE_FOR_reload_v16qi_di_load;
- rs6000_vector_reload[V8HImode][0] = CODE_FOR_reload_v8hi_di_store;
- rs6000_vector_reload[V8HImode][1] = CODE_FOR_reload_v8hi_di_load;
- rs6000_vector_reload[V4SImode][0] = CODE_FOR_reload_v4si_di_store;
- rs6000_vector_reload[V4SImode][1] = CODE_FOR_reload_v4si_di_load;
- rs6000_vector_reload[V2DImode][0] = CODE_FOR_reload_v2di_di_store;
- rs6000_vector_reload[V2DImode][1] = CODE_FOR_reload_v2di_di_load;
- rs6000_vector_reload[V4SFmode][0] = CODE_FOR_reload_v4sf_di_store;
- rs6000_vector_reload[V4SFmode][1] = CODE_FOR_reload_v4sf_di_load;
- rs6000_vector_reload[V2DFmode][0] = CODE_FOR_reload_v2df_di_store;
- rs6000_vector_reload[V2DFmode][1] = CODE_FOR_reload_v2df_di_load;
- if (TARGET_VSX && TARGET_VSX_SCALAR_MEMORY)
+ reg_addr[V16QImode].reload_store = CODE_FOR_reload_v16qi_di_store;
+ reg_addr[V16QImode].reload_load = CODE_FOR_reload_v16qi_di_load;
+ reg_addr[V8HImode].reload_store = CODE_FOR_reload_v8hi_di_store;
+ reg_addr[V8HImode].reload_load = CODE_FOR_reload_v8hi_di_load;
+ reg_addr[V4SImode].reload_store = CODE_FOR_reload_v4si_di_store;
+ reg_addr[V4SImode].reload_load = CODE_FOR_reload_v4si_di_load;
+ reg_addr[V2DImode].reload_store = CODE_FOR_reload_v2di_di_store;
+ reg_addr[V2DImode].reload_load = CODE_FOR_reload_v2di_di_load;
+ reg_addr[V4SFmode].reload_store = CODE_FOR_reload_v4sf_di_store;
+ reg_addr[V4SFmode].reload_load = CODE_FOR_reload_v4sf_di_load;
+ reg_addr[V2DFmode].reload_store = CODE_FOR_reload_v2df_di_store;
+ reg_addr[V2DFmode].reload_load = CODE_FOR_reload_v2df_di_load;
+ if (TARGET_VSX && TARGET_UPPER_REGS_DF)
{
- rs6000_vector_reload[DFmode][0] = CODE_FOR_reload_df_di_store;
- rs6000_vector_reload[DFmode][1] = CODE_FOR_reload_df_di_load;
- rs6000_vector_reload[DDmode][0] = CODE_FOR_reload_dd_di_store;
- rs6000_vector_reload[DDmode][1] = CODE_FOR_reload_dd_di_load;
+ reg_addr[DFmode].reload_store = CODE_FOR_reload_df_di_store;
+ reg_addr[DFmode].reload_load = CODE_FOR_reload_df_di_load;
+ reg_addr[DDmode].reload_store = CODE_FOR_reload_dd_di_store;
+ reg_addr[DDmode].reload_load = CODE_FOR_reload_dd_di_load;
}
if (TARGET_P8_VECTOR)
{
- rs6000_vector_reload[SFmode][0] = CODE_FOR_reload_sf_di_store;
- rs6000_vector_reload[SFmode][1] = CODE_FOR_reload_sf_di_load;
- rs6000_vector_reload[SDmode][0] = CODE_FOR_reload_sd_di_store;
- rs6000_vector_reload[SDmode][1] = CODE_FOR_reload_sd_di_load;
+ reg_addr[SFmode].reload_store = CODE_FOR_reload_sf_di_store;
+ reg_addr[SFmode].reload_load = CODE_FOR_reload_sf_di_load;
+ reg_addr[SDmode].reload_store = CODE_FOR_reload_sd_di_store;
+ reg_addr[SDmode].reload_load = CODE_FOR_reload_sd_di_load;
}
if (TARGET_VSX_TIMODE)
{
- rs6000_vector_reload[TImode][0] = CODE_FOR_reload_ti_di_store;
- rs6000_vector_reload[TImode][1] = CODE_FOR_reload_ti_di_load;
+ reg_addr[TImode].reload_store = CODE_FOR_reload_ti_di_store;
+ reg_addr[TImode].reload_load = CODE_FOR_reload_ti_di_load;
}
if (TARGET_DIRECT_MOVE)
{
if (TARGET_POWERPC64)
{
- reload_gpr_vsx[TImode] = CODE_FOR_reload_gpr_from_vsxti;
- reload_gpr_vsx[V2DFmode] = CODE_FOR_reload_gpr_from_vsxv2df;
- reload_gpr_vsx[V2DImode] = CODE_FOR_reload_gpr_from_vsxv2di;
- reload_gpr_vsx[V4SFmode] = CODE_FOR_reload_gpr_from_vsxv4sf;
- reload_gpr_vsx[V4SImode] = CODE_FOR_reload_gpr_from_vsxv4si;
- reload_gpr_vsx[V8HImode] = CODE_FOR_reload_gpr_from_vsxv8hi;
- reload_gpr_vsx[V16QImode] = CODE_FOR_reload_gpr_from_vsxv16qi;
- reload_gpr_vsx[SFmode] = CODE_FOR_reload_gpr_from_vsxsf;
-
- reload_vsx_gpr[TImode] = CODE_FOR_reload_vsx_from_gprti;
- reload_vsx_gpr[V2DFmode] = CODE_FOR_reload_vsx_from_gprv2df;
- reload_vsx_gpr[V2DImode] = CODE_FOR_reload_vsx_from_gprv2di;
- reload_vsx_gpr[V4SFmode] = CODE_FOR_reload_vsx_from_gprv4sf;
- reload_vsx_gpr[V4SImode] = CODE_FOR_reload_vsx_from_gprv4si;
- reload_vsx_gpr[V8HImode] = CODE_FOR_reload_vsx_from_gprv8hi;
- reload_vsx_gpr[V16QImode] = CODE_FOR_reload_vsx_from_gprv16qi;
- reload_vsx_gpr[SFmode] = CODE_FOR_reload_vsx_from_gprsf;
+ reg_addr[TImode].reload_gpr_vsx = CODE_FOR_reload_gpr_from_vsxti;
+ reg_addr[V2DFmode].reload_gpr_vsx = CODE_FOR_reload_gpr_from_vsxv2df;
+ reg_addr[V2DImode].reload_gpr_vsx = CODE_FOR_reload_gpr_from_vsxv2di;
+ reg_addr[V4SFmode].reload_gpr_vsx = CODE_FOR_reload_gpr_from_vsxv4sf;
+ reg_addr[V4SImode].reload_gpr_vsx = CODE_FOR_reload_gpr_from_vsxv4si;
+ reg_addr[V8HImode].reload_gpr_vsx = CODE_FOR_reload_gpr_from_vsxv8hi;
+ reg_addr[V16QImode].reload_gpr_vsx = CODE_FOR_reload_gpr_from_vsxv16qi;
+ reg_addr[SFmode].reload_gpr_vsx = CODE_FOR_reload_gpr_from_vsxsf;
+
+ reg_addr[TImode].reload_vsx_gpr = CODE_FOR_reload_vsx_from_gprti;
+ reg_addr[V2DFmode].reload_vsx_gpr = CODE_FOR_reload_vsx_from_gprv2df;
+ reg_addr[V2DImode].reload_vsx_gpr = CODE_FOR_reload_vsx_from_gprv2di;
+ reg_addr[V4SFmode].reload_vsx_gpr = CODE_FOR_reload_vsx_from_gprv4sf;
+ reg_addr[V4SImode].reload_vsx_gpr = CODE_FOR_reload_vsx_from_gprv4si;
+ reg_addr[V8HImode].reload_vsx_gpr = CODE_FOR_reload_vsx_from_gprv8hi;
+ reg_addr[V16QImode].reload_vsx_gpr = CODE_FOR_reload_vsx_from_gprv16qi;
+ reg_addr[SFmode].reload_vsx_gpr = CODE_FOR_reload_vsx_from_gprsf;
}
else
{
- reload_fpr_gpr[DImode] = CODE_FOR_reload_fpr_from_gprdi;
- reload_fpr_gpr[DDmode] = CODE_FOR_reload_fpr_from_gprdd;
- reload_fpr_gpr[DFmode] = CODE_FOR_reload_fpr_from_gprdf;
+ reg_addr[DImode].reload_fpr_gpr = CODE_FOR_reload_fpr_from_gprdi;
+ reg_addr[DDmode].reload_fpr_gpr = CODE_FOR_reload_fpr_from_gprdd;
+ reg_addr[DFmode].reload_fpr_gpr = CODE_FOR_reload_fpr_from_gprdf;
}
}
}
else
{
- rs6000_vector_reload[V16QImode][0] = CODE_FOR_reload_v16qi_si_store;
- rs6000_vector_reload[V16QImode][1] = CODE_FOR_reload_v16qi_si_load;
- rs6000_vector_reload[V8HImode][0] = CODE_FOR_reload_v8hi_si_store;
- rs6000_vector_reload[V8HImode][1] = CODE_FOR_reload_v8hi_si_load;
- rs6000_vector_reload[V4SImode][0] = CODE_FOR_reload_v4si_si_store;
- rs6000_vector_reload[V4SImode][1] = CODE_FOR_reload_v4si_si_load;
- rs6000_vector_reload[V2DImode][0] = CODE_FOR_reload_v2di_si_store;
- rs6000_vector_reload[V2DImode][1] = CODE_FOR_reload_v2di_si_load;
- rs6000_vector_reload[V4SFmode][0] = CODE_FOR_reload_v4sf_si_store;
- rs6000_vector_reload[V4SFmode][1] = CODE_FOR_reload_v4sf_si_load;
- rs6000_vector_reload[V2DFmode][0] = CODE_FOR_reload_v2df_si_store;
- rs6000_vector_reload[V2DFmode][1] = CODE_FOR_reload_v2df_si_load;
- if (TARGET_VSX && TARGET_VSX_SCALAR_MEMORY)
+ reg_addr[V16QImode].reload_store = CODE_FOR_reload_v16qi_si_store;
+ reg_addr[V16QImode].reload_load = CODE_FOR_reload_v16qi_si_load;
+ reg_addr[V8HImode].reload_store = CODE_FOR_reload_v8hi_si_store;
+ reg_addr[V8HImode].reload_load = CODE_FOR_reload_v8hi_si_load;
+ reg_addr[V4SImode].reload_store = CODE_FOR_reload_v4si_si_store;
+ reg_addr[V4SImode].reload_load = CODE_FOR_reload_v4si_si_load;
+ reg_addr[V2DImode].reload_store = CODE_FOR_reload_v2di_si_store;
+ reg_addr[V2DImode].reload_load = CODE_FOR_reload_v2di_si_load;
+ reg_addr[V4SFmode].reload_store = CODE_FOR_reload_v4sf_si_store;
+ reg_addr[V4SFmode].reload_load = CODE_FOR_reload_v4sf_si_load;
+ reg_addr[V2DFmode].reload_store = CODE_FOR_reload_v2df_si_store;
+ reg_addr[V2DFmode].reload_load = CODE_FOR_reload_v2df_si_load;
+ if (TARGET_VSX && TARGET_UPPER_REGS_DF)
{
- rs6000_vector_reload[DFmode][0] = CODE_FOR_reload_df_si_store;
- rs6000_vector_reload[DFmode][1] = CODE_FOR_reload_df_si_load;
- rs6000_vector_reload[DDmode][0] = CODE_FOR_reload_dd_si_store;
- rs6000_vector_reload[DDmode][1] = CODE_FOR_reload_dd_si_load;
+ reg_addr[DFmode].reload_store = CODE_FOR_reload_df_si_store;
+ reg_addr[DFmode].reload_load = CODE_FOR_reload_df_si_load;
+ reg_addr[DDmode].reload_store = CODE_FOR_reload_dd_si_store;
+ reg_addr[DDmode].reload_load = CODE_FOR_reload_dd_si_load;
}
if (TARGET_P8_VECTOR)
{
- rs6000_vector_reload[SFmode][0] = CODE_FOR_reload_sf_si_store;
- rs6000_vector_reload[SFmode][1] = CODE_FOR_reload_sf_si_load;
- rs6000_vector_reload[SDmode][0] = CODE_FOR_reload_sd_si_store;
- rs6000_vector_reload[SDmode][1] = CODE_FOR_reload_sd_si_load;
+ reg_addr[SFmode].reload_store = CODE_FOR_reload_sf_si_store;
+ reg_addr[SFmode].reload_load = CODE_FOR_reload_sf_si_load;
+ reg_addr[SDmode].reload_store = CODE_FOR_reload_sd_si_store;
+ reg_addr[SDmode].reload_load = CODE_FOR_reload_sd_si_load;
}
if (TARGET_VSX_TIMODE)
{
- rs6000_vector_reload[TImode][0] = CODE_FOR_reload_ti_si_store;
- rs6000_vector_reload[TImode][1] = CODE_FOR_reload_ti_si_load;
+ reg_addr[TImode].reload_store = CODE_FOR_reload_ti_si_store;
+ reg_addr[TImode].reload_load = CODE_FOR_reload_ti_si_load;
}
}
}
@@ -2608,6 +2853,11 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
}
}
+ /* Update the addr mask bits in reg_addr to help secondary reload and go if
+ legitimate address support to figure out the appropriate addressing to
+ use. */
+ rs6000_setup_reg_addr_masks ();
+
if (global_init_p || TARGET_DEBUG_TARGET)
{
if (TARGET_DEBUG_REG)
@@ -2744,6 +2994,10 @@ rs6000_option_override_internal (bool global_init_p)
= ((global_init_p || target_option_default_node == NULL)
? NULL : TREE_TARGET_OPTION (target_option_default_node));
+ /* Remember the explicit arguments. */
+ if (global_init_p)
+ rs6000_isa_flags_explicit = global_options_set.x_rs6000_isa_flags;
+
/* On 64-bit Darwin, power alignment is ABI-incompatible with some C
library functions, so warn about it. The flag may be useful for
performance studies from time to time though, so don't disable it
@@ -2970,11 +3224,6 @@ rs6000_option_override_internal (bool global_init_p)
}
else if (TARGET_PAIRED_FLOAT)
msg = N_("-mvsx and -mpaired are incompatible");
- /* The hardware will allow VSX and little endian, but until we make sure
- things like vector select, etc. work don't allow VSX on little endian
- systems at this point. */
- else if (!BYTES_BIG_ENDIAN)
- msg = N_("-mvsx used with little endian code");
else if (TARGET_AVOID_XFORM > 0)
msg = N_("-mvsx needs indexed addressing");
else if (!TARGET_ALTIVEC && (rs6000_isa_flags_explicit
@@ -3664,7 +3913,7 @@ rs6000_option_override_internal (bool global_init_p)
/* Save the initial options in case the user does function specific options */
if (global_init_p)
target_option_default_node = target_option_current_node
- = build_target_option_node ();
+ = build_target_option_node (&global_options);
/* If not explicitly specified via option, decide whether to generate the
extra blr's required to preserve the link stack on some cpus (eg, 476). */
@@ -4734,15 +4983,16 @@ vspltis_constant (rtx op, unsigned step, unsigned copies)
/* Check if VAL is present in every STEP-th element, and the
other elements are filled with its most significant bit. */
- for (i = 0; i < nunits - 1; ++i)
+ for (i = 1; i < nunits; ++i)
{
HOST_WIDE_INT desired_val;
- if (((BYTES_BIG_ENDIAN ? i + 1 : i) & (step - 1)) == 0)
+ unsigned elt = BYTES_BIG_ENDIAN ? nunits - 1 - i : i;
+ if ((i & (step - 1)) == 0)
desired_val = val;
else
desired_val = msb_val;
- if (desired_val != const_vector_elt_as_int (op, i))
+ if (desired_val != const_vector_elt_as_int (op, elt))
return false;
}
@@ -5277,10 +5527,27 @@ rs6000_expand_vector_set (rtx target, rtx val, int elt)
XVECEXP (mask, 0, elt*width + i)
= GEN_INT (i + 0x10);
x = gen_rtx_CONST_VECTOR (V16QImode, XVEC (mask, 0));
- x = gen_rtx_UNSPEC (mode,
- gen_rtvec (3, target, reg,
- force_reg (V16QImode, x)),
- UNSPEC_VPERM);
+
+ if (BYTES_BIG_ENDIAN)
+ x = gen_rtx_UNSPEC (mode,
+ gen_rtvec (3, target, reg,
+ force_reg (V16QImode, x)),
+ UNSPEC_VPERM);
+ else
+ {
+ /* Invert selector. */
+ rtx splat = gen_rtx_VEC_DUPLICATE (V16QImode,
+ gen_rtx_CONST_INT (QImode, -1));
+ rtx tmp = gen_reg_rtx (V16QImode);
+ emit_move_insn (tmp, splat);
+ x = gen_rtx_MINUS (V16QImode, tmp, force_reg (V16QImode, x));
+ emit_move_insn (tmp, x);
+
+ /* Permute with operands reversed and adjusted selector. */
+ x = gen_rtx_UNSPEC (mode, gen_rtvec (3, reg, target, tmp),
+ UNSPEC_VPERM);
+ }
+
emit_insn (gen_rtx_SET (VOIDmode, target, x));
}
@@ -5978,7 +6245,7 @@ rs6000_legitimate_offset_address_p (enum machine_mode mode, rtx x,
return false;
if (!reg_offset_addressing_ok_p (mode))
return virtual_stack_registers_memory_p (x);
- if (legitimate_constant_pool_address_p (x, mode, strict))
+ if (legitimate_constant_pool_address_p (x, mode, strict || lra_in_progress))
return true;
if (GET_CODE (XEXP (x, 1)) != CONST_INT)
return false;
@@ -6118,9 +6385,21 @@ legitimate_lo_sum_address_p (enum machine_mode mode, rtx x, int strict)
if (TARGET_ELF || TARGET_MACHO)
{
+ bool large_toc_ok;
+
if (DEFAULT_ABI != ABI_AIX && DEFAULT_ABI != ABI_DARWIN && flag_pic)
return false;
- if (TARGET_TOC)
+ /* LRA don't use LEGITIMIZE_RELOAD_ADDRESS as it usually calls
+ push_reload from reload pass code. LEGITIMIZE_RELOAD_ADDRESS
+ recognizes some LO_SUM addresses as valid although this
+ function says opposite. In most cases, LRA through different
+ transformations can generate correct code for address reloads.
+ It can not manage only some LO_SUM cases. So we need to add
+ code analogous to one in rs6000_legitimize_reload_address for
+ LOW_SUM here saying that some addresses are still valid. */
+ large_toc_ok = (lra_in_progress && TARGET_CMODEL != CMODEL_SMALL
+ && small_toc_ref (x, VOIDmode));
+ if (TARGET_TOC && ! large_toc_ok)
return false;
if (GET_MODE_NUNITS (mode) != 1)
return false;
@@ -6130,7 +6409,7 @@ legitimate_lo_sum_address_p (enum machine_mode mode, rtx x, int strict)
&& (mode == DFmode || mode == DDmode)))
return false;
- return CONSTANT_P (x);
+ return CONSTANT_P (x) || large_toc_ok;
}
return false;
@@ -7110,17 +7389,9 @@ rs6000_legitimate_address_p (enum machine_mode mode, rtx x, bool reg_ok_strict)
return 0;
if (legitimate_indirect_address_p (x, reg_ok_strict))
return 1;
- if ((GET_CODE (x) == PRE_INC || GET_CODE (x) == PRE_DEC)
- && !ALTIVEC_OR_VSX_VECTOR_MODE (mode)
- && !SPE_VECTOR_MODE (mode)
- && mode != TFmode
- && mode != TDmode
- && mode != TImode
- && mode != PTImode
- /* Restrict addressing for DI because of our SUBREG hackery. */
- && !(TARGET_E500_DOUBLE
- && (mode == DFmode || mode == DDmode || mode == DImode))
- && TARGET_UPDATE
+ if (TARGET_UPDATE
+ && (GET_CODE (x) == PRE_INC || GET_CODE (x) == PRE_DEC)
+ && mode_supports_pre_incdec_p (mode)
&& legitimate_indirect_address_p (XEXP (x, 0), reg_ok_strict))
return 1;
if (virtual_stack_registers_memory_p (x))
@@ -7128,14 +7399,15 @@ rs6000_legitimate_address_p (enum machine_mode mode, rtx x, bool reg_ok_strict)
if (reg_offset_p && legitimate_small_data_p (mode, x))
return 1;
if (reg_offset_p
- && legitimate_constant_pool_address_p (x, mode, reg_ok_strict))
+ && legitimate_constant_pool_address_p (x, mode,
+ reg_ok_strict || lra_in_progress))
return 1;
- /* For TImode, if we have load/store quad, only allow register indirect
- addresses. This will allow the values to go in either GPRs or VSX
- registers without reloading. The vector types would tend to go into VSX
- registers, so we allow REG+REG, while TImode seems somewhat split, in that
- some uses are GPR based, and some VSX based. */
- if (mode == TImode && TARGET_QUAD_MEMORY)
+ /* For TImode, if we have load/store quad and TImode in VSX registers, only
+ allow register indirect addresses. This will allow the values to go in
+ either GPRs or VSX registers without reloading. The vector types would
+ tend to go into VSX registers, so we allow REG+REG, while TImode seems
+ somewhat split, in that some uses are GPR based, and some VSX based. */
+ if (mode == TImode && TARGET_QUAD_MEMORY && TARGET_VSX_TIMODE)
return 0;
/* If not REG_OK_STRICT (before reload) let pass any stack offset. */
if (! reg_ok_strict
@@ -7160,21 +7432,8 @@ rs6000_legitimate_address_p (enum machine_mode mode, rtx x, bool reg_ok_strict)
&& !avoiding_indexed_address_p (mode)
&& legitimate_indexed_address_p (x, reg_ok_strict))
return 1;
- if (GET_CODE (x) == PRE_MODIFY
- && mode != TImode
- && mode != PTImode
- && mode != TFmode
- && mode != TDmode
- && ((TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT)
- || TARGET_POWERPC64
- || ((mode != DFmode && mode != DDmode) || TARGET_E500_DOUBLE))
- && (TARGET_POWERPC64 || mode != DImode)
- && !ALTIVEC_OR_VSX_VECTOR_MODE (mode)
- && !SPE_VECTOR_MODE (mode)
- /* Restrict addressing for DI because of our SUBREG hackery. */
- && !(TARGET_E500_DOUBLE
- && (mode == DFmode || mode == DDmode || mode == DImode))
- && TARGET_UPDATE
+ if (TARGET_UPDATE && GET_CODE (x) == PRE_MODIFY
+ && mode_supports_pre_modify_p (mode)
&& legitimate_indirect_address_p (XEXP (x, 0), reg_ok_strict)
&& (rs6000_legitimate_offset_address_p (mode, XEXP (x, 1),
reg_ok_strict, false)
@@ -7195,10 +7454,13 @@ rs6000_debug_legitimate_address_p (enum machine_mode mode, rtx x,
bool ret = rs6000_legitimate_address_p (mode, x, reg_ok_strict);
fprintf (stderr,
"\nrs6000_legitimate_address_p: return = %s, mode = %s, "
- "strict = %d, code = %s\n",
+ "strict = %d, reload = %s, code = %s\n",
ret ? "true" : "false",
GET_MODE_NAME (mode),
reg_ok_strict,
+ (reload_completed
+ ? "after"
+ : (reload_in_progress ? "progress" : "before")),
GET_RTX_NAME (GET_CODE (x)));
debug_rtx (x);
@@ -7424,6 +7686,7 @@ rs6000_conditional_register_usage (void)
fixed_regs[i] = call_used_regs[i] = call_really_used_regs[i] = 1;
}
}
+
/* Try to output insns to set TARGET equal to the constant C if it can
be done in less than N insns. Do all computations in MODE.
@@ -7610,6 +7873,106 @@ rs6000_eliminate_indexed_memrefs (rtx operands[2])
copy_addr_to_reg (XEXP (operands[1], 0)));
}
+/* Generate a vector of constants to permute MODE for a little-endian
+ storage operation by swapping the two halves of a vector. */
+static rtvec
+rs6000_const_vec (enum machine_mode mode)
+{
+ int i, subparts;
+ rtvec v;
+
+ switch (mode)
+ {
+ case V2DFmode:
+ case V2DImode:
+ subparts = 2;
+ break;
+ case V4SFmode:
+ case V4SImode:
+ subparts = 4;
+ break;
+ case V8HImode:
+ subparts = 8;
+ break;
+ case V16QImode:
+ subparts = 16;
+ break;
+ default:
+ gcc_unreachable();
+ }
+
+ v = rtvec_alloc (subparts);
+
+ for (i = 0; i < subparts / 2; ++i)
+ RTVEC_ELT (v, i) = gen_rtx_CONST_INT (DImode, i + subparts / 2);
+ for (i = subparts / 2; i < subparts; ++i)
+ RTVEC_ELT (v, i) = gen_rtx_CONST_INT (DImode, i - subparts / 2);
+
+ return v;
+}
+
+/* Generate a permute rtx that represents an lxvd2x, stxvd2x, or xxpermdi
+ for a VSX load or store operation. */
+rtx
+rs6000_gen_le_vsx_permute (rtx source, enum machine_mode mode)
+{
+ rtx par = gen_rtx_PARALLEL (VOIDmode, rs6000_const_vec (mode));
+ return gen_rtx_VEC_SELECT (mode, source, par);
+}
+
+/* Emit a little-endian load from vector memory location SOURCE to VSX
+ register DEST in mode MODE. The load is done with two permuting
+ insn's that represent an lxvd2x and xxpermdi. */
+void
+rs6000_emit_le_vsx_load (rtx dest, rtx source, enum machine_mode mode)
+{
+ rtx tmp = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (dest) : dest;
+ rtx permute_mem = rs6000_gen_le_vsx_permute (source, mode);
+ rtx permute_reg = rs6000_gen_le_vsx_permute (tmp, mode);
+ emit_insn (gen_rtx_SET (VOIDmode, tmp, permute_mem));
+ emit_insn (gen_rtx_SET (VOIDmode, dest, permute_reg));
+}
+
+/* Emit a little-endian store to vector memory location DEST from VSX
+ register SOURCE in mode MODE. The store is done with two permuting
+ insn's that represent an xxpermdi and an stxvd2x. */
+void
+rs6000_emit_le_vsx_store (rtx dest, rtx source, enum machine_mode mode)
+{
+ rtx tmp = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (source) : source;
+ rtx permute_src = rs6000_gen_le_vsx_permute (source, mode);
+ rtx permute_tmp = rs6000_gen_le_vsx_permute (tmp, mode);
+ emit_insn (gen_rtx_SET (VOIDmode, tmp, permute_src));
+ emit_insn (gen_rtx_SET (VOIDmode, dest, permute_tmp));
+}
+
+/* Emit a sequence representing a little-endian VSX load or store,
+ moving data from SOURCE to DEST in mode MODE. This is done
+ separately from rs6000_emit_move to ensure it is called only
+ during expand. LE VSX loads and stores introduced later are
+ handled with a split. The expand-time RTL generation allows
+ us to optimize away redundant pairs of register-permutes. */
+void
+rs6000_emit_le_vsx_move (rtx dest, rtx source, enum machine_mode mode)
+{
+ gcc_assert (!BYTES_BIG_ENDIAN
+ && VECTOR_MEM_VSX_P (mode)
+ && mode != TImode
+ && (MEM_P (source) ^ MEM_P (dest)));
+
+ if (MEM_P (source))
+ {
+ gcc_assert (REG_P (dest));
+ rs6000_emit_le_vsx_load (dest, source, mode);
+ }
+ else
+ {
+ if (!REG_P (source))
+ source = force_reg (mode, source);
+ rs6000_emit_le_vsx_store (dest, source, mode);
+ }
+}
+
/* Emit a move from SOURCE to DEST in mode MODE. */
void
rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode)
@@ -7728,6 +8091,68 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode)
cfun->machine->sdmode_stack_slot =
eliminate_regs (cfun->machine->sdmode_stack_slot, VOIDmode, NULL_RTX);
+
+ if (lra_in_progress
+ && mode == SDmode
+ && REG_P (operands[0]) && REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER
+ && reg_preferred_class (REGNO (operands[0])) == NO_REGS
+ && (REG_P (operands[1])
+ || (GET_CODE (operands[1]) == SUBREG
+ && REG_P (SUBREG_REG (operands[1])))))
+ {
+ int regno = REGNO (GET_CODE (operands[1]) == SUBREG
+ ? SUBREG_REG (operands[1]) : operands[1]);
+ enum reg_class cl;
+
+ if (regno >= FIRST_PSEUDO_REGISTER)
+ {
+ cl = reg_preferred_class (regno);
+ gcc_assert (cl != NO_REGS);
+ regno = ira_class_hard_regs[cl][0];
+ }
+ if (FP_REGNO_P (regno))
+ {
+ if (GET_MODE (operands[0]) != DDmode)
+ operands[0] = gen_rtx_SUBREG (DDmode, operands[0], 0);
+ emit_insn (gen_movsd_store (operands[0], operands[1]));
+ }
+ else if (INT_REGNO_P (regno))
+ emit_insn (gen_movsd_hardfloat (operands[0], operands[1]));
+ else
+ gcc_unreachable();
+ return;
+ }
+ if (lra_in_progress
+ && mode == SDmode
+ && (REG_P (operands[0])
+ || (GET_CODE (operands[0]) == SUBREG
+ && REG_P (SUBREG_REG (operands[0]))))
+ && REG_P (operands[1]) && REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER
+ && reg_preferred_class (REGNO (operands[1])) == NO_REGS)
+ {
+ int regno = REGNO (GET_CODE (operands[0]) == SUBREG
+ ? SUBREG_REG (operands[0]) : operands[0]);
+ enum reg_class cl;
+
+ if (regno >= FIRST_PSEUDO_REGISTER)
+ {
+ cl = reg_preferred_class (regno);
+ gcc_assert (cl != NO_REGS);
+ regno = ira_class_hard_regs[cl][0];
+ }
+ if (FP_REGNO_P (regno))
+ {
+ if (GET_MODE (operands[1]) != DDmode)
+ operands[1] = gen_rtx_SUBREG (DDmode, operands[1], 0);
+ emit_insn (gen_movsd_load (operands[0], operands[1]));
+ }
+ else if (INT_REGNO_P (regno))
+ emit_insn (gen_movsd_hardfloat (operands[0], operands[1]));
+ else
+ gcc_unreachable();
+ return;
+ }
+
if (reload_in_progress
&& mode == SDmode
&& cfun->machine->sdmode_stack_slot != NULL_RTX
@@ -8179,7 +8604,7 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,
{
tree ret_type = TREE_TYPE (fntype);
fprintf (stderr, " ret code = %s,",
- tree_code_name[ (int)TREE_CODE (ret_type) ]);
+ get_tree_code_name (TREE_CODE (ret_type)));
}
if (cum->call_cookie & CALL_LONG)
@@ -14575,6 +15000,17 @@ rs6000_secondary_memory_needed_rtx (enum machine_mode mode)
return ret;
}
+/* Return the mode to be used for memory when a secondary memory
+ location is needed. For SDmode values we need to use DDmode, in
+ all other cases we can use the same mode. */
+enum machine_mode
+rs6000_secondary_memory_needed_mode (enum machine_mode mode)
+{
+ if (mode == SDmode)
+ return DDmode;
+ return mode;
+}
+
static tree
rs6000_check_sdmode (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
{
@@ -14705,7 +15141,7 @@ rs6000_secondary_reload_direct_move (enum rs6000_reg_type to_type,
if (to_type == VSX_REG_TYPE && from_type == GPR_REG_TYPE)
{
cost = 3; /* 2 mtvsrd's, 1 xxpermdi. */
- icode = reload_vsx_gpr[(int)mode];
+ icode = reg_addr[mode].reload_vsx_gpr;
}
/* Handle moving 128-bit values from VSX point registers to GPRs on
@@ -14714,7 +15150,7 @@ rs6000_secondary_reload_direct_move (enum rs6000_reg_type to_type,
else if (to_type == GPR_REG_TYPE && from_type == VSX_REG_TYPE)
{
cost = 3; /* 2 mfvsrd's, 1 xxpermdi. */
- icode = reload_gpr_vsx[(int)mode];
+ icode = reg_addr[mode].reload_gpr_vsx;
}
}
@@ -14723,13 +15159,13 @@ rs6000_secondary_reload_direct_move (enum rs6000_reg_type to_type,
if (to_type == GPR_REG_TYPE && from_type == VSX_REG_TYPE)
{
cost = 3; /* xscvdpspn, mfvsrd, and. */
- icode = reload_gpr_vsx[(int)mode];
+ icode = reg_addr[mode].reload_gpr_vsx;
}
else if (to_type == VSX_REG_TYPE && from_type == GPR_REG_TYPE)
{
cost = 2; /* mtvsrz, xscvspdpn. */
- icode = reload_vsx_gpr[(int)mode];
+ icode = reg_addr[mode].reload_vsx_gpr;
}
}
}
@@ -14742,7 +15178,7 @@ rs6000_secondary_reload_direct_move (enum rs6000_reg_type to_type,
if (to_type == VSX_REG_TYPE && from_type == GPR_REG_TYPE)
{
cost = 3; /* 2 mtvsrd's, 1 xxpermdi. */
- icode = reload_vsx_gpr[(int)mode];
+ icode = reg_addr[mode].reload_vsx_gpr;
}
/* Handle moving 128-bit values from VSX point registers to GPRs on
@@ -14751,7 +15187,7 @@ rs6000_secondary_reload_direct_move (enum rs6000_reg_type to_type,
else if (to_type == GPR_REG_TYPE && from_type == VSX_REG_TYPE)
{
cost = 3; /* 2 mfvsrd's, 1 xxpermdi. */
- icode = reload_gpr_vsx[(int)mode];
+ icode = reg_addr[mode].reload_gpr_vsx;
}
}
@@ -14767,7 +15203,7 @@ rs6000_secondary_reload_direct_move (enum rs6000_reg_type to_type,
if (to_type == VSX_REG_TYPE && from_type == GPR_REG_TYPE && !altivec_p)
{
cost = 3; /* 2 mtvsrwz's, 1 fmrgow. */
- icode = reload_fpr_gpr[(int)mode];
+ icode = reg_addr[mode].reload_fpr_gpr;
}
}
@@ -14850,7 +15286,9 @@ rs6000_secondary_reload (bool in_p,
bool default_p = false;
sri->icode = CODE_FOR_nothing;
- icode = rs6000_vector_reload[mode][in_p != false];
+ icode = ((in_p)
+ ? reg_addr[mode].reload_load
+ : reg_addr[mode].reload_store);
if (REG_P (x) || register_operand (x, mode))
{
@@ -14865,6 +15303,7 @@ rs6000_secondary_reload (bool in_p,
from_type = exchange;
}
+ /* Can we do a direct move of some sort? */
if (rs6000_secondary_reload_move (to_type, from_type, mode, sri,
altivec_p))
{
@@ -15465,6 +15904,10 @@ rs6000_alloc_sdmode_stack_slot (void)
gimple_stmt_iterator gsi;
gcc_assert (cfun->machine->sdmode_stack_slot == NULL_RTX);
+ /* We use a different approach for dealing with the secondary
+ memory in LRA. */
+ if (ira_use_lra_p)
+ return;
if (TARGET_NO_SDMODE_STACK)
return;
@@ -15686,7 +16129,7 @@ rs6000_secondary_reload_class (enum reg_class rclass, enum machine_mode mode,
/* Constants, memory, and FP registers can go into FP registers. */
if ((regno == -1 || FP_REGNO_P (regno))
&& (rclass == FLOAT_REGS || rclass == NON_SPECIAL_REGS))
- return (mode != SDmode) ? NO_REGS : GENERAL_REGS;
+ return (mode != SDmode || lra_in_progress) ? NO_REGS : GENERAL_REGS;
/* Memory, and FP/altivec registers can go into fp/altivec registers under
VSX. However, for scalar variables, use the traditional floating point
@@ -15838,21 +16281,21 @@ rs6000_output_move_128bit (rtx operands[])
enum machine_mode mode = GET_MODE (dest);
int dest_regno;
int src_regno;
- bool dest_gpr_p, dest_fp_p, dest_av_p, dest_vsx_p;
- bool src_gpr_p, src_fp_p, src_av_p, src_vsx_p;
+ bool dest_gpr_p, dest_fp_p, dest_vmx_p, dest_vsx_p;
+ bool src_gpr_p, src_fp_p, src_vmx_p, src_vsx_p;
if (REG_P (dest))
{
dest_regno = REGNO (dest);
dest_gpr_p = INT_REGNO_P (dest_regno);
dest_fp_p = FP_REGNO_P (dest_regno);
- dest_av_p = ALTIVEC_REGNO_P (dest_regno);
- dest_vsx_p = dest_fp_p | dest_av_p;
+ dest_vmx_p = ALTIVEC_REGNO_P (dest_regno);
+ dest_vsx_p = dest_fp_p | dest_vmx_p;
}
else
{
dest_regno = -1;
- dest_gpr_p = dest_fp_p = dest_av_p = dest_vsx_p = false;
+ dest_gpr_p = dest_fp_p = dest_vmx_p = dest_vsx_p = false;
}
if (REG_P (src))
@@ -15860,13 +16303,13 @@ rs6000_output_move_128bit (rtx operands[])
src_regno = REGNO (src);
src_gpr_p = INT_REGNO_P (src_regno);
src_fp_p = FP_REGNO_P (src_regno);
- src_av_p = ALTIVEC_REGNO_P (src_regno);
- src_vsx_p = src_fp_p | src_av_p;
+ src_vmx_p = ALTIVEC_REGNO_P (src_regno);
+ src_vsx_p = src_fp_p | src_vmx_p;
}
else
{
src_regno = -1;
- src_gpr_p = src_fp_p = src_av_p = src_vsx_p = false;
+ src_gpr_p = src_fp_p = src_vmx_p = src_vsx_p = false;
}
/* Register moves. */
@@ -15890,7 +16333,7 @@ rs6000_output_move_128bit (rtx operands[])
return "#";
}
- else if (TARGET_ALTIVEC && dest_av_p && src_av_p)
+ else if (TARGET_ALTIVEC && dest_vmx_p && src_vmx_p)
return "vor %0,%1,%1";
else if (dest_fp_p && src_fp_p)
@@ -15902,18 +16345,13 @@ rs6000_output_move_128bit (rtx operands[])
{
if (dest_gpr_p)
{
- if (TARGET_QUAD_MEMORY && (dest_regno & 1) == 0
- && quad_memory_operand (src, mode)
- && !reg_overlap_mentioned_p (dest, src))
- {
- /* lq/stq only has DQ-form, so avoid X-form that %y produces. */
- return REG_P (XEXP (src, 0)) ? "lq %0,%1" : "lq %0,%y1";
- }
+ if (TARGET_QUAD_MEMORY && quad_load_store_p (dest, src))
+ return "lq %0,%1";
else
return "#";
}
- else if (TARGET_ALTIVEC && dest_av_p
+ else if (TARGET_ALTIVEC && dest_vmx_p
&& altivec_indexed_or_indirect_operand (src, mode))
return "lvx %0,%y1";
@@ -15925,7 +16363,7 @@ rs6000_output_move_128bit (rtx operands[])
return "lxvd2x %x0,%y1";
}
- else if (TARGET_ALTIVEC && dest_av_p)
+ else if (TARGET_ALTIVEC && dest_vmx_p)
return "lvx %0,%y1";
else if (dest_fp_p)
@@ -15937,17 +16375,13 @@ rs6000_output_move_128bit (rtx operands[])
{
if (src_gpr_p)
{
- if (TARGET_QUAD_MEMORY && (src_regno & 1) == 0
- && quad_memory_operand (dest, mode))
- {
- /* lq/stq only has DQ-form, so avoid X-form that %y produces. */
- return REG_P (XEXP (dest, 0)) ? "stq %1,%0" : "stq %1,%y0";
- }
+ if (TARGET_QUAD_MEMORY && quad_load_store_p (dest, src))
+ return "stq %1,%0";
else
return "#";
}
- else if (TARGET_ALTIVEC && src_av_p
+ else if (TARGET_ALTIVEC && src_vmx_p
&& altivec_indexed_or_indirect_operand (src, mode))
return "stvx %1,%y0";
@@ -15959,7 +16393,7 @@ rs6000_output_move_128bit (rtx operands[])
return "stxvd2x %x1,%y0";
}
- else if (TARGET_ALTIVEC && src_av_p)
+ else if (TARGET_ALTIVEC && src_vmx_p)
return "stvx %1,%y0";
else if (src_fp_p)
@@ -15978,7 +16412,7 @@ rs6000_output_move_128bit (rtx operands[])
else if (TARGET_VSX && dest_vsx_p && zero_constant (src, mode))
return "xxlxor %x0,%x0,%x0";
- else if (TARGET_ALTIVEC && dest_av_p)
+ else if (TARGET_ALTIVEC && dest_vmx_p)
return output_vec_const_move (operands);
}
@@ -17541,7 +17975,7 @@ output_cbranch (rtx op, const char *label, int reversed, rtx insn)
if (note != NULL_RTX)
{
/* PROB is the difference from 50%. */
- int prob = INTVAL (XEXP (note, 0)) - REG_BR_PROB_BASE / 2;
+ int prob = XINT (note, 0) - REG_BR_PROB_BASE / 2;
/* Only hint for highly probable/improbable branches on newer
cpus as static prediction overrides processor dynamic
@@ -18147,12 +18581,12 @@ rs6000_emit_minmax (rtx dest, enum rtx_code code, rtx op0, rtx op1)
static void
emit_unlikely_jump (rtx cond, rtx label)
{
- rtx very_unlikely = GEN_INT (REG_BR_PROB_BASE / 100 - 1);
+ int very_unlikely = REG_BR_PROB_BASE / 100 - 1;
rtx x;
x = gen_rtx_IF_THEN_ELSE (VOIDmode, cond, label, pc_rtx);
x = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, x));
- add_reg_note (x, REG_BR_PROB, very_unlikely);
+ add_int_reg_note (x, REG_BR_PROB, very_unlikely);
}
/* A subroutine of the atomic operation splitters. Emit a load-locked
@@ -21107,8 +21541,19 @@ rs6000_emit_prologue (void)
if (flag_stack_usage_info)
current_function_static_stack_size = info->total_size;
- if (flag_stack_check == STATIC_BUILTIN_STACK_CHECK && info->total_size)
- rs6000_emit_probe_stack_range (STACK_CHECK_PROTECT, info->total_size);
+ if (flag_stack_check == STATIC_BUILTIN_STACK_CHECK)
+ {
+ HOST_WIDE_INT size = info->total_size;
+
+ if (crtl->is_leaf && !cfun->calls_alloca)
+ {
+ if (size > PROBE_INTERVAL && size > STACK_CHECK_PROTECT)
+ rs6000_emit_probe_stack_range (STACK_CHECK_PROTECT,
+ size - STACK_CHECK_PROTECT);
+ }
+ else if (size > 0)
+ rs6000_emit_probe_stack_range (STACK_CHECK_PROTECT, size);
+ }
if (TARGET_FIX_AND_CONTINUE)
{
@@ -28368,6 +28813,136 @@ rs6000_emit_parity (rtx dst, rtx src)
}
}
+/* Expand an Altivec constant permutation for little endian mode.
+ There are two issues: First, the two input operands must be
+ swapped so that together they form a double-wide array in LE
+ order. Second, the vperm instruction has surprising behavior
+ in LE mode: it interprets the elements of the source vectors
+ in BE mode ("left to right") and interprets the elements of
+ the destination vector in LE mode ("right to left"). To
+ correct for this, we must subtract each element of the permute
+ control vector from 31.
+
+ For example, suppose we want to concatenate vr10 = {0, 1, 2, 3}
+ with vr11 = {4, 5, 6, 7} and extract {0, 2, 4, 6} using a vperm.
+ We place {0,1,2,3,8,9,10,11,16,17,18,19,24,25,26,27} in vr12 to
+ serve as the permute control vector. Then, in BE mode,
+
+ vperm 9,10,11,12
+
+ places the desired result in vr9. However, in LE mode the
+ vector contents will be
+
+ vr10 = 00000003 00000002 00000001 00000000
+ vr11 = 00000007 00000006 00000005 00000004
+
+ The result of the vperm using the same permute control vector is
+
+ vr9 = 05000000 07000000 01000000 03000000
+
+ That is, the leftmost 4 bytes of vr10 are interpreted as the
+ source for the rightmost 4 bytes of vr9, and so on.
+
+ If we change the permute control vector to
+
+ vr12 = {31,20,29,28,23,22,21,20,15,14,13,12,7,6,5,4}
+
+ and issue
+
+ vperm 9,11,10,12
+
+ we get the desired
+
+ vr9 = 00000006 00000004 00000002 00000000. */
+
+void
+altivec_expand_vec_perm_const_le (rtx operands[4])
+{
+ unsigned int i;
+ rtx perm[16];
+ rtx constv, unspec;
+ rtx target = operands[0];
+ rtx op0 = operands[1];
+ rtx op1 = operands[2];
+ rtx sel = operands[3];
+
+ /* Unpack and adjust the constant selector. */
+ for (i = 0; i < 16; ++i)
+ {
+ rtx e = XVECEXP (sel, 0, i);
+ unsigned int elt = 31 - (INTVAL (e) & 31);
+ perm[i] = GEN_INT (elt);
+ }
+
+ /* Expand to a permute, swapping the inputs and using the
+ adjusted selector. */
+ if (!REG_P (op0))
+ op0 = force_reg (V16QImode, op0);
+ if (!REG_P (op1))
+ op1 = force_reg (V16QImode, op1);
+
+ constv = gen_rtx_CONST_VECTOR (V16QImode, gen_rtvec_v (16, perm));
+ constv = force_reg (V16QImode, constv);
+ unspec = gen_rtx_UNSPEC (V16QImode, gen_rtvec (3, op1, op0, constv),
+ UNSPEC_VPERM);
+ if (!REG_P (target))
+ {
+ rtx tmp = gen_reg_rtx (V16QImode);
+ emit_move_insn (tmp, unspec);
+ unspec = tmp;
+ }
+
+ emit_move_insn (target, unspec);
+}
+
+/* Similarly to altivec_expand_vec_perm_const_le, we must adjust the
+ permute control vector. But here it's not a constant, so we must
+ generate a vector splat/subtract to do the adjustment. */
+
+void
+altivec_expand_vec_perm_le (rtx operands[4])
+{
+ rtx splat, unspec;
+ rtx target = operands[0];
+ rtx op0 = operands[1];
+ rtx op1 = operands[2];
+ rtx sel = operands[3];
+ rtx tmp = target;
+
+ /* Get everything in regs so the pattern matches. */
+ if (!REG_P (op0))
+ op0 = force_reg (V16QImode, op0);
+ if (!REG_P (op1))
+ op1 = force_reg (V16QImode, op1);
+ if (!REG_P (sel))
+ sel = force_reg (V16QImode, sel);
+ if (!REG_P (target))
+ tmp = gen_reg_rtx (V16QImode);
+
+ /* SEL = splat(31) - SEL. */
+ /* We want to subtract from 31, but we can't vspltisb 31 since
+ it's out of range. -1 works as well because only the low-order
+ five bits of the permute control vector elements are used. */
+ splat = gen_rtx_VEC_DUPLICATE (V16QImode,
+ gen_rtx_CONST_INT (QImode, -1));
+ emit_move_insn (tmp, splat);
+ sel = gen_rtx_MINUS (V16QImode, tmp, sel);
+ emit_move_insn (tmp, sel);
+
+ /* Permute with operands reversed and adjusted selector. */
+ unspec = gen_rtx_UNSPEC (V16QImode, gen_rtvec (3, op1, op0, tmp),
+ UNSPEC_VPERM);
+
+ /* Copy into target, possibly by way of a register. */
+ if (!REG_P (target))
+ {
+ emit_move_insn (tmp, unspec);
+ unspec = tmp;
+ }
+
+ emit_move_insn (target, unspec);
+}
+
/* Expand an Altivec constant permutation. Return true if we match
an efficient implementation; false to fall back to VPERM. */
@@ -28384,17 +28959,23 @@ altivec_expand_vec_perm_const (rtx operands[4])
{ 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31 } },
{ OPTION_MASK_ALTIVEC, CODE_FOR_altivec_vpkuwum,
{ 2, 3, 6, 7, 10, 11, 14, 15, 18, 19, 22, 23, 26, 27, 30, 31 } },
- { OPTION_MASK_ALTIVEC, CODE_FOR_altivec_vmrghb,
+ { OPTION_MASK_ALTIVEC,
+ BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrghb : CODE_FOR_altivec_vmrglb,
{ 0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23 } },
- { OPTION_MASK_ALTIVEC, CODE_FOR_altivec_vmrghh,
+ { OPTION_MASK_ALTIVEC,
+ BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrghh : CODE_FOR_altivec_vmrglh,
{ 0, 1, 16, 17, 2, 3, 18, 19, 4, 5, 20, 21, 6, 7, 22, 23 } },
- { OPTION_MASK_ALTIVEC, CODE_FOR_altivec_vmrghw,
+ { OPTION_MASK_ALTIVEC,
+ BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrghw : CODE_FOR_altivec_vmrglw,
{ 0, 1, 2, 3, 16, 17, 18, 19, 4, 5, 6, 7, 20, 21, 22, 23 } },
- { OPTION_MASK_ALTIVEC, CODE_FOR_altivec_vmrglb,
+ { OPTION_MASK_ALTIVEC,
+ BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrglb : CODE_FOR_altivec_vmrghb,
{ 8, 24, 9, 25, 10, 26, 11, 27, 12, 28, 13, 29, 14, 30, 15, 31 } },
- { OPTION_MASK_ALTIVEC, CODE_FOR_altivec_vmrglh,
+ { OPTION_MASK_ALTIVEC,
+ BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrglh : CODE_FOR_altivec_vmrghh,
{ 8, 9, 24, 25, 10, 11, 26, 27, 12, 13, 28, 29, 14, 15, 30, 31 } },
- { OPTION_MASK_ALTIVEC, CODE_FOR_altivec_vmrglw,
+ { OPTION_MASK_ALTIVEC,
+ BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrglw : CODE_FOR_altivec_vmrghw,
{ 8, 9, 10, 11, 24, 25, 26, 27, 12, 13, 14, 15, 28, 29, 30, 31 } },
{ OPTION_MASK_P8_VECTOR, CODE_FOR_p8_vmrgew,
{ 0, 1, 2, 3, 16, 17, 18, 19, 8, 9, 10, 11, 24, 25, 26, 27 } },
@@ -28527,6 +29108,26 @@ altivec_expand_vec_perm_const (rtx operands[4])
enum machine_mode omode = insn_data[icode].operand[0].mode;
enum machine_mode imode = insn_data[icode].operand[1].mode;
+ /* For little-endian, don't use vpkuwum and vpkuhum if the
+ underlying vector type is not V4SI and V8HI, respectively.
+ For example, using vpkuwum with a V8HI picks up the even
+ halfwords (BE numbering) when the even halfwords (LE
+ numbering) are what we need. */
+ if (!BYTES_BIG_ENDIAN
+ && icode == CODE_FOR_altivec_vpkuwum
+ && ((GET_CODE (op0) == REG
+ && GET_MODE (op0) != V4SImode)
+ || (GET_CODE (op0) == SUBREG
+ && GET_MODE (XEXP (op0, 0)) != V4SImode)))
+ continue;
+ if (!BYTES_BIG_ENDIAN
+ && icode == CODE_FOR_altivec_vpkuhum
+ && ((GET_CODE (op0) == REG
+ && GET_MODE (op0) != V8HImode)
+ || (GET_CODE (op0) == SUBREG
+ && GET_MODE (XEXP (op0, 0)) != V8HImode)))
+ continue;
+
/* For little-endian, the two input operands must be swapped
(or swapped back) to ensure proper right-to-left numbering
from 0 to 2N-1. */
@@ -28548,6 +29149,12 @@ altivec_expand_vec_perm_const (rtx operands[4])
}
}
+ if (!BYTES_BIG_ENDIAN)
+ {
+ altivec_expand_vec_perm_const_le (operands);
+ return true;
+ }
+
return false;
}
@@ -28878,6 +29485,13 @@ rs6000_libcall_value (enum machine_mode mode)
}
+/* Return true if we use LRA instead of reload pass. */
+static bool
+rs6000_lra_p (void)
+{
+ return rs6000_lra_flag;
+}
+
/* Given FROM and TO register numbers, say whether this elimination is allowed.
Frame pointer elimination is automatically handled.
@@ -28992,6 +29606,27 @@ rs6000_init_dwarf_reg_sizes_extra (tree address)
emit_move_insn (adjust_address (mem, mode, offset), value);
}
}
+
+ if (TARGET_MACHO && ! TARGET_ALTIVEC)
+ {
+ int i;
+ enum machine_mode mode = TYPE_MODE (char_type_node);
+ rtx addr = expand_expr (address, NULL_RTX, VOIDmode, EXPAND_NORMAL);
+ rtx mem = gen_rtx_MEM (BLKmode, addr);
+ rtx value = gen_int_mode (16, mode);
+
+ /* On Darwin, libgcc may be built to run on both G3 and G4/5.
+ The unwinder still needs to know the size of Altivec registers. */
+
+ for (i = FIRST_ALTIVEC_REGNO; i < LAST_ALTIVEC_REGNO+1; i++)
+ {
+ int column = DWARF_REG_TO_UNWIND_COLUMN (i);
+ HOST_WIDE_INT offset
+ = DWARF_FRAME_REGNUM (column) * GET_MODE_SIZE (mode);
+
+ emit_move_insn (adjust_address (mem, mode, offset), value);
+ }
+ }
}
/* Map internal gcc register numbers to DWARF2 register numbers. */
@@ -29162,6 +29797,8 @@ static struct rs6000_opt_mask const rs6000_opt_masks[] =
{ "recip-precision", OPTION_MASK_RECIP_PRECISION, false, true },
{ "string", OPTION_MASK_STRING, false, true },
{ "update", OPTION_MASK_NO_UPDATE, true , true },
+ { "upper-regs-df", OPTION_MASK_UPPER_REGS_DF, false, false },
+ { "upper-regs-sf", OPTION_MASK_UPPER_REGS_SF, false, false },
{ "vsx", OPTION_MASK_VSX, false, true },
{ "vsx-timode", OPTION_MASK_VSX_TIMODE, false, true },
#ifdef OPTION_MASK_64BIT
@@ -29434,7 +30071,7 @@ rs6000_valid_attribute_p (tree fndecl,
{
struct cl_target_option cur_target;
bool ret;
- tree old_optimize = build_optimization_node ();
+ tree old_optimize = build_optimization_node (&global_options);
tree new_target, new_optimize;
tree func_optimize = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl);
@@ -29461,7 +30098,7 @@ rs6000_valid_attribute_p (tree fndecl,
fprintf (stderr, "--------------------\n");
}
- old_optimize = build_optimization_node ();
+ old_optimize = build_optimization_node (&global_options);
func_optimize = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl);
/* If the function changed the optimization levels as well as setting target
@@ -29480,12 +30117,12 @@ rs6000_valid_attribute_p (tree fndecl,
if (ret)
{
ret = rs6000_option_override_internal (false);
- new_target = build_target_option_node ();
+ new_target = build_target_option_node (&global_options);
}
else
new_target = NULL;
- new_optimize = build_optimization_node ();
+ new_optimize = build_optimization_node (&global_options);
if (!new_target)
ret = false;
@@ -29515,7 +30152,7 @@ rs6000_valid_attribute_p (tree fndecl,
bool
rs6000_pragma_target_parse (tree args, tree pop_target)
{
- tree prev_tree = build_target_option_node ();
+ tree prev_tree = build_target_option_node (&global_options);
tree cur_tree;
struct cl_target_option *prev_opt, *cur_opt;
HOST_WIDE_INT prev_flags, cur_flags, diff_flags;
@@ -29552,7 +30189,8 @@ rs6000_pragma_target_parse (tree args, tree pop_target)
rs6000_cpu_index = rs6000_tune_index = -1;
if (!rs6000_inner_target_options (args, false)
|| !rs6000_option_override_internal (false)
- || (cur_tree = build_target_option_node ()) == NULL_TREE)
+ || (cur_tree = build_target_option_node (&global_options))
+ == NULL_TREE)
{
if (TARGET_DEBUG_BUILTIN || TARGET_DEBUG_TARGET)
fprintf (stderr, "invalid pragma\n");
@@ -29677,19 +30315,22 @@ rs6000_set_current_function (tree fndecl)
/* Save the current options */
static void
-rs6000_function_specific_save (struct cl_target_option *ptr)
+rs6000_function_specific_save (struct cl_target_option *ptr,
+ struct gcc_options *opts)
{
- ptr->x_rs6000_isa_flags = rs6000_isa_flags;
- ptr->x_rs6000_isa_flags_explicit = rs6000_isa_flags_explicit;
+ ptr->x_rs6000_isa_flags = opts->x_rs6000_isa_flags;
+ ptr->x_rs6000_isa_flags_explicit = opts->x_rs6000_isa_flags_explicit;
}
/* Restore the current options */
static void
-rs6000_function_specific_restore (struct cl_target_option *ptr)
+rs6000_function_specific_restore (struct gcc_options *opts,
+ struct cl_target_option *ptr)
+
{
- rs6000_isa_flags = ptr->x_rs6000_isa_flags;
- rs6000_isa_flags_explicit = ptr->x_rs6000_isa_flags_explicit;
+ opts->x_rs6000_isa_flags = ptr->x_rs6000_isa_flags;
+ opts->x_rs6000_isa_flags_explicit = ptr->x_rs6000_isa_flags_explicit;
(void) rs6000_option_override_internal (false);
}
@@ -29722,7 +30363,6 @@ rs6000_print_options_internal (FILE *file,
size_t cur_column;
size_t max_column = 76;
const char *comma = "";
- const char *nl = "\n";
if (indent)
start_column += fprintf (file, "%*s", indent, "");
@@ -29753,7 +30393,6 @@ rs6000_print_options_internal (FILE *file,
fprintf (stderr, ", \\\n%*s", (int)start_column, "");
cur_column = start_column + len;
comma = "";
- nl = "\n\n";
}
fprintf (file, "%s%s%s%s", comma, prefix, no_str,
@@ -29763,7 +30402,7 @@ rs6000_print_options_internal (FILE *file,
}
}
- fputs (nl, file);
+ fputs ("\n", file);
}
/* Helper function to print the current isa options on a line. */
diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h
index a5a7a859426..f13951eb235 100644
--- a/gcc/config/rs6000/rs6000.h
+++ b/gcc/config/rs6000/rs6000.h
@@ -593,9 +593,6 @@ extern int rs6000_vector_align[];
#define MASK_PROTOTYPE OPTION_MASK_PROTOTYPE
#endif
-/* Explicit ISA options that were set. */
-#define rs6000_isa_flags_explicit global_options_set.x_rs6000_isa_flags
-
/* For power systems, we want to enable Altivec and VSX builtins even if the
user did not use -maltivec or -mvsx to allow the builtins to be used inside
of #pragma GCC target or the target attribute to change the code level for a
@@ -617,6 +614,25 @@ extern int rs6000_vector_align[];
|| rs6000_cpu == PROCESSOR_PPC8548)
+/* Whether SF/DF operations are supported on the E500. */
+#define TARGET_SF_SPE (TARGET_HARD_FLOAT && TARGET_SINGLE_FLOAT \
+ && !TARGET_FPRS)
+
+#define TARGET_DF_SPE (TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT \
+ && !TARGET_FPRS && TARGET_E500_DOUBLE)
+
+/* Whether SF/DF operations are supported by by the normal floating point unit
+ (or the vector/scalar unit). */
+#define TARGET_SF_FPR (TARGET_HARD_FLOAT && TARGET_FPRS \
+ && TARGET_SINGLE_FLOAT)
+
+#define TARGET_DF_FPR (TARGET_HARD_FLOAT && TARGET_FPRS \
+ && TARGET_DOUBLE_FLOAT)
+
+/* Whether SF/DF operations are supported by any hardware. */
+#define TARGET_SF_INSN (TARGET_SF_FPR || TARGET_SF_SPE)
+#define TARGET_DF_INSN (TARGET_DF_FPR || TARGET_DF_SPE)
+
/* Which machine supports the various reciprocal estimate instructions. */
#define TARGET_FRES (TARGET_HARD_FLOAT && TARGET_PPC_GFXOPT \
&& TARGET_FPRS && TARGET_SINGLE_FLOAT)
@@ -1403,15 +1419,18 @@ enum r6000_reg_class_enum {
RS6000_CONSTRAINT_v, /* Altivec registers */
RS6000_CONSTRAINT_wa, /* Any VSX register */
RS6000_CONSTRAINT_wd, /* VSX register for V2DF */
- RS6000_CONSTRAINT_wg, /* FPR register for -mmfpgpr */
RS6000_CONSTRAINT_wf, /* VSX register for V4SF */
+ RS6000_CONSTRAINT_wg, /* FPR register for -mmfpgpr */
RS6000_CONSTRAINT_wl, /* FPR register for LFIWAX */
RS6000_CONSTRAINT_wm, /* VSX register for direct move */
RS6000_CONSTRAINT_wr, /* GPR register if 64-bit */
RS6000_CONSTRAINT_ws, /* VSX register for DF */
RS6000_CONSTRAINT_wt, /* VSX register for TImode */
- RS6000_CONSTRAINT_wv, /* Altivec register for power8 vector */
+ RS6000_CONSTRAINT_wu, /* Altivec register for float load/stores. */
+ RS6000_CONSTRAINT_wv, /* Altivec register for double load/stores. */
+ RS6000_CONSTRAINT_ww, /* FP or VSX register for vsx float ops. */
RS6000_CONSTRAINT_wx, /* FPR register for STFIWX */
+ RS6000_CONSTRAINT_wy, /* VSX register for SF */
RS6000_CONSTRAINT_wz, /* FPR register for LFIWZX */
RS6000_CONSTRAINT_MAX
};
@@ -1469,6 +1488,13 @@ extern enum reg_class rs6000_constraints[RS6000_CONSTRAINT_MAX];
#define SECONDARY_MEMORY_NEEDED_RTX(MODE) \
rs6000_secondary_memory_needed_rtx (MODE)
+/* Specify the mode to be used for memory when a secondary memory
+ location is needed. For cpus that cannot load/store SDmode values
+ from the 64-bit FP registers without using a full 64-bit
+ load/store, we need a wider mode. */
+#define SECONDARY_MEMORY_NEEDED_MODE(MODE) \
+ rs6000_secondary_memory_needed_mode (MODE)
+
/* Return the maximum number of consecutive registers
needed to represent mode MODE in a register of class CLASS.
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 9f749f9a591..3f13c4603f7 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -87,6 +87,7 @@
UNSPEC_FRIP
UNSPEC_FRIZ
UNSPEC_LD_MPIC ; load_macho_picbase
+ UNSPEC_RELD_MPIC ; re-load_macho_picbase
UNSPEC_MPIC_CORRECT ; macho_correct_pic
UNSPEC_TLSGD
UNSPEC_TLSLD
@@ -150,6 +151,7 @@
UNSPECV_EH_RR ; eh_reg_restore
UNSPECV_ISYNC ; isync instruction
UNSPECV_MFTB ; move from time base
+ UNSPECV_NLGR ; non-local goto receiver
])
@@ -314,13 +316,13 @@
(define_mode_attr f32_lr [(SF "f") (SD "wz")])
(define_mode_attr f32_lm [(SF "m") (SD "Z")])
(define_mode_attr f32_li [(SF "lfs%U1%X1 %0,%1") (SD "lfiwzx %0,%y1")])
-(define_mode_attr f32_lv [(SF "lxsspx %0,%y1") (SD "lxsiwzx %0,%y1")])
+(define_mode_attr f32_lv [(SF "lxsspx %x0,%y1") (SD "lxsiwzx %x0,%y1")])
; Definitions for store from 32-bit fpr register
(define_mode_attr f32_sr [(SF "f") (SD "wx")])
(define_mode_attr f32_sm [(SF "m") (SD "Z")])
(define_mode_attr f32_si [(SF "stfs%U0%X0 %1,%0") (SD "stfiwx %1,%y0")])
-(define_mode_attr f32_sv [(SF "stxsspx %1,%y0") (SD "stxsiwzx %1,%y0")])
+(define_mode_attr f32_sv [(SF "stxsspx %x1,%y0") (SD "stxsiwzx %x1,%y0")])
; Definitions for 32-bit fpr direct move
(define_mode_attr f32_dm [(SF "wn") (SD "wm")])
@@ -335,6 +337,25 @@
; Iterator for just SF/DF
(define_mode_iterator SFDF [SF DF])
+; SF/DF suffix for traditional floating instructions
+(define_mode_attr Ftrad [(SF "s") (DF "")])
+
+; SF/DF suffix for VSX instructions
+(define_mode_attr Fvsx [(SF "sp") (DF "dp")])
+
+; SF/DF constraint for arithmetic on traditional floating point registers
+(define_mode_attr Ff [(SF "f") (DF "d")])
+
+; SF/DF constraint for arithmetic on VSX registers
+(define_mode_attr Fv [(SF "wy") (DF "ws")])
+
+; s/d suffix for things like fp_addsub_s/fp_addsub_d
+(define_mode_attr Fs [(SF "s") (DF "d")])
+
+; FRE/FRES support
+(define_mode_attr Ffre [(SF "fres") (DF "fre")])
+(define_mode_attr FFRE [(SF "FRES") (DF "FRE")])
+
; Conditional returns.
(define_code_iterator any_return [return simple_return])
(define_code_attr return_pred [(return "direct_return ()")
@@ -541,7 +562,7 @@
"")
(define_insn "*zero_extendsidi2_lfiwzx"
- [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,??wm,!wz,!wm")
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,??wm,!wz,!wu")
(zero_extend:DI (match_operand:SI 1 "reg_or_mem_operand" "m,r,r,Z,Z")))]
"TARGET_POWERPC64 && TARGET_LFIWZX"
"@
@@ -711,7 +732,7 @@
"")
(define_insn "*extendsidi2_lfiwax"
- [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,??wm,!wl,!wm")
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,??wm,!wl,!wu")
(sign_extend:DI (match_operand:SI 1 "lwa_operand" "m,r,r,Z,Z")))]
"TARGET_POWERPC64 && TARGET_LFIWAX"
"@
@@ -2678,7 +2699,7 @@
(match_operand:SI 2 "gpc_reg_operand" "r,r"))
(const_int 0)))
(clobber (match_scratch:SI 3 "=r,r"))]
- ""
+ "TARGET_32BIT"
"@
mullw. %3,%1,%2
#"
@@ -2691,7 +2712,7 @@
(match_operand:SI 2 "gpc_reg_operand" ""))
(const_int 0)))
(clobber (match_scratch:SI 3 ""))]
- "reload_completed"
+ "TARGET_32BIT && reload_completed"
[(set (match_dup 3)
(mult:SI (match_dup 1) (match_dup 2)))
(set (match_dup 0)
@@ -2706,7 +2727,7 @@
(const_int 0)))
(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
(mult:SI (match_dup 1) (match_dup 2)))]
- ""
+ "TARGET_32BIT"
"@
mullw. %0,%1,%2
#"
@@ -2720,7 +2741,7 @@
(const_int 0)))
(set (match_operand:SI 0 "gpc_reg_operand" "")
(mult:SI (match_dup 1) (match_dup 2)))]
- "reload_completed"
+ "TARGET_32BIT && reload_completed"
[(set (match_dup 0)
(mult:SI (match_dup 1) (match_dup 2)))
(set (match_dup 3)
@@ -5043,22 +5064,172 @@
(const_int 0)))]
"")
-;; Floating-point insns, excluding normal data motion.
-;;
-;; PowerPC has a full set of single-precision floating point instructions.
-;;
-;; For the POWER architecture, we pretend that we have both SFmode and
-;; DFmode insns, while, in fact, all fp insns are actually done in double.
-;; The only conversions we will do will be when storing to memory. In that
-;; case, we will use the "frsp" instruction before storing.
-;;
-;; Note that when we store into a single-precision memory location, we need to
-;; use the frsp insn first. If the register being stored isn't dead, we
-;; need a scratch register for the frsp. But this is difficult when the store
-;; is done by reload. It is not incorrect to do the frsp on the register in
-;; this case, we just lose precision that we would have otherwise gotten but
-;; is not guaranteed. Perhaps this should be tightened up at some point.
+
+;; Floating-point insns, excluding normal data motion. We combine the SF/DF
+;; modes here, and also add in conditional vsx/power8-vector support to access
+;; values in the traditional Altivec registers if the appropriate
+;; -mupper-regs-{df,sf} option is enabled.
+
+(define_expand "abs<mode>2"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
+ (abs:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "")))]
+ "TARGET_<MODE>_INSN"
+ "")
+
+(define_insn "*abs<mode>2_fpr"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
+ (abs:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")))]
+ "TARGET_<MODE>_FPR"
+ "@
+ fabs %0,%1
+ xsabsdp %x0,%x1"
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_addsub_<Fs>")])
+
+(define_insn "*nabs<mode>2_fpr"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
+ (neg:SFDF
+ (abs:SFDF
+ (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>"))))]
+ "TARGET_<MODE>_FPR"
+ "@
+ fnabs %0,%1
+ xsnabsdp %x0,%x1"
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_addsub_<Fs>")])
+
+(define_expand "neg<mode>2"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
+ (neg:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "")))]
+ "TARGET_<MODE>_INSN"
+ "")
+
+(define_insn "*neg<mode>2_fpr"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
+ (neg:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")))]
+ "TARGET_<MODE>_FPR"
+ "@
+ fneg %0,%1
+ xsnegdp %x0,%x1"
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_addsub_<Fs>")])
+
+(define_expand "add<mode>3"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
+ (plus:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "")
+ (match_operand:SFDF 2 "gpc_reg_operand" "")))]
+ "TARGET_<MODE>_INSN"
+ "")
+
+(define_insn "*add<mode>3_fpr"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
+ (plus:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "%<Ff>,<Fv>")
+ (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>")))]
+ "TARGET_<MODE>_FPR"
+ "@
+ fadd<Ftrad> %0,%1,%2
+ xsadd<Fvsx> %x0,%x1,%x2"
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_addsub_<Fs>")])
+
+(define_expand "sub<mode>3"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
+ (minus:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "")
+ (match_operand:SFDF 2 "gpc_reg_operand" "")))]
+ "TARGET_<MODE>_INSN"
+ "")
+
+(define_insn "*sub<mode>3_fpr"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
+ (minus:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")
+ (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>")))]
+ "TARGET_<MODE>_FPR"
+ "@
+ fsub<Ftrad> %0,%1,%2
+ xssub<Fvsx> %x0,%x1,%x2"
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_addsub_<Fs>")])
+
+(define_expand "mul<mode>3"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
+ (mult:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "")
+ (match_operand:SFDF 2 "gpc_reg_operand" "")))]
+ "TARGET_<MODE>_INSN"
+ "")
+
+(define_insn "*mul<mode>3_fpr"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
+ (mult:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "%<Ff>,<Fv>")
+ (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>")))]
+ "TARGET_<MODE>_FPR"
+ "@
+ fmul<Ftrad> %0,%1,%2
+ xsmul<Fvsx> %x0,%x1,%x2"
+ [(set_attr "type" "dmul")
+ (set_attr "fp_type" "fp_mul_<Fs>")])
+
+(define_expand "div<mode>3"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
+ (div:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "")
+ (match_operand:SFDF 2 "gpc_reg_operand" "")))]
+ "TARGET_<MODE>_INSN && !TARGET_SIMPLE_FPU"
+ "")
+
+(define_insn "*div<mode>3_fpr"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
+ (div:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")
+ (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>")))]
+ "TARGET_<MODE>_FPR && !TARGET_SIMPLE_FPU"
+ "@
+ fdiv<Ftrad> %0,%1,%2
+ xsdiv<Fvsx> %x0,%x1,%x2"
+ [(set_attr "type" "<Fs>div")
+ (set_attr "fp_type" "fp_div_<Fs>")])
+
+(define_insn "sqrt<mode>2"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
+ (sqrt:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")))]
+ "TARGET_<MODE>_FPR && !TARGET_SIMPLE_FPU
+ && (TARGET_PPC_GPOPT || (<MODE>mode == SFmode && TARGET_XILINX_FPU))"
+ "@
+ fsqrt<Ftrad> %0,%1
+ xssqrt<Fvsx> %x0,%x1"
+ [(set_attr "type" "<Fs>sqrt")
+ (set_attr "fp_type" "fp_sqrt_<Fs>")])
+
+;; Floating point reciprocal approximation
+(define_insn "fre<Fs>"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
+ (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")]
+ UNSPEC_FRES))]
+ "TARGET_<FFRE>"
+ "@
+ fre<Ftrad> %0,%1
+ xsre<Fvsx> %x0,%x1"
+ [(set_attr "type" "fp")])
+
+(define_insn "*rsqrt<mode>2"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
+ (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")]
+ UNSPEC_RSQRT))]
+ "RS6000_RECIP_HAVE_RSQRTE_P (<MODE>mode)"
+ "@
+ frsqrte<Ftrad> %0,%1
+ xsrsqrte<Fvsx> %x0,%x1"
+ [(set_attr "type" "fp")])
+
+;; Floating point comparisons
+(define_insn "*cmp<mode>_fpr"
+ [(set (match_operand:CCFP 0 "cc_reg_operand" "=y,y")
+ (compare:CCFP (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")
+ (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>")))]
+ "TARGET_<MODE>_FPR"
+ "@
+ fcmpu %0,%1,%2
+ xscmpudp %x0,%x1,%x2"
+ [(set_attr "type" "fpcompare")])
+;; Floating point conversions
(define_expand "extendsfdf2"
[(set (match_operand:DF 0 "gpc_reg_operand" "")
(float_extend:DF (match_operand:SF 1 "reg_or_none500mem_operand" "")))]
@@ -5066,13 +5237,16 @@
"")
(define_insn_and_split "*extendsfdf2_fpr"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=d,?d,d")
- (float_extend:DF (match_operand:SF 1 "reg_or_mem_operand" "0,f,m")))]
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=d,?d,d,wy,?wy,wv")
+ (float_extend:DF (match_operand:SF 1 "reg_or_mem_operand" "0,f,m,0,wz,Z")))]
"TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
"@
#
fmr %0,%1
- lfs%U1%X1 %0,%1"
+ lfs%U1%X1 %0,%1
+ #
+ xxlor %x0,%x1,%x1
+ lxsspx %x0,%y1"
"&& reload_completed && REG_P (operands[1]) && REGNO (operands[0]) == REGNO (operands[1])"
[(const_int 0)]
{
@@ -5088,7 +5262,16 @@
(if_then_else
(match_test "update_address_mem (operands[1], VOIDmode)")
(const_string "fpload_u")
- (const_string "fpload")))])])
+ (const_string "fpload")))
+ (const_string "fp")
+ (const_string "vecsimple")
+ (if_then_else
+ (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
+ (const_string "fpload_ux")
+ (if_then_else
+ (match_test "update_address_mem (operands[1], VOIDmode)")
+ (const_string "fpload_u")
+ (const_string "fpload")))])])
(define_expand "truncdfsf2"
[(set (match_operand:SF 0 "gpc_reg_operand" "")
@@ -5103,175 +5286,6 @@
"frsp %0,%1"
[(set_attr "type" "fp")])
-(define_expand "negsf2"
- [(set (match_operand:SF 0 "gpc_reg_operand" "")
- (neg:SF (match_operand:SF 1 "gpc_reg_operand" "")))]
- "TARGET_HARD_FLOAT && TARGET_SINGLE_FLOAT"
- "")
-
-(define_insn "*negsf2"
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (neg:SF (match_operand:SF 1 "gpc_reg_operand" "f")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT"
- "fneg %0,%1"
- [(set_attr "type" "fp")])
-
-(define_expand "abssf2"
- [(set (match_operand:SF 0 "gpc_reg_operand" "")
- (abs:SF (match_operand:SF 1 "gpc_reg_operand" "")))]
- "TARGET_HARD_FLOAT && TARGET_SINGLE_FLOAT"
- "")
-
-(define_insn "*abssf2"
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (abs:SF (match_operand:SF 1 "gpc_reg_operand" "f")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT"
- "fabs %0,%1"
- [(set_attr "type" "fp")])
-
-(define_insn ""
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (neg:SF (abs:SF (match_operand:SF 1 "gpc_reg_operand" "f"))))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT"
- "fnabs %0,%1"
- [(set_attr "type" "fp")])
-
-(define_expand "addsf3"
- [(set (match_operand:SF 0 "gpc_reg_operand" "")
- (plus:SF (match_operand:SF 1 "gpc_reg_operand" "")
- (match_operand:SF 2 "gpc_reg_operand" "")))]
- "TARGET_HARD_FLOAT && TARGET_SINGLE_FLOAT"
- "")
-
-(define_insn ""
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (plus:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
- (match_operand:SF 2 "gpc_reg_operand" "f")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT"
- "fadds %0,%1,%2"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_addsub_s")])
-
-(define_expand "subsf3"
- [(set (match_operand:SF 0 "gpc_reg_operand" "")
- (minus:SF (match_operand:SF 1 "gpc_reg_operand" "")
- (match_operand:SF 2 "gpc_reg_operand" "")))]
- "TARGET_HARD_FLOAT && TARGET_SINGLE_FLOAT"
- "")
-
-(define_insn ""
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (minus:SF (match_operand:SF 1 "gpc_reg_operand" "f")
- (match_operand:SF 2 "gpc_reg_operand" "f")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT"
- "fsubs %0,%1,%2"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_addsub_s")])
-
-(define_expand "mulsf3"
- [(set (match_operand:SF 0 "gpc_reg_operand" "")
- (mult:SF (match_operand:SF 1 "gpc_reg_operand" "")
- (match_operand:SF 2 "gpc_reg_operand" "")))]
- "TARGET_HARD_FLOAT && TARGET_SINGLE_FLOAT"
- "")
-
-(define_insn ""
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
- (match_operand:SF 2 "gpc_reg_operand" "f")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT"
- "fmuls %0,%1,%2"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_mul_s")])
-
-(define_expand "divsf3"
- [(set (match_operand:SF 0 "gpc_reg_operand" "")
- (div:SF (match_operand:SF 1 "gpc_reg_operand" "")
- (match_operand:SF 2 "gpc_reg_operand" "")))]
- "TARGET_HARD_FLOAT && TARGET_SINGLE_FLOAT && !TARGET_SIMPLE_FPU"
- "")
-
-(define_insn ""
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (div:SF (match_operand:SF 1 "gpc_reg_operand" "f")
- (match_operand:SF 2 "gpc_reg_operand" "f")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS
- && TARGET_SINGLE_FLOAT && !TARGET_SIMPLE_FPU"
- "fdivs %0,%1,%2"
- [(set_attr "type" "sdiv")])
-
-(define_insn "fres"
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (unspec:SF [(match_operand:SF 1 "gpc_reg_operand" "f")] UNSPEC_FRES))]
- "TARGET_FRES"
- "fres %0,%1"
- [(set_attr "type" "fp")])
-
-; builtin fmaf support
-(define_insn "*fmasf4_fpr"
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (fma:SF (match_operand:SF 1 "gpc_reg_operand" "f")
- (match_operand:SF 2 "gpc_reg_operand" "f")
- (match_operand:SF 3 "gpc_reg_operand" "f")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT"
- "fmadds %0,%1,%2,%3"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_maddsub_s")])
-
-(define_insn "*fmssf4_fpr"
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (fma:SF (match_operand:SF 1 "gpc_reg_operand" "f")
- (match_operand:SF 2 "gpc_reg_operand" "f")
- (neg:SF (match_operand:SF 3 "gpc_reg_operand" "f"))))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT"
- "fmsubs %0,%1,%2,%3"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_maddsub_s")])
-
-(define_insn "*nfmasf4_fpr"
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (neg:SF (fma:SF (match_operand:SF 1 "gpc_reg_operand" "f")
- (match_operand:SF 2 "gpc_reg_operand" "f")
- (match_operand:SF 3 "gpc_reg_operand" "f"))))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT"
- "fnmadds %0,%1,%2,%3"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_maddsub_s")])
-
-(define_insn "*nfmssf4_fpr"
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (neg:SF (fma:SF (match_operand:SF 1 "gpc_reg_operand" "f")
- (match_operand:SF 2 "gpc_reg_operand" "f")
- (neg:SF (match_operand:SF 3 "gpc_reg_operand" "f")))))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT"
- "fnmsubs %0,%1,%2,%3"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_maddsub_s")])
-
-(define_expand "sqrtsf2"
- [(set (match_operand:SF 0 "gpc_reg_operand" "")
- (sqrt:SF (match_operand:SF 1 "gpc_reg_operand" "")))]
- "(TARGET_PPC_GPOPT || TARGET_XILINX_FPU)
- && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT
- && !TARGET_SIMPLE_FPU"
- "")
-
-(define_insn ""
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (sqrt:SF (match_operand:SF 1 "gpc_reg_operand" "f")))]
- "(TARGET_PPC_GPOPT || TARGET_XILINX_FPU) && TARGET_HARD_FLOAT
- && TARGET_FPRS && TARGET_SINGLE_FLOAT && !TARGET_SIMPLE_FPU"
- "fsqrts %0,%1"
- [(set_attr "type" "ssqrt")])
-
-(define_insn "*rsqrtsf_internal1"
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (unspec:SF [(match_operand:SF 1 "gpc_reg_operand" "f")]
- UNSPEC_RSQRT))]
- "TARGET_FRSQRTES"
- "frsqrtes %0,%1"
- [(set_attr "type" "fp")])
-
;; This expander is here to avoid FLOAT_WORDS_BIGENDIAN tests in
;; builtins.c and optabs.c that are not correct for IBM long double
;; when little-endian.
@@ -5339,37 +5353,82 @@
;; Use an unspec rather providing an if-then-else in RTL, to prevent the
;; compiler from optimizing -0.0
(define_insn "copysign<mode>3_fcpsgn"
- [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<rreg2>")
- (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>")
- (match_operand:SFDF 2 "gpc_reg_operand" "<rreg2>")]
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
+ (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")
+ (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>")]
UNSPEC_COPYSIGN))]
- "TARGET_CMPB && !VECTOR_UNIT_VSX_P (<MODE>mode)"
- "fcpsgn %0,%2,%1"
+ "TARGET_<MODE>_FPR && TARGET_CMPB"
+ "@
+ fcpsgn %0,%2,%1
+ xscpsgn<VSs> %x0,%x2,%x1"
[(set_attr "type" "fp")])
;; For MIN, MAX, and conditional move, we use DEFINE_EXPAND's that involve a
;; fsel instruction and some auxiliary computations. Then we just have a
;; single DEFINE_INSN for fsel and the define_splits to make them if made by
;; combine.
-(define_expand "smaxsf3"
- [(set (match_operand:SF 0 "gpc_reg_operand" "")
- (if_then_else:SF (ge (match_operand:SF 1 "gpc_reg_operand" "")
- (match_operand:SF 2 "gpc_reg_operand" ""))
- (match_dup 1)
- (match_dup 2)))]
- "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS
- && TARGET_SINGLE_FLOAT && !flag_trapping_math"
- "{ rs6000_emit_minmax (operands[0], SMAX, operands[1], operands[2]); DONE;}")
+;; For MIN, MAX on non-VSX machines, and conditional move all of the time, we
+;; use DEFINE_EXPAND's that involve a fsel instruction and some auxiliary
+;; computations. Then we just have a single DEFINE_INSN for fsel and the
+;; define_splits to make them if made by combine. On VSX machines we have the
+;; min/max instructions.
+;;
+;; On VSX, we only check for TARGET_VSX instead of checking for a vsx/p8 vector
+;; to allow either DF/SF to use only traditional registers.
-(define_expand "sminsf3"
- [(set (match_operand:SF 0 "gpc_reg_operand" "")
- (if_then_else:SF (ge (match_operand:SF 1 "gpc_reg_operand" "")
- (match_operand:SF 2 "gpc_reg_operand" ""))
- (match_dup 2)
- (match_dup 1)))]
- "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS
- && TARGET_SINGLE_FLOAT && !flag_trapping_math"
- "{ rs6000_emit_minmax (operands[0], SMIN, operands[1], operands[2]); DONE;}")
+(define_expand "smax<mode>3"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
+ (if_then_else:SFDF (ge (match_operand:SFDF 1 "gpc_reg_operand" "")
+ (match_operand:SFDF 2 "gpc_reg_operand" ""))
+ (match_dup 1)
+ (match_dup 2)))]
+ "TARGET_<MODE>_FPR && TARGET_PPC_GFXOPT && !flag_trapping_math"
+{
+ rs6000_emit_minmax (operands[0], SMAX, operands[1], operands[2]);
+ DONE;
+})
+
+(define_insn "*smax<mode>3_vsx"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
+ (smax:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "%<Ff>,<Fv>")
+ (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>")))]
+ "TARGET_<MODE>_FPR && TARGET_VSX"
+ "xsmaxdp %x0,%x1,%x2"
+ [(set_attr "type" "fp")])
+
+(define_expand "smin<mode>3"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
+ (if_then_else:SFDF (ge (match_operand:SFDF 1 "gpc_reg_operand" "")
+ (match_operand:SFDF 2 "gpc_reg_operand" ""))
+ (match_dup 2)
+ (match_dup 1)))]
+ "TARGET_<MODE>_FPR && TARGET_PPC_GFXOPT && !flag_trapping_math"
+{
+ rs6000_emit_minmax (operands[0], SMIN, operands[1], operands[2]);
+ DONE;
+})
+
+(define_insn "*smin<mode>3_vsx"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
+ (smin:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "%<Ff>,<Fv>")
+ (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>")))]
+ "TARGET_<MODE>_FPR && TARGET_VSX"
+ "xsmindp %x0,%x1,%x2"
+ [(set_attr "type" "fp")])
+
+(define_split
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
+ (match_operator:SFDF 3 "min_max_operator"
+ [(match_operand:SFDF 1 "gpc_reg_operand" "")
+ (match_operand:SFDF 2 "gpc_reg_operand" "")]))]
+ "TARGET_<MODE>_FPR && TARGET_PPC_GFXOPT && !flag_trapping_math
+ && !TARGET_VSX"
+ [(const_int 0)]
+{
+ rs6000_emit_minmax (operands[0], GET_CODE (operands[3]), operands[1],
+ operands[2]);
+ DONE;
+})
(define_split
[(set (match_operand:SF 0 "gpc_reg_operand" "")
@@ -5501,208 +5560,9 @@
"fsel %0,%1,%2,%3"
[(set_attr "type" "fp")])
-(define_expand "negdf2"
- [(set (match_operand:DF 0 "gpc_reg_operand" "")
- (neg:DF (match_operand:DF 1 "gpc_reg_operand" "")))]
- "TARGET_HARD_FLOAT && ((TARGET_FPRS && TARGET_DOUBLE_FLOAT) || TARGET_E500_DOUBLE)"
- "")
-
-(define_insn "*negdf2_fpr"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
- (neg:DF (match_operand:DF 1 "gpc_reg_operand" "d")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
- && !VECTOR_UNIT_VSX_P (DFmode)"
- "fneg %0,%1"
- [(set_attr "type" "fp")])
-
-(define_expand "absdf2"
- [(set (match_operand:DF 0 "gpc_reg_operand" "")
- (abs:DF (match_operand:DF 1 "gpc_reg_operand" "")))]
- "TARGET_HARD_FLOAT && ((TARGET_FPRS && TARGET_DOUBLE_FLOAT) || TARGET_E500_DOUBLE)"
- "")
-
-(define_insn "*absdf2_fpr"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
- (abs:DF (match_operand:DF 1 "gpc_reg_operand" "d")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
- && !VECTOR_UNIT_VSX_P (DFmode)"
- "fabs %0,%1"
- [(set_attr "type" "fp")])
-
-(define_insn "*nabsdf2_fpr"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
- (neg:DF (abs:DF (match_operand:DF 1 "gpc_reg_operand" "d"))))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
- && !VECTOR_UNIT_VSX_P (DFmode)"
- "fnabs %0,%1"
- [(set_attr "type" "fp")])
-
-(define_expand "adddf3"
- [(set (match_operand:DF 0 "gpc_reg_operand" "")
- (plus:DF (match_operand:DF 1 "gpc_reg_operand" "")
- (match_operand:DF 2 "gpc_reg_operand" "")))]
- "TARGET_HARD_FLOAT && ((TARGET_FPRS && TARGET_DOUBLE_FLOAT) || TARGET_E500_DOUBLE)"
- "")
-
-(define_insn "*adddf3_fpr"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
- (plus:DF (match_operand:DF 1 "gpc_reg_operand" "%d")
- (match_operand:DF 2 "gpc_reg_operand" "d")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
- && !VECTOR_UNIT_VSX_P (DFmode)"
- "fadd %0,%1,%2"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_addsub_d")])
-
-(define_expand "subdf3"
- [(set (match_operand:DF 0 "gpc_reg_operand" "")
- (minus:DF (match_operand:DF 1 "gpc_reg_operand" "")
- (match_operand:DF 2 "gpc_reg_operand" "")))]
- "TARGET_HARD_FLOAT && ((TARGET_FPRS && TARGET_DOUBLE_FLOAT) || TARGET_E500_DOUBLE)"
- "")
-
-(define_insn "*subdf3_fpr"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
- (minus:DF (match_operand:DF 1 "gpc_reg_operand" "d")
- (match_operand:DF 2 "gpc_reg_operand" "d")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
- && !VECTOR_UNIT_VSX_P (DFmode)"
- "fsub %0,%1,%2"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_addsub_d")])
-
-(define_expand "muldf3"
- [(set (match_operand:DF 0 "gpc_reg_operand" "")
- (mult:DF (match_operand:DF 1 "gpc_reg_operand" "")
- (match_operand:DF 2 "gpc_reg_operand" "")))]
- "TARGET_HARD_FLOAT && ((TARGET_FPRS && TARGET_DOUBLE_FLOAT) || TARGET_E500_DOUBLE)"
- "")
-
-(define_insn "*muldf3_fpr"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
- (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%d")
- (match_operand:DF 2 "gpc_reg_operand" "d")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
- && !VECTOR_UNIT_VSX_P (DFmode)"
- "fmul %0,%1,%2"
- [(set_attr "type" "dmul")
- (set_attr "fp_type" "fp_mul_d")])
-
-(define_expand "divdf3"
- [(set (match_operand:DF 0 "gpc_reg_operand" "")
- (div:DF (match_operand:DF 1 "gpc_reg_operand" "")
- (match_operand:DF 2 "gpc_reg_operand" "")))]
- "TARGET_HARD_FLOAT
- && ((TARGET_FPRS && TARGET_DOUBLE_FLOAT) || TARGET_E500_DOUBLE)
- && !TARGET_SIMPLE_FPU"
- "")
-
-(define_insn "*divdf3_fpr"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
- (div:DF (match_operand:DF 1 "gpc_reg_operand" "d")
- (match_operand:DF 2 "gpc_reg_operand" "d")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && !TARGET_SIMPLE_FPU
- && !VECTOR_UNIT_VSX_P (DFmode)"
- "fdiv %0,%1,%2"
- [(set_attr "type" "ddiv")])
-
-(define_insn "*fred_fpr"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
- (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "f")] UNSPEC_FRES))]
- "TARGET_FRE && !VECTOR_UNIT_VSX_P (DFmode)"
- "fre %0,%1"
- [(set_attr "type" "fp")])
-
-(define_insn "*rsqrtdf_internal1"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
- (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "d")]
- UNSPEC_RSQRT))]
- "TARGET_FRSQRTE && !VECTOR_UNIT_VSX_P (DFmode)"
- "frsqrte %0,%1"
- [(set_attr "type" "fp")])
-
-; builtin fma support
-(define_insn "*fmadf4_fpr"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
- (fma:DF (match_operand:DF 1 "gpc_reg_operand" "f")
- (match_operand:DF 2 "gpc_reg_operand" "f")
- (match_operand:DF 3 "gpc_reg_operand" "f")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
- && VECTOR_UNIT_NONE_P (DFmode)"
- "fmadd %0,%1,%2,%3"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_maddsub_d")])
-
-(define_insn "*fmsdf4_fpr"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
- (fma:DF (match_operand:DF 1 "gpc_reg_operand" "f")
- (match_operand:DF 2 "gpc_reg_operand" "f")
- (neg:DF (match_operand:DF 3 "gpc_reg_operand" "f"))))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
- && VECTOR_UNIT_NONE_P (DFmode)"
- "fmsub %0,%1,%2,%3"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_maddsub_d")])
-
-(define_insn "*nfmadf4_fpr"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
- (neg:DF (fma:DF (match_operand:DF 1 "gpc_reg_operand" "f")
- (match_operand:DF 2 "gpc_reg_operand" "f")
- (match_operand:DF 3 "gpc_reg_operand" "f"))))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
- && VECTOR_UNIT_NONE_P (DFmode)"
- "fnmadd %0,%1,%2,%3"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_maddsub_d")])
-
-(define_insn "*nfmsdf4_fpr"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
- (neg:DF (fma:DF (match_operand:DF 1 "gpc_reg_operand" "f")
- (match_operand:DF 2 "gpc_reg_operand" "f")
- (neg:DF (match_operand:DF 3 "gpc_reg_operand" "f")))))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
- && VECTOR_UNIT_NONE_P (DFmode)"
- "fnmsub %0,%1,%2,%3"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_maddsub_d")])
-
-(define_expand "sqrtdf2"
- [(set (match_operand:DF 0 "gpc_reg_operand" "")
- (sqrt:DF (match_operand:DF 1 "gpc_reg_operand" "")))]
- "TARGET_PPC_GPOPT && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
- "")
-
-(define_insn "*sqrtdf2_fpr"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
- (sqrt:DF (match_operand:DF 1 "gpc_reg_operand" "d")))]
- "TARGET_PPC_GPOPT && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
- && !VECTOR_UNIT_VSX_P (DFmode)"
- "fsqrt %0,%1"
- [(set_attr "type" "dsqrt")])
-
;; The conditional move instructions allow us to perform max and min
;; operations even when
-(define_expand "smaxdf3"
- [(set (match_operand:DF 0 "gpc_reg_operand" "")
- (if_then_else:DF (ge (match_operand:DF 1 "gpc_reg_operand" "")
- (match_operand:DF 2 "gpc_reg_operand" ""))
- (match_dup 1)
- (match_dup 2)))]
- "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
- && !flag_trapping_math"
- "{ rs6000_emit_minmax (operands[0], SMAX, operands[1], operands[2]); DONE;}")
-
-(define_expand "smindf3"
- [(set (match_operand:DF 0 "gpc_reg_operand" "")
- (if_then_else:DF (ge (match_operand:DF 1 "gpc_reg_operand" "")
- (match_operand:DF 2 "gpc_reg_operand" ""))
- (match_dup 2)
- (match_dup 1)))]
- "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
- && !flag_trapping_math"
- "{ rs6000_emit_minmax (operands[0], SMIN, operands[1], operands[2]); DONE;}")
-
(define_split
[(set (match_operand:DF 0 "gpc_reg_operand" "")
(match_operator:DF 3 "min_max_operator"
@@ -6386,66 +6246,52 @@
[(set (match_operand:DI 0 "gpc_reg_operand" "=d")
(unspec:DI [(match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>")]
UNSPEC_FCTID))]
- "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT>"
+ "TARGET_<MODE>_FPR && TARGET_FPRND"
"fctid %0,%1"
[(set_attr "type" "fp")])
-(define_expand "btrunc<mode>2"
- [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
- (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "")]
+(define_insn "btrunc<mode>2"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
+ (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")]
UNSPEC_FRIZ))]
- "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT>"
- "")
-
-(define_insn "*btrunc<mode>2_fpr"
- [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<rreg2>")
- (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>")]
- UNSPEC_FRIZ))]
- "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT>
- && !VECTOR_UNIT_VSX_P (<MODE>mode)"
- "friz %0,%1"
- [(set_attr "type" "fp")])
-
-(define_expand "ceil<mode>2"
- [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
- (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "")]
- UNSPEC_FRIP))]
- "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT>"
- "")
+ "TARGET_<MODE>_FPR && TARGET_FPRND"
+ "@
+ friz %0,%1
+ xsrdpiz %x0,%x1"
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_addsub_<Fs>")])
-(define_insn "*ceil<mode>2_fpr"
- [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<rreg2>")
- (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>")]
+(define_insn "ceil<mode>2"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
+ (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")]
UNSPEC_FRIP))]
- "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT>
- && !VECTOR_UNIT_VSX_P (<MODE>mode)"
- "frip %0,%1"
- [(set_attr "type" "fp")])
+ "TARGET_<MODE>_FPR && TARGET_FPRND"
+ "@
+ frip %0,%1
+ xsrdpip %x0,%x1"
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_addsub_<Fs>")])
-(define_expand "floor<mode>2"
- [(set (match_operand:SFDF 0 "gpc_reg_operand" "")
- (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "")]
+(define_insn "floor<mode>2"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>")
+ (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")]
UNSPEC_FRIM))]
- "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT>"
- "")
-
-(define_insn "*floor<mode>2_fpr"
- [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<rreg2>")
- (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>")]
- UNSPEC_FRIM))]
- "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT>
- && !VECTOR_UNIT_VSX_P (<MODE>mode)"
- "frim %0,%1"
- [(set_attr "type" "fp")])
+ "TARGET_<MODE>_FPR && TARGET_FPRND"
+ "@
+ frim %0,%1
+ xsrdpim %x0,%x1"
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_addsub_<Fs>")])
;; No VSX equivalent to frin
(define_insn "round<mode>2"
[(set (match_operand:SFDF 0 "gpc_reg_operand" "=<rreg2>")
(unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>")]
UNSPEC_FRIN))]
- "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT>"
+ "TARGET_<MODE>_FPR && TARGET_FPRND"
"frin %0,%1"
- [(set_attr "type" "fp")])
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_addsub_<Fs>")])
; An UNSPEC is used so we don't have to support SImode in FP registers.
(define_insn "stfiwx"
@@ -9290,8 +9136,8 @@
}")
(define_insn "mov<mode>_hardfloat"
- [(set (match_operand:FMOVE32 0 "nonimmediate_operand" "=!r,!r,m,f,wa,wa,<f32_lr>,<f32_sm>,wm,Z,?<f32_dm>,?r,*c*l,!r,*h,!r,!r")
- (match_operand:FMOVE32 1 "input_operand" "r,m,r,f,wa,j,<f32_lm>,<f32_sr>,Z,wm,r,<f32_dm>,r,h,0,G,Fn"))]
+ [(set (match_operand:FMOVE32 0 "nonimmediate_operand" "=!r,!r,m,f,wa,wa,<f32_lr>,<f32_sm>,wu,Z,?<f32_dm>,?r,*c*l,!r,*h,!r,!r")
+ (match_operand:FMOVE32 1 "input_operand" "r,m,r,f,wa,j,<f32_lm>,<f32_sr>,Z,wu,r,<f32_dm>,r,h,0,G,Fn"))]
"(gpc_reg_operand (operands[0], <MODE>mode)
|| gpc_reg_operand (operands[1], <MODE>mode))
&& (TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT)"
@@ -9492,8 +9338,8 @@
;; reloading.
(define_insn "*mov<mode>_hardfloat32"
- [(set (match_operand:FMOVE64 0 "nonimmediate_operand" "=m,d,d,ws,?wa,Z,?Z,ws,?wa,wa,Y,r,!r,!r,!r,!r")
- (match_operand:FMOVE64 1 "input_operand" "d,m,d,Z,Z,ws,wa,ws,wa,j,r,Y,r,G,H,F"))]
+ [(set (match_operand:FMOVE64 0 "nonimmediate_operand" "=m,d,d,wv,Z,wa,wa,Y,r,!r,!r,!r,!r")
+ (match_operand:FMOVE64 1 "input_operand" "d,m,d,Z,wv,wa,j,r,Y,r,G,H,F"))]
"! TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
&& (gpc_reg_operand (operands[0], <MODE>mode)
|| gpc_reg_operand (operands[1], <MODE>mode))"
@@ -9502,11 +9348,8 @@
lfd%U1%X1 %0,%1
fmr %0,%1
lxsd%U1x %x0,%y1
- lxsd%U1x %x0,%y1
- stxsd%U0x %x1,%y0
stxsd%U0x %x1,%y0
xxlor %x0,%x1,%x1
- xxlor %x0,%x1,%x1
xxlxor %x0,%x0,%x0
#
#
@@ -9535,18 +9378,9 @@
(const_string "fpload_ux")
(const_string "fpload"))
(if_then_else
- (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
- (const_string "fpload_ux")
- (const_string "fpload"))
- (if_then_else
(match_test "update_indexed_address_mem (operands[0], VOIDmode)")
(const_string "fpstore_ux")
(const_string "fpstore"))
- (if_then_else
- (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
- (const_string "fpstore_ux")
- (const_string "fpstore"))
- (const_string "vecsimple")
(const_string "vecsimple")
(const_string "vecsimple")
(const_string "store")
@@ -9555,7 +9389,7 @@
(const_string "fp")
(const_string "fp")
(const_string "*")])
- (set_attr "length" "4,4,4,4,4,4,4,4,4,4,8,8,8,8,12,16")])
+ (set_attr "length" "4,4,4,4,4,4,4,8,8,8,8,12,16")])
(define_insn "*mov<mode>_softfloat32"
[(set (match_operand:FMOVE64 0 "nonimmediate_operand" "=Y,r,r,r,r,r")
@@ -9572,8 +9406,8 @@
; ld/std require word-aligned displacements -> 'Y' constraint.
; List Y->r and r->Y before r->r for reload.
(define_insn "*mov<mode>_hardfloat64"
- [(set (match_operand:FMOVE64 0 "nonimmediate_operand" "=m,d,d,ws,?wa,Z,?Z,ws,?wa,wa,Y,r,!r,*c*l,!r,*h,!r,!r,!r,r,wg,r,wm")
- (match_operand:FMOVE64 1 "input_operand" "d,m,d,Z,Z,ws,wa,ws,wa,j,r,Y,r,r,h,0,G,H,F,wg,r,wm,r"))]
+ [(set (match_operand:FMOVE64 0 "nonimmediate_operand" "=m,d,d,wv,Z,wa,wa,Y,r,!r,*c*l,!r,*h,!r,!r,!r,r,wg,r,wm")
+ (match_operand:FMOVE64 1 "input_operand" "d,m,d,Z,wv,wa,j,r,Y,r,r,h,0,G,H,F,wg,r,wm,r"))]
"TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
&& (gpc_reg_operand (operands[0], <MODE>mode)
|| gpc_reg_operand (operands[1], <MODE>mode))"
@@ -9582,10 +9416,7 @@
lfd%U1%X1 %0,%1
fmr %0,%1
lxsd%U1x %x0,%y1
- lxsd%U1x %x0,%y1
stxsd%U0x %x1,%y0
- stxsd%U0x %x1,%y0
- xxlor %x0,%x1,%x1
xxlor %x0,%x1,%x1
xxlxor %x0,%x0,%x0
std%U0%X0 %1,%0
@@ -9622,20 +9453,11 @@
(const_string "fpload_ux")
(const_string "fpload"))
(if_then_else
- (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
- (const_string "fpload_ux")
- (const_string "fpload"))
- (if_then_else
- (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
- (const_string "fpstore_ux")
- (const_string "fpstore"))
- (if_then_else
(match_test "update_indexed_address_mem (operands[0], VOIDmode)")
(const_string "fpstore_ux")
(const_string "fpstore"))
(const_string "vecsimple")
(const_string "vecsimple")
- (const_string "vecsimple")
(if_then_else
(match_test "update_indexed_address_mem (operands[0], VOIDmode)")
(const_string "store_ux")
@@ -9661,7 +9483,7 @@
(const_string "mffgpr")
(const_string "mftgpr")
(const_string "mffgpr")])
- (set_attr "length" "4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,8,12,16,4,4,4,4")])
+ (set_attr "length" "4,4,4,4,4,4,4,4,4,4,4,4,4,8,12,16,4,4,4,4")])
(define_insn "*mov<mode>_softfloat64"
[(set (match_operand:FMOVE64 0 "nonimmediate_operand" "=Y,r,r,cl,r,r,r,r,*h")
@@ -10324,8 +10146,8 @@
{ rs6000_split_multireg_move (operands[0], operands[1]); DONE; })
(define_insn "*movdi_internal64"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=Y,r,r,r,r,r,?m,?*d,?*d,?Z,?wa,?wa,r,*h,*h,?wa,r,?*wg,r,?*wm")
- (match_operand:DI 1 "input_operand" "r,Y,r,I,L,nF,d,m,d,wa,Z,wa,*h,r,0,O,*wg,r,*wm,r"))]
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=Y,r,r,r,r,r,?m,?*d,?*d,?Z,?wv,?wa,r,*h,*h,?wa,r,?*wg,r,?*wm")
+ (match_operand:DI 1 "input_operand" "r,Y,r,I,L,nF,d,m,d,wv,Z,wa,*h,r,0,O,*wg,r,*wm,r"))]
"TARGET_POWERPC64
&& (gpc_reg_operand (operands[0], DImode)
|| gpc_reg_operand (operands[1], DImode))"
@@ -10490,15 +10312,15 @@
(const_string "conditional")))])
(define_insn "*mov<mode>_ppc64"
- [(set (match_operand:TI2 0 "nonimmediate_operand" "=Y,r,r,r")
- (match_operand:TI2 1 "input_operand" "r,Y,r,F"))]
+ [(set (match_operand:TI2 0 "nonimmediate_operand" "=wQ,Y,r,r,r,r")
+ (match_operand:TI2 1 "input_operand" "r,r,wQ,Y,r,n"))]
"(TARGET_POWERPC64 && VECTOR_MEM_NONE_P (<MODE>mode)
&& (gpc_reg_operand (operands[0], <MODE>mode)
|| gpc_reg_operand (operands[1], <MODE>mode)))"
{
return rs6000_output_move_128bit (operands);
}
- [(set_attr "type" "store,load,*,*")
+ [(set_attr "type" "store,store,load,load,*,*")
(set_attr "length" "8")])
(define_split
@@ -13341,23 +13163,6 @@
[(set (match_dup 3) (compare:CCUNS (match_dup 1) (match_dup 2)))
(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 4)))])
-(define_insn "*cmpsf_internal1"
- [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
- (compare:CCFP (match_operand:SF 1 "gpc_reg_operand" "f")
- (match_operand:SF 2 "gpc_reg_operand" "f")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT"
- "fcmpu %0,%1,%2"
- [(set_attr "type" "fpcompare")])
-
-(define_insn "*cmpdf_internal1"
- [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
- (compare:CCFP (match_operand:DF 1 "gpc_reg_operand" "d")
- (match_operand:DF 2 "gpc_reg_operand" "d")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
- && !VECTOR_UNIT_VSX_P (DFmode)"
- "fcmpu %0,%1,%2"
- [(set_attr "type" "fpcompare")])
-
;; Only need to compare second words if first words equal
(define_insn "*cmptf_internal1"
[(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
@@ -14986,28 +14791,21 @@
(define_expand "doloop_end"
[(use (match_operand 0 "" "")) ; loop pseudo
- (use (match_operand 1 "" "")) ; iterations; zero if unknown
- (use (match_operand 2 "" "")) ; max iterations
- (use (match_operand 3 "" "")) ; loop level
- (use (match_operand 4 "" "")) ; label
- (use (match_operand 5 "" ""))] ; flag: 1 if loop entered at top, else 0
+ (use (match_operand 1 "" ""))] ; label
""
"
{
- /* Only use this on innermost loops. */
- if (INTVAL (operands[3]) > 1)
- FAIL;
if (TARGET_64BIT)
{
if (GET_MODE (operands[0]) != DImode)
FAIL;
- emit_jump_insn (gen_ctrdi (operands[0], operands[4]));
+ emit_jump_insn (gen_ctrdi (operands[0], operands[1]));
}
else
{
if (GET_MODE (operands[0]) != SImode)
FAIL;
- emit_jump_insn (gen_ctrsi (operands[0], operands[4]));
+ emit_jump_insn (gen_ctrsi (operands[0], operands[1]));
}
DONE;
}")
@@ -15652,6 +15450,20 @@
""
"")
+(define_insn "*fma<mode>4_fpr"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>,<Fv>")
+ (fma:SFDF
+ (match_operand:SFDF 1 "gpc_reg_operand" "%<Ff>,<Fv>,<Fv>")
+ (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>,0")
+ (match_operand:SFDF 3 "gpc_reg_operand" "<Ff>,0,<Fv>")))]
+ "TARGET_<MODE>_FPR"
+ "@
+ fmadd<Ftrad> %0,%1,%2,%3
+ xsmadda<Fvsx> %x0,%x1,%x2
+ xsmaddm<Fvsx> %x0,%x1,%x3"
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_maddsub_<Fs>")])
+
; Altivec only has fma and nfms.
(define_expand "fms<mode>4"
[(set (match_operand:FMA_F 0 "register_operand" "")
@@ -15662,6 +15474,20 @@
"!VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
"")
+(define_insn "*fms<mode>4_fpr"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>,<Fv>")
+ (fma:SFDF
+ (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>,<Fv>")
+ (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>,0")
+ (neg:SFDF (match_operand:SFDF 3 "gpc_reg_operand" "<Ff>,0,<Fv>"))))]
+ "TARGET_<MODE>_FPR"
+ "@
+ fmsub<Ftrad> %0,%1,%2,%3
+ xsmsuba<Fvsx> %x0,%x1,%x2
+ xsmsubm<Fvsx> %x0,%x1,%x3"
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_maddsub_<Fs>")])
+
;; If signed zeros are ignored, -(a * b - c) = -a * b + c.
(define_expand "fnma<mode>4"
[(set (match_operand:FMA_F 0 "register_operand" "")
@@ -15695,6 +15521,21 @@
"!VECTOR_UNIT_ALTIVEC_P (<MODE>mode)"
"")
+(define_insn "*nfma<mode>4_fpr"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>,<Fv>")
+ (neg:SFDF
+ (fma:SFDF
+ (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>,<Fv>")
+ (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>,0")
+ (match_operand:SFDF 3 "gpc_reg_operand" "<Ff>,0,<Fv>"))))]
+ "TARGET_<MODE>_FPR"
+ "@
+ fnmadd<Ftrad> %0,%1,%2,%3
+ xsnmadda<Fvsx> %x0,%x1,%x2
+ xsnmaddm<Fvsx> %x0,%x1,%x3"
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_maddsub_<Fs>")])
+
; Not an official optab name, but used from builtins.
(define_expand "nfms<mode>4"
[(set (match_operand:FMA_F 0 "register_operand" "")
@@ -15706,6 +15547,23 @@
""
"")
+(define_insn "*nfmssf4_fpr"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv>,<Fv>")
+ (neg:SFDF
+ (fma:SFDF
+ (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>,<Fv>")
+ (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv>,0")
+ (neg:SFDF
+ (match_operand:SFDF 3 "gpc_reg_operand" "<Ff>,0,<Fv>")))))]
+ "TARGET_<MODE>_FPR"
+ "@
+ fnmsub<Ftrad> %0,%1,%2,%3
+ xsnmsuba<Fvsx> %x0,%x1,%x2
+ xsnmsubm<Fvsx> %x0,%x1,%x3"
+ [(set_attr "type" "fp")
+ (set_attr "fp_type" "fp_maddsub_<Fs>")])
+
+
(define_expand "rs6000_get_timebase"
[(use (match_operand:DI 0 "gpc_reg_operand" ""))]
""
diff --git a/gcc/config/rs6000/rs6000.opt b/gcc/config/rs6000/rs6000.opt
index cd83cb2d206..94e4b3883dc 100644
--- a/gcc/config/rs6000/rs6000.opt
+++ b/gcc/config/rs6000/rs6000.opt
@@ -30,6 +30,9 @@ TargetSave
HOST_WIDE_INT x_rs6000_isa_flags
;; Miscellaneous flag bits that were set explicitly by the user
+Variable
+HOST_WIDE_INT rs6000_isa_flags_explicit
+
TargetSave
HOST_WIDE_INT x_rs6000_isa_flags_explicit
@@ -181,13 +184,16 @@ mvsx
Target Report Mask(VSX) Var(rs6000_isa_flags)
Use vector/scalar (VSX) instructions
+mvsx-scalar-float
+Target Undocumented Report Var(TARGET_VSX_SCALAR_FLOAT) Init(1)
+; If -mpower8-vector, use VSX arithmetic instructions for SFmode (on by default)
+
mvsx-scalar-double
-Target Undocumented Report Var(TARGET_VSX_SCALAR_DOUBLE) Init(-1)
-; If -mvsx, use VSX arithmetic instructions for scalar double (on by default)
+Target Undocumented Report Var(TARGET_VSX_SCALAR_DOUBLE) Init(1)
+; If -mvsx, use VSX arithmetic instructions for DFmode (on by default)
mvsx-scalar-memory
-Target Undocumented Report Var(TARGET_VSX_SCALAR_MEMORY)
-; If -mvsx, use VSX scalar memory reference instructions for scalar double (off by default)
+Target Undocumented Report Alias(mupper-regs-df)
mvsx-align-128
Target Undocumented Report Var(TARGET_VSX_ALIGN_128)
@@ -443,6 +449,10 @@ mlong-double-
Target RejectNegative Joined UInteger Var(rs6000_long_double_type_size) Save
-mlong-double-<n> Specify size of long double (64 or 128 bits)
+mlra
+Target Report Var(rs6000_lra_flag) Init(0) Save
+Use LRA instead of reload
+
msched-costly-dep=
Target RejectNegative Joined Var(rs6000_sched_costly_dep_str)
Determine which dependences between insns are considered costly
@@ -550,3 +560,11 @@ Generate the quad word memory instructions (lq/stq/lqarx/stqcx).
mcompat-align-parm
Target Report Var(rs6000_compat_align_parm) Init(0) Save
Generate aggregate parameter passing code with at most 64-bit alignment.
+
+mupper-regs-df
+Target Undocumented Mask(UPPER_REGS_DF) Var(rs6000_isa_flags)
+Allow double variables in upper registers with -mcpu=power7 or -mvsx
+
+mupper-regs-sf
+Target Undocumented Mask(UPPER_REGS_SF) Var(rs6000_isa_flags)
+Allow float variables in upper registers with -mcpu=power8 or -mp8-vector
diff --git a/gcc/config/rs6000/t-linux b/gcc/config/rs6000/t-linux
index 62a5b941389..0b92eba4617 100644
--- a/gcc/config/rs6000/t-linux
+++ b/gcc/config/rs6000/t-linux
@@ -7,3 +7,7 @@ else
MULTIARCH_DIRNAME = powerpc-linux-gnu
endif
endif
+
+rs6000-linux.o: $(srcdir)/config/rs6000/rs6000-linux.c
+ $(COMPILE) $<
+ $(POSTCOMPILE)
diff --git a/gcc/config/rs6000/t-linux64 b/gcc/config/rs6000/t-linux64
index 70e928dd7cd..0b17ed6a5cf 100644
--- a/gcc/config/rs6000/t-linux64
+++ b/gcc/config/rs6000/t-linux64
@@ -30,3 +30,7 @@ MULTILIB_DIRNAMES := 64 32
MULTILIB_EXTRA_OPTS :=
MULTILIB_OSDIRNAMES := m64=../lib64$(call if_multiarch,:powerpc64-linux-gnu)
MULTILIB_OSDIRNAMES += m32=$(if $(wildcard $(shell echo $(SYSTEM_HEADER_DIR))/../../usr/lib32),../lib32,../lib)$(call if_multiarch,:powerpc-linux-gnu)
+
+rs6000-linux.o: $(srcdir)/config/rs6000/rs6000-linux.c
+ $(COMPILE) $<
+ $(POSTCOMPILE)
diff --git a/gcc/config/rs6000/t-rs6000 b/gcc/config/rs6000/t-rs6000
index 81372dfb140..3123521bd06 100644
--- a/gcc/config/rs6000/t-rs6000
+++ b/gcc/config/rs6000/t-rs6000
@@ -20,21 +20,9 @@
TM_H += $(srcdir)/config/rs6000/rs6000-builtin.def
-rs6000.o: $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(RTL_H) $(REGS_H) hard-reg-set.h \
- real.h insn-config.h conditions.h insn-attr.h flags.h $(RECOG_H) \
- $(OBSTACK_H) $(TREE_H) $(EXPR_H) $(OPTABS_H) except.h function.h \
- output.h dbxout.h $(BASIC_BLOCK_H) toplev.h $(GGC_H) $(HASHTAB_H) \
- $(TM_P_H) $(TARGET_H) $(TARGET_DEF_H) langhooks.h reload.h gt-rs6000.h \
- cfgloop.h $(OPTS_H) $(COMMON_TARGET_H) dumpfile.h \
- $(srcdir)/config/rs6000/rs6000-cpus.def
-
-rs6000-c.o: $(srcdir)/config/rs6000/rs6000-c.c \
- $(srcdir)/config/rs6000/rs6000-protos.h \
- $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(CPPLIB_H) \
- $(TM_P_H) $(C_PRAGMA_H) errors.h coretypes.h $(TM_H)
- $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
- $(srcdir)/config/rs6000/rs6000-c.c
+rs6000-c.o: $(srcdir)/config/rs6000/rs6000-c.c
+ $(COMPILE) $<
+ $(POSTCOMPILE)
$(srcdir)/config/rs6000/rs6000-tables.opt: $(srcdir)/config/rs6000/genopt.sh \
$(srcdir)/config/rs6000/rs6000-cpus.def
diff --git a/gcc/config/rs6000/t-xilinx b/gcc/config/rs6000/t-xilinx
index 2abb333d585..1e05215e221 100644
--- a/gcc/config/rs6000/t-xilinx
+++ b/gcc/config/rs6000/t-xilinx
@@ -26,31 +26,3 @@ MULTILIB_OPTIONS = mfpu=sp_lite/mfpu=dp_lite
MULTILIB_DIRNAMES = single double
-# Multilibs for Xilinx powerpc embedded ELF targets.
-#
-# Copyright (C) 2009-2013 Free Software Foundation, Inc.
-# Contributed by Michael Eager, eager@eagercon.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/>.
-
-# Switch synonyms
-MULTILIB_MATCHES = mfpu?sp_lite=msingle-float mfpu?dp_lite=mdouble-float mfpu?dp_lite=mhard-float mfpu?sp_lite=mfpu?sp_full mfpu?dp_lite=mfpu?dp_full
-
-MULTILIB_OPTIONS = mfpu=sp_lite/mfpu=dp_lite
-
-MULTILIB_DIRNAMES = single double
-
diff --git a/gcc/config/rs6000/vector.md b/gcc/config/rs6000/vector.md
index 3faa7983aa8..68214d91316 100644
--- a/gcc/config/rs6000/vector.md
+++ b/gcc/config/rs6000/vector.md
@@ -88,7 +88,8 @@
(smax "smax")])
-;; Vector move instructions.
+;; Vector move instructions. Little-endian VSX loads and stores require
+;; special handling to circumvent "element endianness."
(define_expand "mov<mode>"
[(set (match_operand:VEC_M 0 "nonimmediate_operand" "")
(match_operand:VEC_M 1 "any_operand" ""))]
@@ -104,6 +105,15 @@
&& !vlogical_operand (operands[1], <MODE>mode))
operands[1] = force_reg (<MODE>mode, operands[1]);
}
+ if (!BYTES_BIG_ENDIAN
+ && VECTOR_MEM_VSX_P (<MODE>mode)
+ && <MODE>mode != TImode
+ && (memory_operand (operands[0], <MODE>mode)
+ ^ memory_operand (operands[1], <MODE>mode)))
+ {
+ rs6000_emit_le_vsx_move (operands[0], operands[1], <MODE>mode);
+ DONE;
+ }
})
;; Generic vector floating point load/store instructions. These will match
@@ -820,7 +830,12 @@
emit_insn (gen_vsx_xvcvdpsp (r1, operands[1]));
emit_insn (gen_vsx_xvcvdpsp (r2, operands[2]));
- rs6000_expand_extract_even (operands[0], r1, r2);
+
+ if (BYTES_BIG_ENDIAN)
+ rs6000_expand_extract_even (operands[0], r1, r2);
+ else
+ rs6000_expand_extract_even (operands[0], r2, r1);
+
DONE;
})
@@ -835,7 +850,12 @@
emit_insn (gen_vsx_xvcvdpsxws (r1, operands[1]));
emit_insn (gen_vsx_xvcvdpsxws (r2, operands[2]));
- rs6000_expand_extract_even (operands[0], r1, r2);
+
+ if (BYTES_BIG_ENDIAN)
+ rs6000_expand_extract_even (operands[0], r1, r2);
+ else
+ rs6000_expand_extract_even (operands[0], r2, r1);
+
DONE;
})
@@ -850,7 +870,12 @@
emit_insn (gen_vsx_xvcvdpuxws (r1, operands[1]));
emit_insn (gen_vsx_xvcvdpuxws (r2, operands[2]));
- rs6000_expand_extract_even (operands[0], r1, r2);
+
+ if (BYTES_BIG_ENDIAN)
+ rs6000_expand_extract_even (operands[0], r1, r2);
+ else
+ rs6000_expand_extract_even (operands[0], r2, r1);
+
DONE;
})
@@ -862,7 +887,7 @@
{
rtx reg = gen_reg_rtx (V4SFmode);
- rs6000_expand_interleave (reg, operands[1], operands[1], true);
+ rs6000_expand_interleave (reg, operands[1], operands[1], BYTES_BIG_ENDIAN);
emit_insn (gen_vsx_xvcvspdp (operands[0], reg));
DONE;
})
@@ -874,7 +899,7 @@
{
rtx reg = gen_reg_rtx (V4SFmode);
- rs6000_expand_interleave (reg, operands[1], operands[1], false);
+ rs6000_expand_interleave (reg, operands[1], operands[1], !BYTES_BIG_ENDIAN);
emit_insn (gen_vsx_xvcvspdp (operands[0], reg));
DONE;
})
@@ -886,7 +911,7 @@
{
rtx reg = gen_reg_rtx (V4SImode);
- rs6000_expand_interleave (reg, operands[1], operands[1], true);
+ rs6000_expand_interleave (reg, operands[1], operands[1], BYTES_BIG_ENDIAN);
emit_insn (gen_vsx_xvcvsxwdp (operands[0], reg));
DONE;
})
@@ -898,7 +923,7 @@
{
rtx reg = gen_reg_rtx (V4SImode);
- rs6000_expand_interleave (reg, operands[1], operands[1], false);
+ rs6000_expand_interleave (reg, operands[1], operands[1], !BYTES_BIG_ENDIAN);
emit_insn (gen_vsx_xvcvsxwdp (operands[0], reg));
DONE;
})
@@ -910,7 +935,7 @@
{
rtx reg = gen_reg_rtx (V4SImode);
- rs6000_expand_interleave (reg, operands[1], operands[1], true);
+ rs6000_expand_interleave (reg, operands[1], operands[1], BYTES_BIG_ENDIAN);
emit_insn (gen_vsx_xvcvuxwdp (operands[0], reg));
DONE;
})
@@ -922,7 +947,7 @@
{
rtx reg = gen_reg_rtx (V4SImode);
- rs6000_expand_interleave (reg, operands[1], operands[1], false);
+ rs6000_expand_interleave (reg, operands[1], operands[1], !BYTES_BIG_ENDIAN);
emit_insn (gen_vsx_xvcvuxwdp (operands[0], reg));
DONE;
})
@@ -940,8 +965,15 @@
emit_insn (gen_altivec_vperm_<mode> (operands[0], operands[1],
operands[2], operands[3]));
else
- emit_insn (gen_altivec_vperm_<mode> (operands[0], operands[2],
- operands[1], operands[3]));
+ {
+ /* Avoid the "subtract from splat31" workaround for vperm since
+ we have changed lvsr to lvsl instead. */
+ rtx unspec = gen_rtx_UNSPEC (<MODE>mode,
+ gen_rtvec (3, operands[2],
+ operands[1], operands[3]),
+ UNSPEC_VPERM);
+ emit_move_insn (operands[0], unspec);
+ }
DONE;
})
diff --git a/gcc/config/rs6000/vsx.md b/gcc/config/rs6000/vsx.md
index 11d6b8bb4d0..8a51afb3c86 100644
--- a/gcc/config/rs6000/vsx.md
+++ b/gcc/config/rs6000/vsx.md
@@ -216,6 +216,359 @@
])
;; VSX moves
+
+;; The patterns for LE permuted loads and stores come before the general
+;; VSX moves so they match first.
+(define_insn_and_split "*vsx_le_perm_load_<mode>"
+ [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wa")
+ (match_operand:VSX_D 1 "memory_operand" "Z"))]
+ "!BYTES_BIG_ENDIAN && TARGET_VSX"
+ "#"
+ "!BYTES_BIG_ENDIAN && TARGET_VSX"
+ [(set (match_dup 2)
+ (vec_select:<MODE>
+ (match_dup 1)
+ (parallel [(const_int 1) (const_int 0)])))
+ (set (match_dup 0)
+ (vec_select:<MODE>
+ (match_dup 2)
+ (parallel [(const_int 1) (const_int 0)])))]
+ "
+{
+ operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[0])
+ : operands[0];
+}
+ "
+ [(set_attr "type" "vecload")
+ (set_attr "length" "8")])
+
+(define_insn_and_split "*vsx_le_perm_load_<mode>"
+ [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wa")
+ (match_operand:VSX_W 1 "memory_operand" "Z"))]
+ "!BYTES_BIG_ENDIAN && TARGET_VSX"
+ "#"
+ "!BYTES_BIG_ENDIAN && TARGET_VSX"
+ [(set (match_dup 2)
+ (vec_select:<MODE>
+ (match_dup 1)
+ (parallel [(const_int 2) (const_int 3)
+ (const_int 0) (const_int 1)])))
+ (set (match_dup 0)
+ (vec_select:<MODE>
+ (match_dup 2)
+ (parallel [(const_int 2) (const_int 3)
+ (const_int 0) (const_int 1)])))]
+ "
+{
+ operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[0])
+ : operands[0];
+}
+ "
+ [(set_attr "type" "vecload")
+ (set_attr "length" "8")])
+
+(define_insn_and_split "*vsx_le_perm_load_v8hi"
+ [(set (match_operand:V8HI 0 "vsx_register_operand" "=wa")
+ (match_operand:V8HI 1 "memory_operand" "Z"))]
+ "!BYTES_BIG_ENDIAN && TARGET_VSX"
+ "#"
+ "!BYTES_BIG_ENDIAN && TARGET_VSX"
+ [(set (match_dup 2)
+ (vec_select:V8HI
+ (match_dup 1)
+ (parallel [(const_int 4) (const_int 5)
+ (const_int 6) (const_int 7)
+ (const_int 0) (const_int 1)
+ (const_int 2) (const_int 3)])))
+ (set (match_dup 0)
+ (vec_select:V8HI
+ (match_dup 2)
+ (parallel [(const_int 4) (const_int 5)
+ (const_int 6) (const_int 7)
+ (const_int 0) (const_int 1)
+ (const_int 2) (const_int 3)])))]
+ "
+{
+ operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[0])
+ : operands[0];
+}
+ "
+ [(set_attr "type" "vecload")
+ (set_attr "length" "8")])
+
+(define_insn_and_split "*vsx_le_perm_load_v16qi"
+ [(set (match_operand:V16QI 0 "vsx_register_operand" "=wa")
+ (match_operand:V16QI 1 "memory_operand" "Z"))]
+ "!BYTES_BIG_ENDIAN && TARGET_VSX"
+ "#"
+ "!BYTES_BIG_ENDIAN && TARGET_VSX"
+ [(set (match_dup 2)
+ (vec_select:V16QI
+ (match_dup 1)
+ (parallel [(const_int 8) (const_int 9)
+ (const_int 10) (const_int 11)
+ (const_int 12) (const_int 13)
+ (const_int 14) (const_int 15)
+ (const_int 0) (const_int 1)
+ (const_int 2) (const_int 3)
+ (const_int 4) (const_int 5)
+ (const_int 6) (const_int 7)])))
+ (set (match_dup 0)
+ (vec_select:V16QI
+ (match_dup 2)
+ (parallel [(const_int 8) (const_int 9)
+ (const_int 10) (const_int 11)
+ (const_int 12) (const_int 13)
+ (const_int 14) (const_int 15)
+ (const_int 0) (const_int 1)
+ (const_int 2) (const_int 3)
+ (const_int 4) (const_int 5)
+ (const_int 6) (const_int 7)])))]
+ "
+{
+ operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[0])
+ : operands[0];
+}
+ "
+ [(set_attr "type" "vecload")
+ (set_attr "length" "8")])
+
+(define_insn "*vsx_le_perm_store_<mode>"
+ [(set (match_operand:VSX_D 0 "memory_operand" "=Z")
+ (match_operand:VSX_D 1 "vsx_register_operand" "+wa"))]
+ "!BYTES_BIG_ENDIAN && TARGET_VSX"
+ "#"
+ [(set_attr "type" "vecstore")
+ (set_attr "length" "12")])
+
+(define_split
+ [(set (match_operand:VSX_D 0 "memory_operand" "")
+ (match_operand:VSX_D 1 "vsx_register_operand" ""))]
+ "!BYTES_BIG_ENDIAN && TARGET_VSX && !reload_completed"
+ [(set (match_dup 2)
+ (vec_select:<MODE>
+ (match_dup 1)
+ (parallel [(const_int 1) (const_int 0)])))
+ (set (match_dup 0)
+ (vec_select:<MODE>
+ (match_dup 2)
+ (parallel [(const_int 1) (const_int 0)])))]
+{
+ operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[1])
+ : operands[1];
+})
+
+;; The post-reload split requires that we re-permute the source
+;; register in case it is still live.
+(define_split
+ [(set (match_operand:VSX_D 0 "memory_operand" "")
+ (match_operand:VSX_D 1 "vsx_register_operand" ""))]
+ "!BYTES_BIG_ENDIAN && TARGET_VSX && reload_completed"
+ [(set (match_dup 1)
+ (vec_select:<MODE>
+ (match_dup 1)
+ (parallel [(const_int 1) (const_int 0)])))
+ (set (match_dup 0)
+ (vec_select:<MODE>
+ (match_dup 1)
+ (parallel [(const_int 1) (const_int 0)])))
+ (set (match_dup 1)
+ (vec_select:<MODE>
+ (match_dup 1)
+ (parallel [(const_int 1) (const_int 0)])))]
+ "")
+
+(define_insn "*vsx_le_perm_store_<mode>"
+ [(set (match_operand:VSX_W 0 "memory_operand" "=Z")
+ (match_operand:VSX_W 1 "vsx_register_operand" "+wa"))]
+ "!BYTES_BIG_ENDIAN && TARGET_VSX"
+ "#"
+ [(set_attr "type" "vecstore")
+ (set_attr "length" "12")])
+
+(define_split
+ [(set (match_operand:VSX_W 0 "memory_operand" "")
+ (match_operand:VSX_W 1 "vsx_register_operand" ""))]
+ "!BYTES_BIG_ENDIAN && TARGET_VSX && !reload_completed"
+ [(set (match_dup 2)
+ (vec_select:<MODE>
+ (match_dup 1)
+ (parallel [(const_int 2) (const_int 3)
+ (const_int 0) (const_int 1)])))
+ (set (match_dup 0)
+ (vec_select:<MODE>
+ (match_dup 2)
+ (parallel [(const_int 2) (const_int 3)
+ (const_int 0) (const_int 1)])))]
+{
+ operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[1])
+ : operands[1];
+})
+
+;; The post-reload split requires that we re-permute the source
+;; register in case it is still live.
+(define_split
+ [(set (match_operand:VSX_W 0 "memory_operand" "")
+ (match_operand:VSX_W 1 "vsx_register_operand" ""))]
+ "!BYTES_BIG_ENDIAN && TARGET_VSX && reload_completed"
+ [(set (match_dup 1)
+ (vec_select:<MODE>
+ (match_dup 1)
+ (parallel [(const_int 2) (const_int 3)
+ (const_int 0) (const_int 1)])))
+ (set (match_dup 0)
+ (vec_select:<MODE>
+ (match_dup 1)
+ (parallel [(const_int 2) (const_int 3)
+ (const_int 0) (const_int 1)])))
+ (set (match_dup 1)
+ (vec_select:<MODE>
+ (match_dup 1)
+ (parallel [(const_int 2) (const_int 3)
+ (const_int 0) (const_int 1)])))]
+ "")
+
+(define_insn "*vsx_le_perm_store_v8hi"
+ [(set (match_operand:V8HI 0 "memory_operand" "=Z")
+ (match_operand:V8HI 1 "vsx_register_operand" "+wa"))]
+ "!BYTES_BIG_ENDIAN && TARGET_VSX"
+ "#"
+ [(set_attr "type" "vecstore")
+ (set_attr "length" "12")])
+
+(define_split
+ [(set (match_operand:V8HI 0 "memory_operand" "")
+ (match_operand:V8HI 1 "vsx_register_operand" ""))]
+ "!BYTES_BIG_ENDIAN && TARGET_VSX && !reload_completed"
+ [(set (match_dup 2)
+ (vec_select:V8HI
+ (match_dup 1)
+ (parallel [(const_int 4) (const_int 5)
+ (const_int 6) (const_int 7)
+ (const_int 0) (const_int 1)
+ (const_int 2) (const_int 3)])))
+ (set (match_dup 0)
+ (vec_select:V8HI
+ (match_dup 2)
+ (parallel [(const_int 4) (const_int 5)
+ (const_int 6) (const_int 7)
+ (const_int 0) (const_int 1)
+ (const_int 2) (const_int 3)])))]
+{
+ operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[1])
+ : operands[1];
+})
+
+;; The post-reload split requires that we re-permute the source
+;; register in case it is still live.
+(define_split
+ [(set (match_operand:V8HI 0 "memory_operand" "")
+ (match_operand:V8HI 1 "vsx_register_operand" ""))]
+ "!BYTES_BIG_ENDIAN && TARGET_VSX && reload_completed"
+ [(set (match_dup 1)
+ (vec_select:V8HI
+ (match_dup 1)
+ (parallel [(const_int 4) (const_int 5)
+ (const_int 6) (const_int 7)
+ (const_int 0) (const_int 1)
+ (const_int 2) (const_int 3)])))
+ (set (match_dup 0)
+ (vec_select:V8HI
+ (match_dup 1)
+ (parallel [(const_int 4) (const_int 5)
+ (const_int 6) (const_int 7)
+ (const_int 0) (const_int 1)
+ (const_int 2) (const_int 3)])))
+ (set (match_dup 1)
+ (vec_select:V8HI
+ (match_dup 1)
+ (parallel [(const_int 4) (const_int 5)
+ (const_int 6) (const_int 7)
+ (const_int 0) (const_int 1)
+ (const_int 2) (const_int 3)])))]
+ "")
+
+(define_insn "*vsx_le_perm_store_v16qi"
+ [(set (match_operand:V16QI 0 "memory_operand" "=Z")
+ (match_operand:V16QI 1 "vsx_register_operand" "+wa"))]
+ "!BYTES_BIG_ENDIAN && TARGET_VSX"
+ "#"
+ [(set_attr "type" "vecstore")
+ (set_attr "length" "12")])
+
+(define_split
+ [(set (match_operand:V16QI 0 "memory_operand" "")
+ (match_operand:V16QI 1 "vsx_register_operand" ""))]
+ "!BYTES_BIG_ENDIAN && TARGET_VSX && !reload_completed"
+ [(set (match_dup 2)
+ (vec_select:V16QI
+ (match_dup 1)
+ (parallel [(const_int 8) (const_int 9)
+ (const_int 10) (const_int 11)
+ (const_int 12) (const_int 13)
+ (const_int 14) (const_int 15)
+ (const_int 0) (const_int 1)
+ (const_int 2) (const_int 3)
+ (const_int 4) (const_int 5)
+ (const_int 6) (const_int 7)])))
+ (set (match_dup 0)
+ (vec_select:V16QI
+ (match_dup 2)
+ (parallel [(const_int 8) (const_int 9)
+ (const_int 10) (const_int 11)
+ (const_int 12) (const_int 13)
+ (const_int 14) (const_int 15)
+ (const_int 0) (const_int 1)
+ (const_int 2) (const_int 3)
+ (const_int 4) (const_int 5)
+ (const_int 6) (const_int 7)])))]
+{
+ operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[1])
+ : operands[1];
+})
+
+;; The post-reload split requires that we re-permute the source
+;; register in case it is still live.
+(define_split
+ [(set (match_operand:V16QI 0 "memory_operand" "")
+ (match_operand:V16QI 1 "vsx_register_operand" ""))]
+ "!BYTES_BIG_ENDIAN && TARGET_VSX && reload_completed"
+ [(set (match_dup 1)
+ (vec_select:V16QI
+ (match_dup 1)
+ (parallel [(const_int 8) (const_int 9)
+ (const_int 10) (const_int 11)
+ (const_int 12) (const_int 13)
+ (const_int 14) (const_int 15)
+ (const_int 0) (const_int 1)
+ (const_int 2) (const_int 3)
+ (const_int 4) (const_int 5)
+ (const_int 6) (const_int 7)])))
+ (set (match_dup 0)
+ (vec_select:V16QI
+ (match_dup 1)
+ (parallel [(const_int 8) (const_int 9)
+ (const_int 10) (const_int 11)
+ (const_int 12) (const_int 13)
+ (const_int 14) (const_int 15)
+ (const_int 0) (const_int 1)
+ (const_int 2) (const_int 3)
+ (const_int 4) (const_int 5)
+ (const_int 6) (const_int 7)])))
+ (set (match_dup 1)
+ (vec_select:V16QI
+ (match_dup 1)
+ (parallel [(const_int 8) (const_int 9)
+ (const_int 10) (const_int 11)
+ (const_int 12) (const_int 13)
+ (const_int 14) (const_int 15)
+ (const_int 0) (const_int 1)
+ (const_int 2) (const_int 3)
+ (const_int 4) (const_int 5)
+ (const_int 6) (const_int 7)])))]
+ "")
+
+
(define_insn "*vsx_mov<mode>"
[(set (match_operand:VSX_M 0 "nonimmediate_operand" "=Z,<VSr>,<VSr>,?Z,?wa,?wa,wQ,?&r,??Y,??r,??r,<VSr>,?wa,*r,v,wZ, v")
(match_operand:VSX_M 1 "input_operand" "<VSr>,Z,<VSr>,wa,Z,wa,r,wQ,r,Y,r,j,j,j,W,v,wZ"))]
@@ -316,40 +669,42 @@
"")
-;; VSX scalar and vector floating point arithmetic instructions
+;; VSX vector floating point arithmetic instructions. The VSX scalar
+;; instructions are now combined with the insn for the traditional floating
+;; point unit.
(define_insn "*vsx_add<mode>3"
- [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
- (plus:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
- (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
+ (plus:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
+ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "x<VSv>add<VSs> %x0,%x1,%x2"
+ "xvadd<VSs> %x0,%x1,%x2"
[(set_attr "type" "<VStype_simple>")
(set_attr "fp_type" "<VSfptype_simple>")])
(define_insn "*vsx_sub<mode>3"
- [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
- (minus:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
- (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
+ (minus:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
+ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "x<VSv>sub<VSs> %x0,%x1,%x2"
+ "xvsub<VSs> %x0,%x1,%x2"
[(set_attr "type" "<VStype_simple>")
(set_attr "fp_type" "<VSfptype_simple>")])
(define_insn "*vsx_mul<mode>3"
- [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
- (mult:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
- (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
+ (mult:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
+ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "x<VSv>mul<VSs> %x0,%x1,%x2"
- [(set_attr "type" "<VStype_mul>")
+ "xvmul<VSs> %x0,%x1,%x2"
+ [(set_attr "type" "<VStype_simple>")
(set_attr "fp_type" "<VSfptype_mul>")])
(define_insn "*vsx_div<mode>3"
- [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
- (div:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
- (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
+ (div:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
+ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "x<VSv>div<VSs> %x0,%x1,%x2"
+ "xvdiv<VSs> %x0,%x1,%x2"
[(set_attr "type" "<VStype_div>")
(set_attr "fp_type" "<VSfptype_div>")])
@@ -392,94 +747,72 @@
(set_attr "fp_type" "<VSfptype_simple>")])
(define_insn "vsx_fre<mode>2"
- [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
- (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
+ (unspec:VSX_F [(match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")]
UNSPEC_FRES))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "x<VSv>re<VSs> %x0,%x1"
+ "xvre<VSs> %x0,%x1"
[(set_attr "type" "<VStype_simple>")
(set_attr "fp_type" "<VSfptype_simple>")])
(define_insn "*vsx_neg<mode>2"
- [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
- (neg:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
+ (neg:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "x<VSv>neg<VSs> %x0,%x1"
+ "xvneg<VSs> %x0,%x1"
[(set_attr "type" "<VStype_simple>")
(set_attr "fp_type" "<VSfptype_simple>")])
(define_insn "*vsx_abs<mode>2"
- [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
- (abs:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
+ (abs:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "x<VSv>abs<VSs> %x0,%x1"
+ "xvabs<VSs> %x0,%x1"
[(set_attr "type" "<VStype_simple>")
(set_attr "fp_type" "<VSfptype_simple>")])
(define_insn "vsx_nabs<mode>2"
- [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
- (neg:VSX_B
- (abs:VSX_B
- (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa"))))]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
+ (neg:VSX_F
+ (abs:VSX_F
+ (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa"))))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "x<VSv>nabs<VSs> %x0,%x1"
+ "xvnabs<VSs> %x0,%x1"
[(set_attr "type" "<VStype_simple>")
(set_attr "fp_type" "<VSfptype_simple>")])
(define_insn "vsx_smax<mode>3"
- [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
- (smax:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
- (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
+ (smax:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
+ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "x<VSv>max<VSs> %x0,%x1,%x2"
+ "xvmax<VSs> %x0,%x1,%x2"
[(set_attr "type" "<VStype_simple>")
(set_attr "fp_type" "<VSfptype_simple>")])
(define_insn "*vsx_smin<mode>3"
- [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
- (smin:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
- (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
+ (smin:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
+ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "x<VSv>min<VSs> %x0,%x1,%x2"
+ "xvmin<VSs> %x0,%x1,%x2"
[(set_attr "type" "<VStype_simple>")
(set_attr "fp_type" "<VSfptype_simple>")])
-;; Special VSX version of smin/smax for single precision floating point. Since
-;; both numbers are rounded to single precision, we can just use the DP version
-;; of the instruction.
-
-(define_insn "*vsx_smaxsf3"
- [(set (match_operand:SF 0 "vsx_register_operand" "=f")
- (smax:SF (match_operand:SF 1 "vsx_register_operand" "f")
- (match_operand:SF 2 "vsx_register_operand" "f")))]
- "VECTOR_UNIT_VSX_P (DFmode)"
- "xsmaxdp %x0,%x1,%x2"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_addsub_d")])
-
-(define_insn "*vsx_sminsf3"
- [(set (match_operand:SF 0 "vsx_register_operand" "=f")
- (smin:SF (match_operand:SF 1 "vsx_register_operand" "f")
- (match_operand:SF 2 "vsx_register_operand" "f")))]
- "VECTOR_UNIT_VSX_P (DFmode)"
- "xsmindp %x0,%x1,%x2"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_addsub_d")])
-
(define_insn "*vsx_sqrt<mode>2"
- [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
- (sqrt:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
+ (sqrt:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "x<VSv>sqrt<VSs> %x0,%x1"
+ "xvsqrt<VSs> %x0,%x1"
[(set_attr "type" "<VStype_sqrt>")
(set_attr "fp_type" "<VSfptype_sqrt>")])
(define_insn "*vsx_rsqrte<mode>2"
- [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
- (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
+ (unspec:VSX_F [(match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")]
UNSPEC_RSQRT))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "x<VSv>rsqrte<VSs> %x0,%x1"
+ "xvrsqrte<VSs> %x0,%x1"
[(set_attr "type" "<VStype_simple>")
(set_attr "fp_type" "<VSfptype_simple>")])
@@ -518,26 +851,10 @@
[(set_attr "type" "<VStype_simple>")
(set_attr "fp_type" "<VSfptype_simple>")])
-;; Fused vector multiply/add instructions Support the classical DF versions of
-;; fma, which allows the target to be a separate register from the 3 inputs.
-;; Under VSX, the target must be either the addend or the first multiply.
-;; Where we can, also do the same for the Altivec V4SF fmas.
-
-(define_insn "*vsx_fmadf4"
- [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws,?wa,?wa,d")
- (fma:DF
- (match_operand:DF 1 "vsx_register_operand" "%ws,ws,wa,wa,d")
- (match_operand:DF 2 "vsx_register_operand" "ws,0,wa,0,d")
- (match_operand:DF 3 "vsx_register_operand" "0,ws,0,wa,d")))]
- "VECTOR_UNIT_VSX_P (DFmode)"
- "@
- xsmaddadp %x0,%x1,%x2
- xsmaddmdp %x0,%x1,%x3
- xsmaddadp %x0,%x1,%x2
- xsmaddmdp %x0,%x1,%x3
- fmadd %0,%1,%2,%3"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_maddsub_d")])
+;; Fused vector multiply/add instructions. Support the classical Altivec
+;; versions of fma, which allows the target to be a separate register from the
+;; 3 inputs. Under VSX, the target must be either the addend or the first
+;; multiply.
(define_insn "*vsx_fmav4sf4"
[(set (match_operand:V4SF 0 "vsx_register_operand" "=ws,ws,?wa,?wa,v")
@@ -568,23 +885,6 @@
xvmaddmdp %x0,%x1,%x3"
[(set_attr "type" "vecdouble")])
-(define_insn "*vsx_fmsdf4"
- [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws,?wa,?wa,d")
- (fma:DF
- (match_operand:DF 1 "vsx_register_operand" "%ws,ws,wa,wa,d")
- (match_operand:DF 2 "vsx_register_operand" "ws,0,wa,0,d")
- (neg:DF
- (match_operand:DF 3 "vsx_register_operand" "0,ws,0,wa,d"))))]
- "VECTOR_UNIT_VSX_P (DFmode)"
- "@
- xsmsubadp %x0,%x1,%x2
- xsmsubmdp %x0,%x1,%x3
- xsmsubadp %x0,%x1,%x2
- xsmsubmdp %x0,%x1,%x3
- fmsub %0,%1,%2,%3"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_maddsub_d")])
-
(define_insn "*vsx_fms<mode>4"
[(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
(fma:VSX_F
@@ -594,29 +894,12 @@
(match_operand:VSX_F 3 "vsx_register_operand" "0,<VSr>,0,wa"))))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
"@
- x<VSv>msuba<VSs> %x0,%x1,%x2
- x<VSv>msubm<VSs> %x0,%x1,%x3
- x<VSv>msuba<VSs> %x0,%x1,%x2
- x<VSv>msubm<VSs> %x0,%x1,%x3"
+ xvmsuba<VSs> %x0,%x1,%x2
+ xvmsubm<VSs> %x0,%x1,%x3
+ xvmsuba<VSs> %x0,%x1,%x2
+ xvmsubm<VSs> %x0,%x1,%x3"
[(set_attr "type" "<VStype_mul>")])
-(define_insn "*vsx_nfmadf4"
- [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws,?wa,?wa,d")
- (neg:DF
- (fma:DF
- (match_operand:DF 1 "vsx_register_operand" "ws,ws,wa,wa,d")
- (match_operand:DF 2 "vsx_register_operand" "ws,0,wa,0,d")
- (match_operand:DF 3 "vsx_register_operand" "0,ws,0,wa,d"))))]
- "VECTOR_UNIT_VSX_P (DFmode)"
- "@
- xsnmaddadp %x0,%x1,%x2
- xsnmaddmdp %x0,%x1,%x3
- xsnmaddadp %x0,%x1,%x2
- xsnmaddmdp %x0,%x1,%x3
- fnmadd %0,%1,%2,%3"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_maddsub_d")])
-
(define_insn "*vsx_nfma<mode>4"
[(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
(neg:VSX_F
@@ -626,31 +909,13 @@
(match_operand:VSX_F 3 "vsx_register_operand" "0,<VSr>,0,wa"))))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
"@
- x<VSv>nmadda<VSs> %x0,%x1,%x2
- x<VSv>nmaddm<VSs> %x0,%x1,%x3
- x<VSv>nmadda<VSs> %x0,%x1,%x2
- x<VSv>nmaddm<VSs> %x0,%x1,%x3"
+ xvnmadda<VSs> %x0,%x1,%x2
+ xvnmaddm<VSs> %x0,%x1,%x3
+ xvnmadda<VSs> %x0,%x1,%x2
+ xvnmaddm<VSs> %x0,%x1,%x3"
[(set_attr "type" "<VStype_mul>")
(set_attr "fp_type" "<VSfptype_mul>")])
-(define_insn "*vsx_nfmsdf4"
- [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws,?wa,?wa,d")
- (neg:DF
- (fma:DF
- (match_operand:DF 1 "vsx_register_operand" "%ws,ws,wa,wa,d")
- (match_operand:DF 2 "vsx_register_operand" "ws,0,wa,0,d")
- (neg:DF
- (match_operand:DF 3 "vsx_register_operand" "0,ws,0,wa,d")))))]
- "VECTOR_UNIT_VSX_P (DFmode)"
- "@
- xsnmsubadp %x0,%x1,%x2
- xsnmsubmdp %x0,%x1,%x3
- xsnmsubadp %x0,%x1,%x2
- xsnmsubmdp %x0,%x1,%x3
- fnmsub %0,%1,%2,%3"
- [(set_attr "type" "fp")
- (set_attr "fp_type" "fp_maddsub_d")])
-
(define_insn "*vsx_nfmsv4sf4"
[(set (match_operand:V4SF 0 "vsx_register_operand" "=wf,wf,?wa,?wa,v")
(neg:V4SF
@@ -712,16 +977,6 @@
[(set_attr "type" "<VStype_simple>")
(set_attr "fp_type" "<VSfptype_simple>")])
-;; Floating point scalar compare
-(define_insn "*vsx_cmpdf_internal1"
- [(set (match_operand:CCFP 0 "cc_reg_operand" "=y,?y")
- (compare:CCFP (match_operand:DF 1 "gpc_reg_operand" "ws,wa")
- (match_operand:DF 2 "gpc_reg_operand" "ws,wa")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
- && VECTOR_UNIT_VSX_P (DFmode)"
- "xscmpudp %0,%x1,%x2"
- [(set_attr "type" "fpcompare")])
-
;; Compare vectors producing a vector result and a predicate, setting CR6 to
;; indicate a combined status
(define_insn "*vsx_eq_<mode>_p"
@@ -788,13 +1043,13 @@
;; Copy sign
(define_insn "vsx_copysign<mode>3"
- [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
- (unspec:VSX_B
- [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
- (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
+ (unspec:VSX_F
+ [(match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
+ (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")]
UNSPEC_COPYSIGN))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "x<VSv>cpsgn<VSs> %x0,%x2,%x1"
+ "xvcpsgn<VSs> %x0,%x2,%x1"
[(set_attr "type" "<VStype_simple>")
(set_attr "fp_type" "<VSfptype_simple>")])
@@ -855,10 +1110,10 @@
(set_attr "fp_type" "<VSfptype_simple>")])
(define_insn "vsx_btrunc<mode>2"
- [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
- (fix:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
+ (fix:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "x<VSv>r<VSs>iz %x0,%x1"
+ "xvr<VSs>iz %x0,%x1"
[(set_attr "type" "<VStype_simple>")
(set_attr "fp_type" "<VSfptype_simple>")])
@@ -872,20 +1127,20 @@
(set_attr "fp_type" "<VSfptype_simple>")])
(define_insn "vsx_floor<mode>2"
- [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
- (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
+ (unspec:VSX_F [(match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")]
UNSPEC_FRIM))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "x<VSv>r<VSs>im %x0,%x1"
+ "xvr<VSs>im %x0,%x1"
[(set_attr "type" "<VStype_simple>")
(set_attr "fp_type" "<VSfptype_simple>")])
(define_insn "vsx_ceil<mode>2"
- [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
- (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
+ (unspec:VSX_F [(match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")]
UNSPEC_FRIP))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "x<VSv>r<VSs>ip %x0,%x1"
+ "xvr<VSs>ip %x0,%x1"
[(set_attr "type" "<VStype_simple>")
(set_attr "fp_type" "<VSfptype_simple>")])
@@ -1060,7 +1315,12 @@
(match_operand:<VS_scalar> 1 "vsx_register_operand" "ws,wa")
(match_operand:<VS_scalar> 2 "vsx_register_operand" "ws,wa")))]
"VECTOR_MEM_VSX_P (<MODE>mode)"
- "xxpermdi %x0,%x1,%x2,0"
+{
+ if (BYTES_BIG_ENDIAN)
+ return "xxpermdi %x0,%x1,%x2,0";
+ else
+ return "xxpermdi %x0,%x2,%x1,0";
+}
[(set_attr "type" "vecperm")])
;; Special purpose concat using xxpermdi to glue two single precision values
@@ -1073,9 +1333,161 @@
(match_operand:SF 2 "vsx_register_operand" "f,f")]
UNSPEC_VSX_CONCAT))]
"VECTOR_MEM_VSX_P (V2DFmode)"
- "xxpermdi %x0,%x1,%x2,0"
+{
+ if (BYTES_BIG_ENDIAN)
+ return "xxpermdi %x0,%x1,%x2,0";
+ else
+ return "xxpermdi %x0,%x2,%x1,0";
+}
+ [(set_attr "type" "vecperm")])
+
+;; xxpermdi for little endian loads and stores. We need several of
+;; these since the form of the PARALLEL differs by mode.
+(define_insn "*vsx_xxpermdi2_le_<mode>"
+ [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wa")
+ (vec_select:VSX_D
+ (match_operand:VSX_D 1 "vsx_register_operand" "wa")
+ (parallel [(const_int 1) (const_int 0)])))]
+ "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (<MODE>mode)"
+ "xxpermdi %x0,%x1,%x1,2"
+ [(set_attr "type" "vecperm")])
+
+(define_insn "*vsx_xxpermdi4_le_<mode>"
+ [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wa")
+ (vec_select:VSX_W
+ (match_operand:VSX_W 1 "vsx_register_operand" "wa")
+ (parallel [(const_int 2) (const_int 3)
+ (const_int 0) (const_int 1)])))]
+ "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (<MODE>mode)"
+ "xxpermdi %x0,%x1,%x1,2"
[(set_attr "type" "vecperm")])
+(define_insn "*vsx_xxpermdi8_le_V8HI"
+ [(set (match_operand:V8HI 0 "vsx_register_operand" "=wa")
+ (vec_select:V8HI
+ (match_operand:V8HI 1 "vsx_register_operand" "wa")
+ (parallel [(const_int 4) (const_int 5)
+ (const_int 6) (const_int 7)
+ (const_int 0) (const_int 1)
+ (const_int 2) (const_int 3)])))]
+ "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (V8HImode)"
+ "xxpermdi %x0,%x1,%x1,2"
+ [(set_attr "type" "vecperm")])
+
+(define_insn "*vsx_xxpermdi16_le_V16QI"
+ [(set (match_operand:V16QI 0 "vsx_register_operand" "=wa")
+ (vec_select:V16QI
+ (match_operand:V16QI 1 "vsx_register_operand" "wa")
+ (parallel [(const_int 8) (const_int 9)
+ (const_int 10) (const_int 11)
+ (const_int 12) (const_int 13)
+ (const_int 14) (const_int 15)
+ (const_int 0) (const_int 1)
+ (const_int 2) (const_int 3)
+ (const_int 4) (const_int 5)
+ (const_int 6) (const_int 7)])))]
+ "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (V16QImode)"
+ "xxpermdi %x0,%x1,%x1,2"
+ [(set_attr "type" "vecperm")])
+
+;; lxvd2x for little endian loads. We need several of
+;; these since the form of the PARALLEL differs by mode.
+(define_insn "*vsx_lxvd2x2_le_<mode>"
+ [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wa")
+ (vec_select:VSX_D
+ (match_operand:VSX_D 1 "memory_operand" "Z")
+ (parallel [(const_int 1) (const_int 0)])))]
+ "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (<MODE>mode)"
+ "lxvd2x %x0,%y1"
+ [(set_attr "type" "vecload")])
+
+(define_insn "*vsx_lxvd2x4_le_<mode>"
+ [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wa")
+ (vec_select:VSX_W
+ (match_operand:VSX_W 1 "memory_operand" "Z")
+ (parallel [(const_int 2) (const_int 3)
+ (const_int 0) (const_int 1)])))]
+ "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (<MODE>mode)"
+ "lxvd2x %x0,%y1"
+ [(set_attr "type" "vecload")])
+
+(define_insn "*vsx_lxvd2x8_le_V8HI"
+ [(set (match_operand:V8HI 0 "vsx_register_operand" "=wa")
+ (vec_select:V8HI
+ (match_operand:V8HI 1 "memory_operand" "Z")
+ (parallel [(const_int 4) (const_int 5)
+ (const_int 6) (const_int 7)
+ (const_int 0) (const_int 1)
+ (const_int 2) (const_int 3)])))]
+ "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (V8HImode)"
+ "lxvd2x %x0,%y1"
+ [(set_attr "type" "vecload")])
+
+(define_insn "*vsx_lxvd2x16_le_V16QI"
+ [(set (match_operand:V16QI 0 "vsx_register_operand" "=wa")
+ (vec_select:V16QI
+ (match_operand:V16QI 1 "memory_operand" "Z")
+ (parallel [(const_int 8) (const_int 9)
+ (const_int 10) (const_int 11)
+ (const_int 12) (const_int 13)
+ (const_int 14) (const_int 15)
+ (const_int 0) (const_int 1)
+ (const_int 2) (const_int 3)
+ (const_int 4) (const_int 5)
+ (const_int 6) (const_int 7)])))]
+ "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (V16QImode)"
+ "lxvd2x %x0,%y1"
+ [(set_attr "type" "vecload")])
+
+;; stxvd2x for little endian stores. We need several of
+;; these since the form of the PARALLEL differs by mode.
+(define_insn "*vsx_stxvd2x2_le_<mode>"
+ [(set (match_operand:VSX_D 0 "memory_operand" "=Z")
+ (vec_select:VSX_D
+ (match_operand:VSX_D 1 "vsx_register_operand" "wa")
+ (parallel [(const_int 1) (const_int 0)])))]
+ "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (<MODE>mode)"
+ "stxvd2x %x1,%y0"
+ [(set_attr "type" "vecstore")])
+
+(define_insn "*vsx_stxvd2x4_le_<mode>"
+ [(set (match_operand:VSX_W 0 "memory_operand" "=Z")
+ (vec_select:VSX_W
+ (match_operand:VSX_W 1 "vsx_register_operand" "wa")
+ (parallel [(const_int 2) (const_int 3)
+ (const_int 0) (const_int 1)])))]
+ "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (<MODE>mode)"
+ "stxvd2x %x1,%y0"
+ [(set_attr "type" "vecstore")])
+
+(define_insn "*vsx_stxvd2x8_le_V8HI"
+ [(set (match_operand:V8HI 0 "memory_operand" "=Z")
+ (vec_select:V8HI
+ (match_operand:V8HI 1 "vsx_register_operand" "wa")
+ (parallel [(const_int 4) (const_int 5)
+ (const_int 6) (const_int 7)
+ (const_int 0) (const_int 1)
+ (const_int 2) (const_int 3)])))]
+ "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (V8HImode)"
+ "stxvd2x %x1,%y0"
+ [(set_attr "type" "vecstore")])
+
+(define_insn "*vsx_stxvd2x16_le_V16QI"
+ [(set (match_operand:V16QI 0 "memory_operand" "=Z")
+ (vec_select:V16QI
+ (match_operand:V16QI 1 "vsx_register_operand" "wa")
+ (parallel [(const_int 8) (const_int 9)
+ (const_int 10) (const_int 11)
+ (const_int 12) (const_int 13)
+ (const_int 14) (const_int 15)
+ (const_int 0) (const_int 1)
+ (const_int 2) (const_int 3)
+ (const_int 4) (const_int 5)
+ (const_int 6) (const_int 7)])))]
+ "!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (V16QImode)"
+ "stxvd2x %x1,%y0"
+ [(set_attr "type" "vecstore")])
+
;; Set the element of a V2DI/VD2F mode
(define_insn "vsx_set_<mode>"
[(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd,?wa")
diff --git a/gcc/config/rs6000/x-darwin b/gcc/config/rs6000/x-darwin
index 5672c698b1e..9d92ef547c8 100644
--- a/gcc/config/rs6000/x-darwin
+++ b/gcc/config/rs6000/x-darwin
@@ -1,5 +1,3 @@
-host-ppc-darwin.o : $(srcdir)/config/rs6000/host-darwin.c \
- $(CONFIG_H) $(SYSTEM_H) coretypes.h hosthooks.h $(HOSTHOOKS_DEF_H) toplev.h \
- config/host-darwin.h $(DIAGNOSTIC_H)
- $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) \
- $(INCLUDES) $< -o $@
+host-ppc-darwin.o : $(srcdir)/config/rs6000/host-darwin.c
+ $(COMPILE) $<
+ $(POSTCOMPILE)
diff --git a/gcc/config/rs6000/x-darwin64 b/gcc/config/rs6000/x-darwin64
index 921d555ba01..093277147bc 100644
--- a/gcc/config/rs6000/x-darwin64
+++ b/gcc/config/rs6000/x-darwin64
@@ -1,5 +1,3 @@
-host-ppc64-darwin.o : $(srcdir)/config/rs6000/host-ppc64-darwin.c \
- $(CONFIG_H) $(SYSTEM_H) coretypes.h hosthooks.h $(HOSTHOOKS_DEF_H) toplev.h \
- config/host-darwin.h $(DIAGNOSTIC_H)
- $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) \
- $(INCLUDES) $< -o $@
+host-ppc64-darwin.o : $(srcdir)/config/rs6000/host-ppc64-darwin.c
+ $(COMPILE) $<
+ $(POSTCOMPILE)
diff --git a/gcc/config/rx/rx.c b/gcc/config/rx/rx.c
index 603e49de3ab..90d89bbc5e1 100644
--- a/gcc/config/rx/rx.c
+++ b/gcc/config/rx/rx.c
@@ -2273,6 +2273,14 @@ static GTY(()) tree rx_builtins[(int) RX_BUILTIN_max];
static void
rx_init_builtins (void)
{
+#define ADD_RX_BUILTIN0(UC_NAME, LC_NAME, RET_TYPE) \
+ rx_builtins[RX_BUILTIN_##UC_NAME] = \
+ add_builtin_function ("__builtin_rx_" LC_NAME, \
+ build_function_type_list (RET_TYPE##_type_node, \
+ NULL_TREE), \
+ RX_BUILTIN_##UC_NAME, \
+ BUILT_IN_MD, NULL, NULL_TREE)
+
#define ADD_RX_BUILTIN1(UC_NAME, LC_NAME, RET_TYPE, ARG_TYPE) \
rx_builtins[RX_BUILTIN_##UC_NAME] = \
add_builtin_function ("__builtin_rx_" LC_NAME, \
@@ -2303,7 +2311,7 @@ rx_init_builtins (void)
RX_BUILTIN_##UC_NAME, \
BUILT_IN_MD, NULL, NULL_TREE)
- ADD_RX_BUILTIN1 (BRK, "brk", void, void);
+ ADD_RX_BUILTIN0 (BRK, "brk", void);
ADD_RX_BUILTIN1 (CLRPSW, "clrpsw", void, integer);
ADD_RX_BUILTIN1 (SETPSW, "setpsw", void, integer);
ADD_RX_BUILTIN1 (INT, "int", void, integer);
@@ -2311,18 +2319,18 @@ rx_init_builtins (void)
ADD_RX_BUILTIN2 (MACLO, "maclo", void, intSI, intSI);
ADD_RX_BUILTIN2 (MULHI, "mulhi", void, intSI, intSI);
ADD_RX_BUILTIN2 (MULLO, "mullo", void, intSI, intSI);
- ADD_RX_BUILTIN1 (MVFACHI, "mvfachi", intSI, void);
- ADD_RX_BUILTIN1 (MVFACMI, "mvfacmi", intSI, void);
+ ADD_RX_BUILTIN0 (MVFACHI, "mvfachi", intSI);
+ ADD_RX_BUILTIN0 (MVFACMI, "mvfacmi", intSI);
ADD_RX_BUILTIN1 (MVTACHI, "mvtachi", void, intSI);
ADD_RX_BUILTIN1 (MVTACLO, "mvtaclo", void, intSI);
- ADD_RX_BUILTIN1 (RMPA, "rmpa", void, void);
+ ADD_RX_BUILTIN0 (RMPA, "rmpa", void);
ADD_RX_BUILTIN1 (MVFC, "mvfc", intSI, integer);
ADD_RX_BUILTIN2 (MVTC, "mvtc", void, integer, integer);
ADD_RX_BUILTIN1 (MVTIPL, "mvtipl", void, integer);
ADD_RX_BUILTIN1 (RACW, "racw", void, integer);
ADD_RX_BUILTIN1 (ROUND, "round", intSI, float);
ADD_RX_BUILTIN1 (REVW, "revw", intSI, intSI);
- ADD_RX_BUILTIN1 (WAIT, "wait", void, void);
+ ADD_RX_BUILTIN0 (WAIT, "wait", void);
}
/* Return the RX builtin for CODE. */
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index 1ea52af0f2b..f0d6a59e978 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -324,6 +324,12 @@ struct GTY (()) s390_frame_layout
int first_save_gpr_slot;
int last_save_gpr_slot;
+ /* Location (FP register number) where GPRs (r0-r15) should
+ be saved to.
+ 0 - does not need to be saved at all
+ -1 - stack slot */
+ signed char gpr_save_slots[16];
+
/* Number of first and last gpr to be saved, restored. */
int first_save_gpr;
int first_restore_gpr;
@@ -377,12 +383,17 @@ struct GTY(()) machine_function
#define cfun_frame_layout (cfun->machine->frame_layout)
#define cfun_save_high_fprs_p (!!cfun_frame_layout.high_fprs)
-#define cfun_gprs_save_area_size ((cfun_frame_layout.last_save_gpr_slot - \
+#define cfun_save_arg_fprs_p (!!(TARGET_64BIT \
+ ? cfun_frame_layout.fpr_bitmap & 0x0f \
+ : cfun_frame_layout.fpr_bitmap & 0x03))
+#define cfun_gprs_save_area_size ((cfun_frame_layout.last_save_gpr_slot - \
cfun_frame_layout.first_save_gpr_slot + 1) * UNITS_PER_LONG)
#define cfun_set_fpr_save(REGNO) (cfun->machine->frame_layout.fpr_bitmap |= \
(1 << (REGNO - FPR0_REGNUM)))
#define cfun_fpr_save_p(REGNO) (!!(cfun->machine->frame_layout.fpr_bitmap & \
(1 << (REGNO - FPR0_REGNUM))))
+#define cfun_gpr_save_slot(REGNO) \
+ cfun->machine->frame_layout.gpr_save_slots[REGNO]
/* Number of GPRs and FPRs used for argument passing. */
#define GP_ARG_NUM_REG 5
@@ -6025,11 +6036,11 @@ s390_split_branches (void)
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
{
- if (! JUMP_P (insn))
+ if (! JUMP_P (insn) || tablejump_p (insn, NULL, NULL))
continue;
pat = PATTERN (insn);
- if (GET_CODE (pat) == PARALLEL && XVECLEN (pat, 0) > 2)
+ if (GET_CODE (pat) == PARALLEL)
pat = XVECEXP (pat, 0, 0);
if (GET_CODE (pat) != SET || SET_DEST (pat) != pc_rtx)
continue;
@@ -7049,6 +7060,8 @@ s390_chunkify_start (void)
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
{
+ rtx table;
+
/* Labels marked with LABEL_PRESERVE_P can be target
of non-local jumps, so we have to mark them.
The same holds for named labels.
@@ -7063,42 +7076,41 @@ s390_chunkify_start (void)
if (! vec_insn || ! JUMP_TABLE_DATA_P (vec_insn))
bitmap_set_bit (far_labels, CODE_LABEL_NUMBER (insn));
}
+ /* Check potential targets in a table jump (casesi_jump). */
+ else if (tablejump_p (insn, NULL, &table))
+ {
+ rtx vec_pat = PATTERN (table);
+ int i, diff_p = GET_CODE (vec_pat) == ADDR_DIFF_VEC;
+
+ for (i = 0; i < XVECLEN (vec_pat, diff_p); i++)
+ {
+ rtx label = XEXP (XVECEXP (vec_pat, diff_p, i), 0);
- /* If we have a direct jump (conditional or unconditional)
- or a casesi jump, check all potential targets. */
+ if (s390_find_pool (pool_list, label)
+ != s390_find_pool (pool_list, insn))
+ bitmap_set_bit (far_labels, CODE_LABEL_NUMBER (label));
+ }
+ }
+ /* If we have a direct jump (conditional or unconditional),
+ check all potential targets. */
else if (JUMP_P (insn))
{
- rtx pat = PATTERN (insn);
- rtx table;
+ rtx pat = PATTERN (insn);
- if (GET_CODE (pat) == PARALLEL && XVECLEN (pat, 0) > 2)
+ if (GET_CODE (pat) == PARALLEL)
pat = XVECEXP (pat, 0, 0);
- if (GET_CODE (pat) == SET)
- {
+ if (GET_CODE (pat) == SET)
+ {
rtx label = JUMP_LABEL (insn);
if (label)
{
- if (s390_find_pool (pool_list, label)
+ if (s390_find_pool (pool_list, label)
!= s390_find_pool (pool_list, insn))
bitmap_set_bit (far_labels, CODE_LABEL_NUMBER (label));
}
- }
- else if (tablejump_p (insn, NULL, &table))
- {
- rtx vec_pat = PATTERN (table);
- int i, diff_p = GET_CODE (vec_pat) == ADDR_DIFF_VEC;
-
- for (i = 0; i < XVECLEN (vec_pat, diff_p); i++)
- {
- rtx label = XEXP (XVECEXP (vec_pat, diff_p, i), 0);
-
- if (s390_find_pool (pool_list, label)
- != s390_find_pool (pool_list, insn))
- bitmap_set_bit (far_labels, CODE_LABEL_NUMBER (label));
- }
}
- }
+ }
}
/* Insert base register reload insns before every pool. */
@@ -7363,7 +7375,7 @@ find_unused_clobbered_reg (void)
static void
s390_reg_clobbered_rtx (rtx setreg, const_rtx set_insn ATTRIBUTE_UNUSED, void *data)
{
- int *regs_ever_clobbered = (int *)data;
+ char *regs_ever_clobbered = (char *)data;
unsigned int i, regno;
enum machine_mode mode = GET_MODE (setreg);
@@ -7391,13 +7403,13 @@ s390_reg_clobbered_rtx (rtx setreg, const_rtx set_insn ATTRIBUTE_UNUSED, void *d
each of those regs. */
static void
-s390_regs_ever_clobbered (int *regs_ever_clobbered)
+s390_regs_ever_clobbered (char regs_ever_clobbered[])
{
basic_block cur_bb;
rtx cur_insn;
unsigned int i;
- memset (regs_ever_clobbered, 0, 32 * sizeof (int));
+ memset (regs_ever_clobbered, 0, 32);
/* For non-leaf functions we have to consider all call clobbered regs to be
clobbered. */
@@ -7424,7 +7436,7 @@ s390_regs_ever_clobbered (int *regs_ever_clobbered)
This flag is also set for the unwinding code in libgcc.
See expand_builtin_unwind_init. For regs_ever_live this is done by
reload. */
- if (cfun->has_nonlocal_label)
+ if (crtl->saves_all_registers)
for (i = 0; i < 32; i++)
if (!call_really_used_regs[i])
regs_ever_clobbered[i] = 1;
@@ -7433,10 +7445,38 @@ s390_regs_ever_clobbered (int *regs_ever_clobbered)
{
FOR_BB_INSNS (cur_bb, cur_insn)
{
- if (INSN_P (cur_insn))
- note_stores (PATTERN (cur_insn),
- s390_reg_clobbered_rtx,
- regs_ever_clobbered);
+ rtx pat;
+
+ if (!INSN_P (cur_insn))
+ continue;
+
+ pat = PATTERN (cur_insn);
+
+ /* Ignore GPR restore insns. */
+ if (epilogue_completed && RTX_FRAME_RELATED_P (cur_insn))
+ {
+ if (GET_CODE (pat) == SET
+ && GENERAL_REG_P (SET_DEST (pat)))
+ {
+ /* lgdr */
+ if (GET_MODE (SET_SRC (pat)) == DImode
+ && FP_REG_P (SET_SRC (pat)))
+ continue;
+
+ /* l / lg */
+ if (GET_CODE (SET_SRC (pat)) == MEM)
+ continue;
+ }
+
+ /* lm / lmg */
+ if (GET_CODE (pat) == PARALLEL
+ && load_multiple_operation (pat, VOIDmode))
+ continue;
+ }
+
+ note_stores (pat,
+ s390_reg_clobbered_rtx,
+ regs_ever_clobbered);
}
}
}
@@ -7486,179 +7526,247 @@ s390_frame_area (int *area_bottom, int *area_top)
*area_bottom = b;
*area_top = t;
}
-
-/* Fill cfun->machine with info about register usage of current function.
- Return in CLOBBERED_REGS which GPRs are currently considered set. */
+/* Update gpr_save_slots in the frame layout trying to make use of
+ FPRs as GPR save slots.
+ This is a helper routine of s390_register_info. */
static void
-s390_register_info (int clobbered_regs[])
+s390_register_info_gprtofpr ()
{
+ int save_reg_slot = FPR0_REGNUM;
int i, j;
- /* Find first and last gpr to be saved. We trust regs_ever_live
- data, except that we don't save and restore global registers.
-
- Also, all registers with special meaning to the compiler need
- to be handled extra. */
-
- s390_regs_ever_clobbered (clobbered_regs);
+ if (!TARGET_Z10 || !TARGET_HARD_FLOAT || !crtl->is_leaf)
+ return;
- /* fprs 8 - 15 are call saved for 64 Bit ABI. */
- if (!epilogue_completed)
+ for (i = 15; i >= 6; i--)
{
- cfun_frame_layout.fpr_bitmap = 0;
- cfun_frame_layout.high_fprs = 0;
- if (TARGET_64BIT)
- for (i = FPR8_REGNUM; i <= FPR15_REGNUM; i++)
- /* During reload we have to use the df_regs_ever_live infos
- since reload is marking FPRs used as spill slots there as
- live before actually making the code changes. Without
- this we fail during elimination offset verification. */
- if ((clobbered_regs[i]
- || (df_regs_ever_live_p (i)
- && (lra_in_progress
- || reload_in_progress
- || crtl->saves_all_registers)))
- && !global_regs[i])
- {
- cfun_set_fpr_save (i);
- cfun_frame_layout.high_fprs++;
- }
+ if (cfun_gpr_save_slot (i) == 0)
+ continue;
+
+ /* Advance to the next FP register which can be used as a
+ GPR save slot. */
+ while ((!call_really_used_regs[save_reg_slot]
+ || df_regs_ever_live_p (save_reg_slot)
+ || cfun_fpr_save_p (save_reg_slot))
+ && FP_REGNO_P (save_reg_slot))
+ save_reg_slot++;
+ if (!FP_REGNO_P (save_reg_slot))
+ {
+ /* We only want to use ldgr/lgdr if we can get rid of
+ stm/lm entirely. So undo the gpr slot allocation in
+ case we ran out of FPR save slots. */
+ for (j = 6; j <= 15; j++)
+ if (FP_REGNO_P (cfun_gpr_save_slot (j)))
+ cfun_gpr_save_slot (j) = -1;
+ break;
+ }
+ cfun_gpr_save_slot (i) = save_reg_slot++;
}
+}
- for (i = 0; i < 16; i++)
- clobbered_regs[i] = clobbered_regs[i] && !global_regs[i] && !fixed_regs[i];
+/* Set the bits in fpr_bitmap for FPRs which need to be saved due to
+ stdarg.
+ This is a helper routine for s390_register_info. */
- if (frame_pointer_needed)
- clobbered_regs[HARD_FRAME_POINTER_REGNUM] = 1;
+static void
+s390_register_info_stdarg_fpr ()
+{
+ int i;
+ int min_fpr;
+ int max_fpr;
+
+ /* Save the FP argument regs for stdarg. f0, f2 for 31 bit and
+ f0-f4 for 64 bit. */
+ if (!cfun->stdarg
+ || !TARGET_HARD_FLOAT
+ || !cfun->va_list_fpr_size
+ || crtl->args.info.fprs >= FP_ARG_NUM_REG)
+ return;
+
+ min_fpr = crtl->args.info.fprs;
+ max_fpr = min_fpr + cfun->va_list_fpr_size;
+ if (max_fpr > FP_ARG_NUM_REG)
+ max_fpr = FP_ARG_NUM_REG;
+
+ for (i = min_fpr; i < max_fpr; i++)
+ cfun_set_fpr_save (i + FPR0_REGNUM);
+}
+
+/* Reserve the GPR save slots for GPRs which need to be saved due to
+ stdarg.
+ This is a helper routine for s390_register_info. */
+
+static void
+s390_register_info_stdarg_gpr ()
+{
+ int i;
+ int min_gpr;
+ int max_gpr;
+
+ if (!cfun->stdarg
+ || !cfun->va_list_gpr_size
+ || crtl->args.info.gprs >= GP_ARG_NUM_REG)
+ return;
+
+ min_gpr = crtl->args.info.gprs;
+ max_gpr = min_gpr + cfun->va_list_gpr_size;
+ if (max_gpr > GP_ARG_NUM_REG)
+ max_gpr = GP_ARG_NUM_REG;
+
+ for (i = min_gpr; i < max_gpr; i++)
+ cfun_gpr_save_slot (2 + i) = -1;
+}
+
+/* The GPR and FPR save slots in cfun->machine->frame_layout are set
+ for registers which need to be saved in function prologue.
+ This function can be used until the insns emitted for save/restore
+ of the regs are visible in the RTL stream. */
+
+static void
+s390_register_info ()
+{
+ int i, j;
+ char clobbered_regs[32];
+
+ gcc_assert (!epilogue_completed);
+
+ if (reload_completed)
+ /* After reload we rely on our own routine to determine which
+ registers need saving. */
+ s390_regs_ever_clobbered (clobbered_regs);
+ else
+ /* During reload we use regs_ever_live as a base since reload
+ does changes in there which we otherwise would not be aware
+ of. */
+ for (i = 0; i < 32; i++)
+ clobbered_regs[i] = df_regs_ever_live_p (i);
+
+ for (i = 0; i < 32; i++)
+ clobbered_regs[i] = clobbered_regs[i] && !global_regs[i];
+
+ /* Mark the call-saved FPRs which need to be saved.
+ This needs to be done before checking the special GPRs since the
+ stack pointer usage depends on whether high FPRs have to be saved
+ or not. */
+ cfun_frame_layout.fpr_bitmap = 0;
+ cfun_frame_layout.high_fprs = 0;
+ for (i = FPR0_REGNUM; i <= FPR15_REGNUM; i++)
+ if (clobbered_regs[i] && !call_really_used_regs[i])
+ {
+ cfun_set_fpr_save (i);
+ if (i >= FPR8_REGNUM)
+ cfun_frame_layout.high_fprs++;
+ }
if (flag_pic)
clobbered_regs[PIC_OFFSET_TABLE_REGNUM]
- |= df_regs_ever_live_p (PIC_OFFSET_TABLE_REGNUM);
+ |= !!df_regs_ever_live_p (PIC_OFFSET_TABLE_REGNUM);
clobbered_regs[BASE_REGNUM]
|= (cfun->machine->base_reg
- && REGNO (cfun->machine->base_reg) == BASE_REGNUM);
+ && REGNO (cfun->machine->base_reg) == BASE_REGNUM);
+
+ clobbered_regs[HARD_FRAME_POINTER_REGNUM]
+ |= !!frame_pointer_needed;
+ /* On pre z900 machines this might take until machine dependent
+ reorg to decide.
+ save_return_addr_p will only be set on non-zarch machines so
+ there is no risk that r14 goes into an FPR instead of a stack
+ slot. */
clobbered_regs[RETURN_REGNUM]
|= (!crtl->is_leaf
|| TARGET_TPF_PROFILING
|| cfun->machine->split_branches_pending_p
|| cfun_frame_layout.save_return_addr_p
- || crtl->calls_eh_return
- || cfun->stdarg);
+ || crtl->calls_eh_return);
clobbered_regs[STACK_POINTER_REGNUM]
|= (!crtl->is_leaf
|| TARGET_TPF_PROFILING
|| cfun_save_high_fprs_p
|| get_frame_size () > 0
- || cfun->calls_alloca
- || cfun->stdarg);
+ || (reload_completed && cfun_frame_layout.frame_size > 0)
+ || cfun->calls_alloca);
+
+ memset (cfun_frame_layout.gpr_save_slots, 0, 16);
for (i = 6; i < 16; i++)
- if (df_regs_ever_live_p (i) || clobbered_regs[i])
- break;
- for (j = 15; j > i; j--)
- if (df_regs_ever_live_p (j) || clobbered_regs[j])
- break;
+ if (clobbered_regs[i])
+ cfun_gpr_save_slot (i) = -1;
- if (i == 16)
- {
- /* Nothing to save/restore. */
- cfun_frame_layout.first_save_gpr_slot = -1;
- cfun_frame_layout.last_save_gpr_slot = -1;
- cfun_frame_layout.first_save_gpr = -1;
- cfun_frame_layout.first_restore_gpr = -1;
- cfun_frame_layout.last_save_gpr = -1;
- cfun_frame_layout.last_restore_gpr = -1;
- }
- else
- {
- /* Save slots for gprs from i to j. */
- cfun_frame_layout.first_save_gpr_slot = i;
- cfun_frame_layout.last_save_gpr_slot = j;
+ s390_register_info_stdarg_fpr ();
+ s390_register_info_gprtofpr ();
- for (i = cfun_frame_layout.first_save_gpr_slot;
- i < cfun_frame_layout.last_save_gpr_slot + 1;
- i++)
- if (clobbered_regs[i])
- break;
+ /* First find the range of GPRs to be restored. Vararg regs don't
+ need to be restored so we do it before assigning slots to the
+ vararg GPRs. */
+ for (i = 0; i < 16 && cfun_gpr_save_slot (i) != -1; i++);
+ for (j = 15; j > i && cfun_gpr_save_slot (j) != -1; j--);
+ cfun_frame_layout.first_restore_gpr = (i == 16) ? -1 : i;
+ cfun_frame_layout.last_restore_gpr = (i == 16) ? -1 : j;
- for (j = cfun_frame_layout.last_save_gpr_slot; j > i; j--)
- if (clobbered_regs[j])
- break;
+ /* stdarg functions might need to save GPRs 2 to 6. This might
+ override the GPR->FPR save decision made above for r6 since
+ vararg regs must go to the stack. */
+ s390_register_info_stdarg_gpr ();
- if (i == cfun_frame_layout.last_save_gpr_slot + 1)
- {
- /* Nothing to save/restore. */
- cfun_frame_layout.first_save_gpr = -1;
- cfun_frame_layout.first_restore_gpr = -1;
- cfun_frame_layout.last_save_gpr = -1;
- cfun_frame_layout.last_restore_gpr = -1;
- }
- else
- {
- /* Save / Restore from gpr i to j. */
- cfun_frame_layout.first_save_gpr = i;
- cfun_frame_layout.first_restore_gpr = i;
- cfun_frame_layout.last_save_gpr = j;
- cfun_frame_layout.last_restore_gpr = j;
- }
- }
+ /* Now the range of GPRs which need saving. */
+ for (i = 0; i < 16 && cfun_gpr_save_slot (i) != -1; i++);
+ for (j = 15; j > i && cfun_gpr_save_slot (j) != -1; j--);
+ cfun_frame_layout.first_save_gpr = (i == 16) ? -1 : i;
+ cfun_frame_layout.last_save_gpr = (i == 16) ? -1 : j;
+}
- if (cfun->stdarg)
- {
- /* Varargs functions need to save gprs 2 to 6. */
- if (cfun->va_list_gpr_size
- && crtl->args.info.gprs < GP_ARG_NUM_REG)
- {
- int min_gpr = crtl->args.info.gprs;
- int max_gpr = min_gpr + cfun->va_list_gpr_size;
- if (max_gpr > GP_ARG_NUM_REG)
- max_gpr = GP_ARG_NUM_REG;
+/* This function is called by s390_optimize_prologue in order to get
+ rid of unnecessary GPR save/restore instructions. The register info
+ for the GPRs is re-computed and the ranges are re-calculated. */
- if (cfun_frame_layout.first_save_gpr == -1
- || cfun_frame_layout.first_save_gpr > 2 + min_gpr)
- {
- cfun_frame_layout.first_save_gpr = 2 + min_gpr;
- cfun_frame_layout.first_save_gpr_slot = 2 + min_gpr;
- }
+static void
+s390_optimize_register_info ()
+{
+ char clobbered_regs[32];
+ int i, j;
- if (cfun_frame_layout.last_save_gpr == -1
- || cfun_frame_layout.last_save_gpr < 2 + max_gpr - 1)
- {
- cfun_frame_layout.last_save_gpr = 2 + max_gpr - 1;
- cfun_frame_layout.last_save_gpr_slot = 2 + max_gpr - 1;
- }
- }
+ gcc_assert (epilogue_completed);
+ gcc_assert (!cfun->machine->split_branches_pending_p);
- /* Mark f0, f2 for 31 bit and f0-f4 for 64 bit to be saved. */
- if (TARGET_HARD_FLOAT && cfun->va_list_fpr_size
- && crtl->args.info.fprs < FP_ARG_NUM_REG)
- {
- int min_fpr = crtl->args.info.fprs;
- int max_fpr = min_fpr + cfun->va_list_fpr_size;
- if (max_fpr > FP_ARG_NUM_REG)
- max_fpr = FP_ARG_NUM_REG;
+ s390_regs_ever_clobbered (clobbered_regs);
- /* ??? This is currently required to ensure proper location
- of the fpr save slots within the va_list save area. */
- if (TARGET_PACKED_STACK)
- min_fpr = 0;
+ for (i = 0; i < 32; i++)
+ clobbered_regs[i] = clobbered_regs[i] && !global_regs[i];
- for (i = min_fpr; i < max_fpr; i++)
- cfun_set_fpr_save (i + FPR0_REGNUM);
- }
- }
+ /* There is still special treatment needed for cases invisible to
+ s390_regs_ever_clobbered. */
+ clobbered_regs[RETURN_REGNUM]
+ |= (TARGET_TPF_PROFILING
+ /* When expanding builtin_return_addr in ESA mode we do not
+ know whether r14 will later be needed as scratch reg when
+ doing branch splitting. So the builtin always accesses the
+ r14 save slot and we need to stick to the save/restore
+ decision for r14 even if it turns out that it didn't get
+ clobbered. */
+ || cfun_frame_layout.save_return_addr_p
+ || crtl->calls_eh_return);
- if (!TARGET_64BIT)
- {
- if (df_regs_ever_live_p (FPR4_REGNUM) && !global_regs[FPR4_REGNUM])
- cfun_set_fpr_save (FPR4_REGNUM);
- if (df_regs_ever_live_p (FPR6_REGNUM) && !global_regs[FPR6_REGNUM])
- cfun_set_fpr_save (FPR6_REGNUM);
- }
+ memset (cfun_frame_layout.gpr_save_slots, 0, 6);
+
+ for (i = 6; i < 16; i++)
+ if (!clobbered_regs[i])
+ cfun_gpr_save_slot (i) = 0;
+
+ for (i = 0; i < 16 && cfun_gpr_save_slot (i) != -1; i++);
+ for (j = 15; j > i && cfun_gpr_save_slot (j) != -1; j--);
+ cfun_frame_layout.first_restore_gpr = (i == 16) ? -1 : i;
+ cfun_frame_layout.last_restore_gpr = (i == 16) ? -1 : j;
+
+ s390_register_info_stdarg_gpr ();
+
+ for (i = 0; i < 16 && cfun_gpr_save_slot (i) != -1; i++);
+ for (j = 15; j > i && cfun_gpr_save_slot (j) != -1; j--);
+ cfun_frame_layout.first_save_gpr = (i == 16) ? -1 : i;
+ cfun_frame_layout.last_save_gpr = (i == 16) ? -1 : j;
}
/* Fill cfun->machine with info about frame of current function. */
@@ -7666,7 +7774,23 @@ s390_register_info (int clobbered_regs[])
static void
s390_frame_info (void)
{
- int i;
+ HOST_WIDE_INT lowest_offset;
+
+ cfun_frame_layout.first_save_gpr_slot = cfun_frame_layout.first_save_gpr;
+ cfun_frame_layout.last_save_gpr_slot = cfun_frame_layout.last_save_gpr;
+
+ /* The va_arg builtin uses a constant distance of 16 *
+ UNITS_PER_LONG (r0-r15) to reach the FPRs from the reg_save_area
+ pointer. So even if we are going to save the stack pointer in an
+ FPR we need the stack space in order to keep the offsets
+ correct. */
+ if (cfun->stdarg && cfun_save_arg_fprs_p)
+ {
+ cfun_frame_layout.last_save_gpr_slot = STACK_POINTER_REGNUM;
+
+ if (cfun_frame_layout.first_save_gpr_slot == -1)
+ cfun_frame_layout.first_save_gpr_slot = STACK_POINTER_REGNUM;
+ }
cfun_frame_layout.frame_size = get_frame_size ();
if (!TARGET_64BIT && cfun_frame_layout.frame_size > 0x7fff0000)
@@ -7674,6 +7798,7 @@ s390_frame_info (void)
if (!TARGET_PACKED_STACK)
{
+ /* Fixed stack layout. */
cfun_frame_layout.backchain_offset = 0;
cfun_frame_layout.f0_offset = 16 * UNITS_PER_LONG;
cfun_frame_layout.f4_offset = cfun_frame_layout.f0_offset + 2 * 8;
@@ -7681,99 +7806,89 @@ s390_frame_info (void)
cfun_frame_layout.gprs_offset = (cfun_frame_layout.first_save_gpr_slot
* UNITS_PER_LONG);
}
- else if (TARGET_BACKCHAIN) /* kernel stack layout */
+ else if (TARGET_BACKCHAIN)
{
+ /* Kernel stack layout - packed stack, backchain, no float */
+ gcc_assert (TARGET_SOFT_FLOAT);
cfun_frame_layout.backchain_offset = (STACK_POINTER_OFFSET
- UNITS_PER_LONG);
- cfun_frame_layout.gprs_offset
- = (cfun_frame_layout.backchain_offset
- - (STACK_POINTER_REGNUM - cfun_frame_layout.first_save_gpr_slot + 1)
- * UNITS_PER_LONG);
- if (TARGET_64BIT)
- {
- cfun_frame_layout.f4_offset
- = (cfun_frame_layout.gprs_offset
- - 8 * (cfun_fpr_save_p (FPR4_REGNUM)
- + cfun_fpr_save_p (FPR6_REGNUM)));
+ /* The distance between the backchain and the return address
+ save slot must not change. So we always need a slot for the
+ stack pointer which resides in between. */
+ cfun_frame_layout.last_save_gpr_slot = STACK_POINTER_REGNUM;
- cfun_frame_layout.f0_offset
- = (cfun_frame_layout.f4_offset
- - 8 * (cfun_fpr_save_p (FPR0_REGNUM)
- + cfun_fpr_save_p (FPR2_REGNUM)));
- }
- else
- {
- /* On 31 bit we have to care about alignment of the
- floating point regs to provide fastest access. */
- cfun_frame_layout.f0_offset
- = ((cfun_frame_layout.gprs_offset
- & ~(STACK_BOUNDARY / BITS_PER_UNIT - 1))
- - 8 * (cfun_fpr_save_p (FPR0_REGNUM)
- + cfun_fpr_save_p (FPR2_REGNUM)));
+ cfun_frame_layout.gprs_offset
+ = cfun_frame_layout.backchain_offset - cfun_gprs_save_area_size;
- cfun_frame_layout.f4_offset
- = (cfun_frame_layout.f0_offset
- - 8 * (cfun_fpr_save_p (FPR4_REGNUM)
- + cfun_fpr_save_p (FPR6_REGNUM)));
- }
+ /* FPRs will not be saved. Nevertheless pick sane values to
+ keep area calculations valid. */
+ cfun_frame_layout.f0_offset =
+ cfun_frame_layout.f4_offset =
+ cfun_frame_layout.f8_offset = cfun_frame_layout.gprs_offset;
}
- else /* no backchain */
+ else
{
- cfun_frame_layout.f4_offset
- = (STACK_POINTER_OFFSET
- - 8 * (cfun_fpr_save_p (FPR4_REGNUM)
- + cfun_fpr_save_p (FPR6_REGNUM)));
+ int num_fprs;
+
+ /* Packed stack layout without backchain. */
+
+ /* With stdarg FPRs need their dedicated slots. */
+ num_fprs = (TARGET_64BIT && cfun->stdarg ? 2
+ : (cfun_fpr_save_p (FPR4_REGNUM) +
+ cfun_fpr_save_p (FPR6_REGNUM)));
+ cfun_frame_layout.f4_offset = STACK_POINTER_OFFSET - 8 * num_fprs;
- cfun_frame_layout.f0_offset
- = (cfun_frame_layout.f4_offset
- - 8 * (cfun_fpr_save_p (FPR0_REGNUM)
- + cfun_fpr_save_p (FPR2_REGNUM)));
+ num_fprs = (cfun->stdarg ? 2
+ : (cfun_fpr_save_p (FPR0_REGNUM)
+ + cfun_fpr_save_p (FPR2_REGNUM)));
+ cfun_frame_layout.f0_offset = cfun_frame_layout.f4_offset - 8 * num_fprs;
cfun_frame_layout.gprs_offset
= cfun_frame_layout.f0_offset - cfun_gprs_save_area_size;
+
+ cfun_frame_layout.f8_offset = (cfun_frame_layout.gprs_offset
+ - cfun_frame_layout.high_fprs * 8);
}
+ if (cfun_save_high_fprs_p)
+ cfun_frame_layout.frame_size += cfun_frame_layout.high_fprs * 8;
+
+ if (!crtl->is_leaf)
+ cfun_frame_layout.frame_size += crtl->outgoing_args_size;
+
+ /* In the following cases we have to allocate a STACK_POINTER_OFFSET
+ sized area at the bottom of the stack. This is required also for
+ leaf functions. When GCC generates a local stack reference it
+ will always add STACK_POINTER_OFFSET to all these references. */
if (crtl->is_leaf
&& !TARGET_TPF_PROFILING
&& cfun_frame_layout.frame_size == 0
- && !cfun_save_high_fprs_p
- && !cfun->calls_alloca
- && !cfun->stdarg)
+ && !cfun->calls_alloca)
return;
- if (!TARGET_PACKED_STACK)
- cfun_frame_layout.frame_size += (STACK_POINTER_OFFSET
- + crtl->outgoing_args_size
- + cfun_frame_layout.high_fprs * 8);
- else
- {
- if (TARGET_BACKCHAIN)
- cfun_frame_layout.frame_size += UNITS_PER_LONG;
-
- /* No alignment trouble here because f8-f15 are only saved under
- 64 bit. */
- cfun_frame_layout.f8_offset = (MIN (MIN (cfun_frame_layout.f0_offset,
- cfun_frame_layout.f4_offset),
- cfun_frame_layout.gprs_offset)
- - cfun_frame_layout.high_fprs * 8);
+ /* Calculate the number of bytes we have used in our own register
+ save area. With the packed stack layout we can re-use the
+ remaining bytes for normal stack elements. */
- cfun_frame_layout.frame_size += cfun_frame_layout.high_fprs * 8;
-
- for (i = FPR0_REGNUM; i <= FPR7_REGNUM; i++)
- if (cfun_fpr_save_p (i))
- cfun_frame_layout.frame_size += 8;
+ if (TARGET_PACKED_STACK)
+ lowest_offset = MIN (MIN (cfun_frame_layout.f0_offset,
+ cfun_frame_layout.f4_offset),
+ cfun_frame_layout.gprs_offset);
+ else
+ lowest_offset = 0;
- cfun_frame_layout.frame_size += cfun_gprs_save_area_size;
+ if (TARGET_BACKCHAIN)
+ lowest_offset = MIN (lowest_offset, cfun_frame_layout.backchain_offset);
- /* If under 31 bit an odd number of gprs has to be saved we have to adjust
- the frame size to sustain 8 byte alignment of stack frames. */
- cfun_frame_layout.frame_size = ((cfun_frame_layout.frame_size +
- STACK_BOUNDARY / BITS_PER_UNIT - 1)
- & ~(STACK_BOUNDARY / BITS_PER_UNIT - 1));
+ cfun_frame_layout.frame_size += STACK_POINTER_OFFSET - lowest_offset;
- cfun_frame_layout.frame_size += crtl->outgoing_args_size;
- }
+ /* If under 31 bit an odd number of gprs has to be saved we have to
+ adjust the frame size to sustain 8 byte alignment of stack
+ frames. */
+ cfun_frame_layout.frame_size = ((cfun_frame_layout.frame_size +
+ STACK_BOUNDARY / BITS_PER_UNIT - 1)
+ & ~(STACK_BOUNDARY / BITS_PER_UNIT - 1));
}
/* Generate frame layout. Fills in register and frame data for the current
@@ -7785,7 +7900,8 @@ s390_init_frame_layout (void)
{
HOST_WIDE_INT frame_size;
int base_used;
- int clobbered_regs[32];
+
+ gcc_assert (!reload_completed);
/* On S/390 machines, we may need to perform branch splitting, which
will require both base and return address register. We have no
@@ -7814,7 +7930,7 @@ s390_init_frame_layout (void)
else
cfun->machine->base_reg = gen_rtx_REG (Pmode, BASE_REGNUM);
- s390_register_info (clobbered_regs);
+ s390_register_info ();
s390_frame_info ();
}
while (frame_size != cfun_frame_layout.frame_size);
@@ -7971,29 +8087,6 @@ s390_optimize_nonescaping_tx (void)
return;
}
-/* Update frame layout. Recompute actual register save data based on
- current info and update regs_ever_live for the special registers.
- May be called multiple times, but may never cause *more* registers
- to be saved than s390_init_frame_layout allocated room for. */
-
-static void
-s390_update_frame_layout (void)
-{
- int clobbered_regs[32];
-
- s390_register_info (clobbered_regs);
-
- df_set_regs_ever_live (BASE_REGNUM,
- clobbered_regs[BASE_REGNUM] ? true : false);
- df_set_regs_ever_live (RETURN_REGNUM,
- clobbered_regs[RETURN_REGNUM] ? true : false);
- df_set_regs_ever_live (STACK_POINTER_REGNUM,
- clobbered_regs[STACK_POINTER_REGNUM] ? true : false);
-
- if (cfun->machine->base_reg)
- df_set_regs_ever_live (REGNO (cfun->machine->base_reg), true);
-}
-
/* Return true if it is legal to put a value with MODE into REGNO. */
bool
@@ -8054,6 +8147,31 @@ s390_hard_regno_rename_ok (unsigned int old_reg, unsigned int new_reg)
|| REGNO (cfun->machine->base_reg) == new_reg)
return false;
+ /* Prevent regrename from using call-saved regs which haven't
+ actually been saved. This is necessary since regrename assumes
+ the backend save/restore decisions are based on
+ df_regs_ever_live. Since we have our own routine we have to tell
+ regrename manually about it. */
+ if (GENERAL_REGNO_P (new_reg)
+ && !call_really_used_regs[new_reg]
+ && cfun_gpr_save_slot (new_reg) == 0)
+ return false;
+
+ return true;
+}
+
+/* Return nonzero if register REGNO can be used as a scratch register
+ in peephole2. */
+
+static bool
+s390_hard_regno_scratch_ok (unsigned int regno)
+{
+ /* See s390_hard_regno_rename_ok. */
+ if (GENERAL_REGNO_P (regno)
+ && !call_really_used_regs[regno]
+ && cfun_gpr_save_slot (regno) == 0)
+ return false;
+
return true;
}
@@ -8133,7 +8251,6 @@ HOST_WIDE_INT
s390_initial_elimination_offset (int from, int to)
{
HOST_WIDE_INT offset;
- int index;
/* ??? Why are we called for non-eliminable pairs? */
if (!s390_can_eliminate (from, to))
@@ -8154,10 +8271,26 @@ s390_initial_elimination_offset (int from, int to)
case RETURN_ADDRESS_POINTER_REGNUM:
s390_init_frame_layout ();
- index = RETURN_REGNUM - cfun_frame_layout.first_save_gpr_slot;
- gcc_assert (index >= 0);
- offset = cfun_frame_layout.frame_size + cfun_frame_layout.gprs_offset;
- offset += index * UNITS_PER_LONG;
+
+ if (cfun_frame_layout.first_save_gpr_slot == -1)
+ {
+ /* If it turns out that for stdarg nothing went into the reg
+ save area we also do not need the return address
+ pointer. */
+ if (cfun->stdarg && !cfun_save_arg_fprs_p)
+ return 0;
+
+ gcc_unreachable ();
+ }
+
+ /* In order to make the following work it is not necessary for
+ r14 to have a save slot. It is sufficient if one other GPR
+ got one. Since the GPRs are always stored without gaps we
+ are able to calculate where the r14 save slot would
+ reside. */
+ offset = (cfun_frame_layout.frame_size + cfun_frame_layout.gprs_offset +
+ (RETURN_REGNUM - cfun_frame_layout.first_save_gpr_slot) *
+ UNITS_PER_LONG);
break;
case BASE_REGNUM:
@@ -8295,6 +8428,23 @@ save_gprs (rtx base, int offset, int first, int last)
addr = plus_constant (Pmode, base,
offset + (start - first) * UNITS_PER_LONG);
+
+ if (start == last)
+ {
+ if (TARGET_64BIT)
+ note = gen_movdi (gen_rtx_MEM (Pmode, addr),
+ gen_rtx_REG (Pmode, start));
+ else
+ note = gen_movsi (gen_rtx_MEM (Pmode, addr),
+ gen_rtx_REG (Pmode, start));
+ note = PATTERN (note);
+
+ add_reg_note (insn, REG_FRAME_RELATED_EXPR, note);
+ RTX_FRAME_RELATED_P (insn) = 1;
+
+ return insn;
+ }
+
note = gen_store_multiple (gen_rtx_MEM (Pmode, addr),
gen_rtx_REG (Pmode, start),
GEN_INT (last - start + 1));
@@ -8335,12 +8485,14 @@ restore_gprs (rtx base, int offset, int first, int last)
else
insn = gen_movsi (gen_rtx_REG (Pmode, first), addr);
+ RTX_FRAME_RELATED_P (insn) = 1;
return insn;
}
insn = gen_load_multiple (gen_rtx_REG (Pmode, first),
addr,
GEN_INT (last - first + 1));
+ RTX_FRAME_RELATED_P (insn) = 1;
return insn;
}
@@ -8405,6 +8557,56 @@ s390_emit_stack_tie (void)
emit_insn (gen_stack_tie (mem));
}
+/* Copy GPRS into FPR save slots. */
+
+static void
+s390_save_gprs_to_fprs (void)
+{
+ int i;
+
+ if (!TARGET_Z10 || !TARGET_HARD_FLOAT || !crtl->is_leaf)
+ return;
+
+ for (i = 6; i < 16; i++)
+ {
+ if (FP_REGNO_P (cfun_gpr_save_slot (i)))
+ {
+ rtx insn =
+ emit_move_insn (gen_rtx_REG (DImode, cfun_gpr_save_slot (i)),
+ gen_rtx_REG (DImode, i));
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+ }
+}
+
+/* Restore GPRs from FPR save slots. */
+
+static void
+s390_restore_gprs_from_fprs (void)
+{
+ int i;
+
+ if (!TARGET_Z10 || !TARGET_HARD_FLOAT || !crtl->is_leaf)
+ return;
+
+ for (i = 6; i < 16; i++)
+ {
+ if (FP_REGNO_P (cfun_gpr_save_slot (i)))
+ {
+ rtx insn =
+ emit_move_insn (gen_rtx_REG (DImode, i),
+ gen_rtx_REG (DImode, cfun_gpr_save_slot (i)));
+ df_set_regs_ever_live (i, true);
+ /* The frame related flag is only required on the save
+ operations. We nevertheless set it also for the restore
+ in order to recognize these instructions in
+ s390_optimize_prologue. The flag will then be
+ deleted. */
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+ }
+}
+
/* Expand the prologue into a bunch of separate insns. */
void
@@ -8419,8 +8621,8 @@ s390_emit_prologue (void)
/* Try to get rid of the FPR clobbers. */
s390_optimize_nonescaping_tx ();
- /* Complete frame layout. */
- s390_update_frame_layout ();
+ /* Re-compute register info. */
+ s390_register_info ();
/* Annotate all constant pool references to let the scheduler know
they implicitly use the base register. */
@@ -8446,6 +8648,8 @@ s390_emit_prologue (void)
else
temp_reg = gen_rtx_REG (Pmode, 1);
+ s390_save_gprs_to_fprs ();
+
/* Save call saved gprs. */
if (cfun_frame_layout.first_save_gpr != -1)
{
@@ -8473,8 +8677,8 @@ s390_emit_prologue (void)
save_fpr (stack_pointer_rtx, offset, i);
offset += 8;
}
- else if (!TARGET_PACKED_STACK)
- offset += 8;
+ else if (!TARGET_PACKED_STACK || cfun->stdarg)
+ offset += 8;
}
/* Save f4 and f6. */
@@ -8486,12 +8690,12 @@ s390_emit_prologue (void)
insn = save_fpr (stack_pointer_rtx, offset, i);
offset += 8;
- /* If f4 and f6 are call clobbered they are saved due to stdargs and
- therefore are not frame related. */
+ /* If f4 and f6 are call clobbered they are saved due to
+ stdargs and therefore are not frame related. */
if (!call_really_used_regs[i])
RTX_FRAME_RELATED_P (insn) = 1;
}
- else if (!TARGET_PACKED_STACK)
+ else if (!TARGET_PACKED_STACK || call_really_used_regs[i])
offset += 8;
}
@@ -8900,6 +9104,8 @@ s390_emit_epilogue (bool sibcall)
RTX_FRAME_RELATED_P (insn) = 1;
}
+ s390_restore_gprs_from_fprs ();
+
if (! sibcall)
{
@@ -9589,7 +9795,7 @@ s390_expand_tbegin (rtx dest, rtx tdb, rtx retry, bool clobber_fprs_p)
rtx retry_reg = gen_reg_rtx (SImode);
rtx retry_label = NULL_RTX;
rtx jump;
- rtx very_unlikely = GEN_INT (REG_BR_PROB_BASE / 100 - 1);
+ int very_unlikely = REG_BR_PROB_BASE / 100 - 1;
if (retry != NULL_RTX)
{
@@ -9612,7 +9818,7 @@ s390_expand_tbegin (rtx dest, rtx tdb, rtx retry, bool clobber_fprs_p)
JUMP_LABEL (jump) = abort_label;
LABEL_NUSES (abort_label) = 1;
- add_reg_note (jump, REG_BR_PROB, very_unlikely);
+ add_int_reg_note (jump, REG_BR_PROB, very_unlikely);
/* Initialize CC return value. */
emit_move_insn (dest, const0_rtx);
@@ -9632,7 +9838,7 @@ s390_expand_tbegin (rtx dest, rtx tdb, rtx retry, bool clobber_fprs_p)
gen_rtx_REG (CCRAWmode, CC_REGNUM),
gen_rtx_CONST_INT (VOIDmode, CC1 | CC3)));
LABEL_NUSES (leave_label) = 2;
- add_reg_note (jump, REG_BR_PROB, very_unlikely);
+ add_int_reg_note (jump, REG_BR_PROB, very_unlikely);
/* CC2 - transient failure. Perform retry with ppa. */
emit_move_insn (count, retry);
@@ -10561,8 +10767,7 @@ s390_optimize_prologue (void)
rtx insn, new_insn, next_insn;
/* Do a final recompute of the frame-related data. */
-
- s390_update_frame_layout ();
+ s390_optimize_register_info ();
/* If all special registers are in fact used, there's nothing we
can do, so no point in walking the insn list. */
@@ -10580,18 +10785,63 @@ s390_optimize_prologue (void)
{
int first, last, off;
rtx set, base, offset;
+ rtx pat;
next_insn = NEXT_INSN (insn);
- if (! NONJUMP_INSN_P (insn))
+ if (! NONJUMP_INSN_P (insn) || ! RTX_FRAME_RELATED_P (insn))
continue;
- if (GET_CODE (PATTERN (insn)) == PARALLEL
- && store_multiple_operation (PATTERN (insn), VOIDmode))
+ pat = PATTERN (insn);
+
+ /* Remove ldgr/lgdr instructions used for saving and restore
+ GPRs if possible. */
+ if (TARGET_Z10
+ && GET_CODE (pat) == SET
+ && GET_MODE (SET_SRC (pat)) == DImode
+ && REG_P (SET_SRC (pat))
+ && REG_P (SET_DEST (pat)))
+ {
+ int src_regno = REGNO (SET_SRC (pat));
+ int dest_regno = REGNO (SET_DEST (pat));
+ int gpr_regno;
+ int fpr_regno;
+
+ if (!((GENERAL_REGNO_P (src_regno) && FP_REGNO_P (dest_regno))
+ || (FP_REGNO_P (src_regno) && GENERAL_REGNO_P (dest_regno))))
+ continue;
+
+ gpr_regno = GENERAL_REGNO_P (src_regno) ? src_regno : dest_regno;
+ fpr_regno = FP_REGNO_P (src_regno) ? src_regno : dest_regno;
+
+ /* GPR must be call-saved, FPR must be call-clobbered. */
+ if (!call_really_used_regs[fpr_regno]
+ || call_really_used_regs[gpr_regno])
+ continue;
+
+ /* For restores we have to revert the frame related flag
+ since no debug info is supposed to be generated for
+ these. */
+ if (dest_regno == gpr_regno)
+ RTX_FRAME_RELATED_P (insn) = 0;
+
+ /* It must not happen that what we once saved in an FPR now
+ needs a stack slot. */
+ gcc_assert (cfun_gpr_save_slot (gpr_regno) != -1);
+
+ if (cfun_gpr_save_slot (gpr_regno) == 0)
+ {
+ remove_insn (insn);
+ continue;
+ }
+ }
+
+ if (GET_CODE (pat) == PARALLEL
+ && store_multiple_operation (pat, VOIDmode))
{
- set = XVECEXP (PATTERN (insn), 0, 0);
+ set = XVECEXP (pat, 0, 0);
first = REGNO (SET_SRC (set));
- last = first + XVECLEN (PATTERN (insn), 0) - 1;
+ last = first + XVECLEN (pat, 0) - 1;
offset = const0_rtx;
base = eliminate_constant_term (XEXP (SET_DEST (set), 0), &offset);
off = INTVAL (offset);
@@ -10624,14 +10874,11 @@ s390_optimize_prologue (void)
}
if (cfun_frame_layout.first_save_gpr == -1
- && GET_CODE (PATTERN (insn)) == SET
- && GET_CODE (SET_SRC (PATTERN (insn))) == REG
- && (REGNO (SET_SRC (PATTERN (insn))) == BASE_REGNUM
- || (!TARGET_CPU_ZARCH
- && REGNO (SET_SRC (PATTERN (insn))) == RETURN_REGNUM))
- && GET_CODE (SET_DEST (PATTERN (insn))) == MEM)
+ && GET_CODE (pat) == SET
+ && GENERAL_REG_P (SET_SRC (pat))
+ && GET_CODE (SET_DEST (pat)) == MEM)
{
- set = PATTERN (insn);
+ set = pat;
first = REGNO (SET_SRC (set));
offset = const0_rtx;
base = eliminate_constant_term (XEXP (SET_DEST (set), 0), &offset);
@@ -10647,18 +10894,21 @@ s390_optimize_prologue (void)
continue;
}
- if (GET_CODE (PATTERN (insn)) == PARALLEL
- && load_multiple_operation (PATTERN (insn), VOIDmode))
+ if (GET_CODE (pat) == PARALLEL
+ && load_multiple_operation (pat, VOIDmode))
{
- set = XVECEXP (PATTERN (insn), 0, 0);
+ set = XVECEXP (pat, 0, 0);
first = REGNO (SET_DEST (set));
- last = first + XVECLEN (PATTERN (insn), 0) - 1;
+ last = first + XVECLEN (pat, 0) - 1;
offset = const0_rtx;
base = eliminate_constant_term (XEXP (SET_SRC (set), 0), &offset);
off = INTVAL (offset);
if (GET_CODE (base) != REG || off < 0)
continue;
+
+ RTX_FRAME_RELATED_P (insn) = 0;
+
if (cfun_frame_layout.first_restore_gpr != -1
&& (cfun_frame_layout.first_restore_gpr < first
|| cfun_frame_layout.last_restore_gpr > last))
@@ -10676,6 +10926,7 @@ s390_optimize_prologue (void)
- first) * UNITS_PER_LONG,
cfun_frame_layout.first_restore_gpr,
cfun_frame_layout.last_restore_gpr);
+ RTX_FRAME_RELATED_P (new_insn) = 0;
new_insn = emit_insn_before (new_insn, insn);
INSN_ADDRESSES_NEW (new_insn, -1);
}
@@ -10685,14 +10936,11 @@ s390_optimize_prologue (void)
}
if (cfun_frame_layout.first_restore_gpr == -1
- && GET_CODE (PATTERN (insn)) == SET
- && GET_CODE (SET_DEST (PATTERN (insn))) == REG
- && (REGNO (SET_DEST (PATTERN (insn))) == BASE_REGNUM
- || (!TARGET_CPU_ZARCH
- && REGNO (SET_DEST (PATTERN (insn))) == RETURN_REGNUM))
- && GET_CODE (SET_SRC (PATTERN (insn))) == MEM)
+ && GET_CODE (pat) == SET
+ && GENERAL_REG_P (SET_DEST (pat))
+ && GET_CODE (SET_SRC (pat)) == MEM)
{
- set = PATTERN (insn);
+ set = pat;
first = REGNO (SET_DEST (set));
offset = const0_rtx;
base = eliminate_constant_term (XEXP (SET_SRC (set), 0), &offset);
@@ -10700,6 +10948,9 @@ s390_optimize_prologue (void)
if (GET_CODE (base) != REG || off < 0)
continue;
+
+ RTX_FRAME_RELATED_P (insn) = 0;
+
if (REGNO (base) != STACK_POINTER_REGNUM
&& REGNO (base) != HARD_FRAME_POINTER_REGNUM)
continue;
@@ -11638,6 +11889,9 @@ s390_loop_unroll_adjust (unsigned nunroll, struct loop *loop)
#undef TARGET_CANONICALIZE_COMPARISON
#define TARGET_CANONICALIZE_COMPARISON s390_canonicalize_comparison
+#undef TARGET_HARD_REGNO_SCRATCH_OK
+#define TARGET_HARD_REGNO_SCRATCH_OK s390_hard_regno_scratch_ok
+
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-s390.h"
diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
index cf9ef774675..8354e263892 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -8412,19 +8412,15 @@
(define_expand "doloop_end"
[(use (match_operand 0 "" "")) ; loop pseudo
- (use (match_operand 1 "" "")) ; iterations; zero if unknown
- (use (match_operand 2 "" "")) ; max iterations
- (use (match_operand 3 "" "")) ; loop level
- (use (match_operand 4 "" "")) ; label
- (use (match_operand 5 "" ""))] ; flag: 1 if loop entered at top, else 0
+ (use (match_operand 1 "" ""))] ; label
""
{
if (GET_MODE (operands[0]) == SImode && !TARGET_CPU_ZARCH)
- emit_jump_insn (gen_doloop_si31 (operands[4], operands[0], operands[0]));
+ emit_jump_insn (gen_doloop_si31 (operands[1], operands[0], operands[0]));
else if (GET_MODE (operands[0]) == SImode && TARGET_CPU_ZARCH)
- emit_jump_insn (gen_doloop_si64 (operands[4], operands[0], operands[0]));
+ emit_jump_insn (gen_doloop_si64 (operands[1], operands[0], operands[0]));
else if (GET_MODE (operands[0]) == DImode && TARGET_ZARCH)
- emit_jump_insn (gen_doloop_di (operands[4], operands[0], operands[0]));
+ emit_jump_insn (gen_doloop_di (operands[1], operands[0], operands[0]));
else
FAIL;
@@ -9962,8 +9958,8 @@
; Non-constrained transaction begin
(define_expand "tbegin"
- [(match_operand:SI 0 "register_operand" "=d")
- (match_operand:BLK 1 "memory_operand" "=Q")]
+ [(match_operand:SI 0 "register_operand" "")
+ (match_operand:BLK 1 "memory_operand" "")]
"TARGET_HTM"
{
s390_expand_tbegin (operands[0], operands[1], NULL_RTX, true);
@@ -9971,8 +9967,8 @@
})
(define_expand "tbegin_nofloat"
- [(match_operand:SI 0 "register_operand" "=d")
- (match_operand:BLK 1 "memory_operand" "=Q")]
+ [(match_operand:SI 0 "register_operand" "")
+ (match_operand:BLK 1 "memory_operand" "")]
"TARGET_HTM"
{
s390_expand_tbegin (operands[0], operands[1], NULL_RTX, false);
@@ -9980,9 +9976,9 @@
})
(define_expand "tbegin_retry"
- [(match_operand:SI 0 "register_operand" "=d")
- (match_operand:BLK 1 "memory_operand" "=Q")
- (match_operand 2 "const_int_operand")]
+ [(match_operand:SI 0 "register_operand" "")
+ (match_operand:BLK 1 "memory_operand" "")
+ (match_operand:SI 2 "general_operand" "")]
"TARGET_HTM"
{
s390_expand_tbegin (operands[0], operands[1], operands[2], true);
@@ -9990,9 +9986,9 @@
})
(define_expand "tbegin_retry_nofloat"
- [(match_operand:SI 0 "register_operand" "=d")
- (match_operand:BLK 1 "memory_operand" "=Q")
- (match_operand 2 "const_int_operand")]
+ [(match_operand:SI 0 "register_operand" "")
+ (match_operand:BLK 1 "memory_operand" "")
+ (match_operand:SI 2 "general_operand" "")]
"TARGET_HTM"
{
s390_expand_tbegin (operands[0], operands[1], operands[2], false);
@@ -10059,7 +10055,7 @@
(define_expand "tend"
[(set (reg:CCRAW CC_REGNUM)
(unspec_volatile:CCRAW [(const_int 0)] UNSPECV_TEND))
- (set (match_operand:SI 0 "register_operand" "=d")
+ (set (match_operand:SI 0 "register_operand" "")
(unspec:SI [(reg:CCRAW CC_REGNUM)] UNSPEC_CC_TO_INT))]
"TARGET_HTM"
"")
@@ -10074,7 +10070,7 @@
; Transaction abort
(define_expand "tabort"
- [(unspec_volatile [(match_operand 0 "shift_count_or_setmem_operand" "")]
+ [(unspec_volatile [(match_operand:SI 0 "shift_count_or_setmem_operand" "")]
UNSPECV_TABORT)]
"TARGET_HTM && operands != NULL"
{
@@ -10089,7 +10085,7 @@
})
(define_insn "*tabort_1"
- [(unspec_volatile [(match_operand 0 "shift_count_or_setmem_operand" "")]
+ [(unspec_volatile [(match_operand:SI 0 "shift_count_or_setmem_operand" "Y")]
UNSPECV_TABORT)]
"TARGET_HTM && operands != NULL"
"tabort\t%Y0"
@@ -10118,7 +10114,7 @@
(define_expand "tx_assist"
[(set (match_dup 1) (const_int 0))
- (unspec_volatile [(match_operand:SI 0 "register_operand" "d")
+ (unspec_volatile [(match_operand:SI 0 "register_operand" "")
(match_dup 1)
(const_int 1)]
UNSPECV_PPA)]
diff --git a/gcc/config/sh/predicates.md b/gcc/config/sh/predicates.md
index 998ba7300ad..2643481a827 100644
--- a/gcc/config/sh/predicates.md
+++ b/gcc/config/sh/predicates.md
@@ -154,7 +154,7 @@
return (regno != T_REG && regno != PR_REG
&& ! TARGET_REGISTER_P (regno)
- && (regno != FPUL_REG || TARGET_SH4)
+ && regno != FPUL_REG
&& regno != MACH_REG && regno != MACL_REG);
}
/* Allow a no-op sign extension - compare LOAD_EXTEND_OP.
@@ -550,17 +550,36 @@
&& ! (reload_in_progress || reload_completed))
return 0;
- if ((mode == QImode || mode == HImode)
- && mode == GET_MODE (op)
- && (MEM_P (op)
- || (GET_CODE (op) == SUBREG && MEM_P (SUBREG_REG (op)))))
+ if (mode == GET_MODE (op)
+ && (MEM_P (op) || (GET_CODE (op) == SUBREG && MEM_P (SUBREG_REG (op)))))
{
- rtx x = XEXP ((MEM_P (op) ? op : SUBREG_REG (op)), 0);
+ rtx mem_rtx = MEM_P (op) ? op : SUBREG_REG (op);
+ rtx x = XEXP (mem_rtx, 0);
- if (GET_CODE (x) == PLUS
+ if ((mode == QImode || mode == HImode)
+ && GET_CODE (x) == PLUS
&& REG_P (XEXP (x, 0))
&& CONST_INT_P (XEXP (x, 1)))
return sh_legitimate_index_p (mode, XEXP (x, 1), TARGET_SH2A, false);
+
+ /* Allow reg+reg addressing here without validating the register
+ numbers. Usually one of the regs must be R0 or a pseudo reg.
+ In some cases it can happen that arguments from hard regs are
+ propagated directly into address expressions. In this cases reload
+ will have to fix it up later. However, allow this only for native
+ 1, 2 or 4 byte addresses. */
+ if (can_create_pseudo_p () && GET_CODE (x) == PLUS
+ && GET_MODE_SIZE (mode) <= 4
+ && REG_P (XEXP (x, 0)) && REG_P (XEXP (x, 1)))
+ return true;
+
+ /* 'general_operand' does not allow volatile mems during RTL expansion to
+ avoid matching arithmetic that operates on mems, it seems.
+ On SH this leads to redundant sign extensions for QImode or HImode
+ stores. Thus we mimic the behavior but allow volatile mems. */
+ if (memory_address_addr_space_p (GET_MODE (mem_rtx), x,
+ MEM_ADDR_SPACE (mem_rtx)))
+ return true;
}
return general_operand (op, mode);
diff --git a/gcc/config/sh/sh-mem.cc b/gcc/config/sh/sh-mem.cc
new file mode 100644
index 00000000000..729e848586d
--- /dev/null
+++ b/gcc/config/sh/sh-mem.cc
@@ -0,0 +1,551 @@
+/* Helper routines for memory move and comparison insns.
+ Copyright (C) 2013 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 "machmode.h"
+#include "rtl.h"
+#include "tree.h"
+#include "expr.h"
+#include "tm_p.h"
+#include "basic-block.h"
+
+/* Like force_operand, but guarantees that VALUE ends up in TARGET. */
+static void
+force_into (rtx value, rtx target)
+{
+ value = force_operand (value, target);
+ if (! rtx_equal_p (value, target))
+ emit_insn (gen_move_insn (target, value));
+}
+
+/* Emit code to perform a block move. Choose the best method.
+
+ OPERANDS[0] is the destination.
+ OPERANDS[1] is the source.
+ OPERANDS[2] is the size.
+ OPERANDS[3] is the alignment safe to use. */
+bool
+expand_block_move (rtx *operands)
+{
+ int align = INTVAL (operands[3]);
+ int constp = (CONST_INT_P (operands[2]));
+ int bytes = (constp ? INTVAL (operands[2]) : 0);
+
+ if (! constp)
+ return false;
+
+ /* If we could use mov.l to move words and dest is word-aligned, we
+ can use movua.l for loads and still generate a relatively short
+ and efficient sequence. */
+ if (TARGET_SH4A_ARCH && align < 4
+ && MEM_ALIGN (operands[0]) >= 32
+ && can_move_by_pieces (bytes, 32))
+ {
+ rtx dest = copy_rtx (operands[0]);
+ rtx src = copy_rtx (operands[1]);
+ /* We could use different pseudos for each copied word, but
+ since movua can only load into r0, it's kind of
+ pointless. */
+ rtx temp = gen_reg_rtx (SImode);
+ rtx src_addr = copy_addr_to_reg (XEXP (src, 0));
+ int copied = 0;
+
+ while (copied + 4 <= bytes)
+ {
+ rtx to = adjust_address (dest, SImode, copied);
+ rtx from = adjust_automodify_address (src, BLKmode,
+ src_addr, copied);
+
+ set_mem_size (from, 4);
+ emit_insn (gen_movua (temp, from));
+ emit_move_insn (src_addr, plus_constant (Pmode, src_addr, 4));
+ emit_move_insn (to, temp);
+ copied += 4;
+ }
+
+ if (copied < bytes)
+ move_by_pieces (adjust_address (dest, BLKmode, copied),
+ adjust_automodify_address (src, BLKmode,
+ src_addr, copied),
+ bytes - copied, align, 0);
+
+ return true;
+ }
+
+ /* If it isn't a constant number of bytes, or if it doesn't have 4 byte
+ alignment, or if it isn't a multiple of 4 bytes, then fail. */
+ if (align < 4 || (bytes % 4 != 0))
+ return false;
+
+ if (TARGET_HARD_SH4)
+ {
+ if (bytes < 12)
+ return false;
+ else if (bytes == 12)
+ {
+ rtx func_addr_rtx = gen_reg_rtx (Pmode);
+ rtx r4 = gen_rtx_REG (SImode, 4);
+ rtx r5 = gen_rtx_REG (SImode, 5);
+
+ function_symbol (func_addr_rtx, "__movmemSI12_i4", SFUNC_STATIC);
+ force_into (XEXP (operands[0], 0), r4);
+ force_into (XEXP (operands[1], 0), r5);
+ emit_insn (gen_block_move_real_i4 (func_addr_rtx));
+ return true;
+ }
+ else if (! optimize_size)
+ {
+ const char *entry_name;
+ rtx func_addr_rtx = gen_reg_rtx (Pmode);
+ int dwords;
+ rtx r4 = gen_rtx_REG (SImode, 4);
+ rtx r5 = gen_rtx_REG (SImode, 5);
+ rtx r6 = gen_rtx_REG (SImode, 6);
+
+ entry_name = (bytes & 4 ? "__movmem_i4_odd" : "__movmem_i4_even");
+ function_symbol (func_addr_rtx, entry_name, SFUNC_STATIC);
+ force_into (XEXP (operands[0], 0), r4);
+ force_into (XEXP (operands[1], 0), r5);
+
+ dwords = bytes >> 3;
+ emit_insn (gen_move_insn (r6, GEN_INT (dwords - 1)));
+ emit_insn (gen_block_lump_real_i4 (func_addr_rtx));
+ return true;
+ }
+ else
+ return false;
+ }
+ if (bytes < 64)
+ {
+ char entry[30];
+ rtx func_addr_rtx = gen_reg_rtx (Pmode);
+ rtx r4 = gen_rtx_REG (SImode, 4);
+ rtx r5 = gen_rtx_REG (SImode, 5);
+
+ sprintf (entry, "__movmemSI%d", bytes);
+ function_symbol (func_addr_rtx, entry, SFUNC_STATIC);
+ force_into (XEXP (operands[0], 0), r4);
+ force_into (XEXP (operands[1], 0), r5);
+ emit_insn (gen_block_move_real (func_addr_rtx));
+ return true;
+ }
+
+ /* This is the same number of bytes as a memcpy call, but to a different
+ less common function name, so this will occasionally use more space. */
+ if (! optimize_size)
+ {
+ rtx func_addr_rtx = gen_reg_rtx (Pmode);
+ int final_switch, while_loop;
+ rtx r4 = gen_rtx_REG (SImode, 4);
+ rtx r5 = gen_rtx_REG (SImode, 5);
+ rtx r6 = gen_rtx_REG (SImode, 6);
+
+ function_symbol (func_addr_rtx, "__movmem", SFUNC_STATIC);
+ force_into (XEXP (operands[0], 0), r4);
+ force_into (XEXP (operands[1], 0), r5);
+
+ /* r6 controls the size of the move. 16 is decremented from it
+ for each 64 bytes moved. Then the negative bit left over is used
+ as an index into a list of move instructions. e.g., a 72 byte move
+ would be set up with size(r6) = 14, for one iteration through the
+ big while loop, and a switch of -2 for the last part. */
+
+ final_switch = 16 - ((bytes / 4) % 16);
+ while_loop = ((bytes / 4) / 16 - 1) * 16;
+ emit_insn (gen_move_insn (r6, GEN_INT (while_loop + final_switch)));
+ emit_insn (gen_block_lump_real (func_addr_rtx));
+ return true;
+ }
+
+ return false;
+}
+
+static int prob_unlikely = REG_BR_PROB_BASE / 10;
+static int prob_likely = REG_BR_PROB_BASE / 4;
+
+/* Emit code to perform a strcmp.
+
+ OPERANDS[0] is the destination.
+ OPERANDS[1] is the first string.
+ OPERANDS[2] is the second string.
+ OPERANDS[3] is the known alignment. */
+bool
+sh_expand_cmpstr (rtx *operands)
+{
+ rtx addr1 = operands[1];
+ rtx addr2 = operands[2];
+ rtx s1_addr = copy_addr_to_reg (XEXP (addr1, 0));
+ rtx s2_addr = copy_addr_to_reg (XEXP (addr2, 0));
+ rtx tmp0 = gen_reg_rtx (SImode);
+ rtx tmp1 = gen_reg_rtx (SImode);
+ rtx tmp2 = gen_reg_rtx (SImode);
+ rtx tmp3 = gen_reg_rtx (SImode);
+
+ rtx jump;
+ rtx L_return = gen_label_rtx ();
+ rtx L_loop_byte = gen_label_rtx ();
+ rtx L_end_loop_byte = gen_label_rtx ();
+ rtx L_loop_long = gen_label_rtx ();
+ rtx L_end_loop_long = gen_label_rtx ();
+
+ int align = INTVAL (operands[3]);
+
+ emit_move_insn (tmp0, const0_rtx);
+
+ if (align < 4)
+ {
+ emit_insn (gen_iorsi3 (tmp1, s1_addr, s2_addr));
+ emit_insn (gen_tstsi_t (GEN_INT (3), tmp1));
+ jump = emit_jump_insn (gen_branch_false (L_loop_byte));
+ add_int_reg_note (jump, REG_BR_PROB, prob_likely);
+ }
+
+ addr1 = adjust_automodify_address (addr1, SImode, s1_addr, 0);
+ addr2 = adjust_automodify_address (addr2, SImode, s2_addr, 0);
+
+ /* tmp2 is aligned, OK to load. */
+ emit_move_insn (tmp3, addr2);
+ emit_move_insn (s2_addr, plus_constant (Pmode, s2_addr, 4));
+
+ /*start long loop. */
+ emit_label (L_loop_long);
+
+ emit_move_insn (tmp2, tmp3);
+
+ /* tmp1 is aligned, OK to load. */
+ emit_move_insn (tmp1, addr1);
+ emit_move_insn (s1_addr, plus_constant (Pmode, s1_addr, 4));
+
+ /* Is there a 0 byte ? */
+ emit_insn (gen_andsi3 (tmp3, tmp3, tmp1));
+
+ emit_insn (gen_cmpstr_t (tmp0, tmp3));
+ jump = emit_jump_insn (gen_branch_true (L_end_loop_long));
+ add_int_reg_note (jump, REG_BR_PROB, prob_unlikely);
+
+ emit_insn (gen_cmpeqsi_t (tmp1, tmp2));
+
+ /* tmp2 is aligned, OK to load. */
+ emit_move_insn (tmp3, addr2);
+ emit_move_insn (s2_addr, plus_constant (Pmode, s2_addr, 4));
+
+ jump = emit_jump_insn (gen_branch_true (L_loop_long));
+ add_int_reg_note (jump, REG_BR_PROB, prob_likely);
+ /* end loop. */
+
+ /* Fallthu, substract words. */
+ if (TARGET_LITTLE_ENDIAN)
+ {
+ rtx low_1 = gen_lowpart (HImode, tmp1);
+ rtx low_2 = gen_lowpart (HImode, tmp2);
+
+ emit_insn (gen_rotlhi3_8 (low_1, low_1));
+ emit_insn (gen_rotlhi3_8 (low_2, low_2));
+ emit_insn (gen_rotlsi3_16 (tmp1, tmp1));
+ emit_insn (gen_rotlsi3_16 (tmp2, tmp2));
+ emit_insn (gen_rotlhi3_8 (low_1, low_1));
+ emit_insn (gen_rotlhi3_8 (low_2, low_2));
+ }
+
+ jump = emit_jump_insn (gen_jump_compact (L_return));
+ emit_barrier_after (jump);
+
+ emit_label (L_end_loop_long);
+
+ emit_move_insn (s1_addr, plus_constant (Pmode, s1_addr, -4));
+ emit_move_insn (s2_addr, plus_constant (Pmode, s2_addr, -4));
+
+ /* start byte loop. */
+ addr1 = adjust_address (addr1, QImode, 0);
+ addr2 = adjust_address (addr2, QImode, 0);
+
+ emit_label (L_loop_byte);
+
+ emit_insn (gen_extendqisi2 (tmp2, addr2));
+ emit_move_insn (s2_addr, plus_constant (Pmode, s2_addr, 1));
+
+ emit_insn (gen_extendqisi2 (tmp1, addr1));
+ emit_move_insn (s1_addr, plus_constant (Pmode, s1_addr, 1));
+
+ emit_insn (gen_cmpeqsi_t (tmp2, const0_rtx));
+ jump = emit_jump_insn (gen_branch_true (L_end_loop_byte));
+ add_int_reg_note (jump, REG_BR_PROB, prob_unlikely);
+
+ emit_insn (gen_cmpeqsi_t (tmp1, tmp2));
+ if (flag_delayed_branch)
+ emit_insn (gen_zero_extendqisi2 (tmp2, gen_lowpart (QImode, tmp2)));
+ jump = emit_jump_insn (gen_branch_true (L_loop_byte));
+ add_int_reg_note (jump, REG_BR_PROB, prob_likely);
+ /* end loop. */
+
+ emit_label (L_end_loop_byte);
+
+ if (! flag_delayed_branch)
+ emit_insn (gen_zero_extendqisi2 (tmp2, gen_lowpart (QImode, tmp2)));
+ emit_insn (gen_zero_extendqisi2 (tmp1, gen_lowpart (QImode, tmp1)));
+
+ emit_label (L_return);
+
+ emit_insn (gen_subsi3 (operands[0], tmp1, tmp2));
+
+ return true;
+}
+
+/* Emit code to perform a strncmp.
+
+ OPERANDS[0] is the destination.
+ OPERANDS[1] is the first string.
+ OPERANDS[2] is the second string.
+ OPERANDS[3] is the length.
+ OPERANDS[4] is the known alignment. */
+bool
+sh_expand_cmpnstr (rtx *operands)
+{
+ rtx addr1 = operands[1];
+ rtx addr2 = operands[2];
+ rtx s1_addr = copy_addr_to_reg (XEXP (addr1, 0));
+ rtx s2_addr = copy_addr_to_reg (XEXP (addr2, 0));
+ rtx tmp0 = gen_reg_rtx (SImode);
+ rtx tmp1 = gen_reg_rtx (SImode);
+ rtx tmp2 = gen_reg_rtx (SImode);
+
+ rtx jump;
+ rtx L_return = gen_label_rtx ();
+ rtx L_loop_byte = gen_label_rtx ();
+ rtx L_end_loop_byte = gen_label_rtx ();
+
+ rtx len = force_reg (SImode, operands[3]);
+ int constp = (CONST_INT_P (operands[3]));
+ int bytes = (constp ? INTVAL (operands[3]) : 0);
+ int witers = bytes / 4;
+
+ /* We could still loop on a register count. Not found very
+ convincing to optimize yet. */
+ if (! constp)
+ return false;
+
+ if (witers > 1)
+ {
+ rtx L_loop_long = gen_label_rtx ();
+ rtx L_end_loop_long = gen_label_rtx ();
+ rtx tmp3 = gen_reg_rtx (SImode);
+ rtx lenw = gen_reg_rtx (SImode);
+ int align = INTVAL (operands[4]);
+
+ emit_move_insn (tmp0, const0_rtx);
+
+ if (align < 4)
+ {
+ emit_insn (gen_iorsi3 (tmp1, s1_addr, s2_addr));
+ emit_insn (gen_tstsi_t (GEN_INT (3), tmp1));
+ jump = emit_jump_insn (gen_branch_false (L_loop_byte));
+ add_int_reg_note (jump, REG_BR_PROB, prob_likely);
+ }
+
+ addr1 = adjust_automodify_address (addr1, SImode, s1_addr, 0);
+ addr2 = adjust_automodify_address (addr2, SImode, s2_addr, 0);
+
+ /* word count. Do we have iterations ? */
+ emit_insn (gen_lshrsi3 (lenw, len, GEN_INT (2)));
+
+ /*start long loop. */
+ emit_label (L_loop_long);
+
+ /* tmp2 is aligned, OK to load. */
+ emit_move_insn (tmp2, addr2);
+ emit_move_insn (s2_addr, plus_constant (Pmode, s2_addr, 4));
+
+ /* tmp1 is aligned, OK to load. */
+ emit_move_insn (tmp1, addr1);
+ emit_move_insn (s1_addr, plus_constant (Pmode, s1_addr, 4));
+
+ /* Is there a 0 byte ? */
+ emit_insn (gen_andsi3 (tmp3, tmp2, tmp1));
+
+ emit_insn (gen_cmpstr_t (tmp0, tmp3));
+ jump = emit_jump_insn (gen_branch_true (L_end_loop_long));
+ add_int_reg_note (jump, REG_BR_PROB, prob_unlikely);
+
+ emit_insn (gen_cmpeqsi_t (tmp1, tmp2));
+ jump = emit_jump_insn (gen_branch_false (L_end_loop_long));
+ add_int_reg_note (jump, REG_BR_PROB, prob_unlikely);
+
+ if (TARGET_SH2)
+ emit_insn (gen_dect (lenw, lenw));
+ else
+ {
+ emit_insn (gen_addsi3 (lenw, lenw, GEN_INT (-1)));
+ emit_insn (gen_tstsi_t (lenw, lenw));
+ }
+ jump = emit_jump_insn (gen_branch_false (L_loop_long));
+ add_int_reg_note (jump, REG_BR_PROB, prob_likely);
+
+ /* end loop. Reached max iterations. */
+ if (bytes % 4 == 0)
+ {
+ /* Done. */
+ jump = emit_jump_insn (gen_jump_compact (L_return));
+ emit_barrier_after (jump);
+ }
+ else
+ {
+ /* Remaining bytes to read. */
+ emit_move_insn (len, GEN_INT (bytes % 4));
+ jump = emit_jump_insn (gen_jump_compact (L_loop_byte));
+ emit_barrier_after (jump);
+ }
+
+ emit_label (L_end_loop_long);
+
+ /* Remaining bytes to read. */
+ emit_move_insn (len, GEN_INT (4));
+
+ /* Found last word. Restart it byte per byte. */
+ emit_move_insn (s1_addr, plus_constant (Pmode, s1_addr, -4));
+ emit_move_insn (s2_addr, plus_constant (Pmode, s2_addr, -4));
+ }
+
+ addr1 = adjust_address (addr1, QImode, 0);
+ addr2 = adjust_address (addr2, QImode, 0);
+
+ emit_label (L_loop_byte);
+
+ emit_insn (gen_extendqisi2 (tmp2, addr2));
+ emit_move_insn (s2_addr, plus_constant (Pmode, s2_addr, 1));
+
+ emit_insn (gen_extendqisi2 (tmp1, addr1));
+ emit_move_insn (s1_addr, plus_constant (Pmode, s1_addr, 1));
+
+ emit_insn (gen_cmpeqsi_t (tmp2, const0_rtx));
+ jump = emit_jump_insn (gen_branch_true (L_end_loop_byte));
+ add_int_reg_note (jump, REG_BR_PROB, prob_unlikely);
+
+ emit_insn (gen_cmpeqsi_t (tmp1, tmp2));
+ if (flag_delayed_branch)
+ emit_insn (gen_zero_extendqisi2 (tmp2, gen_lowpart (QImode, tmp2)));
+ jump = emit_jump_insn (gen_branch_false (L_end_loop_byte));
+ add_int_reg_note (jump, REG_BR_PROB, prob_unlikely);
+
+ if (TARGET_SH2)
+ emit_insn (gen_dect (len, len));
+ else
+ {
+ emit_insn (gen_addsi3 (len, len, GEN_INT (-1)));
+ emit_insn (gen_tstsi_t (len, len));
+ }
+
+ jump = emit_jump_insn (gen_branch_false (L_loop_byte));
+ add_int_reg_note (jump, REG_BR_PROB, prob_likely);
+ /* end byte loop. */
+
+ emit_label (L_end_loop_byte);
+
+ if (! flag_delayed_branch)
+ emit_insn (gen_zero_extendqisi2 (tmp2, gen_lowpart (QImode, tmp2)));
+ emit_insn (gen_zero_extendqisi2 (tmp1, gen_lowpart (QImode, tmp1)));
+
+ emit_label (L_return);
+
+ emit_insn (gen_subsi3 (operands[0], tmp1, tmp2));
+
+ return true;
+}
+
+/* Emit code to perform a strlen
+
+ OPERANDS[0] is the destination.
+ OPERANDS[1] is the string.
+ OPERANDS[2] is the char to search.
+ OPERANDS[3] is the alignment. */
+bool
+sh_expand_strlen (rtx *operands)
+{
+ rtx addr1 = operands[1];
+ rtx current_addr = copy_addr_to_reg (XEXP (addr1, 0));
+ rtx start_addr = gen_reg_rtx (Pmode);
+ rtx tmp0 = gen_reg_rtx (SImode);
+ rtx tmp1 = gen_reg_rtx (SImode);
+ rtx L_return = gen_label_rtx ();
+ rtx L_loop_byte = gen_label_rtx ();
+
+ rtx jump;
+ rtx L_loop_long = gen_label_rtx ();
+ rtx L_end_loop_long = gen_label_rtx ();
+
+ int align = INTVAL (operands[3]);
+
+ emit_move_insn (operands[0], GEN_INT (-1));
+
+ /* remember start of string. */
+ emit_move_insn (start_addr, current_addr);
+
+ if (align < 4)
+ {
+ emit_insn (gen_tstsi_t (GEN_INT (3), current_addr));
+ jump = emit_jump_insn (gen_branch_false (L_loop_byte));
+ add_int_reg_note (jump, REG_BR_PROB, prob_likely);
+ }
+
+ emit_move_insn (tmp0, operands[2]);
+
+ addr1 = adjust_automodify_address (addr1, SImode, current_addr, 0);
+
+ /*start long loop. */
+ emit_label (L_loop_long);
+
+ /* tmp1 is aligned, OK to load. */
+ emit_move_insn (tmp1, addr1);
+ emit_move_insn (current_addr, plus_constant (Pmode, current_addr, 4));
+
+ /* Is there a 0 byte ? */
+ emit_insn (gen_cmpstr_t (tmp0, tmp1));
+
+ jump = emit_jump_insn (gen_branch_false (L_loop_long));
+ add_int_reg_note (jump, REG_BR_PROB, prob_likely);
+ /* end loop. */
+
+ emit_label (L_end_loop_long);
+
+ emit_move_insn (current_addr, plus_constant (Pmode, current_addr, -4));
+
+ /* start byte loop. */
+ addr1 = adjust_address (addr1, QImode, 0);
+
+ emit_label (L_loop_byte);
+
+ emit_insn (gen_extendqisi2 (tmp1, addr1));
+ emit_move_insn (current_addr, plus_constant (Pmode, current_addr, 1));
+
+ emit_insn (gen_cmpeqsi_t (tmp1, const0_rtx));
+ jump = emit_jump_insn (gen_branch_false (L_loop_byte));
+ add_int_reg_note (jump, REG_BR_PROB, prob_likely);
+
+ /* end loop. */
+
+ emit_label (L_return);
+
+ emit_insn (gen_addsi3 (start_addr, start_addr, GEN_INT (1)));
+
+ emit_insn (gen_subsi3 (operands[0], current_addr, start_addr));
+
+ return true;
+}
diff --git a/gcc/config/sh/sh-modes.def b/gcc/config/sh/sh-modes.def
index aec007986ef..aa56038d614 100644
--- a/gcc/config/sh/sh-modes.def
+++ b/gcc/config/sh/sh-modes.def
@@ -18,9 +18,9 @@ along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
/* The SH uses a partial integer mode to represent the FPSCR register. */
-PARTIAL_INT_MODE (SI);
+PARTIAL_INT_MODE (SI, 22, PSI);
/* PDI mode is used to represent a function address in a target register. */
-PARTIAL_INT_MODE (DI);
+PARTIAL_INT_MODE (DI, 64, PDI);
/* Vector modes. */
VECTOR_MODE (INT, QI, 2); /* V2QI */
diff --git a/gcc/config/sh/sh-protos.h b/gcc/config/sh/sh-protos.h
index 4671c5499cc..11877e58b52 100644
--- a/gcc/config/sh/sh-protos.h
+++ b/gcc/config/sh/sh-protos.h
@@ -116,6 +116,9 @@ extern void emit_df_insn (rtx);
extern void output_pic_addr_const (FILE *, rtx);
extern bool expand_block_move (rtx *);
extern void prepare_move_operands (rtx[], enum machine_mode mode);
+extern bool sh_expand_cmpstr (rtx *);
+extern bool sh_expand_cmpnstr (rtx *);
+extern bool sh_expand_strlen (rtx *);
extern enum rtx_code prepare_cbranch_operands (rtx *, enum machine_mode mode,
enum rtx_code comparison);
extern void expand_cbranchsi4 (rtx *operands, enum rtx_code comparison, int);
diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c
index 60f45452036..167b615e37b 100644
--- a/gcc/config/sh/sh.c
+++ b/gcc/config/sh/sh.c
@@ -53,6 +53,9 @@ along with GCC; see the file COPYING3. If not see
#include "alloc-pool.h"
#include "tm-constrs.h"
#include "opts.h"
+#include "tree-pass.h"
+#include "pass_manager.h"
+#include "context.h"
#include <sstream>
#include <vector>
@@ -60,9 +63,6 @@ along with GCC; see the file COPYING3. If not see
int code_for_indirect_jump_scratch = CODE_FOR_indirect_jump_scratch;
-#define MSW (TARGET_LITTLE_ENDIAN ? 1 : 0)
-#define LSW (TARGET_LITTLE_ENDIAN ? 0 : 1)
-
/* These are some macros to abstract register modes. */
#define CONST_OK_FOR_I10(VALUE) (((HOST_WIDE_INT)(VALUE)) >= -512 \
&& ((HOST_WIDE_INT)(VALUE)) <= 511)
@@ -171,7 +171,6 @@ static bool shmedia_space_reserved_for_target_registers;
static void split_branches (rtx);
static int branch_dest (rtx);
-static void force_into (rtx, rtx);
static void print_slot (rtx);
static rtx add_constant (rtx, enum machine_mode, rtx);
static void dump_table (rtx, rtx);
@@ -311,6 +310,7 @@ static bool sequence_insn_p (rtx);
static void sh_canonicalize_comparison (int *, rtx *, rtx *, bool);
static void sh_canonicalize_comparison (enum rtx_code&, rtx&, rtx&,
enum machine_mode, bool);
+static bool sh_fixed_condition_code_regs (unsigned int* p1, unsigned int* p2);
static void sh_init_sync_libfuncs (void) ATTRIBUTE_UNUSED;
@@ -587,6 +587,9 @@ static const struct attribute_spec sh_attribute_table[] =
#undef TARGET_CANONICALIZE_COMPARISON
#define TARGET_CANONICALIZE_COMPARISON sh_canonicalize_comparison
+#undef TARGET_FIXED_CONDITION_CODE_REGS
+#define TARGET_FIXED_CONDITION_CODE_REGS sh_fixed_condition_code_regs
+
/* Machine-specific symbol_ref flags. */
#define SYMBOL_FLAG_FUNCVEC_FUNCTION (SYMBOL_FLAG_MACH_DEP << 0)
@@ -710,6 +713,34 @@ got_mode_name:;
#undef err_ret
}
+/* Register SH specific RTL passes. */
+extern opt_pass* make_pass_sh_treg_combine (gcc::context* ctx, bool split_insns,
+ const char* name);
+static void
+register_sh_passes (void)
+{
+ if (!TARGET_SH1)
+ return;
+
+/* Running the sh_treg_combine pass after ce1 generates better code when
+ comparisons are combined and reg-reg moves are introduced, because
+ reg-reg moves will be eliminated afterwards. However, there are quite
+ some cases where combine will be unable to fold comparison related insns,
+ thus for now don't do it.
+ register_pass (make_pass_sh_treg_combine (g, false, "sh_treg_combine1"),
+ PASS_POS_INSERT_AFTER, "ce1", 1);
+*/
+
+ /* Run sh_treg_combine pass after combine but before register allocation. */
+ register_pass (make_pass_sh_treg_combine (g, true, "sh_treg_combine2"),
+ PASS_POS_INSERT_AFTER, "split1", 1);
+
+ /* Run sh_treg_combine pass after register allocation and basic block
+ reordering as this sometimes creates new opportunities. */
+ register_pass (make_pass_sh_treg_combine (g, true, "sh_treg_combine3"),
+ PASS_POS_INSERT_AFTER, "split4", 1);
+}
+
/* Implement TARGET_OPTION_OVERRIDE macro. Validate and override
various options, and do some machine dependent initialization. */
static void
@@ -1022,6 +1053,8 @@ sh_option_override (void)
target CPU. */
selected_atomic_model_
= parse_validate_atomic_model_option (sh_atomic_model_str);
+
+ register_sh_passes ();
}
/* Print the operand address in x to the stream. */
@@ -1146,7 +1179,7 @@ sh_print_operand (FILE *stream, rtx x, int code)
{
rtx note = find_reg_note (current_output_insn, REG_BR_PROB, 0);
- if (note && INTVAL (XEXP (note, 0)) * 2 < REG_BR_PROB_BASE)
+ if (note && XINT (note, 0) * 2 < REG_BR_PROB_BASE)
fputs ("/u", stream);
break;
}
@@ -1172,12 +1205,12 @@ sh_print_operand (FILE *stream, rtx x, int code)
if (REG_P (x) || GET_CODE (x) == SUBREG)
{
regno = true_regnum (x);
- regno += FP_REGISTER_P (regno) ? 1 : LSW;
+ regno += FP_REGISTER_P (regno) ? 1 : SH_REG_LSW_OFFSET;
fputs (reg_names[regno], (stream));
}
else if (MEM_P (x))
{
- x = adjust_address (x, SImode, 4 * LSW);
+ x = adjust_address (x, SImode, 4 * SH_REG_LSW_OFFSET);
sh_print_operand_address (stream, XEXP (x, 0));
}
else
@@ -1188,7 +1221,7 @@ sh_print_operand (FILE *stream, rtx x, int code)
if (mode == VOIDmode)
mode = DImode;
if (GET_MODE_SIZE (mode) >= 8)
- sub = simplify_subreg (SImode, x, mode, 4 * LSW);
+ sub = simplify_subreg (SImode, x, mode, 4 * SH_REG_LSW_OFFSET);
if (sub)
sh_print_operand (stream, sub, 0);
else
@@ -1199,12 +1232,12 @@ sh_print_operand (FILE *stream, rtx x, int code)
if (REG_P (x) || GET_CODE (x) == SUBREG)
{
regno = true_regnum (x);
- regno += FP_REGISTER_P (regno) ? 0 : MSW;
+ regno += FP_REGISTER_P (regno) ? 0 : SH_REG_MSW_OFFSET;
fputs (reg_names[regno], (stream));
}
else if (MEM_P (x))
{
- x = adjust_address (x, SImode, 4 * MSW);
+ x = adjust_address (x, SImode, 4 * SH_REG_MSW_OFFSET);
sh_print_operand_address (stream, XEXP (x, 0));
}
else
@@ -1215,7 +1248,7 @@ sh_print_operand (FILE *stream, rtx x, int code)
if (mode == VOIDmode)
mode = DImode;
if (GET_MODE_SIZE (mode) >= 8)
- sub = simplify_subreg (SImode, x, mode, 4 * MSW);
+ sub = simplify_subreg (SImode, x, mode, 4 * SH_REG_MSW_OFFSET);
if (sub)
sh_print_operand (stream, sub, 0);
else
@@ -1584,157 +1617,6 @@ sh_encode_section_info (tree decl, rtx rtl, int first)
SYMBOL_REF_FLAGS (XEXP (rtl, 0)) |= SYMBOL_FLAG_FUNCVEC_FUNCTION;
}
-/* Like force_operand, but guarantees that VALUE ends up in TARGET. */
-static void
-force_into (rtx value, rtx target)
-{
- value = force_operand (value, target);
- if (! rtx_equal_p (value, target))
- emit_insn (gen_move_insn (target, value));
-}
-
-/* Emit code to perform a block move. Choose the best method.
-
- OPERANDS[0] is the destination.
- OPERANDS[1] is the source.
- OPERANDS[2] is the size.
- OPERANDS[3] is the alignment safe to use. */
-bool
-expand_block_move (rtx *operands)
-{
- int align = INTVAL (operands[3]);
- int constp = (CONST_INT_P (operands[2]));
- int bytes = (constp ? INTVAL (operands[2]) : 0);
-
- if (! constp)
- return false;
-
- /* If we could use mov.l to move words and dest is word-aligned, we
- can use movua.l for loads and still generate a relatively short
- and efficient sequence. */
- if (TARGET_SH4A_ARCH && align < 4
- && MEM_ALIGN (operands[0]) >= 32
- && can_move_by_pieces (bytes, 32))
- {
- rtx dest = copy_rtx (operands[0]);
- rtx src = copy_rtx (operands[1]);
- /* We could use different pseudos for each copied word, but
- since movua can only load into r0, it's kind of
- pointless. */
- rtx temp = gen_reg_rtx (SImode);
- rtx src_addr = copy_addr_to_reg (XEXP (src, 0));
- int copied = 0;
-
- while (copied + 4 <= bytes)
- {
- rtx to = adjust_address (dest, SImode, copied);
- rtx from = adjust_automodify_address (src, BLKmode,
- src_addr, copied);
-
- set_mem_size (from, 4);
- emit_insn (gen_movua (temp, from));
- emit_move_insn (src_addr, plus_constant (Pmode, src_addr, 4));
- emit_move_insn (to, temp);
- copied += 4;
- }
-
- if (copied < bytes)
- move_by_pieces (adjust_address (dest, BLKmode, copied),
- adjust_automodify_address (src, BLKmode,
- src_addr, copied),
- bytes - copied, align, 0);
-
- return true;
- }
-
- /* If it isn't a constant number of bytes, or if it doesn't have 4 byte
- alignment, or if it isn't a multiple of 4 bytes, then fail. */
- if (align < 4 || (bytes % 4 != 0))
- return false;
-
- if (TARGET_HARD_SH4)
- {
- if (bytes < 12)
- return false;
- else if (bytes == 12)
- {
- rtx func_addr_rtx = gen_reg_rtx (Pmode);
- rtx r4 = gen_rtx_REG (SImode, 4);
- rtx r5 = gen_rtx_REG (SImode, 5);
-
- function_symbol (func_addr_rtx, "__movmemSI12_i4", SFUNC_STATIC);
- force_into (XEXP (operands[0], 0), r4);
- force_into (XEXP (operands[1], 0), r5);
- emit_insn (gen_block_move_real_i4 (func_addr_rtx));
- return true;
- }
- else if (! optimize_size)
- {
- const char *entry_name;
- rtx func_addr_rtx = gen_reg_rtx (Pmode);
- int dwords;
- rtx r4 = gen_rtx_REG (SImode, 4);
- rtx r5 = gen_rtx_REG (SImode, 5);
- rtx r6 = gen_rtx_REG (SImode, 6);
-
- entry_name = (bytes & 4 ? "__movmem_i4_odd" : "__movmem_i4_even");
- function_symbol (func_addr_rtx, entry_name, SFUNC_STATIC);
- force_into (XEXP (operands[0], 0), r4);
- force_into (XEXP (operands[1], 0), r5);
-
- dwords = bytes >> 3;
- emit_insn (gen_move_insn (r6, GEN_INT (dwords - 1)));
- emit_insn (gen_block_lump_real_i4 (func_addr_rtx));
- return true;
- }
- else
- return false;
- }
- if (bytes < 64)
- {
- char entry[30];
- rtx func_addr_rtx = gen_reg_rtx (Pmode);
- rtx r4 = gen_rtx_REG (SImode, 4);
- rtx r5 = gen_rtx_REG (SImode, 5);
-
- sprintf (entry, "__movmemSI%d", bytes);
- function_symbol (func_addr_rtx, entry, SFUNC_STATIC);
- force_into (XEXP (operands[0], 0), r4);
- force_into (XEXP (operands[1], 0), r5);
- emit_insn (gen_block_move_real (func_addr_rtx));
- return true;
- }
-
- /* This is the same number of bytes as a memcpy call, but to a different
- less common function name, so this will occasionally use more space. */
- if (! optimize_size)
- {
- rtx func_addr_rtx = gen_reg_rtx (Pmode);
- int final_switch, while_loop;
- rtx r4 = gen_rtx_REG (SImode, 4);
- rtx r5 = gen_rtx_REG (SImode, 5);
- rtx r6 = gen_rtx_REG (SImode, 6);
-
- function_symbol (func_addr_rtx, "__movmem", SFUNC_STATIC);
- force_into (XEXP (operands[0], 0), r4);
- force_into (XEXP (operands[1], 0), r5);
-
- /* r6 controls the size of the move. 16 is decremented from it
- for each 64 bytes moved. Then the negative bit left over is used
- as an index into a list of move instructions. e.g., a 72 byte move
- would be set up with size(r6) = 14, for one iteration through the
- big while loop, and a switch of -2 for the last part. */
-
- final_switch = 16 - ((bytes / 4) % 16);
- while_loop = ((bytes / 4) / 16 - 1) * 16;
- emit_insn (gen_move_insn (r6, GEN_INT (while_loop + final_switch)));
- emit_insn (gen_block_lump_real (func_addr_rtx));
- return true;
- }
-
- return false;
-}
-
/* Prepare operands for a move define_expand; specifically, one of the
operands must be in a register. */
void
@@ -1908,7 +1790,7 @@ prepare_move_operands (rtx operands[], enum machine_mode mode)
static void
sh_canonicalize_comparison (enum rtx_code& cmp, rtx& op0, rtx& op1,
enum machine_mode mode,
- bool op0_preserve_value ATTRIBUTE_UNUSED)
+ bool op0_preserve_value)
{
/* When invoked from within the combine pass the mode is not specified,
so try to get it from one of the operands. */
@@ -1928,6 +1810,9 @@ sh_canonicalize_comparison (enum rtx_code& cmp, rtx& op0, rtx& op1,
// Make sure that the constant operand is the second operand.
if (CONST_INT_P (op0) && !CONST_INT_P (op1))
{
+ if (op0_preserve_value)
+ return;
+
std::swap (op0, op1);
cmp = swap_condition (cmp);
}
@@ -2016,6 +1901,14 @@ sh_canonicalize_comparison (int *code, rtx *op0, rtx *op1,
*code = (int)tmp_code;
}
+bool
+sh_fixed_condition_code_regs (unsigned int* p1, unsigned int* p2)
+{
+ *p1 = T_REG;
+ *p2 = INVALID_REGNUM;
+ return true;
+}
+
enum rtx_code
prepare_cbranch_operands (rtx *operands, enum machine_mode mode,
enum rtx_code comparison)
@@ -2082,7 +1975,7 @@ expand_cbranchsi4 (rtx *operands, enum rtx_code comparison, int probability)
operands[1], operands[2])));
rtx jump = emit_jump_insn (branch_expander (operands[3]));
if (probability >= 0)
- add_reg_note (jump, REG_BR_PROB, GEN_INT (probability));
+ add_int_reg_note (jump, REG_BR_PROB, probability);
}
/* ??? How should we distribute probabilities when more than one branch
@@ -3266,6 +3159,35 @@ and_xor_ior_costs (rtx x, int code)
static inline int
addsubcosts (rtx x)
{
+ if (GET_MODE (x) == SImode)
+ {
+ /* The addc or subc patterns will eventually become one or two
+ instructions. Below are some costs for some of the patterns
+ which combine would reject because the costs of the individual
+ insns in the patterns are lower.
+
+ FIXME: It would be much easier if we had something like insn cost
+ attributes and the cost calculation machinery used those attributes
+ in the first place. This would eliminate redundant recog-like C
+ code to calculate costs of complex patterns. */
+ rtx op0 = XEXP (x, 0);
+ rtx op1 = XEXP (x, 1);
+
+ if (GET_CODE (x) == PLUS)
+ {
+ if (GET_CODE (op0) == AND
+ && XEXP (op0, 1) == const1_rtx
+ && (GET_CODE (op1) == PLUS
+ || (GET_CODE (op1) == MULT && XEXP (op1, 1) == const2_rtx)))
+ return 1;
+
+ if (GET_CODE (op0) == MULT && XEXP (op0, 1) == const2_rtx
+ && GET_CODE (op1) == LSHIFTRT
+ && CONST_INT_P (XEXP (op1, 1)) && INTVAL (XEXP (op1, 1)) == 31)
+ return 1;
+ }
+ }
+
/* On SH1-4 we have only max. SImode operations.
Double the cost for modes > SImode. */
const int cost_scale = !TARGET_SHMEDIA
@@ -8365,8 +8287,8 @@ sh_builtin_saveregs (void)
emit_insn (gen_addsi3 (fpregs, fpregs, GEN_INT (-UNITS_PER_WORD)));
mem = change_address (regbuf, SFmode, fpregs);
emit_move_insn (mem,
- gen_rtx_REG (SFmode, BASE_ARG_REG (SFmode) + regno
- - (TARGET_LITTLE_ENDIAN != 0)));
+ gen_rtx_REG (SFmode, BASE_ARG_REG (SFmode)
+ + regno - SH_REG_MSW_OFFSET));
}
}
else
@@ -10741,8 +10663,7 @@ sh_adjust_cost (rtx insn, rtx link ATTRIBUTE_UNUSED, rtx dep_insn, int cost)
{
int orig_cost = cost;
rtx note = find_reg_note (insn, REG_BR_PROB, 0);
- rtx target = ((! note
- || INTVAL (XEXP (note, 0)) * 2 < REG_BR_PROB_BASE)
+ rtx target = ((!note || XINT (note, 0) * 2 < REG_BR_PROB_BASE)
? insn : JUMP_LABEL (insn));
/* On the likely path, the branch costs 1, on the unlikely path,
it costs 3. */
diff --git a/gcc/config/sh/sh.h b/gcc/config/sh/sh.h
index 8e27030c6a0..9f07012941c 100644
--- a/gcc/config/sh/sh.h
+++ b/gcc/config/sh/sh.h
@@ -405,16 +405,21 @@ extern enum sh_divide_strategy_e sh_div_strategy;
/* Target machine storage layout. */
+#define TARGET_BIG_ENDIAN (!TARGET_LITTLE_ENDIAN)
+
+#define SH_REG_MSW_OFFSET (TARGET_LITTLE_ENDIAN ? 1 : 0)
+#define SH_REG_LSW_OFFSET (TARGET_LITTLE_ENDIAN ? 0 : 1)
+
/* Define this if most significant bit is lowest numbered
in instructions that operate on numbered bit-fields. */
#define BITS_BIG_ENDIAN 0
/* Define this if most significant byte of a word is the lowest numbered. */
-#define BYTES_BIG_ENDIAN (TARGET_LITTLE_ENDIAN == 0)
+#define BYTES_BIG_ENDIAN TARGET_BIG_ENDIAN
/* Define this if most significant word of a multiword number is the lowest
numbered. */
-#define WORDS_BIG_ENDIAN (TARGET_LITTLE_ENDIAN == 0)
+#define WORDS_BIG_ENDIAN TARGET_BIG_ENDIAN
#define MAX_BITS_PER_WORD 64
@@ -1437,7 +1442,7 @@ struct sh_args {
#define SHCOMPACT_FORCE_ON_STACK(MODE,TYPE) \
((MODE) == BLKmode \
&& TARGET_SHCOMPACT \
- && ! TARGET_LITTLE_ENDIAN \
+ && TARGET_BIG_ENDIAN \
&& int_size_in_bytes (TYPE) > 4 \
&& int_size_in_bytes (TYPE) < 8)
diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md
index 2c20d3868a4..8cc9195c988 100644
--- a/gcc/config/sh/sh.md
+++ b/gcc/config/sh/sh.md
@@ -31,9 +31,6 @@
;; ??? The MAC.W and MAC.L instructions are not supported. There is no
;; way to generate them.
-;; ??? The cmp/str instruction is not supported. Perhaps it can be used
-;; for a str* inline function.
-
;; BSR is not generated by the compiler proper, but when relaxing, it
;; generates .uses pseudo-ops that allow linker relaxation to create
;; BSR. This is actually implemented in bfd/{coff,elf32}-sh.c
@@ -164,6 +161,9 @@
;; (unspec [OFFSET ANCHOR] UNSPEC_PCREL_SYMOFF) == OFFSET - (ANCHOR - .).
(UNSPEC_PCREL_SYMOFF 46)
+ ;; Misc builtins
+ (UNSPEC_BUILTIN_STRLEN 47)
+
;; These are used with unspec_volatile.
(UNSPECV_BLOCKAGE 0)
(UNSPECV_ALIGN 1)
@@ -673,7 +673,7 @@
(and:SI (match_operand:SI 0 "arith_reg_operand" "%r")
(match_operand:SI 1 "arith_reg_operand" "r")) <lowpart_be>)
(const_int 0)))]
- "TARGET_SH1 && !TARGET_LITTLE_ENDIAN"
+ "TARGET_SH1 && TARGET_BIG_ENDIAN"
"tst %0,%1"
[(set_attr "type" "mt_group")])
@@ -764,7 +764,7 @@
(match_operand:SI 3 "const_int_operand")) 3)
(match_operand:SI 1 "const_int_operand")
(match_operand:SI 2 "const_int_operand")))]
- "TARGET_SH1 && ! TARGET_LITTLE_ENDIAN
+ "TARGET_SH1 && TARGET_BIG_ENDIAN
&& ZERO_EXTRACT_ANDMASK (operands[1], operands[2])
== (INTVAL (operands[3]) & 255)
&& CONST_OK_FOR_K08 (INTVAL (operands[3]) & 255)"
@@ -783,7 +783,7 @@
tst %0,%0
cmp/eq %1,%0
cmp/eq %1,%0"
- [(set_attr "type" "mt_group")])
+ [(set_attr "type" "mt_group")])
;; FIXME: For some reason, on SH4A and SH2A combine fails to simplify this
;; pattern by itself. What this actually does is:
@@ -809,7 +809,7 @@
"@
cmp/pl %0
cmp/gt %1,%0"
- [(set_attr "type" "mt_group")])
+ [(set_attr "type" "mt_group")])
(define_insn "cmpgesi_t"
[(set (reg:SI T_REG)
@@ -819,7 +819,7 @@
"@
cmp/pz %0
cmp/ge %1,%0"
- [(set_attr "type" "mt_group")])
+ [(set_attr "type" "mt_group")])
;; FIXME: This is actually wrong. There is no way to literally move a
;; general reg to t reg. Luckily, it seems that this pattern will be only
@@ -831,7 +831,7 @@
[(set (reg:SI T_REG) (match_operand:SI 0 "arith_reg_operand" "r"))]
"TARGET_SH1"
"cmp/pl %0"
- [(set_attr "type" "mt_group")])
+ [(set_attr "type" "mt_group")])
;; Some integer sign comparison patterns can be realized with the div0s insn.
;; div0s Rm,Rn T = (Rm >> 31) ^ (Rn >> 31)
@@ -1750,15 +1750,13 @@
;; -------------------------------------------------------------------------
(define_expand "adddi3"
- [(set (match_operand:DI 0 "arith_reg_operand" "")
- (plus:DI (match_operand:DI 1 "arith_reg_operand" "")
- (match_operand:DI 2 "arith_operand" "")))]
+ [(set (match_operand:DI 0 "arith_reg_operand")
+ (plus:DI (match_operand:DI 1 "arith_reg_operand")
+ (match_operand:DI 2 "arith_operand")))]
""
{
if (TARGET_SH1)
{
- if (!can_create_pseudo_p () && ! arith_reg_operand (operands[2], DImode))
- FAIL;
operands[2] = force_reg (DImode, operands[2]);
emit_insn (gen_adddi3_compact (operands[0], operands[1], operands[2]));
DONE;
@@ -1797,22 +1795,22 @@
(set_attr "highpart" "ignore")])
(define_insn_and_split "adddi3_compact"
- [(set (match_operand:DI 0 "arith_reg_dest" "=&r")
- (plus:DI (match_operand:DI 1 "arith_reg_operand" "%0")
- (match_operand:DI 2 "arith_reg_operand" "r")))
+ [(set (match_operand:DI 0 "arith_reg_dest")
+ (plus:DI (match_operand:DI 1 "arith_reg_operand")
+ (match_operand:DI 2 "arith_reg_operand")))
(clobber (reg:SI T_REG))]
"TARGET_SH1"
"#"
- "&& reload_completed"
+ "&& can_create_pseudo_p ()"
[(const_int 0)]
{
- rtx high0 = gen_highpart (SImode, operands[0]);
- rtx high2 = gen_highpart (SImode, operands[2]);
- rtx low0 = gen_lowpart (SImode, operands[0]);
-
emit_insn (gen_clrt ());
- emit_insn (gen_addc (low0, low0, gen_lowpart (SImode, operands[2])));
- emit_insn (gen_addc (high0, high0, high2));
+ emit_insn (gen_addc (gen_lowpart (SImode, operands[0]),
+ gen_lowpart (SImode, operands[1]),
+ gen_lowpart (SImode, operands[2])));
+ emit_insn (gen_addc (gen_highpart (SImode, operands[0]),
+ gen_highpart (SImode, operands[1]),
+ gen_highpart (SImode, operands[2])));
DONE;
})
@@ -1844,7 +1842,7 @@
;; Split 'reg + reg + 1' into a sett addc sequence, as it can be scheduled
;; better, if the sett insn can be done early.
-(define_insn_and_split "*addc"
+(define_insn_and_split "*addc_r_r_1"
[(set (match_operand:SI 0 "arith_reg_dest" "")
(plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "")
(match_operand:SI 2 "arith_reg_operand" ""))
@@ -1860,7 +1858,7 @@
;; Left shifts by one are usually done with an add insn to avoid T_REG
;; clobbers. Thus addc can also be used to do something like '(x << 1) + 1'.
-(define_insn_and_split "*addc"
+(define_insn_and_split "*addc_2r_1"
[(set (match_operand:SI 0 "arith_reg_dest")
(plus:SI (mult:SI (match_operand:SI 1 "arith_reg_operand")
(const_int 2))
@@ -1900,7 +1898,7 @@
;; can be scheduled much better since the load of the constant can be
;; done earlier, before any comparison insns that store the result in
;; the T bit.
-(define_insn_and_split "*addc"
+(define_insn_and_split "*addc_r_1"
[(set (match_operand:SI 0 "arith_reg_dest" "")
(plus:SI (match_operand:SI 1 "t_reg_operand" "")
(match_operand:SI 2 "arith_reg_operand" "")))
@@ -1913,6 +1911,126 @@
(match_dup 1)))
(clobber (reg:SI T_REG))])])
+;; Use shlr-addc to do 'reg + (reg & 1)'.
+(define_insn_and_split "*addc_r_lsb"
+ [(set (match_operand:SI 0 "arith_reg_dest")
+ (plus:SI (and:SI (match_operand:SI 1 "arith_reg_operand")
+ (const_int 1))
+ (match_operand:SI 2 "arith_reg_operand")))
+ (clobber (reg:SI T_REG))]
+ "TARGET_SH1"
+ "#"
+ "&& can_create_pseudo_p ()"
+ [(parallel [(set (match_dup 0) (plus:SI (reg:SI T_REG) (match_dup 2)))
+ (clobber (reg:SI T_REG))])]
+{
+ emit_insn (gen_shlr (gen_reg_rtx (SImode), operands[1]));
+})
+
+;; Use shlr-addc to do 'reg + reg + (reg & 1)'.
+(define_insn_and_split "*addc_r_r_lsb"
+ [(set (match_operand:SI 0 "arith_reg_dest")
+ (plus:SI (plus:SI (and:SI (match_operand:SI 1 "arith_reg_operand")
+ (const_int 1))
+ (match_operand:SI 2 "arith_reg_operand"))
+ (match_operand:SI 3 "arith_reg_operand")))
+ (clobber (reg:SI T_REG))]
+ "TARGET_SH1"
+ "#"
+ "&& can_create_pseudo_p ()"
+ [(parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 2) (match_dup 3))
+ (reg:SI T_REG)))
+ (clobber (reg:SI T_REG))])]
+{
+ emit_insn (gen_shlr (gen_reg_rtx (SImode), operands[1]));
+})
+
+;; Canonicalize 'reg + (reg & 1) + reg' into 'reg + reg + (reg & 1)'.
+(define_insn_and_split "*addc_r_lsb_r"
+ [(set (match_operand:SI 0 "arith_reg_dest")
+ (plus:SI (and:SI (match_operand:SI 1 "arith_reg_operand")
+ (const_int 1))
+ (plus:SI (match_operand:SI 2 "arith_reg_operand")
+ (match_operand:SI 3 "arith_reg_operand"))))
+ (clobber (reg:SI T_REG))]
+ "TARGET_SH1"
+ "#"
+ "&& can_create_pseudo_p ()"
+ [(parallel [(set (match_dup 0)
+ (plus:SI (plus:SI (and:SI (match_dup 1) (const_int 1))
+ (match_dup 2))
+ (match_dup 3)))
+ (clobber (reg:SI T_REG))])])
+
+;; Canonicalize '2 * reg + (reg & 1)' into 'reg + reg + (reg & 1)'.
+(define_insn_and_split "*addc_2r_lsb"
+ [(set (match_operand:SI 0 "arith_reg_dest")
+ (plus:SI (and:SI (match_operand:SI 1 "arith_reg_operand")
+ (const_int 1))
+ (mult:SI (match_operand:SI 2 "arith_reg_operand")
+ (const_int 2))))
+ (clobber (reg:SI T_REG))]
+ "TARGET_SH1"
+ "#"
+ "&& can_create_pseudo_p ()"
+ [(parallel [(set (match_dup 0)
+ (plus:SI (plus:SI (and:SI (match_dup 1) (const_int 1))
+ (match_dup 2))
+ (match_dup 2)))
+ (clobber (reg:SI T_REG))])])
+
+;; Use shll-addc to do 'reg + ((unsigned int)reg >> 31)'.
+(define_insn_and_split "*addc_r_msb"
+ [(set (match_operand:SI 0 "arith_reg_dest")
+ (plus:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand")
+ (const_int 31))
+ (match_operand:SI 2 "arith_reg_operand")))
+ (clobber (reg:SI T_REG))]
+ "TARGET_SH1"
+ "#"
+ "&& can_create_pseudo_p ()"
+ [(parallel [(set (match_dup 0) (plus:SI (reg:SI T_REG) (match_dup 2)))
+ (clobber (reg:SI T_REG))])]
+{
+ emit_insn (gen_shll (gen_reg_rtx (SImode), operands[1]));
+})
+
+;; Use shll-addc to do 'reg + reg + ((unsigned int)reg >> 31)'.
+(define_insn_and_split "*addc_r_r_msb"
+ [(set (match_operand:SI 0 "arith_reg_dest")
+ (plus:SI (plus:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand")
+ (const_int 31))
+ (match_operand:SI 2 "arith_reg_operand"))
+ (match_operand:SI 3 "arith_reg_operand")))
+ (clobber (reg:SI T_REG))]
+ "TARGET_SH1"
+ "#"
+ "&& can_create_pseudo_p ()"
+ [(parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 2) (match_dup 3))
+ (reg:SI T_REG)))
+ (clobber (reg:SI T_REG))])]
+{
+ emit_insn (gen_shll (gen_reg_rtx (SImode), operands[1]));
+})
+
+;; Canonicalize '2 * reg + ((unsigned int)reg >> 31)'
+;; into 'reg + reg + (reg & 1)'.
+(define_insn_and_split "*addc_2r_msb"
+ [(set (match_operand:SI 0 "arith_reg_dest")
+ (plus:SI (mult:SI (match_operand:SI 1 "arith_reg_operand")
+ (const_int 2))
+ (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand")
+ (const_int 31))))
+ (clobber (reg:SI T_REG))]
+ "TARGET_SH1"
+ "#"
+ "&& can_create_pseudo_p ()"
+ [(parallel [(set (match_dup 0)
+ (plus:SI (plus:SI (lshiftrt:SI (match_dup 2) (const_int 31))
+ (match_dup 1))
+ (match_dup 1)))
+ (clobber (reg:SI T_REG))])])
+
(define_expand "addsi3"
[(set (match_operand:SI 0 "arith_reg_operand" "")
(plus:SI (match_operand:SI 1 "arith_operand" "")
@@ -1991,22 +2109,22 @@
(set_attr "highpart" "ignore")])
(define_insn_and_split "subdi3_compact"
- [(set (match_operand:DI 0 "arith_reg_dest" "=&r")
- (minus:DI (match_operand:DI 1 "arith_reg_operand" "0")
- (match_operand:DI 2 "arith_reg_operand" "r")))
+ [(set (match_operand:DI 0 "arith_reg_dest")
+ (minus:DI (match_operand:DI 1 "arith_reg_operand")
+ (match_operand:DI 2 "arith_reg_operand")))
(clobber (reg:SI T_REG))]
"TARGET_SH1"
"#"
- "&& reload_completed"
+ "&& can_create_pseudo_p ()"
[(const_int 0)]
{
- rtx high0 = gen_highpart (SImode, operands[0]);
- rtx high2 = gen_highpart (SImode, operands[2]);
- rtx low0 = gen_lowpart (SImode, operands[0]);
-
emit_insn (gen_clrt ());
- emit_insn (gen_subc (low0, low0, gen_lowpart (SImode, operands[2])));
- emit_insn (gen_subc (high0, high0, high2));
+ emit_insn (gen_subc (gen_lowpart (SImode, operands[0]),
+ gen_lowpart (SImode, operands[1]),
+ gen_lowpart (SImode, operands[2])));
+ emit_insn (gen_subc (gen_highpart (SImode, operands[0]),
+ gen_highpart (SImode, operands[1]),
+ gen_highpart (SImode, operands[2])));
DONE;
})
@@ -2118,7 +2236,7 @@
(zero_extend:SI (subreg:QI (not:SI (subreg:SI (match_operand:QI 1
"general_extend_operand"
"") 0)) 3)))]
- "TARGET_SHMEDIA && ! TARGET_LITTLE_ENDIAN"
+ "TARGET_SHMEDIA && TARGET_BIG_ENDIAN"
[(set (match_dup 0) (zero_extend:SI (match_dup 1)))
(set (match_dup 0) (xor:SI (match_dup 0) (const_int 255)))]
"")
@@ -3843,7 +3961,7 @@ label:
operands[0] = SUBREG_REG (operands[0]);
}
gcc_assert (REG_P (operands[0]));
- if (! TARGET_LITTLE_ENDIAN)
+ if (TARGET_BIG_ENDIAN)
offset += 8 - GET_MODE_SIZE (inmode);
operands[5] = gen_rtx_SUBREG (inmode, operands[0], offset);
})
@@ -4037,7 +4155,7 @@ label:
DONE;
})
-(define_insn "*rotlhi3_8"
+(define_insn "rotlhi3_8"
[(set (match_operand:HI 0 "arith_reg_dest" "=r")
(rotate:HI (match_operand:HI 1 "arith_reg_operand" "r")
(const_int 8)))]
@@ -5450,8 +5568,8 @@ label:
"sub r63, %1, %0"
[(set_attr "type" "arith_media")])
-;; Don't expand immediately because otherwise neg:DI (abs:DI) will not be
-;; combined.
+;; Don't split into individual negc insns immediately so that neg:DI (abs:DI)
+;; can be combined.
(define_expand "negdi2"
[(parallel [(set (match_operand:DI 0 "arith_reg_dest")
(neg:DI (match_operand:DI 1 "arith_reg_operand")))
@@ -5459,12 +5577,12 @@ label:
"TARGET_SH1")
(define_insn_and_split "*negdi2"
- [(set (match_operand:DI 0 "arith_reg_dest" "=&r")
- (neg:DI (match_operand:DI 1 "arith_reg_operand" "r")))
+ [(set (match_operand:DI 0 "arith_reg_dest")
+ (neg:DI (match_operand:DI 1 "arith_reg_operand")))
(clobber (reg:SI T_REG))]
"TARGET_SH1"
"#"
- "&& reload_completed"
+ "&& can_create_pseudo_p ()"
[(const_int 0)]
{
emit_insn (gen_clrt ());
@@ -6898,9 +7016,9 @@ label:
(match_operand:QIHI 1 "register_operand" "r,*z,m"))]
"TARGET_SH1 && !t_reg_operand (operands[1], VOIDmode)"
"@
- mov %1,%0
- mov.<bw> %1,%0
- mov.<bw> %1,%0"
+ mov %1,%0
+ mov.<bw> %1,%0
+ mov.<bw> %1,%0"
[(set_attr "type" "move,store,load")])
;; FIXME: The non-SH2A and SH2A variants should be combined by adding
@@ -7736,11 +7854,11 @@ label:
rtx mem2
= change_address (mem, SFmode, gen_rtx_POST_INC (Pmode, operands[1]));
insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode,
- regno + !! TARGET_LITTLE_ENDIAN),
+ regno + SH_REG_MSW_OFFSET),
mem2, operands[2]));
add_reg_note (insn, REG_INC, operands[1]);
insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode,
- regno + ! TARGET_LITTLE_ENDIAN),
+ regno + SH_REG_LSW_OFFSET),
change_address (mem, SFmode, NULL_RTX),
operands[2]));
DONE;
@@ -7758,8 +7876,8 @@ label:
int regno = true_regnum (operands[0]);
rtx addr, insn;
rtx mem2 = change_address (operands[1], SFmode, NULL_RTX);
- rtx reg0 = gen_rtx_REG (SFmode, regno + (TARGET_LITTLE_ENDIAN ? 1 : 0));
- rtx reg1 = gen_rtx_REG (SFmode, regno + (TARGET_LITTLE_ENDIAN ? 0 : 1));
+ rtx reg0 = gen_rtx_REG (SFmode, regno + SH_REG_MSW_OFFSET);
+ rtx reg1 = gen_rtx_REG (SFmode, regno + SH_REG_LSW_OFFSET);
operands[1] = copy_rtx (mem2);
addr = XEXP (mem2, 0);
@@ -7824,8 +7942,8 @@ label:
{
int regno = true_regnum (operands[1]);
rtx insn, addr;
- rtx reg0 = gen_rtx_REG (SFmode, regno + (TARGET_LITTLE_ENDIAN ? 1 : 0));
- rtx reg1 = gen_rtx_REG (SFmode, regno + (TARGET_LITTLE_ENDIAN ? 0 : 1));
+ rtx reg0 = gen_rtx_REG (SFmode, regno + SH_REG_MSW_OFFSET);
+ rtx reg1 = gen_rtx_REG (SFmode, regno + SH_REG_LSW_OFFSET);
operands[0] = copy_rtx (operands[0]);
PUT_MODE (operands[0], SFmode);
@@ -8203,15 +8321,9 @@ label:
(use (match_operand:PSI 2 "fpscr_operand" "c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c"))
(clobber (match_scratch:SI 3 "=X,X,Bsc,Bsc,&z,X,X,X,X,X,X,X,X,y,X,X,X,X,X"))]
"TARGET_SH2E
- && (arith_reg_operand (operands[0], SFmode)
- || arith_reg_operand (operands[1], SFmode)
- || arith_reg_operand (operands[3], SImode)
- || (fpul_operand (operands[0], SFmode)
- && memory_operand (operands[1], SFmode)
- && GET_CODE (XEXP (operands[1], 0)) == POST_INC)
- || (fpul_operand (operands[1], SFmode)
- && memory_operand (operands[0], SFmode)
- && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC))"
+ && (arith_reg_operand (operands[0], SFmode) || fpul_operand (operands[0], SFmode)
+ || arith_reg_operand (operands[1], SFmode) || fpul_operand (operands[1], SFmode)
+ || arith_reg_operand (operands[3], SImode))"
"@
fmov %1,%0
mov %1,%0
@@ -8425,89 +8537,32 @@ label:
return output_branch (sh_eval_treg_value (operands[1]), insn, operands);
}
"&& 1"
- [(set (pc) (if_then_else (eq (reg:SI T_REG) (match_dup 2))
- (label_ref (match_dup 0))
- (pc)))]
+ [(const_int 0)]
{
- /* Try to find missed test and branch combine opportunities which result
- in redundant T bit tests before conditional branches.
- This is done not only after combine (and before reload) but in every
- split pass, because some opportunities are formed also after combine.
- FIXME: Probably this would not be needed if CCmode was used
- together with TARGET_FIXED_CONDITION_CODE_REGS. */
+ /* Try to canonicalize the branch condition if it is not one of:
+ (ne (reg:SI T_REG) (const_int 0))
+ (eq (reg:SI T_REG) (const_int 0))
- const int treg_value = sh_eval_treg_value (operands[1]);
- operands[2] = NULL_RTX;
+ Instead of splitting out a new insn, we modify the current insn's
+ operands as needed. This preserves things such as REG_DEAD notes. */
- /* Scan the insns backwards for an insn that sets the T bit by testing a
- reg against zero like:
- (set (reg T_REG) (eq (reg) (const_int 0))) */
- rtx testing_insn = NULL_RTX;
- rtx tested_reg = NULL_RTX;
-
- set_of_reg s0 = sh_find_set_of_reg (get_t_reg_rtx (), curr_insn,
- prev_nonnote_insn_bb);
- if (s0.set_src != NULL_RTX
- && GET_CODE (s0.set_src) == EQ
- && REG_P (XEXP (s0.set_src, 0))
- && satisfies_constraint_Z (XEXP (s0.set_src, 1)))
- {
- testing_insn = s0.insn;
- tested_reg = XEXP (s0.set_src, 0);
- }
- else
- FAIL;
-
- /* Continue scanning the insns backwards and try to find the insn that
- sets the tested reg which we found above. If the reg is set by storing
- the T bit or the negated T bit we can eliminate the test insn before
- the branch. Notice that the branch condition has to be inverted if the
- test is eliminated. */
-
- /* If the T bit is used between the testing insn and the brach insn
- leave it alone. */
- if (reg_used_between_p (get_t_reg_rtx (), testing_insn, curr_insn))
- FAIL;
-
- while (true)
- {
- /* It's not safe to go beyond the current basic block after reload. */
- set_of_reg s1 = sh_find_set_of_reg (tested_reg, s0.insn,
- reload_completed
- ? prev_nonnote_insn_bb
- : prev_nonnote_insn);
- if (s1.set_src == NULL_RTX)
- break;
-
- if (t_reg_operand (s1.set_src, VOIDmode))
- operands[2] = GEN_INT (treg_value ^ 1);
- else if (negt_reg_operand (s1.set_src, VOIDmode))
- operands[2] = GEN_INT (treg_value);
- else if (REG_P (s1.set_src))
- {
- /* If it's a reg-reg copy follow the copied reg. This can
- happen e.g. when T bit store zero-extensions are
- eliminated. */
- tested_reg = s1.set_src;
- s0.insn = s1.insn;
- continue;
- }
+ if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
+ && REG_P (XEXP (operands[1], 0)) && REGNO (XEXP (operands[1], 0)) == T_REG
+ && XEXP (operands[1], 1) == const0_rtx)
+ DONE;
- /* It's only safe to remove the testing insn if the T bit is not
- modified between the testing insn and the insn that stores the
- T bit. Notice that some T bit stores such as negc also modify
- the T bit. */
- if (modified_between_p (get_t_reg_rtx (), s1.insn, testing_insn)
- || modified_in_p (get_t_reg_rtx (), s1.insn))
- operands[2] = NULL_RTX;
+ int branch_cond = sh_eval_treg_value (operands[1]);
+ rtx new_cond_rtx = NULL_RTX;
- break;
- }
-
- if (operands[2] == NULL_RTX)
- FAIL;
+ if (branch_cond == 0)
+ new_cond_rtx = gen_rtx_EQ (VOIDmode, get_t_reg_rtx (), const0_rtx);
+ else if (branch_cond == 1)
+ new_cond_rtx = gen_rtx_NE (VOIDmode, get_t_reg_rtx (), const0_rtx);
- set_insn_deleted (testing_insn);
+ if (new_cond_rtx != NULL_RTX)
+ validate_change (curr_insn, &XEXP (XEXP (PATTERN (curr_insn), 1), 0),
+ new_cond_rtx, false);
+ DONE;
}
[(set_attr "type" "cbranch")])
@@ -8721,25 +8776,21 @@ label:
})
; operand 0 is the loop count pseudo register
-; operand 1 is the number of loop iterations or 0 if it is unknown
-; operand 2 is the maximum number of loop iterations
-; operand 3 is the number of levels of enclosed loops
-; operand 4 is the label to jump to at the top of the loop
+; operand 1 is the label to jump to at the top of the loop
(define_expand "doloop_end"
[(parallel [(set (pc)
(if_then_else (ne:SI (match_operand:SI 0 "" "")
(const_int 1))
- (label_ref (match_operand 4 "" ""))
+ (label_ref (match_operand 1 "" ""))
(pc)))
(set (match_dup 0)
(plus:SI (match_dup 0) (const_int -1)))
- (clobber (reg:SI T_REG))])
- (match_operand 5 "" "")]
+ (clobber (reg:SI T_REG))])]
"TARGET_SH2"
{
if (GET_MODE (operands[0]) != SImode)
FAIL;
- emit_jump_insn (gen_doloop_end_split (operands[0], operands[4], operands[0]));
+ emit_jump_insn (gen_doloop_end_split (operands[0], operands[1], operands[0]));
DONE;
})
@@ -10773,7 +10824,7 @@ label:
(clobber (match_scratch:SI 3 "=X,1"))]
"TARGET_SH1"
{
- rtx diff_vec = PATTERN (next_active_insn (operands[2]));
+ rtx diff_vec = PATTERN (NEXT_INSN (operands[2]));
gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
@@ -10807,7 +10858,7 @@ label:
(clobber (match_operand:SI 4 "" "=X,1"))]
"TARGET_SH2 && reload_completed && flag_pic"
{
- rtx diff_vec = PATTERN (next_active_insn (operands[2]));
+ rtx diff_vec = PATTERN (NEXT_INSN (operands[2]));
gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
switch (GET_MODE (diff_vec))
@@ -10845,7 +10896,7 @@ label:
UNSPEC_CASESI)))]
"TARGET_SHMEDIA"
{
- rtx diff_vec = PATTERN (next_active_insn (operands[2]));
+ rtx diff_vec = PATTERN (NEXT_INSN (operands[2]));
gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
@@ -10872,7 +10923,7 @@ label:
(label_ref:DI (match_operand 3 "" ""))] UNSPEC_CASESI)))]
"TARGET_SHMEDIA"
{
- rtx diff_vec = PATTERN (next_active_insn (operands[3]));
+ rtx diff_vec = PATTERN (NEXT_INSN (operands[3]));
gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
@@ -11486,10 +11537,13 @@ label:
;; multiple insns like:
;; movt Rn
;; tst Rn,Rn
+;; This requires an additional pseudo. The SH specific sh_treg_combine RTL
+;; pass will look for this insn. Disallow using it if pseudos can't be
+;; created.
(define_insn_and_split "nott"
[(set (reg:SI T_REG)
- (xor:SI (match_operand:SI 0 "t_reg_operand" "") (const_int 1)))]
- "TARGET_SH1"
+ (xor:SI (match_operand:SI 0 "t_reg_operand") (const_int 1)))]
+ "TARGET_SH2A || (TARGET_SH1 && can_create_pseudo_p ())"
{
gcc_assert (TARGET_SH2A);
return "nott";
@@ -11899,19 +11953,20 @@ label:
;; String/block move insn.
(define_expand "movmemsi"
- [(parallel [(set (mem:BLK (match_operand:BLK 0 "" ""))
- (mem:BLK (match_operand:BLK 1 "" "")))
- (use (match_operand:SI 2 "nonmemory_operand" ""))
- (use (match_operand:SI 3 "immediate_operand" ""))
+ [(parallel [(set (mem:BLK (match_operand:BLK 0))
+ (mem:BLK (match_operand:BLK 1)))
+ (use (match_operand:SI 2 "nonmemory_operand"))
+ (use (match_operand:SI 3 "immediate_operand"))
(clobber (reg:SI PR_REG))
(clobber (reg:SI R4_REG))
(clobber (reg:SI R5_REG))
(clobber (reg:SI R0_REG))])]
"TARGET_SH1 && ! TARGET_SH5"
{
- if(expand_block_move (operands))
- DONE;
- else FAIL;
+ if (expand_block_move (operands))
+ DONE;
+ else
+ FAIL;
})
(define_insn "block_move_real"
@@ -11972,6 +12027,71 @@ label:
"jsr @%0%#"
[(set_attr "type" "sfunc")
(set_attr "needs_delay_slot" "yes")])
+
+;; byte compare pattern
+;; temp = a ^ b;
+;; !((temp & 0xF000) && (temp & 0x0F00) && (temp & 0x00F0) && (temp & 0x000F))
+(define_insn "cmpstr_t"
+ [(set (reg:SI T_REG)
+ (eq:SI (and:SI
+ (and:SI
+ (and:SI
+ (zero_extract:SI
+ (xor:SI (match_operand:SI 0 "arith_reg_operand" "r")
+ (match_operand:SI 1 "arith_reg_operand" "r"))
+ (const_int 8) (const_int 0))
+ (zero_extract:SI (xor:SI (match_dup 0) (match_dup 1))
+ (const_int 8) (const_int 8)))
+ (zero_extract:SI (xor:SI (match_dup 0) (match_dup 1))
+ (const_int 8) (const_int 16)))
+ (zero_extract:SI (xor:SI (match_dup 0) (match_dup 1))
+ (const_int 8) (const_int 24)))
+ (const_int 0)))]
+ "TARGET_SH1"
+ "cmp/str %0,%1"
+ [(set_attr "type" "mt_group")])
+
+(define_expand "cmpstrsi"
+ [(set (match_operand:SI 0 "register_operand")
+ (compare:SI (match_operand:BLK 1 "memory_operand")
+ (match_operand:BLK 2 "memory_operand")))
+ (use (match_operand 3 "immediate_operand"))]
+ "TARGET_SH1 && optimize"
+{
+ if (! optimize_insn_for_size_p () && sh_expand_cmpstr (operands))
+ DONE;
+ else
+ FAIL;
+})
+
+(define_expand "cmpstrnsi"
+ [(set (match_operand:SI 0 "register_operand")
+ (compare:SI (match_operand:BLK 1 "memory_operand")
+ (match_operand:BLK 2 "memory_operand")))
+ (use (match_operand:SI 3 "immediate_operand"))
+ (use (match_operand:SI 4 "immediate_operand"))]
+ "TARGET_SH1 && optimize"
+{
+ if (! optimize_insn_for_size_p () && sh_expand_cmpnstr (operands))
+ DONE;
+ else
+ FAIL;
+})
+
+(define_expand "strlensi"
+ [(set (match_operand:SI 0 "register_operand")
+ (unspec:SI [(match_operand:BLK 1 "memory_operand")
+ (match_operand:SI 2 "immediate_operand")
+ (match_operand:SI 3 "immediate_operand")]
+ UNSPEC_BUILTIN_STRLEN))]
+ "TARGET_SH1 && optimize"
+{
+ if (! optimize_insn_for_size_p () && sh_expand_strlen (operands))
+ DONE;
+ else
+ FAIL;
+})
+
;; -------------------------------------------------------------------------
;; Floating point instructions.
@@ -12078,9 +12198,9 @@ label:
[(set_attr "type" "fpscr_toggle")])
(define_expand "addsf3"
- [(set (match_operand:SF 0 "arith_reg_operand" "")
- (plus:SF (match_operand:SF 1 "arith_reg_operand" "")
- (match_operand:SF 2 "arith_reg_operand" "")))]
+ [(set (match_operand:SF 0 "fp_arith_reg_operand")
+ (plus:SF (match_operand:SF 1 "fp_arith_reg_operand")
+ (match_operand:SF 2 "fp_arith_reg_operand")))]
"TARGET_SH2E || TARGET_SHMEDIA_FPU"
{
if (TARGET_SH2E)
@@ -12327,9 +12447,9 @@ label:
[(set_attr "type" "fparith_media")])
(define_expand "divsf3"
- [(set (match_operand:SF 0 "arith_reg_operand" "")
- (div:SF (match_operand:SF 1 "arith_reg_operand" "")
- (match_operand:SF 2 "arith_reg_operand" "")))]
+ [(set (match_operand:SF 0 "fp_arith_reg_operand")
+ (div:SF (match_operand:SF 1 "fp_arith_reg_operand")
+ (match_operand:SF 2 "fp_arith_reg_operand")))]
"TARGET_SH2E || TARGET_SHMEDIA_FPU"
{
if (TARGET_SH2E)
@@ -12348,9 +12468,9 @@ label:
[(set_attr "type" "fdiv_media")])
(define_insn "divsf3_i"
- [(set (match_operand:SF 0 "arith_reg_dest" "=f")
- (div:SF (match_operand:SF 1 "arith_reg_operand" "0")
- (match_operand:SF 2 "arith_reg_operand" "f")))
+ [(set (match_operand:SF 0 "fp_arith_reg_dest" "=f")
+ (div:SF (match_operand:SF 1 "fp_arith_reg_operand" "0")
+ (match_operand:SF 2 "fp_arith_reg_operand" "f")))
(use (match_operand:PSI 3 "fpscr_operand" "c"))]
"TARGET_SH2E"
"fdiv %2,%0"
@@ -12634,9 +12754,9 @@ label:
(set_attr "fp_mode" "single")])
(define_insn "rsqrtsf2"
- [(set (match_operand:SF 0 "register_operand" "=f")
+ [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
(div:SF (match_operand:SF 1 "immediate_operand" "i")
- (sqrt:SF (match_operand:SF 2 "register_operand" "0"))))
+ (sqrt:SF (match_operand:SF 2 "fp_arith_reg_operand" "0"))))
(use (match_operand:PSI 3 "fpscr_operand" "c"))]
"TARGET_FPU_ANY && TARGET_FSRRA
&& operands[1] == CONST1_RTX (SFmode)"
@@ -12950,8 +13070,8 @@ label:
(define_insn "cmpgtdf_t"
[(set (reg:SI T_REG)
- (gt:SI (match_operand:DF 0 "arith_reg_operand" "f")
- (match_operand:DF 1 "arith_reg_operand" "f")))
+ (gt:SI (match_operand:DF 0 "fp_arith_reg_operand" "f")
+ (match_operand:DF 1 "fp_arith_reg_operand" "f")))
(use (match_operand:PSI 2 "fpscr_operand" "c"))]
"(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
"fcmp/gt %1,%0"
@@ -12960,8 +13080,8 @@ label:
(define_insn "cmpeqdf_t"
[(set (reg:SI T_REG)
- (eq:SI (match_operand:DF 0 "arith_reg_operand" "f")
- (match_operand:DF 1 "arith_reg_operand" "f")))
+ (eq:SI (match_operand:DF 0 "fp_arith_reg_operand" "f")
+ (match_operand:DF 1 "fp_arith_reg_operand" "f")))
(use (match_operand:PSI 2 "fpscr_operand" "c"))]
"(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
"fcmp/eq %1,%0"
@@ -12971,8 +13091,8 @@ label:
(define_insn "*ieee_ccmpeqdf_t"
[(set (reg:SI T_REG)
(ior:SI (reg:SI T_REG)
- (eq:SI (match_operand:DF 0 "arith_reg_operand" "f")
- (match_operand:DF 1 "arith_reg_operand" "f"))))
+ (eq:SI (match_operand:DF 0 "fp_arith_reg_operand" "f")
+ (match_operand:DF 1 "fp_arith_reg_operand" "f"))))
(use (match_operand:PSI 2 "fpscr_operand" "c"))]
"TARGET_IEEE && (TARGET_SH4 || TARGET_SH2A_DOUBLE)"
{
@@ -13030,10 +13150,9 @@ label:
DONE;
})
-
(define_expand "negdf2"
- [(set (match_operand:DF 0 "arith_reg_operand" "")
- (neg:DF (match_operand:DF 1 "arith_reg_operand" "")))]
+ [(set (match_operand:DF 0 "fp_arith_reg_operand")
+ (neg:DF (match_operand:DF 1 "fp_arith_reg_operand")))]
"(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
{
if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
@@ -13060,8 +13179,8 @@ label:
(set_attr "fp_mode" "double")])
(define_expand "sqrtdf2"
- [(set (match_operand:DF 0 "arith_reg_operand" "")
- (sqrt:DF (match_operand:DF 1 "arith_reg_operand" "")))]
+ [(set (match_operand:DF 0 "fp_arith_reg_operand")
+ (sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand")))]
"(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
{
if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
@@ -13088,8 +13207,8 @@ label:
(set_attr "fp_mode" "double")])
(define_expand "absdf2"
- [(set (match_operand:DF 0 "arith_reg_operand" "")
- (abs:DF (match_operand:DF 1 "arith_reg_operand" "")))]
+ [(set (match_operand:DF 0 "fp_arith_reg_operand")
+ (abs:DF (match_operand:DF 1 "fp_arith_reg_operand")))]
"(TARGET_SH4 || TARGET_SH2A_DOUBLE) || TARGET_SHMEDIA_FPU"
{
if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
@@ -13185,7 +13304,7 @@ label:
(match_operand:SI 1 "immediate_operand" "")
(match_operand:SI 2 "immediate_operand" ""))
(match_operand:SI 3 "general_operand" ""))]
- "TARGET_SH1 && ! TARGET_LITTLE_ENDIAN"
+ "TARGET_SH1 && TARGET_BIG_ENDIAN"
{
rtx addr_target, orig_address, shift_reg, qi_val;
HOST_WIDE_INT bitsize, size, v = 0;
@@ -14547,7 +14666,7 @@ label:
(zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 4))
(zero_extract:QI (not:QI (match_dup 2))
(const_int 2) (const_int 6))])))]
- "TARGET_SHMEDIA && ! TARGET_LITTLE_ENDIAN"
+ "TARGET_SHMEDIA && TARGET_BIG_ENDIAN"
"mperm.w %1, %N2, %0"
[(set_attr "type" "arith_media")])
diff --git a/gcc/config/sh/sh.opt b/gcc/config/sh/sh.opt
index c314e144c21..8a6788eb3d1 100644
--- a/gcc/config/sh/sh.opt
+++ b/gcc/config/sh/sh.opt
@@ -21,7 +21,7 @@
;; Used for various architecture options.
Mask(SH_E)
-;; Set if the default precision of th FPU is single.
+;; Set if the default precision of the FPU is single.
Mask(FPU_SINGLE)
;; Set if the a double-precision FPU is present but is restricted to
diff --git a/gcc/config/sh/sh_treg_combine.cc b/gcc/config/sh/sh_treg_combine.cc
new file mode 100644
index 00000000000..0f9027ec763
--- /dev/null
+++ b/gcc/config/sh/sh_treg_combine.cc
@@ -0,0 +1,1509 @@
+/* An SH specific RTL pass that tries to combine comparisons and redundant
+ condition code register stores across multiple basic blocks.
+ Copyright (C) 2013 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 "machmode.h"
+#include "basic-block.h"
+#include "df.h"
+#include "rtl.h"
+#include "insn-config.h"
+#include "insn-codes.h"
+#include "emit-rtl.h"
+#include "recog.h"
+#include "tree-pass.h"
+#include "target.h"
+#include "expr.h"
+
+#include <algorithm>
+#include <list>
+#include <vector>
+
+/*
+This pass tries to optimize for example this:
+ mov.l @(4,r4),r1
+ tst r1,r1
+ movt r1
+ tst r1,r1
+ bt/s .L5
+
+into something simpler:
+ mov.l @(4,r4),r1
+ tst r1,r1
+ bf/s .L5
+
+Such sequences can be identified by looking for conditional branches and
+checking whether the ccreg is set before the conditional branch
+by testing another register for != 0, which was set by a ccreg store.
+This can be optimized by eliminating the redundant comparison and
+inverting the branch condition. There can be multiple comparisons in
+different basic blocks that all end up in the redunant test insn before the
+conditional branch. Some example RTL ...
+
+Example 1)
+----------
+
+[bb 3]
+(set (reg:SI 147 t) (eq:SI (reg:SI 173) (const_int 0)))
+(set (reg:SI 167) (xor:SI (reg:SI 147 t) (const_int 1)))
+-> bb 5
+
+[bb 4]
+(set (reg:SI 147 t) (eq:SI (reg:SI 177) (const_int 0)))
+(set (reg:SI 167) (reg:SI 147 t))
+-> bb 5
+
+[bb 5]
+(set (reg:SI 147 t) (eq:SI (reg:SI 167) (const_int 0)))
+(set (pc) (if_then_else (ne (reg:SI 147 t) (const_int 0))
+ (label_ref:SI 50) (pc)))
+
+In [bb 4] elimination of the comparison would require inversion of the branch
+condition and compensation of other BBs.
+Instead an inverting reg-move can be used:
+
+[bb 3]
+(set (reg:SI 167) (reg:SI 173))
+-> bb 5
+
+[BB 4]
+(set (reg:SI 167) (not:SI (reg:SI 177)))
+-> bb 5
+
+[bb 5]
+(set (reg:SI 147 t) (eq:SI (reg:SI 167) (const_int 0)))
+(set (pc) (if_then_else (ne (reg:SI 147 t) (const_int 0)))
+ (label_ref:SI 50) (pc)))
+
+
+Example 2)
+----------
+
+[bb 3]
+(set (reg:SI 147 t) (gt:SI (reg:SI 173) (reg:SI 175)))
+(set (reg:SI 167) (reg:SI 147 t))
+-> bb 5
+
+[bb 4]
+(set (reg:SI 147 t) (gt:SI (reg:SI 177) (reg:SI 179)))
+(set (reg:SI 167) (reg:SI 147 t))
+-> bb 5
+
+[bb 5]
+(set (reg:SI 147 t) (eq:SI (reg:SI 167) (const_int 0)))
+(set (pc) (if_then_else (ne (reg:SI 147 t) (const_int 0))
+ (label_ref:SI 51) (pc)))
+
+The common comparison is factored out and the branch condition is inverted:
+
+[bb 3]
+(set (reg:SI 167) (reg:SI 173))
+(set (reg:SI 200) (reg:SI 175))
+-> bb 5
+
+[bb 4]
+(set (reg:SI 167) (reg:SI 177))
+(set (reg:SI 200) (reg:SI 179))
+-> bb 5
+
+[bb 5]
+(set (reg:SI 147 t) (gt:SI (reg:SI 167) (reg:SI 200)))
+(set (pc) (if_then_else (eq (reg:SI 147 t) (const_int 0))
+ (label_ref:SI 51) (pc)))
+
+
+Example 3)
+----------
+
+[bb 3]
+(set (reg:SI 147 t) (gt:SI (reg:SI 173) (reg:SI 175)))
+(set (reg:SI 167) (reg:SI 147 t))
+-> bb 5
+
+[bb 4]
+(set (reg:SI 147 t) (ge:SI (reg:SI 179) (reg:SI 177)))
+(set (reg:SI 167) (reg:SI 147 t))
+-> bb 5
+
+[bb 5]
+(set (reg:SI 147 t) (eq:SI (reg:SI 167) (const_int 0)))
+(set (pc) (if_then_else (ne (reg:SI 147 t) (const_int 0))
+ (label_ref:SI 51) (pc)))
+
+The T bit lifetime is extended and the branch condition is inverted:
+
+[bb 3]
+(set (reg:SI 147 t) (gt:SI (reg:SI 173) (reg:SI 175)))
+-> bb 5
+
+[bb 4]
+(set (reg:SI 147 t) (ge:SI (reg:SI 179) (reg:SI 177)))
+-> bb 5
+
+[bb 5]
+(set (pc) (if_then_else (eq (reg:SI 147 t) (const_int 0))
+ (label_ref:SI 51) (pc)))
+
+
+Example 4)
+----------
+
+[bb 3]
+(set (reg:SI 147 t) (eq:SI (reg:SI 173) (const_int 5)))
+(set (reg:SI 167) (reg:SI 147 t))
+-> bb 5
+
+[bb 4]
+(set (reg:SI 147 t) (eq:SI (reg:SI 176) (const_int 5)))
+(set (reg:SI 167) (xor:SI (reg:SI 147 t) (const_int 1)))
+-> bb 5
+
+[bb 5]
+(set (reg:SI 147 t) (eq:SI (reg:SI 167) (const_int 0)))
+(set (pc) (if_then_else (ne (reg:SI 147 t) (const_int 0))
+ (label_ref:SI 50) (pc)))
+
+In this case the comparisons are the same and could be combined, but the
+branch condition is different for [bb 3] and [bb 5]. Since the comparison
+is not a zero comparison, we can't negate one of the operands. The best thing
+we can do here is to eliminate the comparison before the cbranch and invert
+the ccreg in one of the BBs. On SH2A this will utilize the 'nott' instruction.
+
+[bb 3]
+(set (reg:SI 147 t) (eq:SI (reg:SI 173) (const_int 5)))
+-> bb 5
+
+[bb 4]
+(set (reg:SI 147 t) (eq:SI (reg:SI 176) (const_int 5)))
+(set (reg:SI 147 t) (xor:SI (reg:SI 147 t) (const_int 1)))
+-> bb 5
+
+[bb 5]
+(set (pc) (if_then_else (eq (reg:SI 147 t) (const_int 0)) // inverted
+ (label_ref:SI 50) (pc)))
+
+
+In order to handle cases such as above the RTL pass does the following:
+
+- Find the ccreg sets (comparisons) and ccreg stores
+ (inverting and non-inverting) in all related BBs.
+
+- If the comparison types in the BBs are all the same, try to combine the
+ comparisons in the BBs and replace the zero comparison before the cbranch
+ with the common comparison.
+
+ - If the cstores are the same, move the comparison before the cbranch
+ and replace the comparisons in the BBs with reg-reg copies to get the
+ operands in place (create new pseudo regs).
+
+ - If the cstores differ, try to apply the special case
+ (eq (reg) (const_int 0)) -> inverted = (not (reg)).
+ for the subordinate cstore types and eliminate the dominating ones.
+
+- If the comparison types in the BBs are not the same, or the first approach
+ doesn't work out for some reason, try to eliminate the comparison before the
+ cbranch by extending the lifetime of the ccreg by leaving the individual
+ comparisons but eliminating the cstores.
+ If the cstores are all the same this is straight forward.
+ If they're not, try to reverse the ccreg for the subordinate cstore type
+ and eliminate the dominating one.
+*/
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+// Helper functions
+
+#define log_msg(...)\
+ do { if (dump_file != NULL) fprintf (dump_file, __VA_ARGS__); } while (0)
+
+#define log_insn(i)\
+ do { if (dump_file != NULL) print_rtl_single (dump_file, \
+ (const_rtx)i); } while (0)
+
+#define log_rtx(r)\
+ do { if (dump_file != NULL) print_rtl (dump_file, (const_rtx)r); } while (0)
+
+#define log_return(retval, ...)\
+ do { if (dump_file != NULL) fprintf (dump_file, __VA_ARGS__); \
+ return retval; } while (0)
+
+#define log_return_void(...)\
+ do { if (dump_file != NULL) fprintf (dump_file, __VA_ARGS__); \
+ return; } while (0)
+
+struct set_of_reg
+{
+ // The insn where the search stopped or NULL_RTX.
+ rtx insn;
+
+ // The set rtx of the specified reg if found, NULL_RTX otherwise.
+ // Notice that the set rtx can also be in a parallel.
+ const_rtx set_rtx;
+
+ // The set source operand rtx if found, NULL_RTX otherwise.
+ rtx
+ set_src (void) const
+ {
+ return set_rtx == NULL_RTX ? NULL_RTX : XEXP (set_rtx, 1);
+ }
+
+ // The set destination operand rtx if found, NULL_RTX otherwise.
+ rtx
+ set_dst (void) const
+ {
+ return set_rtx == NULL_RTX ? NULL_RTX : XEXP (set_rtx, 0);
+ }
+
+ bool
+ empty (void) const
+ {
+ return insn == NULL_RTX || set_rtx == NULL_RTX;
+ }
+};
+
+// Given a reg rtx and a start insn find the insn (in the same basic block)
+// that sets the reg.
+static set_of_reg
+find_set_of_reg_bb (rtx reg, rtx insn)
+{
+ set_of_reg result = { insn, NULL_RTX };
+
+ if (!REG_P (reg) || insn == NULL_RTX)
+ return result;
+
+ for (result.insn = insn; result.insn != NULL_RTX;
+ result.insn = prev_nonnote_insn_bb (result.insn))
+ {
+ if (BARRIER_P (result.insn))
+ return result;
+ if (!NONJUMP_INSN_P (result.insn))
+ continue;
+ if (reg_set_p (reg, result.insn))
+ {
+ result.set_rtx = set_of (reg, result.insn);
+ if (result.set_rtx == NULL_RTX || GET_CODE (result.set_rtx) != SET)
+ result.set_rtx = NULL_RTX;
+ return result;
+ }
+ }
+
+ return result;
+}
+
+static bool
+reg_dead_after_insn (const_rtx reg, const_rtx insn)
+{
+ return find_regno_note (insn, REG_DEAD, REGNO (reg)) != NULL_RTX;
+}
+
+static bool
+reg_unused_after_insn (const_rtx reg, const_rtx insn)
+{
+ return find_regno_note (insn, REG_UNUSED, REGNO (reg)) != NULL_RTX;
+}
+
+// Check whether the two specified basic blocks are adjacent, i.e. there's no
+// other basic block in between them.
+static bool
+is_adjacent_bb (basic_block a, basic_block b)
+{
+ basic_block bb0[] = { a, b };
+ basic_block bb1[] = { b, a };
+
+ for (int i = 0; i < 2; ++i)
+ for (edge_iterator ei = ei_start (bb0[i]->succs);
+ !ei_end_p (ei); ei_next (&ei))
+ if (ei_edge (ei)->dest == bb1[i])
+ return true;
+
+ return false;
+}
+
+// Internal function of trace_reg_uses.
+static void
+trace_reg_uses_1 (rtx reg, rtx start_insn, basic_block bb, int& count,
+ std::vector<basic_block>& visited_bb, rtx abort_at_insn)
+{
+ if (bb == NULL)
+ return;
+
+ if (std::find (visited_bb.begin (), visited_bb.end (), bb)
+ != visited_bb.end ())
+ log_return_void ("[bb %d] already visited\n", bb->index);
+
+ visited_bb.push_back (bb);
+
+ if (BB_END (bb) == NULL_RTX)
+ log_return_void ("[bb %d] BB_END is null\n", bb->index);
+
+ if (start_insn == NULL_RTX)
+ log_return_void ("[bb %d] start_insn is null\n", bb->index);
+
+ rtx end_insn = NEXT_INSN (BB_END (bb));
+ if (end_insn == NULL_RTX)
+ log_return_void ("[bb %d] end_insn is null\n", bb->index);
+
+ for (rtx i = NEXT_INSN (start_insn); i != end_insn; i = NEXT_INSN (i))
+ {
+ if (INSN_P (i))
+ {
+ if (NONDEBUG_INSN_P (i)
+ && (reg_overlap_mentioned_p (reg, PATTERN (i))
+ || (CALL_P (i) && find_reg_fusage (i, USE, reg))))
+ {
+ log_msg ("found use in [bb %d] at insn:\n", bb->index);
+ log_insn (i);
+ log_msg ("\n");
+ count += 1;
+ }
+
+ // Stop following this BB if the reg is set or dies along the way.
+ if (reg_set_p (reg, i) || reg_dead_after_insn (reg, i))
+ return;
+ }
+
+ if (abort_at_insn != NULL_RTX && abort_at_insn == i)
+ return;
+ }
+
+ for (edge_iterator ei = ei_start (bb->succs); !ei_end_p (ei); ei_next (&ei))
+ {
+ basic_block succ_bb = ei_edge (ei)->dest;
+ trace_reg_uses_1 (reg, BB_HEAD (succ_bb), succ_bb, count, visited_bb,
+ abort_at_insn);
+ }
+}
+
+// Trace uses of the specified reg in all basic blocks that are reachable from
+// the specified insn. If 'abort_at_insn' is not null, abort the trace at
+// that insn. If the insn 'abort_at_insn' uses the specified reg, it is also
+// counted.
+static int
+trace_reg_uses (rtx reg, rtx start_insn, rtx abort_at_insn)
+{
+ log_msg ("\ntrace_reg_uses\nreg = ");
+ log_rtx (reg);
+ log_msg ("\nstart_insn = ");
+ log_insn (start_insn);
+
+ int count = 0;
+ std::vector<basic_block> visited_bb;
+ visited_bb.reserve (32);
+
+ trace_reg_uses_1 (reg, start_insn, BLOCK_FOR_INSN (start_insn),
+ count, visited_bb, abort_at_insn);
+ return count;
+}
+
+// FIXME: Remove dependency on SH predicate function somehow.
+extern int t_reg_operand (rtx, machine_mode);
+extern int negt_reg_operand (rtx, machine_mode);
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+// RTL pass class
+
+class sh_treg_combine : public rtl_opt_pass
+{
+public:
+ sh_treg_combine (gcc::context* ctx, bool split_insns, const char* name);
+ virtual ~sh_treg_combine (void);
+ virtual bool gate (void);
+ virtual unsigned int execute (void);
+
+private:
+ // Type of ccreg store that is supported.
+ enum cstore_type_t
+ {
+ cstore_normal = 0,
+ cstore_inverted = 1,
+ cstore_unknown = -1
+ };
+
+ // Type of branch condition that is supported.
+ enum branch_condition_type_t
+ {
+ branch_if_true = 1,
+ branch_if_false = 0,
+ unknown_branch_condition = -1
+ };
+
+ // For each basic block there can be a trace entry which consists of an
+ // insn that sets the ccreg (usually a comparison) and a ccreg store.
+ struct bb_entry
+ {
+ basic_block bb;
+ set_of_reg setcc;
+ set_of_reg cstore;
+ cstore_type_t cstore_type;
+ std::vector<set_of_reg> cstore_reg_reg_copies;
+
+ bb_entry (basic_block b)
+ : bb (b), setcc (), cstore (), cstore_type (cstore_unknown) { }
+
+ rtx comparison_rtx (void) const { return setcc.set_src (); }
+ };
+
+ // A ccreg trace for a conditional branch.
+ struct cbranch_trace
+ {
+ rtx cbranch_insn;
+ branch_condition_type_t cbranch_type;
+
+ // The comparison against zero right before the conditional branch.
+ set_of_reg setcc;
+
+ // All BBs that are related to the cbranch. The last BB in the list is
+ // the BB of the cbranch itself and might be empty.
+ std::list<bb_entry> bb_entries;
+
+ cbranch_trace (rtx insn)
+ : cbranch_insn (insn),
+ cbranch_type (unknown_branch_condition),
+ setcc ()
+ {
+ }
+
+ basic_block bb (void) const { return BLOCK_FOR_INSN (cbranch_insn); }
+
+ rtx
+ branch_condition_rtx (void) const
+ {
+ rtx x = pc_set (cbranch_insn);
+ return x == NULL_RTX ? NULL_RTX : XEXP (XEXP (x, 1), 0);
+ }
+
+ bool
+ can_invert_condition (void) const
+ {
+ // The branch condition can be inverted safely only if the condition
+ // reg is dead after the cbranch.
+ return reg_dead_after_insn (XEXP (branch_condition_rtx (), 0),
+ cbranch_insn);
+ }
+ };
+
+ static const pass_data default_pass_data;
+
+ // Tells whether modified or newly added insns are to be split at the end
+ // of the pass.
+ const bool m_split_insns;
+
+ // rtx of the ccreg that is obtained from the target.
+ rtx m_ccreg;
+
+ // Newly added or modified insns.
+ std::vector<rtx> m_touched_insns;
+
+ // Given an rtx determine whether it's a comparison with a constant zero.
+ static bool is_cmp_eq_zero (const_rtx i);
+
+ // Update the stored mode of the ccreg from the given branch condition rtx.
+ void update_ccreg_mode (const_rtx cond);
+
+ // Given an rtx, figure out the branch condition, assuming that it is
+ // in canonical form:
+ // (ne (reg) (const_int 0))
+ // (eq (reg) (const_int 0))
+ branch_condition_type_t branch_condition_type (const_rtx cond) const;
+
+ // Return true if the specified rtx is either a normal ccreg or
+ // a negated form of the ccreg.
+ bool is_normal_ccreg (const_rtx x) const;
+ bool is_inverted_ccreg (const_rtx x) const;
+
+ // Given a reg rtx and a start insn rtx, try to find the insn in the same
+ // basic block that sets the specified reg.
+ // Return how the search ended and the insn where it stopped or NULL_RTX.
+ enum record_return_t
+ {
+ set_found,
+ set_not_found,
+ other_set_found
+ };
+ record_return_t record_set_of_reg (rtx reg, rtx start_insn, bb_entry& e);
+
+ // Tells whether the cbranch insn of the specified bb_entry can be removed
+ // safely without triggering any side effects.
+ bool can_remove_cstore (const bb_entry& e,
+ const cbranch_trace& trace) const;
+
+ // Tells whether the setcc insn of the specified bb_entry can be removed
+ // safely without triggering any side effects.
+ bool can_remove_comparison (const bb_entry& e,
+ const cbranch_trace& trace) const;
+
+ // Tells whether the two specified comparison rtx can be combined into a
+ // single comparison.
+ bool can_combine_comparisons (const_rtx x, const_rtx y) const;
+
+ // Tells whether the ccreg usage can be extended from the bb_entry on until
+ // the final cbranch of the trace.
+ bool can_extend_ccreg_usage (const bb_entry& e,
+ const cbranch_trace& trace) const;
+
+ // Create an insn rtx that is a negating reg move (not operation).
+ rtx make_not_reg_insn (rtx dst_reg, rtx src_reg) const;
+
+ // Create an insn rtx that inverts the ccreg.
+ rtx make_inv_ccreg_insn (void) const;
+
+ // Adds the specified insn to the set of modified or newly added insns that
+ // might need splitting at the end of the pass.
+ rtx touched_insn (rtx i);
+
+ // Try to invert the branch condition of the specified trace.
+ bool try_invert_branch_condition (cbranch_trace& trace);
+
+ // Try to optimize a cbranch trace by combining comparisons in BBs and
+ // eliminate the cstores.
+ bool try_combine_comparisons (cbranch_trace& trace,
+ int cstore_count, int inv_cstore_count,
+ cstore_type_t dominating_cstore);
+
+ // Try to optimize a cbranch trace by eliminating the cstores in BBs only.
+ bool try_eliminate_cstores (cbranch_trace& trace,
+ int cstore_count, int inv_cstore_count,
+ cstore_type_t dominating_cstore);
+
+ // Given a branch insn, try to optimize its branch condition.
+ // If any insns are modified or added they are added to 'm_touched_insns'.
+ void try_optimize_cbranch (rtx i);
+};
+
+
+const pass_data sh_treg_combine::default_pass_data =
+{
+ RTL_PASS, // type
+ "", // name (overwritten by the constructor)
+ OPTGROUP_NONE, // optinfo_flags
+ true, // has_gate
+ true, // has_execute
+ TV_OPTIMIZE, // tv_id
+ 0, // properties_required
+ 0, // properties_provided
+ 0, // properties_destroyed
+ 0, // todo_flags_start
+ TODO_df_finish | TODO_df_verify // todo_flags_finish
+ | TODO_verify_rtl_sharing
+};
+
+sh_treg_combine::sh_treg_combine (gcc::context* ctx, bool split_insns,
+ const char* name)
+: rtl_opt_pass (default_pass_data, ctx),
+ m_split_insns (split_insns),
+ m_ccreg (NULL_RTX)
+{
+ // Overwrite default name in pass_data base class.
+ this->name = name;
+}
+
+sh_treg_combine::~sh_treg_combine (void)
+{
+}
+
+void sh_treg_combine::update_ccreg_mode (const_rtx cond)
+{
+ if (REG_P (XEXP (cond, 0)) && REGNO (XEXP (cond, 0)) != REGNO (m_ccreg))
+ return;
+
+ machine_mode m = GET_MODE (XEXP (cond, 0));
+ if (m == GET_MODE (m_ccreg))
+ return;
+
+ PUT_MODE (m_ccreg, m);
+ log_msg ("updated ccreg mode: ");
+ log_rtx (m_ccreg);
+ log_msg ("\n");
+}
+
+bool
+sh_treg_combine::is_cmp_eq_zero (const_rtx i)
+{
+ return i != NULL_RTX && GET_CODE (i) == EQ
+ && REG_P (XEXP (i, 0)) && XEXP (i, 1) == const0_rtx;
+}
+
+sh_treg_combine::branch_condition_type_t
+sh_treg_combine::branch_condition_type (const_rtx cond) const
+{
+ if (cond == NULL_RTX)
+ return unknown_branch_condition;
+
+ if (GET_CODE (cond) == NE
+ && REG_P (XEXP (cond, 0)) && REGNO (XEXP (cond, 0)) == REGNO (m_ccreg)
+ && XEXP (cond, 1) == const0_rtx)
+ return branch_if_true;
+
+ else if (GET_CODE (cond) == EQ
+ && REG_P (XEXP (cond, 0)) && REGNO (XEXP (cond, 0)) == REGNO (m_ccreg)
+ && XEXP (cond, 1) == const0_rtx)
+ return branch_if_false;
+
+ else
+ return unknown_branch_condition;
+}
+
+bool
+sh_treg_combine::is_normal_ccreg (const_rtx x) const
+{
+ return t_reg_operand (const_cast<rtx> (x), VOIDmode);
+}
+
+bool
+sh_treg_combine::is_inverted_ccreg (const_rtx x) const
+{
+ return negt_reg_operand (const_cast<rtx> (x), VOIDmode);
+}
+
+sh_treg_combine::record_return_t
+sh_treg_combine::record_set_of_reg (rtx reg, rtx start_insn,
+ bb_entry& new_entry)
+{
+ log_msg ("\n[bb %d]\n", new_entry.bb->index);
+
+ if (start_insn == NULL_RTX)
+ log_return (set_not_found, "set of reg not found. empty BB?\n");
+
+ new_entry.cstore_type = cstore_unknown;
+
+ for (rtx i = start_insn; i != NULL_RTX; )
+ {
+ new_entry.cstore = find_set_of_reg_bb (reg, i);
+
+ if (new_entry.cstore.set_src () == NULL_RTX)
+ log_return (set_not_found, "set of reg not found (cstore)\n");
+
+ log_insn (new_entry.cstore.insn);
+ log_msg ("\n");
+
+ if (is_normal_ccreg (new_entry.cstore.set_src ()))
+ {
+ log_msg ("normal condition store\n");
+ new_entry.cstore_type = cstore_normal;
+ }
+ else if (is_inverted_ccreg (new_entry.cstore.set_src ()))
+ {
+ log_msg ("inverted condition store\n");
+ new_entry.cstore_type = cstore_inverted;
+ }
+ else if (REG_P (new_entry.cstore.set_src ()))
+ {
+ // If it's a reg-reg copy follow the copied reg.
+ new_entry.cstore_reg_reg_copies.push_back (new_entry.cstore);
+ reg = new_entry.cstore.set_src ();
+ i = new_entry.cstore.insn;
+
+ log_msg ("reg-reg copy. tracing ");
+ log_rtx (reg);
+ log_msg ("\n");
+ continue;
+ }
+ else
+ log_return (other_set_found, "not a condition store\n");
+
+ gcc_assert (new_entry.cstore_type != cstore_unknown);
+
+ // Now see how the ccreg was set.
+ // For now it must be in the same BB.
+ log_msg ("tracing ccreg\n");
+ new_entry.setcc =
+ find_set_of_reg_bb (m_ccreg,
+ prev_nonnote_insn_bb (new_entry.cstore.insn));
+
+ // If cstore was found but setcc was not found continue anyway, as
+ // for some of the optimization types the setcc is irrelevant.
+ if (new_entry.setcc.set_src () == NULL_RTX)
+ log_return (set_found, "set of ccreg not found\n");
+
+ else if (GET_CODE (new_entry.setcc.set_rtx) == SET)
+ {
+ // Also allow insns that set the ccreg, but are not true comparison
+ // insns, as long as they are sets and not e.g. clobbers.
+ log_insn (new_entry.setcc.insn);
+ log_msg ("\n");
+ return set_found;
+ }
+ else
+ // If cstore was found but setcc was not found continue anyway, as
+ // for some of the optimization types the setcc is irrelevant.
+ log_return (set_found, "unknown set of ccreg\n");
+ }
+
+ log_return (set_not_found, "set of reg not found\n");
+}
+
+bool
+sh_treg_combine::can_remove_cstore (const bb_entry& e,
+ const cbranch_trace& trace) const
+{
+ if (volatile_insn_p (PATTERN (e.cstore.insn)))
+ {
+ log_msg ("can't remove insn\n");
+ log_insn (e.cstore.insn);
+ log_return (false, "\nbecause it's volatile\n");
+ }
+
+ // On SH there are parallel patterns which store the ccreg multiple times.
+ // In this case it's not safe.
+ rtx cstore_pat = PATTERN (e.cstore.insn);
+ if (GET_CODE (cstore_pat) == PARALLEL)
+ for (int i = 0; i < XVECLEN (cstore_pat, 0); ++i)
+ {
+ rtx x = XVECEXP (cstore_pat, 0, i);
+
+ // It's the cstore set that we're referring to, ignore that one.
+ if (x != e.cstore.set_rtx
+ && GET_CODE (x) == SET && reg_referenced_p (m_ccreg, x))
+ {
+ log_msg ("can't remove insn\n");
+ log_insn (e.cstore.insn);
+ log_return (false, "\nbecause it's a multiple ccreg store\n");
+ }
+ }
+
+ // If the cstore sets the ccreg (e.g. negc) and the ccreg is used afterwards
+ // it's not safe.
+ if (modified_in_p (m_ccreg, e.cstore.insn)
+ && !(reg_dead_after_insn (m_ccreg, e.cstore.insn)
+ || reg_unused_after_insn (m_ccreg, e.cstore.insn)))
+ {
+ log_msg ("can't remove insn\n");
+ log_insn (e.cstore.insn);
+ log_return (false, "\nbecause it sets the ccreg\n");
+ }
+
+ // If the cstore destination reg is copied around check the reg-reg
+ // copies. At every reg-reg copy the copied reg must be dead and there
+ // must not be a usage of the copied regs between the reg-reg copies.
+ // Otherwise we assume that the result of the cstore is used in some
+ // other way.
+ rtx prev_insn = e.cstore.insn;
+ for (std::vector<set_of_reg>::const_reverse_iterator i =
+ e.cstore_reg_reg_copies.rbegin ();
+ i != e.cstore_reg_reg_copies.rend (); ++i)
+ {
+ if (!reg_dead_after_insn (i->set_src (), i->insn))
+ {
+ log_msg ("can't remove insn\n");
+ log_insn (i->insn);
+ log_return (false, "\nbecause source of reg-reg copy doesn't die\n");
+ }
+
+ if (reg_used_between_p (i->set_src (), prev_insn, i->insn))
+ {
+ log_msg ("can't remove insn\n");
+ log_insn (i->insn);
+ log_return (false, "\nbecause reg %d is otherwise used\n",
+ REGNO (i->set_src ()));
+ }
+
+ prev_insn = i->insn;
+ }
+
+ // The cstore_dst reg must die after the test before the cbranch, otherwise
+ // it's not safe to remove the cstore.
+ // If the cstore destination reg is copied around check the effective
+ // destination reg of the cstore. The reg-reg copies are recorded in
+ // reverse order, i.e. the most recent reg-reg copy in the insn list
+ // comes first.
+ rtx cstore_dst = e.cstore_reg_reg_copies.empty ()
+ ? e.cstore.set_dst ()
+ : e.cstore_reg_reg_copies.front ().set_dst ();
+
+ if (!reg_dead_after_insn (cstore_dst, trace.setcc.insn))
+ {
+ log_msg ("can't remove insn\n");
+ log_insn (e.cstore.insn);
+ log_return (false, "\nbecause its effective target reg %d doesn't die "
+ "after trace.setcc.insn\n", REGNO (cstore_dst));
+ }
+
+ // Also check that the cstore_dst reg is not used in other reachable code
+ // paths before it dies.
+ // Count the uses of the effective cstore_dst reg (i.e. the last known reg
+ // that holds the cstore value after reg-reg copies) in all BBs that can be
+ // reached from bb_entry's BB including the BB of the cstore insn.
+ // If we get more than 1 uses we assume that it's used somewhere else and is
+ // not safe to be removed.
+ int cstore_dst_use_count = trace_reg_uses (cstore_dst, e.cstore.insn,
+ trace.setcc.insn);
+ if (cstore_dst_use_count > 1)
+ {
+ log_msg ("can't remove insn\n");
+ log_insn (e.cstore.insn);
+ log_return (false, "\nbecause its effective target reg %d is used "
+ "in %d other places\n", REGNO (cstore_dst),
+ cstore_dst_use_count - 1);
+ }
+
+ return true;
+}
+
+bool
+sh_treg_combine::can_remove_comparison (const bb_entry& e,
+ const cbranch_trace&/* trace*/) const
+{
+ // If the ccreg is used otherwise between the comparison and the cstore,
+ // it's not safe.
+ if (reg_used_between_p (m_ccreg, e.setcc.insn, e.cstore.insn))
+ {
+ log_msg ("can't remove insn\n");
+ log_insn (e.setcc.insn);
+ log_return (false, "\nbecause the ccreg is used otherwise\n");
+ }
+
+ if (!reg_dead_after_insn (m_ccreg, e.cstore.insn)
+ && !reg_unused_after_insn (m_ccreg, e.cstore.insn))
+ {
+ log_msg ("can't remove insn\n");
+ log_insn (e.cstore.insn);
+ log_return (false, "\nbecause ccreg is not dead or unused afterwards\n");
+ }
+
+ // On SH there are also multiple set patterns that can be used for
+ // comparisons, such as "shll". It's not safe to remove those.
+ if (multiple_sets (e.setcc.insn))
+ {
+ log_msg ("can't remove insn\n");
+ log_insn (e.cstore.insn);
+ log_return (false, "\nbecause it's a multiple set\n");
+ }
+
+ return true;
+}
+
+rtx
+sh_treg_combine::make_not_reg_insn (rtx dst_reg, rtx src_reg) const
+{
+ // This will to go through expanders and may output multiple insns
+ // for multi-word regs.
+ start_sequence ();
+ expand_simple_unop (GET_MODE (dst_reg), NOT, src_reg, dst_reg, 0);
+ rtx i = get_insns ();
+ end_sequence ();
+ return i;
+}
+
+rtx
+sh_treg_combine::make_inv_ccreg_insn (void) const
+{
+ start_sequence ();
+ rtx i = emit_insn (gen_rtx_SET (VOIDmode, m_ccreg,
+ gen_rtx_fmt_ee (XOR, GET_MODE (m_ccreg),
+ m_ccreg, const1_rtx)));
+ end_sequence ();
+ return i;
+}
+
+rtx
+sh_treg_combine::touched_insn (rtx i)
+{
+ m_touched_insns.push_back (i);
+ return i;
+}
+
+bool
+sh_treg_combine::can_combine_comparisons (const_rtx x, const_rtx y) const
+{
+ if (GET_CODE (x) != GET_CODE (y))
+ return false;
+
+ rtx x_op0 = XEXP (x, 0);
+ rtx x_op1 = XEXP (x, 1);
+
+ rtx y_op0 = XEXP (y, 0);
+ rtx y_op1 = XEXP (y, 1);
+
+ if (!REG_P (x_op0) || !REG_P (y_op0))
+ return false;
+
+ if (GET_MODE (x_op0) != GET_MODE (y_op0))
+ return false;
+
+ // rtx_equal_p also compares the reg numbers which we do not care about
+ // here, as long as both are regs and the modes are the same.
+ if (REG_P (x_op1))
+ return REG_P (y_op1) && GET_MODE (x_op1) == GET_MODE (y_op1);
+
+ return rtx_equal_p (x_op1, y_op1);
+}
+
+bool
+sh_treg_combine::can_extend_ccreg_usage (const bb_entry& e,
+ const cbranch_trace& trace) const
+{
+ // Check if the ccreg is not modified by other insins in the BB path until
+ // the final cbranch of the trace.
+ // Start checking after the cstore that follows the setcc, assuming that
+ // the cstore will be removed.
+
+ // The assumption here is that the specified bb_entry's BB is a direct
+ // predecessor of the trace.cbranch_insn's BB.
+ if (e.bb != trace.bb () && !is_adjacent_bb (e.bb, trace.bb ()))
+ log_return (false,
+ "can't extend ccreg usage -- [bb %d] and [bb %d] are not adjacent\n",
+ e.bb->index, trace.bb ()->index);
+
+ if (e.cstore.empty ())
+ log_return (false, "can't extend ccreg usage -- no cstore\n");
+
+ // The entry's cstore is in the same BB as the final cbranch.
+ if (e.bb == trace.bb ())
+ {
+ if (reg_set_between_p (m_ccreg, e.cstore.insn, trace.setcc.insn))
+ log_return (false,
+ "can't extend ccreg usage -- it's modified between e.cstore.insn "
+ "and trace.setcc.insn");
+ else
+ return true;
+ }
+
+ // The entry's cstore and the final cbranch are in different BBs.
+ if (reg_set_between_p (m_ccreg, e.cstore.insn, NEXT_INSN (BB_END (e.bb))))
+ log_return (false,
+ "can't extend ccreg usage -- it's modified in [bb %d]", e.bb->index);
+
+ if (reg_set_between_p (m_ccreg, PREV_INSN (BB_HEAD (trace.bb ())),
+ trace.setcc.insn))
+ log_return (false,
+ "can't extend ccreg usage -- it's modified in [bb %d]",
+ trace.bb ()->index);
+
+ return true;
+}
+
+bool
+sh_treg_combine::try_invert_branch_condition (cbranch_trace& trace)
+{
+ log_msg ("inverting branch condition\n");
+
+ if (!invert_jump_1 (trace.cbranch_insn, JUMP_LABEL (trace.cbranch_insn)))
+ log_return (false, "invert_jump_1 failed\n");
+
+ if (verify_changes (num_validated_changes ()))
+ confirm_change_group ();
+ else
+ log_return (false, "verify_changed failed\n");
+
+ touched_insn (trace.cbranch_insn);
+ return true;
+}
+
+bool
+sh_treg_combine::try_combine_comparisons (cbranch_trace& trace,
+ int cstore_count,
+ int inv_cstore_count,
+ cstore_type_t dominating_cstore)
+{
+ log_msg ("\ntry_combine_comparisons\n");
+
+ // This function will always try to create new pseudos.
+ if (!can_create_pseudo_p ())
+ log_return (false, "can't create pseudos\n");
+
+ // Check that all ccset insns are comparisons and all comparison types in
+ // all BBs are the same and could be combined into one single comparison.
+ rtx comp = NULL_RTX;
+ rtx comp_insn = NULL_RTX;
+
+ for (std::list<bb_entry>::const_iterator i = trace.bb_entries.begin ();
+ i != trace.bb_entries.end (); ++i)
+ {
+ int i_empty_count = i->setcc.empty () + i->cstore.empty ();
+
+ // A completly empty entry is OK (could be the BB of the cbranch).
+ if (i_empty_count == 2)
+ continue;
+
+ // Otherwise we need both, the setcc and the cstore.
+ if (i_empty_count != 0)
+ log_return (false, "bb entry is not a setcc cstore pair\n");
+
+ rtx other_comp = i->comparison_rtx ();
+
+ if (!COMPARISON_P (other_comp))
+ {
+ log_msg ("setcc is not a comparison:\n");
+ log_rtx (other_comp);
+ log_return (false, "\n");
+ }
+
+ if (comp_insn == NULL_RTX)
+ {
+ comp = other_comp;
+ comp_insn = i->setcc.insn;
+ }
+ else if (!can_combine_comparisons (comp, other_comp))
+ return false;
+
+ // The goal here is to eliminate all cstores and comparisons in the BBs.
+ // Thus check if every cstore can actually be removed safely.
+ if (!can_remove_cstore (*i, trace) || !can_remove_comparison (*i, trace))
+ return false;
+ }
+
+ // FIXME: The first operand of the comparison must be a simple reg.
+ // This effectively prohibits combining div0s comparisons such as
+ // (lt:SI (xor:SI (reg:SI) (reg:SI)))
+ if (!REG_P (XEXP (comp, 0)))
+ {
+ log_msg ("comparison operand 0\n");
+ log_rtx (XEXP (comp, 0));
+ log_return (false, "\nis not a reg\n");
+ }
+
+ rtx comp_op0 = gen_reg_rtx (GET_MODE (XEXP (comp, 0)));
+ rtx comp_op1 = REG_P (XEXP (comp, 1))
+ ? gen_reg_rtx (GET_MODE (XEXP (comp, 1)))
+ : XEXP (comp, 1);
+
+ // If there are both, inverting and non-inverting cstores, they can only
+ // be eliminated if the comparison can be inverted. We assume that the
+ // comparison insns that we find are already minimal and canonicalized.
+ // There is one special case though, where an integer comparison
+ // (eq (reg) (const_int 0))
+ // can be inverted with a sequence
+ // (eq (not (reg)) (const_int 0))
+ if (inv_cstore_count != 0 && cstore_count != 0)
+ {
+ if (make_not_reg_insn (comp_op0, comp_op0) == NULL_RTX)
+ log_return (false, "make_not_reg_insn failed.\n");
+
+ for (std::list<bb_entry>::const_iterator i = trace.bb_entries.begin ();
+ i != trace.bb_entries.end (); ++i)
+ {
+ if (i->setcc.empty () || i->cstore.empty ())
+ continue;
+
+ if (i->cstore_type != dominating_cstore
+ && !is_cmp_eq_zero (i->comparison_rtx ()))
+ {
+ log_msg ("can't invert comparison in insn\n");
+ log_insn (i->setcc.insn);
+ log_return (false,
+ "\nbecause it's not a (eq (reg) (const_int 0))\n");
+ }
+ }
+ }
+
+ if (dominating_cstore == cstore_normal
+ && !try_invert_branch_condition (trace))
+ return false;
+
+ // Replace the test insn before the cbranch with the common comparison.
+ // Instead of creating a new insn from scratch we copy the common comparison
+ // pattern. This simplifies handling parallel comparison patterns, such as
+ // FP comparisons on SH, which have an extra use on FPSCR.
+ log_msg ("installing common comparison in [bb %d]\n", trace.bb ()->index);
+
+ rtx common_comp_pat = copy_rtx (PATTERN (comp_insn));
+ rtx common_comp = const_cast<rtx> (set_of (m_ccreg, common_comp_pat));
+
+ gcc_assert (common_comp != NULL_RTX);
+
+ XEXP (XEXP (common_comp, 1), 0) = comp_op0;
+ XEXP (XEXP (common_comp, 1), 1) = comp_op1;
+
+ log_rtx (common_comp_pat);
+ log_msg ("\n");
+
+ rtx common_comp_insn = touched_insn (emit_insn_after (common_comp_pat,
+ trace.setcc.insn));
+
+ if (REG_P (comp_op0))
+ add_reg_note (common_comp_insn, REG_DEAD, copy_rtx (comp_op0));
+ if (REG_P (comp_op1))
+ add_reg_note (common_comp_insn, REG_DEAD, copy_rtx (comp_op1));
+
+ delete_insn (trace.setcc.insn);
+
+ // Replace comparison and cstore insns with reg-reg moves in all BBs.
+ for (std::list<bb_entry>::const_iterator i = trace.bb_entries.begin ();
+ i != trace.bb_entries.end (); ++i)
+ {
+ if (i->setcc.empty () || i->cstore.empty ())
+ continue;
+
+ rtx i_comp_op0 = XEXP (i->comparison_rtx (), 0);
+ rtx i_comp_op1 = XEXP (i->comparison_rtx (), 1);
+
+ if (i->cstore_type == dominating_cstore)
+ {
+ log_msg ("replacing comparison and cstore with reg move "
+ "in [bb %d]\n", i->bb->index);
+
+ rtx new_i = touched_insn (
+ emit_insn_after (gen_move_insn (comp_op0, i_comp_op0),
+ i->setcc.insn));
+
+ if (REG_P (i_comp_op0)
+ && reg_dead_after_insn (i_comp_op0, i->setcc.insn))
+ add_reg_note (new_i, REG_DEAD, copy_rtx (i_comp_op0));
+
+ // If the second operand is a reg, have to emit a move insn.
+ // Otherwise assume it's a const_int and just reference it.
+ if (REG_P (comp_op1))
+ {
+ new_i = touched_insn (
+ emit_insn_after (gen_move_insn (comp_op1, i_comp_op1),
+ i->setcc.insn));
+
+ if (reg_dead_after_insn (i_comp_op1, i->setcc.insn))
+ add_reg_note (new_i, REG_DEAD, copy_rtx (i_comp_op1));
+ }
+ }
+ else
+ {
+ log_msg ("replacing comparison and cstore with inverting reg move "
+ "in [bb %d]\n", i->bb->index);
+
+ rtx new_i = make_not_reg_insn (comp_op0, i_comp_op0);
+ if (REG_P (i_comp_op0)
+ && reg_dead_after_insn (i_comp_op0, i->setcc.insn))
+ add_reg_note (new_i, REG_DEAD, copy_rtx (i_comp_op0));
+
+ touched_insn (emit_insn_after (new_i, i->setcc.insn));
+ }
+
+ delete_insn (i->cstore.insn);
+ delete_insn (i->setcc.insn);
+ }
+
+ return true;
+}
+
+bool
+sh_treg_combine::try_eliminate_cstores (cbranch_trace& trace,
+ int cstore_count, int inv_cstore_count,
+ cstore_type_t dominating_cstore)
+{
+ log_msg ("\ntry_eliminate_cstores\n");
+
+ for (std::list<bb_entry>::const_iterator i = trace.bb_entries.begin ();
+ i != trace.bb_entries.end (); ++i)
+ {
+ // A completly empty entry is OK (could be the BB of the cbranch).
+ if (i->setcc.empty () && i->cstore.empty ())
+ continue;
+
+ // We're going to eliminate cstores, but for that they have to be
+ // there. We don't care about the setcc in this case.
+ if (i->cstore.empty ())
+ log_return (false, "bb entry cstore empty -- aborting\n");
+
+ // The goal here is to eliminate all cstores in the BBs and extend the
+ // ccreg usage.
+ if (!can_extend_ccreg_usage (*i, trace))
+ return false;
+
+ // If the cstore can't be removed we can keep it around as long as
+ // it doesn't modify the ccreg.
+ if (!can_remove_cstore (*i, trace)
+ && modified_in_p (m_ccreg, i->cstore.insn))
+ log_return (false, "cstore sets ccreg -- aborting\n");
+ }
+
+ // If there are both, inverting and non-inverting cstores, we'll have to
+ // invert the ccreg as a replacement for one of them.
+ if (cstore_count != 0 && inv_cstore_count != 0)
+ {
+ rtx i = make_inv_ccreg_insn ();
+ if (recog_memoized (i) < 0)
+ {
+ log_msg ("failed to match ccreg inversion insn:\n");
+ log_rtx (PATTERN (i));
+ log_return (false, "\naborting\n");
+ }
+ }
+
+ if (dominating_cstore == cstore_normal
+ && !try_invert_branch_condition (trace))
+ return false;
+
+ // Eliminate cstores in all BBs.
+ for (std::list<bb_entry>::const_iterator i = trace.bb_entries.begin ();
+ i != trace.bb_entries.end (); ++i)
+ {
+ if (i->cstore.empty ())
+ continue;
+
+ if (i->cstore_type == dominating_cstore)
+ log_msg ("removing cstore in [bb %d]\n", i->bb->index);
+ else
+ {
+ log_msg ("replacing cstore with ccreg inversion in [bb %d]\n",
+ i->bb->index);
+
+ touched_insn (
+ emit_insn_after (make_inv_ccreg_insn (), i->cstore.insn));
+ }
+
+ if (can_remove_cstore (*i, trace))
+ delete_insn (i->cstore.insn);
+ }
+
+ log_msg ("removing test insn before cbranch\n");
+ delete_insn (trace.setcc.insn);
+ return true;
+}
+
+void
+sh_treg_combine::try_optimize_cbranch (rtx insn)
+{
+ cbranch_trace trace (insn);
+
+ log_msg ("\n\n--------------------------------------\n");
+ log_msg ("found cbranch insn in [bb %d]:\n", trace.bb ()->index);
+ log_insn (insn);
+
+ trace.cbranch_type = branch_condition_type (trace.branch_condition_rtx ());
+
+ if (trace.cbranch_type == branch_if_true)
+ log_msg ("condition: branch if true\n");
+ else if (trace.cbranch_type == branch_if_false)
+ log_msg ("condition: branch if false\n");
+ else
+ {
+ log_msg ("unknown branch condition\n");
+ log_rtx (trace.branch_condition_rtx ());
+ log_return_void ("\n");
+ }
+
+ update_ccreg_mode (trace.branch_condition_rtx ());
+
+ // Scan the insns backwards for an insn that sets the ccreg by testing a
+ // reg against zero like
+ // (set (reg ccreg) (eq (reg) (const_int 0)))
+ // The testing insn could also be outside of the current basic block, but
+ // for now we limit the search to the current basic block.
+ trace.setcc = find_set_of_reg_bb (m_ccreg, prev_nonnote_insn_bb (insn));
+
+ if (!is_cmp_eq_zero (trace.setcc.set_src ()))
+ log_return_void ("could not find set of ccreg in current BB\n");
+
+ rtx trace_reg = XEXP (trace.setcc.set_src (), 0);
+
+ log_msg ("set of ccreg:\n");
+ log_insn (trace.setcc.insn);
+
+ // See if we can remove the trace.setcc insn safely.
+ if (reg_used_between_p (m_ccreg, trace.setcc.insn, trace.cbranch_insn))
+ log_return_void ("ccreg used between testing insn and branch insn\n");
+
+ if (volatile_insn_p (PATTERN (trace.setcc.insn)))
+ {
+ log_msg ("can't remove insn\n");
+ log_insn (trace.setcc.insn);
+ log_return_void ("\nbecause it's volatile\n");
+ }
+
+ // Now that we have an insn which tests some reg and sets the condition
+ // reg before the conditional branch, try to figure out how that tested
+ // reg was formed, i.e. find all the insns that set the tested reg in
+ // some way.
+ // The tested reg might be set in multiple basic blocks so we need to
+ // check all basic blocks which can reach this current basic block.
+ // If the set of reg is an inverting or non-inverting store of the condition
+ // register, check how the ccreg value was obtained.
+ log_msg ("\ntracing ");
+ log_rtx (trace_reg);
+ log_msg ("\n");
+
+
+ // First check the basic block where the conditional branch is in.
+ // If we find it here there's no point in checking other BBs.
+ trace.bb_entries.push_front (bb_entry (trace.bb ()));
+
+ record_return_t res =
+ record_set_of_reg (trace_reg, prev_nonnote_insn_bb (trace.setcc.insn),
+ trace.bb_entries.front ());
+
+ if (res == other_set_found)
+ log_return_void ("other set found - aborting trace\n");
+ else if (res == set_not_found)
+ {
+ // It seems the initial search in the BB of the conditional branch
+ // didn't find anything. Now look in all predecessor BBs.
+ for (edge_iterator ei = ei_start (trace.bb ()->preds);
+ !ei_end_p (ei); ei_next (&ei))
+ {
+ edge e = ei_edge (ei);
+ trace.bb_entries.push_front (bb_entry (e->src));
+
+ res = record_set_of_reg (trace_reg, BB_END (e->src),
+ trace.bb_entries.front ());
+ if (res != set_found)
+ log_return_void ("set not found - aborting trace\n");
+ }
+ }
+
+ if (dump_file != NULL)
+ {
+ log_msg ("\ncbranch trace summary:\n");
+ for (std::list<bb_entry>::const_iterator i = trace.bb_entries.begin ();
+ i != trace.bb_entries.end (); ++i)
+ {
+ log_msg ("\n[bb %d]\n", i->bb->index);
+ if (!i->setcc.empty ())
+ {
+ log_rtx (i->setcc.set_rtx);
+ log_msg ("\n");
+ }
+ if (!i->cstore.empty ())
+ {
+ log_rtx (i->cstore.set_rtx);
+ log_msg ("\n");
+ }
+
+ for (std::vector<set_of_reg>::const_reverse_iterator j =
+ i->cstore_reg_reg_copies.rbegin ();
+ j != i->cstore_reg_reg_copies.rend (); ++j)
+ {
+ log_rtx (j->set_rtx);
+ log_msg ("\n");
+ }
+ }
+
+ log_rtx (trace.setcc.set_rtx);
+ log_msg ("\n");
+ log_rtx (PATTERN (trace.cbranch_insn));
+ log_msg ("\n");
+ }
+
+ // Check that we don't have any empty BBs.
+ // Only the BB with the cbranch may be empty.
+ for (std::list<bb_entry>::const_iterator i = trace.bb_entries.begin ();
+ i != trace.bb_entries.end (); ++i)
+ if (i->setcc.empty () && i->cstore.empty () && i->bb != trace.bb ())
+ log_return_void ("\n[bb %d] is empty - aborting.\n", i->bb->index);
+
+ // Determine the dominating cstore type
+ // FIXME: Try to take the probabilities of the BBs into account somehow.
+ int cstore_count = 0;
+ int inv_cstore_count = 0;
+
+ for (std::list<bb_entry>::const_iterator i = trace.bb_entries.begin ();
+ i != trace.bb_entries.end (); ++i)
+ {
+ if (i->cstore_type == cstore_normal)
+ cstore_count += 1;
+ else if (i->cstore_type == cstore_inverted)
+ inv_cstore_count += 1;
+ }
+
+ log_msg ("cstore count = %d inverted cstore count = %d\n",
+ cstore_count, inv_cstore_count);
+
+ // This puts a priority on inverting cstores.
+ cstore_type_t dominating_cstore = inv_cstore_count >= cstore_count
+ ? cstore_inverted
+ : cstore_normal;
+
+ if (dominating_cstore == cstore_inverted)
+ log_msg ("will try to eliminate inverted cstore\n");
+ else if (dominating_cstore == cstore_normal)
+ {
+ log_msg ("will try to eliminate normal cstore\n");
+ if (!trace.can_invert_condition ())
+ log_return_void ("branch condition can't be inverted - aborting\n");
+ }
+ else
+ gcc_unreachable ();
+
+ if (try_combine_comparisons (trace, cstore_count, inv_cstore_count,
+ dominating_cstore))
+ return;
+
+ try_eliminate_cstores (trace, cstore_count, inv_cstore_count,
+ dominating_cstore);
+}
+
+bool
+sh_treg_combine::gate (void)
+{
+ return optimize > 0;
+}
+
+unsigned int
+sh_treg_combine::execute (void)
+{
+ unsigned int ccr0 = INVALID_REGNUM;
+ unsigned int ccr1 = INVALID_REGNUM;
+
+ if (targetm.fixed_condition_code_regs (&ccr0, &ccr1)
+ && ccr0 != INVALID_REGNUM)
+ {
+ // Initially create a reg rtx with VOIDmode.
+ // When the first conditional branch is discovered, the mode is changed
+ // to the mode that is actually used by the target.
+ m_ccreg = gen_rtx_REG (VOIDmode, ccr0);
+ }
+
+ if (m_ccreg == NULL_RTX)
+ log_return (0, "no ccreg.\n\n");
+
+ if (STORE_FLAG_VALUE != 1)
+ log_return (0, "unsupported STORE_FLAG_VALUE %d", STORE_FLAG_VALUE);
+
+ log_msg ("ccreg: ");
+ log_rtx (m_ccreg);
+ log_msg (" STORE_FLAG_VALUE = %d\n", STORE_FLAG_VALUE);
+
+ // Look for basic blocks that end with a conditional branch and try to
+ // optimize them.
+ basic_block bb;
+ FOR_EACH_BB (bb)
+ {
+ rtx i = BB_END (bb);
+ if (any_condjump_p (i) && onlyjump_p (i))
+ try_optimize_cbranch (i);
+ }
+
+ log_msg ("\n\n");
+
+ // If new insns are created and this pass is executed after all insns
+ // have been split already, we must split the insns we've changed or added
+ // ourselves here.
+ // FIXME: Multi-word operations (which emit multiple insns) are not handled
+ // properly here, since only one insn will end up in 'm_touched_insns'.
+ // On SH this is not a problem though.
+ if (m_split_insns)
+ for (std::vector<rtx>::const_iterator i = m_touched_insns.begin ();
+ i != m_touched_insns.end (); ++i)
+ {
+ log_msg ("trying to split insn:\n");
+ log_insn (*i);
+ log_msg ("\n");
+ try_split (PATTERN (*i), *i, 0);
+ }
+
+ m_touched_insns.clear ();
+ log_return (0, "\n\n");
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+// This allows instantiating the pass somewhere else without having to pull
+// in a header file.
+opt_pass*
+make_pass_sh_treg_combine (gcc::context* ctx, bool split_insns,
+ const char* name)
+{
+ return new sh_treg_combine (ctx, split_insns, name);
+}
diff --git a/gcc/config/sh/t-sh b/gcc/config/sh/t-sh
index a7e028dc0cf..710bc873e75 100644
--- a/gcc/config/sh/t-sh
+++ b/gcc/config/sh/t-sh
@@ -16,11 +16,19 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
+sh-mem.o: $(srcdir)/config/sh/sh-mem.cc \
+ $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(TM_H) $(TM_P_H)
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
+
sh-c.o: $(srcdir)/config/sh/sh-c.c \
$(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(TM_H) $(TM_P_H) coretypes.h
$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
$(srcdir)/config/sh/sh-c.c
+sh_treg_combine.o: $(srcdir)/config/sh/sh_treg_combine.cc \
+ $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(TM_H) $(TM_P_H) coretypes.h
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
+
DEFAULT_ENDIAN = $(word 1,$(TM_ENDIAN_CONFIG))
OTHER_ENDIAN = $(word 2,$(TM_ENDIAN_CONFIG))
diff --git a/gcc/config/sol2.h b/gcc/config/sol2.h
index b606595dfe9..749e16830e3 100644
--- a/gcc/config/sol2.h
+++ b/gcc/config/sol2.h
@@ -194,11 +194,6 @@ along with GCC; see the file COPYING3. If not see
#endif /* HAVE_LD_EH_FRAME && TARGET_DL_ITERATE_PHDR */
#endif
-#ifndef USE_GLD
-/* The default MFLIB_SPEC is GNU ld specific. */
-#define MFLIB_SPEC ""
-#endif
-
/* collect2.c can only parse GNU nm -n output. Solaris nm needs -png to
produce the same format. */
#define NM_FLAGS "-png"
diff --git a/gcc/config/sparc/sparc-protos.h b/gcc/config/sparc/sparc-protos.h
index a0c1a7a05f4..03f83b87b28 100644
--- a/gcc/config/sparc/sparc-protos.h
+++ b/gcc/config/sparc/sparc-protos.h
@@ -81,7 +81,9 @@ extern const char *output_probe_stack_range (rtx, rtx);
extern const char *output_cbcond (rtx, rtx, rtx);
extern bool emit_scc_insn (rtx []);
extern void emit_conditional_branch_insn (rtx []);
+extern int registers_ok_for_ldd_peep (rtx, rtx);
extern int mems_ok_for_ldd_peep (rtx, rtx, rtx);
+extern rtx widen_mem_for_ldd_peep (rtx, rtx, enum machine_mode);
extern int empty_delay_slot (rtx);
extern int emit_cbcond_nop (rtx);
extern int eligible_for_return_delay (rtx);
@@ -95,7 +97,6 @@ extern int mem_min_alignment (rtx, int);
extern int pic_address_needs_scratch (rtx);
extern int register_ok_for_ldd (rtx);
extern int memory_ok_for_ldd (rtx);
-extern int registers_ok_for_ldd_peep (rtx, rtx);
extern int v9_regcmp_p (enum rtx_code);
/* Function used for V8+ code generation. Returns 1 if the high
32 bits of REG are 0 before INSN. */
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index e5b4662512d..0eabd5b2b72 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -5362,8 +5362,17 @@ sparc_expand_prologue (void)
if (flag_stack_usage_info)
current_function_static_stack_size = size;
- if (flag_stack_check == STATIC_BUILTIN_STACK_CHECK && size)
- sparc_emit_probe_stack_range (STACK_CHECK_PROTECT, size);
+ if (flag_stack_check == STATIC_BUILTIN_STACK_CHECK)
+ {
+ if (crtl->is_leaf && !cfun->calls_alloca)
+ {
+ if (size > PROBE_INTERVAL && size > STACK_CHECK_PROTECT)
+ sparc_emit_probe_stack_range (STACK_CHECK_PROTECT,
+ size - STACK_CHECK_PROTECT);
+ }
+ else if (size > 0)
+ sparc_emit_probe_stack_range (STACK_CHECK_PROTECT, size);
+ }
if (size == 0)
; /* do nothing. */
@@ -5464,8 +5473,17 @@ sparc_flat_expand_prologue (void)
if (flag_stack_usage_info)
current_function_static_stack_size = size;
- if (flag_stack_check == STATIC_BUILTIN_STACK_CHECK && size)
- sparc_emit_probe_stack_range (STACK_CHECK_PROTECT, size);
+ if (flag_stack_check == STATIC_BUILTIN_STACK_CHECK)
+ {
+ if (crtl->is_leaf && !cfun->calls_alloca)
+ {
+ if (size > PROBE_INTERVAL && size > STACK_CHECK_PROTECT)
+ sparc_emit_probe_stack_range (STACK_CHECK_PROTECT,
+ size - STACK_CHECK_PROTECT);
+ }
+ else if (size > 0)
+ sparc_emit_probe_stack_range (STACK_CHECK_PROTECT, size);
+ }
if (sparc_save_local_in_regs_p)
emit_save_or_restore_local_in_regs (stack_pointer_rtx, SPARC_STACK_BIAS,
@@ -7724,7 +7742,7 @@ output_cbranch (rtx op, rtx dest, int label, int reversed, int annul,
if (*labelno && insn && (note = find_reg_note (insn, REG_BR_PROB, NULL_RTX)))
{
strcpy (p,
- ((INTVAL (XEXP (note, 0)) >= REG_BR_PROB_BASE / 2) ^ far)
+ ((XINT (note, 0) >= REG_BR_PROB_BASE / 2) ^ far)
? ",pt" : ",pn");
p += 3;
spaces -= 3;
@@ -8195,7 +8213,7 @@ output_v9branch (rtx op, rtx dest, int reg, int label, int reversed,
if (insn && (note = find_reg_note (insn, REG_BR_PROB, NULL_RTX)))
{
strcpy (p,
- ((INTVAL (XEXP (note, 0)) >= REG_BR_PROB_BASE / 2) ^ far)
+ ((XINT (note, 0) >= REG_BR_PROB_BASE / 2) ^ far)
? ",pt" : ",pn");
p += 3;
}
@@ -8543,6 +8561,16 @@ mems_ok_for_ldd_peep (rtx mem1, rtx mem2, rtx dependent_reg_rtx)
return 1;
}
+/* Return the widened memory access made of MEM1 and MEM2 in MODE. */
+
+rtx
+widen_mem_for_ldd_peep (rtx mem1, rtx mem2, enum machine_mode mode)
+{
+ rtx x = widen_memory_access (mem1, mode, 0);
+ MEM_NOTRAP_P (x) = MEM_NOTRAP_P (mem1) && MEM_NOTRAP_P (mem2);
+ return x;
+}
+
/* Return 1 if reg is a pseudo, or is the first register in
a hard register pair. This makes it suitable for use in
ldd and std insns. */
diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md
index 174a6b1ea5f..be7bbe977a2 100644
--- a/gcc/config/sparc/sparc.md
+++ b/gcc/config/sparc/sparc.md
@@ -6971,9 +6971,10 @@
(const_int 0))]
"TARGET_V9
&& mems_ok_for_ldd_peep (operands[0], operands[1], NULL_RTX)"
- [(set (match_dup 0)
- (const_int 0))]
- "operands[0] = widen_memory_access (operands[0], DImode, 0);")
+ [(set (match_dup 0) (const_int 0))]
+{
+ operands[0] = widen_mem_for_ldd_peep (operands[0], operands[1], DImode);
+})
(define_peephole2
[(set (match_operand:SI 0 "memory_operand" "")
@@ -6982,9 +6983,10 @@
(const_int 0))]
"TARGET_V9
&& mems_ok_for_ldd_peep (operands[1], operands[0], NULL_RTX)"
- [(set (match_dup 1)
- (const_int 0))]
- "operands[1] = widen_memory_access (operands[1], DImode, 0);")
+ [(set (match_dup 1) (const_int 0))]
+{
+ operands[1] = widen_mem_for_ldd_peep (operands[1], operands[0], DImode);
+})
(define_peephole2
[(set (match_operand:SI 0 "register_operand" "")
@@ -6993,10 +6995,11 @@
(match_operand:SI 3 "memory_operand" ""))]
"registers_ok_for_ldd_peep (operands[0], operands[2])
&& mems_ok_for_ldd_peep (operands[1], operands[3], operands[0])"
- [(set (match_dup 0)
- (match_dup 1))]
- "operands[1] = widen_memory_access (operands[1], DImode, 0);
- operands[0] = gen_rtx_REG (DImode, REGNO (operands[0]));")
+ [(set (match_dup 0) (match_dup 1))]
+{
+ operands[1] = widen_mem_for_ldd_peep (operands[1], operands[3], DImode);
+ operands[0] = gen_rtx_REG (DImode, REGNO (operands[0]));
+})
(define_peephole2
[(set (match_operand:SI 0 "memory_operand" "")
@@ -7005,10 +7008,11 @@
(match_operand:SI 3 "register_operand" ""))]
"registers_ok_for_ldd_peep (operands[1], operands[3])
&& mems_ok_for_ldd_peep (operands[0], operands[2], NULL_RTX)"
- [(set (match_dup 0)
- (match_dup 1))]
- "operands[0] = widen_memory_access (operands[0], DImode, 0);
- operands[1] = gen_rtx_REG (DImode, REGNO (operands[1]));")
+ [(set (match_dup 0) (match_dup 1))]
+{
+ operands[0] = widen_mem_for_ldd_peep (operands[0], operands[2], DImode);
+ operands[1] = gen_rtx_REG (DImode, REGNO (operands[1]));
+})
(define_peephole2
[(set (match_operand:SF 0 "register_operand" "")
@@ -7017,10 +7021,11 @@
(match_operand:SF 3 "memory_operand" ""))]
"registers_ok_for_ldd_peep (operands[0], operands[2])
&& mems_ok_for_ldd_peep (operands[1], operands[3], operands[0])"
- [(set (match_dup 0)
- (match_dup 1))]
- "operands[1] = widen_memory_access (operands[1], DFmode, 0);
- operands[0] = gen_rtx_REG (DFmode, REGNO (operands[0]));")
+ [(set (match_dup 0) (match_dup 1))]
+{
+ operands[1] = widen_mem_for_ldd_peep (operands[1], operands[3], DFmode);
+ operands[0] = gen_rtx_REG (DFmode, REGNO (operands[0]));
+})
(define_peephole2
[(set (match_operand:SF 0 "memory_operand" "")
@@ -7029,10 +7034,11 @@
(match_operand:SF 3 "register_operand" ""))]
"registers_ok_for_ldd_peep (operands[1], operands[3])
&& mems_ok_for_ldd_peep (operands[0], operands[2], NULL_RTX)"
- [(set (match_dup 0)
- (match_dup 1))]
- "operands[0] = widen_memory_access (operands[0], DFmode, 0);
- operands[1] = gen_rtx_REG (DFmode, REGNO (operands[1]));")
+ [(set (match_dup 0) (match_dup 1))]
+{
+ operands[0] = widen_mem_for_ldd_peep (operands[0], operands[2], DFmode);
+ operands[1] = gen_rtx_REG (DFmode, REGNO (operands[1]));
+})
(define_peephole2
[(set (match_operand:SI 0 "register_operand" "")
@@ -7041,10 +7047,11 @@
(match_operand:SI 3 "memory_operand" ""))]
"registers_ok_for_ldd_peep (operands[2], operands[0])
&& mems_ok_for_ldd_peep (operands[3], operands[1], operands[0])"
- [(set (match_dup 2)
- (match_dup 3))]
- "operands[3] = widen_memory_access (operands[3], DImode, 0);
- operands[2] = gen_rtx_REG (DImode, REGNO (operands[2]));")
+ [(set (match_dup 2) (match_dup 3))]
+{
+ operands[3] = widen_mem_for_ldd_peep (operands[3], operands[1], DImode);
+ operands[2] = gen_rtx_REG (DImode, REGNO (operands[2]));
+})
(define_peephole2
[(set (match_operand:SI 0 "memory_operand" "")
@@ -7053,11 +7060,11 @@
(match_operand:SI 3 "register_operand" ""))]
"registers_ok_for_ldd_peep (operands[3], operands[1])
&& mems_ok_for_ldd_peep (operands[2], operands[0], NULL_RTX)"
- [(set (match_dup 2)
- (match_dup 3))]
- "operands[2] = widen_memory_access (operands[2], DImode, 0);
- operands[3] = gen_rtx_REG (DImode, REGNO (operands[3]));
- ")
+ [(set (match_dup 2) (match_dup 3))]
+{
+ operands[2] = widen_mem_for_ldd_peep (operands[2], operands[0], DImode);
+ operands[3] = gen_rtx_REG (DImode, REGNO (operands[3]));
+})
(define_peephole2
[(set (match_operand:SF 0 "register_operand" "")
@@ -7066,10 +7073,11 @@
(match_operand:SF 3 "memory_operand" ""))]
"registers_ok_for_ldd_peep (operands[2], operands[0])
&& mems_ok_for_ldd_peep (operands[3], operands[1], operands[0])"
- [(set (match_dup 2)
- (match_dup 3))]
- "operands[3] = widen_memory_access (operands[3], DFmode, 0);
- operands[2] = gen_rtx_REG (DFmode, REGNO (operands[2]));")
+ [(set (match_dup 2) (match_dup 3))]
+{
+ operands[3] = widen_mem_for_ldd_peep (operands[3], operands[1], DFmode);
+ operands[2] = gen_rtx_REG (DFmode, REGNO (operands[2]));
+})
(define_peephole2
[(set (match_operand:SF 0 "memory_operand" "")
@@ -7078,10 +7086,11 @@
(match_operand:SF 3 "register_operand" ""))]
"registers_ok_for_ldd_peep (operands[3], operands[1])
&& mems_ok_for_ldd_peep (operands[2], operands[0], NULL_RTX)"
- [(set (match_dup 2)
- (match_dup 3))]
- "operands[2] = widen_memory_access (operands[2], DFmode, 0);
- operands[3] = gen_rtx_REG (DFmode, REGNO (operands[3]));")
+ [(set (match_dup 2) (match_dup 3))]
+{
+ operands[2] = widen_mem_for_ldd_peep (operands[2], operands[0], DFmode);
+ operands[3] = gen_rtx_REG (DFmode, REGNO (operands[3]));
+})
;; Optimize the case of following a reg-reg move with a test
;; of reg just moved. Don't allow floating point regs for operand 0 or 1.
diff --git a/gcc/config/sparc/sync.md b/gcc/config/sparc/sync.md
index 130f5219194..7b431bc6577 100644
--- a/gcc/config/sparc/sync.md
+++ b/gcc/config/sparc/sync.md
@@ -93,6 +93,18 @@
"membar\t%1"
[(set_attr "type" "multi")])
+(define_peephole2
+ [(set (match_operand:BLK 0 "" "")
+ (unspec:BLK [(match_dup 0) (match_operand:SI 1 "const_int_operand")]
+ UNSPEC_MEMBAR))
+ (set (match_operand:BLK 2 "" "")
+ (unspec:BLK [(match_dup 2) (match_operand:SI 3 "const_int_operand")]
+ UNSPEC_MEMBAR))]
+ ""
+ [(set (match_operand:BLK 0 "" "")
+ (unspec:BLK [(match_dup 0) (match_dup 1)] UNSPEC_MEMBAR))]
+{ operands[1] = GEN_INT (UINTVAL (operands[1]) | UINTVAL (operands[3])); })
+
(define_expand "atomic_load<mode>"
[(match_operand:I 0 "register_operand" "")
(match_operand:I 1 "memory_operand" "")
diff --git a/gcc/config/sparc/t-sparc b/gcc/config/sparc/t-sparc
index 62ad3f77934..0f76508f516 100644
--- a/gcc/config/sparc/t-sparc
+++ b/gcc/config/sparc/t-sparc
@@ -18,19 +18,6 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-sparc.o: $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(TREE_H) $(RTL_H) $(REGS_H) hard-reg-set.h insn-config.h \
- insn-codes.h conditions.h output.h $(INSN_ATTR_H) $(FLAGS_H) \
- $(FUNCTION_H) $(EXCEPT_H) $(EXPR_H) $(OPTABS_H) $(RECOG_H) \
- $(DIAGNOSTIC_CORE_H) $(GGC_H) $(TM_P_H) debug.h $(TARGET_H) \
- $(TARGET_DEF_H) $(COMMON_TARGET_H) $(GIMPLE_H) $(TREE_PASS_H) \
- langhooks.h reload.h $(PARAMS_H) $(DF_H) $(OPTS_H) $(CONTEXT_H) \
- gt-sparc.h
-
-sparc-c.o: $(srcdir)/config/sparc/sparc-c.c \
- $(srcdir)/config/sparc/sparc-protos.h \
- $(CONFIG_H) $(SYSTEM_H) $(CPPLIB_H) $(FLAGS_H) \
- $(TM_P_H) coretypes.h $(TM_H) $(TREE_H) \
- $(C_COMMON_H) $(C_PRAGMA_H)
- $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
- $(srcdir)/config/sparc/sparc-c.c
+sparc-c.o: $(srcdir)/config/sparc/sparc-c.c
+ $(COMPILE) $<
+ $(POSTCOMPILE)
diff --git a/gcc/config/sparc/x-sparc b/gcc/config/sparc/x-sparc
index 693ba61d356..5fc65be683e 100644
--- a/gcc/config/sparc/x-sparc
+++ b/gcc/config/sparc/x-sparc
@@ -1,3 +1,4 @@
-driver-sparc.o: $(srcdir)/config/sparc/driver-sparc.c \
- $(CONFIG_H) $(SYSTEM_H)
- $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
+driver-sparc.o: $(srcdir)/config/sparc/driver-sparc.c
+ $(COMPILE) $<
+ $(POSTCOMPILE)
+
diff --git a/gcc/config/spu/spu.c b/gcc/config/spu/spu.c
index 6cbd3f82337..38c441d9a03 100644
--- a/gcc/config/spu/spu.c
+++ b/gcc/config/spu/spu.c
@@ -2197,7 +2197,7 @@ get_branch_target (rtx branch)
{
/* If the more probable case is not a fall through, then
try a branch hint. */
- HOST_WIDE_INT prob = INTVAL (XEXP (note, 0));
+ int prob = XINT (note, 0);
if (prob > (REG_BR_PROB_BASE * 6 / 10)
&& GET_CODE (XEXP (src, 1)) != PC)
lab = XEXP (src, 1);
@@ -4342,7 +4342,7 @@ ea_load_store_inline (rtx mem, bool is_store, rtx ea_addr, rtx data_addr)
hit_ref, pc_rtx)));
/* Say that this branch is very likely to happen. */
v = REG_BR_PROB_BASE - REG_BR_PROB_BASE / 100 - 1;
- add_reg_note (insn, REG_BR_PROB, GEN_INT (v));
+ add_int_reg_note (insn, REG_BR_PROB, v);
ea_load_store (mem, is_store, ea_addr, data_addr);
cont_label = gen_label_rtx ();
@@ -7328,6 +7328,9 @@ static const struct attribute_spec spu_attribute_table[] =
#undef TARGET_CANONICALIZE_COMPARISON
#define TARGET_CANONICALIZE_COMPARISON spu_canonicalize_comparison
+#undef TARGET_CAN_USE_DOLOOP_P
+#define TARGET_CAN_USE_DOLOOP_P can_use_doloop_if_innermost
+
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-spu.h"
diff --git a/gcc/config/spu/spu.md b/gcc/config/spu/spu.md
index 083dea4e668..3ca53481128 100644
--- a/gcc/config/spu/spu.md
+++ b/gcc/config/spu/spu.md
@@ -4487,11 +4487,7 @@ selb\t%0,%4,%0,%3"
;; knows what to generate.
(define_expand "doloop_end"
[(use (match_operand 0 "" "")) ; loop pseudo
- (use (match_operand 1 "" "")) ; iterations; zero if unknown
- (use (match_operand 2 "" "")) ; max iterations
- (use (match_operand 3 "" "")) ; loop level
- (use (match_operand 4 "" "")) ; label
- (match_operand 5 "" "")]
+ (use (match_operand 1 "" ""))] ; label
""
"
{
@@ -4507,16 +4503,13 @@ selb\t%0,%4,%0,%3"
rtx bcomp;
rtx loc_ref;
- /* Only use this on innermost loops. */
- if (INTVAL (operands[3]) > 1)
- FAIL;
if (GET_MODE (operands[0]) != SImode)
FAIL;
s0 = operands [0];
emit_move_insn (s0, gen_rtx_PLUS (SImode, s0, GEN_INT (-1)));
bcomp = gen_rtx_NE(SImode, s0, const0_rtx);
- loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [4]);
+ loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [1]);
emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
loc_ref, pc_rtx)));
diff --git a/gcc/config/t-darwin b/gcc/config/t-darwin
index fdd52c2f29d..87d5df7a935 100644
--- a/gcc/config/t-darwin
+++ b/gcc/config/t-darwin
@@ -18,25 +18,19 @@
TM_H += $(srcdir)/config/darwin-sections.def
-darwin.o: $(srcdir)/config/darwin.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(RTL_H) $(REGS_H) hard-reg-set.h $(REAL_H) insn-config.h \
- conditions.h insn-flags.h output.h insn-attr.h flags.h $(TREE_H) expr.h \
- reload.h function.h $(GGC_H) langhooks.h $(TARGET_H) $(TM_P_H) gt-darwin.h \
- config/darwin-sections.def
- $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
- $(srcdir)/config/darwin.c
+darwin.o: $(srcdir)/config/darwin.c config/darwin-sections.def
+ $(COMPILE) $<
+ $(POSTCOMPILE)
-darwin-c.o: $(srcdir)/config/darwin-c.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(CPPLIB_H) $(TREE_H) $(C_PRAGMA_H) $(TM_P_H) \
- incpath.h flags.h $(C_COMMON_H) $(C_TARGET_H) $(C_TARGET_DEF_H) $(CPP_INTERNAL_H)
- $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
- $(srcdir)/config/darwin-c.c $(PREPROCESSOR_DEFINES)
+darwin-c.o: $(srcdir)/config/darwin-c.c
+ $(COMPILE) $(PREPROCESSOR_DEFINES) $<
+ $(POSTCOMPILE)
-darwin-f.o: $(srcdir)/config/darwin-f.c $(CONFIG_H) $(SYSTEM_H) coretypes.h
- $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
- $(srcdir)/config/darwin-f.c $(PREPROCESSOR_DEFINES)
-darwin-driver.o: $(srcdir)/config/darwin-driver.c \
- $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(GCC_H) opts.h
- $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
- $(srcdir)/config/darwin-driver.c
+darwin-f.o: $(srcdir)/config/darwin-f.c
+ $(COMPILE) $<
+ $(POSTCOMPILE)
+
+darwin-driver.o: $(srcdir)/config/darwin-driver.c
+ $(COMPILE) $<
+ $(POSTCOMPILE)
diff --git a/gcc/config/t-glibc b/gcc/config/t-glibc
index 032c68d07d6..ae7bf7abfa0 100644
--- a/gcc/config/t-glibc
+++ b/gcc/config/t-glibc
@@ -16,7 +16,6 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-glibc-c.o: config/glibc-c.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(C_TARGET_H) $(C_TARGET_DEF_H)
- $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) \
- $< $(OUTPUT_OPTION)
+glibc-c.o: config/glibc-c.c
+ $(COMPILE) $<
+ $(POSTCOMPILE)
diff --git a/gcc/config/t-linux-android b/gcc/config/t-linux-android
index 6f9b03330a7..75155f44d7c 100644
--- a/gcc/config/t-linux-android
+++ b/gcc/config/t-linux-android
@@ -1,5 +1,4 @@
-# Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2013
-# Free Software Foundation, Inc.
+# Copyright (C) 2002-2013 Free Software Foundation, Inc.
#
# This file is part of GCC.
#
@@ -17,7 +16,6 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-linux-android.o: $(srcdir)/config/linux-android.c $(CONFIG_H) $(SYSTEM_H) \
- coretypes.h $(TM_H) $(TM_P_H)
- $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
- $(srcdir)/config/linux-android.c
+linux-android.o: $(srcdir)/config/linux-android.c
+ $(COMPILE) $<
+ $(POSTCOMPILE)
diff --git a/gcc/config/t-sol2 b/gcc/config/t-sol2
index 142de89de95..2d0bd7282a3 100644
--- a/gcc/config/t-sol2
+++ b/gcc/config/t-sol2
@@ -17,22 +17,21 @@
# <http://www.gnu.org/licenses/>.
# Solaris-specific format checking and pragmas
-sol2-c.o: $(srcdir)/config/sol2-c.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- tree.h c-family/c-format.h $(C_PRAGMA_H) $(C_COMMON_H) $(CPPLIB_H) \
- intl.h $(TM_H) $(TM_P_H)
- $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
+sol2-c.o: $(srcdir)/config/sol2-c.c
+ $(COMPILE) $<
+ $(POSTCOMPILE)
# Solaris-specific C++ mangling.
-sol2-cxx.o: $(srcdir)/config/sol2-cxx.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- tree.h cp/cp-tree.h $(TM_H) $(TM_P_H)
- $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
+sol2-cxx.o: $(srcdir)/config/sol2-cxx.c
+ $(COMPILE) $<
+ $(POSTCOMPILE)
# Corresponding stub routines.
-sol2-stubs.o: $(srcdir)/config/sol2-stubs.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- tree.h $(TM_H) $(TM_P_H)
- $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
+sol2-stubs.o: $(srcdir)/config/sol2-stubs.c
+ $(COMPILE) $<
+ $(POSTCOMPILE)
# Solaris-specific attributes
-sol2.o: $(srcdir)/config/sol2.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- tree.h output.h $(TM_H) $(TARGET_H) $(TM_P_H) $(GGC_H) $(HASH_TABLE_H)
- $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
+sol2.o: $(srcdir)/config/sol2.c
+ $(COMPILE) $<
+ $(POSTCOMPILE)
diff --git a/gcc/config/tilegx/tilegx.c b/gcc/config/tilegx/tilegx.c
index beb1012cf2c..dafa44c0674 100644
--- a/gcc/config/tilegx/tilegx.c
+++ b/gcc/config/tilegx/tilegx.c
@@ -39,6 +39,7 @@
#include "function.h"
#include "dwarf2.h"
#include "timevar.h"
+#include "tree.h"
#include "gimple.h"
#include "cfgloop.h"
#include "tilegx-builtins.h"
@@ -1872,7 +1873,7 @@ tilegx_expand_unaligned_load (rtx dest_reg, rtx mem, HOST_WIDE_INT bitsize,
rtx extracted =
extract_bit_field (gen_lowpart (DImode, wide_result),
bitsize, bit_offset % BITS_PER_UNIT,
- !sign, false, gen_lowpart (DImode, dest_reg),
+ !sign, gen_lowpart (DImode, dest_reg),
DImode, DImode);
if (extracted != dest_reg)
@@ -2529,7 +2530,7 @@ cbranch_predicted_p (rtx insn)
if (x)
{
- int pred_val = INTVAL (XEXP (x, 0));
+ int pred_val = XINT (x, 0);
return pred_val >= REG_BR_PROB_BASE / 2;
}
@@ -5577,6 +5578,8 @@ tilegx_file_end (void)
#undef TARGET_ASM_ALIGNED_DI_OP
#define TARGET_ASM_ALIGNED_DI_OP "\t.quad\t"
+#undef TARGET_CAN_USE_DOLOOP_P
+#define TARGET_CAN_USE_DOLOOP_P can_use_doloop_if_innermost
struct gcc_target targetm = TARGET_INITIALIZER;
diff --git a/gcc/config/tilegx/tilegx.md b/gcc/config/tilegx/tilegx.md
index 9c6917059a1..30dc8e628ba 100644
--- a/gcc/config/tilegx/tilegx.md
+++ b/gcc/config/tilegx/tilegx.md
@@ -2414,11 +2414,7 @@
;; generate.
(define_expand "doloop_end"
[(use (match_operand 0 "" "")) ;; loop pseudo
- (use (match_operand 1 "" "")) ;; iterations; zero if unknown
- (use (match_operand 2 "" "")) ;; max iterations
- (use (match_operand 3 "" "")) ;; loop level
- (use (match_operand 4 "" "")) ;; label
- (use (match_operand 5 "" ""))] ;; flag: 1 if loop entered at top, else 0
+ (use (match_operand 1 "" ""))] ;; label
""
{
if (optimize > 0 && flag_modulo_sched)
@@ -2428,9 +2424,6 @@
rtx loc_ref;
enum machine_mode mode = GET_MODE (operands[0]);
- /* only do inner loop */
- if (INTVAL (operands[3]) > 1)
- FAIL;
/* only deal with loop counters in SImode or DImode */
if (mode != SImode && mode != DImode)
FAIL;
@@ -2438,7 +2431,7 @@
s0 = operands [0];
emit_move_insn (s0, gen_rtx_PLUS (mode, s0, GEN_INT (-1)));
bcomp = gen_rtx_NE(mode, s0, const0_rtx);
- loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [4]);
+ loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [1]);
emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
loc_ref, pc_rtx)));
diff --git a/gcc/config/tilepro/tilepro.c b/gcc/config/tilepro/tilepro.c
index 59618e4384b..5e3be831fb1 100644
--- a/gcc/config/tilepro/tilepro.c
+++ b/gcc/config/tilepro/tilepro.c
@@ -40,6 +40,7 @@
#include "function.h"
#include "dwarf2.h"
#include "timevar.h"
+#include "tree.h"
#include "gimple.h"
#include "cfgloop.h"
#include "tilepro-builtins.h"
@@ -1676,7 +1677,7 @@ tilepro_expand_unaligned_load (rtx dest_reg, rtx mem, HOST_WIDE_INT bitsize,
rtx extracted =
extract_bit_field (gen_lowpart (SImode, wide_result),
bitsize, bit_offset % BITS_PER_UNIT,
- !sign, false, gen_lowpart (SImode, dest_reg),
+ !sign, gen_lowpart (SImode, dest_reg),
SImode, SImode);
if (extracted != dest_reg)
@@ -2411,7 +2412,7 @@ cbranch_predicted_p (rtx insn)
if (x)
{
- int pred_val = INTVAL (XEXP (x, 0));
+ int pred_val = XINT (x, 0);
return pred_val >= REG_BR_PROB_BASE / 2;
}
@@ -5066,6 +5067,8 @@ tilepro_file_end (void)
#undef TARGET_ASM_FILE_END
#define TARGET_ASM_FILE_END tilepro_file_end
+#undef TARGET_CAN_USE_DOLOOP_P
+#define TARGET_CAN_USE_DOLOOP_P can_use_doloop_if_innermost
struct gcc_target targetm = TARGET_INITIALIZER;
diff --git a/gcc/config/tilepro/tilepro.md b/gcc/config/tilepro/tilepro.md
index ca8cf80ca18..f090f9e038b 100644
--- a/gcc/config/tilepro/tilepro.md
+++ b/gcc/config/tilepro/tilepro.md
@@ -1318,11 +1318,7 @@
;; generate.
(define_expand "doloop_end"
[(use (match_operand 0 "" "")) ;; loop pseudo
- (use (match_operand 1 "" "")) ;; iterations; zero if unknown
- (use (match_operand 2 "" "")) ;; max iterations
- (use (match_operand 3 "" "")) ;; loop level
- (use (match_operand 4 "" "")) ;; label
- (use (match_operand 5 "" ""))] ;; flag: 1 if loop entered at top, else 0
+ (use (match_operand 1 "" ""))] ;; label
""
{
if (optimize > 0)
@@ -1331,9 +1327,6 @@
rtx bcomp;
rtx loc_ref;
- /* only do inner loop */
- if (INTVAL (operands[3]) > 1)
- FAIL;
/* only deal with loop counters in SImode */
if (GET_MODE (operands[0]) != SImode)
FAIL;
@@ -1342,7 +1335,7 @@
emit_move_insn (s0, gen_rtx_PLUS (SImode, s0, GEN_INT (-1)));
bcomp = gen_rtx_NE(SImode, s0, const0_rtx);
- loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [4]);
+ loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [1]);
emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
loc_ref, pc_rtx)));
diff --git a/gcc/config/v850/v850.c b/gcc/config/v850/v850.c
index 4a746aa1424..006cff4bcdf 100644
--- a/gcc/config/v850/v850.c
+++ b/gcc/config/v850/v850.c
@@ -3269,6 +3269,9 @@ v850_gen_movdi (rtx * operands)
#undef TARGET_LEGITIMATE_CONSTANT_P
#define TARGET_LEGITIMATE_CONSTANT_P v850_legitimate_constant_p
+#undef TARGET_CAN_USE_DOLOOP_P
+#define TARGET_CAN_USE_DOLOOP_P can_use_doloop_if_innermost
+
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-v850.h"
diff --git a/gcc/config/v850/v850.h b/gcc/config/v850/v850.h
index e08c6220eac..9b5053337f5 100644
--- a/gcc/config/v850/v850.h
+++ b/gcc/config/v850/v850.h
@@ -954,10 +954,6 @@ extern tree GHS_current_section_names [(int) COUNT_OF_GHS_SECTION_KINDS];
#define FILE_ASM_OP "\t.file\n"
-/* Enable the register move pass to improve code. */
-#define ENABLE_REGMOVE_PASS
-
-
/* Implement ZDA, TDA, and SDA */
#define EP_REGNUM 30 /* ep register number */
diff --git a/gcc/config/v850/v850.md b/gcc/config/v850/v850.md
index a074f651351..f56d54a91a0 100644
--- a/gcc/config/v850/v850.md
+++ b/gcc/config/v850/v850.md
@@ -1357,20 +1357,11 @@
(define_expand "doloop_begin"
[(use (match_operand 0 "" "")) ; loop pseudo
- (use (match_operand 1 "" "")) ; iterations; zero if unknown
- (use (match_operand 2 "" "")) ; max iterations
- (use (match_operand 3 "" "")) ; loop level
- (use (match_operand 4 "" ""))] ; condition
+ (use (match_operand 1 "" ""))] ; doloop_end pattern
"TARGET_V850E3V5_UP && TARGET_LOOP"
{
- rtx loop_cnt = operands[0];
- rtx loop_level = operands[3];
-
- if (INTVAL (loop_level) > 1)
- FAIL;
- if (GET_MODE (loop_cnt) != SImode)
- FAIL;
-
+ rtx loop_cnt = operands[0];
+ gcc_assert (GET_MODE (loop_cnt) == SImode);
emit_insn (gen_fix_loop_counter (loop_cnt));
DONE;
}
@@ -1394,19 +1385,12 @@
(define_expand "doloop_end"
[(use (match_operand 0 "" "")) ; loop pseudo
- (use (match_operand 1 "" "")) ; iterations; zero if unknown
- (use (match_operand 2 "" "")) ; max iterations
- (use (match_operand 3 "" "")) ; loop level
- (use (match_operand 4 "" "")) ; label
- (use (match_operand 5 "" ""))] ; entered at top
+ (use (match_operand 1 "" ""))] ; label
"TARGET_V850E3V5_UP && TARGET_LOOP"
{
- rtx loop_cnt = operands[0];
- rtx loop_level = operands[3];
- rtx label = operands[4];
+ rtx loop_cnt = operands[0];
+ rtx label = operands[1];
- if (INTVAL (loop_level) > 1)
- FAIL;
if (GET_MODE (loop_cnt) != SImode)
FAIL;
diff --git a/gcc/config/vax/vax.c b/gcc/config/vax/vax.c
index 53189a7e7d6..6b643d1af5d 100644
--- a/gcc/config/vax/vax.c
+++ b/gcc/config/vax/vax.c
@@ -1187,7 +1187,7 @@ vax_output_int_move (rtx insn ATTRIBUTE_UNUSED, rtx *operands,
{
operands[1] = GEN_INT (lval);
operands[2] = GEN_INT (n);
- return "ashq %2,%1,%0";
+ return "ashq %2,%D1,%0";
}
#if HOST_BITS_PER_WIDE_INT == 32
}
@@ -1199,7 +1199,7 @@ vax_output_int_move (rtx insn ATTRIBUTE_UNUSED, rtx *operands,
{
operands[1] = GEN_INT (hval >> n);
operands[2] = GEN_INT (n + 32);
- return "ashq %2,%1,%0";
+ return "ashq %2,%D1,%0";
#endif
}
}
diff --git a/gcc/config/vax/vax.md b/gcc/config/vax/vax.md
index eadde18ad43..2c05d007dae 100644
--- a/gcc/config/vax/vax.md
+++ b/gcc/config/vax/vax.md
@@ -697,14 +697,14 @@
(ashift:DI (match_operand:DI 1 "general_operand" "g")
(match_operand:QI 2 "general_operand" "g")))]
""
- "ashq %2,%1,%0")
+ "ashq %2,%D1,%0")
(define_insn ""
[(set (match_operand:DI 0 "nonimmediate_operand" "=g")
(ashiftrt:DI (match_operand:DI 1 "general_operand" "g")
(neg:QI (match_operand:QI 2 "general_operand" "g"))))]
""
- "ashq %2,%1,%0")
+ "ashq %2,%D1,%0")
;; We used to have expand_shift handle logical right shifts by using extzv,
;; but this make it very difficult to do lshrdi3. Since the VAX is the
diff --git a/gcc/config/x-darwin b/gcc/config/x-darwin
index f671d911f0d..c6226c04883 100644
--- a/gcc/config/x-darwin
+++ b/gcc/config/x-darwin
@@ -1,3 +1,3 @@
-host-darwin.o : $(srcdir)/config/host-darwin.c $(CONFIG_H) $(SYSTEM_H) \
- coretypes.h toplev.h config/host-darwin.h
- $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
+host-darwin.o : $(srcdir)/config/host-darwin.c
+ $(COMPILE) $<
+ $(POSTCOMPILE)
diff --git a/gcc/config/x-linux b/gcc/config/x-linux
index f87a45b24d9..dba21a666e3 100644
--- a/gcc/config/x-linux
+++ b/gcc/config/x-linux
@@ -1,4 +1,3 @@
-host-linux.o : $(srcdir)/config/host-linux.c $(CONFIG_H) $(SYSTEM_H) \
- coretypes.h hosthooks.h hosthooks-def.h $(HOOKS_H)
- $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
- $(srcdir)/config/host-linux.c
+host-linux.o : $(srcdir)/config/host-linux.c
+ $(COMPILE) $<
+ $(POSTCOMPILE)
diff --git a/gcc/config/x-solaris b/gcc/config/x-solaris
index 3e99df65748..d50b4f59a18 100644
--- a/gcc/config/x-solaris
+++ b/gcc/config/x-solaris
@@ -1,4 +1,3 @@
-host-solaris.o : $(srcdir)/config/host-solaris.c $(CONFIG_H) $(SYSTEM_H) \
- coretypes.h hosthooks.h hosthooks-def.h $(HOOKS_H)
- $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
- $(srcdir)/config/host-solaris.c
+host-solaris.o: $(srcdir)/config/host-solaris.c
+ $(COMPILE) $<
+ $(POSTCOMPILE)
diff --git a/gcc/configure b/gcc/configure
index c6bc3a69d84..b5e2fc23d18 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -600,6 +600,8 @@ ac_includes_default="\
ac_subst_vars='LTLIBOBJS
LIBOBJS
+PICFLAG
+enable_host_shared
enable_plugin
pluginlibs
CLOOGINC
@@ -735,6 +737,9 @@ LDEXP_LIB
EXTRA_GCC_LIBS
GNAT_LIBEXC
COLLECT2_LIBS
+CXXDEPMODE
+DEPDIR
+am__leading_dot
CXXCPP
AR
NM
@@ -787,8 +792,6 @@ EGREP
GREP
CPP
PICFLAG_FOR_TARGET
-OUTPUT_OPTION
-NO_MINUS_C_MINUS_O
GNATMAKE
GNATBIND
ac_ct_CXX
@@ -872,6 +875,7 @@ with_demangler_in_ld
with_gnu_as
with_as
enable_largefile
+enable_build_format_warnings
enable_werror_always
enable_checking
enable_coverage
@@ -920,6 +924,7 @@ enable_maintainer_mode
enable_link_mutex
enable_version_specific_runtime_libs
enable_plugin
+enable_host_shared
enable_libquadmath_support
with_linker_hash_style
'
@@ -1565,6 +1570,8 @@ Optional Features:
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
@@ -1635,6 +1642,7 @@ Optional Features:
specify that runtime libraries should be installed
in a compiler-specific directory
--enable-plugin enable plugin support
+ --enable-host-shared build host code as shared libraries
--disable-libquadmath-support
disable libquadmath support for Fortran
@@ -4254,135 +4262,6 @@ 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 "x$CC" != xcc; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC and cc understand -c and -o together" >&5
-$as_echo_n "checking whether $CC and cc understand -c and -o together... " >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether cc understands -c and -o together" >&5
-$as_echo_n "checking whether cc understands -c and -o together... " >&6; }
-fi
-set dummy $CC; ac_cc=`$as_echo "$2" |
- sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'`
-if { as_var=ac_cv_prog_cc_${ac_cc}_c_o; eval "test \"\${$as_var+set}\" = set"; }; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-# Make sure it works both with $CC and with simple cc.
-# We do the test twice because some compilers refuse to overwrite an
-# existing .o file with -o, though they will create one.
-ac_try='$CC -c conftest.$ac_ext -o conftest2.$ac_objext >&5'
-rm -f conftest2.*
-if { { 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; } &&
- test -f conftest2.$ac_objext && { { 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
- eval ac_cv_prog_cc_${ac_cc}_c_o=yes
- if test "x$CC" != xcc; then
- # Test first that cc exists at all.
- if { ac_try='cc -c conftest.$ac_ext >&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_try") 2>&5
- ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; }; then
- ac_try='cc -c conftest.$ac_ext -o conftest2.$ac_objext >&5'
- rm -f conftest2.*
- if { { 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; } &&
- test -f conftest2.$ac_objext && { { 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
- # cc works too.
- :
- else
- # cc exists but doesn't like -o.
- eval ac_cv_prog_cc_${ac_cc}_c_o=no
- fi
- fi
- fi
-else
- eval ac_cv_prog_cc_${ac_cc}_c_o=no
-fi
-rm -f core conftest*
-
-fi
-if eval test \$ac_cv_prog_cc_${ac_cc}_c_o = yes; 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" >&5
-$as_echo "no" >&6; }
-
-$as_echo "#define NO_MINUS_C_MINUS_O 1" >>confdefs.h
-
-fi
-
-# expand $ac_aux_dir to an absolute path
-am_aux_dir=`cd $ac_aux_dir && pwd`
-
-# FIXME: we rely on the cache variable name because
-# there is no other way.
-set dummy $CC
-am_cc=`echo $2 | sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'`
-eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o
-if test "$am_t" != yes; then
- # Losing compiler, so override with the script.
- # FIXME: It is wrong to rewrite CC.
- # But if we don't then we get into trouble of one sort or another.
- # A longer-term fix would be to have automake use am__CC in this case,
- # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
- CC="$am_aux_dir/compile $CC"
-fi
-
-
ac_ext=cpp
ac_cpp='$CXXCPP $CPPFLAGS'
ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -4860,15 +4739,6 @@ else
fi
-# autoconf is lame and doesn't give us any substitution variable for this.
-if eval "test \"`echo '$ac_cv_prog_cc_'${ac_cc}_c_o`\" = no"; then
- NO_MINUS_C_MINUS_O=yes
-else
- OUTPUT_OPTION='-o $@'
-fi
-
-
-
# Remove the -O2: for historical reasons, unless bootstrapping we prefer
# optimizations to be activated explicitly by the toplevel.
case "$CC" in
@@ -6403,9 +6273,22 @@ fi
# * 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
loose_warn=
save_CFLAGS="$CFLAGS"
-for real_option in -W -Wall -Wno-narrowing -Wwrite-strings -Wcast-qual; do
+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
@@ -8873,6 +8756,136 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
# --------
+# Dependency checking.
+# --------
+
+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
+
+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 test "${am_cv_CXX_dependencies_compiler_type+set}" = set; 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
+
+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
+
+
+# --------
# UNSORTED
# --------
@@ -13656,7 +13669,7 @@ ia64-*-hpux*)
rm -rf conftest*
;;
-x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \
+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
@@ -13681,7 +13694,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
;;
esac
;;
- ppc64-*linux*|powerpc64-*linux*)
+ powerpc64le-*linux*)
+ LD="${LD-ld} -m elf32lppclinux"
+ ;;
+ powerpc64-*linux*)
LD="${LD-ld} -m elf32ppclinux"
;;
s390x-*linux*)
@@ -13700,7 +13716,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
x86_64-*linux*)
LD="${LD-ld} -m elf_x86_64"
;;
- ppc*-*linux*|powerpc*-*linux*)
+ powerpcle-*linux*)
+ LD="${LD-ld} -m elf64lppc"
+ ;;
+ powerpc-*linux*)
LD="${LD-ld} -m elf64ppc"
;;
s390*-*linux*|s390*-*tpf*)
@@ -17894,7 +17913,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 17897 "configure"
+#line 17916 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -18000,7 +18019,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 18003 "configure"
+#line 18022 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -21761,7 +21780,13 @@ if test "${gcc_cv_as_flags+set}" = set; then :
else
case "$target" in
i[34567]86-*-linux*)
- gcc_cv_as_flags="--32"
+ 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"
@@ -24777,11 +24802,12 @@ else
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; }
-if test $gcc_cv_as_ix86_interunit_movq = yes; then
-$as_echo "#define HAVE_AS_IX86_INTERUNIT_MOVQ 1" >>confdefs.h
-fi
+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; }
@@ -27544,8 +27570,8 @@ if test x"$enable_plugin" = x"yes"; then
$as_echo_n "checking for exported symbols... " >&6; }
if test "x$export_sym_check" != x; then
echo "int main() {return 0;} int foobar() {return 0;}" > conftest.c
- ${CC} ${CFLAGS} ${LDFLAGS} conftest.c -o conftest > /dev/null 2>&1
- if $export_sym_check conftest | grep foobar > /dev/null; then
+ ${CC} ${CFLAGS} ${LDFLAGS} conftest.c -o conftest$ac_exeext > /dev/null 2>&1
+ if $export_sym_check conftest$ac_exeext | grep -q foobar > /dev/null; then
: # No need to use a flag
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
@@ -27554,8 +27580,8 @@ $as_echo "yes" >&6; }
$as_echo "yes" >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for -rdynamic" >&5
$as_echo_n "checking for -rdynamic... " >&6; }
- ${CC} ${CFLAGS} ${LDFLAGS} -rdynamic conftest.c -o conftest > /dev/null 2>&1
- if $export_sym_check conftest | grep foobar > /dev/null; then
+ ${CC} ${CFLAGS} ${LDFLAGS} -rdynamic conftest.c -o conftest$ac_exeext > /dev/null 2>&1
+ if $export_sym_check conftest$ac_exeext | grep -q foobar > /dev/null; then
plugin_rdynamic=yes
pluginlibs="-rdynamic"
else
@@ -27695,6 +27721,18 @@ $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
@@ -28428,6 +28466,8 @@ 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
@@ -28439,6 +28479,8 @@ 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" ;;
@@ -29022,6 +29064,13 @@ $as_echo "$as_me: executing $ac_file commands" >&6;}
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
+ 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 ;;
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 5d3e5ad5823..eae9504c580 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -278,19 +278,9 @@ rm -f a.out a.exe b.out
# Find the native compiler
AC_PROG_CC
-AM_PROG_CC_C_O
AC_PROG_CXX
ACX_PROG_GNAT([-I"$srcdir"/ada])
-# autoconf is lame and doesn't give us any substitution variable for this.
-if eval "test \"`echo '$ac_cv_prog_cc_'${ac_cc}_c_o`\" = no"; then
- NO_MINUS_C_MINUS_O=yes
-else
- OUTPUT_OPTION='-o $@'
-fi
-AC_SUBST(NO_MINUS_C_MINUS_O)
-AC_SUBST(OUTPUT_OPTION)
-
# Remove the -O2: for historical reasons, unless bootstrapping we prefer
# optimizations to be activated explicitly by the toplevel.
case "$CC" in
@@ -336,8 +326,14 @@ GCC_STDINT_TYPES
# * 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_CC_WARNING_OPTS(
- m4_quote(m4_do([-W -Wall -Wno-narrowing -Wwrite-strings -Wcast-qual])), [loose_warn])
+ 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])
@@ -972,6 +968,22 @@ AC_CHECK_HEADERS(ext/hash_map)
AC_LANG_POP(C++)
# --------
+# Dependency checking.
+# --------
+
+AC_LANG_PUSH(C++)
+ZW_CREATE_DEPDIR
+AC_CONFIG_COMMANDS([gccdepdir],[
+ ${CONFIG_SHELL-/bin/sh} $ac_aux_dir/mkinstalldirs build/$DEPDIR
+ for lang in $subdirs c-family common
+ 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])
+AC_LANG_POP(C++)
+
+# --------
# UNSORTED
# --------
@@ -3742,9 +3754,10 @@ foo: nop
gcc_cv_as_ix86_interunit_movq,,,
[.code64
movq %mm0, %rax
- movq %rax, %xmm0],,
- [AC_DEFINE(HAVE_AS_IX86_INTERUNIT_MOVQ, 1,
- [Define if your assembler supports interunit movq mnemonic.])])
+ 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,,,
@@ -5321,15 +5334,15 @@ if test x"$enable_plugin" = x"yes"; then
AC_MSG_CHECKING([for exported symbols])
if test "x$export_sym_check" != x; then
echo "int main() {return 0;} int foobar() {return 0;}" > conftest.c
- ${CC} ${CFLAGS} ${LDFLAGS} conftest.c -o conftest > /dev/null 2>&1
- if $export_sym_check conftest | grep foobar > /dev/null; then
+ ${CC} ${CFLAGS} ${LDFLAGS} conftest.c -o conftest$ac_exeext > /dev/null 2>&1
+ if $export_sym_check conftest$ac_exeext | grep -q foobar > /dev/null; then
: # No need to use a flag
AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([yes])
AC_MSG_CHECKING([for -rdynamic])
- ${CC} ${CFLAGS} ${LDFLAGS} -rdynamic conftest.c -o conftest > /dev/null 2>&1
- if $export_sym_check conftest | grep foobar > /dev/null; then
+ ${CC} ${CFLAGS} ${LDFLAGS} -rdynamic conftest.c -o conftest$ac_exeext > /dev/null 2>&1
+ if $export_sym_check conftest$ac_exeext | grep -q foobar > /dev/null; then
plugin_rdynamic=yes
pluginlibs="-rdynamic"
else
@@ -5393,6 +5406,15 @@ if test x"$enable_plugin" = x"yes"; then
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])],
diff --git a/gcc/context.c b/gcc/context.c
index b5152419a97..3dd4526845e 100644
--- a/gcc/context.c
+++ b/gcc/context.c
@@ -23,11 +23,16 @@ along with GCC; see the file COPYING3. If not see
#include "ggc.h"
#include "context.h"
#include "pass_manager.h"
+#include "dumpfile.h"
/* The singleton holder of global state: */
gcc::context *g;
-gcc::context::context()
+gcc::context::context ()
{
- passes_ = new gcc::pass_manager (this);
+ /* The pass manager's constructor uses the dump manager (to set up
+ dumps for the various passes), so the dump manager must be set up
+ before the pass manager. */
+ m_dumps = new gcc::dump_manager ();
+ m_passes = new gcc::pass_manager (this);
}
diff --git a/gcc/context.h b/gcc/context.h
index 66260cd279a..d6555ccbd16 100644
--- a/gcc/context.h
+++ b/gcc/context.h
@@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. If not see
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
@@ -30,15 +31,22 @@ class pass_manager;
class context
{
public:
- context();
+ context ();
/* Pass-management. */
- pass_manager *get_passes () { gcc_assert (passes_); return passes_; }
+ 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 *passes_;
+ pass_manager *m_passes;
+
+ /* Dump files. */
+ dump_manager *m_dumps;
}; // class context
diff --git a/gcc/convert.c b/gcc/convert.c
index b07f0efe820..a2f2a334dbf 100644
--- a/gcc/convert.c
+++ b/gcc/convert.c
@@ -135,16 +135,19 @@ convert_to_real (tree type, tree expr)
CASE_MATHFN (COS)
CASE_MATHFN (ERF)
CASE_MATHFN (ERFC)
- CASE_MATHFN (FABS)
CASE_MATHFN (LOG)
CASE_MATHFN (LOG10)
CASE_MATHFN (LOG2)
CASE_MATHFN (LOG1P)
- CASE_MATHFN (LOGB)
CASE_MATHFN (SIN)
- CASE_MATHFN (SQRT)
CASE_MATHFN (TAN)
CASE_MATHFN (TANH)
+ /* The above functions are not safe to do this conversion. */
+ if (!flag_unsafe_math_optimizations)
+ break;
+ CASE_MATHFN (SQRT)
+ CASE_MATHFN (FABS)
+ CASE_MATHFN (LOGB)
#undef CASE_MATHFN
{
tree arg0 = strip_float_extensions (CALL_EXPR_ARG (expr, 0));
@@ -155,13 +158,44 @@ convert_to_real (tree type, tree expr)
if (TYPE_PRECISION (TREE_TYPE (arg0)) > TYPE_PRECISION (type))
newtype = TREE_TYPE (arg0);
+ /* We consider to convert
+
+ (T1) sqrtT2 ((T2) exprT3)
+ to
+ (T1) sqrtT4 ((T4) exprT3)
+
+ , where T1 is TYPE, T2 is ITYPE, T3 is TREE_TYPE (ARG0),
+ and T4 is NEWTYPE. All those types are of floating point types.
+ T4 (NEWTYPE) should be narrower than T2 (ITYPE). This conversion
+ is safe only if P1 >= P2*2+2, where P1 and P2 are precisions of
+ T2 and T4. See the following URL for a reference:
+ http://stackoverflow.com/questions/9235456/determining-
+ floating-point-square-root
+ */
+ if ((fcode == BUILT_IN_SQRT || fcode == BUILT_IN_SQRTL)
+ && !flag_unsafe_math_optimizations)
+ {
+ /* The following conversion is unsafe even the precision condition
+ below is satisfied:
+
+ (float) sqrtl ((long double) double_val) -> (float) sqrt (double_val)
+ */
+ if (TYPE_MODE (type) != TYPE_MODE (newtype))
+ break;
+
+ int p1 = REAL_MODE_FORMAT (TYPE_MODE (itype))->p;
+ int p2 = REAL_MODE_FORMAT (TYPE_MODE (newtype))->p;
+ if (p1 < p2 * 2 + 2)
+ break;
+ }
+
/* Be careful about integer to fp conversions.
These may overflow still. */
if (FLOAT_TYPE_P (TREE_TYPE (arg0))
&& TYPE_PRECISION (newtype) < TYPE_PRECISION (itype)
&& (TYPE_MODE (newtype) == TYPE_MODE (double_type_node)
|| TYPE_MODE (newtype) == TYPE_MODE (float_type_node)))
- {
+ {
tree fn = mathfn_built_in (newtype, fcode);
if (fn)
diff --git a/gcc/coretypes.h b/gcc/coretypes.h
index bff8f5c62d5..f7ef8d777c1 100644
--- a/gcc/coretypes.h
+++ b/gcc/coretypes.h
@@ -43,6 +43,9 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#ifndef USED_FOR_TARGET
+typedef HOST_WIDEST_INT gcov_type;
+typedef unsigned HOST_WIDEST_INT gcov_type_unsigned;
+
struct bitmap_head_def;
typedef struct bitmap_head_def *bitmap;
typedef const struct bitmap_head_def *const_bitmap;
diff --git a/gcc/coverage.c b/gcc/coverage.c
index 9bc23c4bd9f..9b0fc8b3d14 100644
--- a/gcc/coverage.c
+++ b/gcc/coverage.c
@@ -554,12 +554,12 @@ unsigned
coverage_compute_profile_id (struct cgraph_node *n)
{
expanded_location xloc
- = expand_location (DECL_SOURCE_LOCATION (n->symbol.decl));
+ = expand_location (DECL_SOURCE_LOCATION (n->decl));
unsigned chksum = xloc.line;
chksum = coverage_checksum_string (chksum, xloc.file);
chksum = coverage_checksum_string
- (chksum, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (n->symbol.decl)));
+ (chksum, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (n->decl)));
if (first_global_object_name)
chksum = coverage_checksum_string
(chksum, first_global_object_name);
@@ -1137,7 +1137,9 @@ coverage_init (const char *filename)
/* Since coverage_init is invoked very early, before the pass
manager, we need to set up the dumping explicitly. This is
similar to the handling in finish_optimization_passes. */
- dump_start (g->get_passes ()->get_pass_profile ()->static_pass_number, NULL);
+ int profile_pass_num =
+ g->get_passes ()->get_pass_profile ()->static_pass_number;
+ g->get_dumps ()->dump_start (profile_pass_num, NULL);
if (!profile_data_prefix && !IS_ABSOLUTE_PATH (filename))
profile_data_prefix = getpwd ();
@@ -1182,7 +1184,7 @@ coverage_init (const char *filename)
}
}
- dump_finish (g->get_passes ()->get_pass_profile ()->static_pass_number);
+ g->get_dumps ()->dump_finish (profile_pass_num);
}
/* Performs file-level cleanup. Close notes file, generate coverage
@@ -1209,6 +1211,9 @@ coverage_finish (void)
fn_ctor = coverage_obj_fn (fn_ctor, fn->fn_decl, fn);
coverage_obj_finish (fn_ctor);
}
+
+ XDELETEVEC (da_file_name);
+ da_file_name = NULL;
}
#include "gt-coverage.h"
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 5ee1f9173b0..4934577ea2a 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,639 @@
+2013-11-10 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * cvt.c (cp_convert_to_pointer): Call build_ptrmemfunc before
+ maybe_warn_zero_as_null_pointer_constant to avoid duplicate
+ -Wzero-as-null-pointer-constant diagnostics.
+
+ * typeck.c (build_ptrmemfunc): Use cp_build_c_cast.
+
+2013-11-06 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/11006
+ * init.c (build_new_1): Don't call build_java_class_ref on non-class
+ types.
+
+2013-11-05 Jason Merrill <jason@redhat.com>
+
+ PR c++/58868
+ * decl.c (check_initializer): Don't use build_vec_init for arrays
+ of trivial type.
+
+2013-11-05 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58724
+ * name-lookup.c (handle_namespace_attrs): Use get_attribute_name.
+
+2013-11-05 Tobias Burnus <burnus@net-b.de>
+
+ * parser.c (cp_parser_omp_for, cp_parser_omp_parallel,
+ cp_parser_omp_distribute, cp_parser_omp_teams, cp_parser_omp_target,
+ cp_parser_omp_declare): Handle -fopenmp-simd.
+
+2013-11-04 Eric Botcazou <ebotcazou@adacore.com>
+
+ * decl2.c (cpp_check): Change type of first parameter and deal with
+ IS_TRIVIAL.
+
+2013-11-03 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/38313
+ * parser.c (cp_parser_constructor_declarator_p): Check that the
+ class-name matches current_class_type.
+
+2013-11-03 Marek Polacek <polacek@redhat.com>
+
+ * decl.c (cp_finish_decl): Move C++1y bounds checking...
+ (compute_array_index_type): ...here. Add VLA instrumentation.
+ Call stabilize_vla_size.
+ (grokdeclarator): Don't call stabilize_vla_size here.
+
+2013-11-02 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/29234
+ PR c++/56037
+ * parser.c (cp_parser_cast_expression): If we aren't looking at
+ a cast-expression don't call cp_parser_type_id.
+ (cp_parser_postfix_expression): Likewise for compound-literal.
+ (cp_parser_tokens_start_cast_expression): Adjust.
+
+2013-11-01 Edward Smith-Rowland <3dw4rd@verizon.net>
+
+ PR c++/58708
+ * parser.c (make_string_pack): Discover non-const type and size
+ of character and build parm pack with correct type and chars.
+
+2013-11-01 Trevor Saunders <tsaunders@mozilla.com>
+
+ * semantics.c (build_anon_member_initialization): Convert fields to be
+ a stack_vec.
+
+2013-11-01 Marc Glisse <marc.glisse@inria.fr>
+
+ PR c++/58834
+ * pt.c (type_dependent_expression_p): Handle null argument.
+
+2013-11-01 Jakub Jelinek <jakub@redhat.com>
+
+ * semantics.c (finish_omp_clauses) <case OMP_CLAUSE_UNIFORM>: Go to
+ check_dup_generic at the end, unless remove is true.
+ (finish_omp_clauses) <case OMP_CLAUSE_LINEAR>: Add break; after
+ remove = true;.
+
+2013-10-31 Jakub Jelinek <jakub@redhat.com>
+
+ * semantics.c (finish_omp_clauses): Diagnose aligned clause
+ with decl that is not pointer nor array nor reference to those.
+
+2013-10-31 Jason Merrill <jason@redhat.com>
+
+ * semantics.c (cxx_eval_call_expression): Handle trivial
+ value-initialization.
+ * typeck2.c (store_init_value): Call maybe_constant_init after
+ cxx_constant_value.
+
+ * decl.c (cxx_maybe_build_cleanup): Always set LOOKUP_NONVIRTUAL.
+ * decl2.c (build_cleanup): Just call cxx_maybe_build_cleanup.
+
+ PR c++/58162
+ * parser.c (cp_parser_late_parse_one_default_arg): Set
+ TARGET_EXPR_DIRECT_INIT_P.
+
+ * class.c (type_build_ctor_call): Return early in C++98 mode.
+ (type_build_dtor_call): Likewise.
+
+2013-10-31 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58932
+ Revert:
+ 2013-10-18 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58466
+ * pt.c (most_specialized_class): Bump processing_template_decl for
+ get_class_bindings.
+
+2013-10-30 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58581
+ * call.c (build_over_call): Check return value of mark_used.
+
+2013-10-30 Jason Merrill <jason@redhat.com>
+
+ * semantics.c (finish_compound_literal): Don't create a static variable
+ inside cp_unevaluated_operand.
+
+ * init.c (push_base_cleanups): Check ANON_AGGR_TYPE_P.
+
+2013-10-30 Tobias Burnus <burnus@net-b.de>
+
+ PR other/33426
+ * cp-tree.h (RANGE_FOR_IVDEP): Define.
+ (cp_convert_range_for, finish_while_stmt_cond, finish_do_stmt,
+ finish_for_cond): Take 'bool ivdep' parameter.
+ * cp-array-notation.c (create_an_loop): Update call.
+ * init.c (build_vec_init): Ditto.
+ * pt.c (tsubst_expr): Ditto.
+ * parser.c (cp_parser_iteration_statement, cp_parser_for,
+ cp_parser_range_for, cp_convert_range_for): Update calls.
+ (cp_parser_pragma): Accept GCC ivdep for 'while' and 'do'.
+ * semantics.c (finish_while_stmt_cond, finish_do_stmt,
+ finish_for_cond): Optionally build ivdep annotation.
+
+2013-10-30 Jason Merrill <jason@redhat.com>
+
+ * decl.c (cp_finish_decl): Never throw for VLA bound == 0.
+
+2013-10-29 David Malcolm <dmalcolm@redhat.com>
+
+ Patch autogenerated by refactor_symtab.py from
+ https://github.com/davidmalcolm/gcc-refactoring-scripts
+ revision 58bb219cc090b2f4516a9297d868c245495ee622
+
+ * call.c (mark_versions_used): Update for conversion of symtab types
+ to a true class hierarchy.
+ * decl2.c (cp_write_global_declarations): Likewise.
+ (clear_decl_external): Likewise.
+ (build_java_method_aliases): Likewise.
+ (collect_candidates_for_java_method_aliases): Likewise.
+ (mark_needed): Likewise.
+ (var_finalized_p): Likewise.
+ (maybe_make_one_only): Likewise.
+ (maybe_emit_vtables): Likewise.
+ * lambda.c (maybe_add_lambda_conv_op): Likewise.
+ * method.c (use_thunk): Likewise.
+ * optimize.c (maybe_clone_body): Likewise.
+ * tree.c (cp_fix_function_decl_p): Likewise.
+
+2013-10-29 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58888
+ * decl2.c (grokfield): Handle auto like NSDMI.
+
+2013-10-25 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58878
+ * pt.c (check_template_shadow): Don't skip declarations in inline
+ member templates.
+
+2013-10-25 Tobias Burnus <burnus@net-b.de>
+
+ PR other/33426
+ * parser.c (cp_parser_iteration_statement,
+ cp_parser_for, cp_parser_c_for, cp_parser_pragma): Handle
+ IVDEP pragma.
+
+2013-10-24 Marek Polacek <polacek@redhat.com>
+
+ PR c++/58705
+ * typeck2.c (check_narrowing): Don't check narrowing when the scalar
+ initializer is empty.
+
+2013-10-23 Jason Merrill <jason@redhat.com>
+
+ LWG 2165
+ * method.c (defaulted_late_check): Delete on eh-spec mismatch.
+ (maybe_explain_implicit_delete): Explain it.
+
+ * error.c (eh_spec_to_string): New.
+ (cp_printer): Use it for %X.
+
+ In C++11 a trivial [cd]tor might not be callable.
+ * class.c (user_provided_p): A function deleted on its declation
+ in the class is not user-provided.
+ (type_build_ctor_call): Also force a ctor call if we
+ might have a deleted or private trivial ctor.
+ (type_build_dtor_call): New.
+ (deduce_noexcept_on_destructors): Remove obsolete code.
+ * cp-tree.h: Declare type_build_dtor_call.
+ * decl.c (expand_static_init): Make sure trivial dtors are callable.
+ (cxx_maybe_build_cleanup): Likewise.
+ * except.c (build_throw): Likewise.
+ * init.c (build_value_init): Handle trivial but not callable ctors.
+ (perform_target_ctor): Make sure trivial dtor is callable.
+ (perform_member_init): Likewise.
+ (expand_cleanup_for_base): Likewise.
+ (build_vec_delete_1): Likewise.
+ (build_delete): Likewise.
+ (push_base_cleanups): Likewise.
+ (build_new_1): Avoid redundant error.
+ * method.c (synthesized_method_walk): Can't ever exit early in C++11.
+ Always process the subobject destructor.
+ * semantics.c (finish_compound_literal): Make sure trivial dtor is
+ callable.
+ * typeck2.c (split_nonconstant_init): Likewise.
+
+2013-10-23 Edward Smith-Rowland <3dw4rd@verizon.net>
+
+ Implement C++14 [[deprecated]] modulo [[gnu::deprecated]] bugs.
+ * parser.c (cp_parser_std_attribute): Interpret [[deprecated]]
+ as [[gnu::deprecated]].
+
+2013-10-22 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58816
+ * pt.c (apply_late_template_attributes): Use get_attribute_name,
+ not TREE_PURPOSE.
+
+2013-10-18 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58466
+ * pt.c (most_specialized_class): Bump processing_template_decl for
+ get_class_bindings.
+
+2013-10-18 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * parser.c (cp_parser_lookup_name): Tidy.
+
+2013-10-17 Andrew MacLeod <amacleod@redhat.com>
+
+ * parser.c: Include omp-low.h.
+ * semantics.c: Likewise.
+
+2013-10-17 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58596
+ * lambda.c (lambda_expr_this_capture): Handle NSDMIs in the
+ cp_unevaluated_operand case.
+
+2013-10-16 Jason Merrill <jason@redhat.com>
+
+ * pt.c (apply_late_template_attributes): Use
+ attribute_takes_identifier_p.
+
+ * error.c (dump_exception_spec): Print "noexcept" rather than
+ "noexcept (true)".
+
+ Core 1591
+ * pt.c (unify_array_domain): Split out from unify.
+ (unify): Use it for list deduction, too.
+
+ PR c++/57850
+ * decl2.c (dump_tu): Split out from...
+ (cp_write_global_declarations): ...here. Call it in PCH mode.
+
+2013-10-16 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * pt.c (tsubst): Fix typo in last commit.
+
+2013-10-16 Paulo Matos <pmatos@broadcom.com>
+
+ * error.c (code_to_string): Use new wrapper get_tree_code_name.
+ * cxx-pretty-print.c (pp_cxx_assignment_operator): Likewise.
+ * pt.c (tsubst): Likewise.
+ * semantics.c (cxx_eval_constant_expression,
+ potential_constant_expression_1): Likewise.
+ * mangle.c (MANGLE_TRACE_TREE, dump_substitution_candidates,
+ add_substitution, find_substitution): Likewise.
+
+2013-10-15 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58707
+ * parser.c (cp_parser_postfix_open_square_expression): Set
+ parser->greater_than_is_operator_p for the argument.
+
+2013-10-11 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58633
+ * parser.c (cp_parser_commit_to_topmost_tentative_parse): New.
+ (cp_parser_pseudo_destructor_name): Use it.
+
+2013-10-11 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/31671
+ * pt.c (convert_nontype_argument): Set expr_type to
+ TREE_TYPE (probe_type).
+
+2013-10-11 Jakub Jelinek <jakub@redhat.com>
+
+ * decl.c (duplicate_decls): Error out for redeclaration of UDRs.
+ (declare_simd_adjust_this): New function.
+ (grokfndecl): If "omp declare simd" attribute is present,
+ call declare_simd_adjust_this if needed and
+ c_omp_declare_simd_clauses_to_numbers.
+ * cp-array-notation.c (expand_array_notation_exprs): Handle
+ OMP_TASKGROUP.
+ * cp-gimplify.c (cp_gimplify_expr): Handle OMP_SIMD and
+ OMP_DISTRIBUTE. Handle is_invisiref_parm decls in
+ OMP_CLAUSE_REDUCTION.
+ (cp_genericize_r): Handle OMP_SIMD and OMP_DISTRIBUTE like
+ OMP_FOR.
+ (cxx_omp_privatize_by_reference): Return true for
+ is_invisiref_parm decls.
+ (cxx_omp_finish_clause): Adjust cxx_omp_create_clause_info
+ caller.
+ * pt.c (apply_late_template_attributes): For "omp declare simd"
+ attribute call tsubst_omp_clauses,
+ c_omp_declare_simd_clauses_to_decls, finish_omp_clauses
+ and c_omp_declare_simd_clauses_to_numbers.
+ (instantiate_class_template_1): Call cp_check_omp_declare_reduction
+ for UDRs.
+ (tsubst_decl): Handle UDRs.
+ (tsubst_omp_clauses): Add declare_simd argument, if true don't
+ call finish_omp_clauses. Handle new OpenMP 4.0 clauses.
+ Handle non-NULL OMP_CLAUSE_REDUCTION_PLACEHOLDER on
+ OMP_CLAUSE_REDUCTION.
+ (tsubst_expr): For UDRs call pushdecl and
+ cp_check_omp_declare_reduction. Adjust tsubst_omp_clauses
+ callers. Handle OMP_SIMD, OMP_DISTRIBUTE, OMP_TEAMS,
+ OMP_TARGET_DATA, OMP_TARGET_UPDATE, OMP_TARGET, OMP_TASKGROUP.
+ Adjust finish_omp_atomic caller.
+ (tsubst_omp_udr): New function.
+ (instantiate_decl): For UDRs at block scope, don't call
+ start_preparsed_function/finish_function. Call tsubst_omp_udr.
+ * semantics.c (cxx_omp_create_clause_info): Add need_dtor argument,
+ use it instead of need_default_ctor || need_copy_ctor.
+ (struct cp_check_omp_declare_reduction_data): New type.
+ (handle_omp_array_sections_1, handle_omp_array_sections,
+ omp_reduction_id, omp_reduction_lookup,
+ cp_remove_omp_priv_cleanup_stmt, cp_check_omp_declare_reduction_r,
+ cp_check_omp_declare_reduction, clone_omp_udr,
+ find_omp_placeholder_r, finish_omp_reduction_clause): New functions.
+ (finish_omp_clauses): Handle new OpenMP 4.0 clauses and user defined
+ reductions.
+ (finish_omp_for): Add CODE argument, use it instead of hardcoded
+ OMP_FOR. Adjust c_finish_omp_for caller.
+ (finish_omp_atomic): Add seq_cst argument, adjust
+ c_finish_omp_atomic callers, handle seq_cst and new OpenMP 4.0
+ atomic variants.
+ (finish_omp_cancel, finish_omp_cancellation_point): New functions.
+ * decl2.c (mark_used): Force immediate instantiation of
+ DECL_OMP_DECLARE_REDUCTION_P decls.
+ (is_late_template_attribute): Return true for "omp declare simd"
+ attribute.
+ (cp_omp_mappable_type): New function.
+ (cplus_decl_attributes): Add implicit "omp declare target" attribute
+ if requested.
+ * parser.c (cp_debug_parser): Print
+ parser->colon_doesnt_start_class_def_p.
+ (cp_ensure_no_omp_declare_simd, cp_finalize_omp_declare_simd): New
+ functions.
+ (enum pragma_context): Add pragma_member and pragma_objc_icode.
+ (cp_parser_binary_expression): Handle no_toplevel_fold_p
+ even for binary operations other than comparison.
+ (cp_parser_linkage_specification): Call
+ cp_ensure_no_omp_declare_simd if needed.
+ (cp_parser_namespace_definition): Likewise.
+ (cp_parser_init_declarator): Call cp_finalize_omp_declare_simd.
+ (cp_parser_direct_declarator): Pass declarator to
+ cp_parser_late_return_type_opt.
+ (cp_parser_late_return_type_opt): Add declarator argument,
+ call cp_parser_late_parsing_omp_declare_simd for declare simd.
+ (cp_parser_class_specifier_1): Call cp_ensure_no_omp_declare_simd.
+ Parse UDRs before all other methods.
+ (cp_parser_member_specification_opt): Use pragma_member instead of
+ pragma_external.
+ (cp_parser_member_declaration): Call cp_finalize_omp_declare_simd.
+ (cp_parser_function_definition_from_specifiers_and_declarator,
+ cp_parser_save_member_function_body): Likewise.
+ (cp_parser_late_parsing_for_member): Handle UDRs specially.
+ (cp_parser_next_token_starts_class_definition_p): Don't allow
+ CPP_COLON if colon_doesnt_start_class_def_p flag is true.
+ (cp_parser_objc_interstitial_code): Use pragma_objc_icode
+ instead of pragma_external.
+ (cp_parser_omp_clause_name): Parse new OpenMP 4.0 clause names.
+ (cp_parser_omp_var_list_no_open): Parse array sections for
+ OMP_CLAUSE_{DEPEND,MAP,TO,FROM} clauses. Add COLON argument,
+ if non-NULL, allow parsing to end with a colon rather than close
+ paren.
+ (cp_parser_omp_var_list): Adjust cp_parser_omp_var_list_no_open
+ caller.
+ (cp_parser_omp_clause_reduction): Handle user defined reductions.
+ (cp_parser_omp_clause_branch, cp_parser_omp_clause_cancelkind,
+ cp_parser_omp_clause_num_teams, cp_parser_omp_clause_thread_limit,
+ cp_parser_omp_clause_aligned, cp_parser_omp_clause_linear,
+ cp_parser_omp_clause_safelen, cp_parser_omp_clause_simdlen,
+ cp_parser_omp_clause_depend, cp_parser_omp_clause_map,
+ cp_parser_omp_clause_device, cp_parser_omp_clause_dist_schedule,
+ cp_parser_omp_clause_proc_bind, cp_parser_omp_clause_to,
+ cp_parser_omp_clause_from, cp_parser_omp_clause_uniform): New
+ functions.
+ (cp_parser_omp_all_clauses): Add finish_p argument. Don't call
+ finish_omp_clauses if it is false. Handle new OpenMP 4.0 clauses.
+ (cp_parser_omp_atomic): Parse seq_cst clause, pass
+ true if it is present to finish_omp_atomic. Handle new OpenMP 4.0
+ atomic forms.
+ (cp_parser_omp_for_loop): Add CODE argument, pass it through
+ to finish_omp_for. Change last argument to cclauses,
+ and adjust uses to grab parallel clauses from the array of all
+ the split clauses.
+ (cp_omp_split_clauses): New function.
+ (cp_parser_omp_simd): New function.
+ (cp_parser_omp_for): Add p_name, mask and cclauses arguments.
+ Allow the function to be called also when parsing combined constructs,
+ and call c_parser_omp_simd when parsing for simd.
+ (cp_parser_omp_sections_scope): If section-sequence doesn't start with
+ #pragma omp section, require exactly one structured-block instead of
+ sequence of statements.
+ (cp_parser_omp_sections): Add p_name, mask and cclauses arguments.
+ Allow the function to be called also when parsing combined constructs.
+ (cp_parser_omp_parallel): Add p_name, mask and cclauses arguments.
+ Allow the function to be called also when parsing combined
+ constructs.
+ (cp_parser_omp_taskgroup, cp_parser_omp_cancel,
+ cp_parser_omp_cancellation_point, cp_parser_omp_distribute,
+ cp_parser_omp_teams, cp_parser_omp_target_data,
+ cp_parser_omp_target_update, cp_parser_omp_target,
+ cp_parser_omp_declare_simd, cp_parser_late_parsing_omp_declare_simd,
+ cp_parser_omp_declare_target, cp_parser_omp_end_declare_target,
+ cp_parser_omp_declare_reduction_exprs, cp_parser_omp_declare_reduction,
+ cp_parser_omp_declare): New functions.
+ (cp_parser_omp_construct): Add p_name and mask vars. Handle
+ PRAGMA_OMP_DISTRIBUTE, PRAGMA_OMP_SIMD, PRAGMA_OMP_TASKGROUP,
+ PRAGMA_OMP_TEAMS. Adjust cp_parser_omp_for, cp_parser_omp_parallel
+ and cp_parser_omp_sections callers.
+ (cp_parser_pragma): Handle PRAGMA_OMP_CANCEL,
+ PRAGMA_OMP_CANCELLATION_POINT, PRAGMA_OMP_DECLARE_REDUCTION,
+ PRAGMA_OMP_DISTRIBUTE, PRAGMA_OMP_SIMD, PRAGMA_OMP_TASKGROUP,
+ PRAGMA_OMP_TEAMS, PRAGMA_OMP_TARGET, PRAGMA_OMP_END_DECLARE_TARGET.
+ Handle pragma_member and pragma_objc_icode like pragma_external.
+ (OMP_FOR_CLAUSE_MASK, OMP_SECTIONS_CLAUSE_MASK,
+ OMP_SINGLE_CLAUSE_MASK): Use OMP_CLAUSE_MASK_1 instead of 1.
+ (OMP_PARALLEL_CLAUSE_MASK): Likewise. Add OMP_CLAUSE_PROC_BIND.
+ (OMP_TASK_CLAUSE_MASK): Use OMP_CLAUSE_MASK_1 instead of 1. Add
+ OMP_CLAUSE_DEPEND.
+ (OMP_SIMD_CLAUSE_MASK, OMP_CANCEL_CLAUSE_MASK,
+ OMP_CANCELLATION_POINT_CLAUSE_MASK, OMP_DISTRIBUTE_CLAUSE_MASK,
+ OMP_TEAMS_CLAUSE_MASK, OMP_TARGET_DATA_CLAUSE_MASK,
+ OMP_TARGET_UPDATE_CLAUSE_MASK, OMP_TARGET_CLAUSE_MASK,
+ OMP_DECLARE_SIMD_CLAUSE_MASK): Define.
+ * parser.h (struct cp_omp_declare_simd_data): New type.
+ (struct cp_parser): Add colon_doesnt_start_class_def_p and
+ omp_declare_simd fields.
+ * cp-objcp-common.h (LANG_HOOKS_OMP_MAPPABLE_TYPE): Define.
+ * cp-tree.h (struct lang_decl_fn): Add omp_declare_reduction_p
+ bit.
+ (DECL_OMP_DECLARE_REDUCTION_P): Define.
+ (OMP_FOR_GIMPLIFYING_P): Use OMP_LOOP_CHECK macro.
+ (struct saved_scope): Add omp_declare_target_attribute field.
+ (cp_omp_mappable_type, omp_reduction_id,
+ cp_remove_omp_priv_cleanup_stmt, cp_check_omp_declare_reduction,
+ finish_omp_cancel, finish_omp_cancellation_point): New prototypes.
+ (finish_omp_for): Add CODE argument.
+ (finish_omp_atomic): Add seq_cst argument.
+ (cxx_omp_create_clause_info): Add need_dtor argument.
+
+2013-10-09 Marek Polacek <polacek@redhat.com>
+
+ PR c++/58635
+ * semantics.c (finish_return_stmt): Return error_mark_node
+ when error_operand_p of the expr is true.
+ (build_transaction_expr): Check for EXPR_P before setting the
+ expr location.
+
+2013-10-08 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58568
+ * lambda.c (begin_lambda_type): Check return value of xref_tag
+ for error_mark_node; tidy.
+ * decl.c (grokdeclarator): Tweak error message.
+
+2013-10-08 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58665
+ Revert:
+ 2013-10-04 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58448
+ * pt.c (tsubst): Use error_operand_p on parameter t.
+
+2013-10-06 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58126
+ * class.c (check_bases): Propagate CLASSTYPE_READONLY_FIELDS_NEED_INIT
+ and CLASSTYPE_REF_FIELDS_NEED_INIT from bases to derived.
+ * init.c (diagnose_uninitialized_cst_or_ref_member_1): Extend error
+ messages about uninitialized const and references members to mention
+ the base class.
+
+2013-10-06 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/56060
+ * pt.c (type_dependent_expression_p): Handle EXPR_PACK_EXPANSION.
+
+2013-10-04 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58560
+ * typeck2.c (build_functional_cast): Use error_operand_p on exp.
+
+2013-10-04 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58503
+ * parser.c (cp_parser_perform_range_for_lookup): If eventually
+ either *begin or *end is type-dependent, return NULL_TREE.
+ (do_range_for_auto_deduction): If cp_parser_perform_range_for_lookup
+ returns NULL_TREE, don't actually do_auto_deduction.
+
+2013-10-04 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58448
+ * pt.c (tsubst): Use error_operand_p on parameter t.
+
+2013-10-04 Marc Glisse <marc.glisse@inria.fr>
+
+ PR c++/19476
+ * decl.c (cxx_init_decl_processing): Set operator_new_flag.
+
+2013-10-04 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58584
+ * decl2.c (save_template_attributes): Handle error_mark_node as
+ *attr_p argument.
+ (cp_check_const_attributes): Likewise for attributes.
+ * parser.c (cp_parser_std_attribute_spec): When alignas_expr is an
+ error_mark_node call cp_parser_skip_to_end_of_statement.
+
+2013-10-03 Easwaran Raman <eraman@google.com>
+
+ PR c++/33911
+ * parser.c (cp_parser_init_declarator): Do not drop attributes
+ of template member functions.
+
+2013-10-03 Marek Polacek <polacek@redhat.com>
+
+ PR c++/58510
+ * init.c (sort_mem_initializers): Splice when giving an error.
+
+2013-10-02 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58535
+ * parser.c (cp_parser_function_specifier_opt): Upon error about
+ virtual templates don't set ds_virtual.
+ (finish_fully_implicit_template): Reject virtual implicit templates.
+
+2013-10-02 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58565
+ * semantics.c (potential_constant_expression_1): Handle LABEL_EXPR.
+
+2013-10-01 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58563
+ * parser.c (cp_parser_lookup_name): Check make_typename_type return
+ value for error_mark_node.
+
+2013-09-25 Tom Tromey <tromey@redhat.com>
+
+ * Make-lang.in (CXX_TREE_H, CXX_PARSER_H, CXX_PRETTY_PRINT_H):
+ Remove.
+
+2013-09-25 Tom Tromey <tromey@redhat.com>
+
+ * Make-lang.in (g++spec.o): Remove.
+ (CFLAGS-cp/g++spec.o): New variable.
+ (GXX_OBJS): Reference cp/g++spec.o.
+ (cc1plus-checksum.o, cp/lex.o, cp/cp-array-notation.o)
+ (cp/cp-lang.o, cp/decl.o, cp/decl2.o, cp/cp-objcp-common.o)
+ (cp/typeck2.o, cp/typeck.o, cp/class.o, cp/call.o)
+ (cp/friend.o, cp/init.o, cp/method.o, cp/cvt.o, cp/search.o)
+ (cp/tree.o, cp/ptree.o, cp/rtti.o, cp/except.o, cp/expr.o)
+ (cp/pt.o, cp/error.o, cp/repo.o, cp/semantics.o, cp/dump.o)
+ (cp/optimize.o, cp/mangle.o, cp/parser.o, cp/cp-gimplify.o)
+ (cp/name-lookup.o, cp/cxx-pretty-print.o): Remove.
+
+2013-09-25 Tom Tromey <tromey@redhat.com>
+
+ * Make-lang.in (g++spec.o): Don't use subshell.
+
+2013-09-25 Marek Polacek <polacek@redhat.com>
+
+ PR c++/58516
+ * semantics.c (finish_transaction_stmt): Check for EXPR_P before
+ setting the expr location.
+
+2013-09-23 Adam Butcher <adam@jessamine.co.uk>
+
+ PR c++/58500
+ * type-utils.h (find_type_usage): Only traverse one type level into
+ member function pointers.
+
+2013-09-23 Adam Butcher <adam@jessamine.co.uk>
+
+ * parser.c (cp_parser_init_declarator): Defer calling
+ finish_fully_implicit_template for forward declarations until after
+ other decl processing is complete. Cleanup for clarity: Extract 'else'
+ case after 'if' containing unconditional return.
+
+2013-09-23 Adam Butcher <adam@jessamine.co.uk>
+
+ * parser.c (make_generic_type_name): Spell generic type names '<autoN>'
+ rather than '__GenN'.
+
+2013-09-23 Adam Butcher <adam@jessamine.co.uk>
+
+ * lambda.c (maybe_add_lambda_conv_op): Don't check for instantiated
+ callop in the case of generic lambdas.
+
+2013-09-23 Adam Butcher <adam@jessamine.co.uk>
+
+ * parser.c (make_generic_type_name): Use global count rather than
+ parameter and ...
+ (add_implicit_template_parms): ... propagate interface change here.
+
+2013-09-20 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58481
+ * pt.c (tsubst_copy): Use current_nonlambda_class_type to
+ call tsubst_baselink.
+
2013-09-18 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/58457
diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in
index 985f22b72d9..9bcea20bd02 100644
--- a/gcc/cp/Make-lang.in
+++ b/gcc/cp/Make-lang.in
@@ -51,14 +51,10 @@ c++: cc1plus$(exeext)
# Tell GNU make to ignore these if they exist.
.PHONY: c++
-g++spec.o: $(srcdir)/cp/g++spec.c $(SYSTEM_H) coretypes.h $(TM_H) $(GCC_H) \
- $(CONFIG_H) $(OPTS_H)
- (SHLIB='$(SHLIB)'; \
- $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(DRIVER_DEFINES) \
- $(INCLUDES) $(srcdir)/cp/g++spec.c)
+CFLAGS-cp/g++spec.o += $(DRIVER_DEFINES)
# Create the compiler driver for g++.
-GXX_OBJS = $(GCC_OBJS) g++spec.o
+GXX_OBJS = $(GCC_OBJS) cp/g++spec.o
xg++$(exeext): $(GXX_OBJS) $(EXTRA_GCC_OBJS) libcommon-target.a $(LIBDEPS)
+$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
$(GXX_OBJS) $(EXTRA_GCC_OBJS) libcommon-target.a \
@@ -98,8 +94,6 @@ cc1plus-checksum.c : build/genchecksum$(build_exeext) checksum-options \
checksum-options > cc1plus-checksum.c.tmp && \
$(srcdir)/../move-if-change cc1plus-checksum.c.tmp cc1plus-checksum.c
-cc1plus-checksum.o : cc1plus-checksum.c $(CONFIG_H) $(SYSTEM_H)
-
cc1plus$(exeext): $(CXX_OBJS) cc1plus-checksum.o $(BACKEND) $(LIBDEPS)
+$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
$(CXX_OBJS) cc1plus-checksum.o $(BACKEND) $(LIBS) $(BACKENDLIBS)
@@ -246,105 +240,3 @@ c++.stageprofile: stageprofile-start
-mv cp/*$(objext) stageprofile/cp
c++.stagefeedback: stagefeedback-start
-mv cp/*$(objext) stagefeedback/cp
-
-#
-# .o: .h dependencies.
-CXX_TREE_H = $(TREE_H) cp/name-lookup.h cp/cp-tree.h $(C_COMMON_H) \
- $(FUNCTION_H) \
- $(SYSTEM_H) coretypes.h $(CONFIG_H) $(TARGET_H) $(GGC_H) \
- $(srcdir)/../include/hashtab.h
-CXX_PARSER_H = tree.h $(CXX_TREE_H) c-family/c-pragma.h cp/parser.h
-CXX_PRETTY_PRINT_H = cp/cxx-pretty-print.h $(C_PRETTY_PRINT_H)
-
-cp/lex.o: cp/lex.c $(CXX_TREE_H) $(TM_H) $(FLAGS_H) \
- $(C_PRAGMA_H) input.h cp/operators.def $(TM_P_H) \
- c-family/c-objc.h
-cp/cp-array-notation.o: cp/cp-array-notation.c $(CONFIG_H) $(SYSTEM_H) \
- coretypes.h $(TREE_H) $(CXX_TREE_H) $(DIAGNOSTIC_H) tree-iterator.h vec.h \
- $(GIMPLE_H) c-family/array-notation-common.o $(C_COMMON_H)
-cp/cp-lang.o: cp/cp-lang.c $(CXX_TREE_H) $(TM_H) debug.h langhooks.h \
- $(LANGHOOKS_DEF_H) $(C_COMMON_H) gtype-cp.h gt-cp-cp-lang.h \
- cp/cp-objcp-common.h $(EXPR_H) $(TARGET_H) $(CXX_PARSER_H)
-cp/decl.o: cp/decl.c $(CXX_TREE_H) $(TM_H) $(FLAGS_H) cp/decl.h \
- output.h toplev.h $(HASHTAB_H) $(RTL_H) \
- cp/operators.def $(TM_P_H) $(TREE_INLINE_H) $(DIAGNOSTIC_H) $(C_PRAGMA_H) \
- debug.h gt-cp-decl.h $(TIMEVAR_H) $(TARGET_H) $(PLUGIN_H) \
- intl.h tree-iterator.h pointer-set.h $(SPLAY_TREE_H) \
- c-family/c-objc.h
-cp/decl2.o: cp/decl2.c $(CXX_TREE_H) $(TM_H) $(FLAGS_H) cp/decl.h \
- toplev.h $(C_COMMON_H) gt-cp-decl2.h $(CGRAPH_H) \
- $(C_PRAGMA_H) dumpfile.h intl.h $(TARGET_H) $(GIMPLE_H) pointer-set.h \
- $(SPLAY_TREE_H) c-family/c-ada-spec.h \
- c-family/c-objc.h
-cp/cp-objcp-common.o : cp/cp-objcp-common.c $(CONFIG_H) $(SYSTEM_H) \
- coretypes.h $(TM_H) $(TREE_H) $(CXX_TREE_H) $(C_COMMON_H) \
- langhooks.h $(LANGHOOKS_DEF_H) $(DIAGNOSTIC_H) debug.h \
- $(CXX_PRETTY_PRINT_H) cp/cp-objcp-common.h gt-cp-cp-objcp-common.h
-cp/typeck2.o: cp/typeck2.c $(CXX_TREE_H) $(TM_H) $(FLAGS_H) \
- $(TM_P_H) $(DIAGNOSTIC_CORE_H) gt-cp-typeck2.h $(REAL_H) intl.h
-cp/typeck.o: cp/typeck.c $(CXX_TREE_H) $(TM_H) $(FLAGS_H) $(PARAMS_H) \
- toplev.h $(DIAGNOSTIC_H) convert.h $(C_COMMON_H) $(TARGET_H) \
- c-family/c-objc.h
-cp/class.o: cp/class.c $(CXX_TREE_H) $(TM_H) $(FLAGS_H) toplev.h \
- $(TARGET_H) convert.h $(CGRAPH_H) dumpfile.h gt-cp-class.h \
- $(SPLAY_TREE_H) pointer-set.h $(HASH_TABLE_H)
-cp/call.o: cp/call.c $(CXX_TREE_H) $(TM_H) $(FLAGS_H) toplev.h \
- $(DIAGNOSTIC_CORE_H) intl.h gt-cp-call.h convert.h $(TARGET_H) langhooks.h \
- $(TIMEVAR_H) c-family/c-objc.h
-cp/friend.o: cp/friend.c $(CXX_TREE_H) $(TM_H) $(FLAGS_H)
-cp/init.o: cp/init.c $(CXX_TREE_H) $(TM_H) $(FLAGS_H) \
- $(EXCEPT_H) $(TARGET_H)
-cp/method.o: cp/method.c $(CXX_TREE_H) $(TM_H) toplev.h \
- $(TM_P_H) $(TARGET_H) $(DIAGNOSTIC_H) gt-cp-method.h $(GIMPLE_H) \
- $(COMMON_TARGET_H)
-cp/cvt.o: cp/cvt.c $(CXX_TREE_H) $(TM_H) cp/decl.h $(FLAGS_H) \
- convert.h $(TARGET_H) intl.h
-cp/search.o: cp/search.c $(CXX_TREE_H) $(TM_H) $(FLAGS_H) toplev.h \
- intl.h
-cp/tree.o: cp/tree.c $(CXX_TREE_H) $(TM_H) $(FLAGS_H) \
- $(TREE_INLINE_H) $(REAL_H) gt-cp-tree.h \
- $(TARGET_H) debug.h $(CGRAPH_H) $(SPLAY_TREE_H) $(GIMPLE_H) $(HASH_TABLE_H)
-cp/ptree.o: cp/ptree.c $(CXX_TREE_H) $(TM_H)
-cp/rtti.o: cp/rtti.c $(CXX_TREE_H) $(TM_H) $(FLAGS_H) convert.h \
- $(TARGET_H) $(C_PRAGMA_H) gt-cp-rtti.h intl.h
-cp/except.o: cp/except.c $(CXX_TREE_H) $(TM_H) $(FLAGS_H) \
- cp/cfns.h $(TREE_INLINE_H) $(TARGET_H) gt-cp-except.h
-cp/expr.o: cp/expr.c $(CXX_TREE_H) $(TM_H) $(FLAGS_H) $(TM_P_H)
-cp/pt.o: cp/pt.c $(CXX_TREE_H) $(TM_H) cp/decl.h cp/cp-objcp-common.h \
- toplev.h $(TREE_INLINE_H) pointer-set.h gt-cp-pt.h intl.h \
- c-family/c-objc.h cp/type-utils.h
-cp/error.o: cp/error.c $(CXX_TREE_H) $(TM_H) $(DIAGNOSTIC_H) \
- $(FLAGS_H) $(REAL_H) $(LANGHOOKS_DEF_H) $(CXX_PRETTY_PRINT_H) \
- tree-diagnostic.h tree-pretty-print.h pointer-set.h c-family/c-objc.h
-cp/repo.o: cp/repo.c $(CXX_TREE_H) $(TM_H) toplev.h $(DIAGNOSTIC_CORE_H) \
- gt-cp-repo.h
-cp/semantics.o: cp/semantics.c $(CXX_TREE_H) $(TM_H) toplev.h \
- $(FLAGS_H) $(RTL_H) $(TIMEVAR_H) \
- $(TREE_INLINE_H) $(CGRAPH_H) $(TARGET_H) $(C_COMMON_H) $(GIMPLE_H) \
- bitmap.h gt-cp-semantics.h c-family/c-objc.h $(HASH_TABLE_H)
-cp/dump.o: cp/dump.c $(CXX_TREE_H) $(TM_H) $(TREE_DUMP_H)
-cp/optimize.o: cp/optimize.c $(CXX_TREE_H) $(TM_H) \
- input.h $(PARAMS_H) debug.h $(TREE_INLINE_H) $(GIMPLE_H) \
- $(TARGET_H) tree-iterator.h $(CGRAPH_H) $(DIAGNOSTIC_CORE_H) \
- dumpfile.h
-cp/mangle.o: cp/mangle.c $(CXX_TREE_H) $(TM_H) $(REAL_H) \
- gt-cp-mangle.h $(TARGET_H) $(TM_P_H) $(CGRAPH_H)
-cp/parser.o: cp/parser.c $(CXX_TREE_H) $(TM_H) $(DIAGNOSTIC_CORE_H) \
- gt-cp-parser.h $(TARGET_H) $(PLUGIN_H) intl.h cp/decl.h \
- c-family/c-objc.h tree-pretty-print.h $(CXX_PARSER_H) $(TIMEVAR_H) \
- cp/type-utils.h
-cp/cp-gimplify.o: cp/cp-gimplify.c $(CXX_TREE_H) $(C_COMMON_H) \
- $(TM_H) coretypes.h pointer-set.h tree-iterator.h $(SPLAY_TREE_H)
-cp/vtable-class-hierarchy.o: cp/vtable-class-hierarchy.c \
- $(TM_H) $(TIMEVAR_H) $(CXX_TREE_H) intl.h $(CXX_PARSER_H) cp/decl.h \
- $(FLAGS_H) $(DIAGNOSTIC_CORE_H) output.h $(CGRAPH_H) c-family/c-common.h \
- c-family/c-objc.h $(PLUGIN_H) \
- tree-iterator.h vtable-verify.h $(GIMPLE_H) \
- gt-cp-vtable-class-hierarchy.h
-cp/name-lookup.o: cp/name-lookup.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(CXX_TREE_H) $(TIMEVAR_H) gt-cp-name-lookup.h $(PARAMS_H) \
- $(DIAGNOSTIC_CORE_H) $(FLAGS_H) debug.h pointer-set.h
-cp/lambda.o: cp/lambda.c $(CXX_TREE_H) $(CGRAPH_H) $(VEC_H) $(SYSTEM_H) coretypes.h
-
-cp/cxx-pretty-print.o: cp/cxx-pretty-print.c $(CXX_PRETTY_PRINT_H) \
- $(CONFIG_H) $(SYSTEM_H) $(TM_H) coretypes.h $(CXX_TREE_H) tree-pretty-print.h
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 3ed73b80374..961ee2c2278 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -6630,7 +6630,7 @@ mark_versions_used (tree fn)
it_v = node_v->next;
while (it_v != NULL)
{
- mark_used (it_v->this_node->symbol.decl);
+ mark_used (it_v->this_node->decl);
it_v = it_v->next;
}
}
@@ -7112,8 +7112,9 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
mark_versions_used (fn);
}
- if (!already_used)
- mark_used (fn);
+ if (!already_used
+ && !mark_used (fn))
+ return error_mark_node;
if (DECL_VINDEX (fn) && (flags & LOOKUP_NONVIRTUAL) == 0
/* Don't mess with virtual lookup in fold_non_dependent_expr; virtual
@@ -9273,6 +9274,9 @@ set_up_extended_ref_temp (tree decl, tree expr, vec<tree, va_gc> **cleanups,
static_aggregates = tree_cons (NULL_TREE, var,
static_aggregates);
}
+ else
+ /* Check whether the dtor is callable. */
+ cxx_maybe_build_cleanup (var, tf_warning_or_error);
}
*initp = init;
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 9e0229fcba3..64681ba44df 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -1517,6 +1517,12 @@ check_bases (tree t,
|= CLASSTYPE_CONTAINS_EMPTY_CLASS_P (basetype);
TYPE_HAS_COMPLEX_DFLT (t) |= (!TYPE_HAS_DEFAULT_CONSTRUCTOR (basetype)
|| TYPE_HAS_COMPLEX_DFLT (basetype));
+ SET_CLASSTYPE_READONLY_FIELDS_NEED_INIT
+ (t, CLASSTYPE_READONLY_FIELDS_NEED_INIT (t)
+ | CLASSTYPE_READONLY_FIELDS_NEED_INIT (basetype));
+ SET_CLASSTYPE_REF_FIELDS_NEED_INIT
+ (t, CLASSTYPE_REF_FIELDS_NEED_INIT (t)
+ | CLASSTYPE_REF_FIELDS_NEED_INIT (basetype));
/* A standard-layout class is a class that:
...
@@ -4668,15 +4674,8 @@ deduce_noexcept_on_destructors (tree t)
if (!CLASSTYPE_METHOD_VEC (t))
return;
- bool saved_nontrivial_dtor = TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t);
-
- /* Avoid early exit from synthesized_method_walk (c++/57645). */
- TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) = true;
-
for (tree fns = CLASSTYPE_DESTRUCTORS (t); fns; fns = OVL_NEXT (fns))
deduce_noexcept_on_destructor (OVL_CURRENT (fns));
-
- TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) = saved_nontrivial_dtor;
}
/* Subroutine of set_one_vmethod_tm_attributes. Search base classes
@@ -4878,7 +4877,8 @@ user_provided_p (tree fn)
return true;
else
return (!DECL_ARTIFICIAL (fn)
- && !DECL_DEFAULTED_IN_CLASS_P (fn));
+ && !(DECL_INITIALIZED_IN_CLASS_P (fn)
+ && (DECL_DEFAULTED_FN (fn) || DECL_DELETED_FN (fn))));
}
/* Returns true iff class T has a user-provided constructor. */
@@ -5143,7 +5143,7 @@ type_has_user_declared_move_assign (tree t)
}
/* Nonzero if we need to build up a constructor call when initializing an
- object of this class, either because it has a user-provided constructor
+ object of this class, either because it has a user-declared constructor
or because it doesn't have a default constructor (so we need to give an
error if no initializer is provided). Use TYPE_NEEDS_CONSTRUCTING when
what you care about is whether or not an object can be produced by a
@@ -5159,8 +5159,50 @@ type_build_ctor_call (tree t)
if (TYPE_NEEDS_CONSTRUCTING (t))
return true;
inner = strip_array_types (t);
- return (CLASS_TYPE_P (inner) && !TYPE_HAS_DEFAULT_CONSTRUCTOR (inner)
- && !ANON_AGGR_TYPE_P (inner));
+ if (!CLASS_TYPE_P (inner) || ANON_AGGR_TYPE_P (inner))
+ return false;
+ if (!TYPE_HAS_DEFAULT_CONSTRUCTOR (inner))
+ return true;
+ if (cxx_dialect < cxx11)
+ return false;
+ /* A user-declared constructor might be private, and a constructor might
+ be trivial but deleted. */
+ for (tree fns = lookup_fnfields_slot (inner, complete_ctor_identifier);
+ fns; fns = OVL_NEXT (fns))
+ {
+ tree fn = OVL_CURRENT (fns);
+ if (!DECL_ARTIFICIAL (fn)
+ || DECL_DELETED_FN (fn))
+ return true;
+ }
+ return false;
+}
+
+/* Like type_build_ctor_call, but for destructors. */
+
+bool
+type_build_dtor_call (tree t)
+{
+ tree inner;
+ if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t))
+ return true;
+ inner = strip_array_types (t);
+ if (!CLASS_TYPE_P (inner) || ANON_AGGR_TYPE_P (inner)
+ || !COMPLETE_TYPE_P (inner))
+ return false;
+ if (cxx_dialect < cxx11)
+ return false;
+ /* A user-declared destructor might be private, and a destructor might
+ be trivial but deleted. */
+ for (tree fns = lookup_fnfields_slot (inner, complete_dtor_identifier);
+ fns; fns = OVL_NEXT (fns))
+ {
+ tree fn = OVL_CURRENT (fns);
+ if (!DECL_ARTIFICIAL (fn)
+ || DECL_DELETED_FN (fn))
+ return true;
+ }
+ return false;
}
/* Remove all zero-width bit-fields from T. */
diff --git a/gcc/cp/cp-array-notation.c b/gcc/cp/cp-array-notation.c
index f4581f01e57..e1fb0ee99ad 100644
--- a/gcc/cp/cp-array-notation.c
+++ b/gcc/cp/cp-array-notation.c
@@ -71,7 +71,7 @@ create_an_loop (tree init, tree cond, tree incr, tree body)
finish_expr_stmt (init);
for_stmt = begin_for_stmt (NULL_TREE, NULL_TREE);
finish_for_init_stmt (for_stmt);
- finish_for_cond (cond, for_stmt);
+ finish_for_cond (cond, for_stmt, false);
finish_for_expr (incr, for_stmt);
finish_expr_stmt (body);
finish_for_stmt (for_stmt);
@@ -1193,6 +1193,7 @@ expand_array_notation_exprs (tree t)
case OMP_SECTION:
case OMP_SECTIONS:
case OMP_MASTER:
+ case OMP_TASKGROUP:
case OMP_ORDERED:
case OMP_CRITICAL:
case OMP_ATOMIC:
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index 590d8577fdc..53b0ca8f928 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -669,6 +669,8 @@ cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
gcc_unreachable ();
case OMP_FOR:
+ case OMP_SIMD:
+ case OMP_DISTRIBUTE:
ret = cp_gimplify_omp_for (expr_p, pre_p);
break;
@@ -934,7 +936,19 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
*walk_subtrees = 0;
break;
case OMP_CLAUSE_REDUCTION:
- gcc_assert (!is_invisiref_parm (OMP_CLAUSE_DECL (stmt)));
+ /* Don't dereference an invisiref in reduction clause's
+ OMP_CLAUSE_DECL either. OMP_CLAUSE_REDUCTION_{INIT,MERGE}
+ still needs to be genericized. */
+ if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt)))
+ {
+ *walk_subtrees = 0;
+ if (OMP_CLAUSE_REDUCTION_INIT (stmt))
+ cp_walk_tree (&OMP_CLAUSE_REDUCTION_INIT (stmt),
+ cp_genericize_r, data, NULL);
+ if (OMP_CLAUSE_REDUCTION_MERGE (stmt))
+ cp_walk_tree (&OMP_CLAUSE_REDUCTION_MERGE (stmt),
+ cp_genericize_r, data, NULL);
+ }
break;
default:
break;
@@ -1116,7 +1130,9 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
genericize_continue_stmt (stmt_p);
else if (TREE_CODE (stmt) == BREAK_STMT)
genericize_break_stmt (stmt_p);
- else if (TREE_CODE (stmt) == OMP_FOR)
+ else if (TREE_CODE (stmt) == OMP_FOR
+ || TREE_CODE (stmt) == OMP_SIMD
+ || TREE_CODE (stmt) == OMP_DISTRIBUTE)
genericize_omp_for_stmt (stmt_p, walk_subtrees, data);
else if (TREE_CODE (stmt) == SIZEOF_EXPR)
{
@@ -1402,7 +1418,8 @@ cxx_omp_clause_dtor (tree clause, tree decl)
bool
cxx_omp_privatize_by_reference (const_tree decl)
{
- return is_invisiref_parm (decl);
+ return (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE
+ || is_invisiref_parm (decl));
}
/* Return true if DECL is const qualified var having no mutable member. */
@@ -1505,7 +1522,7 @@ cxx_omp_finish_clause (tree c)
for making these queries. */
if (!make_shared
&& CLASS_TYPE_P (inner_type)
- && cxx_omp_create_clause_info (c, inner_type, false, true, false))
+ && cxx_omp_create_clause_info (c, inner_type, false, true, false, true))
make_shared = true;
if (make_shared)
diff --git a/gcc/cp/cp-objcp-common.h b/gcc/cp/cp-objcp-common.h
index 47fb20a7870..ee22423ebd4 100644
--- a/gcc/cp/cp-objcp-common.h
+++ b/gcc/cp/cp-objcp-common.h
@@ -145,6 +145,8 @@ extern void cp_common_init_ts (void);
#define LANG_HOOKS_OMP_FINISH_CLAUSE cxx_omp_finish_clause
#undef LANG_HOOKS_OMP_PRIVATIZE_BY_REFERENCE
#define LANG_HOOKS_OMP_PRIVATIZE_BY_REFERENCE cxx_omp_privatize_by_reference
+#undef LANG_HOOKS_OMP_MAPPABLE_TYPE
+#define LANG_HOOKS_OMP_MAPPABLE_TYPE cp_omp_mappable_type
#undef LANG_HOOKS_EH_USE_CXA_END_CLEANUP
#define LANG_HOOKS_EH_USE_CXA_END_CLEANUP true
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index d7840aff89f..fd79adbd357 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -60,7 +60,7 @@ c-common.h, not after.
STMT_EXPR_NO_SCOPE (in STMT_EXPR)
BIND_EXPR_TRY_BLOCK (in BIND_EXPR)
TYPENAME_IS_ENUM_P (in TYPENAME_TYPE)
- OMP_FOR_GIMPLIFYING_P (in OMP_FOR)
+ OMP_FOR_GIMPLIFYING_P (in OMP_FOR, OMP_SIMD and OMP_DISTRIBUTE)
BASELINK_QUALIFIED_P (in BASELINK)
TARGET_EXPR_IMPLICIT_P (in TARGET_EXPR)
TEMPLATE_PARM_PARAMETER_PACK (in TEMPLATE_PARM_INDEX)
@@ -116,6 +116,7 @@ c-common.h, not after.
6: IDENTIFIER_REPO_CHOSEN (in IDENTIFIER_NODE)
DECL_CONSTRUCTION_VTABLE_P (in VAR_DECL)
TYPE_MARKED_P (in _TYPE)
+ RANGE_FOR_IVDEP (in RANGE_FOR_STMT)
Usage of TYPE_LANG_FLAG_?:
0: TYPE_DEPENDENT_P
@@ -1037,6 +1038,9 @@ struct GTY(()) saved_scope {
int unevaluated_operand;
int inhibit_evaluation_warnings;
+ /* If non-zero, implicit "omp declare target" attribute is added into the
+ attribute lists. */
+ int omp_declare_target_attribute;
struct stmt_tree_s x_stmt_tree;
@@ -1979,7 +1983,8 @@ struct GTY(()) lang_decl_fn {
unsigned thunk_p : 1;
unsigned this_thunk_p : 1;
unsigned hidden_friend_p : 1;
- /* 1 spare bit. */
+ unsigned omp_declare_reduction_p : 1;
+ /* No spare bits on 32-bit hosts, 32 on 64-bit hosts. */
/* For a non-thunk function decl, this is a tree list of
friendly classes. For a thunk function decl, it is the
@@ -3181,6 +3186,11 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
#define DECL_HIDDEN_FRIEND_P(NODE) \
(LANG_DECL_FN_CHECK (DECL_COMMON_CHECK (NODE))->hidden_friend_p)
+/* Nonzero if NODE is an artificial FUNCTION_DECL for
+ #pragma omp declare reduction. */
+#define DECL_OMP_DECLARE_REDUCTION_P(NODE) \
+ (LANG_DECL_FN_CHECK (DECL_COMMON_CHECK (NODE))->omp_declare_reduction_p)
+
/* Nonzero if DECL has been declared threadprivate by
#pragma omp threadprivate. */
#define CP_DECL_THREADPRIVATE_P(DECL) \
@@ -4011,7 +4021,7 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
/* Used while gimplifying continue statements bound to OMP_FOR nodes. */
#define OMP_FOR_GIMPLIFYING_P(NODE) \
- (TREE_LANG_FLAG_0 (OMP_FOR_CHECK (NODE)))
+ (TREE_LANG_FLAG_0 (OMP_LOOP_CHECK (NODE)))
/* A language-specific token attached to the OpenMP data clauses to
hold code (or code fragments) related to ctors, dtors, and op=.
@@ -4079,6 +4089,7 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
#define RANGE_FOR_EXPR(NODE) TREE_OPERAND (RANGE_FOR_STMT_CHECK (NODE), 1)
#define RANGE_FOR_BODY(NODE) TREE_OPERAND (RANGE_FOR_STMT_CHECK (NODE), 2)
#define RANGE_FOR_SCOPE(NODE) TREE_OPERAND (RANGE_FOR_STMT_CHECK (NODE), 3)
+#define RANGE_FOR_IVDEP(NODE) TREE_LANG_FLAG_6 (RANGE_FOR_STMT_CHECK (NODE))
#define SWITCH_STMT_COND(NODE) TREE_OPERAND (SWITCH_STMT_CHECK (NODE), 0)
#define SWITCH_STMT_BODY(NODE) TREE_OPERAND (SWITCH_STMT_CHECK (NODE), 1)
@@ -4312,7 +4323,7 @@ extern int comparing_specializations;
sizeof can be nested. */
extern int cp_unevaluated_operand;
-extern tree cp_convert_range_for (tree, tree, tree);
+extern tree cp_convert_range_for (tree, tree, tree, bool);
extern bool parsing_nsdmi (void);
/* in pt.c */
@@ -5106,6 +5117,7 @@ extern bool type_has_move_assign (tree);
extern bool type_has_user_declared_move_constructor (tree);
extern bool type_has_user_declared_move_assign(tree);
extern bool type_build_ctor_call (tree);
+extern bool type_build_dtor_call (tree);
extern void explain_non_literal_class (tree);
extern void defaulted_late_check (tree);
extern bool defaultable_fn_check (tree);
@@ -5299,6 +5311,7 @@ extern bool possibly_inlined_p (tree);
extern int parm_index (tree);
extern tree vtv_start_verification_constructor_init_function (void);
extern tree vtv_finish_verification_constructor_init_function (tree);
+extern bool cp_omp_mappable_type (tree);
/* in error.c */
extern void init_error (void);
@@ -5660,16 +5673,16 @@ extern void begin_else_clause (tree);
extern void finish_else_clause (tree);
extern void finish_if_stmt (tree);
extern tree begin_while_stmt (void);
-extern void finish_while_stmt_cond (tree, tree);
+extern void finish_while_stmt_cond (tree, tree, bool);
extern void finish_while_stmt (tree);
extern tree begin_do_stmt (void);
extern void finish_do_body (tree);
-extern void finish_do_stmt (tree, tree);
+extern void finish_do_stmt (tree, tree, bool);
extern tree finish_return_stmt (tree);
extern tree begin_for_scope (tree *);
extern tree begin_for_stmt (tree, tree);
extern void finish_for_init_stmt (tree);
-extern void finish_for_cond (tree, tree);
+extern void finish_for_cond (tree, tree, bool);
extern void finish_for_expr (tree, tree);
extern void finish_for_stmt (tree);
extern tree begin_range_for_stmt (tree, tree);
@@ -5774,6 +5787,9 @@ extern tree finish_qualified_id_expr (tree, tree, bool, bool,
extern void simplify_aggr_init_expr (tree *);
extern void finalize_nrv (tree *, tree, tree);
extern void note_decl_for_pch (tree);
+extern tree omp_reduction_id (enum tree_code, tree, tree);
+extern tree cp_remove_omp_priv_cleanup_stmt (tree *, int *, void *);
+extern void cp_check_omp_declare_reduction (tree);
extern tree finish_omp_clauses (tree);
extern void finish_omp_threadprivate (tree);
extern tree begin_omp_structured_block (void);
@@ -5782,18 +5798,23 @@ extern tree begin_omp_parallel (void);
extern tree finish_omp_parallel (tree, tree);
extern tree begin_omp_task (void);
extern tree finish_omp_task (tree, tree);
-extern tree finish_omp_for (location_t, tree, tree,
- tree, tree, tree, tree, tree);
+extern tree finish_omp_for (location_t, enum tree_code,
+ tree, tree, tree, tree, tree,
+ tree, tree);
extern void finish_omp_atomic (enum tree_code, enum tree_code,
- tree, tree, tree, tree, tree);
+ tree, tree, tree, tree, tree,
+ bool);
extern void finish_omp_barrier (void);
extern void finish_omp_flush (void);
extern void finish_omp_taskwait (void);
+extern void finish_omp_taskyield (void);
+extern void finish_omp_cancel (tree);
+extern void finish_omp_cancellation_point (tree);
extern tree begin_transaction_stmt (location_t, tree *, int);
extern void finish_transaction_stmt (tree, tree, int, tree);
extern tree build_transaction_expr (location_t, tree, int, tree);
-extern void finish_omp_taskyield (void);
-extern bool cxx_omp_create_clause_info (tree, tree, bool, bool, bool);
+extern bool cxx_omp_create_clause_info (tree, tree, bool, bool,
+ bool, bool);
extern tree baselink_for_fns (tree);
extern void finish_static_assert (tree, tree, location_t,
bool);
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index 08c026da178..7dac108db95 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -203,13 +203,13 @@ cp_convert_to_pointer (tree type, tree expr, tsubst_flags_t complain)
if (null_ptr_cst_p (expr))
{
- if (complain & tf_warning)
- maybe_warn_zero_as_null_pointer_constant (expr, loc);
-
if (TYPE_PTRMEMFUNC_P (type))
return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0,
/*c_cast_p=*/false, complain);
+ if (complain & tf_warning)
+ maybe_warn_zero_as_null_pointer_constant (expr, loc);
+
/* A NULL pointer-to-data-member is represented by -1, not by
zero. */
tree val = (TYPE_PTRDATAMEM_P (type)
diff --git a/gcc/cp/cxx-pretty-print.c b/gcc/cp/cxx-pretty-print.c
index bcef8760ad7..cb97fb5d59a 100644
--- a/gcc/cp/cxx-pretty-print.c
+++ b/gcc/cp/cxx-pretty-print.c
@@ -971,7 +971,7 @@ pp_cxx_assignment_operator (cxx_pretty_printer *pp, tree t)
break;
default:
- op = tree_code_name[TREE_CODE (t)];
+ op = get_tree_code_name (TREE_CODE (t));
break;
}
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 80ceca138d8..8b7a89fcd99 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -45,6 +45,7 @@ along with GCC; see the file COPYING3. If not see
#include "c-family/c-objc.h"
#include "c-family/c-pragma.h"
#include "c-family/c-target.h"
+#include "c-family/c-ubsan.h"
#include "diagnostic.h"
#include "intl.h"
#include "debug.h"
@@ -1341,6 +1342,15 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
}
return NULL_TREE;
}
+ else if (DECL_OMP_DECLARE_REDUCTION_P (olddecl))
+ {
+ gcc_assert (DECL_OMP_DECLARE_REDUCTION_P (newdecl));
+ error_at (DECL_SOURCE_LOCATION (newdecl),
+ "redeclaration of %<pragma omp declare reduction%>");
+ error_at (DECL_SOURCE_LOCATION (olddecl),
+ "previous %<pragma omp declare reduction%> declaration");
+ return error_mark_node;
+ }
else if (!types_match)
{
/* Avoid warnings redeclaring built-ins which have not been
@@ -3800,8 +3810,8 @@ cxx_init_decl_processing (void)
newtype = build_exception_variant (newtype, new_eh_spec);
deltype = cp_build_type_attribute_variant (void_ftype_ptr, extvisattr);
deltype = build_exception_variant (deltype, empty_except_spec);
- push_cp_library_fn (NEW_EXPR, newtype, 0);
- push_cp_library_fn (VEC_NEW_EXPR, newtype, 0);
+ DECL_IS_OPERATOR_NEW (push_cp_library_fn (NEW_EXPR, newtype, 0)) = 1;
+ DECL_IS_OPERATOR_NEW (push_cp_library_fn (VEC_NEW_EXPR, newtype, 0)) = 1;
global_delete_fndecl = push_cp_library_fn (DELETE_EXPR, deltype, ECF_NOTHROW);
push_cp_library_fn (VEC_DELETE_EXPR, deltype, ECF_NOTHROW);
@@ -5673,6 +5683,7 @@ check_initializer (tree decl, tree init, int flags, vec<tree, va_gc> **cleanups)
&& !(init && BRACE_ENCLOSED_INITIALIZER_P (init)
&& CP_AGGREGATE_TYPE_P (type)
&& (CLASS_TYPE_P (type)
+ || !TYPE_NEEDS_CONSTRUCTING (type)
|| type_has_extended_temps (type))))
{
init_code = build_aggr_init_full_exprs (decl, init, flags);
@@ -6390,21 +6401,6 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
&& TYPE_FOR_JAVA (type) && MAYBE_CLASS_TYPE_P (type))
error ("non-static data member %qD has Java class type", decl);
- if (cxx_dialect >= cxx1y && array_of_runtime_bound_p (type))
- {
- /* If the VLA bound is larger than half the address space, or less
- than zero, throw std::bad_array_length. */
- tree max = convert (ssizetype, TYPE_MAX_VALUE (TYPE_DOMAIN (type)));
- /* C++1y says we should throw for length <= 0, but we have
- historically supported zero-length arrays. Let's treat that as an
- extension to be disabled by -std=c++NN. */
- int lower = flag_iso ? 0 : -1;
- tree comp = build2 (LT_EXPR, boolean_type_node, max, ssize_int (lower));
- comp = build3 (COND_EXPR, void_type_node, comp,
- throw_bad_array_length (), void_zero_node);
- finish_expr_stmt (comp);
- }
-
/* Add this declaration to the statement-tree. This needs to happen
after the call to check_initializer so that the DECL_EXPR for a
reference temp is added before the DECL_EXPR for the reference itself. */
@@ -6888,7 +6884,11 @@ expand_static_init (tree decl, tree init)
/* Some variables require no dynamic initialization. */
if (!init
&& TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
- return;
+ {
+ /* Make sure the destructor is callable. */
+ cxx_maybe_build_cleanup (decl, tf_warning_or_error);
+ return;
+ }
if (DECL_THREAD_LOCAL_P (decl) && DECL_GNU_TLS_P (decl)
&& !DECL_FUNCTION_SCOPE_P (decl))
@@ -7302,6 +7302,22 @@ check_static_quals (tree decl, cp_cv_quals quals)
decl);
}
+/* Helper function. Replace the temporary this parameter injected
+ during cp_finish_omp_declare_simd with the real this parameter. */
+
+static tree
+declare_simd_adjust_this (tree *tp, int *walk_subtrees, void *data)
+{
+ tree this_parm = (tree) data;
+ if (TREE_CODE (*tp) == PARM_DECL
+ && DECL_NAME (*tp) == this_identifier
+ && *tp != this_parm)
+ *tp = this_parm;
+ else if (TYPE_P (*tp))
+ *walk_subtrees = 0;
+ return NULL_TREE;
+}
+
/* CTYPE is class type, or null if non-class.
TYPE is type this FUNCTION_DECL should have, either FUNCTION_TYPE
or METHOD_TYPE.
@@ -7620,6 +7636,33 @@ grokfndecl (tree ctype,
if (TYPE_NOTHROW_P (type) || nothrow_libfn_p (decl))
TREE_NOTHROW (decl) = 1;
+ if (flag_openmp)
+ {
+ /* Adjust "omp declare simd" attributes. */
+ tree ods = lookup_attribute ("omp declare simd", *attrlist);
+ if (ods)
+ {
+ tree attr;
+ for (attr = ods; attr;
+ attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr)))
+ {
+ if (TREE_CODE (type) == METHOD_TYPE)
+ walk_tree (&TREE_VALUE (attr), declare_simd_adjust_this,
+ DECL_ARGUMENTS (decl), NULL);
+ if (TREE_VALUE (attr) != NULL_TREE)
+ {
+ tree cl = TREE_VALUE (TREE_VALUE (attr));
+ cl = c_omp_declare_simd_clauses_to_numbers
+ (DECL_ARGUMENTS (decl), cl);
+ if (cl)
+ TREE_VALUE (TREE_VALUE (attr)) = cl;
+ else
+ TREE_VALUE (attr) = NULL_TREE;
+ }
+ }
+ }
+ }
+
/* Caller will do the rest of this. */
if (check < 0)
return decl;
@@ -8327,6 +8370,7 @@ compute_array_index_type (tree name, tree size, tsubst_flags_t complain)
{
/* A variable sized array. */
itype = variable_size (itype);
+
if (TREE_CODE (itype) != SAVE_EXPR)
{
/* Look for SIZEOF_EXPRs in itype and fold them, otherwise
@@ -8338,6 +8382,32 @@ compute_array_index_type (tree name, tree size, tsubst_flags_t complain)
if (found)
itype = variable_size (fold (newitype));
}
+
+ stabilize_vla_size (itype);
+
+ if (cxx_dialect >= cxx1y)
+ {
+ /* If the VLA bound is larger than half the address space,
+ or less than zero, throw std::bad_array_length. */
+ tree comp = build2 (LT_EXPR, boolean_type_node, itype,
+ ssize_int (-1));
+ comp = build3 (COND_EXPR, void_type_node, comp,
+ throw_bad_array_length (), void_zero_node);
+ finish_expr_stmt (comp);
+ }
+ else if (flag_sanitize & SANITIZE_VLA)
+ {
+ /* From C++1y onwards, we throw an exception on a negative
+ length size of an array; see above. */
+
+ /* We have to add 1 -- in the ubsan routine we generate
+ LE_EXPR rather than LT_EXPR. */
+ tree t = fold_build2 (PLUS_EXPR, TREE_TYPE (itype), itype,
+ build_one_cst (TREE_TYPE (itype)));
+ t = fold_build2 (COMPOUND_EXPR, TREE_TYPE (t),
+ ubsan_instrument_vla (input_location, t), t);
+ finish_expr_stmt (t);
+ }
}
/* Make sure that there was no overflow when creating to a signed
index type. (For example, on a 32-bit machine, an array with
@@ -8774,8 +8844,8 @@ grokdeclarator (const cp_declarator *declarator,
&& !uniquely_derived_from_p (ctype,
current_class_type))
{
- error ("type %qT is not derived from type %qT",
- ctype, current_class_type);
+ error ("invalid use of qualified-name %<%T::%D%>",
+ qualifying_scope, decl);
return error_mark_node;
}
}
@@ -9738,12 +9808,8 @@ grokdeclarator (const cp_declarator *declarator,
&& (decl_context == NORMAL || decl_context == FIELD)
&& at_function_scope_p ()
&& variably_modified_type_p (type, NULL_TREE))
- {
- /* First break out any side-effects. */
- stabilize_vla_size (TYPE_SIZE (type));
- /* And then force evaluation of the SAVE_EXPR. */
- finish_expr_stmt (TYPE_SIZE (type));
- }
+ /* Force evaluation of the SAVE_EXPR. */
+ finish_expr_stmt (TYPE_SIZE (type));
if (declarator->kind == cdk_reference)
{
@@ -9834,14 +9900,6 @@ grokdeclarator (const cp_declarator *declarator,
}
}
- /* We need to stabilize side-effects in VLA sizes for regular array
- declarations too, not just pointers to arrays. */
- if (type != error_mark_node && !TYPE_NAME (type)
- && (decl_context == NORMAL || decl_context == FIELD)
- && at_function_scope_p ()
- && variably_modified_type_p (type, NULL_TREE))
- stabilize_vla_size (TYPE_SIZE (type));
-
/* A `constexpr' specifier used in an object declaration declares
the object as `const'. */
if (constexpr_p && innermost_code != cdk_function)
@@ -14244,11 +14302,9 @@ cxx_maybe_build_cleanup (tree decl, tsubst_flags_t complain)
}
/* Handle ordinary C++ destructors. */
type = TREE_TYPE (decl);
- if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
+ if (type_build_dtor_call (type))
{
- int flags = LOOKUP_NORMAL|LOOKUP_DESTRUCTOR;
- bool has_vbases = (TREE_CODE (type) == RECORD_TYPE
- && CLASSTYPE_VBASECLASSES (type));
+ int flags = LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR;
tree addr;
tree call;
@@ -14257,14 +14313,12 @@ cxx_maybe_build_cleanup (tree decl, tsubst_flags_t complain)
else
addr = build_address (decl);
- /* Optimize for space over speed here. */
- if (!has_vbases || flag_expensive_optimizations)
- flags |= LOOKUP_NONVIRTUAL;
-
call = build_delete (TREE_TYPE (addr), addr,
sfk_complete_destructor, flags, 0, complain);
if (call == error_mark_node)
cleanup = error_mark_node;
+ else if (TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
+ /* Discard the call. */;
else if (cleanup)
cleanup = cp_build_compound_expr (cleanup, call, complain);
else
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 4ac9445ecc9..a094ff3b546 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -101,7 +101,6 @@ static GTY(()) vec<tree, va_gc> *no_linkage_decls;
/* Nonzero if we're done parsing and into end-of-file activities. */
int at_eof;
-
/* Return a member function type (a METHOD_TYPE), given FNTYPE (a
@@ -956,26 +955,6 @@ grokfield (const cp_declarator *declarator,
/* C++11 NSDMI, keep going. */;
else if (!VAR_P (value))
gcc_unreachable ();
- else if (!processing_template_decl)
- {
- if (TREE_CODE (init) == CONSTRUCTOR)
- init = digest_init (TREE_TYPE (value), init, tf_warning_or_error);
- init = maybe_constant_init (init);
-
- if (init != error_mark_node && !TREE_CONSTANT (init))
- {
- /* We can allow references to things that are effectively
- static, since references are initialized with the
- address. */
- if (TREE_CODE (TREE_TYPE (value)) != REFERENCE_TYPE
- || (TREE_STATIC (init) == 0
- && (!DECL_P (init) || DECL_EXTERNAL (init) == 0)))
- {
- error ("field initializer is not constant");
- init = error_mark_node;
- }
- }
- }
}
if (processing_template_decl && VAR_OR_FUNCTION_DECL_P (value))
@@ -1135,6 +1114,11 @@ is_late_template_attribute (tree attr, tree decl)
if (is_attribute_p ("unused", name))
return false;
+ /* #pragma omp declare simd attribute needs to be always deferred. */
+ if (flag_openmp
+ && is_attribute_p ("omp declare simd", name))
+ return true;
+
/* If any of the arguments are dependent expressions, we can't evaluate
the attribute until instantiation time. */
for (arg = args; arg; arg = TREE_CHAIN (arg))
@@ -1218,10 +1202,12 @@ splice_template_attributes (tree *attr_p, tree decl)
static void
save_template_attributes (tree *attr_p, tree *decl_p)
{
- tree late_attrs = splice_template_attributes (attr_p, *decl_p);
tree *q;
- tree old_attrs = NULL_TREE;
+ if (attr_p && *attr_p == error_mark_node)
+ return;
+
+ tree late_attrs = splice_template_attributes (attr_p, *decl_p);
if (!late_attrs)
return;
@@ -1230,7 +1216,7 @@ save_template_attributes (tree *attr_p, tree *decl_p)
else
q = &TYPE_ATTRIBUTES (*decl_p);
- old_attrs = *q;
+ tree old_attrs = *q;
/* Merge the late attributes at the beginning with the attribute
list. */
@@ -1318,6 +1304,9 @@ cp_reconstruct_complex_type (tree type, tree bottom)
static void
cp_check_const_attributes (tree attributes)
{
+ if (attributes == error_mark_node)
+ return;
+
tree attr;
for (attr = attributes; attr; attr = TREE_CHAIN (attr))
{
@@ -1331,6 +1320,34 @@ cp_check_const_attributes (tree attributes)
}
}
+/* Return true if TYPE is an OpenMP mappable type. */
+bool
+cp_omp_mappable_type (tree type)
+{
+ /* Mappable type has to be complete. */
+ if (type == error_mark_node || !COMPLETE_TYPE_P (type))
+ return false;
+ /* Arrays have mappable type if the elements have mappable type. */
+ while (TREE_CODE (type) == ARRAY_TYPE)
+ type = TREE_TYPE (type);
+ /* A mappable type cannot contain virtual members. */
+ if (CLASS_TYPE_P (type) && CLASSTYPE_VTABLES (type))
+ return false;
+ /* All data members must be non-static. */
+ if (CLASS_TYPE_P (type))
+ {
+ tree field;
+ for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
+ if (TREE_CODE (field) == VAR_DECL)
+ return false;
+ /* All fields must have mappable types. */
+ else if (TREE_CODE (field) == FIELD_DECL
+ && !cp_omp_mappable_type (TREE_TYPE (field)))
+ return false;
+ }
+ return true;
+}
+
/* Like decl_attributes, but handle C++ complexity. */
void
@@ -1340,6 +1357,30 @@ cplus_decl_attributes (tree *decl, tree attributes, int flags)
|| *decl == error_mark_node)
return;
+ /* Add implicit "omp declare target" attribute if requested. */
+ if (scope_chain->omp_declare_target_attribute
+ && ((TREE_CODE (*decl) == VAR_DECL && TREE_STATIC (*decl))
+ || TREE_CODE (*decl) == FUNCTION_DECL))
+ {
+ if (TREE_CODE (*decl) == VAR_DECL
+ && DECL_CLASS_SCOPE_P (*decl))
+ error ("%q+D static data member inside of declare target directive",
+ *decl);
+ else if (TREE_CODE (*decl) == VAR_DECL
+ && (DECL_FUNCTION_SCOPE_P (*decl)
+ || (current_function_decl && !DECL_EXTERNAL (*decl))))
+ error ("%q+D in block scope inside of declare target directive",
+ *decl);
+ else if (!processing_template_decl
+ && TREE_CODE (*decl) == VAR_DECL
+ && !cp_omp_mappable_type (TREE_TYPE (*decl)))
+ error ("%q+D in declare target directive does not have mappable type",
+ *decl);
+ else
+ attributes = tree_cons (get_identifier ("omp declare target"),
+ NULL_TREE, attributes);
+ }
+
if (processing_template_decl)
{
if (check_for_bare_parameter_packs (attributes))
@@ -1706,7 +1747,7 @@ maybe_make_one_only (tree decl)
struct varpool_node *node = varpool_node_for_decl (decl);
DECL_COMDAT (decl) = 1;
/* Mark it needed so we don't forget to emit it. */
- node->symbol.forced_by_abi = true;
+ node->forced_by_abi = true;
TREE_USED (decl) = 1;
}
}
@@ -1804,7 +1845,7 @@ import_export_class (tree ctype)
static bool
var_finalized_p (tree var)
{
- return varpool_node_for_decl (var)->symbol.definition;
+ return varpool_node_for_decl (var)->definition;
}
/* DECL is a VAR_DECL or FUNCTION_DECL which, for whatever reason,
@@ -1821,14 +1862,14 @@ mark_needed (tree decl)
functions can be marked reachable, just use the external
definition. */
struct cgraph_node *node = cgraph_get_create_node (decl);
- node->symbol.forced_by_abi = true;
+ node->forced_by_abi = true;
}
else if (TREE_CODE (decl) == VAR_DECL)
{
struct varpool_node *node = varpool_node_for_decl (decl);
/* C++ frontend use mark_decl_references to force COMDAT variables
to be output that might appear dead otherwise. */
- node->symbol.forced_by_abi = true;
+ node->forced_by_abi = true;
}
}
@@ -1938,7 +1979,7 @@ maybe_emit_vtables (tree ctype)
{
current = varpool_node_for_decl (vtbl);
if (last)
- symtab_add_to_same_comdat_group ((symtab_node) current, (symtab_node) last);
+ symtab_add_to_same_comdat_group (current, last);
last = current;
}
}
@@ -2681,26 +2722,9 @@ import_export_decl (tree decl)
tree
build_cleanup (tree decl)
{
- tree temp;
- tree type = TREE_TYPE (decl);
-
- /* This function should only be called for declarations that really
- require cleanups. */
- gcc_assert (!TYPE_HAS_TRIVIAL_DESTRUCTOR (type));
-
- /* Treat all objects with destructors as used; the destructor may do
- something substantive. */
- mark_used (decl);
-
- if (TREE_CODE (type) == ARRAY_TYPE)
- temp = decl;
- else
- temp = build_address (decl);
- temp = build_delete (TREE_TYPE (temp), temp,
- sfk_complete_destructor,
- LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0,
- tf_warning_or_error);
- return temp;
+ tree clean = cxx_maybe_build_cleanup (decl, tf_warning_or_error);
+ gcc_assert (clean != NULL_TREE);
+ return clean;
}
/* Returns the initialization guard variable for the variable DECL,
@@ -3703,7 +3727,7 @@ collect_candidates_for_java_method_aliases (void)
FOR_EACH_FUNCTION (node)
{
- tree fndecl = node->symbol.decl;
+ tree fndecl = node->decl;
if (DECL_CLASS_SCOPE_P (fndecl)
&& TYPE_FOR_JAVA (DECL_CONTEXT (fndecl))
@@ -3736,7 +3760,7 @@ build_java_method_aliases (struct pointer_set_t *candidates)
FOR_EACH_FUNCTION (node)
{
- tree fndecl = node->symbol.decl;
+ tree fndecl = node->decl;
if (TREE_ASM_WRITTEN (fndecl)
&& pointer_set_contains (candidates, fndecl))
@@ -3765,7 +3789,7 @@ build_java_method_aliases (struct pointer_set_t *candidates)
/* Return C++ property of T, based on given operation OP. */
static int
-cpp_check (tree t, cpp_operation op)
+cpp_check (const_tree t, cpp_operation op)
{
switch (op)
{
@@ -3779,6 +3803,8 @@ cpp_check (tree t, cpp_operation op)
return DECL_COPY_CONSTRUCTOR_P (t);
case IS_TEMPLATE:
return TREE_CODE (t) == TEMPLATE_DECL;
+ case IS_TRIVIAL:
+ return trivial_type_p (t);
default:
return 0;
}
@@ -3917,7 +3943,7 @@ collect_all_refs (const char *source_file)
static bool
clear_decl_external (struct cgraph_node *node, void * /*data*/)
{
- DECL_EXTERNAL (node->symbol.decl) = 0;
+ DECL_EXTERNAL (node->decl) = 0;
return false;
}
@@ -3980,6 +4006,22 @@ handle_tls_init (void)
expand_or_defer_fn (finish_function (0));
}
+/* The entire file is now complete. If requested, dump everything
+ to a file. */
+
+static void
+dump_tu (void)
+{
+ int flags;
+ FILE *stream = dump_begin (TDI_tu, &flags);
+
+ if (stream)
+ {
+ dump_node (global_namespace, flags & ~TDF_SLIM, stream);
+ dump_end (TDI_tu, stream);
+ }
+}
+
/* This routine is called at the end of compilation.
Its job is to create all the code needed to initialize and
destroy the global aggregates. We do the destruction
@@ -4010,6 +4052,7 @@ cp_write_global_declarations (void)
if (pch_file)
{
c_common_write_pch ();
+ dump_tu ();
return;
}
@@ -4218,7 +4261,7 @@ cp_write_global_declarations (void)
struct cgraph_node *node, *next;
node = cgraph_get_node (decl);
- if (node->symbol.cpp_implicit_alias)
+ if (node->cpp_implicit_alias)
node = cgraph_alias_target (node);
cgraph_for_node_and_aliases (node, clear_decl_external,
@@ -4226,10 +4269,10 @@ cp_write_global_declarations (void)
/* If we mark !DECL_EXTERNAL one of the symbols in some comdat
group, we need to mark all symbols in the same comdat group
that way. */
- if (node->symbol.same_comdat_group)
- for (next = cgraph (node->symbol.same_comdat_group);
+ if (node->same_comdat_group)
+ for (next = cgraph (node->same_comdat_group);
next != node;
- next = cgraph (next->symbol.same_comdat_group))
+ next = cgraph (next->same_comdat_group))
cgraph_for_node_and_aliases (next, clear_decl_external,
NULL, true);
}
@@ -4241,7 +4284,7 @@ cp_write_global_declarations (void)
if (!DECL_EXTERNAL (decl)
&& decl_needed_p (decl)
&& !TREE_ASM_WRITTEN (decl)
- && !cgraph_get_node (decl)->symbol.definition)
+ && !cgraph_get_node (decl)->definition)
{
/* We will output the function; no longer consider it in this
loop. */
@@ -4396,16 +4439,7 @@ cp_write_global_declarations (void)
/* The entire file is now complete. If requested, dump everything
to a file. */
- {
- int flags;
- FILE *stream = dump_begin (TDI_tu, &flags);
-
- if (stream)
- {
- dump_node (global_namespace, flags & ~TDF_SLIM, stream);
- dump_end (TDI_tu, stream);
- }
- }
+ dump_tu ();
if (flag_detailed_statistics)
{
@@ -4618,13 +4652,16 @@ mark_used (tree decl, tsubst_flags_t complain)
or a constexpr function, we need it right now because a reference to
such a data member or a call to such function is not value-dependent.
For a function that uses auto in the return type, we need to instantiate
- it to find out its type. */
- if ((decl_maybe_constant_var_p (decl)
- || (TREE_CODE (decl) == FUNCTION_DECL
- && DECL_DECLARED_CONSTEXPR_P (decl))
- || undeduced_auto_decl (decl))
- && DECL_LANG_SPECIFIC (decl)
+ it to find out its type. For OpenMP user defined reductions, we need
+ them instantiated for reduction clauses which inline them by hand
+ directly. */
+ if (DECL_LANG_SPECIFIC (decl)
&& DECL_TEMPLATE_INFO (decl)
+ && (decl_maybe_constant_var_p (decl)
+ || (TREE_CODE (decl) == FUNCTION_DECL
+ && (DECL_DECLARED_CONSTEXPR_P (decl)
+ || DECL_OMP_DECLARE_REDUCTION_P (decl)))
+ || undeduced_auto_decl (decl))
&& !uses_template_parms (DECL_TI_ARGS (decl)))
{
/* Instantiating a function will result in garbage collection. We
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index 62e39d3bcbf..5f997c3ed29 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -1595,13 +1595,16 @@ dump_exception_spec (cxx_pretty_printer *pp, tree t, int flags)
if (t && TREE_PURPOSE (t))
{
pp_cxx_ws_string (pp, "noexcept");
- pp_cxx_whitespace (pp);
- pp_cxx_left_paren (pp);
- if (DEFERRED_NOEXCEPT_SPEC_P (t))
- pp_cxx_ws_string (pp, "<uninstantiated>");
- else
- dump_expr (pp, TREE_PURPOSE (t), flags);
- pp_cxx_right_paren (pp);
+ if (!integer_onep (TREE_PURPOSE (t)))
+ {
+ pp_cxx_whitespace (pp);
+ pp_cxx_left_paren (pp);
+ if (DEFERRED_NOEXCEPT_SPEC_P (t))
+ pp_cxx_ws_string (pp, "<uninstantiated>");
+ else
+ dump_expr (pp, TREE_PURPOSE (t), flags);
+ pp_cxx_right_paren (pp);
+ }
}
else if (t)
{
@@ -2852,7 +2855,7 @@ fndecl_to_string (tree fndecl, int verbose)
static const char *
code_to_string (enum tree_code c)
{
- return tree_code_name [c];
+ return get_tree_code_name (c);
}
const char *
@@ -2995,6 +2998,15 @@ cv_to_string (tree p, int v)
return pp_ggc_formatted_text (cxx_pp);
}
+static const char *
+eh_spec_to_string (tree p, int /*v*/)
+{
+ int flags = 0;
+ reinit_cxx_pp ();
+ dump_exception_spec (cxx_pp, p, flags);
+ return pp_ggc_formatted_text (cxx_pp);
+}
+
/* Langhook for print_error_function. */
void
cxx_print_error_function (diagnostic_context *context, const char *file,
@@ -3376,8 +3388,10 @@ maybe_print_constexpr_context (diagnostic_context *context)
%O binary operator.
%P function parameter whose position is indicated by an integer.
%Q assignment operator.
+ %S substitution (template + args)
%T type.
- %V cv-qualifier. */
+ %V cv-qualifier.
+ %X exception-specification. */
static bool
cp_printer (pretty_printer *pp, text_info *text, const char *spec,
int precision, bool wide, bool set_locus, bool verbose)
@@ -3424,6 +3438,7 @@ cp_printer (pretty_printer *pp, text_info *text, const char *spec,
case 'S': result = subst_to_string (next_tree); break;
case 'T': result = type_to_string (next_tree, verbose); break;
case 'V': result = cv_to_string (next_tree, verbose); break;
+ case 'X': result = eh_spec_to_string (next_tree, verbose); break;
case 'K':
percent_K_format (text);
diff --git a/gcc/cp/except.c b/gcc/cp/except.c
index c76d9440aa9..daac0fde7e6 100644
--- a/gcc/cp/except.c
+++ b/gcc/cp/except.c
@@ -868,17 +868,21 @@ build_throw (tree exp)
throw_type = build_eh_type_type (prepare_eh_type (TREE_TYPE (object)));
- if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (object)))
+ cleanup = NULL_TREE;
+ if (type_build_dtor_call (TREE_TYPE (object)))
{
- cleanup = lookup_fnfields (TYPE_BINFO (TREE_TYPE (object)),
+ tree fn = lookup_fnfields (TYPE_BINFO (TREE_TYPE (object)),
complete_dtor_identifier, 0);
- cleanup = BASELINK_FUNCTIONS (cleanup);
- mark_used (cleanup);
- cxx_mark_addressable (cleanup);
- /* Pretend it's a normal function. */
- cleanup = build1 (ADDR_EXPR, cleanup_type, cleanup);
+ fn = BASELINK_FUNCTIONS (fn);
+ mark_used (fn);
+ if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (object)))
+ {
+ cxx_mark_addressable (fn);
+ /* Pretend it's a normal function. */
+ cleanup = build1 (ADDR_EXPR, cleanup_type, fn);
+ }
}
- else
+ if (cleanup == NULL_TREE)
cleanup = build_int_cst (cleanup_type, 0);
/* ??? Indicate that this function call throws throw_type. */
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 8fabdcdb948..a4d8280dfd8 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -312,60 +312,55 @@ build_value_init (tree type, tsubst_flags_t complain)
To value-initialize an object of type T means:
- - if T is a class type (clause 9) with a user-provided constructor
- (12.1), then the default constructor for T is called (and the
- initialization is ill-formed if T has no accessible default
- constructor);
+ - if T is a class type (clause 9) with either no default constructor
+ (12.1) or a default constructor that is user-provided or deleted,
+ then then the object is default-initialized;
- - if T is a non-union class type without a user-provided constructor,
- then every non-static data member and base-class component of T is
- value-initialized;92)
+ - if T is a (possibly cv-qualified) class type without a user-provided
+ or deleted default constructor, then the object is zero-initialized
+ and the semantic constraints for default-initialization are checked,
+ and if T has a non-trivial default constructor, the object is
+ default-initialized;
- if T is an array type, then each element is value-initialized;
- otherwise, the object is zero-initialized.
A program that calls for default-initialization or
- value-initialization of an entity of reference type is ill-formed.
-
- 92) Value-initialization for such a class object may be implemented by
- zero-initializing the object and then calling the default
- constructor. */
+ value-initialization of an entity of reference type is ill-formed. */
/* The AGGR_INIT_EXPR tweaking below breaks in templates. */
gcc_assert (!processing_template_decl
|| (SCALAR_TYPE_P (type) || TREE_CODE (type) == ARRAY_TYPE));
- if (CLASS_TYPE_P (type))
+ if (type_build_ctor_call (type))
{
- /* Instead of the above, only consider the user-providedness of the
- default constructor itself so value-initializing a class with an
- explicitly defaulted default constructor and another user-provided
- constructor works properly (c++std-core-19883). */
- if (type_has_user_provided_default_constructor (type)
- || (!TYPE_HAS_DEFAULT_CONSTRUCTOR (type)
- && type_has_user_provided_constructor (type)))
- return build_aggr_init_expr
- (type,
- build_special_member_call (NULL_TREE, complete_ctor_identifier,
- NULL, type, LOOKUP_NORMAL,
- complain));
+ tree ctor = build_aggr_init_expr
+ (type,
+ build_special_member_call (NULL_TREE, complete_ctor_identifier,
+ NULL, type, LOOKUP_NORMAL,
+ complain));
+ if (ctor == error_mark_node
+ || type_has_user_provided_default_constructor (type))
+ return ctor;
else if (TYPE_HAS_COMPLEX_DFLT (type))
{
/* This is a class that needs constructing, but doesn't have
a user-provided constructor. So we need to zero-initialize
the object and then call the implicitly defined ctor.
This will be handled in simplify_aggr_init_expr. */
- tree ctor = build_special_member_call
- (NULL_TREE, complete_ctor_identifier,
- NULL, type, LOOKUP_NORMAL, complain);
- ctor = build_aggr_init_expr (type, ctor);
- if (ctor != error_mark_node)
- AGGR_INIT_ZERO_FIRST (ctor) = 1;
+ AGGR_INIT_ZERO_FIRST (ctor) = 1;
return ctor;
}
}
- return build_value_init_noctor (type, complain);
+
+ /* Discard any access checking during subobject initialization;
+ the checks are implied by the call to the ctor which we have
+ verified is OK (cpp0x/defaulted46.C). */
+ push_deferring_access_checks (dk_deferred);
+ tree r = build_value_init_noctor (type, complain);
+ pop_deferring_access_checks ();
+ return r;
}
/* Like build_value_init, but don't call the constructor for TYPE. Used
@@ -503,14 +498,15 @@ perform_target_ctor (tree init)
finish_expr_stmt (build_aggr_init (decl, init,
LOOKUP_NORMAL|LOOKUP_DELEGATING_CONS,
tf_warning_or_error));
- if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
+ if (type_build_dtor_call (type))
{
tree expr = build_delete (type, decl, sfk_complete_destructor,
LOOKUP_NORMAL
|LOOKUP_NONVIRTUAL
|LOOKUP_DESTRUCTOR,
0, tf_warning_or_error);
- if (expr != error_mark_node)
+ if (expr != error_mark_node
+ && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
finish_eh_cleanup (expr);
}
}
@@ -732,7 +728,7 @@ perform_member_init (tree member, tree init)
tf_warning_or_error));
}
- if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
+ if (type_build_dtor_call (type))
{
tree expr;
@@ -744,7 +740,8 @@ perform_member_init (tree member, tree init)
LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0,
tf_warning_or_error);
- if (expr != error_mark_node)
+ if (expr != error_mark_node
+ && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
finish_eh_cleanup (expr);
}
}
@@ -980,9 +977,12 @@ sort_mem_initializers (tree t, tree mem_inits)
else if (TREE_VALUE (*last_p) && !TREE_VALUE (init))
goto splice;
else
- error_at (DECL_SOURCE_LOCATION (current_function_decl),
- "initializations for multiple members of %qT",
- ctx);
+ {
+ error_at (DECL_SOURCE_LOCATION (current_function_decl),
+ "initializations for multiple members of %qT",
+ ctx);
+ goto splice;
+ }
}
last_p = p;
@@ -1189,7 +1189,7 @@ expand_cleanup_for_base (tree binfo, tree flag)
{
tree expr;
- if (TYPE_HAS_TRIVIAL_DESTRUCTOR (BINFO_TYPE (binfo)))
+ if (!type_build_dtor_call (BINFO_TYPE (binfo)))
return;
/* Call the destructor. */
@@ -1199,6 +1199,10 @@ expand_cleanup_for_base (tree binfo, tree flag)
binfo,
LOOKUP_NORMAL | LOOKUP_NONVIRTUAL,
tf_warning_or_error);
+
+ if (TYPE_HAS_TRIVIAL_DESTRUCTOR (BINFO_TYPE (binfo)))
+ return;
+
if (flag)
expr = fold_build3_loc (input_location,
COND_EXPR, void_type_node,
@@ -2117,11 +2121,24 @@ diagnose_uninitialized_cst_or_ref_member_1 (tree type, tree origin,
++ error_count;
if (complain)
{
- if (using_new)
- error ("uninitialized reference member in %q#T "
- "using %<new%> without new-initializer", origin);
+ if (DECL_CONTEXT (field) == origin)
+ {
+ if (using_new)
+ error ("uninitialized reference member in %q#T "
+ "using %<new%> without new-initializer", origin);
+ else
+ error ("uninitialized reference member in %q#T", origin);
+ }
else
- error ("uninitialized reference member in %q#T", origin);
+ {
+ if (using_new)
+ error ("uninitialized reference member in base %q#T "
+ "of %q#T using %<new%> without new-initializer",
+ DECL_CONTEXT (field), origin);
+ else
+ error ("uninitialized reference member in base %q#T "
+ "of %q#T", DECL_CONTEXT (field), origin);
+ }
inform (DECL_SOURCE_LOCATION (field),
"%qD should be initialized", field);
}
@@ -2132,11 +2149,24 @@ diagnose_uninitialized_cst_or_ref_member_1 (tree type, tree origin,
++ error_count;
if (complain)
{
- if (using_new)
- error ("uninitialized const member in %q#T "
- "using %<new%> without new-initializer", origin);
+ if (DECL_CONTEXT (field) == origin)
+ {
+ if (using_new)
+ error ("uninitialized const member in %q#T "
+ "using %<new%> without new-initializer", origin);
+ else
+ error ("uninitialized const member in %q#T", origin);
+ }
else
- error ("uninitialized const member in %q#T", origin);
+ {
+ if (using_new)
+ error ("uninitialized const member in base %q#T "
+ "of %q#T using %<new%> without new-initializer",
+ DECL_CONTEXT (field), origin);
+ else
+ error ("uninitialized const member in base %q#T "
+ "of %q#T", DECL_CONTEXT (field), origin);
+ }
inform (DECL_SOURCE_LOCATION (field),
"%qD should be initialized", field);
}
@@ -2331,7 +2361,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
is_initialized = (type_build_ctor_call (elt_type) || *init != NULL);
- if (*init == NULL)
+ if (*init == NULL && cxx_dialect < cxx11)
{
bool maybe_uninitialized_error = false;
/* A program that calls for default-initialization [...] of an
@@ -2431,9 +2461,16 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
if (vec_safe_is_empty (*placement) && TYPE_FOR_JAVA (elt_type))
{
tree class_addr;
- tree class_decl = build_java_class_ref (elt_type);
+ tree class_decl;
static const char alloc_name[] = "_Jv_AllocObject";
+ if (!MAYBE_CLASS_TYPE_P (elt_type))
+ {
+ error ("%qT isn%'t a valid Java class type", elt_type);
+ return error_mark_node;
+ }
+
+ class_decl = build_java_class_ref (elt_type);
if (class_decl == error_mark_node)
return error_mark_node;
@@ -3123,8 +3160,21 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
size_exp = size_in_bytes (type);
- if (! MAYBE_CLASS_TYPE_P (type) || TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
+ if (! MAYBE_CLASS_TYPE_P (type))
goto no_destructor;
+ else if (TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
+ {
+ /* Make sure the destructor is callable. */
+ if (type_build_dtor_call (type))
+ {
+ tmp = build_delete (ptype, base, sfk_complete_destructor,
+ LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 1,
+ complain);
+ if (tmp == error_mark_node)
+ return error_mark_node;
+ }
+ goto no_destructor;
+ }
/* The below is short by the cookie size. */
virtual_size = size_binop (MULT_EXPR, size_exp,
@@ -3624,7 +3674,7 @@ build_vec_init (tree base, tree maxindex, tree init,
finish_for_init_stmt (for_stmt);
finish_for_cond (build2 (NE_EXPR, boolean_type_node, iterator,
build_int_cst (TREE_TYPE (iterator), -1)),
- for_stmt);
+ for_stmt, false);
elt_init = cp_build_unary_op (PREDECREMENT_EXPR, iterator, 0,
complain);
if (elt_init == error_mark_node)
@@ -3800,7 +3850,7 @@ build_dtor_call (tree exp, special_function_kind dtor_kind, int flags,
flags. See cp-tree.h for more info. */
tree
-build_delete (tree type, tree addr, special_function_kind auto_delete,
+build_delete (tree otype, tree addr, special_function_kind auto_delete,
int flags, int use_global_delete, tsubst_flags_t complain)
{
tree expr;
@@ -3808,22 +3858,33 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
if (addr == error_mark_node)
return error_mark_node;
+ tree type = TYPE_MAIN_VARIANT (otype);
+
/* Can happen when CURRENT_EXCEPTION_OBJECT gets its type
set to `error_mark_node' before it gets properly cleaned up. */
if (type == error_mark_node)
return error_mark_node;
- type = TYPE_MAIN_VARIANT (type);
+ if (TREE_CODE (type) == POINTER_TYPE)
+ type = TYPE_MAIN_VARIANT (TREE_TYPE (type));
- addr = mark_rvalue_use (addr);
+ if (TREE_CODE (type) == ARRAY_TYPE)
+ {
+ if (TYPE_DOMAIN (type) == NULL_TREE)
+ {
+ if (complain & tf_error)
+ error ("unknown array size in delete");
+ return error_mark_node;
+ }
+ return build_vec_delete (addr, array_type_nelts (type),
+ auto_delete, use_global_delete, complain);
+ }
- if (TYPE_PTR_P (type))
+ if (TYPE_PTR_P (otype))
{
bool complete_p = true;
- type = TYPE_MAIN_VARIANT (TREE_TYPE (type));
- if (TREE_CODE (type) == ARRAY_TYPE)
- goto handle_array;
+ addr = mark_rvalue_use (addr);
/* We don't want to warn about delete of void*, only other
incomplete types. Deleting other incomplete types
@@ -3879,19 +3940,6 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
/* Throw away const and volatile on target type of addr. */
addr = convert_force (build_pointer_type (type), addr, 0, complain);
}
- else if (TREE_CODE (type) == ARRAY_TYPE)
- {
- handle_array:
-
- if (TYPE_DOMAIN (type) == NULL_TREE)
- {
- if (complain & tf_error)
- error ("unknown array size in delete");
- return error_mark_node;
- }
- return build_vec_delete (addr, array_type_nelts (type),
- auto_delete, use_global_delete, complain);
- }
else
{
/* Don't check PROTECT here; leave that decision to the
@@ -3906,10 +3954,18 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
addr = convert_force (build_pointer_type (type), addr, 0, complain);
}
- gcc_assert (MAYBE_CLASS_TYPE_P (type));
-
if (TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
{
+ /* Make sure the destructor is callable. */
+ if (type_build_dtor_call (type))
+ {
+ expr = build_dtor_call (cp_build_indirect_ref (addr, RO_NULL,
+ complain),
+ sfk_complete_destructor, flags, complain);
+ if (expr == error_mark_node)
+ return error_mark_node;
+ }
+
if (auto_delete != sfk_deleting_destructor)
return void_zero_node;
@@ -4033,7 +4089,7 @@ push_base_cleanups (void)
for (vbases = CLASSTYPE_VBASECLASSES (current_class_type), i = 0;
vec_safe_iterate (vbases, i, &base_binfo); i++)
{
- if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (BINFO_TYPE (base_binfo)))
+ if (type_build_dtor_call (BINFO_TYPE (base_binfo)))
{
expr = build_special_member_call (current_class_ref,
base_dtor_identifier,
@@ -4041,10 +4097,13 @@ push_base_cleanups (void)
base_binfo,
(LOOKUP_NORMAL
| LOOKUP_NONVIRTUAL),
- tf_warning_or_error);
- expr = build3 (COND_EXPR, void_type_node, cond,
- expr, void_zero_node);
- finish_decl_cleanup (NULL_TREE, expr);
+ tf_warning_or_error);
+ if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (BINFO_TYPE (base_binfo)))
+ {
+ expr = build3 (COND_EXPR, void_type_node, cond,
+ expr, void_zero_node);
+ finish_decl_cleanup (NULL_TREE, expr);
+ }
}
}
}
@@ -4053,8 +4112,8 @@ push_base_cleanups (void)
for (binfo = TYPE_BINFO (current_class_type), i = 0;
BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
{
- if (TYPE_HAS_TRIVIAL_DESTRUCTOR (BINFO_TYPE (base_binfo))
- || BINFO_VIRTUAL_P (base_binfo))
+ if (BINFO_VIRTUAL_P (base_binfo)
+ || !type_build_dtor_call (BINFO_TYPE (base_binfo)))
continue;
expr = build_special_member_call (current_class_ref,
@@ -4062,7 +4121,8 @@ push_base_cleanups (void)
NULL, base_binfo,
LOOKUP_NORMAL | LOOKUP_NONVIRTUAL,
tf_warning_or_error);
- finish_decl_cleanup (NULL_TREE, expr);
+ if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (BINFO_TYPE (base_binfo)))
+ finish_decl_cleanup (NULL_TREE, expr);
}
/* Don't automatically destroy union members. */
@@ -4077,9 +4137,9 @@ push_base_cleanups (void)
|| TREE_CODE (member) != FIELD_DECL
|| DECL_ARTIFICIAL (member))
continue;
- if (ANON_UNION_TYPE_P (this_type))
+ if (ANON_AGGR_TYPE_P (this_type))
continue;
- if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (this_type))
+ if (type_build_dtor_call (this_type))
{
tree this_member = (build_class_member_access_expr
(current_class_ref, member,
@@ -4090,7 +4150,8 @@ push_base_cleanups (void)
sfk_complete_destructor,
LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_NORMAL,
0, tf_warning_or_error);
- finish_decl_cleanup (NULL_TREE, expr);
+ if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (this_type))
+ finish_decl_cleanup (NULL_TREE, expr);
}
}
}
diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c
index b04448b5487..f39ce1a5ea6 100644
--- a/gcc/cp/lambda.c
+++ b/gcc/cp/lambda.c
@@ -138,6 +138,8 @@ begin_lambda_type (tree lambda)
name,
/*scope=*/ts_lambda,
/*template_header_p=*/false);
+ if (type == error_mark_node)
+ return error_mark_node;
}
/* Designate it as a struct so that we can use aggregate initialization. */
@@ -152,8 +154,6 @@ begin_lambda_type (tree lambda)
/* Start the class. */
type = begin_class_definition (type);
- if (type == error_mark_node)
- return error_mark_node;
return type;
}
@@ -628,7 +628,14 @@ lambda_expr_this_capture (tree lambda)
/* In unevaluated context this isn't an odr-use, so just return the
nearest 'this'. */
if (cp_unevaluated_operand)
- return lookup_name (this_identifier);
+ {
+ /* In an NSDMI the fake 'this' pointer that we're using for
+ parsing is in scope_chain. */
+ if (LAMBDA_EXPR_EXTRA_SCOPE (lambda)
+ && TREE_CODE (LAMBDA_EXPR_EXTRA_SCOPE (lambda)) == FIELD_DECL)
+ return scope_chain->x_current_class_ptr;
+ return lookup_name (this_identifier);
+ }
/* Try to default capture 'this' if we can. */
if (!this_capture
@@ -810,7 +817,7 @@ maybe_add_lambda_conv_op (tree type)
= (DECL_TEMPLATE_INFO (callop)
&& DECL_TEMPLATE_RESULT (DECL_TI_TEMPLATE (callop)) == callop);
- if (DECL_INITIAL (callop) == NULL_TREE)
+ if (!generic_lambda_p && DECL_INITIAL (callop) == NULL_TREE)
{
/* If the op() wasn't instantiated due to errors, give up. */
gcc_assert (errorcount || sorrycount);
@@ -1013,8 +1020,8 @@ maybe_add_lambda_conv_op (tree type)
{
/* Put the thunk in the same comdat group as the call op. */
symtab_add_to_same_comdat_group
- ((symtab_node) cgraph_get_create_node (statfn),
- (symtab_node) cgraph_get_create_node (callop));
+ (cgraph_get_create_node (statfn),
+ cgraph_get_create_node (callop));
}
tree body = begin_function_body ();
tree compound_stmt = begin_compound_stmt (0);
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index 8c11ba8d394..202fafceb03 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -69,7 +69,7 @@ along with GCC; see the file COPYING3. If not see
fprintf (stderr, " %-24s: %-24s\n", (FN), (INPUT))
# define MANGLE_TRACE_TREE(FN, NODE) \
fprintf (stderr, " %-24s: %-24s (%p)\n", \
- (FN), tree_code_name[TREE_CODE (NODE)], (void *) (NODE))
+ (FN), get_tree_code_name (TREE_CODE (NODE)), (void *) (NODE))
#else
# define MANGLE_TRACE(FN, INPUT)
# define MANGLE_TRACE_TREE(FN, NODE)
@@ -329,7 +329,7 @@ dump_substitution_candidates (void)
|| CP_TYPE_CONST_P (el)))
fprintf (stderr, "CV-");
fprintf (stderr, "%s (%s at %p)\n",
- name, tree_code_name[TREE_CODE (el)], (void *) el);
+ name, get_tree_code_name (TREE_CODE (el)), (void *) el);
}
}
@@ -379,13 +379,13 @@ add_substitution (tree node)
if (DEBUG_MANGLE)
fprintf (stderr, " ++ add_substitution (%s at %10p)\n",
- tree_code_name[TREE_CODE (node)], (void *) node);
+ get_tree_code_name (TREE_CODE (node)), (void *) node);
/* Get the canonicalized substitution candidate for NODE. */
c = canonicalize_for_substitution (node);
if (DEBUG_MANGLE && c != node)
fprintf (stderr, " ++ using candidate (%s at %10p)\n",
- tree_code_name[TREE_CODE (node)], (void *) node);
+ get_tree_code_name (TREE_CODE (node)), (void *) node);
node = c;
#if ENABLE_CHECKING
@@ -513,7 +513,7 @@ find_substitution (tree node)
if (DEBUG_MANGLE)
fprintf (stderr, " ++ find_substitution (%s at %p)\n",
- tree_code_name[TREE_CODE (node)], (void *) node);
+ get_tree_code_name (TREE_CODE (node)), (void *) node);
/* Obtain the canonicalized substitution representation for NODE.
This is what we'll compare against. */
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index 4ac533eacf7..353e99a6410 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -386,8 +386,8 @@ use_thunk (tree thunk_fndecl, bool emit_p)
this_adjusting, fixed_offset, virtual_value,
virtual_offset, alias);
if (DECL_ONE_ONLY (function))
- symtab_add_to_same_comdat_group ((symtab_node) thunk_node,
- (symtab_node) funcn);
+ symtab_add_to_same_comdat_group (thunk_node,
+ funcn);
if (!this_adjusting
|| !targetm.asm_out.can_output_mi_thunk (thunk_fndecl, fixed_offset,
@@ -1265,8 +1265,9 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
class versions and other properties of the type. But a subobject
class can be trivially copyable and yet have overload resolution
choose a template constructor for initialization, depending on
- rvalueness and cv-quals. So we can't exit early for copy/move
- methods in C++0x. The same considerations apply in C++98/03, but
+ rvalueness and cv-quals. And furthermore, a member in a base might
+ be trivial but deleted or otherwise not callable. So we can't exit
+ early in C++0x. The same considerations apply in C++98/03, but
there the definition of triviality does not consider overload
resolution, so a constructor can be trivial even if it would otherwise
call a non-trivial constructor. */
@@ -1282,7 +1283,7 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
inform (input_location, "defaulted default constructor does "
"not initialize any non-static data member");
}
- if (!diag)
+ if (!diag && cxx_dialect < cxx11)
return;
}
@@ -1323,7 +1324,7 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
process_subob_fn (rval, spec_p, trivial_p, deleted_p,
constexpr_p, diag, basetype);
- if (ctor_p && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (basetype))
+ if (ctor_p)
{
/* In a constructor we also need to check the subobject
destructors for cleanup of partially constructed objects. */
@@ -1465,13 +1466,34 @@ maybe_explain_implicit_delete (tree decl)
tree parms = FUNCTION_FIRST_USER_PARMTYPE (decl);
tree parm_type = TREE_VALUE (parms);
bool const_p = CP_TYPE_CONST_P (non_reference (parm_type));
+ tree raises = NULL_TREE;
+ bool deleted_p = false;
tree scope = push_scope (ctype);
- inform (0, "%q+#D is implicitly deleted because the default "
- "definition would be ill-formed:", decl);
- pop_scope (scope);
+
synthesized_method_walk (ctype, sfk, const_p,
- NULL, NULL, NULL, NULL, true,
+ &raises, NULL, &deleted_p, NULL, false,
DECL_INHERITED_CTOR_BASE (decl), parms);
+ if (deleted_p)
+ {
+ inform (0, "%q+#D is implicitly deleted because the default "
+ "definition would be ill-formed:", decl);
+ synthesized_method_walk (ctype, sfk, const_p,
+ NULL, NULL, NULL, NULL, true,
+ DECL_INHERITED_CTOR_BASE (decl), parms);
+ }
+ else if (!comp_except_specs
+ (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (decl)),
+ raises, ce_normal))
+ inform (DECL_SOURCE_LOCATION (decl), "%q#F is implicitly "
+ "deleted because its exception-specification does not "
+ "match the implicit exception-specification %qX",
+ decl, raises);
+#ifdef ENABLE_CHECKING
+ else
+ gcc_unreachable ();
+#endif
+
+ pop_scope (scope);
}
input_location = loc;
@@ -1781,9 +1803,10 @@ defaulted_late_check (tree fn)
eh_spec, ce_normal))
{
if (DECL_DEFAULTED_IN_CLASS_P (fn))
- error ("function %q+D defaulted on its first declaration "
- "with an exception-specification that differs from "
- "the implicit declaration %q#D", fn, implicit_fn);
+ {
+ DECL_DELETED_FN (fn) = true;
+ eh_spec = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn));
+ }
else
error ("function %q+D defaulted on its redeclaration "
"with an exception-specification that differs from "
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 025a03cd9fa..ced596e310a 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -3571,7 +3571,7 @@ handle_namespace_attrs (tree ns, tree attributes)
for (d = attributes; d; d = TREE_CHAIN (d))
{
- tree name = TREE_PURPOSE (d);
+ tree name = get_attribute_name (d);
tree args = TREE_VALUE (d);
if (is_attribute_p ("visibility", name))
diff --git a/gcc/cp/optimize.c b/gcc/cp/optimize.c
index 1b524c3561e..c4ee8484bb9 100644
--- a/gcc/cp/optimize.c
+++ b/gcc/cp/optimize.c
@@ -339,7 +339,7 @@ maybe_clone_body (tree fn)
virtual, it goes into the same comdat group as well. */
if (comdat_group)
symtab_add_to_same_comdat_group
- ((symtab_node) cgraph_get_create_node (clone),
+ (cgraph_get_create_node (clone),
symtab_get_node (fns[0]));
}
else if (alias)
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 2cd60f0db9d..1ff56fed336 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -39,6 +39,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-pretty-print.h"
#include "parser.h"
#include "type-utils.h"
+#include "omp-low.h"
/* The lexer. */
@@ -232,6 +233,9 @@ static void cp_parser_initial_pragma
static tree cp_literal_operator_id
(const char *);
+static bool cp_parser_omp_declare_reduction_exprs
+ (tree, cp_parser *);
+
/* Manifest constants. */
#define CP_LEXER_BUFFER_SIZE ((256 * 1024) / sizeof (cp_token))
#define CP_SAVED_TOKEN_STACK 5
@@ -542,6 +546,8 @@ cp_debug_parser (FILE *file, cp_parser *parser)
"local class", parser->in_function_body);
cp_debug_print_flag (file, "Auto correct a colon to a scope operator",
parser->colon_corrects_to_scope_p);
+ cp_debug_print_flag (file, "Colon doesn't start a class definition",
+ parser->colon_doesnt_start_class_def_p);
if (parser->type_definition_forbidden_message)
fprintf (file, "Error message for forbidden type definitions: %s\n",
parser->type_definition_forbidden_message);
@@ -1222,6 +1228,40 @@ cp_token_cache_new (cp_token *first, cp_token *last)
return cache;
}
+/* Diagnose if #pragma omp declare simd isn't followed immediately
+ by function declaration or definition. */
+
+static inline void
+cp_ensure_no_omp_declare_simd (cp_parser *parser)
+{
+ if (parser->omp_declare_simd && !parser->omp_declare_simd->error_seen)
+ {
+ error ("%<#pragma omp declare simd%> not immediately followed by "
+ "function declaration or definition");
+ parser->omp_declare_simd = NULL;
+ }
+}
+
+/* Finalize #pragma omp declare simd clauses after FNDECL has been parsed,
+ and put that into "omp declare simd" attribute. */
+
+static inline void
+cp_finalize_omp_declare_simd (cp_parser *parser, tree fndecl)
+{
+ if (__builtin_expect (parser->omp_declare_simd != NULL, 0))
+ {
+ if (fndecl == error_mark_node)
+ {
+ parser->omp_declare_simd = NULL;
+ return;
+ }
+ if (TREE_CODE (fndecl) != FUNCTION_DECL)
+ {
+ cp_ensure_no_omp_declare_simd (parser);
+ return;
+ }
+ }
+}
/* Decl-specifiers. */
@@ -1930,15 +1970,15 @@ static tree cp_parser_selection_statement
static tree cp_parser_condition
(cp_parser *);
static tree cp_parser_iteration_statement
- (cp_parser *);
+ (cp_parser *, bool);
static bool cp_parser_for_init_statement
(cp_parser *, tree *decl);
static tree cp_parser_for
- (cp_parser *);
+ (cp_parser *, bool);
static tree cp_parser_c_for
- (cp_parser *, tree, tree);
+ (cp_parser *, tree, tree, bool);
static tree cp_parser_range_for
- (cp_parser *, tree, tree, tree);
+ (cp_parser *, tree, tree, tree, bool);
static void do_range_for_auto_deduction
(tree, tree);
static tree cp_parser_perform_range_for_lookup
@@ -2030,7 +2070,7 @@ static cp_virt_specifiers cp_parser_virt_specifier_seq_opt
static cp_ref_qualifier cp_parser_ref_qualifier_opt
(cp_parser *);
static tree cp_parser_late_return_type_opt
- (cp_parser *, cp_cv_quals);
+ (cp_parser *, cp_declarator *, cp_cv_quals);
static tree cp_parser_declarator_id
(cp_parser *, bool);
static tree cp_parser_type_id
@@ -2064,6 +2104,9 @@ static vec<constructor_elt, va_gc> *cp_parser_initializer_list
static bool cp_parser_ctor_initializer_opt_and_function_body
(cp_parser *, bool);
+static tree cp_parser_late_parsing_omp_declare_simd
+ (cp_parser *, tree);
+
static tree add_implicit_template_parms
(cp_parser *, size_t, tree);
static tree finish_fully_implicit_template
@@ -2211,7 +2254,13 @@ static bool cp_parser_function_transaction
static tree cp_parser_transaction_cancel
(cp_parser *);
-enum pragma_context { pragma_external, pragma_stmt, pragma_compound };
+enum pragma_context {
+ pragma_external,
+ pragma_member,
+ pragma_objc_icode,
+ pragma_stmt,
+ pragma_compound
+};
static bool cp_parser_pragma
(cp_parser *, enum pragma_context);
@@ -2347,6 +2396,8 @@ static void cp_parser_parse_tentatively
(cp_parser *);
static void cp_parser_commit_to_tentative_parse
(cp_parser *);
+static void cp_parser_commit_to_topmost_tentative_parse
+ (cp_parser *);
static void cp_parser_abort_tentative_parse
(cp_parser *);
static bool cp_parser_parse_definitely
@@ -3742,22 +3793,39 @@ make_string_pack (tree value)
tree charvec;
tree argpack = make_node (NONTYPE_ARGUMENT_PACK);
const char *str = TREE_STRING_POINTER (value);
- int i, len = TREE_STRING_LENGTH (value) - 1;
+ int sz = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (value))));
+ int len = TREE_STRING_LENGTH (value) / sz - 1;
tree argvec = make_tree_vec (2);
- tree string_char_type_node = TREE_TYPE (TREE_TYPE (value));
+ tree str_char_type_node = TREE_TYPE (TREE_TYPE (value));
+ str_char_type_node = TYPE_MAIN_VARIANT (str_char_type_node);
/* First template parm is character type. */
- TREE_VEC_ELT (argvec, 0) = string_char_type_node;
+ TREE_VEC_ELT (argvec, 0) = str_char_type_node;
/* Fill in CHARVEC with all of the parameters. */
charvec = make_tree_vec (len);
- for (i = 0; i < len; ++i)
- TREE_VEC_ELT (charvec, i) = build_int_cst (string_char_type_node, str[i]);
+ if (sz == 1)
+ {
+ for (int i = 0; i < len; ++i)
+ TREE_VEC_ELT (charvec, i) = build_int_cst (str_char_type_node, str[i]);
+ }
+ else if (sz == 2)
+ {
+ const uint16_t *num = (const uint16_t *)str;
+ for (int i = 0; i < len; ++i)
+ TREE_VEC_ELT (charvec, i) = build_int_cst (str_char_type_node, num[i]);
+ }
+ else if (sz == 4)
+ {
+ const uint32_t *num = (const uint32_t *)str;
+ for (int i = 0; i < len; ++i)
+ TREE_VEC_ELT (charvec, i) = build_int_cst (str_char_type_node, num[i]);
+ }
/* Build the argument packs. */
SET_ARGUMENT_PACK_ARGS (argpack, charvec);
- TREE_TYPE (argpack) = string_char_type_node;
+ TREE_TYPE (argpack) = str_char_type_node;
TREE_VEC_ELT (argvec, 1) = argpack;
@@ -5749,31 +5817,45 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
&& cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
{
tree initializer = NULL_TREE;
- bool saved_in_type_id_in_expr_p;
+ bool compound_literal_p;
cp_parser_parse_tentatively (parser);
/* Consume the `('. */
cp_lexer_consume_token (parser->lexer);
- /* Parse the type. */
- saved_in_type_id_in_expr_p = parser->in_type_id_in_expr_p;
- parser->in_type_id_in_expr_p = true;
- type = cp_parser_type_id (parser);
- parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
- /* Look for the `)'. */
- cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+
+ /* Avoid calling cp_parser_type_id pointlessly, see comment
+ in cp_parser_cast_expression about c++/29234. */
+ cp_lexer_save_tokens (parser->lexer);
+
+ compound_literal_p
+ = (cp_parser_skip_to_closing_parenthesis (parser, false, false,
+ /*consume_paren=*/true)
+ && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE));
+
+ /* Roll back the tokens we skipped. */
+ cp_lexer_rollback_tokens (parser->lexer);
+
+ if (!compound_literal_p)
+ cp_parser_simulate_error (parser);
+ else
+ {
+ /* Parse the type. */
+ bool saved_in_type_id_in_expr_p = parser->in_type_id_in_expr_p;
+ parser->in_type_id_in_expr_p = true;
+ type = cp_parser_type_id (parser);
+ parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
+ /* Look for the `)'. */
+ cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+ }
+
/* If things aren't going well, there's no need to
keep going. */
if (!cp_parser_error_occurred (parser))
{
- if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
- {
- bool non_constant_p;
- /* Parse the brace-enclosed initializer list. */
- initializer = cp_parser_braced_list (parser,
- &non_constant_p);
- }
- else
- cp_parser_simulate_error (parser);
+ bool non_constant_p;
+ /* Parse the brace-enclosed initializer list. */
+ initializer = cp_parser_braced_list (parser,
+ &non_constant_p);
}
/* If that worked, we're definitely looking at a
compound-literal expression. */
@@ -6181,10 +6263,14 @@ cp_parser_postfix_open_square_expression (cp_parser *parser,
{
tree index = NULL_TREE;
location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+ bool saved_greater_than_is_operator_p;
/* Consume the `[' token. */
cp_lexer_consume_token (parser->lexer);
+ saved_greater_than_is_operator_p = parser->greater_than_is_operator_p;
+ parser->greater_than_is_operator_p = true;
+
/* Parse the index expression. */
/* ??? For offsetof, there is a question of what to allow here. If
offsetof is not being used in an integral constant expression context,
@@ -6228,6 +6314,8 @@ cp_parser_postfix_open_square_expression (cp_parser *parser,
index = cp_parser_expression (parser, /*cast_p=*/false, NULL);
}
+ parser->greater_than_is_operator_p = saved_greater_than_is_operator_p;
+
/* Look for the closing `]'. */
cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE);
@@ -6693,7 +6781,7 @@ cp_parser_pseudo_destructor_name (cp_parser* parser,
/* Once we see the ~, this has to be a pseudo-destructor. */
if (!processing_template_decl && !cp_parser_error_occurred (parser))
- cp_parser_commit_to_tentative_parse (parser);
+ cp_parser_commit_to_topmost_tentative_parse (parser);
/* Look for the type-name again. We are not responsible for
checking that it matches the first type-name. */
@@ -7435,6 +7523,7 @@ cp_parser_tokens_start_cast_expression (cp_parser *parser)
case CPP_CLOSE_SQUARE:
case CPP_CLOSE_PAREN:
case CPP_CLOSE_BRACE:
+ case CPP_OPEN_BRACE:
case CPP_DOT:
case CPP_DOT_STAR:
case CPP_DEREF:
@@ -7502,7 +7591,7 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p,
{
tree type = NULL_TREE;
tree expr = NULL_TREE;
- bool compound_literal_p;
+ bool cast_expression_p;
const char *saved_message;
/* There's no way to know yet whether or not this is a cast.
@@ -7525,26 +7614,38 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p,
will commit to the parse at that point, because we cannot
undo the action that is done when creating a new class. So,
then we cannot back up and do a postfix-expression.
+ Another tricky case is the following (c++/29234):
+
+ struct S { void operator () (); };
+
+ void foo ()
+ {
+ ( S()() );
+ }
+
+ As a type-id we parse the parenthesized S()() as a function
+ returning a function, groktypename complains and we cannot
+ back up in this case either.
Therefore, we scan ahead to the closing `)', and check to see
- if the token after the `)' is a `{'. If so, we are not
- looking at a cast-expression.
+ if the tokens after the `)' can start a cast-expression. Otherwise
+ we are dealing with an unary-expression, a postfix-expression
+ or something else.
Save tokens so that we can put them back. */
cp_lexer_save_tokens (parser->lexer);
- /* Skip tokens until the next token is a closing parenthesis.
- If we find the closing `)', and the next token is a `{', then
- we are looking at a compound-literal. */
- compound_literal_p
+
+ /* We may be looking at a cast-expression. */
+ cast_expression_p
= (cp_parser_skip_to_closing_parenthesis (parser, false, false,
/*consume_paren=*/true)
- && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE));
+ && cp_parser_tokens_start_cast_expression (parser));
+
/* Roll back the tokens we skipped. */
cp_lexer_rollback_tokens (parser->lexer);
- /* If we were looking at a compound-literal, simulate an error
- so that the call to cp_parser_parse_definitely below will
- fail. */
- if (compound_literal_p)
+ /* If we aren't looking at a cast-expression, simulate an error so
+ that the call to cp_parser_parse_definitely below will fail. */
+ if (!cast_expression_p)
cp_parser_simulate_error (parser);
else
{
@@ -7563,8 +7664,7 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p,
/* At this point this can only be either a cast or a
parenthesized ctor such as `(T ())' that looks like a cast to
function returning T. */
- if (!cp_parser_error_occurred (parser)
- && cp_parser_tokens_start_cast_expression (parser))
+ if (!cp_parser_error_occurred (parser))
{
cp_parser_parse_definitely (parser);
expr = cp_parser_cast_expression (parser,
@@ -7807,9 +7907,11 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p,
*/
if (no_toplevel_fold_p
&& lookahead_prec <= current.prec
- && sp == stack
- && TREE_CODE_CLASS (current.tree_type) == tcc_comparison)
- current.lhs = build2 (current.tree_type, boolean_type_node,
+ && sp == stack)
+ current.lhs = build2 (current.tree_type,
+ TREE_CODE_CLASS (current.tree_type)
+ == tcc_comparison
+ ? boolean_type_node : TREE_TYPE (current.lhs),
current.lhs, rhs);
else
current.lhs = build_x_binary_op (current.loc, current.tree_type,
@@ -9172,7 +9274,7 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
case RID_WHILE:
case RID_DO:
case RID_FOR:
- statement = cp_parser_iteration_statement (parser);
+ statement = cp_parser_iteration_statement (parser, false);
break;
case RID_BREAK:
@@ -9833,7 +9935,7 @@ cp_parser_condition (cp_parser* parser)
not included. */
static tree
-cp_parser_for (cp_parser *parser)
+cp_parser_for (cp_parser *parser, bool ivdep)
{
tree init, scope, decl;
bool is_range_for;
@@ -9845,13 +9947,13 @@ cp_parser_for (cp_parser *parser)
is_range_for = cp_parser_for_init_statement (parser, &decl);
if (is_range_for)
- return cp_parser_range_for (parser, scope, init, decl);
+ return cp_parser_range_for (parser, scope, init, decl, ivdep);
else
- return cp_parser_c_for (parser, scope, init);
+ return cp_parser_c_for (parser, scope, init, ivdep);
}
static tree
-cp_parser_c_for (cp_parser *parser, tree scope, tree init)
+cp_parser_c_for (cp_parser *parser, tree scope, tree init, bool ivdep)
{
/* Normal for loop */
tree condition = NULL_TREE;
@@ -9866,7 +9968,13 @@ cp_parser_c_for (cp_parser *parser, tree scope, tree init)
/* If there's a condition, process it. */
if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
condition = cp_parser_condition (parser);
- finish_for_cond (condition, stmt);
+ else if (ivdep)
+ {
+ cp_parser_error (parser, "missing loop condition in loop with "
+ "%<GCC ivdep%> pragma");
+ condition = error_mark_node;
+ }
+ finish_for_cond (condition, stmt, ivdep);
/* Look for the `;'. */
cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
@@ -9889,7 +9997,8 @@ cp_parser_c_for (cp_parser *parser, tree scope, tree init)
regular FOR_STMT. */
static tree
-cp_parser_range_for (cp_parser *parser, tree scope, tree init, tree range_decl)
+cp_parser_range_for (cp_parser *parser, tree scope, tree init, tree range_decl,
+ bool ivdep)
{
tree stmt, range_expr;
@@ -9908,6 +10017,8 @@ cp_parser_range_for (cp_parser *parser, tree scope, tree init, tree range_decl)
if (check_for_bare_parameter_packs (range_expr))
range_expr = error_mark_node;
stmt = begin_range_for_stmt (scope, init);
+ if (ivdep)
+ RANGE_FOR_IVDEP (stmt) = 1;
finish_range_for_decl (stmt, range_decl, range_expr);
if (!type_dependent_expression_p (range_expr)
/* do_auto_deduction doesn't mess with template init-lists. */
@@ -9917,7 +10028,7 @@ cp_parser_range_for (cp_parser *parser, tree scope, tree init, tree range_decl)
else
{
stmt = begin_for_stmt (scope, init);
- stmt = cp_convert_range_for (stmt, range_decl, range_expr);
+ stmt = cp_convert_range_for (stmt, range_decl, range_expr, ivdep);
}
return stmt;
}
@@ -9960,11 +10071,15 @@ do_range_for_auto_deduction (tree decl, tree range_expr)
range_temp = convert_from_reference (build_range_temp (range_expr));
iter_type = (cp_parser_perform_range_for_lookup
(range_temp, &begin_dummy, &end_dummy));
- iter_decl = build_decl (input_location, VAR_DECL, NULL_TREE, iter_type);
- iter_decl = build_x_indirect_ref (input_location, iter_decl, RO_NULL,
- tf_warning_or_error);
- TREE_TYPE (decl) = do_auto_deduction (TREE_TYPE (decl),
- iter_decl, auto_node);
+ if (iter_type)
+ {
+ iter_decl = build_decl (input_location, VAR_DECL, NULL_TREE,
+ iter_type);
+ iter_decl = build_x_indirect_ref (input_location, iter_decl, RO_NULL,
+ tf_warning_or_error);
+ TREE_TYPE (decl) = do_auto_deduction (TREE_TYPE (decl),
+ iter_decl, auto_node);
+ }
}
}
@@ -10004,7 +10119,8 @@ do_range_for_auto_deduction (tree decl, tree range_expr)
namespace. */
tree
-cp_convert_range_for (tree statement, tree range_decl, tree range_expr)
+cp_convert_range_for (tree statement, tree range_decl, tree range_expr,
+ bool ivdep)
{
tree begin, end;
tree iter_type, begin_expr, end_expr;
@@ -10061,7 +10177,7 @@ cp_convert_range_for (tree statement, tree range_decl, tree range_expr)
begin, ERROR_MARK,
end, ERROR_MARK,
NULL, tf_warning_or_error);
- finish_for_cond (condition, statement);
+ finish_for_cond (condition, statement, ivdep);
/* The new increment expression. */
expression = finish_unary_op_expr (input_location,
@@ -10171,6 +10287,11 @@ cp_parser_perform_range_for_lookup (tree range, tree *begin, tree *end)
*begin = *end = error_mark_node;
return error_mark_node;
}
+ else if (type_dependent_expression_p (*begin)
+ || type_dependent_expression_p (*end))
+ /* Can happen, when, eg, in a template context, Koenig lookup
+ can't resolve begin/end (c++/58503). */
+ return NULL_TREE;
else
{
tree iter_type = cv_unqualified (TREE_TYPE (*begin));
@@ -10219,7 +10340,7 @@ cp_parser_range_for_member_function (tree range, tree identifier)
Returns the new WHILE_STMT, DO_STMT, FOR_STMT or RANGE_FOR_STMT. */
static tree
-cp_parser_iteration_statement (cp_parser* parser)
+cp_parser_iteration_statement (cp_parser* parser, bool ivdep)
{
cp_token *token;
enum rid keyword;
@@ -10249,7 +10370,7 @@ cp_parser_iteration_statement (cp_parser* parser)
cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
/* Parse the condition. */
condition = cp_parser_condition (parser);
- finish_while_stmt_cond (condition, statement);
+ finish_while_stmt_cond (condition, statement, ivdep);
/* Look for the `)'. */
cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
/* Parse the dependent statement. */
@@ -10279,7 +10400,7 @@ cp_parser_iteration_statement (cp_parser* parser)
/* Parse the expression. */
expression = cp_parser_expression (parser, /*cast_p=*/false, NULL);
/* We're done with the do-statement. */
- finish_do_stmt (expression, statement);
+ finish_do_stmt (expression, statement, ivdep);
/* Look for the `)'. */
cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
/* Look for the `;'. */
@@ -10292,7 +10413,7 @@ cp_parser_iteration_statement (cp_parser* parser)
/* Look for the `('. */
cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
- statement = cp_parser_for (parser);
+ statement = cp_parser_for (parser, ivdep);
/* Look for the `)'. */
cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
@@ -11460,7 +11581,8 @@ cp_parser_function_specifier_opt (cp_parser* parser,
A member function template shall not be virtual. */
if (PROCESSING_REAL_TEMPLATE_DECL_P ())
error_at (token->location, "templates may not be %<virtual%>");
- set_and_check_decl_spec_loc (decl_specs, ds_virtual, token);
+ else
+ set_and_check_decl_spec_loc (decl_specs, ds_virtual, token);
break;
case RID_EXPLICIT:
@@ -11512,6 +11634,8 @@ cp_parser_linkage_specification (cp_parser* parser)
production. */
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
{
+ cp_ensure_no_omp_declare_simd (parser);
+
/* Consume the `{' token. */
cp_lexer_consume_token (parser->lexer);
/* Parse the declarations. */
@@ -15499,6 +15623,7 @@ cp_parser_namespace_definition (cp_parser* parser)
bool has_visibility;
bool is_inline;
+ cp_ensure_no_omp_declare_simd (parser);
if (cp_lexer_next_token_is_keyword (parser->lexer, RID_INLINE))
{
maybe_warn_cpp0x (CPP0X_INLINE_NAMESPACES);
@@ -16318,47 +16443,43 @@ cp_parser_init_declarator (cp_parser* parser,
"a function-definition is not allowed here");
return error_mark_node;
}
- else
- {
- location_t func_brace_location
- = cp_lexer_peek_token (parser->lexer)->location;
-
- /* Neither attributes nor an asm-specification are allowed
- on a function-definition. */
- if (asm_specification)
- error_at (asm_spec_start_token->location,
- "an asm-specification is not allowed "
- "on a function-definition");
- if (attributes)
- error_at (attributes_start_token->location,
- "attributes are not allowed "
- "on a function-definition");
- /* This is a function-definition. */
- *function_definition_p = true;
-
- /* Parse the function definition. */
- if (member_p)
- decl = cp_parser_save_member_function_body (parser,
- decl_specifiers,
- declarator,
- prefix_attributes);
- else
- decl =
- (cp_parser_function_definition_from_specifiers_and_declarator
- (parser, decl_specifiers, prefix_attributes, declarator));
- if (decl != error_mark_node && DECL_STRUCT_FUNCTION (decl))
- {
- /* This is where the prologue starts... */
- DECL_STRUCT_FUNCTION (decl)->function_start_locus
- = func_brace_location;
- }
+ location_t func_brace_location
+ = cp_lexer_peek_token (parser->lexer)->location;
- return decl;
+ /* Neither attributes nor an asm-specification are allowed
+ on a function-definition. */
+ if (asm_specification)
+ error_at (asm_spec_start_token->location,
+ "an asm-specification is not allowed "
+ "on a function-definition");
+ if (attributes)
+ error_at (attributes_start_token->location,
+ "attributes are not allowed "
+ "on a function-definition");
+ /* This is a function-definition. */
+ *function_definition_p = true;
+
+ /* Parse the function definition. */
+ if (member_p)
+ decl = cp_parser_save_member_function_body (parser,
+ decl_specifiers,
+ declarator,
+ prefix_attributes);
+ else
+ decl =
+ (cp_parser_function_definition_from_specifiers_and_declarator
+ (parser, decl_specifiers, prefix_attributes, declarator));
+
+ if (decl != error_mark_node && DECL_STRUCT_FUNCTION (decl))
+ {
+ /* This is where the prologue starts... */
+ DECL_STRUCT_FUNCTION (decl)->function_start_locus
+ = func_brace_location;
}
+
+ return decl;
}
- else if (parser->fully_implicit_function_template_p)
- decl = finish_fully_implicit_template (parser, decl);
}
/* [dcl.dcl]
@@ -16443,8 +16564,8 @@ cp_parser_init_declarator (cp_parser* parser,
decl_specifiers->storage_class = sc_extern;
decl = start_decl (declarator, decl_specifiers,
range_for_decl_p? SD_INITIALIZED : is_initialized,
- attributes, prefix_attributes,
- &pushed_scope);
+ attributes, prefix_attributes, &pushed_scope);
+ cp_finalize_omp_declare_simd (parser, decl);
/* Adjust location of decl if declarator->id_loc is more appropriate:
set, and decl wasn't merged with another decl, in which case its
location would be different from input_location, and more accurate. */
@@ -16551,9 +16672,10 @@ cp_parser_init_declarator (cp_parser* parser,
decl = grokfield (declarator, decl_specifiers,
initializer, !is_non_constant_init,
/*asmspec=*/NULL_TREE,
- prefix_attributes);
+ chainon (attributes, prefix_attributes));
if (decl && TREE_CODE (decl) == FUNCTION_DECL)
cp_parser_save_default_args (parser, decl);
+ cp_finalize_omp_declare_simd (parser, decl);
}
/* Finish processing the declaration. But, skip member
@@ -16581,6 +16703,15 @@ cp_parser_init_declarator (cp_parser* parser,
if (!friend_p && pushed_scope)
pop_scope (pushed_scope);
+ if (function_declarator_p (declarator)
+ && parser->fully_implicit_function_template_p)
+ {
+ if (member_p)
+ decl = finish_fully_implicit_template (parser, decl);
+ else
+ finish_fully_implicit_template (parser, /*member_decl_opt=*/0);
+ }
+
return decl;
}
@@ -16856,7 +16987,9 @@ cp_parser_direct_declarator (cp_parser* parser,
attrs = cp_parser_std_attribute_spec_seq (parser);
late_return = (cp_parser_late_return_type_opt
- (parser, memfn ? cv_quals : -1));
+ (parser, declarator,
+ memfn ? cv_quals : -1));
+
/* Parse the virt-specifier-seq. */
virt_specifiers = cp_parser_virt_specifier_seq_opt (parser);
@@ -17560,24 +17693,28 @@ parsing_nsdmi (void)
Returns the type indicated by the type-id.
+ In addition to this this parses any queued up omp declare simd
+ clauses.
+
QUALS is either a bitmask of cv_qualifiers or -1 for a non-member
function. */
static tree
-cp_parser_late_return_type_opt (cp_parser* parser, cp_cv_quals quals)
+cp_parser_late_return_type_opt (cp_parser* parser, cp_declarator *declarator,
+ cp_cv_quals quals)
{
cp_token *token;
- tree type;
+ tree type = NULL_TREE;
+ bool declare_simd_p = (parser->omp_declare_simd
+ && declarator
+ && declarator->kind == cdk_id);
/* Peek at the next token. */
token = cp_lexer_peek_token (parser->lexer);
/* A late-specified return type is indicated by an initial '->'. */
- if (token->type != CPP_DEREF)
+ if (token->type != CPP_DEREF && !declare_simd_p)
return NULL_TREE;
- /* Consume the ->. */
- cp_lexer_consume_token (parser->lexer);
-
tree save_ccp = current_class_ptr;
tree save_ccr = current_class_ref;
if (quals >= 0)
@@ -17586,7 +17723,18 @@ cp_parser_late_return_type_opt (cp_parser* parser, cp_cv_quals quals)
inject_this_parameter (current_class_type, quals);
}
- type = cp_parser_trailing_type_id (parser);
+ if (token->type == CPP_DEREF)
+ {
+ /* Consume the ->. */
+ cp_lexer_consume_token (parser->lexer);
+
+ type = cp_parser_trailing_type_id (parser);
+ }
+
+ if (declare_simd_p)
+ declarator->std_attributes
+ = cp_parser_late_parsing_omp_declare_simd (parser,
+ declarator->std_attributes);
if (quals >= 0)
{
@@ -18841,6 +18989,8 @@ cp_parser_class_specifier_1 (cp_parser* parser)
return error_mark_node;
}
+ cp_ensure_no_omp_declare_simd (parser);
+
/* Issue an error message if type-definitions are forbidden here. */
cp_parser_check_type_definition (parser);
/* Remember that we are defining one more class. */
@@ -19068,8 +19218,19 @@ cp_parser_class_specifier_1 (cp_parser* parser)
if (pushed_scope)
pop_scope (pushed_scope);
/* Now parse the body of the functions. */
- FOR_EACH_VEC_SAFE_ELT (unparsed_funs_with_definitions, ix, decl)
- cp_parser_late_parsing_for_member (parser, decl);
+ if (flag_openmp)
+ {
+ /* OpenMP UDRs need to be parsed before all other functions. */
+ FOR_EACH_VEC_SAFE_ELT (unparsed_funs_with_definitions, ix, decl)
+ if (DECL_OMP_DECLARE_REDUCTION_P (decl))
+ cp_parser_late_parsing_for_member (parser, decl);
+ FOR_EACH_VEC_SAFE_ELT (unparsed_funs_with_definitions, ix, decl)
+ if (!DECL_OMP_DECLARE_REDUCTION_P (decl))
+ cp_parser_late_parsing_for_member (parser, decl);
+ }
+ else
+ FOR_EACH_VEC_SAFE_ELT (unparsed_funs_with_definitions, ix, decl)
+ cp_parser_late_parsing_for_member (parser, decl);
vec_safe_truncate (unparsed_funs_with_definitions, 0);
}
@@ -19616,7 +19777,7 @@ cp_parser_member_specification_opt (cp_parser* parser)
/* Accept #pragmas at class scope. */
if (token->type == CPP_PRAGMA)
{
- cp_parser_pragma (parser, pragma_external);
+ cp_parser_pragma (parser, pragma_member);
break;
}
@@ -20072,15 +20233,16 @@ cp_parser_member_declaration (cp_parser* parser)
else
if (declarator->kind == cdk_function)
declarator->id_loc = token->location;
- /* Create the declaration. */
- decl = grokfield (declarator, &decl_specifiers,
- initializer, /*init_const_expr_p=*/true,
- asm_specification,
- attributes);
+ /* Create the declaration. */
+ decl = grokfield (declarator, &decl_specifiers,
+ initializer, /*init_const_expr_p=*/true,
+ asm_specification, attributes);
if (parser->fully_implicit_function_template_p)
decl = finish_fully_implicit_template (parser, decl);
}
+ cp_finalize_omp_declare_simd (parser, decl);
+
/* Reset PREFIX_ATTRIBUTES. */
while (attributes && TREE_CHAIN (attributes) != first_attribute)
attributes = TREE_CHAIN (attributes);
@@ -21317,6 +21479,9 @@ cp_parser_std_attribute (cp_parser *parser)
/* C++11 noreturn attribute is equivalent to GNU's. */
if (is_attribute_p ("noreturn", attr_id))
TREE_PURPOSE (TREE_PURPOSE (attribute)) = get_identifier ("gnu");
+ /* C++14 deprecated attribute is equivalent to GNU's. */
+ else if (cxx_dialect >= cxx1y && is_attribute_p ("deprecated", attr_id))
+ TREE_PURPOSE (TREE_PURPOSE (attribute)) = get_identifier ("gnu");
}
/* Now parse the optional argument clause of the attribute. */
@@ -21452,6 +21617,8 @@ cp_parser_std_attribute_spec (cp_parser *parser)
alignas_expr =
cp_parser_assignment_expression (parser, /*cast_p=*/false,
/**cp_id_kind=*/NULL);
+ if (alignas_expr == error_mark_node)
+ cp_parser_skip_to_end_of_statement (parser);
if (alignas_expr == NULL_TREE
|| alignas_expr == error_mark_node)
return alignas_expr;
@@ -21751,7 +21918,8 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
is dependent. */
type = make_typename_type (parser->scope, name, tag_type,
/*complain=*/tf_error);
- decl = TYPE_NAME (type);
+ if (type != error_mark_node)
+ decl = TYPE_NAME (type);
}
else if (is_template
&& (cp_parser_next_token_ends_template_argument_p (parser)
@@ -21770,7 +21938,6 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
}
else if (object_type)
{
- tree object_decl = NULL_TREE;
/* Look up the name in the scope of the OBJECT_TYPE, unless the
OBJECT_TYPE is not a class. */
if (CLASS_TYPE_P (object_type))
@@ -21778,19 +21945,21 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
be instantiated during name lookup. In that case, errors
may be issued. Even if we rollback the current tentative
parse, those errors are valid. */
- object_decl = lookup_member (object_type,
- name,
- /*protect=*/0,
- tag_type != none_type,
- tf_warning_or_error);
- /* Look it up in the enclosing context, too. */
- decl = lookup_name_real (name, tag_type != none_type,
- /*nonclass=*/0,
- /*block_p=*/true, is_namespace, 0);
+ decl = lookup_member (object_type,
+ name,
+ /*protect=*/0,
+ tag_type != none_type,
+ tf_warning_or_error);
+ else
+ decl = NULL_TREE;
+
+ if (!decl)
+ /* Look it up in the enclosing context. */
+ decl = lookup_name_real (name, tag_type != none_type,
+ /*nonclass=*/0,
+ /*block_p=*/true, is_namespace, 0);
parser->object_scope = object_type;
parser->qualifying_scope = NULL_TREE;
- if (object_decl)
- decl = object_decl;
}
else
{
@@ -22042,6 +22211,7 @@ static bool
cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p)
{
bool constructor_p;
+ bool outside_class_specifier_p;
tree nested_name_specifier;
cp_token *next_token;
@@ -22074,11 +22244,14 @@ cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p)
/*check_dependency_p=*/false,
/*type_p=*/false,
/*is_declaration=*/false));
+
+ outside_class_specifier_p = (!at_class_scope_p ()
+ || !TYPE_BEING_DEFINED (current_class_type)
+ || friend_p);
+
/* Outside of a class-specifier, there must be a
nested-name-specifier. */
- if (!nested_name_specifier &&
- (!at_class_scope_p () || !TYPE_BEING_DEFINED (current_class_type)
- || friend_p))
+ if (!nested_name_specifier && outside_class_specifier_p)
constructor_p = false;
else if (nested_name_specifier == error_mark_node)
constructor_p = false;
@@ -22117,8 +22290,16 @@ cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p)
/*check_dependency_p=*/false,
/*class_head_p=*/false,
/*is_declaration=*/false);
- /* If there was no class-name, then this is not a constructor. */
- constructor_p = !cp_parser_error_occurred (parser);
+ /* If there was no class-name, then this is not a constructor.
+ Otherwise, if we are in a class-specifier and we aren't
+ handling a friend declaration, check that its type matches
+ current_class_type (c++/38313). Note: error_mark_node
+ is left alone for error recovery purposes. */
+ constructor_p = (!cp_parser_error_occurred (parser)
+ && (outside_class_specifier_p
+ || type_decl == error_mark_node
+ || same_type_p (current_class_type,
+ TREE_TYPE (type_decl))));
/* If we're still considering a constructor, we have to see a `(',
to begin the parameter-declaration-clause, followed by either a
@@ -22226,6 +22407,12 @@ cp_parser_function_definition_from_specifiers_and_declarator
might be a friend. */
perform_deferred_access_checks (tf_warning_or_error);
+ if (success_p)
+ {
+ cp_finalize_omp_declare_simd (parser, current_function_decl);
+ parser->omp_declare_simd = NULL;
+ }
+
if (!success_p)
{
/* Skip the entire function. */
@@ -22757,6 +22944,7 @@ cp_parser_save_member_function_body (cp_parser* parser,
/* Create the FUNCTION_DECL. */
fn = grokmethod (decl_specifiers, declarator, attributes);
+ cp_finalize_omp_declare_simd (parser, fn);
/* If something went badly wrong, bail out now. */
if (fn == error_mark_node)
{
@@ -22983,9 +23171,18 @@ cp_parser_late_parsing_for_member (cp_parser* parser, tree member_function)
if (processing_template_decl)
push_deferring_access_checks (dk_no_check);
- /* Now, parse the body of the function. */
- cp_parser_function_definition_after_declarator (parser,
- /*inline_p=*/true);
+ /* #pragma omp declare reduction needs special parsing. */
+ if (DECL_OMP_DECLARE_REDUCTION_P (member_function))
+ {
+ parser->lexer->in_pragma = true;
+ cp_parser_omp_declare_reduction_exprs (member_function, parser);
+ finish_function (0);
+ cp_check_omp_declare_reduction (member_function);
+ }
+ else
+ /* Now, parse the body of the function. */
+ cp_parser_function_definition_after_declarator (parser,
+ /*inline_p=*/true);
if (processing_template_decl)
pop_deferring_access_checks ();
@@ -23070,6 +23267,9 @@ cp_parser_late_parse_one_default_arg (cp_parser *parser, tree decl,
&& CONSTRUCTOR_IS_DIRECT_INIT (parsed_arg))
flags = LOOKUP_NORMAL;
parsed_arg = digest_init_flags (TREE_TYPE (decl), parsed_arg, flags);
+ if (TREE_CODE (parsed_arg) == TARGET_EXPR)
+ /* This represents the whole initialization. */
+ TARGET_EXPR_DIRECT_INIT_P (parsed_arg) = true;
}
}
@@ -23905,7 +24105,9 @@ cp_parser_next_token_starts_class_definition_p (cp_parser *parser)
cp_token *token;
token = cp_lexer_peek_token (parser->lexer);
- return (token->type == CPP_OPEN_BRACE || token->type == CPP_COLON);
+ return (token->type == CPP_OPEN_BRACE
+ || (token->type == CPP_COLON
+ && !parser->colon_doesnt_start_class_def_p));
}
/* Returns TRUE iff the next token is the "," or ">" (or `>>', in
@@ -24328,6 +24530,32 @@ cp_parser_commit_to_tentative_parse (cp_parser* parser)
}
}
+/* Commit to the topmost currently active tentative parse.
+
+ Note that this function shouldn't be called when there are
+ irreversible side-effects while in a tentative state. For
+ example, we shouldn't create a permanent entry in the symbol
+ table, or issue an error message that might not apply if the
+ tentative parse is aborted. */
+
+static void
+cp_parser_commit_to_topmost_tentative_parse (cp_parser* parser)
+{
+ cp_parser_context *context = parser->context;
+ cp_lexer *lexer = parser->lexer;
+
+ if (context)
+ {
+ if (context->status == CP_PARSER_STATUS_KIND_COMMITTED)
+ return;
+ context->status = CP_PARSER_STATUS_KIND_COMMITTED;
+
+ while (!cp_lexer_saving_tokens (lexer))
+ lexer = lexer->next;
+ cp_lexer_commit_tokens (lexer);
+ }
+}
+
/* Abort the currently active tentative parse. All consumed tokens
will be rolled back, and no diagnostics will be issued. */
@@ -25158,7 +25386,7 @@ cp_parser_objc_interstitial_code (cp_parser* parser)
cp_parser_linkage_specification (parser);
/* Handle #pragma, if any. */
else if (token->type == CPP_PRAGMA)
- cp_parser_pragma (parser, pragma_external);
+ cp_parser_pragma (parser, pragma_objc_icode);
/* Allow stray semicolons. */
else if (token->type == CPP_SEMICOLON)
cp_lexer_consume_token (parser->lexer);
@@ -26323,7 +26551,7 @@ cp_parser_objc_at_dynamic_declaration (cp_parser *parser)
}
-/* OpenMP 2.5 parsing routines. */
+/* OpenMP 2.5 / 3.0 / 3.1 / 4.0 parsing routines. */
/* Returns name of the next clause.
If the clause is not recognized PRAGMA_OMP_CLAUSE_NONE is returned and
@@ -26341,6 +26569,8 @@ cp_parser_omp_clause_name (cp_parser *parser)
result = PRAGMA_OMP_CLAUSE_DEFAULT;
else if (cp_lexer_next_token_is_keyword (parser->lexer, RID_PRIVATE))
result = PRAGMA_OMP_CLAUSE_PRIVATE;
+ else if (cp_lexer_next_token_is_keyword (parser->lexer, RID_FOR))
+ result = PRAGMA_OMP_CLAUSE_FOR;
else if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
{
tree id = cp_lexer_peek_token (parser->lexer)->u.value;
@@ -26348,6 +26578,10 @@ cp_parser_omp_clause_name (cp_parser *parser)
switch (p[0])
{
+ case 'a':
+ if (!strcmp ("aligned", p))
+ result = PRAGMA_OMP_CLAUSE_ALIGNED;
+ break;
case 'c':
if (!strcmp ("collapse", p))
result = PRAGMA_OMP_CLAUSE_COLLAPSE;
@@ -26356,23 +26590,45 @@ cp_parser_omp_clause_name (cp_parser *parser)
else if (!strcmp ("copyprivate", p))
result = PRAGMA_OMP_CLAUSE_COPYPRIVATE;
break;
+ case 'd':
+ if (!strcmp ("depend", p))
+ result = PRAGMA_OMP_CLAUSE_DEPEND;
+ else if (!strcmp ("device", p))
+ result = PRAGMA_OMP_CLAUSE_DEVICE;
+ else if (!strcmp ("dist_schedule", p))
+ result = PRAGMA_OMP_CLAUSE_DIST_SCHEDULE;
+ break;
case 'f':
if (!strcmp ("final", p))
result = PRAGMA_OMP_CLAUSE_FINAL;
else if (!strcmp ("firstprivate", p))
result = PRAGMA_OMP_CLAUSE_FIRSTPRIVATE;
+ else if (!strcmp ("from", p))
+ result = PRAGMA_OMP_CLAUSE_FROM;
+ break;
+ case 'i':
+ if (!strcmp ("inbranch", p))
+ result = PRAGMA_OMP_CLAUSE_INBRANCH;
break;
case 'l':
if (!strcmp ("lastprivate", p))
result = PRAGMA_OMP_CLAUSE_LASTPRIVATE;
+ else if (!strcmp ("linear", p))
+ result = PRAGMA_OMP_CLAUSE_LINEAR;
break;
case 'm':
- if (!strcmp ("mergeable", p))
+ if (!strcmp ("map", p))
+ result = PRAGMA_OMP_CLAUSE_MAP;
+ else if (!strcmp ("mergeable", p))
result = PRAGMA_OMP_CLAUSE_MERGEABLE;
break;
case 'n':
- if (!strcmp ("nowait", p))
+ if (!strcmp ("notinbranch", p))
+ result = PRAGMA_OMP_CLAUSE_NOTINBRANCH;
+ else if (!strcmp ("nowait", p))
result = PRAGMA_OMP_CLAUSE_NOWAIT;
+ else if (!strcmp ("num_teams", p))
+ result = PRAGMA_OMP_CLAUSE_NUM_TEAMS;
else if (!strcmp ("num_threads", p))
result = PRAGMA_OMP_CLAUSE_NUM_THREADS;
break;
@@ -26380,18 +26636,40 @@ cp_parser_omp_clause_name (cp_parser *parser)
if (!strcmp ("ordered", p))
result = PRAGMA_OMP_CLAUSE_ORDERED;
break;
+ case 'p':
+ if (!strcmp ("parallel", p))
+ result = PRAGMA_OMP_CLAUSE_PARALLEL;
+ else if (!strcmp ("proc_bind", p))
+ result = PRAGMA_OMP_CLAUSE_PROC_BIND;
+ break;
case 'r':
if (!strcmp ("reduction", p))
result = PRAGMA_OMP_CLAUSE_REDUCTION;
break;
case 's':
- if (!strcmp ("schedule", p))
+ if (!strcmp ("safelen", p))
+ result = PRAGMA_OMP_CLAUSE_SAFELEN;
+ else if (!strcmp ("schedule", p))
result = PRAGMA_OMP_CLAUSE_SCHEDULE;
+ else if (!strcmp ("sections", p))
+ result = PRAGMA_OMP_CLAUSE_SECTIONS;
else if (!strcmp ("shared", p))
result = PRAGMA_OMP_CLAUSE_SHARED;
+ else if (!strcmp ("simdlen", p))
+ result = PRAGMA_OMP_CLAUSE_SIMDLEN;
+ break;
+ case 't':
+ if (!strcmp ("taskgroup", p))
+ result = PRAGMA_OMP_CLAUSE_TASKGROUP;
+ else if (!strcmp ("thread_limit", p))
+ result = PRAGMA_OMP_CLAUSE_THREAD_LIMIT;
+ else if (!strcmp ("to", p))
+ result = PRAGMA_OMP_CLAUSE_TO;
break;
case 'u':
- if (!strcmp ("untied", p))
+ if (!strcmp ("uniform", p))
+ result = PRAGMA_OMP_CLAUSE_UNIFORM;
+ else if (!strcmp ("untied", p))
result = PRAGMA_OMP_CLAUSE_UNTIED;
break;
}
@@ -26424,20 +26702,30 @@ check_no_duplicate_clause (tree clauses, enum omp_clause_code code,
identifier
variable-list , identifier
- In addition, we match a closing parenthesis. An opening parenthesis
- will have been consumed by the caller.
+ In addition, we match a closing parenthesis (or, if COLON is non-NULL,
+ colon). An opening parenthesis will have been consumed by the caller.
If KIND is nonzero, create the appropriate node and install the decl
in OMP_CLAUSE_DECL and add the node to the head of the list.
If KIND is zero, create a TREE_LIST with the decl in TREE_PURPOSE;
- return the list created. */
+ return the list created.
+
+ COLON can be NULL if only closing parenthesis should end the list,
+ or pointer to bool which will receive false if the list is terminated
+ by closing parenthesis or true if the list is terminated by colon. */
static tree
cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
- tree list)
+ tree list, bool *colon)
{
cp_token *token;
+ bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p;
+ if (colon)
+ {
+ parser->colon_corrects_to_scope_p = false;
+ *colon = false;
+ }
while (1)
{
tree name, decl;
@@ -26457,6 +26745,48 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
token->location);
else if (kind != 0)
{
+ switch (kind)
+ {
+ case OMP_CLAUSE_MAP:
+ case OMP_CLAUSE_FROM:
+ case OMP_CLAUSE_TO:
+ case OMP_CLAUSE_DEPEND:
+ while (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_SQUARE))
+ {
+ tree low_bound = NULL_TREE, length = NULL_TREE;
+
+ parser->colon_corrects_to_scope_p = false;
+ cp_lexer_consume_token (parser->lexer);
+ if (!cp_lexer_next_token_is (parser->lexer, CPP_COLON))
+ low_bound = cp_parser_expression (parser, /*cast_p=*/false,
+ NULL);
+ if (!colon)
+ parser->colon_corrects_to_scope_p
+ = saved_colon_corrects_to_scope_p;
+ if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_SQUARE))
+ length = integer_one_node;
+ else
+ {
+ /* Look for `:'. */
+ if (!cp_parser_require (parser, CPP_COLON, RT_COLON))
+ goto skip_comma;
+ if (!cp_lexer_next_token_is (parser->lexer,
+ CPP_CLOSE_SQUARE))
+ length = cp_parser_expression (parser,
+ /*cast_p=*/false,
+ NULL);
+ }
+ /* Look for the closing `]'. */
+ if (!cp_parser_require (parser, CPP_CLOSE_SQUARE,
+ RT_CLOSE_SQUARE))
+ goto skip_comma;
+ decl = tree_cons (low_bound, length, decl);
+ }
+ break;
+ default:
+ break;
+ }
+
tree u = build_omp_clause (token->location, kind);
OMP_CLAUSE_DECL (u) = decl;
OMP_CLAUSE_CHAIN (u) = list;
@@ -26471,6 +26801,16 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
cp_lexer_consume_token (parser->lexer);
}
+ if (colon)
+ parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p;
+
+ if (colon != NULL && cp_lexer_next_token_is (parser->lexer, CPP_COLON))
+ {
+ *colon = true;
+ cp_parser_require (parser, CPP_COLON, RT_COLON);
+ return list;
+ }
+
if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
{
int ending;
@@ -26478,6 +26818,8 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
/* Try to resync to an unnested comma. Copied from
cp_parser_parenthesized_expression_list. */
skip_comma:
+ if (colon)
+ parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p;
ending = cp_parser_skip_to_closing_parenthesis (parser,
/*recovering=*/true,
/*or_comma=*/true,
@@ -26496,7 +26838,7 @@ static tree
cp_parser_omp_var_list (cp_parser *parser, enum omp_clause_code kind, tree list)
{
if (cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
- return cp_parser_omp_var_list_no_open (parser, kind, list);
+ return cp_parser_omp_var_list_no_open (parser, kind, list, NULL);
return list;
}
@@ -26744,77 +27086,102 @@ cp_parser_omp_clause_ordered (cp_parser * /*parser*/,
OpenMP 3.1:
reduction-operator:
- One of: + * - & ^ | && || min max */
+ One of: + * - & ^ | && || min max
+
+ OpenMP 4.0:
+
+ reduction-operator:
+ One of: + * - & ^ | && ||
+ id-expression */
static tree
cp_parser_omp_clause_reduction (cp_parser *parser, tree list)
{
- enum tree_code code;
- tree nlist, c;
+ enum tree_code code = ERROR_MARK;
+ tree nlist, c, id = NULL_TREE;
if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
return list;
switch (cp_lexer_peek_token (parser->lexer)->type)
{
- case CPP_PLUS:
- code = PLUS_EXPR;
- break;
- case CPP_MULT:
- code = MULT_EXPR;
- break;
- case CPP_MINUS:
- code = MINUS_EXPR;
- break;
- case CPP_AND:
- code = BIT_AND_EXPR;
- break;
- case CPP_XOR:
- code = BIT_XOR_EXPR;
- break;
- case CPP_OR:
- code = BIT_IOR_EXPR;
- break;
- case CPP_AND_AND:
- code = TRUTH_ANDIF_EXPR;
- break;
- case CPP_OR_OR:
- code = TRUTH_ORIF_EXPR;
- break;
- case CPP_NAME:
- {
- tree id = cp_lexer_peek_token (parser->lexer)->u.value;
- const char *p = IDENTIFIER_POINTER (id);
+ case CPP_PLUS: code = PLUS_EXPR; break;
+ case CPP_MULT: code = MULT_EXPR; break;
+ case CPP_MINUS: code = MINUS_EXPR; break;
+ case CPP_AND: code = BIT_AND_EXPR; break;
+ case CPP_XOR: code = BIT_XOR_EXPR; break;
+ case CPP_OR: code = BIT_IOR_EXPR; break;
+ case CPP_AND_AND: code = TRUTH_ANDIF_EXPR; break;
+ case CPP_OR_OR: code = TRUTH_ORIF_EXPR; break;
+ default: break;
+ }
- if (strcmp (p, "min") == 0)
- {
+ if (code != ERROR_MARK)
+ cp_lexer_consume_token (parser->lexer);
+ else
+ {
+ bool saved_colon_corrects_to_scope_p;
+ saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p;
+ parser->colon_corrects_to_scope_p = false;
+ id = cp_parser_id_expression (parser, /*template_p=*/false,
+ /*check_dependency_p=*/true,
+ /*template_p=*/NULL,
+ /*declarator_p=*/false,
+ /*optional_p=*/false);
+ parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p;
+ if (identifier_p (id))
+ {
+ const char *p = IDENTIFIER_POINTER (id);
+
+ if (strcmp (p, "min") == 0)
code = MIN_EXPR;
- break;
- }
- if (strcmp (p, "max") == 0)
- {
+ else if (strcmp (p, "max") == 0)
code = MAX_EXPR;
- break;
- }
- }
- /* FALLTHROUGH */
- default:
- cp_parser_error (parser, "expected %<+%>, %<*%>, %<-%>, %<&%>, %<^%>, "
- "%<|%>, %<&&%>, %<||%>, %<min%> or %<max%>");
- resync_fail:
- cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
- /*or_comma=*/false,
- /*consume_paren=*/true);
- return list;
+ else if (id == ansi_opname (PLUS_EXPR))
+ code = PLUS_EXPR;
+ else if (id == ansi_opname (MULT_EXPR))
+ code = MULT_EXPR;
+ else if (id == ansi_opname (MINUS_EXPR))
+ code = MINUS_EXPR;
+ else if (id == ansi_opname (BIT_AND_EXPR))
+ code = BIT_AND_EXPR;
+ else if (id == ansi_opname (BIT_IOR_EXPR))
+ code = BIT_IOR_EXPR;
+ else if (id == ansi_opname (BIT_XOR_EXPR))
+ code = BIT_XOR_EXPR;
+ else if (id == ansi_opname (TRUTH_ANDIF_EXPR))
+ code = TRUTH_ANDIF_EXPR;
+ else if (id == ansi_opname (TRUTH_ORIF_EXPR))
+ code = TRUTH_ORIF_EXPR;
+ id = omp_reduction_id (code, id, NULL_TREE);
+ tree scope = parser->scope;
+ if (scope)
+ id = build_qualified_name (NULL_TREE, scope, id, false);
+ parser->scope = NULL_TREE;
+ parser->qualifying_scope = NULL_TREE;
+ parser->object_scope = NULL_TREE;
+ }
+ else
+ {
+ error ("invalid reduction-identifier");
+ resync_fail:
+ cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+ /*or_comma=*/false,
+ /*consume_paren=*/true);
+ return list;
+ }
}
- cp_lexer_consume_token (parser->lexer);
if (!cp_parser_require (parser, CPP_COLON, RT_COLON))
goto resync_fail;
- nlist = cp_parser_omp_var_list_no_open (parser, OMP_CLAUSE_REDUCTION, list);
+ nlist = cp_parser_omp_var_list_no_open (parser, OMP_CLAUSE_REDUCTION, list,
+ NULL);
for (c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c))
- OMP_CLAUSE_REDUCTION_CODE (c) = code;
+ {
+ OMP_CLAUSE_REDUCTION_CODE (c) = code;
+ OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = id;
+ }
return nlist;
}
@@ -26927,13 +27294,468 @@ cp_parser_omp_clause_untied (cp_parser * /*parser*/,
return c;
}
+/* OpenMP 4.0:
+ inbranch
+ notinbranch */
+
+static tree
+cp_parser_omp_clause_branch (cp_parser * /*parser*/, enum omp_clause_code code,
+ tree list, location_t location)
+{
+ check_no_duplicate_clause (list, code, omp_clause_code_name[code], location);
+ tree c = build_omp_clause (location, code);
+ OMP_CLAUSE_CHAIN (c) = list;
+ return c;
+}
+
+/* OpenMP 4.0:
+ parallel
+ for
+ sections
+ taskgroup */
+
+static tree
+cp_parser_omp_clause_cancelkind (cp_parser * /*parser*/,
+ enum omp_clause_code code,
+ tree list, location_t location)
+{
+ tree c = build_omp_clause (location, code);
+ OMP_CLAUSE_CHAIN (c) = list;
+ return c;
+}
+
+/* OpenMP 4.0:
+ num_teams ( expression ) */
+
+static tree
+cp_parser_omp_clause_num_teams (cp_parser *parser, tree list,
+ location_t location)
+{
+ tree t, c;
+
+ if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ return list;
+
+ t = cp_parser_expression (parser, false, NULL);
+
+ if (t == error_mark_node
+ || !cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+ /*or_comma=*/false,
+ /*consume_paren=*/true);
+
+ check_no_duplicate_clause (list, OMP_CLAUSE_NUM_TEAMS,
+ "num_teams", location);
+
+ c = build_omp_clause (location, OMP_CLAUSE_NUM_TEAMS);
+ OMP_CLAUSE_NUM_TEAMS_EXPR (c) = t;
+ OMP_CLAUSE_CHAIN (c) = list;
+
+ return c;
+}
+
+/* OpenMP 4.0:
+ thread_limit ( expression ) */
+
+static tree
+cp_parser_omp_clause_thread_limit (cp_parser *parser, tree list,
+ location_t location)
+{
+ tree t, c;
+
+ if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ return list;
+
+ t = cp_parser_expression (parser, false, NULL);
+
+ if (t == error_mark_node
+ || !cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+ /*or_comma=*/false,
+ /*consume_paren=*/true);
+
+ check_no_duplicate_clause (list, OMP_CLAUSE_THREAD_LIMIT,
+ "thread_limit", location);
+
+ c = build_omp_clause (location, OMP_CLAUSE_THREAD_LIMIT);
+ OMP_CLAUSE_THREAD_LIMIT_EXPR (c) = t;
+ OMP_CLAUSE_CHAIN (c) = list;
+
+ return c;
+}
+
+/* OpenMP 4.0:
+ aligned ( variable-list )
+ aligned ( variable-list : constant-expression ) */
+
+static tree
+cp_parser_omp_clause_aligned (cp_parser *parser, tree list)
+{
+ tree nlist, c, alignment = NULL_TREE;
+ bool colon;
+
+ if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ return list;
+
+ nlist = cp_parser_omp_var_list_no_open (parser, OMP_CLAUSE_ALIGNED, list,
+ &colon);
+
+ if (colon)
+ {
+ alignment = cp_parser_constant_expression (parser, false, NULL);
+
+ if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+ /*or_comma=*/false,
+ /*consume_paren=*/true);
+
+ if (alignment == error_mark_node)
+ alignment = NULL_TREE;
+ }
+
+ for (c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c))
+ OMP_CLAUSE_ALIGNED_ALIGNMENT (c) = alignment;
+
+ return nlist;
+}
+
+/* OpenMP 4.0:
+ linear ( variable-list )
+ linear ( variable-list : expression ) */
+
+static tree
+cp_parser_omp_clause_linear (cp_parser *parser, tree list)
+{
+ tree nlist, c, step = integer_one_node;
+ bool colon;
+
+ if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ return list;
+
+ nlist = cp_parser_omp_var_list_no_open (parser, OMP_CLAUSE_LINEAR, list,
+ &colon);
+
+ if (colon)
+ {
+ step = cp_parser_expression (parser, false, NULL);
+
+ if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+ /*or_comma=*/false,
+ /*consume_paren=*/true);
+
+ if (step == error_mark_node)
+ return list;
+ }
+
+ for (c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c))
+ OMP_CLAUSE_LINEAR_STEP (c) = step;
+
+ return nlist;
+}
+
+/* OpenMP 4.0:
+ safelen ( constant-expression ) */
+
+static tree
+cp_parser_omp_clause_safelen (cp_parser *parser, tree list,
+ location_t location)
+{
+ tree t, c;
+
+ if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ return list;
+
+ t = cp_parser_constant_expression (parser, false, NULL);
+
+ if (t == error_mark_node
+ || !cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+ /*or_comma=*/false,
+ /*consume_paren=*/true);
+
+ check_no_duplicate_clause (list, OMP_CLAUSE_SAFELEN, "safelen", location);
+
+ c = build_omp_clause (location, OMP_CLAUSE_SAFELEN);
+ OMP_CLAUSE_SAFELEN_EXPR (c) = t;
+ OMP_CLAUSE_CHAIN (c) = list;
+
+ return c;
+}
+
+/* OpenMP 4.0:
+ simdlen ( constant-expression ) */
+
+static tree
+cp_parser_omp_clause_simdlen (cp_parser *parser, tree list,
+ location_t location)
+{
+ tree t, c;
+
+ if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ return list;
+
+ t = cp_parser_constant_expression (parser, false, NULL);
+
+ if (t == error_mark_node
+ || !cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+ /*or_comma=*/false,
+ /*consume_paren=*/true);
+
+ check_no_duplicate_clause (list, OMP_CLAUSE_SIMDLEN, "simdlen", location);
+
+ c = build_omp_clause (location, OMP_CLAUSE_SIMDLEN);
+ OMP_CLAUSE_SIMDLEN_EXPR (c) = t;
+ OMP_CLAUSE_CHAIN (c) = list;
+
+ return c;
+}
+
+/* OpenMP 4.0:
+ depend ( depend-kind : variable-list )
+
+ depend-kind:
+ in | out | inout */
+
+static tree
+cp_parser_omp_clause_depend (cp_parser *parser, tree list)
+{
+ tree nlist, c;
+ enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_INOUT;
+
+ if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ return list;
+
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+ {
+ tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+ const char *p = IDENTIFIER_POINTER (id);
+
+ if (strcmp ("in", p) == 0)
+ kind = OMP_CLAUSE_DEPEND_IN;
+ else if (strcmp ("inout", p) == 0)
+ kind = OMP_CLAUSE_DEPEND_INOUT;
+ else if (strcmp ("out", p) == 0)
+ kind = OMP_CLAUSE_DEPEND_OUT;
+ else
+ goto invalid_kind;
+ }
+ else
+ goto invalid_kind;
+
+ cp_lexer_consume_token (parser->lexer);
+ if (!cp_parser_require (parser, CPP_COLON, RT_COLON))
+ goto resync_fail;
+
+ nlist = cp_parser_omp_var_list_no_open (parser, OMP_CLAUSE_DEPEND, list,
+ NULL);
+
+ for (c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c))
+ OMP_CLAUSE_DEPEND_KIND (c) = kind;
+
+ return nlist;
+
+ invalid_kind:
+ cp_parser_error (parser, "invalid depend kind");
+ resync_fail:
+ cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+ /*or_comma=*/false,
+ /*consume_paren=*/true);
+ return list;
+}
+
+/* OpenMP 4.0:
+ map ( map-kind : variable-list )
+ map ( variable-list )
+
+ map-kind:
+ alloc | to | from | tofrom */
+
+static tree
+cp_parser_omp_clause_map (cp_parser *parser, tree list)
+{
+ tree nlist, c;
+ enum omp_clause_map_kind kind = OMP_CLAUSE_MAP_TOFROM;
+
+ if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ return list;
+
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)
+ && cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_COLON)
+ {
+ tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+ const char *p = IDENTIFIER_POINTER (id);
+
+ if (strcmp ("alloc", p) == 0)
+ kind = OMP_CLAUSE_MAP_ALLOC;
+ else if (strcmp ("to", p) == 0)
+ kind = OMP_CLAUSE_MAP_TO;
+ else if (strcmp ("from", p) == 0)
+ kind = OMP_CLAUSE_MAP_FROM;
+ else if (strcmp ("tofrom", p) == 0)
+ kind = OMP_CLAUSE_MAP_TOFROM;
+ else
+ {
+ cp_parser_error (parser, "invalid map kind");
+ cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+ /*or_comma=*/false,
+ /*consume_paren=*/true);
+ return list;
+ }
+ cp_lexer_consume_token (parser->lexer);
+ cp_lexer_consume_token (parser->lexer);
+ }
+
+ nlist = cp_parser_omp_var_list_no_open (parser, OMP_CLAUSE_MAP, list,
+ NULL);
+
+ for (c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c))
+ OMP_CLAUSE_MAP_KIND (c) = kind;
+
+ return nlist;
+}
+
+/* OpenMP 4.0:
+ device ( expression ) */
+
+static tree
+cp_parser_omp_clause_device (cp_parser *parser, tree list,
+ location_t location)
+{
+ tree t, c;
+
+ if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ return list;
+
+ t = cp_parser_expression (parser, false, NULL);
+
+ if (t == error_mark_node
+ || !cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+ /*or_comma=*/false,
+ /*consume_paren=*/true);
+
+ check_no_duplicate_clause (list, OMP_CLAUSE_DEVICE,
+ "device", location);
+
+ c = build_omp_clause (location, OMP_CLAUSE_DEVICE);
+ OMP_CLAUSE_DEVICE_ID (c) = t;
+ OMP_CLAUSE_CHAIN (c) = list;
+
+ return c;
+}
+
+/* OpenMP 4.0:
+ dist_schedule ( static )
+ dist_schedule ( static , expression ) */
+
+static tree
+cp_parser_omp_clause_dist_schedule (cp_parser *parser, tree list,
+ location_t location)
+{
+ tree c, t;
+
+ if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ return list;
+
+ c = build_omp_clause (location, OMP_CLAUSE_DIST_SCHEDULE);
+
+ if (!cp_lexer_next_token_is_keyword (parser->lexer, RID_STATIC))
+ goto invalid_kind;
+ cp_lexer_consume_token (parser->lexer);
+
+ if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+ {
+ cp_lexer_consume_token (parser->lexer);
+
+ t = cp_parser_assignment_expression (parser, false, NULL);
+
+ if (t == error_mark_node)
+ goto resync_fail;
+ OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (c) = t;
+
+ if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ goto resync_fail;
+ }
+ else if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_COMMA_CLOSE_PAREN))
+ goto resync_fail;
+
+ check_no_duplicate_clause (list, OMP_CLAUSE_DIST_SCHEDULE, "dist_schedule",
+ location);
+ OMP_CLAUSE_CHAIN (c) = list;
+ return c;
+
+ invalid_kind:
+ cp_parser_error (parser, "invalid dist_schedule kind");
+ resync_fail:
+ cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+ /*or_comma=*/false,
+ /*consume_paren=*/true);
+ return list;
+}
+
+/* OpenMP 4.0:
+ proc_bind ( proc-bind-kind )
+
+ proc-bind-kind:
+ master | close | spread */
+
+static tree
+cp_parser_omp_clause_proc_bind (cp_parser *parser, tree list,
+ location_t location)
+{
+ tree c;
+ enum omp_clause_proc_bind_kind kind;
+
+ if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ return list;
+
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+ {
+ tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+ const char *p = IDENTIFIER_POINTER (id);
+
+ if (strcmp ("master", p) == 0)
+ kind = OMP_CLAUSE_PROC_BIND_MASTER;
+ else if (strcmp ("close", p) == 0)
+ kind = OMP_CLAUSE_PROC_BIND_CLOSE;
+ else if (strcmp ("spread", p) == 0)
+ kind = OMP_CLAUSE_PROC_BIND_SPREAD;
+ else
+ goto invalid_kind;
+ }
+ else
+ goto invalid_kind;
+
+ cp_lexer_consume_token (parser->lexer);
+ if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_COMMA_CLOSE_PAREN))
+ goto resync_fail;
+
+ c = build_omp_clause (location, OMP_CLAUSE_PROC_BIND);
+ check_no_duplicate_clause (list, OMP_CLAUSE_PROC_BIND, "proc_bind",
+ location);
+ OMP_CLAUSE_PROC_BIND_KIND (c) = kind;
+ OMP_CLAUSE_CHAIN (c) = list;
+ return c;
+
+ invalid_kind:
+ cp_parser_error (parser, "invalid depend kind");
+ resync_fail:
+ cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+ /*or_comma=*/false,
+ /*consume_paren=*/true);
+ return list;
+}
+
/* Parse all OpenMP clauses. The set clauses allowed by the directive
is a bitmask in MASK. Return the list of clauses found; the result
of clause default goes in *pdefault. */
static tree
-cp_parser_omp_all_clauses (cp_parser *parser, unsigned int mask,
- const char *where, cp_token *pragma_tok)
+cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask,
+ const char *where, cp_token *pragma_tok,
+ bool finish_p = true)
{
tree clauses = NULL;
bool first = true;
@@ -26950,7 +27772,6 @@ cp_parser_omp_all_clauses (cp_parser *parser, unsigned int mask,
token = cp_lexer_peek_token (parser->lexer);
c_kind = cp_parser_omp_clause_name (parser);
- first = false;
switch (c_kind)
{
@@ -27032,13 +27853,125 @@ cp_parser_omp_all_clauses (cp_parser *parser, unsigned int mask,
case PRAGMA_OMP_CLAUSE_UNTIED:
clauses = cp_parser_omp_clause_untied (parser, clauses,
token->location);
- c_name = "nowait";
+ c_name = "untied";
+ break;
+ case PRAGMA_OMP_CLAUSE_INBRANCH:
+ clauses = cp_parser_omp_clause_branch (parser, OMP_CLAUSE_INBRANCH,
+ clauses, token->location);
+ c_name = "inbranch";
+ break;
+ case PRAGMA_OMP_CLAUSE_NOTINBRANCH:
+ clauses = cp_parser_omp_clause_branch (parser,
+ OMP_CLAUSE_NOTINBRANCH,
+ clauses, token->location);
+ c_name = "notinbranch";
+ break;
+ case PRAGMA_OMP_CLAUSE_PARALLEL:
+ clauses = cp_parser_omp_clause_cancelkind (parser, OMP_CLAUSE_PARALLEL,
+ clauses, token->location);
+ c_name = "parallel";
+ if (!first)
+ {
+ clause_not_first:
+ error_at (token->location, "%qs must be the first clause of %qs",
+ c_name, where);
+ clauses = prev;
+ }
+ break;
+ case PRAGMA_OMP_CLAUSE_FOR:
+ clauses = cp_parser_omp_clause_cancelkind (parser, OMP_CLAUSE_FOR,
+ clauses, token->location);
+ c_name = "for";
+ if (!first)
+ goto clause_not_first;
+ break;
+ case PRAGMA_OMP_CLAUSE_SECTIONS:
+ clauses = cp_parser_omp_clause_cancelkind (parser, OMP_CLAUSE_SECTIONS,
+ clauses, token->location);
+ c_name = "sections";
+ if (!first)
+ goto clause_not_first;
+ break;
+ case PRAGMA_OMP_CLAUSE_TASKGROUP:
+ clauses = cp_parser_omp_clause_cancelkind (parser, OMP_CLAUSE_TASKGROUP,
+ clauses, token->location);
+ c_name = "taskgroup";
+ if (!first)
+ goto clause_not_first;
+ break;
+ case PRAGMA_OMP_CLAUSE_TO:
+ clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_TO,
+ clauses);
+ c_name = "to";
+ break;
+ case PRAGMA_OMP_CLAUSE_FROM:
+ clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_FROM,
+ clauses);
+ c_name = "from";
+ break;
+ case PRAGMA_OMP_CLAUSE_UNIFORM:
+ clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_UNIFORM,
+ clauses);
+ c_name = "uniform";
+ break;
+ case PRAGMA_OMP_CLAUSE_NUM_TEAMS:
+ clauses = cp_parser_omp_clause_num_teams (parser, clauses,
+ token->location);
+ c_name = "num_teams";
+ break;
+ case PRAGMA_OMP_CLAUSE_THREAD_LIMIT:
+ clauses = cp_parser_omp_clause_thread_limit (parser, clauses,
+ token->location);
+ c_name = "thread_limit";
+ break;
+ case PRAGMA_OMP_CLAUSE_ALIGNED:
+ clauses = cp_parser_omp_clause_aligned (parser, clauses);
+ c_name = "aligned";
+ break;
+ case PRAGMA_OMP_CLAUSE_LINEAR:
+ clauses = cp_parser_omp_clause_linear (parser, clauses);
+ c_name = "linear";
+ break;
+ case PRAGMA_OMP_CLAUSE_DEPEND:
+ clauses = cp_parser_omp_clause_depend (parser, clauses);
+ c_name = "depend";
+ break;
+ case PRAGMA_OMP_CLAUSE_MAP:
+ clauses = cp_parser_omp_clause_map (parser, clauses);
+ c_name = "map";
+ break;
+ case PRAGMA_OMP_CLAUSE_DEVICE:
+ clauses = cp_parser_omp_clause_device (parser, clauses,
+ token->location);
+ c_name = "device";
+ break;
+ case PRAGMA_OMP_CLAUSE_DIST_SCHEDULE:
+ clauses = cp_parser_omp_clause_dist_schedule (parser, clauses,
+ token->location);
+ c_name = "dist_schedule";
+ break;
+ case PRAGMA_OMP_CLAUSE_PROC_BIND:
+ clauses = cp_parser_omp_clause_proc_bind (parser, clauses,
+ token->location);
+ c_name = "proc_bind";
+ break;
+ case PRAGMA_OMP_CLAUSE_SAFELEN:
+ clauses = cp_parser_omp_clause_safelen (parser, clauses,
+ token->location);
+ c_name = "safelen";
+ break;
+ case PRAGMA_OMP_CLAUSE_SIMDLEN:
+ clauses = cp_parser_omp_clause_simdlen (parser, clauses,
+ token->location);
+ c_name = "simdlen";
break;
default:
cp_parser_error (parser, "expected %<#pragma omp%> clause");
goto saw_error;
}
+ first = false;
+
if (((mask >> c_kind) & 1) == 0)
{
/* Remove the invalid clause(s) from the list to avoid
@@ -27049,7 +27982,9 @@ cp_parser_omp_all_clauses (cp_parser *parser, unsigned int mask,
}
saw_error:
cp_parser_skip_to_pragma_eol (parser, pragma_tok);
- return finish_omp_clauses (clauses);
+ if (finish_p)
+ return finish_omp_clauses (clauses);
+ return clauses;
}
/* OpenMP 2.5:
@@ -27134,10 +28069,18 @@ cp_parser_omp_structured_block (cp_parser *parser)
update-stmt:
expression-stmt | x = x binop expr
capture-stmt:
- v = x binop= expr | v = x++ | v = ++x | v = x-- | v = --x
+ v = expression-stmt
capture-block:
{ v = x; update-stmt; } | { update-stmt; v = x; }
+ OpenMP 4.0:
+ update-stmt:
+ expression-stmt | x = x binop expr | x = expr binop x
+ capture-stmt:
+ v = update-stmt
+ capture-block:
+ { v = x; update-stmt; } | { update-stmt; v = x; } | { v = x; x = expr; }
+
where x and v are lvalue expressions with scalar type. */
static void
@@ -27147,6 +28090,7 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok)
tree rhs1 = NULL_TREE, orig_lhs;
enum tree_code code = OMP_ATOMIC, opcode = NOP_EXPR;
bool structured_block = false;
+ bool seq_cst = false;
if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
{
@@ -27166,6 +28110,18 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok)
if (p)
cp_lexer_consume_token (parser->lexer);
}
+
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+ {
+ tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+ const char *p = IDENTIFIER_POINTER (id);
+
+ if (!strcmp (p, "seq_cst"))
+ {
+ seq_cst = true;
+ cp_lexer_consume_token (parser->lexer);
+ }
+ }
cp_parser_require_pragma_eol (parser, pragma_tok);
switch (code)
@@ -27304,75 +28260,139 @@ restart:
opcode = BIT_XOR_EXPR;
break;
case CPP_EQ:
- if (structured_block || code == OMP_ATOMIC)
+ enum cp_parser_prec oprec;
+ cp_token *token;
+ cp_lexer_consume_token (parser->lexer);
+ cp_parser_parse_tentatively (parser);
+ rhs1 = cp_parser_simple_cast_expression (parser);
+ if (rhs1 == error_mark_node)
{
- enum cp_parser_prec oprec;
- cp_token *token;
- cp_lexer_consume_token (parser->lexer);
- rhs1 = cp_parser_unary_expression (parser, /*address_p=*/false,
- /*cast_p=*/false, NULL);
- if (rhs1 == error_mark_node)
- goto saw_error;
- token = cp_lexer_peek_token (parser->lexer);
- switch (token->type)
+ cp_parser_abort_tentative_parse (parser);
+ cp_parser_simple_cast_expression (parser);
+ goto saw_error;
+ }
+ token = cp_lexer_peek_token (parser->lexer);
+ if (token->type != CPP_SEMICOLON && !cp_tree_equal (lhs, rhs1))
+ {
+ cp_parser_abort_tentative_parse (parser);
+ cp_parser_parse_tentatively (parser);
+ rhs = cp_parser_binary_expression (parser, false, true,
+ PREC_NOT_OPERATOR, NULL);
+ if (rhs == error_mark_node)
{
- case CPP_SEMICOLON:
- if (code == OMP_ATOMIC_CAPTURE_NEW)
+ cp_parser_abort_tentative_parse (parser);
+ cp_parser_binary_expression (parser, false, true,
+ PREC_NOT_OPERATOR, NULL);
+ goto saw_error;
+ }
+ switch (TREE_CODE (rhs))
+ {
+ case MULT_EXPR:
+ case TRUNC_DIV_EXPR:
+ case PLUS_EXPR:
+ case MINUS_EXPR:
+ case LSHIFT_EXPR:
+ case RSHIFT_EXPR:
+ case BIT_AND_EXPR:
+ case BIT_IOR_EXPR:
+ case BIT_XOR_EXPR:
+ if (cp_tree_equal (lhs, TREE_OPERAND (rhs, 1)))
{
- code = OMP_ATOMIC_CAPTURE_OLD;
- v = lhs;
- lhs = NULL_TREE;
- lhs1 = rhs1;
- rhs1 = NULL_TREE;
- cp_lexer_consume_token (parser->lexer);
- goto restart;
+ if (cp_parser_parse_definitely (parser))
+ {
+ opcode = TREE_CODE (rhs);
+ rhs1 = TREE_OPERAND (rhs, 0);
+ rhs = TREE_OPERAND (rhs, 1);
+ goto stmt_done;
+ }
+ else
+ goto saw_error;
}
- cp_parser_error (parser,
- "invalid form of %<#pragma omp atomic%>");
- goto saw_error;
- case CPP_MULT:
- opcode = MULT_EXPR;
- break;
- case CPP_DIV:
- opcode = TRUNC_DIV_EXPR;
- break;
- case CPP_PLUS:
- opcode = PLUS_EXPR;
- break;
- case CPP_MINUS:
- opcode = MINUS_EXPR;
- break;
- case CPP_LSHIFT:
- opcode = LSHIFT_EXPR;
- break;
- case CPP_RSHIFT:
- opcode = RSHIFT_EXPR;
- break;
- case CPP_AND:
- opcode = BIT_AND_EXPR;
- break;
- case CPP_OR:
- opcode = BIT_IOR_EXPR;
- break;
- case CPP_XOR:
- opcode = BIT_XOR_EXPR;
break;
default:
- cp_parser_error (parser,
- "invalid operator for %<#pragma omp atomic%>");
- goto saw_error;
+ break;
}
- oprec = TOKEN_PRECEDENCE (token);
- gcc_assert (oprec != PREC_NOT_OPERATOR);
- if (commutative_tree_code (opcode))
- oprec = (enum cp_parser_prec) (oprec - 1);
- cp_lexer_consume_token (parser->lexer);
- rhs = cp_parser_binary_expression (parser, false, false,
- oprec, NULL);
- if (rhs == error_mark_node)
- goto saw_error;
- goto stmt_done;
+ cp_parser_abort_tentative_parse (parser);
+ if (structured_block && code == OMP_ATOMIC_CAPTURE_OLD)
+ {
+ rhs = cp_parser_expression (parser, /*cast_p=*/false, NULL);
+ if (rhs == error_mark_node)
+ goto saw_error;
+ opcode = NOP_EXPR;
+ rhs1 = NULL_TREE;
+ goto stmt_done;
+ }
+ cp_parser_error (parser,
+ "invalid form of %<#pragma omp atomic%>");
+ goto saw_error;
+ }
+ if (!cp_parser_parse_definitely (parser))
+ goto saw_error;
+ switch (token->type)
+ {
+ case CPP_SEMICOLON:
+ if (structured_block && code == OMP_ATOMIC_CAPTURE_NEW)
+ {
+ code = OMP_ATOMIC_CAPTURE_OLD;
+ v = lhs;
+ lhs = NULL_TREE;
+ lhs1 = rhs1;
+ rhs1 = NULL_TREE;
+ cp_lexer_consume_token (parser->lexer);
+ goto restart;
+ }
+ else if (structured_block)
+ {
+ opcode = NOP_EXPR;
+ rhs = rhs1;
+ rhs1 = NULL_TREE;
+ goto stmt_done;
+ }
+ cp_parser_error (parser,
+ "invalid form of %<#pragma omp atomic%>");
+ goto saw_error;
+ case CPP_MULT:
+ opcode = MULT_EXPR;
+ break;
+ case CPP_DIV:
+ opcode = TRUNC_DIV_EXPR;
+ break;
+ case CPP_PLUS:
+ opcode = PLUS_EXPR;
+ break;
+ case CPP_MINUS:
+ opcode = MINUS_EXPR;
+ break;
+ case CPP_LSHIFT:
+ opcode = LSHIFT_EXPR;
+ break;
+ case CPP_RSHIFT:
+ opcode = RSHIFT_EXPR;
+ break;
+ case CPP_AND:
+ opcode = BIT_AND_EXPR;
+ break;
+ case CPP_OR:
+ opcode = BIT_IOR_EXPR;
+ break;
+ case CPP_XOR:
+ opcode = BIT_XOR_EXPR;
+ break;
+ default:
+ cp_parser_error (parser,
+ "invalid operator for %<#pragma omp atomic%>");
+ goto saw_error;
}
+ oprec = TOKEN_PRECEDENCE (token);
+ gcc_assert (oprec != PREC_NOT_OPERATOR);
+ if (commutative_tree_code (opcode))
+ oprec = (enum cp_parser_prec) (oprec - 1);
+ cp_lexer_consume_token (parser->lexer);
+ rhs = cp_parser_binary_expression (parser, false, false,
+ oprec, NULL);
+ if (rhs == error_mark_node)
+ goto saw_error;
+ goto stmt_done;
/* FALLTHROUGH */
default:
cp_parser_error (parser,
@@ -27408,7 +28428,7 @@ stmt_done:
cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
}
done:
- finish_omp_atomic (code, opcode, lhs, rhs, v, lhs1, rhs1);
+ finish_omp_atomic (code, opcode, lhs, rhs, v, lhs1, rhs1, seq_cst);
if (!structured_block)
cp_parser_consume_semicolon_at_end_of_statement (parser);
return;
@@ -27617,7 +28637,8 @@ cp_parser_omp_for_incr (cp_parser *parser, tree decl)
/* Parse the restricted form of the for statement allowed by OpenMP. */
static tree
-cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses)
+cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
+ tree *cclauses)
{
tree init, cond, incr, body, decl, pre_body = NULL_TREE, ret;
tree real_decl, initv, condv, incrv, declv;
@@ -27827,10 +28848,12 @@ cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses)
if (decl)
real_decl = decl;
- if (par_clauses != NULL && real_decl != NULL_TREE)
+ if (cclauses != NULL
+ && cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] != NULL
+ && real_decl != NULL_TREE)
{
tree *c;
- for (c = par_clauses; *c ; )
+ for (c = &cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL]; *c ; )
if (OMP_CLAUSE_CODE (*c) == OMP_CLAUSE_FIRSTPRIVATE
&& OMP_CLAUSE_DECL (*c) == real_decl)
{
@@ -27976,7 +28999,7 @@ cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses)
if (declv == NULL_TREE)
ret = NULL_TREE;
else
- ret = finish_omp_for (loc_first, declv, initv, condv, incrv, body,
+ ret = finish_omp_for (loc_first, code, declv, initv, condv, incrv, body,
pre_body, clauses);
while (nbraces)
@@ -28009,33 +29032,145 @@ cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses)
return ret;
}
+/* Helper function for OpenMP parsing, split clauses and call
+ finish_omp_clauses on each of the set of clauses afterwards. */
+
+static void
+cp_omp_split_clauses (location_t loc, enum tree_code code,
+ omp_clause_mask mask, tree clauses, tree *cclauses)
+{
+ int i;
+ c_omp_split_clauses (loc, code, mask, clauses, cclauses);
+ for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++)
+ if (cclauses[i])
+ cclauses[i] = finish_omp_clauses (cclauses[i]);
+}
+
+/* OpenMP 4.0:
+ #pragma omp simd simd-clause[optseq] new-line
+ for-loop */
+
+#define OMP_SIMD_CLAUSE_MASK \
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SAFELEN) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALIGNED) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE))
+
+static tree
+cp_parser_omp_simd (cp_parser *parser, cp_token *pragma_tok,
+ char *p_name, omp_clause_mask mask, tree *cclauses)
+{
+ tree clauses, sb, ret;
+ unsigned int save;
+ location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+
+ strcat (p_name, " simd");
+ mask |= OMP_SIMD_CLAUSE_MASK;
+ mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDERED);
+
+ clauses = cp_parser_omp_all_clauses (parser, mask, p_name, pragma_tok,
+ cclauses == NULL);
+ if (cclauses)
+ {
+ cp_omp_split_clauses (loc, OMP_SIMD, mask, clauses, cclauses);
+ clauses = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
+ }
+
+ sb = begin_omp_structured_block ();
+ save = cp_parser_begin_omp_structured_block (parser);
+
+ ret = cp_parser_omp_for_loop (parser, OMP_SIMD, clauses, cclauses);
+
+ cp_parser_end_omp_structured_block (parser, save);
+ add_stmt (finish_omp_structured_block (sb));
+
+ return ret;
+}
+
/* OpenMP 2.5:
#pragma omp for for-clause[optseq] new-line
+ for-loop
+
+ OpenMP 4.0:
+ #pragma omp for simd for-simd-clause[optseq] new-line
for-loop */
-#define OMP_FOR_CLAUSE_MASK \
- ( (1u << PRAGMA_OMP_CLAUSE_PRIVATE) \
- | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
- | (1u << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
- | (1u << PRAGMA_OMP_CLAUSE_REDUCTION) \
- | (1u << PRAGMA_OMP_CLAUSE_ORDERED) \
- | (1u << PRAGMA_OMP_CLAUSE_SCHEDULE) \
- | (1u << PRAGMA_OMP_CLAUSE_NOWAIT) \
- | (1u << PRAGMA_OMP_CLAUSE_COLLAPSE))
+#define OMP_FOR_CLAUSE_MASK \
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDERED) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE))
static tree
-cp_parser_omp_for (cp_parser *parser, cp_token *pragma_tok)
+cp_parser_omp_for (cp_parser *parser, cp_token *pragma_tok,
+ char *p_name, omp_clause_mask mask, tree *cclauses)
{
tree clauses, sb, ret;
unsigned int save;
+ location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+
+ strcat (p_name, " for");
+ mask |= OMP_FOR_CLAUSE_MASK;
+ if (cclauses)
+ mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT);
+
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+ {
+ tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+ const char *p = IDENTIFIER_POINTER (id);
+
+ if (strcmp (p, "simd") == 0)
+ {
+ tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
+ if (cclauses == NULL)
+ cclauses = cclauses_buf;
+
+ cp_lexer_consume_token (parser->lexer);
+ if (!flag_openmp) /* flag_openmp_simd */
+ return cp_parser_omp_simd (parser, pragma_tok, p_name, mask,
+ cclauses);
+ sb = begin_omp_structured_block ();
+ save = cp_parser_begin_omp_structured_block (parser);
+ ret = cp_parser_omp_simd (parser, pragma_tok, p_name, mask,
+ cclauses);
+ cp_parser_end_omp_structured_block (parser, save);
+ tree body = finish_omp_structured_block (sb);
+ if (ret == NULL)
+ return ret;
+ ret = make_node (OMP_FOR);
+ TREE_TYPE (ret) = void_type_node;
+ OMP_FOR_BODY (ret) = body;
+ OMP_FOR_CLAUSES (ret) = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
+ SET_EXPR_LOCATION (ret, loc);
+ add_stmt (ret);
+ return ret;
+ }
+ }
+ if (!flag_openmp) /* flag_openmp_simd */
+ {
+ cp_parser_require_pragma_eol (parser, pragma_tok);
+ return NULL_TREE;
+ }
- clauses = cp_parser_omp_all_clauses (parser, OMP_FOR_CLAUSE_MASK,
- "#pragma omp for", pragma_tok);
+ clauses = cp_parser_omp_all_clauses (parser, mask, p_name, pragma_tok,
+ cclauses == NULL);
+ if (cclauses)
+ {
+ cp_omp_split_clauses (loc, OMP_FOR, mask, clauses, cclauses);
+ clauses = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
+ }
sb = begin_omp_structured_block ();
save = cp_parser_begin_omp_structured_block (parser);
- ret = cp_parser_omp_for_loop (parser, clauses, NULL);
+ ret = cp_parser_omp_for_loop (parser, OMP_FOR, clauses, cclauses);
cp_parser_end_omp_structured_block (parser, save);
add_stmt (finish_omp_structured_block (sb));
@@ -28090,26 +29225,7 @@ cp_parser_omp_sections_scope (cp_parser *parser)
if (cp_lexer_peek_token (parser->lexer)->pragma_kind != PRAGMA_OMP_SECTION)
{
- unsigned save;
-
- substmt = begin_omp_structured_block ();
- save = cp_parser_begin_omp_structured_block (parser);
-
- while (1)
- {
- cp_parser_statement (parser, NULL_TREE, false, NULL);
-
- tok = cp_lexer_peek_token (parser->lexer);
- if (tok->pragma_kind == PRAGMA_OMP_SECTION)
- break;
- if (tok->type == CPP_CLOSE_BRACE)
- break;
- if (tok->type == CPP_EOF)
- break;
- }
-
- cp_parser_end_omp_structured_block (parser, save);
- substmt = finish_omp_structured_block (substmt);
+ substmt = cp_parser_omp_structured_block (parser);
substmt = build1 (OMP_SECTION, void_type_node, substmt);
add_stmt (substmt);
}
@@ -28154,20 +29270,32 @@ cp_parser_omp_sections_scope (cp_parser *parser)
# pragma omp sections sections-clause[optseq] newline
sections-scope */
-#define OMP_SECTIONS_CLAUSE_MASK \
- ( (1u << PRAGMA_OMP_CLAUSE_PRIVATE) \
- | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
- | (1u << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
- | (1u << PRAGMA_OMP_CLAUSE_REDUCTION) \
- | (1u << PRAGMA_OMP_CLAUSE_NOWAIT))
+#define OMP_SECTIONS_CLAUSE_MASK \
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
static tree
-cp_parser_omp_sections (cp_parser *parser, cp_token *pragma_tok)
+cp_parser_omp_sections (cp_parser *parser, cp_token *pragma_tok,
+ char *p_name, omp_clause_mask mask, tree *cclauses)
{
tree clauses, ret;
+ location_t loc = cp_lexer_peek_token (parser->lexer)->location;
- clauses = cp_parser_omp_all_clauses (parser, OMP_SECTIONS_CLAUSE_MASK,
- "#pragma omp sections", pragma_tok);
+ strcat (p_name, " sections");
+ mask |= OMP_SECTIONS_CLAUSE_MASK;
+ if (cclauses)
+ mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT);
+
+ clauses = cp_parser_omp_all_clauses (parser, mask, p_name, pragma_tok,
+ cclauses == NULL);
+ if (cclauses)
+ {
+ cp_omp_split_clauses (loc, OMP_SECTIONS, mask, clauses, cclauses);
+ clauses = cclauses[C_OMP_CLAUSE_SPLIT_SECTIONS];
+ }
ret = cp_parser_omp_sections_scope (parser);
if (ret)
@@ -28179,35 +29307,61 @@ cp_parser_omp_sections (cp_parser *parser, cp_token *pragma_tok)
/* OpenMP 2.5:
# pragma parallel parallel-clause new-line
# pragma parallel for parallel-for-clause new-line
- # pragma parallel sections parallel-sections-clause new-line */
-
-#define OMP_PARALLEL_CLAUSE_MASK \
- ( (1u << PRAGMA_OMP_CLAUSE_IF) \
- | (1u << PRAGMA_OMP_CLAUSE_PRIVATE) \
- | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
- | (1u << PRAGMA_OMP_CLAUSE_DEFAULT) \
- | (1u << PRAGMA_OMP_CLAUSE_SHARED) \
- | (1u << PRAGMA_OMP_CLAUSE_COPYIN) \
- | (1u << PRAGMA_OMP_CLAUSE_REDUCTION) \
- | (1u << PRAGMA_OMP_CLAUSE_NUM_THREADS))
+ # pragma parallel sections parallel-sections-clause new-line
+
+ OpenMP 4.0:
+ # pragma parallel for simd parallel-for-simd-clause new-line */
+
+#define OMP_PARALLEL_CLAUSE_MASK \
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COPYIN) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PROC_BIND))
static tree
-cp_parser_omp_parallel (cp_parser *parser, cp_token *pragma_tok)
+cp_parser_omp_parallel (cp_parser *parser, cp_token *pragma_tok,
+ char *p_name, omp_clause_mask mask, tree *cclauses)
{
- enum pragma_kind p_kind = PRAGMA_OMP_PARALLEL;
- const char *p_name = "#pragma omp parallel";
- tree stmt, clauses, par_clause, ws_clause, block;
- unsigned int mask = OMP_PARALLEL_CLAUSE_MASK;
+ tree stmt, clauses, block;
unsigned int save;
location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+ strcat (p_name, " parallel");
+ mask |= OMP_PARALLEL_CLAUSE_MASK;
+
if (cp_lexer_next_token_is_keyword (parser->lexer, RID_FOR))
{
+ tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
+ if (cclauses == NULL)
+ cclauses = cclauses_buf;
+
cp_lexer_consume_token (parser->lexer);
- p_kind = PRAGMA_OMP_PARALLEL_FOR;
- p_name = "#pragma omp parallel for";
- mask |= OMP_FOR_CLAUSE_MASK;
- mask &= ~(1u << PRAGMA_OMP_CLAUSE_NOWAIT);
+ if (!flag_openmp) /* flag_openmp_simd */
+ return cp_parser_omp_for (parser, pragma_tok, p_name, mask, cclauses);
+ block = begin_omp_parallel ();
+ save = cp_parser_begin_omp_structured_block (parser);
+ cp_parser_omp_for (parser, pragma_tok, p_name, mask, cclauses);
+ cp_parser_end_omp_structured_block (parser, save);
+ stmt = finish_omp_parallel (cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
+ block);
+ OMP_PARALLEL_COMBINED (stmt) = 1;
+ return stmt;
+ }
+ else if (cclauses)
+ {
+ error_at (loc, "expected %<for%> after %qs", p_name);
+ cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+ return NULL_TREE;
+ }
+ else if (!flag_openmp) /* flag_openmp_simd */
+ {
+ cp_parser_require_pragma_eol (parser, pragma_tok);
+ return NULL_TREE;
}
else if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
{
@@ -28215,45 +29369,28 @@ cp_parser_omp_parallel (cp_parser *parser, cp_token *pragma_tok)
const char *p = IDENTIFIER_POINTER (id);
if (strcmp (p, "sections") == 0)
{
+ tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
+ cclauses = cclauses_buf;
+
cp_lexer_consume_token (parser->lexer);
- p_kind = PRAGMA_OMP_PARALLEL_SECTIONS;
- p_name = "#pragma omp parallel sections";
- mask |= OMP_SECTIONS_CLAUSE_MASK;
- mask &= ~(1u << PRAGMA_OMP_CLAUSE_NOWAIT);
+ block = begin_omp_parallel ();
+ save = cp_parser_begin_omp_structured_block (parser);
+ cp_parser_omp_sections (parser, pragma_tok, p_name, mask, cclauses);
+ cp_parser_end_omp_structured_block (parser, save);
+ stmt = finish_omp_parallel (cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
+ block);
+ OMP_PARALLEL_COMBINED (stmt) = 1;
+ return stmt;
}
}
clauses = cp_parser_omp_all_clauses (parser, mask, p_name, pragma_tok);
+
block = begin_omp_parallel ();
save = cp_parser_begin_omp_structured_block (parser);
-
- switch (p_kind)
- {
- case PRAGMA_OMP_PARALLEL:
- cp_parser_statement (parser, NULL_TREE, false, NULL);
- par_clause = clauses;
- break;
-
- case PRAGMA_OMP_PARALLEL_FOR:
- c_split_parallel_clauses (loc, clauses, &par_clause, &ws_clause);
- cp_parser_omp_for_loop (parser, ws_clause, &par_clause);
- break;
-
- case PRAGMA_OMP_PARALLEL_SECTIONS:
- c_split_parallel_clauses (loc, clauses, &par_clause, &ws_clause);
- stmt = cp_parser_omp_sections_scope (parser);
- if (stmt)
- OMP_SECTIONS_CLAUSES (stmt) = ws_clause;
- break;
-
- default:
- gcc_unreachable ();
- }
-
+ cp_parser_statement (parser, NULL_TREE, false, NULL);
cp_parser_end_omp_structured_block (parser, save);
- stmt = finish_omp_parallel (par_clause, block);
- if (p_kind != PRAGMA_OMP_PARALLEL)
- OMP_PARALLEL_COMBINED (stmt) = 1;
+ stmt = finish_omp_parallel (clauses, block);
return stmt;
}
@@ -28261,11 +29398,11 @@ cp_parser_omp_parallel (cp_parser *parser, cp_token *pragma_tok)
# pragma omp single single-clause[optseq] new-line
structured-block */
-#define OMP_SINGLE_CLAUSE_MASK \
- ( (1u << PRAGMA_OMP_CLAUSE_PRIVATE) \
- | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
- | (1u << PRAGMA_OMP_CLAUSE_COPYPRIVATE) \
- | (1u << PRAGMA_OMP_CLAUSE_NOWAIT))
+#define OMP_SINGLE_CLAUSE_MASK \
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COPYPRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
static tree
cp_parser_omp_single (cp_parser *parser, cp_token *pragma_tok)
@@ -28285,15 +29422,16 @@ cp_parser_omp_single (cp_parser *parser, cp_token *pragma_tok)
# pragma omp task task-clause[optseq] new-line
structured-block */
-#define OMP_TASK_CLAUSE_MASK \
- ( (1u << PRAGMA_OMP_CLAUSE_IF) \
- | (1u << PRAGMA_OMP_CLAUSE_UNTIED) \
- | (1u << PRAGMA_OMP_CLAUSE_DEFAULT) \
- | (1u << PRAGMA_OMP_CLAUSE_PRIVATE) \
- | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
- | (1u << PRAGMA_OMP_CLAUSE_SHARED) \
- | (1u << PRAGMA_OMP_CLAUSE_FINAL) \
- | (1u << PRAGMA_OMP_CLAUSE_MERGEABLE))
+#define OMP_TASK_CLAUSE_MASK \
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNTIED) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FINAL) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MERGEABLE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND))
static tree
cp_parser_omp_task (cp_parser *parser, cp_token *pragma_tok)
@@ -28330,6 +29468,19 @@ cp_parser_omp_taskyield (cp_parser *parser, cp_token *pragma_tok)
finish_omp_taskyield ();
}
+/* OpenMP 4.0:
+ # pragma omp taskgroup new-line
+ structured-block */
+
+static tree
+cp_parser_omp_taskgroup (cp_parser *parser, cp_token *pragma_tok)
+{
+ cp_parser_require_pragma_eol (parser, pragma_tok);
+ return c_finish_omp_taskgroup (input_location,
+ cp_parser_omp_structured_block (parser));
+}
+
+
/* OpenMP 2.5:
# pragma omp threadprivate (variable-list) */
@@ -28344,12 +29495,992 @@ cp_parser_omp_threadprivate (cp_parser *parser, cp_token *pragma_tok)
finish_omp_threadprivate (vars);
}
+/* OpenMP 4.0:
+ # pragma omp cancel cancel-clause[optseq] new-line */
+
+#define OMP_CANCEL_CLAUSE_MASK \
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PARALLEL) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FOR) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SECTIONS) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASKGROUP) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF))
+
+static void
+cp_parser_omp_cancel (cp_parser *parser, cp_token *pragma_tok)
+{
+ tree clauses = cp_parser_omp_all_clauses (parser, OMP_CANCEL_CLAUSE_MASK,
+ "#pragma omp cancel", pragma_tok);
+ finish_omp_cancel (clauses);
+}
+
+/* OpenMP 4.0:
+ # pragma omp cancellation point cancelpt-clause[optseq] new-line */
+
+#define OMP_CANCELLATION_POINT_CLAUSE_MASK \
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PARALLEL) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FOR) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SECTIONS) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASKGROUP))
+
+static void
+cp_parser_omp_cancellation_point (cp_parser *parser, cp_token *pragma_tok)
+{
+ tree clauses;
+ bool point_seen = false;
+
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+ {
+ tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+ const char *p = IDENTIFIER_POINTER (id);
+
+ if (strcmp (p, "point") == 0)
+ {
+ cp_lexer_consume_token (parser->lexer);
+ point_seen = true;
+ }
+ }
+ if (!point_seen)
+ {
+ cp_parser_error (parser, "expected %<point%>");
+ cp_parser_require_pragma_eol (parser, pragma_tok);
+ return;
+ }
+
+ clauses = cp_parser_omp_all_clauses (parser,
+ OMP_CANCELLATION_POINT_CLAUSE_MASK,
+ "#pragma omp cancellation point",
+ pragma_tok);
+ finish_omp_cancellation_point (clauses);
+}
+
+/* OpenMP 4.0:
+ #pragma omp distribute distribute-clause[optseq] new-line
+ for-loop */
+
+#define OMP_DISTRIBUTE_CLAUSE_MASK \
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)\
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE))
+
+static tree
+cp_parser_omp_distribute (cp_parser *parser, cp_token *pragma_tok,
+ char *p_name, omp_clause_mask mask, tree *cclauses)
+{
+ tree clauses, sb, ret;
+ unsigned int save;
+ location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+
+ strcat (p_name, " distribute");
+ mask |= OMP_DISTRIBUTE_CLAUSE_MASK;
+
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+ {
+ tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+ const char *p = IDENTIFIER_POINTER (id);
+ bool simd = false;
+ bool parallel = false;
+
+ if (strcmp (p, "simd") == 0)
+ simd = true;
+ else
+ parallel = strcmp (p, "parallel") == 0;
+ if (parallel || simd)
+ {
+ tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
+ if (cclauses == NULL)
+ cclauses = cclauses_buf;
+ cp_lexer_consume_token (parser->lexer);
+ if (!flag_openmp) /* flag_openmp_simd */
+ {
+ if (simd)
+ return cp_parser_omp_simd (parser, pragma_tok, p_name, mask,
+ cclauses);
+ else
+ return cp_parser_omp_parallel (parser, pragma_tok, p_name, mask,
+ cclauses);
+ }
+ sb = begin_omp_structured_block ();
+ save = cp_parser_begin_omp_structured_block (parser);
+ if (simd)
+ ret = cp_parser_omp_simd (parser, pragma_tok, p_name, mask,
+ cclauses);
+ else
+ ret = cp_parser_omp_parallel (parser, pragma_tok, p_name, mask,
+ cclauses);
+ cp_parser_end_omp_structured_block (parser, save);
+ tree body = finish_omp_structured_block (sb);
+ if (ret == NULL)
+ return ret;
+ ret = make_node (OMP_DISTRIBUTE);
+ TREE_TYPE (ret) = void_type_node;
+ OMP_FOR_BODY (ret) = body;
+ OMP_FOR_CLAUSES (ret) = cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE];
+ SET_EXPR_LOCATION (ret, loc);
+ add_stmt (ret);
+ return ret;
+ }
+ }
+ if (!flag_openmp) /* flag_openmp_simd */
+ {
+ cp_parser_require_pragma_eol (parser, pragma_tok);
+ return NULL_TREE;
+ }
+
+ clauses = cp_parser_omp_all_clauses (parser, mask, p_name, pragma_tok,
+ cclauses == NULL);
+ if (cclauses)
+ {
+ cp_omp_split_clauses (loc, OMP_DISTRIBUTE, mask, clauses, cclauses);
+ clauses = cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE];
+ }
+
+ sb = begin_omp_structured_block ();
+ save = cp_parser_begin_omp_structured_block (parser);
+
+ ret = cp_parser_omp_for_loop (parser, OMP_DISTRIBUTE, clauses, NULL);
+
+ cp_parser_end_omp_structured_block (parser, save);
+ add_stmt (finish_omp_structured_block (sb));
+
+ return ret;
+}
+
+/* OpenMP 4.0:
+ # pragma omp teams teams-clause[optseq] new-line
+ structured-block */
+
+#define OMP_TEAMS_CLAUSE_MASK \
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_THREAD_LIMIT) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT))
+
+static tree
+cp_parser_omp_teams (cp_parser *parser, cp_token *pragma_tok,
+ char *p_name, omp_clause_mask mask, tree *cclauses)
+{
+ tree clauses, sb, ret;
+ unsigned int save;
+ location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+
+ strcat (p_name, " teams");
+ mask |= OMP_TEAMS_CLAUSE_MASK;
+
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+ {
+ tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+ const char *p = IDENTIFIER_POINTER (id);
+ if (strcmp (p, "distribute") == 0)
+ {
+ tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
+ if (cclauses == NULL)
+ cclauses = cclauses_buf;
+
+ cp_lexer_consume_token (parser->lexer);
+ if (!flag_openmp) /* flag_openmp_simd */
+ return cp_parser_omp_distribute (parser, pragma_tok, p_name, mask,
+ cclauses);
+ sb = begin_omp_structured_block ();
+ save = cp_parser_begin_omp_structured_block (parser);
+ ret = cp_parser_omp_distribute (parser, pragma_tok, p_name, mask,
+ cclauses);
+ cp_parser_end_omp_structured_block (parser, save);
+ tree body = finish_omp_structured_block (sb);
+ if (ret == NULL)
+ return ret;
+ clauses = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
+ ret = make_node (OMP_TEAMS);
+ TREE_TYPE (ret) = void_type_node;
+ OMP_TEAMS_CLAUSES (ret) = clauses;
+ OMP_TEAMS_BODY (ret) = body;
+ return add_stmt (ret);
+ }
+ }
+ if (!flag_openmp) /* flag_openmp_simd */
+ {
+ cp_parser_require_pragma_eol (parser, pragma_tok);
+ return NULL_TREE;
+ }
+
+ clauses = cp_parser_omp_all_clauses (parser, mask, p_name, pragma_tok,
+ cclauses == NULL);
+ if (cclauses)
+ {
+ cp_omp_split_clauses (loc, OMP_TEAMS, mask, clauses, cclauses);
+ clauses = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
+ }
+
+ tree stmt = make_node (OMP_TEAMS);
+ TREE_TYPE (stmt) = void_type_node;
+ OMP_TEAMS_CLAUSES (stmt) = clauses;
+ OMP_TEAMS_BODY (stmt) = cp_parser_omp_structured_block (parser);
+
+ return add_stmt (stmt);
+}
+
+/* OpenMP 4.0:
+ # pragma omp target data target-data-clause[optseq] new-line
+ structured-block */
+
+#define OMP_TARGET_DATA_CLAUSE_MASK \
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF))
+
+static tree
+cp_parser_omp_target_data (cp_parser *parser, cp_token *pragma_tok)
+{
+ tree stmt = make_node (OMP_TARGET_DATA);
+ TREE_TYPE (stmt) = void_type_node;
+
+ OMP_TARGET_DATA_CLAUSES (stmt)
+ = cp_parser_omp_all_clauses (parser, OMP_TARGET_DATA_CLAUSE_MASK,
+ "#pragma omp target data", pragma_tok);
+ keep_next_level (true);
+ OMP_TARGET_DATA_BODY (stmt) = cp_parser_omp_structured_block (parser);
+
+ SET_EXPR_LOCATION (stmt, pragma_tok->location);
+ return add_stmt (stmt);
+}
+
+/* OpenMP 4.0:
+ # pragma omp target update target-update-clause[optseq] new-line */
+
+#define OMP_TARGET_UPDATE_CLAUSE_MASK \
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FROM) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TO) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF))
+
+static bool
+cp_parser_omp_target_update (cp_parser *parser, cp_token *pragma_tok,
+ enum pragma_context context)
+{
+ if (context == pragma_stmt)
+ {
+ error_at (pragma_tok->location,
+ "%<#pragma omp target update%> may only be "
+ "used in compound statements");
+ cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+ return false;
+ }
+
+ tree clauses
+ = cp_parser_omp_all_clauses (parser, OMP_TARGET_UPDATE_CLAUSE_MASK,
+ "#pragma omp target update", pragma_tok);
+ if (find_omp_clause (clauses, OMP_CLAUSE_TO) == NULL_TREE
+ && find_omp_clause (clauses, OMP_CLAUSE_FROM) == NULL_TREE)
+ {
+ error_at (pragma_tok->location,
+ "%<#pragma omp target update must contain at least one "
+ "%<from%> or %<to%> clauses");
+ return false;
+ }
+
+ tree stmt = make_node (OMP_TARGET_UPDATE);
+ TREE_TYPE (stmt) = void_type_node;
+ OMP_TARGET_UPDATE_CLAUSES (stmt) = clauses;
+ SET_EXPR_LOCATION (stmt, pragma_tok->location);
+ add_stmt (stmt);
+ return false;
+}
+
+/* OpenMP 4.0:
+ # pragma omp target target-clause[optseq] new-line
+ structured-block */
+
+#define OMP_TARGET_CLAUSE_MASK \
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF))
+
+static bool
+cp_parser_omp_target (cp_parser *parser, cp_token *pragma_tok,
+ enum pragma_context context)
+{
+ if (context != pragma_stmt && context != pragma_compound)
+ {
+ cp_parser_error (parser, "expected declaration specifiers");
+ cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+ return false;
+ }
+
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+ {
+ tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+ const char *p = IDENTIFIER_POINTER (id);
+
+ if (strcmp (p, "teams") == 0)
+ {
+ tree cclauses[C_OMP_CLAUSE_SPLIT_COUNT];
+ char p_name[sizeof ("#pragma omp target teams distribute "
+ "parallel for simd")];
+
+ cp_lexer_consume_token (parser->lexer);
+ strcpy (p_name, "#pragma omp target");
+ keep_next_level (true);
+ if (!flag_openmp) /* flag_openmp_simd */
+ return cp_parser_omp_teams (parser, pragma_tok, p_name,
+ OMP_TARGET_CLAUSE_MASK, cclauses);
+ tree sb = begin_omp_structured_block ();
+ unsigned save = cp_parser_begin_omp_structured_block (parser);
+ tree ret = cp_parser_omp_teams (parser, pragma_tok, p_name,
+ OMP_TARGET_CLAUSE_MASK, cclauses);
+ cp_parser_end_omp_structured_block (parser, save);
+ tree body = finish_omp_structured_block (sb);
+ if (ret == NULL)
+ return ret;
+ tree stmt = make_node (OMP_TARGET);
+ TREE_TYPE (stmt) = void_type_node;
+ OMP_TARGET_CLAUSES (stmt) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
+ OMP_TARGET_BODY (stmt) = body;
+ add_stmt (stmt);
+ return true;
+ }
+ else if (!flag_openmp) /* flag_openmp_simd */
+ {
+ cp_parser_require_pragma_eol (parser, pragma_tok);
+ return NULL_TREE;
+ }
+ else if (strcmp (p, "data") == 0)
+ {
+ cp_lexer_consume_token (parser->lexer);
+ cp_parser_omp_target_data (parser, pragma_tok);
+ return true;
+ }
+ else if (strcmp (p, "update") == 0)
+ {
+ cp_lexer_consume_token (parser->lexer);
+ return cp_parser_omp_target_update (parser, pragma_tok, context);
+ }
+ }
+
+ tree stmt = make_node (OMP_TARGET);
+ TREE_TYPE (stmt) = void_type_node;
+
+ OMP_TARGET_CLAUSES (stmt)
+ = cp_parser_omp_all_clauses (parser, OMP_TARGET_CLAUSE_MASK,
+ "#pragma omp target", pragma_tok);
+ keep_next_level (true);
+ OMP_TARGET_BODY (stmt) = cp_parser_omp_structured_block (parser);
+
+ SET_EXPR_LOCATION (stmt, pragma_tok->location);
+ add_stmt (stmt);
+ return true;
+}
+
+/* OpenMP 4.0:
+ # pragma omp declare simd declare-simd-clauses[optseq] new-line */
+
+#define OMP_DECLARE_SIMD_CLAUSE_MASK \
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SIMDLEN) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALIGNED) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNIFORM) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_INBRANCH) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOTINBRANCH))
+
+static void
+cp_parser_omp_declare_simd (cp_parser *parser, cp_token *pragma_tok,
+ enum pragma_context context)
+{
+ bool first_p = parser->omp_declare_simd == NULL;
+ cp_omp_declare_simd_data data;
+ if (first_p)
+ {
+ data.error_seen = false;
+ data.fndecl_seen = false;
+ data.tokens = vNULL;
+ parser->omp_declare_simd = &data;
+ }
+ while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL)
+ && cp_lexer_next_token_is_not (parser->lexer, CPP_EOF))
+ cp_lexer_consume_token (parser->lexer);
+ if (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL))
+ parser->omp_declare_simd->error_seen = true;
+ cp_parser_require_pragma_eol (parser, pragma_tok);
+ struct cp_token_cache *cp
+ = cp_token_cache_new (pragma_tok, cp_lexer_peek_token (parser->lexer));
+ parser->omp_declare_simd->tokens.safe_push (cp);
+ if (first_p)
+ {
+ while (cp_lexer_next_token_is (parser->lexer, CPP_PRAGMA))
+ cp_parser_pragma (parser, context);
+ switch (context)
+ {
+ case pragma_external:
+ cp_parser_declaration (parser);
+ break;
+ case pragma_member:
+ cp_parser_member_declaration (parser);
+ break;
+ case pragma_objc_icode:
+ cp_parser_block_declaration (parser, /*statement_p=*/false);
+ break;
+ default:
+ cp_parser_declaration_statement (parser);
+ break;
+ }
+ if (parser->omp_declare_simd
+ && !parser->omp_declare_simd->error_seen
+ && !parser->omp_declare_simd->fndecl_seen)
+ error_at (pragma_tok->location,
+ "%<#pragma omp declare simd%> not immediately followed by "
+ "function declaration or definition");
+ data.tokens.release ();
+ parser->omp_declare_simd = NULL;
+ }
+}
+
+/* Finalize #pragma omp declare simd clauses after direct declarator has
+ been parsed, and put that into "omp declare simd" attribute. */
+
+static tree
+cp_parser_late_parsing_omp_declare_simd (cp_parser *parser, tree attrs)
+{
+ struct cp_token_cache *ce;
+ cp_omp_declare_simd_data *data = parser->omp_declare_simd;
+ int i;
+
+ if (!data->error_seen && data->fndecl_seen)
+ {
+ error ("%<#pragma omp declare simd%> not immediately followed by "
+ "a single function declaration or definition");
+ data->error_seen = true;
+ return attrs;
+ }
+ if (data->error_seen)
+ return attrs;
+
+ FOR_EACH_VEC_ELT (data->tokens, i, ce)
+ {
+ tree c, cl;
+
+ cp_parser_push_lexer_for_tokens (parser, ce);
+ parser->lexer->in_pragma = true;
+ gcc_assert (cp_lexer_peek_token (parser->lexer)->type == CPP_PRAGMA);
+ cp_token *pragma_tok = cp_lexer_consume_token (parser->lexer);
+ cp_lexer_consume_token (parser->lexer);
+ cl = cp_parser_omp_all_clauses (parser, OMP_DECLARE_SIMD_CLAUSE_MASK,
+ "#pragma omp declare simd", pragma_tok);
+ cp_parser_pop_lexer (parser);
+ if (cl)
+ cl = tree_cons (NULL_TREE, cl, NULL_TREE);
+ c = build_tree_list (get_identifier ("omp declare simd"), cl);
+ TREE_CHAIN (c) = attrs;
+ if (processing_template_decl)
+ ATTR_IS_DEPENDENT (c) = 1;
+ attrs = c;
+ }
+
+ data->fndecl_seen = true;
+ return attrs;
+}
+
+
+/* OpenMP 4.0:
+ # pragma omp declare target new-line
+ declarations and definitions
+ # pragma omp end declare target new-line */
+
+static void
+cp_parser_omp_declare_target (cp_parser *parser, cp_token *pragma_tok)
+{
+ cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+ scope_chain->omp_declare_target_attribute++;
+}
+
+static void
+cp_parser_omp_end_declare_target (cp_parser *parser, cp_token *pragma_tok)
+{
+ const char *p = "";
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+ {
+ tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+ p = IDENTIFIER_POINTER (id);
+ }
+ if (strcmp (p, "declare") == 0)
+ {
+ cp_lexer_consume_token (parser->lexer);
+ p = "";
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+ {
+ tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+ p = IDENTIFIER_POINTER (id);
+ }
+ if (strcmp (p, "target") == 0)
+ cp_lexer_consume_token (parser->lexer);
+ else
+ {
+ cp_parser_error (parser, "expected %<target%>");
+ cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+ return;
+ }
+ }
+ else
+ {
+ cp_parser_error (parser, "expected %<declare%>");
+ cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+ return;
+ }
+ cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+ if (!scope_chain->omp_declare_target_attribute)
+ error_at (pragma_tok->location,
+ "%<#pragma omp end declare target%> without corresponding "
+ "%<#pragma omp declare target%>");
+ else
+ scope_chain->omp_declare_target_attribute--;
+}
+
+/* Helper function of cp_parser_omp_declare_reduction. Parse the combiner
+ expression and optional initializer clause of
+ #pragma omp declare reduction. We store the expression(s) as
+ either 3, 6 or 7 special statements inside of the artificial function's
+ body. The first two statements are DECL_EXPRs for the artificial
+ OMP_OUT resp. OMP_IN variables, followed by a statement with the combiner
+ expression that uses those variables.
+ If there was any INITIALIZER clause, this is followed by further statements,
+ the fourth and fifth statements are DECL_EXPRs for the artificial
+ OMP_PRIV resp. OMP_ORIG variables. If the INITIALIZER clause wasn't the
+ constructor variant (first token after open paren is not omp_priv),
+ then the sixth statement is a statement with the function call expression
+ that uses the OMP_PRIV and optionally OMP_ORIG variable.
+ Otherwise, the sixth statement is whatever statement cp_finish_decl emits
+ to initialize the OMP_PRIV artificial variable and there is seventh
+ statement, a DECL_EXPR of the OMP_PRIV statement again. */
+
+static bool
+cp_parser_omp_declare_reduction_exprs (tree fndecl, cp_parser *parser)
+{
+ tree type = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (fndecl)));
+ gcc_assert (TREE_CODE (type) == REFERENCE_TYPE);
+ type = TREE_TYPE (type);
+ tree omp_out = build_lang_decl (VAR_DECL, get_identifier ("omp_out"), type);
+ DECL_ARTIFICIAL (omp_out) = 1;
+ pushdecl (omp_out);
+ add_decl_expr (omp_out);
+ tree omp_in = build_lang_decl (VAR_DECL, get_identifier ("omp_in"), type);
+ DECL_ARTIFICIAL (omp_in) = 1;
+ pushdecl (omp_in);
+ add_decl_expr (omp_in);
+ tree combiner;
+ tree omp_priv = NULL_TREE, omp_orig = NULL_TREE, initializer = NULL_TREE;
+
+ keep_next_level (true);
+ tree block = begin_omp_structured_block ();
+ combiner = cp_parser_expression (parser, false, NULL);
+ finish_expr_stmt (combiner);
+ block = finish_omp_structured_block (block);
+ add_stmt (block);
+
+ if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ return false;
+
+ const char *p = "";
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+ {
+ tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+ p = IDENTIFIER_POINTER (id);
+ }
+
+ if (strcmp (p, "initializer") == 0)
+ {
+ cp_lexer_consume_token (parser->lexer);
+ if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ return false;
+
+ p = "";
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+ {
+ tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+ p = IDENTIFIER_POINTER (id);
+ }
+
+ omp_priv = build_lang_decl (VAR_DECL, get_identifier ("omp_priv"), type);
+ DECL_ARTIFICIAL (omp_priv) = 1;
+ pushdecl (omp_priv);
+ add_decl_expr (omp_priv);
+ omp_orig = build_lang_decl (VAR_DECL, get_identifier ("omp_orig"), type);
+ DECL_ARTIFICIAL (omp_orig) = 1;
+ pushdecl (omp_orig);
+ add_decl_expr (omp_orig);
+
+ keep_next_level (true);
+ block = begin_omp_structured_block ();
+
+ bool ctor = false;
+ if (strcmp (p, "omp_priv") == 0)
+ {
+ bool is_direct_init, is_non_constant_init;
+ ctor = true;
+ cp_lexer_consume_token (parser->lexer);
+ /* Reject initializer (omp_priv) and initializer (omp_priv ()). */
+ if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN)
+ || (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)
+ && cp_lexer_peek_nth_token (parser->lexer, 2)->type
+ == CPP_CLOSE_PAREN
+ && cp_lexer_peek_nth_token (parser->lexer, 3)->type
+ == CPP_CLOSE_PAREN))
+ {
+ finish_omp_structured_block (block);
+ error ("invalid initializer clause");
+ return false;
+ }
+ initializer = cp_parser_initializer (parser, &is_direct_init,
+ &is_non_constant_init);
+ cp_finish_decl (omp_priv, initializer, !is_non_constant_init,
+ NULL_TREE, LOOKUP_ONLYCONVERTING);
+ }
+ else
+ {
+ cp_parser_parse_tentatively (parser);
+ tree fn_name = cp_parser_id_expression (parser, /*template_p=*/false,
+ /*check_dependency_p=*/true,
+ /*template_p=*/NULL,
+ /*declarator_p=*/false,
+ /*optional_p=*/false);
+ vec<tree, va_gc> *args;
+ if (fn_name == error_mark_node
+ || cp_parser_error_occurred (parser)
+ || !cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)
+ || ((args = cp_parser_parenthesized_expression_list
+ (parser, non_attr, /*cast_p=*/false,
+ /*allow_expansion_p=*/true,
+ /*non_constant_p=*/NULL)),
+ cp_parser_error_occurred (parser)))
+ {
+ finish_omp_structured_block (block);
+ cp_parser_abort_tentative_parse (parser);
+ cp_parser_error (parser, "expected id-expression (arguments)");
+ return false;
+ }
+ unsigned int i;
+ tree arg;
+ FOR_EACH_VEC_SAFE_ELT (args, i, arg)
+ if (arg == omp_priv
+ || (TREE_CODE (arg) == ADDR_EXPR
+ && TREE_OPERAND (arg, 0) == omp_priv))
+ break;
+ cp_parser_abort_tentative_parse (parser);
+ if (arg == NULL_TREE)
+ error ("one of the initializer call arguments should be %<omp_priv%>"
+ " or %<&omp_priv%>");
+ initializer = cp_parser_postfix_expression (parser, false, false, false,
+ false, NULL);
+ finish_expr_stmt (initializer);
+ }
+
+ block = finish_omp_structured_block (block);
+ cp_walk_tree (&block, cp_remove_omp_priv_cleanup_stmt, omp_priv, NULL);
+ finish_expr_stmt (block);
+
+ if (ctor)
+ add_decl_expr (omp_orig);
+
+ if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ return false;
+ }
+
+ if (!cp_lexer_next_token_is (parser->lexer, CPP_PRAGMA_EOL))
+ cp_parser_required_error (parser, RT_PRAGMA_EOL, /*keyword=*/false);
+
+ return true;
+}
+
+/* OpenMP 4.0
+ #pragma omp declare reduction (reduction-id : typename-list : expression) \
+ initializer-clause[opt] new-line
+
+ initializer-clause:
+ initializer (omp_priv initializer)
+ initializer (function-name (argument-list)) */
+
+static void
+cp_parser_omp_declare_reduction (cp_parser *parser, cp_token *pragma_tok,
+ enum pragma_context)
+{
+ vec<tree> types = vNULL;
+ enum tree_code reduc_code = ERROR_MARK;
+ tree reduc_id = NULL_TREE, orig_reduc_id = NULL_TREE, type;
+ unsigned int i;
+ cp_token *first_token;
+ cp_token_cache *cp;
+ int errs;
+
+ if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ goto fail;
+
+ switch (cp_lexer_peek_token (parser->lexer)->type)
+ {
+ case CPP_PLUS:
+ reduc_code = PLUS_EXPR;
+ break;
+ case CPP_MULT:
+ reduc_code = MULT_EXPR;
+ break;
+ case CPP_MINUS:
+ reduc_code = MINUS_EXPR;
+ break;
+ case CPP_AND:
+ reduc_code = BIT_AND_EXPR;
+ break;
+ case CPP_XOR:
+ reduc_code = BIT_XOR_EXPR;
+ break;
+ case CPP_OR:
+ reduc_code = BIT_IOR_EXPR;
+ break;
+ case CPP_AND_AND:
+ reduc_code = TRUTH_ANDIF_EXPR;
+ break;
+ case CPP_OR_OR:
+ reduc_code = TRUTH_ORIF_EXPR;
+ break;
+ case CPP_NAME:
+ reduc_id = orig_reduc_id = cp_parser_identifier (parser);
+ break;
+ default:
+ cp_parser_error (parser, "expected %<+%>, %<*%>, %<-%>, %<&%>, %<^%>, "
+ "%<|%>, %<&&%>, %<||%> or identifier");
+ goto fail;
+ }
+
+ if (reduc_code != ERROR_MARK)
+ cp_lexer_consume_token (parser->lexer);
+
+ reduc_id = omp_reduction_id (reduc_code, reduc_id, NULL_TREE);
+ if (reduc_id == error_mark_node)
+ goto fail;
+
+ if (!cp_parser_require (parser, CPP_COLON, RT_COLON))
+ goto fail;
+
+ /* Types may not be defined in declare reduction type list. */
+ const char *saved_message;
+ saved_message = parser->type_definition_forbidden_message;
+ parser->type_definition_forbidden_message
+ = G_("types may not be defined in declare reduction type list");
+ bool saved_colon_corrects_to_scope_p;
+ saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p;
+ parser->colon_corrects_to_scope_p = false;
+ bool saved_colon_doesnt_start_class_def_p;
+ saved_colon_doesnt_start_class_def_p
+ = parser->colon_doesnt_start_class_def_p;
+ parser->colon_doesnt_start_class_def_p = true;
+
+ while (true)
+ {
+ location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+ type = cp_parser_type_id (parser);
+ if (type == error_mark_node)
+ ;
+ else if (ARITHMETIC_TYPE_P (type)
+ && (orig_reduc_id == NULL_TREE
+ || (TREE_CODE (type) != COMPLEX_TYPE
+ && (strcmp (IDENTIFIER_POINTER (orig_reduc_id),
+ "min") == 0
+ || strcmp (IDENTIFIER_POINTER (orig_reduc_id),
+ "max") == 0))))
+ error_at (loc, "predeclared arithmetic type %qT in "
+ "%<#pragma omp declare reduction%>", type);
+ else if (TREE_CODE (type) == FUNCTION_TYPE
+ || TREE_CODE (type) == METHOD_TYPE
+ || TREE_CODE (type) == ARRAY_TYPE)
+ error_at (loc, "function or array type %qT in "
+ "%<#pragma omp declare reduction%>", type);
+ else if (TREE_CODE (type) == REFERENCE_TYPE)
+ error_at (loc, "reference type %qT in "
+ "%<#pragma omp declare reduction%>", type);
+ else if (TYPE_QUALS_NO_ADDR_SPACE (type))
+ error_at (loc, "const, volatile or __restrict qualified type %qT in "
+ "%<#pragma omp declare reduction%>", type);
+ else
+ types.safe_push (type);
+
+ if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+ cp_lexer_consume_token (parser->lexer);
+ else
+ break;
+ }
+
+ /* Restore the saved message. */
+ parser->type_definition_forbidden_message = saved_message;
+ parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p;
+ parser->colon_doesnt_start_class_def_p
+ = saved_colon_doesnt_start_class_def_p;
+
+ if (!cp_parser_require (parser, CPP_COLON, RT_COLON)
+ || types.is_empty ())
+ {
+ fail:
+ cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+ types.release ();
+ return;
+ }
+
+ first_token = cp_lexer_peek_token (parser->lexer);
+ cp = NULL;
+ errs = errorcount;
+ FOR_EACH_VEC_ELT (types, i, type)
+ {
+ tree fntype
+ = build_function_type_list (void_type_node,
+ cp_build_reference_type (type, false),
+ NULL_TREE);
+ tree this_reduc_id = reduc_id;
+ if (!dependent_type_p (type))
+ this_reduc_id = omp_reduction_id (ERROR_MARK, reduc_id, type);
+ tree fndecl = build_lang_decl (FUNCTION_DECL, this_reduc_id, fntype);
+ DECL_SOURCE_LOCATION (fndecl) = pragma_tok->location;
+ DECL_ARTIFICIAL (fndecl) = 1;
+ DECL_EXTERNAL (fndecl) = 1;
+ DECL_DECLARED_INLINE_P (fndecl) = 1;
+ DECL_IGNORED_P (fndecl) = 1;
+ DECL_OMP_DECLARE_REDUCTION_P (fndecl) = 1;
+ DECL_ATTRIBUTES (fndecl)
+ = tree_cons (get_identifier ("gnu_inline"), NULL_TREE,
+ DECL_ATTRIBUTES (fndecl));
+ if (processing_template_decl)
+ fndecl = push_template_decl (fndecl);
+ bool block_scope = false;
+ tree block = NULL_TREE;
+ if (current_function_decl)
+ {
+ block_scope = true;
+ DECL_CONTEXT (fndecl) = global_namespace;
+ if (!processing_template_decl)
+ pushdecl (fndecl);
+ }
+ else if (current_class_type)
+ {
+ if (cp == NULL)
+ {
+ while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL)
+ && cp_lexer_next_token_is_not (parser->lexer, CPP_EOF))
+ cp_lexer_consume_token (parser->lexer);
+ if (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL))
+ goto fail;
+ cp = cp_token_cache_new (first_token,
+ cp_lexer_peek_nth_token (parser->lexer,
+ 2));
+ }
+ DECL_STATIC_FUNCTION_P (fndecl) = 1;
+ finish_member_declaration (fndecl);
+ DECL_PENDING_INLINE_INFO (fndecl) = cp;
+ DECL_PENDING_INLINE_P (fndecl) = 1;
+ vec_safe_push (unparsed_funs_with_definitions, fndecl);
+ continue;
+ }
+ else
+ {
+ DECL_CONTEXT (fndecl) = current_namespace;
+ pushdecl (fndecl);
+ }
+ if (!block_scope)
+ start_preparsed_function (fndecl, NULL_TREE, SF_PRE_PARSED);
+ else
+ block = begin_omp_structured_block ();
+ if (cp)
+ {
+ cp_parser_push_lexer_for_tokens (parser, cp);
+ parser->lexer->in_pragma = true;
+ }
+ if (!cp_parser_omp_declare_reduction_exprs (fndecl, parser))
+ {
+ if (!block_scope)
+ finish_function (0);
+ else
+ DECL_CONTEXT (fndecl) = current_function_decl;
+ if (cp)
+ cp_parser_pop_lexer (parser);
+ goto fail;
+ }
+ if (cp)
+ cp_parser_pop_lexer (parser);
+ if (!block_scope)
+ finish_function (0);
+ else
+ {
+ DECL_CONTEXT (fndecl) = current_function_decl;
+ block = finish_omp_structured_block (block);
+ if (TREE_CODE (block) == BIND_EXPR)
+ DECL_SAVED_TREE (fndecl) = BIND_EXPR_BODY (block);
+ else if (TREE_CODE (block) == STATEMENT_LIST)
+ DECL_SAVED_TREE (fndecl) = block;
+ if (processing_template_decl)
+ add_decl_expr (fndecl);
+ }
+ cp_check_omp_declare_reduction (fndecl);
+ if (cp == NULL && types.length () > 1)
+ cp = cp_token_cache_new (first_token,
+ cp_lexer_peek_nth_token (parser->lexer, 2));
+ if (errs != errorcount)
+ break;
+ }
+
+ cp_parser_require_pragma_eol (parser, pragma_tok);
+ types.release ();
+}
+
+/* OpenMP 4.0
+ #pragma omp declare simd declare-simd-clauses[optseq] new-line
+ #pragma omp declare reduction (reduction-id : typename-list : expression) \
+ initializer-clause[opt] new-line
+ #pragma omp declare target new-line */
+
+static void
+cp_parser_omp_declare (cp_parser *parser, cp_token *pragma_tok,
+ enum pragma_context context)
+{
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+ {
+ tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+ const char *p = IDENTIFIER_POINTER (id);
+
+ if (strcmp (p, "simd") == 0)
+ {
+ cp_lexer_consume_token (parser->lexer);
+ cp_parser_omp_declare_simd (parser, pragma_tok,
+ context);
+ return;
+ }
+ cp_ensure_no_omp_declare_simd (parser);
+ if (strcmp (p, "reduction") == 0)
+ {
+ cp_lexer_consume_token (parser->lexer);
+ cp_parser_omp_declare_reduction (parser, pragma_tok,
+ context);
+ return;
+ }
+ if (!flag_openmp) /* flag_openmp_simd */
+ {
+ cp_parser_require_pragma_eol (parser, pragma_tok);
+ return;
+ }
+ if (strcmp (p, "target") == 0)
+ {
+ cp_lexer_consume_token (parser->lexer);
+ cp_parser_omp_declare_target (parser, pragma_tok);
+ return;
+ }
+ }
+ cp_parser_error (parser, "expected %<simd%> or %<reduction%> "
+ "or %<target%>");
+ cp_parser_require_pragma_eol (parser, pragma_tok);
+}
+
/* Main entry point to OpenMP statement pragmas. */
static void
cp_parser_omp_construct (cp_parser *parser, cp_token *pragma_tok)
{
tree stmt;
+ char p_name[sizeof "#pragma omp teams distribute parallel for simd"];
+ omp_clause_mask mask (0);
switch (pragma_tok->pragma_kind)
{
@@ -28359,8 +30490,13 @@ cp_parser_omp_construct (cp_parser *parser, cp_token *pragma_tok)
case PRAGMA_OMP_CRITICAL:
stmt = cp_parser_omp_critical (parser, pragma_tok);
break;
+ case PRAGMA_OMP_DISTRIBUTE:
+ strcpy (p_name, "#pragma omp");
+ stmt = cp_parser_omp_distribute (parser, pragma_tok, p_name, mask, NULL);
+ break;
case PRAGMA_OMP_FOR:
- stmt = cp_parser_omp_for (parser, pragma_tok);
+ strcpy (p_name, "#pragma omp");
+ stmt = cp_parser_omp_for (parser, pragma_tok, p_name, mask, NULL);
break;
case PRAGMA_OMP_MASTER:
stmt = cp_parser_omp_master (parser, pragma_tok);
@@ -28369,10 +30505,16 @@ cp_parser_omp_construct (cp_parser *parser, cp_token *pragma_tok)
stmt = cp_parser_omp_ordered (parser, pragma_tok);
break;
case PRAGMA_OMP_PARALLEL:
- stmt = cp_parser_omp_parallel (parser, pragma_tok);
+ strcpy (p_name, "#pragma omp");
+ stmt = cp_parser_omp_parallel (parser, pragma_tok, p_name, mask, NULL);
break;
case PRAGMA_OMP_SECTIONS:
- stmt = cp_parser_omp_sections (parser, pragma_tok);
+ strcpy (p_name, "#pragma omp");
+ stmt = cp_parser_omp_sections (parser, pragma_tok, p_name, mask, NULL);
+ break;
+ case PRAGMA_OMP_SIMD:
+ strcpy (p_name, "#pragma omp");
+ stmt = cp_parser_omp_simd (parser, pragma_tok, p_name, mask, NULL);
break;
case PRAGMA_OMP_SINGLE:
stmt = cp_parser_omp_single (parser, pragma_tok);
@@ -28380,6 +30522,13 @@ cp_parser_omp_construct (cp_parser *parser, cp_token *pragma_tok)
case PRAGMA_OMP_TASK:
stmt = cp_parser_omp_task (parser, pragma_tok);
break;
+ case PRAGMA_OMP_TASKGROUP:
+ stmt = cp_parser_omp_taskgroup (parser, pragma_tok);
+ break;
+ case PRAGMA_OMP_TEAMS:
+ strcpy (p_name, "#pragma omp");
+ stmt = cp_parser_omp_teams (parser, pragma_tok, p_name, mask, NULL);
+ break;
default:
gcc_unreachable ();
}
@@ -28736,6 +30885,8 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context)
parser->lexer->in_pragma = true;
id = pragma_tok->pragma_kind;
+ if (id != PRAGMA_OMP_DECLARE_REDUCTION)
+ cp_ensure_no_omp_declare_simd (parser);
switch (id)
{
case PRAGMA_GCC_PCH_PREPROCESS:
@@ -28805,30 +30956,93 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context)
}
break;
+ case PRAGMA_OMP_CANCEL:
+ switch (context)
+ {
+ case pragma_compound:
+ cp_parser_omp_cancel (parser, pragma_tok);
+ return false;
+ case pragma_stmt:
+ error_at (pragma_tok->location,
+ "%<#pragma omp cancel%> may only be "
+ "used in compound statements");
+ break;
+ default:
+ goto bad_stmt;
+ }
+ break;
+
+ case PRAGMA_OMP_CANCELLATION_POINT:
+ switch (context)
+ {
+ case pragma_compound:
+ cp_parser_omp_cancellation_point (parser, pragma_tok);
+ return false;
+ case pragma_stmt:
+ error_at (pragma_tok->location,
+ "%<#pragma omp cancellation point%> may only be "
+ "used in compound statements");
+ break;
+ default:
+ goto bad_stmt;
+ }
+ break;
+
case PRAGMA_OMP_THREADPRIVATE:
cp_parser_omp_threadprivate (parser, pragma_tok);
return false;
+ case PRAGMA_OMP_DECLARE_REDUCTION:
+ cp_parser_omp_declare (parser, pragma_tok, context);
+ return false;
+
case PRAGMA_OMP_ATOMIC:
case PRAGMA_OMP_CRITICAL:
+ case PRAGMA_OMP_DISTRIBUTE:
case PRAGMA_OMP_FOR:
case PRAGMA_OMP_MASTER:
case PRAGMA_OMP_ORDERED:
case PRAGMA_OMP_PARALLEL:
case PRAGMA_OMP_SECTIONS:
+ case PRAGMA_OMP_SIMD:
case PRAGMA_OMP_SINGLE:
case PRAGMA_OMP_TASK:
- if (context == pragma_external)
+ case PRAGMA_OMP_TASKGROUP:
+ case PRAGMA_OMP_TEAMS:
+ if (context != pragma_stmt && context != pragma_compound)
goto bad_stmt;
cp_parser_omp_construct (parser, pragma_tok);
return true;
+ case PRAGMA_OMP_TARGET:
+ return cp_parser_omp_target (parser, pragma_tok, context);
+
+ case PRAGMA_OMP_END_DECLARE_TARGET:
+ cp_parser_omp_end_declare_target (parser, pragma_tok);
+ return false;
+
case PRAGMA_OMP_SECTION:
error_at (pragma_tok->location,
"%<#pragma omp section%> may only be used in "
"%<#pragma omp sections%> construct");
break;
+ case PRAGMA_IVDEP:
+ {
+ cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+ cp_token *tok;
+ tok = cp_lexer_peek_token (the_parser->lexer);
+ if (tok->type != CPP_KEYWORD
+ || (tok->keyword != RID_FOR && tok->keyword != RID_WHILE
+ && tok->keyword != RID_DO))
+ {
+ cp_parser_error (parser, "for, while or do statement expected");
+ return false;
+ }
+ cp_parser_iteration_statement (parser, true);
+ return true;
+ }
+
default:
gcc_assert (id >= PRAGMA_FIRST_EXTERNAL);
c_invoke_pragma_handler (id);
@@ -28897,11 +31111,12 @@ c_parse_file (void)
/* Create an identifier for a generic parameter type (a synthesized
template parameter implied by `auto' or a concept identifier). */
+static GTY(()) int generic_parm_count;
static tree
-make_generic_type_name (int i)
+make_generic_type_name ()
{
char buf[32];
- sprintf (buf, "__GenT%d", i);
+ sprintf (buf, "<auto%d>", ++generic_parm_count);
return get_identifier (buf);
}
@@ -28915,14 +31130,14 @@ tree_type_is_auto_or_concept (const_tree t)
return TREE_TYPE (t) && is_auto_or_concept (TREE_TYPE (t));
}
-/* Add COUNT implicit template parameters gleaned from the generic
- type parameters in PARAMETERS to the CURRENT_TEMPLATE_PARMS
- (creating a new template parameter list if necessary). Returns
- PARAMETERS suitably rewritten to reference the newly created types
- or ERROR_MARK_NODE on failure. */
+/* Add EXPECT_COUNT implicit template parameters gleaned from the generic
+ type parameters in PARAMETERS to the CURRENT_TEMPLATE_PARMS (creating a new
+ template parameter list if necessary). Returns PARAMETERS suitably rewritten
+ to reference the newly created types or ERROR_MARK_NODE on failure. */
tree
-add_implicit_template_parms (cp_parser *parser, size_t count, tree parameters)
+add_implicit_template_parms (cp_parser *parser, size_t expect_count,
+ tree parameters)
{
gcc_assert (current_binding_level->kind == sk_function_parms);
@@ -28931,7 +31146,7 @@ add_implicit_template_parms (cp_parser *parser, size_t count, tree parameters)
bool become_template =
fn_parms_scope->level_chain->kind != sk_template_parms;
- size_t synth_idx = 0;
+ size_t synth_count = 0;
/* Roll back a scope level and either introduce a new template parameter list
or update an existing one. The function scope is added back after template
@@ -28973,7 +31188,7 @@ add_implicit_template_parms (cp_parser *parser, size_t count, tree parameters)
++processing_template_parmlist;
}
- for (tree p = parameters; p && synth_idx < count; p = TREE_CHAIN (p))
+ for (tree p = parameters; p && synth_count < expect_count; p = TREE_CHAIN (p))
{
tree generic_type_ptr
= find_type_usage (TREE_VALUE (p), tree_type_is_auto_or_concept);
@@ -28981,7 +31196,9 @@ add_implicit_template_parms (cp_parser *parser, size_t count, tree parameters)
if (!generic_type_ptr)
continue;
- tree synth_id = make_generic_type_name (synth_idx++);
+ ++synth_count;
+
+ tree synth_id = make_generic_type_name ();
tree synth_tmpl_parm = finish_template_type_parm (class_type_node,
synth_id);
tparms = process_template_parm (tparms, DECL_SOURCE_LOCATION (TREE_VALUE
@@ -29004,7 +31221,7 @@ add_implicit_template_parms (cp_parser *parser, size_t count, tree parameters)
cur_type = new_type;
}
- gcc_assert (synth_idx == count);
+ gcc_assert (synth_count == expect_count);
push_binding_level (fn_parms_scope);
@@ -29026,6 +31243,14 @@ finish_fully_implicit_template (cp_parser *parser, tree member_decl_opt)
{
gcc_assert (parser->fully_implicit_function_template_p);
+ if (member_decl_opt && member_decl_opt != error_mark_node
+ && DECL_VIRTUAL_P (member_decl_opt))
+ {
+ error_at (DECL_SOURCE_LOCATION (member_decl_opt),
+ "implicit templates may not be %<virtual%>");
+ DECL_VIRTUAL_P (member_decl_opt) = false;
+ }
+
pop_deferring_access_checks ();
if (member_decl_opt)
member_decl_opt = finish_member_template_decl (member_decl_opt);
diff --git a/gcc/cp/parser.h b/gcc/cp/parser.h
index ffdddaf4a08..75f327b1d8b 100644
--- a/gcc/cp/parser.h
+++ b/gcc/cp/parser.h
@@ -196,6 +196,14 @@ typedef struct GTY (()) cp_parser_context {
} cp_parser_context;
+/* Control structure for #pragma omp declare simd parsing. */
+struct cp_omp_declare_simd_data {
+ bool error_seen; /* Set if error has been reported. */
+ bool fndecl_seen; /* Set if one fn decl/definition has been seen already. */
+ vec<cp_token_cache_ptr> tokens;
+};
+
+
/* The cp_parser structure represents the C++ parser. */
typedef struct GTY(()) cp_parser {
@@ -324,6 +332,12 @@ typedef struct GTY(()) cp_parser {
/* TRUE if we can auto-correct a colon to a scope operator. */
bool colon_corrects_to_scope_p;
+ /* TRUE if : doesn't start a class definition. Should be only used
+ together with type_definition_forbidden_message non-NULL, in
+ contexts where new types may not be defined, and the type list
+ is terminated by colon. */
+ bool colon_doesnt_start_class_def_p;
+
/* If non-NULL, then we are parsing a construct where new type
definitions are not permitted. The string stored here will be
issued as an error message if a type is defined. */
@@ -342,6 +356,10 @@ typedef struct GTY(()) cp_parser {
current declaration. */
unsigned num_template_parameter_lists;
+ /* When parsing #pragma omp declare simd, this is a pointer to a
+ data structure with everything needed for parsing the clauses. */
+ cp_omp_declare_simd_data * GTY((skip)) omp_declare_simd;
+
/* TRUE if the function being declared was made a template due to its
parameter list containing generic type specifiers (`auto' or concept
identifiers) rather than an explicit template parameter list. */
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index e0b71108fcf..8c1553feca2 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -3511,7 +3511,8 @@ check_template_shadow (tree decl)
name inside a class. We check TPFI to avoid duplicate errors for
inline member templates. */
if (decl == olddecl
- || TEMPLATE_PARMS_FOR_INLINE (current_template_parms))
+ || (DECL_TEMPLATE_PARM_P (decl)
+ && TEMPLATE_PARMS_FOR_INLINE (current_template_parms)))
return true;
error ("declaration of %q+#D", decl);
@@ -5611,7 +5612,7 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
TREE_TYPE (TREE_TYPE (addr)))))
{
expr = TREE_OPERAND (addr, 0);
- expr_type = TREE_TYPE (expr);
+ expr_type = TREE_TYPE (probe_type);
}
}
}
@@ -8545,6 +8546,8 @@ can_complete_type_without_circularity (tree type)
return 1;
}
+static tree tsubst_omp_clauses (tree, bool, tree, tsubst_flags_t, tree);
+
/* Apply any attributes which had to be deferred until instantiation
time. DECL_P, ATTRIBUTES and ATTR_FLAGS are as cplus_decl_attributes;
ARGS, COMPLAIN, IN_DECL are as tsubst. */
@@ -8586,14 +8589,29 @@ apply_late_template_attributes (tree *decl_p, tree attributes, int attr_flags,
{
*p = TREE_CHAIN (t);
TREE_CHAIN (t) = NULL_TREE;
+ if (flag_openmp
+ && is_attribute_p ("omp declare simd",
+ get_attribute_name (t))
+ && TREE_VALUE (t))
+ {
+ tree clauses = TREE_VALUE (TREE_VALUE (t));
+ clauses = tsubst_omp_clauses (clauses, true, args,
+ complain, in_decl);
+ c_omp_declare_simd_clauses_to_decls (*decl_p, clauses);
+ clauses = finish_omp_clauses (clauses);
+ tree parms = DECL_ARGUMENTS (*decl_p);
+ clauses
+ = c_omp_declare_simd_clauses_to_numbers (parms, clauses);
+ if (clauses)
+ TREE_VALUE (TREE_VALUE (t)) = clauses;
+ else
+ TREE_VALUE (t) = NULL_TREE;
+ }
/* If the first attribute argument is an identifier, don't
pass it through tsubst. Attributes like mode, format,
cleanup and several target specific attributes expect it
unmodified. */
- if (TREE_VALUE (t)
- && TREE_CODE (TREE_VALUE (t)) == TREE_LIST
- && TREE_VALUE (TREE_VALUE (t))
- && (identifier_p (TREE_VALUE (TREE_VALUE (t)))))
+ else if (attribute_takes_identifier_p (get_attribute_name (t)))
{
tree chain
= tsubst_expr (TREE_CHAIN (TREE_VALUE (t)), args, complain,
@@ -8915,6 +8933,9 @@ instantiate_class_template_1 (tree type)
/* Instantiate members marked with attribute used. */
if (r != error_mark_node && DECL_PRESERVE_P (r))
mark_used (r);
+ if (TREE_CODE (r) == FUNCTION_DECL
+ && DECL_OMP_DECLARE_REDUCTION_P (r))
+ cp_check_omp_declare_reduction (r);
}
else
{
@@ -10383,6 +10404,24 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
DECL_INITIAL (r) = NULL_TREE;
DECL_CONTEXT (r) = ctx;
+ /* OpenMP UDRs have the only argument a reference to the declared
+ type. We want to diagnose if the declared type is a reference,
+ which is invalid, but as references to references are usually
+ quietly merged, diagnose it here. */
+ if (DECL_OMP_DECLARE_REDUCTION_P (t))
+ {
+ tree argtype
+ = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (t))));
+ argtype = tsubst (argtype, args, complain, in_decl);
+ if (TREE_CODE (argtype) == REFERENCE_TYPE)
+ error_at (DECL_SOURCE_LOCATION (t),
+ "reference type %qT in "
+ "%<#pragma omp declare reduction%>", argtype);
+ if (strchr (IDENTIFIER_POINTER (DECL_NAME (t)), '~') == NULL)
+ DECL_NAME (r) = omp_reduction_id (ERROR_MARK, DECL_NAME (t),
+ argtype);
+ }
+
if (member && DECL_CONV_FN_P (r))
/* Type-conversion operator. Reconstruct the name, in
case it's the name of one of the template's parameters. */
@@ -12061,7 +12100,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
gcc_unreachable ();
default:
- sorry ("use of %qs in template", tree_code_name [(int) code]);
+ sorry ("use of %qs in template", get_tree_code_name (code));
return error_mark_node;
}
}
@@ -12434,7 +12473,8 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
return t;
case BASELINK:
- return tsubst_baselink (t, current_class_type, args, complain, in_decl);
+ return tsubst_baselink (t, current_nonlambda_class_type (),
+ args, complain, in_decl);
case TEMPLATE_DECL:
if (DECL_TEMPLATE_TEMPLATE_PARM_P (t))
@@ -12814,8 +12854,8 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
/* Like tsubst_copy, but specifically for OpenMP clauses. */
static tree
-tsubst_omp_clauses (tree clauses, tree args, tsubst_flags_t complain,
- tree in_decl)
+tsubst_omp_clauses (tree clauses, bool declare_simd,
+ tree args, tsubst_flags_t complain, tree in_decl)
{
tree new_clauses = NULL, nc, oc;
@@ -12840,7 +12880,6 @@ tsubst_omp_clauses (tree clauses, tree args, tsubst_flags_t complain,
case OMP_CLAUSE_PRIVATE:
case OMP_CLAUSE_SHARED:
case OMP_CLAUSE_FIRSTPRIVATE:
- case OMP_CLAUSE_REDUCTION:
case OMP_CLAUSE_COPYIN:
case OMP_CLAUSE_COPYPRIVATE:
case OMP_CLAUSE_IF:
@@ -12848,22 +12887,73 @@ tsubst_omp_clauses (tree clauses, tree args, tsubst_flags_t complain,
case OMP_CLAUSE_SCHEDULE:
case OMP_CLAUSE_COLLAPSE:
case OMP_CLAUSE_FINAL:
+ case OMP_CLAUSE_DEPEND:
+ case OMP_CLAUSE_FROM:
+ case OMP_CLAUSE_TO:
+ case OMP_CLAUSE_UNIFORM:
+ case OMP_CLAUSE_MAP:
+ case OMP_CLAUSE_DEVICE:
+ case OMP_CLAUSE_DIST_SCHEDULE:
+ case OMP_CLAUSE_NUM_TEAMS:
+ case OMP_CLAUSE_THREAD_LIMIT:
+ case OMP_CLAUSE_SAFELEN:
+ case OMP_CLAUSE_SIMDLEN:
OMP_CLAUSE_OPERAND (nc, 0)
= tsubst_expr (OMP_CLAUSE_OPERAND (oc, 0), args, complain,
in_decl, /*integral_constant_expression_p=*/false);
break;
+ case OMP_CLAUSE_REDUCTION:
+ if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (oc))
+ {
+ tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (oc);
+ if (TREE_CODE (placeholder) == SCOPE_REF)
+ {
+ tree scope = tsubst (TREE_OPERAND (placeholder, 0), args,
+ complain, in_decl);
+ OMP_CLAUSE_REDUCTION_PLACEHOLDER (nc)
+ = build_qualified_name (NULL_TREE, scope,
+ TREE_OPERAND (placeholder, 1),
+ false);
+ }
+ else
+ gcc_assert (identifier_p (placeholder));
+ }
+ OMP_CLAUSE_OPERAND (nc, 0)
+ = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 0), args, complain,
+ in_decl, /*integral_constant_expression_p=*/false);
+ break;
+ case OMP_CLAUSE_LINEAR:
+ case OMP_CLAUSE_ALIGNED:
+ OMP_CLAUSE_OPERAND (nc, 0)
+ = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 0), args, complain,
+ in_decl, /*integral_constant_expression_p=*/false);
+ OMP_CLAUSE_OPERAND (nc, 1)
+ = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 1), args, complain,
+ in_decl, /*integral_constant_expression_p=*/false);
+ break;
+
case OMP_CLAUSE_NOWAIT:
case OMP_CLAUSE_ORDERED:
case OMP_CLAUSE_DEFAULT:
case OMP_CLAUSE_UNTIED:
case OMP_CLAUSE_MERGEABLE:
+ case OMP_CLAUSE_INBRANCH:
+ case OMP_CLAUSE_NOTINBRANCH:
+ case OMP_CLAUSE_PROC_BIND:
+ case OMP_CLAUSE_FOR:
+ case OMP_CLAUSE_PARALLEL:
+ case OMP_CLAUSE_SECTIONS:
+ case OMP_CLAUSE_TASKGROUP:
break;
default:
gcc_unreachable ();
}
}
- return finish_omp_clauses (nreverse (new_clauses));
+ new_clauses = nreverse (new_clauses);
+ if (!declare_simd)
+ new_clauses = finish_omp_clauses (new_clauses);
+ return new_clauses;
}
/* Like tsubst_copy_and_build, but unshare TREE_LIST nodes. */
@@ -13168,6 +13258,15 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
}
else if (DECL_IMPLICIT_TYPEDEF_P (t))
/* We already did a pushtag. */;
+ else if (TREE_CODE (decl) == FUNCTION_DECL
+ && DECL_OMP_DECLARE_REDUCTION_P (decl)
+ && DECL_FUNCTION_SCOPE_P (pattern_decl))
+ {
+ DECL_CONTEXT (decl) = NULL_TREE;
+ pushdecl (decl);
+ DECL_CONTEXT (decl) = current_function_decl;
+ cp_check_omp_declare_reduction (decl);
+ }
else
{
int const_init = false;
@@ -13219,7 +13318,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
RECUR (FOR_INIT_STMT (t));
finish_for_init_stmt (stmt);
tmp = RECUR (FOR_COND (t));
- finish_for_cond (tmp, stmt);
+ finish_for_cond (tmp, stmt, false);
tmp = RECUR (FOR_EXPR (t));
finish_for_expr (tmp, stmt);
RECUR (FOR_BODY (t));
@@ -13234,7 +13333,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
decl = tsubst (decl, args, complain, in_decl);
maybe_push_decl (decl);
expr = RECUR (RANGE_FOR_EXPR (t));
- stmt = cp_convert_range_for (stmt, decl, expr);
+ stmt = cp_convert_range_for (stmt, decl, expr, RANGE_FOR_IVDEP (t));
RECUR (RANGE_FOR_BODY (t));
finish_for_stmt (stmt);
}
@@ -13243,7 +13342,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
case WHILE_STMT:
stmt = begin_while_stmt ();
tmp = RECUR (WHILE_COND (t));
- finish_while_stmt_cond (tmp, stmt);
+ finish_while_stmt_cond (tmp, stmt, false);
RECUR (WHILE_BODY (t));
finish_while_stmt (stmt);
break;
@@ -13253,7 +13352,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
RECUR (DO_BODY (t));
finish_do_body (stmt);
tmp = RECUR (DO_COND (t));
- finish_do_stmt (tmp, stmt);
+ finish_do_stmt (tmp, stmt, false);
break;
case IF_STMT:
@@ -13439,7 +13538,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
break;
case OMP_PARALLEL:
- tmp = tsubst_omp_clauses (OMP_PARALLEL_CLAUSES (t),
+ tmp = tsubst_omp_clauses (OMP_PARALLEL_CLAUSES (t), false,
args, complain, in_decl);
stmt = begin_omp_parallel ();
RECUR (OMP_PARALLEL_BODY (t));
@@ -13448,7 +13547,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
break;
case OMP_TASK:
- tmp = tsubst_omp_clauses (OMP_TASK_CLAUSES (t),
+ tmp = tsubst_omp_clauses (OMP_TASK_CLAUSES (t), false,
args, complain, in_decl);
stmt = begin_omp_task ();
RECUR (OMP_TASK_BODY (t));
@@ -13456,17 +13555,23 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
break;
case OMP_FOR:
+ case OMP_SIMD:
+ case OMP_DISTRIBUTE:
{
tree clauses, body, pre_body;
- tree declv, initv, condv, incrv;
+ tree declv = NULL_TREE, initv = NULL_TREE, condv = NULL_TREE;
+ tree incrv = NULL_TREE;
int i;
- clauses = tsubst_omp_clauses (OMP_FOR_CLAUSES (t),
+ clauses = tsubst_omp_clauses (OMP_FOR_CLAUSES (t), false,
args, complain, in_decl);
- declv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t)));
- initv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t)));
- condv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t)));
- incrv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t)));
+ if (OMP_FOR_INIT (t) != NULL_TREE)
+ {
+ declv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t)));
+ initv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t)));
+ condv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t)));
+ incrv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t)));
+ }
stmt = begin_omp_structured_block ();
@@ -13474,17 +13579,29 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
RECUR (OMP_FOR_PRE_BODY (t));
pre_body = pop_stmt_list (pre_body);
- for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (t)); i++)
- tsubst_omp_for_iterator (t, i, declv, initv, condv, incrv,
- &clauses, args, complain, in_decl,
- integral_constant_expression_p);
+ if (OMP_FOR_INIT (t) != NULL_TREE)
+ for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (t)); i++)
+ tsubst_omp_for_iterator (t, i, declv, initv, condv, incrv,
+ &clauses, args, complain, in_decl,
+ integral_constant_expression_p);
body = push_stmt_list ();
RECUR (OMP_FOR_BODY (t));
body = pop_stmt_list (body);
- t = finish_omp_for (EXPR_LOCATION (t), declv, initv, condv, incrv,
- body, pre_body, clauses);
+ if (OMP_FOR_INIT (t) != NULL_TREE)
+ t = finish_omp_for (EXPR_LOCATION (t), TREE_CODE (t), declv, initv,
+ condv, incrv, body, pre_body, clauses);
+ else
+ {
+ t = make_node (TREE_CODE (t));
+ TREE_TYPE (t) = void_type_node;
+ OMP_FOR_BODY (t) = body;
+ OMP_FOR_PRE_BODY (t) = pre_body;
+ OMP_FOR_CLAUSES (t) = clauses;
+ SET_EXPR_LOCATION (t, EXPR_LOCATION (t));
+ add_stmt (t);
+ }
add_stmt (finish_omp_structured_block (stmt));
}
@@ -13492,7 +13609,11 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
case OMP_SECTIONS:
case OMP_SINGLE:
- tmp = tsubst_omp_clauses (OMP_CLAUSES (t), args, complain, in_decl);
+ case OMP_TEAMS:
+ case OMP_TARGET_DATA:
+ case OMP_TARGET:
+ tmp = tsubst_omp_clauses (OMP_CLAUSES (t), false,
+ args, complain, in_decl);
stmt = push_stmt_list ();
RECUR (OMP_BODY (t));
stmt = pop_stmt_list (stmt);
@@ -13503,9 +13624,18 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
add_stmt (t);
break;
+ case OMP_TARGET_UPDATE:
+ tmp = tsubst_omp_clauses (OMP_TARGET_UPDATE_CLAUSES (t), false,
+ args, complain, in_decl);
+ t = copy_node (t);
+ OMP_CLAUSES (t) = tmp;
+ add_stmt (t);
+ break;
+
case OMP_SECTION:
case OMP_CRITICAL:
case OMP_MASTER:
+ case OMP_TASKGROUP:
case OMP_ORDERED:
stmt = push_stmt_list ();
RECUR (OMP_BODY (t));
@@ -13531,7 +13661,8 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
lhs = RECUR (TREE_OPERAND (op1, 0));
rhs = RECUR (TREE_OPERAND (op1, 1));
finish_omp_atomic (OMP_ATOMIC, TREE_CODE (op1), lhs, rhs,
- NULL_TREE, NULL_TREE, rhs1);
+ NULL_TREE, NULL_TREE, rhs1,
+ OMP_ATOMIC_SEQ_CST (t));
}
else
{
@@ -13559,6 +13690,8 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
lhs = RECUR (TREE_OPERAND (op11, 0));
rhs = RECUR (TREE_OPERAND (op11, 1));
opcode = TREE_CODE (op11);
+ if (opcode == MODIFY_EXPR)
+ opcode = NOP_EXPR;
}
else
{
@@ -13566,7 +13699,8 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
lhs = RECUR (TREE_OPERAND (op1, 0));
rhs = RECUR (TREE_OPERAND (op1, 1));
}
- finish_omp_atomic (code, opcode, lhs, rhs, v, lhs1, rhs1);
+ finish_omp_atomic (code, opcode, lhs, rhs, v, lhs1, rhs1,
+ OMP_ATOMIC_SEQ_CST (t));
}
break;
@@ -13638,6 +13772,73 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
#undef RETURN
}
+/* Instantiate the special body of the artificial DECL_OMP_DECLARE_REDUCTION
+ function. For description of the body see comment above
+ cp_parser_omp_declare_reduction_exprs. */
+
+static void
+tsubst_omp_udr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
+{
+ if (t == NULL_TREE || t == error_mark_node)
+ return;
+
+ gcc_assert (TREE_CODE (t) == STATEMENT_LIST);
+
+ tree_stmt_iterator tsi;
+ int i;
+ tree stmts[7];
+ memset (stmts, 0, sizeof stmts);
+ for (i = 0, tsi = tsi_start (t);
+ i < 7 && !tsi_end_p (tsi);
+ i++, tsi_next (&tsi))
+ stmts[i] = tsi_stmt (tsi);
+ gcc_assert (tsi_end_p (tsi));
+
+ if (i >= 3)
+ {
+ gcc_assert (TREE_CODE (stmts[0]) == DECL_EXPR
+ && TREE_CODE (stmts[1]) == DECL_EXPR);
+ tree omp_out = tsubst (DECL_EXPR_DECL (stmts[0]),
+ args, complain, in_decl);
+ tree omp_in = tsubst (DECL_EXPR_DECL (stmts[1]),
+ args, complain, in_decl);
+ DECL_CONTEXT (omp_out) = current_function_decl;
+ DECL_CONTEXT (omp_in) = current_function_decl;
+ keep_next_level (true);
+ tree block = begin_omp_structured_block ();
+ tsubst_expr (stmts[2], args, complain, in_decl, false);
+ block = finish_omp_structured_block (block);
+ block = maybe_cleanup_point_expr_void (block);
+ add_decl_expr (omp_out);
+ if (TREE_NO_WARNING (DECL_EXPR_DECL (stmts[0])))
+ TREE_NO_WARNING (omp_out) = 1;
+ add_decl_expr (omp_in);
+ finish_expr_stmt (block);
+ }
+ if (i >= 6)
+ {
+ gcc_assert (TREE_CODE (stmts[3]) == DECL_EXPR
+ && TREE_CODE (stmts[4]) == DECL_EXPR);
+ tree omp_priv = tsubst (DECL_EXPR_DECL (stmts[3]),
+ args, complain, in_decl);
+ tree omp_orig = tsubst (DECL_EXPR_DECL (stmts[4]),
+ args, complain, in_decl);
+ DECL_CONTEXT (omp_priv) = current_function_decl;
+ DECL_CONTEXT (omp_orig) = current_function_decl;
+ keep_next_level (true);
+ tree block = begin_omp_structured_block ();
+ tsubst_expr (stmts[5], args, complain, in_decl, false);
+ block = finish_omp_structured_block (block);
+ block = maybe_cleanup_point_expr_void (block);
+ cp_walk_tree (&block, cp_remove_omp_priv_cleanup_stmt, omp_priv, NULL);
+ add_decl_expr (omp_priv);
+ add_decl_expr (omp_orig);
+ finish_expr_stmt (block);
+ if (i == 7)
+ add_decl_expr (omp_orig);
+ }
+}
+
/* T is a postfix-expression that is not being used in a function
call. Return the substituted version of T. */
@@ -16804,6 +17005,72 @@ unify_pack_expansion (tree tparms, tree targs, tree packed_parms,
return unify_success (explain_p);
}
+/* Handle unification of the domain of an array. PARM_DOM and ARG_DOM are
+ INTEGER_TYPEs representing the TYPE_DOMAIN of ARRAY_TYPEs. The other
+ parameters and return value are as for unify. */
+
+static int
+unify_array_domain (tree tparms, tree targs,
+ tree parm_dom, tree arg_dom,
+ bool explain_p)
+{
+ tree parm_max;
+ tree arg_max;
+ bool parm_cst;
+ bool arg_cst;
+
+ /* Our representation of array types uses "N - 1" as the
+ TYPE_MAX_VALUE for an array with "N" elements, if "N" is
+ not an integer constant. We cannot unify arbitrarily
+ complex expressions, so we eliminate the MINUS_EXPRs
+ here. */
+ parm_max = TYPE_MAX_VALUE (parm_dom);
+ parm_cst = TREE_CODE (parm_max) == INTEGER_CST;
+ if (!parm_cst)
+ {
+ gcc_assert (TREE_CODE (parm_max) == MINUS_EXPR);
+ parm_max = TREE_OPERAND (parm_max, 0);
+ }
+ arg_max = TYPE_MAX_VALUE (arg_dom);
+ arg_cst = TREE_CODE (arg_max) == INTEGER_CST;
+ if (!arg_cst)
+ {
+ /* The ARG_MAX may not be a simple MINUS_EXPR, if we are
+ trying to unify the type of a variable with the type
+ of a template parameter. For example:
+
+ template <unsigned int N>
+ void f (char (&) [N]);
+ int g();
+ void h(int i) {
+ char a[g(i)];
+ f(a);
+ }
+
+ Here, the type of the ARG will be "int [g(i)]", and
+ may be a SAVE_EXPR, etc. */
+ if (TREE_CODE (arg_max) != MINUS_EXPR)
+ return unify_vla_arg (explain_p, arg_dom);
+ arg_max = TREE_OPERAND (arg_max, 0);
+ }
+
+ /* If only one of the bounds used a MINUS_EXPR, compensate
+ by adding one to the other bound. */
+ if (parm_cst && !arg_cst)
+ parm_max = fold_build2_loc (input_location, PLUS_EXPR,
+ integer_type_node,
+ parm_max,
+ integer_one_node);
+ else if (arg_cst && !parm_cst)
+ arg_max = fold_build2_loc (input_location, PLUS_EXPR,
+ integer_type_node,
+ arg_max,
+ integer_one_node);
+
+ return unify (tparms, targs, parm_max, arg_max,
+ UNIFY_ALLOW_INTEGER, explain_p);
+}
+
/* Deduce the value of template parameters. TPARMS is the (innermost)
set of template parameters to a template. TARGS is the bindings
for those template parameters, as determined thus far; TARGS may
@@ -16889,13 +17156,17 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
&& flag_deduce_init_list)
parm = listify (parm);
- if (!is_std_init_list (parm))
+ if (!is_std_init_list (parm)
+ && TREE_CODE (parm) != ARRAY_TYPE)
/* We can only deduce from an initializer list argument if the
- parameter is std::initializer_list; otherwise this is a
- non-deduced context. */
+ parameter is std::initializer_list or an array; otherwise this
+ is a non-deduced context. */
return unify_success (explain_p);
- elttype = TREE_VEC_ELT (CLASSTYPE_TI_ARGS (parm), 0);
+ if (TREE_CODE (parm) == ARRAY_TYPE)
+ elttype = TREE_TYPE (parm);
+ else
+ elttype = TREE_VEC_ELT (CLASSTYPE_TI_ARGS (parm), 0);
FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (arg), i, elt)
{
@@ -16918,6 +17189,15 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
explain_p);
}
+ if (TREE_CODE (parm) == ARRAY_TYPE)
+ {
+ /* Also deduce from the length of the initializer list. */
+ tree max = size_int (CONSTRUCTOR_NELTS (arg));
+ tree idx = compute_array_index_type (NULL_TREE, max, tf_none);
+ return unify_array_domain (tparms, targs, TYPE_DOMAIN (parm),
+ idx, explain_p);
+ }
+
/* If the std::initializer_list<T> deduction worked, replace the
deduced A with std::initializer_list<A>. */
if (orig_parm != parm)
@@ -17291,63 +17571,8 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
RECUR_AND_CHECK_FAILURE (tparms, targs, TREE_TYPE (parm), TREE_TYPE (arg),
strict & UNIFY_ALLOW_MORE_CV_QUAL, explain_p);
if (TYPE_DOMAIN (parm) != NULL_TREE)
- {
- tree parm_max;
- tree arg_max;
- bool parm_cst;
- bool arg_cst;
-
- /* Our representation of array types uses "N - 1" as the
- TYPE_MAX_VALUE for an array with "N" elements, if "N" is
- not an integer constant. We cannot unify arbitrarily
- complex expressions, so we eliminate the MINUS_EXPRs
- here. */
- parm_max = TYPE_MAX_VALUE (TYPE_DOMAIN (parm));
- parm_cst = TREE_CODE (parm_max) == INTEGER_CST;
- if (!parm_cst)
- {
- gcc_assert (TREE_CODE (parm_max) == MINUS_EXPR);
- parm_max = TREE_OPERAND (parm_max, 0);
- }
- arg_max = TYPE_MAX_VALUE (TYPE_DOMAIN (arg));
- arg_cst = TREE_CODE (arg_max) == INTEGER_CST;
- if (!arg_cst)
- {
- /* The ARG_MAX may not be a simple MINUS_EXPR, if we are
- trying to unify the type of a variable with the type
- of a template parameter. For example:
-
- template <unsigned int N>
- void f (char (&) [N]);
- int g();
- void h(int i) {
- char a[g(i)];
- f(a);
- }
-
- Here, the type of the ARG will be "int [g(i)]", and
- may be a SAVE_EXPR, etc. */
- if (TREE_CODE (arg_max) != MINUS_EXPR)
- return unify_vla_arg (explain_p, arg);
- arg_max = TREE_OPERAND (arg_max, 0);
- }
-
- /* If only one of the bounds used a MINUS_EXPR, compensate
- by adding one to the other bound. */
- if (parm_cst && !arg_cst)
- parm_max = fold_build2_loc (input_location, PLUS_EXPR,
- integer_type_node,
- parm_max,
- integer_one_node);
- else if (arg_cst && !parm_cst)
- arg_max = fold_build2_loc (input_location, PLUS_EXPR,
- integer_type_node,
- arg_max,
- integer_one_node);
-
- RECUR_AND_CHECK_FAILURE (tparms, targs, parm_max, arg_max,
- UNIFY_ALLOW_INTEGER, explain_p);
- }
+ return unify_array_domain (tparms, targs, TYPE_DOMAIN (parm),
+ TYPE_DOMAIN (arg), explain_p);
return unify_success (explain_p);
case REAL_TYPE:
@@ -19339,6 +19564,7 @@ instantiate_decl (tree d, int defer_ok,
tree subst_decl;
tree tmpl_parm;
tree spec_parm;
+ tree block = NULL_TREE;
/* Save away the current list, in case we are instantiating one
template from within the body of another. */
@@ -19348,7 +19574,11 @@ instantiate_decl (tree d, int defer_ok,
local_specializations = pointer_map_create ();
/* Set up context. */
- start_preparsed_function (d, NULL_TREE, SF_PRE_PARSED);
+ if (DECL_OMP_DECLARE_REDUCTION_P (code_pattern)
+ && TREE_CODE (DECL_CONTEXT (code_pattern)) == FUNCTION_DECL)
+ block = push_stmt_list ();
+ else
+ start_preparsed_function (d, NULL_TREE, SF_PRE_PARSED);
/* Some typedefs referenced from within the template code need to be
access checked at template instantiation time, i.e now. These
@@ -19385,21 +19615,37 @@ instantiate_decl (tree d, int defer_ok,
gcc_assert (!spec_parm);
/* Substitute into the body of the function. */
- tsubst_expr (DECL_SAVED_TREE (code_pattern), args,
- tf_warning_or_error, tmpl,
- /*integral_constant_expression_p=*/false);
-
- /* Set the current input_location to the end of the function
- so that finish_function knows where we are. */
- input_location = DECL_STRUCT_FUNCTION (code_pattern)->function_end_locus;
+ if (DECL_OMP_DECLARE_REDUCTION_P (code_pattern))
+ tsubst_omp_udr (DECL_SAVED_TREE (code_pattern), args,
+ tf_warning_or_error, tmpl);
+ else
+ {
+ tsubst_expr (DECL_SAVED_TREE (code_pattern), args,
+ tf_warning_or_error, tmpl,
+ /*integral_constant_expression_p=*/false);
+
+ /* Set the current input_location to the end of the function
+ so that finish_function knows where we are. */
+ input_location
+ = DECL_STRUCT_FUNCTION (code_pattern)->function_end_locus;
+ }
/* We don't need the local specializations any more. */
pointer_map_destroy (local_specializations);
local_specializations = saved_local_specializations;
/* Finish the function. */
- d = finish_function (0);
- expand_or_defer_fn (d);
+ if (DECL_OMP_DECLARE_REDUCTION_P (code_pattern)
+ && TREE_CODE (DECL_CONTEXT (code_pattern)) == FUNCTION_DECL)
+ DECL_SAVED_TREE (d) = pop_stmt_list (block);
+ else
+ {
+ d = finish_function (0);
+ expand_or_defer_fn (d);
+ }
+
+ if (DECL_OMP_DECLARE_REDUCTION_P (code_pattern))
+ cp_check_omp_declare_reduction (d);
}
/* We're not deferring instantiation any more. */
@@ -20260,7 +20506,7 @@ type_dependent_expression_p (tree expression)
if (!processing_template_decl)
return false;
- if (expression == error_mark_node)
+ if (expression == NULL_TREE || expression == error_mark_node)
return false;
/* An unresolved name is always dependent. */
@@ -20399,6 +20645,10 @@ type_dependent_expression_p (tree expression)
if (TREE_CODE (expression) == SCOPE_REF)
return false;
+ /* Always dependent, on the number of arguments if nothing else. */
+ if (TREE_CODE (expression) == EXPR_PACK_EXPANSION)
+ return true;
+
if (BASELINK_P (expression))
expression = BASELINK_FUNCTIONS (expression);
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 0299b690fb1..366756fd437 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -44,6 +44,7 @@ along with GCC; see the file COPYING3. If not see
#include "gimple.h"
#include "bitmap.h"
#include "hash-table.h"
+#include "omp-low.h"
static bool verify_constant (tree, bool, bool *, bool *);
#define VERIFY_CONSTANT(X) \
@@ -725,9 +726,15 @@ begin_while_stmt (void)
WHILE_STMT. */
void
-finish_while_stmt_cond (tree cond, tree while_stmt)
+finish_while_stmt_cond (tree cond, tree while_stmt, bool ivdep)
{
finish_cond (&WHILE_COND (while_stmt), maybe_convert_cond (cond));
+ if (ivdep && cond != error_mark_node)
+ WHILE_COND (while_stmt) = build2 (ANNOTATE_EXPR,
+ TREE_TYPE (WHILE_COND (while_stmt)),
+ WHILE_COND (while_stmt),
+ build_int_cst (integer_type_node,
+ annot_expr_ivdep_kind));
simplify_loop_decl_cond (&WHILE_COND (while_stmt), WHILE_BODY (while_stmt));
}
@@ -770,9 +777,12 @@ finish_do_body (tree do_stmt)
COND is as indicated. */
void
-finish_do_stmt (tree cond, tree do_stmt)
+finish_do_stmt (tree cond, tree do_stmt, bool ivdep)
{
cond = maybe_convert_cond (cond);
+ if (ivdep && cond != error_mark_node)
+ cond = build2 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
+ build_int_cst (integer_type_node, annot_expr_ivdep_kind));
DO_COND (do_stmt) = cond;
}
@@ -787,7 +797,8 @@ finish_return_stmt (tree expr)
expr = check_return_expr (expr, &no_warning);
- if (flag_openmp && !check_omp_return ())
+ if (error_operand_p (expr)
+ || (flag_openmp && !check_omp_return ()))
return error_mark_node;
if (!processing_template_decl)
{
@@ -874,9 +885,15 @@ finish_for_init_stmt (tree for_stmt)
FOR_STMT. */
void
-finish_for_cond (tree cond, tree for_stmt)
+finish_for_cond (tree cond, tree for_stmt, bool ivdep)
{
finish_cond (&FOR_COND (for_stmt), maybe_convert_cond (cond));
+ if (ivdep && cond != error_mark_node)
+ FOR_COND (for_stmt) = build2 (ANNOTATE_EXPR,
+ TREE_TYPE (FOR_COND (for_stmt)),
+ FOR_COND (for_stmt),
+ build_int_cst (integer_type_node,
+ annot_expr_ivdep_kind));
simplify_loop_decl_cond (&FOR_COND (for_stmt), FOR_BODY (for_stmt));
}
@@ -2499,6 +2516,7 @@ finish_compound_literal (tree type, tree compound_literal,
if ((!at_function_scope_p () || CP_TYPE_CONST_P (type))
&& TREE_CODE (type) == ARRAY_TYPE
&& !TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)
+ && !cp_unevaluated_operand
&& initializer_constant_valid_p (compound_literal, type))
{
tree decl = create_temporary_var (type);
@@ -2519,6 +2537,10 @@ finish_compound_literal (tree type, tree compound_literal,
decl = pushdecl_top_level (decl);
DECL_NAME (decl) = make_anon_name ();
SET_DECL_ASSEMBLER_NAME (decl, DECL_NAME (decl));
+ /* Make sure the destructor is callable. */
+ tree clean = cxx_maybe_build_cleanup (decl, complain);
+ if (clean == error_mark_node)
+ return error_mark_node;
return decl;
}
else
@@ -4046,7 +4068,8 @@ finalize_nrv (tree *tp, tree var, tree result)
bool
cxx_omp_create_clause_info (tree c, tree type, bool need_default_ctor,
- bool need_copy_ctor, bool need_copy_assignment)
+ bool need_copy_ctor, bool need_copy_assignment,
+ bool need_dtor)
{
int save_errorcount = errorcount;
tree info, t;
@@ -4070,8 +4093,7 @@ cxx_omp_create_clause_info (tree c, tree type, bool need_default_ctor,
TREE_VEC_ELT (info, 0) = t;
}
- if ((need_default_ctor || need_copy_ctor)
- && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
+ if (need_dtor && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
TREE_VEC_ELT (info, 1) = get_dtor (type, tf_warning_or_error);
if (need_copy_assignment)
@@ -4085,6 +4107,1037 @@ cxx_omp_create_clause_info (tree c, tree type, bool need_default_ctor,
return errorcount != save_errorcount;
}
+/* Helper function for handle_omp_array_sections. Called recursively
+ to handle multiple array-section-subscripts. C is the clause,
+ T current expression (initially OMP_CLAUSE_DECL), which is either
+ a TREE_LIST for array-section-subscript (TREE_PURPOSE is low-bound
+ expression if specified, TREE_VALUE length expression if specified,
+ TREE_CHAIN is what it has been specified after, or some decl.
+ TYPES vector is populated with array section types, MAYBE_ZERO_LEN
+ set to true if any of the array-section-subscript could have length
+ of zero (explicit or implicit), FIRST_NON_ONE is the index of the
+ first array-section-subscript which is known not to have length
+ of one. Given say:
+ map(a[:b][2:1][:c][:2][:d][e:f][2:5])
+ FIRST_NON_ONE will be 3, array-section-subscript [:b], [2:1] and [:c]
+ all are or may have length of 1, array-section-subscript [:2] is the
+ first one knonwn not to have length 1. For array-section-subscript
+ <= FIRST_NON_ONE we diagnose non-contiguous arrays if low bound isn't
+ 0 or length isn't the array domain max + 1, for > FIRST_NON_ONE we
+ can if MAYBE_ZERO_LEN is false. MAYBE_ZERO_LEN will be true in the above
+ case though, as some lengths could be zero. */
+
+static tree
+handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
+ bool &maybe_zero_len, unsigned int &first_non_one)
+{
+ tree ret, low_bound, length, type;
+ if (TREE_CODE (t) != TREE_LIST)
+ {
+ if (error_operand_p (t))
+ return error_mark_node;
+ if (type_dependent_expression_p (t))
+ return NULL_TREE;
+ if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL)
+ {
+ if (processing_template_decl)
+ return NULL_TREE;
+ if (DECL_P (t))
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD is not a variable in %qs clause", t,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ else
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qE is not a variable in %qs clause", t,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ return error_mark_node;
+ }
+ else if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
+ && TREE_CODE (t) == VAR_DECL && DECL_THREAD_LOCAL_P (t))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD is threadprivate variable in %qs clause", t,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ return error_mark_node;
+ }
+ t = convert_from_reference (t);
+ return t;
+ }
+
+ ret = handle_omp_array_sections_1 (c, TREE_CHAIN (t), types,
+ maybe_zero_len, first_non_one);
+ if (ret == error_mark_node || ret == NULL_TREE)
+ return ret;
+
+ type = TREE_TYPE (ret);
+ low_bound = TREE_PURPOSE (t);
+ length = TREE_VALUE (t);
+ if ((low_bound && type_dependent_expression_p (low_bound))
+ || (length && type_dependent_expression_p (length)))
+ return NULL_TREE;
+
+ if (low_bound == error_mark_node || length == error_mark_node)
+ return error_mark_node;
+
+ if (low_bound && !INTEGRAL_TYPE_P (TREE_TYPE (low_bound)))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "low bound %qE of array section does not have integral type",
+ low_bound);
+ return error_mark_node;
+ }
+ if (length && !INTEGRAL_TYPE_P (TREE_TYPE (length)))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "length %qE of array section does not have integral type",
+ length);
+ return error_mark_node;
+ }
+ if (low_bound
+ && TREE_CODE (low_bound) == INTEGER_CST
+ && TYPE_PRECISION (TREE_TYPE (low_bound))
+ > TYPE_PRECISION (sizetype))
+ low_bound = fold_convert (sizetype, low_bound);
+ if (length
+ && TREE_CODE (length) == INTEGER_CST
+ && TYPE_PRECISION (TREE_TYPE (length))
+ > TYPE_PRECISION (sizetype))
+ length = fold_convert (sizetype, length);
+ if (low_bound == NULL_TREE)
+ low_bound = integer_zero_node;
+
+ if (length != NULL_TREE)
+ {
+ if (!integer_nonzerop (length))
+ maybe_zero_len = true;
+ if (first_non_one == types.length ()
+ && (TREE_CODE (length) != INTEGER_CST || integer_onep (length)))
+ first_non_one++;
+ }
+ if (TREE_CODE (type) == ARRAY_TYPE)
+ {
+ if (length == NULL_TREE
+ && (TYPE_DOMAIN (type) == NULL_TREE
+ || TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "for unknown bound array type length expression must "
+ "be specified");
+ return error_mark_node;
+ }
+ if (TREE_CODE (low_bound) == INTEGER_CST
+ && tree_int_cst_sgn (low_bound) == -1)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "negative low bound in array section in %qs clause",
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ return error_mark_node;
+ }
+ if (length != NULL_TREE
+ && TREE_CODE (length) == INTEGER_CST
+ && tree_int_cst_sgn (length) == -1)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "negative length in array section in %qs clause",
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ return error_mark_node;
+ }
+ if (TYPE_DOMAIN (type)
+ && TYPE_MAX_VALUE (TYPE_DOMAIN (type))
+ && TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type)))
+ == INTEGER_CST)
+ {
+ tree size = size_binop (PLUS_EXPR,
+ TYPE_MAX_VALUE (TYPE_DOMAIN (type)),
+ size_one_node);
+ if (TREE_CODE (low_bound) == INTEGER_CST)
+ {
+ if (tree_int_cst_lt (size, low_bound))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "low bound %qE above array section size "
+ "in %qs clause", low_bound,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ return error_mark_node;
+ }
+ if (tree_int_cst_equal (size, low_bound))
+ maybe_zero_len = true;
+ else if (length == NULL_TREE
+ && first_non_one == types.length ()
+ && tree_int_cst_equal
+ (TYPE_MAX_VALUE (TYPE_DOMAIN (type)),
+ low_bound))
+ first_non_one++;
+ }
+ else if (length == NULL_TREE)
+ {
+ maybe_zero_len = true;
+ if (first_non_one == types.length ())
+ first_non_one++;
+ }
+ if (length && TREE_CODE (length) == INTEGER_CST)
+ {
+ if (tree_int_cst_lt (size, length))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "length %qE above array section size "
+ "in %qs clause", length,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ return error_mark_node;
+ }
+ if (TREE_CODE (low_bound) == INTEGER_CST)
+ {
+ tree lbpluslen
+ = size_binop (PLUS_EXPR,
+ fold_convert (sizetype, low_bound),
+ fold_convert (sizetype, length));
+ if (TREE_CODE (lbpluslen) == INTEGER_CST
+ && tree_int_cst_lt (size, lbpluslen))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "high bound %qE above array section size "
+ "in %qs clause", lbpluslen,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ return error_mark_node;
+ }
+ }
+ }
+ }
+ else if (length == NULL_TREE)
+ {
+ maybe_zero_len = true;
+ if (first_non_one == types.length ())
+ first_non_one++;
+ }
+
+ /* For [lb:] we will need to evaluate lb more than once. */
+ if (length == NULL_TREE && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND)
+ {
+ tree lb = cp_save_expr (low_bound);
+ if (lb != low_bound)
+ {
+ TREE_PURPOSE (t) = lb;
+ low_bound = lb;
+ }
+ }
+ }
+ else if (TREE_CODE (type) == POINTER_TYPE)
+ {
+ if (length == NULL_TREE)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "for pointer type length expression must be specified");
+ return error_mark_node;
+ }
+ /* If there is a pointer type anywhere but in the very first
+ array-section-subscript, the array section can't be contiguous. */
+ if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
+ && TREE_CODE (TREE_CHAIN (t)) == TREE_LIST)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "array section is not contiguous in %qs clause",
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ return error_mark_node;
+ }
+ }
+ else
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qE does not have pointer or array type", ret);
+ return error_mark_node;
+ }
+ if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND)
+ types.safe_push (TREE_TYPE (ret));
+ /* We will need to evaluate lb more than once. */
+ tree lb = cp_save_expr (low_bound);
+ if (lb != low_bound)
+ {
+ TREE_PURPOSE (t) = lb;
+ low_bound = lb;
+ }
+ ret = grok_array_decl (OMP_CLAUSE_LOCATION (c), ret, low_bound, false);
+ return ret;
+}
+
+/* Handle array sections for clause C. */
+
+static bool
+handle_omp_array_sections (tree c)
+{
+ bool maybe_zero_len = false;
+ unsigned int first_non_one = 0;
+ vec<tree> types = vNULL;
+ tree first = handle_omp_array_sections_1 (c, OMP_CLAUSE_DECL (c), types,
+ maybe_zero_len, first_non_one);
+ if (first == error_mark_node)
+ {
+ types.release ();
+ return true;
+ }
+ if (first == NULL_TREE)
+ {
+ types.release ();
+ return false;
+ }
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
+ {
+ tree t = OMP_CLAUSE_DECL (c);
+ tree tem = NULL_TREE;
+ types.release ();
+ if (processing_template_decl)
+ return false;
+ /* Need to evaluate side effects in the length expressions
+ if any. */
+ while (TREE_CODE (t) == TREE_LIST)
+ {
+ if (TREE_VALUE (t) && TREE_SIDE_EFFECTS (TREE_VALUE (t)))
+ {
+ if (tem == NULL_TREE)
+ tem = TREE_VALUE (t);
+ else
+ tem = build2 (COMPOUND_EXPR, TREE_TYPE (tem),
+ TREE_VALUE (t), tem);
+ }
+ t = TREE_CHAIN (t);
+ }
+ if (tem)
+ first = build2 (COMPOUND_EXPR, TREE_TYPE (first), tem, first);
+ OMP_CLAUSE_DECL (c) = first;
+ }
+ else
+ {
+ unsigned int num = types.length (), i;
+ tree t, side_effects = NULL_TREE, size = NULL_TREE;
+ tree condition = NULL_TREE;
+
+ if (int_size_in_bytes (TREE_TYPE (first)) <= 0)
+ maybe_zero_len = true;
+ if (processing_template_decl && maybe_zero_len)
+ {
+ types.release ();
+ return false;
+ }
+
+ for (i = num, t = OMP_CLAUSE_DECL (c); i > 0;
+ t = TREE_CHAIN (t))
+ {
+ tree low_bound = TREE_PURPOSE (t);
+ tree length = TREE_VALUE (t);
+
+ i--;
+ if (low_bound
+ && TREE_CODE (low_bound) == INTEGER_CST
+ && TYPE_PRECISION (TREE_TYPE (low_bound))
+ > TYPE_PRECISION (sizetype))
+ low_bound = fold_convert (sizetype, low_bound);
+ if (length
+ && TREE_CODE (length) == INTEGER_CST
+ && TYPE_PRECISION (TREE_TYPE (length))
+ > TYPE_PRECISION (sizetype))
+ length = fold_convert (sizetype, length);
+ if (low_bound == NULL_TREE)
+ low_bound = integer_zero_node;
+ if (!maybe_zero_len && i > first_non_one)
+ {
+ if (integer_nonzerop (low_bound))
+ goto do_warn_noncontiguous;
+ if (length != NULL_TREE
+ && TREE_CODE (length) == INTEGER_CST
+ && TYPE_DOMAIN (types[i])
+ && TYPE_MAX_VALUE (TYPE_DOMAIN (types[i]))
+ && TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (types[i])))
+ == INTEGER_CST)
+ {
+ tree size;
+ size = size_binop (PLUS_EXPR,
+ TYPE_MAX_VALUE (TYPE_DOMAIN (types[i])),
+ size_one_node);
+ if (!tree_int_cst_equal (length, size))
+ {
+ do_warn_noncontiguous:
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "array section is not contiguous in %qs "
+ "clause",
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ types.release ();
+ return true;
+ }
+ }
+ if (!processing_template_decl
+ && length != NULL_TREE
+ && TREE_SIDE_EFFECTS (length))
+ {
+ if (side_effects == NULL_TREE)
+ side_effects = length;
+ else
+ side_effects = build2 (COMPOUND_EXPR,
+ TREE_TYPE (side_effects),
+ length, side_effects);
+ }
+ }
+ else if (processing_template_decl)
+ continue;
+ else
+ {
+ tree l;
+
+ if (i > first_non_one && length && integer_nonzerop (length))
+ continue;
+ if (length)
+ l = fold_convert (sizetype, length);
+ else
+ {
+ l = size_binop (PLUS_EXPR,
+ TYPE_MAX_VALUE (TYPE_DOMAIN (types[i])),
+ size_one_node);
+ l = size_binop (MINUS_EXPR, l,
+ fold_convert (sizetype, low_bound));
+ }
+ if (i > first_non_one)
+ {
+ l = fold_build2 (NE_EXPR, boolean_type_node, l,
+ size_zero_node);
+ if (condition == NULL_TREE)
+ condition = l;
+ else
+ condition = fold_build2 (BIT_AND_EXPR, boolean_type_node,
+ l, condition);
+ }
+ else if (size == NULL_TREE)
+ {
+ size = size_in_bytes (TREE_TYPE (types[i]));
+ size = size_binop (MULT_EXPR, size, l);
+ if (condition)
+ size = fold_build3 (COND_EXPR, sizetype, condition,
+ size, size_zero_node);
+ }
+ else
+ size = size_binop (MULT_EXPR, size, l);
+ }
+ }
+ types.release ();
+ if (!processing_template_decl)
+ {
+ if (side_effects)
+ size = build2 (COMPOUND_EXPR, sizetype, side_effects, size);
+ OMP_CLAUSE_DECL (c) = first;
+ OMP_CLAUSE_SIZE (c) = size;
+ if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
+ return false;
+ tree c2 = build_omp_clause (OMP_CLAUSE_LOCATION (c),
+ OMP_CLAUSE_MAP);
+ OMP_CLAUSE_MAP_KIND (c2) = OMP_CLAUSE_MAP_POINTER;
+ if (!cxx_mark_addressable (t))
+ return false;
+ OMP_CLAUSE_DECL (c2) = t;
+ t = build_fold_addr_expr (first);
+ t = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
+ ptrdiff_type_node, t);
+ tree ptr = OMP_CLAUSE_DECL (c2);
+ ptr = convert_from_reference (ptr);
+ if (!POINTER_TYPE_P (TREE_TYPE (ptr)))
+ ptr = build_fold_addr_expr (ptr);
+ t = fold_build2_loc (OMP_CLAUSE_LOCATION (c), MINUS_EXPR,
+ ptrdiff_type_node, t,
+ fold_convert_loc (OMP_CLAUSE_LOCATION (c),
+ ptrdiff_type_node, ptr));
+ OMP_CLAUSE_SIZE (c2) = t;
+ OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (c);
+ OMP_CLAUSE_CHAIN (c) = c2;
+ ptr = OMP_CLAUSE_DECL (c2);
+ if (TREE_CODE (TREE_TYPE (ptr)) == REFERENCE_TYPE
+ && POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (ptr))))
+ {
+ tree c3 = build_omp_clause (OMP_CLAUSE_LOCATION (c),
+ OMP_CLAUSE_MAP);
+ OMP_CLAUSE_MAP_KIND (c3) = OMP_CLAUSE_MAP_POINTER;
+ OMP_CLAUSE_DECL (c3) = ptr;
+ OMP_CLAUSE_DECL (c2) = convert_from_reference (ptr);
+ OMP_CLAUSE_SIZE (c3) = size_zero_node;
+ OMP_CLAUSE_CHAIN (c3) = OMP_CLAUSE_CHAIN (c2);
+ OMP_CLAUSE_CHAIN (c2) = c3;
+ }
+ }
+ }
+ return false;
+}
+
+/* Return identifier to look up for omp declare reduction. */
+
+tree
+omp_reduction_id (enum tree_code reduction_code, tree reduction_id, tree type)
+{
+ const char *p = NULL;
+ const char *m = NULL;
+ switch (reduction_code)
+ {
+ case PLUS_EXPR:
+ case MULT_EXPR:
+ case MINUS_EXPR:
+ case BIT_AND_EXPR:
+ case BIT_XOR_EXPR:
+ case BIT_IOR_EXPR:
+ case TRUTH_ANDIF_EXPR:
+ case TRUTH_ORIF_EXPR:
+ reduction_id = ansi_opname (reduction_code);
+ break;
+ case MIN_EXPR:
+ p = "min";
+ break;
+ case MAX_EXPR:
+ p = "max";
+ break;
+ default:
+ break;
+ }
+
+ if (p == NULL)
+ {
+ if (TREE_CODE (reduction_id) != IDENTIFIER_NODE)
+ return error_mark_node;
+ p = IDENTIFIER_POINTER (reduction_id);
+ }
+
+ if (type != NULL_TREE)
+ m = mangle_type_string (TYPE_MAIN_VARIANT (type));
+
+ const char prefix[] = "omp declare reduction ";
+ size_t lenp = sizeof (prefix);
+ if (strncmp (p, prefix, lenp - 1) == 0)
+ lenp = 1;
+ size_t len = strlen (p);
+ size_t lenm = m ? strlen (m) + 1 : 0;
+ char *name = XALLOCAVEC (char, lenp + len + lenm);
+ if (lenp > 1)
+ memcpy (name, prefix, lenp - 1);
+ memcpy (name + lenp - 1, p, len + 1);
+ if (m)
+ {
+ name[lenp + len - 1] = '~';
+ memcpy (name + lenp + len, m, lenm);
+ }
+ return get_identifier (name);
+}
+
+/* Lookup OpenMP UDR ID for TYPE, return the corresponding artificial
+ FUNCTION_DECL or NULL_TREE if not found. */
+
+static tree
+omp_reduction_lookup (location_t loc, tree id, tree type, tree *baselinkp,
+ vec<tree> *ambiguousp)
+{
+ tree orig_id = id;
+ tree baselink = NULL_TREE;
+ if (identifier_p (id))
+ {
+ cp_id_kind idk;
+ bool nonint_cst_expression_p;
+ const char *error_msg;
+ id = omp_reduction_id (ERROR_MARK, id, type);
+ tree decl = lookup_name (id);
+ if (decl == NULL_TREE)
+ decl = error_mark_node;
+ id = finish_id_expression (id, decl, NULL_TREE, &idk, false, true,
+ &nonint_cst_expression_p, false, true, false,
+ false, &error_msg, loc);
+ if (idk == CP_ID_KIND_UNQUALIFIED
+ && identifier_p (id))
+ {
+ vec<tree, va_gc> *args = NULL;
+ vec_safe_push (args, build_reference_type (type));
+ id = perform_koenig_lookup (id, args, false, tf_none);
+ }
+ }
+ else if (TREE_CODE (id) == SCOPE_REF)
+ id = lookup_qualified_name (TREE_OPERAND (id, 0),
+ omp_reduction_id (ERROR_MARK,
+ TREE_OPERAND (id, 1),
+ type),
+ false, false);
+ tree fns = id;
+ if (id && is_overloaded_fn (id))
+ id = get_fns (id);
+ for (; id; id = OVL_NEXT (id))
+ {
+ tree fndecl = OVL_CURRENT (id);
+ if (TREE_CODE (fndecl) == FUNCTION_DECL)
+ {
+ tree argtype = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (fndecl)));
+ if (same_type_p (TREE_TYPE (argtype), type))
+ break;
+ }
+ }
+ if (id && BASELINK_P (fns))
+ {
+ if (baselinkp)
+ *baselinkp = fns;
+ else
+ baselink = fns;
+ }
+ if (id == NULL_TREE && CLASS_TYPE_P (type) && TYPE_BINFO (type))
+ {
+ vec<tree> ambiguous = vNULL;
+ tree binfo = TYPE_BINFO (type), base_binfo, ret = NULL_TREE;
+ unsigned int ix;
+ if (ambiguousp == NULL)
+ ambiguousp = &ambiguous;
+ for (ix = 0; BINFO_BASE_ITERATE (binfo, ix, base_binfo); ix++)
+ {
+ id = omp_reduction_lookup (loc, orig_id, BINFO_TYPE (base_binfo),
+ baselinkp ? baselinkp : &baselink,
+ ambiguousp);
+ if (id == NULL_TREE)
+ continue;
+ if (!ambiguousp->is_empty ())
+ ambiguousp->safe_push (id);
+ else if (ret != NULL_TREE)
+ {
+ ambiguousp->safe_push (ret);
+ ambiguousp->safe_push (id);
+ ret = NULL_TREE;
+ }
+ else
+ ret = id;
+ }
+ if (ambiguousp != &ambiguous)
+ return ret;
+ if (!ambiguous.is_empty ())
+ {
+ const char *str = _("candidates are:");
+ unsigned int idx;
+ tree udr;
+ error_at (loc, "user defined reduction lookup is ambiguous");
+ FOR_EACH_VEC_ELT (ambiguous, idx, udr)
+ {
+ inform (DECL_SOURCE_LOCATION (udr), "%s %#D", str, udr);
+ if (idx == 0)
+ str = get_spaces (str);
+ }
+ ambiguous.release ();
+ ret = error_mark_node;
+ baselink = NULL_TREE;
+ }
+ id = ret;
+ }
+ if (id && baselink)
+ perform_or_defer_access_check (BASELINK_BINFO (baselink),
+ id, id, tf_warning_or_error);
+ return id;
+}
+
+/* Helper function for cp_parser_omp_declare_reduction_exprs
+ and tsubst_omp_udr.
+ Remove CLEANUP_STMT for data (omp_priv variable).
+ Also append INIT_EXPR for DECL_INITIAL of omp_priv after its
+ DECL_EXPR. */
+
+tree
+cp_remove_omp_priv_cleanup_stmt (tree *tp, int *walk_subtrees, void *data)
+{
+ if (TYPE_P (*tp))
+ *walk_subtrees = 0;
+ else if (TREE_CODE (*tp) == CLEANUP_STMT && CLEANUP_DECL (*tp) == (tree) data)
+ *tp = CLEANUP_BODY (*tp);
+ else if (TREE_CODE (*tp) == DECL_EXPR)
+ {
+ tree decl = DECL_EXPR_DECL (*tp);
+ if (!processing_template_decl
+ && decl == (tree) data
+ && DECL_INITIAL (decl)
+ && DECL_INITIAL (decl) != error_mark_node)
+ {
+ tree list = NULL_TREE;
+ append_to_statement_list_force (*tp, &list);
+ tree init_expr = build2 (INIT_EXPR, void_type_node,
+ decl, DECL_INITIAL (decl));
+ DECL_INITIAL (decl) = NULL_TREE;
+ append_to_statement_list_force (init_expr, &list);
+ *tp = list;
+ }
+ }
+ return NULL_TREE;
+}
+
+/* Data passed from cp_check_omp_declare_reduction to
+ cp_check_omp_declare_reduction_r. */
+
+struct cp_check_omp_declare_reduction_data
+{
+ location_t loc;
+ tree stmts[7];
+ bool combiner_p;
+};
+
+/* Helper function for cp_check_omp_declare_reduction, called via
+ cp_walk_tree. */
+
+static tree
+cp_check_omp_declare_reduction_r (tree *tp, int *, void *data)
+{
+ struct cp_check_omp_declare_reduction_data *udr_data
+ = (struct cp_check_omp_declare_reduction_data *) data;
+ if (SSA_VAR_P (*tp)
+ && !DECL_ARTIFICIAL (*tp)
+ && *tp != DECL_EXPR_DECL (udr_data->stmts[udr_data->combiner_p ? 0 : 3])
+ && *tp != DECL_EXPR_DECL (udr_data->stmts[udr_data->combiner_p ? 1 : 4]))
+ {
+ location_t loc = udr_data->loc;
+ if (udr_data->combiner_p)
+ error_at (loc, "%<#pragma omp declare reduction%> combiner refers to "
+ "variable %qD which is not %<omp_out%> nor %<omp_in%>",
+ *tp);
+ else
+ error_at (loc, "%<#pragma omp declare reduction%> initializer refers "
+ "to variable %qD which is not %<omp_priv%> nor "
+ "%<omp_orig%>",
+ *tp);
+ return *tp;
+ }
+ return NULL_TREE;
+}
+
+/* Diagnose violation of OpenMP #pragma omp declare reduction restrictions. */
+
+void
+cp_check_omp_declare_reduction (tree udr)
+{
+ tree type = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (udr)));
+ gcc_assert (TREE_CODE (type) == REFERENCE_TYPE);
+ type = TREE_TYPE (type);
+ int i;
+ location_t loc = DECL_SOURCE_LOCATION (udr);
+
+ if (type == error_mark_node)
+ return;
+ if (ARITHMETIC_TYPE_P (type))
+ {
+ static enum tree_code predef_codes[]
+ = { PLUS_EXPR, MULT_EXPR, MINUS_EXPR, BIT_AND_EXPR, BIT_XOR_EXPR,
+ BIT_IOR_EXPR, TRUTH_ANDIF_EXPR, TRUTH_ORIF_EXPR };
+ for (i = 0; i < 8; i++)
+ {
+ tree id = omp_reduction_id (predef_codes[i], NULL_TREE, NULL_TREE);
+ const char *n1 = IDENTIFIER_POINTER (DECL_NAME (udr));
+ const char *n2 = IDENTIFIER_POINTER (id);
+ if (strncmp (n1, n2, IDENTIFIER_LENGTH (id)) == 0
+ && (n1[IDENTIFIER_LENGTH (id)] == '~'
+ || n1[IDENTIFIER_LENGTH (id)] == '\0'))
+ break;
+ }
+
+ if (i == 8
+ && TREE_CODE (type) != COMPLEX_EXPR)
+ {
+ const char prefix_minmax[] = "omp declare reduction m";
+ size_t prefix_size = sizeof (prefix_minmax) - 1;
+ const char *n = IDENTIFIER_POINTER (DECL_NAME (udr));
+ if (strncmp (IDENTIFIER_POINTER (DECL_NAME (udr)),
+ prefix_minmax, prefix_size) == 0
+ && ((n[prefix_size] == 'i' && n[prefix_size + 1] == 'n')
+ || (n[prefix_size] == 'a' && n[prefix_size + 1] == 'x'))
+ && (n[prefix_size + 2] == '~' || n[prefix_size + 2] == '\0'))
+ i = 0;
+ }
+ if (i < 8)
+ {
+ error_at (loc, "predeclared arithmetic type %qT in "
+ "%<#pragma omp declare reduction%>", type);
+ return;
+ }
+ }
+ else if (TREE_CODE (type) == FUNCTION_TYPE
+ || TREE_CODE (type) == METHOD_TYPE
+ || TREE_CODE (type) == ARRAY_TYPE)
+ {
+ error_at (loc, "function or array type %qT in "
+ "%<#pragma omp declare reduction%>", type);
+ return;
+ }
+ else if (TREE_CODE (type) == REFERENCE_TYPE)
+ {
+ error_at (loc, "reference type %qT in %<#pragma omp declare reduction%>",
+ type);
+ return;
+ }
+ else if (TYPE_QUALS_NO_ADDR_SPACE (type))
+ {
+ error_at (loc, "const, volatile or __restrict qualified type %qT in "
+ "%<#pragma omp declare reduction%>", type);
+ return;
+ }
+
+ tree body = DECL_SAVED_TREE (udr);
+ if (body == NULL_TREE || TREE_CODE (body) != STATEMENT_LIST)
+ return;
+
+ tree_stmt_iterator tsi;
+ struct cp_check_omp_declare_reduction_data data;
+ memset (data.stmts, 0, sizeof data.stmts);
+ for (i = 0, tsi = tsi_start (body);
+ i < 7 && !tsi_end_p (tsi);
+ i++, tsi_next (&tsi))
+ data.stmts[i] = tsi_stmt (tsi);
+ data.loc = loc;
+ gcc_assert (tsi_end_p (tsi));
+ if (i >= 3)
+ {
+ gcc_assert (TREE_CODE (data.stmts[0]) == DECL_EXPR
+ && TREE_CODE (data.stmts[1]) == DECL_EXPR);
+ if (TREE_NO_WARNING (DECL_EXPR_DECL (data.stmts[0])))
+ return;
+ data.combiner_p = true;
+ if (cp_walk_tree (&data.stmts[2], cp_check_omp_declare_reduction_r,
+ &data, NULL))
+ TREE_NO_WARNING (DECL_EXPR_DECL (data.stmts[0])) = 1;
+ }
+ if (i >= 6)
+ {
+ gcc_assert (TREE_CODE (data.stmts[3]) == DECL_EXPR
+ && TREE_CODE (data.stmts[4]) == DECL_EXPR);
+ data.combiner_p = false;
+ if (cp_walk_tree (&data.stmts[5], cp_check_omp_declare_reduction_r,
+ &data, NULL)
+ || cp_walk_tree (&DECL_INITIAL (DECL_EXPR_DECL (data.stmts[3])),
+ cp_check_omp_declare_reduction_r, &data, NULL))
+ TREE_NO_WARNING (DECL_EXPR_DECL (data.stmts[0])) = 1;
+ if (i == 7)
+ gcc_assert (TREE_CODE (data.stmts[6]) == DECL_EXPR);
+ }
+}
+
+/* Helper function of finish_omp_clauses. Clone STMT as if we were making
+ an inline call. But, remap
+ the OMP_DECL1 VAR_DECL (omp_out resp. omp_orig) to PLACEHOLDER
+ and OMP_DECL2 VAR_DECL (omp_in resp. omp_priv) to DECL. */
+
+static tree
+clone_omp_udr (tree stmt, tree omp_decl1, tree omp_decl2,
+ tree decl, tree placeholder)
+{
+ copy_body_data id;
+ struct pointer_map_t *decl_map = pointer_map_create ();
+
+ *pointer_map_insert (decl_map, omp_decl1) = placeholder;
+ *pointer_map_insert (decl_map, omp_decl2) = decl;
+ memset (&id, 0, sizeof (id));
+ id.src_fn = DECL_CONTEXT (omp_decl1);
+ id.dst_fn = current_function_decl;
+ id.src_cfun = DECL_STRUCT_FUNCTION (id.src_fn);
+ id.decl_map = decl_map;
+
+ id.copy_decl = copy_decl_no_change;
+ id.transform_call_graph_edges = CB_CGE_DUPLICATE;
+ id.transform_new_cfg = true;
+ id.transform_return_to_modify = false;
+ id.transform_lang_insert_block = NULL;
+ id.eh_lp_nr = 0;
+ walk_tree (&stmt, copy_tree_body_r, &id, NULL);
+ pointer_map_destroy (decl_map);
+ return stmt;
+}
+
+/* Helper function of finish_omp_clauses, called via cp_walk_tree.
+ Find OMP_CLAUSE_PLACEHOLDER (passed in DATA) in *TP. */
+
+static tree
+find_omp_placeholder_r (tree *tp, int *, void *data)
+{
+ if (*tp == (tree) data)
+ return *tp;
+ return NULL_TREE;
+}
+
+/* Helper function of finish_omp_clauses. Handle OMP_CLAUSE_REDUCTION C.
+ Return true if there is some error and the clause should be removed. */
+
+static bool
+finish_omp_reduction_clause (tree c, bool *need_default_ctor, bool *need_dtor)
+{
+ tree t = OMP_CLAUSE_DECL (c);
+ bool predefined = false;
+ tree type = TREE_TYPE (t);
+ if (TREE_CODE (type) == REFERENCE_TYPE)
+ type = TREE_TYPE (type);
+ if (ARITHMETIC_TYPE_P (type))
+ switch (OMP_CLAUSE_REDUCTION_CODE (c))
+ {
+ case PLUS_EXPR:
+ case MULT_EXPR:
+ case MINUS_EXPR:
+ predefined = true;
+ break;
+ case MIN_EXPR:
+ case MAX_EXPR:
+ if (TREE_CODE (type) == COMPLEX_TYPE)
+ break;
+ predefined = true;
+ break;
+ case BIT_AND_EXPR:
+ case BIT_IOR_EXPR:
+ case BIT_XOR_EXPR:
+ case TRUTH_ANDIF_EXPR:
+ case TRUTH_ORIF_EXPR:
+ if (FLOAT_TYPE_P (type))
+ break;
+ predefined = true;
+ break;
+ default:
+ break;
+ }
+ else if (TREE_CODE (type) == ARRAY_TYPE || TYPE_READONLY (type))
+ {
+ error ("%qE has invalid type for %<reduction%>", t);
+ return true;
+ }
+ else if (!processing_template_decl)
+ {
+ t = require_complete_type (t);
+ if (t == error_mark_node)
+ return true;
+ OMP_CLAUSE_DECL (c) = t;
+ }
+
+ if (predefined)
+ {
+ OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL_TREE;
+ return false;
+ }
+ else if (processing_template_decl)
+ return false;
+
+ tree id = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
+
+ type = TYPE_MAIN_VARIANT (TREE_TYPE (t));
+ if (TREE_CODE (type) == REFERENCE_TYPE)
+ type = TREE_TYPE (type);
+ OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL_TREE;
+ if (id == NULL_TREE)
+ id = omp_reduction_id (OMP_CLAUSE_REDUCTION_CODE (c),
+ NULL_TREE, NULL_TREE);
+ id = omp_reduction_lookup (OMP_CLAUSE_LOCATION (c), id, type, NULL, NULL);
+ if (id)
+ {
+ if (id == error_mark_node)
+ return true;
+ id = OVL_CURRENT (id);
+ mark_used (id);
+ tree body = DECL_SAVED_TREE (id);
+ if (TREE_CODE (body) == STATEMENT_LIST)
+ {
+ tree_stmt_iterator tsi;
+ tree placeholder = NULL_TREE;
+ int i;
+ tree stmts[7];
+ tree atype = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (id)));
+ atype = TREE_TYPE (atype);
+ bool need_static_cast = !same_type_p (type, atype);
+ memset (stmts, 0, sizeof stmts);
+ for (i = 0, tsi = tsi_start (body);
+ i < 7 && !tsi_end_p (tsi);
+ i++, tsi_next (&tsi))
+ stmts[i] = tsi_stmt (tsi);
+ gcc_assert (tsi_end_p (tsi));
+
+ if (i >= 3)
+ {
+ gcc_assert (TREE_CODE (stmts[0]) == DECL_EXPR
+ && TREE_CODE (stmts[1]) == DECL_EXPR);
+ placeholder = build_lang_decl (VAR_DECL, NULL_TREE, type);
+ DECL_ARTIFICIAL (placeholder) = 1;
+ DECL_IGNORED_P (placeholder) = 1;
+ OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = placeholder;
+ if (TREE_ADDRESSABLE (DECL_EXPR_DECL (stmts[0])))
+ cxx_mark_addressable (placeholder);
+ if (TREE_ADDRESSABLE (DECL_EXPR_DECL (stmts[1]))
+ && TREE_CODE (TREE_TYPE (OMP_CLAUSE_DECL (c)))
+ != REFERENCE_TYPE)
+ cxx_mark_addressable (OMP_CLAUSE_DECL (c));
+ tree omp_out = placeholder;
+ tree omp_in = convert_from_reference (OMP_CLAUSE_DECL (c));
+ if (need_static_cast)
+ {
+ tree rtype = build_reference_type (atype);
+ omp_out = build_static_cast (rtype, omp_out,
+ tf_warning_or_error);
+ omp_in = build_static_cast (rtype, omp_in,
+ tf_warning_or_error);
+ if (omp_out == error_mark_node || omp_in == error_mark_node)
+ return true;
+ omp_out = convert_from_reference (omp_out);
+ omp_in = convert_from_reference (omp_in);
+ }
+ OMP_CLAUSE_REDUCTION_MERGE (c)
+ = clone_omp_udr (stmts[2], DECL_EXPR_DECL (stmts[0]),
+ DECL_EXPR_DECL (stmts[1]), omp_in, omp_out);
+ }
+ if (i >= 6)
+ {
+ gcc_assert (TREE_CODE (stmts[3]) == DECL_EXPR
+ && TREE_CODE (stmts[4]) == DECL_EXPR);
+ if (TREE_ADDRESSABLE (DECL_EXPR_DECL (stmts[3])))
+ cxx_mark_addressable (OMP_CLAUSE_DECL (c));
+ if (TREE_ADDRESSABLE (DECL_EXPR_DECL (stmts[4])))
+ cxx_mark_addressable (placeholder);
+ tree omp_priv = convert_from_reference (OMP_CLAUSE_DECL (c));
+ tree omp_orig = placeholder;
+ if (need_static_cast)
+ {
+ if (i == 7)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "user defined reduction with constructor "
+ "initializer for base class %qT", atype);
+ return true;
+ }
+ tree rtype = build_reference_type (atype);
+ omp_priv = build_static_cast (rtype, omp_priv,
+ tf_warning_or_error);
+ omp_orig = build_static_cast (rtype, omp_orig,
+ tf_warning_or_error);
+ if (omp_priv == error_mark_node
+ || omp_orig == error_mark_node)
+ return true;
+ omp_priv = convert_from_reference (omp_priv);
+ omp_orig = convert_from_reference (omp_orig);
+ }
+ if (i == 6)
+ *need_default_ctor = true;
+ OMP_CLAUSE_REDUCTION_INIT (c)
+ = clone_omp_udr (stmts[5], DECL_EXPR_DECL (stmts[4]),
+ DECL_EXPR_DECL (stmts[3]),
+ omp_priv, omp_orig);
+ if (cp_walk_tree (&OMP_CLAUSE_REDUCTION_INIT (c),
+ find_omp_placeholder_r, placeholder, NULL))
+ OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c) = 1;
+ }
+ else if (i >= 3)
+ {
+ if (CLASS_TYPE_P (type) && !pod_type_p (type))
+ *need_default_ctor = true;
+ else
+ {
+ tree init;
+ tree v = convert_from_reference (t);
+ if (AGGREGATE_TYPE_P (TREE_TYPE (v)))
+ init = build_constructor (TREE_TYPE (v), NULL);
+ else
+ init = fold_convert (TREE_TYPE (v), integer_zero_node);
+ OMP_CLAUSE_REDUCTION_INIT (c)
+ = build2 (INIT_EXPR, TREE_TYPE (v), v, init);
+ }
+ }
+ }
+ }
+ if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
+ *need_dtor = true;
+ else
+ {
+ error ("user defined reduction not found for %qD", t);
+ return true;
+ }
+ return false;
+}
+
/* For all elements of CLAUSES, validate them vs OpenMP constraints.
Remove any elements from the list that are invalid. */
@@ -4092,13 +5145,16 @@ tree
finish_omp_clauses (tree clauses)
{
bitmap_head generic_head, firstprivate_head, lastprivate_head;
+ bitmap_head aligned_head;
tree c, t, *pc = &clauses;
- const char *name;
+ bool branch_seen = false;
+ bool copyprivate_seen = false;
bitmap_obstack_initialize (NULL);
bitmap_initialize (&generic_head, &bitmap_default_obstack);
bitmap_initialize (&firstprivate_head, &bitmap_default_obstack);
bitmap_initialize (&lastprivate_head, &bitmap_default_obstack);
+ bitmap_initialize (&aligned_head, &bitmap_default_obstack);
for (pc = &clauses, c = clauses; c ; c = *pc)
{
@@ -4107,19 +5163,65 @@ finish_omp_clauses (tree clauses)
switch (OMP_CLAUSE_CODE (c))
{
case OMP_CLAUSE_SHARED:
- name = "shared";
goto check_dup_generic;
case OMP_CLAUSE_PRIVATE:
- name = "private";
goto check_dup_generic;
case OMP_CLAUSE_REDUCTION:
- name = "reduction";
goto check_dup_generic;
case OMP_CLAUSE_COPYPRIVATE:
- name = "copyprivate";
+ copyprivate_seen = true;
goto check_dup_generic;
case OMP_CLAUSE_COPYIN:
- name = "copyin";
+ goto check_dup_generic;
+ case OMP_CLAUSE_LINEAR:
+ t = OMP_CLAUSE_DECL (c);
+ if (!type_dependent_expression_p (t)
+ && !INTEGRAL_TYPE_P (TREE_TYPE (t))
+ && TREE_CODE (TREE_TYPE (t)) != POINTER_TYPE)
+ {
+ error ("linear clause applied to non-integral non-pointer "
+ "variable with %qT type", TREE_TYPE (t));
+ remove = true;
+ break;
+ }
+ t = OMP_CLAUSE_LINEAR_STEP (c);
+ if (t == NULL_TREE)
+ t = integer_one_node;
+ if (t == error_mark_node)
+ {
+ remove = true;
+ break;
+ }
+ else if (!type_dependent_expression_p (t)
+ && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
+ {
+ error ("linear step expression must be integral");
+ remove = true;
+ break;
+ }
+ else
+ {
+ t = mark_rvalue_use (t);
+ if (!processing_template_decl)
+ {
+ t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
+ if (TREE_CODE (TREE_TYPE (OMP_CLAUSE_DECL (c)))
+ == POINTER_TYPE)
+ {
+ t = pointer_int_sum (OMP_CLAUSE_LOCATION (c), PLUS_EXPR,
+ OMP_CLAUSE_DECL (c), t);
+ t = fold_build2_loc (OMP_CLAUSE_LOCATION (c),
+ MINUS_EXPR, sizetype, t,
+ OMP_CLAUSE_DECL (c));
+ if (t == error_mark_node)
+ {
+ remove = true;
+ break;
+ }
+ }
+ }
+ OMP_CLAUSE_LINEAR_STEP (c) = t;
+ }
goto check_dup_generic;
check_dup_generic:
t = OMP_CLAUSE_DECL (c);
@@ -4128,9 +5230,11 @@ finish_omp_clauses (tree clauses)
if (processing_template_decl)
break;
if (DECL_P (t))
- error ("%qD is not a variable in clause %qs", t, name);
+ error ("%qD is not a variable in clause %qs", t,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
else
- error ("%qE is not a variable in clause %qs", t, name);
+ error ("%qE is not a variable in clause %qs", t,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
remove = true;
}
else if (bitmap_bit_p (&generic_head, DECL_UID (t))
@@ -4248,12 +5352,313 @@ finish_omp_clauses (tree clauses)
}
break;
+ case OMP_CLAUSE_SIMDLEN:
+ case OMP_CLAUSE_SAFELEN:
+ t = OMP_CLAUSE_OPERAND (c, 0);
+ if (t == error_mark_node)
+ remove = true;
+ else if (!type_dependent_expression_p (t)
+ && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
+ {
+ error ("%qs length expression must be integral",
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ remove = true;
+ }
+ else
+ {
+ t = mark_rvalue_use (t);
+ t = maybe_constant_value (t);
+ if (!processing_template_decl)
+ {
+ if (TREE_CODE (t) != INTEGER_CST
+ || tree_int_cst_sgn (t) != 1)
+ {
+ error ("%qs length expression must be positive constant"
+ " integer expression",
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ remove = true;
+ }
+ }
+ OMP_CLAUSE_OPERAND (c, 0) = t;
+ }
+ break;
+
+ case OMP_CLAUSE_NUM_TEAMS:
+ t = OMP_CLAUSE_NUM_TEAMS_EXPR (c);
+ if (t == error_mark_node)
+ remove = true;
+ else if (!type_dependent_expression_p (t)
+ && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
+ {
+ error ("%<num_teams%> expression must be integral");
+ remove = true;
+ }
+ else
+ {
+ t = mark_rvalue_use (t);
+ if (!processing_template_decl)
+ t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
+ OMP_CLAUSE_NUM_TEAMS_EXPR (c) = t;
+ }
+ break;
+
+ case OMP_CLAUSE_THREAD_LIMIT:
+ t = OMP_CLAUSE_THREAD_LIMIT_EXPR (c);
+ if (t == error_mark_node)
+ remove = true;
+ else if (!type_dependent_expression_p (t)
+ && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
+ {
+ error ("%<thread_limit%> expression must be integral");
+ remove = true;
+ }
+ else
+ {
+ t = mark_rvalue_use (t);
+ if (!processing_template_decl)
+ t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
+ OMP_CLAUSE_THREAD_LIMIT_EXPR (c) = t;
+ }
+ break;
+
+ case OMP_CLAUSE_DEVICE:
+ t = OMP_CLAUSE_DEVICE_ID (c);
+ if (t == error_mark_node)
+ remove = true;
+ else if (!type_dependent_expression_p (t)
+ && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
+ {
+ error ("%<device%> id must be integral");
+ remove = true;
+ }
+ else
+ {
+ t = mark_rvalue_use (t);
+ if (!processing_template_decl)
+ t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
+ OMP_CLAUSE_DEVICE_ID (c) = t;
+ }
+ break;
+
+ case OMP_CLAUSE_DIST_SCHEDULE:
+ t = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (c);
+ if (t == NULL)
+ ;
+ else if (t == error_mark_node)
+ remove = true;
+ else if (!type_dependent_expression_p (t)
+ && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
+ {
+ error ("%<dist_schedule%> chunk size expression must be "
+ "integral");
+ remove = true;
+ }
+ else
+ {
+ t = mark_rvalue_use (t);
+ if (!processing_template_decl)
+ t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
+ OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (c) = t;
+ }
+ break;
+
+ case OMP_CLAUSE_ALIGNED:
+ t = OMP_CLAUSE_DECL (c);
+ if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL)
+ {
+ if (processing_template_decl)
+ break;
+ if (DECL_P (t))
+ error ("%qD is not a variable in %<aligned%> clause", t);
+ else
+ error ("%qE is not a variable in %<aligned%> clause", t);
+ remove = true;
+ }
+ else if (!type_dependent_expression_p (t)
+ && TREE_CODE (TREE_TYPE (t)) != POINTER_TYPE
+ && TREE_CODE (TREE_TYPE (t)) != ARRAY_TYPE
+ && (TREE_CODE (TREE_TYPE (t)) != REFERENCE_TYPE
+ || (!POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (t)))
+ && (TREE_CODE (TREE_TYPE (TREE_TYPE (t)))
+ != ARRAY_TYPE))))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qE in %<aligned%> clause is neither a pointer nor "
+ "an array nor a reference to pointer or array", t);
+ remove = true;
+ }
+ else if (bitmap_bit_p (&aligned_head, DECL_UID (t)))
+ {
+ error ("%qD appears more than once in %<aligned%> clauses", t);
+ remove = true;
+ }
+ else
+ bitmap_set_bit (&aligned_head, DECL_UID (t));
+ t = OMP_CLAUSE_ALIGNED_ALIGNMENT (c);
+ if (t == error_mark_node)
+ remove = true;
+ else if (t == NULL_TREE)
+ break;
+ else if (!type_dependent_expression_p (t)
+ && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
+ {
+ error ("%<aligned%> clause alignment expression must "
+ "be integral");
+ remove = true;
+ }
+ else
+ {
+ t = mark_rvalue_use (t);
+ t = maybe_constant_value (t);
+ if (!processing_template_decl)
+ {
+ if (TREE_CODE (t) != INTEGER_CST
+ || tree_int_cst_sgn (t) != 1)
+ {
+ error ("%<aligned%> clause alignment expression must be "
+ "positive constant integer expression");
+ remove = true;
+ }
+ }
+ OMP_CLAUSE_ALIGNED_ALIGNMENT (c) = t;
+ }
+ break;
+
+ case OMP_CLAUSE_DEPEND:
+ t = OMP_CLAUSE_DECL (c);
+ if (TREE_CODE (t) == TREE_LIST)
+ {
+ if (handle_omp_array_sections (c))
+ remove = true;
+ break;
+ }
+ if (t == error_mark_node)
+ remove = true;
+ else if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL)
+ {
+ if (processing_template_decl)
+ break;
+ if (DECL_P (t))
+ error ("%qD is not a variable in %<depend%> clause", t);
+ else
+ error ("%qE is not a variable in %<depend%> clause", t);
+ remove = true;
+ }
+ else if (!processing_template_decl
+ && !cxx_mark_addressable (t))
+ remove = true;
+ break;
+
+ case OMP_CLAUSE_MAP:
+ case OMP_CLAUSE_TO:
+ case OMP_CLAUSE_FROM:
+ t = OMP_CLAUSE_DECL (c);
+ if (TREE_CODE (t) == TREE_LIST)
+ {
+ if (handle_omp_array_sections (c))
+ remove = true;
+ else
+ {
+ t = OMP_CLAUSE_DECL (c);
+ if (!cp_omp_mappable_type (TREE_TYPE (t)))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "array section does not have mappable type "
+ "in %qs clause",
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ remove = true;
+ }
+ }
+ break;
+ }
+ if (t == error_mark_node)
+ remove = true;
+ else if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL)
+ {
+ if (processing_template_decl)
+ break;
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
+ && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER)
+ break;
+ if (DECL_P (t))
+ error ("%qD is not a variable in %qs clause", t,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ else
+ error ("%qE is not a variable in %qs clause", t,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ remove = true;
+ }
+ else if (TREE_CODE (t) == VAR_DECL && DECL_THREAD_LOCAL_P (t))
+ {
+ error ("%qD is threadprivate variable in %qs clause", t,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ remove = true;
+ }
+ else if (!processing_template_decl
+ && TREE_CODE (TREE_TYPE (t)) != REFERENCE_TYPE
+ && !cxx_mark_addressable (t))
+ remove = true;
+ else if (!(OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
+ && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER)
+ && !cp_omp_mappable_type ((TREE_CODE (TREE_TYPE (t))
+ == REFERENCE_TYPE)
+ ? TREE_TYPE (TREE_TYPE (t))
+ : TREE_TYPE (t)))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD does not have a mappable type in %qs clause", t,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ remove = true;
+ }
+ else if (bitmap_bit_p (&generic_head, DECL_UID (t)))
+ {
+ if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
+ error ("%qD appears more than once in motion clauses", t);
+ else
+ error ("%qD appears more than once in map clauses", t);
+ remove = true;
+ }
+ else
+ bitmap_set_bit (&generic_head, DECL_UID (t));
+ break;
+
+ case OMP_CLAUSE_UNIFORM:
+ t = OMP_CLAUSE_DECL (c);
+ if (TREE_CODE (t) != PARM_DECL)
+ {
+ if (processing_template_decl)
+ break;
+ if (DECL_P (t))
+ error ("%qD is not an argument in %<uniform%> clause", t);
+ else
+ error ("%qE is not an argument in %<uniform%> clause", t);
+ remove = true;
+ break;
+ }
+ goto check_dup_generic;
+
case OMP_CLAUSE_NOWAIT:
case OMP_CLAUSE_ORDERED:
case OMP_CLAUSE_DEFAULT:
case OMP_CLAUSE_UNTIED:
case OMP_CLAUSE_COLLAPSE:
case OMP_CLAUSE_MERGEABLE:
+ case OMP_CLAUSE_PARALLEL:
+ case OMP_CLAUSE_FOR:
+ case OMP_CLAUSE_SECTIONS:
+ case OMP_CLAUSE_TASKGROUP:
+ case OMP_CLAUSE_PROC_BIND:
+ break;
+
+ case OMP_CLAUSE_INBRANCH:
+ case OMP_CLAUSE_NOTINBRANCH:
+ if (branch_seen)
+ {
+ error ("%<inbranch%> clause is incompatible with "
+ "%<notinbranch%>");
+ remove = true;
+ }
+ branch_seen = true;
break;
default:
@@ -4275,44 +5680,50 @@ finish_omp_clauses (tree clauses)
bool need_copy_ctor = false;
bool need_copy_assignment = false;
bool need_implicitly_determined = false;
+ bool need_dtor = false;
tree type, inner_type;
switch (c_kind)
{
case OMP_CLAUSE_SHARED:
- name = "shared";
need_implicitly_determined = true;
break;
case OMP_CLAUSE_PRIVATE:
- name = "private";
need_complete_non_reference = true;
need_default_ctor = true;
+ need_dtor = true;
need_implicitly_determined = true;
break;
case OMP_CLAUSE_FIRSTPRIVATE:
- name = "firstprivate";
need_complete_non_reference = true;
need_copy_ctor = true;
+ need_dtor = true;
need_implicitly_determined = true;
break;
case OMP_CLAUSE_LASTPRIVATE:
- name = "lastprivate";
need_complete_non_reference = true;
need_copy_assignment = true;
need_implicitly_determined = true;
break;
case OMP_CLAUSE_REDUCTION:
- name = "reduction";
need_implicitly_determined = true;
break;
case OMP_CLAUSE_COPYPRIVATE:
- name = "copyprivate";
need_copy_assignment = true;
break;
case OMP_CLAUSE_COPYIN:
- name = "copyin";
need_copy_assignment = true;
break;
+ case OMP_CLAUSE_NOWAIT:
+ if (copyprivate_seen)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<nowait%> clause must not be used together "
+ "with %<copyprivate%>");
+ *pc = OMP_CLAUSE_CHAIN (c);
+ continue;
+ }
+ /* FALLTHRU */
default:
pc = &OMP_CLAUSE_CHAIN (c);
continue;
@@ -4330,33 +5741,18 @@ finish_omp_clauses (tree clauses)
{
case OMP_CLAUSE_LASTPRIVATE:
if (!bitmap_bit_p (&firstprivate_head, DECL_UID (t)))
- need_default_ctor = true;
+ {
+ need_default_ctor = true;
+ need_dtor = true;
+ }
break;
case OMP_CLAUSE_REDUCTION:
- if (AGGREGATE_TYPE_P (TREE_TYPE (t))
- || POINTER_TYPE_P (TREE_TYPE (t)))
- {
- error ("%qE has invalid type for %<reduction%>", t);
- remove = true;
- }
- else if (FLOAT_TYPE_P (TREE_TYPE (t)))
- {
- enum tree_code r_code = OMP_CLAUSE_REDUCTION_CODE (c);
- switch (r_code)
- {
- case PLUS_EXPR:
- case MULT_EXPR:
- case MINUS_EXPR:
- case MIN_EXPR:
- case MAX_EXPR:
- break;
- default:
- error ("%qE has invalid type for %<reduction(%s)%>",
- t, operator_name_info[r_code].name);
- remove = true;
- }
- }
+ if (finish_omp_reduction_clause (c, &need_default_ctor,
+ &need_dtor))
+ remove = true;
+ else
+ t = OMP_CLAUSE_DECL (c);
break;
case OMP_CLAUSE_COPYIN:
@@ -4379,7 +5775,8 @@ finish_omp_clauses (tree clauses)
else if (TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE
&& need_complete_non_reference)
{
- error ("%qE has reference type for %qs", t, name);
+ error ("%qE has reference type for %qs", t,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
remove = true;
}
}
@@ -4409,7 +5806,7 @@ finish_omp_clauses (tree clauses)
if (share_name)
{
error ("%qE is predetermined %qs for %qs",
- t, share_name, name);
+ t, share_name, omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
remove = true;
}
}
@@ -4419,15 +5816,21 @@ finish_omp_clauses (tree clauses)
while (TREE_CODE (inner_type) == ARRAY_TYPE)
inner_type = TREE_TYPE (inner_type);
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+ && TREE_CODE (inner_type) == REFERENCE_TYPE)
+ inner_type = TREE_TYPE (inner_type);
+
/* Check for special function availability by building a call to one.
Save the results, because later we won't be in the right context
for making these queries. */
if (CLASS_TYPE_P (inner_type)
&& COMPLETE_TYPE_P (inner_type)
- && (need_default_ctor || need_copy_ctor || need_copy_assignment)
+ && (need_default_ctor || need_copy_ctor
+ || need_copy_assignment || need_dtor)
&& !type_dependent_expression_p (t)
&& cxx_omp_create_clause_info (c, inner_type, need_default_ctor,
- need_copy_ctor, need_copy_assignment))
+ need_copy_ctor, need_copy_assignment,
+ need_dtor))
remove = true;
if (remove)
@@ -4808,8 +6211,8 @@ handle_omp_for_class_iterator (int i, location_t locus, tree declv, tree initv,
sk_omp scope. */
tree
-finish_omp_for (location_t locus, tree declv, tree initv, tree condv,
- tree incrv, tree body, tree pre_body, tree clauses)
+finish_omp_for (location_t locus, enum tree_code code, tree declv, tree initv,
+ tree condv, tree incrv, tree body, tree pre_body, tree clauses)
{
tree omp_for = NULL, orig_incr = NULL;
tree decl, init, cond, incr;
@@ -4878,7 +6281,7 @@ finish_omp_for (location_t locus, tree declv, tree initv, tree condv,
{
tree stmt;
- stmt = make_node (OMP_FOR);
+ stmt = make_node (code);
for (i = 0; i < TREE_VEC_LENGTH (declv); i++)
{
@@ -4936,6 +6339,12 @@ finish_omp_for (location_t locus, tree declv, tree initv, tree condv,
if (CLASS_TYPE_P (TREE_TYPE (decl)))
{
+ if (code == OMP_SIMD)
+ {
+ error_at (elocus, "%<#pragma omp simd%> used with class "
+ "iteration variable %qE", decl);
+ return NULL;
+ }
if (handle_omp_for_class_iterator (i, locus, declv, initv, condv,
incrv, &body, &pre_body, clauses))
return NULL;
@@ -4990,7 +6399,7 @@ finish_omp_for (location_t locus, tree declv, tree initv, tree condv,
if (IS_EMPTY_STMT (pre_body))
pre_body = NULL;
- omp_for = c_finish_omp_for (locus, declv, initv, condv, incrv,
+ omp_for = c_finish_omp_for (locus, code, declv, initv, condv, incrv,
body, pre_body);
if (omp_for == NULL)
@@ -5035,7 +6444,7 @@ finish_omp_for (location_t locus, tree declv, tree initv, tree condv,
void
finish_omp_atomic (enum tree_code code, enum tree_code opcode, tree lhs,
- tree rhs, tree v, tree lhs1, tree rhs1)
+ tree rhs, tree v, tree lhs1, tree rhs1, bool seq_cst)
{
tree orig_lhs;
tree orig_rhs;
@@ -5077,8 +6486,36 @@ finish_omp_atomic (enum tree_code code, enum tree_code opcode, tree lhs,
}
if (!dependent_p)
{
+ bool swapped = false;
+ if (rhs1 && cp_tree_equal (lhs, rhs))
+ {
+ tree tem = rhs;
+ rhs = rhs1;
+ rhs1 = tem;
+ swapped = !commutative_tree_code (opcode);
+ }
+ if (rhs1 && !cp_tree_equal (lhs, rhs1))
+ {
+ if (code == OMP_ATOMIC)
+ error ("%<#pragma omp atomic update%> uses two different "
+ "expressions for memory");
+ else
+ error ("%<#pragma omp atomic capture%> uses two different "
+ "expressions for memory");
+ return;
+ }
+ if (lhs1 && !cp_tree_equal (lhs, lhs1))
+ {
+ if (code == OMP_ATOMIC)
+ error ("%<#pragma omp atomic update%> uses two different "
+ "expressions for memory");
+ else
+ error ("%<#pragma omp atomic capture%> uses two different "
+ "expressions for memory");
+ return;
+ }
stmt = c_finish_omp_atomic (input_location, code, opcode, lhs, rhs,
- v, lhs1, rhs1);
+ v, lhs1, rhs1, swapped, seq_cst);
if (stmt == error_mark_node)
return;
}
@@ -5088,6 +6525,7 @@ finish_omp_atomic (enum tree_code code, enum tree_code opcode, tree lhs,
{
stmt = build_min_nt_loc (EXPR_LOCATION (orig_lhs),
OMP_ATOMIC_READ, orig_lhs);
+ OMP_ATOMIC_SEQ_CST (stmt) = seq_cst;
stmt = build2 (MODIFY_EXPR, void_type_node, orig_v, stmt);
}
else
@@ -5103,10 +6541,12 @@ finish_omp_atomic (enum tree_code code, enum tree_code opcode, tree lhs,
{
stmt = build_min_nt_loc (EXPR_LOCATION (orig_lhs1),
code, orig_lhs1, stmt);
+ OMP_ATOMIC_SEQ_CST (stmt) = seq_cst;
stmt = build2 (MODIFY_EXPR, void_type_node, orig_v, stmt);
}
}
stmt = build2 (OMP_ATOMIC, void_type_node, integer_zero_node, stmt);
+ OMP_ATOMIC_SEQ_CST (stmt) = seq_cst;
}
add_stmt (stmt);
}
@@ -5150,6 +6590,69 @@ finish_omp_taskyield (void)
release_tree_vector (vec);
finish_expr_stmt (stmt);
}
+
+void
+finish_omp_cancel (tree clauses)
+{
+ tree fn = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
+ int mask = 0;
+ if (find_omp_clause (clauses, OMP_CLAUSE_PARALLEL))
+ mask = 1;
+ else if (find_omp_clause (clauses, OMP_CLAUSE_FOR))
+ mask = 2;
+ else if (find_omp_clause (clauses, OMP_CLAUSE_SECTIONS))
+ mask = 4;
+ else if (find_omp_clause (clauses, OMP_CLAUSE_TASKGROUP))
+ mask = 8;
+ else
+ {
+ error ("%<#pragma omp cancel must specify one of "
+ "%<parallel%>, %<for%>, %<sections%> or %<taskgroup%> clauses");
+ return;
+ }
+ vec<tree, va_gc> *vec = make_tree_vector ();
+ tree ifc = find_omp_clause (clauses, OMP_CLAUSE_IF);
+ if (ifc != NULL_TREE)
+ {
+ tree type = TREE_TYPE (OMP_CLAUSE_IF_EXPR (ifc));
+ ifc = fold_build2_loc (OMP_CLAUSE_LOCATION (ifc), NE_EXPR,
+ boolean_type_node, OMP_CLAUSE_IF_EXPR (ifc),
+ build_zero_cst (type));
+ }
+ else
+ ifc = boolean_true_node;
+ vec->quick_push (build_int_cst (integer_type_node, mask));
+ vec->quick_push (ifc);
+ tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
+ release_tree_vector (vec);
+ finish_expr_stmt (stmt);
+}
+
+void
+finish_omp_cancellation_point (tree clauses)
+{
+ tree fn = builtin_decl_explicit (BUILT_IN_GOMP_CANCELLATION_POINT);
+ int mask = 0;
+ if (find_omp_clause (clauses, OMP_CLAUSE_PARALLEL))
+ mask = 1;
+ else if (find_omp_clause (clauses, OMP_CLAUSE_FOR))
+ mask = 2;
+ else if (find_omp_clause (clauses, OMP_CLAUSE_SECTIONS))
+ mask = 4;
+ else if (find_omp_clause (clauses, OMP_CLAUSE_TASKGROUP))
+ mask = 8;
+ else
+ {
+ error ("%<#pragma omp cancellation point must specify one of "
+ "%<parallel%>, %<for%>, %<sections%> or %<taskgroup%> clauses");
+ return;
+ }
+ vec<tree, va_gc> *vec
+ = make_tree_vector_single (build_int_cst (integer_type_node, mask));
+ tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
+ release_tree_vector (vec);
+ finish_expr_stmt (stmt);
+}
/* Begin a __transaction_atomic or __transaction_relaxed statement.
If PCOMPOUND is non-null, this is for a function-transaction-block, and we
@@ -5199,7 +6702,9 @@ finish_transaction_stmt (tree stmt, tree compound_stmt, int flags, tree noex)
{
tree body = build_must_not_throw_expr (TRANSACTION_EXPR_BODY (stmt),
noex);
- SET_EXPR_LOCATION (body, EXPR_LOCATION (TRANSACTION_EXPR_BODY (stmt)));
+ /* This may not be true when the STATEMENT_LIST is empty. */
+ if (EXPR_P (body))
+ SET_EXPR_LOCATION (body, EXPR_LOCATION (TRANSACTION_EXPR_BODY (stmt)));
TREE_SIDE_EFFECTS (body) = 1;
TRANSACTION_EXPR_BODY (stmt) = body;
}
@@ -5219,7 +6724,8 @@ build_transaction_expr (location_t loc, tree expr, int flags, tree noex)
if (noex)
{
expr = build_must_not_throw_expr (expr, noex);
- SET_EXPR_LOCATION (expr, loc);
+ if (EXPR_P (expr))
+ SET_EXPR_LOCATION (expr, loc);
TREE_SIDE_EFFECTS (expr) = 1;
}
ret = build1 (TRANSACTION_EXPR, TREE_TYPE (expr), expr);
@@ -5933,8 +7439,7 @@ build_anon_member_initialization (tree member, tree init,
to build up the initializer from the outside in so that we can reuse
previously built CONSTRUCTORs if this is, say, the second field in an
anonymous struct. So we use a vec as a stack. */
- vec<tree> fields;
- fields.create (2);
+ stack_vec<tree, 2> fields;
do
{
fields.safe_push (TREE_OPERAND (member, 1));
@@ -5966,7 +7471,6 @@ build_anon_member_initialization (tree member, tree init,
/* Now we're at the innermost field, the one that isn't an anonymous
aggregate. Add its initializer to the CONSTRUCTOR and we're done. */
gcc_assert (fields.is_empty());
- fields.release ();
CONSTRUCTOR_APPEND_ELT (*vec, field, init);
return true;
@@ -6804,12 +8308,18 @@ cxx_eval_call_expression (const constexpr_call *old_call, tree t,
return t;
}
- /* Shortcut trivial copy constructor/op=. */
- if (call_expr_nargs (t) == 2 && trivial_fn_p (fun))
+ /* Shortcut trivial constructor/op=. */
+ if (trivial_fn_p (fun))
{
- tree arg = convert_from_reference (get_nth_callarg (t, 1));
- return cxx_eval_constant_expression (old_call, arg, allow_non_constant,
- addr, non_constant_p, overflow_p);
+ if (call_expr_nargs (t) == 2)
+ {
+ tree arg = convert_from_reference (get_nth_callarg (t, 1));
+ return cxx_eval_constant_expression (old_call, arg, allow_non_constant,
+ addr, non_constant_p, overflow_p);
+ }
+ else if (TREE_CODE (t) == AGGR_INIT_EXPR
+ && AGGR_INIT_ZERO_FIRST (t))
+ return build_zero_init (DECL_CONTEXT (fun), NULL_TREE, false);
}
/* If in direct recursive call, optimize definition search. */
@@ -8192,7 +9702,7 @@ cxx_eval_constant_expression (const constexpr_call *call, tree t,
default:
internal_error ("unexpected expression %qE of kind %s", t,
- tree_code_name[TREE_CODE (t)]);
+ get_tree_code_name (TREE_CODE (t)));
*non_constant_p = true;
break;
}
@@ -8420,6 +9930,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
case OVERLOAD:
case TEMPLATE_ID_EXPR:
case LABEL_DECL:
+ case LABEL_EXPR:
case CONST_DECL:
case SIZEOF_EXPR:
case ALIGNOF_EXPR:
@@ -8952,7 +10463,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
if (objc_is_property_ref (t))
return false;
- sorry ("unexpected AST of kind %s", tree_code_name[TREE_CODE (t)]);
+ sorry ("unexpected AST of kind %s", get_tree_code_name (TREE_CODE (t)));
gcc_unreachable();
return false;
}
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 63ec7fa7266..3ac03480620 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -3983,8 +3983,8 @@ cp_fix_function_decl_p (tree decl)
/* Don't fix same_body aliases. Although they don't have their own
CFG, they share it with what they alias to. */
- if (!node || !node->symbol.alias
- || !vec_safe_length (node->symbol.ref_list.references))
+ if (!node || !node->alias
+ || !vec_safe_length (node->ref_list.references))
return true;
}
diff --git a/gcc/cp/type-utils.h b/gcc/cp/type-utils.h
index 3e82ca4f957..2febce76075 100644
--- a/gcc/cp/type-utils.h
+++ b/gcc/cp/type-utils.h
@@ -47,7 +47,7 @@ find_type_usage (tree t, bool (*pred) (const_tree))
if (TYPE_PTRMEMFUNC_P (t))
return find_type_usage
- (TREE_TYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (t))), pred);
+ (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (t)), pred);
return NULL_TREE;
}
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index bcb87825a1e..bff7f17780f 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -7779,7 +7779,7 @@ build_ptrmemfunc (tree type, tree pfn, int force, bool c_cast_p,
/* Handle null pointer to member function conversions. */
if (null_ptr_cst_p (pfn))
{
- pfn = build_c_cast (input_location, type, pfn);
+ pfn = cp_build_c_cast (type, pfn, complain);
return build_ptrmemfunc1 (to_type,
integer_zero_node,
pfn);
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index 8882816666c..9da8e3de844 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -640,12 +640,13 @@ split_nonconstant_init_1 (tree dest, tree init)
code = build_stmt (input_location, EXPR_STMT, code);
code = maybe_cleanup_point_expr_void (code);
add_stmt (code);
- if (!TYPE_HAS_TRIVIAL_DESTRUCTOR (inner_type))
+ if (type_build_dtor_call (inner_type))
{
code = (build_special_member_call
(sub, complete_dtor_identifier, NULL, inner_type,
LOOKUP_NORMAL, tf_warning_or_error));
- finish_eh_cleanup (code);
+ if (!TYPE_HAS_TRIVIAL_DESTRUCTOR (inner_type))
+ finish_eh_cleanup (code);
}
num_split_elts++;
@@ -774,7 +775,6 @@ store_init_value (tree decl, tree init, vec<tree, va_gc>** cleanups, int flags)
{
bool const_init;
value = fold_non_dependent_expr (value);
- value = maybe_constant_init (value);
if (DECL_DECLARED_CONSTEXPR_P (decl)
|| DECL_IN_AGGR_P (decl))
{
@@ -785,6 +785,7 @@ store_init_value (tree decl, tree init, vec<tree, va_gc>** cleanups, int flags)
else
value = cxx_constant_value (value);
}
+ value = maybe_constant_init (value);
const_init = (reduced_constant_expression_p (value)
|| error_operand_p (value));
DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = const_init;
@@ -833,7 +834,8 @@ check_narrowing (tree type, tree init)
&& TREE_CODE (type) == COMPLEX_TYPE)
{
tree elttype = TREE_TYPE (type);
- check_narrowing (elttype, CONSTRUCTOR_ELT (init, 0)->value);
+ if (CONSTRUCTOR_NELTS (init) > 0)
+ check_narrowing (elttype, CONSTRUCTOR_ELT (init, 0)->value);
if (CONSTRUCTOR_NELTS (init) > 1)
check_narrowing (elttype, CONSTRUCTOR_ELT (init, 1)->value);
return;
@@ -1757,7 +1759,7 @@ build_functional_cast (tree exp, tree parms, tsubst_flags_t complain)
tree type;
vec<tree, va_gc> *parmvec;
- if (exp == error_mark_node || parms == error_mark_node)
+ if (error_operand_p (exp) || parms == error_mark_node)
return error_mark_node;
if (TREE_CODE (exp) == TYPE_DECL)
diff --git a/gcc/cppbuiltin.c b/gcc/cppbuiltin.c
index 2ceccdcce2b..cd74e2349c4 100644
--- a/gcc/cppbuiltin.c
+++ b/gcc/cppbuiltin.c
@@ -105,6 +105,8 @@ define_builtin_macros_for_compilation_flags (cpp_reader *pfile)
cpp_define_formatted (pfile, "__FINITE_MATH_ONLY__=%d",
flag_finite_math_only);
+ if (flag_enable_cilkplus)
+ cpp_define (pfile, "__cilk=200");
}
diff --git a/gcc/cprop.c b/gcc/cprop.c
index 3518fd839ce..358fca9171a 100644
--- a/gcc/cprop.c
+++ b/gcc/cprop.c
@@ -246,7 +246,8 @@ insert_set_in_table (rtx dest, rtx src, rtx insn, struct hash_table_d *table,
/* Record bitmap_index of the implicit set in implicit_set_indexes. */
if (implicit)
- implicit_set_indexes[BLOCK_FOR_INSN(insn)->index] = cur_expr->bitmap_index;
+ implicit_set_indexes[BLOCK_FOR_INSN (insn)->index]
+ = cur_expr->bitmap_index;
}
/* Determine whether the rtx X should be treated as a constant for CPROP.
@@ -1402,9 +1403,9 @@ find_implicit_sets (void)
implicit_sets[dest->index] = new_rtx;
if (dump_file)
{
- fprintf(dump_file, "Implicit set of reg %d in ",
- REGNO (XEXP (cond, 0)));
- fprintf(dump_file, "basic block %d\n", dest->index);
+ fprintf (dump_file, "Implicit set of reg %d in ",
+ REGNO (XEXP (cond, 0)));
+ fprintf (dump_file, "basic block %d\n", dest->index);
}
count++;
}
@@ -1934,12 +1935,12 @@ const pass_data pass_data_rtl_cprop =
class pass_rtl_cprop : public rtl_opt_pass
{
public:
- pass_rtl_cprop(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_rtl_cprop, ctxt)
+ pass_rtl_cprop (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_rtl_cprop, ctxt)
{}
/* opt_pass methods: */
- opt_pass * clone () { return new pass_rtl_cprop (ctxt_); }
+ opt_pass * clone () { return new pass_rtl_cprop (m_ctxt); }
bool gate () { return gate_rtl_cprop (); }
unsigned int execute () { return execute_rtl_cprop (); }
diff --git a/gcc/cse.c b/gcc/cse.c
index 664a963f1ac..43fa1e8191f 100644
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -468,7 +468,7 @@ struct table_elt
a cost of 2. Aside from these special cases, call `rtx_cost'. */
#define CHEAP_REGNO(N) \
- (REGNO_PTR_FRAME_P(N) \
+ (REGNO_PTR_FRAME_P (N) \
|| (HARD_REGISTER_NUM_P (N) \
&& FIXED_REGNO_P (N) && REGNO_REG_CLASS (N) != NO_REGS))
@@ -4839,7 +4839,7 @@ cse_insn (rtx insn)
/* Set what we are trying to extend and the operation it might
have been extended with. */
- memset (memory_extend_rtx, 0, sizeof(*memory_extend_rtx));
+ memset (memory_extend_rtx, 0, sizeof (*memory_extend_rtx));
PUT_CODE (memory_extend_rtx, LOAD_EXTEND_OP (mode));
XEXP (memory_extend_rtx, 0) = src;
@@ -6068,9 +6068,12 @@ cse_process_notes_1 (rtx x, rtx object, bool *changed)
return x;
case EXPR_LIST:
- case INSN_LIST:
if (REG_NOTE_KIND (x) == REG_EQUAL)
XEXP (x, 0) = cse_process_notes (XEXP (x, 0), NULL_RTX, changed);
+ /* Fall through. */
+
+ case INSN_LIST:
+ case INT_LIST:
if (XEXP (x, 1))
XEXP (x, 1) = cse_process_notes (XEXP (x, 1), NULL_RTX, changed);
return x;
@@ -6736,6 +6739,7 @@ count_reg_usage (rtx x, int *counts, rtx dest, int incr)
return;
case INSN_LIST:
+ case INT_LIST:
gcc_unreachable ();
default:
@@ -7475,8 +7479,8 @@ const pass_data pass_data_cse =
class pass_cse : public rtl_opt_pass
{
public:
- pass_cse(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_cse, ctxt)
+ pass_cse (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_cse, ctxt)
{}
/* opt_pass methods: */
@@ -7555,8 +7559,8 @@ const pass_data pass_data_cse2 =
class pass_cse2 : public rtl_opt_pass
{
public:
- pass_cse2(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_cse2, ctxt)
+ pass_cse2 (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_cse2, ctxt)
{}
/* opt_pass methods: */
@@ -7633,8 +7637,8 @@ const pass_data pass_data_cse_after_global_opts =
class pass_cse_after_global_opts : public rtl_opt_pass
{
public:
- pass_cse_after_global_opts(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_cse_after_global_opts, ctxt)
+ pass_cse_after_global_opts (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_cse_after_global_opts, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/cselib.c b/gcc/cselib.c
index c3431af1246..e201f5e7c49 100644
--- a/gcc/cselib.c
+++ b/gcc/cselib.c
@@ -259,10 +259,10 @@ void (*cselib_record_sets_hook) (rtx insn, struct cselib_set *sets,
int n_sets);
#define PRESERVED_VALUE_P(RTX) \
- (RTL_FLAG_CHECK1("PRESERVED_VALUE_P", (RTX), VALUE)->unchanging)
+ (RTL_FLAG_CHECK1 ("PRESERVED_VALUE_P", (RTX), VALUE)->unchanging)
#define SP_BASED_VALUE_P(RTX) \
- (RTL_FLAG_CHECK1("SP_BASED_VALUE_P", (RTX), VALUE)->jump)
+ (RTL_FLAG_CHECK1 ("SP_BASED_VALUE_P", (RTX), VALUE)->jump)
diff --git a/gcc/data-streamer-in.c b/gcc/data-streamer-in.c
index 93fe2ff4c3b..84242486941 100644
--- a/gcc/data-streamer-in.c
+++ b/gcc/data-streamer-in.c
@@ -24,6 +24,8 @@ along with GCC; see the file COPYING3. If not see
#include "system.h"
#include "coretypes.h"
#include "diagnostic.h"
+#include "tree.h"
+#include "gimple.h"
#include "data-streamer.h"
/* Read a string from the string table in DATA_IN using input block
diff --git a/gcc/data-streamer-out.c b/gcc/data-streamer-out.c
index 247ff636e49..fbbe0db2759 100644
--- a/gcc/data-streamer-out.c
+++ b/gcc/data-streamer-out.c
@@ -23,6 +23,8 @@ along with GCC; see the file COPYING3. If not see
#include "config.h"
#include "system.h"
#include "coretypes.h"
+#include "tree.h"
+#include "gimple.h"
#include "data-streamer.h"
/* Return index used to reference STRING of LEN characters in the string table
diff --git a/gcc/data-streamer.c b/gcc/data-streamer.c
index cbd1cb9f9dd..675b5093314 100644
--- a/gcc/data-streamer.c
+++ b/gcc/data-streamer.c
@@ -22,6 +22,8 @@ along with GCC; see the file COPYING3. If not see
#include "config.h"
#include "system.h"
#include "coretypes.h"
+#include "tree.h"
+#include "gimple.h"
#include "data-streamer.h"
/* Pack WORK into BP in a variant of uleb format. */
diff --git a/gcc/dbgcnt.def b/gcc/dbgcnt.def
index 45b8eed85af..6f86253a6ed 100644
--- a/gcc/dbgcnt.def
+++ b/gcc/dbgcnt.def
@@ -188,3 +188,4 @@ DEBUG_COUNTER (store_motion)
DEBUG_COUNTER (split_for_sched2)
DEBUG_COUNTER (tail_call)
DEBUG_COUNTER (ira_move)
+DEBUG_COUNTER (registered_jump_thread)
diff --git a/gcc/dbxout.c b/gcc/dbxout.c
index 1cc5d524205..84f765efe5e 100644
--- a/gcc/dbxout.c
+++ b/gcc/dbxout.c
@@ -636,7 +636,7 @@ dbxout_begin_complex_stabs_noforcetext (void)
#define stabstr_C(chr) obstack_1grow (&stabstr_ob, chr)
/* Add STR, a normal C string, to the string being built. */
-#define stabstr_S(str) obstack_grow (&stabstr_ob, str, strlen(str))
+#define stabstr_S(str) obstack_grow (&stabstr_ob, str, strlen (str))
/* Add the text of ID, an IDENTIFIER_NODE, to the string being built. */
#define stabstr_I(id) obstack_grow (&stabstr_ob, \
@@ -2434,7 +2434,7 @@ dbxout_class_name_qualifiers (tree decl)
tree context = decl_type_context (decl);
if (context != NULL_TREE
- && TREE_CODE(context) == RECORD_TYPE
+ && TREE_CODE (context) == RECORD_TYPE
&& TYPE_NAME (context) != 0
&& (TREE_CODE (TYPE_NAME (context)) == IDENTIFIER_NODE
|| (DECL_NAME (TYPE_NAME (context)) != 0)))
@@ -2480,7 +2480,7 @@ dbxout_expand_expr (tree expr)
return NULL, otherwise stabs might reference an undefined
symbol. */
struct varpool_node *node = varpool_get_node (expr);
- if (!node || !node->symbol.definition)
+ if (!node || !node->definition)
return NULL;
}
/* FALLTHRU */
@@ -3302,8 +3302,8 @@ dbxout_common_check (tree decl, int *value)
for thread-local symbols. Can be handled via same mechanism as used
in dwarf2out.c. */
if (TREE_CODE (decl) != VAR_DECL
- || !TREE_STATIC(decl)
- || !DECL_HAS_VALUE_EXPR_P(decl)
+ || !TREE_STATIC (decl)
+ || !DECL_HAS_VALUE_EXPR_P (decl)
|| DECL_THREAD_LOCAL_P (decl)
|| !is_fortran ())
return NULL;
@@ -3337,21 +3337,21 @@ dbxout_common_check (tree decl, int *value)
if (CONST_INT_P (XEXP (sym_addr, 0)))
{
name =
- targetm.strip_name_encoding(XSTR (XEXP (sym_addr, 1), 0));
+ targetm.strip_name_encoding (XSTR (XEXP (sym_addr, 1), 0));
*value = INTVAL (XEXP (sym_addr, 0));
cdecl = SYMBOL_REF_DECL (XEXP (sym_addr, 1));
}
else
{
name =
- targetm.strip_name_encoding(XSTR (XEXP (sym_addr, 0), 0));
+ targetm.strip_name_encoding (XSTR (XEXP (sym_addr, 0), 0));
*value = INTVAL (XEXP (sym_addr, 1));
cdecl = SYMBOL_REF_DECL (XEXP (sym_addr, 0));
}
break;
case SYMBOL_REF:
- name = targetm.strip_name_encoding(XSTR (sym_addr, 0));
+ name = targetm.strip_name_encoding (XSTR (sym_addr, 0));
*value = 0;
cdecl = SYMBOL_REF_DECL (sym_addr);
break;
@@ -3364,7 +3364,7 @@ dbxout_common_check (tree decl, int *value)
/* Check area common symbol is offset into. If this is not public, then
it is not a symbol in a common block. It must be a .lcomm symbol, not
a .comm symbol. */
- if (cdecl == NULL || !TREE_PUBLIC(cdecl))
+ if (cdecl == NULL || !TREE_PUBLIC (cdecl))
name = NULL;
}
else
diff --git a/gcc/dce.c b/gcc/dce.c
index fa22316b5cc..5c11cbeef0d 100644
--- a/gcc/dce.c
+++ b/gcc/dce.c
@@ -806,8 +806,8 @@ const pass_data pass_data_ud_rtl_dce =
class pass_ud_rtl_dce : public rtl_opt_pass
{
public:
- pass_ud_rtl_dce(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_ud_rtl_dce, ctxt)
+ pass_ud_rtl_dce (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_ud_rtl_dce, ctxt)
{}
/* opt_pass methods: */
@@ -1239,8 +1239,8 @@ const pass_data pass_data_fast_rtl_dce =
class pass_fast_rtl_dce : public rtl_opt_pass
{
public:
- pass_fast_rtl_dce(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_fast_rtl_dce, ctxt)
+ pass_fast_rtl_dce (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_fast_rtl_dce, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/defaults.h b/gcc/defaults.h
index 3fa105d113d..37e8a08ac5a 100644
--- a/gcc/defaults.h
+++ b/gcc/defaults.h
@@ -76,7 +76,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
int c = p[i]; \
if (c == '\"' || c == '\\') \
putc ('\\', asm_out_file); \
- if (ISPRINT(c)) \
+ if (ISPRINT (c)) \
putc (c, asm_out_file); \
else \
{ \
@@ -86,7 +86,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
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])) \
+ if (i < thissize - 1 && ISDIGIT (p[i + 1])) \
fprintf (asm_out_file, "\"\n\t.ascii \""); \
} \
} \
@@ -351,7 +351,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
/* 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_IN_DATA_SECTION)
+ && !defined (EH_FRAME_IN_DATA_SECTION)
#ifndef EH_FRAME_SECTION_NAME
#define EH_FRAME_SECTION_NAME ".eh_frame"
#endif
@@ -1278,7 +1278,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
SET_RATIO or more simple move-instruction sequences, we will do a movmem
or libcall instead. */
#ifndef SET_RATIO
-#define SET_RATIO(speed) MOVE_RATIO(speed)
+#define SET_RATIO(speed) MOVE_RATIO (speed)
#endif
/* Supply a default definition for FUNCTION_ARG_PADDING:
diff --git a/gcc/df-core.c b/gcc/df-core.c
index 95df1c1b056..deea7551053 100644
--- a/gcc/df-core.c
+++ b/gcc/df-core.c
@@ -549,7 +549,7 @@ df_set_blocks (bitmap blocks)
{
basic_block bb;
bitmap_initialize (&blocks_to_reset, &df_bitmap_obstack);
- FOR_ALL_BB(bb)
+ FOR_ALL_BB (bb)
{
bitmap_set_bit (&blocks_to_reset, bb->index);
}
@@ -766,8 +766,8 @@ const pass_data pass_data_df_initialize_opt =
class pass_df_initialize_opt : public rtl_opt_pass
{
public:
- pass_df_initialize_opt(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_df_initialize_opt, ctxt)
+ pass_df_initialize_opt (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_df_initialize_opt, ctxt)
{}
/* opt_pass methods: */
@@ -812,8 +812,8 @@ const pass_data pass_data_df_initialize_no_opt =
class pass_df_initialize_no_opt : public rtl_opt_pass
{
public:
- pass_df_initialize_no_opt(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_df_initialize_no_opt, ctxt)
+ pass_df_initialize_no_opt (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_df_initialize_no_opt, ctxt)
{}
/* opt_pass methods: */
@@ -878,8 +878,8 @@ const pass_data pass_data_df_finish =
class pass_df_finish : public rtl_opt_pass
{
public:
- pass_df_finish(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_df_finish, ctxt)
+ pass_df_finish (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_df_finish, ctxt)
{}
/* opt_pass methods: */
@@ -2078,7 +2078,7 @@ df_dump_start (FILE *file)
{
df_dump_problem_function fun = dflow->problem->dump_start_fun;
if (fun)
- fun(file);
+ fun (file);
}
}
}
diff --git a/gcc/df-problems.c b/gcc/df-problems.c
index e647b5ad0a0..59fc2f64444 100644
--- a/gcc/df-problems.c
+++ b/gcc/df-problems.c
@@ -326,7 +326,7 @@ df_rd_bb_local_compute_process_def (struct df_rd_bb_info *bb_info,
if (n_defs > DF_SPARSE_THRESHOLD)
{
bitmap_set_bit (&bb_info->sparse_kill, regno);
- bitmap_clear_range(&bb_info->gen, begin, n_defs);
+ bitmap_clear_range (&bb_info->gen, begin, n_defs);
}
else
{
@@ -594,7 +594,7 @@ df_rd_start_dump (FILE *file)
{
struct df_rd_problem_data *problem_data
= (struct df_rd_problem_data *) df_rd->problem_data;
- unsigned int m = DF_REG_SIZE(df);
+ unsigned int m = DF_REG_SIZE (df);
unsigned int regno;
if (!df_rd->block_info)
@@ -622,7 +622,7 @@ df_rd_dump_defs_set (bitmap defs_set, const char *prefix, FILE *file)
{
bitmap_head tmp;
unsigned int regno;
- unsigned int m = DF_REG_SIZE(df);
+ unsigned int m = DF_REG_SIZE (df);
bool first_reg = true;
fprintf (file, "%s\t(%d) ", prefix, (int) bitmap_count_bits (defs_set));
diff --git a/gcc/df-scan.c b/gcc/df-scan.c
index 3a8e9ca7ec4..aace96d4536 100644
--- a/gcc/df-scan.c
+++ b/gcc/df-scan.c
@@ -86,10 +86,10 @@ static HARD_REG_SET elim_reg_set;
struct df_collection_rec
{
- vec<df_ref, va_stack> def_vec;
- vec<df_ref, va_stack> use_vec;
- vec<df_ref, va_stack> eq_use_vec;
- vec<df_mw_hardreg_ptr, va_stack> mw_vec;
+ stack_vec<df_ref, 128> def_vec;
+ stack_vec<df_ref, 32> use_vec;
+ stack_vec<df_ref, 32> eq_use_vec;
+ stack_vec<df_mw_hardreg_ptr, 32> mw_vec;
};
static df_ref df_null_ref_rec[1];
@@ -131,7 +131,7 @@ static void df_ref_chain_delete_du_chain (df_ref *);
static void df_ref_chain_delete (df_ref *);
static void df_refs_add_to_chains (struct df_collection_rec *,
- basic_block, rtx);
+ basic_block, rtx, unsigned int);
static bool df_insn_refs_verify (struct df_collection_rec *, basic_block, rtx, bool);
static void df_entry_block_defs_collect (struct df_collection_rec *, bitmap);
@@ -153,6 +153,14 @@ static void df_insn_info_delete (unsigned int);
and epilogue to save and restore registers as needed. */
static bool regs_ever_live[FIRST_PSEUDO_REGISTER];
+
+/* Flags used to tell df_refs_add_to_chains() which vectors it should copy. */
+static const unsigned int copy_defs = 0x1;
+static const unsigned int copy_uses = 0x2;
+static const unsigned int copy_eq_uses = 0x4;
+static const unsigned int copy_mw = 0x8;
+static const unsigned int copy_all = copy_defs | copy_uses | copy_eq_uses
+| copy_mw;
/*----------------------------------------------------------------------------
SCANNING DATAFLOW PROBLEM
@@ -191,9 +199,9 @@ df_scan_free_internal (void)
/* The vectors that hold the refs are not pool allocated because
they come in many sizes. This makes them impossible to delete
all at once. */
- for (i = 0; i < DF_INSN_SIZE(); i++)
+ for (i = 0; i < DF_INSN_SIZE (); i++)
{
- struct df_insn_info *insn_info = DF_INSN_UID_GET(i);
+ struct df_insn_info *insn_info = DF_INSN_UID_GET (i);
/* Skip the insns that have no insn_info or have been
deleted. */
if (insn_info)
@@ -233,7 +241,7 @@ df_scan_free_internal (void)
free (df->eq_use_regs);
df->eq_use_regs = NULL;
df->regs_size = 0;
- DF_REG_SIZE(df) = 0;
+ DF_REG_SIZE (df) = 0;
free (df->insns);
df->insns = NULL;
@@ -1268,11 +1276,6 @@ df_insn_rescan (rtx insn)
return false;
}
- vec_stack_alloc (df_ref, collection_rec.def_vec, 128);
- vec_stack_alloc (df_ref, collection_rec.use_vec, 32);
- vec_stack_alloc (df_ref, collection_rec.eq_use_vec, 32);
- vec_stack_alloc (df_mw_hardreg_ptr, collection_rec.mw_vec, 32);
-
bitmap_clear_bit (&df->insns_to_delete, uid);
bitmap_clear_bit (&df->insns_to_rescan, uid);
bitmap_clear_bit (&df->insns_to_notes_rescan, uid);
@@ -1306,15 +1309,10 @@ df_insn_rescan (rtx insn)
fprintf (dump_file, "scanning new insn with uid = %d.\n", uid);
}
- df_refs_add_to_chains (&collection_rec, bb, insn);
+ df_refs_add_to_chains (&collection_rec, bb, insn, copy_all);
if (!DEBUG_INSN_P (insn))
df_set_bb_dirty (bb);
- collection_rec.def_vec.release ();
- collection_rec.use_vec.release ();
- collection_rec.eq_use_vec.release ();
- collection_rec.mw_vec.release ();
-
return true;
}
@@ -2188,7 +2186,7 @@ df_notes_rescan (rtx insn)
df_grow_bb_info (df_scan);
df_grow_reg_info ();
- insn_info = DF_INSN_UID_SAFE_GET (INSN_UID(insn));
+ insn_info = DF_INSN_UID_SAFE_GET (INSN_UID (insn));
/* The client has deferred rescanning. */
if (df->changeable_flags & DF_DEFER_INSN_RESCAN)
@@ -2221,10 +2219,6 @@ df_notes_rescan (rtx insn)
unsigned int num_deleted;
unsigned int mw_len;
- memset (&collection_rec, 0, sizeof (struct df_collection_rec));
- vec_stack_alloc (df_ref, collection_rec.eq_use_vec, 32);
- vec_stack_alloc (df_mw_hardreg_ptr, collection_rec.mw_vec, 32);
-
num_deleted = df_mw_hardreg_chain_delete_eq_uses (insn_info);
df_ref_chain_delete (insn_info->eq_uses);
insn_info->eq_uses = NULL;
@@ -2287,11 +2281,7 @@ df_notes_rescan (rtx insn)
insn_info->mw_hardregs[mw_len] = NULL;
}
}
- /* Get rid of the mw_rec so that df_refs_add_to_chains will
- ignore it. */
- collection_rec.mw_vec.release ();
- df_refs_add_to_chains (&collection_rec, bb, insn);
- collection_rec.eq_use_vec.release ();
+ df_refs_add_to_chains (&collection_rec, bb, insn, copy_eq_uses);
}
else
df_insn_rescan (insn);
@@ -2391,7 +2381,7 @@ df_ref_compare (const void *r1, const void *r2)
}
static void
-df_swap_refs (vec<df_ref, va_stack> *ref_vec, int i, int j)
+df_swap_refs (vec<df_ref, va_heap> *ref_vec, int i, int j)
{
df_ref tmp = (*ref_vec)[i];
(*ref_vec)[i] = (*ref_vec)[j];
@@ -2401,7 +2391,7 @@ df_swap_refs (vec<df_ref, va_stack> *ref_vec, int i, int j)
/* Sort and compress a set of refs. */
static void
-df_sort_and_compress_refs (vec<df_ref, va_stack> *ref_vec)
+df_sort_and_compress_refs (vec<df_ref, va_heap> *ref_vec)
{
unsigned int count;
unsigned int i;
@@ -2510,7 +2500,7 @@ df_mw_compare (const void *m1, const void *m2)
/* Sort and compress a set of refs. */
static void
-df_sort_and_compress_mws (vec<df_mw_hardreg_ptr, va_stack> *mw_vec)
+df_sort_and_compress_mws (vec<df_mw_hardreg_ptr, va_heap> *mw_vec)
{
unsigned int count;
struct df_scan_problem_data *problem_data
@@ -2621,14 +2611,12 @@ df_install_ref (df_ref this_ref,
static df_ref *
df_install_refs (basic_block bb,
- vec<df_ref, va_stack> old_vec,
+ const vec<df_ref, va_heap> *old_vec,
struct df_reg_info **reg_info,
struct df_ref_info *ref_info,
bool is_notes)
{
- unsigned int count;
-
- count = old_vec.length ();
+ unsigned int count = old_vec->length ();
if (count)
{
df_ref *new_vec = XNEWVEC (df_ref, count + 1);
@@ -2659,7 +2647,7 @@ df_install_refs (basic_block bb,
if (add_to_table && df->analyze_subset)
add_to_table = bitmap_bit_p (df->blocks_to_analyze, bb->index);
- FOR_EACH_VEC_ELT (old_vec, ix, this_ref)
+ FOR_EACH_VEC_ELT (*old_vec, ix, this_ref)
{
new_vec[ix] = this_ref;
df_install_ref (this_ref, reg_info[DF_REF_REGNO (this_ref)],
@@ -2678,16 +2666,14 @@ df_install_refs (basic_block bb,
insn. */
static struct df_mw_hardreg **
-df_install_mws (vec<df_mw_hardreg_ptr, va_stack> old_vec)
+df_install_mws (const vec<df_mw_hardreg_ptr, va_heap> *old_vec)
{
- unsigned int count;
-
- count = old_vec.length ();
+ unsigned int count = old_vec->length ();
if (count)
{
struct df_mw_hardreg **new_vec
= XNEWVEC (struct df_mw_hardreg*, count + 1);
- memcpy (new_vec, old_vec.address (),
+ memcpy (new_vec, old_vec->address (),
sizeof (struct df_mw_hardreg*) * count);
new_vec[count] = NULL;
return new_vec;
@@ -2702,7 +2688,7 @@ df_install_mws (vec<df_mw_hardreg_ptr, va_stack> old_vec)
static void
df_refs_add_to_chains (struct df_collection_rec *collection_rec,
- basic_block bb, rtx insn)
+ basic_block bb, rtx insn, unsigned int flags)
{
if (insn)
{
@@ -2710,35 +2696,35 @@ df_refs_add_to_chains (struct df_collection_rec *collection_rec,
/* If there is a vector in the collection rec, add it to the
insn. A null rec is a signal that the caller will handle the
chain specially. */
- if (collection_rec->def_vec.exists ())
+ if (flags & copy_defs)
{
df_scan_free_ref_vec (insn_rec->defs);
insn_rec->defs
- = df_install_refs (bb, collection_rec->def_vec,
+ = df_install_refs (bb, &collection_rec->def_vec,
df->def_regs,
&df->def_info, false);
}
- if (collection_rec->use_vec.exists ())
+ if (flags & copy_uses)
{
df_scan_free_ref_vec (insn_rec->uses);
insn_rec->uses
- = df_install_refs (bb, collection_rec->use_vec,
+ = df_install_refs (bb, &collection_rec->use_vec,
df->use_regs,
&df->use_info, false);
}
- if (collection_rec->eq_use_vec.exists ())
+ if (flags & copy_eq_uses)
{
df_scan_free_ref_vec (insn_rec->eq_uses);
insn_rec->eq_uses
- = df_install_refs (bb, collection_rec->eq_use_vec,
+ = df_install_refs (bb, &collection_rec->eq_use_vec,
df->eq_use_regs,
&df->use_info, true);
}
- if (collection_rec->mw_vec.exists ())
+ if (flags & copy_mw)
{
df_scan_free_mws_vec (insn_rec->mw_hardregs);
insn_rec->mw_hardregs
- = df_install_mws (collection_rec->mw_vec);
+ = df_install_mws (&collection_rec->mw_vec);
}
}
else
@@ -2747,12 +2733,12 @@ df_refs_add_to_chains (struct df_collection_rec *collection_rec,
df_scan_free_ref_vec (bb_info->artificial_defs);
bb_info->artificial_defs
- = df_install_refs (bb, collection_rec->def_vec,
+ = df_install_refs (bb, &collection_rec->def_vec,
df->def_regs,
&df->def_info, false);
df_scan_free_ref_vec (bb_info->artificial_uses);
bb_info->artificial_uses
- = df_install_refs (bb, collection_rec->use_vec,
+ = df_install_refs (bb, &collection_rec->use_vec,
df->use_regs,
&df->use_info, false);
}
@@ -3633,17 +3619,12 @@ df_bb_refs_record (int bb_index, bool scan_insns)
basic_block bb = BASIC_BLOCK (bb_index);
rtx insn;
int luid = 0;
- struct df_collection_rec collection_rec;
if (!df)
return;
+ df_collection_rec collection_rec;
df_grow_bb_info (df_scan);
- vec_stack_alloc (df_ref, collection_rec.def_vec, 128);
- vec_stack_alloc (df_ref, collection_rec.use_vec, 32);
- vec_stack_alloc (df_ref, collection_rec.eq_use_vec, 32);
- vec_stack_alloc (df_mw_hardreg_ptr, collection_rec.mw_vec, 32);
-
if (scan_insns)
/* Scan the block an insn at a time from beginning to end. */
FOR_BB_INSNS (bb, insn)
@@ -3657,19 +3638,14 @@ df_bb_refs_record (int bb_index, bool scan_insns)
/* Record refs within INSN. */
DF_INSN_INFO_LUID (insn_info) = luid++;
df_insn_refs_collect (&collection_rec, bb, DF_INSN_INFO_GET (insn));
- df_refs_add_to_chains (&collection_rec, bb, insn);
+ df_refs_add_to_chains (&collection_rec, bb, insn, copy_all);
}
DF_INSN_INFO_LUID (insn_info) = luid;
}
/* Other block level artificial refs */
df_bb_refs_collect (&collection_rec, bb);
- df_refs_add_to_chains (&collection_rec, bb, NULL);
-
- collection_rec.def_vec.release ();
- collection_rec.use_vec.release ();
- collection_rec.eq_use_vec.release ();
- collection_rec.mw_vec.release ();
+ df_refs_add_to_chains (&collection_rec, bb, NULL, copy_all);
/* Now that the block has been processed, set the block as dirty so
LR and LIVE will get it processed. */
@@ -3911,13 +3887,11 @@ static void
df_record_entry_block_defs (bitmap entry_block_defs)
{
struct df_collection_rec collection_rec;
- memset (&collection_rec, 0, sizeof (struct df_collection_rec));
- vec_stack_alloc (df_ref, collection_rec.def_vec, FIRST_PSEUDO_REGISTER);
df_entry_block_defs_collect (&collection_rec, entry_block_defs);
/* Process bb_refs chain */
- df_refs_add_to_chains (&collection_rec, BASIC_BLOCK (ENTRY_BLOCK), NULL);
- collection_rec.def_vec.release ();
+ df_refs_add_to_chains (&collection_rec, BASIC_BLOCK (ENTRY_BLOCK), NULL,
+ copy_defs);
}
@@ -4084,13 +4058,11 @@ static void
df_record_exit_block_uses (bitmap exit_block_uses)
{
struct df_collection_rec collection_rec;
- memset (&collection_rec, 0, sizeof (struct df_collection_rec));
- vec_stack_alloc (df_ref, collection_rec.use_vec, FIRST_PSEUDO_REGISTER);
df_exit_block_uses_collect (&collection_rec, exit_block_uses);
/* Process bb_refs chain */
- df_refs_add_to_chains (&collection_rec, BASIC_BLOCK (EXIT_BLOCK), NULL);
- collection_rec.use_vec.release ();
+ df_refs_add_to_chains (&collection_rec, BASIC_BLOCK (EXIT_BLOCK), NULL,
+ copy_uses);
}
@@ -4331,13 +4303,13 @@ df_reg_chain_verify_unmarked (df_ref refs)
/* Verify that NEW_REC and OLD_REC have exactly the same members. */
static bool
-df_refs_verify (vec<df_ref, va_stack> new_rec, df_ref *old_rec,
+df_refs_verify (const vec<df_ref, va_heap> *new_rec, df_ref *old_rec,
bool abort_if_fail)
{
unsigned int ix;
df_ref new_ref;
- FOR_EACH_VEC_ELT (new_rec, ix, new_ref)
+ FOR_EACH_VEC_ELT (*new_rec, ix, new_ref)
{
if (*old_rec == NULL || !df_ref_equal_p (new_ref, *old_rec))
{
@@ -4369,14 +4341,14 @@ df_refs_verify (vec<df_ref, va_stack> new_rec, df_ref *old_rec,
/* Verify that NEW_REC and OLD_REC have exactly the same members. */
static bool
-df_mws_verify (vec<df_mw_hardreg_ptr, va_stack> new_rec,
+df_mws_verify (const vec<df_mw_hardreg_ptr, va_heap> *new_rec,
struct df_mw_hardreg **old_rec,
bool abort_if_fail)
{
unsigned int ix;
struct df_mw_hardreg *new_reg;
- FOR_EACH_VEC_ELT (new_rec, ix, new_reg)
+ FOR_EACH_VEC_ELT (*new_rec, ix, new_reg)
{
if (*old_rec == NULL || !df_mw_equal_p (new_reg, *old_rec))
{
@@ -4430,13 +4402,13 @@ df_insn_refs_verify (struct df_collection_rec *collection_rec,
/* Unfortunately we cannot opt out early if one of these is not
right because the marks will not get cleared. */
- ret1 = df_refs_verify (collection_rec->def_vec, DF_INSN_UID_DEFS (uid),
+ ret1 = df_refs_verify (&collection_rec->def_vec, DF_INSN_UID_DEFS (uid),
abort_if_fail);
- ret2 = df_refs_verify (collection_rec->use_vec, DF_INSN_UID_USES (uid),
+ ret2 = df_refs_verify (&collection_rec->use_vec, DF_INSN_UID_USES (uid),
abort_if_fail);
- ret3 = df_refs_verify (collection_rec->eq_use_vec, DF_INSN_UID_EQ_USES (uid),
+ ret3 = df_refs_verify (&collection_rec->eq_use_vec, DF_INSN_UID_EQ_USES (uid),
abort_if_fail);
- ret4 = df_mws_verify (collection_rec->mw_vec, DF_INSN_UID_MWS (uid),
+ ret4 = df_mws_verify (&collection_rec->mw_vec, DF_INSN_UID_MWS (uid),
abort_if_fail);
return (ret1 && ret2 && ret3 && ret4);
}
@@ -4453,12 +4425,6 @@ df_bb_verify (basic_block bb)
struct df_scan_bb_info *bb_info = df_scan_get_bb_info (bb->index);
struct df_collection_rec collection_rec;
- memset (&collection_rec, 0, sizeof (struct df_collection_rec));
- vec_stack_alloc (df_ref, collection_rec.def_vec, 128);
- vec_stack_alloc (df_ref, collection_rec.use_vec, 32);
- vec_stack_alloc (df_ref, collection_rec.eq_use_vec, 32);
- vec_stack_alloc (df_mw_hardreg_ptr, collection_rec.mw_vec, 32);
-
gcc_assert (bb_info);
/* Scan the block, one insn at a time, from beginning to end. */
@@ -4472,8 +4438,8 @@ df_bb_verify (basic_block bb)
/* Do the artificial defs and uses. */
df_bb_refs_collect (&collection_rec, bb);
- df_refs_verify (collection_rec.def_vec, df_get_artificial_defs (bb->index), true);
- df_refs_verify (collection_rec.use_vec, df_get_artificial_uses (bb->index), true);
+ df_refs_verify (&collection_rec.def_vec, df_get_artificial_defs (bb->index), true);
+ df_refs_verify (&collection_rec.use_vec, df_get_artificial_uses (bb->index), true);
df_free_collection_rec (&collection_rec);
return true;
@@ -4558,11 +4524,11 @@ df_scan_verify (void)
for (i = 0; i < DF_REG_SIZE (df); i++)
{
gcc_assert (df_reg_chain_mark (DF_REG_DEF_CHAIN (i), i, true, false)
- == DF_REG_DEF_COUNT(i));
+ == DF_REG_DEF_COUNT (i));
gcc_assert (df_reg_chain_mark (DF_REG_USE_CHAIN (i), i, false, false)
- == DF_REG_USE_COUNT(i));
+ == DF_REG_USE_COUNT (i));
gcc_assert (df_reg_chain_mark (DF_REG_EQ_USE_CHAIN (i), i, false, true)
- == DF_REG_EQ_USE_COUNT(i));
+ == DF_REG_EQ_USE_COUNT (i));
}
/* (2) There are various bitmaps whose value may change over the
diff --git a/gcc/df.h b/gcc/df.h
index 716ce0c8d72..e3ca67b6841 100644
--- a/gcc/df.h
+++ b/gcc/df.h
@@ -607,29 +607,29 @@ struct df_d
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_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))
/* 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_LIVE_IN(BB) (&DF_LIVE_BB_INFO (BB)->in)
+#define DF_LIVE_OUT(BB) (&DF_LIVE_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)
+#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)
+#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. */
@@ -640,10 +640,11 @@ struct df_d
#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 ? \
+#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_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)
@@ -660,7 +661,7 @@ struct df_d
/* 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_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))
@@ -722,35 +723,35 @@ struct df_d
/* 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)
+(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)
+(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_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_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_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()) \
+#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 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)
/* An obstack for bitmap not related to specific dataflow problems.
This obstack should e.g. be used for bitmaps with a short life time
diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
index 295bbb6e045..36094a19c9a 100644
--- a/gcc/diagnostic.c
+++ b/gcc/diagnostic.c
@@ -267,7 +267,7 @@ adjust_line (const char *line, int max_width, int *column_p)
int line_width = strlen (line);
int column = *column_p;
- right_margin = MIN(line_width - column, right_margin);
+ right_margin = MIN (line_width - column, right_margin);
right_margin = max_width - right_margin;
if (line_width >= max_width && column > right_margin)
{
@@ -354,7 +354,7 @@ bt_callback (void *data, uintptr_t pc, const char *filename, int lineno,
/* Skip functions in diagnostic.c. */
if (*pcount == 0
&& filename != NULL
- && strcmp (lbasename(filename), "diagnostic.c") == 0)
+ && strcmp (lbasename (filename), "diagnostic.c") == 0)
return 0;
/* Print up to 20 functions. We could make this a --param, but
@@ -881,7 +881,7 @@ diagnostic_append_note (diagnostic_context *context,
pp_destroy_prefix (context->printer);
pp_set_prefix (context->printer, saved_prefix);
diagnostic_show_locus (context, &diagnostic);
- va_end(ap);
+ va_end (ap);
}
bool
diff --git a/gcc/doc/contrib.texi b/gcc/doc/contrib.texi
index 9dd2c26287c..32a85634eb8 100644
--- a/gcc/doc/contrib.texi
+++ b/gcc/doc/contrib.texi
@@ -238,6 +238,10 @@ maintaining @code{complex<>}, sanity checking and disbursement, configuration
architecture, libio maintenance, and early math work.
@item
+Fran@,{c}ois Dumont for his work on libstdc++-v3, especially maintaining and
+improving @code{debug-mode} and associative and unordered containers.
+
+@item
Zdenek Dvorak for a new loop unroller and various fixes.
@item
@@ -838,6 +842,9 @@ Lars Segerlund for work on GNU Fortran.
Dodji Seketeli for numerous C++ bug fixes and debug info improvements.
@item
+Tim Shen for major work on @code{<regex>}.
+
+@item
Joel Sherrill for his direction via the steering committee, RTEMS
contributions and RTEMS testing.
@@ -873,6 +880,10 @@ Danny Smith for his major efforts on the Mingw (and Cygwin) ports.
Randy Smith finished the Sun FPA support.
@item
+Ed Smith-Rowland for his continuous work on libstdc++-v3, special functions,
+@code{<random>}, and various improvements to C++11 features.
+
+@item
Scott Snyder for queue, iterator, istream, and string fixes and libstdc++
testsuite entries. Also for providing the patch to G77 to add
rudimentary support for @code{INTEGER*1}, @code{INTEGER*2}, and
@@ -995,7 +1006,7 @@ Feng Wang for contributions to GNU Fortran.
@item
Stephen M. Webb for time and effort on making libstdc++ shadow files
work with the tricky Solaris 8+ headers, and for pushing the build-time
-header tree.
+header tree. Also, for starting and driving the @code{<regex>} effort.
@item
John Wehle for various improvements for the x86 code generator,
diff --git a/gcc/doc/cpp.texi b/gcc/doc/cpp.texi
index 7ff04cde765..0ab9361bb42 100644
--- a/gcc/doc/cpp.texi
+++ b/gcc/doc/cpp.texi
@@ -2389,6 +2389,40 @@ These macros are defined with value 1 if the backend supports the
the include file @file{math.h} can define the macros
@code{FP_FAST_FMA}, @code{FP_FAST_FMAF}, and @code{FP_FAST_FMAL}
for compatibility with the 1999 C standard.
+
+@item __GCC_IEC_559
+This macro is defined to indicate the intended level of support for
+IEEE 754 (IEC 60559) floating-point arithmetic. It expands to a
+nonnegative integer value. If 0, it indicates that the combination of
+the compiler configuration and the command-line options is not
+intended to support IEEE 754 arithmetic for @code{float} and
+@code{double} as defined in C99 and C11 Annex F (for example, that the
+standard rounding modes and exceptions are not supported, or that
+optimizations are enabled that conflict with IEEE 754 semantics). If
+1, it indicates that IEEE 754 arithmetic is intended to be supported;
+this does not mean that all relevant language features are supported
+by GCC. If 2 or more, it additionally indicates support for IEEE
+754-2008 (in particular, that the binary encodings for quiet and
+signaling NaNs are as specified in IEEE 754-2008).
+
+This macro does not indicate the default state of command-line options
+that control optimizations that C99 and C11 permit to be controlled by
+standard pragmas, where those standards do not require a particular
+default state. It does not indicate whether optimizations respect
+signaling NaN semantics (the macro for that is
+@code{__SUPPORT_SNAN__}). It does not indicate support for decimal
+floating point or the IEEE 754 binary16 and binary128 types.
+
+@item __GCC_IEC_559_COMPLEX
+This macro is defined to indicate the intended level of support for
+IEEE 754 (IEC 60559) floating-point arithmetic for complex numbers, as
+defined in C99 and C11 Annex G. It expands to a nonnegative integer
+value. If 0, it indicates that the combination of the compiler
+configuration and the command-line options is not intended to support
+Annex G requirements (for example, because @option{-fcx-limited-range}
+was used). If 1 or more, it indicates that it is intended to support
+those requirements; this does not mean that all relevant language
+features are supported by GCC.
@end table
@node System-specific Predefined Macros
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index edf0e2851bc..2132b1e5602 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -82,6 +82,7 @@ extensions, accepted by GCC in C90 mode and in C++.
* x86 specific memory model extensions for transactional memory:: x86 memory models.
* Object Size Checking:: Built-in functions for limited buffer overflow
checking.
+* Pointer Bounds Checker builtins:: Built-in functions for Pointer Bounds Checker.
* Cilk Plus Builtins:: Built-in functions for the Cilk Plus language extension.
* Other Builtins:: Other built-in functions.
* Target Builtins:: Built-in functions specific to particular targets.
@@ -2133,10 +2134,11 @@ attributes are currently defined for functions on all targets:
@code{section}, @code{constructor},
@code{destructor}, @code{used}, @code{unused}, @code{deprecated},
@code{weak}, @code{malloc}, @code{alias}, @code{ifunc},
-@code{warn_unused_result}, @code{nonnull}, @code{gnu_inline},
+@code{warn_unused_result}, @code{nonnull},
+@code{returns_nonnull}, @code{gnu_inline},
@code{externally_visible}, @code{hot}, @code{cold}, @code{artificial},
@code{no_sanitize_address}, @code{no_address_safety_analysis},
-@code{no_sanitize_undefined},
+@code{no_sanitize_undefined}, @code{bnd_legacy},
@code{error} and @code{warning}.
Several other attributes are defined for functions on particular
target systems. Other attributes, including @code{section} are
@@ -2503,6 +2505,12 @@ on data in the eight-bit data area. Note the eight-bit data area is limited to
You must use GAS and GLD from GNU binutils version 2.7 or later for
this attribute to work correctly.
+@item exception
+@cindex exception handler functions
+Use this attribute on the NDS32 target to indicate that the specified function
+is an exception handler. The compiler will generate corresponding sections
+for use in an exception handler.
+
@item exception_handler
@cindex exception handler functions on the Blackfin processor
Use this attribute on the Blackfin to indicate that the specified function
@@ -2813,8 +2821,9 @@ least version 2.20.1), and GNU C library (at least version 2.11.1).
@item interrupt
@cindex interrupt handler functions
-Use this attribute on the ARM, AVR, CR16, Epiphany, M32C, M32R/D, m68k, MeP, MIPS,
-MSP430, RL78, RX and Xstormy16 ports to indicate that the specified function is an
+Use this attribute on the ARC, ARM, AVR, CR16, Epiphany, M32C, M32R/D,
+m68k, MeP, MIPS, MSP430, RL78, RX and Xstormy16 ports to indicate that
+the specified function is an
interrupt handler. The compiler generates function entry and exit
sequences suitable for use in an interrupt handler when this attribute
is present. With Epiphany targets it may also generate a special section with
@@ -2823,6 +2832,16 @@ code to initialize the interrupt vector table.
Note, interrupt handlers for the Blackfin, H8/300, H8/300H, H8S, MicroBlaze,
and SH processors can be specified via the @code{interrupt_handler} attribute.
+Note, on the ARC, you must specify the kind of interrupt to be handled
+in a parameter to the interrupt attribute like this:
+
+@smallexample
+void f () __attribute__ ((interrupt ("ilink1")));
+@end smallexample
+
+Permissible values for this parameter are: @w{@code{ilink1}} and
+@w{@code{ilink2}}.
+
Note, on the AVR, the hardware globally disables interrupts when an
interrupt is executed. The first instruction of an interrupt handler
declared with this attribute is a @code{SEI} instruction to
@@ -2952,6 +2971,32 @@ void __attribute__ ((interrupt, use_shadow_register_set,
use_debug_exception_return)) v7 ();
@end smallexample
+On NDS32 target, this attribute is to indicate that the specified function
+is an interrupt handler. The compiler will generate corresponding sections
+for use in an interrupt handler. You can use the following attributes
+to modify the behavior:
+@table @code
+@item nested
+@cindex @code{nested} attribute
+This interrupt service routine is interruptible.
+@item not_nested
+@cindex @code{not_nested} attribute
+This interrupt service routine is not interruptible.
+@item nested_ready
+@cindex @code{nested_ready} attribute
+This interrupt service routine is interruptible after @code{PSW.GIE}
+(global interrupt enable) is set. This allows interrupt service routine to
+finish some short critical code before enabling interrupts.
+@item save_all
+@cindex @code{save_all} attribute
+The system will help save all registers into stack before entering
+interrupt handler.
+@item partial_save
+@cindex @code{partial_save} attribute
+The system will help save caller registers into stack before entering
+interrupt handler.
+@end table
+
On RL78, use @code{brk_interrupt} instead of @code{interrupt} for
handlers intended to be used with the @code{BRK} opcode (i.e.@: those
that must end with @code{RETB} instead of @code{RETI}).
@@ -3021,18 +3066,33 @@ unit. This is to allow easy merging of multiple compilation units into one,
for example, by using the link-time optimization. For this reason the
attribute is not allowed on types to annotate indirect calls.
-@item long_call/short_call
+@item long_call/medium_call/short_call
+@cindex indirect calls on ARC
@cindex indirect calls on ARM
-This attribute specifies how a particular function is called on
-ARM and Epiphany. Both attributes override the
-@option{-mlong-calls} (@pxref{ARM Options})
-command-line switch and @code{#pragma long_calls} settings. The
+@cindex indirect calls on Epiphany
+These attributes specify how a particular function is called on
+ARC, ARM and Epiphany - with @code{medium_call} being specific to ARC.
+These attributes override the
+@option{-mlong-calls} (@pxref{ARM Options} and @ref{ARC Options})
+and @option{-mmedium-calls} (@pxref{ARC Options})
+command-line switches and @code{#pragma long_calls} settings. For ARM, the
@code{long_call} attribute indicates that the function might be far
away from the call site and require a different (more expensive)
calling sequence. The @code{short_call} attribute always places
the offset to the function from the call site into the @samp{BL}
instruction directly.
+For ARC, a function marked with the @code{long_call} attribute is
+always called using register-indirect jump-and-link instructions,
+thereby enabling the called function to be placed anywhere within the
+32-bit address space. A function marked with the @code{medium_call}
+attribute will always be close enough to be called with an unconditional
+branch-and-link instruction, which has a 25-bit offset from
+the call site. A function marked with the @code{short_call}
+attribute will always be close enough to be called with a conditional
+branch-and-link instruction, which has a 21-bit offset from
+the call site.
+
@item longcall/shortcall
@cindex functions called via pointer on the RS/6000 and PowerPC
On the Blackfin, RS/6000 and PowerPC, the @code{longcall} attribute
@@ -3173,9 +3233,10 @@ and newer.
@item naked
@cindex function without a prologue/epilogue code
-Use this attribute on the ARM, AVR, MCORE, MSP430, RL78, RX and SPU ports to indicate that
-the specified function does not need prologue/epilogue sequences generated by
-the compiler. It is up to the programmer to provide these sequences. The
+Use this attribute on the ARM, AVR, MCORE, MSP430, NDS32, RL78, RX and SPU
+ports to indicate that the specified function does not need prologue/epilogue
+sequences generated by the compiler.
+It is up to the programmer to provide these sequences. The
only statements that can be safely included in naked functions are
@code{asm} statements that do not have operands. All other statements,
including declarations of local variables, @code{if} statements, and so
@@ -3283,6 +3344,20 @@ my_memcpy (void *dest, const void *src, size_t len)
__attribute__((nonnull));
@end smallexample
+@item returns_nonnull
+@cindex @code{returns_nonnull} function attribute
+The @code{returns_nonnull} attribute specifies that the function
+return value should be a non-null pointer. For instance, the declaration:
+
+@smallexample
+extern void *
+mymalloc (size_t len) __attribute__((returns_nonnull));
+@end smallexample
+
+@noindent
+lets the compiler optimize callers based on the knowledge
+that the return value will never be null.
+
@item noreturn
@cindex @code{noreturn} function attribute
A few standard library functions, such as @code{abort} and @code{exit},
@@ -3507,6 +3582,12 @@ The @code{no_sanitize_undefined} attribute on functions is used
to inform the compiler that it should not check for undefined behavior
in the function when compiling with the @option{-fsanitize=undefined} option.
+@item bnd_legacy
+@cindex @code{bnd_legacy} function attribute
+The @code{bnd_legacy} attribute on functions is used to inform
+compiler that function should not be instrumented when compiled
+with @option{-fcheck-pointers} option.
+
@item regparm (@var{number})
@cindex @code{regparm} attribute
@cindex functions that are passed arguments in registers on the 386
@@ -3527,6 +3608,21 @@ safe since the loaders there save EAX, EDX and ECX. (Lazy binding can be
disabled with the linker or the loader if desired, to avoid the
problem.)
+@item reset
+@cindex reset handler functions
+Use this attribute on the NDS32 target to indicate that the specified function
+is a reset handler. The compiler will generate corresponding sections
+for use in a reset handler. You can use the following attributes
+to provide extra exception handling:
+@table @code
+@item nmi
+@cindex @code{nmi} attribute
+Provide a user-defined function to handle NMI exception.
+@item warm
+@cindex @code{warm} attribute
+Provide a user-defined function to handle warm reset exception.
+@end table
+
@item sseregparm
@cindex @code{sseregparm} attribute
On the Intel 386 with SSE support, the @code{sseregparm} attribute
@@ -4179,6 +4275,12 @@ the One Definition Rule; for example, it is usually not useful to mark
an inline method as hidden without marking the whole class as hidden.
A C++ namespace declaration can also have the visibility attribute.
+
+@smallexample
+namespace nspace1 __attribute__ ((visibility ("protected")))
+@{ /* @r{Do something.} */; @}
+@end smallexample
+
This attribute applies only to the particular namespace body, not to
other definitions of the same namespace; it is equivalent to using
@samp{#pragma GCC visibility} before and after the namespace
@@ -5279,12 +5381,12 @@ placed in either the @code{.bss_below100} section or the
The keyword @code{__attribute__} allows you to specify special
attributes of @code{struct} and @code{union} types when you define
such types. This keyword is followed by an attribute specification
-inside double parentheses. Seven attributes are currently defined for
+inside double parentheses. Eight attributes are currently defined for
types: @code{aligned}, @code{packed}, @code{transparent_union},
-@code{unused}, @code{deprecated}, @code{visibility}, and
-@code{may_alias}. Other attributes are defined for functions
-(@pxref{Function Attributes}) and for variables (@pxref{Variable
-Attributes}).
+@code{unused}, @code{deprecated}, @code{visibility}, @code{may_alias}
+and @code{bnd_variable_size}. Other attributes are defined for
+functions (@pxref{Function Attributes}) and for variables
+(@pxref{Variable Attributes}).
You may also specify any one of these attributes with @samp{__}
preceding and following its keyword. This allows you to use these
@@ -5576,6 +5678,35 @@ and caught in another, the class must have default visibility.
Otherwise the two shared objects are unable to use the same
typeinfo node and exception handling will break.
+@item bnd_variable_size
+When applied to a structure field, this attribute tells Pointer
+Bounds Checker that the size of this field should not be computed
+using static type information. It may be used to mark variable
+sized static array fields placed at the end of a structure.
+
+@smallexample
+struct S
+@{
+ int size;
+ char data[1];
+@}
+S *p = (S *)malloc (sizeof(S) + 100);
+p->data[10] = 0; //Bounds violation
+@end smallexample
+
+By using an attribute for a field we may avoid bound violation
+we most probably do not want to see:
+
+@smallexample
+struct S
+@{
+ int size;
+ char data[1] __attribute__((bnd_variable_size));
+@}
+S *p = (S *)malloc (sizeof(S) + 100);
+p->data[10] = 0; //OK
+@end smallexample
+
@end table
To specify multiple attributes, separate them by commas within the
@@ -7711,6 +7842,202 @@ format string @var{fmt}. If the compiler is able to optimize them to
@code{fputc} etc.@: functions, it does, otherwise the checking function
is called and the @var{flag} argument passed to it.
+@node Pointer Bounds Checker builtins
+@section Pointer Bounds Checker Built-in Functions
+@findex __builtin___bnd_set_ptr_bounds
+@findex __builtin___bnd_narrow_ptr_bounds
+@findex __builtin___bnd_copy_ptr_bounds
+@findex __builtin___bnd_init_ptr_bounds
+@findex __builtin___bnd_null_ptr_bounds
+@findex __builtin___bnd_store_ptr_bounds
+@findex __builtin___bnd_chk_ptr_lbounds
+@findex __builtin___bnd_chk_ptr_ubounds
+@findex __builtin___bnd_chk_ptr_bounds
+@findex __builtin___bnd_get_ptr_lbound
+@findex __builtin___bnd_get_ptr_ubound
+
+GCC provides a set of built-in functions to control Pointer Bounds Checker
+instrumentation. Note that all Pointer Bounds Checker builtins are allowed
+to use even if you compile with Pointer Bounds Checker off. But functions
+behavior may differ in such case.
+
+@deftypefn {Built-in Function} void * __builtin___bnd_set_ptr_bounds (const void * @var{q}, size_t @var{size})
+
+This built-in function returns a new pointer with the value of @var{q}, and
+associate it with the bounds [@var{q}, @var{q}+@var{size}-1]. With Pointer
+Bounds Checker off built-in function just returns the first argument.
+
+@smallexample
+extern void *__wrap_malloc (size_t n)
+@{
+ void *p = (void *)__real_malloc (n);
+ if (!p) return __builtin___bnd_null_ptr_bounds (p);
+ return __builtin___bnd_set_ptr_bounds (p, n);
+@}
+@end smallexample
+
+@end deftypefn
+
+@deftypefn {Built-in Function} void * __builtin___bnd_narrow_ptr_bounds (const void * @var{p}, const void * @var{q}, size_t @var{size})
+
+This built-in function returns a new pointer with the value of @var{p}
+and associate it with the narrowed bounds formed by the intersection
+of bounds associated with @var{q} and the [@var{p}, @var{p} + @var{size} - 1].
+With Pointer Bounds Checker off built-in function just returns the first
+argument.
+
+@smallexample
+void init_objects (object *objs, size_t size)
+@{
+ size_t i;
+ /* Initialize objects one-by-one passing pointers with bounds of an object,
+ not the full array of objects. */
+ for (i = 0; i < size; i++)
+ init_object (__builtin___bnd_narrow_ptr_bounds (objs + i, objs, sizeof(object)));
+@}
+@end smallexample
+
+@end deftypefn
+
+@deftypefn {Built-in Function} void * __builtin___bnd_copy_ptr_bounds (const void * @var{q}, const void * @var{r})
+
+This built-in function returns a new pointer with the value of @var{q},
+and associate it with the bounds already associated with pointer @var{r}.
+With Pointer Bounds Checker off built-in function just returns the first
+argument.
+
+@smallexample
+/* Here is a way to get pointer to object's field but
+ still with the full object's bounds. */
+int *field_ptr = __builtin___bnd_copy_ptr_bounds (&objptr->int_filed, objptr);
+@end smallexample
+
+@end deftypefn
+
+@deftypefn {Built-in Function} void * __builtin___bnd_init_ptr_bounds (const void * @var{q})
+
+This built-in function returns a new pointer with the value of @var{q}, and
+associate it with INIT (allowing full memory access) bounds. With Pointer
+Bounds Checker off built-in function just returns the first argument.
+
+@end deftypefn
+
+@deftypefn {Built-in Function} void * __builtin___bnd_null_ptr_bounds (const void * @var{q})
+
+This built-in function returns a new pointer with the value of @var{q}, and
+associate it with NULL (allowing no memory access) bounds. With Pointer
+Bounds Checker off built-in function just returns the first argument.
+
+@end deftypefn
+
+@deftypefn {Built-in Function} void __builtin___bnd_store_ptr_bounds (const void ** @var{ptr_addr}, const void * @var{ptr_val})
+
+This built-in function stores the bounds associated with pointer @var{ptr_val}
+and location @var{ptr_addr} into Bounds Table. This can be useful to propagate
+bounds from legacy code without touching the associated pointer's memory when
+pointers were copied as integers. With Pointer Bounds Checker off built-in
+function call is ignored.
+
+@end deftypefn
+
+@deftypefn {Built-in Function} void __builtin___bnd_chk_ptr_lbounds (const void * @var{q})
+
+This built-in function checks if the pointer @var{q} is within the lower
+bound of its associated bounds. With Pointer Bounds Checker off built-in
+function call is ignored.
+
+@smallexample
+extern void *__wrap_memset (void *dst, int c, size_t len)
+@{
+ if (len > 0)
+ @{
+ __builtin___bnd_chk_ptr_lbounds (dst);
+ __builtin___bnd_chk_ptr_ubounds ((char *)dst + len - 1);
+ __real_memset (dst, c, len);
+ @}
+ return dst;
+@}
+@end smallexample
+
+@end deftypefn
+
+@deftypefn {Built-in Function} void __builtin___bnd_chk_ptr_ubounds (const void * @var{q})
+
+This built-in function checks if the pointer @var{q} is within the upper
+bound of its associated bounds. With Pointer Bounds Checker off built-in
+function call is ignored.
+
+@end deftypefn
+
+@deftypefn {Built-in Function} void __builtin___bnd_chk_ptr_bounds (const void * @var{q}, size_t @var{size})
+
+This built-in function checks if [@var{q}, @var{q} + @var{size} - 1] is within
+the lower and upper bounds associated with @var{q}. With Pointer Bounds Checker
+off built-in function call is ignored.
+
+@smallexample
+extern void *__wrap_memcpy (void *dst, const void *src, size_t n)
+@{
+ if (n > 0)
+ @{
+ __bnd_chk_ptr_bounds (dst, n);
+ __bnd_chk_ptr_bounds (src, n);
+ __real_memcpy (dst, src, n);
+ @}
+ return dst;
+@}
+@end smallexample
+
+@end deftypefn
+
+@deftypefn {Built-in Function} const void * __builtin___bnd_get_ptr_lbound (const void * @var{q})
+
+This built-in function returns the lower bound (which is a pointer) associated
+with the pointer @var{q}. This is at least useful for debugging using printf.
+With Pointer Bounds Checker off built-in function returns 0.
+
+@smallexample
+void *lb = __builtin___bnd_get_ptr_lbound (q);
+void *ub = __builtin___bnd_get_ptr_ubound (q);
+printf ("q = %p lb(q) = %p ub(q) = %p", q, lb, ub);
+@end smallexample
+
+@end deftypefn
+
+@deftypefn {Built-in Function} const void * __builtin___bnd_get_ptr_ubound (const void * @var{q})
+
+This built-in function returns the upper bound (which is a pointer) associated
+with the pointer @var{q}. With Pointer Bounds Checker off built-in function
+returns -1.
+
+@end deftypefn
+
+@node Cilk Plus Builtins
+@section Cilk Plus C/C++ language extension Built-in Functions.
+
+GCC provides support for the following built-in reduction funtions if Cilk Plus
+is enabled. Cilk Plus can be enabled using the @option{-fcilkplus} flag.
+
+@itemize @bullet
+@item __sec_implicit_index
+@item __sec_reduce
+@item __sec_reduce_add
+@item __sec_reduce_all_nonzero
+@item __sec_reduce_all_zero
+@item __sec_reduce_any_nonzero
+@item __sec_reduce_any_zero
+@item __sec_reduce_max
+@item __sec_reduce_min
+@item __sec_reduce_max_ind
+@item __sec_reduce_min_ind
+@item __sec_reduce_mul
+@item __sec_reduce_mutating
+@end itemize
+
+Further details and examples about these built-in functions are described
+in the Cilk Plus language manual which can be found at
+@uref{http://www.cilkplus.org}.
+
@node Other Builtins
@section Other Built-in Functions Provided by GCC
@cindex built-in functions
@@ -8835,32 +9162,6 @@ Similar to @code{__builtin_bswap32}, except the argument and return types
are 64 bit.
@end deftypefn
-@node Cilk Plus Builtins
-@section Cilk Plus C/C++ language extension Built-in Functions.
-
-GCC provides support for the following built-in reduction funtions if Cilk Plus
-is enabled. Cilk Plus can be enabled using the @option{-fcilkplus} flag.
-
-@itemize @bullet
-@item __sec_implicit_index
-@item __sec_reduce
-@item __sec_reduce_add
-@item __sec_reduce_all_nonzero
-@item __sec_reduce_all_zero
-@item __sec_reduce_any_nonzero
-@item __sec_reduce_any_zero
-@item __sec_reduce_max
-@item __sec_reduce_min
-@item __sec_reduce_max_ind
-@item __sec_reduce_min_ind
-@item __sec_reduce_mul
-@item __sec_reduce_mutating
-@end itemize
-
-Further details and examples about these built-in functions are described
-in the Cilk Plus language manual which can be found at
-@uref{http://www.cilkplus.org}.
-
@node Target Builtins
@section Built-in Functions Specific to Particular Target Machines
@@ -8870,6 +9171,8 @@ instructions, but allow the compiler to schedule those calls.
@menu
* Alpha Built-in Functions::
+* ARC Built-in Functions::
+* ARC SIMD Built-in Functions::
* ARM iWMMXt Built-in Functions::
* ARM NEON Intrinsics::
* AVR Built-in Functions::
@@ -8882,6 +9185,7 @@ instructions, but allow the compiler to schedule those calls.
* MIPS Loongson Built-in Functions::
* Other MIPS Built-in Functions::
* MSP430 Built-in Functions::
+* NDS32 Built-in Functions::
* picoChip Built-in Functions::
* PowerPC Built-in Functions::
* PowerPC AltiVec/VSX Built-in Functions::
@@ -8977,6 +9281,430 @@ void *__builtin_thread_pointer (void)
void __builtin_set_thread_pointer (void *)
@end smallexample
+@node ARC Built-in Functions
+@subsection ARC Built-in Functions
+
+The following built-in functions are provided for ARC targets. The
+built-ins generate the corresponding assembly instructions. In the
+examples given below, the generated code often requires an operand or
+result to be in a register. Where necessary further code will be
+generated to ensure this is true, but for brevity this is not
+described in each case.
+
+@emph{Note:} Using a built-in to generate an instruction not supported
+by a target may cause problems. At present the compiler is not
+guaranteed to detect such misuse, and as a result an internal compiler
+error may be generated.
+
+@deftypefn {Built-in Function} int __builtin_arc_aligned (void *@var{val}, int @var{alignval})
+Return 1 if @var{val} is known to have the byte alignment given
+by @var{alignval}, otherwise return 0.
+Note that this is different from
+@smallexample
+__alignof__(*(char *)@var{val}) >= alignval
+@end smallexample
+because __alignof__ sees only the type of the dereference, whereas
+__builtin_arc_align uses alignment information from the pointer
+as well as from the pointed-to type.
+The information available will depend on optimization level.
+@end deftypefn
+
+@deftypefn {Built-in Function} void __builtin_arc_brk (void)
+Generates
+@example
+brk
+@end example
+@end deftypefn
+
+@deftypefn {Built-in Function} {unsigned int} __builtin_arc_core_read (unsigned int @var{regno})
+The operand is the number of a register to be read. Generates:
+@example
+mov @var{dest}, r@var{regno}
+@end example
+where the value in @var{dest} will be the result returned from the
+built-in.
+@end deftypefn
+
+@deftypefn {Built-in Function} void __builtin_arc_core_write (unsigned int @var{regno}, unsigned int @var{val})
+The first operand is the number of a register to be written, the
+second operand is a compile time constant to write into that
+register. Generates:
+@example
+mov r@var{regno}, @var{val}
+@end example
+@end deftypefn
+
+@deftypefn {Built-in Function} int __builtin_arc_divaw (int @var{a}, int @var{b})
+Only available if either @option{-mcpu=ARC700} or @option{-meA} is set.
+Generates:
+@example
+divaw @var{dest}, @var{a}, @var{b}
+@end example
+where the value in @var{dest} will be the result returned from the
+built-in.
+@end deftypefn
+
+@deftypefn {Built-in Function} void __builtin_arc_flag (unsigned int @var{a})
+Generates
+@example
+flag @var{a}
+@end example
+@end deftypefn
+
+@deftypefn {Built-in Function} {unsigned int} __builtin_arc_lr (unsigned int @var{auxr})
+The operand, @var{auxv}, is the address of an auxiliary register and
+must be a compile time constant. Generates:
+@example
+lr @var{dest}, [@var{auxr}]
+@end example
+Where the value in @var{dest} will be the result returned from the
+built-in.
+@end deftypefn
+
+@deftypefn {Built-in Function} void __builtin_arc_mul64 (int @var{a}, int @var{b})
+Only available with @option{-mmul64}. Generates:
+@example
+mul64 @var{a}, @var{b}
+@end example
+@end deftypefn
+
+@deftypefn {Built-in Function} void __builtin_arc_mulu64 (unsigned int @var{a}, unsigned int @var{b})
+Only available with @option{-mmul64}. Generates:
+@example
+mulu64 @var{a}, @var{b}
+@end example
+@end deftypefn
+
+@deftypefn {Built-in Function} void __builtin_arc_nop (void)
+Generates:
+@example
+nop
+@end example
+@end deftypefn
+
+@deftypefn {Built-in Function} int __builtin_arc_norm (int @var{src})
+Only valid if the @samp{norm} instruction is available through the
+@option{-mnorm} option or by default with @option{-mcpu=ARC700}.
+Generates:
+@example
+norm @var{dest}, @var{src}
+@end example
+Where the value in @var{dest} will be the result returned from the
+built-in.
+@end deftypefn
+
+@deftypefn {Built-in Function} {short int} __builtin_arc_normw (short int @var{src})
+Only valid if the @samp{normw} instruction is available through the
+@option{-mnorm} option or by default with @option{-mcpu=ARC700}.
+Generates:
+@example
+normw @var{dest}, @var{src}
+@end example
+Where the value in @var{dest} will be the result returned from the
+built-in.
+@end deftypefn
+
+@deftypefn {Built-in Function} void __builtin_arc_rtie (void)
+Generates:
+@example
+rtie
+@end example
+@end deftypefn
+
+@deftypefn {Built-in Function} void __builtin_arc_sleep (int @var{a}
+Generates:
+@example
+sleep @var{a}
+@end example
+@end deftypefn
+
+@deftypefn {Built-in Function} void __builtin_arc_sr (unsigned int @var{auxr}, unsigned int @var{val})
+The first argument, @var{auxv}, is the address of an auxiliary
+register, the second argument, @var{val}, is a compile time constant
+to be written to the register. Generates:
+@example
+sr @var{auxr}, [@var{val}]
+@end example
+@end deftypefn
+
+@deftypefn {Built-in Function} int __builtin_arc_swap (int @var{src})
+Only valid with @option{-mswap}. Generates:
+@example
+swap @var{dest}, @var{src}
+@end example
+Where the value in @var{dest} will be the result returned from the
+built-in.
+@end deftypefn
+
+@deftypefn {Built-in Function} void __builtin_arc_swi (void)
+Generates:
+@example
+swi
+@end example
+@end deftypefn
+
+@deftypefn {Built-in Function} void __builtin_arc_sync (void)
+Only available with @option{-mcpu=ARC700}. Generates:
+@example
+sync
+@end example
+@end deftypefn
+
+@deftypefn {Built-in Function} void __builtin_arc_trap_s (unsigned int @var{c})
+Only available with @option{-mcpu=ARC700}. Generates:
+@example
+trap_s @var{c}
+@end example
+@end deftypefn
+
+@deftypefn {Built-in Function} void __builtin_arc_unimp_s (void)
+Only available with @option{-mcpu=ARC700}. Generates:
+@example
+unimp_s
+@end example
+@end deftypefn
+
+The instructions generated by the following builtins are not
+considered as candidates for scheduling. They are not moved around by
+the compiler during scheduling, and thus can be expected to appear
+where they are put in the C code:
+@example
+__builtin_arc_brk()
+__builtin_arc_core_read()
+__builtin_arc_core_write()
+__builtin_arc_flag()
+__builtin_arc_lr()
+__builtin_arc_sleep()
+__builtin_arc_sr()
+__builtin_arc_swi()
+@end example
+
+@node ARC SIMD Built-in Functions
+@subsection ARC SIMD Built-in Functions
+
+SIMD builtins provided by the compiler can be used to generate the
+vector instructions. This section describes the available builtins
+and their usage in programs. With the @option{-msimd} option, the
+compiler provides 128-bit vector types, which can be specified using
+the @code{vector_size} attribute. The header file @file{arc-simd.h}
+can be included to use the following predefined types:
+@example
+typedef int __v4si __attribute__((vector_size(16)));
+typedef short __v8hi __attribute__((vector_size(16)));
+@end example
+
+These types can be used to define 128-bit variables. The built-in
+functions listed in the following section can be used on these
+variables to generate the vector operations.
+
+For all builtins, @code{__builtin_arc_@var{someinsn}}, the header file
+@file{arc-simd.h} also provides equivalent macros called
+@code{_@var{someinsn}} that can be used for programming ease and
+improved readability. The following macros for DMA control are also
+provided:
+@example
+#define _setup_dma_in_channel_reg _vdiwr
+#define _setup_dma_out_channel_reg _vdowr
+@end example
+
+The following is a complete list of all the SIMD built-ins provided
+for ARC, grouped by calling signature.
+
+The following take two @code{__v8hi} arguments and return a
+@code{__v8hi} result:
+@example
+__v8hi __builtin_arc_vaddaw (__v8hi, __v8hi)
+__v8hi __builtin_arc_vaddw (__v8hi, __v8hi)
+__v8hi __builtin_arc_vand (__v8hi, __v8hi)
+__v8hi __builtin_arc_vandaw (__v8hi, __v8hi)
+__v8hi __builtin_arc_vavb (__v8hi, __v8hi)
+__v8hi __builtin_arc_vavrb (__v8hi, __v8hi)
+__v8hi __builtin_arc_vbic (__v8hi, __v8hi)
+__v8hi __builtin_arc_vbicaw (__v8hi, __v8hi)
+__v8hi __builtin_arc_vdifaw (__v8hi, __v8hi)
+__v8hi __builtin_arc_vdifw (__v8hi, __v8hi)
+__v8hi __builtin_arc_veqw (__v8hi, __v8hi)
+__v8hi __builtin_arc_vh264f (__v8hi, __v8hi)
+__v8hi __builtin_arc_vh264ft (__v8hi, __v8hi)
+__v8hi __builtin_arc_vh264fw (__v8hi, __v8hi)
+__v8hi __builtin_arc_vlew (__v8hi, __v8hi)
+__v8hi __builtin_arc_vltw (__v8hi, __v8hi)
+__v8hi __builtin_arc_vmaxaw (__v8hi, __v8hi)
+__v8hi __builtin_arc_vmaxw (__v8hi, __v8hi)
+__v8hi __builtin_arc_vminaw (__v8hi, __v8hi)
+__v8hi __builtin_arc_vminw (__v8hi, __v8hi)
+__v8hi __builtin_arc_vmr1aw (__v8hi, __v8hi)
+__v8hi __builtin_arc_vmr1w (__v8hi, __v8hi)
+__v8hi __builtin_arc_vmr2aw (__v8hi, __v8hi)
+__v8hi __builtin_arc_vmr2w (__v8hi, __v8hi)
+__v8hi __builtin_arc_vmr3aw (__v8hi, __v8hi)
+__v8hi __builtin_arc_vmr3w (__v8hi, __v8hi)
+__v8hi __builtin_arc_vmr4aw (__v8hi, __v8hi)
+__v8hi __builtin_arc_vmr4w (__v8hi, __v8hi)
+__v8hi __builtin_arc_vmr5aw (__v8hi, __v8hi)
+__v8hi __builtin_arc_vmr5w (__v8hi, __v8hi)
+__v8hi __builtin_arc_vmr6aw (__v8hi, __v8hi)
+__v8hi __builtin_arc_vmr6w (__v8hi, __v8hi)
+__v8hi __builtin_arc_vmr7aw (__v8hi, __v8hi)
+__v8hi __builtin_arc_vmr7w (__v8hi, __v8hi)
+__v8hi __builtin_arc_vmrb (__v8hi, __v8hi)
+__v8hi __builtin_arc_vmulaw (__v8hi, __v8hi)
+__v8hi __builtin_arc_vmulfaw (__v8hi, __v8hi)
+__v8hi __builtin_arc_vmulfw (__v8hi, __v8hi)
+__v8hi __builtin_arc_vmulw (__v8hi, __v8hi)
+__v8hi __builtin_arc_vnew (__v8hi, __v8hi)
+__v8hi __builtin_arc_vor (__v8hi, __v8hi)
+__v8hi __builtin_arc_vsubaw (__v8hi, __v8hi)
+__v8hi __builtin_arc_vsubw (__v8hi, __v8hi)
+__v8hi __builtin_arc_vsummw (__v8hi, __v8hi)
+__v8hi __builtin_arc_vvc1f (__v8hi, __v8hi)
+__v8hi __builtin_arc_vvc1ft (__v8hi, __v8hi)
+__v8hi __builtin_arc_vxor (__v8hi, __v8hi)
+__v8hi __builtin_arc_vxoraw (__v8hi, __v8hi)
+@end example
+
+The following take one @code{__v8hi} and one @code{int} argument and return a
+@code{__v8hi} result:
+
+@example
+__v8hi __builtin_arc_vbaddw (__v8hi, int)
+__v8hi __builtin_arc_vbmaxw (__v8hi, int)
+__v8hi __builtin_arc_vbminw (__v8hi, int)
+__v8hi __builtin_arc_vbmulaw (__v8hi, int)
+__v8hi __builtin_arc_vbmulfw (__v8hi, int)
+__v8hi __builtin_arc_vbmulw (__v8hi, int)
+__v8hi __builtin_arc_vbrsubw (__v8hi, int)
+__v8hi __builtin_arc_vbsubw (__v8hi, int)
+@end example
+
+The following take one @code{__v8hi} argument and one @code{int} argument which
+must be a 3-bit compile time constant indicating a register number
+I0-I7. They return a @code{__v8hi} result.
+@example
+__v8hi __builtin_arc_vasrw (__v8hi, const int)
+__v8hi __builtin_arc_vsr8 (__v8hi, const int)
+__v8hi __builtin_arc_vsr8aw (__v8hi, const int)
+@end example
+
+The following take one @code{__v8hi} argument and one @code{int}
+argument which must be a 6-bit compile time constant. They return a
+@code{__v8hi} result.
+@example
+__v8hi __builtin_arc_vasrpwbi (__v8hi, const int)
+__v8hi __builtin_arc_vasrrpwbi (__v8hi, const int)
+__v8hi __builtin_arc_vasrrwi (__v8hi, const int)
+__v8hi __builtin_arc_vasrsrwi (__v8hi, const int)
+__v8hi __builtin_arc_vasrwi (__v8hi, const int)
+__v8hi __builtin_arc_vsr8awi (__v8hi, const int)
+__v8hi __builtin_arc_vsr8i (__v8hi, const int)
+@end example
+
+The following take one @code{__v8hi} argument and one @code{int} argument which
+must be a 8-bit compile time constant. They return a @code{__v8hi}
+result.
+@example
+__v8hi __builtin_arc_vd6tapf (__v8hi, const int)
+__v8hi __builtin_arc_vmvaw (__v8hi, const int)
+__v8hi __builtin_arc_vmvw (__v8hi, const int)
+__v8hi __builtin_arc_vmvzw (__v8hi, const int)
+@end example
+
+The following take two @code{int} arguments, the second of which which
+must be a 8-bit compile time constant. They return a @code{__v8hi}
+result:
+@example
+__v8hi __builtin_arc_vmovaw (int, const int)
+__v8hi __builtin_arc_vmovw (int, const int)
+__v8hi __builtin_arc_vmovzw (int, const int)
+@end example
+
+The following take a single @code{__v8hi} argument and return a
+@code{__v8hi} result:
+@example
+__v8hi __builtin_arc_vabsaw (__v8hi)
+__v8hi __builtin_arc_vabsw (__v8hi)
+__v8hi __builtin_arc_vaddsuw (__v8hi)
+__v8hi __builtin_arc_vexch1 (__v8hi)
+__v8hi __builtin_arc_vexch2 (__v8hi)
+__v8hi __builtin_arc_vexch4 (__v8hi)
+__v8hi __builtin_arc_vsignw (__v8hi)
+__v8hi __builtin_arc_vupbaw (__v8hi)
+__v8hi __builtin_arc_vupbw (__v8hi)
+__v8hi __builtin_arc_vupsbaw (__v8hi)
+__v8hi __builtin_arc_vupsbw (__v8hi)
+@end example
+
+The followign take two @code{int} arguments and return no result:
+@example
+void __builtin_arc_vdirun (int, int)
+void __builtin_arc_vdorun (int, int)
+@end example
+
+The following take two @code{int} arguments and return no result. The
+first argument must a 3-bit compile time constant indicating one of
+the DR0-DR7 DMA setup channels:
+@example
+void __builtin_arc_vdiwr (const int, int)
+void __builtin_arc_vdowr (const int, int)
+@end example
+
+The following take an @code{int} argument and return no result:
+@example
+void __builtin_arc_vendrec (int)
+void __builtin_arc_vrec (int)
+void __builtin_arc_vrecrun (int)
+void __builtin_arc_vrun (int)
+@end example
+
+The following take a @code{__v8hi} argument and two @code{int}
+arguments and return a @code{__v8hi} result. The second argument must
+be a 3-bit compile time constants, indicating one the registers I0-I7,
+and the third argument must be an 8-bit compile time constant.
+
+@emph{Note:} Although the equivalent hardware instructions do not take
+an SIMD register as an operand, these builtins overwrite the relevant
+bits of the @code{__v8hi} register provided as the first argument with
+the value loaded from the @code{[Ib, u8]} location in the SDM.
+
+@example
+__v8hi __builtin_arc_vld32 (__v8hi, const int, const int)
+__v8hi __builtin_arc_vld32wh (__v8hi, const int, const int)
+__v8hi __builtin_arc_vld32wl (__v8hi, const int, const int)
+__v8hi __builtin_arc_vld64 (__v8hi, const int, const int)
+@end example
+
+The following take two @code{int} arguments and return a @code{__v8hi}
+result. The first argument must be a 3-bit compile time constants,
+indicating one the registers I0-I7, and the second argument must be an
+8-bit compile time constant.
+
+@example
+__v8hi __builtin_arc_vld128 (const int, const int)
+__v8hi __builtin_arc_vld64w (const int, const int)
+@end example
+
+The following take a @code{__v8hi} argument and two @code{int}
+arguments and return no result. The second argument must be a 3-bit
+compile time constants, indicating one the registers I0-I7, and the
+third argument must be an 8-bit compile time constant.
+
+@example
+void __builtin_arc_vst128 (__v8hi, const int, const int)
+void __builtin_arc_vst64 (__v8hi, const int, const int)
+@end example
+
+The following take a @code{__v8hi} argument and three @code{int}
+arguments and return no result. The second argument must be a 3-bit
+compile-time constant, identifying the 16-bit sub-register to be
+stored, the third argument must be a 3-bit compile time constants,
+indicating one the registers I0-I7, and the fourth argument must be an
+8-bit compile time constant.
+
+@example
+void __builtin_arc_vst16_n (__v8hi, const int, const int, const int)
+void __builtin_arc_vst32_n (__v8hi, const int, const int, const int)
+@end example
+
@node ARM iWMMXt Built-in Functions
@subsection ARM iWMMXt Built-in Functions
@@ -11911,6 +12639,44 @@ handlers and the changes to the status register will only take affect
once the handler returns.
@end table
+@node NDS32 Built-in Functions
+@subsection NDS32 Built-in Functions
+
+These built-in functions are available for the NDS32 target:
+
+@deftypefn {Built-in Function} void __builtin_nds32_isync (int *@var{addr})
+Insert an ISYNC instruction into the instruction stream where
+@var{addr} is an instruction address for serialization.
+@end deftypefn
+
+@deftypefn {Built-in Function} void __builtin_nds32_isb (void)
+Insert an ISB instruction into the instruction stream.
+@end deftypefn
+
+@deftypefn {Built-in Function} int __builtin_nds32_mfsr (int @var{sr})
+Return the content of a system register which is mapped by @var{sr}.
+@end deftypefn
+
+@deftypefn {Built-in Function} int __builtin_nds32_mfusr (int @var{usr})
+Return the content of a user space register which is mapped by @var{usr}.
+@end deftypefn
+
+@deftypefn {Built-in Function} void __builtin_nds32_mtsr (int @var{value}, int @var{sr})
+Move the @var{value} to a system register which is mapped by @var{sr}.
+@end deftypefn
+
+@deftypefn {Built-in Function} void __builtin_nds32_mtusr (int @var{value}, int @var{usr})
+Move the @var{value} to a user space register which is mapped by @var{usr}.
+@end deftypefn
+
+@deftypefn {Built-in Function} void __builtin_nds32_setgie_en (void)
+Enable global interrupt.
+@end deftypefn
+
+@deftypefn {Built-in Function} void __builtin_nds32_setgie_dis (void)
+Disable global interrupt.
+@end deftypefn
+
@node picoChip Built-in Functions
@subsection picoChip Built-in Functions
@@ -14594,7 +15360,7 @@ depth is returned as integer value. For a nesting depth of 0 the code
is not executed as part of an transaction.
@end deftypefn
-@deftypefn {Built-in Function} void __builtin_non_tx_store (unsigned long long *, unsigned long long)
+@deftypefn {Built-in Function} void __builtin_non_tx_store (uint64_t *, uint64_t)
Generates the @code{ntstg} machine instruction. The second argument
is written to the first arguments location. The store operation will
@@ -15006,6 +15772,7 @@ for further explanation.
* Visibility Pragmas::
* Push/Pop Macro Pragmas::
* Function Specific Option Pragmas::
+* Loop-Specific Pragmas::
@end menu
@node ARM Pragmas
@@ -15528,6 +16295,48 @@ The @samp{#pragma GCC reset_options} pragma is not implemented in GCC
versions earlier than 4.4.
@end table
+@node Loop-Specific Pragmas
+@subsection Loop-Specific Pragmas
+
+@table @code
+@item #pragma GCC ivdep
+@cindex pragma GCC ivdep
+@end table
+
+With this pragma, the programmer asserts that there are no loop-carried
+dependencies which would prevent that consecutive iterations of
+the following loop can be executed concurrently with SIMD
+(single instruction multiple data) instructions.
+
+For example, the compiler can only unconditionally vectorize the following
+loop with the pragma:
+
+@smallexample
+void foo (int n, int *a, int *b, int *c)
+@{
+ int i, j;
+#pragma GCC ivdep
+ for (i = 0; i < n; ++i)
+ a[i] = b[i] + c[i];
+@}
+@end smallexample
+
+@noindent
+In this example, using the @code{restrict} qualifier had the same
+effect. In the following example, that would not be possible. Assume
+@math{k < -m} or @math{k >= m}. Only with the pragma, the compiler knows
+that it can unconditionally vectorize the following loop:
+
+@smallexample
+void ignore_vec_dep (int *a, int k, int c, int m)
+@{
+#pragma GCC ivdep
+ for (int i = 0; i < m; i++)
+ a[i] = a[i + k] * c;
+@}
+@end smallexample
+
+
@node Unnamed Fields
@section Unnamed struct/union fields within structs/unions
@cindex @code{struct}
@@ -16831,3 +17640,6 @@ implicitly scoped inside a C language scope. Also, an empty prototype
@code{()} is treated as an unspecified number of arguments, rather
than no arguments, as C++ demands.
@end table
+
+@c LocalWords: emph deftypefn builtin ARCv2EM SIMD builtins msimd
+@c LocalWords: typedef v4si v8hi DMA dma vdiwr vdowr followign
diff --git a/gcc/doc/gcc.texi b/gcc/doc/gcc.texi
index 02b81cf86ec..55307cd35ee 100644
--- a/gcc/doc/gcc.texi
+++ b/gcc/doc/gcc.texi
@@ -83,11 +83,11 @@ This file documents the use of the GNU compilers.
Published by:
@multitable @columnfractions 0.5 0.5
@item GNU Press
-@tab Website: www.gnupress.org
+@tab Website: @uref{http://www.gnupress.org}
@item a division of the
-@tab General: @tex press@@gnu.org @end tex
+@tab General: @email{press@@gnu.org}
@item Free Software Foundation
-@tab Orders: @tex sales@@gnu.org @end tex
+@tab Orders: @email{sales@@gnu.org}
@item 51 Franklin Street, Fifth Floor
@tab Tel 617-542-5942
@item Boston, MA 02110-1301 USA
diff --git a/gcc/doc/generic.texi b/gcc/doc/generic.texi
index cacab01f9a4..f2dd0ffae65 100644
--- a/gcc/doc/generic.texi
+++ b/gcc/doc/generic.texi
@@ -924,6 +924,11 @@ structures, something like the following should be used
(BASE_STRUCT_CHECK(NODE)->base_struct.fieldname
@end smallexample
+Reading them from the generated @file{all-tree.def} file (which in
+turn includes all the @file{tree.def} files), @file{gencheck.c} is
+used during GCC's build to generate the @code{*_CHECK} macros for all
+tree codes.
+
@end table
@@ -1274,6 +1279,7 @@ the byte offset of the field, but should not be used directly; call
@tindex SAVE_EXPR
@tindex TARGET_EXPR
@tindex VA_ARG_EXPR
+@tindex ANNOTATE_EXPR
@table @code
@item NEGATE_EXPR
@@ -1610,29 +1616,31 @@ of temporaries during the evaluation of that expression should be
performed immediately after the expression is evaluated.
@item CONSTRUCTOR
-These nodes represent the brace-enclosed initializers for a structure or
-array. The first operand is reserved for use by the back end. The
-second operand is a @code{TREE_LIST}. If the @code{TREE_TYPE} of the
-@code{CONSTRUCTOR} is a @code{RECORD_TYPE} or @code{UNION_TYPE}, then
-the @code{TREE_PURPOSE} of each node in the @code{TREE_LIST} will be a
-@code{FIELD_DECL} and the @code{TREE_VALUE} of each node will be the
-expression used to initialize that field.
-
-If the @code{TREE_TYPE} of the @code{CONSTRUCTOR} is an
-@code{ARRAY_TYPE}, then the @code{TREE_PURPOSE} of each element in the
-@code{TREE_LIST} will be an @code{INTEGER_CST} or a @code{RANGE_EXPR} of
-two @code{INTEGER_CST}s. A single @code{INTEGER_CST} indicates which
-element of the array (indexed from zero) is being assigned to. A
-@code{RANGE_EXPR} indicates an inclusive range of elements to
-initialize. In both cases the @code{TREE_VALUE} is the corresponding
+These nodes represent the brace-enclosed initializers for a structure or an
+array. They contain a sequence of component values made out of a vector of
+constructor_elt, which is a (@code{INDEX}, @code{VALUE}) pair.
+
+If the @code{TREE_TYPE} of the @code{CONSTRUCTOR} is a @code{RECORD_TYPE},
+@code{UNION_TYPE} or @code{QUAL_UNION_TYPE} then the @code{INDEX} of each
+node in the sequence will be a @code{FIELD_DECL} and the @code{VALUE} will
+be the expression used to initialize that field.
+
+If the @code{TREE_TYPE} of the @code{CONSTRUCTOR} is an @code{ARRAY_TYPE},
+then the @code{INDEX} of each node in the sequence will be an
+@code{INTEGER_CST} or a @code{RANGE_EXPR} of two @code{INTEGER_CST}s.
+A single @code{INTEGER_CST} indicates which element of the array is being
+assigned to. A @code{RANGE_EXPR} indicates an inclusive range of elements
+to initialize. In both cases the @code{VALUE} is the corresponding
initializer. It is re-evaluated for each element of a
-@code{RANGE_EXPR}. If the @code{TREE_PURPOSE} is @code{NULL_TREE}, then
+@code{RANGE_EXPR}. If the @code{INDEX} is @code{NULL_TREE}, then
the initializer is for the next available array element.
In the front end, you should not depend on the fields appearing in any
particular order. However, in the middle end, fields must appear in
declaration order. You should not assume that all fields will be
-represented. Unrepresented fields will be set to zero.
+represented. Unrepresented fields will be cleared (zeroed), unless the
+CONSTRUCTOR_NO_CLEARING flag is set, in which case their value becomes
+undefined.
@item COMPOUND_LITERAL_EXPR
@findex COMPOUND_LITERAL_EXPR_DECL_EXPR
@@ -1687,8 +1695,13 @@ mechanism. It represents expressions like @code{va_arg (ap, type)}.
Its @code{TREE_TYPE} yields the tree representation for @code{type} and
its sole argument yields the representation for @code{ap}.
+@item ANNOTATE_EXPR
+This node is used to attach markers to an expression. The first operand
+is the annotated expression, the second is an @code{INTEGER_CST} with
+a value from @code{enum annot_expr_kind}.
@end table
+
@node Vectors
@subsection Vectors
@tindex VEC_LSHIFT_EXPR
@@ -2199,7 +2212,7 @@ regular critical section around the expression is used.
@item OMP_CLAUSE
Represents clauses associated with one of the @code{OMP_} directives.
-Clauses are represented by separate sub-codes defined in
+Clauses are represented by separate subcodes defined in
@file{tree.h}. Clauses codes can be one of:
@code{OMP_CLAUSE_PRIVATE}, @code{OMP_CLAUSE_SHARED},
@code{OMP_CLAUSE_FIRSTPRIVATE},
@@ -3155,6 +3168,30 @@ several statements chained together.
Used to represent a @code{break} statement. There are no additional
fields.
+@item CILK_SPAWN_STMT
+
+Used to represent a spawning function in the Cilk Plus language extension.
+This tree has one field that holds the name of the spawning function.
+@code{_Cilk_spawn} can be written in C in the following way:
+
+@smallexample
+@code{_Cilk_spawn} <function_name> (<parameters>);
+@end smallexample
+
+Detailed description for usage and functionality of @code{_Cilk_spawn} can be
+found at http://www.cilkplus.org
+
+@item CILK_SYNC_STMT
+
+This statement is part of the Cilk Plus language extension. It indicates that
+the current function cannot continue in parallel with its spawned children.
+There are no additional fields. @code{_Cilk_sync} can be written in C in the
+following way:
+
+@smallexample
+@code{_Cilk_sync};
+@end smallexample
+
@item CLEANUP_STMT
Used to represent an action that should take place upon exit from the
diff --git a/gcc/doc/gimple.texi b/gcc/doc/gimple.texi
index 896aea355bc..7bd9fd51b78 100644
--- a/gcc/doc/gimple.texi
+++ b/gcc/doc/gimple.texi
@@ -711,6 +711,10 @@ Return true if g is a @code{GIMPLE_DEBUG} that binds the value of an
expression to a variable.
@end deftypefn
+@deftypefn {GIMPLE function} bool is_gimple_omp (gimple g)
+Return true if g is any of the OpenMP codes.
+@end deftypefn
+
@node Manipulating GIMPLE statements
@section Manipulating GIMPLE statements
@cindex Manipulating GIMPLE statements
@@ -1846,11 +1850,6 @@ Return a pointer to the data argument for @code{OMP_PARALLEL} @code{G}.
Set @code{DATA_ARG} to be the data argument for @code{OMP_PARALLEL} @code{G}.
@end deftypefn
-@deftypefn {GIMPLE function} bool is_gimple_omp (gimple stmt)
-Returns true when the gimple statement @code{STMT} is any of the OpenMP
-types.
-@end deftypefn
-
@node @code{GIMPLE_OMP_RETURN}
@subsection @code{GIMPLE_OMP_RETURN}
diff --git a/gcc/doc/gty.texi b/gcc/doc/gty.texi
index 82e8e4f728f..a64d110a980 100644
--- a/gcc/doc/gty.texi
+++ b/gcc/doc/gty.texi
@@ -87,6 +87,7 @@ data members.
@menu
* GTY Options:: What goes inside a @code{GTY(())}.
+* Inheritance and GTY:: Adding GTY to a class hierarchy.
* User GC:: Adding user-provided GC marking routines.
* GGC Roots:: Making global variables GGC roots.
* Files:: How the generated files work.
@@ -234,6 +235,10 @@ In this example, the value of BINDING_HAS_LEVEL_P when applied to a
mechanism will treat the field @code{level} as being present and if 0,
will treat the field @code{scope} as being present.
+The @code{desc} and @code{tag} options can also be used for inheritance
+to denote which subclass an instance is. See @ref{Inheritance and GTY}
+for more information.
+
@findex param_is
@findex use_param
@item param_is (@var{type})
@@ -470,6 +475,60 @@ fields is completely handled by user-provided routines. See section
@ref{User GC} for details on what functions need to be provided.
@end table
+@node Inheritance and GTY
+@section Support for inheritance
+gengtype has some support for simple class hierarchies. You can use
+this to have gengtype autogenerate marking routines, provided:
+
+@itemize @bullet
+@item
+There must be a concrete base class, with a discriminator expression
+that can be used to identify which subclass an instance is.
+@item
+Only single inheritance is used.
+@item
+None of the classes within the hierarchy are templates.
+@end itemize
+
+If your class hierarchy does not fit in this pattern, you must use
+@ref{User GC} instead.
+
+The base class and its discriminator must be identified using the ``desc''
+option. Each concrete subclass must use the ``tag'' option to identify
+which value of the discriminator it corresponds to.
+
+Every class in the hierarchy must have a @code{GTY(())} marker, as
+gengtype will only attempt to parse classes that have such a marker
+@footnote{Classes lacking such a marker will not be identified as being
+part of the hierarchy, and so the marking routines will not handle them,
+leading to a assertion failure within the marking routines due to an
+unknown tag value (assuming that assertions are enabled).}.
+
+@smallexample
+class GTY((desc("%h.kind"), tag("0"))) example_base
+@{
+public:
+ int kind;
+ tree a;
+@};
+
+class GTY((tag("1")) some_subclass : public example_base
+@{
+public:
+ tree b;
+@};
+
+class GTY((tag("2")) some_other_subclass : public example_base
+@{
+public:
+ tree c;
+@};
+@end smallexample
+
+The generated marking routines for the above will contain a ``switch''
+on ``kind'', visiting all appropriate fields. For example, if kind is
+2, it will cast to ``some_other_subclass'' and visit fields a, b, and c.
+
@node User GC
@section Support for user-provided GC marking routines
@cindex user gc
diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
index 0011b68065b..fa5d6e5a611 100644
--- a/gcc/doc/install.texi
+++ b/gcc/doc/install.texi
@@ -925,6 +925,19 @@ Use @option{--disable-shared} to build only static libraries. Note that
@option{--disable-shared} does not accept a list of package names as
argument, only @option{--enable-shared} does.
+Contrast with @option{--enable-host-shared}, which affects @emph{host}
+code.
+
+@item --enable-host-shared
+Specify that the @emph{host} code should be built into position-independent
+machine code (with -fPIC), allowing it to be used within shared libraries,
+but yielding a slightly slower compiler.
+
+Currently this option is only of use to people developing GCC itself.
+
+Contrast with @option{--enable-shared}, which affects @emph{target}
+libraries.
+
@item @anchor{with-gnu-as}--with-gnu-as
Specify that the compiler should assume that the
assembler it finds is the GNU assembler. However, this does not modify
@@ -1200,8 +1213,8 @@ This is an alias for @option{--enable-tls=no}.
@itemx --with-cpu-64=@var{cpu}
Specify which cpu variant the compiler should generate code for by default.
@var{cpu} will be used as the default value of the @option{-mcpu=} switch.
-This option is only supported on some targets, including ARM, i386, M68k,
-PowerPC, and SPARC@. The @option{--with-cpu-32} and
+This option is only supported on some targets, including ARC, ARM, i386, M68k,
+PowerPC, and SPARC@. It is mandatory for ARC@. The @option{--with-cpu-32} and
@option{--with-cpu-64} options specify separate default CPUs for
32-bit and 64-bit modes; these options are only supported for i386,
x86-64 and PowerPC.
@@ -1378,7 +1391,7 @@ addition, @samp{libstdc++}'s include files will be installed into
@option{--with-gxx-include-dir=@var{dirname}}. Using this option is
particularly useful if you intend to use several versions of GCC in
parallel. This is currently supported by @samp{libgfortran},
-@samp{libjava}, @samp{libmudflap}, @samp{libstdc++}, and @samp{libobjc}.
+@samp{libjava}, @samp{libstdc++}, and @samp{libobjc}.
@item --enable-languages=@var{lang1},@var{lang2},@dots{}
Specify that only a particular subset of compilers and
@@ -1849,6 +1862,11 @@ This option is only supported for the AVR target. It is not supported for
RTEMS configurations, which currently use newlib. The option is
supported since version 4.7.2 and is the default in 4.8.0 and newer.
+@item --with-nds32-lib=@var{library}
+Specifies that @var{library} setting is used for building @file{libgcc.a}.
+Currently, the valid @var{library} is @samp{newlib} or @samp{mculib}.
+This option is only supported for the NDS32 target.
+
@item --with-build-time-tools=@var{dir}
Specifies where to find the set of target tools (assembler, linker, etc.)
that will be used while building GCC itself. This option can be useful
@@ -3173,8 +3191,8 @@ information have to.
<!-- -------- host/target specific issues start here ---------------- -->
<hr />
@end html
-@heading @anchor{alpha-x-x}alpha*-*-*
-
+@anchor{alpha-x-x}
+@heading alpha*-*-*
This section contains general configuration information for all
alpha-based platforms using ELF (in particular, ignore this section for
DEC OSF/1, Digital UNIX and Tru64 UNIX)@. In addition to reading this
@@ -3188,7 +3206,8 @@ shared libraries.
@html
<hr />
@end html
-@heading @anchor{alpha-dec-osf51}alpha*-dec-osf5.1
+@anchor{alpha-dec-osf51}
+@heading alpha*-dec-osf5.1
Systems using processors that implement the DEC Alpha architecture and
are running the DEC/Compaq/HP Unix (DEC OSF/1, Digital UNIX, or Compaq/HP
Tru64 UNIX) operating system, for example the DEC Alpha AXP systems.
@@ -3201,14 +3220,33 @@ are the versions which identify themselves as DEC OSF/1.)
@html
<hr />
@end html
-@heading @anchor{amd64-x-solaris210}amd64-*-solaris2.1[0-9]*
-
+@anchor{amd64-x-solaris210}
+@heading amd64-*-solaris2.1[0-9]*
This is a synonym for @samp{x86_64-*-solaris2.1[0-9]*}.
@html
<hr />
@end html
-@heading @anchor{arm-x-eabi}arm-*-eabi
+@anchor{arc-x-elf32}
+@heading arc-*-elf32
+
+Use @samp{configure --target=arc-elf32 --with-cpu=@var{cpu} --enable-languages="c,c++"}
+to configure GCC, with @var{cpu} being one of @samp{arc600}, @samp{arc601},
+or @samp{arc700}@.
+
+@html
+<hr />
+@end html
+@anchor{arc-linux-uclibc}
+@heading arc-linux-uclibc
+
+Use @samp{configure --target=arc-linux-uclibc --with-cpu=arc700 --enable-languages="c,c++"} to configure GCC@.
+
+@html
+<hr />
+@end html
+@anchor{arm-x-eabi}
+@heading arm-*-eabi
ARM-family processors. Subtargets that use the ELF object format
require GNU binutils 2.13 or newer. Such subtargets include:
@code{arm-*-netbsdelf}, @code{arm-*-*linux-*}
@@ -3217,8 +3255,8 @@ and @code{arm-*-rtemseabi}.
@html
<hr />
@end html
-@heading @anchor{avr}avr
-
+@anchor{avr}
+@heading avr
ATMEL AVR-family micro controllers. These are used in embedded
applications. There are no standard Unix configurations.
@ifnothtml
@@ -3254,8 +3292,8 @@ indicates that you should upgrade to a newer version of the binutils.
@html
<hr />
@end html
-@heading @anchor{bfin}Blackfin
-
+@anchor{bfin}
+@heading Blackfin
The Blackfin processor, an Analog Devices DSP.
@ifnothtml
@xref{Blackfin Options,, Blackfin Options, gcc, Using the GNU Compiler
@@ -3271,10 +3309,10 @@ is available at @uref{http://blackfin.uclinux.org}
@html
<hr />
@end html
-@heading @anchor{cr16}CR16
-
-The CR16 CompactRISC architecture is a 16-bit architecture. This architecture is
-used in embedded applications.
+@anchor{cr16}
+@heading CR16
+The CR16 CompactRISC architecture is a 16-bit architecture. This
+architecture is used in embedded applications.
@ifnothtml
@xref{CR16 Options,, CR16 Options, gcc, Using and Porting the GNU Compiler
@@ -3288,14 +3326,14 @@ See ``CR16 Options'' in the main manual for a list of CR16-specific options.
Use @samp{configure --target=cr16-elf --enable-languages=c,c++} to configure
GCC@ for building a CR16 elf cross-compiler.
-Use @samp{configure --target=cr16-uclinux --enable-languages=c,c++} to configure
-GCC@ for building a CR16 uclinux cross-compiler.
+Use @samp{configure --target=cr16-uclinux --enable-languages=c,c++} to
+configure GCC@ for building a CR16 uclinux cross-compiler.
@html
<hr />
@end html
-@heading @anchor{cris}CRIS
-
+@anchor{cris}
+@heading CRIS
CRIS is the CPU architecture in Axis Communications ETRAX system-on-a-chip
series. These are used in embedded applications.
@@ -3329,8 +3367,8 @@ information about this platform is available at
@html
<hr />
@end html
-@heading @anchor{dos}DOS
-
+@anchor{dos}
+@heading DOS
Please have a look at the @uref{binaries.html,,binaries page}.
You cannot install GCC by itself on MSDOS; it will not compile under
@@ -3341,15 +3379,16 @@ and includes all the necessary compilation tools and libraries.
@html
<hr />
@end html
-@heading @anchor{epiphany-x-elf}epiphany-*-elf
+@anchor{epiphany-x-elf}
+@heading epiphany-*-elf
Adapteva Epiphany.
This configuration is intended for embedded systems.
@html
<hr />
@end html
-@heading @anchor{x-x-freebsd}*-*-freebsd*
-
+@anchor{x-x-freebsd}
+@heading *-*-freebsd*
Support for FreeBSD 1 was discontinued in GCC 3.2. Support for
FreeBSD 2 (and any mutant a.out variants of FreeBSD 3) was
discontinued in GCC 4.0.
@@ -3386,7 +3425,8 @@ the FreeBSD 7.0 release with GNU binutils after 2.16.1.
@html
<hr />
@end html
-@heading @anchor{h8300-hms}h8300-hms
+@anchor{h8300-hms}
+@heading h8300-hms
Renesas H8/300 series of processors.
Please have a look at the @uref{binaries.html,,binaries page}.
@@ -3399,7 +3439,8 @@ longer a multiple of 2 bytes.
@html
<hr />
@end html
-@heading @anchor{hppa-hp-hpux}hppa*-hp-hpux*
+@anchor{hppa-hp-hpux}
+@heading hppa*-hp-hpux*
Support for HP-UX version 9 and older was discontinued in GCC 3.4.
We require using gas/binutils on all hppa platforms. Version 2.19 or
@@ -3451,8 +3492,8 @@ More specific information to @samp{hppa*-hp-hpux*} targets follows.
@html
<hr />
@end html
-@heading @anchor{hppa-hp-hpux10}hppa*-hp-hpux10
-
+@anchor{hppa-hp-hpux10}
+@heading hppa*-hp-hpux10
For hpux10.20, we @emph{highly} recommend you pick up the latest sed patch
@code{PHCO_19798} from HP@.
@@ -3464,8 +3505,8 @@ with the one implemented under HP-UX 11 using secondary definitions.
@html
<hr />
@end html
-@heading @anchor{hppa-hp-hpux11}hppa*-hp-hpux11
-
+@anchor{hppa-hp-hpux11}
+@heading hppa*-hp-hpux11
GCC 3.0 and up support HP-UX 11. GCC 2.95.x is not supported and cannot
be used to compile GCC 3.0 and up.
@@ -3575,8 +3616,8 @@ supported, so @option{--enable-threads=dce} does not work.
@html
<hr />
@end html
-@heading @anchor{x-x-linux-gnu}*-*-linux-gnu
-
+@anchor{x-x-linux-gnu}
+@heading *-*-linux-gnu
Versions of libstdc++-v3 starting with 3.2.1 require bug fixes present
in glibc 2.2.5 and later. More information is available in the
libstdc++-v3 documentation.
@@ -3584,8 +3625,8 @@ libstdc++-v3 documentation.
@html
<hr />
@end html
-@heading @anchor{ix86-x-linux}i?86-*-linux*
-
+@anchor{ix86-x-linux}
+@heading i?86-*-linux*
As of GCC 3.3, binutils 2.13.1 or later is required for this platform.
See @uref{http://gcc.gnu.org/PR10877,,bug 10877} for more information.
@@ -3596,7 +3637,8 @@ found on @uref{http://www.bitwizard.nl/sig11/,,www.bitwizard.nl}.
@html
<hr />
@end html
-@heading @anchor{ix86-x-solaris29}i?86-*-solaris2.9
+@anchor{ix86-x-solaris29}
+@heading i?86-*-solaris2.9
The Sun assembler in Solaris 9 has several bugs and limitations.
While GCC works around them, several features are missing, so it is
@c FIXME: which ones?
@@ -3616,7 +3658,8 @@ you have the patch installed, you can configure GCC with an appropriate
@html
<hr />
@end html
-@heading @anchor{ix86-x-solaris210}i?86-*-solaris2.10
+@anchor{ix86-x-solaris210}
+@heading i?86-*-solaris2.10
Use this for Solaris 10 or later on x86 and x86-64 systems. Starting
with GCC 4.7, there is also a 64-bit @samp{amd64-*-solaris2.1[0-9]*} or
@samp{x86_64-*-solaris2.1[0-9]*} configuration that corresponds to
@@ -3645,7 +3688,8 @@ guarantee use of Sun @command{ld}.
@html
<hr />
@end html
-@heading @anchor{ia64-x-linux}ia64-*-linux
+@anchor{ia64-x-linux}
+@heading ia64-*-linux
IA-64 processor (also known as IPF, or Itanium Processor Family)
running GNU/Linux.
@@ -3665,7 +3709,8 @@ more major ABI changes are expected.
@html
<hr />
@end html
-@heading @anchor{ia64-x-hpux}ia64-*-hpux*
+@anchor{ia64-x-hpux}
+@heading ia64-*-hpux*
Building GCC on this target requires the GNU Assembler. The bundled HP
assembler will not work. To prevent GCC from using the wrong assembler,
the option @option{--with-gnu-as} may be necessary.
@@ -3680,7 +3725,8 @@ removed and the system libunwind library will always be used.
<hr />
<!-- rs6000-ibm-aix*, powerpc-ibm-aix* -->
@end html
-@heading @anchor{x-ibm-aix}*-ibm-aix*
+@anchor{x-ibm-aix}
+@heading *-ibm-aix*
Support for AIX version 3 and older was discontinued in GCC 3.4.
Support for AIX version 4.2 and older was discontinued in GCC 4.5.
@@ -3831,42 +3877,48 @@ switch and using the configure option @option{--with-cpu-@var{cpu_type}}.
@html
<hr />
@end html
-@heading @anchor{iq2000-x-elf}iq2000-*-elf
+@anchor{iq2000-x-elf}
+@heading iq2000-*-elf
Vitesse IQ2000 processors. These are used in embedded
applications. There are no standard Unix configurations.
@html
<hr />
@end html
-@heading @anchor{lm32-x-elf}lm32-*-elf
+@anchor{lm32-x-elf}
+@heading lm32-*-elf
Lattice Mico32 processor.
This configuration is intended for embedded systems.
@html
<hr />
@end html
-@heading @anchor{lm32-x-uclinux}lm32-*-uclinux
+@anchor{lm32-x-uclinux}
+@heading lm32-*-uclinux
Lattice Mico32 processor.
This configuration is intended for embedded systems running uClinux.
@html
<hr />
@end html
-@heading @anchor{m32c-x-elf}m32c-*-elf
+@anchor{m32c-x-elf}
+@heading m32c-*-elf
Renesas M32C processor.
This configuration is intended for embedded systems.
@html
<hr />
@end html
-@heading @anchor{m32r-x-elf}m32r-*-elf
+@anchor{m32r-x-elf}
+@heading m32r-*-elf
Renesas M32R processor.
This configuration is intended for embedded systems.
@html
<hr />
@end html
-@heading @anchor{m68k-x-x}m68k-*-*
+@anchor{m68k-x-x}
+@heading m68k-*-*
By default,
@samp{m68k-*-elf*}, @samp{m68k-*-rtems}, @samp{m68k-*-uclinux} and
@samp{m68k-*-linux}
@@ -3894,31 +3946,34 @@ GCC requires at least binutils version 2.17 on these targets.
@html
<hr />
@end html
-@heading @anchor{m68k-x-uclinux}m68k-*-uclinux
+@anchor{m68k-x-uclinux}
+@heading m68k-*-uclinux
GCC 4.3 changed the uClinux configuration so that it uses the
@samp{m68k-linux-gnu} ABI rather than the @samp{m68k-elf} ABI.
It also added improved support for C++ and flat shared libraries,
both of which were ABI changes.
-
@html
<hr />
@end html
-@heading @anchor{mep-x-elf}mep-*-elf
+@anchor{mep-x-elf}
+@heading mep-*-elf
Toshiba Media embedded Processor.
This configuration is intended for embedded systems.
@html
<hr />
@end html
-@heading @anchor{microblaze-x-elf}microblaze-*-elf
+@anchor{microblaze-x-elf}
+@heading microblaze-*-elf
Xilinx MicroBlaze processor.
This configuration is intended for embedded systems.
@html
<hr />
@end html
-@heading @anchor{mips-x-x}mips-*-*
+@anchor{mips-x-x}
+@heading mips-*-*
If on a MIPS system you get an error message saying ``does not have gp
sections for all it's [sic] sectons [sic]'', don't worry about it. This
happens whenever you use GAS with the MIPS linker, but there is not
@@ -3970,15 +4025,15 @@ made after Nov. 9, 2006) should be free from both of these problems.
@html
<hr />
@end html
-@heading @anchor{mips-sgi-irix5}mips-sgi-irix5
-
+@anchor{mips-sgi-irix5}
+@heading mips-sgi-irix5
Support for IRIX 5 has been removed in GCC 4.6.
@html
<hr />
@end html
-@heading @anchor{mips-sgi-irix6}mips-sgi-irix6
-
+@anchor{mips-sgi-irix6}
+@heading mips-sgi-irix6
Support for IRIX 6.5 has been removed in GCC 4.8. Support for IRIX 6
releases before 6.5 has been removed in GCC 4.6, as well as support for
the O32 ABI.
@@ -3986,21 +4041,23 @@ the O32 ABI.
@html
<hr />
@end html
-@heading @anchor{moxie-x-elf}moxie-*-elf
+@anchor{moxie-x-elf}
+@heading moxie-*-elf
The moxie processor.
@html
<hr />
@end html
-@heading @anchor{msp430-x-elf}msp430-*-elf
+@anchor{msp430-x-elf}
+@heading msp430-*-elf
TI MSP430 processor.
This configuration is intended for embedded systems.
@html
<hr />
@end html
-@heading @anchor{powerpc-x-x}powerpc-*-*
-
+@anchor{powerpc-x-x}
+@heading powerpc-*-*
You can specify a default version for the @option{-mcpu=@var{cpu_type}}
switch by using the configure option @option{--with-cpu-@var{cpu_type}}.
@@ -4011,7 +4068,8 @@ or newer for a working GCC@.
@html
<hr />
@end html
-@heading @anchor{powerpc-x-darwin}powerpc-*-darwin*
+@anchor{powerpc-x-darwin}
+@heading powerpc-*-darwin*
PowerPC running Darwin (Mac OS X kernel).
Pre-installed versions of Mac OS X may not include any developer tools,
@@ -4027,65 +4085,74 @@ on systems older than 10.3.9 (aka darwin7.9.0).
@html
<hr />
@end html
-@heading @anchor{powerpc-x-elf}powerpc-*-elf
+@anchor{powerpc-x-elf}
+@heading powerpc-*-elf
PowerPC system in big endian mode, running System V.4.
@html
<hr />
@end html
-@heading @anchor{powerpc-x-linux-gnu}powerpc*-*-linux-gnu*
-
+@anchor{powerpc-x-linux-gnu}
+@heading powerpc*-*-linux-gnu*
PowerPC system in big endian mode running Linux.
@html
<hr />
@end html
-@heading @anchor{powerpc-x-netbsd}powerpc-*-netbsd*
+@anchor{powerpc-x-netbsd}
+@heading powerpc-*-netbsd*
PowerPC system in big endian mode running NetBSD@.
@html
<hr />
@end html
-@heading @anchor{powerpc-x-eabisim}powerpc-*-eabisim
+@anchor{powerpc-x-eabisim}
+@heading powerpc-*-eabisim
Embedded PowerPC system in big endian mode for use in running under the
PSIM simulator.
@html
<hr />
@end html
-@heading @anchor{powerpc-x-eabi}powerpc-*-eabi
+@anchor{powerpc-x-eabi}
+@heading powerpc-*-eabi
Embedded PowerPC system in big endian mode.
@html
<hr />
@end html
-@heading @anchor{powerpcle-x-elf}powerpcle-*-elf
+@anchor{powerpcle-x-elf}
+@heading powerpcle-*-elf
PowerPC system in little endian mode, running System V.4.
@html
<hr />
@end html
-@heading @anchor{powerpcle-x-eabisim}powerpcle-*-eabisim
+@anchor{powerpcle-x-eabisim}
+@heading powerpcle-*-eabisim
Embedded PowerPC system in little endian mode for use in running under
the PSIM simulator.
@html
<hr />
@end html
-@heading @anchor{powerpcle-x-eabi}powerpcle-*-eabi
+@anchor{powerpcle-x-eabi}
+@heading powerpcle-*-eabi
Embedded PowerPC system in little endian mode.
@html
<hr />
@end html
-@heading @anchor{rl78-x-elf}rl78-*-elf
+@anchor{rl78-x-elf}
+@heading rl78-*-elf
The Renesas RL78 processor.
This configuration is intended for embedded systems.
@html
<hr />
@end html
-@heading @anchor{rx-x-elf}rx-*-elf
+@anchor{rx-x-elf}
+@heading rx-*-elf
The Renesas RX processor. See
@uref{http://eu.renesas.com/fmwk.jsp?cnt=rx600_series_landing.jsp&fp=/products/mpumcu/rx_family/rx600_series}
for more information about this processor.
@@ -4093,19 +4160,22 @@ for more information about this processor.
@html
<hr />
@end html
-@heading @anchor{s390-x-linux}s390-*-linux*
+@anchor{s390-x-linux}
+@heading s390-*-linux*
S/390 system running GNU/Linux for S/390@.
@html
<hr />
@end html
-@heading @anchor{s390x-x-linux}s390x-*-linux*
+@anchor{s390x-x-linux}
+@heading s390x-*-linux*
zSeries system (64-bit) running GNU/Linux for zSeries@.
@html
<hr />
@end html
-@heading @anchor{s390x-ibm-tpf}s390x-ibm-tpf*
+@anchor{s390x-ibm-tpf}
+@heading s390x-ibm-tpf*
zSeries system (64-bit) running TPF@. This platform is
supported as cross-compilation target only.
@@ -4116,8 +4186,8 @@ supported as cross-compilation target only.
@c with 2.0 until 2.6, 7, 8, etc. Solaris 1 was a marketing name for
@c SunOS 4 releases which we don't use to avoid confusion. Solaris
@c alone is too unspecific and must be avoided.
-@heading @anchor{x-x-solaris2}*-*-solaris2*
-
+@anchor{x-x-solaris2}
+@heading *-*-solaris2*
Support for Solaris 9 has been obsoleted in GCC 4.9, but can still be
enabled by configuring with @option{--enable-obsolete}. Support will be
removed in GCC 4.10. Support for Solaris 8 has removed in GCC 4.8.
@@ -4223,8 +4293,8 @@ additional bug fixes.
@html
<hr />
@end html
-@heading @anchor{sparc-x-x}sparc*-*-*
-
+@anchor{sparc-x-x}
+@heading sparc*-*-*
This section contains general configuration information for all
SPARC-based platforms. In addition to reading this section, please
read all other sections that match your target.
@@ -4238,8 +4308,8 @@ in @uref{prerequisites.html,,the prerequisites}.
@html
<hr />
@end html
-@heading @anchor{sparc-sun-solaris2}sparc-sun-solaris2*
-
+@anchor{sparc-sun-solaris2}
+@heading sparc-sun-solaris2*
When GCC is configured to use GNU binutils 2.14 or later, the binaries
produced are smaller than the ones produced using Sun's native tools;
this difference is quite significant for binaries containing debugging
@@ -4300,8 +4370,8 @@ not that of GMP or MPFR or MPC). For example on a Solaris 9 system:
@html
<hr />
@end html
-@heading @anchor{sparc-sun-solaris210}sparc-sun-solaris2.10
-
+@anchor{sparc-sun-solaris210}
+@heading sparc-sun-solaris2.10
There is a bug in older versions of the Sun assembler which breaks
thread-local storage (TLS). A typical error message is
@@ -4316,7 +4386,8 @@ This bug is fixed in Sun patch 118683-03 or later.
@html
<hr />
@end html
-@heading @anchor{sparc-x-linux}sparc-*-linux*
+@anchor{sparc-x-linux}
+@heading sparc-*-linux*
GCC versions 3.0 and higher require binutils 2.11.2 and glibc 2.2.4
or newer on this platform. All earlier binutils and glibc
@@ -4326,8 +4397,8 @@ releases mishandled unaligned relocations on @code{sparc-*-*} targets.
@html
<hr />
@end html
-@heading @anchor{sparc64-x-solaris2}sparc64-*-solaris2*
-
+@anchor{sparc64-x-solaris2}
+@heading sparc64-*-solaris2*
When configuring the GNU Multiple Precision Library (GMP), the MPFR
library or the MPC library, the canonical target triplet must be specified
as the @command{build} parameter on the configure line. For example
@@ -4351,37 +4422,38 @@ and @option{-xildoff} turns off the incremental linker.
@html
<hr />
@end html
-@heading @anchor{sparcv9-x-solaris2}sparcv9-*-solaris2*
-
+@anchor{sparcv9-x-solaris2}
+@heading sparcv9-*-solaris2*
This is a synonym for @samp{sparc64-*-solaris2*}.
@html
<hr />
@end html
-@heading @anchor{c6x-x-x}c6x-*-*
-
+@anchor{c6x-x-x}
+@heading c6x-*-*
The C6X family of processors. This port requires binutils-2.22 or newer.
@html
<hr />
@end html
-@heading @anchor{tilegx-*-linux}tilegx-*-linux*
-
+@anchor{tilegx-*-linux}
+@heading tilegx-*-linux*
The TILE-Gx processor running GNU/Linux. This port requires
binutils-2.22 or newer.
@html
<hr />
@end html
-@heading @anchor{tilepro-*-linux}tilepro-*-linux*
-
+@anchor{tilepro-*-linux}
+@heading tilepro-*-linux*
The TILEPro processor running GNU/Linux. This port requires
binutils-2.22 or newer.
@html
<hr />
@end html
-@heading @anchor{x-x-vxworks}*-*-vxworks*
+@anchor{x-x-vxworks}
+@heading *-*-vxworks*
Support for VxWorks is in flux. At present GCC supports @emph{only} the
very recent VxWorks 5.5 (aka Tornado 2.2) release, and only on PowerPC@.
We welcome patches for other architectures supported by VxWorks 5.5.
@@ -4416,8 +4488,8 @@ VxWorks will incorporate this module.)
@html
<hr />
@end html
-@heading @anchor{x86-64-x-x}x86_64-*-*, amd64-*-*
-
+@anchor{x86-64-x-x}
+@heading x86_64-*-*, amd64-*-*
GCC supports the x86-64 architecture implemented by the AMD64 processor
(amd64-*-* is an alias for x86_64-*-*) on GNU/Linux, FreeBSD and NetBSD@.
On GNU/Linux the default is a bi-arch compiler which is able to generate
@@ -4426,8 +4498,8 @@ both 64-bit x86-64 and 32-bit x86 code (via the @option{-m32} switch).
@html
<hr />
@end html
-@heading @anchor{x86-64-x-solaris210}x86_64-*-solaris2.1[0-9]*
-
+@anchor{x86-64-x-solaris210}
+@heading x86_64-*-solaris2.1[0-9]*
GCC also supports the x86-64 architecture implemented by the AMD64
processor (@samp{amd64-*-*} is an alias for @samp{x86_64-*-*}) on
Solaris 10 or later. Unlike other systems, without special options a
@@ -4442,8 +4514,8 @@ and @samp{CC=gcc -m64}.
@html
<hr />
@end html
-@heading @anchor{xtensa-x-elf}xtensa*-*-elf
-
+@anchor{xtensa-x-elf}
+@heading xtensa*-*-elf
This target is intended for embedded Xtensa systems using the
@samp{newlib} C library. It uses ELF but does not support shared
objects. Designed-defined instructions specified via the
@@ -4460,8 +4532,8 @@ which you can use to replace the default header file.
@html
<hr />
@end html
-@heading @anchor{xtensa-x-linux}xtensa*-*-linux*
-
+@anchor{xtensa-x-linux}
+@heading xtensa*-*-linux*
This target is for Xtensa systems running GNU/Linux. It supports ELF
shared objects and the GNU C library (glibc). It also generates
position-independent code (PIC) regardless of whether the
@@ -4472,7 +4544,8 @@ respects, this target is the same as the
@html
<hr />
@end html
-@heading @anchor{windows}Microsoft Windows
+@anchor{windows}
+@heading Microsoft Windows
@subheading Intel 16-bit versions
The 16-bit versions of Microsoft Windows, such as Windows 3.1, are not
@@ -4482,7 +4555,6 @@ However, the 32-bit port has limited support for Microsoft
Windows 3.11 in the Win32s environment, as a target only. See below.
@subheading Intel 32-bit versions
-
The 32-bit versions of Windows, including Windows 95, Windows NT, Windows
XP, and Windows Vista, are supported by several different target
platforms. These targets differ in which Windows subsystem they target
@@ -4500,7 +4572,6 @@ the Win32 subsystem that provides a subset of POSIX.
@end itemize
@subheading Intel 64-bit versions
-
GCC contains support for x86-64 using the mingw-w64
runtime library, available from @uref{http://mingw-w64.sourceforge.net/}.
This library should be used with the target triple x86_64-pc-mingw32.
@@ -4508,12 +4579,10 @@ This library should be used with the target triple x86_64-pc-mingw32.
Presently Windows for Itanium is not supported.
@subheading Windows CE
-
Windows CE is supported as a target only on Hitachi
SuperH (sh-wince-pe), and MIPS (mips-wince-pe).
@subheading Other Windows Platforms
-
GCC no longer supports Windows NT on the Alpha or PowerPC.
GCC no longer supports the Windows POSIX subsystem. However, it does
@@ -4529,8 +4598,8 @@ UWIN support has been removed due to a lack of maintenance.
@html
<hr />
@end html
-@heading @anchor{x-x-cygwin}*-*-cygwin
-
+@anchor{x-x-cygwin}
+@heading *-*-cygwin
Ports of GCC are included with the
@uref{http://www.cygwin.com/,,Cygwin environment}.
@@ -4546,8 +4615,8 @@ or version 2.20 or above if building your own.
@html
<hr />
@end html
-@heading @anchor{x-x-interix}*-*-interix
-
+@anchor{x-x-interix}
+@heading *-*-interix
The Interix target is used by OpenNT, Interix, Services For UNIX (SFU),
and Subsystem for UNIX-based Applications (SUA). Applications compiled
with this target run in the Interix subsystem, which is separate from
@@ -4556,8 +4625,8 @@ the Win32 subsystem. This target was last known to work in GCC 3.3.
@html
<hr />
@end html
-@heading @anchor{x-x-mingw32}*-*-mingw32
-
+@anchor{x-x-mingw32}
+@heading *-*-mingw32
GCC will build with and support only MinGW runtime 3.12 and later.
Earlier versions of headers are incompatible with the new default semantics
of @code{extern inline} in @code{-std=c99} and @code{-std=gnu99} modes.
@@ -4565,8 +4634,8 @@ of @code{extern inline} in @code{-std=c99} and @code{-std=gnu99} modes.
@html
<hr />
@end html
-@heading @anchor{older}Older systems
-
+@anchor{older}
+@heading Older systems
GCC contains support files for many older (1980s and early
1990s) Unix variants. For the most part, support for these systems
has not been deliberately removed, but it has not been maintained for
@@ -4611,8 +4680,8 @@ current GCC) is to be found in the GCC texinfo manual.
@html
<hr />
@end html
-@heading @anchor{elf}all ELF targets (SVR4, Solaris 2, etc.)
-
+@anchor{elf}
+@heading all ELF targets (SVR4, Solaris 2, etc.)
C++ support is significantly better on ELF targets if you use the
@uref{./configure.html#with-gnu-ld,,GNU linker}; duplicate copies of
inlines, vtables and template instantiations will be discarded
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 497f237f08a..aa3f0237336 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -168,8 +168,8 @@ in the following sections.
@gccoptlist{-ansi -std=@var{standard} -fgnu89-inline @gol
-aux-info @var{filename} -fallow-parameterless-variadic-functions @gol
-fno-asm -fno-builtin -fno-builtin-@var{function} @gol
--fhosted -ffreestanding -fopenmp -fms-extensions -fplan9-extensions @gol
--trigraphs -traditional -traditional-cpp @gol
+-fhosted -ffreestanding -fopenmp -fopenmp-simd -fms-extensions @gol
+-fplan9-extensions -trigraphs -traditional -traditional-cpp @gol
-fallow-single-precision -fcond-mismatch -flax-vector-conversions @gol
-fsigned-bitfields -fsigned-char @gol
-funsigned-bitfields -funsigned-char}
@@ -190,7 +190,7 @@ in the following sections.
-frepo -fno-rtti -fstats -ftemplate-backtrace-limit=@var{n} @gol
-ftemplate-depth=@var{n} @gol
-fno-threadsafe-statics -fuse-cxa-atexit -fno-weak -nostdinc++ @gol
--fno-default-inline -fvisibility-inlines-hidden @gol
+-fvisibility-inlines-hidden @gol
-fvtable-verify=@var{std|preinit|none} @gol
-fvtv-counts -fvtv-debug @gol
-fvisibility-ms-compat @gol
@@ -240,7 +240,7 @@ Objective-C and Objective-C++ Dialects}.
-Wno-attributes -Wno-builtin-macro-redefined @gol
-Wc++-compat -Wc++11-compat -Wcast-align -Wcast-qual @gol
-Wchar-subscripts -Wclobbered -Wcomment -Wconditionally-supported @gol
--Wconversion -Wcoverage-mismatch -Wdelete-incomplete -Wno-cpp @gol
+-Wconversion -Wcoverage-mismatch -Wdate-time -Wdelete-incomplete -Wno-cpp @gol
-Wno-deprecated -Wno-deprecated-declarations -Wdisabled-optimization @gol
-Wno-div-by-zero -Wdouble-promotion -Wempty-body -Wenum-compare @gol
-Wno-endif-labels -Werror -Werror=* @gol
@@ -256,7 +256,6 @@ Objective-C and Objective-C++ Dialects}.
-Wlogical-op -Wlong-long @gol
-Wmain -Wmaybe-uninitialized -Wmissing-braces -Wmissing-field-initializers @gol
-Wmissing-include-dirs @gol
--Wno-mudflap @gol
-Wno-multichar -Wnonnull -Wno-overflow @gol
-Woverlength-strings -Wpacked -Wpacked-bitfield-compat -Wpadded @gol
-Wparentheses -Wpedantic-ms-format -Wno-pedantic-ms-format @gol
@@ -308,7 +307,7 @@ Objective-C and Objective-C++ Dialects}.
-fdump-tree-ch @gol
-fdump-tree-ssa@r{[}-@var{n}@r{]} -fdump-tree-pre@r{[}-@var{n}@r{]} @gol
-fdump-tree-ccp@r{[}-@var{n}@r{]} -fdump-tree-dce@r{[}-@var{n}@r{]} @gol
--fdump-tree-gimple@r{[}-raw@r{]} -fdump-tree-mudflap@r{[}-@var{n}@r{]} @gol
+-fdump-tree-gimple@r{[}-raw@r{]} @gol
-fdump-tree-dom@r{[}-@var{n}@r{]} @gol
-fdump-tree-dse@r{[}-@var{n}@r{]} @gol
-fdump-tree-phiprop@r{[}-@var{n}@r{]} @gol
@@ -322,7 +321,6 @@ Objective-C and Objective-C++ Dialects}.
-fdump-tree-fre@r{[}-@var{n}@r{]} @gol
-fdump-tree-vtable-verify @gol
-fdump-tree-vrp@r{[}-@var{n}@r{]} @gol
--ftree-vectorizer-verbose=@var{n} @gol
-fdump-tree-storeccp@r{[}-@var{n}@r{]} @gol
-fdump-final-insns=@var{file} @gol
-fcompare-debug@r{[}=@var{opts}@r{]} -fcompare-debug-second @gol
@@ -379,24 +377,24 @@ Objective-C and Objective-C++ Dialects}.
-fira-region=@var{region} -fira-hoist-pressure @gol
-fira-loop-pressure -fno-ira-share-save-slots @gol
-fno-ira-share-spill-slots -fira-verbose=@var{n} @gol
--fivopts -fkeep-inline-functions -fkeep-static-consts @gol
+-fisolate-erroneous-paths
+-fivopts -fkeep-inline-functions -fkeep-static-consts -flive-range-shrinkage @gol
-floop-block -floop-interchange -floop-strip-mine -floop-nest-optimize @gol
-floop-parallelize-all -flto -flto-compression-level @gol
-flto-partition=@var{alg} -flto-report -flto-report-wpa -fmerge-all-constants @gol
-fmerge-constants -fmodulo-sched -fmodulo-sched-allow-regmoves @gol
--fmove-loop-invariants fmudflap -fmudflapir -fmudflapth -fno-branch-count-reg @gol
--fno-default-inline @gol
+-fmove-loop-invariants -fno-branch-count-reg @gol
-fno-defer-pop -fno-function-cse -fno-guess-branch-probability @gol
-fno-inline -fno-math-errno -fno-peephole -fno-peephole2 @gol
-fno-sched-interblock -fno-sched-spec -fno-signed-zeros @gol
-fno-toplevel-reorder -fno-trapping-math -fno-zero-initialized-in-bss @gol
--fomit-frame-pointer -foptimize-register-move -foptimize-sibling-calls @gol
+-fomit-frame-pointer -foptimize-sibling-calls @gol
-fpartial-inlining -fpeel-loops -fpredictive-commoning @gol
-fprefetch-loop-arrays -fprofile-report @gol
-fprofile-correction -fprofile-dir=@var{path} -fprofile-generate @gol
-fprofile-generate=@var{path} @gol
-fprofile-use -fprofile-use=@var{path} -fprofile-values @gol
--freciprocal-math -free -fregmove -frename-registers -freorder-blocks @gol
+-freciprocal-math -free -frename-registers -freorder-blocks @gol
-freorder-blocks-and-partition -freorder-functions @gol
-frerun-cse-after-loop -freschedule-modulo-scheduled-loops @gol
-frounding-math -fsched2-use-superblocks -fsched-pressure @gol
@@ -423,7 +421,7 @@ Objective-C and Objective-C++ Dialects}.
-ftree-parallelize-loops=@var{n} -ftree-pre -ftree-partial-pre -ftree-pta @gol
-ftree-reassoc -ftree-sink -ftree-slsr -ftree-sra @gol
-ftree-switch-conversion -ftree-tail-merge -ftree-ter @gol
--ftree-vect-loop-version -ftree-vectorize -ftree-vrp @gol
+-ftree-vectorize -ftree-vrp @gol
-funit-at-a-time -funroll-all-loops -funroll-loops @gol
-funsafe-loop-optimizations -funsafe-math-optimizations -funswitch-loops @gol
-fvariable-expansion-in-unroller -fvect-cost-model -fvpt -fweb @gol
@@ -490,6 +488,23 @@ Objective-C and Objective-C++ Dialects}.
-mfp-mode=@var{mode} -mvect-double -max-vect-align=@var{num} @gol
-msplit-vecmove-early -m1reg-@var{reg}}
+@emph{ARC Options}
+@gccoptlist{-mbarrel-shifter @gol
+-mcpu=@var{cpu} -mA6 -mARC600 -mA7 -mARC700 @gol
+-mdpfp -mdpfp-compact -mdpfp-fast -mno-dpfp-lrsr @gol
+-mea -mno-mpy -mmul32x16 -mmul64 @gol
+-mnorm -mspfp -mspfp-compact -mspfp-fast -msimd -msoft-float -mswap @gol
+-mcrc -mdsp-packa -mdvbf -mlock -mmac-d16 -mmac-24 -mrtsc -mswape @gol
+-mtelephony -mxy -misize -mannotate-align -marclinux -marclinux_prof @gol
+-mepilogue-cfi -mlong-calls -mmedium-calls -msdata @gol
+-mucb-mcount -mvolatile-cache @gol
+-malign-call -mauto-modify-reg -mbbit-peephole -mno-brcc @gol
+-mcase-vector-pcrel -mcompact-casesi -mno-cond-exec -mearly-cbranchsi @gol
+-mexpand-adddi -mindexed-loads -mlra -mlra-priority-none @gol
+-mlra-priority-compact mlra-priority-noncompact -mno-millicode @gol
+-mmixed-code -mq-class -mRcq -mRcw -msize-level=@var{level} @gol
+-mtune=@var{cpu} -mmultcost=@var{num} -munalign-prob-threshold=@var{probability}}
+
@emph{ARM Options}
@gccoptlist{-mapcs-frame -mno-apcs-frame @gol
-mabi=@var{name} @gol
@@ -652,7 +667,7 @@ Objective-C and Objective-C++ Dialects}.
-mavx2 -mavx512f -mavx512pf -mavx512er -mavx512cd @gol
-maes -mpclmul -mfsgsbase -mrdrnd -mf16c -mfma @gol
-msse4a -m3dnow -mpopcnt -mabm -mbmi -mtbm -mfma4 -mxop -mlzcnt @gol
--mbmi2 -mfxsr -mxsave -mxsaveopt -mrtm -mlwp -mthreads @gol
+-mbmi2 -mfxsr -mxsave -mxsaveopt -mrtm -mlwp -mmpx -mthreads @gol
-mno-align-stringops -minline-all-stringops @gol
-minline-stringops-dynamically -mstringop-strategy=@var{alg} @gol
-mmemcpy-strategy=@var{strategy} -mmemset-strategy=@var{strategy}
@@ -808,6 +823,20 @@ Objective-C and Objective-C++ Dialects}.
@emph{MSP430 Options}
@gccoptlist{-msim -masm-hex -mmcu= -mlarge -msmall -mrelax}
+@emph{NDS32 Options}
+@gccoptlist{-mbig-endian -mlittle-endian @gol
+-mreduced-regs -mfull-regs @gol
+-mcmov -mno-cmov @gol
+-mperf-ext -mno-perf-ext @gol
+-mv3push -mno-v3push @gol
+-m16bit -mno-16bit @gol
+-mgp-direct -mno-gp-direct @gol
+-misr-vector-size=@var{num} @gol
+-mcache-block-size=@var{num} @gol
+-march=@var{arch} @gol
+-mforce-fp-as-gp -mforbid-fp-as-gp @gol
+-mex9 -mctor-dtor -mrelax}
+
@emph{PDP-11 Options}
@gccoptlist{-mfpu -msoft-float -mac0 -mno-ac0 -m40 -m45 -m10 @gol
-mbcopy -mbcopy-builtin -mint32 -mno-int16 @gol
@@ -1809,9 +1838,18 @@ freestanding and hosted environments.
Enable handling of OpenMP directives @code{#pragma omp} in C/C++ and
@code{!$omp} in Fortran. When @option{-fopenmp} is specified, the
compiler generates parallel code according to the OpenMP Application
-Program Interface v3.0 @w{@uref{http://www.openmp.org/}}. This option
+Program Interface v4.0 @w{@uref{http://www.openmp.org/}}. This option
implies @option{-pthread}, and thus is only supported on targets that
-have support for @option{-pthread}.
+have support for @option{-pthread}. @option{-fopenmp} implies
+@option{-fopenmp-simd}.
+
+@item -fopenmp-simd
+@opindex fopenmp-simd
+@cindex OpenMP SIMD
+@cindex SIMD
+Enable handling of OpenMP's SIMD directives with @code{#pragma omp}
+in C/C++ and @code{!$omp} in Fortran. Other OpenMP directives
+are ignored.
@item -fcilkplus
@opindex fcilkplus
@@ -2390,13 +2428,6 @@ In addition, these optimization, warning, and code generation options
have meanings only for C++ programs:
@table @gcctabopt
-@item -fno-default-inline
-@opindex fno-default-inline
-Do not assume @samp{inline} for functions defined inside a class scope.
-@xref{Optimize Options,,Options That Control Optimization}. Note that these
-functions have linkage like inline functions; they just aren't
-inlined by default.
-
@item -Wabi @r{(C, Objective-C, C++ and Objective-C++ only)}
@opindex Wabi
@opindex Wno-abi
@@ -4500,6 +4531,13 @@ types. @option{-Wconversion-null} is enabled by default.
Warn when a literal '0' is used as null pointer constant. This can
be useful to facilitate the conversion to @code{nullptr} in C++11.
+@item -Wdate-time
+@opindex Wdate-time
+@opindex Wno-date-time
+Warn when macros @code{__TIME__}, @code{__DATE__} or @code{__TIMESTAMP__}
+are encountered as they might prevent bit-wise-identical reproducible
+compilations.
+
@item -Wdelete-incomplete @r{(C++ and Objective-C++ only)}
@opindex Wdelete-incomplete
@opindex Wno-delete-incomplete
@@ -4986,11 +5024,6 @@ This option is only supported for C and Objective-C@. It is implied by
This option is only active when @option{-fstack-protector} is active. It
warns about functions that are not protected against stack smashing.
-@item -Wno-mudflap
-@opindex Wno-mudflap
-Suppress warnings about constructs that cannot be instrumented by
-@option{-fmudflap}.
-
@item -Woverlength-strings
@opindex Woverlength-strings
@opindex Wno-overlength-strings
@@ -5074,6 +5107,12 @@ possible.
@opindex gpubnames
Generate dwarf .debug_pubnames and .debug_pubtypes sections.
+@item -ggnu-pubnames
+@opindex ggnu-pubnames
+Generate .debug_pubnames and .debug_pubtypes sections in a format
+suitable for conversion into a GDB@ index. This option is only useful
+with a linker that can produce GDB@ index version 7.
+
@item -gstabs
@opindex gstabs
Produce debugging information in stabs format (if that is supported),
@@ -5818,10 +5857,6 @@ Dump after post-reload optimizations.
@opindex fdump-rtl-pro_and_epilogue
Dump after generating the function prologues and epilogues.
-@item -fdump-rtl-regmove
-@opindex fdump-rtl-regmove
-Dump after the register move pass.
-
@item -fdump-rtl-sched1
@itemx -fdump-rtl-sched2
@opindex fdump-rtl-sched1
@@ -6190,11 +6225,6 @@ by appending @file{.store_copyprop} to the source file name.
Dump each function after dead code elimination. The file name is made by
appending @file{.dce} to the source file name.
-@item mudflap
-@opindex fdump-tree-mudflap
-Dump each function after adding mudflap instrumentation. The file name is
-made by appending @file{.mudflap} to the source file name.
-
@item sra
@opindex fdump-tree-sra
Dump each function after performing scalar replacement of aggregates. The
@@ -6366,24 +6396,6 @@ the first option takes effect and the subsequent options are
ignored. Thus only the @file{vec.miss} is produced which cotaints
dumps from the vectorizer about missed opportunities.
-@item -ftree-vectorizer-verbose=@var{n}
-@opindex ftree-vectorizer-verbose
-This option is deprecated and is implemented in terms of
-@option{-fopt-info}. Please use @option{-fopt-info-@var{kind}} form
-instead, where @var{kind} is one of the valid opt-info options. It
-prints additional optimization information. For @var{n}=0 no
-diagnostic information is reported. If @var{n}=1 the vectorizer
-reports each loop that got vectorized, and the total number of loops
-that got vectorized. If @var{n}=2 the vectorizer reports locations
-which could not be vectorized and the reasons for those. For any
-higher verbosity levels all the analysis and transformation
-information from the vectorizer is reported.
-
-Note that the information output by @option{-ftree-vectorizer-verbose}
-option is sent to @file{stderr}. If the equivalent form
-@option{-fopt-info-@var{options}=@var{filename}} is used then the
-output is sent into @var{filename} instead.
-
@item -frandom-seed=@var{string}
@opindex frandom-seed
This option provides a seed that GCC uses in place of
@@ -6736,10 +6748,10 @@ also turns on the following optimization flags:
-finline-small-functions @gol
-findirect-inlining @gol
-fipa-sra @gol
+-fisolate-erroneous-paths @gol
-foptimize-sibling-calls @gol
-fpartial-inlining @gol
-fpeephole2 @gol
--fregmove @gol
-freorder-blocks -freorder-functions @gol
-frerun-cse-after-loop @gol
-fsched-interblock -fsched-spec @gol
@@ -6775,7 +6787,7 @@ optimizations designed to reduce code size.
@option{-Os} disables the following optimization flags:
@gccoptlist{-falign-functions -falign-jumps -falign-loops @gol
-falign-labels -freorder-blocks -freorder-blocks-and-partition @gol
--fprefetch-loop-arrays -ftree-vect-loop-version}
+-fprefetch-loop-arrays}
@item -Ofast
@opindex Ofast
@@ -6810,14 +6822,6 @@ can use the following flags in the rare cases when ``fine-tuning'' of
optimizations to be performed is desired.
@table @gcctabopt
-@item -fno-default-inline
-@opindex fno-default-inline
-Do not make member functions inline by default merely because they are
-defined inside the class scope (C++ only). Otherwise, when you specify
-@w{@option{-O}}, member functions defined inside class scope are compiled
-inline by default; i.e., you don't need to add @samp{inline} in front of
-the member function name.
-
@item -fno-defer-pop
@opindex fno-defer-pop
Always pop the arguments to each function call as soon as that function
@@ -7069,32 +7073,6 @@ assumptions based on that.
The default is @option{-fzero-initialized-in-bss}.
-@item -fmudflap -fmudflapth -fmudflapir
-@opindex fmudflap
-@opindex fmudflapth
-@opindex fmudflapir
-@cindex bounds checking
-@cindex mudflap
-For front-ends that support it (C and C++), instrument all risky
-pointer/array dereferencing operations, some standard library
-string/heap functions, and some other associated constructs with
-range/validity tests. Modules so instrumented should be immune to
-buffer overflows, invalid heap use, and some other classes of C/C++
-programming errors. The instrumentation relies on a separate runtime
-library (@file{libmudflap}), which is linked into a program if
-@option{-fmudflap} is given at link time. Run-time behavior of the
-instrumented program is controlled by the @env{MUDFLAP_OPTIONS}
-environment variable. See @code{env MUDFLAP_OPTIONS=-help a.out}
-for its options.
-
-Use @option{-fmudflapth} instead of @option{-fmudflap} to compile and to
-link if your program is multi-threaded. Use @option{-fmudflapir}, in
-addition to @option{-fmudflap} or @option{-fmudflapth}, if
-instrumentation should ignore pointer reads. This produces less
-instrumentation (and therefore faster execution) and still provides
-some protection against outright memory corrupting writes, but allows
-erroneously read data to propagate within a program.
-
@item -fthread-jumps
@opindex fthread-jumps
Perform optimizations that check to see if a jump branches to a
@@ -7297,19 +7275,11 @@ registers after writing to their lower 32-bit half.
Enabled for x86 at levels @option{-O2}, @option{-O3}.
-@item -foptimize-register-move
-@itemx -fregmove
-@opindex foptimize-register-move
-@opindex fregmove
-Attempt to reassign register numbers in move instructions and as
-operands of other simple instructions in order to maximize the amount of
-register tying. This is especially helpful on machines with two-operand
-instructions.
-
-Note @option{-fregmove} and @option{-foptimize-register-move} are the same
-optimization.
-
-Enabled at levels @option{-O2}, @option{-O3}, @option{-Os}.
+@item -flive-range-shrinkage
+@opindex flive-range-shrinkage
+Attempt to decrease register pressure through register live range
+shrinkage. This is helpful for fast processors with small or moderate
+size register sets.
@item -fira-algorithm=@var{algorithm}
Use the specified coloring algorithm for the integrated register
@@ -7672,6 +7642,11 @@ it may significantly increase code size
(see @option{--param ipcp-unit-growth=@var{value}}).
This flag is enabled by default at @option{-O3}.
+@item -fisolate-erroneous-paths
+Detect paths which trigger erroneous or undefined behaviour. Isolate those
+paths from the main control flow and turn the statement with erroneous or
+undefined behaviour into a trap.
+
@item -ftree-sink
@opindex ftree-sink
Perform forward store motion on trees. This flag is
@@ -8030,19 +8005,20 @@ Perform loop vectorization on trees. This flag is enabled by default at
Perform basic block vectorization on trees. This flag is enabled by default at
@option{-O3} and when @option{-ftree-vectorize} is enabled.
-@item -ftree-vect-loop-version
-@opindex ftree-vect-loop-version
-Perform loop versioning when doing loop vectorization on trees. When a loop
-appears to be vectorizable except that data alignment or data dependence cannot
-be determined at compile time, then vectorized and non-vectorized versions of
-the loop are generated along with run-time checks for alignment or dependence
-to control which version is executed. This option is enabled by default
-except at level @option{-Os} where it is disabled.
-
-@item -fvect-cost-model
+@item -fvect-cost-model=@var{model}
@opindex fvect-cost-model
-Enable cost model for vectorization. This option is enabled by default at
-@option{-O3}.
+Alter the cost model used for vectorization. The @var{model} argument
+should be one of @code{unlimited}, @code{dynamic} or @code{cheap}.
+With the @code{unlimited} model the vectorized code-path is assumed
+to be profitable while with the @code{dynamic} model a runtime check
+will guard the vectorized code-path to enable it only for iteration
+counts that will likely execute faster than when executing the original
+scalar loop. The @code{cheap} model will disable vectorization of
+loops where doing so would be cost prohibitive for example due to
+required runtime checks for data dependence or alignment but otherwise
+is equal to the @code{dynamic} model.
+The default cost model depends on other optimization flags and is
+either @code{dynamic} or @code{cheap}.
@item -ftree-vrp
@opindex ftree-vrp
@@ -8351,7 +8327,7 @@ statements. Output them in the same order that they appear in the
input file. When this option is used, unreferenced static variables
are not removed. This option is intended to support existing code
that relies on a particular ordering. For new code, it is better to
-use attributes.
+use attributes when possible.
Enabled at level @option{-O0}. When disabled explicitly, it also implies
@option{-fno-section-anchors}, which is otherwise enabled at @option{-O0} on some
@@ -9448,13 +9424,15 @@ constraints. The default value is 0.
@item vect-max-version-for-alignment-checks
The maximum number of run-time checks that can be performed when
-doing loop versioning for alignment in the vectorizer. See option
-@option{-ftree-vect-loop-version} for more information.
+doing loop versioning for alignment in the vectorizer.
@item vect-max-version-for-alias-checks
The maximum number of run-time checks that can be performed when
-doing loop versioning for alias in the vectorizer. See option
-@option{-ftree-vect-loop-version} for more information.
+doing loop versioning for alias in the vectorizer.
+
+@item vect-max-peeling-for-alignment
+The maximum number of loop peels to enhance access alignment
+for vectorizer. Value -1 means 'no limit'.
@item max-iterations-to-track
The maximum number of iterations of a loop the brute-force algorithm
@@ -9476,6 +9454,11 @@ The known number of iterations is predicted correctly, while
the unknown number of iterations average to roughly 10. This means that the
loop without bounds appears artificially cold relative to the other one.
+@item builtin-expect-probability
+Control the probability of the expression having the specified value. This
+parameter takes a percentage (i.e. 0 ... 100) as input.
+The default probability of 90 is obtained empirically.
+
@item align-threshold
Select fraction of the maximal frequency of executions of a basic block in
@@ -9666,6 +9649,10 @@ value of a shared integer constant. The default value is 256.
The minimum size of buffers (i.e.@: arrays) that receive stack smashing
protection when @option{-fstack-protection} is used.
+@item min-size-for-stack-sharing
+The minimum size of variables taking part in stack slot sharing when not
+optimizing. The default value is 32.
+
@item max-jump-thread-duplication-stmts
Maximum number of statements allowed in a block that needs to be
duplicated when threading jumps.
@@ -10343,7 +10330,7 @@ separator character at the end of the path.
@option{-B} prefixes that effectively specify directory names also apply
to libraries in the linker, because the compiler translates these
options into @option{-L} options for the linker. They also apply to
-includes files in the preprocessor, because the compiler translates these
+include files in the preprocessor, because the compiler translates these
options into @option{-isystem} options for the preprocessor. In this case,
the compiler appends @samp{include} to the prefix.
@@ -10905,6 +10892,22 @@ appears somewhere in @code{X}, then @code{X} is substituted once
for each matching switch, with the @code{%*} replaced by the part of
that switch matching the @code{*}.
+If @code{%*} appears as the last part of a spec sequence then a space
+will be added after the end of the last substitution. If there is more
+text in the sequence however then a space will not be generated. This
+allows the @code{%*} substitution to be used as part of a larger
+string. For example, a spec string like this:
+
+@smallexample
+%@{mcu=*:--script=%*/memory.ld@}
+@end smallexample
+
+when matching an option like @code{-mcu=newchip} will produce:
+
+@smallexample
+--script=newchip/memory.ld
+@end smallexample
+
@item %@{.@code{S}:@code{X}@}
Substitutes @code{X}, if processing a file with suffix @code{S}.
@@ -11023,6 +11026,7 @@ platform.
@menu
* AArch64 Options::
* Adapteva Epiphany Options::
+* ARC Options::
* ARM Options::
* AVR Options::
* Blackfin Options::
@@ -11051,6 +11055,7 @@ platform.
* MN10300 Options::
* Moxie Options::
* MSP430 Options::
+* NDS32 Options::
* PDP-11 Options::
* picoChip Options::
* PowerPC Options::
@@ -11364,6 +11369,511 @@ purpose. The default is @option{-m1reg-none}.
@end table
+@node ARC Options
+@subsection ARC Options
+@cindex ARC options
+
+The following options control the architecture variant for which code
+is being compiled:
+
+@c architecture variants
+@table @gcctabopt
+
+@item -mbarrel-shifter
+@opindex mbarrel-shifter
+Generate instructions supported by barrel shifter. This is the default
+unless @samp{-mcpu=ARC601} is in effect.
+
+@item -mcpu=@var{cpu}
+@opindex mcpu
+Set architecture type, register usage, and instruction scheduling
+parameters for @var{cpu}. There are also shortcut alias options
+available for backward compatibility and convenience. Supported
+values for @var{cpu} are
+
+@table @samp
+@opindex mA6
+@opindex mARC600
+@item ARC600
+Compile for ARC600. Aliases: @option{-mA6}, @option{-mARC600}.
+
+@item ARC601
+@opindex mARC601
+Compile for ARC601. Alias: @option{-mARC601}.
+
+@item ARC700
+@opindex mA7
+@opindex mARC700
+Compile for ARC700. Aliases: @option{-mA7}, @option{-mARC700}.
+This is the default when configured with @samp{--with-cpu=arc700}@.
+@end table
+
+@item -mdpfp
+@opindex mdpfp
+@itemx -mdpfp-compact
+@opindex mdpfp-compact
+FPX: Generate Double Precision FPX instructions, tuned for the compact
+implementation.
+
+@item -mdpfp-fast
+@opindex mdpfp-fast
+FPX: Generate Double Precision FPX instructions, tuned for the fast
+implementation.
+
+@item -mno-dpfp-lrsr
+@opindex mno-dpfp-lrsr
+Disable LR and SR instructions from using FPX extension aux registers.
+
+@item -mea
+@opindex mea
+Generate Extended arithmetic instructions. Currently only
+@code{divaw}, @code{adds}, @code{subs}, and @code{sat16} are
+supported. This is always enabled for @samp{-mcpu=ARC700}.
+
+@item -mno-mpy
+@opindex mno-mpy
+Do not generate mpy instructions for ARC700.
+
+@item -mmul32x16
+@opindex mmul32x16
+Generate 32x16 bit multiply and mac instructions.
+
+@item -mmul64
+@opindex mmul64
+Generate mul64 and mulu64 instructions. Only valid for @samp{-mcpu=ARC600}.
+
+@item -mnorm
+@opindex mnorm
+Generate norm instruction. This is the default if @samp{-mcpu=ARC700}
+is in effect.
+
+@item -mspfp
+@opindex mspfp
+@itemx -mspfp-compact
+@opindex mspfp-compact
+FPX: Generate Single Precision FPX instructions, tuned for the compact
+implementation.
+
+@item -mspfp-fast
+@opindex mspfp-fast
+FPX: Generate Single Precision FPX instructions, tuned for the fast
+implementation.
+
+@item -msimd
+@opindex msimd
+Enable generation of ARC SIMD instructions via target-specific
+builtins. Only valid for @samp{-mcpu=ARC700}.
+
+@item -msoft-float
+@opindex msoft-float
+This option ignored; it is provided for compatibility purposes only.
+Software floating point code is emitted by default, and this default
+can overridden by FPX options; @samp{mspfp}, @samp{mspfp-compact}, or
+@samp{mspfp-fast} for single precision, and @samp{mdpfp},
+@samp{mdpfp-compact}, or @samp{mdpfp-fast} for double precision.
+
+@item -mswap
+@opindex mswap
+Generate swap instructions.
+
+@end table
+
+The following options are passed through to the assembler, and also
+define preprocessor macro symbols.
+
+@c Flags used by the assembler, but for which we define preprocessor
+@c macro symbols as well.
+@table @gcctabopt
+@item -mdsp-packa
+@opindex mdsp-packa
+Passed down to the assembler to enable the DSP Pack A extensions.
+Also sets the preprocessor symbol @code{__Xdsp_packa}.
+
+@item -mdvbf
+@opindex mdvbf
+Passed down to the assembler to enable the dual viterbi butterfly
+extension. Also sets the preprocessor symbol @code{__Xdvbf}.
+
+@c ARC700 4.10 extension instruction
+@item -mlock
+@opindex mlock
+Passed down to the assembler to enable the Locked Load/Store
+Conditional extension. Also sets the preprocessor symbol
+@code{__Xlock}.
+
+@item -mmac-d16
+@opindex mmac-d16
+Passed down to the assembler. Also sets the preprocessor symbol
+@code{__Xxmac_d16}.
+
+@item -mmac-24
+@opindex mmac-24
+Passed down to the assembler. Also sets the preprocessor symbol
+@code{__Xxmac_24}.
+
+@c ARC700 4.10 extension instruction
+@item -mrtsc
+@opindex mrtsc
+Passed down to the assembler to enable the 64-bit Time-Stamp Counter
+extension instruction. Also sets the preprocessor symbol
+@code{__Xrtsc}.
+
+@c ARC700 4.10 extension instruction
+@item -mswape
+@opindex mswape
+Passed down to the assembler to enable the swap byte ordering
+extension instruction. Also sets the preprocessor symbol
+@code{__Xswape}.
+
+@item -mtelephony
+@opindex mtelephony
+Passed down to the assembler to enable dual and single operand
+instructions for telephony. Also sets the preprocessor symbol
+@code{__Xtelephony}.
+
+@item -mxy
+@opindex mxy
+Passed down to the assembler to enable the XY Memory extension. Also
+sets the preprocessor symbol @code{__Xxy}.
+
+@end table
+
+The following options control how the assembly code is annotated:
+
+@c Assembly annotation options
+@table @gcctabopt
+@item -misize
+@opindex misize
+Annotate assembler instructions with estimated addresses.
+
+@item -mannotate-align
+@opindex mannotate-align
+Explain what alignment considerations lead to the decision to make an
+instruction short or long.
+
+@end table
+
+The following options are passed through to the linker:
+
+@c options passed through to the linker
+@table @gcctabopt
+@item -marclinux
+@opindex marclinux
+Passed through to the linker, to specify use of the @code{arclinux} emulation.
+This option is enabled by default in tool chains built for
+@w{@code{arc-linux-uclibc}} and @w{@code{arceb-linux-uclibc}} targets
+when profiling is not requested.
+
+@item -marclinux_prof
+@opindex marclinux_prof
+Passed through to the linker, to specify use of the
+@code{arclinux_prof} emulation. This option is enabled by default in
+tool chains built for @w{@code{arc-linux-uclibc}} and
+@w{@code{arceb-linux-uclibc}} targets when profiling is requested.
+
+@end table
+
+The following options control the semantics of generated code:
+
+@c semantically relevant code generation options
+@table @gcctabopt
+@item -mepilogue-cfi
+@opindex mepilogue-cfi
+Enable generation of call frame information for epilogues.
+
+@item -mno-epilogue-cfi
+@opindex mno-epilogue-cfi
+Disable generation of call frame information for epilogues.
+
+@item -mlong-calls
+@opindex mlong-calls
+Generate call insns as register indirect calls, thus providing access
+to the full 32-bit address range.
+
+@item -mmedium-calls
+@opindex mmedium-calls
+Don't use less than 25 bit addressing range for calls, which is the
+offset available for an unconditional branch-and-link
+instruction. Conditional execution of function calls is suppressed, to
+allow use of the 25-bit range, rather than the 21-bit range with
+conditional branch-and-link. This is the default for tool chains built
+for @w{@code{arc-linux-uclibc}} and @w{@code{arceb-linux-uclibc}} targets.
+
+@item -mno-sdata
+@opindex mno-sdata
+Do not generate sdata references. This is the default for tool chains
+built for @w{@code{arc-linux-uclibc}} and @w{@code{arceb-linux-uclibc}}
+targets.
+
+@item -mucb-mcount
+@opindex mucb-mcount
+Instrument with mcount calls as used in UCB code. I.e. do the
+counting in the callee, not the caller. By default ARC instrumentation
+counts in the caller.
+
+@item -mvolatile-cache
+@opindex mvolatile-cache
+Use ordinarily cached memory accesses for volatile references. This is the
+default.
+
+@item -mno-volatile-cache
+@opindex mno-volatile-cache
+Enable cache bypass for volatile references.
+
+@end table
+
+The following options fine tune code generation:
+@c code generation tuning options
+@table @gcctabopt
+@item -malign-call
+@opindex malign-call
+Do alignment optimizations for call instructions.
+
+@item -mauto-modify-reg
+@opindex mauto-modify-reg
+Enable the use of pre/post modify with register displacement.
+
+@item -mbbit-peephole
+@opindex mbbit-peephole
+Enable bbit peephole2.
+
+@item -mno-brcc
+@opindex mno-brcc
+This option disables a target-specific pass in @file{arc_reorg} to
+generate @code{BRcc} instructions. It has no effect on @code{BRcc}
+generation driven by the combiner pass.
+
+@item -mcase-vector-pcrel
+@opindex mcase-vector-pcrel
+Use pc-relative switch case tables - this enables case table shortening.
+This is the default for @option{-Os}.
+
+@item -mcompact-casesi
+@opindex mcompact-casesi
+Enable compact casesi pattern.
+This is the default for @option{-Os}.
+
+@item -mno-cond-exec
+@opindex mno-cond-exec
+Disable ARCompact specific pass to generate conditional execution instructions.
+Due to delay slot scheduling and interactions between operand numbers,
+literal sizes, instruction lengths, and the support for conditional execution,
+the target-independent pass to generate conditional execution is often lacking,
+so the ARC port has kept a special pass around that tries to find more
+conditional execution generating opportunities after register allocation,
+branch shortening, and delay slot scheduling have been done. This pass
+generally, but not always, improves performance and code size, at the cost of
+extra compilation time, which is why there is an option to switch it off.
+If you have a problem with call instructions exceeding their allowable
+offset range because they are conditionalized, you should consider using
+@option{-mmedium-calls} instead.
+
+@item -mearly-cbranchsi
+@opindex mearly-cbranchsi
+Enable pre-reload use of the cbranchsi pattern.
+
+@item -mexpand-adddi
+@opindex mexpand-adddi
+Expand @code{adddi3} and @code{subdi3} at rtl generation time into
+@code{add.f}, @code{adc} etc.
+
+@item -mindexed-loads
+@opindex mindexed-loads
+Enable the use of indexed loads. This can be problematic because some
+optimizers will then assume the that indexed stores exist, which is not
+the case.
+
+@item -mlra
+@opindex mlra
+Enable Local Register Allocation. This is still experimental for ARC,
+so by default the compiler uses standard reload
+(i.e. @samp{-mno-lra}).
+
+@item -mlra-priority-none
+@opindex mlra-priority-none
+Don't indicate any priority for target registers.
+
+@item -mlra-priority-compact
+@opindex mlra-priority-compact
+Indicate target register priority for r0..r3 / r12..r15.
+
+@item -mlra-priority-noncompact
+@opindex mlra-priority-noncompact
+Reduce target regsiter priority for r0..r3 / r12..r15.
+
+@item -mno-millicode
+@opindex mno-millicode
+When optimizing for size (using @option{-Os}), prologues and epilogues
+that have to save or restore a large number of registers are often
+shortened by using call to a special function in libgcc; this is
+referred to as a @emph{millicode} call. As these calls can pose
+performance issues, and/or cause linking issues when linking in a
+nonstandard way, this option is provided to turn off millicode call
+generation.
+
+@item -mmixed-code
+@opindex mmixed-code
+Tweak register allocation to help 16-bit instruction generation.
+This generally has the effect of decreasing the average instruction size
+while increasing the instruction count.
+
+@item -mq-class
+@opindex mq-class
+Enable 'q' instruction alternatives.
+This is the default for @option{-Os}.
+
+@item -mRcq
+@opindex mRcq
+Enable Rcq constraint handling - most short code generation depends on this.
+This is the default.
+
+@item -mRcw
+@opindex mRcw
+Enable Rcw constraint handling - ccfsm condexec mostly depends on this.
+This is the default.
+
+@item -msize-level=@var{level}
+@ opindex msize-level
+Fine-tune size optimization with regards to instruction lengths and alignment.
+The recognized values for @var{level} are:
+@table @samp
+@item 0
+No size optimization. This level is deprecated and treated like @samp{1}.
+
+@item 1
+Short instructions are used opportunistically.
+
+@item 2
+In addition, alignment of loops and of code after barriers are dropped.
+
+@item 3
+In addition, optional data alignment is dropped, and the option @option{Os} is enabled.
+
+@end table
+
+This defaults to @samp{3} when @option{-Os} is in effect. Otherwise,
+the behavior when this is not set is equivalent to level @samp{1}.
+
+@item -mtune=@var{cpu}
+@opindex mtune
+Set instruction scheduling parameters for @var{cpu}, overriding any implied
+by @option{-mcpu=}.
+
+Supported values for @var{cpu} are
+
+@table @samp
+@item ARC600
+Tune for ARC600 cpu.
+
+@item ARC601
+Tune for ARC601 cpu.
+
+@item ARC700
+Tune for ARC700 cpu with standard multiplier block.
+
+@item ARC700-xmac
+Tune for ARC700 cpu with XMAC block.
+
+@item ARC725D
+Tune for ARC725D cpu.
+
+@item ARC750D
+Tune for ARC750D cpu.
+
+@end table
+
+@item -mmultcost=@var{num}
+@opindex mmultcost
+Cost to assume for a multiply instruction, with @samp{4} being equal to a
+normal instruction.
+
+@item -munalign-prob-threshold=@var{probability}
+@opindex munalign-prob-threshold
+Set probability threshold for unaligning branches.
+When tuning for @samp{ARC700} and optimizing for speed, branches without
+filled delay slot are preferably emitted unaligned and long, unless
+profiling indicates that the probability for the branch to be taken
+is below @var{probability}. @xref{Cross-profiling}.
+The default is (REG_BR_PROB_BASE/2), i.e.@: 5000.
+
+@end table
+
+The following options are maintained for backward compatibility, but
+are now deprecated and will be removed in a future release:
+
+@c Deprecated options
+@table @gcctabopt
+
+@item -margonaut
+@opindex margonaut
+Obsolete FPX.
+
+@item -mbig-endian
+@opindex mbig-endian
+@itemx -EB
+@opindex EB
+Compile code for big endian targets. Use of these options is now
+deprecated. Users wanting big-endian code, should use the
+@w{@code{arceb-elf32}} and @w{@code{arceb-linux-uclibc}} targets when
+building the tool chain, for which big-endian is the default.
+
+@item -mlittle-endian
+@opindex mlittle-endian
+@itemx -EL
+@opindex EL
+Compile code for little endian targets. Use of these options is now
+deprecated. Users wanting little-endian code should use the
+@w{@code{arc-elf32}} and @w{@code{arc-linux-uclibc}} targets when
+building the tool chain, for which little-endian is the default.
+
+@item -mbarrel_shifter
+@opindex mbarrel_shifter
+Replaced by @samp{-mbarrel-shifter}
+
+@item -mdpfp_compact
+@opindex mdpfp_compact
+Replaced by @samp{-mdpfp-compact}
+
+@item -mdpfp_fast
+@opindex mdpfp_fast
+Replaced by @samp{-mdpfp-fast}
+
+@item -mdsp_packa
+@opindex mdsp_packa
+Replaced by @samp{-mdsp-packa}
+
+@item -mEA
+@opindex mEA
+Replaced by @samp{-mea}
+
+@item -mmac_24
+@opindex mmac_24
+Replaced by @samp{-mmac-24}
+
+@item -mmac_d16
+@opindex mmac_d16
+Replaced by @samp{-mmac-d16}
+
+@item -mspfp_compact
+@opindex mspfp_compact
+Replaced by @samp{-mspfp-compact}
+
+@item -mspfp_fast
+@opindex mspfp_fast
+Replaced by @samp{-mspfp-fast}
+
+@item -mtune=@var{cpu}
+@opindex mtune
+Values @samp{arc600}, @samp{arc601}, @samp{arc700} and
+@samp{arc700-xmac} for @var{cpu} are replaced by @samp{ARC600},
+@samp{ARC601}, @samp{ARC700} and @samp{ARC700-xmac} respectively
+
+@item -multcost=@var{num}
+@opindex multcost
+Replaced by @samp{-mmultcost}.
+
+@end table
+
@node ARM Options
@subsection ARM Options
@cindex ARM options
@@ -12049,7 +12559,7 @@ generic or @code{__flash} is used, then @code{RAMPZ} is set
as needed before the operation.
@item
-If the device supports RAM larger than 64@tie{KiB} and the compiler
+If the device supports RAM larger than 64@tie{}KiB and the compiler
needs to change @code{RAMPZ} to accomplish an operation, @code{RAMPZ}
is reset to zero after the operation.
@@ -12059,7 +12569,7 @@ prologue/epilogue saves/restores that SFR and initializes it with
zero in case the ISR code might (implicitly) use it.
@item
-RAM larger than 64@tie{KiB} is not supported by GCC for AVR targets.
+RAM larger than 64@tie{}KiB is not supported by GCC for AVR targets.
If you use inline assembler to read from locations outside the
16-bit address range and change one of the @code{RAMP} registers,
you must reset it to zero after the access.
@@ -14472,6 +14982,8 @@ preferred alignment to @option{-mpreferred-stack-boundary=2}.
@itemx -mrtm
@itemx -mtbm
@itemx -mno-tbm
+@itemx -mmpx
+@itemx -mno-mpx
@opindex mmmx
@opindex mno-mmx
@opindex msse
@@ -14481,7 +14993,7 @@ preferred alignment to @option{-mpreferred-stack-boundary=2}.
These switches enable or disable the use of instructions in the MMX, SSE,
SSE2, SSE3, SSSE3, SSE4.1, AVX, AVX2, AVX512F, AVX512PF, AVX512ER, AVX512CD,
AES, PCLMUL, FSGSBASE, RDRND, F16C, FMA, SSE4A, FMA4, XOP, LWP, ABM, BMI, BMI2,
-FXSR, XSAVE, XSAVEOPT, LZCNT, RTM or 3DNow!@:
+FXSR, XSAVE, XSAVEOPT, LZCNT, RTM, MPX or 3DNow!@:
extended instruction sets.
These extensions are also available as built-in functions: see
@ref{X86 Built-in Functions}, for details of the functions enabled and
@@ -17313,10 +17825,6 @@ These options are defined for the MSP430:
@table @gcctabopt
-@item -msim
-@opindex msim
-Link the simulator runtime libraries.
-
@item -masm-hex
@opindex masm-hex
Force assembly output to always use hex constants. Normally such
@@ -17325,9 +17833,25 @@ testsuite and/or aesthetic purposes.
@item -mmcu=
@opindex mmcu=
-Select the MCU to target. Note that there are two ``generic'' MCUs,
-@code{msp430} and @code{msp430x}, which should be used most of the
-time. This option is also passed to the assembler.
+Select the MCU to target. If the MCU supports the MSP430X ISA or the
+MSP430Xv2 ISA then gcc will make use of the extra instructions. A C
+preprocessor symbol will be defined based upon the MCU name, converted
+to upper case and pre- and post- fixed with @code{__}.
+
+In addition two scripts will be added to the linker command line:
+@code{memory.ld} and @code{peripherals.ld}, with a search path based
+upon the MCU name.
+
+Note that there are three ``generic'' MCUs: @code{msp430},
+@code{msp430x} and @code{msp430xv2}, which can be used if a specific
+MCU is not being targeted.
+
+This option is also passed on to the assembler.
+
+@item -msim
+@opindex msim
+Link to the simulator runtime libraries and linker script. Overrides
+any scripts that would be selected by the @option{-mmcu=} option.
@item -mlarge
@opindex mlarge
@@ -17345,6 +17869,108 @@ the final link.
@end table
+@node NDS32 Options
+@subsection NDS32 Options
+@cindex NDS32 Options
+
+These options are defined for NDS32 implementations:
+
+@table @gcctabopt
+
+@item -mbig-endian
+@opindex mbig-endian
+Generate code in big-endian mode.
+
+@item -mlittle-endian
+@opindex mlittle-endian
+Generate code in little-endian mode.
+
+@item -mreduced-regs
+@opindex mreduced-regs
+Use reduced-set registers for register allocation.
+
+@item -mfull-regs
+@opindex mfull-regs
+Use full-set registers for register allocation.
+
+@item -mcmov
+@opindex mcmov
+Generate conditional move instructions.
+
+@item -mno-cmov
+@opindex mno-cmov
+Do not generate conditional move instructions.
+
+@item -mperf-ext
+@opindex mperf-ext
+Generate performance extension instructions.
+
+@item -mno-perf-ext
+@opindex mno-perf-ext
+Do not generate performance extension instructions.
+
+@item -mv3push
+@opindex mv3push
+Generate v3 push25/pop25 instructions.
+
+@item -mno-v3push
+@opindex mno-v3push
+Do not generate v3 push25/pop25 instructions.
+
+@item -m16-bit
+@opindex m16-bit
+Generate 16-bit instructions.
+
+@item -mno-16-bit
+@opindex mno-16-bit
+Do not generate 16-bit instructions.
+
+@item -mgp-direct
+@opindex mgp-direct
+Generate GP base instructions directly.
+
+@item -mno-gp-direct
+@opindex mno-gp-direct
+Do no generate GP base instructions directly.
+
+@item -misr-vector-size=@var{num}
+@opindex misr-vector-size
+Specify the size of each interrupt vector, which must be 4 or 16.
+
+@item -mcache-block-size=@var{num}
+@opindex mcache-block-size
+Specify the size of each cache block,
+which must be a power of 2 between 4 and 512.
+
+@item -march=@var{arch}
+@opindex march
+Specify the name of the target architecture.
+
+@item -mforce-fp-as-gp
+@opindex mforce-fp-as-gp
+Prevent $fp being allocated during register allocation so that compiler
+is able to force performing fp-as-gp optimization.
+
+@item -mforbid-fp-as-gp
+@opindex mforbid-fp-as-gp
+Forbid using $fp to access static and global variables.
+This option strictly forbids fp-as-gp optimization
+regardless of @option{-mforce-fp-as-gp}.
+
+@item -mex9
+@opindex mex9
+Use special directives to guide linker doing ex9 optimization.
+
+@item -mctor-dtor
+@opindex mctor-dtor
+Enable constructor/destructor feature.
+
+@item -mrelax
+@opindex mrelax
+Guide linker to relax instructions.
+
+@end table
+
@node PDP-11 Options
@subsection PDP-11 Options
@cindex PDP-11 Options
@@ -21171,14 +21797,6 @@ instruction, even though that accesses bytes that do not contain
any portion of the bit-field, or memory-mapped registers unrelated to
the one being updated.
-If the target requires strict alignment, and honoring the field
-type would require violating this alignment, a warning is issued.
-If the field has @code{packed} attribute, the access is done without
-honoring the field type. If the field doesn't have @code{packed}
-attribute, the access is done honoring the field type. In both cases,
-GCC assumes that the user knows something about the target hardware
-that it is unaware of.
-
The default value of this option is determined by the application binary
interface for the target processor.
diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi
index 57760469d33..1a06e3d6e74 100644
--- a/gcc/doc/md.texi
+++ b/gcc/doc/md.texi
@@ -1725,6 +1725,54 @@ DF modes
@end table
+@item ARC ---@file{config/arc/constraints.md}
+@table @code
+@item q
+Registers usable in ARCompact 16-bit instructions: @code{r0}-@code{r3},
+@code{r12}-@code{r15}. This constraint can only match when the @option{-mq}
+option is in effect.
+
+@item e
+Registers usable as base-regs of memory addresses in ARCompact 16-bit memory
+instructions: @code{r0}-@code{r3}, @code{r12}-@code{r15}, @code{sp}.
+This constraint can only match when the @option{-mq}
+option is in effect.
+@item D
+ARC FPX (dpfp) 64-bit registers. @code{D0}, @code{D1}.
+
+@item I
+A signed 12-bit integer constant.
+
+@item Cal
+constant for arithmetic/logical operations. This might be any constant
+that can be put into a long immediate by the assmbler or linker without
+involving a PIC relocation.
+
+@item K
+A 3-bit unsigned integer constant.
+
+@item L
+A 6-bit unsigned integer constant.
+
+@item CnL
+One's complement of a 6-bit unsigned integer constant.
+
+@item CmL
+Two's complement of a 6-bit unsigned integer constant.
+
+@item M
+A 5-bit unsigned integer constant.
+
+@item O
+A 7-bit unsigned integer constant.
+
+@item P
+A 8-bit unsigned integer constant.
+
+@item H
+Any const_double value.
+@end table
+
@item ARM family---@file{config/arm/constraints.md}
@table @code
@item w
@@ -2067,40 +2115,52 @@ Floating point register (containing 32-bit value)
Altivec vector register
@item wa
-Any VSX register
+Any VSX register if the -mvsx option was used or NO_REGS.
@item wd
-VSX vector register to hold vector double data
+VSX vector register to hold vector double data or NO_REGS.
@item wf
-VSX vector register to hold vector float data
+VSX vector register to hold vector float data or NO_REGS.
@item wg
-If @option{-mmfpgpr} was used, a floating point register
+If @option{-mmfpgpr} was used, a floating point register or NO_REGS.
@item wl
-If the LFIWAX instruction is enabled, a floating point register
+Floating point register if the LFIWAX instruction is enabled or NO_REGS.
@item wm
-If direct moves are enabled, a VSX register.
+VSX register if direct move instructions are enabled, or NO_REGS.
@item wn
-No register.
+No register (NO_REGS).
@item wr
-General purpose register if 64-bit mode is used
+General purpose register if 64-bit instructions are enabled or NO_REGS.
@item ws
-VSX vector register to hold scalar float data
+VSX vector register to hold scalar double values or NO_REGS.
@item wt
-VSX vector register to hold 128 bit integer
+VSX vector register to hold 128 bit integer or NO_REGS.
+
+@item wu
+Altivec register to use for float/32-bit int loads/stores or NO_REGS.
+
+@item wv
+Altivec register to use for double loads/stores or NO_REGS.
+
+@item ww
+FP or VSX register to perform float operations under @option{-mvsx} or NO_REGS.
@item wx
-If the STFIWX instruction is enabled, a floating point register
+Floating point register if the STFIWX instruction is enabled or NO_REGS.
+
+@item wy
+VSX vector register to hold scalar float values or NO_REGS.
@item wz
-If the LFIWZX instruction is enabled, a floating point register
+Floating point register if the LFIWZX instruction is enabled or NO_REGS.
@item wQ
A memory address that will work with the @code{lq} and @code{stq}
@@ -3092,6 +3152,87 @@ Memory reference, stack only.
@end table
+@item NDS32---@file{config/nds32/constraints.md}
+@table @code
+@item w
+LOW register class $r0 to $r7 constraint for V3/V3M ISA.
+@item l
+LOW register class $r0 to $r7.
+@item d
+MIDDLE register class $r0 to $r11, $r16 to $r19.
+@item h
+HIGH register class $r12 to $r14, $r20 to $r31.
+@item t
+Temporary assist register $ta (i.e.@: $r15).
+@item k
+Stack register $sp.
+@item Iu03
+Unsigned immediate 3-bit value.
+@item In03
+Negative immediate 3-bit value in the range of @minus{}7--0.
+@item Iu04
+Unsigned immediate 4-bit value.
+@item Is05
+Signed immediate 5-bit value.
+@item Iu05
+Unsigned immediate 5-bit value.
+@item In05
+Negative immediate 5-bit value in the range of @minus{}31--0.
+@item Ip05
+Unsigned immediate 5-bit value for movpi45 instruction with range 16--47.
+@item Iu06
+Unsigned immediate 6-bit value constraint for addri36.sp instruction.
+@item Iu08
+Unsigned immediate 8-bit value.
+@item Iu09
+Unsigned immediate 9-bit value.
+@item Is10
+Signed immediate 10-bit value.
+@item Is11
+Signed immediate 11-bit value.
+@item Is15
+Signed immediate 15-bit value.
+@item Iu15
+Unsigned immediate 15-bit value.
+@item Ic15
+A constant which is not in the range of imm15u but ok for bclr instruction.
+@item Ie15
+A constant which is not in the range of imm15u but ok for bset instruction.
+@item It15
+A constant which is not in the range of imm15u but ok for btgl instruction.
+@item Ii15
+A constant whose compliment value is in the range of imm15u
+and ok for bitci instruction.
+@item Is16
+Signed immediate 16-bit value.
+@item Is17
+Signed immediate 17-bit value.
+@item Is19
+Signed immediate 19-bit value.
+@item Is20
+Signed immediate 20-bit value.
+@item Ihig
+The immediate value that can be simply set high 20-bit.
+@item Izeb
+The immediate value 0xff.
+@item Izeh
+The immediate value 0xffff.
+@item Ixls
+The immediate value 0x01.
+@item Ix11
+The immediate value 0x7ff.
+@item Ibms
+The immediate value with power of 2.
+@item Ifex
+The immediate value with power of 2 minus 1.
+@item U33
+Memory constraint for 333 format.
+@item U45
+Memory constraint for 45 format.
+@item U37
+Memory constraint for 37 format.
+@end table
+
@item PDP-11---@file{config/pdp11/constraints.md}
@table @code
@item a
@@ -5150,12 +5291,13 @@ are the first two operands, and both are @code{mem:BLK}s with an
address in mode @code{Pmode}.
The number of bytes to move is the third operand, in mode @var{m}.
-Usually, you specify @code{word_mode} for @var{m}. However, if you can
+Usually, you specify @code{Pmode} for @var{m}. However, if you can
generate better code knowing the range of valid lengths is smaller than
-those representable in a full word, you should provide a pattern with a
+those representable in a full Pmode pointer, you should provide
+a pattern with a
mode corresponding to the range of values you can handle efficiently
(e.g., @code{QImode} for values in the range 0--127; note we avoid numbers
-that appear negative) and also a pattern with @code{word_mode}.
+that appear negative) and also a pattern with @code{Pmode}.
The fourth operand is the known shared alignment of the source and
destination, in the form of a @code{const_int} rtx. Thus, if the
@@ -5715,34 +5857,27 @@ reduction is enabled.
@cindex @code{doloop_end} instruction pattern
@item @samp{doloop_end}
-Conditional branch instruction that decrements a register and jumps if
-the register is nonzero. This instruction takes five operands: Operand
-0 is the register to decrement and test; operand 1 is the number of loop
-iterations as a @code{const_int} or @code{const0_rtx} if this cannot be
-determined until run-time; operand 2 is the actual or estimated maximum
-number of iterations as a @code{const_int}; operand 3 is the number of
-enclosed loops as a @code{const_int} (an innermost loop has a value of
-1); operand 4 is the label to jump to if the register is nonzero;
-operand 5 is const1_rtx if the loop in entered at its top, const0_rtx
-otherwise.
+Conditional branch instruction that decrements a register and
+jumps if the register is nonzero. Operand 0 is the register to
+decrement and test; operand 1 is the label to jump to if the
+register is nonzero.
@xref{Looping Patterns}.
This optional instruction pattern should be defined for machines with
low-overhead looping instructions as the loop optimizer will try to
-modify suitable loops to utilize it. If nested low-overhead looping is
-not supported, use a @code{define_expand} (@pxref{Expander Definitions})
-and make the pattern fail if operand 3 is not @code{const1_rtx}.
-Similarly, if the actual or estimated maximum number of iterations is
-too large for this instruction, make it fail.
+modify suitable loops to utilize it. The target hook
+@code{TARGET_CAN_USE_DOLOOP_P} controls the conditions under which
+low-overhead loops can be used.
@cindex @code{doloop_begin} instruction pattern
@item @samp{doloop_begin}
Companion instruction to @code{doloop_end} required for machines that
-need to perform some initialization, such as loading special registers
-used by a low-overhead looping instruction. If initialization insns do
-not always need to be emitted, use a @code{define_expand}
-(@pxref{Expander Definitions}) and make it fail.
+need to perform some initialization, such as loading a special counter
+register. Operand 1 is the associated @code{doloop_end} pattern and
+operand 0 is the register that it decrements.
+If initialization insns do not always need to be emitted, use a
+@code{define_expand} (@pxref{Expander Definitions}) and make it fail.
@cindex @code{canonicalize_funcptr_for_compare} instruction pattern
@item @samp{canonicalize_funcptr_for_compare}
@@ -7638,6 +7773,7 @@ to track the condition codes.
* Attr Example:: An example of assigning attributes.
* Insn Lengths:: Computing the length of insns.
* Constant Attributes:: Defining attributes that are constant.
+* Mnemonic Attribute:: Obtain the instruction mnemonic as attribute value.
* Delay Slots:: Defining delay slots required for a machine.
* Processor pipeline description:: Specifying information for insn scheduling.
@end menu
@@ -7657,15 +7793,17 @@ by the target machine. It looks like:
(define_attr @var{name} @var{list-of-values} @var{default})
@end smallexample
-@var{name} is a string specifying the name of the attribute being defined.
-Some attributes are used in a special way by the rest of the compiler. The
-@code{enabled} attribute can be used to conditionally enable or disable
-insn alternatives (@pxref{Disable Insn Alternatives}). The @code{predicable}
-attribute, together with a suitable @code{define_cond_exec}
-(@pxref{Conditional Execution}), can be used to automatically generate
-conditional variants of instruction patterns. The compiler internally uses
-the names @code{ce_enabled} and @code{nonce_enabled}, so they should not be
-used elsewhere as alternative names.
+@var{name} is a string specifying the name of the attribute being
+defined. Some attributes are used in a special way by the rest of the
+compiler. The @code{enabled} attribute can be used to conditionally
+enable or disable insn alternatives (@pxref{Disable Insn
+Alternatives}). The @code{predicable} attribute, together with a
+suitable @code{define_cond_exec} (@pxref{Conditional Execution}), can
+be used to automatically generate conditional variants of instruction
+patterns. The @code{mnemonic} attribute can be used to check for the
+instruction mnemonic (@pxref{Mnemonic Attribute}). The compiler
+internally uses the names @code{ce_enabled} and @code{nonce_enabled},
+so they should not be used elsewhere as alternative names.
@var{list-of-values} is either a string that specifies a comma-separated
list of values that can be assigned to the attribute, or a null string to
@@ -7729,6 +7867,11 @@ distances. @xref{Insn Lengths}.
The @code{enabled} attribute can be defined to prevent certain
alternatives of an insn definition from being used during code
generation. @xref{Disable Insn Alternatives}.
+
+@item mnemonic
+The @code{mnemonic} attribute can be defined to implement instruction
+specific checks in e.g. the pipeline description.
+@xref{Mnemonic Attribute}.
@end table
For each of these special attributes, the corresponding
@@ -8281,6 +8424,47 @@ forms involving insn attributes.
@end ifset
@ifset INTERNALS
+@node Mnemonic Attribute
+@subsection Mnemonic Attribute
+@cindex mnemonic attribute
+
+The @code{mnemonic} attribute is a string type attribute holding the
+instruction mnemonic for an insn alternative. The attribute values
+will automatically be generated by the machine description parser if
+there is an attribute definition in the md file:
+
+@smallexample
+(define_attr "mnemonic" "unknown" (const_string "unknown"))
+@end smallexample
+
+The default value can be freely chosen as long as it does not collide
+with any of the instruction mnemonics. This value will be used
+whenever the machine description parser is not able to determine the
+mnemonic string. This might be the case for output templates
+containing more than a single instruction as in
+@code{"mvcle\t%0,%1,0\;jo\t.-4"}.
+
+The @code{mnemonic} attribute set is not generated automatically if the
+instruction string is generated via C code.
+
+An existing @code{mnemonic} attribute set in an insn definition will not
+be overriden by the md file parser. That way it is possible to
+manually set the instruction mnemonics for the cases where the md file
+parser fails to determine it automatically.
+
+The @code{mnemonic} attribute is useful for dealing with instruction
+specific properties in the pipeline description without defining
+additional insn attributes.
+
+@smallexample
+(define_attr "ooo_expanded" ""
+ (cond [(eq_attr "mnemonic" "dlr,dsgr,d,dsgf,stam,dsgfr,dlgr")
+ (const_int 1)]
+ (const_int 0)))
+@end smallexample
+
+@end ifset
+@ifset INTERNALS
@node Delay Slots
@subsection Delay Slot Scheduling
@cindex delay slots, defining
diff --git a/gcc/doc/passes.texi b/gcc/doc/passes.texi
index 045f964a939..3ed9a4fc204 100644
--- a/gcc/doc/passes.texi
+++ b/gcc/doc/passes.texi
@@ -124,13 +124,45 @@ true, then we expand them using either @code{expand_array_notation_exprs} or
inside conditions, they are transformed using the function
@code{fix_conditional_array_notations}. The C language-specific routines are
located in @file{c/c-array-notation.c} and the equivalent C++ routines are in
-file @file{cp/cp-array-notation.c}. Common routines such as functions to
-initialize builtin functions are stored in @file{array-notation-common.c}.
+the file @file{cp/cp-array-notation.c}. Common routines such as functions to
+initialize built-in functions are stored in @file{array-notation-common.c}.
+
+@item Cilk keywords:
+@itemize @bullet
+@item @code{_Cilk_spawn}:
+The @code{_Cilk_spawn} keyword is parsed and the function it contains is marked
+as a spawning function. The spawning function is called the spawner. At
+the end of the parsing phase, appropriate built-in functions are
+added to the spawner that are defined in the Cilk runtime. The appropriate
+locations of these functions, and the internal structures are detailed in
+@code{cilk_init_builtins} in the file @file{cilk-common.c}. The pointers to
+Cilk functions and fields of internal structures are described
+in @file{cilk.h}. The built-in functions are described in
+@file{cilk-builtins.def}.
+
+During gimplification, a new "spawn-helper" function is created.
+The spawned function is replaced with a spawn helper function in the spawner.
+The spawned function-call is moved into the spawn helper. The main function
+that does these transformations is @code{gimplify_cilk_spawn} in
+@file{c-family/cilk.c}. In the spawn-helper, the gimplification function
+@code{gimplify_call_expr}, inserts a function call @code{__cilkrts_detach}.
+This function is expanded by @code{builtin_expand_cilk_detach} located in
+@file{c-family/cilk.c}.
+
+@item @code{_Cilk_sync}:
+@code{_Cilk_sync} is parsed like a keyword. During gimplification,
+the function @code{gimplify_cilk_sync} in @file{c-family/cilk.c}, will replace
+this keyword with a set of functions that are stored in the Cilk runtime.
+One of the internal functions inserted during gimplification,
+@code{__cilkrts_pop_frame} must be expanded by the compiler and is
+done by @code{builtin_expand_cilk_pop_frame} in @file{cilk-common.c}.
+
+@end itemize
@end itemize
-Detailed information about Cilk Plus and language specification is provided in
-@w{@uref{http://www.cilkplus.org/}}. It is worth mentioning that the current
-implementation follows ABI 0.9.
+Documentation about Cilk Plus and language specification is provided under the
+"Learn" section in @w{@uref{http://www.cilkplus.org/}}. It is worth mentioning
+that the current implementation follows ABI 1.1.
@node Gimplification pass
@section Gimplification pass
@@ -225,20 +257,6 @@ stuff quickly rather than wait until later when it's more work to get
rid of it. This pass is located in @file{tree-cfg.c} and described by
@code{pass_remove_useless_stmts}.
-@item Mudflap declaration registration
-
-If mudflap (@pxref{Optimize Options,,-fmudflap -fmudflapth
--fmudflapir,gcc,Using the GNU Compiler Collection (GCC)}) is
-enabled, we generate code to register some variable declarations with
-the mudflap runtime. Specifically, the runtime tracks the lifetimes of
-those variable declarations that have their addresses taken, or whose
-bounds are unknown at compile time (@code{extern}). This pass generates
-new exception handling constructs (@code{try}/@code{finally}), and so
-must run before those are lowered. In addition, the pass enqueues
-declarations of static variables whose lifetimes extend to the entire
-program. The pass is located in @file{tree-mudflap.c} and is described
-by @code{pass_mudflap_1}.
-
@item OpenMP lowering
If OpenMP generation (@option{-fopenmp}) is enabled, this pass lowers
@@ -576,18 +594,6 @@ run last so that we have as much time as possible to prove that the
statement is not reachable. It is located in @file{tree-cfg.c} and
is described by @code{pass_warn_function_return}.
-@item Mudflap statement annotation
-
-If mudflap is enabled, we rewrite some memory accesses with code to
-validate that the memory access is correct. In particular, expressions
-involving pointer dereferences (@code{INDIRECT_REF}, @code{ARRAY_REF},
-etc.) are replaced by code that checks the selected address range
-against the mudflap runtime's database of valid regions. This check
-includes an inline lookup into a direct-mapped cache, based on
-shift/mask operations of the pointer value, with a fallback function
-call into the runtime. The pass is located in @file{tree-mudflap.c} and
-is described by @code{pass_mudflap_2}.
-
@item Leave static single assignment form
This pass rewrites the function such that it is in normal form. At
@@ -817,14 +823,6 @@ RTL expressions for the instructions by substitution, simplifies the
result using algebra, and then attempts to match the result against
the machine description. The code is located in @file{combine.c}.
-@item Register movement
-
-This pass looks for cases where matching constraints would force an
-instruction to need a reload, and this reload would be a
-register-to-register move. It then attempts to change the registers
-used by the instruction to avoid the move instruction. The code is
-located in @file{regmove.c}.
-
@item Mode switching optimization
This pass looks for instructions that require the processor to be in a
@@ -863,11 +861,6 @@ them on the stack. This is done in several subpasses:
@itemize @bullet
@item
-Register move optimizations. This pass makes some simple RTL code
-transformations which improve the subsequent register allocation. The
-source file is @file{regmove.c}.
-
-@item
The integrated register allocator (@acronym{IRA}). It is called
integrated because coalescing, register live range splitting, and hard
register preferencing are done on-the-fly during coloring. It also
@@ -968,10 +961,7 @@ This pass outputs the assembler code for the function. The source files
are @file{final.c} plus @file{insn-output.c}; the latter is generated
automatically from the machine description by the tool @file{genoutput}.
The header file @file{conditions.h} is used for communication between
-these files. If mudflap is enabled, the queue of deferred declarations
-and any addressed constants (e.g., string literals) is processed by
-@code{mudflap_finish_file} into a synthetic constructor function
-containing calls into the mudflap runtime.
+these files.
@item Debugging information output
diff --git a/gcc/doc/rtl.texi b/gcc/doc/rtl.texi
index 1d6222382b8..df2bb6806dc 100644
--- a/gcc/doc/rtl.texi
+++ b/gcc/doc/rtl.texi
@@ -1295,6 +1295,12 @@ These modes stand for a complex number represented as a pair of integer
values. The integer values are in @code{QImode}, @code{HImode},
@code{SImode}, @code{DImode}, @code{TImode}, and @code{OImode},
respectively.
+
+@findex BND32mode
+@findex BND64mode
+@item BND32mode BND64mode
+These modes stand for bounds for pointer of 32 and 64 bit size respectively.
+Mode size is double pointer mode size.
@end table
The machine description defines @code{Pmode} as a C macro which expands
@@ -1382,6 +1388,12 @@ any @code{CC_MODE} modes listed in the @file{@var{machine}-modes.def}.
@xref{Jump Patterns},
also see @ref{Condition Code}.
+@findex MODE_POINTER_BOUNDS
+@item MODE_POINTER_BOUNDS
+Pointer bounds modes. Used to represent values of pointer bounds type.
+Operations in these modes may be executed as NOPs depending on hardware
+features and environment setup.
+
@findex MODE_RANDOM
@item MODE_RANDOM
This is a catchall mode class for modes which don't fit into the above
@@ -3732,8 +3744,8 @@ Def-use and use-def chains are now preferred.
@findex REG_NOTES
@item REG_NOTES (@var{i})
-A list (chain of @code{expr_list} and @code{insn_list} expressions)
-giving miscellaneous information about the insn. It is often
+A list (chain of @code{expr_list}, @code{insn_list} and @code{int_list}
+expressions) giving miscellaneous information about the insn. It is often
information pertaining to the registers used in this insn.
@end table
@@ -3752,10 +3764,10 @@ analysis pass adds a link to insns which store into registers values
that are used for the first time in this insn.
The @code{REG_NOTES} field of an insn is a chain similar to the
-@code{LOG_LINKS} field but it includes @code{expr_list} expressions in
-addition to @code{insn_list} expressions. There are several kinds of
-register notes, which are distinguished by the machine mode, which in a
-register note is really understood as being an @code{enum reg_note}.
+@code{LOG_LINKS} field but it includes @code{expr_list} and @code{int_list}
+expressions in addition to @code{insn_list} expressions. There are several
+kinds of register notes, which are distinguished by the machine mode, which
+in a register note is really understood as being an @code{enum reg_note}.
The first operand @var{op} of the note is data whose meaning depends on
the kind of note.
@@ -3956,16 +3968,16 @@ This indicates an anti dependence (a write after read dependence).
@end table
These notes describe information gathered from gcov profile data. They
-are stored in the @code{REG_NOTES} field of an insn as an
-@code{expr_list}.
+are stored in the @code{REG_NOTES} field of an insn.
@table @code
@findex REG_BR_PROB
@item REG_BR_PROB
This is used to specify the ratio of branches to non-branches of a
-branch insn according to the profile data. The value is stored as a
-value between 0 and REG_BR_PROB_BASE; larger values indicate a higher
-probability that the branch will be taken.
+branch insn according to the profile data. The note is represented
+as an @code{int_list} expression whose integer value is between 0 and
+REG_BR_PROB_BASE. Larger values indicate a higher probability that
+the branch will be taken.
@findex REG_BR_PRED
@item REG_BR_PRED
diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi
index 90bd0bdf230..2947ac8fae2 100644
--- a/gcc/doc/sourcebuild.texi
+++ b/gcc/doc/sourcebuild.texi
@@ -103,10 +103,6 @@ The runtime support library for transactional memory.
@item libjava
The Java runtime library.
-@item libmudflap
-The @code{libmudflap} library, used for instrumenting pointer and array
-dereferencing operations.
-
@item libobjc
The Objective-C and Objective-C++ runtime library.
@@ -120,7 +116,7 @@ The Stack protector runtime library.
The C++ runtime library.
@item lto-plugin
-Plugin used by @command{gold} if link-time optimizations are enabled.
+Plugin used by the linker if link-time optimizations are enabled.
@item maintainer-scripts
Scripts used by the @code{gccadmin} account on @code{gcc.gnu.org}.
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 8d220f31b51..35cfa995583 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -768,6 +768,10 @@ Define this macro to 1 if your target needs this facility. The default
is 0.
@end defmac
+@deftypefn {Target Hook} bool TARGET_FLOAT_EXCEPTIONS_ROUNDING_SUPPORTED_P (void)
+Returns true if the target supports IEEE 754 floating-point exceptions and rounding modes, false otherwise. This is intended to relate to the @code{float} and @code{double} types, but not necessarily @code{long double}. By default, returns true if the @code{adddf3} instruction pattern is available and false otherwise, on the assumption that hardware floating point supports exceptions and rounding modes but software floating point does not.
+@end deftypefn
+
@node Per-Function Data
@section Defining data structures for per-function information.
@cindex per-function data
@@ -4334,6 +4338,13 @@ This hook returns the va_list type of the calling convention specified by
The default version of this hook returns @code{va_list_type_node}.
@end deftypefn
+@deftypefn {Target Hook} tree TARGET_FN_ABI_VA_LIST_BOUNDS_SIZE (tree @var{fndecl})
+This hook returns size for @code{va_list} object in function specified
+by @var{fndecl}. This hook is used by Pointer Bounds Checker to build bounds
+for @code{va_list} object. Return @code{integer_zero_node} if no bounds
+should be used (e.g. @code{va_list} is a scalar pointer to the stack).
+@end deftypefn
+
@deftypefn {Target Hook} tree TARGET_CANONICAL_VA_LIST_TYPE (tree @var{type})
This hook returns the va_list type of the calling convention specified by the
type of @var{type}. If @var{type} is not a valid va_list type, it returns
@@ -5151,6 +5162,26 @@ defined, then define this hook to return @code{true} if
Otherwise, you should not define this hook.
@end deftypefn
+@deftypefn {Target Hook} rtx TARGET_LOAD_BOUNDS_FOR_ARG (rtx @var{slot}, rtx @var{arg}, rtx @var{slot_no})
+This hook is used by expand pass to emit insn to load bounds of
+@var{arg} passed in @var{slot}. Expand pass uses this hook in case
+bounds of @var{arg} are not passed in register. If @var{slot} is a
+memory, then bounds are loaded as for regular pointer loaded from
+memory. If @var{slot} is not a memory then @var{slot_no} is an integer
+constant holding number of the target dependent special slot which
+should be used to obtain bounds. Hook returns RTX holding loaded bounds.
+@end deftypefn
+
+@deftypefn {Target Hook} void TARGET_STORE_BOUNDS_FOR_ARG (rtx @var{arg}, rtx @var{slot}, rtx @var{bounds}, rtx @var{slot_no})
+This hook is used by expand pass to emit insns to store @var{bounds} of
+@var{arg} passed in @var{slot}. Expand pass uses this hook in case
+@var{bounds} of @var{arg} are not passed in register. If @var{slot} is a
+memory, then @var{bounds} are stored as for regular pointer stored in
+memory. If @var{slot} is not a memory then @var{slot_no} is an integer
+constant holding number of the target dependent special slot which
+should be used to store @var{bounds}.
+@end deftypefn
+
@node Trampolines
@section Trampolines for Nested Functions
@cindex trampolines for nested functions
@@ -6543,6 +6574,17 @@ scheduling one insn causes other insns to become ready in the same
cycle. These other insns can then be taken into account properly.
@end deftypefn
+@deftypefn {Target Hook} bool TARGET_SCHED_MACRO_FUSION_P (void)
+This hook is used to check whether target platform supports macro fusion.
+@end deftypefn
+
+@deftypefn {Target Hook} bool TARGET_SCHED_MACRO_FUSION_PAIR_P (rtx @var{condgen}, rtx @var{condjmp})
+This hook is used to check whether two insns could be macro fused for
+target microarchitecture. If this hook returns true for the given insn pair
+(@var{condgen} and @var{condjmp}), scheduler will put them into a sched
+group, and they will not be scheduled apart.
+@end deftypefn
+
@deftypefn {Target Hook} void TARGET_SCHED_DEPENDENCIES_EVALUATION_HOOK (rtx @var{head}, rtx @var{tail})
This hook is called after evaluation forward dependencies of insns in
chain given by two parameter values (@var{head} and @var{tail}
@@ -9853,17 +9895,17 @@ the function declaration to hold a pointer to a target-specific
@code{struct cl_target_option} structure.
@end deftypefn
-@deftypefn {Target Hook} void TARGET_OPTION_SAVE (struct cl_target_option *@var{ptr})
+@deftypefn {Target Hook} void TARGET_OPTION_SAVE (struct cl_target_option *@var{ptr}, struct gcc_options *@var{opts})
This hook is called to save any additional target-specific information
in the @code{struct cl_target_option} structure for function-specific
-options.
+options from the @code{struct gcc_options} structure.
@xref{Option file format}.
@end deftypefn
-@deftypefn {Target Hook} void TARGET_OPTION_RESTORE (struct cl_target_option *@var{ptr})
+@deftypefn {Target Hook} void TARGET_OPTION_RESTORE (struct gcc_options *@var{opts}, struct cl_target_option *@var{ptr})
This hook is called to restore any additional target-specific
information in the @code{struct cl_target_option} structure for
-function-specific options.
+function-specific options to the @code{struct gcc_options} structure.
@end deftypefn
@deftypefn {Target Hook} void TARGET_OPTION_PRINT (FILE *@var{file}, int @var{indent}, struct cl_target_option *@var{ptr})
@@ -10907,6 +10949,96 @@ ignored. This function should return the result of the call to the
built-in function.
@end deftypefn
+@deftypefn {Target Hook} tree TARGET_BUILTIN_CHKP_FUNCTION (unsigned @var{fcode})
+This hook allows target to redefine built-in functions used by
+Pointer Bounds Checker for code instrumentation. Hook should return
+fndecl of function implementing generic builtin whose code is
+passed in @var{fcode}. Currently following built-in functions are
+obtained using this hook:
+@deftypefn {Built-in Function} bnd __chkp_bndmk (const void *@var{lb}, size_t @var{size})
+Function code - BUILT_IN_CHKP_BNDMK. This built-in function is used
+by Pointer Bounds Checker to create bound values. @var{lb} holds low
+bound of the resulting bounds. @var{size} holds size of created bounds.
+@end deftypefn
+
+@deftypefn {Built-in Function} void __chkp_bndstx (const void **@var{loc}, const void *@var{ptr}, bnd @var{b})
+Function code - @code{BUILT_IN_CHKP_BNDSTX}. This built-in function is used
+by Pointer Bounds Checker to store bounds @var{b} for pointer @var{ptr}
+stored by address @var{loc}.
+@end deftypefn
+
+@deftypefn {Built-in Function} bnd __chkp_bndldx (const void **@var{loc}, const void *@var{ptr})
+Function code - @code{BUILT_IN_CHKP_BNDLDX}. This built-in function is used
+by Pointer Bounds Checker to get bounds of pointer @var{ptr} loaded by
+address @var{loc}.
+@end deftypefn
+
+@deftypefn {Built-in Function} void __chkp_bndcl (bnd @var{b}, const void *@var{ptr})
+Function code - @code{BUILT_IN_CHKP_BNDCL}. This built-in function is used
+by Pointer Bounds Checker to perform check for pointer @var{ptr} against
+lower bound of bounds @var{b}.
+@end deftypefn
+
+@deftypefn {Built-in Function} void __chkp_bndcu (bnd @var{b}, const void *@var{ptr})
+Function code - @code{BUILT_IN_CHKP_BNDCU}. This built-in function is used
+by Pointer Bounds Checker to perform check for pointer @var{ptr} against
+upper bound of bounds @var{b}.
+@end deftypefn
+
+@deftypefn {Built-in Function} bnd __chkp_bndret (void *@var{ptr})
+Function code - @code{BUILT_IN_CHKP_BNDRET}. This built-in function is used
+by Pointer Bounds Checker to obtain bounds returned by call statement.
+@var{ptr} passed to buil-in is @code{SSA_NAME} returned by call.
+@end deftypefn
+
+@deftypefn {Built-in Function} bnd __chkp_arg_bnd (void *@var{arg})
+Function code - @code{BUILT_IN_CHKP_ARG_BND}. This built-in function is
+used by Pointer Bounds Checker to obtain bounds passed for input argument.
+@var{arg} is default @code{SSA_NAME} of the @code{PARM_DECL} whose
+bounds we want to obtain.
+@end deftypefn
+
+@deftypefn {Built-in Function} bnd __chkp_intersect (bnd @var{b1}, bnd @var{b2})
+Function code - @code{BUILT_IN_CHKP_INTERSECT}. This built-in function
+returns intersection of bounds @var{b1} and @var{b2}.
+@end deftypefn
+
+@deftypefn {Built-in Function} bnd __chkp_narrow (const void *@var{ptr}, bnd @var{b}, size_t @var{s})
+Function code - @code{BUILT_IN_CHKP_NARROW}. This built-in function
+returns intersection of bounds @var{b} and
+[@var{ptr}, @var{ptr} + @var{s} - @code{1}].
+@end deftypefn
+
+@deftypefn {Built-in Function} void *__chkp_set_bounds (const void *@var{ptr}, size_t @var{s})
+Function code - @code{BUILT_IN_CHKP_SET_PTR_BOUNDS}. This built-in function
+returns @var{ptr} with bounds [@var{ptr}, @var{ptr} + @var{s} - @code{1}].
+@end deftypefn
+
+@deftypefn {Built-in Function} size_t __chkp_sizeof (const void *@var{ptr})
+Function code - @code{BUILT_IN_CHKP_SIZEOF}. This built-in function
+returns size of object referenced by @var{ptr}. @var{ptr} is always
+@code{ADDR_EXPR} of @code{VAR_DECL}. This built-in is used by
+Pointer Boudns Checker when bounds of object cannot be computed statically
+(e.g. object has incomplete type).
+@end deftypefn
+
+@deftypefn {Built-in Function} const void *__chkp_extract_lower (bnd @var{b})
+Function code - @code{BUILT_IN_CHKP_EXTRACT_LOWER}. This built-in function
+returns lower bound of bounds @var{b}.
+@end deftypefn
+
+@deftypefn {Built-in Function} const void *__chkp_extract_upper (bnd @var{b})
+Function code - @code{BUILT_IN_CHKP_EXTRACT_UPPER}. This built-in function
+returns upper bound of bounds @var{b}.
+@end deftypefn
+@end deftypefn
+@deftypefn {Target Hook} tree TARGET_CHKP_BOUND_TYPE (void)
+Return type to be used for bounds
+@end deftypefn
+@deftypefn {Target Hook} {enum machine_mode} TARGET_CHKP_BOUND_MODE (void)
+Return mode to be used for bounds.
+@end deftypefn
+
@deftypefn {Target Hook} tree TARGET_RESOLVE_OVERLOADED_BUILTIN (unsigned int @var{loc}, tree @var{fndecl}, void *@var{arglist})
Select a replacement for a machine specific built-in function that
was set up by @samp{TARGET_INIT_BUILTINS}. This is done
@@ -10959,6 +11091,20 @@ function version at run-time for a given set of function versions.
body must be generated.
@end deftypefn
+@deftypefn {Target Hook} bool TARGET_CAN_USE_DOLOOP_P (double_int @var{iterations}, double_int @var{iterations_max}, unsigned int @var{loop_depth}, bool @var{entered_at_top})
+Return true if it is possible to use low-overhead loops (@code{doloop_end}
+and @code{doloop_begin}) for a particular loop. @var{iterations} gives the
+exact number of iterations, or 0 if not known. @var{iterations_max} gives
+the maximum number of iterations, or 0 if not known. @var{loop_depth} is
+the nesting depth of the loop, with 1 for innermost loops, 2 for loops that
+contain innermost loops, and so on. @var{entered_at_top} is true if the
+loop is only entered from the top.
+
+This hook is only used if @code{doloop_end} is available. The default
+implementation returns true. You can use @code{can_use_doloop_if_innermost}
+if the loop must be the innermost, and if there are no other restrictions.
+@end deftypefn
+
@deftypefn {Target Hook} {const char *} TARGET_INVALID_WITHIN_DOLOOP (const_rtx @var{insn})
Take an instruction in @var{insn} and return NULL if it is valid within a
@@ -11353,3 +11499,7 @@ It returns true if the target supports GNU indirect functions.
The support includes the assembler, linker and dynamic linker.
The default value of this hook is based on target's libc.
@end deftypefn
+
+@deftypefn {Target Hook} void TARGET_ATOMIC_ASSIGN_EXPAND_FENV (tree *@var{hold}, tree *@var{clear}, tree *@var{update})
+ISO C11 requires atomic compound assignments that may raise floating-point exceptions to raise exceptions corresponding to the arithmetic operation whose result was successfully stored in a compare-and-exchange sequence. This requires code equivalent to calls to @code{feholdexcept}, @code{feclearexcept} and @code{feupdateenv} to be generated at appropriate points in the compare-and-exchange sequence. This hook should set @code{*@var{hold}} to an expression equivalent to the call to @code{feholdexcept}, @code{*@var{clear}} to an expression equivalent to the call to @code{feclearexcept} and @code{*@var{update}} to an expression equivalent to the call to @code{feupdateenv}. The three expressions are @code{NULL_TREE} on entry to the hook and may be left as @code{NULL_TREE} if no code is required in a particular place. The default implementation leaves all three expressions as @code{NULL_TREE}. The @code{__atomic_feraiseexcept} function from @code{libatomic} may be of use as part of the code generated in @code{*@var{update}}.
+@end deftypefn
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index 863e843af3d..b10ecd7dda8 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -744,6 +744,8 @@ Define this macro to 1 if your target needs this facility. The default
is 0.
@end defmac
+@hook TARGET_FLOAT_EXCEPTIONS_ROUNDING_SUPPORTED_P
+
@node Per-Function Data
@section Defining data structures for per-function information.
@cindex per-function data
@@ -3694,6 +3696,8 @@ stack.
@hook TARGET_FN_ABI_VA_LIST
+@hook TARGET_FN_ABI_VA_LIST_BOUNDS_SIZE
+
@hook TARGET_CANONICAL_VA_LIST_TYPE
@hook TARGET_GIMPLIFY_VA_ARG_EXPR
@@ -4064,6 +4068,10 @@ These machine description macros help implement varargs:
@hook TARGET_PRETEND_OUTGOING_VARARGS_NAMED
+@hook TARGET_LOAD_BOUNDS_FOR_ARG
+
+@hook TARGET_STORE_BOUNDS_FOR_ARG
+
@node Trampolines
@section Trampolines for Nested Functions
@cindex trampolines for nested functions
@@ -4930,6 +4938,10 @@ them: try the first ones in this list first.
@hook TARGET_SCHED_REORDER2
+@hook TARGET_SCHED_MACRO_FUSION_P
+
+@hook TARGET_SCHED_MACRO_FUSION_PAIR_P
+
@hook TARGET_SCHED_DEPENDENCIES_EVALUATION_HOOK
@hook TARGET_SCHED_INIT
@@ -8184,6 +8196,10 @@ to by @var{ce_info}.
@hook TARGET_EXPAND_BUILTIN
+@hook TARGET_BUILTIN_CHKP_FUNCTION
+@hook TARGET_CHKP_BOUND_TYPE
+@hook TARGET_CHKP_BOUND_MODE
+
@hook TARGET_RESOLVE_OVERLOADED_BUILTIN
@hook TARGET_FOLD_BUILTIN
@@ -8196,6 +8212,8 @@ to by @var{ce_info}.
@hook TARGET_GENERATE_VERSION_DISPATCHER_BODY
+@hook TARGET_CAN_USE_DOLOOP_P
+
@hook TARGET_INVALID_WITHIN_DOLOOP
@hook TARGET_LEGITIMATE_COMBINED_INSN
@@ -8388,3 +8406,5 @@ and the associated definitions of those functions.
@hook TARGET_ATOMIC_TEST_AND_SET_TRUEVAL
@hook TARGET_HAS_IFUNC_P
+
+@hook TARGET_ATOMIC_ASSIGN_EXPAND_FENV
diff --git a/gcc/doc/tree-ssa.texi b/gcc/doc/tree-ssa.texi
index fc479d63629..93f596d07a4 100644
--- a/gcc/doc/tree-ssa.texi
+++ b/gcc/doc/tree-ssa.texi
@@ -526,31 +526,29 @@ the result of ``merging'' @code{a_1}, @code{a_2} and @code{a_3}.
Hence, PHI nodes mean ``one of these operands. I don't know
which''.
-The following macros can be used to examine PHI nodes
+The following functions can be used to examine PHI nodes
-@defmac PHI_RESULT (@var{phi})
+@defun gimple_phi_result (@var{phi})
Returns the @code{SSA_NAME} created by PHI node @var{phi} (i.e.,
@var{phi}'s LHS)@.
-@end defmac
+@end defun
-@defmac PHI_NUM_ARGS (@var{phi})
+@defun gimple_phi_num_args (@var{phi})
Returns the number of arguments in @var{phi}. This number is exactly
the number of incoming edges to the basic block holding @var{phi}@.
-@end defmac
+@end defun
-@defmac PHI_ARG_ELT (@var{phi}, @var{i})
-Returns a tuple representing the @var{i}th argument of @var{phi}@.
-Each element of this tuple contains an @code{SSA_NAME} @var{var} and
-the incoming edge through which @var{var} flows.
-@end defmac
+@defun gimple_phi_arg (@var{phi}, @var{i})
+Returns @var{i}th argument of @var{phi}@.
+@end defun
-@defmac PHI_ARG_EDGE (@var{phi}, @var{i})
+@defun gimple_phi_arg_edge (@var{phi}, @var{i})
Returns the incoming edge for the @var{i}th argument of @var{phi}.
-@end defmac
+@end defun
-@defmac PHI_ARG_DEF (@var{phi}, @var{i})
+@defun gimple_phi_arg_def (@var{phi}, @var{i})
Returns the @code{SSA_NAME} for the @var{i}th argument of @var{phi}.
-@end defmac
+@end defun
@subsection Preserving the SSA form
@@ -725,33 +723,6 @@ Returns the version number of the @code{SSA_NAME} object @var{var}.
@end defmac
-@subsection Walking use-def chains
-
-@deftypefn {Tree SSA function} void walk_use_def_chains (@var{var}, @var{fn}, @var{data})
-
-Walks use-def chains starting at the @code{SSA_NAME} node @var{var}.
-Calls function @var{fn} at each reaching definition found. Function
-@var{FN} takes three arguments: @var{var}, its defining statement
-(@var{def_stmt}) and a generic pointer to whatever state information
-that @var{fn} may want to maintain (@var{data}). Function @var{fn} is
-able to stop the walk by returning @code{true}, otherwise in order to
-continue the walk, @var{fn} should return @code{false}.
-
-Note, that if @var{def_stmt} is a @code{PHI} node, the semantics are
-slightly different. For each argument @var{arg} of the PHI node, this
-function will:
-
-@enumerate
-@item Walk the use-def chains for @var{arg}.
-@item Call @code{FN (@var{arg}, @var{phi}, @var{data})}.
-@end enumerate
-
-Note how the first argument to @var{fn} is no longer the original
-variable @var{var}, but the PHI argument currently being examined.
-If @var{fn} wants to get at @var{var}, it should call
-@code{PHI_RESULT} (@var{phi}).
-@end deftypefn
-
@subsection Walking the dominator tree
@deftypefn {Tree SSA function} void walk_dominator_tree (@var{walk_data}, @var{bb})
diff --git a/gcc/dojump.c b/gcc/dojump.c
index 3f04eacabb7..ee12d761eee 100644
--- a/gcc/dojump.c
+++ b/gcc/dojump.c
@@ -311,32 +311,66 @@ do_jump_1 (enum tree_code code, tree op0, tree op1,
break;
case TRUTH_ANDIF_EXPR:
- if (if_false_label == NULL_RTX)
- {
- drop_through_label = gen_label_rtx ();
- do_jump (op0, drop_through_label, NULL_RTX, prob);
- do_jump (op1, NULL_RTX, if_true_label, prob);
- }
- else
- {
- do_jump (op0, if_false_label, NULL_RTX, prob);
- do_jump (op1, if_false_label, if_true_label, prob);
- }
- break;
+ {
+ /* Spread the probability that the expression is false evenly between
+ the two conditions. So the first condition is false half the total
+ probability of being false. The second condition is false the other
+ half of the total probability of being false, so its jump has a false
+ probability of half the total, relative to the probability we
+ reached it (i.e. the first condition was true). */
+ int op0_prob = -1;
+ int op1_prob = -1;
+ if (prob != -1)
+ {
+ int false_prob = inv (prob);
+ int op0_false_prob = false_prob / 2;
+ int op1_false_prob = GCOV_COMPUTE_SCALE ((false_prob / 2),
+ inv (op0_false_prob));
+ /* Get the probability that each jump below is true. */
+ op0_prob = inv (op0_false_prob);
+ op1_prob = inv (op1_false_prob);
+ }
+ if (if_false_label == NULL_RTX)
+ {
+ drop_through_label = gen_label_rtx ();
+ do_jump (op0, drop_through_label, NULL_RTX, op0_prob);
+ do_jump (op1, NULL_RTX, if_true_label, op1_prob);
+ }
+ else
+ {
+ do_jump (op0, if_false_label, NULL_RTX, op0_prob);
+ do_jump (op1, if_false_label, if_true_label, op1_prob);
+ }
+ break;
+ }
case TRUTH_ORIF_EXPR:
- if (if_true_label == NULL_RTX)
- {
- drop_through_label = gen_label_rtx ();
- do_jump (op0, NULL_RTX, drop_through_label, prob);
- do_jump (op1, if_false_label, NULL_RTX, prob);
- }
- else
- {
- do_jump (op0, NULL_RTX, if_true_label, prob);
- do_jump (op1, if_false_label, if_true_label, prob);
- }
- break;
+ {
+ /* Spread the probability evenly between the two conditions. So
+ the first condition has half the total probability of being true.
+ The second condition has the other half of the total probability,
+ so its jump has a probability of half the total, relative to
+ the probability we reached it (i.e. the first condition was false). */
+ int op0_prob = -1;
+ int op1_prob = -1;
+ if (prob != -1)
+ {
+ op0_prob = prob / 2;
+ op1_prob = GCOV_COMPUTE_SCALE ((prob / 2), inv (op0_prob));
+ }
+ if (if_true_label == NULL_RTX)
+ {
+ drop_through_label = gen_label_rtx ();
+ do_jump (op0, NULL_RTX, drop_through_label, op0_prob);
+ do_jump (op1, if_false_label, NULL_RTX, op1_prob);
+ }
+ else
+ {
+ do_jump (op0, NULL_RTX, if_true_label, op0_prob);
+ do_jump (op1, if_false_label, if_true_label, op1_prob);
+ }
+ break;
+ }
default:
gcc_unreachable ();
diff --git a/gcc/domwalk.c b/gcc/domwalk.c
index bffa4aa4851..4816b4c8d85 100644
--- a/gcc/domwalk.c
+++ b/gcc/domwalk.c
@@ -154,7 +154,7 @@ dom_walker::walk (basic_block bb)
int sp = 0;
int *postorder, postorder_num;
- if (dom_direction_ == CDI_DOMINATORS)
+ if (m_dom_direction == CDI_DOMINATORS)
{
postorder = XNEWVEC (int, n_basic_blocks);
postorder_num = inverted_post_order_compute (postorder);
@@ -181,10 +181,10 @@ dom_walker::walk (basic_block bb)
worklist[sp++] = NULL;
int saved_sp = sp;
- for (dest = first_dom_son (dom_direction_, bb);
- dest; dest = next_dom_son (dom_direction_, dest))
+ for (dest = first_dom_son (m_dom_direction, bb);
+ dest; dest = next_dom_son (m_dom_direction, dest))
worklist[sp++] = dest;
- if (dom_direction_ == CDI_DOMINATORS)
+ if (m_dom_direction == CDI_DOMINATORS)
switch (sp - saved_sp)
{
case 0:
@@ -210,7 +210,7 @@ dom_walker::walk (basic_block bb)
else
break;
}
- if (dom_direction_ == CDI_DOMINATORS)
+ if (m_dom_direction == CDI_DOMINATORS)
{
free (bb_postorder);
bb_postorder = NULL;
diff --git a/gcc/domwalk.h b/gcc/domwalk.h
index b33d70eda23..43c15740f7a 100644
--- a/gcc/domwalk.h
+++ b/gcc/domwalk.h
@@ -30,7 +30,7 @@ along with GCC; see the file COPYING3. If not see
class dom_walker
{
public:
- dom_walker (cdi_direction direction) : dom_direction_ (direction) {}
+ dom_walker (cdi_direction direction) : m_dom_direction (direction) {}
/* Walk the dominator tree. */
void walk (basic_block);
@@ -46,7 +46,7 @@ private:
if it is set to CDI_DOMINATORS, then we walk the dominator tree,
if it is set to CDI_POST_DOMINATORS, then we walk the post
dominator tree. */
- const ENUM_BITFIELD (cdi_direction) dom_direction_ : 2;
+ const ENUM_BITFIELD (cdi_direction) m_dom_direction : 2;
};
#endif
diff --git a/gcc/double-int.c b/gcc/double-int.c
index 7eaad659279..3803a63e3a9 100644
--- a/gcc/double-int.c
+++ b/gcc/double-int.c
@@ -20,7 +20,7 @@ along with GCC; see the file COPYING3. If not see
#include "config.h"
#include "system.h"
#include "coretypes.h"
-#include "tm.h" /* For SHIFT_COUNT_TRUNCATED. */
+#include "tm.h" /* For BITS_PER_UNIT and *_BIG_ENDIAN. */
#include "tree.h"
static int add_double_with_sign (unsigned HOST_WIDE_INT, HOST_WIDE_INT,
@@ -237,9 +237,6 @@ rshift_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
? -((unsigned HOST_WIDE_INT) h1 >> (HOST_BITS_PER_WIDE_INT - 1))
: 0);
- if (SHIFT_COUNT_TRUNCATED)
- count %= prec;
-
if (count >= HOST_BITS_PER_DOUBLE_INT)
{
/* Shifting by the host word size is undefined according to the
@@ -295,9 +292,6 @@ lshift_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
{
unsigned HOST_WIDE_INT signmask;
- if (SHIFT_COUNT_TRUNCATED)
- count %= prec;
-
if (count >= HOST_BITS_PER_DOUBLE_INT)
{
/* Shifting by the host word size is undefined according to the
@@ -1555,11 +1549,11 @@ mpz_get_double_int (const_tree type, mpz_t val, bool wrap)
for representing the value. The code to calculate count is
extracted from the GMP manual, section "Integer Import and Export":
http://gmplib.org/manual/Integer-Import-and-Export.html */
- numb = 8*sizeof(HOST_WIDE_INT);
+ numb = 8 * sizeof (HOST_WIDE_INT);
count = (mpz_sizeinbase (val, 2) + numb-1) / numb;
if (count < 2)
count = 2;
- vp = (unsigned HOST_WIDE_INT *) alloca (count * sizeof(HOST_WIDE_INT));
+ vp = (unsigned HOST_WIDE_INT *) alloca (count * sizeof (HOST_WIDE_INT));
vp[0] = 0;
vp[1] = 0;
diff --git a/gcc/dse.c b/gcc/dse.c
index d0e99db3dbd..b602caa291f 100644
--- a/gcc/dse.c
+++ b/gcc/dse.c
@@ -46,7 +46,8 @@ along with GCC; see the file COPYING3. If not see
#include "dbgcnt.h"
#include "target.h"
#include "params.h"
-#include "tree-ssa.h" /* for may_be_aliased */
+#include "gimple.h"
+#include "gimple-ssa.h"
/* This file contains three techniques for performing Dead Store
Elimination (dse).
@@ -2916,8 +2917,8 @@ dse_step2_nospill (void)
if (group == clear_alias_group)
continue;
- memset (group->offset_map_n, 0, sizeof(int) * group->offset_map_size_n);
- memset (group->offset_map_p, 0, sizeof(int) * group->offset_map_size_p);
+ memset (group->offset_map_n, 0, sizeof (int) * group->offset_map_size_n);
+ memset (group->offset_map_p, 0, sizeof (int) * group->offset_map_size_p);
bitmap_clear (group->group_kill);
EXECUTE_IF_SET_IN_BITMAP (group->store2_n, 0, j, bi)
@@ -3749,8 +3750,8 @@ const pass_data pass_data_rtl_dse1 =
class pass_rtl_dse1 : public rtl_opt_pass
{
public:
- pass_rtl_dse1(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_rtl_dse1, ctxt)
+ pass_rtl_dse1 (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_rtl_dse1, ctxt)
{}
/* opt_pass methods: */
@@ -3787,8 +3788,8 @@ const pass_data pass_data_rtl_dse2 =
class pass_rtl_dse2 : public rtl_opt_pass
{
public:
- pass_rtl_dse2(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_rtl_dse2, ctxt)
+ pass_rtl_dse2 (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_rtl_dse2, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/dumpfile.c b/gcc/dumpfile.c
index dc87ab35e8c..e80f9bf37e2 100644
--- a/gcc/dumpfile.c
+++ b/gcc/dumpfile.c
@@ -22,8 +22,9 @@ along with GCC; see the file COPYING3. If not see
#include "coretypes.h"
#include "diagnostic-core.h"
#include "dumpfile.h"
-#include "gimple-pretty-print.h"
#include "tree.h"
+#include "gimple-pretty-print.h"
+#include "context.h"
/* If non-NULL, return one past-the-end of the matching SUBPART of
the WHOLE string. */
@@ -34,7 +35,6 @@ static int pflags; /* current dump_flags */
static int alt_flags; /* current opt_info flags */
static void dump_loc (int, FILE *, source_location);
-static int dump_phase_enabled_p (int);
static FILE *dump_open_alternate_stream (struct dump_file_info *);
/* These are currently used for communicating between passes.
@@ -74,11 +74,6 @@ static struct dump_file_info dump_files[TDI_end] =
0, 0, 0, 0, 0},
};
-/* Dynamically registered tree dump files and switches. */
-static struct dump_file_info *extra_dump_files;
-static size_t extra_dump_files_in_use;
-static size_t extra_dump_files_alloced;
-
/* Define a name->number mapping for a dump flag value. */
struct dump_option_value_info
{
@@ -141,33 +136,41 @@ static const struct dump_option_value_info optgroup_options[] =
{NULL, 0}
};
+gcc::dump_manager::dump_manager ():
+ m_next_dump (FIRST_AUTO_NUMBERED_DUMP),
+ m_extra_dump_files (NULL),
+ m_extra_dump_files_in_use (0),
+ m_extra_dump_files_alloced (0)
+{
+}
+
unsigned int
+gcc::dump_manager::
dump_register (const char *suffix, const char *swtch, const char *glob,
int flags, int optgroup_flags)
{
- static int next_dump = FIRST_AUTO_NUMBERED_DUMP;
- int num = next_dump++;
+ int num = m_next_dump++;
- size_t count = extra_dump_files_in_use++;
+ size_t count = m_extra_dump_files_in_use++;
- if (count >= extra_dump_files_alloced)
+ if (count >= m_extra_dump_files_alloced)
{
- if (extra_dump_files_alloced == 0)
- extra_dump_files_alloced = 32;
+ if (m_extra_dump_files_alloced == 0)
+ m_extra_dump_files_alloced = 32;
else
- extra_dump_files_alloced *= 2;
- extra_dump_files = XRESIZEVEC (struct dump_file_info,
- extra_dump_files,
- extra_dump_files_alloced);
+ m_extra_dump_files_alloced *= 2;
+ m_extra_dump_files = XRESIZEVEC (struct dump_file_info,
+ m_extra_dump_files,
+ m_extra_dump_files_alloced);
}
- memset (&extra_dump_files[count], 0, sizeof (struct dump_file_info));
- extra_dump_files[count].suffix = suffix;
- extra_dump_files[count].swtch = swtch;
- extra_dump_files[count].glob = glob;
- extra_dump_files[count].pflags = flags;
- extra_dump_files[count].optgroup_flags = optgroup_flags;
- extra_dump_files[count].num = num;
+ memset (&m_extra_dump_files[count], 0, sizeof (struct dump_file_info));
+ m_extra_dump_files[count].suffix = suffix;
+ m_extra_dump_files[count].swtch = swtch;
+ m_extra_dump_files[count].glob = glob;
+ m_extra_dump_files[count].pflags = flags;
+ m_extra_dump_files[count].optgroup_flags = optgroup_flags;
+ m_extra_dump_files[count].num = num;
return count + TDI_end;
}
@@ -176,14 +179,15 @@ dump_register (const char *suffix, const char *swtch, const char *glob,
/* Return the dump_file_info for the given phase. */
struct dump_file_info *
-get_dump_file_info (int phase)
+gcc::dump_manager::
+get_dump_file_info (int phase) const
{
if (phase < TDI_end)
return &dump_files[phase];
- else if ((size_t) (phase - TDI_end) >= extra_dump_files_in_use)
+ else if ((size_t) (phase - TDI_end) >= m_extra_dump_files_in_use)
return NULL;
else
- return extra_dump_files + (phase - TDI_end);
+ return m_extra_dump_files + (phase - TDI_end);
}
@@ -191,7 +195,8 @@ get_dump_file_info (int phase)
If the dump is not enabled, returns NULL. */
char *
-get_dump_file_name (int phase)
+gcc::dump_manager::
+get_dump_file_name (int phase) const
{
char dump_id[10];
struct dump_file_info *dfi;
@@ -240,10 +245,10 @@ dump_open_alternate_stream (struct dump_file_info *dfi)
if (dfi->alt_stream)
return dfi->alt_stream;
- stream = strcmp("stderr", dfi->alt_filename) == 0
+ stream = strcmp ("stderr", dfi->alt_filename) == 0
? stderr
- : strcmp("stdout", dfi->alt_filename) == 0
- ? stdout
+ : strcmp ("stdout", dfi->alt_filename) == 0
+ ? stdout
: fopen (dfi->alt_filename, dfi->alt_state < 0 ? "w" : "a");
if (!stream)
@@ -391,6 +396,7 @@ dump_printf_loc (int dump_kind, source_location loc, const char *format, ...)
-fopt-info stream. */
int
+gcc::dump_manager::
dump_start (int phase, int *flag_ptr)
{
int count = 0;
@@ -404,10 +410,10 @@ dump_start (int phase, int *flag_ptr)
name = get_dump_file_name (phase);
if (name)
{
- stream = strcmp("stderr", name) == 0
+ stream = strcmp ("stderr", name) == 0
? stderr
- : strcmp("stdout", name) == 0
- ? stdout
+ : strcmp ("stdout", name) == 0
+ ? stdout
: fopen (name, dfi->pstate < 0 ? "w" : "a");
if (!stream)
error ("could not open dump file %qs: %m", name);
@@ -443,6 +449,7 @@ dump_start (int phase, int *flag_ptr)
reset the globals DUMP_FILE, ALT_DUMP_FILE, and DUMP_FLAGS. */
void
+gcc::dump_manager::
dump_finish (int phase)
{
struct dump_file_info *dfi;
@@ -451,12 +458,12 @@ dump_finish (int phase)
return;
dfi = get_dump_file_info (phase);
if (dfi->pstream && (!dfi->pfilename
- || (strcmp("stderr", dfi->pfilename) != 0
- && strcmp("stdout", dfi->pfilename) != 0)))
+ || (strcmp ("stderr", dfi->pfilename) != 0
+ && strcmp ("stdout", dfi->pfilename) != 0)))
fclose (dfi->pstream);
- if (dfi->alt_stream && strcmp("stderr", dfi->alt_filename) != 0
- && strcmp("stdout", dfi->alt_filename) != 0)
+ if (dfi->alt_stream && strcmp ("stderr", dfi->alt_filename) != 0
+ && strcmp ("stdout", dfi->alt_filename) != 0)
fclose (dfi->alt_stream);
dfi->alt_stream = NULL;
@@ -476,6 +483,13 @@ dump_finish (int phase)
FILE *
dump_begin (int phase, int *flag_ptr)
{
+ return g->get_dumps ()->dump_begin (phase, flag_ptr);
+}
+
+FILE *
+gcc::dump_manager::
+dump_begin (int phase, int *flag_ptr)
+{
char *name;
struct dump_file_info *dfi;
FILE *stream;
@@ -488,10 +502,10 @@ dump_begin (int phase, int *flag_ptr)
return NULL;
dfi = get_dump_file_info (phase);
- stream = strcmp("stderr", name) == 0
+ stream = strcmp ("stderr", name) == 0
? stderr
- : strcmp("stdout", name) == 0
- ? stdout
+ : strcmp ("stdout", name) == 0
+ ? stdout
: fopen (name, dfi->pstate < 0 ? "w" : "a");
if (!stream)
@@ -512,8 +526,9 @@ dump_begin (int phase, int *flag_ptr)
If PHASE is TDI_tree_all, return nonzero if any dump is enabled for
any phase. */
-static int
-dump_phase_enabled_p (int phase)
+int
+gcc::dump_manager::
+dump_phase_enabled_p (int phase) const
{
if (phase == TDI_tree_all)
{
@@ -521,8 +536,8 @@ dump_phase_enabled_p (int phase)
for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
if (dump_files[i].pstate || dump_files[i].alt_state)
return 1;
- for (i = 0; i < extra_dump_files_in_use; i++)
- if (extra_dump_files[i].pstate || extra_dump_files[i].alt_state)
+ for (i = 0; i < m_extra_dump_files_in_use; i++)
+ if (m_extra_dump_files[i].pstate || m_extra_dump_files[i].alt_state)
return 1;
return 0;
}
@@ -536,7 +551,8 @@ dump_phase_enabled_p (int phase)
/* Returns nonzero if tree dump PHASE has been initialized. */
int
-dump_initialized_p (int phase)
+gcc::dump_manager::
+dump_initialized_p (int phase) const
{
struct dump_file_info *dfi = get_dump_file_info (phase);
return dfi->pstate > 0 || dfi->alt_state > 0;
@@ -547,6 +563,13 @@ dump_initialized_p (int phase)
const char *
dump_flag_name (int phase)
{
+ return g->get_dumps ()->dump_flag_name (phase);
+}
+
+const char *
+gcc::dump_manager::
+dump_flag_name (int phase) const
+{
struct dump_file_info *dfi = get_dump_file_info (phase);
return dfi->swtch;
}
@@ -564,7 +587,8 @@ dump_end (int phase ATTRIBUTE_UNUSED, FILE *stream)
/* Enable all tree dumps with FLAGS on FILENAME. Return number of
enabled tree dumps. */
-static int
+int
+gcc::dump_manager::
dump_enable_all (int flags, const char *filename)
{
int ir_dump_type = (flags & (TDF_TREE | TDF_RTL | TDF_IPA));
@@ -592,21 +616,21 @@ dump_enable_all (int flags, const char *filename)
}
}
- for (i = 0; i < extra_dump_files_in_use; i++)
+ for (i = 0; i < m_extra_dump_files_in_use; i++)
{
- if ((extra_dump_files[i].pflags & ir_dump_type))
+ if ((m_extra_dump_files[i].pflags & ir_dump_type))
{
- const char *old_filename = extra_dump_files[i].pfilename;
- extra_dump_files[i].pstate = -1;
- extra_dump_files[i].pflags |= flags;
+ const char *old_filename = m_extra_dump_files[i].pfilename;
+ m_extra_dump_files[i].pstate = -1;
+ m_extra_dump_files[i].pflags |= flags;
n++;
/* Override the existing filename. */
if (filename)
{
- extra_dump_files[i].pfilename = xstrdup (filename);
+ m_extra_dump_files[i].pfilename = xstrdup (filename);
/* Since it is a command-line provided file, which is
common to all the phases, use it in append mode. */
- extra_dump_files[i].pstate = 1;
+ m_extra_dump_files[i].pstate = 1;
}
if (old_filename && filename != old_filename)
free (CONST_CAST (char *, old_filename));
@@ -620,7 +644,8 @@ dump_enable_all (int flags, const char *filename)
Enable dumps with FLAGS on FILENAME. Return the number of enabled
dumps. */
-static int
+int
+gcc::dump_manager::
opt_info_enable_passes (int optgroup_flags, int flags, const char *filename)
{
int n = 0;
@@ -644,19 +669,19 @@ opt_info_enable_passes (int optgroup_flags, int flags, const char *filename)
}
}
- for (i = 0; i < extra_dump_files_in_use; i++)
+ for (i = 0; i < m_extra_dump_files_in_use; i++)
{
- if ((extra_dump_files[i].optgroup_flags & optgroup_flags))
+ if ((m_extra_dump_files[i].optgroup_flags & optgroup_flags))
{
- const char *old_filename = extra_dump_files[i].alt_filename;
+ const char *old_filename = m_extra_dump_files[i].alt_filename;
/* Since this file is shared among different passes, it
should be opened in append mode. */
- extra_dump_files[i].alt_state = 1;
- extra_dump_files[i].alt_flags |= flags;
+ m_extra_dump_files[i].alt_state = 1;
+ m_extra_dump_files[i].alt_flags |= flags;
n++;
/* Override the existing filename. */
if (filename)
- extra_dump_files[i].alt_filename = xstrdup (filename);
+ m_extra_dump_files[i].alt_filename = xstrdup (filename);
if (old_filename && filename != old_filename)
free (CONST_CAST (char *, old_filename));
}
@@ -668,7 +693,8 @@ opt_info_enable_passes (int optgroup_flags, int flags, const char *filename)
/* Parse ARG as a dump switch. Return nonzero if it is, and store the
relevant details in the dump_files array. */
-static int
+int
+gcc::dump_manager::
dump_switch_p_1 (const char *arg, struct dump_file_info *dfi, bool doglob)
{
const char *option_value;
@@ -743,6 +769,7 @@ dump_switch_p_1 (const char *arg, struct dump_file_info *dfi, bool doglob)
}
int
+gcc::dump_manager::
dump_switch_p (const char *arg)
{
size_t i;
@@ -756,12 +783,12 @@ dump_switch_p (const char *arg)
for (i = TDI_none + 1; i != TDI_end; i++)
any |= dump_switch_p_1 (arg, &dump_files[i], true);
- for (i = 0; i < extra_dump_files_in_use; i++)
- any |= dump_switch_p_1 (arg, &extra_dump_files[i], false);
+ for (i = 0; i < m_extra_dump_files_in_use; i++)
+ any |= dump_switch_p_1 (arg, &m_extra_dump_files[i], false);
if (!any)
- for (i = 0; i < extra_dump_files_in_use; i++)
- any |= dump_switch_p_1 (arg, &extra_dump_files[i], true);
+ for (i = 0; i < m_extra_dump_files_in_use; i++)
+ any |= dump_switch_p_1 (arg, &m_extra_dump_files[i], true);
return any;
@@ -853,6 +880,7 @@ opt_info_switch_p (const char *arg)
int optgroup_flags;
char *filename;
static char *file_seen = NULL;
+ gcc::dump_manager *dumps = g->get_dumps ();
if (!opt_info_switch_p_1 (arg, &flags, &optgroup_flags, &filename))
return 0;
@@ -874,7 +902,7 @@ opt_info_switch_p (const char *arg)
if (!optgroup_flags)
optgroup_flags = OPTGROUP_ALL;
- return opt_info_enable_passes (optgroup_flags, flags, filename);
+ return dumps->opt_info_enable_passes (optgroup_flags, flags, filename);
}
/* Print basic block on the dump streams. */
@@ -902,5 +930,8 @@ print_combine_total_stats (void)
bool
enable_rtl_dump_file (void)
{
- return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS, NULL) > 0;
+ gcc::dump_manager *dumps = g->get_dumps ();
+ int num_enabled =
+ dumps->dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS, NULL);
+ return num_enabled > 0;
}
diff --git a/gcc/dumpfile.h b/gcc/dumpfile.h
index ddc770ab947..a6b377eaf8c 100644
--- a/gcc/dumpfile.h
+++ b/gcc/dumpfile.h
@@ -121,13 +121,8 @@ struct dump_file_info
};
/* In dumpfile.c */
-extern char *get_dump_file_name (int);
-extern int dump_initialized_p (int);
extern FILE *dump_begin (int, int *);
extern void dump_end (int, FILE *);
-extern int dump_start (int, int *);
-extern void dump_finish (int);
-extern int dump_switch_p (const char *);
extern int opt_info_switch_p (const char *);
extern const char *dump_flag_name (int);
extern void dump_printf (int, const char *, ...) ATTRIBUTE_PRINTF_2;
@@ -139,8 +134,6 @@ extern void dump_generic_expr (int, int, tree);
extern void dump_gimple_stmt_loc (int, source_location, int, gimple, int);
extern void dump_gimple_stmt (int, int, gimple, int);
extern void print_combine_total_stats (void);
-extern unsigned int dump_register (const char *, const char *, const char *,
- int, int);
extern bool enable_rtl_dump_file (void);
/* In tree-dump.c */
@@ -157,9 +150,6 @@ extern FILE *alt_dump_file;
extern int dump_flags;
extern const char *dump_file_name;
-/* Return the dump_file_info for the given phase. */
-extern struct dump_file_info *get_dump_file_info (int);
-
/* Return true if any of the dumps is enabled, false otherwise. */
static inline bool
dump_enabled_p (void)
@@ -167,4 +157,84 @@ dump_enabled_p (void)
return (dump_file || alt_dump_file);
}
+namespace gcc {
+
+class dump_manager
+{
+public:
+
+ dump_manager ();
+
+ unsigned int
+ dump_register (const char *suffix, const char *swtch, const char *glob,
+ int flags, int optgroup_flags);
+
+ /* Return the dump_file_info for the given phase. */
+ struct dump_file_info *
+ get_dump_file_info (int phase) 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) const;
+
+ int
+ 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, int *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, int *flag_ptr);
+
+ /* 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;
+
+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 (int flags, const char *filename);
+
+ int
+ opt_info_enable_passes (int optgroup_flags, int flags, const char *filename);
+
+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;
+
+ /* 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/gcc/dwarf2asm.c b/gcc/dwarf2asm.c
index 37dc8959bdc..69907f9fbf2 100644
--- a/gcc/dwarf2asm.c
+++ b/gcc/dwarf2asm.c
@@ -315,7 +315,7 @@ dw2_asm_output_nstring (const char *str, size_t orig_len,
int c = str[i];
if (c == '\"' || c == '\\')
fputc ('\\', asm_out_file);
- if (ISPRINT(c))
+ if (ISPRINT (c))
fputc (c, asm_out_file);
else
fprintf (asm_out_file, "\\%o", c);
diff --git a/gcc/dwarf2cfi.c b/gcc/dwarf2cfi.c
index 12256bcec39..e0f85edc61b 100644
--- a/gcc/dwarf2cfi.c
+++ b/gcc/dwarf2cfi.c
@@ -24,6 +24,7 @@ along with GCC; see the file COPYING3. If not see
#include "version.h"
#include "flags.h"
#include "rtl.h"
+#include "tree.h"
#include "function.h"
#include "basic-block.h"
#include "dwarf2.h"
@@ -2841,14 +2842,14 @@ create_cie_data (void)
dw_stack_pointer_regnum = DWARF_FRAME_REGNUM (STACK_POINTER_REGNUM);
dw_frame_pointer_regnum = DWARF_FRAME_REGNUM (HARD_FRAME_POINTER_REGNUM);
- memset (&cie_trace, 0, sizeof(cie_trace));
+ memset (&cie_trace, 0, sizeof (cie_trace));
cur_trace = &cie_trace;
add_cfi_vec = &cie_cfi_vec;
cie_cfi_row = cur_row = new_cfi_row ();
/* On entry, the Canonical Frame Address is at SP. */
- memset(&loc, 0, sizeof (loc));
+ memset (&loc, 0, sizeof (loc));
loc.reg = dw_stack_pointer_regnum;
loc.offset = INCOMING_FRAME_SP_OFFSET;
def_cfa_1 (&loc);
@@ -3268,7 +3269,7 @@ dump_cfi_row (FILE *f, dw_cfi_row *row)
if (!cfi)
{
dw_cfa_location dummy;
- memset(&dummy, 0, sizeof(dummy));
+ memset (&dummy, 0, sizeof (dummy));
dummy.reg = INVALID_REGNUM;
cfi = def_cfa_0 (&dummy, &row->cfa);
}
@@ -3391,8 +3392,8 @@ const pass_data pass_data_dwarf2_frame =
class pass_dwarf2_frame : public rtl_opt_pass
{
public:
- pass_dwarf2_frame(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_dwarf2_frame, ctxt)
+ pass_dwarf2_frame (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_dwarf2_frame, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 95049e4d184..5ef7bd2034d 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -92,6 +92,8 @@ along with GCC; see the file COPYING3. If not see
#include "lra.h"
#include "dumpfile.h"
#include "opts.h"
+#include "tree-dfa.h"
+#include "gdb/gdb-index.h"
static void dwarf2out_source_line (unsigned int, const char *, int, bool);
static rtx last_var_location_insn;
@@ -3322,10 +3324,14 @@ new_addr_loc_descr (rtx addr, enum dtprel_bool dtprel)
#define DEBUG_DWO_LOC_SECTION ".debug_loc.dwo"
#endif
#ifndef DEBUG_PUBNAMES_SECTION
-#define DEBUG_PUBNAMES_SECTION ".debug_pubnames"
+#define DEBUG_PUBNAMES_SECTION \
+ ((debug_generate_pub_sections == 2) \
+ ? ".debug_gnu_pubnames" : ".debug_pubnames")
#endif
#ifndef DEBUG_PUBTYPES_SECTION
-#define DEBUG_PUBTYPES_SECTION ".debug_pubtypes"
+#define DEBUG_PUBTYPES_SECTION \
+ ((debug_generate_pub_sections == 2) \
+ ? ".debug_gnu_pubtypes" : ".debug_pubtypes")
#endif
#define DEBUG_NORM_STR_OFFSETS_SECTION ".debug_str_offsets"
#define DEBUG_DWO_STR_OFFSETS_SECTION ".debug_str_offsets.dwo"
@@ -4245,7 +4251,7 @@ index_addr_table_entry (void **h, void *v)
if (node->refcount == 0)
return 1;
- gcc_assert(node->index == NO_INDEX_ASSIGNED);
+ gcc_assert (node->index == NO_INDEX_ASSIGNED);
node->index = *index;
*index += 1;
@@ -4568,6 +4574,16 @@ is_cxx (void)
return lang == DW_LANG_C_plus_plus || lang == DW_LANG_ObjC_plus_plus;
}
+/* Return TRUE if the language is Java. */
+
+static inline bool
+is_java (void)
+{
+ unsigned int lang = get_AT_unsigned (comp_unit_die (), DW_AT_language);
+
+ return lang == DW_LANG_Java;
+}
+
/* Return TRUE if the language is Fortran. */
static inline bool
@@ -6163,7 +6179,7 @@ generate_type_signature (dw_die_ref die, comdat_type_node *type_node)
context, if any. This is stored in the type unit DIE for link-time
ODR (one-definition rule) checking. */
- if (is_cxx() && name != NULL)
+ if (is_cxx () && name != NULL)
{
md5_init_ctx (&ctx);
@@ -6249,7 +6265,7 @@ same_dw_val_p (const dw_val_node *v1, const dw_val_node *v2, int *mark)
case dw_val_class_flag:
return v1->v.val_flag == v2->v.val_flag;
case dw_val_class_str:
- return !strcmp(v1->v.val_str->str, v2->v.val_str->str);
+ return !strcmp (v1->v.val_str->str, v2->v.val_str->str);
case dw_val_class_addr:
r1 = v1->v.val_addr;
@@ -6788,7 +6804,7 @@ contains_subprogram_definition (dw_die_ref die)
if (die->die_tag == DW_TAG_subprogram && ! is_declaration_die (die))
return 1;
- FOR_EACH_CHILD (die, c, if (contains_subprogram_definition(c)) return 1);
+ FOR_EACH_CHILD (die, c, if (contains_subprogram_definition (c)) return 1);
return 0;
}
@@ -6860,7 +6876,7 @@ clone_tree (dw_die_ref die)
dw_die_ref c;
dw_die_ref clone = clone_die (die);
- FOR_EACH_CHILD (die, c, add_child_die (clone, clone_tree(c)));
+ FOR_EACH_CHILD (die, c, add_child_die (clone, clone_tree (c)));
return clone;
}
@@ -7052,7 +7068,7 @@ copy_declaration_context (dw_die_ref unit, dw_die_ref die)
add_dwarf_attr (die, a);
}
- FOR_EACH_CHILD (decl, c, add_child_die (die, clone_tree(c)));
+ FOR_EACH_CHILD (decl, c, add_child_die (die, clone_tree (c)));
}
if (decl->die_parent != NULL
@@ -7959,6 +7975,12 @@ unmark_all_dies (dw_die_ref die)
static bool
include_pubname_in_output (vec<pubname_entry, va_gc> *table, pubname_entry *p)
{
+ /* By limiting gnu pubnames to definitions only, gold can generate a
+ gdb index without entries for declarations, which don't include
+ enough information to be useful. */
+ if (debug_generate_pub_sections == 2 && is_declaration_die (p->die))
+ return false;
+
if (table == pubname_table)
{
/* Enumerator names are part of the pubname table, but the
@@ -7988,11 +8010,12 @@ size_of_pubnames (vec<pubname_entry, va_gc> *names)
unsigned long size;
unsigned i;
pubname_ref p;
+ int space_for_flags = (debug_generate_pub_sections == 2) ? 1 : 0;
size = DWARF_PUBNAMES_HEADER_SIZE;
FOR_EACH_VEC_ELT (*names, i, p)
if (include_pubname_in_output (names, p))
- size += strlen (p->name) + DWARF_OFFSET_SIZE + 1;
+ size += strlen (p->name) + DWARF_OFFSET_SIZE + 1 + space_for_flags;
size += DWARF_OFFSET_SIZE;
return size;
@@ -9145,6 +9168,76 @@ add_pubtype (tree decl, dw_die_ref die)
}
}
+/* Output a single entry in the pubnames table. */
+
+static void
+output_pubname (dw_offset die_offset, pubname_entry *entry)
+{
+ dw_die_ref die = entry->die;
+ int is_static = get_AT_flag (die, DW_AT_external) ? 0 : 1;
+
+ dw2_asm_output_data (DWARF_OFFSET_SIZE, die_offset, "DIE offset");
+
+ if (debug_generate_pub_sections == 2)
+ {
+ /* This logic follows gdb's method for determining the value of the flag
+ byte. */
+ uint32_t flags = GDB_INDEX_SYMBOL_KIND_NONE;
+ switch (die->die_tag)
+ {
+ case DW_TAG_typedef:
+ case DW_TAG_base_type:
+ case DW_TAG_subrange_type:
+ GDB_INDEX_SYMBOL_KIND_SET_VALUE(flags, GDB_INDEX_SYMBOL_KIND_TYPE);
+ GDB_INDEX_SYMBOL_STATIC_SET_VALUE(flags, 1);
+ break;
+ case DW_TAG_enumerator:
+ GDB_INDEX_SYMBOL_KIND_SET_VALUE(flags,
+ GDB_INDEX_SYMBOL_KIND_VARIABLE);
+ if (!is_cxx () && !is_java ())
+ GDB_INDEX_SYMBOL_STATIC_SET_VALUE(flags, 1);
+ break;
+ case DW_TAG_subprogram:
+ GDB_INDEX_SYMBOL_KIND_SET_VALUE(flags,
+ GDB_INDEX_SYMBOL_KIND_FUNCTION);
+ if (!is_ada ())
+ GDB_INDEX_SYMBOL_STATIC_SET_VALUE(flags, is_static);
+ break;
+ case DW_TAG_constant:
+ GDB_INDEX_SYMBOL_KIND_SET_VALUE(flags,
+ GDB_INDEX_SYMBOL_KIND_VARIABLE);
+ GDB_INDEX_SYMBOL_STATIC_SET_VALUE(flags, is_static);
+ break;
+ case DW_TAG_variable:
+ GDB_INDEX_SYMBOL_KIND_SET_VALUE(flags,
+ GDB_INDEX_SYMBOL_KIND_VARIABLE);
+ GDB_INDEX_SYMBOL_STATIC_SET_VALUE(flags, is_static);
+ break;
+ case DW_TAG_namespace:
+ case DW_TAG_imported_declaration:
+ GDB_INDEX_SYMBOL_KIND_SET_VALUE(flags, GDB_INDEX_SYMBOL_KIND_TYPE);
+ break;
+ case DW_TAG_class_type:
+ case DW_TAG_interface_type:
+ case DW_TAG_structure_type:
+ case DW_TAG_union_type:
+ case DW_TAG_enumeration_type:
+ GDB_INDEX_SYMBOL_KIND_SET_VALUE(flags, GDB_INDEX_SYMBOL_KIND_TYPE);
+ if (!is_cxx () && !is_java ())
+ GDB_INDEX_SYMBOL_STATIC_SET_VALUE(flags, 1);
+ break;
+ default:
+ /* An unusual tag. Leave the flag-byte empty. */
+ break;
+ }
+ dw2_asm_output_data (1, flags >> GDB_INDEX_CU_BITSIZE,
+ "GDB-index flags");
+ }
+
+ dw2_asm_output_nstring (entry->name, -1, "external name");
+}
+
+
/* Output the public names table used to speed up access to externally
visible names; or the public types table used to find type definitions. */
@@ -9155,23 +9248,14 @@ output_pubnames (vec<pubname_entry, va_gc> *names)
unsigned long pubnames_length = size_of_pubnames (names);
pubname_ref pub;
- if (!want_pubnames () || !info_section_emitted)
- return;
- if (names == pubname_table)
- switch_to_section (debug_pubnames_section);
- else
- switch_to_section (debug_pubtypes_section);
if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
dw2_asm_output_data (4, 0xffffffff,
"Initial length escape value indicating 64-bit DWARF extension");
- if (names == pubname_table)
- dw2_asm_output_data (DWARF_OFFSET_SIZE, pubnames_length,
- "Length of Public Names Info");
- else
- dw2_asm_output_data (DWARF_OFFSET_SIZE, pubnames_length,
- "Length of Public Type Names Info");
- /* Version number for pubnames/pubtypes is still 2, even in DWARF3. */
+ dw2_asm_output_data (DWARF_OFFSET_SIZE, pubnames_length, "Pub Info Length");
+
+ /* Version number for pubnames/pubtypes is independent of dwarf version. */
dw2_asm_output_data (2, 2, "DWARF Version");
+
if (dwarf_split_debug_info)
dw2_asm_output_offset (DWARF_OFFSET_SIZE, debug_skeleton_info_section_label,
debug_skeleton_info_section,
@@ -9207,15 +9291,31 @@ output_pubnames (vec<pubname_entry, va_gc> *names)
: 0);
}
- dw2_asm_output_data (DWARF_OFFSET_SIZE, die_offset, "DIE offset");
-
- dw2_asm_output_nstring (pub->name, -1, "external name");
+ output_pubname (die_offset, pub);
}
}
dw2_asm_output_data (DWARF_OFFSET_SIZE, 0, NULL);
}
+/* Output public names and types tables if necessary. */
+
+static void
+output_pubtables (void)
+{
+ if (!want_pubnames () || !info_section_emitted)
+ return;
+
+ switch_to_section (debug_pubnames_section);
+ output_pubnames (pubname_table);
+ /* ??? Only defined by DWARF3, but emitted by Darwin for DWARF2.
+ It shouldn't hurt to emit it always, since pure DWARF2 consumers
+ simply won't look for the section. */
+ switch_to_section (debug_pubtypes_section);
+ output_pubnames (pubtype_table);
+}
+
+
/* Output the information that goes into the .debug_aranges table.
Namely, define the beginning and ending address range of the
text section generated for this compilation unit. */
@@ -13491,6 +13591,9 @@ dw_sra_loc_expr (tree decl, rtx loc)
if (last != NULL && opsize != bitsize)
{
padsize += bitsize;
+ /* Discard the current piece of the descriptor and release any
+ addr_table entries it uses. */
+ remove_loc_list_addr_table_entries (cur_descr);
continue;
}
@@ -13499,18 +13602,24 @@ dw_sra_loc_expr (tree decl, rtx loc)
if (padsize)
{
if (padsize > decl_size)
- return NULL;
+ {
+ remove_loc_list_addr_table_entries (cur_descr);
+ goto discard_descr;
+ }
decl_size -= padsize;
*descr_tail = new_loc_descr_op_bit_piece (padsize, 0);
if (*descr_tail == NULL)
- return NULL;
+ {
+ remove_loc_list_addr_table_entries (cur_descr);
+ goto discard_descr;
+ }
descr_tail = &(*descr_tail)->dw_loc_next;
padsize = 0;
}
*descr_tail = cur_descr;
descr_tail = tail;
if (bitsize > decl_size)
- return NULL;
+ goto discard_descr;
decl_size -= bitsize;
if (last == NULL)
{
@@ -13546,9 +13655,9 @@ dw_sra_loc_expr (tree decl, rtx loc)
{
if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN
&& (memsize > BITS_PER_WORD || bitsize > BITS_PER_WORD))
- return NULL;
+ goto discard_descr;
if (memsize < bitsize)
- return NULL;
+ goto discard_descr;
if (BITS_BIG_ENDIAN)
offset = memsize - bitsize;
}
@@ -13556,7 +13665,7 @@ dw_sra_loc_expr (tree decl, rtx loc)
*descr_tail = new_loc_descr_op_bit_piece (bitsize, offset);
if (*descr_tail == NULL)
- return NULL;
+ goto discard_descr;
descr_tail = &(*descr_tail)->dw_loc_next;
}
}
@@ -13567,9 +13676,14 @@ dw_sra_loc_expr (tree decl, rtx loc)
{
*descr_tail = new_loc_descr_op_bit_piece (decl_size, 0);
if (*descr_tail == NULL)
- return NULL;
+ goto discard_descr;
}
return descr;
+
+discard_descr:
+ /* Discard the descriptor and release any addr_table entries it uses. */
+ remove_loc_list_addr_table_entries (descr);
+ return NULL;
}
/* Return the dwarf representation of the location list LOC_LIST of
@@ -15029,7 +15143,7 @@ reference_to_unused (tree * tp, int * walk_subtrees,
else if (TREE_CODE (*tp) == VAR_DECL)
{
struct varpool_node *node = varpool_get_node (*tp);
- if (!node || !node->symbol.definition)
+ if (!node || !node->definition)
return *tp;
}
else if (TREE_CODE (*tp) == FUNCTION_DECL
@@ -17707,7 +17821,7 @@ premark_types_used_by_global_vars_helper (void **slot,
/* Ask cgraph if the global variable really is to be emitted.
If yes, then we'll keep the DIE of ENTRY->TYPE. */
struct varpool_node *node = varpool_get_node (entry->var_decl);
- if (node && node->symbol.definition)
+ if (node && node->definition)
{
die->die_perennial_p = 1;
/* Keep the parent DIEs as well. */
@@ -19109,7 +19223,7 @@ gen_compile_unit_die (const char *filename)
else if (strcmp (common_lang, TRANSLATION_UNIT_LANGUAGE (t)) == 0)
;
else if (strncmp (common_lang, "GNU C", 5) == 0
- && strncmp(TRANSLATION_UNIT_LANGUAGE (t), "GNU C", 5) == 0)
+ && strncmp (TRANSLATION_UNIT_LANGUAGE (t), "GNU C", 5) == 0)
/* Mixing C and C++ is ok, use C++ in that case. */
common_lang = "GNU C++";
else
@@ -21996,7 +22110,7 @@ index_string (void **h, void *v)
find_string_form (node);
if (node->form == DW_FORM_GNU_str_index && node->refcount > 0)
{
- gcc_assert(node->index == NO_INDEX_ASSIGNED);
+ gcc_assert (node->index == NO_INDEX_ASSIGNED);
node->index = *index;
*index += 1;
}
@@ -24077,12 +24191,7 @@ dwarf2out_finish (const char *filename)
output_location_lists (comp_unit_die ());
}
- /* Output public names and types tables if necessary. */
- output_pubnames (pubname_table);
- /* ??? Only defined by DWARF3, but emitted by Darwin for DWARF2.
- It shouldn't hurt to emit it always, since pure DWARF2 consumers
- simply won't look for the section. */
- output_pubnames (pubtype_table);
+ output_pubtables ();
/* Output the address range information if a CU (.debug_info section)
was emitted. We output an empty table even if we had no functions
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index 8a7b8a563d5..b0fc8462268 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -55,6 +55,7 @@ along with GCC; see the file COPYING3. If not see
#include "df.h"
#include "params.h"
#include "target.h"
+#include "tree-eh.h"
struct target_rtl default_target_rtl;
#if SWITCHABLE_TARGET
@@ -1704,7 +1705,7 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
/* If this expression uses it's parent's alias set, mark it such
that we won't change it. */
- if (component_uses_parent_alias_set (t))
+ if (component_uses_parent_alias_set_from (t) != NULL_TREE)
MEM_KEEP_ALIAS_SET_P (ref) = 1;
/* If this is a decl, set the attributes of the MEM from it. */
@@ -3461,7 +3462,7 @@ try_split (rtx pat, rtx trial, int last)
if (any_condjump_p (trial)
&& (note = find_reg_note (trial, REG_BR_PROB, 0)))
- split_branch_probability = INTVAL (XEXP (note, 0));
+ split_branch_probability = XINT (note, 0);
probability = split_branch_probability;
seq = split_insns (pat, trial);
@@ -3512,7 +3513,7 @@ try_split (rtx pat, rtx trial, int last)
is responsible for this step using
split_branch_probability variable. */
gcc_assert (njumps == 1);
- add_reg_note (insn, REG_BR_PROB, GEN_INT (probability));
+ add_int_reg_note (insn, REG_BR_PROB, probability);
}
}
}
@@ -4090,7 +4091,7 @@ reorder_insns_nobb (rtx from, rtx to, rtx after)
NEXT_INSN (to) = NEXT_INSN (after);
PREV_INSN (from) = after;
NEXT_INSN (after) = from;
- if (after == get_last_insn())
+ if (after == get_last_insn ())
set_last_insn (to);
}
@@ -4300,7 +4301,7 @@ emit_insn_after_1 (rtx first, rtx after, basic_block bb)
if (after_after)
PREV_INSN (after_after) = last;
- if (after == get_last_insn())
+ if (after == get_last_insn ())
set_last_insn (last);
return last;
@@ -4700,7 +4701,7 @@ emit_debug_insn_before (rtx pattern, rtx before)
rtx
emit_insn (rtx x)
{
- rtx last = get_last_insn();
+ rtx last = get_last_insn ();
rtx insn;
if (x == NULL_RTX)
@@ -4747,7 +4748,7 @@ emit_insn (rtx x)
rtx
emit_debug_insn (rtx x)
{
- rtx last = get_last_insn();
+ rtx last = get_last_insn ();
rtx insn;
if (x == NULL_RTX)
@@ -5804,9 +5805,9 @@ init_emit_once (void)
mode != VOIDmode;
mode = GET_MODE_WIDER_MODE (mode))
{
- FCONST0(mode).data.high = 0;
- FCONST0(mode).data.low = 0;
- FCONST0(mode).mode = mode;
+ FCONST0 (mode).data.high = 0;
+ FCONST0 (mode).data.low = 0;
+ FCONST0 (mode).mode = mode;
const_tiny_rtx[0][(int) mode] = CONST_FIXED_FROM_FIXED_VALUE (
FCONST0 (mode), mode);
}
@@ -5815,9 +5816,9 @@ init_emit_once (void)
mode != VOIDmode;
mode = GET_MODE_WIDER_MODE (mode))
{
- FCONST0(mode).data.high = 0;
- FCONST0(mode).data.low = 0;
- FCONST0(mode).mode = mode;
+ FCONST0 (mode).data.high = 0;
+ FCONST0 (mode).data.low = 0;
+ FCONST0 (mode).mode = mode;
const_tiny_rtx[0][(int) mode] = CONST_FIXED_FROM_FIXED_VALUE (
FCONST0 (mode), mode);
}
@@ -5826,17 +5827,17 @@ init_emit_once (void)
mode != VOIDmode;
mode = GET_MODE_WIDER_MODE (mode))
{
- FCONST0(mode).data.high = 0;
- FCONST0(mode).data.low = 0;
- FCONST0(mode).mode = mode;
+ FCONST0 (mode).data.high = 0;
+ FCONST0 (mode).data.low = 0;
+ FCONST0 (mode).mode = mode;
const_tiny_rtx[0][(int) mode] = CONST_FIXED_FROM_FIXED_VALUE (
FCONST0 (mode), mode);
/* We store the value 1. */
- FCONST1(mode).data.high = 0;
- FCONST1(mode).data.low = 0;
- FCONST1(mode).mode = mode;
- FCONST1(mode).data
+ FCONST1 (mode).data.high = 0;
+ FCONST1 (mode).data.low = 0;
+ FCONST1 (mode).mode = mode;
+ FCONST1 (mode).data
= double_int_one.lshift (GET_MODE_FBIT (mode),
HOST_BITS_PER_DOUBLE_INT,
SIGNED_FIXED_POINT_MODE_P (mode));
@@ -5848,17 +5849,17 @@ init_emit_once (void)
mode != VOIDmode;
mode = GET_MODE_WIDER_MODE (mode))
{
- FCONST0(mode).data.high = 0;
- FCONST0(mode).data.low = 0;
- FCONST0(mode).mode = mode;
+ FCONST0 (mode).data.high = 0;
+ FCONST0 (mode).data.low = 0;
+ FCONST0 (mode).mode = mode;
const_tiny_rtx[0][(int) mode] = CONST_FIXED_FROM_FIXED_VALUE (
FCONST0 (mode), mode);
/* We store the value 1. */
- FCONST1(mode).data.high = 0;
- FCONST1(mode).data.low = 0;
- FCONST1(mode).mode = mode;
- FCONST1(mode).data
+ FCONST1 (mode).data.high = 0;
+ FCONST1 (mode).data.low = 0;
+ FCONST1 (mode).mode = mode;
+ FCONST1 (mode).data
= double_int_one.lshift (GET_MODE_FBIT (mode),
HOST_BITS_PER_DOUBLE_INT,
SIGNED_FIXED_POINT_MODE_P (mode));
@@ -5968,7 +5969,7 @@ emit_copy_of_insn_after (rtx insn, rtx after)
add_reg_note (new_rtx, REG_NOTE_KIND (link),
copy_insn_1 (XEXP (link, 0)));
else
- add_reg_note (new_rtx, REG_NOTE_KIND (link), XEXP (link, 0));
+ add_shallow_copy_of_reg_note (new_rtx, link);
}
INSN_CODE (new_rtx) = INSN_CODE (insn);
diff --git a/gcc/errors.c b/gcc/errors.c
index cac7dcb9c09..5e0bc720e6f 100644
--- a/gcc/errors.c
+++ b/gcc/errors.c
@@ -48,7 +48,7 @@ warning (const char *format, ...)
fprintf (stderr, "%s: warning: ", progname);
vfprintf (stderr, format, ap);
va_end (ap);
- fputc('\n', stderr);
+ fputc ('\n', stderr);
}
@@ -63,7 +63,7 @@ error (const char *format, ...)
fprintf (stderr, "%s: ", progname);
vfprintf (stderr, format, ap);
va_end (ap);
- fputc('\n', stderr);
+ fputc ('\n', stderr);
have_error = 1;
}
@@ -80,7 +80,7 @@ fatal (const char *format, ...)
fprintf (stderr, "%s: ", progname);
vfprintf (stderr, format, ap);
va_end (ap);
- fputc('\n', stderr);
+ fputc ('\n', stderr);
exit (FATAL_EXIT_CODE);
}
diff --git a/gcc/except.c b/gcc/except.c
index b161f9e2b69..a52d317ddae 100644
--- a/gcc/except.c
+++ b/gcc/except.c
@@ -139,7 +139,7 @@ along with GCC; see the file COPYING3. If not see
#include "diagnostic.h"
#include "tree-pretty-print.h"
#include "tree-pass.h"
-#include "tree-ssa.h"
+#include "gimple.h"
#include "cfgloop.h"
/* Provide defaults for stuff that may not be defined when using
@@ -641,7 +641,7 @@ eh_region_outermost (struct function *ifun, eh_region region_a,
gcc_assert (ifun->eh->region_array);
gcc_assert (ifun->eh->region_tree);
- b_outer = sbitmap_alloc (ifun->eh->region_array->length());
+ b_outer = sbitmap_alloc (ifun->eh->region_array->length ());
bitmap_clear (b_outer);
do
@@ -2021,8 +2021,8 @@ const pass_data pass_data_set_nothrow_function_flags =
class pass_set_nothrow_function_flags : public rtl_opt_pass
{
public:
- pass_set_nothrow_function_flags(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_set_nothrow_function_flags, ctxt)
+ pass_set_nothrow_function_flags (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_set_nothrow_function_flags, ctxt)
{}
/* opt_pass methods: */
@@ -2652,8 +2652,8 @@ const pass_data pass_data_convert_to_eh_region_ranges =
class pass_convert_to_eh_region_ranges : public rtl_opt_pass
{
public:
- pass_convert_to_eh_region_ranges(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_convert_to_eh_region_ranges, ctxt)
+ pass_convert_to_eh_region_ranges (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_convert_to_eh_region_ranges, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/explow.c b/gcc/explow.c
index f278e29b78e..bf5742de896 100644
--- a/gcc/explow.c
+++ b/gcc/explow.c
@@ -235,6 +235,18 @@ eliminate_constant_term (rtx x, rtx *constptr)
return x;
}
+/* Returns a tree for the size of EXP in bytes. */
+
+static tree
+tree_expr_size (const_tree exp)
+{
+ if (DECL_P (exp)
+ && DECL_SIZE_UNIT (exp) != 0)
+ return DECL_SIZE_UNIT (exp);
+ else
+ return size_in_bytes (TREE_TYPE (exp));
+}
+
/* Return an rtx for the size in bytes of the value of EXP. */
rtx
diff --git a/gcc/expmed.c b/gcc/expmed.c
index ba9a7b68c42..1617bc05aa1 100644
--- a/gcc/expmed.c
+++ b/gcc/expmed.c
@@ -54,7 +54,7 @@ static void store_split_bit_field (rtx, unsigned HOST_WIDE_INT,
rtx);
static rtx extract_fixed_bit_field (enum machine_mode, rtx,
unsigned HOST_WIDE_INT,
- unsigned HOST_WIDE_INT, rtx, int, bool);
+ unsigned HOST_WIDE_INT, rtx, int);
static rtx mask_rtx (enum machine_mode, int, int, int);
static rtx lshift_value (enum machine_mode, unsigned HOST_WIDE_INT, int);
static rtx extract_split_bit_field (rtx, unsigned HOST_WIDE_INT,
@@ -624,13 +624,28 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
|| (bitsize % BITS_PER_WORD == 0 && bitnum % BITS_PER_WORD == 0)))
{
/* Use the subreg machinery either to narrow OP0 to the required
- words or to cope with mode punning between equal-sized modes. */
- rtx sub = simplify_gen_subreg (fieldmode, op0, GET_MODE (op0),
- bitnum / BITS_PER_UNIT);
- if (sub)
+ words or to cope with mode punning between equal-sized modes.
+ In the latter case, use subreg on the rhs side, not lhs. */
+ rtx sub;
+
+ if (bitsize == GET_MODE_BITSIZE (GET_MODE (op0)))
{
- emit_move_insn (sub, value);
- return true;
+ sub = simplify_gen_subreg (GET_MODE (op0), value, fieldmode, 0);
+ if (sub)
+ {
+ emit_move_insn (op0, sub);
+ return true;
+ }
+ }
+ else
+ {
+ sub = simplify_gen_subreg (fieldmode, op0, GET_MODE (op0),
+ bitnum / BITS_PER_UNIT);
+ if (sub)
+ {
+ emit_move_insn (sub, value);
+ return true;
+ }
}
}
@@ -1128,7 +1143,7 @@ store_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
endianness compensation) to fetch the piece we want. */
part = extract_fixed_bit_field (word_mode, value, thissize,
total_bits - bitsize + bitsdone,
- NULL_RTX, 1, false);
+ NULL_RTX, 1);
}
}
else
@@ -1140,7 +1155,7 @@ store_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
& (((HOST_WIDE_INT) 1 << thissize) - 1));
else
part = extract_fixed_bit_field (word_mode, value, thissize,
- bitsdone, NULL_RTX, 1, false);
+ bitsdone, NULL_RTX, 1);
}
/* If OP0 is a register, then handle OFFSET here.
@@ -1301,8 +1316,7 @@ extract_bit_field_using_extv (const extraction_insn *extv, rtx op0,
static rtx
extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
- unsigned HOST_WIDE_INT bitnum,
- int unsignedp, bool packedp, rtx target,
+ unsigned HOST_WIDE_INT bitnum, int unsignedp, rtx target,
enum machine_mode mode, enum machine_mode tmode,
bool fallback_p)
{
@@ -1517,7 +1531,7 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
rtx result_part
= extract_bit_field_1 (op0, MIN (BITS_PER_WORD,
bitsize - i * BITS_PER_WORD),
- bitnum + bit_offset, 1, false, target_part,
+ bitnum + bit_offset, 1, target_part,
mode, word_mode, fallback_p);
gcc_assert (target_part);
@@ -1621,7 +1635,7 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
{
xop0 = copy_to_reg (xop0);
rtx result = extract_bit_field_1 (xop0, bitsize, bitpos,
- unsignedp, packedp, target,
+ unsignedp, target,
mode, tmode, false);
if (result)
return result;
@@ -1641,7 +1655,7 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
gcc_assert (int_mode != BLKmode);
target = extract_fixed_bit_field (int_mode, op0, bitsize, bitnum,
- target, unsignedp, packedp);
+ target, unsignedp);
return convert_extracted_bit_field (target, mode, tmode, unsignedp);
}
@@ -1652,7 +1666,6 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
STR_RTX is the structure containing the byte (a REG or MEM).
UNSIGNEDP is nonzero if this is an unsigned bit field.
- PACKEDP is nonzero if the field has the packed attribute.
MODE is the natural mode of the field value once extracted.
TMODE is the mode the caller would like the value to have;
but the value may be returned with type MODE instead.
@@ -1664,10 +1677,10 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
rtx
extract_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
- unsigned HOST_WIDE_INT bitnum, int unsignedp, bool packedp,
- rtx target, enum machine_mode mode, enum machine_mode tmode)
+ unsigned HOST_WIDE_INT bitnum, int unsignedp, rtx target,
+ enum machine_mode mode, enum machine_mode tmode)
{
- return extract_bit_field_1 (str_rtx, bitsize, bitnum, unsignedp, packedp,
+ return extract_bit_field_1 (str_rtx, bitsize, bitnum, unsignedp,
target, mode, tmode, true);
}
@@ -1675,8 +1688,6 @@ extract_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
from bit BITNUM of OP0.
UNSIGNEDP is nonzero for an unsigned bit field (don't sign-extend value).
- PACKEDP is true if the field has the packed attribute.
-
If TARGET is nonzero, attempts to store the value there
and return TARGET, but this is not guaranteed.
If TARGET is not used, create a pseudo-reg of mode TMODE for the value. */
@@ -1685,7 +1696,7 @@ static rtx
extract_fixed_bit_field (enum machine_mode tmode, rtx op0,
unsigned HOST_WIDE_INT bitsize,
unsigned HOST_WIDE_INT bitnum, rtx target,
- int unsignedp, bool packedp)
+ int unsignedp)
{
enum machine_mode mode;
@@ -1726,45 +1737,10 @@ extract_fixed_bit_field (enum machine_mode tmode, rtx op0,
&& bitnum % BITS_PER_UNIT + bitsize <= total_bits
&& bitnum % GET_MODE_BITSIZE (mode) + bitsize > total_bits)
{
+ /* If the target doesn't support unaligned access, give up and
+ split the access into two. */
if (STRICT_ALIGNMENT)
- {
- static bool informed_about_misalignment = false;
-
- if (packedp)
- {
- if (bitsize == total_bits)
- warning_at (input_location, OPT_fstrict_volatile_bitfields,
- "multiple accesses to volatile structure"
- " member because of packed attribute");
- else
- warning_at (input_location, OPT_fstrict_volatile_bitfields,
- "multiple accesses to volatile structure"
- " bitfield because of packed attribute");
-
- return extract_split_bit_field (op0, bitsize, bitnum,
- unsignedp);
- }
-
- if (bitsize == total_bits)
- warning_at (input_location, OPT_fstrict_volatile_bitfields,
- "mis-aligned access used for structure member");
- else
- warning_at (input_location, OPT_fstrict_volatile_bitfields,
- "mis-aligned access used for structure bitfield");
-
- if (! informed_about_misalignment)
- {
- informed_about_misalignment = true;
- inform (input_location,
- "when a volatile object spans multiple type-sized"
- " locations, the compiler must choose between using"
- " a single mis-aligned access to preserve the"
- " volatility, or using multiple aligned accesses"
- " to avoid runtime faults; this code may fail at"
- " runtime if the hardware does not allow this"
- " access");
- }
- }
+ return extract_split_bit_field (op0, bitsize, bitnum, unsignedp);
bit_offset = bitnum - bitnum % BITS_PER_UNIT;
}
op0 = adjust_bitfield_address (op0, mode, bit_offset / BITS_PER_UNIT);
@@ -1940,7 +1916,7 @@ extract_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
whose meaning is determined by BYTES_PER_UNIT.
OFFSET is in UNITs, and UNIT is in bits. */
part = extract_fixed_bit_field (word_mode, word, thissize,
- offset * unit + thispos, 0, 1, false);
+ offset * unit + thispos, 0, 1);
bitsdone += thissize;
/* Shift this part into place for the result. */
@@ -2845,7 +2821,7 @@ choose_mult_variant (enum machine_mode mode, HOST_WIDE_INT val,
`unsigned int' */
if (HOST_BITS_PER_INT >= GET_MODE_UNIT_BITSIZE (mode))
{
- op_cost = neg_cost(speed, mode);
+ op_cost = neg_cost (speed, mode);
if (MULT_COST_LESS (&alg->cost, mult_cost))
{
limit.cost = alg->cost.cost - op_cost;
@@ -3163,7 +3139,7 @@ expand_mult (enum machine_mode mode, rtx op0, rtx op1, rtx target,
calculation of the synth_mult. */
coeff = -(unsigned HOST_WIDE_INT) coeff;
max_cost = (set_src_cost (gen_rtx_MULT (mode, fake_reg, op1), speed)
- - neg_cost(speed, mode));
+ - neg_cost (speed, mode));
if (max_cost <= 0)
goto skip_synth;
@@ -3916,7 +3892,7 @@ expand_divmod (int rem_flag, enum tree_code code, enum machine_mode mode,
{
if (rem_flag)
return const0_rtx;
- return expand_unop (mode, flag_trapv && GET_MODE_CLASS(mode) == MODE_INT
+ return expand_unop (mode, flag_trapv && GET_MODE_CLASS (mode) == MODE_INT
? negv_optab : neg_optab, op0, target, 0);
}
@@ -5425,6 +5401,13 @@ emit_store_flag (rtx target, enum rtx_code code, rtx op0, rtx op1,
rtx subtarget;
rtx tem, last, trueval;
+ /* If we compare constants, we shouldn't use a store-flag operation,
+ but a constant load. We can get there via the vanilla route that
+ usually generates a compare-branch sequence, but will in this case
+ fold the comparison to a constant, and thus elide the branch. */
+ if (CONSTANT_P (op0) && CONSTANT_P (op1))
+ return NULL_RTX;
+
tem = emit_store_flag_1 (target, code, op0, op1, mode, unsignedp, normalizep,
target_mode);
if (tem)
diff --git a/gcc/expr.c b/gcc/expr.c
index 39fa71e8051..28b43320798 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -43,15 +43,20 @@ along with GCC; see the file COPYING3. If not see
#include "intl.h"
#include "tm_p.h"
#include "tree-iterator.h"
-#include "tree-ssa.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "cgraph.h"
+#include "tree-ssanames.h"
#include "target.h"
#include "common/common-target.h"
#include "timevar.h"
#include "df.h"
#include "diagnostic.h"
-#include "ssaexpand.h"
+#include "tree-ssa-live.h"
+#include "tree-outof-ssa.h"
#include "target-globals.h"
#include "params.h"
+#include "tree-ssa-address.h"
/* Decide whether a function's arguments should be processed
from first to last or from last to first.
@@ -1292,11 +1297,12 @@ emit_block_move_via_movmem (rtx x, rtx y, rtx size, unsigned int align,
/* We don't need MODE to be narrower than BITS_PER_HOST_WIDE_INT
here because if SIZE is less than the mode mask, as it is
returned by the macro, it will definitely be less than the
- actual mode mask. */
+ actual mode mask. Since SIZE is within the Pmode address
+ space, we limit MODE to Pmode. */
&& ((CONST_INT_P (size)
&& ((unsigned HOST_WIDE_INT) INTVAL (size)
<= (GET_MODE_MASK (mode) >> 1)))
- || GET_MODE_BITSIZE (mode) >= BITS_PER_WORD))
+ || GET_MODE_BITSIZE (mode) >= GET_MODE_BITSIZE (Pmode)))
{
struct expand_operand ops[6];
unsigned int nops;
@@ -1710,7 +1716,7 @@ emit_group_load_1 (rtx *tmps, rtx dst, rtx orig_src, tree type, int ssize)
&& (!REG_P (tmps[i]) || GET_MODE (tmps[i]) != mode))
tmps[i] = extract_bit_field (tmps[i], bytelen * BITS_PER_UNIT,
(bytepos % slen0) * BITS_PER_UNIT,
- 1, false, NULL_RTX, mode, mode);
+ 1, NULL_RTX, mode, mode);
}
else
{
@@ -1720,7 +1726,7 @@ emit_group_load_1 (rtx *tmps, rtx dst, rtx orig_src, tree type, int ssize)
mem = assign_stack_temp (GET_MODE (src), slen);
emit_move_insn (mem, src);
tmps[i] = extract_bit_field (mem, bytelen * BITS_PER_UNIT,
- 0, 1, false, NULL_RTX, mode, mode);
+ 0, 1, NULL_RTX, mode, mode);
}
}
/* FIXME: A SIMD parallel will eventually lead to a subreg of a
@@ -1738,7 +1744,7 @@ emit_group_load_1 (rtx *tmps, rtx dst, rtx orig_src, tree type, int ssize)
}
else if (CONSTANT_P (src) && GET_MODE (dst) != BLKmode
&& XVECLEN (dst, 0) > 1)
- tmps[i] = simplify_gen_subreg (mode, src, GET_MODE(dst), bytepos);
+ tmps[i] = simplify_gen_subreg (mode, src, GET_MODE (dst), bytepos);
else if (CONSTANT_P (src))
{
HOST_WIDE_INT len = (HOST_WIDE_INT) bytelen;
@@ -1761,7 +1767,7 @@ emit_group_load_1 (rtx *tmps, rtx dst, rtx orig_src, tree type, int ssize)
tmps[i] = src;
else
tmps[i] = extract_bit_field (src, bytelen * BITS_PER_UNIT,
- bytepos * BITS_PER_UNIT, 1, false, NULL_RTX,
+ bytepos * BITS_PER_UNIT, 1, NULL_RTX,
mode, mode);
if (shift)
@@ -2204,7 +2210,7 @@ copy_blkmode_from_reg (rtx target, rtx srcreg, tree type)
bitpos for the destination store (left justified). */
store_bit_field (dst, bitsize, bitpos % BITS_PER_WORD, 0, 0, copy_mode,
extract_bit_field (src, bitsize,
- xbitpos % BITS_PER_WORD, 1, false,
+ xbitpos % BITS_PER_WORD, 1,
NULL_RTX, copy_mode, copy_mode));
}
}
@@ -2281,7 +2287,7 @@ copy_blkmode_to_reg (enum machine_mode mode, tree src)
store_bit_field (dst_word, bitsize, xbitpos % BITS_PER_WORD,
0, 0, word_mode,
extract_bit_field (src_word, bitsize,
- bitpos % BITS_PER_WORD, 1, false,
+ bitpos % BITS_PER_WORD, 1,
NULL_RTX, word_mode, word_mode));
}
@@ -2874,14 +2880,15 @@ set_storage_via_setmem (rtx object, rtx size, rtx val, unsigned int align,
enum insn_code code = direct_optab_handler (setmem_optab, mode);
if (code != CODE_FOR_nothing
- /* We don't need MODE to be narrower than
- BITS_PER_HOST_WIDE_INT here because if SIZE is less than
- the mode mask, as it is returned by the macro, it will
- definitely be less than the actual mode mask. */
+ /* We don't need MODE to be narrower than BITS_PER_HOST_WIDE_INT
+ here because if SIZE is less than the mode mask, as it is
+ returned by the macro, it will definitely be less than the
+ actual mode mask. Since SIZE is within the Pmode address
+ space, we limit MODE to Pmode. */
&& ((CONST_INT_P (size)
&& ((unsigned HOST_WIDE_INT) INTVAL (size)
<= (GET_MODE_MASK (mode) >> 1)))
- || GET_MODE_BITSIZE (mode) >= BITS_PER_WORD))
+ || GET_MODE_BITSIZE (mode) >= GET_MODE_BITSIZE (Pmode)))
{
struct expand_operand ops[6];
unsigned int nops;
@@ -3029,7 +3036,7 @@ read_complex_part (rtx cplx, bool imag_p)
}
return extract_bit_field (cplx, ibitsize, imag_p ? ibitsize : 0,
- true, false, NULL_RTX, imode, imode);
+ true, NULL_RTX, imode, imode);
}
/* A subroutine of emit_move_insn_1. Yet another lowpart generator.
@@ -3247,10 +3254,10 @@ emit_move_complex (enum machine_mode mode, rtx x, rtx y)
&& optab_handler (mov_optab, GET_MODE_INNER (mode)) != CODE_FOR_nothing
&& !(REG_P (x)
&& HARD_REGISTER_P (x)
- && hard_regno_nregs[REGNO(x)][mode] == 1)
+ && hard_regno_nregs[REGNO (x)][mode] == 1)
&& !(REG_P (y)
&& HARD_REGISTER_P (y)
- && hard_regno_nregs[REGNO(y)][mode] == 1))
+ && hard_regno_nregs[REGNO (y)][mode] == 1))
try_int = false;
/* Not possible if the values are inherently not adjacent. */
else if (GET_CODE (x) == CONCAT || GET_CODE (y) == CONCAT)
@@ -4569,19 +4576,19 @@ get_bit_range (unsigned HOST_WIDE_INT *bitstart,
- tree_low_cst (DECL_FIELD_BIT_OFFSET (repr), 1));
/* If the adjustment is larger than bitpos, we would have a negative bit
- position for the lower bound and this may wreak havoc later. This can
- occur only if we have a non-null offset, so adjust offset and bitpos
- to make the lower bound non-negative. */
+ position for the lower bound and this may wreak havoc later. Adjust
+ offset and bitpos to make the lower bound non-negative in that case. */
if (bitoffset > *bitpos)
{
HOST_WIDE_INT adjust = bitoffset - *bitpos;
-
gcc_assert ((adjust % BITS_PER_UNIT) == 0);
- gcc_assert (*offset != NULL_TREE);
*bitpos += adjust;
- *offset
- = size_binop (MINUS_EXPR, *offset, size_int (adjust / BITS_PER_UNIT));
+ if (*offset == NULL_TREE)
+ *offset = size_int (-adjust / BITS_PER_UNIT);
+ else
+ *offset
+ = size_binop (MINUS_EXPR, *offset, size_int (adjust / BITS_PER_UNIT));
*bitstart = 0;
}
else
@@ -4623,17 +4630,6 @@ mem_ref_refers_to_non_mem_p (tree ref)
return addr_expr_of_non_mem_decl_p_1 (base, false);
}
-/* Return TRUE iff OP is an ADDR_EXPR of a DECL that's not
- addressable. This is very much like mem_ref_refers_to_non_mem_p,
- but instead of the MEM_REF, it takes its base, and it doesn't
- assume a DECL is in memory just because its RTL is not set yet. */
-
-bool
-addr_expr_of_non_mem_decl_p (tree op)
-{
- return addr_expr_of_non_mem_decl_p_1 (op, true);
-}
-
/* Expand an assignment that stores the value of FROM into TO. If NONTEMPORAL
is true, try generating a nontemporal store. */
@@ -4709,51 +4705,25 @@ expand_assignment (tree to, tree from, bool nontemporal)
int unsignedp;
int volatilep = 0;
tree tem;
- bool misalignp;
- rtx mem = NULL_RTX;
push_temp_slots ();
tem = get_inner_reference (to, &bitsize, &bitpos, &offset, &mode1,
&unsignedp, &volatilep, true);
+ /* Make sure bitpos is not negative, it can wreak havoc later. */
+ if (bitpos < 0)
+ {
+ gcc_assert (offset == NULL_TREE);
+ offset = size_int (bitpos >> (BITS_PER_UNIT == 8
+ ? 3 : exact_log2 (BITS_PER_UNIT)));
+ bitpos &= BITS_PER_UNIT - 1;
+ }
+
if (TREE_CODE (to) == COMPONENT_REF
&& DECL_BIT_FIELD_TYPE (TREE_OPERAND (to, 1)))
get_bit_range (&bitregion_start, &bitregion_end, to, &bitpos, &offset);
- /* If we are going to use store_bit_field and extract_bit_field,
- make sure to_rtx will be safe for multiple use. */
- mode = TYPE_MODE (TREE_TYPE (tem));
- if (TREE_CODE (tem) == MEM_REF
- && mode != BLKmode
- && ((align = get_object_alignment (tem))
- < GET_MODE_ALIGNMENT (mode))
- && ((icode = optab_handler (movmisalign_optab, mode))
- != CODE_FOR_nothing))
- {
- struct expand_operand ops[2];
-
- misalignp = true;
- to_rtx = gen_reg_rtx (mode);
- mem = expand_expr (tem, NULL_RTX, VOIDmode, EXPAND_WRITE);
-
- /* If the misaligned store doesn't overwrite all bits, perform
- rmw cycle on MEM. */
- if (bitsize != GET_MODE_BITSIZE (mode))
- {
- create_input_operand (&ops[0], to_rtx, mode);
- create_fixed_operand (&ops[1], mem);
- /* The movmisalign<mode> pattern cannot fail, else the assignment
- would silently be omitted. */
- expand_insn (icode, 2, ops);
-
- mem = copy_rtx (mem);
- }
- }
- else
- {
- misalignp = false;
- to_rtx = expand_expr (tem, NULL_RTX, VOIDmode, EXPAND_WRITE);
- }
+ to_rtx = expand_expr (tem, NULL_RTX, VOIDmode, EXPAND_WRITE);
/* If the bitfield is volatile, we want to access it in the
field's mode, not the computed mode.
@@ -4871,11 +4841,7 @@ expand_assignment (tree to, tree from, bool nontemporal)
/* If the field is at offset zero, we could have been given the
DECL_RTX of the parent struct. Don't munge it. */
to_rtx = shallow_copy_rtx (to_rtx);
-
set_mem_attributes_minus_bitpos (to_rtx, to, 0, bitpos);
-
- /* Deal with volatile and readonly fields. The former is only
- done for MEM. Also set MEM_KEEP_ALIAS_SET_P if needed. */
if (volatilep)
MEM_VOLATILE_P (to_rtx) = 1;
}
@@ -4892,17 +4858,6 @@ expand_assignment (tree to, tree from, bool nontemporal)
get_alias_set (to), nontemporal);
}
- if (misalignp)
- {
- struct expand_operand ops[2];
-
- create_fixed_operand (&ops[0], mem);
- create_input_operand (&ops[1], to_rtx, mode);
- /* The movmisalign<mode> pattern cannot fail, else the assignment
- would silently be omitted. */
- expand_insn (icode, 2, ops);
- }
-
if (result)
preserve_temp_slots (result);
pop_temp_slots ();
@@ -5787,6 +5742,23 @@ store_constructor_field (rtx target, unsigned HOST_WIDE_INT bitsize,
store_field (target, bitsize, bitpos, 0, 0, mode, exp, alias_set, false);
}
+
+/* Returns the number of FIELD_DECLs in TYPE. */
+
+static int
+fields_length (const_tree type)
+{
+ tree t = TYPE_FIELDS (type);
+ int count = 0;
+
+ for (; t; t = DECL_CHAIN (t))
+ if (TREE_CODE (t) == FIELD_DECL)
+ ++count;
+
+ return count;
+}
+
+
/* Store the value of constructor EXP into the rtx TARGET.
TARGET is either a REG or a MEM; we know it cannot conflict, since
safe_from_p has been called.
@@ -6520,7 +6492,7 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
temp_target = gen_reg_rtx (mode);
temp_target
= extract_bit_field (temp, size * BITS_PER_UNIT, 0, 1,
- false, temp_target, mode, mode);
+ temp_target, mode, mode);
temp = temp_target;
}
}
@@ -6601,16 +6573,18 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize,
{
tree field = TREE_OPERAND (exp, 1);
size_tree = DECL_SIZE (field);
- if (!DECL_BIT_FIELD (field))
- mode = DECL_MODE (field);
- else if (DECL_MODE (field) == BLKmode)
- blkmode_bitfield = true;
- else if (TREE_THIS_VOLATILE (exp)
- && flag_strict_volatile_bitfields > 0)
+ if (flag_strict_volatile_bitfields > 0
+ && TREE_THIS_VOLATILE (exp)
+ && DECL_BIT_FIELD_TYPE (field)
+ && DECL_MODE (field) != BLKmode)
/* Volatile bitfields should be accessed in the mode of the
field's type, not the mode computed based on the bit
size. */
mode = TYPE_MODE (DECL_BIT_FIELD_TYPE (field));
+ else if (!DECL_BIT_FIELD (field))
+ mode = DECL_MODE (field);
+ else if (DECL_MODE (field) == BLKmode)
+ blkmode_bitfield = true;
*punsignedp = DECL_UNSIGNED (field);
}
@@ -7326,74 +7300,14 @@ safe_from_p (const_rtx x, tree exp, int top_p)
unsigned HOST_WIDE_INT
highest_pow2_factor (const_tree exp)
{
- unsigned HOST_WIDE_INT c0, c1;
-
- switch (TREE_CODE (exp))
- {
- case INTEGER_CST:
- /* We can find the lowest bit that's a one. If the low
- HOST_BITS_PER_WIDE_INT bits are zero, return BIGGEST_ALIGNMENT.
- We need to handle this case since we can find it in a COND_EXPR,
- a MIN_EXPR, or a MAX_EXPR. If the constant overflows, we have an
- erroneous program, so return BIGGEST_ALIGNMENT to avoid any
- later ICE. */
- if (TREE_OVERFLOW (exp))
- return BIGGEST_ALIGNMENT;
- else
- {
- /* Note: tree_low_cst is intentionally not used here,
- we don't care about the upper bits. */
- c0 = TREE_INT_CST_LOW (exp);
- c0 &= -c0;
- return c0 ? c0 : BIGGEST_ALIGNMENT;
- }
- break;
-
- case PLUS_EXPR: case MINUS_EXPR: case MIN_EXPR: case MAX_EXPR:
- c0 = highest_pow2_factor (TREE_OPERAND (exp, 0));
- c1 = highest_pow2_factor (TREE_OPERAND (exp, 1));
- return MIN (c0, c1);
-
- case MULT_EXPR:
- c0 = highest_pow2_factor (TREE_OPERAND (exp, 0));
- c1 = highest_pow2_factor (TREE_OPERAND (exp, 1));
- return c0 * c1;
-
- case ROUND_DIV_EXPR: case TRUNC_DIV_EXPR: case FLOOR_DIV_EXPR:
- case CEIL_DIV_EXPR:
- if (integer_pow2p (TREE_OPERAND (exp, 1))
- && host_integerp (TREE_OPERAND (exp, 1), 1))
- {
- c0 = highest_pow2_factor (TREE_OPERAND (exp, 0));
- c1 = tree_low_cst (TREE_OPERAND (exp, 1), 1);
- return MAX (1, c0 / c1);
- }
- break;
-
- case BIT_AND_EXPR:
- /* The highest power of two of a bit-and expression is the maximum of
- that of its operands. We typically get here for a complex LHS and
- a constant negative power of two on the RHS to force an explicit
- alignment, so don't bother looking at the LHS. */
- return highest_pow2_factor (TREE_OPERAND (exp, 1));
-
- CASE_CONVERT:
- case SAVE_EXPR:
- return highest_pow2_factor (TREE_OPERAND (exp, 0));
-
- case COMPOUND_EXPR:
- return highest_pow2_factor (TREE_OPERAND (exp, 1));
-
- case COND_EXPR:
- c0 = highest_pow2_factor (TREE_OPERAND (exp, 1));
- c1 = highest_pow2_factor (TREE_OPERAND (exp, 2));
- return MIN (c0, c1);
-
- default:
- break;
- }
-
- return 1;
+ unsigned HOST_WIDE_INT ret;
+ int trailing_zeros = tree_ctz (exp);
+ if (trailing_zeros >= HOST_BITS_PER_WIDE_INT)
+ return BIGGEST_ALIGNMENT;
+ ret = (unsigned HOST_WIDE_INT) 1 << trailing_zeros;
+ if (ret > BIGGEST_ALIGNMENT)
+ return BIGGEST_ALIGNMENT;
+ return ret;
}
/* Similar, except that the alignment requirements of TARGET are
@@ -7610,7 +7524,7 @@ expand_expr_addr_expr_1 (tree exp, rtx target, enum machine_mode tmode,
if (TREE_ADDRESSABLE (exp)
&& ! MEM_P (result)
- && ! targetm.calls.allocate_stack_slots_for_args())
+ && ! targetm.calls.allocate_stack_slots_for_args ())
{
error ("local frame unavailable (naked function?)");
return result;
@@ -9176,6 +9090,24 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
}
#undef REDUCE_BIT_FIELD
+
+/* Return TRUE if expression STMT is suitable for replacement.
+ Never consider memory loads as replaceable, because those don't ever lead
+ into constant expressions. */
+
+static bool
+stmt_is_replaceable_p (gimple stmt)
+{
+ if (ssa_is_replaceable_p (stmt))
+ {
+ /* Don't move around loads. */
+ if (!gimple_assign_single_p (stmt)
+ || is_gimple_val (gimple_assign_rhs1 (stmt)))
+ return true;
+ }
+ return false;
+}
+
rtx
expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
enum expand_modifier modifier, rtx *alt_rtl)
@@ -9592,12 +9524,10 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
{
addr_space_t as
= TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 0))));
- struct mem_address addr;
enum insn_code icode;
unsigned int align;
- get_address_description (exp, &addr);
- op0 = addr_for_mem_ref (&addr, as, true);
+ op0 = addr_for_mem_ref (exp, as, true);
op0 = memory_address_addr_space (mode, op0, as);
temp = gen_rtx_MEM (mode, op0);
set_mem_attributes (temp, exp, 0);
@@ -9670,14 +9600,14 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
}
align = get_object_alignment (exp);
op0 = expand_expr (base, NULL_RTX, VOIDmode, EXPAND_SUM);
- op0 = memory_address_addr_space (address_mode, op0, as);
+ op0 = memory_address_addr_space (mode, op0, as);
if (!integer_zerop (TREE_OPERAND (exp, 1)))
{
rtx off
= immed_double_int_const (mem_ref_offset (exp), address_mode);
op0 = simplify_gen_binary (PLUS, address_mode, op0, off);
+ op0 = memory_address_addr_space (mode, op0, as);
}
- op0 = memory_address_addr_space (mode, op0, as);
temp = gen_rtx_MEM (mode, op0);
set_mem_attributes (temp, exp, 0);
set_mem_addr_space (temp, as);
@@ -9704,8 +9634,8 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
else if (SLOW_UNALIGNED_ACCESS (mode, align))
temp = extract_bit_field (temp, GET_MODE_BITSIZE (mode),
0, TYPE_UNSIGNED (TREE_TYPE (exp)),
- true, (modifier == EXPAND_STACK_PARM
- ? NULL_RTX : target),
+ (modifier == EXPAND_STACK_PARM
+ ? NULL_RTX : target),
mode, mode);
}
return temp;
@@ -9896,7 +9826,6 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
HOST_WIDE_INT bitsize, bitpos;
tree offset;
int volatilep = 0, must_force_mem;
- bool packedp = false;
tree tem = get_inner_reference (exp, &bitsize, &bitpos, &offset,
&mode1, &unsignedp, &volatilep, true);
rtx orig_op0, memloc;
@@ -9907,11 +9836,6 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
infinitely recurse. */
gcc_assert (tem != exp);
- if (TYPE_PACKED (TREE_TYPE (TREE_OPERAND (exp, 0)))
- || (TREE_CODE (TREE_OPERAND (exp, 1)) == FIELD_DECL
- && DECL_PACKED (TREE_OPERAND (exp, 1))))
- packedp = true;
-
/* If TEM's type is a union of variable size, pass TARGET to the inner
computation, since it will need a temporary and TARGET is known
to have to do. This occurs in unchecked conversion in Ada. */
@@ -10136,7 +10060,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
if (MEM_P (op0) && REG_P (XEXP (op0, 0)))
mark_reg_pointer (XEXP (op0, 0), MEM_ALIGN (op0));
- op0 = extract_bit_field (op0, bitsize, bitpos, unsignedp, packedp,
+ op0 = extract_bit_field (op0, bitsize, bitpos, unsignedp,
(modifier == EXPAND_STACK_PARM
? NULL_RTX : target),
ext_mode, ext_mode);
diff --git a/gcc/expr.h b/gcc/expr.h
index 15fcb471d8d..56f504ac155 100644
--- a/gcc/expr.h
+++ b/gcc/expr.h
@@ -28,7 +28,7 @@ along with GCC; see the file COPYING3. If not see
#include "flags.h"
/* For host_integerp, tree_low_cst, fold_convert, size_binop, ssize_int,
TREE_CODE, TYPE_SIZE, int_size_in_bytes, */
-#include "tree.h"
+#include "tree-core.h"
/* For GET_MODE_BITSIZE, word_mode */
#include "machmode.h"
@@ -704,7 +704,7 @@ extern void store_bit_field (rtx, unsigned HOST_WIDE_INT,
unsigned HOST_WIDE_INT,
enum machine_mode, rtx);
extern rtx extract_bit_field (rtx, unsigned HOST_WIDE_INT,
- unsigned HOST_WIDE_INT, int, bool, rtx,
+ unsigned HOST_WIDE_INT, int, rtx,
enum machine_mode, enum machine_mode);
extern rtx extract_low_bits (enum machine_mode, enum machine_mode, rtx);
extern rtx expand_mult (enum machine_mode, rtx, rtx, rtx, int);
diff --git a/gcc/file-find.c b/gcc/file-find.c
index bc6b4349ef5..3952349e989 100644
--- a/gcc/file-find.c
+++ b/gcc/file-find.c
@@ -25,7 +25,7 @@ along with GCC; see the file COPYING3. If not see
static bool debug = false;
void
-find_file_set_debug(bool debug_state)
+find_file_set_debug (bool debug_state)
{
debug = debug_state;
}
diff --git a/gcc/final.c b/gcc/final.c
index c25f7566567..39947329650 100644
--- a/gcc/final.c
+++ b/gcc/final.c
@@ -70,14 +70,15 @@ along with GCC; see the file COPYING3. If not see
#include "debug.h"
#include "expr.h"
#include "tree-pass.h"
-#include "tree-ssa.h"
#include "cgraph.h"
+#include "tree-ssa.h"
#include "coverage.h"
#include "df.h"
#include "ggc.h"
#include "cfgloop.h"
#include "params.h"
#include "tree-pretty-print.h" /* for dump_function_header */
+#include "asan.h"
#ifdef XCOFF_DEBUGGING_INFO
#include "xcoffout.h" /* Needed for external data
@@ -704,7 +705,7 @@ compute_alignments (void)
freq_threshold = freq_max / PARAM_VALUE (PARAM_ALIGN_THRESHOLD);
if (dump_file)
- fprintf(dump_file, "freq_max: %i\n",freq_max);
+ fprintf (dump_file, "freq_max: %i\n",freq_max);
FOR_EACH_BB (bb)
{
rtx label = BB_HEAD (bb);
@@ -716,9 +717,10 @@ compute_alignments (void)
|| optimize_bb_for_size_p (bb))
{
if (dump_file)
- fprintf(dump_file, "BB %4i freq %4i loop %2i loop_depth %2i skipped.\n",
- bb->index, bb->frequency, bb->loop_father->num,
- bb_loop_depth (bb));
+ fprintf (dump_file,
+ "BB %4i freq %4i loop %2i loop_depth %2i skipped.\n",
+ bb->index, bb->frequency, bb->loop_father->num,
+ bb_loop_depth (bb));
continue;
}
max_log = LABEL_ALIGN (label);
@@ -733,10 +735,11 @@ compute_alignments (void)
}
if (dump_file)
{
- fprintf(dump_file, "BB %4i freq %4i loop %2i loop_depth %2i fall %4i branch %4i",
- bb->index, bb->frequency, bb->loop_father->num,
- bb_loop_depth (bb),
- fallthru_frequency, branch_frequency);
+ fprintf (dump_file, "BB %4i freq %4i loop %2i loop_depth"
+ " %2i fall %4i branch %4i",
+ bb->index, bb->frequency, bb->loop_father->num,
+ bb_loop_depth (bb),
+ fallthru_frequency, branch_frequency);
if (!bb->loop_father->inner && bb->loop_father->num)
fprintf (dump_file, " inner_loop");
if (bb->loop_father->header == bb)
@@ -762,7 +765,7 @@ compute_alignments (void)
{
log = JUMP_ALIGN (label);
if (dump_file)
- fprintf(dump_file, " jump alignment added.\n");
+ fprintf (dump_file, " jump alignment added.\n");
if (max_log < log)
{
max_log = log;
@@ -779,7 +782,7 @@ compute_alignments (void)
{
log = LOOP_ALIGN (label);
if (dump_file)
- fprintf(dump_file, " internal loop alignment added.\n");
+ fprintf (dump_file, " internal loop alignment added.\n");
if (max_log < log)
{
max_log = log;
@@ -862,8 +865,8 @@ const pass_data pass_data_compute_alignments =
class pass_compute_alignments : public rtl_opt_pass
{
public:
- pass_compute_alignments(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_compute_alignments, ctxt)
+ pass_compute_alignments (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_compute_alignments, ctxt)
{}
/* opt_pass methods: */
@@ -1123,7 +1126,7 @@ shorten_branches (rtx first)
INSN_ADDRESSES (uid) = insn_current_address + insn_lengths[uid];
if (NOTE_P (insn) || BARRIER_P (insn)
- || LABEL_P (insn) || DEBUG_INSN_P(insn))
+ || LABEL_P (insn) || DEBUG_INSN_P (insn))
continue;
if (INSN_DELETED_P (insn))
continue;
@@ -1736,6 +1739,9 @@ final_start_function (rtx first, FILE *file,
high_block_linenum = high_function_linenum = last_linenum;
+ if (flag_sanitize & SANITIZE_ADDRESS)
+ asan_function_start ();
+
if (!DECL_IGNORED_P (current_function_decl))
debug_hooks->begin_prologue (last_linenum, last_filename);
@@ -4489,8 +4495,8 @@ const pass_data pass_data_final =
class pass_final : public rtl_opt_pass
{
public:
- pass_final(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_final, ctxt)
+ pass_final (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_final, ctxt)
{}
/* opt_pass methods: */
@@ -4535,8 +4541,8 @@ const pass_data pass_data_shorten_branches =
class pass_shorten_branches : public rtl_opt_pass
{
public:
- pass_shorten_branches(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_shorten_branches, ctxt)
+ pass_shorten_branches (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_shorten_branches, ctxt)
{}
/* opt_pass methods: */
@@ -4699,8 +4705,8 @@ const pass_data pass_data_clean_state =
class pass_clean_state : public rtl_opt_pass
{
public:
- pass_clean_state(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_clean_state, ctxt)
+ pass_clean_state (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_clean_state, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/fixed-value.c b/gcc/fixed-value.c
index 8ba78769c79..91ec5880119 100644
--- a/gcc/fixed-value.c
+++ b/gcc/fixed-value.c
@@ -97,7 +97,7 @@ fixed_from_double_int (double_int payload, enum machine_mode mode)
else if (UNSIGNED_SCALAR_FIXED_POINT_MODE_P (mode))
value.data = payload.zext (GET_MODE_IBIT (mode) + GET_MODE_FBIT (mode));
else
- gcc_unreachable();
+ gcc_unreachable ();
value.mode = mode;
diff --git a/gcc/flag-types.h b/gcc/flag-types.h
index 45616bc74f5..7d0ac3582e4 100644
--- a/gcc/flag-types.h
+++ b/gcc/flag-types.h
@@ -191,6 +191,15 @@ enum fp_contract_mode {
FP_CONTRACT_FAST = 2
};
+/* Vectorizer cost-model. */
+enum vect_cost_model {
+ VECT_COST_MODEL_UNLIMITED = 0,
+ VECT_COST_MODEL_CHEAP = 1,
+ VECT_COST_MODEL_DYNAMIC = 2,
+ VECT_COST_MODEL_DEFAULT = 3
+};
+
+
/* Different instrumentation modes. */
enum sanitize_code {
/* AddressSanitizer. */
@@ -201,7 +210,9 @@ enum sanitize_code {
SANITIZE_SHIFT = 1 << 2,
SANITIZE_DIVIDE = 1 << 3,
SANITIZE_UNREACHABLE = 1 << 4,
+ SANITIZE_VLA = 1 << 5,
SANITIZE_UNDEFINED = SANITIZE_SHIFT | SANITIZE_DIVIDE | SANITIZE_UNREACHABLE
+ | SANITIZE_VLA
};
/* flag_vtable_verify initialization levels. */
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index d23c1737ed3..3e6f15887db 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -58,7 +58,7 @@ along with GCC; see the file COPYING3. If not see
#include "langhooks.h"
#include "md5.h"
#include "gimple.h"
-#include "tree-ssa.h"
+#include "tree-dfa.h"
/* Nonzero if we are folding constants inside an initializer; zero
otherwise. */
@@ -2693,8 +2693,9 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
&& operand_equal_p (TYPE_SIZE (TREE_TYPE (arg0)),
TYPE_SIZE (TREE_TYPE (arg1)), flags)))
&& types_compatible_p (TREE_TYPE (arg0), TREE_TYPE (arg1))
- && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (arg0, 1)))
- == TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (arg1, 1))))
+ && alias_ptr_types_compatible_p
+ (TREE_TYPE (TREE_OPERAND (arg0, 1)),
+ TREE_TYPE (TREE_OPERAND (arg1, 1)))
&& OP_SAME (0) && OP_SAME (1));
case ARRAY_REF:
@@ -2714,10 +2715,11 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
case COMPONENT_REF:
/* Handle operand 2 the same as for ARRAY_REF. Operand 0
may be NULL when we're called to compare MEM_EXPRs. */
- if (!OP_SAME_WITH_NULL (0))
+ if (!OP_SAME_WITH_NULL (0)
+ || !OP_SAME (1))
return 0;
flags &= ~OEP_CONSTANT_ADDRESS_OF;
- return OP_SAME (1) && OP_SAME_WITH_NULL (2);
+ return OP_SAME_WITH_NULL (2);
case BIT_FIELD_REF:
if (!OP_SAME (0))
@@ -3471,11 +3473,6 @@ optimize_bit_field_compare (location_t loc, enum tree_code code,
tree mask;
tree offset;
- /* In the strict volatile bitfields case, doing code changes here may prevent
- other optimizations, in particular in a SLOW_BYTE_ACCESS setting. */
- if (flag_strict_volatile_bitfields > 0)
- return 0;
-
/* Get all the information about the extractions being done. If the bit size
if the same as the size of the underlying object, we aren't doing an
extraction at all and so can do nothing. We also don't want to
@@ -3484,7 +3481,7 @@ optimize_bit_field_compare (location_t loc, enum tree_code code,
linner = get_inner_reference (lhs, &lbitsize, &lbitpos, &offset, &lmode,
&lunsignedp, &lvolatilep, false);
if (linner == lhs || lbitsize == GET_MODE_BITSIZE (lmode) || lbitsize < 0
- || offset != 0 || TREE_CODE (linner) == PLACEHOLDER_EXPR)
+ || offset != 0 || TREE_CODE (linner) == PLACEHOLDER_EXPR || lvolatilep)
return 0;
if (!const_p)
@@ -3496,22 +3493,17 @@ optimize_bit_field_compare (location_t loc, enum tree_code code,
if (rinner == rhs || lbitpos != rbitpos || lbitsize != rbitsize
|| lunsignedp != runsignedp || offset != 0
- || TREE_CODE (rinner) == PLACEHOLDER_EXPR)
+ || TREE_CODE (rinner) == PLACEHOLDER_EXPR || rvolatilep)
return 0;
}
/* See if we can find a mode to refer to this field. We should be able to,
but fail if we can't. */
- if (lvolatilep
- && GET_MODE_BITSIZE (lmode) > 0
- && flag_strict_volatile_bitfields > 0)
- nmode = lmode;
- else
- nmode = get_best_mode (lbitsize, lbitpos, 0, 0,
- const_p ? TYPE_ALIGN (TREE_TYPE (linner))
- : MIN (TYPE_ALIGN (TREE_TYPE (linner)),
- TYPE_ALIGN (TREE_TYPE (rinner))),
- word_mode, lvolatilep || rvolatilep);
+ nmode = get_best_mode (lbitsize, lbitpos, 0, 0,
+ const_p ? TYPE_ALIGN (TREE_TYPE (linner))
+ : MIN (TYPE_ALIGN (TREE_TYPE (linner)),
+ TYPE_ALIGN (TREE_TYPE (rinner))),
+ word_mode, false);
if (nmode == VOIDmode)
return 0;
@@ -3600,11 +3592,6 @@ optimize_bit_field_compare (location_t loc, enum tree_code code,
appropriate number of bits and mask it with the computed mask
(in case this was a signed field). If we changed it, make a new one. */
lhs = make_bit_field_ref (loc, linner, unsigned_type, nbitsize, nbitpos, 1);
- if (lvolatilep)
- {
- TREE_SIDE_EFFECTS (lhs) = 1;
- TREE_THIS_VOLATILE (lhs) = 1;
- }
rhs = const_binop (BIT_AND_EXPR,
const_binop (LSHIFT_EXPR,
@@ -4983,12 +4970,16 @@ fold_range_test (location_t loc, enum tree_code code, tree type,
int in0_p, in1_p, in_p;
tree low0, low1, low, high0, high1, high;
bool strict_overflow_p = false;
- tree lhs = make_range (op0, &in0_p, &low0, &high0, &strict_overflow_p);
- tree rhs = make_range (op1, &in1_p, &low1, &high1, &strict_overflow_p);
- tree tem;
+ tree tem, lhs, rhs;
const char * const warnmsg = G_("assuming signed overflow does not occur "
"when simplifying range test");
+ if (!INTEGRAL_TYPE_P (type))
+ return 0;
+
+ lhs = make_range (op0, &in0_p, &low0, &high0, &strict_overflow_p);
+ rhs = make_range (op1, &in1_p, &low1, &high1, &strict_overflow_p);
+
/* If this is an OR operation, invert both sides; we will invert
again at the end. */
if (or_op)
@@ -8953,6 +8944,17 @@ pointer_may_wrap_p (tree base, tree offset, HOST_WIDE_INT bitpos)
return total.low > (unsigned HOST_WIDE_INT) size;
}
+/* Return the HOST_WIDE_INT least significant bits of T, a sizetype
+ kind INTEGER_CST. This makes sure to properly sign-extend the
+ constant. */
+
+static HOST_WIDE_INT
+size_low_cst (const_tree t)
+{
+ double_int d = tree_to_double_int (t);
+ return d.sext (TYPE_PRECISION (TREE_TYPE (t))).low;
+}
+
/* Subroutine of fold_binary. This routine performs all of the
transformations that are common to the equality/inequality
operators (EQ_EXPR and NE_EXPR) and the ordering operators
@@ -9960,6 +9962,117 @@ mask_with_tz (tree type, double_int x, double_int y)
return x;
}
+/* Return true when T is an address and is known to be nonzero.
+ For floating point we further ensure that T is not denormal.
+ Similar logic is present in nonzero_address in rtlanal.h.
+
+ If the return value is based on the assumption that signed overflow
+ is undefined, set *STRICT_OVERFLOW_P to true; otherwise, don't
+ change *STRICT_OVERFLOW_P. */
+
+static bool
+tree_expr_nonzero_warnv_p (tree t, bool *strict_overflow_p)
+{
+ tree type = TREE_TYPE (t);
+ enum tree_code code;
+
+ /* Doing something useful for floating point would need more work. */
+ if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
+ return false;
+
+ code = TREE_CODE (t);
+ switch (TREE_CODE_CLASS (code))
+ {
+ case tcc_unary:
+ return tree_unary_nonzero_warnv_p (code, type, TREE_OPERAND (t, 0),
+ strict_overflow_p);
+ case tcc_binary:
+ case tcc_comparison:
+ return tree_binary_nonzero_warnv_p (code, type,
+ TREE_OPERAND (t, 0),
+ TREE_OPERAND (t, 1),
+ strict_overflow_p);
+ case tcc_constant:
+ case tcc_declaration:
+ case tcc_reference:
+ return tree_single_nonzero_warnv_p (t, strict_overflow_p);
+
+ default:
+ break;
+ }
+
+ switch (code)
+ {
+ case TRUTH_NOT_EXPR:
+ return tree_unary_nonzero_warnv_p (code, type, TREE_OPERAND (t, 0),
+ strict_overflow_p);
+
+ case TRUTH_AND_EXPR:
+ case TRUTH_OR_EXPR:
+ case TRUTH_XOR_EXPR:
+ return tree_binary_nonzero_warnv_p (code, type,
+ TREE_OPERAND (t, 0),
+ TREE_OPERAND (t, 1),
+ strict_overflow_p);
+
+ case COND_EXPR:
+ case CONSTRUCTOR:
+ case OBJ_TYPE_REF:
+ case ASSERT_EXPR:
+ case ADDR_EXPR:
+ case WITH_SIZE_EXPR:
+ case SSA_NAME:
+ return tree_single_nonzero_warnv_p (t, strict_overflow_p);
+
+ case COMPOUND_EXPR:
+ case MODIFY_EXPR:
+ case BIND_EXPR:
+ return tree_expr_nonzero_warnv_p (TREE_OPERAND (t, 1),
+ strict_overflow_p);
+
+ case SAVE_EXPR:
+ return tree_expr_nonzero_warnv_p (TREE_OPERAND (t, 0),
+ strict_overflow_p);
+
+ case CALL_EXPR:
+ {
+ tree fndecl = get_callee_fndecl (t);
+ if (!fndecl) return false;
+ if (flag_delete_null_pointer_checks && !flag_check_new
+ && DECL_IS_OPERATOR_NEW (fndecl)
+ && !TREE_NOTHROW (fndecl))
+ return true;
+ if (flag_delete_null_pointer_checks
+ && lookup_attribute ("returns_nonnull",
+ TYPE_ATTRIBUTES (TREE_TYPE (fndecl))))
+ return true;
+ return alloca_call_p (t);
+ }
+
+ default:
+ break;
+ }
+ return false;
+}
+
+/* Return true when T is an address and is known to be nonzero.
+ Handle warnings about undefined signed overflow. */
+
+static bool
+tree_expr_nonzero_p (tree t)
+{
+ bool ret, strict_overflow_p;
+
+ strict_overflow_p = false;
+ ret = tree_expr_nonzero_warnv_p (t, &strict_overflow_p);
+ if (strict_overflow_p)
+ fold_overflow_warning (("assuming signed overflow does not occur when "
+ "determining that expression is always "
+ "non-zero"),
+ WARN_STRICT_OVERFLOW_MISC);
+ return ret;
+}
+
/* Fold a binary expression of code CODE and type TYPE with operands
OP0 and OP1. LOC is the location of the resulting expression.
Return the folded expression if folding is successful. Otherwise,
@@ -11001,6 +11114,13 @@ fold_binary_loc (location_t loc,
fold_build2_loc (loc, MULT_EXPR, type,
build_int_cst (type, 2) , arg1));
+ /* ((T) (X /[ex] C)) * C cancels out if the conversion is
+ sign-changing only. */
+ if (TREE_CODE (arg1) == INTEGER_CST
+ && TREE_CODE (arg0) == EXACT_DIV_EXPR
+ && operand_equal_p (arg1, TREE_OPERAND (arg0, 1), 0))
+ return fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
+
strict_overflow_p = false;
if (TREE_CODE (arg1) == INTEGER_CST
&& 0 != (tem = extract_muldiv (op0, arg1, code, NULL_TREE,
@@ -11710,8 +11830,8 @@ fold_binary_loc (location_t loc,
if (TREE_CODE (arg1) == INTEGER_CST)
{
double_int cst1 = tree_to_double_int (arg1);
- double_int ncst1 = (-cst1).ext(TYPE_PRECISION (TREE_TYPE (arg1)),
- TYPE_UNSIGNED (TREE_TYPE (arg1)));
+ double_int ncst1 = (-cst1).ext (TYPE_PRECISION (TREE_TYPE (arg1)),
+ TYPE_UNSIGNED (TREE_TYPE (arg1)));
if ((cst1 & ncst1) == ncst1
&& multiple_of_p (type, arg0,
double_int_to_tree (TREE_TYPE (arg1), ncst1)))
@@ -14195,14 +14315,29 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
&& integer_zerop (op2)
&& (tem = sign_bit_p (TREE_OPERAND (arg0, 0), arg1)))
{
+ /* sign_bit_p looks through both zero and sign extensions,
+ but for this optimization only sign extensions are
+ usable. */
+ tree tem2 = TREE_OPERAND (arg0, 0);
+ while (tem != tem2)
+ {
+ if (TREE_CODE (tem2) != NOP_EXPR
+ || TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (tem2, 0))))
+ {
+ tem = NULL_TREE;
+ break;
+ }
+ tem2 = TREE_OPERAND (tem2, 0);
+ }
/* sign_bit_p only checks ARG1 bits within A's precision.
If <sign bit of A> has wider type than A, bits outside
of A's precision in <sign bit of A> need to be checked.
If they are all 0, this optimization needs to be done
in unsigned A's type, if they are all 1 in signed A's type,
otherwise this can't be done. */
- if (TYPE_PRECISION (TREE_TYPE (tem))
- < TYPE_PRECISION (TREE_TYPE (arg1))
+ if (tem
+ && TYPE_PRECISION (TREE_TYPE (tem))
+ < TYPE_PRECISION (TREE_TYPE (arg1))
&& TYPE_PRECISION (TREE_TYPE (tem))
< TYPE_PRECISION (type))
{
@@ -15231,19 +15366,6 @@ fold_build2_initializer_loc (location_t loc, enum tree_code code,
}
tree
-fold_build3_initializer_loc (location_t loc, enum tree_code code,
- tree type, tree op0, tree op1, tree op2)
-{
- tree result;
- START_FOLD_INIT;
-
- result = fold_build3_loc (loc, code, type, op0, op1, op2);
-
- END_FOLD_INIT;
- return result;
-}
-
-tree
fold_build_call_array_initializer_loc (location_t loc, tree type, tree fn,
int nargs, tree *argarray)
{
@@ -15432,7 +15554,7 @@ tree_unary_nonnegative_warnv_p (enum tree_code code, tree type, tree op0,
if (TREE_CODE (inner_type) == REAL_TYPE)
return tree_expr_nonnegative_warnv_p (op0,
strict_overflow_p);
- if (TREE_CODE (inner_type) == INTEGER_TYPE)
+ if (INTEGRAL_TYPE_P (inner_type))
{
if (TYPE_UNSIGNED (inner_type))
return true;
@@ -15440,12 +15562,12 @@ tree_unary_nonnegative_warnv_p (enum tree_code code, tree type, tree op0,
strict_overflow_p);
}
}
- else if (TREE_CODE (outer_type) == INTEGER_TYPE)
+ else if (INTEGRAL_TYPE_P (outer_type))
{
if (TREE_CODE (inner_type) == REAL_TYPE)
return tree_expr_nonnegative_warnv_p (op0,
strict_overflow_p);
- if (TREE_CODE (inner_type) == INTEGER_TYPE)
+ if (INTEGRAL_TYPE_P (inner_type))
return TYPE_PRECISION (inner_type) < TYPE_PRECISION (outer_type)
&& TYPE_UNSIGNED (inner_type);
}
@@ -15764,7 +15886,7 @@ tree_call_nonnegative_warnv_p (tree type, tree fndecl,
set *STRICT_OVERFLOW_P to true; otherwise, don't change
*STRICT_OVERFLOW_P. */
-bool
+static bool
tree_invalid_nonnegative_warnv_p (tree t, bool *strict_overflow_p)
{
enum tree_code code = TREE_CODE (t);
@@ -16133,105 +16255,6 @@ tree_single_nonzero_warnv_p (tree t, bool *strict_overflow_p)
return false;
}
-/* Return true when T is an address and is known to be nonzero.
- For floating point we further ensure that T is not denormal.
- Similar logic is present in nonzero_address in rtlanal.h.
-
- If the return value is based on the assumption that signed overflow
- is undefined, set *STRICT_OVERFLOW_P to true; otherwise, don't
- change *STRICT_OVERFLOW_P. */
-
-bool
-tree_expr_nonzero_warnv_p (tree t, bool *strict_overflow_p)
-{
- tree type = TREE_TYPE (t);
- enum tree_code code;
-
- /* Doing something useful for floating point would need more work. */
- if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
- return false;
-
- code = TREE_CODE (t);
- switch (TREE_CODE_CLASS (code))
- {
- case tcc_unary:
- return tree_unary_nonzero_warnv_p (code, type, TREE_OPERAND (t, 0),
- strict_overflow_p);
- case tcc_binary:
- case tcc_comparison:
- return tree_binary_nonzero_warnv_p (code, type,
- TREE_OPERAND (t, 0),
- TREE_OPERAND (t, 1),
- strict_overflow_p);
- case tcc_constant:
- case tcc_declaration:
- case tcc_reference:
- return tree_single_nonzero_warnv_p (t, strict_overflow_p);
-
- default:
- break;
- }
-
- switch (code)
- {
- case TRUTH_NOT_EXPR:
- return tree_unary_nonzero_warnv_p (code, type, TREE_OPERAND (t, 0),
- strict_overflow_p);
-
- case TRUTH_AND_EXPR:
- case TRUTH_OR_EXPR:
- case TRUTH_XOR_EXPR:
- return tree_binary_nonzero_warnv_p (code, type,
- TREE_OPERAND (t, 0),
- TREE_OPERAND (t, 1),
- strict_overflow_p);
-
- case COND_EXPR:
- case CONSTRUCTOR:
- case OBJ_TYPE_REF:
- case ASSERT_EXPR:
- case ADDR_EXPR:
- case WITH_SIZE_EXPR:
- case SSA_NAME:
- return tree_single_nonzero_warnv_p (t, strict_overflow_p);
-
- case COMPOUND_EXPR:
- case MODIFY_EXPR:
- case BIND_EXPR:
- return tree_expr_nonzero_warnv_p (TREE_OPERAND (t, 1),
- strict_overflow_p);
-
- case SAVE_EXPR:
- return tree_expr_nonzero_warnv_p (TREE_OPERAND (t, 0),
- strict_overflow_p);
-
- case CALL_EXPR:
- return alloca_call_p (t);
-
- default:
- break;
- }
- return false;
-}
-
-/* Return true when T is an address and is known to be nonzero.
- Handle warnings about undefined signed overflow. */
-
-bool
-tree_expr_nonzero_p (tree t)
-{
- bool ret, strict_overflow_p;
-
- strict_overflow_p = false;
- ret = tree_expr_nonzero_warnv_p (t, &strict_overflow_p);
- if (strict_overflow_p)
- fold_overflow_warning (("assuming signed overflow does not occur when "
- "determining that expression is always "
- "non-zero"),
- WARN_STRICT_OVERFLOW_MISC);
- return ret;
-}
-
/* Given the components of a binary expression CODE, TYPE, OP0 and OP1,
attempt to fold the expression to a constant without modifying TYPE,
OP0 or OP1.
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 0e4d688f975..8e2e10c8539 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,194 @@
+2013-11-07 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/58471
+ * primary.c (gfc_expr_attr): Check for result symbol.
+
+2013-11-06 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
+
+ * gfortran.texi: Fix typo.
+
+2013-11-05 Tobias Burnus <burnus@net-b.de>
+
+ * lang.opt (-Wdate-time): New option
+ * cpp.c (gfc_cpp_option_data): Add warn_date_time.
+ (gfc_cpp_init_options, gfc_cpp_handle_option,
+ gfc_cpp_post_options): Handle it and pass on to libcpp.
+
+2013-11-05 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/58989
+ * check.c (gfc_check_reshape): ensure that shape is a constant
+ expression.
+
+2013-11-05 Tobias Burnus <burnus@net-b.de>
+
+ * lang.opt (fopenmp-simd): New option.
+ * gfortran.h (gfc_option_t): Add gfc_flag_openmp_simd.
+ * options.c (gfc_handle_option): Handle it.
+
+2013-11-04 Ian Lance Taylor <iant@google.com>
+
+ * f95-lang.c (ATTR_LEAF_LIST): Define.
+
+2013-11-04 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/58771
+ * trans-io.c (transfer_expr): If the backend_decl for a derived
+ type is missing, build it with gfc_typenode_for_spec.
+
+2013-11-04 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/57445
+ * trans-expr.c (gfc_conv_class_to_class): Remove spurious
+ assert.
+
+2013-10-29 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/44350
+ * parse.c (parse_spec): Add C1116 constraint
+ check for BLOCK DATA.
+
+2013-10-29 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/58793
+ * trans-types.c (gfc_typenode_for_spec): Add typenode for
+ BT_HOLLERITH. Note that the length is incorrect but unusable.
+
+ PR fortran/58858
+ * target-memory.c (gfc_element_size): Add element sizes for
+ BT_VOID and BT_ASSUMED, using gfc_typenode_for_spec.
+
+2013-10-24 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/44646
+ * trans-stmt.c (struct forall_info): Add do_concurrent field.
+ (gfc_trans_forall_1): Set it for do concurrent.
+ (gfc_trans_forall_loop): Mark those as annot_expr_ivdep_kind.
+
+2013-10-23 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/58793
+ * interface.c (compare_parameter): Reject passing TYPE(*)
+ to CLASS(*).
+
+2013-10-22 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran 57893
+ * class.c : Include target-memory.h.
+ (gfc_find_intrinsic_vtab) Build a minimal expression so that
+ gfc_element_size can be used to obtain the storage size, rather
+ that the kind value.
+
+2013-10-21 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/58803
+ * decl.c (match_ppc_decl): Prevent later
+ double free.
+
+2013-10-17 Andrew MacLeod <amacleod@redhat.com>
+
+ * trans-openmp.c: Include omp-low.h.
+
+2013-10-16 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/58652
+ * interface.c (compare_parameter): Accept passing CLASS(*)
+ to CLASS(*).
+
+2013-10-16 Tobias Burnus <burnus@net-b.de>
+
+ * intrinsic.texi (OpenMP Modules): Update to OpenMPv4.
+ Document omp_proc_bind_kind.
+
+2013-10-15 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/58652
+ * trans-intrinsic.c (conv_intrinsic_move_alloc): Fix handling
+ of CLASS(*) variables.
+
+2013-10-14 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/58658
+ * expr.c (gfc_check_vardef_context): Fix pointer diagnostic
+ for CLASS(*).
+
+2013-10-11 Jakub Jelinek <jakub@redhat.com>
+
+ * trans-openmp.c (gfc_omp_clause_default_ctor,
+ gfc_omp_clause_dtor): Return NULL for OMP_CLAUSE_REDUCTION.
+ * f95-lang.c (ATTR_NULL, DEF_FUNCTION_TYPE_8): Define.
+ * types.def (DEF_FUNCTION_TYPE_8): Document.
+ (BT_FN_VOID_OMPFN_PTR_UINT,
+ BT_FN_VOID_OMPFN_PTR_UINT_LONG_LONG_LONG,
+ BT_FN_VOID_OMPFN_PTR_UINT_LONG_LONG_LONG_LONG,
+ BT_FN_VOID_OMPFN_PTR_OMPCPYFN_LONG_LONG_BOOL_UINT): Remove.
+ (BT_FN_VOID_OMPFN_PTR_UINT_UINT_UINT,
+ BT_FN_VOID_OMPFN_PTR_UINT_LONG_LONG_LONG_UINT,
+ BT_FN_VOID_OMPFN_PTR_UINT_LONG_LONG_LONG_LONG_UINT,
+ BT_FN_BOOL_INT, BT_FN_BOOL_INT_BOOL, BT_FN_VOID_UINT_UINT,
+ BT_FN_VOID_INT_PTR_SIZE_PTR_PTR_PTR,
+ BT_FN_VOID_INT_OMPFN_PTR_SIZE_PTR_PTR_PTR,
+ BT_FN_VOID_OMPFN_PTR_OMPCPYFN_LONG_LONG_BOOL_UINT_PTR): New.
+
+2013-10-10 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/58226
+ * options.c (gfc_get_option_string): Handle zero arg case.
+
+2013-10-02 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/58593
+ * trans-expr.c (gfc_conv_string_tmp): Fix obtaining
+ the byte size of a single character.
+
+2013-10-01 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/58579
+ * trans-expr.c (gfc_conv_string_tmp): Correctly obtain
+ the byte size of a single character.
+
+2013-09-27 Janne Blomqvist <jb@gcc.gnu.org>
+
+ * intrinsic.texi (DATE_AND_TIME): Fix example.
+
+2013-09-25 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/58436
+ * class.c (generate_finalization_wrapper): Handle CLASS(*).
+
+2013-09-25 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/57697
+ PR fortran/58469
+ * resolve.c (generate_component_assignments): Avoid double free
+ at runtime and freeing a still-being used expr.
+
+2013-09-25 Tom Tromey <tromey@redhat.com>
+
+ * Make-lang.in (fortran_OBJS): Use fortran/gfortranspec.o.
+ (gfortranspec.o): Remove.
+ (CFLAGS-fortran/gfortranspec.o): New variable.
+ (GFORTRAN_D_OBJS): Update.
+ ($(F95_PARSER_OBJS), fortran/openmp.o, GFORTRAN_TRANS_DEPS)
+ (fortran/f95-lang.o, fortran/scanner.o, fortran/convert.o)
+ (fortran/frontend-passes.o, fortran/trans.o, fortran/trans-decl.o)
+ (fortran/trans-types, fortran/trans-const.o, fortran/trans-expr.o)
+ (fortran/trans-stmt.o, fortran/trans-openmp.o, fortran/trans-io.o)
+ (fortran/trans-array.o, fortran/trans-intrinsic.o)
+ (fortran/dependency.o, fortran/trans-common.o, fortran/resolve.o)
+ (fortran/data.o, fortran/options.o, fortran/cpp.o)
+ (fortran/scanner.o, fortran/module.o): Remove.
+
+2013-09-25 Tom Tromey <tromey@redhat.com>
+
+ * Make-lang.in (gfortranspec.o): Don't use subshell.
+
+2013-09-23 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/58355
+ * decl.c (check_extended_derived_type): Prevent segfault, modify error
+ message.
+
2013-09-20 Janus Weil <janus@gcc.gnu.org>
PR fortran/58099
@@ -1320,7 +1511,7 @@
(TS 29113 Status): Add TYPE(*) and DIMENSION(..).
(C Interop): Update the section about TS29113.
-2013-02-06 Paul Thomas <pault@gcc.gnu.org>
+2013-02-06 Paul Thomas <pault@gcc.gnu.org>
PR fortran/55789
* trans-array.c (trans_array_constructor): Remove condition
@@ -1417,7 +1608,7 @@
(variable_decl): Remove undeclared type error.
(gfc_match_import): Use renamed instead of original name.
-2013-01-27 Paul Thomas <pault@gcc.gnu.org>
+2013-01-27 Paul Thomas <pault@gcc.gnu.org>
PR fortran/55984
PR fortran/56047
diff --git a/gcc/fortran/Make-lang.in b/gcc/fortran/Make-lang.in
index 47deca61c6f..41abe0f7ef2 100644
--- a/gcc/fortran/Make-lang.in
+++ b/gcc/fortran/Make-lang.in
@@ -67,7 +67,7 @@ F95_OBJS = $(F95_PARSER_OBJS) $(FORTRAN_TARGET_OBJS) \
fortran/trans-intrinsic.o fortran/trans-io.o fortran/trans-openmp.o \
fortran/trans-stmt.o fortran/trans-types.o fortran/frontend-passes.o
-fortran_OBJS = $(F95_OBJS) gfortranspec.o
+fortran_OBJS = $(F95_OBJS) fortran/gfortranspec.o
#
# Define the names for selecting gfortran in LANGUAGES.
@@ -76,14 +76,10 @@ fortran: f951$(exeext)
# Tell GNU make to ignore files by these names if they exist.
.PHONY: fortran
-gfortranspec.o: $(srcdir)/fortran/gfortranspec.c $(SYSTEM_H) $(TM_H) $(GCC_H) \
- $(CONFIG_H) coretypes.h intl.h $(OPTS_H)
- (SHLIB='$(SHLIB)'; \
- $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(DRIVER_DEFINES) \
- $(INCLUDES) $(srcdir)/fortran/gfortranspec.c)
+CFLAGS-fortran/gfortranspec.o += $(DRIVER_DEFINES)
# Create the compiler driver gfortran.
-GFORTRAN_D_OBJS = $(GCC_OBJS) gfortranspec.o
+GFORTRAN_D_OBJS = $(GCC_OBJS) fortran/gfortranspec.o
gfortran$(exeext): $(GFORTRAN_D_OBJS) $(EXTRA_GCC_OBJS) libcommon-target.a \
$(LIBDEPS)
+$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
@@ -312,59 +308,6 @@ fortran.stagefeedback: stageprofile-start
-mv fortran/*$(objext) stagefeedback/fortran
#
-# .o: .h dependencies.
-
-# Everything depends on gfortran.h, but only a few files depend on
-# the other headers. So at some point we'll have to split out
-# which objects depend on what. FIXME
-# TODO: Add dependencies on the backend/tree header files
-
-$(F95_PARSER_OBJS): fortran/gfortran.h fortran/libgfortran.h \
- fortran/intrinsic.h fortran/match.h fortran/constructor.h \
- fortran/parse.h fortran/arith.h fortran/target-memory.h \
- $(CONFIG_H) $(SYSTEM_H) $(TM_H) $(TM_P_H) coretypes.h \
- dumpfile.h $(TREE_H) dumpfile.h $(GGC_H) $(VEC_H) \
- $(FLAGS_H) $(DIAGNOSTIC_H) errors.h $(FUNCTION_H) \
- fortran/iso-c-binding.def fortran/iso-fortran-env.def
-fortran/openmp.o: pointer-set.h $(TARGET_H) toplev.h
-
-GFORTRAN_TRANS_DEPS = fortran/gfortran.h fortran/libgfortran.h \
- fortran/intrinsic.h fortran/trans-array.h \
- fortran/trans-const.h fortran/trans-const.h fortran/trans.h \
- fortran/trans-stmt.h fortran/trans-types.h \
- $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(TM_H) coretypes.h $(GGC_H) \
- fortran/iso-c-binding.def fortran/iso-fortran-env.def
CFLAGS-fortran/cpp.o += $(TARGET_SYSTEM_ROOT_DEFINE)
-fortran/f95-lang.o: $(GFORTRAN_TRANS_DEPS) fortran/mathbuiltins.def \
- gt-fortran-f95-lang.h gtype-fortran.h $(CGRAPH_H) $(TARGET_H) fortran/cpp.h \
- $(BUILTINS_DEF) fortran/types.def \
- $(TM_H) debug.h langhooks.h $(FLAGS_H) $(EXPR_H) $(LANGHOOKS_DEF_H) \
- libfuncs.h expr.h $(DIAGNOSTIC_H)
-fortran/scanner.o: toplev.h fortran/cpp.h
-fortran/convert.o: $(GFORTRAN_TRANS_DEPS) convert.h
-fortran/frontend-passes.o: $(GFORTRAN_TRANS_DEPS)
-fortran/trans.o: $(GFORTRAN_TRANS_DEPS) tree-iterator.h
-fortran/trans-decl.o: $(GFORTRAN_TRANS_DEPS) gt-fortran-trans-decl.h \
- $(CGRAPH_H) $(TARGET_H) $(FUNCTION_H) $(FLAGS_H) $(RTL_H) $(GIMPLE_H) \
- $(TREE_DUMP_H) debug.h pointer-set.h
-fortran/trans-types.o: $(GFORTRAN_TRANS_DEPS) gt-fortran-trans-types.h \
- $(REAL_H) toplev.h $(TARGET_H) $(FLAGS_H) dwarf2out.h
-fortran/trans-const.o: $(GFORTRAN_TRANS_DEPS) realmpfr.h
-fortran/trans-expr.o: $(GFORTRAN_TRANS_DEPS) fortran/dependency.h
-fortran/trans-stmt.o: $(GFORTRAN_TRANS_DEPS) fortran/dependency.h
-fortran/trans-openmp.o: $(GFORTRAN_TRANS_DEPS)
-fortran/trans-io.o: $(GFORTRAN_TRANS_DEPS) gt-fortran-trans-io.h \
- fortran/ioparm.def
-fortran/trans-array.o: $(GFORTRAN_TRANS_DEPS) $(GIMPLE_H)
-fortran/trans-intrinsic.o: $(GFORTRAN_TRANS_DEPS) fortran/mathbuiltins.def \
- gt-fortran-trans-intrinsic.h
-fortran/dependency.o: $(GFORTRAN_TRANS_DEPS) fortran/dependency.h
-fortran/trans-common.o: $(GFORTRAN_TRANS_DEPS) $(TARGET_H) $(RTL_H)
-fortran/resolve.o: fortran/dependency.h fortran/data.h fortran/target-memory.h
-fortran/data.o: fortran/data.h
-fortran/options.o: $(PARAMS_H) $(TARGET_H) fortran/cpp.h
-fortran/cpp.o: fortran/cpp.c incpath.h incpath.o cppbuiltin.h
-fortran/scanner.o: fortran/scanner.h
CFLAGS-fortran/module.o += $(ZLIBINC)
-fortran/module.o: fortran/scanner.h
diff --git a/gcc/fortran/check.c b/gcc/fortran/check.c
index 758639e27af..1508c744724 100644
--- a/gcc/fortran/check.c
+++ b/gcc/fortran/check.c
@@ -3277,7 +3277,7 @@ gfc_check_reshape (gfc_expr *source, gfc_expr *shape,
"than %d elements", &shape->where, GFC_MAX_DIMENSIONS);
return false;
}
- else if (shape->expr_type == EXPR_ARRAY)
+ else if (shape->expr_type == EXPR_ARRAY && gfc_is_constant_expr (shape))
{
gfc_expr *e;
int i, extent;
diff --git a/gcc/fortran/class.c b/gcc/fortran/class.c
index 7117e836156..52b9760b271 100644
--- a/gcc/fortran/class.c
+++ b/gcc/fortran/class.c
@@ -53,6 +53,7 @@ along with GCC; see the file COPYING3. If not see
#include "coretypes.h"
#include "gfortran.h"
#include "constructor.h"
+#include "target-memory.h"
/* Inserts a derived type component reference in a data reference chain.
TS: base type of the ref chain so far, in which we will pick the component
@@ -618,7 +619,7 @@ gfc_build_class_symbol (gfc_typespec *ts, symbol_attribute *attr,
if (!ts->u.derived->attr.unlimited_polymorphic)
fclass->attr.abstract = ts->u.derived->attr.abstract;
fclass->f2k_derived = gfc_get_namespace (NULL, 0);
- if (!gfc_add_flavor (&fclass->attr, FL_DERIVED, NULL,
+ if (!gfc_add_flavor (&fclass->attr, FL_DERIVED, NULL,
&gfc_current_locus))
return false;
@@ -1427,6 +1428,12 @@ generate_finalization_wrapper (gfc_symbol *derived, gfc_namespace *ns,
gfc_expr *ancestor_wrapper = NULL, *rank;
gfc_iterator *iter;
+ if (derived->attr.unlimited_polymorphic)
+ {
+ vtab_final->initializer = gfc_get_null_expr (NULL);
+ return;
+ }
+
/* Search for the ancestor's finalizers. */
if (derived->attr.extension && derived->components
&& (!derived->components->ts.u.derived->attr.abstract
@@ -2129,7 +2136,7 @@ gfc_find_derived_vtab (gfc_symbol *derived)
{
gfc_get_symbol (name, ns, &vtab);
vtab->ts.type = BT_DERIVED;
- if (!gfc_add_flavor (&vtab->attr, FL_VARIABLE, NULL,
+ if (!gfc_add_flavor (&vtab->attr, FL_VARIABLE, NULL,
&gfc_current_locus))
goto cleanup;
vtab->attr.target = 1;
@@ -2146,7 +2153,7 @@ gfc_find_derived_vtab (gfc_symbol *derived)
gfc_symbol *parent = NULL, *parent_vtab = NULL;
gfc_get_symbol (name, ns, &vtype);
- if (!gfc_add_flavor (&vtype->attr, FL_DERIVED, NULL,
+ if (!gfc_add_flavor (&vtype->attr, FL_DERIVED, NULL,
&gfc_current_locus))
goto cleanup;
vtype->attr.access = ACCESS_PUBLIC;
@@ -2450,7 +2457,7 @@ gfc_find_intrinsic_vtab (gfc_typespec *ts)
{
gfc_get_symbol (name, ns, &vtab);
vtab->ts.type = BT_DERIVED;
- if (!gfc_add_flavor (&vtab->attr, FL_VARIABLE, NULL,
+ if (!gfc_add_flavor (&vtab->attr, FL_VARIABLE, NULL,
&gfc_current_locus))
goto cleanup;
vtab->attr.target = 1;
@@ -2467,9 +2474,10 @@ gfc_find_intrinsic_vtab (gfc_typespec *ts)
int hash;
gfc_namespace *sub_ns;
gfc_namespace *contained;
+ gfc_expr *e;
gfc_get_symbol (name, ns, &vtype);
- if (!gfc_add_flavor (&vtype->attr, FL_DERIVED, NULL,
+ if (!gfc_add_flavor (&vtype->attr, FL_DERIVED, NULL,
&gfc_current_locus))
goto cleanup;
vtype->attr.access = ACCESS_PUBLIC;
@@ -2492,12 +2500,16 @@ gfc_find_intrinsic_vtab (gfc_typespec *ts)
c->ts.type = BT_INTEGER;
c->ts.kind = 4;
c->attr.access = ACCESS_PRIVATE;
- if (ts->type == BT_CHARACTER)
- c->initializer = gfc_get_int_expr (gfc_default_integer_kind,
- NULL, charlen*ts->kind);
- else
- c->initializer = gfc_get_int_expr (gfc_default_integer_kind,
- NULL, ts->kind);
+
+ /* Build a minimal expression to make use of
+ target-memory.c/gfc_element_size for 'size'. */
+ e = gfc_get_expr ();
+ e->ts = *ts;
+ e->expr_type = EXPR_VARIABLE;
+ c->initializer = gfc_get_int_expr (gfc_default_integer_kind,
+ NULL,
+ (int)gfc_element_size (e));
+ gfc_free_expr (e);
/* Add component _extends. */
if (!gfc_add_component (vtype, "_extends", &c))
diff --git a/gcc/fortran/cpp.c b/gcc/fortran/cpp.c
index ea53681af0c..8417ddca163 100644
--- a/gcc/fortran/cpp.c
+++ b/gcc/fortran/cpp.c
@@ -100,6 +100,7 @@ struct gfc_cpp_option_data
const char *deps_filename_user; /* -MF <arg> */
int deps_missing_are_generated; /* -MG */
int deps_phony; /* -MP */
+ int warn_date_time; /* -Wdate-time */
const char *multilib; /* -imultilib <dir> */
const char *prefix; /* -iprefix <dir> */
@@ -262,6 +263,7 @@ gfc_cpp_init_options (unsigned int decoded_options_count,
gfc_cpp_option.no_predefined = 0;
gfc_cpp_option.standard_include_paths = 1;
gfc_cpp_option.verbose = 0;
+ gfc_cpp_option.warn_date_time = 0;
gfc_cpp_option.deps = 0;
gfc_cpp_option.deps_skip_system = 0;
gfc_cpp_option.deps_phony = 0;
@@ -359,6 +361,9 @@ gfc_cpp_handle_option (size_t scode, const char *arg, int value ATTRIBUTE_UNUSED
gfc_cpp_option.verbose = value;
break;
+ case OPT_Wdate_time:
+ gfc_cpp_option.warn_date_time = value;
+
case OPT_A:
case OPT_D:
case OPT_U:
@@ -469,6 +474,7 @@ gfc_cpp_post_options (void)
cpp_option->discard_comments_in_macro_exp = gfc_cpp_option.discard_comments_in_macro_exp;
cpp_option->print_include_names = gfc_cpp_option.print_include_names;
cpp_option->preprocessed = gfc_option.flag_preprocessed;
+ cpp_option->warn_date_time = gfc_cpp_option.warn_date_time;
if (gfc_cpp_makedep ())
{
diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c
index 152511962d9..9c9fd4ffbf0 100644
--- a/gcc/fortran/decl.c
+++ b/gcc/fortran/decl.c
@@ -5055,7 +5055,14 @@ match_ppc_decl (void)
if (!gfc_add_proc (&c->attr, name, NULL))
return MATCH_ERROR;
- c->tb = tb;
+ if (num == 1)
+ c->tb = tb;
+ else
+ {
+ c->tb = XCNEW (gfc_typebound_proc);
+ c->tb->where = gfc_current_locus;
+ *c->tb = *tb;
+ }
/* Set interface. */
if (proc_if != NULL)
@@ -7390,6 +7397,7 @@ syntax:
/* Check a derived type that is being extended. */
+
static gfc_symbol*
check_extended_derived_type (char *name)
{
@@ -7401,14 +7409,15 @@ check_extended_derived_type (char *name)
return NULL;
}
+ extended = gfc_find_dt_in_generic (extended);
+
+ /* F08:C428. */
if (!extended)
{
- gfc_error ("No such symbol in TYPE definition at %C");
+ gfc_error ("Symbol '%s' at %C has not been previously defined", name);
return NULL;
}
- extended = gfc_find_dt_in_generic (extended);
-
if (extended->attr.flavor != FL_DERIVED)
{
gfc_error ("'%s' in EXTENDS expression at %C is not a "
diff --git a/gcc/fortran/expr.c b/gcc/fortran/expr.c
index b2af32816e5..df96e5b4d35 100644
--- a/gcc/fortran/expr.c
+++ b/gcc/fortran/expr.c
@@ -4693,7 +4693,6 @@ gfc_check_vardef_context (gfc_expr* e, bool pointer, bool alloc_obj,
bool is_pointer;
bool check_intentin;
bool ptr_component;
- bool unlimited;
symbol_attribute attr;
gfc_ref* ref;
int i;
@@ -4709,8 +4708,6 @@ gfc_check_vardef_context (gfc_expr* e, bool pointer, bool alloc_obj,
sym = e->value.function.esym ? e->value.function.esym : e->symtree->n.sym;
}
- unlimited = e->ts.type == BT_CLASS && UNLIMITED_POLY (sym);
-
attr = gfc_expr_attr (e);
if (!pointer && e->expr_type == EXPR_FUNCTION && attr.pointer)
{
@@ -4750,7 +4747,7 @@ gfc_check_vardef_context (gfc_expr* e, bool pointer, bool alloc_obj,
/* Find out whether the expr is a pointer; this also means following
component references to the last one. */
is_pointer = (attr.pointer || attr.proc_pointer);
- if (pointer && !is_pointer && !unlimited)
+ if (pointer && !is_pointer)
{
if (context)
gfc_error ("Non-POINTER in pointer association context (%s)"
diff --git a/gcc/fortran/f95-lang.c b/gcc/fortran/f95-lang.c
index 7bb2913552c..a70d60d6882 100644
--- a/gcc/fortran/f95-lang.c
+++ b/gcc/fortran/f95-lang.c
@@ -531,7 +531,9 @@ gfc_builtin_function (tree decl)
return decl;
}
-/* So far we need just these 4 attribute types. */
+/* So far we need just these 7 attribute types. */
+#define ATTR_NULL 0
+#define ATTR_LEAF_LIST (ECF_LEAF)
#define ATTR_NOTHROW_LEAF_LIST (ECF_NOTHROW | ECF_LEAF)
#define ATTR_NOTHROW_LEAF_MALLOC_LIST (ECF_NOTHROW | ECF_LEAF | ECF_MALLOC)
#define ATTR_CONST_NOTHROW_LEAF_LIST (ECF_NOTHROW | ECF_LEAF | ECF_CONST)
@@ -618,6 +620,7 @@ gfc_init_builtin_functions (void)
#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_VAR_0(NAME, RETURN) NAME,
#define DEF_POINTER_TYPE(NAME, TYPE) NAME,
#include "types.def"
@@ -630,6 +633,7 @@ gfc_init_builtin_functions (void)
#undef DEF_FUNCTION_TYPE_5
#undef DEF_FUNCTION_TYPE_6
#undef DEF_FUNCTION_TYPE_7
+#undef DEF_FUNCTION_TYPE_8
#undef DEF_FUNCTION_TYPE_VAR_0
#undef DEF_POINTER_TYPE
BT_LAST
@@ -992,6 +996,19 @@ gfc_init_builtin_functions (void)
builtin_types[(int) ARG6], \
builtin_types[(int) ARG7], \
NULL_TREE);
+#define DEF_FUNCTION_TYPE_8(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
+ ARG6, ARG7, ARG8) \
+ builtin_types[(int) ENUM] \
+ = build_function_type_list (builtin_types[(int) RETURN], \
+ builtin_types[(int) ARG1], \
+ builtin_types[(int) ARG2], \
+ builtin_types[(int) ARG3], \
+ builtin_types[(int) ARG4], \
+ builtin_types[(int) ARG5], \
+ builtin_types[(int) ARG6], \
+ builtin_types[(int) ARG7], \
+ builtin_types[(int) ARG8], \
+ NULL_TREE);
#define DEF_FUNCTION_TYPE_VAR_0(ENUM, RETURN) \
builtin_types[(int) ENUM] \
= build_varargs_function_type_list (builtin_types[(int) RETURN], \
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index b28edd80002..af5e68c13ab 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -2286,6 +2286,7 @@ typedef struct
int flag_cray_pointer;
int flag_d_lines;
int gfc_flag_openmp;
+ int gfc_flag_openmp_simd;
int flag_sign_zero;
int flag_stack_arrays;
int flag_module_private;
diff --git a/gcc/fortran/gfortran.texi b/gcc/fortran/gfortran.texi
index ad8caccc4a3..292569b5376 100644
--- a/gcc/fortran/gfortran.texi
+++ b/gcc/fortran/gfortran.texi
@@ -2624,7 +2624,7 @@ other hand, assumed-type assumed-rank dummy arguments
(@code{TYPE(*), DIMENSION(..)}) allow for both scalars and arrays, but
require special code on the callee side to handle the array descriptor.
-@item Assumed-shape arrays (@code{DIMENSION(..)}) as dummy argument
+@item Assumed-rank arrays (@code{DIMENSION(..)}) as dummy argument
allow that scalars and arrays of any rank can be passed as actual
argument. As the Technical Specification does not provide for direct
means to operate with them, they have to be used either from the C side
diff --git a/gcc/fortran/interface.c b/gcc/fortran/interface.c
index b8786440fbe..0504c904b96 100644
--- a/gcc/fortran/interface.c
+++ b/gcc/fortran/interface.c
@@ -1972,6 +1972,15 @@ compare_parameter (gfc_symbol *formal, gfc_expr *actual,
return 0;
}
+ if (actual->ts.type == BT_ASSUMED && formal->ts.type != BT_ASSUMED)
+ {
+ if (where)
+ gfc_error ("Assumed-type actual argument at %L requires that dummy "
+ "argument '%s' is of assumed type", &actual->where,
+ formal->name);
+ return 0;
+ }
+
/* F2008, 12.5.2.5; IR F08/0073. */
if (formal->ts.type == BT_CLASS && formal->attr.class_ok
&& actual->expr_type != EXPR_NULL
@@ -1990,8 +1999,9 @@ compare_parameter (gfc_symbol *formal, gfc_expr *actual,
if (!gfc_expr_attr (actual).class_ok)
return 0;
- if (!gfc_compare_derived_types (CLASS_DATA (actual)->ts.u.derived,
- CLASS_DATA (formal)->ts.u.derived))
+ if ((!UNLIMITED_POLY (formal) || !UNLIMITED_POLY(actual))
+ && !gfc_compare_derived_types (CLASS_DATA (actual)->ts.u.derived,
+ CLASS_DATA (formal)->ts.u.derived))
{
if (where)
gfc_error ("Actual argument to '%s' at %L must have the same "
diff --git a/gcc/fortran/intrinsic.texi b/gcc/fortran/intrinsic.texi
index db4d748c876..18bd4d241b2 100644
--- a/gcc/fortran/intrinsic.texi
+++ b/gcc/fortran/intrinsic.texi
@@ -3461,7 +3461,7 @@ program test_time_and_date
call date_and_time(TIME=time)
call date_and_time(VALUES=values)
print '(a,2x,a,2x,a)', date, time, zone
- print '(8i5))', values
+ print '(8i5)', values
end program test_time_and_date
@end smallexample
@@ -13177,7 +13177,7 @@ Both are equivalent to the value @code{NULL} in C.
@section OpenMP Modules @code{OMP_LIB} and @code{OMP_LIB_KINDS}
@table @asis
@item @emph{Standard}:
-OpenMP Application Program Interface v3.1
+OpenMP Application Program Interface v4.0
@end table
@@ -13190,8 +13190,8 @@ the named constants defined in the modules are listed
below.
For details refer to the actual
-@uref{http://www.openmp.org/mp-documents/spec31.pdf,
-OpenMP Application Program Interface v3.1}.
+@uref{http://www.openmp.org/mp-documents/OpenMP4.0.0.pdf,
+OpenMP Application Program Interface v4.0}.
@code{OMP_LIB_KINDS} provides the following scalar default-integer
named constants:
@@ -13199,15 +13199,17 @@ named constants:
@table @asis
@item @code{omp_lock_kind}
@item @code{omp_nest_lock_kind}
+@item @code{omp_proc_bind_kind}
@item @code{omp_sched_kind}
@end table
@code{OMP_LIB} provides the scalar default-integer
named constant @code{openmp_version} with a value of the form
@var{yyyymm}, where @code{yyyy} is the year and @var{mm} the month
-of the OpenMP version; for OpenMP v3.1 the value is @code{201107}.
+of the OpenMP version; for OpenMP v3.1 the value is @code{201107}
+and for OpenMP v4.0 the value is @code{201307}.
-And the following scalar integer named constants of the
+The following scalar integer named constants of the
kind @code{omp_sched_kind}:
@table @asis
@@ -13216,3 +13218,14 @@ kind @code{omp_sched_kind}:
@item @code{omp_sched_guided}
@item @code{omp_sched_auto}
@end table
+
+And the following scalar integer named constants of the
+kind @code{omp_proc_bind_kind}:
+
+@table @asis
+@item @code{omp_proc_bind_false}
+@item @code{omp_proc_bind_true}
+@item @code{omp_proc_bind_master}
+@item @code{omp_proc_bind_close}
+@item @code{omp_proc_bind_spread}
+@end table
diff --git a/gcc/fortran/lang.opt b/gcc/fortran/lang.opt
index 4f7993433d4..5e09cbd1459 100644
--- a/gcc/fortran/lang.opt
+++ b/gcc/fortran/lang.opt
@@ -213,6 +213,10 @@ Wc-binding-type
Fortran Warning
Warn if the type of a variable might be not interoperable with C
+Wdate-time
+Fortran
+; Documented in C
+
Wcharacter-truncation
Fortran Warning
Warn about truncated character expressions
@@ -517,6 +521,10 @@ fopenmp
Fortran
; Documented in C
+fopenmp-simd
+Fortran
+; Documented in C
+
fpack-derived
Fortran
Try to lay out derived types as compactly as possible
diff --git a/gcc/fortran/options.c b/gcc/fortran/options.c
index 3a9c508dc27..e05528a9223 100644
--- a/gcc/fortran/options.c
+++ b/gcc/fortran/options.c
@@ -836,6 +836,10 @@ gfc_handle_option (size_t scode, const char *arg, int value,
gfc_option.gfc_flag_openmp = value;
break;
+ case OPT_fopenmp_simd:
+ gfc_option.gfc_flag_openmp_simd = value;
+ break;
+
case OPT_ffree_line_length_none:
gfc_option.free_line_length = 0;
break;
@@ -1166,6 +1170,10 @@ gfc_get_option_string (void)
size_t len, pos;
char *result;
+ /* Allocate and return a one-character string with '\0'. */
+ if (!save_decoded_options_count)
+ return XCNEWVEC (char, 1);
+
/* Determine required string length. */
len = 0;
diff --git a/gcc/fortran/parse.c b/gcc/fortran/parse.c
index 512babfd450..e8b988558a8 100644
--- a/gcc/fortran/parse.c
+++ b/gcc/fortran/parse.c
@@ -2628,6 +2628,33 @@ loop:
default:
break;
}
+ else if (gfc_current_state () == COMP_BLOCK_DATA)
+ /* Fortran 2008, C1116. */
+ switch (st)
+ {
+ case ST_DATA_DECL:
+ case ST_COMMON:
+ case ST_DATA:
+ case ST_TYPE:
+ case ST_END_BLOCK_DATA:
+ case ST_ATTR_DECL:
+ case ST_EQUIVALENCE:
+ case ST_PARAMETER:
+ case ST_IMPLICIT:
+ case ST_IMPLICIT_NONE:
+ case ST_DERIVED_DECL:
+ case ST_USE:
+ break;
+
+ case ST_NONE:
+ break;
+
+ default:
+ gfc_error ("%s statement is not allowed inside of BLOCK DATA at %C",
+ gfc_ascii_statement (st));
+ reject_statement ();
+ break;
+ }
/* If we find a statement that can not be followed by an IMPLICIT statement
(and thus we can expect to see none any further), type the function result
diff --git a/gcc/fortran/primary.c b/gcc/fortran/primary.c
index 80d45eaea12..c9a26b09be4 100644
--- a/gcc/fortran/primary.c
+++ b/gcc/fortran/primary.c
@@ -2258,7 +2258,7 @@ gfc_expr_attr (gfc_expr *e)
case EXPR_FUNCTION:
gfc_clear_attr (&attr);
- if (e->value.function.esym != NULL)
+ if (e->value.function.esym && e->value.function.esym->result)
{
gfc_symbol *sym = e->value.function.esym->result;
attr = sym->attr;
diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
index d33fe49b661..4befb9fdda4 100644
--- a/gcc/fortran/resolve.c
+++ b/gcc/fortran/resolve.c
@@ -9602,8 +9602,9 @@ generate_component_assignments (gfc_code **code, gfc_namespace *ns)
&& gfc_expr_attr ((*code)->expr1).allocatable)
{
gfc_code *block;
- gfc_expr *cond;
- cond = gfc_get_expr ();
+ gfc_expr *cond;
+
+ cond = gfc_get_expr ();
cond->ts.type = BT_LOGICAL;
cond->ts.kind = gfc_default_logical_kind;
cond->expr_type = EXPR_OP;
@@ -9621,7 +9622,7 @@ generate_component_assignments (gfc_code **code, gfc_namespace *ns)
add_code_to_chain (&block, &head, &tail);
}
}
- }
+ }
else if (this_code->op == EXEC_ASSIGN && !this_code->next)
{
/* Don't add intrinsic assignments since they are already
@@ -9643,13 +9644,6 @@ generate_component_assignments (gfc_code **code, gfc_namespace *ns)
}
}
- /* This is probably not necessary. */
- if (this_code)
- {
- gfc_free_statements (this_code);
- this_code = NULL;
- }
-
/* Put the temporary assignments at the top of the generated code. */
if (tmp_head && component_assignment_level == 1)
{
@@ -9658,6 +9652,28 @@ generate_component_assignments (gfc_code **code, gfc_namespace *ns)
tmp_head = tmp_tail = NULL;
}
+ // If we did a pointer assignment - thus, we need to ensure that the LHS is
+ // not accidentally deallocated. Hence, nullify t1.
+ if (t1 && (*code)->expr1->symtree->n.sym->attr.allocatable
+ && gfc_expr_attr ((*code)->expr1).allocatable)
+ {
+ gfc_code *block;
+ gfc_expr *cond;
+ gfc_expr *e;
+
+ e = gfc_lval_expr_from_sym ((*code)->expr1->symtree->n.sym);
+ cond = gfc_build_intrinsic_call (ns, GFC_ISYM_ASSOCIATED, "associated",
+ (*code)->loc, 2, gfc_copy_expr (t1), e);
+ block = gfc_get_code (EXEC_IF);
+ block->block = gfc_get_code (EXEC_IF);
+ block->block->expr1 = cond;
+ block->block->next = build_assignment (EXEC_POINTER_ASSIGN,
+ t1, gfc_get_null_expr (&(*code)->loc),
+ NULL, NULL, (*code)->loc);
+ gfc_append_code (tail, block);
+ tail = block;
+ }
+
/* Now attach the remaining code chain to the input code. Step on
to the end of the new code since resolution is complete. */
gcc_assert ((*code)->op == EXEC_ASSIGN);
@@ -9667,7 +9683,8 @@ generate_component_assignments (gfc_code **code, gfc_namespace *ns)
gfc_free_expr ((*code)->expr1);
gfc_free_expr ((*code)->expr2);
**code = *head;
- free (head);
+ if (head != tail)
+ free (head);
*code = tail;
component_assignment_level--;
diff --git a/gcc/fortran/target-memory.c b/gcc/fortran/target-memory.c
index 21b44ae482f..e905b3a67dc 100644
--- a/gcc/fortran/target-memory.c
+++ b/gcc/fortran/target-memory.c
@@ -32,7 +32,7 @@ along with GCC; see the file COPYING3. If not see
#include "trans-types.h"
#include "target-memory.h"
-/* --------------------------------------------------------------- */
+/* --------------------------------------------------------------- */
/* Calculate the size of an expression. */
@@ -109,6 +109,8 @@ gfc_element_size (gfc_expr *e)
return e->representation.length;
case BT_DERIVED:
case BT_CLASS:
+ case BT_VOID:
+ case BT_ASSUMED:
{
/* Determine type size without clobbering the typespec for ISO C
binding types. */
@@ -151,7 +153,7 @@ gfc_target_expr_size (gfc_expr *e)
}
-/* The encode_* functions export a value into a buffer, and
+/* The encode_* functions export a value into a buffer, and
return the number of bytes of the buffer that have been
used. */
@@ -286,7 +288,7 @@ gfc_target_encode_expr (gfc_expr *source, unsigned char *buffer,
|| source->expr_type == EXPR_STRUCTURE
|| source->expr_type == EXPR_SUBSTRING);
- /* If we already have a target-memory representation, we use that rather
+ /* If we already have a target-memory representation, we use that rather
than recreating one. */
if (source->representation.string)
{
@@ -496,7 +498,7 @@ gfc_interpret_derived (unsigned char *buffer, size_t buffer_size, gfc_expr *resu
/* Needed as gfc_typenode_for_spec as gfc_typenode_for_spec
sets this to BT_INTEGER. */
result->ts.type = BT_DERIVED;
- e = gfc_get_constant_expr (cmp->ts.type, cmp->ts.kind, &result->where);
+ e = gfc_get_constant_expr (cmp->ts.type, cmp->ts.kind, &result->where);
c = gfc_constructor_append_expr (&result->value.constructor, e, NULL);
c->n.component = cmp;
gfc_target_interpret_expr (buffer, buffer_size, e, true);
@@ -511,7 +513,7 @@ gfc_interpret_derived (unsigned char *buffer, size_t buffer_size, gfc_expr *resu
{
gfc_constructor *c;
gfc_expr *e = gfc_get_constant_expr (cmp->ts.type, cmp->ts.kind,
- &result->where);
+ &result->where);
e->ts = cmp->ts;
/* Copy shape, if needed. */
@@ -551,7 +553,7 @@ gfc_interpret_derived (unsigned char *buffer, size_t buffer_size, gfc_expr *resu
gfc_target_interpret_expr (&buffer[ptr], buffer_size - ptr, e, true);
}
-
+
return int_size_in_bytes (type);
}
@@ -567,31 +569,31 @@ gfc_target_interpret_expr (unsigned char *buffer, size_t buffer_size,
switch (result->ts.type)
{
case BT_INTEGER:
- result->representation.length =
+ result->representation.length =
gfc_interpret_integer (result->ts.kind, buffer, buffer_size,
result->value.integer);
break;
case BT_REAL:
- result->representation.length =
+ result->representation.length =
gfc_interpret_float (result->ts.kind, buffer, buffer_size,
result->value.real);
break;
case BT_COMPLEX:
- result->representation.length =
+ result->representation.length =
gfc_interpret_complex (result->ts.kind, buffer, buffer_size,
result->value.complex);
break;
case BT_LOGICAL:
- result->representation.length =
+ result->representation.length =
gfc_interpret_logical (result->ts.kind, buffer, buffer_size,
&result->value.logical);
break;
case BT_CHARACTER:
- result->representation.length =
+ result->representation.length =
gfc_interpret_character (buffer, buffer_size, result);
break;
@@ -599,7 +601,7 @@ gfc_target_interpret_expr (unsigned char *buffer, size_t buffer_size,
result->ts = CLASS_DATA (result)->ts;
/* Fall through. */
case BT_DERIVED:
- result->representation.length =
+ result->representation.length =
gfc_interpret_derived (buffer, buffer_size, result);
gcc_assert (result->representation.length >= 0);
break;
@@ -626,7 +628,7 @@ gfc_target_interpret_expr (unsigned char *buffer, size_t buffer_size,
}
-/* --------------------------------------------------------------- */
+/* --------------------------------------------------------------- */
/* Two functions used by trans-common.c to write overlapping
equivalence initializers to a buffer. This is added to the union
and the original initializers freed. */
@@ -791,7 +793,7 @@ gfc_convert_boz (gfc_expr *expr, gfc_typespec *ts)
gfc_interpret_complex (ts->kind, buffer, buffer_size,
expr->value.complex);
}
- expr->is_boz = 0;
+ expr->is_boz = 0;
expr->ts.type = ts->type;
expr->ts.kind = ts->kind;
diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c
index 0ecfdfce469..9586ca388e2 100644
--- a/gcc/fortran/trans-expr.c
+++ b/gcc/fortran/trans-expr.c
@@ -737,7 +737,6 @@ gfc_conv_class_to_class (gfc_se *parmse, gfc_expr *e, gfc_typespec class_ts,
gfc_add_modify (&parmse->post, vptr,
fold_convert (TREE_TYPE (vptr), ctree));
- gcc_assert (!optional || (optional && !copyback));
if (optional)
{
tree tmp2;
@@ -2355,11 +2354,15 @@ gfc_conv_string_tmp (gfc_se * se, tree type, tree len)
{
/* Allocate a temporary to hold the result. */
var = gfc_create_var (type, "pstr");
- tmp = gfc_call_malloc (&se->pre, type,
- fold_build2_loc (input_location, MULT_EXPR,
- TREE_TYPE (len), len,
- fold_convert (TREE_TYPE (len),
- TYPE_SIZE (type))));
+ gcc_assert (POINTER_TYPE_P (type));
+ tmp = TREE_TYPE (type);
+ if (TREE_CODE (tmp) == ARRAY_TYPE)
+ tmp = TREE_TYPE (tmp);
+ tmp = TYPE_SIZE_UNIT (tmp);
+ tmp = fold_build2_loc (input_location, MULT_EXPR, size_type_node,
+ fold_convert (size_type_node, len),
+ fold_convert (size_type_node, tmp));
+ tmp = gfc_call_malloc (&se->pre, type, tmp);
gfc_add_modify (&se->pre, var, tmp);
/* Free the temporary afterwards. */
@@ -7765,7 +7768,7 @@ is_runtime_conformable (gfc_expr *expr1, gfc_expr *expr2)
e1 = a->expr;
if (e1->rank > 0 && !is_runtime_conformable (expr1, e1))
return false;
- }
+ }
return true;
}
else if (expr2->value.function.isym
diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c
index 6b85b5b78db..7e2bb36ca6d 100644
--- a/gcc/fortran/trans-intrinsic.c
+++ b/gcc/fortran/trans-intrinsic.c
@@ -7639,7 +7639,8 @@ conv_intrinsic_move_alloc (gfc_code *code)
from_se.expr));
/* Reset _vptr component to declared type. */
- if (UNLIMITED_POLY (from_expr))
+ if (vtab == NULL)
+ /* Unlimited polymorphic. */
gfc_add_modify_loc (input_location, &block, from_se.expr,
fold_convert (TREE_TYPE (from_se.expr),
null_pointer_node));
@@ -7695,7 +7696,8 @@ conv_intrinsic_move_alloc (gfc_code *code)
from_se.expr));
/* Reset _vptr component to declared type. */
- if (UNLIMITED_POLY (from_expr))
+ if (vtab == NULL)
+ /* Unlimited polymorphic. */
gfc_add_modify_loc (input_location, &block, from_se.expr,
fold_convert (TREE_TYPE (from_se.expr),
null_pointer_node));
diff --git a/gcc/fortran/trans-io.c b/gcc/fortran/trans-io.c
index ec17dc97c21..5fa1cdc091e 100644
--- a/gcc/fortran/trans-io.c
+++ b/gcc/fortran/trans-io.c
@@ -243,16 +243,16 @@ gfc_trans_io_runtime_check (tree cond, tree var, int error_code,
/* The code to generate the error. */
gfc_start_block (&block);
-
+
arg1 = gfc_build_addr_expr (NULL_TREE, var);
-
+
arg2 = build_int_cst (integer_type_node, error_code),
-
+
asprintf (&message, "%s", _(msgid));
arg3 = gfc_build_addr_expr (pchar_type_node,
gfc_build_localized_cstring_const (message));
free (message);
-
+
tmp = build_call_expr_loc (input_location,
gfor_fndecl_generate_error, 3, arg1, arg2, arg3);
@@ -521,7 +521,7 @@ set_parameter_value (stmtblock_t *block, tree var, enum iofield type,
gfc_trans_io_runtime_check (cond, var, LIBERROR_BAD_UNIT,
"Unit number in I/O statement too small",
&se.pre);
-
+
/* UNIT numbers should be less than the max. */
val = gfc_conv_mpz_to_tree (gfc_integer_kinds[i].huge, 4);
cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
@@ -1000,7 +1000,7 @@ gfc_trans_open (gfc_code * code)
if (p->convert)
mask |= set_string (&block, &post_block, var, IOPARM_open_convert,
p->convert);
-
+
if (p->newunit)
mask |= set_parameter_ref (&block, &post_block, var, IOPARM_open_newunit,
p->newunit);
@@ -1234,7 +1234,7 @@ gfc_trans_inquire (gfc_code * code)
{
mask |= set_parameter_ref (&block, &post_block, var, IOPARM_inquire_exist,
p->exist);
-
+
if (p->unit && !p->iostat)
{
p->iostat = create_dummy_iostat ();
@@ -1322,7 +1322,7 @@ gfc_trans_inquire (gfc_code * code)
if (p->pad)
mask |= set_string (&block, &post_block, var, IOPARM_inquire_pad,
p->pad);
-
+
if (p->convert)
mask |= set_string (&block, &post_block, var, IOPARM_inquire_convert,
p->convert);
@@ -1547,7 +1547,7 @@ transfer_namelist_element (stmtblock_t * block, const char * var_name,
tree dtype;
tree dt_parm_addr;
tree decl = NULL_TREE;
- int n_dim;
+ int n_dim;
int itype;
int rank = 0;
@@ -2029,7 +2029,7 @@ transfer_expr (gfc_se * se, gfc_typespec * ts, tree addr_expr, gfc_code * code)
ts->type = BT_INTEGER;
ts->kind = gfc_index_integer_kind;
}
-
+
kind = ts->kind;
function = NULL;
arg2 = NULL;
@@ -2111,7 +2111,7 @@ transfer_expr (gfc_se * se, gfc_typespec * ts, tree addr_expr, gfc_code * code)
function = iocall[IOCALL_X_CHARACTER_WIDE];
else
function = iocall[IOCALL_X_CHARACTER_WIDE_WRITE];
-
+
tmp = gfc_build_addr_expr (NULL_TREE, dt_parm);
tmp = build_call_expr_loc (input_location,
function, 4, tmp, addr_expr, arg2, arg3);
@@ -2146,6 +2146,12 @@ transfer_expr (gfc_se * se, gfc_typespec * ts, tree addr_expr, gfc_code * code)
expr = build_fold_indirect_ref_loc (input_location,
expr);
+ /* Make sure that the derived type has been built. An external
+ function, if only referenced in an io statement, requires this
+ check (see PR58771). */
+ if (ts->u.derived->backend_decl == NULL_TREE)
+ tmp = gfc_typenode_for_spec (ts);
+
for (c = ts->u.derived->components; c; c = c->next)
{
field = c->backend_decl;
diff --git a/gcc/fortran/trans-openmp.c b/gcc/fortran/trans-openmp.c
index 2765561e889..bf282498eab 100644
--- a/gcc/fortran/trans-openmp.c
+++ b/gcc/fortran/trans-openmp.c
@@ -32,6 +32,7 @@ along with GCC; see the file COPYING3. If not see
#include "trans-array.h"
#include "trans-const.h"
#include "arith.h"
+#include "omp-low.h"
int ompws_flags;
@@ -159,6 +160,9 @@ gfc_omp_clause_default_ctor (tree clause, tree decl, tree outer)
|| GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
return NULL;
+ if (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_REDUCTION)
+ return NULL;
+
gcc_assert (outer != NULL);
gcc_assert (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_PRIVATE
|| OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_LASTPRIVATE);
@@ -323,6 +327,9 @@ gfc_omp_clause_dtor (tree clause ATTRIBUTE_UNUSED, tree decl)
|| GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
return NULL;
+ if (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_REDUCTION)
+ return NULL;
+
/* Allocatable arrays in FIRSTPRIVATE/LASTPRIVATE etc. clauses need
to be deallocated if they were allocated. */
return gfc_trans_dealloc_allocated (decl, false, NULL);
diff --git a/gcc/fortran/trans-stmt.c b/gcc/fortran/trans-stmt.c
index edd2dacf579..62e690d407c 100644
--- a/gcc/fortran/trans-stmt.c
+++ b/gcc/fortran/trans-stmt.c
@@ -53,6 +53,7 @@ typedef struct forall_info
int nvar;
tree size;
struct forall_info *prev_nest;
+ bool do_concurrent;
}
forall_info;
@@ -2759,6 +2760,11 @@ gfc_trans_forall_loop (forall_info *forall_tmp, tree body,
/* The exit condition. */
cond = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
count, build_int_cst (TREE_TYPE (count), 0));
+ if (forall_tmp->do_concurrent)
+ cond = build2 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
+ build_int_cst (integer_type_node,
+ annot_expr_ivdep_kind));
+
tmp = build1_v (GOTO_EXPR, exit_label);
tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
cond, tmp, build_empty_stmt (input_location));
@@ -3842,6 +3848,7 @@ gfc_trans_forall_1 (gfc_code * code, forall_info * nested_forall_info)
}
tmp = gfc_finish_block (&body);
+ nested_forall_info->do_concurrent = true;
tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
gfc_add_expr_to_block (&block, tmp);
goto done;
diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c
index 806accc7015..fa84d5dab81 100644
--- a/gcc/fortran/trans-types.c
+++ b/gcc/fortran/trans-types.c
@@ -1099,6 +1099,12 @@ gfc_typenode_for_spec (gfc_typespec * spec)
basetype = gfc_get_character_type (spec->kind, spec->u.cl);
break;
+ case BT_HOLLERITH:
+ /* Since this cannot be used, return a length one character. */
+ basetype = gfc_get_character_type_len (gfc_default_character_kind,
+ gfc_index_one_node);
+ break;
+
case BT_DERIVED:
case BT_CLASS:
basetype = gfc_get_derived_type (spec->u.derived);
diff --git a/gcc/fortran/types.def b/gcc/fortran/types.def
index e4cd1d18eb9..9bbee3504fe 100644
--- a/gcc/fortran/types.def
+++ b/gcc/fortran/types.def
@@ -34,6 +34,8 @@ along with GCC; see the file COPYING3. If not see
DEF_FUNCTION_TYPE_5 (ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5)
DEF_FUNCTION_TYPE_6 (ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6)
DEF_FUNCTION_TYPE_7 (ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7)
+ DEF_FUNCTION_TYPE_8 (ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7,
+ ARG8)
These macros describe function types. ENUM is as above. The
RETURN type is one of the enumerals already defined. ARG1, ARG2,
@@ -89,7 +91,7 @@ DEF_FUNCTION_TYPE_1 (BT_FN_VOID_VPTR, BT_VOID, BT_VOLATILE_PTR)
DEF_FUNCTION_TYPE_1 (BT_FN_UINT_UINT, BT_UINT, BT_UINT)
DEF_FUNCTION_TYPE_1 (BT_FN_PTR_PTR, BT_PTR, BT_PTR)
DEF_FUNCTION_TYPE_1 (BT_FN_VOID_INT, BT_VOID, BT_INT)
-
+DEF_FUNCTION_TYPE_1 (BT_FN_BOOL_INT, BT_BOOL, BT_INT)
DEF_POINTER_TYPE (BT_PTR_FN_VOID_PTR, BT_FN_VOID_PTR)
@@ -117,7 +119,8 @@ 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_VOID_UINT_UINT, BT_VOID, BT_UINT, BT_UINT)
DEF_POINTER_TYPE (BT_PTR_FN_VOID_PTR_PTR, BT_FN_VOID_PTR_PTR)
@@ -137,8 +140,6 @@ 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_VOID_OMPFN_PTR_UINT, BT_VOID, BT_PTR_FN_VOID_PTR,
- BT_PTR, BT_UINT)
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)
@@ -159,6 +160,9 @@ DEF_FUNCTION_TYPE_4 (BT_FN_VOID_SIZE_VPTR_PTR_INT, BT_VOID, BT_SIZE,
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_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_LONG_LONG_LONG_LONGPTR_LONGPTR,
BT_BOOL, BT_LONG, BT_LONG, BT_LONG,
BT_PTR_LONG, BT_PTR_LONG)
@@ -168,9 +172,6 @@ DEF_FUNCTION_TYPE_5 (BT_FN_VOID_SIZE_VPTR_PTR_PTR_INT, BT_VOID, BT_SIZE,
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_VOID_OMPFN_PTR_UINT_LONG_LONG_LONG,
- BT_VOID, BT_PTR_FN_VOID_PTR, BT_PTR, BT_UINT,
- BT_LONG, BT_LONG, BT_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)
@@ -191,17 +192,26 @@ DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_VPTR_PTR_I16_BOOL_INT_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_6 (BT_FN_VOID_INT_PTR_SIZE_PTR_PTR_PTR,
+ BT_VOID, BT_INT, BT_PTR, BT_SIZE, BT_PTR, BT_PTR, BT_PTR)
-DEF_FUNCTION_TYPE_7 (BT_FN_VOID_OMPFN_PTR_UINT_LONG_LONG_LONG_LONG,
+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_LONG)
-DEF_FUNCTION_TYPE_7 (BT_FN_VOID_OMPFN_PTR_OMPCPYFN_LONG_LONG_BOOL_UINT,
- BT_VOID, BT_PTR_FN_VOID_PTR, BT_PTR,
- BT_PTR_FN_VOID_PTR_PTR, BT_LONG, BT_LONG,
- BT_BOOL, 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_OMPFN_PTR_SIZE_PTR_PTR_PTR,
+ BT_VOID, BT_INT, BT_PTR_FN_VOID_PTR, BT_PTR, BT_SIZE,
+ BT_PTR, BT_PTR, 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_VOID_OMPFN_PTR_OMPCPYFN_LONG_LONG_BOOL_UINT_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)
DEF_FUNCTION_TYPE_VAR_0 (BT_FN_VOID_VAR, BT_VOID)
diff --git a/gcc/function.c b/gcc/function.c
index c7d259c73ff..a36f152b79a 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -71,14 +71,6 @@ along with GCC; see the file COPYING3. If not see
#define STACK_BYTES (STACK_BOUNDARY / BITS_PER_UNIT)
-/* Some systems use __main in a way incompatible with its use in gcc, in these
- cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
- give the same symbol without quotes for an alternative entry point. You
- must define both, or neither. */
-#ifndef NAME__MAIN
-#define NAME__MAIN "__main"
-#endif
-
/* Round a value to the lowest integer less than it that is a multiple of
the required alignment. Avoid using division in case the value is
negative. Assume the alignment is a power of two. */
@@ -130,7 +122,6 @@ static bool contains (const_rtx, htab_t);
static void prepare_function_start (void);
static void do_clobber_return_reg (rtx, void *);
static void do_use_return_reg (rtx, void *);
-static void set_insn_locations (rtx, int) ATTRIBUTE_UNUSED;
/* Stack of nested functions. */
/* Keep track of the cfun stack. */
@@ -1970,8 +1961,8 @@ const pass_data pass_data_instantiate_virtual_regs =
class pass_instantiate_virtual_regs : public rtl_opt_pass
{
public:
- pass_instantiate_virtual_regs(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_instantiate_virtual_regs, ctxt)
+ pass_instantiate_virtual_regs (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_instantiate_virtual_regs, ctxt)
{}
/* opt_pass methods: */
@@ -2078,7 +2069,7 @@ aggregate_value_p (const_tree exp, const_tree fntype)
bool
use_register_for_decl (const_tree decl)
{
- if (!targetm.calls.allocate_stack_slots_for_args())
+ if (!targetm.calls.allocate_stack_slots_for_args ())
return true;
/* Honor volatile. */
@@ -4128,12 +4119,11 @@ void
reorder_blocks (void)
{
tree block = DECL_INITIAL (current_function_decl);
- vec<tree> block_stack;
if (block == NULL_TREE)
return;
- block_stack.create (10);
+ stack_vec<tree, 10> block_stack;
/* Reset the TREE_ASM_WRITTEN bit for all blocks. */
clear_block_marks (block);
@@ -4145,8 +4135,6 @@ reorder_blocks (void)
/* Recreate the block tree from the note nesting. */
reorder_blocks_1 (get_insns (), block, &block_stack);
BLOCK_SUBBLOCKS (block) = blocks_nreverse_all (BLOCK_SUBBLOCKS (block));
-
- block_stack.release ();
}
/* Helper function for reorder_blocks. Reset TREE_ASM_WRITTEN. */
@@ -4647,51 +4635,6 @@ init_function_start (tree subr)
warning (OPT_Waggregate_return, "function returns an aggregate");
}
-
-void
-expand_main_function (void)
-{
-#if (defined(INVOKE__main) \
- || (!defined(HAS_INIT_SECTION) \
- && !defined(INIT_SECTION_ASM_OP) \
- && !defined(INIT_ARRAY_SECTION_ASM_OP)))
- emit_library_call (init_one_libfunc (NAME__MAIN), LCT_NORMAL, VOIDmode, 0);
-#endif
-}
-
-/* Expand code to initialize the stack_protect_guard. This is invoked at
- the beginning of a function to be protected. */
-
-#ifndef HAVE_stack_protect_set
-# define HAVE_stack_protect_set 0
-# define gen_stack_protect_set(x,y) (gcc_unreachable (), NULL_RTX)
-#endif
-
-void
-stack_protect_prologue (void)
-{
- tree guard_decl = targetm.stack_protect_guard ();
- rtx x, y;
-
- x = expand_normal (crtl->stack_protect_guard);
- y = expand_normal (guard_decl);
-
- /* Allow the target to copy from Y to X without leaking Y into a
- register. */
- if (HAVE_stack_protect_set)
- {
- rtx insn = gen_stack_protect_set (x, y);
- if (insn)
- {
- emit_insn (insn);
- return;
- }
- }
-
- /* Otherwise do a straight move. */
- emit_move_insn (x, y);
-}
-
/* Expand code to verify the stack_protect_guard. This is invoked at
the end of a function to be protected. */
@@ -5009,6 +4952,19 @@ do_warn_unused_parameter (tree fn)
warning (OPT_Wunused_parameter, "unused parameter %q+D", decl);
}
+/* Set the location of the insn chain starting at INSN to LOC. */
+
+static void
+set_insn_locations (rtx insn, int loc)
+{
+ while (insn != NULL_RTX)
+ {
+ if (INSN_P (insn))
+ INSN_LOCATION (insn) = loc;
+ insn = NEXT_INSN (insn);
+ }
+}
+
/* Generate RTL for the end of the current function. */
void
@@ -5338,18 +5294,6 @@ maybe_copy_prologue_epilogue_insn (rtx insn, rtx copy)
*slot = copy;
}
-/* Set the location of the insn chain starting at INSN to LOC. */
-static void
-set_insn_locations (rtx insn, int loc)
-{
- while (insn != NULL_RTX)
- {
- if (INSN_P (insn))
- INSN_LOCATION (insn) = loc;
- insn = NEXT_INSN (insn);
- }
-}
-
/* Determine if any INSNs in HASH are, or are part of, INSN. Because
we can be running after reorg, SEQUENCE rtl is possible. */
@@ -7022,8 +6966,8 @@ const pass_data pass_data_leaf_regs =
class pass_leaf_regs : public rtl_opt_pass
{
public:
- pass_leaf_regs(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_leaf_regs, ctxt)
+ pass_leaf_regs (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_leaf_regs, ctxt)
{}
/* opt_pass methods: */
@@ -7079,8 +7023,8 @@ const pass_data pass_data_thread_prologue_and_epilogue =
class pass_thread_prologue_and_epilogue : public rtl_opt_pass
{
public:
- pass_thread_prologue_and_epilogue(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_thread_prologue_and_epilogue, ctxt)
+ pass_thread_prologue_and_epilogue (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_thread_prologue_and_epilogue, ctxt)
{}
/* opt_pass methods: */
@@ -7298,8 +7242,8 @@ const pass_data pass_data_match_asm_constraints =
class pass_match_asm_constraints : public rtl_opt_pass
{
public:
- pass_match_asm_constraints(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_match_asm_constraints, ctxt)
+ pass_match_asm_constraints (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_match_asm_constraints, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/function.h b/gcc/function.h
index d1f4ffc1fd4..9bb6ff04c50 100644
--- a/gcc/function.h
+++ b/gcc/function.h
@@ -552,6 +552,9 @@ struct GTY(()) function {
/* Vector of function local variables, functions, types and constants. */
vec<tree, va_gc> *local_decls;
+ /* In a Cilk function, the VAR_DECL for the frame descriptor. */
+ tree cilk_frame_decl;
+
/* For md files. */
/* tm.h can use this to store whatever it likes. */
@@ -607,6 +610,12 @@ struct GTY(()) function {
either as a subroutine or builtin. */
unsigned int calls_alloca : 1;
+ /* This will indicate whether a function is a cilk function */
+ unsigned int is_cilk_function : 1;
+
+ /* Nonzero if this is a Cilk function that spawns. */
+ unsigned int calls_cilk_spawn : 1;
+
/* Nonzero if function being compiled receives nonlocal gotos
from nested functions. */
unsigned int has_nonlocal_label : 1;
diff --git a/gcc/fwprop.c b/gcc/fwprop.c
index 137011d3324..d08710c9614 100644
--- a/gcc/fwprop.c
+++ b/gcc/fwprop.c
@@ -1504,8 +1504,8 @@ const pass_data pass_data_rtl_fwprop =
class pass_rtl_fwprop : public rtl_opt_pass
{
public:
- pass_rtl_fwprop(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_rtl_fwprop, ctxt)
+ pass_rtl_fwprop (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_rtl_fwprop, ctxt)
{}
/* opt_pass methods: */
@@ -1570,8 +1570,8 @@ const pass_data pass_data_rtl_fwprop_addr =
class pass_rtl_fwprop_addr : public rtl_opt_pass
{
public:
- pass_rtl_fwprop_addr(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_rtl_fwprop_addr, ctxt)
+ pass_rtl_fwprop_addr (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_rtl_fwprop_addr, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/gcc-ar.c b/gcc/gcc-ar.c
index ef425c1cb30..d7e05e3f35c 100644
--- a/gcc/gcc-ar.c
+++ b/gcc/gcc-ar.c
@@ -123,7 +123,7 @@ setup_prefixes (const char *exec_path)
}
int
-main(int ac, char **av)
+main (int ac, char **av)
{
const char *exe_name;
char *plugin;
@@ -166,7 +166,7 @@ main(int ac, char **av)
nargv[1] = "--plugin";
nargv[2] = plugin;
if (is_ar && av[1] && av[1][0] != '-')
- av[1] = concat("-", av[1], NULL);
+ av[1] = concat ("-", av[1], NULL);
for (k = 1; k < ac; k++)
nargv[2 + k] = av[k];
nargv[2 + k] = NULL;
@@ -176,18 +176,18 @@ main(int ac, char **av)
err_msg = pex_one (PEX_LAST|PEX_SEARCH,
exe_name,
CONST_CAST2 (char * const *, const char **, nargv),
- concat("gcc-", exe_name, NULL),
+ concat ("gcc-", exe_name, NULL),
NULL,NULL, &status, &err);
if (err_msg)
- fprintf(stderr, "Error running %s: %s\n", exe_name, err_msg);
+ fprintf (stderr, "Error running %s: %s\n", exe_name, err_msg);
else if (status)
{
if (WIFSIGNALED (status))
{
int sig = WTERMSIG (status);
fprintf (stderr, "%s terminated with signal %d [%s]%s\n",
- exe_name, sig, strsignal(sig),
- WCOREDUMP(status) ? ", core dumped" : "");
+ exe_name, sig, strsignal (sig),
+ WCOREDUMP (status) ? ", core dumped" : "");
}
else if (WIFEXITED (status))
exit_code = WEXITSTATUS (status);
diff --git a/gcc/gcc.c b/gcc/gcc.c
index d48c4db118b..dff7477f54e 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -388,7 +388,8 @@ or with constant text in a single argument.
%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 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
@@ -422,7 +423,9 @@ or with constant text in a single argument.
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 '*'.
+ 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.
@@ -523,28 +526,12 @@ proper position among the other output files. */
#define LIB_SPEC "%{!shared:%{g*:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}}"
#endif
-/* mudflap specs */
-#ifndef MFWRAP_SPEC
-/* XXX: valid only for GNU ld */
-/* XXX: should exactly match hooks provided by libmudflap.a */
-#define MFWRAP_SPEC " %{static: %{fmudflap|fmudflapth: \
- --wrap=malloc --wrap=free --wrap=calloc --wrap=realloc\
- --wrap=mmap --wrap=mmap64 --wrap=munmap --wrap=alloca\
-} %{fmudflapth: --wrap=pthread_create\
-}} %{fmudflap|fmudflapth: --wrap=main}"
-#endif
-#ifndef MFLIB_SPEC
-#define MFLIB_SPEC "%{fmudflap|fmudflapth: -export-dynamic}"
-#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. FIXME: This is incompatible with
- -fmudflap when linking statically, which wants to do its own
- wrapping. */
+ only works with GNU ld and gold. */
#define STACK_SPLIT_SPEC " %{fsplit-stack: --wrap=pthread_create}"
#ifndef LIBASAN_SPEC
@@ -820,8 +807,6 @@ 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 *mfwrap_spec = MFWRAP_SPEC;
-static const char *mflib_spec = MFLIB_SPEC;
static const char *link_gomp_spec = "";
static const char *libgcc_spec = LIBGCC_SPEC;
static const char *endfile_spec = ENDFILE_SPEC;
@@ -862,8 +847,6 @@ static const char *cpp_unique_options =
%{remap} %{g3|ggdb3|gstabs3|gcoff3|gxcoff3|gvms3:-dD}\
%{!iplugindir*:%{fplugin*:%:find-plugindir()}}\
%{H} %C %{D*&U*&A*} %{i*} %Z %i\
- %{fmudflap:-D_MUDFLAP -include mf-runtime.h}\
- %{fmudflapth:-D_MUDFLAP -D_MUDFLAPTH -include mf-runtime.h}\
%{E|M|MM:%W{o*}}";
/* This contains cpp options which are common with cc1_options and are passed
@@ -895,7 +878,6 @@ static const char *cc1_options =
%{-help=*:--help=%*}\
%{!fsyntax-only:%{S:%W{o*}%{!o*:-o %b.s}}}\
%{fsyntax-only:-o %j} %{-param*}\
- %{fmudflap|fmudflapth:-fno-builtin -fno-merge-constants}\
%{coverage:-fprofile-arcs -ftest-coverage}";
static const char *asm_options =
@@ -942,7 +924,7 @@ static const char *const multilib_defaults_raw[] = MULTILIB_DEFAULTS;
#define DRIVER_SELF_SPECS ""
#endif
-/* Adding -fopenmp should imply pthreads. This is particularly important
+/* 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 "%{fopenmp|ftree-parallelize-loops=*: -pthread}"
@@ -1309,8 +1291,6 @@ static struct spec_list static_specs[] =
INIT_STATIC_SPEC ("endfile", &endfile_spec),
INIT_STATIC_SPEC ("link", &link_spec),
INIT_STATIC_SPEC ("lib", &lib_spec),
- INIT_STATIC_SPEC ("mfwrap", &mfwrap_spec),
- INIT_STATIC_SPEC ("mflib", &mflib_spec),
INIT_STATIC_SPEC ("link_gomp", &link_gomp_spec),
INIT_STATIC_SPEC ("libgcc", &libgcc_spec),
INIT_STATIC_SPEC ("startfile", &startfile_spec),
@@ -1556,7 +1536,7 @@ init_spec (void)
/* Prepend "--traditional-format" to whatever asm_spec we had before. */
{
static const char tf[] = "--traditional-format ";
- obstack_grow (&obstack, tf, sizeof(tf) - 1);
+ obstack_grow (&obstack, tf, sizeof (tf) - 1);
obstack_grow0 (&obstack, asm_spec, strlen (asm_spec));
asm_spec = XOBFINISH (&obstack, const char *);
}
@@ -1566,19 +1546,19 @@ init_spec (void)
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);
+ 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);
+ 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_grow (&obstack, hash_style, sizeof (hash_style) - 1);
+ obstack_grow (&obstack, LINKER_HASH_STYLE, sizeof (LINKER_HASH_STYLE) - 1);
obstack_1grow (&obstack, ' ');
}
# endif
@@ -1644,7 +1624,7 @@ set_spec (const char *name, const char *spec, bool user_p)
/* Free the old spec. */
if (old_spec && sl->alloc_p)
- free (CONST_CAST(char *, old_spec));
+ free (CONST_CAST (char *, old_spec));
sl->user_p = user_p;
sl->alloc_p = true;
@@ -2490,7 +2470,7 @@ find_a_file (const struct path_prefix *pprefix, const char *name, int mode,
#endif
#ifdef DEFAULT_LINKER
- if (! strcmp(name, "ld") && access (DEFAULT_LINKER, mode) == 0)
+ if (! strcmp (name, "ld") && access (DEFAULT_LINKER, mode) == 0)
return xstrdup (DEFAULT_LINKER);
#endif
@@ -5375,7 +5355,17 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
{
if (soft_matched_part[0])
do_spec_1 (soft_matched_part, 1, NULL);
- do_spec_1 (" ", 0, 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
@@ -5741,11 +5731,11 @@ handle_braces (const char *p)
a_is_negated = false;
a_is_spectype = false;
- SKIP_WHITE();
+ SKIP_WHITE ();
if (*p == '!')
p++, a_is_negated = true;
- SKIP_WHITE();
+ SKIP_WHITE ();
if (*p == '%' && p[1] == ':')
{
atom = NULL;
@@ -5760,7 +5750,7 @@ handle_braces (const char *p)
p++, a_is_spectype = true;
atom = p;
- while (ISIDNUM(*p) || *p == '-' || *p == '+' || *p == '='
+ while (ISIDNUM (*p) || *p == '-' || *p == '+' || *p == '='
|| *p == ',' || *p == '.' || *p == '@')
p++;
end_atom = p;
@@ -5769,7 +5759,7 @@ handle_braces (const char *p)
p++, a_is_starred = 1;
}
- SKIP_WHITE();
+ SKIP_WHITE ();
switch (*p)
{
case '&': case '}':
@@ -6074,13 +6064,13 @@ give_switch (int switchnum, int omit_first_word)
while (length-- && !IS_DIR_SEPARATOR (arg[length]))
if (arg[length] == '.')
{
- (CONST_CAST(char *, arg))[length] = 0;
+ (CONST_CAST (char *, arg))[length] = 0;
dot = 1;
break;
}
do_spec_1 (arg, 1, NULL);
if (dot)
- (CONST_CAST(char *, arg))[length] = '.';
+ (CONST_CAST (char *, arg))[length] = '.';
do_spec_1 (suffix_subst, 1, NULL);
}
else
@@ -8395,7 +8385,7 @@ get_random_number (void)
}
#endif
- return ret ^ getpid();
+ return ret ^ getpid ();
}
/* %:compare-debug-dump-opt spec function. Save the last argument,
@@ -8607,7 +8597,7 @@ replace_extension_spec_func (int argc, const char **argv)
name = xstrdup (argv[0]);
- for (i = strlen(name) - 1; i >= 0; i--)
+ for (i = strlen (name) - 1; i >= 0; i--)
if (IS_DIR_SEPARATOR (name[i]))
break;
diff --git a/gcc/gcov-io.c b/gcc/gcov-io.c
index 441aad92833..5a21c1f0691 100644
--- a/gcc/gcov-io.c
+++ b/gcc/gcov-io.c
@@ -386,7 +386,7 @@ gcov_write_summary (gcov_unsigned_t tag, const struct gcov_summary *summary)
h_cnt++;
}
}
- gcov_write_tag_length (tag, GCOV_TAG_SUMMARY_LENGTH(h_cnt));
+ gcov_write_tag_length (tag, GCOV_TAG_SUMMARY_LENGTH (h_cnt));
gcov_write_unsigned (summary->checksum);
for (csum = summary->ctrs, ix = GCOV_COUNTERS_SUMMABLE; ix--; csum++)
{
@@ -559,7 +559,7 @@ gcov_read_summary (struct gcov_summary *summary)
while (!cur_bitvector)
{
h_ix = bv_ix * 32;
- gcc_assert(bv_ix < GCOV_HISTOGRAM_BITVECTOR_SIZE);
+ gcc_assert (bv_ix < GCOV_HISTOGRAM_BITVECTOR_SIZE);
cur_bitvector = histo_bitvector[bv_ix++];
}
while (!(cur_bitvector & 0x1))
@@ -567,7 +567,7 @@ gcov_read_summary (struct gcov_summary *summary)
h_ix++;
cur_bitvector >>= 1;
}
- gcc_assert(h_ix < GCOV_HISTOGRAM_SIZE);
+ gcc_assert (h_ix < GCOV_HISTOGRAM_SIZE);
csum->histogram[h_ix].num_counters = gcov_read_unsigned ();
csum->histogram[h_ix].min_value = gcov_read_counter ();
@@ -709,7 +709,7 @@ static void gcov_histogram_merge (gcov_bucket_type *tgt_histo,
gcov_bucket_type tmp_histo[GCOV_HISTOGRAM_SIZE];
int src_done = 0;
- memset(tmp_histo, 0, sizeof (gcov_bucket_type) * GCOV_HISTOGRAM_SIZE);
+ memset (tmp_histo, 0, sizeof (gcov_bucket_type) * GCOV_HISTOGRAM_SIZE);
/* Assume that the counters are in the same relative order in both
histograms. Walk the histograms from largest to smallest entry,
@@ -797,7 +797,7 @@ static void gcov_histogram_merge (gcov_bucket_type *tgt_histo,
/* The merged counters get placed in the new merged histogram
at the entry for the merged min_value. */
- tmp_i = gcov_histo_index(merge_min);
+ tmp_i = gcov_histo_index (merge_min);
gcc_assert (tmp_i < GCOV_HISTOGRAM_SIZE);
tmp_histo[tmp_i].num_counters += merge_num;
tmp_histo[tmp_i].cum_value += merge_cum;
@@ -829,12 +829,13 @@ static void gcov_histogram_merge (gcov_bucket_type *tgt_histo,
}
/* At this point, tmp_i should be the smallest non-zero entry in the
tmp_histo. */
- gcc_assert(tmp_i >= 0 && tmp_i < GCOV_HISTOGRAM_SIZE
- && tmp_histo[tmp_i].num_counters > 0);
+ gcc_assert (tmp_i >= 0 && tmp_i < GCOV_HISTOGRAM_SIZE
+ && tmp_histo[tmp_i].num_counters > 0);
tmp_histo[tmp_i].cum_value += src_cum;
/* Finally, copy the merged histogram into tgt_histo. */
- memcpy(tgt_histo, tmp_histo, sizeof (gcov_bucket_type) * GCOV_HISTOGRAM_SIZE);
+ memcpy (tgt_histo, tmp_histo,
+ sizeof (gcov_bucket_type) * GCOV_HISTOGRAM_SIZE);
}
#endif /* !IN_GCOV */
diff --git a/gcc/gcov-io.h b/gcc/gcov-io.h
index db1a6bf4c30..73a52798f0d 100644
--- a/gcc/gcov-io.h
+++ b/gcc/gcov-io.h
@@ -342,9 +342,10 @@ typedef unsigned HOST_WIDEST_INT gcov_type_unsigned;
counter. */
#define GCOV_COUNTER_IOR 7 /* IOR of the all values passed to
counter. */
-#define GCOV_LAST_VALUE_COUNTER 7 /* The last of counters used for value
+#define GCOV_TIME_PROFILER 8 /* Time profile collecting first run of a function */
+#define GCOV_LAST_VALUE_COUNTER 8 /* The last of counters used for value
profiling. */
-#define GCOV_COUNTERS 8
+#define GCOV_COUNTERS 9
/* Number of counters used for value profiling. */
#define GCOV_N_VALUE_COUNTERS \
@@ -352,7 +353,7 @@ typedef unsigned HOST_WIDEST_INT gcov_type_unsigned;
/* A list of human readable names of the counters */
#define GCOV_COUNTER_NAMES {"arcs", "interval", "pow2", "single", \
- "delta", "indirect_call", "average", "ior"}
+ "delta", "indirect_call", "average", "ior", "time_profiler"}
/* Names of merge functions for counters. */
#define GCOV_MERGE_FUNCTIONS {"__gcov_merge_add", \
@@ -362,7 +363,8 @@ typedef unsigned HOST_WIDEST_INT gcov_type_unsigned;
"__gcov_merge_delta", \
"__gcov_merge_single", \
"__gcov_merge_add", \
- "__gcov_merge_ior"}
+ "__gcov_merge_ior", \
+ "__gcov_merge_time_profile" }
/* Convert a counter index to a tag. */
#define GCOV_TAG_FOR_COUNTER(COUNT) \
@@ -382,7 +384,7 @@ typedef unsigned HOST_WIDEST_INT gcov_type_unsigned;
/* Return nonzero if SUB is an immediate subtag of TAG. */
#define GCOV_TAG_IS_SUBTAG(TAG,SUB) \
(GCOV_TAG_MASK (TAG) >> 8 == GCOV_TAG_MASK (SUB) \
- && !(((SUB) ^ (TAG)) & ~GCOV_TAG_MASK(TAG)))
+ && !(((SUB) ^ (TAG)) & ~GCOV_TAG_MASK (TAG)))
/* Return nonzero if SUB is at a sublevel to TAG. */
#define GCOV_TAG_IS_SUBLEVEL(TAG,SUB) \
@@ -511,6 +513,8 @@ extern void __gcov_merge_delta (gcov_type *, unsigned) ATTRIBUTE_HIDDEN;
/* The merge function that just ors the counters together. */
extern void __gcov_merge_ior (gcov_type *, unsigned) ATTRIBUTE_HIDDEN;
+extern void __gcov_merge_time_profile (gcov_type *, unsigned) ATTRIBUTE_HIDDEN;
+
/* The profiler functions. */
extern void __gcov_interval_profiler (gcov_type *, gcov_type, int, unsigned);
extern void __gcov_pow2_profiler (gcov_type *, gcov_type);
@@ -518,6 +522,7 @@ extern void __gcov_one_value_profiler (gcov_type *, gcov_type);
extern void __gcov_indirect_call_profiler_v2 (gcov_type, void *);
extern void __gcov_average_profiler (gcov_type *, gcov_type);
extern void __gcov_ior_profiler (gcov_type *, gcov_type);
+extern void __gcov_time_profiler (gcov_type *);
#ifndef inhibit_libc
/* The wrappers around some library functions.. */
diff --git a/gcc/gcov.c b/gcc/gcov.c
index 6aa48fd26c2..9458812d86b 100644
--- a/gcc/gcov.c
+++ b/gcc/gcov.c
@@ -398,7 +398,7 @@ static void executed_summary (unsigned, unsigned);
static void function_summary (const coverage_t *, const char *);
static const char *format_gcov (gcov_type, gcov_type, int);
static void accumulate_line_counts (source_t *);
-static void output_gcov_file(const char *, source_t *);
+static void output_gcov_file (const char *, source_t *);
static int output_branch_count (FILE *, int, const arc_t *);
static void output_lines (FILE *, const source_t *);
static char *make_gcov_file_name (const char *, const char *);
@@ -448,8 +448,8 @@ main (int argc, char **argv)
for (; argno != argc; argno++)
{
if (flag_display_progress)
- printf("Processing file %d out of %d\n",
- argno - first_arg + 1, argc - first_arg);
+ printf ("Processing file %d out of %d\n",
+ argno - first_arg + 1, argc - first_arg);
process_file (argv[argno]);
}
@@ -621,7 +621,7 @@ get_gcov_intermediate_filename (const char *file_name)
/* Find the 'basename'. */
cptr = lbasename (file_name);
- result = XNEWVEC(char, strlen (cptr) + strlen (gcov) + 1);
+ result = XNEWVEC (char, strlen (cptr) + strlen (gcov) + 1);
sprintf (result, "%s%s", cptr, gcov);
return result;
@@ -699,7 +699,7 @@ output_intermediate_file (FILE *gcov_file, source_t *src)
branch_type = (arc->count > 0) ? "taken" : "nottaken";
else
branch_type = "notexec";
- fprintf(gcov_file, "branch:%d,%s\n", line_num, branch_type);
+ fprintf (gcov_file, "branch:%d,%s\n", line_num, branch_type);
}
}
}
@@ -782,7 +782,7 @@ process_file (const char *file_name)
}
static void
-output_gcov_file(const char *file_name, source_t *src)
+output_gcov_file (const char *file_name, source_t *src)
{
char *gcov_file_name = make_gcov_file_name (file_name, src->coverage.name);
diff --git a/gcc/gcse.c b/gcc/gcse.c
index 422d6f060eb..571e8788c83 100644
--- a/gcc/gcse.c
+++ b/gcc/gcse.c
@@ -2535,7 +2535,7 @@ gcse_emit_move_after (rtx dest, rtx src, rtx insn)
/* Delete redundant computations.
Deletion is done by changing the insn to copy the `reaching_reg' of
the expression into the result of the SET. It is left to later passes
- (cprop, cse2, flow, combine, regmove) to propagate the copy or eliminate it.
+ to propagate the copy or eliminate it.
Return nonzero if a change is made. */
@@ -4169,8 +4169,8 @@ const pass_data pass_data_rtl_pre =
class pass_rtl_pre : public rtl_opt_pass
{
public:
- pass_rtl_pre(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_rtl_pre, ctxt)
+ pass_rtl_pre (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_rtl_pre, ctxt)
{}
/* opt_pass methods: */
@@ -4208,8 +4208,8 @@ const pass_data pass_data_rtl_hoist =
class pass_rtl_hoist : public rtl_opt_pass
{
public:
- pass_rtl_hoist(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_rtl_hoist, ctxt)
+ pass_rtl_hoist (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_rtl_hoist, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/gdbhooks.py b/gcc/gdbhooks.py
index 3d69b11bfe9..53abf329113 100644
--- a/gcc/gdbhooks.py
+++ b/gcc/gdbhooks.py
@@ -226,8 +226,7 @@ class CGraphNodePrinter:
# symtab_node_name calls lang_hooks.decl_printable_name
# default implementation (lhd_decl_printable_name) is:
# return IDENTIFIER_POINTER (DECL_NAME (decl));
- symbol = self.gdbval['symbol']
- tree_decl = Tree(symbol['decl'])
+ tree_decl = Tree(self.gdbval['decl'])
result += ' "%s"' % tree_decl.DECL_NAME().IDENTIFIER_POINTER()
result += '>'
return result
diff --git a/gcc/gdbinit.in b/gcc/gdbinit.in
index 8e8a9d42b15..2cba8d9699e 100644
--- a/gcc/gdbinit.in
+++ b/gcc/gdbinit.in
@@ -219,6 +219,11 @@ set complaints 0
b exit
b abort
+# Disable strict type checking. This allows developers to (for example)
+# make inferior calls without casting absolute address to a suitable
+# pointer type.
+set check type off
+
# Skip all inline functions in tree.h.
# These are used in accessor macros.
# Note that this is added at the end because older gdb versions
diff --git a/gcc/genattr-common.c b/gcc/genattr-common.c
index 69bfcae48c7..b0848cff7ec 100644
--- a/gcc/genattr-common.c
+++ b/gcc/genattr-common.c
@@ -33,7 +33,7 @@ static void
write_upcase (const char *str)
{
for (; *str; str++)
- putchar (TOUPPER(*str));
+ putchar (TOUPPER (*str));
}
static void
diff --git a/gcc/genattr.c b/gcc/genattr.c
index e16cad9c79a..0b92243a86d 100644
--- a/gcc/genattr.c
+++ b/gcc/genattr.c
@@ -361,10 +361,10 @@ main (int argc, char **argv)
/* Output flag masks for use by reorg.
Flags are used to hold branch direction for use by eligible_for_... */
- printf("\n#define ATTR_FLAG_forward\t0x1\n");
- printf("#define ATTR_FLAG_backward\t0x2\n");
+ printf ("\n#define ATTR_FLAG_forward\t0x1\n");
+ printf ("#define ATTR_FLAG_backward\t0x2\n");
- puts("\n#endif /* GCC_INSN_ATTR_H */");
+ puts ("\n#endif /* GCC_INSN_ATTR_H */");
if (ferror (stdout) || fflush (stdout) || fclose (stdout))
return FATAL_EXIT_CODE;
diff --git a/gcc/genattrtab.c b/gcc/genattrtab.c
index 8fcbb1610e6..f79380d6e46 100644
--- a/gcc/genattrtab.c
+++ b/gcc/genattrtab.c
@@ -90,9 +90,9 @@ along with GCC; see the file COPYING3. If not see
`return_val' (ATTR_PERMANENT_P): This rtx is permanent and unique
(see attr_rtx). */
-#define ATTR_IND_SIMPLIFIED_P(RTX) (RTX_FLAG((RTX), unchanging))
-#define ATTR_CURR_SIMPLIFIED_P(RTX) (RTX_FLAG((RTX), in_struct))
-#define ATTR_PERMANENT_P(RTX) (RTX_FLAG((RTX), return_val))
+#define ATTR_IND_SIMPLIFIED_P(RTX) (RTX_FLAG ((RTX), unchanging))
+#define ATTR_CURR_SIMPLIFIED_P(RTX) (RTX_FLAG ((RTX), in_struct))
+#define ATTR_PERMANENT_P(RTX) (RTX_FLAG ((RTX), return_val))
#if 0
#define strcmp_check(S1, S2) ((S1) == (S2) \
@@ -2815,7 +2815,7 @@ simplify_test_exp (rtx exp, int insn_code, int insn_index)
x = evaluate_eq_attr (exp, attr, av->value,
insn_code, insn_index);
x = SIMPLIFY_TEST_EXP (x, insn_code, insn_index);
- if (attr_rtx_cost(x) < 7)
+ if (attr_rtx_cost (x) < 7)
return x;
}
}
@@ -4403,7 +4403,7 @@ write_upcase (FILE *outf, const char *str)
while (*str)
{
/* The argument of TOUPPER should not have side effects. */
- fputc (TOUPPER(*str), outf);
+ fputc (TOUPPER (*str), outf);
str++;
}
}
@@ -5100,6 +5100,7 @@ write_header (FILE *outf)
fprintf (outf, "#include \"system.h\"\n");
fprintf (outf, "#include \"coretypes.h\"\n");
fprintf (outf, "#include \"tm.h\"\n");
+ fprintf (outf, "#include \"tree.h\"\n");
fprintf (outf, "#include \"rtl.h\"\n");
fprintf (outf, "#include \"insn-attr.h\"\n");
fprintf (outf, "#include \"tm_p.h\"\n");
@@ -5285,7 +5286,7 @@ main (int argc, char **argv)
{
FILE *outf;
-#define IS_ATTR_GROUP(X) (!strncmp(attr->name,X,strlen(X)))
+#define IS_ATTR_GROUP(X) (!strncmp (attr->name, X, strlen (X)))
if (IS_ATTR_GROUP ("*internal_dfa_insn_code"))
outf = dfa_file;
else if (IS_ATTR_GROUP ("*insn_default_latency"))
diff --git a/gcc/genautomata.c b/gcc/genautomata.c
index add4624ba17..f6c4b91c42e 100644
--- a/gcc/genautomata.c
+++ b/gcc/genautomata.c
@@ -5533,7 +5533,7 @@ static reserv_sets_t
form_reservs_matter (automaton_t automaton)
{
int cycle, unit;
- reserv_sets_t reservs_matter = alloc_empty_reserv_sets();
+ reserv_sets_t reservs_matter = alloc_empty_reserv_sets ();
for (cycle = 0; cycle < max_cycles_num; cycle++)
for (unit = 0; unit < description->units_num; unit++)
@@ -7558,7 +7558,7 @@ output_trans_table (automaton_t automaton)
{
size_t i;
arc_t arc;
- vla_hwint_t transition_vect = vla_hwint_t();
+ vla_hwint_t transition_vect = vla_hwint_t ();
undefined_vect_el_value = automaton->achieved_states_num;
automaton->trans_table = create_state_ainsn_table (automaton);
@@ -7742,7 +7742,7 @@ output_dead_lock_vect (automaton_t automaton)
{
size_t i;
arc_t arc;
- vla_hwint_t dead_lock_vect = vla_hwint_t();
+ vla_hwint_t dead_lock_vect = vla_hwint_t ();
/* Create vect of pointers to states ordered by num of
transitions from the state (state with the maximum num is the
@@ -7787,7 +7787,7 @@ output_dead_lock_vect (automaton_t automaton)
static void
output_reserved_units_table (automaton_t automaton)
{
- vla_hwint_t reserved_units_table = vla_hwint_t();
+ vla_hwint_t reserved_units_table = vla_hwint_t ();
int state_byte_size;
int reserved_units_size;
size_t n;
@@ -9665,6 +9665,7 @@ main (int argc, char **argv)
"#include \"system.h\"\n"
"#include \"coretypes.h\"\n"
"#include \"tm.h\"\n"
+ "#include \"tree.h\"\n"
"#include \"rtl.h\"\n"
"#include \"tm_p.h\"\n"
"#include \"insn-config.h\"\n"
diff --git a/gcc/genconfig.c b/gcc/genconfig.c
index 81edc7466ab..498dd72e375 100644
--- a/gcc/genconfig.c
+++ b/gcc/genconfig.c
@@ -355,7 +355,7 @@ main (int argc, char **argv)
printf ("#define MAX_INSNS_PER_PEEP2 %d\n", max_insns_per_peep2);
}
- puts("\n#endif /* GCC_INSN_CONFIG_H */");
+ puts ("\n#endif /* GCC_INSN_CONFIG_H */");
if (ferror (stdout) || fflush (stdout) || fclose (stdout))
return FATAL_EXIT_CODE;
diff --git a/gcc/genemit.c b/gcc/genemit.c
index 692ef526abf..724a114da44 100644
--- a/gcc/genemit.c
+++ b/gcc/genemit.c
@@ -68,7 +68,7 @@ print_code (RTX_CODE code)
{
const char *p1;
for (p1 = GET_RTX_NAME (code); *p1; p1++)
- putchar (TOUPPER(*p1));
+ putchar (TOUPPER (*p1));
}
static void
@@ -790,6 +790,7 @@ from the machine description file `md'. */\n\n");
printf ("#include \"system.h\"\n");
printf ("#include \"coretypes.h\"\n");
printf ("#include \"tm.h\"\n");
+ printf ("#include \"tree.h\"\n");
printf ("#include \"rtl.h\"\n");
printf ("#include \"tm_p.h\"\n");
printf ("#include \"function.h\"\n");
diff --git a/gcc/genextract.c b/gcc/genextract.c
index 6d2d3d2d0bb..35fc91e8806 100644
--- a/gcc/genextract.c
+++ b/gcc/genextract.c
@@ -165,9 +165,9 @@ gen_insn (rtx insn, int insn_code_number)
p->duplocs = p->oplocs + op_count;
p->dupnums = (int *)(p->duplocs + dup_count);
- memcpy(p->oplocs, acc.oplocs.address(), op_count*sizeof(locstr));
- memcpy(p->duplocs, acc.duplocs.address(), dup_count*sizeof(locstr));
- memcpy(p->dupnums, acc.dupnums.address(), dup_count*sizeof(int));
+ memcpy (p->oplocs, acc.oplocs.address (), op_count * sizeof (locstr));
+ memcpy (p->duplocs, acc.duplocs.address (), dup_count * sizeof (locstr));
+ memcpy (p->dupnums, acc.dupnums.address (), dup_count * sizeof (int));
done:
acc.oplocs.release ();
@@ -334,7 +334,7 @@ print_path (const char *path)
{
if (ISLOWER (path[i]))
printf (", 0, %d)", path[i] - 'a');
- else if (ISDIGIT(path[i]))
+ else if (ISDIGIT (path[i]))
printf (", %d)", path[i] - '0');
else
gcc_unreachable ();
diff --git a/gcc/genflags.c b/gcc/genflags.c
index df329b5a806..80d8315e41b 100644
--- a/gcc/genflags.c
+++ b/gcc/genflags.c
@@ -109,7 +109,7 @@ gen_macro (const char *name, int real, int expect)
for (i = 0; name[i]; i++)
putchar (TOUPPER (name[i]));
- putchar('(');
+ putchar ('(');
for (i = 0; i < expect - 1; i++)
printf ("%c, ", i + 'A');
printf ("%c) gen_%s (", i + 'A', name);
@@ -290,7 +290,7 @@ main (int argc, char **argv)
for (insn_ptr = insns; *insn_ptr; insn_ptr++)
gen_proto (*insn_ptr);
- puts("\n#endif /* GCC_INSN_FLAGS_H */");
+ puts ("\n#endif /* GCC_INSN_FLAGS_H */");
if (have_error || ferror (stdout) || fflush (stdout) || fclose (stdout))
return FATAL_EXIT_CODE;
diff --git a/gcc/gengenrtl.c b/gcc/gengenrtl.c
index 5b5a3ca0308..4a35683c896 100644
--- a/gcc/gengenrtl.c
+++ b/gcc/gengenrtl.c
@@ -37,7 +37,7 @@ static const struct rtx_definition defs[] =
{
#include "rtl.def" /* rtl expressions are documented here */
};
-#define NUM_RTX_CODE ARRAY_SIZE(defs)
+#define NUM_RTX_CODE ARRAY_SIZE (defs)
static const char *formats[NUM_RTX_CODE];
diff --git a/gcc/gengtype-parse.c b/gcc/gengtype-parse.c
index 68d372eb684..8328e3adf6e 100644
--- a/gcc/gengtype-parse.c
+++ b/gcc/gengtype-parse.c
@@ -165,6 +165,21 @@ require (int t)
return v;
}
+/* As per require, but do not advance. */
+static const char *
+require_without_advance (int t)
+{
+ int u = token ();
+ const char *v = T.value;
+ if (u != t)
+ {
+ parse_error ("expected %s, have %s",
+ print_token (t, 0), print_token (u, v));
+ return 0;
+ }
+ return v;
+}
+
/* If the next token does not have one of the codes T1 or T2, report a
parse error; otherwise return the token's value. */
static const char *
@@ -715,7 +730,7 @@ declarator (type_p ty, const char **namep, options_p *optsp,
(
type bitfield ';'
| type declarator bitfield? ( ',' declarator bitfield? )+ ';'
- )+
+ )*
Knows that such declarations must end with a close brace (or,
erroneously, at EOF).
@@ -729,10 +744,21 @@ struct_field_seq (void)
const char *name;
bool another;
- do
+ while (token () != '}' && token () != EOF_TOKEN)
{
ty = type (&opts, true);
+ /* Ignore access-control keywords ("public:" etc). */
+ while (!ty && token () == IGNORABLE_CXX_KEYWORD)
+ {
+ const char *keyword = advance ();
+ if (strcmp (keyword, "public:") != 0
+ && strcmp (keyword, "private:") != 0
+ && strcmp (keyword, "protected:") != 0)
+ break;
+ ty = type (&opts, true);
+ }
+
if (!ty || token () == ':')
{
consume_until_eos ();
@@ -761,13 +787,12 @@ struct_field_seq (void)
}
while (another);
}
- while (token () != '}' && token () != EOF_TOKEN);
return nreverse_pairs (f);
}
/* Return true if OPTS contain the option named STR. */
-static bool
+bool
opts_have (options_p opts, const char *str)
{
for (options_p opt = opts; opt; opt = opt->next)
@@ -818,6 +843,7 @@ type (options_p *optsp, bool nested)
case STRUCT:
case UNION:
{
+ type_p base_class = NULL;
options_p opts = 0;
/* GTY annotations follow attribute syntax
GTY_BEFORE_ID is for union/struct declarations
@@ -857,16 +883,39 @@ type (options_p *optsp, bool nested)
opts = gtymarker_opt ();
}
+ bool is_user_gty = opts_have (opts, "user");
+
if (token () == ':')
{
- /* Skip over C++ inheritance specification. */
- while (token () != '{')
- advance ();
+ if (is_gty && !is_user_gty)
+ {
+ /* For GTY-marked types that are not "user", parse some C++
+ inheritance specifications.
+ We require single-inheritance from a non-template type. */
+ advance ();
+ const char *basename = require (ID);
+ /* This may be either an access specifier, or the base name. */
+ if (0 == strcmp (basename, "public")
+ || 0 == strcmp (basename, "protected")
+ || 0 == strcmp (basename, "private"))
+ basename = require (ID);
+ base_class = find_structure (basename, TYPE_STRUCT);
+ if (!base_class)
+ parse_error ("unrecognized base class: %s", basename);
+ require_without_advance ('{');
+ }
+ else
+ {
+ /* For types lacking GTY-markings, skip over C++ inheritance
+ specification (and thus avoid having to parse e.g. template
+ types). */
+ while (token () != '{')
+ advance ();
+ }
}
if (is_gty)
{
- bool is_user_gty = opts_have (opts, "user");
if (token () == '{')
{
pair_p fields;
@@ -889,7 +938,8 @@ type (options_p *optsp, bool nested)
return create_user_defined_type (s, &lexer_line);
}
- return new_structure (s, kind, &lexer_line, fields, opts);
+ return new_structure (s, kind, &lexer_line, fields, opts,
+ base_class);
}
}
else if (token () == '{')
diff --git a/gcc/gengtype-state.c b/gcc/gengtype-state.c
index ba7948a1ff0..fda473a2dbe 100644
--- a/gcc/gengtype-state.c
+++ b/gcc/gengtype-state.c
@@ -142,7 +142,7 @@ static long state_bol = 0; /* offset of beginning of line */
class s_expr_writer
{
public:
- s_expr_writer();
+ s_expr_writer ();
void write_new_line ();
void write_any_indent (int leading_spaces);
@@ -151,15 +151,15 @@ public:
void end_s_expr ();
private:
- int indent_amount_;
- int had_recent_newline_;
+ int m_indent_amount;
+ int m_had_recent_newline;
}; // class s_expr_writer
/* A class for writing out "gtype.state". */
class state_writer : public s_expr_writer
{
public:
- state_writer();
+ state_writer ();
private:
void write_state_fileloc (struct fileloc *floc);
@@ -200,14 +200,14 @@ private:
private:
/* Counter of written types. */
- int state_written_type_count;
+ int m_state_written_type_count;
}; // class state_writer
/* class s_expr_writer's trivial constructor. */
-s_expr_writer::s_expr_writer()
- : indent_amount_(0),
- had_recent_newline_(0)
+s_expr_writer::s_expr_writer ()
+ : m_indent_amount (0),
+ m_had_recent_newline (0)
{
}
@@ -216,10 +216,10 @@ void
s_expr_writer::write_new_line (void)
{
/* Don't add a newline if we've just had one. */
- if (!had_recent_newline_)
+ if (!m_had_recent_newline)
{
fprintf (state_file, "\n");
- had_recent_newline_ = 1;
+ m_had_recent_newline = 1;
}
}
@@ -236,11 +236,11 @@ void
s_expr_writer::write_any_indent (int leading_spaces)
{
int i;
- int amount = indent_amount_ - leading_spaces;
- if (had_recent_newline_)
+ int amount = m_indent_amount - leading_spaces;
+ if (m_had_recent_newline)
for (i = 0; i < amount; i++)
fprintf (state_file, " ");
- had_recent_newline_ = 0;
+ m_had_recent_newline = 0;
}
/* Write the beginning of a new s-expresion e.g. "(!foo "
@@ -253,7 +253,7 @@ s_expr_writer::begin_s_expr (const char *tag)
write_new_line ();
write_any_indent (0);
fprintf (state_file, "(!%s ", tag);
- indent_amount_++;
+ m_indent_amount++;
}
/* Write out the end of an s-expression: any necssessary indentation,
@@ -261,7 +261,7 @@ s_expr_writer::begin_s_expr (const char *tag)
void
s_expr_writer::end_s_expr (void)
{
- indent_amount_--;
+ m_indent_amount--;
write_any_indent (0);
fprintf (state_file, ")");
write_new_line ();
@@ -269,9 +269,9 @@ s_expr_writer::end_s_expr (void)
/* class state_writer's trivial constructor. */
-state_writer::state_writer()
- : s_expr_writer(),
- state_written_type_count(0)
+state_writer::state_writer ()
+ : s_expr_writer (),
+ m_state_written_type_count (0)
{
}
@@ -309,7 +309,7 @@ fatal_reading_state (struct state_token_st* tok, const char*msg)
else \
fatal ("%s:%d: Invalid state file; " Fmt, \
state_path, state_line, __VA_ARGS__); \
- } while(0)
+ } while (0)
/* Find or allocate an identifier in our name hash table. */
@@ -957,6 +957,7 @@ state_writer::write_state_struct_type (type_p current)
{
write_state_struct_union_type (current, "struct");
write_state_type (current->u.s.lang_struct);
+ write_state_type (current->u.s.base_class);
}
/* Write a GTY user-defined struct type. */
@@ -1136,10 +1137,10 @@ state_writer::write_state_type (type_p current)
}
else
{
- state_written_type_count++;
- DBGPRINTF ("writing type #%d @%p old number %d", state_written_type_count,
+ m_state_written_type_count++;
+ DBGPRINTF ("writing type #%d @%p old number %d", m_state_written_type_count,
(void *) current, current->state_number);
- current->state_number = state_written_type_count;
+ current->state_number = m_state_written_type_count;
switch (current->kind)
{
case TYPE_NONE:
@@ -1441,7 +1442,7 @@ write_state (const char *state_path)
if (verbosity_level >= 1)
printf ("%s wrote state file %s of %ld bytes with %d GTY-ed types\n",
- progname, state_path, statelen, sw.state_written_type_count);
+ progname, state_path, statelen, sw.m_state_written_type_count);
}
@@ -1613,6 +1614,9 @@ read_state_struct_type (type_p type)
read_state_options (&(type->u.s.opt));
read_state_lang_bitmap (&(type->u.s.bitmap));
read_state_type (&(type->u.s.lang_struct));
+ read_state_type (&(type->u.s.base_class));
+ if (type->u.s.base_class)
+ add_subclass (type->u.s.base_class, type);
}
else
{
diff --git a/gcc/gengtype.c b/gcc/gengtype.c
index 658d2e959b2..d5e58ce3d03 100644
--- a/gcc/gengtype.c
+++ b/gcc/gengtype.c
@@ -137,6 +137,16 @@ xasprintf (const char *format, ...)
return result;
}
+/* Locate the ultimate base class of struct S. */
+
+static const_type_p
+get_ultimate_base_class (const_type_p s)
+{
+ while (s->u.s.base_class)
+ s = s->u.s.base_class;
+ return s;
+}
+
/* Input file handling. */
/* Table of all input files. */
@@ -617,7 +627,7 @@ type_for_name (const char *s)
extern GTY(()) gcc::some_type *some_ptr;
where the autogenerated functions will refer to simply "some_type",
where they can be resolved into their namespace. */
- if (0 == strncmp(s, "gcc::", 5))
+ if (0 == strncmp (s, "gcc::", 5))
s += 5;
for (p = typedefs; p != NULL; p = p->next)
@@ -667,6 +677,16 @@ resolve_typedef (const char *s, struct fileloc *pos)
return p;
}
+/* Add SUBCLASS to head of linked list of BASE's subclasses. */
+
+void add_subclass (type_p base, type_p subclass)
+{
+ gcc_assert (union_or_struct_p (base));
+ gcc_assert (union_or_struct_p (subclass));
+
+ subclass->u.s.next_sibling_class = base->u.s.first_subclass;
+ base->u.s.first_subclass = subclass;
+}
/* Create and return a new structure with tag NAME at POS with fields
FIELDS and options O. The KIND of structure must be one of
@@ -674,7 +694,7 @@ resolve_typedef (const char *s, struct fileloc *pos)
type_p
new_structure (const char *name, enum typekind kind, struct fileloc *pos,
- pair_p fields, options_p o)
+ pair_p fields, options_p o, type_p base_class)
{
type_p si;
type_p s = NULL;
@@ -748,6 +768,9 @@ new_structure (const char *name, enum typekind kind, struct fileloc *pos,
s->u.s.bitmap = bitmap;
if (s->u.s.lang_struct)
s->u.s.lang_struct->u.s.bitmap |= bitmap;
+ s->u.s.base_class = base_class;
+ if (base_class)
+ add_subclass (base_class, s);
return s;
}
@@ -953,7 +976,7 @@ create_field_at (pair_p next, type_p type, const char *name, options_p opt,
/* Create a fake field with the given type and name. NEXT is the next
field in the chain. */
#define create_field(next,type,name) \
- create_field_all(next,type,name, 0, this_file, __LINE__)
+ create_field_all (next,type,name, 0, this_file, __LINE__)
/* Like create_field, but the field is only valid when condition COND
is true. */
@@ -976,7 +999,7 @@ create_optional_field_ (pair_p next, type_p type, const char *name,
create_string_option (union_fields->opt, "tag", "1");
union_type =
new_structure (xasprintf ("%s_%d", "fake_union", id++), TYPE_UNION,
- &lexer_line, union_fields, NULL);
+ &lexer_line, union_fields, NULL, NULL);
/* Create the field and give it the new fake union type. Add a "desc"
tag that specifies the condition under which the field is valid. */
@@ -1167,7 +1190,7 @@ adjust_field_rtx_def (type_p t, options_p ARG_UNUSED (opt))
create_string_option (nodot, "tag", note_insn_name[c]);
}
note_union_tp = new_structure ("rtx_def_note_subunion", TYPE_UNION,
- &lexer_line, note_flds, NULL);
+ &lexer_line, note_flds, NULL, NULL);
}
/* Create a type to represent the various forms of SYMBOL_REF_DATA. */
{
@@ -1177,7 +1200,7 @@ adjust_field_rtx_def (type_p t, options_p ARG_UNUSED (opt))
sym_flds = create_field (sym_flds, constant_tp, "rt_constant");
sym_flds->opt = create_string_option (nodot, "tag", "1");
symbol_union_tp = new_structure ("rtx_def_symbol_subunion", TYPE_UNION,
- &lexer_line, sym_flds, NULL);
+ &lexer_line, sym_flds, NULL, NULL);
}
for (i = 0; i < NUM_RTX_CODE; i++)
{
@@ -1319,7 +1342,7 @@ adjust_field_rtx_def (type_p t, options_p ARG_UNUSED (opt))
sname = xasprintf ("rtx_def_%s", rtx_name[i]);
substruct = new_structure (sname, TYPE_STRUCT, &lexer_line, subfields,
- NULL);
+ NULL, NULL);
ftag = xstrdup (rtx_name[i]);
for (nmindex = 0; nmindex < strlen (ftag); nmindex++)
@@ -1328,7 +1351,7 @@ adjust_field_rtx_def (type_p t, options_p ARG_UNUSED (opt))
flds->opt = create_string_option (nodot, "tag", ftag);
}
return new_structure ("rtx_def_subunion", TYPE_UNION, &lexer_line, flds,
- nodot);
+ nodot, NULL);
}
/* Handle `special("tree_exp")'. This is a special case for
@@ -1358,7 +1381,7 @@ adjust_field_tree_exp (type_p t, options_p opt ATTRIBUTE_UNUSED)
flds->opt = create_string_option (flds->opt, "default", "");
return new_structure ("tree_exp_subunion", TYPE_UNION, &lexer_line, flds,
- nodot);
+ nodot, NULL);
}
/* Perform any special processing on a type T, about to become the type
@@ -1531,7 +1554,17 @@ set_gc_used_type (type_p t, enum gc_used_enum level, type_p param[NUM_PARAM],
process_gc_options (t->u.s.opt, level, &dummy, &dummy, &dummy, &dummy,
&dummy2);
- for (f = t->u.s.fields; f; f = f->next)
+ if (t->u.s.base_class)
+ set_gc_used_type (t->u.s.base_class, level, param,
+ allow_undefined_types);
+ /* Anything pointing to a base class might actually be pointing
+ to a subclass. */
+ for (type_p subclass = t->u.s.first_subclass; subclass;
+ subclass = subclass->u.s.next_sibling_class)
+ set_gc_used_type (subclass, level, param,
+ allow_undefined_types);
+
+ FOR_ALL_INHERITED_FIELDS(t, f)
{
int maybe_undef = 0;
int pass_param = 0;
@@ -1736,8 +1769,12 @@ open_base_files (void)
"tree.h", "rtl.h", "function.h", "insn-config.h", "expr.h",
"hard-reg-set.h", "basic-block.h", "cselib.h", "insn-addr.h",
"optabs.h", "libfuncs.h", "debug.h", "ggc.h", "cgraph.h",
+ "gimple.h", "gimple-ssa.h", "tree-cfg.h", "tree-phinodes.h",
+ "ssa-iterators.h", "tree-ssanames.h", "tree-ssa-loop.h",
+ "tree-ssa-loop-ivopts.h", "tree-ssa-loop-manip.h",
+ "tree-ssa-loop-niter.h", "tree-into-ssa.h", "tree-dfa.h",
"tree-ssa.h", "reload.h", "cpp-id-data.h", "tree-chrec.h",
- "except.h", "output.h", "gimple.h", "cfgloop.h",
+ "except.h", "output.h", "cfgloop.h",
"target.h", "ipa-prop.h", "lto-streamer.h", "target-globals.h",
"ipa-inline.h", "dwarf2out.h",
@@ -2009,8 +2046,8 @@ struct file_rule_st files_rules[] = {
REG_EXTENDED, NULL_REGEX,
"gt-objc-objc-map.h", "objc/objc-map.c", NULL_FRULACT },
- /* General cases. For header *.h and source *.c or *.cc files, we need
- * special actions to handle the language. */
+ /* General cases. For header *.h and source *.c or *.cc files, we
+ * need special actions to handle the language. */
/* Source *.c files are using get_file_gtfilename to compute their
output_name and get_file_basename to compute their for_name
@@ -2136,7 +2173,7 @@ matching_file_name_substitute (const char *filnam, regmatch_t pmatch[10],
else
{
/* This can happen only when files_rules is buggy! */
- gcc_unreachable();
+ gcc_unreachable ();
}
/* Always skip the character after the dollar. */
pt++;
@@ -2344,6 +2381,8 @@ is_file_equal (outf_p of)
break;
}
}
+ if (equal && EOF != fgetc (newfile))
+ equal = false;
fclose (newfile);
return equal;
}
@@ -2545,11 +2584,15 @@ output_mangled_typename (outf_p of, const_type_p t)
case TYPE_LANG_STRUCT:
case TYPE_USER_STRUCT:
{
+ /* For references to classes within an inheritance hierarchy,
+ only ever reference the ultimate base class, since only
+ it will have gt_ functions. */
+ t = get_ultimate_base_class (t);
const char *id_for_tag = filter_type_name (t->u.s.tag);
oprintf (of, "%lu%s", (unsigned long) strlen (id_for_tag),
id_for_tag);
if (id_for_tag != t->u.s.tag)
- free (CONST_CAST(char *, id_for_tag));
+ free (CONST_CAST (char *, id_for_tag));
}
break;
case TYPE_PARAM_STRUCT:
@@ -2607,6 +2650,42 @@ output_escaped_param (struct walk_type_data *d, const char *param,
}
}
+const char *
+get_string_option (options_p opt, const char *key)
+{
+ for (; opt; opt = opt->next)
+ if (strcmp (opt->name, key) == 0)
+ return opt->info.string;
+ return NULL;
+}
+
+static void
+walk_subclasses (type_p base, struct walk_type_data *d)
+{
+ for (type_p sub = base->u.s.first_subclass; sub != NULL;
+ sub = sub->u.s.next_sibling_class)
+ {
+ const char *type_tag = get_string_option (sub->u.s.opt, "tag");
+ if (type_tag)
+ {
+ oprintf (d->of, "%*scase %s:\n", d->indent, "", type_tag);
+ d->indent += 2;
+ oprintf (d->of, "%*s{\n", d->indent, "");
+ d->indent += 2;
+ oprintf (d->of, "%*s%s *sub = static_cast <%s *> (x);\n",
+ d->indent, "", sub->u.s.tag, sub->u.s.tag);
+ const char *old_val = d->val;
+ d->val = "(*sub)";
+ walk_type (sub, d);
+ d->val = old_val;
+ d->indent -= 2;
+ oprintf (d->of, "%*s}\n", d->indent, "");
+ oprintf (d->of, "%*sbreak;\n", d->indent, "");
+ d->indent -= 2;
+ }
+ walk_subclasses (sub, d);
+ }
+}
/* Call D->PROCESS_FIELD for every field (or subfield) of D->VAL,
which is of type T. Write code to D->OF to constrain execution (at
@@ -2624,6 +2703,7 @@ walk_type (type_p t, struct walk_type_data *d)
{
const char *length = NULL;
const char *desc = NULL;
+ const char *type_tag = NULL;
int maybe_undef_p = 0;
int use_param_num = -1;
int use_params_p = 0;
@@ -2652,7 +2732,7 @@ walk_type (type_p t, struct walk_type_data *d)
else if (strcmp (oo->name, "dot") == 0)
;
else if (strcmp (oo->name, "tag") == 0)
- ;
+ type_tag = oo->info.string;
else if (strcmp (oo->name, "special") == 0)
;
else if (strcmp (oo->name, "skip") == 0)
@@ -2971,8 +3051,32 @@ walk_type (type_p t, struct walk_type_data *d)
d->indent += 2;
oprintf (d->of, "%*s{\n", d->indent, "");
}
+ else if (desc)
+ {
+ /* We have a "desc" option on a struct, signifying the
+ base class within a GC-managed inheritance hierarchy.
+ The current code specialcases the base class, then walks
+ into subclasses, recursing into this routine to handle them.
+ This organization requires the base class to have a case in
+ the switch statement, and hence a tag value is mandatory
+ for the base class. This restriction could be removed, but
+ it would require some restructing of this code. */
+ if (!type_tag)
+ {
+ error_at_line (d->line,
+ "missing `tag' option for type `%s'",
+ t->u.s.tag);
+ }
+ oprintf (d->of, "%*sswitch (", d->indent, "");
+ output_escaped_param (d, desc, "desc");
+ oprintf (d->of, ")\n");
+ d->indent += 2;
+ oprintf (d->of, "%*s{\n", d->indent, "");
+ oprintf (d->of, "%*scase %s:\n", d->indent, "", type_tag);
+ d->indent += 2;
+ }
- for (f = t->u.s.fields; f; f = f->next)
+ FOR_ALL_INHERITED_FIELDS (t, f)
{
options_p oo;
int skip_p = 0;
@@ -3010,7 +3114,7 @@ walk_type (type_p t, struct walk_type_data *d)
}
endcounter = d->counter;
- for (f = t->u.s.fields; f; f = f->next)
+ FOR_ALL_INHERITED_FIELDS (t, f)
{
options_p oo;
const char *dot = ".";
@@ -3112,11 +3216,36 @@ walk_type (type_p t, struct walk_type_data *d)
oprintf (d->of, "%*sdefault:\n", d->indent, "");
oprintf (d->of, "%*s break;\n", d->indent, "");
}
+
+ if (desc && !union_p)
+ {
+ oprintf (d->of, "%*sbreak;\n", d->indent, "");
+ d->indent -= 2;
+ }
if (union_p)
{
oprintf (d->of, "%*s}\n", d->indent, "");
d->indent -= 2;
}
+ else if (desc)
+ {
+ /* Add cases to handle subclasses. */
+ walk_subclasses (t, d);
+
+ /* Ensure that if someone forgets a "tag" option that we don't
+ silent fail to traverse that subclass's fields. */
+ if (!seen_default_p)
+ {
+ oprintf (d->of, "%*s/* Unrecognized tag value. */\n",
+ d->indent, "");
+ oprintf (d->of, "%*sdefault: gcc_unreachable (); \n",
+ d->indent, "");
+ }
+
+ /* End of the switch statement */
+ oprintf (d->of, "%*s}\n", d->indent, "");
+ d->indent -= 2;
+ }
if (any_length_seen)
{
d->indent -= 2;
@@ -3334,7 +3463,7 @@ write_marker_function_name (outf_p of, type_p s, const char *prefix)
const char *id_for_tag = filter_type_name (s->u.s.tag);
oprintf (of, "gt_%sx_%s", prefix, id_for_tag);
if (id_for_tag != s->u.s.tag)
- free (CONST_CAST(char *, id_for_tag));
+ free (CONST_CAST (char *, id_for_tag));
}
else if (s->kind == TYPE_PARAM_STRUCT)
{
@@ -3462,6 +3591,24 @@ write_func_for_structure (type_p orig_s, type_p s, type_p *param,
options_p opt;
struct walk_type_data d;
+ if (s->u.s.base_class)
+ {
+ /* Verify that the base class has a "desc", since otherwise
+ the traversal hooks there won't attempt to visit fields of
+ subclasses such as this one. */
+ const_type_p ubc = get_ultimate_base_class (s);
+ if ((!opts_have (ubc->u.s.opt, "user")
+ && !opts_have (ubc->u.s.opt, "desc")))
+ error_at_line (&s->u.s.line,
+ ("'%s' is a subclass of non-GTY(user) GTY class '%s'"
+ ", but '%s' lacks a discriminator 'desc' option"),
+ s->u.s.tag, ubc->u.s.tag, ubc->u.s.tag);
+
+ /* Don't write fns for subclasses, only for the ultimate base class
+ within an inheritance hierarchy. */
+ return;
+ }
+
memset (&d, 0, sizeof (d));
d.of = get_output_file_for_structure (s, param);
for (opt = s->u.s.opt; opt; opt = opt->next)
@@ -3638,7 +3785,10 @@ write_types (outf_p output_header, type_p structures, type_p param_structs,
emitted afterwards. This is needed in plugin mode. */
oprintf (output_header, "/* Macros and declarations. */\n");
for (s = structures; s; s = s->next)
- if (s->gc_used == GC_POINTED_TO || s->gc_used == GC_MAYBE_POINTED_TO)
+ /* Do not emit handlers for derived classes; we only ever deal with
+ the ultimate base class within an inheritance hierarchy. */
+ if ((s->gc_used == GC_POINTED_TO || s->gc_used == GC_MAYBE_POINTED_TO)
+ && !s->u.s.base_class)
{
options_p opt;
@@ -3668,7 +3818,7 @@ write_types (outf_p output_header, type_p structures, type_p param_structs,
"#define gt_%sx_%s gt_%sx_%s\n",
wtd->prefix, s->u.s.tag, wtd->prefix, t_id_for_tag);
if (t_id_for_tag != t->u.s.tag)
- free (CONST_CAST(char *, t_id_for_tag));
+ free (CONST_CAST (char *, t_id_for_tag));
}
else
error_at_line (&s->u.s.line,
@@ -3684,7 +3834,7 @@ write_types (outf_p output_header, type_p structures, type_p param_structs,
wtd->prefix, s_id_for_tag);
if (s_id_for_tag != s->u.s.tag)
- free (CONST_CAST(char *, s_id_for_tag));
+ free (CONST_CAST (char *, s_id_for_tag));
if (s->u.s.line.file == NULL)
{
@@ -3943,6 +4093,11 @@ write_local_func_for_structure (const_type_p orig_s, type_p s, type_p *param)
{
struct walk_type_data d;
+ /* Don't write fns for subclasses, only for the ultimate base class
+ within an inheritance hierarchy. */
+ if (s->u.s.base_class)
+ return;
+
memset (&d, 0, sizeof (d));
d.of = get_output_file_for_structure (s, param);
d.process_field = write_types_local_process_field;
@@ -4087,7 +4242,9 @@ write_local (outf_p output_header, type_p structures, type_p param_structs)
|| ((s)->gc_used == GC_MAYBE_POINTED_TO \
&& s->u.s.line.file != NULL) \
|| ((s)->gc_used == GC_USED \
- && strncmp (s->u.s.tag, "anonymous", strlen ("anonymous"))))))
+ && strncmp (s->u.s.tag, "anonymous", strlen ("anonymous"))) \
+ || (s->u.s.base_class && opts_have (s->u.s.opt, "tag")))))
+
/* Might T contain any non-pointer elements? */
@@ -4362,7 +4519,7 @@ write_root (outf_p f, pair_p v, type_p type, const char *name, int has_length,
case TYPE_POINTER:
{
- type_p tp;
+ const_type_p tp;
if (!start_root_entry (f, v, name, line))
return;
@@ -4371,6 +4528,7 @@ write_root (outf_p f, pair_p v, type_p type, const char *name, int has_length,
if (!has_length && union_or_struct_p (tp))
{
+ tp = get_ultimate_base_class (tp);
const char *id_for_tag = filter_type_name (tp->u.s.tag);
oprintf (f, " &gt_ggc_mx_%s,\n", id_for_tag);
if (emit_pch)
@@ -4378,7 +4536,7 @@ write_root (outf_p f, pair_p v, type_p type, const char *name, int has_length,
else
oprintf (f, " NULL");
if (id_for_tag != tp->u.s.tag)
- free (CONST_CAST(char *, id_for_tag));
+ free (CONST_CAST (char *, id_for_tag));
}
else if (!has_length && tp->kind == TYPE_PARAM_STRUCT)
{
@@ -4794,7 +4952,7 @@ write_typed_alloc_def (outf_p f,
oprintf (f, ", n");
oprintf (f, " MEM_STAT_INFO)))\n");
if (type_name_as_id != type_name)
- free (CONST_CAST(char *, type_name_as_id));
+ free (CONST_CAST (char *, type_name_as_id));
}
/* Writes a typed allocator definition into output F for a struct or
@@ -4861,7 +5019,7 @@ write_typed_alloc_defns (outf_p f,
relevant to plugin input files. */
if (nb_plugin_files > 0)
{
- struct fileloc* filoc = type_fileloc(s);
+ struct fileloc* filoc = type_fileloc (s);
if (!filoc || !filoc->file->inpisplugin)
continue;
};
@@ -5475,7 +5633,7 @@ main (int argc, char **argv)
we can see them. We should initialize them before calling
read_input_list. */
#define POS_HERE(Call) do { pos.file = this_file; pos.line = __LINE__; \
- Call;} while(0)
+ Call;} while (0)
POS_HERE (do_scalar_typedef ("CUMULATIVE_ARGS", &pos));
POS_HERE (do_scalar_typedef ("REAL_VALUE_TYPE", &pos));
POS_HERE (do_scalar_typedef ("FIXED_VALUE_TYPE", &pos));
diff --git a/gcc/gengtype.h b/gcc/gengtype.h
index f71ad97049d..0c3ec964a2f 100644
--- a/gcc/gengtype.h
+++ b/gcc/gengtype.h
@@ -291,6 +291,17 @@ struct type {
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;
} s;
/* when TYPE_SCALAR: */
@@ -422,9 +433,10 @@ extern char *xasprintf (const char *, ...) ATTRIBUTE_PRINTF_1;
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);
+ 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);
@@ -504,4 +516,12 @@ void dbgprint_count_type_at (const char *, int, const char *, type_p);
#define DBGPRINT_COUNT_TYPE(Msg,Ty) do{/*nodbgprint_count_type*/}while (0)
#endif /*ENABLE_CHECKING */
+#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/gcc/genmodes.c b/gcc/genmodes.c
index dc384833871..12a98f30162 100644
--- a/gcc/genmodes.c
+++ b/gcc/genmodes.c
@@ -333,6 +333,7 @@ complete_mode (struct mode_data *m)
break;
case MODE_INT:
+ case MODE_POINTER_BOUNDS:
case MODE_FLOAT:
case MODE_DECIMAL_FLOAT:
case MODE_FRACT:
@@ -418,7 +419,7 @@ complete_all_modes (void)
}
/* For each mode in class CLASS, construct a corresponding complex mode. */
-#define COMPLEX_MODES(C) make_complex_modes(MODE_##C, __FILE__, __LINE__)
+#define COMPLEX_MODES(C) make_complex_modes (MODE_##C, __FILE__, __LINE__)
static void
make_complex_modes (enum mode_class cl,
const char *file, unsigned int line)
@@ -474,7 +475,7 @@ make_complex_modes (enum mode_class cl,
/* For all modes in class CL, construct vector modes of width
WIDTH, having as many components as necessary. */
-#define VECTOR_MODES(C, W) make_vector_modes(MODE_##C, W, __FILE__, __LINE__)
+#define VECTOR_MODES(C, W) make_vector_modes (MODE_##C, W, __FILE__, __LINE__)
static void ATTRIBUTE_UNUSED
make_vector_modes (enum mode_class cl, unsigned int width,
const char *file, unsigned int line)
@@ -522,7 +523,8 @@ make_vector_modes (enum mode_class cl, unsigned int width,
/* Input. */
-#define _SPECIAL_MODE(C, N) make_special_mode(MODE_##C, #N, __FILE__, __LINE__)
+#define _SPECIAL_MODE(C, N) \
+ make_special_mode (MODE_##C, #N, __FILE__, __LINE__)
#define RANDOM_MODE(N) _SPECIAL_MODE (RANDOM, N)
#define CC_MODE(N) _SPECIAL_MODE (CC, N)
@@ -533,6 +535,19 @@ make_special_mode (enum mode_class cl, const char *name,
new_mode (cl, name, file, line);
}
+#define POINTER_BOUNDS_MODE(N, Y) \
+ make_pointer_bounds_mode (#N, Y, __FILE__, __LINE__)
+
+static void ATTRIBUTE_UNUSED
+make_pointer_bounds_mode (const char *name,
+ unsigned int bytesize,
+ const char *file, unsigned int line)
+{
+ struct mode_data *m = new_mode (MODE_POINTER_BOUNDS, name, file, line);
+ m->bytesize = bytesize;
+}
+
+
#define INT_MODE(N, Y) FRACTIONAL_INT_MODE (N, -1U, Y)
#define FRACTIONAL_INT_MODE(N, B, Y) \
make_int_mode (#N, B, Y, __FILE__, __LINE__)
@@ -629,10 +644,10 @@ reset_float_format (const char *name, const char *format,
m->format = format;
}
-/* Partial integer modes are specified by relation to a full integer mode.
- For now, we do not attempt to narrow down their bit sizes. */
-#define PARTIAL_INT_MODE(M) \
- make_partial_integer_mode (#M, "P" #M, -1U, __FILE__, __LINE__)
+/* Partial integer modes are specified by relation to a full integer
+ mode. */
+#define PARTIAL_INT_MODE(M,PREC,NAME) \
+ make_partial_integer_mode (#M, #NAME, PREC, __FILE__, __LINE__)
static void ATTRIBUTE_UNUSED
make_partial_integer_mode (const char *base, const char *name,
unsigned int precision,
@@ -669,7 +684,7 @@ make_vector_mode (enum mode_class bclass,
struct mode_data *v;
enum mode_class vclass = vector_class (bclass);
struct mode_data *component = find_mode (base);
- char namebuf[8];
+ char namebuf[16];
if (vclass == MODE_RANDOM)
return;
@@ -704,11 +719,11 @@ make_vector_mode (enum mode_class bclass,
#define _ADD_ADJUST(A, M, X, C1, C2) \
new_adjust (#M, &adj_##A, #A, #X, MODE_##C1, MODE_##C2, __FILE__, __LINE__)
-#define ADJUST_BYTESIZE(M, X) _ADD_ADJUST(bytesize, M, X, RANDOM, RANDOM)
-#define ADJUST_ALIGNMENT(M, X) _ADD_ADJUST(alignment, M, X, RANDOM, RANDOM)
-#define ADJUST_FLOAT_FORMAT(M, X) _ADD_ADJUST(format, M, X, FLOAT, FLOAT)
-#define ADJUST_IBIT(M, X) _ADD_ADJUST(ibit, M, X, ACCUM, UACCUM)
-#define ADJUST_FBIT(M, X) _ADD_ADJUST(fbit, M, X, FRACT, UACCUM)
+#define ADJUST_BYTESIZE(M, X) _ADD_ADJUST (bytesize, M, X, RANDOM, RANDOM)
+#define ADJUST_ALIGNMENT(M, X) _ADD_ADJUST (alignment, M, X, RANDOM, RANDOM)
+#define ADJUST_FLOAT_FORMAT(M, X) _ADD_ADJUST (format, M, X, FLOAT, FLOAT)
+#define ADJUST_IBIT(M, X) _ADD_ADJUST (ibit, M, X, ACCUM, UACCUM)
+#define ADJUST_FBIT(M, X) _ADD_ADJUST (fbit, M, X, FRACT, UACCUM)
static void
create_modes (void)
@@ -917,7 +932,7 @@ enum machine_mode\n{");
end will try to use it for bitfields in structures and the
like, which we do not want. Only the target md file should
generate BImode widgets. */
- if (first && first->precision == 1)
+ if (first && first->precision == 1 && c == MODE_INT)
first = first->next;
if (first && last)
@@ -1187,7 +1202,7 @@ emit_class_narrowest_mode (void)
/* Bleah, all this to get the comment right for MIN_MODE_INT. */
tagged_printf ("MIN_%s", mode_class_names[c],
modes[c]
- ? (modes[c]->precision != 1
+ ? ((c != MODE_INT || modes[c]->precision != 1)
? modes[c]->name
: (modes[c]->next
? modes[c]->next->name
diff --git a/gcc/genopinit.c b/gcc/genopinit.c
index fb8071765dd..3efb71e249e 100644
--- a/gcc/genopinit.c
+++ b/gcc/genopinit.c
@@ -194,7 +194,7 @@ match_pattern (pattern *p, const char *name, const char *pat)
for (i = (MAX_MACHINE_MODE) - 1; i >= 0; i--)
{
const char *p, *q;
- for (p = GET_MODE_NAME(i), q = name; *p; p++, q++)
+ for (p = GET_MODE_NAME (i), q = name; *p; p++, q++)
if (TOLOWER (*p) != *q)
break;
if (*p == 0
@@ -372,7 +372,7 @@ main (int argc, char **argv)
/* Sort the (real) optabs. Better than forcing the optabs.def file to
remain sorted by kind. We also scrogged any real ordering with the
purging of the X patterns above. */
- qsort (optabs, n, sizeof(optab_def), optab_kind_cmp);
+ qsort (optabs, n, sizeof (optab_def), optab_kind_cmp);
/* Emit the optab enumeration for the header file. */
fprintf (h_file, "enum optab_tag {\n");
@@ -404,6 +404,7 @@ main (int argc, char **argv)
"#include \"system.h\"\n"
"#include \"coretypes.h\"\n"
"#include \"tm.h\"\n"
+ "#include \"tree.h\"\n"
"#include \"rtl.h\"\n"
"#include \"tm_p.h\"\n"
"#include \"flags.h\"\n"
diff --git a/gcc/genoutput.c b/gcc/genoutput.c
index 59afaa452aa..2a7ee2391db 100644
--- a/gcc/genoutput.c
+++ b/gcc/genoutput.c
@@ -238,6 +238,7 @@ output_prologue (void)
printf ("#include \"tm.h\"\n");
printf ("#include \"flags.h\"\n");
printf ("#include \"ggc.h\"\n");
+ printf ("#include \"tree.h\"\n");
printf ("#include \"rtl.h\"\n");
printf ("#include \"expr.h\"\n");
printf ("#include \"insn-codes.h\"\n");
@@ -286,9 +287,9 @@ output_operand_data (void)
pred = lookup_predicate (d->predicate);
printf (" %d\n", pred && pred->codes[MEM]);
- printf(" },\n");
+ printf (" },\n");
}
- printf("};\n\n\n");
+ printf ("};\n\n\n");
}
static void
@@ -415,7 +416,7 @@ output_insn_data (void)
printf (" %d,\n", d->n_alternatives);
printf (" %d\n", d->output_format);
- printf(" },\n");
+ printf (" },\n");
}
printf ("};\n\n\n");
}
@@ -1112,7 +1113,7 @@ main (int argc, char **argv)
next_index_number++;
}
- printf("\n\n");
+ printf ("\n\n");
output_operand_data ();
output_insn_data ();
output_get_insn_name ();
@@ -1223,7 +1224,7 @@ note_constraint (rtx exp, int lineno)
}
}
new_cdata = XNEWVAR (struct constraint_data, sizeof (struct constraint_data) + namelen);
- strcpy (CONST_CAST(char *, new_cdata->name), name);
+ strcpy (CONST_CAST (char *, new_cdata->name), name);
new_cdata->namelen = namelen;
new_cdata->lineno = lineno;
new_cdata->next_this_letter = *slot;
diff --git a/gcc/genpeep.c b/gcc/genpeep.c
index 81bd9df64bb..877fde3ec90 100644
--- a/gcc/genpeep.c
+++ b/gcc/genpeep.c
@@ -334,7 +334,7 @@ print_code (RTX_CODE code)
{
const char *p1;
for (p1 = GET_RTX_NAME (code); *p1; p1++)
- putchar (TOUPPER(*p1));
+ putchar (TOUPPER (*p1));
}
extern int main (int, char **);
@@ -359,6 +359,7 @@ from the machine description file `md'. */\n\n");
printf ("#include \"coretypes.h\"\n");
printf ("#include \"tm.h\"\n");
printf ("#include \"insn-config.h\"\n");
+ printf ("#include \"tree.h\"\n");
printf ("#include \"rtl.h\"\n");
printf ("#include \"tm_p.h\"\n");
printf ("#include \"regs.h\"\n");
diff --git a/gcc/genpreds.c b/gcc/genpreds.c
index 98488e30b8b..f3d9dac9c55 100644
--- a/gcc/genpreds.c
+++ b/gcc/genpreds.c
@@ -529,7 +529,7 @@ write_match_code_switch (rtx exp)
putchar (TOUPPER (*code));
code++;
}
- fputs(":\n", stdout);
+ fputs (":\n", stdout);
}
}
@@ -596,9 +596,9 @@ write_predicate_stmts (rtx exp)
break;
}
- fputs(" return ",stdout);
+ fputs (" return ",stdout);
write_predicate_expr (exp);
- fputs(";\n", stdout);
+ fputs (";\n", stdout);
}
/* Given a predicate, write out a complete C function to compute it. */
@@ -932,7 +932,7 @@ write_lookup_constraint (void)
" switch (str[0])\n"
" {");
- for (i = 0; i < ARRAY_SIZE(constraints_by_letter_table); i++)
+ for (i = 0; i < ARRAY_SIZE (constraints_by_letter_table); i++)
{
struct constraint_data *c = constraints_by_letter_table[i];
if (!c)
@@ -975,7 +975,7 @@ write_insn_constraint_len (void)
" switch (fc)\n"
" {");
- for (i = 0; i < ARRAY_SIZE(constraints_by_letter_table); i++)
+ for (i = 0; i < ARRAY_SIZE (constraints_by_letter_table); i++)
{
struct constraint_data *c = constraints_by_letter_table[i];
diff --git a/gcc/genrecog.c b/gcc/genrecog.c
index 691b0281175..814be7d17e3 100644
--- a/gcc/genrecog.c
+++ b/gcc/genrecog.c
@@ -58,7 +58,7 @@
#include "gensupport.h"
#define OUTPUT_LABEL(INDENT_STRING, LABEL_NUMBER) \
- printf("%sL%d: ATTRIBUTE_UNUSED_LABEL\n", (INDENT_STRING), (LABEL_NUMBER))
+ printf ("%sL%d: ATTRIBUTE_UNUSED_LABEL\n", (INDENT_STRING), (LABEL_NUMBER))
/* Ways of obtaining an rtx to be tested. */
enum position_type {
@@ -1619,7 +1619,7 @@ write_afterward (struct decision *start, struct decision *afterward,
const char *indent)
{
if (!afterward || start->subroutine_number > 0)
- printf("%sgoto ret0;\n", indent);
+ printf ("%sgoto ret0;\n", indent);
else
{
change_state (start->position, afterward->position, indent);
@@ -1669,7 +1669,7 @@ write_switch (struct decision *start, int depth)
struct decision *ret;
RTX_CODE code;
- memset (codemap, 0, sizeof(codemap));
+ memset (codemap, 0, sizeof (codemap));
printf (" switch (GET_CODE (x%d))\n {\n", depth);
code = p->tests->u.code;
@@ -1762,7 +1762,8 @@ write_switch (struct decision *start, int depth)
if (type == DT_elt_zero_wide_safe)
{
indent = " ";
- printf(" if ((int) XWINT (x%d, 0) == XWINT (x%d, 0))\n", depth, depth);
+ printf (" if ((int) XWINT (x%d, 0) == XWINT (x%d, 0))\n",
+ depth, depth);
}
printf ("%s switch (", indent);
switch (type)
@@ -1937,7 +1938,7 @@ write_action (struct decision *p, struct decision_test *test,
if (test->type == DT_accept_op)
{
- printf("%soperands[%d] = x%d;\n", indent, test->u.opno, depth);
+ printf ("%soperands[%d] = x%d;\n", indent, test->u.opno, depth);
/* Only allow DT_accept_insn to follow. */
if (test->next)
@@ -1992,7 +1993,7 @@ write_action (struct decision *p, struct decision_test *test,
}
else
{
- printf("%sgoto L%d;\n", indent, success->number);
+ printf ("%sgoto L%d;\n", indent, success->number);
success->need_label = 1;
}
@@ -2357,7 +2358,7 @@ make_insn_sequence (rtx insn, enum routine_type type)
validate_pattern (x, insn, NULL_RTX, 0);
- memset(&head, 0, sizeof(head));
+ memset (&head, 0, sizeof (head));
last = add_to_sequence (x, &head, &root_pos, type, 1);
/* Find the end of the test chain on the last node. */
@@ -2423,7 +2424,7 @@ make_insn_sequence (rtx insn, enum routine_type type)
}
/* Recognize it. */
- memset (&clobber_head, 0, sizeof(clobber_head));
+ memset (&clobber_head, 0, sizeof (clobber_head));
last = add_to_sequence (new_rtx, &clobber_head, &root_pos,
type, 1);
@@ -2493,7 +2494,7 @@ process_tree (struct decision_head *head, enum routine_type subroutine_type)
/* We run this after find_afterward, because find_afterward needs
the redundant DT_mode tests on predicates to determine whether
two tests can both be true or not. */
- simplify_tests(head);
+ simplify_tests (head);
write_subroutines (head, subroutine_type);
}
@@ -2601,12 +2602,12 @@ debug_decision_2 (struct decision_test *test)
break;
case DT_pred:
fprintf (stderr, "pred=(%s,%s)",
- test->u.pred.name, GET_MODE_NAME(test->u.pred.mode));
+ test->u.pred.name, GET_MODE_NAME (test->u.pred.mode));
break;
case DT_c_test:
{
char sub[16+4];
- strncpy (sub, test->u.c_test, sizeof(sub));
+ strncpy (sub, test->u.c_test, sizeof (sub));
memcpy (sub+16, "...", 4);
fprintf (stderr, "c_test=\"%s\"", sub);
}
diff --git a/gcc/gensupport.c b/gcc/gensupport.c
index c7a27c42617..e6c5c23a161 100644
--- a/gcc/gensupport.c
+++ b/gcc/gensupport.c
@@ -392,7 +392,7 @@ static struct queue_elem *
queue_pattern (rtx pattern, struct queue_elem ***list_tail,
const char *filename, int lineno)
{
- struct queue_elem *e = XNEW(struct queue_elem);
+ struct queue_elem *e = XNEW (struct queue_elem);
e->data = pattern;
e->filename = filename;
e->lineno = lineno;
@@ -429,7 +429,7 @@ remove_from_queue (struct queue_elem *elem, struct queue_elem **queue)
static void
add_define_attr (const char *name)
{
- struct queue_elem *e = XNEW(struct queue_elem);
+ struct queue_elem *e = XNEW (struct queue_elem);
rtx t1 = rtx_alloc (DEFINE_ATTR);
XSTR (t1, 0) = name;
XSTR (t1, 1) = "no,yes";
@@ -2445,14 +2445,29 @@ gen_mnemonic_attr (void)
bool found = false;
/* Check if the insn definition already has
- (set_attr "mnemonic" ...). */
+ (set_attr "mnemonic" ...) or (set (attr "mnemonic") ...). */
if (XVEC (insn, 4))
for (i = 0; i < XVECLEN (insn, 4); i++)
- if (strcmp (XSTR (XVECEXP (insn, 4, i), 0), MNEMONIC_ATTR_NAME) == 0)
- {
- found = true;
- break;
- }
+ {
+ rtx set_attr = XVECEXP (insn, 4, i);
+
+ switch (GET_CODE (set_attr))
+ {
+ case SET_ATTR:
+ case SET_ATTR_ALTERNATIVE:
+ if (strcmp (XSTR (set_attr, 0), MNEMONIC_ATTR_NAME) == 0)
+ found = true;
+ break;
+ case SET:
+ if (GET_CODE (SET_DEST (set_attr)) == ATTR
+ && strcmp (XSTR (SET_DEST (set_attr), 0),
+ MNEMONIC_ATTR_NAME) == 0)
+ found = true;
+ break;
+ default:
+ break;
+ }
+ }
if (!found)
gen_mnemonic_setattr (mnemonic_htab, insn);
@@ -2870,7 +2885,7 @@ record_insn_name (int code, const char *name)
new_size = (insn_name_ptr_size ? insn_name_ptr_size * 2 : 512);
insn_name_ptr = XRESIZEVEC (char *, insn_name_ptr, new_size);
memset (insn_name_ptr + insn_name_ptr_size, 0,
- sizeof(char *) * (new_size - insn_name_ptr_size));
+ sizeof (char *) * (new_size - insn_name_ptr_size));
insn_name_ptr_size = new_size;
}
diff --git a/gcc/ggc-common.c b/gcc/ggc-common.c
index 0bb2eb19f23..dcabd61433d 100644
--- a/gcc/ggc-common.c
+++ b/gcc/ggc-common.c
@@ -488,7 +488,7 @@ gt_pch_save (FILE *f)
char *this_object = NULL;
size_t this_object_size = 0;
struct mmap_info mmi;
- const size_t mmap_offset_alignment = host_hooks.gt_pch_alloc_granularity();
+ const size_t mmap_offset_alignment = host_hooks.gt_pch_alloc_granularity ();
gt_pch_save_stringpool ();
@@ -749,7 +749,7 @@ default_gt_pch_use_address (void *base, size_t size, int fd ATTRIBUTE_UNUSED,
size_t
default_gt_pch_alloc_granularity (void)
{
- return getpagesize();
+ return getpagesize ();
}
#if HAVE_MMAP_FILE
@@ -837,7 +837,7 @@ ggc_rlimit_bound (double limit)
static int
ggc_min_expand_heuristic (void)
{
- double min_expand = physmem_total();
+ double min_expand = physmem_total ();
/* Adjust for rlimits. */
min_expand = ggc_rlimit_bound (min_expand);
@@ -856,7 +856,7 @@ ggc_min_expand_heuristic (void)
static int
ggc_min_heapsize_heuristic (void)
{
- double phys_kbytes = physmem_total();
+ double phys_kbytes = physmem_total ();
double limit_kbytes = ggc_rlimit_bound (phys_kbytes * 2);
phys_kbytes /= 1024; /* Convert to Kbytes. */
diff --git a/gcc/ggc-page.c b/gcc/ggc-page.c
index 487a6d45c78..f68129e4da6 100644
--- a/gcc/ggc-page.c
+++ b/gcc/ggc-page.c
@@ -30,7 +30,7 @@ along with GCC; see the file COPYING3. If not see
#include "ggc-internal.h"
#include "timevar.h"
#include "params.h"
-#include "tree-ssa.h"
+#include "cgraph.h"
#include "cfgloop.h"
#include "plugin.h"
@@ -462,7 +462,7 @@ static struct globals
/* 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))
+ (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
@@ -785,7 +785,7 @@ alloc_page (unsigned order)
page = alloc_anon (NULL, G.pagesize * GGC_QUIRE_SIZE, false);
if (page == NULL)
{
- page = alloc_anon(NULL, G.pagesize, true);
+ page = alloc_anon (NULL, G.pagesize, true);
entries = 1;
}
@@ -1644,7 +1644,7 @@ init_ggc (void)
{
unsigned order;
- G.pagesize = getpagesize();
+ G.pagesize = getpagesize ();
G.lg_pagesize = exact_log2 (G.pagesize);
#ifdef HAVE_MMAP_DEV_ZERO
@@ -2163,7 +2163,7 @@ ggc_print_statistics (void)
}
fprintf (stderr, "%-5s %10lu%c %10lu%c %10lu%c\n", "Total",
SCALE (G.bytes_mapped), STAT_LABEL (G.bytes_mapped),
- SCALE (G.allocated), STAT_LABEL(G.allocated),
+ SCALE (G.allocated), STAT_LABEL (G.allocated),
SCALE (total_overhead), STAT_LABEL (total_overhead));
if (GATHER_STATISTICS)
@@ -2315,13 +2315,13 @@ ggc_pch_write_object (struct ggc_pch_data *d,
if (size != OBJECT_SIZE (order))
{
- unsigned padding = OBJECT_SIZE(order) - size;
+ 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 (padding <= sizeof (emptyBytes))
{
if (fwrite (emptyBytes, 1, padding, f) != padding)
fatal_error ("can%'t write PCH file");
@@ -2419,7 +2419,7 @@ ggc_pch_read (FILE *f, void *addr)
#endif
/* Since we free all the allocated objects, the free list becomes
useless. Validate it now, which will also clear it. */
- validate_free_objects();
+ 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
diff --git a/gcc/gimple-builder.c b/gcc/gimple-builder.c
new file mode 100644
index 00000000000..6b53221b6b3
--- /dev/null
+++ b/gcc/gimple-builder.c
@@ -0,0 +1,118 @@
+/* Functions for high level gimple building routines.
+ Copyright (C) 2013 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 "tree.h"
+#include "gimple.h"
+#include "tree-ssanames.h"
+
+
+/* Return the expression type to use based on the CODE and type of
+ the given operand OP. If the expression CODE is a comparison,
+ the returned type is boolean_type_node. Otherwise, it returns
+ the type of OP. */
+
+static tree
+get_expr_type (enum tree_code code, tree op)
+{
+ return (TREE_CODE_CLASS (code) == tcc_comparison)
+ ? boolean_type_node
+ : TREE_TYPE (op);
+}
+
+
+/* Build a new gimple assignment. The LHS of the assignment is a new
+ temporary whose type matches the given expression. MODE indicates
+ whether the LHS should be an SSA or a normal temporary. CODE is
+ the expression code for the RHS. OP1 is the first operand and VAL
+ is an integer value to be used as the second operand. */
+
+gimple
+build_assign (enum tree_code code, tree op1, int val, tree lhs)
+{
+ tree op2 = build_int_cst (TREE_TYPE (op1), val);
+ if (lhs == NULL_TREE)
+ lhs = make_ssa_name (get_expr_type (code, op1), NULL);
+ return gimple_build_assign_with_ops (code, lhs, op1, op2);
+}
+
+gimple
+build_assign (enum tree_code code, gimple g, int val, tree lhs )
+{
+ return build_assign (code, gimple_assign_lhs (g), val, lhs);
+}
+
+
+/* Build and return a new GIMPLE assignment. The new assignment will
+ have the opcode CODE and operands OP1 and OP2. The type of the
+ expression on the RHS is inferred to be the type of OP1.
+
+ The LHS of the statement will be an SSA name or a GIMPLE temporary
+ in normal form depending on the type of builder invoking this
+ function. */
+
+gimple
+build_assign (enum tree_code code, tree op1, tree op2, tree lhs)
+{
+ if (lhs == NULL_TREE)
+ lhs = make_ssa_name (get_expr_type (code, op1), NULL);
+ return gimple_build_assign_with_ops (code, lhs, op1, op2);
+}
+
+gimple
+build_assign (enum tree_code code, gimple op1, tree op2, tree lhs)
+{
+ return build_assign (code, gimple_assign_lhs (op1), op2, lhs);
+}
+
+gimple
+build_assign (enum tree_code code, tree op1, gimple op2, tree lhs)
+{
+ return build_assign (code, op1, gimple_assign_lhs (op2), lhs);
+}
+
+gimple
+build_assign (enum tree_code code, gimple op1, gimple op2, tree lhs)
+{
+ return build_assign (code, gimple_assign_lhs (op1), gimple_assign_lhs (op2),
+ lhs);
+}
+
+
+/* Create and return a type cast assignment. This creates a NOP_EXPR
+ that converts OP to TO_TYPE. */
+
+gimple
+build_type_cast (tree to_type, tree op, tree lhs)
+{
+ if (lhs == NULL_TREE)
+ lhs = make_ssa_name (to_type, NULL);
+ return gimple_build_assign_with_ops (NOP_EXPR, lhs, op, NULL_TREE);
+}
+
+gimple
+build_type_cast (tree to_type, gimple op, tree lhs)
+{
+ return build_type_cast (to_type, gimple_assign_lhs (op), lhs);
+}
+
+
+
diff --git a/gcc/gimple-builder.h b/gcc/gimple-builder.h
new file mode 100644
index 00000000000..532c04e2189
--- /dev/null
+++ b/gcc/gimple-builder.h
@@ -0,0 +1,34 @@
+/* Header file for high level statement building routines.
+ Copyright (C) 2013 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_GIMPLE_BUILDER_H
+#define GCC_GIMPLE_BUILDER_H
+
+tree create_gimple_tmp (tree, tree lhs = NULL_TREE);
+gimple build_assign (enum tree_code, tree, int, tree lhs = NULL_TREE);
+gimple build_assign (enum tree_code, gimple, int, tree lhs = NULL_TREE);
+gimple build_assign (enum tree_code, tree, tree, tree lhs = NULL_TREE);
+gimple build_assign (enum tree_code, gimple, tree, tree lhs = NULL_TREE);
+gimple build_assign (enum tree_code, tree, gimple, tree lhs = NULL_TREE);
+gimple build_assign (enum tree_code, gimple, gimple, tree lhs = NULL_TREE);
+gimple build_type_cast (tree, tree, tree lhs = NULL_TREE);
+gimple build_type_cast (tree, gimple, tree lhs = NULL_TREE);
+
+#endif /* GCC_GIMPLE_BUILDER_H */
diff --git a/gcc/gimple-expr.c b/gcc/gimple-expr.c
new file mode 100644
index 00000000000..c74d9295d1d
--- /dev/null
+++ b/gcc/gimple-expr.c
@@ -0,0 +1,721 @@
+/* Gimple decl, type, and expression support functions.
+
+ Copyright (C) 2007-2013 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/>. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "tree.h"
+#include "gimple.h"
+#include "demangle.h"
+
+/* ----- Type related ----- */
+
+/* Return true if the conversion from INNER_TYPE to OUTER_TYPE is a
+ useless type conversion, otherwise return false.
+
+ This function implicitly defines the middle-end type system. With
+ the notion of 'a < b' meaning that useless_type_conversion_p (a, b)
+ holds and 'a > b' meaning that useless_type_conversion_p (b, a) holds,
+ the following invariants shall be fulfilled:
+
+ 1) useless_type_conversion_p is transitive.
+ If a < b and b < c then a < c.
+
+ 2) useless_type_conversion_p is not symmetric.
+ From a < b does not follow a > b.
+
+ 3) Types define the available set of operations applicable to values.
+ A type conversion is useless if the operations for the target type
+ is a subset of the operations for the source type. For example
+ casts to void* are useless, casts from void* are not (void* can't
+ be dereferenced or offsetted, but copied, hence its set of operations
+ is a strict subset of that of all other data pointer types). Casts
+ to const T* are useless (can't be written to), casts from const T*
+ to T* are not. */
+
+bool
+useless_type_conversion_p (tree outer_type, tree inner_type)
+{
+ /* Do the following before stripping toplevel qualifiers. */
+ if (POINTER_TYPE_P (inner_type)
+ && POINTER_TYPE_P (outer_type))
+ {
+ /* Do not lose casts between pointers to different address spaces. */
+ if (TYPE_ADDR_SPACE (TREE_TYPE (outer_type))
+ != TYPE_ADDR_SPACE (TREE_TYPE (inner_type)))
+ return false;
+ }
+
+ /* From now on qualifiers on value types do not matter. */
+ inner_type = TYPE_MAIN_VARIANT (inner_type);
+ outer_type = TYPE_MAIN_VARIANT (outer_type);
+
+ if (inner_type == outer_type)
+ return true;
+
+ /* If we know the canonical types, compare them. */
+ if (TYPE_CANONICAL (inner_type)
+ && TYPE_CANONICAL (inner_type) == TYPE_CANONICAL (outer_type))
+ return true;
+
+ /* Changes in machine mode are never useless conversions unless we
+ deal with aggregate types in which case we defer to later checks. */
+ if (TYPE_MODE (inner_type) != TYPE_MODE (outer_type)
+ && !AGGREGATE_TYPE_P (inner_type))
+ return false;
+
+ /* If both the inner and outer types are integral types, then the
+ conversion is not necessary if they have the same mode and
+ signedness and precision, and both or neither are boolean. */
+ if (INTEGRAL_TYPE_P (inner_type)
+ && INTEGRAL_TYPE_P (outer_type))
+ {
+ /* Preserve changes in signedness or precision. */
+ if (TYPE_UNSIGNED (inner_type) != TYPE_UNSIGNED (outer_type)
+ || TYPE_PRECISION (inner_type) != TYPE_PRECISION (outer_type))
+ return false;
+
+ /* Preserve conversions to/from BOOLEAN_TYPE if types are not
+ of precision one. */
+ if (((TREE_CODE (inner_type) == BOOLEAN_TYPE)
+ != (TREE_CODE (outer_type) == BOOLEAN_TYPE))
+ && TYPE_PRECISION (outer_type) != 1)
+ return false;
+
+ /* We don't need to preserve changes in the types minimum or
+ maximum value in general as these do not generate code
+ unless the types precisions are different. */
+ return true;
+ }
+
+ /* Scalar floating point types with the same mode are compatible. */
+ else if (SCALAR_FLOAT_TYPE_P (inner_type)
+ && SCALAR_FLOAT_TYPE_P (outer_type))
+ return true;
+
+ /* Fixed point types with the same mode are compatible. */
+ else if (FIXED_POINT_TYPE_P (inner_type)
+ && FIXED_POINT_TYPE_P (outer_type))
+ return true;
+
+ /* We need to take special care recursing to pointed-to types. */
+ else if (POINTER_TYPE_P (inner_type)
+ && POINTER_TYPE_P (outer_type))
+ {
+ /* Do not lose casts to function pointer types. */
+ if ((TREE_CODE (TREE_TYPE (outer_type)) == FUNCTION_TYPE
+ || TREE_CODE (TREE_TYPE (outer_type)) == METHOD_TYPE)
+ && !(TREE_CODE (TREE_TYPE (inner_type)) == FUNCTION_TYPE
+ || TREE_CODE (TREE_TYPE (inner_type)) == METHOD_TYPE))
+ return false;
+
+ /* We do not care for const qualification of the pointed-to types
+ as const qualification has no semantic value to the middle-end. */
+
+ /* Otherwise pointers/references are equivalent. */
+ return true;
+ }
+
+ /* Recurse for complex types. */
+ else if (TREE_CODE (inner_type) == COMPLEX_TYPE
+ && TREE_CODE (outer_type) == COMPLEX_TYPE)
+ return useless_type_conversion_p (TREE_TYPE (outer_type),
+ TREE_TYPE (inner_type));
+
+ /* Recurse for vector types with the same number of subparts. */
+ else if (TREE_CODE (inner_type) == VECTOR_TYPE
+ && TREE_CODE (outer_type) == VECTOR_TYPE
+ && TYPE_PRECISION (inner_type) == TYPE_PRECISION (outer_type))
+ return useless_type_conversion_p (TREE_TYPE (outer_type),
+ TREE_TYPE (inner_type));
+
+ else if (TREE_CODE (inner_type) == ARRAY_TYPE
+ && TREE_CODE (outer_type) == ARRAY_TYPE)
+ {
+ /* Preserve string attributes. */
+ if (TYPE_STRING_FLAG (inner_type) != TYPE_STRING_FLAG (outer_type))
+ return false;
+
+ /* Conversions from array types with unknown extent to
+ array types with known extent are not useless. */
+ if (!TYPE_DOMAIN (inner_type)
+ && TYPE_DOMAIN (outer_type))
+ return false;
+
+ /* Nor are conversions from array types with non-constant size to
+ array types with constant size or to different size. */
+ if (TYPE_SIZE (outer_type)
+ && TREE_CODE (TYPE_SIZE (outer_type)) == INTEGER_CST
+ && (!TYPE_SIZE (inner_type)
+ || TREE_CODE (TYPE_SIZE (inner_type)) != INTEGER_CST
+ || !tree_int_cst_equal (TYPE_SIZE (outer_type),
+ TYPE_SIZE (inner_type))))
+ return false;
+
+ /* Check conversions between arrays with partially known extents.
+ If the array min/max values are constant they have to match.
+ Otherwise allow conversions to unknown and variable extents.
+ In particular this declares conversions that may change the
+ mode to BLKmode as useless. */
+ if (TYPE_DOMAIN (inner_type)
+ && TYPE_DOMAIN (outer_type)
+ && TYPE_DOMAIN (inner_type) != TYPE_DOMAIN (outer_type))
+ {
+ tree inner_min = TYPE_MIN_VALUE (TYPE_DOMAIN (inner_type));
+ tree outer_min = TYPE_MIN_VALUE (TYPE_DOMAIN (outer_type));
+ tree inner_max = TYPE_MAX_VALUE (TYPE_DOMAIN (inner_type));
+ tree outer_max = TYPE_MAX_VALUE (TYPE_DOMAIN (outer_type));
+
+ /* After gimplification a variable min/max value carries no
+ additional information compared to a NULL value. All that
+ matters has been lowered to be part of the IL. */
+ if (inner_min && TREE_CODE (inner_min) != INTEGER_CST)
+ inner_min = NULL_TREE;
+ if (outer_min && TREE_CODE (outer_min) != INTEGER_CST)
+ outer_min = NULL_TREE;
+ if (inner_max && TREE_CODE (inner_max) != INTEGER_CST)
+ inner_max = NULL_TREE;
+ if (outer_max && TREE_CODE (outer_max) != INTEGER_CST)
+ outer_max = NULL_TREE;
+
+ /* Conversions NULL / variable <- cst are useless, but not
+ the other way around. */
+ if (outer_min
+ && (!inner_min
+ || !tree_int_cst_equal (inner_min, outer_min)))
+ return false;
+ if (outer_max
+ && (!inner_max
+ || !tree_int_cst_equal (inner_max, outer_max)))
+ return false;
+ }
+
+ /* Recurse on the element check. */
+ return useless_type_conversion_p (TREE_TYPE (outer_type),
+ TREE_TYPE (inner_type));
+ }
+
+ else if ((TREE_CODE (inner_type) == FUNCTION_TYPE
+ || TREE_CODE (inner_type) == METHOD_TYPE)
+ && TREE_CODE (inner_type) == TREE_CODE (outer_type))
+ {
+ tree outer_parm, inner_parm;
+
+ /* If the return types are not compatible bail out. */
+ if (!useless_type_conversion_p (TREE_TYPE (outer_type),
+ TREE_TYPE (inner_type)))
+ return false;
+
+ /* Method types should belong to a compatible base class. */
+ if (TREE_CODE (inner_type) == METHOD_TYPE
+ && !useless_type_conversion_p (TYPE_METHOD_BASETYPE (outer_type),
+ TYPE_METHOD_BASETYPE (inner_type)))
+ return false;
+
+ /* A conversion to an unprototyped argument list is ok. */
+ if (!prototype_p (outer_type))
+ return true;
+
+ /* If the unqualified argument types are compatible the conversion
+ is useless. */
+ if (TYPE_ARG_TYPES (outer_type) == TYPE_ARG_TYPES (inner_type))
+ return true;
+
+ for (outer_parm = TYPE_ARG_TYPES (outer_type),
+ inner_parm = TYPE_ARG_TYPES (inner_type);
+ outer_parm && inner_parm;
+ outer_parm = TREE_CHAIN (outer_parm),
+ inner_parm = TREE_CHAIN (inner_parm))
+ if (!useless_type_conversion_p
+ (TYPE_MAIN_VARIANT (TREE_VALUE (outer_parm)),
+ TYPE_MAIN_VARIANT (TREE_VALUE (inner_parm))))
+ return false;
+
+ /* If there is a mismatch in the number of arguments the functions
+ are not compatible. */
+ if (outer_parm || inner_parm)
+ return false;
+
+ /* Defer to the target if necessary. */
+ if (TYPE_ATTRIBUTES (inner_type) || TYPE_ATTRIBUTES (outer_type))
+ return comp_type_attributes (outer_type, inner_type) != 0;
+
+ return true;
+ }
+
+ /* For aggregates we rely on TYPE_CANONICAL exclusively and require
+ explicit conversions for types involving to be structurally
+ compared types. */
+ else if (AGGREGATE_TYPE_P (inner_type)
+ && TREE_CODE (inner_type) == TREE_CODE (outer_type))
+ return false;
+
+ return false;
+}
+
+
+/* ----- Decl related ----- */
+
+/* Set sequence SEQ to be the GIMPLE body for function FN. */
+
+void
+gimple_set_body (tree fndecl, gimple_seq seq)
+{
+ struct function *fn = DECL_STRUCT_FUNCTION (fndecl);
+ if (fn == NULL)
+ {
+ /* If FNDECL still does not have a function structure associated
+ with it, then it does not make sense for it to receive a
+ GIMPLE body. */
+ gcc_assert (seq == NULL);
+ }
+ else
+ fn->gimple_body = seq;
+}
+
+
+/* Return the body of GIMPLE statements for function FN. After the
+ CFG pass, the function body doesn't exist anymore because it has
+ been split up into basic blocks. In this case, it returns
+ NULL. */
+
+gimple_seq
+gimple_body (tree fndecl)
+{
+ struct function *fn = DECL_STRUCT_FUNCTION (fndecl);
+ return fn ? fn->gimple_body : NULL;
+}
+
+/* Return true when FNDECL has Gimple body either in unlowered
+ or CFG form. */
+bool
+gimple_has_body_p (tree fndecl)
+{
+ struct function *fn = DECL_STRUCT_FUNCTION (fndecl);
+ return (gimple_body (fndecl) || (fn && fn->cfg));
+}
+
+/* Return a printable name for symbol DECL. */
+
+const char *
+gimple_decl_printable_name (tree decl, int verbosity)
+{
+ if (!DECL_NAME (decl))
+ return NULL;
+
+ if (DECL_ASSEMBLER_NAME_SET_P (decl))
+ {
+ const char *str, *mangled_str;
+ int dmgl_opts = DMGL_NO_OPTS;
+
+ if (verbosity >= 2)
+ {
+ dmgl_opts = DMGL_VERBOSE
+ | DMGL_ANSI
+ | DMGL_GNU_V3
+ | DMGL_RET_POSTFIX;
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ dmgl_opts |= DMGL_PARAMS;
+ }
+
+ mangled_str = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+ str = cplus_demangle_v3 (mangled_str, dmgl_opts);
+ return (str) ? str : mangled_str;
+ }
+
+ return IDENTIFIER_POINTER (DECL_NAME (decl));
+}
+
+
+/* Create a new VAR_DECL and copy information from VAR to it. */
+
+tree
+copy_var_decl (tree var, tree name, tree type)
+{
+ tree copy = build_decl (DECL_SOURCE_LOCATION (var), VAR_DECL, name, type);
+
+ TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (var);
+ TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (var);
+ DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (var);
+ DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (var);
+ DECL_IGNORED_P (copy) = DECL_IGNORED_P (var);
+ DECL_CONTEXT (copy) = DECL_CONTEXT (var);
+ TREE_NO_WARNING (copy) = TREE_NO_WARNING (var);
+ TREE_USED (copy) = 1;
+ DECL_SEEN_IN_BIND_EXPR_P (copy) = 1;
+ DECL_ATTRIBUTES (copy) = DECL_ATTRIBUTES (var);
+
+ return copy;
+}
+
+/* Given SSA_NAMEs NAME1 and NAME2, return true if they are candidates for
+ coalescing together, false otherwise.
+
+ This must stay consistent with var_map_base_init in tree-ssa-live.c. */
+
+bool
+gimple_can_coalesce_p (tree name1, tree name2)
+{
+ /* First check the SSA_NAME's associated DECL. We only want to
+ coalesce if they have the same DECL or both have no associated DECL. */
+ tree var1 = SSA_NAME_VAR (name1);
+ tree var2 = SSA_NAME_VAR (name2);
+ var1 = (var1 && (!VAR_P (var1) || !DECL_IGNORED_P (var1))) ? var1 : NULL_TREE;
+ var2 = (var2 && (!VAR_P (var2) || !DECL_IGNORED_P (var2))) ? var2 : NULL_TREE;
+ if (var1 != var2)
+ return false;
+
+ /* Now check the types. If the types are the same, then we should
+ try to coalesce V1 and V2. */
+ tree t1 = TREE_TYPE (name1);
+ tree t2 = TREE_TYPE (name2);
+ if (t1 == t2)
+ return true;
+
+ /* If the types are not the same, check for a canonical type match. This
+ (for example) allows coalescing when the types are fundamentally the
+ same, but just have different names.
+
+ Note pointer types with different address spaces may have the same
+ canonical type. Those are rejected for coalescing by the
+ types_compatible_p check. */
+ if (TYPE_CANONICAL (t1)
+ && TYPE_CANONICAL (t1) == TYPE_CANONICAL (t2)
+ && types_compatible_p (t1, t2))
+ return true;
+
+ return false;
+}
+
+
+/* ----- Expression related ----- */
+
+/* Extract the operands and code for expression EXPR into *SUBCODE_P,
+ *OP1_P, *OP2_P and *OP3_P respectively. */
+
+void
+extract_ops_from_tree_1 (tree expr, enum tree_code *subcode_p, tree *op1_p,
+ tree *op2_p, tree *op3_p)
+{
+ enum gimple_rhs_class grhs_class;
+
+ *subcode_p = TREE_CODE (expr);
+ grhs_class = get_gimple_rhs_class (*subcode_p);
+
+ if (grhs_class == GIMPLE_TERNARY_RHS)
+ {
+ *op1_p = TREE_OPERAND (expr, 0);
+ *op2_p = TREE_OPERAND (expr, 1);
+ *op3_p = TREE_OPERAND (expr, 2);
+ }
+ else if (grhs_class == GIMPLE_BINARY_RHS)
+ {
+ *op1_p = TREE_OPERAND (expr, 0);
+ *op2_p = TREE_OPERAND (expr, 1);
+ *op3_p = NULL_TREE;
+ }
+ else if (grhs_class == GIMPLE_UNARY_RHS)
+ {
+ *op1_p = TREE_OPERAND (expr, 0);
+ *op2_p = NULL_TREE;
+ *op3_p = NULL_TREE;
+ }
+ else if (grhs_class == GIMPLE_SINGLE_RHS)
+ {
+ *op1_p = expr;
+ *op2_p = NULL_TREE;
+ *op3_p = NULL_TREE;
+ }
+ else
+ gcc_unreachable ();
+}
+
+/* Extract operands for a GIMPLE_COND statement out of COND_EXPR tree COND. */
+
+void
+gimple_cond_get_ops_from_tree (tree cond, enum tree_code *code_p,
+ tree *lhs_p, tree *rhs_p)
+{
+ gcc_assert (TREE_CODE_CLASS (TREE_CODE (cond)) == tcc_comparison
+ || TREE_CODE (cond) == TRUTH_NOT_EXPR
+ || is_gimple_min_invariant (cond)
+ || SSA_VAR_P (cond));
+
+ extract_ops_from_tree (cond, code_p, lhs_p, rhs_p);
+
+ /* Canonicalize conditionals of the form 'if (!VAL)'. */
+ if (*code_p == TRUTH_NOT_EXPR)
+ {
+ *code_p = EQ_EXPR;
+ gcc_assert (*lhs_p && *rhs_p == NULL_TREE);
+ *rhs_p = build_zero_cst (TREE_TYPE (*lhs_p));
+ }
+ /* Canonicalize conditionals of the form 'if (VAL)' */
+ else if (TREE_CODE_CLASS (*code_p) != tcc_comparison)
+ {
+ *code_p = NE_EXPR;
+ gcc_assert (*lhs_p && *rhs_p == NULL_TREE);
+ *rhs_p = build_zero_cst (TREE_TYPE (*lhs_p));
+ }
+}
+
+/* Return true if T is a valid LHS for a GIMPLE assignment expression. */
+
+bool
+is_gimple_lvalue (tree t)
+{
+ return (is_gimple_addressable (t)
+ || TREE_CODE (t) == WITH_SIZE_EXPR
+ /* These are complex lvalues, but don't have addresses, so they
+ go here. */
+ || TREE_CODE (t) == BIT_FIELD_REF);
+}
+
+/* Return true if T is a GIMPLE condition. */
+
+bool
+is_gimple_condexpr (tree t)
+{
+ return (is_gimple_val (t) || (COMPARISON_CLASS_P (t)
+ && !tree_could_throw_p (t)
+ && is_gimple_val (TREE_OPERAND (t, 0))
+ && is_gimple_val (TREE_OPERAND (t, 1))));
+}
+
+/* Return true if T is a gimple address. */
+
+bool
+is_gimple_address (const_tree t)
+{
+ tree op;
+
+ if (TREE_CODE (t) != ADDR_EXPR)
+ return false;
+
+ op = TREE_OPERAND (t, 0);
+ while (handled_component_p (op))
+ {
+ if ((TREE_CODE (op) == ARRAY_REF
+ || TREE_CODE (op) == ARRAY_RANGE_REF)
+ && !is_gimple_val (TREE_OPERAND (op, 1)))
+ return false;
+
+ op = TREE_OPERAND (op, 0);
+ }
+
+ if (CONSTANT_CLASS_P (op) || TREE_CODE (op) == MEM_REF)
+ return true;
+
+ switch (TREE_CODE (op))
+ {
+ case PARM_DECL:
+ case RESULT_DECL:
+ case LABEL_DECL:
+ case FUNCTION_DECL:
+ case VAR_DECL:
+ case CONST_DECL:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+/* Return true if T is a gimple invariant address. */
+
+bool
+is_gimple_invariant_address (const_tree t)
+{
+ const_tree op;
+
+ if (TREE_CODE (t) != ADDR_EXPR)
+ return false;
+
+ op = strip_invariant_refs (TREE_OPERAND (t, 0));
+ if (!op)
+ return false;
+
+ if (TREE_CODE (op) == MEM_REF)
+ {
+ const_tree op0 = TREE_OPERAND (op, 0);
+ return (TREE_CODE (op0) == ADDR_EXPR
+ && (CONSTANT_CLASS_P (TREE_OPERAND (op0, 0))
+ || decl_address_invariant_p (TREE_OPERAND (op0, 0))));
+ }
+
+ return CONSTANT_CLASS_P (op) || decl_address_invariant_p (op);
+}
+
+/* Return true if T is a gimple invariant address at IPA level
+ (so addresses of variables on stack are not allowed). */
+
+bool
+is_gimple_ip_invariant_address (const_tree t)
+{
+ const_tree op;
+
+ if (TREE_CODE (t) != ADDR_EXPR)
+ return false;
+
+ op = strip_invariant_refs (TREE_OPERAND (t, 0));
+ if (!op)
+ return false;
+
+ if (TREE_CODE (op) == MEM_REF)
+ {
+ const_tree op0 = TREE_OPERAND (op, 0);
+ return (TREE_CODE (op0) == ADDR_EXPR
+ && (CONSTANT_CLASS_P (TREE_OPERAND (op0, 0))
+ || decl_address_ip_invariant_p (TREE_OPERAND (op0, 0))));
+ }
+
+ return CONSTANT_CLASS_P (op) || decl_address_ip_invariant_p (op);
+}
+
+/* Return true if T is a GIMPLE minimal invariant. It's a restricted
+ form of function invariant. */
+
+bool
+is_gimple_min_invariant (const_tree t)
+{
+ if (TREE_CODE (t) == ADDR_EXPR)
+ return is_gimple_invariant_address (t);
+
+ return is_gimple_constant (t);
+}
+
+/* Return true if T is a GIMPLE interprocedural invariant. It's a restricted
+ form of gimple minimal invariant. */
+
+bool
+is_gimple_ip_invariant (const_tree t)
+{
+ if (TREE_CODE (t) == ADDR_EXPR)
+ return is_gimple_ip_invariant_address (t);
+
+ return is_gimple_constant (t);
+}
+
+/* Return true if T is a non-aggregate register variable. */
+
+bool
+is_gimple_reg (tree t)
+{
+ if (virtual_operand_p (t))
+ return false;
+
+ if (TREE_CODE (t) == SSA_NAME)
+ return true;
+
+ if (!is_gimple_variable (t))
+ return false;
+
+ if (!is_gimple_reg_type (TREE_TYPE (t)))
+ return false;
+
+ /* A volatile decl is not acceptable because we can't reuse it as
+ needed. We need to copy it into a temp first. */
+ if (TREE_THIS_VOLATILE (t))
+ return false;
+
+ /* We define "registers" as things that can be renamed as needed,
+ which with our infrastructure does not apply to memory. */
+ if (needs_to_live_in_memory (t))
+ return false;
+
+ /* Hard register variables are an interesting case. For those that
+ are call-clobbered, we don't know where all the calls are, since
+ we don't (want to) take into account which operations will turn
+ into libcalls at the rtl level. For those that are call-saved,
+ we don't currently model the fact that calls may in fact change
+ global hard registers, nor do we examine ASM_CLOBBERS at the tree
+ level, and so miss variable changes that might imply. All around,
+ it seems safest to not do too much optimization with these at the
+ tree level at all. We'll have to rely on the rtl optimizers to
+ clean this up, as there we've got all the appropriate bits exposed. */
+ if (TREE_CODE (t) == VAR_DECL && DECL_HARD_REGISTER (t))
+ return false;
+
+ /* Complex and vector values must have been put into SSA-like form.
+ That is, no assignments to the individual components. */
+ if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE
+ || TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE)
+ return DECL_GIMPLE_REG_P (t);
+
+ return true;
+}
+
+
+/* Return true if T is a GIMPLE rvalue, i.e. an identifier or a constant. */
+
+bool
+is_gimple_val (tree t)
+{
+ /* Make loads from volatiles and memory vars explicit. */
+ if (is_gimple_variable (t)
+ && is_gimple_reg_type (TREE_TYPE (t))
+ && !is_gimple_reg (t))
+ return false;
+
+ return (is_gimple_variable (t) || is_gimple_min_invariant (t));
+}
+
+/* Similarly, but accept hard registers as inputs to asm statements. */
+
+bool
+is_gimple_asm_val (tree t)
+{
+ if (TREE_CODE (t) == VAR_DECL && DECL_HARD_REGISTER (t))
+ return true;
+
+ return is_gimple_val (t);
+}
+
+/* Return true if T is a GIMPLE minimal lvalue. */
+
+bool
+is_gimple_min_lval (tree t)
+{
+ if (!(t = CONST_CAST_TREE (strip_invariant_refs (t))))
+ return false;
+ return (is_gimple_id (t) || TREE_CODE (t) == MEM_REF);
+}
+
+/* Return true if T is a valid function operand of a CALL_EXPR. */
+
+bool
+is_gimple_call_addr (tree t)
+{
+ return (TREE_CODE (t) == OBJ_TYPE_REF || is_gimple_val (t));
+}
+
+/* Return true if T is a valid address operand of a MEM_REF. */
+
+bool
+is_gimple_mem_ref_addr (tree t)
+{
+ return (is_gimple_reg (t)
+ || TREE_CODE (t) == INTEGER_CST
+ || (TREE_CODE (t) == ADDR_EXPR
+ && (CONSTANT_CLASS_P (TREE_OPERAND (t, 0))
+ || decl_address_invariant_p (TREE_OPERAND (t, 0)))));
+}
diff --git a/gcc/gimple-expr.h b/gcc/gimple-expr.h
new file mode 100644
index 00000000000..aad558cebb7
--- /dev/null
+++ b/gcc/gimple-expr.h
@@ -0,0 +1,171 @@
+/* Header file for gimple decl, type and expressions.
+ Copyright (C) 2013 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_GIMPLE_EXPR_H
+#define GCC_GIMPLE_EXPR_H
+
+extern bool useless_type_conversion_p (tree, tree);
+
+extern void gimple_set_body (tree, gimple_seq);
+extern gimple_seq gimple_body (tree);
+extern bool gimple_has_body_p (tree);
+extern const char *gimple_decl_printable_name (tree, int);
+extern tree copy_var_decl (tree, tree, tree);
+extern bool gimple_can_coalesce_p (tree, tree);
+
+extern void extract_ops_from_tree_1 (tree, enum tree_code *, tree *, tree *,
+ tree *);
+extern void gimple_cond_get_ops_from_tree (tree, enum tree_code *, tree *,
+ tree *);
+extern bool is_gimple_lvalue (tree);
+extern bool is_gimple_condexpr (tree);
+extern bool is_gimple_address (const_tree);
+extern bool is_gimple_invariant_address (const_tree);
+extern bool is_gimple_ip_invariant_address (const_tree);
+extern bool is_gimple_min_invariant (const_tree);
+extern bool is_gimple_ip_invariant (const_tree);
+extern bool is_gimple_reg (tree);
+extern bool is_gimple_val (tree);
+extern bool is_gimple_asm_val (tree);
+extern bool is_gimple_min_lval (tree);
+extern bool is_gimple_call_addr (tree);
+extern bool is_gimple_mem_ref_addr (tree);
+
+/* Return true if a conversion from either type of TYPE1 and TYPE2
+ to the other is not required. Otherwise return false. */
+
+static inline bool
+types_compatible_p (tree type1, tree type2)
+{
+ return (type1 == type2
+ || (useless_type_conversion_p (type1, type2)
+ && useless_type_conversion_p (type2, type1)));
+}
+
+/* Return true if TYPE is a suitable type for a scalar register variable. */
+
+static inline bool
+is_gimple_reg_type (tree type)
+{
+ return !AGGREGATE_TYPE_P (type);
+}
+
+/* Return true if T is a variable. */
+
+static inline bool
+is_gimple_variable (tree t)
+{
+ return (TREE_CODE (t) == VAR_DECL
+ || TREE_CODE (t) == PARM_DECL
+ || TREE_CODE (t) == RESULT_DECL
+ || TREE_CODE (t) == SSA_NAME);
+}
+
+/* Return true if T is a GIMPLE identifier (something with an address). */
+
+static inline bool
+is_gimple_id (tree t)
+{
+ return (is_gimple_variable (t)
+ || TREE_CODE (t) == FUNCTION_DECL
+ || TREE_CODE (t) == LABEL_DECL
+ || TREE_CODE (t) == CONST_DECL
+ /* Allow string constants, since they are addressable. */
+ || TREE_CODE (t) == STRING_CST);
+}
+
+/* Return true if OP, an SSA name or a DECL is a virtual operand. */
+
+static inline bool
+virtual_operand_p (tree op)
+{
+ if (TREE_CODE (op) == SSA_NAME)
+ {
+ op = SSA_NAME_VAR (op);
+ if (!op)
+ return false;
+ }
+
+ if (TREE_CODE (op) == VAR_DECL)
+ return VAR_DECL_IS_VIRTUAL_OPERAND (op);
+
+ return false;
+}
+
+/* Return true if T is something whose address can be taken. */
+
+static inline bool
+is_gimple_addressable (tree t)
+{
+ return (is_gimple_id (t) || handled_component_p (t)
+ || TREE_CODE (t) == MEM_REF);
+}
+
+/* Return true if T is a valid gimple constant. */
+
+static inline bool
+is_gimple_constant (const_tree t)
+{
+ switch (TREE_CODE (t))
+ {
+ case INTEGER_CST:
+ case REAL_CST:
+ case FIXED_CST:
+ case STRING_CST:
+ case COMPLEX_CST:
+ case VECTOR_CST:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+/* A wrapper around extract_ops_from_tree_1, for callers which expect
+ to see only a maximum of two operands. */
+
+static inline void
+extract_ops_from_tree (tree expr, enum tree_code *code, tree *op0,
+ tree *op1)
+{
+ tree op2;
+ extract_ops_from_tree_1 (expr, code, op0, op1, &op2);
+ gcc_assert (op2 == NULL_TREE);
+}
+
+/* Given a valid GIMPLE_CALL function address return the FUNCTION_DECL
+ associated with the callee if known. Otherwise return NULL_TREE. */
+
+static inline tree
+gimple_call_addr_fndecl (const_tree fn)
+{
+ if (fn && TREE_CODE (fn) == ADDR_EXPR)
+ {
+ tree fndecl = TREE_OPERAND (fn, 0);
+ if (TREE_CODE (fndecl) == MEM_REF
+ && TREE_CODE (TREE_OPERAND (fndecl, 0)) == ADDR_EXPR
+ && integer_zerop (TREE_OPERAND (fndecl, 1)))
+ fndecl = TREE_OPERAND (TREE_OPERAND (fndecl, 0), 0);
+ if (TREE_CODE (fndecl) == FUNCTION_DECL)
+ return fndecl;
+ }
+ return NULL_TREE;
+}
+
+#endif /* GCC_GIMPLE_EXPR_H */
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index 51713e64655..89d1ac993f6 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -26,10 +26,19 @@ along with GCC; see the file COPYING3. If not see
#include "flags.h"
#include "function.h"
#include "dumpfile.h"
+#include "bitmap.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-ssanames.h"
+#include "tree-into-ssa.h"
+#include "tree-dfa.h"
#include "tree-ssa.h"
#include "tree-ssa-propagate.h"
#include "target.h"
-#include "gimple-fold.h"
+#include "ipa-utils.h"
+#include "gimple-pretty-print.h"
+#include "tree-ssa-address.h"
+#include "langhooks.h"
/* Return true when DECL can be referenced from current unit.
FROM_DECL (if non-null) specify constructor of variable DECL was taken from.
@@ -48,7 +57,7 @@ along with GCC; see the file COPYING3. If not see
that has no corresponding callgraph/varpool node
declaring the body.
3) COMDAT functions referred by external vtables that
- we devirtualize only during final copmilation stage.
+ we devirtualize only during final compilation stage.
At this time we already decided that we will not output
the function body and thus we can't reference the symbol
directly. */
@@ -58,7 +67,7 @@ can_refer_decl_in_current_unit_p (tree decl, tree from_decl)
{
struct varpool_node *vnode;
struct cgraph_node *node;
- symtab_node snode;
+ symtab_node *snode;
if (DECL_ABSTRACT (decl))
return false;
@@ -85,14 +94,14 @@ can_refer_decl_in_current_unit_p (tree decl, tree from_decl)
|| TREE_CODE (from_decl) != VAR_DECL
|| !DECL_EXTERNAL (from_decl)
|| (flag_ltrans
- && symtab_get_node (from_decl)->symbol.in_other_partition))
+ && symtab_get_node (from_decl)->in_other_partition))
return true;
/* We are folding reference from external vtable. The vtable may reffer
to a symbol keyed to other compilation unit. The other compilation
unit may be in separate DSO and the symbol may be hidden. */
if (DECL_VISIBILITY_SPECIFIED (decl)
&& DECL_EXTERNAL (decl)
- && (!(snode = symtab_get_node (decl)) || !snode->symbol.in_other_partition))
+ && (!(snode = symtab_get_node (decl)) || !snode->in_other_partition))
return false;
/* When function is public, we always can introduce new reference.
Exception are the COMDAT functions where introducing a direct
@@ -123,7 +132,7 @@ can_refer_decl_in_current_unit_p (tree decl, tree from_decl)
The second is important when devirtualization happens during final
compilation stage when making a new reference no longer makes callee
to be compiled. */
- if (!node || !node->symbol.definition || node->global.inlined_to)
+ if (!node || !node->definition || node->global.inlined_to)
{
gcc_checking_assert (!TREE_ASM_WRITTEN (decl));
return false;
@@ -132,7 +141,7 @@ can_refer_decl_in_current_unit_p (tree decl, tree from_decl)
else if (TREE_CODE (decl) == VAR_DECL)
{
vnode = varpool_get_node (decl);
- if (!vnode || !vnode->symbol.definition)
+ if (!vnode || !vnode->definition)
{
gcc_checking_assert (!TREE_ASM_WRITTEN (decl));
return false;
@@ -197,6 +206,8 @@ canonicalize_constructor_val (tree cval, tree from_decl)
cval = fold_convert (TREE_TYPE (orig_cval), cval);
return cval;
}
+ if (TREE_OVERFLOW_P (cval))
+ return drop_tree_overflow (cval);
return orig_cval;
}
@@ -1116,6 +1127,19 @@ gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace)
{
if (gimple_call_addr_fndecl (OBJ_TYPE_REF_EXPR (callee)) != NULL_TREE)
{
+ if (dump_file && virtual_method_call_p (callee)
+ && !possible_polymorphic_call_target_p
+ (callee, cgraph_get_node (gimple_call_addr_fndecl
+ (OBJ_TYPE_REF_EXPR (callee)))))
+ {
+ fprintf (dump_file,
+ "Type inheritnace inconsistent devirtualization of ");
+ print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
+ fprintf (dump_file, " to ");
+ print_generic_expr (dump_file, callee, TDF_SLIM);
+ fprintf (dump_file, "\n");
+ }
+
gimple_call_set_fn (stmt, OBJ_TYPE_REF_EXPR (callee));
changed = true;
}
@@ -1131,6 +1155,11 @@ gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace)
tree fndecl = gimple_get_virt_method_for_binfo (token, binfo);
if (fndecl)
{
+#ifdef ENABLE_CHECKING
+ gcc_assert (possible_polymorphic_call_target_p
+ (callee, cgraph_get_node (fndecl)));
+
+#endif
gimple_call_set_fndecl (stmt, fndecl);
changed = true;
}
@@ -2805,7 +2834,7 @@ fold_array_ctor_reference (tree type, tree ctor,
else
low_bound = double_int_zero;
/* Static constructors for variably sized objects makes no sense. */
- gcc_assert (TREE_CODE(TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ctor))))
+ gcc_assert (TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ctor))))
== INTEGER_CST);
elt_size =
tree_to_double_int (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ctor))));
@@ -3302,3 +3331,125 @@ gimple_val_nonnegative_real_p (tree val)
return false;
}
+
+/* Given a pointer value OP0, return a simplified version of an
+ indirection through OP0, or NULL_TREE if no simplification is
+ possible. Note that the resulting type may be different from
+ the type pointed to in the sense that it is still compatible
+ from the langhooks point of view. */
+
+tree
+gimple_fold_indirect_ref (tree t)
+{
+ tree ptype = TREE_TYPE (t), type = TREE_TYPE (ptype);
+ tree sub = t;
+ tree subtype;
+
+ STRIP_NOPS (sub);
+ subtype = TREE_TYPE (sub);
+ if (!POINTER_TYPE_P (subtype))
+ return NULL_TREE;
+
+ if (TREE_CODE (sub) == ADDR_EXPR)
+ {
+ tree op = TREE_OPERAND (sub, 0);
+ tree optype = TREE_TYPE (op);
+ /* *&p => p */
+ if (useless_type_conversion_p (type, optype))
+ return op;
+
+ /* *(foo *)&fooarray => fooarray[0] */
+ if (TREE_CODE (optype) == ARRAY_TYPE
+ && TREE_CODE (TYPE_SIZE (TREE_TYPE (optype))) == INTEGER_CST
+ && useless_type_conversion_p (type, TREE_TYPE (optype)))
+ {
+ tree type_domain = TYPE_DOMAIN (optype);
+ tree min_val = size_zero_node;
+ if (type_domain && TYPE_MIN_VALUE (type_domain))
+ min_val = TYPE_MIN_VALUE (type_domain);
+ if (TREE_CODE (min_val) == INTEGER_CST)
+ return build4 (ARRAY_REF, type, op, min_val, NULL_TREE, NULL_TREE);
+ }
+ /* *(foo *)&complexfoo => __real__ complexfoo */
+ else if (TREE_CODE (optype) == COMPLEX_TYPE
+ && useless_type_conversion_p (type, TREE_TYPE (optype)))
+ return fold_build1 (REALPART_EXPR, type, op);
+ /* *(foo *)&vectorfoo => BIT_FIELD_REF<vectorfoo,...> */
+ else if (TREE_CODE (optype) == VECTOR_TYPE
+ && useless_type_conversion_p (type, TREE_TYPE (optype)))
+ {
+ tree part_width = TYPE_SIZE (type);
+ tree index = bitsize_int (0);
+ return fold_build3 (BIT_FIELD_REF, type, op, part_width, index);
+ }
+ }
+
+ /* *(p + CST) -> ... */
+ if (TREE_CODE (sub) == POINTER_PLUS_EXPR
+ && TREE_CODE (TREE_OPERAND (sub, 1)) == INTEGER_CST)
+ {
+ tree addr = TREE_OPERAND (sub, 0);
+ tree off = TREE_OPERAND (sub, 1);
+ tree addrtype;
+
+ STRIP_NOPS (addr);
+ addrtype = TREE_TYPE (addr);
+
+ /* ((foo*)&vectorfoo)[1] -> BIT_FIELD_REF<vectorfoo,...> */
+ if (TREE_CODE (addr) == ADDR_EXPR
+ && TREE_CODE (TREE_TYPE (addrtype)) == VECTOR_TYPE
+ && useless_type_conversion_p (type, TREE_TYPE (TREE_TYPE (addrtype)))
+ && host_integerp (off, 1))
+ {
+ unsigned HOST_WIDE_INT offset = tree_low_cst (off, 1);
+ tree part_width = TYPE_SIZE (type);
+ unsigned HOST_WIDE_INT part_widthi
+ = tree_low_cst (part_width, 0) / BITS_PER_UNIT;
+ unsigned HOST_WIDE_INT indexi = offset * BITS_PER_UNIT;
+ tree index = bitsize_int (indexi);
+ if (offset / part_widthi
+ <= TYPE_VECTOR_SUBPARTS (TREE_TYPE (addrtype)))
+ return fold_build3 (BIT_FIELD_REF, type, TREE_OPERAND (addr, 0),
+ part_width, index);
+ }
+
+ /* ((foo*)&complexfoo)[1] -> __imag__ complexfoo */
+ if (TREE_CODE (addr) == ADDR_EXPR
+ && TREE_CODE (TREE_TYPE (addrtype)) == COMPLEX_TYPE
+ && useless_type_conversion_p (type, TREE_TYPE (TREE_TYPE (addrtype))))
+ {
+ tree size = TYPE_SIZE_UNIT (type);
+ if (tree_int_cst_equal (size, off))
+ return fold_build1 (IMAGPART_EXPR, type, TREE_OPERAND (addr, 0));
+ }
+
+ /* *(p + CST) -> MEM_REF <p, CST>. */
+ if (TREE_CODE (addr) != ADDR_EXPR
+ || DECL_P (TREE_OPERAND (addr, 0)))
+ return fold_build2 (MEM_REF, type,
+ addr,
+ build_int_cst_wide (ptype,
+ TREE_INT_CST_LOW (off),
+ TREE_INT_CST_HIGH (off)));
+ }
+
+ /* *(foo *)fooarrptr => (*fooarrptr)[0] */
+ if (TREE_CODE (TREE_TYPE (subtype)) == ARRAY_TYPE
+ && TREE_CODE (TYPE_SIZE (TREE_TYPE (TREE_TYPE (subtype)))) == INTEGER_CST
+ && useless_type_conversion_p (type, TREE_TYPE (TREE_TYPE (subtype))))
+ {
+ tree type_domain;
+ tree min_val = size_zero_node;
+ tree osub = sub;
+ sub = gimple_fold_indirect_ref (sub);
+ if (! sub)
+ sub = build1 (INDIRECT_REF, TREE_TYPE (subtype), osub);
+ type_domain = TYPE_DOMAIN (TREE_TYPE (sub));
+ if (type_domain && TYPE_MIN_VALUE (type_domain))
+ min_val = TYPE_MIN_VALUE (type_domain);
+ if (TREE_CODE (min_val) == INTEGER_CST)
+ return build4 (ARRAY_REF, type, sub, min_val, NULL_TREE, NULL_TREE);
+ }
+
+ return NULL_TREE;
+}
diff --git a/gcc/gimple-fold.h b/gcc/gimple-fold.h
index fb0502add8e..7a631a9604d 100644
--- a/gcc/gimple-fold.h
+++ b/gcc/gimple-fold.h
@@ -22,10 +22,23 @@ along with GCC; see the file COPYING3. If not see
#ifndef GCC_GIMPLE_FOLD_H
#define GCC_GIMPLE_FOLD_H
-tree fold_const_aggregate_ref_1 (tree, tree (*) (tree));
-tree fold_const_aggregate_ref (tree);
-
-tree gimple_fold_stmt_to_constant_1 (gimple, tree (*) (tree));
-tree gimple_fold_stmt_to_constant (gimple, tree (*) (tree));
+extern tree canonicalize_constructor_val (tree, tree);
+extern tree get_symbol_constant_value (tree);
+extern void gimplify_and_update_call_from_tree (gimple_stmt_iterator *, tree);
+extern tree gimple_fold_builtin (gimple);
+extern tree gimple_extract_devirt_binfo_from_cst (tree, tree);
+extern bool fold_stmt (gimple_stmt_iterator *);
+extern bool fold_stmt_inplace (gimple_stmt_iterator *);
+extern tree maybe_fold_and_comparisons (enum tree_code, tree, tree,
+ enum tree_code, tree, tree);
+extern tree maybe_fold_or_comparisons (enum tree_code, tree, tree,
+ enum tree_code, tree, tree);
+extern tree gimple_fold_stmt_to_constant_1 (gimple, tree (*) (tree));
+extern tree gimple_fold_stmt_to_constant (gimple, tree (*) (tree));
+extern tree fold_const_aggregate_ref_1 (tree, tree (*) (tree));
+extern tree fold_const_aggregate_ref (tree);
+extern tree gimple_get_virt_method_for_binfo (HOST_WIDE_INT, tree);
+extern bool gimple_val_nonnegative_real_p (tree);
+extern tree gimple_fold_indirect_ref (tree);
#endif /* GCC_GIMPLE_FOLD_H */
diff --git a/gcc/gimple-iterator.c b/gcc/gimple-iterator.c
index 574e31f298f..e430050fcf7 100644
--- a/gcc/gimple-iterator.c
+++ b/gcc/gimple-iterator.c
@@ -24,6 +24,11 @@ along with GCC; see the file COPYING3. If not see
#include "tm.h"
#include "tree.h"
#include "gimple.h"
+#include "gimple-ssa.h"
+#include "cgraph.h"
+#include "tree-cfg.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
#include "tree-ssa.h"
#include "value-prof.h"
diff --git a/gcc/gimple-low.c b/gcc/gimple-low.c
index a46a69f56ed..d527d86ab22 100644
--- a/gcc/gimple-low.c
+++ b/gcc/gimple-low.c
@@ -26,12 +26,12 @@ along with GCC; see the file COPYING3. If not see
#include "gimple.h"
#include "tree-iterator.h"
#include "tree-inline.h"
-#include "tree-ssa.h"
#include "flags.h"
#include "function.h"
#include "diagnostic-core.h"
#include "tree-pass.h"
#include "langhooks.h"
+#include "gimple-low.h"
/* The differences between High GIMPLE and Low GIMPLE are the
following:
@@ -118,7 +118,8 @@ lower_function_body (void)
need to do anything special. Otherwise build one by hand. */
if (gimple_seq_may_fallthru (lowered_body)
&& (data.return_statements.is_empty ()
- || gimple_return_retval (data.return_statements.last().stmt) != NULL))
+ || (gimple_return_retval (data.return_statements.last().stmt)
+ != NULL)))
{
x = gimple_build_return (NULL);
gimple_set_location (x, cfun->function_end_locus);
@@ -197,8 +198,8 @@ const pass_data pass_data_lower_cf =
class pass_lower_cf : public gimple_opt_pass
{
public:
- pass_lower_cf(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_lower_cf, ctxt)
+ pass_lower_cf (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_lower_cf, ctxt)
{}
/* opt_pass methods: */
@@ -214,103 +215,6 @@ make_pass_lower_cf (gcc::context *ctxt)
return new pass_lower_cf (ctxt);
}
-
-
-/* Verify if the type of the argument matches that of the function
- declaration. If we cannot verify this or there is a mismatch,
- return false. */
-
-static bool
-gimple_check_call_args (gimple stmt, tree fndecl, bool args_count_match)
-{
- tree parms, p;
- unsigned int i, nargs;
-
- /* Calls to internal functions always match their signature. */
- if (gimple_call_internal_p (stmt))
- return true;
-
- nargs = gimple_call_num_args (stmt);
-
- /* Get argument types for verification. */
- if (fndecl)
- parms = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
- else
- parms = TYPE_ARG_TYPES (gimple_call_fntype (stmt));
-
- /* Verify if the type of the argument matches that of the function
- declaration. If we cannot verify this or there is a mismatch,
- return false. */
- if (fndecl && DECL_ARGUMENTS (fndecl))
- {
- for (i = 0, p = DECL_ARGUMENTS (fndecl);
- i < nargs;
- i++, p = DECL_CHAIN (p))
- {
- tree arg;
- /* We cannot distinguish a varargs function from the case
- of excess parameters, still deferring the inlining decision
- to the callee is possible. */
- if (!p)
- break;
- arg = gimple_call_arg (stmt, i);
- if (p == error_mark_node
- || arg == error_mark_node
- || (!types_compatible_p (DECL_ARG_TYPE (p), TREE_TYPE (arg))
- && !fold_convertible_p (DECL_ARG_TYPE (p), arg)))
- return false;
- }
- if (args_count_match && p)
- return false;
- }
- else if (parms)
- {
- for (i = 0, p = parms; i < nargs; i++, p = TREE_CHAIN (p))
- {
- tree arg;
- /* If this is a varargs function defer inlining decision
- to callee. */
- if (!p)
- break;
- arg = gimple_call_arg (stmt, i);
- if (TREE_VALUE (p) == error_mark_node
- || arg == error_mark_node
- || TREE_CODE (TREE_VALUE (p)) == VOID_TYPE
- || (!types_compatible_p (TREE_VALUE (p), TREE_TYPE (arg))
- && !fold_convertible_p (TREE_VALUE (p), arg)))
- return false;
- }
- }
- else
- {
- if (nargs != 0)
- return false;
- }
- return true;
-}
-
-/* Verify if the type of the argument and lhs of CALL_STMT matches
- that of the function declaration CALLEE. If ARGS_COUNT_MATCH is
- true, the arg count needs to be the same.
- If we cannot verify this or there is a mismatch, return false. */
-
-bool
-gimple_check_call_matching_types (gimple call_stmt, tree callee,
- bool args_count_match)
-{
- tree lhs;
-
- if ((DECL_RESULT (callee)
- && !DECL_BY_REFERENCE (DECL_RESULT (callee))
- && (lhs = gimple_call_lhs (call_stmt)) != NULL_TREE
- && !useless_type_conversion_p (TREE_TYPE (DECL_RESULT (callee)),
- TREE_TYPE (lhs))
- && !fold_convertible_p (TREE_TYPE (DECL_RESULT (callee)), lhs))
- || !gimple_check_call_args (call_stmt, callee, args_count_match))
- return false;
- return true;
-}
-
/* Lower sequence SEQ. Unlike gimplification the statements are not relowered
when they are changed -- if this has to be done, the lowering routine must
do it explicitly. DATA is passed through the recursion. */
@@ -424,6 +328,7 @@ lower_stmt (gimple_stmt_iterator *gsi, struct lower_data *data)
case GIMPLE_OMP_SECTION:
case GIMPLE_OMP_SINGLE:
case GIMPLE_OMP_MASTER:
+ case GIMPLE_OMP_TASKGROUP:
case GIMPLE_OMP_ORDERED:
case GIMPLE_OMP_CRITICAL:
case GIMPLE_OMP_RETURN:
@@ -465,6 +370,8 @@ lower_stmt (gimple_stmt_iterator *gsi, struct lower_data *data)
case GIMPLE_OMP_PARALLEL:
case GIMPLE_OMP_TASK:
+ case GIMPLE_OMP_TARGET:
+ case GIMPLE_OMP_TEAMS:
data->cannot_fallthru = false;
lower_omp_directive (gsi, data);
data->cannot_fallthru = false;
@@ -597,56 +504,9 @@ lower_try_catch (gimple_stmt_iterator *gsi, struct lower_data *data)
gsi_next (gsi);
}
-/* Try to determine whether a TRY_CATCH expression can fall through.
- This is a subroutine of block_may_fallthru. */
-
-static bool
-try_catch_may_fallthru (const_tree stmt)
-{
- tree_stmt_iterator i;
-
- /* If the TRY block can fall through, the whole TRY_CATCH can
- fall through. */
- if (block_may_fallthru (TREE_OPERAND (stmt, 0)))
- return true;
-
- i = tsi_start (TREE_OPERAND (stmt, 1));
- switch (TREE_CODE (tsi_stmt (i)))
- {
- case CATCH_EXPR:
- /* We expect to see a sequence of CATCH_EXPR trees, each with a
- catch expression and a body. The whole TRY_CATCH may fall
- through iff any of the catch bodies falls through. */
- for (; !tsi_end_p (i); tsi_next (&i))
- {
- if (block_may_fallthru (CATCH_BODY (tsi_stmt (i))))
- return true;
- }
- return false;
- case EH_FILTER_EXPR:
- /* The exception filter expression only matters if there is an
- exception. If the exception does not match EH_FILTER_TYPES,
- we will execute EH_FILTER_FAILURE, and we will fall through
- if that falls through. If the exception does match
- EH_FILTER_TYPES, the stack unwinder will continue up the
- stack, so we will not fall through. We don't know whether we
- will throw an exception which matches EH_FILTER_TYPES or not,
- so we just ignore EH_FILTER_TYPES and assume that we might
- throw an exception which doesn't match. */
- return block_may_fallthru (EH_FILTER_FAILURE (tsi_stmt (i)));
-
- default:
- /* This case represents statements to be executed when an
- exception occurs. Those statements are implicitly followed
- by a RESX statement to resume execution after the exception.
- So in this case the TRY_CATCH never falls through. */
- return false;
- }
-}
-
-
-/* Same as above, but for a GIMPLE_TRY_CATCH. */
+/* Try to determine whether a TRY_CATCH expression can fall through.
+ This is a subroutine of gimple_stmt_may_fallthru. */
static bool
gimple_try_catch_may_fallthru (gimple stmt)
@@ -697,81 +557,6 @@ gimple_try_catch_may_fallthru (gimple stmt)
}
-/* Try to determine if we can fall out of the bottom of BLOCK. This guess
- need not be 100% accurate; simply be conservative and return true if we
- don't know. This is used only to avoid stupidly generating extra code.
- If we're wrong, we'll just delete the extra code later. */
-
-bool
-block_may_fallthru (const_tree block)
-{
- /* This CONST_CAST is okay because expr_last returns its argument
- unmodified and we assign it to a const_tree. */
- const_tree stmt = expr_last (CONST_CAST_TREE(block));
-
- switch (stmt ? TREE_CODE (stmt) : ERROR_MARK)
- {
- case GOTO_EXPR:
- case RETURN_EXPR:
- /* Easy cases. If the last statement of the block implies
- control transfer, then we can't fall through. */
- return false;
-
- case SWITCH_EXPR:
- /* If SWITCH_LABELS is set, this is lowered, and represents a
- branch to a selected label and hence can not fall through.
- Otherwise SWITCH_BODY is set, and the switch can fall
- through. */
- return SWITCH_LABELS (stmt) == NULL_TREE;
-
- case COND_EXPR:
- if (block_may_fallthru (COND_EXPR_THEN (stmt)))
- return true;
- return block_may_fallthru (COND_EXPR_ELSE (stmt));
-
- case BIND_EXPR:
- return block_may_fallthru (BIND_EXPR_BODY (stmt));
-
- case TRY_CATCH_EXPR:
- return try_catch_may_fallthru (stmt);
-
- case TRY_FINALLY_EXPR:
- /* The finally clause is always executed after the try clause,
- so if it does not fall through, then the try-finally will not
- fall through. Otherwise, if the try clause does not fall
- through, then when the finally clause falls through it will
- resume execution wherever the try clause was going. So the
- whole try-finally will only fall through if both the try
- clause and the finally clause fall through. */
- return (block_may_fallthru (TREE_OPERAND (stmt, 0))
- && block_may_fallthru (TREE_OPERAND (stmt, 1)));
-
- case MODIFY_EXPR:
- if (TREE_CODE (TREE_OPERAND (stmt, 1)) == CALL_EXPR)
- stmt = TREE_OPERAND (stmt, 1);
- else
- return true;
- /* FALLTHRU */
-
- case CALL_EXPR:
- /* Functions that do not return do not fall through. */
- return (call_expr_flags (stmt) & ECF_NORETURN) == 0;
-
- case CLEANUP_POINT_EXPR:
- return block_may_fallthru (TREE_OPERAND (stmt, 0));
-
- case TARGET_EXPR:
- return block_may_fallthru (TREE_OPERAND (stmt, 1));
-
- case ERROR_MARK:
- return true;
-
- default:
- return lang_hooks.block_may_fallthru (stmt);
- }
-}
-
-
/* Try to determine if we can continue executing the statement
immediately following STMT. This guess need not be 100% accurate;
simply be conservative and return true if we don't know. This is
diff --git a/gcc/gimple-low.h b/gcc/gimple-low.h
new file mode 100644
index 00000000000..7e8ff6c74d8
--- /dev/null
+++ b/gcc/gimple-low.h
@@ -0,0 +1,28 @@
+/* Header file for gimple lowering pass.
+ Copyright (C) 2013 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_GIMPLE_LOW_H
+#define GCC_GIMPLE_LOW_H
+
+extern bool gimple_stmt_may_fallthru (gimple);
+extern bool gimple_seq_may_fallthru (gimple_seq);
+extern void record_vars_into (tree, tree);
+extern void record_vars (tree);
+
+#endif /* GCC_GIMPLE_LOW_H */
diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c
index 01a1ab56680..6842213199a 100644
--- a/gcc/gimple-pretty-print.c
+++ b/gcc/gimple-pretty-print.c
@@ -27,9 +27,13 @@ along with GCC; see the file COPYING3. If not see
#include "diagnostic.h"
#include "gimple-pretty-print.h"
#include "hashtab.h"
-#include "tree-ssa.h"
-#include "dumpfile.h" /* for dump_flags */
+#include "bitmap.h"
#include "gimple.h"
+#include "gimple-ssa.h"
+#include "cgraph.h"
+#include "tree-cfg.h"
+#include "tree-ssanames.h"
+#include "dumpfile.h" /* for dump_flags */
#include "value-prof.h"
#include "trans-mem.h"
@@ -312,7 +316,7 @@ dump_unary_rhs (pretty_printer *buffer, gimple gs, int spc, int flags)
else
{
pp_left_bracket (buffer);
- pp_string (buffer, tree_code_name [rhs_code]);
+ pp_string (buffer, get_tree_code_name (rhs_code));
pp_string (buffer, "] ");
}
@@ -351,7 +355,7 @@ dump_binary_rhs (pretty_printer *buffer, gimple gs, int spc, int flags)
case VEC_PACK_FIX_TRUNC_EXPR:
case VEC_WIDEN_LSHIFT_HI_EXPR:
case VEC_WIDEN_LSHIFT_LO_EXPR:
- for (p = tree_code_name [(int) code]; *p; p++)
+ for (p = get_tree_code_name (code); *p; p++)
pp_character (buffer, TOUPPER (*p));
pp_string (buffer, " <");
dump_generic_node (buffer, gimple_assign_rhs1 (gs), spc, flags, false);
@@ -397,7 +401,7 @@ dump_ternary_rhs (pretty_printer *buffer, gimple gs, int spc, int flags)
{
case WIDEN_MULT_PLUS_EXPR:
case WIDEN_MULT_MINUS_EXPR:
- for (p = tree_code_name [(int) code]; *p; p++)
+ for (p = get_tree_code_name (code); *p; p++)
pp_character (buffer, TOUPPER (*p));
pp_string (buffer, " <");
dump_generic_node (buffer, gimple_assign_rhs1 (gs), spc, flags, false);
@@ -495,7 +499,7 @@ dump_gimple_assign (pretty_printer *buffer, gimple gs, int spc, int flags)
}
dump_gimple_fmt (buffer, spc, flags, "%G <%s, %T, %T, %T, %T>", gs,
- tree_code_name[gimple_assign_rhs_code (gs)],
+ get_tree_code_name (gimple_assign_rhs_code (gs)),
gimple_assign_lhs (gs), arg1, arg2, arg3);
}
else
@@ -524,7 +528,7 @@ dump_gimple_assign (pretty_printer *buffer, gimple gs, int spc, int flags)
else
gcc_unreachable ();
if (!(flags & TDF_RHS_ONLY))
- pp_semicolon(buffer);
+ pp_semicolon (buffer);
}
}
@@ -535,11 +539,12 @@ dump_gimple_assign (pretty_printer *buffer, gimple gs, int spc, int flags)
static void
dump_gimple_return (pretty_printer *buffer, gimple gs, int spc, int flags)
{
- tree t;
+ tree t, t2;
t = gimple_return_retval (gs);
+ t2 = gimple_return_retbnd (gs);
if (flags & TDF_RAW)
- dump_gimple_fmt (buffer, spc, flags, "%G <%T>", gs, t);
+ dump_gimple_fmt (buffer, spc, flags, "%G <%T %T>", gs, t, t2);
else
{
pp_string (buffer, "return");
@@ -548,6 +553,11 @@ dump_gimple_return (pretty_printer *buffer, gimple gs, int spc, int flags)
pp_space (buffer);
dump_generic_node (buffer, t, spc, flags, false);
}
+ if (t2)
+ {
+ pp_string (buffer, ", ");
+ dump_generic_node (buffer, t2, spc, flags, false);
+ }
pp_semicolon (buffer);
}
}
@@ -790,9 +800,9 @@ dump_gimple_cond (pretty_printer *buffer, gimple gs, int spc, int flags)
{
if (flags & TDF_RAW)
dump_gimple_fmt (buffer, spc, flags, "%G <%s, %T, %T, %T, %T>", gs,
- tree_code_name [gimple_cond_code (gs)],
- gimple_cond_lhs (gs), gimple_cond_rhs (gs),
- gimple_cond_true_label (gs), gimple_cond_false_label (gs));
+ get_tree_code_name (gimple_cond_code (gs)),
+ gimple_cond_lhs (gs), gimple_cond_rhs (gs),
+ gimple_cond_true_label (gs), gimple_cond_false_label (gs));
else
{
if (!(flags & TDF_RHS_ONLY))
@@ -1097,6 +1107,9 @@ dump_gimple_omp_for (pretty_printer *buffer, gimple gs, int spc, int flags)
case GF_OMP_FOR_KIND_SIMD:
kind = " simd";
break;
+ case GF_OMP_FOR_KIND_DISTRIBUTE:
+ kind = " distribute";
+ break;
default:
gcc_unreachable ();
}
@@ -1110,7 +1123,7 @@ dump_gimple_omp_for (pretty_printer *buffer, gimple gs, int spc, int flags)
gimple_omp_for_index (gs, i),
gimple_omp_for_initial (gs, i),
gimple_omp_for_final (gs, i),
- tree_code_name[gimple_omp_for_cond (gs, i)],
+ get_tree_code_name (gimple_omp_for_cond (gs, i)),
gimple_omp_for_incr (gs, i));
dump_gimple_fmt (buffer, spc, flags, "PRE_BODY <%S>%->",
gimple_omp_for_pre_body (gs));
@@ -1125,6 +1138,9 @@ dump_gimple_omp_for (pretty_printer *buffer, gimple gs, int spc, int flags)
case GF_OMP_FOR_KIND_SIMD:
pp_string (buffer, "#pragma omp simd");
break;
+ case GF_OMP_FOR_KIND_DISTRIBUTE:
+ pp_string (buffer, "#pragma omp distribute");
+ break;
default:
gcc_unreachable ();
}
@@ -1239,6 +1255,85 @@ dump_gimple_omp_single (pretty_printer *buffer, gimple gs, int spc, int flags)
}
}
+/* Dump a GIMPLE_OMP_TARGET tuple on the pretty_printer BUFFER. */
+
+static void
+dump_gimple_omp_target (pretty_printer *buffer, gimple gs, int spc, int flags)
+{
+ const char *kind;
+ switch (gimple_omp_target_kind (gs))
+ {
+ case GF_OMP_TARGET_KIND_REGION:
+ kind = "";
+ break;
+ case GF_OMP_TARGET_KIND_DATA:
+ kind = " data";
+ break;
+ case GF_OMP_TARGET_KIND_UPDATE:
+ kind = " update";
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ if (flags & TDF_RAW)
+ {
+ dump_gimple_fmt (buffer, spc, flags, "%G%s <%+BODY <%S>%nCLAUSES <", gs,
+ kind, gimple_omp_body (gs));
+ dump_omp_clauses (buffer, gimple_omp_target_clauses (gs), spc, flags);
+ dump_gimple_fmt (buffer, spc, flags, " >");
+ }
+ else
+ {
+ pp_string (buffer, "#pragma omp target");
+ pp_string (buffer, kind);
+ dump_omp_clauses (buffer, gimple_omp_target_clauses (gs), spc, flags);
+ if (gimple_omp_target_child_fn (gs))
+ {
+ pp_string (buffer, " [child fn: ");
+ dump_generic_node (buffer, gimple_omp_target_child_fn (gs),
+ spc, flags, false);
+ pp_right_bracket (buffer);
+ }
+ if (!gimple_seq_empty_p (gimple_omp_body (gs)))
+ {
+ newline_and_indent (buffer, spc + 2);
+ pp_character (buffer, '{');
+ pp_newline (buffer);
+ dump_gimple_seq (buffer, gimple_omp_body (gs), spc + 4, flags);
+ newline_and_indent (buffer, spc + 2);
+ pp_character (buffer, '}');
+ }
+ }
+}
+
+/* Dump a GIMPLE_OMP_TEAMS tuple on the pretty_printer BUFFER. */
+
+static void
+dump_gimple_omp_teams (pretty_printer *buffer, gimple gs, int spc, int flags)
+{
+ if (flags & TDF_RAW)
+ {
+ dump_gimple_fmt (buffer, spc, flags, "%G <%+BODY <%S>%nCLAUSES <", gs,
+ gimple_omp_body (gs));
+ dump_omp_clauses (buffer, gimple_omp_teams_clauses (gs), spc, flags);
+ dump_gimple_fmt (buffer, spc, flags, " >");
+ }
+ else
+ {
+ pp_string (buffer, "#pragma omp teams");
+ dump_omp_clauses (buffer, gimple_omp_teams_clauses (gs), spc, flags);
+ if (!gimple_seq_empty_p (gimple_omp_body (gs)))
+ {
+ newline_and_indent (buffer, spc + 2);
+ pp_character (buffer, '{');
+ pp_newline (buffer);
+ dump_gimple_seq (buffer, gimple_omp_body (gs), spc + 4, flags);
+ newline_and_indent (buffer, spc + 2);
+ pp_character (buffer, '}');
+ }
+ }
+}
+
/* Dump a GIMPLE_OMP_SECTIONS tuple on the pretty_printer BUFFER. */
static void
@@ -1275,8 +1370,8 @@ dump_gimple_omp_sections (pretty_printer *buffer, gimple gs, int spc,
}
}
-/* Dump a GIMPLE_OMP_{MASTER,ORDERED,SECTION} tuple on the pretty_printer
- BUFFER. */
+/* Dump a GIMPLE_OMP_{MASTER,TASKGROUP,ORDERED,SECTION} tuple on the
+ pretty_printer BUFFER. */
static void
dump_gimple_omp_block (pretty_printer *buffer, gimple gs, int spc, int flags)
@@ -1291,6 +1386,9 @@ dump_gimple_omp_block (pretty_printer *buffer, gimple gs, int spc, int flags)
case GIMPLE_OMP_MASTER:
pp_string (buffer, "#pragma omp master");
break;
+ case GIMPLE_OMP_TASKGROUP:
+ pp_string (buffer, "#pragma omp taskgroup");
+ break;
case GIMPLE_OMP_ORDERED:
pp_string (buffer, "#pragma omp ordered");
break;
@@ -1350,14 +1448,26 @@ dump_gimple_omp_return (pretty_printer *buffer, gimple gs, int spc, int flags)
{
if (flags & TDF_RAW)
{
- dump_gimple_fmt (buffer, spc, flags, "%G <nowait=%d>", gs,
+ dump_gimple_fmt (buffer, spc, flags, "%G <nowait=%d", gs,
(int) gimple_omp_return_nowait_p (gs));
+ if (gimple_omp_return_lhs (gs))
+ dump_gimple_fmt (buffer, spc, flags, ", lhs=%T>",
+ gimple_omp_return_lhs (gs));
+ else
+ dump_gimple_fmt (buffer, spc, flags, ">");
}
else
{
pp_string (buffer, "#pragma omp return");
if (gimple_omp_return_nowait_p (gs))
pp_string (buffer, "(nowait)");
+ if (gimple_omp_return_lhs (gs))
+ {
+ pp_string (buffer, " (set ");
+ dump_generic_node (buffer, gimple_omp_return_lhs (gs),
+ spc, flags, false);
+ pp_character (buffer, ')');
+ }
}
}
@@ -1600,24 +1710,21 @@ dump_gimple_asm (pretty_printer *buffer, gimple gs, int spc, int flags)
}
}
-
-/* Dump a PHI node PHI. BUFFER, SPC and FLAGS are as in pp_gimple_stmt_1.
- The caller is responsible for calling pp_flush on BUFFER to finalize
- pretty printer. */
+/* Dump ptr_info and range_info for NODE on pretty_printer BUFFER with
+ SPC spaces of indent. */
static void
-dump_gimple_phi (pretty_printer *buffer, gimple phi, int spc, int flags)
+dump_ssaname_info (pretty_printer *buffer, tree node, int spc)
{
- size_t i;
- tree lhs = gimple_phi_result (phi);
+ if (TREE_CODE (node) != SSA_NAME)
+ return;
- if (flags & TDF_ALIAS
- && POINTER_TYPE_P (TREE_TYPE (lhs))
- && SSA_NAME_PTR_INFO (lhs))
+ if (POINTER_TYPE_P (TREE_TYPE (node))
+ && SSA_NAME_PTR_INFO (node))
{
unsigned int align, misalign;
- struct ptr_info_def *pi = SSA_NAME_PTR_INFO (lhs);
- pp_string (buffer, "PT = ");
+ struct ptr_info_def *pi = SSA_NAME_PTR_INFO (node);
+ pp_string (buffer, "# PT = ");
pp_points_to_solution (buffer, &pi->pt);
newline_and_indent (buffer, spc);
if (get_ptr_info_alignment (pi, &align, &misalign))
@@ -1625,12 +1732,62 @@ dump_gimple_phi (pretty_printer *buffer, gimple phi, int spc, int flags)
pp_printf (buffer, "# ALIGN = %u, MISALIGN = %u", align, misalign);
newline_and_indent (buffer, spc);
}
- pp_string (buffer, "# ");
}
+ if (!POINTER_TYPE_P (TREE_TYPE (node))
+ && SSA_NAME_RANGE_INFO (node))
+ {
+ double_int min, max, nonzero_bits;
+ value_range_type range_type = get_range_info (node, &min, &max);
+
+ if (range_type == VR_VARYING)
+ pp_printf (buffer, "# RANGE VR_VARYING");
+ else if (range_type == VR_RANGE || range_type == VR_ANTI_RANGE)
+ {
+ pp_printf (buffer, "# RANGE ");
+ pp_printf (buffer, "%s[", range_type == VR_RANGE ? "" : "~");
+ pp_double_int (buffer, min, TYPE_UNSIGNED (TREE_TYPE (node)));
+ pp_printf (buffer, ", ");
+ pp_double_int (buffer, max, TYPE_UNSIGNED (TREE_TYPE (node)));
+ pp_printf (buffer, "]");
+ }
+ nonzero_bits = get_nonzero_bits (node);
+ if (nonzero_bits != double_int_minus_one
+ && (nonzero_bits
+ != double_int::mask (TYPE_PRECISION (TREE_TYPE (node)))))
+ {
+ pp_string (buffer, " NONZERO ");
+ sprintf (pp_buffer (buffer)->digit_buffer,
+ HOST_WIDE_INT_PRINT_DOUBLE_HEX,
+ (unsigned HOST_WIDE_INT) nonzero_bits.high,
+ nonzero_bits.low);
+ pp_string (buffer, pp_buffer (buffer)->digit_buffer);
+ }
+ newline_and_indent (buffer, spc);
+ }
+}
+
+
+/* Dump a PHI node PHI. BUFFER, SPC and FLAGS are as in pp_gimple_stmt_1.
+ The caller is responsible for calling pp_flush on BUFFER to finalize
+ pretty printer. If COMMENT is true, print this after #. */
+
+static void
+dump_gimple_phi (pretty_printer *buffer, gimple phi, int spc, bool comment,
+ int flags)
+{
+ size_t i;
+ tree lhs = gimple_phi_result (phi);
+
+ if (flags & TDF_ALIAS)
+ dump_ssaname_info (buffer, lhs, spc);
+
+ if (comment)
+ pp_string (buffer, "# ");
+
if (flags & TDF_RAW)
- dump_gimple_fmt (buffer, spc, flags, "%G <%T, ", phi,
- gimple_phi_result (phi));
+ dump_gimple_fmt (buffer, spc, flags, "%G <%T, ", phi,
+ gimple_phi_result (phi));
else
{
dump_generic_node (buffer, lhs, spc, flags, false);
@@ -1794,6 +1951,8 @@ dump_gimple_omp_atomic_load (pretty_printer *buffer, gimple gs, int spc,
else
{
pp_string (buffer, "#pragma omp atomic_load");
+ if (gimple_omp_atomic_seq_cst_p (gs))
+ pp_string (buffer, " seq_cst");
if (gimple_omp_atomic_need_value_p (gs))
pp_string (buffer, " [needed]");
newline_and_indent (buffer, spc + 2);
@@ -1824,6 +1983,8 @@ dump_gimple_omp_atomic_store (pretty_printer *buffer, gimple gs, int spc,
else
{
pp_string (buffer, "#pragma omp atomic_store ");
+ if (gimple_omp_atomic_seq_cst_p (gs))
+ pp_string (buffer, "seq_cst ");
if (gimple_omp_atomic_need_value_p (gs))
pp_string (buffer, "[needed] ");
pp_left_paren (buffer);
@@ -1908,27 +2069,9 @@ pp_gimple_stmt_1 (pretty_printer *buffer, gimple gs, int spc, int flags)
&& gimple_has_mem_ops (gs))
dump_gimple_mem_ops (buffer, gs, spc, flags);
- if ((flags & TDF_ALIAS)
- && gimple_has_lhs (gs))
- {
- tree lhs = gimple_get_lhs (gs);
- if (TREE_CODE (lhs) == SSA_NAME
- && POINTER_TYPE_P (TREE_TYPE (lhs))
- && SSA_NAME_PTR_INFO (lhs))
- {
- unsigned int align, misalign;
- struct ptr_info_def *pi = SSA_NAME_PTR_INFO (lhs);
- pp_string (buffer, "# PT = ");
- pp_points_to_solution (buffer, &pi->pt);
- newline_and_indent (buffer, spc);
- if (get_ptr_info_alignment (pi, &align, &misalign))
- {
- pp_printf (buffer, "# ALIGN = %u, MISALIGN = %u",
- align, misalign);
- newline_and_indent (buffer, spc);
- }
- }
- }
+ if (gimple_has_lhs (gs)
+ && (flags & TDF_ALIAS))
+ dump_ssaname_info (buffer, gimple_get_lhs (gs), spc);
switch (gimple_code (gs))
{
@@ -1977,7 +2120,7 @@ pp_gimple_stmt_1 (pretty_printer *buffer, gimple gs, int spc, int flags)
break;
case GIMPLE_PHI:
- dump_gimple_phi (buffer, gs, spc, flags);
+ dump_gimple_phi (buffer, gs, spc, false, flags);
break;
case GIMPLE_OMP_PARALLEL:
@@ -2009,6 +2152,14 @@ pp_gimple_stmt_1 (pretty_printer *buffer, gimple gs, int spc, int flags)
dump_gimple_omp_single (buffer, gs, spc, flags);
break;
+ case GIMPLE_OMP_TARGET:
+ dump_gimple_omp_target (buffer, gs, spc, flags);
+ break;
+
+ case GIMPLE_OMP_TEAMS:
+ dump_gimple_omp_teams (buffer, gs, spc, flags);
+ break;
+
case GIMPLE_OMP_RETURN:
dump_gimple_omp_return (buffer, gs, spc, flags);
break;
@@ -2022,6 +2173,7 @@ pp_gimple_stmt_1 (pretty_printer *buffer, gimple gs, int spc, int flags)
break;
case GIMPLE_OMP_MASTER:
+ case GIMPLE_OMP_TASKGROUP:
case GIMPLE_OMP_ORDERED:
case GIMPLE_OMP_SECTION:
dump_gimple_omp_block (buffer, gs, spc, flags);
@@ -2144,8 +2296,7 @@ dump_phi_nodes (pretty_printer *buffer, basic_block bb, int indent, int flags)
if (!virtual_operand_p (gimple_phi_result (phi)) || (flags & TDF_VOPS))
{
INDENT (indent);
- pp_string (buffer, "# ");
- dump_gimple_phi (buffer, phi, indent, flags);
+ dump_gimple_phi (buffer, phi, indent, true, flags);
pp_newline (buffer);
}
}
@@ -2271,7 +2422,7 @@ gimple_dump_bb_buff (pretty_printer *buffer, basic_block bb, int indent,
pp_newline_and_flush (buffer);
gcc_checking_assert (DECL_STRUCT_FUNCTION (current_function_decl));
dump_histograms_for_stmt (DECL_STRUCT_FUNCTION (current_function_decl),
- pp_buffer(buffer)->stream, stmt);
+ pp_buffer (buffer)->stream, stmt);
}
dump_implicit_edges (buffer, bb, indent, flags);
diff --git a/gcc/gimple-pretty-print.h b/gcc/gimple-pretty-print.h
index 2b0285d356c..5227eb8d584 100644
--- a/gcc/gimple-pretty-print.h
+++ b/gcc/gimple-pretty-print.h
@@ -33,6 +33,7 @@ extern void debug (gimple_statement_d &ref);
extern void debug (gimple_statement_d *ptr);
extern void print_gimple_expr (FILE *, gimple, int, int);
extern void pp_gimple_stmt_1 (pretty_printer *, gimple, int, int);
+extern void gimple_dump_bb (FILE *, basic_block, int, int);
extern void gimple_dump_bb_for_graph (pretty_printer *, basic_block);
#endif /* ! GCC_GIMPLE_PRETTY_PRINT_H */
diff --git a/gcc/gimple-ssa-isolate-paths.c b/gcc/gimple-ssa-isolate-paths.c
new file mode 100644
index 00000000000..983ed4d7602
--- /dev/null
+++ b/gcc/gimple-ssa-isolate-paths.c
@@ -0,0 +1,324 @@
+/* Detect paths through the CFG which can never be executed in a conforming
+ program and isolate them.
+
+ Copyright (C) 2013
+ 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 "tree.h"
+#include "flags.h"
+#include "basic-block.h"
+#include "gimple.h"
+#include "tree-ssa.h"
+#include "tree-ssanames.h"
+#include "gimple-ssa.h"
+#include "tree-ssa-operands.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "cfgloop.h"
+#include "tree-pass.h"
+
+
+static bool cfg_altered;
+
+/* Insert a trap before SI and remove SI and all statements after SI. */
+
+static void
+insert_trap_and_remove_trailing_statements (gimple_stmt_iterator *si_p)
+{
+ gimple_seq seq = NULL;
+ gimple stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
+ gimple_seq_add_stmt (&seq, stmt);
+ gsi_insert_before (si_p, seq, GSI_SAME_STMT);
+
+ /* Now delete all remaining statements in this block. */
+ for (; !gsi_end_p (*si_p);)
+ {
+ stmt = gsi_stmt (*si_p);
+ unlink_stmt_vdef (stmt);
+ gsi_remove (si_p, true);
+ release_defs (stmt);
+ }
+}
+
+/* BB when reached via incoming edge E will exhibit undefined behaviour
+ at STMT. Isolate and optimize the path which exhibits undefined
+ behaviour.
+
+ Isolation is simple. Duplicate BB and redirect E to BB'.
+
+ Optimization is simple as well. Replace STMT in BB' with an
+ unconditional trap and remove all outgoing edges from BB'.
+
+ DUPLICATE is a pre-existing duplicate, use it as BB' if it exists.
+
+ Return BB'. */
+
+basic_block
+isolate_path (basic_block bb, basic_block duplicate, edge e, gimple stmt)
+{
+ gimple_stmt_iterator si, si2;
+ edge_iterator ei;
+ edge e2;
+
+
+ /* First duplicate BB if we have not done so already and remove all
+ the duplicate's outgoing edges as duplicate is going to unconditionally
+ trap. Removing the outgoing edges is both an optimization and ensures
+ we don't need to do any PHI node updates. */
+ if (!duplicate)
+ {
+ duplicate = duplicate_block (bb, NULL, NULL);
+ for (ei = ei_start (duplicate->succs); (e2 = ei_safe_edge (ei)); )
+ remove_edge (e2);
+ }
+
+ /* Complete the isolation step by redirecting E to reach DUPLICATE. */
+ e2 = redirect_edge_and_branch (e, duplicate);
+ if (e2)
+ flush_pending_stmts (e2);
+
+
+ /* There may be more than one statement in DUPLICATE which exhibits
+ undefined behaviour. Ultimately we want the first such statement in
+ DUPLCIATE so that we're able to delete as much code as possible.
+
+ So each time we discover undefined behaviour in DUPLICATE, search for
+ the statement which triggers undefined behaviour. If found, then
+ transform the statement into a trap and delete everything after the
+ statement. If not found, then this particular instance was subsumed by
+ an earlier instance of undefined behaviour and there's nothing to do.
+
+ This is made more complicated by the fact that we have STMT, which is in
+ BB rather than in DUPLICATE. So we set up two iterators, one for each
+ block and walk forward looking for STMT in BB, advancing each iterator at
+ each step.
+
+ When we find STMT the second iterator should point to STMT's equivalent in
+ duplicate. If DUPLICATE ends before STMT is found in BB, then there's
+ nothing to do.
+
+ Ignore labels and debug statements. */
+ si = gsi_start_nondebug_after_labels_bb (bb);
+ si2 = gsi_start_nondebug_after_labels_bb (duplicate);
+ while (!gsi_end_p (si) && !gsi_end_p (si2) && gsi_stmt (si) != stmt)
+ {
+ gsi_next_nondebug (&si);
+ gsi_next_nondebug (&si2);
+ }
+
+ /* This would be an indicator that we never found STMT in BB, which should
+ never happen. */
+ gcc_assert (!gsi_end_p (si));
+
+ /* If we did not run to the end of DUPLICATE, then SI points to STMT and
+ SI2 points to the duplicate of STMT in DUPLICATE. Insert a trap
+ before SI2 and remove SI2 and all trailing statements. */
+ if (!gsi_end_p (si2))
+ insert_trap_and_remove_trailing_statements (&si2);
+
+ return duplicate;
+}
+
+/* Search the function for statements which, if executed, would cause
+ the program to fault such as a dereference of a NULL pointer.
+
+ Such a program can't be valid if such a statement was to execute
+ according to ISO standards.
+
+ We detect explicit NULL pointer dereferences as well as those implied
+ by a PHI argument having a NULL value which unconditionally flows into
+ a dereference in the same block as the PHI.
+
+ In the former case we replace the offending statement with an
+ unconditional trap and eliminate the outgoing edges from the statement's
+ basic block. This may expose secondary optimization opportunities.
+
+ In the latter case, we isolate the path(s) with the NULL PHI
+ feeding the dereference. We can then replace the offending statement
+ and eliminate the outgoing edges in the duplicate. Again, this may
+ expose secondary optimization opportunities.
+
+ A warning for both cases may be advisable as well.
+
+ Other statically detectable violations of the ISO standard could be
+ handled in a similar way, such as out-of-bounds array indexing. */
+
+static unsigned int
+gimple_ssa_isolate_erroneous_paths (void)
+{
+ basic_block bb;
+
+ initialize_original_copy_tables ();
+
+ /* Search all the blocks for edges which, if traversed, will
+ result in undefined behaviour. */
+ cfg_altered = false;
+ FOR_EACH_BB (bb)
+ {
+ gimple_stmt_iterator si;
+
+ /* First look for a PHI which sets a pointer to NULL and which
+ is then dereferenced within BB. This is somewhat overly
+ conservative, but probably catches most of the interesting
+ cases. */
+ for (si = gsi_start_phis (bb); !gsi_end_p (si); gsi_next (&si))
+ {
+ gimple phi = gsi_stmt (si);
+ tree lhs = gimple_phi_result (phi);
+
+ /* If the result is not a pointer, then there is no need to
+ examine the arguments. */
+ if (!POINTER_TYPE_P (TREE_TYPE (lhs)))
+ continue;
+
+ /* PHI produces a pointer result. See if any of the PHI's
+ arguments are NULL.
+
+ When we remove an edge, we want to reprocess the current
+ index, hence the ugly way we update I for each iteration. */
+ basic_block duplicate = NULL;
+ for (unsigned i = 0, next_i = 0;
+ i < gimple_phi_num_args (phi);
+ i = next_i)
+ {
+ tree op = gimple_phi_arg_def (phi, i);
+
+ next_i = i + 1;
+
+ if (!integer_zerop (op))
+ continue;
+
+ edge e = gimple_phi_arg_edge (phi, i);
+ imm_use_iterator iter;
+ gimple use_stmt;
+
+ /* We've got a NULL PHI argument. Now see if the
+ PHI's result is dereferenced within BB. */
+ FOR_EACH_IMM_USE_STMT (use_stmt, iter, lhs)
+ {
+ /* We only care about uses in BB. Catching cases in
+ in other blocks would require more complex path
+ isolation code. */
+ if (gimple_bb (use_stmt) != bb)
+ continue;
+
+ if (infer_nonnull_range (use_stmt, lhs))
+ {
+ duplicate = isolate_path (bb, duplicate,
+ e, use_stmt);
+
+ /* When we remove an incoming edge, we need to
+ reprocess the Ith element. */
+ next_i = i;
+ cfg_altered = true;
+ }
+ }
+ }
+ }
+
+ /* Now look at the statements in the block and see if any of
+ them explicitly dereference a NULL pointer. This happens
+ because of jump threading and constant propagation. */
+ for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
+ {
+ gimple stmt = gsi_stmt (si);
+
+ /* By passing null_pointer_node, we can use infer_nonnull_range
+ to detect explicit NULL pointer dereferences and other uses
+ where a non-NULL value is required. */
+ if (infer_nonnull_range (stmt, null_pointer_node))
+ {
+ insert_trap_and_remove_trailing_statements (&si);
+
+ /* And finally, remove all outgoing edges from BB. */
+ edge e;
+ for (edge_iterator ei = ei_start (bb->succs);
+ (e = ei_safe_edge (ei)); )
+ remove_edge (e);
+
+ /* Ignore any more operands on this statement and
+ continue the statement iterator (which should
+ terminate its loop immediately. */
+ cfg_altered = true;
+ break;
+ }
+ }
+ }
+ free_original_copy_tables ();
+
+ /* We scramble the CFG and loop structures a bit, clean up
+ appropriately. We really should incrementally update the
+ loop structures, in theory it shouldn't be that hard. */
+ if (cfg_altered)
+ {
+ free_dominance_info (CDI_DOMINATORS);
+ free_dominance_info (CDI_POST_DOMINATORS);
+ loops_state_set (LOOPS_NEED_FIXUP);
+ return TODO_cleanup_cfg | TODO_update_ssa;
+ }
+ return 0;
+}
+
+static bool
+gate_isolate_erroneous_paths (void)
+{
+ /* If we do not have a suitable builtin function for the trap statement,
+ then do not perform the optimization. */
+ return (flag_isolate_erroneous_paths != 0);
+}
+
+namespace {
+const pass_data pass_data_isolate_erroneous_paths =
+{
+ GIMPLE_PASS, /* type */
+ "isolate-paths", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
+ true, /* has_gate */
+ true, /* has_execute */
+ TV_ISOLATE_ERRONEOUS_PATHS, /* tv_id */
+ ( PROP_cfg | PROP_ssa ), /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ TODO_verify_ssa, /* todo_flags_finish */
+};
+
+class pass_isolate_erroneous_paths : public gimple_opt_pass
+{
+public:
+ pass_isolate_erroneous_paths (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_isolate_erroneous_paths, ctxt)
+ {}
+
+ /* opt_pass methods: */
+ opt_pass * clone () { return new pass_isolate_erroneous_paths (m_ctxt); }
+ bool gate () { return gate_isolate_erroneous_paths (); }
+ unsigned int execute () { return gimple_ssa_isolate_erroneous_paths (); }
+
+}; // class pass_uncprop
+}
+
+gimple_opt_pass *
+make_pass_isolate_erroneous_paths (gcc::context *ctxt)
+{
+ return new pass_isolate_erroneous_paths (ctxt);
+}
diff --git a/gcc/gimple-ssa-strength-reduction.c b/gcc/gimple-ssa-strength-reduction.c
index 8d48adde01d..88afc91200f 100644
--- a/gcc/gimple-ssa-strength-reduction.c
+++ b/gcc/gimple-ssa-strength-reduction.c
@@ -42,12 +42,17 @@ along with GCC; see the file COPYING3. If not see
#include "tree-pass.h"
#include "cfgloop.h"
#include "gimple-pretty-print.h"
-#include "tree-ssa.h"
+#include "gimple-ssa.h"
+#include "tree-cfg.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
#include "domwalk.h"
#include "pointer-set.h"
#include "expmed.h"
#include "params.h"
#include "hash-table.h"
+#include "tree-ssa-address.h"
/* Information about a strength reduction candidate. Each statement
in the candidate table represents an expression of one of the
@@ -379,6 +384,7 @@ static bool address_arithmetic_p;
/* Forward function declarations. */
static slsr_cand_t base_cand_from_table (tree);
static tree introduce_cast_before_cand (slsr_cand_t, tree, tree);
+static bool legal_cast_p_1 (tree, tree);
/* Produce a pointer to the IDX'th candidate in the candidate vector. */
@@ -768,6 +774,14 @@ backtrace_base_for_ref (tree *pbase)
slsr_cand_t base_cand;
STRIP_NOPS (base_in);
+
+ /* Strip off widening conversion(s) to handle cases where
+ e.g. 'B' is widened from an 'int' in order to calculate
+ a 64-bit address. */
+ if (CONVERT_EXPR_P (base_in)
+ && legal_cast_p_1 (base_in, TREE_OPERAND (base_in, 0)))
+ base_in = get_unwidened (base_in, NULL_TREE);
+
if (TREE_CODE (base_in) != SSA_NAME)
return tree_to_double_int (integer_zero_node);
@@ -786,7 +800,7 @@ backtrace_base_for_ref (tree *pbase)
else if (base_cand->kind == CAND_ADD
&& TREE_CODE (base_cand->stride) == INTEGER_CST
&& integer_onep (base_cand->stride))
- {
+ {
/* X = B + (i * S), S is integer one. */
*pbase = base_cand->base_expr;
return base_cand->index;
@@ -3564,8 +3578,8 @@ const pass_data pass_data_strength_reduction =
class pass_strength_reduction : public gimple_opt_pass
{
public:
- pass_strength_reduction(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_strength_reduction, ctxt)
+ pass_strength_reduction (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_strength_reduction, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/gimple-ssa.h b/gcc/gimple-ssa.h
new file mode 100644
index 00000000000..23aa099ba51
--- /dev/null
+++ b/gcc/gimple-ssa.h
@@ -0,0 +1,154 @@
+/* Header file for routines that straddle the border between GIMPLE and
+ SSA in gimple.
+ Copyright (C) 2009-2013 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_GIMPLE_SSA_H
+#define GCC_GIMPLE_SSA_H
+
+#include "tree-ssa-operands.h"
+
+/* This structure is used to map a gimple statement to a label,
+ or list of labels to represent transaction restart. */
+
+struct GTY(()) tm_restart_node {
+ gimple stmt;
+ tree label_or_list;
+};
+
+/* Gimple dataflow datastructure. All publicly available fields shall have
+ gimple_ accessor defined, all publicly modifiable fields should have
+ gimple_set accessor. */
+struct GTY(()) gimple_df {
+ /* A vector of all the noreturn calls passed to modify_stmt.
+ cleanup_control_flow uses it to detect cases where a mid-block
+ indirect call has been turned into a noreturn call. When this
+ happens, all the instructions after the call are no longer
+ reachable and must be deleted as dead. */
+ vec<gimple, va_gc> *modified_noreturn_calls;
+
+ /* Array of all SSA_NAMEs used in the function. */
+ vec<tree, va_gc> *ssa_names;
+
+ /* Artificial variable used for the virtual operand FUD chain. */
+ tree vop;
+
+ /* The PTA solution for the ESCAPED artificial variable. */
+ struct pt_solution escaped;
+
+ /* A map of decls to artificial ssa-names that point to the partition
+ of the decl. */
+ struct pointer_map_t * GTY((skip(""))) decls_to_pointers;
+
+ /* Free list of SSA_NAMEs. */
+ vec<tree, va_gc> *free_ssanames;
+
+ /* Hashtable holding definition for symbol. If this field is not NULL, it
+ means that the first reference to this variable in the function is a
+ USE or a VUSE. In those cases, the SSA renamer creates an SSA name
+ for this variable with an empty defining statement. */
+ htab_t GTY((param_is (union tree_node))) default_defs;
+
+ /* True if there are any symbols that need to be renamed. */
+ unsigned int ssa_renaming_needed : 1;
+
+ /* True if all virtual operands need to be renamed. */
+ unsigned int rename_vops : 1;
+
+ /* True if the code is in ssa form. */
+ unsigned int in_ssa_p : 1;
+
+ /* True if IPA points-to information was computed for this function. */
+ unsigned int ipa_pta : 1;
+
+ struct ssa_operands ssa_operands;
+
+ /* Map gimple stmt to tree label (or list of labels) for transaction
+ restart and abort. */
+ htab_t GTY ((param_is (struct tm_restart_node))) tm_restart;
+};
+
+
+/* Return true when gimple SSA form was built.
+ gimple_in_ssa_p is queried by gimplifier in various early stages before SSA
+ infrastructure is initialized. Check for presence of the datastructures
+ at first place. */
+static inline bool
+gimple_in_ssa_p (const struct function *fun)
+{
+ return fun && fun->gimple_df && fun->gimple_df->in_ssa_p;
+}
+
+/* Artificial variable used for the virtual operand FUD chain. */
+static inline tree
+gimple_vop (const struct function *fun)
+{
+ gcc_checking_assert (fun && fun->gimple_df);
+ return fun->gimple_df->vop;
+}
+
+/* Return the set of VUSE operand for statement G. */
+
+static inline use_operand_p
+gimple_vuse_op (const_gimple g)
+{
+ struct use_optype_d *ops;
+ if (!gimple_has_mem_ops (g))
+ return NULL_USE_OPERAND_P;
+ ops = g->gsops.opbase.use_ops;
+ if (ops
+ && USE_OP_PTR (ops)->use == &g->gsmembase.vuse)
+ return USE_OP_PTR (ops);
+ return NULL_USE_OPERAND_P;
+}
+
+/* Return the set of VDEF operand for statement G. */
+
+static inline def_operand_p
+gimple_vdef_op (gimple g)
+{
+ if (!gimple_has_mem_ops (g))
+ return NULL_DEF_OPERAND_P;
+ if (g->gsmembase.vdef)
+ return &g->gsmembase.vdef;
+ return NULL_DEF_OPERAND_P;
+}
+
+/* Mark statement S as modified, and update it. */
+
+static inline void
+update_stmt (gimple s)
+{
+ if (gimple_has_ops (s))
+ {
+ gimple_set_modified (s, true);
+ update_stmt_operands (s);
+ }
+}
+
+/* Update statement S if it has been optimized. */
+
+static inline void
+update_stmt_if_modified (gimple s)
+{
+ if (gimple_modified_p (s))
+ update_stmt_operands (s);
+}
+
+
+#endif /* GCC_GIMPLE_SSA_H */
diff --git a/gcc/gimple-streamer-in.c b/gcc/gimple-streamer-in.c
index 8161a087656..2a19aab44fe 100644
--- a/gcc/gimple-streamer-in.c
+++ b/gcc/gimple-streamer-in.c
@@ -24,7 +24,10 @@ along with GCC; see the file COPYING3. If not see
#include "coretypes.h"
#include "diagnostic.h"
#include "tree.h"
-#include "tree-ssa.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-phinodes.h"
+#include "tree-ssanames.h"
#include "data-streamer.h"
#include "tree-streamer.h"
#include "gimple-streamer.h"
diff --git a/gcc/gimple-streamer-out.c b/gcc/gimple-streamer-out.c
index 33699bbbfa9..976f57ecef4 100644
--- a/gcc/gimple-streamer-out.c
+++ b/gcc/gimple-streamer-out.c
@@ -23,7 +23,8 @@ along with GCC; see the file COPYING3. If not see
#include "system.h"
#include "coretypes.h"
#include "tree.h"
-#include "tree-ssa.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
#include "data-streamer.h"
#include "gimple-streamer.h"
#include "lto-streamer.h"
diff --git a/gcc/gimple.c b/gcc/gimple.c
index 59fcf4335a3..55dd09106bb 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -30,18 +30,13 @@ along with GCC; see the file COPYING3. If not see
#include "basic-block.h"
#include "gimple.h"
#include "diagnostic.h"
-#include "tree-ssa.h"
#include "value-prof.h"
#include "flags.h"
#include "alias.h"
#include "demangle.h"
#include "langhooks.h"
+#include "bitmap.h"
-/* Global canonical type table. */
-static GTY((if_marked ("ggc_marked_p"), param_is (union tree_node)))
- htab_t gimple_canonical_types;
-static GTY((if_marked ("tree_int_map_marked_p"), param_is (struct tree_int_map)))
- htab_t canonical_type_hash_cache;
/* All the tuples have their operand vector (if present) at the very bottom
of the structure. Therefore, the offset required to find the
@@ -54,7 +49,7 @@ EXPORTED_CONST size_t gimple_ops_offset_[] = {
};
#undef DEFGSSTRUCT
-#define DEFGSSTRUCT(SYM, STRUCT, HAS_TREE_OP) sizeof(struct STRUCT),
+#define DEFGSSTRUCT(SYM, STRUCT, HAS_TREE_OP) sizeof (struct STRUCT),
static const size_t gsstruct_code_size[] = {
#include "gsstruct.def"
};
@@ -157,7 +152,7 @@ gimple_set_subcode (gimple g, unsigned subcode)
/* Build a tuple with operands. CODE is the statement to build (which
- must be one of the GIMPLE_WITH_OPS tuples). SUBCODE is the sub-code
+ must be one of the GIMPLE_WITH_OPS tuples). SUBCODE is the subcode
for the new tuple. NUM_OPS is the number of operands to allocate. */
#define gimple_build_with_ops(c, s, n) \
@@ -179,7 +174,7 @@ gimple_build_with_ops_stat (enum gimple_code code, unsigned subcode,
gimple
gimple_build_return (tree retval)
{
- gimple s = gimple_build_with_ops (GIMPLE_RETURN, ERROR_MARK, 1);
+ gimple s = gimple_build_with_ops (GIMPLE_RETURN, ERROR_MARK, 2);
if (retval)
gimple_return_set_retval (s, retval);
return s;
@@ -371,44 +366,23 @@ gimple_build_call_from_tree (tree t)
}
-/* Extract the operands and code for expression EXPR into *SUBCODE_P,
- *OP1_P, *OP2_P and *OP3_P respectively. */
+/* Return index of INDEX's non bound argument of the call. */
-void
-extract_ops_from_tree_1 (tree expr, enum tree_code *subcode_p, tree *op1_p,
- tree *op2_p, tree *op3_p)
+unsigned
+gimple_call_get_nobnd_arg_index (const_gimple gs, unsigned index)
{
- enum gimple_rhs_class grhs_class;
-
- *subcode_p = TREE_CODE (expr);
- grhs_class = get_gimple_rhs_class (*subcode_p);
-
- if (grhs_class == GIMPLE_TERNARY_RHS)
- {
- *op1_p = TREE_OPERAND (expr, 0);
- *op2_p = TREE_OPERAND (expr, 1);
- *op3_p = TREE_OPERAND (expr, 2);
- }
- else if (grhs_class == GIMPLE_BINARY_RHS)
- {
- *op1_p = TREE_OPERAND (expr, 0);
- *op2_p = TREE_OPERAND (expr, 1);
- *op3_p = NULL_TREE;
- }
- else if (grhs_class == GIMPLE_UNARY_RHS)
- {
- *op1_p = TREE_OPERAND (expr, 0);
- *op2_p = NULL_TREE;
- *op3_p = NULL_TREE;
- }
- else if (grhs_class == GIMPLE_SINGLE_RHS)
+ unsigned num_args = gimple_call_num_args (gs);
+ for (unsigned n = 0; n < num_args; n++)
{
- *op1_p = expr;
- *op2_p = NULL_TREE;
- *op3_p = NULL_TREE;
+ if (POINTER_BOUNDS_P (gimple_call_arg (gs, n)))
+ continue;
+ else if (index)
+ index--;
+ else
+ return n;
}
- else
- gcc_unreachable ();
+
+ gcc_unreachable ();
}
@@ -429,7 +403,7 @@ gimple_build_assign_stat (tree lhs, tree rhs MEM_STAT_DECL)
}
-/* Build a GIMPLE_ASSIGN statement with sub-code SUBCODE and operands
+/* Build a GIMPLE_ASSIGN statement with subcode SUBCODE and operands
OP1 and OP2. If OP2 is NULL then SUBCODE must be of class
GIMPLE_UNARY_RHS or GIMPLE_SINGLE_RHS. */
@@ -511,37 +485,6 @@ gimple_build_cond (enum tree_code pred_code, tree lhs, tree rhs,
return p;
}
-
-/* Extract operands for a GIMPLE_COND statement out of COND_EXPR tree COND. */
-
-void
-gimple_cond_get_ops_from_tree (tree cond, enum tree_code *code_p,
- tree *lhs_p, tree *rhs_p)
-{
- gcc_assert (TREE_CODE_CLASS (TREE_CODE (cond)) == tcc_comparison
- || TREE_CODE (cond) == TRUTH_NOT_EXPR
- || is_gimple_min_invariant (cond)
- || SSA_VAR_P (cond));
-
- extract_ops_from_tree (cond, code_p, lhs_p, rhs_p);
-
- /* Canonicalize conditionals of the form 'if (!VAL)'. */
- if (*code_p == TRUTH_NOT_EXPR)
- {
- *code_p = EQ_EXPR;
- gcc_assert (*lhs_p && *rhs_p == NULL_TREE);
- *rhs_p = build_zero_cst (TREE_TYPE (*lhs_p));
- }
- /* Canonicalize conditionals of the form 'if (VAL)' */
- else if (TREE_CODE_CLASS (*code_p) != tcc_comparison)
- {
- *code_p = NE_EXPR;
- gcc_assert (*lhs_p && *rhs_p == NULL_TREE);
- *rhs_p = build_zero_cst (TREE_TYPE (*lhs_p));
- }
-}
-
-
/* Build a GIMPLE_COND statement from the conditional expression tree
COND. T_LABEL and F_LABEL are as in gimple_build_cond. */
@@ -1007,6 +950,22 @@ gimple_build_omp_master (gimple_seq body)
}
+/* Build a GIMPLE_OMP_TASKGROUP statement.
+
+ BODY is the sequence of statements to be executed by the taskgroup
+ construct. */
+
+gimple
+gimple_build_omp_taskgroup (gimple_seq body)
+{
+ gimple p = gimple_alloc (GIMPLE_OMP_TASKGROUP, 0);
+ if (body)
+ gimple_omp_set_body (p, body);
+
+ return p;
+}
+
+
/* Build a GIMPLE_OMP_CONTINUE statement.
CONTROL_DEF is the definition of the control variable.
@@ -1096,6 +1055,41 @@ gimple_build_omp_single (gimple_seq body, tree clauses)
}
+/* Build a GIMPLE_OMP_TARGET statement.
+
+ BODY is the sequence of statements that will be executed.
+ CLAUSES are any of the OMP target construct's clauses. */
+
+gimple
+gimple_build_omp_target (gimple_seq body, int kind, tree clauses)
+{
+ gimple p = gimple_alloc (GIMPLE_OMP_TARGET, 0);
+ if (body)
+ gimple_omp_set_body (p, body);
+ gimple_omp_target_set_clauses (p, clauses);
+ gimple_omp_target_set_kind (p, kind);
+
+ return p;
+}
+
+
+/* Build a GIMPLE_OMP_TEAMS statement.
+
+ BODY is the sequence of statements that will be executed.
+ CLAUSES are any of the OMP teams construct's clauses. */
+
+gimple
+gimple_build_omp_teams (gimple_seq body, tree clauses)
+{
+ gimple p = gimple_alloc (GIMPLE_OMP_TEAMS, 0);
+ if (body)
+ gimple_omp_set_body (p, body);
+ gimple_omp_teams_set_clauses (p, clauses);
+
+ return p;
+}
+
+
/* Build a GIMPLE_OMP_ATOMIC_LOAD statement. */
gimple
@@ -1154,10 +1148,10 @@ gimple_check_failed (const_gimple gs, const char *file, int line,
{
internal_error ("gimple check: expected %s(%s), have %s(%s) in %s, at %s:%d",
gimple_code_name[code],
- tree_code_name[subcode],
+ get_tree_code_name (subcode),
gimple_code_name[gimple_code (gs)],
gs->gsbase.subcode > 0
- ? tree_code_name[gs->gsbase.subcode]
+ ? get_tree_code_name ((enum tree_code) gs->gsbase.subcode)
: "",
function, trim_filename (file), line);
}
@@ -1612,6 +1606,20 @@ walk_gimple_op (gimple stmt, walk_tree_fn callback_op,
return ret;
break;
+ case GIMPLE_OMP_TARGET:
+ ret = walk_tree (gimple_omp_target_clauses_ptr (stmt), callback_op, wi,
+ pset);
+ if (ret)
+ return ret;
+ break;
+
+ case GIMPLE_OMP_TEAMS:
+ ret = walk_tree (gimple_omp_teams_clauses_ptr (stmt), callback_op, wi,
+ pset);
+ if (ret)
+ return ret;
+ break;
+
case GIMPLE_OMP_ATOMIC_LOAD:
ret = walk_tree (gimple_omp_atomic_load_lhs_ptr (stmt), callback_op, wi,
pset);
@@ -1638,10 +1646,16 @@ walk_gimple_op (gimple stmt, walk_tree_fn callback_op,
return ret;
break;
+ case GIMPLE_OMP_RETURN:
+ ret = walk_tree (gimple_omp_return_lhs_ptr (stmt), callback_op, wi,
+ pset);
+ if (ret)
+ return ret;
+ break;
+
/* Tuples that do not have operands. */
case GIMPLE_NOP:
case GIMPLE_RESX:
- case GIMPLE_OMP_RETURN:
case GIMPLE_PREDICT:
break;
@@ -1782,12 +1796,15 @@ walk_gimple_stmt (gimple_stmt_iterator *gsi, walk_stmt_fn callback_stmt,
/* FALL THROUGH. */
case GIMPLE_OMP_CRITICAL:
case GIMPLE_OMP_MASTER:
+ case GIMPLE_OMP_TASKGROUP:
case GIMPLE_OMP_ORDERED:
case GIMPLE_OMP_SECTION:
case GIMPLE_OMP_PARALLEL:
case GIMPLE_OMP_TASK:
case GIMPLE_OMP_SECTIONS:
case GIMPLE_OMP_SINGLE:
+ case GIMPLE_OMP_TARGET:
+ case GIMPLE_OMP_TEAMS:
ret = walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), callback_stmt,
callback_op, wi);
if (ret)
@@ -1817,45 +1834,6 @@ walk_gimple_stmt (gimple_stmt_iterator *gsi, walk_stmt_fn callback_stmt,
}
-/* Set sequence SEQ to be the GIMPLE body for function FN. */
-
-void
-gimple_set_body (tree fndecl, gimple_seq seq)
-{
- struct function *fn = DECL_STRUCT_FUNCTION (fndecl);
- if (fn == NULL)
- {
- /* If FNDECL still does not have a function structure associated
- with it, then it does not make sense for it to receive a
- GIMPLE body. */
- gcc_assert (seq == NULL);
- }
- else
- fn->gimple_body = seq;
-}
-
-
-/* Return the body of GIMPLE statements for function FN. After the
- CFG pass, the function body doesn't exist anymore because it has
- been split up into basic blocks. In this case, it returns
- NULL. */
-
-gimple_seq
-gimple_body (tree fndecl)
-{
- struct function *fn = DECL_STRUCT_FUNCTION (fndecl);
- return fn ? fn->gimple_body : NULL;
-}
-
-/* Return true when FNDECL has Gimple body either in unlowered
- or CFG form. */
-bool
-gimple_has_body_p (tree fndecl)
-{
- struct function *fn = DECL_STRUCT_FUNCTION (fndecl);
- return (gimple_body (fndecl) || (fn && fn->cfg));
-}
-
/* Return true if calls C1 and C2 are known to go to the same function. */
bool
@@ -2153,42 +2131,9 @@ gimple_set_lhs (gimple stmt, tree lhs)
else if (code == GIMPLE_CALL)
gimple_call_set_lhs (stmt, lhs);
else
- gcc_unreachable();
+ gcc_unreachable ();
}
-/* Replace the LHS of STMT, an assignment, either a GIMPLE_ASSIGN or a
- GIMPLE_CALL, with NLHS, in preparation for modifying the RHS to an
- expression with a different value.
-
- This will update any annotations (say debug bind stmts) referring
- to the original LHS, so that they use the RHS instead. This is
- done even if NLHS and LHS are the same, for it is understood that
- the RHS will be modified afterwards, and NLHS will not be assigned
- an equivalent value.
-
- Adjusting any non-annotation uses of the LHS, if needed, is a
- responsibility of the caller.
-
- The effect of this call should be pretty much the same as that of
- inserting a copy of STMT before STMT, and then removing the
- original stmt, at which time gsi_remove() would have update
- annotations, but using this function saves all the inserting,
- copying and removing. */
-
-void
-gimple_replace_lhs (gimple stmt, tree nlhs)
-{
- if (MAY_HAVE_DEBUG_STMTS)
- {
- tree lhs = gimple_get_lhs (stmt);
-
- gcc_assert (SSA_NAME_DEF_STMT (lhs) == stmt);
-
- insert_debug_temp_for_var_def (NULL, lhs);
- }
-
- gimple_set_lhs (stmt, nlhs);
-}
/* Return a deep copy of statement STMT. All the operands from STMT
are reallocated and copied using unshare_expr. The DEF, USE, VDEF
@@ -2310,8 +2255,11 @@ gimple_copy (gimple stmt)
/* FALLTHRU */
case GIMPLE_OMP_SINGLE:
+ case GIMPLE_OMP_TARGET:
+ case GIMPLE_OMP_TEAMS:
case GIMPLE_OMP_SECTION:
case GIMPLE_OMP_MASTER:
+ case GIMPLE_OMP_TASKGROUP:
case GIMPLE_OMP_ORDERED:
copy_omp_body:
new_seq = gimple_seq_copy (gimple_omp_body (stmt));
@@ -2543,306 +2491,6 @@ const unsigned char gimple_rhs_class_table[] = {
#undef DEFTREECODE
#undef END_OF_BASE_TREE_CODES
-/* For the definitive definition of GIMPLE, see doc/tree-ssa.texi. */
-
-/* Validation of GIMPLE expressions. */
-
-/* Return true if T is a valid LHS for a GIMPLE assignment expression. */
-
-bool
-is_gimple_lvalue (tree t)
-{
- return (is_gimple_addressable (t)
- || TREE_CODE (t) == WITH_SIZE_EXPR
- /* These are complex lvalues, but don't have addresses, so they
- go here. */
- || TREE_CODE (t) == BIT_FIELD_REF);
-}
-
-/* Return true if T is a GIMPLE condition. */
-
-bool
-is_gimple_condexpr (tree t)
-{
- return (is_gimple_val (t) || (COMPARISON_CLASS_P (t)
- && !tree_could_throw_p (t)
- && is_gimple_val (TREE_OPERAND (t, 0))
- && is_gimple_val (TREE_OPERAND (t, 1))));
-}
-
-/* Return true if T is something whose address can be taken. */
-
-bool
-is_gimple_addressable (tree t)
-{
- return (is_gimple_id (t) || handled_component_p (t)
- || TREE_CODE (t) == MEM_REF);
-}
-
-/* Return true if T is a valid gimple constant. */
-
-bool
-is_gimple_constant (const_tree t)
-{
- switch (TREE_CODE (t))
- {
- case INTEGER_CST:
- case REAL_CST:
- case FIXED_CST:
- case STRING_CST:
- case COMPLEX_CST:
- case VECTOR_CST:
- return true;
-
- default:
- return false;
- }
-}
-
-/* Return true if T is a gimple address. */
-
-bool
-is_gimple_address (const_tree t)
-{
- tree op;
-
- if (TREE_CODE (t) != ADDR_EXPR)
- return false;
-
- op = TREE_OPERAND (t, 0);
- while (handled_component_p (op))
- {
- if ((TREE_CODE (op) == ARRAY_REF
- || TREE_CODE (op) == ARRAY_RANGE_REF)
- && !is_gimple_val (TREE_OPERAND (op, 1)))
- return false;
-
- op = TREE_OPERAND (op, 0);
- }
-
- if (CONSTANT_CLASS_P (op) || TREE_CODE (op) == MEM_REF)
- return true;
-
- switch (TREE_CODE (op))
- {
- case PARM_DECL:
- case RESULT_DECL:
- case LABEL_DECL:
- case FUNCTION_DECL:
- case VAR_DECL:
- case CONST_DECL:
- return true;
-
- default:
- return false;
- }
-}
-
-/* Return true if T is a gimple invariant address. */
-
-bool
-is_gimple_invariant_address (const_tree t)
-{
- const_tree op;
-
- if (TREE_CODE (t) != ADDR_EXPR)
- return false;
-
- op = strip_invariant_refs (TREE_OPERAND (t, 0));
- if (!op)
- return false;
-
- if (TREE_CODE (op) == MEM_REF)
- {
- const_tree op0 = TREE_OPERAND (op, 0);
- return (TREE_CODE (op0) == ADDR_EXPR
- && (CONSTANT_CLASS_P (TREE_OPERAND (op0, 0))
- || decl_address_invariant_p (TREE_OPERAND (op0, 0))));
- }
-
- return CONSTANT_CLASS_P (op) || decl_address_invariant_p (op);
-}
-
-/* Return true if T is a gimple invariant address at IPA level
- (so addresses of variables on stack are not allowed). */
-
-bool
-is_gimple_ip_invariant_address (const_tree t)
-{
- const_tree op;
-
- if (TREE_CODE (t) != ADDR_EXPR)
- return false;
-
- op = strip_invariant_refs (TREE_OPERAND (t, 0));
- if (!op)
- return false;
-
- if (TREE_CODE (op) == MEM_REF)
- {
- const_tree op0 = TREE_OPERAND (op, 0);
- return (TREE_CODE (op0) == ADDR_EXPR
- && (CONSTANT_CLASS_P (TREE_OPERAND (op0, 0))
- || decl_address_ip_invariant_p (TREE_OPERAND (op0, 0))));
- }
-
- return CONSTANT_CLASS_P (op) || decl_address_ip_invariant_p (op);
-}
-
-/* Return true if T is a GIMPLE minimal invariant. It's a restricted
- form of function invariant. */
-
-bool
-is_gimple_min_invariant (const_tree t)
-{
- if (TREE_CODE (t) == ADDR_EXPR)
- return is_gimple_invariant_address (t);
-
- return is_gimple_constant (t);
-}
-
-/* Return true if T is a GIMPLE interprocedural invariant. It's a restricted
- form of gimple minimal invariant. */
-
-bool
-is_gimple_ip_invariant (const_tree t)
-{
- if (TREE_CODE (t) == ADDR_EXPR)
- return is_gimple_ip_invariant_address (t);
-
- return is_gimple_constant (t);
-}
-
-/* Return true if T is a variable. */
-
-bool
-is_gimple_variable (tree t)
-{
- return (TREE_CODE (t) == VAR_DECL
- || TREE_CODE (t) == PARM_DECL
- || TREE_CODE (t) == RESULT_DECL
- || TREE_CODE (t) == SSA_NAME);
-}
-
-/* Return true if T is a GIMPLE identifier (something with an address). */
-
-bool
-is_gimple_id (tree t)
-{
- return (is_gimple_variable (t)
- || TREE_CODE (t) == FUNCTION_DECL
- || TREE_CODE (t) == LABEL_DECL
- || TREE_CODE (t) == CONST_DECL
- /* Allow string constants, since they are addressable. */
- || TREE_CODE (t) == STRING_CST);
-}
-
-/* Return true if T is a non-aggregate register variable. */
-
-bool
-is_gimple_reg (tree t)
-{
- if (virtual_operand_p (t))
- return false;
-
- if (TREE_CODE (t) == SSA_NAME)
- return true;
-
- if (!is_gimple_variable (t))
- return false;
-
- if (!is_gimple_reg_type (TREE_TYPE (t)))
- return false;
-
- /* A volatile decl is not acceptable because we can't reuse it as
- needed. We need to copy it into a temp first. */
- if (TREE_THIS_VOLATILE (t))
- return false;
-
- /* We define "registers" as things that can be renamed as needed,
- which with our infrastructure does not apply to memory. */
- if (needs_to_live_in_memory (t))
- return false;
-
- /* Hard register variables are an interesting case. For those that
- are call-clobbered, we don't know where all the calls are, since
- we don't (want to) take into account which operations will turn
- into libcalls at the rtl level. For those that are call-saved,
- we don't currently model the fact that calls may in fact change
- global hard registers, nor do we examine ASM_CLOBBERS at the tree
- level, and so miss variable changes that might imply. All around,
- it seems safest to not do too much optimization with these at the
- tree level at all. We'll have to rely on the rtl optimizers to
- clean this up, as there we've got all the appropriate bits exposed. */
- if (TREE_CODE (t) == VAR_DECL && DECL_HARD_REGISTER (t))
- return false;
-
- /* Complex and vector values must have been put into SSA-like form.
- That is, no assignments to the individual components. */
- if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE
- || TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE)
- return DECL_GIMPLE_REG_P (t);
-
- return true;
-}
-
-
-/* Return true if T is a GIMPLE rvalue, i.e. an identifier or a constant. */
-
-bool
-is_gimple_val (tree t)
-{
- /* Make loads from volatiles and memory vars explicit. */
- if (is_gimple_variable (t)
- && is_gimple_reg_type (TREE_TYPE (t))
- && !is_gimple_reg (t))
- return false;
-
- return (is_gimple_variable (t) || is_gimple_min_invariant (t));
-}
-
-/* Similarly, but accept hard registers as inputs to asm statements. */
-
-bool
-is_gimple_asm_val (tree t)
-{
- if (TREE_CODE (t) == VAR_DECL && DECL_HARD_REGISTER (t))
- return true;
-
- return is_gimple_val (t);
-}
-
-/* Return true if T is a GIMPLE minimal lvalue. */
-
-bool
-is_gimple_min_lval (tree t)
-{
- if (!(t = CONST_CAST_TREE (strip_invariant_refs (t))))
- return false;
- return (is_gimple_id (t) || TREE_CODE (t) == MEM_REF);
-}
-
-/* Return true if T is a valid function operand of a CALL_EXPR. */
-
-bool
-is_gimple_call_addr (tree t)
-{
- return (TREE_CODE (t) == OBJ_TYPE_REF || is_gimple_val (t));
-}
-
-/* Return true if T is a valid address operand of a MEM_REF. */
-
-bool
-is_gimple_mem_ref_addr (tree t)
-{
- return (is_gimple_reg (t)
- || TREE_CODE (t) == INTEGER_CST
- || (TREE_CODE (t) == ADDR_EXPR
- && (CONSTANT_CLASS_P (TREE_OPERAND (t, 0))
- || decl_address_invariant_p (TREE_OPERAND (t, 0)))));
-}
-
-
/* Given a memory reference expression T, return its base address.
The base address of a memory reference expression is the main
object being referenced. For instance, the base address for
@@ -3055,455 +2703,6 @@ gimple_compare_field_offset (tree f1, tree f2)
return false;
}
-/* Returning a hash value for gimple type TYPE combined with VAL.
-
- The hash value returned is equal for types considered compatible
- by gimple_canonical_types_compatible_p. */
-
-static hashval_t
-iterative_hash_canonical_type (tree type, hashval_t val)
-{
- hashval_t v;
- void **slot;
- struct tree_int_map *mp, m;
-
- m.base.from = type;
- if ((slot = htab_find_slot (canonical_type_hash_cache, &m, INSERT))
- && *slot)
- return iterative_hash_hashval_t (((struct tree_int_map *) *slot)->to, val);
-
- /* Combine a few common features of types so that types are grouped into
- smaller sets; when searching for existing matching types to merge,
- only existing types having the same features as the new type will be
- checked. */
- v = iterative_hash_hashval_t (TREE_CODE (type), 0);
- v = iterative_hash_hashval_t (TREE_ADDRESSABLE (type), v);
- v = iterative_hash_hashval_t (TYPE_ALIGN (type), v);
- v = iterative_hash_hashval_t (TYPE_MODE (type), v);
-
- /* Incorporate common features of numerical types. */
- if (INTEGRAL_TYPE_P (type)
- || SCALAR_FLOAT_TYPE_P (type)
- || FIXED_POINT_TYPE_P (type)
- || TREE_CODE (type) == OFFSET_TYPE
- || POINTER_TYPE_P (type))
- {
- v = iterative_hash_hashval_t (TYPE_PRECISION (type), v);
- v = iterative_hash_hashval_t (TYPE_UNSIGNED (type), v);
- }
-
- if (VECTOR_TYPE_P (type))
- {
- v = iterative_hash_hashval_t (TYPE_VECTOR_SUBPARTS (type), v);
- v = iterative_hash_hashval_t (TYPE_UNSIGNED (type), v);
- }
-
- if (TREE_CODE (type) == COMPLEX_TYPE)
- v = iterative_hash_hashval_t (TYPE_UNSIGNED (type), v);
-
- /* For pointer and reference types, fold in information about the type
- pointed to but do not recurse to the pointed-to type. */
- if (POINTER_TYPE_P (type))
- {
- v = iterative_hash_hashval_t (TYPE_REF_CAN_ALIAS_ALL (type), v);
- v = iterative_hash_hashval_t (TYPE_ADDR_SPACE (TREE_TYPE (type)), v);
- v = iterative_hash_hashval_t (TYPE_RESTRICT (type), v);
- v = iterative_hash_hashval_t (TREE_CODE (TREE_TYPE (type)), v);
- }
-
- /* For integer types hash only the string flag. */
- if (TREE_CODE (type) == INTEGER_TYPE)
- v = iterative_hash_hashval_t (TYPE_STRING_FLAG (type), v);
-
- /* For array types hash the domain bounds and the string flag. */
- if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type))
- {
- v = iterative_hash_hashval_t (TYPE_STRING_FLAG (type), v);
- /* OMP lowering can introduce error_mark_node in place of
- random local decls in types. */
- if (TYPE_MIN_VALUE (TYPE_DOMAIN (type)) != error_mark_node)
- v = iterative_hash_expr (TYPE_MIN_VALUE (TYPE_DOMAIN (type)), v);
- if (TYPE_MAX_VALUE (TYPE_DOMAIN (type)) != error_mark_node)
- v = iterative_hash_expr (TYPE_MAX_VALUE (TYPE_DOMAIN (type)), v);
- }
-
- /* Recurse for aggregates with a single element type. */
- if (TREE_CODE (type) == ARRAY_TYPE
- || TREE_CODE (type) == COMPLEX_TYPE
- || TREE_CODE (type) == VECTOR_TYPE)
- v = iterative_hash_canonical_type (TREE_TYPE (type), v);
-
- /* Incorporate function return and argument types. */
- if (TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == METHOD_TYPE)
- {
- unsigned na;
- tree p;
-
- /* For method types also incorporate their parent class. */
- if (TREE_CODE (type) == METHOD_TYPE)
- v = iterative_hash_canonical_type (TYPE_METHOD_BASETYPE (type), v);
-
- v = iterative_hash_canonical_type (TREE_TYPE (type), v);
-
- for (p = TYPE_ARG_TYPES (type), na = 0; p; p = TREE_CHAIN (p))
- {
- v = iterative_hash_canonical_type (TREE_VALUE (p), v);
- na++;
- }
-
- v = iterative_hash_hashval_t (na, v);
- }
-
- if (RECORD_OR_UNION_TYPE_P (type))
- {
- unsigned nf;
- tree f;
-
- for (f = TYPE_FIELDS (type), nf = 0; f; f = TREE_CHAIN (f))
- if (TREE_CODE (f) == FIELD_DECL)
- {
- v = iterative_hash_canonical_type (TREE_TYPE (f), v);
- nf++;
- }
-
- v = iterative_hash_hashval_t (nf, v);
- }
-
- /* Cache the just computed hash value. */
- mp = ggc_alloc_cleared_tree_int_map ();
- mp->base.from = type;
- mp->to = v;
- *slot = (void *) mp;
-
- return iterative_hash_hashval_t (v, val);
-}
-
-static hashval_t
-gimple_canonical_type_hash (const void *p)
-{
- if (canonical_type_hash_cache == NULL)
- canonical_type_hash_cache = htab_create_ggc (512, tree_int_map_hash,
- tree_int_map_eq, NULL);
-
- return iterative_hash_canonical_type (CONST_CAST_TREE ((const_tree) p), 0);
-}
-
-
-
-
-/* The TYPE_CANONICAL merging machinery. It should closely resemble
- the middle-end types_compatible_p function. It needs to avoid
- claiming types are different for types that should be treated
- the same with respect to TBAA. Canonical types are also used
- for IL consistency checks via the useless_type_conversion_p
- predicate which does not handle all type kinds itself but falls
- back to pointer-comparison of TYPE_CANONICAL for aggregates
- for example. */
-
-/* Return true iff T1 and T2 are structurally identical for what
- TBAA is concerned. */
-
-static bool
-gimple_canonical_types_compatible_p (tree t1, tree t2)
-{
- /* Before starting to set up the SCC machinery handle simple cases. */
-
- /* Check first for the obvious case of pointer identity. */
- if (t1 == t2)
- return true;
-
- /* Check that we have two types to compare. */
- if (t1 == NULL_TREE || t2 == NULL_TREE)
- return false;
-
- /* If the types have been previously registered and found equal
- they still are. */
- if (TYPE_CANONICAL (t1)
- && TYPE_CANONICAL (t1) == TYPE_CANONICAL (t2))
- return true;
-
- /* Can't be the same type if the types don't have the same code. */
- if (TREE_CODE (t1) != TREE_CODE (t2))
- return false;
-
- if (TREE_ADDRESSABLE (t1) != TREE_ADDRESSABLE (t2))
- return false;
-
- /* Qualifiers do not matter for canonical type comparison purposes. */
-
- /* Void types and nullptr types are always the same. */
- if (TREE_CODE (t1) == VOID_TYPE
- || TREE_CODE (t1) == NULLPTR_TYPE)
- return true;
-
- /* Can't be the same type if they have different alignment, or mode. */
- if (TYPE_ALIGN (t1) != TYPE_ALIGN (t2)
- || TYPE_MODE (t1) != TYPE_MODE (t2))
- return false;
-
- /* Non-aggregate types can be handled cheaply. */
- if (INTEGRAL_TYPE_P (t1)
- || SCALAR_FLOAT_TYPE_P (t1)
- || FIXED_POINT_TYPE_P (t1)
- || TREE_CODE (t1) == VECTOR_TYPE
- || TREE_CODE (t1) == COMPLEX_TYPE
- || TREE_CODE (t1) == OFFSET_TYPE
- || POINTER_TYPE_P (t1))
- {
- /* Can't be the same type if they have different sign or precision. */
- if (TYPE_PRECISION (t1) != TYPE_PRECISION (t2)
- || TYPE_UNSIGNED (t1) != TYPE_UNSIGNED (t2))
- return false;
-
- if (TREE_CODE (t1) == INTEGER_TYPE
- && TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2))
- return false;
-
- /* For canonical type comparisons we do not want to build SCCs
- so we cannot compare pointed-to types. But we can, for now,
- require the same pointed-to type kind and match what
- useless_type_conversion_p would do. */
- if (POINTER_TYPE_P (t1))
- {
- /* If the two pointers have different ref-all attributes,
- they can't be the same type. */
- if (TYPE_REF_CAN_ALIAS_ALL (t1) != TYPE_REF_CAN_ALIAS_ALL (t2))
- return false;
-
- if (TYPE_ADDR_SPACE (TREE_TYPE (t1))
- != TYPE_ADDR_SPACE (TREE_TYPE (t2)))
- return false;
-
- if (TYPE_RESTRICT (t1) != TYPE_RESTRICT (t2))
- return false;
-
- if (TREE_CODE (TREE_TYPE (t1)) != TREE_CODE (TREE_TYPE (t2)))
- return false;
- }
-
- /* Tail-recurse to components. */
- if (TREE_CODE (t1) == VECTOR_TYPE
- || TREE_CODE (t1) == COMPLEX_TYPE)
- return gimple_canonical_types_compatible_p (TREE_TYPE (t1),
- TREE_TYPE (t2));
-
- return true;
- }
-
- /* Do type-specific comparisons. */
- switch (TREE_CODE (t1))
- {
- case ARRAY_TYPE:
- /* Array types are the same if the element types are the same and
- the number of elements are the same. */
- if (!gimple_canonical_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2))
- || TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2)
- || TYPE_NONALIASED_COMPONENT (t1) != TYPE_NONALIASED_COMPONENT (t2))
- return false;
- else
- {
- tree i1 = TYPE_DOMAIN (t1);
- tree i2 = TYPE_DOMAIN (t2);
-
- /* For an incomplete external array, the type domain can be
- NULL_TREE. Check this condition also. */
- if (i1 == NULL_TREE && i2 == NULL_TREE)
- return true;
- else if (i1 == NULL_TREE || i2 == NULL_TREE)
- return false;
- else
- {
- tree min1 = TYPE_MIN_VALUE (i1);
- tree min2 = TYPE_MIN_VALUE (i2);
- tree max1 = TYPE_MAX_VALUE (i1);
- tree max2 = TYPE_MAX_VALUE (i2);
-
- /* The minimum/maximum values have to be the same. */
- if ((min1 == min2
- || (min1 && min2
- && ((TREE_CODE (min1) == PLACEHOLDER_EXPR
- && TREE_CODE (min2) == PLACEHOLDER_EXPR)
- || operand_equal_p (min1, min2, 0))))
- && (max1 == max2
- || (max1 && max2
- && ((TREE_CODE (max1) == PLACEHOLDER_EXPR
- && TREE_CODE (max2) == PLACEHOLDER_EXPR)
- || operand_equal_p (max1, max2, 0)))))
- return true;
- else
- return false;
- }
- }
-
- case METHOD_TYPE:
- case FUNCTION_TYPE:
- /* Function types are the same if the return type and arguments types
- are the same. */
- if (!gimple_canonical_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2)))
- return false;
-
- if (!comp_type_attributes (t1, t2))
- return false;
-
- if (TYPE_ARG_TYPES (t1) == TYPE_ARG_TYPES (t2))
- return true;
- else
- {
- tree parms1, parms2;
-
- for (parms1 = TYPE_ARG_TYPES (t1), parms2 = TYPE_ARG_TYPES (t2);
- parms1 && parms2;
- parms1 = TREE_CHAIN (parms1), parms2 = TREE_CHAIN (parms2))
- {
- if (!gimple_canonical_types_compatible_p
- (TREE_VALUE (parms1), TREE_VALUE (parms2)))
- return false;
- }
-
- if (parms1 || parms2)
- return false;
-
- return true;
- }
-
- case RECORD_TYPE:
- case UNION_TYPE:
- case QUAL_UNION_TYPE:
- {
- tree f1, f2;
-
- /* For aggregate types, all the fields must be the same. */
- for (f1 = TYPE_FIELDS (t1), f2 = TYPE_FIELDS (t2);
- f1 || f2;
- f1 = TREE_CHAIN (f1), f2 = TREE_CHAIN (f2))
- {
- /* Skip non-fields. */
- while (f1 && TREE_CODE (f1) != FIELD_DECL)
- f1 = TREE_CHAIN (f1);
- while (f2 && TREE_CODE (f2) != FIELD_DECL)
- f2 = TREE_CHAIN (f2);
- if (!f1 || !f2)
- break;
- /* The fields must have the same name, offset and type. */
- if (DECL_NONADDRESSABLE_P (f1) != DECL_NONADDRESSABLE_P (f2)
- || !gimple_compare_field_offset (f1, f2)
- || !gimple_canonical_types_compatible_p
- (TREE_TYPE (f1), TREE_TYPE (f2)))
- return false;
- }
-
- /* If one aggregate has more fields than the other, they
- are not the same. */
- if (f1 || f2)
- return false;
-
- return true;
- }
-
- default:
- gcc_unreachable ();
- }
-}
-
-
-/* Returns nonzero if P1 and P2 are equal. */
-
-static int
-gimple_canonical_type_eq (const void *p1, const void *p2)
-{
- const_tree t1 = (const_tree) p1;
- const_tree t2 = (const_tree) p2;
- return gimple_canonical_types_compatible_p (CONST_CAST_TREE (t1),
- CONST_CAST_TREE (t2));
-}
-
-/* Register type T in the global type table gimple_types.
- If another type T', compatible with T, already existed in
- gimple_types then return T', otherwise return T. This is used by
- LTO to merge identical types read from different TUs.
-
- ??? This merging does not exactly match how the tree.c middle-end
- functions will assign TYPE_CANONICAL when new types are created
- during optimization (which at least happens for pointer and array
- types). */
-
-tree
-gimple_register_canonical_type (tree t)
-{
- void **slot;
-
- gcc_assert (TYPE_P (t));
-
- if (TYPE_CANONICAL (t))
- return TYPE_CANONICAL (t);
-
- if (gimple_canonical_types == NULL)
- gimple_canonical_types = htab_create_ggc (16381, gimple_canonical_type_hash,
- gimple_canonical_type_eq, 0);
-
- slot = htab_find_slot (gimple_canonical_types, t, INSERT);
- if (*slot
- && *(tree *)slot != t)
- {
- tree new_type = (tree) *((tree *) slot);
-
- TYPE_CANONICAL (t) = new_type;
- t = new_type;
- }
- else
- {
- TYPE_CANONICAL (t) = t;
- *slot = (void *) t;
- }
-
- return t;
-}
-
-
-/* Show statistics on references to the global type table gimple_types. */
-
-void
-print_gimple_types_stats (const char *pfx)
-{
- if (gimple_canonical_types)
- fprintf (stderr, "[%s] GIMPLE canonical type table: size %ld, "
- "%ld elements, %ld searches, %ld collisions (ratio: %f)\n", pfx,
- (long) htab_size (gimple_canonical_types),
- (long) htab_elements (gimple_canonical_types),
- (long) gimple_canonical_types->searches,
- (long) gimple_canonical_types->collisions,
- htab_collisions (gimple_canonical_types));
- else
- fprintf (stderr, "[%s] GIMPLE canonical type table is empty\n", pfx);
- if (canonical_type_hash_cache)
- fprintf (stderr, "[%s] GIMPLE canonical type hash table: size %ld, "
- "%ld elements, %ld searches, %ld collisions (ratio: %f)\n", pfx,
- (long) htab_size (canonical_type_hash_cache),
- (long) htab_elements (canonical_type_hash_cache),
- (long) canonical_type_hash_cache->searches,
- (long) canonical_type_hash_cache->collisions,
- htab_collisions (canonical_type_hash_cache));
- else
- fprintf (stderr, "[%s] GIMPLE canonical type hash table is empty\n", pfx);
-}
-
-/* Free the gimple type hashtables used for LTO type merging. */
-
-void
-free_gimple_type_tables (void)
-{
- if (gimple_canonical_types)
- {
- htab_delete (gimple_canonical_types);
- gimple_canonical_types = NULL;
- }
- if (canonical_type_hash_cache)
- {
- htab_delete (canonical_type_hash_cache);
- canonical_type_hash_cache = NULL;
- }
-}
-
/* Return a type the same as TYPE except unsigned or
signed according to UNSIGNEDP. */
@@ -3739,96 +2938,6 @@ gimple_get_alias_set (tree t)
}
-/* Data structure used to count the number of dereferences to PTR
- inside an expression. */
-struct count_ptr_d
-{
- tree ptr;
- unsigned num_stores;
- unsigned num_loads;
-};
-
-/* Helper for count_uses_and_derefs. Called by walk_tree to look for
- (ALIGN/MISALIGNED_)INDIRECT_REF nodes for the pointer passed in DATA. */
-
-static tree
-count_ptr_derefs (tree *tp, int *walk_subtrees, void *data)
-{
- struct walk_stmt_info *wi_p = (struct walk_stmt_info *) data;
- struct count_ptr_d *count_p = (struct count_ptr_d *) wi_p->info;
-
- /* Do not walk inside ADDR_EXPR nodes. In the expression &ptr->fld,
- pointer 'ptr' is *not* dereferenced, it is simply used to compute
- the address of 'fld' as 'ptr + offsetof(fld)'. */
- if (TREE_CODE (*tp) == ADDR_EXPR)
- {
- *walk_subtrees = 0;
- return NULL_TREE;
- }
-
- if (TREE_CODE (*tp) == MEM_REF && TREE_OPERAND (*tp, 0) == count_p->ptr)
- {
- if (wi_p->is_lhs)
- count_p->num_stores++;
- else
- count_p->num_loads++;
- }
-
- return NULL_TREE;
-}
-
-/* Count the number of direct and indirect uses for pointer PTR in
- statement STMT. The number of direct uses is stored in
- *NUM_USES_P. Indirect references are counted separately depending
- on whether they are store or load operations. The counts are
- stored in *NUM_STORES_P and *NUM_LOADS_P. */
-
-void
-count_uses_and_derefs (tree ptr, gimple stmt, unsigned *num_uses_p,
- unsigned *num_loads_p, unsigned *num_stores_p)
-{
- ssa_op_iter i;
- tree use;
-
- *num_uses_p = 0;
- *num_loads_p = 0;
- *num_stores_p = 0;
-
- /* Find out the total number of uses of PTR in STMT. */
- FOR_EACH_SSA_TREE_OPERAND (use, stmt, i, SSA_OP_USE)
- if (use == ptr)
- (*num_uses_p)++;
-
- /* Now count the number of indirect references to PTR. This is
- truly awful, but we don't have much choice. There are no parent
- pointers inside INDIRECT_REFs, so an expression like
- '*x_1 = foo (x_1, *x_1)' needs to be traversed piece by piece to
- find all the indirect and direct uses of x_1 inside. The only
- shortcut we can take is the fact that GIMPLE only allows
- INDIRECT_REFs inside the expressions below. */
- if (is_gimple_assign (stmt)
- || gimple_code (stmt) == GIMPLE_RETURN
- || gimple_code (stmt) == GIMPLE_ASM
- || is_gimple_call (stmt))
- {
- struct walk_stmt_info wi;
- struct count_ptr_d count;
-
- count.ptr = ptr;
- count.num_stores = 0;
- count.num_loads = 0;
-
- memset (&wi, 0, sizeof (wi));
- wi.info = &count;
- walk_gimple_op (stmt, count_ptr_derefs, &wi);
-
- *num_stores_p = count.num_stores;
- *num_loads_p = count.num_loads;
- }
-
- gcc_assert (*num_uses_p >= *num_loads_p + *num_stores_p);
-}
-
/* From a tree operand OP return the base of a load or store operation
or NULL_TREE if OP is not a load or a store. */
@@ -4046,7 +3155,7 @@ walk_stmt_load_store_addr_ops (gimple stmt, void *data,
{
for (i = 0; i < gimple_phi_num_args (stmt); ++i)
{
- tree op = PHI_ARG_DEF (stmt, i);
+ tree op = gimple_phi_arg_def (stmt, i);
if (TREE_CODE (op) == ADDR_EXPR)
ret |= visit_addr (stmt, TREE_OPERAND (op, 0), data);
}
@@ -4103,37 +3212,6 @@ gimple_ior_addresses_taken (bitmap addresses_taken, gimple stmt)
}
-/* Return a printable name for symbol DECL. */
-
-const char *
-gimple_decl_printable_name (tree decl, int verbosity)
-{
- if (!DECL_NAME (decl))
- return NULL;
-
- if (DECL_ASSEMBLER_NAME_SET_P (decl))
- {
- const char *str, *mangled_str;
- int dmgl_opts = DMGL_NO_OPTS;
-
- if (verbosity >= 2)
- {
- dmgl_opts = DMGL_VERBOSE
- | DMGL_ANSI
- | DMGL_GNU_V3
- | DMGL_RET_POSTFIX;
- if (TREE_CODE (decl) == FUNCTION_DECL)
- dmgl_opts |= DMGL_PARAMS;
- }
-
- mangled_str = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
- str = cplus_demangle_v3 (mangled_str, dmgl_opts);
- return (str) ? str : mangled_str;
- }
-
- return IDENTIFIER_POINTER (DECL_NAME (decl));
-}
-
/* Return TRUE iff stmt is a call to a built-in function. */
bool
@@ -4224,360 +3302,129 @@ gimple_asm_clobbers_memory_p (const_gimple stmt)
return false;
}
+/* Dump bitmap SET (assumed to contain VAR_DECLs) to FILE. */
-/* Create and return an unnamed temporary. MODE indicates whether
- this should be an SSA or NORMAL temporary. TYPE is the type to use
- for the new temporary. */
-
-tree
-create_gimple_tmp (tree type, enum ssa_mode mode)
-{
- return (mode == M_SSA)
- ? make_ssa_name (type, NULL)
- : create_tmp_var (type, NULL);
-}
-
-
-/* Return the expression type to use based on the CODE and type of
- the given operand OP. If the expression CODE is a comparison,
- the returned type is boolean_type_node. Otherwise, it returns
- the type of OP. */
-
-static tree
-get_expr_type (enum tree_code code, tree op)
-{
- return (TREE_CODE_CLASS (code) == tcc_comparison)
- ? boolean_type_node
- : TREE_TYPE (op);
-}
-
-
-/* Build a new gimple assignment. The LHS of the assignment is a new
- temporary whose type matches the given expression. MODE indicates
- whether the LHS should be an SSA or a normal temporary. CODE is
- the expression code for the RHS. OP1 is the first operand and VAL
- is an integer value to be used as the second operand. */
-
-gimple
-build_assign (enum tree_code code, tree op1, int val, enum ssa_mode mode)
-{
- tree op2 = build_int_cst (TREE_TYPE (op1), val);
- tree lhs = create_gimple_tmp (get_expr_type (code, op1), mode);
- return gimple_build_assign_with_ops (code, lhs, op1, op2);
-}
-
-gimple
-build_assign (enum tree_code code, gimple g, int val, enum ssa_mode mode)
+void
+dump_decl_set (FILE *file, bitmap set)
{
- return build_assign (code, gimple_assign_lhs (g), val, mode);
-}
-
-
-/* Build and return a new GIMPLE assignment. The new assignment will
- have the opcode CODE and operands OP1 and OP2. The type of the
- expression on the RHS is inferred to be the type of OP1.
+ if (set)
+ {
+ bitmap_iterator bi;
+ unsigned i;
- The LHS of the statement will be an SSA name or a GIMPLE temporary
- in normal form depending on the type of builder invoking this
- function. */
+ fprintf (file, "{ ");
-gimple
-build_assign (enum tree_code code, tree op1, tree op2, enum ssa_mode mode)
-{
- tree lhs = create_gimple_tmp (get_expr_type (code, op1), mode);
- return gimple_build_assign_with_ops (code, lhs, op1, op2);
-}
+ EXECUTE_IF_SET_IN_BITMAP (set, 0, i, bi)
+ {
+ fprintf (file, "D.%u", i);
+ fprintf (file, " ");
+ }
-gimple
-build_assign (enum tree_code code, gimple op1, tree op2, enum ssa_mode mode)
-{
- return build_assign (code, gimple_assign_lhs (op1), op2, mode);
+ fprintf (file, "}");
+ }
+ else
+ fprintf (file, "NIL");
}
-gimple
-build_assign (enum tree_code code, tree op1, gimple op2, enum ssa_mode mode)
+/* Return true when CALL is a call stmt that definitely doesn't
+ free any memory or makes it unavailable otherwise. */
+bool
+nonfreeing_call_p (gimple call)
{
- return build_assign (code, op1, gimple_assign_lhs (op2), mode);
-}
+ if (gimple_call_builtin_p (call, BUILT_IN_NORMAL)
+ && gimple_call_flags (call) & ECF_LEAF)
+ switch (DECL_FUNCTION_CODE (gimple_call_fndecl (call)))
+ {
+ /* Just in case these become ECF_LEAF in the future. */
+ case BUILT_IN_FREE:
+ case BUILT_IN_TM_FREE:
+ case BUILT_IN_REALLOC:
+ case BUILT_IN_STACK_RESTORE:
+ return false;
+ default:
+ return true;
+ }
-gimple
-build_assign (enum tree_code code, gimple op1, gimple op2, enum ssa_mode mode)
-{
- return build_assign (code, gimple_assign_lhs (op1), gimple_assign_lhs (op2),
- mode);
+ return false;
}
+/* Callback for walk_stmt_load_store_ops.
+
+ Return TRUE if OP will dereference the tree stored in DATA, FALSE
+ otherwise.
-/* Create and return a type cast assignment. This creates a NOP_EXPR
- that converts OP to TO_TYPE. */
-
-gimple
-build_type_cast (tree to_type, tree op, enum ssa_mode mode)
-{
- tree lhs = create_gimple_tmp (to_type, mode);
- return gimple_build_assign_with_ops (NOP_EXPR, lhs, op, NULL_TREE);
-}
-
-gimple
-build_type_cast (tree to_type, gimple op, enum ssa_mode mode)
+ This routine only makes a superficial check for a dereference. Thus
+ it must only be used if it is safe to return a false negative. */
+static bool
+check_loadstore (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data)
{
- return build_type_cast (to_type, gimple_assign_lhs (op), mode);
+ if ((TREE_CODE (op) == MEM_REF || TREE_CODE (op) == TARGET_MEM_REF)
+ && operand_equal_p (TREE_OPERAND (op, 0), (tree)data, 0))
+ return true;
+ return false;
}
-
-/* Return true if the conversion from INNER_TYPE to OUTER_TYPE is a
- useless type conversion, otherwise return false.
-
- This function implicitly defines the middle-end type system. With
- the notion of 'a < b' meaning that useless_type_conversion_p (a, b)
- holds and 'a > b' meaning that useless_type_conversion_p (b, a) holds,
- the following invariants shall be fulfilled:
-
- 1) useless_type_conversion_p is transitive.
- If a < b and b < c then a < c.
-
- 2) useless_type_conversion_p is not symmetric.
- From a < b does not follow a > b.
-
- 3) Types define the available set of operations applicable to values.
- A type conversion is useless if the operations for the target type
- is a subset of the operations for the source type. For example
- casts to void* are useless, casts from void* are not (void* can't
- be dereferenced or offsetted, but copied, hence its set of operations
- is a strict subset of that of all other data pointer types). Casts
- to const T* are useless (can't be written to), casts from const T*
- to T* are not. */
+/* If OP can be inferred to be non-zero after STMT executes, return true. */
bool
-useless_type_conversion_p (tree outer_type, tree inner_type)
+infer_nonnull_range (gimple stmt, tree op)
{
- /* Do the following before stripping toplevel qualifiers. */
- if (POINTER_TYPE_P (inner_type)
- && POINTER_TYPE_P (outer_type))
- {
- /* Do not lose casts between pointers to different address spaces. */
- if (TYPE_ADDR_SPACE (TREE_TYPE (outer_type))
- != TYPE_ADDR_SPACE (TREE_TYPE (inner_type)))
- return false;
- }
-
- /* From now on qualifiers on value types do not matter. */
- inner_type = TYPE_MAIN_VARIANT (inner_type);
- outer_type = TYPE_MAIN_VARIANT (outer_type);
-
- if (inner_type == outer_type)
- return true;
-
- /* If we know the canonical types, compare them. */
- if (TYPE_CANONICAL (inner_type)
- && TYPE_CANONICAL (inner_type) == TYPE_CANONICAL (outer_type))
- return true;
-
- /* Changes in machine mode are never useless conversions unless we
- deal with aggregate types in which case we defer to later checks. */
- if (TYPE_MODE (inner_type) != TYPE_MODE (outer_type)
- && !AGGREGATE_TYPE_P (inner_type))
+ /* We can only assume that a pointer dereference will yield
+ non-NULL if -fdelete-null-pointer-checks is enabled. */
+ if (!flag_delete_null_pointer_checks
+ || !POINTER_TYPE_P (TREE_TYPE (op))
+ || gimple_code (stmt) == GIMPLE_ASM)
return false;
- /* If both the inner and outer types are integral types, then the
- conversion is not necessary if they have the same mode and
- signedness and precision, and both or neither are boolean. */
- if (INTEGRAL_TYPE_P (inner_type)
- && INTEGRAL_TYPE_P (outer_type))
- {
- /* Preserve changes in signedness or precision. */
- if (TYPE_UNSIGNED (inner_type) != TYPE_UNSIGNED (outer_type)
- || TYPE_PRECISION (inner_type) != TYPE_PRECISION (outer_type))
- return false;
-
- /* Preserve conversions to/from BOOLEAN_TYPE if types are not
- of precision one. */
- if (((TREE_CODE (inner_type) == BOOLEAN_TYPE)
- != (TREE_CODE (outer_type) == BOOLEAN_TYPE))
- && TYPE_PRECISION (outer_type) != 1)
- return false;
-
- /* We don't need to preserve changes in the types minimum or
- maximum value in general as these do not generate code
- unless the types precisions are different. */
- return true;
- }
-
- /* Scalar floating point types with the same mode are compatible. */
- else if (SCALAR_FLOAT_TYPE_P (inner_type)
- && SCALAR_FLOAT_TYPE_P (outer_type))
- return true;
-
- /* Fixed point types with the same mode are compatible. */
- else if (FIXED_POINT_TYPE_P (inner_type)
- && FIXED_POINT_TYPE_P (outer_type))
+ if (walk_stmt_load_store_ops (stmt, (void *)op,
+ check_loadstore, check_loadstore))
return true;
- /* We need to take special care recursing to pointed-to types. */
- else if (POINTER_TYPE_P (inner_type)
- && POINTER_TYPE_P (outer_type))
- {
- /* Do not lose casts to function pointer types. */
- if ((TREE_CODE (TREE_TYPE (outer_type)) == FUNCTION_TYPE
- || TREE_CODE (TREE_TYPE (outer_type)) == METHOD_TYPE)
- && !(TREE_CODE (TREE_TYPE (inner_type)) == FUNCTION_TYPE
- || TREE_CODE (TREE_TYPE (inner_type)) == METHOD_TYPE))
- return false;
-
- /* We do not care for const qualification of the pointed-to types
- as const qualification has no semantic value to the middle-end. */
-
- /* Otherwise pointers/references are equivalent. */
- return true;
- }
-
- /* Recurse for complex types. */
- else if (TREE_CODE (inner_type) == COMPLEX_TYPE
- && TREE_CODE (outer_type) == COMPLEX_TYPE)
- return useless_type_conversion_p (TREE_TYPE (outer_type),
- TREE_TYPE (inner_type));
-
- /* Recurse for vector types with the same number of subparts. */
- else if (TREE_CODE (inner_type) == VECTOR_TYPE
- && TREE_CODE (outer_type) == VECTOR_TYPE
- && TYPE_PRECISION (inner_type) == TYPE_PRECISION (outer_type))
- return useless_type_conversion_p (TREE_TYPE (outer_type),
- TREE_TYPE (inner_type));
-
- else if (TREE_CODE (inner_type) == ARRAY_TYPE
- && TREE_CODE (outer_type) == ARRAY_TYPE)
+ if (is_gimple_call (stmt) && !gimple_call_internal_p (stmt))
{
- /* Preserve string attributes. */
- if (TYPE_STRING_FLAG (inner_type) != TYPE_STRING_FLAG (outer_type))
- return false;
-
- /* Conversions from array types with unknown extent to
- array types with known extent are not useless. */
- if (!TYPE_DOMAIN (inner_type)
- && TYPE_DOMAIN (outer_type))
- return false;
-
- /* Nor are conversions from array types with non-constant size to
- array types with constant size or to different size. */
- if (TYPE_SIZE (outer_type)
- && TREE_CODE (TYPE_SIZE (outer_type)) == INTEGER_CST
- && (!TYPE_SIZE (inner_type)
- || TREE_CODE (TYPE_SIZE (inner_type)) != INTEGER_CST
- || !tree_int_cst_equal (TYPE_SIZE (outer_type),
- TYPE_SIZE (inner_type))))
- return false;
-
- /* Check conversions between arrays with partially known extents.
- If the array min/max values are constant they have to match.
- Otherwise allow conversions to unknown and variable extents.
- In particular this declares conversions that may change the
- mode to BLKmode as useless. */
- if (TYPE_DOMAIN (inner_type)
- && TYPE_DOMAIN (outer_type)
- && TYPE_DOMAIN (inner_type) != TYPE_DOMAIN (outer_type))
+ tree fntype = gimple_call_fntype (stmt);
+ tree attrs = TYPE_ATTRIBUTES (fntype);
+ for (; attrs; attrs = TREE_CHAIN (attrs))
{
- tree inner_min = TYPE_MIN_VALUE (TYPE_DOMAIN (inner_type));
- tree outer_min = TYPE_MIN_VALUE (TYPE_DOMAIN (outer_type));
- tree inner_max = TYPE_MAX_VALUE (TYPE_DOMAIN (inner_type));
- tree outer_max = TYPE_MAX_VALUE (TYPE_DOMAIN (outer_type));
-
- /* After gimplification a variable min/max value carries no
- additional information compared to a NULL value. All that
- matters has been lowered to be part of the IL. */
- if (inner_min && TREE_CODE (inner_min) != INTEGER_CST)
- inner_min = NULL_TREE;
- if (outer_min && TREE_CODE (outer_min) != INTEGER_CST)
- outer_min = NULL_TREE;
- if (inner_max && TREE_CODE (inner_max) != INTEGER_CST)
- inner_max = NULL_TREE;
- if (outer_max && TREE_CODE (outer_max) != INTEGER_CST)
- outer_max = NULL_TREE;
-
- /* Conversions NULL / variable <- cst are useless, but not
- the other way around. */
- if (outer_min
- && (!inner_min
- || !tree_int_cst_equal (inner_min, outer_min)))
- return false;
- if (outer_max
- && (!inner_max
- || !tree_int_cst_equal (inner_max, outer_max)))
- return false;
- }
-
- /* Recurse on the element check. */
- return useless_type_conversion_p (TREE_TYPE (outer_type),
- TREE_TYPE (inner_type));
- }
-
- else if ((TREE_CODE (inner_type) == FUNCTION_TYPE
- || TREE_CODE (inner_type) == METHOD_TYPE)
- && TREE_CODE (inner_type) == TREE_CODE (outer_type))
- {
- tree outer_parm, inner_parm;
-
- /* If the return types are not compatible bail out. */
- if (!useless_type_conversion_p (TREE_TYPE (outer_type),
- TREE_TYPE (inner_type)))
- return false;
+ attrs = lookup_attribute ("nonnull", attrs);
- /* Method types should belong to a compatible base class. */
- if (TREE_CODE (inner_type) == METHOD_TYPE
- && !useless_type_conversion_p (TYPE_METHOD_BASETYPE (outer_type),
- TYPE_METHOD_BASETYPE (inner_type)))
- return false;
-
- /* A conversion to an unprototyped argument list is ok. */
- if (!prototype_p (outer_type))
- return true;
-
- /* If the unqualified argument types are compatible the conversion
- is useless. */
- if (TYPE_ARG_TYPES (outer_type) == TYPE_ARG_TYPES (inner_type))
- return true;
-
- for (outer_parm = TYPE_ARG_TYPES (outer_type),
- inner_parm = TYPE_ARG_TYPES (inner_type);
- outer_parm && inner_parm;
- outer_parm = TREE_CHAIN (outer_parm),
- inner_parm = TREE_CHAIN (inner_parm))
- if (!useless_type_conversion_p
- (TYPE_MAIN_VARIANT (TREE_VALUE (outer_parm)),
- TYPE_MAIN_VARIANT (TREE_VALUE (inner_parm))))
- return false;
-
- /* If there is a mismatch in the number of arguments the functions
- are not compatible. */
- if (outer_parm || inner_parm)
- return false;
+ /* If "nonnull" wasn't specified, we know nothing about
+ the argument. */
+ if (attrs == NULL_TREE)
+ return false;
- /* Defer to the target if necessary. */
- if (TYPE_ATTRIBUTES (inner_type) || TYPE_ATTRIBUTES (outer_type))
- return comp_type_attributes (outer_type, inner_type) != 0;
+ /* If "nonnull" applies to all the arguments, then ARG
+ is non-null if it's in the argument list. */
+ if (TREE_VALUE (attrs) == NULL_TREE)
+ {
+ for (unsigned int i = 0; i < gimple_call_num_args (stmt); i++)
+ {
+ if (operand_equal_p (op, gimple_call_arg (stmt, i), 0)
+ && POINTER_TYPE_P (TREE_TYPE (gimple_call_arg (stmt, i))))
+ return true;
+ }
+ return false;
+ }
- return true;
+ /* Now see if op appears in the nonnull list. */
+ for (tree t = TREE_VALUE (attrs); t; t = TREE_CHAIN (t))
+ {
+ int idx = TREE_INT_CST_LOW (TREE_VALUE (t)) - 1;
+ tree arg = gimple_call_arg (stmt, idx);
+ if (operand_equal_p (op, arg, 0))
+ return true;
+ }
+ }
}
- /* For aggregates we rely on TYPE_CANONICAL exclusively and require
- explicit conversions for types involving to be structurally
- compared types. */
- else if (AGGREGATE_TYPE_P (inner_type)
- && TREE_CODE (inner_type) == TREE_CODE (outer_type))
- return false;
+ /* If this function is marked as returning non-null, then we can
+ infer OP is non-null if it is used in the return statement. */
+ if (gimple_code (stmt) == GIMPLE_RETURN
+ && gimple_return_retval (stmt)
+ && operand_equal_p (gimple_return_retval (stmt), op, 0)
+ && lookup_attribute ("returns_nonnull",
+ TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))))
+ return true;
return false;
}
-
-/* Return true if a conversion from either type of TYPE1 and TYPE2
- to the other is not required. Otherwise return false. */
-
-bool
-types_compatible_p (tree type1, tree type2)
-{
- return (type1 == type2
- || (useless_type_conversion_p (type1, type2)
- && useless_type_conversion_p (type2, type1)));
-}
-
-
-#include "gt-gimple.h"
diff --git a/gcc/gimple.def b/gcc/gimple.def
index f3652f4e78f..07370aedd29 100644
--- a/gcc/gimple.def
+++ b/gcc/gimple.def
@@ -276,6 +276,10 @@ DEFGSCODE(GIMPLE_OMP_FOR, "gimple_omp_for", GSS_OMP_FOR)
BODY is the sequence of statements to execute in the master section. */
DEFGSCODE(GIMPLE_OMP_MASTER, "gimple_omp_master", GSS_OMP)
+/* GIMPLE_OMP_TASKGROUP <BODY> represents #pragma omp taskgroup.
+ BODY is the sequence of statements to execute in the taskgroup section. */
+DEFGSCODE(GIMPLE_OMP_TASKGROUP, "gimple_omp_taskgroup", GSS_OMP)
+
/* GIMPLE_OMP_ORDERED <BODY> represents #pragma omp ordered.
BODY is the sequence of statements to execute in the ordered section. */
DEFGSCODE(GIMPLE_OMP_ORDERED, "gimple_omp_ordered", GSS_OMP)
@@ -325,7 +329,7 @@ DEFGSCODE(GIMPLE_OMP_PARALLEL, "gimple_omp_parallel", GSS_OMP_PARALLEL)
DEFGSCODE(GIMPLE_OMP_TASK, "gimple_omp_task", GSS_OMP_TASK)
/* OMP_RETURN marks the end of an OpenMP directive. */
-DEFGSCODE(GIMPLE_OMP_RETURN, "gimple_omp_return", GSS_BASE)
+DEFGSCODE(GIMPLE_OMP_RETURN, "gimple_omp_return", GSS_OMP_ATOMIC_STORE)
/* OMP_SECTION <BODY> represents #pragma omp section.
BODY is the sequence of statements in the section body. */
@@ -349,6 +353,24 @@ DEFGSCODE(GIMPLE_OMP_SECTIONS_SWITCH, "gimple_omp_sections_switch", GSS_BASE)
CLAUSES is an OMP_CLAUSE chain holding the associated clauses. */
DEFGSCODE(GIMPLE_OMP_SINGLE, "gimple_omp_single", GSS_OMP_SINGLE)
+/* GIMPLE_OMP_TARGET <BODY, CLAUSES, CHILD_FN> represents
+ #pragma omp target {,data,update}
+ BODY is the sequence of statements inside the target construct
+ (NULL for target update).
+ CLAUSES is an OMP_CLAUSE chain holding the associated clauses.
+ CHILD_FN is set when outlining the body of the target region.
+ All the statements in BODY are moved into this newly created
+ function when converting OMP constructs into low-GIMPLE.
+ DATA_ARG is a vec of 3 local variables in the parent function
+ containing data to be mapped to CHILD_FN. This is used to
+ implement the MAP clauses. */
+DEFGSCODE(GIMPLE_OMP_TARGET, "gimple_omp_target", GSS_OMP_PARALLEL)
+
+/* GIMPLE_OMP_TEAMS <BODY, CLAUSES> represents #pragma omp teams
+ BODY is the sequence of statements inside the single section.
+ CLAUSES is an OMP_CLAUSE chain holding the associated clauses. */
+DEFGSCODE(GIMPLE_OMP_TEAMS, "gimple_omp_teams", GSS_OMP_SINGLE)
+
/* GIMPLE_PREDICT <PREDICT, OUTCOME> specifies a hint for branch prediction.
PREDICT is one of the predictors from predict.def.
diff --git a/gcc/gimple.h b/gcc/gimple.h
index 5f1280586d2..33e790c18da 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -27,22 +27,14 @@ along with GCC; see the file COPYING3. If not see
#include "vec.h"
#include "ggc.h"
#include "basic-block.h"
-#include "tree.h"
-#include "tree-ssa-operands.h"
#include "tree-ssa-alias.h"
#include "internal-fn.h"
+#include "gimple-fold.h"
+#include "tree-eh.h"
+#include "gimple-expr.h"
typedef gimple gimple_seq_node;
-/* Types of supported temporaries. GIMPLE temporaries may be symbols
- in normal form (i.e., regular decls) or SSA names. This enum is
- used by create_gimple_tmp to tell it what kind of temporary the
- caller wants. */
-enum ssa_mode {
- M_SSA = 0,
- M_NORMAL
-};
-
/* For each block, the PHI nodes that need to be rewritten are stored into
these vectors. */
typedef vec<gimple> gimple_vec;
@@ -90,7 +82,7 @@ enum gimple_rhs_class
/* Specific flags for individual GIMPLE statements. These flags are
always stored in gimple_statement_base.subcode and they may only be
- defined for statement codes that do not use sub-codes.
+ defined for statement codes that do not use subcodes.
Values for the masks can overlap as long as the overlapping values
are never used in the same statement class.
@@ -113,6 +105,13 @@ enum gf_mask {
GF_OMP_FOR_KIND_MASK = 3 << 0,
GF_OMP_FOR_KIND_FOR = 0 << 0,
GF_OMP_FOR_KIND_SIMD = 1 << 0,
+ GF_OMP_FOR_KIND_DISTRIBUTE = 2 << 0,
+ GF_OMP_FOR_COMBINED = 1 << 2,
+ GF_OMP_FOR_COMBINED_INTO = 1 << 3,
+ GF_OMP_TARGET_KIND_MASK = 3 << 0,
+ GF_OMP_TARGET_KIND_REGION = 0 << 0,
+ GF_OMP_TARGET_KIND_DATA = 1 << 0,
+ GF_OMP_TARGET_KIND_UPDATE = 2 << 0,
/* True on an GIMPLE_OMP_RETURN statement if the return does not require
a thread synchronization via some sort of barrier. The exact barrier
@@ -122,6 +121,7 @@ enum gf_mask {
GF_OMP_SECTION_LAST = 1 << 0,
GF_OMP_ATOMIC_NEED_VALUE = 1 << 0,
+ GF_OMP_ATOMIC_SEQ_CST = 1 << 1,
GF_PREDICT_TAKEN = 1 << 15
};
@@ -615,7 +615,7 @@ struct GTY(()) gimple_statement_omp_continue {
tree control_use;
};
-/* GIMPLE_OMP_SINGLE */
+/* GIMPLE_OMP_SINGLE, GIMPLE_OMP_TARGET, GIMPLE_OMP_TEAMS */
struct GTY(()) gimple_statement_omp_single {
/* [ WORD 1-7 ] */
@@ -730,19 +730,6 @@ union GTY ((desc ("gimple_statement_structure (&%h)"),
struct gimple_statement_transaction GTY((tag ("GSS_TRANSACTION"))) gimple_transaction;
};
-/* In gimple.c. */
-
-/* Helper functions to build GIMPLE statements. */
-tree create_gimple_tmp (tree, enum ssa_mode = M_SSA);
-gimple build_assign (enum tree_code, tree, int, enum ssa_mode = M_SSA);
-gimple build_assign (enum tree_code, gimple, int, enum ssa_mode = M_SSA);
-gimple build_assign (enum tree_code, tree, tree, enum ssa_mode = M_SSA);
-gimple build_assign (enum tree_code, gimple, tree, enum ssa_mode = M_SSA);
-gimple build_assign (enum tree_code, tree, gimple, enum ssa_mode = M_SSA);
-gimple build_assign (enum tree_code, gimple, gimple, enum ssa_mode = M_SSA);
-gimple build_type_cast (tree, tree, enum ssa_mode = M_SSA);
-gimple build_type_cast (tree, gimple, enum ssa_mode = M_SSA);
-
/* Offset in bytes to the location of the operand vector.
Zero if there is no operand vector for this tuple structure. */
extern size_t const gimple_ops_offset_[];
@@ -759,8 +746,6 @@ gimple gimple_build_return (tree);
gimple gimple_build_assign_stat (tree, tree MEM_STAT_DECL);
#define gimple_build_assign(l,r) gimple_build_assign_stat (l, r MEM_STAT_INFO)
-void extract_ops_from_tree_1 (tree, enum tree_code *, tree *, tree *, tree *);
-
gimple
gimple_build_assign_with_ops (enum tree_code, tree,
tree, tree CXX_MEM_STAT_INFO);
@@ -807,11 +792,14 @@ gimple gimple_build_omp_critical (gimple_seq, tree);
gimple gimple_build_omp_section (gimple_seq);
gimple gimple_build_omp_continue (tree, tree);
gimple gimple_build_omp_master (gimple_seq);
+gimple gimple_build_omp_taskgroup (gimple_seq);
gimple gimple_build_omp_return (bool);
gimple gimple_build_omp_ordered (gimple_seq);
gimple gimple_build_omp_sections (gimple_seq, tree);
gimple gimple_build_omp_sections_switch (void);
gimple gimple_build_omp_single (gimple_seq, tree);
+gimple gimple_build_omp_target (gimple_seq, int, tree);
+gimple gimple_build_omp_teams (gimple_seq, tree);
gimple gimple_build_cdt (tree, tree);
gimple gimple_build_omp_atomic_load (tree, tree);
gimple gimple_build_omp_atomic_store (tree);
@@ -820,9 +808,6 @@ gimple gimple_build_predict (enum br_predictor, enum prediction);
enum gimple_statement_structure_enum gss_for_assign (enum tree_code);
void sort_case_labels (vec<tree> );
void preprocess_case_label_vec_for_gimple (vec<tree> , tree, tree *);
-void gimple_set_body (tree, gimple_seq);
-gimple_seq gimple_body (tree);
-bool gimple_has_body_p (tree);
gimple_seq gimple_seq_alloc (void);
void gimple_seq_free (gimple_seq);
void gimple_seq_add_seq (gimple_seq *, gimple_seq);
@@ -843,7 +828,6 @@ tree gimple_get_lhs (const_gimple);
void gimple_set_lhs (gimple, tree);
void gimple_replace_lhs (gimple, tree);
gimple gimple_copy (gimple);
-void gimple_cond_get_ops_from_tree (tree, enum tree_code *, tree *, tree *);
gimple gimple_build_cond_from_tree (tree, tree, tree);
void gimple_cond_set_condition_from_tree (gimple, tree);
bool gimple_has_side_effects (const_gimple);
@@ -855,62 +839,15 @@ bool empty_body_p (gimple_seq);
unsigned get_gimple_rhs_num_ops (enum tree_code);
#define gimple_alloc(c, n) gimple_alloc_stat (c, n MEM_STAT_INFO)
gimple gimple_alloc_stat (enum gimple_code, unsigned MEM_STAT_DECL);
-const char *gimple_decl_printable_name (tree, int);
-tree gimple_get_virt_method_for_binfo (HOST_WIDE_INT, tree);
-tree gimple_extract_devirt_binfo_from_cst (tree, tree);
-
-/* Returns true iff T is a scalar register variable. */
-extern bool is_gimple_reg (tree);
-/* Returns true iff T is any sort of variable. */
-extern bool is_gimple_variable (tree);
-/* Returns true iff T is any sort of symbol. */
-extern bool is_gimple_id (tree);
-/* Returns true iff T is a variable or an INDIRECT_REF (of a variable). */
-extern bool is_gimple_min_lval (tree);
-/* Returns true iff T is something whose address can be taken. */
-extern bool is_gimple_addressable (tree);
-/* Returns true iff T is any valid GIMPLE lvalue. */
-extern bool is_gimple_lvalue (tree);
-
-/* Returns true iff T is a GIMPLE address. */
-bool is_gimple_address (const_tree);
-/* Returns true iff T is a GIMPLE invariant address. */
-bool is_gimple_invariant_address (const_tree);
-/* Returns true iff T is a GIMPLE invariant address at interprocedural
- level. */
-bool is_gimple_ip_invariant_address (const_tree);
-/* Returns true iff T is a valid GIMPLE constant. */
-bool is_gimple_constant (const_tree);
-/* Returns true iff T is a GIMPLE restricted function invariant. */
-extern bool is_gimple_min_invariant (const_tree);
-/* Returns true iff T is a GIMPLE restricted interprecodural invariant. */
-extern bool is_gimple_ip_invariant (const_tree);
-/* Returns true iff T is a GIMPLE rvalue. */
-extern bool is_gimple_val (tree);
-/* Returns true iff T is a GIMPLE asm statement input. */
-extern bool is_gimple_asm_val (tree);
-/* Returns true iff T is a valid address operand of a MEM_REF. */
-bool is_gimple_mem_ref_addr (tree);
-
-/* Returns true iff T is a valid if-statement condition. */
-extern bool is_gimple_condexpr (tree);
-
-/* Returns true iff T is a valid call address expression. */
-extern bool is_gimple_call_addr (tree);
/* Return TRUE iff stmt is a call to a built-in function. */
extern bool is_gimple_builtin_call (gimple stmt);
extern void recalculate_side_effects (tree);
extern bool gimple_compare_field_offset (tree, tree);
-extern tree gimple_register_canonical_type (tree);
-extern void print_gimple_types_stats (const char *);
-extern void free_gimple_type_tables (void);
extern tree gimple_unsigned_type (tree);
extern tree gimple_signed_type (tree);
extern alias_set_type gimple_get_alias_set (tree);
-extern void count_uses_and_derefs (tree, gimple, unsigned *, unsigned *,
- unsigned *);
extern bool walk_stmt_load_store_addr_ops (gimple, void *,
bool (*)(gimple, tree, void *),
bool (*)(gimple, tree, void *),
@@ -922,8 +859,6 @@ extern bool gimple_ior_addresses_taken (bitmap, gimple);
extern bool gimple_call_builtin_p (gimple, enum built_in_class);
extern bool gimple_call_builtin_p (gimple, enum built_in_function);
extern bool gimple_asm_clobbers_memory_p (const_gimple);
-extern bool useless_type_conversion_p (tree, tree);
-extern bool types_compatible_p (tree, tree);
/* In gimplify.c */
extern tree create_tmp_var_raw (tree, const char *);
@@ -934,6 +869,7 @@ extern tree get_initialized_tmp_var (tree, gimple_seq *, gimple_seq *);
extern tree get_formal_tmp_var (tree, gimple_seq *);
extern void declare_vars (tree, gimple, bool);
extern void annotate_all_with_location (gimple_seq, location_t);
+extern unsigned gimple_call_get_nobnd_arg_index (const_gimple, unsigned);
/* Validation of GIMPLE expressions. Note that these predicates only check
the basic form of the expression, they don't recurse to make sure that
@@ -1053,6 +989,27 @@ is_gimple_sizepos (tree expr)
|| CONTAINS_PLACEHOLDER_P (expr));
}
+/* Get the number of the next statement uid to be allocated. */
+static inline unsigned int
+gimple_stmt_max_uid (struct function *fn)
+{
+ return fn->last_stmt_uid;
+}
+
+/* Set the number of the next statement uid to be allocated. */
+static inline void
+set_gimple_stmt_max_uid (struct function *fn, unsigned int maxid)
+{
+ fn->last_stmt_uid = maxid;
+}
+
+/* Set the number of the next statement uid to be allocated. */
+static inline unsigned int
+inc_gimple_stmt_max_uid (struct function *fn)
+{
+ return fn->last_stmt_uid++;
+}
+
extern enum gimplify_status gimplify_expr (tree *, gimple_seq *, gimple_seq *,
bool (*) (tree), fallback_t);
extern void gimplify_type_sizes (tree, gimple_seq *);
@@ -1079,9 +1036,9 @@ extern void omp_firstprivatize_variable (struct gimplify_omp_ctx *, tree);
extern tree gimple_boolify (tree);
extern gimple_predicate rhs_predicate_for (tree);
extern tree canonicalize_cond_expr_cond (tree);
-
-/* In omp-low.c. */
-extern tree omp_reduction_init (tree, tree);
+extern void dump_decl_set (FILE *, bitmap);
+extern bool nonfreeing_call_p (gimple);
+extern bool infer_nonnull_range (gimple, tree);
/* In trans-mem.c. */
extern void diagnose_tm_safe_errors (tree);
@@ -1100,9 +1057,6 @@ extern tree gimple_assign_rhs_to_tree (gimple);
/* In builtins.c */
extern bool validate_gimple_arglist (const_gimple, ...);
-/* In tree-ssa-coalesce.c */
-extern bool gimple_can_coalesce_p (tree, tree);
-
/* Return the first node in GIMPLE sequence S. */
static inline gimple_seq_node
@@ -1254,12 +1208,15 @@ gimple_has_substatements (gimple g)
case GIMPLE_TRY:
case GIMPLE_OMP_FOR:
case GIMPLE_OMP_MASTER:
+ case GIMPLE_OMP_TASKGROUP:
case GIMPLE_OMP_ORDERED:
case GIMPLE_OMP_SECTION:
case GIMPLE_OMP_PARALLEL:
case GIMPLE_OMP_TASK:
case GIMPLE_OMP_SECTIONS:
case GIMPLE_OMP_SINGLE:
+ case GIMPLE_OMP_TARGET:
+ case GIMPLE_OMP_TEAMS:
case GIMPLE_OMP_CRITICAL:
case GIMPLE_WITH_CLEANUP_EXPR:
case GIMPLE_TRANSACTION:
@@ -1486,34 +1443,6 @@ gimple_set_use_ops (gimple g, struct use_optype_d *use)
}
-/* Return the set of VUSE operand for statement G. */
-
-static inline use_operand_p
-gimple_vuse_op (const_gimple g)
-{
- struct use_optype_d *ops;
- if (!gimple_has_mem_ops (g))
- return NULL_USE_OPERAND_P;
- ops = g->gsops.opbase.use_ops;
- if (ops
- && USE_OP_PTR (ops)->use == &g->gsmembase.vuse)
- return USE_OP_PTR (ops);
- return NULL_USE_OPERAND_P;
-}
-
-/* Return the set of VDEF operand for statement G. */
-
-static inline def_operand_p
-gimple_vdef_op (gimple g)
-{
- if (!gimple_has_mem_ops (g))
- return NULL_DEF_OPERAND_P;
- if (g->gsmembase.vdef)
- return &g->gsmembase.vdef;
- return NULL_DEF_OPERAND_P;
-}
-
-
/* Return the single VUSE operand of the statement G. */
static inline tree
@@ -1614,27 +1543,6 @@ gimple_expr_code (const_gimple stmt)
}
-/* Mark statement S as modified, and update it. */
-
-static inline void
-update_stmt (gimple s)
-{
- if (gimple_has_ops (s))
- {
- gimple_set_modified (s, true);
- update_stmt_operands (s);
- }
-}
-
-/* Update statement S if it has been optimized. */
-
-static inline void
-update_stmt_if_modified (gimple s)
-{
- if (gimple_modified_p (s))
- update_stmt_operands (s);
-}
-
/* Return true if statement STMT contains volatile operands. */
static inline bool
@@ -1656,20 +1564,12 @@ gimple_set_has_volatile_ops (gimple stmt, bool volatilep)
stmt->gsbase.has_volatile_ops = (unsigned) volatilep;
}
-/* Return true if BB is in a transaction. */
-
-static inline bool
-block_in_transaction (basic_block bb)
-{
- return flag_tm && bb->flags & BB_IN_TRANSACTION;
-}
-
/* Return true if STMT is in a transaction. */
static inline bool
gimple_in_transaction (gimple stmt)
{
- return block_in_transaction (gimple_bb (stmt));
+ return bb_in_transaction (gimple_bb (stmt));
}
/* Return true if statement STMT may access memory. */
@@ -1687,7 +1587,7 @@ static inline unsigned
gimple_omp_subcode (const_gimple s)
{
gcc_gimple_checking_assert (gimple_code (s) >= GIMPLE_OMP_ATOMIC_LOAD
- && gimple_code (s) <= GIMPLE_OMP_SINGLE);
+ && gimple_code (s) <= GIMPLE_OMP_TEAMS);
return s->gsbase.subcode;
}
@@ -1723,6 +1623,36 @@ gimple_omp_return_nowait_p (const_gimple g)
}
+/* Set the LHS of OMP return. */
+
+static inline void
+gimple_omp_return_set_lhs (gimple g, tree lhs)
+{
+ GIMPLE_CHECK (g, GIMPLE_OMP_RETURN);
+ g->gimple_omp_atomic_store.val = lhs;
+}
+
+
+/* Get the LHS of OMP return. */
+
+static inline tree
+gimple_omp_return_lhs (const_gimple g)
+{
+ GIMPLE_CHECK (g, GIMPLE_OMP_RETURN);
+ return g->gimple_omp_atomic_store.val;
+}
+
+
+/* Return a pointer to the LHS of OMP return. */
+
+static inline tree *
+gimple_omp_return_lhs_ptr (gimple g)
+{
+ GIMPLE_CHECK (g, GIMPLE_OMP_RETURN);
+ return &g->gimple_omp_atomic_store.val;
+}
+
+
/* Return true if OMP section statement G has the GF_OMP_SECTION_LAST
flag set. */
@@ -1792,6 +1722,29 @@ gimple_omp_atomic_set_need_value (gimple g)
}
+/* Return true if OMP atomic load/store statement G has the
+ GF_OMP_ATOMIC_SEQ_CST flag set. */
+
+static inline bool
+gimple_omp_atomic_seq_cst_p (const_gimple g)
+{
+ if (gimple_code (g) != GIMPLE_OMP_ATOMIC_LOAD)
+ GIMPLE_CHECK (g, GIMPLE_OMP_ATOMIC_STORE);
+ return (gimple_omp_subcode (g) & GF_OMP_ATOMIC_SEQ_CST) != 0;
+}
+
+
+/* Set the GF_OMP_ATOMIC_SEQ_CST flag on G. */
+
+static inline void
+gimple_omp_atomic_set_seq_cst (gimple g)
+{
+ if (gimple_code (g) != GIMPLE_OMP_ATOMIC_LOAD)
+ GIMPLE_CHECK (g, GIMPLE_OMP_ATOMIC_STORE);
+ g->gsbase.subcode |= GF_OMP_ATOMIC_SEQ_CST;
+}
+
+
/* Return the number of operands for statement GS. */
static inline unsigned
@@ -2031,18 +1984,6 @@ gimple_assign_set_rhs_with_ops (gimple_stmt_iterator *gsi, enum tree_code code,
gimple_assign_set_rhs_with_ops_1 (gsi, code, op1, op2, NULL);
}
-/* A wrapper around extract_ops_from_tree_1, for callers which expect
- to see only a maximum of two operands. */
-
-static inline void
-extract_ops_from_tree (tree expr, enum tree_code *code, tree *op0,
- tree *op1)
-{
- tree op2;
- extract_ops_from_tree_1 (expr, code, op0, op1, &op2);
- gcc_assert (op2 == NULL_TREE);
-}
-
/* Returns true if GS is a nontemporal move. */
static inline bool
@@ -2305,25 +2246,6 @@ gimple_call_set_internal_fn (gimple gs, enum internal_fn fn)
}
-/* Given a valid GIMPLE_CALL function address return the FUNCTION_DECL
- associated with the callee if known. Otherwise return NULL_TREE. */
-
-static inline tree
-gimple_call_addr_fndecl (const_tree fn)
-{
- if (fn && TREE_CODE (fn) == ADDR_EXPR)
- {
- tree fndecl = TREE_OPERAND (fn, 0);
- if (TREE_CODE (fndecl) == MEM_REF
- && TREE_CODE (TREE_OPERAND (fndecl, 0)) == ADDR_EXPR
- && integer_zerop (TREE_OPERAND (fndecl, 1)))
- fndecl = TREE_OPERAND (TREE_OPERAND (fndecl, 0), 0);
- if (TREE_CODE (fndecl) == FUNCTION_DECL)
- return fndecl;
- }
- return NULL_TREE;
-}
-
/* If a given GIMPLE_CALL's callee is a FUNCTION_DECL, return it.
Otherwise return NULL. This function is analogous to
get_callee_fndecl in tree land. */
@@ -2403,6 +2325,32 @@ gimple_call_arg (const_gimple gs, unsigned index)
}
+/* Return the number of arguments used by call statement GS
+ ignoring bound ones. */
+
+static inline unsigned
+gimple_call_num_nobnd_args (const_gimple gs)
+{
+ unsigned num_args = gimple_call_num_args (gs);
+ unsigned res = num_args;
+ for (unsigned n = 0; n < num_args; n++)
+ if (POINTER_BOUNDS_P (gimple_call_arg (gs, n)))
+ res--;
+ return res;
+}
+
+
+/* Return INDEX's call argument ignoring bound ones. */
+static inline tree
+gimple_call_nobnd_arg (const_gimple gs, unsigned index)
+{
+ /* No bound args may exist if pointers checker is off. */
+ if (!flag_check_pointer_bounds)
+ return gimple_call_arg (gs, index);
+ return gimple_call_arg (gs, gimple_call_get_nobnd_arg_index (gs, index));
+}
+
+
/* Return a pointer to the argument at position INDEX for call
statement GS. */
@@ -3596,6 +3544,83 @@ gimple_phi_set_arg (gimple gs, unsigned index, struct phi_arg_d * phiarg)
gs->gimple_phi.args[index] = *phiarg;
}
+/* Return the PHI nodes for basic block BB, or NULL if there are no
+ PHI nodes. */
+
+static inline gimple_seq
+phi_nodes (const_basic_block bb)
+{
+ gcc_checking_assert (!(bb->flags & BB_RTL));
+ return bb->il.gimple.phi_nodes;
+}
+
+/* Return a pointer to the PHI nodes for basic block BB. */
+
+static inline gimple_seq *
+phi_nodes_ptr (basic_block bb)
+{
+ gcc_checking_assert (!(bb->flags & BB_RTL));
+ return &bb->il.gimple.phi_nodes;
+}
+
+/* Return the tree operand for argument I of PHI node GS. */
+
+static inline tree
+gimple_phi_arg_def (gimple gs, size_t index)
+{
+ return gimple_phi_arg (gs, index)->def;
+}
+
+
+/* Return a pointer to the tree operand for argument I of PHI node GS. */
+
+static inline tree *
+gimple_phi_arg_def_ptr (gimple gs, size_t index)
+{
+ return &gimple_phi_arg (gs, index)->def;
+}
+
+/* Return the edge associated with argument I of phi node GS. */
+
+static inline edge
+gimple_phi_arg_edge (gimple gs, size_t i)
+{
+ return EDGE_PRED (gimple_bb (gs), i);
+}
+
+/* Return the source location of gimple argument I of phi node GS. */
+
+static inline source_location
+gimple_phi_arg_location (gimple gs, size_t i)
+{
+ return gimple_phi_arg (gs, i)->locus;
+}
+
+/* Return the source location of the argument on edge E of phi node GS. */
+
+static inline source_location
+gimple_phi_arg_location_from_edge (gimple gs, edge e)
+{
+ return gimple_phi_arg (gs, e->dest_idx)->locus;
+}
+
+/* Set the source location of gimple argument I of phi node GS to LOC. */
+
+static inline void
+gimple_phi_arg_set_location (gimple gs, size_t i, source_location loc)
+{
+ gimple_phi_arg (gs, i)->locus = loc;
+}
+
+/* Return TRUE if argument I of phi node GS has a location record. */
+
+static inline bool
+gimple_phi_arg_has_location (gimple gs, size_t i)
+{
+ return gimple_phi_arg_location (gs, i) != UNKNOWN_LOCATION;
+}
+
+
/* Return the region number for GIMPLE_RESX GS. */
static inline int
@@ -3892,6 +3917,23 @@ gimple_debug_source_bind_set_value (gimple dbg, tree value)
gimple_set_op (dbg, 1, value);
}
+/* Return the line number for EXPR, or return -1 if we have no line
+ number information for it. */
+static inline int
+get_lineno (const_gimple stmt)
+{
+ location_t loc;
+
+ if (!stmt)
+ return -1;
+
+ loc = gimple_location (stmt);
+ if (loc == UNKNOWN_LOCATION)
+ return -1;
+
+ return LOCATION_LINE (loc);
+}
+
/* Return a pointer to the body for the OMP statement GS. */
static inline gimple_seq *
@@ -3968,6 +4010,56 @@ gimple_omp_for_set_kind (gimple g, int kind)
}
+/* Return true if OMP for statement G has the
+ GF_OMP_FOR_COMBINED flag set. */
+
+static inline bool
+gimple_omp_for_combined_p (const_gimple g)
+{
+ GIMPLE_CHECK (g, GIMPLE_OMP_FOR);
+ return (gimple_omp_subcode (g) & GF_OMP_FOR_COMBINED) != 0;
+}
+
+
+/* Set the GF_OMP_FOR_COMBINED field in G depending on the boolean
+ value of COMBINED_P. */
+
+static inline void
+gimple_omp_for_set_combined_p (gimple g, bool combined_p)
+{
+ GIMPLE_CHECK (g, GIMPLE_OMP_FOR);
+ if (combined_p)
+ g->gsbase.subcode |= GF_OMP_FOR_COMBINED;
+ else
+ g->gsbase.subcode &= ~GF_OMP_FOR_COMBINED;
+}
+
+
+/* Return true if OMP for statement G has the
+ GF_OMP_FOR_COMBINED_INTO flag set. */
+
+static inline bool
+gimple_omp_for_combined_into_p (const_gimple g)
+{
+ GIMPLE_CHECK (g, GIMPLE_OMP_FOR);
+ return (gimple_omp_subcode (g) & GF_OMP_FOR_COMBINED_INTO) != 0;
+}
+
+
+/* Set the GF_OMP_FOR_COMBINED_INTO field in G depending on the boolean
+ value of COMBINED_P. */
+
+static inline void
+gimple_omp_for_set_combined_into_p (gimple g, bool combined_p)
+{
+ GIMPLE_CHECK (g, GIMPLE_OMP_FOR);
+ if (combined_p)
+ g->gsbase.subcode |= GF_OMP_FOR_COMBINED_INTO;
+ else
+ g->gsbase.subcode &= ~GF_OMP_FOR_COMBINED_INTO;
+}
+
+
/* Return the clauses associated with OMP_FOR GS. */
static inline tree
@@ -4577,6 +4669,148 @@ gimple_omp_single_set_clauses (gimple gs, tree clauses)
}
+/* Return the clauses associated with OMP_TARGET GS. */
+
+static inline tree
+gimple_omp_target_clauses (const_gimple gs)
+{
+ GIMPLE_CHECK (gs, GIMPLE_OMP_TARGET);
+ return gs->gimple_omp_parallel.clauses;
+}
+
+
+/* Return a pointer to the clauses associated with OMP_TARGET GS. */
+
+static inline tree *
+gimple_omp_target_clauses_ptr (gimple gs)
+{
+ GIMPLE_CHECK (gs, GIMPLE_OMP_TARGET);
+ return &gs->gimple_omp_parallel.clauses;
+}
+
+
+/* Set CLAUSES to be the clauses associated with OMP_TARGET GS. */
+
+static inline void
+gimple_omp_target_set_clauses (gimple gs, tree clauses)
+{
+ GIMPLE_CHECK (gs, GIMPLE_OMP_TARGET);
+ gs->gimple_omp_parallel.clauses = clauses;
+}
+
+
+/* Return the kind of OMP target statemement. */
+
+static inline int
+gimple_omp_target_kind (const_gimple g)
+{
+ GIMPLE_CHECK (g, GIMPLE_OMP_TARGET);
+ return (gimple_omp_subcode (g) & GF_OMP_TARGET_KIND_MASK);
+}
+
+
+/* Set the OMP target kind. */
+
+static inline void
+gimple_omp_target_set_kind (gimple g, int kind)
+{
+ GIMPLE_CHECK (g, GIMPLE_OMP_TARGET);
+ g->gsbase.subcode = (g->gsbase.subcode & ~GF_OMP_TARGET_KIND_MASK)
+ | (kind & GF_OMP_TARGET_KIND_MASK);
+}
+
+
+/* Return the child function used to hold the body of OMP_TARGET GS. */
+
+static inline tree
+gimple_omp_target_child_fn (const_gimple gs)
+{
+ GIMPLE_CHECK (gs, GIMPLE_OMP_TARGET);
+ return gs->gimple_omp_parallel.child_fn;
+}
+
+/* Return a pointer to the child function used to hold the body of
+ OMP_TARGET GS. */
+
+static inline tree *
+gimple_omp_target_child_fn_ptr (gimple gs)
+{
+ GIMPLE_CHECK (gs, GIMPLE_OMP_TARGET);
+ return &gs->gimple_omp_parallel.child_fn;
+}
+
+
+/* Set CHILD_FN to be the child function for OMP_TARGET GS. */
+
+static inline void
+gimple_omp_target_set_child_fn (gimple gs, tree child_fn)
+{
+ GIMPLE_CHECK (gs, GIMPLE_OMP_TARGET);
+ gs->gimple_omp_parallel.child_fn = child_fn;
+}
+
+
+/* Return the artificial argument used to send variables and values
+ from the parent to the children threads in OMP_TARGET GS. */
+
+static inline tree
+gimple_omp_target_data_arg (const_gimple gs)
+{
+ GIMPLE_CHECK (gs, GIMPLE_OMP_TARGET);
+ return gs->gimple_omp_parallel.data_arg;
+}
+
+
+/* Return a pointer to the data argument for OMP_TARGET GS. */
+
+static inline tree *
+gimple_omp_target_data_arg_ptr (gimple gs)
+{
+ GIMPLE_CHECK (gs, GIMPLE_OMP_TARGET);
+ return &gs->gimple_omp_parallel.data_arg;
+}
+
+
+/* Set DATA_ARG to be the data argument for OMP_TARGET GS. */
+
+static inline void
+gimple_omp_target_set_data_arg (gimple gs, tree data_arg)
+{
+ GIMPLE_CHECK (gs, GIMPLE_OMP_TARGET);
+ gs->gimple_omp_parallel.data_arg = data_arg;
+}
+
+
+/* Return the clauses associated with OMP_TEAMS GS. */
+
+static inline tree
+gimple_omp_teams_clauses (const_gimple gs)
+{
+ GIMPLE_CHECK (gs, GIMPLE_OMP_TEAMS);
+ return gs->gimple_omp_single.clauses;
+}
+
+
+/* Return a pointer to the clauses associated with OMP_TEAMS GS. */
+
+static inline tree *
+gimple_omp_teams_clauses_ptr (gimple gs)
+{
+ GIMPLE_CHECK (gs, GIMPLE_OMP_TEAMS);
+ return &gs->gimple_omp_single.clauses;
+}
+
+
+/* Set CLAUSES to be the clauses associated with OMP_TEAMS GS. */
+
+static inline void
+gimple_omp_teams_set_clauses (gimple gs, tree clauses)
+{
+ GIMPLE_CHECK (gs, GIMPLE_OMP_TEAMS);
+ gs->gimple_omp_single.clauses = clauses;
+}
+
+
/* Return the clauses associated with OMP_SECTIONS GS. */
static inline tree
@@ -4910,6 +5144,26 @@ gimple_return_set_retval (gimple gs, tree retval)
}
+/* Return the return bounds for GIMPLE_RETURN GS. */
+
+static inline tree
+gimple_return_retbnd (const_gimple gs)
+{
+ GIMPLE_CHECK (gs, GIMPLE_RETURN);
+ return gimple_op (gs, 1);
+}
+
+
+/* Set RETVAL to be the return bounds for GIMPLE_RETURN GS. */
+
+static inline void
+gimple_return_set_retbnd (gimple gs, tree retval)
+{
+ GIMPLE_CHECK (gs, GIMPLE_RETURN);
+ gimple_set_op (gs, 1, retval);
+}
+
+
/* Returns true when the gimple statement STMT is any of the OpenMP types. */
#define CASE_GIMPLE_OMP \
@@ -4919,8 +5173,11 @@ gimple_return_set_retval (gimple gs, tree retval)
case GIMPLE_OMP_SECTIONS: \
case GIMPLE_OMP_SECTIONS_SWITCH: \
case GIMPLE_OMP_SINGLE: \
+ case GIMPLE_OMP_TARGET: \
+ case GIMPLE_OMP_TEAMS: \
case GIMPLE_OMP_SECTION: \
case GIMPLE_OMP_MASTER: \
+ case GIMPLE_OMP_TASKGROUP: \
case GIMPLE_OMP_ORDERED: \
case GIMPLE_OMP_CRITICAL: \
case GIMPLE_OMP_RETURN: \
@@ -5039,14 +5296,6 @@ gimple_expr_type (const_gimple stmt)
return void_type_node;
}
-/* Return true if TYPE is a suitable type for a scalar register variable. */
-
-static inline bool
-is_gimple_reg_type (tree type)
-{
- return !AGGREGATE_TYPE_P (type);
-}
-
/* Return a new iterator pointing to GIMPLE_SEQ's first statement. */
static inline gimple_stmt_iterator
@@ -5061,7 +5310,7 @@ gsi_start_1 (gimple_seq *seq)
return i;
}
-#define gsi_start(x) gsi_start_1(&(x))
+#define gsi_start(x) gsi_start_1 (&(x))
static inline gimple_stmt_iterator
gsi_none (void)
@@ -5104,7 +5353,7 @@ gsi_last_1 (gimple_seq *seq)
return i;
}
-#define gsi_last(x) gsi_last_1(&(x))
+#define gsi_last(x) gsi_last_1 (&(x))
/* Return a new iterator pointing to the last statement in basic block BB. */
@@ -5221,6 +5470,20 @@ gsi_start_nondebug_bb (basic_block bb)
return i;
}
+/* Return a new iterator pointing to the first non-debug non-label statement in
+ basic block BB. */
+
+static inline gimple_stmt_iterator
+gsi_start_nondebug_after_labels_bb (basic_block bb)
+{
+ gimple_stmt_iterator i = gsi_after_labels (bb);
+
+ if (!gsi_end_p (i) && is_gimple_debug (gsi_stmt (i)))
+ gsi_next_nondebug (&i);
+
+ return i;
+}
+
/* Return a new iterator pointing to the last non-debug statement in
basic block BB. */
@@ -5300,6 +5563,14 @@ void gsi_commit_one_edge_insert (edge, basic_block *);
void gsi_commit_edge_inserts (void);
gimple gimple_call_copy_skip_args (gimple, bitmap);
+/* In gimplify.c. */
+tree force_gimple_operand_1 (tree, gimple_seq *, gimple_predicate, tree);
+tree force_gimple_operand (tree, gimple_seq *, bool, tree);
+tree force_gimple_operand_gsi_1 (gimple_stmt_iterator *, tree,
+ gimple_predicate, tree,
+ bool, enum gsi_iterator_update);
+tree force_gimple_operand_gsi (gimple_stmt_iterator *, tree, bool, tree,
+ bool, enum gsi_iterator_update);
/* Convenience routines to walk all statements of a gimple function.
Note that this is useful exclusively before the code is converted
@@ -5404,21 +5675,6 @@ gimple_alloc_kind (enum gimple_code code)
extern void dump_gimple_statistics (void);
-/* In gimple-fold.c. */
-void gimplify_and_update_call_from_tree (gimple_stmt_iterator *, tree);
-tree gimple_fold_builtin (gimple);
-bool fold_stmt (gimple_stmt_iterator *);
-bool fold_stmt_inplace (gimple_stmt_iterator *);
-tree get_symbol_constant_value (tree);
-tree canonicalize_constructor_val (tree, tree);
-extern tree maybe_fold_and_comparisons (enum tree_code, tree, tree,
- enum tree_code, tree, tree);
-extern tree maybe_fold_or_comparisons (enum tree_code, tree, tree,
- enum tree_code, tree, tree);
-
-bool gimple_val_nonnegative_real_p (tree);
-
-
/* Set the location of all statements in SEQ to LOC. */
static inline void
@@ -5428,4 +5684,15 @@ gimple_seq_set_location (gimple_seq seq, location_t loc)
gimple_set_location (gsi_stmt (i), loc);
}
+/* Macros for showing usage statistics. */
+#define SCALE(x) ((unsigned long) ((x) < 1024*10 \
+ ? (x) \
+ : ((x) < 1024*1024*10 \
+ ? (x) / 1024 \
+ : (x) / (1024*1024))))
+
+#define LABEL(x) ((x) < 1024*10 ? 'b' : ((x) < 1024*1024*10 ? 'k' : 'M'))
+
+#define PERCENT(x,y) ((float)(x) * 100.0 / (float)(y))
+
#endif /* GCC_GIMPLE_H */
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 1589db44b42..914766ad3b0 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -30,8 +30,12 @@ along with GCC; see the file COPYING3. If not see
#include "tree-inline.h"
#include "tree-pretty-print.h"
#include "langhooks.h"
-#include "tree-ssa.h"
+#include "bitmap.h"
+#include "gimple-ssa.h"
#include "cgraph.h"
+#include "tree-cfg.h"
+#include "tree-ssanames.h"
+#include "tree-ssa.h"
#include "timevar.h"
#include "hashtab.h"
#include "flags.h"
@@ -42,9 +46,14 @@ along with GCC; see the file COPYING3. If not see
#include "pointer-set.h"
#include "splay-tree.h"
#include "vec.h"
+#include "omp-low.h"
+#include "gimple-low.h"
+#include "cilk.h"
#include "langhooks-def.h" /* FIXME: for lhd_set_decl_assembler_name */
#include "tree-pass.h" /* FIXME: only for PROP_gimple_any */
+#include "expr.h"
+#include "tm_p.h"
enum gimplify_omp_var_data
{
@@ -56,9 +65,12 @@ enum gimplify_omp_var_data
GOVD_LASTPRIVATE = 32,
GOVD_REDUCTION = 64,
GOVD_LOCAL = 128,
- GOVD_DEBUG_PRIVATE = 256,
- GOVD_PRIVATE_OUTER_REF = 512,
+ GOVD_MAP = 256,
+ GOVD_DEBUG_PRIVATE = 512,
+ GOVD_PRIVATE_OUTER_REF = 1024,
GOVD_LINEAR = 2048,
+ GOVD_ALIGNED = 4096,
+ GOVD_MAP_TO_ONLY = 8192,
GOVD_DATA_SHARE_CLASS = (GOVD_SHARED | GOVD_PRIVATE | GOVD_FIRSTPRIVATE
| GOVD_LASTPRIVATE | GOVD_REDUCTION | GOVD_LINEAR
| GOVD_LOCAL)
@@ -72,7 +84,10 @@ enum omp_region_type
ORT_PARALLEL = 2,
ORT_COMBINED_PARALLEL = 3,
ORT_TASK = 4,
- ORT_UNTIED_TASK = 5
+ ORT_UNTIED_TASK = 5,
+ ORT_TEAMS = 8,
+ ORT_TARGET_DATA = 16,
+ ORT_TARGET = 32
};
struct gimplify_omp_ctx
@@ -83,6 +98,7 @@ struct gimplify_omp_ctx
location_t location;
enum omp_clause_default_kind default_kind;
enum omp_region_type region_type;
+ bool combined_loop;
};
static struct gimplify_ctx *gimplify_ctxp;
@@ -962,7 +978,7 @@ unshare_body (tree fndecl)
if (cgn)
for (cgn = cgn->nested; cgn; cgn = cgn->next_nested)
- unshare_body (cgn->symbol.decl);
+ unshare_body (cgn->decl);
}
/* Callback for walk_tree to unmark the visited trees rooted at *TP.
@@ -1005,7 +1021,7 @@ unvisit_body (tree fndecl)
if (cgn)
for (cgn = cgn->nested; cgn; cgn = cgn->next_nested)
- unvisit_body (cgn->symbol.decl);
+ unvisit_body (cgn->decl);
}
/* Unconditionally make an unshared copy of EXPR. This is used when using
@@ -1220,8 +1236,7 @@ gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p)
gimple stack_restore;
/* Save stack on entry and restore it on exit. Add a try_finally
- block to achieve this. Note that mudflap depends on the
- format of the emitted code: see mx_register_decls(). */
+ block to achieve this. */
build_stack_save_restore (&stack_save, &stack_restore);
gimplify_seq_add_stmt (&cleanup, stack_restore);
@@ -1295,6 +1310,15 @@ gimplify_return_expr (tree stmt, gimple_seq *pre_p)
if (ret_expr == error_mark_node)
return GS_ERROR;
+ /* Implicit _Cilk_sync must be inserted right before any return statement
+ if there is a _Cilk_spawn in the function. If the user has provided a
+ _Cilk_sync, the optimizer should remove this duplicate one. */
+ if (fn_contains_cilk_spawn_p (cfun))
+ {
+ tree impl_sync = build0 (CILK_SYNC_STMT, void_type_node);
+ gimplify_and_add (impl_sync, pre_p);
+ }
+
if (!ret_expr
|| TREE_CODE (ret_expr) == RESULT_DECL
|| ret_expr == error_mark_node)
@@ -1379,8 +1403,7 @@ static void
gimplify_vla_decl (tree decl, gimple_seq *seq_p)
{
/* This is a variable-sized decl. Simplify its size and mark it
- for deferred expansion. Note that mudflap depends on the format
- of the emitted code: see mx_register_decls(). */
+ for deferred expansion. */
tree t, addr, ptr_type;
gimplify_one_sizepos (&DECL_SIZE (decl), seq_p);
@@ -2119,7 +2142,6 @@ gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
fallback_t fallback)
{
tree *p;
- vec<tree> expr_stack;
enum gimplify_status ret = GS_ALL_DONE, tret;
int i;
location_t loc = EXPR_LOCATION (*expr_p);
@@ -2127,7 +2149,7 @@ gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
/* Create a stack of the subexpressions so later we can walk them in
order from inner to outer. */
- expr_stack.create (10);
+ stack_vec<tree, 10> expr_stack;
/* We can handle anything that get_inner_reference can deal with. */
for (p = expr_p; ; p = &TREE_OPERAND (*p, 0))
@@ -2485,6 +2507,12 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
if (! EXPR_HAS_LOCATION (*expr_p))
SET_EXPR_LOCATION (*expr_p, input_location);
+ if (fn_contains_cilk_spawn_p (cfun)
+ && lang_hooks.cilkplus.cilk_detect_spawn_and_unwrap (expr_p)
+ && !seen_error ())
+ return (enum gimplify_status)
+ lang_hooks.cilkplus.gimplify_cilk_spawn (expr_p, pre_p, NULL);
+
/* This may be a call to a builtin function.
Builtin function calls may be transformed into different
@@ -2698,7 +2726,14 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
notice_special_calls (call);
gimplify_seq_add_stmt (pre_p, call);
gsi = gsi_last (*pre_p);
- fold_stmt (&gsi);
+ /* Don't fold stmts inside of target construct. We'll do it
+ during omplower pass instead. */
+ struct gimplify_omp_ctx *ctx;
+ for (ctx = gimplify_omp_ctxp; ctx; ctx = ctx->outer_context)
+ if (ctx->region_type == ORT_TARGET)
+ break;
+ if (ctx == NULL)
+ fold_stmt (&gsi);
*expr_p = NULL_TREE;
}
else
@@ -3053,6 +3088,17 @@ gimple_boolify (tree expr)
TREE_TYPE (expr) = boolean_type_node;
return expr;
+ case ANNOTATE_EXPR:
+ if ((enum annot_expr_kind) TREE_INT_CST_LOW (TREE_OPERAND (expr, 1))
+ == annot_expr_ivdep_kind)
+ {
+ TREE_OPERAND (expr, 0) = gimple_boolify (TREE_OPERAND (expr, 0));
+ if (TREE_CODE (type) != BOOLEAN_TYPE)
+ TREE_TYPE (expr) = boolean_type_node;
+ return expr;
+ }
+ /* FALLTHRU */
+
default:
if (COMPARISON_CLASS_P (expr))
{
@@ -4006,9 +4052,9 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
objects. Initializers for such objects must explicitly set
every field that needs to be set. */
cleared = false;
- else if (!complete_p)
+ else if (!complete_p && !CONSTRUCTOR_NO_CLEARING (ctor))
/* If the constructor isn't complete, clear the whole object
- beforehand.
+ beforehand, unless CONSTRUCTOR_NO_CLEARING is set on it.
??? This ought not to be needed. For any element not present
in the initializer, we should simply set them to zero. Except
@@ -4033,10 +4079,19 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
individual element initialization. Also don't do this for small
all-zero initializers (which aren't big enough to merit
clearing), and don't try to make bitwise copies of
- TREE_ADDRESSABLE types. */
+ TREE_ADDRESSABLE types.
+
+ We cannot apply such transformation when compiling chkp static
+ initializer because creation of initializer image in the memory
+ will require static initialization of bounds for it. It should
+ result in another gimplification of similar initializer and we
+ may fall into infinite loop. */
if (valid_const_initializer
&& !(cleared || num_nonzero_elements == 0)
- && !TREE_ADDRESSABLE (type))
+ && !TREE_ADDRESSABLE (type)
+ && (!current_function_decl
+ || !lookup_attribute ("chkp ctor",
+ DECL_ATTRIBUTES (current_function_decl))))
{
HOST_WIDE_INT size = int_size_in_bytes (type);
unsigned int align;
@@ -4262,128 +4317,6 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
/* Given a pointer value OP0, return a simplified version of an
indirection through OP0, or NULL_TREE if no simplification is
- possible. Note that the resulting type may be different from
- the type pointed to in the sense that it is still compatible
- from the langhooks point of view. */
-
-tree
-gimple_fold_indirect_ref (tree t)
-{
- tree ptype = TREE_TYPE (t), type = TREE_TYPE (ptype);
- tree sub = t;
- tree subtype;
-
- STRIP_NOPS (sub);
- subtype = TREE_TYPE (sub);
- if (!POINTER_TYPE_P (subtype))
- return NULL_TREE;
-
- if (TREE_CODE (sub) == ADDR_EXPR)
- {
- tree op = TREE_OPERAND (sub, 0);
- tree optype = TREE_TYPE (op);
- /* *&p => p */
- if (useless_type_conversion_p (type, optype))
- return op;
-
- /* *(foo *)&fooarray => fooarray[0] */
- if (TREE_CODE (optype) == ARRAY_TYPE
- && TREE_CODE (TYPE_SIZE (TREE_TYPE (optype))) == INTEGER_CST
- && useless_type_conversion_p (type, TREE_TYPE (optype)))
- {
- tree type_domain = TYPE_DOMAIN (optype);
- tree min_val = size_zero_node;
- if (type_domain && TYPE_MIN_VALUE (type_domain))
- min_val = TYPE_MIN_VALUE (type_domain);
- if (TREE_CODE (min_val) == INTEGER_CST)
- return build4 (ARRAY_REF, type, op, min_val, NULL_TREE, NULL_TREE);
- }
- /* *(foo *)&complexfoo => __real__ complexfoo */
- else if (TREE_CODE (optype) == COMPLEX_TYPE
- && useless_type_conversion_p (type, TREE_TYPE (optype)))
- return fold_build1 (REALPART_EXPR, type, op);
- /* *(foo *)&vectorfoo => BIT_FIELD_REF<vectorfoo,...> */
- else if (TREE_CODE (optype) == VECTOR_TYPE
- && useless_type_conversion_p (type, TREE_TYPE (optype)))
- {
- tree part_width = TYPE_SIZE (type);
- tree index = bitsize_int (0);
- return fold_build3 (BIT_FIELD_REF, type, op, part_width, index);
- }
- }
-
- /* *(p + CST) -> ... */
- if (TREE_CODE (sub) == POINTER_PLUS_EXPR
- && TREE_CODE (TREE_OPERAND (sub, 1)) == INTEGER_CST)
- {
- tree addr = TREE_OPERAND (sub, 0);
- tree off = TREE_OPERAND (sub, 1);
- tree addrtype;
-
- STRIP_NOPS (addr);
- addrtype = TREE_TYPE (addr);
-
- /* ((foo*)&vectorfoo)[1] -> BIT_FIELD_REF<vectorfoo,...> */
- if (TREE_CODE (addr) == ADDR_EXPR
- && TREE_CODE (TREE_TYPE (addrtype)) == VECTOR_TYPE
- && useless_type_conversion_p (type, TREE_TYPE (TREE_TYPE (addrtype)))
- && host_integerp (off, 1))
- {
- unsigned HOST_WIDE_INT offset = tree_low_cst (off, 1);
- tree part_width = TYPE_SIZE (type);
- unsigned HOST_WIDE_INT part_widthi
- = tree_low_cst (part_width, 0) / BITS_PER_UNIT;
- unsigned HOST_WIDE_INT indexi = offset * BITS_PER_UNIT;
- tree index = bitsize_int (indexi);
- if (offset / part_widthi
- <= TYPE_VECTOR_SUBPARTS (TREE_TYPE (addrtype)))
- return fold_build3 (BIT_FIELD_REF, type, TREE_OPERAND (addr, 0),
- part_width, index);
- }
-
- /* ((foo*)&complexfoo)[1] -> __imag__ complexfoo */
- if (TREE_CODE (addr) == ADDR_EXPR
- && TREE_CODE (TREE_TYPE (addrtype)) == COMPLEX_TYPE
- && useless_type_conversion_p (type, TREE_TYPE (TREE_TYPE (addrtype))))
- {
- tree size = TYPE_SIZE_UNIT (type);
- if (tree_int_cst_equal (size, off))
- return fold_build1 (IMAGPART_EXPR, type, TREE_OPERAND (addr, 0));
- }
-
- /* *(p + CST) -> MEM_REF <p, CST>. */
- if (TREE_CODE (addr) != ADDR_EXPR
- || DECL_P (TREE_OPERAND (addr, 0)))
- return fold_build2 (MEM_REF, type,
- addr,
- build_int_cst_wide (ptype,
- TREE_INT_CST_LOW (off),
- TREE_INT_CST_HIGH (off)));
- }
-
- /* *(foo *)fooarrptr => (*fooarrptr)[0] */
- if (TREE_CODE (TREE_TYPE (subtype)) == ARRAY_TYPE
- && TREE_CODE (TYPE_SIZE (TREE_TYPE (TREE_TYPE (subtype)))) == INTEGER_CST
- && useless_type_conversion_p (type, TREE_TYPE (TREE_TYPE (subtype))))
- {
- tree type_domain;
- tree min_val = size_zero_node;
- tree osub = sub;
- sub = gimple_fold_indirect_ref (sub);
- if (! sub)
- sub = build1 (INDIRECT_REF, TREE_TYPE (subtype), osub);
- type_domain = TYPE_DOMAIN (TREE_TYPE (sub));
- if (type_domain && TYPE_MIN_VALUE (type_domain))
- min_val = TYPE_MIN_VALUE (type_domain);
- if (TREE_CODE (min_val) == INTEGER_CST)
- return build4 (ARRAY_REF, type, sub, min_val, NULL_TREE, NULL_TREE);
- }
-
- return NULL_TREE;
-}
-
-/* Given a pointer value OP0, return a simplified version of an
- indirection through OP0, or NULL_TREE if no simplification is
possible. This may only be applied to a rhs of an expression.
Note that the resulting type may be different from the type pointed
to in the sense that it is still compatible from the langhooks
@@ -4710,10 +4643,12 @@ is_gimple_stmt (tree t)
case OMP_PARALLEL:
case OMP_FOR:
case OMP_SIMD:
+ case OMP_DISTRIBUTE:
case OMP_SECTIONS:
case OMP_SECTION:
case OMP_SINGLE:
case OMP_MASTER:
+ case OMP_TASKGROUP:
case OMP_ORDERED:
case OMP_CRITICAL:
case OMP_TASK:
@@ -4803,6 +4738,12 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
gcc_assert (TREE_CODE (*expr_p) == MODIFY_EXPR
|| TREE_CODE (*expr_p) == INIT_EXPR);
+
+ if (fn_contains_cilk_spawn_p (cfun)
+ && lang_hooks.cilkplus.cilk_detect_spawn_and_unwrap (expr_p)
+ && !seen_error ())
+ return (enum gimplify_status)
+ lang_hooks.cilkplus.gimplify_cilk_spawn (expr_p, pre_p, post_p);
/* Trying to simplify a clobber using normal logic doesn't work,
so handle it here. */
@@ -4954,7 +4895,14 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
gimplify_seq_add_stmt (pre_p, assign);
gsi = gsi_last (*pre_p);
- fold_stmt (&gsi);
+ /* Don't fold stmts inside of target construct. We'll do it
+ during omplower pass instead. */
+ struct gimplify_omp_ctx *ctx;
+ for (ctx = gimplify_omp_ctxp; ctx; ctx = ctx->outer_context)
+ if (ctx->region_type == ORT_TARGET)
+ break;
+ if (ctx == NULL)
+ fold_stmt (&gsi);
if (want_value)
{
@@ -5419,11 +5367,21 @@ gimplify_asm_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
vec_safe_push (inputs, link);
}
- for (link = ASM_CLOBBERS (expr); link; ++i, link = TREE_CHAIN (link))
- vec_safe_push (clobbers, link);
+ link_next = NULL_TREE;
+ for (link = ASM_CLOBBERS (expr); link; ++i, link = link_next)
+ {
+ link_next = TREE_CHAIN (link);
+ TREE_CHAIN (link) = NULL_TREE;
+ vec_safe_push (clobbers, link);
+ }
- for (link = ASM_LABELS (expr); link; ++i, link = TREE_CHAIN (link))
- vec_safe_push (labels, link);
+ link_next = NULL_TREE;
+ for (link = ASM_LABELS (expr); link; ++i, link = link_next)
+ {
+ link_next = TREE_CHAIN (link);
+ TREE_CHAIN (link) = NULL_TREE;
+ vec_safe_push (labels, link);
+ }
/* Do not add ASMs with errors to the gimple IL stream. */
if (ret != GS_ERROR)
@@ -5719,11 +5677,16 @@ omp_firstprivatize_variable (struct gimplify_omp_ctx *ctx, tree decl)
{
if (n->value & GOVD_SHARED)
n->value = GOVD_FIRSTPRIVATE | (n->value & GOVD_SEEN);
+ else if (n->value & GOVD_MAP)
+ n->value |= GOVD_MAP_TO_ONLY;
else
return;
}
+ else if (ctx->region_type == ORT_TARGET)
+ omp_add_variable (ctx, decl, GOVD_MAP | GOVD_MAP_TO_ONLY);
else if (ctx->region_type != ORT_WORKSHARE
- && ctx->region_type != ORT_SIMD)
+ && ctx->region_type != ORT_SIMD
+ && ctx->region_type != ORT_TARGET_DATA)
omp_add_variable (ctx, decl, GOVD_FIRSTPRIVATE);
ctx = ctx->outer_context;
@@ -5806,7 +5769,7 @@ omp_add_variable (struct gimplify_omp_ctx *ctx, tree decl, unsigned int flags)
flags |= GOVD_SEEN;
n = splay_tree_lookup (ctx->variables, (splay_tree_key)decl);
- if (n != NULL)
+ if (n != NULL && n->value != GOVD_ALIGNED)
{
/* We shouldn't be re-adding the decl with the same data
sharing class. */
@@ -5832,7 +5795,9 @@ omp_add_variable (struct gimplify_omp_ctx *ctx, tree decl, unsigned int flags)
copy into or out of the context. */
if (!(flags & GOVD_LOCAL))
{
- nflags = flags & GOVD_PRIVATE ? GOVD_PRIVATE : GOVD_FIRSTPRIVATE;
+ nflags = flags & GOVD_MAP
+ ? GOVD_MAP | GOVD_MAP_TO_ONLY | GOVD_EXPLICIT
+ : flags & GOVD_PRIVATE ? GOVD_PRIVATE : GOVD_FIRSTPRIVATE;
nflags |= flags & GOVD_SEEN;
t = DECL_VALUE_EXPR (decl);
gcc_assert (TREE_CODE (t) == INDIRECT_REF);
@@ -5861,13 +5826,13 @@ omp_add_variable (struct gimplify_omp_ctx *ctx, tree decl, unsigned int flags)
For local variables TYPE_SIZE_UNIT might not be gimplified yet,
in this case omp_notice_variable will be called later
on when it is gimplified. */
- else if (! (flags & GOVD_LOCAL)
+ else if (! (flags & (GOVD_LOCAL | GOVD_MAP))
&& DECL_P (TYPE_SIZE_UNIT (TREE_TYPE (decl))))
omp_notice_variable (ctx, TYPE_SIZE_UNIT (TREE_TYPE (decl)), true);
}
- else if (lang_hooks.decls.omp_privatize_by_reference (decl))
+ else if ((flags & (GOVD_MAP | GOVD_LOCAL)) == 0
+ && lang_hooks.decls.omp_privatize_by_reference (decl))
{
- gcc_assert ((flags & GOVD_LOCAL) == 0);
omp_firstprivatize_type_sizes (ctx, TREE_TYPE (decl));
/* Similar to the direct variable sized case above, we'll need the
@@ -5896,6 +5861,22 @@ omp_notice_threadprivate_variable (struct gimplify_omp_ctx *ctx, tree decl,
tree decl2)
{
splay_tree_node n;
+ struct gimplify_omp_ctx *octx;
+
+ for (octx = ctx; octx; octx = octx->outer_context)
+ if (octx->region_type == ORT_TARGET)
+ {
+ n = splay_tree_lookup (octx->variables, (splay_tree_key)decl);
+ if (n == NULL)
+ {
+ error ("threadprivate variable %qE used in target region",
+ DECL_NAME (decl));
+ error_at (octx->location, "enclosing target region");
+ splay_tree_insert (octx->variables, (splay_tree_key)decl, 0);
+ }
+ if (decl2)
+ splay_tree_insert (octx->variables, (splay_tree_key)decl2, 0);
+ }
if (ctx->region_type != ORT_UNTIED_TASK)
return false;
@@ -5944,13 +5925,33 @@ omp_notice_variable (struct gimplify_omp_ctx *ctx, tree decl, bool in_code)
}
n = splay_tree_lookup (ctx->variables, (splay_tree_key)decl);
+ if (ctx->region_type == ORT_TARGET)
+ {
+ if (n == NULL)
+ {
+ if (!lang_hooks.types.omp_mappable_type (TREE_TYPE (decl)))
+ {
+ error ("%qD referenced in target region does not have "
+ "a mappable type", decl);
+ omp_add_variable (ctx, decl, GOVD_MAP | GOVD_EXPLICIT | flags);
+ }
+ else
+ omp_add_variable (ctx, decl, GOVD_MAP | flags);
+ }
+ else
+ n->value |= flags;
+ ret = lang_hooks.decls.omp_disregard_value_expr (decl, true);
+ goto do_outer;
+ }
+
if (n == NULL)
{
enum omp_clause_default_kind default_kind, kind;
struct gimplify_omp_ctx *octx;
if (ctx->region_type == ORT_WORKSHARE
- || ctx->region_type == ORT_SIMD)
+ || ctx->region_type == ORT_SIMD
+ || ctx->region_type == ORT_TARGET_DATA)
goto do_outer;
/* ??? Some compiler-generated variables (like SAVE_EXPRs) could be
@@ -5964,12 +5965,24 @@ omp_notice_variable (struct gimplify_omp_ctx *ctx, tree decl, bool in_code)
switch (default_kind)
{
case OMP_CLAUSE_DEFAULT_NONE:
- error ("%qE not specified in enclosing parallel",
- DECL_NAME (lang_hooks.decls.omp_report_decl (decl)));
if ((ctx->region_type & ORT_TASK) != 0)
- error_at (ctx->location, "enclosing task");
+ {
+ error ("%qE not specified in enclosing task",
+ DECL_NAME (lang_hooks.decls.omp_report_decl (decl)));
+ error_at (ctx->location, "enclosing task");
+ }
+ else if (ctx->region_type == ORT_TEAMS)
+ {
+ error ("%qE not specified in enclosing teams construct",
+ DECL_NAME (lang_hooks.decls.omp_report_decl (decl)));
+ error_at (ctx->location, "enclosing teams construct");
+ }
else
- error_at (ctx->location, "enclosing parallel");
+ {
+ error ("%qE not specified in enclosing parallel",
+ DECL_NAME (lang_hooks.decls.omp_report_decl (decl)));
+ error_at (ctx->location, "enclosing parallel");
+ }
/* FALLTHRU */
case OMP_CLAUSE_DEFAULT_SHARED:
flags |= GOVD_SHARED;
@@ -5989,13 +6002,15 @@ omp_notice_variable (struct gimplify_omp_ctx *ctx, tree decl, bool in_code)
{
splay_tree_node n2;
+ if ((octx->region_type & (ORT_TARGET_DATA | ORT_TARGET)) != 0)
+ continue;
n2 = splay_tree_lookup (octx->variables, (splay_tree_key) decl);
if (n2 && (n2->value & GOVD_DATA_SHARE_CLASS) != GOVD_SHARED)
{
flags |= GOVD_FIRSTPRIVATE;
break;
}
- if ((octx->region_type & ORT_PARALLEL) != 0)
+ if ((octx->region_type & (ORT_PARALLEL | ORT_TEAMS)) != 0)
break;
}
if (flags & GOVD_FIRSTPRIVATE)
@@ -6137,6 +6152,9 @@ omp_check_private (struct gimplify_omp_ctx *ctx, tree decl)
/* References might be private, but might be shared too. */
|| lang_hooks.decls.omp_privatize_by_reference (decl));
+ if ((ctx->region_type & (ORT_TARGET | ORT_TARGET_DATA)) != 0)
+ continue;
+
n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
if (n != NULL)
return (n->value & GOVD_SHARED) == 0;
@@ -6195,15 +6213,87 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
flags = GOVD_REDUCTION | GOVD_SEEN | GOVD_EXPLICIT;
check_non_private = "reduction";
goto do_add;
- case OMP_CLAUSE_LINEAR:
- if (gimplify_expr (&OMP_CLAUSE_LINEAR_STEP (c), pre_p, NULL,
- is_gimple_val, fb_rvalue) == GS_ERROR)
- {
- remove = true;
- break;
- }
- flags = GOVD_LINEAR | GOVD_EXPLICIT;
- goto do_add;
+ case OMP_CLAUSE_LINEAR:
+ if (gimplify_expr (&OMP_CLAUSE_LINEAR_STEP (c), pre_p, NULL,
+ is_gimple_val, fb_rvalue) == GS_ERROR)
+ {
+ remove = true;
+ break;
+ }
+ flags = GOVD_LINEAR | GOVD_EXPLICIT;
+ goto do_add;
+
+ case OMP_CLAUSE_MAP:
+ if (OMP_CLAUSE_SIZE (c)
+ && gimplify_expr (&OMP_CLAUSE_SIZE (c), pre_p,
+ NULL, is_gimple_val, fb_rvalue) == GS_ERROR)
+ {
+ remove = true;
+ break;
+ }
+ decl = OMP_CLAUSE_DECL (c);
+ if (!DECL_P (decl))
+ {
+ if (gimplify_expr (&OMP_CLAUSE_DECL (c), pre_p,
+ NULL, is_gimple_lvalue, fb_lvalue)
+ == GS_ERROR)
+ {
+ remove = true;
+ break;
+ }
+ break;
+ }
+ flags = GOVD_MAP | GOVD_EXPLICIT;
+ goto do_add;
+
+ case OMP_CLAUSE_DEPEND:
+ if (TREE_CODE (OMP_CLAUSE_DECL (c)) == COMPOUND_EXPR)
+ {
+ gimplify_expr (&TREE_OPERAND (OMP_CLAUSE_DECL (c), 0), pre_p,
+ NULL, is_gimple_val, fb_rvalue);
+ OMP_CLAUSE_DECL (c) = TREE_OPERAND (OMP_CLAUSE_DECL (c), 1);
+ }
+ if (error_operand_p (OMP_CLAUSE_DECL (c)))
+ {
+ remove = true;
+ break;
+ }
+ OMP_CLAUSE_DECL (c) = build_fold_addr_expr (OMP_CLAUSE_DECL (c));
+ if (gimplify_expr (&OMP_CLAUSE_DECL (c), pre_p, NULL,
+ is_gimple_val, fb_rvalue) == GS_ERROR)
+ {
+ remove = true;
+ break;
+ }
+ break;
+
+ case OMP_CLAUSE_TO:
+ case OMP_CLAUSE_FROM:
+ if (OMP_CLAUSE_SIZE (c)
+ && gimplify_expr (&OMP_CLAUSE_SIZE (c), pre_p,
+ NULL, is_gimple_val, fb_rvalue) == GS_ERROR)
+ {
+ remove = true;
+ break;
+ }
+ decl = OMP_CLAUSE_DECL (c);
+ if (error_operand_p (decl))
+ {
+ remove = true;
+ break;
+ }
+ if (!DECL_P (decl))
+ {
+ if (gimplify_expr (&OMP_CLAUSE_DECL (c), pre_p,
+ NULL, is_gimple_lvalue, fb_lvalue)
+ == GS_ERROR)
+ {
+ remove = true;
+ break;
+ }
+ break;
+ }
+ goto do_notice;
do_add:
decl = OMP_CLAUSE_DECL (c);
@@ -6292,9 +6382,13 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
case OMP_CLAUSE_SCHEDULE:
case OMP_CLAUSE_NUM_THREADS:
+ case OMP_CLAUSE_NUM_TEAMS:
+ case OMP_CLAUSE_THREAD_LIMIT:
+ case OMP_CLAUSE_DIST_SCHEDULE:
+ case OMP_CLAUSE_DEVICE:
if (gimplify_expr (&OMP_CLAUSE_OPERAND (c, 0), pre_p, NULL,
is_gimple_val, fb_rvalue) == GS_ERROR)
- remove = true;
+ remove = true;
break;
case OMP_CLAUSE_NOWAIT:
@@ -6302,9 +6396,22 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
case OMP_CLAUSE_UNTIED:
case OMP_CLAUSE_COLLAPSE:
case OMP_CLAUSE_MERGEABLE:
+ case OMP_CLAUSE_PROC_BIND:
case OMP_CLAUSE_SAFELEN:
break;
+ case OMP_CLAUSE_ALIGNED:
+ decl = OMP_CLAUSE_DECL (c);
+ if (error_operand_p (decl))
+ {
+ remove = true;
+ break;
+ }
+ if (!is_global_var (decl)
+ && TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE)
+ omp_add_variable (ctx, decl, GOVD_ALIGNED);
+ break;
+
case OMP_CLAUSE_DEFAULT:
ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
break;
@@ -6344,12 +6451,16 @@ gimplify_adjust_omp_clauses_1 (splay_tree_node n, void *data)
gcc_assert ((flags & GOVD_DATA_SHARE_CLASS) == GOVD_PRIVATE);
private_debug = true;
}
+ else if (flags & GOVD_MAP)
+ private_debug = false;
else
private_debug
= lang_hooks.decls.omp_private_debug_clause (decl,
!!(flags & GOVD_SHARED));
if (private_debug)
code = OMP_CLAUSE_PRIVATE;
+ else if (flags & GOVD_MAP)
+ code = OMP_CLAUSE_MAP;
else if (flags & GOVD_SHARED)
{
if (is_global_var (decl))
@@ -6376,6 +6487,8 @@ gimplify_adjust_omp_clauses_1 (splay_tree_node n, void *data)
code = OMP_CLAUSE_FIRSTPRIVATE;
else if (flags & GOVD_LASTPRIVATE)
code = OMP_CLAUSE_LASTPRIVATE;
+ else if (flags & GOVD_ALIGNED)
+ return 0;
else
gcc_unreachable ();
@@ -6386,6 +6499,36 @@ gimplify_adjust_omp_clauses_1 (splay_tree_node n, void *data)
OMP_CLAUSE_PRIVATE_DEBUG (clause) = 1;
else if (code == OMP_CLAUSE_PRIVATE && (flags & GOVD_PRIVATE_OUTER_REF))
OMP_CLAUSE_PRIVATE_OUTER_REF (clause) = 1;
+ else if (code == OMP_CLAUSE_MAP)
+ {
+ OMP_CLAUSE_MAP_KIND (clause) = flags & GOVD_MAP_TO_ONLY
+ ? OMP_CLAUSE_MAP_TO
+ : OMP_CLAUSE_MAP_TOFROM;
+ if (DECL_SIZE (decl)
+ && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
+ {
+ tree decl2 = DECL_VALUE_EXPR (decl);
+ gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
+ decl2 = TREE_OPERAND (decl2, 0);
+ gcc_assert (DECL_P (decl2));
+ tree mem = build_simple_mem_ref (decl2);
+ OMP_CLAUSE_DECL (clause) = mem;
+ OMP_CLAUSE_SIZE (clause) = TYPE_SIZE_UNIT (TREE_TYPE (decl));
+ if (gimplify_omp_ctxp->outer_context)
+ {
+ struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp->outer_context;
+ omp_notice_variable (ctx, decl2, true);
+ omp_notice_variable (ctx, OMP_CLAUSE_SIZE (clause), true);
+ }
+ tree nc = build_omp_clause (OMP_CLAUSE_LOCATION (clause),
+ OMP_CLAUSE_MAP);
+ OMP_CLAUSE_DECL (nc) = decl;
+ OMP_CLAUSE_SIZE (nc) = size_zero_node;
+ OMP_CLAUSE_MAP_KIND (nc) = OMP_CLAUSE_MAP_POINTER;
+ OMP_CLAUSE_CHAIN (nc) = OMP_CLAUSE_CHAIN (clause);
+ OMP_CLAUSE_CHAIN (clause) = nc;
+ }
+ }
*list_p = clause;
lang_hooks.decls.omp_finish_clause (clause);
@@ -6461,11 +6604,116 @@ gimplify_adjust_omp_clauses (tree *list_p)
= (n->value & GOVD_FIRSTPRIVATE) != 0;
break;
+ case OMP_CLAUSE_ALIGNED:
+ decl = OMP_CLAUSE_DECL (c);
+ if (!is_global_var (decl))
+ {
+ n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
+ remove = n == NULL || !(n->value & GOVD_SEEN);
+ if (!remove && TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE)
+ {
+ struct gimplify_omp_ctx *octx;
+ if (n != NULL
+ && (n->value & (GOVD_DATA_SHARE_CLASS
+ & ~GOVD_FIRSTPRIVATE)))
+ remove = true;
+ else
+ for (octx = ctx->outer_context; octx;
+ octx = octx->outer_context)
+ {
+ n = splay_tree_lookup (octx->variables,
+ (splay_tree_key) decl);
+ if (n == NULL)
+ continue;
+ if (n->value & GOVD_LOCAL)
+ break;
+ /* We have to avoid assigning a shared variable
+ to itself when trying to add
+ __builtin_assume_aligned. */
+ if (n->value & GOVD_SHARED)
+ {
+ remove = true;
+ break;
+ }
+ }
+ }
+ }
+ else if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
+ {
+ n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
+ if (n != NULL && (n->value & GOVD_DATA_SHARE_CLASS) != 0)
+ remove = true;
+ }
+ break;
+
+ case OMP_CLAUSE_MAP:
+ decl = OMP_CLAUSE_DECL (c);
+ if (!DECL_P (decl))
+ break;
+ n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
+ if (ctx->region_type == ORT_TARGET && !(n->value & GOVD_SEEN))
+ remove = true;
+ else if (DECL_SIZE (decl)
+ && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST
+ && OMP_CLAUSE_MAP_KIND (c) != OMP_CLAUSE_MAP_POINTER)
+ {
+ tree decl2 = DECL_VALUE_EXPR (decl);
+ gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
+ decl2 = TREE_OPERAND (decl2, 0);
+ gcc_assert (DECL_P (decl2));
+ tree mem = build_simple_mem_ref (decl2);
+ OMP_CLAUSE_DECL (c) = mem;
+ OMP_CLAUSE_SIZE (c) = TYPE_SIZE_UNIT (TREE_TYPE (decl));
+ if (ctx->outer_context)
+ {
+ omp_notice_variable (ctx->outer_context, decl2, true);
+ omp_notice_variable (ctx->outer_context,
+ OMP_CLAUSE_SIZE (c), true);
+ }
+ tree nc = build_omp_clause (OMP_CLAUSE_LOCATION (c),
+ OMP_CLAUSE_MAP);
+ OMP_CLAUSE_DECL (nc) = decl;
+ OMP_CLAUSE_SIZE (nc) = size_zero_node;
+ OMP_CLAUSE_MAP_KIND (nc) = OMP_CLAUSE_MAP_POINTER;
+ OMP_CLAUSE_CHAIN (nc) = OMP_CLAUSE_CHAIN (c);
+ OMP_CLAUSE_CHAIN (c) = nc;
+ c = nc;
+ }
+ break;
+
+ case OMP_CLAUSE_TO:
+ case OMP_CLAUSE_FROM:
+ decl = OMP_CLAUSE_DECL (c);
+ if (!DECL_P (decl))
+ break;
+ if (DECL_SIZE (decl)
+ && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
+ {
+ tree decl2 = DECL_VALUE_EXPR (decl);
+ gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
+ decl2 = TREE_OPERAND (decl2, 0);
+ gcc_assert (DECL_P (decl2));
+ tree mem = build_simple_mem_ref (decl2);
+ OMP_CLAUSE_DECL (c) = mem;
+ OMP_CLAUSE_SIZE (c) = TYPE_SIZE_UNIT (TREE_TYPE (decl));
+ if (ctx->outer_context)
+ {
+ omp_notice_variable (ctx->outer_context, decl2, true);
+ omp_notice_variable (ctx->outer_context,
+ OMP_CLAUSE_SIZE (c), true);
+ }
+ }
+ break;
+
case OMP_CLAUSE_REDUCTION:
case OMP_CLAUSE_COPYIN:
case OMP_CLAUSE_COPYPRIVATE:
case OMP_CLAUSE_IF:
case OMP_CLAUSE_NUM_THREADS:
+ case OMP_CLAUSE_NUM_TEAMS:
+ case OMP_CLAUSE_THREAD_LIMIT:
+ case OMP_CLAUSE_DIST_SCHEDULE:
+ case OMP_CLAUSE_DEVICE:
case OMP_CLAUSE_SCHEDULE:
case OMP_CLAUSE_NOWAIT:
case OMP_CLAUSE_ORDERED:
@@ -6474,7 +6722,9 @@ gimplify_adjust_omp_clauses (tree *list_p)
case OMP_CLAUSE_COLLAPSE:
case OMP_CLAUSE_FINAL:
case OMP_CLAUSE_MERGEABLE:
+ case OMP_CLAUSE_PROC_BIND:
case OMP_CLAUSE_SAFELEN:
+ case OMP_CLAUSE_DEPEND:
break;
default:
@@ -6567,12 +6817,39 @@ gimplify_omp_task (tree *expr_p, gimple_seq *pre_p)
*expr_p = NULL_TREE;
}
+/* Helper function of gimplify_omp_for, find OMP_FOR resp. OMP_SIMD
+ with non-NULL OMP_FOR_INIT. */
+
+static tree
+find_combined_omp_for (tree *tp, int *walk_subtrees, void *)
+{
+ *walk_subtrees = 0;
+ switch (TREE_CODE (*tp))
+ {
+ case OMP_FOR:
+ *walk_subtrees = 1;
+ /* FALLTHRU */
+ case OMP_SIMD:
+ if (OMP_FOR_INIT (*tp) != NULL_TREE)
+ return *tp;
+ break;
+ case BIND_EXPR:
+ case STATEMENT_LIST:
+ case OMP_PARALLEL:
+ *walk_subtrees = 1;
+ break;
+ default:
+ break;
+ }
+ return NULL_TREE;
+}
+
/* Gimplify the gross structure of an OMP_FOR statement. */
static enum gimplify_status
gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
{
- tree for_stmt, decl, var, t;
+ tree for_stmt, orig_for_stmt, decl, var, t;
enum gimplify_status ret = GS_ALL_DONE;
enum gimplify_status tret;
gimple gfor;
@@ -6581,9 +6858,9 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
bool simd;
bitmap has_decl_expr = NULL;
- for_stmt = *expr_p;
+ orig_for_stmt = for_stmt = *expr_p;
- simd = TREE_CODE (for_stmt) == OMP_SIMD;
+ simd = TREE_CODE (for_stmt) == OMP_SIMD;
gimplify_scan_omp_clauses (&OMP_FOR_CLAUSES (for_stmt), pre_p,
simd ? ORT_SIMD : ORT_WORKSHARE);
@@ -6594,7 +6871,7 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
has_decl_expr = BITMAP_ALLOC (NULL);
if (TREE_CODE (OMP_FOR_PRE_BODY (for_stmt)) == DECL_EXPR
&& TREE_CODE (DECL_EXPR_DECL (OMP_FOR_PRE_BODY (for_stmt)))
- == VAR_DECL)
+ == VAR_DECL)
{
t = OMP_FOR_PRE_BODY (for_stmt);
bitmap_set_bit (has_decl_expr, DECL_UID (DECL_EXPR_DECL (t)));
@@ -6615,6 +6892,14 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
gimplify_and_add (OMP_FOR_PRE_BODY (for_stmt), &for_pre_body);
OMP_FOR_PRE_BODY (for_stmt) = NULL_TREE;
+ if (OMP_FOR_INIT (for_stmt) == NULL_TREE)
+ {
+ for_stmt = walk_tree (&OMP_FOR_BODY (for_stmt), find_combined_omp_for,
+ NULL, NULL);
+ gcc_assert (for_stmt != NULL_TREE);
+ gimplify_omp_ctxp->combined_loop = true;
+ }
+
for_body = NULL;
gcc_assert (TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt))
== TREE_VEC_LENGTH (OMP_FOR_COND (for_stmt)));
@@ -6631,7 +6916,9 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
/* Make sure the iteration variable is private. */
tree c = NULL_TREE;
- if (simd)
+ if (orig_for_stmt != for_stmt)
+ /* Do this only on innermost construct for combined ones. */;
+ else if (simd)
{
splay_tree_node n = splay_tree_lookup (gimplify_omp_ctxp->variables,
(splay_tree_key)decl);
@@ -6675,7 +6962,9 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
/* If DECL is not a gimple register, create a temporary variable to act
as an iteration counter. This is valid, since DECL cannot be
modified in the body of the loop. */
- if (!is_gimple_reg (decl))
+ if (orig_for_stmt != for_stmt)
+ var = decl;
+ else if (!is_gimple_reg (decl))
{
var = create_tmp_var (TREE_TYPE (decl), get_name (decl));
TREE_OPERAND (t, 0) = var;
@@ -6708,6 +6997,8 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
{
case PREINCREMENT_EXPR:
case POSTINCREMENT_EXPR:
+ if (orig_for_stmt != for_stmt)
+ break;
t = build_int_cst (TREE_TYPE (decl), 1);
if (c)
OMP_CLAUSE_LINEAR_STEP (c) = t;
@@ -6718,6 +7009,8 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
case PREDECREMENT_EXPR:
case POSTDECREMENT_EXPR:
+ if (orig_for_stmt != for_stmt)
+ break;
t = build_int_cst (TREE_TYPE (decl), -1);
if (c)
OMP_CLAUSE_LINEAR_STEP (c) = t;
@@ -6774,9 +7067,9 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
gcc_unreachable ();
}
- if (var != decl || TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) > 1)
+ if ((var != decl || TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) > 1)
+ && orig_for_stmt == for_stmt)
{
- tree c;
for (c = OMP_FOR_CLAUSES (for_stmt); c ; c = OMP_CLAUSE_CHAIN (c))
if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
&& OMP_CLAUSE_DECL (c) == decl
@@ -6800,21 +7093,49 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
BITMAP_FREE (has_decl_expr);
- gimplify_and_add (OMP_FOR_BODY (for_stmt), &for_body);
+ gimplify_and_add (OMP_FOR_BODY (orig_for_stmt), &for_body);
- gimplify_adjust_omp_clauses (&OMP_FOR_CLAUSES (for_stmt));
+ if (orig_for_stmt != for_stmt)
+ for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++)
+ {
+ t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i);
+ decl = TREE_OPERAND (t, 0);
+ var = create_tmp_var (TREE_TYPE (decl), get_name (decl));
+ omp_add_variable (gimplify_omp_ctxp, var, GOVD_PRIVATE | GOVD_SEEN);
+ TREE_OPERAND (t, 0) = var;
+ t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i);
+ TREE_OPERAND (t, 1) = copy_node (TREE_OPERAND (t, 1));
+ TREE_OPERAND (TREE_OPERAND (t, 1), 0) = var;
+ }
+
+ gimplify_adjust_omp_clauses (&OMP_FOR_CLAUSES (orig_for_stmt));
int kind;
- switch (TREE_CODE (for_stmt))
+ switch (TREE_CODE (orig_for_stmt))
{
case OMP_FOR: kind = GF_OMP_FOR_KIND_FOR; break;
case OMP_SIMD: kind = GF_OMP_FOR_KIND_SIMD; break;
+ case OMP_DISTRIBUTE: kind = GF_OMP_FOR_KIND_DISTRIBUTE; break;
default:
gcc_unreachable ();
}
- gfor = gimple_build_omp_for (for_body, kind, OMP_FOR_CLAUSES (for_stmt),
+ gfor = gimple_build_omp_for (for_body, kind, OMP_FOR_CLAUSES (orig_for_stmt),
TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)),
for_pre_body);
+ if (orig_for_stmt != for_stmt)
+ gimple_omp_for_set_combined_p (gfor, true);
+ if (gimplify_omp_ctxp
+ && (gimplify_omp_ctxp->combined_loop
+ || (gimplify_omp_ctxp->region_type == ORT_COMBINED_PARALLEL
+ && gimplify_omp_ctxp->outer_context
+ && gimplify_omp_ctxp->outer_context->combined_loop)))
+ {
+ gimple_omp_for_set_combined_into_p (gfor, true);
+ if (gimplify_omp_ctxp->combined_loop)
+ gcc_assert (TREE_CODE (orig_for_stmt) == OMP_SIMD);
+ else
+ gcc_assert (TREE_CODE (orig_for_stmt) == OMP_FOR);
+ }
for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++)
{
@@ -6835,8 +7156,9 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
return GS_ALL_DONE;
}
-/* Gimplify the gross structure of other OpenMP worksharing constructs.
- In particular, OMP_SECTIONS and OMP_SINGLE. */
+/* Gimplify the gross structure of other OpenMP constructs.
+ In particular, OMP_SECTIONS, OMP_SINGLE, OMP_TARGET, OMP_TARGET_DATA
+ and OMP_TEAMS. */
static void
gimplify_omp_workshare (tree *expr_p, gimple_seq *pre_p)
@@ -6844,19 +7166,93 @@ gimplify_omp_workshare (tree *expr_p, gimple_seq *pre_p)
tree expr = *expr_p;
gimple stmt;
gimple_seq body = NULL;
+ enum omp_region_type ort = ORT_WORKSHARE;
- gimplify_scan_omp_clauses (&OMP_CLAUSES (expr), pre_p, ORT_WORKSHARE);
- gimplify_and_add (OMP_BODY (expr), &body);
+ switch (TREE_CODE (expr))
+ {
+ case OMP_SECTIONS:
+ case OMP_SINGLE:
+ break;
+ case OMP_TARGET:
+ ort = ORT_TARGET;
+ break;
+ case OMP_TARGET_DATA:
+ ort = ORT_TARGET_DATA;
+ break;
+ case OMP_TEAMS:
+ ort = ORT_TEAMS;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ gimplify_scan_omp_clauses (&OMP_CLAUSES (expr), pre_p, ort);
+ if (ort == ORT_TARGET || ort == ORT_TARGET_DATA)
+ {
+ struct gimplify_ctx gctx;
+ push_gimplify_context (&gctx);
+ gimple g = gimplify_and_return_first (OMP_BODY (expr), &body);
+ if (gimple_code (g) == GIMPLE_BIND)
+ pop_gimplify_context (g);
+ else
+ pop_gimplify_context (NULL);
+ if (ort == ORT_TARGET_DATA)
+ {
+ gimple_seq cleanup = NULL;
+ tree fn = builtin_decl_explicit (BUILT_IN_GOMP_TARGET_END_DATA);
+ g = gimple_build_call (fn, 0);
+ gimple_seq_add_stmt (&cleanup, g);
+ g = gimple_build_try (body, cleanup, GIMPLE_TRY_FINALLY);
+ body = NULL;
+ gimple_seq_add_stmt (&body, g);
+ }
+ }
+ else
+ gimplify_and_add (OMP_BODY (expr), &body);
gimplify_adjust_omp_clauses (&OMP_CLAUSES (expr));
- if (TREE_CODE (expr) == OMP_SECTIONS)
- stmt = gimple_build_omp_sections (body, OMP_CLAUSES (expr));
- else if (TREE_CODE (expr) == OMP_SINGLE)
- stmt = gimple_build_omp_single (body, OMP_CLAUSES (expr));
- else
- gcc_unreachable ();
+ switch (TREE_CODE (expr))
+ {
+ case OMP_SECTIONS:
+ stmt = gimple_build_omp_sections (body, OMP_CLAUSES (expr));
+ break;
+ case OMP_SINGLE:
+ stmt = gimple_build_omp_single (body, OMP_CLAUSES (expr));
+ break;
+ case OMP_TARGET:
+ stmt = gimple_build_omp_target (body, GF_OMP_TARGET_KIND_REGION,
+ OMP_CLAUSES (expr));
+ break;
+ case OMP_TARGET_DATA:
+ stmt = gimple_build_omp_target (body, GF_OMP_TARGET_KIND_DATA,
+ OMP_CLAUSES (expr));
+ break;
+ case OMP_TEAMS:
+ stmt = gimple_build_omp_teams (body, OMP_CLAUSES (expr));
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ gimplify_seq_add_stmt (pre_p, stmt);
+ *expr_p = NULL_TREE;
+}
+
+/* Gimplify the gross structure of OpenMP target update construct. */
+
+static void
+gimplify_omp_target_update (tree *expr_p, gimple_seq *pre_p)
+{
+ tree expr = *expr_p;
+ gimple stmt;
+
+ gimplify_scan_omp_clauses (&OMP_TARGET_UPDATE_CLAUSES (expr), pre_p,
+ ORT_WORKSHARE);
+ gimplify_adjust_omp_clauses (&OMP_TARGET_UPDATE_CLAUSES (expr));
+ stmt = gimple_build_omp_target (NULL, GF_OMP_TARGET_KIND_UPDATE,
+ OMP_TARGET_UPDATE_CLAUSES (expr));
gimplify_seq_add_stmt (pre_p, stmt);
+ *expr_p = NULL_TREE;
}
/* A subroutine of gimplify_omp_atomic. The front end is supposed to have
@@ -6995,6 +7391,11 @@ gimplify_omp_atomic (tree *expr_p, gimple_seq *pre_p)
rhs = tmp_load;
storestmt = gimple_build_omp_atomic_store (rhs);
gimplify_seq_add_stmt (pre_p, storestmt);
+ if (OMP_ATOMIC_SEQ_CST (*expr_p))
+ {
+ gimple_omp_atomic_set_seq_cst (loadstmt);
+ gimple_omp_atomic_set_seq_cst (storestmt);
+ }
switch (TREE_CODE (*expr_p))
{
case OMP_ATOMIC_READ:
@@ -7011,7 +7412,7 @@ gimplify_omp_atomic (tree *expr_p, gimple_seq *pre_p)
break;
}
- return GS_ALL_DONE;
+ return GS_ALL_DONE;
}
/* Gimplify a TRANSACTION_EXPR. This involves gimplification of the
@@ -7289,6 +7690,19 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
}
break;
+ case CILK_SPAWN_STMT:
+ gcc_assert
+ (fn_contains_cilk_spawn_p (cfun)
+ && lang_hooks.cilkplus.cilk_detect_spawn_and_unwrap (expr_p));
+ if (!seen_error ())
+ {
+ ret = (enum gimplify_status)
+ lang_hooks.cilkplus.gimplify_cilk_spawn (expr_p, pre_p,
+ post_p);
+ break;
+ }
+ /* If errors are seen, then just process it as a CALL_EXPR. */
+
case CALL_EXPR:
ret = gimplify_call_expr (expr_p, pre_p, fallback != fb_none);
@@ -7368,6 +7782,21 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
ret = gimplify_addr_expr (expr_p, pre_p, post_p);
break;
+ case ANNOTATE_EXPR:
+ {
+ tree cond = TREE_OPERAND (*expr_p, 0);
+ tree id = TREE_OPERAND (*expr_p, 1);
+ tree tmp = create_tmp_var_raw (TREE_TYPE(cond), NULL);
+ gimplify_arg (&cond, pre_p, EXPR_LOCATION (*expr_p));
+ gimple call = gimple_build_call_internal (IFN_ANNOTATE, 2,
+ cond, id);
+ gimple_call_set_lhs (call, tmp);
+ gimplify_seq_add_stmt (pre_p, call);
+ *expr_p = tmp;
+ ret = GS_ALL_DONE;
+ break;
+ }
+
case VA_ARG_EXPR:
ret = gimplify_va_arg_expr (expr_p, pre_p, post_p);
break;
@@ -7468,6 +7897,10 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
case STRING_CST:
case COMPLEX_CST:
case VECTOR_CST:
+ /* Drop the overflow flag on constants, we do not want
+ that in the GIMPLE IL. */
+ if (TREE_OVERFLOW_P (*expr_p))
+ *expr_p = drop_tree_overflow (*expr_p);
ret = GS_ALL_DONE;
break;
@@ -7751,17 +8184,27 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
case OMP_FOR:
case OMP_SIMD:
+ case OMP_DISTRIBUTE:
ret = gimplify_omp_for (expr_p, pre_p);
break;
case OMP_SECTIONS:
case OMP_SINGLE:
+ case OMP_TARGET:
+ case OMP_TARGET_DATA:
+ case OMP_TEAMS:
gimplify_omp_workshare (expr_p, pre_p);
ret = GS_ALL_DONE;
break;
+ case OMP_TARGET_UPDATE:
+ gimplify_omp_target_update (expr_p, pre_p);
+ ret = GS_ALL_DONE;
+ break;
+
case OMP_SECTION:
case OMP_MASTER:
+ case OMP_TASKGROUP:
case OMP_ORDERED:
case OMP_CRITICAL:
{
@@ -7777,6 +8220,19 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
case OMP_MASTER:
g = gimple_build_omp_master (body);
break;
+ case OMP_TASKGROUP:
+ {
+ gimple_seq cleanup = NULL;
+ tree fn
+ = builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_END);
+ g = gimple_build_call (fn, 0);
+ gimple_seq_add_stmt (&cleanup, g);
+ g = gimple_build_try (body, cleanup, GIMPLE_TRY_FINALLY);
+ body = NULL;
+ gimple_seq_add_stmt (&body, g);
+ g = gimple_build_omp_taskgroup (body);
+ }
+ break;
case OMP_ORDERED:
g = gimple_build_omp_ordered (body);
break;
@@ -7886,6 +8342,22 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
break;
}
+ case CILK_SYNC_STMT:
+ {
+ if (!fn_contains_cilk_spawn_p (cfun))
+ {
+ error_at (EXPR_LOCATION (*expr_p),
+ "expected %<_Cilk_spawn%> before %<_Cilk_sync%>");
+ ret = GS_ERROR;
+ }
+ else
+ {
+ gimplify_cilk_sync (expr_p, pre_p);
+ ret = GS_ALL_DONE;
+ }
+ break;
+ }
+
default:
switch (TREE_CODE_CLASS (TREE_CODE (*expr_p)))
{
@@ -8109,6 +8581,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
&& code != OMP_CRITICAL
&& code != OMP_FOR
&& code != OMP_MASTER
+ && code != OMP_TASKGROUP
&& code != OMP_ORDERED
&& code != OMP_PARALLEL
&& code != OMP_SECTIONS
@@ -8333,6 +8806,13 @@ gimplify_body (tree fndecl, bool do_parms)
gcc_assert (gimplify_ctxp == NULL);
push_gimplify_context (&gctx);
+ if (flag_openmp)
+ {
+ gcc_assert (gimplify_omp_ctxp == NULL);
+ if (lookup_attribute ("omp declare target", DECL_ATTRIBUTES (fndecl)))
+ gimplify_omp_ctxp = new_omp_context (ORT_TARGET);
+ }
+
/* Unshare most shared trees in the body and in that of any nested functions.
It would seem we don't have to do this for nested functions because
they are supposed to be output and then the outer function gimplified
@@ -8395,6 +8875,12 @@ gimplify_body (tree fndecl, bool do_parms)
nonlocal_vlas = NULL;
}
+ if ((flag_openmp || flag_openmp_simd) && gimplify_omp_ctxp)
+ {
+ delete_omp_context (gimplify_omp_ctxp);
+ gimplify_omp_ctxp = NULL;
+ }
+
pop_gimplify_context (outer_bind);
gcc_assert (gimplify_ctxp == NULL);
@@ -8705,8 +9191,6 @@ gimple_regimplify_operands (gimple stmt, gimple_stmt_iterator *gsi_p)
temp = make_ssa_name (temp, NULL);
gimple_set_lhs (stmt, temp);
post_stmt = gimple_build_assign (lhs, temp);
- if (TREE_CODE (lhs) == SSA_NAME)
- SSA_NAME_DEF_STMT (lhs) = post_stmt;
}
}
break;
@@ -8832,5 +9316,107 @@ force_gimple_operand_gsi (gimple_stmt_iterator *gsi, tree expr,
var, before, m);
}
+/* Return a dummy expression of type TYPE in order to keep going after an
+ error. */
+
+static tree
+dummy_object (tree type)
+{
+ tree t = build_int_cst (build_pointer_type (type), 0);
+ return build2 (MEM_REF, type, t, t);
+}
+
+/* Gimplify __builtin_va_arg, aka VA_ARG_EXPR, which is not really a
+ builtin function, but a very special sort of operator. */
+
+enum gimplify_status
+gimplify_va_arg_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
+{
+ tree promoted_type, have_va_type;
+ tree valist = TREE_OPERAND (*expr_p, 0);
+ tree type = TREE_TYPE (*expr_p);
+ tree t;
+ location_t loc = EXPR_LOCATION (*expr_p);
+
+ /* Verify that valist is of the proper type. */
+ have_va_type = TREE_TYPE (valist);
+ if (have_va_type == error_mark_node)
+ return GS_ERROR;
+ have_va_type = targetm.canonical_va_list_type (have_va_type);
+
+ if (have_va_type == NULL_TREE)
+ {
+ error_at (loc, "first argument to %<va_arg%> not of type %<va_list%>");
+ return GS_ERROR;
+ }
+
+ /* Generate a diagnostic for requesting data of a type that cannot
+ be passed through `...' due to type promotion at the call site. */
+ if ((promoted_type = lang_hooks.types.type_promotes_to (type))
+ != type)
+ {
+ static bool gave_help;
+ bool warned;
+
+ /* Unfortunately, this is merely undefined, rather than a constraint
+ violation, so we cannot make this an error. If this call is never
+ executed, the program is still strictly conforming. */
+ warned = warning_at (loc, 0,
+ "%qT is promoted to %qT when passed through %<...%>",
+ type, promoted_type);
+ if (!gave_help && warned)
+ {
+ gave_help = true;
+ inform (loc, "(so you should pass %qT not %qT to %<va_arg%>)",
+ promoted_type, type);
+ }
+
+ /* We can, however, treat "undefined" any way we please.
+ Call abort to encourage the user to fix the program. */
+ if (warned)
+ inform (loc, "if this code is reached, the program will abort");
+ /* Before the abort, allow the evaluation of the va_list
+ expression to exit or longjmp. */
+ gimplify_and_add (valist, pre_p);
+ t = build_call_expr_loc (loc,
+ builtin_decl_implicit (BUILT_IN_TRAP), 0);
+ gimplify_and_add (t, pre_p);
+
+ /* This is dead code, but go ahead and finish so that the
+ mode of the result comes out right. */
+ *expr_p = dummy_object (type);
+ return GS_ALL_DONE;
+ }
+ else
+ {
+ /* Make it easier for the backends by protecting the valist argument
+ from multiple evaluations. */
+ if (TREE_CODE (have_va_type) == ARRAY_TYPE)
+ {
+ /* For this case, the backends will be expecting a pointer to
+ TREE_TYPE (abi), but it's possible we've
+ actually been given an array (an actual TARGET_FN_ABI_VA_LIST).
+ So fix it. */
+ if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE)
+ {
+ tree p1 = build_pointer_type (TREE_TYPE (have_va_type));
+ valist = fold_convert_loc (loc, p1,
+ build_fold_addr_expr_loc (loc, valist));
+ }
+
+ gimplify_expr (&valist, pre_p, post_p, is_gimple_val, fb_rvalue);
+ }
+ else
+ gimplify_expr (&valist, pre_p, post_p, is_gimple_min_lval, fb_lvalue);
+
+ if (!targetm.gimplify_va_arg_expr)
+ /* FIXME: Once most targets are converted we should merely
+ assert this is non-null. */
+ return GS_ALL_DONE;
+
+ *expr_p = targetm.gimplify_va_arg_expr (valist, type, pre_p, post_p);
+ return GS_OK;
+ }
+}
#include "gt-gimplify.h"
diff --git a/gcc/ginclude/stdatomic.h b/gcc/ginclude/stdatomic.h
new file mode 100644
index 00000000000..622577f0877
--- /dev/null
+++ b/gcc/ginclude/stdatomic.h
@@ -0,0 +1,244 @@
+/* Copyright (C) 2013 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/>. */
+
+/* ISO C11 Standard: 7.17 Atomics <stdatomic.h>. */
+
+#ifndef _STDATOMIC_H
+#define _STDATOMIC_H
+
+typedef enum
+ {
+ memory_order_relaxed = __ATOMIC_RELAXED,
+ memory_order_consume = __ATOMIC_CONSUME,
+ memory_order_acquire = __ATOMIC_ACQUIRE,
+ memory_order_release = __ATOMIC_RELEASE,
+ memory_order_acq_rel = __ATOMIC_ACQ_REL,
+ memory_order_seq_cst = __ATOMIC_SEQ_CST
+ } memory_order;
+
+
+typedef _Atomic _Bool atomic_bool;
+typedef _Atomic char atomic_char;
+typedef _Atomic signed char atomic_schar;
+typedef _Atomic unsigned char atomic_uchar;
+typedef _Atomic short atomic_short;
+typedef _Atomic unsigned short atomic_ushort;
+typedef _Atomic int atomic_int;
+typedef _Atomic unsigned int atomic_uint;
+typedef _Atomic long atomic_long;
+typedef _Atomic unsigned long atomic_ulong;
+typedef _Atomic long long atomic_llong;
+typedef _Atomic unsigned long long atomic_ullong;
+typedef _Atomic __CHAR16_TYPE__ atomic_char16_t;
+typedef _Atomic __CHAR32_TYPE__ atomic_char32_t;
+typedef _Atomic __WCHAR_TYPE__ atomic_wchar_t;
+typedef _Atomic __INT_LEAST8_TYPE__ atomic_int_least8_t;
+typedef _Atomic __UINT_LEAST8_TYPE__ atomic_uint_least8_t;
+typedef _Atomic __INT_LEAST16_TYPE__ atomic_int_least16_t;
+typedef _Atomic __UINT_LEAST16_TYPE__ atomic_uint_least16_t;
+typedef _Atomic __INT_LEAST32_TYPE__ atomic_int_least32_t;
+typedef _Atomic __UINT_LEAST32_TYPE__ atomic_uint_least32_t;
+typedef _Atomic __INT_LEAST64_TYPE__ atomic_int_least64_t;
+typedef _Atomic __UINT_LEAST64_TYPE__ atomic_uint_least64_t;
+typedef _Atomic __INT_FAST8_TYPE__ atomic_int_fast8_t;
+typedef _Atomic __UINT_FAST8_TYPE__ atomic_uint_fast8_t;
+typedef _Atomic __INT_FAST16_TYPE__ atomic_int_fast16_t;
+typedef _Atomic __UINT_FAST16_TYPE__ atomic_uint_fast16_t;
+typedef _Atomic __INT_FAST32_TYPE__ atomic_int_fast32_t;
+typedef _Atomic __UINT_FAST32_TYPE__ atomic_uint_fast32_t;
+typedef _Atomic __INT_FAST64_TYPE__ atomic_int_fast64_t;
+typedef _Atomic __UINT_FAST64_TYPE__ atomic_uint_fast64_t;
+typedef _Atomic __INTPTR_TYPE__ atomic_intptr_t;
+typedef _Atomic __UINTPTR_TYPE__ atomic_uintptr_t;
+typedef _Atomic __SIZE_TYPE__ atomic_size_t;
+typedef _Atomic __PTRDIFF_TYPE__ atomic_ptrdiff_t;
+typedef _Atomic __INTMAX_TYPE__ atomic_intmax_t;
+typedef _Atomic __UINTMAX_TYPE__ atomic_uintmax_t;
+
+
+#define ATOMIC_VAR_INIT(VALUE) (VALUE)
+#define atomic_init(PTR, VAL) \
+ do \
+ { \
+ *(PTR) = (VAL); \
+ } \
+ while (0)
+
+#define kill_dependency(Y) \
+ __extension__ \
+ ({ \
+ __typeof__ (Y) __kill_dependency_tmp = (Y); \
+ __kill_dependency_tmp; \
+ })
+
+#define atomic_thread_fence(MO) __atomic_thread_fence (MO)
+#define atomic_signal_fence(MO) __atomic_signal_fence (MO)
+#define atomic_is_lock_free(OBJ) __atomic_is_lock_free (sizeof (*(OBJ)), (OBJ))
+
+#define __atomic_type_lock_free(T) \
+ (__atomic_always_lock_free (sizeof (T), (void *) 0) \
+ ? 2 \
+ : (__atomic_is_lock_free (sizeof (T), (void *) 0) ? 1 : 0))
+#define ATOMIC_BOOL_LOCK_FREE \
+ __atomic_type_lock_free (atomic_bool)
+#define ATOMIC_CHAR_LOCK_FREE \
+ __atomic_type_lock_free (atomic_char)
+#define ATOMIC_CHAR16_T_LOCK_FREE \
+ __atomic_type_lock_free (atomic_char16_t)
+#define ATOMIC_CHAR32_T_LOCK_FREE \
+ __atomic_type_lock_free (atomic_char32_t)
+#define ATOMIC_WCHAR_T_LOCK_FREE \
+ __atomic_type_lock_free (atomic_wchar_t)
+#define ATOMIC_SHORT_LOCK_FREE \
+ __atomic_type_lock_free (atomic_short)
+#define ATOMIC_INT_LOCK_FREE \
+ __atomic_type_lock_free (atomic_int)
+#define ATOMIC_LONG_LOCK_FREE \
+ __atomic_type_lock_free (atomic_long)
+#define ATOMIC_LLONG_LOCK_FREE \
+ __atomic_type_lock_free (atomic_llong)
+#define ATOMIC_POINTER_LOCK_FREE \
+ __atomic_type_lock_free (void * _Atomic)
+
+
+/* Note that these macros require __typeof__ to remove _Atomic
+ qualifiers (and const qualifiers, if those are valid on macro
+ operands).
+
+ Also note that the header file uses the generic form of __atomic
+ builtins, which requires the address to be taken of the value
+ parameter, and then we pass that value on. This allows the macros
+ to work for any type, and the compiler is smart enough to convert
+ these to lock-free _N variants if possible, and throw away the
+ temps. */
+
+#define atomic_store_explicit(PTR, VAL, MO) \
+ __extension__ \
+ ({ \
+ __typeof__ (*(PTR)) __atomic_store_tmp = (VAL); \
+ __atomic_store ((PTR), &__atomic_store_tmp, (MO)); \
+ })
+
+#define atomic_store(PTR, VAL) \
+ atomic_store_explicit (PTR, VAL, __ATOMIC_SEQ_CST)
+
+
+#define atomic_load_explicit(PTR, MO) \
+ __extension__ \
+ ({ \
+ __typeof__ (*(PTR)) __atomic_load_tmp; \
+ __atomic_load ((PTR), &__atomic_load_tmp, (MO)); \
+ __atomic_load_tmp; \
+ })
+
+#define atomic_load(PTR) atomic_load_explicit (PTR, __ATOMIC_SEQ_CST)
+
+
+#define atomic_exchange_explicit(PTR, VAL, MO) \
+ __extension__ \
+ ({ \
+ __typeof__ (*(PTR)) __atomic_exchange_val = (VAL), __atomic_exchange_tmp; \
+ __atomic_exchange ((PTR), &__atomic_exchange_val, \
+ &__atomic_exchange_tmp, (MO)); \
+ __atomic_exchange_tmp; \
+ })
+
+#define atomic_exchange(PTR, VAL) \
+ atomic_exchange_explicit (PTR, VAL, __ATOMIC_SEQ_CST)
+
+
+#define atomic_compare_exchange_strong_explicit(PTR, VAL, DES, SUC, FAIL) \
+ __extension__ \
+ ({ \
+ __typeof__ (*(PTR)) __atomic_compare_exchange_tmp = (DES); \
+ __atomic_compare_exchange ((PTR), (VAL), \
+ &__atomic_compare_exchange_tmp, 0, \
+ (SUC), (FAIL)); \
+ })
+
+#define atomic_compare_exchange_strong(PTR, VAL, DES) \
+ atomic_compare_exchange_strong_explicit (PTR, VAL, DES, __ATOMIC_SEQ_CST, \
+ __ATOMIC_SEQ_CST)
+
+#define atomic_compare_exchange_weak_explicit(PTR, VAL, DES, SUC, FAIL) \
+ __extension__ \
+ ({ \
+ __typeof__ (*(PTR)) __atomic_compare_exchange_tmp = (DES); \
+ __atomic_compare_exchange ((PTR), (VAL), \
+ &__atomic_compare_exchange_tmp, 1, \
+ (SUC), (FAIL)); \
+ })
+
+#define atomic_compare_exchange_weak(PTR, VAL, DES) \
+ atomic_compare_exchange_weak_explicit (PTR, VAL, DES, __ATOMIC_SEQ_CST, \
+ __ATOMIC_SEQ_CST)
+
+
+
+#define atomic_fetch_add(PTR, VAL) __atomic_fetch_add ((PTR), (VAL), \
+ __ATOMIC_SEQ_CST)
+#define atomic_fetch_add_explicit(PTR, VAL, MO) \
+ __atomic_fetch_add ((PTR), (VAL), (MO))
+
+#define atomic_fetch_sub(PTR, VAL) __atomic_fetch_sub ((PTR), (VAL), \
+ __ATOMIC_SEQ_CST)
+#define atomic_fetch_sub_explicit(PTR, VAL, MO) \
+ __atomic_fetch_sub ((PTR), (VAL), (MO))
+
+#define atomic_fetch_or(PTR, VAL) __atomic_fetch_or ((PTR), (VAL), \
+ __ATOMIC_SEQ_CST)
+#define atomic_fetch_or_explicit(PTR, VAL, MO) \
+ __atomic_fetch_or ((PTR), (VAL), (MO))
+
+#define atomic_fetch_xor(PTR, VAL) __atomic_fetch_xor ((PTR), (VAL), \
+ __ATOMIC_SEQ_CST)
+#define atomic_fetch_xor_explicit(PTR, VAL, MO) \
+ __atomic_fetch_xor ((PTR), (VAL), (MO))
+
+#define atomic_fetch_and(PTR, VAL) __atomic_fetch_and ((PTR), (VAL), \
+ __ATOMIC_SEQ_CST)
+#define atomic_fetch_and_explicit(PTR, VAL, MO) \
+ __atomic_fetch_and ((PTR), (VAL), (MO))
+
+
+typedef _Atomic struct
+{
+#if __GCC_ATOMIC_TEST_AND_SET_TRUEVAL == 1
+ _Bool __val;
+#else
+ unsigned char __val;
+#endif
+} atomic_flag;
+
+#define ATOMIC_FLAG_INIT { 0 }
+
+
+#define atomic_flag_test_and_set(PTR) \
+ __atomic_test_and_set ((PTR), __ATOMIC_SEQ_CST)
+#define atomic_flag_test_and_set_explicit(PTR, MO) \
+ __atomic_test_and_set ((PTR), (MO))
+
+#define atomic_flag_clear(PTR) __atomic_clear ((PTR), __ATOMIC_SEQ_CST)
+#define atomic_flag_clear_explicit(PTR, MO) __atomic_clear ((PTR), (MO))
+
+#endif /* _STDATOMIC_H */
diff --git a/gcc/go/ChangeLog b/gcc/go/ChangeLog
index c730ecaa183..33ccc1cdce8 100644
--- a/gcc/go/ChangeLog
+++ b/gcc/go/ChangeLog
@@ -1,3 +1,64 @@
+2013-11-06 Ian Lance Taylor <iant@google.com>
+
+ * go-lang.c (go_langhook_post_options): If
+ -fisolate-erroneous-paths was turned on by an optimization option,
+ turn it off.
+
+2013-10-14 Chris Manghane <cmang@google.com>
+
+ * go-gcc.cc (Gcc_backend::address_expression): New function.
+
+2013-10-11 Chris Manghane <cmang@google.com>
+
+ * go-gcc.cc (Gcc_backend::function_code_expression): New
+ function.
+
+2013-10-10 Chris Manghane <cmang@google.com>
+
+ * go-gcc.cc (Gcc_backend::error_function): New function.
+ (Gcc_backend::function): New function.
+ (Gcc_backend::make_function): New function.
+ (function_to_tree): New function.
+
+2013-10-04 Chris Manghane <cmang@google.com>
+
+ * go-gcc.cc (Gcc_backend::convert_expression): New function.
+
+2013-10-02 Chris Manghane <cmang@google.com>
+
+ * go-gcc.cc: Include "real.h" and "realmpfr.h".
+ (Gcc_backend::integer_constant_expression): New function.
+ (Gcc_backend::float_constant_expression): New function.
+ (Gcc_backend::complex_constant_expression): New function.
+
+2013-09-30 Chris Manghane <cmang@google.com>
+
+ * go-gcc.cc (Gcc_backend::error_expression): New function.
+ (Gcc_backend::var_expression): New function.
+ (Gcc_backend::indirect_expression): New function.
+
+2013-09-25 Tom Tromey <tromey@redhat.com>
+
+ * Make-lang.in (gospec.o): Remove.
+ (CFLAGS-go/gospec.o): New variable.
+ (GCCGO_OBJS): Update to use go/gospec.o.
+ (go_OBJS): Define.
+ (GO_SYSTEM_H, GO_C_H, GO_LINEMAP_H, GO_LEX_H, GO_PARSE_H)
+ (GO_GOGO_H, GO_TYPES_H, GO_STATEMENTS_H, GO_EXPRESSIONS_H)
+ (GO_EXPORT_H, GO_IMPORT_H, GO_RUNTIME_H, GO_AST_DUMP_H)
+ (go/go-backend.o, go/go-lang.o, go/go-gcc.o, go/go-linemap.o)
+ (go/ast-dump.o, go/dataflow.o, go/export.o, go/expressions.o)
+ (go/go.o, go/go-dump.o, go/go-optimize.o, go/gogo-tree.o)
+ (go/gogo.o, go/import.o, go/import-archive.o, go/lex.o)
+ (go/parse.o, go/runtime.o, go/statements.o, go/types.o)
+ (go/unsafe.o): Remove.
+ (CFLAGS-go/go-gcc.o, CFLAGS-go/go-linemap.o): New variables.
+ (go/%.o: go/gofrontend/%.cc): Use COMPILE and POSTCOMPILE.
+
+2013-09-25 Tom Tromey <tromey@redhat.com>
+
+ * Make-lang.in (gospec.o): Don't use subshell.
+
2013-08-28 Ian Lance Taylor <iant@google.com>
* go-gcc.cc (Gcc_backend::immutable_struct): Set TREE_PUBLIC if
@@ -469,7 +530,7 @@
2011-04-14 Ian Lance Taylor <iant@google.com>
- * go-gcc.cc (Backend::error_statement): New function.
+ * go-gcc.cc (Gcc_backend::error_statement): New function.
2011-04-13 Ian Lance Taylor <iant@google.com>
diff --git a/gcc/go/Make-lang.in b/gcc/go/Make-lang.in
index 3cb18d6adcf..e4bceb21c08 100644
--- a/gcc/go/Make-lang.in
+++ b/gcc/go/Make-lang.in
@@ -30,13 +30,9 @@ go: go1$(exeext)
.PHONY: go
-gospec.o: $(srcdir)/go/gospec.c $(SYSTEM_H) coretypes.h $(TM_H) $(GCC_H) \
- $(CONFIG_H) opts.h
- (SHLIB='$(SHLIB)'; \
- $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(DRIVER_DEFINES) \
- $(INCLUDES) $(srcdir)/go/gospec.c)
+CFLAGS-go/gospec.o += $(DRIVER_DEFINES)
-GCCGO_OBJS = $(GCC_OBJS) gospec.o
+GCCGO_OBJS = $(GCC_OBJS) go/gospec.o
gccgo$(exeext): $(GCCGO_OBJS) $(EXTRA_GCC_OBJS) libcommon-target.a $(LIBDEPS)
+$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
$(GCCGO_OBJS) $(EXTRA_GCC_OBJS) libcommon-target.a \
@@ -75,6 +71,8 @@ GO_OBJS = \
go/types.o \
go/unsafe.o
+go_OBJS = $(GO_OBJS) go/gospec.o
+
go1$(exeext): $(GO_OBJS) attribs.o $(BACKEND) $(LIBDEPS)
+$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
$(GO_OBJS) attribs.o $(BACKEND) $(LIBS) $(BACKENDLIBS)
@@ -223,96 +221,14 @@ go.stageprofile: stageprofile-start
go.stagefeedback: stagefeedback-start
-mv go/*$(objext) stagefeedback/go
-GO_SYSTEM_H = go/go-system.h $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(DIAGNOSTIC_CORE_H) $(INPUT_H) intl.h
-
-GO_C_H = go/go-c.h $(MACHMODE_H)
-GO_LINEMAP_H = go/gofrontend/go-linemap.h $(GO_SYSTEM_H) go/go-location.h
-GO_LEX_H = go/gofrontend/lex.h go/gofrontend/operator.h $(GO_LINEMAP_H)
-GO_PARSE_H = go/gofrontend/parse.h
-GO_GOGO_H = go/gofrontend/gogo.h $(GO_LINEMAP_H)
-GO_TYPES_H = go/gofrontend/types.h $(GO_LINEMAP_H)
-GO_STATEMENTS_H = go/gofrontend/statements.h go/gofrontend/operator.h
-GO_EXPRESSIONS_H = go/gofrontend/expressions.h go/gofrontend/operator.h
-GO_EXPORT_H = go/gofrontend/export.h go/gofrontend/string-dump.h
-GO_IMPORT_H = go/gofrontend/import.h $(GO_EXPORT_H) $(GO_LINEMAP_H)
-GO_RUNTIME_H = go/gofrontend/runtime.h go/gofrontend/runtime.def
-GO_AST_DUMP_H = go/gofrontend/ast-dump.h go/gofrontend/string-dump.h
-
-go/go-backend.o: go/go-backend.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(TREE_H) $(TM_P_H) output.h $(TARGET_H) \
- $(COMMON_TARGET_H)
-
CFLAGS-go/go-lang.o += -DDEFAULT_TARGET_VERSION=\"$(version)\" \
-DDEFAULT_TARGET_MACHINE=\"$(target_noncanonical)\"
-go/go-lang.o: go/go-lang.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(OPTS_H) \
- $(TREE_H) $(GIMPLE_H) $(GGC_H) $(TOPLEV_H) debug.h options.h \
- $(FLAGS_H) convert.h $(DIAGNOSTIC_H) langhooks.h \
- $(LANGHOOKS_DEF_H) $(TARGET_H) $(GO_C_H) \
- gt-go-go-lang.h gtype-go.h $(COMMON_TARGET_H)
GOINCLUDES = -I $(srcdir)/go -I $(srcdir)/go/gofrontend
-go/go-gcc.o: go/go-gcc.cc $(GO_SYSTEM_H) $(TREE_H) tree-iterator.h \
- $(GIMPLE_H) toplev.h output.h $(GO_C_H) $(GO_GOGO_H) \
- go/gofrontend/backend.h
- $(CXX) -c $(GOINCLUDES) $(ALL_CPPFLAGS) $(ALL_CXXFLAGS) $< $(OUTPUT_OPTION)
-
-go/go-linemap.o: go/go-linemap.cc $(GO_SYSTEM_H) $(GO_LINEMAP_H)
- $(CXX) -c $(GOINCLUDES) $(ALL_CPPFLAGS) $(ALL_CXXFLAGS) $< $(OUTPUT_OPTION)
+CFLAGS-go/go-gcc.o += $(GOINCLUDES)
+CFLAGS-go/go-linemap.o += $(GOINCLUDES)
go/%.o: go/gofrontend/%.cc
- $(CXX) -c $(GOINCLUDES) $(ALL_CPPFLAGS) $(ALL_CXXFLAGS) $< $(OUTPUT_OPTION)
-
-go/ast-dump.o: go/gofrontend/ast-dump.cc $(GO_SYSTME_H) $(GO_GOGO_H) \
- $(GO_EXPRESSIONS_H) $(GO_STATEMENTS_H) $(GO_TYPES_H) \
- $(GO_AST_DUMP_H) $(GO_C_H) go/gofrontend/go-dump.h
-go/dataflow.o: go/gofrontend/dataflow.cc $(GO_SYSTEM_H) $(GO_GOGO_H) \
- $(GO_EXPRESSIONS_H) $(GO_STATEMENTS_H) go/gofrontend/dataflow.h
-go/export.o: go/gofrontend/export.cc $(GO_SYSTEM_H) \
- $(srcdir)/../include/sha1.h $(GO_C_H) $(GO_GOGO_H) $(GO_TYPES_H) \
- $(GO_STATEMENTS_H) $(GO_EXPORT_H)
-go/expressions.o: go/gofrontend/expressions.cc $(GO_SYSTEM_H) $(TOPLEV_H) \
- intl.h $(TREE_H) $(GIMPLE_H) tree-iterator.h convert.h $(REAL_H) \
- realmpfr.h $(GO_C_H) $(GO_GOGO_H) $(GO_TYPES_H) \
- $(GO_EXPORT_H) $(GO_IMPORT_H) $(GO_STATEMENTS_H) $(GO_LEX_H) \
- $(GO_RUNTIME_H) go/gofrontend/backend.h $(GO_EXPRESSIONS_H) \
- $(GO_AST_DUMP_H)
-go/go.o: go/gofrontend/go.cc $(GO_SYSTEM_H) $(GO_C_H) $(GO_LEX_H) \
- $(GO_PARSE_H) go/gofrontend/backend.h $(GO_GOGO_H)
-go/go-dump.o: go/gofrontend/go-dump.cc $(GO_SYSTEM_H) $(GO_C_H) \
- go/gofrontend/go-dump.h
-go/go-optimize.o: go/gofrontend/go-optimize.cc $(GO_SYSTEM_H) $(GO_C_H) \
- go/gofrontend/go-optimize.h
-go/gogo-tree.o: go/gofrontend/gogo-tree.cc $(GO_SYSTEM_H) $(TOPLEV_H) \
- $(TREE_H) $(GIMPLE_H) tree-iterator.h $(CGRAPH_H) langhooks.h \
- convert.h output.h $(DIAGNOSTIC_H) $(GO_TYPES_H) \
- $(GO_EXPRESSIONS_H) $(GO_STATEMENTS_H) $(GO_RUNTIME_H) \
- go/gofrontend/backend.h $(GO_GOGO_H)
-go/gogo.o: go/gofrontend/gogo.cc $(GO_SYSTEM_H) \
- $(srcdir)/../include/filenames.h $(GO_C_H) go/gofrontend/go-dump.h \
- $(GO_LEX_H) $(GO_TYPES_H) $(GO_STATEMENTS_H) $(GO_EXPRESSIONS_H) \
- go/gofrontend/dataflow.h $(GO_RUNTIME_H) $(GO_IMPORT_H) \
- $(GO_EXPORT_H) go/gofrontend/backend.h $(GO_GOGO_H)
-go/import.o: go/gofrontend/import.cc $(GO_SYSTEM_H) \
- $(srcdir)/../include/filenames.h $(srcdir)/../include/simple-object.h \
- $(GO_C_H) $(GO_GOGO_H) $(GO_LEX_H) $(GO_TYPES_H) $(GO_EXPORT_H) \
- $(GO_IMPORT_H)
-go/import-archive.o: go/gofrontend/import-archive.cc $(GO_SYSTEM_H) \
- $(GO_IMPORT_H)
-go/lex.o: go/gofrontend/lex.cc $(GO_LEX_H) $(GO_SYSTEM_H)
-go/parse.o: go/gofrontend/parse.cc $(GO_SYSTEM_H) $(GO_LEX_H) $(GO_GOGO_H) \
- $(GO_TYPES_H) $(GO_STATEMENTS_H) $(GO_EXPRESSIONS_H) $(GO_PARSE_H)
-go/runtime.o: go/gofrontend/runtime.cc $(GO_SYSTEM_H) $(GO_GOGO_H) \
- $(GO_TYPES_H) $(GO_EXPRESSIONS_H) $(GO_RUNTIME_H) \
- go/gofrontend/runtime.def
-go/statements.o: go/gofrontend/statements.cc $(GO_SYSTEM_H) \
- $(GO_C_H) $(GO_TYPES_H) $(GO_EXPRESSIONS_H) $(GO_GOGO_H) \
- $(GO_RUNTIME_H) go/gofrontend/backend.h $(GO_STATEMENTS_H) \
- $(GO_AST_DUMP_H)
-go/types.o: go/gofrontend/types.cc $(GO_SYSTEM_H) $(TOPLEV_H) intl.h $(TREE_H) \
- $(GIMPLE_H) $(REAL_H) convert.h $(GO_C_H) $(GO_GOGO_H) \
- go/gofrontend/operator.h $(GO_EXPRESSIONS_H) $(GO_STATEMENTS_H) \
- $(GO_EXPORT_H) $(GO_IMPORT_H) go/gofrontend/backend.h $(GO_TYPES_H)
-go/unsafe.o: go/gofrontend/unsafe.cc $(GO_SYSTEM_H) $(GO_C_H) $(GO_TYPES_H) \
- $(GO_GOGO_H)
+ $(COMPILE) $(GOINCLUDES) $<
+ $(POSTCOMPILE)
diff --git a/gcc/go/go-gcc.cc b/gcc/go/go-gcc.cc
index 025bb2bdca0..5ff529fc62b 100644
--- a/gcc/go/go-gcc.cc
+++ b/gcc/go/go-gcc.cc
@@ -29,6 +29,8 @@
#include "gimple.h"
#include "toplev.h"
#include "output.h"
+#include "real.h"
+#include "realmpfr.h"
#include "go-c.h"
@@ -208,6 +210,34 @@ class Gcc_backend : public Backend
Bexpression*
zero_expression(Btype*);
+ Bexpression*
+ error_expression()
+ { return this->make_expression(error_mark_node); }
+
+ Bexpression*
+ var_expression(Bvariable* var, Location);
+
+ Bexpression*
+ indirect_expression(Bexpression* expr, bool known_valid, Location);
+
+ Bexpression*
+ integer_constant_expression(Btype* btype, mpz_t val);
+
+ Bexpression*
+ float_constant_expression(Btype* btype, mpfr_t val);
+
+ Bexpression*
+ complex_constant_expression(Btype* btype, mpfr_t real, mpfr_t imag);
+
+ Bexpression*
+ convert_expression(Btype* type, Bexpression* expr, Location);
+
+ Bexpression*
+ function_code_expression(Bfunction*, Location);
+
+ Bexpression*
+ address_expression(Bexpression*, Location);
+
// Statements.
Bstatement*
@@ -310,6 +340,17 @@ class Gcc_backend : public Backend
Bexpression*
label_address(Blabel*, Location);
+ // Functions.
+
+ Bfunction*
+ error_function()
+ { return this->make_function(error_mark_node); }
+
+ Bfunction*
+ function(Btype* fntype, const std::string& name, const std::string& asm_name,
+ bool is_visible, bool is_declaration, bool is_inlinable,
+ bool disable_split_stack, bool in_unique_section, Location);
+
private:
// Make a Bexpression from a tree.
Bexpression*
@@ -326,6 +367,10 @@ class Gcc_backend : public Backend
make_type(tree t)
{ return new Btype(t); }
+ Bfunction*
+ make_function(tree t)
+ { return new Bfunction(t); }
+
Btype*
fill_in_struct(Btype*, const std::vector<Btyped_identifier>&);
@@ -848,6 +893,126 @@ Gcc_backend::zero_expression(Btype* btype)
return tree_to_expr(ret);
}
+// An expression that references a variable.
+
+Bexpression*
+Gcc_backend::var_expression(Bvariable* var, Location)
+{
+ tree ret = var->get_tree();
+ if (ret == error_mark_node)
+ return this->error_expression();
+ return tree_to_expr(ret);
+}
+
+// An expression that indirectly references an expression.
+
+Bexpression*
+Gcc_backend::indirect_expression(Bexpression* expr, bool known_valid,
+ Location location)
+{
+ tree ret = build_fold_indirect_ref_loc(location.gcc_location(),
+ expr->get_tree());
+ if (known_valid)
+ TREE_THIS_NOTRAP(ret) = 1;
+ return tree_to_expr(ret);
+}
+
+// Return a typed value as a constant integer.
+
+Bexpression*
+Gcc_backend::integer_constant_expression(Btype* btype, mpz_t val)
+{
+ tree t = btype->get_tree();
+ if (t == error_mark_node)
+ return this->error_expression();
+
+ tree ret = double_int_to_tree(t, mpz_get_double_int(t, val, true));
+ return tree_to_expr(ret);
+}
+
+// Return a typed value as a constant floating-point number.
+
+Bexpression*
+Gcc_backend::float_constant_expression(Btype* btype, mpfr_t val)
+{
+ tree t = btype->get_tree();
+ tree ret;
+ if (t == error_mark_node)
+ return this->error_expression();
+
+ REAL_VALUE_TYPE r1;
+ real_from_mpfr(&r1, val, t, GMP_RNDN);
+ REAL_VALUE_TYPE r2;
+ real_convert(&r2, TYPE_MODE(t), &r1);
+ ret = build_real(t, r2);
+ return tree_to_expr(ret);
+}
+
+// Return a typed real and imaginary value as a constant complex number.
+
+Bexpression*
+Gcc_backend::complex_constant_expression(Btype* btype, mpfr_t real, mpfr_t imag)
+{
+ tree t = btype->get_tree();
+ tree ret;
+ if (t == error_mark_node)
+ return this->error_expression();
+
+ REAL_VALUE_TYPE r1;
+ real_from_mpfr(&r1, real, TREE_TYPE(t), GMP_RNDN);
+ REAL_VALUE_TYPE r2;
+ real_convert(&r2, TYPE_MODE(TREE_TYPE(t)), &r1);
+
+ REAL_VALUE_TYPE r3;
+ real_from_mpfr(&r3, imag, TREE_TYPE(t), GMP_RNDN);
+ REAL_VALUE_TYPE r4;
+ real_convert(&r4, TYPE_MODE(TREE_TYPE(t)), &r3);
+
+ ret = build_complex(t, build_real(TREE_TYPE(t), r2),
+ build_real(TREE_TYPE(t), r4));
+ return tree_to_expr(ret);
+}
+
+// An expression that converts an expression to a different type.
+
+Bexpression*
+Gcc_backend::convert_expression(Btype* type, Bexpression* expr, Location)
+{
+ tree type_tree = type->get_tree();
+ tree expr_tree = expr->get_tree();
+ if (type_tree == error_mark_node || expr_tree == error_mark_node)
+ return this->error_expression();
+
+ tree ret = fold_convert(type_tree, expr_tree);
+ return tree_to_expr(ret);
+}
+
+// Get the address of a function.
+
+Bexpression*
+Gcc_backend::function_code_expression(Bfunction* bfunc, Location location)
+{
+ tree func = bfunc->get_tree();
+ if (func == error_mark_node)
+ return this->error_expression();
+
+ tree ret = build_fold_addr_expr_loc(location.gcc_location(), func);
+ return this->make_expression(ret);
+}
+
+// Get the address of an expression.
+
+Bexpression*
+Gcc_backend::address_expression(Bexpression* bexpr, Location location)
+{
+ tree expr = bexpr->get_tree();
+ if (expr == error_mark_node)
+ return this->error_expression();
+
+ tree ret = build_fold_addr_expr_loc(location.gcc_location(), expr);
+ return this->make_expression(ret);
+}
+
// An expression as a statement.
Bstatement*
@@ -1606,6 +1771,56 @@ Gcc_backend::label_address(Blabel* label, Location location)
return this->make_expression(ret);
}
+// Declare or define a new function.
+
+Bfunction*
+Gcc_backend::function(Btype* fntype, const std::string& name,
+ const std::string& asm_name, bool is_visible,
+ bool is_declaration, bool is_inlinable,
+ bool disable_split_stack, bool in_unique_section,
+ Location location)
+{
+ tree functype = fntype->get_tree();
+ if (functype != error_mark_node)
+ {
+ gcc_assert(FUNCTION_POINTER_TYPE_P(functype));
+ functype = TREE_TYPE(functype);
+ }
+ tree id = get_identifier_from_string(name);
+ if (functype == error_mark_node || id == error_mark_node)
+ return this->error_function();
+
+ tree decl = build_decl(location.gcc_location(), FUNCTION_DECL, id, functype);
+ if (!asm_name.empty())
+ SET_DECL_ASSEMBLER_NAME(decl, get_identifier_from_string(asm_name));
+ if (is_visible)
+ TREE_PUBLIC(decl) = 1;
+ if (is_declaration)
+ DECL_EXTERNAL(decl) = 1;
+ else
+ {
+ tree restype = TREE_TYPE(functype);
+ tree resdecl =
+ build_decl(location.gcc_location(), RESULT_DECL, NULL_TREE, restype);
+ DECL_ARTIFICIAL(resdecl) = 1;
+ DECL_IGNORED_P(resdecl) = 1;
+ DECL_CONTEXT(resdecl) = decl;
+ DECL_RESULT(decl) = resdecl;
+ }
+ if (!is_inlinable)
+ DECL_UNINLINABLE(decl) = 1;
+ if (disable_split_stack)
+ {
+ tree attr = get_identifier("__no_split_stack__");
+ DECL_ATTRIBUTES(decl) = tree_cons(attr, NULL_TREE, NULL_TREE);
+ }
+ if (in_unique_section)
+ resolve_unique_section(decl, 0, 1);
+
+ go_preserve_from_gc(decl);
+ return new Bfunction(decl);
+}
+
// The single backend.
static Gcc_backend gcc_backend;
@@ -1681,3 +1896,9 @@ var_to_tree(Bvariable* bv)
{
return bv->get_tree();
}
+
+tree
+function_to_tree(Bfunction* bf)
+{
+ return bf->get_tree();
+}
diff --git a/gcc/go/go-lang.c b/gcc/go/go-lang.c
index 37d61d1f5d7..14080f098c8 100644
--- a/gcc/go/go-lang.c
+++ b/gcc/go/go-lang.c
@@ -268,6 +268,12 @@ go_langhook_post_options (const char **pfilename ATTRIBUTE_UNUSED)
if (flag_excess_precision_cmdline == EXCESS_PRECISION_DEFAULT)
flag_excess_precision_cmdline = EXCESS_PRECISION_STANDARD;
+ /* The isolate_erroneous_paths optimization can change a nil
+ dereference from a panic to a trap, so we have to disable it for
+ Go, even though it is normally enabled by -O2. */
+ if (!global_options_set.x_flag_isolate_erroneous_paths)
+ global_options.x_flag_isolate_erroneous_paths = 0;
+
/* Returning false means that the backend should be used. */
return false;
}
diff --git a/gcc/go/gofrontend/backend.h b/gcc/go/gofrontend/backend.h
index ac29b03e453..6f2c321e09e 100644
--- a/gcc/go/gofrontend/backend.h
+++ b/gcc/go/gofrontend/backend.h
@@ -7,6 +7,9 @@
#ifndef GO_BACKEND_H
#define GO_BACKEND_H
+#include <gmp.h>
+#include <mpfr.h>
+
// Pointers to these types are created by the backend, passed to the
// frontend, and passed back to the backend. The types must be
// defined by the backend using these names.
@@ -20,7 +23,7 @@ class Bexpression;
// The backend representation of a statement.
class Bstatement;
-// The backend representation of a function definition.
+// The backend representation of a function definition or declaration.
class Bfunction;
// The backend representation of a block.
@@ -231,6 +234,47 @@ class Backend
virtual Bexpression*
zero_expression(Btype*) = 0;
+ // Create an error expression. This is used for cases which should
+ // not occur in a correct program, in order to keep the compilation
+ // going without crashing.
+ virtual Bexpression*
+ error_expression() = 0;
+
+ // Create a reference to a variable.
+ virtual Bexpression*
+ var_expression(Bvariable* var, Location) = 0;
+
+ // Create an expression that indirects through the pointer expression EXPR
+ // (i.e., return the expression for *EXPR). KNOWN_VALID is true if the pointer
+ // is known to point to a valid memory location.
+ virtual Bexpression*
+ indirect_expression(Bexpression* expr, bool known_valid, Location) = 0;
+
+ // Return an expression for the multi-precision integer VAL in BTYPE.
+ virtual Bexpression*
+ integer_constant_expression(Btype* btype, mpz_t val) = 0;
+
+ // Return an expression for the floating point value VAL in BTYPE.
+ virtual Bexpression*
+ float_constant_expression(Btype* btype, mpfr_t val) = 0;
+
+ // Return an expression for the complex value REAL/IMAG in BTYPE.
+ virtual Bexpression*
+ complex_constant_expression(Btype* btype, mpfr_t real, mpfr_t imag) = 0;
+
+ // Return an expression that converts EXPR to TYPE.
+ virtual Bexpression*
+ convert_expression(Btype* type, Bexpression* expr, Location) = 0;
+
+ // Create an expression for the address of a function. This is used to
+ // get the address of the code for a function.
+ virtual Bexpression*
+ function_code_expression(Bfunction*, Location) = 0;
+
+ // Create an expression that takes the address of an expression.
+ virtual Bexpression*
+ address_expression(Bexpression*, Location) = 0;
+
// Statements.
// Create an error statement. This is used for cases which should
@@ -463,6 +507,32 @@ class Backend
// recover.
virtual Bexpression*
label_address(Blabel*, Location) = 0;
+
+ // Functions.
+
+ // Create an error function. This is used for cases which should
+ // not occur in a correct program, in order to keep the compilation
+ // going without crashing.
+ virtual Bfunction*
+ error_function() = 0;
+
+ // Declare or define a function of FNTYPE.
+ // NAME is the Go name of the function. ASM_NAME, if not the empty string, is
+ // the name that should be used in the symbol table; this will be non-empty if
+ // a magic extern comment is used.
+ // IS_VISIBLE is true if this function should be visible outside of the
+ // current compilation unit. IS_DECLARATION is true if this is a function
+ // declaration rather than a definition; the function definition will be in
+ // another compilation unit.
+ // IS_INLINABLE is true if the function can be inlined.
+ // DISABLE_SPLIT_STACK is true if this function may not split the stack; this
+ // is used for the implementation of recover.
+ // IN_UNIQUE_SECTION is true if this function should be put into a unique
+ // location if possible; this is used for field tracking.
+ virtual Bfunction*
+ function(Btype* fntype, const std::string& name, const std::string& asm_name,
+ bool is_visible, bool is_declaration, bool is_inlinable,
+ bool disable_split_stack, bool in_unique_section, Location) = 0;
};
// The backend interface has to define this function.
@@ -482,5 +552,6 @@ extern tree expr_to_tree(Bexpression*);
extern tree stat_to_tree(Bstatement*);
extern tree block_to_tree(Bblock*);
extern tree var_to_tree(Bvariable*);
+extern tree function_to_tree(Bfunction*);
#endif // !defined(GO_BACKEND_H)
diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc
index 99edb4b8031..e26bf353e00 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -286,7 +286,11 @@ Expression::convert_type_to_interface(Translate_context* context,
// Otherwise it is the interface method table for RHS_TYPE.
tree first_field_value;
if (lhs_is_empty)
- first_field_value = rhs_type->type_descriptor_pointer(gogo, location);
+ {
+ Bexpression* rhs_bexpr =
+ rhs_type->type_descriptor_pointer(gogo, location);
+ first_field_value = expr_to_tree(rhs_bexpr);
+ }
else
{
// Build the interface method table for this interface and this
@@ -457,8 +461,9 @@ Expression::convert_interface_to_interface(Translate_context* context,
if (for_type_guard)
{
// A type assertion fails when converting a nil interface.
- tree lhs_type_descriptor = lhs_type->type_descriptor_pointer(gogo,
- location);
+ Bexpression* lhs_type_expr = lhs_type->type_descriptor_pointer(gogo,
+ location);
+ tree lhs_type_descriptor = expr_to_tree(lhs_type_expr);
static tree assert_interface_decl;
tree call = Gogo::call_builtin(&assert_interface_decl,
location,
@@ -491,8 +496,10 @@ Expression::convert_interface_to_interface(Translate_context* context,
// type assertion converting nil will always succeed.
go_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__methods")
== 0);
- tree lhs_type_descriptor = lhs_type->type_descriptor_pointer(gogo,
- location);
+ Bexpression* lhs_type_expr = lhs_type->type_descriptor_pointer(gogo,
+ location);
+ tree lhs_type_descriptor = expr_to_tree(lhs_type_expr);
+
static tree convert_interface_decl;
tree call = Gogo::call_builtin(&convert_interface_decl,
location,
@@ -546,8 +553,9 @@ Expression::convert_interface_to_type(Translate_context* context,
// Call a function to check that the type is valid. The function
// will panic with an appropriate runtime type error if the type is
// not valid.
-
- tree lhs_type_descriptor = lhs_type->type_descriptor_pointer(gogo, location);
+ Bexpression* lhs_type_expr = lhs_type->type_descriptor_pointer(gogo,
+ location);
+ tree lhs_type_descriptor = expr_to_tree(lhs_type_expr);
if (!DECL_P(rhs_tree))
rhs_tree = save_expr(rhs_tree);
@@ -556,8 +564,9 @@ Expression::convert_interface_to_type(Translate_context* context,
Expression::get_interface_type_descriptor(context, rhs_type, rhs_tree,
location);
- tree rhs_inter_descriptor = rhs_type->type_descriptor_pointer(gogo,
- location);
+ Bexpression* rhs_inter_expr = rhs_type->type_descriptor_pointer(gogo,
+ location);
+ tree rhs_inter_descriptor = expr_to_tree(rhs_inter_expr);
static tree check_interface_type_decl;
tree call = Gogo::call_builtin(&check_interface_type_decl,
@@ -610,102 +619,57 @@ Expression::get_tree(Translate_context* context)
return this->do_get_tree(context);
}
-// Return a tree for VAL in TYPE.
-
-tree
-Expression::integer_constant_tree(mpz_t val, tree type)
+// Return a backend expression for VAL.
+Bexpression*
+Expression::backend_numeric_constant_expression(Translate_context* context,
+ Numeric_constant* val)
{
- if (type == error_mark_node)
- return error_mark_node;
- else if (TREE_CODE(type) == INTEGER_TYPE)
- return double_int_to_tree(type,
- mpz_get_double_int(type, val, true));
- else if (TREE_CODE(type) == REAL_TYPE)
- {
- mpfr_t fval;
- mpfr_init_set_z(fval, val, GMP_RNDN);
- tree ret = Expression::float_constant_tree(fval, type);
- mpfr_clear(fval);
- return ret;
- }
- else if (TREE_CODE(type) == COMPLEX_TYPE)
- {
- mpfr_t fval;
- mpfr_init_set_z(fval, val, GMP_RNDN);
- tree real = Expression::float_constant_tree(fval, TREE_TYPE(type));
- mpfr_clear(fval);
- tree imag = build_real_from_int_cst(TREE_TYPE(type),
- integer_zero_node);
- return build_complex(type, real, imag);
- }
- else
- go_unreachable();
-}
-
-// Return a tree for VAL in TYPE.
+ Gogo* gogo = context->gogo();
+ Type* type = val->type();
+ if (type == NULL)
+ return gogo->backend()->error_expression();
-tree
-Expression::float_constant_tree(mpfr_t val, tree type)
-{
- if (type == error_mark_node)
- return error_mark_node;
- else if (TREE_CODE(type) == INTEGER_TYPE)
+ Btype* btype = type->get_backend(gogo);
+ Bexpression* ret;
+ if (type->integer_type() != NULL)
{
mpz_t ival;
- mpz_init(ival);
- mpfr_get_z(ival, val, GMP_RNDN);
- tree ret = Expression::integer_constant_tree(ival, type);
+ if (!val->to_int(&ival))
+ {
+ go_assert(saw_errors());
+ return gogo->backend()->error_expression();
+ }
+ ret = gogo->backend()->integer_constant_expression(btype, ival);
mpz_clear(ival);
- return ret;
}
- else if (TREE_CODE(type) == REAL_TYPE)
+ else if (type->float_type() != NULL)
{
- REAL_VALUE_TYPE r1;
- real_from_mpfr(&r1, val, type, GMP_RNDN);
- REAL_VALUE_TYPE r2;
- real_convert(&r2, TYPE_MODE(type), &r1);
- return build_real(type, r2);
+ mpfr_t fval;
+ if (!val->to_float(&fval))
+ {
+ go_assert(saw_errors());
+ return gogo->backend()->error_expression();
+ }
+ ret = gogo->backend()->float_constant_expression(btype, fval);
+ mpfr_clear(fval);
}
- else if (TREE_CODE(type) == COMPLEX_TYPE)
+ else if (type->complex_type() != NULL)
{
- REAL_VALUE_TYPE r1;
- real_from_mpfr(&r1, val, TREE_TYPE(type), GMP_RNDN);
- REAL_VALUE_TYPE r2;
- real_convert(&r2, TYPE_MODE(TREE_TYPE(type)), &r1);
- tree imag = build_real_from_int_cst(TREE_TYPE(type),
- integer_zero_node);
- return build_complex(type, build_real(TREE_TYPE(type), r2), imag);
+ mpfr_t real;
+ mpfr_t imag;
+ if (!val->to_complex(&real, &imag))
+ {
+ go_assert(saw_errors());
+ return gogo->backend()->error_expression();
+ }
+ ret = gogo->backend()->complex_constant_expression(btype, real, imag);
+ mpfr_clear(real);
+ mpfr_clear(imag);
}
else
go_unreachable();
-}
-
-// Return a tree for REAL/IMAG in TYPE.
-
-tree
-Expression::complex_constant_tree(mpfr_t real, mpfr_t imag, tree type)
-{
- if (type == error_mark_node)
- return error_mark_node;
- else if (TREE_CODE(type) == INTEGER_TYPE || TREE_CODE(type) == REAL_TYPE)
- return Expression::float_constant_tree(real, type);
- else if (TREE_CODE(type) == COMPLEX_TYPE)
- {
- REAL_VALUE_TYPE r1;
- real_from_mpfr(&r1, real, TREE_TYPE(type), GMP_RNDN);
- REAL_VALUE_TYPE r2;
- real_convert(&r2, TYPE_MODE(TREE_TYPE(type)), &r1);
-
- REAL_VALUE_TYPE r3;
- real_from_mpfr(&r3, imag, TREE_TYPE(type), GMP_RNDN);
- REAL_VALUE_TYPE r4;
- real_convert(&r4, TYPE_MODE(TREE_TYPE(type)), &r3);
- return build_complex(type, build_real(TREE_TYPE(type), r2),
- build_real(TREE_TYPE(type), r4));
- }
- else
- go_unreachable();
+ return ret;
}
// Return a tree which evaluates to true if VAL, of arbitrary integer
@@ -978,22 +942,19 @@ Var_expression::do_get_tree(Translate_context* context)
{
Bvariable* bvar = this->variable_->get_backend_variable(context->gogo(),
context->function());
- tree ret = var_to_tree(bvar);
- if (ret == error_mark_node)
- return error_mark_node;
bool is_in_heap;
+ Location loc = this->location();
if (this->variable_->is_variable())
is_in_heap = this->variable_->var_value()->is_in_heap();
else if (this->variable_->is_result_variable())
is_in_heap = this->variable_->result_var_value()->is_in_heap();
else
go_unreachable();
+
+ Bexpression* ret = context->backend()->var_expression(bvar, loc);
if (is_in_heap)
- {
- ret = build_fold_indirect_ref_loc(this->location().gcc_location(), ret);
- TREE_THIS_NOTRAP(ret) = 1;
- }
- return ret;
+ ret = context->backend()->indirect_expression(ret, true, loc);
+ return expr_to_tree(ret);
}
// Ast dump for variable expression.
@@ -1043,23 +1004,24 @@ Temporary_reference_expression::do_address_taken(bool)
tree
Temporary_reference_expression::do_get_tree(Translate_context* context)
{
+ Gogo* gogo = context->gogo();
Bvariable* bvar = this->statement_->get_backend_variable(context);
+ Bexpression* ret = gogo->backend()->var_expression(bvar, this->location());
- // The gcc backend can't represent the same set of recursive types
+ // The backend can't always represent the same set of recursive types
// that the Go frontend can. In some cases this means that a
// temporary variable won't have the right backend type. Correct
// that here by adding a type cast. We need to use base() to push
// the circularity down one level.
- tree ret = var_to_tree(bvar);
+ Type* stype = this->statement_->type();
if (!this->is_lvalue_
- && POINTER_TYPE_P(TREE_TYPE(ret))
- && VOID_TYPE_P(TREE_TYPE(TREE_TYPE(ret))))
+ && stype->has_pointer()
+ && stype->deref()->is_void_type())
{
- Btype* type_btype = this->type()->base()->get_backend(context->gogo());
- tree type_tree = type_to_tree(type_btype);
- ret = fold_convert_loc(this->location().gcc_location(), type_tree, ret);
+ Btype* btype = this->type()->base()->get_backend(gogo);
+ ret = gogo->backend()->convert_expression(btype, ret, this->location());
}
- return ret;
+ return expr_to_tree(ret);
}
// Ast dump for temporary reference.
@@ -1266,7 +1228,7 @@ Func_expression::do_type()
// Get the tree for the code of a function expression.
-tree
+Bexpression*
Func_expression::get_code_pointer(Gogo* gogo, Named_object* no, Location loc)
{
Function_type* fntype;
@@ -1284,25 +1246,18 @@ Func_expression::get_code_pointer(Gogo* gogo, Named_object* no, Location loc)
error_at(loc,
"invalid use of special builtin function %qs; must be called",
no->message_name().c_str());
- return error_mark_node;
+ return gogo->backend()->error_expression();
}
- tree id = no->get_id(gogo);
- if (id == error_mark_node)
- return error_mark_node;
-
- tree fndecl;
+ Bfunction* fndecl;
if (no->is_function())
- fndecl = no->func_value()->get_or_make_decl(gogo, no, id);
+ fndecl = no->func_value()->get_or_make_decl(gogo, no);
else if (no->is_function_declaration())
- fndecl = no->func_declaration_value()->get_or_make_decl(gogo, no, id);
+ fndecl = no->func_declaration_value()->get_or_make_decl(gogo, no);
else
go_unreachable();
- if (fndecl == error_mark_node)
- return error_mark_node;
-
- return build_fold_addr_expr_loc(loc.gcc_location(), fndecl);
+ return gogo->backend()->function_code_expression(fndecl, loc);
}
// Get the tree for a function expression. This is used when we take
@@ -1539,8 +1494,10 @@ class Func_code_reference_expression : public Expression
tree
Func_code_reference_expression::do_get_tree(Translate_context* context)
{
- return Func_expression::get_code_pointer(context->gogo(), this->function_,
- this->location());
+ Bexpression* ret =
+ Func_expression::get_code_pointer(context->gogo(), this->function_,
+ this->location());
+ return expr_to_tree(ret);
}
// Make a reference to the code of a function.
@@ -2001,21 +1958,18 @@ Integer_expression::do_check_types(Gogo*)
tree
Integer_expression::do_get_tree(Translate_context* context)
{
- Gogo* gogo = context->gogo();
- tree type;
+ Type* resolved_type = NULL;
if (this->type_ != NULL && !this->type_->is_abstract())
- type = type_to_tree(this->type_->get_backend(gogo));
+ resolved_type = this->type_;
else if (this->type_ != NULL && this->type_->float_type() != NULL)
{
// We are converting to an abstract floating point type.
- Type* ftype = Type::lookup_float_type("float64");
- type = type_to_tree(ftype->get_backend(gogo));
+ resolved_type = Type::lookup_float_type("float64");
}
else if (this->type_ != NULL && this->type_->complex_type() != NULL)
{
// We are converting to an abstract complex type.
- Type* ctype = Type::lookup_complex_type("complex128");
- type = type_to_tree(ctype->get_backend(gogo));
+ resolved_type = Type::lookup_complex_type("complex128");
}
else
{
@@ -2026,16 +1980,23 @@ Integer_expression::do_get_tree(Translate_context* context)
int bits = mpz_sizeinbase(this->val_, 2);
Type* int_type = Type::lookup_integer_type("int");
if (bits < int_type->integer_type()->bits())
- type = type_to_tree(int_type->get_backend(gogo));
+ resolved_type = int_type;
else if (bits < 64)
- {
- Type* t = Type::lookup_integer_type("int64");
- type = type_to_tree(t->get_backend(gogo));
- }
+ resolved_type = Type::lookup_integer_type("int64");
else
- type = long_long_integer_type_node;
+ {
+ if (!saw_errors())
+ error_at(this->location(),
+ "unknown type for large integer constant");
+ Bexpression* ret = context->gogo()->backend()->error_expression();
+ return expr_to_tree(ret);
+ }
}
- return Expression::integer_constant_tree(this->val_, type);
+ Numeric_constant nc;
+ nc.set_int(resolved_type, this->val_);
+ Bexpression* ret =
+ Expression::backend_numeric_constant_expression(context, &nc);
+ return expr_to_tree(ret);
}
// Write VAL to export data.
@@ -2289,24 +2250,32 @@ Float_expression::do_check_types(Gogo*)
tree
Float_expression::do_get_tree(Translate_context* context)
{
- Gogo* gogo = context->gogo();
- tree type;
+ Type* resolved_type;
if (this->type_ != NULL && !this->type_->is_abstract())
- type = type_to_tree(this->type_->get_backend(gogo));
+ resolved_type = this->type_;
else if (this->type_ != NULL && this->type_->integer_type() != NULL)
{
// We have an abstract integer type. We just hope for the best.
- type = type_to_tree(Type::lookup_integer_type("int")->get_backend(gogo));
+ resolved_type = Type::lookup_integer_type("int");
+ }
+ else if (this->type_ != NULL && this->type_->complex_type() != NULL)
+ {
+ // We are converting to an abstract complex type.
+ resolved_type = Type::lookup_complex_type("complex128");
}
else
{
// If we still have an abstract type here, then this is being
// used in a constant expression which didn't get reduced. We
// just use float64 and hope for the best.
- Type* ft = Type::lookup_float_type("float64");
- type = type_to_tree(ft->get_backend(gogo));
+ resolved_type = Type::lookup_float_type("float64");
}
- return Expression::float_constant_tree(this->val_, type);
+
+ Numeric_constant nc;
+ nc.set_float(resolved_type, this->val_);
+ Bexpression* ret =
+ Expression::backend_numeric_constant_expression(context, &nc);
+ return expr_to_tree(ret);
}
// Write a floating point number to a string dump.
@@ -2466,19 +2435,32 @@ Complex_expression::do_check_types(Gogo*)
tree
Complex_expression::do_get_tree(Translate_context* context)
{
- Gogo* gogo = context->gogo();
- tree type;
+ Type* resolved_type;
if (this->type_ != NULL && !this->type_->is_abstract())
- type = type_to_tree(this->type_->get_backend(gogo));
+ resolved_type = this->type_;
+ else if (this->type_ != NULL && this->type_->integer_type() != NULL)
+ {
+ // We are converting to an abstract integer type.
+ resolved_type = Type::lookup_integer_type("int");
+ }
+ else if (this->type_ != NULL && this->type_->float_type() != NULL)
+ {
+ // We are converting to an abstract float type.
+ resolved_type = Type::lookup_float_type("float64");
+ }
else
{
// If we still have an abstract type here, this this is being
// used in a constant expression which didn't get reduced. We
// just use complex128 and hope for the best.
- Type* ct = Type::lookup_complex_type("complex128");
- type = type_to_tree(ct->get_backend(gogo));
+ resolved_type = Type::lookup_complex_type("complex128");
}
- return Expression::complex_constant_tree(this->real_, this->imag_, type);
+
+ Numeric_constant nc;
+ nc.set_complex(resolved_type, this->real_, this->imag_);
+ Bexpression* ret =
+ Expression::backend_numeric_constant_expression(context, &nc);
+ return expr_to_tree(ret);
}
// Write REAL/IMAG to export data.
@@ -3077,8 +3059,7 @@ class Type_conversion_expression : public Expression
do_lower(Gogo*, Named_object*, Statement_inserter*, int);
bool
- do_is_constant() const
- { return this->expr_->is_constant(); }
+ do_is_constant() const;
bool
do_numeric_constant_value(Numeric_constant*) const;
@@ -3220,6 +3201,27 @@ Type_conversion_expression::do_lower(Gogo*, Named_object*,
return this;
}
+// Return whether a type conversion is a constant.
+
+bool
+Type_conversion_expression::do_is_constant() const
+{
+ if (!this->expr_->is_constant())
+ return false;
+
+ // A conversion to a type that may not be used as a constant is not
+ // a constant. For example, []byte(nil).
+ Type* type = this->type_;
+ if (type->integer_type() == NULL
+ && type->float_type() == NULL
+ && type->complex_type() == NULL
+ && !type->is_boolean_type()
+ && !type->is_string_type())
+ return false;
+
+ return true;
+}
+
// Return the constant numeric value if there is one.
bool
@@ -3349,14 +3351,11 @@ Type_conversion_expression::do_get_tree(Translate_context* context)
return se->get_tree(context);
}
- static tree int_to_string_fndecl;
- ret = Gogo::call_builtin(&int_to_string_fndecl,
- this->location(),
- "__go_int_to_string",
- 1,
- type_tree,
- int_type_tree,
- expr_tree);
+ Expression* i2s_expr =
+ Runtime::make_call(Runtime::INT_TO_STRING, this->location(), 1,
+ this->expr_);
+ i2s_expr = Expression::make_cast(type, i2s_expr, this->location());
+ ret = i2s_expr->get_tree(context);
}
else if (type->is_string_type() && expr_type->is_slice_type())
{
@@ -3406,29 +3405,20 @@ Type_conversion_expression::do_get_tree(Translate_context* context)
{
Type* e = type->array_type()->element_type()->forwarded();
go_assert(e->integer_type() != NULL);
+
+ Expression* s2a_expr;
if (e->integer_type()->is_byte())
- {
- tree string_to_byte_array_fndecl = NULL_TREE;
- ret = Gogo::call_builtin(&string_to_byte_array_fndecl,
- this->location(),
- "__go_string_to_byte_array",
- 1,
- type_tree,
- TREE_TYPE(expr_tree),
- expr_tree);
- }
+ s2a_expr = Runtime::make_call(Runtime::STRING_TO_BYTE_ARRAY,
+ this->location(), 1, this->expr_);
else
{
go_assert(e->integer_type()->is_rune());
- tree string_to_int_array_fndecl = NULL_TREE;
- ret = Gogo::call_builtin(&string_to_int_array_fndecl,
- this->location(),
- "__go_string_to_int_array",
- 1,
- type_tree,
- TREE_TYPE(expr_tree),
- expr_tree);
+ s2a_expr = Runtime::make_call(Runtime::STRING_TO_INT_ARRAY,
+ this->location(), 1, this->expr_);
}
+ s2a_expr = Expression::make_unsafe_cast(type, s2a_expr,
+ this->location());
+ ret = s2a_expr->get_tree(context);
}
else if ((type->is_unsafe_pointer_type()
&& expr_type->points_to() != NULL)
@@ -3643,7 +3633,8 @@ class Unary_expression : public Expression
public:
Unary_expression(Operator op, Expression* expr, Location location)
: Expression(EXPRESSION_UNARY, location),
- op_(op), escapes_(true), create_temp_(false), expr_(expr)
+ op_(op), escapes_(true), create_temp_(false), expr_(expr),
+ issue_nil_check_(false)
{ }
// Return the operator.
@@ -3729,6 +3720,10 @@ class Unary_expression : public Expression
void
do_dump_expression(Ast_dump_context*) const;
+ void
+ do_issue_nil_check()
+ { this->issue_nil_check_ = (this->op_ == OPERATOR_MULT); }
+
private:
// The unary operator to apply.
Operator op_;
@@ -3740,6 +3735,9 @@ class Unary_expression : public Expression
bool create_temp_;
// The operand.
Expression* expr_;
+ // Whether or not to issue a nil check for this expression if its address
+ // is being taken.
+ bool issue_nil_check_;
};
// If we are taking the address of a composite literal, and the
@@ -4117,7 +4115,10 @@ Unary_expression::do_check_types(Gogo*)
this->report_error(_("invalid operand for unary %<&%>"));
}
else
- this->expr_->address_taken(this->escapes_);
+ {
+ this->expr_->address_taken(this->escapes_);
+ this->expr_->issue_nil_check();
+ }
break;
case OPERATOR_MULT:
@@ -4287,12 +4288,13 @@ Unary_expression::do_get_tree(Translate_context* context)
// If we are dereferencing the pointer to a large struct, we
// need to check for nil. We don't bother to check for small
// structs because we expect the system to crash on a nil
- // pointer dereference.
+ // pointer dereference. However, if we know the address of this
+ // expression is being taken, we must always check for nil.
tree target_type_tree = TREE_TYPE(TREE_TYPE(expr));
if (!VOID_TYPE_P(target_type_tree))
{
HOST_WIDE_INT s = int_size_in_bytes(target_type_tree);
- if (s == -1 || s >= 4096)
+ if (s == -1 || s >= 4096 || this->issue_nil_check_)
{
if (!DECL_P(expr))
expr = save_expr(expr);
@@ -5608,6 +5610,15 @@ Binary_expression::do_determine_type(const Type_context* context)
subcontext.type = NULL;
}
+ if (this->op_ == OPERATOR_ANDAND || this->op_ == OPERATOR_OROR)
+ {
+ // For a logical operation, the context does not determine the
+ // types of the operands. The operands must be some boolean
+ // type but if the context has a boolean type they do not
+ // inherit it. See http://golang.org/issue/3924.
+ subcontext.type = NULL;
+ }
+
// Set the context for the left hand operand.
if (is_shift_op)
{
@@ -5989,6 +6000,43 @@ Binary_expression::do_get_tree(Translate_context* context)
right);
}
+ // For complex division Go wants slightly different results than the
+ // GCC library provides, so we have our own runtime routine.
+ if (this->op_ == OPERATOR_DIV && this->left_->type()->complex_type() != NULL)
+ {
+ const char *name;
+ tree *pdecl;
+ Type* ctype;
+ static tree complex64_div_decl;
+ static tree complex128_div_decl;
+ switch (this->left_->type()->complex_type()->bits())
+ {
+ case 64:
+ name = "__go_complex64_div";
+ pdecl = &complex64_div_decl;
+ ctype = Type::lookup_complex_type("complex64");
+ break;
+ case 128:
+ name = "__go_complex128_div";
+ pdecl = &complex128_div_decl;
+ ctype = Type::lookup_complex_type("complex128");
+ break;
+ default:
+ go_unreachable();
+ }
+ Btype* cbtype = ctype->get_backend(gogo);
+ tree ctype_tree = type_to_tree(cbtype);
+ return Gogo::call_builtin(pdecl,
+ this->location(),
+ name,
+ 2,
+ ctype_tree,
+ ctype_tree,
+ fold_convert_loc(gccloc, ctype_tree, left),
+ type,
+ fold_convert_loc(gccloc, ctype_tree, right));
+ }
+
tree compute_type = excess_precision_type(type);
if (compute_type != NULL_TREE)
{
@@ -6461,8 +6509,9 @@ Expression::comparison_tree(Translate_context* context, Type* result_type,
}
arg = fold_convert_loc(location.gcc_location(), ptr_type_node, arg);
- tree descriptor = right_type->type_descriptor_pointer(context->gogo(),
- location);
+ Bexpression* descriptor_bexpr =
+ right_type->type_descriptor_pointer(context->gogo(), location);
+ tree descriptor = expr_to_tree(descriptor_bexpr);
if (left_type->interface_type()->is_empty())
{
@@ -7213,6 +7262,15 @@ Builtin_call_expression::do_lower(Gogo* gogo, Named_object* function,
if (this->code_ == BUILTIN_OFFSETOF)
{
Expression* arg = this->one_arg();
+
+ if (arg->bound_method_expression() != NULL
+ || arg->interface_field_reference_expression() != NULL)
+ {
+ this->report_error(_("invalid use of method value as argument "
+ "of Offsetof"));
+ return this;
+ }
+
Field_reference_expression* farg = arg->field_reference_expression();
while (farg != NULL)
{
@@ -7222,7 +7280,8 @@ Builtin_call_expression::do_lower(Gogo* gogo, Named_object* function,
// it must not be reached through pointer indirections.
if (farg->expr()->deref() != farg->expr())
{
- this->report_error(_("argument of Offsetof implies indirection of an embedded field"));
+ this->report_error(_("argument of Offsetof implies "
+ "indirection of an embedded field"));
return this;
}
// Go up until we reach the original base.
@@ -7498,7 +7557,7 @@ Builtin_call_expression::check_int_value(Expression* e, bool is_length)
switch (nc.to_unsigned_long(&v))
{
case Numeric_constant::NC_UL_VALID:
- return true;
+ break;
case Numeric_constant::NC_UL_NOTINT:
error_at(e->location(), "non-integer %s argument to make",
is_length ? "len" : "cap");
@@ -7510,8 +7569,23 @@ Builtin_call_expression::check_int_value(Expression* e, bool is_length)
case Numeric_constant::NC_UL_BIG:
// We don't want to give a compile-time error for a 64-bit
// value on a 32-bit target.
- return true;
+ break;
}
+
+ mpz_t val;
+ if (!nc.to_int(&val))
+ go_unreachable();
+ int bits = mpz_sizeinbase(val, 2);
+ mpz_clear(val);
+ Type* int_type = Type::lookup_integer_type("int");
+ if (bits >= int_type->integer_type()->bits())
+ {
+ error_at(e->location(), "%s argument too large for make",
+ is_length ? "len" : "cap");
+ return false;
+ }
+
+ return true;
}
if (e->type()->integer_type() != NULL)
@@ -7617,6 +7691,8 @@ Find_call_expression::expression(Expression** pexpr)
bool
Builtin_call_expression::do_is_constant() const
{
+ if (this->is_error_expression())
+ return true;
switch (this->code_)
{
case BUILTIN_LEN:
@@ -9766,14 +9842,8 @@ Call_expression::do_get_tree(Translate_context* context)
}
tree fntype_tree = type_to_tree(fntype->get_backend(gogo));
- if (fntype_tree == error_mark_node)
- return error_mark_node;
- go_assert(POINTER_TYPE_P(fntype_tree));
- if (TREE_TYPE(fntype_tree) == error_mark_node)
- return error_mark_node;
- go_assert(TREE_CODE(TREE_TYPE(fntype_tree)) == RECORD_TYPE);
- tree fnfield_type = TREE_TYPE(TYPE_FIELDS(TREE_TYPE(fntype_tree)));
- if (fnfield_type == error_mark_node)
+ tree fnfield_type = type_to_tree(fntype->get_backend_fntype(gogo));
+ if (fntype_tree == error_mark_node || fnfield_type == error_mark_node)
return error_mark_node;
go_assert(FUNCTION_POINTER_TYPE_P(fnfield_type));
tree rettype = TREE_TYPE(TREE_TYPE(fnfield_type));
@@ -9785,7 +9855,7 @@ Call_expression::do_get_tree(Translate_context* context)
if (func != NULL)
{
Named_object* no = func->named_object();
- fn = Func_expression::get_code_pointer(gogo, no, location);
+ fn = expr_to_tree(Func_expression::get_code_pointer(gogo, no, location));
if (!has_closure)
closure_tree = NULL_TREE;
else
@@ -10180,7 +10250,9 @@ Index_expression::do_traverse(Traverse* traverse)
if (Expression::traverse(&this->left_, traverse) == TRAVERSE_EXIT
|| Expression::traverse(&this->start_, traverse) == TRAVERSE_EXIT
|| (this->end_ != NULL
- && Expression::traverse(&this->end_, traverse) == TRAVERSE_EXIT))
+ && Expression::traverse(&this->end_, traverse) == TRAVERSE_EXIT)
+ || (this->cap_ != NULL
+ && Expression::traverse(&this->cap_, traverse) == TRAVERSE_EXIT))
return TRAVERSE_EXIT;
return TRAVERSE_CONTINUE;
}
@@ -10195,6 +10267,7 @@ Index_expression::do_lower(Gogo*, Named_object*, Statement_inserter*, int)
Expression* left = this->left_;
Expression* start = this->start_;
Expression* end = this->end_;
+ Expression* cap = this->cap_;
Type* type = left->type();
if (type->is_error())
@@ -10205,20 +10278,27 @@ Index_expression::do_lower(Gogo*, Named_object*, Statement_inserter*, int)
return Expression::make_error(location);
}
else if (type->array_type() != NULL)
- return Expression::make_array_index(left, start, end, location);
+ return Expression::make_array_index(left, start, end, cap, location);
else if (type->points_to() != NULL
&& type->points_to()->array_type() != NULL
&& !type->points_to()->is_slice_type())
{
Expression* deref = Expression::make_unary(OPERATOR_MULT, left,
location);
- return Expression::make_array_index(deref, start, end, location);
+ return Expression::make_array_index(deref, start, end, cap, location);
}
else if (type->is_string_type())
- return Expression::make_string_index(left, start, end, location);
+ {
+ if (cap != NULL)
+ {
+ error_at(location, "invalid 3-index slice of string");
+ return Expression::make_error(location);
+ }
+ return Expression::make_string_index(left, start, end, location);
+ }
else if (type->map_type() != NULL)
{
- if (end != NULL)
+ if (end != NULL || cap != NULL)
{
error_at(location, "invalid slice of map");
return Expression::make_error(location);
@@ -10237,14 +10317,15 @@ Index_expression::do_lower(Gogo*, Named_object*, Statement_inserter*, int)
}
}
-// Write an indexed expression (expr[expr:expr] or expr[expr]) to a
-// dump context
+// Write an indexed expression
+// (expr[expr:expr:expr], expr[expr:expr] or expr[expr]) to a dump context.
void
Index_expression::dump_index_expression(Ast_dump_context* ast_dump_context,
const Expression* expr,
const Expression* start,
- const Expression* end)
+ const Expression* end,
+ const Expression* cap)
{
expr->dump_expression(ast_dump_context);
ast_dump_context->ostream() << "[";
@@ -10254,6 +10335,11 @@ Index_expression::dump_index_expression(Ast_dump_context* ast_dump_context,
ast_dump_context->ostream() << ":";
end->dump_expression(ast_dump_context);
}
+ if (cap != NULL)
+ {
+ ast_dump_context->ostream() << ":";
+ cap->dump_expression(ast_dump_context);
+ }
ast_dump_context->ostream() << "]";
}
@@ -10264,16 +10350,16 @@ Index_expression::do_dump_expression(Ast_dump_context* ast_dump_context)
const
{
Index_expression::dump_index_expression(ast_dump_context, this->left_,
- this->start_, this->end_);
+ this->start_, this->end_, this->cap_);
}
// Make an index expression.
Expression*
Expression::make_index(Expression* left, Expression* start, Expression* end,
- Location location)
+ Expression* cap, Location location)
{
- return new Index_expression(left, start, end, location);
+ return new Index_expression(left, start, end, cap, location);
}
// An array index. This is used for both indexing and slicing.
@@ -10282,9 +10368,9 @@ class Array_index_expression : public Expression
{
public:
Array_index_expression(Expression* array, Expression* start,
- Expression* end, Location location)
+ Expression* end, Expression* cap, Location location)
: Expression(EXPRESSION_ARRAY_INDEX, location),
- array_(array), start_(start), end_(end), type_(NULL)
+ array_(array), start_(start), end_(end), cap_(cap), type_(NULL)
{ }
protected:
@@ -10308,6 +10394,9 @@ class Array_index_expression : public Expression
(this->end_ == NULL
? NULL
: this->end_->copy()),
+ (this->cap_ == NULL
+ ? NULL
+ : this->cap_->copy()),
this->location());
}
@@ -10325,6 +10414,10 @@ class Array_index_expression : public Expression
do_address_taken(bool escapes)
{ this->array_->address_taken(escapes); }
+ void
+ do_issue_nil_check()
+ { this->array_->issue_nil_check(); }
+
tree
do_get_tree(Translate_context*);
@@ -10339,6 +10432,9 @@ class Array_index_expression : public Expression
// The end index of a slice. This may be NULL for a simple array
// index, or it may be a nil expression for the length of the array.
Expression* end_;
+ // The capacity argument of a slice. This may be NULL for an array index or
+ // slice.
+ Expression* cap_;
// The type of the expression.
Type* type_;
};
@@ -10357,6 +10453,11 @@ Array_index_expression::do_traverse(Traverse* traverse)
if (Expression::traverse(&this->end_, traverse) == TRAVERSE_EXIT)
return TRAVERSE_EXIT;
}
+ if (this->cap_ != NULL)
+ {
+ if (Expression::traverse(&this->cap_, traverse) == TRAVERSE_EXIT)
+ return TRAVERSE_EXIT;
+ }
return TRAVERSE_CONTINUE;
}
@@ -10396,6 +10497,8 @@ Array_index_expression::do_determine_type(const Type_context*)
this->start_->determine_type_no_context();
if (this->end_ != NULL)
this->end_->determine_type_no_context();
+ if (this->cap_ != NULL)
+ this->cap_->determine_type_no_context();
}
// Check types of an array index.
@@ -10418,6 +10521,14 @@ Array_index_expression::do_check_types(Gogo*)
&& (!this->end_->numeric_constant_value(&nc)
|| nc.to_unsigned_long(&v) == Numeric_constant::NC_UL_NOTINT))
this->report_error(_("slice end must be integer"));
+ if (this->cap_ != NULL
+ && this->cap_->type()->integer_type() == NULL
+ && !this->cap_->type()->is_error()
+ && !this->cap_->is_nil_expression()
+ && !this->cap_->is_error_expression()
+ && (!this->cap_->numeric_constant_value(&nc)
+ || nc.to_unsigned_long(&v) == Numeric_constant::NC_UL_NOTINT))
+ this->report_error(_("slice capacity must be integer"));
Array_type* array_type = this->array_->type()->array_type();
if (array_type == NULL)
@@ -10455,8 +10566,10 @@ Array_index_expression::do_check_types(Gogo*)
{
Numeric_constant enc;
mpz_t eval;
+ bool eval_valid = false;
if (this->end_->numeric_constant_value(&enc) && enc.to_int(&eval))
{
+ eval_valid = true;
if (mpz_sgn(eval) < 0
|| mpz_sizeinbase(eval, 2) >= int_bits
|| (lval_valid && mpz_cmp(eval, lval) > 0))
@@ -10466,8 +10579,37 @@ Array_index_expression::do_check_types(Gogo*)
}
else if (ival_valid && mpz_cmp(ival, eval) > 0)
this->report_error(_("inverted slice range"));
- mpz_clear(eval);
}
+
+ Numeric_constant cnc;
+ mpz_t cval;
+ if (this->cap_ != NULL
+ && this->cap_->numeric_constant_value(&cnc) && cnc.to_int(&cval))
+ {
+ if (mpz_sgn(cval) < 0
+ || mpz_sizeinbase(cval, 2) >= int_bits
+ || (lval_valid && mpz_cmp(cval, lval) > 0))
+ {
+ error_at(this->cap_->location(), "array index out of bounds");
+ this->set_is_error();
+ }
+ else if (ival_valid && mpz_cmp(ival, cval) > 0)
+ {
+ error_at(this->cap_->location(),
+ "invalid slice index: capacity less than start");
+ this->set_is_error();
+ }
+ else if (eval_valid && mpz_cmp(eval, cval) > 0)
+ {
+ error_at(this->cap_->location(),
+ "invalid slice index: capacity less than length");
+ this->set_is_error();
+ }
+ mpz_clear(cval);
+ }
+
+ if (eval_valid)
+ mpz_clear(eval);
}
if (ival_valid)
mpz_clear(ival);
@@ -10547,9 +10689,17 @@ Array_index_expression::do_get_tree(Translate_context* context)
capacity_tree = save_expr(capacity_tree);
}
+ tree cap_arg = capacity_tree;
+ if (this->cap_ != NULL)
+ {
+ cap_arg = this->cap_->get_tree(context);
+ if (cap_arg == error_mark_node)
+ return error_mark_node;
+ }
+
tree length_type = (length_tree != NULL_TREE
? TREE_TYPE(length_tree)
- : TREE_TYPE(capacity_tree));
+ : TREE_TYPE(cap_arg));
tree bad_index = boolean_false_node;
@@ -10621,6 +10771,29 @@ Array_index_expression::do_get_tree(Translate_context* context)
// Array slice.
+ if (this->cap_ != NULL)
+ {
+ if (!DECL_P(cap_arg))
+ cap_arg = save_expr(cap_arg);
+ if (!INTEGRAL_TYPE_P(TREE_TYPE(cap_arg)))
+ cap_arg = convert_to_integer(length_type, cap_arg);
+
+ bad_index = Expression::check_bounds(cap_arg, length_type, bad_index,
+ loc);
+ cap_arg = fold_convert_loc(loc.gcc_location(), length_type, cap_arg);
+
+ tree bad_cap = fold_build2_loc(loc.gcc_location(), TRUTH_OR_EXPR,
+ boolean_type_node,
+ fold_build2_loc(loc.gcc_location(),
+ LT_EXPR, boolean_type_node,
+ cap_arg, start_tree),
+ fold_build2_loc(loc.gcc_location(),
+ GT_EXPR, boolean_type_node,
+ cap_arg, capacity_tree));
+ bad_index = fold_build2_loc(loc.gcc_location(), TRUTH_OR_EXPR,
+ boolean_type_node, bad_index, bad_cap);
+ }
+
tree end_tree;
if (this->end_->is_nil_expression())
end_tree = length_tree;
@@ -10646,11 +10819,12 @@ Array_index_expression::do_get_tree(Translate_context* context)
end_tree, start_tree),
fold_build2_loc(loc.gcc_location(),
GT_EXPR, boolean_type_node,
- end_tree, capacity_tree));
+ end_tree, cap_arg));
bad_index = fold_build2_loc(loc.gcc_location(), TRUTH_OR_EXPR,
boolean_type_node, bad_index, bad_end);
}
+
Type* element_type = array_type->element_type();
tree element_type_tree = type_to_tree(element_type->get_backend(gogo));
if (element_type_tree == error_mark_node)
@@ -10674,8 +10848,7 @@ Array_index_expression::do_get_tree(Translate_context* context)
length_type, end_tree, start_tree);
tree result_capacity_tree = fold_build2_loc(loc.gcc_location(), MINUS_EXPR,
- length_type, capacity_tree,
- start_tree);
+ length_type, cap_arg, start_tree);
tree struct_tree = type_to_tree(this->type()->get_backend(gogo));
go_assert(TREE_CODE(struct_tree) == RECORD_TYPE);
@@ -10725,16 +10898,17 @@ Array_index_expression::do_dump_expression(Ast_dump_context* ast_dump_context)
const
{
Index_expression::dump_index_expression(ast_dump_context, this->array_,
- this->start_, this->end_);
+ this->start_, this->end_, this->cap_);
}
-// Make an array index expression. END may be NULL.
+// Make an array index expression. END and CAP may be NULL.
Expression*
Expression::make_array_index(Expression* array, Expression* start,
- Expression* end, Location location)
+ Expression* end, Expression* cap,
+ Location location)
{
- return new Array_index_expression(array, start, end, location);
+ return new Array_index_expression(array, start, end, cap, location);
}
// A string index. This is used for both indexing and slicing.
@@ -10839,11 +11013,20 @@ String_index_expression::do_determine_type(const Type_context*)
void
String_index_expression::do_check_types(Gogo*)
{
- if (this->start_->type()->integer_type() == NULL)
+ Numeric_constant nc;
+ unsigned long v;
+ if (this->start_->type()->integer_type() == NULL
+ && !this->start_->type()->is_error()
+ && (!this->start_->numeric_constant_value(&nc)
+ || nc.to_unsigned_long(&v) == Numeric_constant::NC_UL_NOTINT))
this->report_error(_("index must be integer"));
if (this->end_ != NULL
&& this->end_->type()->integer_type() == NULL
- && !this->end_->is_nil_expression())
+ && !this->end_->type()->is_error()
+ && !this->end_->is_nil_expression()
+ && !this->end_->is_error_expression()
+ && (!this->end_->numeric_constant_value(&nc)
+ || nc.to_unsigned_long(&v) == Numeric_constant::NC_UL_NOTINT))
this->report_error(_("slice end must be integer"));
std::string sval;
@@ -11003,8 +11186,8 @@ void
String_index_expression::do_dump_expression(Ast_dump_context* ast_dump_context)
const
{
- Index_expression::dump_index_expression(ast_dump_context, this->string_,
- this->start_, this->end_);
+ Index_expression::dump_index_expression(ast_dump_context, this->string_,
+ this->start_, this->end_, NULL);
}
// Make a string index expression. END may be NULL.
@@ -11231,8 +11414,8 @@ void
Map_index_expression::do_dump_expression(Ast_dump_context* ast_dump_context)
const
{
- Index_expression::dump_index_expression(ast_dump_context,
- this->map_, this->index_, NULL);
+ Index_expression::dump_index_expression(ast_dump_context, this->map_,
+ this->index_, NULL, NULL);
}
// Make a map index expression.
@@ -11315,7 +11498,7 @@ Field_reference_expression::do_lower(Gogo* gogo, Named_object* function,
}
Expression* e = Expression::make_composite_literal(array_type, 0, false,
- bytes, loc);
+ bytes, false, loc);
Variable* var = new Variable(array_type, e, true, false, false, loc);
@@ -13187,7 +13370,8 @@ Map_construction_expression::do_get_tree(Translate_context* context)
valaddr = build_fold_addr_expr(tmp);
}
- tree descriptor = mt->map_descriptor_pointer(gogo, loc);
+ Bexpression* bdescriptor = mt->map_descriptor_pointer(gogo, loc);
+ tree descriptor = expr_to_tree(bdescriptor);
tree type_tree = type_to_tree(this->type_->get_backend(gogo));
if (type_tree == error_mark_node)
@@ -13258,9 +13442,11 @@ class Composite_literal_expression : public Parser_expression
{
public:
Composite_literal_expression(Type* type, int depth, bool has_keys,
- Expression_list* vals, Location location)
+ Expression_list* vals, bool all_are_names,
+ Location location)
: Parser_expression(EXPRESSION_COMPOSITE_LITERAL, location),
- type_(type), depth_(depth), vals_(vals), has_keys_(has_keys)
+ type_(type), depth_(depth), vals_(vals), has_keys_(has_keys),
+ all_are_names_(all_are_names)
{ }
protected:
@@ -13278,6 +13464,7 @@ class Composite_literal_expression : public Parser_expression
(this->vals_ == NULL
? NULL
: this->vals_->copy()),
+ this->all_are_names_,
this->location());
}
@@ -13307,6 +13494,9 @@ class Composite_literal_expression : public Parser_expression
// If this is true, then VALS_ is a list of pairs: a key and a
// value. In an array initializer, a missing key will be NULL.
bool has_keys_;
+ // If this is true, then HAS_KEYS_ is true, and every key is a
+ // simple identifier.
+ bool all_are_names_;
};
// Traversal.
@@ -13314,10 +13504,52 @@ class Composite_literal_expression : public Parser_expression
int
Composite_literal_expression::do_traverse(Traverse* traverse)
{
- if (this->vals_ != NULL
- && this->vals_->traverse(traverse) == TRAVERSE_EXIT)
+ if (Type::traverse(this->type_, traverse) == TRAVERSE_EXIT)
return TRAVERSE_EXIT;
- return Type::traverse(this->type_, traverse);
+
+ // If this is a struct composite literal with keys, then the keys
+ // are field names, not expressions. We don't want to traverse them
+ // in that case. If we do, we can give an erroneous error "variable
+ // initializer refers to itself." See bug482.go in the testsuite.
+ if (this->has_keys_ && this->vals_ != NULL)
+ {
+ // The type may not be resolvable at this point.
+ Type* type = this->type_;
+ while (true)
+ {
+ if (type->classification() == Type::TYPE_NAMED)
+ type = type->named_type()->real_type();
+ else if (type->classification() == Type::TYPE_FORWARD)
+ {
+ Type* t = type->forwarded();
+ if (t == type)
+ break;
+ type = t;
+ }
+ else
+ break;
+ }
+
+ if (type->classification() == Type::TYPE_STRUCT)
+ {
+ Expression_list::iterator p = this->vals_->begin();
+ while (p != this->vals_->end())
+ {
+ // Skip key.
+ ++p;
+ go_assert(p != this->vals_->end());
+ if (Expression::traverse(&*p, traverse) == TRAVERSE_EXIT)
+ return TRAVERSE_EXIT;
+ ++p;
+ }
+ return TRAVERSE_CONTINUE;
+ }
+ }
+
+ if (this->vals_ != NULL)
+ return this->vals_->traverse(traverse);
+
+ return TRAVERSE_CONTINUE;
}
// Lower a generic composite literal into a specific version based on
@@ -13409,6 +13641,8 @@ Composite_literal_expression::lower_struct(Gogo* gogo, Type* type)
std::vector<Expression*> vals(field_count);
std::vector<int>* traverse_order = new(std::vector<int>);
Expression_list::const_iterator p = this->vals_->begin();
+ Expression* external_expr = NULL;
+ const Named_object* external_no = NULL;
while (p != this->vals_->end())
{
Expression* name_expr = *p;
@@ -13514,6 +13748,12 @@ Composite_literal_expression::lower_struct(Gogo* gogo, Type* type)
if (no != NULL)
{
+ if (no->package() != NULL && external_expr == NULL)
+ {
+ external_expr = name_expr;
+ external_no = no;
+ }
+
name = no->name();
// A predefined name won't be packed. If it starts with a
@@ -13563,6 +13803,23 @@ Composite_literal_expression::lower_struct(Gogo* gogo, Type* type)
traverse_order->push_back(index);
}
+ if (!this->all_are_names_)
+ {
+ // This is a weird case like bug462 in the testsuite.
+ if (external_expr == NULL)
+ error_at(this->location(), "unknown field in %qs literal",
+ (type->named_type() != NULL
+ ? type->named_type()->message_name().c_str()
+ : "unnamed struct"));
+ else
+ error_at(external_expr->location(), "unknown field %qs in %qs",
+ external_no->message_name().c_str(),
+ (type->named_type() != NULL
+ ? type->named_type()->message_name().c_str()
+ : "unnamed struct"));
+ return Expression::make_error(location);
+ }
+
Expression_list* list = new Expression_list;
list->reserve(field_count);
for (size_t i = 0; i < field_count; ++i)
@@ -13852,11 +14109,11 @@ Composite_literal_expression::do_dump_expression(
Expression*
Expression::make_composite_literal(Type* type, int depth, bool has_keys,
- Expression_list* vals,
+ Expression_list* vals, bool all_are_names,
Location location)
{
return new Composite_literal_expression(type, depth, has_keys, vals,
- location);
+ all_are_names, location);
}
// Return whether this expression is a composite literal.
@@ -14212,8 +14469,9 @@ class Type_descriptor_expression : public Expression
tree
do_get_tree(Translate_context* context)
{
- return this->type_->type_descriptor_pointer(context->gogo(),
- this->location());
+ Bexpression* ret = this->type_->type_descriptor_pointer(context->gogo(),
+ this->location());
+ return expr_to_tree(ret);
}
void
@@ -14468,8 +14726,9 @@ class Map_descriptor_expression : public Expression
tree
do_get_tree(Translate_context* context)
{
- return this->type_->map_descriptor_pointer(context->gogo(),
- this->location());
+ Bexpression* ret = this->type_->map_descriptor_pointer(context->gogo(),
+ this->location());
+ return expr_to_tree(ret);
}
void
diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h
index 95584f2748b..47ce4c0a1e5 100644
--- a/gcc/go/gofrontend/expressions.h
+++ b/gcc/go/gofrontend/expressions.h
@@ -232,19 +232,21 @@ class Expression
Named_object* function, Location);
// Make an index or slice expression. This is a parser expression
- // which represents LEFT[START:END]. END may be NULL, meaning an
- // index rather than a slice. At parse time we may not know the
- // type of LEFT. After parsing this is lowered to an array index, a
- // string index, or a map index.
+ // which represents LEFT[START:END:CAP]. END may be NULL, meaning an
+ // index rather than a slice. CAP may be NULL, meaning we use the default
+ // capacity of LEFT. At parse time we may not know the type of LEFT.
+ // After parsing this is lowered to an array index, a string index,
+ // or a map index.
static Expression*
make_index(Expression* left, Expression* start, Expression* end,
- Location);
+ Expression* cap, Location);
// Make an array index expression. END may be NULL, in which case
- // this is an lvalue.
+ // this is an lvalue. CAP may be NULL, in which case it defaults
+ // to cap(ARRAY).
static Expression*
make_array_index(Expression* array, Expression* start, Expression* end,
- Location);
+ Expression* cap, Location);
// Make a string index expression. END may be NULL. This is never
// an lvalue.
@@ -291,10 +293,13 @@ class Expression
make_unsafe_cast(Type*, Expression*, Location);
// Make a composite literal. The DEPTH parameter is how far down we
- // are in a list of composite literals with omitted types.
+ // are in a list of composite literals with omitted types. HAS_KEYS
+ // is true if the expression list has keys alternating with values.
+ // ALL_ARE_NAMES is true if all the keys could be struct field
+ // names.
static Expression*
make_composite_literal(Type*, int depth, bool has_keys, Expression_list*,
- Location);
+ bool all_are_names, Location);
// Make a struct composite literal.
static Expression*
@@ -608,6 +613,11 @@ class Expression
address_taken(bool escapes)
{ this->do_address_taken(escapes); }
+ // Note that a nil check must be issued for this expression.
+ void
+ issue_nil_check()
+ { this->do_issue_nil_check(); }
+
// Return whether this expression must be evaluated in order
// according to the order of evaluation rules. This is basically
// true of all expressions with side-effects.
@@ -652,17 +662,10 @@ class Expression
Type* left_type, tree left_tree, Type* right_type,
tree right_tree, Location);
- // Return a tree for the multi-precision integer VAL in TYPE.
- static tree
- integer_constant_tree(mpz_t val, tree type);
-
- // Return a tree for the floating point value VAL in TYPE.
- static tree
- float_constant_tree(mpfr_t val, tree type);
-
- // Return a tree for the complex value REAL/IMAG in TYPE.
- static tree
- complex_constant_tree(mpfr_t real, mpfr_t imag, tree type);
+ // Return the backend expression for the numeric constant VAL.
+ static Bexpression*
+ backend_numeric_constant_expression(Translate_context*,
+ Numeric_constant* val);
// Export the expression. This is only used for constants. It will
// be used for things like values of named constants and sizes of
@@ -744,6 +747,11 @@ class Expression
do_address_taken(bool)
{ }
+ // Child class implements issuing a nil check if the address is taken.
+ virtual void
+ do_issue_nil_check()
+ { }
+
// Child class implements whether this expression must be evaluated
// in order.
virtual bool
@@ -1518,8 +1526,8 @@ class Func_expression : public Expression
closure()
{ return this->closure_; }
- // Return a tree for the code for a function.
- static tree
+ // Return a backend expression for the code of a function.
+ static Bexpression*
get_code_pointer(Gogo*, Named_object* function, Location loc);
protected:
@@ -1676,9 +1684,9 @@ class Index_expression : public Parser_expression
{
public:
Index_expression(Expression* left, Expression* start, Expression* end,
- Location location)
+ Expression* cap, Location location)
: Parser_expression(EXPRESSION_INDEX, location),
- left_(left), start_(start), end_(end), is_lvalue_(false)
+ left_(left), start_(start), end_(end), cap_(cap), is_lvalue_(false)
{ }
// Record that this expression is an lvalue.
@@ -1687,10 +1695,11 @@ class Index_expression : public Parser_expression
{ this->is_lvalue_ = true; }
// Dump an index expression, i.e. an expression of the form
- // expr[expr] or expr[expr:expr], to a dump context.
+ // expr[expr], expr[expr:expr], or expr[expr:expr:expr] to a dump context.
static void
dump_index_expression(Ast_dump_context*, const Expression* expr,
- const Expression* start, const Expression* end);
+ const Expression* start, const Expression* end,
+ const Expression* cap);
protected:
int
@@ -1706,6 +1715,9 @@ class Index_expression : public Parser_expression
(this->end_ == NULL
? NULL
: this->end_->copy()),
+ (this->cap_ == NULL
+ ? NULL
+ : this->cap_->copy()),
this->location());
}
@@ -1719,6 +1731,9 @@ class Index_expression : public Parser_expression
void
do_dump_expression(Ast_dump_context*) const;
+ void
+ do_issue_nil_check()
+ { this->left_->issue_nil_check(); }
private:
// The expression being indexed.
Expression* left_;
@@ -1727,6 +1742,10 @@ class Index_expression : public Parser_expression
// The second index. This is NULL for an index, non-NULL for a
// slice.
Expression* end_;
+ // The capacity argument. This is NULL for indices and slices that use the
+ // default capacity, non-NULL for indices and slices that specify the
+ // capacity.
+ Expression* cap_;
// Whether this is being used as an l-value. We set this during the
// parse because map index expressions need to know.
bool is_lvalue_;
@@ -2005,6 +2024,10 @@ class Field_reference_expression : public Expression
do_address_taken(bool escapes)
{ this->expr_->address_taken(escapes); }
+ void
+ do_issue_nil_check()
+ { this->expr_->issue_nil_check(); }
+
tree
do_get_tree(Translate_context*);
diff --git a/gcc/go/gofrontend/gogo-tree.cc b/gcc/go/gofrontend/gogo-tree.cc
index 7813cc18822..3793b839b55 100644
--- a/gcc/go/gofrontend/gogo-tree.cc
+++ b/gcc/go/gofrontend/gogo-tree.cc
@@ -985,74 +985,6 @@ Gogo::write_globals()
delete[] vec;
}
-// Get a tree for the identifier for a named object.
-
-tree
-Named_object::get_id(Gogo* gogo)
-{
- go_assert(!this->is_variable() && !this->is_result_variable());
- std::string decl_name;
- if (this->is_function_declaration()
- && !this->func_declaration_value()->asm_name().empty())
- decl_name = this->func_declaration_value()->asm_name();
- else if (this->is_type()
- && Linemap::is_predeclared_location(this->type_value()->location()))
- {
- // We don't need the package name for builtin types.
- decl_name = Gogo::unpack_hidden_name(this->name_);
- }
- else
- {
- std::string package_name;
- if (this->package_ == NULL)
- package_name = gogo->package_name();
- else
- package_name = this->package_->package_name();
-
- // Note that this will be misleading if this is an unexported
- // method generated for an embedded imported type. In that case
- // the unexported method should have the package name of the
- // package from which it is imported, but we are going to give
- // it our package name. Fixing this would require knowing the
- // package name, but we only know the package path. It might be
- // better to use package paths here anyhow. This doesn't affect
- // the assembler code, because we always set that name in
- // Function::get_or_make_decl anyhow. FIXME.
-
- decl_name = package_name + '.' + Gogo::unpack_hidden_name(this->name_);
-
- Function_type* fntype;
- if (this->is_function())
- fntype = this->func_value()->type();
- else if (this->is_function_declaration())
- fntype = this->func_declaration_value()->type();
- else
- fntype = NULL;
- if (fntype != NULL && fntype->is_method())
- {
- decl_name.push_back('.');
- decl_name.append(fntype->receiver()->type()->mangled_name(gogo));
- }
- }
- if (this->is_type())
- {
- unsigned int index;
- const Named_object* in_function = this->type_value()->in_function(&index);
- if (in_function != NULL)
- {
- decl_name += '$' + Gogo::unpack_hidden_name(in_function->name());
- if (index > 0)
- {
- char buf[30];
- snprintf(buf, sizeof buf, "%u", index);
- decl_name += '$';
- decl_name += buf;
- }
- }
- }
- return get_identifier_from_string(decl_name);
-}
-
// Get a tree for a named object.
tree
@@ -1061,11 +993,12 @@ Named_object::get_tree(Gogo* gogo, Named_object* function)
if (this->tree_ != NULL_TREE)
return this->tree_;
- tree name;
- if (this->classification_ == NAMED_OBJECT_TYPE)
- name = NULL_TREE;
- else
- name = this->get_id(gogo);
+ if (Gogo::is_erroneous_name(this->name_))
+ {
+ this->tree_ = error_mark_node;
+ return error_mark_node;
+ }
+
tree decl;
switch (this->classification_)
{
@@ -1093,6 +1026,7 @@ Named_object::get_tree(Gogo* gogo, Named_object* function)
decl = error_mark_node;
else if (INTEGRAL_TYPE_P(TREE_TYPE(expr_tree)))
{
+ tree name = get_identifier_from_string(this->get_id(gogo));
decl = build_decl(named_constant->location().gcc_location(),
CONST_DECL, name, TREE_TYPE(expr_tree));
DECL_INITIAL(decl) = expr_tree;
@@ -1155,7 +1089,7 @@ Named_object::get_tree(Gogo* gogo, Named_object* function)
case NAMED_OBJECT_FUNC:
{
Function* func = this->u_.func_value;
- decl = func->get_or_make_decl(gogo, this, name);
+ decl = function_to_tree(func->get_or_make_decl(gogo, this));
if (decl != error_mark_node)
{
if (func->block() != NULL)
@@ -1280,123 +1214,12 @@ Variable::get_init_block(Gogo* gogo, Named_object* function, tree var_decl)
return block_tree;
}
-// Get a tree for a function decl.
-
-tree
-Function::get_or_make_decl(Gogo* gogo, Named_object* no, tree id)
-{
- if (this->fndecl_ == NULL_TREE)
- {
- tree functype = type_to_tree(this->type_->get_backend(gogo));
-
- if (functype != error_mark_node)
- {
- // The type of a function comes back as a pointer to a
- // struct whose first field is the function, but we want the
- // real function type for a function declaration.
- go_assert(POINTER_TYPE_P(functype)
- && TREE_CODE(TREE_TYPE(functype)) == RECORD_TYPE);
- functype = TREE_TYPE(TYPE_FIELDS(TREE_TYPE(functype)));
- go_assert(FUNCTION_POINTER_TYPE_P(functype));
- functype = TREE_TYPE(functype);
- }
-
- if (functype == error_mark_node)
- this->fndecl_ = error_mark_node;
- else
- {
- tree decl = build_decl(this->location().gcc_location(), FUNCTION_DECL,
- id, functype);
-
- this->fndecl_ = decl;
-
- if (no->package() != NULL)
- ;
- else if (this->enclosing_ != NULL || Gogo::is_thunk(no))
- ;
- else if (Gogo::unpack_hidden_name(no->name()) == "init"
- && !this->type_->is_method())
- ;
- else if (Gogo::unpack_hidden_name(no->name()) == "main"
- && gogo->is_main_package())
- TREE_PUBLIC(decl) = 1;
- // Methods have to be public even if they are hidden because
- // they can be pulled into type descriptors when using
- // anonymous fields.
- else if (!Gogo::is_hidden_name(no->name())
- || this->type_->is_method())
- {
- TREE_PUBLIC(decl) = 1;
- std::string pkgpath = gogo->pkgpath_symbol();
- if (this->type_->is_method()
- && Gogo::is_hidden_name(no->name())
- && Gogo::hidden_name_pkgpath(no->name()) != gogo->pkgpath())
- {
- // This is a method we created for an unexported
- // method of an imported embedded type. We need to
- // use the pkgpath of the imported package to avoid
- // a possible name collision. See bug478 for a test
- // case.
- pkgpath = Gogo::hidden_name_pkgpath(no->name());
- pkgpath = Gogo::pkgpath_for_symbol(pkgpath);
- }
-
- std::string asm_name = pkgpath;
- asm_name.append(1, '.');
- asm_name.append(Gogo::unpack_hidden_name(no->name()));
- if (this->type_->is_method())
- {
- asm_name.append(1, '.');
- Type* rtype = this->type_->receiver()->type();
- asm_name.append(rtype->mangled_name(gogo));
- }
- SET_DECL_ASSEMBLER_NAME(decl,
- get_identifier_from_string(asm_name));
- }
-
- // Why do we have to do this in the frontend?
- tree restype = TREE_TYPE(functype);
- tree resdecl =
- build_decl(this->location().gcc_location(), RESULT_DECL, NULL_TREE,
- restype);
- DECL_ARTIFICIAL(resdecl) = 1;
- DECL_IGNORED_P(resdecl) = 1;
- DECL_CONTEXT(resdecl) = decl;
- DECL_RESULT(decl) = resdecl;
-
- // If a function calls the predeclared recover function, we
- // can't inline it, because recover behaves differently in a
- // function passed directly to defer. If this is a recover
- // thunk that we built to test whether a function can be
- // recovered, we can't inline it, because that will mess up
- // our return address comparison.
- if (this->calls_recover_ || this->is_recover_thunk_)
- DECL_UNINLINABLE(decl) = 1;
-
- // If this is a thunk created to call a function which calls
- // the predeclared recover function, we need to disable
- // stack splitting for the thunk.
- if (this->is_recover_thunk_)
- {
- tree attr = get_identifier("__no_split_stack__");
- DECL_ATTRIBUTES(decl) = tree_cons(attr, NULL_TREE, NULL_TREE);
- }
-
- if (this->in_unique_section_)
- resolve_unique_section (decl, 0, 1);
-
- go_preserve_from_gc(decl);
- }
- }
- return this->fndecl_;
-}
-
-// Get a tree for a function declaration.
+// Get the backend representation.
-tree
-Function_declaration::get_or_make_decl(Gogo* gogo, Named_object* no, tree id)
+Bfunction*
+Function_declaration::get_or_make_decl(Gogo* gogo, Named_object* no)
{
- if (this->fndecl_ == NULL_TREE)
+ if (this->fndecl_ == NULL)
{
// Let Go code use an asm declaration to pick up a builtin
// function.
@@ -1406,58 +1229,46 @@ Function_declaration::get_or_make_decl(Gogo* gogo, Named_object* no, tree id)
builtin_functions.find(this->asm_name_);
if (p != builtin_functions.end())
{
- this->fndecl_ = p->second;
+ this->fndecl_ = tree_to_function(p->second);
return this->fndecl_;
}
}
- tree functype = type_to_tree(this->fntype_->get_backend(gogo));
-
- if (functype != error_mark_node)
- {
- // The type of a function comes back as a pointer to a
- // struct whose first field is the function, but we want the
- // real function type for a function declaration.
- go_assert(POINTER_TYPE_P(functype)
- && TREE_CODE(TREE_TYPE(functype)) == RECORD_TYPE);
- functype = TREE_TYPE(TYPE_FIELDS(TREE_TYPE(functype)));
- go_assert(FUNCTION_POINTER_TYPE_P(functype));
- functype = TREE_TYPE(functype);
- }
-
- tree decl;
- if (functype == error_mark_node)
- decl = error_mark_node;
- else
- {
- decl = build_decl(this->location().gcc_location(), FUNCTION_DECL, id,
- functype);
- TREE_PUBLIC(decl) = 1;
- DECL_EXTERNAL(decl) = 1;
+ std::string asm_name;
+ if (this->asm_name_.empty())
+ {
+ asm_name = (no->package() == NULL
+ ? gogo->pkgpath_symbol()
+ : no->package()->pkgpath_symbol());
+ asm_name.append(1, '.');
+ asm_name.append(Gogo::unpack_hidden_name(no->name()));
+ if (this->fntype_->is_method())
+ {
+ asm_name.append(1, '.');
+ Type* rtype = this->fntype_->receiver()->type();
+ asm_name.append(rtype->mangled_name(gogo));
+ }
+ }
- if (this->asm_name_.empty())
- {
- std::string asm_name = (no->package() == NULL
- ? gogo->pkgpath_symbol()
- : no->package()->pkgpath_symbol());
- asm_name.append(1, '.');
- asm_name.append(Gogo::unpack_hidden_name(no->name()));
- if (this->fntype_->is_method())
- {
- asm_name.append(1, '.');
- Type* rtype = this->fntype_->receiver()->type();
- asm_name.append(rtype->mangled_name(gogo));
- }
- SET_DECL_ASSEMBLER_NAME(decl,
- get_identifier_from_string(asm_name));
- }
- }
- this->fndecl_ = decl;
- go_preserve_from_gc(decl);
+ Btype* functype = this->fntype_->get_backend_fntype(gogo);
+ this->fndecl_ =
+ gogo->backend()->function(functype, no->get_id(gogo), asm_name,
+ true, true, true, false, false,
+ this->location());
}
+
return this->fndecl_;
}
+// Return the function's decl after it has been built.
+
+tree
+Function::get_decl() const
+{
+ go_assert(this->fndecl_ != NULL);
+ return function_to_tree(this->fndecl_);
+}
+
// We always pass the receiver to a method as a pointer. If the
// receiver is actually declared as a non-pointer type, then we copy
// the value into a local variable, so that it has the right type. In
@@ -1552,7 +1363,7 @@ Function::copy_parm_to_heap(Gogo* gogo, Named_object* no, tree var_decl)
void
Function::build_tree(Gogo* gogo, Named_object* named_function)
{
- tree fndecl = this->fndecl_;
+ tree fndecl = this->get_decl();
go_assert(fndecl != NULL_TREE);
tree params = NULL_TREE;
@@ -1790,7 +1601,7 @@ Function::build_defer_wrapper(Gogo* gogo, Named_object* named_function,
set = NULL_TREE;
else
set = fold_build2_loc(end_loc.gcc_location(), MODIFY_EXPR, void_type_node,
- DECL_RESULT(this->fndecl_), retval);
+ DECL_RESULT(this->get_decl()), retval);
tree ret_stmt = fold_build1_loc(end_loc.gcc_location(), RETURN_EXPR,
void_type_node, set);
append_to_statement_list(ret_stmt, &stmt_list);
@@ -1845,7 +1656,7 @@ Function::build_defer_wrapper(Gogo* gogo, Named_object* named_function,
retval = this->return_value(gogo, named_function, end_loc,
&stmt_list);
set = fold_build2_loc(end_loc.gcc_location(), MODIFY_EXPR, void_type_node,
- DECL_RESULT(this->fndecl_), retval);
+ DECL_RESULT(this->get_decl()), retval);
ret_stmt = fold_build1_loc(end_loc.gcc_location(), RETURN_EXPR,
void_type_node, set);
@@ -1863,7 +1674,7 @@ Function::build_defer_wrapper(Gogo* gogo, Named_object* named_function,
*fini = stmt_list;
}
-// Return the value to assign to DECL_RESULT(this->fndecl_). This may
+// Return the value to assign to DECL_RESULT(this->get_decl()). This may
// also add statements to STMT_LIST, which need to be executed before
// the assignment. This is used for a return statement with no
// explicit values.
@@ -1896,7 +1707,7 @@ Function::return_value(Gogo* gogo, Named_object* named_function,
}
else
{
- tree rettype = TREE_TYPE(DECL_RESULT(this->fndecl_));
+ tree rettype = TREE_TYPE(DECL_RESULT(this->get_decl()));
retval = create_tmp_var(rettype, "RESULT");
tree field = TYPE_FIELDS(rettype);
int index = 0;
@@ -2296,8 +2107,10 @@ Gogo::interface_method_table_for_type(const Interface_type* interface,
td_type = type;
else
td_type = Type::make_pointer_type(type);
- tree tdp = td_type->type_descriptor_pointer(this,
- Linemap::predeclared_location());
+
+ Location loc = Linemap::predeclared_location();
+ Bexpression* tdp_bexpr = td_type->type_descriptor_pointer(this, loc);
+ tree tdp = expr_to_tree(tdp_bexpr);
elt->value = fold_convert(const_ptr_type_node, tdp);
Named_type* nt = type->named_type();
@@ -2317,18 +2130,14 @@ Gogo::interface_method_table_for_type(const Interface_type* interface,
go_assert(m != NULL);
Named_object* no = m->named_object();
-
- tree fnid = no->get_id(this);
-
- tree fndecl;
+ Bfunction* bf;
if (no->is_function())
- fndecl = no->func_value()->get_or_make_decl(this, no, fnid);
+ bf = no->func_value()->get_or_make_decl(this, no);
else if (no->is_function_declaration())
- fndecl = no->func_declaration_value()->get_or_make_decl(this, no,
- fnid);
+ bf = no->func_declaration_value()->get_or_make_decl(this, no);
else
go_unreachable();
- fndecl = build_fold_addr_expr(fndecl);
+ tree fndecl = build_fold_addr_expr(function_to_tree(bf));
elt = pointers->quick_push(empty);
elt->index = size_int(i);
@@ -2347,10 +2156,11 @@ Gogo::interface_method_table_for_type(const Interface_type* interface,
TREE_CONSTANT(decl) = 1;
DECL_INITIAL(decl) = constructor;
- // If the interface type has hidden methods, then this is the only
- // definition of the table. Otherwise it is a comdat table which
- // may be defined in multiple packages.
- if (has_hidden_methods)
+ // If the interface type has hidden methods, and the table is for a
+ // named type, then this is the only definition of the table.
+ // Otherwise it is a comdat table which may be defined in multiple
+ // packages.
+ if (has_hidden_methods && type->named_type() != NULL)
TREE_PUBLIC(decl) = 1;
else
{
diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc
index 17cbb6b9b49..eebb75377fa 100644
--- a/gcc/go/gofrontend/gogo.cc
+++ b/gcc/go/gofrontend/gogo.cc
@@ -1192,6 +1192,27 @@ Gogo::record_interface_type(Interface_type* itype)
this->interface_types_.push_back(itype);
}
+// Return an erroneous name that indicates that an error has already
+// been reported.
+
+std::string
+Gogo::erroneous_name()
+{
+ static int erroneous_count;
+ char name[50];
+ snprintf(name, sizeof name, "$erroneous%d", erroneous_count);
+ ++erroneous_count;
+ return name;
+}
+
+// Return whether a name is an erroneous name.
+
+bool
+Gogo::is_erroneous_name(const std::string& name)
+{
+ return name.compare(0, 10, "$erroneous") == 0;
+}
+
// Return a name for a thunk object.
std::string
@@ -3299,7 +3320,8 @@ Function::Function(Function_type* type, Function* enclosing, Block* block,
closure_var_(NULL), block_(block), location_(location), labels_(),
local_type_count_(0), descriptor_(NULL), fndecl_(NULL), defer_stack_(NULL),
is_sink_(false), results_are_named_(false), nointerface_(false),
- calls_recover_(false), is_recover_thunk_(false), has_recover_thunk_(false),
+ is_unnamed_type_stub_method_(false), calls_recover_(false),
+ is_recover_thunk_(false), has_recover_thunk_(false),
in_unique_section_(false)
{
}
@@ -3798,6 +3820,81 @@ Function::import_func(Import* imp, std::string* pname,
*presults = results;
}
+// Get the backend representation.
+
+Bfunction*
+Function::get_or_make_decl(Gogo* gogo, Named_object* no)
+{
+ if (this->fndecl_ == NULL)
+ {
+ std::string asm_name;
+ bool is_visible = false;
+ if (no->package() != NULL)
+ ;
+ else if (this->enclosing_ != NULL || Gogo::is_thunk(no))
+ ;
+ else if (Gogo::unpack_hidden_name(no->name()) == "init"
+ && !this->type_->is_method())
+ ;
+ else if (Gogo::unpack_hidden_name(no->name()) == "main"
+ && gogo->is_main_package())
+ is_visible = true;
+ // Methods have to be public even if they are hidden because
+ // they can be pulled into type descriptors when using
+ // anonymous fields.
+ else if (!Gogo::is_hidden_name(no->name())
+ || this->type_->is_method())
+ {
+ if (!this->is_unnamed_type_stub_method_)
+ is_visible = true;
+ std::string pkgpath = gogo->pkgpath_symbol();
+ if (this->type_->is_method()
+ && Gogo::is_hidden_name(no->name())
+ && Gogo::hidden_name_pkgpath(no->name()) != gogo->pkgpath())
+ {
+ // This is a method we created for an unexported
+ // method of an imported embedded type. We need to
+ // use the pkgpath of the imported package to avoid
+ // a possible name collision. See bug478 for a test
+ // case.
+ pkgpath = Gogo::hidden_name_pkgpath(no->name());
+ pkgpath = Gogo::pkgpath_for_symbol(pkgpath);
+ }
+
+ asm_name = pkgpath;
+ asm_name.append(1, '.');
+ asm_name.append(Gogo::unpack_hidden_name(no->name()));
+ if (this->type_->is_method())
+ {
+ asm_name.append(1, '.');
+ Type* rtype = this->type_->receiver()->type();
+ asm_name.append(rtype->mangled_name(gogo));
+ }
+ }
+
+ // If a function calls the predeclared recover function, we
+ // can't inline it, because recover behaves differently in a
+ // function passed directly to defer. If this is a recover
+ // thunk that we built to test whether a function can be
+ // recovered, we can't inline it, because that will mess up
+ // our return address comparison.
+ bool is_inlinable = !(this->calls_recover_ || this->is_recover_thunk_);
+
+ // If this is a thunk created to call a function which calls
+ // the predeclared recover function, we need to disable
+ // stack splitting for the thunk.
+ bool disable_split_stack = this->is_recover_thunk_;
+
+ Btype* functype = this->type_->get_backend_fntype(gogo);
+ this->fndecl_ =
+ gogo->backend()->function(functype, no->get_id(gogo), asm_name,
+ is_visible, false, is_inlinable,
+ disable_split_stack,
+ this->in_unique_section_, this->location());
+ }
+ return this->fndecl_;
+}
+
// Class Block.
Block::Block(Block* enclosing, Location location)
@@ -5089,6 +5186,75 @@ Named_object::get_backend_variable(Gogo* gogo, Named_object* function)
go_unreachable();
}
+
+// Return the external identifier for this object.
+
+std::string
+Named_object::get_id(Gogo* gogo)
+{
+ go_assert(!this->is_variable() && !this->is_result_variable());
+ std::string decl_name;
+ if (this->is_function_declaration()
+ && !this->func_declaration_value()->asm_name().empty())
+ decl_name = this->func_declaration_value()->asm_name();
+ else if (this->is_type()
+ && Linemap::is_predeclared_location(this->type_value()->location()))
+ {
+ // We don't need the package name for builtin types.
+ decl_name = Gogo::unpack_hidden_name(this->name_);
+ }
+ else
+ {
+ std::string package_name;
+ if (this->package_ == NULL)
+ package_name = gogo->package_name();
+ else
+ package_name = this->package_->package_name();
+
+ // Note that this will be misleading if this is an unexported
+ // method generated for an embedded imported type. In that case
+ // the unexported method should have the package name of the
+ // package from which it is imported, but we are going to give
+ // it our package name. Fixing this would require knowing the
+ // package name, but we only know the package path. It might be
+ // better to use package paths here anyhow. This doesn't affect
+ // the assembler code, because we always set that name in
+ // Function::get_or_make_decl anyhow. FIXME.
+
+ decl_name = package_name + '.' + Gogo::unpack_hidden_name(this->name_);
+
+ Function_type* fntype;
+ if (this->is_function())
+ fntype = this->func_value()->type();
+ else if (this->is_function_declaration())
+ fntype = this->func_declaration_value()->type();
+ else
+ fntype = NULL;
+ if (fntype != NULL && fntype->is_method())
+ {
+ decl_name.push_back('.');
+ decl_name.append(fntype->receiver()->type()->mangled_name(gogo));
+ }
+ }
+ if (this->is_type())
+ {
+ unsigned int index;
+ const Named_object* in_function = this->type_value()->in_function(&index);
+ if (in_function != NULL)
+ {
+ decl_name += '$' + Gogo::unpack_hidden_name(in_function->name());
+ if (index > 0)
+ {
+ char buf[30];
+ snprintf(buf, sizeof buf, "%u", index);
+ decl_name += '$';
+ decl_name += buf;
+ }
+ }
+ }
+ return decl_name;
+}
+
// Class Bindings.
Bindings::Bindings(Bindings* enclosing)
diff --git a/gcc/go/gofrontend/gogo.h b/gcc/go/gofrontend/gogo.h
index 6a87f2d562c..31b258d62d6 100644
--- a/gcc/go/gofrontend/gogo.h
+++ b/gcc/go/gofrontend/gogo.h
@@ -48,6 +48,7 @@ class Bstatement;
class Bblock;
class Bvariable;
class Blabel;
+class Bfunction;
// This file declares the basic classes used to hold the internal
// representation of Go which is built by the parser.
@@ -387,6 +388,16 @@ class Gogo
void
mark_locals_used();
+ // Return a name to use for an error case. This should only be used
+ // after reporting an error, and is used to avoid useless knockon
+ // errors.
+ static std::string
+ erroneous_name();
+
+ // Return whether the name indicates an error.
+ static bool
+ is_erroneous_name(const std::string&);
+
// Return a name to use for a thunk function. A thunk function is
// one we create during the compilation, for a go statement or a
// defer statement or a method expression.
@@ -942,6 +953,15 @@ class Function
this->nointerface_ = true;
}
+ // Record that this function is a stub method created for an unnamed
+ // type.
+ void
+ set_is_unnamed_type_stub_method()
+ {
+ go_assert(this->is_method());
+ this->is_unnamed_type_stub_method_ = true;
+ }
+
// Add a new field to the closure variable.
void
add_closure_field(Named_object* var, Location loc)
@@ -1079,17 +1099,13 @@ class Function
this->descriptor_ = descriptor;
}
- // Return the function's decl given an identifier.
- tree
- get_or_make_decl(Gogo*, Named_object*, tree id);
+ // Return the backend representation.
+ Bfunction*
+ get_or_make_decl(Gogo*, Named_object*);
// Return the function's decl after it has been built.
tree
- get_decl() const
- {
- go_assert(this->fndecl_ != NULL);
- return this->fndecl_;
- }
+ get_decl() const;
// Set the function decl to hold a tree of the function code.
void
@@ -1160,7 +1176,7 @@ class Function
// The function descriptor, if any.
Expression* descriptor_;
// The function decl.
- tree fndecl_;
+ Bfunction* fndecl_;
// The defer stack variable. A pointer to this variable is used to
// distinguish the defer stack for one function from another. This
// is NULL unless we actually need a defer stack.
@@ -1171,6 +1187,9 @@ class Function
bool results_are_named_ : 1;
// True if this method should not be included in the type descriptor.
bool nointerface_ : 1;
+ // True if this function is a stub method created for an unnamed
+ // type.
+ bool is_unnamed_type_stub_method_ : 1;
// True if this function calls the predeclared recover function.
bool calls_recover_ : 1;
// True if this a thunk built for a function which calls recover.
@@ -1255,9 +1274,9 @@ class Function_declaration
has_descriptor() const
{ return this->descriptor_ != NULL; }
- // Return a decl for the function given an identifier.
- tree
- get_or_make_decl(Gogo*, Named_object*, tree id);
+ // Return a backend representation.
+ Bfunction*
+ get_or_make_decl(Gogo*, Named_object*);
// If there is a descriptor, build it into the backend
// representation.
@@ -1280,7 +1299,7 @@ class Function_declaration
// The function descriptor, if any.
Expression* descriptor_;
// The function decl if needed.
- tree fndecl_;
+ Bfunction* fndecl_;
};
// A variable.
@@ -2171,8 +2190,8 @@ class Named_object
Bvariable*
get_backend_variable(Gogo*, Named_object* function);
- // Return a tree for the external identifier for this object.
- tree
+ // Return the external identifier for this object.
+ std::string
get_id(Gogo*);
// Return a tree representing this object.
diff --git a/gcc/go/gofrontend/import.h b/gcc/go/gofrontend/import.h
index c6844cda8a5..9917937e4d3 100644
--- a/gcc/go/gofrontend/import.h
+++ b/gcc/go/gofrontend/import.h
@@ -149,6 +149,11 @@ class Import
location() const
{ return this->location_; }
+ // Return the package we are importing.
+ Package*
+ package() const
+ { return this->package_; }
+
// Return the next character.
int
peek_char()
diff --git a/gcc/go/gofrontend/lex.cc b/gcc/go/gofrontend/lex.cc
index 22a1f6e2a0c..16169634733 100644
--- a/gcc/go/gofrontend/lex.cc
+++ b/gcc/go/gofrontend/lex.cc
@@ -873,7 +873,28 @@ Lex::gather_identifier()
&& (cc < 'a' || cc > 'z')
&& cc != '_'
&& (cc < '0' || cc > '9'))
- break;
+ {
+ // Check for an invalid character here, as we get better
+ // error behaviour if we swallow them as part of the
+ // identifier we are building.
+ if ((cc >= ' ' && cc < 0x7f)
+ || cc == '\t'
+ || cc == '\r'
+ || cc == '\n')
+ break;
+
+ this->lineoff_ = p - this->linebuf_;
+ error_at(this->location(),
+ "invalid character 0x%x in identifier",
+ cc);
+ if (!has_non_ascii_char)
+ {
+ buf.assign(pstart, p - pstart);
+ has_non_ascii_char = true;
+ }
+ if (!Lex::is_invalid_identifier(buf))
+ buf.append("$INVALID$");
+ }
++p;
if (is_first)
{
diff --git a/gcc/go/gofrontend/parse.cc b/gcc/go/gofrontend/parse.cc
index 9d112850fee..6e56f835699 100644
--- a/gcc/go/gofrontend/parse.cc
+++ b/gcc/go/gofrontend/parse.cc
@@ -213,7 +213,7 @@ Parse::qualified_ident(std::string* pname, Named_object** ppackage)
if (name == "_")
{
error_at(this->location(), "invalid use of %<_%>");
- name = "blank";
+ name = Gogo::erroneous_name();
}
if (package->name() == this->gogo_->package_name())
@@ -744,6 +744,8 @@ Parse::signature(Typed_identifier* receiver, Location location)
return NULL;
Parse::Names names;
+ if (receiver != NULL)
+ names[receiver->name()] = receiver;
if (params != NULL)
this->check_signature_names(params, &names);
if (results != NULL)
@@ -1940,12 +1942,9 @@ Parse::init_var(const Typed_identifier& tid, Type* type, Expression* init,
{
if (this->gogo_->in_global_scope())
return this->create_dummy_global(type, init, location);
- else if (type == NULL)
- this->gogo_->add_statement(Statement::make_statement(init, true));
else
{
- // With both a type and an initializer, create a dummy
- // variable so that we will check whether the
+ // Create a dummy variable so that we will check whether the
// initializer can be assigned to the type.
Variable* var = new Variable(type, init, false, false, false,
location);
@@ -2693,15 +2692,17 @@ Parse::composite_lit(Type* type, int depth, Location location)
{
this->advance_token();
return Expression::make_composite_literal(type, depth, false, NULL,
- location);
+ false, location);
}
bool has_keys = false;
+ bool all_are_names = true;
Expression_list* vals = new Expression_list;
while (true)
{
Expression* val;
bool is_type_omitted = false;
+ bool is_name = false;
const Token* token = this->peek_token();
@@ -2722,6 +2723,7 @@ Parse::composite_lit(Type* type, int depth, Location location)
val = this->id_to_expression(gogo->pack_hidden_name(identifier,
is_exported),
location);
+ is_name = true;
}
else
{
@@ -2747,6 +2749,7 @@ Parse::composite_lit(Type* type, int depth, Location location)
{
if (has_keys)
vals->push_back(NULL);
+ is_name = false;
}
else
{
@@ -2793,6 +2796,9 @@ Parse::composite_lit(Type* type, int depth, Location location)
vals->push_back(val);
+ if (!is_name)
+ all_are_names = false;
+
if (token->is_op(OPERATOR_COMMA))
{
if (this->advance_token()->is_op(OPERATOR_RCURLY))
@@ -2833,7 +2839,7 @@ Parse::composite_lit(Type* type, int depth, Location location)
}
return Expression::make_composite_literal(type, depth, has_keys, vals,
- location);
+ all_are_names, location);
}
// FunctionLit = "func" Signature Block .
@@ -3107,7 +3113,7 @@ Parse::selector(Expression* left, bool* is_type_switch)
if (token->identifier() == "_")
{
error_at(this->location(), "invalid use of %<_%>");
- name = this->gogo_->pack_hidden_name("blank", false);
+ name = Gogo::erroneous_name();
}
this->advance_token();
return Expression::make_selector(left, name, location);
@@ -3146,7 +3152,7 @@ Parse::selector(Expression* left, bool* is_type_switch)
}
// Index = "[" Expression "]" .
-// Slice = "[" Expression ":" [ Expression ] "]" .
+// Slice = "[" Expression ":" [ Expression ] [ ":" Expression ] "]" .
Expression*
Parse::index(Expression* expr)
@@ -3172,14 +3178,31 @@ Parse::index(Expression* expr)
// We use nil to indicate a missing high expression.
if (this->advance_token()->is_op(OPERATOR_RSQUARE))
end = Expression::make_nil(this->location());
+ else if (this->peek_token()->is_op(OPERATOR_COLON))
+ {
+ error_at(this->location(), "middle index required in 3-index slice");
+ end = Expression::make_error(this->location());
+ }
else
end = this->expression(PRECEDENCE_NORMAL, false, true, NULL, NULL);
}
+
+ Expression* cap = NULL;
+ if (this->peek_token()->is_op(OPERATOR_COLON))
+ {
+ if (this->advance_token()->is_op(OPERATOR_RSQUARE))
+ {
+ error_at(this->location(), "final index required in 3-index slice");
+ cap = Expression::make_error(this->location());
+ }
+ else
+ cap = this->expression(PRECEDENCE_NORMAL, false, true, NULL, NULL);
+ }
if (!this->peek_token()->is_op(OPERATOR_RSQUARE))
error_at(this->location(), "missing %<]%>");
else
this->advance_token();
- return Expression::make_index(expr, start, end, location);
+ return Expression::make_index(expr, start, end, cap, location);
}
// Call = "(" [ ArgumentList [ "," ] ] ")" .
@@ -4932,7 +4955,7 @@ Parse::send_or_recv_stmt(bool* is_send, Expression** channel, Expression** val,
{
error_at(recv_var_loc,
"no new variables on left side of %<:=%>");
- recv_var = "blank";
+ recv_var = Gogo::erroneous_name();
}
*is_send = false;
*varname = gogo->pack_hidden_name(recv_var, is_rv_exported);
@@ -4968,7 +4991,7 @@ Parse::send_or_recv_stmt(bool* is_send, Expression** channel, Expression** val,
{
error_at(recv_var_loc,
"no new variables on left side of %<:=%>");
- recv_var = "blank";
+ recv_var = Gogo::erroneous_name();
}
*is_send = false;
if (recv_var != "_")
@@ -5505,7 +5528,7 @@ Parse::package_clause()
if (name == "_")
{
error_at(this->location(), "invalid package name _");
- name = "blank";
+ name = Gogo::erroneous_name();
}
this->advance_token();
}
diff --git a/gcc/go/gofrontend/runtime.cc b/gcc/go/gofrontend/runtime.cc
index ecc508d0dcc..3b0f1880758 100644
--- a/gcc/go/gofrontend/runtime.cc
+++ b/gcc/go/gofrontend/runtime.cc
@@ -42,6 +42,8 @@ enum Runtime_function_type
RFT_RUNE,
// Go type float64, C type double.
RFT_FLOAT64,
+ // Go type complex64, C type __complex float.
+ RFT_COMPLEX64,
// Go type complex128, C type __complex double.
RFT_COMPLEX128,
// Go type string, C type struct __go_string.
@@ -126,6 +128,10 @@ runtime_function_type(Runtime_function_type bft)
t = Type::lookup_float_type("float64");
break;
+ case RFT_COMPLEX64:
+ t = Type::lookup_complex_type("complex64");
+ break;
+
case RFT_COMPLEX128:
t = Type::lookup_complex_type("complex128");
break;
@@ -216,6 +222,7 @@ convert_to_runtime_function_type(Runtime_function_type bft, Expression* e,
case RFT_UINTPTR:
case RFT_RUNE:
case RFT_FLOAT64:
+ case RFT_COMPLEX64:
case RFT_COMPLEX128:
case RFT_STRING:
case RFT_POINTER:
diff --git a/gcc/go/gofrontend/runtime.def b/gcc/go/gofrontend/runtime.def
index 0d3fd3c43f1..a303a50410f 100644
--- a/gcc/go/gofrontend/runtime.def
+++ b/gcc/go/gofrontend/runtime.def
@@ -68,6 +68,12 @@ DEF_GO_RUNTIME(STRING_TO_INT_ARRAY, "__go_string_to_int_array",
P1(STRING), R1(SLICE))
+// Complex division.
+DEF_GO_RUNTIME(COMPLEX64_DIV, "__go_complex64_div",
+ P2(COMPLEX64, COMPLEX64), R1(COMPLEX64))
+DEF_GO_RUNTIME(COMPLEX128_DIV, "__go_complex128_div",
+ P2(COMPLEX128, COMPLEX128), R1(COMPLEX128))
+
// Make a slice.
DEF_GO_RUNTIME(MAKESLICE1, "__go_make_slice1", P2(TYPE, UINTPTR), R1(SLICE))
DEF_GO_RUNTIME(MAKESLICE2, "__go_make_slice2", P3(TYPE, UINTPTR, UINTPTR),
diff --git a/gcc/go/gofrontend/statements.cc b/gcc/go/gofrontend/statements.cc
index 0261f9d4882..3a0bc3b9739 100644
--- a/gcc/go/gofrontend/statements.cc
+++ b/gcc/go/gofrontend/statements.cc
@@ -594,6 +594,15 @@ Assignment_statement::do_check_types(Gogo*)
Type* lhs_type = this->lhs_->type();
Type* rhs_type = this->rhs_->type();
+
+ // Invalid assignment of nil to the blank identifier.
+ if (lhs_type->is_sink_type()
+ && rhs_type->is_nil_type())
+ {
+ this->report_error(_("use of untyped nil"));
+ return;
+ }
+
std::string reason;
bool ok;
if (this->are_hidden_fields_ok_)
@@ -975,7 +984,10 @@ Tuple_assignment_statement::do_lower(Gogo*, Named_object*, Block* enclosing,
if ((*plhs)->is_sink_expression())
{
- b->add_statement(Statement::make_statement(*prhs, true));
+ if ((*prhs)->type()->is_nil_type())
+ this->report_error(_("use of untyped nil"));
+ else
+ b->add_statement(Statement::make_statement(*prhs, true));
continue;
}
@@ -5528,7 +5540,7 @@ For_range_statement::lower_range_array(Gogo* gogo,
ref = this->make_range_ref(range_object, range_temp, loc);
Expression* ref2 = Expression::make_temporary_reference(index_temp, loc);
- Expression* index = Expression::make_index(ref, ref2, NULL, loc);
+ Expression* index = Expression::make_index(ref, ref2, NULL, NULL, loc);
tref = Expression::make_temporary_reference(value_temp, loc);
tref->set_is_lvalue();
@@ -5629,7 +5641,7 @@ For_range_statement::lower_range_slice(Gogo* gogo,
ref = Expression::make_temporary_reference(for_temp, loc);
Expression* ref2 = Expression::make_temporary_reference(index_temp, loc);
- Expression* index = Expression::make_index(ref, ref2, NULL, loc);
+ Expression* index = Expression::make_index(ref, ref2, NULL, NULL, loc);
tref = Expression::make_temporary_reference(value_temp, loc);
tref->set_is_lvalue();
@@ -5837,7 +5849,7 @@ For_range_statement::lower_range_map(Gogo*,
Expression* zexpr = Expression::make_integer(&zval, NULL, loc);
mpz_clear(zval);
- Expression* index = Expression::make_index(ref, zexpr, NULL, loc);
+ Expression* index = Expression::make_index(ref, zexpr, NULL, NULL, loc);
Expression* ne = Expression::make_binary(OPERATOR_NOTEQ, index,
Expression::make_nil(loc),
diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc
index 32f827dd316..551e97a7b6d 100644
--- a/gcc/go/gofrontend/types.cc
+++ b/gcc/go/gofrontend/types.cc
@@ -1204,7 +1204,7 @@ Type::finish_backend(Gogo* gogo, Btype *placeholder)
// Return a pointer to the type descriptor for this type.
-tree
+Bexpression*
Type::type_descriptor_pointer(Gogo* gogo, Location location)
{
Type* t = this->forwarded();
@@ -1215,10 +1215,9 @@ Type::type_descriptor_pointer(Gogo* gogo, Location location)
t->make_type_descriptor_var(gogo);
go_assert(t->type_descriptor_var_ != NULL);
}
- tree var_tree = var_to_tree(t->type_descriptor_var_);
- if (var_tree == error_mark_node)
- return error_mark_node;
- return build_fold_addr_expr_loc(location.gcc_location(), var_tree);
+ Bexpression* var_expr =
+ gogo->backend()->var_expression(t->type_descriptor_var_, location);
+ return gogo->backend()->address_expression(var_expr, location);
}
// A mapping from unnamed types to type descriptor variables.
@@ -3383,6 +3382,68 @@ Function_type::do_hash_for_method(Gogo* gogo) const
// Get the backend representation for a function type.
Btype*
+Function_type::get_backend_fntype(Gogo* gogo)
+{
+ if (this->fnbtype_ == NULL)
+ {
+ Backend::Btyped_identifier breceiver;
+ if (this->receiver_ != NULL)
+ {
+ breceiver.name = Gogo::unpack_hidden_name(this->receiver_->name());
+
+ // We always pass the address of the receiver parameter, in
+ // order to make interface calls work with unknown types.
+ Type* rtype = this->receiver_->type();
+ if (rtype->points_to() == NULL)
+ rtype = Type::make_pointer_type(rtype);
+ breceiver.btype = rtype->get_backend(gogo);
+ breceiver.location = this->receiver_->location();
+ }
+
+ std::vector<Backend::Btyped_identifier> bparameters;
+ if (this->parameters_ != NULL)
+ {
+ bparameters.resize(this->parameters_->size());
+ size_t i = 0;
+ for (Typed_identifier_list::const_iterator p =
+ this->parameters_->begin(); p != this->parameters_->end();
+ ++p, ++i)
+ {
+ bparameters[i].name = Gogo::unpack_hidden_name(p->name());
+ bparameters[i].btype = p->type()->get_backend(gogo);
+ bparameters[i].location = p->location();
+ }
+ go_assert(i == bparameters.size());
+ }
+
+ std::vector<Backend::Btyped_identifier> bresults;
+ if (this->results_ != NULL)
+ {
+ bresults.resize(this->results_->size());
+ size_t i = 0;
+ for (Typed_identifier_list::const_iterator p =
+ this->results_->begin(); p != this->results_->end();
+ ++p, ++i)
+ {
+ bresults[i].name = Gogo::unpack_hidden_name(p->name());
+ bresults[i].btype = p->type()->get_backend(gogo);
+ bresults[i].location = p->location();
+ }
+ go_assert(i == bresults.size());
+ }
+
+ this->fnbtype_ = gogo->backend()->function_type(breceiver, bparameters,
+ bresults,
+ this->location());
+
+ }
+
+ return this->fnbtype_;
+}
+
+// Get the backend representation for a Go function type.
+
+Btype*
Function_type::do_get_backend(Gogo* gogo)
{
// When we do anything with a function value other than call it, it
@@ -3395,57 +3456,9 @@ Function_type::do_get_backend(Gogo* gogo)
gogo->backend()->placeholder_struct_type("__go_descriptor", loc);
Btype* ptr_struct_type = gogo->backend()->pointer_type(struct_type);
- Backend::Btyped_identifier breceiver;
- if (this->receiver_ != NULL)
- {
- breceiver.name = Gogo::unpack_hidden_name(this->receiver_->name());
-
- // We always pass the address of the receiver parameter, in
- // order to make interface calls work with unknown types.
- Type* rtype = this->receiver_->type();
- if (rtype->points_to() == NULL)
- rtype = Type::make_pointer_type(rtype);
- breceiver.btype = rtype->get_backend(gogo);
- breceiver.location = this->receiver_->location();
- }
-
- std::vector<Backend::Btyped_identifier> bparameters;
- if (this->parameters_ != NULL)
- {
- bparameters.resize(this->parameters_->size());
- size_t i = 0;
- for (Typed_identifier_list::const_iterator p = this->parameters_->begin();
- p != this->parameters_->end();
- ++p, ++i)
- {
- bparameters[i].name = Gogo::unpack_hidden_name(p->name());
- bparameters[i].btype = p->type()->get_backend(gogo);
- bparameters[i].location = p->location();
- }
- go_assert(i == bparameters.size());
- }
-
- std::vector<Backend::Btyped_identifier> bresults;
- if (this->results_ != NULL)
- {
- bresults.resize(this->results_->size());
- size_t i = 0;
- for (Typed_identifier_list::const_iterator p = this->results_->begin();
- p != this->results_->end();
- ++p, ++i)
- {
- bresults[i].name = Gogo::unpack_hidden_name(p->name());
- bresults[i].btype = p->type()->get_backend(gogo);
- bresults[i].location = p->location();
- }
- go_assert(i == bresults.size());
- }
-
- Btype* fntype = gogo->backend()->function_type(breceiver, bparameters,
- bresults, loc);
std::vector<Backend::Btyped_identifier> fields(1);
fields[0].name = "code";
- fields[0].btype = fntype;
+ fields[0].btype = this->get_backend_fntype(gogo);
fields[0].location = loc;
if (!gogo->backend()->set_placeholder_struct_type(struct_type, fields))
return gogo->backend()->error_type();
@@ -4195,7 +4208,8 @@ Struct_field::is_field_name(const std::string& name) const
// This is a horrible hack caused by the fact that we don't pack
// the names of builtin types. FIXME.
- if (nt != NULL
+ if (!this->is_imported_
+ && nt != NULL
&& nt->is_builtin()
&& nt->name() == Gogo::unpack_hidden_name(name))
return true;
@@ -4204,6 +4218,36 @@ Struct_field::is_field_name(const std::string& name) const
}
}
+// Return whether this field is an unexported field named NAME.
+
+bool
+Struct_field::is_unexported_field_name(Gogo* gogo,
+ const std::string& name) const
+{
+ const std::string& field_name(this->field_name());
+ if (Gogo::is_hidden_name(field_name)
+ && name == Gogo::unpack_hidden_name(field_name)
+ && gogo->pack_hidden_name(name, false) != field_name)
+ return true;
+
+ // Check for the name of a builtin type. This is like the test in
+ // is_field_name, only there we return false if this->is_imported_,
+ // and here we return true.
+ if (this->is_imported_ && this->is_anonymous())
+ {
+ Type* t = this->typed_identifier_.type();
+ if (t->points_to() != NULL)
+ t = t->points_to();
+ Named_type* nt = t->named_type();
+ if (nt != NULL
+ && nt->is_builtin()
+ && nt->name() == Gogo::unpack_hidden_name(name))
+ return true;
+ }
+
+ return false;
+}
+
// Return whether this field is an embedded built-in type.
bool
@@ -4264,12 +4308,7 @@ Struct_type::do_verify()
++p)
{
Type* t = p->type();
- if (t->is_undefined())
- {
- error_at(p->location(), "struct field type is incomplete");
- p->set_type(Type::make_error_type());
- }
- else if (p->is_anonymous())
+ if (p->is_anonymous())
{
if (t->named_type() != NULL && t->points_to() != NULL)
{
@@ -4641,13 +4680,8 @@ Struct_type::is_unexported_local_field(Gogo* gogo,
for (Struct_field_list::const_iterator pf = fields->begin();
pf != fields->end();
++pf)
- {
- const std::string& field_name(pf->field_name());
- if (Gogo::is_hidden_name(field_name)
- && name == Gogo::unpack_hidden_name(field_name)
- && gogo->pack_hidden_name(name, false) != field_name)
- return true;
- }
+ if (pf->is_unexported_field_name(gogo, name))
+ return true;
}
return false;
}
@@ -5250,6 +5284,7 @@ Struct_type::do_import(Import* imp)
Type* ftype = imp->read_type();
Struct_field sf(Typed_identifier(name, ftype, imp->location()));
+ sf.set_is_imported();
if (imp->peek_char() == ' ')
{
@@ -5610,12 +5645,12 @@ Array_type::write_equal_function(Gogo* gogo, Named_type* name)
Expression* e1 = Expression::make_temporary_reference(p1, bloc);
e1 = Expression::make_unary(OPERATOR_MULT, e1, bloc);
ref = Expression::make_temporary_reference(index, bloc);
- e1 = Expression::make_array_index(e1, ref, NULL, bloc);
+ e1 = Expression::make_array_index(e1, ref, NULL, NULL, bloc);
Expression* e2 = Expression::make_temporary_reference(p2, bloc);
e2 = Expression::make_unary(OPERATOR_MULT, e2, bloc);
ref = Expression::make_temporary_reference(index, bloc);
- e2 = Expression::make_array_index(e2, ref, NULL, bloc);
+ e2 = Expression::make_array_index(e2, ref, NULL, NULL, bloc);
Expression* cond = Expression::make_binary(OPERATOR_NOTEQ, e1, e2, bloc);
@@ -5665,8 +5700,10 @@ Array_type::get_length_tree(Gogo* gogo)
t = Type::lookup_integer_type("int");
else if (t->is_abstract())
t = t->make_non_abstract_type();
- tree tt = type_to_tree(t->get_backend(gogo));
- this->length_tree_ = Expression::integer_constant_tree(val, tt);
+ Btype* btype = t->get_backend(gogo);
+ Bexpression* iexpr =
+ gogo->backend()->integer_constant_expression(btype, val);
+ this->length_tree_ = expr_to_tree(iexpr);
mpz_clear(val);
}
else
@@ -6226,14 +6263,12 @@ Map_type::Map_descriptors Map_type::map_descriptors;
// Build a map descriptor for this type. Return a pointer to it.
-tree
+Bexpression*
Map_type::map_descriptor_pointer(Gogo* gogo, Location location)
{
Bvariable* bvar = this->map_descriptor(gogo);
- tree var_tree = var_to_tree(bvar);
- if (var_tree == error_mark_node)
- return error_mark_node;
- return build_fold_addr_expr_loc(location.gcc_location(), var_tree);
+ Bexpression* var_expr = gogo->backend()->var_expression(bvar, location);
+ return gogo->backend()->address_expression(var_expr, location);
}
// Build a map descriptor for this type.
@@ -8812,8 +8847,7 @@ Type::add_local_methods_for_type(const Named_type* nt,
bool is_value_method = (is_embedded_pointer
|| !Type::method_expects_pointer(no));
Method* m = new Named_method(no, field_indexes, depth, is_value_method,
- (needs_stub_method
- || (depth > 0 && is_value_method)));
+ (needs_stub_method || depth > 0));
if (!(*methods)->insert(no->name(), m))
delete m;
}
@@ -9020,6 +9054,8 @@ Type::build_stub_methods(Gogo* gogo, const Type* type, const Methods* methods,
fntype->is_varargs(), location);
gogo->finish_function(fntype->location());
+ if (type->named_type() == NULL && stub->is_function())
+ stub->func_value()->set_is_unnamed_type_stub_method();
if (m->nointerface() && stub->is_function())
stub->func_value()->set_nointerface();
}
@@ -9269,7 +9305,11 @@ Type::bind_field_or_method(Gogo* gogo, const Type* type, Expression* expr,
}
else
{
- if (!ambig1.empty())
+ if (Gogo::is_erroneous_name(name))
+ {
+ // An error was already reported.
+ }
+ else if (!ambig1.empty())
error_at(location, "%qs is ambiguous via %qs and %qs",
Gogo::message_name(name).c_str(), ambig1.c_str(),
ambig2.c_str());
@@ -9283,7 +9323,9 @@ Type::bind_field_or_method(Gogo* gogo, const Type* type, Expression* expr,
else
{
bool is_unexported;
- if (!Gogo::is_hidden_name(name))
+ // The test for 'a' and 'z' is to handle builtin names,
+ // which are not hidden.
+ if (!Gogo::is_hidden_name(name) && (name[0] < 'a' || name[0] > 'z'))
is_unexported = false;
else
{
diff --git a/gcc/go/gofrontend/types.h b/gcc/go/gofrontend/types.h
index d8a3080f586..12a7c8579b2 100644
--- a/gcc/go/gofrontend/types.h
+++ b/gcc/go/gofrontend/types.h
@@ -901,7 +901,7 @@ class Type
// Build a type descriptor entry for this type. Return a pointer to
// it. The location is the location which causes us to need the
// entry.
- tree
+ Bexpression*
type_descriptor_pointer(Gogo* gogo, Location);
// Return the type reflection string for this type.
@@ -1717,7 +1717,8 @@ class Function_type : public Type
Typed_identifier_list* results, Location location)
: Type(TYPE_FUNCTION),
receiver_(receiver), parameters_(parameters), results_(results),
- location_(location), is_varargs_(false), is_builtin_(false)
+ location_(location), is_varargs_(false), is_builtin_(false),
+ fnbtype_(NULL)
{ }
// Get the receiver.
@@ -1798,6 +1799,11 @@ class Function_type : public Type
static Type*
make_function_type_descriptor_type();
+ // Return the backend representation of this function type. This is used
+ // as the real type of a backend function declaration or defintion.
+ Btype*
+ get_backend_fntype(Gogo*);
+
protected:
int
do_traverse(Traverse*);
@@ -1851,6 +1857,9 @@ class Function_type : public Type
// Whether this is a special builtin function which can not simply
// be called. This is used for len, cap, etc.
bool is_builtin_;
+ // The backend representation of this type for backend function
+ // declarations and definitions.
+ Btype* fnbtype_;
};
// The type of a pointer.
@@ -1915,7 +1924,7 @@ class Struct_field
{
public:
explicit Struct_field(const Typed_identifier& typed_identifier)
- : typed_identifier_(typed_identifier), tag_(NULL)
+ : typed_identifier_(typed_identifier), tag_(NULL), is_imported_(false)
{ }
// The field name.
@@ -1926,6 +1935,10 @@ class Struct_field
bool
is_field_name(const std::string& name) const;
+ // Return whether this struct field is an unexported field named NAME.
+ bool
+ is_unexported_field_name(Gogo*, const std::string& name) const;
+
// Return whether this struct field is an embedded built-in type.
bool
is_embedded_builtin(Gogo*) const;
@@ -1963,6 +1976,11 @@ class Struct_field
set_tag(const std::string& tag)
{ this->tag_ = new std::string(tag); }
+ // Record that this field is defined in an imported struct.
+ void
+ set_is_imported()
+ { this->is_imported_ = true; }
+
// Set the type. This is only used in error cases.
void
set_type(Type* type)
@@ -1973,6 +1991,8 @@ class Struct_field
Typed_identifier typed_identifier_;
// The field tag. This is NULL if the field has no tag.
std::string* tag_;
+ // Whether this field is defined in an imported struct.
+ bool is_imported_;
};
// A list of struct fields.
@@ -2392,7 +2412,7 @@ class Map_type : public Type
// Build a map descriptor for this type. Return a pointer to it.
// The location is the location which causes us to need the
// descriptor.
- tree
+ Bexpression*
map_descriptor_pointer(Gogo* gogo, Location);
protected:
diff --git a/gcc/godump.c b/gcc/godump.c
index 81efa2877cb..0303e4f0628 100644
--- a/gcc/godump.c
+++ b/gcc/godump.c
@@ -1213,7 +1213,7 @@ go_finish (const char *filename)
break;
default:
- gcc_unreachable();
+ gcc_unreachable ();
}
}
diff --git a/gcc/graph.c b/gcc/graph.c
index 0ec279d86a9..5c890e5956c 100644
--- a/gcc/graph.c
+++ b/gcc/graph.c
@@ -160,9 +160,9 @@ draw_cfg_nodes_no_loops (pretty_printer *pp, struct function *fun)
visited = sbitmap_alloc (last_basic_block);
bitmap_clear (visited);
- /* FIXME: pre_and_rev_post_order_compute only works if fun == cfun. */
- n = pre_and_rev_post_order_compute (NULL, rpo, true);
- for (i = 0; i < n; i++)
+ n = pre_and_rev_post_order_compute_fn (fun, NULL, rpo, true);
+ for (i = n_basic_blocks_for_function (fun) - n;
+ i < n_basic_blocks_for_function (fun); i++)
{
basic_block bb = BASIC_BLOCK (rpo[i]);
draw_cfg_node (pp, fun->funcdef_no, bb);
diff --git a/gcc/graphite-blocking.c b/gcc/graphite-blocking.c
index 9226da00eae..1fff36c53bc 100644
--- a/gcc/graphite-blocking.c
+++ b/gcc/graphite-blocking.c
@@ -34,7 +34,9 @@ along with GCC; see the file COPYING3. If not see
#include "system.h"
#include "coretypes.h"
-#include "tree-ssa.h"
+#include "tree.h"
+#include "gimple.h"
+#include "tree-ssa-loop.h"
#include "dumpfile.h"
#include "cfgloop.h"
#include "tree-chrec.h"
diff --git a/gcc/graphite-clast-to-gimple.c b/gcc/graphite-clast-to-gimple.c
index d40164c6774..ec4c1d1f461 100644
--- a/gcc/graphite-clast-to-gimple.c
+++ b/gcc/graphite-clast-to-gimple.c
@@ -35,7 +35,12 @@ along with GCC; see the file COPYING3. If not see
#include "system.h"
#include "coretypes.h"
#include "diagnostic-core.h"
-#include "tree-ssa.h"
+#include "tree.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-ssa-loop-manip.h"
+#include "tree-ssa-loop.h"
+#include "tree-into-ssa.h"
#include "tree-pass.h"
#include "cfgloop.h"
#include "tree-chrec.h"
@@ -1306,7 +1311,7 @@ translate_clast (loop_p context_loop, struct clast_stmt *stmt, edge next_e,
next_e = translate_clast_assignment ((struct clast_assignment *) stmt,
next_e, level, ip);
else
- gcc_unreachable();
+ gcc_unreachable ();
recompute_all_dominators ();
graphite_verify ();
@@ -1409,7 +1414,7 @@ init_cloog_input_file (int scop_number)
/* Extend the scattering to NEW_DIMS scattering dimensions. */
static
-isl_map *extend_scattering(isl_map *scattering, int new_dims)
+isl_map *extend_scattering (isl_map *scattering, int new_dims)
{
int old_dims, i;
isl_space *space;
@@ -1462,12 +1467,13 @@ build_cloog_union_domain (scop_p scop, int nb_scattering_dims)
/* Dead code elimination: when the domain of a PBB is empty,
don't generate code for the PBB. */
- if (isl_set_is_empty(pbb->domain))
+ if (isl_set_is_empty (pbb->domain))
continue;
- domain = cloog_domain_from_isl_set(isl_set_copy(pbb->domain));
- scattering = cloog_scattering_from_isl_map(extend_scattering(isl_map_copy(pbb->transformed),
- nb_scattering_dims));
+ domain = cloog_domain_from_isl_set (isl_set_copy (pbb->domain));
+ scattering = cloog_scattering_from_isl_map
+ (extend_scattering (isl_map_copy (pbb->transformed),
+ nb_scattering_dims));
union_domain = cloog_union_domain_add_domain (union_domain, "", domain,
scattering, pbb);
@@ -1646,8 +1652,7 @@ debug_generated_program (scop_p scop)
bool
gloog (scop_p scop, bb_pbb_htab_type bb_pbb_mapping)
{
- vec<tree> newivs;
- newivs.create (10);
+ stack_vec<tree, 10> newivs;
loop_p context_loop;
sese region = SCOP_REGION (scop);
ifsese if_region = NULL;
@@ -1705,7 +1710,6 @@ gloog (scop_p scop, bb_pbb_htab_type bb_pbb_mapping)
newivs_index.dispose ();
params_index.dispose ();
- newivs.release ();
cloog_clast_free (clast);
timevar_pop (TV_GRAPHITE_CODE_GEN);
diff --git a/gcc/graphite-dependences.c b/gcc/graphite-dependences.c
index 5139e69b942..417ea2cd153 100644
--- a/gcc/graphite-dependences.c
+++ b/gcc/graphite-dependences.c
@@ -33,7 +33,9 @@ along with GCC; see the file COPYING3. If not see
#include "system.h"
#include "coretypes.h"
-#include "tree-ssa.h"
+#include "tree.h"
+#include "gimple.h"
+#include "tree-ssa-loop.h"
#include "tree-pass.h"
#include "cfgloop.h"
#include "tree-chrec.h"
@@ -583,13 +585,11 @@ loop_is_parallel_p (loop_p loop, bb_pbb_htab_type bb_pbb_mapping, int depth)
{
bool dependences;
scop_p scop;
- vec<poly_bb_p> body;
- body.create (3);
timevar_push (TV_GRAPHITE_DATA_DEPS);
+ stack_vec<poly_bb_p, 3> body;
scop = get_loop_body_pbbs (loop, bb_pbb_mapping, &body);
dependences = loop_level_carries_dependences (scop, body, depth);
- body.release ();
timevar_pop (TV_GRAPHITE_DATA_DEPS);
return !dependences;
diff --git a/gcc/graphite-interchange.c b/gcc/graphite-interchange.c
index 289c1d9568f..36e1b55757d 100644
--- a/gcc/graphite-interchange.c
+++ b/gcc/graphite-interchange.c
@@ -35,7 +35,9 @@ along with GCC; see the file COPYING3. If not see
#include "system.h"
#include "coretypes.h"
-#include "tree-ssa.h"
+#include "tree.h"
+#include "gimple.h"
+#include "tree-ssa-loop.h"
#include "dumpfile.h"
#include "cfgloop.h"
#include "tree-chrec.h"
diff --git a/gcc/graphite-optimize-isl.c b/gcc/graphite-optimize-isl.c
index f47e21a5023..d039c1b74e1 100644
--- a/gcc/graphite-optimize-isl.c
+++ b/gcc/graphite-optimize-isl.c
@@ -32,7 +32,9 @@ along with GCC; see the file COPYING3. If not see
#include "system.h"
#include "coretypes.h"
-#include "tree-ssa.h"
+#include "tree.h"
+#include "gimple.h"
+#include "tree-ssa-loop.h"
#include "dumpfile.h"
#include "cfgloop.h"
#include "tree-chrec.h"
@@ -114,7 +116,7 @@ scop_get_dependences (scop_p scop)
*/
static isl_basic_map *
-getTileMap(isl_ctx *ctx, int scheduleDimensions, int tileSize)
+getTileMap (isl_ctx *ctx, int scheduleDimensions, int tileSize)
{
int x;
/* We construct
@@ -124,11 +126,11 @@ getTileMap(isl_ctx *ctx, int scheduleDimensions, int tileSize)
s1 = a1 * 32 and s1 = p1 and t1 <= p1 < t1 + 32}
and project out the auxilary dimensions a0 and a1. */
- isl_space *Space = isl_space_alloc(ctx, 0, scheduleDimensions,
- scheduleDimensions * 3);
- isl_basic_map *tileMap = isl_basic_map_universe(isl_space_copy(Space));
+ isl_space *Space = isl_space_alloc (ctx, 0, scheduleDimensions,
+ scheduleDimensions * 3);
+ isl_basic_map *tileMap = isl_basic_map_universe (isl_space_copy (Space));
- isl_local_space *LocalSpace = isl_local_space_from_space(Space);
+ isl_local_space *LocalSpace = isl_local_space_from_space (Space);
for (x = 0; x < scheduleDimensions; x++)
{
@@ -140,29 +142,29 @@ getTileMap(isl_ctx *ctx, int scheduleDimensions, int tileSize)
isl_constraint *c;
/* sX = aX * tileSize; */
- c = isl_equality_alloc(isl_local_space_copy(LocalSpace));
- isl_constraint_set_coefficient_si(c, isl_dim_out, sX, 1);
- isl_constraint_set_coefficient_si(c, isl_dim_out, aX, -tileSize);
- tileMap = isl_basic_map_add_constraint(tileMap, c);
+ c = isl_equality_alloc (isl_local_space_copy (LocalSpace));
+ isl_constraint_set_coefficient_si (c, isl_dim_out, sX, 1);
+ isl_constraint_set_coefficient_si (c, isl_dim_out, aX, -tileSize);
+ tileMap = isl_basic_map_add_constraint (tileMap, c);
/* pX = sX; */
- c = isl_equality_alloc(isl_local_space_copy(LocalSpace));
- isl_constraint_set_coefficient_si(c, isl_dim_out, pX, 1);
- isl_constraint_set_coefficient_si(c, isl_dim_in, sX, -1);
- tileMap = isl_basic_map_add_constraint(tileMap, c);
+ c = isl_equality_alloc (isl_local_space_copy (LocalSpace));
+ isl_constraint_set_coefficient_si (c, isl_dim_out, pX, 1);
+ isl_constraint_set_coefficient_si (c, isl_dim_in, sX, -1);
+ tileMap = isl_basic_map_add_constraint (tileMap, c);
/* tX <= pX */
- c = isl_inequality_alloc(isl_local_space_copy(LocalSpace));
- isl_constraint_set_coefficient_si(c, isl_dim_out, pX, 1);
- isl_constraint_set_coefficient_si(c, isl_dim_out, tX, -1);
- tileMap = isl_basic_map_add_constraint(tileMap, c);
+ c = isl_inequality_alloc (isl_local_space_copy (LocalSpace));
+ isl_constraint_set_coefficient_si (c, isl_dim_out, pX, 1);
+ isl_constraint_set_coefficient_si (c, isl_dim_out, tX, -1);
+ tileMap = isl_basic_map_add_constraint (tileMap, c);
/* pX <= tX + (tileSize - 1) */
- c = isl_inequality_alloc(isl_local_space_copy(LocalSpace));
- isl_constraint_set_coefficient_si(c, isl_dim_out, tX, 1);
- isl_constraint_set_coefficient_si(c, isl_dim_out, pX, -1);
- isl_constraint_set_constant_si(c, tileSize - 1);
- tileMap = isl_basic_map_add_constraint(tileMap, c);
+ c = isl_inequality_alloc (isl_local_space_copy (LocalSpace));
+ isl_constraint_set_coefficient_si (c, isl_dim_out, tX, 1);
+ isl_constraint_set_coefficient_si (c, isl_dim_out, pX, -1);
+ isl_constraint_set_constant_si (c, tileSize - 1);
+ tileMap = isl_basic_map_add_constraint (tileMap, c);
}
/* Project out auxiliary dimensions.
@@ -170,10 +172,10 @@ getTileMap(isl_ctx *ctx, int scheduleDimensions, int tileSize)
The auxiliary dimensions are transformed into existentially quantified ones.
This reduces the number of visible scattering dimensions and allows Cloog
to produces better code. */
- tileMap = isl_basic_map_project_out(tileMap, isl_dim_out,
- 2 * scheduleDimensions,
- scheduleDimensions);
- isl_local_space_free(LocalSpace);
+ tileMap = isl_basic_map_project_out (tileMap, isl_dim_out,
+ 2 * scheduleDimensions,
+ scheduleDimensions);
+ isl_local_space_free (LocalSpace);
return tileMap;
}
@@ -185,7 +187,7 @@ getTileMap(isl_ctx *ctx, int scheduleDimensions, int tileSize)
static bool DisableTiling = false;
static isl_union_map *
-getScheduleForBand(isl_band *Band, int *Dimensions)
+getScheduleForBand (isl_band *Band, int *Dimensions)
{
isl_union_map *PartialSchedule;
isl_ctx *ctx;
@@ -193,8 +195,8 @@ getScheduleForBand(isl_band *Band, int *Dimensions)
isl_basic_map *TileMap;
isl_union_map *TileUMap;
- PartialSchedule = isl_band_get_partial_schedule(Band);
- *Dimensions = isl_band_n_member(Band);
+ PartialSchedule = isl_band_get_partial_schedule (Band);
+ *Dimensions = isl_band_n_member (Band);
if (DisableTiling)
return PartialSchedule;
@@ -203,15 +205,15 @@ getScheduleForBand(isl_band *Band, int *Dimensions)
if (*Dimensions == 1)
return PartialSchedule;
- ctx = isl_union_map_get_ctx(PartialSchedule);
- Space = isl_union_map_get_space(PartialSchedule);
+ ctx = isl_union_map_get_ctx (PartialSchedule);
+ Space = isl_union_map_get_space (PartialSchedule);
- TileMap = getTileMap(ctx, *Dimensions, 32);
- TileUMap = isl_union_map_from_map(isl_map_from_basic_map(TileMap));
- TileUMap = isl_union_map_align_params(TileUMap, Space);
+ TileMap = getTileMap (ctx, *Dimensions, 32);
+ TileUMap = isl_union_map_from_map (isl_map_from_basic_map (TileMap));
+ TileUMap = isl_union_map_align_params (TileUMap, Space);
*Dimensions = 2 * *Dimensions;
- return isl_union_map_apply_range(PartialSchedule, TileUMap);
+ return isl_union_map_apply_range (PartialSchedule, TileUMap);
}
/* Create a map that pre-vectorizes one scheduling dimension.
@@ -253,9 +255,9 @@ getScheduleForBand(isl_band *Band, int *Dimensions)
currently constant and not yet target specific. This function does not reason
about parallelism. */
static isl_map *
-getPrevectorMap(isl_ctx *ctx, int DimToVectorize,
- int ScheduleDimensions,
- int VectorWidth)
+getPrevectorMap (isl_ctx *ctx, int DimToVectorize,
+ int ScheduleDimensions,
+ int VectorWidth)
{
isl_space *Space;
isl_local_space *LocalSpace, *LocalSpaceRange;
@@ -270,9 +272,9 @@ getPrevectorMap(isl_ctx *ctx, int DimToVectorize,
/* assert (0 <= DimToVectorize && DimToVectorize < ScheduleDimensions);*/
- Space = isl_space_alloc(ctx, 0, ScheduleDimensions, ScheduleDimensions + 1);
- TilingMap = isl_map_universe(isl_space_copy(Space));
- LocalSpace = isl_local_space_from_space(Space);
+ Space = isl_space_alloc (ctx, 0, ScheduleDimensions, ScheduleDimensions + 1);
+ TilingMap = isl_map_universe (isl_space_copy (Space));
+ LocalSpace = isl_local_space_from_space (Space);
PointDimension = ScheduleDimensions;
TileDimension = DimToVectorize;
@@ -280,43 +282,43 @@ getPrevectorMap(isl_ctx *ctx, int DimToVectorize,
DimToVectorize to the point loop at the innermost dimension. */
for (i = 0; i < ScheduleDimensions; i++)
{
- c = isl_equality_alloc(isl_local_space_copy(LocalSpace));
- isl_constraint_set_coefficient_si(c, isl_dim_in, i, -1);
+ c = isl_equality_alloc (isl_local_space_copy (LocalSpace));
+ isl_constraint_set_coefficient_si (c, isl_dim_in, i, -1);
if (i == DimToVectorize)
- isl_constraint_set_coefficient_si(c, isl_dim_out, PointDimension, 1);
+ isl_constraint_set_coefficient_si (c, isl_dim_out, PointDimension, 1);
else
- isl_constraint_set_coefficient_si(c, isl_dim_out, i, 1);
+ isl_constraint_set_coefficient_si (c, isl_dim_out, i, 1);
- TilingMap = isl_map_add_constraint(TilingMap, c);
+ TilingMap = isl_map_add_constraint (TilingMap, c);
}
/* it % 'VectorWidth' = 0 */
- LocalSpaceRange = isl_local_space_range(isl_local_space_copy(LocalSpace));
- Aff = isl_aff_zero_on_domain(LocalSpaceRange);
- Aff = isl_aff_set_constant_si(Aff, VectorWidth);
- Aff = isl_aff_set_coefficient_si(Aff, isl_dim_in, TileDimension, 1);
- isl_int_init(VectorWidthMP);
- isl_int_set_si(VectorWidthMP, VectorWidth);
- Aff = isl_aff_mod(Aff, VectorWidthMP);
- isl_int_clear(VectorWidthMP);
- Modulo = isl_pw_aff_zero_set(isl_pw_aff_from_aff(Aff));
- TilingMap = isl_map_intersect_range(TilingMap, Modulo);
+ LocalSpaceRange = isl_local_space_range (isl_local_space_copy (LocalSpace));
+ Aff = isl_aff_zero_on_domain (LocalSpaceRange);
+ Aff = isl_aff_set_constant_si (Aff, VectorWidth);
+ Aff = isl_aff_set_coefficient_si (Aff, isl_dim_in, TileDimension, 1);
+ isl_int_init (VectorWidthMP);
+ isl_int_set_si (VectorWidthMP, VectorWidth);
+ Aff = isl_aff_mod (Aff, VectorWidthMP);
+ isl_int_clear (VectorWidthMP);
+ Modulo = isl_pw_aff_zero_set (isl_pw_aff_from_aff (Aff));
+ TilingMap = isl_map_intersect_range (TilingMap, Modulo);
/* it <= ip */
- c = isl_inequality_alloc(isl_local_space_copy(LocalSpace));
- isl_constraint_set_coefficient_si(c, isl_dim_out, TileDimension, -1);
- isl_constraint_set_coefficient_si(c, isl_dim_out, PointDimension, 1);
- TilingMap = isl_map_add_constraint(TilingMap, c);
+ c = isl_inequality_alloc (isl_local_space_copy (LocalSpace));
+ isl_constraint_set_coefficient_si (c, isl_dim_out, TileDimension, -1);
+ isl_constraint_set_coefficient_si (c, isl_dim_out, PointDimension, 1);
+ TilingMap = isl_map_add_constraint (TilingMap, c);
/* ip <= it + ('VectorWidth' - 1) */
- c = isl_inequality_alloc(LocalSpace);
- isl_constraint_set_coefficient_si(c, isl_dim_out, TileDimension, 1);
- isl_constraint_set_coefficient_si(c, isl_dim_out, PointDimension, -1);
- isl_constraint_set_constant_si(c, VectorWidth - 1);
- TilingMap = isl_map_add_constraint(TilingMap, c);
+ c = isl_inequality_alloc (LocalSpace);
+ isl_constraint_set_coefficient_si (c, isl_dim_out, TileDimension, 1);
+ isl_constraint_set_coefficient_si (c, isl_dim_out, PointDimension, -1);
+ isl_constraint_set_constant_si (c, VectorWidth - 1);
+ TilingMap = isl_map_add_constraint (TilingMap, c);
- isl_map_dump(TilingMap);
+ isl_map_dump (TilingMap);
return TilingMap;
}
@@ -329,15 +331,15 @@ static bool EnablePollyVector = false;
individual bands to the overall schedule. In case tiling is requested,
the individual bands are tiled. */
static isl_union_map *
-getScheduleForBandList(isl_band_list *BandList)
+getScheduleForBandList (isl_band_list *BandList)
{
int NumBands, i;
isl_union_map *Schedule;
isl_ctx *ctx;
- ctx = isl_band_list_get_ctx(BandList);
- NumBands = isl_band_list_n_band(BandList);
- Schedule = isl_union_map_empty(isl_space_params_alloc(ctx, 0));
+ ctx = isl_band_list_get_ctx (BandList);
+ NumBands = isl_band_list_n_band (BandList);
+ Schedule = isl_union_map_empty (isl_space_params_alloc (ctx, 0));
for (i = 0; i < NumBands; i++)
{
@@ -346,61 +348,61 @@ getScheduleForBandList(isl_band_list *BandList)
int ScheduleDimensions;
isl_space *Space;
- Band = isl_band_list_get_band(BandList, i);
- PartialSchedule = getScheduleForBand(Band, &ScheduleDimensions);
- Space = isl_union_map_get_space(PartialSchedule);
+ Band = isl_band_list_get_band (BandList, i);
+ PartialSchedule = getScheduleForBand (Band, &ScheduleDimensions);
+ Space = isl_union_map_get_space (PartialSchedule);
- if (isl_band_has_children(Band))
+ if (isl_band_has_children (Band))
{
isl_band_list *Children;
isl_union_map *SuffixSchedule;
- Children = isl_band_get_children(Band);
- SuffixSchedule = getScheduleForBandList(Children);
- PartialSchedule = isl_union_map_flat_range_product(PartialSchedule,
- SuffixSchedule);
- isl_band_list_free(Children);
+ Children = isl_band_get_children (Band);
+ SuffixSchedule = getScheduleForBandList (Children);
+ PartialSchedule = isl_union_map_flat_range_product (PartialSchedule,
+ SuffixSchedule);
+ isl_band_list_free (Children);
}
else if (EnablePollyVector)
{
for (i = ScheduleDimensions - 1 ; i >= 0 ; i--)
{
- if (isl_band_member_is_zero_distance(Band, i))
+ if (isl_band_member_is_zero_distance (Band, i))
{
isl_map *TileMap;
isl_union_map *TileUMap;
- TileMap = getPrevectorMap(ctx, i, ScheduleDimensions, 4);
- TileUMap = isl_union_map_from_map(TileMap);
- TileUMap = isl_union_map_align_params(TileUMap,
- isl_space_copy(Space));
- PartialSchedule = isl_union_map_apply_range(PartialSchedule,
- TileUMap);
+ TileMap = getPrevectorMap (ctx, i, ScheduleDimensions, 4);
+ TileUMap = isl_union_map_from_map (TileMap);
+ TileUMap = isl_union_map_align_params
+ (TileUMap, isl_space_copy (Space));
+ PartialSchedule = isl_union_map_apply_range
+ (PartialSchedule, TileUMap);
break;
}
}
}
- Schedule = isl_union_map_union(Schedule, PartialSchedule);
+ Schedule = isl_union_map_union (Schedule, PartialSchedule);
- isl_band_free(Band);
- isl_space_free(Space);
+ isl_band_free (Band);
+ isl_space_free (Space);
}
return Schedule;
}
static isl_union_map *
-getScheduleMap(isl_schedule *Schedule)
+getScheduleMap (isl_schedule *Schedule)
{
- isl_band_list *BandList = isl_schedule_get_band_forest(Schedule);
- isl_union_map *ScheduleMap = getScheduleForBandList(BandList);
- isl_band_list_free(BandList);
+ isl_band_list *BandList = isl_schedule_get_band_forest (Schedule);
+ isl_union_map *ScheduleMap = getScheduleForBandList (BandList);
+ isl_band_list_free (BandList);
return ScheduleMap;
}
static int
-getSingleMap(__isl_take isl_map *map, void *user)
+getSingleMap (__isl_take isl_map *map, void *user)
{
isl_map **singleMap = (isl_map **) user;
*singleMap = map;
@@ -420,12 +422,13 @@ apply_schedule_map_to_scop (scop_p scop, isl_union_map *schedule_map)
isl_union_map *stmtBand;
isl_map *stmtSchedule;
- stmtBand = isl_union_map_intersect_domain(isl_union_map_copy(schedule_map),
- isl_union_set_from_set(domain));
- isl_union_map_foreach_map(stmtBand, getSingleMap, &stmtSchedule);
- isl_map_free(pbb->transformed);
+ stmtBand = isl_union_map_intersect_domain
+ (isl_union_map_copy (schedule_map),
+ isl_union_set_from_set (domain));
+ isl_union_map_foreach_map (stmtBand, getSingleMap, &stmtSchedule);
+ isl_map_free (pbb->transformed);
pbb->transformed = stmtSchedule;
- isl_union_map_free(stmtBand);
+ isl_union_map_free (stmtBand);
}
}
@@ -442,20 +445,20 @@ optimize_isl (scop_p scop)
domain = scop_get_domains (scop);
dependences = scop_get_dependences (scop);
- dependences = isl_union_map_gist_domain(dependences,
- isl_union_set_copy(domain));
- dependences = isl_union_map_gist_range(dependences,
- isl_union_set_copy(domain));
+ dependences = isl_union_map_gist_domain (dependences,
+ isl_union_set_copy (domain));
+ dependences = isl_union_map_gist_range (dependences,
+ isl_union_set_copy (domain));
validity = dependences;
proximity = isl_union_map_copy (validity);
- isl_options_set_schedule_max_constant_term(scop->ctx, CONSTANT_BOUND);
- isl_options_set_schedule_maximize_band_depth(scop->ctx, 1);
- isl_options_set_schedule_fuse(scop->ctx, ISL_SCHEDULE_FUSE_MIN);
- isl_options_set_on_error(scop->ctx, ISL_ON_ERROR_CONTINUE);
+ isl_options_set_schedule_max_constant_term (scop->ctx, CONSTANT_BOUND);
+ isl_options_set_schedule_maximize_band_depth (scop->ctx, 1);
+ isl_options_set_schedule_fuse (scop->ctx, ISL_SCHEDULE_FUSE_MIN);
+ isl_options_set_on_error (scop->ctx, ISL_ON_ERROR_CONTINUE);
schedule = isl_union_set_compute_schedule (domain, validity, proximity);
- isl_options_set_on_error(scop->ctx, ISL_ON_ERROR_ABORT);
+ isl_options_set_on_error (scop->ctx, ISL_ON_ERROR_ABORT);
if (!schedule)
return false;
diff --git a/gcc/graphite-poly.c b/gcc/graphite-poly.c
index 35fe3ba2342..2749555c371 100644
--- a/gcc/graphite-poly.c
+++ b/gcc/graphite-poly.c
@@ -35,7 +35,9 @@ along with GCC; see the file COPYING3. If not see
#include "system.h"
#include "coretypes.h"
#include "diagnostic-core.h"
-#include "tree-ssa.h"
+#include "tree.h"
+#include "gimple.h"
+#include "tree-ssa-loop.h"
#include "dumpfile.h"
#include "gimple-pretty-print.h"
#include "cfgloop.h"
diff --git a/gcc/graphite-poly.h b/gcc/graphite-poly.h
index 52d6b1cdc53..9720f3f60f5 100644
--- a/gcc/graphite-poly.h
+++ b/gcc/graphite-poly.h
@@ -403,7 +403,7 @@ extern int scop_do_interchange (scop_p);
extern int scop_do_strip_mine (scop_p, int);
extern bool scop_do_block (scop_p);
extern bool flatten_all_loops (scop_p);
-extern bool optimize_isl(scop_p);
+extern bool optimize_isl (scop_p);
extern void pbb_number_of_iterations_at_time (poly_bb_p, graphite_dim_t, mpz_t);
extern void debug_gmp_value (mpz_t);
diff --git a/gcc/graphite-scop-detection.c b/gcc/graphite-scop-detection.c
index d2b8a2d0424..e73a349803a 100644
--- a/gcc/graphite-scop-detection.c
+++ b/gcc/graphite-scop-detection.c
@@ -31,6 +31,15 @@ along with GCC; see the file COPYING3. If not see
#include "system.h"
#include "coretypes.h"
+#include "tree.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssa-loop-manip.h"
+#include "tree-ssa-loop-niter.h"
+#include "tree-ssa-loop.h"
+#include "tree-into-ssa.h"
#include "tree-ssa.h"
#include "cfgloop.h"
#include "tree-chrec.h"
@@ -38,6 +47,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-scalar-evolution.h"
#include "tree-pass.h"
#include "sese.h"
+#include "tree-ssa-propagate.h"
#ifdef HAVE_cloog
#include "graphite-poly.h"
@@ -465,8 +475,7 @@ scopdet_basic_block_info (basic_block bb, loop_p outermost_loop,
case GBB_LOOP_SING_EXIT_HEADER:
{
- vec<sd_region> regions;
- regions.create (3);
+ stack_vec<sd_region, 3> regions;
struct scopdet_info sinfo;
edge exit_e = single_exit (loop);
@@ -531,8 +540,7 @@ scopdet_basic_block_info (basic_block bb, loop_p outermost_loop,
{
/* XXX: For now we just do not join loops with multiple exits. If the
exits lead to the same bb it may be possible to join the loop. */
- vec<sd_region> regions;
- regions.create (3);
+ stack_vec<sd_region, 3> regions;
vec<edge> exits = get_loop_exit_edges (loop);
edge e;
int i;
@@ -575,8 +583,7 @@ scopdet_basic_block_info (basic_block bb, loop_p outermost_loop,
}
case GBB_COND_HEADER:
{
- vec<sd_region> regions;
- regions.create (3);
+ stack_vec<sd_region, 3> regions;
struct scopdet_info sinfo;
vec<basic_block> dominated;
int i;
@@ -1179,8 +1186,7 @@ print_graphite_statistics (FILE* file, vec<scop_p> scops)
static void
limit_scops (vec<scop_p> *scops)
{
- vec<sd_region> regions;
- regions.create (3);
+ stack_vec<sd_region, 3> regions;
int i;
scop_p scop;
@@ -1215,7 +1221,6 @@ limit_scops (vec<scop_p> *scops)
create_sese_edges (regions);
build_graphite_scops (regions, scops);
- regions.release ();
}
/* Returns true when P1 and P2 are close phis with the same
@@ -1394,8 +1399,7 @@ void
build_scops (vec<scop_p> *scops)
{
struct loop *loop = current_loops->tree_root;
- vec<sd_region> regions;
- regions.create (3);
+ stack_vec<sd_region, 3> regions;
canonicalize_loop_closed_ssa_form ();
build_scops_1 (single_succ (ENTRY_BLOCK_PTR), ENTRY_BLOCK_PTR->loop_father,
@@ -1585,7 +1589,7 @@ dot_all_scops (vec<scop_p> scops)
DEBUG_FUNCTION void
dot_scop (scop_p scop)
{
- vec<scop_p> scops = vNULL;
+ stack_vec<scop_p, 1> scops;
if (scop)
scops.safe_push (scop);
@@ -1605,8 +1609,6 @@ dot_scop (scop_p scop)
#else
dot_all_scops_1 (stderr, scops);
#endif
-
- scops.release ();
}
#endif
diff --git a/gcc/graphite-sese-to-poly.c b/gcc/graphite-sese-to-poly.c
index 49856914782..514be1d3847 100644
--- a/gcc/graphite-sese-to-poly.c
+++ b/gcc/graphite-sese-to-poly.c
@@ -33,7 +33,17 @@ along with GCC; see the file COPYING3. If not see
#include "system.h"
#include "coretypes.h"
-#include "tree-ssa.h"
+#include "tree.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-cfg.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
+#include "tree-ssa-loop-manip.h"
+#include "tree-ssa-loop-niter.h"
+#include "tree-ssa-loop.h"
+#include "tree-into-ssa.h"
#include "tree-pass.h"
#include "cfgloop.h"
#include "tree-chrec.h"
@@ -41,6 +51,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-scalar-evolution.h"
#include "domwalk.h"
#include "sese.h"
+#include "tree-ssa-propagate.h"
#ifdef HAVE_cloog
#include "graphite-poly.h"
@@ -90,7 +101,6 @@ remove_simple_copy_phi (gimple_stmt_iterator *psi)
remove_phi_node (psi, false);
gsi_insert_on_edge_immediate (e, stmt);
- SSA_NAME_DEF_STMT (res) = stmt;
}
/* Removes an invariant phi node at position PSI by inserting on the
@@ -665,7 +675,7 @@ extract_affine_name (scop_p s, tree e, __isl_take isl_space *space)
id = isl_id_for_ssa_name (s, e);
dimension = isl_space_find_dim_by_id (space, isl_dim_param, id);
- isl_id_free(id);
+ isl_id_free (id);
dom = isl_set_universe (isl_space_copy (space));
aff = isl_aff_zero_on_domain (isl_local_space_from_space (space));
aff = isl_aff_add_coefficient_si (aff, isl_dim_param, dimension, 1);
@@ -994,7 +1004,7 @@ build_loop_iteration_domains (scop_p scop, struct loop *loop,
if (TREE_CODE (nb_iters) == INTEGER_CST)
{
c = isl_inequality_alloc
- (isl_local_space_from_space(isl_space_copy (space)));
+ (isl_local_space_from_space (isl_space_copy (space)));
c = isl_constraint_set_coefficient_si (c, isl_dim_set, pos, -1);
tree_int_to_gmp (nb_iters, g);
isl_int_set_gmp (v, g);
@@ -1132,8 +1142,8 @@ add_condition_to_pbb (poly_bb_p pbb, gimple stmt, enum tree_code code)
break;
default:
- isl_pw_aff_free(lhs);
- isl_pw_aff_free(rhs);
+ isl_pw_aff_free (lhs);
+ isl_pw_aff_free (rhs);
return;
}
@@ -1220,27 +1230,18 @@ class sese_dom_walker : public dom_walker
{
public:
sese_dom_walker (cdi_direction, sese);
- ~sese_dom_walker ();
virtual void before_dom_children (basic_block);
virtual void after_dom_children (basic_block);
private:
- vec<gimple> conditions_, cases_;
- sese region_;
+ stack_vec<gimple, 3> m_conditions, m_cases;
+ sese m_region;
};
sese_dom_walker::sese_dom_walker (cdi_direction direction, sese region)
- : dom_walker (direction), region_ (region)
+ : dom_walker (direction), m_region (region)
{
- conditions_.create (3);
- cases_.create (3);
-}
-
-sese_dom_walker::~sese_dom_walker ()
-{
- conditions_.release ();
- cases_.release ();
}
/* Call-back for dom_walk executed before visiting the dominated
@@ -1252,7 +1253,7 @@ sese_dom_walker::before_dom_children (basic_block bb)
gimple_bb_p gbb;
gimple stmt;
- if (!bb_in_sese_p (bb, region_))
+ if (!bb_in_sese_p (bb, m_region))
return;
stmt = single_pred_cond_non_loop_exit (bb);
@@ -1261,20 +1262,20 @@ sese_dom_walker::before_dom_children (basic_block bb)
{
edge e = single_pred_edge (bb);
- conditions_.safe_push (stmt);
+ m_conditions.safe_push (stmt);
if (e->flags & EDGE_TRUE_VALUE)
- cases_.safe_push (stmt);
+ m_cases.safe_push (stmt);
else
- cases_.safe_push (NULL);
+ m_cases.safe_push (NULL);
}
gbb = gbb_from_bb (bb);
if (gbb)
{
- GBB_CONDITIONS (gbb) = conditions_.copy ();
- GBB_CONDITION_CASES (gbb) = cases_.copy ();
+ GBB_CONDITIONS (gbb) = m_conditions.copy ();
+ GBB_CONDITION_CASES (gbb) = m_cases.copy ();
}
}
@@ -1284,13 +1285,13 @@ sese_dom_walker::before_dom_children (basic_block bb)
void
sese_dom_walker::after_dom_children (basic_block bb)
{
- if (!bb_in_sese_p (bb, region_))
+ if (!bb_in_sese_p (bb, m_region))
return;
if (single_pred_cond_non_loop_exit (bb))
{
- conditions_.pop ();
- cases_.pop ();
+ m_conditions.pop ();
+ m_cases.pop ();
}
}
@@ -1879,8 +1880,7 @@ build_scop_drs (scop_p scop)
int i, j;
poly_bb_p pbb;
data_reference_p dr;
- vec<data_reference_p> drs;
- drs.create (3);
+ stack_vec<data_reference_p, 3> drs;
/* Remove all the PBBs that do not have data references: these basic
blocks are not handled in the polyhedral representation. */
@@ -1978,8 +1978,7 @@ insert_stmts (scop_p scop, gimple stmt, gimple_seq stmts,
gimple_stmt_iterator insert_gsi)
{
gimple_stmt_iterator gsi;
- vec<gimple> x;
- x.create (3);
+ stack_vec<gimple, 3> x;
gimple_seq_add_stmt (&stmts, stmt);
for (gsi = gsi_start (stmts); !gsi_end_p (gsi); gsi_next (&gsi))
@@ -1987,7 +1986,6 @@ insert_stmts (scop_p scop, gimple stmt, gimple_seq stmts,
gsi_insert_seq_before (&insert_gsi, stmts, GSI_SAME_STMT);
analyze_drs_in_stmts (scop, gsi_bb (insert_gsi), x);
- x.release ();
}
/* Insert the assignment "RES := EXPR" just after AFTER_STMT. */
@@ -1999,8 +1997,7 @@ insert_out_of_ssa_copy (scop_p scop, tree res, tree expr, gimple after_stmt)
gimple_stmt_iterator gsi;
tree var = force_gimple_operand (expr, &stmts, true, NULL_TREE);
gimple stmt = gimple_build_assign (unshare_expr (res), var);
- vec<gimple> x;
- x.create (3);
+ stack_vec<gimple, 3> x;
gimple_seq_add_stmt (&stmts, stmt);
for (gsi = gsi_start (stmts); !gsi_end_p (gsi); gsi_next (&gsi))
@@ -2018,7 +2015,6 @@ insert_out_of_ssa_copy (scop_p scop, tree res, tree expr, gimple after_stmt)
}
analyze_drs_in_stmts (scop, gimple_bb (after_stmt), x);
- x.release ();
}
/* Creates a poly_bb_p for basic_block BB from the existing PBB. */
@@ -2056,8 +2052,7 @@ insert_out_of_ssa_copy_on_edge (scop_p scop, edge e, tree res, tree expr)
tree var = force_gimple_operand (expr, &stmts, true, NULL_TREE);
gimple stmt = gimple_build_assign (unshare_expr (res), var);
basic_block bb;
- vec<gimple> x;
- x.create (3);
+ stack_vec<gimple, 3> x;
gimple_seq_add_stmt (&stmts, stmt);
for (gsi = gsi_start (stmts); !gsi_end_p (gsi); gsi_next (&gsi))
@@ -2074,7 +2069,6 @@ insert_out_of_ssa_copy_on_edge (scop_p scop, edge e, tree res, tree expr)
new_pbb_from_pbb (scop, pbb_from_bb (e->src), bb);
analyze_drs_in_stmts (scop, bb, x);
- x.release ();
}
/* Creates a zero dimension array of the same type as VAR. */
@@ -2179,7 +2173,6 @@ rewrite_close_phi_out_of_ssa (scop_p scop, gimple_stmt_iterator *psi)
stmt = gimple_build_assign (res, arg);
remove_phi_node (psi, false);
gsi_insert_before (&gsi, stmt, GSI_NEW_STMT);
- SSA_NAME_DEF_STMT (res) = stmt;
return;
}
@@ -2256,7 +2249,6 @@ rewrite_phi_out_of_ssa (scop_p scop, gimple_stmt_iterator *psi)
stmt = gimple_build_assign (res, unshare_expr (zero_dim_array));
remove_phi_node (psi, false);
- SSA_NAME_DEF_STMT (res) = stmt;
insert_stmts (scop, stmt, NULL, gsi_after_labels (bb));
}
@@ -2279,7 +2271,6 @@ rewrite_degenerate_phi (gimple_stmt_iterator *psi)
stmt = gimple_build_assign (res, rhs);
remove_phi_node (psi, false);
- SSA_NAME_DEF_STMT (res) = stmt;
gsi = gsi_after_labels (bb);
gsi_insert_before (&gsi, stmt, GSI_NEW_STMT);
@@ -2386,7 +2377,6 @@ handle_scalar_deps_crossing_scop_limits (scop_p scop, tree def, gimple stmt)
gimple assign = gimple_build_assign (new_name, def);
gimple_stmt_iterator psi = gsi_after_labels (SESE_EXIT (region)->dest);
- SSA_NAME_DEF_STMT (new_name) = assign;
update_stmt (assign);
gsi_insert_before (&psi, assign, GSI_SAME_STMT);
}
@@ -2870,8 +2860,7 @@ remove_phi (gimple phi)
tree def;
use_operand_p use_p;
gimple_stmt_iterator gsi;
- vec<gimple> update;
- update.create (3);
+ stack_vec<gimple, 3> update;
unsigned int i;
gimple stmt;
@@ -2890,8 +2879,6 @@ remove_phi (gimple phi)
FOR_EACH_VEC_ELT (update, i, stmt)
update_stmt (stmt);
- update.release ();
-
gsi = gsi_for_phi_node (phi);
remove_phi_node (&gsi, false);
}
@@ -3031,18 +3018,14 @@ rewrite_commutative_reductions_out_of_ssa_close_phi (scop_p scop,
gimple close_phi)
{
bool res;
- vec<gimple> in;
- in.create (10);
- vec<gimple> out;
- out.create (10);
+ stack_vec<gimple, 10> in;
+ stack_vec<gimple, 10> out;
detect_commutative_reduction (scop, close_phi, &in, &out);
res = in.length () > 1;
if (res)
translate_scalar_reduction_to_array (scop, in, out);
- in.release ();
- out.release ();
return res;
}
diff --git a/gcc/graphite.c b/gcc/graphite.c
index 2cea3894da8..176c47c980e 100644
--- a/gcc/graphite.c
+++ b/gcc/graphite.c
@@ -47,7 +47,10 @@ along with GCC; see the file COPYING3. If not see
#include "system.h"
#include "coretypes.h"
#include "diagnostic-core.h"
-#include "tree-ssa.h"
+#include "tree.h"
+#include "gimple.h"
+#include "tree-cfg.h"
+#include "tree-ssa-loop.h"
#include "tree-dump.h"
#include "cfgloop.h"
#include "tree-chrec.h"
@@ -55,6 +58,9 @@ along with GCC; see the file COPYING3. If not see
#include "tree-scalar-evolution.h"
#include "sese.h"
#include "dbgcnt.h"
+#include "tree-parloops.h"
+#include "tree-pass.h"
+#include "tree-cfgcleanup.h"
#ifdef HAVE_cloog
@@ -265,7 +271,7 @@ graphite_transform_loops (void)
return;
ctx = isl_ctx_alloc ();
- isl_options_set_on_error(ctx, ISL_ON_ERROR_ABORT);
+ isl_options_set_on_error (ctx, ISL_ON_ERROR_ABORT);
if (!graphite_initialize (ctx))
return;
@@ -301,10 +307,115 @@ graphite_transform_loops (void)
#else /* If Cloog is not available: #ifndef HAVE_cloog. */
-void
+static void
graphite_transform_loops (void)
{
sorry ("Graphite loop optimizations cannot be used");
}
#endif
+
+
+static unsigned int
+graphite_transforms (void)
+{
+ if (!current_loops)
+ return 0;
+
+ graphite_transform_loops ();
+
+ return 0;
+}
+
+static bool
+gate_graphite_transforms (void)
+{
+ /* Enable -fgraphite pass if any one of the graphite optimization flags
+ is turned on. */
+ if (flag_loop_block
+ || flag_loop_interchange
+ || flag_loop_strip_mine
+ || flag_graphite_identity
+ || flag_loop_parallelize_all
+ || flag_loop_optimize_isl)
+ flag_graphite = 1;
+
+ return flag_graphite != 0;
+}
+
+namespace {
+
+const pass_data pass_data_graphite =
+{
+ GIMPLE_PASS, /* type */
+ "graphite0", /* name */
+ OPTGROUP_LOOP, /* optinfo_flags */
+ true, /* has_gate */
+ false, /* has_execute */
+ TV_GRAPHITE, /* tv_id */
+ ( PROP_cfg | PROP_ssa ), /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ 0, /* todo_flags_finish */
+};
+
+class pass_graphite : public gimple_opt_pass
+{
+public:
+ pass_graphite (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_graphite, ctxt)
+ {}
+
+ /* opt_pass methods: */
+ bool gate () { return gate_graphite_transforms (); }
+
+}; // class pass_graphite
+
+} // anon namespace
+
+gimple_opt_pass *
+make_pass_graphite (gcc::context *ctxt)
+{
+ return new pass_graphite (ctxt);
+}
+
+namespace {
+
+const pass_data pass_data_graphite_transforms =
+{
+ GIMPLE_PASS, /* type */
+ "graphite", /* name */
+ OPTGROUP_LOOP, /* optinfo_flags */
+ true, /* has_gate */
+ true, /* has_execute */
+ TV_GRAPHITE_TRANSFORMS, /* tv_id */
+ ( PROP_cfg | PROP_ssa ), /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ 0, /* todo_flags_finish */
+};
+
+class pass_graphite_transforms : public gimple_opt_pass
+{
+public:
+ pass_graphite_transforms (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_graphite_transforms, ctxt)
+ {}
+
+ /* opt_pass methods: */
+ bool gate () { return gate_graphite_transforms (); }
+ unsigned int execute () { return graphite_transforms (); }
+
+}; // class pass_graphite_transforms
+
+} // anon namespace
+
+gimple_opt_pass *
+make_pass_graphite_transforms (gcc::context *ctxt)
+{
+ return new pass_graphite_transforms (ctxt);
+}
+
+
diff --git a/gcc/haifa-sched.c b/gcc/haifa-sched.c
index 61eaaefa418..728d51b7308 100644
--- a/gcc/haifa-sched.c
+++ b/gcc/haifa-sched.c
@@ -150,6 +150,24 @@ along with GCC; see the file COPYING3. If not see
#ifdef INSN_SCHEDULING
+/* True if we do register pressure relief through live-range
+ shrinkage. */
+static bool live_range_shrinkage_p;
+
+/* Switch on live range shrinkage. */
+void
+initialize_live_range_shrinkage (void)
+{
+ live_range_shrinkage_p = true;
+}
+
+/* Switch off live range shrinkage. */
+void
+finish_live_range_shrinkage (void)
+{
+ live_range_shrinkage_p = false;
+}
+
/* issue_rate is the number of insns that can be scheduled in the same
machine cycle. It can be defined in the config/mach/mach.h file,
otherwise we set it to 1. */
@@ -2519,7 +2537,7 @@ rank_for_schedule (const void *x, const void *y)
rtx tmp = *(const rtx *) y;
rtx tmp2 = *(const rtx *) x;
int tmp_class, tmp2_class;
- int val, priority_val, info_val;
+ int val, priority_val, info_val, diff;
if (MAY_HAVE_DEBUG_INSNS)
{
@@ -2532,6 +2550,22 @@ rank_for_schedule (const void *x, const void *y)
return INSN_LUID (tmp) - INSN_LUID (tmp2);
}
+ if (live_range_shrinkage_p)
+ {
+ /* Don't use SCHED_PRESSURE_MODEL -- it results in much worse
+ code. */
+ gcc_assert (sched_pressure == SCHED_PRESSURE_WEIGHTED);
+ if ((INSN_REG_PRESSURE_EXCESS_COST_CHANGE (tmp) < 0
+ || INSN_REG_PRESSURE_EXCESS_COST_CHANGE (tmp2) < 0)
+ && (diff = (INSN_REG_PRESSURE_EXCESS_COST_CHANGE (tmp)
+ - INSN_REG_PRESSURE_EXCESS_COST_CHANGE (tmp2))) != 0)
+ return diff;
+ /* Sort by INSN_LUID (original insn order), so that we make the
+ sort stable. This minimizes instruction movement, thus
+ minimizing sched's effect on debugging and cross-jumping. */
+ return INSN_LUID (tmp) - INSN_LUID (tmp2);
+ }
+
/* The insn in a schedule group should be issued the first. */
if (flag_sched_group_heuristic &&
SCHED_GROUP_P (tmp) != SCHED_GROUP_P (tmp2))
@@ -2542,8 +2576,6 @@ rank_for_schedule (const void *x, const void *y)
if (sched_pressure != SCHED_PRESSURE_NONE)
{
- int diff;
-
/* Prefer insn whose scheduling results in the smallest register
pressure excess. */
if ((diff = (INSN_REG_PRESSURE_EXCESS_COST_CHANGE (tmp)
@@ -2605,7 +2637,7 @@ rank_for_schedule (const void *x, const void *y)
}
info_val = (*current_sched_info->rank) (tmp, tmp2);
- if(flag_sched_rank_heuristic && info_val)
+ if (flag_sched_rank_heuristic && info_val)
return info_val;
/* Compare insns based on their relation to the last scheduled
@@ -3731,7 +3763,10 @@ schedule_insn (rtx insn)
{
fputc (':', sched_dump);
for (i = 0; i < ira_pressure_classes_num; i++)
- fprintf (sched_dump, "%s%+d(%d)",
+ fprintf (sched_dump, "%s%s%+d(%d)",
+ scheduled_insns.length () > 1
+ && INSN_LUID (insn)
+ < INSN_LUID (scheduled_insns[scheduled_insns.length () - 2]) ? "@" : "",
reg_class_names[ira_pressure_classes[i]],
pressure_info[i].set_increase, pressure_info[i].change);
}
@@ -6519,6 +6554,50 @@ setup_sched_dump (void)
? stderr : dump_file);
}
+/* Try to group comparison and the following conditional jump INSN if
+ they're already adjacent. This is to prevent scheduler from scheduling
+ them apart. */
+
+static void
+try_group_insn (rtx insn)
+{
+ unsigned int condreg1, condreg2;
+ rtx cc_reg_1;
+ rtx prev;
+
+ if (!any_condjump_p (insn))
+ return;
+
+ targetm.fixed_condition_code_regs (&condreg1, &condreg2);
+ cc_reg_1 = gen_rtx_REG (CCmode, condreg1);
+ prev = prev_nonnote_nondebug_insn (insn);
+ if (!reg_referenced_p (cc_reg_1, PATTERN (insn))
+ || !prev
+ || !modified_in_p (cc_reg_1, prev))
+ return;
+
+ /* Different microarchitectures support macro fusions for different
+ combinations of insn pairs. */
+ if (!targetm.sched.macro_fusion_pair_p
+ || !targetm.sched.macro_fusion_pair_p (prev, insn))
+ return;
+
+ SCHED_GROUP_P (insn) = 1;
+}
+
+/* If the last cond jump and the cond register defining insn are consecutive
+ before scheduling, we want them to be in a schedule group. This is good
+ for performance on microarchitectures supporting macro-fusion. */
+
+static void
+group_insns_for_macro_fusion ()
+{
+ basic_block bb;
+
+ FOR_EACH_BB (bb)
+ try_group_insn (BB_END (bb));
+}
+
/* Initialize some global state for the scheduler. This function works
with the common data shared between all the schedulers. It is called
from the scheduler specific initialization routine. */
@@ -6534,9 +6613,11 @@ sched_init (void)
if (targetm.sched.dispatch (NULL_RTX, IS_DISPATCH_ON))
targetm.sched.dispatch_do (NULL_RTX, DISPATCH_INIT);
- if (flag_sched_pressure
- && !reload_completed
- && common_sched_info->sched_pass_id == SCHED_RGN_PASS)
+ if (live_range_shrinkage_p)
+ sched_pressure = SCHED_PRESSURE_WEIGHTED;
+ else if (flag_sched_pressure
+ && !reload_completed
+ && common_sched_info->sched_pass_id == SCHED_RGN_PASS)
sched_pressure = ((enum sched_pressure_algorithm)
PARAM_VALUE (PARAM_SCHED_PRESSURE_ALGORITHM));
else
@@ -6645,6 +6726,11 @@ sched_init (void)
}
curr_state = xmalloc (dfa_state_size);
+
+ /* Group compare and branch insns for macro-fusion. */
+ if (targetm.sched.macro_fusion_p
+ && targetm.sched.macro_fusion_p ())
+ group_insns_for_macro_fusion ();
}
static void haifa_init_only_bb (basic_block, basic_block);
@@ -7879,7 +7965,7 @@ create_check_block_twin (rtx insn, bool mutate_p)
/* Fix priorities. If MUTATE_P is nonzero, this is not necessary,
because it'll be done later in add_to_speculative_block. */
{
- rtx_vec_t priorities_roots = rtx_vec_t();
+ rtx_vec_t priorities_roots = rtx_vec_t ();
clear_priorities (twin, &priorities_roots);
calc_priorities (priorities_roots);
diff --git a/gcc/hash-table.c b/gcc/hash-table.c
index d3cb7b10818..1cf7b234862 100644
--- a/gcc/hash-table.c
+++ b/gcc/hash-table.c
@@ -111,7 +111,7 @@ unsigned int
hash_table_higher_prime_index (unsigned long n)
{
unsigned int low = 0;
- unsigned int high = sizeof(prime_tab) / sizeof(prime_tab[0]);
+ unsigned int high = sizeof (prime_tab) / sizeof (prime_tab[0]);
while (low != high)
{
diff --git a/gcc/hash-table.h b/gcc/hash-table.h
index 00637789923..5f80efb6bf4 100644
--- a/gcc/hash-table.h
+++ b/gcc/hash-table.h
@@ -419,8 +419,8 @@ public:
inline iterator &operator ++ ();
inline bool operator != (const iterator &) const;
private:
- value_type **slot_;
- value_type **limit_;
+ value_type **m_slot;
+ value_type **m_limit;
};
private:
@@ -456,8 +456,8 @@ public:
int (*Callback) (value_type **slot, Argument argument)>
void traverse (Argument argument);
- iterator begin();
- iterator end();
+ iterator begin ();
+ iterator end ();
};
@@ -522,7 +522,7 @@ hash_table <Descriptor, Allocator>::remove_elt (const value_type *value)
template <typename Descriptor,
template <typename Type> class Allocator>
inline size_t
-hash_table <Descriptor, Allocator>::size()
+hash_table <Descriptor, Allocator>::size ()
{
return htab->size;
}
@@ -556,7 +556,7 @@ hash_table <Descriptor, Allocator>::elements_with_deleted ()
template <typename Descriptor,
template <typename Type> class Allocator>
inline double
-hash_table <Descriptor, Allocator>::collisions()
+hash_table <Descriptor, Allocator>::collisions ()
{
if (htab->searches == 0)
return 0.0;
@@ -959,7 +959,7 @@ template <typename Descriptor,
template <typename Type> class Allocator>
inline
hash_table <Descriptor, Allocator>::iterator::iterator ()
-: slot_ (NULL), limit_ (NULL)
+: m_slot (NULL), m_limit (NULL)
{
}
@@ -970,7 +970,7 @@ template <typename Descriptor,
inline
hash_table <Descriptor, Allocator>::iterator::iterator
(value_type **slot, value_type **limit)
-: slot_ (slot), limit_ (limit)
+: m_slot (slot), m_limit (limit)
{
}
@@ -981,7 +981,7 @@ template <typename Descriptor,
inline typename hash_table <Descriptor, Allocator>::value_type &
hash_table <Descriptor, Allocator>::iterator::operator * ()
{
- return **slot_;
+ return **m_slot;
}
/* Slide down the iterator slots until an active entry is found. */
@@ -991,14 +991,14 @@ template <typename Descriptor,
void
hash_table <Descriptor, Allocator>::iterator::slide ()
{
- for ( ; slot_ < limit_; ++slot_ )
+ for ( ; m_slot < m_limit; ++m_slot )
{
- value_type *x = *slot_;
+ value_type *x = *m_slot;
if (x != HTAB_EMPTY_ENTRY && x != HTAB_DELETED_ENTRY)
return;
}
- slot_ = NULL;
- limit_ = NULL;
+ m_slot = NULL;
+ m_limit = NULL;
}
/* Bump the iterator. */
@@ -1008,7 +1008,7 @@ template <typename Descriptor,
inline typename hash_table <Descriptor, Allocator>::iterator &
hash_table <Descriptor, Allocator>::iterator::operator ++ ()
{
- ++slot_;
+ ++m_slot;
slide ();
return *this;
}
@@ -1021,7 +1021,7 @@ inline bool
hash_table <Descriptor, Allocator>::iterator::
operator != (const iterator &other) const
{
- return slot_ != other.slot_ || limit_ != other.limit_;
+ return m_slot != other.m_slot || m_limit != other.m_limit;
}
/* Hash table iterator producers. */
diff --git a/gcc/hooks.c b/gcc/hooks.c
index 3259658e4f4..9f53007337d 100644
--- a/gcc/hooks.c
+++ b/gcc/hooks.c
@@ -331,6 +331,12 @@ hook_bool_rtx_int_int_int_intp_bool_false (rtx a ATTRIBUTE_UNUSED,
return false;
}
+bool
+hook_bool_dint_dint_uint_bool_true (double_int, double_int, unsigned int, bool)
+{
+ return true;
+}
+
/* Generic hook that takes an rtx and returns it. */
rtx
hook_rtx_rtx_identity (rtx x)
diff --git a/gcc/hooks.h b/gcc/hooks.h
index eaf4b03ebbb..38454fbe10a 100644
--- a/gcc/hooks.h
+++ b/gcc/hooks.h
@@ -23,6 +23,7 @@
#define GCC_HOOKS_H
#include "machmode.h"
+#include "double-int.h"
extern bool hook_bool_void_false (void);
extern bool hook_bool_void_true (void);
@@ -60,6 +61,8 @@ extern bool hook_bool_rtx_int_int_int_intp_bool_false (rtx, int, int, int,
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_dint_dint_uint_bool_true (double_int, double_int,
+ unsigned int, bool);
extern void hook_void_void (void);
extern void hook_void_constcharptr (const char *);
diff --git a/gcc/hw-doloop.c b/gcc/hw-doloop.c
index 9b59f5ddc6d..5d266387485 100644
--- a/gcc/hw-doloop.c
+++ b/gcc/hw-doloop.c
@@ -237,7 +237,6 @@ discover_loop (hwloop_info loop, basic_block tail_bb, rtx tail_insn, rtx reg)
bool found_tail;
unsigned dwork = 0;
basic_block bb;
- vec<basic_block> works;
loop->tail = tail_bb;
loop->loop_end = tail_insn;
@@ -253,7 +252,7 @@ discover_loop (hwloop_info loop, basic_block tail_bb, rtx tail_insn, rtx reg)
loop->head = BRANCH_EDGE (tail_bb)->dest;
loop->successor = FALLTHRU_EDGE (tail_bb)->dest;
- works.create (20);
+ stack_vec<basic_block, 20> works;
works.safe_push (loop->head);
found_tail = false;
@@ -340,8 +339,6 @@ discover_loop (hwloop_info loop, basic_block tail_bb, rtx tail_insn, rtx reg)
}
}
}
-
- works.release ();
}
/* Analyze the structure of the loops in the current function. Use
diff --git a/gcc/hwint.c b/gcc/hwint.c
index 134fe1da2cc..f47be4ac5f5 100644
--- a/gcc/hwint.c
+++ b/gcc/hwint.c
@@ -93,7 +93,7 @@ ctz_hwi (unsigned HOST_WIDE_INT x)
int
clz_hwi (unsigned HOST_WIDE_INT x)
{
- return HOST_BITS_PER_WIDE_INT - 1 - floor_log2(x);
+ return HOST_BITS_PER_WIDE_INT - 1 - floor_log2 (x);
}
/* Similar to ctz_hwi, except that the least significant bit is numbered
@@ -204,35 +204,3 @@ least_common_multiple (HOST_WIDE_INT a, HOST_WIDE_INT b)
{
return mul_hwi (abs_hwi (a) / gcd (a, b), abs_hwi (b));
}
-
-#ifdef ENABLE_CHECKING
-/* Sign extend SRC starting from PREC. */
-
-HOST_WIDE_INT
-sext_hwi (HOST_WIDE_INT src, unsigned int prec)
-{
- gcc_checking_assert (prec <= HOST_BITS_PER_WIDE_INT);
-
- if (prec == HOST_BITS_PER_WIDE_INT)
- return src;
- else
- {
- int shift = HOST_BITS_PER_WIDE_INT - prec;
- return (src << shift) >> shift;
- }
-}
-
-/* Zero extend SRC starting from PREC. */
-
-unsigned HOST_WIDE_INT
-zext_hwi (unsigned HOST_WIDE_INT src, unsigned int prec)
-{
- gcc_checking_assert (prec <= HOST_BITS_PER_WIDE_INT);
-
- if (prec == HOST_BITS_PER_WIDE_INT)
- return src;
- else
- return src & (((HOST_WIDE_INT)1 << prec) - 1);
-}
-
-#endif
diff --git a/gcc/hwint.h b/gcc/hwint.h
index 9930baac100..77ae64224f7 100644
--- a/gcc/hwint.h
+++ b/gcc/hwint.h
@@ -37,7 +37,7 @@
# 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];
+extern char sizeof_long_long_must_be_8[sizeof (long long) == 8 ? 1 : -1];
# endif
#endif
@@ -110,11 +110,11 @@ extern char sizeof_long_long_must_be_8[sizeof(long long) == 8 ? 1 : -1];
#endif
-#define HOST_WIDE_INT_UC(X) HOST_WIDE_INT_C(X ## U)
-#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)
+#define HOST_WIDE_INT_UC(X) HOST_WIDE_INT_C (X ## U)
+#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
@@ -168,7 +168,7 @@ typedef HOST_WIDE_INT __gcc_host_wide_int__;
# define HOST_WIDEST_INT_PRINT_UNSIGNED HOST_WIDE_INT_PRINT_UNSIGNED
# define HOST_WIDEST_INT_PRINT_HEX HOST_WIDE_INT_PRINT_HEX
# define HOST_WIDEST_INT_PRINT_DOUBLE_HEX HOST_WIDE_INT_PRINT_DOUBLE_HEX
-# define HOST_WIDEST_INT_C(X) HOST_WIDE_INT(X)
+# define HOST_WIDEST_INT_C(X) HOST_WIDE_INT (X)
#else
# if HOST_BITS_PER_LONGLONG >= 64
# define HOST_BITS_PER_WIDEST_INT HOST_BITS_PER_LONGLONG
@@ -322,9 +322,6 @@ extern HOST_WIDE_INT least_common_multiple (HOST_WIDE_INT, HOST_WIDE_INT);
/* Sign extend SRC starting from PREC. */
-#ifdef ENABLE_CHECKING
-extern HOST_WIDE_INT sext_hwi (HOST_WIDE_INT, unsigned int);
-#else
static inline HOST_WIDE_INT
sext_hwi (HOST_WIDE_INT src, unsigned int prec)
{
@@ -332,24 +329,23 @@ sext_hwi (HOST_WIDE_INT src, unsigned int prec)
return src;
else
{
+ gcc_checking_assert (prec < HOST_BITS_PER_WIDE_INT);
int shift = HOST_BITS_PER_WIDE_INT - prec;
return (src << shift) >> shift;
}
}
-#endif
/* Zero extend SRC starting from PREC. */
-#ifdef ENABLE_CHECKING
-extern unsigned HOST_WIDE_INT zext_hwi (unsigned HOST_WIDE_INT, unsigned int);
-#else
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
- return src & (((HOST_WIDE_INT)1 << prec) - 1);
+ {
+ gcc_checking_assert (prec < HOST_BITS_PER_WIDE_INT);
+ return src & (((HOST_WIDE_INT) 1 << prec) - 1);
+ }
}
-#endif
#endif /* ! GCC_HWINT_H */
diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c
index ebc4f1c3e54..fafff9d0925 100644
--- a/gcc/ifcvt.c
+++ b/gcc/ifcvt.c
@@ -91,7 +91,7 @@ static rtx last_active_insn (basic_block, int);
static rtx find_active_insn_before (basic_block, rtx);
static rtx find_active_insn_after (basic_block, rtx);
static basic_block block_fallthru (basic_block);
-static int cond_exec_process_insns (ce_if_block_t *, rtx, rtx, rtx, rtx, int);
+static int cond_exec_process_insns (ce_if_block_t *, rtx, rtx, rtx, int, int);
static rtx cond_exec_get_condition (rtx);
static rtx noce_get_condition (rtx, rtx *, bool);
static int noce_operand_ok (const_rtx);
@@ -316,7 +316,7 @@ cond_exec_process_insns (ce_if_block_t *ce_info ATTRIBUTE_UNUSED,
/* if block information */rtx start,
/* first insn to look at */rtx end,
/* last insn to look at */rtx test,
- /* conditional execution test */rtx prob_val,
+ /* conditional execution test */int prob_val,
/* probability of branch taken. */int mod_ok)
{
int must_be_last = FALSE;
@@ -336,7 +336,7 @@ cond_exec_process_insns (ce_if_block_t *ce_info ATTRIBUTE_UNUSED,
if (NOTE_P (insn) || DEBUG_INSN_P (insn))
goto insn_done;
- gcc_assert(NONJUMP_INSN_P (insn) || CALL_P (insn));
+ gcc_assert (NONJUMP_INSN_P (insn) || CALL_P (insn));
/* Remove USE insns that get in the way. */
if (reload_completed && GET_CODE (PATTERN (insn)) == USE)
@@ -387,10 +387,10 @@ cond_exec_process_insns (ce_if_block_t *ce_info ATTRIBUTE_UNUSED,
validate_change (insn, &PATTERN (insn), pattern, 1);
- if (CALL_P (insn) && prob_val)
+ if (CALL_P (insn) && prob_val >= 0)
validate_change (insn, &REG_NOTES (insn),
- alloc_EXPR_LIST (REG_BR_PROB, prob_val,
- REG_NOTES (insn)), 1);
+ gen_rtx_INT_LIST ((enum machine_mode) REG_BR_PROB,
+ prob_val, REG_NOTES (insn)), 1);
insn_done:
if (insn == end)
@@ -449,14 +449,15 @@ cond_exec_process_if_block (ce_if_block_t * ce_info,
int then_mod_ok; /* whether conditional mods are ok in THEN */
rtx true_expr; /* test for else block insns */
rtx false_expr; /* test for then block insns */
- rtx true_prob_val; /* probability of else block */
- rtx false_prob_val; /* probability of then block */
+ int true_prob_val; /* probability of else block */
+ int false_prob_val; /* probability of then block */
rtx then_last_head = NULL_RTX; /* Last match at the head of THEN */
rtx else_last_head = NULL_RTX; /* Last match at the head of ELSE */
rtx then_first_tail = NULL_RTX; /* First match at the tail of THEN */
rtx else_first_tail = NULL_RTX; /* First match at the tail of ELSE */
int then_n_insns, else_n_insns, n_insns;
enum rtx_code false_code;
+ rtx note;
/* If test is comprised of && or || elements, and we've failed at handling
all of them together, just use the last test if it is the special case of
@@ -588,14 +589,17 @@ cond_exec_process_if_block (ce_if_block_t * ce_info,
goto fail;
#endif
- true_prob_val = find_reg_note (BB_END (test_bb), REG_BR_PROB, NULL_RTX);
- if (true_prob_val)
+ note = find_reg_note (BB_END (test_bb), REG_BR_PROB, NULL_RTX);
+ if (note)
{
- true_prob_val = XEXP (true_prob_val, 0);
- false_prob_val = GEN_INT (REG_BR_PROB_BASE - INTVAL (true_prob_val));
+ true_prob_val = XINT (note, 0);
+ false_prob_val = REG_BR_PROB_BASE - true_prob_val;
}
else
- false_prob_val = NULL_RTX;
+ {
+ true_prob_val = -1;
+ false_prob_val = -1;
+ }
/* If we have && or || tests, do them here. These tests are in the adjacent
blocks after the first block containing the test. */
@@ -4113,15 +4117,14 @@ dead_or_predicable (basic_block test_bb, basic_block merge_bb,
All that's left is making sure the insns involved can actually
be predicated. */
- rtx cond, prob_val;
+ rtx cond;
cond = cond_exec_get_condition (jump);
if (! cond)
return FALSE;
- prob_val = find_reg_note (jump, REG_BR_PROB, NULL_RTX);
- if (prob_val)
- prob_val = XEXP (prob_val, 0);
+ rtx note = find_reg_note (jump, REG_BR_PROB, NULL_RTX);
+ int prob_val = (note ? XINT (note, 0) : -1);
if (reversep)
{
@@ -4130,8 +4133,8 @@ dead_or_predicable (basic_block test_bb, basic_block merge_bb,
return FALSE;
cond = gen_rtx_fmt_ee (rev, GET_MODE (cond), XEXP (cond, 0),
XEXP (cond, 1));
- if (prob_val)
- prob_val = GEN_INT (REG_BR_PROB_BASE - INTVAL (prob_val));
+ if (prob_val >= 0)
+ prob_val = REG_BR_PROB_BASE - prob_val;
}
if (cond_exec_process_insns (NULL, head, end, cond, prob_val, 0)
@@ -4500,8 +4503,8 @@ const pass_data pass_data_rtl_ifcvt =
class pass_rtl_ifcvt : public rtl_opt_pass
{
public:
- pass_rtl_ifcvt(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_rtl_ifcvt, ctxt)
+ pass_rtl_ifcvt (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_rtl_ifcvt, ctxt)
{}
/* opt_pass methods: */
@@ -4555,8 +4558,8 @@ const pass_data pass_data_if_after_combine =
class pass_if_after_combine : public rtl_opt_pass
{
public:
- pass_if_after_combine(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_if_after_combine, ctxt)
+ pass_if_after_combine (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_if_after_combine, ctxt)
{}
/* opt_pass methods: */
@@ -4609,8 +4612,8 @@ const pass_data pass_data_if_after_reload =
class pass_if_after_reload : public rtl_opt_pass
{
public:
- pass_if_after_reload(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_if_after_reload, ctxt)
+ pass_if_after_reload (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_if_after_reload, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/incpath.c b/gcc/incpath.c
index 018da982c14..54b636034f3 100644
--- a/gcc/incpath.c
+++ b/gcc/incpath.c
@@ -33,7 +33,7 @@
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))
+# 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)
@@ -41,7 +41,7 @@
#if defined INO_T_EQ
#define DIRS_EQ(A, B) ((A)->dev == (B)->dev \
- && INO_T_EQ((A)->ino, (B)->ino))
+ && INO_T_EQ ((A)->ino, (B)->ino))
#else
#define DIRS_EQ(A, B) (!filename_cmp ((A)->canonical_name, (B)->canonical_name))
#endif
@@ -128,7 +128,7 @@ add_standard_paths (const char *sysroot, const char *iprefix,
const char *imultilib, int cxx_stdinc)
{
const struct default_include *p;
- int relocated = cpp_relocated();
+ int relocated = cpp_relocated ();
size_t len;
if (iprefix && (len = cpp_GCC_INCLUDE_DIR_len) != 0)
diff --git a/gcc/init-regs.c b/gcc/init-regs.c
index ddb0b3792ba..2a15b3e0a6f 100644
--- a/gcc/init-regs.c
+++ b/gcc/init-regs.c
@@ -158,8 +158,8 @@ const pass_data pass_data_initialize_regs =
class pass_initialize_regs : public rtl_opt_pass
{
public:
- pass_initialize_regs(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_initialize_regs, ctxt)
+ pass_initialize_regs (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_initialize_regs, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/input.h b/gcc/input.h
index 56f6de0e0e4..8fdc7b28d92 100644
--- a/gcc/input.h
+++ b/gcc/input.h
@@ -37,7 +37,7 @@ extern char builtins_location_check[(BUILTINS_LOCATION
< RESERVED_LOCATION_COUNT) ? 1 : -1];
extern expanded_location expand_location (source_location);
-extern const char * location_get_source_line(expanded_location xloc);
+extern const char *location_get_source_line (expanded_location xloc);
extern expanded_location expand_location_to_spelling_point (source_location);
extern source_location expansion_point_location_if_in_system_header (source_location);
@@ -51,10 +51,11 @@ extern location_t input_location;
#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))
+ ((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))
+ : NULL))
#define input_line LOCATION_LINE (input_location)
#define input_filename LOCATION_FILE (input_location)
diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c
index 983efeb751b..a22f222012c 100644
--- a/gcc/internal-fn.c
+++ b/gcc/internal-fn.c
@@ -109,6 +109,12 @@ expand_STORE_LANES (gimple stmt)
expand_insn (get_multi_vector_move (type, vec_store_lanes_optab), 2, ops);
}
+static void
+expand_ANNOTATE (gimple stmt ATTRIBUTE_UNUSED)
+{
+ gcc_unreachable ();
+}
+
/* This should get expanded in adjust_simduid_builtins. */
static void
diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def
index 5427664b8e3..0f5cc3cba42 100644
--- a/gcc/internal-fn.def
+++ b/gcc/internal-fn.def
@@ -43,3 +43,4 @@ DEF_INTERNAL_FN (STORE_LANES, ECF_CONST | ECF_LEAF)
DEF_INTERNAL_FN (GOMP_SIMD_LANE, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW)
DEF_INTERNAL_FN (GOMP_SIMD_VF, ECF_CONST | ECF_LEAF | ECF_NOTHROW)
DEF_INTERNAL_FN (GOMP_SIMD_LAST_LANE, ECF_CONST | ECF_LEAF | ECF_NOTHROW)
+DEF_INTERNAL_FN (ANNOTATE, ECF_CONST | ECF_LEAF | ECF_NOTHROW)
diff --git a/gcc/intl.c b/gcc/intl.c
index 262745f8049..aa443509a6f 100644
--- a/gcc/intl.c
+++ b/gcc/intl.c
@@ -140,7 +140,7 @@ char *
get_spaces (const char *str)
{
size_t len = gcc_gettext_width (str);
- char *spaces = XNEWVEC(char, len + 1);
+ char *spaces = XNEWVEC (char, len + 1);
memset (spaces, ' ', len);
spaces[len] = '\0';
return spaces;
diff --git a/gcc/intl.h b/gcc/intl.h
index e1c6c2b22f6..d34973e88fc 100644
--- a/gcc/intl.h
+++ b/gcc/intl.h
@@ -38,12 +38,12 @@ extern size_t gcc_gettext_width (const char *);
# define bindtextdomain(domain, directory) (domain)
# undef gettext
# define gettext(msgid) (msgid)
-# define ngettext(singular,plural,n) fake_ngettext(singular,plural,n)
+# define ngettext(singular,plural,n) fake_ngettext (singular, plural, n)
# define gcc_init_libintl() /* nothing */
-# define gcc_gettext_width(s) strlen(s)
+# define gcc_gettext_width(s) strlen (s)
-extern const char *fake_ngettext(const char *singular,const char *plural,
- unsigned long int n);
+extern const char *fake_ngettext (const char *singular, const char *plural,
+ unsigned long int n);
#endif
diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c
index 56b27b257b4..72a96d22c17 100644
--- a/gcc/ipa-cp.c
+++ b/gcc/ipa-cp.c
@@ -104,11 +104,10 @@ along with GCC; see the file COPYING3. If not see
#include "system.h"
#include "coretypes.h"
#include "tree.h"
-#include "target.h"
#include "gimple.h"
-#include "cgraph.h"
+#include "target.h"
#include "ipa-prop.h"
-#include "tree-ssa.h"
+#include "bitmap.h"
#include "tree-pass.h"
#include "flags.h"
#include "diagnostic.h"
@@ -287,22 +286,6 @@ ipa_lat_is_single_const (struct ipcp_lattice *lat)
return true;
}
-/* Return true iff the CS is an edge within a strongly connected component as
- computed by ipa_reduced_postorder. */
-
-static inline bool
-edge_within_scc (struct cgraph_edge *cs)
-{
- struct ipa_dfs_info *caller_dfs = (struct ipa_dfs_info *) cs->caller->symbol.aux;
- struct ipa_dfs_info *callee_dfs;
- struct cgraph_node *callee = cgraph_function_node (cs->callee, NULL);
-
- callee_dfs = (struct ipa_dfs_info *) callee->symbol.aux;
- return (caller_dfs
- && callee_dfs
- && caller_dfs->scc_no == callee_dfs->scc_no);
-}
-
/* Print V which is extracted from a value in a lattice to F. */
static void
@@ -369,7 +352,7 @@ print_lattice (FILE * f, struct ipcp_lattice *lat,
fprintf (f, " [from:");
for (s = val->sources; s; s = s->next)
- fprintf (f, " %i(%i)", s->cs->caller->symbol.order,
+ fprintf (f, " %i(%i)", s->cs->caller->order,
s->cs->frequency);
fprintf (f, "]");
}
@@ -399,7 +382,7 @@ print_all_lattices (FILE * f, bool dump_sources, bool dump_benefits)
info = IPA_NODE_REF (node);
fprintf (f, " Node: %s/%i:\n", cgraph_node_name (node),
- node->symbol.order);
+ node->order);
count = ipa_get_param_count (info);
for (i = 0; i < count; i++)
{
@@ -440,16 +423,16 @@ determine_versionability (struct cgraph_node *node)
/* There are a number of generic reasons functions cannot be versioned. We
also cannot remove parameters if there are type attributes such as fnspec
present. */
- if (node->symbol.alias || node->thunk.thunk_p)
+ if (node->alias || node->thunk.thunk_p)
reason = "alias or thunk";
else if (!node->local.versionable)
reason = "not a tree_versionable_function";
else if (cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE)
reason = "insufficient body availability";
- if (reason && dump_file && !node->symbol.alias && !node->thunk.thunk_p)
+ if (reason && dump_file && !node->alias && !node->thunk.thunk_p)
fprintf (dump_file, "Function %s/%i is not versionable, reason: %s.\n",
- cgraph_node_name (node), node->symbol.order, reason);
+ cgraph_node_name (node), node->order, reason);
node->local.versionable = (reason == NULL);
}
@@ -525,7 +508,7 @@ ipcp_cloning_candidate_p (struct cgraph_node *node)
return false;
}
- if (!optimize_function_for_speed_p (DECL_STRUCT_FUNCTION (node->symbol.decl)))
+ if (!optimize_function_for_speed_p (DECL_STRUCT_FUNCTION (node->decl)))
{
if (dump_file)
fprintf (dump_file, "Not considering %s for cloning; "
@@ -727,9 +710,9 @@ initialize_node_lattices (struct cgraph_node *node)
set_all_contains_variable (plats);
}
if (dump_file && (dump_flags & TDF_DETAILS)
- && !node->symbol.alias && !node->thunk.thunk_p)
+ && !node->alias && !node->thunk.thunk_p)
fprintf (dump_file, "Marking all lattices of %s/%i as %s\n",
- cgraph_node_name (node), node->symbol.order,
+ cgraph_node_name (node), node->order,
disable ? "BOTTOM" : "VARIABLE");
}
@@ -957,7 +940,7 @@ add_value_to_lattice (struct ipcp_lattice *lat, tree newval,
for (val = lat->values; val; val = val->next)
if (values_equal_for_ipcp_p (val->value, newval))
{
- if (edge_within_scc (cs))
+ if (ipa_edge_within_scc (cs))
{
struct ipcp_value_source *s;
for (s = val->sources; s ; s = s->next)
@@ -1030,7 +1013,7 @@ propagate_vals_accross_pass_through (struct cgraph_edge *cs,
are arithmetic functions with circular dependencies, there is infinite
number of them and we would just make lattices bottom. */
if ((ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
- and edge_within_scc (cs))
+ && ipa_edge_within_scc (cs))
ret = set_lattice_contains_variable (dest_lat);
else
for (src_val = src_lat->values; src_val; src_val = src_val->next)
@@ -1061,7 +1044,7 @@ propagate_vals_accross_ancestor (struct cgraph_edge *cs,
struct ipcp_value *src_val;
bool ret = false;
- if (edge_within_scc (cs))
+ if (ipa_edge_within_scc (cs))
return set_lattice_contains_variable (dest_lat);
for (src_val = src_lat->values; src_val; src_val = src_val->next)
@@ -1422,7 +1405,7 @@ propagate_constants_accross_call (struct cgraph_edge *cs)
int i, args_count, parms_count;
callee = cgraph_function_node (cs->callee, &availability);
- if (!callee->symbol.definition)
+ if (!callee->definition)
return false;
gcc_checking_assert (cgraph_function_with_gimple_body_p (callee));
callee_info = IPA_NODE_REF (callee);
@@ -1435,7 +1418,7 @@ propagate_constants_accross_call (struct cgraph_edge *cs)
parameter. However, we might need to uncover a thunk from below a series
of aliases first. */
alias_or_thunk = cs->callee;
- while (alias_or_thunk->symbol.alias)
+ while (alias_or_thunk->alias)
alias_or_thunk = cgraph_alias_target (alias_or_thunk);
if (alias_or_thunk->thunk.thunk_p)
{
@@ -1484,6 +1467,7 @@ ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
HOST_WIDE_INT token, anc_offset;
tree otr_type;
tree t;
+ tree target;
if (param_index == -1
|| known_vals.length () <= (unsigned int) param_index)
@@ -1552,7 +1536,7 @@ ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
binfo = get_binfo_at_offset (binfo, anc_offset, otr_type);
if (!binfo)
return NULL_TREE;
- return gimple_get_virt_method_for_binfo (token, binfo);
+ target = gimple_get_virt_method_for_binfo (token, binfo);
}
else
{
@@ -1561,8 +1545,15 @@ ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
binfo = get_binfo_at_offset (t, anc_offset, otr_type);
if (!binfo)
return NULL_TREE;
- return gimple_get_virt_method_for_binfo (token, binfo);
+ target = gimple_get_virt_method_for_binfo (token, binfo);
}
+#ifdef ENABLE_CHECKING
+ if (target)
+ gcc_assert (possible_polymorphic_call_target_p
+ (ie, cgraph_get_node (target)));
+#endif
+
+ return target;
}
@@ -1606,7 +1597,7 @@ devirtualization_time_bonus (struct cgraph_node *node,
/* Only bare minimum benefit for clearly un-inlineable targets. */
res += 1;
callee = cgraph_get_node (target);
- if (!callee || !callee->symbol.definition)
+ if (!callee || !callee->definition)
continue;
isummary = inline_summary (callee);
if (!isummary->inlinable)
@@ -1619,7 +1610,7 @@ devirtualization_time_bonus (struct cgraph_node *node,
else if (isummary->size <= MAX_INLINE_INSNS_AUTO / 2)
res += 15;
else if (isummary->size <= MAX_INLINE_INSNS_AUTO
- || DECL_DECLARED_INLINE_P (callee->symbol.decl))
+ || DECL_DECLARED_INLINE_P (callee->decl))
res += 7;
}
@@ -1649,7 +1640,7 @@ good_cloning_opportunity_p (struct cgraph_node *node, int time_benefit,
{
if (time_benefit == 0
|| !flag_ipa_cp_clone
- || !optimize_function_for_speed_p (DECL_STRUCT_FUNCTION (node->symbol.decl)))
+ || !optimize_function_for_speed_p (DECL_STRUCT_FUNCTION (node->decl)))
return false;
gcc_assert (size_cost > 0);
@@ -1826,7 +1817,7 @@ estimate_local_effects (struct cgraph_node *node)
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "\nEstimating effects for %s/%i, base_time: %i.\n",
- cgraph_node_name (node), node->symbol.order, base_time);
+ cgraph_node_name (node), node->order, base_time);
always_const = gather_context_independent_values (info, &known_csts,
&known_binfos, &known_aggs,
@@ -2129,7 +2120,7 @@ propagate_constants_topo (struct topo_info *topo)
struct cgraph_edge *cs;
for (cs = v->callees; cs; cs = cs->next_callee)
- if (edge_within_scc (cs)
+ if (ipa_edge_within_scc (cs)
&& propagate_constants_accross_call (cs))
push_node_to_stack (topo, cs->callee);
v = pop_node_from_stack (topo);
@@ -2146,7 +2137,7 @@ propagate_constants_topo (struct topo_info *topo)
estimate_local_effects (v);
add_all_node_vals_to_toposort (v);
for (cs = v->callees; cs; cs = cs->next_callee)
- if (!edge_within_scc (cs))
+ if (!ipa_edge_within_scc (cs))
propagate_constants_accross_call (cs);
}
cycle_nodes.release ();
@@ -2228,7 +2219,7 @@ ipcp_propagate_stage (struct topo_info *topo)
ipa_get_param_count (info));
initialize_node_lattices (node);
}
- if (node->symbol.definition && !node->symbol.alias)
+ if (node->definition && !node->alias)
overall_size += inline_summary (node)->self_size;
if (node->count > max_count)
max_count = node->count;
@@ -2296,8 +2287,8 @@ ipcp_discover_new_direct_edges (struct cgraph_node *node,
fprintf (dump_file, " controlled uses count of param "
"%i bumped down to %i\n", param_index, c);
if (c == 0
- && (to_del = ipa_find_reference ((symtab_node) node,
- (symtab_node) cs->callee,
+ && (to_del = ipa_find_reference (node,
+ cs->callee,
NULL, 0)))
{
if (dump_file && (dump_flags & TDF_DETAILS))
@@ -2553,7 +2544,7 @@ update_profiling_info (struct cgraph_node *orig_node,
fprintf (dump_file, " Problem: node %s/%i has too low count "
HOST_WIDE_INT_PRINT_DEC " while the sum of incoming "
"counts is " HOST_WIDE_INT_PRINT_DEC "\n",
- cgraph_node_name (orig_node), orig_node->symbol.order,
+ cgraph_node_name (orig_node), orig_node->order,
(HOST_WIDE_INT) orig_node_count,
(HOST_WIDE_INT) (orig_sum + new_sum));
@@ -2686,13 +2677,13 @@ create_specialized_node (struct cgraph_node *node,
args_to_skip, "constprop");
ipa_set_node_agg_value_chain (new_node, aggvals);
for (av = aggvals; av; av = av->next)
- ipa_maybe_record_reference ((symtab_node) new_node, av->value,
+ ipa_maybe_record_reference (new_node, av->value,
IPA_REF_ADDR, NULL);
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, " the new node is %s/%i.\n",
- cgraph_node_name (new_node), new_node->symbol.order);
+ cgraph_node_name (new_node), new_node->order);
if (aggvals)
ipa_dump_agg_replacement_values (dump_file, aggvals);
}
@@ -3015,7 +3006,7 @@ intersect_aggregates_with_edge (struct cgraph_edge *cs, int index,
}
else
{
- inter.release();
+ inter.release ();
return vec<ipa_agg_jf_item_t>();
}
return inter;
@@ -3186,7 +3177,7 @@ cgraph_edge_brings_all_agg_vals_for_node (struct cgraph_edge *cs,
return false;
values = intersect_aggregates_with_edge (cs, i, values);
- if (!values.exists())
+ if (!values.exists ())
return false;
for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
@@ -3205,7 +3196,7 @@ cgraph_edge_brings_all_agg_vals_for_node (struct cgraph_edge *cs,
}
if (!found)
{
- values.release();
+ values.release ();
return false;
}
}
@@ -3245,9 +3236,9 @@ perhaps_add_new_callers (struct cgraph_node *node, struct ipcp_value *val)
fprintf (dump_file, " - adding an extra caller %s/%i"
" of %s/%i\n",
xstrdup (cgraph_node_name (cs->caller)),
- cs->caller->symbol.order,
+ cs->caller->order,
xstrdup (cgraph_node_name (val->spec_node)),
- val->spec_node->symbol.order);
+ val->spec_node->order);
cgraph_redirect_edge_callee (cs, val->spec_node);
redirected_sum += cs->count;
@@ -3351,7 +3342,7 @@ decide_about_value (struct cgraph_node *node, int index, HOST_WIDE_INT offset,
if (dump_file)
fprintf (dump_file, " Creating a specialized node of %s/%i.\n",
- cgraph_node_name (node), node->symbol.order);
+ cgraph_node_name (node), node->order);
callers = gather_edges_for_value (val, caller_count);
kv = known_csts.copy ();
@@ -3388,7 +3379,7 @@ decide_whether_version_node (struct cgraph_node *node)
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "\nEvaluating opportunities for %s/%i.\n",
- cgraph_node_name (node), node->symbol.order);
+ cgraph_node_name (node), node->order);
gather_context_independent_values (info, &known_csts, &known_binfos,
info->do_clone_for_all_contexts ? &known_aggs
@@ -3432,7 +3423,7 @@ decide_whether_version_node (struct cgraph_node *node)
if (dump_file)
fprintf (dump_file, " - Creating a specialized node of %s/%i "
"for all known contexts.\n", cgraph_node_name (node),
- node->symbol.order);
+ node->order);
callers = collect_callers_of_node (node);
move_binfos_to_values (known_csts, known_binfos);
@@ -3462,7 +3453,7 @@ spread_undeadness (struct cgraph_node *node)
struct cgraph_edge *cs;
for (cs = node->callees; cs; cs = cs->next_callee)
- if (edge_within_scc (cs))
+ if (ipa_edge_within_scc (cs))
{
struct cgraph_node *callee;
struct ipa_node_params *info;
@@ -3493,7 +3484,7 @@ has_undead_caller_from_outside_scc_p (struct cgraph_node *node,
has_undead_caller_from_outside_scc_p,
NULL, true))
return true;
- else if (!edge_within_scc (cs)
+ else if (!ipa_edge_within_scc (cs)
&& !IPA_NODE_REF (cs->caller)->node_dead)
return true;
return false;
@@ -3507,23 +3498,23 @@ static void
identify_dead_nodes (struct cgraph_node *node)
{
struct cgraph_node *v;
- for (v = node; v ; v = ((struct ipa_dfs_info *) v->symbol.aux)->next_cycle)
+ for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
if (cgraph_will_be_removed_from_program_if_no_direct_calls (v)
&& !cgraph_for_node_and_aliases (v,
has_undead_caller_from_outside_scc_p,
NULL, true))
IPA_NODE_REF (v)->node_dead = 1;
- for (v = node; v ; v = ((struct ipa_dfs_info *) v->symbol.aux)->next_cycle)
+ for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
if (!IPA_NODE_REF (v)->node_dead)
spread_undeadness (v);
if (dump_file && (dump_flags & TDF_DETAILS))
{
- for (v = node; v ; v = ((struct ipa_dfs_info *) v->symbol.aux)->next_cycle)
+ for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
if (IPA_NODE_REF (v)->node_dead)
fprintf (dump_file, " Marking node as dead: %s/%i.\n",
- cgraph_node_name (v), v->symbol.order);
+ cgraph_node_name (v), v->order);
}
}
@@ -3547,7 +3538,7 @@ ipcp_decision_stage (struct topo_info *topo)
{
struct cgraph_node *v;
iterate = false;
- for (v = node; v ; v = ((struct ipa_dfs_info *) v->symbol.aux)->next_cycle)
+ for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle)
if (cgraph_function_with_gimple_body_p (v)
&& ipcp_versionable_function_p (v))
iterate |= decide_whether_version_node (v);
@@ -3620,7 +3611,7 @@ ipcp_generate_summary (void)
FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
{
node->local.versionable
- = tree_versionable_function_p (node->symbol.decl);
+ = tree_versionable_function_p (node->decl);
ipa_analyze_node (node);
}
}
@@ -3671,19 +3662,19 @@ const pass_data pass_data_ipa_cp =
class pass_ipa_cp : public ipa_opt_pass_d
{
public:
- pass_ipa_cp(gcc::context *ctxt)
- : ipa_opt_pass_d(pass_data_ipa_cp, ctxt,
- ipcp_generate_summary, /* generate_summary */
- ipcp_write_summary, /* write_summary */
- ipcp_read_summary, /* read_summary */
- ipa_prop_write_all_agg_replacement, /*
- write_optimization_summary */
- ipa_prop_read_all_agg_replacement, /*
- read_optimization_summary */
- NULL, /* stmt_fixup */
- 0, /* function_transform_todo_flags_start */
- ipcp_transform_function, /* function_transform */
- NULL) /* variable_transform */
+ pass_ipa_cp (gcc::context *ctxt)
+ : ipa_opt_pass_d (pass_data_ipa_cp, ctxt,
+ ipcp_generate_summary, /* generate_summary */
+ ipcp_write_summary, /* write_summary */
+ ipcp_read_summary, /* read_summary */
+ ipa_prop_write_all_agg_replacement, /*
+ write_optimization_summary */
+ ipa_prop_read_all_agg_replacement, /*
+ read_optimization_summary */
+ NULL, /* stmt_fixup */
+ 0, /* function_transform_todo_flags_start */
+ ipcp_transform_function, /* function_transform */
+ NULL) /* variable_transform */
{}
/* opt_pass methods: */
diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c
index 85bc5b0652b..80c6b73a4b1 100644
--- a/gcc/ipa-devirt.c
+++ b/gcc/ipa-devirt.c
@@ -109,6 +109,7 @@ along with GCC; see the file COPYING3. If not see
#include "system.h"
#include "coretypes.h"
#include "tm.h"
+#include "tree.h"
#include "cgraph.h"
#include "tree-pass.h"
#include "ggc.h"
@@ -373,7 +374,7 @@ add_type_duplicate (odr_type val, tree type)
unsigned int i;
TYPE_BINFO (val->type) = TYPE_BINFO (type);
- for (i = 0; i < val->types->length(); i++)
+ for (i = 0; i < val->types->length (); i++)
{
if (TYPE_BINFO ((*val->types)[i])
== master_binfo)
@@ -438,7 +439,7 @@ get_odr_type (tree type, bool insert)
}
/* First record bases, then add into array so ids are increasing. */
if (odr_types_ptr)
- val->id = odr_types.length();
+ val->id = odr_types.length ();
vec_safe_push (odr_types_ptr, val);
}
return val;
@@ -460,17 +461,17 @@ dump_odr_type (FILE *f, odr_type t, int indent=0)
DECL_SOURCE_FILE (TYPE_NAME (t->type)),
DECL_SOURCE_LINE (TYPE_NAME (t->type)));
}
- if (t->bases.length())
+ if (t->bases.length ())
{
fprintf (f, "%*s base odr type ids: ", indent * 2, "");
- for (i = 0; i < t->bases.length(); i++)
+ for (i = 0; i < t->bases.length (); i++)
fprintf (f, " %i", t->bases[i]->id);
fprintf (f, "\n");
}
- if (t->derived_types.length())
+ if (t->derived_types.length ())
{
fprintf (f, "%*s derived types:\n", indent * 2, "");
- for (i = 0; i < t->derived_types.length(); i++)
+ for (i = 0; i < t->derived_types.length (); i++)
dump_odr_type (f, t->derived_types[i], indent + 1);
}
fprintf (f, "\n");
@@ -485,19 +486,19 @@ dump_type_inheritance_graph (FILE *f)
if (!odr_types_ptr)
return;
fprintf (f, "\n\nType inheritance graph:\n");
- for (i = 0; i < odr_types.length(); i++)
+ for (i = 0; i < odr_types.length (); i++)
{
- if (odr_types[i]->bases.length() == 0)
+ if (odr_types[i]->bases.length () == 0)
dump_odr_type (f, odr_types[i]);
}
- for (i = 0; i < odr_types.length(); i++)
+ for (i = 0; i < odr_types.length (); i++)
{
- if (odr_types[i]->types && odr_types[i]->types->length())
+ if (odr_types[i]->types && odr_types[i]->types->length ())
{
unsigned int j;
fprintf (f, "Duplicate tree types for odr type %i\n", i);
print_node (f, "", odr_types[i]->type, 0);
- for (j = 0; j < odr_types[i]->types->length(); j++)
+ for (j = 0; j < odr_types[i]->types->length (); j++)
{
tree t;
fprintf (f, "duplicate #%i\n", j);
@@ -543,9 +544,9 @@ build_type_inheritance_graph (void)
/* We reconstruct the graph starting of types of all methods seen in the
the unit. */
FOR_EACH_FUNCTION (n)
- if (DECL_VIRTUAL_P (n->symbol.decl)
- && symtab_real_symbol_p ((symtab_node)n))
- get_odr_type (method_class_type (TREE_TYPE (n->symbol.decl)), true);
+ if (DECL_VIRTUAL_P (n->decl)
+ && symtab_real_symbol_p (n))
+ get_odr_type (method_class_type (TREE_TYPE (n->decl)), true);
if (inheritance_dump_file)
{
dump_type_inheritance_graph (inheritance_dump_file);
@@ -571,8 +572,8 @@ maybe_record_node (vec <cgraph_node *> &nodes,
&& !pointer_set_insert (inserted, target)
&& (target_node = cgraph_get_node (target)) != NULL
&& (TREE_PUBLIC (target)
- || target_node->symbol.definition)
- && symtab_real_symbol_p ((symtab_node)target_node))
+ || target_node->definition)
+ && symtab_real_symbol_p (target_node))
{
pointer_set_insert (cached_polymorphic_call_targets,
target_node);
@@ -626,7 +627,7 @@ record_binfo (vec <cgraph_node *> &nodes,
if (TREE_CODE (vtable) == POINTER_PLUS_EXPR)
vtable = TREE_OPERAND (TREE_OPERAND (vtable, 0), 0);
vnode = varpool_get_node (vtable);
- if (!vnode || !vnode->symbol.definition)
+ if (!vnode || !vnode->definition)
return;
}
tree target = gimple_get_virt_method_for_binfo (otr_token, type_binfo);
@@ -665,7 +666,7 @@ possible_polymorphic_call_targets_1 (vec <cgraph_node *> &nodes,
record_binfo (nodes, binfo, otr_type, binfo, otr_token, inserted,
matched_vtables, type->anonymous_namespace);
- for (i = 0; i < type->derived_types.length(); i++)
+ for (i = 0; i < type->derived_types.length (); i++)
possible_polymorphic_call_targets_1 (nodes, inserted,
matched_vtables,
otr_type,
@@ -760,8 +761,8 @@ devirt_variable_node_removal_hook (struct varpool_node *n,
void *d ATTRIBUTE_UNUSED)
{
if (cached_polymorphic_call_targets
- && DECL_VIRTUAL_P (n->symbol.decl)
- && type_in_anonymous_namespace_p (DECL_CONTEXT (n->symbol.decl)))
+ && DECL_VIRTUAL_P (n->decl)
+ && type_in_anonymous_namespace_p (DECL_CONTEXT (n->decl)))
free_polymorphic_call_targets_hash ();
}
@@ -854,7 +855,7 @@ possible_polymorphic_call_targets (tree otr_type,
/* Walk recursively all derived types. Here we need to lookup proper basetype
via their BINFO walk that is done by record_binfo */
- for (i = 0; i < type->derived_types.length(); i++)
+ for (i = 0; i < type->derived_types.length (); i++)
possible_polymorphic_call_targets_1 (nodes, inserted,
matched_vtables,
otr_type, type->derived_types[i],
@@ -890,7 +891,7 @@ dump_possible_polymorphic_call_targets (FILE *f,
final ? " (full list)" : " (partial list, may call to other unit)");
for (i = 0; i < targets.length (); i++)
fprintf (f, " %s/%i", cgraph_node_name (targets[i]),
- targets[i]->symbol.order);
+ targets[i]->order);
fprintf (f, "\n");
}
@@ -905,13 +906,19 @@ possible_polymorphic_call_target_p (tree otr_type,
{
vec <cgraph_node *> targets;
unsigned int i;
+ bool final;
if (!odr_hash.is_created ())
return true;
- targets = possible_polymorphic_call_targets (otr_type, otr_token);
+ targets = possible_polymorphic_call_targets (otr_type, otr_token, &final);
for (i = 0; i < targets.length (); i++)
if (n == targets[i])
return true;
+
+ /* At a moment we allow middle end to dig out new external declarations
+ as a targets of polymorphic calls. */
+ if (!final && !n->definition)
+ return true;
return false;
}
@@ -931,10 +938,10 @@ update_type_inheritance_graph (void)
/* We reconstruct the graph starting of types of all methods seen in the
the unit. */
FOR_EACH_FUNCTION (n)
- if (DECL_VIRTUAL_P (n->symbol.decl)
- && !n->symbol.definition
- && symtab_real_symbol_p ((symtab_node)n))
- get_odr_type (method_class_type (TREE_TYPE (n->symbol.decl)), true);
+ if (DECL_VIRTUAL_P (n->decl)
+ && !n->definition
+ && symtab_real_symbol_p (n))
+ get_odr_type (method_class_type (TREE_TYPE (n->decl)), true);
timevar_pop (TV_IPA_INHERITANCE);
}
@@ -948,13 +955,13 @@ likely_target_p (struct cgraph_node *n)
{
int flags;
/* cxa_pure_virtual and similar things are not likely. */
- if (TREE_CODE (TREE_TYPE (n->symbol.decl)) != METHOD_TYPE)
+ if (TREE_CODE (TREE_TYPE (n->decl)) != METHOD_TYPE)
return false;
- flags = flags_from_decl_or_type (n->symbol.decl);
+ flags = flags_from_decl_or_type (n->decl);
if (flags & ECF_NORETURN)
return false;
if (lookup_attribute ("cold",
- DECL_ATTRIBUTES (n->symbol.decl)))
+ DECL_ATTRIBUTES (n->decl)))
return false;
if (n->frequency < NODE_FREQUENCY_NORMAL)
return false;
@@ -981,7 +988,7 @@ ipa_devirt (void)
bool update = false;
if (dump_file && n->indirect_calls)
fprintf (dump_file, "\n\nProcesing function %s/%i\n",
- cgraph_node_name (n), n->symbol.order);
+ cgraph_node_name (n), n->order);
for (e = n->indirect_calls; e; e = e->next_callee)
if (e->indirect_info->polymorphic)
{
@@ -1024,7 +1031,7 @@ ipa_devirt (void)
nmultiple++;
continue;
}
- for (i = 0; i < targets.length(); i++)
+ for (i = 0; i < targets.length (); i++)
if (likely_target_p (targets[i]))
{
if (likely_target)
@@ -1062,7 +1069,7 @@ ipa_devirt (void)
}
continue;
}
- if (!likely_target->symbol.definition)
+ if (!likely_target->definition)
{
if (dump_file)
fprintf (dump_file, "Target is not an definition\n");
@@ -1073,7 +1080,7 @@ ipa_devirt (void)
can handle these just well, it is common for programs to
incorrectly with headers defining methods they are linked
with. */
- if (DECL_EXTERNAL (likely_target->symbol.decl))
+ if (DECL_EXTERNAL (likely_target->decl))
{
if (dump_file)
fprintf (dump_file, "Target is external\n");
@@ -1082,7 +1089,7 @@ ipa_devirt (void)
}
if (cgraph_function_body_availability (likely_target)
<= AVAIL_OVERWRITABLE
- && symtab_can_be_discarded ((symtab_node) likely_target))
+ && symtab_can_be_discarded (likely_target))
{
if (dump_file)
fprintf (dump_file, "Target is overwritable\n");
@@ -1094,14 +1101,14 @@ ipa_devirt (void)
if (dump_file)
fprintf (dump_file,
"Speculatively devirtualizing call in %s/%i to %s/%i\n",
- cgraph_node_name (n), n->symbol.order,
+ cgraph_node_name (n), n->order,
cgraph_node_name (likely_target),
- likely_target->symbol.order);
- if (!symtab_can_be_discarded ((symtab_node) likely_target))
+ likely_target->order);
+ if (!symtab_can_be_discarded (likely_target))
{
cgraph_node *alias;
alias = cgraph (symtab_nonoverwritable_alias
- ((symtab_node)likely_target));
+ (likely_target));
if (alias)
likely_target = alias;
}
@@ -1157,17 +1164,17 @@ const pass_data pass_data_ipa_devirt =
class pass_ipa_devirt : public ipa_opt_pass_d
{
public:
- pass_ipa_devirt(gcc::context *ctxt)
- : ipa_opt_pass_d(pass_data_ipa_devirt, ctxt,
- NULL, /* generate_summary */
- NULL, /* write_summary */
- NULL, /* read_summary */
- NULL, /* write_optimization_summary */
- NULL, /* read_optimization_summary */
- NULL, /* stmt_fixup */
- 0, /* function_transform_todo_flags_start */
- NULL, /* function_transform */
- NULL) /* variable_transform */
+ pass_ipa_devirt (gcc::context *ctxt)
+ : ipa_opt_pass_d (pass_data_ipa_devirt, ctxt,
+ NULL, /* generate_summary */
+ NULL, /* write_summary */
+ NULL, /* read_summary */
+ NULL, /* write_optimization_summary */
+ NULL, /* read_optimization_summary */
+ NULL, /* stmt_fixup */
+ 0, /* function_transform_todo_flags_start */
+ NULL, /* function_transform */
+ NULL) /* variable_transform */
{}
/* opt_pass methods: */
diff --git a/gcc/ipa-inline-analysis.c b/gcc/ipa-inline-analysis.c
index ba6221e41fd..445872387d8 100644
--- a/gcc/ipa-inline-analysis.c
+++ b/gcc/ipa-inline-analysis.c
@@ -72,14 +72,20 @@ along with GCC; see the file COPYING3. If not see
#include "tree-inline.h"
#include "langhooks.h"
#include "flags.h"
-#include "cgraph.h"
#include "diagnostic.h"
#include "gimple-pretty-print.h"
#include "params.h"
#include "tree-pass.h"
#include "coverage.h"
#include "ggc.h"
-#include "tree-ssa.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-cfg.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
+#include "tree-ssa-loop-niter.h"
+#include "tree-ssa-loop.h"
#include "ipa-prop.h"
#include "lto-streamer.h"
#include "data-streamer.h"
@@ -89,6 +95,7 @@ along with GCC; see the file COPYING3. If not see
#include "cfgloop.h"
#include "tree-scalar-evolution.h"
#include "ipa-utils.h"
+#include "cilk.h"
/* Estimate runtime of function can easilly run into huge numbers with many
nested loops. Be sure we can compute time * INLINE_SIZE_SCALE * 2 in an
@@ -1292,7 +1299,7 @@ dump_inline_edge_summary (FILE *f, int indent, struct cgraph_node *node,
fprintf (f,
"%*s%s/%i %s\n%*s loop depth:%2i freq:%4i size:%2i"
" time: %2i callee size:%2i stack:%2i",
- indent, "", cgraph_node_name (callee), callee->symbol.order,
+ indent, "", cgraph_node_name (callee), callee->order,
!edge->inline_failed
? "inlined" : cgraph_inline_failed_string (edge-> inline_failed),
indent, "", es->loop_depth, edge->frequency,
@@ -1352,14 +1359,14 @@ dump_inline_edge_summary (FILE *f, int indent, struct cgraph_node *node,
void
dump_inline_summary (FILE *f, struct cgraph_node *node)
{
- if (node->symbol.definition)
+ if (node->definition)
{
struct inline_summary *s = inline_summary (node);
size_time_entry *e;
int i;
fprintf (f, "Inline summary for %s/%i", cgraph_node_name (node),
- node->symbol.order);
- if (DECL_DISREGARD_INLINE_LIMITS (node->symbol.decl))
+ node->order);
+ if (DECL_DISREGARD_INLINE_LIMITS (node->decl))
fprintf (f, " always_inline");
if (s->inlinable)
fprintf (f, " inlinable");
@@ -1428,12 +1435,15 @@ initialize_inline_failed (struct cgraph_edge *e)
if (e->indirect_unknown_callee)
e->inline_failed = CIF_INDIRECT_UNKNOWN_CALL;
- else if (!callee->symbol.definition)
+ else if (!callee->definition)
e->inline_failed = CIF_BODY_NOT_AVAILABLE;
else if (callee->local.redefined_extern_inline)
e->inline_failed = CIF_REDEFINED_EXTERN_INLINE;
else if (e->call_stmt_cannot_inline_p)
e->inline_failed = CIF_MISMATCHED_ARGUMENTS;
+ else if (cfun && fn_contains_cilk_spawn_p (cfun))
+ /* We can't inline if the function is spawing a function. */
+ e->inline_failed = CIF_FUNCTION_NOT_INLINABLE;
else
e->inline_failed = CIF_FUNCTION_NOT_CONSIDERED;
}
@@ -1815,7 +1825,7 @@ compute_bb_predicates (struct cgraph_node *node,
struct ipa_node_params *parms_info,
struct inline_summary *summary)
{
- struct function *my_function = DECL_STRUCT_FUNCTION (node->symbol.decl);
+ struct function *my_function = DECL_STRUCT_FUNCTION (node->decl);
bool done = false;
basic_block bb;
@@ -2257,6 +2267,77 @@ array_index_predicate (struct inline_summary *info,
return p;
}
+/* For a typical usage of __builtin_expect (a<b, 1), we
+ may introduce an extra relation stmt:
+ With the builtin, we have
+ t1 = a <= b;
+ t2 = (long int) t1;
+ t3 = __builtin_expect (t2, 1);
+ if (t3 != 0)
+ goto ...
+ Without the builtin, we have
+ if (a<=b)
+ goto...
+ This affects the size/time estimation and may have
+ an impact on the earlier inlining.
+ Here find this pattern and fix it up later. */
+
+static gimple
+find_foldable_builtin_expect (basic_block bb)
+{
+ gimple_stmt_iterator bsi;
+
+ for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi))
+ {
+ gimple stmt = gsi_stmt (bsi);
+ if (gimple_call_builtin_p (stmt, BUILT_IN_EXPECT))
+ {
+ tree var = gimple_call_lhs (stmt);
+ tree arg = gimple_call_arg (stmt, 0);
+ use_operand_p use_p;
+ gimple use_stmt;
+ bool match = false;
+ bool done = false;
+
+ if (!var || !arg)
+ continue;
+ gcc_assert (TREE_CODE (var) == SSA_NAME);
+
+ while (TREE_CODE (arg) == SSA_NAME)
+ {
+ gimple stmt_tmp = SSA_NAME_DEF_STMT (arg);
+ if (!is_gimple_assign (stmt_tmp))
+ break;
+ switch (gimple_assign_rhs_code (stmt_tmp))
+ {
+ case LT_EXPR:
+ case LE_EXPR:
+ case GT_EXPR:
+ case GE_EXPR:
+ case EQ_EXPR:
+ case NE_EXPR:
+ match = true;
+ done = true;
+ break;
+ case NOP_EXPR:
+ break;
+ default:
+ done = true;
+ break;
+ }
+ if (done)
+ break;
+ arg = gimple_assign_rhs1 (stmt_tmp);
+ }
+
+ if (match && single_imm_use (var, &use_p, &use_stmt)
+ && gimple_code (use_stmt) == GIMPLE_COND)
+ return use_stmt;
+ }
+ }
+ return NULL;
+}
+
/* Compute function body size parameters for NODE.
When EARLY is true, we compute only simple summaries without
non-trivial predicates to drive the early inliner. */
@@ -2271,7 +2352,7 @@ estimate_function_body_sizes (struct cgraph_node *node, bool early)
<0,2>. */
basic_block bb;
gimple_stmt_iterator bsi;
- struct function *my_function = DECL_STRUCT_FUNCTION (node->symbol.decl);
+ struct function *my_function = DECL_STRUCT_FUNCTION (node->decl);
int freq;
struct inline_summary *info = inline_summary (node);
struct predicate bb_predicate;
@@ -2280,6 +2361,7 @@ estimate_function_body_sizes (struct cgraph_node *node, bool early)
int nblocks, n;
int *order;
predicate array_index = true_predicate ();
+ gimple fix_builtin_expect_stmt;
info->conds = NULL;
info->entry = NULL;
@@ -2318,7 +2400,7 @@ estimate_function_body_sizes (struct cgraph_node *node, bool early)
for (n = 0; n < nblocks; n++)
{
bb = BASIC_BLOCK (order[n]);
- freq = compute_call_stmt_bb_frequency (node->symbol.decl, bb);
+ freq = compute_call_stmt_bb_frequency (node->decl, bb);
/* TODO: Obviously predicates can be propagated down across CFG. */
if (parms_info)
@@ -2360,6 +2442,8 @@ estimate_function_body_sizes (struct cgraph_node *node, bool early)
}
}
+ fix_builtin_expect_stmt = find_foldable_builtin_expect (bb);
+
for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi))
{
gimple stmt = gsi_stmt (bsi);
@@ -2368,6 +2452,14 @@ estimate_function_body_sizes (struct cgraph_node *node, bool early)
int prob;
struct predicate will_be_nonconstant;
+ /* This relation stmt should be folded after we remove
+ buildin_expect call. Adjust the cost here. */
+ if (stmt == fix_builtin_expect_stmt)
+ {
+ this_size--;
+ this_time--;
+ }
+
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, " ");
@@ -2655,7 +2747,7 @@ compute_inline_parameters (struct cgraph_node *node, bool early)
}
/* Even is_gimple_min_invariant rely on current_function_decl. */
- push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
+ push_cfun (DECL_STRUCT_FUNCTION (node->decl));
/* Estimate the stack size for the function if we're optimizing. */
self_stack_size = optimize ? estimated_stack_frame_size (node) : 0;
@@ -2665,13 +2757,13 @@ compute_inline_parameters (struct cgraph_node *node, bool early)
/* Can this function be inlined at all? */
if (!optimize && !lookup_attribute ("always_inline",
- DECL_ATTRIBUTES (node->symbol.decl)))
+ DECL_ATTRIBUTES (node->decl)))
info->inlinable = false;
else
- info->inlinable = tree_inlinable_function_p (node->symbol.decl);
+ info->inlinable = tree_inlinable_function_p (node->decl);
/* Type attributes can use parameter indices to describe them. */
- if (TYPE_ATTRIBUTES (TREE_TYPE (node->symbol.decl)))
+ if (TYPE_ATTRIBUTES (TREE_TYPE (node->decl)))
node->local.can_change_signature = false;
else
{
@@ -2683,7 +2775,7 @@ compute_inline_parameters (struct cgraph_node *node, bool early)
/* Functions calling builtin_apply can not change signature. */
for (e = node->callees; e; e = e->next_callee)
{
- tree cdecl = e->callee->symbol.decl;
+ tree cdecl = e->callee->decl;
if (DECL_BUILT_IN (cdecl)
&& DECL_BUILT_IN_CLASS (cdecl) == BUILT_IN_NORMAL
&& (DECL_FUNCTION_CODE (cdecl) == BUILT_IN_APPLY_ARGS
@@ -2739,12 +2831,12 @@ const pass_data pass_data_inline_parameters =
class pass_inline_parameters : public gimple_opt_pass
{
public:
- pass_inline_parameters(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_inline_parameters, ctxt)
+ pass_inline_parameters (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_inline_parameters, ctxt)
{}
/* opt_pass methods: */
- opt_pass * clone () { return new pass_inline_parameters (ctxt_); }
+ opt_pass * clone () { return new pass_inline_parameters (m_ctxt); }
unsigned int execute () {
return compute_inline_parameters_for_current ();
}
@@ -2791,7 +2883,7 @@ estimate_edge_devirt_benefit (struct cgraph_edge *ie,
gcc_checking_assert (*size >= 0);
callee = cgraph_get_node (target);
- if (!callee || !callee->symbol.definition)
+ if (!callee || !callee->definition)
return false;
isummary = inline_summary (callee);
return isummary->inlinable;
@@ -2897,7 +2989,7 @@ estimate_node_size_and_time (struct cgraph_node *node,
bool found = false;
fprintf (dump_file, " Estimating body: %s/%i\n"
" Known to be false: ", cgraph_node_name (node),
- node->symbol.order);
+ node->order);
for (i = predicate_not_inlined_condition;
i < (predicate_first_dynamic_condition
@@ -2948,7 +3040,7 @@ estimate_node_size_and_time (struct cgraph_node *node,
hints |= INLINE_HINT_array_index;
if (info->scc_no)
hints |= INLINE_HINT_in_scc;
- if (DECL_DECLARED_INLINE_P (node->symbol.decl))
+ if (DECL_DECLARED_INLINE_P (node->decl))
hints |= INLINE_HINT_declared_inline;
estimate_calls_size_and_time (node, &size, &time, &hints, possible_truths,
@@ -3408,8 +3500,8 @@ simple_edge_hints (struct cgraph_edge *edge)
&& !cgraph_edge_recursive_p (edge))
hints |= INLINE_HINT_same_scc;
- if (to->symbol.lto_file_data && edge->callee->symbol.lto_file_data
- && to->symbol.lto_file_data != edge->callee->symbol.lto_file_data)
+ if (to->lto_file_data && edge->callee->lto_file_data
+ && to->lto_file_data != edge->callee->lto_file_data)
hints |= INLINE_HINT_cross_module;
return hints;
@@ -3628,7 +3720,7 @@ do_estimate_growth (struct cgraph_node *node)
return zero or negative growths. */
if (d.self_recursive)
d.growth = d.growth < info->size ? info->size : d.growth;
- else if (DECL_EXTERNAL (node->symbol.decl))
+ else if (DECL_EXTERNAL (node->decl))
;
else
{
@@ -3637,7 +3729,7 @@ do_estimate_growth (struct cgraph_node *node)
/* COMDAT functions are very often not shared across multiple units
since they come from various template instantiations.
Take this into account. */
- else if (DECL_COMDAT (node->symbol.decl)
+ else if (DECL_COMDAT (node->decl)
&& cgraph_can_remove_if_no_direct_calls_p (node))
d.growth -= (info->size
* (100 - PARAM_VALUE (PARAM_COMDAT_SHARING_PROBABILITY))
@@ -3674,11 +3766,11 @@ inline_indirect_intraprocedural_analysis (struct cgraph_node *node)
static void
inline_analyze_function (struct cgraph_node *node)
{
- push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
+ push_cfun (DECL_STRUCT_FUNCTION (node->decl));
if (dump_file)
fprintf (dump_file, "\nAnalyzing function: %s/%u\n",
- cgraph_node_name (node), node->symbol.order);
+ cgraph_node_name (node), node->order);
if (optimize && !node->thunk.thunk_p)
inline_indirect_intraprocedural_analysis (node);
compute_inline_parameters (node, false);
@@ -3731,7 +3823,7 @@ inline_generate_summary (void)
inline_free_summary ();
FOR_EACH_DEFINED_FUNCTION (node)
- if (!node->symbol.alias)
+ if (!node->alias)
inline_analyze_function (node);
}
@@ -3963,18 +4055,18 @@ inline_write_summary (void)
for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
{
- symtab_node snode = lto_symtab_encoder_deref (encoder, i);
+ symtab_node *snode = lto_symtab_encoder_deref (encoder, i);
cgraph_node *cnode = dyn_cast <cgraph_node> (snode);
- if (cnode && cnode->symbol.definition && !cnode->symbol.alias)
+ if (cnode && cnode->definition && !cnode->alias)
count++;
}
streamer_write_uhwi (ob, count);
for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
{
- symtab_node snode = lto_symtab_encoder_deref (encoder, i);
+ symtab_node *snode = lto_symtab_encoder_deref (encoder, i);
cgraph_node *cnode = dyn_cast <cgraph_node> (snode);
- if (cnode && (node = cnode)->symbol.definition && !node->symbol.alias)
+ if (cnode && (node = cnode)->definition && !node->alias)
{
struct inline_summary *info = inline_summary (node);
struct bitpack_d bp;
@@ -3985,7 +4077,7 @@ inline_write_summary (void)
streamer_write_uhwi (ob,
lto_symtab_encoder_encode (encoder,
- (symtab_node)
+
node));
streamer_write_hwi (ob, info->estimated_self_stack_size);
streamer_write_hwi (ob, info->self_size);
diff --git a/gcc/ipa-inline-transform.c b/gcc/ipa-inline-transform.c
index d8a637cb850..32f068e460e 100644
--- a/gcc/ipa-inline-transform.c
+++ b/gcc/ipa-inline-transform.c
@@ -34,11 +34,10 @@ along with GCC; see the file COPYING3. If not see
#include "tm.h"
#include "tree.h"
#include "langhooks.h"
-#include "cgraph.h"
#include "intl.h"
#include "coverage.h"
#include "ggc.h"
-#include "tree-ssa.h"
+#include "tree-cfg.h"
#include "ipa-prop.h"
#include "ipa-inline.h"
#include "tree-inline.h"
@@ -86,15 +85,15 @@ can_remove_node_now_p_1 (struct cgraph_node *node)
/* FIXME: When address is taken of DECL_EXTERNAL function we still
can remove its offline copy, but we would need to keep unanalyzed node in
the callgraph so references can point to it. */
- return (!node->symbol.address_taken
- && !ipa_ref_has_aliases_p (&node->symbol.ref_list)
+ return (!node->address_taken
+ && !ipa_ref_has_aliases_p (&node->ref_list)
&& !node->used_as_abstract_origin
&& cgraph_can_remove_if_no_direct_calls_p (node)
/* Inlining might enable more devirtualizing, so we want to remove
those only after all devirtualizable virtual calls are processed.
Lacking may edges in callgraph we just preserve them post
inlining. */
- && !DECL_VIRTUAL_P (node->symbol.decl)
+ && !DECL_VIRTUAL_P (node->decl)
/* During early inlining some unanalyzed cgraph nodes might be in the
callgraph and they might reffer the function in question. */
&& !cgraph_new_nodes);
@@ -113,10 +112,10 @@ can_remove_node_now_p (struct cgraph_node *node, struct cgraph_edge *e)
/* When we see same comdat group, we need to be sure that all
items can be removed. */
- if (!node->symbol.same_comdat_group)
+ if (!node->same_comdat_group)
return true;
- for (next = cgraph (node->symbol.same_comdat_group);
- next != node; next = cgraph (next->symbol.same_comdat_group))
+ for (next = cgraph (node->same_comdat_group);
+ next != node; next = cgraph (next->same_comdat_group))
if ((next->callers && next->callers != e)
|| !can_remove_node_now_p_1 (next))
return false;
@@ -162,28 +161,28 @@ clone_inlined_nodes (struct cgraph_edge *e, bool duplicate,
For now we keep the ohter functions in the group in program until
cgraph_remove_unreachable_functions gets rid of them. */
gcc_assert (!e->callee->global.inlined_to);
- symtab_dissolve_same_comdat_group_list ((symtab_node) e->callee);
- if (e->callee->symbol.definition && !DECL_EXTERNAL (e->callee->symbol.decl))
+ symtab_dissolve_same_comdat_group_list (e->callee);
+ if (e->callee->definition && !DECL_EXTERNAL (e->callee->decl))
{
if (overall_size)
*overall_size -= inline_summary (e->callee)->size;
nfunctions_inlined++;
}
duplicate = false;
- e->callee->symbol.externally_visible = false;
+ e->callee->externally_visible = false;
update_noncloned_frequencies (e->callee, e->frequency);
}
else
{
struct cgraph_node *n;
- n = cgraph_clone_node (e->callee, e->callee->symbol.decl,
+ n = cgraph_clone_node (e->callee, e->callee->decl,
e->count, e->frequency, update_original,
vNULL, true, inlining_into);
cgraph_redirect_edge_callee (e, n);
}
}
else
- symtab_dissolve_same_comdat_group_list ((symtab_node) e->callee);
+ symtab_dissolve_same_comdat_group_list (e->callee);
e->callee->global.inlined_to = inlining_into;
@@ -235,7 +234,7 @@ inline_call (struct cgraph_edge *e, bool update_original,
gcc_assert (!callee->global.inlined_to);
e->inline_failed = CIF_OK;
- DECL_POSSIBLY_INLINED (callee->symbol.decl) = true;
+ DECL_POSSIBLY_INLINED (callee->decl) = true;
to = e->caller;
if (to->global.inlined_to)
@@ -287,7 +286,7 @@ inline_call (struct cgraph_edge *e, bool update_original,
/* Account the change of overall unit size; external functions will be
removed and are thus not accounted. */
if (overall_size
- && !DECL_EXTERNAL (to->symbol.decl))
+ && !DECL_EXTERNAL (to->decl))
*overall_size += new_size - old_size;
ncalls_inlined++;
@@ -313,13 +312,13 @@ save_inline_function_body (struct cgraph_node *node)
fprintf (dump_file, "\nSaving body of %s for later reuse\n",
cgraph_node_name (node));
- gcc_assert (node == cgraph_get_node (node->symbol.decl));
+ gcc_assert (node == cgraph_get_node (node->decl));
/* first_clone will be turned into real function. */
first_clone = node->clones;
- first_clone->symbol.decl = copy_node (node->symbol.decl);
- symtab_insert_node_to_hashtable ((symtab_node) first_clone);
- gcc_assert (first_clone == cgraph_get_node (first_clone->symbol.decl));
+ first_clone->decl = copy_node (node->decl);
+ symtab_insert_node_to_hashtable (first_clone);
+ gcc_assert (first_clone == cgraph_get_node (first_clone->decl));
/* Now reshape the clone tree, so all other clones descends from
first_clone. */
@@ -347,8 +346,8 @@ save_inline_function_body (struct cgraph_node *node)
if (first_clone->clones)
for (n = first_clone->clones; n != first_clone;)
{
- gcc_assert (n->symbol.decl == node->symbol.decl);
- n->symbol.decl = first_clone->symbol.decl;
+ gcc_assert (n->decl == node->decl);
+ n->decl = first_clone->decl;
if (n->clones)
n = n->clones;
else if (n->next_sibling_clone)
@@ -363,16 +362,16 @@ save_inline_function_body (struct cgraph_node *node)
}
/* Copy the OLD_VERSION_NODE function tree to the new version. */
- tree_function_versioning (node->symbol.decl, first_clone->symbol.decl,
+ tree_function_versioning (node->decl, first_clone->decl,
NULL, true, NULL, false,
NULL, NULL);
/* The function will be short lived and removed after we inline all the clones,
but make it internal so we won't confuse ourself. */
- DECL_EXTERNAL (first_clone->symbol.decl) = 0;
- DECL_COMDAT_GROUP (first_clone->symbol.decl) = NULL_TREE;
- TREE_PUBLIC (first_clone->symbol.decl) = 0;
- DECL_COMDAT (first_clone->symbol.decl) = 0;
+ DECL_EXTERNAL (first_clone->decl) = 0;
+ DECL_COMDAT_GROUP (first_clone->decl) = NULL_TREE;
+ TREE_PUBLIC (first_clone->decl) = 0;
+ DECL_COMDAT (first_clone->decl) = 0;
first_clone->ipa_transforms_to_apply.release ();
/* When doing recursive inlining, the clone may become unnecessary.
@@ -398,7 +397,7 @@ static bool
preserve_function_body_p (struct cgraph_node *node)
{
gcc_assert (cgraph_global_info_ready);
- gcc_assert (!node->symbol.alias && !node->thunk.thunk_p);
+ gcc_assert (!node->alias && !node->thunk.thunk_p);
/* Look if there is any clone around. */
if (node->clones)
@@ -429,7 +428,7 @@ inline_transform (struct cgraph_node *node)
next = e->next_callee;
cgraph_redirect_edge_call_stmt_to_callee (e);
}
- ipa_remove_all_references (&node->symbol.ref_list);
+ ipa_remove_all_references (&node->ref_list);
timevar_push (TV_INTEGRATION);
if (node->callees && optimize)
diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c
index 3672e57e471..f4cb72a9c2b 100644
--- a/gcc/ipa-inline.c
+++ b/gcc/ipa-inline.c
@@ -97,7 +97,6 @@ along with GCC; see the file COPYING3. If not see
#include "tree-inline.h"
#include "langhooks.h"
#include "flags.h"
-#include "cgraph.h"
#include "diagnostic.h"
#include "gimple-pretty-print.h"
#include "params.h"
@@ -107,13 +106,16 @@ along with GCC; see the file COPYING3. If not see
#include "coverage.h"
#include "ggc.h"
#include "rtl.h"
-#include "tree-ssa.h"
+#include "bitmap.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
#include "ipa-prop.h"
#include "except.h"
#include "target.h"
#include "ipa-inline.h"
#include "ipa-utils.h"
#include "sreal.h"
+#include "cilk.h"
/* Statistics we collect about inlining algorithm. */
static int overall_size;
@@ -220,8 +222,8 @@ report_inline_failed_reason (struct cgraph_edge *e)
if (dump_file)
{
fprintf (dump_file, " not inlinable: %s/%i -> %s/%i, %s\n",
- xstrdup (cgraph_node_name (e->caller)), e->caller->symbol.order,
- xstrdup (cgraph_node_name (e->callee)), e->callee->symbol.order,
+ xstrdup (cgraph_node_name (e->caller)), e->caller->order,
+ xstrdup (cgraph_node_name (e->callee)), e->callee->order,
cgraph_inline_failed_string (e->inline_failed));
}
}
@@ -243,27 +245,28 @@ can_inline_edge_p (struct cgraph_edge *e, bool report,
enum availability avail;
struct cgraph_node *callee
= cgraph_function_or_thunk_node (e->callee, &avail);
- tree caller_tree = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (e->caller->symbol.decl);
+ tree caller_tree = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (e->caller->decl);
tree callee_tree
- = callee ? DECL_FUNCTION_SPECIFIC_OPTIMIZATION (callee->symbol.decl) : NULL;
- struct function *caller_cfun = DECL_STRUCT_FUNCTION (e->caller->symbol.decl);
+ = callee ? DECL_FUNCTION_SPECIFIC_OPTIMIZATION (callee->decl) : NULL;
+ struct function *caller_cfun = DECL_STRUCT_FUNCTION (e->caller->decl);
struct function *callee_cfun
- = callee ? DECL_STRUCT_FUNCTION (callee->symbol.decl) : NULL;
+ = callee ? DECL_STRUCT_FUNCTION (callee->decl) : NULL;
if (!caller_cfun && e->caller->clone_of)
- caller_cfun = DECL_STRUCT_FUNCTION (e->caller->clone_of->symbol.decl);
+ caller_cfun = DECL_STRUCT_FUNCTION (e->caller->clone_of->decl);
if (!callee_cfun && callee && callee->clone_of)
- callee_cfun = DECL_STRUCT_FUNCTION (callee->clone_of->symbol.decl);
+ callee_cfun = DECL_STRUCT_FUNCTION (callee->clone_of->decl);
gcc_assert (e->inline_failed);
- if (!callee || !callee->symbol.definition)
+ if (!callee || !callee->definition)
{
e->inline_failed = CIF_BODY_NOT_AVAILABLE;
inlinable = false;
}
- else if (!inline_summary (callee)->inlinable)
+ else if (!inline_summary (callee)->inlinable
+ || (caller_cfun && fn_contains_cilk_spawn_p (caller_cfun)))
{
e->inline_failed = CIF_FUNCTION_NOT_INLINABLE;
inlinable = false;
@@ -280,18 +283,18 @@ can_inline_edge_p (struct cgraph_edge *e, bool report,
inlinable = false;
}
/* Don't inline if the functions have different EH personalities. */
- else if (DECL_FUNCTION_PERSONALITY (e->caller->symbol.decl)
- && DECL_FUNCTION_PERSONALITY (callee->symbol.decl)
- && (DECL_FUNCTION_PERSONALITY (e->caller->symbol.decl)
- != DECL_FUNCTION_PERSONALITY (callee->symbol.decl)))
+ else if (DECL_FUNCTION_PERSONALITY (e->caller->decl)
+ && DECL_FUNCTION_PERSONALITY (callee->decl)
+ && (DECL_FUNCTION_PERSONALITY (e->caller->decl)
+ != DECL_FUNCTION_PERSONALITY (callee->decl)))
{
e->inline_failed = CIF_EH_PERSONALITY;
inlinable = false;
}
/* TM pure functions should not be inlined into non-TM_pure
functions. */
- else if (is_tm_pure (callee->symbol.decl)
- && !is_tm_pure (e->caller->symbol.decl))
+ else if (is_tm_pure (callee->decl)
+ && !is_tm_pure (e->caller->decl))
{
e->inline_failed = CIF_UNSPECIFIED;
inlinable = false;
@@ -307,20 +310,20 @@ can_inline_edge_p (struct cgraph_edge *e, bool report,
inlinable = false;
}
/* Check compatibility of target optimization options. */
- else if (!targetm.target_option.can_inline_p (e->caller->symbol.decl,
- callee->symbol.decl))
+ else if (!targetm.target_option.can_inline_p (e->caller->decl,
+ callee->decl))
{
e->inline_failed = CIF_TARGET_OPTION_MISMATCH;
inlinable = false;
}
/* Check if caller growth allows the inlining. */
- else if (!DECL_DISREGARD_INLINE_LIMITS (callee->symbol.decl)
+ else if (!DECL_DISREGARD_INLINE_LIMITS (callee->decl)
&& !disregard_limits
&& !lookup_attribute ("flatten",
DECL_ATTRIBUTES
(e->caller->global.inlined_to
- ? e->caller->global.inlined_to->symbol.decl
- : e->caller->symbol.decl))
+ ? e->caller->global.inlined_to->decl
+ : e->caller->decl))
&& !caller_growth_limits (e))
inlinable = false;
/* Don't inline a function with a higher optimization level than the
@@ -341,7 +344,7 @@ can_inline_edge_p (struct cgraph_edge *e, bool report,
if (((caller_opt->x_optimize > callee_opt->x_optimize)
|| (caller_opt->x_optimize_size != callee_opt->x_optimize_size))
/* gcc.dg/pr43564.c. Look at forced inline even in -O0. */
- && !DECL_DISREGARD_INLINE_LIMITS (e->callee->symbol.decl))
+ && !DECL_DISREGARD_INLINE_LIMITS (e->callee->decl))
{
e->inline_failed = CIF_OPTIMIZATION_MISMATCH;
inlinable = false;
@@ -364,7 +367,7 @@ can_early_inline_edge_p (struct cgraph_edge *e)
/* Early inliner might get called at WPA stage when IPA pass adds new
function. In this case we can not really do any of early inlining
because function bodies are missing. */
- if (!gimple_has_body_p (callee->symbol.decl))
+ if (!gimple_has_body_p (callee->decl))
{
e->inline_failed = CIF_BODY_NOT_AVAILABLE;
return false;
@@ -373,8 +376,8 @@ can_early_inline_edge_p (struct cgraph_edge *e)
(i.e. the callgraph is cyclic and we did not process
the callee by early inliner, yet). We don't have CIF code for this
case; later we will re-do the decision in the real inliner. */
- if (!gimple_in_ssa_p (DECL_STRUCT_FUNCTION (e->caller->symbol.decl))
- || !gimple_in_ssa_p (DECL_STRUCT_FUNCTION (callee->symbol.decl)))
+ if (!gimple_in_ssa_p (DECL_STRUCT_FUNCTION (e->caller->decl))
+ || !gimple_in_ssa_p (DECL_STRUCT_FUNCTION (callee->decl)))
{
if (dump_file)
fprintf (dump_file, " edge not inlinable: not in SSA form\n");
@@ -395,7 +398,7 @@ num_calls (struct cgraph_node *n)
int num = 0;
for (e = n->callees; e; e = e->next_callee)
- if (!is_inexpensive_builtin (e->callee->symbol.decl))
+ if (!is_inexpensive_builtin (e->callee->decl))
num++;
return num;
}
@@ -409,9 +412,9 @@ want_early_inline_function_p (struct cgraph_edge *e)
bool want_inline = true;
struct cgraph_node *callee = cgraph_function_or_thunk_node (e->callee, NULL);
- if (DECL_DISREGARD_INLINE_LIMITS (callee->symbol.decl))
+ if (DECL_DISREGARD_INLINE_LIMITS (callee->decl))
;
- else if (!DECL_DECLARED_INLINE_P (callee->symbol.decl)
+ else if (!DECL_DECLARED_INLINE_P (callee->decl)
&& !flag_inline_small_functions)
{
e->inline_failed = CIF_FUNCTION_NOT_INLINE_CANDIDATE;
@@ -432,8 +435,8 @@ want_early_inline_function_p (struct cgraph_edge *e)
fprintf (dump_file, " will not early inline: %s/%i->%s/%i, "
"call is cold and code would grow by %i\n",
xstrdup (cgraph_node_name (e->caller)),
- e->caller->symbol.order,
- xstrdup (cgraph_node_name (callee)), callee->symbol.order,
+ e->caller->order,
+ xstrdup (cgraph_node_name (callee)), callee->order,
growth);
want_inline = false;
}
@@ -443,8 +446,8 @@ want_early_inline_function_p (struct cgraph_edge *e)
fprintf (dump_file, " will not early inline: %s/%i->%s/%i, "
"growth %i exceeds --param early-inlining-insns\n",
xstrdup (cgraph_node_name (e->caller)),
- e->caller->symbol.order,
- xstrdup (cgraph_node_name (callee)), callee->symbol.order,
+ e->caller->order,
+ xstrdup (cgraph_node_name (callee)), callee->order,
growth);
want_inline = false;
}
@@ -456,8 +459,8 @@ want_early_inline_function_p (struct cgraph_edge *e)
"growth %i exceeds --param early-inlining-insns "
"divided by number of calls\n",
xstrdup (cgraph_node_name (e->caller)),
- e->caller->symbol.order,
- xstrdup (cgraph_node_name (callee)), callee->symbol.order,
+ e->caller->order,
+ xstrdup (cgraph_node_name (callee)), callee->order,
growth);
want_inline = false;
}
@@ -527,9 +530,9 @@ want_inline_small_function_p (struct cgraph_edge *e, bool report)
bool want_inline = true;
struct cgraph_node *callee = cgraph_function_or_thunk_node (e->callee, NULL);
- if (DECL_DISREGARD_INLINE_LIMITS (callee->symbol.decl))
+ if (DECL_DISREGARD_INLINE_LIMITS (callee->decl))
;
- else if (!DECL_DECLARED_INLINE_P (callee->symbol.decl)
+ else if (!DECL_DECLARED_INLINE_P (callee->decl)
&& !flag_inline_small_functions)
{
e->inline_failed = CIF_FUNCTION_NOT_INLINE_CANDIDATE;
@@ -545,7 +548,7 @@ want_inline_small_function_p (struct cgraph_edge *e, bool report)
;
/* Apply MAX_INLINE_INSNS_SINGLE limit. Do not do so when
hints suggests that inlining given function is very profitable. */
- else if (DECL_DECLARED_INLINE_P (callee->symbol.decl)
+ else if (DECL_DECLARED_INLINE_P (callee->decl)
&& growth >= MAX_INLINE_INSNS_SINGLE
&& !big_speedup
&& !(hints & (INLINE_HINT_indirect_call
@@ -588,11 +591,11 @@ want_inline_small_function_p (struct cgraph_edge *e, bool report)
Consequently we ask cgraph_can_remove_if_no_direct_calls_p
instead of
cgraph_will_be_removed_from_program_if_no_direct_calls */
- && !DECL_EXTERNAL (callee->symbol.decl)
+ && !DECL_EXTERNAL (callee->decl)
&& cgraph_can_remove_if_no_direct_calls_p (callee)
&& estimate_growth (callee) <= 0)
;
- else if (!DECL_DECLARED_INLINE_P (callee->symbol.decl)
+ else if (!DECL_DECLARED_INLINE_P (callee->decl)
&& !flag_inline_functions)
{
e->inline_failed = CIF_NOT_DECLARED_INLINED;
@@ -601,7 +604,7 @@ want_inline_small_function_p (struct cgraph_edge *e, bool report)
/* Apply MAX_INLINE_INSNS_AUTO limit for functions not declared inline
Upgrade it to MAX_INLINE_INSNS_SINGLE when hints suggests that
inlining given function is very profitable. */
- else if (!DECL_DECLARED_INLINE_P (callee->symbol.decl)
+ else if (!DECL_DECLARED_INLINE_P (callee->decl)
&& !big_speedup
&& growth >= ((hints & (INLINE_HINT_indirect_call
| INLINE_HINT_loop_iterations
@@ -648,7 +651,7 @@ want_inline_self_recursive_call_p (struct cgraph_edge *edge,
int caller_freq = CGRAPH_FREQ_BASE;
int max_depth = PARAM_VALUE (PARAM_MAX_INLINE_RECURSIVE_DEPTH_AUTO);
- if (DECL_DECLARED_INLINE_P (edge->caller->symbol.decl))
+ if (DECL_DECLARED_INLINE_P (edge->caller->decl))
max_depth = PARAM_VALUE (PARAM_MAX_INLINE_RECURSIVE_DEPTH);
if (!cgraph_maybe_hot_edge_p (edge))
@@ -814,8 +817,8 @@ relative_time_benefit (struct inline_summary *callee_info,
/* Inlining into extern inline function is not a win. */
if (DECL_EXTERNAL (edge->caller->global.inlined_to
- ? edge->caller->global.inlined_to->symbol.decl
- : edge->caller->symbol.decl))
+ ? edge->caller->global.inlined_to->decl
+ : edge->caller->decl))
return 1;
/* Watch overflows. */
@@ -854,7 +857,7 @@ edge_badness (struct cgraph_edge *edge, bool dump)
struct inline_summary *callee_info = inline_summary (callee);
inline_hints hints;
- if (DECL_DISREGARD_INLINE_LIMITS (callee->symbol.decl))
+ if (DECL_DISREGARD_INLINE_LIMITS (callee->decl))
return INT_MIN;
growth = estimate_edge_growth (edge);
@@ -868,9 +871,9 @@ edge_badness (struct cgraph_edge *edge, bool dump)
{
fprintf (dump_file, " Badness calculation for %s/%i -> %s/%i\n",
xstrdup (cgraph_node_name (edge->caller)),
- edge->caller->symbol.order,
+ edge->caller->order,
xstrdup (cgraph_node_name (callee)),
- edge->callee->symbol.order);
+ edge->callee->order);
fprintf (dump_file, " size growth %i, time %i ",
growth,
edge_time);
@@ -903,12 +906,16 @@ edge_badness (struct cgraph_edge *edge, bool dump)
{
sreal tmp, relbenefit_real, growth_real;
int relbenefit = relative_time_benefit (callee_info, edge, edge_time);
+ /* Capping edge->count to max_count. edge->count can be larger than
+ max_count if an inline adds new edges which increase max_count
+ after max_count is computed. */
+ int edge_count = edge->count > max_count ? max_count : edge->count;
- sreal_init(&relbenefit_real, relbenefit, 0);
- sreal_init(&growth_real, growth, 0);
+ sreal_init (&relbenefit_real, relbenefit, 0);
+ sreal_init (&growth_real, growth, 0);
/* relative_edge_count. */
- sreal_init (&tmp, edge->count, 0);
+ sreal_init (&tmp, edge_count, 0);
sreal_div (&tmp, &tmp, &max_count_real);
/* relative_time_benefit. */
@@ -921,16 +928,14 @@ edge_badness (struct cgraph_edge *edge, bool dump)
badness = -1 * sreal_to_int (&tmp);
- /* Be sure that insanity of the profile won't lead to increasing counts
- in the scalling and thus to overflow in the computation above. */
- gcc_assert (max_count >= edge->count);
if (dump)
{
fprintf (dump_file,
- " %i (relative %f): profile info. Relative count %f"
+ " %i (relative %f): profile info. Relative count %f%s"
" * Relative benefit %f\n",
(int) badness, (double) badness / INT_MIN,
- (double) edge->count / max_count,
+ (double) edge_count / max_count,
+ edge->count > max_count ? " (capped to max_count)" : "",
relbenefit * 100.0 / RELATIVE_TIME_BENEFIT_RANGE);
}
}
@@ -1033,9 +1038,9 @@ update_edge_key (fibheap_t heap, struct cgraph_edge *edge)
fprintf (dump_file,
" decreasing badness %s/%i -> %s/%i, %i to %i\n",
xstrdup (cgraph_node_name (edge->caller)),
- edge->caller->symbol.order,
+ edge->caller->order,
xstrdup (cgraph_node_name (edge->callee)),
- edge->callee->symbol.order,
+ edge->callee->order,
(int)n->key,
badness);
}
@@ -1050,9 +1055,9 @@ update_edge_key (fibheap_t heap, struct cgraph_edge *edge)
fprintf (dump_file,
" enqueuing call %s/%i -> %s/%i, badness %i\n",
xstrdup (cgraph_node_name (edge->caller)),
- edge->caller->symbol.order,
+ edge->caller->order,
xstrdup (cgraph_node_name (edge->callee)),
- edge->callee->symbol.order,
+ edge->callee->order,
badness);
}
edge->aux = fibheap_insert (heap, badness, edge);
@@ -1083,7 +1088,7 @@ reset_edge_caches (struct cgraph_node *node)
for (edge = where->callers; edge; edge = edge->next_caller)
if (edge->inline_failed)
reset_edge_growth_cache (edge);
- for (i = 0; ipa_ref_list_referring_iterate (&where->symbol.ref_list,
+ for (i = 0; ipa_ref_list_referring_iterate (&where->ref_list,
i, ref); i++)
if (ref->use == IPA_REF_ALIAS)
reset_edge_caches (ipa_ref_referring_node (ref));
@@ -1128,13 +1133,13 @@ update_caller_keys (fibheap_t heap, struct cgraph_node *node,
int i;
struct ipa_ref *ref;
- if ((!node->symbol.alias && !inline_summary (node)->inlinable)
+ if ((!node->alias && !inline_summary (node)->inlinable)
|| node->global.inlined_to)
return;
if (!bitmap_set_bit (updated_nodes, node->uid))
return;
- for (i = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list,
+ for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list,
i, ref); i++)
if (ref->use == IPA_REF_ALIAS)
{
@@ -1266,7 +1271,7 @@ recursive_inlining (struct cgraph_edge *edge,
if (node->global.inlined_to)
node = node->global.inlined_to;
- if (DECL_DECLARED_INLINE_P (node->symbol.decl))
+ if (DECL_DECLARED_INLINE_P (node->decl))
limit = PARAM_VALUE (PARAM_MAX_INLINE_INSNS_RECURSIVE);
/* Make sure that function is small enough to be considered for inlining. */
@@ -1315,8 +1320,8 @@ recursive_inlining (struct cgraph_edge *edge,
depth = 1;
for (cnode = curr->caller;
cnode->global.inlined_to; cnode = cnode->callers->caller)
- if (node->symbol.decl
- == cgraph_function_or_thunk_node (curr->callee, NULL)->symbol.decl)
+ if (node->decl
+ == cgraph_function_or_thunk_node (curr->callee, NULL)->decl)
depth++;
if (!want_inline_self_recursive_call_p (curr, node, false, depth))
@@ -1340,7 +1345,7 @@ recursive_inlining (struct cgraph_edge *edge,
if (!master_clone)
{
/* We need original clone to copy around. */
- master_clone = cgraph_clone_node (node, node->symbol.decl,
+ master_clone = cgraph_clone_node (node, node->decl,
node->count, CGRAPH_FREQ_BASE,
false, vNULL, true, NULL);
for (e = master_clone->callees; e; e = e->next_callee)
@@ -1452,7 +1457,7 @@ speculation_useful_p (struct cgraph_edge *e, bool anticipate_inlining)
else we propagate is useless. */
if (avail >= AVAIL_AVAILABLE)
{
- int ecf_flags = flags_from_decl_or_type (target->symbol.decl);
+ int ecf_flags = flags_from_decl_or_type (target->decl);
if (ecf_flags & ECF_CONST)
{
cgraph_speculative_call_info (e, direct, indirect, ref);
@@ -1542,9 +1547,9 @@ inline_small_functions (void)
|| node->thunk.thunk_p)
{
struct inline_summary *info = inline_summary (node);
- struct ipa_dfs_info *dfs = (struct ipa_dfs_info *) node->symbol.aux;
+ struct ipa_dfs_info *dfs = (struct ipa_dfs_info *) node->aux;
- if (!DECL_EXTERNAL (node->symbol.decl))
+ if (!DECL_EXTERNAL (node->decl))
initial_size += info->size;
info->growth = estimate_growth (node);
if (dfs && dfs->next_cycle)
@@ -1552,7 +1557,7 @@ inline_small_functions (void)
struct cgraph_node *n2;
int id = dfs->scc_no + 1;
for (n2 = node; n2;
- n2 = ((struct ipa_dfs_info *) node->symbol.aux)->next_cycle)
+ n2 = ((struct ipa_dfs_info *) node->aux)->next_cycle)
{
struct inline_summary *info2 = inline_summary (n2);
if (info2->scc_no)
@@ -1590,7 +1595,7 @@ inline_small_functions (void)
if (dump_file)
fprintf (dump_file, "Enqueueing calls in %s/%i.\n",
- cgraph_node_name (node), node->symbol.order);
+ cgraph_node_name (node), node->order);
for (edge = node->callees; edge; edge = next)
{
@@ -1673,13 +1678,13 @@ inline_small_functions (void)
{
fprintf (dump_file,
"\nConsidering %s/%i with %i size\n",
- cgraph_node_name (callee), callee->symbol.order,
+ cgraph_node_name (callee), callee->order,
inline_summary (callee)->size);
fprintf (dump_file,
" to be inlined into %s/%i in %s:%i\n"
" Estimated growth after inlined into all is %+i insns.\n"
" Estimated badness is %i, frequency %.2f.\n",
- cgraph_node_name (edge->caller), edge->caller->symbol.order,
+ cgraph_node_name (edge->caller), edge->caller->order,
flag_wpa ? "unknown"
: gimple_filename ((const_gimple) edge->call_stmt),
flag_wpa ? -1
@@ -1695,7 +1700,7 @@ inline_small_functions (void)
}
if (overall_size + growth > max_size
- && !DECL_DISREGARD_INLINE_LIMITS (callee->symbol.decl))
+ && !DECL_DISREGARD_INLINE_LIMITS (callee->decl))
{
edge->inline_failed = CIF_INLINE_UNIT_GROWTH_LIMIT;
report_inline_failed_reason (edge);
@@ -1747,7 +1752,7 @@ inline_small_functions (void)
where = edge->caller;
while (where->global.inlined_to)
{
- if (where->symbol.decl == callee->symbol.decl)
+ if (where->decl == callee->decl)
outer_node = where, depth++;
where = where->callers->caller;
}
@@ -1756,7 +1761,7 @@ inline_small_functions (void)
true, depth))
{
edge->inline_failed
- = (DECL_DISREGARD_INLINE_LIMITS (edge->callee->symbol.decl)
+ = (DECL_DISREGARD_INLINE_LIMITS (edge->callee->decl)
? CIF_RECURSIVE_INLINING : CIF_UNSPECIFIED);
resolve_noninline_speculation (edge_heap, edge);
continue;
@@ -1828,9 +1833,9 @@ flatten_function (struct cgraph_node *node, bool early)
struct cgraph_edge *e;
/* We shouldn't be called recursively when we are being processed. */
- gcc_assert (node->symbol.aux == NULL);
+ gcc_assert (node->aux == NULL);
- node->symbol.aux = (void *) node;
+ node->aux = (void *) node;
for (e = node->callees; e; e = e->next_callee)
{
@@ -1838,7 +1843,7 @@ flatten_function (struct cgraph_node *node, bool early)
struct cgraph_node *callee = cgraph_function_or_thunk_node (e->callee, NULL);
/* We've hit cycle? It is time to give up. */
- if (callee->symbol.aux)
+ if (callee->aux)
{
if (dump_file)
fprintf (dump_file,
@@ -1872,8 +1877,8 @@ flatten_function (struct cgraph_node *node, bool early)
continue;
}
- if (gimple_in_ssa_p (DECL_STRUCT_FUNCTION (node->symbol.decl))
- != gimple_in_ssa_p (DECL_STRUCT_FUNCTION (callee->symbol.decl)))
+ if (gimple_in_ssa_p (DECL_STRUCT_FUNCTION (node->decl))
+ != gimple_in_ssa_p (DECL_STRUCT_FUNCTION (callee->decl)))
{
if (dump_file)
fprintf (dump_file, "Not inlining: SSA form does not match.\n");
@@ -1889,13 +1894,13 @@ flatten_function (struct cgraph_node *node, bool early)
orig_callee = callee;
inline_call (e, true, NULL, NULL, false);
if (e->callee != orig_callee)
- orig_callee->symbol.aux = (void *) node;
+ orig_callee->aux = (void *) node;
flatten_function (e->callee, early);
if (e->callee != orig_callee)
- orig_callee->symbol.aux = NULL;
+ orig_callee->aux = NULL;
}
- node->symbol.aux = NULL;
+ node->aux = NULL;
if (!node->global.inlined_to)
inline_update_overall_summary (node);
}
@@ -1962,8 +1967,7 @@ ipa_inline (void)
{
struct cgraph_node *node;
int nnodes;
- struct cgraph_node **order =
- XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
+ struct cgraph_node **order;
int i;
int cold;
bool remove_functions = false;
@@ -1971,6 +1975,8 @@ ipa_inline (void)
if (!optimize)
return 0;
+ order = XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
+
if (in_lto_p && optimize)
ipa_update_after_lto_read ();
@@ -1980,7 +1986,7 @@ ipa_inline (void)
nnodes = ipa_reverse_postorder (order);
FOR_EACH_FUNCTION (node)
- node->symbol.aux = 0;
+ node->aux = 0;
if (dump_file)
fprintf (dump_file, "\nFlattening functions:\n");
@@ -1997,7 +2003,7 @@ ipa_inline (void)
try to flatten itself turning it into a self-recursive
function. */
if (lookup_attribute ("flatten",
- DECL_ATTRIBUTES (node->symbol.decl)) != NULL)
+ DECL_ATTRIBUTES (node->decl)) != NULL)
{
if (dump_file)
fprintf (dump_file,
@@ -2102,7 +2108,7 @@ inline_always_inline_functions (struct cgraph_node *node)
for (e = node->callees; e; e = e->next_callee)
{
struct cgraph_node *callee = cgraph_function_or_thunk_node (e->callee, NULL);
- if (!DECL_DISREGARD_INLINE_LIMITS (callee->symbol.decl))
+ if (!DECL_DISREGARD_INLINE_LIMITS (callee->decl))
continue;
if (cgraph_edge_recursive_p (e))
@@ -2120,7 +2126,7 @@ inline_always_inline_functions (struct cgraph_node *node)
is not inlinable. This will allow flagging an error later in
expand_call_inline in tree-inline.c. */
if (lookup_attribute ("always_inline",
- DECL_ATTRIBUTES (callee->symbol.decl)) != NULL)
+ DECL_ATTRIBUTES (callee->decl)) != NULL)
inlined = true;
continue;
}
@@ -2155,7 +2161,7 @@ early_inline_small_functions (struct cgraph_node *node)
continue;
/* Do not consider functions not declared inline. */
- if (!DECL_DECLARED_INLINE_P (callee->symbol.decl)
+ if (!DECL_DECLARED_INLINE_P (callee->decl)
&& !flag_inline_small_functions
&& !flag_inline_functions)
continue;
@@ -2215,7 +2221,7 @@ early_inliner (void)
#ifdef ENABLE_CHECKING
verify_cgraph_node (node);
#endif
- ipa_remove_all_references (&node->symbol.ref_list);
+ ipa_remove_all_references (&node->ref_list);
/* Even when not optimizing or not inlining inline always-inline
functions. */
@@ -2232,10 +2238,10 @@ early_inliner (void)
cycles of edges to be always inlined in the callgraph.
We might want to be smarter and just avoid this type of inlining. */
- || DECL_DISREGARD_INLINE_LIMITS (node->symbol.decl))
+ || DECL_DISREGARD_INLINE_LIMITS (node->decl))
;
else if (lookup_attribute ("flatten",
- DECL_ATTRIBUTES (node->symbol.decl)) != NULL)
+ DECL_ATTRIBUTES (node->decl)) != NULL)
{
/* When the function is marked to be flattened, recursively inline
all calls in it. */
@@ -2266,9 +2272,9 @@ early_inliner (void)
= estimate_num_insns (edge->call_stmt, &eni_size_weights);
es->call_stmt_time
= estimate_num_insns (edge->call_stmt, &eni_time_weights);
- if (edge->callee->symbol.decl
+ if (edge->callee->decl
&& !gimple_check_call_matching_types (
- edge->call_stmt, edge->callee->symbol.decl, false))
+ edge->call_stmt, edge->callee->decl, false))
edge->call_stmt_cannot_inline_p = true;
}
timevar_pop (TV_INTEGRATION);
@@ -2311,8 +2317,8 @@ const pass_data pass_data_early_inline =
class pass_early_inline : public gimple_opt_pass
{
public:
- pass_early_inline(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_early_inline, ctxt)
+ pass_early_inline (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_early_inline, ctxt)
{}
/* opt_pass methods: */
@@ -2361,17 +2367,17 @@ const pass_data pass_data_ipa_inline =
class pass_ipa_inline : public ipa_opt_pass_d
{
public:
- pass_ipa_inline(gcc::context *ctxt)
- : ipa_opt_pass_d(pass_data_ipa_inline, ctxt,
- inline_generate_summary, /* generate_summary */
- inline_write_summary, /* write_summary */
- inline_read_summary, /* read_summary */
- NULL, /* write_optimization_summary */
- NULL, /* read_optimization_summary */
- NULL, /* stmt_fixup */
- 0, /* function_transform_todo_flags_start */
- inline_transform, /* function_transform */
- NULL) /* variable_transform */
+ pass_ipa_inline (gcc::context *ctxt)
+ : ipa_opt_pass_d (pass_data_ipa_inline, ctxt,
+ inline_generate_summary, /* generate_summary */
+ inline_write_summary, /* write_summary */
+ inline_read_summary, /* read_summary */
+ NULL, /* write_optimization_summary */
+ NULL, /* read_optimization_summary */
+ NULL, /* stmt_fixup */
+ 0, /* function_transform_todo_flags_start */
+ inline_transform, /* function_transform */
+ NULL) /* variable_transform */
{}
/* opt_pass methods: */
diff --git a/gcc/ipa-profile.c b/gcc/ipa-profile.c
index 424e4a6b6fe..1260069207e 100644
--- a/gcc/ipa-profile.c
+++ b/gcc/ipa-profile.c
@@ -48,6 +48,7 @@ along with GCC; see the file COPYING3. If not see
#include "system.h"
#include "coretypes.h"
#include "tm.h"
+#include "tree.h"
#include "cgraph.h"
#include "tree-pass.h"
#include "gimple.h"
@@ -184,7 +185,7 @@ ipa_profile_generate_summary (void)
10);
FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
- FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->symbol.decl))
+ FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
{
int time = 0;
int size = 0;
@@ -196,7 +197,7 @@ ipa_profile_generate_summary (void)
{
histogram_value h;
h = gimple_histogram_value_of_type
- (DECL_STRUCT_FUNCTION (node->symbol.decl),
+ (DECL_STRUCT_FUNCTION (node->decl),
stmt, HIST_TYPE_INDIR_CALL);
/* No need to do sanity check: gimple_ic_transform already
takes away bad histograms. */
@@ -218,7 +219,7 @@ ipa_profile_generate_summary (void)
e->indirect_info->common_target_probability = REG_BR_PROB_BASE;
}
}
- gimple_remove_histogram_value (DECL_STRUCT_FUNCTION (node->symbol.decl),
+ gimple_remove_histogram_value (DECL_STRUCT_FUNCTION (node->decl),
stmt, h);
}
}
@@ -240,7 +241,7 @@ ipa_profile_write_summary (void)
= lto_create_simple_output_block (LTO_section_ipa_profile);
unsigned int i;
- streamer_write_uhwi_stream (ob->main_stream, histogram.length());
+ streamer_write_uhwi_stream (ob->main_stream, histogram.length ());
for (i = 0; i < histogram.length (); i++)
{
streamer_write_gcov_count_stream (ob->main_stream, histogram[i]->count);
@@ -324,7 +325,7 @@ ipa_propagate_frequency_1 (struct cgraph_node *node, void *data)
/* It makes sense to put main() together with the static constructors.
It will be executed for sure, but rest of functions called from
main are definitely not at startup only. */
- if (MAIN_NAME_P (DECL_NAME (edge->caller->symbol.decl)))
+ if (MAIN_NAME_P (DECL_NAME (edge->caller->decl)))
d->only_called_at_startup = 0;
d->only_called_at_exit &= edge->caller->only_called_at_exit;
}
@@ -400,10 +401,10 @@ ipa_propagate_frequency (struct cgraph_node *node)
/* We can not propagate anything useful about externally visible functions
nor about virtuals. */
if (!node->local.local
- || node->symbol.alias
- || (flag_devirtualize && DECL_VIRTUAL_P (node->symbol.decl)))
+ || node->alias
+ || (flag_devirtualize && DECL_VIRTUAL_P (node->decl)))
return false;
- gcc_assert (node->symbol.analyzed);
+ gcc_assert (node->analyzed);
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "Processing frequency %s\n", cgraph_node_name (node));
@@ -560,7 +561,7 @@ ipa_profile (void)
set_hot_bb_threshold (threshold);
}
}
- histogram.release();
+ histogram.release ();
free_alloc_pool (histogram_pool);
/* Produce speculative calls: we saved common traget from porfiling into
@@ -588,8 +589,8 @@ ipa_profile (void)
{
fprintf (dump_file, "Indirect call -> direct call from"
" other module %s/%i => %s/%i, prob %3.2f\n",
- xstrdup (cgraph_node_name (n)), n->symbol.order,
- xstrdup (cgraph_node_name (n2)), n2->symbol.order,
+ xstrdup (cgraph_node_name (n)), n->order,
+ xstrdup (cgraph_node_name (n2)), n2->order,
e->indirect_info->common_target_probability
/ (float)REG_BR_PROB_BASE);
}
@@ -610,7 +611,7 @@ ipa_profile (void)
}
else if (cgraph_function_body_availability (n2)
<= AVAIL_OVERWRITABLE
- && symtab_can_be_discarded ((symtab_node) n2))
+ && symtab_can_be_discarded (n2))
{
nuseless++;
if (dump_file)
@@ -624,11 +625,11 @@ ipa_profile (void)
control flow goes to this particular implementation
of N2. Speculate on the local alias to allow inlining.
*/
- if (!symtab_can_be_discarded ((symtab_node) n2))
+ if (!symtab_can_be_discarded (n2))
{
cgraph_node *alias;
alias = cgraph (symtab_nonoverwritable_alias
- ((symtab_node)n2));
+ (n2));
if (alias)
n2 = alias;
}
@@ -676,13 +677,13 @@ ipa_profile (void)
if (order[i]->local.local && ipa_propagate_frequency (order[i]))
{
for (e = order[i]->callees; e; e = e->next_callee)
- if (e->callee->local.local && !e->callee->symbol.aux)
+ if (e->callee->local.local && !e->callee->aux)
{
something_changed = true;
- e->callee->symbol.aux = (void *)1;
+ e->callee->aux = (void *)1;
}
}
- order[i]->symbol.aux = NULL;
+ order[i]->aux = NULL;
}
while (something_changed)
@@ -690,16 +691,16 @@ ipa_profile (void)
something_changed = false;
for (i = order_pos - 1; i >= 0; i--)
{
- if (order[i]->symbol.aux && ipa_propagate_frequency (order[i]))
+ if (order[i]->aux && ipa_propagate_frequency (order[i]))
{
for (e = order[i]->callees; e; e = e->next_callee)
- if (e->callee->local.local && !e->callee->symbol.aux)
+ if (e->callee->local.local && !e->callee->aux)
{
something_changed = true;
- e->callee->symbol.aux = (void *)1;
+ e->callee->aux = (void *)1;
}
}
- order[i]->symbol.aux = NULL;
+ order[i]->aux = NULL;
}
}
free (order);
@@ -732,17 +733,17 @@ const pass_data pass_data_ipa_profile =
class pass_ipa_profile : public ipa_opt_pass_d
{
public:
- pass_ipa_profile(gcc::context *ctxt)
- : ipa_opt_pass_d(pass_data_ipa_profile, ctxt,
- ipa_profile_generate_summary, /* generate_summary */
- ipa_profile_write_summary, /* write_summary */
- ipa_profile_read_summary, /* read_summary */
- NULL, /* write_optimization_summary */
- NULL, /* read_optimization_summary */
- NULL, /* stmt_fixup */
- 0, /* function_transform_todo_flags_start */
- NULL, /* function_transform */
- NULL) /* variable_transform */
+ pass_ipa_profile (gcc::context *ctxt)
+ : ipa_opt_pass_d (pass_data_ipa_profile, ctxt,
+ ipa_profile_generate_summary, /* generate_summary */
+ ipa_profile_write_summary, /* write_summary */
+ ipa_profile_read_summary, /* read_summary */
+ NULL, /* write_optimization_summary */
+ NULL, /* read_optimization_summary */
+ NULL, /* stmt_fixup */
+ 0, /* function_transform_todo_flags_start */
+ NULL, /* function_transform */
+ NULL) /* variable_transform */
{}
/* opt_pass methods: */
diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c
index c09ec2f0166..07af67724f5 100644
--- a/gcc/ipa-prop.c
+++ b/gcc/ipa-prop.c
@@ -21,16 +21,21 @@ along with GCC; see the file COPYING3. If not see
#include "system.h"
#include "coretypes.h"
#include "tree.h"
+#include "gimple.h"
#include "langhooks.h"
#include "ggc.h"
#include "target.h"
-#include "cgraph.h"
#include "ipa-prop.h"
-#include "tree-ssa.h"
+#include "bitmap.h"
+#include "gimple-ssa.h"
+#include "tree-cfg.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-into-ssa.h"
+#include "tree-dfa.h"
#include "tree-pass.h"
#include "tree-inline.h"
#include "ipa-inline.h"
-#include "gimple.h"
#include "flags.h"
#include "diagnostic.h"
#include "gimple-pretty-print.h"
@@ -38,6 +43,7 @@ along with GCC; see the file COPYING3. If not see
#include "data-streamer.h"
#include "tree-streamer.h"
#include "params.h"
+#include "ipa-utils.h"
/* Intermediate information about a parameter that is only useful during the
run of ipa_analyze_node and is not kept afterwards. */
@@ -84,7 +90,7 @@ static alloc_pool ipa_refdesc_pool;
static bool
ipa_func_spec_opts_forbid_analysis_p (struct cgraph_node *node)
{
- tree fs_opts = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (node->symbol.decl);
+ tree fs_opts = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (node->decl);
struct cl_optimization *os;
if (!fs_opts)
@@ -130,7 +136,7 @@ ipa_populate_param_decls (struct cgraph_node *node,
tree parm;
int param_num;
- fndecl = node->symbol.decl;
+ fndecl = node->decl;
gcc_assert (gimple_has_body_p (fndecl));
fnargs = DECL_ARGUMENTS (fndecl);
param_num = 0;
@@ -195,7 +201,7 @@ ipa_initialize_node_params (struct cgraph_node *node)
if (!info->descriptors.exists ())
{
- ipa_alloc_node_params (node, count_formal_params (node->symbol.decl));
+ ipa_alloc_node_params (node, count_formal_params (node->decl));
ipa_populate_param_decls (node, info->descriptors);
}
}
@@ -247,8 +253,7 @@ ipa_print_node_jump_functions_for_edge (FILE *f, struct cgraph_edge *cs)
fprintf (f, "PASS THROUGH: ");
fprintf (f, "%d, op %s",
jump_func->value.pass_through.formal_id,
- tree_code_name[(int)
- jump_func->value.pass_through.operation]);
+ get_tree_code_name(jump_func->value.pass_through.operation));
if (jump_func->value.pass_through.operation != NOP_EXPR)
{
fprintf (f, " ");
@@ -310,16 +315,16 @@ ipa_print_node_jump_functions (FILE *f, struct cgraph_node *node)
struct cgraph_edge *cs;
fprintf (f, " Jump functions of caller %s/%i:\n", cgraph_node_name (node),
- node->symbol.order);
+ node->order);
for (cs = node->callees; cs; cs = cs->next_callee)
{
if (!ipa_edge_args_info_available_for_edge_p (cs))
continue;
fprintf (f, " callsite %s/%i -> %s/%i : \n",
- xstrdup (cgraph_node_name (node)), node->symbol.order,
+ xstrdup (cgraph_node_name (node)), node->order,
xstrdup (cgraph_node_name (cs->callee)),
- cs->callee->symbol.order);
+ cs->callee->order);
ipa_print_node_jump_functions_for_edge (f, cs);
}
@@ -847,7 +852,7 @@ static bool
ipa_load_from_parm_agg_1 (vec<ipa_param_descriptor_t> descriptors,
struct param_analysis_info *parms_ainfo, gimple stmt,
tree op, int *index_p, HOST_WIDE_INT *offset_p,
- bool *by_ref_p)
+ HOST_WIDE_INT *size_p, bool *by_ref_p)
{
int index;
HOST_WIDE_INT size, max_size;
@@ -865,6 +870,8 @@ ipa_load_from_parm_agg_1 (vec<ipa_param_descriptor_t> descriptors,
{
*index_p = index;
*by_ref_p = false;
+ if (size_p)
+ *size_p = size;
return true;
}
return false;
@@ -907,6 +914,8 @@ ipa_load_from_parm_agg_1 (vec<ipa_param_descriptor_t> descriptors,
{
*index_p = index;
*by_ref_p = true;
+ if (size_p)
+ *size_p = size;
return true;
}
return false;
@@ -921,7 +930,7 @@ ipa_load_from_parm_agg (struct ipa_node_params *info, gimple stmt,
bool *by_ref_p)
{
return ipa_load_from_parm_agg_1 (info->descriptors, NULL, stmt, op, index_p,
- offset_p, by_ref_p);
+ offset_p, NULL, by_ref_p);
}
/* Given that an actual argument is an SSA_NAME (given in NAME) and is a result
@@ -1508,7 +1517,7 @@ ipa_get_callee_param_type (struct cgraph_edge *e, int i)
{
int n;
tree type = (e->callee
- ? TREE_TYPE (e->callee->symbol.decl)
+ ? TREE_TYPE (e->callee->decl)
: gimple_call_fntype (e->call_stmt));
tree t = TYPE_ARG_TYPES (type);
@@ -1522,7 +1531,7 @@ ipa_get_callee_param_type (struct cgraph_edge *e, int i)
return TREE_VALUE (t);
if (!e->callee)
return NULL;
- t = DECL_ARGUMENTS (e->callee->symbol.decl);
+ t = DECL_ARGUMENTS (e->callee->decl);
for (n = 0; n < i; n++)
{
if (!t)
@@ -1642,7 +1651,7 @@ ipa_compute_jump_functions (struct cgraph_node *node,
NULL);
/* We do not need to bother analyzing calls to unknown
functions unless they may become known during lto/whopr. */
- if (!callee->symbol.definition && !flag_lto)
+ if (!callee->definition && !flag_lto)
continue;
ipa_compute_jump_functions_for_edge (parms_ainfo, cs);
}
@@ -1821,7 +1830,7 @@ ipa_analyze_indirect_call_uses (struct cgraph_node *node,
if (gimple_assign_single_p (def)
&& ipa_load_from_parm_agg_1 (info->descriptors, parms_ainfo, def,
gimple_assign_rhs1 (def), &index, &offset,
- &by_ref))
+ NULL, &by_ref))
{
struct cgraph_edge *cs = ipa_note_param_call (node, index, call);
cs->indirect_info->offset = offset;
@@ -2051,7 +2060,7 @@ static void
ipa_analyze_params_uses (struct cgraph_node *node,
struct param_analysis_info *parms_ainfo)
{
- tree decl = node->symbol.decl;
+ tree decl = node->decl;
basic_block bb;
struct function *func;
gimple_stmt_iterator gsi;
@@ -2081,7 +2090,7 @@ ipa_analyze_params_uses (struct cgraph_node *node,
the flag during modification analysis. */
if (is_gimple_reg (parm))
{
- tree ddef = ssa_default_def (DECL_STRUCT_FUNCTION (node->symbol.decl),
+ tree ddef = ssa_default_def (DECL_STRUCT_FUNCTION (node->decl),
parm);
if (ddef && !has_zero_uses (ddef))
{
@@ -2160,7 +2169,7 @@ ipa_analyze_node (struct cgraph_node *node)
ipa_check_create_node_params ();
ipa_check_create_edge_args ();
info = IPA_NODE_REF (node);
- push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
+ push_cfun (DECL_STRUCT_FUNCTION (node->decl));
ipa_initialize_node_params (node);
param_count = ipa_get_param_count (info);
@@ -2196,6 +2205,11 @@ ipa_intraprocedural_devirtualization (gimple call)
token = OBJ_TYPE_REF_TOKEN (otr);
fndecl = gimple_get_virt_method_for_binfo (tree_low_cst (token, 1),
binfo);
+#ifdef ENABLE_CHECKING
+ if (fndecl)
+ gcc_assert (possible_polymorphic_call_target_p
+ (otr, cgraph_get_node (fndecl)));
+#endif
return fndecl;
}
@@ -2408,7 +2422,7 @@ ipa_make_edge_direct_to_target (struct cgraph_edge *ie, tree target)
if (dump_file)
fprintf (dump_file, "ipa-prop: Discovered direct call to non-function"
" in %s/%i, making it unreachable.\n",
- cgraph_node_name (ie->caller), ie->caller->symbol.order);
+ cgraph_node_name (ie->caller), ie->caller->order);
target = builtin_decl_implicit (BUILT_IN_UNREACHABLE);
callee = cgraph_get_create_node (target);
unreachable = true;
@@ -2435,9 +2449,9 @@ ipa_make_edge_direct_to_target (struct cgraph_edge *ie, tree target)
fprintf (dump_file, "ipa-prop: Discovered call to a known target "
"(%s/%i -> %s/%i) but can not refer to it. Giving up.\n",
xstrdup (cgraph_node_name (ie->caller)),
- ie->caller->symbol.order,
+ ie->caller->order,
xstrdup (cgraph_node_name (ie->callee)),
- ie->callee->symbol.order);
+ ie->callee->order);
return NULL;
}
callee = cgraph_get_create_real_symbol_node (target);
@@ -2454,9 +2468,9 @@ ipa_make_edge_direct_to_target (struct cgraph_edge *ie, tree target)
"(%s/%i -> %s/%i), for stmt ",
ie->indirect_info->polymorphic ? "a virtual" : "an indirect",
xstrdup (cgraph_node_name (ie->caller)),
- ie->caller->symbol.order,
+ ie->caller->order,
xstrdup (cgraph_node_name (callee)),
- callee->symbol.order);
+ callee->order);
if (ie->call_stmt)
print_gimple_stmt (dump_file, ie->call_stmt, 2, TDF_SLIM);
else
@@ -2502,7 +2516,7 @@ ipa_find_agg_cst_for_param (struct ipa_agg_jump_function *agg,
successfully found and removed. */
static bool
-remove_described_reference (symtab_node symbol, struct ipa_cst_ref_desc *rdesc)
+remove_described_reference (symtab_node *symbol, struct ipa_cst_ref_desc *rdesc)
{
struct ipa_ref *to_del;
struct cgraph_edge *origin;
@@ -2510,7 +2524,7 @@ remove_described_reference (symtab_node symbol, struct ipa_cst_ref_desc *rdesc)
origin = rdesc->cs;
if (!origin)
return false;
- to_del = ipa_find_reference ((symtab_node) origin->caller, symbol,
+ to_del = ipa_find_reference (origin->caller, symbol,
origin->call_stmt, origin->lto_stmt_uid);
if (!to_del)
return false;
@@ -2519,7 +2533,7 @@ remove_described_reference (symtab_node symbol, struct ipa_cst_ref_desc *rdesc)
if (dump_file)
fprintf (dump_file, "ipa-prop: Removed a reference from %s/%i to %s.\n",
xstrdup (cgraph_node_name (origin->caller)),
- origin->caller->symbol.order, xstrdup (symtab_node_name (symbol)));
+ origin->caller->order, xstrdup (symtab_node_name (symbol)));
return true;
}
@@ -2567,7 +2581,7 @@ try_decrement_rdesc_refcount (struct ipa_jump_func *jfunc)
&& (rdesc = jfunc_rdesc_usable (jfunc))
&& --rdesc->refcount == 0)
{
- symtab_node symbol = (symtab_node) cgraph_node_for_jfunc (jfunc);
+ symtab_node *symbol = cgraph_node_for_jfunc (jfunc);
if (!symbol)
return false;
@@ -2651,7 +2665,13 @@ try_make_edge_direct_virtual_call (struct cgraph_edge *ie,
return NULL;
if (target)
- return ipa_make_edge_direct_to_target (ie, target);
+ {
+#ifdef ENABLE_CHECKING
+ gcc_assert (possible_polymorphic_call_target_p
+ (ie, cgraph_get_node (target)));
+#endif
+ return ipa_make_edge_direct_to_target (ie, target);
+ }
else
return NULL;
}
@@ -2721,7 +2741,7 @@ update_indirect_edges_after_inlining (struct cgraph_edge *cs,
new_direct_edge->call_stmt_cannot_inline_p
= !gimple_check_call_matching_types (
new_direct_edge->call_stmt,
- new_direct_edge->callee->symbol.decl, false);
+ new_direct_edge->callee->decl, false);
if (new_edges)
{
new_edges->safe_push (new_direct_edge);
@@ -2837,15 +2857,15 @@ propagate_controlled_uses (struct cgraph_edge *cs)
if (t && TREE_CODE (t) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL
&& (n = cgraph_get_node (TREE_OPERAND (t, 0)))
- && (ref = ipa_find_reference ((symtab_node) new_root,
- (symtab_node) n, NULL, 0)))
+ && (ref = ipa_find_reference (new_root,
+ n, NULL, 0)))
{
if (dump_file)
fprintf (dump_file, "ipa-prop: Removing cloning-created "
"reference from %s/%i to %s/%i.\n",
xstrdup (cgraph_node_name (new_root)),
- new_root->symbol.order,
- xstrdup (cgraph_node_name (n)), n->symbol.order);
+ new_root->order,
+ xstrdup (cgraph_node_name (n)), n->order);
ipa_remove_reference (ref);
}
}
@@ -2868,7 +2888,7 @@ propagate_controlled_uses (struct cgraph_edge *cs)
{
struct cgraph_node *clone;
bool ok;
- ok = remove_described_reference ((symtab_node) n, rdesc);
+ ok = remove_described_reference (n, rdesc);
gcc_checking_assert (ok);
clone = cs->caller;
@@ -2877,8 +2897,8 @@ propagate_controlled_uses (struct cgraph_edge *cs)
&& IPA_NODE_REF (clone)->ipcp_orig_node)
{
struct ipa_ref *ref;
- ref = ipa_find_reference ((symtab_node) clone,
- (symtab_node) n, NULL, 0);
+ ref = ipa_find_reference (clone,
+ n, NULL, 0);
if (ref)
{
if (dump_file)
@@ -2886,9 +2906,9 @@ propagate_controlled_uses (struct cgraph_edge *cs)
"cloning-created reference "
"from %s/%i to %s/%i.\n",
xstrdup (cgraph_node_name (clone)),
- clone->symbol.order,
+ clone->order,
xstrdup (cgraph_node_name (n)),
- n->symbol.order);
+ n->order);
ipa_remove_reference (ref);
}
clone = clone->callers->caller;
@@ -3081,12 +3101,12 @@ ipa_edge_duplication_hook (struct cgraph_edge *src, struct cgraph_edge *dst,
else if (src->caller == dst->caller)
{
struct ipa_ref *ref;
- symtab_node n = (symtab_node) cgraph_node_for_jfunc (src_jf);
+ symtab_node *n = cgraph_node_for_jfunc (src_jf);
gcc_checking_assert (n);
- ref = ipa_find_reference ((symtab_node) src->caller, n,
+ ref = ipa_find_reference (src->caller, n,
src->call_stmt, src->lto_stmt_uid);
gcc_checking_assert (ref);
- ipa_clone_ref (ref, (symtab_node) dst->caller, ref->stmt);
+ ipa_clone_ref (ref, dst->caller, ref->stmt);
gcc_checking_assert (ipa_refdesc_pool);
struct ipa_cst_ref_desc *dst_rdesc
@@ -3267,11 +3287,11 @@ ipa_print_node_params (FILE *f, struct cgraph_node *node)
int i, count;
struct ipa_node_params *info;
- if (!node->symbol.definition)
+ if (!node->definition)
return;
info = IPA_NODE_REF (node);
fprintf (f, " function %s/%i parameter descriptors:\n",
- cgraph_node_name (node), node->symbol.order);
+ cgraph_node_name (node), node->order);
count = ipa_get_param_count (info);
for (i = 0; i < count; i++)
{
@@ -3514,8 +3534,8 @@ ipa_modify_call_arguments (struct cgraph_edge *cs, gimple stmt,
len = adjustments.length ();
vargs.create (len);
- callee_decl = !cs ? gimple_call_fndecl (stmt) : cs->callee->symbol.decl;
- ipa_remove_stmt_references ((symtab_node) current_node, stmt);
+ callee_decl = !cs ? gimple_call_fndecl (stmt) : cs->callee->decl;
+ ipa_remove_stmt_references (current_node, stmt);
gsi = gsi_for_stmt (stmt);
prev_gsi = gsi;
@@ -4107,7 +4127,7 @@ ipa_write_node_info (struct output_block *ob, struct cgraph_node *node)
struct bitpack_d bp;
encoder = ob->decl_state->symtab_node_encoder;
- node_ref = lto_symtab_encoder_encode (encoder, (symtab_node) node);
+ node_ref = lto_symtab_encoder_encode (encoder, node);
streamer_write_uhwi (ob, node_ref);
streamer_write_uhwi (ob, ipa_get_param_count (info));
@@ -4271,7 +4291,7 @@ ipa_prop_read_section (struct lto_file_decl_data *file_data, const char *data,
index = streamer_read_uhwi (&ib_main);
encoder = file_data->symtab_node_encoder;
node = cgraph (lto_symtab_encoder_deref (encoder, index));
- gcc_assert (node->symbol.definition);
+ gcc_assert (node->definition);
ipa_read_node_info (&ib_main, node, data_in);
}
lto_free_section_data (file_data, LTO_section_jump_functions, NULL, data,
@@ -4323,7 +4343,7 @@ write_agg_replacement_chain (struct output_block *ob, struct cgraph_node *node)
aggvals = ipa_get_agg_replacements_for_node (node);
encoder = ob->decl_state->symtab_node_encoder;
- node_ref = lto_symtab_encoder_encode (encoder, (symtab_node) node);
+ node_ref = lto_symtab_encoder_encode (encoder, node);
streamer_write_uhwi (ob, node_ref);
for (av = aggvals; av; av = av->next)
@@ -4447,7 +4467,7 @@ read_replacements_section (struct lto_file_decl_data *file_data,
index = streamer_read_uhwi (&ib_main);
encoder = file_data->symtab_node_encoder;
node = cgraph (lto_symtab_encoder_deref (encoder, index));
- gcc_assert (node->symbol.definition);
+ gcc_assert (node->definition);
read_agg_replacement_chain (&ib_main, node, data_in);
}
lto_free_section_data (file_data, LTO_section_jump_functions, NULL, data,
@@ -4529,12 +4549,12 @@ ipcp_transform_function (struct cgraph_node *node)
if (dump_file)
fprintf (dump_file, "Modification phase of node %s/%i\n",
- cgraph_node_name (node), node->symbol.order);
+ cgraph_node_name (node), node->order);
aggval = ipa_get_agg_replacements_for_node (node);
if (!aggval)
return 0;
- param_count = count_formal_params (node->symbol.decl);
+ param_count = count_formal_params (node->decl);
if (param_count == 0)
return 0;
adjust_agg_replacement_values (node, aggval);
@@ -4551,7 +4571,7 @@ ipcp_transform_function (struct cgraph_node *node)
struct ipa_agg_replacement_value *v;
gimple stmt = gsi_stmt (gsi);
tree rhs, val, t;
- HOST_WIDE_INT offset;
+ HOST_WIDE_INT offset, size;
int index;
bool by_ref, vce;
@@ -4578,13 +4598,15 @@ ipcp_transform_function (struct cgraph_node *node)
continue;
if (!ipa_load_from_parm_agg_1 (descriptors, parms_ainfo, stmt,
- rhs, &index, &offset, &by_ref))
+ rhs, &index, &offset, &size, &by_ref))
continue;
for (v = aggval; v; v = v->next)
if (v->index == index
&& v->offset == offset)
break;
- if (!v || v->by_ref != by_ref)
+ if (!v
+ || v->by_ref != by_ref
+ || tree_low_cst (TYPE_SIZE (TREE_TYPE (v->value)), 0) != size)
continue;
gcc_checking_assert (is_gimple_ip_invariant (v->value));
diff --git a/gcc/ipa-prop.h b/gcc/ipa-prop.h
index 48634d2e172..4da22a1c05d 100644
--- a/gcc/ipa-prop.h
+++ b/gcc/ipa-prop.h
@@ -20,10 +20,8 @@ along with GCC; see the file COPYING3. If not see
#ifndef IPA_PROP_H
#define IPA_PROP_H
-#include "tree.h"
#include "vec.h"
#include "cgraph.h"
-#include "gimple.h"
#include "alloc-pool.h"
/* The following definitions and interfaces are used by
diff --git a/gcc/ipa-pure-const.c b/gcc/ipa-pure-const.c
index 55b679d98a2..50bf500b172 100644
--- a/gcc/ipa-pure-const.c
+++ b/gcc/ipa-pure-const.c
@@ -36,15 +36,15 @@ along with GCC; see the file COPYING3. If not see
#include "coretypes.h"
#include "tm.h"
#include "tree.h"
-#include "tree-ssa.h"
+#include "gimple.h"
+#include "tree-cfg.h"
+#include "tree-ssa-loop-niter.h"
#include "tree-inline.h"
#include "tree-pass.h"
#include "langhooks.h"
#include "pointer-set.h"
#include "ggc.h"
#include "ipa-utils.h"
-#include "gimple.h"
-#include "cgraph.h"
#include "flags.h"
#include "diagnostic.h"
#include "gimple-pretty-print.h"
@@ -179,7 +179,7 @@ warn_function_const (tree decl, bool known_finite)
known_finite, warned_about, "const");
}
-void
+static void
warn_function_noreturn (tree decl)
{
static struct pointer_set_t *warned_about;
@@ -190,15 +190,6 @@ warn_function_noreturn (tree decl)
true, warned_about, "noreturn");
}
-/* Init the function state. */
-
-static void
-finish_state (void)
-{
- funct_state_vec.release ();
-}
-
-
/* Return true if we have a function state for NODE. */
static inline bool
@@ -725,7 +716,7 @@ check_stmt (gimple_stmt_iterator *gsip, funct_state local, bool ipa)
static funct_state
analyze_function (struct cgraph_node *fn, bool ipa)
{
- tree decl = fn->symbol.decl;
+ tree decl = fn->decl;
funct_state l;
basic_block this_block;
@@ -736,10 +727,10 @@ analyze_function (struct cgraph_node *fn, bool ipa)
l->looping = false;
l->can_throw = false;
state_from_flags (&l->state_previously_known, &l->looping_previously_known,
- flags_from_decl_or_type (fn->symbol.decl),
+ flags_from_decl_or_type (fn->decl),
cgraph_node_cannot_return (fn));
- if (fn->thunk.thunk_p || fn->symbol.alias)
+ if (fn->thunk.thunk_p || fn->alias)
{
/* Thunk gets propagated through, so nothing interesting happens. */
gcc_assert (ipa);
@@ -759,7 +750,7 @@ analyze_function (struct cgraph_node *fn, bool ipa)
gimple_stmt_iterator gsi;
struct walk_stmt_info wi;
- memset (&wi, 0, sizeof(wi));
+ memset (&wi, 0, sizeof (wi));
for (gsi = gsi_start_bb (this_block);
!gsi_end_p (gsi);
gsi_next (&gsi))
@@ -952,7 +943,7 @@ pure_const_write_summary (void)
lsei_next_function_in_partition (&lsei))
{
node = lsei_cgraph_node (lsei);
- if (node->symbol.definition && has_function_state (node))
+ if (node->definition && has_function_state (node))
count++;
}
@@ -963,7 +954,7 @@ pure_const_write_summary (void)
lsei_next_function_in_partition (&lsei))
{
node = lsei_cgraph_node (lsei);
- if (node->symbol.definition && has_function_state (node))
+ if (node->definition && has_function_state (node))
{
struct bitpack_d bp;
funct_state fs;
@@ -973,7 +964,7 @@ pure_const_write_summary (void)
fs = get_function_state (node);
encoder = ob->decl_state->symtab_node_encoder;
- node_ref = lto_symtab_encoder_encode (encoder, (symtab_node)node);
+ node_ref = lto_symtab_encoder_encode (encoder, node);
streamer_write_uhwi_stream (ob->main_stream, node_ref);
/* Note that flags will need to be read in the opposite
@@ -1042,10 +1033,10 @@ pure_const_read_summary (void)
fs->can_throw = bp_unpack_value (&bp, 1);
if (dump_file)
{
- int flags = flags_from_decl_or_type (node->symbol.decl);
+ int flags = flags_from_decl_or_type (node->decl);
fprintf (dump_file, "Read info for %s/%i ",
cgraph_node_name (node),
- node->symbol.order);
+ node->order);
if (flags & ECF_CONST)
fprintf (dump_file, " const");
if (flags & ECF_PURE)
@@ -1126,7 +1117,7 @@ propagate_pure_const (void)
int count = 0;
node = order[i];
- if (node->symbol.alias)
+ if (node->alias)
continue;
if (dump_file && (dump_flags & TDF_DETAILS))
@@ -1145,7 +1136,7 @@ propagate_pure_const (void)
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, " Visiting %s/%i state:%s looping %i\n",
cgraph_node_name (w),
- w->symbol.order,
+ w->order,
pure_const_names[w_l->pure_const_state],
w_l->looping);
@@ -1192,7 +1183,7 @@ propagate_pure_const (void)
fprintf (dump_file,
" Call to %s/%i",
cgraph_node_name (e->callee),
- e->callee->symbol.order);
+ e->callee->order);
}
if (avail > AVAIL_OVERWRITABLE)
{
@@ -1221,11 +1212,11 @@ propagate_pure_const (void)
}
}
else if (special_builtin_state (&edge_state, &edge_looping,
- y->symbol.decl))
+ y->decl))
;
else
state_from_flags (&edge_state, &edge_looping,
- flags_from_decl_or_type (y->symbol.decl),
+ flags_from_decl_or_type (y->decl),
cgraph_edge_cannot_lead_to_return (e));
/* Merge the results with what we already know. */
@@ -1264,7 +1255,7 @@ propagate_pure_const (void)
break;
/* And finally all loads and stores. */
- for (i = 0; ipa_ref_list_reference_iterate (&w->symbol.ref_list, i, ref); i++)
+ for (i = 0; ipa_ref_list_reference_iterate (&w->ref_list, i, ref); i++)
{
enum pure_const_state_e ref_state = IPA_CONST;
bool ref_looping = false;
@@ -1272,7 +1263,7 @@ propagate_pure_const (void)
{
case IPA_REF_LOAD:
/* readonly reads are safe. */
- if (TREE_READONLY (ipa_ref_varpool_node (ref)->symbol.decl))
+ if (TREE_READONLY (ipa_ref_varpool_node (ref)->decl))
break;
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, " nonreadonly global var read\n");
@@ -1296,7 +1287,7 @@ propagate_pure_const (void)
if (pure_const_state == IPA_NEITHER)
break;
}
- w_info = (struct ipa_dfs_info *) w->symbol.aux;
+ w_info = (struct ipa_dfs_info *) w->aux;
w = w_info->next_cycle;
}
if (dump_file && (dump_flags & TDF_DETAILS))
@@ -1331,9 +1322,9 @@ propagate_pure_const (void)
switch (this_state)
{
case IPA_CONST:
- if (!TREE_READONLY (w->symbol.decl))
+ if (!TREE_READONLY (w->decl))
{
- warn_function_const (w->symbol.decl, !this_looping);
+ warn_function_const (w->decl, !this_looping);
if (dump_file)
fprintf (dump_file, "Function found to be %sconst: %s\n",
this_looping ? "looping " : "",
@@ -1343,9 +1334,9 @@ propagate_pure_const (void)
break;
case IPA_PURE:
- if (!DECL_PURE_P (w->symbol.decl))
+ if (!DECL_PURE_P (w->decl))
{
- warn_function_pure (w->symbol.decl, !this_looping);
+ warn_function_pure (w->decl, !this_looping);
if (dump_file)
fprintf (dump_file, "Function found to be %spure: %s\n",
this_looping ? "looping " : "",
@@ -1357,7 +1348,7 @@ propagate_pure_const (void)
default:
break;
}
- w_info = (struct ipa_dfs_info *) w->symbol.aux;
+ w_info = (struct ipa_dfs_info *) w->aux;
w = w_info->next_cycle;
}
}
@@ -1396,7 +1387,7 @@ propagate_nothrow (void)
bool can_throw = false;
node = order[i];
- if (node->symbol.alias)
+ if (node->alias)
continue;
/* Find the worst state for any node in the cycle. */
@@ -1424,11 +1415,11 @@ propagate_nothrow (void)
if (can_throw)
break;
- if (y_l->can_throw && !TREE_NOTHROW (w->symbol.decl)
+ if (y_l->can_throw && !TREE_NOTHROW (w->decl)
&& e->can_throw_external)
can_throw = true;
}
- else if (e->can_throw_external && !TREE_NOTHROW (y->symbol.decl))
+ else if (e->can_throw_external && !TREE_NOTHROW (y->decl))
can_throw = true;
}
for (ie = node->indirect_calls; ie; ie = ie->next_callee)
@@ -1437,7 +1428,7 @@ propagate_nothrow (void)
can_throw = true;
break;
}
- w_info = (struct ipa_dfs_info *) w->symbol.aux;
+ w_info = (struct ipa_dfs_info *) w->aux;
w = w_info->next_cycle;
}
@@ -1447,16 +1438,16 @@ propagate_nothrow (void)
while (w)
{
funct_state w_l = get_function_state (w);
- if (!can_throw && !TREE_NOTHROW (w->symbol.decl))
+ if (!can_throw && !TREE_NOTHROW (w->decl))
{
cgraph_set_nothrow_flag (w, true);
if (dump_file)
fprintf (dump_file, "Function found to be nothrow: %s\n",
cgraph_node_name (w));
}
- else if (can_throw && !TREE_NOTHROW (w->symbol.decl))
+ else if (can_throw && !TREE_NOTHROW (w->decl))
w_l->can_throw = true;
- w_info = (struct ipa_dfs_info *) w->symbol.aux;
+ w_info = (struct ipa_dfs_info *) w->aux;
w = w_info->next_cycle;
}
}
@@ -1488,7 +1479,6 @@ propagate (void)
if (has_function_state (node))
free (get_function_state (node));
funct_state_vec.release ();
- finish_state ();
return 0;
}
@@ -1520,17 +1510,17 @@ const pass_data pass_data_ipa_pure_const =
class pass_ipa_pure_const : public ipa_opt_pass_d
{
public:
- pass_ipa_pure_const(gcc::context *ctxt)
- : ipa_opt_pass_d(pass_data_ipa_pure_const, ctxt,
- pure_const_generate_summary, /* generate_summary */
- pure_const_write_summary, /* write_summary */
- pure_const_read_summary, /* read_summary */
- NULL, /* write_optimization_summary */
- NULL, /* read_optimization_summary */
- NULL, /* stmt_fixup */
- 0, /* function_transform_todo_flags_start */
- NULL, /* function_transform */
- NULL) /* variable_transform */
+ pass_ipa_pure_const (gcc::context *ctxt)
+ : ipa_opt_pass_d (pass_data_ipa_pure_const, ctxt,
+ pure_const_generate_summary, /* generate_summary */
+ pure_const_write_summary, /* write_summary */
+ pure_const_read_summary, /* read_summary */
+ NULL, /* write_optimization_summary */
+ NULL, /* read_optimization_summary */
+ NULL, /* stmt_fixup */
+ 0, /* function_transform_todo_flags_start */
+ NULL, /* function_transform */
+ NULL) /* variable_transform */
{}
/* opt_pass methods: */
@@ -1704,12 +1694,12 @@ const pass_data pass_data_local_pure_const =
class pass_local_pure_const : public gimple_opt_pass
{
public:
- pass_local_pure_const(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_local_pure_const, ctxt)
+ pass_local_pure_const (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_local_pure_const, ctxt)
{}
/* opt_pass methods: */
- opt_pass * clone () { return new pass_local_pure_const (ctxt_); }
+ opt_pass * clone () { return new pass_local_pure_const (m_ctxt); }
bool gate () { return gate_pure_const (); }
unsigned int execute () { return local_pure_const (); }
@@ -1722,3 +1712,60 @@ make_pass_local_pure_const (gcc::context *ctxt)
{
return new pass_local_pure_const (ctxt);
}
+
+/* Emit noreturn warnings. */
+
+static unsigned int
+execute_warn_function_noreturn (void)
+{
+ if (!TREE_THIS_VOLATILE (current_function_decl)
+ && EDGE_COUNT (EXIT_BLOCK_PTR->preds) == 0)
+ warn_function_noreturn (current_function_decl);
+ return 0;
+}
+
+static bool
+gate_warn_function_noreturn (void)
+{
+ return warn_suggest_attribute_noreturn;
+}
+
+namespace {
+
+const pass_data pass_data_warn_function_noreturn =
+{
+ GIMPLE_PASS, /* type */
+ "*warn_function_noreturn", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
+ true, /* has_gate */
+ true, /* has_execute */
+ TV_NONE, /* tv_id */
+ PROP_cfg, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ 0, /* todo_flags_finish */
+};
+
+class pass_warn_function_noreturn : public gimple_opt_pass
+{
+public:
+ pass_warn_function_noreturn (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_warn_function_noreturn, ctxt)
+ {}
+
+ /* opt_pass methods: */
+ bool gate () { return gate_warn_function_noreturn (); }
+ unsigned int execute () { return execute_warn_function_noreturn (); }
+
+}; // class pass_warn_function_noreturn
+
+} // anon namespace
+
+gimple_opt_pass *
+make_pass_warn_function_noreturn (gcc::context *ctxt)
+{
+ return new pass_warn_function_noreturn (ctxt);
+}
+
+
diff --git a/gcc/ipa-ref-inline.h b/gcc/ipa-ref-inline.h
index bb74f8723a4..4bb43c2af1d 100644
--- a/gcc/ipa-ref-inline.h
+++ b/gcc/ipa-ref-inline.h
@@ -54,7 +54,7 @@ ipa_ref_referring_varpool_node (struct ipa_ref *ref)
static inline struct ipa_ref_list *
ipa_ref_referring_ref_list (struct ipa_ref *ref)
{
- return &ref->referring->symbol.ref_list;
+ return &ref->referring->ref_list;
}
/* Return reference list REF is in. */
@@ -62,7 +62,7 @@ ipa_ref_referring_ref_list (struct ipa_ref *ref)
static inline struct ipa_ref_list *
ipa_ref_referred_ref_list (struct ipa_ref *ref)
{
- return &ref->referred->symbol.ref_list;
+ return &ref->referred->ref_list;
}
/* Return first reference in LIST or NULL if empty. */
diff --git a/gcc/ipa-ref.c b/gcc/ipa-ref.c
index a7c3b40b0cf..04ce9090dfe 100644
--- a/gcc/ipa-ref.c
+++ b/gcc/ipa-ref.c
@@ -34,8 +34,8 @@ static const char *ipa_ref_use_name[] = {"read","write","addr","alias"};
of the use and STMT the statement (if it exists). */
struct ipa_ref *
-ipa_record_reference (symtab_node referring_node,
- symtab_node referred_node,
+ipa_record_reference (symtab_node *referring_node,
+ symtab_node *referred_node,
enum ipa_ref_use use_type, gimple stmt)
{
struct ipa_ref *ref, *ref2;
@@ -45,12 +45,12 @@ ipa_record_reference (symtab_node referring_node,
gcc_checking_assert (!stmt || is_a <cgraph_node> (referring_node));
gcc_checking_assert (use_type != IPA_REF_ALIAS || !stmt);
- list = &referring_node->symbol.ref_list;
+ list = &referring_node->ref_list;
old_references = vec_safe_address (list->references);
vec_safe_grow (list->references, vec_safe_length (list->references) + 1);
ref = &list->references->last ();
- list2 = &referred_node->symbol.ref_list;
+ list2 = &referred_node->ref_list;
list2->referring.safe_push (ref);
ref->referred_index = list2->referring.length () - 1;
ref->referring = referring_node;
@@ -76,7 +76,7 @@ ipa_record_reference (symtab_node referring_node,
reference or NULL if none was created. */
struct ipa_ref *
-ipa_maybe_record_reference (symtab_node referring_node, tree val,
+ipa_maybe_record_reference (symtab_node *referring_node, tree val,
enum ipa_ref_use use_type, gimple stmt)
{
STRIP_NOPS (val);
@@ -86,7 +86,7 @@ ipa_maybe_record_reference (symtab_node referring_node, tree val,
if (val && (TREE_CODE (val) == FUNCTION_DECL
|| TREE_CODE (val) == VAR_DECL))
{
- symtab_node referred = symtab_get_node (val);
+ symtab_node *referred = symtab_get_node (val);
gcc_checking_assert (referred);
return ipa_record_reference (referring_node, referred,
use_type, stmt);
@@ -155,7 +155,7 @@ ipa_dump_references (FILE * file, struct ipa_ref_list *list)
{
fprintf (file, "%s/%i (%s)",
symtab_node_asm_name (ref->referred),
- ref->referred->symbol.order,
+ ref->referred->order,
ipa_ref_use_name [ref->use]);
if (ref->speculative)
fprintf (file, " (speculative)");
@@ -174,7 +174,7 @@ ipa_dump_referring (FILE * file, struct ipa_ref_list *list)
{
fprintf (file, "%s/%i (%s)",
symtab_node_asm_name (ref->referring),
- ref->referring->symbol.order,
+ ref->referring->order,
ipa_ref_use_name [ref->use]);
if (ref->speculative)
fprintf (file, " (speculative)");
@@ -186,7 +186,7 @@ ipa_dump_referring (FILE * file, struct ipa_ref_list *list)
struct ipa_ref *
ipa_clone_ref (struct ipa_ref *ref,
- symtab_node dest_node,
+ symtab_node *dest_node,
gimple stmt)
{
bool speculative = ref->speculative;
@@ -204,7 +204,7 @@ ipa_clone_ref (struct ipa_ref *ref,
/* Clone all references from SRC to DEST_NODE or DEST_VARPOOL_NODE. */
void
-ipa_clone_references (symtab_node dest_node,
+ipa_clone_references (symtab_node *dest_node,
struct ipa_ref_list *src)
{
struct ipa_ref *ref, *ref2;
@@ -225,7 +225,7 @@ ipa_clone_references (symtab_node dest_node,
/* Clone all referring from SRC to DEST_NODE or DEST_VARPOOL_NODE. */
void
-ipa_clone_referring (symtab_node dest_node,
+ipa_clone_referring (symtab_node *dest_node,
struct ipa_ref_list *src)
{
struct ipa_ref *ref, *ref2;
@@ -268,13 +268,13 @@ ipa_ref_has_aliases_p (struct ipa_ref_list *ref_list)
and associated with statement STMT. */
struct ipa_ref *
-ipa_find_reference (symtab_node referring_node, symtab_node referred_node,
+ipa_find_reference (symtab_node *referring_node, symtab_node *referred_node,
gimple stmt, unsigned int lto_stmt_uid)
{
struct ipa_ref *r = NULL;
int i;
- for (i = 0; ipa_ref_list_reference_iterate (&referring_node->symbol.ref_list, i, r); i++)
+ for (i = 0; ipa_ref_list_reference_iterate (&referring_node->ref_list, i, r); i++)
if (r->referred == referred_node
&& !r->speculative
&& ((stmt && r->stmt == stmt)
@@ -288,12 +288,12 @@ ipa_find_reference (symtab_node referring_node, symtab_node referred_node,
STMT. */
void
-ipa_remove_stmt_references (symtab_node referring_node, gimple stmt)
+ipa_remove_stmt_references (symtab_node *referring_node, gimple stmt)
{
struct ipa_ref *r = NULL;
int i;
- for (i = 0; ipa_ref_list_reference_iterate (&referring_node->symbol.ref_list, i, r); i++)
+ for (i = 0; ipa_ref_list_reference_iterate (&referring_node->ref_list, i, r); i++)
if (r->stmt == stmt)
ipa_remove_reference (r);
}
@@ -304,12 +304,12 @@ ipa_remove_stmt_references (symtab_node referring_node, gimple stmt)
with callgraph edges associated with them. */
void
-ipa_clear_stmts_in_references (symtab_node referring_node)
+ipa_clear_stmts_in_references (symtab_node *referring_node)
{
struct ipa_ref *r = NULL;
int i;
- for (i = 0; ipa_ref_list_reference_iterate (&referring_node->symbol.ref_list, i, r); i++)
+ for (i = 0; ipa_ref_list_reference_iterate (&referring_node->ref_list, i, r); i++)
if (!r->speculative)
{
r->stmt = NULL;
diff --git a/gcc/ipa-ref.h b/gcc/ipa-ref.h
index e0553bb6609..9f392b41588 100644
--- a/gcc/ipa-ref.h
+++ b/gcc/ipa-ref.h
@@ -20,9 +20,7 @@ along with GCC; see the file COPYING3. If not see
struct cgraph_node;
struct varpool_node;
-union symtab_node_def;
-typedef union symtab_node_def *symtab_node;
-typedef const union symtab_node_def *const_symtab_node;
+class symtab_node;
/* How the reference is done. */
@@ -37,8 +35,8 @@ enum GTY(()) ipa_ref_use
/* Record of reference in callgraph or varpool. */
struct GTY(()) ipa_ref
{
- symtab_node referring;
- symtab_node referred;
+ symtab_node *referring;
+ symtab_node *referred;
gimple stmt;
unsigned int lto_stmt_uid;
unsigned int referred_index;
@@ -60,10 +58,10 @@ struct GTY(()) ipa_ref_list
vec<ipa_ref_ptr> GTY((skip)) referring;
};
-struct ipa_ref * ipa_record_reference (symtab_node,
- symtab_node,
+struct ipa_ref * ipa_record_reference (symtab_node *,
+ symtab_node *,
enum ipa_ref_use, gimple);
-struct ipa_ref * ipa_maybe_record_reference (symtab_node, tree,
+struct ipa_ref * ipa_maybe_record_reference (symtab_node *, tree,
enum ipa_ref_use, gimple);
void ipa_remove_reference (struct ipa_ref *);
@@ -71,11 +69,11 @@ void ipa_remove_all_references (struct ipa_ref_list *);
void ipa_remove_all_referring (struct ipa_ref_list *);
void ipa_dump_references (FILE *, struct ipa_ref_list *);
void ipa_dump_referring (FILE *, struct ipa_ref_list *);
-void ipa_clone_references (symtab_node, struct ipa_ref_list *);
-void ipa_clone_referring (symtab_node, struct ipa_ref_list *);
-struct ipa_ref * ipa_clone_ref (struct ipa_ref *, symtab_node, gimple);
+void ipa_clone_references (symtab_node *, struct ipa_ref_list *);
+void ipa_clone_referring (symtab_node *, struct ipa_ref_list *);
+struct ipa_ref * ipa_clone_ref (struct ipa_ref *, symtab_node *, gimple);
bool ipa_ref_cannot_lead_to_return (struct ipa_ref *);
bool ipa_ref_has_aliases_p (struct ipa_ref_list *);
-struct ipa_ref * ipa_find_reference (symtab_node, symtab_node, gimple, unsigned int);
-void ipa_remove_stmt_references (symtab_node, gimple);
-void ipa_clear_stmts_in_references (symtab_node);
+struct ipa_ref * ipa_find_reference (symtab_node *, symtab_node *, gimple, unsigned int);
+void ipa_remove_stmt_references (symtab_node *, gimple);
+void ipa_clear_stmts_in_references (symtab_node *);
diff --git a/gcc/ipa-reference.c b/gcc/ipa-reference.c
index e6f19fdd1bf..ae8ba3c651f 100644
--- a/gcc/ipa-reference.c
+++ b/gcc/ipa-reference.c
@@ -41,7 +41,7 @@ along with GCC; see the file COPYING3. If not see
#include "coretypes.h"
#include "tm.h"
#include "tree.h"
-#include "tree-ssa.h"
+#include "gimple.h"
#include "tree-inline.h"
#include "tree-pass.h"
#include "pointer-set.h"
@@ -49,8 +49,6 @@ along with GCC; see the file COPYING3. If not see
#include "ggc.h"
#include "ipa-utils.h"
#include "ipa-reference.h"
-#include "gimple.h"
-#include "cgraph.h"
#include "flags.h"
#include "diagnostic.h"
#include "data-streamer.h"
@@ -180,7 +178,7 @@ ipa_reference_get_not_read_global (struct cgraph_node *fn)
get_reference_optimization_summary (cgraph_function_node (fn, NULL));
if (info)
return info->statics_not_read;
- else if (flags_from_decl_or_type (fn->symbol.decl) & ECF_LEAF)
+ else if (flags_from_decl_or_type (fn->decl) & ECF_LEAF)
return all_module_statics;
else
return NULL;
@@ -198,7 +196,7 @@ ipa_reference_get_not_written_global (struct cgraph_node *fn)
get_reference_optimization_summary (fn);
if (info)
return info->statics_not_written;
- else if (flags_from_decl_or_type (fn->symbol.decl) & ECF_LEAF)
+ else if (flags_from_decl_or_type (fn->decl) & ECF_LEAF)
return all_module_statics;
else
return NULL;
@@ -367,7 +365,7 @@ propagate_bits (ipa_reference_global_vars_info_t x_global, struct cgraph_node *x
continue;
/* Only look into nodes we can propagate something. */
- int flags = flags_from_decl_or_type (y->symbol.decl);
+ int flags = flags_from_decl_or_type (y->decl);
if (avail > AVAIL_OVERWRITABLE
|| (avail == AVAIL_OVERWRITABLE && (flags & ECF_LEAF)))
{
@@ -462,11 +460,11 @@ analyze_function (struct cgraph_node *fn)
tree var;
local = init_function_info (fn);
- for (i = 0; ipa_ref_list_reference_iterate (&fn->symbol.ref_list, i, ref); i++)
+ for (i = 0; ipa_ref_list_reference_iterate (&fn->ref_list, i, ref); i++)
{
if (!is_a <varpool_node> (ref->referred))
continue;
- var = ipa_ref_varpool_node (ref)->symbol.decl;
+ var = ipa_ref_varpool_node (ref)->decl;
if (!is_proper_for_analysis (var))
continue;
switch (ref->use)
@@ -564,7 +562,7 @@ generate_summary (void)
l = &get_reference_vars_info (node)->local;
fprintf (dump_file,
"\nFunction name:%s/%i:",
- cgraph_node_asm_name (node), node->symbol.order);
+ cgraph_node_asm_name (node), node->order);
fprintf (dump_file, "\n locals read: ");
if (l->statics_read)
EXECUTE_IF_SET_IN_BITMAP (l->statics_read,
@@ -578,8 +576,7 @@ generate_summary (void)
EXECUTE_IF_SET_IN_BITMAP (l->statics_written,
0, index, bi)
{
- fprintf(dump_file, "%s ",
- get_static_name (index));
+ fprintf (dump_file, "%s ", get_static_name (index));
}
}
}
@@ -590,7 +587,7 @@ static void
read_write_all_from_decl (struct cgraph_node *node,
bool &read_all, bool &write_all)
{
- tree decl = node->symbol.decl;
+ tree decl = node->decl;
int flags = flags_from_decl_or_type (decl);
if ((flags & ECF_LEAF)
&& cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE)
@@ -603,7 +600,7 @@ read_write_all_from_decl (struct cgraph_node *node,
read_all = true;
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, " %s/%i -> read all\n",
- cgraph_node_asm_name (node), node->symbol.order);
+ cgraph_node_asm_name (node), node->order);
}
else
{
@@ -613,7 +610,7 @@ read_write_all_from_decl (struct cgraph_node *node,
write_all = true;
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, " %s/%i -> read all, write all\n",
- cgraph_node_asm_name (node), node->symbol.order);
+ cgraph_node_asm_name (node), node->order);
}
}
@@ -680,12 +677,12 @@ propagate (void)
/* Now we know what vars are really statics; prune out those that aren't. */
FOR_EACH_VARIABLE (vnode)
- if (vnode->symbol.externally_visible
- || TREE_ADDRESSABLE (vnode->symbol.decl)
- || TREE_READONLY (vnode->symbol.decl)
- || !is_proper_for_analysis (vnode->symbol.decl)
- || !vnode->symbol.definition)
- bitmap_clear_bit (all_module_statics, DECL_UID (vnode->symbol.decl));
+ if (vnode->externally_visible
+ || TREE_ADDRESSABLE (vnode->decl)
+ || TREE_READONLY (vnode->decl)
+ || !is_proper_for_analysis (vnode->decl)
+ || !vnode->definition)
+ bitmap_clear_bit (all_module_statics, DECL_UID (vnode->decl));
/* Forget info we collected "just for fun" on variables that turned out to be
non-local. */
@@ -716,7 +713,7 @@ propagate (void)
bool write_all = false;
node = order[i];
- if (node->symbol.alias)
+ if (node->alias)
continue;
node_info = get_reference_vars_info (node);
@@ -726,7 +723,7 @@ propagate (void)
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "Starting cycle with %s/%i\n",
- cgraph_node_asm_name (node), node->symbol.order);
+ cgraph_node_asm_name (node), node->order);
vec<cgraph_node_ptr> cycle_nodes = ipa_get_nodes_in_cycle (node);
@@ -735,7 +732,7 @@ propagate (void)
{
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, " Visiting %s/%i\n",
- cgraph_node_asm_name (w), w->symbol.order);
+ cgraph_node_asm_name (w), w->order);
get_read_write_all_from_node (w, read_all, write_all);
if (read_all && write_all)
break;
@@ -762,7 +759,7 @@ propagate (void)
{
ipa_reference_vars_info_t w_ri = get_reference_vars_info (w);
ipa_reference_local_vars_info_t w_l = &w_ri->local;
- int flags = flags_from_decl_or_type (w->symbol.decl);
+ int flags = flags_from_decl_or_type (w->decl);
if (!(flags & ECF_CONST))
read_all = union_static_var_sets (node_g->statics_read,
@@ -794,12 +791,12 @@ propagate (void)
struct cgraph_node *w;
node = order[i];
- if (node->symbol.alias)
+ if (node->alias)
continue;
fprintf (dump_file,
"\nFunction name:%s/%i:",
- cgraph_node_asm_name (node), node->symbol.order);
+ cgraph_node_asm_name (node), node->order);
ipa_reference_vars_info_t node_info = get_reference_vars_info (node);
ipa_reference_global_vars_info_t node_g = &node_info->global;
@@ -811,7 +808,7 @@ propagate (void)
ipa_reference_local_vars_info_t w_l = &w_ri->local;
if (w != node)
fprintf (dump_file, "\n next cycle: %s/%i ",
- cgraph_node_asm_name (w), w->symbol.order);
+ cgraph_node_asm_name (w), w->order);
fprintf (dump_file, "\n locals read: ");
dump_static_vars_set_to_file (dump_file, w_l->statics_read);
fprintf (dump_file, "\n locals written: ");
@@ -835,9 +832,9 @@ propagate (void)
ipa_reference_optimization_summary_t opt;
node_info = get_reference_vars_info (node);
- if (!node->symbol.alias
+ if (!node->alias
&& (cgraph_function_body_availability (node) > AVAIL_OVERWRITABLE
- || (flags_from_decl_or_type (node->symbol.decl) & ECF_LEAF)))
+ || (flags_from_decl_or_type (node->decl) & ECF_LEAF)))
{
node_g = &node_info->global;
@@ -894,7 +891,7 @@ write_node_summary_p (struct cgraph_node *node,
ipa_reference_optimization_summary_t info;
/* See if we have (non-empty) info. */
- if (!node->symbol.definition || node->global.inlined_to)
+ if (!node->definition || node->global.inlined_to)
return false;
info = get_reference_optimization_summary (node);
if (!info || (bitmap_empty_p (info->statics_not_read)
@@ -908,7 +905,7 @@ write_node_summary_p (struct cgraph_node *node,
In future we might also want to include summaries of functions references
by initializers of constant variables references in current unit. */
if (!reachable_from_this_partition_p (node, encoder)
- && !referenced_from_this_partition_p (&node->symbol.ref_list, encoder))
+ && !referenced_from_this_partition_p (&node->ref_list, encoder))
return false;
/* See if the info has non-empty intersections with vars we want to encode. */
@@ -949,7 +946,7 @@ stream_out_bitmap (struct lto_simple_output_block *ob,
EXECUTE_IF_AND_IN_BITMAP (bits, ltrans_statics, 0, index, bi)
{
tree decl = (tree)splay_tree_lookup (reference_vars_to_consider, index)->value;
- lto_output_var_decl_index(ob->decl_state, ob->main_stream, decl);
+ lto_output_var_decl_index (ob->decl_state, ob->main_stream, decl);
}
}
@@ -971,13 +968,13 @@ ipa_reference_write_optimization_summary (void)
/* See what variables we are interested in. */
for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
{
- symtab_node snode = lto_symtab_encoder_deref (encoder, i);
+ symtab_node *snode = lto_symtab_encoder_deref (encoder, i);
varpool_node *vnode = dyn_cast <varpool_node> (snode);
if (vnode
- && bitmap_bit_p (all_module_statics, DECL_UID (vnode->symbol.decl))
- && referenced_from_this_partition_p (&vnode->symbol.ref_list, encoder))
+ && bitmap_bit_p (all_module_statics, DECL_UID (vnode->decl))
+ && referenced_from_this_partition_p (&vnode->ref_list, encoder))
{
- tree decl = vnode->symbol.decl;
+ tree decl = vnode->decl;
bitmap_set_bit (ltrans_statics, DECL_UID (decl));
splay_tree_insert (reference_vars_to_consider,
DECL_UID (decl), (splay_tree_value)decl);
@@ -989,7 +986,7 @@ ipa_reference_write_optimization_summary (void)
if (ltrans_statics_bitcount)
for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
{
- symtab_node snode = lto_symtab_encoder_deref (encoder, i);
+ symtab_node *snode = lto_symtab_encoder_deref (encoder, i);
cgraph_node *cnode = dyn_cast <cgraph_node> (snode);
if (cnode && write_node_summary_p (cnode, encoder, ltrans_statics))
count++;
@@ -1004,7 +1001,7 @@ ipa_reference_write_optimization_summary (void)
if (ltrans_statics_bitcount)
for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
{
- symtab_node snode = lto_symtab_encoder_deref (encoder, i);
+ symtab_node *snode = lto_symtab_encoder_deref (encoder, i);
cgraph_node *cnode = dyn_cast <cgraph_node> (snode);
if (cnode && write_node_summary_p (cnode, encoder, ltrans_statics))
{
@@ -1089,7 +1086,7 @@ ipa_reference_read_optimization_summary (void)
if (dump_file)
fprintf (dump_file,
"\nFunction name:%s/%i:\n static not read:",
- cgraph_node_asm_name (node), node->symbol.order);
+ cgraph_node_asm_name (node), node->order);
/* Set the statics not read. */
v_count = streamer_read_hwi (ib);
@@ -1175,20 +1172,20 @@ const pass_data pass_data_ipa_reference =
class pass_ipa_reference : public ipa_opt_pass_d
{
public:
- pass_ipa_reference(gcc::context *ctxt)
- : ipa_opt_pass_d(pass_data_ipa_reference, ctxt,
- NULL, /* generate_summary */
- NULL, /* write_summary */
- NULL, /* read_summary */
- ipa_reference_write_optimization_summary, /*
- write_optimization_summary */
- ipa_reference_read_optimization_summary, /*
- read_optimization_summary */
- NULL, /* stmt_fixup */
- 0, /* function_transform_todo_flags_start */
- NULL, /* function_transform */
- NULL) /* variable_transform */
- {}
+ pass_ipa_reference (gcc::context *ctxt)
+ : ipa_opt_pass_d (pass_data_ipa_reference, ctxt,
+ NULL, /* generate_summary */
+ NULL, /* write_summary */
+ NULL, /* read_summary */
+ ipa_reference_write_optimization_summary, /*
+ write_optimization_summary */
+ ipa_reference_read_optimization_summary, /*
+ read_optimization_summary */
+ NULL, /* stmt_fixup */
+ 0, /* function_transform_todo_flags_start */
+ NULL, /* function_transform */
+ NULL) /* variable_transform */
+ {}
/* opt_pass methods: */
bool gate () { return gate_reference (); }
diff --git a/gcc/ipa-reference.h b/gcc/ipa-reference.h
index c1e910e481a..317ebb02de2 100644
--- a/gcc/ipa-reference.h
+++ b/gcc/ipa-reference.h
@@ -21,7 +21,7 @@ along with GCC; see the file COPYING3. If not see
#ifndef GCC_IPA_REFERENCE_H
#define GCC_IPA_REFERENCE_H
#include "bitmap.h"
-#include "tree.h"
+#include "cgraph.h"
/* In ipa-reference.c */
bitmap ipa_reference_get_not_read_global (struct cgraph_node *fn);
diff --git a/gcc/ipa-split.c b/gcc/ipa-split.c
index 322258a66f8..849868ca68c 100644
--- a/gcc/ipa-split.c
+++ b/gcc/ipa-split.c
@@ -78,10 +78,16 @@ along with GCC; see the file COPYING3. If not see
#include "system.h"
#include "coretypes.h"
#include "tree.h"
+#include "gimple.h"
#include "target.h"
-#include "cgraph.h"
#include "ipa-prop.h"
-#include "tree-ssa.h"
+#include "gimple-ssa.h"
+#include "tree-cfg.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
+#include "tree-into-ssa.h"
+#include "tree-dfa.h"
#include "tree-pass.h"
#include "flags.h"
#include "diagnostic.h"
@@ -1217,20 +1223,20 @@ split_function (struct split_point *split_point)
/* For usual cloning it is enough to clear builtin only when signature
changes. For partial inlining we however can not expect the part
of builtin implementation to have same semantic as the whole. */
- if (DECL_BUILT_IN (node->symbol.decl))
+ if (DECL_BUILT_IN (node->decl))
{
- DECL_BUILT_IN_CLASS (node->symbol.decl) = NOT_BUILT_IN;
- DECL_FUNCTION_CODE (node->symbol.decl) = (enum built_in_function) 0;
+ DECL_BUILT_IN_CLASS (node->decl) = NOT_BUILT_IN;
+ DECL_FUNCTION_CODE (node->decl) = (enum built_in_function) 0;
}
/* If the original function is declared inline, there is no point in issuing
a warning for the non-inlinable part. */
- DECL_NO_INLINE_WARNING_P (node->symbol.decl) = 1;
+ DECL_NO_INLINE_WARNING_P (node->decl) = 1;
cgraph_node_remove_callees (cur_node);
- ipa_remove_all_references (&cur_node->symbol.ref_list);
+ ipa_remove_all_references (&cur_node->ref_list);
if (!split_part_return_p)
- TREE_THIS_VOLATILE (node->symbol.decl) = 1;
+ TREE_THIS_VOLATILE (node->decl) = 1;
if (dump_file)
- dump_function_to_file (node->symbol.decl, dump_file, dump_flags);
+ dump_function_to_file (node->decl, dump_file, dump_flags);
/* Create the basic block we place call into. It is the entry basic block
split after last label. */
@@ -1255,7 +1261,7 @@ split_function (struct split_point *split_point)
false, GSI_CONTINUE_LINKING);
args_to_pass[i] = arg;
}
- call = gimple_build_call_vec (node->symbol.decl, args_to_pass);
+ call = gimple_build_call_vec (node->decl, args_to_pass);
gimple_set_block (call, DECL_INITIAL (current_function_decl));
args_to_pass.release ();
@@ -1282,7 +1288,7 @@ split_function (struct split_point *split_point)
continue;
if (debug_args == NULL)
- debug_args = decl_debug_args_insert (node->symbol.decl);
+ debug_args = decl_debug_args_insert (node->decl);
ddecl = make_node (DEBUG_EXPR_DECL);
DECL_ARTIFICIAL (ddecl) = 1;
TREE_TYPE (ddecl) = TREE_TYPE (parm);
@@ -1308,8 +1314,8 @@ split_function (struct split_point *split_point)
gimple_stmt_iterator cgsi;
gimple def_temp;
- push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
- var = BLOCK_VARS (DECL_INITIAL (node->symbol.decl));
+ push_cfun (DECL_STRUCT_FUNCTION (node->decl));
+ var = BLOCK_VARS (DECL_INITIAL (node->decl));
i = vec_safe_length (*debug_args);
cgsi = gsi_after_labels (single_succ (ENTRY_BLOCK_PTR));
do
@@ -1509,7 +1515,7 @@ execute_split_functions (void)
fprintf (dump_file, "Not splitting: not inlinable.\n");
return 0;
}
- if (DECL_DISREGARD_INLINE_LIMITS (node->symbol.decl))
+ if (DECL_DISREGARD_INLINE_LIMITS (node->decl))
{
if (dump_file)
fprintf (dump_file, "Not splitting: disregarding inline limits.\n");
@@ -1543,8 +1549,8 @@ execute_split_functions (void)
if ((!node->callers
/* Local functions called once will be completely inlined most of time. */
|| (!node->callers->next_caller && node->local.local))
- && !node->symbol.address_taken
- && (!flag_lto || !node->symbol.externally_visible))
+ && !node->address_taken
+ && (!flag_lto || !node->externally_visible))
{
if (dump_file)
fprintf (dump_file, "Not splitting: not called directly "
@@ -1650,8 +1656,8 @@ const pass_data pass_data_split_functions =
class pass_split_functions : public gimple_opt_pass
{
public:
- pass_split_functions(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_split_functions, ctxt)
+ pass_split_functions (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_split_functions, ctxt)
{}
/* opt_pass methods: */
@@ -1710,8 +1716,8 @@ const pass_data pass_data_feedback_split_functions =
class pass_feedback_split_functions : public gimple_opt_pass
{
public:
- pass_feedback_split_functions(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_feedback_split_functions, ctxt)
+ pass_feedback_split_functions (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_feedback_split_functions, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/ipa-utils.c b/gcc/ipa-utils.c
index 12ce0ca0292..84108166e66 100644
--- a/gcc/ipa-utils.c
+++ b/gcc/ipa-utils.c
@@ -23,7 +23,7 @@ along with GCC; see the file COPYING3. If not see
#include "coretypes.h"
#include "tm.h"
#include "tree.h"
-#include "tree-ssa.h"
+#include "gimple.h"
#include "tree-inline.h"
#include "dumpfile.h"
#include "langhooks.h"
@@ -32,8 +32,6 @@ along with GCC; see the file COPYING3. If not see
#include "ggc.h"
#include "ipa-utils.h"
#include "ipa-reference.h"
-#include "gimple.h"
-#include "cgraph.h"
#include "flags.h"
#include "diagnostic.h"
#include "langhooks.h"
@@ -54,9 +52,9 @@ ipa_print_order (FILE* out,
fprintf (out, "\n\n ordered call graph: %s\n", note);
for (i = count - 1; i >= 0; i--)
- dump_cgraph_node(dump_file, order[i]);
+ dump_cgraph_node (dump_file, order[i]);
fprintf (out, "\n");
- fflush(out);
+ fflush (out);
}
@@ -86,7 +84,7 @@ searchc (struct searchc_env* env, struct cgraph_node *v,
bool (*ignore_edge) (struct cgraph_edge *))
{
struct cgraph_edge *edge;
- struct ipa_dfs_info *v_info = (struct ipa_dfs_info *) v->symbol.aux;
+ struct ipa_dfs_info *v_info = (struct ipa_dfs_info *) v->aux;
/* mark node as old */
v_info->new_node = false;
@@ -107,11 +105,11 @@ searchc (struct searchc_env* env, struct cgraph_node *v,
if (!w || (ignore_edge && ignore_edge (edge)))
continue;
- if (w->symbol.aux
+ if (w->aux
&& (avail > AVAIL_OVERWRITABLE
|| (env->allow_overwritable && avail == AVAIL_OVERWRITABLE)))
{
- w_info = (struct ipa_dfs_info *) w->symbol.aux;
+ w_info = (struct ipa_dfs_info *) w->aux;
if (w_info->new_node)
{
searchc (env, w, ignore_edge);
@@ -136,7 +134,7 @@ searchc (struct searchc_env* env, struct cgraph_node *v,
struct ipa_dfs_info *x_info;
do {
x = env->stack[--(env->stack_size)];
- x_info = (struct ipa_dfs_info *) x->symbol.aux;
+ x_info = (struct ipa_dfs_info *) x->aux;
x_info->on_stack = false;
x_info->scc_no = v_info->dfn_number;
@@ -190,20 +188,20 @@ ipa_reduced_postorder (struct cgraph_node **order,
&& (avail == AVAIL_OVERWRITABLE)))
{
/* Reuse the info if it is already there. */
- struct ipa_dfs_info *info = (struct ipa_dfs_info *) node->symbol.aux;
+ struct ipa_dfs_info *info = (struct ipa_dfs_info *) node->aux;
if (!info)
info = XCNEW (struct ipa_dfs_info);
info->new_node = true;
info->on_stack = false;
info->next_cycle = NULL;
- node->symbol.aux = info;
+ node->aux = info;
splay_tree_insert (env.nodes_marked_new,
(splay_tree_key)node->uid,
(splay_tree_value)node);
}
else
- node->symbol.aux = NULL;
+ node->aux = NULL;
}
result = splay_tree_min (env.nodes_marked_new);
while (result)
@@ -228,10 +226,10 @@ ipa_free_postorder_info (void)
FOR_EACH_DEFINED_FUNCTION (node)
{
/* Get rid of the aux information. */
- if (node->symbol.aux)
+ if (node->aux)
{
- free (node->symbol.aux);
- node->symbol.aux = NULL;
+ free (node->aux);
+ node->aux = NULL;
}
}
}
@@ -247,12 +245,28 @@ ipa_get_nodes_in_cycle (struct cgraph_node *node)
while (node)
{
v.safe_push (node);
- node_dfs_info = (struct ipa_dfs_info *) node->symbol.aux;
+ node_dfs_info = (struct ipa_dfs_info *) node->aux;
node = node_dfs_info->next_cycle;
}
return v;
}
+/* Return true iff the CS is an edge within a strongly connected component as
+ computed by ipa_reduced_postorder. */
+
+bool
+ipa_edge_within_scc (struct cgraph_edge *cs)
+{
+ struct ipa_dfs_info *caller_dfs = (struct ipa_dfs_info *) cs->caller->aux;
+ struct ipa_dfs_info *callee_dfs;
+ struct cgraph_node *callee = cgraph_function_node (cs->callee, NULL);
+
+ callee_dfs = (struct ipa_dfs_info *) callee->aux;
+ return (caller_dfs
+ && callee_dfs
+ && caller_dfs->scc_no == callee_dfs->scc_no);
+}
+
struct postorder_stack
{
struct cgraph_node *node;
@@ -282,21 +296,21 @@ ipa_reverse_postorder (struct cgraph_node **order)
to be output and put them into order as well, so we get dependencies
right through inline functions. */
FOR_EACH_FUNCTION (node)
- node->symbol.aux = NULL;
+ node->aux = NULL;
for (pass = 0; pass < 2; pass++)
FOR_EACH_FUNCTION (node)
- if (!node->symbol.aux
+ if (!node->aux
&& (pass
- || (!node->symbol.address_taken
+ || (!node->address_taken
&& !node->global.inlined_to
- && !node->symbol.alias && !node->thunk.thunk_p
+ && !node->alias && !node->thunk.thunk_p
&& !cgraph_only_called_directly_p (node))))
{
stack_size = 0;
stack[stack_size].node = node;
stack[stack_size].edge = node->callers;
stack[stack_size].ref = 0;
- node->symbol.aux = (void *)(size_t)1;
+ node->aux = (void *)(size_t)1;
while (stack_size >= 0)
{
while (true)
@@ -310,12 +324,12 @@ ipa_reverse_postorder (struct cgraph_node **order)
/* Break possible cycles involving always-inline
functions by ignoring edges from always-inline
functions to non-always-inline functions. */
- if (DECL_DISREGARD_INLINE_LIMITS (edge->caller->symbol.decl)
+ if (DECL_DISREGARD_INLINE_LIMITS (edge->caller->decl)
&& !DECL_DISREGARD_INLINE_LIMITS
- (cgraph_function_node (edge->callee, NULL)->symbol.decl))
+ (cgraph_function_node (edge->callee, NULL)->decl))
node2 = NULL;
}
- for (;ipa_ref_list_referring_iterate (&stack[stack_size].node->symbol.ref_list,
+ for (;ipa_ref_list_referring_iterate (&stack[stack_size].node->ref_list,
stack[stack_size].ref,
ref) && !node2;
stack[stack_size].ref++)
@@ -325,12 +339,12 @@ ipa_reverse_postorder (struct cgraph_node **order)
}
if (!node2)
break;
- if (!node2->symbol.aux)
+ if (!node2->aux)
{
stack[++stack_size].node = node2;
stack[stack_size].edge = node2->callers;
stack[stack_size].ref = 0;
- node2->symbol.aux = (void *)(size_t)1;
+ node2->aux = (void *)(size_t)1;
}
}
order[order_pos++] = stack[stack_size--].node;
@@ -338,7 +352,7 @@ ipa_reverse_postorder (struct cgraph_node **order)
}
free (stack);
FOR_EACH_FUNCTION (node)
- node->symbol.aux = NULL;
+ node->aux = NULL;
return order_pos;
}
@@ -467,7 +481,7 @@ dump_cgraph_node_set (FILE *f, cgraph_node_set set)
for (iter = csi_start (set); !csi_end_p (iter); csi_next (&iter))
{
struct cgraph_node *node = csi_node (iter);
- fprintf (f, " %s/%i", cgraph_node_name (node), node->symbol.order);
+ fprintf (f, " %s/%i", cgraph_node_name (node), node->order);
}
fprintf (f, "\n");
}
@@ -629,12 +643,12 @@ void
ipa_merge_profiles (struct cgraph_node *dst,
struct cgraph_node *src)
{
- tree oldsrcdecl = src->symbol.decl;
+ tree oldsrcdecl = src->decl;
struct function *srccfun, *dstcfun;
bool match = true;
- if (!src->symbol.definition
- || !dst->symbol.definition)
+ if (!src->definition
+ || !dst->definition)
return;
if (src->frequency < dst->frequency)
src->frequency = dst->frequency;
@@ -643,8 +657,8 @@ ipa_merge_profiles (struct cgraph_node *dst,
if (cgraph_dump_file)
{
fprintf (cgraph_dump_file, "Merging profiles of %s/%i to %s/%i\n",
- xstrdup (cgraph_node_name (src)), src->symbol.order,
- xstrdup (cgraph_node_name (dst)), dst->symbol.order);
+ xstrdup (cgraph_node_name (src)), src->order,
+ xstrdup (cgraph_node_name (dst)), dst->order);
}
dst->count += src->count;
@@ -652,7 +666,7 @@ ipa_merge_profiles (struct cgraph_node *dst,
If declaration is merged, we need to duplicate it to be able
to load body that is being replaced. This makes symbol table
temporarily inconsistent. */
- if (src->symbol.decl == dst->symbol.decl)
+ if (src->decl == dst->decl)
{
void **slot;
struct lto_in_decl_state temp;
@@ -660,32 +674,32 @@ ipa_merge_profiles (struct cgraph_node *dst,
/* We are going to move the decl, we want to remove its file decl data.
and link these with the new decl. */
- temp.fn_decl = src->symbol.decl;
- slot = htab_find_slot (src->symbol.lto_file_data->function_decl_states,
+ temp.fn_decl = src->decl;
+ slot = htab_find_slot (src->lto_file_data->function_decl_states,
&temp, NO_INSERT);
state = (lto_in_decl_state *)*slot;
- htab_clear_slot (src->symbol.lto_file_data->function_decl_states, slot);
+ htab_clear_slot (src->lto_file_data->function_decl_states, slot);
gcc_assert (state);
/* Duplicate the decl and be sure it does not link into body of DST. */
- src->symbol.decl = copy_node (src->symbol.decl);
- DECL_STRUCT_FUNCTION (src->symbol.decl) = NULL;
- DECL_ARGUMENTS (src->symbol.decl) = NULL;
- DECL_INITIAL (src->symbol.decl) = NULL;
- DECL_RESULT (src->symbol.decl) = NULL;
+ src->decl = copy_node (src->decl);
+ DECL_STRUCT_FUNCTION (src->decl) = NULL;
+ DECL_ARGUMENTS (src->decl) = NULL;
+ DECL_INITIAL (src->decl) = NULL;
+ DECL_RESULT (src->decl) = NULL;
/* Associate the decl state with new declaration, so LTO streamer
can look it up. */
- state->fn_decl = src->symbol.decl;
- slot = htab_find_slot (src->symbol.lto_file_data->function_decl_states,
+ state->fn_decl = src->decl;
+ slot = htab_find_slot (src->lto_file_data->function_decl_states,
state, INSERT);
gcc_assert (!*slot);
*slot = state;
}
cgraph_get_body (src);
cgraph_get_body (dst);
- srccfun = DECL_STRUCT_FUNCTION (src->symbol.decl);
- dstcfun = DECL_STRUCT_FUNCTION (dst->symbol.decl);
+ srccfun = DECL_STRUCT_FUNCTION (src->decl);
+ dstcfun = DECL_STRUCT_FUNCTION (dst->decl);
if (n_basic_blocks_for_function (srccfun)
!= n_basic_blocks_for_function (dstcfun))
{
@@ -773,7 +787,7 @@ ipa_merge_profiles (struct cgraph_node *dst,
gcc_assert (!e->speculative);
e->count = gimple_bb (e->call_stmt)->count;
e->frequency = compute_call_stmt_bb_frequency
- (dst->symbol.decl,
+ (dst->decl,
gimple_bb (e->call_stmt));
}
for (e = dst->indirect_calls; e; e = e->next_callee)
@@ -781,14 +795,14 @@ ipa_merge_profiles (struct cgraph_node *dst,
gcc_assert (!e->speculative);
e->count = gimple_bb (e->call_stmt)->count;
e->frequency = compute_call_stmt_bb_frequency
- (dst->symbol.decl,
+ (dst->decl,
gimple_bb (e->call_stmt));
}
cgraph_release_function_body (src);
inline_update_overall_summary (dst);
}
/* TODO: if there is no match, we can scale up. */
- src->symbol.decl = oldsrcdecl;
+ src->decl = oldsrcdecl;
}
/* Return true if call to DEST is known to be self-recusive call withing FUNC. */
@@ -799,6 +813,6 @@ recursive_call_p (tree func, tree dest)
struct cgraph_node *dest_node = cgraph_get_create_node (dest);
struct cgraph_node *cnode = cgraph_get_create_node (func);
- return symtab_semantically_equivalent_p ((symtab_node)dest_node,
- (symtab_node)cnode);
+ return symtab_semantically_equivalent_p (dest_node,
+ cnode);
}
diff --git a/gcc/ipa-utils.h b/gcc/ipa-utils.h
index d6f390daf15..cc72619348e 100644
--- a/gcc/ipa-utils.h
+++ b/gcc/ipa-utils.h
@@ -20,7 +20,6 @@ along with GCC; see the file COPYING3. If not see
#ifndef GCC_IPA_UTILS_H
#define GCC_IPA_UTILS_H
-#include "tree.h"
#include "cgraph.h"
struct ipa_dfs_info {
@@ -42,6 +41,7 @@ int ipa_reduced_postorder (struct cgraph_node **, bool, bool,
bool (*ignore_edge) (struct cgraph_edge *));
void ipa_free_postorder_info (void);
vec<cgraph_node_ptr> ipa_get_nodes_in_cycle (struct cgraph_node *);
+bool ipa_edge_within_scc (struct cgraph_edge *);
int ipa_reverse_postorder (struct cgraph_node **);
tree get_base_var (tree);
void ipa_merge_profiles (struct cgraph_node *dst,
@@ -108,6 +108,19 @@ possible_polymorphic_call_target_p (struct cgraph_edge *e,
return possible_polymorphic_call_target_p (e->indirect_info->otr_type,
e->indirect_info->otr_token, n);
}
+
+/* Return true if N can be possibly target of a polymorphic call of
+ OBJ_TYPE_REF expression CALL. */
+
+inline bool
+possible_polymorphic_call_target_p (tree call,
+ struct cgraph_node *n)
+{
+ return possible_polymorphic_call_target_p (obj_type_ref_class (call),
+ tree_low_cst
+ (OBJ_TYPE_REF_TOKEN (call), 1),
+ n);
+}
#endif /* GCC_IPA_UTILS_H */
diff --git a/gcc/ipa.c b/gcc/ipa.c
index 67b3bc0f07c..aef437a46f5 100644
--- a/gcc/ipa.c
+++ b/gcc/ipa.c
@@ -21,6 +21,7 @@ along with GCC; see the file COPYING3. If not see
#include "system.h"
#include "coretypes.h"
#include "tm.h"
+#include "tree.h"
#include "cgraph.h"
#include "tree-pass.h"
#include "gimple.h"
@@ -42,12 +43,12 @@ cgraph_non_local_node_p_1 (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED
{
/* FIXME: Aliases can be local, but i386 gets thunks wrong then. */
return !(cgraph_only_called_directly_or_aliased_p (node)
- && !ipa_ref_has_aliases_p (&node->symbol.ref_list)
- && node->symbol.definition
- && !DECL_EXTERNAL (node->symbol.decl)
- && !node->symbol.externally_visible
- && !node->symbol.used_from_other_partition
- && !node->symbol.in_other_partition);
+ && !ipa_ref_has_aliases_p (&node->ref_list)
+ && node->definition
+ && !DECL_EXTERNAL (node->decl)
+ && !node->externally_visible
+ && !node->used_from_other_partition
+ && !node->in_other_partition);
}
/* Return true when function can be marked local. */
@@ -75,7 +76,7 @@ has_addr_references_p (struct cgraph_node *node,
int i;
struct ipa_ref *ref;
- for (i = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list,
+ for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list,
i, ref); i++)
if (ref->use == IPA_REF_ADDR)
return true;
@@ -106,17 +107,17 @@ update_inlined_to_pointer (struct cgraph_node *node, struct cgraph_node *inlined
reachable. */
static void
-enqueue_node (symtab_node node, symtab_node *first,
+enqueue_node (symtab_node *node, symtab_node **first,
struct pointer_set_t *reachable)
{
/* Node is still in queue; do nothing. */
- if (node->symbol.aux && node->symbol.aux != (void *) 2)
+ if (node->aux && node->aux != (void *) 2)
return;
/* Node was already processed as unreachable, re-enqueue
only if it became reachable now. */
- if (node->symbol.aux == (void *)2 && !pointer_set_contains (reachable, node))
+ if (node->aux == (void *)2 && !pointer_set_contains (reachable, node))
return;
- node->symbol.aux = *first;
+ node->aux = *first;
*first = node;
}
@@ -124,7 +125,7 @@ enqueue_node (symtab_node node, symtab_node *first,
static void
process_references (struct ipa_ref_list *list,
- symtab_node *first,
+ symtab_node **first,
bool before_inlining_p,
struct pointer_set_t *reachable)
{
@@ -132,20 +133,20 @@ process_references (struct ipa_ref_list *list,
struct ipa_ref *ref;
for (i = 0; ipa_ref_list_reference_iterate (list, i, ref); i++)
{
- symtab_node node = ref->referred;
+ symtab_node *node = ref->referred;
- if (node->symbol.definition && !node->symbol.in_other_partition
- && ((!DECL_EXTERNAL (node->symbol.decl) || node->symbol.alias)
+ if (node->definition && !node->in_other_partition
+ && ((!DECL_EXTERNAL (node->decl) || node->alias)
|| (before_inlining_p
/* We use variable constructors during late complation for
constant folding. Keep references alive so partitioning
knows about potential references. */
- || (TREE_CODE (node->symbol.decl) == VAR_DECL
+ || (TREE_CODE (node->decl) == VAR_DECL
&& flag_wpa
- && ctor_for_folding (node->symbol.decl)
+ && ctor_for_folding (node->decl)
!= error_mark_node))))
pointer_set_insert (reachable, node);
- enqueue_node ((symtab_node) node, first, reachable);
+ enqueue_node (node, first, reachable);
}
}
@@ -160,7 +161,7 @@ process_references (struct ipa_ref_list *list,
static void
walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets,
struct cgraph_edge *edge,
- symtab_node *first,
+ symtab_node **first,
pointer_set_t *reachable, bool before_inlining_p)
{
unsigned int i;
@@ -173,28 +174,28 @@ walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets,
if (!pointer_set_insert (reachable_call_targets,
cache_token))
{
- for (i = 0; i < targets.length(); i++)
+ for (i = 0; i < targets.length (); i++)
{
struct cgraph_node *n = targets[i];
/* Do not bother to mark virtual methods in anonymous namespace;
either we will find use of virtual table defining it, or it is
unused. */
- if (TREE_CODE (TREE_TYPE (n->symbol.decl)) == METHOD_TYPE
+ if (TREE_CODE (TREE_TYPE (n->decl)) == METHOD_TYPE
&& type_in_anonymous_namespace_p
- (method_class_type (TREE_TYPE (n->symbol.decl))))
+ (method_class_type (TREE_TYPE (n->decl))))
continue;
/* Prior inlining, keep alive bodies of possible targets for
devirtualization. */
- if (n->symbol.definition
+ if (n->definition
&& before_inlining_p)
pointer_set_insert (reachable, n);
/* Even after inlining we want to keep the possible targets in the
boundary, so late passes can still produce direct call even if
the chance for inlining is lost. */
- enqueue_node ((symtab_node) n, first, reachable);
+ enqueue_node (n, first, reachable);
}
}
@@ -204,7 +205,7 @@ walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets,
make the edge direct. */
if (final)
{
- if (targets.length() <= 1)
+ if (targets.length () <= 1)
{
cgraph_node *target, *node = edge->caller;
if (targets.length () == 1)
@@ -217,8 +218,8 @@ walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets,
fprintf (dump_file,
"Devirtualizing call in %s/%i to %s/%i\n",
cgraph_node_name (edge->caller),
- edge->caller->symbol.order,
- cgraph_node_name (target), target->symbol.order);
+ edge->caller->order,
+ cgraph_node_name (target), target->order);
edge = cgraph_make_edge_direct (edge, target);
if (!inline_summary_vec && edge->call_stmt)
cgraph_redirect_edge_call_stmt_to_callee (edge);
@@ -286,7 +287,7 @@ walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets,
bool
symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
{
- symtab_node first = (symtab_node) (void *) 1;
+ symtab_node *first = (symtab_node *) (void *) 1;
struct cgraph_node *node, *next;
struct varpool_node *vnode, *vnext;
bool changed = false;
@@ -304,9 +305,9 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
fprintf (file, "\nReclaiming functions:");
#ifdef ENABLE_CHECKING
FOR_EACH_FUNCTION (node)
- gcc_assert (!node->symbol.aux);
+ gcc_assert (!node->aux);
FOR_EACH_VARIABLE (vnode)
- gcc_assert (!vnode->symbol.aux);
+ gcc_assert (!vnode->aux);
#endif
/* Mark functions whose bodies are obviously needed.
This is mostly when they can be referenced externally. Inline clones
@@ -315,62 +316,62 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
FOR_EACH_FUNCTION (node)
{
node->used_as_abstract_origin = false;
- if (node->symbol.definition
+ if (node->definition
&& !node->global.inlined_to
- && !node->symbol.in_other_partition
+ && !node->in_other_partition
&& !cgraph_can_remove_if_no_direct_calls_and_refs_p (node))
{
gcc_assert (!node->global.inlined_to);
pointer_set_insert (reachable, node);
- enqueue_node ((symtab_node)node, &first, reachable);
+ enqueue_node (node, &first, reachable);
}
else
- gcc_assert (!node->symbol.aux);
+ gcc_assert (!node->aux);
}
/* Mark variables that are obviously needed. */
FOR_EACH_DEFINED_VARIABLE (vnode)
if (!varpool_can_remove_if_no_refs (vnode)
- && !vnode->symbol.in_other_partition)
+ && !vnode->in_other_partition)
{
pointer_set_insert (reachable, vnode);
- enqueue_node ((symtab_node)vnode, &first, reachable);
+ enqueue_node (vnode, &first, reachable);
}
/* Perform reachability analysis. */
- while (first != (symtab_node) (void *) 1)
+ while (first != (symtab_node *) (void *) 1)
{
bool in_boundary_p = !pointer_set_contains (reachable, first);
- symtab_node node = first;
+ symtab_node *node = first;
- first = (symtab_node)first->symbol.aux;
+ first = (symtab_node *)first->aux;
/* If we are processing symbol in boundary, mark its AUX pointer for
possible later re-processing in enqueue_node. */
if (in_boundary_p)
- node->symbol.aux = (void *)2;
+ node->aux = (void *)2;
else
{
- if (DECL_ABSTRACT_ORIGIN (node->symbol.decl))
+ if (DECL_ABSTRACT_ORIGIN (node->decl))
{
struct cgraph_node *origin_node
- = cgraph_get_create_real_symbol_node (DECL_ABSTRACT_ORIGIN (node->symbol.decl));
+ = cgraph_get_create_real_symbol_node (DECL_ABSTRACT_ORIGIN (node->decl));
origin_node->used_as_abstract_origin = true;
- enqueue_node ((symtab_node) origin_node, &first, reachable);
+ enqueue_node (origin_node, &first, reachable);
}
/* If any symbol in a comdat group is reachable, force
all other in the same comdat group to be also reachable. */
- if (node->symbol.same_comdat_group)
+ if (node->same_comdat_group)
{
- symtab_node next;
- for (next = node->symbol.same_comdat_group;
+ symtab_node *next;
+ for (next = node->same_comdat_group;
next != node;
- next = next->symbol.same_comdat_group)
+ next = next->same_comdat_group)
if (!pointer_set_insert (reachable, next))
- enqueue_node ((symtab_node) next, &first, reachable);
+ enqueue_node (next, &first, reachable);
}
/* Mark references as reachable. */
- process_references (&node->symbol.ref_list, &first,
+ process_references (&node->ref_list, &first,
before_inlining_p, reachable);
}
@@ -396,31 +397,31 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
}
for (e = cnode->callees; e; e = e->next_callee)
{
- if (e->callee->symbol.definition
- && !e->callee->symbol.in_other_partition
+ if (e->callee->definition
+ && !e->callee->in_other_partition
&& (!e->inline_failed
- || !DECL_EXTERNAL (e->callee->symbol.decl)
- || e->callee->symbol.alias
+ || !DECL_EXTERNAL (e->callee->decl)
+ || e->callee->alias
|| before_inlining_p))
pointer_set_insert (reachable, e->callee);
- enqueue_node ((symtab_node) e->callee, &first, reachable);
+ enqueue_node (e->callee, &first, reachable);
}
/* When inline clone exists, mark body to be preserved so when removing
offline copy of the function we don't kill it. */
if (cnode->global.inlined_to)
- pointer_set_insert (body_needed_for_clonning, cnode->symbol.decl);
+ pointer_set_insert (body_needed_for_clonning, cnode->decl);
/* For non-inline clones, force their origins to the boundary and ensure
that body is not removed. */
while (cnode->clone_of)
{
- bool noninline = cnode->clone_of->symbol.decl != cnode->symbol.decl;
+ bool noninline = cnode->clone_of->decl != cnode->decl;
cnode = cnode->clone_of;
if (noninline)
{
- pointer_set_insert (body_needed_for_clonning, cnode->symbol.decl);
- enqueue_node ((symtab_node)cnode, &first, reachable);
+ pointer_set_insert (body_needed_for_clonning, cnode->decl);
+ enqueue_node (cnode, &first, reachable);
}
}
}
@@ -430,12 +431,12 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
refers to. */
varpool_node *vnode = dyn_cast <varpool_node> (node);
if (vnode
- && DECL_EXTERNAL (node->symbol.decl)
- && !vnode->symbol.alias
+ && DECL_EXTERNAL (node->decl)
+ && !vnode->alias
&& in_boundary_p)
{
struct ipa_ref *ref;
- for (int i = 0; ipa_ref_list_reference_iterate (&node->symbol.ref_list, i, ref); i++)
+ for (int i = 0; ipa_ref_list_reference_iterate (&node->ref_list, i, ref); i++)
enqueue_node (ref->referred, &first, reachable);
}
}
@@ -446,7 +447,7 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
next = cgraph_next_function (node);
/* If node is not needed at all, remove it. */
- if (!node->symbol.aux)
+ if (!node->aux)
{
if (file)
fprintf (file, " %s", cgraph_node_name (node));
@@ -456,29 +457,29 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
/* If node is unreachable, remove its body. */
else if (!pointer_set_contains (reachable, node))
{
- if (!pointer_set_contains (body_needed_for_clonning, node->symbol.decl))
+ if (!pointer_set_contains (body_needed_for_clonning, node->decl))
cgraph_release_function_body (node);
else if (!node->clone_of)
- gcc_assert (in_lto_p || DECL_RESULT (node->symbol.decl));
- if (node->symbol.definition)
+ gcc_assert (in_lto_p || DECL_RESULT (node->decl));
+ if (node->definition)
{
if (file)
fprintf (file, " %s", cgraph_node_name (node));
- node->symbol.analyzed = false;
- node->symbol.definition = false;
- node->symbol.cpp_implicit_alias = false;
- node->symbol.alias = false;
- node->symbol.weakref = false;
- if (!node->symbol.in_other_partition)
+ node->analyzed = false;
+ node->definition = false;
+ node->cpp_implicit_alias = false;
+ node->alias = false;
+ node->weakref = false;
+ if (!node->in_other_partition)
node->local.local = false;
cgraph_node_remove_callees (node);
- ipa_remove_all_references (&node->symbol.ref_list);
+ ipa_remove_all_references (&node->ref_list);
changed = true;
}
}
else
gcc_assert (node->clone_of || !cgraph_function_with_gimple_body_p (node)
- || in_lto_p || DECL_RESULT (node->symbol.decl));
+ || in_lto_p || DECL_RESULT (node->decl));
}
/* Inline clones might be kept around so their materializing allows further
@@ -493,7 +494,7 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
node->global.inlined_to = NULL;
update_inlined_to_pointer (node, node);
}
- node->symbol.aux = NULL;
+ node->aux = NULL;
}
/* Remove unreachable variables. */
@@ -502,11 +503,11 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
for (vnode = varpool_first_variable (); vnode; vnode = vnext)
{
vnext = varpool_next_variable (vnode);
- if (!vnode->symbol.aux
+ if (!vnode->aux
/* For can_refer_decl_in_current_unit_p we want to track for
all external variables if they are defined in other partition
or not. */
- && (!flag_ltrans || !DECL_EXTERNAL (vnode->symbol.decl)))
+ && (!flag_ltrans || !DECL_EXTERNAL (vnode->decl)))
{
if (file)
fprintf (file, " %s", varpool_node_name (vnode));
@@ -516,25 +517,25 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
else if (!pointer_set_contains (reachable, vnode))
{
tree init;
- if (vnode->symbol.definition)
+ if (vnode->definition)
{
if (file)
fprintf (file, " %s", varpool_node_name (vnode));
changed = true;
}
- vnode->symbol.definition = false;
- vnode->symbol.analyzed = false;
- vnode->symbol.aux = NULL;
+ vnode->definition = false;
+ vnode->analyzed = false;
+ vnode->aux = NULL;
/* Keep body if it may be useful for constant folding. */
- if ((init = ctor_for_folding (vnode->symbol.decl)) == error_mark_node)
+ if ((init = ctor_for_folding (vnode->decl)) == error_mark_node)
varpool_remove_initializer (vnode);
else
- DECL_INITIAL (vnode->symbol.decl) = init;
- ipa_remove_all_references (&vnode->symbol.ref_list);
+ DECL_INITIAL (vnode->decl) = init;
+ ipa_remove_all_references (&vnode->ref_list);
}
else
- vnode->symbol.aux = NULL;
+ vnode->aux = NULL;
}
pointer_set_destroy (reachable);
@@ -545,14 +546,14 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
if (file)
fprintf (file, "\nClearing address taken flags:");
FOR_EACH_DEFINED_FUNCTION (node)
- if (node->symbol.address_taken
- && !node->symbol.used_from_other_partition)
+ if (node->address_taken
+ && !node->used_from_other_partition)
{
if (!cgraph_for_node_and_aliases (node, has_addr_references_p, NULL, true))
{
if (file)
fprintf (file, " %s", cgraph_node_name (node));
- node->symbol.address_taken = false;
+ node->address_taken = false;
changed = true;
if (cgraph_local_node_p (node))
{
@@ -594,15 +595,15 @@ ipa_discover_readonly_nonaddressable_vars (void)
if (dump_file)
fprintf (dump_file, "Clearing variable flags:");
FOR_EACH_VARIABLE (vnode)
- if (vnode->symbol.definition && varpool_all_refs_explicit_p (vnode)
- && (TREE_ADDRESSABLE (vnode->symbol.decl)
- || !TREE_READONLY (vnode->symbol.decl)))
+ if (vnode->definition && varpool_all_refs_explicit_p (vnode)
+ && (TREE_ADDRESSABLE (vnode->decl)
+ || !TREE_READONLY (vnode->decl)))
{
bool written = false;
bool address_taken = false;
int i;
struct ipa_ref *ref;
- for (i = 0; ipa_ref_list_referring_iterate (&vnode->symbol.ref_list,
+ for (i = 0; ipa_ref_list_referring_iterate (&vnode->ref_list,
i, ref)
&& (!written || !address_taken); i++)
switch (ref->use)
@@ -616,21 +617,21 @@ ipa_discover_readonly_nonaddressable_vars (void)
written = true;
break;
}
- if (TREE_ADDRESSABLE (vnode->symbol.decl) && !address_taken)
+ if (TREE_ADDRESSABLE (vnode->decl) && !address_taken)
{
if (dump_file)
fprintf (dump_file, " %s (addressable)", varpool_node_name (vnode));
- TREE_ADDRESSABLE (vnode->symbol.decl) = 0;
+ TREE_ADDRESSABLE (vnode->decl) = 0;
}
- if (!TREE_READONLY (vnode->symbol.decl) && !address_taken && !written
+ if (!TREE_READONLY (vnode->decl) && !address_taken && !written
/* Making variable in explicit section readonly can cause section
type conflict.
See e.g. gcc.c-torture/compile/pr23237.c */
- && DECL_SECTION_NAME (vnode->symbol.decl) == NULL)
+ && DECL_SECTION_NAME (vnode->decl) == NULL)
{
if (dump_file)
fprintf (dump_file, " %s (read-only)", varpool_node_name (vnode));
- TREE_READONLY (vnode->symbol.decl) = 1;
+ TREE_READONLY (vnode->decl) = 1;
}
}
if (dump_file)
@@ -639,11 +640,11 @@ ipa_discover_readonly_nonaddressable_vars (void)
/* Return true when there is a reference to node and it is not vtable. */
static bool
-address_taken_from_non_vtable_p (symtab_node node)
+address_taken_from_non_vtable_p (symtab_node *node)
{
int i;
struct ipa_ref *ref;
- for (i = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list,
+ for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list,
i, ref); i++)
if (ref->use == IPA_REF_ADDR)
{
@@ -651,7 +652,7 @@ address_taken_from_non_vtable_p (symtab_node node)
if (is_a <cgraph_node> (ref->referring))
return true;
node = ipa_ref_referring_varpool_node (ref);
- if (!DECL_VIRTUAL_P (node->symbol.decl))
+ if (!DECL_VIRTUAL_P (node->decl))
return true;
}
return false;
@@ -660,35 +661,35 @@ address_taken_from_non_vtable_p (symtab_node node)
/* A helper for comdat_can_be_unshared_p. */
static bool
-comdat_can_be_unshared_p_1 (symtab_node node)
+comdat_can_be_unshared_p_1 (symtab_node *node)
{
/* When address is taken, we don't know if equality comparison won't
break eventually. Exception are virutal functions, C++
constructors/destructors and vtables, where this is not possible by
language standard. */
- if (!DECL_VIRTUAL_P (node->symbol.decl)
- && (TREE_CODE (node->symbol.decl) != FUNCTION_DECL
- || (!DECL_CXX_CONSTRUCTOR_P (node->symbol.decl)
- && !DECL_CXX_DESTRUCTOR_P (node->symbol.decl)))
+ if (!DECL_VIRTUAL_P (node->decl)
+ && (TREE_CODE (node->decl) != FUNCTION_DECL
+ || (!DECL_CXX_CONSTRUCTOR_P (node->decl)
+ && !DECL_CXX_DESTRUCTOR_P (node->decl)))
&& address_taken_from_non_vtable_p (node))
return false;
/* If the symbol is used in some weird way, better to not touch it. */
- if (node->symbol.force_output)
+ if (node->force_output)
return false;
/* Explicit instantiations needs to be output when possibly
used externally. */
- if (node->symbol.forced_by_abi
- && TREE_PUBLIC (node->symbol.decl)
- && (node->symbol.resolution != LDPR_PREVAILING_DEF_IRONLY
+ if (node->forced_by_abi
+ && TREE_PUBLIC (node->decl)
+ && (node->resolution != LDPR_PREVAILING_DEF_IRONLY
&& !flag_whole_program))
return false;
/* Non-readonly and volatile variables can not be duplicated. */
if (is_a <varpool_node> (node)
- && (!TREE_READONLY (node->symbol.decl)
- || TREE_THIS_VOLATILE (node->symbol.decl)))
+ && (!TREE_READONLY (node->decl)
+ || TREE_THIS_VOLATILE (node->decl)))
return false;
return true;
}
@@ -703,19 +704,19 @@ comdat_can_be_unshared_p_1 (symtab_node node)
but in C++ there is no way to compare their addresses for equality. */
static bool
-comdat_can_be_unshared_p (symtab_node node)
+comdat_can_be_unshared_p (symtab_node *node)
{
if (!comdat_can_be_unshared_p_1 (node))
return false;
- if (node->symbol.same_comdat_group)
+ if (node->same_comdat_group)
{
- symtab_node next;
+ symtab_node *next;
/* If more than one function is in the same COMDAT group, it must
be shared even if just one function in the comdat group has
address taken. */
- for (next = node->symbol.same_comdat_group;
- next != node; next = next->symbol.same_comdat_group)
+ for (next = node->same_comdat_group;
+ next != node; next = next->same_comdat_group)
if (!comdat_can_be_unshared_p_1 (next))
return false;
}
@@ -728,10 +729,10 @@ static bool
cgraph_externally_visible_p (struct cgraph_node *node,
bool whole_program)
{
- if (!node->symbol.definition)
+ if (!node->definition)
return false;
- if (!TREE_PUBLIC (node->symbol.decl)
- || DECL_EXTERNAL (node->symbol.decl))
+ if (!TREE_PUBLIC (node->decl)
+ || DECL_EXTERNAL (node->decl))
return false;
/* Do not try to localize built-in functions yet. One of problems is that we
@@ -739,44 +740,44 @@ cgraph_externally_visible_p (struct cgraph_node *node,
using the implicit built-in declarations anymore. Similarly this enables
us to remove them as unreachable before actual calls may appear during
expansion or folding. */
- if (DECL_BUILT_IN (node->symbol.decl))
+ if (DECL_BUILT_IN (node->decl))
return true;
/* If linker counts on us, we must preserve the function. */
- if (symtab_used_from_object_file_p ((symtab_node) node))
+ if (symtab_used_from_object_file_p (node))
return true;
- if (DECL_PRESERVE_P (node->symbol.decl))
+ if (DECL_PRESERVE_P (node->decl))
return true;
if (lookup_attribute ("externally_visible",
- DECL_ATTRIBUTES (node->symbol.decl)))
+ DECL_ATTRIBUTES (node->decl)))
return true;
if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
&& lookup_attribute ("dllexport",
- DECL_ATTRIBUTES (node->symbol.decl)))
+ DECL_ATTRIBUTES (node->decl)))
return true;
- if (node->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY)
+ if (node->resolution == LDPR_PREVAILING_DEF_IRONLY)
return false;
/* When doing LTO or whole program, we can bring COMDAT functoins static.
This improves code quality and we know we will duplicate them at most twice
(in the case that we are not using plugin and link with object file
implementing same COMDAT) */
if ((in_lto_p || whole_program)
- && DECL_COMDAT (node->symbol.decl)
- && comdat_can_be_unshared_p ((symtab_node) node))
+ && DECL_COMDAT (node->decl)
+ && comdat_can_be_unshared_p (node))
return false;
/* When doing link time optimizations, hidden symbols become local. */
if (in_lto_p
- && (DECL_VISIBILITY (node->symbol.decl) == VISIBILITY_HIDDEN
- || DECL_VISIBILITY (node->symbol.decl) == VISIBILITY_INTERNAL)
+ && (DECL_VISIBILITY (node->decl) == VISIBILITY_HIDDEN
+ || DECL_VISIBILITY (node->decl) == VISIBILITY_INTERNAL)
/* Be sure that node is defined in IR file, not in other object
file. In that case we don't set used_from_other_object_file. */
- && node->symbol.definition)
+ && node->definition)
;
else if (!whole_program)
return true;
- if (MAIN_NAME_P (DECL_NAME (node->symbol.decl)))
+ if (MAIN_NAME_P (DECL_NAME (node->decl)))
return true;
return false;
@@ -787,26 +788,26 @@ cgraph_externally_visible_p (struct cgraph_node *node,
bool
varpool_externally_visible_p (struct varpool_node *vnode)
{
- if (DECL_EXTERNAL (vnode->symbol.decl))
+ if (DECL_EXTERNAL (vnode->decl))
return true;
- if (!TREE_PUBLIC (vnode->symbol.decl))
+ if (!TREE_PUBLIC (vnode->decl))
return false;
/* If linker counts on us, we must preserve the function. */
- if (symtab_used_from_object_file_p ((symtab_node) vnode))
+ if (symtab_used_from_object_file_p (vnode))
return true;
- if (DECL_HARD_REGISTER (vnode->symbol.decl))
+ if (DECL_HARD_REGISTER (vnode->decl))
return true;
- if (DECL_PRESERVE_P (vnode->symbol.decl))
+ if (DECL_PRESERVE_P (vnode->decl))
return true;
if (lookup_attribute ("externally_visible",
- DECL_ATTRIBUTES (vnode->symbol.decl)))
+ DECL_ATTRIBUTES (vnode->decl)))
return true;
if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
&& lookup_attribute ("dllexport",
- DECL_ATTRIBUTES (vnode->symbol.decl)))
+ DECL_ATTRIBUTES (vnode->decl)))
return true;
/* See if we have linker information about symbol not being used or
@@ -815,9 +816,9 @@ varpool_externally_visible_p (struct varpool_node *vnode)
Even if the linker clams the symbol is unused, never bring internal
symbols that are declared by user as used or externally visible.
This is needed for i.e. references from asm statements. */
- if (symtab_used_from_object_file_p ((symtab_node) vnode))
+ if (symtab_used_from_object_file_p (vnode))
return true;
- if (vnode->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY)
+ if (vnode->resolution == LDPR_PREVAILING_DEF_IRONLY)
return false;
/* As a special case, the COMDAT virtual tables can be unshared.
@@ -826,17 +827,17 @@ varpool_externally_visible_p (struct varpool_node *vnode)
is faster for dynamic linking. Also this match logic hidding vtables
from LTO symbol tables. */
if ((in_lto_p || flag_whole_program)
- && DECL_COMDAT (vnode->symbol.decl)
- && comdat_can_be_unshared_p ((symtab_node) vnode))
+ && DECL_COMDAT (vnode->decl)
+ && comdat_can_be_unshared_p (vnode))
return false;
/* When doing link time optimizations, hidden symbols become local. */
if (in_lto_p
- && (DECL_VISIBILITY (vnode->symbol.decl) == VISIBILITY_HIDDEN
- || DECL_VISIBILITY (vnode->symbol.decl) == VISIBILITY_INTERNAL)
+ && (DECL_VISIBILITY (vnode->decl) == VISIBILITY_HIDDEN
+ || DECL_VISIBILITY (vnode->decl) == VISIBILITY_INTERNAL)
/* Be sure that node is defined in IR file, not in other object
file. In that case we don't set used_from_other_object_file. */
- && vnode->symbol.definition)
+ && vnode->definition)
;
else if (!flag_whole_program)
return true;
@@ -848,7 +849,7 @@ varpool_externally_visible_p (struct varpool_node *vnode)
FIXME: We can do so for readonly vars with no address taken and
possibly also for vtables since no direct pointer comparsion is done.
It might be interesting to do so to reduce linking overhead. */
- if (DECL_COMDAT (vnode->symbol.decl) || DECL_WEAK (vnode->symbol.decl))
+ if (DECL_COMDAT (vnode->decl) || DECL_WEAK (vnode->decl))
return true;
return false;
}
@@ -858,7 +859,7 @@ varpool_externally_visible_p (struct varpool_node *vnode)
*/
bool
-can_replace_by_local_alias (symtab_node node)
+can_replace_by_local_alias (symtab_node *node)
{
return (symtab_node_availability (node) > AVAIL_OVERWRITABLE
&& !symtab_can_be_discarded (node));
@@ -882,89 +883,89 @@ function_and_variable_visibility (bool whole_program)
struct varpool_node *vnode;
/* All aliases should be procssed at this point. */
- gcc_checking_assert (!alias_pairs || !alias_pairs->length());
+ gcc_checking_assert (!alias_pairs || !alias_pairs->length ());
FOR_EACH_FUNCTION (node)
{
- int flags = flags_from_decl_or_type (node->symbol.decl);
+ int flags = flags_from_decl_or_type (node->decl);
/* Optimize away PURE and CONST constructors and destructors. */
if (optimize
&& (flags & (ECF_CONST | ECF_PURE))
&& !(flags & ECF_LOOPING_CONST_OR_PURE))
{
- DECL_STATIC_CONSTRUCTOR (node->symbol.decl) = 0;
- DECL_STATIC_DESTRUCTOR (node->symbol.decl) = 0;
+ DECL_STATIC_CONSTRUCTOR (node->decl) = 0;
+ DECL_STATIC_DESTRUCTOR (node->decl) = 0;
}
/* Frontends and alias code marks nodes as needed before parsing is finished.
We may end up marking as node external nodes where this flag is meaningless
strip it. */
- if (DECL_EXTERNAL (node->symbol.decl) || !node->symbol.definition)
+ if (DECL_EXTERNAL (node->decl) || !node->definition)
{
- node->symbol.force_output = 0;
- node->symbol.forced_by_abi = 0;
+ node->force_output = 0;
+ node->forced_by_abi = 0;
}
/* C++ FE on lack of COMDAT support create local COMDAT functions
(that ought to be shared but can not due to object format
limitations). It is necessary to keep the flag to make rest of C++ FE
happy. Clear the flag here to avoid confusion in middle-end. */
- if (DECL_COMDAT (node->symbol.decl) && !TREE_PUBLIC (node->symbol.decl))
- DECL_COMDAT (node->symbol.decl) = 0;
+ if (DECL_COMDAT (node->decl) && !TREE_PUBLIC (node->decl))
+ DECL_COMDAT (node->decl) = 0;
/* For external decls stop tracking same_comdat_group. It doesn't matter
what comdat group they are in when they won't be emitted in this TU. */
- if (node->symbol.same_comdat_group && DECL_EXTERNAL (node->symbol.decl))
+ if (node->same_comdat_group && DECL_EXTERNAL (node->decl))
{
#ifdef ENABLE_CHECKING
- symtab_node n;
+ symtab_node *n;
- for (n = node->symbol.same_comdat_group;
- n != (symtab_node)node;
- n = n->symbol.same_comdat_group)
+ for (n = node->same_comdat_group;
+ n != node;
+ n = n->same_comdat_group)
/* If at least one of same comdat group functions is external,
all of them have to be, otherwise it is a front-end bug. */
- gcc_assert (DECL_EXTERNAL (n->symbol.decl));
+ gcc_assert (DECL_EXTERNAL (n->decl));
#endif
- symtab_dissolve_same_comdat_group_list ((symtab_node) node);
+ symtab_dissolve_same_comdat_group_list (node);
}
- gcc_assert ((!DECL_WEAK (node->symbol.decl)
- && !DECL_COMDAT (node->symbol.decl))
- || TREE_PUBLIC (node->symbol.decl)
- || node->symbol.weakref
- || DECL_EXTERNAL (node->symbol.decl));
+ gcc_assert ((!DECL_WEAK (node->decl)
+ && !DECL_COMDAT (node->decl))
+ || TREE_PUBLIC (node->decl)
+ || node->weakref
+ || DECL_EXTERNAL (node->decl));
if (cgraph_externally_visible_p (node, whole_program))
{
gcc_assert (!node->global.inlined_to);
- node->symbol.externally_visible = true;
+ node->externally_visible = true;
}
else
{
- node->symbol.externally_visible = false;
- node->symbol.forced_by_abi = false;
+ node->externally_visible = false;
+ node->forced_by_abi = false;
}
- if (!node->symbol.externally_visible
- && node->symbol.definition && !node->symbol.weakref
- && !DECL_EXTERNAL (node->symbol.decl))
+ if (!node->externally_visible
+ && node->definition && !node->weakref
+ && !DECL_EXTERNAL (node->decl))
{
gcc_assert (whole_program || in_lto_p
- || !TREE_PUBLIC (node->symbol.decl));
- node->symbol.unique_name = ((node->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY
- || node->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY_EXP)
- && TREE_PUBLIC (node->symbol.decl));
- symtab_make_decl_local (node->symbol.decl);
- node->symbol.resolution = LDPR_PREVAILING_DEF_IRONLY;
- if (node->symbol.same_comdat_group)
+ || !TREE_PUBLIC (node->decl));
+ node->unique_name = ((node->resolution == LDPR_PREVAILING_DEF_IRONLY
+ || node->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP)
+ && TREE_PUBLIC (node->decl));
+ symtab_make_decl_local (node->decl);
+ node->resolution = LDPR_PREVAILING_DEF_IRONLY;
+ if (node->same_comdat_group)
/* cgraph_externally_visible_p has already checked all other nodes
in the group and they will all be made local. We need to
dissolve the group at once so that the predicate does not
segfault though. */
- symtab_dissolve_same_comdat_group_list ((symtab_node) node);
+ symtab_dissolve_same_comdat_group_list (node);
}
if (node->thunk.thunk_p
- && TREE_PUBLIC (node->symbol.decl))
+ && TREE_PUBLIC (node->decl))
{
struct cgraph_node *decl_node = node;
@@ -972,16 +973,16 @@ function_and_variable_visibility (bool whole_program)
/* Thunks have the same visibility as function they are attached to.
Make sure the C++ front end set this up properly. */
- if (DECL_ONE_ONLY (decl_node->symbol.decl))
+ if (DECL_ONE_ONLY (decl_node->decl))
{
- gcc_checking_assert (DECL_COMDAT (node->symbol.decl)
- == DECL_COMDAT (decl_node->symbol.decl));
- gcc_checking_assert (DECL_COMDAT_GROUP (node->symbol.decl)
- == DECL_COMDAT_GROUP (decl_node->symbol.decl));
- gcc_checking_assert (node->symbol.same_comdat_group);
+ gcc_checking_assert (DECL_COMDAT (node->decl)
+ == DECL_COMDAT (decl_node->decl));
+ gcc_checking_assert (DECL_COMDAT_GROUP (node->decl)
+ == DECL_COMDAT_GROUP (decl_node->decl));
+ gcc_checking_assert (node->same_comdat_group);
}
- if (DECL_EXTERNAL (decl_node->symbol.decl))
- DECL_EXTERNAL (node->symbol.decl) = 1;
+ if (DECL_EXTERNAL (decl_node->decl))
+ DECL_EXTERNAL (node->decl) = 1;
}
}
FOR_EACH_DEFINED_FUNCTION (node)
@@ -994,9 +995,9 @@ function_and_variable_visibility (bool whole_program)
cheaper and enable more optimization.
TODO: We can also update virtual tables. */
- if (node->callers && can_replace_by_local_alias ((symtab_node)node))
+ if (node->callers && can_replace_by_local_alias (node))
{
- struct cgraph_node *alias = cgraph (symtab_nonoverwritable_alias ((symtab_node) node));
+ struct cgraph_node *alias = cgraph (symtab_nonoverwritable_alias (node));
if (alias && alias != node)
{
@@ -1005,9 +1006,9 @@ function_and_variable_visibility (bool whole_program)
struct cgraph_edge *e = node->callers;
cgraph_redirect_edge_callee (e, alias);
- if (gimple_has_body_p (e->caller->symbol.decl))
+ if (gimple_has_body_p (e->caller->decl))
{
- push_cfun (DECL_STRUCT_FUNCTION (e->caller->symbol.decl));
+ push_cfun (DECL_STRUCT_FUNCTION (e->caller->decl));
cgraph_redirect_edge_call_stmt_to_callee (e);
pop_cfun ();
}
@@ -1018,10 +1019,10 @@ function_and_variable_visibility (bool whole_program)
FOR_EACH_VARIABLE (vnode)
{
/* weak flag makes no sense on local variables. */
- gcc_assert (!DECL_WEAK (vnode->symbol.decl)
- || vnode->symbol.weakref
- || TREE_PUBLIC (vnode->symbol.decl)
- || DECL_EXTERNAL (vnode->symbol.decl));
+ gcc_assert (!DECL_WEAK (vnode->decl)
+ || vnode->weakref
+ || TREE_PUBLIC (vnode->decl)
+ || DECL_EXTERNAL (vnode->decl));
/* In several cases declarations can not be common:
- when declaration has initializer
@@ -1035,39 +1036,39 @@ function_and_variable_visibility (bool whole_program)
static int a __attribute__ ((common))
Canonicalize things here and clear the redundant flag. */
- if (DECL_COMMON (vnode->symbol.decl)
- && (!(TREE_PUBLIC (vnode->symbol.decl)
- || DECL_EXTERNAL (vnode->symbol.decl))
- || (DECL_INITIAL (vnode->symbol.decl)
- && DECL_INITIAL (vnode->symbol.decl) != error_mark_node)
- || DECL_WEAK (vnode->symbol.decl)
- || DECL_SECTION_NAME (vnode->symbol.decl) != NULL
+ if (DECL_COMMON (vnode->decl)
+ && (!(TREE_PUBLIC (vnode->decl)
+ || DECL_EXTERNAL (vnode->decl))
+ || (DECL_INITIAL (vnode->decl)
+ && DECL_INITIAL (vnode->decl) != error_mark_node)
+ || DECL_WEAK (vnode->decl)
+ || DECL_SECTION_NAME (vnode->decl) != NULL
|| ! (ADDR_SPACE_GENERIC_P
- (TYPE_ADDR_SPACE (TREE_TYPE (vnode->symbol.decl))))))
- DECL_COMMON (vnode->symbol.decl) = 0;
+ (TYPE_ADDR_SPACE (TREE_TYPE (vnode->decl))))))
+ DECL_COMMON (vnode->decl) = 0;
}
FOR_EACH_DEFINED_VARIABLE (vnode)
{
- if (!vnode->symbol.definition)
+ if (!vnode->definition)
continue;
if (varpool_externally_visible_p (vnode))
- vnode->symbol.externally_visible = true;
+ vnode->externally_visible = true;
else
{
- vnode->symbol.externally_visible = false;
- vnode->symbol.forced_by_abi = false;
+ vnode->externally_visible = false;
+ vnode->forced_by_abi = false;
}
- if (!vnode->symbol.externally_visible
- && !vnode->symbol.weakref)
+ if (!vnode->externally_visible
+ && !vnode->weakref)
{
- gcc_assert (in_lto_p || whole_program || !TREE_PUBLIC (vnode->symbol.decl));
- vnode->symbol.unique_name = ((vnode->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY
- || vnode->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY_EXP)
- && TREE_PUBLIC (vnode->symbol.decl));
- symtab_make_decl_local (vnode->symbol.decl);
- if (vnode->symbol.same_comdat_group)
- symtab_dissolve_same_comdat_group_list ((symtab_node) vnode);
- vnode->symbol.resolution = LDPR_PREVAILING_DEF_IRONLY;
+ gcc_assert (in_lto_p || whole_program || !TREE_PUBLIC (vnode->decl));
+ vnode->unique_name = ((vnode->resolution == LDPR_PREVAILING_DEF_IRONLY
+ || vnode->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP)
+ && TREE_PUBLIC (vnode->decl));
+ symtab_make_decl_local (vnode->decl);
+ if (vnode->same_comdat_group)
+ symtab_dissolve_same_comdat_group_list (vnode);
+ vnode->resolution = LDPR_PREVAILING_DEF_IRONLY;
}
}
@@ -1080,12 +1081,12 @@ function_and_variable_visibility (bool whole_program)
fprintf (dump_file, "\n\n");
fprintf (dump_file, "\nMarking externally visible functions:");
FOR_EACH_DEFINED_FUNCTION (node)
- if (node->symbol.externally_visible)
+ if (node->externally_visible)
fprintf (dump_file, " %s", cgraph_node_name (node));
fprintf (dump_file, "\n\n");
fprintf (dump_file, "\nMarking externally visible variables:");
FOR_EACH_DEFINED_VARIABLE (vnode)
- if (vnode->symbol.externally_visible)
+ if (vnode->externally_visible)
fprintf (dump_file, " %s", varpool_node_name (vnode));
fprintf (dump_file, "\n\n");
}
@@ -1122,8 +1123,9 @@ const pass_data pass_data_ipa_function_and_variable_visibility =
class pass_ipa_function_and_variable_visibility : public simple_ipa_opt_pass
{
public:
- pass_ipa_function_and_variable_visibility(gcc::context *ctxt)
- : simple_ipa_opt_pass(pass_data_ipa_function_and_variable_visibility, ctxt)
+ pass_ipa_function_and_variable_visibility (gcc::context *ctxt)
+ : simple_ipa_opt_pass (pass_data_ipa_function_and_variable_visibility,
+ ctxt)
{}
/* opt_pass methods: */
@@ -1170,8 +1172,8 @@ const pass_data pass_data_ipa_free_inline_summary =
class pass_ipa_free_inline_summary : public simple_ipa_opt_pass
{
public:
- pass_ipa_free_inline_summary(gcc::context *ctxt)
- : simple_ipa_opt_pass(pass_data_ipa_free_inline_summary, ctxt)
+ pass_ipa_free_inline_summary (gcc::context *ctxt)
+ : simple_ipa_opt_pass (pass_data_ipa_free_inline_summary, ctxt)
{}
/* opt_pass methods: */
@@ -1226,17 +1228,17 @@ const pass_data pass_data_ipa_whole_program_visibility =
class pass_ipa_whole_program_visibility : public ipa_opt_pass_d
{
public:
- pass_ipa_whole_program_visibility(gcc::context *ctxt)
- : ipa_opt_pass_d(pass_data_ipa_whole_program_visibility, ctxt,
- NULL, /* generate_summary */
- NULL, /* write_summary */
- NULL, /* read_summary */
- NULL, /* write_optimization_summary */
- NULL, /* read_optimization_summary */
- NULL, /* stmt_fixup */
- 0, /* function_transform_todo_flags_start */
- NULL, /* function_transform */
- NULL) /* variable_transform */
+ pass_ipa_whole_program_visibility (gcc::context *ctxt)
+ : ipa_opt_pass_d (pass_data_ipa_whole_program_visibility, ctxt,
+ NULL, /* generate_summary */
+ NULL, /* write_summary */
+ NULL, /* read_summary */
+ NULL, /* write_optimization_summary */
+ NULL, /* read_optimization_summary */
+ NULL, /* stmt_fixup */
+ 0, /* function_transform_todo_flags_start */
+ NULL, /* function_transform */
+ NULL) /* variable_transform */
{}
/* opt_pass methods: */
@@ -1258,9 +1260,11 @@ make_pass_ipa_whole_program_visibility (gcc::context *ctxt)
}
/* Generate and emit a static constructor or destructor. WHICH must
- be one of 'I' (for a constructor) or 'D' (for a destructor). BODY
- is a STATEMENT_LIST containing GENERIC statements. PRIORITY is the
- initialization priority for this constructor or destructor.
+ be one of 'I' (for a constructor), 'D' (for a destructor), 'P'
+ (for chp static vars constructor) or 'B' (for chkp static bounds
+ constructor). BODY is a STATEMENT_LIST containing GENERIC
+ statements. PRIORITY is the initialization priority for this
+ constructor or destructor.
FINAL specify whether the externally visible name for collect2 should
be produced. */
@@ -1319,6 +1323,20 @@ cgraph_build_static_cdtor_1 (char which, tree body, int priority, bool final)
DECL_STATIC_CONSTRUCTOR (decl) = 1;
decl_init_priority_insert (decl, priority);
break;
+ case 'P':
+ DECL_STATIC_CONSTRUCTOR (decl) = 1;
+ DECL_ATTRIBUTES (decl) = tree_cons (get_identifier ("chkp ctor"),
+ NULL,
+ NULL_TREE);
+ decl_init_priority_insert (decl, priority);
+ break;
+ case 'B':
+ DECL_STATIC_CONSTRUCTOR (decl) = 1;
+ DECL_ATTRIBUTES (decl) = tree_cons (get_identifier ("bnd_legacy"),
+ NULL,
+ NULL_TREE);
+ decl_init_priority_insert (decl, priority);
+ break;
case 'D':
DECL_STATIC_DESTRUCTOR (decl) = 1;
decl_fini_priority_insert (decl, priority);
@@ -1336,9 +1354,11 @@ cgraph_build_static_cdtor_1 (char which, tree body, int priority, bool final)
}
/* Generate and emit a static constructor or destructor. WHICH must
- be one of 'I' (for a constructor) or 'D' (for a destructor). BODY
- is a STATEMENT_LIST containing GENERIC statements. PRIORITY is the
- initialization priority for this constructor or destructor. */
+ be one of 'I' (for a constructor), 'D' (for a destructor), 'P'
+ (for chkp static vars constructor) or 'B' (for chkp static bounds
+ constructor). BODY is a STATEMENT_LIST containing GENERIC
+ statements. PRIORITY is the initialization priority for this
+ constructor or destructor. */
void
cgraph_build_static_cdtor (char which, tree body, int priority)
@@ -1361,12 +1381,12 @@ static vec<tree> static_dtors;
static void
record_cdtor_fn (struct cgraph_node *node)
{
- if (DECL_STATIC_CONSTRUCTOR (node->symbol.decl))
- static_ctors.safe_push (node->symbol.decl);
- if (DECL_STATIC_DESTRUCTOR (node->symbol.decl))
- static_dtors.safe_push (node->symbol.decl);
- node = cgraph_get_node (node->symbol.decl);
- DECL_DISREGARD_INLINE_LIMITS (node->symbol.decl) = 1;
+ if (DECL_STATIC_CONSTRUCTOR (node->decl))
+ static_ctors.safe_push (node->decl);
+ if (DECL_STATIC_DESTRUCTOR (node->decl))
+ static_dtors.safe_push (node->decl);
+ node = cgraph_get_node (node->decl);
+ DECL_DISREGARD_INLINE_LIMITS (node->decl) = 1;
}
/* Define global constructors/destructor functions for the CDTORS, of
@@ -1520,8 +1540,8 @@ ipa_cdtor_merge (void)
{
struct cgraph_node *node;
FOR_EACH_DEFINED_FUNCTION (node)
- if (DECL_STATIC_CONSTRUCTOR (node->symbol.decl)
- || DECL_STATIC_DESTRUCTOR (node->symbol.decl))
+ if (DECL_STATIC_CONSTRUCTOR (node->decl)
+ || DECL_STATIC_DESTRUCTOR (node->decl))
record_cdtor_fn (node);
build_cdtor_fns ();
static_ctors.release ();
@@ -1559,17 +1579,17 @@ const pass_data pass_data_ipa_cdtor_merge =
class pass_ipa_cdtor_merge : public ipa_opt_pass_d
{
public:
- pass_ipa_cdtor_merge(gcc::context *ctxt)
- : ipa_opt_pass_d(pass_data_ipa_cdtor_merge, ctxt,
- NULL, /* generate_summary */
- NULL, /* write_summary */
- NULL, /* read_summary */
- NULL, /* write_optimization_summary */
- NULL, /* read_optimization_summary */
- NULL, /* stmt_fixup */
- 0, /* function_transform_todo_flags_start */
- NULL, /* function_transform */
- NULL) /* variable_transform */
+ pass_ipa_cdtor_merge (gcc::context *ctxt)
+ : ipa_opt_pass_d (pass_data_ipa_cdtor_merge, ctxt,
+ NULL, /* generate_summary */
+ NULL, /* write_summary */
+ NULL, /* read_summary */
+ NULL, /* write_optimization_summary */
+ NULL, /* read_optimization_summary */
+ NULL, /* stmt_fixup */
+ 0, /* function_transform_todo_flags_start */
+ NULL, /* function_transform */
+ NULL) /* variable_transform */
{}
/* opt_pass methods: */
diff --git a/gcc/ira-build.c b/gcc/ira-build.c
index 0e2fd0c5510..ed513767f3c 100644
--- a/gcc/ira-build.c
+++ b/gcc/ira-build.c
@@ -79,6 +79,13 @@ int ira_objects_num;
/* Map a conflict id to its conflict record. */
ira_object_t *ira_object_id_map;
+/* Array of references to all allocno preferences. The order number
+ of the preference corresponds to the index in the array. */
+ira_pref_t *ira_prefs;
+
+/* Size of the previous array. */
+int ira_prefs_num;
+
/* Array of references to all copies. The order number of the copy
corresponds to the index in the array. Removed copies have NULL
element value. */
@@ -515,6 +522,7 @@ ira_create_allocno (int regno, bool cap_p,
ALLOCNO_BAD_SPILL_P (a) = false;
ALLOCNO_ASSIGNED_P (a) = false;
ALLOCNO_MODE (a) = (regno < 0 ? VOIDmode : PSEUDO_REGNO_MODE (regno));
+ ALLOCNO_PREFS (a) = NULL;
ALLOCNO_COPIES (a) = NULL;
ALLOCNO_HARD_REG_COSTS (a) = NULL;
ALLOCNO_CONFLICT_HARD_REG_COSTS (a) = NULL;
@@ -1163,6 +1171,195 @@ finish_allocnos (void)
+/* Pools for allocno preferences. */
+static alloc_pool pref_pool;
+
+/* Vec containing references to all created preferences. It is a
+ container of array ira_prefs. */
+static vec<ira_pref_t> pref_vec;
+
+/* The function initializes data concerning allocno prefs. */
+static void
+initiate_prefs (void)
+{
+ pref_pool
+ = create_alloc_pool ("prefs", sizeof (struct ira_allocno_pref), 100);
+ pref_vec.create (get_max_uid ());
+ ira_prefs = NULL;
+ ira_prefs_num = 0;
+}
+
+/* Return pref for A and HARD_REGNO if any. */
+static ira_pref_t
+find_allocno_pref (ira_allocno_t a, int hard_regno)
+{
+ ira_pref_t pref;
+
+ for (pref = ALLOCNO_PREFS (a); pref != NULL; pref = pref->next_pref)
+ if (pref->allocno == a && pref->hard_regno == hard_regno)
+ return pref;
+ return NULL;
+}
+
+/* Create and return pref with given attributes A, HARD_REGNO, and FREQ. */
+ira_pref_t
+ira_create_pref (ira_allocno_t a, int hard_regno, int freq)
+{
+ ira_pref_t pref;
+
+ pref = (ira_pref_t) pool_alloc (pref_pool);
+ pref->num = ira_prefs_num;
+ pref->allocno = a;
+ pref->hard_regno = hard_regno;
+ pref->freq = freq;
+ pref_vec.safe_push (pref);
+ ira_prefs = pref_vec.address ();
+ ira_prefs_num = pref_vec.length ();
+ return pref;
+}
+
+/* Attach a pref PREF to the cooresponding allocno. */
+static void
+add_allocno_pref_to_list (ira_pref_t pref)
+{
+ ira_allocno_t a = pref->allocno;
+
+ pref->next_pref = ALLOCNO_PREFS (a);
+ ALLOCNO_PREFS (a) = pref;
+}
+
+/* Create (or update frequency if the pref already exists) the pref of
+ allocnos A preferring HARD_REGNO with frequency FREQ. */
+void
+ira_add_allocno_pref (ira_allocno_t a, int hard_regno, int freq)
+{
+ ira_pref_t pref;
+
+ if (freq <= 0)
+ return;
+ if ((pref = find_allocno_pref (a, hard_regno)) != NULL)
+ {
+ pref->freq += freq;
+ return;
+ }
+ pref = ira_create_pref (a, hard_regno, freq);
+ ira_assert (a != NULL);
+ add_allocno_pref_to_list (pref);
+}
+
+/* Print info about PREF into file F. */
+static void
+print_pref (FILE *f, ira_pref_t pref)
+{
+ fprintf (f, " pref%d:a%d(r%d)<-hr%d@%d\n", pref->num,
+ ALLOCNO_NUM (pref->allocno), ALLOCNO_REGNO (pref->allocno),
+ pref->hard_regno, pref->freq);
+}
+
+/* Print info about PREF into stderr. */
+void
+ira_debug_pref (ira_pref_t pref)
+{
+ print_pref (stderr, pref);
+}
+
+/* Print info about all prefs into file F. */
+static void
+print_prefs (FILE *f)
+{
+ ira_pref_t pref;
+ ira_pref_iterator pi;
+
+ FOR_EACH_PREF (pref, pi)
+ print_pref (f, pref);
+}
+
+/* Print info about all prefs into stderr. */
+void
+ira_debug_prefs (void)
+{
+ print_prefs (stderr);
+}
+
+/* Print info about prefs involving allocno A into file F. */
+static void
+print_allocno_prefs (FILE *f, ira_allocno_t a)
+{
+ ira_pref_t pref;
+
+ fprintf (f, " a%d(r%d):", ALLOCNO_NUM (a), ALLOCNO_REGNO (a));
+ for (pref = ALLOCNO_PREFS (a); pref != NULL; pref = pref->next_pref)
+ fprintf (f, " pref%d:hr%d@%d", pref->num, pref->hard_regno, pref->freq);
+ fprintf (f, "\n");
+}
+
+/* Print info about prefs involving allocno A into stderr. */
+void
+ira_debug_allocno_prefs (ira_allocno_t a)
+{
+ print_allocno_prefs (stderr, a);
+}
+
+/* The function frees memory allocated for PREF. */
+static void
+finish_pref (ira_pref_t pref)
+{
+ ira_prefs[pref->num] = NULL;
+ pool_free (pref_pool, pref);
+}
+
+/* Remove PREF from the list of allocno prefs and free memory for
+ it. */
+void
+ira_remove_pref (ira_pref_t pref)
+{
+ ira_pref_t cpref, prev;
+
+ if (internal_flag_ira_verbose > 1 && ira_dump_file != NULL)
+ fprintf (ira_dump_file, " Removing pref%d:hr%d@%d\n",
+ pref->num, pref->hard_regno, pref->freq);
+ for (prev = NULL, cpref = ALLOCNO_PREFS (pref->allocno);
+ cpref != NULL;
+ prev = cpref, cpref = cpref->next_pref)
+ if (cpref == pref)
+ break;
+ ira_assert (cpref != NULL);
+ if (prev == NULL)
+ ALLOCNO_PREFS (pref->allocno) = pref->next_pref;
+ else
+ prev->next_pref = pref->next_pref;
+ finish_pref (pref);
+}
+
+/* Remove all prefs of allocno A. */
+void
+ira_remove_allocno_prefs (ira_allocno_t a)
+{
+ ira_pref_t pref, next_pref;
+
+ for (pref = ALLOCNO_PREFS (a); pref != NULL; pref = next_pref)
+ {
+ next_pref = pref->next_pref;
+ finish_pref (pref);
+ }
+ ALLOCNO_PREFS (a) = NULL;
+}
+
+/* Free memory allocated for all prefs. */
+static void
+finish_prefs (void)
+{
+ ira_pref_t pref;
+ ira_pref_iterator pi;
+
+ FOR_EACH_PREF (pref, pi)
+ finish_pref (pref);
+ pref_vec.release ();
+ free_alloc_pool (pref_pool);
+}
+
+
+
/* Pools for copies. */
static alloc_pool copy_pool;
@@ -1235,8 +1432,8 @@ ira_create_copy (ira_allocno_t first, ira_allocno_t second, int freq,
}
/* Attach a copy CP to allocnos involved into the copy. */
-void
-ira_add_allocno_copy_to_list (ira_copy_t cp)
+static void
+add_allocno_copy_to_list (ira_copy_t cp)
{
ira_allocno_t first = cp->first, second = cp->second;
@@ -1264,8 +1461,8 @@ ira_add_allocno_copy_to_list (ira_copy_t cp)
/* Make a copy CP a canonical copy where number of the
first allocno is less than the second one. */
-void
-ira_swap_allocno_copy_ends_if_necessary (ira_copy_t cp)
+static void
+swap_allocno_copy_ends_if_necessary (ira_copy_t cp)
{
ira_allocno_t temp;
ira_copy_t temp_cp;
@@ -1305,8 +1502,8 @@ ira_add_allocno_copy (ira_allocno_t first, ira_allocno_t second, int freq,
cp = ira_create_copy (first, second, freq, constraint_p, insn,
loop_tree_node);
ira_assert (first != NULL && second != NULL);
- ira_add_allocno_copy_to_list (cp);
- ira_swap_allocno_copy_ends_if_necessary (cp);
+ add_allocno_copy_to_list (cp);
+ swap_allocno_copy_ends_if_necessary (cp);
return cp;
}
@@ -2305,6 +2502,7 @@ remove_unnecessary_allocnos (void)
map to avoid info propagation of subsequent
allocno into this already removed allocno. */
a_node->regno_allocno_map[regno] = NULL;
+ ira_remove_allocno_prefs (a);
finish_allocno (a);
}
}
@@ -2388,7 +2586,10 @@ remove_low_level_allocnos (void)
#endif
}
else
- finish_allocno (a);
+ {
+ ira_remove_allocno_prefs (a);
+ finish_allocno (a);
+ }
}
if (merged_p)
ira_rebuild_start_finish_chains ();
@@ -2408,8 +2609,8 @@ remove_unnecessary_regions (bool all_p)
mark_all_loops_for_removal ();
else
mark_loops_for_removal ();
- children_vec.create(last_basic_block + number_of_loops (cfun));
- removed_loop_vec.create(last_basic_block + number_of_loops (cfun));
+ children_vec.create (last_basic_block + number_of_loops (cfun));
+ removed_loop_vec.create (last_basic_block + number_of_loops (cfun));
remove_uneccesary_loop_nodes_from_loop_tree (ira_loop_tree_root);
children_vec.release ();
if (all_p)
@@ -3105,6 +3306,7 @@ ira_flattening (int max_regno_before_emit, int ira_max_point_before_emit)
if (internal_flag_ira_verbose > 4 && ira_dump_file != NULL)
fprintf (ira_dump_file, " Remove a%dr%d\n",
ALLOCNO_NUM (a), REGNO (allocno_emit_reg (a)));
+ ira_remove_allocno_prefs (a);
finish_allocno (a);
continue;
}
@@ -3131,8 +3333,8 @@ ira_flattening (int max_regno_before_emit, int ira_max_point_before_emit)
ira_assert
(ALLOCNO_LOOP_TREE_NODE (cp->first) == ira_loop_tree_root
&& ALLOCNO_LOOP_TREE_NODE (cp->second) == ira_loop_tree_root);
- ira_add_allocno_copy_to_list (cp);
- ira_swap_allocno_copy_ends_if_necessary (cp);
+ add_allocno_copy_to_list (cp);
+ swap_allocno_copy_ends_if_necessary (cp);
}
rebuild_regno_allocno_maps ();
if (ira_max_point != ira_max_point_before_emit)
@@ -3220,6 +3422,7 @@ ira_build (void)
df_analyze ();
initiate_cost_vectors ();
initiate_allocnos ();
+ initiate_prefs ();
initiate_copies ();
create_loop_tree_nodes ();
form_loop_tree ();
@@ -3265,6 +3468,8 @@ ira_build (void)
}
if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
print_copies (ira_dump_file);
+ if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
+ print_prefs (ira_dump_file);
if (internal_flag_ira_verbose > 0 && ira_dump_file != NULL)
{
int n, nr, nr_big;
@@ -3304,6 +3509,7 @@ void
ira_destroy (void)
{
finish_loop_tree_nodes ();
+ finish_prefs ();
finish_copies ();
finish_allocnos ();
finish_cost_vectors ();
diff --git a/gcc/ira-color.c b/gcc/ira-color.c
index 0ee31573e2e..295cd5327d7 100644
--- a/gcc/ira-color.c
+++ b/gcc/ira-color.c
@@ -88,6 +88,17 @@ struct allocno_hard_regs_node
allocno_hard_regs_node_t parent, first, prev, next;
};
+/* Info about changing hard reg costs of an allocno. */
+struct update_cost_record
+{
+ /* Hard regno for which we changed the cost. */
+ int hard_regno;
+ /* Divisor used when we changed the cost of HARD_REGNO. */
+ int divisor;
+ /* Next record for given allocno. */
+ struct update_cost_record *next;
+};
+
/* To decrease footprint of ira_allocno structure we store all data
needed only for coloring in the following structure. */
struct allocno_color_data
@@ -126,6 +137,11 @@ struct allocno_color_data
int hard_regs_subnodes_start;
/* The length of the previous array. */
int hard_regs_subnodes_num;
+ /* Records about updating allocno hard reg costs from copies. If
+ the allocno did not get expected hard register, these records are
+ used to restore original hard reg costs of allocnos connected to
+ this allocno by copies. */
+ struct update_cost_record *update_cost_records;
};
/* See above. */
@@ -1113,6 +1129,53 @@ setup_profitable_hard_regs (void)
/* This page contains functions used to choose hard registers for
allocnos. */
+/* Pool for update cost records. */
+static alloc_pool update_cost_record_pool;
+
+/* Initiate update cost records. */
+static void
+init_update_cost_records (void)
+{
+ update_cost_record_pool
+ = create_alloc_pool ("update cost records",
+ sizeof (struct update_cost_record), 100);
+}
+
+/* Return new update cost record with given params. */
+static struct update_cost_record *
+get_update_cost_record (int hard_regno, int divisor,
+ struct update_cost_record *next)
+{
+ struct update_cost_record *record;
+
+ record = (struct update_cost_record *) pool_alloc (update_cost_record_pool);
+ record->hard_regno = hard_regno;
+ record->divisor = divisor;
+ record->next = next;
+ return record;
+}
+
+/* Free memory for all records in LIST. */
+static void
+free_update_cost_record_list (struct update_cost_record *list)
+{
+ struct update_cost_record *next;
+
+ while (list != NULL)
+ {
+ next = list->next;
+ pool_free (update_cost_record_pool, list);
+ list = next;
+ }
+}
+
+/* Free memory allocated for all update cost records. */
+static void
+finish_update_cost_records (void)
+{
+ free_alloc_pool (update_cost_record_pool);
+}
+
/* Array whose element value is TRUE if the corresponding hard
register was already allocated for an allocno. */
static bool allocated_hardreg_p[FIRST_PSEUDO_REGISTER];
@@ -1129,6 +1192,11 @@ struct update_cost_queue_elem
connecting this allocno to the one being allocated. */
int divisor;
+ /* Allocno from which we are chaning costs of connected allocnos.
+ It is used not go back in graph of allocnos connected by
+ copies. */
+ ira_allocno_t from;
+
/* The next allocno in the queue, or null if this is the last element. */
ira_allocno_t next;
};
@@ -1145,11 +1213,11 @@ static struct update_cost_queue_elem *update_cost_queue_tail;
Elements are indexed by ALLOCNO_NUM. */
static struct update_cost_queue_elem *update_cost_queue_elems;
-/* The current value of update_copy_cost call count. */
+/* The current value of update_costs_from_copies call count. */
static int update_cost_check;
/* Allocate and initialize data necessary for function
- update_copy_costs. */
+ update_costs_from_copies. */
static void
initiate_cost_update (void)
{
@@ -1160,13 +1228,15 @@ initiate_cost_update (void)
= (struct update_cost_queue_elem *) ira_allocate (size);
memset (update_cost_queue_elems, 0, size);
update_cost_check = 0;
+ init_update_cost_records ();
}
-/* Deallocate data used by function update_copy_costs. */
+/* Deallocate data used by function update_costs_from_copies. */
static void
finish_cost_update (void)
{
ira_free (update_cost_queue_elems);
+ finish_update_cost_records ();
}
/* When we traverse allocnos to update hard register costs, the cost
@@ -1182,10 +1252,10 @@ start_update_cost (void)
update_cost_queue = NULL;
}
-/* Add (ALLOCNO, DIVISOR) to the end of update_cost_queue, unless
+/* Add (ALLOCNO, FROM, DIVISOR) to the end of update_cost_queue, unless
ALLOCNO is already in the queue, or has NO_REGS class. */
static inline void
-queue_update_cost (ira_allocno_t allocno, int divisor)
+queue_update_cost (ira_allocno_t allocno, ira_allocno_t from, int divisor)
{
struct update_cost_queue_elem *elem;
@@ -1194,6 +1264,7 @@ queue_update_cost (ira_allocno_t allocno, int divisor)
&& ALLOCNO_CLASS (allocno) != NO_REGS)
{
elem->check = update_cost_check;
+ elem->from = from;
elem->divisor = divisor;
elem->next = NULL;
if (update_cost_queue == NULL)
@@ -1204,11 +1275,11 @@ queue_update_cost (ira_allocno_t allocno, int divisor)
}
}
-/* Try to remove the first element from update_cost_queue. Return false
- if the queue was empty, otherwise make (*ALLOCNO, *DIVISOR) describe
- the removed element. */
+/* Try to remove the first element from update_cost_queue. Return
+ false if the queue was empty, otherwise make (*ALLOCNO, *FROM,
+ *DIVISOR) describe the removed element. */
static inline bool
-get_next_update_cost (ira_allocno_t *allocno, int *divisor)
+get_next_update_cost (ira_allocno_t *allocno, ira_allocno_t *from, int *divisor)
{
struct update_cost_queue_elem *elem;
@@ -1217,34 +1288,50 @@ get_next_update_cost (ira_allocno_t *allocno, int *divisor)
*allocno = update_cost_queue;
elem = &update_cost_queue_elems[ALLOCNO_NUM (*allocno)];
+ *from = elem->from;
*divisor = elem->divisor;
update_cost_queue = elem->next;
return true;
}
-/* Update the cost of allocnos to increase chances to remove some
- copies as the result of subsequent assignment. */
+/* Increase costs of HARD_REGNO by UPDATE_COST for ALLOCNO. Return
+ true if we really modified the cost. */
+static bool
+update_allocno_cost (ira_allocno_t allocno, int hard_regno, int update_cost)
+{
+ int i;
+ enum reg_class aclass = ALLOCNO_CLASS (allocno);
+
+ i = ira_class_hard_reg_index[aclass][hard_regno];
+ if (i < 0)
+ return false;
+ ira_allocate_and_set_or_copy_costs
+ (&ALLOCNO_UPDATED_HARD_REG_COSTS (allocno), aclass,
+ ALLOCNO_UPDATED_CLASS_COST (allocno),
+ ALLOCNO_HARD_REG_COSTS (allocno));
+ ira_allocate_and_set_or_copy_costs
+ (&ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (allocno),
+ aclass, 0, ALLOCNO_CONFLICT_HARD_REG_COSTS (allocno));
+ ALLOCNO_UPDATED_HARD_REG_COSTS (allocno)[i] += update_cost;
+ ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (allocno)[i] += update_cost;
+ return true;
+}
+
+/* Update (decrease if DECR_P) HARD_REGNO cost of allocnos connected
+ by copies to ALLOCNO to increase chances to remove some copies as
+ the result of subsequent assignment. Record cost updates if
+ RECORD_P is true. */
static void
-update_copy_costs (ira_allocno_t allocno, bool decr_p)
+update_costs_from_allocno (ira_allocno_t allocno, int hard_regno,
+ int divisor, bool decr_p, bool record_p)
{
- int i, cost, update_cost, hard_regno, divisor;
+ int cost, update_cost;
enum machine_mode mode;
enum reg_class rclass, aclass;
- ira_allocno_t another_allocno;
+ ira_allocno_t another_allocno, from = NULL;
ira_copy_t cp, next_cp;
- hard_regno = ALLOCNO_HARD_REGNO (allocno);
- ira_assert (hard_regno >= 0);
-
- aclass = ALLOCNO_CLASS (allocno);
- if (aclass == NO_REGS)
- return;
- i = ira_class_hard_reg_index[aclass][hard_regno];
- ira_assert (i >= 0);
rclass = REGNO_REG_CLASS (hard_regno);
-
- start_update_cost ();
- divisor = 1;
do
{
mode = ALLOCNO_MODE (allocno);
@@ -1264,6 +1351,9 @@ update_copy_costs (ira_allocno_t allocno, bool decr_p)
else
gcc_unreachable ();
+ if (another_allocno == from)
+ continue;
+
aclass = ALLOCNO_CLASS (another_allocno);
if (! TEST_HARD_REG_BIT (reg_class_contents[aclass],
hard_regno)
@@ -1280,24 +1370,67 @@ update_copy_costs (ira_allocno_t allocno, bool decr_p)
if (update_cost == 0)
continue;
- ira_allocate_and_set_or_copy_costs
- (&ALLOCNO_UPDATED_HARD_REG_COSTS (another_allocno), aclass,
- ALLOCNO_UPDATED_CLASS_COST (another_allocno),
- ALLOCNO_HARD_REG_COSTS (another_allocno));
- ira_allocate_and_set_or_copy_costs
- (&ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (another_allocno),
- aclass, 0, ALLOCNO_CONFLICT_HARD_REG_COSTS (another_allocno));
- i = ira_class_hard_reg_index[aclass][hard_regno];
- if (i < 0)
+ if (! update_allocno_cost (another_allocno, hard_regno, update_cost))
continue;
- ALLOCNO_UPDATED_HARD_REG_COSTS (another_allocno)[i] += update_cost;
- ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (another_allocno)[i]
- += update_cost;
-
- queue_update_cost (another_allocno, divisor * COST_HOP_DIVISOR);
+ queue_update_cost (another_allocno, allocno, divisor * COST_HOP_DIVISOR);
+ if (record_p && ALLOCNO_COLOR_DATA (another_allocno) != NULL)
+ ALLOCNO_COLOR_DATA (another_allocno)->update_cost_records
+ = get_update_cost_record (hard_regno, divisor,
+ ALLOCNO_COLOR_DATA (another_allocno)
+ ->update_cost_records);
}
}
- while (get_next_update_cost (&allocno, &divisor));
+ while (get_next_update_cost (&allocno, &from, &divisor));
+}
+
+/* Decrease preferred ALLOCNO hard register costs and costs of
+ allocnos connected to ALLOCNO through copy. */
+static void
+update_costs_from_prefs (ira_allocno_t allocno)
+{
+ ira_pref_t pref;
+
+ start_update_cost ();
+ for (pref = ALLOCNO_PREFS (allocno); pref != NULL; pref = pref->next_pref)
+ update_costs_from_allocno (allocno, pref->hard_regno,
+ COST_HOP_DIVISOR, true, true);
+}
+
+/* Update (decrease if DECR_P) the cost of allocnos connected to
+ ALLOCNO through copies to increase chances to remove some copies as
+ the result of subsequent assignment. ALLOCNO was just assigned to
+ a hard register. Record cost updates if RECORD_P is true. */
+static void
+update_costs_from_copies (ira_allocno_t allocno, bool decr_p, bool record_p)
+{
+ int hard_regno;
+
+ hard_regno = ALLOCNO_HARD_REGNO (allocno);
+ ira_assert (hard_regno >= 0 && ALLOCNO_CLASS (allocno) != NO_REGS);
+ start_update_cost ();
+ update_costs_from_allocno (allocno, hard_regno, 1, decr_p, record_p);
+}
+
+/* Restore costs of allocnos connected to ALLOCNO by copies as it was
+ before updating costs of these allocnos from given allocno. This
+ is a wise thing to do as if given allocno did not get an expected
+ hard reg, using smaller cost of the hard reg for allocnos connected
+ by copies to given allocno becomes actually misleading. Free all
+ update cost records for ALLOCNO as we don't need them anymore. */
+static void
+restore_costs_from_copies (ira_allocno_t allocno)
+{
+ struct update_cost_record *records, *curr;
+
+ if (ALLOCNO_COLOR_DATA (allocno) == NULL)
+ return;
+ records = ALLOCNO_COLOR_DATA (allocno)->update_cost_records;
+ start_update_cost ();
+ for (curr = records; curr != NULL; curr = curr->next)
+ update_costs_from_allocno (allocno, curr->hard_regno,
+ curr->divisor, true, false);
+ free_update_cost_record_list (records);
+ ALLOCNO_COLOR_DATA (allocno)->update_cost_records = NULL;
}
/* This function updates COSTS (decrease if DECR_P) for hard_registers
@@ -1313,10 +1446,10 @@ update_conflict_hard_regno_costs (int *costs, enum reg_class aclass,
int *conflict_costs;
bool cont_p;
enum reg_class another_aclass;
- ira_allocno_t allocno, another_allocno;
+ ira_allocno_t allocno, another_allocno, from;
ira_copy_t cp, next_cp;
- while (get_next_update_cost (&allocno, &divisor))
+ while (get_next_update_cost (&allocno, &from, &divisor))
for (cp = ALLOCNO_COPIES (allocno); cp != NULL; cp = next_cp)
{
if (cp->first == allocno)
@@ -1331,6 +1464,10 @@ update_conflict_hard_regno_costs (int *costs, enum reg_class aclass,
}
else
gcc_unreachable ();
+
+ if (another_allocno == from)
+ continue;
+
another_aclass = ALLOCNO_CLASS (another_allocno);
if (! ira_reg_classes_intersect_p[aclass][another_aclass]
|| ALLOCNO_ASSIGNED_P (another_allocno)
@@ -1374,7 +1511,7 @@ update_conflict_hard_regno_costs (int *costs, enum reg_class aclass,
* COST_HOP_DIVISOR
* COST_HOP_DIVISOR
* COST_HOP_DIVISOR))
- queue_update_cost (another_allocno, divisor * COST_HOP_DIVISOR);
+ queue_update_cost (another_allocno, allocno, divisor * COST_HOP_DIVISOR);
}
}
@@ -1640,7 +1777,8 @@ assign_hard_reg (ira_allocno_t a, bool retry_p)
continue;
full_costs[j] -= conflict_costs[k];
}
- queue_update_cost (conflict_a, COST_HOP_DIVISOR);
+ queue_update_cost (conflict_a, NULL, COST_HOP_DIVISOR);
+
}
}
}
@@ -1654,7 +1792,7 @@ assign_hard_reg (ira_allocno_t a, bool retry_p)
if (! retry_p)
{
start_update_cost ();
- queue_update_cost (a, COST_HOP_DIVISOR);
+ queue_update_cost (a, NULL, COST_HOP_DIVISOR);
update_conflict_hard_regno_costs (full_costs, aclass, false);
}
min_cost = min_full_cost = INT_MAX;
@@ -1711,10 +1849,12 @@ assign_hard_reg (ira_allocno_t a, bool retry_p)
for (i = hard_regno_nregs[best_hard_regno][mode] - 1; i >= 0; i--)
allocated_hardreg_p[best_hard_regno + i] = true;
}
+ if (! retry_p)
+ restore_costs_from_copies (a);
ALLOCNO_HARD_REGNO (a) = best_hard_regno;
ALLOCNO_ASSIGNED_P (a) = true;
if (best_hard_regno >= 0)
- update_copy_costs (a, true);
+ update_costs_from_copies (a, true, ! retry_p);
ira_assert (ALLOCNO_CLASS (a) == aclass);
/* We don't need updated costs anymore: */
ira_free_allocno_updated_costs (a);
@@ -2164,7 +2304,9 @@ pop_allocnos_from_stack (void)
else if (ALLOCNO_ASSIGNED_P (allocno))
{
if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
- fprintf (ira_dump_file, "spill\n");
+ fprintf (ira_dump_file, "spill%s\n",
+ ALLOCNO_COLOR_DATA (allocno)->may_be_spilled_p
+ ? "" : "!");
}
ALLOCNO_COLOR_DATA (allocno)->in_graph_p = true;
}
@@ -2546,6 +2688,32 @@ color_allocnos (void)
ira_allocno_t a;
setup_profitable_hard_regs ();
+ EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi)
+ {
+ int l, nr;
+ HARD_REG_SET conflict_hard_regs;
+ allocno_color_data_t data;
+ ira_pref_t pref, next_pref;
+
+ a = ira_allocnos[i];
+ nr = ALLOCNO_NUM_OBJECTS (a);
+ CLEAR_HARD_REG_SET (conflict_hard_regs);
+ for (l = 0; l < nr; l++)
+ {
+ ira_object_t obj = ALLOCNO_OBJECT (a, l);
+ IOR_HARD_REG_SET (conflict_hard_regs,
+ OBJECT_CONFLICT_HARD_REGS (obj));
+ }
+ data = ALLOCNO_COLOR_DATA (a);
+ for (pref = ALLOCNO_PREFS (a); pref != NULL; pref = next_pref)
+ {
+ next_pref = pref->next_pref;
+ if (! ira_hard_reg_in_set_p (pref->hard_regno,
+ ALLOCNO_MODE (a),
+ data->profitable_hard_regs))
+ ira_remove_pref (pref);
+ }
+ }
if (flag_ira_algorithm == IRA_ALGORITHM_PRIORITY)
{
n = 0;
@@ -2605,7 +2773,10 @@ color_allocnos (void)
{
a = ira_allocnos[i];
if (ALLOCNO_CLASS (a) != NO_REGS && ! empty_profitable_hard_regs (a))
- ALLOCNO_COLOR_DATA (a)->in_graph_p = true;
+ {
+ ALLOCNO_COLOR_DATA (a)->in_graph_p = true;
+ update_costs_from_prefs (a);
+ }
else
{
ALLOCNO_HARD_REGNO (a) = -1;
@@ -2772,7 +2943,7 @@ color_pass (ira_loop_tree_node_t loop_tree_node)
ALLOCNO_HARD_REGNO (subloop_allocno) = hard_regno;
ALLOCNO_ASSIGNED_P (subloop_allocno) = true;
if (hard_regno >= 0)
- update_copy_costs (subloop_allocno, true);
+ update_costs_from_copies (subloop_allocno, true, true);
/* We don't need updated costs anymore: */
ira_free_allocno_updated_costs (subloop_allocno);
}
@@ -2816,7 +2987,7 @@ color_pass (ira_loop_tree_node_t loop_tree_node)
ALLOCNO_HARD_REGNO (subloop_allocno) = hard_regno;
ALLOCNO_ASSIGNED_P (subloop_allocno) = true;
if (hard_regno >= 0)
- update_copy_costs (subloop_allocno, true);
+ update_costs_from_copies (subloop_allocno, true, true);
/* We don't need updated costs anymore: */
ira_free_allocno_updated_costs (subloop_allocno);
}
@@ -2832,7 +3003,7 @@ color_pass (ira_loop_tree_node_t loop_tree_node)
ALLOCNO_HARD_REGNO (subloop_allocno) = hard_regno;
ALLOCNO_ASSIGNED_P (subloop_allocno) = true;
if (hard_regno >= 0)
- update_copy_costs (subloop_allocno, true);
+ update_costs_from_copies (subloop_allocno, true, true);
/* We don't need updated costs anymore: */
ira_free_allocno_updated_costs (subloop_allocno);
}
@@ -3813,7 +3984,7 @@ ira_mark_allocation_change (int regno)
? ALLOCNO_CLASS_COST (a)
: ALLOCNO_HARD_REG_COSTS (a)
[ira_class_hard_reg_index[aclass][old_hard_regno]]);
- update_copy_costs (a, false);
+ update_costs_from_copies (a, false, false);
}
ira_overall_cost -= cost;
ALLOCNO_HARD_REGNO (a) = hard_regno;
@@ -3828,7 +3999,7 @@ ira_mark_allocation_change (int regno)
? ALLOCNO_CLASS_COST (a)
: ALLOCNO_HARD_REG_COSTS (a)
[ira_class_hard_reg_index[aclass][hard_regno]]);
- update_copy_costs (a, true);
+ update_costs_from_copies (a, true, false);
}
else
/* Reload changed class of the allocno. */
diff --git a/gcc/ira-conflicts.c b/gcc/ira-conflicts.c
index 710986b073e..ba0e4e5fad3 100644
--- a/gcc/ira-conflicts.c
+++ b/gcc/ira-conflicts.c
@@ -208,149 +208,6 @@ allocnos_conflict_for_copy_p (ira_allocno_t a1, ira_allocno_t a2)
return OBJECTS_CONFLICT_P (obj1, obj2);
}
-/* Return TRUE if the operand constraint STR is commutative. */
-static bool
-commutative_constraint_p (const char *str)
-{
- int curr_alt, c;
- bool ignore_p;
-
- for (ignore_p = false, curr_alt = 0;;)
- {
- c = *str;
- if (c == '\0')
- break;
- str += CONSTRAINT_LEN (c, str);
- if (c == '#' || !recog_data.alternative_enabled_p[curr_alt])
- ignore_p = true;
- else if (c == ',')
- {
- curr_alt++;
- ignore_p = false;
- }
- else if (! ignore_p)
- {
- /* Usually `%' is the first constraint character but the
- documentation does not require this. */
- if (c == '%')
- return true;
- }
- }
- return false;
-}
-
-/* Return the number of the operand which should be the same in any
- case as operand with number OP_NUM (or negative value if there is
- no such operand). If USE_COMMUT_OP_P is TRUE, the function makes
- temporarily commutative operand exchange before this. The function
- takes only really possible alternatives into consideration. */
-static int
-get_dup_num (int op_num, bool use_commut_op_p)
-{
- int curr_alt, c, original, dup;
- bool ignore_p, commut_op_used_p;
- const char *str;
- rtx op;
-
- if (op_num < 0 || recog_data.n_alternatives == 0)
- return -1;
- op = recog_data.operand[op_num];
- commut_op_used_p = true;
- if (use_commut_op_p)
- {
- if (commutative_constraint_p (recog_data.constraints[op_num]))
- op_num++;
- else if (op_num > 0 && commutative_constraint_p (recog_data.constraints
- [op_num - 1]))
- op_num--;
- else
- commut_op_used_p = false;
- }
- str = recog_data.constraints[op_num];
- for (ignore_p = false, original = -1, curr_alt = 0;;)
- {
- c = *str;
- if (c == '\0')
- break;
- if (c == '#' || !recog_data.alternative_enabled_p[curr_alt])
- ignore_p = true;
- else if (c == ',')
- {
- curr_alt++;
- ignore_p = false;
- }
- else if (! ignore_p)
- switch (c)
- {
- case 'X':
- return -1;
-
- case 'm':
- case 'o':
- /* Accept a register which might be placed in memory. */
- return -1;
- break;
-
- case 'V':
- case '<':
- case '>':
- break;
-
- case 'p':
- if (address_operand (op, VOIDmode))
- return -1;
- break;
-
- case 'g':
- return -1;
-
- case 'r':
- case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
- case 'h': case 'j': case 'k': case 'l':
- case 'q': case 't': case 'u':
- case 'v': case 'w': case 'x': case 'y': case 'z':
- case 'A': case 'B': case 'C': case 'D':
- case 'Q': case 'R': case 'S': case 'T': case 'U':
- case 'W': case 'Y': case 'Z':
- {
- enum reg_class cl;
-
- cl = (c == 'r'
- ? GENERAL_REGS : REG_CLASS_FROM_CONSTRAINT (c, str));
- if (cl != NO_REGS)
- return -1;
-#ifdef EXTRA_CONSTRAINT_STR
- else if (EXTRA_CONSTRAINT_STR (op, c, str))
- return -1;
-#endif
- break;
- }
-
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- if (original != -1 && original != c)
- return -1;
- original = c;
- break;
- }
- str += CONSTRAINT_LEN (c, str);
- }
- if (original == -1)
- return -1;
- dup = original - '0';
- if (use_commut_op_p)
- {
- if (commutative_constraint_p (recog_data.constraints[dup]))
- dup++;
- else if (dup > 0
- && commutative_constraint_p (recog_data.constraints[dup -1]))
- dup--;
- else if (! commut_op_used_p)
- return -1;
- }
- return dup;
-}
-
/* Check that X is REG or SUBREG of REG. */
#define REG_SUBREG_P(x) \
(REG_P (x) || (GET_CODE (x) == SUBREG && REG_P (SUBREG_REG (x))))
@@ -461,6 +318,7 @@ process_regs_for_copy (rtx reg1, rtx reg2, bool constraint_p,
ALLOCNO_CONFLICT_HARD_REG_COSTS (a)[index] -= cost;
if (ALLOCNO_HARD_REG_COSTS (a)[index] < ALLOCNO_CLASS_COST (a))
ALLOCNO_CLASS_COST (a) = ALLOCNO_HARD_REG_COSTS (a)[index];
+ ira_add_allocno_pref (a, allocno_preferenced_hard_regno, freq);
a = ira_parent_or_cap_allocno (a);
}
while (a != NULL);
@@ -498,9 +356,9 @@ static void
add_insn_allocno_copies (rtx insn)
{
rtx set, operand, dup;
- const char *str;
- bool commut_p, bound_p[MAX_RECOG_OPERANDS];
- int i, j, n, freq;
+ bool bound_p[MAX_RECOG_OPERANDS];
+ int i, n, freq;
+ HARD_REG_SET alts;
freq = REG_FREQ_FROM_BB (BLOCK_FOR_INSN (insn));
if (freq == 0)
@@ -513,7 +371,7 @@ add_insn_allocno_copies (rtx insn)
? SET_SRC (set)
: SUBREG_REG (SET_SRC (set))) != NULL_RTX)
{
- process_regs_for_copy (SET_DEST (set), SET_SRC (set),
+ process_regs_for_copy (SET_SRC (set), SET_DEST (set),
false, insn, freq);
return;
}
@@ -521,7 +379,7 @@ add_insn_allocno_copies (rtx insn)
there are no dead registers, there will be no such copies. */
if (! find_reg_note (insn, REG_DEAD, NULL_RTX))
return;
- extract_insn (insn);
+ ira_setup_alts (insn, alts);
for (i = 0; i < recog_data.n_operands; i++)
bound_p[i] = false;
for (i = 0; i < recog_data.n_operands; i++)
@@ -529,21 +387,18 @@ add_insn_allocno_copies (rtx insn)
operand = recog_data.operand[i];
if (! REG_SUBREG_P (operand))
continue;
- str = recog_data.constraints[i];
- while (*str == ' ' || *str == '\t')
- str++;
- for (j = 0, commut_p = false; j < 2; j++, commut_p = true)
- if ((n = get_dup_num (i, commut_p)) >= 0)
- {
- bound_p[n] = true;
- dup = recog_data.operand[n];
- if (REG_SUBREG_P (dup)
- && find_reg_note (insn, REG_DEAD,
- REG_P (operand)
- ? operand
- : SUBREG_REG (operand)) != NULL_RTX)
- process_regs_for_copy (operand, dup, true, NULL_RTX, freq);
- }
+ if ((n = ira_get_dup_out_num (i, alts)) >= 0)
+ {
+ bound_p[n] = true;
+ dup = recog_data.operand[n];
+ if (REG_SUBREG_P (dup)
+ && find_reg_note (insn, REG_DEAD,
+ REG_P (operand)
+ ? operand
+ : SUBREG_REG (operand)) != NULL_RTX)
+ process_regs_for_copy (operand, dup, true, NULL_RTX,
+ freq);
+ }
}
for (i = 0; i < recog_data.n_operands; i++)
{
diff --git a/gcc/ira-costs.c b/gcc/ira-costs.c
index 5f998f7aefb..424b99c2c53 100644
--- a/gcc/ira-costs.c
+++ b/gcc/ira-costs.c
@@ -405,7 +405,6 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
{
int alt;
int i, j, k;
- rtx set;
int insn_allows_mem[MAX_RECOG_OPERANDS];
for (i = 0; i < n_ops; i++)
@@ -914,60 +913,6 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
ALLOCNO_BAD_SPILL_P (a) = true;
}
- /* If this insn is a single set copying operand 1 to operand 0 and
- one operand is an allocno with the other a hard reg or an allocno
- that prefers a hard register that is in its own register class
- then we may want to adjust the cost of that register class to -1.
-
- Avoid the adjustment if the source does not die to avoid
- stressing of register allocator by preferrencing two colliding
- registers into single class.
-
- Also avoid the adjustment if a copy between hard registers of the
- class is expensive (ten times the cost of a default copy is
- considered arbitrarily expensive). This avoids losing when the
- preferred class is very expensive as the source of a copy
- instruction. */
- if ((set = single_set (insn)) != 0
- && ops[0] == SET_DEST (set) && ops[1] == SET_SRC (set)
- && REG_P (ops[0]) && REG_P (ops[1])
- && find_regno_note (insn, REG_DEAD, REGNO (ops[1])))
- for (i = 0; i <= 1; i++)
- if (REGNO (ops[i]) >= FIRST_PSEUDO_REGISTER
- && REGNO (ops[!i]) < FIRST_PSEUDO_REGISTER)
- {
- unsigned int regno = REGNO (ops[i]);
- unsigned int other_regno = REGNO (ops[!i]);
- enum machine_mode mode = GET_MODE (ops[!i]);
- cost_classes_t cost_classes_ptr = regno_cost_classes[regno];
- enum reg_class *cost_classes = cost_classes_ptr->classes;
- reg_class_t rclass;
- int nr;
-
- for (k = cost_classes_ptr->num - 1; k >= 0; k--)
- {
- rclass = cost_classes[k];
- if (TEST_HARD_REG_BIT (reg_class_contents[rclass], other_regno)
- && (reg_class_size[(int) rclass]
- == ira_reg_class_max_nregs [(int) rclass][(int) mode]))
- {
- if (reg_class_size[rclass] == 1)
- op_costs[i]->cost[k] = -frequency;
- else
- {
- for (nr = 0;
- nr < hard_regno_nregs[other_regno][mode];
- nr++)
- if (! TEST_HARD_REG_BIT (reg_class_contents[rclass],
- other_regno + nr))
- break;
-
- if (nr == hard_regno_nregs[other_regno][mode])
- op_costs[i]->cost[k] = -frequency;
- }
- }
- }
- }
}
@@ -1204,6 +1149,8 @@ record_operand_costs (rtx insn, enum reg_class *pref)
{
const char *constraints[MAX_RECOG_OPERANDS];
enum machine_mode modes[MAX_RECOG_OPERANDS];
+ rtx ops[MAX_RECOG_OPERANDS];
+ rtx set;
int i;
for (i = 0; i < recog_data.n_operands; i++)
@@ -1221,6 +1168,7 @@ record_operand_costs (rtx insn, enum reg_class *pref)
{
memcpy (op_costs[i], init_cost, struct_costs_size);
+ ops[i] = recog_data.operand[i];
if (GET_CODE (recog_data.operand[i]) == SUBREG)
recog_data.operand[i] = SUBREG_REG (recog_data.operand[i]);
@@ -1260,6 +1208,77 @@ record_operand_costs (rtx insn, enum reg_class *pref)
record_reg_classes (recog_data.n_alternatives, recog_data.n_operands,
recog_data.operand, modes,
constraints, insn, pref);
+
+ /* If this insn is a single set copying operand 1 to operand 0 and
+ one operand is an allocno with the other a hard reg or an allocno
+ that prefers a hard register that is in its own register class
+ then we may want to adjust the cost of that register class to -1.
+
+ Avoid the adjustment if the source does not die to avoid
+ stressing of register allocator by preferrencing two colliding
+ registers into single class.
+
+ Also avoid the adjustment if a copy between hard registers of the
+ class is expensive (ten times the cost of a default copy is
+ considered arbitrarily expensive). This avoids losing when the
+ preferred class is very expensive as the source of a copy
+ instruction. */
+ if ((set = single_set (insn)) != NULL_RTX
+ && ops[0] == SET_DEST (set) && ops[1] == SET_SRC (set))
+ {
+ int regno, other_regno;
+ rtx dest = SET_DEST (set);
+ rtx src = SET_SRC (set);
+
+ dest = SET_DEST (set);
+ src = SET_SRC (set);
+ if (GET_CODE (dest) == SUBREG
+ && (GET_MODE_SIZE (GET_MODE (dest))
+ == GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest)))))
+ dest = SUBREG_REG (dest);
+ if (GET_CODE (src) == SUBREG
+ && (GET_MODE_SIZE (GET_MODE (src))
+ == GET_MODE_SIZE (GET_MODE (SUBREG_REG (src)))))
+ src = SUBREG_REG (src);
+ if (REG_P (src) && REG_P (dest)
+ && find_regno_note (insn, REG_DEAD, REGNO (src))
+ && (((regno = REGNO (src)) >= FIRST_PSEUDO_REGISTER
+ && (other_regno = REGNO (dest)) < FIRST_PSEUDO_REGISTER)
+ || ((regno = REGNO (dest)) >= FIRST_PSEUDO_REGISTER
+ && (other_regno = REGNO (src)) < FIRST_PSEUDO_REGISTER)))
+ {
+ enum machine_mode mode = GET_MODE (src);
+ cost_classes_t cost_classes_ptr = regno_cost_classes[regno];
+ enum reg_class *cost_classes = cost_classes_ptr->classes;
+ reg_class_t rclass;
+ int k, nr;
+
+ i = regno == (int) REGNO (src) ? 1 : 0;
+ for (k = cost_classes_ptr->num - 1; k >= 0; k--)
+ {
+ rclass = cost_classes[k];
+ if (TEST_HARD_REG_BIT (reg_class_contents[rclass], other_regno)
+ && (reg_class_size[(int) rclass]
+ == ira_reg_class_max_nregs [(int) rclass][(int) mode]))
+ {
+ if (reg_class_size[rclass] == 1)
+ op_costs[i]->cost[k] = -frequency;
+ else
+ {
+ for (nr = 0;
+ nr < hard_regno_nregs[other_regno][mode];
+ nr++)
+ if (! TEST_HARD_REG_BIT (reg_class_contents[rclass],
+ other_regno + nr))
+ break;
+
+ if (nr == hard_regno_nregs[other_regno][mode])
+ op_costs[i]->cost[k] = -frequency;
+ }
+ }
+ }
+ }
+ }
}
@@ -1741,14 +1760,15 @@ find_costs_and_classes (FILE *dump_file)
a != NULL;
a = ALLOCNO_NEXT_REGNO_ALLOCNO (a))
{
- a_num = ALLOCNO_NUM (a);
- if (regno_aclass[i] == NO_REGS)
+ enum reg_class aclass = regno_aclass[i];
+ int a_num = ALLOCNO_NUM (a);
+ int *total_a_costs = COSTS (total_allocno_costs, a_num)->cost;
+ int *a_costs = COSTS (costs, a_num)->cost;
+
+ if (aclass == NO_REGS)
best = NO_REGS;
else
{
- int *total_a_costs = COSTS (total_allocno_costs, a_num)->cost;
- int *a_costs = COSTS (costs, a_num)->cost;
-
/* Finding best class which is subset of the common
class. */
best_cost = (1 << (HOST_BITS_PER_INT - 2)) - 1;
@@ -1757,7 +1777,7 @@ find_costs_and_classes (FILE *dump_file)
for (k = 0; k < cost_classes_ptr->num; k++)
{
rclass = cost_classes[k];
- if (! ira_class_subset_p[rclass][regno_aclass[i]])
+ if (! ira_class_subset_p[rclass][aclass])
continue;
/* Ignore classes that are too small or invalid
for this operand. */
@@ -1792,9 +1812,25 @@ find_costs_and_classes (FILE *dump_file)
ALLOCNO_LOOP_TREE_NODE (a)->loop_num);
fprintf (dump_file, ") best %s, allocno %s\n",
reg_class_names[best],
- reg_class_names[regno_aclass[i]]);
+ reg_class_names[aclass]);
}
pref[a_num] = best;
+ if (pass == flag_expensive_optimizations && best != aclass
+ && ira_class_hard_regs_num[best] > 0
+ && (ira_reg_class_max_nregs[best][ALLOCNO_MODE (a)]
+ >= ira_class_hard_regs_num[best]))
+ {
+ int ind = cost_classes_ptr->index[aclass];
+
+ ira_assert (ind >= 0);
+ ira_add_allocno_pref (a, ira_class_hard_regs[best][0],
+ (a_costs[ind] - ALLOCNO_CLASS_COST (a))
+ / (ira_register_move_cost
+ [ALLOCNO_MODE (a)][best][aclass]));
+ for (k = 0; k < cost_classes_ptr->num; k++)
+ if (ira_class_subset_p[cost_classes[k]][best])
+ a_costs[k] = a_costs[ind];
+ }
}
}
@@ -1820,11 +1856,11 @@ find_costs_and_classes (FILE *dump_file)
static void
process_bb_node_for_hard_reg_moves (ira_loop_tree_node_t loop_tree_node)
{
- int i, freq, cost, src_regno, dst_regno, hard_regno;
+ int i, freq, src_regno, dst_regno, hard_regno, a_regno;
bool to_p;
- ira_allocno_t a;
- enum reg_class rclass, hard_reg_class;
- enum machine_mode mode;
+ ira_allocno_t a, curr_a;
+ ira_loop_tree_node_t curr_loop_tree_node;
+ enum reg_class rclass;
basic_block bb;
rtx insn, set, src, dst;
@@ -1851,15 +1887,15 @@ process_bb_node_for_hard_reg_moves (ira_loop_tree_node_t loop_tree_node)
&& src_regno < FIRST_PSEUDO_REGISTER)
{
hard_regno = src_regno;
- to_p = true;
a = ira_curr_regno_allocno_map[dst_regno];
+ to_p = true;
}
else if (src_regno >= FIRST_PSEUDO_REGISTER
&& dst_regno < FIRST_PSEUDO_REGISTER)
{
hard_regno = dst_regno;
- to_p = false;
a = ira_curr_regno_allocno_map[src_regno];
+ to_p = false;
}
else
continue;
@@ -1869,20 +1905,31 @@ process_bb_node_for_hard_reg_moves (ira_loop_tree_node_t loop_tree_node)
i = ira_class_hard_reg_index[rclass][hard_regno];
if (i < 0)
continue;
- mode = ALLOCNO_MODE (a);
- hard_reg_class = REGNO_REG_CLASS (hard_regno);
- ira_init_register_move_cost_if_necessary (mode);
- cost
- = (to_p ? ira_register_move_cost[mode][hard_reg_class][rclass]
- : ira_register_move_cost[mode][rclass][hard_reg_class]) * freq;
- ira_allocate_and_set_costs (&ALLOCNO_HARD_REG_COSTS (a), rclass,
- ALLOCNO_CLASS_COST (a));
- ira_allocate_and_set_costs (&ALLOCNO_CONFLICT_HARD_REG_COSTS (a),
- rclass, 0);
- ALLOCNO_HARD_REG_COSTS (a)[i] -= cost;
- ALLOCNO_CONFLICT_HARD_REG_COSTS (a)[i] -= cost;
- ALLOCNO_CLASS_COST (a) = MIN (ALLOCNO_CLASS_COST (a),
- ALLOCNO_HARD_REG_COSTS (a)[i]);
+ a_regno = ALLOCNO_REGNO (a);
+ for (curr_loop_tree_node = ALLOCNO_LOOP_TREE_NODE (a);
+ curr_loop_tree_node != NULL;
+ curr_loop_tree_node = curr_loop_tree_node->parent)
+ if ((curr_a = curr_loop_tree_node->regno_allocno_map[a_regno]) != NULL)
+ ira_add_allocno_pref (curr_a, hard_regno, freq);
+ {
+ int cost;
+ enum reg_class hard_reg_class;
+ enum machine_mode mode;
+
+ mode = ALLOCNO_MODE (a);
+ hard_reg_class = REGNO_REG_CLASS (hard_regno);
+ ira_init_register_move_cost_if_necessary (mode);
+ cost = (to_p ? ira_register_move_cost[mode][hard_reg_class][rclass]
+ : ira_register_move_cost[mode][rclass][hard_reg_class]) * freq;
+ ira_allocate_and_set_costs (&ALLOCNO_HARD_REG_COSTS (a), rclass,
+ ALLOCNO_CLASS_COST (a));
+ ira_allocate_and_set_costs (&ALLOCNO_CONFLICT_HARD_REG_COSTS (a),
+ rclass, 0);
+ ALLOCNO_HARD_REG_COSTS (a)[i] -= cost;
+ ALLOCNO_CONFLICT_HARD_REG_COSTS (a)[i] -= cost;
+ ALLOCNO_CLASS_COST (a) = MIN (ALLOCNO_CLASS_COST (a),
+ ALLOCNO_HARD_REG_COSTS (a)[i]);
+ }
}
}
diff --git a/gcc/ira-int.h b/gcc/ira-int.h
index 519f656f652..b9b21ba27af 100644
--- a/gcc/ira-int.h
+++ b/gcc/ira-int.h
@@ -57,6 +57,7 @@ extern FILE *ira_dump_file;
allocnos. */
typedef struct live_range *live_range_t;
typedef struct ira_allocno *ira_allocno_t;
+typedef struct ira_allocno_pref *ira_pref_t;
typedef struct ira_allocno_copy *ira_copy_t;
typedef struct ira_object *ira_object_t;
@@ -346,6 +347,8 @@ struct ira_allocno
register class living at the point than number of hard-registers
of the class available for the allocation. */
int excess_pressure_points_num;
+ /* Allocno hard reg preferences. */
+ ira_pref_t allocno_prefs;
/* Copies to other non-conflicting allocnos. The copies can
represent move insn or potential move insn usually because of two
operand insn constraints. */
@@ -426,6 +429,7 @@ struct ira_allocno
#define ALLOCNO_BAD_SPILL_P(A) ((A)->bad_spill_p)
#define ALLOCNO_ASSIGNED_P(A) ((A)->assigned_p)
#define ALLOCNO_MODE(A) ((A)->mode)
+#define ALLOCNO_PREFS(A) ((A)->allocno_prefs)
#define ALLOCNO_COPIES(A) ((A)->allocno_copies)
#define ALLOCNO_HARD_REG_COSTS(A) ((A)->hard_reg_costs)
#define ALLOCNO_UPDATED_HARD_REG_COSTS(A) ((A)->updated_hard_reg_costs)
@@ -516,6 +520,33 @@ extern ira_object_t *ira_object_id_map;
/* The size of the previous array. */
extern int ira_objects_num;
+/* The following structure represents a hard register prefererence of
+ allocno. The preference represent move insns or potential move
+ insns usually because of two operand insn constraints. One move
+ operand is a hard register. */
+struct ira_allocno_pref
+{
+ /* The unique order number of the preference node starting with 0. */
+ int num;
+ /* Preferred hard register. */
+ int hard_regno;
+ /* Accumulated execution frequency of insns from which the
+ preference created. */
+ int freq;
+ /* Given allocno. */
+ ira_allocno_t allocno;
+ /* All prefernces with the same allocno are linked by the following
+ member. */
+ ira_pref_t next_pref;
+};
+
+/* Array of references to all allocno preferences. The order number
+ of the preference corresponds to the index in the array. */
+extern ira_pref_t *ira_prefs;
+
+/* Size of the previous array. */
+extern int ira_prefs_num;
+
/* The following structure represents a copy of two allocnos. The
copies represent move insns or potential move insns usually because
of two operand insn constraints. To remove register shuffle, we
@@ -925,6 +956,8 @@ extern void ira_print_disposition (FILE *);
extern void ira_debug_disposition (void);
extern void ira_debug_allocno_classes (void);
extern void ira_init_register_move_cost (enum machine_mode);
+extern void ira_setup_alts (rtx insn, HARD_REG_SET &alts);
+extern int ira_get_dup_out_num (int op_num, HARD_REG_SET &alts);
/* ira-build.c */
@@ -932,6 +965,10 @@ extern void ira_init_register_move_cost (enum machine_mode);
extern ira_loop_tree_node_t ira_curr_loop_tree_node;
extern ira_allocno_t *ira_curr_regno_allocno_map;
+extern void ira_debug_pref (ira_pref_t);
+extern void ira_debug_prefs (void);
+extern void ira_debug_allocno_prefs (ira_allocno_t);
+
extern void ira_debug_copy (ira_copy_t);
extern void debug (ira_allocno_copy &ref);
extern void debug (ira_allocno_copy *ptr);
@@ -963,10 +1000,12 @@ extern bool ira_live_ranges_intersect_p (live_range_t, live_range_t);
extern void ira_finish_live_range (live_range_t);
extern void ira_finish_live_range_list (live_range_t);
extern void ira_free_allocno_updated_costs (ira_allocno_t);
+extern ira_pref_t ira_create_pref (ira_allocno_t, int, int);
+extern void ira_add_allocno_pref (ira_allocno_t, int, int);
+extern void ira_remove_pref (ira_pref_t);
+extern void ira_remove_allocno_prefs (ira_allocno_t);
extern ira_copy_t ira_create_copy (ira_allocno_t, ira_allocno_t,
int, bool, rtx, ira_loop_tree_node_t);
-extern void ira_add_allocno_copy_to_list (ira_copy_t);
-extern void ira_swap_allocno_copy_ends_if_necessary (ira_copy_t);
extern ira_copy_t ira_add_allocno_copy (ira_allocno_t, ira_allocno_t, int,
bool, rtx, ira_loop_tree_node_t);
@@ -1151,6 +1190,44 @@ ira_allocno_object_iter_cond (ira_allocno_object_iterator *i, ira_allocno_t a,
ira_allocno_object_iter_cond (&(ITER), (A), &(O));)
+/* The iterator for prefs. */
+typedef struct {
+ /* The number of the current element in IRA_PREFS. */
+ int n;
+} ira_pref_iterator;
+
+/* Initialize the iterator I. */
+static inline void
+ira_pref_iter_init (ira_pref_iterator *i)
+{
+ i->n = 0;
+}
+
+/* Return TRUE if we have more prefs to visit, in which case *PREF is
+ set to the pref to be visited. Otherwise, return FALSE. */
+static inline bool
+ira_pref_iter_cond (ira_pref_iterator *i, ira_pref_t *pref)
+{
+ int n;
+
+ for (n = i->n; n < ira_prefs_num; n++)
+ if (ira_prefs[n] != NULL)
+ {
+ *pref = ira_prefs[n];
+ i->n = n + 1;
+ return true;
+ }
+ return false;
+}
+
+/* Loop over all prefs. In each iteration, P is set to the next
+ pref. ITER is an instance of ira_pref_iterator used to iterate
+ the prefs. */
+#define FOR_EACH_PREF(P, ITER) \
+ for (ira_pref_iter_init (&(ITER)); \
+ ira_pref_iter_cond (&(ITER), &(P));)
+
+
/* The iterator for copies. */
typedef struct {
/* The number of the current element in IRA_COPIES. */
diff --git a/gcc/ira.c b/gcc/ira.c
index 44fa0bc2835..10e71d97db3 100644
--- a/gcc/ira.c
+++ b/gcc/ira.c
@@ -361,6 +361,7 @@ along with GCC; see the file COPYING3. If not see
#include "coretypes.h"
#include "tm.h"
#include "regs.h"
+#include "tree.h"
#include "rtl.h"
#include "tm_p.h"
#include "target.h"
@@ -1760,6 +1761,527 @@ setup_prohibited_mode_move_regs (void)
+/* Return TRUE if the operand constraint STR is commutative. */
+static bool
+commutative_constraint_p (const char *str)
+{
+ int curr_alt, c;
+ bool ignore_p;
+
+ for (ignore_p = false, curr_alt = 0;;)
+ {
+ c = *str;
+ if (c == '\0')
+ break;
+ str += CONSTRAINT_LEN (c, str);
+ if (c == '#' || !recog_data.alternative_enabled_p[curr_alt])
+ ignore_p = true;
+ else if (c == ',')
+ {
+ curr_alt++;
+ ignore_p = false;
+ }
+ else if (! ignore_p)
+ {
+ /* Usually `%' is the first constraint character but the
+ documentation does not require this. */
+ if (c == '%')
+ return true;
+ }
+ }
+ return false;
+}
+
+/* Setup possible alternatives in ALTS for INSN. */
+void
+ira_setup_alts (rtx insn, HARD_REG_SET &alts)
+{
+ /* MAP nalt * nop -> start of constraints for given operand and
+ alternative */
+ static vec<const char *> insn_constraints;
+ int nop, nalt;
+ bool curr_swapped;
+ const char *p;
+ rtx op;
+ int commutative = -1;
+
+ extract_insn (insn);
+ CLEAR_HARD_REG_SET (alts);
+ insn_constraints.release ();
+ insn_constraints.safe_grow_cleared (recog_data.n_operands
+ * recog_data.n_alternatives + 1);
+ /* Check that the hard reg set is enough for holding all
+ alternatives. It is hard to imagine the situation when the
+ assertion is wrong. */
+ ira_assert (recog_data.n_alternatives
+ <= (int) MAX (sizeof (HARD_REG_ELT_TYPE) * CHAR_BIT,
+ FIRST_PSEUDO_REGISTER));
+ for (curr_swapped = false;; curr_swapped = true)
+ {
+ /* Calculate some data common for all alternatives to speed up the
+ function. */
+ for (nop = 0; nop < recog_data.n_operands; nop++)
+ {
+ for (nalt = 0, p = recog_data.constraints[nop];
+ nalt < recog_data.n_alternatives;
+ nalt++)
+ {
+ insn_constraints[nop * recog_data.n_alternatives + nalt] = p;
+ while (*p && *p != ',')
+ p++;
+ if (*p)
+ p++;
+ }
+ }
+ for (nalt = 0; nalt < recog_data.n_alternatives; nalt++)
+ {
+ if (! recog_data.alternative_enabled_p[nalt] || TEST_HARD_REG_BIT (alts, nalt))
+ continue;
+
+ for (nop = 0; nop < recog_data.n_operands; nop++)
+ {
+ int c, len;
+
+ op = recog_data.operand[nop];
+ p = insn_constraints[nop * recog_data.n_alternatives + nalt];
+ if (*p == 0 || *p == ',')
+ continue;
+
+ do
+ switch (c = *p, len = CONSTRAINT_LEN (c, p), c)
+ {
+ case '#':
+ case ',':
+ c = '\0';
+ case '\0':
+ len = 0;
+ break;
+
+ case '?': case '!': case '*': case '=': case '+':
+ break;
+
+ case '%':
+ /* We only support one commutative marker, the
+ first one. We already set commutative
+ above. */
+ if (commutative < 0)
+ commutative = nop;
+ break;
+
+ case '&':
+ break;
+
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ goto op_success;
+ break;
+
+ case 'p':
+ case 'g':
+ case 'X':
+ case TARGET_MEM_CONSTRAINT:
+ goto op_success;
+ break;
+
+ case '<':
+ if (MEM_P (op)
+ && (GET_CODE (XEXP (op, 0)) == PRE_DEC
+ || GET_CODE (XEXP (op, 0)) == POST_DEC))
+ goto op_success;
+ break;
+
+ case '>':
+ if (MEM_P (op)
+ && (GET_CODE (XEXP (op, 0)) == PRE_INC
+ || GET_CODE (XEXP (op, 0)) == POST_INC))
+ goto op_success;
+ break;
+
+ case 'E':
+ case 'F':
+ if (CONST_DOUBLE_AS_FLOAT_P (op)
+ || (GET_CODE (op) == CONST_VECTOR
+ && GET_MODE_CLASS (GET_MODE (op)) == MODE_VECTOR_FLOAT))
+ goto op_success;
+ break;
+
+ case 'G':
+ case 'H':
+ if (CONST_DOUBLE_AS_FLOAT_P (op)
+ && CONST_DOUBLE_OK_FOR_CONSTRAINT_P (op, c, p))
+ goto op_success;
+ break;
+
+ case 's':
+ if (CONST_SCALAR_INT_P (op))
+ break;
+ case 'i':
+ if (CONSTANT_P (op))
+ goto op_success;
+ break;
+
+ case 'n':
+ if (CONST_SCALAR_INT_P (op))
+ goto op_success;
+ break;
+
+ case 'I':
+ case 'J':
+ case 'K':
+ case 'L':
+ case 'M':
+ case 'N':
+ case 'O':
+ case 'P':
+ if (CONST_INT_P (op)
+ && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), c, p))
+ goto op_success;
+ break;
+
+ case 'V':
+ if (MEM_P (op) && ! offsettable_memref_p (op))
+ goto op_success;
+ break;
+
+ case 'o':
+ goto op_success;
+ break;
+
+ default:
+ {
+ enum reg_class cl;
+
+ cl = (c == 'r' ? GENERAL_REGS : REG_CLASS_FROM_CONSTRAINT (c, p));
+ if (cl != NO_REGS)
+ goto op_success;
+#ifdef EXTRA_CONSTRAINT_STR
+ else if (EXTRA_CONSTRAINT_STR (op, c, p))
+ goto op_success;
+ else if (EXTRA_MEMORY_CONSTRAINT (c, p))
+ goto op_success;
+ else if (EXTRA_ADDRESS_CONSTRAINT (c, p))
+ goto op_success;
+#endif
+ break;
+ }
+ }
+ while (p += len, c);
+ break;
+ op_success:
+ ;
+ }
+ if (nop >= recog_data.n_operands)
+ SET_HARD_REG_BIT (alts, nalt);
+ }
+ if (commutative < 0)
+ break;
+ if (curr_swapped)
+ break;
+ op = recog_data.operand[commutative];
+ recog_data.operand[commutative] = recog_data.operand[commutative + 1];
+ recog_data.operand[commutative + 1] = op;
+
+ }
+}
+
+/* Return the number of the output non-early clobber operand which
+ should be the same in any case as operand with number OP_NUM (or
+ negative value if there is no such operand). The function takes
+ only really possible alternatives into consideration. */
+int
+ira_get_dup_out_num (int op_num, HARD_REG_SET &alts)
+{
+ int curr_alt, c, original, dup;
+ bool ignore_p, use_commut_op_p;
+ const char *str;
+#ifdef EXTRA_CONSTRAINT_STR
+ rtx op;
+#endif
+
+ if (op_num < 0 || recog_data.n_alternatives == 0)
+ return -1;
+ use_commut_op_p = false;
+ str = recog_data.constraints[op_num];
+ for (;;)
+ {
+#ifdef EXTRA_CONSTRAINT_STR
+ op = recog_data.operand[op_num];
+#endif
+
+ for (ignore_p = false, original = -1, curr_alt = 0;;)
+ {
+ c = *str;
+ if (c == '\0')
+ break;
+ if (c == '#' || !TEST_HARD_REG_BIT (alts, curr_alt))
+ ignore_p = true;
+ else if (c == ',')
+ {
+ curr_alt++;
+ ignore_p = false;
+ }
+ else if (! ignore_p)
+ switch (c)
+ {
+ /* We should find duplications only for input operands. */
+ case '=':
+ case '+':
+ goto fail;
+ case 'X':
+ case 'p':
+ case 'g':
+ goto fail;
+ case 'r':
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+ case 'h': case 'j': case 'k': case 'l':
+ case 'q': case 't': case 'u':
+ case 'v': case 'w': case 'x': case 'y': case 'z':
+ case 'A': case 'B': case 'C': case 'D':
+ case 'Q': case 'R': case 'S': case 'T': case 'U':
+ case 'W': case 'Y': case 'Z':
+ {
+ enum reg_class cl;
+
+ cl = (c == 'r'
+ ? GENERAL_REGS : REG_CLASS_FROM_CONSTRAINT (c, str));
+ if (cl != NO_REGS)
+ {
+ if (! targetm.class_likely_spilled_p (cl))
+ goto fail;
+ }
+#ifdef EXTRA_CONSTRAINT_STR
+ else if (EXTRA_CONSTRAINT_STR (op, c, str))
+ goto fail;
+#endif
+ break;
+ }
+
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ if (original != -1 && original != c)
+ goto fail;
+ original = c;
+ break;
+ }
+ str += CONSTRAINT_LEN (c, str);
+ }
+ if (original == -1)
+ goto fail;
+ dup = -1;
+ for (ignore_p = false, str = recog_data.constraints[original - '0'];
+ *str != 0;
+ str++)
+ if (ignore_p)
+ {
+ if (*str == ',')
+ ignore_p = false;
+ }
+ else if (*str == '#')
+ ignore_p = true;
+ else if (! ignore_p)
+ {
+ if (*str == '=')
+ dup = original - '0';
+ /* It is better ignore an alternative with early clobber. */
+ else if (*str == '&')
+ goto fail;
+ }
+ if (dup >= 0)
+ return dup;
+ fail:
+ if (use_commut_op_p)
+ break;
+ use_commut_op_p = true;
+ if (commutative_constraint_p (recog_data.constraints[op_num]))
+ str = recog_data.constraints[op_num + 1];
+ else if (op_num > 0 && commutative_constraint_p (recog_data.constraints
+ [op_num - 1]))
+ str = recog_data.constraints[op_num - 1];
+ else
+ break;
+ }
+ return -1;
+}
+
+
+
+/* Search forward to see if the source register of a copy insn dies
+ before either it or the destination register is modified, but don't
+ scan past the end of the basic block. If so, we can replace the
+ source with the destination and let the source die in the copy
+ insn.
+
+ This will reduce the number of registers live in that range and may
+ enable the destination and the source coalescing, thus often saving
+ one register in addition to a register-register copy. */
+
+static void
+decrease_live_ranges_number (void)
+{
+ basic_block bb;
+ rtx insn, set, src, dest, dest_death, p, q, note;
+ int sregno, dregno;
+
+ if (! flag_expensive_optimizations)
+ return;
+
+ if (ira_dump_file)
+ fprintf (ira_dump_file, "Starting decreasing number of live ranges...\n");
+
+ FOR_EACH_BB (bb)
+ FOR_BB_INSNS (bb, insn)
+ {
+ set = single_set (insn);
+ if (! set)
+ continue;
+ src = SET_SRC (set);
+ dest = SET_DEST (set);
+ if (! REG_P (src) || ! REG_P (dest)
+ || find_reg_note (insn, REG_DEAD, src))
+ continue;
+ sregno = REGNO (src);
+ dregno = REGNO (dest);
+
+ /* We don't want to mess with hard regs if register classes
+ are small. */
+ if (sregno == dregno
+ || (targetm.small_register_classes_for_mode_p (GET_MODE (src))
+ && (sregno < FIRST_PSEUDO_REGISTER
+ || dregno < FIRST_PSEUDO_REGISTER))
+ /* We don't see all updates to SP if they are in an
+ auto-inc memory reference, so we must disallow this
+ optimization on them. */
+ || sregno == STACK_POINTER_REGNUM
+ || dregno == STACK_POINTER_REGNUM)
+ continue;
+
+ dest_death = NULL_RTX;
+
+ for (p = NEXT_INSN (insn); p; p = NEXT_INSN (p))
+ {
+ if (! INSN_P (p))
+ continue;
+ if (BLOCK_FOR_INSN (p) != bb)
+ break;
+
+ if (reg_set_p (src, p) || reg_set_p (dest, p)
+ /* If SRC is an asm-declared register, it must not be
+ replaced in any asm. Unfortunately, the REG_EXPR
+ tree for the asm variable may be absent in the SRC
+ rtx, so we can't check the actual register
+ declaration easily (the asm operand will have it,
+ though). To avoid complicating the test for a rare
+ case, we just don't perform register replacement
+ for a hard reg mentioned in an asm. */
+ || (sregno < FIRST_PSEUDO_REGISTER
+ && asm_noperands (PATTERN (p)) >= 0
+ && reg_overlap_mentioned_p (src, PATTERN (p)))
+ /* Don't change hard registers used by a call. */
+ || (CALL_P (p) && sregno < FIRST_PSEUDO_REGISTER
+ && find_reg_fusage (p, USE, src))
+ /* Don't change a USE of a register. */
+ || (GET_CODE (PATTERN (p)) == USE
+ && reg_overlap_mentioned_p (src, XEXP (PATTERN (p), 0))))
+ break;
+
+ /* See if all of SRC dies in P. This test is slightly
+ more conservative than it needs to be. */
+ if ((note = find_regno_note (p, REG_DEAD, sregno))
+ && GET_MODE (XEXP (note, 0)) == GET_MODE (src))
+ {
+ int failed = 0;
+
+ /* We can do the optimization. Scan forward from INSN
+ again, replacing regs as we go. Set FAILED if a
+ replacement can't be done. In that case, we can't
+ move the death note for SRC. This should be
+ rare. */
+
+ /* Set to stop at next insn. */
+ for (q = next_real_insn (insn);
+ q != next_real_insn (p);
+ q = next_real_insn (q))
+ {
+ if (reg_overlap_mentioned_p (src, PATTERN (q)))
+ {
+ /* If SRC is a hard register, we might miss
+ some overlapping registers with
+ validate_replace_rtx, so we would have to
+ undo it. We can't if DEST is present in
+ the insn, so fail in that combination of
+ cases. */
+ if (sregno < FIRST_PSEUDO_REGISTER
+ && reg_mentioned_p (dest, PATTERN (q)))
+ failed = 1;
+
+ /* Attempt to replace all uses. */
+ else if (!validate_replace_rtx (src, dest, q))
+ failed = 1;
+
+ /* If this succeeded, but some part of the
+ register is still present, undo the
+ replacement. */
+ else if (sregno < FIRST_PSEUDO_REGISTER
+ && reg_overlap_mentioned_p (src, PATTERN (q)))
+ {
+ validate_replace_rtx (dest, src, q);
+ failed = 1;
+ }
+ }
+
+ /* If DEST dies here, remove the death note and
+ save it for later. Make sure ALL of DEST dies
+ here; again, this is overly conservative. */
+ if (! dest_death
+ && (dest_death = find_regno_note (q, REG_DEAD, dregno)))
+ {
+ if (GET_MODE (XEXP (dest_death, 0)) == GET_MODE (dest))
+ remove_note (q, dest_death);
+ else
+ {
+ failed = 1;
+ dest_death = 0;
+ }
+ }
+ }
+
+ if (! failed)
+ {
+ /* Move death note of SRC from P to INSN. */
+ remove_note (p, note);
+ XEXP (note, 1) = REG_NOTES (insn);
+ REG_NOTES (insn) = note;
+ }
+
+ /* DEST is also dead if INSN has a REG_UNUSED note for
+ DEST. */
+ if (! dest_death
+ && (dest_death
+ = find_regno_note (insn, REG_UNUSED, dregno)))
+ {
+ PUT_REG_NOTE_KIND (dest_death, REG_DEAD);
+ remove_note (insn, dest_death);
+ }
+
+ /* Put death note of DEST on P if we saw it die. */
+ if (dest_death)
+ {
+ XEXP (dest_death, 1) = REG_NOTES (p);
+ REG_NOTES (p) = dest_death;
+ }
+ break;
+ }
+
+ /* If SRC is a hard register which is set or killed in
+ some other way, we can't do this optimization. */
+ else if (sregno < FIRST_PSEUDO_REGISTER && dead_or_set_p (p, src))
+ break;
+ }
+ }
+}
+
+
+
/* Return nonzero if REGNO is a particularly bad choice for reloading X. */
static bool
ira_bad_reload_regno_1 (int regno, rtx x)
@@ -1873,6 +2395,9 @@ ira_setup_eliminable_regset (bool from_ira_p)
|| (flag_stack_check && STACK_CHECK_MOVING_SP)
|| crtl->accesses_prior_frames
|| crtl->stack_realign_needed
+ /* We need a frame pointer for all Cilk Plus functions that use
+ Cilk keywords. */
+ || (flag_enable_cilkplus && cfun->is_cilk_function)
|| targetm.frame_pointer_required ());
if (from_ira_p && ira_use_lra_p)
@@ -3269,11 +3794,12 @@ update_equiv_regs (void)
if (! reg_equiv[regno].replace
|| reg_equiv[regno].loop_depth < loop_depth
- /* There is no sense to move insns if we did
- register pressure-sensitive scheduling was
- done because it will not improve allocation
- but worsen insn schedule with a big
- probability. */
+ /* There is no sense to move insns if live range
+ shrinkage or register pressure-sensitive
+ scheduling were done because it will not
+ improve allocation but worsen insn schedule
+ with a big probability. */
+ || flag_live_range_shrinkage
|| (flag_sched_pressure && flag_schedule_insns))
continue;
@@ -3515,7 +4041,7 @@ setup_reg_equiv (void)
static void
print_insn_chain (FILE *file, struct insn_chain *c)
{
- fprintf (file, "insn=%d, ", INSN_UID(c->insn));
+ fprintf (file, "insn=%d, ", INSN_UID (c->insn));
bitmap_print (file, &c->live_throughout, "live_throughout: ", ", ");
bitmap_print (file, &c->dead_or_set, "dead_or_set: ", "\n");
}
@@ -4391,9 +4917,9 @@ allocate_initial_values (void)
/* Update global register liveness information. */
FOR_EACH_BB (bb)
{
- if (REGNO_REG_SET_P(df_get_live_in (bb), regno))
+ if (REGNO_REG_SET_P (df_get_live_in (bb), regno))
SET_REGNO_REG_SET (df_get_live_in (bb), new_regno);
- if (REGNO_REG_SET_P(df_get_live_out (bb), regno))
+ if (REGNO_REG_SET_P (df_get_live_out (bb), regno))
SET_REGNO_REG_SET (df_get_live_out (bb), new_regno);
}
}
@@ -4465,7 +4991,7 @@ ira (FILE *f)
}
setup_prohibited_mode_move_regs ();
-
+ decrease_live_ranges_number ();
df_note_add_problem ();
/* DF_LIVE can't be used in the register allocator, too many other
@@ -4481,6 +5007,7 @@ ira (FILE *f)
df->changeable_flags |= DF_VERIFY_SCHEDULED;
#endif
df_analyze ();
+
df_clear_flags (DF_NO_INSN_RESCAN);
regstat_init_n_sets_and_refs ();
regstat_compute_ri ();
@@ -4792,8 +5319,8 @@ const pass_data pass_data_ira =
class pass_ira : public rtl_opt_pass
{
public:
- pass_ira(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_ira, ctxt)
+ pass_ira (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_ira, ctxt)
{}
/* opt_pass methods: */
@@ -4836,8 +5363,8 @@ const pass_data pass_data_reload =
class pass_reload : public rtl_opt_pass
{
public:
- pass_reload(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_reload, ctxt)
+ pass_reload (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_reload, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/is-a.h b/gcc/is-a.h
index b5ee8543abe..c47d10f20f4 100644
--- a/gcc/is-a.h
+++ b/gcc/is-a.h
@@ -31,7 +31,7 @@ bool is_a <TYPE> (pointer)
Tests whether the pointer actually points to a more derived TYPE.
- Suppose you have a symtab_node_def *ptr, AKA symtab_node ptr. You can test
+ 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))
@@ -110,9 +110,9 @@ example,
template <>
template <>
inline bool
- is_a_helper <cgraph_node>::test (symtab_node_def *p)
+ is_a_helper <cgraph_node>::test (symtab_node *p)
{
- return p->symbol.type == SYMTAB_FUNCTION;
+ return p->type == SYMTAB_FUNCTION;
}
If a simple reinterpret_cast between the pointer types is incorrect, then you
@@ -122,7 +122,7 @@ when needed may result in a crash. For example,
template <>
template <>
inline bool
- is_a_helper <cgraph_node>::cast (symtab_node_def *p)
+ is_a_helper <cgraph_node>::cast (symtab_node *p)
{
return &p->x_function;
}
diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog
index 9cc34c51a5a..4cb9e461a40 100644
--- a/gcc/java/ChangeLog
+++ b/gcc/java/ChangeLog
@@ -1,3 +1,39 @@
+2013-11-07 Jeff Law <law@redhat.com>
+
+ * builtins.c (initialize_builtins): Provide __builtin_trap.
+
+2013-10-29 David Malcolm <dmalcolm@redhat.com>
+
+ Patch autogenerated by refactor_symtab.py from
+ https://github.com/davidmalcolm/gcc-refactoring-scripts
+ revision 58bb219cc090b2f4516a9297d868c245495ee622
+
+ * decl.c (java_mark_decl_local): Update for conversion of symtab types
+ to a true class hierarchy.
+
+2013-10-14 David Malcolm <dmalcolm@redhat.com>
+
+ * lang.c (java_handle_option): Update for introduction of
+ gcc::dump_manager.
+
+2013-09-25 Tom Tromey <tromey@redhat.com>
+
+ * Make-lang.in (jvspec.o): Remove.
+ (CFLAGS-java/jvspec.o): New variable.
+ ($(XGCJ)$(exeext), java_OBJS): Use java/jvspec.o
+ (java/jvspec.o-warn): Rename from jvspec.o-warn.
+ (JAVA_TREE_H, java/jcf-dump.o, java/boehm.o, java/builtins.o)
+ (java/class.o, java/constants.o, java/decl.o, java/except.o)
+ (java/expr.o, java/jcf-depend.o, java/jcf-parse.o)
+ (java/jvgenmain.o, java/lang.o, java/mangle.o, java/mangle_name.o)
+ (java/resource.o java/typeck.o, java/win32-host.o)
+ (java/verify-glue.o, java/verify-impl.o, java/zextract.o)
+ (java/java-gimplify.o, java/jcf-io.o, java/jcf-path.o): Remove.
+
+2013-09-25 Tom Tromey <tromey@redhat.com>
+
+ * Make-lang.in (jvspec.o): Don't use subshell.
+
2013-06-05 Jan Hubicka <jh@suse.cz>
* class.c (emit_register_classes_in_jcr_section): Use DECL_PRESERVE_P
diff --git a/gcc/java/Make-lang.in b/gcc/java/Make-lang.in
index 8a6210fea3b..5ed344cc0d2 100644
--- a/gcc/java/Make-lang.in
+++ b/gcc/java/Make-lang.in
@@ -55,17 +55,13 @@ JAVA_TARGET_INDEPENDENT_BIN_TOOLS = jcf-dump
# Tell GNU make to ignore these if they exist.
.PHONY: java
-jvspec.o: $(srcdir)/java/jvspec.c $(SYSTEM_H) coretypes.h $(TM_H) \
- $(GCC_H) $(CONFIG_H) java/jcf.h java/javaop.h $(OPTS_H)
- (SHLIB='$(SHLIB)'; \
- $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(DRIVER_DEFINES) \
- $(INCLUDES) $(srcdir)/java/jvspec.c $(OUTPUT_OPTION))
+CFLAGS-java/jvspec.o += $(DRIVER_DEFINES)
# Create the compiler driver for $(XGCJ).
-$(XGCJ)$(exeext): $(GCC_OBJS) jvspec.o java/jcf-path.o \
+$(XGCJ)$(exeext): $(GCC_OBJS) java/jvspec.o java/jcf-path.o \
libcommon-target.a $(LIBDEPS) $(EXTRA_GCC_OBJS)
+$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ $(GCC_OBJS) \
- jvspec.o java/jcf-path.o $(EXTRA_GCC_OBJS) libcommon-target.a \
+ java/jvspec.o java/jcf-path.o $(EXTRA_GCC_OBJS) libcommon-target.a \
$(EXTRA_GCC_LIBS) $(LIBS)
# Create a version of the $(XGCJ) driver which calls the cross-compiler.
@@ -89,13 +85,13 @@ JCFDUMP_OBJS = java/jcf-dump.o java/jcf-io.o java/jcf-depend.o java/jcf-path.o \
JVGENMAIN_OBJS = java/jvgenmain.o java/mangle_name.o
-java_OBJS = $(sort $(JAVA_OBJS) $(JCFDUMP_OBJS) $(JVGENMAIN_OBJS)) jvspec.o
+java_OBJS = $(sort $(JAVA_OBJS) $(JCFDUMP_OBJS) $(JVGENMAIN_OBJS)) java/jvspec.o
# Use strict warnings for this front end.
java-warn = $(STRICT_WARN)
# String length warnings
-jvspec.o-warn = -Wno-error
+java/jvspec.o-warn = -Wno-error
jc1$(exeext): $(JAVA_OBJS) $(BACKEND) $(LIBDEPS) attribs.o
rm -f $@
@@ -263,76 +259,14 @@ java.stagefeedback: stageprofile-start
-mv java/*$(objext) stagefeedback/java
#
-# .o:.h dependencies.
-JAVA_TREE_H = $(TREE_H) $(HASHTAB_H) java/java-tree.h
-
-java/jcf-dump.o: $(CONFIG_H) $(SYSTEM_H) coretypes.h $(JAVA_TREE_H) \
- java/jcf-dump.c java/jcf-reader.c java/jcf.h java/javaop.h java/javaop.def \
- version.h $(GGC_H) intl.h java/zipfile.h $(DIAGNOSTIC_H)
-java/boehm.o: java/boehm.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(TREE_H) $(JAVA_TREE_H) java/parse.h
-java/builtins.o: java/builtins.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(JAVA_TREE_H) $(GGC_H) $(FLAGS_H) $(OPTABS_H) $(EXPR_H) langhooks.h \
- gt-java-builtins.h
-java/class.o: java/class.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(JAVA_TREE_H) java/jcf.h java/parse.h toplev.h output.h $(GGC_H) \
- $(FUNCTION_H) gt-java-class.h
-java/constants.o: java/constants.c $(CONFIG_H) $(JAVA_TREE_H) java/jcf.h \
- toplev.h $(SYSTEM_H) coretypes.h $(TM_H) $(GGC_H) gt-java-constants.h
-java/decl.o: java/decl.c $(CONFIG_H) $(JAVA_TREE_H) java/jcf.h \
- toplev.h $(FLAGS_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- java/java-except.h $(GGC_H) $(REAL_H) gt-java-decl.h \
- $(TARGET_H) $(CGRAPH_H) langhooks.h
-java/except.o: java/except.c $(CONFIG_H) $(JAVA_TREE_H) java/jcf.h $(REAL_H) \
- java/javaop.h java/java-opcodes.h java/java-except.h \
- toplev.h $(SYSTEM_H) coretypes.h
-java/expr.o: java/expr.c $(CONFIG_H) $(JAVA_TREE_H) java/jcf.h $(REAL_H) \
- java/javaop.h java/java-opcodes.h \
- java/java-except.h java/java-except.h java/parse.h \
- $(SYSTEM_H) coretypes.h $(TM_H) $(GGC_H) gt-java-expr.h $(TARGET_H) \
- tree-iterator.h
-java/jcf-depend.o: java/jcf-depend.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- java/jcf.h
-java/jcf-parse.o: java/jcf-parse.c $(CONFIG_H) $(JAVA_TREE_H) $(FLAGS_H) \
- input.h java/java-except.h $(SYSTEM_H) coretypes.h \
- java/parse.h $(GGC_H) debug.h $(REAL_H) gt-java-jcf-parse.h \
- java/jcf-reader.c java/zipfile.h java/jcf.h $(BITMAP_H)
-java/jvgenmain.o: java/jvgenmain.c $(CONFIG_H) $(JAVA_TREE_H) $(SYSTEM_H) \
- coretypes.h $(TM_H) intl.h $(DIAGNOSTIC_H)
-java/lang.o: java/lang.c $(CONFIG_H) $(JAVA_TREE_H) java/jcf.h input.h \
- $(SYSTEM_H) coretypes.h $(TM_H) $(DIAGNOSTIC_H) \
- langhooks.h $(LANGHOOKS_DEF_H) gt-java-lang.h $(OPTS_H) $(OPTIONS_H) \
- $(TARGET_H)
-java/mangle.o: java/mangle.c $(CONFIG_H) java/jcf.h $(JAVA_TREE_H) $(SYSTEM_H) \
- coretypes.h $(TM_H) $(GGC_H) gt-java-mangle.h $(LANGHOOKS_DEF_H)
-java/mangle_name.o: java/mangle_name.c $(CONFIG_H) java/jcf.h $(JAVA_TREE_H) \
- $(SYSTEM_H) coretypes.h $(GGC_H)
-java/resource.o: java/resource.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(JAVA_TREE_H) java/jcf.h java/parse.h toplev.h $(GGC_H) \
- $(TARGET_H) $(FUNCTION_H) gt-java-resource.h
-java/typeck.o: java/typeck.c $(CONFIG_H) $(JAVA_TREE_H) java/jcf.h \
- $(SYSTEM_H) coretypes.h $(GGC_H) $(REAL_H)
-java/win32-host.o: java/win32-host.c $(CONFIG_H) $(SYSTEM_H) coretypes.h java/jcf.h
-java/verify-glue.o: java/verify-glue.c $(CONFIG_H) $(SYSTEM_H) $(JAVA_TREE_H) \
- coretypes.h java/verify.h
-java/verify-impl.o: java/verify-impl.c $(CONFIG_H) java/verify.h $(SYSTEM_H) \
- coretypes.h java/jcf.h $(JAVA_TREE_H)
-java/zextract.o: java/zextract.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- java/zipfile.h
-java/java-gimplify.o: java/java-gimplify.c $(CONFIG_H) $(SYSTEM_H) \
- coretypes.h dumpfile.h $(JAVA_TREE_H) $(GIMPLE_H)
# jcf-io.o needs $(ZLIBINC) added to cflags.
CFLAGS-java/jcf-io.o += $(ZLIBINC)
-java/jcf-io.o: java/jcf-io.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(JAVA_TREE_H) java/zipfile.h $(HASH_TABLE_H)
# jcf-path.o needs a -D.
CFLAGS-java/jcf-path.o += \
-DLIBGCJ_ZIP_FILE='"$(datadir)/java/libgcj-$(version).jar"' \
-DDEFAULT_TARGET_VERSION=\"$(version)\"
-java/jcf-path.o: java/jcf-path.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- java/jcf.h
TEXI_JAVA_FILES = java/gcj.texi $(gcc_docdir)/include/fdl.texi \
$(gcc_docdir)/include/gpl_v3.texi $(gcc_docdir)/include/gcc-common.texi \
diff --git a/gcc/java/builtins.c b/gcc/java/builtins.c
index f971a6fb25e..c05543782ae 100644
--- a/gcc/java/builtins.c
+++ b/gcc/java/builtins.c
@@ -579,7 +579,9 @@ initialize_builtins (void)
define_builtin (BUILT_IN_RETURN_ADDRESS, "__builtin_return_address",
build_function_type_list (ptr_type_node, int_type_node, NULL_TREE),
"__builtin_return_address", ECF_NOTHROW | ECF_LEAF);
-
+ define_builtin (BUILT_IN_TRAP, "__builtin_trap",
+ build_function_type_list (void_type_node, NULL_TREE),
+ "__builtin_trap", ECF_NOTHROW | ECF_LEAF | ECF_NORETURN);
build_common_builtin_nodes ();
}
diff --git a/gcc/java/decl.c b/gcc/java/decl.c
index c5a654d1c61..0a2cecc3fef 100644
--- a/gcc/java/decl.c
+++ b/gcc/java/decl.c
@@ -1904,7 +1904,7 @@ java_mark_decl_local (tree decl)
if (TREE_CODE (decl) == FUNCTION_DECL)
{
struct cgraph_node *node = cgraph_get_node (decl);
- gcc_assert (!node || !node->symbol.definition);
+ gcc_assert (!node || !node->definition);
}
#endif
gcc_assert (!DECL_RTL_SET_P (decl));
diff --git a/gcc/java/lang.c b/gcc/java/lang.c
index d40af8722b5..6d89134debe 100644
--- a/gcc/java/lang.c
+++ b/gcc/java/lang.c
@@ -42,6 +42,7 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */
#include "opts.h"
#include "options.h"
#include "target.h"
+#include "context.h"
static bool java_init (void);
static void java_finish (void);
@@ -271,7 +272,7 @@ java_handle_option (size_t scode, const char *arg, int value,
break;
case OPT_fdump_:
- if (!dump_switch_p (arg))
+ if (!g->get_dumps ()->dump_switch_p (arg))
return false;
break;
diff --git a/gcc/jump.c b/gcc/jump.c
index 6f7bcb72d1c..a27aaa94b8d 100644
--- a/gcc/jump.c
+++ b/gcc/jump.c
@@ -159,8 +159,8 @@ const pass_data pass_data_cleanup_barriers =
class pass_cleanup_barriers : public rtl_opt_pass
{
public:
- pass_cleanup_barriers(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_cleanup_barriers, ctxt)
+ pass_cleanup_barriers (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_cleanup_barriers, ctxt)
{}
/* opt_pass methods: */
@@ -401,9 +401,9 @@ reversed_comparison_code_parts (enum rtx_code code, const_rtx arg0,
/* These CONST_CAST's are okay because prev_nonnote_insn just
returns its argument and we assign it to a const_rtx
variable. */
- for (prev = prev_nonnote_insn (CONST_CAST_RTX(insn));
+ for (prev = prev_nonnote_insn (CONST_CAST_RTX (insn));
prev != 0 && !LABEL_P (prev);
- prev = prev_nonnote_insn (CONST_CAST_RTX(prev)))
+ prev = prev_nonnote_insn (CONST_CAST_RTX (prev)))
{
const_rtx set = set_of (arg0, prev);
if (set && GET_CODE (set) == SET
diff --git a/gcc/langhooks-def.h b/gcc/langhooks-def.h
index 7bd2e9930da..411cf74b666 100644
--- a/gcc/langhooks-def.h
+++ b/gcc/langhooks-def.h
@@ -77,6 +77,7 @@ extern tree lhd_omp_assignment (tree, tree, tree);
struct gimplify_omp_ctx;
extern void lhd_omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *,
tree);
+extern bool lhd_omp_mappable_type (tree);
#define LANG_HOOKS_NAME "GNU unknown"
#define LANG_HOOKS_IDENTIFIER_SIZE sizeof (struct lang_identifier)
@@ -166,6 +167,7 @@ extern tree lhd_make_node (enum tree_code);
#define LANG_HOOKS_TYPE_MAX_SIZE lhd_return_null_const_tree
#define LANG_HOOKS_OMP_FIRSTPRIVATIZE_TYPE_SIZES \
lhd_omp_firstprivatize_type_sizes
+#define LANG_HOOKS_OMP_MAPPABLE_TYPE lhd_omp_mappable_type
#define LANG_HOOKS_TYPE_HASH_EQ NULL
#define LANG_HOOKS_GET_ARRAY_DESCR_INFO NULL
#define LANG_HOOKS_GET_SUBRANGE_BOUNDS NULL
@@ -184,6 +186,7 @@ extern tree lhd_make_node (enum tree_code);
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_GET_ARRAY_DESCR_INFO, \
LANG_HOOKS_GET_SUBRANGE_BOUNDS, \
@@ -211,6 +214,18 @@ extern tree lhd_make_node (enum tree_code);
#define LANG_HOOKS_OMP_CLAUSE_DTOR hook_tree_tree_tree_null
#define LANG_HOOKS_OMP_FINISH_CLAUSE hook_void_tree
+extern void lhd_install_body_with_frame_cleanup (tree, tree);
+extern bool lhd_cilk_detect_spawn (tree *);
+#define LANG_HOOKS_CILKPLUS_DETECT_SPAWN_AND_UNWRAP lhd_cilk_detect_spawn
+#define LANG_HOOKS_CILKPLUS_FRAME_CLEANUP lhd_install_body_with_frame_cleanup
+#define LANG_HOOKS_CILKPLUS_GIMPLIFY_SPAWN lhd_gimplify_expr
+
+#define LANG_HOOKS_CILKPLUS { \
+ LANG_HOOKS_CILKPLUS_DETECT_SPAWN_AND_UNWRAP, \
+ LANG_HOOKS_CILKPLUS_FRAME_CLEANUP, \
+ LANG_HOOKS_CILKPLUS_GIMPLIFY_SPAWN \
+}
+
#define LANG_HOOKS_DECLS { \
LANG_HOOKS_GLOBAL_BINDINGS_P, \
LANG_HOOKS_PUSHDECL, \
@@ -288,6 +303,7 @@ extern void lhd_end_section (void);
LANG_HOOKS_TREE_DUMP_INITIALIZER, \
LANG_HOOKS_DECLS, \
LANG_HOOKS_FOR_TYPES_INITIALIZER, \
+ LANG_HOOKS_CILKPLUS, \
LANG_HOOKS_LTO, \
LANG_HOOKS_GET_INNERMOST_GENERIC_PARMS, \
LANG_HOOKS_GET_INNERMOST_GENERIC_ARGS, \
diff --git a/gcc/langhooks.c b/gcc/langhooks.c
index fbf545b466a..5d1457b1b22 100644
--- a/gcc/langhooks.c
+++ b/gcc/langhooks.c
@@ -523,6 +523,15 @@ lhd_omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *c ATTRIBUTE_UNUSED,
{
}
+/* Return true if TYPE is an OpenMP mappable type. By default return true
+ if type is complete. */
+
+bool
+lhd_omp_mappable_type (tree type)
+{
+ return COMPLETE_TYPE_P (type);
+}
+
/* Common function for add_builtin_function and
add_builtin_function_ext_scope. */
static tree
@@ -666,3 +675,18 @@ lhd_end_section (void)
saved_section = NULL;
}
}
+
+/* Empty function that is replaced with appropriate language dependent
+ frame cleanup function for _Cilk_spawn. */
+
+void
+lhd_install_body_with_frame_cleanup (tree, tree)
+{
+}
+
+/* Empty function to handle cilk_valid_spawn. */
+bool
+lhd_cilk_detect_spawn (tree *)
+{
+ return false;
+}
diff --git a/gcc/langhooks.h b/gcc/langhooks.h
index 80d4ef3b8a6..9539e7d5b7a 100644
--- a/gcc/langhooks.h
+++ b/gcc/langhooks.h
@@ -111,6 +111,9 @@ struct lang_hooks_for_types
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
@@ -136,6 +139,23 @@ struct lang_hooks_for_types
tree (*reconstruct_complex_type) (tree, tree);
};
+/* Language hooks related to Cilk Plus. */
+
+struct lang_hooks_for_cilkplus
+{
+ /* Returns true if the expression passed in has a spawned function call. */
+ bool (*cilk_detect_spawn_and_unwrap) (tree *);
+
+ /* Function to add the clean up functions after spawn. The reason why it is
+ language dependent is because in C++, it must handle exceptions. */
+ void (*install_body_with_frame_cleanup) (tree, tree);
+
+ /* Function to gimplify a spawned function call. Returns enum gimplify
+ status, but as mentioned in a previous comment, we can't see that type
+ here, so just return an int. */
+ int (*gimplify_cilk_spawn) (tree *, gimple_seq *, gimple_seq *);
+};
+
/* Language hooks related to decls and the symbol table. */
struct lang_hooks_for_decls
@@ -405,6 +425,8 @@ struct lang_hooks
struct lang_hooks_for_types types;
+ struct lang_hooks_for_cilkplus cilkplus;
+
struct lang_hooks_for_lto lto;
/* Returns a TREE_VEC of the generic parameters of an instantiation of
diff --git a/gcc/loop-doloop.c b/gcc/loop-doloop.c
index b47901b69b7..82c01a54b9d 100644
--- a/gcc/loop-doloop.c
+++ b/gcc/loop-doloop.c
@@ -381,7 +381,7 @@ add_test (rtx cond, edge *e, basic_block dest)
JUMP_LABEL (jump) = label;
/* The jump is supposed to handle an unlikely special case. */
- add_reg_note (jump, REG_BR_PROB, const0_rtx);
+ add_int_reg_note (jump, REG_BR_PROB, 0);
LABEL_NUSES (label)++;
@@ -460,7 +460,7 @@ doloop_modify (struct loop *loop, struct niter_desc *desc,
/* Determine if the iteration counter will be non-negative.
Note that the maximum value loaded is iterations_max - 1. */
- if (max_loop_iterations (loop, &iterations)
+ if (get_max_loop_iterations (loop, &iterations)
&& (iterations.ule (double_int_one.llshift
(GET_MODE_PRECISION (mode) - 1,
GET_MODE_PRECISION (mode)))))
@@ -548,20 +548,8 @@ doloop_modify (struct loop *loop, struct niter_desc *desc,
#ifdef HAVE_doloop_begin
{
rtx init;
- unsigned level = get_loop_level (loop) + 1;
- double_int iter;
- rtx iter_rtx;
-
- if (!max_loop_iterations (loop, &iter)
- || !iter.fits_shwi ())
- iter_rtx = const0_rtx;
- else
- iter_rtx = GEN_INT (iter.to_shwi());
- init = gen_doloop_begin (counter_reg,
- desc->const_iter ? desc->niter_expr : const0_rtx,
- iter_rtx,
- GEN_INT (level),
- doloop_seq);
+
+ init = gen_doloop_begin (counter_reg, doloop_seq);
if (init)
{
start_sequence ();
@@ -594,8 +582,7 @@ doloop_modify (struct loop *loop, struct niter_desc *desc,
if (true_prob_val)
{
/* Seems safer to use the branch probability. */
- add_reg_note (jump_insn, REG_BR_PROB,
- GEN_INT (desc->in_edge->probability));
+ add_int_reg_note (jump_insn, REG_BR_PROB, desc->in_edge->probability);
}
}
@@ -609,8 +596,8 @@ doloop_optimize (struct loop *loop)
{
enum machine_mode mode;
rtx doloop_seq, doloop_pat, doloop_reg;
- rtx iterations, count;
- rtx iterations_max;
+ rtx count;
+ double_int iterations, iterations_max;
rtx start_label;
rtx condition;
unsigned level, est_niter;
@@ -618,7 +605,6 @@ doloop_optimize (struct loop *loop)
struct niter_desc *desc;
unsigned word_mode_size;
unsigned HOST_WIDE_INT word_mode_max;
- double_int iter;
int entered_at_top;
if (dump_file)
@@ -668,25 +654,30 @@ doloop_optimize (struct loop *loop)
return false;
}
- count = copy_rtx (desc->niter_expr);
- iterations = desc->const_iter ? desc->niter_expr : const0_rtx;
- if (!max_loop_iterations (loop, &iter)
- || !iter.fits_shwi ())
- iterations_max = const0_rtx;
+ if (desc->const_iter)
+ iterations = rtx_to_double_int (desc->niter_expr);
else
- iterations_max = GEN_INT (iter.to_shwi());
+ iterations = double_int_zero;
+ if (!get_max_loop_iterations (loop, &iterations_max))
+ iterations_max = double_int_zero;
level = get_loop_level (loop) + 1;
+ entered_at_top = (loop->latch == desc->in_edge->dest
+ && contains_no_active_insn_p (loop->latch));
+ if (!targetm.can_use_doloop_p (iterations, iterations_max, level,
+ entered_at_top))
+ {
+ if (dump_file)
+ fprintf (dump_file, "Loop rejected by can_use_doloop_p.\n");
+ return false;
+ }
/* Generate looping insn. If the pattern FAILs then give up trying
to modify the loop since there is some aspect the back-end does
not like. */
+ count = copy_rtx (desc->niter_expr);
start_label = block_label (desc->in_edge->dest);
doloop_reg = gen_reg_rtx (mode);
- entered_at_top = (loop->latch == desc->in_edge->dest
- && contains_no_active_insn_p (loop->latch));
- doloop_seq = gen_doloop_end (doloop_reg, iterations, iterations_max,
- GEN_INT (level), start_label,
- GEN_INT (entered_at_top));
+ doloop_seq = gen_doloop_end (doloop_reg, start_label);
word_mode_size = GET_MODE_PRECISION (word_mode);
word_mode_max
@@ -697,27 +688,14 @@ doloop_optimize (struct loop *loop)
computed, we must be sure that the number of iterations fits into
the new mode. */
&& (word_mode_size >= GET_MODE_PRECISION (mode)
- || iter.ule (double_int::from_shwi (word_mode_max))))
+ || iterations_max.ule (double_int::from_shwi (word_mode_max))))
{
if (word_mode_size > GET_MODE_PRECISION (mode))
- {
- count = simplify_gen_unary (ZERO_EXTEND, word_mode,
- count, mode);
- iterations = simplify_gen_unary (ZERO_EXTEND, word_mode,
- iterations, mode);
- iterations_max = simplify_gen_unary (ZERO_EXTEND, word_mode,
- iterations_max, mode);
- }
+ count = simplify_gen_unary (ZERO_EXTEND, word_mode, count, mode);
else
- {
- count = lowpart_subreg (word_mode, count, mode);
- iterations = lowpart_subreg (word_mode, iterations, mode);
- iterations_max = lowpart_subreg (word_mode, iterations_max, mode);
- }
+ count = lowpart_subreg (word_mode, count, mode);
PUT_MODE (doloop_reg, word_mode);
- doloop_seq = gen_doloop_end (doloop_reg, iterations, iterations_max,
- GEN_INT (level), start_label,
- GEN_INT (entered_at_top));
+ doloop_seq = gen_doloop_end (doloop_reg, start_label);
}
if (! doloop_seq)
{
diff --git a/gcc/loop-init.c b/gcc/loop-init.c
index d45f42d9153..0318ba9e5f6 100644
--- a/gcc/loop-init.c
+++ b/gcc/loop-init.c
@@ -22,6 +22,7 @@ along with GCC; see the file COPYING3. If not see
#include "coretypes.h"
#include "tm.h"
#include "rtl.h"
+#include "tree.h"
#include "regs.h"
#include "obstack.h"
#include "basic-block.h"
@@ -30,7 +31,8 @@ along with GCC; see the file COPYING3. If not see
#include "flags.h"
#include "df.h"
#include "ggc.h"
-#include "tree-ssa.h"
+#include "gimple.h"
+#include "tree-ssa-loop-niter.h"
/* Apply FLAGS to the loop state. */
@@ -336,8 +338,8 @@ const pass_data pass_data_loop2 =
class pass_loop2 : public rtl_opt_pass
{
public:
- pass_loop2(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_loop2, ctxt)
+ pass_loop2 (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_loop2, ctxt)
{}
/* opt_pass methods: */
@@ -390,8 +392,8 @@ const pass_data pass_data_rtl_loop_init =
class pass_rtl_loop_init : public rtl_opt_pass
{
public:
- pass_rtl_loop_init(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_rtl_loop_init, ctxt)
+ pass_rtl_loop_init (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_rtl_loop_init, ctxt)
{}
/* opt_pass methods: */
@@ -448,8 +450,8 @@ const pass_data pass_data_rtl_loop_done =
class pass_rtl_loop_done : public rtl_opt_pass
{
public:
- pass_rtl_loop_done(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_rtl_loop_done, ctxt)
+ pass_rtl_loop_done (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_rtl_loop_done, ctxt)
{}
/* opt_pass methods: */
@@ -502,8 +504,8 @@ const pass_data pass_data_rtl_move_loop_invariants =
class pass_rtl_move_loop_invariants : public rtl_opt_pass
{
public:
- pass_rtl_move_loop_invariants(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_rtl_move_loop_invariants, ctxt)
+ pass_rtl_move_loop_invariants (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_rtl_move_loop_invariants, ctxt)
{}
/* opt_pass methods: */
@@ -556,8 +558,8 @@ const pass_data pass_data_rtl_unswitch =
class pass_rtl_unswitch : public rtl_opt_pass
{
public:
- pass_rtl_unswitch(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_rtl_unswitch, ctxt)
+ pass_rtl_unswitch (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_rtl_unswitch, ctxt)
{}
/* opt_pass methods: */
@@ -623,8 +625,8 @@ const pass_data pass_data_rtl_unroll_and_peel_loops =
class pass_rtl_unroll_and_peel_loops : public rtl_opt_pass
{
public:
- pass_rtl_unroll_and_peel_loops(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_rtl_unroll_and_peel_loops, ctxt)
+ pass_rtl_unroll_and_peel_loops (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_rtl_unroll_and_peel_loops, ctxt)
{}
/* opt_pass methods: */
@@ -683,8 +685,8 @@ const pass_data pass_data_rtl_doloop =
class pass_rtl_doloop : public rtl_opt_pass
{
public:
- pass_rtl_doloop(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_rtl_doloop, ctxt)
+ pass_rtl_doloop (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_rtl_doloop, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/loop-invariant.c b/gcc/loop-invariant.c
index 73200e199b2..c5d6b5ac29d 100644
--- a/gcc/loop-invariant.c
+++ b/gcc/loop-invariant.c
@@ -180,7 +180,7 @@ static vec<invariant_p> invariants;
static void
check_invariant_table_size (void)
{
- if (invariant_table_size < DF_DEFS_TABLE_SIZE())
+ if (invariant_table_size < DF_DEFS_TABLE_SIZE ())
{
unsigned int new_size = DF_DEFS_TABLE_SIZE () + (DF_DEFS_TABLE_SIZE () / 4);
invariant_table = XRESIZEVEC (struct invariant *, invariant_table, new_size);
@@ -274,13 +274,13 @@ invariant_for_use (df_ref use)
return NULL;
def = defs->ref;
check_invariant_table_size ();
- if (!invariant_table[DF_REF_ID(def)])
+ if (!invariant_table[DF_REF_ID (def)])
return NULL;
def_bb = DF_REF_BB (def);
if (!dominated_by_p (CDI_DOMINATORS, bb, def_bb))
return NULL;
- return invariant_table[DF_REF_ID(def)];
+ return invariant_table[DF_REF_ID (def)];
}
/* Computes hash value for invariant expression X in INSN. */
@@ -807,7 +807,7 @@ check_dependency (basic_block bb, df_ref use, bitmap depends_on)
def = defs->ref;
check_invariant_table_size ();
- inv = invariant_table[DF_REF_ID(def)];
+ inv = invariant_table[DF_REF_ID (def)];
if (!inv)
return false;
@@ -908,7 +908,7 @@ find_invariant_insn (rtx insn, bool always_reached, bool always_executed)
{
ref = df_find_def (insn, dest);
check_invariant_table_size ();
- invariant_table[DF_REF_ID(ref)] = inv;
+ invariant_table[DF_REF_ID (ref)] = inv;
}
}
diff --git a/gcc/loop-iv.c b/gcc/loop-iv.c
index 9112e886318..97aa52fc6dd 100644
--- a/gcc/loop-iv.c
+++ b/gcc/loop-iv.c
@@ -99,8 +99,8 @@ static unsigned int iv_ref_table_size = 0;
static struct rtx_iv ** iv_ref_table;
/* Induction variable stored at the reference. */
-#define DF_REF_IV(REF) iv_ref_table[DF_REF_ID(REF)]
-#define DF_REF_IV_SET(REF, IV) iv_ref_table[DF_REF_ID(REF)] = (IV)
+#define DF_REF_IV(REF) iv_ref_table[DF_REF_ID (REF)]
+#define DF_REF_IV_SET(REF, IV) iv_ref_table[DF_REF_ID (REF)] = (IV)
/* The current loop. */
@@ -212,7 +212,7 @@ lowpart_subreg (enum machine_mode outer_mode, rtx expr,
static void
check_iv_ref_table_size (void)
{
- if (iv_ref_table_size < DF_DEFS_TABLE_SIZE())
+ if (iv_ref_table_size < DF_DEFS_TABLE_SIZE ())
{
unsigned int new_size = DF_DEFS_TABLE_SIZE () + (DF_DEFS_TABLE_SIZE () / 4);
iv_ref_table = XRESIZEVEC (struct rtx_iv *, iv_ref_table, new_size);
@@ -436,7 +436,9 @@ iv_subreg (struct rtx_iv *iv, enum machine_mode mode)
&& !iv->first_special)
{
rtx val = get_iv_value (iv, const0_rtx);
- val = lowpart_subreg (mode, val, iv->extend_mode);
+ val = lowpart_subreg (mode, val,
+ iv->extend == IV_UNKNOWN_EXTEND
+ ? iv->mode : iv->extend_mode);
iv->base = val;
iv->extend = IV_UNKNOWN_EXTEND;
@@ -476,8 +478,14 @@ iv_extend (struct rtx_iv *iv, enum iv_extend_code extend, enum machine_mode mode
&& !iv->first_special)
{
rtx val = get_iv_value (iv, const0_rtx);
+ if (iv->extend_mode != iv->mode
+ && iv->extend != IV_UNKNOWN_EXTEND
+ && iv->extend != extend)
+ val = lowpart_subreg (iv->mode, val, iv->extend_mode);
val = simplify_gen_unary (iv_extend_to_rtx_code (extend), mode,
- val, iv->extend_mode);
+ val,
+ iv->extend == extend
+ ? iv->extend_mode : iv->mode);
iv->base = val;
iv->extend = IV_UNKNOWN_EXTEND;
iv->mode = iv->extend_mode = mode;
@@ -3001,9 +3009,9 @@ find_simple_exit (struct loop *loop, struct niter_desc *desc)
fprintf (dump_file, "\n");
fprintf (dump_file, " upper bound: %li\n",
- (long)max_loop_iterations_int (loop));
+ (long)get_max_loop_iterations_int (loop));
fprintf (dump_file, " realistic bound: %li\n",
- (long)estimated_loop_iterations_int (loop));
+ (long)get_estimated_loop_iterations_int (loop));
}
else
fprintf (dump_file, "Loop %d is not simple.\n", loop->num);
diff --git a/gcc/loop-unroll.c b/gcc/loop-unroll.c
index 95d58209224..40f06dbbca3 100644
--- a/gcc/loop-unroll.c
+++ b/gcc/loop-unroll.c
@@ -22,6 +22,7 @@ along with GCC; see the file COPYING3. If not see
#include "coretypes.h"
#include "tm.h"
#include "rtl.h"
+#include "tree.h"
#include "hard-reg-set.h"
#include "obstack.h"
#include "basic-block.h"
@@ -469,7 +470,7 @@ decide_peel_once_rolling (struct loop *loop, int flags ATTRIBUTE_UNUSED)
|| desc->infinite
|| !desc->const_iter
|| (desc->niter != 0
- && max_loop_iterations_int (loop) != 0))
+ && get_max_loop_iterations_int (loop) != 0))
{
if (dump_file)
fprintf (dump_file,
@@ -694,8 +695,8 @@ decide_unroll_constant_iterations (struct loop *loop, int flags)
than one exit it may well loop less than determined maximal number
of iterations. */
if (desc->niter < 2 * nunroll
- || ((estimated_loop_iterations (loop, &iterations)
- || max_loop_iterations (loop, &iterations))
+ || ((get_estimated_loop_iterations (loop, &iterations)
+ || get_max_loop_iterations (loop, &iterations))
&& iterations.ult (double_int::from_shwi (2 * nunroll))))
{
if (dump_file)
@@ -999,8 +1000,8 @@ decide_unroll_runtime_iterations (struct loop *loop, int flags)
}
/* Check whether the loop rolls. */
- if ((estimated_loop_iterations (loop, &iterations)
- || max_loop_iterations (loop, &iterations))
+ if ((get_estimated_loop_iterations (loop, &iterations)
+ || get_max_loop_iterations (loop, &iterations))
&& iterations.ult (double_int::from_shwi (2 * nunroll)))
{
if (dump_file)
@@ -1388,7 +1389,7 @@ decide_peel_simple (struct loop *loop, int flags)
}
/* If we have realistic estimate on number of iterations, use it. */
- if (estimated_loop_iterations (loop, &iterations))
+ if (get_estimated_loop_iterations (loop, &iterations))
{
if (double_int::from_shwi (npeel).ule (iterations))
{
@@ -1406,7 +1407,7 @@ decide_peel_simple (struct loop *loop, int flags)
}
/* If we have small enough bound on iterations, we can still peel (completely
unroll). */
- else if (max_loop_iterations (loop, &iterations)
+ else if (get_max_loop_iterations (loop, &iterations)
&& iterations.ult (double_int::from_shwi (npeel)))
npeel = iterations.to_shwi () + 1;
else
@@ -1556,8 +1557,8 @@ decide_unroll_stupid (struct loop *loop, int flags)
}
/* Check whether the loop rolls. */
- if ((estimated_loop_iterations (loop, &iterations)
- || max_loop_iterations (loop, &iterations))
+ if ((get_estimated_loop_iterations (loop, &iterations)
+ || get_max_loop_iterations (loop, &iterations))
&& iterations.ult (double_int::from_shwi (2 * nunroll)))
{
if (dump_file)
diff --git a/gcc/loop-unswitch.c b/gcc/loop-unswitch.c
index 213e74d515a..219c943545b 100644
--- a/gcc/loop-unswitch.c
+++ b/gcc/loop-unswitch.c
@@ -126,7 +126,7 @@ compare_and_jump_seq (rtx op0, rtx op1, enum rtx_code comp, rtx label, int prob,
JUMP_LABEL (jump) = label;
LABEL_NUSES (label)++;
}
- add_reg_note (jump, REG_BR_PROB, GEN_INT (prob));
+ add_int_reg_note (jump, REG_BR_PROB, prob);
seq = get_insns ();
end_sequence ();
@@ -191,6 +191,7 @@ may_unswitch_on (basic_block bb, struct loop *loop, rtx *cinsn)
if (!test)
return NULL_RTX;
+ mode = VOIDmode;
for (i = 0; i < 2; i++)
{
op[i] = XEXP (test, i);
@@ -205,11 +206,15 @@ may_unswitch_on (basic_block bb, struct loop *loop, rtx *cinsn)
return NULL_RTX;
op[i] = get_iv_value (&iv, const0_rtx);
+ if (iv.extend != IV_UNKNOWN_EXTEND
+ && iv.mode != iv.extend_mode)
+ op[i] = lowpart_subreg (iv.mode, op[i], iv.extend_mode);
+ if (mode == VOIDmode)
+ mode = iv.mode;
+ else
+ gcc_assert (mode == iv.mode);
}
- mode = GET_MODE (op[0]);
- if (mode == VOIDmode)
- mode = GET_MODE (op[1]);
if (GET_MODE_CLASS (mode) == MODE_CC)
{
if (at != BB_END (bb))
@@ -304,7 +309,7 @@ unswitch_single_loop (struct loop *loop, rtx cond_checked, int num)
}
/* Nor if the loop usually does not roll. */
- iterations = estimated_loop_iterations_int (loop);
+ iterations = get_estimated_loop_iterations_int (loop);
if (iterations >= 0 && iterations <= 1)
{
if (dump_file)
diff --git a/gcc/lower-subreg.c b/gcc/lower-subreg.c
index ac67398a2db..e67bc35648b 100644
--- a/gcc/lower-subreg.c
+++ b/gcc/lower-subreg.c
@@ -24,6 +24,7 @@ along with GCC; see the file COPYING3. If not see
#include "coretypes.h"
#include "machmode.h"
#include "tm.h"
+#include "tree.h"
#include "rtl.h"
#include "tm_p.h"
#include "flags.h"
@@ -966,7 +967,20 @@ resolve_simple_move (rtx set, rtx insn)
rtx reg;
reg = gen_reg_rtx (orig_mode);
+
+#ifdef AUTO_INC_DEC
+ {
+ rtx move = emit_move_insn (reg, src);
+ if (MEM_P (src))
+ {
+ rtx note = find_reg_note (insn, REG_INC, NULL_RTX);
+ if (note)
+ add_reg_note (move, REG_INC, XEXP (note, 0));
+ }
+ }
+#else
emit_move_insn (reg, src);
+#endif
src = reg;
}
@@ -1056,6 +1070,16 @@ resolve_simple_move (rtx set, rtx insn)
mdest = simplify_gen_subreg (orig_mode, dest, GET_MODE (dest), 0);
minsn = emit_move_insn (real_dest, mdest);
+#ifdef AUTO_INC_DEC
+ if (MEM_P (real_dest)
+ && !(resolve_reg_p (real_dest) || resolve_subreg_p (real_dest)))
+ {
+ rtx note = find_reg_note (insn, REG_INC, NULL_RTX);
+ if (note)
+ add_reg_note (minsn, REG_INC, XEXP (note, 0));
+ }
+#endif
+
smove = single_set (minsn);
gcc_assert (smove != NULL_RTX);
@@ -1069,7 +1093,7 @@ resolve_simple_move (rtx set, rtx insn)
emit_insn_before (insns, insn);
- /* If we get here via self-recutsion, then INSN is not yet in the insns
+ /* If we get here via self-recursion, then INSN is not yet in the insns
chain and delete_insn will fail. We only want to remove INSN from the
current sequence. See PR56738. */
if (in_sequence_p ())
@@ -1709,8 +1733,8 @@ const pass_data pass_data_lower_subreg =
class pass_lower_subreg : public rtl_opt_pass
{
public:
- pass_lower_subreg(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_lower_subreg, ctxt)
+ pass_lower_subreg (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_lower_subreg, ctxt)
{}
/* opt_pass methods: */
@@ -1748,8 +1772,8 @@ const pass_data pass_data_lower_subreg2 =
class pass_lower_subreg2 : public rtl_opt_pass
{
public:
- pass_lower_subreg2(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_lower_subreg2, ctxt)
+ pass_lower_subreg2 (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_lower_subreg2, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c
index f9652c773cd..ee82c6f496c 100644
--- a/gcc/lra-constraints.c
+++ b/gcc/lra-constraints.c
@@ -1158,6 +1158,30 @@ process_addr_reg (rtx *loc, rtx *before, rtx *after, enum reg_class cl)
return true;
}
+/* Insert move insn in simplify_operand_subreg. BEFORE returns
+ the insn to be inserted before curr insn. AFTER returns the
+ the insn to be inserted after curr insn. ORIGREG and NEWREG
+ are the original reg and new reg for reload. */
+static void
+insert_move_for_subreg (rtx *before, rtx *after, rtx origreg, rtx newreg)
+{
+ if (before)
+ {
+ push_to_sequence (*before);
+ lra_emit_move (newreg, origreg);
+ *before = get_insns ();
+ end_sequence ();
+ }
+ if (after)
+ {
+ start_sequence ();
+ lra_emit_move (origreg, newreg);
+ emit_insn (*after);
+ *after = get_insns ();
+ end_sequence ();
+ }
+}
+
/* Make reloads for subreg in operand NOP with internal subreg mode
REG_MODE, add new reloads for further processing. Return true if
any reload was generated. */
@@ -1169,6 +1193,8 @@ simplify_operand_subreg (int nop, enum machine_mode reg_mode)
enum machine_mode mode;
rtx reg, new_reg;
rtx operand = *curr_id->operand_loc[nop];
+ enum reg_class regclass;
+ enum op_type type;
before = after = NULL_RTX;
@@ -1177,6 +1203,7 @@ simplify_operand_subreg (int nop, enum machine_mode reg_mode)
mode = GET_MODE (operand);
reg = SUBREG_REG (operand);
+ type = curr_static_id->operand[nop].type;
/* If we change address for paradoxical subreg of memory, the
address might violate the necessary alignment or the access might
be slow. So take this into consideration. We should not worry
@@ -1221,7 +1248,6 @@ simplify_operand_subreg (int nop, enum machine_mode reg_mode)
&& ! LRA_SUBREG_P (operand))
|| CONSTANT_P (reg) || GET_CODE (reg) == PLUS || MEM_P (reg))
{
- enum op_type type = curr_static_id->operand[nop].type;
/* The class will be defined later in curr_insn_transform. */
enum reg_class rclass
= (enum reg_class) targetm.preferred_reload_class (reg, ALL_REGS);
@@ -1229,29 +1255,85 @@ simplify_operand_subreg (int nop, enum machine_mode reg_mode)
if (get_reload_reg (curr_static_id->operand[nop].type, reg_mode, reg,
rclass, "subreg reg", &new_reg))
{
+ bool insert_before, insert_after;
bitmap_set_bit (&lra_subreg_reload_pseudos, REGNO (new_reg));
- if (type != OP_OUT
- || GET_MODE_SIZE (GET_MODE (reg)) > GET_MODE_SIZE (mode))
- {
- push_to_sequence (before);
- lra_emit_move (new_reg, reg);
- before = get_insns ();
- end_sequence ();
- }
- if (type != OP_IN)
- {
- start_sequence ();
- lra_emit_move (reg, new_reg);
- emit_insn (after);
- after = get_insns ();
- end_sequence ();
- }
+
+ insert_before = (type != OP_OUT
+ || GET_MODE_SIZE (GET_MODE (reg)) > GET_MODE_SIZE (mode));
+ insert_after = (type != OP_IN);
+ insert_move_for_subreg (insert_before ? &before : NULL,
+ insert_after ? &after : NULL,
+ reg, new_reg);
}
SUBREG_REG (operand) = new_reg;
lra_process_new_insns (curr_insn, before, after,
"Inserting subreg reload");
return true;
}
+ /* Force a reload for a paradoxical subreg. For paradoxical subreg,
+ IRA allocates hardreg to the inner pseudo reg according to its mode
+ instead of the outermode, so the size of the hardreg may not be enough
+ to contain the outermode operand, in that case we may need to insert
+ reload for the reg. For the following two types of paradoxical subreg,
+ we need to insert reload:
+ 1. If the op_type is OP_IN, and the hardreg could not be paired with
+ other hardreg to contain the outermode operand
+ (checked by in_hard_reg_set_p), we need to insert the reload.
+ 2. If the op_type is OP_OUT or OP_INOUT.
+
+ Here is a paradoxical subreg example showing how the reload is generated:
+
+ (insn 5 4 7 2 (set (reg:TI 106 [ __comp ])
+ (subreg:TI (reg:DI 107 [ __comp ]) 0)) {*movti_internal_rex64}
+
+ In IRA, reg107 is allocated to a DImode hardreg. We use x86-64 as example
+ here, if reg107 is assigned to hardreg R15, because R15 is the last
+ hardreg, compiler cannot find another hardreg to pair with R15 to
+ contain TImode data. So we insert a TImode reload reg180 for it.
+ After reload is inserted:
+
+ (insn 283 0 0 (set (subreg:DI (reg:TI 180 [orig:107 __comp ] [107]) 0)
+ (reg:DI 107 [ __comp ])) -1
+ (insn 5 4 7 2 (set (reg:TI 106 [ __comp ])
+ (subreg:TI (reg:TI 180 [orig:107 __comp ] [107]) 0)) {*movti_internal_rex64}
+
+ Two reload hard registers will be allocated to reg180 to save TImode data
+ in LRA_assign. */
+ else if (REG_P (reg)
+ && REGNO (reg) >= FIRST_PSEUDO_REGISTER
+ && (hard_regno = lra_get_regno_hard_regno (REGNO (reg))) >= 0
+ && (hard_regno_nregs[hard_regno][GET_MODE (reg)]
+ < hard_regno_nregs[hard_regno][mode])
+ && (regclass = lra_get_allocno_class (REGNO (reg)))
+ && (type != OP_IN
+ || !in_hard_reg_set_p (reg_class_contents[regclass],
+ mode, hard_regno)))
+ {
+ /* The class will be defined later in curr_insn_transform. */
+ enum reg_class rclass
+ = (enum reg_class) targetm.preferred_reload_class (reg, ALL_REGS);
+
+ if (get_reload_reg (curr_static_id->operand[nop].type, mode, reg,
+ rclass, "paradoxical subreg", &new_reg))
+ {
+ rtx subreg;
+ bool insert_before, insert_after;
+
+ PUT_MODE (new_reg, mode);
+ subreg = simplify_gen_subreg (GET_MODE (reg), new_reg, mode, 0);
+ bitmap_set_bit (&lra_subreg_reload_pseudos, REGNO (new_reg));
+
+ insert_before = (type != OP_OUT);
+ insert_after = (type != OP_IN);
+ insert_move_for_subreg (insert_before ? &before : NULL,
+ insert_after ? &after : NULL,
+ reg, subreg);
+ }
+ SUBREG_REG (operand) = new_reg;
+ lra_process_new_insns (curr_insn, before, after,
+ "Inserting paradoxical subreg reload");
+ return true;
+ }
return false;
}
@@ -1384,23 +1466,32 @@ process_alt_operands (int only_alternative)
function. */
for (nop = 0; nop < n_operands; nop++)
{
+ rtx reg;
+
op = no_subreg_reg_operand[nop] = *curr_id->operand_loc[nop];
/* The real hard regno of the operand after the allocation. */
hard_regno[nop] = get_hard_regno (op);
- operand_reg[nop] = op;
- biggest_mode[nop] = GET_MODE (operand_reg[nop]);
- if (GET_CODE (operand_reg[nop]) == SUBREG)
+ operand_reg[nop] = reg = op;
+ biggest_mode[nop] = GET_MODE (op);
+ if (GET_CODE (op) == SUBREG)
{
- operand_reg[nop] = SUBREG_REG (operand_reg[nop]);
+ operand_reg[nop] = reg = SUBREG_REG (op);
if (GET_MODE_SIZE (biggest_mode[nop])
- < GET_MODE_SIZE (GET_MODE (operand_reg[nop])))
- biggest_mode[nop] = GET_MODE (operand_reg[nop]);
+ < GET_MODE_SIZE (GET_MODE (reg)))
+ biggest_mode[nop] = GET_MODE (reg);
}
- if (REG_P (operand_reg[nop]))
- no_subreg_reg_operand[nop] = operand_reg[nop];
- else
+ if (! REG_P (reg))
operand_reg[nop] = NULL_RTX;
+ else if (REGNO (reg) >= FIRST_PSEUDO_REGISTER
+ || ((int) REGNO (reg)
+ == lra_get_elimination_hard_regno (REGNO (reg))))
+ no_subreg_reg_operand[nop] = reg;
+ else
+ operand_reg[nop] = no_subreg_reg_operand[nop]
+ /* Just use natural mode for elimination result. It should
+ be enough for extra constraints hooks. */
+ = regno_reg_rtx[hard_regno[nop]];
}
/* The constraints are made of several alternatives. Each operand's
@@ -1453,6 +1544,7 @@ process_alt_operands (int only_alternative)
HARD_REG_SET this_alternative_set, this_costly_alternative_set;
bool this_alternative_match_win, this_alternative_win;
bool this_alternative_offmemok;
+ bool scratch_p;
enum machine_mode mode;
opalt_num = nalt * n_operands + nop;
@@ -1858,6 +1950,8 @@ process_alt_operands (int only_alternative)
}
while ((p += len), c);
+ scratch_p = (operand_reg[nop] != NULL_RTX
+ && lra_former_scratch_p (REGNO (operand_reg[nop])));
/* Record which operands fit this alternative. */
if (win)
{
@@ -1878,14 +1972,17 @@ process_alt_operands (int only_alternative)
}
else
{
- /* Prefer won reg to spilled pseudo under other equal
- conditions. */
- if (lra_dump_file != NULL)
- fprintf
- (lra_dump_file,
- " %d Non pseudo reload: reject++\n",
- nop);
- reject++;
+ /* Prefer won reg to spilled pseudo under other
+ equal conditions for possibe inheritance. */
+ if (! scratch_p)
+ {
+ if (lra_dump_file != NULL)
+ fprintf
+ (lra_dump_file,
+ " %d Non pseudo reload: reject++\n",
+ nop);
+ reject++;
+ }
if (in_class_p (operand_reg[nop],
this_costly_alternative, NULL))
{
@@ -1904,13 +2001,13 @@ process_alt_operands (int only_alternative)
insns are generated for the scratches. So it
might cost something but probably less than old
reload pass believes. */
- if (lra_former_scratch_p (REGNO (operand_reg[nop])))
+ if (scratch_p)
{
if (lra_dump_file != NULL)
fprintf (lra_dump_file,
- " %d Scratch win: reject+=3\n",
+ " %d Scratch win: reject+=2\n",
nop);
- reject += 3;
+ reject += 2;
}
}
}
@@ -2124,7 +2221,7 @@ process_alt_operands (int only_alternative)
}
}
- if (early_clobber_p)
+ if (early_clobber_p && ! scratch_p)
{
if (lra_dump_file != NULL)
fprintf (lra_dump_file,
@@ -3887,18 +3984,6 @@ lra_constraints (bool first_p)
dest_reg = SUBREG_REG (dest_reg);
if ((REG_P (dest_reg)
&& (x = get_equiv_substitution (dest_reg)) != dest_reg
- /* Check that this is actually an insn setting up
- the equivalence. */
- && (in_list_p (curr_insn,
- ira_reg_equiv
- [REGNO (dest_reg)].init_insns)
- /* Init insns may contain not all insns setting
- up equivalence as we have live range
- splitting. So here we use another condition
- to check insn setting up the equivalence
- which should be removed, e.g. in case when
- the equivalence is a constant. */
- || ! MEM_P (x))
/* Remove insns which set up a pseudo whose value
can not be changed. Such insns might be not in
init_insns because we don't update equiv data
@@ -3911,8 +3996,10 @@ lra_constraints (bool first_p)
secondary memory movement. Then the pseudo is
spilled and we use the equiv constant. In this
case we should remove the additional insn and
- this insn is not init_insns list. */
+ this insn is not init_insns list. */
&& (! MEM_P (x) || MEM_READONLY_P (x)
+ /* Check that this is actually an insn setting
+ up the equivalence. */
|| in_list_p (curr_insn,
ira_reg_equiv
[REGNO (dest_reg)].init_insns)))
diff --git a/gcc/lra-eliminations.c b/gcc/lra-eliminations.c
index f2a57511cbd..2eddb9dd85a 100644
--- a/gcc/lra-eliminations.c
+++ b/gcc/lra-eliminations.c
@@ -471,6 +471,7 @@ lra_eliminate_regs_1 (rtx x, enum machine_mode mem_mode,
/* ... fall through ... */
case INSN_LIST:
+ case INT_LIST:
/* Now do eliminations in the rest of the chain. If this was
an EXPR_LIST, this might result in allocating more memory than is
strictly needed, but it simplifies the code. */
@@ -808,69 +809,69 @@ eliminate_regs_in_insn (rtx insn, bool replace_p)
if (old_set != 0 && REG_P (SET_DEST (old_set))
&& (ep = get_elimination (SET_DEST (old_set))) != NULL)
{
- bool delete_p = replace_p;
-
+ for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
+ if (ep->from_rtx == SET_DEST (old_set) && ep->can_eliminate)
+ {
+ bool delete_p = replace_p;
+
#ifdef HARD_FRAME_POINTER_REGNUM
- /* If this is setting the frame pointer register to the hardware
- frame pointer register and this is an elimination that will
- be done (tested above), this insn is really adjusting the
- frame pointer downward to compensate for the adjustment done
- before a nonlocal goto. */
- if (ep->from == FRAME_POINTER_REGNUM
- && ep->to == HARD_FRAME_POINTER_REGNUM)
- {
- rtx src = SET_SRC (old_set);
- rtx off = remove_reg_equal_offset_note (insn, ep->to_rtx);
-
- if (replace_p)
- {
- SET_DEST (old_set) = ep->to_rtx;
- lra_update_insn_recog_data (insn);
- return;
- }
- else if (off != NULL_RTX
- || src == ep->to_rtx
- || (GET_CODE (src) == PLUS
- && XEXP (src, 1) == ep->to_rtx
- && CONST_INT_P (XEXP (src, 1))))
- {
- HOST_WIDE_INT offset = (off != NULL_RTX
- ? INTVAL (off)
- : src == ep->to_rtx
- ? 0 : INTVAL (XEXP (src, 1)));
-
- offset -= (ep->offset - ep->previous_offset);
- src = plus_constant (Pmode, ep->to_rtx, offset);
-
- /* First see if this insn remains valid when we make
- the change. If not, keep the INSN_CODE the same
- and let the constraint pass fit it up. */
- validate_change (insn, &SET_SRC (old_set), src, 1);
- validate_change (insn, &SET_DEST (old_set),
- ep->from_rtx, 1);
- if (! apply_change_group ())
- {
- SET_SRC (old_set) = src;
- SET_DEST (old_set) = ep->from_rtx;
- }
- lra_update_insn_recog_data (insn);
- /* Add offset note for future updates. */
- add_reg_note (insn, REG_EQUAL, src);
- return;
- }
-
-
- /* We can't delete this insn, but needn't process it
- since it won't be used unless something changes. */
- delete_p = false;
- }
+ if (ep->from == FRAME_POINTER_REGNUM
+ && ep->to == HARD_FRAME_POINTER_REGNUM)
+ /* If this is setting the frame pointer register to the
+ hardware frame pointer register and this is an
+ elimination that will be done (tested above), this
+ insn is really adjusting the frame pointer downward
+ to compensate for the adjustment done before a
+ nonlocal goto. */
+ {
+ rtx src = SET_SRC (old_set);
+ rtx off = remove_reg_equal_offset_note (insn, ep->to_rtx);
+
+ if (off != NULL_RTX
+ || src == ep->to_rtx
+ || (GET_CODE (src) == PLUS
+ && XEXP (src, 0) == ep->to_rtx
+ && CONST_INT_P (XEXP (src, 1))))
+ {
+ HOST_WIDE_INT offset;
+
+ if (replace_p)
+ {
+ SET_DEST (old_set) = ep->to_rtx;
+ lra_update_insn_recog_data (insn);
+ return;
+ }
+ offset = (off != NULL_RTX ? INTVAL (off)
+ : src == ep->to_rtx ? 0 : INTVAL (XEXP (src, 1)));
+ offset -= (ep->offset - ep->previous_offset);
+ src = plus_constant (Pmode, ep->to_rtx, offset);
+
+ /* First see if this insn remains valid when we
+ make the change. If not, keep the INSN_CODE
+ the same and let the constraint pass fit it
+ up. */
+ validate_change (insn, &SET_SRC (old_set), src, 1);
+ validate_change (insn, &SET_DEST (old_set),
+ ep->from_rtx, 1);
+ if (! apply_change_group ())
+ {
+ SET_SRC (old_set) = src;
+ SET_DEST (old_set) = ep->from_rtx;
+ }
+ lra_update_insn_recog_data (insn);
+ /* Add offset note for future updates. */
+ add_reg_note (insn, REG_EQUAL, src);
+ return;
+ }
+ }
#endif
-
- /* This insn isn't serving a useful purpose. We delete it
- when REPLACE is set. */
- if (delete_p)
- lra_delete_dead_insn (insn);
- return;
+
+ /* This insn isn't serving a useful purpose. We delete it
+ when REPLACE is set. */
+ if (delete_p)
+ lra_delete_dead_insn (insn);
+ return;
+ }
}
/* We allow one special case which happens to work on all machines we
@@ -1159,9 +1160,9 @@ update_reg_eliminate (bitmap insns_with_changed_offsets)
static void
init_elim_table (void)
{
- bool value_p;
struct elim_table *ep;
#ifdef ELIMINABLE_REGS
+ bool value_p;
const struct elim_table_1 *ep1;
#endif
@@ -1317,7 +1318,9 @@ lra_eliminate (bool final_p)
"Updating elimination of equiv for reg %d\n", i);
}
EXECUTE_IF_SET_IN_BITMAP (&insns_with_changed_offsets, 0, uid, bi)
- process_insn_for_elimination (lra_insn_recog_data[uid]->insn, final_p);
+ /* A dead insn can be deleted in process_insn_for_elimination. */
+ if (lra_insn_recog_data[uid] != NULL)
+ process_insn_for_elimination (lra_insn_recog_data[uid]->insn, final_p);
bitmap_clear (&insns_with_changed_offsets);
lra_eliminate_done:
diff --git a/gcc/lra-spills.c b/gcc/lra-spills.c
index 7c0c630273d..4ab10c25b98 100644
--- a/gcc/lra-spills.c
+++ b/gcc/lra-spills.c
@@ -334,8 +334,8 @@ assign_spill_hard_regs (int *pseudo_regnos, int n)
for (nr = 0;
nr < hard_regno_nregs[hard_regno][lra_reg_info[regno].biggest_mode];
nr++)
- /* Just loop. */;
- df_set_regs_ever_live (hard_regno + nr, true);
+ /* Just loop. */
+ df_set_regs_ever_live (hard_regno + nr, true);
}
bitmap_clear (&ok_insn_bitmap);
free (reserved_hard_regs);
@@ -618,6 +618,33 @@ alter_subregs (rtx *loc, bool final_p)
return res;
}
+/* Return true if REGNO is used for return in the current
+ function. */
+static bool
+return_regno_p (unsigned int regno)
+{
+ rtx outgoing = crtl->return_rtx;
+
+ if (! outgoing)
+ return false;
+
+ if (REG_P (outgoing))
+ return REGNO (outgoing) == regno;
+ else if (GET_CODE (outgoing) == PARALLEL)
+ {
+ int i;
+
+ for (i = 0; i < XVECLEN (outgoing, 0); i++)
+ {
+ rtx x = XEXP (XVECEXP (outgoing, 0, i), 0);
+
+ if (REG_P (x) && REGNO (x) == regno)
+ return true;
+ }
+ }
+ return false;
+}
+
/* Final change of pseudos got hard registers into the corresponding
hard registers and removing temporary clobbers. */
void
@@ -648,6 +675,24 @@ lra_final_code_change (void)
continue;
}
+ /* IRA can generate move insns involving pseudos. It is
+ better remove them earlier to speed up compiler a bit.
+ It is also better to do it here as they might not pass
+ final RTL check in LRA, (e.g. insn moving a control
+ register into itself). So remove an useless move insn
+ unless next insn is USE marking the return reg (we should
+ save this as some subsequent optimizations assume that
+ such original insns are saved). */
+ if (NONJUMP_INSN_P (insn) && GET_CODE (pat) == SET
+ && REG_P (SET_SRC (pat)) && REG_P (SET_DEST (pat))
+ && REGNO (SET_SRC (pat)) == REGNO (SET_DEST (pat))
+ && ! return_regno_p (REGNO (SET_SRC (pat))))
+ {
+ lra_invalidate_insn_data (insn);
+ delete_insn (insn);
+ continue;
+ }
+
lra_insn_recog_data_t id = lra_get_insn_recog_data (insn);
struct lra_static_insn_data *static_id = id->insn_static_data;
bool insn_change_p = false;
diff --git a/gcc/lra.c b/gcc/lra.c
index f5aab173927..1aea599a2e5 100644
--- a/gcc/lra.c
+++ b/gcc/lra.c
@@ -2017,10 +2017,8 @@ restore_scratches (void)
static void
check_rtl (bool final_p)
{
- int i;
basic_block bb;
rtx insn;
- lra_insn_recog_data_t id;
lra_assert (! final_p || reload_completed);
FOR_EACH_BB (bb)
@@ -2036,31 +2034,13 @@ check_rtl (bool final_p)
lra_assert (constrain_operands (1));
continue;
}
+ /* LRA code is based on assumption that all addresses can be
+ correctly decomposed. LRA can generate reloads for
+ decomposable addresses. The decomposition code checks the
+ correctness of the addresses. So we don't need to check
+ the addresses here. */
if (insn_invalid_p (insn, false))
fatal_insn_not_found (insn);
- if (asm_noperands (PATTERN (insn)) >= 0)
- continue;
- id = lra_get_insn_recog_data (insn);
- /* The code is based on assumption that all addresses in
- regular instruction are legitimate before LRA. The code in
- lra-constraints.c is based on assumption that there is no
- subreg of memory as an insn operand. */
- for (i = 0; i < id->insn_static_data->n_operands; i++)
- {
- rtx op = *id->operand_loc[i];
-
- if (MEM_P (op)
- && (GET_MODE (op) != BLKmode
- || GET_CODE (XEXP (op, 0)) != SCRATCH)
- && ! memory_address_p (GET_MODE (op), XEXP (op, 0))
- /* Some ports don't recognize the following addresses
- as legitimate. Although they are legitimate if
- they satisfies the constraints and will be checked
- by insn constraints which we ignore here. */
- && GET_CODE (XEXP (op, 0)) != UNSPEC
- && GET_RTX_CLASS (GET_CODE (XEXP (op, 0))) != RTX_AUTOINC)
- fatal_insn_not_found (insn);
- }
}
}
#endif /* #ifdef ENABLE_CHECKING */
@@ -2163,7 +2143,9 @@ update_inc_notes (void)
pnote = &REG_NOTES (insn);
while (*pnote != 0)
{
- if (REG_NOTE_KIND (*pnote) == REG_INC)
+ if (REG_NOTE_KIND (*pnote) == REG_DEAD
+ || REG_NOTE_KIND (*pnote) == REG_UNUSED
+ || REG_NOTE_KIND (*pnote) == REG_INC)
*pnote = XEXP (*pnote, 1);
else
pnote = &XEXP (*pnote, 1);
diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c
index 952588dba2f..99dbf96b7a5 100644
--- a/gcc/lto-cgraph.c
+++ b/gcc/lto-cgraph.c
@@ -25,6 +25,7 @@ along with GCC; see the file COPYING3. If not see
#include "coretypes.h"
#include "tm.h"
#include "tree.h"
+#include "gimple.h"
#include "expr.h"
#include "flags.h"
#include "params.h"
@@ -32,8 +33,7 @@ along with GCC; see the file COPYING3. If not see
#include "hashtab.h"
#include "langhooks.h"
#include "basic-block.h"
-#include "tree-ssa.h"
-#include "cgraph.h"
+#include "bitmap.h"
#include "function.h"
#include "ggc.h"
#include "diagnostic-core.h"
@@ -52,7 +52,7 @@ along with GCC; see the file COPYING3. If not see
#include "ipa-utils.h"
static void output_cgraph_opt_summary (void);
-static void input_cgraph_opt_summary (vec<symtab_node> nodes);
+static void input_cgraph_opt_summary (vec<symtab_node *> nodes);
/* Number of LDPR values known to GCC. */
#define LDPR_NUM_KNOWN (LDPR_PREVAILING_DEF_IRONLY_EXP + 1)
@@ -111,7 +111,7 @@ lto_symtab_encoder_delete (lto_symtab_encoder_t encoder)
int
lto_symtab_encoder_encode (lto_symtab_encoder_t encoder,
- symtab_node node)
+ symtab_node *node)
{
int ref;
void **slot;
@@ -145,7 +145,7 @@ lto_symtab_encoder_encode (lto_symtab_encoder_t encoder,
bool
lto_symtab_encoder_delete_node (lto_symtab_encoder_t encoder,
- symtab_node node)
+ symtab_node *node)
{
void **slot, **last_slot;
int index;
@@ -183,7 +183,7 @@ bool
lto_symtab_encoder_encode_body_p (lto_symtab_encoder_t encoder,
struct cgraph_node *node)
{
- int index = lto_symtab_encoder_lookup (encoder, (symtab_node)node);
+ int index = lto_symtab_encoder_lookup (encoder, node);
return encoder->nodes[index].body;
}
@@ -193,8 +193,8 @@ static void
lto_set_symtab_encoder_encode_body (lto_symtab_encoder_t encoder,
struct cgraph_node *node)
{
- int index = lto_symtab_encoder_encode (encoder, (symtab_node)node);
- gcc_checking_assert (encoder->nodes[index].node == (symtab_node)node);
+ int index = lto_symtab_encoder_encode (encoder, node);
+ gcc_checking_assert (encoder->nodes[index].node == node);
encoder->nodes[index].body = true;
}
@@ -204,7 +204,7 @@ bool
lto_symtab_encoder_encode_initializer_p (lto_symtab_encoder_t encoder,
struct varpool_node *node)
{
- int index = lto_symtab_encoder_lookup (encoder, (symtab_node)node);
+ int index = lto_symtab_encoder_lookup (encoder, node);
if (index == LCC_NOT_FOUND)
return false;
return encoder->nodes[index].initializer;
@@ -216,7 +216,7 @@ static void
lto_set_symtab_encoder_encode_initializer (lto_symtab_encoder_t encoder,
struct varpool_node *node)
{
- int index = lto_symtab_encoder_lookup (encoder, (symtab_node)node);
+ int index = lto_symtab_encoder_lookup (encoder, node);
encoder->nodes[index].initializer = true;
}
@@ -224,9 +224,9 @@ lto_set_symtab_encoder_encode_initializer (lto_symtab_encoder_t encoder,
bool
lto_symtab_encoder_in_partition_p (lto_symtab_encoder_t encoder,
- symtab_node node)
+ symtab_node *node)
{
- int index = lto_symtab_encoder_lookup (encoder, (symtab_node)node);
+ int index = lto_symtab_encoder_lookup (encoder, node);
if (index == LCC_NOT_FOUND)
return false;
return encoder->nodes[index].in_partition;
@@ -236,9 +236,9 @@ lto_symtab_encoder_in_partition_p (lto_symtab_encoder_t encoder,
void
lto_set_symtab_encoder_in_partition (lto_symtab_encoder_t encoder,
- symtab_node node)
+ symtab_node *node)
{
- int index = lto_symtab_encoder_encode (encoder, (symtab_node)node);
+ int index = lto_symtab_encoder_encode (encoder, node);
encoder->nodes[index].in_partition = true;
}
@@ -259,13 +259,13 @@ lto_output_edge (struct lto_simple_output_block *ob, struct cgraph_edge *edge,
streamer_write_enum (ob->main_stream, LTO_symtab_tags, LTO_symtab_last_tag,
LTO_symtab_edge);
- ref = lto_symtab_encoder_lookup (encoder, (symtab_node)edge->caller);
+ ref = lto_symtab_encoder_lookup (encoder, edge->caller);
gcc_assert (ref != LCC_NOT_FOUND);
streamer_write_hwi_stream (ob->main_stream, ref);
if (!edge->indirect_unknown_callee)
{
- ref = lto_symtab_encoder_lookup (encoder, (symtab_node)edge->callee);
+ ref = lto_symtab_encoder_lookup (encoder, edge->callee);
gcc_assert (ref != LCC_NOT_FOUND);
streamer_write_hwi_stream (ob->main_stream, ref);
}
@@ -273,7 +273,7 @@ lto_output_edge (struct lto_simple_output_block *ob, struct cgraph_edge *edge,
streamer_write_gcov_count_stream (ob->main_stream, edge->count);
bp = bitpack_create (ob->main_stream);
- uid = (!gimple_has_body_p (edge->caller->symbol.decl)
+ uid = (!gimple_has_body_p (edge->caller->decl)
? edge->lto_stmt_uid : gimple_uid (edge->call_stmt) + 1);
bp_pack_enum (&bp, cgraph_inline_failed_enum,
CIF_N_REASONS, edge->inline_failed);
@@ -319,7 +319,7 @@ referenced_from_other_partition_p (struct ipa_ref_list *list, lto_symtab_encoder
struct ipa_ref *ref;
for (i = 0; ipa_ref_list_referring_iterate (list, i, ref); i++)
{
- if (ref->referring->symbol.in_other_partition
+ if (ref->referring->in_other_partition
|| !lto_symtab_encoder_in_partition_p (encoder, ref->referring))
return true;
}
@@ -332,13 +332,13 @@ bool
reachable_from_other_partition_p (struct cgraph_node *node, lto_symtab_encoder_t encoder)
{
struct cgraph_edge *e;
- if (!node->symbol.definition)
+ if (!node->definition)
return false;
if (node->global.inlined_to)
return false;
for (e = node->callers; e; e = e->next_caller)
- if (e->caller->symbol.in_other_partition
- || !lto_symtab_encoder_in_partition_p (encoder, (symtab_node)e->caller))
+ if (e->caller->in_other_partition
+ || !lto_symtab_encoder_in_partition_p (encoder, e->caller))
return true;
return false;
}
@@ -364,7 +364,7 @@ reachable_from_this_partition_p (struct cgraph_node *node, lto_symtab_encoder_t
{
struct cgraph_edge *e;
for (e = node->callers; e; e = e->next_caller)
- if (lto_symtab_encoder_in_partition_p (encoder, (symtab_node)e->caller))
+ if (lto_symtab_encoder_in_partition_p (encoder, e->caller))
return true;
return false;
}
@@ -391,16 +391,16 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
int i;
bool alias_p;
- boundary_p = !lto_symtab_encoder_in_partition_p (encoder, (symtab_node)node);
+ boundary_p = !lto_symtab_encoder_in_partition_p (encoder, node);
- if (node->symbol.analyzed && !boundary_p)
+ if (node->analyzed && !boundary_p)
tag = LTO_symtab_analyzed_node;
else
tag = LTO_symtab_unavail_node;
streamer_write_enum (ob->main_stream, LTO_symtab_tags, LTO_symtab_last_tag,
tag);
- streamer_write_hwi_stream (ob->main_stream, node->symbol.order);
+ streamer_write_hwi_stream (ob->main_stream, node->order);
/* In WPA mode, we only output part of the call-graph. Also, we
fake cgraph node attributes. There are two cases that we care.
@@ -412,7 +412,7 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
Cherry-picked nodes: These are nodes we pulled from other
translation units into SET during IPA-inlining. We make them as
local static nodes to prevent clashes with other local statics. */
- if (boundary_p && node->symbol.analyzed && !DECL_EXTERNAL (node->symbol.decl))
+ if (boundary_p && node->analyzed && !DECL_EXTERNAL (node->decl))
{
/* Inline clones can not be part of boundary.
gcc_assert (!node->global.inlined_to);
@@ -427,7 +427,7 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
clone_of = node->clone_of;
while (clone_of
- && (ref = lto_symtab_encoder_lookup (encoder, (symtab_node)clone_of)) == LCC_NOT_FOUND)
+ && (ref = lto_symtab_encoder_lookup (encoder, clone_of)) == LCC_NOT_FOUND)
if (clone_of->prev_sibling_clone)
clone_of = clone_of->prev_sibling_clone;
else
@@ -450,7 +450,7 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
streamer_write_hwi_stream (ob->main_stream, ref);
- lto_output_fn_decl_index (ob->decl_state, ob->main_stream, node->symbol.decl);
+ lto_output_fn_decl_index (ob->decl_state, ob->main_stream, node->decl);
streamer_write_gcov_count_stream (ob->main_stream, node->count);
streamer_write_hwi_stream (ob->main_stream, node->count_materialization_scale);
@@ -463,7 +463,7 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
{
if (node->global.inlined_to)
{
- ref = lto_symtab_encoder_lookup (encoder, (symtab_node)node->global.inlined_to);
+ ref = lto_symtab_encoder_lookup (encoder, node->global.inlined_to);
gcc_assert (ref != LCC_NOT_FOUND);
}
else
@@ -472,32 +472,34 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
streamer_write_hwi_stream (ob->main_stream, ref);
}
- if (node->symbol.same_comdat_group && !boundary_p)
+ if (node->same_comdat_group && !boundary_p)
{
ref = lto_symtab_encoder_lookup (encoder,
- node->symbol.same_comdat_group);
+ node->same_comdat_group);
gcc_assert (ref != LCC_NOT_FOUND);
}
else
ref = LCC_NOT_FOUND;
streamer_write_hwi_stream (ob->main_stream, ref);
+ streamer_write_hwi_stream (ob->main_stream, node->tp_first_run);
+
bp = bitpack_create (ob->main_stream);
bp_pack_value (&bp, node->local.local, 1);
- bp_pack_value (&bp, node->symbol.externally_visible, 1);
- bp_pack_value (&bp, node->symbol.definition, 1);
+ bp_pack_value (&bp, node->externally_visible, 1);
+ bp_pack_value (&bp, node->definition, 1);
bp_pack_value (&bp, node->local.versionable, 1);
bp_pack_value (&bp, node->local.can_change_signature, 1);
bp_pack_value (&bp, node->local.redefined_extern_inline, 1);
- bp_pack_value (&bp, node->symbol.force_output, 1);
- bp_pack_value (&bp, node->symbol.forced_by_abi, 1);
- bp_pack_value (&bp, node->symbol.unique_name, 1);
- bp_pack_value (&bp, node->symbol.address_taken, 1);
+ bp_pack_value (&bp, node->force_output, 1);
+ bp_pack_value (&bp, node->forced_by_abi, 1);
+ bp_pack_value (&bp, node->unique_name, 1);
+ bp_pack_value (&bp, node->address_taken, 1);
bp_pack_value (&bp, tag == LTO_symtab_analyzed_node
- && !DECL_EXTERNAL (node->symbol.decl)
- && !DECL_COMDAT (node->symbol.decl)
+ && !DECL_EXTERNAL (node->decl)
+ && !DECL_COMDAT (node->decl)
&& (reachable_from_other_partition_p (node, encoder)
- || referenced_from_other_partition_p (&node->symbol.ref_list,
+ || referenced_from_other_partition_p (&node->ref_list,
encoder)), 1);
bp_pack_value (&bp, node->lowered, 1);
bp_pack_value (&bp, in_other_partition, 1);
@@ -507,16 +509,16 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
defined in other unit, we may use the info on aliases to resolve
symbol1 != symbol2 type tests that we can do only for locally defined objects
otherwise. */
- alias_p = node->symbol.alias && (!boundary_p || node->symbol.weakref);
+ alias_p = node->alias && (!boundary_p || node->weakref);
bp_pack_value (&bp, alias_p, 1);
- bp_pack_value (&bp, node->symbol.weakref, 1);
+ bp_pack_value (&bp, node->weakref, 1);
bp_pack_value (&bp, node->frequency, 2);
bp_pack_value (&bp, node->only_called_at_startup, 1);
bp_pack_value (&bp, node->only_called_at_exit, 1);
bp_pack_value (&bp, node->tm_clone, 1);
bp_pack_value (&bp, node->thunk.thunk_p && !boundary_p, 1);
bp_pack_enum (&bp, ld_plugin_symbol_resolution,
- LDPR_NUM_KNOWN, node->symbol.resolution);
+ LDPR_NUM_KNOWN, node->resolution);
streamer_write_bitpack (&bp);
if (node->thunk.thunk_p && !boundary_p)
@@ -538,57 +540,57 @@ static void
lto_output_varpool_node (struct lto_simple_output_block *ob, struct varpool_node *node,
lto_symtab_encoder_t encoder)
{
- bool boundary_p = !lto_symtab_encoder_in_partition_p (encoder, (symtab_node)node);
+ bool boundary_p = !lto_symtab_encoder_in_partition_p (encoder, node);
struct bitpack_d bp;
int ref;
bool alias_p;
streamer_write_enum (ob->main_stream, LTO_symtab_tags, LTO_symtab_last_tag,
LTO_symtab_variable);
- streamer_write_hwi_stream (ob->main_stream, node->symbol.order);
- lto_output_var_decl_index (ob->decl_state, ob->main_stream, node->symbol.decl);
+ streamer_write_hwi_stream (ob->main_stream, node->order);
+ lto_output_var_decl_index (ob->decl_state, ob->main_stream, node->decl);
bp = bitpack_create (ob->main_stream);
- bp_pack_value (&bp, node->symbol.externally_visible, 1);
- bp_pack_value (&bp, node->symbol.force_output, 1);
- bp_pack_value (&bp, node->symbol.forced_by_abi, 1);
- bp_pack_value (&bp, node->symbol.unique_name, 1);
- bp_pack_value (&bp, node->symbol.definition, 1);
- alias_p = node->symbol.alias && (!boundary_p || node->symbol.weakref);
+ bp_pack_value (&bp, node->externally_visible, 1);
+ bp_pack_value (&bp, node->force_output, 1);
+ bp_pack_value (&bp, node->forced_by_abi, 1);
+ bp_pack_value (&bp, node->unique_name, 1);
+ bp_pack_value (&bp, node->definition, 1);
+ alias_p = node->alias && (!boundary_p || node->weakref);
bp_pack_value (&bp, alias_p, 1);
- bp_pack_value (&bp, node->symbol.weakref, 1);
- bp_pack_value (&bp, node->symbol.analyzed && !boundary_p, 1);
- gcc_assert (node->symbol.definition || !node->symbol.analyzed);
+ bp_pack_value (&bp, node->weakref, 1);
+ bp_pack_value (&bp, node->analyzed && !boundary_p, 1);
+ gcc_assert (node->definition || !node->analyzed);
/* Constant pool initializers can be de-unified into individual ltrans units.
FIXME: Alternatively at -Os we may want to avoid generating for them the local
labels and share them across LTRANS partitions. */
- if (DECL_IN_CONSTANT_POOL (node->symbol.decl)
- && !DECL_EXTERNAL (node->symbol.decl)
- && !DECL_COMDAT (node->symbol.decl))
+ if (DECL_IN_CONSTANT_POOL (node->decl)
+ && !DECL_EXTERNAL (node->decl)
+ && !DECL_COMDAT (node->decl))
{
bp_pack_value (&bp, 0, 1); /* used_from_other_parition. */
bp_pack_value (&bp, 0, 1); /* in_other_partition. */
}
else
{
- bp_pack_value (&bp, node->symbol.definition
- && referenced_from_other_partition_p (&node->symbol.ref_list,
+ bp_pack_value (&bp, node->definition
+ && referenced_from_other_partition_p (&node->ref_list,
encoder), 1);
- bp_pack_value (&bp, node->symbol.analyzed
- && boundary_p && !DECL_EXTERNAL (node->symbol.decl), 1);
+ bp_pack_value (&bp, node->analyzed
+ && boundary_p && !DECL_EXTERNAL (node->decl), 1);
/* in_other_partition. */
}
streamer_write_bitpack (&bp);
- if (node->symbol.same_comdat_group && !boundary_p)
+ if (node->same_comdat_group && !boundary_p)
{
ref = lto_symtab_encoder_lookup (encoder,
- node->symbol.same_comdat_group);
+ node->same_comdat_group);
gcc_assert (ref != LCC_NOT_FOUND);
}
else
ref = LCC_NOT_FOUND;
streamer_write_hwi_stream (ob->main_stream, ref);
streamer_write_enum (ob->main_stream, ld_plugin_symbol_resolution,
- LDPR_NUM_KNOWN, node->symbol.resolution);
+ LDPR_NUM_KNOWN, node->resolution);
}
/* Output the varpool NODE to OB.
@@ -703,15 +705,15 @@ output_refs (lto_symtab_encoder_t encoder)
for (lsei = lsei_start_in_partition (encoder); !lsei_end_p (lsei);
lsei_next_in_partition (&lsei))
{
- symtab_node node = lsei_node (lsei);
+ symtab_node *node = lsei_node (lsei);
- count = ipa_ref_list_nreferences (&node->symbol.ref_list);
+ count = ipa_ref_list_nreferences (&node->ref_list);
if (count)
{
streamer_write_gcov_count_stream (ob->main_stream, count);
streamer_write_uhwi_stream (ob->main_stream,
lto_symtab_encoder_lookup (encoder, node));
- for (i = 0; ipa_ref_list_reference_iterate (&node->symbol.ref_list,
+ for (i = 0; ipa_ref_list_reference_iterate (&node->ref_list,
i, ref); i++)
lto_output_ref (ob, ref, encoder);
}
@@ -733,7 +735,7 @@ add_node_to (lto_symtab_encoder_t encoder, struct cgraph_node *node,
add_node_to (encoder, node->clone_of, include_body);
else if (include_body)
lto_set_symtab_encoder_encode_body (encoder, node);
- lto_symtab_encoder_encode (encoder, (symtab_node)node);
+ lto_symtab_encoder_encode (encoder, node);
}
/* Add all references in LIST to encoders. */
@@ -779,13 +781,13 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder)
{
node = lsei_cgraph_node (lsei);
add_node_to (encoder, node, true);
- lto_set_symtab_encoder_in_partition (encoder, (symtab_node)node);
- add_references (encoder, &node->symbol.ref_list);
+ lto_set_symtab_encoder_in_partition (encoder, node);
+ add_references (encoder, &node->ref_list);
/* For proper debug info, we need to ship the origins, too. */
- if (DECL_ABSTRACT_ORIGIN (node->symbol.decl))
+ if (DECL_ABSTRACT_ORIGIN (node->decl))
{
struct cgraph_node *origin_node
- = cgraph_get_node (DECL_ABSTRACT_ORIGIN (node->symbol.decl));
+ = cgraph_get_node (DECL_ABSTRACT_ORIGIN (node->decl));
add_node_to (encoder, origin_node, true);
}
}
@@ -794,15 +796,15 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder)
{
struct varpool_node *vnode = lsei_varpool_node (lsei);
- lto_set_symtab_encoder_in_partition (encoder, (symtab_node)vnode);
+ lto_set_symtab_encoder_in_partition (encoder, vnode);
lto_set_symtab_encoder_encode_initializer (encoder, vnode);
- add_references (encoder, &vnode->symbol.ref_list);
+ add_references (encoder, &vnode->ref_list);
/* For proper debug info, we need to ship the origins, too. */
- if (DECL_ABSTRACT_ORIGIN (vnode->symbol.decl))
+ if (DECL_ABSTRACT_ORIGIN (vnode->decl))
{
struct varpool_node *origin_node
- = varpool_get_node (DECL_ABSTRACT_ORIGIN (node->symbol.decl));
- lto_set_symtab_encoder_in_partition (encoder, (symtab_node)origin_node);
+ = varpool_get_node (DECL_ABSTRACT_ORIGIN (node->decl));
+ lto_set_symtab_encoder_in_partition (encoder, origin_node);
}
}
/* Pickle in also the initializer of all referenced readonly variables
@@ -810,15 +812,15 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder)
pickle those too. */
for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
{
- symtab_node node = lto_symtab_encoder_deref (encoder, i);
+ symtab_node *node = lto_symtab_encoder_deref (encoder, i);
if (varpool_node *vnode = dyn_cast <varpool_node> (node))
{
if (!lto_symtab_encoder_encode_initializer_p (encoder,
vnode)
- && ctor_for_folding (vnode->symbol.decl) != error_mark_node)
+ && ctor_for_folding (vnode->decl) != error_mark_node)
{
lto_set_symtab_encoder_encode_initializer (encoder, vnode);
- add_references (encoder, &vnode->symbol.ref_list);
+ add_references (encoder, &vnode->ref_list);
}
}
}
@@ -832,7 +834,7 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder)
for (edge = node->callees; edge; edge = edge->next_callee)
{
struct cgraph_node *callee = edge->callee;
- if (!lto_symtab_encoder_in_partition_p (encoder, (symtab_node)callee))
+ if (!lto_symtab_encoder_in_partition_p (encoder, callee))
{
/* We should have moved all the inlines. */
gcc_assert (!callee->global.inlined_to);
@@ -853,15 +855,15 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder)
if (!pointer_set_insert (reachable_call_targets,
cache_token))
{
- for (i = 0; i < targets.length(); i++)
+ for (i = 0; i < targets.length (); i++)
{
struct cgraph_node *callee = targets[i];
/* Adding an external declarations into the unit serves
no purpose and just increases its boundary. */
- if (callee->symbol.definition
+ if (callee->definition
&& !lto_symtab_encoder_in_partition_p
- (encoder, (symtab_node)callee))
+ (encoder, callee))
{
gcc_assert (!callee->global.inlined_to);
add_node_to (encoder, callee, false);
@@ -905,7 +907,7 @@ output_symtab (void)
n_nodes = lto_symtab_encoder_size (encoder);
for (i = 0; i < n_nodes; i++)
{
- symtab_node node = lto_symtab_encoder_deref (encoder, i);
+ symtab_node *node = lto_symtab_encoder_deref (encoder, i);
if (cgraph_node *cnode = dyn_cast <cgraph_node> (node))
lto_output_node (ob, cnode, encoder);
else
@@ -952,24 +954,24 @@ input_overwrite_node (struct lto_file_decl_data *file_data,
enum LTO_symtab_tags tag,
struct bitpack_d *bp)
{
- node->symbol.aux = (void *) tag;
- node->symbol.lto_file_data = file_data;
+ node->aux = (void *) tag;
+ node->lto_file_data = file_data;
node->local.local = bp_unpack_value (bp, 1);
- node->symbol.externally_visible = bp_unpack_value (bp, 1);
- node->symbol.definition = bp_unpack_value (bp, 1);
+ node->externally_visible = bp_unpack_value (bp, 1);
+ node->definition = bp_unpack_value (bp, 1);
node->local.versionable = bp_unpack_value (bp, 1);
node->local.can_change_signature = bp_unpack_value (bp, 1);
node->local.redefined_extern_inline = bp_unpack_value (bp, 1);
- node->symbol.force_output = bp_unpack_value (bp, 1);
- node->symbol.forced_by_abi = bp_unpack_value (bp, 1);
- node->symbol.unique_name = bp_unpack_value (bp, 1);
- node->symbol.address_taken = bp_unpack_value (bp, 1);
- node->symbol.used_from_other_partition = bp_unpack_value (bp, 1);
+ node->force_output = bp_unpack_value (bp, 1);
+ node->forced_by_abi = bp_unpack_value (bp, 1);
+ node->unique_name = bp_unpack_value (bp, 1);
+ node->address_taken = bp_unpack_value (bp, 1);
+ node->used_from_other_partition = bp_unpack_value (bp, 1);
node->lowered = bp_unpack_value (bp, 1);
- node->symbol.analyzed = tag == LTO_symtab_analyzed_node;
- node->symbol.in_other_partition = bp_unpack_value (bp, 1);
- if (node->symbol.in_other_partition
+ node->analyzed = tag == LTO_symtab_analyzed_node;
+ node->in_other_partition = bp_unpack_value (bp, 1);
+ if (node->in_other_partition
/* Avoid updating decl when we are seeing just inline clone.
When inlining function that has functions already inlined into it,
we produce clones of inline clones.
@@ -978,19 +980,19 @@ input_overwrite_node (struct lto_file_decl_data *file_data,
we might end up streaming inline clone from other partition
to support clone we are interested in. */
&& (!node->clone_of
- || node->clone_of->symbol.decl != node->symbol.decl))
+ || node->clone_of->decl != node->decl))
{
- DECL_EXTERNAL (node->symbol.decl) = 1;
- TREE_STATIC (node->symbol.decl) = 0;
+ DECL_EXTERNAL (node->decl) = 1;
+ TREE_STATIC (node->decl) = 0;
}
- node->symbol.alias = bp_unpack_value (bp, 1);
- node->symbol.weakref = bp_unpack_value (bp, 1);
+ node->alias = bp_unpack_value (bp, 1);
+ node->weakref = bp_unpack_value (bp, 1);
node->frequency = (enum node_frequency)bp_unpack_value (bp, 2);
node->only_called_at_startup = bp_unpack_value (bp, 1);
node->only_called_at_exit = bp_unpack_value (bp, 1);
node->tm_clone = bp_unpack_value (bp, 1);
node->thunk.thunk_p = bp_unpack_value (bp, 1);
- node->symbol.resolution = bp_unpack_enum (bp, ld_plugin_symbol_resolution,
+ node->resolution = bp_unpack_enum (bp, ld_plugin_symbol_resolution,
LDPR_NUM_KNOWN);
}
@@ -1011,7 +1013,7 @@ static struct cgraph_node *
input_node (struct lto_file_decl_data *file_data,
struct lto_input_block *ib,
enum LTO_symtab_tags tag,
- vec<symtab_node> nodes)
+ vec<symtab_node *> nodes)
{
gcc::pass_manager *passes = g->get_passes ();
tree fn_decl;
@@ -1041,11 +1043,11 @@ input_node (struct lto_file_decl_data *file_data,
from other input file. We keep cgraph unmerged until after streaming
of ipa passes is done. Alays forcingly create a fresh node. */
node = cgraph_create_empty_node ();
- node->symbol.decl = fn_decl;
- symtab_register_node ((symtab_node)node);
+ node->decl = fn_decl;
+ symtab_register_node (node);
}
- node->symbol.order = order;
+ node->order = order;
if (order >= symtab_order)
symtab_order = order + 1;
@@ -1073,18 +1075,21 @@ input_node (struct lto_file_decl_data *file_data,
have already been read will have their tag stored in the 'aux'
field. Since built-in functions can be referenced in multiple
functions, they are expected to be read more than once. */
- if (node->symbol.aux && !DECL_BUILT_IN (node->symbol.decl))
+ if (node->aux && !DECL_BUILT_IN (node->decl))
internal_error ("bytecode stream: found multiple instances of cgraph "
"node with uid %d", node->uid);
+ node->tp_first_run = streamer_read_uhwi (ib);
+
bp = streamer_read_bitpack (ib);
+
input_overwrite_node (file_data, node, tag, &bp);
/* Store a reference for now, and fix up later to be a pointer. */
node->global.inlined_to = (cgraph_node_ptr) (intptr_t) ref;
/* Store a reference for now, and fix up later to be a pointer. */
- node->symbol.same_comdat_group = (symtab_node) (intptr_t) ref2;
+ node->same_comdat_group = (symtab_node *) (intptr_t) ref2;
if (node->thunk.thunk_p)
{
@@ -1097,8 +1102,8 @@ input_node (struct lto_file_decl_data *file_data,
node->thunk.virtual_value = virtual_value;
node->thunk.virtual_offset_p = (type & 4);
}
- if (node->symbol.alias && !node->symbol.analyzed && node->symbol.weakref)
- node->symbol.alias_target = get_alias_symbol (node->symbol.decl);
+ if (node->alias && !node->analyzed && node->weakref)
+ node->alias_target = get_alias_symbol (node->decl);
node->profile_id = streamer_read_hwi (ib);
return node;
}
@@ -1125,36 +1130,36 @@ input_varpool_node (struct lto_file_decl_data *file_data,
from other input file. We keep cgraph unmerged until after streaming
of ipa passes is done. Alays forcingly create a fresh node. */
node = varpool_create_empty_node ();
- node->symbol.decl = var_decl;
- symtab_register_node ((symtab_node)node);
+ node->decl = var_decl;
+ symtab_register_node (node);
- node->symbol.order = order;
+ node->order = order;
if (order >= symtab_order)
symtab_order = order + 1;
- node->symbol.lto_file_data = file_data;
+ node->lto_file_data = file_data;
bp = streamer_read_bitpack (ib);
- node->symbol.externally_visible = bp_unpack_value (&bp, 1);
- node->symbol.force_output = bp_unpack_value (&bp, 1);
- node->symbol.forced_by_abi = bp_unpack_value (&bp, 1);
- node->symbol.unique_name = bp_unpack_value (&bp, 1);
- node->symbol.definition = bp_unpack_value (&bp, 1);
- node->symbol.alias = bp_unpack_value (&bp, 1);
- node->symbol.weakref = bp_unpack_value (&bp, 1);
- node->symbol.analyzed = bp_unpack_value (&bp, 1);
- node->symbol.used_from_other_partition = bp_unpack_value (&bp, 1);
- node->symbol.in_other_partition = bp_unpack_value (&bp, 1);
- if (node->symbol.in_other_partition)
+ node->externally_visible = bp_unpack_value (&bp, 1);
+ node->force_output = bp_unpack_value (&bp, 1);
+ node->forced_by_abi = bp_unpack_value (&bp, 1);
+ node->unique_name = bp_unpack_value (&bp, 1);
+ node->definition = bp_unpack_value (&bp, 1);
+ node->alias = bp_unpack_value (&bp, 1);
+ node->weakref = bp_unpack_value (&bp, 1);
+ node->analyzed = bp_unpack_value (&bp, 1);
+ node->used_from_other_partition = bp_unpack_value (&bp, 1);
+ node->in_other_partition = bp_unpack_value (&bp, 1);
+ if (node->in_other_partition)
{
- DECL_EXTERNAL (node->symbol.decl) = 1;
- TREE_STATIC (node->symbol.decl) = 0;
+ DECL_EXTERNAL (node->decl) = 1;
+ TREE_STATIC (node->decl) = 0;
}
- if (node->symbol.alias && !node->symbol.analyzed && node->symbol.weakref)
- node->symbol.alias_target = get_alias_symbol (node->symbol.decl);
+ if (node->alias && !node->analyzed && node->weakref)
+ node->alias_target = get_alias_symbol (node->decl);
ref = streamer_read_hwi (ib);
/* Store a reference for now, and fix up later to be a pointer. */
- node->symbol.same_comdat_group = (symtab_node) (intptr_t) ref;
- node->symbol.resolution = streamer_read_enum (ib, ld_plugin_symbol_resolution,
+ node->same_comdat_group = (symtab_node *) (intptr_t) ref;
+ node->resolution = streamer_read_enum (ib, ld_plugin_symbol_resolution,
LDPR_NUM_KNOWN);
return node;
@@ -1165,10 +1170,10 @@ input_varpool_node (struct lto_file_decl_data *file_data,
static void
input_ref (struct lto_input_block *ib,
- symtab_node referring_node,
- vec<symtab_node> nodes)
+ symtab_node *referring_node,
+ vec<symtab_node *> nodes)
{
- symtab_node node = NULL;
+ symtab_node *node = NULL;
struct bitpack_d bp;
enum ipa_ref_use use;
bool speculative;
@@ -1190,7 +1195,7 @@ input_ref (struct lto_input_block *ib,
indirect_unknown_callee set). */
static void
-input_edge (struct lto_input_block *ib, vec<symtab_node> nodes,
+input_edge (struct lto_input_block *ib, vec<symtab_node *> nodes,
bool indirect)
{
struct cgraph_node *caller, *callee;
@@ -1203,13 +1208,13 @@ input_edge (struct lto_input_block *ib, vec<symtab_node> nodes,
int ecf_flags = 0;
caller = cgraph (nodes[streamer_read_hwi (ib)]);
- if (caller == NULL || caller->symbol.decl == NULL_TREE)
+ if (caller == NULL || caller->decl == NULL_TREE)
internal_error ("bytecode stream: no caller found while reading edge");
if (!indirect)
{
callee = cgraph (nodes[streamer_read_hwi (ib)]);
- if (callee == NULL || callee->symbol.decl == NULL_TREE)
+ if (callee == NULL || callee->decl == NULL_TREE)
internal_error ("bytecode stream: no callee found while reading edge");
}
else
@@ -1257,13 +1262,13 @@ input_edge (struct lto_input_block *ib, vec<symtab_node> nodes,
/* Read a cgraph from IB using the info in FILE_DATA. */
-static vec<symtab_node>
+static vec<symtab_node *>
input_cgraph_1 (struct lto_file_decl_data *file_data,
struct lto_input_block *ib)
{
enum LTO_symtab_tags tag;
- vec<symtab_node> nodes = vNULL;
- symtab_node node;
+ vec<symtab_node *> nodes = vNULL;
+ symtab_node *node;
unsigned i;
tag = streamer_read_enum (ib, LTO_symtab_tags, LTO_symtab_last_tag);
@@ -1276,14 +1281,14 @@ input_cgraph_1 (struct lto_file_decl_data *file_data,
input_edge (ib, nodes, true);
else if (tag == LTO_symtab_variable)
{
- node = (symtab_node)input_varpool_node (file_data, ib);
+ node = input_varpool_node (file_data, ib);
nodes.safe_push (node);
lto_symtab_encoder_encode (file_data->symtab_node_encoder, node);
}
else
{
- node = (symtab_node)input_node (file_data, ib, tag, nodes);
- if (node == NULL || node->symbol.decl == NULL_TREE)
+ node = input_node (file_data, ib, tag, nodes);
+ if (node == NULL || node->decl == NULL_TREE)
internal_error ("bytecode stream: found empty cgraph node");
nodes.safe_push (node);
lto_symtab_encoder_encode (file_data->symtab_node_encoder, node);
@@ -1297,7 +1302,7 @@ input_cgraph_1 (struct lto_file_decl_data *file_data,
/* AUX pointers should be all non-zero for function nodes read from the stream. */
#ifdef ENABLE_CHECKING
FOR_EACH_VEC_ELT (nodes, i, node)
- gcc_assert (node->symbol.aux || !is_a <cgraph_node> (node));
+ gcc_assert (node->aux || !is_a <cgraph_node> (node));
#endif
FOR_EACH_VEC_ELT (nodes, i, node)
{
@@ -1307,9 +1312,9 @@ input_cgraph_1 (struct lto_file_decl_data *file_data,
ref = (int) (intptr_t) cnode->global.inlined_to;
/* We share declaration of builtins, so we may read same node twice. */
- if (!node->symbol.aux)
+ if (!node->aux)
continue;
- node->symbol.aux = NULL;
+ node->aux = NULL;
/* Fixup inlined_to from reference to pointer. */
if (ref != LCC_NOT_FOUND)
@@ -1318,16 +1323,16 @@ input_cgraph_1 (struct lto_file_decl_data *file_data,
cnode->global.inlined_to = NULL;
}
- ref = (int) (intptr_t) node->symbol.same_comdat_group;
+ ref = (int) (intptr_t) node->same_comdat_group;
/* Fixup same_comdat_group from reference to pointer. */
if (ref != LCC_NOT_FOUND)
- node->symbol.same_comdat_group = nodes[ref];
+ node->same_comdat_group = nodes[ref];
else
- node->symbol.same_comdat_group = NULL;
+ node->same_comdat_group = NULL;
}
FOR_EACH_VEC_ELT (nodes, i, node)
- node->symbol.aux = is_a <cgraph_node> (node) ? (void *)1 : NULL;
+ node->aux = is_a <cgraph_node> (node) ? (void *)1 : NULL;
return nodes;
}
@@ -1335,13 +1340,13 @@ input_cgraph_1 (struct lto_file_decl_data *file_data,
static void
input_refs (struct lto_input_block *ib,
- vec<symtab_node> nodes)
+ vec<symtab_node *> nodes)
{
int count;
int idx;
while (true)
{
- symtab_node node;
+ symtab_node *node;
count = streamer_read_uhwi (ib);
if (!count)
break;
@@ -1509,13 +1514,13 @@ merge_profile_summaries (struct lto_file_decl_data **file_data_vec)
During LTRANS we already have values of count_materialization_scale
computed, so just update them. */
FOR_EACH_FUNCTION (node)
- if (node->symbol.lto_file_data
- && node->symbol.lto_file_data->profile_info.runs)
+ if (node->lto_file_data
+ && node->lto_file_data->profile_info.runs)
{
int scale;
scale = RDIV (node->count_materialization_scale * max_runs,
- node->symbol.lto_file_data->profile_info.runs);
+ node->lto_file_data->profile_info.runs);
node->count_materialization_scale = scale;
if (scale < 0)
fatal_error ("Profile information in %s corrupted",
@@ -1545,7 +1550,7 @@ input_symtab (void)
const char *data;
size_t len;
struct lto_input_block *ib;
- vec<symtab_node> nodes;
+ vec<symtab_node *> nodes;
ib = lto_create_simple_input_block (file_data, LTO_section_symtab_nodes,
&data, &len);
@@ -1560,7 +1565,8 @@ input_symtab (void)
ib = lto_create_simple_input_block (file_data, LTO_section_refs,
&data, &len);
if (!ib)
- fatal_error("cannot find LTO section refs in %s", file_data->file_name);
+ fatal_error ("cannot find LTO section refs in %s",
+ file_data->file_name);
input_refs (ib, nodes);
lto_destroy_simple_input_block (file_data, LTO_section_refs,
ib, data, len);
@@ -1582,8 +1588,8 @@ input_symtab (void)
node for the parent function was never emitted to the gimple
file, cgraph_node will create a node for it when setting the
context of the nested function. */
- if (node->symbol.lto_file_data)
- node->symbol.aux = NULL;
+ if (node->lto_file_data)
+ node->aux = NULL;
}
}
@@ -1650,7 +1656,7 @@ output_node_opt_summary (struct output_block *ob,
streamer_write_bitpack (&bp);
}
- if (lto_symtab_encoder_in_partition_p (encoder, (symtab_node) node))
+ if (lto_symtab_encoder_in_partition_p (encoder, node))
{
for (e = node->callees; e; e = e->next_callee)
output_edge_opt_summary (ob, e);
@@ -1675,7 +1681,7 @@ output_cgraph_opt_summary (void)
n_nodes = lto_symtab_encoder_size (encoder);
for (i = 0; i < n_nodes; i++)
{
- symtab_node node = lto_symtab_encoder_deref (encoder, i);
+ symtab_node *node = lto_symtab_encoder_deref (encoder, i);
cgraph_node *cnode = dyn_cast <cgraph_node> (node);
if (cnode && output_cgraph_opt_summary_p (cnode))
count++;
@@ -1683,7 +1689,7 @@ output_cgraph_opt_summary (void)
streamer_write_uhwi (ob, count);
for (i = 0; i < n_nodes; i++)
{
- symtab_node node = lto_symtab_encoder_deref (encoder, i);
+ symtab_node *node = lto_symtab_encoder_deref (encoder, i);
cgraph_node *cnode = dyn_cast <cgraph_node> (node);
if (cnode && output_cgraph_opt_summary_p (cnode))
{
@@ -1756,7 +1762,7 @@ input_node_opt_summary (struct cgraph_node *node,
static void
input_cgraph_opt_section (struct lto_file_decl_data *file_data,
const char *data, size_t len,
- vec<symtab_node> nodes)
+ vec<symtab_node *> nodes)
{
const struct lto_function_header *header =
(const struct lto_function_header *) data;
@@ -1790,7 +1796,7 @@ input_cgraph_opt_section (struct lto_file_decl_data *file_data,
/* Input optimization summary of cgraph. */
static void
-input_cgraph_opt_summary (vec<symtab_node> nodes)
+input_cgraph_opt_summary (vec<symtab_node *> nodes)
{
struct lto_file_decl_data **file_data_vec = lto_get_file_decl_data ();
struct lto_file_decl_data *file_data;
diff --git a/gcc/lto-compress.c b/gcc/lto-compress.c
index 238bb64574e..3a67616cf8b 100644
--- a/gcc/lto-compress.c
+++ b/gcc/lto-compress.c
@@ -28,6 +28,7 @@ along with GCC; see the file COPYING3. If not see
#include <zlib.h>
#include "coretypes.h"
#include "tree.h"
+#include "gimple.h"
#include "diagnostic-core.h"
#include "langhooks.h"
#include "lto-streamer.h"
diff --git a/gcc/lto-opts.c b/gcc/lto-opts.c
index 4d9cdfd07eb..c9d4e03d00c 100644
--- a/gcc/lto-opts.c
+++ b/gcc/lto-opts.c
@@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. If not see
#include "system.h"
#include "coretypes.h"
#include "tree.h"
+#include "gimple.h"
#include "hashtab.h"
#include "ggc.h"
#include "vec.h"
@@ -76,7 +77,7 @@ lto_write_options (void)
obstack_init (&temporary_obstack);
- /* Output options that affect GIMPLE IL semantics and are implicitely
+ /* Output options that affect GIMPLE IL semantics and are implicitly
enabled by the frontend.
This for now includes an explicit set of options that we also handle
explicitly in lto-wrapper.c. In the end the effects on GIMPLE IL
@@ -87,8 +88,13 @@ lto_write_options (void)
if (global_options.x_flag_exceptions)
append_to_collect_gcc_options (&temporary_obstack, &first_p,
"-fexceptions");
+ /* -fnon-call-exceptions changes the generation of exception
+ regions. It is enabled implicitly by the Go frontend. */
+ if (global_options.x_flag_non_call_exceptions)
+ append_to_collect_gcc_options (&temporary_obstack, &first_p,
+ "-fnon-call-exceptions");
- /* Output explicitely passed options. */
+ /* Output explicitly passed options. */
for (i = 1; i < save_decoded_options_count; ++i)
{
struct cl_decoded_option *option = &save_decoded_options[i];
diff --git a/gcc/lto-section-in.c b/gcc/lto-section-in.c
index d96cdb47548..e4f0aedfa0f 100644
--- a/gcc/lto-section-in.c
+++ b/gcc/lto-section-in.c
@@ -24,14 +24,13 @@ along with GCC; see the file COPYING3. If not see
#include "coretypes.h"
#include "tm.h"
#include "tree.h"
+#include "gimple.h"
#include "expr.h"
#include "flags.h"
#include "params.h"
#include "input.h"
#include "hashtab.h"
#include "basic-block.h"
-#include "tree-ssa.h"
-#include "cgraph.h"
#include "function.h"
#include "ggc.h"
#include "diagnostic-core.h"
@@ -429,24 +428,24 @@ lto_free_function_in_decl_state (struct lto_in_decl_state *state)
release trees needed by the NODE's body. */
void
-lto_free_function_in_decl_state_for_node (symtab_node node)
+lto_free_function_in_decl_state_for_node (symtab_node *node)
{
struct lto_in_decl_state temp;
void **slot;
- if (!node->symbol.lto_file_data)
+ if (!node->lto_file_data)
return;
- temp.fn_decl = node->symbol.decl;
- slot = htab_find_slot (node->symbol.lto_file_data->function_decl_states,
+ temp.fn_decl = node->decl;
+ slot = htab_find_slot (node->lto_file_data->function_decl_states,
&temp, NO_INSERT);
if (slot && *slot)
{
lto_free_function_in_decl_state ((struct lto_in_decl_state*) *slot);
- htab_clear_slot (node->symbol.lto_file_data->function_decl_states,
+ htab_clear_slot (node->lto_file_data->function_decl_states,
slot);
}
- node->symbol.lto_file_data = NULL;
+ node->lto_file_data = NULL;
}
diff --git a/gcc/lto-section-out.c b/gcc/lto-section-out.c
index 59eed716630..4a2867376d5 100644
--- a/gcc/lto-section-out.c
+++ b/gcc/lto-section-out.c
@@ -24,19 +24,17 @@ along with GCC; see the file COPYING3. If not see
#include "coretypes.h"
#include "tm.h"
#include "tree.h"
+#include "gimple.h"
#include "expr.h"
#include "params.h"
#include "input.h"
#include "hashtab.h"
#include "basic-block.h"
-#include "tree-ssa.h"
-#include "cgraph.h"
#include "function.h"
#include "ggc.h"
#include "except.h"
#include "vec.h"
#include "pointer-set.h"
-#include "bitmap.h"
#include "langhooks.h"
#include "data-streamer.h"
#include "lto-streamer.h"
diff --git a/gcc/lto-streamer-in.c b/gcc/lto-streamer-in.c
index 78957565edb..d4a52a76671 100644
--- a/gcc/lto-streamer-in.c
+++ b/gcc/lto-streamer-in.c
@@ -32,9 +32,14 @@ along with GCC; see the file COPYING3. If not see
#include "input.h"
#include "hashtab.h"
#include "basic-block.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-cfg.h"
+#include "tree-ssanames.h"
+#include "tree-into-ssa.h"
+#include "tree-dfa.h"
#include "tree-ssa.h"
#include "tree-pass.h"
-#include "cgraph.h"
#include "function.h"
#include "ggc.h"
#include "diagnostic.h"
@@ -652,7 +657,7 @@ input_cfg (struct lto_input_block *ib, struct function *fn,
index = streamer_read_hwi (ib);
}
- p_bb = ENTRY_BLOCK_PTR_FOR_FUNCTION(fn);
+ p_bb = ENTRY_BLOCK_PTR_FOR_FUNCTION (fn);
index = streamer_read_hwi (ib);
while (index != -1)
{
@@ -779,7 +784,7 @@ fixup_call_stmt_edges_1 (struct cgraph_node *node, gimple *stmts,
fatal_error ("Cgraph edge statement index not found");
}
for (i = 0;
- ipa_ref_list_reference_iterate (&node->symbol.ref_list, i, ref);
+ ipa_ref_list_reference_iterate (&node->ref_list, i, ref);
i++)
if (ref->lto_stmt_uid)
{
@@ -802,7 +807,7 @@ fixup_call_stmt_edges (struct cgraph_node *orig, gimple *stmts)
while (orig->clone_of)
orig = orig->clone_of;
- fn = DECL_STRUCT_FUNCTION (orig->symbol.decl);
+ fn = DECL_STRUCT_FUNCTION (orig->decl);
fixup_call_stmt_edges_1 (orig, stmts, fn);
if (orig->clones)
@@ -1019,7 +1024,7 @@ lto_read_body (struct lto_file_decl_data *file_data, struct cgraph_node *node,
int string_offset;
struct lto_input_block ib_cfg;
struct lto_input_block ib_main;
- tree fn_decl = node->symbol.decl;
+ tree fn_decl = node->decl;
header = (const struct lto_function_header *) data;
cfg_offset = sizeof (struct lto_function_header);
diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c
index 8f823f2c712..55186234d8c 100644
--- a/gcc/lto-streamer-out.c
+++ b/gcc/lto-streamer-out.c
@@ -31,9 +31,10 @@ along with GCC; see the file COPYING3. If not see
#include "input.h"
#include "hashtab.h"
#include "basic-block.h"
-#include "tree-ssa.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-ssanames.h"
#include "tree-pass.h"
-#include "cgraph.h"
#include "function.h"
#include "ggc.h"
#include "diagnostic-core.h"
@@ -367,7 +368,7 @@ lto_write_tree (struct output_block *ob, tree expr, bool ref_p)
{
if (!lto_is_streamable (expr))
internal_error ("tree code %qs is not supported in LTO streams",
- tree_code_name[TREE_CODE (expr)]);
+ get_tree_code_name (TREE_CODE (expr)));
/* Write the header, containing everything needed to materialize
EXPR on the reading side. */
@@ -1241,7 +1242,7 @@ DFS_write_tree (struct output_block *ob, sccs *from_state,
if (!lto_is_streamable (t))
internal_error ("tree code %qs is not supported "
"in LTO streams",
- tree_code_name[TREE_CODE (t)]);
+ get_tree_code_name (TREE_CODE (t)));
gcc_checking_assert (!streamer_handle_as_builtin_p (t));
@@ -1750,7 +1751,7 @@ output_function (struct cgraph_node *node)
basic_block bb;
struct output_block *ob;
- function = node->symbol.decl;
+ function = node->decl;
fn = DECL_STRUCT_FUNCTION (function);
ob = create_output_block (LTO_section_function_body);
@@ -1909,8 +1910,8 @@ lto_output_toplevel_asms (void)
static void
copy_function (struct cgraph_node *node)
{
- tree function = node->symbol.decl;
- struct lto_file_decl_data *file_data = node->symbol.lto_file_data;
+ tree function = node->decl;
+ struct lto_file_decl_data *file_data = node->lto_file_data;
struct lto_output_stream *output_stream = XCNEW (struct lto_output_stream);
const char *data;
size_t len;
@@ -1937,7 +1938,7 @@ copy_function (struct cgraph_node *node)
/* Copy decls. */
in_state =
- lto_get_function_in_decl_state (node->symbol.lto_file_data, function);
+ lto_get_function_in_decl_state (node->lto_file_data, function);
gcc_assert (in_state);
for (i = 0; i < LTO_N_DECL_STREAMS; i++)
@@ -1981,25 +1982,25 @@ lto_output (void)
/* Process only the functions with bodies. */
for (i = 0; i < n_nodes; i++)
{
- symtab_node snode = lto_symtab_encoder_deref (encoder, i);
+ symtab_node *snode = lto_symtab_encoder_deref (encoder, i);
cgraph_node *node = dyn_cast <cgraph_node> (snode);
if (node
&& lto_symtab_encoder_encode_body_p (encoder, node)
- && !node->symbol.alias)
+ && !node->alias)
{
#ifdef ENABLE_CHECKING
- gcc_assert (!bitmap_bit_p (output, DECL_UID (node->symbol.decl)));
- bitmap_set_bit (output, DECL_UID (node->symbol.decl));
+ gcc_assert (!bitmap_bit_p (output, DECL_UID (node->decl)));
+ bitmap_set_bit (output, DECL_UID (node->decl));
#endif
decl_state = lto_new_out_decl_state ();
lto_push_out_decl_state (decl_state);
- if (gimple_has_body_p (node->symbol.decl) || !flag_wpa)
+ if (gimple_has_body_p (node->decl) || !flag_wpa)
output_function (node);
else
copy_function (node);
gcc_assert (lto_get_out_decl_state () == decl_state);
lto_pop_out_decl_state ();
- lto_record_function_out_decl_state (node->symbol.decl, decl_state);
+ lto_record_function_out_decl_state (node->decl, decl_state);
}
}
@@ -2034,17 +2035,17 @@ const pass_data pass_data_ipa_lto_gimple_out =
class pass_ipa_lto_gimple_out : public ipa_opt_pass_d
{
public:
- pass_ipa_lto_gimple_out(gcc::context *ctxt)
- : ipa_opt_pass_d(pass_data_ipa_lto_gimple_out, ctxt,
- NULL, /* generate_summary */
- lto_output, /* write_summary */
- NULL, /* read_summary */
- lto_output, /* write_optimization_summary */
- NULL, /* read_optimization_summary */
- NULL, /* stmt_fixup */
- 0, /* function_transform_todo_flags_start */
- NULL, /* function_transform */
- NULL) /* variable_transform */
+ pass_ipa_lto_gimple_out (gcc::context *ctxt)
+ : ipa_opt_pass_d (pass_data_ipa_lto_gimple_out, ctxt,
+ NULL, /* generate_summary */
+ lto_output, /* write_summary */
+ NULL, /* read_summary */
+ lto_output, /* write_optimization_summary */
+ NULL, /* read_optimization_summary */
+ NULL, /* stmt_fixup */
+ 0, /* function_transform_todo_flags_start */
+ NULL, /* function_transform */
+ NULL) /* variable_transform */
{}
/* opt_pass methods: */
@@ -2231,10 +2232,10 @@ write_symbol (struct streamer_tree_cache_d *cache,
/* When something is defined, it should have node attached. */
gcc_assert (alias || TREE_CODE (t) != VAR_DECL
- || varpool_get_node (t)->symbol.definition);
+ || varpool_get_node (t)->definition);
gcc_assert (alias || TREE_CODE (t) != FUNCTION_DECL
|| (cgraph_get_node (t)
- && cgraph_get_node (t)->symbol.definition));
+ && cgraph_get_node (t)->definition));
}
/* Imitate what default_elf_asm_output_external do.
@@ -2248,7 +2249,7 @@ write_symbol (struct streamer_tree_cache_d *cache,
&& !targetm.binds_local_p (t))
visibility = GCCPV_DEFAULT;
else
- switch (DECL_VISIBILITY(t))
+ switch (DECL_VISIBILITY (t))
{
case VISIBILITY_DEFAULT:
visibility = GCCPV_DEFAULT;
@@ -2289,7 +2290,7 @@ write_symbol (struct streamer_tree_cache_d *cache,
/* Return true if NODE should appear in the plugin symbol table. */
bool
-output_symbol_p (symtab_node node)
+output_symbol_p (symtab_node *node)
{
struct cgraph_node *cnode;
if (!symtab_real_symbol_p (node))
@@ -2298,7 +2299,7 @@ output_symbol_p (symtab_node node)
and devirtualization. We do not want to see them in symbol table as
references unless they are really used. */
cnode = dyn_cast <cgraph_node> (node);
- if (cnode && (!node->symbol.definition || DECL_EXTERNAL (cnode->symbol.decl))
+ if (cnode && (!node->definition || DECL_EXTERNAL (cnode->decl))
&& cnode->callers)
return true;
@@ -2306,18 +2307,18 @@ output_symbol_p (symtab_node node)
part of the compilation unit until they are used by folding. Some symbols,
like references to external construction vtables can not be referred to at all.
We decide this at can_refer_decl_in_current_unit_p. */
- if (!node->symbol.definition || DECL_EXTERNAL (node->symbol.decl))
+ if (!node->definition || DECL_EXTERNAL (node->decl))
{
int i;
struct ipa_ref *ref;
- for (i = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list,
+ for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list,
i, ref); i++)
{
if (ref->use == IPA_REF_ALIAS)
continue;
if (is_a <cgraph_node> (ref->referring))
return true;
- if (!DECL_EXTERNAL (ref->referring->symbol.decl))
+ if (!DECL_EXTERNAL (ref->referring->decl))
return true;
}
return false;
@@ -2351,20 +2352,20 @@ produce_symtab (struct output_block *ob)
for (lsei = lsei_start (encoder);
!lsei_end_p (lsei); lsei_next (&lsei))
{
- symtab_node node = lsei_node (lsei);
+ symtab_node *node = lsei_node (lsei);
- if (!output_symbol_p (node) || DECL_EXTERNAL (node->symbol.decl))
+ if (!output_symbol_p (node) || DECL_EXTERNAL (node->decl))
continue;
- write_symbol (cache, &stream, node->symbol.decl, seen, false);
+ write_symbol (cache, &stream, node->decl, seen, false);
}
for (lsei = lsei_start (encoder);
!lsei_end_p (lsei); lsei_next (&lsei))
{
- symtab_node node = lsei_node (lsei);
+ symtab_node *node = lsei_node (lsei);
- if (!output_symbol_p (node) || !DECL_EXTERNAL (node->symbol.decl))
+ if (!output_symbol_p (node) || !DECL_EXTERNAL (node->decl))
continue;
- write_symbol (cache, &stream, node->symbol.decl, seen, false);
+ write_symbol (cache, &stream, node->decl, seen, false);
}
lto_write_stream (&stream);
@@ -2458,7 +2459,7 @@ produce_asm_for_decls (void)
lto_output_decl_state_refs (ob, decl_state_stream, fn_out_state);
}
lto_write_stream (decl_state_stream);
- free(decl_state_stream);
+ free (decl_state_stream);
lto_write_stream (ob->main_stream);
lto_write_stream (ob->string_stream);
@@ -2506,17 +2507,17 @@ const pass_data pass_data_ipa_lto_finish_out =
class pass_ipa_lto_finish_out : public ipa_opt_pass_d
{
public:
- pass_ipa_lto_finish_out(gcc::context *ctxt)
- : ipa_opt_pass_d(pass_data_ipa_lto_finish_out, ctxt,
- NULL, /* generate_summary */
- produce_asm_for_decls, /* write_summary */
- NULL, /* read_summary */
- produce_asm_for_decls, /* write_optimization_summary */
- NULL, /* read_optimization_summary */
- NULL, /* stmt_fixup */
- 0, /* function_transform_todo_flags_start */
- NULL, /* function_transform */
- NULL) /* variable_transform */
+ pass_ipa_lto_finish_out (gcc::context *ctxt)
+ : ipa_opt_pass_d (pass_data_ipa_lto_finish_out, ctxt,
+ NULL, /* generate_summary */
+ produce_asm_for_decls, /* write_summary */
+ NULL, /* read_summary */
+ produce_asm_for_decls, /* write_optimization_summary */
+ NULL, /* read_optimization_summary */
+ NULL, /* stmt_fixup */
+ 0, /* function_transform_todo_flags_start */
+ NULL, /* function_transform */
+ NULL) /* variable_transform */
{}
/* opt_pass methods: */
diff --git a/gcc/lto-streamer.c b/gcc/lto-streamer.c
index cdc75de9bae..1540e4c4be8 100644
--- a/gcc/lto-streamer.c
+++ b/gcc/lto-streamer.c
@@ -28,9 +28,8 @@ along with GCC; see the file COPYING3. If not see
#include "flags.h"
#include "tree.h"
#include "gimple.h"
-#include "tree-ssa.h"
-#include "diagnostic-core.h"
#include "bitmap.h"
+#include "diagnostic-core.h"
#include "vec.h"
#include "tree-streamer.h"
#include "lto-streamer.h"
@@ -54,7 +53,7 @@ lto_tag_name (enum LTO_tags tag)
{
/* For tags representing tree nodes, return the name of the
associated tree code. */
- return tree_code_name[lto_tag_to_tree_code (tag)];
+ return get_tree_code_name (lto_tag_to_tree_code (tag));
}
if (lto_tag_is_gimple_code_p (tag))
@@ -199,7 +198,7 @@ print_lto_report (const char *s)
if (lto_stats.num_trees[i])
fprintf (stderr, "[%s] # of '%s' objects read: "
HOST_WIDE_INT_PRINT_UNSIGNED "\n", s,
- tree_code_name[i], lto_stats.num_trees[i]);
+ get_tree_code_name ((enum tree_code) i), lto_stats.num_trees[i]);
if (flag_lto)
{
diff --git a/gcc/lto-streamer.h b/gcc/lto-streamer.h
index 13a9593a866..797e92e335b 100644
--- a/gcc/lto-streamer.h
+++ b/gcc/lto-streamer.h
@@ -25,8 +25,6 @@ along with GCC; see the file COPYING3. If not see
#include "plugin-api.h"
#include "hash-table.h"
-#include "tree.h"
-#include "gimple.h"
#include "target.h"
#include "cgraph.h"
#include "vec.h"
@@ -432,7 +430,7 @@ struct lto_stats_d
/* Entry of LTO symtab encoder. */
typedef struct
{
- symtab_node node;
+ 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;
@@ -775,7 +773,7 @@ extern int lto_eq_in_decl_state (const void *, const void *);
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_free_function_in_decl_state_for_node (symtab_node *);
extern void lto_section_overrun (struct lto_input_block *) ATTRIBUTE_NORETURN;
extern void lto_value_range_error (const char *,
HOST_WIDE_INT, HOST_WIDE_INT,
@@ -874,15 +872,15 @@ void lto_output_location (struct output_block *, struct bitpack_d *, location_t)
/* In lto-cgraph.c */
lto_symtab_encoder_t lto_symtab_encoder_new (bool);
-int lto_symtab_encoder_encode (lto_symtab_encoder_t, symtab_node);
+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_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);
+ symtab_node *);
void lto_set_symtab_encoder_in_partition (lto_symtab_encoder_t,
- symtab_node);
+ symtab_node *);
bool lto_symtab_encoder_encode_initializer_p (lto_symtab_encoder_t,
struct varpool_node *);
@@ -1045,7 +1043,7 @@ lto_symtab_encoder_size (lto_symtab_encoder_t encoder)
static inline int
lto_symtab_encoder_lookup (lto_symtab_encoder_t encoder,
- symtab_node node)
+ symtab_node *node)
{
void **slot = pointer_map_contains (encoder->map, node);
return (slot && *slot ? (size_t) *(slot) - 1 : LCC_NOT_FOUND);
@@ -1066,7 +1064,7 @@ lsei_next (lto_symtab_encoder_iterator *lsei)
}
/* Return the node pointed to by LSI. */
-static inline symtab_node
+static inline symtab_node *
lsei_node (lto_symtab_encoder_iterator lsei)
{
return lsei.encoder->nodes[lsei.index].node;
@@ -1088,7 +1086,7 @@ lsei_varpool_node (lto_symtab_encoder_iterator lsei)
/* Return the cgraph node corresponding to REF using ENCODER. */
-static inline symtab_node
+static inline symtab_node *
lto_symtab_encoder_deref (lto_symtab_encoder_t encoder, int ref)
{
if (ref == LCC_NOT_FOUND)
diff --git a/gcc/lto-wrapper.c b/gcc/lto-wrapper.c
index 15a34dd6956..57978c883d4 100644
--- a/gcc/lto-wrapper.c
+++ b/gcc/lto-wrapper.c
@@ -409,6 +409,7 @@ merge_and_complain (struct cl_decoded_option **decoded_options,
case OPT_fpie:
case OPT_fcommon:
case OPT_fexceptions:
+ case OPT_fnon_call_exceptions:
case OPT_fgnu_tm:
/* Do what the old LTO code did - collect exactly one option
setting per OPT code, we pick the first we encounter.
@@ -573,6 +574,7 @@ run_gcc (unsigned argc, char *argv[])
case OPT_fpie:
case OPT_fcommon:
case OPT_fexceptions:
+ case OPT_fnon_call_exceptions:
case OPT_fgnu_tm:
case OPT_freg_struct_return:
case OPT_fpcc_struct_return:
@@ -744,7 +746,7 @@ run_gcc (unsigned argc, char *argv[])
if (lto_mode == LTO_MODE_LTO)
{
- printf("%s\n", flto_out);
+ printf ("%s\n", flto_out);
free (flto_out);
flto_out = NULL;
}
@@ -820,9 +822,9 @@ cont:
{
char *dumpbase
= (char *) xmalloc (strlen (linker_output)
- + sizeof(DUMPBASE_SUFFIX) + 1);
+ + sizeof (DUMPBASE_SUFFIX) + 1);
snprintf (dumpbase,
- strlen (linker_output) + sizeof(DUMPBASE_SUFFIX),
+ strlen (linker_output) + sizeof (DUMPBASE_SUFFIX),
"%s.ltrans%u", linker_output, i);
argv_ptr[0] = dumpbase;
}
diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog
index 8ac0f8d60a4..b3bed0b3921 100644
--- a/gcc/lto/ChangeLog
+++ b/gcc/lto/ChangeLog
@@ -1,3 +1,176 @@
+2013-10-31 David Malcolm <dmalcolm@redhat.com>
+
+ Automated part of renaming of symtab_node_base to symtab_node.
+
+ Patch autogenerated by rename_symtab.py from
+ https://github.com/davidmalcolm/gcc-refactoring-scripts
+ revision 58bb219cc090b2f4516a9297d868c245495ee622
+
+ * lto-partition.c (add_symbol_to_partition): Rename
+ symtab_node_base to symtab_node.
+ (get_symbol_class): Likewise.
+ (symbol_partitioned_p): Likewise.
+ (add_references_to_partition): Likewise.
+ (add_symbol_to_partition_1): Likewise.
+ (contained_in_symbol): Likewise.
+ (add_symbol_to_partition): Likewise.
+ (lto_1_to_1_map): Likewise.
+ (lto_max_map): Likewise.
+ (lto_balanced_map): Likewise.
+ (privatize_symbol_name): Likewise.
+ (promote_symbol): Likewise.
+ (may_need_named_section_p): Likewise.
+ (rename_statics): Likewise.
+ (lto_promote_statics_nonwpa): Likewise.
+ * lto-symtab.c (lto_symtab_merge): Likewise.
+ (lto_symtab_resolve_replaceable_p): Likewise.
+ (lto_symtab_symbol_p): Likewise.
+ (lto_symtab_resolve_can_prevail_p): Likewise.
+ (lto_symtab_resolve_symbols): Likewise.
+ (lto_symtab_merge_decls_2): Likewise.
+ (lto_symtab_merge_decls_1): Likewise.
+ (lto_symtab_merge_decls): Likewise.
+ (lto_symtab_merge_symbols_1): Likewise.
+ (lto_symtab_merge_symbols): Likewise.
+ (lto_symtab_prevailing_decl): Likewise.
+ * lto.c (lto_wpa_write_files): Likewise.
+ (read_cgraph_and_symbols): Likewise.
+ (do_whole_program_analysis): Likewise.
+
+2013-10-30 David Malcolm <dmalcolm@redhat.com>
+
+ * lto-symtab.c (lto_symtab_merge_decls_2): Split symtab_node
+ declarations onto multiple lines to make things easier for
+ rename_symtab.py.
+ (lto_symtab_merge_decls_1): Likewise.
+ (lto_symtab_merge_symbols_1): Likewise.
+
+2013-10-29 Balaji V. Iyer <balaji.v.iyer@intel.com>
+
+ * Make-lang.in (lto/lto-lang.o): Added cilk.h in dependency list.
+ * lto-lang.c (lto_init): Added a call to cilk_init_builtins if Cilk
+ Plus is enabled.
+
+2013-10-29 David Malcolm <dmalcolm@redhat.com>
+
+ Patch autogenerated by refactor_symtab.py from
+ https://github.com/davidmalcolm/gcc-refactoring-scripts
+ revision 58bb219cc090b2f4516a9297d868c245495ee622
+
+ * lto-partition.c (lto_promote_cross_file_statics): Update for
+ conversion of symtab types to a true class hierarchy.
+ (rename_statics): Likewise.
+ (promote_symbol): Likewise.
+ (privatize_symbol_name): Likewise.
+ (lto_balanced_map): Likewise.
+ (varpool_node_cmp): Likewise.
+ (node_cmp): Likewise.
+ (lto_1_to_1_map): Likewise.
+ (undo_partition): Likewise.
+ (add_symbol_to_partition): Likewise.
+ (contained_in_symbol): Likewise.
+ (add_symbol_to_partition_1): Likewise.
+ (add_references_to_partition): Likewise.
+ (symbol_partitioned_p): Likewise.
+ (get_symbol_class): Likewise.
+ (lto_max_map): Likewise.
+ * lto-symtab.c (lto_symtab_prevailing_decl): Likewise.
+ (lto_symtab_merge_symbols): Likewise.
+ (lto_symtab_merge_symbols_1): Likewise.
+ (lto_symtab_merge_decls): Likewise.
+ (lto_symtab_merge_decls_1): Likewise.
+ (lto_symtab_merge_decls_2): Likewise.
+ (lto_symtab_resolve_symbols): Likewise.
+ (lto_symtab_resolve_can_prevail_p): Likewise.
+ (lto_symtab_symbol_p): Likewise.
+ (lto_symtab_resolve_replaceable_p): Likewise.
+ (lto_symtab_merge): Likewise.
+ (lto_varpool_replace_node): Likewise.
+ (lto_cgraph_replace_node): Likewise.
+ * lto.c (lto_main): Likewise.
+ (do_whole_program_analysis): Likewise.
+ (materialize_cgraph): Likewise.
+ (read_cgraph_and_symbols): Likewise.
+ (cmp_partitions_order): Likewise.
+ (lto_materialize_function): Likewise.
+ (has_analyzed_clone_p): Likewise.
+
+2013-10-29 Andrew MacLeod <amacleod@redhat.com>
+
+ * lto/lto-object.c: Add gimple.h to include list.
+ * lto/lto-partition.c: Likewise.
+
+2013-10-18 Andrew MacLeod <amacleod@redhat.com>
+
+ * lto.c: Remove tree-flow.h from include list.
+
+2013-10-15 Richard Biener <rguenther@suse.de>
+
+ * lto.c (hash_canonical_type): Split out from ...
+ (iterative_hash_canonical_type): ... here. Register types
+ we recurse to.
+ (gimple_canonical_type_hash): Adjust.
+ (gimple_register_canonical_type_1): Split out from ...
+ (gimple_register_canonical_type): ... here. Cache computed
+ hash value.
+ (lto_register_canonical_types): Split into two modes,
+ clearing and computing TYPE_CANONICAL.
+ (lto_read_decls): Adjust.
+ (read_cgraph_and_symbols): Do two passes over global trees,
+ first clearing then computing TYPE_CANONICAL.
+
+2013-10-14 Richard Biener <rguenther@suse.de>
+
+ * lto.c (gimple_canonical_types): Move out-of GC space.
+ (canonical_type_hash_cache): Make a pointer-map.
+ (num_canonical_type_hash_entries, num_canonical_type_hash_queries):
+ New counters.
+ (iterative_hash_canonical_type): Adjust.
+ (read_cgraph_and_symbols): Likewise.
+ (print_lto_report_1): Likewise.
+
+2013-10-14 Richard Biener <rguenther@suse.de>
+
+ * lto.c (gimple_types, type_hash_cache, struct type_pair_d,
+ type_pair_cache, lookup_type_pair, struct sccs, next_dfs_num,
+ gtc_next_dfs_num, compare_type_names_p, gtc_visit,
+ gimple_types_compatible_p_1, gimple_types_compatible_p,
+ visit, iterative_hash_name, struct type_hash_pair,
+ type_hash_pair_compare, iterative_hash_gimple_type, gimple_type_hash,
+ gimple_type_eq, gimple_register_type, num_not_merged_types,
+ num_not_merged_types_in_same_scc, num_not_merged_types_trees,
+ num_not_merged_types_in_same_scc_trees): Remove old merging code
+ and statistics.
+ (lto_read_decls): Do not run old merging code in parallel.
+ (read_cgraph_and_symbols): Do not init/free old merging
+ data structures.
+ (print_lto_report_1): Do not report differences of old vs. new
+ merging code.
+
+2013-10-14 Richard Biener <rguenther@suse.de>
+
+ * lto-lang.c (lto_init): Do not re-init canonical types here.
+ (lto_register_canonical_types): Move to ...
+ * lto.c (lto_register_canonical_types): ... here.
+ (gimple_canonical_types, canonical_type_hash_cache,
+ iterative_hash_canonical_type, gimple_canonical_type_hash,
+ gimple_canonical_types_compatible_p, gimple_canonical_type_eq,
+ gimple_register_canonical_type): Add canonical type merging machinery
+ moved from gimple.c.
+ (read_cgraph_and_symbols): Init and free canonical type tables
+ here.
+ (print_lto_report_1): Report canonical type table stats here.
+
+2013-10-11 Jakub Jelinek <jakub@redhat.com>
+
+ * lto-lang.c (DEF_FUNCTION_TYPE_8): Define.
+
+2013-09-25 Tom Tromey <tromey@redhat.com>
+
+ * Make-lang.in (LTO_H, LINKER_PLUGIN_API_H, LTO_TREE_H)
+ (lto/lto-lang.o, lto/lto.o, lto/lto-partition.o)
+ (lto/lto-object.o): Remove.
+
2013-09-06 Richard Biener <rguenther@suse.de>
* lto-symtab.c: Move from gcc/
@@ -170,7 +343,7 @@
lto_register_function_decl_in_symtab): Update.
(read_cgraph_and_symbols): Update resolution_map handling.
-2013-06-11 Jan Hubicka <jh@suse.cz>
+2013-06-11 Jan Hubicka <jh@suse.cz>
* lto-partition.c (get_symbol_class): Simplify weakref handling.
(add_symbol_to_partition_1): Likewise.
@@ -633,7 +806,7 @@
builtins on the fly in the future. Change all uses, and poison
the old names. Make sure 0 is not a legitimate builtin index.
-2011-10-02 Andi Kleen <ak@linux.intel.com>
+2011-10-02 Andi Kleen <ak@linux.intel.com>
* lto-object.c (lto_obj_add_section_data): Add list.
(lto_obj_add_section): Fill in list.
@@ -672,7 +845,7 @@
lto_splay_tree_insert.
(lto_file_read): Use lto_splay_tree_new.
-2011-09-26 Andi Kleen <ak@linux.intel.com>
+2011-09-26 Andi Kleen <ak@linux.intel.com>
* lto.c (lto_resolution_read): Remove id dumping.
(lto_section_with_id): Turn id HOST_WIDE_ID.
@@ -1047,7 +1220,7 @@
* lto.c (lto_balanced_map): Do not produce empty partitions.
-2010-10-06 Andi Kleen <ak@linux.intel.com>
+2010-10-06 Andi Kleen <ak@linux.intel.com>
* lto.c (lto_process_name): Add.
(lto_main): Call lto_process_name.
@@ -1073,11 +1246,11 @@
(do_whole_program_analysis): Chose proper partitioning alg.
* Make-lang.in (lto.o): Add dependency on params.h
-2010-10-04 Andi Kleen <ak@linux.intel.com>
+2010-10-04 Andi Kleen <ak@linux.intel.com>
* Make-lang.in (lto1): Add + to build rule.
-2010-10-03 Andi Kleen <ak@linux.intel.com>
+2010-10-03 Andi Kleen <ak@linux.intel.com>
* lto.c (lto_file_finalize): Replace gcc_assert for missing section
with fatal_error.
@@ -1163,7 +1336,7 @@
* lto.c: Use FOR_EACH_VEC_ELT.
-2010-07-27 Andi Kleen <ak@linux.intel.com>
+2010-07-27 Andi Kleen <ak@linux.intel.com>
* Make-lang.in (lto.o): Add dependency to splay-tree.h
@@ -1180,7 +1353,7 @@
(LANG_HOOKS_OPTION_LANG_MASK, LANG_HOOKS_COMPLAIN_WRONG_LANG_P):
Define.
-2010-07-10 Andi Kleen <ak@linux.intel.com>
+2010-07-10 Andi Kleen <ak@linux.intel.com>
PR lto/44992
* lto.c: Include splay-tree.h
@@ -1196,7 +1369,7 @@
(lto_flatten_file): Add.
(read_cgraph_and_symbols): Handle linked lists of file_datas.
-2010-07-10 Andi Kleen <ak@linux.intel.com>
+2010-07-10 Andi Kleen <ak@linux.intel.com>
* lto-coff.c (hash_name, eq_name): Move.
(lto_obj_build_section_table): Call lto_obj_create_section_hash_table.
diff --git a/gcc/lto/Make-lang.in b/gcc/lto/Make-lang.in
index c67c58e7f83..66b0015f2bd 100644
--- a/gcc/lto/Make-lang.in
+++ b/gcc/lto/Make-lang.in
@@ -23,10 +23,7 @@
LTO_EXE = lto1$(exeext)
# The LTO-specific object files inclued in $(LTO_EXE).
LTO_OBJS = lto/lto-lang.o lto/lto.o lto/lto-object.o attribs.o lto/lto-partition.o lto/lto-symtab.o
-LTO_H = lto/lto.h $(HASHTAB_H)
-LINKER_PLUGIN_API_H = $(srcdir)/../include/plugin-api.h
-LTO_TREE_H = lto/lto-tree.h $(LINKER_PLUGIN_API_H)
-
+lto_OBJS = $(LTO_OBJS)
# Rules
@@ -74,30 +71,5 @@ $(LTO_EXE): $(LTO_OBJS) $(BACKEND) $(LIBDEPS)
+$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
$(LTO_OBJS) $(BACKEND) $(BACKENDLIBS) $(LIBS)
-# Dependencies
-lto/lto-lang.o: lto/lto-lang.c $(CONFIG_H) coretypes.h debug.h \
- flags.h $(GGC_H) langhooks.h $(LANGHOOKS_DEF_H) $(SYSTEM_H) \
- $(TARGET_H) $(LTO_H) $(GIMPLE_H) gtype-lto.h gt-lto-lto-lang.h \
- $(EXPR_H) $(LTO_STREAMER_H)
-lto/lto.o: lto/lto.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(OPTS_H) \
- toplev.h $(TREE_H) $(TREE_FLOW_H) $(DIAGNOSTIC_CORE_H) $(TM_H) \
- $(CGRAPH_H) $(GGC_H) tree-ssa-operands.h $(TREE_PASS_H) \
- langhooks.h $(VEC_H) $(BITMAP_H) pointer-set.h $(IPA_PROP_H) \
- $(COMMON_H) debug.h $(GIMPLE_H) $(LTO_H) $(LTO_TREE_H) \
- $(LTO_TAGS_H) $(LTO_STREAMER_H) $(SPLAY_TREE_H) gt-lto-lto.h \
- $(TREE_STREAMER_H) $(DATA_STREAMER_H) lto/lto-partition.h \
- $(CONTEXT_H) $(PIPELINE_H)
-lto/lto-partition.o: lto/lto-partition.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- toplev.h $(TREE_H) $(TM_H) \
- $(CGRAPH_H) $(TIMEVAR_H) \
- $(LTO_STREAMER_H) $(SPLAY_TREE_H) gt-lto-lto.h $(PARAMS_H) \
- ipa-inline.h $(IPA_UTILS_H) lto/lto-partition.h
-lto/lto-object.o: lto/lto-object.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(DIAGNOSTIC_CORE_H) $(LTO_H) $(TM_H) $(LTO_STREAMER_H) \
- ../include/simple-object.h
-lto/lto-symtab.o: lto/lto-symtab.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TREE_H) $(GIMPLE_H) $(GGC_H) $(HASHTAB_H) \
- $(LTO_STREAMER_H) $(LINKER_PLUGIN_API_H)
-
# LTO testing is done as part of C/C++/Fortran etc. testing.
check-lto:
diff --git a/gcc/lto/lto-lang.c b/gcc/lto/lto-lang.c
index 87a756d5763..b56c22b8a87 100644
--- a/gcc/lto/lto-lang.c
+++ b/gcc/lto/lto-lang.c
@@ -35,6 +35,7 @@ along with GCC; see the file COPYING3. If not see
#include "diagnostic-core.h"
#include "toplev.h"
#include "lto-streamer.h"
+#include "cilk.h"
static tree lto_type_for_size (unsigned, int);
@@ -140,6 +141,7 @@ enum lto_builtin_type
#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_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,
@@ -158,6 +160,7 @@ enum lto_builtin_type
#undef DEF_FUNCTION_TYPE_5
#undef DEF_FUNCTION_TYPE_6
#undef DEF_FUNCTION_TYPE_7
+#undef DEF_FUNCTION_TYPE_8
#undef DEF_FUNCTION_TYPE_VAR_0
#undef DEF_FUNCTION_TYPE_VAR_1
#undef DEF_FUNCTION_TYPE_VAR_2
@@ -631,6 +634,10 @@ lto_define_builtins (tree va_list_ref_type_node ATTRIBUTE_UNUSED,
#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_VAR_0(ENUM, RETURN) \
def_fn_type (ENUM, RETURN, 1, 0);
#define DEF_FUNCTION_TYPE_VAR_1(ENUM, RETURN, ARG1) \
@@ -1128,31 +1135,11 @@ lto_build_c_type_nodes (void)
pid_type_node = integer_type_node;
}
-/* Re-compute TYPE_CANONICAL for NODE and related types. */
-
-static void
-lto_register_canonical_types (tree node)
-{
- if (!node
- || !TYPE_P (node))
- return;
-
- TYPE_CANONICAL (node) = NULL_TREE;
- TYPE_CANONICAL (node) = gimple_register_canonical_type (node);
-
- if (POINTER_TYPE_P (node)
- || TREE_CODE (node) == COMPLEX_TYPE
- || TREE_CODE (node) == ARRAY_TYPE)
- lto_register_canonical_types (TREE_TYPE (node));
-}
-
/* Perform LTO-specific initialization. */
static bool
lto_init (void)
{
- unsigned i;
-
/* We need to generate LTO if running in WPA mode. */
flag_generate_lto = flag_wpa;
@@ -1188,6 +1175,9 @@ lto_init (void)
lto_define_builtins (va_list_type_node,
build_reference_type (va_list_type_node));
}
+
+ if (flag_enable_cilkplus)
+ cilk_init_builtins ();
targetm.init_builtins ();
build_common_builtin_nodes ();
@@ -1220,17 +1210,6 @@ lto_init (void)
NAME_TYPE (boolean_type_node, "bool");
#undef NAME_TYPE
- /* Register the common node types with the canonical type machinery so
- we properly share alias-sets across languages and TUs. Do not
- expose the common nodes as type merge target - those that should be
- are already exposed so by pre-loading the LTO streamer caches. */
- for (i = 0; i < itk_none; ++i)
- lto_register_canonical_types (integer_types[i]);
- /* The sizetypes are not used to access data so we do not need to
- do anything about them. */
- for (i = 0; i < TI_MAX; ++i)
- lto_register_canonical_types (global_trees[i]);
-
/* Initialize LTO-specific data structures. */
vec_alloc (lto_global_var_decls, 256);
in_lto_p = true;
diff --git a/gcc/lto/lto-object.c b/gcc/lto/lto-object.c
index 77be1fbe230..19f10ccb978 100644
--- a/gcc/lto/lto-object.c
+++ b/gcc/lto/lto-object.c
@@ -21,6 +21,8 @@ along with GCC; see the file COPYING3. If not see
#include "config.h"
#include "system.h"
#include "coretypes.h"
+#include "tree.h"
+#include "gimple.h"
#include "diagnostic-core.h"
#include "lto.h"
#include "tm.h"
diff --git a/gcc/lto/lto-partition.c b/gcc/lto/lto-partition.c
index e05f805fea4..6a3d881acca 100644
--- a/gcc/lto/lto-partition.c
+++ b/gcc/lto/lto-partition.c
@@ -22,6 +22,7 @@ along with GCC; see the file COPYING3. If not see
#include "coretypes.h"
#include "toplev.h"
#include "tree.h"
+#include "gimple.h"
#include "tm.h"
#include "cgraph.h"
#include "lto-streamer.h"
@@ -46,29 +47,29 @@ enum symbol_class
vec<ltrans_partition> ltrans_partitions;
-static void add_symbol_to_partition (ltrans_partition part, symtab_node node);
+static void add_symbol_to_partition (ltrans_partition part, symtab_node *node);
/* Classify symbol NODE. */
enum symbol_class
-get_symbol_class (symtab_node node)
+get_symbol_class (symtab_node *node)
{
/* Inline clones are always duplicated.
This include external delcarations. */
cgraph_node *cnode = dyn_cast <cgraph_node> (node);
- if (DECL_ABSTRACT (node->symbol.decl))
+ if (DECL_ABSTRACT (node->decl))
return SYMBOL_EXTERNAL;
if (cnode && cnode->global.inlined_to)
return SYMBOL_DUPLICATE;
/* Weakref aliases are always duplicated. */
- if (node->symbol.weakref)
+ if (node->weakref)
return SYMBOL_DUPLICATE;
/* External declarations are external. */
- if (DECL_EXTERNAL (node->symbol.decl))
+ if (DECL_EXTERNAL (node->decl))
return SYMBOL_EXTERNAL;
if (varpool_node *vnode = dyn_cast <varpool_node> (node))
@@ -76,22 +77,22 @@ get_symbol_class (symtab_node node)
/* Constant pool references use local symbol names that can not
be promoted global. We should never put into a constant pool
objects that can not be duplicated across partitions. */
- if (DECL_IN_CONSTANT_POOL (node->symbol.decl))
+ if (DECL_IN_CONSTANT_POOL (node->decl))
return SYMBOL_DUPLICATE;
- gcc_checking_assert (vnode->symbol.definition);
+ gcc_checking_assert (vnode->definition);
}
/* Functions that are cloned may stay in callgraph even if they are unused.
Handle them as external; compute_ltrans_boundary take care to make
proper things to happen (i.e. to make them appear in the boundary but
with body streamed, so clone can me materialized). */
- else if (!cgraph (node)->symbol.definition)
+ else if (!cgraph (node)->definition)
return SYMBOL_EXTERNAL;
/* Comdats are duplicated to every use unless they are keyed.
Those do not need duplication. */
- if (DECL_COMDAT (node->symbol.decl)
- && !node->symbol.force_output
- && !symtab_used_from_object_file_p ((symtab_node) node))
+ if (DECL_COMDAT (node->decl)
+ && !node->force_output
+ && !symtab_used_from_object_file_p (node))
return SYMBOL_DUPLICATE;
return SYMBOL_PARTITION;
@@ -130,27 +131,27 @@ free_ltrans_partitions (void)
/* Return true if symbol is already in some partition. */
static inline bool
-symbol_partitioned_p (symtab_node node)
+symbol_partitioned_p (symtab_node *node)
{
- return node->symbol.aux;
+ return node->aux;
}
/* Add references into the partition. */
static void
-add_references_to_partition (ltrans_partition part, symtab_node node)
+add_references_to_partition (ltrans_partition part, symtab_node *node)
{
int i;
struct ipa_ref *ref;
/* Add all duplicated references to the partition. */
- for (i = 0; ipa_ref_list_reference_iterate (&node->symbol.ref_list, i, ref); i++)
+ for (i = 0; ipa_ref_list_reference_iterate (&node->ref_list, i, ref); i++)
if (get_symbol_class (ref->referred) == SYMBOL_DUPLICATE)
add_symbol_to_partition (part, ref->referred);
/* References to a readonly variable may be constant foled into its value.
Recursively look into the initializers of the constant variable and add
references, too. */
else if (is_a <varpool_node> (ref->referred)
- && ctor_for_folding (ref->referred->symbol.decl) != error_mark_node
+ && ctor_for_folding (ref->referred->decl) != error_mark_node
&& !lto_symtab_encoder_in_partition_p (part->encoder, ref->referred))
{
if (!part->initializers_visited)
@@ -164,15 +165,15 @@ add_references_to_partition (ltrans_partition part, symtab_node node)
of adding NODE to PART. */
static bool
-add_symbol_to_partition_1 (ltrans_partition part, symtab_node node)
+add_symbol_to_partition_1 (ltrans_partition part, symtab_node *node)
{
enum symbol_class c = get_symbol_class (node);
int i;
struct ipa_ref *ref;
- symtab_node node1;
+ symtab_node *node1;
/* If NODE is already there, we have nothing to do. */
- if (lto_symtab_encoder_in_partition_p (part->encoder, (symtab_node) node))
+ if (lto_symtab_encoder_in_partition_p (part->encoder, node))
return true;
/* non-duplicated aliases or tunks of a duplicated symbol needs to be output
@@ -180,7 +181,7 @@ add_symbol_to_partition_1 (ltrans_partition part, symtab_node node)
Be lax about comdats; they may or may not be duplicated and we may
end up in need to duplicate keyed comdat because it has unkeyed alias. */
- if (c == SYMBOL_PARTITION && !DECL_COMDAT (node->symbol.decl)
+ if (c == SYMBOL_PARTITION && !DECL_COMDAT (node->decl)
&& symbol_partitioned_p (node))
return false;
@@ -189,16 +190,16 @@ add_symbol_to_partition_1 (ltrans_partition part, symtab_node node)
gcc_assert (c != SYMBOL_EXTERNAL
&& (c == SYMBOL_DUPLICATE || !symbol_partitioned_p (node)));
- lto_set_symtab_encoder_in_partition (part->encoder, (symtab_node) node);
+ lto_set_symtab_encoder_in_partition (part->encoder, node);
if (symbol_partitioned_p (node))
{
- node->symbol.in_other_partition = 1;
+ node->in_other_partition = 1;
if (cgraph_dump_file)
fprintf (cgraph_dump_file, "Symbol node %s now used in multiple partitions\n",
symtab_node_name (node));
}
- node->symbol.aux = (void *)((size_t)node->symbol.aux + 1);
+ node->aux = (void *)((size_t)node->aux + 1);
if (cgraph_node *cnode = dyn_cast <cgraph_node> (node))
{
@@ -208,27 +209,27 @@ add_symbol_to_partition_1 (ltrans_partition part, symtab_node node)
/* Add all inline clones and callees that are duplicated. */
for (e = cnode->callees; e; e = e->next_callee)
if (!e->inline_failed)
- add_symbol_to_partition_1 (part, (symtab_node) e->callee);
- else if (get_symbol_class ((symtab_node) e->callee) == SYMBOL_DUPLICATE)
- add_symbol_to_partition (part, (symtab_node) e->callee);
+ add_symbol_to_partition_1 (part, e->callee);
+ else if (get_symbol_class (e->callee) == SYMBOL_DUPLICATE)
+ add_symbol_to_partition (part, e->callee);
/* Add all thunks associated with the function. */
for (e = cnode->callers; e; e = e->next_caller)
if (e->caller->thunk.thunk_p)
- add_symbol_to_partition_1 (part, (symtab_node) e->caller);
+ add_symbol_to_partition_1 (part, e->caller);
}
add_references_to_partition (part, node);
/* Add all aliases associated with the symbol. */
- for (i = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list, i, ref); i++)
- if (ref->use == IPA_REF_ALIAS && !node->symbol.weakref)
+ for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list, i, ref); i++)
+ if (ref->use == IPA_REF_ALIAS && !node->weakref)
add_symbol_to_partition_1 (part, ref->referring);
/* Ensure that SAME_COMDAT_GROUP lists all allways added in a group. */
- if (node->symbol.same_comdat_group)
- for (node1 = node->symbol.same_comdat_group;
- node1 != node; node1 = node1->symbol.same_comdat_group)
+ if (node->same_comdat_group)
+ for (node1 = node->same_comdat_group;
+ node1 != node; node1 = node1->same_comdat_group)
{
bool added = add_symbol_to_partition_1 (part, node1);
gcc_assert (added);
@@ -240,21 +241,21 @@ add_symbol_to_partition_1 (ltrans_partition part, symtab_node node)
internal label, thunk, alias or so), return the outer symbol.
When add_symbol_to_partition_1 is called on the outer symbol it must
eventually add NODE, too. */
-static symtab_node
-contained_in_symbol (symtab_node node)
+static symtab_node *
+contained_in_symbol (symtab_node *node)
{
/* Weakrefs are never contained in anything. */
- if (node->symbol.weakref)
+ if (node->weakref)
return node;
if (cgraph_node *cnode = dyn_cast <cgraph_node> (node))
{
cnode = cgraph_function_node (cnode, NULL);
if (cnode->global.inlined_to)
cnode = cnode->global.inlined_to;
- return (symtab_node) cnode;
+ return cnode;
}
else if (varpool_node *vnode = dyn_cast <varpool_node> (node))
- return (symtab_node) varpool_variable_node (vnode, NULL);
+ return varpool_variable_node (vnode, NULL);
return node;
}
@@ -262,9 +263,9 @@ contained_in_symbol (symtab_node node)
of other symbol definition, add the other symbol, too. */
static void
-add_symbol_to_partition (ltrans_partition part, symtab_node node)
+add_symbol_to_partition (ltrans_partition part, symtab_node *node)
{
- symtab_node node1;
+ symtab_node *node1;
/* Verify that we do not try to duplicate something that can not be. */
gcc_checking_assert (get_symbol_class (node) == SYMBOL_DUPLICATE
@@ -280,7 +281,7 @@ add_symbol_to_partition (ltrans_partition part, symtab_node node)
Be lax about comdats; they may or may not be duplicated and we may
end up in need to duplicate keyed comdat because it has unkeyed alias. */
gcc_assert (get_symbol_class (node) == SYMBOL_DUPLICATE
- || DECL_COMDAT (node->symbol.decl)
+ || DECL_COMDAT (node->decl)
|| !symbol_partitioned_p (node));
add_symbol_to_partition_1 (part, node);
}
@@ -293,7 +294,7 @@ undo_partition (ltrans_partition partition, unsigned int n_nodes)
{
while (lto_symtab_encoder_size (partition->encoder) > (int)n_nodes)
{
- symtab_node node = lto_symtab_encoder_deref (partition->encoder,
+ symtab_node *node = lto_symtab_encoder_deref (partition->encoder,
n_nodes);
/* After UNDO we no longer know what was visited. */
@@ -304,7 +305,7 @@ undo_partition (ltrans_partition partition, unsigned int n_nodes)
if (cgraph_node *cnode = dyn_cast <cgraph_node> (node))
partition->insns -= inline_summary (cnode)->self_size;
lto_symtab_encoder_delete_node (partition->encoder, node);
- node->symbol.aux = (void *)((size_t)node->symbol.aux - 1);
+ node->aux = (void *)((size_t)node->aux - 1);
}
}
@@ -314,7 +315,7 @@ undo_partition (ltrans_partition partition, unsigned int n_nodes)
void
lto_1_to_1_map (void)
{
- symtab_node node;
+ symtab_node *node;
struct lto_file_decl_data *file_data;
struct pointer_map_t *pmap;
ltrans_partition partition;
@@ -329,7 +330,7 @@ lto_1_to_1_map (void)
|| symbol_partitioned_p (node))
continue;
- file_data = node->symbol.lto_file_data;
+ file_data = node->lto_file_data;
if (file_data)
{
@@ -354,7 +355,7 @@ lto_1_to_1_map (void)
npartitions++;
}
- add_symbol_to_partition (partition, (symtab_node) node);
+ add_symbol_to_partition (partition, node);
}
/* If the cgraph is empty, create one cgraph node set so that there is still
@@ -371,7 +372,7 @@ lto_1_to_1_map (void)
void
lto_max_map (void)
{
- symtab_node node;
+ symtab_node *node;
ltrans_partition partition;
int npartitions = 0;
@@ -381,7 +382,7 @@ lto_max_map (void)
|| symbol_partitioned_p (node))
continue;
partition = new_partition (symtab_node_asm_name (node));
- add_symbol_to_partition (partition, (symtab_node) node);
+ add_symbol_to_partition (partition, node);
npartitions++;
}
if (!npartitions)
@@ -394,7 +395,7 @@ node_cmp (const void *pa, const void *pb)
{
const struct cgraph_node *a = *(const struct cgraph_node * const *) pa;
const struct cgraph_node *b = *(const struct cgraph_node * const *) pb;
- return b->symbol.order - a->symbol.order;
+ return b->order - a->order;
}
/* Helper function for qsort; sort nodes by order. */
@@ -403,7 +404,7 @@ varpool_node_cmp (const void *pa, const void *pb)
{
const struct varpool_node *a = *(const struct varpool_node * const *) pa;
const struct varpool_node *b = *(const struct varpool_node * const *) pb;
- return b->symbol.order - a->symbol.order;
+ return b->order - a->order;
}
/* Group cgraph nodes into equally-sized partitions.
@@ -465,10 +466,10 @@ lto_balanced_map (void)
int current_order = -1;
FOR_EACH_VARIABLE (vnode)
- gcc_assert (!vnode->symbol.aux);
+ gcc_assert (!vnode->aux);
FOR_EACH_DEFINED_FUNCTION (node)
- if (get_symbol_class ((symtab_node) node) == SYMBOL_PARTITION)
+ if (get_symbol_class (node) == SYMBOL_PARTITION)
{
order[n_nodes++] = node;
total_size += inline_summary (node)->size;
@@ -485,13 +486,13 @@ lto_balanced_map (void)
qsort (order, n_nodes, sizeof (struct cgraph_node *), node_cmp);
FOR_EACH_VARIABLE (vnode)
- if (get_symbol_class ((symtab_node) vnode) == SYMBOL_PARTITION)
+ if (get_symbol_class (vnode) == SYMBOL_PARTITION)
n_varpool_nodes++;
varpool_order = XNEWVEC (struct varpool_node *, n_varpool_nodes);
n_varpool_nodes = 0;
FOR_EACH_VARIABLE (vnode)
- if (get_symbol_class ((symtab_node) vnode) == SYMBOL_PARTITION)
+ if (get_symbol_class (vnode) == SYMBOL_PARTITION)
varpool_order[n_varpool_nodes++] = vnode;
qsort (varpool_order, n_varpool_nodes, sizeof (struct varpool_node *),
varpool_node_cmp);
@@ -509,21 +510,21 @@ lto_balanced_map (void)
for (i = 0; i < n_nodes; i++)
{
- if (symbol_partitioned_p ((symtab_node) order[i]))
+ if (symbol_partitioned_p (order[i]))
continue;
- current_order = order[i]->symbol.order;
+ current_order = order[i]->order;
if (!flag_toplevel_reorder)
while (varpool_pos < n_varpool_nodes
- && varpool_order[varpool_pos]->symbol.order < current_order)
+ && varpool_order[varpool_pos]->order < current_order)
{
- if (!symbol_partitioned_p ((symtab_node) varpool_order[varpool_pos]))
- add_symbol_to_partition (partition, (symtab_node) varpool_order[varpool_pos]);
+ if (!symbol_partitioned_p (varpool_order[varpool_pos]))
+ add_symbol_to_partition (partition, varpool_order[varpool_pos]);
varpool_pos++;
}
- add_symbol_to_partition (partition, (symtab_node) order[i]);
+ add_symbol_to_partition (partition, order[i]);
total_size -= inline_summary (order[i])->size;
@@ -544,22 +545,22 @@ lto_balanced_map (void)
struct ipa_ref_list *refs;
int j;
struct ipa_ref *ref;
- symtab_node snode = lto_symtab_encoder_deref (partition->encoder,
+ symtab_node *snode = lto_symtab_encoder_deref (partition->encoder,
last_visited_node);
if (cgraph_node *node = dyn_cast <cgraph_node> (snode))
{
struct cgraph_edge *edge;
- refs = &node->symbol.ref_list;
+ refs = &node->ref_list;
last_visited_node++;
- gcc_assert (node->symbol.definition || node->symbol.weakref);
+ gcc_assert (node->definition || node->weakref);
/* Compute boundary cost of callgraph edges. */
for (edge = node->callees; edge; edge = edge->next_callee)
- if (edge->callee->symbol.definition)
+ if (edge->callee->definition)
{
int edge_cost = edge->frequency;
int index;
@@ -568,7 +569,7 @@ lto_balanced_map (void)
edge_cost = 1;
gcc_assert (edge_cost > 0);
index = lto_symtab_encoder_lookup (partition->encoder,
- (symtab_node)edge->callee);
+ edge->callee);
if (index != LCC_NOT_FOUND
&& index < last_visited_node - 1)
cost -= edge_cost, internal += edge_cost;
@@ -580,12 +581,12 @@ lto_balanced_map (void)
int edge_cost = edge->frequency;
int index;
- gcc_assert (edge->caller->symbol.definition);
+ gcc_assert (edge->caller->definition);
if (!edge_cost)
edge_cost = 1;
gcc_assert (edge_cost > 0);
index = lto_symtab_encoder_lookup (partition->encoder,
- (symtab_node)edge->caller);
+ edge->caller);
if (index != LCC_NOT_FOUND
&& index < last_visited_node - 1)
cost -= edge_cost;
@@ -595,7 +596,7 @@ lto_balanced_map (void)
}
else
{
- refs = &snode->symbol.ref_list;
+ refs = &snode->ref_list;
last_visited_node++;
}
@@ -607,13 +608,13 @@ lto_balanced_map (void)
int index;
vnode = ipa_ref_varpool_node (ref);
- if (!vnode->symbol.definition)
+ if (!vnode->definition)
continue;
- if (!symbol_partitioned_p ((symtab_node) vnode) && flag_toplevel_reorder
- && get_symbol_class ((symtab_node) vnode) == SYMBOL_PARTITION)
- add_symbol_to_partition (partition, (symtab_node) vnode);
+ if (!symbol_partitioned_p (vnode) && flag_toplevel_reorder
+ && get_symbol_class (vnode) == SYMBOL_PARTITION)
+ add_symbol_to_partition (partition, vnode);
index = lto_symtab_encoder_lookup (partition->encoder,
- (symtab_node)vnode);
+ vnode);
if (index != LCC_NOT_FOUND
&& index < last_visited_node - 1)
cost--, internal++;
@@ -625,10 +626,10 @@ lto_balanced_map (void)
int index;
node = ipa_ref_node (ref);
- if (!node->symbol.definition)
+ if (!node->definition)
continue;
index = lto_symtab_encoder_lookup (partition->encoder,
- (symtab_node)node);
+ node);
if (index != LCC_NOT_FOUND
&& index < last_visited_node - 1)
cost--, internal++;
@@ -641,12 +642,12 @@ lto_balanced_map (void)
int index;
vnode = ipa_ref_referring_varpool_node (ref);
- gcc_assert (vnode->symbol.definition);
- if (!symbol_partitioned_p ((symtab_node) vnode) && flag_toplevel_reorder
- && get_symbol_class ((symtab_node) vnode) == SYMBOL_PARTITION)
- add_symbol_to_partition (partition, (symtab_node) vnode);
+ gcc_assert (vnode->definition);
+ if (!symbol_partitioned_p (vnode) && flag_toplevel_reorder
+ && get_symbol_class (vnode) == SYMBOL_PARTITION)
+ add_symbol_to_partition (partition, vnode);
index = lto_symtab_encoder_lookup (partition->encoder,
- (symtab_node)vnode);
+ vnode);
if (index != LCC_NOT_FOUND
&& index < last_visited_node - 1)
cost--;
@@ -658,9 +659,9 @@ lto_balanced_map (void)
int index;
node = ipa_ref_referring_node (ref);
- gcc_assert (node->symbol.definition);
+ gcc_assert (node->definition);
index = lto_symtab_encoder_lookup (partition->encoder,
- (symtab_node)node);
+ node);
if (index != LCC_NOT_FOUND
&& index < last_visited_node - 1)
cost--;
@@ -687,7 +688,7 @@ lto_balanced_map (void)
if (cgraph_dump_file)
fprintf (cgraph_dump_file, "Step %i: added %s/%i, size %i, cost %i/%i "
"best %i/%i, step %i\n", i,
- cgraph_node_name (order[i]), order[i]->symbol.order,
+ cgraph_node_name (order[i]), order[i]->order,
partition->insns, cost, internal,
best_cost, best_internal, best_i);
/* Partition is too large, unwind into step when best cost was reached and
@@ -704,7 +705,7 @@ lto_balanced_map (void)
}
i = best_i;
/* When we are finished, avoid creating empty partition. */
- while (i < n_nodes - 1 && symbol_partitioned_p ((symtab_node) order[i + 1]))
+ while (i < n_nodes - 1 && symbol_partitioned_p (order[i + 1]))
i++;
if (i == n_nodes - 1)
break;
@@ -736,16 +737,16 @@ lto_balanced_map (void)
if (flag_toplevel_reorder)
{
FOR_EACH_VARIABLE (vnode)
- if (get_symbol_class ((symtab_node) vnode) == SYMBOL_PARTITION
- && !symbol_partitioned_p ((symtab_node) vnode))
- add_symbol_to_partition (partition, (symtab_node) vnode);
+ if (get_symbol_class (vnode) == SYMBOL_PARTITION
+ && !symbol_partitioned_p (vnode))
+ add_symbol_to_partition (partition, vnode);
}
else
{
while (varpool_pos < n_varpool_nodes)
{
- if (!symbol_partitioned_p ((symtab_node) varpool_order[varpool_pos]))
- add_symbol_to_partition (partition, (symtab_node) varpool_order[varpool_pos]);
+ if (!symbol_partitioned_p (varpool_order[varpool_pos]))
+ add_symbol_to_partition (partition, varpool_order[varpool_pos]);
varpool_pos++;
}
free (varpool_order);
@@ -762,15 +763,15 @@ lto_balanced_map (void)
*/
static bool
-privatize_symbol_name (symtab_node node)
+privatize_symbol_name (symtab_node *node)
{
- tree decl = node->symbol.decl;
+ tree decl = node->decl;
const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
/* Our renaming machinery do not handle more than one change of assembler name.
We should not need more than one anyway. */
- if (node->symbol.lto_file_data
- && lto_get_decl_name_mapping (node->symbol.lto_file_data, name) != name)
+ if (node->lto_file_data
+ && lto_get_decl_name_mapping (node->lto_file_data, name) != name)
{
if (cgraph_dump_file)
fprintf (cgraph_dump_file,
@@ -782,7 +783,7 @@ privatize_symbol_name (symtab_node node)
??? should have a flag whether a symbol has a 'private' name already,
since we produce some symbols like that i.e. for global constructors
that are not really clones. */
- if (node->symbol.unique_name)
+ if (node->unique_name)
{
if (cgraph_dump_file)
fprintf (cgraph_dump_file,
@@ -791,8 +792,8 @@ privatize_symbol_name (symtab_node node)
return false;
}
change_decl_assembler_name (decl, clone_function_name (decl, "lto_priv"));
- if (node->symbol.lto_file_data)
- lto_record_renamed_decl (node->symbol.lto_file_data, name,
+ if (node->lto_file_data)
+ lto_record_renamed_decl (node->lto_file_data, name,
IDENTIFIER_POINTER
(DECL_ASSEMBLER_NAME (decl)));
if (cgraph_dump_file)
@@ -805,22 +806,22 @@ privatize_symbol_name (symtab_node node)
/* Promote variable VNODE to be static. */
static void
-promote_symbol (symtab_node node)
+promote_symbol (symtab_node *node)
{
/* We already promoted ... */
- if (DECL_VISIBILITY (node->symbol.decl) == VISIBILITY_HIDDEN
- && DECL_VISIBILITY_SPECIFIED (node->symbol.decl)
- && TREE_PUBLIC (node->symbol.decl))
+ if (DECL_VISIBILITY (node->decl) == VISIBILITY_HIDDEN
+ && DECL_VISIBILITY_SPECIFIED (node->decl)
+ && TREE_PUBLIC (node->decl))
return;
- gcc_checking_assert (!TREE_PUBLIC (node->symbol.decl)
- && !DECL_EXTERNAL (node->symbol.decl));
+ gcc_checking_assert (!TREE_PUBLIC (node->decl)
+ && !DECL_EXTERNAL (node->decl));
/* Be sure that newly public symbol does not conflict with anything already
defined by the non-LTO part. */
privatize_symbol_name (node);
- TREE_PUBLIC (node->symbol.decl) = 1;
- DECL_VISIBILITY (node->symbol.decl) = VISIBILITY_HIDDEN;
- DECL_VISIBILITY_SPECIFIED (node->symbol.decl) = true;
+ TREE_PUBLIC (node->decl) = 1;
+ DECL_VISIBILITY (node->decl) = VISIBILITY_HIDDEN;
+ DECL_VISIBILITY_SPECIFIED (node->decl) = true;
if (cgraph_dump_file)
fprintf (cgraph_dump_file,
"Promoting as hidden: %s\n", symtab_node_name (node));
@@ -831,7 +832,7 @@ promote_symbol (symtab_node node)
FIXME: we should really not use named sections for inline clones and master clones. */
static bool
-may_need_named_section_p (lto_symtab_encoder_t encoder, symtab_node node)
+may_need_named_section_p (lto_symtab_encoder_t encoder, symtab_node *node)
{
struct cgraph_node *cnode = dyn_cast <cgraph_node> (node);
if (!cnode)
@@ -851,18 +852,18 @@ may_need_named_section_p (lto_symtab_encoder_t encoder, symtab_node node)
asm statemnets referring to them by symbol name. */
static void
-rename_statics (lto_symtab_encoder_t encoder, symtab_node node)
+rename_statics (lto_symtab_encoder_t encoder, symtab_node *node)
{
- tree decl = node->symbol.decl;
- symtab_node s;
+ tree decl = node->decl;
+ symtab_node *s;
tree name = DECL_ASSEMBLER_NAME (decl);
/* See if this is static symbol. */
- if ((node->symbol.externally_visible
+ if ((node->externally_visible
/* FIXME: externally_visible is somewhat illogically not set for
external symbols (i.e. those not defined). Remove this test
once this is fixed. */
- || DECL_EXTERNAL (node->symbol.decl)
+ || DECL_EXTERNAL (node->decl)
|| !symtab_real_symbol_p (node))
&& !may_need_named_section_p (encoder, node))
return;
@@ -871,9 +872,9 @@ rename_statics (lto_symtab_encoder_t encoder, symtab_node node)
(all types of symbols counts here, since we can not have static of the
same name as external or public symbol.) */
for (s = symtab_node_for_asm (name);
- s; s = s->symbol.next_sharing_asm_name)
+ s; s = s->next_sharing_asm_name)
if ((symtab_real_symbol_p (s) || may_need_named_section_p (encoder, s))
- && s->symbol.decl != node->symbol.decl
+ && s->decl != node->decl
&& (!encoder
|| lto_symtab_encoder_lookup (encoder, s) != LCC_NOT_FOUND))
break;
@@ -889,10 +890,10 @@ rename_statics (lto_symtab_encoder_t encoder, symtab_node node)
/* Assign every symbol in the set that shares the same ASM name an unique
mangled name. */
for (s = symtab_node_for_asm (name); s;)
- if (!s->symbol.externally_visible
+ if (!s->externally_visible
&& ((symtab_real_symbol_p (s)
- && !DECL_EXTERNAL (node->symbol.decl)
- && !TREE_PUBLIC (node->symbol.decl))
+ && !DECL_EXTERNAL (node->decl)
+ && !TREE_PUBLIC (node->decl))
|| may_need_named_section_p (encoder, s))
&& (!encoder
|| lto_symtab_encoder_lookup (encoder, s) != LCC_NOT_FOUND))
@@ -900,9 +901,9 @@ rename_statics (lto_symtab_encoder_t encoder, symtab_node node)
if (privatize_symbol_name (s))
/* Re-start from beginning since we do not know how many symbols changed a name. */
s = symtab_node_for_asm (name);
- else s = s->symbol.next_sharing_asm_name;
+ else s = s->next_sharing_asm_name;
}
- else s = s->symbol.next_sharing_asm_name;
+ else s = s->next_sharing_asm_name;
}
/* Find out all static decls that need to be promoted to global because
@@ -934,19 +935,19 @@ lto_promote_cross_file_statics (void)
for (lsei = lsei_start (encoder); !lsei_end_p (lsei);
lsei_next (&lsei))
{
- symtab_node node = lsei_node (lsei);
+ symtab_node *node = lsei_node (lsei);
/* If symbol is static, rename it if its assembler name clash with
anything else in this unit. */
rename_statics (encoder, node);
/* No need to promote if symbol already is externally visible ... */
- if (node->symbol.externally_visible
+ if (node->externally_visible
/* ... or if it is part of current partition ... */
|| lto_symtab_encoder_in_partition_p (encoder, node)
/* ... or if we do not partition it. This mean that it will
appear in every partition refernecing it. */
- || get_symbol_class ((symtab_node) node) != SYMBOL_PARTITION)
+ || get_symbol_class (node) != SYMBOL_PARTITION)
continue;
promote_symbol (node);
@@ -960,7 +961,7 @@ lto_promote_cross_file_statics (void)
void
lto_promote_statics_nonwpa (void)
{
- symtab_node node;
+ symtab_node *node;
FOR_EACH_SYMBOL (node)
rename_statics (NULL, node);
}
diff --git a/gcc/lto/lto-symtab.c b/gcc/lto/lto-symtab.c
index b1b7731c830..2ebc07d4fb4 100644
--- a/gcc/lto/lto-symtab.c
+++ b/gcc/lto/lto-symtab.c
@@ -29,6 +29,7 @@ along with GCC; see the file COPYING3. If not see
#include "plugin-api.h"
#include "lto-streamer.h"
#include "ipa-utils.h"
+#include "ipa-inline.h"
/* Replace the cgraph node NODE with PREVAILING_NODE in the cgraph, merging
all edges and removing the old node. */
@@ -44,17 +45,17 @@ lto_cgraph_replace_node (struct cgraph_node *node,
{
fprintf (cgraph_dump_file, "Replacing cgraph node %s/%i by %s/%i"
" for symbol %s\n",
- cgraph_node_name (node), node->symbol.order,
+ cgraph_node_name (node), node->order,
cgraph_node_name (prevailing_node),
- prevailing_node->symbol.order,
+ prevailing_node->order,
IDENTIFIER_POINTER ((*targetm.asm_out.mangle_assembler_name)
- (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->symbol.decl)))));
+ (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl)))));
}
/* Merge node flags. */
- if (node->symbol.force_output)
+ if (node->force_output)
cgraph_mark_force_output_node (prevailing_node);
- if (node->symbol.address_taken)
+ if (node->address_taken)
{
gcc_assert (!prevailing_node->global.inlined_to);
cgraph_mark_address_taken_node (prevailing_node);
@@ -62,8 +63,8 @@ lto_cgraph_replace_node (struct cgraph_node *node,
/* Redirect all incoming edges. */
compatible_p
- = types_compatible_p (TREE_TYPE (TREE_TYPE (prevailing_node->symbol.decl)),
- TREE_TYPE (TREE_TYPE (node->symbol.decl)));
+ = types_compatible_p (TREE_TYPE (TREE_TYPE (prevailing_node->decl)),
+ TREE_TYPE (TREE_TYPE (node->decl)));
for (e = node->callers; e; e = next)
{
next = e->next_caller;
@@ -76,14 +77,20 @@ lto_cgraph_replace_node (struct cgraph_node *node,
e->call_stmt_cannot_inline_p = 1;
}
/* Redirect incomming references. */
- ipa_clone_referring ((symtab_node)prevailing_node, &node->symbol.ref_list);
+ ipa_clone_referring (prevailing_node, &node->ref_list);
ipa_merge_profiles (prevailing_node, node);
- lto_free_function_in_decl_state_for_node ((symtab_node)node);
+ lto_free_function_in_decl_state_for_node (node);
- if (node->symbol.decl != prevailing_node->symbol.decl)
+ if (node->decl != prevailing_node->decl)
cgraph_release_function_body (node);
+ /* Time profile merging */
+ if (node->tp_first_run)
+ prevailing_node->tp_first_run = prevailing_node->tp_first_run ?
+ MIN (prevailing_node->tp_first_run, node->tp_first_run) :
+ node->tp_first_run;
+
/* Finally remove the replaced node. */
cgraph_remove_node (node);
}
@@ -95,15 +102,15 @@ static void
lto_varpool_replace_node (struct varpool_node *vnode,
struct varpool_node *prevailing_node)
{
- gcc_assert (!vnode->symbol.definition || prevailing_node->symbol.definition);
- gcc_assert (!vnode->symbol.analyzed || prevailing_node->symbol.analyzed);
+ gcc_assert (!vnode->definition || prevailing_node->definition);
+ gcc_assert (!vnode->analyzed || prevailing_node->analyzed);
- ipa_clone_referring ((symtab_node)prevailing_node, &vnode->symbol.ref_list);
+ ipa_clone_referring (prevailing_node, &vnode->ref_list);
/* Be sure we can garbage collect the initializer. */
- if (DECL_INITIAL (vnode->symbol.decl)
- && vnode->symbol.decl != prevailing_node->symbol.decl)
- DECL_INITIAL (vnode->symbol.decl) = error_mark_node;
+ if (DECL_INITIAL (vnode->decl)
+ && vnode->decl != prevailing_node->decl)
+ DECL_INITIAL (vnode->decl) = error_mark_node;
/* Finally remove the replaced node. */
varpool_remove_node (vnode);
}
@@ -113,10 +120,10 @@ lto_varpool_replace_node (struct varpool_node *vnode,
should be emitted. */
static bool
-lto_symtab_merge (symtab_node prevailing, symtab_node entry)
+lto_symtab_merge (symtab_node *prevailing, symtab_node *entry)
{
- tree prevailing_decl = prevailing->symbol.decl;
- tree decl = entry->symbol.decl;
+ tree prevailing_decl = prevailing->decl;
+ tree decl = entry->decl;
tree prevailing_type, type;
if (prevailing_decl == decl)
@@ -216,17 +223,17 @@ lto_symtab_merge (symtab_node prevailing, symtab_node entry)
entry. */
static bool
-lto_symtab_resolve_replaceable_p (symtab_node e)
+lto_symtab_resolve_replaceable_p (symtab_node *e)
{
- if (DECL_EXTERNAL (e->symbol.decl)
- || DECL_COMDAT (e->symbol.decl)
- || DECL_ONE_ONLY (e->symbol.decl)
- || DECL_WEAK (e->symbol.decl))
+ if (DECL_EXTERNAL (e->decl)
+ || DECL_COMDAT (e->decl)
+ || DECL_ONE_ONLY (e->decl)
+ || DECL_WEAK (e->decl))
return true;
- if (TREE_CODE (e->symbol.decl) == VAR_DECL)
- return (DECL_COMMON (e->symbol.decl)
- || (!flag_no_common && !DECL_INITIAL (e->symbol.decl)));
+ if (TREE_CODE (e->decl) == VAR_DECL)
+ return (DECL_COMMON (e->decl)
+ || (!flag_no_common && !DECL_INITIAL (e->decl)));
return false;
}
@@ -236,9 +243,9 @@ lto_symtab_resolve_replaceable_p (symtab_node e)
handle renaming of static later in partitioning). */
static bool
-lto_symtab_symbol_p (symtab_node e)
+lto_symtab_symbol_p (symtab_node *e)
{
- if (!TREE_PUBLIC (e->symbol.decl) && !DECL_EXTERNAL (e->symbol.decl))
+ if (!TREE_PUBLIC (e->decl) && !DECL_EXTERNAL (e->decl))
return false;
return symtab_real_symbol_p (e);
}
@@ -246,7 +253,7 @@ lto_symtab_symbol_p (symtab_node e)
/* Return true if the symtab entry E can be the prevailing one. */
static bool
-lto_symtab_resolve_can_prevail_p (symtab_node e)
+lto_symtab_resolve_can_prevail_p (symtab_node *e)
{
if (!lto_symtab_symbol_p (e))
return false;
@@ -254,27 +261,27 @@ lto_symtab_resolve_can_prevail_p (symtab_node e)
/* The C++ frontend ends up neither setting TREE_STATIC nor
DECL_EXTERNAL on virtual methods but only TREE_PUBLIC.
So do not reject !TREE_STATIC here but only DECL_EXTERNAL. */
- if (DECL_EXTERNAL (e->symbol.decl))
+ if (DECL_EXTERNAL (e->decl))
return false;
- return e->symbol.definition;
+ return e->definition;
}
/* Resolve the symbol with the candidates in the chain *SLOT and store
their resolutions. */
-static symtab_node
-lto_symtab_resolve_symbols (symtab_node first)
+static symtab_node *
+lto_symtab_resolve_symbols (symtab_node *first)
{
- symtab_node e;
- symtab_node prevailing = NULL;
+ symtab_node *e;
+ symtab_node *prevailing = NULL;
/* Always set e->node so that edges are updated to reflect decl merging. */
- for (e = first; e; e = e->symbol.next_sharing_asm_name)
+ for (e = first; e; e = e->next_sharing_asm_name)
if (lto_symtab_symbol_p (e)
- && (e->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY
- || e->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY_EXP
- || e->symbol.resolution == LDPR_PREVAILING_DEF))
+ && (e->resolution == LDPR_PREVAILING_DEF_IRONLY
+ || e->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP
+ || e->resolution == LDPR_PREVAILING_DEF))
{
prevailing = e;
break;
@@ -284,19 +291,19 @@ lto_symtab_resolve_symbols (symtab_node first)
if (prevailing)
{
/* Assert it's the only one. */
- for (e = prevailing->symbol.next_sharing_asm_name; e; e = e->symbol.next_sharing_asm_name)
+ for (e = prevailing->next_sharing_asm_name; e; e = e->next_sharing_asm_name)
if (lto_symtab_symbol_p (e)
- && (e->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY
- || e->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY_EXP
- || e->symbol.resolution == LDPR_PREVAILING_DEF))
+ && (e->resolution == LDPR_PREVAILING_DEF_IRONLY
+ || e->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP
+ || e->resolution == LDPR_PREVAILING_DEF))
fatal_error ("multiple prevailing defs for %qE",
- DECL_NAME (prevailing->symbol.decl));
+ DECL_NAME (prevailing->decl));
return prevailing;
}
/* Find the single non-replaceable prevailing symbol and
diagnose ODR violations. */
- for (e = first; e; e = e->symbol.next_sharing_asm_name)
+ for (e = first; e; e = e->next_sharing_asm_name)
{
if (!lto_symtab_resolve_can_prevail_p (e))
continue;
@@ -306,9 +313,9 @@ lto_symtab_resolve_symbols (symtab_node first)
{
if (prevailing)
{
- error_at (DECL_SOURCE_LOCATION (e->symbol.decl),
- "%qD has already been defined", e->symbol.decl);
- inform (DECL_SOURCE_LOCATION (prevailing->symbol.decl),
+ error_at (DECL_SOURCE_LOCATION (e->decl),
+ "%qD has already been defined", e->decl);
+ inform (DECL_SOURCE_LOCATION (prevailing->decl),
"previously defined here");
}
prevailing = e;
@@ -318,13 +325,13 @@ lto_symtab_resolve_symbols (symtab_node first)
return prevailing;
/* Do a second round choosing one from the replaceable prevailing decls. */
- for (e = first; e; e = e->symbol.next_sharing_asm_name)
+ for (e = first; e; e = e->next_sharing_asm_name)
{
if (!lto_symtab_resolve_can_prevail_p (e))
continue;
/* Choose the first function that can prevail as prevailing. */
- if (TREE_CODE (e->symbol.decl) == FUNCTION_DECL)
+ if (TREE_CODE (e->decl) == FUNCTION_DECL)
{
prevailing = e;
break;
@@ -332,8 +339,8 @@ lto_symtab_resolve_symbols (symtab_node first)
/* From variables that can prevail choose the largest one. */
if (!prevailing
- || tree_int_cst_lt (DECL_SIZE (prevailing->symbol.decl),
- DECL_SIZE (e->symbol.decl))
+ || tree_int_cst_lt (DECL_SIZE (prevailing->decl),
+ DECL_SIZE (e->decl))
/* When variables are equivalent try to chose one that has useful
DECL_INITIAL. This makes sense for keyed vtables that are
DECL_EXTERNAL but initialized. In units that do not need them
@@ -343,11 +350,11 @@ lto_symtab_resolve_symbols (symtab_node first)
We know that the vtable is keyed outside the LTO unit - otherwise
the keyed instance would prevail. We still can preserve useful
info in the initializer. */
- || (DECL_SIZE (prevailing->symbol.decl) == DECL_SIZE (e->symbol.decl)
- && (DECL_INITIAL (e->symbol.decl)
- && DECL_INITIAL (e->symbol.decl) != error_mark_node)
- && (!DECL_INITIAL (prevailing->symbol.decl)
- || DECL_INITIAL (prevailing->symbol.decl) == error_mark_node)))
+ || (DECL_SIZE (prevailing->decl) == DECL_SIZE (e->decl)
+ && (DECL_INITIAL (e->decl)
+ && DECL_INITIAL (e->decl) != error_mark_node)
+ && (!DECL_INITIAL (prevailing->decl)
+ || DECL_INITIAL (prevailing->decl) == error_mark_node)))
prevailing = e;
}
@@ -359,26 +366,27 @@ lto_symtab_resolve_symbols (symtab_node first)
do not issue further diagnostics.*/
static void
-lto_symtab_merge_decls_2 (symtab_node first, bool diagnosed_p)
+lto_symtab_merge_decls_2 (symtab_node *first, bool diagnosed_p)
{
- symtab_node prevailing, e;
+ symtab_node *prevailing;
+ symtab_node *e;
vec<tree> mismatches = vNULL;
unsigned i;
tree decl;
/* Nothing to do for a single entry. */
prevailing = first;
- if (!prevailing->symbol.next_sharing_asm_name)
+ if (!prevailing->next_sharing_asm_name)
return;
/* Try to merge each entry with the prevailing one. */
- for (e = prevailing->symbol.next_sharing_asm_name;
- e; e = e->symbol.next_sharing_asm_name)
- if (TREE_PUBLIC (e->symbol.decl))
+ for (e = prevailing->next_sharing_asm_name;
+ e; e = e->next_sharing_asm_name)
+ if (TREE_PUBLIC (e->decl))
{
if (!lto_symtab_merge (prevailing, e)
&& !diagnosed_p)
- mismatches.safe_push (e->symbol.decl);
+ mismatches.safe_push (e->decl);
}
if (mismatches.is_empty ())
return;
@@ -386,15 +394,15 @@ lto_symtab_merge_decls_2 (symtab_node first, bool diagnosed_p)
/* Diagnose all mismatched re-declarations. */
FOR_EACH_VEC_ELT (mismatches, i, decl)
{
- if (!types_compatible_p (TREE_TYPE (prevailing->symbol.decl),
+ if (!types_compatible_p (TREE_TYPE (prevailing->decl),
TREE_TYPE (decl)))
diagnosed_p |= warning_at (DECL_SOURCE_LOCATION (decl), 0,
"type of %qD does not match original "
"declaration", decl);
- else if ((DECL_USER_ALIGN (prevailing->symbol.decl)
+ else if ((DECL_USER_ALIGN (prevailing->decl)
&& DECL_USER_ALIGN (decl))
- && DECL_ALIGN (prevailing->symbol.decl) < DECL_ALIGN (decl))
+ && DECL_ALIGN (prevailing->decl) < DECL_ALIGN (decl))
{
diagnosed_p |= warning_at (DECL_SOURCE_LOCATION (decl), 0,
"alignment of %qD is bigger than "
@@ -402,7 +410,7 @@ lto_symtab_merge_decls_2 (symtab_node first, bool diagnosed_p)
}
}
if (diagnosed_p)
- inform (DECL_SOURCE_LOCATION (prevailing->symbol.decl),
+ inform (DECL_SOURCE_LOCATION (prevailing->decl),
"previously declared here");
mismatches.release ();
@@ -411,17 +419,18 @@ lto_symtab_merge_decls_2 (symtab_node first, bool diagnosed_p)
/* Helper to process the decl chain for the symbol table entry *SLOT. */
static void
-lto_symtab_merge_decls_1 (symtab_node first)
+lto_symtab_merge_decls_1 (symtab_node *first)
{
- symtab_node e, prevailing;
+ symtab_node *e;
+ symtab_node *prevailing;
bool diagnosed_p = false;
if (cgraph_dump_file)
{
fprintf (cgraph_dump_file, "Merging nodes for %s. Candidates:\n",
symtab_node_asm_name (first));
- for (e = first; e; e = e->symbol.next_sharing_asm_name)
- if (TREE_PUBLIC (e->symbol.decl))
+ for (e = first; e; e = e->next_sharing_asm_name)
+ if (TREE_PUBLIC (e->decl))
dump_symtab_node (cgraph_dump_file, e);
}
@@ -442,21 +451,21 @@ lto_symtab_merge_decls_1 (symtab_node first)
This is needed for C++ typeinfos, for example in
lto/20081204-1 there are typeifos in both units, just
one of them do have size. */
- if (TREE_CODE (prevailing->symbol.decl) == VAR_DECL)
+ if (TREE_CODE (prevailing->decl) == VAR_DECL)
{
- for (e = prevailing->symbol.next_sharing_asm_name;
- e; e = e->symbol.next_sharing_asm_name)
- if (!COMPLETE_TYPE_P (TREE_TYPE (prevailing->symbol.decl))
- && COMPLETE_TYPE_P (TREE_TYPE (e->symbol.decl))
+ for (e = prevailing->next_sharing_asm_name;
+ e; e = e->next_sharing_asm_name)
+ if (!COMPLETE_TYPE_P (TREE_TYPE (prevailing->decl))
+ && COMPLETE_TYPE_P (TREE_TYPE (e->decl))
&& lto_symtab_symbol_p (e))
prevailing = e;
}
/* For variables prefer the non-builtin if one is available. */
- else if (TREE_CODE (prevailing->symbol.decl) == FUNCTION_DECL)
+ else if (TREE_CODE (prevailing->decl) == FUNCTION_DECL)
{
- for (e = first; e; e = e->symbol.next_sharing_asm_name)
- if (TREE_CODE (e->symbol.decl) == FUNCTION_DECL
- && !DECL_BUILT_IN (e->symbol.decl)
+ for (e = first; e; e = e->next_sharing_asm_name)
+ if (TREE_CODE (e->decl) == FUNCTION_DECL
+ && !DECL_BUILT_IN (e->decl)
&& lto_symtab_symbol_p (e))
{
prevailing = e;
@@ -468,29 +477,29 @@ lto_symtab_merge_decls_1 (symtab_node first)
symtab_prevail_in_asm_name_hash (prevailing);
/* Diagnose mismatched objects. */
- for (e = prevailing->symbol.next_sharing_asm_name;
- e; e = e->symbol.next_sharing_asm_name)
+ for (e = prevailing->next_sharing_asm_name;
+ e; e = e->next_sharing_asm_name)
{
- if (TREE_CODE (prevailing->symbol.decl)
- == TREE_CODE (e->symbol.decl))
+ if (TREE_CODE (prevailing->decl)
+ == TREE_CODE (e->decl))
continue;
if (!lto_symtab_symbol_p (e))
continue;
- switch (TREE_CODE (prevailing->symbol.decl))
+ switch (TREE_CODE (prevailing->decl))
{
case VAR_DECL:
- gcc_assert (TREE_CODE (e->symbol.decl) == FUNCTION_DECL);
- error_at (DECL_SOURCE_LOCATION (e->symbol.decl),
+ gcc_assert (TREE_CODE (e->decl) == FUNCTION_DECL);
+ error_at (DECL_SOURCE_LOCATION (e->decl),
"variable %qD redeclared as function",
- prevailing->symbol.decl);
+ prevailing->decl);
break;
case FUNCTION_DECL:
- gcc_assert (TREE_CODE (e->symbol.decl) == VAR_DECL);
- error_at (DECL_SOURCE_LOCATION (e->symbol.decl),
+ gcc_assert (TREE_CODE (e->decl) == VAR_DECL);
+ error_at (DECL_SOURCE_LOCATION (e->decl),
"function %qD redeclared as variable",
- prevailing->symbol.decl);
+ prevailing->decl);
break;
default:
@@ -500,7 +509,7 @@ lto_symtab_merge_decls_1 (symtab_node first)
diagnosed_p = true;
}
if (diagnosed_p)
- inform (DECL_SOURCE_LOCATION (prevailing->symbol.decl),
+ inform (DECL_SOURCE_LOCATION (prevailing->decl),
"previously declared here");
/* Merge the chain to the single prevailing decl and diagnose
@@ -510,7 +519,7 @@ lto_symtab_merge_decls_1 (symtab_node first)
if (cgraph_dump_file)
{
fprintf (cgraph_dump_file, "After resolution:\n");
- for (e = prevailing; e; e = e->symbol.next_sharing_asm_name)
+ for (e = prevailing; e; e = e->next_sharing_asm_name)
dump_symtab_node (cgraph_dump_file, e);
}
}
@@ -520,34 +529,35 @@ lto_symtab_merge_decls_1 (symtab_node first)
void
lto_symtab_merge_decls (void)
{
- symtab_node node;
+ symtab_node *node;
/* Populate assembler name hash. */
symtab_initialize_asm_name_hash ();
FOR_EACH_SYMBOL (node)
- if (!node->symbol.previous_sharing_asm_name
- && node->symbol.next_sharing_asm_name)
+ if (!node->previous_sharing_asm_name
+ && node->next_sharing_asm_name)
lto_symtab_merge_decls_1 (node);
}
/* Helper to process the decl chain for the symbol table entry *SLOT. */
static void
-lto_symtab_merge_symbols_1 (symtab_node prevailing)
+lto_symtab_merge_symbols_1 (symtab_node *prevailing)
{
- symtab_node e, next;
+ symtab_node *e;
+ symtab_node *next;
/* Replace the cgraph node of each entry with the prevailing one. */
- for (e = prevailing->symbol.next_sharing_asm_name; e;
+ for (e = prevailing->next_sharing_asm_name; e;
e = next)
{
- next = e->symbol.next_sharing_asm_name;
+ next = e->next_sharing_asm_name;
if (!lto_symtab_symbol_p (e))
continue;
cgraph_node *ce = dyn_cast <cgraph_node> (e);
- if (ce && !DECL_BUILT_IN (e->symbol.decl))
+ if (ce && !DECL_BUILT_IN (e->decl))
lto_cgraph_replace_node (ce, cgraph (prevailing));
if (varpool_node *ve = dyn_cast <varpool_node> (e))
lto_varpool_replace_node (ve, varpool (prevailing));
@@ -562,7 +572,7 @@ lto_symtab_merge_symbols_1 (symtab_node prevailing)
void
lto_symtab_merge_symbols (void)
{
- symtab_node node;
+ symtab_node *node;
if (!flag_ltrans)
{
@@ -574,8 +584,8 @@ lto_symtab_merge_symbols (void)
updated to the ohter dupliate. */
FOR_EACH_SYMBOL (node)
if (lto_symtab_symbol_p (node)
- && node->symbol.next_sharing_asm_name
- && !node->symbol.previous_sharing_asm_name)
+ && node->next_sharing_asm_name
+ && !node->previous_sharing_asm_name)
lto_symtab_merge_symbols_1 (node);
/* Resolve weakref aliases whose target are now in the compilation unit.
@@ -584,26 +594,26 @@ lto_symtab_merge_symbols (void)
{
cgraph_node *cnode, *cnode2;
varpool_node *vnode;
- symtab_node node2;
+ symtab_node *node2;
- if (!node->symbol.analyzed && node->symbol.alias_target)
+ if (!node->analyzed && node->alias_target)
{
- symtab_node tgt = symtab_node_for_asm (node->symbol.alias_target);
- gcc_assert (node->symbol.weakref);
+ symtab_node *tgt = symtab_node_for_asm (node->alias_target);
+ gcc_assert (node->weakref);
if (tgt)
symtab_resolve_alias (node, tgt);
}
- node->symbol.aux = NULL;
+ node->aux = NULL;
if (!(cnode = dyn_cast <cgraph_node> (node))
|| !cnode->clone_of
- || cnode->clone_of->symbol.decl != cnode->symbol.decl)
+ || cnode->clone_of->decl != cnode->decl)
{
/* Builtins are not merged via decl merging. It is however
possible that tree merging unified the declaration. We
do not want duplicate entries in symbol table. */
- if (cnode && DECL_BUILT_IN (node->symbol.decl)
- && (cnode2 = cgraph_get_node (node->symbol.decl))
+ if (cnode && DECL_BUILT_IN (node->decl)
+ && (cnode2 = cgraph_get_node (node->decl))
&& cnode2 != cnode)
lto_cgraph_replace_node (cnode2, cnode);
@@ -611,8 +621,8 @@ lto_symtab_merge_symbols (void)
symbol name (since it is irrelevant), but we need to unify symbol
nodes if tree merging occured. */
if ((vnode = dyn_cast <varpool_node> (node))
- && DECL_HARD_REGISTER (vnode->symbol.decl)
- && (node2 = symtab_get_node (vnode->symbol.decl))
+ && DECL_HARD_REGISTER (vnode->decl)
+ && (node2 = symtab_get_node (vnode->decl))
&& node2 != node)
lto_varpool_replace_node (dyn_cast <varpool_node> (node2),
vnode);
@@ -620,12 +630,12 @@ lto_symtab_merge_symbols (void)
/* Abstract functions may have duplicated cgraph nodes attached;
remove them. */
- else if (cnode && DECL_ABSTRACT (cnode->symbol.decl)
- && (cnode2 = cgraph_get_node (node->symbol.decl))
+ else if (cnode && DECL_ABSTRACT (cnode->decl)
+ && (cnode2 = cgraph_get_node (node->decl))
&& cnode2 != cnode)
cgraph_remove_node (cnode2);
- symtab_insert_node_to_hashtable ((symtab_node)node);
+ symtab_insert_node_to_hashtable (node);
}
}
}
@@ -636,7 +646,7 @@ lto_symtab_merge_symbols (void)
tree
lto_symtab_prevailing_decl (tree decl)
{
- symtab_node ret;
+ symtab_node *ret;
/* Builtins and local symbols are their own prevailing decl. */
if ((!TREE_PUBLIC (decl) && !DECL_EXTERNAL (decl)) || is_builtin_fn (decl))
@@ -659,5 +669,5 @@ lto_symtab_prevailing_decl (tree decl)
if (!ret)
return decl;
- return ret->symbol.decl;
+ return ret->decl;
}
diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c
index 470f3c1d7a7..62856d085b7 100644
--- a/gcc/lto/lto.c
+++ b/gcc/lto/lto.c
@@ -24,7 +24,6 @@ along with GCC; see the file COPYING3. If not see
#include "opts.h"
#include "toplev.h"
#include "tree.h"
-#include "tree-flow.h"
#include "diagnostic-core.h"
#include "tm.h"
#include "cgraph.h"
@@ -172,7 +171,7 @@ has_analyzed_clone_p (struct cgraph_node *node)
if (node)
while (node != orig)
{
- if (node->symbol.analyzed)
+ if (node->analyzed)
return true;
if (node->clones)
node = node->clones;
@@ -196,10 +195,10 @@ lto_materialize_function (struct cgraph_node *node)
{
tree decl;
- decl = node->symbol.decl;
+ decl = node->decl;
/* Read in functions with body (analyzed nodes)
and also functions that are needed to produce virtual clones. */
- if ((cgraph_function_with_gimple_body_p (node) && node->symbol.analyzed)
+ if ((cgraph_function_with_gimple_body_p (node) && node->analyzed)
|| node->used_as_abstract_origin
|| has_analyzed_clone_p (node))
{
@@ -254,153 +253,179 @@ lto_read_in_decl_state (struct data_in *data_in, const uint32_t *data,
}
+/* Global canonical type table. */
+static htab_t gimple_canonical_types;
+static pointer_map <hashval_t> *canonical_type_hash_cache;
+static unsigned long num_canonical_type_hash_entries;
+static unsigned long num_canonical_type_hash_queries;
-/* ??? Old hashing and merging code follows, we keep it for statistics
- purposes for now. */
+static hashval_t iterative_hash_canonical_type (tree type, hashval_t val);
+static hashval_t gimple_canonical_type_hash (const void *p);
+static void gimple_register_canonical_type_1 (tree t, hashval_t hash);
-/* Global type table. FIXME, it should be possible to re-use some
- of the type hashing routines in tree.c (type_hash_canon, type_hash_lookup,
- etc), but those assume that types were built with the various
- build_*_type routines which is not the case with the streamer. */
-static GTY((if_marked ("ggc_marked_p"), param_is (union tree_node)))
- htab_t gimple_types;
-static GTY((if_marked ("tree_int_map_marked_p"), param_is (struct tree_int_map)))
- htab_t type_hash_cache;
+/* Returning a hash value for gimple type TYPE.
-static hashval_t gimple_type_hash (const void *);
+ The hash value returned is equal for types considered compatible
+ by gimple_canonical_types_compatible_p. */
-/* Structure used to maintain a cache of some type pairs compared by
- gimple_types_compatible_p when comparing aggregate types. There are
- three possible values for SAME_P:
-
- -2: The pair (T1, T2) has just been inserted in the table.
- 0: T1 and T2 are different types.
- 1: T1 and T2 are the same type. */
-
-struct type_pair_d
+static hashval_t
+hash_canonical_type (tree type)
{
- unsigned int uid1;
- unsigned int uid2;
- signed char same_p;
-};
-typedef struct type_pair_d *type_pair_t;
+ hashval_t v;
-#define GIMPLE_TYPE_PAIR_SIZE 16381
-struct type_pair_d *type_pair_cache;
+ /* Combine a few common features of types so that types are grouped into
+ smaller sets; when searching for existing matching types to merge,
+ only existing types having the same features as the new type will be
+ checked. */
+ v = iterative_hash_hashval_t (TREE_CODE (type), 0);
+ v = iterative_hash_hashval_t (TREE_ADDRESSABLE (type), v);
+ v = iterative_hash_hashval_t (TYPE_ALIGN (type), v);
+ v = iterative_hash_hashval_t (TYPE_MODE (type), v);
+ /* Incorporate common features of numerical types. */
+ if (INTEGRAL_TYPE_P (type)
+ || SCALAR_FLOAT_TYPE_P (type)
+ || FIXED_POINT_TYPE_P (type)
+ || TREE_CODE (type) == OFFSET_TYPE
+ || POINTER_TYPE_P (type))
+ {
+ v = iterative_hash_hashval_t (TYPE_PRECISION (type), v);
+ v = iterative_hash_hashval_t (TYPE_UNSIGNED (type), v);
+ }
-/* Lookup the pair of types T1 and T2 in *VISITED_P. Insert a new
- entry if none existed. */
+ if (VECTOR_TYPE_P (type))
+ {
+ v = iterative_hash_hashval_t (TYPE_VECTOR_SUBPARTS (type), v);
+ v = iterative_hash_hashval_t (TYPE_UNSIGNED (type), v);
+ }
-static inline type_pair_t
-lookup_type_pair (tree t1, tree t2)
-{
- unsigned int index;
- unsigned int uid1, uid2;
+ if (TREE_CODE (type) == COMPLEX_TYPE)
+ v = iterative_hash_hashval_t (TYPE_UNSIGNED (type), v);
- if (TYPE_UID (t1) < TYPE_UID (t2))
+ /* For pointer and reference types, fold in information about the type
+ pointed to but do not recurse to the pointed-to type. */
+ if (POINTER_TYPE_P (type))
{
- uid1 = TYPE_UID (t1);
- uid2 = TYPE_UID (t2);
+ v = iterative_hash_hashval_t (TYPE_REF_CAN_ALIAS_ALL (type), v);
+ v = iterative_hash_hashval_t (TYPE_ADDR_SPACE (TREE_TYPE (type)), v);
+ v = iterative_hash_hashval_t (TYPE_RESTRICT (type), v);
+ v = iterative_hash_hashval_t (TREE_CODE (TREE_TYPE (type)), v);
}
- else
+
+ /* For integer types hash only the string flag. */
+ if (TREE_CODE (type) == INTEGER_TYPE)
+ v = iterative_hash_hashval_t (TYPE_STRING_FLAG (type), v);
+
+ /* For array types hash the domain bounds and the string flag. */
+ if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type))
{
- uid1 = TYPE_UID (t2);
- uid2 = TYPE_UID (t1);
+ v = iterative_hash_hashval_t (TYPE_STRING_FLAG (type), v);
+ /* OMP lowering can introduce error_mark_node in place of
+ random local decls in types. */
+ if (TYPE_MIN_VALUE (TYPE_DOMAIN (type)) != error_mark_node)
+ v = iterative_hash_expr (TYPE_MIN_VALUE (TYPE_DOMAIN (type)), v);
+ if (TYPE_MAX_VALUE (TYPE_DOMAIN (type)) != error_mark_node)
+ v = iterative_hash_expr (TYPE_MAX_VALUE (TYPE_DOMAIN (type)), v);
}
- gcc_checking_assert (uid1 != uid2);
- /* iterative_hash_hashval_t imply an function calls.
- We know that UIDS are in limited range. */
- index = ((((unsigned HOST_WIDE_INT)uid1 << HOST_BITS_PER_WIDE_INT / 2) + uid2)
- % GIMPLE_TYPE_PAIR_SIZE);
- if (type_pair_cache [index].uid1 == uid1
- && type_pair_cache [index].uid2 == uid2)
- return &type_pair_cache[index];
+ /* Recurse for aggregates with a single element type. */
+ if (TREE_CODE (type) == ARRAY_TYPE
+ || TREE_CODE (type) == COMPLEX_TYPE
+ || TREE_CODE (type) == VECTOR_TYPE)
+ v = iterative_hash_canonical_type (TREE_TYPE (type), v);
- type_pair_cache [index].uid1 = uid1;
- type_pair_cache [index].uid2 = uid2;
- type_pair_cache [index].same_p = -2;
+ /* Incorporate function return and argument types. */
+ if (TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == METHOD_TYPE)
+ {
+ unsigned na;
+ tree p;
- return &type_pair_cache[index];
-}
+ /* For method types also incorporate their parent class. */
+ if (TREE_CODE (type) == METHOD_TYPE)
+ v = iterative_hash_canonical_type (TYPE_METHOD_BASETYPE (type), v);
-/* Per pointer state for the SCC finding. The on_sccstack flag
- is not strictly required, it is true when there is no hash value
- recorded for the type and false otherwise. But querying that
- is slower. */
+ v = iterative_hash_canonical_type (TREE_TYPE (type), v);
-struct sccs
-{
- unsigned int dfsnum;
- unsigned int low;
- bool on_sccstack;
- union {
- hashval_t hash;
- signed char same_p;
- } u;
-};
-
-static unsigned int next_dfs_num;
-static unsigned int gtc_next_dfs_num;
+ for (p = TYPE_ARG_TYPES (type), na = 0; p; p = TREE_CHAIN (p))
+ {
+ v = iterative_hash_canonical_type (TREE_VALUE (p), v);
+ na++;
+ }
-/* Return true if T1 and T2 have the same name. If FOR_COMPLETION_P is
- true then if any type has no name return false, otherwise return
- true if both types have no names. */
+ v = iterative_hash_hashval_t (na, v);
+ }
-static bool
-compare_type_names_p (tree t1, tree t2)
-{
- tree name1 = TYPE_NAME (t1);
- tree name2 = TYPE_NAME (t2);
+ if (RECORD_OR_UNION_TYPE_P (type))
+ {
+ unsigned nf;
+ tree f;
- if ((name1 != NULL_TREE) != (name2 != NULL_TREE))
- return false;
+ for (f = TYPE_FIELDS (type), nf = 0; f; f = TREE_CHAIN (f))
+ if (TREE_CODE (f) == FIELD_DECL)
+ {
+ v = iterative_hash_canonical_type (TREE_TYPE (f), v);
+ nf++;
+ }
- if (name1 == NULL_TREE)
- return true;
+ v = iterative_hash_hashval_t (nf, v);
+ }
- /* Either both should be a TYPE_DECL or both an IDENTIFIER_NODE. */
- if (TREE_CODE (name1) != TREE_CODE (name2))
- return false;
+ return v;
+}
- if (TREE_CODE (name1) == TYPE_DECL)
- name1 = DECL_NAME (name1);
- gcc_checking_assert (!name1 || TREE_CODE (name1) == IDENTIFIER_NODE);
+/* Returning a hash value for gimple type TYPE combined with VAL. */
- if (TREE_CODE (name2) == TYPE_DECL)
- name2 = DECL_NAME (name2);
- gcc_checking_assert (!name2 || TREE_CODE (name2) == IDENTIFIER_NODE);
+static hashval_t
+iterative_hash_canonical_type (tree type, hashval_t val)
+{
+ hashval_t v;
+ /* An already processed type. */
+ if (TYPE_CANONICAL (type))
+ {
+ type = TYPE_CANONICAL (type);
+ v = gimple_canonical_type_hash (type);
+ }
+ else
+ {
+ /* Canonical types should not be able to form SCCs by design, this
+ recursion is just because we do not register canonical types in
+ optimal order. To avoid quadratic behavior also register the
+ type here. */
+ v = hash_canonical_type (type);
+ gimple_register_canonical_type_1 (type, v);
+ }
+ return iterative_hash_hashval_t (v, val);
+}
- /* Identifiers can be compared with pointer equality rather
- than a string comparison. */
- if (name1 == name2)
- return true;
+/* Returns the hash for a canonical type P. */
- return false;
+static hashval_t
+gimple_canonical_type_hash (const void *p)
+{
+ num_canonical_type_hash_queries++;
+ hashval_t *slot
+ = canonical_type_hash_cache->contains (CONST_CAST_TREE ((const_tree) p));
+ gcc_assert (slot != NULL);
+ return *slot;
}
-static bool
-gimple_types_compatible_p_1 (tree, tree, type_pair_t,
- vec<type_pair_t> *,
- struct pointer_map_t *, struct obstack *);
-/* DFS visit the edge from the callers type pair with state *STATE to
- the pair T1, T2 while operating in FOR_MERGING_P mode.
- Update the merging status if it is not part of the SCC containing the
- callers pair and return it.
- SCCSTACK, SCCSTATE and SCCSTATE_OBSTACK are state for the DFS walk done. */
+/* The TYPE_CANONICAL merging machinery. It should closely resemble
+ the middle-end types_compatible_p function. It needs to avoid
+ claiming types are different for types that should be treated
+ the same with respect to TBAA. Canonical types are also used
+ for IL consistency checks via the useless_type_conversion_p
+ predicate which does not handle all type kinds itself but falls
+ back to pointer-comparison of TYPE_CANONICAL for aggregates
+ for example. */
+
+/* Return true iff T1 and T2 are structurally identical for what
+ TBAA is concerned. */
static bool
-gtc_visit (tree t1, tree t2,
- struct sccs *state,
- vec<type_pair_t> *sccstack,
- struct pointer_map_t *sccstate,
- struct obstack *sccstate_obstack)
-{
- struct sccs *cstate = NULL;
- type_pair_t p;
- void **slot;
+gimple_canonical_types_compatible_p (tree t1, tree t2)
+{
+ /* Before starting to set up the SCC machinery handle simple cases. */
/* Check first for the obvious case of pointer identity. */
if (t1 == t2)
@@ -410,28 +435,32 @@ gtc_visit (tree t1, tree t2,
if (t1 == NULL_TREE || t2 == NULL_TREE)
return false;
+ /* If the types have been previously registered and found equal
+ they still are. */
+ if (TYPE_CANONICAL (t1)
+ && TYPE_CANONICAL (t1) == TYPE_CANONICAL (t2))
+ return true;
+
/* Can't be the same type if the types don't have the same code. */
if (TREE_CODE (t1) != TREE_CODE (t2))
return false;
- /* Can't be the same type if they have different CV qualifiers. */
- if (TYPE_QUALS (t1) != TYPE_QUALS (t2))
- return false;
-
if (TREE_ADDRESSABLE (t1) != TREE_ADDRESSABLE (t2))
return false;
+ /* Qualifiers do not matter for canonical type comparison purposes. */
+
/* Void types and nullptr types are always the same. */
if (TREE_CODE (t1) == VOID_TYPE
|| TREE_CODE (t1) == NULLPTR_TYPE)
return true;
- /* Can't be the same type if they have different alignment or mode. */
+ /* Can't be the same type if they have different alignment, or mode. */
if (TYPE_ALIGN (t1) != TYPE_ALIGN (t2)
|| TYPE_MODE (t1) != TYPE_MODE (t2))
return false;
- /* Do some simple checks before doing three hashtable queries. */
+ /* Non-aggregate types can be handled cheaply. */
if (INTEGRAL_TYPE_P (t1)
|| SCALAR_FLOAT_TYPE_P (t1)
|| FIXED_POINT_TYPE_P (t1)
@@ -449,122 +478,47 @@ gtc_visit (tree t1, tree t2,
&& TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2))
return false;
- /* That's all we need to check for float and fixed-point types. */
- if (SCALAR_FLOAT_TYPE_P (t1)
- || FIXED_POINT_TYPE_P (t1))
- return true;
-
- /* For other types fall through to more complex checks. */
- }
-
- /* If the hash values of t1 and t2 are different the types can't
- possibly be the same. This helps keeping the type-pair hashtable
- small, only tracking comparisons for hash collisions. */
- if (gimple_type_hash (t1) != gimple_type_hash (t2))
- return false;
-
- /* Allocate a new cache entry for this comparison. */
- p = lookup_type_pair (t1, t2);
- if (p->same_p == 0 || p->same_p == 1)
- {
- /* We have already decided whether T1 and T2 are the
- same, return the cached result. */
- return p->same_p == 1;
- }
-
- if ((slot = pointer_map_contains (sccstate, p)) != NULL)
- cstate = (struct sccs *)*slot;
- /* Not yet visited. DFS recurse. */
- if (!cstate)
- {
- gimple_types_compatible_p_1 (t1, t2, p,
- sccstack, sccstate, sccstate_obstack);
- cstate = (struct sccs *)* pointer_map_contains (sccstate, p);
- state->low = MIN (state->low, cstate->low);
- }
- /* If the type is still on the SCC stack adjust the parents low. */
- if (cstate->dfsnum < state->dfsnum
- && cstate->on_sccstack)
- state->low = MIN (cstate->dfsnum, state->low);
-
- /* Return the current lattice value. We start with an equality
- assumption so types part of a SCC will be optimistically
- treated equal unless proven otherwise. */
- return cstate->u.same_p;
-}
-
-/* Worker for gimple_types_compatible.
- SCCSTACK, SCCSTATE and SCCSTATE_OBSTACK are state for the DFS walk done. */
-
-static bool
-gimple_types_compatible_p_1 (tree t1, tree t2, type_pair_t p,
- vec<type_pair_t> *sccstack,
- struct pointer_map_t *sccstate,
- struct obstack *sccstate_obstack)
-{
- struct sccs *state;
-
- gcc_assert (p->same_p == -2);
+ /* For canonical type comparisons we do not want to build SCCs
+ so we cannot compare pointed-to types. But we can, for now,
+ require the same pointed-to type kind and match what
+ useless_type_conversion_p would do. */
+ if (POINTER_TYPE_P (t1))
+ {
+ /* If the two pointers have different ref-all attributes,
+ they can't be the same type. */
+ if (TYPE_REF_CAN_ALIAS_ALL (t1) != TYPE_REF_CAN_ALIAS_ALL (t2))
+ return false;
- state = XOBNEW (sccstate_obstack, struct sccs);
- *pointer_map_insert (sccstate, p) = state;
+ if (TYPE_ADDR_SPACE (TREE_TYPE (t1))
+ != TYPE_ADDR_SPACE (TREE_TYPE (t2)))
+ return false;
- sccstack->safe_push (p);
- state->dfsnum = gtc_next_dfs_num++;
- state->low = state->dfsnum;
- state->on_sccstack = true;
- /* Start with an equality assumption. As we DFS recurse into child
- SCCs this assumption may get revisited. */
- state->u.same_p = 1;
+ if (TYPE_RESTRICT (t1) != TYPE_RESTRICT (t2))
+ return false;
- /* The struct tags shall compare equal. */
- if (!compare_type_names_p (t1, t2))
- goto different_types;
+ if (TREE_CODE (TREE_TYPE (t1)) != TREE_CODE (TREE_TYPE (t2)))
+ return false;
+ }
- /* The main variant of both types should compare equal. */
- if (TYPE_MAIN_VARIANT (t1) != t1
- || TYPE_MAIN_VARIANT (t2) != t2)
- {
- if (!gtc_visit (TYPE_MAIN_VARIANT (t1), TYPE_MAIN_VARIANT (t2),
- state, sccstack, sccstate, sccstate_obstack))
- goto different_types;
- }
+ /* Tail-recurse to components. */
+ if (TREE_CODE (t1) == VECTOR_TYPE
+ || TREE_CODE (t1) == COMPLEX_TYPE)
+ return gimple_canonical_types_compatible_p (TREE_TYPE (t1),
+ TREE_TYPE (t2));
- /* We may not merge typedef types to the same type in different
- contexts. */
- if (TYPE_NAME (t1)
- && TREE_CODE (TYPE_NAME (t1)) == TYPE_DECL
- && DECL_CONTEXT (TYPE_NAME (t1))
- && TYPE_P (DECL_CONTEXT (TYPE_NAME (t1))))
- {
- if (!gtc_visit (DECL_CONTEXT (TYPE_NAME (t1)),
- DECL_CONTEXT (TYPE_NAME (t2)),
- state, sccstack, sccstate, sccstate_obstack))
- goto different_types;
+ return true;
}
- /* If their attributes are not the same they can't be the same type. */
- if (!attribute_list_equal (TYPE_ATTRIBUTES (t1), TYPE_ATTRIBUTES (t2)))
- goto different_types;
-
/* Do type-specific comparisons. */
switch (TREE_CODE (t1))
{
- case VECTOR_TYPE:
- case COMPLEX_TYPE:
- if (!gtc_visit (TREE_TYPE (t1), TREE_TYPE (t2),
- state, sccstack, sccstate, sccstate_obstack))
- goto different_types;
- goto same_types;
-
case ARRAY_TYPE:
/* Array types are the same if the element types are the same and
the number of elements are the same. */
- if (!gtc_visit (TREE_TYPE (t1), TREE_TYPE (t2),
- state, sccstack, sccstate, sccstate_obstack)
+ if (!gimple_canonical_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2))
|| TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2)
|| TYPE_NONALIASED_COMPONENT (t1) != TYPE_NONALIASED_COMPONENT (t2))
- goto different_types;
+ return false;
else
{
tree i1 = TYPE_DOMAIN (t1);
@@ -573,9 +527,9 @@ gimple_types_compatible_p_1 (tree t1, tree t2, type_pair_t p,
/* For an incomplete external array, the type domain can be
NULL_TREE. Check this condition also. */
if (i1 == NULL_TREE && i2 == NULL_TREE)
- goto same_types;
+ return true;
else if (i1 == NULL_TREE || i2 == NULL_TREE)
- goto different_types;
+ return false;
else
{
tree min1 = TYPE_MIN_VALUE (i1);
@@ -594,32 +548,24 @@ gimple_types_compatible_p_1 (tree t1, tree t2, type_pair_t p,
&& ((TREE_CODE (max1) == PLACEHOLDER_EXPR
&& TREE_CODE (max2) == PLACEHOLDER_EXPR)
|| operand_equal_p (max1, max2, 0)))))
- goto same_types;
+ return true;
else
- goto different_types;
+ return false;
}
}
case METHOD_TYPE:
- /* Method types should belong to the same class. */
- if (!gtc_visit (TYPE_METHOD_BASETYPE (t1), TYPE_METHOD_BASETYPE (t2),
- state, sccstack, sccstate, sccstate_obstack))
- goto different_types;
-
- /* Fallthru */
-
case FUNCTION_TYPE:
/* Function types are the same if the return type and arguments types
are the same. */
- if (!gtc_visit (TREE_TYPE (t1), TREE_TYPE (t2),
- state, sccstack, sccstate, sccstate_obstack))
- goto different_types;
+ if (!gimple_canonical_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2)))
+ return false;
if (!comp_type_attributes (t1, t2))
- goto different_types;
+ return false;
if (TYPE_ARG_TYPES (t1) == TYPE_ARG_TYPES (t2))
- goto same_types;
+ return true;
else
{
tree parms1, parms2;
@@ -628,118 +574,17 @@ gimple_types_compatible_p_1 (tree t1, tree t2, type_pair_t p,
parms1 && parms2;
parms1 = TREE_CHAIN (parms1), parms2 = TREE_CHAIN (parms2))
{
- if (!gtc_visit (TREE_VALUE (parms1), TREE_VALUE (parms2),
- state, sccstack, sccstate, sccstate_obstack))
- goto different_types;
+ if (!gimple_canonical_types_compatible_p
+ (TREE_VALUE (parms1), TREE_VALUE (parms2)))
+ return false;
}
if (parms1 || parms2)
- goto different_types;
+ return false;
- goto same_types;
+ return true;
}
- case OFFSET_TYPE:
- {
- if (!gtc_visit (TREE_TYPE (t1), TREE_TYPE (t2),
- state, sccstack, sccstate, sccstate_obstack)
- || !gtc_visit (TYPE_OFFSET_BASETYPE (t1),
- TYPE_OFFSET_BASETYPE (t2),
- state, sccstack, sccstate, sccstate_obstack))
- goto different_types;
-
- goto same_types;
- }
-
- case POINTER_TYPE:
- case REFERENCE_TYPE:
- {
- /* If the two pointers have different ref-all attributes,
- they can't be the same type. */
- if (TYPE_REF_CAN_ALIAS_ALL (t1) != TYPE_REF_CAN_ALIAS_ALL (t2))
- goto different_types;
-
- /* Otherwise, pointer and reference types are the same if the
- pointed-to types are the same. */
- if (gtc_visit (TREE_TYPE (t1), TREE_TYPE (t2),
- state, sccstack, sccstate, sccstate_obstack))
- goto same_types;
-
- goto different_types;
- }
-
- case INTEGER_TYPE:
- case BOOLEAN_TYPE:
- {
- tree min1 = TYPE_MIN_VALUE (t1);
- tree max1 = TYPE_MAX_VALUE (t1);
- tree min2 = TYPE_MIN_VALUE (t2);
- tree max2 = TYPE_MAX_VALUE (t2);
- bool min_equal_p = false;
- bool max_equal_p = false;
-
- /* If either type has a minimum value, the other type must
- have the same. */
- if (min1 == NULL_TREE && min2 == NULL_TREE)
- min_equal_p = true;
- else if (min1 && min2 && operand_equal_p (min1, min2, 0))
- min_equal_p = true;
-
- /* Likewise, if either type has a maximum value, the other
- type must have the same. */
- if (max1 == NULL_TREE && max2 == NULL_TREE)
- max_equal_p = true;
- else if (max1 && max2 && operand_equal_p (max1, max2, 0))
- max_equal_p = true;
-
- if (!min_equal_p || !max_equal_p)
- goto different_types;
-
- goto same_types;
- }
-
- case ENUMERAL_TYPE:
- {
- /* FIXME lto, we cannot check bounds on enumeral types because
- different front ends will produce different values.
- In C, enumeral types are integers, while in C++ each element
- will have its own symbolic value. We should decide how enums
- are to be represented in GIMPLE and have each front end lower
- to that. */
- tree v1, v2;
-
- /* For enumeral types, all the values must be the same. */
- if (TYPE_VALUES (t1) == TYPE_VALUES (t2))
- goto same_types;
-
- for (v1 = TYPE_VALUES (t1), v2 = TYPE_VALUES (t2);
- v1 && v2;
- v1 = TREE_CHAIN (v1), v2 = TREE_CHAIN (v2))
- {
- tree c1 = TREE_VALUE (v1);
- tree c2 = TREE_VALUE (v2);
-
- if (TREE_CODE (c1) == CONST_DECL)
- c1 = DECL_INITIAL (c1);
-
- if (TREE_CODE (c2) == CONST_DECL)
- c2 = DECL_INITIAL (c2);
-
- if (tree_int_cst_equal (c1, c2) != 1)
- goto different_types;
-
- if (TREE_PURPOSE (v1) != TREE_PURPOSE (v2))
- goto different_types;
- }
-
- /* If one enumeration has more values than the other, they
- are not the same. */
- if (v1 || v2)
- goto different_types;
-
- goto same_types;
- }
-
case RECORD_TYPE:
case UNION_TYPE:
case QUAL_UNION_TYPE:
@@ -748,543 +593,118 @@ gimple_types_compatible_p_1 (tree t1, tree t2, type_pair_t p,
/* For aggregate types, all the fields must be the same. */
for (f1 = TYPE_FIELDS (t1), f2 = TYPE_FIELDS (t2);
- f1 && f2;
+ f1 || f2;
f1 = TREE_CHAIN (f1), f2 = TREE_CHAIN (f2))
{
- /* Different field kinds are not compatible. */
- if (TREE_CODE (f1) != TREE_CODE (f2))
- goto different_types;
- /* Field decls must have the same name and offset. */
- if (TREE_CODE (f1) == FIELD_DECL
- && (DECL_NONADDRESSABLE_P (f1) != DECL_NONADDRESSABLE_P (f2)
- || !gimple_compare_field_offset (f1, f2)))
- goto different_types;
- /* All entities should have the same name and type. */
- if (DECL_NAME (f1) != DECL_NAME (f2)
- || !gtc_visit (TREE_TYPE (f1), TREE_TYPE (f2),
- state, sccstack, sccstate, sccstate_obstack))
- goto different_types;
+ /* Skip non-fields. */
+ while (f1 && TREE_CODE (f1) != FIELD_DECL)
+ f1 = TREE_CHAIN (f1);
+ while (f2 && TREE_CODE (f2) != FIELD_DECL)
+ f2 = TREE_CHAIN (f2);
+ if (!f1 || !f2)
+ break;
+ /* The fields must have the same name, offset and type. */
+ if (DECL_NONADDRESSABLE_P (f1) != DECL_NONADDRESSABLE_P (f2)
+ || !gimple_compare_field_offset (f1, f2)
+ || !gimple_canonical_types_compatible_p
+ (TREE_TYPE (f1), TREE_TYPE (f2)))
+ return false;
}
/* If one aggregate has more fields than the other, they
are not the same. */
if (f1 || f2)
- goto different_types;
+ return false;
- goto same_types;
+ return true;
}
default:
gcc_unreachable ();
}
-
- /* Common exit path for types that are not compatible. */
-different_types:
- state->u.same_p = 0;
- goto pop;
-
- /* Common exit path for types that are compatible. */
-same_types:
- gcc_assert (state->u.same_p == 1);
-
-pop:
- if (state->low == state->dfsnum)
- {
- type_pair_t x;
-
- /* Pop off the SCC and set its cache values to the final
- comparison result. */
- do
- {
- struct sccs *cstate;
- x = sccstack->pop ();
- cstate = (struct sccs *)*pointer_map_contains (sccstate, x);
- cstate->on_sccstack = false;
- x->same_p = state->u.same_p;
- }
- while (x != p);
- }
-
- return state->u.same_p;
-}
-
-/* Return true iff T1 and T2 are structurally identical. When
- FOR_MERGING_P is true the an incomplete type and a complete type
- are considered different, otherwise they are considered compatible. */
-
-static bool
-gimple_types_compatible_p (tree t1, tree t2)
-{
- vec<type_pair_t> sccstack = vNULL;
- struct pointer_map_t *sccstate;
- struct obstack sccstate_obstack;
- type_pair_t p = NULL;
- bool res;
-
- /* Before starting to set up the SCC machinery handle simple cases. */
-
- /* Check first for the obvious case of pointer identity. */
- if (t1 == t2)
- return true;
-
- /* Check that we have two types to compare. */
- if (t1 == NULL_TREE || t2 == NULL_TREE)
- return false;
-
- /* Can't be the same type if the types don't have the same code. */
- if (TREE_CODE (t1) != TREE_CODE (t2))
- return false;
-
- /* Can't be the same type if they have different CV qualifiers. */
- if (TYPE_QUALS (t1) != TYPE_QUALS (t2))
- return false;
-
- if (TREE_ADDRESSABLE (t1) != TREE_ADDRESSABLE (t2))
- return false;
-
- /* Void types and nullptr types are always the same. */
- if (TREE_CODE (t1) == VOID_TYPE
- || TREE_CODE (t1) == NULLPTR_TYPE)
- return true;
-
- /* Can't be the same type if they have different alignment or mode. */
- if (TYPE_ALIGN (t1) != TYPE_ALIGN (t2)
- || TYPE_MODE (t1) != TYPE_MODE (t2))
- return false;
-
- /* Do some simple checks before doing three hashtable queries. */
- if (INTEGRAL_TYPE_P (t1)
- || SCALAR_FLOAT_TYPE_P (t1)
- || FIXED_POINT_TYPE_P (t1)
- || TREE_CODE (t1) == VECTOR_TYPE
- || TREE_CODE (t1) == COMPLEX_TYPE
- || TREE_CODE (t1) == OFFSET_TYPE
- || POINTER_TYPE_P (t1))
- {
- /* Can't be the same type if they have different sign or precision. */
- if (TYPE_PRECISION (t1) != TYPE_PRECISION (t2)
- || TYPE_UNSIGNED (t1) != TYPE_UNSIGNED (t2))
- return false;
-
- if (TREE_CODE (t1) == INTEGER_TYPE
- && TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2))
- return false;
-
- /* That's all we need to check for float and fixed-point types. */
- if (SCALAR_FLOAT_TYPE_P (t1)
- || FIXED_POINT_TYPE_P (t1))
- return true;
-
- /* For other types fall through to more complex checks. */
- }
-
- /* If the hash values of t1 and t2 are different the types can't
- possibly be the same. This helps keeping the type-pair hashtable
- small, only tracking comparisons for hash collisions. */
- if (gimple_type_hash (t1) != gimple_type_hash (t2))
- return false;
-
- /* If we've visited this type pair before (in the case of aggregates
- with self-referential types), and we made a decision, return it. */
- p = lookup_type_pair (t1, t2);
- if (p->same_p == 0 || p->same_p == 1)
- {
- /* We have already decided whether T1 and T2 are the
- same, return the cached result. */
- return p->same_p == 1;
- }
-
- /* Now set up the SCC machinery for the comparison. */
- gtc_next_dfs_num = 1;
- sccstate = pointer_map_create ();
- gcc_obstack_init (&sccstate_obstack);
- res = gimple_types_compatible_p_1 (t1, t2, p,
- &sccstack, sccstate, &sccstate_obstack);
- sccstack.release ();
- pointer_map_destroy (sccstate);
- obstack_free (&sccstate_obstack, NULL);
-
- return res;
-}
-
-static hashval_t
-iterative_hash_gimple_type (tree, hashval_t, vec<tree> *,
- struct pointer_map_t *, struct obstack *);
-
-/* DFS visit the edge from the callers type with state *STATE to T.
- Update the callers type hash V with the hash for T if it is not part
- of the SCC containing the callers type and return it.
- SCCSTACK, SCCSTATE and SCCSTATE_OBSTACK are state for the DFS walk done. */
-
-static hashval_t
-visit (tree t, struct sccs *state, hashval_t v,
- vec<tree> *sccstack,
- struct pointer_map_t *sccstate,
- struct obstack *sccstate_obstack)
-{
- struct sccs *cstate = NULL;
- struct tree_int_map m;
- void **slot;
-
- /* If there is a hash value recorded for this type then it can't
- possibly be part of our parent SCC. Simply mix in its hash. */
- m.base.from = t;
- if ((slot = htab_find_slot (type_hash_cache, &m, NO_INSERT))
- && *slot)
- return iterative_hash_hashval_t (((struct tree_int_map *) *slot)->to, v);
-
- if ((slot = pointer_map_contains (sccstate, t)) != NULL)
- cstate = (struct sccs *)*slot;
- if (!cstate)
- {
- hashval_t tem;
- /* Not yet visited. DFS recurse. */
- tem = iterative_hash_gimple_type (t, v,
- sccstack, sccstate, sccstate_obstack);
- if (!cstate)
- cstate = (struct sccs *)* pointer_map_contains (sccstate, t);
- state->low = MIN (state->low, cstate->low);
- /* If the type is no longer on the SCC stack and thus is not part
- of the parents SCC mix in its hash value. Otherwise we will
- ignore the type for hashing purposes and return the unaltered
- hash value. */
- if (!cstate->on_sccstack)
- return tem;
- }
- if (cstate->dfsnum < state->dfsnum
- && cstate->on_sccstack)
- state->low = MIN (cstate->dfsnum, state->low);
-
- /* We are part of our parents SCC, skip this type during hashing
- and return the unaltered hash value. */
- return v;
}
-/* Hash NAME with the previous hash value V and return it. */
-static hashval_t
-iterative_hash_name (tree name, hashval_t v)
-{
- if (!name)
- return v;
- v = iterative_hash_hashval_t (TREE_CODE (name), v);
- if (TREE_CODE (name) == TYPE_DECL)
- name = DECL_NAME (name);
- if (!name)
- return v;
- gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
- return iterative_hash_object (IDENTIFIER_HASH_VALUE (name), v);
-}
-
-/* A type, hashvalue pair for sorting SCC members. */
-
-struct type_hash_pair {
- tree type;
- hashval_t hash;
-};
-
-/* Compare two type, hashvalue pairs. */
+/* Returns nonzero if P1 and P2 are equal. */
static int
-type_hash_pair_compare (const void *p1_, const void *p2_)
+gimple_canonical_type_eq (const void *p1, const void *p2)
{
- const struct type_hash_pair *p1 = (const struct type_hash_pair *) p1_;
- const struct type_hash_pair *p2 = (const struct type_hash_pair *) p2_;
- if (p1->hash < p2->hash)
- return -1;
- else if (p1->hash > p2->hash)
- return 1;
- return 0;
+ const_tree t1 = (const_tree) p1;
+ const_tree t2 = (const_tree) p2;
+ return gimple_canonical_types_compatible_p (CONST_CAST_TREE (t1),
+ CONST_CAST_TREE (t2));
}
-/* Returning a hash value for gimple type TYPE combined with VAL.
- SCCSTACK, SCCSTATE and SCCSTATE_OBSTACK are state for the DFS walk done.
+/* Main worker for gimple_register_canonical_type. */
- To hash a type we end up hashing in types that are reachable.
- Through pointers we can end up with cycles which messes up the
- required property that we need to compute the same hash value
- for structurally equivalent types. To avoid this we have to
- hash all types in a cycle (the SCC) in a commutative way. The
- easiest way is to not mix in the hashes of the SCC members at
- all. To make this work we have to delay setting the hash
- values of the SCC until it is complete. */
-
-static hashval_t
-iterative_hash_gimple_type (tree type, hashval_t val,
- vec<tree> *sccstack,
- struct pointer_map_t *sccstate,
- struct obstack *sccstate_obstack)
+static void
+gimple_register_canonical_type_1 (tree t, hashval_t hash)
{
- hashval_t v;
void **slot;
- struct sccs *state;
-
- /* Not visited during this DFS walk. */
- gcc_checking_assert (!pointer_map_contains (sccstate, type));
- state = XOBNEW (sccstate_obstack, struct sccs);
- *pointer_map_insert (sccstate, type) = state;
-
- sccstack->safe_push (type);
- state->dfsnum = next_dfs_num++;
- state->low = state->dfsnum;
- state->on_sccstack = true;
-
- /* Combine a few common features of types so that types are grouped into
- smaller sets; when searching for existing matching types to merge,
- only existing types having the same features as the new type will be
- checked. */
- v = iterative_hash_name (TYPE_NAME (type), 0);
- if (TYPE_NAME (type)
- && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
- && DECL_CONTEXT (TYPE_NAME (type))
- && TYPE_P (DECL_CONTEXT (TYPE_NAME (type))))
- v = visit (DECL_CONTEXT (TYPE_NAME (type)), state, v,
- sccstack, sccstate, sccstate_obstack);
-
- /* Factor in the variant structure. */
- if (TYPE_MAIN_VARIANT (type) != type)
- v = visit (TYPE_MAIN_VARIANT (type), state, v,
- sccstack, sccstate, sccstate_obstack);
-
- v = iterative_hash_hashval_t (TREE_CODE (type), v);
- v = iterative_hash_hashval_t (TYPE_QUALS (type), v);
- v = iterative_hash_hashval_t (TREE_ADDRESSABLE (type), v);
-
- /* Do not hash the types size as this will cause differences in
- hash values for the complete vs. the incomplete type variant. */
-
- /* Incorporate common features of numerical types. */
- if (INTEGRAL_TYPE_P (type)
- || SCALAR_FLOAT_TYPE_P (type)
- || FIXED_POINT_TYPE_P (type))
- {
- v = iterative_hash_hashval_t (TYPE_PRECISION (type), v);
- v = iterative_hash_hashval_t (TYPE_MODE (type), v);
- v = iterative_hash_hashval_t (TYPE_UNSIGNED (type), v);
- }
-
- /* For pointer and reference types, fold in information about the type
- pointed to. */
- if (POINTER_TYPE_P (type))
- v = visit (TREE_TYPE (type), state, v,
- sccstack, sccstate, sccstate_obstack);
-
- /* For integer types hash the types min/max values and the string flag. */
- if (TREE_CODE (type) == INTEGER_TYPE)
- {
- /* OMP lowering can introduce error_mark_node in place of
- random local decls in types. */
- if (TYPE_MIN_VALUE (type) != error_mark_node)
- v = iterative_hash_expr (TYPE_MIN_VALUE (type), v);
- if (TYPE_MAX_VALUE (type) != error_mark_node)
- v = iterative_hash_expr (TYPE_MAX_VALUE (type), v);
- v = iterative_hash_hashval_t (TYPE_STRING_FLAG (type), v);
- }
- /* For array types hash the domain and the string flag. */
- if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type))
- {
- v = iterative_hash_hashval_t (TYPE_STRING_FLAG (type), v);
- v = visit (TYPE_DOMAIN (type), state, v,
- sccstack, sccstate, sccstate_obstack);
- }
-
- /* Recurse for aggregates with a single element type. */
- if (TREE_CODE (type) == ARRAY_TYPE
- || TREE_CODE (type) == COMPLEX_TYPE
- || TREE_CODE (type) == VECTOR_TYPE)
- v = visit (TREE_TYPE (type), state, v,
- sccstack, sccstate, sccstate_obstack);
+ gcc_checking_assert (TYPE_P (t) && !TYPE_CANONICAL (t));
- /* Incorporate function return and argument types. */
- if (TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == METHOD_TYPE)
+ slot = htab_find_slot_with_hash (gimple_canonical_types, t, hash, INSERT);
+ if (*slot)
{
- unsigned na;
- tree p;
-
- /* For method types also incorporate their parent class. */
- if (TREE_CODE (type) == METHOD_TYPE)
- v = visit (TYPE_METHOD_BASETYPE (type), state, v,
- sccstack, sccstate, sccstate_obstack);
-
- /* Check result and argument types. */
- v = visit (TREE_TYPE (type), state, v,
- sccstack, sccstate, sccstate_obstack);
- for (p = TYPE_ARG_TYPES (type), na = 0; p; p = TREE_CHAIN (p))
- {
- v = visit (TREE_VALUE (p), state, v,
- sccstack, sccstate, sccstate_obstack);
- na++;
- }
-
- v = iterative_hash_hashval_t (na, v);
+ tree new_type = (tree)(*slot);
+ gcc_checking_assert (new_type != t);
+ TYPE_CANONICAL (t) = new_type;
}
-
- if (RECORD_OR_UNION_TYPE_P (type))
- {
- unsigned nf;
- tree f;
-
- for (f = TYPE_FIELDS (type), nf = 0; f; f = TREE_CHAIN (f))
- {
- v = iterative_hash_name (DECL_NAME (f), v);
- v = visit (TREE_TYPE (f), state, v,
- sccstack, sccstate, sccstate_obstack);
- nf++;
- }
-
- v = iterative_hash_hashval_t (nf, v);
- }
-
- /* Record hash for us. */
- state->u.hash = v;
-
- /* See if we found an SCC. */
- if (state->low == state->dfsnum)
+ else
{
- tree x;
- struct tree_int_map *m;
-
- /* Pop off the SCC and set its hash values. */
- x = sccstack->pop ();
- /* Optimize SCC size one. */
- if (x == type)
- {
- state->on_sccstack = false;
- m = ggc_alloc_cleared_tree_int_map ();
- m->base.from = x;
- m->to = v;
- slot = htab_find_slot (type_hash_cache, m, INSERT);
- gcc_assert (!*slot);
- *slot = (void *) m;
- }
- else
- {
- struct sccs *cstate;
- unsigned first, i, size, j;
- struct type_hash_pair *pairs;
- /* Pop off the SCC and build an array of type, hash pairs. */
- first = sccstack->length () - 1;
- while ((*sccstack)[first] != type)
- --first;
- size = sccstack->length () - first + 1;
- pairs = XALLOCAVEC (struct type_hash_pair, size);
- i = 0;
- cstate = (struct sccs *)*pointer_map_contains (sccstate, x);
- cstate->on_sccstack = false;
- pairs[i].type = x;
- pairs[i].hash = cstate->u.hash;
- do
- {
- x = sccstack->pop ();
- cstate = (struct sccs *)*pointer_map_contains (sccstate, x);
- cstate->on_sccstack = false;
- ++i;
- pairs[i].type = x;
- pairs[i].hash = cstate->u.hash;
- }
- while (x != type);
- gcc_assert (i + 1 == size);
- /* Sort the arrays of type, hash pairs so that when we mix in
- all members of the SCC the hash value becomes independent on
- the order we visited the SCC. Disregard hashes equal to
- the hash of the type we mix into because we cannot guarantee
- a stable sort for those across different TUs. */
- qsort (pairs, size, sizeof (struct type_hash_pair),
- type_hash_pair_compare);
- for (i = 0; i < size; ++i)
- {
- hashval_t hash;
- m = ggc_alloc_cleared_tree_int_map ();
- m->base.from = pairs[i].type;
- hash = pairs[i].hash;
- /* Skip same hashes. */
- for (j = i + 1; j < size && pairs[j].hash == pairs[i].hash; ++j)
- ;
- for (; j < size; ++j)
- hash = iterative_hash_hashval_t (pairs[j].hash, hash);
- for (j = 0; pairs[j].hash != pairs[i].hash; ++j)
- hash = iterative_hash_hashval_t (pairs[j].hash, hash);
- m->to = hash;
- if (pairs[i].type == type)
- v = hash;
- slot = htab_find_slot (type_hash_cache, m, INSERT);
- gcc_assert (!*slot);
- *slot = (void *) m;
- }
- }
+ TYPE_CANONICAL (t) = t;
+ *slot = (void *) t;
+ /* Cache the just computed hash value. */
+ num_canonical_type_hash_entries++;
+ bool existed_p;
+ hashval_t *hslot = canonical_type_hash_cache->insert (t, &existed_p);
+ gcc_assert (!existed_p);
+ *hslot = hash;
}
-
- return iterative_hash_hashval_t (v, val);
}
-/* Returns a hash value for P (assumed to be a type). The hash value
- is computed using some distinguishing features of the type. Note
- that we cannot use pointer hashing here as we may be dealing with
- two distinct instances of the same type.
+/* Register type T in the global type table gimple_types and set
+ TYPE_CANONICAL of T accordingly.
+ This is used by LTO to merge structurally equivalent types for
+ type-based aliasing purposes across different TUs and languages.
- This function should produce the same hash value for two compatible
- types according to gimple_types_compatible_p. */
+ ??? This merging does not exactly match how the tree.c middle-end
+ functions will assign TYPE_CANONICAL when new types are created
+ during optimization (which at least happens for pointer and array
+ types). */
-static hashval_t
-gimple_type_hash (const void *p)
+static void
+gimple_register_canonical_type (tree t)
{
- const_tree t = (const_tree) p;
- vec<tree> sccstack = vNULL;
- struct pointer_map_t *sccstate;
- struct obstack sccstate_obstack;
- hashval_t val;
- void **slot;
- struct tree_int_map m;
-
- m.base.from = CONST_CAST_TREE (t);
- if ((slot = htab_find_slot (type_hash_cache, &m, NO_INSERT))
- && *slot)
- return iterative_hash_hashval_t (((struct tree_int_map *) *slot)->to, 0);
-
- /* Perform a DFS walk and pre-hash all reachable types. */
- next_dfs_num = 1;
- sccstate = pointer_map_create ();
- gcc_obstack_init (&sccstate_obstack);
- val = iterative_hash_gimple_type (CONST_CAST_TREE (t), 0,
- &sccstack, sccstate, &sccstate_obstack);
- sccstack.release ();
- pointer_map_destroy (sccstate);
- obstack_free (&sccstate_obstack, NULL);
+ if (TYPE_CANONICAL (t))
+ return;
- return val;
+ gimple_register_canonical_type_1 (t, hash_canonical_type (t));
}
-/* Returns nonzero if P1 and P2 are equal. */
+/* Re-compute TYPE_CANONICAL for NODE and related types. */
-static int
-gimple_type_eq (const void *p1, const void *p2)
+static void
+lto_register_canonical_types (tree node, bool first_p)
{
- const_tree t1 = (const_tree) p1;
- const_tree t2 = (const_tree) p2;
- return gimple_types_compatible_p (CONST_CAST_TREE (t1),
- CONST_CAST_TREE (t2));
-}
-
-/* Register type T in the global type table gimple_types. */
+ if (!node
+ || !TYPE_P (node))
+ return;
-static tree
-gimple_register_type (tree t)
-{
- void **slot;
+ if (first_p)
+ TYPE_CANONICAL (node) = NULL_TREE;
- /* See if we already have an equivalent type registered. */
- slot = htab_find_slot (gimple_types, t, INSERT);
- if (*slot
- && *(tree *)slot != t)
- return (tree) *((tree *) slot);
+ if (POINTER_TYPE_P (node)
+ || TREE_CODE (node) == COMPLEX_TYPE
+ || TREE_CODE (node) == ARRAY_TYPE)
+ lto_register_canonical_types (TREE_TYPE (node), first_p);
- /* If not, insert it to the cache and the hash. */
- *slot = (void *) t;
- return t;
+ if (!first_p)
+ gimple_register_canonical_type (node);
}
-/* End of old merging code. */
/* Remember trees that contains references to declarations. */
static GTY(()) vec <tree, va_gc> *tree_with_vars;
@@ -1724,10 +1144,6 @@ static struct obstack tree_scc_hash_obstack;
static unsigned long num_merged_types;
static unsigned long num_prevailing_types;
-static unsigned long num_not_merged_types;
-static unsigned long num_not_merged_types_in_same_scc;
-static unsigned long num_not_merged_types_trees;
-static unsigned long num_not_merged_types_in_same_scc_trees;
static unsigned long num_type_scc_trees;
static unsigned long total_scc_size;
static unsigned long num_sccs_read;
@@ -2449,38 +1865,10 @@ lto_read_decls (struct lto_file_decl_data *decl_data, const void *data,
/* Do remaining fixup tasks for prevailing nodes. */
bool seen_type = false;
- bool not_merged_type_same_scc = false;
- bool not_merged_type_not_same_scc = false;
for (unsigned i = 0; i < len; ++i)
{
tree t = streamer_tree_cache_get_tree (data_in->reader_cache,
from + i);
- /* For statistics, see if the old code would have merged
- the type. */
- if (TYPE_P (t)
- && (flag_lto_report || (flag_wpa && flag_lto_report_wpa)))
- {
- tree newt = gimple_register_type (t);
- if (newt != t)
- {
- num_not_merged_types++;
- unsigned j;
- /* Check if we can never merge the types because
- they are in the same SCC and thus the old
- code was broken. */
- for (j = 0; j < len; ++j)
- if (i != j
- && streamer_tree_cache_get_tree
- (data_in->reader_cache, from + j) == newt)
- {
- num_not_merged_types_in_same_scc++;
- not_merged_type_same_scc = true;
- break;
- }
- if (j == len)
- not_merged_type_not_same_scc = true;
- }
- }
/* Reconstruct the type variant and pointer-to/reference-to
chains. */
if (TYPE_P (t))
@@ -2492,7 +1880,7 @@ lto_read_decls (struct lto_file_decl_data *decl_data, const void *data,
/* Compute the canonical type of all types.
??? Should be able to assert that !TYPE_CANONICAL. */
if (TYPE_P (t) && !TYPE_CANONICAL (t))
- TYPE_CANONICAL (t) = gimple_register_canonical_type (t);
+ gimple_register_canonical_type (t);
/* Link shared INTEGER_CSTs into TYPE_CACHED_VALUEs of its
type which is also member of this SCC. */
if (TREE_CODE (t) == INTEGER_CST
@@ -2517,13 +1905,6 @@ lto_read_decls (struct lto_file_decl_data *decl_data, const void *data,
vec_safe_push (tree_with_vars, t);
}
}
- if (not_merged_type_same_scc)
- {
- num_not_merged_types_in_same_scc_trees += len;
- num_not_merged_types_trees += len;
- }
- else if (not_merged_type_not_same_scc)
- num_not_merged_types_trees += len;
if (seen_type)
num_type_scc_trees += len;
}
@@ -3017,9 +2398,9 @@ cmp_partitions_order (const void *a, const void *b)
int ordera = -1, orderb = -1;
if (lto_symtab_encoder_size (pa->encoder))
- ordera = lto_symtab_encoder_deref (pa->encoder, 0)->symbol.order;
+ ordera = lto_symtab_encoder_deref (pa->encoder, 0)->order;
if (lto_symtab_encoder_size (pb->encoder))
- orderb = lto_symtab_encoder_deref (pb->encoder, 0)->symbol.order;
+ orderb = lto_symtab_encoder_deref (pb->encoder, 0)->order;
return orderb - ordera;
}
@@ -3098,14 +2479,14 @@ lto_wpa_write_files (void)
for (lsei = lsei_start_in_partition (part->encoder); !lsei_end_p (lsei);
lsei_next_in_partition (&lsei))
{
- symtab_node node = lsei_node (lsei);
+ symtab_node *node = lsei_node (lsei);
fprintf (cgraph_dump_file, "%s ", symtab_node_asm_name (node));
}
fprintf (cgraph_dump_file, "\n Symbols in boundary: ");
for (lsei = lsei_start (part->encoder); !lsei_end_p (lsei);
lsei_next (&lsei))
{
- symtab_node node = lsei_node (lsei);
+ symtab_node *node = lsei_node (lsei);
if (!lto_symtab_encoder_in_partition_p (part->encoder, node))
{
fprintf (cgraph_dump_file, "%s ", symtab_node_asm_name (node));
@@ -3369,7 +2750,7 @@ read_cgraph_and_symbols (unsigned nfiles, const char **fnames)
int count = 0;
struct lto_file_decl_data **decl_data;
void **res;
- symtab_node snode;
+ symtab_node *snode;
init_cgraph ();
@@ -3398,13 +2779,30 @@ read_cgraph_and_symbols (unsigned nfiles, const char **fnames)
}
cgraph_state = CGRAPH_LTO_STREAMING;
- type_hash_cache = htab_create_ggc (512, tree_int_map_hash,
- tree_int_map_eq, NULL);
- type_pair_cache = XCNEWVEC (struct type_pair_d, GIMPLE_TYPE_PAIR_SIZE);
- gimple_types = htab_create_ggc (16381, gimple_type_hash, gimple_type_eq, 0);
+ canonical_type_hash_cache = new pointer_map <hashval_t>;
+ gimple_canonical_types = htab_create_ggc (16381, gimple_canonical_type_hash,
+ gimple_canonical_type_eq, 0);
gcc_obstack_init (&tree_scc_hash_obstack);
tree_scc_hash.create (4096);
+ /* Register the common node types with the canonical type machinery so
+ we properly share alias-sets across languages and TUs. Do not
+ expose the common nodes as type merge target - those that should be
+ are already exposed so by pre-loading the LTO streamer caches.
+ Do two passes - first clear TYPE_CANONICAL and then re-compute it. */
+ for (i = 0; i < itk_none; ++i)
+ lto_register_canonical_types (integer_types[i], true);
+ for (i = 0; i < stk_type_kind_last; ++i)
+ lto_register_canonical_types (sizetype_tab[i], true);
+ for (i = 0; i < TI_MAX; ++i)
+ lto_register_canonical_types (global_trees[i], true);
+ for (i = 0; i < itk_none; ++i)
+ lto_register_canonical_types (integer_types[i], false);
+ for (i = 0; i < stk_type_kind_last; ++i)
+ lto_register_canonical_types (sizetype_tab[i], false);
+ for (i = 0; i < TI_MAX; ++i)
+ lto_register_canonical_types (global_trees[i], false);
+
if (!quiet_flag)
fprintf (stderr, "Reading object files:");
@@ -3451,15 +2849,12 @@ read_cgraph_and_symbols (unsigned nfiles, const char **fnames)
print_lto_report_1 ();
/* Free gimple type merging datastructures. */
- htab_delete (gimple_types);
- gimple_types = NULL;
- htab_delete (type_hash_cache);
- type_hash_cache = NULL;
- free (type_pair_cache);
- type_pair_cache = NULL;
tree_scc_hash.dispose ();
obstack_free (&tree_scc_hash_obstack, NULL);
- free_gimple_type_tables ();
+ htab_delete (gimple_canonical_types);
+ gimple_canonical_types = NULL;
+ delete canonical_type_hash_cache;
+ canonical_type_hash_cache = NULL;
ggc_collect ();
/* Set the hooks so that all of the ipa passes can read in their data. */
@@ -3478,11 +2873,11 @@ read_cgraph_and_symbols (unsigned nfiles, const char **fnames)
FOR_EACH_SYMBOL (snode)
if (symtab_real_symbol_p (snode)
- && snode->symbol.lto_file_data
- && snode->symbol.lto_file_data->resolution_map
- && (res = pointer_map_contains (snode->symbol.lto_file_data->resolution_map,
- snode->symbol.decl)))
- snode->symbol.resolution
+ && snode->lto_file_data
+ && snode->lto_file_data->resolution_map
+ && (res = pointer_map_contains (snode->lto_file_data->resolution_map,
+ snode->decl)))
+ snode->resolution
= (enum ld_plugin_symbol_resolution)(size_t)*res;
for (i = 0; all_file_decl_data[i]; i++)
if (all_file_decl_data[i]->resolution_map)
@@ -3584,7 +2979,7 @@ materialize_cgraph (void)
FOR_EACH_FUNCTION (node)
{
- if (node->symbol.lto_file_data)
+ if (node->lto_file_data)
{
lto_materialize_function (node);
lto_stats.num_input_cgraph_nodes++;
@@ -3657,15 +3052,19 @@ print_lto_report_1 (void)
fprintf (stderr, "[%s] Merged %lu types\n", pfx, num_merged_types);
fprintf (stderr, "[%s] %lu types prevailed (%lu associated trees)\n",
pfx, num_prevailing_types, num_type_scc_trees);
- fprintf (stderr, "[%s] Old merging code merges an additional %lu types"
- " of which %lu are in the same SCC with their "
- "prevailing variant (%lu and %lu associated trees)\n",
- pfx, num_not_merged_types, num_not_merged_types_in_same_scc,
- num_not_merged_types_trees,
- num_not_merged_types_in_same_scc_trees);
+ fprintf (stderr, "[%s] GIMPLE canonical type table: size %ld, "
+ "%ld elements, %ld searches, %ld collisions (ratio: %f)\n", pfx,
+ (long) htab_size (gimple_canonical_types),
+ (long) htab_elements (gimple_canonical_types),
+ (long) gimple_canonical_types->searches,
+ (long) gimple_canonical_types->collisions,
+ htab_collisions (gimple_canonical_types));
+ fprintf (stderr, "[%s] GIMPLE canonical type pointer-map: "
+ "%lu elements, %ld searches\n", pfx,
+ num_canonical_type_hash_entries,
+ num_canonical_type_hash_queries);
}
- print_gimple_types_stats (pfx);
print_lto_report (pfx);
}
@@ -3675,7 +3074,7 @@ print_lto_report_1 (void)
static void
do_whole_program_analysis (void)
{
- symtab_node node;
+ symtab_node *node;
timevar_start (TV_PHASE_OPT_GEN);
@@ -3727,7 +3126,7 @@ do_whole_program_analysis (void)
/* AUX pointers are used by partitioning code to bookkeep number of
partitions symbol is in. This is no longer needed. */
FOR_EACH_SYMBOL (node)
- node->symbol.aux = NULL;
+ node->aux = NULL;
lto_stats.num_cgraph_partitions += ltrans_partitions.length ();
timevar_pop (TV_WHOPR_PARTITIONING);
@@ -3889,7 +3288,7 @@ lto_main (void)
/* Record the global variables. */
FOR_EACH_DEFINED_VARIABLE (vnode)
- vec_safe_push (lto_global_var_decls, vnode->symbol.decl);
+ vec_safe_push (lto_global_var_decls, vnode->decl);
}
}
diff --git a/gcc/machmode.def b/gcc/machmode.def
index 1062f186e8a..8c4cd73a335 100644
--- a/gcc/machmode.def
+++ b/gcc/machmode.def
@@ -121,11 +121,11 @@ along with GCC; see the file COPYING3. If not see
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);
+ 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). The name of the new mode
- is made by prefixing a P to the name MODE. This statement
- may grow a PRECISION argument in the future.
+ 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
diff --git a/gcc/machmode.h b/gcc/machmode.h
index 981ee92a87a..71c72525b4a 100644
--- a/gcc/machmode.h
+++ b/gcc/machmode.h
@@ -174,6 +174,9 @@ extern const unsigned char mode_class[NUM_MACHINE_MODES];
|| CLASS == MODE_ACCUM \
|| CLASS == MODE_UACCUM)
+#define POINTER_BOUNDS_MODE_P(MODE) \
+ (GET_MODE_CLASS (MODE) == MODE_POINTER_BOUNDS)
+
/* Get the size in bytes and bits of an object of mode MODE. */
extern CONST_MODE_SIZE unsigned char mode_size[NUM_MACHINE_MODES];
@@ -269,16 +272,16 @@ public:
bool prefer_smaller_modes ();
private:
- enum machine_mode mode_;
+ enum machine_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 bitsize_;
- HOST_WIDE_INT bitpos_;
- HOST_WIDE_INT bitregion_start_;
- HOST_WIDE_INT bitregion_end_;
- unsigned int align_;
- bool volatilep_;
- int count_;
+ HOST_WIDE_INT m_bitsize;
+ HOST_WIDE_INT m_bitpos;
+ HOST_WIDE_INT m_bitregion_start;
+ HOST_WIDE_INT m_bitregion_end;
+ unsigned int m_align;
+ bool m_volatilep;
+ int m_count;
};
/* Find the best mode to use to access a bit field. */
diff --git a/gcc/mcf.c b/gcc/mcf.c
index 7a716f58177..52020b8c2f8 100644
--- a/gcc/mcf.c
+++ b/gcc/mcf.c
@@ -385,7 +385,7 @@ add_fixup_edge (fixup_graph_type *fixup_graph, int src, int dest,
edge_type type, gcov_type weight, gcov_type cost,
gcov_type max_capacity)
{
- fixup_edge_p curr_edge = add_edge(fixup_graph, src, dest, cost);
+ fixup_edge_p curr_edge = add_edge (fixup_graph, src, dest, cost);
curr_edge->type = type;
curr_edge->weight = weight;
curr_edge->max_capacity = max_capacity;
diff --git a/gcc/melt-run.proto.h b/gcc/melt-run.proto.h
index 106de9e0fa7..9d5ad228f1b 100644
--- a/gcc/melt-run.proto.h
+++ b/gcc/melt-run.proto.h
@@ -1,8 +1,9 @@
/* -*- C -*-
- MELT file melt-run.h included in every generated file.
+ Generated MELT file melt-run.h included in every generated file.
+ Please edit melt-run.proto.h ....
all include files for generated code
- Copyright (C) 2008,2009,2011,2012 Free Software Foundation, Inc.
+ Copyright (C) 2008 - 2013 Free Software Foundation, Inc.
Contributed by Basile Starynkevitch <basile@starynkevitch.net>
and Pierre Vittet <piervit@pvittet.com>
and Romain Geissler <romain.geissler@gmail.com>
@@ -47,7 +48,6 @@ along with GCC; see the file COPYING3. If not see
#include "filenames.h"
#include "tree-pass.h"
#include "tree-dump.h"
-#include "tree-flow.h"
#include "tree-iterator.h"
#include "tree-inline.h"
#include "basic-block.h"
@@ -72,6 +72,9 @@ along with GCC; see the file COPYING3. If not see
#if MELT_GCC_VERSION >= 4009
#include "context.h"
+#include "tree-cfg.h"
+#else
+#include "tree-flow.h"
#endif /* GCC 4.9 */
#include "flags.h"
diff --git a/gcc/melt-runtime.cc b/gcc/melt-runtime.cc
index dcc68dcec70..ca3b6dcedda 100644
--- a/gcc/melt-runtime.cc
+++ b/gcc/melt-runtime.cc
@@ -71,7 +71,6 @@ const int melt_is_plugin = 0;
#include "filenames.h"
#include "tree-pass.h"
#include "tree-dump.h"
-#include "tree-flow.h"
#include "tree-iterator.h"
#include "tree-inline.h"
#include "basic-block.h"
@@ -80,6 +79,9 @@ const int melt_is_plugin = 0;
#if MELT_GCC_VERSION >= 4009
#include "tree-ssa.h"
+#include "tree-cfg.h"
+#else
+#include "tree-flow.h"
#endif
@@ -13636,6 +13638,12 @@ void meltgc_walk_use_def_chain (melt_ptr_t clos_p, melt_ptr_t val_p, tree trvar,
closv = clos_p;
valv = val_p;
MELT_LOCATION_HERE ("meltgc_walk_use_def_chain");
+#if MELT_GCC_VERSION >= 4009
+ /* walk_use_def_chains disappeared in GCC 4.9 */
+ melt_fatal_error ("meltgc_walk_use_def_chain disappears in GCC 4.9, depthfirstflag=%d",
+ (int) depthfirstflag);
+ goto end;
+#else
MELT_CHECK_SIGNAL ();
if (!trvar || TREE_CODE (trvar) != SSA_NAME)
goto end;
@@ -13643,6 +13651,7 @@ void meltgc_walk_use_def_chain (melt_ptr_t clos_p, melt_ptr_t val_p, tree trvar,
goto end;
walk_use_def_chains (trvar, meltgc_usedef_internalfun, &closv, depthfirstflag);
valv = valv; /* So that valv is used here! */
+#endif /*MELT_GCC_VERSION >= 4009 */
end:
MELT_EXITFRAME ();
#undef closv
diff --git a/gcc/melt-runtime.h b/gcc/melt-runtime.h
index 8097344eafc..be82cc820d6 100644
--- a/gcc/melt-runtime.h
+++ b/gcc/melt-runtime.h
@@ -117,7 +117,7 @@ MELT_EXTERN int melt_count_runtime_extensions;
/* The version string of MELT; this is parsed by make, so spaces are
important! That version string is extracted by scripts or
makefiles... */
-#define MELT_VERSION_STRING "1.0.1"
+#define MELT_VERSION_STRING "1.0.1+"
/* return a read only version string */
extern const char* melt_version_str(void);
diff --git a/gcc/melt/xtramelt-ana-gimple.melt b/gcc/melt/xtramelt-ana-gimple.melt
index b73068c45b8..f1843a17855 100644
--- a/gcc/melt/xtramelt-ana-gimple.melt
+++ b/gcc/melt/xtramelt-ana-gimple.melt
@@ -2436,8 +2436,12 @@ secondary result. The $TREECLOS function, if given, gets the $DATA and
the ran :tree as arguments, and return a boolean value, with a subtree
walking :long flag and the replacing :tree, if any, as secondary results }#
;;
- #{ /* walk_gimple_seq */ meltgc_walk_gimple_seq ((melt_ptr_t)$DATA, ($GSEQ),
- $STMTCLOS, $TREECLOS, FALSE)
+ #{ /* walk_gimple_seq */
+#if MELT_GCC_VERSION >= 4009
+#warning MELT walk_gimple_seq is obsolete with GCC 4.9
+#endif /* GCC >= 4.9 */
+ meltgc_walk_gimple_seq ((melt_ptr_t)$DATA, ($GSEQ),
+ $STMTCLOS, $TREECLOS, FALSE)
}#)
(defprimitive walk_gimple_seq_unique_tree (:value data :gimple_seq gseq :value stmtclos treeclos) :gimple
@@ -2446,6 +2450,9 @@ the given $GSEQ like $WALK_GIMPLE_SEQ, applying $STMTCLOS to gimples
and $TREECLOS to trees, but avoid walking more than once inside
trees.}#
#{ /* walk_gimple_seq_unique_tree */
+#if MELT_GCC_VERSION >= 4009
+#warning MELT walk_gimple_seq_unique_tree is obsolete with GCC 4.9
+#endif /* GCC >= 4.9 */
meltgc_walk_gimple_seq ((melt_ptr_t)$DATA, ($GSEQ), $STMTCLOS,
$TREECLOS, TRUE) }#)
diff --git a/gcc/melt/xtramelt-probe.melt b/gcc/melt/xtramelt-probe.melt
index 5aaea9287f9..c9bc52c68fb 100644
--- a/gcc/melt/xtramelt-probe.melt
+++ b/gcc/melt/xtramelt-probe.melt
@@ -896,6 +896,8 @@
;;;;;;;;;;;;;;;; mode to start the probe
(defun probe_docmd (cmd moduldata)
(debug "probe_docmd cmd=" cmd " moduldata=" moduldata)
+ (gccif "4.9."
+ (error_at () "the MELT probe is not usable with GCC 4.9 because walk_gimple_seq does not really exist any more"))
(start_probe)
(install_scanprobe_pass)
(debug "probe_docmd after scanprobe cmd=" cmd)
diff --git a/gcc/mode-classes.def b/gcc/mode-classes.def
index 7207ef7712b..a94fd614603 100644
--- a/gcc/mode-classes.def
+++ b/gcc/mode-classes.def
@@ -22,6 +22,7 @@ along with GCC; see the file COPYING3. If not see
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_POINTER_BOUNDS), /* bounds */ \
DEF_MODE_CLASS (MODE_FRACT), /* signed fractional number */ \
DEF_MODE_CLASS (MODE_UFRACT), /* unsigned fractional number */ \
DEF_MODE_CLASS (MODE_ACCUM), /* signed accumulator */ \
diff --git a/gcc/mode-switching.c b/gcc/mode-switching.c
index 56c4d0fef9a..d54f32ca071 100644
--- a/gcc/mode-switching.c
+++ b/gcc/mode-switching.c
@@ -229,9 +229,9 @@ create_pre_exit (int n_entities, int *entity_map, const int *num_modes)
int ret_start = REGNO (ret_reg);
int nregs = hard_regno_nregs[ret_start][GET_MODE (ret_reg)];
int ret_end = ret_start + nregs;
- int short_block = 0;
- int maybe_builtin_apply = 0;
- int forced_late_switch = 0;
+ bool short_block = false;
+ bool multi_reg_return = false;
+ bool forced_late_switch = false;
rtx before_return_copy;
do
@@ -251,19 +251,20 @@ create_pre_exit (int n_entities, int *entity_map, const int *num_modes)
copy yet, the copy must have been deleted. */
if (CALL_P (return_copy))
{
- short_block = 1;
+ short_block = true;
break;
}
return_copy_pat = PATTERN (return_copy);
switch (GET_CODE (return_copy_pat))
{
case USE:
- /* Skip __builtin_apply pattern. */
+ /* Skip USEs of multiple return registers.
+ __builtin_apply pattern is also handled here. */
if (GET_CODE (XEXP (return_copy_pat, 0)) == REG
&& (targetm.calls.function_value_regno_p
(REGNO (XEXP (return_copy_pat, 0)))))
{
- maybe_builtin_apply = 1;
+ multi_reg_return = true;
last_insn = return_copy;
continue;
}
@@ -326,7 +327,7 @@ create_pre_exit (int n_entities, int *entity_map, const int *num_modes)
there are no return copy insns at all. This
avoids an ice on that invalid function. */
if (ret_start + nregs == ret_end)
- short_block = 1;
+ short_block = true;
break;
}
if (!targetm.calls.function_value_regno_p (copy_start))
@@ -354,10 +355,10 @@ create_pre_exit (int n_entities, int *entity_map, const int *num_modes)
another mode than MODE_EXIT, even if it is
unrelated to the return value, so we want to put
the final mode switch after it. */
- if (maybe_builtin_apply
+ if (multi_reg_return
&& targetm.calls.function_value_regno_p
(copy_start))
- forced_late_switch = 1;
+ forced_late_switch = true;
/* For the SH4, floating point loads depend on fpscr,
thus we might need to put the final mode switch
@@ -367,7 +368,7 @@ create_pre_exit (int n_entities, int *entity_map, const int *num_modes)
if (copy_start >= ret_start
&& copy_start + copy_num <= ret_end
&& OBJECT_P (SET_SRC (return_copy_pat)))
- forced_late_switch = 1;
+ forced_late_switch = true;
break;
}
if (copy_num == 0)
@@ -379,7 +380,7 @@ create_pre_exit (int n_entities, int *entity_map, const int *num_modes)
if (copy_start >= ret_start
&& copy_start + copy_num <= ret_end)
nregs -= copy_num;
- else if (!maybe_builtin_apply
+ else if (!multi_reg_return
|| !targetm.calls.function_value_regno_p
(copy_start))
break;
@@ -393,7 +394,7 @@ create_pre_exit (int n_entities, int *entity_map, const int *num_modes)
isolated use. */
if (return_copy == BB_HEAD (src_bb))
{
- short_block = 1;
+ short_block = true;
break;
}
last_insn = return_copy;
@@ -570,12 +571,15 @@ optimize_mode_switching (void)
info[bb->index].computing = last_mode;
/* Check for blocks without ANY mode requirements.
- N.B. because of MODE_AFTER, last_mode might still be different
- from no_mode. */
+ N.B. because of MODE_AFTER, last_mode might still
+ be different from no_mode, in which case we need to
+ mark the block as nontransparent. */
if (!any_set_required)
{
ptr = new_seginfo (no_mode, BB_END (bb), bb->index, live_now);
add_seginfo (info + bb->index, ptr);
+ if (last_mode != no_mode)
+ bitmap_clear_bit (transp[bb->index], j);
}
}
#if defined (MODE_ENTRY) && defined (MODE_EXIT)
@@ -804,14 +808,14 @@ const pass_data pass_data_mode_switching =
class pass_mode_switching : public rtl_opt_pass
{
public:
- pass_mode_switching(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_mode_switching, ctxt)
+ pass_mode_switching (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_mode_switching, ctxt)
{}
/* opt_pass methods: */
/* The epiphany backend creates a second instance of this pass, so we need
a clone method. */
- opt_pass * clone () { return new pass_mode_switching (ctxt_); }
+ opt_pass * clone () { return new pass_mode_switching (m_ctxt); }
bool gate () { return gate_mode_switching (); }
unsigned int execute () { return rest_of_handle_mode_switching (); }
diff --git a/gcc/modulo-sched.c b/gcc/modulo-sched.c
index 3ad2ec77f1e..599c025f57d 100644
--- a/gcc/modulo-sched.c
+++ b/gcc/modulo-sched.c
@@ -3374,8 +3374,8 @@ const pass_data pass_data_sms =
class pass_sms : public rtl_opt_pass
{
public:
- pass_sms(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_sms, ctxt)
+ pass_sms (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_sms, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog
index 0cdd7616490..e3be5f8d212 100644
--- a/gcc/objc/ChangeLog
+++ b/gcc/objc/ChangeLog
@@ -1,3 +1,15 @@
+2013-11-07 Andrew MacLeod <amacleod@redhat.com>
+
+ * objc-act.c (objc_push_parm): Handle atomic qualifier.
+
+2013-09-25 Tom Tromey <tromey@redhat.com>
+
+ * Make-lang.in (START_HDRS, cc1obj-checksum.o, objc/objc-lang.o)
+ (objc/objc-runtime-shared-support.o)
+ (objc/objc-gnu-runtime-abi-01.o, objc/objc-next-runtime-abi-01.o)
+ (objc/objc-next-runtime-abi-02.o, objc/objc-act.o)
+ (objc/objc-encoding.o, objc/objc-map.o): Remove.
+
2013-09-14 Iain Sandoe <iain@codesourcery.com>
PR target/48094
diff --git a/gcc/objc/Make-lang.in b/gcc/objc/Make-lang.in
index f04d60686c8..02e78fbfc3a 100644
--- a/gcc/objc/Make-lang.in
+++ b/gcc/objc/Make-lang.in
@@ -42,9 +42,6 @@ objc: cc1obj$(exeext)
# Tell GNU make to ignore these if they exist.
.PHONY: objc
-START_HDRS = $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(C_TREE_H) \
- c/c-lang.h langhooks.h c-family/c-objc.h objc/objc-act.h
-
# Use maximal warnings for this front end.
objc-warn = $(STRICT_WARN)
@@ -65,87 +62,11 @@ cc1obj-checksum.c : build/genchecksum$(build_exeext) checksum-options \
$(BACKEND) $(LIBDEPS) checksum-options > cc1obj-checksum.c.tmp && \
$(srcdir)/../move-if-change cc1obj-checksum.c.tmp cc1obj-checksum.c
-cc1obj-checksum.o : cc1obj-checksum.c $(CONFIG_H) $(SYSTEM_H)
-
cc1obj$(exeext): $(OBJC_OBJS) $(C_AND_OBJC_OBJS) cc1obj-checksum.o $(BACKEND) $(LIBDEPS)
+$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
$(OBJC_OBJS) $(C_AND_OBJC_OBJS) cc1obj-checksum.o \
$(BACKEND) $(LIBS) $(BACKENDLIBS)
-# Objective C language specific files.
-
-# When editing, please keep the objc/ header dependencies in
-# alphabetical order, and try to use a similar logical order for the
-# other files between the different targets.
-
-objc/objc-lang.o : objc/objc-lang.c \
- $(START_HDRS) \
- $(GGC_H) \
- $(LANGHOOKS_DEF_H) $(C_COMMON_H) gtype-objc.h \
- c/c-objc-common.h
-
-objc/objc-runtime-shared-support.o : objc/objc-runtime-shared-support.c \
- gt-objc-objc-runtime-shared-support.h \
- $(START_HDRS) \
- $(GGC_H) $(DIAGNOSTIC_CORE_H) $(FLAGS_H) input.h \
- objc/objc-encoding.h \
- objc/objc-next-metadata-tags.h \
- objc/objc-runtime-shared-support.h
-
-objc/objc-gnu-runtime-abi-01.o: objc/objc-gnu-runtime-abi-01.c \
- gt-objc-objc-gnu-runtime-abi-01.h \
- $(START_HDRS) \
- $(GGC_H) $(DIAGNOSTIC_CORE_H) $(FLAGS_H) input.h \
- toplev.h \
- objc/objc-encoding.h \
- objc/objc-runtime-hooks.h \
- objc/objc-runtime-shared-support.h
-
-objc/objc-next-runtime-abi-01.o: objc/objc-next-runtime-abi-01.c \
- gt-objc-objc-next-runtime-abi-01.h \
- $(START_HDRS) \
- $(GGC_H) $(DIAGNOSTIC_CORE_H) $(FLAGS_H) input.h \
- $(TARGET_H) \
- objc/objc-encoding.h \
- objc/objc-next-metadata-tags.h \
- objc/objc-runtime-hooks.h \
- objc/objc-runtime-shared-support.h
-
-objc/objc-next-runtime-abi-02.o: objc/objc-next-runtime-abi-02.c \
- gt-objc-objc-next-runtime-abi-02.h \
- $(START_HDRS) \
- $(GGC_H) $(DIAGNOSTIC_CORE_H) $(FLAGS_H) input.h \
- $(TARGET_H) \
- objc/objc-encoding.h \
- objc/objc-next-metadata-tags.h \
- objc/objc-runtime-hooks.h \
- objc/objc-runtime-shared-support.h
-
-objc/objc-act.o : objc/objc-act.c \
- gt-objc-objc-act.h \
- $(START_HDRS) \
- $(GGC_H) $(DIAGNOSTIC_CORE_H) $(FLAGS_H) input.h \
- toplev.h $(FUNCTION_H) debug.h $(LANGHOOKS_DEF_H) \
- $(HASH_TABLE_H) $(GIMPLE_H) \
- $(C_PRAGMA_H) $(C_TARGET_H) \
- objc/objc-encoding.h \
- objc/objc-map.h \
- objc/objc-runtime-hooks.h \
- objc/objc-runtime-shared-support.h
-
-objc/objc-encoding.o : objc/objc-encoding.c \
- $(START_HDRS) \
- $(GGC_H) $(DIAGNOSTIC_CORE_H) $(FLAGS_H) input.h \
- $(OBSTACK_H) \
- objc/objc-encoding.h \
- objc/objc-runtime-shared-support.h
-
-objc/objc-map.o : objc/objc-map.c \
- $(START_HDRS) \
- $(GGC_H) $(DIAGNOSTIC_CORE_H) $(FLAGS_H) input.h \
- $(OBSTACK_H) \
- objc/objc-map.h
-
objc.srcextra:
#
diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c
index 95ec4ecd40f..3125398c276 100644
--- a/gcc/objc/objc-act.c
+++ b/gcc/objc/objc-act.c
@@ -8244,6 +8244,7 @@ objc_push_parm (tree parm)
c_apply_type_quals_to_decl
((TYPE_READONLY (TREE_TYPE (parm)) ? TYPE_QUAL_CONST : 0)
| (TYPE_RESTRICT (TREE_TYPE (parm)) ? TYPE_QUAL_RESTRICT : 0)
+ | (TYPE_ATOMIC (TREE_TYPE (parm)) ? TYPE_QUAL_ATOMIC : 0)
| (TYPE_VOLATILE (TREE_TYPE (parm)) ? TYPE_QUAL_VOLATILE : 0), parm);
objc_parmlist = chainon (objc_parmlist, parm);
diff --git a/gcc/objcp/ChangeLog b/gcc/objcp/ChangeLog
index 7369195624a..af4e4b3f49d 100644
--- a/gcc/objcp/ChangeLog
+++ b/gcc/objcp/ChangeLog
@@ -1,3 +1,13 @@
+2013-09-25 Tom Tromey <tromey@redhat.com>
+
+ * Make-lang.in (START_HDRS, cc1objplus-checksum.o)
+ (objcp/objcp-lang.o, objcp/objcp-decl.o
+ (objcp/objc-runtime-shared-support.o)
+ (objcp/objc-gnu-runtime-abi-01.o objcp/objc-next-runtime-abi-01.o)
+ (objcp/objc-next-runtime-abi-02.o, objcp/objcp-act.o)
+ (objcp/objc-encoding.o, objcp/objc-map.o): Use COMPILE and
+ POSTCOMPILE. Remove explicit dependencies.
+
2013-05-16 Jason Merrill <jason@redhat.com>
* Make-lang.in (cc1objplus$(exeext)): Use link mutex.
diff --git a/gcc/objcp/Make-lang.in b/gcc/objcp/Make-lang.in
index ec10fc890c2..439bfa223af 100644
--- a/gcc/objcp/Make-lang.in
+++ b/gcc/objcp/Make-lang.in
@@ -43,9 +43,6 @@ obj-c++: cc1objplus$(exeext)
# Tell GNU make to ignore these if they exist.
.PHONY: obj-c++
-START_HDRS = $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(CXX_TREE_H) \
- $(CXX_PARSER_H) $(CXX_PRETTY_PRINT_H) langhooks.h c-family/c-objc.h objc/objc-act.h
-
# Use maximal warnings for this front end. Also, make ObjC and C++
# headers accessible.
objcp-warn = $(STRICT_WARN) -DOBJCPLUS -I$(srcdir)/objc -I$(srcdir)/cp
@@ -69,110 +66,39 @@ cc1objplus-checksum.c : build/genchecksum$(build_exeext) checksum-options \
$(srcdir)/../move-if-change cc1objplus-checksum.c.tmp \
cc1objplus-checksum.c
-cc1objplus-checksum.o : cc1objplus-checksum.c $(CONFIG_H) $(SYSTEM_H)
-
cc1objplus$(exeext): $(OBJCXX_OBJS) cc1objplus-checksum.o $(BACKEND) $(LIBDEPS)
+$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
$(OBJCXX_OBJS) cc1objplus-checksum.o $(BACKEND) $(LIBS) $(BACKENDLIBS)
# Objective C++ language specific files.
-objcp/objcp-lang.o : objcp/objcp-lang.c \
- $(START_HDRS) \
- $(GGC_H) \
- $(C_COMMON_H) $(LANGHOOKS_DEF_H) cp/cp-objcp-common.h \
- $(TARGET_H) gtype-objcp.h
-
-objcp/objcp-decl.o : objcp/objcp-decl.c \
- $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(CXX_TREE_H) \
- objc/objc-act.h c-family/c-objc.h \
- objcp/objcp-decl.h
-
-objcp/objc-runtime-shared-support.o : objc/objc-runtime-shared-support.c \
- gt-objc-objc-runtime-shared-support.h \
- $(START_HDRS) \
- $(GGC_H) $(DIAGNOSTIC_CORE_H) $(FLAGS_H) input.h \
- objc/objc-encoding.h \
- objc/objc-next-metadata-tags.h \
- objc/objc-runtime-shared-support.h \
- objcp/objcp-decl.h
- $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< \
- $(OUTPUT_OPTION)
-
-objcp/objc-gnu-runtime-abi-01.o: objc/objc-gnu-runtime-abi-01.c \
- gt-objc-objc-gnu-runtime-abi-01.h \
- $(START_HDRS) \
- $(GGC_H) $(DIAGNOSTIC_CORE_H) $(FLAGS_H) input.h \
- toplev.h \
- objc/objc-encoding.h \
- objc/objc-runtime-hooks.h \
- objc/objc-runtime-shared-support.h \
- objcp/objcp-decl.h
- $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< \
- $(OUTPUT_OPTION)
-
-objcp/objc-next-runtime-abi-01.o: objc/objc-next-runtime-abi-01.c \
- gt-objc-objc-next-runtime-abi-01.h \
- $(START_HDRS) \
- $(GGC_H) $(DIAGNOSTIC_CORE_H) $(FLAGS_H) input.h \
- $(TARGET_H) output.h \
- objc/objc-encoding.h \
- objc/objc-next-metadata-tags.h \
- objc/objc-runtime-hooks.h \
- objc/objc-runtime-shared-support.h \
- objcp/objcp-decl.h
- $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< \
- $(OUTPUT_OPTION)
-
-objcp/objc-next-runtime-abi-02.o: objc/objc-next-runtime-abi-02.c \
- gt-objc-objc-next-runtime-abi-02.h \
- $(START_HDRS) \
- $(GGC_H) $(DIAGNOSTIC_CORE_H) $(FLAGS_H) input.h \
- $(TARGET_H) \
- objc/objc-encoding.h \
- objc/objc-next-metadata-tags.h \
- objc/objc-runtime-hooks.h \
- objc/objc-runtime-shared-support.h \
- objcp/objcp-decl.h
- $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< \
- $(OUTPUT_OPTION)
-
-
-# The following must be an explicit rule; please keep in sync with the implicit
-# one in Makefile.in.
-objcp/objcp-act.o : objc/objc-act.c \
- gt-objc-objc-act.h \
- $(START_HDRS) \
- $(GGC_H) $(DIAGNOSTIC_H) $(FLAGS_H) input.h \
- toplev.h $(FUNCTION_H) output.h debug.h $(LANGHOOKS_DEF_H) \
- $(HASHTAB_H) $(GIMPLE_H) \
- $(RTL_H) $(EXPR_H) $(TARGET_H) \
- objcp/objcp-decl.h \
- objc/objc-encoding.h \
- objc/objc-map.h \
- objc/objc-runtime-hooks.h \
- objc/objc-runtime-shared-support.h \
- objcp/objcp-decl.h
- $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< \
- $(OUTPUT_OPTION)
-
-objcp/objc-encoding.o : objc/objc-encoding.c \
- $(START_HDRS) \
- $(GGC_H) $(DIAGNOSTIC_CORE_H) $(FLAGS_H) input.h \
- $(OBSTACK_H) \
- objc/objc-encoding.h \
- objc/objc-runtime-shared-support.h \
- objcp/objcp-decl.h
- $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< \
- $(OUTPUT_OPTION)
-
-objcp/objc-map.o : objc/objc-map.c \
- $(START_HDRS) \
- $(GGC_H) $(DIAGNOSTIC_CORE_H) $(FLAGS_H) input.h \
- $(OBSTACK_H) \
- objc/objc-map.h
- $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< \
- $(OUTPUT_OPTION)
+objcp/objc-runtime-shared-support.o: objc/objc-runtime-shared-support.c
+ $(COMPILE) $<
+ $(POSTCOMPILE)
+
+objcp/objc-gnu-runtime-abi-01.o: objc/objc-gnu-runtime-abi-01.c
+ $(COMPILE) $<
+ $(POSTCOMPILE)
+
+objcp/objc-next-runtime-abi-01.o: objc/objc-next-runtime-abi-01.c
+ $(COMPILE) $<
+ $(POSTCOMPILE)
+
+objcp/objc-next-runtime-abi-02.o: objc/objc-next-runtime-abi-02.c
+ $(COMPILE) $<
+ $(POSTCOMPILE)
+
+objcp/objcp-act.o: objc/objc-act.c
+ $(COMPILE) $<
+ $(POSTCOMPILE)
+
+objcp/objc-encoding.o: objc/objc-encoding.c
+ $(COMPILE) $<
+ $(POSTCOMPILE)
+
+objcp/objc-map.o: objc/objc-map.c
+ $(COMPILE) $<
+ $(POSTCOMPILE)
po-generated:
diff --git a/gcc/omp-builtins.def b/gcc/omp-builtins.def
index 83c26c44fc9..8fd99548e7e 100644
--- a/gcc/omp-builtins.def
+++ b/gcc/omp-builtins.def
@@ -28,6 +28,10 @@ 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)
@@ -35,10 +39,20 @@ 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_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",
@@ -156,49 +170,52 @@ DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ULL_ORDERED_GUIDED_NEXT,
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_*_START.
+/* 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.c. */
-DEF_GOMP_BUILTIN (BUILT_IN_GOMP_PARALLEL_LOOP_STATIC_START,
- "GOMP_parallel_loop_static_start",
- BT_FN_VOID_OMPFN_PTR_UINT_LONG_LONG_LONG_LONG,
+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_START,
- "GOMP_parallel_loop_dynamic_start",
- BT_FN_VOID_OMPFN_PTR_UINT_LONG_LONG_LONG_LONG,
+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_START,
- "GOMP_parallel_loop_guided_start",
- BT_FN_VOID_OMPFN_PTR_UINT_LONG_LONG_LONG_LONG,
+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_START,
- "GOMP_parallel_loop_runtime_start",
- BT_FN_VOID_OMPFN_PTR_UINT_LONG_LONG_LONG,
+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_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_PARALLEL_START, "GOMP_parallel_start",
- BT_FN_VOID_OMPFN_PTR_UINT, ATTR_NOTHROW_LIST)
-DEF_GOMP_BUILTIN (BUILT_IN_GOMP_PARALLEL_END, "GOMP_parallel_end",
- BT_FN_VOID, 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_TASK, "GOMP_task",
- BT_FN_VOID_OMPFN_PTR_OMPCPYFN_LONG_LONG_BOOL_UINT,
+ BT_FN_VOID_OMPFN_PTR_OMPCPYFN_LONG_LONG_BOOL_UINT_PTR,
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_SECTIONS_NEXT, "GOMP_sections_next",
BT_FN_UINT, ATTR_NOTHROW_LEAF_LIST)
-DEF_GOMP_BUILTIN (BUILT_IN_GOMP_PARALLEL_SECTIONS_START,
- "GOMP_parallel_sections_start",
- BT_FN_VOID_OMPFN_PTR_UINT_UINT, ATTR_NOTHROW_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)
@@ -208,3 +225,14 @@ 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_TARGET, "GOMP_target",
+ BT_FN_VOID_INT_OMPFN_PTR_SIZE_PTR_PTR_PTR,
+ ATTR_NOTHROW_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_TARGET_DATA, "GOMP_target_data",
+ BT_FN_VOID_INT_PTR_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",
+ BT_FN_VOID_INT_PTR_SIZE_PTR_PTR_PTR, ATTR_NOTHROW_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_TEAMS, "GOMP_teams",
+ BT_FN_VOID_UINT_UINT, ATTR_NOTHROW_LIST)
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index fa9aca49a3a..7874ff13dd6 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -32,6 +32,14 @@ along with GCC; see the file COPYING3. If not see
#include "tree-inline.h"
#include "langhooks.h"
#include "diagnostic-core.h"
+#include "gimple-ssa.h"
+#include "cgraph.h"
+#include "tree-cfg.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
+#include "tree-into-ssa.h"
+#include "tree-dfa.h"
#include "tree-ssa.h"
#include "flags.h"
#include "function.h"
@@ -43,6 +51,9 @@ along with GCC; see the file COPYING3. If not see
#include "optabs.h"
#include "cfgloop.h"
#include "target.h"
+#include "omp-low.h"
+#include "gimple-low.h"
+#include "tree-cfgcleanup.h"
/* Lowering of OpenMP parallel and workshare constructs proceeds in two
@@ -56,6 +67,45 @@ along with GCC; see the file COPYING3. If not see
scanned for parallel regions which are then moved to a new
function, to be invoked by the thread library. */
+/* Parallel region information. Every parallel and workshare
+ directive is enclosed between two markers, the OMP_* directive
+ and a corresponding OMP_RETURN statement. */
+
+struct omp_region
+{
+ /* The enclosing region. */
+ struct omp_region *outer;
+
+ /* First child region. */
+ struct omp_region *inner;
+
+ /* Next peer region. */
+ struct omp_region *next;
+
+ /* Block containing the omp directive as its last stmt. */
+ basic_block entry;
+
+ /* Block containing the OMP_RETURN as its last stmt. */
+ basic_block exit;
+
+ /* Block containing the OMP_CONTINUE as its last stmt. */
+ basic_block cont;
+
+ /* If this is a combined parallel+workshare region, this is a list
+ of additional arguments needed by the combined parallel+workshare
+ library call. */
+ vec<tree, va_gc> *ws_args;
+
+ /* The code for the omp directive of this region. */
+ enum gimple_code type;
+
+ /* Schedule kind, only used for OMP_FOR type regions. */
+ enum omp_clause_schedule_kind sched_kind;
+
+ /* True if this is a combined parallel+workshare region. */
+ bool is_combined_parallel;
+};
+
/* Context structure. Used to store information about each parallel
directive in the code. */
@@ -90,6 +140,10 @@ typedef struct omp_context
construct. In the case of a parallel, this is in the child function. */
tree block_vars;
+ /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
+ barriers should jump to during omplower pass. */
+ tree cancel_label;
+
/* What to do with variables with implicitly determined sharing
attributes. */
enum omp_clause_default_kind default_kind;
@@ -101,6 +155,9 @@ typedef struct omp_context
/* True if this parallel directive is nested within another. */
bool is_nested;
+
+ /* True if this construct can be cancelled. */
+ bool cancellable;
} omp_context;
@@ -127,7 +184,8 @@ struct omp_for_data
static splay_tree all_contexts;
static int taskreg_nesting_level;
-struct omp_region *root_omp_region;
+static int target_nesting_level;
+static struct omp_region *root_omp_region;
static bitmap task_shared_vars;
static void scan_omp (gimple_seq *, omp_context *);
@@ -224,6 +282,8 @@ extract_omp_for_data (gimple for_stmt, struct omp_for_data *fd,
struct omp_for_data_loop dummy_loop;
location_t loc = gimple_location (for_stmt);
bool simd = gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_SIMD;
+ bool distribute = gimple_omp_for_kind (for_stmt)
+ == GF_OMP_FOR_KIND_DISTRIBUTE;
fd->for_stmt = for_stmt;
fd->pre = NULL;
@@ -233,7 +293,8 @@ extract_omp_for_data (gimple for_stmt, struct omp_for_data *fd,
else
fd->loops = &fd->loop;
- fd->have_nowait = fd->have_ordered = false;
+ fd->have_nowait = distribute || simd;
+ fd->have_ordered = false;
fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
fd->chunk_size = NULL_TREE;
collapse_iter = NULL;
@@ -249,9 +310,14 @@ extract_omp_for_data (gimple for_stmt, struct omp_for_data *fd,
fd->have_ordered = true;
break;
case OMP_CLAUSE_SCHEDULE:
+ gcc_assert (!distribute);
fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t);
fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
break;
+ case OMP_CLAUSE_DIST_SCHEDULE:
+ gcc_assert (distribute);
+ fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
+ break;
case OMP_CLAUSE_COLLAPSE:
if (fd->collapse > 1)
{
@@ -279,8 +345,7 @@ extract_omp_for_data (gimple for_stmt, struct omp_for_data *fd,
/* We only need to compute a default chunk size for ordered
static loops and dynamic loops. */
if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
- || fd->have_ordered
- || fd->collapse > 1)
+ || fd->have_ordered)
fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
? integer_zero_node : integer_one_node;
}
@@ -294,7 +359,6 @@ extract_omp_for_data (gimple for_stmt, struct omp_for_data *fd,
else
loop = &dummy_loop;
-
loop->v = gimple_omp_for_index (for_stmt, i);
gcc_assert (SSA_VAR_P (loop->v));
gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
@@ -351,7 +415,9 @@ extract_omp_for_data (gimple for_stmt, struct omp_for_data *fd,
gcc_unreachable ();
}
- if (simd)
+ if (simd
+ || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
+ && !fd->have_ordered))
{
if (fd->collapse == 1)
iter_type = TREE_TYPE (loop->v);
@@ -360,7 +426,7 @@ extract_omp_for_data (gimple for_stmt, struct omp_for_data *fd,
< TYPE_PRECISION (TREE_TYPE (loop->v)))
iter_type
= build_nonstandard_integer_type
- (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
+ (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
}
else if (iter_type != long_long_unsigned_type_node)
{
@@ -459,7 +525,9 @@ extract_omp_for_data (gimple for_stmt, struct omp_for_data *fd,
}
if (count
- && !simd)
+ && !simd
+ && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
+ || fd->have_ordered))
{
if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
iter_type = long_long_unsigned_type_node;
@@ -570,7 +638,7 @@ workshare_safe_to_combine_p (basic_block ws_entry_bb)
expanded. */
static vec<tree, va_gc> *
-get_ws_args_for (gimple ws_stmt)
+get_ws_args_for (gimple par_stmt, gimple ws_stmt)
{
tree t;
location_t loc = gimple_location (ws_stmt);
@@ -579,15 +647,31 @@ get_ws_args_for (gimple ws_stmt)
if (gimple_code (ws_stmt) == GIMPLE_OMP_FOR)
{
struct omp_for_data fd;
+ tree n1, n2;
extract_omp_for_data (ws_stmt, &fd, NULL);
+ n1 = fd.loop.n1;
+ n2 = fd.loop.n2;
+
+ if (gimple_omp_for_combined_into_p (ws_stmt))
+ {
+ tree innerc
+ = find_omp_clause (gimple_omp_parallel_clauses (par_stmt),
+ OMP_CLAUSE__LOOPTEMP_);
+ gcc_assert (innerc);
+ n1 = OMP_CLAUSE_DECL (innerc);
+ innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
+ OMP_CLAUSE__LOOPTEMP_);
+ gcc_assert (innerc);
+ n2 = OMP_CLAUSE_DECL (innerc);
+ }
vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
- t = fold_convert_loc (loc, long_integer_type_node, fd.loop.n1);
+ t = fold_convert_loc (loc, long_integer_type_node, n1);
ws_args->quick_push (t);
- t = fold_convert_loc (loc, long_integer_type_node, fd.loop.n2);
+ t = fold_convert_loc (loc, long_integer_type_node, n2);
ws_args->quick_push (t);
t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
@@ -650,6 +734,7 @@ determine_parallel_type (struct omp_region *region)
|| (last_and_only_stmt (ws_entry_bb)
&& last_and_only_stmt (par_exit_bb))))
{
+ gimple par_stmt = last_stmt (par_entry_bb);
gimple ws_stmt = last_stmt (ws_entry_bb);
if (region->inner->type == GIMPLE_OMP_FOR)
@@ -677,7 +762,7 @@ determine_parallel_type (struct omp_region *region)
region->is_combined_parallel = true;
region->inner->is_combined_parallel = true;
- region->ws_args = get_ws_args_for (ws_stmt);
+ region->ws_args = get_ws_args_for (par_stmt, ws_stmt);
}
}
@@ -837,27 +922,6 @@ use_pointer_for_field (tree decl, omp_context *shared_ctx)
return false;
}
-/* Create a new VAR_DECL and copy information from VAR to it. */
-
-tree
-copy_var_decl (tree var, tree name, tree type)
-{
- tree copy = build_decl (DECL_SOURCE_LOCATION (var), VAR_DECL, name, type);
-
- TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (var);
- TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (var);
- DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (var);
- DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (var);
- DECL_IGNORED_P (copy) = DECL_IGNORED_P (var);
- DECL_CONTEXT (copy) = DECL_CONTEXT (var);
- TREE_NO_WARNING (copy) = TREE_NO_WARNING (var);
- TREE_USED (copy) = 1;
- DECL_SEEN_IN_BIND_EXPR_P (copy) = 1;
- DECL_ATTRIBUTES (copy) = DECL_ATTRIBUTES (var);
-
- return copy;
-}
-
/* Construct a new automatic decl similar to VAR. */
static tree
@@ -984,7 +1048,12 @@ install_var_field (tree var, bool by_ref, int mask, omp_context *ctx)
|| !splay_tree_lookup (ctx->sfield_map, (splay_tree_key) var));
type = TREE_TYPE (var);
- if (by_ref)
+ if (mask & 4)
+ {
+ gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
+ type = build_pointer_type (build_pointer_type (type));
+ }
+ else if (by_ref)
type = build_pointer_type (type);
else if ((mask & 3) == 1 && is_reference (var))
type = TREE_TYPE (type);
@@ -1179,7 +1248,7 @@ debug_all_omp_regions (void)
/* Create a new parallel region starting at STMT inside region PARENT. */
-struct omp_region *
+static struct omp_region *
new_omp_region (basic_block bb, enum gimple_code type,
struct omp_region *parent)
{
@@ -1421,6 +1490,9 @@ scan_sharing_clauses (tree clauses, omp_context *ctx)
break;
case OMP_CLAUSE_SHARED:
+ /* Ignore shared directives in teams construct. */
+ if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
+ break;
gcc_assert (is_taskreg_ctx (ctx));
decl = OMP_CLAUSE_DECL (c);
gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
@@ -1480,6 +1552,13 @@ scan_sharing_clauses (tree clauses, omp_context *ctx)
install_var_local (decl, ctx);
break;
+ case OMP_CLAUSE__LOOPTEMP_:
+ gcc_assert (is_parallel_ctx (ctx));
+ decl = OMP_CLAUSE_DECL (c);
+ install_var_field (decl, false, 3, ctx);
+ install_var_local (decl, ctx);
+ break;
+
case OMP_CLAUSE_COPYPRIVATE:
case OMP_CLAUSE_COPYIN:
decl = OMP_CLAUSE_DECL (c);
@@ -1494,19 +1573,113 @@ scan_sharing_clauses (tree clauses, omp_context *ctx)
case OMP_CLAUSE_FINAL:
case OMP_CLAUSE_IF:
case OMP_CLAUSE_NUM_THREADS:
+ case OMP_CLAUSE_NUM_TEAMS:
+ case OMP_CLAUSE_THREAD_LIMIT:
+ case OMP_CLAUSE_DEVICE:
case OMP_CLAUSE_SCHEDULE:
+ case OMP_CLAUSE_DIST_SCHEDULE:
+ case OMP_CLAUSE_DEPEND:
if (ctx->outer)
scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
break;
+ case OMP_CLAUSE_TO:
+ case OMP_CLAUSE_FROM:
+ case OMP_CLAUSE_MAP:
+ if (ctx->outer)
+ scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
+ decl = OMP_CLAUSE_DECL (c);
+ /* Global variables with "omp declare target" attribute
+ don't need to be copied, the receiver side will use them
+ directly. */
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
+ && DECL_P (decl)
+ && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
+ && lookup_attribute ("omp declare target",
+ DECL_ATTRIBUTES (decl)))
+ break;
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
+ && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER)
+ {
+ /* Ignore OMP_CLAUSE_MAP_POINTER kind for arrays in
+ #pragma omp target data, there is nothing to map for
+ those. */
+ if (gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_DATA
+ && !POINTER_TYPE_P (TREE_TYPE (decl)))
+ break;
+ }
+ if (DECL_P (decl))
+ {
+ if (DECL_SIZE (decl)
+ && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
+ {
+ tree decl2 = DECL_VALUE_EXPR (decl);
+ gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
+ decl2 = TREE_OPERAND (decl2, 0);
+ gcc_assert (DECL_P (decl2));
+ install_var_field (decl2, true, 3, ctx);
+ install_var_local (decl2, ctx);
+ install_var_local (decl, ctx);
+ }
+ else
+ {
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
+ && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
+ && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
+ && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
+ install_var_field (decl, true, 7, ctx);
+ else
+ install_var_field (decl, true, 3, ctx);
+ if (gimple_omp_target_kind (ctx->stmt)
+ == GF_OMP_TARGET_KIND_REGION)
+ install_var_local (decl, ctx);
+ }
+ }
+ else
+ {
+ tree base = get_base_address (decl);
+ tree nc = OMP_CLAUSE_CHAIN (c);
+ if (DECL_P (base)
+ && nc != NULL_TREE
+ && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
+ && OMP_CLAUSE_DECL (nc) == base
+ && OMP_CLAUSE_MAP_KIND (nc) == OMP_CLAUSE_MAP_POINTER
+ && integer_zerop (OMP_CLAUSE_SIZE (nc)))
+ {
+ OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
+ OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
+ }
+ else
+ {
+ gcc_assert (!splay_tree_lookup (ctx->field_map,
+ (splay_tree_key) decl));
+ tree field
+ = build_decl (OMP_CLAUSE_LOCATION (c),
+ FIELD_DECL, NULL_TREE, ptr_type_node);
+ DECL_ALIGN (field) = TYPE_ALIGN (ptr_type_node);
+ insert_field_into_struct (ctx->record_type, field);
+ splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
+ (splay_tree_value) field);
+ }
+ }
+ break;
+
case OMP_CLAUSE_NOWAIT:
case OMP_CLAUSE_ORDERED:
case OMP_CLAUSE_COLLAPSE:
case OMP_CLAUSE_UNTIED:
case OMP_CLAUSE_MERGEABLE:
+ case OMP_CLAUSE_PROC_BIND:
case OMP_CLAUSE_SAFELEN:
break;
+ case OMP_CLAUSE_ALIGNED:
+ decl = OMP_CLAUSE_DECL (c);
+ if (is_global_var (decl)
+ && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
+ install_var_local (decl, ctx);
+ break;
+
default:
gcc_unreachable ();
}
@@ -1541,24 +1714,71 @@ scan_sharing_clauses (tree clauses, omp_context *ctx)
break;
case OMP_CLAUSE_SHARED:
+ /* Ignore shared directives in teams construct. */
+ if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
+ break;
decl = OMP_CLAUSE_DECL (c);
if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
fixup_remapped_decl (decl, ctx, false);
break;
+ case OMP_CLAUSE_MAP:
+ if (gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_DATA)
+ break;
+ decl = OMP_CLAUSE_DECL (c);
+ if (DECL_P (decl)
+ && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
+ && lookup_attribute ("omp declare target",
+ DECL_ATTRIBUTES (decl)))
+ break;
+ if (DECL_P (decl))
+ {
+ if (OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
+ && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
+ && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
+ {
+ tree new_decl = lookup_decl (decl, ctx);
+ TREE_TYPE (new_decl)
+ = remap_type (TREE_TYPE (decl), &ctx->cb);
+ }
+ else if (DECL_SIZE (decl)
+ && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
+ {
+ tree decl2 = DECL_VALUE_EXPR (decl);
+ gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
+ decl2 = TREE_OPERAND (decl2, 0);
+ gcc_assert (DECL_P (decl2));
+ fixup_remapped_decl (decl2, ctx, false);
+ fixup_remapped_decl (decl, ctx, true);
+ }
+ else
+ fixup_remapped_decl (decl, ctx, false);
+ }
+ break;
+
case OMP_CLAUSE_COPYPRIVATE:
case OMP_CLAUSE_COPYIN:
case OMP_CLAUSE_DEFAULT:
case OMP_CLAUSE_IF:
case OMP_CLAUSE_NUM_THREADS:
+ case OMP_CLAUSE_NUM_TEAMS:
+ case OMP_CLAUSE_THREAD_LIMIT:
+ case OMP_CLAUSE_DEVICE:
case OMP_CLAUSE_SCHEDULE:
+ case OMP_CLAUSE_DIST_SCHEDULE:
case OMP_CLAUSE_NOWAIT:
case OMP_CLAUSE_ORDERED:
case OMP_CLAUSE_COLLAPSE:
case OMP_CLAUSE_UNTIED:
case OMP_CLAUSE_FINAL:
case OMP_CLAUSE_MERGEABLE:
+ case OMP_CLAUSE_PROC_BIND:
case OMP_CLAUSE_SAFELEN:
+ case OMP_CLAUSE_ALIGNED:
+ case OMP_CLAUSE_DEPEND:
+ case OMP_CLAUSE__LOOPTEMP_:
+ case OMP_CLAUSE_TO:
+ case OMP_CLAUSE_FROM:
break;
default:
@@ -1623,6 +1843,26 @@ create_omp_child_function (omp_context *ctx, bool task_copy)
DECL_EXTERNAL (decl) = 0;
DECL_CONTEXT (decl) = NULL_TREE;
DECL_INITIAL (decl) = make_node (BLOCK);
+ bool target_p = false;
+ if (lookup_attribute ("omp declare target",
+ DECL_ATTRIBUTES (current_function_decl)))
+ target_p = true;
+ else
+ {
+ omp_context *octx;
+ for (octx = ctx; octx; octx = octx->outer)
+ if (gimple_code (octx->stmt) == GIMPLE_OMP_TARGET
+ && gimple_omp_target_kind (octx->stmt)
+ == GF_OMP_TARGET_KIND_REGION)
+ {
+ target_p = true;
+ break;
+ }
+ }
+ if (target_p)
+ DECL_ATTRIBUTES (decl)
+ = tree_cons (get_identifier ("omp declare target"),
+ NULL_TREE, DECL_ATTRIBUTES (decl));
t = build_decl (DECL_SOURCE_LOCATION (decl),
RESULT_DECL, NULL_TREE, void_type_node);
@@ -1664,6 +1904,35 @@ create_omp_child_function (omp_context *ctx, bool task_copy)
pop_cfun ();
}
+/* Callback for walk_gimple_seq. Check if combined parallel
+ contains gimple_omp_for_combined_into_p OMP_FOR. */
+
+static tree
+find_combined_for (gimple_stmt_iterator *gsi_p,
+ bool *handled_ops_p,
+ struct walk_stmt_info *wi)
+{
+ gimple stmt = gsi_stmt (*gsi_p);
+
+ *handled_ops_p = true;
+ switch (gimple_code (stmt))
+ {
+ WALK_SUBSTMTS;
+
+ case GIMPLE_OMP_FOR:
+ if (gimple_omp_for_combined_into_p (stmt)
+ && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
+ {
+ wi->info = stmt;
+ return integer_zero_node;
+ }
+ break;
+ default:
+ break;
+ }
+ return NULL;
+}
+
/* Scan an OpenMP parallel directive. */
static void
@@ -1684,6 +1953,40 @@ scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
return;
}
+ if (gimple_omp_parallel_combined_p (stmt))
+ {
+ gimple for_stmt;
+ struct walk_stmt_info wi;
+
+ memset (&wi, 0, sizeof (wi));
+ wi.val_only = true;
+ walk_gimple_seq (gimple_omp_body (stmt),
+ find_combined_for, NULL, &wi);
+ for_stmt = (gimple) wi.info;
+ if (for_stmt)
+ {
+ struct omp_for_data fd;
+ extract_omp_for_data (for_stmt, &fd, NULL);
+ /* We need two temporaries with fd.loop.v type (istart/iend)
+ and then (fd.collapse - 1) temporaries with the same
+ type for count2 ... countN-1 vars if not constant. */
+ size_t count = 2, i;
+ tree type = fd.iter_type;
+ if (fd.collapse > 1
+ && TREE_CODE (fd.loop.n2) != INTEGER_CST)
+ count += fd.collapse - 1;
+ for (i = 0; i < count; i++)
+ {
+ tree temp = create_tmp_var (type, NULL);
+ tree c = build_omp_clause (UNKNOWN_LOCATION,
+ OMP_CLAUSE__LOOPTEMP_);
+ OMP_CLAUSE_DECL (c) = temp;
+ OMP_CLAUSE_CHAIN (c) = gimple_omp_parallel_clauses (stmt);
+ gimple_omp_parallel_set_clauses (stmt, c);
+ }
+ }
+ }
+
ctx = new_omp_context (stmt, outer_ctx);
if (taskreg_nesting_level > 1)
ctx->is_nested = true;
@@ -1858,6 +2161,63 @@ scan_omp_single (gimple stmt, omp_context *outer_ctx)
layout_type (ctx->record_type);
}
+/* Scan an OpenMP target{, data, update} directive. */
+
+static void
+scan_omp_target (gimple stmt, omp_context *outer_ctx)
+{
+ omp_context *ctx;
+ tree name;
+ int kind = gimple_omp_target_kind (stmt);
+
+ ctx = new_omp_context (stmt, outer_ctx);
+ ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
+ ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
+ ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
+ name = create_tmp_var_name (".omp_data_t");
+ name = build_decl (gimple_location (stmt),
+ TYPE_DECL, name, ctx->record_type);
+ DECL_ARTIFICIAL (name) = 1;
+ DECL_NAMELESS (name) = 1;
+ TYPE_NAME (ctx->record_type) = name;
+ if (kind == GF_OMP_TARGET_KIND_REGION)
+ {
+ create_omp_child_function (ctx, false);
+ gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
+ }
+
+ scan_sharing_clauses (gimple_omp_target_clauses (stmt), ctx);
+ scan_omp (gimple_omp_body_ptr (stmt), ctx);
+
+ if (TYPE_FIELDS (ctx->record_type) == NULL)
+ ctx->record_type = ctx->receiver_decl = NULL;
+ else
+ {
+ TYPE_FIELDS (ctx->record_type)
+ = nreverse (TYPE_FIELDS (ctx->record_type));
+#ifdef ENABLE_CHECKING
+ tree field;
+ unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
+ for (field = TYPE_FIELDS (ctx->record_type);
+ field;
+ field = DECL_CHAIN (field))
+ gcc_assert (DECL_ALIGN (field) == align);
+#endif
+ layout_type (ctx->record_type);
+ if (kind == GF_OMP_TARGET_KIND_REGION)
+ fixup_child_record_type (ctx);
+ }
+}
+
+/* Scan an OpenMP teams directive. */
+
+static void
+scan_omp_teams (gimple stmt, omp_context *outer_ctx)
+{
+ omp_context *ctx = new_omp_context (stmt, outer_ctx);
+ scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
+ scan_omp (gimple_omp_body_ptr (stmt), ctx);
+}
/* Check OpenMP nesting restrictions. */
static bool
@@ -1872,16 +2232,149 @@ check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
"OpenMP constructs may not be nested inside simd region");
return false;
}
+ else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
+ {
+ if ((gimple_code (stmt) != GIMPLE_OMP_FOR
+ || (gimple_omp_for_kind (stmt)
+ != GF_OMP_FOR_KIND_DISTRIBUTE))
+ && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
+ {
+ error_at (gimple_location (stmt),
+ "only distribute or parallel constructs are allowed to "
+ "be closely nested inside teams construct");
+ return false;
+ }
+ }
}
switch (gimple_code (stmt))
{
case GIMPLE_OMP_FOR:
if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_SIMD)
return true;
+ if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
+ {
+ if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
+ {
+ error_at (gimple_location (stmt),
+ "distribute construct must be closely nested inside "
+ "teams construct");
+ return false;
+ }
+ return true;
+ }
+ /* FALLTHRU */
+ case GIMPLE_CALL:
+ if (is_gimple_call (stmt)
+ && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
+ == BUILT_IN_GOMP_CANCEL
+ || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
+ == BUILT_IN_GOMP_CANCELLATION_POINT))
+ {
+ const char *bad = NULL;
+ const char *kind = NULL;
+ if (ctx == NULL)
+ {
+ error_at (gimple_location (stmt), "orphaned %qs construct",
+ DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
+ == BUILT_IN_GOMP_CANCEL
+ ? "#pragma omp cancel"
+ : "#pragma omp cancellation point");
+ return false;
+ }
+ switch (host_integerp (gimple_call_arg (stmt, 0), 0)
+ ? tree_low_cst (gimple_call_arg (stmt, 0), 0)
+ : 0)
+ {
+ case 1:
+ if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
+ bad = "#pragma omp parallel";
+ else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
+ == BUILT_IN_GOMP_CANCEL
+ && !integer_zerop (gimple_call_arg (stmt, 1)))
+ ctx->cancellable = true;
+ kind = "parallel";
+ break;
+ case 2:
+ if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
+ || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
+ bad = "#pragma omp for";
+ else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
+ == BUILT_IN_GOMP_CANCEL
+ && !integer_zerop (gimple_call_arg (stmt, 1)))
+ {
+ ctx->cancellable = true;
+ if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
+ OMP_CLAUSE_NOWAIT))
+ warning_at (gimple_location (stmt), 0,
+ "%<#pragma omp cancel for%> inside "
+ "%<nowait%> for construct");
+ if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
+ OMP_CLAUSE_ORDERED))
+ warning_at (gimple_location (stmt), 0,
+ "%<#pragma omp cancel for%> inside "
+ "%<ordered%> for construct");
+ }
+ kind = "for";
+ break;
+ case 4:
+ if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
+ && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
+ bad = "#pragma omp sections";
+ else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
+ == BUILT_IN_GOMP_CANCEL
+ && !integer_zerop (gimple_call_arg (stmt, 1)))
+ {
+ if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
+ {
+ ctx->cancellable = true;
+ if (find_omp_clause (gimple_omp_sections_clauses
+ (ctx->stmt),
+ OMP_CLAUSE_NOWAIT))
+ warning_at (gimple_location (stmt), 0,
+ "%<#pragma omp cancel sections%> inside "
+ "%<nowait%> sections construct");
+ }
+ else
+ {
+ gcc_assert (ctx->outer
+ && gimple_code (ctx->outer->stmt)
+ == GIMPLE_OMP_SECTIONS);
+ ctx->outer->cancellable = true;
+ if (find_omp_clause (gimple_omp_sections_clauses
+ (ctx->outer->stmt),
+ OMP_CLAUSE_NOWAIT))
+ warning_at (gimple_location (stmt), 0,
+ "%<#pragma omp cancel sections%> inside "
+ "%<nowait%> sections construct");
+ }
+ }
+ kind = "sections";
+ break;
+ case 8:
+ if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
+ bad = "#pragma omp task";
+ else
+ ctx->cancellable = true;
+ kind = "taskgroup";
+ break;
+ default:
+ error_at (gimple_location (stmt), "invalid arguments");
+ return false;
+ }
+ if (bad)
+ {
+ error_at (gimple_location (stmt),
+ "%<%s %s%> construct not closely nested inside of %qs",
+ DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
+ == BUILT_IN_GOMP_CANCEL
+ ? "#pragma omp cancel"
+ : "#pragma omp cancellation point", kind, bad);
+ return false;
+ }
+ }
/* FALLTHRU */
case GIMPLE_OMP_SECTIONS:
case GIMPLE_OMP_SINGLE:
- case GIMPLE_CALL:
for (; ctx != NULL; ctx = ctx->outer)
switch (gimple_code (ctx->stmt))
{
@@ -1891,8 +2384,12 @@ check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
case GIMPLE_OMP_ORDERED:
case GIMPLE_OMP_MASTER:
case GIMPLE_OMP_TASK:
+ case GIMPLE_OMP_CRITICAL:
if (is_gimple_call (stmt))
{
+ if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
+ != BUILT_IN_GOMP_BARRIER)
+ return true;
error_at (gimple_location (stmt),
"barrier region may not be closely nested inside "
"of work-sharing, critical, ordered, master or "
@@ -1949,7 +2446,10 @@ check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
}
return true;
case GIMPLE_OMP_PARALLEL:
- return true;
+ error_at (gimple_location (stmt),
+ "ordered region must be closely nested inside "
+ "a loop region with an ordered clause");
+ return false;
default:
break;
}
@@ -1966,6 +2466,17 @@ check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
return false;
}
break;
+ case GIMPLE_OMP_TEAMS:
+ if (ctx == NULL
+ || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
+ || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
+ {
+ error_at (gimple_location (stmt),
+ "teams construct not closely nested inside of target "
+ "region");
+ return false;
+ }
+ break;
default:
break;
}
@@ -2038,23 +2549,33 @@ scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
input_location = gimple_location (stmt);
/* Check the OpenMP nesting restrictions. */
- if (ctx != NULL)
- {
- bool remove = false;
- if (is_gimple_omp (stmt))
- remove = !check_omp_nesting_restrictions (stmt, ctx);
- else if (is_gimple_call (stmt))
- {
- tree fndecl = gimple_call_fndecl (stmt);
- if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
- && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
+ bool remove = false;
+ if (is_gimple_omp (stmt))
+ remove = !check_omp_nesting_restrictions (stmt, ctx);
+ else if (is_gimple_call (stmt))
+ {
+ tree fndecl = gimple_call_fndecl (stmt);
+ if (fndecl
+ && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
+ switch (DECL_FUNCTION_CODE (fndecl))
+ {
+ case BUILT_IN_GOMP_BARRIER:
+ case BUILT_IN_GOMP_CANCEL:
+ case BUILT_IN_GOMP_CANCELLATION_POINT:
+ case BUILT_IN_GOMP_TASKYIELD:
+ case BUILT_IN_GOMP_TASKWAIT:
+ case BUILT_IN_GOMP_TASKGROUP_START:
+ case BUILT_IN_GOMP_TASKGROUP_END:
remove = !check_omp_nesting_restrictions (stmt, ctx);
- }
- if (remove)
- {
- stmt = gimple_build_nop ();
- gsi_replace (gsi, stmt, false);
- }
+ break;
+ default:
+ break;
+ }
+ }
+ if (remove)
+ {
+ stmt = gimple_build_nop ();
+ gsi_replace (gsi, stmt, false);
}
*handled_ops_p = true;
@@ -2087,12 +2608,21 @@ scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
case GIMPLE_OMP_SECTION:
case GIMPLE_OMP_MASTER:
+ case GIMPLE_OMP_TASKGROUP:
case GIMPLE_OMP_ORDERED:
case GIMPLE_OMP_CRITICAL:
ctx = new_omp_context (stmt, ctx);
scan_omp (gimple_omp_body_ptr (stmt), ctx);
break;
+ case GIMPLE_OMP_TARGET:
+ scan_omp_target (stmt, ctx);
+ break;
+
+ case GIMPLE_OMP_TEAMS:
+ scan_omp_teams (stmt, ctx);
+ break;
+
case GIMPLE_BIND:
{
tree var;
@@ -2135,10 +2665,15 @@ scan_omp (gimple_seq *body_p, omp_context *ctx)
/* Build a call to GOMP_barrier. */
-static tree
-build_omp_barrier (void)
-{
- return build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_BARRIER), 0);
+static gimple
+build_omp_barrier (tree lhs)
+{
+ tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
+ : BUILT_IN_GOMP_BARRIER);
+ gimple g = gimple_build_call (fndecl, 0);
+ if (lhs)
+ gimple_call_set_lhs (g, lhs);
+ return g;
}
/* If a context was created for STMT when it was scanned, return it. */
@@ -2299,6 +2834,49 @@ omp_reduction_init (tree clause, tree type)
}
}
+/* Return alignment to be assumed for var in CLAUSE, which should be
+ OMP_CLAUSE_ALIGNED. */
+
+static tree
+omp_clause_aligned_alignment (tree clause)
+{
+ if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
+ return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
+
+ /* Otherwise return implementation defined alignment. */
+ unsigned int al = 1;
+ enum machine_mode mode, vmode;
+ int vs = targetm.vectorize.autovectorize_vector_sizes ();
+ if (vs)
+ vs = 1 << floor_log2 (vs);
+ static enum mode_class classes[]
+ = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
+ for (int i = 0; i < 4; i += 2)
+ for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
+ mode != VOIDmode;
+ mode = GET_MODE_WIDER_MODE (mode))
+ {
+ vmode = targetm.vectorize.preferred_simd_mode (mode);
+ if (GET_MODE_CLASS (vmode) != classes[i + 1])
+ continue;
+ while (vs
+ && GET_MODE_SIZE (vmode) < vs
+ && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
+ vmode = GET_MODE_2XWIDER_MODE (vmode);
+
+ tree type = lang_hooks.types.type_for_mode (mode, 1);
+ if (type == NULL_TREE || TYPE_MODE (type) != mode)
+ continue;
+ type = build_vector_type (type, GET_MODE_SIZE (vmode)
+ / GET_MODE_SIZE (mode));
+ if (TYPE_MODE (type) != vmode)
+ continue;
+ if (TYPE_ALIGN_UNIT (type) > al)
+ al = TYPE_ALIGN_UNIT (type);
+ }
+ return build_int_cst (integer_type_node, al);
+}
+
/* Return maximum possible vectorization factor for the target. */
static int
@@ -2362,8 +2940,11 @@ lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
NULL_TREE, NULL_TREE);
lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
NULL_TREE, NULL_TREE);
- SET_DECL_VALUE_EXPR (new_var, lvar);
- DECL_HAS_VALUE_EXPR_P (new_var) = 1;
+ if (DECL_P (new_var))
+ {
+ SET_DECL_VALUE_EXPR (new_var, lvar);
+ DECL_HAS_VALUE_EXPR_P (new_var) = 1;
+ }
return true;
}
@@ -2374,11 +2955,12 @@ lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
static void
lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
- omp_context *ctx)
+ omp_context *ctx, struct omp_for_data *fd)
{
tree c, dtor, copyin_seq, x, ptr;
bool copyin_by_ref = false;
bool lastprivate_firstprivate = false;
+ bool reduction_omp_orig_ref = false;
int pass;
bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
&& gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD);
@@ -2398,9 +2980,6 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
switch (OMP_CLAUSE_CODE (c))
{
case OMP_CLAUSE_REDUCTION:
- if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
- max_vf = 1;
- /* FALLTHRU */
case OMP_CLAUSE_PRIVATE:
case OMP_CLAUSE_FIRSTPRIVATE:
case OMP_CLAUSE_LASTPRIVATE:
@@ -2432,6 +3011,9 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
continue;
break;
case OMP_CLAUSE_SHARED:
+ /* Ignore shared directives in teams construct. */
+ if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
+ continue;
if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
{
gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
@@ -2439,9 +3021,16 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
}
case OMP_CLAUSE_FIRSTPRIVATE:
case OMP_CLAUSE_COPYIN:
+ case OMP_CLAUSE_LINEAR:
+ break;
case OMP_CLAUSE_REDUCTION:
+ if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
+ reduction_omp_orig_ref = true;
break;
- case OMP_CLAUSE_LINEAR:
+ case OMP_CLAUSE__LOOPTEMP_:
+ /* Handle _looptemp_ clauses only on parallel. */
+ if (fd)
+ continue;
break;
case OMP_CLAUSE_LASTPRIVATE:
if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
@@ -2451,6 +3040,42 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
continue;
}
break;
+ case OMP_CLAUSE_ALIGNED:
+ if (pass == 0)
+ continue;
+ var = OMP_CLAUSE_DECL (c);
+ if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
+ && !is_global_var (var))
+ {
+ new_var = maybe_lookup_decl (var, ctx);
+ if (new_var == NULL_TREE)
+ new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
+ x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
+ x = build_call_expr_loc (clause_loc, x, 2, new_var,
+ omp_clause_aligned_alignment (c));
+ x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
+ x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
+ gimplify_and_add (x, ilist);
+ }
+ else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
+ && is_global_var (var))
+ {
+ tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
+ new_var = lookup_decl (var, ctx);
+ t = maybe_lookup_decl_in_outer_ctx (var, ctx);
+ t = build_fold_addr_expr_loc (clause_loc, t);
+ t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
+ t = build_call_expr_loc (clause_loc, t2, 2, t,
+ omp_clause_aligned_alignment (c));
+ t = fold_convert_loc (clause_loc, ptype, t);
+ x = create_tmp_var (ptype, NULL);
+ t = build2 (MODIFY_EXPR, ptype, x, t);
+ gimplify_and_add (t, ilist);
+ t = build_simple_mem_ref_loc (clause_loc, x);
+ SET_DECL_VALUE_EXPR (new_var, t);
+ DECL_HAS_VALUE_EXPR_P (new_var) = 1;
+ }
+ continue;
default:
continue;
}
@@ -2502,10 +3127,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
allocate new backing storage for the new pointer
variable. This allows us to avoid changing all the
code that expects a pointer to something that expects
- a direct variable. Note that this doesn't apply to
- C++, since reference types are disallowed in data
- sharing clauses there, except for NRV optimized
- return values. */
+ a direct variable. */
if (pass == 0)
continue;
@@ -2550,6 +3172,9 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
switch (OMP_CLAUSE_CODE (c))
{
case OMP_CLAUSE_SHARED:
+ /* Ignore shared directives in teams construct. */
+ if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
+ continue;
/* Shared global vars are just accessed directly. */
if (is_global_var (new_var))
break;
@@ -2588,19 +3213,20 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
else
x = NULL;
do_private:
- x = lang_hooks.decls.omp_clause_default_ctor (c, new_var, x);
+ tree nx;
+ nx = lang_hooks.decls.omp_clause_default_ctor (c, new_var, x);
if (is_simd)
{
tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
- if ((TREE_ADDRESSABLE (new_var) || x || y
+ if ((TREE_ADDRESSABLE (new_var) || nx || y
|| OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
&& lower_rec_simd_input_clauses (new_var, ctx, max_vf,
idx, lane, ivar, lvar))
{
- if (x)
+ if (nx)
x = lang_hooks.decls.omp_clause_default_ctor
(c, unshare_expr (ivar), x);
- if (x)
+ if (nx && x)
gimplify_and_add (x, &llist[0]);
if (y)
{
@@ -2617,8 +3243,8 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
break;
}
}
- if (x)
- gimplify_and_add (x, ilist);
+ if (nx)
+ gimplify_and_add (nx, ilist);
/* FALLTHRU */
do_dtor:
@@ -2661,6 +3287,44 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
x = build_outer_var_ref (var, ctx);
if (is_simd)
{
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
+ && gimple_omp_for_combined_into_p (ctx->stmt))
+ {
+ tree stept = POINTER_TYPE_P (TREE_TYPE (x))
+ ? sizetype : TREE_TYPE (x);
+ tree t = fold_convert (stept,
+ OMP_CLAUSE_LINEAR_STEP (c));
+ tree c = find_omp_clause (clauses,
+ OMP_CLAUSE__LOOPTEMP_);
+ gcc_assert (c);
+ tree l = OMP_CLAUSE_DECL (c);
+ if (fd->collapse == 1)
+ {
+ tree n1 = fd->loop.n1;
+ tree step = fd->loop.step;
+ tree itype = TREE_TYPE (l);
+ if (POINTER_TYPE_P (itype))
+ itype = signed_type_for (itype);
+ l = fold_build2 (MINUS_EXPR, itype, l, n1);
+ if (TYPE_UNSIGNED (itype)
+ && fd->loop.cond_code == GT_EXPR)
+ l = fold_build2 (TRUNC_DIV_EXPR, itype,
+ fold_build1 (NEGATE_EXPR,
+ itype, l),
+ fold_build1 (NEGATE_EXPR,
+ itype, step));
+ else
+ l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
+ }
+ t = fold_build2 (MULT_EXPR, stept,
+ fold_convert (stept, l), t);
+ if (POINTER_TYPE_P (TREE_TYPE (x)))
+ x = fold_build2 (POINTER_PLUS_EXPR,
+ TREE_TYPE (x), x, t);
+ else
+ x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
+ }
+
if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
|| TREE_ADDRESSABLE (new_var))
&& lower_rec_simd_input_clauses (new_var, ctx, max_vf,
@@ -2708,6 +3372,13 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
gimplify_and_add (x, ilist);
goto do_dtor;
+ case OMP_CLAUSE__LOOPTEMP_:
+ gcc_assert (is_parallel_ctx (ctx));
+ x = build_outer_var_ref (var, ctx);
+ x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
+ gimplify_and_add (x, ilist);
+ break;
+
case OMP_CLAUSE_COPYIN:
by_ref = use_pointer_for_field (var, NULL);
x = build_receiver_ref (var, by_ref, ctx);
@@ -2720,19 +3391,89 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
{
tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
+ gimple tseq;
x = build_outer_var_ref (var, ctx);
- /* FIXME: Not handled yet. */
- gcc_assert (!is_simd);
- if (is_reference (var))
+ if (is_reference (var)
+ && !useless_type_conversion_p (TREE_TYPE (placeholder),
+ TREE_TYPE (x)))
x = build_fold_addr_expr_loc (clause_loc, x);
SET_DECL_VALUE_EXPR (placeholder, x);
DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
- lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
- gimple_seq_add_seq (ilist,
- OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c));
+ tree new_vard = new_var;
+ if (is_reference (var))
+ {
+ gcc_assert (TREE_CODE (new_var) == MEM_REF);
+ new_vard = TREE_OPERAND (new_var, 0);
+ gcc_assert (DECL_P (new_vard));
+ }
+ if (is_simd
+ && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
+ idx, lane, ivar, lvar))
+ {
+ if (new_vard == new_var)
+ {
+ gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
+ SET_DECL_VALUE_EXPR (new_var, ivar);
+ }
+ else
+ {
+ SET_DECL_VALUE_EXPR (new_vard,
+ build_fold_addr_expr (ivar));
+ DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
+ }
+ x = lang_hooks.decls.omp_clause_default_ctor
+ (c, unshare_expr (ivar),
+ build_outer_var_ref (var, ctx));
+ if (x)
+ gimplify_and_add (x, &llist[0]);
+ if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
+ {
+ tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
+ lower_omp (&tseq, ctx);
+ gimple_seq_add_seq (&llist[0], tseq);
+ }
+ OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
+ tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
+ lower_omp (&tseq, ctx);
+ gimple_seq_add_seq (&llist[1], tseq);
+ OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
+ DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
+ if (new_vard == new_var)
+ SET_DECL_VALUE_EXPR (new_var, lvar);
+ else
+ SET_DECL_VALUE_EXPR (new_vard,
+ build_fold_addr_expr (lvar));
+ x = lang_hooks.decls.omp_clause_dtor (c, ivar);
+ if (x)
+ {
+ tseq = NULL;
+ dtor = x;
+ gimplify_stmt (&dtor, &tseq);
+ gimple_seq_add_seq (&llist[1], tseq);
+ }
+ break;
+ }
+ x = lang_hooks.decls.omp_clause_default_ctor
+ (c, new_var, unshare_expr (x));
+ if (x)
+ gimplify_and_add (x, ilist);
+ if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
+ {
+ tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
+ lower_omp (&tseq, ctx);
+ gimple_seq_add_seq (ilist, tseq);
+ }
OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
+ if (is_simd)
+ {
+ tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
+ lower_omp (&tseq, ctx);
+ gimple_seq_add_seq (dlist, tseq);
+ OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
+ }
DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
+ goto do_dtor;
}
else
{
@@ -2835,14 +3576,15 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
master thread doesn't modify it before it is copied over in all
threads. Similarly for variables in both firstprivate and
lastprivate clauses we need to ensure the lastprivate copying
- happens after firstprivate copying in all threads. */
- if (copyin_by_ref || lastprivate_firstprivate)
+ happens after firstprivate copying in all threads. And similarly
+ for UDRs if initializer expression refers to omp_orig. */
+ if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
{
/* Don't add any barrier for #pragma omp simd or
#pragma omp distribute. */
if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
|| gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
- gimplify_and_add (build_omp_barrier (), ilist);
+ gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
}
/* If max_vf is non-zero, then we can use only a vectorization factor
@@ -2871,7 +3613,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
static void
lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
- omp_context *ctx)
+ omp_context *ctx)
{
tree x, c, label = NULL, orig_clauses = clauses;
bool par_clauses = false;
@@ -3025,7 +3767,7 @@ lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
{
if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
{
- /* Never use OMP_ATOMIC for array reductions. */
+ /* Never use OMP_ATOMIC for array reductions or UDRs. */
count = -1;
break;
}
@@ -3072,7 +3814,9 @@ lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
{
tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
- if (is_reference (var))
+ if (is_reference (var)
+ && !useless_type_conversion_p (TREE_TYPE (placeholder),
+ TREE_TYPE (ref)))
ref = build_fold_addr_expr_loc (clause_loc, ref);
SET_DECL_VALUE_EXPR (placeholder, ref);
DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
@@ -3175,6 +3919,7 @@ lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
case OMP_CLAUSE_COPYIN:
case OMP_CLAUSE_LASTPRIVATE:
case OMP_CLAUSE_REDUCTION:
+ case OMP_CLAUSE__LOOPTEMP_:
break;
default:
continue;
@@ -3195,6 +3940,7 @@ lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
case OMP_CLAUSE_PRIVATE:
case OMP_CLAUSE_FIRSTPRIVATE:
case OMP_CLAUSE_COPYIN:
+ case OMP_CLAUSE__LOOPTEMP_:
do_in = true;
break;
@@ -3317,7 +4063,7 @@ static void
expand_parallel_call (struct omp_region *region, basic_block bb,
gimple entry_stmt, vec<tree, va_gc> *ws_args)
{
- tree t, t1, t2, val, cond, c, clauses;
+ tree t, t1, t2, val, cond, c, clauses, flags;
gimple_stmt_iterator gsi;
gimple stmt;
enum built_in_function start_ix;
@@ -3327,23 +4073,23 @@ expand_parallel_call (struct omp_region *region, basic_block bb,
clauses = gimple_omp_parallel_clauses (entry_stmt);
- /* Determine what flavor of GOMP_parallel_start we will be
+ /* Determine what flavor of GOMP_parallel we will be
emitting. */
- start_ix = BUILT_IN_GOMP_PARALLEL_START;
+ start_ix = BUILT_IN_GOMP_PARALLEL;
if (is_combined_parallel (region))
{
switch (region->inner->type)
{
case GIMPLE_OMP_FOR:
gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
- start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC_START
+ start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
+ (region->inner->sched_kind
== OMP_CLAUSE_SCHEDULE_RUNTIME
? 3 : region->inner->sched_kind));
start_ix = (enum built_in_function)start_ix2;
break;
case GIMPLE_OMP_SECTIONS:
- start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS_START;
+ start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
break;
default:
gcc_unreachable ();
@@ -3354,6 +4100,7 @@ expand_parallel_call (struct omp_region *region, basic_block bb,
and there is no conditional. */
cond = NULL_TREE;
val = build_int_cst (unsigned_type_node, 0);
+ flags = build_int_cst (unsigned_type_node, 0);
c = find_omp_clause (clauses, OMP_CLAUSE_IF);
if (c)
@@ -3368,6 +4115,10 @@ expand_parallel_call (struct omp_region *region, basic_block bb,
else
clause_loc = gimple_location (entry_stmt);
+ c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
+ if (c)
+ flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
+
/* Ensure 'val' is of the correct type. */
val = fold_convert_loc (clause_loc, unsigned_type_node, val);
@@ -3459,34 +4210,19 @@ expand_parallel_call (struct omp_region *region, basic_block bb,
t1 = build_fold_addr_expr (t);
t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
- vec_alloc (args, 3 + vec_safe_length (ws_args));
+ vec_alloc (args, 4 + vec_safe_length (ws_args));
args->quick_push (t2);
args->quick_push (t1);
args->quick_push (val);
if (ws_args)
args->splice (*ws_args);
+ args->quick_push (flags);
t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
builtin_decl_explicit (start_ix), args);
force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
false, GSI_CONTINUE_LINKING);
-
- t = gimple_omp_parallel_data_arg (entry_stmt);
- if (t == NULL)
- t = null_pointer_node;
- else
- t = build_fold_addr_expr (t);
- t = build_call_expr_loc (gimple_location (entry_stmt),
- gimple_omp_parallel_child_fn (entry_stmt), 1, t);
- force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
- false, GSI_CONTINUE_LINKING);
-
- t = build_call_expr_loc (gimple_location (entry_stmt),
- builtin_decl_explicit (BUILT_IN_GOMP_PARALLEL_END),
- 0);
- force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
- false, GSI_CONTINUE_LINKING);
}
@@ -3496,7 +4232,7 @@ expand_parallel_call (struct omp_region *region, basic_block bb,
static void
expand_task_call (basic_block bb, gimple entry_stmt)
{
- tree t, t1, t2, t3, flags, cond, c, c2, clauses;
+ tree t, t1, t2, t3, flags, cond, c, c2, clauses, depend;
gimple_stmt_iterator gsi;
location_t loc = gimple_location (entry_stmt);
@@ -3510,8 +4246,9 @@ expand_task_call (basic_block bb, gimple entry_stmt)
c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
c2 = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
+ depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
flags = build_int_cst (unsigned_type_node,
- (c ? 1 : 0) + (c2 ? 4 : 0));
+ (c ? 1 : 0) + (c2 ? 4 : 0) + (depend ? 8 : 0));
c = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
if (c)
@@ -3522,6 +4259,10 @@ expand_task_call (basic_block bb, gimple entry_stmt)
build_int_cst (unsigned_type_node, 0));
flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, c);
}
+ if (depend)
+ depend = OMP_CLAUSE_DECL (depend);
+ else
+ depend = build_int_cst (ptr_type_node, 0);
gsi = gsi_last_bb (bb);
t = gimple_omp_task_data_arg (entry_stmt);
@@ -3537,9 +4278,10 @@ expand_task_call (basic_block bb, gimple entry_stmt)
t3 = build_fold_addr_expr_loc (loc, t);
t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
- 7, t1, t2, t3,
+ 8, t1, t2, t3,
gimple_omp_task_arg_size (entry_stmt),
- gimple_omp_task_arg_align (entry_stmt), cond, flags);
+ gimple_omp_task_arg_align (entry_stmt), cond, flags,
+ depend);
force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
false, GSI_CONTINUE_LINKING);
@@ -4064,7 +4806,9 @@ expand_omp_taskreg (struct omp_region *region)
count = count1 * count2 * count3;
Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
count = 0;
- and set ZERO_ITER_BB to that bb. */
+ and set ZERO_ITER_BB to that bb. If this isn't the outermost
+ of the combined loop constructs, just initialize COUNTS array
+ from the _looptemp_ clauses. */
/* NOTE: It *could* be better to moosh all of the BBs together,
creating one larger BB with all the computation and the unexpected
@@ -4106,6 +4850,28 @@ expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
/* Collapsed loops need work for expansion into SSA form. */
gcc_assert (!gimple_in_ssa_p (cfun));
+ if (gimple_omp_for_combined_into_p (fd->for_stmt)
+ && TREE_CODE (fd->loop.n2) != INTEGER_CST)
+ {
+ /* First two _looptemp_ clauses are for istart/iend, counts[0]
+ isn't supposed to be handled, as the inner loop doesn't
+ use it. */
+ tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
+ OMP_CLAUSE__LOOPTEMP_);
+ gcc_assert (innerc);
+ for (i = 0; i < fd->collapse; i++)
+ {
+ innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
+ OMP_CLAUSE__LOOPTEMP_);
+ gcc_assert (innerc);
+ if (i)
+ counts[i] = OMP_CLAUSE_DECL (innerc);
+ else
+ counts[0] = NULL_TREE;
+ }
+ return;
+ }
+
for (i = 0; i < fd->collapse; i++)
{
tree itype = TREE_TYPE (fd->loops[i].v);
@@ -4209,13 +4975,49 @@ expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
V2 = N21 + (T % count2) * STEP2;
T = T / count2;
V1 = N11 + T * STEP1;
- if this loop doesn't have an inner loop construct combined with it. */
+ if this loop doesn't have an inner loop construct combined with it.
+ If it does have an inner loop construct combined with it and the
+ iteration count isn't known constant, store values from counts array
+ into its _looptemp_ temporaries instead. */
static void
expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
- tree *counts, tree startvar)
+ tree *counts, gimple inner_stmt, tree startvar)
{
int i;
+ if (gimple_omp_for_combined_p (fd->for_stmt))
+ {
+ /* If fd->loop.n2 is constant, then no propagation of the counts
+ is needed, they are constant. */
+ if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
+ return;
+
+ tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
+ ? gimple_omp_parallel_clauses (inner_stmt)
+ : gimple_omp_for_clauses (inner_stmt);
+ /* First two _looptemp_ clauses are for istart/iend, counts[0]
+ isn't supposed to be handled, as the inner loop doesn't
+ use it. */
+ tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
+ gcc_assert (innerc);
+ for (i = 0; i < fd->collapse; i++)
+ {
+ innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
+ OMP_CLAUSE__LOOPTEMP_);
+ gcc_assert (innerc);
+ if (i)
+ {
+ tree tem = OMP_CLAUSE_DECL (innerc);
+ tree t = fold_convert (TREE_TYPE (tem), counts[i]);
+ t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
+ false, GSI_CONTINUE_LINKING);
+ gimple stmt = gimple_build_assign (tem, t);
+ gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
+ }
+ }
+ return;
+ }
+
tree type = TREE_TYPE (fd->loop.v);
tree tem = create_tmp_reg (type, ".tem");
gimple stmt = gimple_build_assign (tem, startvar);
@@ -4368,6 +5170,10 @@ extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
If this is a combined omp parallel loop, instead of the call to
GOMP_loop_foo_start, we call GOMP_loop_foo_next.
+ If this is gimple_omp_for_combined_p loop, then instead of assigning
+ V and iend in L0 we assign the first two _looptemp_ clause decls of the
+ inner GIMPLE_OMP_FOR and V += STEP; and
+ if (V cond iend) goto L1; else goto L2; are removed.
For collapsed loops, given parameters:
collapse(3)
@@ -4437,7 +5243,8 @@ static void
expand_omp_for_generic (struct omp_region *region,
struct omp_for_data *fd,
enum built_in_function start_fn,
- enum built_in_function next_fn)
+ enum built_in_function next_fn,
+ gimple inner_stmt)
{
tree type, istart0, iend0, iend;
tree t, vmain, vback, bias = NULL_TREE;
@@ -4552,6 +5359,17 @@ expand_omp_for_generic (struct omp_region *region,
t2 = fold_convert (fd->iter_type, fd->loop.step);
t1 = fd->loop.n2;
t0 = fd->loop.n1;
+ if (gimple_omp_for_combined_into_p (fd->for_stmt))
+ {
+ tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
+ OMP_CLAUSE__LOOPTEMP_);
+ gcc_assert (innerc);
+ t0 = OMP_CLAUSE_DECL (innerc);
+ innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
+ OMP_CLAUSE__LOOPTEMP_);
+ gcc_assert (innerc);
+ t1 = OMP_CLAUSE_DECL (innerc);
+ }
if (POINTER_TYPE_P (TREE_TYPE (t0))
&& TYPE_PRECISION (TREE_TYPE (t0))
!= TYPE_PRECISION (fd->iter_type))
@@ -4622,6 +5440,21 @@ expand_omp_for_generic (struct omp_region *region,
tree startvar = fd->loop.v;
tree endvar = NULL_TREE;
+ if (gimple_omp_for_combined_p (fd->for_stmt))
+ {
+ gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
+ && gimple_omp_for_kind (inner_stmt)
+ == GF_OMP_FOR_KIND_SIMD);
+ tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
+ OMP_CLAUSE__LOOPTEMP_);
+ gcc_assert (innerc);
+ startvar = OMP_CLAUSE_DECL (innerc);
+ innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
+ OMP_CLAUSE__LOOPTEMP_);
+ gcc_assert (innerc);
+ endvar = OMP_CLAUSE_DECL (innerc);
+ }
+
gsi = gsi_start_bb (l0_bb);
t = istart0;
if (bias)
@@ -4650,7 +5483,7 @@ expand_omp_for_generic (struct omp_region *region,
gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
}
if (fd->collapse > 1)
- expand_omp_for_init_vars (fd, &gsi, counts, startvar);
+ expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
if (!broken_loop)
{
@@ -4662,8 +5495,7 @@ expand_omp_for_generic (struct omp_region *region,
vmain = gimple_omp_continue_control_use (stmt);
vback = gimple_omp_continue_control_def (stmt);
- /* OMP4 placeholder: if (!gimple_omp_for_combined_p (fd->for_stmt)). */
- if (1)
+ if (!gimple_omp_for_combined_p (fd->for_stmt))
{
if (POINTER_TYPE_P (type))
t = fold_build_pointer_plus (vmain, fd->loop.step);
@@ -4686,7 +5518,7 @@ expand_omp_for_generic (struct omp_region *region,
/* Remove GIMPLE_OMP_CONTINUE. */
gsi_remove (&gsi, true);
- if (fd->collapse > 1)
+ if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
/* Emit code to get the next parallel iteration in L2_BB. */
@@ -4708,9 +5540,13 @@ expand_omp_for_generic (struct omp_region *region,
gsi = gsi_last_bb (exit_bb);
if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
+ else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
+ t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
else
t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
stmt = gimple_build_call (t, 0);
+ if (gimple_omp_return_lhs (gsi_stmt (gsi)))
+ gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
gsi_remove (&gsi, true);
@@ -4738,9 +5574,11 @@ expand_omp_for_generic (struct omp_region *region,
if (current_loops)
add_bb_to_loop (l2_bb, cont_bb->loop_father);
e = find_edge (cont_bb, l1_bb);
- /* OMP4 placeholder for gimple_omp_for_combined_p (fd->for_stmt). */
- if (0)
- ;
+ if (gimple_omp_for_combined_p (fd->for_stmt))
+ {
+ remove_edge (e);
+ e = NULL;
+ }
else if (fd->collapse > 1)
{
remove_edge (e);
@@ -4774,8 +5612,7 @@ expand_omp_for_generic (struct omp_region *region,
outer_loop->latch = l2_bb;
add_loop (outer_loop, l0_bb->loop_father);
- /* OMP4 placeholder: if (!gimple_omp_for_combined_p (fd->for_stmt)). */
- if (1)
+ if (!gimple_omp_for_combined_p (fd->for_stmt))
{
struct loop *loop = alloc_loop ();
loop->header = l1_bb;
@@ -4825,16 +5662,22 @@ expand_omp_for_generic (struct omp_region *region,
static void
expand_omp_for_static_nochunk (struct omp_region *region,
- struct omp_for_data *fd)
+ struct omp_for_data *fd,
+ gimple inner_stmt)
{
tree n, q, s0, e0, e, t, tt, nthreads, threadid;
tree type, itype, vmain, vback;
basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
- basic_block body_bb, cont_bb;
+ basic_block body_bb, cont_bb, collapse_bb = NULL;
basic_block fin_bb;
gimple_stmt_iterator gsi;
gimple stmt;
edge ep;
+ enum built_in_function get_num_threads = BUILT_IN_OMP_GET_NUM_THREADS;
+ enum built_in_function get_thread_num = BUILT_IN_OMP_GET_THREAD_NUM;
+ bool broken_loop = region->cont == NULL;
+ tree *counts = NULL;
+ tree n1, n2, step;
itype = type = TREE_TYPE (fd->loop.v);
if (POINTER_TYPE_P (type))
@@ -4843,25 +5686,49 @@ expand_omp_for_static_nochunk (struct omp_region *region,
entry_bb = region->entry;
cont_bb = region->cont;
gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
- gcc_assert (BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
+ fin_bb = BRANCH_EDGE (entry_bb)->dest;
+ gcc_assert (broken_loop
+ || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
body_bb = single_succ (seq_start_bb);
- gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
- gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
- fin_bb = FALLTHRU_EDGE (cont_bb)->dest;
+ if (!broken_loop)
+ {
+ gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
+ gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
+ }
exit_bb = region->exit;
/* Iteration space partitioning goes in ENTRY_BB. */
gsi = gsi_last_bb (entry_bb);
gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
- t = fold_binary (fd->loop.cond_code, boolean_type_node,
- fold_convert (type, fd->loop.n1),
- fold_convert (type, fd->loop.n2));
- if (TYPE_UNSIGNED (type)
+ if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
+ {
+ get_num_threads = BUILT_IN_OMP_GET_NUM_TEAMS;
+ get_thread_num = BUILT_IN_OMP_GET_TEAM_NUM;
+ }
+
+ if (fd->collapse > 1)
+ {
+ int first_zero_iter = -1;
+ basic_block l2_dom_bb = NULL;
+
+ counts = XALLOCAVEC (tree, fd->collapse);
+ expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
+ fin_bb, first_zero_iter,
+ l2_dom_bb);
+ t = NULL_TREE;
+ }
+ else if (gimple_omp_for_combined_into_p (fd->for_stmt))
+ t = integer_one_node;
+ else
+ t = fold_binary (fd->loop.cond_code, boolean_type_node,
+ fold_convert (type, fd->loop.n1),
+ fold_convert (type, fd->loop.n2));
+ if (fd->collapse == 1
+ && TYPE_UNSIGNED (type)
&& (t == NULL_TREE || !integer_onep (t)))
{
- tree n1, n2;
n1 = fold_convert (type, unshare_expr (fd->loop.n1));
n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
true, GSI_SAME_STMT);
@@ -4899,36 +5766,47 @@ expand_omp_for_static_nochunk (struct omp_region *region,
gsi = gsi_last_bb (entry_bb);
}
- t = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS), 0);
+ t = build_call_expr (builtin_decl_explicit (get_num_threads), 0);
t = fold_convert (itype, t);
nthreads = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
true, GSI_SAME_STMT);
- t = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM), 0);
+ t = build_call_expr (builtin_decl_explicit (get_thread_num), 0);
t = fold_convert (itype, t);
threadid = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
true, GSI_SAME_STMT);
- fd->loop.n1
- = force_gimple_operand_gsi (&gsi, fold_convert (type, fd->loop.n1),
- true, NULL_TREE, true, GSI_SAME_STMT);
- fd->loop.n2
- = force_gimple_operand_gsi (&gsi, fold_convert (itype, fd->loop.n2),
- true, NULL_TREE, true, GSI_SAME_STMT);
- fd->loop.step
- = force_gimple_operand_gsi (&gsi, fold_convert (itype, fd->loop.step),
- true, NULL_TREE, true, GSI_SAME_STMT);
+ n1 = fd->loop.n1;
+ n2 = fd->loop.n2;
+ step = fd->loop.step;
+ if (gimple_omp_for_combined_into_p (fd->for_stmt))
+ {
+ tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
+ OMP_CLAUSE__LOOPTEMP_);
+ gcc_assert (innerc);
+ n1 = OMP_CLAUSE_DECL (innerc);
+ innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
+ OMP_CLAUSE__LOOPTEMP_);
+ gcc_assert (innerc);
+ n2 = OMP_CLAUSE_DECL (innerc);
+ }
+ n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
+ true, NULL_TREE, true, GSI_SAME_STMT);
+ n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
+ true, NULL_TREE, true, GSI_SAME_STMT);
+ step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
+ true, NULL_TREE, true, GSI_SAME_STMT);
t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
- t = fold_build2 (PLUS_EXPR, itype, fd->loop.step, t);
- t = fold_build2 (PLUS_EXPR, itype, t, fd->loop.n2);
- t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, fd->loop.n1));
+ t = fold_build2 (PLUS_EXPR, itype, step, t);
+ t = fold_build2 (PLUS_EXPR, itype, t, n2);
+ t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
t = fold_build2 (TRUNC_DIV_EXPR, itype,
fold_build1 (NEGATE_EXPR, itype, t),
- fold_build1 (NEGATE_EXPR, itype, fd->loop.step));
+ fold_build1 (NEGATE_EXPR, itype, step));
else
- t = fold_build2 (TRUNC_DIV_EXPR, itype, t, fd->loop.step);
+ t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
t = fold_convert (itype, t);
n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
@@ -4976,58 +5854,96 @@ expand_omp_for_static_nochunk (struct omp_region *region,
/* Setup code for sequential iteration goes in SEQ_START_BB. */
gsi = gsi_start_bb (seq_start_bb);
+ tree startvar = fd->loop.v;
+ tree endvar = NULL_TREE;
+
+ if (gimple_omp_for_combined_p (fd->for_stmt))
+ {
+ tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
+ ? gimple_omp_parallel_clauses (inner_stmt)
+ : gimple_omp_for_clauses (inner_stmt);
+ tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
+ gcc_assert (innerc);
+ startvar = OMP_CLAUSE_DECL (innerc);
+ innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
+ OMP_CLAUSE__LOOPTEMP_);
+ gcc_assert (innerc);
+ endvar = OMP_CLAUSE_DECL (innerc);
+ }
t = fold_convert (itype, s0);
- t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
+ t = fold_build2 (MULT_EXPR, itype, t, step);
if (POINTER_TYPE_P (type))
- t = fold_build_pointer_plus (fd->loop.n1, t);
+ t = fold_build_pointer_plus (n1, t);
else
- t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1);
+ t = fold_build2 (PLUS_EXPR, type, t, n1);
+ t = fold_convert (TREE_TYPE (startvar), t);
t = force_gimple_operand_gsi (&gsi, t,
- DECL_P (fd->loop.v)
- && TREE_ADDRESSABLE (fd->loop.v),
+ DECL_P (startvar)
+ && TREE_ADDRESSABLE (startvar),
NULL_TREE, false, GSI_CONTINUE_LINKING);
- stmt = gimple_build_assign (fd->loop.v, t);
+ stmt = gimple_build_assign (startvar, t);
gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
t = fold_convert (itype, e0);
- t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
+ t = fold_build2 (MULT_EXPR, itype, t, step);
if (POINTER_TYPE_P (type))
- t = fold_build_pointer_plus (fd->loop.n1, t);
+ t = fold_build_pointer_plus (n1, t);
else
- t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1);
+ t = fold_build2 (PLUS_EXPR, type, t, n1);
+ t = fold_convert (TREE_TYPE (startvar), t);
e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
false, GSI_CONTINUE_LINKING);
+ if (endvar)
+ {
+ stmt = gimple_build_assign (endvar, e);
+ gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
+ }
+ if (fd->collapse > 1)
+ expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
- /* The code controlling the sequential loop replaces the
- GIMPLE_OMP_CONTINUE. */
- gsi = gsi_last_bb (cont_bb);
- stmt = gsi_stmt (gsi);
- gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
- vmain = gimple_omp_continue_control_use (stmt);
- vback = gimple_omp_continue_control_def (stmt);
+ if (!broken_loop)
+ {
+ /* The code controlling the sequential loop replaces the
+ GIMPLE_OMP_CONTINUE. */
+ gsi = gsi_last_bb (cont_bb);
+ stmt = gsi_stmt (gsi);
+ gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
+ vmain = gimple_omp_continue_control_use (stmt);
+ vback = gimple_omp_continue_control_def (stmt);
- if (POINTER_TYPE_P (type))
- t = fold_build_pointer_plus (vmain, fd->loop.step);
- else
- t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
- t = force_gimple_operand_gsi (&gsi, t,
- DECL_P (vback) && TREE_ADDRESSABLE (vback),
- NULL_TREE, true, GSI_SAME_STMT);
- stmt = gimple_build_assign (vback, t);
- gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
+ if (!gimple_omp_for_combined_p (fd->for_stmt))
+ {
+ if (POINTER_TYPE_P (type))
+ t = fold_build_pointer_plus (vmain, step);
+ else
+ t = fold_build2 (PLUS_EXPR, type, vmain, step);
+ t = force_gimple_operand_gsi (&gsi, t,
+ DECL_P (vback)
+ && TREE_ADDRESSABLE (vback),
+ NULL_TREE, true, GSI_SAME_STMT);
+ stmt = gimple_build_assign (vback, t);
+ gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
- t = build2 (fd->loop.cond_code, boolean_type_node,
- DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback, e);
- gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
+ t = build2 (fd->loop.cond_code, boolean_type_node,
+ DECL_P (vback) && TREE_ADDRESSABLE (vback)
+ ? t : vback, e);
+ gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
+ }
- /* Remove the GIMPLE_OMP_CONTINUE statement. */
- gsi_remove (&gsi, true);
+ /* Remove the GIMPLE_OMP_CONTINUE statement. */
+ gsi_remove (&gsi, true);
+
+ if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
+ collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
+ }
/* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
gsi = gsi_last_bb (exit_bb);
if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
- force_gimple_operand_gsi (&gsi, build_omp_barrier (), false, NULL_TREE,
- false, GSI_SAME_STMT);
+ {
+ t = gimple_omp_return_lhs (gsi_stmt (gsi));
+ gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
+ }
gsi_remove (&gsi, true);
/* Connect all the blocks. */
@@ -5039,21 +5955,42 @@ expand_omp_for_static_nochunk (struct omp_region *region,
find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
- find_edge (cont_bb, body_bb)->flags = EDGE_TRUE_VALUE;
- find_edge (cont_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
+ if (!broken_loop)
+ {
+ ep = find_edge (cont_bb, body_bb);
+ if (gimple_omp_for_combined_p (fd->for_stmt))
+ {
+ remove_edge (ep);
+ ep = NULL;
+ }
+ else if (fd->collapse > 1)
+ {
+ remove_edge (ep);
+ ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
+ }
+ else
+ ep->flags = EDGE_TRUE_VALUE;
+ find_edge (cont_bb, fin_bb)->flags
+ = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
+ }
set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
+
set_immediate_dominator (CDI_DOMINATORS, body_bb,
recompute_dominator (CDI_DOMINATORS, body_bb));
set_immediate_dominator (CDI_DOMINATORS, fin_bb,
recompute_dominator (CDI_DOMINATORS, fin_bb));
- struct loop *loop = alloc_loop ();
- loop->header = body_bb;
- loop->latch = cont_bb;
- add_loop (loop, body_bb->loop_father);
+ if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
+ {
+ struct loop *loop = alloc_loop ();
+ loop->header = body_bb;
+ if (collapse_bb == NULL)
+ loop->latch = cont_bb;
+ add_loop (loop, body_bb->loop_father);
+ }
}
@@ -5096,16 +6033,22 @@ expand_omp_for_static_nochunk (struct omp_region *region,
*/
static void
-expand_omp_for_static_chunk (struct omp_region *region, struct omp_for_data *fd)
+expand_omp_for_static_chunk (struct omp_region *region,
+ struct omp_for_data *fd, gimple inner_stmt)
{
tree n, s0, e0, e, t;
tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
tree type, itype, v_main, v_back, v_extra;
basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
- basic_block trip_update_bb, cont_bb, fin_bb;
+ basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
gimple_stmt_iterator si;
gimple stmt;
edge se;
+ enum built_in_function get_num_threads = BUILT_IN_OMP_GET_NUM_THREADS;
+ enum built_in_function get_thread_num = BUILT_IN_OMP_GET_THREAD_NUM;
+ bool broken_loop = region->cont == NULL;
+ tree *counts = NULL;
+ tree n1, n2, step;
itype = type = TREE_TYPE (fd->loop.v);
if (POINTER_TYPE_P (type))
@@ -5117,27 +6060,50 @@ expand_omp_for_static_chunk (struct omp_region *region, struct omp_for_data *fd)
iter_part_bb = se->dest;
cont_bb = region->cont;
gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
- gcc_assert (BRANCH_EDGE (iter_part_bb)->dest
- == FALLTHRU_EDGE (cont_bb)->dest);
+ fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
+ gcc_assert (broken_loop
+ || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
body_bb = single_succ (seq_start_bb);
- gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
- gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
- fin_bb = FALLTHRU_EDGE (cont_bb)->dest;
- trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
+ if (!broken_loop)
+ {
+ gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
+ gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
+ trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
+ }
exit_bb = region->exit;
/* Trip and adjustment setup goes in ENTRY_BB. */
si = gsi_last_bb (entry_bb);
gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_FOR);
- t = fold_binary (fd->loop.cond_code, boolean_type_node,
- fold_convert (type, fd->loop.n1),
- fold_convert (type, fd->loop.n2));
- if (TYPE_UNSIGNED (type)
+ if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
+ {
+ get_num_threads = BUILT_IN_OMP_GET_NUM_TEAMS;
+ get_thread_num = BUILT_IN_OMP_GET_TEAM_NUM;
+ }
+
+ if (fd->collapse > 1)
+ {
+ int first_zero_iter = -1;
+ basic_block l2_dom_bb = NULL;
+
+ counts = XALLOCAVEC (tree, fd->collapse);
+ expand_omp_for_init_counts (fd, &si, entry_bb, counts,
+ fin_bb, first_zero_iter,
+ l2_dom_bb);
+ t = NULL_TREE;
+ }
+ else if (gimple_omp_for_combined_into_p (fd->for_stmt))
+ t = integer_one_node;
+ else
+ t = fold_binary (fd->loop.cond_code, boolean_type_node,
+ fold_convert (type, fd->loop.n1),
+ fold_convert (type, fd->loop.n2));
+ if (fd->collapse == 1
+ && TYPE_UNSIGNED (type)
&& (t == NULL_TREE || !integer_onep (t)))
{
- tree n1, n2;
n1 = fold_convert (type, unshare_expr (fd->loop.n1));
n1 = force_gimple_operand_gsi (&si, n1, true, NULL_TREE,
true, GSI_SAME_STMT);
@@ -5175,39 +6141,50 @@ expand_omp_for_static_chunk (struct omp_region *region, struct omp_for_data *fd)
si = gsi_last_bb (entry_bb);
}
- t = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS), 0);
+ t = build_call_expr (builtin_decl_explicit (get_num_threads), 0);
t = fold_convert (itype, t);
nthreads = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
true, GSI_SAME_STMT);
- t = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM), 0);
+ t = build_call_expr (builtin_decl_explicit (get_thread_num), 0);
t = fold_convert (itype, t);
threadid = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
true, GSI_SAME_STMT);
- fd->loop.n1
- = force_gimple_operand_gsi (&si, fold_convert (type, fd->loop.n1),
- true, NULL_TREE, true, GSI_SAME_STMT);
- fd->loop.n2
- = force_gimple_operand_gsi (&si, fold_convert (itype, fd->loop.n2),
- true, NULL_TREE, true, GSI_SAME_STMT);
- fd->loop.step
- = force_gimple_operand_gsi (&si, fold_convert (itype, fd->loop.step),
- true, NULL_TREE, true, GSI_SAME_STMT);
+ n1 = fd->loop.n1;
+ n2 = fd->loop.n2;
+ step = fd->loop.step;
+ if (gimple_omp_for_combined_into_p (fd->for_stmt))
+ {
+ tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
+ OMP_CLAUSE__LOOPTEMP_);
+ gcc_assert (innerc);
+ n1 = OMP_CLAUSE_DECL (innerc);
+ innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
+ OMP_CLAUSE__LOOPTEMP_);
+ gcc_assert (innerc);
+ n2 = OMP_CLAUSE_DECL (innerc);
+ }
+ n1 = force_gimple_operand_gsi (&si, fold_convert (type, n1),
+ true, NULL_TREE, true, GSI_SAME_STMT);
+ n2 = force_gimple_operand_gsi (&si, fold_convert (itype, n2),
+ true, NULL_TREE, true, GSI_SAME_STMT);
+ step = force_gimple_operand_gsi (&si, fold_convert (itype, step),
+ true, NULL_TREE, true, GSI_SAME_STMT);
fd->chunk_size
= force_gimple_operand_gsi (&si, fold_convert (itype, fd->chunk_size),
true, NULL_TREE, true, GSI_SAME_STMT);
t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
- t = fold_build2 (PLUS_EXPR, itype, fd->loop.step, t);
- t = fold_build2 (PLUS_EXPR, itype, t, fd->loop.n2);
- t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, fd->loop.n1));
+ t = fold_build2 (PLUS_EXPR, itype, step, t);
+ t = fold_build2 (PLUS_EXPR, itype, t, n2);
+ t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
t = fold_build2 (TRUNC_DIV_EXPR, itype,
fold_build1 (NEGATE_EXPR, itype, t),
- fold_build1 (NEGATE_EXPR, itype, fd->loop.step));
+ fold_build1 (NEGATE_EXPR, itype, step));
else
- t = fold_build2 (TRUNC_DIV_EXPR, itype, t, fd->loop.step);
+ t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
t = fold_convert (itype, t);
n = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
true, GSI_SAME_STMT);
@@ -5230,11 +6207,11 @@ expand_omp_for_static_chunk (struct omp_region *region, struct omp_for_data *fd)
gsi_insert_before (&si, stmt, GSI_SAME_STMT);
t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size);
- t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
+ t = fold_build2 (MULT_EXPR, itype, t, step);
if (POINTER_TYPE_P (type))
- t = fold_build_pointer_plus (fd->loop.n1, t);
+ t = fold_build_pointer_plus (n1, t);
else
- t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1);
+ t = fold_build2 (PLUS_EXPR, type, t, n1);
v_extra = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
true, GSI_SAME_STMT);
@@ -5261,77 +6238,130 @@ expand_omp_for_static_chunk (struct omp_region *region, struct omp_for_data *fd)
/* Setup code for sequential iteration goes in SEQ_START_BB. */
si = gsi_start_bb (seq_start_bb);
+ tree startvar = fd->loop.v;
+ tree endvar = NULL_TREE;
+
+ if (gimple_omp_for_combined_p (fd->for_stmt))
+ {
+ tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
+ ? gimple_omp_parallel_clauses (inner_stmt)
+ : gimple_omp_for_clauses (inner_stmt);
+ tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
+ gcc_assert (innerc);
+ startvar = OMP_CLAUSE_DECL (innerc);
+ innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
+ OMP_CLAUSE__LOOPTEMP_);
+ gcc_assert (innerc);
+ endvar = OMP_CLAUSE_DECL (innerc);
+ }
+
t = fold_convert (itype, s0);
- t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
+ t = fold_build2 (MULT_EXPR, itype, t, step);
if (POINTER_TYPE_P (type))
- t = fold_build_pointer_plus (fd->loop.n1, t);
+ t = fold_build_pointer_plus (n1, t);
else
- t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1);
+ t = fold_build2 (PLUS_EXPR, type, t, n1);
+ t = fold_convert (TREE_TYPE (startvar), t);
t = force_gimple_operand_gsi (&si, t,
- DECL_P (fd->loop.v)
- && TREE_ADDRESSABLE (fd->loop.v),
+ DECL_P (startvar)
+ && TREE_ADDRESSABLE (startvar),
NULL_TREE, false, GSI_CONTINUE_LINKING);
- stmt = gimple_build_assign (fd->loop.v, t);
+ stmt = gimple_build_assign (startvar, t);
gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
t = fold_convert (itype, e0);
- t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
+ t = fold_build2 (MULT_EXPR, itype, t, step);
if (POINTER_TYPE_P (type))
- t = fold_build_pointer_plus (fd->loop.n1, t);
+ t = fold_build_pointer_plus (n1, t);
else
- t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1);
+ t = fold_build2 (PLUS_EXPR, type, t, n1);
+ t = fold_convert (TREE_TYPE (startvar), t);
e = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
false, GSI_CONTINUE_LINKING);
+ if (endvar)
+ {
+ stmt = gimple_build_assign (endvar, e);
+ gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
+ }
+ if (fd->collapse > 1)
+ expand_omp_for_init_vars (fd, &si, counts, inner_stmt, startvar);
- /* The code controlling the sequential loop goes in CONT_BB,
- replacing the GIMPLE_OMP_CONTINUE. */
- si = gsi_last_bb (cont_bb);
- stmt = gsi_stmt (si);
- gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
- v_main = gimple_omp_continue_control_use (stmt);
- v_back = gimple_omp_continue_control_def (stmt);
+ if (!broken_loop)
+ {
+ /* The code controlling the sequential loop goes in CONT_BB,
+ replacing the GIMPLE_OMP_CONTINUE. */
+ si = gsi_last_bb (cont_bb);
+ stmt = gsi_stmt (si);
+ gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
+ v_main = gimple_omp_continue_control_use (stmt);
+ v_back = gimple_omp_continue_control_def (stmt);
- if (POINTER_TYPE_P (type))
- t = fold_build_pointer_plus (v_main, fd->loop.step);
- else
- t = fold_build2 (PLUS_EXPR, type, v_main, fd->loop.step);
- if (DECL_P (v_back) && TREE_ADDRESSABLE (v_back))
- t = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
- true, GSI_SAME_STMT);
- stmt = gimple_build_assign (v_back, t);
- gsi_insert_before (&si, stmt, GSI_SAME_STMT);
+ if (!gimple_omp_for_combined_p (fd->for_stmt))
+ {
+ if (POINTER_TYPE_P (type))
+ t = fold_build_pointer_plus (v_main, step);
+ else
+ t = fold_build2 (PLUS_EXPR, type, v_main, step);
+ if (DECL_P (v_back) && TREE_ADDRESSABLE (v_back))
+ t = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
+ true, GSI_SAME_STMT);
+ stmt = gimple_build_assign (v_back, t);
+ gsi_insert_before (&si, stmt, GSI_SAME_STMT);
- t = build2 (fd->loop.cond_code, boolean_type_node,
- DECL_P (v_back) && TREE_ADDRESSABLE (v_back)
- ? t : v_back, e);
- gsi_insert_before (&si, gimple_build_cond_empty (t), GSI_SAME_STMT);
+ t = build2 (fd->loop.cond_code, boolean_type_node,
+ DECL_P (v_back) && TREE_ADDRESSABLE (v_back)
+ ? t : v_back, e);
+ gsi_insert_before (&si, gimple_build_cond_empty (t), GSI_SAME_STMT);
+ }
- /* Remove GIMPLE_OMP_CONTINUE. */
- gsi_remove (&si, true);
+ /* Remove GIMPLE_OMP_CONTINUE. */
+ gsi_remove (&si, true);
- /* Trip update code goes into TRIP_UPDATE_BB. */
- si = gsi_start_bb (trip_update_bb);
+ if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
+ collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
- t = build_int_cst (itype, 1);
- t = build2 (PLUS_EXPR, itype, trip_main, t);
- stmt = gimple_build_assign (trip_back, t);
- gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
+ /* Trip update code goes into TRIP_UPDATE_BB. */
+ si = gsi_start_bb (trip_update_bb);
+
+ t = build_int_cst (itype, 1);
+ t = build2 (PLUS_EXPR, itype, trip_main, t);
+ stmt = gimple_build_assign (trip_back, t);
+ gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
+ }
/* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
si = gsi_last_bb (exit_bb);
if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
- force_gimple_operand_gsi (&si, build_omp_barrier (), false, NULL_TREE,
- false, GSI_SAME_STMT);
+ {
+ t = gimple_omp_return_lhs (gsi_stmt (si));
+ gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
+ }
gsi_remove (&si, true);
/* Connect the new blocks. */
find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
- find_edge (cont_bb, body_bb)->flags = EDGE_TRUE_VALUE;
- find_edge (cont_bb, trip_update_bb)->flags = EDGE_FALSE_VALUE;
+ if (!broken_loop)
+ {
+ se = find_edge (cont_bb, body_bb);
+ if (gimple_omp_for_combined_p (fd->for_stmt))
+ {
+ remove_edge (se);
+ se = NULL;
+ }
+ else if (fd->collapse > 1)
+ {
+ remove_edge (se);
+ se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
+ }
+ else
+ se->flags = EDGE_TRUE_VALUE;
+ find_edge (cont_bb, trip_update_bb)->flags
+ = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
- redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
+ redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
+ }
if (gimple_in_ssa_p (cfun))
{
@@ -5342,6 +6372,8 @@ expand_omp_for_static_chunk (struct omp_region *region, struct omp_for_data *fd)
edge_var_map *vm;
size_t i;
+ gcc_assert (fd->collapse == 1 && !broken_loop);
+
/* When we redirect the edge from trip_update_bb to iter_part_bb, we
remove arguments of the phi nodes in fin_bb. We need to create
appropriate phi nodes in iter_part_bb instead. */
@@ -5391,7 +6423,8 @@ expand_omp_for_static_chunk (struct omp_region *region, struct omp_for_data *fd)
UNKNOWN_LOCATION);
}
- set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
+ if (!broken_loop)
+ set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
recompute_dominator (CDI_DOMINATORS, iter_part_bb));
set_immediate_dominator (CDI_DOMINATORS, fin_bb,
@@ -5401,17 +6434,24 @@ expand_omp_for_static_chunk (struct omp_region *region, struct omp_for_data *fd)
set_immediate_dominator (CDI_DOMINATORS, body_bb,
recompute_dominator (CDI_DOMINATORS, body_bb));
- struct loop *trip_loop = alloc_loop ();
- trip_loop->header = iter_part_bb;
- trip_loop->latch = trip_update_bb;
- add_loop (trip_loop, iter_part_bb->loop_father);
+ if (!broken_loop)
+ {
+ struct loop *trip_loop = alloc_loop ();
+ trip_loop->header = iter_part_bb;
+ trip_loop->latch = trip_update_bb;
+ add_loop (trip_loop, iter_part_bb->loop_father);
- struct loop *loop = alloc_loop ();
- loop->header = body_bb;
- loop->latch = cont_bb;
- add_loop (loop, trip_loop);
+ if (!gimple_omp_for_combined_p (fd->for_stmt))
+ {
+ struct loop *loop = alloc_loop ();
+ loop->header = body_bb;
+ loop->latch = cont_bb;
+ add_loop (loop, trip_loop);
+ }
+ }
}
+
/* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
loop. Given parameters:
@@ -5487,7 +6527,7 @@ expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
OMP_CLAUSE_SAFELEN);
tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
OMP_CLAUSE__SIMDUID_);
- tree n2;
+ tree n1, n2;
type = TREE_TYPE (fd->loop.v);
entry_bb = region->entry;
@@ -5530,10 +6570,27 @@ expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
if (l2_dom_bb == NULL)
l2_dom_bb = l1_bb;
+ n1 = fd->loop.n1;
n2 = fd->loop.n2;
- if (0)
- /* Place holder for gimple_omp_for_combined_into_p() in
- the upcoming gomp-4_0-branch merge. */;
+ if (gimple_omp_for_combined_into_p (fd->for_stmt))
+ {
+ tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
+ OMP_CLAUSE__LOOPTEMP_);
+ gcc_assert (innerc);
+ n1 = OMP_CLAUSE_DECL (innerc);
+ innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
+ OMP_CLAUSE__LOOPTEMP_);
+ gcc_assert (innerc);
+ n2 = OMP_CLAUSE_DECL (innerc);
+ expand_omp_build_assign (&gsi, fd->loop.v,
+ fold_convert (type, n1));
+ if (fd->collapse > 1)
+ {
+ gsi_prev (&gsi);
+ expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
+ gsi_next (&gsi);
+ }
+ }
else
{
expand_omp_build_assign (&gsi, fd->loop.v,
@@ -5706,7 +6763,7 @@ expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
/* Expand the OpenMP loop defined by REGION. */
static void
-expand_omp_for (struct omp_region *region)
+expand_omp_for (struct omp_region *region, gimple inner_stmt)
{
struct omp_for_data fd;
struct omp_for_data_loop *loops;
@@ -5736,14 +6793,12 @@ expand_omp_for (struct omp_region *region)
if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_SIMD)
expand_omp_simd (region, &fd);
else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
- && !fd.have_ordered
- && fd.collapse == 1
- && region->cont != NULL)
+ && !fd.have_ordered)
{
if (fd.chunk_size == NULL)
- expand_omp_for_static_nochunk (region, &fd);
+ expand_omp_for_static_nochunk (region, &fd, inner_stmt);
else
- expand_omp_for_static_chunk (region, &fd);
+ expand_omp_for_static_chunk (region, &fd, inner_stmt);
}
else
{
@@ -5768,7 +6823,7 @@ expand_omp_for (struct omp_region *region)
- (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
}
expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
- (enum built_in_function) next_ix);
+ (enum built_in_function) next_ix, inner_stmt);
}
if (gimple_in_ssa_p (cfun))
@@ -5983,9 +7038,13 @@ expand_omp_sections (struct omp_region *region)
si = gsi_last_bb (l2_bb);
if (gimple_omp_return_nowait_p (gsi_stmt (si)))
t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
+ else if (gimple_omp_return_lhs (gsi_stmt (si)))
+ t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
else
t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
stmt = gimple_build_call (t, 0);
+ if (gimple_omp_return_lhs (gsi_stmt (si)))
+ gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
gsi_insert_after (&si, stmt, GSI_SAME_STMT);
gsi_remove (&si, true);
@@ -6001,26 +7060,21 @@ expand_omp_single (struct omp_region *region)
{
basic_block entry_bb, exit_bb;
gimple_stmt_iterator si;
- bool need_barrier = false;
entry_bb = region->entry;
exit_bb = region->exit;
si = gsi_last_bb (entry_bb);
- /* The terminal barrier at the end of a GOMP_single_copy sequence cannot
- be removed. We need to ensure that the thread that entered the single
- does not exit before the data is copied out by the other threads. */
- if (find_omp_clause (gimple_omp_single_clauses (gsi_stmt (si)),
- OMP_CLAUSE_COPYPRIVATE))
- need_barrier = true;
gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
gsi_remove (&si, true);
single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
si = gsi_last_bb (exit_bb);
- if (!gimple_omp_return_nowait_p (gsi_stmt (si)) || need_barrier)
- force_gimple_operand_gsi (&si, build_omp_barrier (), false, NULL_TREE,
- false, GSI_SAME_STMT);
+ if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
+ {
+ tree t = gimple_omp_return_lhs (gsi_stmt (si));
+ gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
+ }
gsi_remove (&si, true);
single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
}
@@ -6042,8 +7096,10 @@ expand_omp_synch (struct omp_region *region)
si = gsi_last_bb (entry_bb);
gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
|| gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
+ || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
|| gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
- || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL);
+ || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
+ || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
gsi_remove (&si, true);
single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
@@ -6088,7 +7144,10 @@ expand_omp_atomic_load (basic_block load_bb, tree addr,
itype = TREE_TYPE (TREE_TYPE (decl));
call = build_call_expr_loc (loc, decl, 2, addr,
- build_int_cst (NULL, MEMMODEL_RELAXED));
+ build_int_cst (NULL,
+ gimple_omp_atomic_seq_cst_p (stmt)
+ ? MEMMODEL_SEQ_CST
+ : MEMMODEL_RELAXED));
if (!useless_type_conversion_p (type, itype))
call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
@@ -6160,7 +7219,10 @@ expand_omp_atomic_store (basic_block load_bb, tree addr,
if (!useless_type_conversion_p (itype, type))
stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
- build_int_cst (NULL, MEMMODEL_RELAXED));
+ build_int_cst (NULL,
+ gimple_omp_atomic_seq_cst_p (stmt)
+ ? MEMMODEL_SEQ_CST
+ : MEMMODEL_RELAXED));
if (exchange)
{
if (!useless_type_conversion_p (type, itype))
@@ -6201,6 +7263,7 @@ expand_omp_atomic_fetch_op (basic_block load_bb,
enum tree_code code;
bool need_old, need_new;
enum machine_mode imode;
+ bool seq_cst;
/* We expect to find the following sequences:
@@ -6226,6 +7289,7 @@ expand_omp_atomic_fetch_op (basic_block load_bb,
return false;
need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
+ seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
gcc_checking_assert (!need_old || !need_new);
if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
@@ -6292,7 +7356,9 @@ expand_omp_atomic_fetch_op (basic_block load_bb,
use the RELAXED memory model. */
call = build_call_expr_loc (loc, decl, 3, addr,
fold_convert_loc (loc, itype, rhs),
- build_int_cst (NULL, MEMMODEL_RELAXED));
+ build_int_cst (NULL,
+ seq_cst ? MEMMODEL_SEQ_CST
+ : MEMMODEL_RELAXED));
if (need_old || need_new)
{
@@ -6622,6 +7688,321 @@ expand_omp_atomic (struct omp_region *region)
}
+/* Expand the OpenMP target{, data, update} directive starting at REGION. */
+
+static void
+expand_omp_target (struct omp_region *region)
+{
+ basic_block entry_bb, exit_bb, new_bb;
+ struct function *child_cfun = NULL;
+ tree child_fn = NULL_TREE, block, t;
+ gimple_stmt_iterator gsi;
+ gimple entry_stmt, stmt;
+ edge e;
+
+ entry_stmt = last_stmt (region->entry);
+ new_bb = region->entry;
+ int kind = gimple_omp_target_kind (entry_stmt);
+ if (kind == GF_OMP_TARGET_KIND_REGION)
+ {
+ child_fn = gimple_omp_target_child_fn (entry_stmt);
+ child_cfun = DECL_STRUCT_FUNCTION (child_fn);
+ }
+
+ entry_bb = region->entry;
+ exit_bb = region->exit;
+
+ if (kind == GF_OMP_TARGET_KIND_REGION)
+ {
+ unsigned srcidx, dstidx, num;
+
+ /* If the target region needs data sent from the parent
+ function, then the very first statement (except possible
+ tree profile counter updates) of the parallel body
+ is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
+ &.OMP_DATA_O is passed as an argument to the child function,
+ we need to replace it with the argument as seen by the child
+ function.
+
+ In most cases, this will end up being the identity assignment
+ .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
+ a function call that has been inlined, the original PARM_DECL
+ .OMP_DATA_I may have been converted into a different local
+ variable. In which case, we need to keep the assignment. */
+ if (gimple_omp_target_data_arg (entry_stmt))
+ {
+ basic_block entry_succ_bb = single_succ (entry_bb);
+ gimple_stmt_iterator gsi;
+ tree arg;
+ gimple tgtcopy_stmt = NULL;
+ tree sender
+ = TREE_VEC_ELT (gimple_omp_target_data_arg (entry_stmt), 0);
+
+ for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
+ {
+ gcc_assert (!gsi_end_p (gsi));
+ stmt = gsi_stmt (gsi);
+ if (gimple_code (stmt) != GIMPLE_ASSIGN)
+ continue;
+
+ if (gimple_num_ops (stmt) == 2)
+ {
+ tree arg = gimple_assign_rhs1 (stmt);
+
+ /* We're ignoring the subcode because we're
+ effectively doing a STRIP_NOPS. */
+
+ if (TREE_CODE (arg) == ADDR_EXPR
+ && TREE_OPERAND (arg, 0) == sender)
+ {
+ tgtcopy_stmt = stmt;
+ break;
+ }
+ }
+ }
+
+ gcc_assert (tgtcopy_stmt != NULL);
+ arg = DECL_ARGUMENTS (child_fn);
+
+ gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
+ gsi_remove (&gsi, true);
+ }
+
+ /* Declare local variables needed in CHILD_CFUN. */
+ block = DECL_INITIAL (child_fn);
+ BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
+ /* The gimplifier could record temporaries in target block
+ rather than in containing function's local_decls chain,
+ which would mean cgraph missed finalizing them. Do it now. */
+ for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
+ if (TREE_CODE (t) == VAR_DECL
+ && TREE_STATIC (t)
+ && !DECL_EXTERNAL (t))
+ varpool_finalize_decl (t);
+ DECL_SAVED_TREE (child_fn) = NULL;
+ /* We'll create a CFG for child_fn, so no gimple body is needed. */
+ gimple_set_body (child_fn, NULL);
+ TREE_USED (block) = 1;
+
+ /* Reset DECL_CONTEXT on function arguments. */
+ for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
+ DECL_CONTEXT (t) = child_fn;
+
+ /* Split ENTRY_BB at GIMPLE_OMP_TARGET,
+ so that it can be moved to the child function. */
+ gsi = gsi_last_bb (entry_bb);
+ stmt = gsi_stmt (gsi);
+ gcc_assert (stmt && gimple_code (stmt) == GIMPLE_OMP_TARGET
+ && gimple_omp_target_kind (stmt)
+ == GF_OMP_TARGET_KIND_REGION);
+ gsi_remove (&gsi, true);
+ e = split_block (entry_bb, stmt);
+ entry_bb = e->dest;
+ single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
+
+ /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
+ if (exit_bb)
+ {
+ gsi = gsi_last_bb (exit_bb);
+ gcc_assert (!gsi_end_p (gsi)
+ && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
+ stmt = gimple_build_return (NULL);
+ gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
+ gsi_remove (&gsi, true);
+ }
+
+ /* Move the target region into CHILD_CFUN. */
+
+ block = gimple_block (entry_stmt);
+
+ new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
+ if (exit_bb)
+ single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
+ /* When the OMP expansion process cannot guarantee an up-to-date
+ loop tree arrange for the child function to fixup loops. */
+ if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
+ child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
+
+ /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
+ num = vec_safe_length (child_cfun->local_decls);
+ for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
+ {
+ t = (*child_cfun->local_decls)[srcidx];
+ if (DECL_CONTEXT (t) == cfun->decl)
+ continue;
+ if (srcidx != dstidx)
+ (*child_cfun->local_decls)[dstidx] = t;
+ dstidx++;
+ }
+ if (dstidx != num)
+ vec_safe_truncate (child_cfun->local_decls, dstidx);
+
+ /* Inform the callgraph about the new function. */
+ DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
+ cgraph_add_new_function (child_fn, true);
+
+ /* Fix the callgraph edges for child_cfun. Those for cfun will be
+ fixed in a following pass. */
+ push_cfun (child_cfun);
+ rebuild_cgraph_edges ();
+
+ /* Some EH regions might become dead, see PR34608. If
+ pass_cleanup_cfg isn't the first pass to happen with the
+ new child, these dead EH edges might cause problems.
+ Clean them up now. */
+ if (flag_exceptions)
+ {
+ basic_block bb;
+ bool changed = false;
+
+ FOR_EACH_BB (bb)
+ changed |= gimple_purge_dead_eh_edges (bb);
+ if (changed)
+ cleanup_tree_cfg ();
+ }
+ pop_cfun ();
+ }
+
+ /* Emit a library call to launch the target region, or do data
+ transfers. */
+ tree t1, t2, t3, t4, device, cond, c, clauses;
+ enum built_in_function start_ix;
+ location_t clause_loc;
+
+ clauses = gimple_omp_target_clauses (entry_stmt);
+
+ if (kind == GF_OMP_TARGET_KIND_REGION)
+ start_ix = BUILT_IN_GOMP_TARGET;
+ else if (kind == GF_OMP_TARGET_KIND_DATA)
+ start_ix = BUILT_IN_GOMP_TARGET_DATA;
+ else
+ start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
+
+ /* By default, the value of DEVICE is -1 (let runtime library choose)
+ and there is no conditional. */
+ cond = NULL_TREE;
+ device = build_int_cst (integer_type_node, -1);
+
+ c = find_omp_clause (clauses, OMP_CLAUSE_IF);
+ if (c)
+ cond = OMP_CLAUSE_IF_EXPR (c);
+
+ c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
+ if (c)
+ {
+ device = OMP_CLAUSE_DEVICE_ID (c);
+ clause_loc = OMP_CLAUSE_LOCATION (c);
+ }
+ else
+ clause_loc = gimple_location (entry_stmt);
+
+ /* Ensure 'device' is of the correct type. */
+ device = fold_convert_loc (clause_loc, integer_type_node, device);
+
+ /* If we found the clause 'if (cond)', build
+ (cond ? device : -2). */
+ if (cond)
+ {
+ cond = gimple_boolify (cond);
+
+ basic_block cond_bb, then_bb, else_bb;
+ edge e;
+ tree tmp_var;
+
+ tmp_var = create_tmp_var (TREE_TYPE (device), NULL);
+ if (kind != GF_OMP_TARGET_KIND_REGION)
+ {
+ gsi = gsi_last_bb (new_bb);
+ gsi_prev (&gsi);
+ e = split_block (new_bb, gsi_stmt (gsi));
+ }
+ else
+ e = split_block (new_bb, NULL);
+ cond_bb = e->src;
+ new_bb = e->dest;
+ remove_edge (e);
+
+ then_bb = create_empty_bb (cond_bb);
+ else_bb = create_empty_bb (then_bb);
+ set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
+ set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
+
+ stmt = gimple_build_cond_empty (cond);
+ gsi = gsi_last_bb (cond_bb);
+ gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
+
+ gsi = gsi_start_bb (then_bb);
+ stmt = gimple_build_assign (tmp_var, device);
+ gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
+
+ gsi = gsi_start_bb (else_bb);
+ stmt = gimple_build_assign (tmp_var,
+ build_int_cst (integer_type_node, -2));
+ gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
+
+ make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
+ make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
+ if (current_loops)
+ {
+ add_bb_to_loop (then_bb, cond_bb->loop_father);
+ add_bb_to_loop (else_bb, cond_bb->loop_father);
+ }
+ make_edge (then_bb, new_bb, EDGE_FALLTHRU);
+ make_edge (else_bb, new_bb, EDGE_FALLTHRU);
+
+ device = tmp_var;
+ }
+
+ gsi = gsi_last_bb (new_bb);
+ t = gimple_omp_target_data_arg (entry_stmt);
+ if (t == NULL)
+ {
+ t1 = size_zero_node;
+ t2 = build_zero_cst (ptr_type_node);
+ t3 = t2;
+ t4 = t2;
+ }
+ else
+ {
+ t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
+ t1 = size_binop (PLUS_EXPR, t1, size_int (1));
+ t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
+ t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
+ t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
+ }
+
+ gimple g;
+ /* FIXME: This will be address of
+ extern char __OPENMP_TARGET__[] __attribute__((visibility ("hidden")))
+ symbol, as soon as the linker plugin is able to create it for us. */
+ tree openmp_target = build_zero_cst (ptr_type_node);
+ if (kind == GF_OMP_TARGET_KIND_REGION)
+ {
+ tree fnaddr = build_fold_addr_expr (child_fn);
+ g = gimple_build_call (builtin_decl_explicit (start_ix), 7,
+ device, fnaddr, openmp_target, t1, t2, t3, t4);
+ }
+ else
+ g = gimple_build_call (builtin_decl_explicit (start_ix), 6,
+ device, openmp_target, t1, t2, t3, t4);
+ gimple_set_location (g, gimple_location (entry_stmt));
+ gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+ if (kind != GF_OMP_TARGET_KIND_REGION)
+ {
+ g = gsi_stmt (gsi);
+ gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
+ gsi_remove (&gsi, true);
+ }
+ if (kind == GF_OMP_TARGET_KIND_DATA && region->exit)
+ {
+ gsi = gsi_last_bb (region->exit);
+ g = gsi_stmt (gsi);
+ gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
+ gsi_remove (&gsi, true);
+ }
+}
+
+
/* Expand the parallel region tree rooted at REGION. Expansion
proceeds in depth-first order. Innermost regions are expanded
first. This way, parallel regions that require a new function to
@@ -6634,12 +8015,17 @@ expand_omp (struct omp_region *region)
while (region)
{
location_t saved_location;
+ gimple inner_stmt = NULL;
/* First, determine whether this is a combined parallel+workshare
region. */
if (region->type == GIMPLE_OMP_PARALLEL)
determine_parallel_type (region);
+ if (region->type == GIMPLE_OMP_FOR
+ && gimple_omp_for_combined_p (last_stmt (region->entry)))
+ inner_stmt = last_stmt (region->inner->entry);
+
if (region->inner)
expand_omp (region->inner);
@@ -6655,7 +8041,7 @@ expand_omp (struct omp_region *region)
break;
case GIMPLE_OMP_FOR:
- expand_omp_for (region);
+ expand_omp_for (region, inner_stmt);
break;
case GIMPLE_OMP_SECTIONS:
@@ -6672,8 +8058,10 @@ expand_omp (struct omp_region *region)
break;
case GIMPLE_OMP_MASTER:
+ case GIMPLE_OMP_TASKGROUP:
case GIMPLE_OMP_ORDERED:
case GIMPLE_OMP_CRITICAL:
+ case GIMPLE_OMP_TEAMS:
expand_omp_synch (region);
break;
@@ -6681,6 +8069,10 @@ expand_omp (struct omp_region *region)
expand_omp_atomic (region);
break;
+ case GIMPLE_OMP_TARGET:
+ expand_omp_target (region);
+ break;
+
default:
gcc_unreachable ();
}
@@ -6745,6 +8137,9 @@ build_omp_regions_1 (basic_block bb, struct omp_region *parent,
GIMPLE_OMP_SECTIONS, and we do nothing for it. */
;
}
+ else if (code == GIMPLE_OMP_TARGET
+ && gimple_omp_target_kind (stmt) == GF_OMP_TARGET_KIND_UPDATE)
+ new_omp_region (bb, code, parent);
else
{
/* Otherwise, this directive becomes the parent for a new
@@ -6837,7 +8232,7 @@ execute_expand_omp (void)
static bool
gate_expand_omp (void)
{
- return (flag_openmp != 0 && !seen_error ());
+ return ((flag_openmp != 0 || flag_openmp_simd != 0) && !seen_error ());
}
namespace {
@@ -6860,8 +8255,8 @@ const pass_data pass_data_expand_omp =
class pass_expand_omp : public gimple_opt_pass
{
public:
- pass_expand_omp(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_expand_omp, ctxt)
+ pass_expand_omp (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_expand_omp, ctxt)
{}
/* opt_pass methods: */
@@ -6880,6 +8275,32 @@ make_pass_expand_omp (gcc::context *ctxt)
/* Routines to lower OpenMP directives into OMP-GIMPLE. */
+/* If ctx is a worksharing context inside of a cancellable parallel
+ region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
+ and conditional branch to parallel's cancel_label to handle
+ cancellation in the implicit barrier. */
+
+static void
+maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
+{
+ gimple omp_return = gimple_seq_last_stmt (*body);
+ gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
+ if (gimple_omp_return_nowait_p (omp_return))
+ return;
+ if (ctx->outer
+ && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
+ && ctx->outer->cancellable)
+ {
+ tree lhs = create_tmp_var (boolean_type_node, NULL);
+ gimple_omp_return_set_lhs (omp_return, lhs);
+ tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
+ gimple g = gimple_build_cond (NE_EXPR, lhs, boolean_false_node,
+ ctx->outer->cancel_label, fallthru_label);
+ gimple_seq_add_stmt (body, g);
+ gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
+ }
+}
+
/* Lower the OpenMP sections directive in the current statement in GSI_P.
CTX is the enclosing OMP context for the current statement. */
@@ -6899,7 +8320,7 @@ lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
dlist = NULL;
ilist = NULL;
lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
- &ilist, &dlist, ctx);
+ &ilist, &dlist, ctx, NULL);
new_body = gimple_omp_body (stmt);
gimple_omp_set_body (stmt, NULL);
@@ -6959,6 +8380,8 @@ lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
gimple_seq_add_stmt (&new_body, t);
gimple_seq_add_seq (&new_body, olist);
+ if (ctx->cancellable)
+ gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
gimple_seq_add_seq (&new_body, dlist);
new_body = maybe_catch_exception (new_body);
@@ -6967,6 +8390,7 @@ lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
(!!find_omp_clause (gimple_omp_sections_clauses (stmt),
OMP_CLAUSE_NOWAIT));
gimple_seq_add_stmt (&new_body, t);
+ maybe_add_implicit_barrier_cancel (ctx, &new_body);
gimple_bind_set_body (new_stmt, new_body);
}
@@ -7096,7 +8520,7 @@ lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
{
tree block;
gimple t, bind, single_stmt = gsi_stmt (*gsi_p);
- gimple_seq bind_body, dlist;
+ gimple_seq bind_body, bind_body_tail = NULL, dlist;
struct gimplify_ctx gctx;
push_gimplify_context (&gctx);
@@ -7107,7 +8531,7 @@ lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
bind_body = NULL;
dlist = NULL;
lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
- &bind_body, &dlist, ctx);
+ &bind_body, &dlist, ctx, NULL);
lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
gimple_seq_add_stmt (&bind_body, single_stmt);
@@ -7126,7 +8550,17 @@ lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
t = gimple_build_omp_return
(!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
OMP_CLAUSE_NOWAIT));
- gimple_seq_add_stmt (&bind_body, t);
+ gimple_seq_add_stmt (&bind_body_tail, t);
+ maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
+ if (ctx->record_type)
+ {
+ gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
+ tree clobber = build_constructor (ctx->record_type, NULL);
+ TREE_THIS_VOLATILE (clobber) = 1;
+ gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
+ clobber), GSI_SAME_STMT);
+ }
+ gimple_seq_add_seq (&bind_body, bind_body_tail);
gimple_bind_set_body (bind, bind_body);
pop_gimplify_context (bind);
@@ -7180,6 +8614,33 @@ lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
}
+/* Expand code for an OpenMP taskgroup directive. */
+
+static void
+lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
+{
+ gimple stmt = gsi_stmt (*gsi_p), bind, x;
+ tree block = make_node (BLOCK);
+
+ bind = gimple_build_bind (NULL, NULL, block);
+ gsi_replace (gsi_p, bind, true);
+ gimple_bind_add_stmt (bind, stmt);
+
+ x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
+ 0);
+ gimple_bind_add_stmt (bind, x);
+
+ lower_omp (gimple_omp_body_ptr (stmt), ctx);
+ gimple_bind_add_seq (bind, gimple_omp_body (stmt));
+ gimple_omp_set_body (stmt, NULL);
+
+ gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
+
+ gimple_bind_append_vars (bind, ctx->block_vars);
+ BLOCK_VARS (block) = ctx->block_vars;
+}
+
+
/* Expand code for an OpenMP ordered directive. */
static void
@@ -7372,7 +8833,7 @@ static void
lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
{
tree *rhs_p, block;
- struct omp_for_data fd;
+ struct omp_for_data fd, *fdp = NULL;
gimple stmt = gsi_stmt (*gsi_p), new_stmt;
gimple_seq omp_for_body, body, dlist;
size_t i;
@@ -7399,10 +8860,50 @@ lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
gimple_bind_append_vars (new_stmt, vars);
}
+ if (gimple_omp_for_combined_into_p (stmt))
+ {
+ extract_omp_for_data (stmt, &fd, NULL);
+ fdp = &fd;
+
+ /* We need two temporaries with fd.loop.v type (istart/iend)
+ and then (fd.collapse - 1) temporaries with the same
+ type for count2 ... countN-1 vars if not constant. */
+ size_t count = 2;
+ tree type = fd.iter_type;
+ if (fd.collapse > 1
+ && TREE_CODE (fd.loop.n2) != INTEGER_CST)
+ count += fd.collapse - 1;
+ bool parallel_for = gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR;
+ tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
+ tree clauses = *pc;
+ if (parallel_for)
+ outerc
+ = find_omp_clause (gimple_omp_parallel_clauses (ctx->outer->stmt),
+ OMP_CLAUSE__LOOPTEMP_);
+ for (i = 0; i < count; i++)
+ {
+ tree temp;
+ if (parallel_for)
+ {
+ gcc_assert (outerc);
+ temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
+ outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
+ OMP_CLAUSE__LOOPTEMP_);
+ }
+ else
+ temp = create_tmp_var (type, NULL);
+ *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
+ OMP_CLAUSE_DECL (*pc) = temp;
+ pc = &OMP_CLAUSE_CHAIN (*pc);
+ }
+ *pc = clauses;
+ }
+
/* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
dlist = NULL;
body = NULL;
- lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx);
+ lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
+ fdp);
gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
lower_omp (gimple_omp_body_ptr (stmt), ctx);
@@ -7442,13 +8943,17 @@ lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
/* After the loop, add exit clauses. */
lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
+
+ if (ctx->cancellable)
+ gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
+
gimple_seq_add_seq (&body, dlist);
body = maybe_catch_exception (body);
/* Region exit marker goes at the end of the loop body. */
gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
-
+ maybe_add_implicit_barrier_cancel (ctx, &body);
pop_gimplify_context (new_stmt);
gimple_bind_append_vars (new_stmt, ctx->block_vars);
@@ -7769,6 +9274,68 @@ create_task_copyfn (gimple task_stmt, omp_context *ctx)
pop_cfun ();
}
+static void
+lower_depend_clauses (gimple stmt, gimple_seq *iseq, gimple_seq *oseq)
+{
+ tree c, clauses;
+ gimple g;
+ size_t n_in = 0, n_out = 0, idx = 2, i;
+
+ clauses = find_omp_clause (gimple_omp_task_clauses (stmt),
+ OMP_CLAUSE_DEPEND);
+ gcc_assert (clauses);
+ for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
+ switch (OMP_CLAUSE_DEPEND_KIND (c))
+ {
+ case OMP_CLAUSE_DEPEND_IN:
+ n_in++;
+ break;
+ case OMP_CLAUSE_DEPEND_OUT:
+ case OMP_CLAUSE_DEPEND_INOUT:
+ n_out++;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
+ tree array = create_tmp_var (type, NULL);
+ tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
+ NULL_TREE);
+ g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
+ gimple_seq_add_stmt (iseq, g);
+ r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
+ NULL_TREE);
+ g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
+ gimple_seq_add_stmt (iseq, g);
+ for (i = 0; i < 2; i++)
+ {
+ if ((i ? n_in : n_out) == 0)
+ continue;
+ for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
+ && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
+ {
+ tree t = OMP_CLAUSE_DECL (c);
+ t = fold_convert (ptr_type_node, t);
+ gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
+ r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
+ NULL_TREE, NULL_TREE);
+ g = gimple_build_assign (r, t);
+ gimple_seq_add_stmt (iseq, g);
+ }
+ }
+ tree *p = gimple_omp_task_clauses_ptr (stmt);
+ c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
+ OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
+ OMP_CLAUSE_CHAIN (c) = *p;
+ *p = c;
+ tree clobber = build_constructor (type, NULL);
+ TREE_THIS_VOLATILE (clobber) = 1;
+ g = gimple_build_assign (array, clobber);
+ gimple_seq_add_stmt (oseq, g);
+}
+
/* Lower the OpenMP parallel or task directive in the current statement
in GSI_P. CTX holds context information for the directive. */
@@ -7778,9 +9345,9 @@ lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
tree clauses;
tree child_fn, t;
gimple stmt = gsi_stmt (*gsi_p);
- gimple par_bind, bind;
- gimple_seq par_body, olist, ilist, par_olist, par_ilist, new_body;
- struct gimplify_ctx gctx;
+ gimple par_bind, bind, dep_bind = NULL;
+ gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
+ struct gimplify_ctx gctx, dep_gctx;
location_t loc = gimple_location (stmt);
clauses = gimple_omp_taskreg_clauses (stmt);
@@ -7800,6 +9367,16 @@ lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
if (ws_num == 1)
gimple_omp_parallel_set_combined_p (stmt, true);
}
+ gimple_seq dep_ilist = NULL;
+ gimple_seq dep_olist = NULL;
+ if (gimple_code (stmt) == GIMPLE_OMP_TASK
+ && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
+ {
+ push_gimplify_context (&dep_gctx);
+ dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
+ lower_depend_clauses (stmt, &dep_ilist, &dep_olist);
+ }
+
if (ctx->srecord_type)
create_task_copyfn (stmt, ctx);
@@ -7807,10 +9384,11 @@ lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
par_olist = NULL;
par_ilist = NULL;
- lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx);
+ par_rlist = NULL;
+ lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
lower_omp (&par_body, ctx);
if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
- lower_reduction_clauses (clauses, &par_olist, ctx);
+ lower_reduction_clauses (clauses, &par_rlist, ctx);
/* Declare all the variables created by mapping and the variables
declared in the scope of the parallel body. */
@@ -7832,6 +9410,14 @@ lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
lower_send_clauses (clauses, &ilist, &olist, ctx);
lower_send_shared_vars (&ilist, &olist, ctx);
+ if (ctx->record_type)
+ {
+ tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
+ TREE_THIS_VOLATILE (clobber) = 1;
+ gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
+ clobber));
+ }
+
/* Once all the expansions are done, sequence all the different
fragments inside gimple_omp_body. */
@@ -7848,12 +9434,329 @@ lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
gimple_seq_add_seq (&new_body, par_ilist);
gimple_seq_add_seq (&new_body, par_body);
+ gimple_seq_add_seq (&new_body, par_rlist);
+ if (ctx->cancellable)
+ gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
gimple_seq_add_seq (&new_body, par_olist);
new_body = maybe_catch_exception (new_body);
gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
gimple_omp_set_body (stmt, new_body);
bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
+ gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
+ gimple_bind_add_seq (bind, ilist);
+ gimple_bind_add_stmt (bind, stmt);
+ gimple_bind_add_seq (bind, olist);
+
+ pop_gimplify_context (NULL);
+
+ if (dep_bind)
+ {
+ gimple_bind_add_seq (dep_bind, dep_ilist);
+ gimple_bind_add_stmt (dep_bind, bind);
+ gimple_bind_add_seq (dep_bind, dep_olist);
+ pop_gimplify_context (dep_bind);
+ }
+}
+
+/* Lower the OpenMP target directive in the current statement
+ in GSI_P. CTX holds context information for the directive. */
+
+static void
+lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
+{
+ tree clauses;
+ tree child_fn, t, c;
+ gimple stmt = gsi_stmt (*gsi_p);
+ gimple tgt_bind = NULL, bind;
+ gimple_seq tgt_body = NULL, olist, ilist, new_body;
+ struct gimplify_ctx gctx;
+ location_t loc = gimple_location (stmt);
+ int kind = gimple_omp_target_kind (stmt);
+ unsigned int map_cnt = 0;
+
+ clauses = gimple_omp_target_clauses (stmt);
+ if (kind == GF_OMP_TARGET_KIND_REGION)
+ {
+ tgt_bind = gimple_seq_first_stmt (gimple_omp_body (stmt));
+ tgt_body = gimple_bind_body (tgt_bind);
+ }
+ else if (kind == GF_OMP_TARGET_KIND_DATA)
+ tgt_body = gimple_omp_body (stmt);
+ child_fn = ctx->cb.dst_fn;
+
+ push_gimplify_context (&gctx);
+
+ for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
+ switch (OMP_CLAUSE_CODE (c))
+ {
+ tree var, x;
+
+ default:
+ break;
+ case OMP_CLAUSE_MAP:
+ case OMP_CLAUSE_TO:
+ case OMP_CLAUSE_FROM:
+ var = OMP_CLAUSE_DECL (c);
+ if (!DECL_P (var))
+ {
+ if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
+ || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
+ map_cnt++;
+ continue;
+ }
+
+ if (DECL_SIZE (var)
+ && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
+ {
+ tree var2 = DECL_VALUE_EXPR (var);
+ gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
+ var2 = TREE_OPERAND (var2, 0);
+ gcc_assert (DECL_P (var2));
+ var = var2;
+ }
+
+ if (!maybe_lookup_field (var, ctx))
+ continue;
+
+ if (kind == GF_OMP_TARGET_KIND_REGION)
+ {
+ x = build_receiver_ref (var, true, ctx);
+ tree new_var = lookup_decl (var, ctx);
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
+ && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
+ && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
+ && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
+ x = build_simple_mem_ref (x);
+ SET_DECL_VALUE_EXPR (new_var, x);
+ DECL_HAS_VALUE_EXPR_P (new_var) = 1;
+ }
+ map_cnt++;
+ }
+
+ if (kind == GF_OMP_TARGET_KIND_REGION)
+ {
+ target_nesting_level++;
+ lower_omp (&tgt_body, ctx);
+ target_nesting_level--;
+ }
+ else if (kind == GF_OMP_TARGET_KIND_DATA)
+ lower_omp (&tgt_body, ctx);
+
+ if (kind == GF_OMP_TARGET_KIND_REGION)
+ {
+ /* Declare all the variables created by mapping and the variables
+ declared in the scope of the target body. */
+ record_vars_into (ctx->block_vars, child_fn);
+ record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
+ }
+
+ olist = NULL;
+ ilist = NULL;
+ if (ctx->record_type)
+ {
+ ctx->sender_decl
+ = create_tmp_var (ctx->record_type, ".omp_data_arr");
+ DECL_NAMELESS (ctx->sender_decl) = 1;
+ TREE_ADDRESSABLE (ctx->sender_decl) = 1;
+ t = make_tree_vec (3);
+ TREE_VEC_ELT (t, 0) = ctx->sender_decl;
+ TREE_VEC_ELT (t, 1)
+ = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
+ ".omp_data_sizes");
+ DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
+ TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
+ TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
+ TREE_VEC_ELT (t, 2)
+ = create_tmp_var (build_array_type_nelts (unsigned_char_type_node,
+ map_cnt),
+ ".omp_data_kinds");
+ DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
+ TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
+ TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
+ gimple_omp_target_set_data_arg (stmt, t);
+
+ vec<constructor_elt, va_gc> *vsize;
+ vec<constructor_elt, va_gc> *vkind;
+ vec_alloc (vsize, map_cnt);
+ vec_alloc (vkind, map_cnt);
+ unsigned int map_idx = 0;
+
+ for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
+ switch (OMP_CLAUSE_CODE (c))
+ {
+ tree ovar, nc;
+
+ default:
+ break;
+ case OMP_CLAUSE_MAP:
+ case OMP_CLAUSE_TO:
+ case OMP_CLAUSE_FROM:
+ nc = c;
+ ovar = OMP_CLAUSE_DECL (c);
+ if (!DECL_P (ovar))
+ {
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
+ && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
+ {
+ gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
+ == get_base_address (ovar));
+ nc = OMP_CLAUSE_CHAIN (c);
+ ovar = OMP_CLAUSE_DECL (nc);
+ }
+ else
+ {
+ tree x = build_sender_ref (ovar, ctx);
+ tree v
+ = build_fold_addr_expr_with_type (ovar, ptr_type_node);
+ gimplify_assign (x, v, &ilist);
+ nc = NULL_TREE;
+ }
+ }
+ else
+ {
+ if (DECL_SIZE (ovar)
+ && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
+ {
+ tree ovar2 = DECL_VALUE_EXPR (ovar);
+ gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
+ ovar2 = TREE_OPERAND (ovar2, 0);
+ gcc_assert (DECL_P (ovar2));
+ ovar = ovar2;
+ }
+ if (!maybe_lookup_field (ovar, ctx))
+ continue;
+ }
+
+ if (nc)
+ {
+ tree var = lookup_decl_in_outer_ctx (ovar, ctx);
+ tree x = build_sender_ref (ovar, ctx);
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
+ && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
+ && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
+ && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
+ {
+ gcc_assert (kind == GF_OMP_TARGET_KIND_REGION);
+ tree avar
+ = create_tmp_var (TREE_TYPE (TREE_TYPE (x)), NULL);
+ mark_addressable (avar);
+ gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
+ avar = build_fold_addr_expr (avar);
+ gimplify_assign (x, avar, &ilist);
+ }
+ else if (is_gimple_reg (var))
+ {
+ gcc_assert (kind == GF_OMP_TARGET_KIND_REGION);
+ tree avar = create_tmp_var (TREE_TYPE (var), NULL);
+ mark_addressable (avar);
+ if (OMP_CLAUSE_MAP_KIND (c) != OMP_CLAUSE_MAP_ALLOC
+ && OMP_CLAUSE_MAP_KIND (c) != OMP_CLAUSE_MAP_FROM)
+ gimplify_assign (avar, var, &ilist);
+ avar = build_fold_addr_expr (avar);
+ gimplify_assign (x, avar, &ilist);
+ if ((OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_FROM
+ || OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_TOFROM)
+ && !TYPE_READONLY (TREE_TYPE (var)))
+ {
+ x = build_sender_ref (ovar, ctx);
+ x = build_simple_mem_ref (x);
+ gimplify_assign (var, x, &olist);
+ }
+ }
+ else
+ {
+ var = build_fold_addr_expr (var);
+ gimplify_assign (x, var, &ilist);
+ }
+ }
+ tree s = OMP_CLAUSE_SIZE (c);
+ if (s == NULL_TREE)
+ s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
+ s = fold_convert (size_type_node, s);
+ tree purpose = size_int (map_idx++);
+ CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
+ if (TREE_CODE (s) != INTEGER_CST)
+ TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
+
+ unsigned char tkind = 0;
+ switch (OMP_CLAUSE_CODE (c))
+ {
+ case OMP_CLAUSE_MAP:
+ tkind = OMP_CLAUSE_MAP_KIND (c);
+ break;
+ case OMP_CLAUSE_TO:
+ tkind = OMP_CLAUSE_MAP_TO;
+ break;
+ case OMP_CLAUSE_FROM:
+ tkind = OMP_CLAUSE_MAP_FROM;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ unsigned int talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
+ if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
+ talign = DECL_ALIGN_UNIT (ovar);
+ talign = ceil_log2 (talign);
+ tkind |= talign << 3;
+ CONSTRUCTOR_APPEND_ELT (vkind, purpose,
+ build_int_cst (unsigned_char_type_node,
+ tkind));
+ if (nc && nc != c)
+ c = nc;
+ }
+
+ gcc_assert (map_idx == map_cnt);
+
+ DECL_INITIAL (TREE_VEC_ELT (t, 1))
+ = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
+ DECL_INITIAL (TREE_VEC_ELT (t, 2))
+ = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
+ if (!TREE_STATIC (TREE_VEC_ELT (t, 1)))
+ {
+ gimple_seq initlist = NULL;
+ force_gimple_operand (build1 (DECL_EXPR, void_type_node,
+ TREE_VEC_ELT (t, 1)),
+ &initlist, true, NULL_TREE);
+ gimple_seq_add_seq (&ilist, initlist);
+ }
+
+ tree clobber = build_constructor (ctx->record_type, NULL);
+ TREE_THIS_VOLATILE (clobber) = 1;
+ gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
+ clobber));
+ }
+
+ /* Once all the expansions are done, sequence all the different
+ fragments inside gimple_omp_body. */
+
+ new_body = NULL;
+
+ if (ctx->record_type && kind == GF_OMP_TARGET_KIND_REGION)
+ {
+ t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
+ /* fixup_child_record_type might have changed receiver_decl's type. */
+ t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
+ gimple_seq_add_stmt (&new_body,
+ gimple_build_assign (ctx->receiver_decl, t));
+ }
+
+ if (kind == GF_OMP_TARGET_KIND_REGION)
+ {
+ gimple_seq_add_seq (&new_body, tgt_body);
+ new_body = maybe_catch_exception (new_body);
+ }
+ else if (kind == GF_OMP_TARGET_KIND_DATA)
+ new_body = tgt_body;
+ if (kind != GF_OMP_TARGET_KIND_UPDATE)
+ {
+ gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
+ gimple_omp_set_body (stmt, new_body);
+ }
+
+ bind = gimple_build_bind (NULL, NULL,
+ tgt_bind ? gimple_bind_block (tgt_bind)
+ : NULL_TREE);
gsi_replace (gsi_p, bind, true);
gimple_bind_add_seq (bind, ilist);
gimple_bind_add_stmt (bind, stmt);
@@ -7862,6 +9765,72 @@ lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
pop_gimplify_context (NULL);
}
+/* Expand code for an OpenMP teams directive. */
+
+static void
+lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
+{
+ gimple teams_stmt = gsi_stmt (*gsi_p);
+ struct gimplify_ctx gctx;
+ push_gimplify_context (&gctx);
+
+ tree block = make_node (BLOCK);
+ gimple bind = gimple_build_bind (NULL, NULL, block);
+ gsi_replace (gsi_p, bind, true);
+ gimple_seq bind_body = NULL;
+ gimple_seq dlist = NULL;
+ gimple_seq olist = NULL;
+
+ tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
+ OMP_CLAUSE_NUM_TEAMS);
+ if (num_teams == NULL_TREE)
+ num_teams = build_int_cst (unsigned_type_node, 0);
+ else
+ {
+ num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
+ num_teams = fold_convert (unsigned_type_node, num_teams);
+ gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
+ }
+ tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
+ OMP_CLAUSE_THREAD_LIMIT);
+ if (thread_limit == NULL_TREE)
+ thread_limit = build_int_cst (unsigned_type_node, 0);
+ else
+ {
+ thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
+ thread_limit = fold_convert (unsigned_type_node, thread_limit);
+ gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
+ fb_rvalue);
+ }
+
+ lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
+ &bind_body, &dlist, ctx, NULL);
+ lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
+ lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
+ gimple_seq_add_stmt (&bind_body, teams_stmt);
+
+ location_t loc = gimple_location (teams_stmt);
+ tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
+ gimple call = gimple_build_call (decl, 2, num_teams, thread_limit);
+ gimple_set_location (call, loc);
+ gimple_seq_add_stmt (&bind_body, call);
+
+ gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
+ gimple_omp_set_body (teams_stmt, NULL);
+ gimple_seq_add_seq (&bind_body, olist);
+ gimple_seq_add_seq (&bind_body, dlist);
+ gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
+ gimple_bind_set_body (bind, bind_body);
+
+ pop_gimplify_context (bind);
+
+ gimple_bind_append_vars (bind, ctx->block_vars);
+ BLOCK_VARS (block) = ctx->block_vars;
+ if (BLOCK_VARS (block))
+ TREE_USED (block) = 1;
+}
+
+
/* Callback for lower_omp_1. Return non-NULL if *tp needs to be
regimplified. If DATA is non-NULL, lower_omp_1 is outside
of OpenMP context, but with task_shared_vars set. */
@@ -7940,16 +9909,23 @@ lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
case GIMPLE_OMP_PARALLEL:
case GIMPLE_OMP_TASK:
ctx = maybe_lookup_ctx (stmt);
+ gcc_assert (ctx);
+ if (ctx->cancellable)
+ ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
lower_omp_taskreg (gsi_p, ctx);
break;
case GIMPLE_OMP_FOR:
ctx = maybe_lookup_ctx (stmt);
gcc_assert (ctx);
+ if (ctx->cancellable)
+ ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
lower_omp_for (gsi_p, ctx);
break;
case GIMPLE_OMP_SECTIONS:
ctx = maybe_lookup_ctx (stmt);
gcc_assert (ctx);
+ if (ctx->cancellable)
+ ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
lower_omp_sections (gsi_p, ctx);
break;
case GIMPLE_OMP_SINGLE:
@@ -7962,6 +9938,11 @@ lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
gcc_assert (ctx);
lower_omp_master (gsi_p, ctx);
break;
+ case GIMPLE_OMP_TASKGROUP:
+ ctx = maybe_lookup_ctx (stmt);
+ gcc_assert (ctx);
+ lower_omp_taskgroup (gsi_p, ctx);
+ break;
case GIMPLE_OMP_ORDERED:
ctx = maybe_lookup_ctx (stmt);
gcc_assert (ctx);
@@ -7978,6 +9959,66 @@ lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
gimple_regimplify_operands (stmt, gsi_p);
break;
+ case GIMPLE_OMP_TARGET:
+ ctx = maybe_lookup_ctx (stmt);
+ gcc_assert (ctx);
+ lower_omp_target (gsi_p, ctx);
+ break;
+ case GIMPLE_OMP_TEAMS:
+ ctx = maybe_lookup_ctx (stmt);
+ gcc_assert (ctx);
+ lower_omp_teams (gsi_p, ctx);
+ break;
+ case GIMPLE_CALL:
+ tree fndecl;
+ fndecl = gimple_call_fndecl (stmt);
+ if (fndecl
+ && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
+ switch (DECL_FUNCTION_CODE (fndecl))
+ {
+ case BUILT_IN_GOMP_BARRIER:
+ if (ctx == NULL)
+ break;
+ /* FALLTHRU */
+ case BUILT_IN_GOMP_CANCEL:
+ case BUILT_IN_GOMP_CANCELLATION_POINT:
+ omp_context *cctx;
+ cctx = ctx;
+ if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
+ cctx = cctx->outer;
+ gcc_assert (gimple_call_lhs (stmt) == NULL_TREE);
+ if (!cctx->cancellable)
+ {
+ if (DECL_FUNCTION_CODE (fndecl)
+ == BUILT_IN_GOMP_CANCELLATION_POINT)
+ {
+ stmt = gimple_build_nop ();
+ gsi_replace (gsi_p, stmt, false);
+ }
+ break;
+ }
+ tree lhs;
+ lhs = create_tmp_var (boolean_type_node, NULL);
+ if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
+ {
+ fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
+ gimple_call_set_fndecl (stmt, fndecl);
+ gimple_call_set_fntype (stmt, TREE_TYPE (fndecl));
+ }
+ gimple_call_set_lhs (stmt, lhs);
+ tree fallthru_label;
+ fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
+ gimple g;
+ g = gimple_build_label (fallthru_label);
+ gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
+ g = gimple_build_cond (NE_EXPR, lhs, boolean_false_node,
+ cctx->cancel_label, fallthru_label);
+ gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
+ break;
+ default:
+ break;
+ }
+ /* FALLTHRU */
default:
if ((ctx || task_shared_vars)
&& walk_gimple_op (stmt, lower_omp_regimplify_p,
@@ -7994,6 +10035,12 @@ lower_omp (gimple_seq *body, omp_context *ctx)
gimple_stmt_iterator gsi;
for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
lower_omp_1 (&gsi, ctx);
+ /* Inside target region we haven't called fold_stmt during gimplification,
+ because it can break code by adding decl references that weren't in the
+ source. Call fold_stmt now. */
+ if (target_nesting_level)
+ for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
+ fold_stmt (&gsi);
input_location = saved_location;
}
@@ -8006,7 +10053,7 @@ execute_lower_omp (void)
/* This pass always runs, to provide PROP_gimple_lomp.
But there is nothing to do unless -fopenmp is given. */
- if (flag_openmp == 0)
+ if (flag_openmp == 0 && flag_openmp_simd == 0)
return 0;
all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
@@ -8056,8 +10103,8 @@ const pass_data pass_data_lower_omp =
class pass_lower_omp : public gimple_opt_pass
{
public:
- pass_lower_omp(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_lower_omp, ctxt)
+ pass_lower_omp (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_lower_omp, ctxt)
{}
/* opt_pass methods: */
@@ -8162,6 +10209,9 @@ diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
case GIMPLE_OMP_MASTER:
case GIMPLE_OMP_ORDERED:
case GIMPLE_OMP_CRITICAL:
+ case GIMPLE_OMP_TARGET:
+ case GIMPLE_OMP_TEAMS:
+ case GIMPLE_OMP_TASKGROUP:
/* The minimal context here is just the current OMP construct. */
inner_context = stmt;
wi->info = inner_context;
@@ -8217,6 +10267,9 @@ diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
case GIMPLE_OMP_MASTER:
case GIMPLE_OMP_ORDERED:
case GIMPLE_OMP_CRITICAL:
+ case GIMPLE_OMP_TARGET:
+ case GIMPLE_OMP_TEAMS:
+ case GIMPLE_OMP_TASKGROUP:
wi->info = stmt;
walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
wi->info = context;
@@ -8288,6 +10341,121 @@ diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
return NULL_TREE;
}
+/* Called from tree-cfg.c::make_edges to create cfg edges for all GIMPLE_OMP
+ codes. */
+bool
+make_gimple_omp_edges (basic_block bb, struct omp_region **region)
+{
+ gimple last = last_stmt (bb);
+ enum gimple_code code = gimple_code (last);
+ struct omp_region *cur_region = *region;
+ bool fallthru = false;
+
+ switch (code)
+ {
+ case GIMPLE_OMP_PARALLEL:
+ case GIMPLE_OMP_TASK:
+ case GIMPLE_OMP_FOR:
+ case GIMPLE_OMP_SINGLE:
+ case GIMPLE_OMP_TEAMS:
+ case GIMPLE_OMP_MASTER:
+ case GIMPLE_OMP_TASKGROUP:
+ case GIMPLE_OMP_ORDERED:
+ case GIMPLE_OMP_CRITICAL:
+ case GIMPLE_OMP_SECTION:
+ cur_region = new_omp_region (bb, code, cur_region);
+ fallthru = true;
+ break;
+
+ case GIMPLE_OMP_TARGET:
+ cur_region = new_omp_region (bb, code, cur_region);
+ fallthru = true;
+ if (gimple_omp_target_kind (last) == GF_OMP_TARGET_KIND_UPDATE)
+ cur_region = cur_region->outer;
+ break;
+
+ case GIMPLE_OMP_SECTIONS:
+ cur_region = new_omp_region (bb, code, cur_region);
+ fallthru = true;
+ break;
+
+ case GIMPLE_OMP_SECTIONS_SWITCH:
+ fallthru = false;
+ break;
+
+ case GIMPLE_OMP_ATOMIC_LOAD:
+ case GIMPLE_OMP_ATOMIC_STORE:
+ fallthru = true;
+ break;
+
+ case GIMPLE_OMP_RETURN:
+ /* In the case of a GIMPLE_OMP_SECTION, the edge will go
+ somewhere other than the next block. This will be
+ created later. */
+ cur_region->exit = bb;
+ fallthru = cur_region->type != GIMPLE_OMP_SECTION;
+ cur_region = cur_region->outer;
+ break;
+
+ case GIMPLE_OMP_CONTINUE:
+ cur_region->cont = bb;
+ switch (cur_region->type)
+ {
+ case GIMPLE_OMP_FOR:
+ /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
+ succs edges as abnormal to prevent splitting
+ them. */
+ single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
+ /* Make the loopback edge. */
+ make_edge (bb, single_succ (cur_region->entry),
+ EDGE_ABNORMAL);
+
+ /* Create an edge from GIMPLE_OMP_FOR to exit, which
+ corresponds to the case that the body of the loop
+ is not executed at all. */
+ make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
+ make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
+ fallthru = false;
+ break;
+
+ case GIMPLE_OMP_SECTIONS:
+ /* Wire up the edges into and out of the nested sections. */
+ {
+ basic_block switch_bb = single_succ (cur_region->entry);
+
+ struct omp_region *i;
+ for (i = cur_region->inner; i ; i = i->next)
+ {
+ gcc_assert (i->type == GIMPLE_OMP_SECTION);
+ make_edge (switch_bb, i->entry, 0);
+ make_edge (i->exit, bb, EDGE_FALLTHRU);
+ }
+
+ /* Make the loopback edge to the block with
+ GIMPLE_OMP_SECTIONS_SWITCH. */
+ make_edge (bb, switch_bb, 0);
+
+ /* Make the edge from the switch to exit. */
+ make_edge (switch_bb, bb->next_bb, 0);
+ fallthru = false;
+ }
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ if (*region != cur_region)
+ *region = cur_region;
+
+ return fallthru;
+}
+
static unsigned int
diagnose_omp_structured_block_errors (void)
{
@@ -8337,8 +10505,8 @@ const pass_data pass_data_diagnose_omp_blocks =
class pass_diagnose_omp_blocks : public gimple_opt_pass
{
public:
- pass_diagnose_omp_blocks(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_diagnose_omp_blocks, ctxt)
+ pass_diagnose_omp_blocks (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/omp-low.h b/gcc/omp-low.h
new file mode 100644
index 00000000000..6b5a2ff304d
--- /dev/null
+++ b/gcc/omp-low.h
@@ -0,0 +1,31 @@
+/* Header file for openMP lowering directives.
+ Copyright (C) 2013 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_LOW_H
+#define GCC_OMP_LOW_H
+
+struct omp_region;
+
+extern tree find_omp_clause (tree, enum omp_clause_code);
+extern void omp_expand_local (basic_block);
+extern void free_omp_regions (void);
+extern tree omp_reduction_init (tree, tree);
+extern bool make_gimple_omp_edges (basic_block, struct omp_region **);
+
+#endif /* GCC_OMP_LOW_H */
diff --git a/gcc/optabs.c b/gcc/optabs.c
index 1d0659e1361..164e4dd91e6 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -401,8 +401,8 @@ optab_for_tree_code (enum tree_code code, const_tree type,
case FLOOR_DIV_EXPR:
case ROUND_DIV_EXPR:
case EXACT_DIV_EXPR:
- if (TYPE_SATURATING(type))
- return TYPE_UNSIGNED(type) ? usdiv_optab : ssdiv_optab;
+ if (TYPE_SATURATING (type))
+ return TYPE_UNSIGNED (type) ? usdiv_optab : ssdiv_optab;
return TYPE_UNSIGNED (type) ? udiv_optab : sdiv_optab;
case LSHIFT_EXPR:
@@ -413,8 +413,8 @@ optab_for_tree_code (enum tree_code code, const_tree type,
gcc_assert (subtype == optab_scalar);
}
- if (TYPE_SATURATING(type))
- return TYPE_UNSIGNED(type) ? usashl_optab : ssashl_optab;
+ if (TYPE_SATURATING (type))
+ return TYPE_UNSIGNED (type) ? usashl_optab : ssashl_optab;
return ashl_optab;
case RSHIFT_EXPR:
@@ -556,23 +556,23 @@ optab_for_tree_code (enum tree_code code, const_tree type,
{
case POINTER_PLUS_EXPR:
case PLUS_EXPR:
- if (TYPE_SATURATING(type))
- return TYPE_UNSIGNED(type) ? usadd_optab : ssadd_optab;
+ if (TYPE_SATURATING (type))
+ return TYPE_UNSIGNED (type) ? usadd_optab : ssadd_optab;
return trapv ? addv_optab : add_optab;
case MINUS_EXPR:
- if (TYPE_SATURATING(type))
- return TYPE_UNSIGNED(type) ? ussub_optab : sssub_optab;
+ if (TYPE_SATURATING (type))
+ return TYPE_UNSIGNED (type) ? ussub_optab : sssub_optab;
return trapv ? subv_optab : sub_optab;
case MULT_EXPR:
- if (TYPE_SATURATING(type))
- return TYPE_UNSIGNED(type) ? usmul_optab : ssmul_optab;
+ if (TYPE_SATURATING (type))
+ return TYPE_UNSIGNED (type) ? usmul_optab : ssmul_optab;
return trapv ? smulv_optab : smul_optab;
case NEGATE_EXPR:
- if (TYPE_SATURATING(type))
- return TYPE_UNSIGNED(type) ? usneg_optab : ssneg_optab;
+ if (TYPE_SATURATING (type))
+ return TYPE_UNSIGNED (type) ? usneg_optab : ssneg_optab;
return trapv ? negv_optab : neg_optab;
case ABS_EXPR:
@@ -4288,7 +4288,7 @@ emit_cmp_and_jump_insn_1 (rtx test, enum machine_mode mode, rtx label, int prob)
&& JUMP_P (insn)
&& any_condjump_p (insn)
&& !find_reg_note (insn, REG_BR_PROB, 0))
- add_reg_note (insn, REG_BR_PROB, GEN_INT (prob));
+ add_int_reg_note (insn, REG_BR_PROB, prob);
}
/* Generate code to compare X with Y so that the condition codes are
@@ -5714,7 +5714,7 @@ gen_interclass_conv_libfunc (convert_optab tab,
fname = GET_MODE_NAME (fmode);
tname = GET_MODE_NAME (tmode);
- if (DECIMAL_FLOAT_MODE_P(fmode) || DECIMAL_FLOAT_MODE_P(tmode))
+ if (DECIMAL_FLOAT_MODE_P (fmode) || DECIMAL_FLOAT_MODE_P (tmode))
{
libfunc_name = dec_name;
suffix = dec_suffix;
@@ -5847,7 +5847,7 @@ gen_intraclass_conv_libfunc (convert_optab tab, const char *opname,
fname = GET_MODE_NAME (fmode);
tname = GET_MODE_NAME (tmode);
- if (DECIMAL_FLOAT_MODE_P(fmode) || DECIMAL_FLOAT_MODE_P(tmode))
+ if (DECIMAL_FLOAT_MODE_P (fmode) || DECIMAL_FLOAT_MODE_P (tmode))
{
libfunc_name = dec_name;
suffix = dec_suffix;
@@ -6624,8 +6624,8 @@ expand_vec_perm (enum machine_mode mode, rtx v0, rtx v1, rtx sel, rtx target)
icode = direct_optab_handler (vec_perm_const_optab, qimode);
if (icode != CODE_FOR_nothing)
{
- tmp = expand_vec_perm_1 (icode, gen_lowpart (qimode, target),
- gen_lowpart (qimode, v0),
+ tmp = mode != qimode ? gen_reg_rtx (qimode) : target;
+ tmp = expand_vec_perm_1 (icode, tmp, gen_lowpart (qimode, v0),
gen_lowpart (qimode, v1), sel_qi);
if (tmp)
return gen_lowpart (mode, tmp);
@@ -6689,8 +6689,8 @@ expand_vec_perm (enum machine_mode mode, rtx v0, rtx v1, rtx sel, rtx target)
gcc_assert (sel_qi != NULL);
}
- tmp = expand_vec_perm_1 (icode, gen_lowpart (qimode, target),
- gen_lowpart (qimode, v0),
+ tmp = mode != qimode ? gen_reg_rtx (qimode) : target;
+ tmp = expand_vec_perm_1 (icode, tmp, gen_lowpart (qimode, v0),
gen_lowpart (qimode, v1), sel_qi);
if (tmp)
tmp = gen_lowpart (mode, tmp);
@@ -7040,8 +7040,7 @@ maybe_emit_atomic_exchange (rtx target, rtx mem, rtx val, enum memmodel model)
create_output_operand (&ops[0], target, mode);
create_fixed_operand (&ops[1], mem);
- /* VAL may have been promoted to a wider mode. Shrink it if so. */
- create_convert_operand_to (&ops[2], val, mode, true);
+ create_input_operand (&ops[2], val, mode);
create_integer_operand (&ops[3], model);
if (maybe_expand_insn (icode, 4, ops))
return ops[0].value;
@@ -7080,8 +7079,7 @@ maybe_emit_sync_lock_test_and_set (rtx target, rtx mem, rtx val,
struct expand_operand ops[3];
create_output_operand (&ops[0], target, mode);
create_fixed_operand (&ops[1], mem);
- /* VAL may have been promoted to a wider mode. Shrink it if so. */
- create_convert_operand_to (&ops[2], val, mode, true);
+ create_input_operand (&ops[2], val, mode);
if (maybe_expand_insn (icode, 3, ops))
return ops[0].value;
}
@@ -7123,8 +7121,6 @@ maybe_emit_compare_and_swap_exchange_loop (rtx target, rtx mem, rtx val)
{
if (!target || !register_operand (target, mode))
target = gen_reg_rtx (mode);
- if (GET_MODE (val) != VOIDmode && GET_MODE (val) != mode)
- val = convert_modes (mode, GET_MODE (val), val, 1);
if (expand_compare_and_swap_loop (mem, target, val, NULL_RTX))
return target;
}
@@ -7336,8 +7332,8 @@ expand_atomic_compare_and_swap (rtx *ptarget_bool, rtx *ptarget_oval,
create_output_operand (&ops[0], target_bool, bool_mode);
create_output_operand (&ops[1], target_oval, mode);
create_fixed_operand (&ops[2], mem);
- create_convert_operand_to (&ops[3], expected, mode, true);
- create_convert_operand_to (&ops[4], desired, mode, true);
+ create_input_operand (&ops[3], expected, mode);
+ create_input_operand (&ops[4], desired, mode);
create_integer_operand (&ops[5], is_weak);
create_integer_operand (&ops[6], succ_model);
create_integer_operand (&ops[7], fail_model);
@@ -7358,8 +7354,8 @@ expand_atomic_compare_and_swap (rtx *ptarget_bool, rtx *ptarget_oval,
create_output_operand (&ops[0], target_oval, mode);
create_fixed_operand (&ops[1], mem);
- create_convert_operand_to (&ops[2], expected, mode, true);
- create_convert_operand_to (&ops[3], desired, mode, true);
+ create_input_operand (&ops[2], expected, mode);
+ create_input_operand (&ops[3], desired, mode);
if (!maybe_expand_insn (icode, 4, ops))
return false;
@@ -7585,7 +7581,7 @@ expand_atomic_store (rtx mem, rtx val, enum memmodel model, bool use_release)
/* If the size of the object is greater than word size on this target,
a default store will not be atomic, Try a mem_exchange and throw away
the result. If that doesn't work, don't do anything. */
- if (GET_MODE_PRECISION(mode) > BITS_PER_WORD)
+ if (GET_MODE_PRECISION (mode) > BITS_PER_WORD)
{
rtx target = maybe_emit_atomic_exchange (NULL_RTX, mem, val, model);
if (!target)
diff --git a/gcc/optc-save-gen.awk b/gcc/optc-save-gen.awk
index 4672228ff20..b822a0b1158 100644
--- a/gcc/optc-save-gen.awk
+++ b/gcc/optc-save-gen.awk
@@ -284,7 +284,7 @@ if (have_assert)
print "";
print " if (targetm.target_option.save)";
-print " targetm.target_option.save (ptr);";
+print " targetm.target_option.save (ptr, opts);";
print "";
for (i = 0; i < n_extra_target_vars; i++) {
@@ -347,7 +347,7 @@ for (i = 0; i < n_target_char; i++) {
# variables.
print "";
print " if (targetm.target_option.restore)";
-print " targetm.target_option.restore (ptr);";
+print " targetm.target_option.restore (opts, ptr);";
print "}";
diff --git a/gcc/opth-gen.awk b/gcc/opth-gen.awk
index 54d2a9bf48e..46bd570f6f7 100644
--- a/gcc/opth-gen.awk
+++ b/gcc/opth-gen.awk
@@ -382,6 +382,8 @@ for (i = 0; i < n_opts; i++) {
}
print "#define TARGET_" name \
" ((" vname " & " mask name ") != 0)"
+ print "#define TARGET_" name "_P(" vname ")" \
+ " ((" vname " & " mask name ") != 0)"
}
}
for (i = 0; i < n_extra_masks; i++) {
diff --git a/gcc/opts-global.c b/gcc/opts-global.c
index 32ea320da4b..af603b956e3 100644
--- a/gcc/opts-global.c
+++ b/gcc/opts-global.c
@@ -26,6 +26,7 @@ along with GCC; see the file COPYING3. If not see
#include "flags.h"
#include "ggc.h"
#include "tree.h" /* Required by langhooks.h. */
+#include "gimple.h"
#include "langhooks.h"
#include "tm.h" /* Required by rtl.h. */
#include "rtl.h"
@@ -36,6 +37,7 @@ along with GCC; see the file COPYING3. If not see
#include "plugin.h"
#include "toplev.h"
#include "tree-pass.h"
+#include "context.h"
typedef const char *const_char_p; /* For DEF_VEC_P. */
@@ -230,40 +232,6 @@ read_cmdline_options (struct gcc_options *opts, struct gcc_options *opts_set,
}
}
-/* Handle -ftree-vectorizer-verbose=ARG by remapping it to -fopt-info.
- It remaps the old verbosity values as following:
-
- REPORT_NONE ==> No dump is output
- REPORT_VECTORIZED_LOCATIONS ==> "-optimized"
- REPORT_UNVECTORIZED_LOCATIONS ==> "-missed"
-
- Any higher verbosity levels get mapped to "-all" flags. */
-
-static void
-dump_remap_tree_vectorizer_verbose (const char *arg)
-{
- int value = atoi (arg);
- const char *remapped_opt_info = NULL;
-
- switch (value)
- {
- case 0:
- break;
- case 1:
- remapped_opt_info = "optimized";
- break;
- case 2:
- remapped_opt_info = "missed";
- break;
- default:
- remapped_opt_info = "all";
- break;
- }
-
- if (remapped_opt_info)
- opt_info_switch_p (remapped_opt_info);
-}
-
/* Language mask determined at initialization. */
static unsigned int initial_lang_mask;
@@ -385,7 +353,7 @@ handle_common_deferred_options (void)
break;
case OPT_fdump_:
- if (!dump_switch_p (opt->arg))
+ if (!g->get_dumps ()->dump_switch_p (opt->arg))
error ("unrecognized command line option %<-fdump-%s%>", opt->arg);
break;
@@ -454,10 +422,6 @@ handle_common_deferred_options (void)
stack_limit_rtx = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (opt->arg));
break;
- case OPT_ftree_vectorizer_verbose_:
- dump_remap_tree_vectorizer_verbose (opt->arg);
- break;
-
default:
gcc_unreachable ();
}
diff --git a/gcc/opts.c b/gcc/opts.c
index 944834c4438..3a939ac92b9 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -169,7 +169,7 @@ base_of_path (const char *path, const char **base_out)
char c = *p;
while (c)
{
- if (IS_DIR_SEPARATOR(c))
+ if (IS_DIR_SEPARATOR (c))
{
base = p + 1;
dot = 0;
@@ -279,10 +279,15 @@ init_options_struct (struct gcc_options *opts, struct gcc_options *opts_set)
gcc_obstack_init (&opts_obstack);
*opts = global_options_init;
- memset (opts_set, 0, sizeof (*opts_set));
+
+ if (opts_set)
+ memset (opts_set, 0, sizeof (*opts_set));
opts->x_param_values = XNEWVEC (int, num_params);
- opts_set->x_param_values = XCNEWVEC (int, num_params);
+
+ if (opts_set)
+ opts_set->x_param_values = XCNEWVEC (int, num_params);
+
init_param_values (opts->x_param_values);
/* Initialize whether `char' is signed. */
@@ -468,7 +473,6 @@ static const struct default_options default_options_table[] =
{ OPT_LEVELS_2_PLUS_SPEED_ONLY, OPT_fschedule_insns, NULL, 1 },
{ OPT_LEVELS_2_PLUS, OPT_fschedule_insns2, NULL, 1 },
#endif
- { OPT_LEVELS_2_PLUS, OPT_fregmove, NULL, 1 },
{ OPT_LEVELS_2_PLUS, OPT_fstrict_aliasing, NULL, 1 },
{ OPT_LEVELS_2_PLUS, OPT_fstrict_overflow, NULL, 1 },
{ OPT_LEVELS_2_PLUS, OPT_freorder_blocks, NULL, 1 },
@@ -486,8 +490,10 @@ static const struct default_options default_options_table[] =
{ OPT_LEVELS_2_PLUS, OPT_falign_labels, NULL, 1 },
{ OPT_LEVELS_2_PLUS, OPT_falign_functions, NULL, 1 },
{ OPT_LEVELS_2_PLUS, OPT_ftree_tail_merge, NULL, 1 },
+ { OPT_LEVELS_2_PLUS, OPT_fvect_cost_model_, NULL, VECT_COST_MODEL_CHEAP },
{ OPT_LEVELS_2_PLUS_SPEED_ONLY, OPT_foptimize_strlen, NULL, 1 },
{ OPT_LEVELS_2_PLUS, OPT_fhoist_adjacent_loads, NULL, 1 },
+ { OPT_LEVELS_2_PLUS, OPT_fisolate_erroneous_paths, NULL, 1 },
/* -O3 optimizations. */
{ OPT_LEVELS_3_PLUS, OPT_ftree_loop_distribute_patterns, NULL, 1 },
@@ -500,7 +506,7 @@ static const struct default_options default_options_table[] =
{ OPT_LEVELS_3_PLUS, OPT_fgcse_after_reload, NULL, 1 },
{ OPT_LEVELS_3_PLUS, OPT_ftree_loop_vectorize, NULL, 1 },
{ OPT_LEVELS_3_PLUS, OPT_ftree_slp_vectorize, NULL, 1 },
- { OPT_LEVELS_3_PLUS, OPT_fvect_cost_model, NULL, 1 },
+ { OPT_LEVELS_3_PLUS, OPT_fvect_cost_model_, NULL, VECT_COST_MODEL_DYNAMIC },
{ OPT_LEVELS_3_PLUS, OPT_fipa_cp_clone, NULL, 1 },
{ OPT_LEVELS_3_PLUS, OPT_ftree_partial_pre, NULL, 1 },
@@ -825,6 +831,17 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
}
}
+ /* Tune vectorization related parametees according to cost model. */
+ if (opts->x_flag_vect_cost_model == VECT_COST_MODEL_CHEAP)
+ {
+ maybe_set_param_value (PARAM_VECT_MAX_VERSION_FOR_ALIAS_CHECKS,
+ 6, opts->x_param_values, opts_set->x_param_values);
+ maybe_set_param_value (PARAM_VECT_MAX_VERSION_FOR_ALIGNMENT_CHECKS,
+ 0, opts->x_param_values, opts_set->x_param_values);
+ maybe_set_param_value (PARAM_VECT_MAX_PEELING_FOR_ALIGNMENT,
+ 0, opts->x_param_values, opts_set->x_param_values);
+ }
+
/* Set PARAM_MAX_STORES_TO_SINK to 0 if either vectorization or if-conversion
is disabled. */
if ((!opts->x_flag_tree_loop_vectorize && !opts->x_flag_tree_slp_vectorize)
@@ -876,7 +893,7 @@ wrap_help (const char *help,
}
}
- printf( " %-*.*s %.*s\n", col_width, item_width, item, len, help);
+ printf (" %-*.*s %.*s\n", col_width, item_width, item, len, help);
item_width = 0;
while (help[len] == ' ')
len++;
@@ -1428,6 +1445,7 @@ common_handle_option (struct gcc_options *opts,
{ "undefined", SANITIZE_UNDEFINED, sizeof "undefined" - 1 },
{ "unreachable", SANITIZE_UNREACHABLE,
sizeof "unreachable" - 1 },
+ { "vla-bound", SANITIZE_VLA, sizeof "vla-bound" - 1 },
{ NULL, 0, 0 }
};
const char *comma;
@@ -1669,7 +1687,7 @@ common_handle_option (struct gcc_options *opts,
&& !opts_set->x_flag_tree_vectorize)
opts->x_flag_tree_slp_vectorize = value;
if (!opts_set->x_flag_vect_cost_model)
- opts->x_flag_vect_cost_model = value;
+ opts->x_flag_vect_cost_model = VECT_COST_MODEL_DYNAMIC;
if (!opts_set->x_flag_tree_loop_distribute_patterns)
opts->x_flag_tree_loop_distribute_patterns = value;
/* Indirect call profiling should do all useful transformations
@@ -1772,12 +1790,6 @@ common_handle_option (struct gcc_options *opts,
opts->x_flag_stack_usage_info = value != 0;
break;
- case OPT_ftree_vectorizer_verbose_:
- /* -ftree-vectorizer-verbose is deprecated. It is defined in
- -terms of fopt-info=N. */
- /* Deferred. */
- break;
-
case OPT_g:
set_debug_level (NO_DEBUG, DEFAULT_GDB_EXTENSIONS, arg, opts, opts_set,
loc);
diff --git a/gcc/params.def b/gcc/params.def
index 496a66b512d..454a68890dd 100644
--- a/gcc/params.def
+++ b/gcc/params.def
@@ -373,6 +373,11 @@ DEFPARAM(HOT_BB_FREQUENCY_FRACTION,
"Select fraction of the maximal frequency of executions of basic block in function given basic block needs to have to be considered hot",
1000, 0, 0)
+DEFPARAM(UNLIKELY_BB_COUNT_FRACTION,
+ "unlikely-bb-count-fraction",
+ "The minimum fraction of profile runs a given basic block execution count must be not to be considered unlikely",
+ 20, 1, 10000)
+
DEFPARAM (PARAM_ALIGN_THRESHOLD,
"align-threshold",
"Select fraction of the maximal frequency of executions of basic block in function given basic block get alignment",
@@ -398,6 +403,19 @@ DEFPARAM(PARAM_MAX_PREDICTED_ITERATIONS,
"max-predicted-iterations",
"The maximum number of loop iterations we predict statically",
100, 0, 0)
+
+/* This parameter controls the probability of builtin_expect. The default
+ value is 90%. This empirical value is obtained through the weighted
+ probability of FDO counters (with the FDO count value as the weight)
+ in some real world programs:
+ (1) Google performance test benchmarks: the probability is 0.9081.
+ (2) Linux 3.3 kernel running Google search workload: the probability
+ is 0.8717. */
+
+DEFPARAM(BUILTIN_EXPECT_PROBABILITY,
+ "builtin-expect-probability",
+ "Set the estimated probability in percentage for builtin expect. The default value is 90% probability.",
+ 90, 0, 100)
DEFPARAM(TRACER_DYNAMIC_COVERAGE_FEEDBACK,
"tracer-dynamic-coverage-feedback",
"The percentage of function, weighted by execution frequency, that must be covered by trace formation. Used when profile feedback is available",
@@ -544,6 +562,11 @@ DEFPARAM(PARAM_VECT_MAX_VERSION_FOR_ALIAS_CHECKS,
"Bound on number of runtime checks inserted by the vectorizer's loop versioning for alias check",
10, 0, 0)
+DEFPARAM(PARAM_VECT_MAX_PEELING_FOR_ALIGNMENT,
+ "vect-max-peeling-for-alignment",
+ "Max number of loop peels to enhancement alignment of data references in a loop",
+ -1, -1, 64)
+
DEFPARAM(PARAM_MAX_CSELIB_MEMORY_LOCATIONS,
"max-cselib-memory-locations",
"The maximum memory locations recorded by cselib",
@@ -664,6 +687,12 @@ DEFPARAM (PARAM_SSP_BUFFER_SIZE,
"The lower bound for a buffer to be considered for stack smashing protection",
8, 1, 0)
+DEFPARAM (PARAM_MIN_SIZE_FOR_STACK_SHARING,
+ "min-size-for-stack-sharing",
+ "The minimum size of variables taking part in stack slot sharing "
+ "when not optimizing",
+ 32, 0, 0)
+
/* When we thread through a block we have to make copies of the
statements within the block. Clearly for large blocks the code
duplication is bad.
diff --git a/gcc/pass_manager.h b/gcc/pass_manager.h
index 04c6237d791..77d78eb11f5 100644
--- a/gcc/pass_manager.h
+++ b/gcc/pass_manager.h
@@ -49,7 +49,7 @@ class pass_manager
public:
void *operator new (size_t sz);
- pass_manager(context *ctxt);
+ pass_manager (context *ctxt);
void register_pass (struct register_pass_info *pass_info);
void register_one_dump_file (struct opt_pass *pass);
@@ -97,7 +97,7 @@ private:
void register_dump_files (struct opt_pass *pass, int properties);
private:
- context *ctxt_;
+ context *m_ctxt;
/* References to all of the individual passes.
These fields are generated via macro expansion.
diff --git a/gcc/passes.c b/gcc/passes.c
index b3be53bb187..47ba6a81ce5 100644
--- a/gcc/passes.c
+++ b/gcc/passes.c
@@ -56,11 +56,17 @@ along with GCC; see the file COPYING3. If not see
#include "langhooks.h"
#include "cfgloop.h"
#include "hosthooks.h"
-#include "cgraph.h"
#include "opts.h"
#include "coverage.h"
#include "value-prof.h"
#include "tree-inline.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-cfg.h"
+#include "tree-ssanames.h"
+#include "tree-ssa-loop-manip.h"
+#include "tree-into-ssa.h"
+#include "tree-dfa.h"
#include "tree-ssa.h"
#include "tree-pass.h"
#include "tree-dump.h"
@@ -72,6 +78,8 @@ along with GCC; see the file COPYING3. If not see
#include "tree-pretty-print.h" /* for dump_function_header */
#include "context.h"
#include "pass_manager.h"
+#include "tree-ssa-live.h" /* For remove_unused_locals. */
+#include "tree-cfgcleanup.h"
using namespace gcc;
@@ -107,12 +115,12 @@ opt_pass::execute ()
return 0;
}
-opt_pass::opt_pass(const pass_data &data, context *ctxt)
- : pass_data(data),
- sub(NULL),
- next(NULL),
- static_pass_number(0),
- ctxt_(ctxt)
+opt_pass::opt_pass (const pass_data &data, context *ctxt)
+ : pass_data (data),
+ sub (NULL),
+ next (NULL),
+ static_pass_number (0),
+ m_ctxt (ctxt)
{
}
@@ -278,27 +286,28 @@ finish_optimization_passes (void)
int i;
struct dump_file_info *dfi;
char *name;
+ gcc::dump_manager *dumps = m_ctxt->get_dumps ();
timevar_push (TV_DUMP);
if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities)
{
- dump_start (pass_profile_1->static_pass_number, NULL);
+ dumps->dump_start (pass_profile_1->static_pass_number, NULL);
end_branch_prob ();
- dump_finish (pass_profile_1->static_pass_number);
+ dumps->dump_finish (pass_profile_1->static_pass_number);
}
if (optimize > 0)
{
- dump_start (pass_profile_1->static_pass_number, NULL);
+ dumps->dump_start (pass_profile_1->static_pass_number, NULL);
print_combine_total_stats ();
- dump_finish (pass_profile_1->static_pass_number);
+ dumps->dump_finish (pass_profile_1->static_pass_number);
}
/* Do whatever is necessary to finish printing the graphs. */
- for (i = TDI_end; (dfi = get_dump_file_info (i)) != NULL; ++i)
- if (dump_initialized_p (i)
+ for (i = TDI_end; (dfi = dumps->get_dump_file_info (i)) != NULL; ++i)
+ if (dumps->dump_initialized_p (i)
&& (dfi->pflags & TDF_GRAPH) != 0
- && (name = get_dump_file_name (i)) != NULL)
+ && (name = dumps->get_dump_file_name (i)) != NULL)
{
finish_graph_dump_file (name);
free (name);
@@ -350,8 +359,8 @@ const pass_data pass_data_early_local_passes =
class pass_early_local_passes : public simple_ipa_opt_pass
{
public:
- pass_early_local_passes(gcc::context *ctxt)
- : simple_ipa_opt_pass(pass_data_early_local_passes, ctxt)
+ pass_early_local_passes (gcc::context *ctxt)
+ : simple_ipa_opt_pass (pass_data_early_local_passes, ctxt)
{}
/* opt_pass methods: */
@@ -398,8 +407,8 @@ const pass_data pass_data_all_early_optimizations =
class pass_all_early_optimizations : public gimple_opt_pass
{
public:
- pass_all_early_optimizations(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_all_early_optimizations, ctxt)
+ pass_all_early_optimizations (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_all_early_optimizations, ctxt)
{}
/* opt_pass methods: */
@@ -443,8 +452,8 @@ const pass_data pass_data_all_optimizations =
class pass_all_optimizations : public gimple_opt_pass
{
public:
- pass_all_optimizations(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_all_optimizations, ctxt)
+ pass_all_optimizations (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_all_optimizations, ctxt)
{}
/* opt_pass methods: */
@@ -488,8 +497,8 @@ const pass_data pass_data_all_optimizations_g =
class pass_all_optimizations_g : public gimple_opt_pass
{
public:
- pass_all_optimizations_g(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_all_optimizations_g, ctxt)
+ pass_all_optimizations_g (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_all_optimizations_g, ctxt)
{}
/* opt_pass methods: */
@@ -533,8 +542,8 @@ const pass_data pass_data_rest_of_compilation =
class pass_rest_of_compilation : public rtl_opt_pass
{
public:
- pass_rest_of_compilation(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_rest_of_compilation, ctxt)
+ pass_rest_of_compilation (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_rest_of_compilation, ctxt)
{}
/* opt_pass methods: */
@@ -576,8 +585,8 @@ const pass_data pass_data_postreload =
class pass_postreload : public rtl_opt_pass
{
public:
- pass_postreload(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_postreload, ctxt)
+ pass_postreload (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_postreload, ctxt)
{}
/* opt_pass methods: */
@@ -641,6 +650,7 @@ pass_manager::register_one_dump_file (struct opt_pass *pass)
char num[10];
int flags, id;
int optgroup_flags = OPTGROUP_NONE;
+ gcc::dump_manager *dumps = m_ctxt->get_dumps ();
/* See below in next_pass_1. */
num[0] = '\0';
@@ -681,7 +691,8 @@ pass_manager::register_one_dump_file (struct opt_pass *pass)
any dump messages are emitted properly under -fopt-info(-optall). */
if (optgroup_flags == OPTGROUP_NONE)
optgroup_flags = OPTGROUP_OTHER;
- id = dump_register (dot_name, flag_name, glob_name, flags, optgroup_flags);
+ id = dumps->dump_register (dot_name, flag_name, glob_name, flags,
+ optgroup_flags);
set_pass_for_id (id, pass);
full_name = concat (prefix, pass->name, num, NULL);
register_pass_name (pass, full_name);
@@ -836,7 +847,7 @@ dump_one_pass (struct opt_pass *pass, int pass_indent)
const char *pn;
bool is_on, is_really_on;
- is_on = pass->has_gate ? pass->gate() : true;
+ is_on = pass->has_gate ? pass->gate () : true;
is_really_on = override_gate_status (pass, current_function_decl, is_on);
if (pass->static_pass_number <= 0)
@@ -879,10 +890,10 @@ pass_manager::dump_passes () const
{
struct cgraph_node *n, *node = NULL;
- create_pass_tab();
+ create_pass_tab ();
FOR_EACH_FUNCTION (n)
- if (DECL_STRUCT_FUNCTION (n->symbol.decl))
+ if (DECL_STRUCT_FUNCTION (n->decl))
{
node = n;
break;
@@ -891,7 +902,7 @@ pass_manager::dump_passes () const
if (!node)
return;
- push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
+ push_cfun (DECL_STRUCT_FUNCTION (node->decl));
dump_pass_list (all_lowering_passes, 1);
dump_pass_list (all_small_ipa_passes, 1);
@@ -1389,6 +1400,7 @@ void
pass_manager::register_pass (struct register_pass_info *pass_info)
{
bool all_instances, success;
+ gcc::dump_manager *dumps = m_ctxt->get_dumps ();
/* The checks below could fail in buggy plugins. Existing GCC
passes should never fail these checks, so we mention plugin in
@@ -1446,9 +1458,9 @@ pass_manager::register_pass (struct register_pass_info *pass_info)
else
tdi = TDI_rtl_all;
/* Check if dump-all flag is specified. */
- if (get_dump_file_info (tdi)->pstate)
- get_dump_file_info (added_pass_nodes->pass->static_pass_number)
- ->pstate = get_dump_file_info (tdi)->pstate;
+ if (dumps->get_dump_file_info (tdi)->pstate)
+ dumps->get_dump_file_info (added_pass_nodes->pass->static_pass_number)
+ ->pstate = dumps->get_dump_file_info (tdi)->pstate;
XDELETE (added_pass_nodes);
added_pass_nodes = next_node;
}
@@ -1485,10 +1497,10 @@ pass_manager::operator new (size_t sz)
}
pass_manager::pass_manager (context *ctxt)
-: all_passes(NULL), all_small_ipa_passes(NULL), all_lowering_passes(NULL),
- all_regular_ipa_passes(NULL), all_lto_gen_passes(NULL),
- all_late_ipa_passes(NULL), passes_by_id(NULL), passes_by_id_size(0),
- ctxt_(ctxt)
+: all_passes (NULL), all_small_ipa_passes (NULL), all_lowering_passes (NULL),
+ all_regular_ipa_passes (NULL), all_lto_gen_passes (NULL),
+ all_late_ipa_passes (NULL), passes_by_id (NULL), passes_by_id_size (0),
+ m_ctxt (ctxt)
{
struct opt_pass **p;
@@ -1513,7 +1525,7 @@ pass_manager::pass_manager (context *ctxt)
do { \
gcc_assert (NULL == PASS ## _ ## NUM); \
if ((NUM) == 1) \
- PASS ## _1 = make_##PASS (ctxt_); \
+ PASS ## _1 = make_##PASS (m_ctxt); \
else \
{ \
gcc_assert (PASS ## _1); \
@@ -1565,10 +1577,10 @@ do_per_function (void (*callback) (void *data), void *data)
{
struct cgraph_node *node;
FOR_EACH_DEFINED_FUNCTION (node)
- if (node->symbol.analyzed && gimple_has_body_p (node->symbol.decl)
- && (!node->clone_of || node->symbol.decl != node->clone_of->symbol.decl))
+ if (node->analyzed && gimple_has_body_p (node->decl)
+ && (!node->clone_of || node->decl != node->clone_of->decl))
{
- push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
+ push_cfun (DECL_STRUCT_FUNCTION (node->decl));
callback (data);
if (!flag_wpa)
{
@@ -1615,7 +1627,7 @@ do_per_function_toporder (void (*callback) (void *data), void *data)
if (cgraph_function_with_gimple_body_p (node))
{
cgraph_get_body (node);
- push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
+ push_cfun (DECL_STRUCT_FUNCTION (node->decl));
callback (data);
free_dominance_info (CDI_DOMINATORS);
free_dominance_info (CDI_POST_DOMINATORS);
@@ -1931,9 +1943,11 @@ pass_init_dump_file (struct opt_pass *pass)
if (pass->static_pass_number != -1)
{
timevar_push (TV_DUMP);
- bool initializing_dump = !dump_initialized_p (pass->static_pass_number);
- dump_file_name = get_dump_file_name (pass->static_pass_number);
- dump_start (pass->static_pass_number, &dump_flags);
+ gcc::dump_manager *dumps = g->get_dumps ();
+ bool initializing_dump =
+ !dumps->dump_initialized_p (pass->static_pass_number);
+ dump_file_name = dumps->get_dump_file_name (pass->static_pass_number);
+ dumps->dump_start (pass->static_pass_number, &dump_flags);
if (dump_file && current_function_decl)
dump_function_header (dump_file, current_function_decl, dump_flags);
if (initializing_dump
@@ -1962,7 +1976,7 @@ pass_fini_dump_file (struct opt_pass *pass)
dump_file_name = NULL;
}
- dump_finish (pass->static_pass_number);
+ g->get_dumps ()->dump_finish (pass->static_pass_number);
timevar_pop (TV_DUMP);
}
@@ -2090,7 +2104,7 @@ apply_ipa_transforms (void *data)
if (!node->global.inlined_to && node->ipa_transforms_to_apply.exists ())
{
*(bool *)data = true;
- execute_all_ipa_transforms();
+ execute_all_ipa_transforms ();
rebuild_cgraph_edges ();
}
}
@@ -2139,7 +2153,7 @@ execute_one_pass (struct opt_pass *pass)
/* Check whether gate check should be avoided.
User controls the value of the gate through the parameter "gate_status". */
- gate_status = pass->has_gate ? pass->gate() : true;
+ gate_status = pass->has_gate ? pass->gate () : true;
gate_status = override_gate_status (pass, current_function_decl, gate_status);
/* Override gate with plugin. */
@@ -2358,19 +2372,19 @@ ipa_write_summaries (void)
ordering then matches the one IPA-passes get in their stmt_fixup
hooks. */
- push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
+ push_cfun (DECL_STRUCT_FUNCTION (node->decl));
renumber_gimple_stmt_uids ();
pop_cfun ();
}
- if (node->symbol.definition)
- lto_set_symtab_encoder_in_partition (encoder, (symtab_node)node);
+ if (node->definition)
+ lto_set_symtab_encoder_in_partition (encoder, node);
}
FOR_EACH_DEFINED_FUNCTION (node)
- if (node->symbol.alias)
- lto_set_symtab_encoder_in_partition (encoder, (symtab_node)node);
+ if (node->alias)
+ lto_set_symtab_encoder_in_partition (encoder, node);
FOR_EACH_DEFINED_VARIABLE (vnode)
- lto_set_symtab_encoder_in_partition (encoder, (symtab_node)vnode);
+ lto_set_symtab_encoder_in_partition (encoder, vnode);
ipa_write_summaries_1 (compute_ltrans_boundary (encoder));
@@ -2436,10 +2450,10 @@ ipa_write_optimization_summaries (lto_symtab_encoder_t encoder)
For functions newly born at WPA stage we need to initialize
the uids here. */
- if (node->symbol.definition
- && gimple_has_body_p (node->symbol.decl))
+ if (node->definition
+ && gimple_has_body_p (node->decl))
{
- push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
+ push_cfun (DECL_STRUCT_FUNCTION (node->decl));
renumber_gimple_stmt_uids ();
pop_cfun ();
}
@@ -2681,11 +2695,11 @@ function_called_by_processed_nodes_p (void)
e;
e = e->next_caller)
{
- if (e->caller->symbol.decl == current_function_decl)
+ if (e->caller->decl == current_function_decl)
continue;
if (!cgraph_function_with_gimple_body_p (e->caller))
continue;
- if (TREE_ASM_WRITTEN (e->caller->symbol.decl))
+ if (TREE_ASM_WRITTEN (e->caller->decl))
continue;
if (!e->caller->process && !e->caller->global.inlined_to)
break;
diff --git a/gcc/passes.def b/gcc/passes.def
index 84eb3f37e57..8d8dd800315 100644
--- a/gcc/passes.def
+++ b/gcc/passes.def
@@ -34,7 +34,6 @@ along with GCC; see the file COPYING3. If not see
NEXT_PASS (pass_warn_unused_result);
NEXT_PASS (pass_diagnose_omp_blocks);
NEXT_PASS (pass_diagnose_tm_blocks);
- NEXT_PASS (pass_mudflap_1);
NEXT_PASS (pass_lower_omp);
NEXT_PASS (pass_lower_cf);
NEXT_PASS (pass_lower_tm);
@@ -127,6 +126,7 @@ along with GCC; see the file COPYING3. If not see
/* 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_all_optimizations);
PUSH_INSERT_PASSES_WITHIN (pass_all_optimizations)
@@ -167,9 +167,16 @@ along with GCC; see the file COPYING3. If not see
is removed, and this place fits nicely. Remember this when
trying to move or duplicate pass_dominator somewhere earlier. */
NEXT_PASS (pass_dominator);
+ /* At this point the majority of const/copy propagations
+ are exposed. Go ahead and identify paths that should never
+ be executed in a conforming program and isolate those paths.
+
+ This will expose more degenerate PHIs in the main path and
+ expose more PRE/DOM optimization opportunities. */
+ NEXT_PASS (pass_isolate_erroneous_paths);
/* The only const/copy propagation opportunities left after
- DOM should be due to degenerate PHI nodes. So rather than
- run the full propagators, run a specialized pass which
+ DOM and erroneous path isolation should be due to degenerate PHI nodes.
+ So rather than run the full propagators, run a specialized pass which
only examines PHIs to discover const/copy propagation
opportunities. */
NEXT_PASS (pass_phi_only_cprop);
@@ -305,7 +312,6 @@ along with GCC; see the file COPYING3. If not see
NEXT_PASS (pass_cleanup_eh);
NEXT_PASS (pass_lower_resx);
NEXT_PASS (pass_nrv);
- NEXT_PASS (pass_mudflap_2);
NEXT_PASS (pass_cleanup_cfg_post_optimizing);
NEXT_PASS (pass_warn_function_noreturn);
@@ -352,7 +358,6 @@ along with GCC; see the file COPYING3. If not see
NEXT_PASS (pass_combine);
NEXT_PASS (pass_if_after_combine);
NEXT_PASS (pass_partition_blocks);
- NEXT_PASS (pass_regmove);
NEXT_PASS (pass_outof_cfg_layout_mode);
NEXT_PASS (pass_split_all_insns);
NEXT_PASS (pass_lower_subreg2);
@@ -361,6 +366,7 @@ along with GCC; see the file COPYING3. If not see
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_ira);
NEXT_PASS (pass_reload);
diff --git a/gcc/plugin.c b/gcc/plugin.c
index b269dfa3971..d7dcb5f4d36 100644
--- a/gcc/plugin.c
+++ b/gcc/plugin.c
@@ -241,16 +241,13 @@ parse_plugin_arg_opt (const char *arg)
}
else if (*ptr == '=')
{
- if (key_parsed)
- {
- error ("malformed option -fplugin-arg-%s (multiple '=' signs)",
- arg);
- return;
- }
- key_len = len;
- len = 0;
- value_start = ptr + 1;
- key_parsed = true;
+ if (!key_parsed)
+ {
+ key_len = len;
+ len = 0;
+ value_start = ptr + 1;
+ key_parsed = true;
+ }
continue;
}
else
@@ -806,7 +803,7 @@ dump_active_plugins (FILE *file)
for (ci = plugin_callbacks[event]; ci; ci = ci->next)
fprintf (file, " %s", ci->plugin_name);
- putc('\n', file);
+ putc ('\n', file);
}
}
diff --git a/gcc/postreload-gcse.c b/gcc/postreload-gcse.c
index 0f3ed7acda6..941007f5220 100644
--- a/gcc/postreload-gcse.c
+++ b/gcc/postreload-gcse.c
@@ -892,7 +892,7 @@ get_avail_load_store_reg (rtx insn)
{
if (REG_P (SET_DEST (PATTERN (insn))))
/* A load. */
- return SET_DEST(PATTERN(insn));
+ return SET_DEST (PATTERN (insn));
else
{
/* A store. */
@@ -1344,8 +1344,8 @@ const pass_data pass_data_gcse2 =
class pass_gcse2 : public rtl_opt_pass
{
public:
- pass_gcse2(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_gcse2, ctxt)
+ pass_gcse2 (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_gcse2, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/postreload.c b/gcc/postreload.c
index 97d7e5d0332..b0c63422357 100644
--- a/gcc/postreload.c
+++ b/gcc/postreload.c
@@ -2359,8 +2359,8 @@ const pass_data pass_data_postreload_cse =
class pass_postreload_cse : public rtl_opt_pass
{
public:
- pass_postreload_cse(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_postreload_cse, ctxt)
+ pass_postreload_cse (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_postreload_cse, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/predict.c b/gcc/predict.c
index 3b275d0afdb..cc9a0534e03 100644
--- a/gcc/predict.c
+++ b/gcc/predict.c
@@ -50,7 +50,14 @@ along with GCC; see the file COPYING3. If not see
#include "params.h"
#include "target.h"
#include "cfgloop.h"
-#include "tree-ssa.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "cgraph.h"
+#include "tree-cfg.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssa-loop-niter.h"
+#include "tree-ssa-loop.h"
#include "ggc.h"
#include "tree-pass.h"
#include "tree-scalar-evolution.h"
@@ -226,25 +233,44 @@ maybe_hot_edge_p (edge e)
}
-/* Return true in case BB is probably never executed. */
-bool
-probably_never_executed_bb_p (struct function *fun, const_basic_block bb)
+/* Return true if profile COUNT and FREQUENCY, or function FUN static
+ node frequency reflects never being executed. */
+
+static bool
+probably_never_executed (struct function *fun,
+ gcov_type count, int frequency)
{
gcc_checking_assert (fun);
if (profile_status_for_function (fun) == PROFILE_READ)
{
- if ((bb->count * 4 + profile_info->runs / 2) / profile_info->runs > 0)
+ int unlikely_count_fraction = PARAM_VALUE (UNLIKELY_BB_COUNT_FRACTION);
+ if (count * unlikely_count_fraction >= profile_info->runs)
return false;
- if (!bb->frequency)
+ if (!frequency)
return true;
if (!ENTRY_BLOCK_PTR->frequency)
return false;
- if (ENTRY_BLOCK_PTR->count && ENTRY_BLOCK_PTR->count < REG_BR_PROB_BASE)
+ if (ENTRY_BLOCK_PTR->count)
{
- return (RDIV (bb->frequency * ENTRY_BLOCK_PTR->count,
- ENTRY_BLOCK_PTR->frequency)
- < REG_BR_PROB_BASE / 4);
+ gcov_type computed_count;
+ /* Check for possibility of overflow, in which case entry bb count
+ is large enough to do the division first without losing much
+ precision. */
+ if (ENTRY_BLOCK_PTR->count < REG_BR_PROB_BASE * REG_BR_PROB_BASE)
+ {
+ gcov_type scaled_count
+ = frequency * ENTRY_BLOCK_PTR->count * unlikely_count_fraction;
+ computed_count = RDIV (scaled_count, ENTRY_BLOCK_PTR->frequency);
+ }
+ else
+ {
+ computed_count = RDIV (ENTRY_BLOCK_PTR->count,
+ ENTRY_BLOCK_PTR->frequency);
+ computed_count *= frequency * unlikely_count_fraction;
+ }
+ if (computed_count >= profile_info->runs)
+ return false;
}
return true;
}
@@ -256,19 +282,21 @@ probably_never_executed_bb_p (struct function *fun, const_basic_block bb)
}
+/* Return true in case BB is probably never executed. */
+
+bool
+probably_never_executed_bb_p (struct function *fun, const_basic_block bb)
+{
+ return probably_never_executed (fun, bb->count, bb->frequency);
+}
+
+
/* Return true in case edge E is probably never executed. */
bool
probably_never_executed_edge_p (struct function *fun, edge e)
{
- gcc_checking_assert (fun);
- if (profile_info && flag_branch_probabilities)
- return ((e->count + profile_info->runs / 2) / profile_info->runs) == 0;
- if ((!profile_info || !flag_branch_probabilities)
- && (cgraph_get_node (fun->decl)->frequency
- == NODE_FREQUENCY_UNLIKELY_EXECUTED))
- return true;
- return false;
+ return probably_never_executed (fun, e->count, EDGE_FREQUENCY (e));
}
/* Return true if NODE should be optimized for size. */
@@ -528,7 +556,7 @@ bool
br_prob_note_reliable_p (const_rtx note)
{
gcc_assert (REG_NOTE_KIND (note) == REG_BR_PROB);
- return probability_reliable_p (INTVAL (XEXP (note, 0)));
+ return probability_reliable_p (XINT (note, 0));
}
static void
@@ -682,7 +710,7 @@ invert_br_probabilities (rtx insn)
for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
if (REG_NOTE_KIND (note) == REG_BR_PROB)
- XEXP (note, 0) = GEN_INT (REG_BR_PROB_BASE - INTVAL (XEXP (note, 0)));
+ XINT (note, 0) = REG_BR_PROB_BASE - XINT (note, 0);
else if (REG_NOTE_KIND (note) == REG_BR_PRED)
XEXP (XEXP (note, 0), 1)
= GEN_INT (REG_BR_PROB_BASE - INTVAL (XEXP (XEXP (note, 0), 1)));
@@ -836,7 +864,7 @@ combine_predictions_for_insn (rtx insn, basic_block bb)
if (!prob_note)
{
- add_reg_note (insn, REG_BR_PROB, GEN_INT (combined_probability));
+ add_int_reg_note (insn, REG_BR_PROB, combined_probability);
/* Save the prediction into CFG in case we are seeing non-degenerated
conditional jump. */
@@ -849,7 +877,7 @@ combine_predictions_for_insn (rtx insn, basic_block bb)
}
else if (!single_succ_p (bb))
{
- int prob = INTVAL (XEXP (prob_note, 0));
+ int prob = XINT (prob_note, 0);
BRANCH_EDGE (bb)->probability = prob;
FALLTHRU_EDGE (bb)->probability = REG_BR_PROB_BASE - prob;
@@ -1995,11 +2023,12 @@ tree_predict_by_opcode (basic_block bb)
BITMAP_FREE (visited);
if (val)
{
+ int percent = PARAM_VALUE (BUILTIN_EXPECT_PROBABILITY);
+
+ gcc_assert (percent >= 0 && percent <= 100);
if (integer_zerop (val))
- predict_edge_def (then_edge, PRED_BUILTIN_EXPECT, NOT_TAKEN);
- else
- predict_edge_def (then_edge, PRED_BUILTIN_EXPECT, TAKEN);
- return;
+ percent = 100 - percent;
+ predict_edge (then_edge, PRED_BUILTIN_EXPECT, HITRATE (percent));
}
/* Try "pointer heuristic."
A comparison ptr == 0 is predicted as false.
@@ -2383,7 +2412,7 @@ tree_estimate_probability (void)
pointer_map_destroy (bb_predictions);
bb_predictions = NULL;
- estimate_bb_frequencies ();
+ estimate_bb_frequencies (false);
free_dominance_info (CDI_POST_DOMINATORS);
remove_fake_exit_edges ();
}
@@ -2686,7 +2715,7 @@ propagate_freq (basic_block head, bitmap tovisit)
}
}
-/* Estimate probabilities of loopback edges in loops at same nest level. */
+/* Estimate frequencies in loops at same nest level. */
static void
estimate_loops_at_level (struct loop *first_loop)
@@ -2795,15 +2824,17 @@ expensive_function_p (int threshold)
return false;
}
-/* Estimate basic blocks frequency by given branch probabilities. */
+/* Estimate and propagate basic block frequencies using the given branch
+ probabilities. If FORCE is true, the frequencies are used to estimate
+ the counts even when there are already non-zero profile counts. */
void
-estimate_bb_frequencies (void)
+estimate_bb_frequencies (bool force)
{
basic_block bb;
sreal freq_max;
- if (profile_status != PROFILE_READ || !counts_to_freqs ())
+ if (force || profile_status != PROFILE_READ || !counts_to_freqs ())
{
static int real_values_initialized = 0;
@@ -2840,8 +2871,8 @@ estimate_bb_frequencies (void)
}
}
- /* First compute probabilities locally for each loop from innermost
- to outermost to examine probabilities for back edges. */
+ /* First compute frequencies locally for each loop from innermost
+ to outermost to examine frequencies for back edges. */
estimate_loops ();
memcpy (&freq_max, &real_zero, sizeof (real_zero));
@@ -2957,8 +2988,8 @@ const pass_data pass_data_profile =
class pass_profile : public gimple_opt_pass
{
public:
- pass_profile(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_profile, ctxt)
+ pass_profile (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_profile, ctxt)
{}
/* opt_pass methods: */
@@ -2995,12 +3026,12 @@ const pass_data pass_data_strip_predict_hints =
class pass_strip_predict_hints : public gimple_opt_pass
{
public:
- pass_strip_predict_hints(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_strip_predict_hints, ctxt)
+ pass_strip_predict_hints (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_strip_predict_hints, ctxt)
{}
/* opt_pass methods: */
- opt_pass * clone () { return new pass_strip_predict_hints (ctxt_); }
+ opt_pass * clone () { return new pass_strip_predict_hints (m_ctxt); }
unsigned int execute () { return strip_predict_hints (); }
}; // class pass_strip_predict_hints
@@ -3022,13 +3053,29 @@ void
rebuild_frequencies (void)
{
timevar_push (TV_REBUILD_FREQUENCIES);
- if (profile_status == PROFILE_GUESSED)
+
+ /* When the max bb count in the function is small, there is a higher
+ chance that there were truncation errors in the integer scaling
+ of counts by inlining and other optimizations. This could lead
+ to incorrect classification of code as being cold when it isn't.
+ In that case, force the estimation of bb counts/frequencies from the
+ branch probabilities, rather than computing frequencies from counts,
+ which may also lead to frequencies incorrectly reduced to 0. There
+ is less precision in the probabilities, so we only do this for small
+ max counts. */
+ gcov_type count_max = 0;
+ basic_block bb;
+ FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
+ count_max = MAX (bb->count, count_max);
+
+ if (profile_status == PROFILE_GUESSED
+ || (profile_status == PROFILE_READ && count_max < REG_BR_PROB_BASE/10))
{
loop_optimizer_init (0);
add_noreturn_fake_exit_edges ();
mark_irreducible_loops ();
connect_infinite_loops_to_exit ();
- estimate_bb_frequencies ();
+ estimate_bb_frequencies (true);
remove_fake_exit_edges ();
loop_optimizer_finalize ();
}
diff --git a/gcc/predict.def b/gcc/predict.def
index 0006233da35..2ce135c0ce0 100644
--- a/gcc/predict.def
+++ b/gcc/predict.def
@@ -57,7 +57,10 @@ DEF_PREDICTOR (PRED_UNCONDITIONAL, "unconditional jump", PROB_ALWAYS,
DEF_PREDICTOR (PRED_LOOP_ITERATIONS, "loop iterations", PROB_ALWAYS,
PRED_FLAG_FIRST_MATCH)
-/* Hints dropped by user via __builtin_expect feature. */
+/* 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)
@@ -114,9 +117,6 @@ DEF_PREDICTOR (PRED_NEGATIVE_RETURN, "negative return", HITRATE (96), 0)
/* Branch ending with return; is probably not taken */
DEF_PREDICTOR (PRED_NULL_RETURN, "null return", HITRATE (90), 0)
-/* Branches to a mudflap bounds check are extremely unlikely. */
-DEF_PREDICTOR (PRED_MUDFLAP, "mudflap check", PROB_VERY_LIKELY, 0)
-
/* Branches to compare induction variable to a loop bound is
extremely likely. */
DEF_PREDICTOR (PRED_LOOP_IV_COMPARE_GUESS, "guess loop iv compare",
diff --git a/gcc/predict.h b/gcc/predict.h
index 559f803076e..02650e2d55c 100644
--- a/gcc/predict.h
+++ b/gcc/predict.h
@@ -37,7 +37,7 @@ enum prediction
extern void predict_insn_def (rtx, enum br_predictor, enum prediction);
extern int counts_to_freqs (void);
-extern void estimate_bb_frequencies (void);
+extern void estimate_bb_frequencies (bool);
extern const char *predictor_name (enum br_predictor);
extern tree build_predict_expr (enum br_predictor, enum prediction);
extern void tree_estimate_probability (void);
diff --git a/gcc/prefix.c b/gcc/prefix.c
index 058e19156c5..6092fbf1987 100644
--- a/gcc/prefix.c
+++ b/gcc/prefix.c
@@ -250,7 +250,7 @@ update_path (const char *path, const char *key)
const int len = strlen (std_prefix);
if (! filename_ncmp (path, std_prefix, len)
- && (IS_DIR_SEPARATOR(path[len])
+ && (IS_DIR_SEPARATOR (path[len])
|| path[len] == '\0')
&& key != 0)
{
diff --git a/gcc/pretty-print.c b/gcc/pretty-print.c
index 05f345ca2a8..8cec71b762a 100644
--- a/gcc/pretty-print.c
+++ b/gcc/pretty-print.c
@@ -773,7 +773,7 @@ pretty_printer::pretty_printer (const char *p, int l)
format_decoder (),
emitted_prefix (),
need_newline (),
- translate_identifiers(true),
+ translate_identifiers (true),
show_color ()
{
pp_line_cutoff (this) = l;
diff --git a/gcc/print-rtl.c b/gcc/print-rtl.c
index d2bda9ec84c..7d712c1562d 100644
--- a/gcc/print-rtl.c
+++ b/gcc/print-rtl.c
@@ -150,7 +150,8 @@ print_rtx (const_rtx in_rtx)
/* Print REG_NOTE names for EXPR_LIST and INSN_LIST. */
if ((GET_CODE (in_rtx) == EXPR_LIST
- || GET_CODE (in_rtx) == INSN_LIST)
+ || GET_CODE (in_rtx) == INSN_LIST
+ || GET_CODE (in_rtx) == INT_LIST)
&& (int)GET_MODE (in_rtx) < REG_NOTE_MAX)
fprintf (outfile, ":%s",
GET_REG_NOTE_NAME (GET_MODE (in_rtx)));
@@ -398,7 +399,8 @@ print_rtx (const_rtx in_rtx)
redundant with line number information and do not print anything
when there is no location information available. */
if (INSN_LOCATION (in_rtx) && insn_file (in_rtx))
- fprintf(outfile, " %s:%i", insn_file (in_rtx), insn_line (in_rtx));
+ fprintf (outfile, " %s:%i", insn_file (in_rtx),
+ insn_line (in_rtx));
#endif
}
else if (i == 6 && GET_CODE (in_rtx) == ASM_OPERANDS)
diff --git a/gcc/print-tree.c b/gcc/print-tree.c
index 22f007879db..5916c523f9d 100644
--- a/gcc/print-tree.c
+++ b/gcc/print-tree.c
@@ -28,7 +28,8 @@ along with GCC; see the file COPYING3. If not see
#include "tree-iterator.h"
#include "diagnostic.h"
#include "gimple-pretty-print.h" /* FIXME */
-#include "tree-ssa.h"
+#include "cgraph.h"
+#include "tree-cfg.h"
#include "tree-dump.h"
#include "dumpfile.h"
@@ -71,7 +72,7 @@ print_node_brief (FILE *file, const char *prefix, const_tree node, int indent)
name if any. */
if (indent > 0)
fprintf (file, " ");
- fprintf (file, "%s <%s", prefix, tree_code_name[(int) TREE_CODE (node)]);
+ fprintf (file, "%s <%s", prefix, get_tree_code_name (TREE_CODE (node)));
dump_addr (file, " ", node);
if (tclass == tcc_declaration)
@@ -247,7 +248,7 @@ print_node (FILE *file, const char *prefix, tree node, int indent)
indent_to (file, indent);
/* Print the slot this node is in, and its code, and address. */
- fprintf (file, "%s <%s", prefix, tree_code_name[(int) code]);
+ fprintf (file, "%s <%s", prefix, get_tree_code_name (code));
dump_addr (file, " ", node);
/* Print the name, if any. */
@@ -304,6 +305,8 @@ print_node (FILE *file, const char *prefix, tree node, int indent)
if (TYPE_P (node) ? TYPE_READONLY (node) : TREE_READONLY (node))
fputs (" readonly", file);
+ if (TYPE_P (node) && TYPE_ATOMIC (node))
+ fputs (" atomic", file);
if (!TYPE_P (node) && TREE_CONSTANT (node))
fputs (" constant", file);
else if (TYPE_P (node) && TYPE_SIZES_GIMPLIFIED (node))
@@ -818,7 +821,7 @@ print_node (FILE *file, const char *prefix, tree node, int indent)
if (ch >= ' ' && ch < 127)
putc (ch, file);
else
- fprintf(file, "\\%03o", ch & 0xFF);
+ fprintf (file, "\\%03o", ch & 0xFF);
}
fputc ('\"', file);
}
@@ -959,30 +962,6 @@ print_node (FILE *file, const char *prefix, tree node, int indent)
fprintf (file, ">");
}
-/* Print the tree vector VEC in full on file FILE, preceded by PREFIX,
- starting in column INDENT. */
-
-void
-print_vec_tree (FILE *file, const char *prefix, vec<tree, va_gc> *vec, int indent)
-{
- tree elt;
- unsigned ix;
-
- /* Indent to the specified column, since this is the long form. */
- indent_to (file, indent);
-
- /* Print the slot this node is in, and its code, and address. */
- fprintf (file, "%s <VEC", prefix);
- dump_addr (file, " ", vec->address ());
-
- FOR_EACH_VEC_ELT (*vec, ix, elt)
- {
- char temp[10];
- sprintf (temp, "elt %d", ix);
- print_node (file, temp, elt, indent + 4);
- }
-}
-
/* Print the node NODE on standard error, for debugging.
Most nodes referred to by this one are printed recursively
diff --git a/gcc/profile.c b/gcc/profile.c
index 94a3f07c6f3..9e50560830e 100644
--- a/gcc/profile.c
+++ b/gcc/profile.c
@@ -61,9 +61,11 @@ along with GCC; see the file COPYING3. If not see
#include "coverage.h"
#include "value-prof.h"
#include "tree.h"
-#include "tree-ssa.h"
+#include "gimple.h"
+#include "tree-cfg.h"
#include "cfgloop.h"
#include "dumpfile.h"
+#include "cgraph.h"
#include "profile.h"
@@ -187,6 +189,15 @@ instrument_values (histogram_values values)
gimple_gen_ior_profiler (hist, t, 0);
break;
+ case HIST_TYPE_TIME_PROFILE:
+ {
+ basic_block bb = split_edge (single_succ_edge (ENTRY_BLOCK_PTR));
+ gimple_stmt_iterator gsi = gsi_start_bb (bb);
+
+ gimple_gen_time_profiler (t, 0, gsi);
+ break;
+ }
+
default:
gcc_unreachable ();
}
@@ -275,11 +286,11 @@ get_exec_counts (unsigned cfg_checksum, unsigned lineno_checksum)
if (!counts)
return NULL;
- get_working_sets();
+ get_working_sets ();
if (dump_file && profile_info)
- fprintf(dump_file, "Merged %u profiles with maximal count %u.\n",
- profile_info->runs, (unsigned) profile_info->sum_max);
+ fprintf (dump_file, "Merged %u profiles with maximal count %u.\n",
+ profile_info->runs, (unsigned) profile_info->sum_max);
return counts;
}
@@ -849,6 +860,7 @@ compute_value_histograms (histogram_values values, unsigned cfg_checksum,
gcov_type *histogram_counts[GCOV_N_VALUE_COUNTERS];
gcov_type *act_count[GCOV_N_VALUE_COUNTERS];
gcov_type *aact_count;
+ struct cgraph_node *node;
for (t = 0; t < GCOV_N_VALUE_COUNTERS; t++)
n_histogram_counters[t] = 0;
@@ -887,6 +899,7 @@ compute_value_histograms (histogram_values values, unsigned cfg_checksum,
t = (int) hist->type;
aact_count = act_count[t];
+
if (act_count[t])
act_count[t] += hist->n_counters;
@@ -894,9 +907,22 @@ compute_value_histograms (histogram_values values, unsigned cfg_checksum,
hist->hvalue.counters = XNEWVEC (gcov_type, hist->n_counters);
for (j = 0; j < hist->n_counters; j++)
if (aact_count)
- hist->hvalue.counters[j] = aact_count[j];
- else
- hist->hvalue.counters[j] = 0;
+ hist->hvalue.counters[j] = aact_count[j];
+ else
+ hist->hvalue.counters[j] = 0;
+
+ /* Time profiler counter is not related to any statement,
+ so that we have to read the counter and set the value to
+ the corresponding call graph node. */
+ if (hist->type == HIST_TYPE_TIME_PROFILE)
+ {
+ node = cgraph_get_node (hist->fun->decl);
+
+ node->tp_first_run = hist->hvalue.counters[0];
+
+ if (dump_file)
+ fprintf (dump_file, "Read tp_first_run: %d\n", node->tp_first_run);
+ }
}
for (t = 0; t < GCOV_N_VALUE_COUNTERS; t++)
@@ -976,7 +1002,7 @@ branch_prob (void)
unsigned num_edges, ignored_edges;
unsigned num_instrumented;
struct edge_list *el;
- histogram_values values = histogram_values();
+ histogram_values values = histogram_values ();
unsigned cfg_checksum, lineno_checksum;
total_num_times_called++;
diff --git a/gcc/read-md.c b/gcc/read-md.c
index d32072be7a5..c108d51fd06 100644
--- a/gcc/read-md.c
+++ b/gcc/read-md.c
@@ -672,7 +672,7 @@ scan_comma_elt (const char **pstr)
if (*p == ',')
p++;
- while (ISSPACE(*p))
+ while (ISSPACE (*p))
p++;
if (*p == '\0')
diff --git a/gcc/real.c b/gcc/real.c
index b80aeac843f..b59be66af94 100644
--- a/gcc/real.c
+++ b/gcc/real.c
@@ -2855,7 +2855,7 @@ real_hash (const REAL_VALUE_TYPE *r)
gcc_unreachable ();
}
- if (sizeof(unsigned long) > sizeof(unsigned int))
+ if (sizeof (unsigned long) > sizeof (unsigned int))
for (i = 0; i < SIGSZ; ++i)
{
unsigned long s = r->sig[i];
diff --git a/gcc/real.h b/gcc/real.h
index 2ff84f6d295..b92453411d7 100644
--- a/gcc/real.h
+++ b/gcc/real.h
@@ -73,7 +73,7 @@ struct GTY(()) real_value {
/* Verify the guess. */
extern char test_real_width
- [sizeof(REAL_VALUE_TYPE) <= REAL_WIDTH*sizeof(HOST_WIDE_INT) ? 1 : -1];
+ [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
diff --git a/gcc/recog.c b/gcc/recog.c
index 690b20e4751..c8594bb5904 100644
--- a/gcc/recog.c
+++ b/gcc/recog.c
@@ -22,6 +22,7 @@ along with GCC; see the file COPYING3. If not see
#include "system.h"
#include "coretypes.h"
#include "tm.h"
+#include "tree.h"
#include "rtl-error.h"
#include "tm_p.h"
#include "insn-config.h"
@@ -725,7 +726,7 @@ validate_replace_rtx_1 (rtx *loc, rtx from, rtx to, rtx object,
/* Call ourself recursively to perform the replacements.
We must not replace inside already replaced expression, otherwise we
get infinite recursion for replacements like (reg X)->(subreg (reg X))
- done by regmove, so we must special case shared ASM_OPERANDS. */
+ so we must special case shared ASM_OPERANDS. */
if (GET_CODE (x) == PARALLEL)
{
@@ -761,6 +762,7 @@ validate_replace_rtx_1 (rtx *loc, rtx from, rtx to, rtx object,
if (num_changes == prev_changes)
return;
+ /* ??? The regmove is no more, so is this aberration still necessary? */
/* Allow substituted expression to have different mode. This is used by
regmove to change mode of pseudo register. */
if (fmt[0] == 'e' && GET_MODE (XEXP (x, 0)) != VOIDmode)
@@ -3068,6 +3070,9 @@ peep2_reg_dead_p (int ofs, rtx reg)
return 1;
}
+/* Regno offset to be used in the register search. */
+static int search_ofs;
+
/* Try to find a hard register of mode MODE, matching the register class in
CLASS_STR, which is available at the beginning of insn CURRENT_INSN and
remains available until the end of LAST_INSN. LAST_INSN may be NULL_RTX,
@@ -3083,7 +3088,6 @@ rtx
peep2_find_free_register (int from, int to, const char *class_str,
enum machine_mode mode, HARD_REG_SET *reg_set)
{
- static int search_ofs;
enum reg_class cl;
HARD_REG_SET live;
df_ref *def_rec;
@@ -3548,6 +3552,7 @@ peephole2_optimize (void)
/* Initialize the regsets we're going to use. */
for (i = 0; i < MAX_INSNS_PER_PEEP2 + 1; ++i)
peep2_insn_data[i].live_before = BITMAP_ALLOC (&reg_obstack);
+ search_ofs = 0;
live = BITMAP_ALLOC (&reg_obstack);
FOR_EACH_BB_REVERSE (bb)
@@ -3801,14 +3806,14 @@ const pass_data pass_data_peephole2 =
class pass_peephole2 : public rtl_opt_pass
{
public:
- pass_peephole2(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_peephole2, ctxt)
+ pass_peephole2 (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_peephole2, ctxt)
{}
/* opt_pass methods: */
/* The epiphany backend creates a second instance of this pass, so we need
a clone method. */
- opt_pass * clone () { return new pass_peephole2 (ctxt_); }
+ opt_pass * clone () { return new pass_peephole2 (m_ctxt); }
bool gate () { return gate_handle_peephole2 (); }
unsigned int execute () { return rest_of_handle_peephole2 (); }
@@ -3849,14 +3854,14 @@ const pass_data pass_data_split_all_insns =
class pass_split_all_insns : public rtl_opt_pass
{
public:
- pass_split_all_insns(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_split_all_insns, ctxt)
+ pass_split_all_insns (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_split_all_insns, ctxt)
{}
/* opt_pass methods: */
/* The epiphany backend creates a second instance of this pass, so
we need a clone method. */
- opt_pass * clone () { return new pass_split_all_insns (ctxt_); }
+ opt_pass * clone () { return new pass_split_all_insns (m_ctxt); }
unsigned int execute () { return rest_of_handle_split_all_insns (); }
}; // class pass_split_all_insns
@@ -3900,8 +3905,8 @@ const pass_data pass_data_split_after_reload =
class pass_split_after_reload : public rtl_opt_pass
{
public:
- pass_split_after_reload(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_split_after_reload, ctxt)
+ pass_split_after_reload (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_split_after_reload, ctxt)
{}
/* opt_pass methods: */
@@ -3962,8 +3967,8 @@ const pass_data pass_data_split_before_regstack =
class pass_split_before_regstack : public rtl_opt_pass
{
public:
- pass_split_before_regstack(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_split_before_regstack, ctxt)
+ pass_split_before_regstack (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_split_before_regstack, ctxt)
{}
/* opt_pass methods: */
@@ -4021,8 +4026,8 @@ const pass_data pass_data_split_before_sched2 =
class pass_split_before_sched2 : public rtl_opt_pass
{
public:
- pass_split_before_sched2(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_split_before_sched2, ctxt)
+ pass_split_before_sched2 (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_split_before_sched2, ctxt)
{}
/* opt_pass methods: */
@@ -4071,8 +4076,8 @@ const pass_data pass_data_split_for_shorten_branches =
class pass_split_for_shorten_branches : public rtl_opt_pass
{
public:
- pass_split_for_shorten_branches(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_split_for_shorten_branches, ctxt)
+ pass_split_for_shorten_branches (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_split_for_shorten_branches, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/ree.c b/gcc/ree.c
index 541bdb5a131..fa05feed749 100644
--- a/gcc/ree.c
+++ b/gcc/ree.c
@@ -800,7 +800,7 @@ add_removable_extension (const_rtx expr, rtx insn,
/* Second, make sure the reaching definitions don't feed another and
different extension. FIXME: this obviously can be improved. */
for (def = defs; def; def = def->next)
- if ((idx = def_map[INSN_UID(DF_REF_INSN (def->ref))])
+ if ((idx = def_map[INSN_UID (DF_REF_INSN (def->ref))])
&& (cand = &(*insn_list)[idx - 1])
&& cand->code != code)
{
@@ -820,7 +820,7 @@ add_removable_extension (const_rtx expr, rtx insn,
idx = insn_list->length ();
for (def = defs; def; def = def->next)
- def_map[INSN_UID(DF_REF_INSN (def->ref))] = idx;
+ def_map[INSN_UID (DF_REF_INSN (def->ref))] = idx;
}
}
@@ -961,8 +961,8 @@ const pass_data pass_data_ree =
class pass_ree : public rtl_opt_pass
{
public:
- pass_ree(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_ree, ctxt)
+ pass_ree (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_ree, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/reg-notes.def b/gcc/reg-notes.def
index 3b1d27ca8a7..fd7e337c2d6 100644
--- a/gcc/reg-notes.def
+++ b/gcc/reg-notes.def
@@ -18,9 +18,9 @@ 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 rtxes in the REG_NOTES chain of an insn. The codes are
- stored in the mode field of the EXPR_LIST. Source files define
- DEF_REG_NOTE appropriately before including this file. */
+ 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. */
/* Shorthand. */
#define REG_NOTE(NAME) DEF_REG_NOTE (REG_##NAME)
@@ -94,9 +94,9 @@ REG_NOTE (DEP_ANTI)
REG_NOTE (DEP_CONTROL)
/* REG_BR_PROB is attached to JUMP_INSNs and CALL_INSNs. It has an
- integer value. For jumps, it is the probability that this is a
- taken branch. For calls, it is the probability that this call
- won't return. */
+ integer value (in an INT_LIST). For jumps, it is the probability
+ that this is a taken branch. For calls, it is the probability that
+ this call won't return. */
REG_NOTE (BR_PROB)
/* Attached to a call insn; indicates that the call is malloc-like and
diff --git a/gcc/reg-stack.c b/gcc/reg-stack.c
index b3574e66d17..1917c46fe96 100644
--- a/gcc/reg-stack.c
+++ b/gcc/reg-stack.c
@@ -253,7 +253,7 @@ static void replace_reg (rtx *, int);
static void remove_regno_note (rtx, enum reg_note, unsigned int);
static int get_hard_regnum (stack_ptr, rtx);
static rtx emit_pop_insn (rtx, stack_ptr, rtx, enum emit_where);
-static void swap_to_top(rtx, stack_ptr, rtx, rtx);
+static void swap_to_top (rtx, stack_ptr, rtx, rtx);
static bool move_for_stack_reg (rtx, stack_ptr, rtx);
static bool move_nan_for_stack_reg (rtx, stack_ptr, rtx);
static int swap_rtx_condition_1 (rtx);
@@ -2058,6 +2058,8 @@ subst_asm_stack_regs (rtx insn, stack_ptr regstack)
n_notes = 0;
for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
{
+ if (GET_CODE (note) != EXPR_LIST)
+ continue;
rtx reg = XEXP (note, 0);
rtx *loc = & XEXP (note, 0);
@@ -3312,8 +3314,8 @@ const pass_data pass_data_stack_regs =
class pass_stack_regs : public rtl_opt_pass
{
public:
- pass_stack_regs(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_stack_regs, ctxt)
+ pass_stack_regs (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_stack_regs, ctxt)
{}
/* opt_pass methods: */
@@ -3361,8 +3363,8 @@ const pass_data pass_data_stack_regs_run =
class pass_stack_regs_run : public rtl_opt_pass
{
public:
- pass_stack_regs_run(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_stack_regs_run, ctxt)
+ pass_stack_regs_run (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_stack_regs_run, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/regcprop.c b/gcc/regcprop.c
index 19f33495170..0fa0afbc824 100644
--- a/gcc/regcprop.c
+++ b/gcc/regcprop.c
@@ -1256,8 +1256,8 @@ const pass_data pass_data_cprop_hardreg =
class pass_cprop_hardreg : public rtl_opt_pass
{
public:
- pass_cprop_hardreg(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_cprop_hardreg, ctxt)
+ pass_cprop_hardreg (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_cprop_hardreg, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/reginfo.c b/gcc/reginfo.c
index 49a7a5864e2..db66a095765 100644
--- a/gcc/reginfo.c
+++ b/gcc/reginfo.c
@@ -30,6 +30,7 @@ along with GCC; see the file COPYING3. If not see
#include "coretypes.h"
#include "tm.h"
#include "hard-reg-set.h"
+#include "tree.h"
#include "rtl.h"
#include "expr.h"
#include "tm_p.h"
@@ -447,7 +448,7 @@ init_reg_sets_1 (void)
}
}
- COPY_HARD_REG_SET(call_fixed_reg_set, fixed_reg_set);
+ COPY_HARD_REG_SET (call_fixed_reg_set, fixed_reg_set);
/* Preserve global registers if called more than once. */
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
@@ -495,7 +496,7 @@ init_reg_modes_target (void)
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
for (j = 0; j < MAX_MACHINE_MODE; j++)
- hard_regno_nregs[i][j] = HARD_REGNO_NREGS(i, (enum machine_mode)j);
+ hard_regno_nregs[i][j] = HARD_REGNO_NREGS (i, (enum machine_mode)j);
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
{
@@ -980,8 +981,8 @@ const pass_data pass_data_reginfo_init =
class pass_reginfo_init : public rtl_opt_pass
{
public:
- pass_reginfo_init(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_reginfo_init, ctxt)
+ pass_reginfo_init (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_reginfo_init, ctxt)
{}
/* opt_pass methods: */
@@ -1075,6 +1076,7 @@ reg_scan_mark_refs (rtx x, rtx insn)
break;
case INSN_LIST:
+ case INT_LIST:
if (XEXP (x, 1))
reg_scan_mark_refs (XEXP (x, 1), insn);
break;
diff --git a/gcc/regmove.c b/gcc/regmove.c
deleted file mode 100644
index e579a7a234d..00000000000
--- a/gcc/regmove.c
+++ /dev/null
@@ -1,1401 +0,0 @@
-/* Move registers around to reduce number of move instructions needed.
- Copyright (C) 1987-2013 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 module makes some simple RTL code transformations which
- improve the subsequent register allocation. */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "tm.h"
-#include "rtl.h"
-#include "tm_p.h"
-#include "insn-config.h"
-#include "recog.h"
-#include "target.h"
-#include "regs.h"
-#include "hard-reg-set.h"
-#include "flags.h"
-#include "function.h"
-#include "expr.h"
-#include "basic-block.h"
-#include "except.h"
-#include "diagnostic-core.h"
-#include "reload.h"
-#include "tree-pass.h"
-#include "df.h"
-#include "ira.h"
-
-static int optimize_reg_copy_1 (rtx, rtx, rtx);
-static void optimize_reg_copy_2 (rtx, rtx, rtx);
-static void optimize_reg_copy_3 (rtx, rtx, rtx);
-static void copy_src_to_dest (rtx, rtx, rtx);
-
-enum match_use
-{
- READ,
- WRITE,
- READWRITE
-};
-
-struct match {
- int with[MAX_RECOG_OPERANDS];
- enum match_use use[MAX_RECOG_OPERANDS];
- int commutative[MAX_RECOG_OPERANDS];
- int early_clobber[MAX_RECOG_OPERANDS];
-};
-
-static int find_matches (rtx, struct match *);
-static int fixup_match_2 (rtx, rtx, rtx, rtx);
-
-/* Return nonzero if registers with CLASS1 and CLASS2 can be merged without
- causing too much register allocation problems. */
-static int
-regclass_compatible_p (reg_class_t class0, reg_class_t class1)
-{
- return (class0 == class1
- || (reg_class_subset_p (class0, class1)
- && ! targetm.class_likely_spilled_p (class0))
- || (reg_class_subset_p (class1, class0)
- && ! targetm.class_likely_spilled_p (class1)));
-}
-
-
-#ifdef AUTO_INC_DEC
-
-/* Find the place in the rtx X where REG is used as a memory address.
- Return the MEM rtx that so uses it.
- If PLUSCONST is nonzero, search instead for a memory address equivalent to
- (plus REG (const_int PLUSCONST)).
-
- If such an address does not appear, return 0.
- If REG appears more than once, or is used other than in such an address,
- return (rtx) 1. */
-
-static rtx
-find_use_as_address (rtx x, rtx reg, HOST_WIDE_INT plusconst)
-{
- enum rtx_code code = GET_CODE (x);
- const char * const fmt = GET_RTX_FORMAT (code);
- int i;
- rtx value = 0;
- rtx tem;
-
- if (code == MEM && XEXP (x, 0) == reg && plusconst == 0)
- return x;
-
- if (code == MEM && GET_CODE (XEXP (x, 0)) == PLUS
- && XEXP (XEXP (x, 0), 0) == reg
- && CONST_INT_P (XEXP (XEXP (x, 0), 1))
- && INTVAL (XEXP (XEXP (x, 0), 1)) == plusconst)
- return x;
-
- if (code == SIGN_EXTRACT || code == ZERO_EXTRACT)
- {
- /* If REG occurs inside a MEM used in a bit-field reference,
- that is unacceptable. */
- if (find_use_as_address (XEXP (x, 0), reg, 0) != 0)
- return (rtx) (size_t) 1;
- }
-
- if (x == reg)
- return (rtx) (size_t) 1;
-
- for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
- {
- if (fmt[i] == 'e')
- {
- tem = find_use_as_address (XEXP (x, i), reg, plusconst);
- if (value == 0)
- value = tem;
- else if (tem != 0)
- return (rtx) (size_t) 1;
- }
- else if (fmt[i] == 'E')
- {
- int j;
- for (j = XVECLEN (x, i) - 1; j >= 0; j--)
- {
- tem = find_use_as_address (XVECEXP (x, i, j), reg, plusconst);
- if (value == 0)
- value = tem;
- else if (tem != 0)
- return (rtx) (size_t) 1;
- }
- }
- }
-
- return value;
-}
-
-
-/* INC_INSN is an instruction that adds INCREMENT to REG.
- Try to fold INC_INSN as a post/pre in/decrement into INSN.
- Iff INC_INSN_SET is nonzero, inc_insn has a destination different from src.
- Return nonzero for success. */
-static int
-try_auto_increment (rtx insn, rtx inc_insn, rtx inc_insn_set, rtx reg,
- HOST_WIDE_INT increment, int pre)
-{
- enum rtx_code inc_code;
-
- rtx pset = single_set (insn);
- if (pset)
- {
- /* Can't use the size of SET_SRC, we might have something like
- (sign_extend:SI (mem:QI ... */
- rtx use = find_use_as_address (pset, reg, 0);
- if (use != 0 && use != (rtx) (size_t) 1)
- {
- int size = GET_MODE_SIZE (GET_MODE (use));
- if (0
- || (HAVE_POST_INCREMENT
- && pre == 0 && (inc_code = POST_INC, increment == size))
- || (HAVE_PRE_INCREMENT
- && pre == 1 && (inc_code = PRE_INC, increment == size))
- || (HAVE_POST_DECREMENT
- && pre == 0 && (inc_code = POST_DEC, increment == -size))
- || (HAVE_PRE_DECREMENT
- && pre == 1 && (inc_code = PRE_DEC, increment == -size))
- )
- {
- if (inc_insn_set)
- validate_change
- (inc_insn,
- &SET_SRC (inc_insn_set),
- XEXP (SET_SRC (inc_insn_set), 0), 1);
- validate_change (insn, &XEXP (use, 0),
- gen_rtx_fmt_e (inc_code,
- GET_MODE (XEXP (use, 0)), reg),
- 1);
- if (apply_change_group ())
- {
- /* If there is a REG_DEAD note on this insn, we must
- change this not to REG_UNUSED meaning that the register
- is set, but the value is dead. Failure to do so will
- result in sched1 dying -- when it recomputes lifetime
- information, the number of REG_DEAD notes will have
- changed. */
- rtx note = find_reg_note (insn, REG_DEAD, reg);
- if (note)
- PUT_REG_NOTE_KIND (note, REG_UNUSED);
-
- add_reg_note (insn, REG_INC, reg);
-
- if (! inc_insn_set)
- delete_insn (inc_insn);
- return 1;
- }
- }
- }
- }
- return 0;
-}
-#endif
-
-
-static int *regno_src_regno;
-
-/* INSN is a copy from SRC to DEST, both registers, and SRC does not die
- in INSN.
-
- Search forward to see if SRC dies before either it or DEST is modified,
- but don't scan past the end of a basic block. If so, we can replace SRC
- with DEST and let SRC die in INSN.
-
- This will reduce the number of registers live in that range and may enable
- DEST to be tied to SRC, thus often saving one register in addition to a
- register-register copy. */
-
-static int
-optimize_reg_copy_1 (rtx insn, rtx dest, rtx src)
-{
- rtx p, q;
- rtx note;
- rtx dest_death = 0;
- int sregno = REGNO (src);
- int dregno = REGNO (dest);
- basic_block bb = BLOCK_FOR_INSN (insn);
-
- /* We don't want to mess with hard regs if register classes are small. */
- if (sregno == dregno
- || (targetm.small_register_classes_for_mode_p (GET_MODE (src))
- && (sregno < FIRST_PSEUDO_REGISTER
- || dregno < FIRST_PSEUDO_REGISTER))
- /* We don't see all updates to SP if they are in an auto-inc memory
- reference, so we must disallow this optimization on them. */
- || sregno == STACK_POINTER_REGNUM || dregno == STACK_POINTER_REGNUM)
- return 0;
-
- for (p = NEXT_INSN (insn); p; p = NEXT_INSN (p))
- {
- if (! INSN_P (p))
- continue;
- if (BLOCK_FOR_INSN (p) != bb)
- break;
-
- if (reg_set_p (src, p) || reg_set_p (dest, p)
- /* If SRC is an asm-declared register, it must not be replaced
- in any asm. Unfortunately, the REG_EXPR tree for the asm
- variable may be absent in the SRC rtx, so we can't check the
- actual register declaration easily (the asm operand will have
- it, though). To avoid complicating the test for a rare case,
- we just don't perform register replacement for a hard reg
- mentioned in an asm. */
- || (sregno < FIRST_PSEUDO_REGISTER
- && asm_noperands (PATTERN (p)) >= 0
- && reg_overlap_mentioned_p (src, PATTERN (p)))
- /* Don't change hard registers used by a call. */
- || (CALL_P (p) && sregno < FIRST_PSEUDO_REGISTER
- && find_reg_fusage (p, USE, src))
- /* Don't change a USE of a register. */
- || (GET_CODE (PATTERN (p)) == USE
- && reg_overlap_mentioned_p (src, XEXP (PATTERN (p), 0))))
- break;
-
- /* See if all of SRC dies in P. This test is slightly more
- conservative than it needs to be. */
- if ((note = find_regno_note (p, REG_DEAD, sregno)) != 0
- && GET_MODE (XEXP (note, 0)) == GET_MODE (src))
- {
- int failed = 0;
- int d_length = 0;
- int s_length = 0;
- int d_n_calls = 0;
- int s_n_calls = 0;
- int s_freq_calls = 0;
- int d_freq_calls = 0;
-
- /* We can do the optimization. Scan forward from INSN again,
- replacing regs as we go. Set FAILED if a replacement can't
- be done. In that case, we can't move the death note for SRC.
- This should be rare. */
-
- /* Set to stop at next insn. */
- for (q = next_real_insn (insn);
- q != next_real_insn (p);
- q = next_real_insn (q))
- {
- if (reg_overlap_mentioned_p (src, PATTERN (q)))
- {
- /* If SRC is a hard register, we might miss some
- overlapping registers with validate_replace_rtx,
- so we would have to undo it. We can't if DEST is
- present in the insn, so fail in that combination
- of cases. */
- if (sregno < FIRST_PSEUDO_REGISTER
- && reg_mentioned_p (dest, PATTERN (q)))
- failed = 1;
-
- /* Attempt to replace all uses. */
- else if (!validate_replace_rtx (src, dest, q))
- failed = 1;
-
- /* If this succeeded, but some part of the register
- is still present, undo the replacement. */
- else if (sregno < FIRST_PSEUDO_REGISTER
- && reg_overlap_mentioned_p (src, PATTERN (q)))
- {
- validate_replace_rtx (dest, src, q);
- failed = 1;
- }
- }
-
- /* For SREGNO, count the total number of insns scanned.
- For DREGNO, count the total number of insns scanned after
- passing the death note for DREGNO. */
- if (!DEBUG_INSN_P (p))
- {
- s_length++;
- if (dest_death)
- d_length++;
- }
-
- /* If the insn in which SRC dies is a CALL_INSN, don't count it
- as a call that has been crossed. Otherwise, count it. */
- if (q != p && CALL_P (q))
- {
- /* Similarly, total calls for SREGNO, total calls beyond
- the death note for DREGNO. */
- s_n_calls++;
- s_freq_calls += REG_FREQ_FROM_BB (BLOCK_FOR_INSN (q));
- if (dest_death)
- {
- d_n_calls++;
- d_freq_calls += REG_FREQ_FROM_BB (BLOCK_FOR_INSN (q));
- }
- }
-
- /* If DEST dies here, remove the death note and save it for
- later. Make sure ALL of DEST dies here; again, this is
- overly conservative. */
- if (dest_death == 0
- && (dest_death = find_regno_note (q, REG_DEAD, dregno)) != 0)
- {
- if (GET_MODE (XEXP (dest_death, 0)) != GET_MODE (dest))
- failed = 1, dest_death = 0;
- else
- remove_note (q, dest_death);
- }
- }
-
- if (! failed)
- {
- /* These counters need to be updated if and only if we are
- going to move the REG_DEAD note. */
- if (sregno >= FIRST_PSEUDO_REGISTER)
- {
- if (REG_LIVE_LENGTH (sregno) >= 0)
- {
- REG_LIVE_LENGTH (sregno) -= s_length;
- /* REG_LIVE_LENGTH is only an approximation after
- combine if sched is not run, so make sure that we
- still have a reasonable value. */
- if (REG_LIVE_LENGTH (sregno) < 2)
- REG_LIVE_LENGTH (sregno) = 2;
- }
-
- REG_N_CALLS_CROSSED (sregno) -= s_n_calls;
- REG_FREQ_CALLS_CROSSED (sregno) -= s_freq_calls;
- }
-
- /* Move death note of SRC from P to INSN. */
- remove_note (p, note);
- XEXP (note, 1) = REG_NOTES (insn);
- REG_NOTES (insn) = note;
- }
-
- /* DEST is also dead if INSN has a REG_UNUSED note for DEST. */
- if (! dest_death
- && (dest_death = find_regno_note (insn, REG_UNUSED, dregno)))
- {
- PUT_REG_NOTE_KIND (dest_death, REG_DEAD);
- remove_note (insn, dest_death);
- }
-
- /* Put death note of DEST on P if we saw it die. */
- if (dest_death)
- {
- XEXP (dest_death, 1) = REG_NOTES (p);
- REG_NOTES (p) = dest_death;
-
- if (dregno >= FIRST_PSEUDO_REGISTER)
- {
- /* If and only if we are moving the death note for DREGNO,
- then we need to update its counters. */
- if (REG_LIVE_LENGTH (dregno) >= 0)
- REG_LIVE_LENGTH (dregno) += d_length;
- REG_N_CALLS_CROSSED (dregno) += d_n_calls;
- REG_FREQ_CALLS_CROSSED (dregno) += d_freq_calls;
- }
- }
-
- return ! failed;
- }
-
- /* If SRC is a hard register which is set or killed in some other
- way, we can't do this optimization. */
- else if (sregno < FIRST_PSEUDO_REGISTER
- && dead_or_set_p (p, src))
- break;
- }
- return 0;
-}
-
-/* INSN is a copy of SRC to DEST, in which SRC dies. See if we now have
- a sequence of insns that modify DEST followed by an insn that sets
- SRC to DEST in which DEST dies, with no prior modification of DEST.
- (There is no need to check if the insns in between actually modify
- DEST. We should not have cases where DEST is not modified, but
- the optimization is safe if no such modification is detected.)
- In that case, we can replace all uses of DEST, starting with INSN and
- ending with the set of SRC to DEST, with SRC. We do not do this
- optimization if a CALL_INSN is crossed unless SRC already crosses a
- call or if DEST dies before the copy back to SRC.
-
- It is assumed that DEST and SRC are pseudos; it is too complicated to do
- this for hard registers since the substitutions we may make might fail. */
-
-static void
-optimize_reg_copy_2 (rtx insn, rtx dest, rtx src)
-{
- rtx p, q;
- rtx set;
- int sregno = REGNO (src);
- int dregno = REGNO (dest);
- basic_block bb = BLOCK_FOR_INSN (insn);
-
- for (p = NEXT_INSN (insn); p; p = NEXT_INSN (p))
- {
- if (! INSN_P (p))
- continue;
- if (BLOCK_FOR_INSN (p) != bb)
- break;
-
- set = single_set (p);
- if (set && SET_SRC (set) == dest && SET_DEST (set) == src
- && find_reg_note (p, REG_DEAD, dest))
- {
- /* We can do the optimization. Scan forward from INSN again,
- replacing regs as we go. */
-
- /* Set to stop at next insn. */
- for (q = insn; q != NEXT_INSN (p); q = NEXT_INSN (q))
- if (INSN_P (q))
- {
- if (reg_mentioned_p (dest, PATTERN (q)))
- {
- rtx note;
-
- PATTERN (q) = replace_rtx (PATTERN (q), dest, src);
- note = FIND_REG_INC_NOTE (q, dest);
- if (note)
- {
- remove_note (q, note);
- add_reg_note (q, REG_INC, src);
- }
- df_insn_rescan (q);
- }
-
- if (CALL_P (q))
- {
- int freq = REG_FREQ_FROM_BB (BLOCK_FOR_INSN (q));
- REG_N_CALLS_CROSSED (dregno)--;
- REG_N_CALLS_CROSSED (sregno)++;
- REG_FREQ_CALLS_CROSSED (dregno) -= freq;
- REG_FREQ_CALLS_CROSSED (sregno) += freq;
- }
- }
-
- remove_note (p, find_reg_note (p, REG_DEAD, dest));
- REG_N_DEATHS (dregno)--;
- remove_note (insn, find_reg_note (insn, REG_DEAD, src));
- REG_N_DEATHS (sregno)--;
- return;
- }
-
- if (reg_set_p (src, p)
- || find_reg_note (p, REG_DEAD, dest)
- || (CALL_P (p) && REG_N_CALLS_CROSSED (sregno) == 0))
- break;
- }
-}
-
-/* INSN is a ZERO_EXTEND or SIGN_EXTEND of SRC to DEST.
- Look if SRC dies there, and if it is only set once, by loading
- it from memory. If so, try to incorporate the zero/sign extension
- into the memory read, change SRC to the mode of DEST, and alter
- the remaining accesses to use the appropriate SUBREG. This allows
- SRC and DEST to be tied later. */
-static void
-optimize_reg_copy_3 (rtx insn, rtx dest, rtx src)
-{
- rtx src_reg = XEXP (src, 0);
- int src_no = REGNO (src_reg);
- int dst_no = REGNO (dest);
- rtx p, set, set_insn;
- enum machine_mode old_mode;
- basic_block bb = BLOCK_FOR_INSN (insn);
-
- if (src_no < FIRST_PSEUDO_REGISTER
- || dst_no < FIRST_PSEUDO_REGISTER
- || ! find_reg_note (insn, REG_DEAD, src_reg)
- || REG_N_DEATHS (src_no) != 1
- || REG_N_SETS (src_no) != 1)
- return;
-
- for (p = PREV_INSN (insn); p && ! reg_set_p (src_reg, p); p = PREV_INSN (p))
- if (INSN_P (p) && BLOCK_FOR_INSN (p) != bb)
- break;
-
- if (! p || BLOCK_FOR_INSN (p) != bb)
- return;
-
- if (! (set = single_set (p))
- || !MEM_P (SET_SRC (set))
- /* If there's a REG_EQUIV note, this must be an insn that loads an
- argument. Prefer keeping the note over doing this optimization. */
- || find_reg_note (p, REG_EQUIV, NULL_RTX)
- || SET_DEST (set) != src_reg)
- return;
-
- /* Be conservative: although this optimization is also valid for
- volatile memory references, that could cause trouble in later passes. */
- if (MEM_VOLATILE_P (SET_SRC (set)))
- return;
-
- /* Do not use a SUBREG to truncate from one mode to another if truncation
- is not a nop. */
- if (GET_MODE_BITSIZE (GET_MODE (src_reg)) <= GET_MODE_BITSIZE (GET_MODE (src))
- && !TRULY_NOOP_TRUNCATION_MODES_P (GET_MODE (src), GET_MODE (src_reg)))
- return;
-
- set_insn = p;
- old_mode = GET_MODE (src_reg);
- PUT_MODE (src_reg, GET_MODE (src));
- XEXP (src, 0) = SET_SRC (set);
-
- /* Include this change in the group so that it's easily undone if
- one of the changes in the group is invalid. */
- validate_change (p, &SET_SRC (set), src, 1);
-
- /* Now walk forward making additional replacements. We want to be able
- to undo all the changes if a later substitution fails. */
- while (p = NEXT_INSN (p), p != insn)
- {
- if (! INSN_P (p))
- continue;
-
- /* Make a tentative change. */
- validate_replace_rtx_group (src_reg,
- gen_lowpart_SUBREG (old_mode, src_reg),
- p);
- }
-
- validate_replace_rtx_group (src, src_reg, insn);
-
- /* Now see if all the changes are valid. */
- if (! apply_change_group ())
- {
- /* One or more changes were no good. Back out everything. */
- PUT_MODE (src_reg, old_mode);
- XEXP (src, 0) = src_reg;
- }
- else
- {
- rtx note = find_reg_note (set_insn, REG_EQUAL, NULL_RTX);
- if (note)
- {
- if (rtx_equal_p (XEXP (note, 0), XEXP (src, 0)))
- {
- XEXP (note, 0)
- = gen_rtx_fmt_e (GET_CODE (src), GET_MODE (src),
- XEXP (note, 0));
- df_notes_rescan (set_insn);
- }
- else
- remove_note (set_insn, note);
- }
- }
-}
-
-
-/* If we were not able to update the users of src to use dest directly, try
- instead moving the value to dest directly before the operation. */
-
-static void
-copy_src_to_dest (rtx insn, rtx src, rtx dest)
-{
- rtx seq;
- rtx link;
- rtx next;
- rtx set;
- rtx move_insn;
- rtx *p_insn_notes;
- rtx *p_move_notes;
- int src_regno;
- int dest_regno;
-
- /* A REG_LIVE_LENGTH of -1 indicates the register must not go into
- a hard register, e.g. because it crosses as setjmp. See the
- comment in regstat.c:regstat_bb_compute_ri. Don't try to apply
- any transformations to such regs. */
-
- if (REG_P (src)
- && REG_LIVE_LENGTH (REGNO (src)) > 0
- && REG_P (dest)
- && REG_LIVE_LENGTH (REGNO (dest)) > 0
- && (set = single_set (insn)) != NULL_RTX
- && !reg_mentioned_p (dest, SET_SRC (set))
- && GET_MODE (src) == GET_MODE (dest))
- {
- int old_num_regs = reg_rtx_no;
-
- /* Generate the src->dest move. */
- start_sequence ();
- emit_move_insn (dest, src);
- seq = get_insns ();
- end_sequence ();
- /* If this sequence uses new registers, we may not use it. */
- if (old_num_regs != reg_rtx_no
- || ! validate_replace_rtx (src, dest, insn))
- {
- /* We have to restore reg_rtx_no to its old value, lest
- recompute_reg_usage will try to compute the usage of the
- new regs, yet reg_n_info is not valid for them. */
- reg_rtx_no = old_num_regs;
- return;
- }
- emit_insn_before (seq, insn);
- move_insn = PREV_INSN (insn);
- p_move_notes = &REG_NOTES (move_insn);
- p_insn_notes = &REG_NOTES (insn);
-
- /* Move any notes mentioning src to the move instruction. */
- for (link = REG_NOTES (insn); link != NULL_RTX; link = next)
- {
- next = XEXP (link, 1);
- if (XEXP (link, 0) == src)
- {
- *p_move_notes = link;
- p_move_notes = &XEXP (link, 1);
- }
- else
- {
- *p_insn_notes = link;
- p_insn_notes = &XEXP (link, 1);
- }
- }
-
- *p_move_notes = NULL_RTX;
- *p_insn_notes = NULL_RTX;
-
- /* Update the various register tables. */
- dest_regno = REGNO (dest);
- INC_REG_N_SETS (dest_regno, 1);
- REG_LIVE_LENGTH (dest_regno)++;
- src_regno = REGNO (src);
- if (! find_reg_note (move_insn, REG_DEAD, src))
- REG_LIVE_LENGTH (src_regno)++;
- }
-}
-
-/* reg_set_in_bb[REGNO] points to basic block iff the register is set
- only once in the given block and has REG_EQUAL note. */
-
-static basic_block *reg_set_in_bb;
-
-/* Size of reg_set_in_bb array. */
-static unsigned int max_reg_computed;
-
-
-/* Return whether REG is set in only one location, and is set to a
- constant, but is set in a different basic block from INSN (an
- instructions which uses REG). In this case REG is equivalent to a
- constant, and we don't want to break that equivalence, because that
- may increase register pressure and make reload harder. If REG is
- set in the same basic block as INSN, we don't worry about it,
- because we'll probably need a register anyhow (??? but what if REG
- is used in a different basic block as well as this one?). */
-
-static bool
-reg_is_remote_constant_p (rtx reg, rtx insn)
-{
- basic_block bb;
- rtx p;
- int max;
-
- if (!reg_set_in_bb)
- {
- max_reg_computed = max = max_reg_num ();
- reg_set_in_bb = XCNEWVEC (basic_block, max);
-
- FOR_EACH_BB (bb)
- FOR_BB_INSNS (bb, p)
- {
- rtx s;
-
- if (!INSN_P (p))
- continue;
- s = single_set (p);
- /* This is the instruction which sets REG. If there is a
- REG_EQUAL note, then REG is equivalent to a constant. */
- if (s != 0
- && REG_P (SET_DEST (s))
- && REG_N_SETS (REGNO (SET_DEST (s))) == 1
- && find_reg_note (p, REG_EQUAL, NULL_RTX))
- reg_set_in_bb[REGNO (SET_DEST (s))] = bb;
- }
- }
-
- gcc_assert (REGNO (reg) < max_reg_computed);
- if (reg_set_in_bb[REGNO (reg)] == NULL)
- return false;
- return (reg_set_in_bb[REGNO (reg)] != BLOCK_FOR_INSN (insn));
-}
-
-/* INSN is adding a CONST_INT to a REG. We search backwards looking for
- another add immediate instruction with the same source and dest registers,
- and if we find one, we change INSN to an increment, and return 1. If
- no changes are made, we return 0.
-
- This changes
- (set (reg100) (plus reg1 offset1))
- ...
- (set (reg100) (plus reg1 offset2))
- to
- (set (reg100) (plus reg1 offset1))
- ...
- (set (reg100) (plus reg100 offset2-offset1)) */
-
-/* ??? What does this comment mean? */
-/* cse disrupts preincrement / postdecrement sequences when it finds a
- hard register as ultimate source, like the frame pointer. */
-
-static int
-fixup_match_2 (rtx insn, rtx dst, rtx src, rtx offset)
-{
- rtx p, dst_death = 0;
- int length, num_calls = 0, freq_calls = 0;
- basic_block bb = BLOCK_FOR_INSN (insn);
-
- /* If SRC dies in INSN, we'd have to move the death note. This is
- considered to be very unlikely, so we just skip the optimization
- in this case. */
- if (find_regno_note (insn, REG_DEAD, REGNO (src)))
- return 0;
-
- /* Scan backward to find the first instruction that sets DST. */
-
- for (length = 0, p = PREV_INSN (insn); p; p = PREV_INSN (p))
- {
- rtx pset;
-
- if (! INSN_P (p))
- continue;
- if (BLOCK_FOR_INSN (p) != bb)
- break;
-
- if (find_regno_note (p, REG_DEAD, REGNO (dst)))
- dst_death = p;
- if (! dst_death && !DEBUG_INSN_P (p))
- length++;
-
- pset = single_set (p);
- if (pset && SET_DEST (pset) == dst
- && GET_CODE (SET_SRC (pset)) == PLUS
- && XEXP (SET_SRC (pset), 0) == src
- && CONST_INT_P (XEXP (SET_SRC (pset), 1)))
- {
- HOST_WIDE_INT newconst
- = INTVAL (offset) - INTVAL (XEXP (SET_SRC (pset), 1));
- rtx add = gen_add3_insn (dst, dst,
- gen_int_mode (newconst, GET_MODE (dst)));
-
- if (add && validate_change (insn, &PATTERN (insn), add, 0))
- {
- /* Remove the death note for DST from DST_DEATH. */
- if (dst_death)
- {
- remove_death (REGNO (dst), dst_death);
- REG_LIVE_LENGTH (REGNO (dst)) += length;
- REG_N_CALLS_CROSSED (REGNO (dst)) += num_calls;
- REG_FREQ_CALLS_CROSSED (REGNO (dst)) += freq_calls;
- }
-
- if (dump_file)
- fprintf (dump_file,
- "Fixed operand of insn %d.\n",
- INSN_UID (insn));
-
-#ifdef AUTO_INC_DEC
- for (p = PREV_INSN (insn); p; p = PREV_INSN (p))
- {
- if (! INSN_P (p))
- continue;
- if (BLOCK_FOR_INSN (p) != bb)
- break;
- if (reg_overlap_mentioned_p (dst, PATTERN (p)))
- {
- if (try_auto_increment (p, insn, 0, dst, newconst, 0))
- return 1;
- break;
- }
- }
- for (p = NEXT_INSN (insn); p; p = NEXT_INSN (p))
- {
- if (! INSN_P (p))
- continue;
- if (BLOCK_FOR_INSN (p) != bb)
- break;
- if (reg_overlap_mentioned_p (dst, PATTERN (p)))
- {
- try_auto_increment (p, insn, 0, dst, newconst, 1);
- break;
- }
- }
-#endif
- return 1;
- }
- }
-
- if (reg_set_p (dst, PATTERN (p)))
- break;
-
- /* If we have passed a call instruction, and the
- pseudo-reg SRC is not already live across a call,
- then don't perform the optimization. */
- /* reg_set_p is overly conservative for CALL_INSNS, thinks that all
- hard regs are clobbered. Thus, we only use it for src for
- non-call insns. */
- if (CALL_P (p))
- {
- if (! dst_death)
- {
- num_calls++;
- freq_calls += REG_FREQ_FROM_BB (BLOCK_FOR_INSN (p));
- }
-
- if (REG_N_CALLS_CROSSED (REGNO (src)) == 0)
- break;
-
- if ((HARD_REGISTER_P (dst) && call_used_regs [REGNO (dst)])
- || find_reg_fusage (p, CLOBBER, dst))
- break;
- }
- else if (reg_set_p (src, PATTERN (p)))
- break;
- }
-
- return 0;
-}
-
-/* A forward pass. Replace output operands with input operands. */
-
-static void
-regmove_forward_pass (void)
-{
- basic_block bb;
- rtx insn;
-
- if (! flag_expensive_optimizations)
- return;
-
- if (dump_file)
- fprintf (dump_file, "Starting forward pass...\n");
-
- FOR_EACH_BB (bb)
- {
- FOR_BB_INSNS (bb, insn)
- {
- rtx set = single_set (insn);
- if (! set)
- continue;
-
- if ((GET_CODE (SET_SRC (set)) == SIGN_EXTEND
- || GET_CODE (SET_SRC (set)) == ZERO_EXTEND)
- && REG_P (XEXP (SET_SRC (set), 0))
- && REG_P (SET_DEST (set)))
- optimize_reg_copy_3 (insn, SET_DEST (set), SET_SRC (set));
-
- if (REG_P (SET_SRC (set))
- && REG_P (SET_DEST (set)))
- {
- /* If this is a register-register copy where SRC is not dead,
- see if we can optimize it. If this optimization succeeds,
- it will become a copy where SRC is dead. */
- if ((find_reg_note (insn, REG_DEAD, SET_SRC (set))
- || optimize_reg_copy_1 (insn, SET_DEST (set), SET_SRC (set)))
- && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER)
- {
- /* Similarly for a pseudo-pseudo copy when SRC is dead. */
- if (REGNO (SET_SRC (set)) >= FIRST_PSEUDO_REGISTER)
- optimize_reg_copy_2 (insn, SET_DEST (set), SET_SRC (set));
- if (regno_src_regno[REGNO (SET_DEST (set))] < 0
- && SET_SRC (set) != SET_DEST (set))
- {
- int srcregno = REGNO (SET_SRC (set));
- if (regno_src_regno[srcregno] >= 0)
- srcregno = regno_src_regno[srcregno];
- regno_src_regno[REGNO (SET_DEST (set))] = srcregno;
- }
- }
- }
- }
- }
-}
-
-/* A backward pass. Replace input operands with output operands. */
-
-static void
-regmove_backward_pass (void)
-{
- basic_block bb;
- rtx insn, prev;
-
- if (dump_file)
- fprintf (dump_file, "Starting backward pass...\n");
-
- FOR_EACH_BB_REVERSE (bb)
- {
- /* ??? Use the safe iterator because fixup_match_2 can remove
- insns via try_auto_increment. */
- FOR_BB_INSNS_REVERSE_SAFE (bb, insn, prev)
- {
- struct match match;
- rtx copy_src, copy_dst;
- int op_no, match_no;
- int success = 0;
-
- if (! INSN_P (insn))
- continue;
-
- if (! find_matches (insn, &match))
- continue;
-
- /* Now scan through the operands looking for a destination operand
- which is supposed to match a source operand.
- Then scan backward for an instruction which sets the source
- operand. If safe, then replace the source operand with the
- dest operand in both instructions. */
-
- copy_src = NULL_RTX;
- copy_dst = NULL_RTX;
- for (op_no = 0; op_no < recog_data.n_operands; op_no++)
- {
- rtx set, p, src, dst;
- rtx src_note, dst_note;
- int num_calls = 0, freq_calls = 0;
- enum reg_class src_class, dst_class;
- int length;
-
- match_no = match.with[op_no];
-
- /* Nothing to do if the two operands aren't supposed to match. */
- if (match_no < 0)
- continue;
-
- dst = recog_data.operand[match_no];
- src = recog_data.operand[op_no];
-
- if (!REG_P (src))
- continue;
-
- if (!REG_P (dst)
- || REGNO (dst) < FIRST_PSEUDO_REGISTER
- || REG_LIVE_LENGTH (REGNO (dst)) < 0
- || GET_MODE (src) != GET_MODE (dst))
- continue;
-
- /* If the operands already match, then there is nothing to do. */
- if (operands_match_p (src, dst))
- continue;
-
- if (match.commutative[op_no] >= 0)
- {
- rtx comm = recog_data.operand[match.commutative[op_no]];
- if (operands_match_p (comm, dst))
- continue;
- }
-
- set = single_set (insn);
- if (! set)
- continue;
-
- /* Note that single_set ignores parts of a parallel set for
- which one of the destinations is REG_UNUSED. We can't
- handle that here, since we can wind up rewriting things
- such that a single register is set twice within a single
- parallel. */
- if (reg_set_p (src, insn))
- continue;
-
- /* match_no/dst must be a write-only operand, and
- operand_operand/src must be a read-only operand. */
- if (match.use[op_no] != READ
- || match.use[match_no] != WRITE)
- continue;
-
- if (match.early_clobber[match_no]
- && count_occurrences (PATTERN (insn), src, 0) > 1)
- continue;
-
- /* Make sure match_no is the destination. */
- if (recog_data.operand[match_no] != SET_DEST (set))
- continue;
-
- if (REGNO (src) < FIRST_PSEUDO_REGISTER)
- {
- if (GET_CODE (SET_SRC (set)) == PLUS
- && CONST_INT_P (XEXP (SET_SRC (set), 1))
- && XEXP (SET_SRC (set), 0) == src
- && fixup_match_2 (insn, dst, src,
- XEXP (SET_SRC (set), 1)))
- break;
- continue;
- }
- src_class = reg_preferred_class (REGNO (src));
- dst_class = reg_preferred_class (REGNO (dst));
-
- if (! (src_note = find_reg_note (insn, REG_DEAD, src)))
- {
- /* We used to force the copy here like in other cases, but
- it produces worse code, as it eliminates no copy
- instructions and the copy emitted will be produced by
- reload anyway. On patterns with multiple alternatives,
- there may be better solution available.
-
- In particular this change produced slower code for numeric
- i387 programs. */
-
- continue;
- }
-
- if (! regclass_compatible_p (src_class, dst_class))
- {
- if (!copy_src)
- {
- copy_src = src;
- copy_dst = dst;
- }
- continue;
- }
-
- /* Can not modify an earlier insn to set dst if this insn
- uses an old value in the source. */
- if (reg_overlap_mentioned_p (dst, SET_SRC (set)))
- {
- if (!copy_src)
- {
- copy_src = src;
- copy_dst = dst;
- }
- continue;
- }
-
- /* If src is set once in a different basic block,
- and is set equal to a constant, then do not use
- it for this optimization, as this would make it
- no longer equivalent to a constant. */
-
- if (reg_is_remote_constant_p (src, insn))
- {
- if (!copy_src)
- {
- copy_src = src;
- copy_dst = dst;
- }
- continue;
- }
-
-
- if (dump_file)
- fprintf (dump_file,
- "Could fix operand %d of insn %d matching operand %d.\n",
- op_no, INSN_UID (insn), match_no);
-
- /* Scan backward to find the first instruction that uses
- the input operand. If the operand is set here, then
- replace it in both instructions with match_no. */
-
- for (length = 0, p = PREV_INSN (insn); p; p = PREV_INSN (p))
- {
- rtx pset;
-
- if (! INSN_P (p))
- continue;
- if (BLOCK_FOR_INSN (p) != bb)
- break;
-
- if (!DEBUG_INSN_P (p))
- length++;
-
- /* ??? See if all of SRC is set in P. This test is much
- more conservative than it needs to be. */
- pset = single_set (p);
- if (pset && SET_DEST (pset) == src)
- {
- /* We use validate_replace_rtx, in case there
- are multiple identical source operands. All
- of them have to be changed at the same time:
- when validate_replace_rtx() calls
- apply_change_group(). */
- validate_change (p, &SET_DEST (pset), dst, 1);
- if (validate_replace_rtx (src, dst, insn))
- success = 1;
- break;
- }
-
- /* We can't make this change if DST is mentioned at
- all in P, since we are going to change its value.
- We can't make this change if SRC is read or
- partially written in P, since we are going to
- eliminate SRC. However, if it's a debug insn, we
- can't refrain from making the change, for this
- would cause codegen differences, so instead we
- invalidate debug expressions that reference DST,
- and adjust references to SRC in them so that they
- become references to DST. */
- if (reg_mentioned_p (dst, PATTERN (p)))
- {
- if (DEBUG_INSN_P (p))
- validate_change (p, &INSN_VAR_LOCATION_LOC (p),
- gen_rtx_UNKNOWN_VAR_LOC (), 1);
- else
- break;
- }
- if (reg_overlap_mentioned_p (src, PATTERN (p)))
- {
- if (DEBUG_INSN_P (p))
- validate_replace_rtx_group (src, dst, p);
- else
- break;
- }
-
- /* If we have passed a call instruction, and the
- pseudo-reg DST is not already live across a call,
- then don't perform the optimization. */
- if (CALL_P (p))
- {
- num_calls++;
- freq_calls += REG_FREQ_FROM_BB (BLOCK_FOR_INSN (p));
-
- if (REG_N_CALLS_CROSSED (REGNO (dst)) == 0)
- break;
- }
- }
-
- if (success)
- {
- int dstno, srcno;
-
- /* Remove the death note for SRC from INSN. */
- remove_note (insn, src_note);
- /* Move the death note for SRC to P if it is used
- there. */
- if (reg_overlap_mentioned_p (src, PATTERN (p)))
- {
- XEXP (src_note, 1) = REG_NOTES (p);
- REG_NOTES (p) = src_note;
- }
- /* If there is a REG_DEAD note for DST on P, then remove
- it, because DST is now set there. */
- if ((dst_note = find_reg_note (p, REG_DEAD, dst)))
- remove_note (p, dst_note);
-
- dstno = REGNO (dst);
- srcno = REGNO (src);
-
- INC_REG_N_SETS (dstno, 1);
- INC_REG_N_SETS (srcno, -1);
-
- REG_N_CALLS_CROSSED (dstno) += num_calls;
- REG_N_CALLS_CROSSED (srcno) -= num_calls;
- REG_FREQ_CALLS_CROSSED (dstno) += freq_calls;
- REG_FREQ_CALLS_CROSSED (srcno) -= freq_calls;
-
- REG_LIVE_LENGTH (dstno) += length;
- if (REG_LIVE_LENGTH (srcno) >= 0)
- {
- REG_LIVE_LENGTH (srcno) -= length;
- /* REG_LIVE_LENGTH is only an approximation after
- combine if sched is not run, so make sure that we
- still have a reasonable value. */
- if (REG_LIVE_LENGTH (srcno) < 2)
- REG_LIVE_LENGTH (srcno) = 2;
- }
-
- if (dump_file)
- fprintf (dump_file,
- "Fixed operand %d of insn %d matching operand %d.\n",
- op_no, INSN_UID (insn), match_no);
-
- break;
- }
- else if (num_changes_pending () > 0)
- cancel_changes (0);
- }
-
- /* If we weren't able to replace any of the alternatives, try an
- alternative approach of copying the source to the destination. */
- if (!success && copy_src != NULL_RTX)
- copy_src_to_dest (insn, copy_src, copy_dst);
- }
- }
-}
-
-/* Main entry for the register move optimization. */
-
-static unsigned int
-regmove_optimize (void)
-{
- int i;
- int nregs = max_reg_num ();
-
- df_note_add_problem ();
- df_analyze ();
-
- regstat_init_n_sets_and_refs ();
- regstat_compute_ri ();
-
- if (flag_ira_loop_pressure)
- ira_set_pseudo_classes (true, dump_file);
-
- regno_src_regno = XNEWVEC (int, nregs);
- for (i = nregs; --i >= 0; )
- regno_src_regno[i] = -1;
-
- /* A forward pass. Replace output operands with input operands. */
- regmove_forward_pass ();
-
- /* A backward pass. Replace input operands with output operands. */
- regmove_backward_pass ();
-
- /* Clean up. */
- free (regno_src_regno);
- if (reg_set_in_bb)
- {
- free (reg_set_in_bb);
- reg_set_in_bb = NULL;
- }
- regstat_free_n_sets_and_refs ();
- regstat_free_ri ();
- if (flag_ira_loop_pressure)
- free_reg_info ();
- return 0;
-}
-
-/* Returns nonzero if INSN's pattern has matching constraints for any operand.
- Returns 0 if INSN can't be recognized, or if the alternative can't be
- determined.
-
- Initialize the info in MATCHP based on the constraints. */
-
-static int
-find_matches (rtx insn, struct match *matchp)
-{
- int likely_spilled[MAX_RECOG_OPERANDS];
- int op_no;
- int any_matches = 0;
-
- extract_insn (insn);
- if (! constrain_operands (0))
- return 0;
-
- /* Must initialize this before main loop, because the code for
- the commutative case may set matches for operands other than
- the current one. */
- for (op_no = recog_data.n_operands; --op_no >= 0; )
- matchp->with[op_no] = matchp->commutative[op_no] = -1;
-
- for (op_no = 0; op_no < recog_data.n_operands; op_no++)
- {
- const char *p;
- char c;
- int i = 0;
-
- p = recog_data.constraints[op_no];
-
- likely_spilled[op_no] = 0;
- matchp->use[op_no] = READ;
- matchp->early_clobber[op_no] = 0;
- if (*p == '=')
- matchp->use[op_no] = WRITE;
- else if (*p == '+')
- matchp->use[op_no] = READWRITE;
-
- for (;*p && i < which_alternative; p++)
- if (*p == ',')
- i++;
-
- while ((c = *p) != '\0' && c != ',')
- {
- switch (c)
- {
- case '=':
- break;
- case '+':
- break;
- case '&':
- matchp->early_clobber[op_no] = 1;
- break;
- case '%':
- matchp->commutative[op_no] = op_no + 1;
- matchp->commutative[op_no + 1] = op_no;
- break;
-
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- {
- char *end;
- unsigned long match_ul = strtoul (p, &end, 10);
- int match = match_ul;
-
- p = end;
-
- if (match < op_no && likely_spilled[match])
- continue;
- matchp->with[op_no] = match;
- any_matches = 1;
- if (matchp->commutative[op_no] >= 0)
- matchp->with[matchp->commutative[op_no]] = match;
- }
- continue;
-
- case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'h':
- case 'j': case 'k': case 'l': case 'p': case 'q': case 't': case 'u':
- case 'v': case 'w': case 'x': case 'y': case 'z': case 'A': case 'B':
- case 'C': case 'D': case 'W': case 'Y': case 'Z':
- if (targetm.class_likely_spilled_p (REG_CLASS_FROM_CONSTRAINT ((unsigned char) c, p)))
- likely_spilled[op_no] = 1;
- break;
- }
- p += CONSTRAINT_LEN (c, p);
- }
- }
- return any_matches;
-}
-
-
-
-static bool
-gate_handle_regmove (void)
-{
- return (optimize > 0 && flag_regmove);
-}
-
-
-namespace {
-
-const pass_data pass_data_regmove =
-{
- RTL_PASS, /* type */
- "regmove", /* name */
- OPTGROUP_NONE, /* optinfo_flags */
- true, /* has_gate */
- true, /* has_execute */
- TV_REGMOVE, /* tv_id */
- 0, /* properties_required */
- 0, /* properties_provided */
- 0, /* properties_destroyed */
- 0, /* todo_flags_start */
- ( TODO_df_finish | TODO_verify_rtl_sharing ), /* todo_flags_finish */
-};
-
-class pass_regmove : public rtl_opt_pass
-{
-public:
- pass_regmove(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_regmove, ctxt)
- {}
-
- /* opt_pass methods: */
- bool gate () { return gate_handle_regmove (); }
- unsigned int execute () { return regmove_optimize (); }
-
-}; // class pass_regmove
-
-} // anon namespace
-
-rtl_opt_pass *
-make_pass_regmove (gcc::context *ctxt)
-{
- return new pass_regmove (ctxt);
-}
diff --git a/gcc/regrename.c b/gcc/regrename.c
index 6830bd8389a..5b2c85799bb 100644
--- a/gcc/regrename.c
+++ b/gcc/regrename.c
@@ -1862,8 +1862,8 @@ const pass_data pass_data_regrename =
class pass_regrename : public rtl_opt_pass
{
public:
- pass_regrename(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_regrename, ctxt)
+ pass_regrename (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_regrename, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/regs.h b/gcc/regs.h
index 090d6b64e83..b5fa3f3995f 100644
--- a/gcc/regs.h
+++ b/gcc/regs.h
@@ -69,7 +69,7 @@ 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)
+REG_N_REFS (int regno)
{
return regstat_n_sets_and_refs[regno].refs;
}
diff --git a/gcc/regstat.c b/gcc/regstat.c
index 5b1f3c421ee..85678a70f68 100644
--- a/gcc/regstat.c
+++ b/gcc/regstat.c
@@ -172,7 +172,7 @@ regstat_bb_compute_ri (unsigned int bb_index,
while (link)
{
if (REG_NOTE_KIND (link) == REG_DEAD)
- REG_N_DEATHS(REGNO (XEXP (link, 0)))++;
+ REG_N_DEATHS (REGNO (XEXP (link, 0)))++;
link = XEXP (link, 1);
}
diff --git a/gcc/reload1.c b/gcc/reload1.c
index 7a82c07ef21..204685da316 100644
--- a/gcc/reload1.c
+++ b/gcc/reload1.c
@@ -373,6 +373,7 @@ static void init_eliminable_invariants (rtx, bool);
static void init_elim_table (void);
static void free_reg_equiv (void);
static void update_eliminables (HARD_REG_SET *);
+static bool update_eliminables_and_spill (void);
static void elimination_costs_in_insn (rtx);
static void spill_hard_reg (unsigned int, int);
static int finish_spills (int);
@@ -913,9 +914,6 @@ reload (rtx first, int global)
if (caller_save_needed)
setup_save_areas ();
- /* If we allocated another stack slot, redo elimination bookkeeping. */
- if (something_was_spilled || starting_frame_size != get_frame_size ())
- continue;
if (starting_frame_size && crtl->stack_alignment_needed)
{
/* If we have a stack frame, we must align it now. The
@@ -927,8 +925,12 @@ reload (rtx first, int global)
STARTING_FRAME_OFFSET not be already aligned to
STACK_BOUNDARY. */
assign_stack_local (BLKmode, 0, crtl->stack_alignment_needed);
- if (starting_frame_size != get_frame_size ())
- continue;
+ }
+ /* If we allocated another stack slot, redo elimination bookkeeping. */
+ if (something_was_spilled || starting_frame_size != get_frame_size ())
+ {
+ update_eliminables_and_spill ();
+ continue;
}
if (caller_save_needed)
@@ -962,30 +964,11 @@ reload (rtx first, int global)
else if (!verify_initial_elim_offsets ())
something_changed = 1;
- {
- HARD_REG_SET to_spill;
- CLEAR_HARD_REG_SET (to_spill);
- update_eliminables (&to_spill);
- AND_COMPL_HARD_REG_SET (used_spill_regs, to_spill);
-
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- if (TEST_HARD_REG_BIT (to_spill, i))
- {
- spill_hard_reg (i, 1);
- did_spill = 1;
-
- /* Regardless of the state of spills, if we previously had
- a register that we thought we could eliminate, but now can
- not eliminate, we must run another pass.
-
- Consider pseudos which have an entry in reg_equiv_* which
- reference an eliminable register. We must make another pass
- to update reg_equiv_* so that we do not substitute in the
- old value from when we thought the elimination could be
- performed. */
- something_changed = 1;
- }
- }
+ if (update_eliminables_and_spill ())
+ {
+ did_spill = 1;
+ something_changed = 1;
+ }
select_reload_regs ();
if (failure)
@@ -2325,7 +2308,7 @@ mark_home_live_1 (int regno, enum machine_mode mode)
return;
lim = end_hard_regno (mode, i);
while (i < lim)
- df_set_regs_ever_live(i++, true);
+ df_set_regs_ever_live (i++, true);
}
/* Mark the slots in regs_ever_live for the hard regs
@@ -2776,6 +2759,7 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
/* ... fall through ... */
case INSN_LIST:
+ case INT_LIST:
/* Now do eliminations in the rest of the chain. If this was
an EXPR_LIST, this might result in allocating more memory than is
strictly needed, but it simplifies the code. */
@@ -4030,6 +4014,38 @@ update_eliminables (HARD_REG_SET *pset)
SET_HARD_REG_BIT (*pset, HARD_FRAME_POINTER_REGNUM);
}
+/* Call update_eliminables an spill any registers we can't eliminate anymore.
+ Return true iff a register was spilled. */
+
+static bool
+update_eliminables_and_spill (void)
+{
+ int i;
+ bool did_spill = false;
+ HARD_REG_SET to_spill;
+ CLEAR_HARD_REG_SET (to_spill);
+ update_eliminables (&to_spill);
+ AND_COMPL_HARD_REG_SET (used_spill_regs, to_spill);
+
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ if (TEST_HARD_REG_BIT (to_spill, i))
+ {
+ spill_hard_reg (i, 1);
+ did_spill = true;
+
+ /* Regardless of the state of spills, if we previously had
+ a register that we thought we could eliminate, but now can
+ not eliminate, we must run another pass.
+
+ Consider pseudos which have an entry in reg_equiv_* which
+ reference an eliminable register. We must make another pass
+ to update reg_equiv_* so that we do not substitute in the
+ old value from when we thought the elimination could be
+ performed. */
+ }
+ return did_spill;
+}
+
/* Return true if X is used as the target register of an elimination. */
bool
@@ -5559,6 +5575,14 @@ reloads_unique_chain_p (int r1, int r2)
|| reg_mentioned_p (rld[r2].in, rld[r1].in)))
return false;
+ /* The following loop assumes that r1 is the reload that feeds r2. */
+ if (r1 > r2)
+ {
+ int tmp = r2;
+ r2 = r1;
+ r1 = tmp;
+ }
+
for (i = 0; i < n_reloads; i ++)
/* Look for input reloads that aren't our two */
if (i != r1 && i != r2 && rld[i].in)
@@ -6362,6 +6386,37 @@ replaced_subreg (rtx x)
}
#endif
+/* Compute the offset to pass to subreg_regno_offset, for a pseudo of
+ mode OUTERMODE that is available in a hard reg of mode INNERMODE.
+ SUBREG is non-NULL if the pseudo is a subreg whose reg is a pseudo,
+ otherwise it is NULL. */
+
+static int
+compute_reload_subreg_offset (enum machine_mode outermode,
+ rtx subreg,
+ enum machine_mode innermode)
+{
+ int outer_offset;
+ enum machine_mode middlemode;
+
+ if (!subreg)
+ return subreg_lowpart_offset (outermode, innermode);
+
+ outer_offset = SUBREG_BYTE (subreg);
+ middlemode = GET_MODE (SUBREG_REG (subreg));
+
+ /* If SUBREG is paradoxical then return the normal lowpart offset
+ for OUTERMODE and INNERMODE. Our caller has already checked
+ that OUTERMODE fits in INNERMODE. */
+ if (outer_offset == 0
+ && GET_MODE_SIZE (outermode) > GET_MODE_SIZE (middlemode))
+ return subreg_lowpart_offset (outermode, innermode);
+
+ /* SUBREG is normal, but may not be lowpart; return OUTER_OFFSET
+ plus the normal lowpart offset for MIDDLEMODE and INNERMODE. */
+ return outer_offset + subreg_lowpart_offset (middlemode, innermode);
+}
+
/* Assign hard reg targets for the pseudo-registers we must reload
into hard regs for this insn.
Also output the instructions to copy them in and out of the hard regs.
@@ -6499,6 +6554,7 @@ choose_reload_regs (struct insn_chain *chain)
int byte = 0;
int regno = -1;
enum machine_mode mode = VOIDmode;
+ rtx subreg = NULL_RTX;
if (rld[r].in == 0)
;
@@ -6519,7 +6575,10 @@ choose_reload_regs (struct insn_chain *chain)
if (regno < FIRST_PSEUDO_REGISTER)
regno = subreg_regno (rld[r].in_reg);
else
- byte = SUBREG_BYTE (rld[r].in_reg);
+ {
+ subreg = rld[r].in_reg;
+ byte = SUBREG_BYTE (subreg);
+ }
mode = GET_MODE (rld[r].in_reg);
}
#ifdef AUTO_INC_DEC
@@ -6557,6 +6616,9 @@ choose_reload_regs (struct insn_chain *chain)
rtx last_reg = reg_last_reload_reg[regno];
i = REGNO (last_reg);
+ byte = compute_reload_subreg_offset (mode,
+ subreg,
+ GET_MODE (last_reg));
i += subreg_regno_offset (i, GET_MODE (last_reg), byte, mode);
last_class = REGNO_REG_CLASS (i);
diff --git a/gcc/reorg.c b/gcc/reorg.c
index d39cc7d8a4a..e9aa889b17d 100644
--- a/gcc/reorg.c
+++ b/gcc/reorg.c
@@ -876,7 +876,7 @@ mostly_true_jump (rtx jump_insn)
rtx note = find_reg_note (jump_insn, REG_BR_PROB, 0);
if (note)
{
- int prob = INTVAL (XEXP (note, 0));
+ int prob = XINT (note, 0);
if (prob >= REG_BR_PROB_BASE * 9 / 10)
return 2;
@@ -2173,7 +2173,7 @@ fill_simple_delay_slots (int non_jumps_p)
&& ! (maybe_never && may_trap_or_fault_p (pat))
&& (trial = try_split (pat, trial, 0))
&& eligible_for_delay (insn, slots_filled, trial, flags)
- && ! can_throw_internal(trial))
+ && ! can_throw_internal (trial))
{
next_trial = next_nonnote_insn (trial);
delay_list = add_to_delay_list (trial, delay_list);
@@ -2363,8 +2363,8 @@ fill_slots_from_thread (rtx insn, rtx condition, rtx thread,
int flags;
/* Validate our arguments. */
- gcc_assert(condition != const_true_rtx || thread_if_true);
- gcc_assert(own_thread || thread_if_true);
+ gcc_assert (condition != const_true_rtx || thread_if_true);
+ gcc_assert (own_thread || thread_if_true);
flags = get_jump_flags (insn, JUMP_LABEL (insn));
@@ -3888,8 +3888,8 @@ const pass_data pass_data_delay_slots =
class pass_delay_slots : public rtl_opt_pass
{
public:
- pass_delay_slots(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_delay_slots, ctxt)
+ pass_delay_slots (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_delay_slots, ctxt)
{}
/* opt_pass methods: */
@@ -3941,8 +3941,8 @@ const pass_data pass_data_machine_reorg =
class pass_machine_reorg : public rtl_opt_pass
{
public:
- pass_machine_reorg(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_machine_reorg, ctxt)
+ pass_machine_reorg (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_machine_reorg, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/rtl.c b/gcc/rtl.c
index b2d88f783b7..52b7747b693 100644
--- a/gcc/rtl.c
+++ b/gcc/rtl.c
@@ -222,7 +222,7 @@ shared_const_p (const_rtx orig)
a LABEL_REF, it isn't sharable. */
return (GET_CODE (XEXP (orig, 0)) == PLUS
&& GET_CODE (XEXP (XEXP (orig, 0), 0)) == SYMBOL_REF
- && CONST_INT_P(XEXP (XEXP (orig, 0), 1)));
+ && CONST_INT_P (XEXP (XEXP (orig, 0), 1)));
}
diff --git a/gcc/rtl.def b/gcc/rtl.def
index b4ce1b99f3f..15a997b8c25 100644
--- a/gcc/rtl.def
+++ b/gcc/rtl.def
@@ -95,13 +95,16 @@ DEF_RTL_EXPR(DEBUG_EXPR, "debug_expr", "0", RTX_OBJ)
Expressions used in constructing lists.
--------------------------------------------------------------------- */
-/* a linked list of expressions */
+/* A linked list of expressions. */
DEF_RTL_EXPR(EXPR_LIST, "expr_list", "ee", RTX_EXTRA)
-/* a linked list of instructions.
+/* 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.
diff --git a/gcc/rtl.h b/gcc/rtl.h
index b5bfdffebc1..247a0d06701 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -544,7 +544,7 @@ struct GTY((variable_size)) rtvec_def {
if (_n < 0 || _n >= GET_RTX_LENGTH (_code)) \
rtl_check_failed_bounds (_rtx, _n, __FILE__, __LINE__, \
__FUNCTION__); \
- if (GET_RTX_FORMAT(_code)[_n] != C1) \
+ if (GET_RTX_FORMAT (_code)[_n] != C1) \
rtl_check_failed_type1 (_rtx, _n, C1, __FILE__, __LINE__, \
__FUNCTION__); \
&_rtx->u.fld[_n]; }))
@@ -555,8 +555,8 @@ struct GTY((variable_size)) rtvec_def {
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) \
+ 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]; }))
@@ -589,7 +589,7 @@ struct GTY((variable_size)) rtvec_def {
if (_n < 0 || _n >= GET_RTX_LENGTH (_code)) \
rtl_check_failed_bounds (_rtx, _n, __FILE__, __LINE__, \
__FUNCTION__); \
- if (GET_RTX_FORMAT(_code)[_n] != 'w') \
+ if (GET_RTX_FORMAT (_code)[_n] != 'w') \
rtl_check_failed_type1 (_rtx, _n, 'w', __FILE__, __LINE__, \
__FUNCTION__); \
&_rtx->u.hwint[_n]; }))
@@ -679,39 +679,39 @@ extern void rtvec_check_failed_bounds (const_rtvec, int, const char *, int,
#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) \
+ 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) \
+ 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) \
+ 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) \
+ 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) \
+ 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; })
@@ -719,9 +719,9 @@ extern void rtvec_check_failed_bounds (const_rtvec, int, const char *, int,
#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) \
+ 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; })
@@ -729,10 +729,10 @@ extern void rtvec_check_failed_bounds (const_rtvec, int, const char *, int,
#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) \
+ 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; })
@@ -740,10 +740,10 @@ extern void rtvec_check_failed_bounds (const_rtvec, int, const char *, int,
#define RTL_FLAG_CHECK8(NAME, RTX, C1, C2, C3, C4, C5, C6, C7, C8) \
__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 && GET_CODE(_rtx) != C8) \
+ 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 && GET_CODE (_rtx) != C8) \
rtl_check_failed_flag (NAME, _rtx, __FILE__, __LINE__, \
__FUNCTION__); \
_rtx; })
@@ -844,56 +844,57 @@ extern void rtl_check_failed_flag (const char *, const_rtx, const char *,
#define INSN_CODE(INSN) XINT (INSN, 6)
#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)
+ (RTL_FLAG_CHECK6 ("RTX_FRAME_RELATED_P", (RTX), DEBUG_INSN, INSN, \
+ CALL_INSN, JUMP_INSN, BARRIER, SET)->frame_related)
/* 1 if RTX is an insn that has been deleted. */
#define INSN_DELETED_P(RTX) \
- (RTL_FLAG_CHECK8("INSN_DELETED_P", (RTX), DEBUG_INSN, INSN, \
- CALL_INSN, JUMP_INSN, JUMP_TABLE_DATA, \
- CODE_LABEL, BARRIER, NOTE)->volatil)
+ (RTL_FLAG_CHECK8 ("INSN_DELETED_P", (RTX), DEBUG_INSN, INSN, \
+ CALL_INSN, JUMP_INSN, JUMP_TABLE_DATA, \
+ CODE_LABEL, BARRIER, NOTE)->volatil)
/* 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)
+ (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)
+ (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))
+ (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)
+ (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)
+ (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)
+ (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)
+ (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)
+#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_struct", see cselib.h. */
-#define CSELIB_VAL_PTR(RTX) X0CSELIB(RTX, 0)
+#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
@@ -1003,7 +1004,7 @@ extern const char * const reg_note_name[];
/* 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)
+ (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)
@@ -1109,7 +1110,8 @@ enum label_kind
/* 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 (REGNO(RTX), N, RTX), XCUINT (RTX, 0, REG) = N)
+#define SET_REGNO(RTX,N) \
+ (df_ref_change_reg_with_loc (REGNO (RTX), N, RTX), XCUINT (RTX, 0, REG) = N)
#define SET_REGNO_RAW(RTX,N) (XCUINT (RTX, 0, REG) = N)
/* ORIGINAL_REGNO holds the number the register originally had; for a
@@ -1128,19 +1130,19 @@ rhs_regno (const_rtx x)
/* 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)
+ (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)
+ (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)
+ (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)
+ (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)))
@@ -1149,7 +1151,7 @@ rhs_regno (const_rtx x)
#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 INTVAL(RTX) XCWINT (RTX, 0, CONST_INT)
#define UINTVAL(RTX) ((unsigned HOST_WIDE_INT) INTVAL (RTX))
/* For a CONST_DOUBLE:
@@ -1165,9 +1167,9 @@ rhs_regno (const_rtx x)
#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))
+ ((HOST_WIDE_INT) (CONST_FIXED_VALUE (r)->data.high))
#define CONST_FIXED_VALUE_LOW(r) \
- ((HOST_WIDE_INT) (CONST_FIXED_VALUE(r)->data.low))
+ ((HOST_WIDE_INT) (CONST_FIXED_VALUE (r)->data.low))
/* For a CONST_VECTOR, return element #n. */
#define CONST_VECTOR_ELT(RTX, N) XCVECEXP (RTX, 0, N, CONST_VECTOR)
@@ -1387,11 +1389,12 @@ get_full_set_src_cost (rtx x, struct full_rtx_costs *c)
when assigning to SUBREG_REG. */
#define SUBREG_PROMOTED_VAR_P(RTX) \
- (RTL_FLAG_CHECK1("SUBREG_PROMOTED", (RTX), SUBREG)->in_struct)
+ (RTL_FLAG_CHECK1 ("SUBREG_PROMOTED", (RTX), SUBREG)->in_struct)
#define SUBREG_PROMOTED_UNSIGNED_SET(RTX, VAL) \
do { \
- rtx const _rtx = RTL_FLAG_CHECK1("SUBREG_PROMOTED_UNSIGNED_SET", (RTX), SUBREG); \
+ rtx const _rtx = RTL_FLAG_CHECK1 ("SUBREG_PROMOTED_UNSIGNED_SET", \
+ (RTX), SUBREG); \
if ((VAL) < 0) \
_rtx->volatil = 1; \
else { \
@@ -1409,13 +1412,13 @@ do { \
emit special code (ptr_extend insns) on some architectures. */
#define SUBREG_PROMOTED_UNSIGNED_P(RTX) \
- ((RTL_FLAG_CHECK1("SUBREG_PROMOTED_UNSIGNED_P", (RTX), SUBREG)->volatil) \
+ ((RTL_FLAG_CHECK1 ("SUBREG_PROMOTED_UNSIGNED_P", (RTX), SUBREG)->volatil) \
? -1 : (int) (RTX)->unchanging)
/* 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)
+ (RTL_FLAG_CHECK1 ("LRA_SUBREG_P", (RTX), SUBREG)->jump)
/* Access various components of an ASM_OPERANDS rtx. */
@@ -1440,22 +1443,22 @@ do { \
/* 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)
+ (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)
+ (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)
+ (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)
+ (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. */
@@ -1521,25 +1524,24 @@ do { \
/* 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)
+ (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)
+ (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)
+ (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_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)
+ (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)
@@ -1554,26 +1556,26 @@ do { \
/* 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)
+ (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.c. */
#define TREE_CONSTANT_POOL_ADDRESS_P(RTX) \
- (RTL_FLAG_CHECK1("TREE_CONSTANT_POOL_ADDRESS_P", \
- (RTX), SYMBOL_REF)->frame_related)
+ (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)
+ (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)
+ (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)
+ (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. */
@@ -1656,7 +1658,7 @@ do { \
/* 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)
+ (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. */
@@ -2055,6 +2057,8 @@ 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, enum reg_note, int);
+extern void add_shallow_copy_of_reg_note (rtx, rtx);
extern void remove_note (rtx, const_rtx);
extern void remove_reg_equal_equiv_notes (rtx);
extern void remove_reg_equal_equiv_notes_for_regno (unsigned int);
@@ -2070,7 +2074,7 @@ extern bool insn_could_throw_p (const_rtx);
extern bool insn_nothrow_p (const_rtx);
extern bool can_nonlocal_goto (const_rtx);
extern void copy_reg_eh_region_note_forward (rtx, rtx, rtx);
-extern void copy_reg_eh_region_note_backward(rtx, rtx, rtx);
+extern void copy_reg_eh_region_note_backward (rtx, rtx, rtx);
extern int inequality_comparisons_p (const_rtx);
extern rtx replace_rtx (rtx, rtx, rtx);
extern int replace_label (rtx *, void *);
diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c
index c15037e9645..b9f3e2b7925 100644
--- a/gcc/rtlanal.c
+++ b/gcc/rtlanal.c
@@ -1923,6 +1923,14 @@ find_regno_fusage (const_rtx insn, enum rtx_code code, unsigned int regno)
}
+/* Return true if KIND is an integer REG_NOTE. */
+
+static bool
+int_reg_note_p (enum reg_note kind)
+{
+ return kind == REG_BR_PROB;
+}
+
/* Allocate a register note with kind KIND and datum DATUM. LIST is
stored as the pointer to the next register note. */
@@ -1931,6 +1939,7 @@ alloc_reg_note (enum reg_note kind, rtx datum, rtx list)
{
rtx note;
+ gcc_checking_assert (!int_reg_note_p (kind));
switch (kind)
{
case REG_CC_SETTER:
@@ -1961,6 +1970,27 @@ add_reg_note (rtx insn, enum reg_note kind, rtx datum)
REG_NOTES (insn) = alloc_reg_note (kind, datum, REG_NOTES (insn));
}
+/* Add an integer register note with kind KIND and datum DATUM to INSN. */
+
+void
+add_int_reg_note (rtx insn, enum reg_note kind, int datum)
+{
+ gcc_checking_assert (int_reg_note_p (kind));
+ REG_NOTES (insn) = gen_rtx_INT_LIST ((enum machine_mode) kind,
+ datum, REG_NOTES (insn));
+}
+
+/* Add a register note like NOTE to INSN. */
+
+void
+add_shallow_copy_of_reg_note (rtx insn, rtx note)
+{
+ if (GET_CODE (note) == INT_LIST)
+ add_int_reg_note (insn, REG_NOTE_KIND (note), XINT (note, 0));
+ else
+ add_reg_note (insn, REG_NOTE_KIND (note), XEXP (note, 0));
+}
+
/* Remove register note NOTE from the REG_NOTES of INSN. */
void
@@ -2712,10 +2742,9 @@ tablejump_p (const_rtx insn, rtx *labelp, rtx *tablep)
label = JUMP_LABEL (insn);
if (label != NULL_RTX && !ANY_RETURN_P (label)
- && (table = next_active_insn (label)) != NULL_RTX
+ && (table = NEXT_INSN (label)) != NULL_RTX
&& JUMP_TABLE_DATA_P (table))
{
- gcc_assert (table == NEXT_INSN (label));
if (labelp)
*labelp = label;
if (tablep)
@@ -3683,7 +3712,7 @@ keep_with_call_p (const_rtx insn)
/* This CONST_CAST is okay because next_nonnote_insn just
returns its argument and we assign it to a const_rtx
variable. */
- const_rtx i2 = next_nonnote_insn (CONST_CAST_RTX(insn));
+ const_rtx i2 = next_nonnote_insn (CONST_CAST_RTX (insn));
if (i2 && keep_with_call_p (i2))
return true;
}
@@ -5437,12 +5466,29 @@ split_double (rtx value, rtx *first, rtx *second)
}
}
+/* Return true if X is a sign_extract or zero_extract from the least
+ significant bit. */
+
+static bool
+lsb_bitfield_op_p (rtx x)
+{
+ if (GET_RTX_CLASS (GET_CODE (x)) == RTX_BITFIELD_OPS)
+ {
+ enum machine_mode mode = GET_MODE (XEXP (x, 0));
+ HOST_WIDE_INT len = INTVAL (XEXP (x, 1));
+ HOST_WIDE_INT pos = INTVAL (XEXP (x, 2));
+
+ return (pos == (BITS_BIG_ENDIAN ? GET_MODE_PRECISION (mode) - len : 0));
+ }
+ return false;
+}
+
/* Strip outer address "mutations" from LOC and return a pointer to the
inner value. If OUTER_CODE is nonnull, store the code of the innermost
stripped expression there.
"Mutations" either convert between modes or apply some kind of
- alignment. */
+ extension, truncation or alignment. */
rtx *
strip_address_mutations (rtx *loc, enum rtx_code *outer_code)
@@ -5454,6 +5500,10 @@ strip_address_mutations (rtx *loc, enum rtx_code *outer_code)
/* Things like SIGN_EXTEND, ZERO_EXTEND and TRUNCATE can be
used to convert between pointer sizes. */
loc = &XEXP (*loc, 0);
+ else if (lsb_bitfield_op_p (*loc))
+ /* A [SIGN|ZERO]_EXTRACT from the least significant bit effectively
+ acts as a combined truncation and extension. */
+ loc = &XEXP (*loc, 0);
else if (code == AND && CONST_INT_P (XEXP (*loc, 1)))
/* (and ... (const_int -X)) is used to align to X bytes. */
loc = &XEXP (*loc, 0);
@@ -5470,20 +5520,50 @@ strip_address_mutations (rtx *loc, enum rtx_code *outer_code)
}
}
-/* Return true if X must be a base rather than an index. */
+/* Return true if CODE applies some kind of scale. The scaled value is
+ is the first operand and the scale is the second. */
static bool
-must_be_base_p (rtx x)
+binary_scale_code_p (enum rtx_code code)
{
- return GET_CODE (x) == LO_SUM;
+ return (code == MULT
+ || code == ASHIFT
+ /* Needed by ARM targets. */
+ || code == ASHIFTRT
+ || code == LSHIFTRT
+ || code == ROTATE
+ || code == ROTATERT);
}
-/* Return true if X must be an index rather than a base. */
+/* If *INNER can be interpreted as a base, return a pointer to the inner term
+ (see address_info). Return null otherwise. */
-static bool
-must_be_index_p (rtx x)
+static rtx *
+get_base_term (rtx *inner)
+{
+ if (GET_CODE (*inner) == LO_SUM)
+ inner = strip_address_mutations (&XEXP (*inner, 0));
+ if (REG_P (*inner)
+ || MEM_P (*inner)
+ || GET_CODE (*inner) == SUBREG)
+ return inner;
+ return 0;
+}
+
+/* If *INNER can be interpreted as an index, return a pointer to the inner term
+ (see address_info). Return null otherwise. */
+
+static rtx *
+get_index_term (rtx *inner)
{
- return GET_CODE (x) == MULT || GET_CODE (x) == ASHIFT;
+ /* At present, only constant scales are allowed. */
+ if (binary_scale_code_p (GET_CODE (*inner)) && CONSTANT_P (XEXP (*inner, 1)))
+ inner = strip_address_mutations (&XEXP (*inner, 0));
+ if (REG_P (*inner)
+ || MEM_P (*inner)
+ || GET_CODE (*inner) == SUBREG)
+ return inner;
+ return 0;
}
/* Set the segment part of address INFO to LOC, given that INNER is the
@@ -5492,8 +5572,6 @@ must_be_index_p (rtx x)
static void
set_address_segment (struct address_info *info, rtx *loc, rtx *inner)
{
- gcc_checking_assert (GET_CODE (*inner) == UNSPEC);
-
gcc_assert (!info->segment);
info->segment = loc;
info->segment_term = inner;
@@ -5505,12 +5583,6 @@ set_address_segment (struct address_info *info, rtx *loc, rtx *inner)
static void
set_address_base (struct address_info *info, rtx *loc, rtx *inner)
{
- if (GET_CODE (*inner) == LO_SUM)
- inner = strip_address_mutations (&XEXP (*inner, 0));
- gcc_checking_assert (REG_P (*inner)
- || MEM_P (*inner)
- || GET_CODE (*inner) == SUBREG);
-
gcc_assert (!info->base);
info->base = loc;
info->base_term = inner;
@@ -5522,13 +5594,6 @@ set_address_base (struct address_info *info, rtx *loc, rtx *inner)
static void
set_address_index (struct address_info *info, rtx *loc, rtx *inner)
{
- if ((GET_CODE (*inner) == MULT || GET_CODE (*inner) == ASHIFT)
- && CONSTANT_P (XEXP (*inner, 1)))
- inner = strip_address_mutations (&XEXP (*inner, 0));
- gcc_checking_assert (REG_P (*inner)
- || MEM_P (*inner)
- || GET_CODE (*inner) == SUBREG);
-
gcc_assert (!info->index);
info->index = loc;
info->index_term = inner;
@@ -5540,8 +5605,6 @@ set_address_index (struct address_info *info, rtx *loc, rtx *inner)
static void
set_address_disp (struct address_info *info, rtx *loc, rtx *inner)
{
- gcc_checking_assert (CONSTANT_P (*inner));
-
gcc_assert (!info->disp);
info->disp = loc;
info->disp_term = inner;
@@ -5621,12 +5684,6 @@ static int
baseness (rtx x, enum machine_mode mode, addr_space_t as,
enum rtx_code outer_code, enum rtx_code index_code)
{
- /* See whether we can be certain. */
- if (must_be_base_p (x))
- return 3;
- if (must_be_index_p (x))
- return -3;
-
/* Believe *_POINTER unless the address shape requires otherwise. */
if (REG_P (x) && REG_POINTER (x))
return 2;
@@ -5661,8 +5718,8 @@ decompose_normal_address (struct address_info *info)
if (n_ops > 1)
info->base_outer_code = PLUS;
- /* Separate the parts that contain a REG or MEM from those that don't.
- Record the latter in INFO and leave the former in OPS. */
+ /* Try to classify each sum operand now. Leave those that could be
+ either a base or an index in OPS. */
rtx *inner_ops[4];
size_t out = 0;
for (size_t in = 0; in < n_ops; ++in)
@@ -5675,18 +5732,31 @@ decompose_normal_address (struct address_info *info)
set_address_segment (info, loc, inner);
else
{
- ops[out] = loc;
- inner_ops[out] = inner;
- ++out;
+ /* The only other possibilities are a base or an index. */
+ rtx *base_term = get_base_term (inner);
+ rtx *index_term = get_index_term (inner);
+ gcc_assert (base_term || index_term);
+ if (!base_term)
+ set_address_index (info, loc, index_term);
+ else if (!index_term)
+ set_address_base (info, loc, base_term);
+ else
+ {
+ gcc_assert (base_term == index_term);
+ ops[out] = loc;
+ inner_ops[out] = base_term;
+ ++out;
+ }
}
}
/* Classify the remaining OPS members as bases and indexes. */
if (out == 1)
{
- /* Assume that the remaining value is a base unless the shape
- requires otherwise. */
- if (!must_be_index_p (*inner_ops[0]))
+ /* If we haven't seen a base or an index yet, assume that this is
+ the base. If we were confident that another term was the base
+ or index, treat the remaining operand as the other kind. */
+ if (!info->base)
set_address_base (info, ops[0], inner_ops[0]);
else
set_address_index (info, ops[0], inner_ops[0]);
diff --git a/gcc/sanitizer.def b/gcc/sanitizer.def
index 4c8a0377d8b..0f45e9eead4 100644
--- a/gcc/sanitizer.def
+++ b/gcc/sanitizer.def
@@ -27,7 +27,7 @@ along with GCC; see the file COPYING3. If not see
for other FEs by asan.c. */
/* Address Sanitizer */
-DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_INIT, "__asan_init_v1",
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_INIT, "__asan_init_v3",
BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
/* Do not reorder the BUILT_IN_ASAN_REPORT* builtins, e.g. cfgcleanup.c
relies on this order. */
@@ -297,3 +297,7 @@ DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE,
"__ubsan_handle_builtin_unreachable",
BT_FN_VOID_PTR,
ATTR_COLD_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)
diff --git a/gcc/sbitmap.c b/gcc/sbitmap.c
index bc77d43a617..ceadd09edda 100644
--- a/gcc/sbitmap.c
+++ b/gcc/sbitmap.c
@@ -30,15 +30,15 @@ along with GCC; see the file COPYING3. If not see
#if GCC_VERSION >= 3400
# if SBITMAP_ELT_BITS == HOST_BITS_PER_LONG
-# define do_popcount(x) __builtin_popcountl(x)
+# define do_popcount(x) __builtin_popcountl (x)
# elif SBITMAP_ELT_BITS == HOST_BITS_PER_LONGLONG
-# define do_popcount(x) __builtin_popcountll(x)
+# define do_popcount(x) __builtin_popcountll (x)
# else
# error "internal error: sbitmap.h and hwint.h are inconsistent"
# endif
#else
static unsigned long sbitmap_elt_popcount (SBITMAP_ELT_TYPE);
-# define do_popcount(x) sbitmap_elt_popcount((x))
+# define do_popcount(x) sbitmap_elt_popcount (x)
#endif
typedef SBITMAP_ELT_TYPE *sbitmap_ptr;
diff --git a/gcc/sched-deps.c b/gcc/sched-deps.c
index 353090157dd..8496014a72b 100644
--- a/gcc/sched-deps.c
+++ b/gcc/sched-deps.c
@@ -1938,8 +1938,8 @@ create_insn_reg_use (int regno, rtx insn)
return use;
}
-/* Allocate and return reg_set_data structure for REGNO and INSN. */
-static struct reg_set_data *
+/* Allocate reg_set_data structure for REGNO and INSN. */
+static void
create_insn_reg_set (int regno, rtx insn)
{
struct reg_set_data *set;
@@ -1949,7 +1949,6 @@ create_insn_reg_set (int regno, rtx insn)
set->insn = insn;
set->next_insn_set = INSN_REG_SET_LIST (insn);
INSN_REG_SET_LIST (insn) = set;
- return set;
}
/* Set up insn register uses for INSN and dependency context DEPS. */
diff --git a/gcc/sched-int.h b/gcc/sched-int.h
index 90d5b05c75e..33112eef075 100644
--- a/gcc/sched-int.h
+++ b/gcc/sched-int.h
@@ -1333,6 +1333,8 @@ extern void debug_ds (ds_t);
/* Functions in haifa-sched.c. */
+extern void initialize_live_range_shrinkage (void);
+extern void finish_live_range_shrinkage (void);
extern void sched_init_region_reg_pressure_info (void);
extern int haifa_classify_insn (const_rtx);
extern void get_ebb_head_tail (basic_block, basic_block, rtx *, rtx *);
diff --git a/gcc/sched-rgn.c b/gcc/sched-rgn.c
index e1a2dce16a2..b2a7dbd4a94 100644
--- a/gcc/sched-rgn.c
+++ b/gcc/sched-rgn.c
@@ -2443,6 +2443,8 @@ add_branch_dependences (rtx head, rtx tail)
cc0 setters remain at the end because they can't be moved away from
their cc0 user.
+ Predecessors of SCHED_GROUP_P instructions at the end remain at the end.
+
COND_EXEC insns cannot be moved past a branch (see e.g. PR17808).
Insns setting TARGET_CLASS_LIKELY_SPILLED_P registers (usually return
@@ -2465,7 +2467,8 @@ add_branch_dependences (rtx head, rtx tail)
#endif
|| (!reload_completed
&& sets_likely_spilled (PATTERN (insn)))))
- || NOTE_P (insn))
+ || NOTE_P (insn)
+ || (last != 0 && SCHED_GROUP_P (last)))
{
if (!NOTE_P (insn))
{
@@ -3562,6 +3565,33 @@ advance_target_bb (basic_block bb, rtx insn)
#endif
static bool
+gate_handle_live_range_shrinkage (void)
+{
+#ifdef INSN_SCHEDULING
+ return flag_live_range_shrinkage;
+#else
+ return 0;
+#endif
+}
+
+/* Run instruction scheduler. */
+static unsigned int
+rest_of_handle_live_range_shrinkage (void)
+{
+#ifdef INSN_SCHEDULING
+ int saved;
+
+ initialize_live_range_shrinkage ();
+ saved = flag_schedule_interblock;
+ flag_schedule_interblock = false;
+ schedule_insns ();
+ flag_schedule_interblock = saved;
+ finish_live_range_shrinkage ();
+#endif
+ return 0;
+}
+
+static bool
gate_handle_sched (void)
{
#ifdef INSN_SCHEDULING
@@ -3619,6 +3649,45 @@ rest_of_handle_sched2 (void)
namespace {
+const pass_data pass_data_live_range_shrinkage =
+{
+ RTL_PASS, /* type */
+ "lr_shrinkage", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
+ true, /* has_gate */
+ true, /* has_execute */
+ TV_LIVE_RANGE_SHRINKAGE, /* tv_id */
+ 0, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ ( TODO_df_finish | TODO_verify_rtl_sharing
+ | TODO_verify_flow ), /* todo_flags_finish */
+};
+
+class pass_live_range_shrinkage : public rtl_opt_pass
+{
+public:
+ pass_live_range_shrinkage(gcc::context *ctxt)
+ : rtl_opt_pass(pass_data_live_range_shrinkage, ctxt)
+ {}
+
+ /* opt_pass methods: */
+ bool gate () { return gate_handle_live_range_shrinkage (); }
+ unsigned int execute () { return rest_of_handle_live_range_shrinkage (); }
+
+}; // class pass_live_range_shrinkage
+
+} // anon namespace
+
+rtl_opt_pass *
+make_pass_live_range_shrinkage (gcc::context *ctxt)
+{
+ return new pass_live_range_shrinkage (ctxt);
+}
+
+namespace {
+
const pass_data pass_data_sched =
{
RTL_PASS, /* type */
@@ -3638,8 +3707,8 @@ const pass_data pass_data_sched =
class pass_sched : public rtl_opt_pass
{
public:
- pass_sched(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_sched, ctxt)
+ pass_sched (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_sched, ctxt)
{}
/* opt_pass methods: */
@@ -3677,8 +3746,8 @@ const pass_data pass_data_sched2 =
class pass_sched2 : public rtl_opt_pass
{
public:
- pass_sched2(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_sched2, ctxt)
+ pass_sched2 (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_sched2, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/sched-vis.c b/gcc/sched-vis.c
index eb2410cbc4f..a965c4d54d6 100644
--- a/gcc/sched-vis.c
+++ b/gcc/sched-vis.c
@@ -751,7 +751,10 @@ print_insn_with_notes (pretty_printer *pp, const_rtx x)
{
pp_printf (pp, "%s %s ", print_rtx_head,
GET_REG_NOTE_NAME (REG_NOTE_KIND (note)));
- print_pattern (pp, XEXP (note, 0), 1);
+ if (GET_CODE (note) == INT_LIST)
+ pp_printf (pp, "%d", XINT (note, 0));
+ else
+ print_pattern (pp, XEXP (note, 0), 1);
pp_newline (pp);
}
}
diff --git a/gcc/sdbout.c b/gcc/sdbout.c
index 13c11c29682..1eedde3f520 100644
--- a/gcc/sdbout.c
+++ b/gcc/sdbout.c
@@ -155,7 +155,7 @@ static void sdbout_global_decl (tree);
#endif
#ifndef PUT_SDB_SCL
-#define PUT_SDB_SCL(a) fprintf(asm_out_file, "\t.scl\t%d%s", (a), SDB_DELIM)
+#define PUT_SDB_SCL(a) fprintf (asm_out_file, "\t.scl\t%d%s", (a), SDB_DELIM)
#endif
#ifndef PUT_SDB_INT_VAL
@@ -182,15 +182,16 @@ do { fprintf (asm_out_file, "\t.def\t"); \
#endif
#ifndef PUT_SDB_PLAIN_DEF
-#define PUT_SDB_PLAIN_DEF(a) fprintf(asm_out_file,"\t.def\t.%s%s",a, SDB_DELIM)
+#define PUT_SDB_PLAIN_DEF(a) \
+ fprintf (asm_out_file, "\t.def\t.%s%s", a, SDB_DELIM)
#endif
#ifndef PUT_SDB_ENDEF
-#define PUT_SDB_ENDEF fputs("\t.endef\n", asm_out_file)
+#define PUT_SDB_ENDEF fputs ("\t.endef\n", asm_out_file)
#endif
#ifndef PUT_SDB_TYPE
-#define PUT_SDB_TYPE(a) fprintf(asm_out_file, "\t.type\t0%o%s", a, SDB_DELIM)
+#define PUT_SDB_TYPE(a) fprintf (asm_out_file, "\t.type\t0%o%s", a, SDB_DELIM)
#endif
#ifndef PUT_SDB_SIZE
@@ -198,19 +199,19 @@ do { fprintf (asm_out_file, "\t.def\t"); \
do { \
fprintf (asm_out_file, "\t.size\t" HOST_WIDE_INT_PRINT_DEC "%s", \
(HOST_WIDE_INT) (a), SDB_DELIM); \
- } while(0)
+ } while (0)
#endif
#ifndef PUT_SDB_START_DIM
-#define PUT_SDB_START_DIM fprintf(asm_out_file, "\t.dim\t")
+#define PUT_SDB_START_DIM fprintf (asm_out_file, "\t.dim\t")
#endif
#ifndef PUT_SDB_NEXT_DIM
-#define PUT_SDB_NEXT_DIM(a) fprintf(asm_out_file, "%d,", a)
+#define PUT_SDB_NEXT_DIM(a) fprintf (asm_out_file, "%d,", a)
#endif
#ifndef PUT_SDB_LAST_DIM
-#define PUT_SDB_LAST_DIM(a) fprintf(asm_out_file, "%d%s", a, SDB_DELIM)
+#define PUT_SDB_LAST_DIM(a) fprintf (asm_out_file, "%d%s", a, SDB_DELIM)
#endif
#ifndef PUT_SDB_TAG
diff --git a/gcc/sel-sched-ir.c b/gcc/sel-sched-ir.c
index 47e769534db..4eb27c5da5d 100644
--- a/gcc/sel-sched-ir.c
+++ b/gcc/sel-sched-ir.c
@@ -4881,7 +4881,7 @@ in_same_ebb_p (insn_t insn, insn_t succ)
{
basic_block ptr = BLOCK_FOR_INSN (insn);
- for(;;)
+ for (;;)
{
if (ptr == BLOCK_FOR_INSN (succ))
return true;
diff --git a/gcc/sel-sched.c b/gcc/sel-sched.c
index 46c66b4f3ed..08fdc772292 100644
--- a/gcc/sel-sched.c
+++ b/gcc/sel-sched.c
@@ -509,12 +509,12 @@ typedef vec<vinsn_t> vinsn_vec_t;
can't be moved up due to bookkeeping created during code motion to another
fence. See comment near the call to update_and_record_unavailable_insns
for the detailed explanations. */
-static vinsn_vec_t vec_bookkeeping_blocked_vinsns = vinsn_vec_t();
+static vinsn_vec_t vec_bookkeeping_blocked_vinsns = vinsn_vec_t ();
/* This vector has vinsns which are scheduled with renaming on the first fence
and then seen on the second. For expressions with such vinsns, target
availability information may be wrong. */
-static vinsn_vec_t vec_target_unavailable_vinsns = vinsn_vec_t();
+static vinsn_vec_t vec_target_unavailable_vinsns = vinsn_vec_t ();
/* Vector to store temporary nops inserted in move_op to prevent removal
of empty bbs. */
@@ -809,7 +809,7 @@ count_occurrences_1 (rtx *cur_rtx, void *arg)
/* Bail out if mode is different or more than one register is used. */
if (GET_MODE (*cur_rtx) != GET_MODE (p->x)
|| (HARD_REGISTER_P (*cur_rtx)
- && hard_regno_nregs[REGNO(*cur_rtx)][GET_MODE (*cur_rtx)] > 1))
+ && hard_regno_nregs[REGNO (*cur_rtx)][GET_MODE (*cur_rtx)] > 1))
{
p->n = 0;
return 1;
diff --git a/gcc/sese.c b/gcc/sese.c
index d5ffa25bbb9..1daf4576258 100644
--- a/gcc/sese.c
+++ b/gcc/sese.c
@@ -23,8 +23,16 @@ along with GCC; see the file COPYING3. If not see
#include "system.h"
#include "coretypes.h"
#include "hash-table.h"
+#include "tree.h"
#include "tree-pretty-print.h"
-#include "tree-ssa.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-cfg.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
+#include "tree-ssa-loop.h"
+#include "tree-into-ssa.h"
#include "cfgloop.h"
#include "tree-chrec.h"
#include "tree-data-ref.h"
@@ -32,6 +40,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-pass.h"
#include "value-prof.h"
#include "sese.h"
+#include "tree-ssa-propagate.h"
/* Print to stderr the element ELT. */
diff --git a/gcc/sparseset.c b/gcc/sparseset.c
index 3c25a6de355..279c22bf72b 100644
--- a/gcc/sparseset.c
+++ b/gcc/sparseset.c
@@ -30,7 +30,7 @@ sparseset_alloc (SPARSESET_ELT_TYPE n_elms)
unsigned int n_bytes = sizeof (struct sparseset_def)
+ ((n_elms - 1) * 2 * sizeof (SPARSESET_ELT_TYPE));
- sparseset set = XNEWVAR(struct sparseset_def, n_bytes);
+ sparseset set = XNEWVAR (struct sparseset_def, n_bytes);
/* Mark the sparseset as defined to silence some valgrind uninitialized
read errors when accessing set->sparse[n] when "n" is not, and never has
diff --git a/gcc/ssa-iterators.h b/gcc/ssa-iterators.h
new file mode 100644
index 00000000000..af486b6118d
--- /dev/null
+++ b/gcc/ssa-iterators.h
@@ -0,0 +1,996 @@
+/* Header file for SSA iterators.
+ Copyright (C) 2013 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_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_d 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. */
+typedef struct immediate_use_iterator_d
+{
+ /* 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;
+} imm_use_iterator;
+
+
+/* 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))))
+
+/* Use this iterator to visit each stmt which has a use of SSAVAR. */
+
+#define FOR_EACH_IMM_USE_STMT(STMT, ITER, SSAVAR) \
+ for ((STMT) = first_imm_use_stmt (&(ITER), (SSAVAR)); \
+ !end_imm_use_stmt_p (&(ITER)); \
+ (void) ((STMT) = next_imm_use_stmt (&(ITER))))
+
+/* Use this to terminate the FOR_EACH_IMM_USE_STMT loop early. Failure to
+ do so will result in leaving a iterator marker node in the immediate
+ use list, and nothing good will come from that. */
+#define BREAK_FROM_IMM_USE_STMT(ITER) \
+ { \
+ end_imm_use_stmt_traverse (&(ITER)); \
+ break; \
+ }
+
+
+/* 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, var)
+ {
+ 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 has_zero_uses_1 (const ssa_use_operand_t *head);
+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. */
+
+typedef struct ssa_operand_iterator_d
+{
+ enum ssa_op_iter_type iter_type;
+ bool done;
+ int flags;
+ unsigned i;
+ unsigned numops;
+ use_optype_p uses;
+ gimple stmt;
+} ssa_op_iter;
+
+/* 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), 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), 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;
+#ifdef ENABLE_CHECKING
+ imm->iter_node.next = imm->imm_use->next;
+#endif
+ 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;
+
+#ifdef ENABLE_CHECKING
+ /* 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. */
+ gcc_assert (imm->iter_node.next == old->next);
+ imm->iter_node.next = old->next->next;
+#endif
+
+ 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 ptr = &(SSA_NAME_IMM_USE_NODE (var));
+
+ /* A single use_operand means there is no items in the list. */
+ if (ptr == ptr->next)
+ return true;
+
+ /* If there are debug stmts, we have to look at each use and see
+ whether there are any nondebug uses. */
+ if (!MAY_HAVE_DEBUG_STMTS)
+ return false;
+
+ return has_zero_uses_1 (ptr);
+}
+
+/* Return true if VAR has a single nondebug use. */
+static inline bool
+has_single_use (const_tree var)
+{
+ 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;
+
+ /* If there's a single use, check that it's not a debug stmt. */
+ if (ptr == ptr->next->next)
+ return !is_gimple_debug (USE_STMT (ptr->next));
+
+ /* If there are debug stmts, we have to look at each of them. */
+ if (!MAY_HAVE_DEBUG_STMTS)
+ return false;
+
+ return single_imm_use_1 (ptr, NULL, NULL);
+}
+
+
+/* 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 (!is_gimple_debug (USE_STMT (ptr->next)))
+ {
+ *use_p = ptr->next;
+ *stmt = ptr->next->loc.stmt;
+ return true;
+ }
+ else
+ goto return_false;
+ }
+
+ /* If there are debug stmts, we have to look at each of them. */
+ if (!MAY_HAVE_DEBUG_STMTS)
+ 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_STMTS)
+ for (ptr = start->next; ptr != start; ptr = ptr->next)
+ num++;
+ else
+ for (ptr = start->next; ptr != start; ptr = ptr->next)
+ if (!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 (stmt);
+ 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;
+}
+
+
+
+/* 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 (gimple 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, gimple 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, gimple 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 (gimple_code (head_stmt) == GIMPLE_PHI)
+ {
+ FOR_EACH_PHI_ARG (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 (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/gcc/ssaexpand.h b/gcc/ssaexpand.h
deleted file mode 100644
index 0bdc8d48097..00000000000
--- a/gcc/ssaexpand.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/* Routines for expanding from SSA form to RTL.
- Copyright (C) 2009-2013 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 _SSAEXPAND_H
-#define _SSAEXPAND_H 1
-
-#include "tree-ssa-live.h"
-
-/* This structure (of which only a singleton SA exists) is used to
- pass around information between the outof-SSA functions, cfgexpand
- and expand itself. */
-struct ssaexpand
-{
- /* The computed partitions of SSA names are stored here. */
- var_map map;
-
- /* For an SSA name version V bit V is set iff TER decided that
- its definition should be forwarded. */
- bitmap values;
-
- /* For a partition number I partition_to_pseudo[I] contains the
- RTL expression of the allocated space of it (either a MEM or
- a pseudos REG). */
- rtx *partition_to_pseudo;
-
- /* If partition I contains an SSA name that has a default def,
- bit I will be set in this bitmap. */
- bitmap partition_has_default_def;
-};
-
-/* This is the singleton described above. */
-extern struct ssaexpand SA;
-
-/* Returns the RTX expression representing the storage of the outof-SSA
- partition that the SSA name EXP is a member of. */
-static inline rtx
-get_rtx_for_ssa_name (tree exp)
-{
- int p = partition_find (SA.map->var_partition, SSA_NAME_VERSION (exp));
- if (SA.map->partition_to_view)
- p = SA.map->partition_to_view[p];
- gcc_assert (p != NO_PARTITION);
- return SA.partition_to_pseudo[p];
-}
-
-/* If TER decided to forward the definition of SSA name EXP this function
- returns the defining statement, otherwise NULL. */
-static inline gimple
-get_gimple_for_ssa_name (tree exp)
-{
- int v = SSA_NAME_VERSION (exp);
- if (SA.values && bitmap_bit_p (SA.values, v))
- return SSA_NAME_DEF_STMT (exp);
- return NULL;
-}
-
-/* In tree-outof-ssa.c. */
-void finish_out_of_ssa (struct ssaexpand *sa);
-unsigned int rewrite_out_of_ssa (struct ssaexpand *sa);
-void expand_phi_nodes (struct ssaexpand *sa);
-
-#endif
diff --git a/gcc/stack-ptr-mod.c b/gcc/stack-ptr-mod.c
index 737a07f5727..68ccd1619ed 100644
--- a/gcc/stack-ptr-mod.c
+++ b/gcc/stack-ptr-mod.c
@@ -110,8 +110,8 @@ const pass_data pass_data_stack_ptr_mod =
class pass_stack_ptr_mod : public rtl_opt_pass
{
public:
- pass_stack_ptr_mod(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_stack_ptr_mod, ctxt)
+ pass_stack_ptr_mod (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_stack_ptr_mod, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/statistics.c b/gcc/statistics.c
index b198b3455fa..51d3f3af088 100644
--- a/gcc/statistics.c
+++ b/gcc/statistics.c
@@ -76,7 +76,7 @@ stats_counter_hasher::equal (const value_type *c1, const compare_type *c2)
inline void
stats_counter_hasher::remove (value_type *v)
{
- free (CONST_CAST(char *, v->id));
+ free (CONST_CAST (char *, v->id));
free (v);
}
@@ -260,8 +260,10 @@ statistics_fini (void)
void
statistics_early_init (void)
{
- statistics_dump_nr = dump_register (".statistics", "statistics",
- "statistics", TDF_TREE, OPTGROUP_NONE);
+ gcc::dump_manager *dumps = g->get_dumps ();
+ statistics_dump_nr = dumps->dump_register (".statistics", "statistics",
+ "statistics", TDF_TREE,
+ OPTGROUP_NONE);
}
/* Init the statistics. */
@@ -269,8 +271,9 @@ statistics_early_init (void)
void
statistics_init (void)
{
+ gcc::dump_manager *dumps = g->get_dumps ();
statistics_dump_file = dump_begin (statistics_dump_nr, NULL);
- statistics_dump_flags = get_dump_file_info (statistics_dump_nr)->pflags;
+ statistics_dump_flags = dumps->get_dump_file_info (statistics_dump_nr)->pflags;
}
/* Lookup or add a statistics counter in the hashtable HASH with ID, VAL
diff --git a/gcc/stmt.c b/gcc/stmt.c
index 1dc447a5c85..947dca9e8b8 100644
--- a/gcc/stmt.c
+++ b/gcc/stmt.c
@@ -102,13 +102,8 @@ typedef struct case_node *case_node_ptr;
extern basic_block label_to_block_fn (struct function *, tree);
-static int n_occurrences (int, const char *);
-static bool tree_conflicts_with_clobbers_p (tree, HARD_REG_SET *);
-static bool check_operand_nalternatives (tree, tree);
static bool check_unique_operand_names (tree, tree, tree);
static char *resolve_operand_name_1 (char *, tree, tree, tree);
-static void expand_null_return_1 (void);
-static void expand_value_return (rtx);
static void balance_case_nodes (case_node_ptr *, case_node_ptr);
static int node_has_low_bound (case_node_ptr, tree);
static int node_has_high_bound (case_node_ptr, tree);
@@ -157,20 +152,6 @@ emit_jump (rtx label)
emit_jump_insn (gen_jump (label));
emit_barrier ();
}
-
-/* Emit code to jump to the address
- specified by the pointer expression EXP. */
-
-void
-expand_computed_goto (tree exp)
-{
- rtx x = expand_normal (exp);
-
- x = convert_memory_address (Pmode, x);
-
- do_pending_stack_adjust ();
- emit_indirect_jump (x);
-}
/* Handle goto statements and the labels that they can go to. */
@@ -209,56 +190,7 @@ expand_label (tree label)
if (DECL_NONLOCAL (label) || FORCED_LABEL (label))
maybe_set_first_label_num (label_r);
}
-
-/* Generate RTL code for a `goto' statement with target label LABEL.
- LABEL should be a LABEL_DECL tree node that was or will later be
- defined with `expand_label'. */
-
-void
-expand_goto (tree label)
-{
-#ifdef ENABLE_CHECKING
- /* Check for a nonlocal goto to a containing function. Should have
- gotten translated to __builtin_nonlocal_goto. */
- tree context = decl_function_context (label);
- gcc_assert (!context || context == current_function_decl);
-#endif
-
- emit_jump (label_rtx (label));
-}
-/* Return the number of times character C occurs in string S. */
-static int
-n_occurrences (int c, const char *s)
-{
- int n = 0;
- while (*s)
- n += (*s++ == c);
- return n;
-}
-
-/* Generate RTL for an asm statement (explicit assembler code).
- STRING is a STRING_CST node containing the assembler code text,
- or an ADDR_EXPR containing a STRING_CST. VOL nonzero means the
- insn is volatile; don't optimize it. */
-
-static void
-expand_asm_loc (tree string, int vol, location_t locus)
-{
- rtx body;
-
- if (TREE_CODE (string) == ADDR_EXPR)
- string = TREE_OPERAND (string, 0);
-
- body = gen_rtx_ASM_INPUT_loc (VOIDmode,
- ggc_strdup (TREE_STRING_POINTER (string)),
- locus);
-
- MEM_VOLATILE_P (body) = vol;
-
- emit_insn (body);
-}
-
/* Parse the output constraint pointed to by *CONSTRAINT_P. It is the
OPERAND_NUMth output operand, indexed from zero. There are NINPUTS
inputs and NOUTPUTS outputs to this extended-asm. Upon return,
@@ -577,634 +509,6 @@ tree_overlaps_hard_reg_set (tree decl, HARD_REG_SET *regs)
return walk_tree (&decl, decl_overlaps_hard_reg_set_p, regs, NULL);
}
-/* Check for overlap between registers marked in CLOBBERED_REGS and
- anything inappropriate in T. Emit error and return the register
- variable definition for error, NULL_TREE for ok. */
-
-static bool
-tree_conflicts_with_clobbers_p (tree t, HARD_REG_SET *clobbered_regs)
-{
- /* Conflicts between asm-declared register variables and the clobber
- list are not allowed. */
- tree overlap = tree_overlaps_hard_reg_set (t, clobbered_regs);
-
- if (overlap)
- {
- error ("asm-specifier for variable %qE conflicts with asm clobber list",
- DECL_NAME (overlap));
-
- /* Reset registerness to stop multiple errors emitted for a single
- variable. */
- DECL_REGISTER (overlap) = 0;
- return true;
- }
-
- return false;
-}
-
-/* Generate RTL for an asm statement with arguments.
- STRING is the instruction template.
- OUTPUTS is a list of output arguments (lvalues); INPUTS a list of inputs.
- Each output or input has an expression in the TREE_VALUE and
- a tree list in TREE_PURPOSE which in turn contains a constraint
- name in TREE_VALUE (or NULL_TREE) and a constraint string
- in TREE_PURPOSE.
- CLOBBERS is a list of STRING_CST nodes each naming a hard register
- that is clobbered by this insn.
-
- Not all kinds of lvalue that may appear in OUTPUTS can be stored directly.
- Some elements of OUTPUTS may be replaced with trees representing temporary
- values. The caller should copy those temporary values to the originally
- specified lvalues.
-
- VOL nonzero means the insn is volatile; don't optimize it. */
-
-static void
-expand_asm_operands (tree string, tree outputs, tree inputs,
- tree clobbers, tree labels, int vol, location_t locus)
-{
- rtvec argvec, constraintvec, labelvec;
- rtx body;
- int ninputs = list_length (inputs);
- int noutputs = list_length (outputs);
- int nlabels = list_length (labels);
- int ninout;
- int nclobbers;
- HARD_REG_SET clobbered_regs;
- int clobber_conflict_found = 0;
- tree tail;
- tree t;
- int i;
- /* Vector of RTX's of evaluated output operands. */
- rtx *output_rtx = XALLOCAVEC (rtx, noutputs);
- int *inout_opnum = XALLOCAVEC (int, noutputs);
- rtx *real_output_rtx = XALLOCAVEC (rtx, noutputs);
- enum machine_mode *inout_mode = XALLOCAVEC (enum machine_mode, noutputs);
- const char **constraints = XALLOCAVEC (const char *, noutputs + ninputs);
- int old_generating_concat_p = generating_concat_p;
-
- /* An ASM with no outputs needs to be treated as volatile, for now. */
- if (noutputs == 0)
- vol = 1;
-
- if (! check_operand_nalternatives (outputs, inputs))
- return;
-
- string = resolve_asm_operand_names (string, outputs, inputs, labels);
-
- /* Collect constraints. */
- i = 0;
- for (t = outputs; t ; t = TREE_CHAIN (t), i++)
- constraints[i] = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t)));
- for (t = inputs; t ; t = TREE_CHAIN (t), i++)
- constraints[i] = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t)));
-
- /* Sometimes we wish to automatically clobber registers across an asm.
- Case in point is when the i386 backend moved from cc0 to a hard reg --
- maintaining source-level compatibility means automatically clobbering
- the flags register. */
- clobbers = targetm.md_asm_clobbers (outputs, inputs, clobbers);
-
- /* Count the number of meaningful clobbered registers, ignoring what
- we would ignore later. */
- nclobbers = 0;
- CLEAR_HARD_REG_SET (clobbered_regs);
- for (tail = clobbers; tail; tail = TREE_CHAIN (tail))
- {
- const char *regname;
- int nregs;
-
- if (TREE_VALUE (tail) == error_mark_node)
- return;
- regname = TREE_STRING_POINTER (TREE_VALUE (tail));
-
- i = decode_reg_name_and_count (regname, &nregs);
- if (i == -4)
- ++nclobbers;
- else if (i == -2)
- error ("unknown register name %qs in %<asm%>", regname);
-
- /* Mark clobbered registers. */
- if (i >= 0)
- {
- int reg;
-
- for (reg = i; reg < i + nregs; reg++)
- {
- ++nclobbers;
-
- /* Clobbering the PIC register is an error. */
- if (reg == (int) PIC_OFFSET_TABLE_REGNUM)
- {
- error ("PIC register clobbered by %qs in %<asm%>", regname);
- return;
- }
-
- SET_HARD_REG_BIT (clobbered_regs, reg);
- }
- }
- }
-
- /* First pass over inputs and outputs checks validity and sets
- mark_addressable if needed. */
-
- ninout = 0;
- for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
- {
- tree val = TREE_VALUE (tail);
- tree type = TREE_TYPE (val);
- const char *constraint;
- bool is_inout;
- bool allows_reg;
- bool allows_mem;
-
- /* If there's an erroneous arg, emit no insn. */
- if (type == error_mark_node)
- return;
-
- /* Try to parse the output constraint. If that fails, there's
- no point in going further. */
- constraint = constraints[i];
- if (!parse_output_constraint (&constraint, i, ninputs, noutputs,
- &allows_mem, &allows_reg, &is_inout))
- return;
-
- if (! allows_reg
- && (allows_mem
- || is_inout
- || (DECL_P (val)
- && REG_P (DECL_RTL (val))
- && GET_MODE (DECL_RTL (val)) != TYPE_MODE (type))))
- mark_addressable (val);
-
- if (is_inout)
- ninout++;
- }
-
- ninputs += ninout;
- if (ninputs + noutputs > MAX_RECOG_OPERANDS)
- {
- error ("more than %d operands in %<asm%>", MAX_RECOG_OPERANDS);
- return;
- }
-
- for (i = 0, tail = inputs; tail; i++, tail = TREE_CHAIN (tail))
- {
- bool allows_reg, allows_mem;
- const char *constraint;
-
- /* If there's an erroneous arg, emit no insn, because the ASM_INPUT
- would get VOIDmode and that could cause a crash in reload. */
- if (TREE_TYPE (TREE_VALUE (tail)) == error_mark_node)
- return;
-
- constraint = constraints[i + noutputs];
- if (! parse_input_constraint (&constraint, i, ninputs, noutputs, ninout,
- constraints, &allows_mem, &allows_reg))
- return;
-
- if (! allows_reg && allows_mem)
- mark_addressable (TREE_VALUE (tail));
- }
-
- /* Second pass evaluates arguments. */
-
- /* Make sure stack is consistent for asm goto. */
- if (nlabels > 0)
- do_pending_stack_adjust ();
-
- ninout = 0;
- for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
- {
- tree val = TREE_VALUE (tail);
- tree type = TREE_TYPE (val);
- bool is_inout;
- bool allows_reg;
- bool allows_mem;
- rtx op;
- bool ok;
-
- ok = parse_output_constraint (&constraints[i], i, ninputs,
- noutputs, &allows_mem, &allows_reg,
- &is_inout);
- gcc_assert (ok);
-
- /* If an output operand is not a decl or indirect ref and our constraint
- allows a register, make a temporary to act as an intermediate.
- Make the asm insn write into that, then our caller will copy it to
- the real output operand. Likewise for promoted variables. */
-
- generating_concat_p = 0;
-
- real_output_rtx[i] = NULL_RTX;
- if ((TREE_CODE (val) == INDIRECT_REF
- && allows_mem)
- || (DECL_P (val)
- && (allows_mem || REG_P (DECL_RTL (val)))
- && ! (REG_P (DECL_RTL (val))
- && GET_MODE (DECL_RTL (val)) != TYPE_MODE (type)))
- || ! allows_reg
- || is_inout)
- {
- op = expand_expr (val, NULL_RTX, VOIDmode, EXPAND_WRITE);
- if (MEM_P (op))
- op = validize_mem (op);
-
- if (! allows_reg && !MEM_P (op))
- error ("output number %d not directly addressable", i);
- if ((! allows_mem && MEM_P (op))
- || GET_CODE (op) == CONCAT)
- {
- real_output_rtx[i] = op;
- op = gen_reg_rtx (GET_MODE (op));
- if (is_inout)
- emit_move_insn (op, real_output_rtx[i]);
- }
- }
- else
- {
- op = assign_temp (type, 0, 1);
- op = validize_mem (op);
- if (!MEM_P (op) && TREE_CODE (TREE_VALUE (tail)) == SSA_NAME)
- set_reg_attrs_for_decl_rtl (SSA_NAME_VAR (TREE_VALUE (tail)), op);
- TREE_VALUE (tail) = make_tree (type, op);
- }
- output_rtx[i] = op;
-
- generating_concat_p = old_generating_concat_p;
-
- if (is_inout)
- {
- inout_mode[ninout] = TYPE_MODE (type);
- inout_opnum[ninout++] = i;
- }
-
- if (tree_conflicts_with_clobbers_p (val, &clobbered_regs))
- clobber_conflict_found = 1;
- }
-
- /* Make vectors for the expression-rtx, constraint strings,
- and named operands. */
-
- argvec = rtvec_alloc (ninputs);
- constraintvec = rtvec_alloc (ninputs);
- labelvec = rtvec_alloc (nlabels);
-
- body = gen_rtx_ASM_OPERANDS ((noutputs == 0 ? VOIDmode
- : GET_MODE (output_rtx[0])),
- ggc_strdup (TREE_STRING_POINTER (string)),
- empty_string, 0, argvec, constraintvec,
- labelvec, locus);
-
- MEM_VOLATILE_P (body) = vol;
-
- /* Eval the inputs and put them into ARGVEC.
- Put their constraints into ASM_INPUTs and store in CONSTRAINTS. */
-
- for (i = 0, tail = inputs; tail; tail = TREE_CHAIN (tail), ++i)
- {
- bool allows_reg, allows_mem;
- const char *constraint;
- tree val, type;
- rtx op;
- bool ok;
-
- constraint = constraints[i + noutputs];
- ok = parse_input_constraint (&constraint, i, ninputs, noutputs, ninout,
- constraints, &allows_mem, &allows_reg);
- gcc_assert (ok);
-
- generating_concat_p = 0;
-
- val = TREE_VALUE (tail);
- type = TREE_TYPE (val);
- /* EXPAND_INITIALIZER will not generate code for valid initializer
- constants, but will still generate code for other types of operand.
- This is the behavior we want for constant constraints. */
- op = expand_expr (val, NULL_RTX, VOIDmode,
- allows_reg ? EXPAND_NORMAL
- : allows_mem ? EXPAND_MEMORY
- : EXPAND_INITIALIZER);
-
- /* Never pass a CONCAT to an ASM. */
- if (GET_CODE (op) == CONCAT)
- op = force_reg (GET_MODE (op), op);
- else if (MEM_P (op))
- op = validize_mem (op);
-
- if (asm_operand_ok (op, constraint, NULL) <= 0)
- {
- if (allows_reg && TYPE_MODE (type) != BLKmode)
- op = force_reg (TYPE_MODE (type), op);
- else if (!allows_mem)
- warning (0, "asm operand %d probably doesn%'t match constraints",
- i + noutputs);
- else if (MEM_P (op))
- {
- /* We won't recognize either volatile memory or memory
- with a queued address as available a memory_operand
- at this point. Ignore it: clearly this *is* a memory. */
- }
- else
- gcc_unreachable ();
- }
-
- generating_concat_p = old_generating_concat_p;
- ASM_OPERANDS_INPUT (body, i) = op;
-
- ASM_OPERANDS_INPUT_CONSTRAINT_EXP (body, i)
- = gen_rtx_ASM_INPUT (TYPE_MODE (type),
- ggc_strdup (constraints[i + noutputs]));
-
- if (tree_conflicts_with_clobbers_p (val, &clobbered_regs))
- clobber_conflict_found = 1;
- }
-
- /* Protect all the operands from the queue now that they have all been
- evaluated. */
-
- generating_concat_p = 0;
-
- /* For in-out operands, copy output rtx to input rtx. */
- for (i = 0; i < ninout; i++)
- {
- int j = inout_opnum[i];
- char buffer[16];
-
- ASM_OPERANDS_INPUT (body, ninputs - ninout + i)
- = output_rtx[j];
-
- sprintf (buffer, "%d", j);
- ASM_OPERANDS_INPUT_CONSTRAINT_EXP (body, ninputs - ninout + i)
- = gen_rtx_ASM_INPUT (inout_mode[i], ggc_strdup (buffer));
- }
-
- /* Copy labels to the vector. */
- for (i = 0, tail = labels; i < nlabels; ++i, tail = TREE_CHAIN (tail))
- ASM_OPERANDS_LABEL (body, i)
- = gen_rtx_LABEL_REF (Pmode, label_rtx (TREE_VALUE (tail)));
-
- generating_concat_p = old_generating_concat_p;
-
- /* Now, for each output, construct an rtx
- (set OUTPUT (asm_operands INSN OUTPUTCONSTRAINT OUTPUTNUMBER
- ARGVEC CONSTRAINTS OPNAMES))
- If there is more than one, put them inside a PARALLEL. */
-
- if (nlabels > 0 && nclobbers == 0)
- {
- gcc_assert (noutputs == 0);
- emit_jump_insn (body);
- }
- else if (noutputs == 0 && nclobbers == 0)
- {
- /* No output operands: put in a raw ASM_OPERANDS rtx. */
- emit_insn (body);
- }
- else if (noutputs == 1 && nclobbers == 0)
- {
- ASM_OPERANDS_OUTPUT_CONSTRAINT (body) = ggc_strdup (constraints[0]);
- emit_insn (gen_rtx_SET (VOIDmode, output_rtx[0], body));
- }
- else
- {
- rtx obody = body;
- int num = noutputs;
-
- if (num == 0)
- num = 1;
-
- body = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (num + nclobbers));
-
- /* For each output operand, store a SET. */
- for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
- {
- XVECEXP (body, 0, i)
- = gen_rtx_SET (VOIDmode,
- output_rtx[i],
- gen_rtx_ASM_OPERANDS
- (GET_MODE (output_rtx[i]),
- ggc_strdup (TREE_STRING_POINTER (string)),
- ggc_strdup (constraints[i]),
- i, argvec, constraintvec, labelvec, locus));
-
- MEM_VOLATILE_P (SET_SRC (XVECEXP (body, 0, i))) = vol;
- }
-
- /* If there are no outputs (but there are some clobbers)
- store the bare ASM_OPERANDS into the PARALLEL. */
-
- if (i == 0)
- XVECEXP (body, 0, i++) = obody;
-
- /* Store (clobber REG) for each clobbered register specified. */
-
- for (tail = clobbers; tail; tail = TREE_CHAIN (tail))
- {
- const char *regname = TREE_STRING_POINTER (TREE_VALUE (tail));
- int reg, nregs;
- int j = decode_reg_name_and_count (regname, &nregs);
- rtx clobbered_reg;
-
- if (j < 0)
- {
- if (j == -3) /* `cc', which is not a register */
- continue;
-
- if (j == -4) /* `memory', don't cache memory across asm */
- {
- XVECEXP (body, 0, i++)
- = gen_rtx_CLOBBER (VOIDmode,
- gen_rtx_MEM
- (BLKmode,
- gen_rtx_SCRATCH (VOIDmode)));
- continue;
- }
-
- /* Ignore unknown register, error already signaled. */
- continue;
- }
-
- for (reg = j; reg < j + nregs; reg++)
- {
- /* Use QImode since that's guaranteed to clobber just
- * one reg. */
- clobbered_reg = gen_rtx_REG (QImode, reg);
-
- /* Do sanity check for overlap between clobbers and
- respectively input and outputs that hasn't been
- handled. Such overlap should have been detected and
- reported above. */
- if (!clobber_conflict_found)
- {
- int opno;
-
- /* We test the old body (obody) contents to avoid
- tripping over the under-construction body. */
- for (opno = 0; opno < noutputs; opno++)
- if (reg_overlap_mentioned_p (clobbered_reg,
- output_rtx[opno]))
- internal_error
- ("asm clobber conflict with output operand");
-
- for (opno = 0; opno < ninputs - ninout; opno++)
- if (reg_overlap_mentioned_p (clobbered_reg,
- ASM_OPERANDS_INPUT (obody,
- opno)))
- internal_error
- ("asm clobber conflict with input operand");
- }
-
- XVECEXP (body, 0, i++)
- = gen_rtx_CLOBBER (VOIDmode, clobbered_reg);
- }
- }
-
- if (nlabels > 0)
- emit_jump_insn (body);
- else
- emit_insn (body);
- }
-
- /* For any outputs that needed reloading into registers, spill them
- back to where they belong. */
- for (i = 0; i < noutputs; ++i)
- if (real_output_rtx[i])
- emit_move_insn (real_output_rtx[i], output_rtx[i]);
-
- crtl->has_asm_statement = 1;
- free_temp_slots ();
-}
-
-void
-expand_asm_stmt (gimple stmt)
-{
- int noutputs;
- tree outputs, tail, t;
- tree *o;
- size_t i, n;
- const char *s;
- tree str, out, in, cl, labels;
- location_t locus = gimple_location (stmt);
-
- /* Meh... convert the gimple asm operands into real tree lists.
- Eventually we should make all routines work on the vectors instead
- of relying on TREE_CHAIN. */
- out = NULL_TREE;
- n = gimple_asm_noutputs (stmt);
- if (n > 0)
- {
- t = out = gimple_asm_output_op (stmt, 0);
- for (i = 1; i < n; i++)
- t = TREE_CHAIN (t) = gimple_asm_output_op (stmt, i);
- }
-
- in = NULL_TREE;
- n = gimple_asm_ninputs (stmt);
- if (n > 0)
- {
- t = in = gimple_asm_input_op (stmt, 0);
- for (i = 1; i < n; i++)
- t = TREE_CHAIN (t) = gimple_asm_input_op (stmt, i);
- }
-
- cl = NULL_TREE;
- n = gimple_asm_nclobbers (stmt);
- if (n > 0)
- {
- t = cl = gimple_asm_clobber_op (stmt, 0);
- for (i = 1; i < n; i++)
- t = TREE_CHAIN (t) = gimple_asm_clobber_op (stmt, i);
- }
-
- labels = NULL_TREE;
- n = gimple_asm_nlabels (stmt);
- if (n > 0)
- {
- t = labels = gimple_asm_label_op (stmt, 0);
- for (i = 1; i < n; i++)
- t = TREE_CHAIN (t) = gimple_asm_label_op (stmt, i);
- }
-
- s = gimple_asm_string (stmt);
- str = build_string (strlen (s), s);
-
- if (gimple_asm_input_p (stmt))
- {
- expand_asm_loc (str, gimple_asm_volatile_p (stmt), locus);
- return;
- }
-
- outputs = out;
- noutputs = gimple_asm_noutputs (stmt);
- /* o[I] is the place that output number I should be written. */
- o = (tree *) alloca (noutputs * sizeof (tree));
-
- /* Record the contents of OUTPUTS before it is modified. */
- for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
- o[i] = TREE_VALUE (tail);
-
- /* Generate the ASM_OPERANDS insn; store into the TREE_VALUEs of
- OUTPUTS some trees for where the values were actually stored. */
- expand_asm_operands (str, outputs, in, cl, labels,
- gimple_asm_volatile_p (stmt), locus);
-
- /* Copy all the intermediate outputs into the specified outputs. */
- for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
- {
- if (o[i] != TREE_VALUE (tail))
- {
- expand_assignment (o[i], TREE_VALUE (tail), false);
- free_temp_slots ();
-
- /* Restore the original value so that it's correct the next
- time we expand this function. */
- TREE_VALUE (tail) = o[i];
- }
- }
-}
-
-/* A subroutine of expand_asm_operands. Check that all operands have
- the same number of alternatives. Return true if so. */
-
-static bool
-check_operand_nalternatives (tree outputs, tree inputs)
-{
- if (outputs || inputs)
- {
- tree tmp = TREE_PURPOSE (outputs ? outputs : inputs);
- int nalternatives
- = n_occurrences (',', TREE_STRING_POINTER (TREE_VALUE (tmp)));
- tree next = inputs;
-
- if (nalternatives + 1 > MAX_RECOG_ALTERNATIVES)
- {
- error ("too many alternatives in %<asm%>");
- return false;
- }
-
- tmp = outputs;
- while (tmp)
- {
- const char *constraint
- = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (tmp)));
-
- if (n_occurrences (',', constraint) != nalternatives)
- {
- error ("operand constraints for %<asm%> differ "
- "in number of alternatives");
- return false;
- }
-
- if (TREE_CHAIN (tmp))
- tmp = TREE_CHAIN (tmp);
- else
- tmp = next, next = 0;
- }
- }
-
- return true;
-}
/* A subroutine of expand_asm_operands. Check that all operand names
are unique. Return true if so. We rely on the fact that these names
@@ -1398,19 +702,6 @@ resolve_operand_name_1 (char *p, tree outputs, tree inputs, tree labels)
return p;
}
-/* Generate RTL to return from the current function, with no value.
- (That is, we do not do anything about returning any value.) */
-
-void
-expand_null_return (void)
-{
- /* If this function was declared to return a value, but we
- didn't, clobber the return registers so that they are not
- propagated live to the rest of the function. */
- clobber_return_register ();
-
- expand_null_return_1 ();
-}
/* Generate RTL to return directly from the current function.
(That is, we bypass any return value.) */
@@ -1430,154 +721,6 @@ expand_naked_return (void)
emit_jump (end_label);
}
-/* Generate RTL to return from the current function, with value VAL. */
-
-static void
-expand_value_return (rtx val)
-{
- /* Copy the value to the return location unless it's already there. */
-
- tree decl = DECL_RESULT (current_function_decl);
- rtx return_reg = DECL_RTL (decl);
- if (return_reg != val)
- {
- tree funtype = TREE_TYPE (current_function_decl);
- tree type = TREE_TYPE (decl);
- int unsignedp = TYPE_UNSIGNED (type);
- enum machine_mode old_mode = DECL_MODE (decl);
- enum machine_mode mode;
- if (DECL_BY_REFERENCE (decl))
- mode = promote_function_mode (type, old_mode, &unsignedp, funtype, 2);
- else
- mode = promote_function_mode (type, old_mode, &unsignedp, funtype, 1);
-
- if (mode != old_mode)
- val = convert_modes (mode, old_mode, val, unsignedp);
-
- if (GET_CODE (return_reg) == PARALLEL)
- emit_group_load (return_reg, val, type, int_size_in_bytes (type));
- else
- emit_move_insn (return_reg, val);
- }
-
- expand_null_return_1 ();
-}
-
-/* Output a return with no value. */
-
-static void
-expand_null_return_1 (void)
-{
- clear_pending_stack_adjust ();
- do_pending_stack_adjust ();
- emit_jump (return_label);
-}
-
-/* Generate RTL to evaluate the expression RETVAL and return it
- from the current function. */
-
-void
-expand_return (tree retval)
-{
- rtx result_rtl;
- rtx val = 0;
- tree retval_rhs;
-
- /* If function wants no value, give it none. */
- if (TREE_CODE (TREE_TYPE (TREE_TYPE (current_function_decl))) == VOID_TYPE)
- {
- expand_normal (retval);
- expand_null_return ();
- return;
- }
-
- if (retval == error_mark_node)
- {
- /* Treat this like a return of no value from a function that
- returns a value. */
- expand_null_return ();
- return;
- }
- else if ((TREE_CODE (retval) == MODIFY_EXPR
- || TREE_CODE (retval) == INIT_EXPR)
- && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
- retval_rhs = TREE_OPERAND (retval, 1);
- else
- retval_rhs = retval;
-
- result_rtl = DECL_RTL (DECL_RESULT (current_function_decl));
-
- /* If we are returning the RESULT_DECL, then the value has already
- been stored into it, so we don't have to do anything special. */
- if (TREE_CODE (retval_rhs) == RESULT_DECL)
- expand_value_return (result_rtl);
-
- /* If the result is an aggregate that is being returned in one (or more)
- registers, load the registers here. */
-
- else if (retval_rhs != 0
- && TYPE_MODE (TREE_TYPE (retval_rhs)) == BLKmode
- && REG_P (result_rtl))
- {
- val = copy_blkmode_to_reg (GET_MODE (result_rtl), retval_rhs);
- if (val)
- {
- /* Use the mode of the result value on the return register. */
- PUT_MODE (result_rtl, GET_MODE (val));
- expand_value_return (val);
- }
- else
- expand_null_return ();
- }
- else if (retval_rhs != 0
- && !VOID_TYPE_P (TREE_TYPE (retval_rhs))
- && (REG_P (result_rtl)
- || (GET_CODE (result_rtl) == PARALLEL)))
- {
- /* Calculate the return value into a temporary (usually a pseudo
- reg). */
- tree ot = TREE_TYPE (DECL_RESULT (current_function_decl));
- tree nt = build_qualified_type (ot, TYPE_QUALS (ot) | TYPE_QUAL_CONST);
-
- val = assign_temp (nt, 0, 1);
- val = expand_expr (retval_rhs, val, GET_MODE (val), EXPAND_NORMAL);
- val = force_not_mem (val);
- /* Return the calculated value. */
- expand_value_return (val);
- }
- else
- {
- /* No hard reg used; calculate value into hard return reg. */
- expand_expr (retval, const0_rtx, VOIDmode, EXPAND_NORMAL);
- expand_value_return (result_rtl);
- }
-}
-
-
-/* Emit code to save the current value of stack. */
-rtx
-expand_stack_save (void)
-{
- rtx ret = NULL_RTX;
-
- do_pending_stack_adjust ();
- emit_stack_save (SAVE_BLOCK, &ret);
- return ret;
-}
-
-/* Emit code to restore the current value of stack. */
-void
-expand_stack_restore (tree var)
-{
- rtx prev, sa = expand_normal (var);
-
- sa = convert_memory_address (Pmode, sa);
-
- prev = get_last_insn ();
- emit_stack_restore (SAVE_BLOCK, sa);
- fixup_args_size_notes (prev, get_last_insn (), 0);
-}
-
/* Generate code to jump to LABEL if OP0 and OP1 are equal in mode MODE. PROB
is the probability of jumping to LABEL. */
static void
@@ -1638,11 +781,11 @@ dump_case_nodes (FILE *f, struct case_node *root,
fputs (";; ", f);
if (high == low)
- fprintf(f, "%*s" HOST_WIDE_INT_PRINT_DEC,
- indent_step * indent_level, "", low);
+ fprintf (f, "%*s" HOST_WIDE_INT_PRINT_DEC,
+ indent_step * indent_level, "", low);
else
- fprintf(f, "%*s" HOST_WIDE_INT_PRINT_DEC " ... " HOST_WIDE_INT_PRINT_DEC,
- indent_step * indent_level, "", low, high);
+ fprintf (f, "%*s" HOST_WIDE_INT_PRINT_DEC " ... " HOST_WIDE_INT_PRINT_DEC,
+ indent_step * indent_level, "", low, high);
fputs ("\n", f);
dump_case_nodes (f, root->right, indent_step, indent_level);
@@ -1799,7 +942,7 @@ get_outgoing_edge_probs (basic_block bb)
int prob_sum = 0;
if (!bb)
return 0;
- FOR_EACH_EDGE(e, ei, bb->succs)
+ FOR_EACH_EDGE (e, ei, bb->succs)
prob_sum += e->probability;
return prob_sum;
}
@@ -1848,7 +991,7 @@ emit_case_dispatch_table (tree index_expr, tree index_type,
rtx fallback_label = label_rtx (case_list->code_label);
rtx table_label = gen_label_rtx ();
bool has_gaps = false;
- edge default_edge = stmt_bb ? EDGE_SUCC(stmt_bb, 0) : NULL;
+ edge default_edge = stmt_bb ? EDGE_SUCC (stmt_bb, 0) : NULL;
int default_prob = default_edge ? default_edge->probability : 0;
int base = get_outgoing_edge_probs (stmt_bb);
bool try_with_tablejump = false;
@@ -1973,7 +1116,7 @@ reset_out_edges_aux (basic_block bb)
{
edge e;
edge_iterator ei;
- FOR_EACH_EDGE(e, ei, bb->succs)
+ FOR_EACH_EDGE (e, ei, bb->succs)
e->aux = (void *)0;
}
@@ -2039,7 +1182,7 @@ expand_case (gimple stmt)
/* Find the default case target label. */
default_label = label_rtx (CASE_LABEL (gimple_switch_default_label (stmt)));
- edge default_edge = EDGE_SUCC(bb, 0);
+ edge default_edge = EDGE_SUCC (bb, 0);
int default_prob = default_edge->probability;
/* Get upper and lower bounds of case values. */
diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c
index 6f6b3107841..f390eea7910 100644
--- a/gcc/stor-layout.c
+++ b/gcc/stor-layout.c
@@ -383,6 +383,7 @@ int_mode_for_mode (enum machine_mode mode)
case MODE_VECTOR_ACCUM:
case MODE_VECTOR_UFRACT:
case MODE_VECTOR_UACCUM:
+ case MODE_POINTER_BOUNDS:
mode = mode_for_size (GET_MODE_BITSIZE (mode), MODE_INT, 0);
break;
@@ -606,14 +607,10 @@ layout_decl (tree decl, unsigned int known_align)
/* See if we can use an ordinary integer mode for a bit-field.
Conditions are: a fixed size that is correct for another mode,
- occupying a complete byte or bytes on proper boundary,
- and not -fstrict-volatile-bitfields. If the latter is set,
- we unfortunately can't check TREE_THIS_VOLATILE, as a cast
- may make a volatile object later. */
+ occupying a complete byte or bytes on proper boundary. */
if (TYPE_SIZE (type) != 0
&& TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
- && GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
- && flag_strict_volatile_bitfields <= 0)
+ && GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT)
{
enum machine_mode xmode
= mode_for_size_tree (DECL_SIZE (decl), MODE_INT, 1);
@@ -1352,7 +1349,7 @@ place_field (record_layout_info rli, tree field)
/* Cause a new bitfield to be captured, either this time (if
currently a bitfield) or next time we see one. */
- if (!DECL_BIT_FIELD_TYPE(field)
+ if (!DECL_BIT_FIELD_TYPE (field)
|| integer_zerop (DECL_SIZE (field)))
rli->prev_field = NULL;
}
@@ -2052,18 +2049,9 @@ layout_type (tree type)
of the language-specific code. */
gcc_unreachable ();
- case BOOLEAN_TYPE: /* Used for Java, Pascal, and Chill. */
- if (TYPE_PRECISION (type) == 0)
- TYPE_PRECISION (type) = 1; /* default to one byte/boolean. */
-
- /* ... fall through ... */
-
+ case BOOLEAN_TYPE:
case INTEGER_TYPE:
case ENUMERAL_TYPE:
- if (TREE_CODE (TYPE_MIN_VALUE (type)) == INTEGER_CST
- && tree_int_cst_sgn (TYPE_MIN_VALUE (type)) >= 0)
- TYPE_UNSIGNED (type) = 1;
-
SET_TYPE_MODE (type,
smallest_mode_for_size (TYPE_PRECISION (type), MODE_INT));
TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (TYPE_MODE (type)));
@@ -2135,6 +2123,14 @@ layout_type (tree type)
SET_TYPE_MODE (type, VOIDmode);
break;
+ case POINTER_BOUNDS_TYPE:
+ SET_TYPE_MODE (type,
+ mode_for_size (TYPE_PRECISION (type),
+ MODE_POINTER_BOUNDS, 0));
+ TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (TYPE_MODE (type)));
+ TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (TYPE_MODE (type)));
+ break;
+
case OFFSET_TYPE:
TYPE_SIZE (type) = bitsize_int (POINTER_SIZE);
TYPE_SIZE_UNIT (type) = size_int (POINTER_SIZE / BITS_PER_UNIT);
@@ -2520,6 +2516,12 @@ set_min_and_max_values_for_integral_type (tree type,
tree min_value;
tree max_value;
+ /* For bitfields with zero width we end up creating integer types
+ with zero precision. Don't assign any minimum/maximum values
+ to those types, they don't have any valid value. */
+ if (precision < 1)
+ return;
+
if (is_unsigned)
{
min_value = build_int_cst (type, 0);
@@ -2627,12 +2629,12 @@ bit_field_mode_iterator
HOST_WIDE_INT bitregion_start,
HOST_WIDE_INT bitregion_end,
unsigned int align, bool volatilep)
-: mode_ (GET_CLASS_NARROWEST_MODE (MODE_INT)), bitsize_ (bitsize),
- bitpos_ (bitpos), bitregion_start_ (bitregion_start),
- bitregion_end_ (bitregion_end), align_ (align),
- volatilep_ (volatilep), count_ (0)
+: m_mode (GET_CLASS_NARROWEST_MODE (MODE_INT)), m_bitsize (bitsize),
+ m_bitpos (bitpos), m_bitregion_start (bitregion_start),
+ m_bitregion_end (bitregion_end), m_align (align),
+ m_volatilep (volatilep), m_count (0)
{
- if (!bitregion_end_)
+ if (!m_bitregion_end)
{
/* We can assume that any aligned chunk of ALIGN bits that overlaps
the bitfield is mapped and won't trap, provided that ALIGN isn't
@@ -2642,8 +2644,8 @@ bit_field_mode_iterator
= MIN (align, MAX (BIGGEST_ALIGNMENT, BITS_PER_WORD));
if (bitsize <= 0)
bitsize = 1;
- bitregion_end_ = bitpos + bitsize + units - 1;
- bitregion_end_ -= bitregion_end_ % units + 1;
+ m_bitregion_end = bitpos + bitsize + units - 1;
+ m_bitregion_end -= m_bitregion_end % units + 1;
}
}
@@ -2654,12 +2656,12 @@ bit_field_mode_iterator
bool
bit_field_mode_iterator::next_mode (enum machine_mode *out_mode)
{
- for (; mode_ != VOIDmode; mode_ = GET_MODE_WIDER_MODE (mode_))
+ for (; m_mode != VOIDmode; m_mode = GET_MODE_WIDER_MODE (m_mode))
{
- unsigned int unit = GET_MODE_BITSIZE (mode_);
+ unsigned int unit = GET_MODE_BITSIZE (m_mode);
/* Skip modes that don't have full precision. */
- if (unit != GET_MODE_PRECISION (mode_))
+ if (unit != GET_MODE_PRECISION (m_mode))
continue;
/* Stop if the mode is too wide to handle efficiently. */
@@ -2668,31 +2670,31 @@ bit_field_mode_iterator::next_mode (enum machine_mode *out_mode)
/* Don't deliver more than one multiword mode; the smallest one
should be used. */
- if (count_ > 0 && unit > BITS_PER_WORD)
+ if (m_count > 0 && unit > BITS_PER_WORD)
break;
/* Skip modes that are too small. */
- unsigned HOST_WIDE_INT substart = (unsigned HOST_WIDE_INT) bitpos_ % unit;
- unsigned HOST_WIDE_INT subend = substart + bitsize_;
+ unsigned HOST_WIDE_INT substart = (unsigned HOST_WIDE_INT) m_bitpos % unit;
+ unsigned HOST_WIDE_INT subend = substart + m_bitsize;
if (subend > unit)
continue;
/* Stop if the mode goes outside the bitregion. */
- HOST_WIDE_INT start = bitpos_ - substart;
- if (bitregion_start_ && start < bitregion_start_)
+ HOST_WIDE_INT start = m_bitpos - substart;
+ if (m_bitregion_start && start < m_bitregion_start)
break;
HOST_WIDE_INT end = start + unit;
- if (end > bitregion_end_ + 1)
+ if (end > m_bitregion_end + 1)
break;
/* Stop if the mode requires too much alignment. */
- if (GET_MODE_ALIGNMENT (mode_) > align_
- && SLOW_UNALIGNED_ACCESS (mode_, align_))
+ if (GET_MODE_ALIGNMENT (m_mode) > m_align
+ && SLOW_UNALIGNED_ACCESS (m_mode, m_align))
break;
- *out_mode = mode_;
- mode_ = GET_MODE_WIDER_MODE (mode_);
- count_++;
+ *out_mode = m_mode;
+ m_mode = GET_MODE_WIDER_MODE (m_mode);
+ m_count++;
return true;
}
return false;
@@ -2704,7 +2706,7 @@ bit_field_mode_iterator::next_mode (enum machine_mode *out_mode)
bool
bit_field_mode_iterator::prefer_smaller_modes ()
{
- return (volatilep_
+ return (m_volatilep
? targetm.narrow_volatile_bitfield ()
: !SLOW_BYTE_ACCESS);
}
diff --git a/gcc/store-motion.c b/gcc/store-motion.c
index e0b58477d4c..68f293c6252 100644
--- a/gcc/store-motion.c
+++ b/gcc/store-motion.c
@@ -271,7 +271,7 @@ store_ops_ok (const_rtx x, int *regs_set)
for (; x; x = XEXP (x, 1))
{
reg = XEXP (x, 0);
- if (regs_set[REGNO(reg)])
+ if (regs_set[REGNO (reg)])
return false;
}
@@ -1256,8 +1256,8 @@ const pass_data pass_data_rtl_store_motion =
class pass_rtl_store_motion : public rtl_opt_pass
{
public:
- pass_rtl_store_motion(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_rtl_store_motion, ctxt)
+ pass_rtl_store_motion (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_rtl_store_motion, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/streamer-hooks.c b/gcc/streamer-hooks.c
index 86fc10b75b3..c4f8475ddd8 100644
--- a/gcc/streamer-hooks.c
+++ b/gcc/streamer-hooks.c
@@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. If not see
#include "config.h"
#include "system.h"
#include "coretypes.h"
+#include "input.h"
#include "streamer-hooks.h"
/* Streamer hooks. */
diff --git a/gcc/streamer-hooks.h b/gcc/streamer-hooks.h
index 11e00b20155..afbe0132639 100644
--- a/gcc/streamer-hooks.h
+++ b/gcc/streamer-hooks.h
@@ -23,8 +23,6 @@ along with GCC; see the file COPYING3. If not see
#ifndef GCC_STREAMER_HOOKS_H
#define GCC_STREAMER_HOOKS_H
-#include "tree.h"
-
/* Forward declarations to avoid including unnecessary headers. */
struct output_block;
struct lto_input_block;
@@ -61,19 +59,19 @@ struct streamer_hooks {
};
#define stream_write_tree(OB, EXPR, REF_P) \
- streamer_hooks.write_tree(OB, EXPR, REF_P, REF_P)
+ streamer_hooks.write_tree (OB, EXPR, REF_P, REF_P)
#define stream_write_tree_shallow_non_ref(OB, EXPR, REF_P) \
- streamer_hooks.write_tree(OB, EXPR, REF_P, false)
+ streamer_hooks.write_tree (OB, EXPR, REF_P, false)
#define stream_read_tree(IB, DATA_IN) \
- streamer_hooks.read_tree(IB, DATA_IN)
+ streamer_hooks.read_tree (IB, DATA_IN)
#define stream_input_location(BP, DATA_IN) \
- streamer_hooks.input_location(BP, DATA_IN)
+ streamer_hooks.input_location (BP, DATA_IN)
#define stream_output_location(OB, BP, LOC) \
- streamer_hooks.output_location(OB, BP, LOC)
+ streamer_hooks.output_location (OB, BP, LOC)
/* Streamer hooks. */
extern struct streamer_hooks streamer_hooks;
diff --git a/gcc/symtab.c b/gcc/symtab.c
index 62fe166bd61..9310dfd21ec 100644
--- a/gcc/symtab.c
+++ b/gcc/symtab.c
@@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. If not see
#include "coretypes.h"
#include "tm.h"
#include "tree.h"
+#include "gimple.h"
#include "tree-inline.h"
#include "langhooks.h"
#include "hashtab.h"
@@ -32,6 +33,7 @@ along with GCC; see the file COPYING3. If not see
#include "timevar.h"
#include "lto-streamer.h"
#include "rtl.h"
+#include "output.h"
const char * const ld_plugin_symbol_resolution_names[]=
{
@@ -48,12 +50,12 @@ const char * const ld_plugin_symbol_resolution_names[]=
};
/* Hash table used to convert declarations into nodes. */
-static GTY((param_is (union symtab_node_def))) htab_t symtab_hash;
+static GTY((param_is (symtab_node))) htab_t symtab_hash;
/* Hash table used to convert assembler names into nodes. */
-static GTY((param_is (union symtab_node_def))) htab_t assembler_name_hash;
+static GTY((param_is (symtab_node))) htab_t assembler_name_hash;
/* Linked list of symbol table nodes. */
-symtab_node symtab_nodes;
+symtab_node *symtab_nodes;
/* 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
@@ -65,8 +67,8 @@ int symtab_order;
static hashval_t
hash_node (const void *p)
{
- const_symtab_node n = (const_symtab_node ) p;
- return (hashval_t) DECL_UID (n->symbol.decl);
+ const symtab_node *n = (const symtab_node *) p;
+ return (hashval_t) DECL_UID (n->decl);
}
@@ -75,62 +77,140 @@ hash_node (const void *p)
static int
eq_node (const void *p1, const void *p2)
{
- const_symtab_node n1 = (const_symtab_node) p1;
- const_symtab_node n2 = (const_symtab_node) p2;
- return DECL_UID (n1->symbol.decl) == DECL_UID (n2->symbol.decl);
+ const symtab_node *n1 = (const symtab_node *) p1;
+ const symtab_node *n2 = (const symtab_node *) p2;
+ return DECL_UID (n1->decl) == DECL_UID (n2->decl);
}
+/* Hash asmnames ignoring the user specified marks. */
+
+static hashval_t
+decl_assembler_name_hash (const_tree asmname)
+{
+ if (IDENTIFIER_POINTER (asmname)[0] == '*')
+ {
+ const char *decl_str = IDENTIFIER_POINTER (asmname) + 1;
+ size_t ulp_len = strlen (user_label_prefix);
+
+ if (ulp_len == 0)
+ ;
+ else if (strncmp (decl_str, user_label_prefix, ulp_len) == 0)
+ decl_str += ulp_len;
+
+ return htab_hash_string (decl_str);
+ }
+
+ return htab_hash_string (IDENTIFIER_POINTER (asmname));
+}
+
+
/* Returns a hash code for P. */
static hashval_t
hash_node_by_assembler_name (const void *p)
{
- const_symtab_node n = (const_symtab_node) p;
- return (hashval_t) decl_assembler_name_hash (DECL_ASSEMBLER_NAME (n->symbol.decl));
+ const symtab_node *n = (const symtab_node *) p;
+ return (hashval_t) decl_assembler_name_hash (DECL_ASSEMBLER_NAME (n->decl));
}
+/* Compare ASMNAME with the DECL_ASSEMBLER_NAME of DECL. */
+
+static bool
+decl_assembler_name_equal (tree decl, const_tree asmname)
+{
+ tree decl_asmname = DECL_ASSEMBLER_NAME (decl);
+ const char *decl_str;
+ const char *asmname_str;
+ bool test = false;
+
+ if (decl_asmname == asmname)
+ return true;
+
+ decl_str = IDENTIFIER_POINTER (decl_asmname);
+ asmname_str = IDENTIFIER_POINTER (asmname);
+
+
+ /* If the target assembler name was set by the user, things are trickier.
+ We have a leading '*' to begin with. After that, it's arguable what
+ is the correct thing to do with -fleading-underscore. Arguably, we've
+ historically been doing the wrong thing in assemble_alias by always
+ printing the leading underscore. Since we're not changing that, make
+ sure user_label_prefix follows the '*' before matching. */
+ if (decl_str[0] == '*')
+ {
+ size_t ulp_len = strlen (user_label_prefix);
+
+ decl_str ++;
+
+ if (ulp_len == 0)
+ test = true;
+ else if (strncmp (decl_str, user_label_prefix, ulp_len) == 0)
+ decl_str += ulp_len, test=true;
+ else
+ decl_str --;
+ }
+ if (asmname_str[0] == '*')
+ {
+ size_t ulp_len = strlen (user_label_prefix);
+
+ asmname_str ++;
+
+ if (ulp_len == 0)
+ test = true;
+ else if (strncmp (asmname_str, user_label_prefix, ulp_len) == 0)
+ asmname_str += ulp_len, test=true;
+ else
+ asmname_str --;
+ }
+
+ if (!test)
+ return false;
+ return strcmp (decl_str, asmname_str) == 0;
+}
+
+
/* Returns nonzero if P1 and P2 are equal. */
static int
eq_assembler_name (const void *p1, const void *p2)
{
- const_symtab_node n1 = (const_symtab_node) p1;
+ const symtab_node *n1 = (const symtab_node *) p1;
const_tree name = (const_tree)p2;
- return (decl_assembler_name_equal (n1->symbol.decl, name));
+ return (decl_assembler_name_equal (n1->decl, name));
}
/* Insert NODE to assembler name hash. */
static void
-insert_to_assembler_name_hash (symtab_node node, bool with_clones)
+insert_to_assembler_name_hash (symtab_node *node, bool with_clones)
{
- if (is_a <varpool_node> (node) && DECL_HARD_REGISTER (node->symbol.decl))
+ if (is_a <varpool_node> (node) && DECL_HARD_REGISTER (node->decl))
return;
- gcc_checking_assert (!node->symbol.previous_sharing_asm_name
- && !node->symbol.next_sharing_asm_name);
+ gcc_checking_assert (!node->previous_sharing_asm_name
+ && !node->next_sharing_asm_name);
if (assembler_name_hash)
{
void **aslot;
struct cgraph_node *cnode;
- tree decl = node->symbol.decl;
+ tree decl = node->decl;
- tree name = DECL_ASSEMBLER_NAME (node->symbol.decl);
+ tree name = DECL_ASSEMBLER_NAME (node->decl);
aslot = htab_find_slot_with_hash (assembler_name_hash, name,
decl_assembler_name_hash (name),
INSERT);
gcc_assert (*aslot != node);
- node->symbol.next_sharing_asm_name = (symtab_node)*aslot;
+ node->next_sharing_asm_name = (symtab_node *)*aslot;
if (*aslot != NULL)
- ((symtab_node)*aslot)->symbol.previous_sharing_asm_name = node;
+ ((symtab_node *)*aslot)->previous_sharing_asm_name = node;
*aslot = node;
/* Update also possible inline clones sharing a decl. */
cnode = dyn_cast <cgraph_node> (node);
if (cnode && cnode->clones && with_clones)
for (cnode = cnode->clones; cnode; cnode = cnode->next_sibling_clone)
- if (cnode->symbol.decl == decl)
- insert_to_assembler_name_hash ((symtab_node) cnode, true);
+ if (cnode->decl == decl)
+ insert_to_assembler_name_hash (cnode, true);
}
}
@@ -138,50 +218,50 @@ insert_to_assembler_name_hash (symtab_node node, bool with_clones)
/* Remove NODE from assembler name hash. */
static void
-unlink_from_assembler_name_hash (symtab_node node, bool with_clones)
+unlink_from_assembler_name_hash (symtab_node *node, bool with_clones)
{
if (assembler_name_hash)
{
struct cgraph_node *cnode;
- tree decl = node->symbol.decl;
+ tree decl = node->decl;
- if (node->symbol.next_sharing_asm_name)
- node->symbol.next_sharing_asm_name->symbol.previous_sharing_asm_name
- = node->symbol.previous_sharing_asm_name;
- if (node->symbol.previous_sharing_asm_name)
+ if (node->next_sharing_asm_name)
+ node->next_sharing_asm_name->previous_sharing_asm_name
+ = node->previous_sharing_asm_name;
+ if (node->previous_sharing_asm_name)
{
- node->symbol.previous_sharing_asm_name->symbol.next_sharing_asm_name
- = node->symbol.next_sharing_asm_name;
+ node->previous_sharing_asm_name->next_sharing_asm_name
+ = node->next_sharing_asm_name;
}
else
{
- tree name = DECL_ASSEMBLER_NAME (node->symbol.decl);
+ tree name = DECL_ASSEMBLER_NAME (node->decl);
void **slot;
slot = htab_find_slot_with_hash (assembler_name_hash, name,
decl_assembler_name_hash (name),
NO_INSERT);
gcc_assert (*slot == node);
- if (!node->symbol.next_sharing_asm_name)
+ if (!node->next_sharing_asm_name)
htab_clear_slot (assembler_name_hash, slot);
else
- *slot = node->symbol.next_sharing_asm_name;
+ *slot = node->next_sharing_asm_name;
}
- node->symbol.next_sharing_asm_name = NULL;
- node->symbol.previous_sharing_asm_name = NULL;
+ node->next_sharing_asm_name = NULL;
+ node->previous_sharing_asm_name = NULL;
/* Update also possible inline clones sharing a decl. */
cnode = dyn_cast <cgraph_node> (node);
if (cnode && cnode->clones && with_clones)
for (cnode = cnode->clones; cnode; cnode = cnode->next_sibling_clone)
- if (cnode->symbol.decl == decl)
- unlink_from_assembler_name_hash ((symtab_node) cnode, true);
+ if (cnode->decl == decl)
+ unlink_from_assembler_name_hash (cnode, true);
}
}
/* Arrange node to be first in its entry of assembler_name_hash. */
void
-symtab_prevail_in_asm_name_hash (symtab_node node)
+symtab_prevail_in_asm_name_hash (symtab_node *node)
{
unlink_from_assembler_name_hash (node, false);
insert_to_assembler_name_hash (node, false);
@@ -192,27 +272,27 @@ symtab_prevail_in_asm_name_hash (symtab_node node)
cgraph/varpool node creation routines. */
void
-symtab_register_node (symtab_node node)
+symtab_register_node (symtab_node *node)
{
- struct symtab_node_base key;
- symtab_node *slot;
+ struct symtab_node key;
+ symtab_node **slot;
- node->symbol.next = symtab_nodes;
- node->symbol.previous = NULL;
+ node->next = symtab_nodes;
+ node->previous = NULL;
if (symtab_nodes)
- symtab_nodes->symbol.previous = node;
+ symtab_nodes->previous = node;
symtab_nodes = node;
if (!symtab_hash)
symtab_hash = htab_create_ggc (10, hash_node, eq_node, NULL);
- key.decl = node->symbol.decl;
- slot = (symtab_node *) htab_find_slot (symtab_hash, &key, INSERT);
+ key.decl = node->decl;
+ slot = (symtab_node **) htab_find_slot (symtab_hash, &key, INSERT);
if (*slot == NULL)
*slot = node;
- ipa_empty_ref_list (&node->symbol.ref_list);
+ ipa_empty_ref_list (&node->ref_list);
- node->symbol.order = symtab_order++;
+ node->order = symtab_order++;
/* Be sure to do this last; C++ FE might create new nodes via
DECL_ASSEMBLER_NAME langhook! */
@@ -223,15 +303,15 @@ symtab_register_node (symtab_node node)
of inline clones. */
void
-symtab_insert_node_to_hashtable (symtab_node node)
+symtab_insert_node_to_hashtable (symtab_node *node)
{
- struct symtab_node_base key;
- symtab_node *slot;
+ struct symtab_node key;
+ symtab_node **slot;
if (!symtab_hash)
symtab_hash = htab_create_ggc (10, hash_node, eq_node, NULL);
- key.decl = node->symbol.decl;
- slot = (symtab_node *) htab_find_slot (symtab_hash, &key, INSERT);
+ key.decl = node->decl;
+ slot = (symtab_node **) htab_find_slot (symtab_hash, &key, INSERT);
*slot = node;
}
@@ -239,34 +319,34 @@ symtab_insert_node_to_hashtable (symtab_node node)
cgraph/varpool node removal routines. */
void
-symtab_unregister_node (symtab_node node)
+symtab_unregister_node (symtab_node *node)
{
void **slot;
- ipa_remove_all_references (&node->symbol.ref_list);
- ipa_remove_all_referring (&node->symbol.ref_list);
+ ipa_remove_all_references (&node->ref_list);
+ ipa_remove_all_referring (&node->ref_list);
- if (node->symbol.same_comdat_group)
+ if (node->same_comdat_group)
{
- symtab_node prev;
- for (prev = node->symbol.same_comdat_group;
- prev->symbol.same_comdat_group != node;
- prev = prev->symbol.same_comdat_group)
+ symtab_node *prev;
+ for (prev = node->same_comdat_group;
+ prev->same_comdat_group != node;
+ prev = prev->same_comdat_group)
;
- if (node->symbol.same_comdat_group == prev)
- prev->symbol.same_comdat_group = NULL;
+ if (node->same_comdat_group == prev)
+ prev->same_comdat_group = NULL;
else
- prev->symbol.same_comdat_group = node->symbol.same_comdat_group;
- node->symbol.same_comdat_group = NULL;
+ prev->same_comdat_group = node->same_comdat_group;
+ node->same_comdat_group = NULL;
}
- if (node->symbol.previous)
- node->symbol.previous->symbol.next = node->symbol.next;
+ if (node->previous)
+ node->previous->next = node->next;
else
- symtab_nodes = node->symbol.next;
- if (node->symbol.next)
- node->symbol.next->symbol.previous = node->symbol.previous;
- node->symbol.next = NULL;
- node->symbol.previous = NULL;
+ symtab_nodes = node->next;
+ if (node->next)
+ node->next->previous = node->previous;
+ node->next = NULL;
+ node->previous = NULL;
slot = htab_find_slot (symtab_hash, node, NO_INSERT);
@@ -275,26 +355,26 @@ symtab_unregister_node (symtab_node node)
gcc_assert ((slot && *slot) || in_lto_p);
if (slot && *slot && *slot == node)
{
- symtab_node replacement_node = NULL;
+ symtab_node *replacement_node = NULL;
if (cgraph_node *cnode = dyn_cast <cgraph_node> (node))
- replacement_node = (symtab_node)cgraph_find_replacement_node (cnode);
+ replacement_node = cgraph_find_replacement_node (cnode);
if (!replacement_node)
htab_clear_slot (symtab_hash, slot);
else
*slot = replacement_node;
}
- if (!is_a <varpool_node> (node) || !DECL_HARD_REGISTER (node->symbol.decl))
+ if (!is_a <varpool_node> (node) || !DECL_HARD_REGISTER (node->decl))
unlink_from_assembler_name_hash (node, false);
}
/* Return symbol table node associated with DECL, if any,
and NULL otherwise. */
-symtab_node
+symtab_node *
symtab_get_node (const_tree decl)
{
- symtab_node *slot;
- struct symtab_node_base key;
+ symtab_node **slot;
+ struct symtab_node key;
#ifdef ENABLE_CHECKING
/* Check that we are called for sane type of object - functions
@@ -310,7 +390,7 @@ symtab_get_node (const_tree decl)
key.decl = CONST_CAST2 (tree, const_tree, decl);
- slot = (symtab_node *) htab_find_slot (symtab_hash, &key,
+ slot = (symtab_node **) htab_find_slot (symtab_hash, &key,
NO_INSERT);
if (slot)
@@ -321,7 +401,7 @@ symtab_get_node (const_tree decl)
/* Remove symtab NODE from the symbol table. */
void
-symtab_remove_node (symtab_node node)
+symtab_remove_node (symtab_node *node)
{
if (cgraph_node *cnode = dyn_cast <cgraph_node> (node))
cgraph_remove_node (cnode);
@@ -334,7 +414,7 @@ symtab_remove_node (symtab_node node)
void
symtab_initialize_asm_name_hash (void)
{
- symtab_node node;
+ symtab_node *node;
if (!assembler_name_hash)
{
assembler_name_hash =
@@ -348,10 +428,10 @@ symtab_initialize_asm_name_hash (void)
/* Return the cgraph node that has ASMNAME for its DECL_ASSEMBLER_NAME.
Return NULL if there's no such node. */
-symtab_node
+symtab_node *
symtab_node_for_asm (const_tree asmname)
{
- symtab_node node;
+ symtab_node *node;
void **slot;
symtab_initialize_asm_name_hash ();
@@ -361,7 +441,7 @@ symtab_node_for_asm (const_tree asmname)
if (slot)
{
- node = (symtab_node) *slot;
+ node = (symtab_node *) *slot;
return node;
}
return NULL;
@@ -372,7 +452,7 @@ symtab_node_for_asm (const_tree asmname)
void
change_decl_assembler_name (tree decl, tree name)
{
- symtab_node node = NULL;
+ symtab_node *node = NULL;
/* We can have user ASM names on things, like global register variables, that
are not in the symbol table. */
@@ -414,41 +494,42 @@ change_decl_assembler_name (tree decl, tree name)
/* Add NEW_ to the same comdat group that OLD is in. */
void
-symtab_add_to_same_comdat_group (symtab_node new_node,
- symtab_node old_node)
+symtab_add_to_same_comdat_group (symtab_node *new_node,
+ symtab_node *old_node)
{
- gcc_assert (DECL_ONE_ONLY (old_node->symbol.decl));
- gcc_assert (!new_node->symbol.same_comdat_group);
+ gcc_assert (DECL_ONE_ONLY (old_node->decl));
+ gcc_assert (!new_node->same_comdat_group);
gcc_assert (new_node != old_node);
- DECL_COMDAT_GROUP (new_node->symbol.decl) = DECL_COMDAT_GROUP (old_node->symbol.decl);
- new_node->symbol.same_comdat_group = old_node;
- if (!old_node->symbol.same_comdat_group)
- old_node->symbol.same_comdat_group = new_node;
+ DECL_COMDAT_GROUP (new_node->decl) = DECL_COMDAT_GROUP (old_node->decl);
+ new_node->same_comdat_group = old_node;
+ if (!old_node->same_comdat_group)
+ old_node->same_comdat_group = new_node;
else
{
- symtab_node n;
- for (n = old_node->symbol.same_comdat_group;
- n->symbol.same_comdat_group != old_node;
- n = n->symbol.same_comdat_group)
+ symtab_node *n;
+ for (n = old_node->same_comdat_group;
+ n->same_comdat_group != old_node;
+ n = n->same_comdat_group)
;
- n->symbol.same_comdat_group = new_node;
+ n->same_comdat_group = new_node;
}
}
/* Dissolve the same_comdat_group list in which NODE resides. */
void
-symtab_dissolve_same_comdat_group_list (symtab_node node)
+symtab_dissolve_same_comdat_group_list (symtab_node *node)
{
- symtab_node n = node, next;
+ symtab_node *n = node;
+ symtab_node *next;
- if (!node->symbol.same_comdat_group)
+ if (!node->same_comdat_group)
return;
do
{
- next = n->symbol.same_comdat_group;
- n->symbol.same_comdat_group = NULL;
+ next = n->same_comdat_group;
+ n->same_comdat_group = NULL;
n = next;
}
while (n != node);
@@ -459,19 +540,19 @@ symtab_dissolve_same_comdat_group_list (symtab_node node)
is unknown go with identifier name. */
const char *
-symtab_node_asm_name (symtab_node node)
+symtab_node_asm_name (symtab_node *node)
{
- if (!DECL_ASSEMBLER_NAME_SET_P (node->symbol.decl))
- return lang_hooks.decl_printable_name (node->symbol.decl, 2);
- return IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->symbol.decl));
+ if (!DECL_ASSEMBLER_NAME_SET_P (node->decl))
+ return lang_hooks.decl_printable_name (node->decl, 2);
+ return IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl));
}
/* Return printable identifier name. */
const char *
-symtab_node_name (symtab_node node)
+symtab_node_name (symtab_node *node)
{
- return lang_hooks.decl_printable_name (node->symbol.decl, 2);
+ return lang_hooks.decl_printable_name (node->decl, 2);
}
static const char * const symtab_type_names[] = {"symbol", "function", "variable"};
@@ -479,7 +560,7 @@ static const char * const symtab_type_names[] = {"symbol", "function", "variable
/* Dump base fields of symtab nodes. Not to be used directly. */
void
-dump_symtab_base (FILE *f, symtab_node node)
+dump_symtab_base (FILE *f, symtab_node *node)
{
static const char * const visibility_types[] = {
"default", "protected", "hidden", "internal"
@@ -487,113 +568,113 @@ dump_symtab_base (FILE *f, symtab_node node)
fprintf (f, "%s/%i (%s)",
symtab_node_asm_name (node),
- node->symbol.order,
+ node->order,
symtab_node_name (node));
dump_addr (f, " @", (void *)node);
- fprintf (f, "\n Type: %s", symtab_type_names[node->symbol.type]);
+ fprintf (f, "\n Type: %s", symtab_type_names[node->type]);
- if (node->symbol.definition)
+ if (node->definition)
fprintf (f, " definition");
- if (node->symbol.analyzed)
+ if (node->analyzed)
fprintf (f, " analyzed");
- if (node->symbol.alias)
+ if (node->alias)
fprintf (f, " alias");
- if (node->symbol.weakref)
+ if (node->weakref)
fprintf (f, " weakref");
- if (node->symbol.cpp_implicit_alias)
+ if (node->cpp_implicit_alias)
fprintf (f, " cpp_implicit_alias");
- if (node->symbol.alias_target)
+ if (node->alias_target)
fprintf (f, " target:%s",
- DECL_P (node->symbol.alias_target)
+ DECL_P (node->alias_target)
? IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME
- (node->symbol.alias_target))
- : IDENTIFIER_POINTER (node->symbol.alias_target));
+ (node->alias_target))
+ : IDENTIFIER_POINTER (node->alias_target));
fprintf (f, "\n Visibility:");
- if (node->symbol.in_other_partition)
+ if (node->in_other_partition)
fprintf (f, " in_other_partition");
- if (node->symbol.used_from_other_partition)
+ if (node->used_from_other_partition)
fprintf (f, " used_from_other_partition");
- if (node->symbol.force_output)
+ if (node->force_output)
fprintf (f, " force_output");
- if (node->symbol.forced_by_abi)
+ if (node->forced_by_abi)
fprintf (f, " forced_by_abi");
- if (node->symbol.externally_visible)
+ if (node->externally_visible)
fprintf (f, " externally_visible");
- if (node->symbol.resolution != LDPR_UNKNOWN)
+ if (node->resolution != LDPR_UNKNOWN)
fprintf (f, " %s",
- ld_plugin_symbol_resolution_names[(int)node->symbol.resolution]);
- if (TREE_ASM_WRITTEN (node->symbol.decl))
+ ld_plugin_symbol_resolution_names[(int)node->resolution]);
+ if (TREE_ASM_WRITTEN (node->decl))
fprintf (f, " asm_written");
- if (DECL_EXTERNAL (node->symbol.decl))
+ if (DECL_EXTERNAL (node->decl))
fprintf (f, " external");
- if (TREE_PUBLIC (node->symbol.decl))
+ if (TREE_PUBLIC (node->decl))
fprintf (f, " public");
- if (DECL_COMMON (node->symbol.decl))
+ if (DECL_COMMON (node->decl))
fprintf (f, " common");
- if (DECL_WEAK (node->symbol.decl))
+ if (DECL_WEAK (node->decl))
fprintf (f, " weak");
- if (DECL_DLLIMPORT_P (node->symbol.decl))
+ if (DECL_DLLIMPORT_P (node->decl))
fprintf (f, " dll_import");
- if (DECL_COMDAT (node->symbol.decl))
+ if (DECL_COMDAT (node->decl))
fprintf (f, " comdat");
- if (DECL_COMDAT_GROUP (node->symbol.decl))
+ if (DECL_COMDAT_GROUP (node->decl))
fprintf (f, " comdat_group:%s",
- IDENTIFIER_POINTER (DECL_COMDAT_GROUP (node->symbol.decl)));
- if (DECL_ONE_ONLY (node->symbol.decl))
+ IDENTIFIER_POINTER (DECL_COMDAT_GROUP (node->decl)));
+ if (DECL_ONE_ONLY (node->decl))
fprintf (f, " one_only");
- if (DECL_SECTION_NAME (node->symbol.decl))
+ if (DECL_SECTION_NAME (node->decl))
fprintf (f, " section_name:%s",
- TREE_STRING_POINTER (DECL_SECTION_NAME (node->symbol.decl)));
- if (DECL_VISIBILITY_SPECIFIED (node->symbol.decl))
+ TREE_STRING_POINTER (DECL_SECTION_NAME (node->decl)));
+ if (DECL_VISIBILITY_SPECIFIED (node->decl))
fprintf (f, " visibility_specified");
- if (DECL_VISIBILITY (node->symbol.decl))
+ if (DECL_VISIBILITY (node->decl))
fprintf (f, " visibility:%s",
- visibility_types [DECL_VISIBILITY (node->symbol.decl)]);
- if (DECL_VIRTUAL_P (node->symbol.decl))
+ visibility_types [DECL_VISIBILITY (node->decl)]);
+ if (DECL_VIRTUAL_P (node->decl))
fprintf (f, " virtual");
- if (DECL_ARTIFICIAL (node->symbol.decl))
+ if (DECL_ARTIFICIAL (node->decl))
fprintf (f, " artificial");
- if (TREE_CODE (node->symbol.decl) == FUNCTION_DECL)
+ if (TREE_CODE (node->decl) == FUNCTION_DECL)
{
- if (DECL_STATIC_CONSTRUCTOR (node->symbol.decl))
+ if (DECL_STATIC_CONSTRUCTOR (node->decl))
fprintf (f, " constructor");
- if (DECL_STATIC_DESTRUCTOR (node->symbol.decl))
+ if (DECL_STATIC_DESTRUCTOR (node->decl))
fprintf (f, " destructor");
}
fprintf (f, "\n");
- if (node->symbol.same_comdat_group)
+ if (node->same_comdat_group)
fprintf (f, " Same comdat group as: %s/%i\n",
- symtab_node_asm_name (node->symbol.same_comdat_group),
- node->symbol.same_comdat_group->symbol.order);
- if (node->symbol.next_sharing_asm_name)
+ symtab_node_asm_name (node->same_comdat_group),
+ node->same_comdat_group->order);
+ if (node->next_sharing_asm_name)
fprintf (f, " next sharing asm name: %i\n",
- node->symbol.next_sharing_asm_name->symbol.order);
- if (node->symbol.previous_sharing_asm_name)
+ node->next_sharing_asm_name->order);
+ if (node->previous_sharing_asm_name)
fprintf (f, " previous sharing asm name: %i\n",
- node->symbol.previous_sharing_asm_name->symbol.order);
+ node->previous_sharing_asm_name->order);
- if (node->symbol.address_taken)
+ if (node->address_taken)
fprintf (f, " Address is taken.\n");
- if (node->symbol.aux)
+ if (node->aux)
{
fprintf (f, " Aux:");
- dump_addr (f, " @", (void *)node->symbol.aux);
+ dump_addr (f, " @", (void *)node->aux);
}
fprintf (f, " References: ");
- ipa_dump_references (f, &node->symbol.ref_list);
+ ipa_dump_references (f, &node->ref_list);
fprintf (f, " Referring: ");
- ipa_dump_referring (f, &node->symbol.ref_list);
- if (node->symbol.lto_file_data)
+ ipa_dump_referring (f, &node->ref_list);
+ if (node->lto_file_data)
fprintf (f, " Read from file: %s\n",
- node->symbol.lto_file_data->file_name);
+ node->lto_file_data->file_name);
}
/* Dump symtab node. */
void
-dump_symtab_node (FILE *f, symtab_node node)
+dump_symtab_node (FILE *f, symtab_node *node)
{
if (cgraph_node *cnode = dyn_cast <cgraph_node> (node))
dump_cgraph_node (f, cnode);
@@ -606,7 +687,7 @@ dump_symtab_node (FILE *f, symtab_node node)
void
dump_symtab (FILE *f)
{
- symtab_node node;
+ symtab_node *node;
fprintf (f, "Symbol table:\n\n");
FOR_EACH_SYMBOL (node)
dump_symtab_node (f, node);
@@ -615,7 +696,7 @@ dump_symtab (FILE *f)
/* Dump symtab node NODE to stderr. */
DEBUG_FUNCTION void
-debug_symtab_node (symtab_node node)
+debug_symtab_node (symtab_node *node)
{
dump_symtab_node (stderr, node);
}
@@ -631,14 +712,14 @@ debug_symtab (void)
/* Verify common part of symtab nodes. */
DEBUG_FUNCTION bool
-verify_symtab_base (symtab_node node)
+verify_symtab_base (symtab_node *node)
{
bool error_found = false;
- symtab_node hashed_node;
+ symtab_node *hashed_node;
if (is_a <cgraph_node> (node))
{
- if (TREE_CODE (node->symbol.decl) != FUNCTION_DECL)
+ if (TREE_CODE (node->decl) != FUNCTION_DECL)
{
error ("function symbol is not function");
error_found = true;
@@ -646,7 +727,7 @@ verify_symtab_base (symtab_node node)
}
else if (is_a <varpool_node> (node))
{
- if (TREE_CODE (node->symbol.decl) != VAR_DECL)
+ if (TREE_CODE (node->decl) != VAR_DECL)
{
error ("variable symbol is not variable");
error_found = true;
@@ -660,7 +741,7 @@ verify_symtab_base (symtab_node node)
if (cgraph_state != CGRAPH_LTO_STREAMING)
{
- hashed_node = symtab_get_node (node->symbol.decl);
+ hashed_node = symtab_get_node (node->decl);
if (!hashed_node)
{
error ("node not found in symtab decl hashtable");
@@ -669,8 +750,8 @@ verify_symtab_base (symtab_node node)
if (hashed_node != node
&& (!is_a <cgraph_node> (node)
|| !dyn_cast <cgraph_node> (node)->clone_of
- || dyn_cast <cgraph_node> (node)->clone_of->symbol.decl
- != node->symbol.decl))
+ || dyn_cast <cgraph_node> (node)->clone_of->decl
+ != node->decl))
{
error ("node differs from symtab decl hashtable");
error_found = true;
@@ -678,8 +759,8 @@ verify_symtab_base (symtab_node node)
}
if (assembler_name_hash)
{
- hashed_node = symtab_node_for_asm (DECL_ASSEMBLER_NAME (node->symbol.decl));
- if (hashed_node && hashed_node->symbol.previous_sharing_asm_name)
+ hashed_node = symtab_node_for_asm (DECL_ASSEMBLER_NAME (node->decl));
+ if (hashed_node && hashed_node->previous_sharing_asm_name)
{
error ("assembler name hash list corrupted");
error_found = true;
@@ -688,53 +769,53 @@ verify_symtab_base (symtab_node node)
{
if (hashed_node == node)
break;
- hashed_node = hashed_node->symbol.next_sharing_asm_name;
+ hashed_node = hashed_node->next_sharing_asm_name;
}
if (!hashed_node
&& !(is_a <varpool_node> (node)
- || DECL_HARD_REGISTER (node->symbol.decl)))
+ || DECL_HARD_REGISTER (node->decl)))
{
error ("node not found in symtab assembler name hash");
error_found = true;
}
}
- if (node->symbol.previous_sharing_asm_name
- && node->symbol.previous_sharing_asm_name->symbol.next_sharing_asm_name != node)
+ if (node->previous_sharing_asm_name
+ && node->previous_sharing_asm_name->next_sharing_asm_name != node)
{
error ("double linked list of assembler names corrupted");
error_found = true;
}
- if (node->symbol.analyzed && !node->symbol.definition)
+ if (node->analyzed && !node->definition)
{
error ("node is analyzed byt it is not a definition");
error_found = true;
}
- if (node->symbol.cpp_implicit_alias && !node->symbol.alias)
+ if (node->cpp_implicit_alias && !node->alias)
{
error ("node is alias but not implicit alias");
error_found = true;
}
- if (node->symbol.alias && !node->symbol.definition
- && !node->symbol.weakref)
+ if (node->alias && !node->definition
+ && !node->weakref)
{
error ("node is alias but not definition");
error_found = true;
}
- if (node->symbol.weakref && !node->symbol.alias)
+ if (node->weakref && !node->alias)
{
error ("node is weakref but not an alias");
error_found = true;
}
- if (node->symbol.same_comdat_group)
+ if (node->same_comdat_group)
{
- symtab_node n = node->symbol.same_comdat_group;
+ symtab_node *n = node->same_comdat_group;
- if (!DECL_ONE_ONLY (n->symbol.decl))
+ if (!DECL_ONE_ONLY (n->decl))
{
error ("non-DECL_ONE_ONLY node in a same_comdat_group list");
error_found = true;
}
- if (n->symbol.type != node->symbol.type)
+ if (n->type != node->type)
{
error ("mixing different types of symbol in same comdat groups is not supported");
error_found = true;
@@ -746,13 +827,13 @@ verify_symtab_base (symtab_node node)
}
do
{
- if (!n->symbol.same_comdat_group)
+ if (!n->same_comdat_group)
{
error ("same_comdat_group is not a circular list");
error_found = true;
break;
}
- n = n->symbol.same_comdat_group;
+ n = n->same_comdat_group;
}
while (n != node);
}
@@ -762,7 +843,7 @@ verify_symtab_base (symtab_node node)
/* Verify consistency of NODE. */
DEBUG_FUNCTION void
-verify_symtab_node (symtab_node node)
+verify_symtab_node (symtab_node *node)
{
if (seen_error ())
return;
@@ -784,7 +865,7 @@ verify_symtab_node (symtab_node node)
DEBUG_FUNCTION void
verify_symtab (void)
{
- symtab_node node;
+ symtab_node *node;
FOR_EACH_SYMBOL (node)
verify_symtab_node (node);
}
@@ -805,11 +886,11 @@ resolution_used_from_other_file_p (enum ld_plugin_symbol_resolution resolution)
Known only when doing LTO via linker plugin. */
bool
-symtab_used_from_object_file_p (symtab_node node)
+symtab_used_from_object_file_p (symtab_node *node)
{
- if (!TREE_PUBLIC (node->symbol.decl) || DECL_EXTERNAL (node->symbol.decl))
+ if (!TREE_PUBLIC (node->decl) || DECL_EXTERNAL (node->decl))
return false;
- if (resolution_used_from_other_file_p (node->symbol.resolution))
+ if (resolution_used_from_other_file_p (node->resolution))
return true;
return false;
}
@@ -857,7 +938,7 @@ symtab_make_decl_local (tree decl)
/* Return availability of NODE. */
enum availability
-symtab_node_availability (symtab_node node)
+symtab_node_availability (symtab_node *node)
{
if (is_a <cgraph_node> (node))
return cgraph_function_body_availability (cgraph (node));
@@ -869,12 +950,12 @@ symtab_node_availability (symtab_node node)
If NODE is not an alias, return NODE.
When AVAILABILITY is non-NULL, get minimal availability in the chain. */
-symtab_node
-symtab_alias_ultimate_target (symtab_node node, enum availability *availability)
+symtab_node *
+symtab_alias_ultimate_target (symtab_node *node, enum availability *availability)
{
bool weakref_p = false;
- if (!node->symbol.alias)
+ if (!node->alias)
{
if (availability)
*availability = symtab_node_availability (node);
@@ -897,7 +978,7 @@ symtab_alias_ultimate_target (symtab_node node, enum availability *availability)
if (availability)
{
- weakref_p = node->symbol.weakref;
+ weakref_p = node->weakref;
if (!weakref_p)
*availability = symtab_node_availability (node);
else
@@ -905,13 +986,13 @@ symtab_alias_ultimate_target (symtab_node node, enum availability *availability)
}
while (node)
{
- if (node->symbol.alias && node->symbol.analyzed)
+ if (node->alias && node->analyzed)
node = symtab_alias_target (node);
else
{
if (!availability)
;
- else if (node->symbol.analyzed)
+ else if (node->analyzed)
{
if (weakref_p)
{
@@ -929,7 +1010,7 @@ symtab_alias_ultimate_target (symtab_node node, enum availability *availability)
enum availability a = symtab_node_availability (node);
if (a < *availability)
*availability = a;
- weakref_p = node->symbol.weakref;
+ weakref_p = node->weakref;
}
}
if (availability)
@@ -945,35 +1026,35 @@ symtab_alias_ultimate_target (symtab_node node, enum availability *availability)
copy the visibility from the target to get things right. */
void
-fixup_same_cpp_alias_visibility (symtab_node node, symtab_node target)
+fixup_same_cpp_alias_visibility (symtab_node *node, symtab_node *target)
{
if (is_a <cgraph_node> (node))
{
- DECL_DECLARED_INLINE_P (node->symbol.decl)
- = DECL_DECLARED_INLINE_P (target->symbol.decl);
- DECL_DISREGARD_INLINE_LIMITS (node->symbol.decl)
- = DECL_DISREGARD_INLINE_LIMITS (target->symbol.decl);
+ DECL_DECLARED_INLINE_P (node->decl)
+ = DECL_DECLARED_INLINE_P (target->decl);
+ DECL_DISREGARD_INLINE_LIMITS (node->decl)
+ = DECL_DISREGARD_INLINE_LIMITS (target->decl);
}
/* FIXME: It is not really clear why those flags should not be copied for
functions, too. */
else
{
- DECL_WEAK (node->symbol.decl) = DECL_WEAK (target->symbol.decl);
- DECL_EXTERNAL (node->symbol.decl) = DECL_EXTERNAL (target->symbol.decl);
- DECL_VISIBILITY (node->symbol.decl) = DECL_VISIBILITY (target->symbol.decl);
+ DECL_WEAK (node->decl) = DECL_WEAK (target->decl);
+ DECL_EXTERNAL (node->decl) = DECL_EXTERNAL (target->decl);
+ DECL_VISIBILITY (node->decl) = DECL_VISIBILITY (target->decl);
}
- DECL_VIRTUAL_P (node->symbol.decl) = DECL_VIRTUAL_P (target->symbol.decl);
- if (TREE_PUBLIC (node->symbol.decl))
+ DECL_VIRTUAL_P (node->decl) = DECL_VIRTUAL_P (target->decl);
+ if (TREE_PUBLIC (node->decl))
{
- DECL_EXTERNAL (node->symbol.decl) = DECL_EXTERNAL (target->symbol.decl);
- DECL_COMDAT (node->symbol.decl) = DECL_COMDAT (target->symbol.decl);
- DECL_COMDAT_GROUP (node->symbol.decl)
- = DECL_COMDAT_GROUP (target->symbol.decl);
- if (DECL_ONE_ONLY (target->symbol.decl)
- && !node->symbol.same_comdat_group)
- symtab_add_to_same_comdat_group ((symtab_node)node, (symtab_node)target);
+ DECL_EXTERNAL (node->decl) = DECL_EXTERNAL (target->decl);
+ DECL_COMDAT (node->decl) = DECL_COMDAT (target->decl);
+ DECL_COMDAT_GROUP (node->decl)
+ = DECL_COMDAT_GROUP (target->decl);
+ if (DECL_ONE_ONLY (target->decl)
+ && !node->same_comdat_group)
+ symtab_add_to_same_comdat_group (node, target);
}
- node->symbol.externally_visible = target->symbol.externally_visible;
+ node->externally_visible = target->externally_visible;
}
/* Add reference recording that NODE is alias of TARGET.
@@ -981,46 +1062,46 @@ fixup_same_cpp_alias_visibility (symtab_node node, symtab_node target)
it returns false. */
bool
-symtab_resolve_alias (symtab_node node, symtab_node target)
+symtab_resolve_alias (symtab_node *node, symtab_node *target)
{
- symtab_node n;
+ symtab_node *n;
- gcc_assert (!node->symbol.analyzed
- && !vec_safe_length (node->symbol.ref_list.references));
+ gcc_assert (!node->analyzed
+ && !vec_safe_length (node->ref_list.references));
/* Never let cycles to creep into the symbol table alias references;
those will make alias walkers to be infinite. */
- for (n = target; n && n->symbol.alias;
- n = n->symbol.analyzed ? symtab_alias_target (n) : NULL)
+ for (n = target; n && n->alias;
+ n = n->analyzed ? symtab_alias_target (n) : NULL)
if (n == node)
{
if (is_a <cgraph_node> (node))
- error ("function %q+D part of alias cycle", node->symbol.decl);
+ error ("function %q+D part of alias cycle", node->decl);
else if (is_a <varpool_node> (node))
- error ("variable %q+D part of alias cycle", node->symbol.decl);
+ error ("variable %q+D part of alias cycle", node->decl);
else
gcc_unreachable ();
- node->symbol.alias = false;
+ node->alias = false;
return false;
}
/* "analyze" the node - i.e. mark the reference. */
- node->symbol.definition = true;
- node->symbol.alias = true;
- node->symbol.analyzed = true;
+ node->definition = true;
+ node->alias = true;
+ node->analyzed = true;
ipa_record_reference (node, target, IPA_REF_ALIAS, NULL);
/* Alias targets become reudndant after alias is resolved into an reference.
We do not want to keep it around or we would have to mind updating them
when renaming symbols. */
- node->symbol.alias_target = NULL;
+ node->alias_target = NULL;
- if (node->symbol.cpp_implicit_alias && cgraph_state >= CGRAPH_STATE_CONSTRUCTION)
+ if (node->cpp_implicit_alias && cgraph_state >= CGRAPH_STATE_CONSTRUCTION)
fixup_same_cpp_alias_visibility (node, target);
/* If alias has address taken, so does the target. */
- if (node->symbol.address_taken)
- symtab_alias_ultimate_target (target, NULL)->symbol.address_taken = true;
+ if (node->address_taken)
+ symtab_alias_ultimate_target (target, NULL)->address_taken = true;
return true;
}
@@ -1029,8 +1110,8 @@ symtab_resolve_alias (symtab_node node, symtab_node target)
skipped. */
bool
-symtab_for_node_and_aliases (symtab_node node,
- bool (*callback) (symtab_node, void *),
+symtab_for_node_and_aliases (symtab_node *node,
+ bool (*callback) (symtab_node *, void *),
void *data,
bool include_overwritable)
{
@@ -1039,10 +1120,10 @@ symtab_for_node_and_aliases (symtab_node node,
if (callback (node, data))
return true;
- for (i = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list, i, ref); i++)
+ for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list, i, ref); i++)
if (ref->use == IPA_REF_ALIAS)
{
- symtab_node alias = ref->referring;
+ symtab_node *alias = ref->referring;
if (include_overwritable
|| symtab_node_availability (alias) > AVAIL_OVERWRITABLE)
if (symtab_for_node_and_aliases (alias, callback, data,
@@ -1055,11 +1136,11 @@ symtab_for_node_and_aliases (symtab_node node,
/* Worker searching nonoverwritable alias. */
static bool
-symtab_nonoverwritable_alias_1 (symtab_node node, void *data)
+symtab_nonoverwritable_alias_1 (symtab_node *node, void *data)
{
- if (decl_binds_to_current_def_p (node->symbol.decl))
+ if (decl_binds_to_current_def_p (node->decl))
{
- *(symtab_node *)data = node;
+ *(symtab_node **)data = node;
return true;
}
return false;
@@ -1069,16 +1150,16 @@ symtab_nonoverwritable_alias_1 (symtab_node node, void *data)
definition, return NODE. Otherwise look for alias with such property and if
none exists, introduce new one. */
-symtab_node
-symtab_nonoverwritable_alias (symtab_node node)
+symtab_node *
+symtab_nonoverwritable_alias (symtab_node *node)
{
tree new_decl;
- symtab_node new_node = NULL;
+ symtab_node *new_node = NULL;
/* First try to look up existing alias or base object
(if that is already non-overwritable). */
node = symtab_alias_ultimate_target (node, NULL);
- gcc_assert (!node->symbol.alias && !node->symbol.weakref);
+ gcc_assert (!node->alias && !node->weakref);
symtab_for_node_and_aliases (node, symtab_nonoverwritable_alias_1,
(void *)&new_node, true);
if (new_node)
@@ -1089,8 +1170,8 @@ symtab_nonoverwritable_alias (symtab_node node)
#endif
/* Otherwise create a new one. */
- new_decl = copy_node (node->symbol.decl);
- DECL_NAME (new_decl) = clone_function_name (node->symbol.decl, "localalias");
+ new_decl = copy_node (node->decl);
+ DECL_NAME (new_decl) = clone_function_name (node->decl, "localalias");
if (TREE_CODE (new_decl) == FUNCTION_DECL)
DECL_STRUCT_FUNCTION (new_decl) = NULL;
DECL_INITIAL (new_decl) = NULL;
@@ -1099,7 +1180,7 @@ symtab_nonoverwritable_alias (symtab_node node)
/* Update the properties. */
DECL_EXTERNAL (new_decl) = 0;
- if (DECL_ONE_ONLY (node->symbol.decl))
+ if (DECL_ONE_ONLY (node->decl))
DECL_SECTION_NAME (new_decl) = NULL;
DECL_COMDAT_GROUP (new_decl) = 0;
TREE_PUBLIC (new_decl) = 0;
@@ -1110,12 +1191,12 @@ symtab_nonoverwritable_alias (symtab_node node)
{
DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
DECL_STATIC_DESTRUCTOR (new_decl) = 0;
- new_node = (symtab_node) cgraph_create_function_alias
- (new_decl, node->symbol.decl);
+ new_node = cgraph_create_function_alias
+ (new_decl, node->decl);
}
else
- new_node = (symtab_node) varpool_create_variable_alias (new_decl,
- node->symbol.decl);
+ new_node = varpool_create_variable_alias (new_decl,
+ node->decl);
symtab_resolve_alias (new_node, node);
gcc_assert (decl_binds_to_current_def_p (new_decl));
return new_node;
@@ -1124,14 +1205,15 @@ symtab_nonoverwritable_alias (symtab_node node)
/* Return true if A and B represents semantically equivalent symbols. */
bool
-symtab_semantically_equivalent_p (symtab_node a,
- symtab_node b)
+symtab_semantically_equivalent_p (symtab_node *a,
+ symtab_node *b)
{
enum availability avail;
- symtab_node ba, bb;
+ symtab_node *ba;
+ symtab_node *bb;
/* Equivalent functions are equivalent. */
- if (a->symbol.decl == b->symbol.decl)
+ if (a->decl == b->decl)
return true;
/* If symbol is not overwritable by different implementation,
diff --git a/gcc/sync-builtins.def b/gcc/sync-builtins.def
index 4f7a22f8a65..26c8ba09f9b 100644
--- a/gcc/sync-builtins.def
+++ b/gcc/sync-builtins.def
@@ -29,559 +29,565 @@ along with GCC; see the file COPYING3. If not see
"_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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ BT_FN_VOID_VPTR, ATTR_NOTHROWCALL_LEAF_LIST)
DEF_SYNC_BUILTIN (BUILT_IN_SYNC_SYNCHRONIZE, "__sync_synchronize",
- BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ BT_FN_BOOL_VPTR_INT, ATTR_NOTHROWCALL_LEAF_LIST)
DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_CLEAR, "__atomic_clear", BT_FN_VOID_VPTR_INT,
- ATTR_NOTHROW_LEAF_LIST)
+ ATTR_NOTHROWCALL_LEAF_LIST)
DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_EXCHANGE,
"__atomic_exchange",
- BT_FN_VOID_SIZE_VPTR_PTR_PTR_INT, ATTR_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ ATTR_NOTHROWCALL_LEAF_LIST)
DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_N,
"__atomic_compare_exchange_n",
- BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ 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_NOTHROW_LEAF_LIST)
+ BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROWCALL_LEAF_LIST)
DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_ALWAYS_LOCK_FREE,
"__atomic_always_lock_free",
@@ -600,3 +606,9 @@ 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/gcc/system.h b/gcc/system.h
index b735a96c10b..a1fc6de5db5 100644
--- a/gcc/system.h
+++ b/gcc/system.h
@@ -27,7 +27,7 @@ along with GCC; see the file COPYING3. If not see
#ifndef va_copy
# ifdef __va_copy
-# define va_copy(d,s) __va_copy((d),(s))
+# define va_copy(d,s) __va_copy (d, s)
# else
# define va_copy(d,s) ((d) = (s))
# endif
@@ -53,9 +53,9 @@ along with GCC; see the file COPYING3. If not see
#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)
+#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
@@ -264,17 +264,15 @@ extern int errno;
#ifdef HAVE_SYS_PARAM_H
# include <sys/param.h>
-/* We use this identifier later and it appears in some vendor param.h's. */
+/* 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
-/* Get definitions of HOST_WIDE_INT and HOST_WIDEST_INT. */
-#include "hwint.h"
-
/* 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
@@ -294,7 +292,7 @@ extern int errno;
/* 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) 0 << (sizeof(t) * CHAR_BIT - 1) : (t) 0))
+ ? ~ (t) 0 << (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. */
@@ -536,7 +534,7 @@ 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);
+extern int vsnprintf (char *, size_t, const char *, va_list);
#endif
#ifdef __cplusplus
@@ -611,11 +609,11 @@ extern int vsnprintf(char *, size_t, const char *, va_list);
/* Some systems have mkdir that takes a single argument. */
#ifdef MKDIR_TAKES_ONE_ARG
-# define mkdir(a,b) mkdir(a)
+# define mkdir(a,b) mkdir (a)
#endif
#ifndef HAVE_KILL
-# define kill(p,s) raise(s)
+# define kill(p,s) raise (s)
#endif
/* Provide a way to print an address via printf. */
@@ -693,7 +691,7 @@ extern void fancy_abort (const char *, int, const char *) ATTRIBUTE_NORETURN;
((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))
+ ((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)))
@@ -708,7 +706,7 @@ extern void fancy_abort (const char *, int, const char *) ATTRIBUTE_NORETURN;
/* 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()
+#define gcc_unreachable() __builtin_unreachable ()
#else
#define gcc_unreachable() (fancy_abort (__FILE__, __LINE__, __FUNCTION__))
#endif
@@ -1011,11 +1009,11 @@ helper_const_non_const_cast (const char *p)
#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_BB(X) CONST_CAST(struct basic_block_def *, (X))
-#define CONST_CAST_GIMPLE(X) CONST_CAST(union gimple_statement_d *, (X))
+#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_BB(X) CONST_CAST (struct basic_block_def *, (X))
+#define CONST_CAST_GIMPLE(X) CONST_CAST (union gimple_statement_d *, (X))
/* Activate certain diagnostics as warnings (not errors via the
-Werror flag). */
@@ -1062,4 +1060,7 @@ helper_const_non_const_cast (const char *p)
#define DEBUG_VARIABLE
#endif
+/* Get definitions of HOST_WIDE_INT and HOST_WIDEST_INT. */
+#include "hwint.h"
+
#endif /* ! GCC_SYSTEM_H */
diff --git a/gcc/target-globals.c b/gcc/target-globals.c
index 65ccb8af5e6..9d223fcbed0 100644
--- a/gcc/target-globals.c
+++ b/gcc/target-globals.c
@@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. If not see
#include "tm.h"
#include "insn-config.h"
#include "machmode.h"
+#include "tree.h"
#include "ggc.h"
#include "toplev.h"
#include "target-globals.h"
diff --git a/gcc/target-hooks-macros.h b/gcc/target-hooks-macros.h
index fb392c292d5..602b2a42d28 100644
--- a/gcc/target-hooks-macros.h
+++ b/gcc/target-hooks-macros.h
@@ -37,7 +37,7 @@
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)
+#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 ;)
diff --git a/gcc/target.def b/gcc/target.def
index 6de513fdf9a..f6e42a17b0e 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -1041,6 +1041,19 @@ 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 *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 could be macro fused for\n\
+target microarchitecture. If this hook returns true for the given insn pair\n\
+(@var{condgen} and @var{condjmp}), scheduler will put them into a sched\n\
+group, and they will not be scheduled apart.",
+ bool, (rtx condgen, rtx condjmp), 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). */
@@ -1935,6 +1948,18 @@ DEFHOOK_UNDOC
bool, (void),
targhook_float_words_big_endian)
+DEFHOOK
+(float_exceptions_rounding_supported_p,
+ "Returns true if the target supports IEEE 754 floating-point exceptions\
+ and rounding modes, false otherwise. This is intended to relate to the\
+ @code{float} and @code{double} types, but not necessarily @code{long double}.\
+ By default, returns true if the @code{adddf3} instruction pattern is\
+ available and false otherwise, on the assumption that hardware floating\
+ point supports exceptions and rounding modes but software floating point\
+ does not.",
+ bool, (void),
+ default_float_exceptions_rounding_supported_p)
+
/* True if the target supports decimal floating point. */
DEFHOOK
(decimal_float_supported_p,
@@ -2023,6 +2048,104 @@ built-in function.",
(tree exp, rtx target, rtx subtarget, enum machine_mode mode, int ignore),
default_expand_builtin)
+DEFHOOK
+(builtin_chkp_function,
+ "This hook allows target to redefine built-in functions used by\n\
+Pointer Bounds Checker for code instrumentation. Hook should return\n\
+fndecl of function implementing generic builtin whose code is\n\
+passed in @var{fcode}. Currently following built-in functions are\n\
+obtained using this hook:\n\
+@deftypefn {Built-in Function} bnd __chkp_bndmk (const void *@var{lb}, size_t @var{size})\n\
+Function code - BUILT_IN_CHKP_BNDMK. This built-in function is used\n\
+by Pointer Bounds Checker to create bound values. @var{lb} holds low\n\
+bound of the resulting bounds. @var{size} holds size of created bounds.\n\
+@end deftypefn\n\
+\n\
+@deftypefn {Built-in Function} void __chkp_bndstx (const void **@var{loc}, const void *@var{ptr}, bnd @var{b})\n\
+Function code - @code{BUILT_IN_CHKP_BNDSTX}. This built-in function is used\n\
+by Pointer Bounds Checker to store bounds @var{b} for pointer @var{ptr}\n\
+stored by address @var{loc}.\n\
+@end deftypefn\n\
+\n\
+@deftypefn {Built-in Function} bnd __chkp_bndldx (const void **@var{loc}, const void *@var{ptr})\n\
+Function code - @code{BUILT_IN_CHKP_BNDLDX}. This built-in function is used\n\
+by Pointer Bounds Checker to get bounds of pointer @var{ptr} loaded by\n\
+address @var{loc}.\n\
+@end deftypefn\n\
+\n\
+@deftypefn {Built-in Function} void __chkp_bndcl (bnd @var{b}, const void *@var{ptr})\n\
+Function code - @code{BUILT_IN_CHKP_BNDCL}. This built-in function is used\n\
+by Pointer Bounds Checker to perform check for pointer @var{ptr} against\n\
+lower bound of bounds @var{b}.\n\
+@end deftypefn\n\
+\n\
+@deftypefn {Built-in Function} void __chkp_bndcu (bnd @var{b}, const void *@var{ptr})\n\
+Function code - @code{BUILT_IN_CHKP_BNDCU}. This built-in function is used\n\
+by Pointer Bounds Checker to perform check for pointer @var{ptr} against\n\
+upper bound of bounds @var{b}.\n\
+@end deftypefn\n\
+\n\
+@deftypefn {Built-in Function} bnd __chkp_bndret (void *@var{ptr})\n\
+Function code - @code{BUILT_IN_CHKP_BNDRET}. This built-in function is used\n\
+by Pointer Bounds Checker to obtain bounds returned by call statement.\n\
+@var{ptr} passed to buil-in is @code{SSA_NAME} returned by call.\n\
+@end deftypefn\n\
+\n\
+@deftypefn {Built-in Function} bnd __chkp_arg_bnd (void *@var{arg})\n\
+Function code - @code{BUILT_IN_CHKP_ARG_BND}. This built-in function is\n\
+used by Pointer Bounds Checker to obtain bounds passed for input argument.\n\
+@var{arg} is default @code{SSA_NAME} of the @code{PARM_DECL} whose\n\
+bounds we want to obtain.\n\
+@end deftypefn\n\
+\n\
+@deftypefn {Built-in Function} bnd __chkp_intersect (bnd @var{b1}, bnd @var{b2})\n\
+Function code - @code{BUILT_IN_CHKP_INTERSECT}. This built-in function\n\
+returns intersection of bounds @var{b1} and @var{b2}.\n\
+@end deftypefn\n\
+\n\
+@deftypefn {Built-in Function} bnd __chkp_narrow (const void *@var{ptr}, bnd @var{b}, size_t @var{s})\n\
+Function code - @code{BUILT_IN_CHKP_NARROW}. This built-in function\n\
+returns intersection of bounds @var{b} and\n\
+[@var{ptr}, @var{ptr} + @var{s} - @code{1}].\n\
+@end deftypefn\n\
+\n\
+@deftypefn {Built-in Function} void *__chkp_set_bounds (const void *@var{ptr}, size_t @var{s})\n\
+Function code - @code{BUILT_IN_CHKP_SET_PTR_BOUNDS}. This built-in function\n\
+returns @var{ptr} with bounds [@var{ptr}, @var{ptr} + @var{s} - @code{1}].\n\
+@end deftypefn\n\
+\n\
+@deftypefn {Built-in Function} size_t __chkp_sizeof (const void *@var{ptr})\n\
+Function code - @code{BUILT_IN_CHKP_SIZEOF}. This built-in function\n\
+returns size of object referenced by @var{ptr}. @var{ptr} is always\n\
+@code{ADDR_EXPR} of @code{VAR_DECL}. This built-in is used by\n\
+Pointer Boudns Checker when bounds of object cannot be computed statically\n\
+(e.g. object has incomplete type).\n\
+@end deftypefn\n\
+\n\
+@deftypefn {Built-in Function} const void *__chkp_extract_lower (bnd @var{b})\n\
+Function code - @code{BUILT_IN_CHKP_EXTRACT_LOWER}. This built-in function\n\
+returns lower bound of bounds @var{b}.\n\
+@end deftypefn\n\
+\n\
+@deftypefn {Built-in Function} const void *__chkp_extract_upper (bnd @var{b})\n\
+Function code - @code{BUILT_IN_CHKP_EXTRACT_UPPER}. This built-in function\n\
+returns upper bound of bounds @var{b}.\n\
+@end deftypefn",
+ tree, (unsigned fcode),
+ default_builtin_chkp_function)
+
+DEFHOOK
+(chkp_bound_type,
+ "Return type to be used for bounds",
+ tree, (void),
+ default_chkp_bound_type)
+
+DEFHOOK
+(chkp_bound_mode,
+ "Return mode to be used for bounds.",
+ enum machine_mode, (void),
+ default_chkp_bound_mode)
+
/* 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
@@ -3273,6 +3396,15 @@ The default version of this hook returns @code{va_list_type_node}.",
tree, (tree fndecl),
std_fn_abi_va_list)
+DEFHOOK
+(fn_abi_va_list_bounds_size,
+ "This hook returns size for @code{va_list} object in function specified\n\
+by @var{fndecl}. This hook is used by Pointer Bounds Checker to build bounds\n\
+for @code{va_list} object. Return @code{integer_zero_node} if no bounds\n\
+should be used (e.g. @code{va_list} is a scalar pointer to the stack).",
+ tree, (tree fndecl),
+ default_fn_abi_va_list_bounds_size)
+
/* Get the __builtin_va_list type dependent on input type. */
DEFHOOK
(canonical_va_list_type,
@@ -3465,6 +3597,23 @@ normally defined in @file{libgcc2.c}.",
tree, (void),
default_external_stack_protect_fail)
+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, (double_int iterations, double_int iterations_max,
+ unsigned int loop_depth, bool entered_at_top),
+ hook_bool_dint_dint_uint_bool_true)
+
/* Returns NULL if target supports the insn within a doloop block,
otherwise it returns an error message. */
DEFHOOK
@@ -3704,6 +3853,30 @@ not generate any instructions in this case.",
default_setup_incoming_varargs)
DEFHOOK
+(load_bounds_for_arg,
+ "This hook is used by expand pass to emit insn to load bounds of\n\
+@var{arg} passed in @var{slot}. Expand pass uses this hook in case\n\
+bounds of @var{arg} are not passed in register. If @var{slot} is a\n\
+memory, then bounds are loaded as for regular pointer loaded from\n\
+memory. If @var{slot} is not a memory then @var{slot_no} is an integer\n\
+constant holding number of the target dependent special slot which\n\
+should be used to obtain bounds. Hook returns RTX holding loaded bounds.",
+ rtx, (rtx slot, rtx arg, rtx slot_no),
+ default_load_bounds_for_arg)
+
+DEFHOOK
+(store_bounds_for_arg,
+ "This hook is used by expand pass to emit insns to store @var{bounds} of\n\
+@var{arg} passed in @var{slot}. Expand pass uses this hook in case\n\
+@var{bounds} of @var{arg} are not passed in register. If @var{slot} is a\n\
+memory, then @var{bounds} are stored as for regular pointer stored in\n\
+memory. If @var{slot} is not a memory then @var{slot_no} is an integer\n\
+constant holding number of the target dependent special slot which\n\
+should be used to store @var{bounds}.",
+ void, (rtx arg, rtx slot, rtx bounds, rtx slot_no),
+ default_store_bounds_for_arg)
+
+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\
@@ -4964,9 +5137,9 @@ 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.\n\
+options from the @code{struct gcc_options} structure.\n\
@xref{Option file format}.",
- void, (struct cl_target_option *ptr), NULL)
+ void, (struct cl_target_option *ptr, struct gcc_options *opts), NULL)
/* Function to restore any extra target state from the target options
structure. */
@@ -4974,8 +5147,8 @@ 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.",
- void, (struct cl_target_option *ptr), NULL)
+function-specific options to the @code{struct gcc_options} structure.",
+ void, (struct gcc_options *opts, struct cl_target_option *ptr), NULL)
/* Function to print any extra target state from the target options
structure. */
@@ -5123,7 +5296,27 @@ DEFHOOKPOD
@code{atomic_test_and_set} is not exactly 1, i.e. the\
@code{bool} @code{true}.",
unsigned char, 1)
-
+
+DEFHOOK
+(atomic_assign_expand_fenv,
+"ISO C11 requires atomic compound assignments that may raise floating-point\
+ exceptions to raise exceptions corresponding to the arithmetic operation\
+ whose result was successfully stored in a compare-and-exchange sequence. \
+ This requires code equivalent to calls to @code{feholdexcept},\
+ @code{feclearexcept} and @code{feupdateenv} to be generated at\
+ appropriate points in the compare-and-exchange sequence. This hook should\
+ set @code{*@var{hold}} to an expression equivalent to the call to\
+ @code{feholdexcept}, @code{*@var{clear}} to an expression equivalent to\
+ the call to @code{feclearexcept} and @code{*@var{update}} to an expression\
+ equivalent to the call to @code{feupdateenv}. The three expressions are\
+ @code{NULL_TREE} on entry to the hook and may be left as @code{NULL_TREE}\
+ if no code is required in a particular place. The default implementation\
+ leaves all three expressions as @code{NULL_TREE}. The\
+ @code{__atomic_feraiseexcept} function from @code{libatomic} may be of use\
+ 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
diff --git a/gcc/target.h b/gcc/target.h
index 405e2928b73..12249ecfd5c 100644
--- a/gcc/target.h
+++ b/gcc/target.h
@@ -50,6 +50,7 @@
#include "insn-modes.h"
#include "insn-codes.h"
+#include "double-int.h"
#ifdef ENABLE_CHECKING
diff --git a/gcc/targhooks.c b/gcc/targhooks.c
index 03db7b4da1e..a671486453a 100644
--- a/gcc/targhooks.c
+++ b/gcc/targhooks.c
@@ -68,7 +68,8 @@ along with GCC; see the file COPYING3. If not see
#include "recog.h"
#include "intl.h"
#include "opts.h"
-#include "tree-ssa.h"
+#include "gimple.h"
+#include "tree-ssanames.h"
#include "tree-ssa-alias.h"
#include "insn-codes.h"
@@ -93,7 +94,7 @@ void
default_external_libcall (rtx fun ATTRIBUTE_UNUSED)
{
#ifdef ASM_OUTPUT_EXTERNAL_LIBCALL
- ASM_OUTPUT_EXTERNAL_LIBCALL(asm_out_file, fun);
+ ASM_OUTPUT_EXTERNAL_LIBCALL (asm_out_file, fun);
#endif
}
@@ -435,6 +436,19 @@ targhook_float_words_big_endian (void)
return !!FLOAT_WORDS_BIG_ENDIAN;
}
+/* True if the target supports floating-point exceptions and rounding
+ modes. */
+
+bool
+default_float_exceptions_rounding_supported_p (void)
+{
+#ifdef HAVE_adddf3
+ return HAVE_adddf3;
+#else
+ return false;
+#endif
+}
+
/* True if the target supports decimal floating point. */
bool
@@ -1057,20 +1071,17 @@ default_add_stmt_cost (void *data, int count, enum vect_cost_for_stmt kind,
unsigned *cost = (unsigned *) data;
unsigned retval = 0;
- if (flag_vect_cost_model)
- {
- tree vectype = stmt_info ? stmt_vectype (stmt_info) : NULL_TREE;
- int stmt_cost = default_builtin_vectorization_cost (kind, vectype,
+ tree vectype = stmt_info ? stmt_vectype (stmt_info) : NULL_TREE;
+ int stmt_cost = default_builtin_vectorization_cost (kind, vectype,
misalign);
- /* Statements in an inner loop relative to the loop being
- vectorized are weighted more heavily. The value here is
- arbitrary and could potentially be improved with analysis. */
- if (where == vect_body && stmt_info && stmt_in_inner_loop_p (stmt_info))
- count *= 50; /* FIXME. */
-
- retval = (unsigned) (count * stmt_cost);
- cost[where] += retval;
- }
+ /* Statements in an inner loop relative to the loop being
+ vectorized are weighted more heavily. The value here is
+ arbitrary and could potentially be improved with analysis. */
+ if (where == vect_body && stmt_info && stmt_in_inner_loop_p (stmt_info))
+ count *= 50; /* FIXME. */
+
+ retval = (unsigned) (count * stmt_cost);
+ cost[where] += retval;
return retval;
}
@@ -1430,7 +1441,7 @@ default_debug_unwind_info (void)
mode for registers used in apply_builtin_return and apply_builtin_arg. */
enum machine_mode
-default_get_reg_raw_mode(int regno)
+default_get_reg_raw_mode (int regno)
{
return reg_raw_mode[regno];
}
@@ -1559,6 +1570,28 @@ default_member_type_forces_blk (const_tree, enum machine_mode)
{
return false;
}
+rtx
+default_load_bounds_for_arg (rtx addr ATTRIBUTE_UNUSED,
+ rtx ptr ATTRIBUTE_UNUSED,
+ rtx bnd ATTRIBUTE_UNUSED)
+{
+ gcc_unreachable ();
+}
+
+void
+default_store_bounds_for_arg (rtx val ATTRIBUTE_UNUSED,
+ rtx addr ATTRIBUTE_UNUSED,
+ rtx bounds ATTRIBUTE_UNUSED,
+ rtx to ATTRIBUTE_UNUSED)
+{
+ gcc_unreachable ();
+}
+
+tree
+default_fn_abi_va_list_bounds_size (tree fndecl ATTRIBUTE_UNUSED)
+{
+ return integer_zero_node;
+}
/* Default version of canonicalize_comparison. */
@@ -1567,4 +1600,152 @@ default_canonicalize_comparison (int *, rtx *, rtx *, bool)
{
}
+/* Default implementation of TARGET_ATOMIC_ASSIGN_EXPAND_FENV. */
+
+void
+default_atomic_assign_expand_fenv (tree *, tree *, tree *)
+{
+}
+
+#ifndef PAD_VARARGS_DOWN
+#define PAD_VARARGS_DOWN BYTES_BIG_ENDIAN
+#endif
+
+/* Build an indirect-ref expression over the given TREE, which represents a
+ piece of a va_arg() expansion. */
+tree
+build_va_arg_indirect_ref (tree addr)
+{
+ addr = build_simple_mem_ref_loc (EXPR_LOCATION (addr), addr);
+ return addr;
+}
+
+/* The "standard" implementation of va_arg: read the value from the
+ current (padded) address and increment by the (padded) size. */
+
+tree
+std_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
+ gimple_seq *post_p)
+{
+ tree addr, t, type_size, rounded_size, valist_tmp;
+ unsigned HOST_WIDE_INT align, boundary;
+ bool indirect;
+
+#ifdef ARGS_GROW_DOWNWARD
+ /* All of the alignment and movement below is for args-grow-up machines.
+ As of 2004, there are only 3 ARGS_GROW_DOWNWARD targets, and they all
+ implement their own specialized gimplify_va_arg_expr routines. */
+ gcc_unreachable ();
+#endif
+
+ indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false);
+ if (indirect)
+ type = build_pointer_type (type);
+
+ align = PARM_BOUNDARY / BITS_PER_UNIT;
+ boundary = targetm.calls.function_arg_boundary (TYPE_MODE (type), type);
+
+ /* When we align parameter on stack for caller, if the parameter
+ alignment is beyond MAX_SUPPORTED_STACK_ALIGNMENT, it will be
+ aligned at MAX_SUPPORTED_STACK_ALIGNMENT. We will match callee
+ here with caller. */
+ if (boundary > MAX_SUPPORTED_STACK_ALIGNMENT)
+ boundary = MAX_SUPPORTED_STACK_ALIGNMENT;
+
+ boundary /= BITS_PER_UNIT;
+
+ /* Hoist the valist value into a temporary for the moment. */
+ valist_tmp = get_initialized_tmp_var (valist, pre_p, NULL);
+
+ /* va_list pointer is aligned to PARM_BOUNDARY. If argument actually
+ requires greater alignment, we must perform dynamic alignment. */
+ if (boundary > align
+ && !integer_zerop (TYPE_SIZE (type)))
+ {
+ t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
+ fold_build_pointer_plus_hwi (valist_tmp, boundary - 1));
+ gimplify_and_add (t, pre_p);
+
+ t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
+ fold_build2 (BIT_AND_EXPR, TREE_TYPE (valist),
+ valist_tmp,
+ build_int_cst (TREE_TYPE (valist), -boundary)));
+ gimplify_and_add (t, pre_p);
+ }
+ else
+ boundary = align;
+
+ /* If the actual alignment is less than the alignment of the type,
+ adjust the type accordingly so that we don't assume strict alignment
+ when dereferencing the pointer. */
+ boundary *= BITS_PER_UNIT;
+ if (boundary < TYPE_ALIGN (type))
+ {
+ type = build_variant_type_copy (type);
+ TYPE_ALIGN (type) = boundary;
+ }
+
+ /* Compute the rounded size of the type. */
+ type_size = size_in_bytes (type);
+ rounded_size = round_up (type_size, align);
+
+ /* Reduce rounded_size so it's sharable with the postqueue. */
+ gimplify_expr (&rounded_size, pre_p, post_p, is_gimple_val, fb_rvalue);
+
+ /* Get AP. */
+ addr = valist_tmp;
+ if (PAD_VARARGS_DOWN && !integer_zerop (rounded_size))
+ {
+ /* Small args are padded downward. */
+ t = fold_build2_loc (input_location, GT_EXPR, sizetype,
+ rounded_size, size_int (align));
+ t = fold_build3 (COND_EXPR, sizetype, t, size_zero_node,
+ size_binop (MINUS_EXPR, rounded_size, type_size));
+ addr = fold_build_pointer_plus (addr, t);
+ }
+
+ /* Compute new value for AP. */
+ t = fold_build_pointer_plus (valist_tmp, rounded_size);
+ t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
+ gimplify_and_add (t, pre_p);
+
+ addr = fold_convert (build_pointer_type (type), addr);
+
+ if (indirect)
+ addr = build_va_arg_indirect_ref (addr);
+
+ return build_va_arg_indirect_ref (addr);
+}
+
+tree
+default_chkp_bound_type (void)
+{
+ tree res = make_node (POINTER_BOUNDS_TYPE);
+ TYPE_PRECISION (res) = TYPE_PRECISION (size_type_node) * 2;
+ layout_type (res);
+ return res;
+}
+
+enum machine_mode
+default_chkp_bound_mode (void)
+{
+ return VOIDmode;
+}
+
+tree
+default_builtin_chkp_function (unsigned int fcode ATTRIBUTE_UNUSED)
+{
+ return NULL_TREE;
+}
+
+/* An implementation of TARGET_CAN_USE_DOLOOP_P for targets that do
+ not support nested low-overhead loops. */
+
+bool
+can_use_doloop_if_innermost (double_int, double_int,
+ unsigned int loop_depth, bool)
+{
+ return loop_depth == 1;
+}
+
#include "gt-targhooks.h"
diff --git a/gcc/targhooks.h b/gcc/targhooks.h
index aaddae93209..1ba0c1d4e7d 100644
--- a/gcc/targhooks.h
+++ b/gcc/targhooks.h
@@ -69,6 +69,7 @@ extern tree default_mangle_assembler_name (const char *);
extern bool default_scalar_mode_supported_p (enum machine_mode);
extern bool targhook_words_big_endian (void);
extern bool targhook_float_words_big_endian (void);
+extern bool default_float_exceptions_rounding_supported_p (void);
extern bool default_decimal_float_supported_p (void);
extern bool default_fixed_point_supported_p (void);
@@ -193,7 +194,7 @@ extern int default_label_align_max_skip (rtx);
extern int default_jump_align_max_skip (rtx);
extern section * default_function_section(tree decl, enum node_frequency freq,
bool startup, bool exit);
-extern enum machine_mode default_get_reg_raw_mode(int);
+extern enum machine_mode default_get_reg_raw_mode (int);
extern void *default_get_pch_validity (size_t *);
extern const char *default_pch_valid_p (const void *, size_t);
@@ -202,3 +203,15 @@ extern void default_asm_output_ident_directive (const char*);
extern enum machine_mode default_cstore_mode (enum insn_code);
extern bool default_member_type_forces_blk (const_tree, enum machine_mode);
+extern void default_atomic_assign_expand_fenv (tree *, tree *, tree *);
+extern tree build_va_arg_indirect_ref (tree);
+extern tree std_gimplify_va_arg_expr (tree, tree, gimple_seq *, gimple_seq *);
+
+extern rtx default_load_bounds_for_arg (rtx, rtx, rtx);
+extern void default_store_bounds_for_arg (rtx, rtx, rtx, rtx);
+extern tree default_fn_abi_va_list_bounds_size (tree);
+extern tree default_chkp_bound_type (void);
+extern enum machine_mode default_chkp_bound_mode (void);
+extern tree default_builtin_chkp_function (unsigned int);
+extern bool can_use_doloop_if_innermost (double_int, double_int,
+ unsigned int, bool);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 203fd13ddb0..849597c0d0c 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,1782 @@
+2013-11-11 Martin Liska <marxin.liska@gmail.com>
+
+ * gcc.dg/time-profiler-1.c: New test.
+ * gcc.dg/time-profiler-2.c: Ditto.
+
+2013-11-11 Marc Glisse <marc.glisse@inria.fr>
+ Jeff Law <law@redhat.com>
+
+ * gcc.dg/tree-ssa/alias-27.c: New testcase.
+
+2013-11-11 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/58853
+ * gcc.target/i386/pr58853.c: New test.
+
+2013-11-11 Joern Rennecke <joern.rennecke@embecosm.com>
+
+ * gcc.dg/tree-ssa/forwprop-28.c: Adjust for ARC
+ LOGICAL_OP_NON_SHORT_CIRCUIT definition.
+ * gcc.dg/tree-ssa/ssa-dom-thread-4.c: Likewise.
+ * gcc.dg/tree-ssa/ssa-ifcombine-ccmp-1.c: Likewise.
+ * gcc.dg/tree-ssa/ssa-ifcombine-ccmp-4.c: Likewise.
+ * gcc.dg/tree-ssa/ssa-ifcombine-ccmp-5.c: Likewise.
+ * gcc.dg/tree-ssa/ssa-ifcombine-ccmp-6.c: Likewise.
+ * gcc.dg/tree-ssa/vrp47.c: Likewise.
+ * gcc.dg/tree-ssa/vrp87.c: Likewise.
+
+2013-11-08 Joseph Myers <joseph@codesourcery.com>
+
+ * gcc.dg/atomic/stdatomic-compare-exchange-1.c,
+ gcc.dg/atomic/stdatomic-compare-exchange-2.c,
+ gcc.dg/atomic/stdatomic-compare-exchange-3.c,
+ gcc.dg/atomic/stdatomic-compare-exchange-4.c,
+ gcc.dg/atomic/stdatomic-exchange-1.c,
+ gcc.dg/atomic/stdatomic-exchange-2.c,
+ gcc.dg/atomic/stdatomic-exchange-3.c,
+ gcc.dg/atomic/stdatomic-exchange-4.c,
+ gcc.dg/atomic/stdatomic-fence.c, gcc.dg/atomic/stdatomic-flag.c,
+ gcc.dg/atomic/stdatomic-generic.c,
+ gcc.dg/atomic/stdatomic-kill-dep.c,
+ gcc.dg/atomic/stdatomic-load-1.c,
+ gcc.dg/atomic/stdatomic-load-2.c,
+ gcc.dg/atomic/stdatomic-load-3.c,
+ gcc.dg/atomic/stdatomic-load-4.c,
+ gcc.dg/atomic/stdatomic-lockfree.c,
+ gcc.dg/atomic/stdatomic-op-1.c, gcc.dg/atomic/stdatomic-op-2.c,
+ gcc.dg/atomic/stdatomic-op-3.c, gcc.dg/atomic/stdatomic-op-4.c,
+ gcc.dg/atomic/stdatomic-store-1.c,
+ gcc.dg/atomic/stdatomic-store-2.c,
+ gcc.dg/atomic/stdatomic-store-3.c,
+ gcc.dg/atomic/stdatomic-store-4.c, gcc.dg/c11-stdatomic-1.c: New
+ tests.
+
+2013-11-08 Cong Hou <congh@google.com>
+
+ PR tree-optimization/58508
+ * gcc.dg/vect/pr58508.c: Update.
+
+2013-11-08 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/59047
+ * gcc.dg/torture/pr59047.c: New testcase.
+
+2013-11-08 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/59038
+ PR tree-optimization/58955
+ * gcc.dg/torture/pr59038.c: New testcase.
+
+2013-11-07 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/58471
+ * gfortran.dg/constructor_9.f90: New.
+
+2013-11-07 Joseph Myers <joseph@codesourcery.com>
+
+ * gcc.dg/atomic-compare-exchange-1.c,
+ gcc.dg/atomic-compare-exchange-2.c,
+ gcc.dg/atomic-compare-exchange-3.c,
+ gcc.dg/atomic-compare-exchange-4.c,
+ gcc.dg/atomic-compare-exchange-5.c, gcc.dg/atomic-exchange-1.c,
+ gcc.dg/atomic-exchange-2.c, gcc.dg/atomic-exchange-3.c,
+ gcc.dg/atomic-exchange-4.c, gcc.dg/atomic-exchange-5.c,
+ gcc.dg/atomic-fence.c, gcc.dg/atomic-flag.c,
+ gcc.dg/atomic-generic.c, gcc.dg/atomic-invalid.c,
+ gcc.dg/atomic-load-1.c, gcc.dg/atomic-load-2.c,
+ gcc.dg/atomic-load-3.c, gcc.dg/atomic-load-4.c,
+ gcc.dg/atomic-load-5.c, gcc.dg/atomic-lockfree.c,
+ gcc.dg/atomic-noinline.c, gcc.dg/atomic-op-1.c,
+ gcc.dg/atomic-op-2.c, gcc.dg/atomic-op-3.c, gcc.dg/atomic-op-4.c,
+ gcc.dg/atomic-op-5.c, gcc.dg/atomic-param.c,
+ gcc.dg/atomic-store-1.c, gcc.dg/atomic-store-2.c,
+ gcc.dg/atomic-store-3.c, gcc.dg/atomic-store-4.c,
+ gcc.dg/atomic-store-5.c: Declare main as returning int.
+ * gcc.dg/atomic-exchange-1.c, gcc.dg/atomic-exchange-2.c,
+ gcc.dg/atomic-exchange-3.c, gcc.dg/atomic-exchange-4.c,
+ gcc.dg/atomic-exchange-5.c: Separate increments of count from
+ expression using value of count.
+
+2013-11-07 Joseph Myers <joseph@codesourcery.com>
+
+ * lib/target-supports.exp
+ (check_effective_target_fenv_exceptions): New function.
+ * lib/atomic-dg.exp, gcc.dg/atomic/atomic.exp: New files.
+ * gcc.dg/atomic/c11-atomic-exec-1.c,
+ gcc.dg/atomic/c11-atomic-exec-2.c,
+ gcc.dg/atomic/c11-atomic-exec-3.c,
+ gcc.dg/atomic/c11-atomic-exec-4.c,
+ gcc.dg/atomic/c11-atomic-exec-5.c, gcc.dg/c11-atomic-1.c,
+ gcc.dg/c11-atomic-2.c, gcc.dg/c11-atomic-3.c,
+ gcc.dg/c90-atomic-1.c, gcc.dg/c99-atomic-1.c: New tests.
+
+2013-11-07 Cong Hou <congh@google.com>
+
+ * gcc.dg/vect/vect-alias-check.c: New.
+
+2013-11-07 Jakub Jelinek <jakub@redhat.com>
+
+ * gcc.dg/tree-ssa/loop-39.c: New test.
+
+ * gcc.dg/unroll_1.c: Add -fno-tree-vrp to dg-options.
+ * gcc.dg/unroll_2.c: Likewise.
+ * gcc.dg/unroll_3.c: Likewise.
+ * gcc.dg/unroll_4.c: Likewise.
+ * gcc.dg/vrp90.c: New test.
+
+2013-11-07 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58176
+ * g++.dg/cpp0x/nullptr30.C: New.
+
+2013-11-07 Yury Gribov <y.gribov@samsung.com>
+ Jakub Jelinek <jakub@redhat.com>
+
+ PR sanitizer/59029
+ * c-c++-common/asan/pr59029.c: New test.
+
+2013-11-07 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/59034
+ * gcc.target/i386/pr59034-1.c: New test.
+ * gcc.target/i386/pr59034-2.c: Likewise.
+
+2013-11-07 Bin Cheng <bin.cheng@arm.com>
+
+ * gcc.dg/tree-ssa/loop-2.c: Refine check condition.
+ * gcc.dg/tree-ssa/ivopt_infer_2.c: Ditto.
+ * gcc.dg/tree-ssa/ivopt_mult_3.c: Ditto.
+
+2013-11-06 DJ Delorie <dj@redhat.com>
+
+ * gcc.dg/mismatch-decl-1.c: New test.
+
+2013-11-06 Joseph Myers <joseph@codesourcery.com>
+
+ * gcc.dg/torture/float128-cmp-invalid.c,
+ gcc.dg/torture/float128-div-underflow.c,
+ gcc.dg/torture/float128-extend-nan.c,
+ gcc.dg/torture/fp-int-convert-float128-timode-3.c: New tests.
+
+2013-11-06 Oleg Endo <olegendo@gcc.gnu.org>
+
+ * gcc.target/sh/pr51244-11.c: Remove target line.
+ * gcc.target/sh/sh4a-sincosf.c: Likewise.
+ * gcc.target/sh/attr-isr-trap_exit.c: Likewise.
+ * gcc.target/sh/pr51244-15.c: Likewise.
+ * gcc.target/sh/pr51244-19.c: Likewise.
+ * gcc.target/sh/cmpstr.c: Likewise.
+ * gcc.target/sh/pr33135-3.c: Likewise.
+ * gcc.target/sh/pr53512-2.c: Likewise.
+ * gcc.target/sh/pr54602-2.c: Likewise.
+ * gcc.target/sh/pr52483-1.c: Likewise.
+ * gcc.target/sh/pr21255-2-ml.c: Likewise.
+ * gcc.target/sh/pr54760-4.c: Likewise.
+ * gcc.target/sh/pr52483-5.c: Likewise.
+ * gcc.target/sh/pr54089-2.c: Likewise.
+ * gcc.target/sh/pr56547-2.c: Likewise.
+ * gcc.target/sh/pr54089-6.c: Likewise.
+ * gcc.target/sh/pr51244-20.c: Likewise.
+ * gcc.target/sh/pr50749-sf-predec-4.c: Likewise.
+ * gcc.target/sh/sh4a-fsrra.c: Likewise.
+ * gcc.target/sh/pr50749-qihisi-predec-1.c: Likewise.
+ * gcc.target/sh/pr50749-sf-postinc-2.c: Likewise.
+ * gcc.target/sh/pr55303-2.c: Likewise.
+ * gcc.target/sh/sh2a-resbank.c: Likewise.
+ * gcc.target/sh/sp-switch.c: Likewise.
+ * gcc.target/sh/pr51244-3.c: Likewise.
+ * gcc.target/sh/pr50751-3.c: Likewise.
+ * gcc.target/sh/pr51244-7.c: Likewise.
+ * gcc.target/sh/struct-arg-dw2.c: Likewise.
+ * gcc.target/sh/pr50751-7.c: Likewise.
+ * gcc.target/sh/pr49468-di.c: Likewise.
+ * gcc.target/sh/pr50749-qihisi-postinc-4.c: Likewise.
+ * gcc.target/sh/pr49880-3.c: Likewise.
+ * gcc.target/sh/pr51244-12.c: Likewise.
+ * gcc.target/sh/pr53988.c: Likewise.
+ * gcc.target/sh/pr6526.c: Likewise.
+ * gcc.target/sh/sh2a-bxor.c: Likewise.
+ * gcc.target/sh/pr51244-16.c: Likewise.
+ * gcc.target/sh/sh2a-bclrmem.c: Likewise.
+ * gcc.target/sh/sh2a-bor.c: Likewise.
+ * gcc.target/sh/pr53511-1.c: Likewise.
+ * gcc.target/sh/pr21255-3.c: Likewise.
+ * gcc.target/sh/pr53512-3.c: Likewise.
+ * gcc.target/sh/pr33135-4.c: Likewise.
+ * gcc.target/sh/pr54602-3.c: Likewise.
+ * gcc.target/sh/pr54760-1.c: Likewise.
+ * gcc.target/sh/pr52483-2.c: Likewise.
+ * gcc.target/sh/sh2a-bsetmem.c: Likewise.
+ * gcc.target/sh/pr54680.c: Likewise.
+ * gcc.target/sh/pr54386.c: Likewise.
+ * gcc.target/sh/pr51244-20-sh2a.c: Likewise.
+ * gcc.target/sh/pr54089-3.c: Likewise.
+ * gcc.target/sh/pr50749-sf-predec-1.c: Likewise.
+ * gcc.target/sh/pr54089-7.c: Likewise.
+ * gcc.target/sh/strlen.c: Likewise.
+ * gcc.target/sh/pr50749-sf-postinc-3.c: Likewise.
+ * gcc.target/sh/pr50749-qihisi-predec-2.c: Likewise.
+ * gcc.target/sh/pr55303-3.c: Likewise.
+ * gcc.target/sh/pr51244-4.c: Likewise.
+ * gcc.target/sh/pr50751-4.c: Likewise.
+ * gcc.target/sh/pr39423-1.c: Likewise.
+ * gcc.target/sh/pr51244-8.c: Likewise.
+ * gcc.target/sh/pr55146.c: Likewise.
+ * gcc.target/sh/pr50751-8.c: Likewise.
+ * gcc.target/sh/sh2a-bset.c: Likewise.
+ * gcc.target/sh/pr50749-qihisi-postinc-1.c: Likewise.
+ * gcc.target/sh/sh2a-movi20s.c: Likewise.
+ * gcc.target/sh/20080410-1.c: Likewise.
+ * gcc.target/sh/pr49880-4.c: Likewise.
+ * gcc.target/sh/pr51244-13.c: Likewise.
+ * gcc.target/sh/sh2a-movrt.c: Likewise.
+ * gcc.target/sh/pr51244-17.c: Likewise.
+ * gcc.target/sh/pr21255-2-mb.c: Likewise.
+ * gcc.target/sh/sh2a-bclr.c: Likewise.
+ * gcc.target/sh/pr33135-1.c: Likewise.
+ * gcc.target/sh/pr53512-4.c: Likewise.
+ * gcc.target/sh/pr54602-4.c: Likewise.
+ * gcc.target/sh/sh4a-bitmovua.c: Likewise.
+ * gcc.target/sh/pr54760-2.c: Likewise.
+ * gcc.target/sh/pr52483-3.c: Likewise.
+ * gcc.target/sh/sh2a-bld.c: Likewise.
+ * gcc.target/sh/pr54089-4.c: Likewise.
+ * gcc.target/sh/pr54685.c: Likewise.
+ * gcc.target/sh/pr50749-sf-predec-2.c: Likewise.
+ * gcc.target/sh/pr54089-8.c: Likewise.
+ * gcc.target/sh/pragma-isr-trap-exit.c: Likewise.
+ * gcc.target/sh/pr50749-qihisi-predec-3.c: Likewise.
+ * gcc.target/sh/pr50749-sf-postinc-4.c: Likewise.
+ * gcc.target/sh/pr51244-1.c: Likewise.
+ * gcc.target/sh/pr50751-1.c: Likewise.
+ * gcc.target/sh/pr55160.c: Likewise.
+ * gcc.target/sh/pr51244-5.c: Likewise.
+ * gcc.target/sh/pr54236-1.c: Likewise.
+ * gcc.target/sh/pr50751-5.c: Likewise.
+ * gcc.target/sh/pr52933-1.c: Likewise.
+ * gcc.target/sh/pr39423-2.c: Likewise.
+ * gcc.target/sh/pr51244-9.c: Likewise.
+ * gcc.target/sh/pr49263.c: Likewise.
+ * gcc.target/sh/pr50749-qihisi-postinc-2.c: Likewise.
+ * gcc.target/sh/pr49880-1.c: Likewise.
+ * gcc.target/sh/sh2a-band.c: Likewise.
+ * gcc.target/sh/pr51244-10.c: Likewise.
+ * gcc.target/sh/pr49880-5.c: Likewise.
+ * gcc.target/sh/prefetch.c: Likewise.
+ * gcc.target/sh/pr51244-14.c: Likewise.
+ * gcc.target/sh/rte-delay-slot.c: Likewise.
+ * gcc.target/sh/fpul-usage-1.c: Likewise.
+ * gcc.target/sh/pr51244-18.c: Likewise.
+ * gcc.target/sh/pr21255-1.c: Likewise.
+ * gcc.target/sh/pr33135-2.c: Likewise.
+ * gcc.target/sh/pr53512-1.c: Likewise.
+ * gcc.target/sh/pr54602-1.c: Likewise.
+ * gcc.target/sh/sh2a-rtsn.c: Likewise.
+ * gcc.target/sh/torture/pragma-isr.c: Likewise.
+ * gcc.target/sh/torture/pragma-isr2.c: Likewise.
+ * gcc.target/sh/torture/pr58314.c: Likewise.
+ * gcc.target/sh/torture/pr34777.c: Likewise.
+ * gcc.target/sh/torture/pr58475.c: Likewise.
+ * gcc.target/sh/pr54760-3.c: Likewise.
+ * gcc.target/sh/sh4a-cosf.c: Likewise.
+ * gcc.target/sh/pr52483-4.c: Likewise.
+ * gcc.target/sh/mfmovd.c: Likewise.
+ * gcc.target/sh/pr54089-1.c: Likewise.
+ * gcc.target/sh/pr56547-1.c: Likewise.
+ * gcc.target/sh/pr54089-5.c: Likewise.
+ * gcc.target/sh/pr50749-sf-predec-3.c: Likewise.
+ * gcc.target/sh/pr54089-9.c: Likewise.
+ * gcc.target/sh/sh2a-jsrn.c: Likewise.
+ * gcc.target/sh/pr49468-si.c: Likewise.
+ * gcc.target/sh/pr50749-sf-postinc-1.c: Likewise.
+ * gcc.target/sh/pr50749-qihisi-predec-4.c: Likewise.
+ * gcc.target/sh/pr55303-1.c: Likewise.
+ * gcc.target/sh/pr51244-2.c: Likewise.
+ * gcc.target/sh/pr50751-2.c: Likewise.
+ * gcc.target/sh/pr54236-2.c: Likewise.
+ * gcc.target/sh/pr51244-6.c: Likewise.
+ * gcc.target/sh/cmpstrn.c: Likewise.
+ * gcc.target/sh/pr50751-6.c: Likewise.
+ * gcc.target/sh/pr52933-2.c: Likewise.
+ * gcc.target/sh/pr53568-1.c: Likewise.
+ * gcc.target/sh/pr50749-qihisi-postinc-3.c: Likewise.
+ * gcc.target/sh/sh2a-tbr-jump.c: Likewise.
+ * gcc.target/sh/sh4a-sinf.c: Likewise.
+ * gcc.target/sh/pr49880-2.c: Likewise.
+
+2013-11-06 Tobias Burnus <burnus@net-b.de>
+
+ * g++.dg/warn/wdate-time.C: Update dg-error pattern.
+ * gcc.dg/wdate-time.c: Ditto.
+ * gfortran.dg/wdate-time.F90: Ditto.
+
+2013-11-06 Oleg Endo <olegendo@gcc.gnu.org>
+
+ PR target/30807
+ * gcc.target/sh/torture/pr30807.c: New.
+
+2013-11-06 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/11006
+ * g++.dg/other/java3.C: New.
+
+2013-11-06 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/59021
+ * gcc.target/i386/pr59021.c: New test.
+
+2013-11-06 James Lemke <jwlemke@codesourcery.com>
+
+ * lib/gcc-defs.exp (dg-additional-files-options): Extend regsub for
+ dg-additional-files to also match BOL.
+
+2013-11-06 Joseph Myers <joseph@codesourcery.com>
+
+ * gcc.dg/torture/c99-contract-1.c: New test.
+
+2013-11-06 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/58653
+ * gcc.dg/tree-ssa/predcom-6.c: New testcase.
+ * gcc.dg/tree-ssa/predcom-7.c: Likewise.
+
+2013-11-05 Balaji V. Iyer <balaji.v.iyer@intel.com>
+
+ * c-c++-common/cilk-plus/CK/fib.c: Reduced the iteration from
+ 40 to 30. Replaced iteration variable with a #define. Instead of
+ returning non-zero value for error, called __builtin_abort (). Fixed
+ a bug of calling fib_serial in serial case instead of fib.
+ * c-c++-common/cilk-plus/CK/fib_init_expr_xy.c: Likewise.
+ * c-c++-common/cilk-plus/CK/fib_no_return.c: Likewise.
+ * c-c++-common/cilk-plus/CK/fib_no_sync.c: Likewise.
+ * gcc.dg/cilk-plus/cilk-plus.exp: Removed duplicate/un-necessary
+ compiler flag testing.
+
+2013-11-06 Christian Bruel <christian.bruel@st.com>
+
+ * gcc.target/sh/strlen.c: New test.
+
+2013-11-06 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/58970
+ * gcc.c-torture/compile/pr58970.c: New test.
+
+2013-11-05 Wei Mi <wmi@google.com>
+
+ PR regression/58985
+ * testsuite/gcc.dg/pr57518.c: Add subreg in regexp pattern.
+
+2013-11-05 Tobias Burnus <burnus@net-b.de>
+
+ * g++.dg/warn/wdate-time.C: New.
+ * gcc.dg/wdate-time.c: New.
+ * gfortran.dg/wdate-time.F90: New.
+
+2013-11-05 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/58989
+ * gfortran.dg/reshape_6.f90: New test.
+
+2013-10-05 Jeff Law <law@redhat.com>
+
+ * gcc.dg/pr38984.c: Add -fno-isolate-erroneous-paths.
+ * gcc.dg/tree-ssa/isolate-1.c: New test.
+ * gcc.dg/tree-ssa/isolate-2.c: New test.
+ * gcc.dg/tree-ssa/isolate-3.c: New test.
+ * gcc.dg/tree-ssa/isolate-4.c: New test.
+
+2013-11-05 Jakub Jelinek <jakub@redhat.com>
+
+ PR rtl-optimization/58997
+ * gcc.c-torture/compile/pr58997.c: New test.
+
+2013-11-05 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58724
+ * g++.dg/cpp0x/gen-attrs-56.C: New.
+
+2013-11-05 Richard Biener <rguenther@suse.de>
+
+ PR ipa/58492
+ * gcc.dg/ipa/pr58492.c: New testcase.
+
+2013-11-05 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/58955
+ * gcc.dg/torture/pr58955-1.c: New testcase.
+ * gcc.dg/torture/pr58955-2.c: Likewise.
+
+2013-11-05 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR middle-end/58981
+ * gcc.dg/pr58981.c: New test.
+
+2013-11-05 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/58941
+ * gcc.dg/torture/pr58941.c: New testcase.
+
+2013-11-05 Marc Glisse <marc.glisse@inria.fr>
+
+ PR tree-optimization/58958
+ * gcc.dg/tree-ssa/pr58958.c: New file.
+
+2013-11-05 Marc Glisse <marc.glisse@inria.fr>
+
+ * gcc.dg/tree-ssa/alias-26.c: New file.
+
+2013-11-05 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/58984
+ * gcc.c-torture/execute/pr58984.c: New test.
+
+2013-11-05 Andreas Schwab <schwab@suse.de>
+
+ * g++.dg/ext/sync-4.C: Require sync_long_long_runtime support.
+
+2013-11-05 Tobias Burnus <burnus@net-b.de>
+
+ * g++.dg/gomp/openmp-simd-1.C: New.
+ * g++.dg/gomp/openmp-simd-2.C: New.
+ * gcc.dg/gomp/openmp-simd-1.c: New.
+ * gcc.dg/gomp/openmp-simd-2.c: New.
+
+2013-11-04 Senthil Kumar Selvaraj <senthil_kumar.selvaraj@atmel.com>
+
+ * gcc.dg/superblock.c: Require scheduling support.
+
+2013-11-04 Kostya Serebryany <kcc@google.com>
+
+ * g++.dg/asan/asan_test.cc: Update the test
+ to match the fresh asan run-time.
+ * c-c++-common/asan/stack-overflow-1.c: Ditto.
+
+2013-11-04 Ian Lance Taylor <iant@google.com>
+
+ * g++.dg/ext/sync-4.C: New test.
+
+2013-11-04 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/58771
+ * gfortran.dg/derived_external_function_1.f90 : New test
+
+2013-11-04 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/58978
+ * gcc.c-torture/compile/pr58978.c: New test.
+
+2013-11-04 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/57445
+ * gfortran.dg/optional_class_1.f90 : New test
+
+2013-11-04 Vladimir Makarov <vmakarov@redhat.com>
+
+ PR rtl-optimization/58968
+ * gfortran.dg/pr58968.f: New
+
+2013-11-04 Marek Polacek <polacek@redhat.com>
+
+ PR c++/58979
+ * g++.dg/diagnostic/pr58979.C: New test.
+
+2013-11-04 Joseph Myers <joseph@codesourcery.com>
+
+ * gcc.dg/iec-559-macros-1.c, gcc.dg/iec-559-macros-2.c,
+ gcc.dg/iec-559-macros-3.c, gcc.dg/iec-559-macros-4.c,
+ gcc.dg/iec-559-macros-5.c, gcc.dg/iec-559-macros-6.c,
+ gcc.dg/iec-559-macros-7.c, gcc.dg/iec-559-macros-8.c,
+ gcc.dg/iec-559-macros-9.c: New tests.
+
+2013-11-04 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/58946
+ * gcc.c-torture/compile/pr58946.c: New test.
+
+2013-11-03 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/52071
+ * g++.dg/parse/pr52071.C: New.
+
+2013-11-03 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/38313
+ * g++.dg/lookup/name-clash10.C: New.
+
+2013-11-03 Kugan Vivekanandarajah <kuganv@linaro.org>
+
+ * gcc.target/arm/neon-vcond-gt.c: Scan for vbsl or vbit or vbif.
+ * gcc.target/arm/neon-vcond-ltgt.c: Scan for vbsl or vbit or vbif.
+ * gcc.target/arm/neon-vcond-unordered.c: Scan for vbsl or vbit or
+ vbif.
+
+2013-11-03 Marek Polacek <polacek@redhat.com>
+
+ * g++.dg/ubsan/cxx1y-vla.C: New test.
+ * c-c++-common/ubsan/vla-3.c: New test.
+ * c-c++-common/ubsan/vla-2.c: New test.
+ * c-c++-common/ubsan/vla-4.c: New test.
+ * c-c++-common/ubsan/vla-1.c: New test.
+
+2013-11-02 Bill Schmidt <wschmidt@vnet.linux.ibm.com>
+
+ * gcc.dg/vmx/vec-set.c: New.
+
+2013-11-02 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/29234
+ PR c++/56037
+ * g++.dg/parse/pr29234.C: New.
+ * g++.dg/parse/pr56037.C: Likewise.
+
+2013-11-01 Balaji V. Iyer <balaji.v.iyer@intel.com>
+
+ * gcc.dg/cilk-plus/cilk-plus.exp: Loaded libcilkrts library path and
+ passed it in as one of the options to all Cilk keywords test.
+
+2013-11-01 Edward Smith-Rowland <3dw4rd@verizon.net>
+
+ PR c++/58708
+ * g++.dg/cpp1y/pr58708.C: New.
+
+2013-11-01 Marc Glisse <marc.glisse@inria.fr>
+
+ PR c++/58834
+ * g++.dg/ext/pr58834.C: New file.
+
+2013-11-01 Jakub Jelinek <jakub@redhat.com>
+
+ * gcc.dg/gomp/declare-simd-2.c (f12, f13, f14, f15, f16, f17): New
+ tests.
+ * g++.dg/gomp/declare-simd-2.C (f15, f16, f17, f18, f19, f20): New
+ tests.
+
+2013-11-01 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/57893
+ * gfortran.dg/unlimited_polymorphic_13.f90 : Break up select
+ type block.
+
+2013-10-31 Jakub Jelinek <jakub@redhat.com>
+
+ * g++.dg/gomp/simd-1.C: New test.
+ * g++.dg/gomp/declare-simd-1.C (f32): Fix up aligned clause argument.
+ * g++.dg/gomp/declare-simd-2.C (fn13, fn14): Add new tests.
+ * gcc.dg/gomp/declare-simd-2.c (fn7, fn8, fn9, fn10, fn11): Likewise.
+ * c-c++-common/gomp/simd6.c: New test.
+
+2013-10-31 Edward Smith-Rowland <3dw4rd@verizon.net>
+
+ Implement C++14 digit separators.
+ * g++.dg/cpp1y/digit-sep.C: New.
+ * g++.dg/cpp1y/digit-sep-neg.C: New.
+ * g++.dg/cpp1y/digit-sep-cxx11-neg.C: New.
+
+2013-10-31 Jakub Jelinek <jakub@redhat.com>
+
+ * gcc.dg/vect/vect-align-3.c: New test.
+
+ * g++.dg/warn/pr33738.C (main): Initialize a2 again to make sure
+ we warn about it already during VRP1 pass.
+
+2013-10-31 Martin Jambor <mjambor@suse.cz>
+
+ PR rtl-optimization/58934
+ Revert:
+ 2013-10-30 Martin Jambor <mjambor@suse.cz>
+ PR rtl-optimization/10474
+ * gcc.dg/pr10474.c: New testcase.
+ * gcc.dg/ira-shrinkwrap-prep-1.c: Likewise.
+ * gcc.dg/ira-shrinkwrap-prep-2.c: Likewise.
+
+2013-10-31 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58932
+ Revert:
+ 2013-10-18 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58466
+ * g++.dg/cpp0x/variadic145.C: New.
+
+ * g++.dg/cpp0x/sfinae49.C: New.
+
+2013-10-30 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58581
+ * g++.dg/cpp0x/deleted1.C: New.
+
+2013-10-31 Zhenqiang Chen <zhenqiang.chen@linaro.org>
+
+ * gcc.target/arm/lp1243022.c: New test.
+
+2013-10-30 Joern Rennecke <joern.rennecke@embecosm.com>
+
+ PR other/58545
+ * gcc.target/avr/pr58545.c: New test.
+
+2013-10-30 Tobias Burnus <burnus@net-b.de>
+
+ Revert:
+ 2013-10-30 Tobias Burnus <burnus@net-b.de>
+ * gcc.dg/cilk-plus/cilk-plus.exp: Add the libcilkrts library
+ path to the compile flags.
+
+2013-10-30 Cong Hou <congh@google.com>
+
+ * gcc.target/i386/vect-abs-s8.c: New test.
+ * gcc.target/i386/vect-abs-s16.c: New test.
+ * gcc.target/i386/vect-abs-s32.c: New test.
+
+2013-10-30 Tobias Burnus <burnus@net-b.de>
+
+ * gcc.dg/cilk-plus/cilk-plus.exp: Add the libcilkrts library
+ path to the compile flags.
+
+2013-10-30 Mikael Pettersson <mikpe@it.uu.se>
+
+ PR rtl-optimization/58369
+ * g++.dg/torture/pr58369.C: New test.
+
+2013-10-30 Tobias Burnus <burnus@net-b.de>
+
+ PR other/33426
+ * g++.dg/vect/pr33426-ivdep-2.cc: New.
+ * g++.dg/vect/pr33426-ivdep-3.cc: New.
+ * g++.dg/vect/pr33426-ivdep-4.cc: New.
+
+2013-10-30 Vladimir Makarov <vmakarov@redhat.com>
+
+ PR target/58784
+ * gcc.target/arm/pr58784.c: New.
+
+2013-10-30 Marc Glisse <marc.glisse@inria.fr>
+
+ * gcc.dg/tree-ssa/alias-24.c: New file.
+
+2013-10-30 Vladimir Makarov <vmakarov@redhat.com>
+
+ * gcc.target/i386/fma_double_3.c: Use pattern for
+ scan-assembler-times instead of just one insn name.
+ * gcc.target/i386/fma_double_5.c: Ditto.
+ * gcc.target/i386/fma_float_3.c: Ditto.
+ * gcc.target/i386/fma_float_5.c: Ditto.
+ * gcc.target/i386/l_fma_double_1.c: Ditto.
+ * gcc.target/i386/l_fma_double_2.c: Ditto.
+ * gcc.target/i386/l_fma_double_3.c: Ditto.
+ * gcc.target/i386/l_fma_double_4.c: Ditto.
+ * gcc.target/i386/l_fma_double_5.c: Ditto.
+ * gcc.target/i386/l_fma_double_6.c: Ditto.
+ * gcc.target/i386/l_fma_float_1.c: Ditto.
+ * gcc.target/i386/l_fma_float_2.c: Ditto.
+ * gcc.target/i386/l_fma_float_3.c: Ditto.
+ * gcc.target/i386/l_fma_float_4.c: Ditto.
+ * gcc.target/i386/l_fma_float_5.c: Ditto.
+ * gcc.target/i386/l_fma_float_6.c: Ditto.
+
+2013-10-30 Christian Bruel <christian.bruel@st.com>
+
+ * gcc.c-torture/execute/builtins/strncmp-2.c: Enable for SH.
+ * gcc.target/sh/cmpstr.c: New test.
+ * gcc.target/sh/cmpstrn.c: New test.
+
+2013-10-30 Martin Jambor <mjambor@suse.cz>
+
+ PR rtl-optimization/10474
+ * gcc.dg/pr10474.c: New testcase.
+ * gcc.dg/ira-shrinkwrap-prep-1.c: Likewise.
+ * gcc.dg/ira-shrinkwrap-prep-2.c: Likewise.
+
+2013-10-29 Andrew Pinski <apinski@cavium.com>
+ Zhenqiang Chen <zhenqiang.chen@linaro.org>
+
+ * gcc.dg/tree-ssa/ssa-ifcombine-ccmp-1.c: New test case.
+ * gcc.dg/tree-ssa/ssa-ifcombine-ccmp-2.c: New test case.
+ * gcc.dg/tree-ssa/ssa-ifcombine-ccmp-3.c: New test case.
+ * gcc.dg/tree-ssa/ssa-ifcombine-ccmp-4.c: New test case.
+ * gcc.dg/tree-ssa/ssa-ifcombine-ccmp-5.c: New test case.
+ * gcc.dg/tree-ssa/ssa-ifcombine-ccmp-6.c: New test case.
+ * gcc.dg/tree-ssa/phi-opt-9.c: Use a function call to prevent
+ conditional move to be used.
+ * gcc.dg/tree-ssa/ssa-dom-thread-3.c: Remove.
+
+2013-10-29 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/44350
+ * gfortran.dg/blockdata_8.f90: New.
+
+2013-10-29 Oleg Endo <olegendo@gcc.gnu.org>
+
+ PR target/54236
+ * gcc.target/sh/pr54236-2: New.
+ * gcc.target/sh/pr54089-6: Add another rotl special case.
+
+2013-10-29 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/58793
+ * gfortran.dg/unlimited_polymorphic_13.f90: Use real variables
+ to determine sizes of real kinds.
+
+ PR fortran/58858
+ * gfortran.dg/unlimited_polymorphic_14.f90: New test.
+
+2013-10-29 Balaji V. Iyer <balaji.v.iyer@intel.com>
+
+ * c-c++-common/cilk-plus/CK/compound_cilk_spawn.c: New test.
+ * c-c++-common/cilk-plus/CK/concec_cilk_spawn.c: Likewise.
+ * c-c++-common/cilk-plus/CK/fib.c: Likewise.
+ * c-c++-common/cilk-plus/CK/no_args_error.c: Likewise.
+ * c-c++-common/cilk-plus/CK/spawnee_inline.c: Likewise.
+ * c-c++-common/cilk-plus/CK/spawner_inline.c: Likewise.
+ * c-c++-common/cilk-plus/CK/spawning_arg.c: Likewise.
+ * c-c++-common/cilk-plus/CK/steal_check.c: Likewise.
+ * c-c++-common/cilk-plus/CK/test__cilk.c: Likewise.
+ * c-c++-common/cilk-plus/CK/varargs_test.c: Likewise.
+ * c-c++-common/cilk-plus/CK/sync_wo_spawn.c: Likewise.
+ * c-c++-common/cilk-plus/CK/invalid_spawn.c: Likewise.
+ * c-c++-common/cilk-plus/CK/spawn_in_return.c: Likewise.
+ * c-c++-common/cilk-plus/CK/fib_init_expr_xy.c: Likewise.
+ * c-c++-common/cilk-plus/CK/fib_no_sync.c: Likewise.
+ * c-c++-common/cilk-plus/CK/fib_no_return.c: Likewise.
+ * gcc.dg/cilk-plus/cilk-plus.exp: Added support to run Cilk Keywords
+ test stored in c-c++-common. Also, added the Cilk runtime's library
+ to the ld_library_path.
+
+2013-10-29 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58888
+ * g++.dg/cpp0x/auto40.C: New.
+ * g++.dg/other/warning1.C: Adjust.
+
+2013-10-29 Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/torture/restrict-2.c: New testcase.
+ * gcc.dg/torture/restrict-3.c: Likewise.
+ * gcc.dg/torture/restrict-4.c: Likewise.
+ * gcc.dg/torture/restrict-5.c: Likewise.
+
+2013-10-29 Marc Glisse <marc.glisse@inria.fr>
+
+ PR tree-optimization/19831
+ * gcc.dg/tree-ssa/alias-25.c: New file.
+
+2013-10-29 Richard Biener <rguenther@suse.de>
+
+ * g++.dg/vect/slp-pr56812.cc: Adjust with respect to -fvect-cost-model
+ changes.
+ * gcc.dg/vect/bb-slp-32.c: Likewise.
+ * gcc.dg/vect/costmodel/i386/i386-costmodel-vect.exp: Likewise.
+ * gcc.dg/vect/costmodel/ppc/ppc-costmodel-vect.exp: Likewise.
+ * gcc.dg/vect/costmodel/spu/spu-costmodel-vect.exp: Likewise.
+ * gcc.dg/vect/costmodel/x86_64/x86_64-costmodel-vect.exp: Likewise.
+ * gcc.target/powerpc/crypto-builtin-1.c: Likewise.
+ * gcc.target/powerpc/p8vector-builtin-1.c: Likewise.
+ * gcc.target/powerpc/p8vector-builtin-2.c: Likewise.
+ * gcc.target/powerpc/p8vector-builtin-3.c: Likewise.
+ * gcc.target/powerpc/p8vector-builtin-4.c: Likewise.
+ * gcc.target/powerpc/p8vector-builtin-5.c: Likewise.
+ * gcc.target/powerpc/p8vector-vectorize-1.c: Likewise.
+ * gcc.target/powerpc/p8vector-vectorize-2.c: Likewise.
+ * gcc.target/powerpc/p8vector-vectorize-3.c: Likewise.
+ * gcc.target/powerpc/p8vector-vectorize-4.c: Likewise.
+ * gcc.target/powerpc/p8vector-vectorize-5.c: Likewise.
+ * gfortran.dg/vect/vect.exp: Likewise.
+
+2013-10-28 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * gcc.dg/vmx/gcc-bug-i.c: Add little endian variant.
+ * gcc.dg/vmx/eg-5.c: Likewise.
+
+2013-10-28 Claudiu Zissulescu <claziss@synopsys.com>
+ Joern Rennecke <joern.rennecke@embecosm.com>
+
+ * gcc.target/arc/jump-around-jump.c: New test.
+
+2013-10-27 Tom de Vries <tom@codesourcery.com>
+
+ * gcc.target/arm/require-pic-register-loc.c: New test.
+
+2013-10-27 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/58679
+ * gcc.target/i386/pr58679-1.c: New test.
+ * gcc.target/i386/pr58679-2.c: Ditto.
+
+2013-10-27 Tobias Burnus <burnus@net-b.de>
+
+ PR other/33426
+ * gcc.dg/vect/vect-ivdep-2.c: New.
+
+2013-10-26 Oleg Endo <olegendo@gcc.gnu.org>
+
+ PR target/52483
+ * gcc.target/sh/pr52483-1.c: Add tests for memory stores.
+ * gcc.target/sh/pr52483-2.c: Likewise.
+ * gcc.target/sh/pr52483-3.c: Likewise.
+ * gcc.target/sh/pr52483-4.c: Likewise.
+
+2013-10-26 Jeff Law <law@redhat.com>
+
+ * g++.dg/torture/pr49309.C: Removed.
+ * gcc.dg/dfp/pr35739.c: Removed.
+
+2013-10-25 Vladimir Makarov <vmakarov@redhat.com>
+
+ PR rtl-optimization/58759
+ * gcc.target/i386/pr58759.c: New.
+
+2013-10-25 Tobias Burnus <burnus@net-b.de>
+
+ * g++.dg/vect/pr33426-ivdep.cc: Use dg-options.
+ * gfortran.dg/vect/vect-do-concurrent-1.f90: Ditto.
+ * testsuite/gcc.dg/vect/vect-ivdep-1.c: Ditto.
+
+2013-10-25 Yufeng Zhang <yufeng.zhang@arm.com>
+
+ * gcc.dg/wmul-1.c: New test.
+
+2013-10-25 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58878
+ * g++.dg/template/pr58878.C: New.
+
+2013-10-25 Marc Glisse <marc.glisse@inria.fr>
+
+ * gcc.dg/tree-ssa/alias-23.c: New file.
+
+2013-10-25 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/58626
+ * gcc.dg/torture/pr58626.c: New testcase.
+
+2013-10-25 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/54812
+ * g++.dg/cpp0x/defaulted47.C: New.
+
+2013-10-25 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc.c-torture/execute/pr58831.c: New test.
+
+2013-10-25 Nick Clifton <nickc@redhat.com>
+
+ * c-c++-common/pr57793.c: Add expected error messages for
+ targets with small integers.
+ * gcc.dg/c99-stdint-1.c: Only run on 32-bit plus targets.
+ * gcc.dg/c99-stdint-2.c: Likewise.
+ * gcc.dg/cdce1.c: Likewise.
+ * gcc.dg/fold-overflow-1.c: Likewise.
+ * gcc.dg/utf-cvt.c: Likewise.
+ * gcc.dg/ftrapv-1.c: Only run on targets that support trapping
+ arithmetic.
+ * gcc.dg/ftrapv-2.c: Likewise.
+ * gcc.dg/pr30286.c: Likewise.
+ * gcc.dg/pr19340.c: Only run on targets that support scheduling.
+ * lib/target-supports.exp (check_effective_target_trapping): New
+ proc. Returns true if the target supports trapping arithmetic.
+
+2013-10-25 Tobias Burnus <burnus@net-b.de>
+
+ * g++.dg/parse/ivdep.C: New.
+ * g++.dg/vect/pr33426-ivdep.cc: New.
+
+2013-10-24 Richard Henderson <rth@redhat.com>
+
+ PR rtl/58542
+ * gcc.dg/atomic-store-6.c: New.
+
+2013-10-24 Ian Lance Taylor <iant@google.com>
+
+ * go.test/go-test.exp (errchk): Combine quoted strings in comments.
+
+2013-10-24 Cong Hou <congh@google.com>
+
+ * gcc.c-torture/execute/20030125-1.c: Update.
+
+2013-10-24 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/44646
+ * gfortran.dg/vect/vect-do-concurrent-1.f90: New.
+
+2013-10-24 Dehao Chen <dehao@google.com>
+
+ * g++.dg/opt/devirt3.C: New test.
+
+2013-08-24 Tobias Burnus <burnus@net-b.de>
+
+ PR other/33426
+ * testsuite/gcc.dg/ivdep.c: New.
+ * testsuite/gcc.dg/vect/vect-ivdep-1.c: New.
+
+2013-10-24 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * gcc.target/aarch64/c-output-mod-2.c: Fix for -fPIC.
+ * gcc.target/aarch64/c-output-mod-3.c: Likewise.
+
+2013-10-24 Nick Clifton <nickc@redhat.com>
+
+ * gcc.dg/20020312-2.c: No PIC register for RL78 or MSP430.
+
+2013-10-24 Marek Polacek <polacek@redhat.com>
+
+ PR c++/58705
+ * g++.dg/parse/pr58705.C: New test.
+
+2013-10-24 Marek Polacek <polacek@redhat.com>
+
+ * gcc.dg/c11-align-5.c: Add more testing.
+
+2013-10-23 Pat Haugen <pthaugen@us.ibm.com>
+
+ * gcc.target/powerpc/direct-move.h: Fix header for executable tests.
+
+2013-10-23 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/58775
+ PR tree-optimization/58791
+ * gcc.dg/guality/pr58791-1.c: New test.
+ * gcc.dg/guality/pr58791-2.c: New test.
+ * gcc.dg/guality/pr58791-3.c: New test.
+ * gcc.dg/guality/pr58791-4.c: New test.
+ * gcc.dg/guality/pr58791-5.c: New test.
+ * gcc.c-torture/compile/pr58775.c: New test.
+ * gcc.dg/tree-ssa/reassoc-28.c: Don't scan reassoc1 dump.
+
+2013-10-23 Tom de Vries <tom@codesourcery.com>
+
+ PR tree-optimization/58805
+ * gcc.dg/pr58805.c: New test.
+
+2013-10-23 Jakub Jelinek <jakub@redhat.com>
+
+ * gcc.target/i386/vect-div-1.c: New test.
+
+ * gcc.dg/vect/pr58508.c: Remove dg-options.
+
+2013-10-23 Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/torture/pr58830.c: New testcase.
+
+2013-10-23 Edward Smith-Rowland <3dw4rd@verizon.net>
+
+ Implement C++14 [[deprecated]] modulo [[gnu::deprecated]] bugs.
+ * g++.dg/cpp1y/attr-deprecated.C: New.
+ * g++.dg/cpp1y/attr-deprecated-neg.C: New.
+
+2013-10-23 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/58793
+ * gfortran.dg/assumed_type_8.f90: New.
+
+2013-10-22 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/58779
+ * gcc.target/i386/pr30315.c: Remove MINUSCC, DECCC, MINUSCCONLY
+ and MINUSCCZEXT defines. Update scan-assembler dg directive.
+ * gcc.dg/torture/pr58779.c: New test.
+
+2013-10-22 Steve Ellcey <sellcey@mips.com>
+
+ * gcc.target/mips/nor.c: New.
+
+2013-10-22 Bill Schmidt <wschmidt@vnet.ibm.com>
+
+ * gcc.target/powerpc/altivec-perm-1.c: Move the two vector pack
+ tests into...
+ * gcc.target/powerpc/altivec-perm-3.c: ...this new test, which is
+ restricted to big-endian targets.
+
+2013-10-22 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran 57893
+ * gfortran.dg/unlimited_polymorphic_13.f90 : New test.
+
+2013-10-21 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/58803
+ * gfortran.dg/proc_ptr_comp_38.f90: New.
+
+2013-10-21 Marek Polacek <polacek@redhat.com>
+
+ PR middle-end/58809
+ * gcc.dg/gomp/pr58809.c: New test.
+
+2013-10-21 Vidya Praveen <vidyapraveen@arm.com>
+
+ * gcc.dg/20050922-1.c: Remove stdlib.h and declare abort().
+ * gcc.dg/20050922-1.c: Remove stdlib.h and declare abort() and exit().
+
+2013-10-21 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/58794
+ * c-c++-common/torture/pr58794-1.c: New testcase.
+ * c-c++-common/torture/pr58794-2.c: Likewise.
+
+2013-10-21 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/58742
+ * c-c++-common/fold-divmul-1.c: New testcase.
+
+2013-10-21 Michael Zolotukhin <michael.v.zolotukhin@gmail.com>
+
+ * gcc.target/i386/memset-vector_loop-1.c: New test.
+ * gcc.target/i386/memset-vector_loop-2.c: New test.
+
+2013-10-21 Diego Novillo <dnovillo@google.com>
+
+ * g++.dg/plugin/selfassign.c: Include tree.h.
+ * gcc.dg/plugin/finish_unit_plugin.c: Likewise.
+ * gcc.dg/plugin/ggcplug.c: Likewise.
+ * gcc.dg/plugin/one_time_plugin.c: Likewise.
+ * gcc.dg/plugin/selfassign.c: Likewise.
+ * gcc.dg/plugin/start_unit_plugin.c: Likewise.
+
+2013-10-20 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * gcc.target/mips/mips-ps-5.c: Add alignment attributes.
+ * gcc.target/mips/mips-ps-7.c: Likewise.
+
+2013-10-20 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * gcc.target/mips/bswap-1.c, gcc.target/mips/bswap-2.c,
+ gcc.target/mips/bswap-3.c, gcc.target/mips/bswap-4.c,
+ gcc.target/mips/bswap-5.c, gcc.target/mips/bswap-6.c: New tests.
+
+2013-10-19 John David Anglin <danglin@gcc.gnu.org>
+
+ * c-c++-common/opaque-vector.c: Skip long double test on hppa.
+
+ PR testsuite/58645
+ * gnat.dg/specs/linker_alias.ads: Skip on hppa*-*-hpux*.
+
+2013-10-19 Mike Stump <mikestump@comcast.net>
+
+ * g++.dg/lto/lto.exp: Add support for C/C++ mix language testing.
+
+ * gcc.dg/lto/pr54625-1_0.c: Move from here...
+ * g++.dg/lto/pr54625-1_0.c: ... to here.
+ * gcc.dg/lto/pr54625-1_1.C: Likewise.
+ * g++.dg/lto/pr54625-1_1.C: Likewise.
+ * gcc.dg/lto/pr54625-2_0.c: Likewise.
+ * g++.dg/lto/pr54625-2_0.c: Likewise.
+ * gcc.dg/lto/pr54625-2_1.C: Likewise.
+ * g++.dg/lto/pr54625-2_1.C: Likewise.
+
+2013-10-19 Oleg Endo <olegendo@gcc.gnu.org>
+
+ * gcc.target/sh/pr54089-3.c: Fix test for load of constant 31.
+
+2013-10-18 Cong Hou <congh@google.com>
+
+ * gcc.dg/vect/pr58508.c: New test.
+
+2013-10-18 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58466
+ * g++.dg/cpp0x/variadic145.C: New.
+
+2013-10-18 Andrew MacLeod <amacleod@redhat.com>
+
+ * g++.dg/plugin/header_plugin.c: Don't include tree-flow.h.
+
+2013-10-18 Hans-Peter Nilsson <hp@axis.com>
+
+ * gcc.dg/tree-ssa/gen-vect-11.c: Use dynamic vector cost model.
+ * gcc.dg/tree-ssa/gen-vect-11a.c: Likewise.
+ * gcc.dg/tree-ssa/gen-vect-2.c: Likewise.
+ * gcc.dg/tree-ssa/gen-vect-25.c: Likewise.
+
+2013-10-17 Charles Bayis <charles.baylis@linaro.org>
+
+ * gcc.dg/builtin-apply2.c: Skip test on arm hardfloat ABI targets.
+ * gcc.dg/tls/pr42894.c: Remove dg-options for arm*-*-* targets.
+ * gcc.target/arm/thumb-ltu.c: Remove dg-skip-if and require
+ effective target arm_thumb1_ok.
+ * lib/target-supports.exp
+ (check_effective_target_arm_fp16_ok_nocache): Don't force
+ -mfloat-abi=soft when building for hardfloat target.
+
+2013-10-17 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ PR target/58673
+ * gcc.target/powerpc/pr58673-1.c: New file to test whether
+ -mquad-word + -mno-vsx-timode causes errors.
+ * gcc.target/powerpc/pr58673-2.c: Likewise.
+
+2013-10-17 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58596
+ * g++.dg/cpp0x/lambda/lambda-nsdmi5.C: New
+
+2013-10-17 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * gcc.target/aarch64/c-output-template.c: New testcase.
+ * gcc.target/aarch64/c-output-template-2.c: Likewise.
+ * gcc.target/aarch64/c-output-template-3.c: Likewise.
+
+2013-10-17 Michael Hudson-Doyle <michael.hudson@linaro.org>
+
+ * gcc/testsuite/lib/target-supports.exp
+ (check_effective_target_sync_long_long): AArch64 supports
+ atomic operations on "long long".
+ (check_effective_target_sync_long_long_runtime): AArch64 can
+ execute atomic operations on "long long".
+
+2013-10-17 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/58143
+ * gcc.dg/torture/pr58143-1.c: New testcase.
+ * gcc.dg/torture/pr58143-2.c: Likewise.
+ * gcc.dg/torture/pr58143-3.c: Likewise.
+
+2013-10-17 Marek Polacek <polacek@redhat.com>
+
+ PR c/58267
+ * gcc.dg/c1x-align-5.c: New test.
+
+2013-10-16 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/58652
+ * gfortran.dg/unlimited_polymorphic_12.f90: New.
+
+2013-10-16 Thomas Schwinge <thomas@codesourcery.com>
+
+ * c-c++-common/cpp/openmp-define-1.c: Move
+ dg-require-effective-target fopenmp after dg-do directive.
+ * c-c++-common/cpp/openmp-define-2.c: Likewise.
+ * gfortran.dg/openmp-define-1.f90: Likewise.
+ * gfortran.dg/openmp-define-2.f90: Likewise.
+ * gfortran.dg/openmp-define-3.f90: Likewise.
+
+2013-10-16 Paulo Matos <pmatos@broadcom.com>
+
+ * gcc.dg/tree-prof/tree-prof.exp: Fix comment.
+
+2013-10-15 Sriraman Tallam <tmsriram@google.com>
+
+ PR target/57756
+ * gcc.target/i386/pr57756.c: New test.
+ * gcc.target/i386/pr57756_2.c: New test.
+
+2013-10-15 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * gcc.dg/torture/builtin-self.c: New file.
+
+2013-10-15 Zhenqiang Chen <zhenqiang.chen@arm.com>
+
+ * gcc.dg/tree-ssa/reassoc-32.c: New test case.
+ * gcc.dg/tree-ssa/reassoc-33.c: New test case.
+ * gcc.dg/tree-ssa/reassoc-34.c: New test case.
+ * gcc.dg/tree-ssa/reassoc-35.c: New test case.
+ * gcc.dg/tree-ssa/reassoc-36.c: New test case.
+
+2013-10-15 Cong Hou <congh@google.com>
+
+ * gcc.dg/vect/vect-reduc-pattern-3.c: New test.
+
+2013-10-15 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58707
+ * g++.dg/cpp0x/pr58707.C: New.
+
+2013-10-15 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * c-c++-common/cpp/openmp-define-3.c: Move effective target check
+ after other directives.
+
+2013-10-15 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/58652
+ * gfortran.dg/unlimited_polymorphic_11.f90: New.
+
+2013-10-14 Ian Lance Taylor <iant@google.com>
+
+ * go.test/go-test.exp (go-find-packages): New proc.
+ (go-gc-tests): Skip stress and safe tests. Skip *.dir
+ subdirectories. Do simple +build line matching. Handle run with
+ arguments. Handle errorcheckdir and rundircmpout. Use packages
+ for rundir. Remove special handling for bug191 and dwarf.
+
+2013-10-14 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/58658
+ * gfortran.dg/unlimited_polymorphic_10.f90: New.
+
+2013-10-14 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * gcc.dg/torture/pr58670.c (ASM_STR) [__i386__ || __x86_64__]:
+ Use btsl.
+
+2013-10-14 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/specs/opt1.ads: New test.
+
+2013-10-14 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/58640
+ * gcc.c-torture/execute/pr58640-2.c: New testcase.
+
+2013-10-13 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/uninit_array.ad[sn]: New test.
+ * gnat.dg/uninit_array_pkg.ads: New helper.
+
+2013-10-13 Richard Biener <rguenther@suse.de>
+
+ * gcc.c-torture/execute/pr58662.c: New test.
+
+2013-10-12 Oleg Endo <olegendo@gcc.gnu.org>
+
+ PR target/51244
+ * gcc.dg/torture/p51244-21.c: New.
+ * gcc.target/sh/pr51244-20.c: New.
+ * gcc.target/sh/pr51244-20-sh2a.c: New.
+
+2013-10-12 Arnaud Charlet <charlet@adacore.com>
+
+ * gnat.dg/specs/linker_section.ads: Update test.
+
+2013-10-12 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/58690
+ * gcc.target/i386/pr58690.c: New test
+
+2013-10-12 Alexander Monakov <amonakov@ispras.ru>
+
+ * gcc.target/i386/builtin-ucmp.c: New test.
+
+2013-10-11 Brooks Moses <bmoses@google.com>
+
+ * g++.dg/ext/altivec-7.C: Check for standard vector-type name mangling.
+
+2013-10-11 Jeff Law <law@redhat.com>
+
+ * gcc.c-torture/execute/pr58640.c: New test.
+
+2013-10-11 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58633
+ * g++.dg/cpp0x/decltype57.C: New.
+
+2013-10-11 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/31671
+ * g++.dg/template/nontype26.C: New.
+
+2013-10-11 Thomas Schwinge <thomas@codesourcery.com>
+
+ * c-c++-common/cpp/openmp-define-1.c: New file.
+ * c-c++-common/cpp/openmp-define-2.c: Likewise.
+ * c-c++-common/cpp/openmp-define-3.c: Likewise.
+ * gfortran.dg/openmp-define-1.f90: Likewise.
+ * gfortran.dg/openmp-define-2.f90: Likewise.
+ * gfortran.dg/openmp-define-3.f90: Likewise.
+
+ * g++.dg/gomp/gomp.exp: Recurse into subdirectories when looking
+ for test source files.
+ * gcc.dg/gomp/gomp.exp: Likewise.
+ * gcc.dg/gomp/appendix-a/a.35.1.c: Expect error.
+ * gcc.dg/gomp/appendix-a/a.35.3.c: Likewise.
+ * gcc.dg/gomp/appendix-a/a.35.4.c: Likewise.
+ * gcc.dg/gomp/appendix-a/a.35.5.c: Likewise.
+ * gcc.dg/gomp/appendix-a/a.35.6.c: Likewise.
+
+2013-10-11 Jakub Jelinek <jakub@redhat.com>
+
+ * c-c++-common/gomp/atomic-15.c: Adjust for C diagnostics.
+ Remove error test that is now valid in OpenMP 4.0.
+ * c-c++-common/gomp/atomic-16.c: New test.
+ * c-c++-common/gomp/cancel-1.c: New test.
+ * c-c++-common/gomp/depend-1.c: New test.
+ * c-c++-common/gomp/depend-2.c: New test.
+ * c-c++-common/gomp/map-1.c: New test.
+ * c-c++-common/gomp/pr58472.c: New test.
+ * c-c++-common/gomp/sections1.c: New test.
+ * c-c++-common/gomp/simd1.c: New test.
+ * c-c++-common/gomp/simd2.c: New test.
+ * c-c++-common/gomp/simd3.c: New test.
+ * c-c++-common/gomp/simd4.c: New test.
+ * c-c++-common/gomp/simd5.c: New test.
+ * c-c++-common/gomp/single1.c: New test.
+ * g++.dg/gomp/block-0.C: Adjust for stricter #pragma omp sections
+ parser.
+ * g++.dg/gomp/block-3.C: Likewise.
+ * g++.dg/gomp/clause-3.C: Adjust error messages.
+ * g++.dg/gomp/declare-simd-1.C: New test.
+ * g++.dg/gomp/declare-simd-2.C: New test.
+ * g++.dg/gomp/depend-1.C: New test.
+ * g++.dg/gomp/depend-2.C: New test.
+ * g++.dg/gomp/target-1.C: New test.
+ * g++.dg/gomp/target-2.C: New test.
+ * g++.dg/gomp/taskgroup-1.C: New test.
+ * g++.dg/gomp/teams-1.C: New test.
+ * g++.dg/gomp/udr-1.C: New test.
+ * g++.dg/gomp/udr-2.C: New test.
+ * g++.dg/gomp/udr-3.C: New test.
+ * g++.dg/gomp/udr-4.C: New test.
+ * g++.dg/gomp/udr-5.C: New test.
+ * g++.dg/gomp/udr-6.C: New test.
+ * gcc.dg/autopar/outer-1.c: Expect 4 instead of 5 loopfn matches.
+ * gcc.dg/autopar/outer-2.c: Likewise.
+ * gcc.dg/autopar/outer-3.c: Likewise.
+ * gcc.dg/autopar/outer-4.c: Likewise.
+ * gcc.dg/autopar/outer-5.c: Likewise.
+ * gcc.dg/autopar/outer-6.c: Likewise.
+ * gcc.dg/autopar/parallelization-1.c: Likewise.
+ * gcc.dg/gomp/block-3.c: Adjust for stricter #pragma omp sections
+ parser.
+ * gcc.dg/gomp/clause-1.c: Adjust error messages.
+ * gcc.dg/gomp/combined-1.c: Look for GOMP_parallel_loop_runtime
+ instead of GOMP_parallel_loop_runtime_start.
+ * gcc.dg/gomp/declare-simd-1.c: New test.
+ * gcc.dg/gomp/declare-simd-2.c: New test.
+ * gcc.dg/gomp/nesting-1.c: Adjust for stricter #pragma omp sections
+ parser. Add further #pragma omp sections nesting tests.
+ * gcc.dg/gomp/target-1.c: New test.
+ * gcc.dg/gomp/target-2.c: New test.
+ * gcc.dg/gomp/taskgroup-1.c: New test.
+ * gcc.dg/gomp/teams-1.c: New test.
+ * gcc.dg/gomp/udr-1.c: New test.
+ * gcc.dg/gomp/udr-2.c: New test.
+ * gcc.dg/gomp/udr-3.c: New test.
+ * gcc.dg/gomp/udr-4.c: New test.
+ * gfortran.dg/gomp/appendix-a/a.35.5.f90: Add dg-error.
+
+2013-10-10 Jan Hubicka <jh@suse.cz>
+
+ * gcc.target/i386/avx256-unaligned-store-3.c: Update template for
+ tuning change.
+ * gcc.target/i386/avx256-unaligned-store-1.c: Likewise.
+ * gcc.target/i386/pr49168-1.c: Likewise.
+ * gcc.target/i386/pr49002-2.c: Likewise.
+
+2013-10-10 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/58670
+ * gcc.dg/torture/pr58670.c: New test.
+
+2013-10-09 Zhenqiang Chen <zhenqiang.chen@arm.com>
+
+ * gcc.dg/tree-ssa/phi-opt-11.c: New test.
+
+2013-10-09 Marek Polacek <polacek@redhat.com>
+
+ PR c++/58635
+ * g++.dg/tm/pr58635-1.C: New test.
+ * g++.dg/tm/pr58635-2.C: New test.
+
+2013-10-09 Jakub Jelinek <jakub@redhat.com>
+
+ * gcc.dg/vect/bb-slp-31.c: Add cleanup-tree-dump.
+
+2013-10-09 Marc Glisse <marc.glisse@inria.fr>
+
+ PR tree-optimization/20318
+ * c-c++-common/pr20318.c: New file.
+ * gcc.dg/tree-ssa/pr20318.c: New file.
+
+2013-10-09 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc.c-torture/execute/pr58570.c: New test.
+
+2013-10-09 Alex Velenko <Alex.Velenko@arm.com>
+
+ * gcc.target/aarch64/vclz.c: New testcase.
+
+2013-10-09 Alex Velenko <Alex.Velenko@arm.com>
+
+ * gcc.target/aarch64/vadd_f64.c: New testcase.
+ * gcc.target/aarch64/vsub_f64.c: New testcase.
+
+2013-10-09 Alex Velenko <Alex.Velenko@arm.com>
+
+ * gcc.target/aarch64/vdiv_f.c: New testcase.
+
+2013-10-09 Alex Velenko <Alex.Velenko@arm.com>
+
+ * gcc.target/aarch64/vneg_f.c: New testcase.
+ * gcc.target/aarch64/vneg_s.c: New testcase.
+
+2013-10-08 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58568
+ * g++.dg/cpp0x/lambda/lambda-ice10.C: New.
+ * g++.old-deja/g++.mike/misc9.C: Adjust.
+
+2013-10-08 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58665
+ Revert:
+ 2013-10-04 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58448
+ * g++.dg/template/crash117.C: New.
+
+2013-10-08 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
+
+ * gcc.target/s390/htm-nofloat-2.c: Add -mzarch to asm options.
+
+2013-10-08 Marc Glisse <marc.glisse@inria.fr>
+
+ PR tree-optimization/58480
+ * gcc.dg/tree-ssa/pr58480.c: New file.
+
+2013-10-07 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * gcc.target/powerpc/pr43154.c: Skip for ppc64 little endian.
+ * gcc.target/powerpc/fusion.c: Likewise.
+
+2013-10-07 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
+
+ * gcc.target/s390/htm-nofloat-2.c: New testcase.
+
+2013-10-07 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
+
+ * gcc.target/s390/htm-1.c: Add more tests to cover different
+ operand types.
+
+2013-10-06 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58126
+ * g++.dg/init/uninitialized1.C: New.
+
+2013-10-06 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/56060
+ * g++.dg/cpp0x/variadic144.C: New.
+
+2013-10-04 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58560
+ * g++.dg/cpp0x/auto39.C: New.
+
+2013-10-04 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58503
+ * g++.dg/cpp0x/range-for26.C: New.
+ * g++.dg/cpp0x/range-for27.C: Likewise.
+
+2013-10-04 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58448
+ * g++.dg/template/crash117.C: New.
+
+2013-10-04 Marc Glisse <marc.glisse@inria.fr>
+
+ PR c++/19476
+ * g++.dg/tree-ssa/pr19476-5.C: New file.
+ * g++.dg/tree-ssa/pr19476-1.C: Mention pr19476-5.C.
+
+2013-10-04 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58584
+ * g++.dg/cpp0x/gen-attrs-55.C: New.
+
+2013-10-03 Easwaran Raman <eraman@google.com>
+
+ PR c++/33911
+ * g++.dg/ext/attribute47.C: New.
+
+2013-10-03 Rong Xu <xur@google.com>
+
+ * gcc.target/i386/cold-attribute-2.c: Fix the test by using original
+ probability.
+ * gcc.dg/tree-ssa/ipa-split-5.c: Ditto.
+ * gcc.dg/tree-ssa/ipa-split-6.c: Ditto.
+
+2013-10-03 Marek Polacek <polacek@redhat.com>
+
+ PR c++/58510
+ * g++.dg/cpp0x/pr58510.C: New test.
+
+2013-10-03 Marc Glisse <marc.glisse@inria.fr>
+
+ PR c++/19476
+ * g++.dg/tree-ssa/pr19476-1.C: New file.
+ * g++.dg/tree-ssa/pr19476-2.C: Likewise.
+ * g++.dg/tree-ssa/pr19476-3.C: Likewise.
+ * g++.dg/tree-ssa/pr19476-4.C: Likewise.
+
+2013-10-03 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * gcc.target/powerpc/p8vector-fp.c: New test for floating point
+ scalar operations when using -mupper-regs-sf and -mupper-regs-df.
+ * gcc.target/powerpc/ppc-target-1.c: Update tests to allow either
+ VSX scalar operations or the traditional floating point form of
+ the instruction.
+ * gcc.target/powerpc/ppc-target-2.c: Likewise.
+ * gcc.target/powerpc/recip-3.c: Likewise.
+ * gcc.target/powerpc/recip-5.c: Likewise.
+ * gcc.target/powerpc/pr72747.c: Likewise.
+ * gcc.target/powerpc/vsx-builtin-3.c: Likewise.
+
+2013-10-03 Marcus Shawcroft <marcus.shawcroft@arm.com>
+
+ PR target/58460
+ * gcc.target/aarch64/pr58460.c: New file.
+
+2013-10-02 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/58593
+ * gfortran.dg/char_length_19.f90: New.
+
+2013-10-02 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58535
+ * g++.dg/parse/crash65.C: New.
+ * g++.dg/cpp1y/pr58535.C: Likewise.
+
+2013-10-02 Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/tree-ssa/ldist-11.c: Adjust.
+ * gcc.dg/tree-ssa/ldist-17.c: Likewise.
+ * gcc.dg/tree-ssa/ldist-23.c: Likewise.
+ * gcc.dg/tree-ssa/ldist-pr45948.c: Likewise.
+ * gfortran.dg/ldist-pr45199.f: Likewise.
+
+2013-10-02 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58565
+ * g++.dg/parse/crash64.C: New.
+
+2013-10-02 Yufeng Zhang <yufeng.zhang@arm.com>
+
+ * gcc.dg/tree-ssa/slsr-40.c: New test.
+
+2013-10-01 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58563
+ * g++.dg/cpp0x/pr58563.C: New.
+
+2013-10-01 Vidya Praveen <vidyapraveen@arm.com>
+
+ * gcc.target/aarch64/vect_saddl_1.c: New.
+
+2013-10-01 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/58574
+ * gcc.c-torture/execute/pr58574.c: New testcase.
+
+2013-10-01 Kugan Vivekanandarajah <kuganv@linaro.org>
+
+ PR Target/58578
+ * gcc.target/arm/pr58578.c: New test.
+
+2013-10-01 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ PR tree-optimization/58556
+ * gcc.dg/tree-ssa/gen-vect-26.c: Use dynamic vector cost model.
+ * gcc.dg/tree-ssa/gen-vect-28.c: Likewise.
+
+2013-10-01 Nick Clifton <nickc@redhat.com>
+
+ * lib/target-supports.exp (check_effective_target_ptr32plus): Fail
+ for MSP430.
+ * gcc.c-torture/compile/20010327-1.c: Only run the test for
+ ptr32plus targets.
+ * gcc.c-torture/compile/pr41181.c: Likewise.
+ * gcc.c-torture/compile/calls.c: Likewise.
+ * gcc.c-torture/compile/990617-1.c: Likewise.
+ * gcc.c-torture/compile/pr55955.c: Only run the test for
+ int32plus targets.
+ * gcc.c-torture/compile/limits-externdecl.c: Likewise.
+
+2013-10-01 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/58553
+ * gcc.dg/torture/pr58553.c: New testcase.
+
+2013-09-30 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/58564
+ * gcc.c-torture/execute/pr58564.c: New test.
+
+2013-09-30 Teresa Johnson <tejohnson@google.com>
+
+ * testsuite/gcc.dg/tree-ssa/ssa-dom-thread-3.c (expand_one_var):
+ Update for additional dump message.
+
+2013-09-30 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/58554
+ * gcc.dg/torture/pr58554.c: New testcase.
+
+2013-09-30 Simon Cook <simon.cook@embecosm.com>
+ Joern Rennecke <joern.rennecke@embecosm.com>
+
+ * gcc.target/arc/barrel-shifter-1.c: New test.
+ * gcc.target/arc/barrel-shifter-2.c: Likewise.
+ * gcc.target/arc/long-calls.c, gcc.target/arc/mA6.c: Likewise.
+ * gcc.target/arc/mA7.c, gcc.target/arc/mARC600.c: Likewise.
+ * gcc.target/arc/mARC601.c, gcc.target/arc/mARC700.c: Likewise.
+ * gcc.target/arc/mcpu-arc600.c, gcc.target/arc/mcpu-arc601.c: Likewise.
+ * gcc.target/arc/mcpu-arc700.c, gcc.target/arc/mcrc.c: Likewise.
+ * gcc.target/arc/mdpfp.c, gcc.target/arc/mdsp-packa.c: Likewise.
+ * gcc.target/arc/mdvbf.c, gcc.target/arc/mlock.c: Likewise.
+ * gcc.target/arc/mmac-24.c, gcc.target/arc/mmac-d16.c: Likewise.
+ * gcc.target/arc/mno-crc.c, gcc.target/arc/mno-dsp-packa.c: Likewise.
+ * gcc.target/arc/mno-dvbf.c, gcc.target/arc/mno-lock.c: Likewise.
+ * gcc.target/arc/mno-mac-24.c, gcc.target/arc/mno-mac-d16.c: Likewise.
+ * gcc.target/arc/mno-rtsc.c, gcc.target/arc/mno-swape.c: Likewise.
+ * gcc.target/arc/mno-xy.c, gcc.target/arc/mrtsc.c: Likewise.
+ * gcc.target/arc/mspfp.c, gcc.target/arc/mswape.c: Likewise.
+ * gcc.target/arc/mtune-ARC600.c: Likewise.
+ * gcc.target/arc/mtune-ARC601.c: Likewise.
+ * gcc.target/arc/mtune-ARC700-xmac: Likewise.
+ * gcc.target/arc/mtune-ARC700.c: Likewise.
+ * gcc.target/arc/mtune-ARC725D.c: Likewise.
+ * gcc.target/arc/mtune-ARC750D.c: Likewise.
+ * gcc.target/arc/mul64.c, gcc.target/arc/mxy.c: Likewise.
+ * gcc.target/arc/no-dpfp-lrsr.c: Likewise.
+
+2013-09-30 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/58532
+ * g++.dg/torture/pr58552.C: New testcase.
+
+2013-09-27 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * gcc.target/powerpc/p8vector-ldst.c: New test for -mupper-regs-sf
+ and -mupper-regs-df.
+
+2013-09-27 Paulo Matos <pmatos@broadcom.com>
+
+ PR middle-end/58463
+ * gcc.dg/pr58463.c: New test.
+
+2013-09-27 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/58551
+ * c-c++-common/gomp/pr58551.c: New test.
+
+2013-09-27 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/58459
+ * gcc.dg/tree-ssa/ssa-pre-31.c: New testcase.
+
+2013-09-26 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ PR fortran/58113
+ * gfortran.dg/round_4.f90: Check for rounding support.
+
+2013-09-26 James Greenhalgh <james.greenhalgh@arm.com>
+
+ * g++.dg/vect/pr58513.cc (op): Make static.
+
+2013-09-26 Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/tree-ssa/coalesce-2.c: New testcase.
+
+2013-09-26 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/58539
+ * gcc.dg/torture/pr58539.c: New testcase.
+
+2013-09-25 Jeff Law <law@redhat.com>
+
+ * gcc.dg/tree-ssa/ssa-dom-thread-3.c: Update expected output.
+
+2013-09-25 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/58436
+ * gfortran.dg/finalize_21.f90: New.
+
+2013-09-25 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/57697
+ PR fortran/58469
+ * gfortran.dg/defined_assignment_8.f90: New.
+ * gfortran.dg/defined_assignment_9.f90: New.
+
+2013-09-25 Marek Polacek <polacek@redhat.com>
+
+ PR sanitizer/58413
+ * c-c++-common/ubsan/shift-5.c: New test.
+ * c-c++-common/ubsan/shift-6.c: New test.
+ * c-c++-common/ubsan/div-by-zero-5.c: New test.
+ * gcc.dg/ubsan/c-shift-1.c: New test.
+
+2013-09-25 Marek Polacek <polacek@redhat.com>
+
+ PR c++/58516
+ * g++.dg/tm/pr58516.C: New test.
+
+2013-09-24 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * lib/target-supports.exp (check_effective_target_arm_cond_exec):
+ New procedure.
+ * gcc.target/arm/minmax_minus.c: Check for cond_exec target.
+
+2013-09-24 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/58513
+ * g++.dg/vect/pr58513.cc: New testcase.
+
+2013-09-24 Yvan Roux <yvan.roux@linaro.org>
+
+ * gcc.target/arm/atomic-comp-swap-release-acquire.c: Adjust expected
+ output.
+
+2013-09-23 Adam Butcher <adam@jessamine.co.uk>
+
+ PR c++/58500
+ * g++.dg/cpp1y/pr58500.C: New testcase.
+
+2013-09-23 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/opt28.ad[sb]: New test.
+ * gnat.dg/opt28_pkg.ads: New helper.
+
+2013-09-23 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/58464
+ * g++.dg/torture/pr58464.C: New testcase.
+
+2013-09-23 Christian Bruel <christian.bruel@st.com>
+
+ PR target/58475
+ * gcc.target/sh/torture/pr58475.c: New test.
+
+2013-09-23 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/58355
+ * gfortran.dg/extends_15.f90: New.
+
+2013-09-20 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/58481
+ * g++.dg/cpp0x/lambda/lambda-this17.C: New.
+
+2013-09-20 Jan-Benedict Glaw <jbglaw@lug-owl.de>
+
+ PR target/56875
+ * gcc.target/vax/vax.exp: New.
+ * gcc.target/vax/pr56875.c: Ditto.
+
+2013-09-20 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/58484
+ * gfortran.dg/pr58484.f: New testcase.
+
+2013-09-20 Jeff Law <law@redhat.com>
+
+ * gcc.dg/tree-ssa/ssa-dom-thread-3.c: Add missing dg-final clause.
+
+2013-09-20 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ PR middle-end/57748
+ * gcc.dg/torture/pr57748-1.c: New test.
+ * gcc.dg/torture/pr57748-2.c: New test.
+
+2013-09-20 Marek Polacek <polacek@redhat.com>
+
+ PR sanitizer/58413
+ * c-c++-common/ubsan/shift-4.c: New test.
+
+2013-09-20 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/58453
+ * gcc.dg/tree-ssa/ldist-23.c: New testcase.
+
2013-09-20 Janus Weil <janus@gcc.gnu.org>
PR fortran/58099
@@ -48,7 +1827,7 @@
2013-09-18 Eric Botcazou <ebotcazou@adacore.com>
- * gnat.dg/array_bounds_test2.adb: New test.
+ * gnat.dg/array_bounds_test2.adb: New test.
2013-09-18 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
@@ -66,7 +1845,7 @@
2013-09-17 Cong Hou <congh@google.com>
- * gcc.dg/vect/vect-reduc-dot-s16c.c: Add a test case with dot product
+ * gcc.dg/vect/vect-reduc-dot-s16c.c: Add a test case with dot product
on two arrays with short and int types. This should not be recognized
as a dot product pattern.
@@ -93,8 +1872,7 @@
2013-09-17 Nick Clifton <nickc@redhat.com>
* lib/target-supports.exp (check_effective_target_trampolines):
- Add MSP430 to the list of targets that do not support
- trampolines.
+ Add MSP430 to the list of targets that do not support trampolines.
(check_profiling_available): Add MSP430 to the list of targets
that do not support profiling.
(check_effective_target_tls_runtime): Add MSP430 to the list of
@@ -178,7 +1956,7 @@
2013-09-13 Kai Tietz <ktietz@redhat.com>
- gcc.target/i386/pr57848.c: New file.
+ * gcc.target/i386/pr57848.c: New file.
2013-09-13 Christian Bruel <christian.bruel@st.com>
@@ -196,8 +1974,7 @@
2013-09-12 Paolo Carlini <paolo.carlini@oracle.com>
- * g++.dg/template/pseudodtor2.C: Add column number to dg-error
- strings.
+ * g++.dg/template/pseudodtor2.C: Add column number to dg-error strings.
* g++.dg/template/pseudodtor3.C: Likewise.
2013-09-12 Richard Biener <rguenther@suse.de>
@@ -1206,6 +2983,7 @@
2013-08-08 Richard Sandiford <rdsandiford@googlemail.com>
+ PR rtl-optimization/58079
* gcc.dg/torture/pr58079.c: New test.
2013-08-07 Eric Botcazou <ebotcazou@adacore.com>
@@ -5236,7 +7014,7 @@
* gcc.target/arm/vselvsdf.c: Likewise.
* gcc.target/arm/vselvssf.c: Likewise.
-2013-03-25 Kyrylo Tkachov <kyrylo.tkachov at arm.com>
+2013-03-25 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
* gcc.target/aarch64/atomic-comp-swap-release-acquire.c: Move test
body from here...
@@ -6124,7 +7902,7 @@
PR rtl-optimization/56151
* gcc.target/i386/pr56151.c: New test.
-2013-02-11 Sriraman Tallam <tmsriramgoogle.com>
+2013-02-11 Sriraman Tallam <tmsriram@google.com>
* g++.dg/ext/mv12.C: New test.
* g++.dg/ext/mv12.h: New file.
@@ -6305,7 +8083,7 @@
PR target/54131
* gfortran.dg/pr54131.f: New test.
-2013-02-06 Paul Thomas <pault@gcc.gnu.org>
+2013-02-06 Paul Thomas <pault@gcc.gnu.org>
PR fortran/55789
* gfortran.dg/array_constructor_41.f90: New test.
diff --git a/gcc/testsuite/ChangeLog-2009 b/gcc/testsuite/ChangeLog-2009
index a4614a03ec7..4c14e744fab 100644
--- a/gcc/testsuite/ChangeLog-2009
+++ b/gcc/testsuite/ChangeLog-2009
@@ -4683,7 +4683,7 @@
* gcc.c-torture/compile/limits-fndefn.c: Add dg-timeout-factor.
-2009-08-25 Ville Voutilainen <ville.voutilainen@gmail.com>
+2009-08-25 Ville Voutilainen <ville.voutilainen@gmail.com>
* g++.dg/cpp0x/alignof.C: New. Tests that the alignof
keyword works in the same manner as __alignof.
diff --git a/gcc/testsuite/ChangeLog-2012 b/gcc/testsuite/ChangeLog-2012
index 90e08399a79..83c15e1f4a6 100644
--- a/gcc/testsuite/ChangeLog-2012
+++ b/gcc/testsuite/ChangeLog-2012
@@ -5983,7 +5983,7 @@
PR c++/52637
* g++.dg/debug/localclass1.C: New.
-2012-06-16 Ville Voutilainen <ville.voutilainen@gmail.com>
+2012-06-16 Ville Voutilainen <ville.voutilainen@gmail.com>
* g++.dg/cpp0x/override4.C: New.
diff --git a/gcc/testsuite/c-c++-common/asan/pr59029.c b/gcc/testsuite/c-c++-common/asan/pr59029.c
new file mode 100644
index 00000000000..a1319b2720e
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/pr59029.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+
+int
+foo ()
+{
+ return __sync_fetch_and_add ((int *) 0, 1);
+}
diff --git a/gcc/testsuite/c-c++-common/asan/stack-overflow-1.c b/gcc/testsuite/c-c++-common/asan/stack-overflow-1.c
index 5f563561935..c7176509710 100644
--- a/gcc/testsuite/c-c++-common/asan/stack-overflow-1.c
+++ b/gcc/testsuite/c-c++-common/asan/stack-overflow-1.c
@@ -19,4 +19,5 @@ int main() {
/* { dg-output "READ of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output " #0 0x\[0-9a-f\]+ (in _*main (\[^\n\r]*stack-overflow-1.c:16|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]*Address 0x\[0-9a-f\]+ is\[^\n\r]*frame <main>" } */
+/* { dg-output "\[^\n\r]*Address 0x\[0-9a-f\]+ is located in stack of thread T0.*(\n|\r\n|\r)" */
+/* { dg-output "\[^\n\r]*in main.*stack-overflow-1.c.*(\n|\r\n|\r)" */
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/CK/compound_cilk_spawn.c b/gcc/testsuite/c-c++-common/cilk-plus/CK/compound_cilk_spawn.c
new file mode 100644
index 00000000000..5e687bd0a0c
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/compound_cilk_spawn.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-fcilkplus" } */
+
+/* <feature>
+ A program is considered ill formed if the _Cilk_spawn form of this
+ expression appears other than in one of the following contexts:
+ as the entire body of an expression statement,
+ as the entire right hand side of an assignment expression that is the entire
+ body of an expression statement, or as the entire initializer-clause in a
+ simple declaration.
+ </feature>
+*/
+
+int spawn_func (int arg)
+{
+ return arg + 1;
+}
+
+int check()
+{
+ int z;
+ z = 23, _Cilk_spawn spawn_func (3), 3424; /* { dg-error "spawned function call cannot be part of a comma expression" } */
+ 23, spawn_func (5), _Cilk_spawn spawn_func (3); /* { dg-error "spawned function call cannot be part of a comma expression" } */
+ _Cilk_spawn spawn_func (0), _Cilk_spawn spawn_func (3), 3, spawn_func (0); /* { dg-error "spawned function call cannot be part of a comma expression" } */
+ return 23;
+}
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/CK/concec_cilk_spawn.c b/gcc/testsuite/c-c++-common/cilk-plus/CK/concec_cilk_spawn.c
new file mode 100644
index 00000000000..b93c9626d18
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/concec_cilk_spawn.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-fcilkplus" } */
+
+/* <feature> Consecutive _Cilk_spawn tokens are not permitted
+ </feature>
+*/
+
+int spawn_func (int arg)
+{
+ return arg + 1;
+}
+
+void func ()
+{
+ int a;
+ a = _Cilk_spawn _Cilk_spawn spawn_func (4); /* { dg-error "consecutive" } */
+ a = _Cilk_spawn _Cilk_spawn _Cilk_spawn spawn_func (4); /* { dg-error "consecutive" } */
+ a = _Cilk_spawn _Cilk_spawn _Cilk_spawn _Cilk_spawn spawn_func (4); /* { dg-error "consecutive" } */
+ return;
+}
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/CK/fib.c b/gcc/testsuite/c-c++-common/cilk-plus/CK/fib.c
new file mode 100644
index 00000000000..a8849fb9e6c
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/fib.c
@@ -0,0 +1,54 @@
+/* { dg-options "-fcilkplus" } */
+/* { dg-do run { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-fcilkplus -lcilkrts" { target { i?86-*-* x86_64-*-* } } } */
+
+#if HAVE_IO
+#include <stdio.h>
+#endif
+
+int fib (int);
+int fib_serial (int);
+
+#define FIB_ITERATION 30
+
+int main(void)
+{
+ int ii = 0;
+ int fib_result[FIB_ITERATION+1], fib_serial_result[FIB_ITERATION+1];
+#if HAVE_IO
+
+ for (ii = 0; ii <= FIB_ITERATION; ii++)
+ printf("fib (%2d) = %10d\n", ii, fib (ii));
+#else
+ for (ii = 0; ii <= FIB_ITERATION; ii++)
+ {
+ fib_result[ii] = fib (ii);
+ }
+
+ fib_serial_result[0] = 0;
+ fib_serial_result[1] = 1;
+ for (ii = 2; ii <= FIB_ITERATION; ii++)
+ fib_serial_result[ii] = fib_serial_result[ii-1] + fib_serial_result[ii-2];
+
+ for (ii = 0; ii <= FIB_ITERATION; ii++)
+ {
+ if (fib_result[ii] != fib_serial_result[ii])
+ __builtin_abort ();
+ }
+#endif
+ return 0;
+}
+
+int fib(int n)
+{
+ int x = 0, y = 0;
+ if (n < 2)
+ return n;
+ else
+ {
+ x = _Cilk_spawn fib(n-1);
+ y = fib(n-2);
+ _Cilk_sync;
+ return (x+y);
+ }
+}
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/CK/fib_init_expr_xy.c b/gcc/testsuite/c-c++-common/cilk-plus/CK/fib_init_expr_xy.c
new file mode 100644
index 00000000000..0196a8daba8
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/fib_init_expr_xy.c
@@ -0,0 +1,68 @@
+/* { dg-options "-fcilkplus" } */
+/* { dg-do run { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-fcilkplus -lcilkrts" { target { i?86-*-* x86_64-*-* } } } */
+
+#if HAVE_IO
+#include <stdio.h>
+#endif
+
+int fib (int);
+int fib_serial (int);
+
+#define FIB_ITERATION 30
+
+int main(void)
+{
+ int ii = 0;
+ int fib_result[FIB_ITERATION+1], fib_serial_result[FIB_ITERATION+1];
+#if HAVE_IO
+
+ for (ii = 0; ii <= FIB_ITERATION; ii++)
+ printf("fib (%2d) = %10d\n", ii, fib (ii));
+#else
+ for (ii = 0; ii <= FIB_ITERATION; ii++)
+ {
+ fib_result[ii] = fib (ii);
+ }
+
+ fib_serial_result[0] = 0;
+ fib_serial_result[1] = 1;
+
+ for (ii = 2; ii <= FIB_ITERATION; ii++)
+ fib_serial_result[ii] = fib_serial_result[ii-1] + fib_serial_result[ii-2];
+
+ for (ii = 0; ii <= FIB_ITERATION; ii++)
+ {
+ if (fib_result[ii] != fib_serial_result[ii])
+ __builtin_abort ();
+ }
+
+#endif
+ return 0;
+}
+
+int fib_serial (int n)
+{
+ int x = 0, y = 0;
+ if (n < 2)
+ return n;
+ else
+ {
+ x = fib_serial (n-1);
+ y = fib_serial (n-2);
+ return (x+y);
+ }
+}
+
+int fib(int n)
+{
+ if (n < 2)
+ return n;
+ else
+ {
+ int x = _Cilk_spawn fib(n-1);
+ int y = fib(n-2);
+ _Cilk_sync;
+ return (x+y);
+ }
+}
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/CK/fib_no_return.c b/gcc/testsuite/c-c++-common/cilk-plus/CK/fib_no_return.c
new file mode 100644
index 00000000000..47ebef52030
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/fib_no_return.c
@@ -0,0 +1,73 @@
+/* { dg-options "-fcilkplus" } */
+/* { dg-do run { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-fcilkplus -lcilkrts" { target { i?86-*-* x86_64-*-* } } } */
+
+#if HAVE_IO
+#include <stdio.h>
+#endif
+
+#define FIB_ITERATION 30
+
+void fib (int *, int);
+int fib_serial (int);
+
+int main(void)
+{
+ int ii = 0, error = 0;
+ int fib_result[FIB_ITERATION+1], fib_serial_result[FIB_ITERATION+1];
+
+#if HAVE_IO
+ for (ii = 0; ii <= FIB_ITERATION; ii++)
+ {
+ int result = 0;
+ fib (&result, ii);
+ printf("fib (%2d) = %10d\n", ii, result);
+ }
+#else
+ for (ii = 0; ii <= FIB_ITERATION; ii++)
+ {
+ fib (&fib_result[ii], ii);
+ }
+
+ fib_serial_result[0] = 0;
+ fib_serial_result[1] = 1;
+
+ for (ii = 2; ii <= FIB_ITERATION; ii++)
+ fib_serial_result[ii] = fib_serial_result[ii-1] + fib_serial_result[ii-2];
+
+ for (ii = 0; ii <= FIB_ITERATION; ii++)
+ {
+ if (fib_result[ii] != fib_serial_result[ii])
+ __builtin_abort ();
+ }
+#endif
+
+ return 0;
+}
+
+int fib_serial (int n)
+{
+ int x = 0, y = 0;
+ if (n < 2)
+ return n;
+ else
+ {
+ x = fib_serial (n-1);
+ y = fib_serial (n-2);
+ return (x+y);
+ }
+}
+
+void fib(int *result, int n)
+{
+ int x = 0, y = 0;
+ if (n < 2)
+ x = n;
+ else
+ {
+ _Cilk_spawn fib(&x, n-1);
+ fib(&y, n-2);
+ _Cilk_sync;
+ }
+ *result = (x+y);
+}
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/CK/fib_no_sync.c b/gcc/testsuite/c-c++-common/cilk-plus/CK/fib_no_sync.c
new file mode 100644
index 00000000000..a23051d4819
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/fib_no_sync.c
@@ -0,0 +1,67 @@
+/* { dg-options "-fcilkplus" } */
+/* { dg-do run { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-fcilkplus -lcilkrts" { target { i?86-*-* x86_64-*-* } } } */
+
+#if HAVE_IO
+#include <stdio.h>
+#endif
+
+#define FIB_ITERATION 30
+
+int fib (int);
+int fib_serial (int);
+
+int main(void)
+{
+ int ii = 0;
+ int fib_result[FIB_ITERATION+1], fib_serial_result[FIB_ITERATION+1];
+#if HAVE_IO
+
+ for (ii = 0; ii <= FIB_ITERATION; ii++)
+ printf("fib (%2d) = %10d\n", ii, fib (ii));
+#else
+ for (ii = 0; ii <= FIB_ITERATION; ii++)
+ {
+ fib_result[ii] = fib (ii);
+ }
+
+ fib_serial_result[0] = 0;
+ fib_serial_result[1] = 1;
+
+ for (ii = 2; ii <= FIB_ITERATION; ii++)
+ fib_serial_result[ii] = fib_serial_result[ii-1] + fib_serial_result[ii-2];
+
+ for (ii = 0; ii <= FIB_ITERATION; ii++)
+ {
+ if (fib_result[ii] != fib_serial_result[ii])
+ __builtin_abort ();
+ }
+
+#endif
+ return 0;
+}
+
+int fib_serial (int n)
+{
+ int x = 0, y = 0;
+ if (n < 2)
+ return n;
+ else
+ {
+ x = fib_serial (n-1);
+ y = fib_serial (n-2);
+ return (x+y);
+ }
+}
+
+int fib(int n)
+{
+ if (n < 2)
+ return n;
+ else
+ {
+ int x = _Cilk_spawn fib(n-1);
+ int y = fib(n-2);
+ return (x+y);
+ }
+}
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/CK/invalid_spawns.c b/gcc/testsuite/c-c++-common/cilk-plus/CK/invalid_spawns.c
new file mode 100644
index 00000000000..90dd5c130b4
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/invalid_spawns.c
@@ -0,0 +1,11 @@
+extern int foo ();
+int bar = _Cilk_spawn foo (); /* { dg-error "may only be used inside a function" } */
+
+
+int main (void)
+{
+ int x;
+
+ _Cilk_spawn x; /* { dg-error "only function calls can be spawned" } */
+ return x;
+}
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/CK/no_args_error.c b/gcc/testsuite/c-c++-common/cilk-plus/CK/no_args_error.c
new file mode 100644
index 00000000000..593732ef5ab
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/no_args_error.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-fcilkplus" } */
+
+int spawn_1 ();
+typedef int(*func) (int);
+
+void check () {
+ func var = spawn_1; /* { dg-error "invalid conversion from" "" { target c++ } 8 } */
+ _Cilk_spawn var (); /* { dg-error "too few arguments to function" } */
+}
+
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/CK/spawn_in_return.c b/gcc/testsuite/c-c++-common/cilk-plus/CK/spawn_in_return.c
new file mode 100644
index 00000000000..14b7eef1276
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/spawn_in_return.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-fcilkplus" } */
+
+int main (void)
+{
+ extern int foo ();
+ return _Cilk_spawn foo (); /* { dg-error "return statement is not allowed" } */
+}
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/CK/spawnee_inline.c b/gcc/testsuite/c-c++-common/cilk-plus/CK/spawnee_inline.c
new file mode 100644
index 00000000000..8060c6ceb15
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/spawnee_inline.c
@@ -0,0 +1,80 @@
+/* { dg-do run { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-options "-fcilkplus -w" } */
+/* { dg-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */
+
+#include <stdio.h>
+#include <stdlib.h>
+#define DEFAULT_VALUE "30"
+
+int fib (char *n_char)
+{
+ int n;
+ char n_char_minus_one[20], n_char_minus_two[20];
+ if (n_char)
+ n = atoi (n_char);
+ else
+ n = atoi(DEFAULT_VALUE);
+
+ if (n < 2)
+ return n;
+ else
+ {
+ int x, y;
+ sprintf (n_char_minus_one,"%d", n-1);
+ sprintf (n_char_minus_two,"%d", n-2);
+ x = _Cilk_spawn fib (n_char_minus_one);
+ y = _Cilk_spawn fib (n_char_minus_two);
+ _Cilk_sync;
+ return (x+y);
+ }
+}
+
+int fib_serial (int n)
+{
+ int x, y;
+ if (n < 2)
+ return n;
+ else
+ {
+ x = fib_serial (n-1);
+ y = fib_serial (n-2);
+ return (x+y);
+ }
+ return 0;
+}
+
+int main2_parallel (int argc, char *argv[])
+{
+ int n, result_parallel = 0;
+
+ if (argc == 2)
+ {
+ result_parallel = _Cilk_spawn fib (argv[1]);
+ _Cilk_sync;
+ }
+ else
+ {
+ result_parallel = _Cilk_spawn fib((char *)"30");
+ _Cilk_sync;
+ }
+ return result_parallel;
+}
+
+int main2_serial (int argc, char *argv[])
+{
+ int n, result_serial = 0;
+ if (argc == 2)
+ result_serial = fib_serial (atoi (argv[1]));
+ else
+ result_serial = fib_serial (atoi (DEFAULT_VALUE));
+
+ return result_serial;
+}
+
+int main (void)
+{
+ if (main2_serial (1, 0) != main2_parallel (1,0))
+ return 1;
+ return 0;
+}
+
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/CK/spawner_inline.c b/gcc/testsuite/c-c++-common/cilk-plus/CK/spawner_inline.c
new file mode 100644
index 00000000000..eab9e4206a0
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/spawner_inline.c
@@ -0,0 +1,67 @@
+/* { dg-do run { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-options "-fcilkplus" } */
+/* { dg-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */
+
+#include <stdlib.h>
+#define DEFAULT_VALUE 30
+int fib (int n)
+{
+ if (n<2)
+ return n;
+ else
+ {
+ int x, y;
+ x = _Cilk_spawn fib (n-1);
+ y = _Cilk_spawn fib (n-2);
+ _Cilk_sync;
+ return (x+y);
+ return 5;
+ }
+}
+
+int main_parallel (int argc, char *argv[])
+{
+ int n, result;
+ if (argc == 2)
+ n = atoi(argv[1]);
+ else
+ n = DEFAULT_VALUE;
+ result = _Cilk_spawn fib(n);
+ _Cilk_sync;
+ return result;
+}
+
+int fib_serial (int n)
+{
+ int x, y;
+ if (n < 2)
+ return n;
+ else
+ {
+ x = fib (n-1);
+ y = fib (n-2);
+ return (x+y);
+ }
+}
+
+int main_serial (int argc, char *argv[])
+{
+ int n, result;
+
+ if (argc == 2)
+ n = atoi (argv[1]);
+ else
+ n = DEFAULT_VALUE;
+ result = fib_serial (n);
+
+ return result;
+}
+
+int main (void)
+{
+ if (main_serial (1, 0) != main_parallel (1,0))
+ return 1;
+ else
+ return 0;
+}
+
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/CK/spawning_arg.c b/gcc/testsuite/c-c++-common/cilk-plus/CK/spawning_arg.c
new file mode 100644
index 00000000000..ac379528379
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/spawning_arg.c
@@ -0,0 +1,37 @@
+/* { dg-do run { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-options "-fcilkplus" } */
+/* { dg-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */
+
+void f0(volatile int *steal_flag)
+{
+ int i = 0;
+ /* Wait for steal_flag to be set */
+ while (!*steal_flag)
+ ;
+}
+
+int f1()
+{
+
+ volatile int steal_flag = 0;
+ _Cilk_spawn f0(&steal_flag);
+ steal_flag = 1; // Indicate stolen
+ _Cilk_sync;
+ return 0;
+}
+
+void f2(int q)
+{
+ q = 5;
+}
+
+void f3()
+{
+ _Cilk_spawn f2(f1());
+}
+
+int main()
+{
+ f3();
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/CK/steal_check.c b/gcc/testsuite/c-c++-common/cilk-plus/CK/steal_check.c
new file mode 100644
index 00000000000..21d6797857d
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/steal_check.c
@@ -0,0 +1,43 @@
+/* { dg-do run { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-options "-fcilkplus" } */
+/* { dg-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */
+
+// #include <cilk/cilk_api.h>
+extern void __cilkrts_set_param (char *, char *);
+
+void foo(volatile int *);
+
+void main2(void);
+
+int main(void)
+{
+ // __cilkrts_set_param ((char *)"nworkers", (char *)"2");
+ main2();
+ return 0;
+}
+
+
+void main2(void)
+{
+ int some_var = 0;
+
+ _Cilk_spawn foo(&some_var);
+
+ some_var=1;
+ some_var=5;
+ some_var=3;
+ some_var=4;
+
+ _Cilk_sync;
+ return;
+}
+
+void foo(volatile int *some_other_var)
+{
+ while (*some_other_var == 0)
+ {
+ ;
+ }
+}
+
+
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/CK/sync_wo_spawn.c b/gcc/testsuite/c-c++-common/cilk-plus/CK/sync_wo_spawn.c
new file mode 100644
index 00000000000..51be796e562
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/sync_wo_spawn.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-fcilkplus" } */
+
+int main (void)
+{
+ _Cilk_sync; /* { dg-error "expected '_Cilk_spawn' before '_Cilk_sync'" } */
+ return 0;
+}
+
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/CK/test__cilk.c b/gcc/testsuite/c-c++-common/cilk-plus/CK/test__cilk.c
new file mode 100644
index 00000000000..2b37cd664c1
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/test__cilk.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-do run { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-options "-fcilkplus" } */
+
+int main (void)
+{
+ if (__cilk == 200)
+ return 0;
+ return 1;
+}
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/CK/varargs_test.c b/gcc/testsuite/c-c++-common/cilk-plus/CK/varargs_test.c
new file mode 100644
index 00000000000..ab5d63a3f4c
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/varargs_test.c
@@ -0,0 +1,47 @@
+/* { dg-do run { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-options "-fcilkplus" } */
+/* { dg-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */
+
+#include <stdarg.h>
+#include <stdlib.h>
+
+
+double compute_total (int no_elements, ...);
+
+int main(void)
+{
+ double array[5] = {5.0, 4.0, 9.0, 3.0, 4.0};
+ double array2[5] = {5.0, 6.0, 8.0, 6.0};
+ double yy=0, xx=0, xx_serial, yy_serial;
+
+ yy = _Cilk_spawn compute_total(5,array[0],array[1],array[2],
+ array[3], array[4]);
+ xx= compute_total(4,array2[0],array2[1],array2[2], array2[3]);
+
+ _Cilk_sync;
+
+ yy_serial = compute_total(5,array[0],array[1],array[2], array[3], array[4]);
+ xx_serial = compute_total(4,array2[0],array2[1],array2[2], array2[3]);
+
+ if ((xx + yy) != (xx_serial + yy_serial))
+ return 1;
+ return 0;
+
+}
+
+
+double compute_total (int no_elements, ...)
+{
+ double total = 0;
+ va_list args;
+ va_start(args, no_elements);
+ int ii = 0;
+ for (ii = 0; ii < no_elements; ii++)
+ {
+ total += va_arg(args,double);
+ }
+ va_end(args);
+
+ return total;
+}
+
diff --git a/gcc/testsuite/c-c++-common/cpp/openmp-define-1.c b/gcc/testsuite/c-c++-common/cpp/openmp-define-1.c
new file mode 100644
index 00000000000..c5379223c84
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cpp/openmp-define-1.c
@@ -0,0 +1,6 @@
+/* { dg-do preprocess } */
+/* { dg-require-effective-target fopenmp } */
+
+#ifdef _OPENMP
+# error _OPENMP defined
+#endif
diff --git a/gcc/testsuite/c-c++-common/cpp/openmp-define-2.c b/gcc/testsuite/c-c++-common/cpp/openmp-define-2.c
new file mode 100644
index 00000000000..8823e291b8b
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cpp/openmp-define-2.c
@@ -0,0 +1,7 @@
+/* { dg-options "-fno-openmp" } */
+/* { dg-do preprocess } */
+/* { dg-require-effective-target fopenmp } */
+
+#ifdef _OPENMP
+# error _OPENMP defined
+#endif
diff --git a/gcc/testsuite/c-c++-common/cpp/openmp-define-3.c b/gcc/testsuite/c-c++-common/cpp/openmp-define-3.c
new file mode 100644
index 00000000000..6986c5507b9
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cpp/openmp-define-3.c
@@ -0,0 +1,11 @@
+/* { dg-options "-fopenmp" } */
+/* { dg-do preprocess } */
+/* { dg-require-effective-target fopenmp } */
+
+#ifndef _OPENMP
+# error _OPENMP not defined
+#endif
+
+#if _OPENMP != 201307
+# error _OPENMP defined to wrong value
+#endif
diff --git a/gcc/testsuite/c-c++-common/fold-divmul-1.c b/gcc/testsuite/c-c++-common/fold-divmul-1.c
new file mode 100644
index 00000000000..5c867923d2e
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/fold-divmul-1.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-tree-original" } */
+
+int *
+fx (int *b, int *e)
+{
+ return b + (e - b);
+}
+
+/* { dg-final { scan-tree-dump-not "/\\\[ex\\\]" "original" } } */
+/* { dg-final { cleanup-tree-dump "original" } } */
diff --git a/gcc/testsuite/c-c++-common/gomp/atomic-15.c b/gcc/testsuite/c-c++-common/gomp/atomic-15.c
index 13a9e0ce48a..5e669fa3543 100644
--- a/gcc/testsuite/c-c++-common/gomp/atomic-15.c
+++ b/gcc/testsuite/c-c++-common/gomp/atomic-15.c
@@ -8,39 +8,37 @@ main ()
{
int v;
#pragma omp atomic
- x = x * 7 + 6; /* { dg-error "expected" } */
+ x = x * 7 + 6; /* { dg-error "expected|invalid form of" } */
#pragma omp atomic
- x = x * 7 ^ 6; /* { dg-error "expected" } */
+ x = x * 7 ^ 6; /* { dg-error "expected|invalid form of" } */
#pragma omp atomic update
- x = x - 8 + 6; /* { dg-error "expected" } */
+ x = x - 8 + 6; /* { dg-error "expected|invalid form of" } */
#pragma omp atomic
- x = x ^ 7 | 2; /* { dg-error "expected" } */
+ x = x ^ 7 | 2; /* { dg-error "expected|invalid form of" } */
#pragma omp atomic
- x = x / 7 * 2; /* { dg-error "expected" } */
+ x = x / 7 * 2; /* { dg-error "expected|invalid form of" } */
#pragma omp atomic
- x = x / 7 / 2; /* { dg-error "expected" } */
+ x = x / 7 / 2; /* { dg-error "expected|invalid form of" } */
#pragma omp atomic capture
- v = x = x | 6; /* { dg-error "invalid operator" } */
+ { v = x; x = x * 7 + 6; } /* { dg-error "expected" "" { target c++ } } */
#pragma omp atomic capture
- { v = x; x = x * 7 + 6; } /* { dg-error "expected" } */
+ { v = x; x = x * 7 ^ 6; } /* { dg-error "expected" "" { target c++ } } */
#pragma omp atomic capture
- { v = x; x = x * 7 ^ 6; } /* { dg-error "expected" } */
+ { v = x; x = x - 8 + 6; } /* { dg-error "expected" "" { target c++ } } */
#pragma omp atomic capture
- { v = x; x = x - 8 + 6; } /* { dg-error "expected" } */
+ { v = x; x = x ^ 7 | 2; } /* { dg-error "expected" "" { target c++ } } */
#pragma omp atomic capture
- { v = x; x = x ^ 7 | 2; } /* { dg-error "expected" } */
+ { v = x; x = x / 7 * 2; } /* { dg-error "expected" "" { target c++ } } */
#pragma omp atomic capture
- { v = x; x = x / 7 * 2; } /* { dg-error "expected" } */
+ { v = x; x = x / 7 / 2; } /* { dg-error "expected" "" { target c++ } } */
#pragma omp atomic capture
- { v = x; x = x / 7 / 2; } /* { dg-error "expected" } */
+ { x = x * 7 + 6; v = x; } /* { dg-error "expected|uses two different expressions for memory" } */
#pragma omp atomic capture
- { x = x * 7 + 6; v = x; } /* { dg-error "expected" } */
+ { x = x * 7 ^ 6; v = x; } /* { dg-error "expected|uses two different expressions for memory" } */
#pragma omp atomic capture
- { x = x * 7 ^ 6; v = x; } /* { dg-error "expected" } */
+ { x = x - 8 + 6; v = x; } /* { dg-error "expected|uses two different expressions for memory" } */
#pragma omp atomic capture
- { x = x - 8 + 6; v = x; } /* { dg-error "expected" } */
- #pragma omp atomic capture
- { x = x ^ 7 | 2; v = x; } /* { dg-error "expected" } */
+ { x = x ^ 7 | 2; v = x; } /* { dg-error "expected|uses two different expressions for memory" } */
(void) v;
return 0;
}
diff --git a/gcc/testsuite/c-c++-common/gomp/atomic-16.c b/gcc/testsuite/c-c++-common/gomp/atomic-16.c
new file mode 100644
index 00000000000..87fbaa23317
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/atomic-16.c
@@ -0,0 +1,34 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp" } */
+
+int x = 6;
+
+void
+foo ()
+{
+ int v;
+ #pragma omp atomic seq_cst load /* { dg-error "expected end of line" } */
+ v = x; /* { dg-error "invalid form" } */
+ #pragma omp atomic seq_cst, load /* { dg-error "expected end of line" } */
+ v = x; /* { dg-error "invalid form" } */
+ #pragma omp atomic seq_cst store /* { dg-error "expected end of line" } */
+ x = v; /* { dg-error "invalid form" } */
+ #pragma omp atomic seq_cst ,store /* { dg-error "expected end of line" } */
+ x = v; /* { dg-error "invalid form" } */
+ #pragma omp atomic seq_cst update /* { dg-error "expected end of line" } */
+ x += v;
+ #pragma omp atomic seq_cst , update /* { dg-error "expected end of line" } */
+ x += v;
+ #pragma omp atomic seq_cst capture /* { dg-error "expected end of line" } */
+ v = x += 2; /* { dg-error "invalid form" } */
+ #pragma omp atomic seq_cst, capture /* { dg-error "expected end of line" } */
+ v = x += 2; /* { dg-error "invalid form" } */
+ #pragma omp atomic load , seq_cst /* { dg-error "expected end of line" } */
+ v = x; /* { dg-error "invalid form" } */
+ #pragma omp atomic store ,seq_cst /* { dg-error "expected end of line" } */
+ x = v; /* { dg-error "invalid form" } */
+ #pragma omp atomic update, seq_cst /* { dg-error "expected end of line" } */
+ x += v;
+ #pragma omp atomic capture, seq_cst /* { dg-error "expected end of line" } */
+ v = x += 2;
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/cancel-1.c b/gcc/testsuite/c-c++-common/gomp/cancel-1.c
new file mode 100644
index 00000000000..d8f7bc1b8fa
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/cancel-1.c
@@ -0,0 +1,396 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp" } */
+
+void
+f1 (void)
+{
+ #pragma omp cancel parallel /* { dg-error "orphaned" } */
+ #pragma omp cancel for /* { dg-error "orphaned" } */
+ #pragma omp cancel sections /* { dg-error "orphaned" } */
+ #pragma omp cancel taskgroup /* { dg-error "orphaned" } */
+ #pragma omp cancellation point parallel /* { dg-error "orphaned" } */
+ #pragma omp cancellation point for /* { dg-error "orphaned" } */
+ #pragma omp cancellation point sections /* { dg-error "orphaned" } */
+ #pragma omp cancellation point taskgroup /* { dg-error "orphaned" } */
+}
+
+void
+f2 (void)
+{
+ int i;
+ #pragma omp parallel
+ {
+ #pragma omp cancel parallel
+ #pragma omp cancel for /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel sections /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel taskgroup /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point parallel
+ #pragma omp cancellation point for /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point sections /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point taskgroup /* { dg-error "not closely nested inside" } */
+ #pragma omp master
+ {
+ #pragma omp cancel parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel for /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel sections /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel taskgroup /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point for /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point sections /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point taskgroup /* { dg-error "not closely nested inside" } */
+ }
+ #pragma omp single
+ {
+ #pragma omp cancel parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel for /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel sections /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel taskgroup /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point for /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point sections /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point taskgroup /* { dg-error "not closely nested inside" } */
+ }
+ #pragma omp critical
+ {
+ #pragma omp cancel parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel for /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel sections /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel taskgroup /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point for /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point sections /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point taskgroup /* { dg-error "not closely nested inside" } */
+ }
+ #pragma omp taskgroup
+ {
+ #pragma omp cancel parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel for /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel sections /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel taskgroup /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point for /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point sections /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point taskgroup /* { dg-error "not closely nested inside" } */
+ }
+ #pragma omp task
+ {
+ #pragma omp cancel parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel for /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel sections /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel taskgroup
+ #pragma omp cancellation point parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point for /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point sections /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point taskgroup
+ }
+ #pragma omp for
+ for (i = 0; i < 10; i++)
+ {
+ #pragma omp cancel parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel for
+ #pragma omp cancel sections /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel taskgroup /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point for
+ #pragma omp cancellation point sections /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point taskgroup/* { dg-error "not closely nested inside" } */
+ }
+ #pragma omp for ordered
+ for (i = 0; i < 10; i++)
+ #pragma omp ordered
+ {
+ #pragma omp cancel parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel for /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel sections /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel taskgroup /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point for /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point sections /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point taskgroup/* { dg-error "not closely nested inside" } */
+ }
+ #pragma omp sections
+ {
+ {
+ #pragma omp cancel parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel for /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel sections
+ #pragma omp cancel taskgroup /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point for /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point sections
+ #pragma omp cancellation point taskgroup/* { dg-error "not closely nested inside" } */
+ }
+ #pragma omp section
+ {
+ #pragma omp cancel parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel for /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel sections
+ #pragma omp cancel taskgroup /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point for /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point sections
+ #pragma omp cancellation point taskgroup/* { dg-error "not closely nested inside" } */
+ }
+ }
+ #pragma omp target data
+ {
+ #pragma omp cancel parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel for /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel sections /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel taskgroup /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point for /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point sections /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point taskgroup /* { dg-error "not closely nested inside" } */
+ }
+ #pragma omp target
+ {
+ #pragma omp cancel parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel for /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel sections /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel taskgroup /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point for /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point sections /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point taskgroup /* { dg-error "not closely nested inside" } */
+ }
+ }
+ #pragma omp target data
+ {
+ #pragma omp cancel parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel for /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel sections /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel taskgroup /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point for /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point sections /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point taskgroup /* { dg-error "not closely nested inside" } */
+ }
+ #pragma omp target
+ {
+ #pragma omp cancel parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel for /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel sections /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel taskgroup /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point for /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point sections /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point taskgroup /* { dg-error "not closely nested inside" } */
+ }
+ #pragma omp target teams
+ {
+ #pragma omp cancel parallel /* { dg-error "only distribute or parallel constructs are allowed to be closely nested" } */
+ #pragma omp cancel for /* { dg-error "only distribute or parallel constructs are allowed to be closely nested" } */
+ #pragma omp cancel sections /* { dg-error "only distribute or parallel constructs are allowed to be closely nested" } */
+ #pragma omp cancel taskgroup /* { dg-error "only distribute or parallel constructs are allowed to be closely nested" } */
+ #pragma omp cancellation point parallel /* { dg-error "only distribute or parallel constructs are allowed to be closely nested" } */
+ #pragma omp cancellation point for /* { dg-error "only distribute or parallel constructs are allowed to be closely nested" } */
+ #pragma omp cancellation point sections /* { dg-error "only distribute or parallel constructs are allowed to be closely nested" } */
+ #pragma omp cancellation point taskgroup /* { dg-error "only distribute or parallel constructs are allowed to be closely nested" } */
+ }
+ #pragma omp target teams distribute
+ for (i = 0; i < 10; i++)
+ {
+ #pragma omp cancel parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel for /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel sections /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel taskgroup /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point for /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point sections /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point taskgroup /* { dg-error "not closely nested inside" } */
+ }
+ #pragma omp for
+ for (i = 0; i < 10; i++)
+ {
+ #pragma omp cancel parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel for
+ #pragma omp cancel sections /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel taskgroup /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point for
+ #pragma omp cancellation point sections /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point taskgroup /* { dg-error "not closely nested inside" } */
+ }
+ #pragma omp for
+ for (i = 0; i < 10; i++)
+ #pragma omp target data
+ {
+ #pragma omp cancel parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel for /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel sections /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel taskgroup /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point for /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point sections /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point taskgroup /* { dg-error "not closely nested inside" } */
+ }
+ #pragma omp for
+ for (i = 0; i < 10; i++)
+ #pragma omp target
+ {
+ #pragma omp cancel parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel for /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel sections /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel taskgroup /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point for /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point sections /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point taskgroup /* { dg-error "not closely nested inside" } */
+ }
+ #pragma omp for ordered
+ for (i = 0; i < 10; i++)
+ #pragma omp ordered
+ #pragma omp target data
+ {
+ #pragma omp cancel parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel for /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel sections /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel taskgroup /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point for /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point sections /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point taskgroup/* { dg-error "not closely nested inside" } */
+ }
+ #pragma omp for ordered
+ for (i = 0; i < 10; i++)
+ #pragma omp ordered
+ #pragma omp target
+ {
+ #pragma omp cancel parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel for /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel sections /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel taskgroup /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point for /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point sections /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point taskgroup/* { dg-error "not closely nested inside" } */
+ }
+ #pragma omp sections
+ {
+ {
+ #pragma omp cancel parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel for /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel sections
+ #pragma omp cancel taskgroup /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point for /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point sections
+ #pragma omp cancellation point taskgroup /* { dg-error "not closely nested inside" } */
+ }
+ #pragma omp section
+ {
+ #pragma omp cancel parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel for /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel sections
+ #pragma omp cancel taskgroup /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point for /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point sections
+ #pragma omp cancellation point taskgroup /* { dg-error "not closely nested inside" } */
+ }
+ }
+ #pragma omp sections
+ {
+ #pragma omp target data
+ {
+ #pragma omp cancel parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel for /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel sections /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel taskgroup /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point for /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point sections /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point taskgroup /* { dg-error "not closely nested inside" } */
+ }
+ #pragma omp section
+ #pragma omp target data
+ {
+ #pragma omp cancel parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel for /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel sections /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel taskgroup /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point for /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point sections /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point taskgroup /* { dg-error "not closely nested inside" } */
+ }
+ }
+ #pragma omp sections
+ {
+ #pragma omp target
+ {
+ #pragma omp cancel parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel for /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel sections /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel taskgroup /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point for /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point sections /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point taskgroup /* { dg-error "not closely nested inside" } */
+ }
+ #pragma omp section
+ #pragma omp target
+ {
+ #pragma omp cancel parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel for /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel sections /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel taskgroup /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point for /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point sections /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point taskgroup /* { dg-error "not closely nested inside" } */
+ }
+ }
+ #pragma omp task
+ {
+ #pragma omp cancel parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel for /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel sections /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel taskgroup
+ #pragma omp cancellation point parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point for /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point sections /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point taskgroup
+ #pragma omp taskgroup
+ {
+ #pragma omp cancel parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel for /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel sections /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel taskgroup /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point for /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point sections /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point taskgroup /* { dg-error "not closely nested inside" } */
+ }
+ }
+}
+
+void
+f3 (void)
+{
+ int i;
+ #pragma omp for nowait
+ for (i = 0; i < 10; i++)
+ {
+ #pragma omp cancel for /* { dg-warning "nowait" } */
+ }
+ #pragma omp sections nowait
+ {
+ {
+ #pragma omp cancel sections /* { dg-warning "nowait" } */
+ }
+ #pragma omp section
+ {
+ #pragma omp cancel sections /* { dg-warning "nowait" } */
+ }
+ }
+ #pragma omp for ordered
+ for (i = 0; i < 10; i++)
+ {
+ #pragma omp cancel for /* { dg-warning "ordered" } */
+ #pragma omp ordered
+ {
+ }
+ }
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/depend-1.c b/gcc/testsuite/c-c++-common/gomp/depend-1.c
new file mode 100644
index 00000000000..8a5850e45fe
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/depend-1.c
@@ -0,0 +1,79 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp" } */
+
+extern int a[][10], a2[][10];
+int b[10], c[10][2], d[10], e[10], f[10];
+int b2[10], c2[10][2], d2[10], e2[10], f2[10];
+int k[10], l[10], m[10], n[10], o;
+int *p;
+void bar (void);
+int t[10];
+#pragma omp threadprivate (t)
+
+void
+foo (int g[3][10], int h[4][8], int i[2][10], int j[][9],
+ int g2[3][10], int h2[4][8], int i2[2][10], int j2[][9])
+{
+ #pragma omp task depend(in: bar[2:5]) /* { dg-error "is not a variable" } */
+ ;
+ #pragma omp task depend(out: t[2:5])
+ ;
+ #pragma omp task depend(inout: k[0.5:]) /* { dg-error "low bound \[^\n\r]* of array section does not have integral type" } */
+ ;
+ #pragma omp task depend(in: l[:7.5f]) /* { dg-error "length \[^\n\r]* of array section does not have integral type" } */
+ ;
+ #pragma omp task depend(out: m[p:]) /* { dg-error "low bound \[^\n\r]* of array section does not have integral type" } */
+ ;
+ #pragma omp task depend(inout: n[:p]) /* { dg-error "length \[^\n\r]* of array section does not have integral type" } */
+ ;
+ #pragma omp task depend(in: o[2:5]) /* { dg-error "does not have pointer or array type" } */
+ ;
+ #pragma omp task depend(out: a[:][2:4]) /* { dg-error "array type length expression must be specified" } */
+ ;
+ #pragma omp task depend(inout: b[-1:]) /* { dg-error "negative low bound in array section" } */
+ ;
+ #pragma omp task depend(inout: c[:-3][1:1]) /* { dg-error "negative length in array section" } */
+ ;
+ #pragma omp task depend(in: d[11:]) /* { dg-error "low bound \[^\n\r]* above array section size" } */
+ ;
+ #pragma omp task depend(out: e[:11]) /* { dg-error "length \[^\n\r]* above array section size" } */
+ ;
+ #pragma omp task depend(out: f[1:10]) /* { dg-error "high bound \[^\n\r]* above array section size" } */
+ ;
+ #pragma omp task depend(in: g[:][2:4]) /* { dg-error "for pointer type length expression must be specified" } */
+ ;
+ #pragma omp task depend(in: h[2:2][-1:]) /* { dg-error "negative low bound in array section" } */
+ ;
+ #pragma omp task depend(inout: h[:1][:-3]) /* { dg-error "negative length in array section" } */
+ ;
+ #pragma omp task depend(out: i[:1][11:]) /* { dg-error "low bound \[^\n\r]* above array section size" } */
+ ;
+ #pragma omp task depend(in: j[3:4][:10]) /* { dg-error "length \[^\n\r]* above array section size" } */
+ ;
+ #pragma omp task depend(out: j[30:10][5:5]) /* { dg-error "high bound \[^\n\r]* above array section size" } */
+ ;
+ #pragma omp task depend(out: a2[:3][2:4])
+ ;
+ #pragma omp task depend(inout: b2[0:])
+ ;
+ #pragma omp task depend(inout: c2[:3][1:1])
+ ;
+ #pragma omp task depend(in: d2[9:])
+ ;
+ #pragma omp task depend(out: e2[:10])
+ ;
+ #pragma omp task depend(out: f2[1:9])
+ ;
+ #pragma omp task depend(in: g2[:2][2:4])
+ ;
+ #pragma omp task depend(in: h2[2:2][0:])
+ ;
+ #pragma omp task depend(inout: h2[:1][:3])
+ ;
+ #pragma omp task depend(out: i2[:1][9:])
+ ;
+ #pragma omp task depend(in: j2[3:4][:9])
+ ;
+ #pragma omp task depend(out: j2[30:10][5:4])
+ ;
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/depend-2.c b/gcc/testsuite/c-c++-common/gomp/depend-2.c
new file mode 100644
index 00000000000..99bf8ae1b83
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/depend-2.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp" } */
+
+void bar (int a[10][10][10]);
+void
+foo (int a[10][10][10], int **b)
+{
+ int c[10][10][10];
+ #pragma omp task depend(out: a[2:4][3:][:7], b[1:7][2:8])
+ bar (a);
+ int i = 1, j = 3, k = 2, l = 6;
+ #pragma omp task depend(in: a[++i:++j][++k:][:++l])
+ bar (a);
+ #pragma omp task depend(out: a[7:2][:][:], c[5:2][:][:])
+ {
+ bar (c);
+ bar (a);
+ }
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/map-1.c b/gcc/testsuite/c-c++-common/gomp/map-1.c
new file mode 100644
index 00000000000..694d88cc795
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/map-1.c
@@ -0,0 +1,103 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp" } */
+
+extern int a[][10], a2[][10];
+int b[10], c[10][2], d[10], e[10], f[10];
+int b2[10], c2[10][2], d2[10], e2[10], f2[10];
+int k[10], l[10], m[10], n[10], o;
+int *p;
+int **q;
+int r[4][4][4][4][4];
+int t[10];
+#pragma omp threadprivate (t)
+#pragma omp declare target
+void bar (int *);
+#pragma omp end declare target
+
+void
+foo (int g[3][10], int h[4][8], int i[2][10], int j[][9],
+ int g2[3][10], int h2[4][8], int i2[2][10], int j2[][9])
+{
+ #pragma omp target map(to: bar[2:5]) /* { dg-error "is not a variable" } */
+ ;
+ #pragma omp target map(from: t[2:5]) /* { dg-error "is threadprivate variable" } */
+ ;
+ #pragma omp target map(tofrom: k[0.5:]) /* { dg-error "low bound \[^\n\r]* of array section does not have integral type" } */
+ ;
+ #pragma omp target map(from: l[:7.5f]) /* { dg-error "length \[^\n\r]* of array section does not have integral type" } */
+ ;
+ #pragma omp target map(to: m[p:]) /* { dg-error "low bound \[^\n\r]* of array section does not have integral type" } */
+ ;
+ #pragma omp target map(tofrom: n[:p]) /* { dg-error "length \[^\n\r]* of array section does not have integral type" } */
+ ;
+ #pragma omp target map(to: o[2:5]) /* { dg-error "does not have pointer or array type" } */
+ ;
+ #pragma omp target map(to: a[:][:]) /* { dg-error "array type length expression must be specified" } */
+ bar (&a[0][0]); /* { dg-error "referenced in target region does not have a mappable type" } */
+ #pragma omp target map(tofrom: b[-1:]) /* { dg-error "negative low bound in array section" } */
+ bar (b);
+ #pragma omp target map(tofrom: c[:-3][:]) /* { dg-error "negative length in array section" } */
+ bar (&c[0][0]);
+ #pragma omp target map(from: d[11:]) /* { dg-error "low bound \[^\n\r]* above array section size" } */
+ bar (d);
+ #pragma omp target map(to: e[:11]) /* { dg-error "length \[^\n\r]* above array section size" } */
+ bar (e);
+ #pragma omp target map(to: f[1:10]) /* { dg-error "high bound \[^\n\r]* above array section size" } */
+ bar (f);
+ #pragma omp target map(from: g[:][0:10]) /* { dg-error "for pointer type length expression must be specified" } */
+ bar (&g[0][0]);
+ #pragma omp target map(from: h[2:1][-1:]) /* { dg-error "negative low bound in array section" } */
+ bar (&h[0][0]);
+ #pragma omp target map(tofrom: h[:1][:-3]) /* { dg-error "negative length in array section" } */
+ bar (&h[0][0]);
+ #pragma omp target map(i[:1][11:]) /* { dg-error "low bound \[^\n\r]* above array section size" } */
+ bar (&i[0][0]);
+ #pragma omp target map(from: j[3:1][:10]) /* { dg-error "length \[^\n\r]* above array section size" } */
+ bar (&j[0][0]);
+ #pragma omp target map(to: j[30:1][5:5]) /* { dg-error "high bound \[^\n\r]* above array section size" } */
+ bar (&j[0][0]);
+ #pragma omp target map(to: a2[:1][2:4])
+ bar (&a2[0][0]);
+ #pragma omp target map(a2[3:5][:])
+ bar (&a2[0][0]);
+ #pragma omp target map(to: a2[3:5][:10])
+ bar (&a2[0][0]);
+ #pragma omp target map(tofrom: b2[0:])
+ bar (b2);
+ #pragma omp target map(tofrom: c2[:3][:])
+ bar (&c2[0][0]);
+ #pragma omp target map(from: d2[9:])
+ bar (d2);
+ #pragma omp target map(to: e2[:10])
+ bar (e2);
+ #pragma omp target map(to: f2[1:9])
+ bar (f2);
+ #pragma omp target map(g2[:1][2:4])
+ bar (&g2[0][0]);
+ #pragma omp target map(from: h2[2:2][0:])
+ bar (&h2[0][0]);
+ #pragma omp target map(tofrom: h2[:1][:3])
+ bar (&h2[0][0]);
+ #pragma omp target map(to: i2[:1][9:])
+ bar (&i2[0][0]);
+ #pragma omp target map(from: j2[3:4][:9])
+ bar (&j2[0][0]);
+ #pragma omp target map(to: j2[30:1][5:4])
+ bar (&j2[0][0]);
+ #pragma omp target map(q[1:2])
+ ;
+ #pragma omp target map(tofrom: q[3:5][:10]) /* { dg-error "array section is not contiguous" } */
+ ;
+ #pragma omp target map(r[3:][2:1][1:2])
+ ;
+ #pragma omp target map(r[3:][2:1][1:2][:][0:4])
+ ;
+ #pragma omp target map(r[3:][2:1][1:2][1:][0:4]) /* { dg-error "array section is not contiguous" } */
+ ;
+ #pragma omp target map(r[3:][2:1][1:2][:3][0:4]) /* { dg-error "array section is not contiguous" } */
+ ;
+ #pragma omp target map(r[3:][2:1][1:2][:][1:]) /* { dg-error "array section is not contiguous" } */
+ ;
+ #pragma omp target map(r[3:][2:1][1:2][:][:3]) /* { dg-error "array section is not contiguous" } */
+ ;
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/pr58472.c b/gcc/testsuite/c-c++-common/gomp/pr58472.c
new file mode 100644
index 00000000000..355ca4008bf
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/pr58472.c
@@ -0,0 +1,16 @@
+/* PR tree-optimization/58472 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wall -fopenmp" } */
+
+float a[1024], b[1024];
+
+float
+foo ()
+{
+ float s = 0.f;
+ unsigned int i;
+#pragma omp simd reduction(+:s)
+ for (i = 0; i < 1024; ++i)
+ s += a[i] * b[i];
+ return s;
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/pr58551.c b/gcc/testsuite/c-c++-common/gomp/pr58551.c
new file mode 100644
index 00000000000..e2db70f9e86
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/pr58551.c
@@ -0,0 +1,33 @@
+/* PR middle-end/58551 */
+/* { dg-do compile } */
+/* { dg-options "-O0 -fopenmp" } */
+
+void
+foo (int *a)
+{
+ int i;
+ for (i = 0; i < 8; i++)
+ #pragma omp task
+ if (a[i])
+ __builtin_abort ();
+}
+
+void bar (int, int);
+
+void
+baz (int *a)
+{
+ int i;
+ for (i = 0; i < 8; i++)
+ #pragma omp task
+ if (a[i])
+ {
+ int j, k;
+ for (j = 0; j < 10; j++)
+ for (k = 0; k < 8; k++)
+ bar (j, k);
+ for (k = 0; k < 12; k++)
+ bar (-1, k);
+ __builtin_abort ();
+ }
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/sections1.c b/gcc/testsuite/c-c++-common/gomp/sections1.c
new file mode 100644
index 00000000000..8c8ab91f7f1
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/sections1.c
@@ -0,0 +1,73 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp" } */
+
+void bar (int);
+
+void
+foo ()
+{
+ #pragma omp sections
+ {
+ bar (1);
+ #pragma omp section
+ {
+ bar (2);
+ }
+ }
+ #pragma omp sections
+ {
+ #pragma omp section
+ bar (3);
+ #pragma omp section
+ {
+ bar (4);
+ bar (5);
+ }
+ }
+ #pragma omp sections
+ {
+ {
+ bar (6);
+ bar (7);
+ }
+ #pragma omp section
+ bar (8);
+ }
+ #pragma omp sections
+ {
+ #pragma omp section
+ {
+ bar (9);
+ }
+ #pragma omp section
+ bar (10);
+ #pragma omp section
+ bar (11);
+ }
+ #pragma omp sections
+ {
+ } /* { dg-error "expression before" } */
+ #pragma omp sections
+ {
+ bar (12);
+ bar (13); /* { dg-error "pragma omp section" } */
+ #pragma omp section
+ bar (14);
+ }
+ #pragma omp sections
+ {
+ #pragma omp section
+ } /* { dg-error "expression before" } */
+ #pragma omp sections
+ {
+ bar (15);
+ #pragma omp section
+ bar (16);
+ bar (17); /* { dg-error "pragma omp section" } */
+ }
+ #pragma omp sections
+ {
+ bar (18);
+ #pragma omp section
+ } /* { dg-error "expression before" } */
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/simd1.c b/gcc/testsuite/c-c++-common/gomp/simd1.c
new file mode 100644
index 00000000000..29e464ca035
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/simd1.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp" } */
+/* { dg-additional-options "-std=c99" { target c } } */
+
+extern int a[1024], b[1024], k, l, m;
+
+void
+foo ()
+{
+ int i;
+ #pragma omp simd safelen(16) aligned(a, b : 32)
+ for (i = 0; i < 1024; i++)
+ a[i] *= b[i];
+}
+
+void
+bar (int *p)
+{
+ int i;
+ #pragma omp simd safelen(16) aligned(a, p : 32) linear(k, l : m + 1)
+ for (i = 0; i < 1024; i++)
+ a[i] *= p[i], k += m + 1;
+}
+
+void
+baz (int *p)
+{
+ #pragma omp simd safelen(16) aligned(a, p : 32) linear(k, l : m + 1)
+ for (int i = 0; i < 1024; i++)
+ a[i] *= p[i], k += m + 1;
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/simd2.c b/gcc/testsuite/c-c++-common/gomp/simd2.c
new file mode 100644
index 00000000000..dda9c62d6d1
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/simd2.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp" } */
+/* { dg-additional-options "-std=c99" { target c } } */
+
+extern int a[13][13][13][13], k, l, m;
+
+void
+foo (int *q, float *p)
+{
+ int i, j, n, o;
+#pragma omp simd collapse (4) linear(k : m + 1) aligned(p, q)
+ for (i = 0; i < 13; i++)
+ for (j = 0; j < 13; j++)
+ for (n = 0; n < 13; n++)
+ for (o = 0; o < 13; o += 2)
+ q[k] *= p[k] + 7 * i + 14 * j + 21 * n + 28 * o, k += m + 1;
+}
+
+void
+bar (float *p)
+{
+ int i, j, n, o;
+#pragma omp simd collapse (4) linear(k : m + 1)
+ for (i = 0; i < 13; i++)
+ for (j = 0; j < 13; j++)
+ for (n = 0; n < 13; n++)
+ for (o = 0; o < 13; o += 2)
+ a[i][j][n][o] *= p[k], k += m + 1;
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/simd3.c b/gcc/testsuite/c-c++-common/gomp/simd3.c
new file mode 100644
index 00000000000..e8270fc4521
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/simd3.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp" } */
+/* { dg-additional-options "-std=c99" { target c } } */
+
+extern int a[13*13*13*13*2], b[1024], *k, l, m;
+
+void
+foo (int *q, float *p)
+{
+ int *i, *j, *n, *o;
+#pragma omp simd collapse (4) linear(k : m + 1) aligned(p, q)
+ for (i = &a[0]; i < &a[13*13*13*13*2]; i += 13*13*13*2)
+ for (j = &a[0]; j < &a[13*13*13*2]; j += 13*13*2)
+ for (n = &a[0]; n < &a[13*13*2]; n += 13*2)
+ for (o = &a[0]; o < &a[13*2]; o += 2)
+ q[k - &a[0]] *= p[k - &a[0]] + 7 * (i-&a[0]) + 14 * (j-&a[0]) + 21 * (n-&a[0]) + 28 * (o-&a[0]), k += m + 1;
+}
+
+void
+bar ()
+{
+ int *i;
+ #pragma omp simd safelen(16) aligned(a, b : 32)
+ for (i = &a[0]; i < &a[1024]; i++)
+ *i *= b[i - &a[0]];
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/simd4.c b/gcc/testsuite/c-c++-common/gomp/simd4.c
new file mode 100644
index 00000000000..37901b6a07f
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/simd4.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp" } */
+/* { dg-additional-options "-std=c99" { target c } } */
+
+struct S *p; /* { dg-error "forward declaration" "" { target c++ } } */
+float f;
+int j;
+
+void
+foo (void)
+{
+#pragma omp simd linear(p) linear(f : 1)
+ for (int i = 0; i < 10; i++)
+ ;
+#pragma omp simd linear(j : 7.0) /* { dg-error "step expression must be integral" } */
+ for (int i = 0; i < 10; i++)
+ ;
+}
+
+/* { dg-error "linear clause applied to" "" { target *-*-* } 12 } */
+/* { dg-error "(incomplete|undefined) type" "" { target *-*-* } 12 } */
diff --git a/gcc/testsuite/c-c++-common/gomp/simd5.c b/gcc/testsuite/c-c++-common/gomp/simd5.c
new file mode 100644
index 00000000000..a57896d8704
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/simd5.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp" } */
+/* { dg-additional-options "-std=c99" { target c } } */
+
+void baz (void) __attribute__((noreturn));
+
+void
+foo (int x)
+{
+ if (x)
+ #pragma omp simd
+ for (int i = 0; i < 10; i++)
+ baz ();
+#pragma omp simd collapse(3)
+ for (int i = 0; i < 10; i++)
+ for (int j = 0; j < 10; j++)
+ for (int k = 0; k < 10; k++)
+ baz ();
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/simd6.c b/gcc/testsuite/c-c++-common/gomp/simd6.c
new file mode 100644
index 00000000000..3a90c225e9e
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/simd6.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp" } */
+
+extern int a[1024];
+
+struct S { int i; } s;
+
+void
+f1 (int x, float f, int *p)
+{
+ int i;
+ #pragma omp simd aligned(x : 32) /* { dg-error "neither a pointer nor an array" } */
+ for (i = 0; i < 1024; i++)
+ a[i]++;
+ #pragma omp simd aligned(f) /* { dg-error "neither a pointer nor an array" } */
+ for (i = 0; i < 1024; i++)
+ a[i]++;
+ #pragma omp simd aligned(s : 16) /* { dg-error "neither a pointer nor an array" } */
+ for (i = 0; i < 1024; i++)
+ a[i]++;
+ #pragma omp simd aligned(a : 8)
+ for (i = 0; i < 1024; i++)
+ a[i]++;
+ #pragma omp simd aligned(p : 8)
+ for (i = 0; i < 1024; i++)
+ a[i]++;
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/single1.c b/gcc/testsuite/c-c++-common/gomp/single1.c
new file mode 100644
index 00000000000..c080a8804cf
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/single1.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp" } */
+
+void
+foo (int i)
+{
+ #pragma omp single copyprivate (i)
+ ;
+ #pragma omp single nowait
+ ;
+ #pragma omp single copyprivate (i) nowait /* { dg-error "clause must not be used together with" } */
+ ;
+ #pragma omp single nowait copyprivate (i) /* { dg-error "clause must not be used together with" } */
+ ;
+}
diff --git a/gcc/testsuite/c-c++-common/opaque-vector.c b/gcc/testsuite/c-c++-common/opaque-vector.c
index cad266e893b..bac3497be3e 100644
--- a/gcc/testsuite/c-c++-common/opaque-vector.c
+++ b/gcc/testsuite/c-c++-common/opaque-vector.c
@@ -16,7 +16,7 @@ void f ()
T_TEST(float)
T_TEST(double)
/* Avoid trouble with non-power-of-two sizes. */
-#if !defined(__i386__) && !defined(__x86_64__) && !defined(__m68k__) && !defined(__ia64__)
+#if !defined(__i386__) && !defined(__x86_64__) && !defined(__m68k__) && !defined(__ia64__) && !defined(__hppa__)
T_TEST(long double)
#endif
}
diff --git a/gcc/testsuite/c-c++-common/pr20318.c b/gcc/testsuite/c-c++-common/pr20318.c
new file mode 100644
index 00000000000..c6e9639fc4e
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pr20318.c
@@ -0,0 +1,3 @@
+/* { dg-do compile } */
+
+extern int f() __attribute__((returns_nonnull)); /* { dg-error "not returning a pointer" } */
diff --git a/gcc/testsuite/c-c++-common/pr57793.c b/gcc/testsuite/c-c++-common/pr57793.c
index d66fadaa1f7..f2719529ebb 100644
--- a/gcc/testsuite/c-c++-common/pr57793.c
+++ b/gcc/testsuite/c-c++-common/pr57793.c
@@ -3,8 +3,8 @@
struct A { unsigned a : 1; unsigned b : 1; };
struct B /* { dg-error "type .B. is too large" "" { target { c++ && ilp32 } } } */
{
- unsigned char c[0x40000000];
- unsigned char d[0x40000ff0];
+ unsigned char c[0x40000000]; /* { dg-error "size of array .c. is too large" "" { target { ! int32plus } } } */
+ unsigned char d[0x40000ff0];/* { dg-error "size of array .d. is too large" "" { target { ! int32plus } } } */
struct A e;
}; /* { dg-error "type .struct B. is too large" "" { target { c && ilp32 } } } */
diff --git a/gcc/testsuite/c-c++-common/torture/pr58794-1.c b/gcc/testsuite/c-c++-common/torture/pr58794-1.c
new file mode 100644
index 00000000000..175629fec90
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/pr58794-1.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+
+struct S0
+{
+ int f;
+};
+
+struct S1
+{
+ struct S0 f1;
+ volatile int f2;
+};
+
+struct S2
+{
+ struct S1 g;
+} a, b;
+
+static int *c[1][2] = {{0, (int *)&a.g.f2}};
+static int d;
+
+int
+main ()
+{
+ for (d = 0; d < 1; d++)
+ for (b.g.f1.f = 0; b.g.f1.f < 1; b.g.f1.f++)
+ *c[b.g.f1.f][d + 1] = 0;
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/torture/pr58794-2.c b/gcc/testsuite/c-c++-common/torture/pr58794-2.c
new file mode 100644
index 00000000000..767798806db
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/torture/pr58794-2.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+
+struct S
+{
+ volatile int f;
+} a;
+
+unsigned int b;
+
+static int *c[1][2] = {{0, (int *)&a.f}};
+static unsigned int d;
+
+int
+main ()
+{
+ for (; d < 1; d++)
+ for (; b < 1; b++)
+ *c[b][d + 1] = 0;
+
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/ubsan/div-by-zero-5.c b/gcc/testsuite/c-c++-common/ubsan/div-by-zero-5.c
new file mode 100644
index 00000000000..7a28bacd14b
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ubsan/div-by-zero-5.c
@@ -0,0 +1,8 @@
+/* { dg-do compile} */
+/* { dg-options "-fsanitize=integer-divide-by-zero" } */
+
+void
+foo (void)
+{
+ int A[-2 / -1] = {};
+}
diff --git a/gcc/testsuite/c-c++-common/ubsan/shift-4.c b/gcc/testsuite/c-c++-common/ubsan/shift-4.c
new file mode 100644
index 00000000000..239c0131fb9
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ubsan/shift-4.c
@@ -0,0 +1,14 @@
+/* { dg-do run } */
+/* { dg-options "-fsanitize=shift -w" } */
+
+struct S { unsigned long long int b:40; } s;
+
+int
+main ()
+{
+ s.b = 2;
+ s.b <<= 120;
+ return 0;
+}
+
+/* { dg-output "shift exponent 120 is too large\[^\n\r]*(\n|\r\n|\r)" } */
diff --git a/gcc/testsuite/c-c++-common/ubsan/shift-5.c b/gcc/testsuite/c-c++-common/ubsan/shift-5.c
new file mode 100644
index 00000000000..6f9c52a7288
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ubsan/shift-5.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-fsanitize=shift -w" } */
+/* { dg-shouldfail "ubsan" } */
+
+int x;
+int
+foo (void)
+{
+ /* None of the following should pass. */
+ switch (x)
+ {
+ case 1 >> -1:
+/* { dg-error "case label does not reduce to an integer constant" "" {target c } 12 } */
+/* { dg-error "is not a constant expression" "" { target c++ } 12 } */
+ case -1 >> -1:
+/* { dg-error "case label does not reduce to an integer constant" "" {target c } 15 } */
+/* { dg-error "is not a constant expression" "" { target c++ } 15 } */
+ case 1 << -1:
+/* { dg-error "case label does not reduce to an integer constant" "" {target c } 18 } */
+/* { dg-error "is not a constant expression" "" { target c++ } 18 } */
+ case -1 << -1:
+/* { dg-error "case label does not reduce to an integer constant" "" {target c } 21 } */
+/* { dg-error "is not a constant expression" "" { target c++ } 21 } */
+ case -1 >> 200:
+/* { dg-error "case label does not reduce to an integer constant" "" {target c } 24 } */
+/* { dg-error "is not a constant expression" "" { target c++ } 24 } */
+ case 1 << 200:
+/* { dg-error "case label does not reduce to an integer constant" "" {target c } 27 } */
+/* { dg-error "is not a constant expression" "" { target c++ } 27 } */
+ return 1;
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/ubsan/shift-6.c b/gcc/testsuite/c-c++-common/ubsan/shift-6.c
new file mode 100644
index 00000000000..a0e2e20acc1
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ubsan/shift-6.c
@@ -0,0 +1,30 @@
+/* PR sanitizer/58413 */
+/* { dg-do run { target int32plus } } */
+/* { dg-options "-fsanitize=shift -w" } */
+
+int x = 7;
+int
+main (void)
+{
+ /* All of the following should pass. */
+ int A[128 >> 5] = {};
+ int B[128 << 5] = {};
+
+ static int e =
+ ((int)
+ (0x00000000 | ((31 & ((1 << (4)) - 1)) << (((15) + 6) + 4)) |
+ ((0) << ((15) + 6)) | ((0) << (15))));
+
+ if (e != 503316480)
+ __builtin_abort ();
+
+ switch (x)
+ {
+ case 1 >> 4:
+ case 1 << 4:
+ case 128 << (4 + 1):
+ case 128 >> (4 + 1):
+ return 1;
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/ubsan/vla-1.c b/gcc/testsuite/c-c++-common/ubsan/vla-1.c
new file mode 100644
index 00000000000..6c1d81e9d22
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ubsan/vla-1.c
@@ -0,0 +1,48 @@
+/* { dg-do run } */
+/* { dg-options "-fsanitize=vla-bound -w" } */
+
+static int
+bar (void)
+{
+ return -42;
+}
+
+typedef long int V;
+int
+main (void)
+{
+ int x = -1;
+ double di = -3.2;
+ V v = -666;
+
+ int a[x];
+ int aa[x][x];
+ int aaa[x][x][x];
+ int b[x - 4];
+ int c[(int) di];
+ int d[1 + x];
+ int e[1 ? x : -1];
+ int f[++x];
+ int g[(signed char) --x];
+ int h[(++x, --x, x)];
+ int i[v];
+ int j[bar ()];
+
+ return 0;
+}
+
+/* { dg-output "variable length array bound evaluates to non-positive value -1(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*variable length array bound evaluates to non-positive value -1(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*variable length array bound evaluates to non-positive value -1(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*variable length array bound evaluates to non-positive value -1(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*variable length array bound evaluates to non-positive value -1(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*variable length array bound evaluates to non-positive value -1(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*variable length array bound evaluates to non-positive value -5(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*variable length array bound evaluates to non-positive value -3(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*variable length array bound evaluates to non-positive value 0(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*variable length array bound evaluates to non-positive value -1(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*variable length array bound evaluates to non-positive value 0(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*variable length array bound evaluates to non-positive value -1(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*variable length array bound evaluates to non-positive value -1(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*variable length array bound evaluates to non-positive value -666(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*variable length array bound evaluates to non-positive value -42(\n|\r\n|\r)" } */
diff --git a/gcc/testsuite/c-c++-common/ubsan/vla-2.c b/gcc/testsuite/c-c++-common/ubsan/vla-2.c
new file mode 100644
index 00000000000..2fbeb7113b8
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ubsan/vla-2.c
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+/* { dg-options "-fsanitize=vla-bound -w" } */
+
+int
+main (void)
+{
+ const int t = 0;
+ struct s {
+ int x;
+ /* Don't instrument this one. */
+ int g[t];
+ };
+
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/ubsan/vla-3.c b/gcc/testsuite/c-c++-common/ubsan/vla-3.c
new file mode 100644
index 00000000000..20dd38b79a7
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ubsan/vla-3.c
@@ -0,0 +1,16 @@
+/* { dg-do run } */
+/* { dg-options "-fsanitize=vla-bound -w" } */
+
+/* Don't instrument the arrays here. */
+int
+foo (int n, int a[])
+{
+ return a[n - 1];
+}
+
+int
+main (void)
+{
+ int a[6] = { };
+ return foo (3, a);
+}
diff --git a/gcc/testsuite/c-c++-common/ubsan/vla-4.c b/gcc/testsuite/c-c++-common/ubsan/vla-4.c
new file mode 100644
index 00000000000..3f7dd1de50c
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ubsan/vla-4.c
@@ -0,0 +1,13 @@
+/* { dg-do run } */
+/* { dg-options "-fsanitize=vla-bound" } */
+
+int
+main (void)
+{
+ int x = 1;
+ /* Check that the size of an array is evaluated only once. */
+ int a[++x];
+ if (x != 2)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/asan/asan_test.cc b/gcc/testsuite/g++.dg/asan/asan_test.cc
index 76b6e693498..2df8c62cbb1 100644
--- a/gcc/testsuite/g++.dg/asan/asan_test.cc
+++ b/gcc/testsuite/g++.dg/asan/asan_test.cc
@@ -204,16 +204,6 @@ TEST(AddressSanitizer, BitFieldNegativeTest) {
delete Ident(x);
}
-TEST(AddressSanitizer, OutOfMemoryTest) {
- size_t size = SANITIZER_WORDSIZE == 64 ? (size_t)(1ULL << 48) : (0xf0000000);
- EXPECT_EQ(0, realloc(0, size));
- EXPECT_EQ(0, realloc(0, ~Ident(0)));
- EXPECT_EQ(0, malloc(size));
- EXPECT_EQ(0, malloc(~Ident(0)));
- EXPECT_EQ(0, calloc(1, size));
- EXPECT_EQ(0, calloc(1, ~Ident(0)));
-}
-
#if ASAN_NEEDS_SEGV
namespace {
@@ -497,42 +487,6 @@ TEST(AddressSanitizer, ManyStackObjectsTest) {
EXPECT_DEATH(Ident(ZZZ)[-1] = 0, ASAN_PCRE_DOTALL "XXX.*YYY.*ZZZ");
}
-NOINLINE static void Frame0(int frame, char *a, char *b, char *c) {
- char d[4] = {0};
- char *D = Ident(d);
- switch (frame) {
- case 3: a[5]++; break;
- case 2: b[5]++; break;
- case 1: c[5]++; break;
- case 0: D[5]++; break;
- }
-}
-NOINLINE static void Frame1(int frame, char *a, char *b) {
- char c[4] = {0}; Frame0(frame, a, b, c);
- break_optimization(0);
-}
-NOINLINE static void Frame2(int frame, char *a) {
- char b[4] = {0}; Frame1(frame, a, b);
- break_optimization(0);
-}
-NOINLINE static void Frame3(int frame) {
- char a[4] = {0}; Frame2(frame, a);
- break_optimization(0);
-}
-
-TEST(AddressSanitizer, GuiltyStackFrame0Test) {
- EXPECT_DEATH(Frame3(0), "located .*in frame <.*Frame0");
-}
-TEST(AddressSanitizer, GuiltyStackFrame1Test) {
- EXPECT_DEATH(Frame3(1), "located .*in frame <.*Frame1");
-}
-TEST(AddressSanitizer, GuiltyStackFrame2Test) {
- EXPECT_DEATH(Frame3(2), "located .*in frame <.*Frame2");
-}
-TEST(AddressSanitizer, GuiltyStackFrame3Test) {
- EXPECT_DEATH(Frame3(3), "located .*in frame <.*Frame3");
-}
-
NOINLINE void LongJmpFunc1(jmp_buf buf) {
// create three red zones for these two stack objects.
int a;
diff --git a/gcc/testsuite/g++.dg/cpp0x/Wliteral-suffix.C b/gcc/testsuite/g++.dg/cpp0x/Wliteral-suffix.C
index 39a8353561c..520d77ef5c5 100644
--- a/gcc/testsuite/g++.dg/cpp0x/Wliteral-suffix.C
+++ b/gcc/testsuite/g++.dg/cpp0x/Wliteral-suffix.C
@@ -1,5 +1,5 @@
// { dg-do run }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// Make sure -Wliteral-suffix is enabled by default and
// triggers as expected.
diff --git a/gcc/testsuite/g++.dg/cpp0x/Wzero-as-null-pointer-constant-1.C b/gcc/testsuite/g++.dg/cpp0x/Wzero-as-null-pointer-constant-1.C
index aad273792ac..9acfafe2be9 100644
--- a/gcc/testsuite/g++.dg/cpp0x/Wzero-as-null-pointer-constant-1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/Wzero-as-null-pointer-constant-1.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x -Wzero-as-null-pointer-constant" }
+// { dg-options "-std=c++11 -Wzero-as-null-pointer-constant" }
struct A;
diff --git a/gcc/testsuite/g++.dg/cpp0x/__func__.C b/gcc/testsuite/g++.dg/cpp0x/__func__.C
index 1ac90651533..a7d5633614a 100644
--- a/gcc/testsuite/g++.dg/cpp0x/__func__.C
+++ b/gcc/testsuite/g++.dg/cpp0x/__func__.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x -pedantic" }
+// { dg-options "-std=c++11 -pedantic" }
const char* foo()
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/access01.C b/gcc/testsuite/g++.dg/cpp0x/access01.C
index 43e5e863720..a6c86016146 100644
--- a/gcc/testsuite/g++.dg/cpp0x/access01.C
+++ b/gcc/testsuite/g++.dg/cpp0x/access01.C
@@ -1,5 +1,5 @@
// PR c++/49042
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template <class T>
class A
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-0.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-0.C
index f38f9932b44..7f5d361a627 100644
--- a/gcc/testsuite/g++.dg/cpp0x/alias-decl-0.C
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-0.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<template<class> class TT> struct X { };
template<class> struct Y { };
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-1.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-1.C
index cbba90fa133..e3704d39f4a 100644
--- a/gcc/testsuite/g++.dg/cpp0x/alias-decl-1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-1.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// These also represent tests for printing alias declarations and
// their instantiations.
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-10.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-10.C
index 733e791c2bc..b4e80f411c0 100644
--- a/gcc/testsuite/g++.dg/cpp0x/alias-decl-10.C
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-10.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template <class T> using Ptr = T*;
Ptr<unsigned>; // { dg-error "does not declare anything" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-11.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-11.C
index 43ef7ba45e6..80795a8304d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/alias-decl-11.C
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-11.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
namespace N
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-12.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-12.C
index 11c26865d9e..758d180e1f9 100644
--- a/gcc/testsuite/g++.dg/cpp0x/alias-decl-12.C
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-12.C
@@ -1,4 +1,4 @@
// Origin: PR c++/51027
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
using INT = int // { dg-error "expected|;|at end of input" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-13.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-13.C
index 8555154c634..a7a55ddc168 100644
--- a/gcc/testsuite/g++.dg/cpp0x/alias-decl-13.C
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-13.C
@@ -1,5 +1,5 @@
// Origin PR c++/51191
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template< class T >
class ClassTemplate {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-14.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-14.C
index 1a998022adc..9e6b19cde93 100644
--- a/gcc/testsuite/g++.dg/cpp0x/alias-decl-14.C
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-14.C
@@ -1,5 +1,5 @@
// Origin: PR c++/51145
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
struct A {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-15.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-15.C
index b23e4029f79..6ef8bf7eb4a 100644
--- a/gcc/testsuite/g++.dg/cpp0x/alias-decl-15.C
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-15.C
@@ -1,5 +1,5 @@
// Origin PR c++/51194
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<class U, class V> //#1
struct foo {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-2.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-2.C
index 6b5b42f7fde..d8a71a48107 100644
--- a/gcc/testsuite/g++.dg/cpp0x/alias-decl-2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-2.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<class T> struct S0 {};
template<class T> using AS0 = S0<T>;
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-3.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-3.C
index 5484efce19e..072cfb1f03a 100644
--- a/gcc/testsuite/g++.dg/cpp0x/alias-decl-3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-3.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// Exercise some member alias templates ...
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-4.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-4.C
index 876944e23c3..c7da542189f 100644
--- a/gcc/testsuite/g++.dg/cpp0x/alias-decl-4.C
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-4.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// [temp.alias]/3:
// The type-id in an alias template declaration shall not refer
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-5.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-5.C
index 1a4cbd5e5bc..f57a67a0459 100644
--- a/gcc/testsuite/g++.dg/cpp0x/alias-decl-5.C
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-5.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// alias template of a partial specialization
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-6.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-6.C
index f60b2ea7fc0..11440385c33 100644
--- a/gcc/testsuite/g++.dg/cpp0x/alias-decl-6.C
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-6.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// Alias template of non-class types.
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-7.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-7.C
index 96c349a0da6..a1a6a362ec3 100644
--- a/gcc/testsuite/g++.dg/cpp0x/alias-decl-7.C
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-7.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// Add arguments to unbound template template parameter.
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-8.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-8.C
index c926df7539b..80c2fdd6743 100644
--- a/gcc/testsuite/g++.dg/cpp0x/alias-decl-8.C
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-8.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
struct A {
template <class U> using C = U;
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-9.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-9.C
index dcf642d7683..b4a23d0b853 100644
--- a/gcc/testsuite/g++.dg/cpp0x/alias-decl-9.C
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-9.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template <class T>
struct A {
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-debug-0.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-debug-0.C
index a9aae374947..04e9b7065bf 100644
--- a/gcc/testsuite/g++.dg/cpp0x/alias-decl-debug-0.C
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-debug-0.C
@@ -1,6 +1,6 @@
// Origin: PR c++/51032
// { dg-skip-if "No stabs" { aarch64*-*-* mmix-*-* *-*-aix* alpha*-*-* hppa*64*-*-* ia64-*-* *-*-vxworks* } { "*" } { "" } }
-// { dg-options "-std=c++0x -gstabs+" }
+// { dg-options "-std=c++11 -gstabs+" }
template <class C>
struct A {
diff --git a/gcc/testsuite/g++.dg/cpp0x/alignof.C b/gcc/testsuite/g++.dg/cpp0x/alignof.C
index 8e8f715cdf3..a0a556131ca 100644
--- a/gcc/testsuite/g++.dg/cpp0x/alignof.C
+++ b/gcc/testsuite/g++.dg/cpp0x/alignof.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
int main(void)
{
static_assert(alignof(int) == __alignof(int), "alignof(int) does not equal __alignof(int)");
diff --git a/gcc/testsuite/g++.dg/cpp0x/alignof2.C b/gcc/testsuite/g++.dg/cpp0x/alignof2.C
index 7c5aad3de29..9683a1eb613 100644
--- a/gcc/testsuite/g++.dg/cpp0x/alignof2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/alignof2.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-std=c++0x -pedantic" }
+// { dg-options "-std=c++11 -pedantic" }
int main(void)
{
alignof(int); //ok with a type but not with an expression
diff --git a/gcc/testsuite/g++.dg/cpp0x/alignof3.C b/gcc/testsuite/g++.dg/cpp0x/alignof3.C
index 50c6ac915e1..75eff1f8ae0 100644
--- a/gcc/testsuite/g++.dg/cpp0x/alignof3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/alignof3.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-std=c++0x -pedantic" }
+// { dg-options "-std=c++11 -pedantic" }
int main(void)
{
alignof(void (void)); // { dg-warning "function type" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/alignof4.C b/gcc/testsuite/g++.dg/cpp0x/alignof4.C
index 92d636faf09..a05baa89295 100644
--- a/gcc/testsuite/g++.dg/cpp0x/alignof4.C
+++ b/gcc/testsuite/g++.dg/cpp0x/alignof4.C
@@ -1,5 +1,5 @@
// PR c++/51316
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
int main()
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/auto10.C b/gcc/testsuite/g++.dg/cpp0x/auto10.C
index 9b89291d640..82e98ff8adc 100644
--- a/gcc/testsuite/g++.dg/cpp0x/auto10.C
+++ b/gcc/testsuite/g++.dg/cpp0x/auto10.C
@@ -1,6 +1,6 @@
// Positive test for auto
// { dg-do run }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
#include <typeinfo>
extern "C" void abort();
diff --git a/gcc/testsuite/g++.dg/cpp0x/auto11.C b/gcc/testsuite/g++.dg/cpp0x/auto11.C
index bd21daef0c6..05f5f5c20ef 100644
--- a/gcc/testsuite/g++.dg/cpp0x/auto11.C
+++ b/gcc/testsuite/g++.dg/cpp0x/auto11.C
@@ -1,5 +1,5 @@
// PR c++/38256
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<int> struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/auto14.C b/gcc/testsuite/g++.dg/cpp0x/auto14.C
index cb2c4e0351a..726fa05651d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/auto14.C
+++ b/gcc/testsuite/g++.dg/cpp0x/auto14.C
@@ -1,5 +1,5 @@
// PR c++/40306, c++/40307
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// { dg-do run }
template< typename T >
diff --git a/gcc/testsuite/g++.dg/cpp0x/auto15.C b/gcc/testsuite/g++.dg/cpp0x/auto15.C
index b23e1e2fd6f..1dca688a6ed 100644
--- a/gcc/testsuite/g++.dg/cpp0x/auto15.C
+++ b/gcc/testsuite/g++.dg/cpp0x/auto15.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template< typename Fn > struct function;
diff --git a/gcc/testsuite/g++.dg/cpp0x/auto16.C b/gcc/testsuite/g++.dg/cpp0x/auto16.C
index 1b4ae8f82b2..3610662b951 100644
--- a/gcc/testsuite/g++.dg/cpp0x/auto16.C
+++ b/gcc/testsuite/g++.dg/cpp0x/auto16.C
@@ -1,5 +1,5 @@
// PR c++/40619
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<typename U> struct X {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/auto17.C b/gcc/testsuite/g++.dg/cpp0x/auto17.C
index 03608d33ac6..f04b89f30ce 100644
--- a/gcc/testsuite/g++.dg/cpp0x/auto17.C
+++ b/gcc/testsuite/g++.dg/cpp0x/auto17.C
@@ -1,5 +1,5 @@
// PR c++/42567
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<typename B>
struct A {
diff --git a/gcc/testsuite/g++.dg/cpp0x/auto18.C b/gcc/testsuite/g++.dg/cpp0x/auto18.C
index 0a59242ab29..a5c521c685b 100644
--- a/gcc/testsuite/g++.dg/cpp0x/auto18.C
+++ b/gcc/testsuite/g++.dg/cpp0x/auto18.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
void f()
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/auto19.C b/gcc/testsuite/g++.dg/cpp0x/auto19.C
index f7099028710..66c0cfe0528 100644
--- a/gcc/testsuite/g++.dg/cpp0x/auto19.C
+++ b/gcc/testsuite/g++.dg/cpp0x/auto19.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct Explicit {
Explicit() = default; // Line 2
diff --git a/gcc/testsuite/g++.dg/cpp0x/auto2.C b/gcc/testsuite/g++.dg/cpp0x/auto2.C
index 626e9e245d4..cf6bcffbedf 100644
--- a/gcc/testsuite/g++.dg/cpp0x/auto2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/auto2.C
@@ -1,6 +1,6 @@
// Positive test for auto
// { dg-do run }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
#include <typeinfo>
extern "C" void abort();
diff --git a/gcc/testsuite/g++.dg/cpp0x/auto20.C b/gcc/testsuite/g++.dg/cpp0x/auto20.C
index 90f875114a0..8561b3d4a8a 100644
--- a/gcc/testsuite/g++.dg/cpp0x/auto20.C
+++ b/gcc/testsuite/g++.dg/cpp0x/auto20.C
@@ -1,6 +1,6 @@
// Test for proper non-deduced context handling of the initializer
// for an auto declaration/new.
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct with_apply
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/auto21.C b/gcc/testsuite/g++.dg/cpp0x/auto21.C
index 1cbcac58d6a..1d022b390e8 100644
--- a/gcc/testsuite/g++.dg/cpp0x/auto21.C
+++ b/gcc/testsuite/g++.dg/cpp0x/auto21.C
@@ -1,5 +1,5 @@
// Origin PR c++/47208
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
constexpr auto list = { }; // { dg-error "deducing from brace-enclosed initializer list requires #include <initializer_list>" }
static const int l = list.size();
diff --git a/gcc/testsuite/g++.dg/cpp0x/auto22.C b/gcc/testsuite/g++.dg/cpp0x/auto22.C
index 66630e5367f..30111783624 100644
--- a/gcc/testsuite/g++.dg/cpp0x/auto22.C
+++ b/gcc/testsuite/g++.dg/cpp0x/auto22.C
@@ -1,5 +1,5 @@
// PR c++/47999
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
int& identity(int& i)
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/auto23.C b/gcc/testsuite/g++.dg/cpp0x/auto23.C
index 49b5a0eb9e8..799445c8c3f 100644
--- a/gcc/testsuite/g++.dg/cpp0x/auto23.C
+++ b/gcc/testsuite/g++.dg/cpp0x/auto23.C
@@ -1,4 +1,4 @@
// PR c++/46245
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<auto f()->int> struct A { };
diff --git a/gcc/testsuite/g++.dg/cpp0x/auto24.C b/gcc/testsuite/g++.dg/cpp0x/auto24.C
index b024ad5b2ab..3911c5887d4 100644
--- a/gcc/testsuite/g++.dg/cpp0x/auto24.C
+++ b/gcc/testsuite/g++.dg/cpp0x/auto24.C
@@ -1,5 +1,5 @@
// PR c++/48599
-// { dg-options "-std=c++0x -pedantic-errors" }
+// { dg-options "-std=c++11 -pedantic-errors" }
int v[1];
auto (*p)[1] = &v; // { dg-error "array of .auto" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/auto25.C b/gcc/testsuite/g++.dg/cpp0x/auto25.C
index 2917c0e1978..0153d9c96fb 100644
--- a/gcc/testsuite/g++.dg/cpp0x/auto25.C
+++ b/gcc/testsuite/g++.dg/cpp0x/auto25.C
@@ -1,5 +1,5 @@
// PR c++/42056
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<int> struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/auto26.C b/gcc/testsuite/g++.dg/cpp0x/auto26.C
index 6e55aa451ac..9d0c89426d3 100644
--- a/gcc/testsuite/g++.dg/cpp0x/auto26.C
+++ b/gcc/testsuite/g++.dg/cpp0x/auto26.C
@@ -1,5 +1,5 @@
// PR c++/43321
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template <class T>
void f(T t)
diff --git a/gcc/testsuite/g++.dg/cpp0x/auto28.C b/gcc/testsuite/g++.dg/cpp0x/auto28.C
index 8d250166a8c..1d6f0d0293d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/auto28.C
+++ b/gcc/testsuite/g++.dg/cpp0x/auto28.C
@@ -1,4 +1,4 @@
// PR c++/51404
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
int i = auto().x; // { dg-error "invalid use of" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/auto39.C b/gcc/testsuite/g++.dg/cpp0x/auto39.C
new file mode 100644
index 00000000000..dfa1fb4e9e8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/auto39.C
@@ -0,0 +1,6 @@
+// PR c++/58560
+// { dg-do compile { target c++11 } }
+
+typedef auto T; // { dg-error "typedef declared 'auto'" }
+
+void foo() { T(); }
diff --git a/gcc/testsuite/g++.dg/cpp0x/auto4.C b/gcc/testsuite/g++.dg/cpp0x/auto4.C
index d47bca4369d..71b0dede29a 100644
--- a/gcc/testsuite/g++.dg/cpp0x/auto4.C
+++ b/gcc/testsuite/g++.dg/cpp0x/auto4.C
@@ -1,6 +1,6 @@
// Testcase for deduction of std::initializer_list for auto.
// { dg-do run }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
#include <typeinfo>
#include <initializer_list>
diff --git a/gcc/testsuite/g++.dg/cpp0x/auto40.C b/gcc/testsuite/g++.dg/cpp0x/auto40.C
new file mode 100644
index 00000000000..287191e5910
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/auto40.C
@@ -0,0 +1,11 @@
+// PR c++/58888
+// { dg-do compile { target c++11 } }
+
+#include <initializer_list>
+
+struct A
+{
+ static constexpr auto b{1.0};
+};
+
+constexpr decltype(A::b) A::b;
diff --git a/gcc/testsuite/g++.dg/cpp0x/auto5.C b/gcc/testsuite/g++.dg/cpp0x/auto5.C
index ebe2df22e6f..b5dd0d8a02c 100644
--- a/gcc/testsuite/g++.dg/cpp0x/auto5.C
+++ b/gcc/testsuite/g++.dg/cpp0x/auto5.C
@@ -1,5 +1,5 @@
// Testcase for non-dependent auto in templates
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/auto7.C b/gcc/testsuite/g++.dg/cpp0x/auto7.C
index 3b3b8290168..d795c23baa5 100644
--- a/gcc/testsuite/g++.dg/cpp0x/auto7.C
+++ b/gcc/testsuite/g++.dg/cpp0x/auto7.C
@@ -1,6 +1,6 @@
// PR c++/37965
// Negative test for auto
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
auto i = 6;
auto j; // { dg-error "has no initializer" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/auto9.C b/gcc/testsuite/g++.dg/cpp0x/auto9.C
index f357f2b9663..ee6497921cd 100644
--- a/gcc/testsuite/g++.dg/cpp0x/auto9.C
+++ b/gcc/testsuite/g++.dg/cpp0x/auto9.C
@@ -1,7 +1,7 @@
// PR c++/37962
// Negative test for auto
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
#include <typeinfo>
#include <stdarg.h>
diff --git a/gcc/testsuite/g++.dg/cpp0x/bind.C b/gcc/testsuite/g++.dg/cpp0x/bind.C
index 42a2ac203db..a0ce6b8ff62 100644
--- a/gcc/testsuite/g++.dg/cpp0x/bind.C
+++ b/gcc/testsuite/g++.dg/cpp0x/bind.C
@@ -1,4 +1,4 @@
-// { dg-options "--std=c++0x" }
+// { dg-options "--std=c++11" }
struct S{};
void f(S&&);
diff --git a/gcc/testsuite/g++.dg/cpp0x/bracket1.C b/gcc/testsuite/g++.dg/cpp0x/bracket1.C
index dfb5bf4ea40..abda4034374 100644
--- a/gcc/testsuite/g++.dg/cpp0x/bracket1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/bracket1.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename T>
struct list {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/bracket2.C b/gcc/testsuite/g++.dg/cpp0x/bracket2.C
index 300015d01e6..65cf2699c92 100644
--- a/gcc/testsuite/g++.dg/cpp0x/bracket2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/bracket2.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<int i> class X { /* ... */ };
X< 1>2 > x1; // // { dg-error "numeric constant" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/bracket4.C b/gcc/testsuite/g++.dg/cpp0x/bracket4.C
index 0e1985ceff9..e6381c74c84 100644
--- a/gcc/testsuite/g++.dg/cpp0x/bracket4.C
+++ b/gcc/testsuite/g++.dg/cpp0x/bracket4.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<typename T>
struct vector {
};
diff --git a/gcc/testsuite/g++.dg/cpp0x/cast-bug.C b/gcc/testsuite/g++.dg/cpp0x/cast-bug.C
index 211f88b2b19..5485611dc65 100644
--- a/gcc/testsuite/g++.dg/cpp0x/cast-bug.C
+++ b/gcc/testsuite/g++.dg/cpp0x/cast-bug.C
@@ -1,4 +1,4 @@
-// { dg-options "--std=c++0x" }
+// { dg-options "--std=c++11" }
struct S
{
S();
diff --git a/gcc/testsuite/g++.dg/cpp0x/cast.C b/gcc/testsuite/g++.dg/cpp0x/cast.C
index 9cf97e688b0..2f109762c26 100644
--- a/gcc/testsuite/g++.dg/cpp0x/cast.C
+++ b/gcc/testsuite/g++.dg/cpp0x/cast.C
@@ -3,7 +3,7 @@
// Test cast from lvalue to rvalue
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// { dg-skip-if "packed attribute missing for struct one" { "epiphany-*-*" } { "*" } { "" } }
template <bool> struct sa;
diff --git a/gcc/testsuite/g++.dg/cpp0x/collapse-bug.C b/gcc/testsuite/g++.dg/cpp0x/collapse-bug.C
index 02a59cd1d21..93f2c9fc9b6 100644
--- a/gcc/testsuite/g++.dg/cpp0x/collapse-bug.C
+++ b/gcc/testsuite/g++.dg/cpp0x/collapse-bug.C
@@ -1,4 +1,4 @@
-// { dg-options "--std=c++0x" }
+// { dg-options "--std=c++11" }
template<typename T, typename U> struct same_type;
template<typename T> struct same_type<T, T> {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/collapse.C b/gcc/testsuite/g++.dg/cpp0x/collapse.C
index 96c32732461..98435f159d7 100644
--- a/gcc/testsuite/g++.dg/cpp0x/collapse.C
+++ b/gcc/testsuite/g++.dg/cpp0x/collapse.C
@@ -1,4 +1,4 @@
-// { dg-options "--std=c++0x" }
+// { dg-options "--std=c++11" }
template<typename T, typename U> struct same_type;
template<typename T> struct same_type<T, T> {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-46336.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-46336.C
index 3c51c2cbf54..4268a6ba43a 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-46336.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-46336.C
@@ -1,5 +1,5 @@
// PR c++/46336
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
extern "C" {
enum A { };
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-46420.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-46420.C
index 757a6e315b0..c59949aa68e 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-46420.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-46420.C
@@ -1,5 +1,5 @@
// PR c++/46420
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<typename> class vector { };
struct A{};
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-47570.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-47570.C
index c60ba865862..53c20a62382 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-47570.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-47570.C
@@ -1,5 +1,5 @@
// PR c++/47570
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
unsigned int constexpr one()
{ return 1; }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-47969.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-47969.C
index c950a3642fe..140965150a1 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-47969.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-47969.C
@@ -1,5 +1,5 @@
// PR c++/47969
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-48089.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-48089.C
index a6cf4080756..039411ef58d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-48089.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-48089.C
@@ -1,5 +1,5 @@
// PR c++/48089
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
// bang is ill-formed (diagnostic required) because its initializer is
// non-constant, because it uses the value of an uninitialized object.
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-49776.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-49776.C
index 3fe3dcb86c1..8f407191192 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-49776.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-49776.C
@@ -1,5 +1,5 @@
// PR c++/49776
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct s
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-abi1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-abi1.C
index e83f142300a..c596a4386a9 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-abi1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-abi1.C
@@ -1,5 +1,5 @@
// PR c++/47301
-// { dg-options "-std=c++0x -fabi-version=1" }
+// { dg-options "-std=c++11 -fabi-version=1" }
struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-access.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-access.C
index ee5fc9854fc..3cde1efa914 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-access.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-access.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
class base
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr.C
index 36939e1afe1..db95e569492 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<class T>
constexpr T do_get(T* x, int n) {
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr2.C
index 7cf733445d9..23c6ebdaf6a 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr2.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<class T>
struct IsNegative {
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr3.C
index f84cb525774..a282b85490b 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr3.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
constexpr bool is_negative(int x) {
return x < 0;
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr4.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr4.C
index 697d2d9f708..f530265863d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr4.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr4.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
constexpr const int do_last(const int* x, int n) {
return x[n - 1];
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr5.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr5.C
index d58f254f6c8..20b6344e490 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr5.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr5.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<class T>
constexpr T do_last(T* x, int n) {
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr6.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr6.C
index 17dd6e50be9..c307edba6e1 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr6.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr6.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
typedef decltype(sizeof(char)) size_type;
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr7.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr7.C
index 44775c0703c..7c83178a9b5 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr7.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr7.C
@@ -1,5 +1,5 @@
// PR c++/49290
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
typedef unsigned T;
struct S
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-array-tparm.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-array-tparm.C
index c17090cc3b4..4b6a3df1892 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-array-tparm.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-array-tparm.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template <const int I[2]> struct A { int ir[I[0]]; };
extern constexpr int ar[2] = { 1, 2 };
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-array.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-array.C
index e37400a8bda..f2c8ddcc966 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-array.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-array.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
// { dg-final { scan-assembler-not "static_initialization" } }
struct A
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-array2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-array2.C
index 9577f75d9fd..4f556ae6661 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-array2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-array2.C
@@ -1,5 +1,5 @@
// PR c++/46348
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<__SIZE_TYPE__ _Nw>
struct _Base
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-array3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-array3.C
index 145a4307e36..38314ec0f5f 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-array3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-array3.C
@@ -1,5 +1,5 @@
// PR c++/48132
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct C
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-array4.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-array4.C
index 9aeb75d6b06..0658be9011f 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-array4.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-array4.C
@@ -1,5 +1,5 @@
// PR c++/49924
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A { constexpr A() { } };
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-attribute.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-attribute.C
index ac85c076d3e..fef7007cf0c 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-attribute.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-attribute.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
//A few constexpr's
constexpr int foo() { return __alignof__(int); }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-auto.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-auto.C
index ddf0da0b9b4..60bd5589745 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-auto.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-auto.C
@@ -1,2 +1,2 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
constexpr auto value = 0;
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-base.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-base.C
index 774df318ab6..b159bb8dba4 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-base.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-base.C
@@ -1,5 +1,5 @@
// Test base/member class and static_assert with constexpr
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A {
int i;
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-base2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-base2.C
index 3ea75432a22..9849f206c54 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-base2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-base2.C
@@ -1,5 +1,5 @@
// PR c++/46293
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-base3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-base3.C
index cffe9ea240c..ec6646bc560 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-base3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-base3.C
@@ -1,6 +1,6 @@
// PR c++/46526
// { dg-do run }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
struct Base
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-base4.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-base4.C
index ce23cb9dd10..8a061bfd27e 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-base4.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-base4.C
@@ -1,6 +1,6 @@
// PR c++/46626
// { dg-do run }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-bitfield.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-bitfield.C
index 7eba49833f2..5025f4782d1 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-bitfield.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-bitfield.C
@@ -1,5 +1,5 @@
// PR c++/46369
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-bitfield2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-bitfield2.C
index 531bf31fc01..6ad5aeab586 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-bitfield2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-bitfield2.C
@@ -1,6 +1,6 @@
// PR c++/49136
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
struct day
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-bitfield3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-bitfield3.C
index b0ecbfb9abb..6b20e707f7b 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-bitfield3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-bitfield3.C
@@ -1,6 +1,6 @@
// PR c++/49136
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
struct S
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-builtin1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-builtin1.C
index b3f5576360b..ef2762e7cdb 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-builtin1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-builtin1.C
@@ -1,5 +1,5 @@
// PR c++/49813
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
inline constexpr bool
isinf(long double __x)
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-cache1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-cache1.C
index b6d7b647139..7c128df7b1b 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-cache1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-cache1.C
@@ -1,5 +1,5 @@
// PR c++/51433
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
constexpr int f();
constexpr int g() { return f(); }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-cleanup.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-cleanup.C
index de17f3ddb25..ff86b1bdbce 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-cleanup.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-cleanup.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-complex.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-complex.C
index eee773ef308..0d4ea010cb3 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-complex.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-complex.C
@@ -1,5 +1,5 @@
// Make sure C99 complex works with constexpr
-// { dg-options -std=gnu++0x }
+// { dg-options -std=gnu++11 }
struct complex
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-compound.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-compound.C
index 81fcc54b3e6..006a8c77613 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-compound.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-compound.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x -pedantic-errors" }
+// { dg-options "-std=c++11 -pedantic-errors" }
constexpr int f()
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-condition.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-condition.C
index e2328fcc578..dd47a79433d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-condition.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-condition.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
// Core DR 948
constexpr int something() { return 3; }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-condition2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-condition2.C
index 243409669bf..855c8dcea2a 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-condition2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-condition2.C
@@ -1,5 +1,5 @@
// PR c++/48909
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
#define SA(X) static_assert((X),#X)
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor.C
index 91c489db230..23076b3ac34 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor2.C
index 5280b131b7b..02333734bb2 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor2.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor3.C
index d5bfbad3d67..23159839c01 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor3.C
@@ -1,5 +1,5 @@
// PR c++/46348
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor4.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor4.C
index 397b4b054ef..96b99e320ad 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor4.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor4.C
@@ -1,5 +1,5 @@
// PR c++/46873
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct S
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor5.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor5.C
index 36b01785fee..63d4b151d71 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor5.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor5.C
@@ -1,5 +1,5 @@
// PR c++/46877
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct new_allocator
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor6.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor6.C
index 4f86f73a458..40512975003 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor6.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor6.C
@@ -1,5 +1,5 @@
// PR c++/47041
-// { dg-options "-std=c++0x -fno-elide-constructors" }
+// { dg-options "-std=c++11 -fno-elide-constructors" }
struct S
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor7.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor7.C
index 8338bf1f7ec..8a65ad2f34e 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor7.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor7.C
@@ -1,5 +1,5 @@
// PR c++/47199
-// { dg-options "-std=c++0x -fno-elide-constructors" }
+// { dg-options "-std=c++11 -fno-elide-constructors" }
template < int > struct S
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor8.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor8.C
index 81fc83737bc..4d204a17336 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor8.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor8.C
@@ -1,5 +1,5 @@
// PR c++/46466
-// { dg-options "-std=c++0x -fno-elide-constructors" }
+// { dg-options "-std=c++11 -fno-elide-constructors" }
struct S { bool b; };
constexpr S f() { return S{true}; }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor9.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor9.C
index b7693f1e637..9d7e88de0de 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor9.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor9.C
@@ -1,5 +1,5 @@
// PR c++/47774
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-data1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-data1.C
index 0943fa4225d..f2a4d443514 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-data1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-data1.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
// From N2235
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-data2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-data2.C
index 2d614ec32ed..47967ab416e 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-data2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-data2.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename _Tp, _Tp v>
struct A3
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-decl.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-decl.C
index 8c46fab3334..1af0662ff53 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-decl.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-decl.C
@@ -1,5 +1,5 @@
// PR c++/46930
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct S {
static constexpr int size; // { dg-error "must have an initializer" "must have" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-defarg.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-defarg.C
index 1413b24bd84..22ccedd1359 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-defarg.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-defarg.C
@@ -1,5 +1,5 @@
// PR c++/46335
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct T { };
struct A {
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-defarg2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-defarg2.C
index faa8a3603ff..4a02336647c 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-defarg2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-defarg2.C
@@ -1,5 +1,5 @@
// PR c++/46368
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
class A;
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-default-ctor.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-default-ctor.C
index d3868b599ac..02f695853db 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-default-ctor.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-default-ctor.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A {
int i;
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-delegating.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-delegating.C
index a0208887671..571e58f3de6 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-delegating.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-delegating.C
@@ -1,5 +1,5 @@
// PR c++/51526
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
const int j = 42;
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-delegating2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-delegating2.C
index c85ed2e8191..8115baa1aa1 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-delegating2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-delegating2.C
@@ -1,5 +1,5 @@
// PR c++/51723
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template <int... V>
struct A
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-delete.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-delete.C
index 67c9503025b..5eb478d851c 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-delete.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-delete.C
@@ -1,3 +1,3 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
constexpr bool never() = delete; // useless, but OK
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-deref.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-deref.C
index 7363e98ecb8..29adab9f23e 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-deref.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-deref.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-diag1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-diag1.C
index cbd4983e84b..21213eb5eb4 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-diag1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-diag1.C
@@ -1,5 +1,5 @@
// Test that we explain why a template instantiation isn't constexpr
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template <class T>
struct A
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-diag2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-diag2.C
index c78416ec1a3..161b5a7bdfb 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-diag2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-diag2.C
@@ -1,5 +1,5 @@
// PR c++/47207
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
constexpr int X (X); // { dg-error "not usable" }
// { dg-message "own initializer" "" { target *-*-* } 4 }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-diag3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-diag3.C
index 100c17edb45..0a0887fd6c1 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-diag3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-diag3.C
@@ -1,5 +1,5 @@
// PR c++/45923
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
int f(int);
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-eh-spec.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-eh-spec.C
index 6d231fafadb..45fee3bc032 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-eh-spec.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-eh-spec.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<class T> class my_limits {
public:
static constexpr T min() throw() { return T(); }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ellipsis.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ellipsis.C
index 5d090b541d4..55f8fa5322f 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ellipsis.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ellipsis.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
constexpr int ellipsis(...) { return 1; }
constexpr int ellipsis_c = ellipsis(); // OK
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ellipsis2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ellipsis2.C
index 0bb6904061f..d6b44828e15 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ellipsis2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ellipsis2.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-empty.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-empty.C
index a9fc4388a34..6a5565fc3f4 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-empty.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-empty.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct Empty {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-empty2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-empty2.C
index ef212119447..5e6694d9953 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-empty2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-empty2.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct IsLiteral {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-empty3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-empty3.C
index e0026fcc760..133ad42e36d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-empty3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-empty3.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct IsLiteral {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-empty4.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-empty4.C
index b07f924649d..3b7380d1284 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-empty4.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-empty4.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
typedef decltype(sizeof(char)) size_type;
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-empty5.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-empty5.C
index 9bd9aa583dc..f693cc196f6 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-empty5.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-empty5.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A { };
struct B: A { };
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ex1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ex1.C
index 3df7956fd28..acf8bccc176 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ex1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ex1.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
// From N2235
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ex2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ex2.C
index 29e835c4bbb..a760a729022 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ex2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ex2.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
// From N2235
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ex3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ex3.C
index 5c0b1e21cb7..1cda29b3b8d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ex3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ex3.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x -ftrack-macro-expansion=0" }
+// { dg-options "-std=c++11 -ftrack-macro-expansion=0" }
#define SA(X) static_assert (X, #X)
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ex4.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ex4.C
index 4214f5c52de..13089043c3b 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ex4.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ex4.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-expinst.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-expinst.C
index 20898736983..d8ba4193e7c 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-expinst.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-expinst.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
// Error: Explicit instantiation of a function template shall not use the
// inline or constexpr specifiers
template<class T> constexpr inline T bar(T x) { return x; }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-explicit-inst.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-explicit-inst.C
index 8f0da0af0c5..65210417226 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-explicit-inst.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-explicit-inst.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<class T> constexpr inline T bar(T x) { return x; }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-fnptr.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-fnptr.C
index 4c84d827f07..a81ce5a1378 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-fnptr.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-fnptr.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
constexpr bool is_negative(int x) { return x < 0; }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-friend.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-friend.C
index 57782cf349a..ee35f1ff98a 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-friend.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-friend.C
@@ -1,5 +1,5 @@
// PR c++/48948
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A { A(); };
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-function1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-function1.C
index c708b040f80..e4cddf7ea96 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-function1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-function1.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
// From N2235
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-function2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-function2.C
index 6403ea16e87..5dda09305db 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-function2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-function2.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
// From N2235
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-function3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-function3.C
index e8ca7bc68c9..bd35e97d1b8 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-function3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-function3.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
// From N2235
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-generated1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-generated1.C
index 73ddc8f5c2e..e66d33286f1 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-generated1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-generated1.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template <class T> struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ice.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ice.C
index 3b72484a005..aca701531a1 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ice.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ice.C
@@ -1,5 +1,5 @@
// We used to crash on this instead of giving a decent error.
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A { int i; };
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ice2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ice2.C
index 856246fcc95..952c6fdcc4c 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ice2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ice2.C
@@ -1,3 +1,3 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
int x;
constexpr int& rx = x;
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ice3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ice3.C
index 23903bca78d..1a66840080e 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ice3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ice3.C
@@ -1,5 +1,5 @@
// PR c++/46289
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ice4.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ice4.C
index e1ee36dfc90..35109e8d04f 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ice4.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ice4.C
@@ -1,5 +1,5 @@
// PR c++/51612
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ice5.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ice5.C
index b88ec66c9f6..56936b0ba65 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ice5.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ice5.C
@@ -1,5 +1,5 @@
// PR c++/51621
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ice6.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ice6.C
index 1a494bb3236..3512261cd31 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ice6.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ice6.C
@@ -1,5 +1,5 @@
// PR c++/51327
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-incomplete1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-incomplete1.C
index 3f40e29aec0..179566ba503 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-incomplete1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-incomplete1.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-incomplete2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-incomplete2.C
index f61535f06be..96de0c37243 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-incomplete2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-incomplete2.C
@@ -1,6 +1,6 @@
// A constructor that might or might not be constexpr still makes
// its class literal.
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template <class T>
struct B
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-incomplete3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-incomplete3.C
index 81822b07e2f..26ffd3e1fbd 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-incomplete3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-incomplete3.C
@@ -1,5 +1,5 @@
// PR c++/49015
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
class A;
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-initlist.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-initlist.C
index 6854e7341b7..982332b82c7 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-initlist.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-initlist.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
// { dg-do run }
namespace xstd {
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-initlist2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-initlist2.C
index f34b9801607..7a75e5ff271 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-initlist2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-initlist2.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
#include <initializer_list>
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-initlist3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-initlist3.C
index 7620e6b2c96..4909a082976 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-initlist3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-initlist3.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
#include <initializer_list>
#define SA(X) static_assert(X,#X)
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-initlist4.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-initlist4.C
index 81518575692..a45e8cdcf3c 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-initlist4.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-initlist4.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A { int i; };
struct B: A { constexpr B(): A{} {} };
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-initlist5.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-initlist5.C
index 97f03999802..9ddc9f8ab36 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-initlist5.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-initlist5.C
@@ -1,5 +1,5 @@
// PR c++/50024
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template< class T >
struct Container
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-is_literal.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-is_literal.C
index 82514ed865a..6423588fd7f 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-is_literal.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-is_literal.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
#include <type_traits>
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-memfn1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-memfn1.C
index ef7ac6b4842..10a0aaa2f08 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-memfn1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-memfn1.C
@@ -1,5 +1,5 @@
// PR c++/48296
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct X
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-missing.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-missing.C
index 547f552e377..6f1d1a23653 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-missing.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-missing.C
@@ -1,6 +1,6 @@
// PR c++/48911
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
#define SA(X) static_assert((X),#X)
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-mutable1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-mutable1.C
index a14d611cee8..3d595d5d925 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-mutable1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-mutable1.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-neg1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-neg1.C
index c27615f05ad..8e1bcd0f2f9 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-neg1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-neg1.C
@@ -1,5 +1,5 @@
// Negative examples from N3092 (FCD)
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
// OK: declaration
constexpr int square(int x); // { dg-message "never defined" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-noexcept.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-noexcept.C
index 0476f909654..9e337793092 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-noexcept.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-noexcept.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<class T>
struct is_funny {
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-noexcept2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-noexcept2.C
index 95a1443fa28..e4e998b50d4 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-noexcept2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-noexcept2.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<class T>
constexpr T value(T t) { return t; }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-noexcept3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-noexcept3.C
index 6e76ea8fa0b..1cda3521897 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-noexcept3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-noexcept3.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
constexpr int f(int i) { return i; }
#define SA(X) static_assert (X, #X)
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-noexcept4.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-noexcept4.C
index 119d4e16730..b19c1575acf 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-noexcept4.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-noexcept4.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
// A call is noexcept if it is a valid subexpression of a constant
// expression, even if it is not itself a constant expression.
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-noexcept5.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-noexcept5.C
index 7bf961b3c45..52f2040b90b 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-noexcept5.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-noexcept5.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct booleable {
bool data;
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-noexcept6.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-noexcept6.C
index 91e93fd91bc..56dc68308ca 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-noexcept6.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-noexcept6.C
@@ -1,5 +1,5 @@
// PR c++/51305
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
constexpr bool ok() noexcept
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-non-const-arg.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-non-const-arg.C
index 7637c0a05bc..c8bdb28384b 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-non-const-arg.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-non-const-arg.C
@@ -1,6 +1,6 @@
// Example from issue 1125 drafting; D() and v were well-formed with the
// wording approved in Rapperswil, now seems they should be ill-formed.
-// { dg-options "-std=c++0x -pedantic-errors" }
+// { dg-options "-std=c++11 -pedantic-errors" }
struct B {
constexpr B(int x) : i(0) { } // "x" is unused
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-non-const-arg2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-non-const-arg2.C
index 20e05c3c068..02ec95f7e9e 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-non-const-arg2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-non-const-arg2.C
@@ -1,5 +1,5 @@
// PR c++/47200
-// { dg-options "-std=c++0x -w" }
+// { dg-options "-std=c++11 -w" }
template < int > struct duration
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-non-const-arg3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-non-const-arg3.C
index 581be6d15ce..3a9c92c4011 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-non-const-arg3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-non-const-arg3.C
@@ -1,5 +1,5 @@
// PR c++/49988
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
// { dg-do run }
template<int ... I> struct X { };
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-nonlit.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-nonlit.C
index 9104c8afac6..21036d8e7d0 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-nonlit.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-nonlit.C
@@ -1,5 +1,5 @@
// FIXME this is currently invalid, but seems like it should be OK
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A { A() { } };
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-nonlit2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-nonlit2.C
index 21e8bd50961..77ceefe0569 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-nonlit2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-nonlit2.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-nonstatic.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-nonstatic.C
index 3951fbdb15c..110edd4db10 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-nonstatic.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-nonstatic.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-nullptr.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-nullptr.C
index 6381323cc0c..77b56af049d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-nullptr.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-nullptr.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
constexpr int zero() { return 0; }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-object1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-object1.C
index 6c9d4664418..f5c319ad9d6 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-object1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-object1.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
// From N2235
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-object2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-object2.C
index a038970f6a4..9234ad218e2 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-object2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-object2.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
constexpr int verysquare(int x) { return x * x; }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-overflow.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-overflow.C
index 3eb27aa0a88..b9f82470727 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-overflow.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-overflow.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x -w -ftrack-macro-expansion=0" }
+// { dg-options "-std=c++11 -w -ftrack-macro-expansion=0" }
#include <limits.h>
extern constexpr int max_s = INT_MAX + 1; // { dg-error "" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-overflow2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-overflow2.C
index 5d5749ce2c3..8534f5f9376 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-overflow2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-overflow2.C
@@ -1,5 +1,5 @@
// PR c++/47504
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
char constexpr sub(char arg)
{ return char(arg - char(1)); }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-pedantic.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-pedantic.C
index dc393d75915..84ff462abc7 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-pedantic.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-pedantic.C
@@ -1,6 +1,6 @@
// The FCD doesn't allow typedefs and static_assert in constexpr functions,
// but it should.
-// { dg-options "-std=c++0x -pedantic" }
+// { dg-options "-std=c++11 -pedantic" }
template <class T>
constexpr T f(T t)
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-pos1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-pos1.C
index 775080acce6..c234f4a8c34 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-pos1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-pos1.C
@@ -1,5 +1,5 @@
// Positive examples from N3092 (FCD)
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
#define SA(X) static_assert(X, #X)
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-potential1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-potential1.C
index e933506b8a1..85a26f0886a 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-potential1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-potential1.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
// We decided in Rapperswil that it's OK if any value of decide can produce
// a constant expression.
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ptrmem.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ptrmem.C
index f6ed2f40afb..8a1c5517bd4 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ptrmem.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ptrmem.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct C { // literal type
int m;
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ptrsub.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ptrsub.C
index bccec73bb0b..a7c79d7456d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ptrsub.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ptrsub.C
@@ -1,6 +1,6 @@
// PR c++/51489
// DR 1313
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
struct array
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-pure.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-pure.C
index e17e02a4220..556b4e7cb3f 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-pure.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-pure.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-recursion.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-recursion.C
index 2f9b4887df6..327efa44648 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-recursion.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-recursion.C
@@ -1,5 +1,5 @@
// Test that we catch excessive recursion.
-// { dg-options "-std=c++0x -fconstexpr-depth=5" }
+// { dg-options "-std=c++11 -fconstexpr-depth=5" }
// { dg-prune-output "in constexpr expansion" }
constexpr int f (int i) { return f (i-1); }
constexpr int i = f(42); // { dg-error "constexpr evaluation depth" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ref1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ref1.C
index 482e1ba3691..0c10b4b5578 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ref1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ref1.C
@@ -1,5 +1,5 @@
// PR c++/49172
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
#define SA(X) static_assert((X),#X)
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ref2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ref2.C
index 2a86eb765cb..5091593056f 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ref2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ref2.C
@@ -1,5 +1,5 @@
// Negative reference variable tests.
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
extern int *p;
constexpr int& ri = *p; // { dg-error "p" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ref3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ref3.C
index 24cc9c82449..37222525e60 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ref3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ref3.C
@@ -1,5 +1,5 @@
// PR c++/50298
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
int global_variable;
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ref4.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ref4.C
index 6ae355a273f..c256814a3ad 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ref4.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ref4.C
@@ -1,5 +1,5 @@
// PR c++/54777
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct S
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-rom.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-rom.C
index a6aa34eb2f5..0f5384a9062 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-rom.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-rom.C
@@ -1,5 +1,5 @@
// PR c++/49673: check that test_data goes into .rodata
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
// { dg-additional-options -G0 { target { { alpha*-*-* frv*-*-* ia64-*-* lm32*-*-* m32r*-*-* microblaze*-*-* mips*-*-* powerpc*-*-* rs6000*-*-* score*-*-* } && { ! { *-*-darwin* *-*-aix* alpha*-*-*vms* } } } } }
// { dg-final { scan-assembler "\\.rdata" { target mips*-*-* } } }
// { dg-final { scan-assembler "rodata" { target { { *-*-linux-gnu *-*-gnu* *-*-elf } && { ! mips*-*-* } } } } }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-sassert.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-sassert.C
index 3e08fb0efa3..b9b5003a06f 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-sassert.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-sassert.C
@@ -1,5 +1,5 @@
// Allow static_assert in constexpr constructors, too.
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<typename T>
struct A
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-static.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-static.C
index 8ed2b5e82ed..aa96499b284 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-static.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-static.C
@@ -1,5 +1,5 @@
// Test for constant initialization of non-literal class (e.g. mutex)
-// { dg-options "-std=c++0x -save-temps" }
+// { dg-options "-std=c++11 -save-temps" }
// { dg-do run }
struct A
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-static2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-static2.C
index 67c35308024..2ed8147ff1d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-static2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-static2.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct IsLiteral {};
struct ShouldBeLiteral {
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-static3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-static3.C
index dccdc854b39..1951edbf43b 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-static3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-static3.C
@@ -1,5 +1,5 @@
// Test for constant initialization of class with vtable
-// { dg-options "-std=c++0x -save-temps" }
+// { dg-options "-std=c++11 -save-temps" }
// { dg-final { scan-assembler-not "static_initialization" } }
// { dg-final cleanup-saved-temps }
// { dg-do run }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-static4.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-static4.C
index 8189fc5de47..aa060b8d43d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-static4.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-static4.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
// { dg-do run }
extern "C" void abort ();
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-static5.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-static5.C
index a401cc0b890..886e693d52c 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-static5.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-static5.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template <class T>
struct A
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-static6.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-static6.C
index a34704d839c..cf64979a9a9 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-static6.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-static6.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct B
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-static7.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-static7.C
index e46ddafd702..bb333b7d897 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-static7.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-static7.C
@@ -1,5 +1,5 @@
// PR c++/48945
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A {
static constexpr bool is();
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-static8.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-static8.C
index 7c84cf8b07b..c6fd94e9c74 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-static8.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-static8.C
@@ -1,5 +1,5 @@
// PR c++/50258
-// { dg-options "-std=c++0x -fpermissive" }
+// { dg-options "-std=c++11 -fpermissive" }
struct Foo {
static const double d = 3.14; // { dg-warning "constexpr" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-stmtexpr.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-stmtexpr.C
index 40e0c2d65d0..562cf760872 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-stmtexpr.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-stmtexpr.C
@@ -1,5 +1,5 @@
// PR c++/46977
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template < typename > void
foo ()
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-string.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-string.C
index e76d00d7e63..a7132e1c812 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-string.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-string.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
constexpr char c1 = "hi"[1];
constexpr char c2 = "hi"[2];
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-switch.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-switch.C
index d229304e419..705d3553c45 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-switch.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-switch.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<class T>
constexpr T value(T t = T()) { return t; }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-switch2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-switch2.C
index 55cf2ad7ce8..a59e7671979 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-switch2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-switch2.C
@@ -1,5 +1,5 @@
// Test for constexpr conversion in case context
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
enum class E { e1, e2 };
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-synth1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-synth1.C
index 9830939806b..1e7a92a82c8 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-synth1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-synth1.C
@@ -1,5 +1,5 @@
// PR c++/46472
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<class T> struct A {
T t;
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-targ.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-targ.C
index 0c8c73d2e1d..ba97ab7f4c2 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-targ.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-targ.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-template1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-template1.C
index 88077231b0d..d109229f002 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-template1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-template1.C
@@ -1,5 +1,5 @@
// PR c++/50248, DR 1358
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<class Elt, unsigned max>
struct earray
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-template2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-template2.C
index 6786d1651e5..368edb50705 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-template2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-template2.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template <class T> struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-template3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-template3.C
index 75b2fc4634e..66fcb2a7726 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-template3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-template3.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A { constexpr operator int() { return 42; } };
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-throw.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-throw.C
index f1ef9dc7d0d..7f06080c476 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-throw.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-throw.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
constexpr int may_throw(bool decide) {
return decide ? 42 : throw -1; // { dg-error "throw" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-typedef1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-typedef1.C
index 2719e3aea12..98f25ecf5ba 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-typedef1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-typedef1.C
@@ -1,5 +1,5 @@
// PR c++/50508
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template <class T>
struct integral_constant {
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-typeid.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-typeid.C
index b523bb38cc1..d72dc5a3f7a 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-typeid.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-typeid.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
#include <typeinfo>
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-union.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-union.C
index 3c7a7f38ec8..53cecfaeb46 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-union.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-union.C
@@ -1,6 +1,6 @@
// Test that we don't have to deal with type punning
// DR 1188 says this is ill-formed
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
union U
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-union2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-union2.C
index 0bf2aa7e2bc..2ae7e40dacf 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-union2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-union2.C
@@ -1,5 +1,5 @@
// PR c++/51675
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
union foo
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-using.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-using.C
index fc794e9abdf..a28d15eb781 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-using.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-using.C
@@ -1,5 +1,5 @@
// Core issue 898
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
namespace N { const int i = 42; }
namespace M { const int j = 42; }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-using2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-using2.C
index 6b282813e55..18272a6faf6 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-using2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-using2.C
@@ -1,5 +1,5 @@
// PR c++/49520
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
namespace x { void foo(); }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-value.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-value.C
index 85799d90b68..2004a779d73 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-value.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-value.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct HopefullyLiteral {
HopefullyLiteral() = default; // Should be a constexpr c'tor as of 12.1/6 and 8.4.2/4
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-value2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-value2.C
index 1b0e28f162d..1be6a08dda3 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-value2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-value2.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<class T>
constexpr T value_init() { return T(); }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-value3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-value3.C
index 38d89936ec4..57fe868cd47 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-value3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-value3.C
@@ -1,5 +1,5 @@
// PR c++/50234
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
#define SA(X) static_assert((X),#X)
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-variadic.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-variadic.C
index 5d0ad05941e..c2be3272734 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-variadic.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-variadic.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<class... T>
constexpr bool variadics(T&&...) { return true; }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-virtual.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-virtual.C
index 448ecb1dc70..22ad73d50c9 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-virtual.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-virtual.C
@@ -1,5 +1,5 @@
// PR c++/47067
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct X {
virtual void x();
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-wstring1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-wstring1.C
index 059977bfff9..0195a863fde 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-wstring1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-wstring1.C
@@ -1,6 +1,6 @@
// PR c++/48570
// { dg-do run }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
extern "C" void abort ();
constexpr wchar_t foo (int i) { return L"0123"[i]; }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-wstring2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-wstring2.C
index 4fc8980ef96..586e0baa5e8 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-wstring2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-wstring2.C
@@ -1,6 +1,6 @@
// PR c++/48570
// { dg-do compile }
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
constexpr wchar_t c1 = L"hi"[3]; // { dg-error "out of bound" }
constexpr char16_t c2 = u"hi"[3]; // { dg-error "out of bound" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/dc1.C b/gcc/testsuite/g++.dg/cpp0x/dc1.C
index ba2e4f4fd05..c1a5f39dce3 100644
--- a/gcc/testsuite/g++.dg/cpp0x/dc1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/dc1.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options --std=c++0x }
+// { dg-options --std=c++11 }
struct B {
int i;
diff --git a/gcc/testsuite/g++.dg/cpp0x/dc2.C b/gcc/testsuite/g++.dg/cpp0x/dc2.C
index dda0b9fc697..227bab13705 100644
--- a/gcc/testsuite/g++.dg/cpp0x/dc2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/dc2.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options --std=c++0x }
+// { dg-options --std=c++11 }
struct A {
int i, j;
diff --git a/gcc/testsuite/g++.dg/cpp0x/dc3.C b/gcc/testsuite/g++.dg/cpp0x/dc3.C
index b411c997d8f..c68d622d202 100644
--- a/gcc/testsuite/g++.dg/cpp0x/dc3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/dc3.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options --std=c++0x }
+// { dg-options --std=c++11 }
struct X {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/dc5.C b/gcc/testsuite/g++.dg/cpp0x/dc5.C
index 0052b321113..59cf2ea1785 100644
--- a/gcc/testsuite/g++.dg/cpp0x/dc5.C
+++ b/gcc/testsuite/g++.dg/cpp0x/dc5.C
@@ -1,5 +1,5 @@
// { dg-do run }
-// { dg-options "--std=c++0x" }
+// { dg-options "--std=c++11" }
#include <cassert>
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype-1212.C b/gcc/testsuite/g++.dg/cpp0x/decltype-1212.C
index 38393d3b874..24bf339a516 100644
--- a/gcc/testsuite/g++.dg/cpp0x/decltype-1212.C
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype-1212.C
@@ -1,5 +1,5 @@
// Core 1212
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template <class T, class U> struct assert_same_type;
template <class T> struct assert_same_type<T,T> {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype-33837.C b/gcc/testsuite/g++.dg/cpp0x/decltype-33837.C
index 2c263dd0a97..7f85bc32c92 100644
--- a/gcc/testsuite/g++.dg/cpp0x/decltype-33837.C
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype-33837.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
// PR c++/33837
void foo()
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype-33838.C b/gcc/testsuite/g++.dg/cpp0x/decltype-33838.C
index 260a0d1cf09..8f4a86c12ad 100644
--- a/gcc/testsuite/g++.dg/cpp0x/decltype-33838.C
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype-33838.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
// PR c++/33838
template<typename T> struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype-refbug.C b/gcc/testsuite/g++.dg/cpp0x/decltype-refbug.C
index 8e3c8240724..d58011b2a31 100644
--- a/gcc/testsuite/g++.dg/cpp0x/decltype-refbug.C
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype-refbug.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// PR c++/33045
int && f ();
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype1.C b/gcc/testsuite/g++.dg/cpp0x/decltype1.C
index d1288e07d93..7b268fdbca0 100644
--- a/gcc/testsuite/g++.dg/cpp0x/decltype1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype1.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename T, typename U>
struct is_same
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype10.C b/gcc/testsuite/g++.dg/cpp0x/decltype10.C
index 6c488998c59..381f6363b3a 100644
--- a/gcc/testsuite/g++.dg/cpp0x/decltype10.C
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype10.C
@@ -1,6 +1,6 @@
// PR c++/34271
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<int> struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype11.C b/gcc/testsuite/g++.dg/cpp0x/decltype11.C
index ac32d349a6c..01a65568d9e 100644
--- a/gcc/testsuite/g++.dg/cpp0x/decltype11.C
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype11.C
@@ -1,5 +1,5 @@
// PR c++/35316
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<int> struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype12.C b/gcc/testsuite/g++.dg/cpp0x/decltype12.C
index 77c794bcf09..c39f6f103cd 100644
--- a/gcc/testsuite/g++.dg/cpp0x/decltype12.C
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype12.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<typename T, typename U>
struct is_same
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype15.C b/gcc/testsuite/g++.dg/cpp0x/decltype15.C
index 5c2d445debf..e0348ea9a38 100644
--- a/gcc/testsuite/g++.dg/cpp0x/decltype15.C
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype15.C
@@ -1,6 +1,6 @@
// PR c++/38640
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<int N> void foo (decltype (N));
template<long int N> void foo (decltype (N));
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype16.C b/gcc/testsuite/g++.dg/cpp0x/decltype16.C
index 2002458b851..9f2398ece1f 100644
--- a/gcc/testsuite/g++.dg/cpp0x/decltype16.C
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype16.C
@@ -1,5 +1,5 @@
// PR c++/39070
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<typename X> struct junk {
template<typename Z> static Z y();
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype17.C b/gcc/testsuite/g++.dg/cpp0x/decltype17.C
index 7f36ff01e50..c3a44535974 100644
--- a/gcc/testsuite/g++.dg/cpp0x/decltype17.C
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype17.C
@@ -1,5 +1,5 @@
// PR c++/36628
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// { dg-do run }
#include <typeinfo>
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype18.C b/gcc/testsuite/g++.dg/cpp0x/decltype18.C
index 0d44586e9d2..0f639a0cdfb 100644
--- a/gcc/testsuite/g++.dg/cpp0x/decltype18.C
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype18.C
@@ -1,5 +1,5 @@
// PR c++/37875
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template <typename> struct X {};
X<decltype(1 > 2)> x;
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype2.C b/gcc/testsuite/g++.dg/cpp0x/decltype2.C
index e0c59003047..81cb56b7ed9 100644
--- a/gcc/testsuite/g++.dg/cpp0x/decltype2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype2.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename T, typename U>
struct is_same
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype20.C b/gcc/testsuite/g++.dg/cpp0x/decltype20.C
index 3155cdcf86a..bba848ccc41 100644
--- a/gcc/testsuite/g++.dg/cpp0x/decltype20.C
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype20.C
@@ -1,5 +1,5 @@
// PR c++/42277
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct S { int s; };
template <int N>
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype21.C b/gcc/testsuite/g++.dg/cpp0x/decltype21.C
index 733725626c3..a6e973ff88f 100644
--- a/gcc/testsuite/g++.dg/cpp0x/decltype21.C
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype21.C
@@ -1,6 +1,6 @@
// PR c++/6709 (DR 743)
// PR c++/42603 (DR 950)
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template <class T>
T make();
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype22.C b/gcc/testsuite/g++.dg/cpp0x/decltype22.C
index 74811cfe701..623163f4b14 100644
--- a/gcc/testsuite/g++.dg/cpp0x/decltype22.C
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype22.C
@@ -1,5 +1,5 @@
// PR c++/42761
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<typename _Tp> _Tp* fn();
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype23.C b/gcc/testsuite/g++.dg/cpp0x/decltype23.C
index 78eb89d8ee2..a2543243a52 100644
--- a/gcc/testsuite/g++.dg/cpp0x/decltype23.C
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype23.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
int x, &&y = static_cast<int &&>(x);
typedef decltype((y)) myInt; // `y' is a parenthesized id-expression of type int that is an lvalue
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype24.C b/gcc/testsuite/g++.dg/cpp0x/decltype24.C
index 16d0736d66f..3b3a7d59718 100644
--- a/gcc/testsuite/g++.dg/cpp0x/decltype24.C
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype24.C
@@ -1,5 +1,5 @@
// PR c++/47068
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template <class T> struct broken {
int member;
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype25.C b/gcc/testsuite/g++.dg/cpp0x/decltype25.C
index c9559f1511a..04465b90220 100644
--- a/gcc/testsuite/g++.dg/cpp0x/decltype25.C
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype25.C
@@ -1,5 +1,5 @@
// PR c++/47851
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct Type {
void display_type();
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype26.C b/gcc/testsuite/g++.dg/cpp0x/decltype26.C
index a81d411558c..705fd64e51e 100644
--- a/gcc/testsuite/g++.dg/cpp0x/decltype26.C
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype26.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A { };
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype27.C b/gcc/testsuite/g++.dg/cpp0x/decltype27.C
index cb962ada525..0f0cd42168b 100644
--- a/gcc/testsuite/g++.dg/cpp0x/decltype27.C
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype27.C
@@ -1,5 +1,5 @@
// PR c++/48617
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<class T, decltype(T())> // #
struct A {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype28.C b/gcc/testsuite/g++.dg/cpp0x/decltype28.C
index 00457357b2b..591bb03b573 100644
--- a/gcc/testsuite/g++.dg/cpp0x/decltype28.C
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype28.C
@@ -1,5 +1,5 @@
// PR c++/44175
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template <bool, class T> struct enable_if { };
template <class T> struct enable_if <true, T> { typedef T type; };
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype29.C b/gcc/testsuite/g++.dg/cpp0x/decltype29.C
index a64bb65a476..ae1cb2ab2fc 100644
--- a/gcc/testsuite/g++.dg/cpp0x/decltype29.C
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype29.C
@@ -1,5 +1,5 @@
// PR c++/44175
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template <bool, class T> struct enable_if { };
template <class T> struct enable_if <true, T> { typedef T type; };
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype3.C b/gcc/testsuite/g++.dg/cpp0x/decltype3.C
index b44dd17c8ea..57300566e3b 100644
--- a/gcc/testsuite/g++.dg/cpp0x/decltype3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype3.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename T, typename U>
struct is_same
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype30.C b/gcc/testsuite/g++.dg/cpp0x/decltype30.C
index b23c9a94d8f..2e7283e55d7 100644
--- a/gcc/testsuite/g++.dg/cpp0x/decltype30.C
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype30.C
@@ -1,5 +1,5 @@
// PR c++/49369
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template <class,class> struct assert_same;
template <class T> struct assert_same<T,T> {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype31.C b/gcc/testsuite/g++.dg/cpp0x/decltype31.C
index b9817eb9e13..ce03ec11cc8 100644
--- a/gcc/testsuite/g++.dg/cpp0x/decltype31.C
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype31.C
@@ -1,5 +1,5 @@
// PR c++/49921
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct Local
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype32.C b/gcc/testsuite/g++.dg/cpp0x/decltype32.C
index c5f3a55c6d2..a53f9d05469 100644
--- a/gcc/testsuite/g++.dg/cpp0x/decltype32.C
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype32.C
@@ -1,5 +1,5 @@
// PR c++/50075
-// { dg-options "-std=c++0x -ftemplate-depth=10" }
+// { dg-options "-std=c++11 -ftemplate-depth=10" }
template <typename T>
auto make_array(const T& il) ->
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype33.C b/gcc/testsuite/g++.dg/cpp0x/decltype33.C
index d022d166482..935423ab555 100644
--- a/gcc/testsuite/g++.dg/cpp0x/decltype33.C
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype33.C
@@ -1,5 +1,5 @@
// PR c++/50084
-// { dg-options "-std=c++0x -fno-inline" }
+// { dg-options "-std=c++11 -fno-inline" }
template<typename> struct remove_reference;
template<typename T> struct remove_reference<T&> { typedef T type; };
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype34.C b/gcc/testsuite/g++.dg/cpp0x/decltype34.C
index fbd15c2797d..9d7c3182825 100644
--- a/gcc/testsuite/g++.dg/cpp0x/decltype34.C
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype34.C
@@ -1,5 +1,5 @@
// PR c++/50870
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
struct impl
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype35.C b/gcc/testsuite/g++.dg/cpp0x/decltype35.C
index d1fd47638a9..ee9537d97eb 100644
--- a/gcc/testsuite/g++.dg/cpp0x/decltype35.C
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype35.C
@@ -1,5 +1,5 @@
// PR c++/50870
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template <class V>
struct impl
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype36.C b/gcc/testsuite/g++.dg/cpp0x/decltype36.C
index f3dfed992cf..2cf34c0ecf2 100644
--- a/gcc/testsuite/g++.dg/cpp0x/decltype36.C
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype36.C
@@ -1,5 +1,5 @@
// PR c++/51265
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct Funny
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype4.C b/gcc/testsuite/g++.dg/cpp0x/decltype4.C
index cd715cb2892..5db826fc522 100644
--- a/gcc/testsuite/g++.dg/cpp0x/decltype4.C
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype4.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename T, typename U>
struct is_same
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype5.C b/gcc/testsuite/g++.dg/cpp0x/decltype5.C
index 1391539873f..4c31a2b4a6a 100644
--- a/gcc/testsuite/g++.dg/cpp0x/decltype5.C
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype5.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename T, typename U>
struct is_same
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype57.C b/gcc/testsuite/g++.dg/cpp0x/decltype57.C
new file mode 100644
index 00000000000..353cc72c335
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype57.C
@@ -0,0 +1,8 @@
+// PR c++/58633
+// { dg-do compile { target c++11 } }
+
+void foo(int i)
+{
+ typedef int I;
+ decltype(i.I::~I())* p;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype6.C b/gcc/testsuite/g++.dg/cpp0x/decltype6.C
index 7aa8e1505ef..2f742ce08cc 100644
--- a/gcc/testsuite/g++.dg/cpp0x/decltype6.C
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype6.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename T, typename U>
struct is_same
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype9.C b/gcc/testsuite/g++.dg/cpp0x/decltype9.C
index 4cd150ea6cf..c13ff8db5d6 100644
--- a/gcc/testsuite/g++.dg/cpp0x/decltype9.C
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype9.C
@@ -1,6 +1,6 @@
// PR c++/34271
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<int> struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/deduce.C b/gcc/testsuite/g++.dg/cpp0x/deduce.C
index 635228cca08..5185f9a3953 100644
--- a/gcc/testsuite/g++.dg/cpp0x/deduce.C
+++ b/gcc/testsuite/g++.dg/cpp0x/deduce.C
@@ -1,4 +1,4 @@
-// { dg-options "--std=c++0x" }
+// { dg-options "--std=c++11" }
template<typename T, typename U> struct same_type;
template<typename T> struct same_type<T, T> {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted1.C b/gcc/testsuite/g++.dg/cpp0x/defaulted1.C
index e8fe37eb39a..1f36b185452 100644
--- a/gcc/testsuite/g++.dg/cpp0x/defaulted1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted1.C
@@ -1,6 +1,6 @@
// Positive test for defaulted/deleted fns
// { dg-do run }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted10.C b/gcc/testsuite/g++.dg/cpp0x/defaulted10.C
index 64fa5f01930..fe3eae5b417 100644
--- a/gcc/testsuite/g++.dg/cpp0x/defaulted10.C
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted10.C
@@ -1,5 +1,5 @@
// PR c++/40381
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted11.C b/gcc/testsuite/g++.dg/cpp0x/defaulted11.C
index b9bed7e0037..65cd0e27f47 100644
--- a/gcc/testsuite/g++.dg/cpp0x/defaulted11.C
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted11.C
@@ -1,5 +1,5 @@
// Core issue 901
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted13.C b/gcc/testsuite/g++.dg/cpp0x/defaulted13.C
index 5ddbcb38c1c..ad15a0e853c 100644
--- a/gcc/testsuite/g++.dg/cpp0x/defaulted13.C
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted13.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<typename T>
struct NonCopyable {
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted14.C b/gcc/testsuite/g++.dg/cpp0x/defaulted14.C
index e476d576cfa..73072e2057d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/defaulted14.C
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted14.C
@@ -1,5 +1,5 @@
// PR c++/39866
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
struct A {
A& operator=(const A&) = delete; // { dg-bogus "" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted15.C b/gcc/testsuite/g++.dg/cpp0x/defaulted15.C
index 6d182df2158..99400ac4f9c 100644
--- a/gcc/testsuite/g++.dg/cpp0x/defaulted15.C
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted15.C
@@ -1,5 +1,5 @@
// PR c++/38796
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
#define SA(X) static_assert ((X), #X)
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted16.C b/gcc/testsuite/g++.dg/cpp0x/defaulted16.C
index 741b43de27d..25b2d5ad673 100644
--- a/gcc/testsuite/g++.dg/cpp0x/defaulted16.C
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted16.C
@@ -1,7 +1,7 @@
// Test that non-inline default causes the function to be defined even if
// it isn't used.
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
// { dg-final { scan-assembler "_ZN1AC1Ev" } }
struct A
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted17.C b/gcc/testsuite/g++.dg/cpp0x/defaulted17.C
index 79e91a0eb61..48529f5a3a7 100644
--- a/gcc/testsuite/g++.dg/cpp0x/defaulted17.C
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted17.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A // { dg-error "const|operator=" }
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted18.C b/gcc/testsuite/g++.dg/cpp0x/defaulted18.C
index 559dfde4833..7dd17345d11 100644
--- a/gcc/testsuite/g++.dg/cpp0x/defaulted18.C
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted18.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
void f(char i, int j) = delete; // { dg-message "<deleted>" }
void f(int i, ...); // { dg-message "void f" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted19.C b/gcc/testsuite/g++.dg/cpp0x/defaulted19.C
index ea33df39838..f7de0730625 100644
--- a/gcc/testsuite/g++.dg/cpp0x/defaulted19.C
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted19.C
@@ -1,5 +1,6 @@
-// We allocate a cookie to help us run the destructor even if it's deleted.
-// { dg-options -std=c++0x }
+// We don't allocate a cookie to help us run the destructor if it's trivial,
+// even if it's deleted.
+// { dg-options "-std=c++11" }
// { dg-do run }
struct A
@@ -17,5 +18,5 @@ void *operator new[](__SIZE_TYPE__ t)
int main()
{
A* ap = new A[5];
- return ap == p;
+ return ap != p;
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted19a.C b/gcc/testsuite/g++.dg/cpp0x/defaulted19a.C
new file mode 100644
index 00000000000..6d2a26a818c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted19a.C
@@ -0,0 +1,24 @@
+// We allocate a cookie to help us run the destructor if it's non-trivial,
+// even if it's deleted.
+// { dg-options "-std=c++0x" }
+// { dg-do run }
+
+struct B { ~B() {} };
+struct A
+{
+ B b;
+ ~A() = delete;
+};
+
+void *p = 0;
+void *operator new[](__SIZE_TYPE__ t)
+{
+ p = ::operator new (t);
+ return p;
+}
+
+int main()
+{
+ A* ap = new A[5];
+ return ap == p;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted2.C b/gcc/testsuite/g++.dg/cpp0x/defaulted2.C
index 57f74e8e714..3cef60050ac 100644
--- a/gcc/testsuite/g++.dg/cpp0x/defaulted2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted2.C
@@ -1,5 +1,5 @@
// Negative test for defaulted/deleted fns.
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
void f(); // { dg-error "previous" }
void f() = delete; // { dg-error "deleted" }
@@ -62,7 +62,7 @@ int main()
{
F f;
F f2(f); // { dg-error "use" }
- B* b = new const B; // { dg-error "uninitialized const" }
+ const B* b = new const B; // { dg-error "uninitialized const" }
U u; // { dg-error "deleted" }
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted20.C b/gcc/testsuite/g++.dg/cpp0x/defaulted20.C
index 9b8c697abad..49919ef7813 100644
--- a/gcc/testsuite/g++.dg/cpp0x/defaulted20.C
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted20.C
@@ -1,5 +1,5 @@
// PR c++/46497
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A {
A(A&&) = default;
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted21.C b/gcc/testsuite/g++.dg/cpp0x/defaulted21.C
index 51505dc460e..09a211ff7d3 100644
--- a/gcc/testsuite/g++.dg/cpp0x/defaulted21.C
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted21.C
@@ -1,5 +1,5 @@
// PR c++/46736
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct U {
U();
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted22.C b/gcc/testsuite/g++.dg/cpp0x/defaulted22.C
index 61e9d320521..86dbed90bf8 100644
--- a/gcc/testsuite/g++.dg/cpp0x/defaulted22.C
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted22.C
@@ -1,6 +1,6 @@
// Test that a virtual defaulted constructor is still virtual.
// { dg-do run }
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
int r = 1;
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted23.C b/gcc/testsuite/g++.dg/cpp0x/defaulted23.C
index 5b4438ddd02..be2fd2fbf90 100644
--- a/gcc/testsuite/g++.dg/cpp0x/defaulted23.C
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted23.C
@@ -1,27 +1,37 @@
// Test for checking of exception specifications on defaulted fns
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A
{
A() noexcept = default;
};
+A a;
+
struct B
{
- B() throw (int) = default; // { dg-error "exception-specification that differs from the implicit declaration" }
+ B() throw (int) = default; // { dg-message "exception-specification" }
};
+B b; // { dg-error "deleted" }
+
struct C
{
C() throw (int) { }
};
+C c;
+
struct D: C
{
D() throw (int) = default;
};
+D d;
+
struct E
{
E() = default;
};
+
+E e;
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted24.C b/gcc/testsuite/g++.dg/cpp0x/defaulted24.C
index 307bf94ab85..7f9aed69f0e 100644
--- a/gcc/testsuite/g++.dg/cpp0x/defaulted24.C
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted24.C
@@ -1,5 +1,5 @@
// PR c++/48280
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct S {
template < typename > S (const S &) = default; // { dg-error "" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted25.C b/gcc/testsuite/g++.dg/cpp0x/defaulted25.C
index 2a38fedb248..26b0c9184ea 100644
--- a/gcc/testsuite/g++.dg/cpp0x/defaulted25.C
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted25.C
@@ -1,5 +1,5 @@
// PR c++/48930
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
// { dg-prune-output "note" }
struct A
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted26.C b/gcc/testsuite/g++.dg/cpp0x/defaulted26.C
index 746fa908180..b9be726b3a7 100644
--- a/gcc/testsuite/g++.dg/cpp0x/defaulted26.C
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted26.C
@@ -1,5 +1,5 @@
// PR c++/49066
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
void foo() = delete; // { dg-message "declared here" }
void foo();
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted27.C b/gcc/testsuite/g++.dg/cpp0x/defaulted27.C
index 7d9139d2373..8f71e9eb254 100644
--- a/gcc/testsuite/g++.dg/cpp0x/defaulted27.C
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted27.C
@@ -1,5 +1,5 @@
// PR c++/47544
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
// { dg-final { scan-assembler "_ZN1sIiEC2Ev" } }
// { dg-final { scan-assembler-not "_ZN1sIiED2Ev" } }
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted28.C b/gcc/testsuite/g++.dg/cpp0x/defaulted28.C
index bcbf763f6da..e8b44daeae3 100644
--- a/gcc/testsuite/g++.dg/cpp0x/defaulted28.C
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted28.C
@@ -1,6 +1,6 @@
// PR c++/49102
// PR c++/50034
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A {
A() = default;
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted29.C b/gcc/testsuite/g++.dg/cpp0x/defaulted29.C
index 5fcf5b0c543..9e6382e3793 100644
--- a/gcc/testsuite/g++.dg/cpp0x/defaulted29.C
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted29.C
@@ -1,5 +1,5 @@
// PR c++/46696
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted3.C b/gcc/testsuite/g++.dg/cpp0x/defaulted3.C
index bc5b14d2d59..21b13783426 100644
--- a/gcc/testsuite/g++.dg/cpp0x/defaulted3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted3.C
@@ -1,5 +1,5 @@
// PR c++/37006
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<class T>
struct A {
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted30.C b/gcc/testsuite/g++.dg/cpp0x/defaulted30.C
index 0bf4425b875..2440b94034f 100644
--- a/gcc/testsuite/g++.dg/cpp0x/defaulted30.C
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted30.C
@@ -1,5 +1,5 @@
// PR c++/49507
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<typename T>
struct ConcretePoolKey
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted31.C b/gcc/testsuite/g++.dg/cpp0x/defaulted31.C
index c76a0f2bd69..d866872157d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/defaulted31.C
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted31.C
@@ -1,5 +1,5 @@
// PR c++/39164
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted32.C b/gcc/testsuite/g++.dg/cpp0x/defaulted32.C
index 351cdae1102..a3654833617 100644
--- a/gcc/testsuite/g++.dg/cpp0x/defaulted32.C
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted32.C
@@ -1,5 +1,5 @@
// PR c++/50531
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template <typename T>
class DataFilter
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted34.C b/gcc/testsuite/g++.dg/cpp0x/defaulted34.C
index 08219926739..463cc34e7fb 100644
--- a/gcc/testsuite/g++.dg/cpp0x/defaulted34.C
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted34.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
// { dg-final { scan-assembler "__cxa_deleted_virtual" } }
struct A
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted35.C b/gcc/testsuite/g++.dg/cpp0x/defaulted35.C
index ca700fb784c..8312ba16aa9 100644
--- a/gcc/testsuite/g++.dg/cpp0x/defaulted35.C
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted35.C
@@ -1,5 +1,5 @@
// PR c++/53096
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct foo
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted4.C b/gcc/testsuite/g++.dg/cpp0x/defaulted4.C
index 56053840bdf..3e5e92604ed 100644
--- a/gcc/testsuite/g++.dg/cpp0x/defaulted4.C
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted4.C
@@ -1,6 +1,6 @@
// PR c++/37208: SFINAE and deleted functions.
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// { dg-do compile }
template<int> struct A { };
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted43.C b/gcc/testsuite/g++.dg/cpp0x/defaulted43.C
index e1c2b72ba27..f2846fe390c 100644
--- a/gcc/testsuite/g++.dg/cpp0x/defaulted43.C
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted43.C
@@ -7,6 +7,8 @@ struct T
~T() noexcept(false) { }
};
+T t;
+
struct A
{
A() noexcept;
@@ -24,6 +26,8 @@ struct U
~U() noexcept(false) { }
};
+U u;
+
struct B
{
B() noexcept(false);
@@ -35,16 +39,22 @@ struct B
B::B() noexcept(false) = default;
B::~B() noexcept(false) = default;
+B b;
+
struct V
{
V() noexcept(false) { }
~V() noexcept(false) { }
};
+V v;
+
struct C
{
- C() noexcept = default; // { dg-error "defaulted" }
- ~C() noexcept = default; // { dg-error "defaulted" }
+ C() noexcept = default; // { dg-message "exception-specification" }
+ ~C() noexcept = default; // { dg-message "exception-specification" }
V v;
};
+
+C c; // { dg-error "deleted" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted46.C b/gcc/testsuite/g++.dg/cpp0x/defaulted46.C
new file mode 100644
index 00000000000..d4562c95903
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted46.C
@@ -0,0 +1,17 @@
+// { dg-require-effective-target c++11 }
+
+struct A
+{
+protected:
+ A() = default;
+ int i;
+};
+
+struct B: A {
+ B() = default;
+};
+
+int main()
+{
+ B();
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted47.C b/gcc/testsuite/g++.dg/cpp0x/defaulted47.C
new file mode 100644
index 00000000000..f4b62a3c659
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted47.C
@@ -0,0 +1,16 @@
+// PR c++/54812
+// { dg-do compile { target c++11 } }
+
+class A
+{
+ A() = default; // { dg-error "private" }
+};
+
+A a; // { dg-error "context" }
+
+class B
+{
+ ~B() = default; // { dg-error "private" }
+};
+
+B b; // { dg-error "context" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted5.C b/gcc/testsuite/g++.dg/cpp0x/defaulted5.C
index b7bd16b4063..a8d7e9828cf 100644
--- a/gcc/testsuite/g++.dg/cpp0x/defaulted5.C
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted5.C
@@ -1,6 +1,6 @@
// PR c++/37234
// { dg-do link }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template <typename T>
class foo {
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted6.C b/gcc/testsuite/g++.dg/cpp0x/defaulted6.C
index c33d5729223..05f06c94680 100644
--- a/gcc/testsuite/g++.dg/cpp0x/defaulted6.C
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted6.C
@@ -1,5 +1,5 @@
// PR c++/37906
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
struct b
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted7.C b/gcc/testsuite/g++.dg/cpp0x/defaulted7.C
index 97c29258e98..00a24f03999 100644
--- a/gcc/testsuite/g++.dg/cpp0x/defaulted7.C
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted7.C
@@ -1,5 +1,5 @@
// PR c++/38701, 38702
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
void foo() = default; // { dg-error "cannot be defaulted" }
namespace
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted8.C b/gcc/testsuite/g++.dg/cpp0x/defaulted8.C
index f446f815691..6ec936322d2 100644
--- a/gcc/testsuite/g++.dg/cpp0x/defaulted8.C
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted8.C
@@ -1,5 +1,5 @@
// PR c++/38649
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted9.C b/gcc/testsuite/g++.dg/cpp0x/defaulted9.C
index 1e5e2cbf9fb..2907b03a123 100644
--- a/gcc/testsuite/g++.dg/cpp0x/defaulted9.C
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted9.C
@@ -1,5 +1,5 @@
// PR c++/39153
-// { dg-options "-std=c++0x -fno-inline" }
+// { dg-options "-std=c++11 -fno-inline" }
struct _Impl_base
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/deleted1.C b/gcc/testsuite/g++.dg/cpp0x/deleted1.C
new file mode 100644
index 00000000000..0a632bfb30b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/deleted1.C
@@ -0,0 +1,6 @@
+// PR c++/58581
+// { dg-do compile { target c++11 } }
+
+template<typename T> int foo(T) noexcept(T()) = delete;
+
+int i = foo(0); // { dg-error "deleted" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/dependent1.C b/gcc/testsuite/g++.dg/cpp0x/dependent1.C
index 1ceeeafd78d..de8a1a9380b 100644
--- a/gcc/testsuite/g++.dg/cpp0x/dependent1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/dependent1.C
@@ -1,5 +1,5 @@
// PR c++/48319
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
// We were failing to recognize declval<_Args1> as dependent.
template<typename Tp> Tp declval() noexcept;
diff --git a/gcc/testsuite/g++.dg/cpp0x/diag1.C b/gcc/testsuite/g++.dg/cpp0x/diag1.C
index b3f30bcd0b4..0e53dcb69a3 100644
--- a/gcc/testsuite/g++.dg/cpp0x/diag1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/diag1.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template <int U>
struct TypeA
diff --git a/gcc/testsuite/g++.dg/cpp0x/elision.C b/gcc/testsuite/g++.dg/cpp0x/elision.C
index 35d5e4b02fb..70162a151bb 100644
--- a/gcc/testsuite/g++.dg/cpp0x/elision.C
+++ b/gcc/testsuite/g++.dg/cpp0x/elision.C
@@ -3,7 +3,7 @@
// Test: Implicit cast to rvalue when eliding copy
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template <bool> struct sa;
template <> struct sa<true> {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/elision2.C b/gcc/testsuite/g++.dg/cpp0x/elision2.C
index 216b1b59d16..811c5394d7f 100644
--- a/gcc/testsuite/g++.dg/cpp0x/elision2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/elision2.C
@@ -1,5 +1,5 @@
// Core 1148: should be able to move from value parameter on return
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/elision_neg.C b/gcc/testsuite/g++.dg/cpp0x/elision_neg.C
index 78feac72a5b..f302605f73f 100644
--- a/gcc/testsuite/g++.dg/cpp0x/elision_neg.C
+++ b/gcc/testsuite/g++.dg/cpp0x/elision_neg.C
@@ -3,7 +3,7 @@
// Test: Implicit cast to rvalue when eliding copy
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template <bool> struct sa;
template <> struct sa<true> {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/enum1.C b/gcc/testsuite/g++.dg/cpp0x/enum1.C
index fb03692fab4..41dd62240d4 100644
--- a/gcc/testsuite/g++.dg/cpp0x/enum1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/enum1.C
@@ -1,6 +1,6 @@
// PR c++/38021
// { dg-do compile }
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
enum : { }; // { dg-error "expected" }
enum : 3 { }; // { dg-error "expected" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/enum10.C b/gcc/testsuite/g++.dg/cpp0x/enum10.C
index 55a1ab46be1..825cc647d52 100644
--- a/gcc/testsuite/g++.dg/cpp0x/enum10.C
+++ b/gcc/testsuite/g++.dg/cpp0x/enum10.C
@@ -1,5 +1,5 @@
// PR c++/48534
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
enum class OpSE : bool;
diff --git a/gcc/testsuite/g++.dg/cpp0x/enum11.C b/gcc/testsuite/g++.dg/cpp0x/enum11.C
index 156c765beaf..a2bd3535213 100644
--- a/gcc/testsuite/g++.dg/cpp0x/enum11.C
+++ b/gcc/testsuite/g++.dg/cpp0x/enum11.C
@@ -1,5 +1,5 @@
// PR c++/48969
-// { dg-options "-std=c++0x -ftemplate-depth=10" }
+// { dg-options "-std=c++11 -ftemplate-depth=10" }
template<unsigned int N> struct Pair { };
struct Foo { enum { Mask = 1 }; } foo;
diff --git a/gcc/testsuite/g++.dg/cpp0x/enum12.C b/gcc/testsuite/g++.dg/cpp0x/enum12.C
index b2ec91990e2..46d2686a6b3 100644
--- a/gcc/testsuite/g++.dg/cpp0x/enum12.C
+++ b/gcc/testsuite/g++.dg/cpp0x/enum12.C
@@ -1,5 +1,5 @@
// PR c++/48780
-// { dg-options "-std=c++0x -fabi-version=0" }
+// { dg-options "-std=c++11 -fabi-version=0" }
typedef __builtin_va_list __gnuc_va_list;
typedef __gnuc_va_list va_list;
diff --git a/gcc/testsuite/g++.dg/cpp0x/enum13.C b/gcc/testsuite/g++.dg/cpp0x/enum13.C
index ec02d3bf607..3f637241fdc 100644
--- a/gcc/testsuite/g++.dg/cpp0x/enum13.C
+++ b/gcc/testsuite/g++.dg/cpp0x/enum13.C
@@ -1,5 +1,5 @@
// PR c++/48780
-// { dg-options "-std=c++0x -fabi-version=5 -Wabi" }
+// { dg-options "-std=c++11 -fabi-version=5 -Wabi" }
typedef __builtin_va_list __gnuc_va_list;
typedef __gnuc_va_list va_list;
diff --git a/gcc/testsuite/g++.dg/cpp0x/enum14.C b/gcc/testsuite/g++.dg/cpp0x/enum14.C
index 709b201d1f7..fe791f1a26b 100644
--- a/gcc/testsuite/g++.dg/cpp0x/enum14.C
+++ b/gcc/testsuite/g++.dg/cpp0x/enum14.C
@@ -1,5 +1,5 @@
// PR c++/48106
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
enum class E : char
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/enum15.C b/gcc/testsuite/g++.dg/cpp0x/enum15.C
index 1d33f90290f..61737742adb 100644
--- a/gcc/testsuite/g++.dg/cpp0x/enum15.C
+++ b/gcc/testsuite/g++.dg/cpp0x/enum15.C
@@ -1,5 +1,5 @@
// PR c++/44311
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
enum class A { Val0, Val1 };
diff --git a/gcc/testsuite/g++.dg/cpp0x/enum16.C b/gcc/testsuite/g++.dg/cpp0x/enum16.C
index ebb48688b18..941d85b5c58 100644
--- a/gcc/testsuite/g++.dg/cpp0x/enum16.C
+++ b/gcc/testsuite/g++.dg/cpp0x/enum16.C
@@ -1,5 +1,5 @@
// PR c++/48935
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
enum class ENUM { a };
diff --git a/gcc/testsuite/g++.dg/cpp0x/enum17.C b/gcc/testsuite/g++.dg/cpp0x/enum17.C
index 8ba827e50f4..e67928ba4ca 100644
--- a/gcc/testsuite/g++.dg/cpp0x/enum17.C
+++ b/gcc/testsuite/g++.dg/cpp0x/enum17.C
@@ -1,5 +1,5 @@
// PR c++/48536
-// { dg-options "-std=c++0x -pedantic-errors" }
+// { dg-options "-std=c++11 -pedantic-errors" }
#include <climits>
diff --git a/gcc/testsuite/g++.dg/cpp0x/enum18.C b/gcc/testsuite/g++.dg/cpp0x/enum18.C
index 306ed8259f9..c37eebe9de2 100644
--- a/gcc/testsuite/g++.dg/cpp0x/enum18.C
+++ b/gcc/testsuite/g++.dg/cpp0x/enum18.C
@@ -1,5 +1,5 @@
// PR c++/47277
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
int main(void) {
enum e {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/enum19.C b/gcc/testsuite/g++.dg/cpp0x/enum19.C
index acdd86c0ba4..de423aa8cca 100644
--- a/gcc/testsuite/g++.dg/cpp0x/enum19.C
+++ b/gcc/testsuite/g++.dg/cpp0x/enum19.C
@@ -1,5 +1,5 @@
// We shouldn't give an ABI warning about promotion in switch.
-// { dg-options "-std=c++0x -fabi-version=5 -Wabi" }
+// { dg-options "-std=c++11 -fabi-version=5 -Wabi" }
enum class Foo { X };
void test(Foo val)
diff --git a/gcc/testsuite/g++.dg/cpp0x/enum2.C b/gcc/testsuite/g++.dg/cpp0x/enum2.C
index 21c265a923c..57eccafe14c 100644
--- a/gcc/testsuite/g++.dg/cpp0x/enum2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/enum2.C
@@ -1,5 +1,5 @@
// PR c++/38637
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<int> enum E : int { e }; // { dg-error "declaration|expected" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/enum20.C b/gcc/testsuite/g++.dg/cpp0x/enum20.C
index e5dc186e4af..0fcd9c907de 100644
--- a/gcc/testsuite/g++.dg/cpp0x/enum20.C
+++ b/gcc/testsuite/g++.dg/cpp0x/enum20.C
@@ -1,5 +1,5 @@
// PR c++/47635
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
enum A { };
void A::f() { } // { dg-error "not a class" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/enum21b.C b/gcc/testsuite/g++.dg/cpp0x/enum21b.C
index 48989128d89..aab0f5e215e 100644
--- a/gcc/testsuite/g++.dg/cpp0x/enum21b.C
+++ b/gcc/testsuite/g++.dg/cpp0x/enum21b.C
@@ -1,4 +1,4 @@
// { dg-do compile }
-// { dg-options "-pedantic -std=c++0x" }
+// { dg-options "-pedantic -std=c++11" }
enum x { y, };
diff --git a/gcc/testsuite/g++.dg/cpp0x/enum3.C b/gcc/testsuite/g++.dg/cpp0x/enum3.C
index 5ae5e1a9d66..3e630d6e1e8 100644
--- a/gcc/testsuite/g++.dg/cpp0x/enum3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/enum3.C
@@ -1,5 +1,5 @@
// PR c++/38064
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// { dg-do run }
enum class E { elem };
diff --git a/gcc/testsuite/g++.dg/cpp0x/enum4.C b/gcc/testsuite/g++.dg/cpp0x/enum4.C
index 002edf0923e..adf24b9cecf 100644
--- a/gcc/testsuite/g++.dg/cpp0x/enum4.C
+++ b/gcc/testsuite/g++.dg/cpp0x/enum4.C
@@ -1,5 +1,5 @@
// PR c++/40633
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template< typename T >
struct wrap {
diff --git a/gcc/testsuite/g++.dg/cpp0x/enum5.C b/gcc/testsuite/g++.dg/cpp0x/enum5.C
index c4ceebed71e..fd413228e69 100644
--- a/gcc/testsuite/g++.dg/cpp0x/enum5.C
+++ b/gcc/testsuite/g++.dg/cpp0x/enum5.C
@@ -1,5 +1,5 @@
// PR c++/40639
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template< typename T >
struct wrap {
diff --git a/gcc/testsuite/g++.dg/cpp0x/enum6.C b/gcc/testsuite/g++.dg/cpp0x/enum6.C
index e0639847125..74bd228a0bf 100644
--- a/gcc/testsuite/g++.dg/cpp0x/enum6.C
+++ b/gcc/testsuite/g++.dg/cpp0x/enum6.C
@@ -1,5 +1,5 @@
// PR c++/37946
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
enum class E : char
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/enum7.C b/gcc/testsuite/g++.dg/cpp0x/enum7.C
index 407672a4799..ed6635d53bd 100644
--- a/gcc/testsuite/g++.dg/cpp0x/enum7.C
+++ b/gcc/testsuite/g++.dg/cpp0x/enum7.C
@@ -1,5 +1,5 @@
// PR c++/37816
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
class A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/enum8.C b/gcc/testsuite/g++.dg/cpp0x/enum8.C
index 0075e2daa8b..b0205a92497 100644
--- a/gcc/testsuite/g++.dg/cpp0x/enum8.C
+++ b/gcc/testsuite/g++.dg/cpp0x/enum8.C
@@ -1,6 +1,6 @@
// PR c++/47704
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
void
foo ()
diff --git a/gcc/testsuite/g++.dg/cpp0x/enum9.C b/gcc/testsuite/g++.dg/cpp0x/enum9.C
index 10e510bcd25..70a2103916e 100644
--- a/gcc/testsuite/g++.dg/cpp0x/enum9.C
+++ b/gcc/testsuite/g++.dg/cpp0x/enum9.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
enum class E { };
E f();
diff --git a/gcc/testsuite/g++.dg/cpp0x/enum_base.C b/gcc/testsuite/g++.dg/cpp0x/enum_base.C
index 7da232cc2aa..e63f4184237 100644
--- a/gcc/testsuite/g++.dg/cpp0x/enum_base.C
+++ b/gcc/testsuite/g++.dg/cpp0x/enum_base.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
typedef unsigned volatile long long uvlonglong;
diff --git a/gcc/testsuite/g++.dg/cpp0x/enum_base_warn.C b/gcc/testsuite/g++.dg/cpp0x/enum_base_warn.C
index 4b14cf65e09..5257a9e4d11 100644
--- a/gcc/testsuite/g++.dg/cpp0x/enum_base_warn.C
+++ b/gcc/testsuite/g++.dg/cpp0x/enum_base_warn.C
@@ -1,5 +1,5 @@
// { dg-do run }
-// { dg-options "-O2 -Wtype-limits -std=c++0x" }
+// { dg-options "-O2 -Wtype-limits -std=c++11" }
extern void link_error (void);
enum Alpha : unsigned char {
diff --git a/gcc/testsuite/g++.dg/cpp0x/error1.C b/gcc/testsuite/g++.dg/cpp0x/error1.C
index 15cd38f8807..59abd169503 100644
--- a/gcc/testsuite/g++.dg/cpp0x/error1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/error1.C
@@ -1,6 +1,6 @@
// PR c++/34395
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<int... N> void foo (int... x[N]) // { dg-message "int \\\[N\\\]\\.\\.\\. x" }
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/error2.C b/gcc/testsuite/g++.dg/cpp0x/error2.C
index ca681eb2f79..d39e7f023f6 100644
--- a/gcc/testsuite/g++.dg/cpp0x/error2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/error2.C
@@ -1,5 +1,5 @@
// PR c++/38656
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<int> int foo();
diff --git a/gcc/testsuite/g++.dg/cpp0x/error3.C b/gcc/testsuite/g++.dg/cpp0x/error3.C
index e7da961950e..deee9a24253 100644
--- a/gcc/testsuite/g++.dg/cpp0x/error3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/error3.C
@@ -1,5 +1,5 @@
// PR c++/47336
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template <typename T>
void g(T t)
diff --git a/gcc/testsuite/g++.dg/cpp0x/error4.C b/gcc/testsuite/g++.dg/cpp0x/error4.C
index 064c2f2f620..fa638a44d25 100644
--- a/gcc/testsuite/g++.dg/cpp0x/error4.C
+++ b/gcc/testsuite/g++.dg/cpp0x/error4.C
@@ -1,5 +1,5 @@
// PR c++/49156
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<typename T> T declval();
diff --git a/gcc/testsuite/g++.dg/cpp0x/error5.C b/gcc/testsuite/g++.dg/cpp0x/error5.C
index 19319264224..0baa5000694 100644
--- a/gcc/testsuite/g++.dg/cpp0x/error5.C
+++ b/gcc/testsuite/g++.dg/cpp0x/error5.C
@@ -1,5 +1,5 @@
// PR c++/49181
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
namespace std
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/error6.C b/gcc/testsuite/g++.dg/cpp0x/error6.C
index 3b457952d38..e059e2261d2 100644
--- a/gcc/testsuite/g++.dg/cpp0x/error6.C
+++ b/gcc/testsuite/g++.dg/cpp0x/error6.C
@@ -1,5 +1,5 @@
// PR c++/48284
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<typename C>
auto g(C& c) -> decltype (c.f()) { return c.f(); } // { dg-message "decltype .c\\.f" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/error7.C b/gcc/testsuite/g++.dg/cpp0x/error7.C
index 0dfbf9f0406..9c9f1c9b1c1 100644
--- a/gcc/testsuite/g++.dg/cpp0x/error7.C
+++ b/gcc/testsuite/g++.dg/cpp0x/error7.C
@@ -1,5 +1,5 @@
// Test for printing the type of T{} in error messages.
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template <class T, T t> struct A { };
template <class T> A<T,T{}> f(T t); // { dg-message "T{}" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/explicit1.C b/gcc/testsuite/g++.dg/cpp0x/explicit1.C
index fe164fc8cb1..e3004c7314d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/explicit1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/explicit1.C
@@ -1,5 +1,5 @@
// Test for explicit conversion ops from N2437.
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
class U; class V;
class T
diff --git a/gcc/testsuite/g++.dg/cpp0x/explicit2.C b/gcc/testsuite/g++.dg/cpp0x/explicit2.C
index c2327c140d8..9938f549712 100644
--- a/gcc/testsuite/g++.dg/cpp0x/explicit2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/explicit2.C
@@ -1,5 +1,5 @@
// Test for explicit conversion ops in various conversion situations.
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
typedef void (*pfn)();
diff --git a/gcc/testsuite/g++.dg/cpp0x/explicit3.C b/gcc/testsuite/g++.dg/cpp0x/explicit3.C
index 78d6f590cab..6933c8cfa01 100644
--- a/gcc/testsuite/g++.dg/cpp0x/explicit3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/explicit3.C
@@ -1,5 +1,5 @@
// Test for "contextually converted to bool"
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/explicit4.C b/gcc/testsuite/g++.dg/cpp0x/explicit4.C
index 0f3bc623a53..bbefb68cbe5 100644
--- a/gcc/testsuite/g++.dg/cpp0x/explicit4.C
+++ b/gcc/testsuite/g++.dg/cpp0x/explicit4.C
@@ -1,5 +1,5 @@
// Negative explicit conv test.
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
struct A {
A(const A&, int = 0); // { dg-message "note" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/explicit5.C b/gcc/testsuite/g++.dg/cpp0x/explicit5.C
index 88a47071db1..4573fc6296c 100644
--- a/gcc/testsuite/g++.dg/cpp0x/explicit5.C
+++ b/gcc/testsuite/g++.dg/cpp0x/explicit5.C
@@ -1,5 +1,5 @@
// test for extension of DR 899 to handle template ctors
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// { dg-do run }
int r = 1;
diff --git a/gcc/testsuite/g++.dg/cpp0x/explicit6.C b/gcc/testsuite/g++.dg/cpp0x/explicit6.C
index 0d620be0803..741b9a29fc2 100644
--- a/gcc/testsuite/g++.dg/cpp0x/explicit6.C
+++ b/gcc/testsuite/g++.dg/cpp0x/explicit6.C
@@ -1,5 +1,5 @@
// PR c++/47080
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A {
explicit operator int(); // { dg-message "qualification conversion" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/explicit7.C b/gcc/testsuite/g++.dg/cpp0x/explicit7.C
index 7a0b73e9ba0..ed3b494fce5 100644
--- a/gcc/testsuite/g++.dg/cpp0x/explicit7.C
+++ b/gcc/testsuite/g++.dg/cpp0x/explicit7.C
@@ -3,7 +3,7 @@
// can be converted to type T with a qualification conversion (4.4) are
// also candidate functions.
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A { };
struct B: A { };
diff --git a/gcc/testsuite/g++.dg/cpp0x/extern_template-1.C b/gcc/testsuite/g++.dg/cpp0x/extern_template-1.C
index ec2cb784e19..9cec57c1c66 100644
--- a/gcc/testsuite/g++.dg/cpp0x/extern_template-1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/extern_template-1.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x -pedantic" }
+// { dg-options "-std=c++11 -pedantic" }
template <typename> void f() {}
extern template void f<int>();
diff --git a/gcc/testsuite/g++.dg/cpp0x/extern_template-2.C b/gcc/testsuite/g++.dg/cpp0x/extern_template-2.C
index 89a9ceb5a77..7ec1864ec8f 100644
--- a/gcc/testsuite/g++.dg/cpp0x/extern_template-2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/extern_template-2.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x -pedantic" }
+// { dg-options "-std=c++11 -pedantic" }
template <typename> class S {};
extern template class S<int>;
diff --git a/gcc/testsuite/g++.dg/cpp0x/fntmpdefarg1.C b/gcc/testsuite/g++.dg/cpp0x/fntmpdefarg1.C
index 25192ad8672..27cb0579d85 100644
--- a/gcc/testsuite/g++.dg/cpp0x/fntmpdefarg1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/fntmpdefarg1.C
@@ -1,5 +1,5 @@
// PR c++/37766
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
int a = 1;
template<int& b = a> void f() {
diff --git a/gcc/testsuite/g++.dg/cpp0x/fntmpdefarg2.C b/gcc/testsuite/g++.dg/cpp0x/fntmpdefarg2.C
index d94843c1fe5..c119e86afed 100644
--- a/gcc/testsuite/g++.dg/cpp0x/fntmpdefarg2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/fntmpdefarg2.C
@@ -1,5 +1,5 @@
// PR c++/46831
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct B { };
struct D : B { };
diff --git a/gcc/testsuite/g++.dg/cpp0x/forw_enum1.C b/gcc/testsuite/g++.dg/cpp0x/forw_enum1.C
index 2817ae59573..a147538ded9 100644
--- a/gcc/testsuite/g++.dg/cpp0x/forw_enum1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/forw_enum1.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// opaque enum declarations
enum class E1;
diff --git a/gcc/testsuite/g++.dg/cpp0x/forw_enum10.C b/gcc/testsuite/g++.dg/cpp0x/forw_enum10.C
index a57c0a9f415..59c8045cdad 100644
--- a/gcc/testsuite/g++.dg/cpp0x/forw_enum10.C
+++ b/gcc/testsuite/g++.dg/cpp0x/forw_enum10.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
//This error is diagnosed at instantiation time
template<typename T> struct S1
diff --git a/gcc/testsuite/g++.dg/cpp0x/forw_enum2.C b/gcc/testsuite/g++.dg/cpp0x/forw_enum2.C
index b6ad8714867..d11dc7465ff 100644
--- a/gcc/testsuite/g++.dg/cpp0x/forw_enum2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/forw_enum2.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
struct S1
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/forw_enum3.C b/gcc/testsuite/g++.dg/cpp0x/forw_enum3.C
index 4a7e9f98d47..682fd93c772 100644
--- a/gcc/testsuite/g++.dg/cpp0x/forw_enum3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/forw_enum3.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
namespace S1
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/forw_enum4.C b/gcc/testsuite/g++.dg/cpp0x/forw_enum4.C
index 0fcc3bde0f5..162b4bf332e 100644
--- a/gcc/testsuite/g++.dg/cpp0x/forw_enum4.C
+++ b/gcc/testsuite/g++.dg/cpp0x/forw_enum4.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<typename T> struct S1
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/forw_enum5.C b/gcc/testsuite/g++.dg/cpp0x/forw_enum5.C
index a2edfa7635c..a0e74863306 100644
--- a/gcc/testsuite/g++.dg/cpp0x/forw_enum5.C
+++ b/gcc/testsuite/g++.dg/cpp0x/forw_enum5.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
namespace one
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/forw_enum6.C b/gcc/testsuite/g++.dg/cpp0x/forw_enum6.C
index 51ef6e43ec7..a42d93c47b0 100644
--- a/gcc/testsuite/g++.dg/cpp0x/forw_enum6.C
+++ b/gcc/testsuite/g++.dg/cpp0x/forw_enum6.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
enum class E1 : int; // { dg-error "previous definition" }
enum E1 : int; // { dg-error "scoped/unscoped mismatch" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/forw_enum7.C b/gcc/testsuite/g++.dg/cpp0x/forw_enum7.C
index 62e445c707b..34e9af077d2 100644
--- a/gcc/testsuite/g++.dg/cpp0x/forw_enum7.C
+++ b/gcc/testsuite/g++.dg/cpp0x/forw_enum7.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<typename T> struct S1
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/forw_enum8.C b/gcc/testsuite/g++.dg/cpp0x/forw_enum8.C
index 69e73119e0c..1d85162aa2d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/forw_enum8.C
+++ b/gcc/testsuite/g++.dg/cpp0x/forw_enum8.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
//This instatiation is ok
template<typename T> struct S1
diff --git a/gcc/testsuite/g++.dg/cpp0x/forw_enum9.C b/gcc/testsuite/g++.dg/cpp0x/forw_enum9.C
index da8cde27b40..ba7d3c76717 100644
--- a/gcc/testsuite/g++.dg/cpp0x/forw_enum9.C
+++ b/gcc/testsuite/g++.dg/cpp0x/forw_enum9.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<typename T> struct S1
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/friend1.C b/gcc/testsuite/g++.dg/cpp0x/friend1.C
index 2cf4c3c715a..838d250b23b 100644
--- a/gcc/testsuite/g++.dg/cpp0x/friend1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/friend1.C
@@ -1,5 +1,5 @@
// From N1791
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
class C;
typedef C Ct;
diff --git a/gcc/testsuite/g++.dg/cpp0x/friend2.C b/gcc/testsuite/g++.dg/cpp0x/friend2.C
index 39276a05ac3..7dbc8946b23 100644
--- a/gcc/testsuite/g++.dg/cpp0x/friend2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/friend2.C
@@ -1,5 +1,5 @@
// PR c++/47721
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
// template type parameter friend:
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-55.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-55.C
new file mode 100644
index 00000000000..c4e6deabe1d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-55.C
@@ -0,0 +1,12 @@
+// PR c++/58584
+// { dg-do compile { target c++11 } }
+
+struct A
+{
+ int i alignas(this); // { dg-error "17:invalid use of 'this'" }
+};
+
+template<int> struct B
+{
+ int j alignas(this); // { dg-error "17:invalid use of 'this'" }
+};
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-56.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-56.C
new file mode 100644
index 00000000000..f331ed369ac
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-56.C
@@ -0,0 +1,5 @@
+// PR c++/58724
+// { dg-do compile { target c++11 } }
+
+namespace foo __attribute__((visibility("default"))) {}
+namespace bar [[gnu::visibility("default")]] {}
diff --git a/gcc/testsuite/g++.dg/cpp0x/implicit-copy.C b/gcc/testsuite/g++.dg/cpp0x/implicit-copy.C
index c3f6b85e247..70454dbf9c3 100644
--- a/gcc/testsuite/g++.dg/cpp0x/implicit-copy.C
+++ b/gcc/testsuite/g++.dg/cpp0x/implicit-copy.C
@@ -1,4 +1,4 @@
-// { dg-options "--std=c++0x" }
+// { dg-options "--std=c++11" }
struct S
{
S();
diff --git a/gcc/testsuite/g++.dg/cpp0x/implicit-trivial1.C b/gcc/testsuite/g++.dg/cpp0x/implicit-trivial1.C
index 64084c14855..7ab73bd22cf 100644
--- a/gcc/testsuite/g++.dg/cpp0x/implicit-trivial1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/implicit-trivial1.C
@@ -1,8 +1,8 @@
// PR c++/46807
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
// In C++98/03, B::B(const B&) is trivial because A::A(const A&) is trivial,
// even though doing overload resolution would mean calling the template
-// constructor. In C++0x, we do overload resolution to determine triviality.
+// constructor. In C++11, we do overload resolution to determine triviality.
struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/implicit1.C b/gcc/testsuite/g++.dg/cpp0x/implicit1.C
index e4e16e1ad35..777ed549249 100644
--- a/gcc/testsuite/g++.dg/cpp0x/implicit1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/implicit1.C
@@ -1,5 +1,5 @@
// Test for implicitly deleted destructors.
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// { dg-prune-output "default definition would be ill-formed" }
// { dg-prune-output "within this context" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/implicit10.C b/gcc/testsuite/g++.dg/cpp0x/implicit10.C
index 721a93dd57e..fcc47616f76 100644
--- a/gcc/testsuite/g++.dg/cpp0x/implicit10.C
+++ b/gcc/testsuite/g++.dg/cpp0x/implicit10.C
@@ -1,5 +1,5 @@
// PR c++/46103
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct MoveOnly {
MoveOnly(const MoveOnly&) = delete;
diff --git a/gcc/testsuite/g++.dg/cpp0x/implicit11.C b/gcc/testsuite/g++.dg/cpp0x/implicit11.C
index c974e2b7761..9f5841d17cf 100644
--- a/gcc/testsuite/g++.dg/cpp0x/implicit11.C
+++ b/gcc/testsuite/g++.dg/cpp0x/implicit11.C
@@ -1,6 +1,6 @@
// Test that we consider base dtors in determining whether
// a derived ctor is deleted even if the ctor is trivial.
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A
{
@@ -12,6 +12,6 @@ struct B: A { }; // { dg-error "deleted" }
extern B eb;
int main()
{
- B* b1 = new B; // { dg-error "use of deleted function" "" { xfail *-*-* } }
+ B* b1 = new B; // { dg-error "use of deleted function" }
B* b2 = new B(eb); // { dg-error "use of deleted function" }
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/implicit12.C b/gcc/testsuite/g++.dg/cpp0x/implicit12.C
index da806e006a6..ab51a87005f 100644
--- a/gcc/testsuite/g++.dg/cpp0x/implicit12.C
+++ b/gcc/testsuite/g++.dg/cpp0x/implicit12.C
@@ -1,5 +1,5 @@
// PR c++/50500
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// If a class declares move operations, the implicitly declared copy
// operations are deleted.
diff --git a/gcc/testsuite/g++.dg/cpp0x/implicit2.C b/gcc/testsuite/g++.dg/cpp0x/implicit2.C
index f24a78838fa..ae516b7fe82 100644
--- a/gcc/testsuite/g++.dg/cpp0x/implicit2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/implicit2.C
@@ -1,6 +1,6 @@
// Test that the synthesized C copy constructor calls the A template
// constructor and has the appropriate exception specification.
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
// { dg-do run }
int r = 1;
diff --git a/gcc/testsuite/g++.dg/cpp0x/implicit3.C b/gcc/testsuite/g++.dg/cpp0x/implicit3.C
index a43eca708c0..abef33a8e63 100644
--- a/gcc/testsuite/g++.dg/cpp0x/implicit3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/implicit3.C
@@ -1,6 +1,6 @@
// Basic runtime test for implicit move constructor
// { dg-do run }
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
int m;
diff --git a/gcc/testsuite/g++.dg/cpp0x/implicit4.C b/gcc/testsuite/g++.dg/cpp0x/implicit4.C
index 47fd56a5252..16cd4b4a0f0 100644
--- a/gcc/testsuite/g++.dg/cpp0x/implicit4.C
+++ b/gcc/testsuite/g++.dg/cpp0x/implicit4.C
@@ -1,6 +1,6 @@
// Test that a base with only a move constructor causes the implicit copy
// constructor to be deleted.
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
struct A // { dg-message "declares a move" }
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/implicit5.C b/gcc/testsuite/g++.dg/cpp0x/implicit5.C
index d25294831e3..89ab44a2c30 100644
--- a/gcc/testsuite/g++.dg/cpp0x/implicit5.C
+++ b/gcc/testsuite/g++.dg/cpp0x/implicit5.C
@@ -1,6 +1,6 @@
// Test that the default B copy constructor calls the deleted A
// copy constructor.
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A // { dg-message "declares a move" }
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/implicit6.C b/gcc/testsuite/g++.dg/cpp0x/implicit6.C
index c7902969dce..41781fb83d1 100644
--- a/gcc/testsuite/g++.dg/cpp0x/implicit6.C
+++ b/gcc/testsuite/g++.dg/cpp0x/implicit6.C
@@ -1,5 +1,5 @@
// Circular implicit declarations were causing errors
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct Ray;
diff --git a/gcc/testsuite/g++.dg/cpp0x/implicit7.C b/gcc/testsuite/g++.dg/cpp0x/implicit7.C
index f29e5009fbd..4d9d6a6076c 100644
--- a/gcc/testsuite/g++.dg/cpp0x/implicit7.C
+++ b/gcc/testsuite/g++.dg/cpp0x/implicit7.C
@@ -1,5 +1,5 @@
// PR c++/44909
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
// Declaring A<D<E>>'s copy ctor means choosing a ctor to initialize D<E>,
// which means choosing a ctor for C<B<E>>, which meant considering
// C(const B<E>&) which means choosing a ctor for B<E>, which means choosing
diff --git a/gcc/testsuite/g++.dg/cpp0x/implicit8.C b/gcc/testsuite/g++.dg/cpp0x/implicit8.C
index c949af21050..ba7f1b62a8e 100644
--- a/gcc/testsuite/g++.dg/cpp0x/implicit8.C
+++ b/gcc/testsuite/g++.dg/cpp0x/implicit8.C
@@ -1,6 +1,6 @@
// The hack for PR c++/44909 breaks this testcase. We need feedback
// from the C++ committee to know how to proceed.
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/implicit9.C b/gcc/testsuite/g++.dg/cpp0x/implicit9.C
index 3a6dbc558d9..dd5dd76e0f2 100644
--- a/gcc/testsuite/g++.dg/cpp0x/implicit9.C
+++ b/gcc/testsuite/g++.dg/cpp0x/implicit9.C
@@ -1,5 +1,5 @@
// Test that private base dtor makes derived ctor deleted
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-array2.C b/gcc/testsuite/g++.dg/cpp0x/initlist-array2.C
index 19eec33acf7..6eb5bf25e3d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist-array2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist-array2.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
typedef int IA[2];
typedef double DA[2];
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-arrray1.C b/gcc/testsuite/g++.dg/cpp0x/initlist-arrray1.C
index 25113d770b0..e3008cc559c 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist-arrray1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist-arrray1.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
typedef int IRT[2];
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-deduce.C b/gcc/testsuite/g++.dg/cpp0x/initlist-deduce.C
index 0ffcb3bcbae..13ac0b3fec4 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist-deduce.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist-deduce.C
@@ -2,7 +2,7 @@
// supported by the working draft, but is necessary for perfect forwarding
// of initializer-lists to things that can take a std::initializer_list.
-// { dg-options "-std=c++0x -fdeduce-init-list" }
+// { dg-options "-std=c++11 -fdeduce-init-list" }
// { dg-do run }
#include <initializer_list>
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-lifetime1.C b/gcc/testsuite/g++.dg/cpp0x/initlist-lifetime1.C
index e43ce5d62cd..673a05fcb59 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist-lifetime1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist-lifetime1.C
@@ -1,6 +1,6 @@
// Test that we properly extend the lifetime of the initializer_list
// array even if the initializer_list is a subobject.
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
// { dg-do run }
#include <initializer_list>
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-lifetime2.C b/gcc/testsuite/g++.dg/cpp0x/initlist-lifetime2.C
index 16ae1ac6e07..914b2c82d47 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist-lifetime2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist-lifetime2.C
@@ -1,6 +1,6 @@
// Test that we properly extend the lifetime of the initializer_list
// array even if the initializer_list is a subobject.
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
// { dg-do run }
#include <initializer_list>
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-opt.C b/gcc/testsuite/g++.dg/cpp0x/initlist-opt.C
index d17cda3f63a..9999f2ebe86 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist-opt.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist-opt.C
@@ -1,5 +1,5 @@
// PR c++/41997
-// { dg-options "-std=c++0x -O2 -fdump-tree-optimized" }
+// { dg-options "-std=c++11 -O2 -fdump-tree-optimized" }
// { dg-final { scan-tree-dump-not "_0" "optimized" } }
// { dg-final { cleanup-tree-dump "optimized" } }
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-postfix-open-square.C b/gcc/testsuite/g++.dg/cpp0x/initlist-postfix-open-square.C
index 38b17820db3..87c926ef6e2 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist-postfix-open-square.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist-postfix-open-square.C
@@ -1,5 +1,5 @@
// PR c++/51738
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct Index
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-value.C b/gcc/testsuite/g++.dg/cpp0x/initlist-value.C
index 215bb90d4df..bb40b786d30 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist-value.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist-value.C
@@ -1,5 +1,5 @@
// Test for value-initialization via {}
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
// { dg-do run }
void * operator new (__SIZE_TYPE__, void *p) { return p; }
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-value2.C b/gcc/testsuite/g++.dg/cpp0x/initlist-value2.C
index 2b78241e956..594d814e405 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist-value2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist-value2.C
@@ -2,7 +2,7 @@
// constructor but defaulted default constructor. The FDIS got this
// wrong; see c++std-core-19883.
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
// { dg-do run }
struct A
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist1.C b/gcc/testsuite/g++.dg/cpp0x/initlist1.C
index ff45f7176f6..fab577130d7 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist1.C
@@ -1,6 +1,6 @@
// Basic uses of initializer lists
// { dg-do run }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
#include <initializer_list>
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist10.C b/gcc/testsuite/g++.dg/cpp0x/initlist10.C
index bf955f513e3..0f78b2c5f66 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist10.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist10.C
@@ -1,5 +1,5 @@
// PR c++/38380
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
namespace std
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist11.C b/gcc/testsuite/g++.dg/cpp0x/initlist11.C
index 546a5335f1a..1948d3ec534 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist11.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist11.C
@@ -1,5 +1,5 @@
// PR c++/38684
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
#include <initializer_list>
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist12.C b/gcc/testsuite/g++.dg/cpp0x/initlist12.C
index f344c780cc2..f18f48f3290 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist12.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist12.C
@@ -1,5 +1,5 @@
// PR c++/38698
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// { dg-prune-output "note" }
struct A
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist13.C b/gcc/testsuite/g++.dg/cpp0x/initlist13.C
index bc5ee2c3aec..53c90590a29 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist13.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist13.C
@@ -1,6 +1,6 @@
// PR c++/39056
// { dg-do compile }
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
#include <complex>
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist14.C b/gcc/testsuite/g++.dg/cpp0x/initlist14.C
index bb67f3e54da..1760c612a8d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist14.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist14.C
@@ -1,6 +1,6 @@
// Bug: We weren't doing the normal replacement of array with pointer
// for deduction in the context of a call because of the initializer list.
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
#include <initializer_list>
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist15.C b/gcc/testsuite/g++.dg/cpp0x/initlist15.C
index b75cc81729f..55fc4a47936 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist15.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist15.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// Just discard errors pointing at header files
// { dg-prune-output "include" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist16.C b/gcc/testsuite/g++.dg/cpp0x/initlist16.C
index 86a00396051..b6d1b1a09a8 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist16.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist16.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// { dg-do run }
extern "C" void abort();
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist17.C b/gcc/testsuite/g++.dg/cpp0x/initlist17.C
index 6ea08d15003..4e78bad91d8 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist17.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist17.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x -pedantic-errors" }
+// { dg-options "-std=c++11 -pedantic-errors" }
void f(int i);
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist18.C b/gcc/testsuite/g++.dg/cpp0x/initlist18.C
index c9a9bcd9415..755c267d6cd 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist18.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist18.C
@@ -1,6 +1,6 @@
// PR c++/40308, 40311
// { dg-do run }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template< typename T >
struct test {
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist19.C b/gcc/testsuite/g++.dg/cpp0x/initlist19.C
index 9cb197c9be2..6edd069c94c 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist19.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist19.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// Allow other errors, too
// { dg-prune-output "error" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist2.C b/gcc/testsuite/g++.dg/cpp0x/initlist2.C
index 2fe4770560d..c0133dd2523 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist2.C
@@ -2,7 +2,7 @@
// user-defined conversions.
// { dg-do link }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
#include <initializer_list>
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist20.C b/gcc/testsuite/g++.dg/cpp0x/initlist20.C
index fcdb73f190c..ce2982b7f51 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist20.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist20.C
@@ -1,5 +1,5 @@
// PR c++/40689
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
class X
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist21.C b/gcc/testsuite/g++.dg/cpp0x/initlist21.C
index 16923f87d7d..bad9e003d8f 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist21.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist21.C
@@ -1,5 +1,5 @@
// PR c++/40689
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
class X
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist22.C b/gcc/testsuite/g++.dg/cpp0x/initlist22.C
index 0855b59d5d5..f913aebb906 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist22.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist22.C
@@ -1,5 +1,5 @@
// Core issue 934
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
int i;
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist23.C b/gcc/testsuite/g++.dg/cpp0x/initlist23.C
index 48a997fca20..bc37fe601a5 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist23.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist23.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
#include <initializer_list>
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist24.C b/gcc/testsuite/g++.dg/cpp0x/initlist24.C
index 33e97c7dfb4..e4c99c4fc8f 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist24.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist24.C
@@ -1,5 +1,5 @@
// PR c++/39923
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
#include <initializer_list>
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist25.C b/gcc/testsuite/g++.dg/cpp0x/initlist25.C
index 8e5e0065cfc..cf0bfdaeb13 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist25.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist25.C
@@ -1,5 +1,5 @@
// PR c++/41754
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
// { dg-do run }
#include <map>
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist26.C b/gcc/testsuite/g++.dg/cpp0x/initlist26.C
index bb28bdbd9b3..1b9dfcad6fd 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist26.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist26.C
@@ -1,6 +1,6 @@
// PR c++/42059
// { dg-do compile }
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
void
foo (int i)
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist27.C b/gcc/testsuite/g++.dg/cpp0x/initlist27.C
index f8536d3e7e7..95f93ac43aa 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist27.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist27.C
@@ -1,5 +1,5 @@
// PR c++/42061
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
int& i = { j }; // { dg-error "invalid initialization|was not declared" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist28.C b/gcc/testsuite/g++.dg/cpp0x/initlist28.C
index d1df7cb0044..b4125a5b43d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist28.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist28.C
@@ -1,5 +1,5 @@
// PR c++/42060
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
void foo()
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist29.C b/gcc/testsuite/g++.dg/cpp0x/initlist29.C
index 1568678e0d0..dbedeb9d29e 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist29.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist29.C
@@ -1,5 +1,5 @@
// PR c++/42331
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
class Mesh
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist3.C b/gcc/testsuite/g++.dg/cpp0x/initlist3.C
index 412deb51129..063a08f5633 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist3.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
#include <initializer_list>
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist30.C b/gcc/testsuite/g++.dg/cpp0x/initlist30.C
index a5bdb2eda91..e2c21ab17a3 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist30.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist30.C
@@ -1,5 +1,5 @@
// Testcase for variadic init list deduction.
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
#include <initializer_list>
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist31.C b/gcc/testsuite/g++.dg/cpp0x/initlist31.C
index ffc985567ed..85594a6fcf1 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist31.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist31.C
@@ -1,5 +1,5 @@
// PR c++/43028
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
#include <initializer_list>
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist32.C b/gcc/testsuite/g++.dg/cpp0x/initlist32.C
index 78bbb5ef996..7db5e78fd6f 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist32.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist32.C
@@ -1,5 +1,5 @@
// Test that we try normal init if no list ctor is viable.
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
#include <initializer_list>
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist33.C b/gcc/testsuite/g++.dg/cpp0x/initlist33.C
index b1c0ba09b5e..6376473922b 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist33.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist33.C
@@ -1,5 +1,5 @@
// PR c++/44045
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
struct base
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist34.C b/gcc/testsuite/g++.dg/cpp0x/initlist34.C
index 92f5a3a4605..20df3432b05 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist34.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist34.C
@@ -1,5 +1,5 @@
// PR c++/44157
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
#include <initializer_list>
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist35.C b/gcc/testsuite/g++.dg/cpp0x/initlist35.C
index e5b7cb4bd52..4b8547504c1 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist35.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist35.C
@@ -1,5 +1,5 @@
// PR c++/41510
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
struct B
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist36.C b/gcc/testsuite/g++.dg/cpp0x/initlist36.C
index a703b45907e..2d412466aef 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist36.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist36.C
@@ -1,5 +1,5 @@
// PR c++/44358
-// { dg-options "-std=c++0x -pedantic-errors" }
+// { dg-options "-std=c++11 -pedantic-errors" }
#include <initializer_list>
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist37.C b/gcc/testsuite/g++.dg/cpp0x/initlist37.C
index 20c6ab6311f..8fed990eb05 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist37.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist37.C
@@ -1,5 +1,5 @@
// DR 990
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
#include <initializer_list>
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist38.C b/gcc/testsuite/g++.dg/cpp0x/initlist38.C
index 32e20d591c7..1a4b8e50549 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist38.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist38.C
@@ -1,5 +1,5 @@
// DR 990
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
#include <initializer_list>
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist39.C b/gcc/testsuite/g++.dg/cpp0x/initlist39.C
index a6dd1ec43d1..afd8315496a 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist39.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist39.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A { int i; };
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist4.C b/gcc/testsuite/g++.dg/cpp0x/initlist4.C
index d1ffab8546c..8e5edb9abc4 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist4.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist4.C
@@ -1,5 +1,5 @@
// Test for initializer-list 'explicit' rule
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist40.C b/gcc/testsuite/g++.dg/cpp0x/initlist40.C
index 8cf36be1ca1..0592fa23f96 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist40.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist40.C
@@ -1,5 +1,5 @@
// PR c++/54835, DR 1518
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist41.C b/gcc/testsuite/g++.dg/cpp0x/initlist41.C
index b5385480c89..f07cf1dd832 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist41.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist41.C
@@ -1,5 +1,5 @@
// PR c++/44703
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
#include <initializer_list>
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist42.C b/gcc/testsuite/g++.dg/cpp0x/initlist42.C
index e63959deb21..c1ab63dc2e0 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist42.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist42.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
enum Unscoped { };
enum class Scoped { };
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist43.C b/gcc/testsuite/g++.dg/cpp0x/initlist43.C
index 72a09bdea49..6e524f4bf63 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist43.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist43.C
@@ -1,5 +1,5 @@
// Test that using T{} at file scope doesn't create a static temporary.
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
// { dg-final { scan-assembler-not "local" } }
struct A { };
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist44.C b/gcc/testsuite/g++.dg/cpp0x/initlist44.C
index fbe0ea3fefe..1c6403336a9 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist44.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist44.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
#include <initializer_list>
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist45.C b/gcc/testsuite/g++.dg/cpp0x/initlist45.C
index 0e34bc18977..c4c1867bf67 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist45.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist45.C
@@ -1,5 +1,5 @@
// PR c++/46289
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist46.C b/gcc/testsuite/g++.dg/cpp0x/initlist46.C
index 2b9f07dbdc9..64bc314ffbd 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist46.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist46.C
@@ -1,5 +1,5 @@
// PR c++/48281
-// { dg-options "-std=c++0x -O2" }
+// { dg-options "-std=c++11 -O2" }
// { dg-do run }
#include <initializer_list>
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist47.C b/gcc/testsuite/g++.dg/cpp0x/initlist47.C
index 06d683e038a..91f7d5edd84 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist47.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist47.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A { ~A() = delete; }; // { dg-message "declared" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist48.C b/gcc/testsuite/g++.dg/cpp0x/initlist48.C
index 9eb451a8277..b8a5cf2d960 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist48.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist48.C
@@ -1,5 +1,5 @@
// PR c++/48726
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
#include <memory>
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist49.C b/gcc/testsuite/g++.dg/cpp0x/initlist49.C
index 752c4331afb..cfed1547423 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist49.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist49.C
@@ -1,5 +1,5 @@
// Test for non-trivial list-initialization with array new.
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
// { dg-do run }
struct A
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist5.C b/gcc/testsuite/g++.dg/cpp0x/initlist5.C
index 51345c73fc1..ed8f00a7a73 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist5.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist5.C
@@ -1,5 +1,5 @@
// Test for narrowing diagnostics
-// { dg-options "-std=c++0x -pedantic-errors" }
+// { dg-options "-std=c++11 -pedantic-errors" }
#include <initializer_list>
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist50.C b/gcc/testsuite/g++.dg/cpp0x/initlist50.C
index 5cb23e2db3e..50b5d18efb3 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist50.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist50.C
@@ -1,5 +1,5 @@
// PR c++/45418
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A1 { };
struct A2 {
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist51.C b/gcc/testsuite/g++.dg/cpp0x/initlist51.C
index 9163dd3a867..1a63570f6a9 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist51.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist51.C
@@ -1,5 +1,5 @@
// PR c++/47184
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct S
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist52.C b/gcc/testsuite/g++.dg/cpp0x/initlist52.C
index 17c0cfe3f14..8a70513bca9 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist52.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist52.C
@@ -1,5 +1,5 @@
// PR c++/45378
-// { dg-options "-std=c++0x -pedantic-errors" }
+// { dg-options "-std=c++11 -pedantic-errors" }
int main()
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist53.C b/gcc/testsuite/g++.dg/cpp0x/initlist53.C
index 22633f90955..8e5332704be 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist53.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist53.C
@@ -1,5 +1,5 @@
// PR c++/49216
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
// { dg-do run }
#include <initializer_list>
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist54.C b/gcc/testsuite/g++.dg/cpp0x/initlist54.C
index cdb296133f8..d50c230dba6 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist54.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist54.C
@@ -1,5 +1,5 @@
// PR c++/49355
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
#include <string>
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist55.C b/gcc/testsuite/g++.dg/cpp0x/initlist55.C
index cb42e81ed6a..917bc935470 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist55.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist55.C
@@ -1,5 +1,5 @@
// Test for -Wno-narrowing
-// { dg-options "-std=c++0x -pedantic-errors -Wno-narrowing" }
+// { dg-options "-std=c++11 -pedantic-errors -Wno-narrowing" }
int i;
float d = { i };
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist56.C b/gcc/testsuite/g++.dg/cpp0x/initlist56.C
index 862b41bb3c8..72ad364ef27 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist56.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist56.C
@@ -1,5 +1,5 @@
// PR c++/47453
-// { dg-options "-std=c++0x -pedantic-errors" }
+// { dg-options "-std=c++11 -pedantic-errors" }
// invalid
int a({0}); // { dg-error "" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist57.C b/gcc/testsuite/g++.dg/cpp0x/initlist57.C
index d945a468988..1a44b8124d0 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist57.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist57.C
@@ -1,5 +1,5 @@
// PR c++/50054
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
void g( const int& (a)[1] ) {} // { dg-error "array of references" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist58.C b/gcc/testsuite/g++.dg/cpp0x/initlist58.C
index dfb9f0cd508..a04e191b57d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist58.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist58.C
@@ -1,5 +1,5 @@
// PR c++/50209
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct S { int i,j; };
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist59.C b/gcc/testsuite/g++.dg/cpp0x/initlist59.C
index 2cc015d1fee..3974042d26e 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist59.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist59.C
@@ -1,5 +1,5 @@
// PR c++/49996
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist6.C b/gcc/testsuite/g++.dg/cpp0x/initlist6.C
index 523570315eb..631bbd0407a 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist6.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist6.C
@@ -1,5 +1,5 @@
// Test for initlist lifetime
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// { dg-do run }
#include <initializer_list>
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist62.C b/gcc/testsuite/g++.dg/cpp0x/initlist62.C
index cabbcd1db4e..3a25e13f1ef 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist62.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist62.C
@@ -1,5 +1,5 @@
// PR c++/51399
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
#include <initializer_list>
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist64.C b/gcc/testsuite/g++.dg/cpp0x/initlist64.C
index bcf1658074d..1550d477fb3 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist64.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist64.C
@@ -1,5 +1,5 @@
// PR c++/51553
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct X
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist7.C b/gcc/testsuite/g++.dg/cpp0x/initlist7.C
index 55a0371860f..73c924250bf 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist7.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist7.C
@@ -1,5 +1,5 @@
// PR c++/37932
-// { dg-options "-std=c++0x -pedantic-errors" }
+// { dg-options "-std=c++11 -pedantic-errors" }
typedef enum { AA=1, BB=2 } my_enum;
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist74.C b/gcc/testsuite/g++.dg/cpp0x/initlist74.C
new file mode 100644
index 00000000000..4305b59a0ec
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist74.C
@@ -0,0 +1,7 @@
+// Core 1591
+// { dg-require-effective-target c++11 }
+
+template<class T, int N> void g(T const (&)[N]);
+void f() {
+ g( { 1, 2, 3, 4 } );
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist8.C b/gcc/testsuite/g++.dg/cpp0x/initlist8.C
index db63eee78b6..e2c85d70d20 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist8.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist8.C
@@ -1,5 +1,5 @@
// PR c++/37740
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist9.C b/gcc/testsuite/g++.dg/cpp0x/initlist9.C
index 197fdd4ad04..0ad39463bc0 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist9.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist9.C
@@ -1,5 +1,5 @@
// PR c++/37860
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
struct b
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/inline-ns1.C b/gcc/testsuite/g++.dg/cpp0x/inline-ns1.C
index e422d8970f1..287b7e072aa 100644
--- a/gcc/testsuite/g++.dg/cpp0x/inline-ns1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/inline-ns1.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
// { dg-final { scan-assembler "_ZN1Q2V11fEv" } }
// { dg-final { scan-assembler "_ZN1Q2V11iE" } }
diff --git a/gcc/testsuite/g++.dg/cpp0x/inline-ns2.C b/gcc/testsuite/g++.dg/cpp0x/inline-ns2.C
index 17a8bf60192..19fb9adfe90 100644
--- a/gcc/testsuite/g++.dg/cpp0x/inline-ns2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/inline-ns2.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
namespace Q {
inline namespace V1 {
diff --git a/gcc/testsuite/g++.dg/cpp0x/inline-ns3.C b/gcc/testsuite/g++.dg/cpp0x/inline-ns3.C
index 7c9d6b9b546..4e8449e30ec 100644
--- a/gcc/testsuite/g++.dg/cpp0x/inline-ns3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/inline-ns3.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
namespace C
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/iop.C b/gcc/testsuite/g++.dg/cpp0x/iop.C
index 2eb3a3ce337..34a5a5a1c2d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/iop.C
+++ b/gcc/testsuite/g++.dg/cpp0x/iop.C
@@ -7,7 +7,7 @@
// section "Revision 1 Summary and Rationale" for more details.
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// { dg-skip-if "packed attribute missing for struct one" { "epiphany-*-*" } { "*" } { "" } }
template <bool> struct sa;
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice10.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice10.C
new file mode 100644
index 00000000000..1ea59c21c84
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice10.C
@@ -0,0 +1,8 @@
+// PR c++/58568
+// { dg-do compile { target c++11 } }
+
+template<int> struct A
+{
+ static const int i;
+ template<int N> const int A<N>::i = []{ return 0; }(); // { dg-error "invalid use" }
+};
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nsdmi5.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nsdmi5.C
new file mode 100644
index 00000000000..1d2778fb5ac
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nsdmi5.C
@@ -0,0 +1,7 @@
+// PR c++/58596
+// { dg-do compile { target c++11 } }
+
+struct A
+{
+ int i = [] { return decltype(i)(); }();
+};
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this17.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this17.C
new file mode 100644
index 00000000000..2386e6b1eb8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this17.C
@@ -0,0 +1,21 @@
+// PR c++/58481
+// { dg-require-effective-target c++11 }
+
+struct Test {
+ template<typename... Args> inline void triggerTest (Args&&... fargs) { }
+};
+
+struct TestPickled : Test {
+ template<typename... Args> void triggerTest (Args&&... fargs) {
+ [=](Args... as) {
+ Test::triggerTest (as...);
+ } ();
+ }
+};
+
+int main()
+{
+ TestPickled test;
+ test.triggerTest ();
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/linkage2.C b/gcc/testsuite/g++.dg/cpp0x/linkage2.C
index f41c21a7741..d9932948a20 100644
--- a/gcc/testsuite/g++.dg/cpp0x/linkage2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/linkage2.C
@@ -4,7 +4,7 @@
// o the variable or function is not used (3.2 [basic.def.odr]) or is
// defined in the same translation unit.
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template <typename T> struct B {
void g(T){}
diff --git a/gcc/testsuite/g++.dg/cpp0x/long_long.C b/gcc/testsuite/g++.dg/cpp0x/long_long.C
index 3ef710df483..eb6a326bba3 100644
--- a/gcc/testsuite/g++.dg/cpp0x/long_long.C
+++ b/gcc/testsuite/g++.dg/cpp0x/long_long.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x -pedantic" }
+// { dg-options "-std=c++11 -pedantic" }
void foo()
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/move1.C b/gcc/testsuite/g++.dg/cpp0x/move1.C
index 12e363a8cab..f86618a7036 100644
--- a/gcc/testsuite/g++.dg/cpp0x/move1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/move1.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x -pedantic-errors" }
+// { dg-options "-std=c++11 -pedantic-errors" }
#include <utility>
diff --git a/gcc/testsuite/g++.dg/cpp0x/named.C b/gcc/testsuite/g++.dg/cpp0x/named.C
index 2dff24ca475..e97f4f6fd6a 100644
--- a/gcc/testsuite/g++.dg/cpp0x/named.C
+++ b/gcc/testsuite/g++.dg/cpp0x/named.C
@@ -1,4 +1,4 @@
-// { dg-options "--std=c++0x" }
+// { dg-options "--std=c++11" }
// { dg-do link }
template<typename _Tp>
diff --git a/gcc/testsuite/g++.dg/cpp0x/named_refs.C b/gcc/testsuite/g++.dg/cpp0x/named_refs.C
index 0ccd42f4a0f..f710f1e1f73 100644
--- a/gcc/testsuite/g++.dg/cpp0x/named_refs.C
+++ b/gcc/testsuite/g++.dg/cpp0x/named_refs.C
@@ -3,7 +3,7 @@
// Test: Named rvalue references are treated as lvalues.
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// { dg-skip-if "packed attribute missing for struct one" { "epiphany-*-*" } { "*" } { "" } }
template <bool> struct sa;
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept01.C b/gcc/testsuite/g++.dg/cpp0x/noexcept01.C
index b6be1ef7a3f..4526cd30158 100644
--- a/gcc/testsuite/g++.dg/cpp0x/noexcept01.C
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept01.C
@@ -1,5 +1,5 @@
// Test for noexcept-expression
-// { dg-options "-std=c++0x -O2" }
+// { dg-options "-std=c++11 -O2" }
#include <typeinfo>
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept02.C b/gcc/testsuite/g++.dg/cpp0x/noexcept02.C
index ffbb0919241..78831762491 100644
--- a/gcc/testsuite/g++.dg/cpp0x/noexcept02.C
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept02.C
@@ -1,5 +1,5 @@
// Test for noexcept-specification
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
#define SA(X) static_assert(X, #X)
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept03.C b/gcc/testsuite/g++.dg/cpp0x/noexcept03.C
index 41c442e90be..b45cf365ce2 100644
--- a/gcc/testsuite/g++.dg/cpp0x/noexcept03.C
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept03.C
@@ -1,5 +1,5 @@
// Runtime test for noexcept-specification.
-// { dg-options "-std=c++0x -Wnoexcept" }
+// { dg-options "-std=c++11 -Wnoexcept" }
// { dg-do run { target nonpic } }
#include <exception>
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept04.C b/gcc/testsuite/g++.dg/cpp0x/noexcept04.C
index 8df818610f5..6d31e5b4ca7 100644
--- a/gcc/testsuite/g++.dg/cpp0x/noexcept04.C
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept04.C
@@ -3,7 +3,7 @@
// the compiler doesn't get clever about optimizing the calls based on
// knowledge about the called functions.
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// { dg-do run }
#include <exception>
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept05.C b/gcc/testsuite/g++.dg/cpp0x/noexcept05.C
index 6acea432736..8c74712b647 100644
--- a/gcc/testsuite/g++.dg/cpp0x/noexcept05.C
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept05.C
@@ -8,7 +8,7 @@
// { dg-final { scan-assembler-not "EHB" } }
// { dg-final { scan-assembler "LSDA" } }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
struct A { ~A(); };
void g();
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept06.C b/gcc/testsuite/g++.dg/cpp0x/noexcept06.C
index 3babdffdad5..5168dc640fc 100644
--- a/gcc/testsuite/g++.dg/cpp0x/noexcept06.C
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept06.C
@@ -1,6 +1,6 @@
// Test that checking of a nothrow specification uses the one on the
// definition.
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// { dg-do run }
#include <exception>
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept07.C b/gcc/testsuite/g++.dg/cpp0x/noexcept07.C
index 0a5773fc86b..f6df39f950e 100644
--- a/gcc/testsuite/g++.dg/cpp0x/noexcept07.C
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept07.C
@@ -1,6 +1,6 @@
// Test that checking of a nothrow specification uses the one on the
// definition.
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// { dg-do run }
#include <exception>
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept08.C b/gcc/testsuite/g++.dg/cpp0x/noexcept08.C
index 1df85efff9c..bceebb7ca19 100644
--- a/gcc/testsuite/g++.dg/cpp0x/noexcept08.C
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept08.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// { dg-prune-output "overriding" }
struct A
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept09.C b/gcc/testsuite/g++.dg/cpp0x/noexcept09.C
index 2a4525cbd6c..b50ef9975db 100644
--- a/gcc/testsuite/g++.dg/cpp0x/noexcept09.C
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept09.C
@@ -1,5 +1,5 @@
// Test that -Wnoexcept works with templates
-// { dg-options "-std=c++0x -Wnoexcept" }
+// { dg-options "-std=c++11 -Wnoexcept" }
template <class T>
T f (T t) { return t; } // { dg-warning "does not throw" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept10.C b/gcc/testsuite/g++.dg/cpp0x/noexcept10.C
index 058a387d778..1e86ac205ba 100644
--- a/gcc/testsuite/g++.dg/cpp0x/noexcept10.C
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept10.C
@@ -1,5 +1,5 @@
// PR c++/49082
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
namespace std { template <class T> T&& declval() noexcept; }
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept11.C b/gcc/testsuite/g++.dg/cpp0x/noexcept11.C
index b7c64a6ef06..879a63ee5e2 100644
--- a/gcc/testsuite/g++.dg/cpp0x/noexcept11.C
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept11.C
@@ -1,5 +1,5 @@
// PR c++/49107
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<typename _Tp>
_Tp declval() noexcept;
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept12.C b/gcc/testsuite/g++.dg/cpp0x/noexcept12.C
index 1fd1b032f4c..592504bd5e9 100644
--- a/gcc/testsuite/g++.dg/cpp0x/noexcept12.C
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept12.C
@@ -1,5 +1,5 @@
// Test that we handle merging with deferred noexcept.
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template <class U>
struct O
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept13.C b/gcc/testsuite/g++.dg/cpp0x/noexcept13.C
index 7d51c82b549..7e76200befe 100644
--- a/gcc/testsuite/g++.dg/cpp0x/noexcept13.C
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept13.C
@@ -1,5 +1,5 @@
// PR c++/49107
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
namespace std
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept14.C b/gcc/testsuite/g++.dg/cpp0x/noexcept14.C
index eba2c408089..e6afca2b43a 100644
--- a/gcc/testsuite/g++.dg/cpp0x/noexcept14.C
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept14.C
@@ -1,4 +1,4 @@
// PR c++/50309
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
void foo () noexcept () { } // { dg-error "expected" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept15.C b/gcc/testsuite/g++.dg/cpp0x/noexcept15.C
index db5b5c7f3d7..efbd2ba90b6 100644
--- a/gcc/testsuite/g++.dg/cpp0x/noexcept15.C
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept15.C
@@ -1,5 +1,5 @@
// PR c++/50391
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
#include <type_traits>
diff --git a/gcc/testsuite/g++.dg/cpp0x/nolinkage1.C b/gcc/testsuite/g++.dg/cpp0x/nolinkage1.C
index b69b6ddc4cf..a7e6cd82c0d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/nolinkage1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/nolinkage1.C
@@ -3,7 +3,7 @@
// { dg-additional-sources "nolinkage1a.cc" }
// { dg-do link }
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
#include "nolinkage1.h"
diff --git a/gcc/testsuite/g++.dg/cpp0x/not_special.C b/gcc/testsuite/g++.dg/cpp0x/not_special.C
index 2b510bb9a1b..7b3c4ad1e3d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/not_special.C
+++ b/gcc/testsuite/g++.dg/cpp0x/not_special.C
@@ -4,7 +4,7 @@
// That is, their presence should cause compiler declared
// copy ctor or assignment to be deleted.
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
#include <assert.h>
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-const1.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-const1.C
index ddf9f04c580..1051288a4d8 100644
--- a/gcc/testsuite/g++.dg/cpp0x/nsdmi-const1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-const1.C
@@ -1,5 +1,5 @@
// PR c++/50707
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
int g;
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer1.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer1.C
index b3d9b935750..4398739c8cd 100644
--- a/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer1.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
#define SA(X) static_assert(X,#X)
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer2.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer2.C
index 1951262f9da..e4b963c9436 100644
--- a/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer2.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer3.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer3.C
index 2777fb5d8e6..3aae12c2a4c 100644
--- a/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer3.C
@@ -1,5 +1,5 @@
// Do NSDMI get deferred instantiation?
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template <class T>
struct A
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer4.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer4.C
index 65b2e738077..9d39f29df6e 100644
--- a/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer4.C
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer4.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
// { dg-do run }
struct A
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer5.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer5.C
index 85abfbf8618..ada5104615d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer5.C
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer5.C
@@ -1,5 +1,5 @@
// PR c++/51666 (DR 325)
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<typename T, typename U>
struct tuple
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-eh1.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-eh1.C
index 09c92d2f158..301eb61053e 100644
--- a/gcc/testsuite/g++.dg/cpp0x/nsdmi-eh1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-eh1.C
@@ -1,6 +1,6 @@
// Core issue 1351
// { dg-do run { xfail *-*-* } }
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
bool fail;
struct A
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-list1.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-list1.C
index 526f29ae285..68af7353755 100644
--- a/gcc/testsuite/g++.dg/cpp0x/nsdmi-list1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-list1.C
@@ -1,5 +1,5 @@
// PR c++/50563
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct S1 {
int a{10}, b{20}; // OK
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-list2.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-list2.C
index a6321ffb605..0d71417389f 100644
--- a/gcc/testsuite/g++.dg/cpp0x/nsdmi-list2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-list2.C
@@ -1,5 +1,5 @@
// PR c++/50930
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct nmc {
nmc() = default;
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-template1.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template1.C
index 04f1e0391d9..aa77680f2e9 100644
--- a/gcc/testsuite/g++.dg/cpp0x/nsdmi-template1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template1.C
@@ -1,5 +1,5 @@
// { dg-do run }
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct base
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-template2.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template2.C
index 27b0aa5f9da..952949c8950 100644
--- a/gcc/testsuite/g++.dg/cpp0x/nsdmi-template2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template2.C
@@ -1,5 +1,5 @@
// PR c++/50614
-// { dg-options "-std=c++0x -fcompare-debug" }
+// { dg-options "-std=c++11 -fcompare-debug" }
struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-virtual1.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-virtual1.C
index 4aa8d482da8..edf54bb1d2d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/nsdmi-virtual1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-virtual1.C
@@ -1,5 +1,5 @@
// PR c++/51611
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
// { dg-do run }
struct A
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi1.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi1.C
index 159c16de851..a840700e88c 100644
--- a/gcc/testsuite/g++.dg/cpp0x/nsdmi1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi1.C
@@ -1,5 +1,5 @@
// { dg-do run }
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi2.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi2.C
index 9636bed8820..5be3366f1dd 100644
--- a/gcc/testsuite/g++.dg/cpp0x/nsdmi2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi2.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi3.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi3.C
index 73b2bc2e1ac..3024e731587 100644
--- a/gcc/testsuite/g++.dg/cpp0x/nsdmi3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi3.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi4.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi4.C
index db365cb55e5..08579eef194 100644
--- a/gcc/testsuite/g++.dg/cpp0x/nsdmi4.C
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi4.C
@@ -1,5 +1,5 @@
// { dg-do run }
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
int c;
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi5.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi5.C
index 62803b0819e..9b33346422c 100644
--- a/gcc/testsuite/g++.dg/cpp0x/nsdmi5.C
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi5.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct X
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi9.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi9.C
new file mode 100644
index 00000000000..febe0ecac46
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi9.C
@@ -0,0 +1,13 @@
+// PR c++/58162
+// { dg-require-effective-target c++11 }
+
+struct A {
+ A();
+ A(A&&);
+};
+
+struct B {
+ A const a = A();
+};
+
+B b;
diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr01.C b/gcc/testsuite/g++.dg/cpp0x/nullptr01.C
index de3860c9ea4..27643e6b732 100644
--- a/gcc/testsuite/g++.dg/cpp0x/nullptr01.C
+++ b/gcc/testsuite/g++.dg/cpp0x/nullptr01.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// Test assignment to pointer
diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr02.C b/gcc/testsuite/g++.dg/cpp0x/nullptr02.C
index 80977cb2f00..7c330743b8c 100644
--- a/gcc/testsuite/g++.dg/cpp0x/nullptr02.C
+++ b/gcc/testsuite/g++.dg/cpp0x/nullptr02.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// Test assignment to nullptr_t
diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr03.C b/gcc/testsuite/g++.dg/cpp0x/nullptr03.C
index b6df8963740..aaf199ce0db 100644
--- a/gcc/testsuite/g++.dg/cpp0x/nullptr03.C
+++ b/gcc/testsuite/g++.dg/cpp0x/nullptr03.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// Test assignment to int
diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr04.C b/gcc/testsuite/g++.dg/cpp0x/nullptr04.C
index be581bcb6e3..999f05467c3 100644
--- a/gcc/testsuite/g++.dg/cpp0x/nullptr04.C
+++ b/gcc/testsuite/g++.dg/cpp0x/nullptr04.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// Test cast to int
diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr05.C b/gcc/testsuite/g++.dg/cpp0x/nullptr05.C
index 22a8b51c1c7..e6e6a1bb9d3 100644
--- a/gcc/testsuite/g++.dg/cpp0x/nullptr05.C
+++ b/gcc/testsuite/g++.dg/cpp0x/nullptr05.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// Test assignment to method pointer
diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr06.C b/gcc/testsuite/g++.dg/cpp0x/nullptr06.C
index c50bb9bc113..9b7b4dccfce 100644
--- a/gcc/testsuite/g++.dg/cpp0x/nullptr06.C
+++ b/gcc/testsuite/g++.dg/cpp0x/nullptr06.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// Test compare to pointer
diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr07.C b/gcc/testsuite/g++.dg/cpp0x/nullptr07.C
index 64d442be331..b2c27e81114 100644
--- a/gcc/testsuite/g++.dg/cpp0x/nullptr07.C
+++ b/gcc/testsuite/g++.dg/cpp0x/nullptr07.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// Test compare to int
diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr08.C b/gcc/testsuite/g++.dg/cpp0x/nullptr08.C
index 1e5db278ddf..d09e070eaa8 100644
--- a/gcc/testsuite/g++.dg/cpp0x/nullptr08.C
+++ b/gcc/testsuite/g++.dg/cpp0x/nullptr08.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// Test conversion to bool
diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr09.C b/gcc/testsuite/g++.dg/cpp0x/nullptr09.C
index b35a3c3207d..df6f5014a01 100644
--- a/gcc/testsuite/g++.dg/cpp0x/nullptr09.C
+++ b/gcc/testsuite/g++.dg/cpp0x/nullptr09.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// Test compare to literal 0
diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr10.C b/gcc/testsuite/g++.dg/cpp0x/nullptr10.C
index fa32267ec02..4924dba9ce1 100644
--- a/gcc/testsuite/g++.dg/cpp0x/nullptr10.C
+++ b/gcc/testsuite/g++.dg/cpp0x/nullptr10.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// Test arithmetic operations
diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr11.C b/gcc/testsuite/g++.dg/cpp0x/nullptr11.C
index 5907816a847..91e8e71a3a8 100644
--- a/gcc/testsuite/g++.dg/cpp0x/nullptr11.C
+++ b/gcc/testsuite/g++.dg/cpp0x/nullptr11.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// Test relational operators
diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr12.C b/gcc/testsuite/g++.dg/cpp0x/nullptr12.C
index 1713259f103..0c131518297 100644
--- a/gcc/testsuite/g++.dg/cpp0x/nullptr12.C
+++ b/gcc/testsuite/g++.dg/cpp0x/nullptr12.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// Test sizeof
diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr13.C b/gcc/testsuite/g++.dg/cpp0x/nullptr13.C
index a9377584c56..c51c81ef962 100644
--- a/gcc/testsuite/g++.dg/cpp0x/nullptr13.C
+++ b/gcc/testsuite/g++.dg/cpp0x/nullptr13.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// Test typeid
diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr14.C b/gcc/testsuite/g++.dg/cpp0x/nullptr14.C
index 4c4627b541b..1e9e5173786 100644
--- a/gcc/testsuite/g++.dg/cpp0x/nullptr14.C
+++ b/gcc/testsuite/g++.dg/cpp0x/nullptr14.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// Test overload preference char*/int
diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr15.C b/gcc/testsuite/g++.dg/cpp0x/nullptr15.C
index af661ecc3af..1f91bae4fe5 100644
--- a/gcc/testsuite/g++.dg/cpp0x/nullptr15.C
+++ b/gcc/testsuite/g++.dg/cpp0x/nullptr15.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// Test template deduction
diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr16.C b/gcc/testsuite/g++.dg/cpp0x/nullptr16.C
index 0ec0b6a12b6..9456523037b 100644
--- a/gcc/testsuite/g++.dg/cpp0x/nullptr16.C
+++ b/gcc/testsuite/g++.dg/cpp0x/nullptr16.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// Test template deduction
diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr17.C b/gcc/testsuite/g++.dg/cpp0x/nullptr17.C
index 2e580557bc3..72884149525 100644
--- a/gcc/testsuite/g++.dg/cpp0x/nullptr17.C
+++ b/gcc/testsuite/g++.dg/cpp0x/nullptr17.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// Test that bool is a better overload match than int
diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr18.C b/gcc/testsuite/g++.dg/cpp0x/nullptr18.C
index b8fa38c718d..656628828f4 100644
--- a/gcc/testsuite/g++.dg/cpp0x/nullptr18.C
+++ b/gcc/testsuite/g++.dg/cpp0x/nullptr18.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// Test overload of pointer versus bool when applied on a nullptr_t
diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr19.C b/gcc/testsuite/g++.dg/cpp0x/nullptr19.C
index ecc36139a40..92e7f9a88d2 100644
--- a/gcc/testsuite/g++.dg/cpp0x/nullptr19.C
+++ b/gcc/testsuite/g++.dg/cpp0x/nullptr19.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// Test overload of pointer versus nullptr_t when applied on a literal 0/__null
diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr20.C b/gcc/testsuite/g++.dg/cpp0x/nullptr20.C
index 3e58406770d..6c07eced7d1 100644
--- a/gcc/testsuite/g++.dg/cpp0x/nullptr20.C
+++ b/gcc/testsuite/g++.dg/cpp0x/nullptr20.C
@@ -1,5 +1,5 @@
// { dg-do run }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// Test passing to ellipisis
diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr21.C b/gcc/testsuite/g++.dg/cpp0x/nullptr21.C
index 8362bd2965b..0355b826062 100644
--- a/gcc/testsuite/g++.dg/cpp0x/nullptr21.C
+++ b/gcc/testsuite/g++.dg/cpp0x/nullptr21.C
@@ -1,5 +1,5 @@
// { dg-do run }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// Test throw and catch
diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr22.C b/gcc/testsuite/g++.dg/cpp0x/nullptr22.C
index d800f9869d2..08c3b0ae037 100644
--- a/gcc/testsuite/g++.dg/cpp0x/nullptr22.C
+++ b/gcc/testsuite/g++.dg/cpp0x/nullptr22.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-std=c++0x -Wall -Wformat=2 -Wstrict-null-sentinel" }
+// { dg-options "-std=c++11 -Wall -Wformat=2 -Wstrict-null-sentinel" }
// Test various warnings
diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr23.C b/gcc/testsuite/g++.dg/cpp0x/nullptr23.C
index a078269de20..077cd36806e 100644
--- a/gcc/testsuite/g++.dg/cpp0x/nullptr23.C
+++ b/gcc/testsuite/g++.dg/cpp0x/nullptr23.C
@@ -1,5 +1,5 @@
// PR c++/50361
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
#include <initializer_list>
diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr24.C b/gcc/testsuite/g++.dg/cpp0x/nullptr24.C
index f3917796627..e7833d11ef4 100644
--- a/gcc/testsuite/g++.dg/cpp0x/nullptr24.C
+++ b/gcc/testsuite/g++.dg/cpp0x/nullptr24.C
@@ -1,5 +1,5 @@
// PR c++/50371
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<decltype(nullptr)>
struct nt;
diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr25.C b/gcc/testsuite/g++.dg/cpp0x/nullptr25.C
index b8a7f45c674..bdc2ed3ad5c 100644
--- a/gcc/testsuite/g++.dg/cpp0x/nullptr25.C
+++ b/gcc/testsuite/g++.dg/cpp0x/nullptr25.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<decltype(nullptr)>
struct nt{};
diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr26.C b/gcc/testsuite/g++.dg/cpp0x/nullptr26.C
index b7421b8d048..457e3ae2d34 100644
--- a/gcc/testsuite/g++.dg/cpp0x/nullptr26.C
+++ b/gcc/testsuite/g++.dg/cpp0x/nullptr26.C
@@ -1,5 +1,5 @@
// PR c++/51530
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template <class T, class U>
void f(T, U);
diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr30.C b/gcc/testsuite/g++.dg/cpp0x/nullptr30.C
new file mode 100644
index 00000000000..3673999d884
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/nullptr30.C
@@ -0,0 +1,40 @@
+// PR c++/58176
+// { dg-do compile { target c++11 } }
+
+// Nil
+struct nil_ { constexpr nil_ () {} };
+constexpr nil_ nil;
+
+// Cons
+template <class H, class T = nil_>
+struct cons_ {
+ using head_ = H;
+ using tail_ = T;
+
+ H head;
+ T tail;
+
+ constexpr cons_() {}
+ constexpr cons_(H const &h, T const &t) : head(h), tail(t) {}
+};
+template <class H, class T = nil_>
+constexpr cons_<H, T> cons (H const &h, T const &t = nil) { return
+cons_<H,T>(h,t); }
+
+// List
+template <class... T> struct list_s;
+template <class H, class... T>
+struct list_s<H, T...> {
+ using type = cons_<H, typename list_s<T...>::type>;
+};
+template <>
+struct list_s<> {
+ using type = nil_;
+};
+template <class... T>
+using list_ = typename list_s<T...>::type;
+constexpr nil_ list () { return nil; }
+template <class H, class... T>
+constexpr list_<H, T...> list (H h, T... t) { return cons(h, list(t...)); }
+
+constexpr auto l1 = list("monkey", 123.4, cons(1, 2), nullptr);
diff --git a/gcc/testsuite/g++.dg/cpp0x/overload-conv-1.C b/gcc/testsuite/g++.dg/cpp0x/overload-conv-1.C
index 778111283ff..2661060b6e7 100644
--- a/gcc/testsuite/g++.dg/cpp0x/overload-conv-1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/overload-conv-1.C
@@ -1,4 +1,4 @@
-// { dg-options "--std=c++0x" }
+// { dg-options "--std=c++11" }
// { dg-do link }
struct S {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/overload-conv-2.C b/gcc/testsuite/g++.dg/cpp0x/overload-conv-2.C
index 0e622bcacb2..a3fdd3a8fa4 100644
--- a/gcc/testsuite/g++.dg/cpp0x/overload-conv-2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/overload-conv-2.C
@@ -1,4 +1,4 @@
-// { dg-options "--std=c++0x" }
+// { dg-options "--std=c++11" }
// { dg-do link }
struct T {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/overload.C b/gcc/testsuite/g++.dg/cpp0x/overload.C
index 3782d4a208e..b10bb43fe11 100644
--- a/gcc/testsuite/g++.dg/cpp0x/overload.C
+++ b/gcc/testsuite/g++.dg/cpp0x/overload.C
@@ -1,4 +1,4 @@
-// { dg-options "--std=c++0x" }
+// { dg-options "--std=c++11" }
// { dg-do link }
// Generated by overload.py
diff --git a/gcc/testsuite/g++.dg/cpp0x/overload2.C b/gcc/testsuite/g++.dg/cpp0x/overload2.C
index b335ea2be99..e532fa25d54 100644
--- a/gcc/testsuite/g++.dg/cpp0x/overload2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/overload2.C
@@ -1,5 +1,5 @@
// Core 1321
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
// Two dependent names are equivalent even if the overload sets found by
// phase 1 lookup are different. Merging them keeps the earlier set.
diff --git a/gcc/testsuite/g++.dg/cpp0x/overloadn.C b/gcc/testsuite/g++.dg/cpp0x/overloadn.C
index a42707fe4f1..00f9fde4900 100644
--- a/gcc/testsuite/g++.dg/cpp0x/overloadn.C
+++ b/gcc/testsuite/g++.dg/cpp0x/overloadn.C
@@ -1,4 +1,4 @@
-// { dg-options "--std=c++0x" }
+// { dg-options "--std=c++11" }
// { dg-do link }
// Generated by overload.py
diff --git a/gcc/testsuite/g++.dg/cpp0x/override1.C b/gcc/testsuite/g++.dg/cpp0x/override1.C
index ba580b5c09f..5b487106bfa 100644
--- a/gcc/testsuite/g++.dg/cpp0x/override1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/override1.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "--std=c++0x" }
+// { dg-options "--std=c++11" }
struct B
{
virtual void f() final {}
diff --git a/gcc/testsuite/g++.dg/cpp0x/override2.C b/gcc/testsuite/g++.dg/cpp0x/override2.C
index 1a7a36e1ae0..e5a9aa6ac50 100644
--- a/gcc/testsuite/g++.dg/cpp0x/override2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/override2.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "--std=c++0x" }
+// { dg-options "--std=c++11" }
struct B1 {};
struct B2 final {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/parse1.C b/gcc/testsuite/g++.dg/cpp0x/parse1.C
index 4fa7461cb22..0a86caf4ac4 100644
--- a/gcc/testsuite/g++.dg/cpp0x/parse1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/parse1.C
@@ -1,5 +1,5 @@
// PR c++/43509
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
typedef int B; // { dg-message "" }
B::B() {} // { dg-error "" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr31431-2.C b/gcc/testsuite/g++.dg/cpp0x/pr31431-2.C
index 076493938a8..95901e56aa1 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr31431-2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr31431-2.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename, typename..., typename> void foo(); // { dg-message "note" }
void bar()
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr31431.C b/gcc/testsuite/g++.dg/cpp0x/pr31431.C
index afd32371574..1e7507cd8b8 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr31431.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr31431.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename..., typename> void foo(); // { dg-message "note" }
void bar()
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr31432.C b/gcc/testsuite/g++.dg/cpp0x/pr31432.C
index 8016ee69d75..f4de1973bd9 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr31432.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr31432.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename..., typename> struct A // { dg-error "parameter pack" }
{
static int i;
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr31434.C b/gcc/testsuite/g++.dg/cpp0x/pr31434.C
index 54786167c35..3bce5785eca 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr31434.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr31434.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename... T> int foo(const T&) // { dg-error "not expanded with|T" }
{
union { T t; }; // { dg-error "not expanded with|T" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr31437.C b/gcc/testsuite/g++.dg/cpp0x/pr31437.C
index 956a08b058d..b7a7bbf28bf 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr31437.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr31437.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template <typename... T> struct A // { dg-message "candidates|A" }
{
A(T* p) { // { dg-error "parameter packs|T" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr31438.C b/gcc/testsuite/g++.dg/cpp0x/pr31438.C
index 74738830ad1..26c34b05ae3 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr31438.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr31438.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename> struct A;
template<typename T, typename... U> struct A<T(U)> // { dg-error "parameter packs|U" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr31439.C b/gcc/testsuite/g++.dg/cpp0x/pr31439.C
index c64bc3145b6..13221959bd9 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr31439.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr31439.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<typename...> struct A;
template<char> struct A<> {}; // { dg-error "not used in partial specialization|anonymous|declaration" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr31442.C b/gcc/testsuite/g++.dg/cpp0x/pr31442.C
index f4e411c4505..bed4b57be97 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr31442.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr31442.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename... T, T = 0> struct A {}; // { dg-error "parameter packs|T|the end|parameter packs|anonymous" }
struct B
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr31443.C b/gcc/testsuite/g++.dg/cpp0x/pr31443.C
index 1eb9d318de0..0decd759367 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr31443.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr31443.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<int, typename... T> struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr31444.C b/gcc/testsuite/g++.dg/cpp0x/pr31444.C
index b1f86fe7a7e..316ddb62187 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr31444.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr31444.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename... T> struct A
{
template<int> void foo(A<T>); // { dg-error "not expanded|T" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr31445.C b/gcc/testsuite/g++.dg/cpp0x/pr31445.C
index b3f2b5b09da..283eafb5990 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr31445.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr31445.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template <typename... T> struct A
{
void foo(T...);
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr31993.C b/gcc/testsuite/g++.dg/cpp0x/pr31993.C
index 94fb9ccdab9..39a73498fc8 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr31993.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr31993.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<typename...> struct A;
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr32114.C b/gcc/testsuite/g++.dg/cpp0x/pr32114.C
index e78dfdf1df9..923187163b4 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr32114.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr32114.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<typename ...T> struct A
{
typedef typename T::X Y; // { dg-error "not expanded|T" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr32115.C b/gcc/testsuite/g++.dg/cpp0x/pr32115.C
index a721eed4eb7..4e5700cdf73 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr32115.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr32115.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<typename ...T, int = 0> struct A {}; // { dg-error "end of" }
A<int> a; // { dg-error "mismatch|expected|invalid" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr32125.C b/gcc/testsuite/g++.dg/cpp0x/pr32125.C
index 210a29c0829..7b913605b8b 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr32125.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr32125.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<typename...> struct A;
template<typename...T> struct A<T*> // { dg-error "not expanded|T" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr32126.C b/gcc/testsuite/g++.dg/cpp0x/pr32126.C
index c525cca684b..c1cca94b869 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr32126.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr32126.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<typename...> struct A;
template<typename...T> struct A<T> // { dg-error "not expanded|T|" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr32127.C b/gcc/testsuite/g++.dg/cpp0x/pr32127.C
index 8e4bc0050b2..ca197ec4b3f 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr32127.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr32127.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<typename...T> struct A
{
static T i; // { dg-error "parameter packs|T" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr32128.C b/gcc/testsuite/g++.dg/cpp0x/pr32128.C
index 5876dbec485..595e20e0876 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr32128.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr32128.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<typename...> struct A;
template<typename...T, typename...U>
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr32252.C b/gcc/testsuite/g++.dg/cpp0x/pr32252.C
index 543dc887390..f0f4b3ca610 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr32252.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr32252.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
int x[5];
template<int M, int N, int (&... p)[N]> struct A;
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr32253.C b/gcc/testsuite/g++.dg/cpp0x/pr32253.C
index d8f7b03b92f..df30b6a7842 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr32253.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr32253.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<void (*... fp)()> struct A
{
A() { fp(); } // { dg-error "not expanded|fp" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr32566.C b/gcc/testsuite/g++.dg/cpp0x/pr32566.C
index f6e7a5b548d..5802078f7c9 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr32566.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr32566.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<int...> struct A;
template<template<int> class... T> struct A<T...> {}; // { dg-error "mismatch|expected" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr33839.C b/gcc/testsuite/g++.dg/cpp0x/pr33839.C
index 0a6610ac995..b4d3a620339 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr33839.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr33839.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<int> struct A;
void foo()
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr33930.C b/gcc/testsuite/g++.dg/cpp0x/pr33930.C
index d1e6fa56b1d..814fb6537b9 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr33930.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr33930.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
typedef const int* type;
float& foo( const type& ggg );
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr33955.C b/gcc/testsuite/g++.dg/cpp0x/pr33955.C
index cde92dedf97..191fe5c356d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr33955.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr33955.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<typename T>
struct uncvref
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr33996.C b/gcc/testsuite/g++.dg/cpp0x/pr33996.C
index 07590f06f95..47829c04bc1 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr33996.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr33996.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
#define BUG
struct type
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr34054.C b/gcc/testsuite/g++.dg/cpp0x/pr34054.C
index cfc6c4bdc76..19fcece6ca5 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr34054.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr34054.C
@@ -1,5 +1,5 @@
// PR c++/34054
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<typename... T> T foo() {} // { dg-error "not expanded|T" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr34056.C b/gcc/testsuite/g++.dg/cpp0x/pr34056.C
index 0e5246b6ab6..f227ce1a405 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr34056.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr34056.C
@@ -1,6 +1,6 @@
// PR c++/34056
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<typename... T> struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr34057.C b/gcc/testsuite/g++.dg/cpp0x/pr34057.C
index 38da5ff5015..1c28c546b31 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr34057.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr34057.C
@@ -1,6 +1,6 @@
// PR c++/34057
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template <typename... T> struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr34058.C b/gcc/testsuite/g++.dg/cpp0x/pr34058.C
index 0cf1faec73f..74dabc5151f 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr34058.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr34058.C
@@ -1,6 +1,6 @@
// PR c++/34058
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template <typename...T> struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr34060.C b/gcc/testsuite/g++.dg/cpp0x/pr34060.C
index 8e0d321b2ac..6653eb68fc8 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr34060.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr34060.C
@@ -1,6 +1,6 @@
// PR c++/34060
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template <int> struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr34061.C b/gcc/testsuite/g++.dg/cpp0x/pr34061.C
index 7d6e71d0e74..bb750f1d6cd 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr34061.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr34061.C
@@ -1,5 +1,5 @@
// PR c++/34061
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<template<int> class ...T> struct A : T<0> {}; // { dg-error "not expanded|T" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr38646.C b/gcc/testsuite/g++.dg/cpp0x/pr38646.C
index f15fc8c29bb..2177aab8f02 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr38646.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr38646.C
@@ -1,6 +1,6 @@
/* PR c++/38646 */
/* { dg-do compile } */
-/* { dg-options "-std=c++0x" } */
+/* { dg-options "-std=c++11" } */
template<int...> struct A;
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr38795.C b/gcc/testsuite/g++.dg/cpp0x/pr38795.C
index 54fb361d3d4..bf44357fdf7 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr38795.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr38795.C
@@ -1,6 +1,6 @@
// PR c++/38795
// { dg-do compile }
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename... T> int foo(int i)
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr39639.C b/gcc/testsuite/g++.dg/cpp0x/pr39639.C
index 0838a0ba25f..873c51e35f0 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr39639.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr39639.C
@@ -1,7 +1,7 @@
// Contributed by Dodji Seketeli <dodji@redhat.com>
// Origin: PR c++/39639
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// { dg-prune-output "template argument 1 is invalid" }
template <class... Types>
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr42844-2.C b/gcc/testsuite/g++.dg/cpp0x/pr42844-2.C
index 4425aacf627..c7a02c2c738 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr42844-2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr42844-2.C
@@ -1,6 +1,6 @@
// PR c++/42844
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
struct A // { dg-message "user-provided default constructor" }
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr45908.C b/gcc/testsuite/g++.dg/cpp0x/pr45908.C
index 45399b5395f..b50b7b03ca0 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr45908.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr45908.C
@@ -2,7 +2,7 @@
// Testcase by Jonathan Wakely <redi@gcc.gnu.org>
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
struct vector {
struct iterator { };
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr47416.C b/gcc/testsuite/g++.dg/cpp0x/pr47416.C
index 55426c1f81d..d7c5b13080a 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr47416.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr47416.C
@@ -1,6 +1,6 @@
// PR c++/47416
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
namespace std
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr47476.C b/gcc/testsuite/g++.dg/cpp0x/pr47476.C
index 1f6f09cccc6..dd386d17e8a 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr47476.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr47476.C
@@ -1,6 +1,6 @@
// PR c++/47476
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
int
foo (int a, int b)
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr48522.C b/gcc/testsuite/g++.dg/cpp0x/pr48522.C
index 1543d8a281d..4f1117b9e31 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr48522.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr48522.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template <typename T>
struct Handle
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr50491.C b/gcc/testsuite/g++.dg/cpp0x/pr50491.C
index 48e7a1f743b..c6177169a73 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr50491.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr50491.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
struct GrandParent {
void *get();
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr50901.C b/gcc/testsuite/g++.dg/cpp0x/pr50901.C
index 439c15cc1cd..091952f3e68 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr50901.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr50901.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<class T> int foo(int a)
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr51150.C b/gcc/testsuite/g++.dg/cpp0x/pr51150.C
index 37eb166b43e..8fe2b6f0f2b 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr51150.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr51150.C
@@ -1,5 +1,5 @@
// PR c++/51150
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
struct Clock {
double Now();
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr51216.C b/gcc/testsuite/g++.dg/cpp0x/pr51216.C
index 4bdd071475e..0433c848f09 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr51216.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr51216.C
@@ -1,5 +1,5 @@
// PR c++/51216
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
void foo()
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr51225.C b/gcc/testsuite/g++.dg/cpp0x/pr51225.C
index 6fcf8611f9c..a9f1cf0dc67 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr51225.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr51225.C
@@ -1,5 +1,5 @@
// PR c++/51225
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<int> struct A {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr51313.C b/gcc/testsuite/g++.dg/cpp0x/pr51313.C
index ff078e02d67..20332963564 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr51313.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr51313.C
@@ -1,5 +1,5 @@
// PR c++/51313
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
class ostream;
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr51547.C b/gcc/testsuite/g++.dg/cpp0x/pr51547.C
index 80215f6a341..5fae55a5f9c 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr51547.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr51547.C
@@ -1,5 +1,5 @@
// PR c++/51547
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template <class T>
struct vector
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr51619.C b/gcc/testsuite/g++.dg/cpp0x/pr51619.C
index dd51679158d..75a922091aa 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr51619.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr51619.C
@@ -1,6 +1,6 @@
// PR c++/51619
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
struct A { virtual ~A(); };
struct B { A a[1][1]; } b;
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr58510.C b/gcc/testsuite/g++.dg/cpp0x/pr58510.C
new file mode 100644
index 00000000000..71f25209826
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/pr58510.C
@@ -0,0 +1,11 @@
+// PR c++/58510
+// { dg-do compile { target c++11 } }
+
+void foo()
+{
+ union
+ { // { dg-error "multiple" }
+ int i = 0;
+ char c = 0;
+ };
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr58563.C b/gcc/testsuite/g++.dg/cpp0x/pr58563.C
new file mode 100644
index 00000000000..c9e3e308af9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/pr58563.C
@@ -0,0 +1,8 @@
+// PR c++/58563
+// { dg-do compile { target c++11 } }
+
+template<int> void foo()
+{
+ enum E {};
+ E().E::~T(); // { dg-error "not a class" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr58707.C b/gcc/testsuite/g++.dg/cpp0x/pr58707.C
new file mode 100644
index 00000000000..12f2e309788
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/pr58707.C
@@ -0,0 +1,6 @@
+// PR c++/58707
+// { dg-do compile { target c++11 } }
+
+template<int i> class TC { };
+constexpr int foo[] = { 42 };
+TC<foo[0 > 1]> bar;
diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for1.C b/gcc/testsuite/g++.dg/cpp0x/range-for1.C
index 49e2ecd0bde..b0e71158174 100644
--- a/gcc/testsuite/g++.dg/cpp0x/range-for1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/range-for1.C
@@ -2,7 +2,7 @@
// Test the loop with an array
// { dg-do run }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
extern "C" void abort();
diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for10.C b/gcc/testsuite/g++.dg/cpp0x/range-for10.C
index 662074890d9..e93f76eb4e9 100644
--- a/gcc/testsuite/g++.dg/cpp0x/range-for10.C
+++ b/gcc/testsuite/g++.dg/cpp0x/range-for10.C
@@ -1,6 +1,6 @@
// PR c++/47388
// { dg-do compile }
-// { dg-options "-fno-for-scope -std=c++0x" }
+// { dg-options "-fno-for-scope -std=c++11" }
template <int>
void
diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for11.C b/gcc/testsuite/g++.dg/cpp0x/range-for11.C
index d02519a2519..84f855890ae 100644
--- a/gcc/testsuite/g++.dg/cpp0x/range-for11.C
+++ b/gcc/testsuite/g++.dg/cpp0x/range-for11.C
@@ -3,7 +3,7 @@
// with begin/end as member functions
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
struct iterator
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for12.C b/gcc/testsuite/g++.dg/cpp0x/range-for12.C
index 9b405dc620a..4b85366e6a7 100644
--- a/gcc/testsuite/g++.dg/cpp0x/range-for12.C
+++ b/gcc/testsuite/g++.dg/cpp0x/range-for12.C
@@ -2,7 +2,7 @@
// and begin/end as member functions
// { dg-do run }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
/* Preliminary declarations */
namespace pre
diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for13.C b/gcc/testsuite/g++.dg/cpp0x/range-for13.C
index 7ebf0c563e8..2b8d7f7105b 100644
--- a/gcc/testsuite/g++.dg/cpp0x/range-for13.C
+++ b/gcc/testsuite/g++.dg/cpp0x/range-for13.C
@@ -2,7 +2,7 @@
// with member begin/end
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
//These should not be used
template<typename T> int *begin(T &t)
diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for14.C b/gcc/testsuite/g++.dg/cpp0x/range-for14.C
index 438555e1344..651ce37f1d8 100644
--- a/gcc/testsuite/g++.dg/cpp0x/range-for14.C
+++ b/gcc/testsuite/g++.dg/cpp0x/range-for14.C
@@ -2,7 +2,7 @@
// begin/end member functions
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
//These should not be used
template<typename T> int *begin(T &t)
diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for15.C b/gcc/testsuite/g++.dg/cpp0x/range-for15.C
index 38f330771ea..bbdc1999b04 100644
--- a/gcc/testsuite/g++.dg/cpp0x/range-for15.C
+++ b/gcc/testsuite/g++.dg/cpp0x/range-for15.C
@@ -2,7 +2,7 @@
// and begin/end as member (non-)virtual functions
// { dg-do run }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
unsigned int g;
diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for16.C b/gcc/testsuite/g++.dg/cpp0x/range-for16.C
index 86cc2a828bf..76c1b91649a 100644
--- a/gcc/testsuite/g++.dg/cpp0x/range-for16.C
+++ b/gcc/testsuite/g++.dg/cpp0x/range-for16.C
@@ -2,7 +2,7 @@
// incomplete type or unknown size
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
extern int a[10];
extern int b[];
diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for17.C b/gcc/testsuite/g++.dg/cpp0x/range-for17.C
index eb888d9ab62..72516f15e05 100644
--- a/gcc/testsuite/g++.dg/cpp0x/range-for17.C
+++ b/gcc/testsuite/g++.dg/cpp0x/range-for17.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
extern "C" int printf (const char *, ...);
diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for18.C b/gcc/testsuite/g++.dg/cpp0x/range-for18.C
index 386d73d1817..f06311c7668 100644
--- a/gcc/testsuite/g++.dg/cpp0x/range-for18.C
+++ b/gcc/testsuite/g++.dg/cpp0x/range-for18.C
@@ -1,7 +1,7 @@
// PR c++/48994
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template <typename T>
struct myvec
diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for19.C b/gcc/testsuite/g++.dg/cpp0x/range-for19.C
index 4306fbda6ce..ee208d77e1b 100644
--- a/gcc/testsuite/g++.dg/cpp0x/range-for19.C
+++ b/gcc/testsuite/g++.dg/cpp0x/range-for19.C
@@ -1,7 +1,7 @@
// PR c++/49838
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
int main()
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for2.C b/gcc/testsuite/g++.dg/cpp0x/range-for2.C
index 17eb41dba7b..325525ce4e3 100644
--- a/gcc/testsuite/g++.dg/cpp0x/range-for2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/range-for2.C
@@ -3,7 +3,7 @@
// with begin/end in an associated namespace
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
struct iterator
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for20.C b/gcc/testsuite/g++.dg/cpp0x/range-for20.C
index 890eb0aeaf9..3d979d26fd1 100644
--- a/gcc/testsuite/g++.dg/cpp0x/range-for20.C
+++ b/gcc/testsuite/g++.dg/cpp0x/range-for20.C
@@ -1,6 +1,6 @@
// PR c++/49834
// PR c++/50020
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for21.C b/gcc/testsuite/g++.dg/cpp0x/range-for21.C
index 07bb95fbf2b..bf0b02bf398 100644
--- a/gcc/testsuite/g++.dg/cpp0x/range-for21.C
+++ b/gcc/testsuite/g++.dg/cpp0x/range-for21.C
@@ -1,5 +1,5 @@
// PR c++/49983
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template <class T>
void f(T t)
diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for22.C b/gcc/testsuite/g++.dg/cpp0x/range-for22.C
index 5fef5e6accb..9db46eeb8fd 100644
--- a/gcc/testsuite/g++.dg/cpp0x/range-for22.C
+++ b/gcc/testsuite/g++.dg/cpp0x/range-for22.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<int I> void f() {
for (auto i: {I} );
diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for26.C b/gcc/testsuite/g++.dg/cpp0x/range-for26.C
new file mode 100644
index 00000000000..71359cde6e4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/range-for26.C
@@ -0,0 +1,7 @@
+// PR c++/58503
+// { dg-require-effective-target c++11 }
+
+template<int> void foo()
+{
+ for (auto i : 0) {} // { dg-error "there are no arguments" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for27.C b/gcc/testsuite/g++.dg/cpp0x/range-for27.C
new file mode 100644
index 00000000000..a9cfb8ebc32
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/range-for27.C
@@ -0,0 +1,15 @@
+// PR c++/58503
+// { dg-require-effective-target c++11 }
+// { dg-options "-fpermissive -w" }
+
+struct c { };
+
+template<int> void foo()
+{
+ for (auto i : c()) { }
+}
+
+c* begin(const c&);
+c* end(const c&);
+
+template void foo<1>();
diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for3.C b/gcc/testsuite/g++.dg/cpp0x/range-for3.C
index 85115a38f5e..c2204f91758 100644
--- a/gcc/testsuite/g++.dg/cpp0x/range-for3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/range-for3.C
@@ -3,7 +3,7 @@
// with begin/end in std
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
struct iterator
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for4.C b/gcc/testsuite/g++.dg/cpp0x/range-for4.C
index afbcf14b26e..b27ec6ff4bf 100644
--- a/gcc/testsuite/g++.dg/cpp0x/range-for4.C
+++ b/gcc/testsuite/g++.dg/cpp0x/range-for4.C
@@ -1,7 +1,7 @@
// Test for range-based for loop with templates
// { dg-do run }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
/* Preliminary declarations */
namespace pre
diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for5.C b/gcc/testsuite/g++.dg/cpp0x/range-for5.C
index 04754b780e6..e74e33a2373 100644
--- a/gcc/testsuite/g++.dg/cpp0x/range-for5.C
+++ b/gcc/testsuite/g++.dg/cpp0x/range-for5.C
@@ -1,7 +1,7 @@
// Test for errors in range-based for loops
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
struct container
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for6.C b/gcc/testsuite/g++.dg/cpp0x/range-for6.C
index 775507f8de8..5fe405fac88 100644
--- a/gcc/testsuite/g++.dg/cpp0x/range-for6.C
+++ b/gcc/testsuite/g++.dg/cpp0x/range-for6.C
@@ -2,7 +2,7 @@
// Test the loop with an initializer_list
// { dg-do run }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
#include <initializer_list>
diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for7.C b/gcc/testsuite/g++.dg/cpp0x/range-for7.C
index ad89dc201b6..253d6b0c433 100644
--- a/gcc/testsuite/g++.dg/cpp0x/range-for7.C
+++ b/gcc/testsuite/g++.dg/cpp0x/range-for7.C
@@ -1,7 +1,7 @@
// PR c++/46056
// Check that range-based for loop calls destructors
// when required
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// { dg-do run }
extern "C" void abort();
diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for8.C b/gcc/testsuite/g++.dg/cpp0x/range-for8.C
index 641dfe052c2..7ef214edfaf 100644
--- a/gcc/testsuite/g++.dg/cpp0x/range-for8.C
+++ b/gcc/testsuite/g++.dg/cpp0x/range-for8.C
@@ -2,7 +2,7 @@
// a new type
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
#include <initializer_list>
diff --git a/gcc/testsuite/g++.dg/cpp0x/reference_collapsing.C b/gcc/testsuite/g++.dg/cpp0x/reference_collapsing.C
index 5b682e30459..669689dbba5 100644
--- a/gcc/testsuite/g++.dg/cpp0x/reference_collapsing.C
+++ b/gcc/testsuite/g++.dg/cpp0x/reference_collapsing.C
@@ -4,7 +4,7 @@
// for how cv-qualifications are applied to reference types. 7.1.3, 14.3.1
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template <bool> struct sa;
template <> struct sa<true> {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-bitfield.C b/gcc/testsuite/g++.dg/cpp0x/rv-bitfield.C
index ed866f9e1f3..e4db7a27736 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv-bitfield.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv-bitfield.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-bitfield2.C b/gcc/testsuite/g++.dg/cpp0x/rv-bitfield2.C
index e054151b056..1f0d12e48a6 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv-bitfield2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv-bitfield2.C
@@ -1,5 +1,5 @@
// PR c++/51868
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A {
A() {}
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-cast.C b/gcc/testsuite/g++.dg/cpp0x/rv-cast.C
index 48b7c13ba59..d7bafc483cf 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv-cast.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv-cast.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
void f(int i)
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-cast2.C b/gcc/testsuite/g++.dg/cpp0x/rv-cast2.C
index 94ee4ca849e..4d2ed52128d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv-cast2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv-cast2.C
@@ -1,5 +1,5 @@
// Test for const_cast to reference (5.2.11/4).
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template <class T> T&& xval();
template <class T> T& lval();
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-conv1.C b/gcc/testsuite/g++.dg/cpp0x/rv-conv1.C
index 38529913f85..ba2b6bb4d6d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv-conv1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv-conv1.C
@@ -1,5 +1,5 @@
// PR c++/49267
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct X {
operator int&();
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-deduce.C b/gcc/testsuite/g++.dg/cpp0x/rv-deduce.C
index 043543631ad..7763c42b290 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv-deduce.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv-deduce.C
@@ -1,5 +1,5 @@
// PR c++/36816, core issue 873
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template <class T> void h (T&&) { }
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-deduce2.C b/gcc/testsuite/g++.dg/cpp0x/rv-deduce2.C
index 160296f640f..26a8d551fb6 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv-deduce2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv-deduce2.C
@@ -1,5 +1,5 @@
// PR c++/48313
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<typename F>
void f(F&&) { }
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-dotstar.C b/gcc/testsuite/g++.dg/cpp0x/rv-dotstar.C
index 65aac8da2a1..104ecbdacca 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv-dotstar.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv-dotstar.C
@@ -1,5 +1,5 @@
// PR c++/49389
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<class T> T&& val();
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-func.C b/gcc/testsuite/g++.dg/cpp0x/rv-func.C
index db142961128..3ac7118b49f 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv-func.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv-func.C
@@ -1,5 +1,5 @@
// PR c++/48457, Core 1238
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<class T>
T&& create();
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-func2.C b/gcc/testsuite/g++.dg/cpp0x/rv-func2.C
index b792342dada..51516bf53de 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv-func2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv-func2.C
@@ -1,5 +1,5 @@
// PR c++/49458
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
typedef void ftype();
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-func3.C b/gcc/testsuite/g++.dg/cpp0x/rv-func3.C
index 8504682d791..f33140174a4 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv-func3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv-func3.C
@@ -1,5 +1,5 @@
// DR 1328
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template <class T> struct A {
operator T&(); // #1
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-lvalue-req.C b/gcc/testsuite/g++.dg/cpp0x/rv-lvalue-req.C
index a8f424df003..fd5aa65b3a6 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv-lvalue-req.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv-lvalue-req.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template <class T> T&& declval();
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-reinterpret.C b/gcc/testsuite/g++.dg/cpp0x/rv-reinterpret.C
index 5b6e4c3d126..02061fc3f28 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv-reinterpret.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv-reinterpret.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
// { dg-do run }
void f(int &);
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-restrict.C b/gcc/testsuite/g++.dg/cpp0x/rv-restrict.C
index 569ee5bb6c9..23c7bbe2212 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv-restrict.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv-restrict.C
@@ -1,5 +1,5 @@
// PR c++/45401
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
typedef int &__restrict restrictLvref;
typedef restrictLvref &&rvrefToRestrictLvref;
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-return.C b/gcc/testsuite/g++.dg/cpp0x/rv-return.C
index 3ab659833ea..088f376cf1f 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv-return.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv-return.C
@@ -1,5 +1,5 @@
// PR c++/41815
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<typename T, typename U> struct same_type;
template<typename T> struct same_type<T, T> {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-template1.C b/gcc/testsuite/g++.dg/cpp0x/rv-template1.C
index 11f53bd1c0a..d73108c23b9 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv-template1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv-template1.C
@@ -1,5 +1,5 @@
// PR c++/44870
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
void foo(int&& data);
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-trivial-bug.C b/gcc/testsuite/g++.dg/cpp0x/rv-trivial-bug.C
index cbce7c4ddd7..217116a3902 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv-trivial-bug.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv-trivial-bug.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// PR c++/33235
#include <cassert>
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv10.C b/gcc/testsuite/g++.dg/cpp0x/rv10.C
index 5e78b1dbb69..3c6566bcd91 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv10.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv10.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv1n.C b/gcc/testsuite/g++.dg/cpp0x/rv1n.C
index b15bdfb4c93..9ee46dc12f5 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv1n.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv1n.C
@@ -3,7 +3,7 @@
// Test overload resolution among reference types
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template <bool> struct sa;
template <> struct sa<true> {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv1p.C b/gcc/testsuite/g++.dg/cpp0x/rv1p.C
index 99e39e6a4bc..f2f4c0b0391 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv1p.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv1p.C
@@ -3,7 +3,7 @@
// Test overload resolution among reference types
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// { dg-skip-if "packed attribute missing for struct one/three/five/seven" { "epiphany-*-*" } { "*" } { "" } }
template <bool> struct sa;
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv2n.C b/gcc/testsuite/g++.dg/cpp0x/rv2n.C
index f22e863230e..c39d5c06e50 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv2n.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv2n.C
@@ -3,7 +3,7 @@
// Test overload resolution among reference types
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template <bool> struct sa;
template <> struct sa<true> {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv2p.C b/gcc/testsuite/g++.dg/cpp0x/rv2p.C
index fca45c7352a..209f89392ad 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv2p.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv2p.C
@@ -3,7 +3,7 @@
// Test overload resolution among reference types
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// { dg-skip-if "packed attribute missing for struct one/three/five/seven" { "epiphany-*-*" } { "*" } { "" } }
template <bool> struct sa;
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv3n.C b/gcc/testsuite/g++.dg/cpp0x/rv3n.C
index 14b810ae68d..67cbde24d5e 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv3n.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv3n.C
@@ -3,7 +3,7 @@
// Test overload resolution among reference types
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template <bool> struct sa;
template <> struct sa<true> {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv3p.C b/gcc/testsuite/g++.dg/cpp0x/rv3p.C
index 804b2ffbdbe..12db70ca2e7 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv3p.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv3p.C
@@ -3,7 +3,7 @@
// Test overload resolution among reference types
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// { dg-skip-if "packed attribute missing for struct one/three/five/seven" { "epiphany-*-*" } { "*" } { "" } }
template <bool> struct sa;
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv4n.C b/gcc/testsuite/g++.dg/cpp0x/rv4n.C
index 076e9a0488e..9ed324e4655 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv4n.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv4n.C
@@ -3,7 +3,7 @@
// Test overload resolution among reference types
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template <bool> struct sa;
template <> struct sa<true> {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv4p.C b/gcc/testsuite/g++.dg/cpp0x/rv4p.C
index b2744e3cd9e..8ec25717919 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv4p.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv4p.C
@@ -3,7 +3,7 @@
// Test overload resolution among reference types
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// { dg-skip-if "packed attribute missing for struct one/three/five/seven" { "epiphany-*-*" } { "*" } { "" } }
template <bool> struct sa;
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv5n.C b/gcc/testsuite/g++.dg/cpp0x/rv5n.C
index d9b8cd23988..667012f55b5 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv5n.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv5n.C
@@ -3,7 +3,7 @@
// Test overload resolution among reference types
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template <bool> struct sa;
template <> struct sa<true> {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv5p.C b/gcc/testsuite/g++.dg/cpp0x/rv5p.C
index 9bb5e2bbb89..171b6dcf706 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv5p.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv5p.C
@@ -3,7 +3,7 @@
// Test overload resolution among reference types
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// { dg-skip-if "packed attribute missing for struct one/three/five/seven" { "epiphany-*-*" } { "*" } { "" } }
template <bool> struct sa;
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv6n.C b/gcc/testsuite/g++.dg/cpp0x/rv6n.C
index fbc932de1ef..89ed1c0ac50 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv6n.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv6n.C
@@ -3,7 +3,7 @@
// Test overload resolution among reference types
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template <bool> struct sa;
template <> struct sa<true> {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv6p.C b/gcc/testsuite/g++.dg/cpp0x/rv6p.C
index b2a3bdedd1b..92a4f94336f 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv6p.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv6p.C
@@ -3,7 +3,7 @@
// Test overload resolution among reference types
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// { dg-skip-if "packed attribute missing for struct one/three/five/seven" { "epiphany-*-*" } { "*" } { "" } }
template <bool> struct sa;
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv7n.C b/gcc/testsuite/g++.dg/cpp0x/rv7n.C
index 206cc79bb14..4d81e2a71c1 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv7n.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv7n.C
@@ -3,7 +3,7 @@
// Test overload resolution among reference types
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template <bool> struct sa;
template <> struct sa<true> {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv7p.C b/gcc/testsuite/g++.dg/cpp0x/rv7p.C
index 918dc14b98c..551b9d9c783 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv7p.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv7p.C
@@ -3,7 +3,7 @@
// Test overload resolution among reference types
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// { dg-skip-if "packed attribute missing for struct one/three/five/seven" { "epiphany-*-*" } { "*" } { "" } }
template <bool> struct sa;
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv8p.C b/gcc/testsuite/g++.dg/cpp0x/rv8p.C
index f6784dffc22..650fd76ba82 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv8p.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv8p.C
@@ -3,7 +3,7 @@
// Test overload resolution among reference types
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// { dg-skip-if "packed attribute missing for struct one/three/five/seven" { "epiphany-*-*" } { "*" } { "" } }
template <bool> struct sa;
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv9p.C b/gcc/testsuite/g++.dg/cpp0x/rv9p.C
index ec08a824865..4714d7c936e 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv9p.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv9p.C
@@ -1,5 +1,5 @@
// PR c++/36744
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// { dg-do run }
struct S
diff --git a/gcc/testsuite/g++.dg/cpp0x/rvo.C b/gcc/testsuite/g++.dg/cpp0x/rvo.C
index d4459af64d3..0ba8b100293 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rvo.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rvo.C
@@ -1,5 +1,5 @@
// { dg-do run }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// Contributed by Sylvain Pion
static int rvalue_constructions = 0;
diff --git a/gcc/testsuite/g++.dg/cpp0x/scoped_enum.C b/gcc/testsuite/g++.dg/cpp0x/scoped_enum.C
index 20391eb407b..a1f99482940 100644
--- a/gcc/testsuite/g++.dg/cpp0x/scoped_enum.C
+++ b/gcc/testsuite/g++.dg/cpp0x/scoped_enum.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
enum class Color1 {
Red,
Green,
diff --git a/gcc/testsuite/g++.dg/cpp0x/scoped_enum2.C b/gcc/testsuite/g++.dg/cpp0x/scoped_enum2.C
index e87b36a2732..bf9e6574dc7 100644
--- a/gcc/testsuite/g++.dg/cpp0x/scoped_enum2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/scoped_enum2.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
enum class E { e = 10 };
enum E2 { e2 = 10 };
diff --git a/gcc/testsuite/g++.dg/cpp0x/scoped_enum_examples.C b/gcc/testsuite/g++.dg/cpp0x/scoped_enum_examples.C
index 67c3fcbebb1..aea744d9a4d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/scoped_enum_examples.C
+++ b/gcc/testsuite/g++.dg/cpp0x/scoped_enum_examples.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
enum class Col { red, yellow, green };
int x = Col::red; // { dg-error "cannot convert" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae1.C b/gcc/testsuite/g++.dg/cpp0x/sfinae1.C
index 292d8ae04b0..855d96795cd 100644
--- a/gcc/testsuite/g++.dg/cpp0x/sfinae1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/sfinae1.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template< typename T_VECTOR >
void f(const T_VECTOR &a, decltype(a[0]) t = 0);
diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae10.C b/gcc/testsuite/g++.dg/cpp0x/sfinae10.C
index ede8b704245..c62aba77373 100644
--- a/gcc/testsuite/g++.dg/cpp0x/sfinae10.C
+++ b/gcc/testsuite/g++.dg/cpp0x/sfinae10.C
@@ -1,5 +1,5 @@
// PR c++/48452
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
namespace std {
template <class T> T&& declval();
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae11.C b/gcc/testsuite/g++.dg/cpp0x/sfinae11.C
index 2e8408d8f4d..e5d5255c11c 100644
--- a/gcc/testsuite/g++.dg/cpp0x/sfinae11.C
+++ b/gcc/testsuite/g++.dg/cpp0x/sfinae11.C
@@ -1,5 +1,5 @@
// PR c++/48468
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
// { dg-prune-output "note" }
template<class T>
diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae12.C b/gcc/testsuite/g++.dg/cpp0x/sfinae12.C
index 114f1b42da8..927ac7a6d82 100644
--- a/gcc/testsuite/g++.dg/cpp0x/sfinae12.C
+++ b/gcc/testsuite/g++.dg/cpp0x/sfinae12.C
@@ -1,5 +1,5 @@
// PR c++/48535
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<class T,
class = decltype(T{})
diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae13.C b/gcc/testsuite/g++.dg/cpp0x/sfinae13.C
index 465df2d8b8c..511944b8e46 100644
--- a/gcc/testsuite/g++.dg/cpp0x/sfinae13.C
+++ b/gcc/testsuite/g++.dg/cpp0x/sfinae13.C
@@ -1,5 +1,5 @@
// PR c++/48581
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<class T>
T&& create();
diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae14.C b/gcc/testsuite/g++.dg/cpp0x/sfinae14.C
index 305f96eddca..23ef8443fdb 100644
--- a/gcc/testsuite/g++.dg/cpp0x/sfinae14.C
+++ b/gcc/testsuite/g++.dg/cpp0x/sfinae14.C
@@ -1,5 +1,5 @@
// PR c++/48557
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<class T>
struct add_rval_ref
diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae15.C b/gcc/testsuite/g++.dg/cpp0x/sfinae15.C
index 595ca40b555..e2830968bb0 100644
--- a/gcc/testsuite/g++.dg/cpp0x/sfinae15.C
+++ b/gcc/testsuite/g++.dg/cpp0x/sfinae15.C
@@ -1,5 +1,5 @@
// PR c++/48531
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<class T,
class = decltype(T())
diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae16.C b/gcc/testsuite/g++.dg/cpp0x/sfinae16.C
index 6470567b7a2..7bd1aabd8a3 100644
--- a/gcc/testsuite/g++.dg/cpp0x/sfinae16.C
+++ b/gcc/testsuite/g++.dg/cpp0x/sfinae16.C
@@ -1,5 +1,5 @@
// PR c++/48531
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<class T,
class = decltype(T())
diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae17.C b/gcc/testsuite/g++.dg/cpp0x/sfinae17.C
index dbbd9efe410..3b91621b11a 100644
--- a/gcc/testsuite/g++.dg/cpp0x/sfinae17.C
+++ b/gcc/testsuite/g++.dg/cpp0x/sfinae17.C
@@ -1,5 +1,5 @@
// PR c++/48530
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<class T,
class = decltype(T{})
diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae18.C b/gcc/testsuite/g++.dg/cpp0x/sfinae18.C
index bb54335e6cc..bf98f402451 100644
--- a/gcc/testsuite/g++.dg/cpp0x/sfinae18.C
+++ b/gcc/testsuite/g++.dg/cpp0x/sfinae18.C
@@ -1,5 +1,5 @@
// PR c++/48530
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<class T,
class = decltype(T())
diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae19.C b/gcc/testsuite/g++.dg/cpp0x/sfinae19.C
index be96983bf39..59c6a71b2d1 100644
--- a/gcc/testsuite/g++.dg/cpp0x/sfinae19.C
+++ b/gcc/testsuite/g++.dg/cpp0x/sfinae19.C
@@ -1,5 +1,5 @@
// PR c++/48737
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<class T>
T&& create();
diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae2.C b/gcc/testsuite/g++.dg/cpp0x/sfinae2.C
index b9ef70d99cf..1eec1a10525 100644
--- a/gcc/testsuite/g++.dg/cpp0x/sfinae2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/sfinae2.C
@@ -1,5 +1,5 @@
// PR c++/44967
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template <typename T> T&& declval();
diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae20.C b/gcc/testsuite/g++.dg/cpp0x/sfinae20.C
index 486064c3af7..c0ba70ced97 100644
--- a/gcc/testsuite/g++.dg/cpp0x/sfinae20.C
+++ b/gcc/testsuite/g++.dg/cpp0x/sfinae20.C
@@ -1,5 +1,5 @@
// PR c++/48744
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<class T>
struct add_rval_ref {
diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae21.C b/gcc/testsuite/g++.dg/cpp0x/sfinae21.C
index 4fba6eb82a1..62c003a458c 100644
--- a/gcc/testsuite/g++.dg/cpp0x/sfinae21.C
+++ b/gcc/testsuite/g++.dg/cpp0x/sfinae21.C
@@ -1,5 +1,5 @@
// PR c++/48735
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<class T,
class = decltype(T{})
@@ -9,6 +9,10 @@ char f(int);
template<class>
char (&f(...))[2];
-struct ND { ND() = delete; };
+struct ND {
+ // Make ND() non-aggregate.
+ virtual void f();
+ ND() = delete;
+};
static_assert(sizeof(f<ND[1]>(0)) != 1, "Error");
diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae22.C b/gcc/testsuite/g++.dg/cpp0x/sfinae22.C
index 1c3efd2e079..8379d04ca3e 100644
--- a/gcc/testsuite/g++.dg/cpp0x/sfinae22.C
+++ b/gcc/testsuite/g++.dg/cpp0x/sfinae22.C
@@ -1,5 +1,5 @@
// PR c++/48745
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<class T>
struct add_rval_ref {
diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae23.C b/gcc/testsuite/g++.dg/cpp0x/sfinae23.C
index 4e2ea88b171..794b336aead 100644
--- a/gcc/testsuite/g++.dg/cpp0x/sfinae23.C
+++ b/gcc/testsuite/g++.dg/cpp0x/sfinae23.C
@@ -1,5 +1,5 @@
// PR c++/48647
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template< class T >
T&& declval();
diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae24.C b/gcc/testsuite/g++.dg/cpp0x/sfinae24.C
index f974d82b144..d6746e01e21 100644
--- a/gcc/testsuite/g++.dg/cpp0x/sfinae24.C
+++ b/gcc/testsuite/g++.dg/cpp0x/sfinae24.C
@@ -1,7 +1,7 @@
// PR c++/49058
// This error is not subject to SFINAE because it doesn't happen in the
// deduction context.
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
// { dg-prune-output "note" }
template<typename T> T val();
diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae25.C b/gcc/testsuite/g++.dg/cpp0x/sfinae25.C
index 7bdc8f88e51..d8c46d0597a 100644
--- a/gcc/testsuite/g++.dg/cpp0x/sfinae25.C
+++ b/gcc/testsuite/g++.dg/cpp0x/sfinae25.C
@@ -1,5 +1,5 @@
// PR c++/49105
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<class T, class = decltype(T{})>
char f(int);
diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae26.C b/gcc/testsuite/g++.dg/cpp0x/sfinae26.C
index 374f9976b2c..3fc5b280da7 100644
--- a/gcc/testsuite/g++.dg/cpp0x/sfinae26.C
+++ b/gcc/testsuite/g++.dg/cpp0x/sfinae26.C
@@ -1,5 +1,5 @@
// PR c++/49229
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
extern void* enabler;
diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae27.C b/gcc/testsuite/g++.dg/cpp0x/sfinae27.C
index 93327ba9cc5..2fa2232ab39 100644
--- a/gcc/testsuite/g++.dg/cpp0x/sfinae27.C
+++ b/gcc/testsuite/g++.dg/cpp0x/sfinae27.C
@@ -1,5 +1,5 @@
// PR c++/50157
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<class T>
T val();
diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae28.C b/gcc/testsuite/g++.dg/cpp0x/sfinae28.C
index da64f413c71..a06fc9f7407 100644
--- a/gcc/testsuite/g++.dg/cpp0x/sfinae28.C
+++ b/gcc/testsuite/g++.dg/cpp0x/sfinae28.C
@@ -1,5 +1,5 @@
// PR c++/50324
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct complete { };
struct incomplete;
diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae29.C b/gcc/testsuite/g++.dg/cpp0x/sfinae29.C
index a2e10b41d3e..49ab9699376 100644
--- a/gcc/testsuite/g++.dg/cpp0x/sfinae29.C
+++ b/gcc/testsuite/g++.dg/cpp0x/sfinae29.C
@@ -1,5 +1,5 @@
// PR c++/51047
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<typename T> T &&declval();
template<class T> decltype(declval<T>().x) f(T *);
diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae3.C b/gcc/testsuite/g++.dg/cpp0x/sfinae3.C
index 8582ba777c4..b25b3886137 100644
--- a/gcc/testsuite/g++.dg/cpp0x/sfinae3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/sfinae3.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
namespace std { template <class T> T&& declval(); }
diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae31.C b/gcc/testsuite/g++.dg/cpp0x/sfinae31.C
index ea151fe6490..066b1de022a 100644
--- a/gcc/testsuite/g++.dg/cpp0x/sfinae31.C
+++ b/gcc/testsuite/g++.dg/cpp0x/sfinae31.C
@@ -1,5 +1,5 @@
// PR c++/51973
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template <class T>
void f(T t) { };
diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae32.C b/gcc/testsuite/g++.dg/cpp0x/sfinae32.C
index db3bf5a21fc..67237ffb490 100644
--- a/gcc/testsuite/g++.dg/cpp0x/sfinae32.C
+++ b/gcc/testsuite/g++.dg/cpp0x/sfinae32.C
@@ -1,5 +1,5 @@
// PR c++/51989
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template <typename T>
struct is_container
diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae4.C b/gcc/testsuite/g++.dg/cpp0x/sfinae4.C
index b6648312498..a409bf8b8b7 100644
--- a/gcc/testsuite/g++.dg/cpp0x/sfinae4.C
+++ b/gcc/testsuite/g++.dg/cpp0x/sfinae4.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
namespace std { template <class T> T&& declval(); }
diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae49.C b/gcc/testsuite/g++.dg/cpp0x/sfinae49.C
new file mode 100644
index 00000000000..59381f341b4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/sfinae49.C
@@ -0,0 +1,29 @@
+// PR c++/58932
+// { dg-do compile { target c++11 } }
+
+using nullptr_t = decltype(nullptr);
+
+template<typename T, typename Sfinae = nullptr_t>
+struct B {
+ static float& int_if_addable();
+};
+
+template<typename T>
+struct B<T, decltype( (T() + T()), nullptr )> {
+ static int& int_if_addable();
+};
+
+struct X { };
+
+struct Y { };
+Y operator+(Y, Y);
+
+struct Z { };
+Z operator+(Z, Z) = delete;
+
+int main()
+{
+ float& a = B<X>::int_if_addable();
+ int& b = B<Y>::int_if_addable();
+ float& c = B<Z>::int_if_addable();
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae5.C b/gcc/testsuite/g++.dg/cpp0x/sfinae5.C
index 8474fb31431..e3592d06b49 100644
--- a/gcc/testsuite/g++.dg/cpp0x/sfinae5.C
+++ b/gcc/testsuite/g++.dg/cpp0x/sfinae5.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<class T>
T&& create();
diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae6.C b/gcc/testsuite/g++.dg/cpp0x/sfinae6.C
index 401d5362d84..1b884330165 100644
--- a/gcc/testsuite/g++.dg/cpp0x/sfinae6.C
+++ b/gcc/testsuite/g++.dg/cpp0x/sfinae6.C
@@ -1,5 +1,5 @@
// PR c++/48113
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<typename T> T declval();
diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae7.C b/gcc/testsuite/g++.dg/cpp0x/sfinae7.C
index 0a95a9644c7..19ec2ad1961 100644
--- a/gcc/testsuite/g++.dg/cpp0x/sfinae7.C
+++ b/gcc/testsuite/g++.dg/cpp0x/sfinae7.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae8.C b/gcc/testsuite/g++.dg/cpp0x/sfinae8.C
index 7f3012f94df..a5464dee03b 100644
--- a/gcc/testsuite/g++.dg/cpp0x/sfinae8.C
+++ b/gcc/testsuite/g++.dg/cpp0x/sfinae8.C
@@ -1,5 +1,5 @@
// PR c++/48449
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<class T, class = decltype(T())>
char f(int);
diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae9.C b/gcc/testsuite/g++.dg/cpp0x/sfinae9.C
index 6f1de21d51d..98ac52c12a2 100644
--- a/gcc/testsuite/g++.dg/cpp0x/sfinae9.C
+++ b/gcc/testsuite/g++.dg/cpp0x/sfinae9.C
@@ -1,5 +1,5 @@
// PR c++/48450
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
namespace std {
template <class T> T&& declval();
diff --git a/gcc/testsuite/g++.dg/cpp0x/static_assert1.C b/gcc/testsuite/g++.dg/cpp0x/static_assert1.C
index a54617598fb..81a86615a55 100644
--- a/gcc/testsuite/g++.dg/cpp0x/static_assert1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/static_assert1.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
void foo()
{
static_assert(1, "okay");
diff --git a/gcc/testsuite/g++.dg/cpp0x/static_assert2.C b/gcc/testsuite/g++.dg/cpp0x/static_assert2.C
index 3e74bb1b480..ac7dfdc9260 100644
--- a/gcc/testsuite/g++.dg/cpp0x/static_assert2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/static_assert2.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<int I>
struct accept_evens {
static_assert( I % 2 == 0, "I must be an even number"); // { dg-error "even number" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/static_assert3.C b/gcc/testsuite/g++.dg/cpp0x/static_assert3.C
index 0a4cbc98aff..84d2e2a0b16 100644
--- a/gcc/testsuite/g++.dg/cpp0x/static_assert3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/static_assert3.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
static_assert(7 / 0, "X"); // { dg-error "non-constant condition" "non-constant" }
// { dg-warning "division by zero" "zero" { target *-*-* } 2 }
// { dg-error "7 / 0.. is not a constant expression" "not a constant" { target *-*-* } 2 }
diff --git a/gcc/testsuite/g++.dg/cpp0x/static_assert4.C b/gcc/testsuite/g++.dg/cpp0x/static_assert4.C
index b0818873f10..97c0bd65950 100644
--- a/gcc/testsuite/g++.dg/cpp0x/static_assert4.C
+++ b/gcc/testsuite/g++.dg/cpp0x/static_assert4.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x --param ggc-min-heapsize=0 --param ggc-min-expand=0 " }
+// { dg-options "-std=c++11 --param ggc-min-heapsize=0 --param ggc-min-expand=0 " }
// PR C++/30033
// Make sure that the static assert does not crash the GC.
diff --git a/gcc/testsuite/g++.dg/cpp0x/static_assert5.C b/gcc/testsuite/g++.dg/cpp0x/static_assert5.C
index b918796220c..fdf26d12f07 100644
--- a/gcc/testsuite/g++.dg/cpp0x/static_assert5.C
+++ b/gcc/testsuite/g++.dg/cpp0x/static_assert5.C
@@ -1,5 +1,5 @@
// PR c++/50837
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<class T>
struct z
diff --git a/gcc/testsuite/g++.dg/cpp0x/static_assert6.C b/gcc/testsuite/g++.dg/cpp0x/static_assert6.C
index d1ab0dded9d..6fd9c27b85a 100644
--- a/gcc/testsuite/g++.dg/cpp0x/static_assert6.C
+++ b/gcc/testsuite/g++.dg/cpp0x/static_assert6.C
@@ -1,4 +1,4 @@
// PR c++/51397
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
static_assert('X' != '\130', "'X' has the wrong value"); // { dg-error "'X' has the wrong value" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/std-layout1.C b/gcc/testsuite/g++.dg/cpp0x/std-layout1.C
index bdad8211145..bff657c7396 100644
--- a/gcc/testsuite/g++.dg/cpp0x/std-layout1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/std-layout1.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// [basic.types]/10:
// Scalar types, standard-layout class types (Clause 9), arrays of such
diff --git a/gcc/testsuite/g++.dg/cpp0x/syntax-err1.C b/gcc/testsuite/g++.dg/cpp0x/syntax-err1.C
index ce1c9eea534..818eaac0a14 100644
--- a/gcc/testsuite/g++.dg/cpp0x/syntax-err1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/syntax-err1.C
@@ -1,5 +1,5 @@
// PR c++/47198
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct S
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/temp-constructor-bug.C b/gcc/testsuite/g++.dg/cpp0x/temp-constructor-bug.C
index a0672070205..b7bb9b85a25 100644
--- a/gcc/testsuite/g++.dg/cpp0x/temp-constructor-bug.C
+++ b/gcc/testsuite/g++.dg/cpp0x/temp-constructor-bug.C
@@ -1,4 +1,4 @@
-// { dg-options "--std=c++0x" }
+// { dg-options "--std=c++11" }
struct S { };
diff --git a/gcc/testsuite/g++.dg/cpp0x/temp-va-arg-bug.C b/gcc/testsuite/g++.dg/cpp0x/temp-va-arg-bug.C
index 085915f907e..97b33ac67d4 100644
--- a/gcc/testsuite/g++.dg/cpp0x/temp-va-arg-bug.C
+++ b/gcc/testsuite/g++.dg/cpp0x/temp-va-arg-bug.C
@@ -1,5 +1,5 @@
-// { dg-options "--std=c++0x" }
-// { dg-options "-Wno-abi --std=c++0x" { target arm_eabi } }
+// { dg-options "--std=c++11" }
+// { dg-options "-Wno-abi --std=c++11" { target arm_eabi } }
#include <stdarg.h>
struct S { };
diff --git a/gcc/testsuite/g++.dg/cpp0x/temp_default1.C b/gcc/testsuite/g++.dg/cpp0x/temp_default1.C
index dfa2cfb7bc7..bf2629214ed 100644
--- a/gcc/testsuite/g++.dg/cpp0x/temp_default1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/temp_default1.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<typename T, typename U>
struct is_same
diff --git a/gcc/testsuite/g++.dg/cpp0x/temp_default2.C b/gcc/testsuite/g++.dg/cpp0x/temp_default2.C
index dab1650e448..0d1598ce959 100644
--- a/gcc/testsuite/g++.dg/cpp0x/temp_default2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/temp_default2.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template <class T, class U = double>
void f(T t = 0, U u = 0); // { dg-message "note" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/temp_default3.C b/gcc/testsuite/g++.dg/cpp0x/temp_default3.C
index f71fe0f435a..e72e75797fb 100644
--- a/gcc/testsuite/g++.dg/cpp0x/temp_default3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/temp_default3.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<typename T, typename U = typename T::value_type>
void f(T);
diff --git a/gcc/testsuite/g++.dg/cpp0x/temp_default4.C b/gcc/testsuite/g++.dg/cpp0x/temp_default4.C
index aa2ad58e01e..6b2f5b18928 100644
--- a/gcc/testsuite/g++.dg/cpp0x/temp_default4.C
+++ b/gcc/testsuite/g++.dg/cpp0x/temp_default4.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
class X {
template<typename T = int> friend void f(X) { }
diff --git a/gcc/testsuite/g++.dg/cpp0x/template_deduction.C b/gcc/testsuite/g++.dg/cpp0x/template_deduction.C
index 4b8bd12b489..73aa3eec9dc 100644
--- a/gcc/testsuite/g++.dg/cpp0x/template_deduction.C
+++ b/gcc/testsuite/g++.dg/cpp0x/template_deduction.C
@@ -3,7 +3,7 @@
// Test the "Augmented" template argument deduction when binding an lvalue to an rvalue reference.
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template <bool> struct sa;
template <> struct sa<true> {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/trailing1.C b/gcc/testsuite/g++.dg/cpp0x/trailing1.C
index f637857b427..8b568a286ca 100644
--- a/gcc/testsuite/g++.dg/cpp0x/trailing1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/trailing1.C
@@ -1,5 +1,5 @@
// Tests for late-specified return type.
-// { dg-options "-std=c++0x -fabi-version=5" }
+// { dg-options "-std=c++11 -fabi-version=5" }
auto f() -> int
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/trailing3.C b/gcc/testsuite/g++.dg/cpp0x/trailing3.C
index 1c64f45731a..d95f298a157 100644
--- a/gcc/testsuite/g++.dg/cpp0x/trailing3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/trailing3.C
@@ -1,5 +1,5 @@
// More auto/decltype mangling tests.
-// { dg-options "-std=c++0x -fabi-version=0" }
+// { dg-options "-std=c++11 -fabi-version=0" }
template <class T>
struct B
diff --git a/gcc/testsuite/g++.dg/cpp0x/trailing4.C b/gcc/testsuite/g++.dg/cpp0x/trailing4.C
index 8d4baa97e5d..f508bc4e890 100644
--- a/gcc/testsuite/g++.dg/cpp0x/trailing4.C
+++ b/gcc/testsuite/g++.dg/cpp0x/trailing4.C
@@ -1,5 +1,5 @@
// PR c++/38597
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<class T, class U>
auto f(T,U) -> decltype(T() + U())
diff --git a/gcc/testsuite/g++.dg/cpp0x/trailing5.C b/gcc/testsuite/g++.dg/cpp0x/trailing5.C
index b97d362be2f..b4f2bf75ffb 100644
--- a/gcc/testsuite/g++.dg/cpp0x/trailing5.C
+++ b/gcc/testsuite/g++.dg/cpp0x/trailing5.C
@@ -1,5 +1,5 @@
// PR c++/38798, DR 770
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A {};
auto foo() -> struct A {}
diff --git a/gcc/testsuite/g++.dg/cpp0x/trailing6.C b/gcc/testsuite/g++.dg/cpp0x/trailing6.C
index 3476e90e580..86b8e4435c0 100644
--- a/gcc/testsuite/g++.dg/cpp0x/trailing6.C
+++ b/gcc/testsuite/g++.dg/cpp0x/trailing6.C
@@ -1,5 +1,5 @@
// PR c++/49003
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A {
auto a() const -> decltype(this) { return this; }
diff --git a/gcc/testsuite/g++.dg/cpp0x/trailing7.C b/gcc/testsuite/g++.dg/cpp0x/trailing7.C
index c4db10ec80d..e322a3c5ad9 100644
--- a/gcc/testsuite/g++.dg/cpp0x/trailing7.C
+++ b/gcc/testsuite/g++.dg/cpp0x/trailing7.C
@@ -1,5 +1,5 @@
// PR c++/50365
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A { int i; };
diff --git a/gcc/testsuite/g++.dg/cpp0x/trivial1.C b/gcc/testsuite/g++.dg/cpp0x/trivial1.C
index 109c8ccdbd4..06ed25733f3 100644
--- a/gcc/testsuite/g++.dg/cpp0x/trivial1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/trivial1.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// [basic.types]/10:
// Scalar types, trivial class types (Clause 9), arrays of such types and
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-addr.C b/gcc/testsuite/g++.dg/cpp0x/udlit-addr.C
index 7d3286e007b..92f192450a5 100644
--- a/gcc/testsuite/g++.dg/cpp0x/udlit-addr.C
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-addr.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
#include <cstddef>
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-args-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-args-neg.C
index df7b7281c3d..602d8293e35 100644
--- a/gcc/testsuite/g++.dg/cpp0x/udlit-args-neg.C
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-args-neg.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
#include <cstddef>
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-args.C b/gcc/testsuite/g++.dg/cpp0x/udlit-args.C
index ca2039c59d3..15aa6a3ad2c 100644
--- a/gcc/testsuite/g++.dg/cpp0x/udlit-args.C
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-args.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
#include <cstddef>
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-clink-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-clink-neg.C
index a80e7244afd..675ef31d241 100644
--- a/gcc/testsuite/g++.dg/cpp0x/udlit-clink-neg.C
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-clink-neg.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
extern "C" {
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-concat-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-concat-neg.C
index 61dc2ab02c6..10ff69b7a2b 100644
--- a/gcc/testsuite/g++.dg/cpp0x/udlit-concat-neg.C
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-concat-neg.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
#include <string>
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-concat.C b/gcc/testsuite/g++.dg/cpp0x/udlit-concat.C
index 612bc1d1116..870ddc3f5e2 100644
--- a/gcc/testsuite/g++.dg/cpp0x/udlit-concat.C
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-concat.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
#include <string>
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-constexpr.C b/gcc/testsuite/g++.dg/cpp0x/udlit-constexpr.C
index 40b0dfac531..e62c34af0c1 100644
--- a/gcc/testsuite/g++.dg/cpp0x/udlit-constexpr.C
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-constexpr.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
constexpr unsigned long long
operator"" _grow(unsigned long long n)
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-declare-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-declare-neg.C
index 9060abba494..a7eeb4629ab 100644
--- a/gcc/testsuite/g++.dg/cpp0x/udlit-declare-neg.C
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-declare-neg.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// Check that undeclared literal operator calls and literals give appropriate errors.
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-embed-quote.C b/gcc/testsuite/g++.dg/cpp0x/udlit-embed-quote.C
index 48a2a1b171d..2832312f3a4 100644
--- a/gcc/testsuite/g++.dg/cpp0x/udlit-embed-quote.C
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-embed-quote.C
@@ -1,5 +1,5 @@
// { dg-do run }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// Make sure embedded quotes are not a problem for string and char literals.
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-friend.C b/gcc/testsuite/g++.dg/cpp0x/udlit-friend.C
index b3f3ef8a604..0319701edb5 100644
--- a/gcc/testsuite/g++.dg/cpp0x/udlit-friend.C
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-friend.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
long double
operator"" _Hertz(long double);
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-general.C b/gcc/testsuite/g++.dg/cpp0x/udlit-general.C
index 9e448ac8050..b876a07cde4 100644
--- a/gcc/testsuite/g++.dg/cpp0x/udlit-general.C
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-general.C
@@ -1,5 +1,5 @@
// { dg-do run }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// Test user-defined literals.
// Test simple operator declaration and definition.
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-implicit-conv-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-implicit-conv-neg.C
index 998ad155bf7..851cd9b9c18 100644
--- a/gcc/testsuite/g++.dg/cpp0x/udlit-implicit-conv-neg.C
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-implicit-conv-neg.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
#include <cstdint>
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-inline.C b/gcc/testsuite/g++.dg/cpp0x/udlit-inline.C
index 75032c57679..063fd8345de 100644
--- a/gcc/testsuite/g++.dg/cpp0x/udlit-inline.C
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-inline.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// Literal operators can be inline.
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-linkage-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-linkage-neg.C
index c2ecede8d48..f969bb5ebab 100644
--- a/gcc/testsuite/g++.dg/cpp0x/udlit-linkage-neg.C
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-linkage-neg.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
extern "C"_badlinkage { // { dg-error "expected unqualified-id before" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-mangle.C b/gcc/testsuite/g++.dg/cpp0x/udlit-mangle.C
index 6de31b65ea7..c226c269a54 100644
--- a/gcc/testsuite/g++.dg/cpp0x/udlit-mangle.C
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-mangle.C
@@ -1,5 +1,5 @@
// PR c++/52521
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
// { dg-final { scan-assembler "_Zli2_wPKc" } }
int operator "" _w(const char*);
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-member-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-member-neg.C
index a6220c4c0fc..e6ea5776213 100644
--- a/gcc/testsuite/g++.dg/cpp0x/udlit-member-neg.C
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-member-neg.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
class Foo
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-namespace.C b/gcc/testsuite/g++.dg/cpp0x/udlit-namespace.C
index e5d54e51900..a84ed0e3a4f 100644
--- a/gcc/testsuite/g++.dg/cpp0x/udlit-namespace.C
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-namespace.C
@@ -1,5 +1,5 @@
// { dg-do run }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// Test user-defined literals.
// Test simple operator declaration and definition in namespaces.
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-nofunc-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-nofunc-neg.C
index 6ad79b85b1d..2de8f778983 100644
--- a/gcc/testsuite/g++.dg/cpp0x/udlit-nofunc-neg.C
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-nofunc-neg.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// Test user-defined literals.
// Test error on non-function declaration.
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-nonempty-str-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-nonempty-str-neg.C
index 981865f1526..e8ad1232ef0 100644
--- a/gcc/testsuite/g++.dg/cpp0x/udlit-nonempty-str-neg.C
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-nonempty-str-neg.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// Test user-defined literals.
// Test error on non-empty string after 'operator' keyword.
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-nospace-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-nospace-neg.C
index f06bd8bdf02..429a876efc1 100644
--- a/gcc/testsuite/g++.dg/cpp0x/udlit-nospace-neg.C
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-nospace-neg.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
float operator ""_abc(const char*);
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-nosuffix-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-nosuffix-neg.C
index b90635cd0fc..3c56f216a15 100644
--- a/gcc/testsuite/g++.dg/cpp0x/udlit-nosuffix-neg.C
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-nosuffix-neg.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
char32_t
operator"" (char32_t C) // { dg-error "expected suffix identifier" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-nounder-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-nounder-neg.C
index 2067bbe561f..b238f132878 100644
--- a/gcc/testsuite/g++.dg/cpp0x/udlit-nounder-neg.C
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-nounder-neg.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// Test user-defined literals.
// Test warning on declaration without leading underscore.
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-operator-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-operator-neg.C
index 27fdedec766..caaaa4951e2 100644
--- a/gcc/testsuite/g++.dg/cpp0x/udlit-operator-neg.C
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-operator-neg.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// Can't have *both* literal operator template and raw literal operator.
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-overflow-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-overflow-neg.C
index ed2de22e49d..c90467b6dda 100644
--- a/gcc/testsuite/g++.dg/cpp0x/udlit-overflow-neg.C
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-overflow-neg.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x -Woverflow" }
+// { dg-options "-std=c++11 -Woverflow" }
// PR c++/52654
int
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-overflow.C b/gcc/testsuite/g++.dg/cpp0x/udlit-overflow.C
index 85c15721887..569c10f279c 100644
--- a/gcc/testsuite/g++.dg/cpp0x/udlit-overflow.C
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-overflow.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
// PR c++/52654
int
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-preproc-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-preproc-neg.C
index 23633390cf0..0638ceeb4fe 100644
--- a/gcc/testsuite/g++.dg/cpp0x/udlit-preproc-neg.C
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-preproc-neg.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
int
operator"" _badpreproc(const char *str)
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-raw-length.C b/gcc/testsuite/g++.dg/cpp0x/udlit-raw-length.C
index 2d910624a7c..d30e9eeeec1 100644
--- a/gcc/testsuite/g++.dg/cpp0x/udlit-raw-length.C
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-raw-length.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// PR c++/50958
typedef decltype(sizeof(0)) size_type;
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-raw-op-string-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-raw-op-string-neg.C
index 58ad0e609d0..36d364c908b 100644
--- a/gcc/testsuite/g++.dg/cpp0x/udlit-raw-op-string-neg.C
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-raw-op-string-neg.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// Make sure handing a string to a raw literal generates a sensible error message.
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-raw-op.C b/gcc/testsuite/g++.dg/cpp0x/udlit-raw-op.C
index a31ef9328d2..dea0734b5d3 100644
--- a/gcc/testsuite/g++.dg/cpp0x/udlit-raw-op.C
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-raw-op.C
@@ -1,5 +1,5 @@
// { dg-do run }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
#include <cassert>
#include <cstring>
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-raw-str.C b/gcc/testsuite/g++.dg/cpp0x/udlit-raw-str.C
index e94410fd061..e0778897598 100644
--- a/gcc/testsuite/g++.dg/cpp0x/udlit-raw-str.C
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-raw-str.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
#include <string>
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-resolve.C b/gcc/testsuite/g++.dg/cpp0x/udlit-resolve.C
index a25516220c2..b4544ee0727 100644
--- a/gcc/testsuite/g++.dg/cpp0x/udlit-resolve.C
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-resolve.C
@@ -1,5 +1,5 @@
// { dg-do run }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
#include <cstdint>
#include <cassert>
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-shadow-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-shadow-neg.C
index 994d58c1a0b..65284073b1a 100644
--- a/gcc/testsuite/g++.dg/cpp0x/udlit-shadow-neg.C
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-shadow-neg.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
// Test that the standard suffixes shadow any user-defined suffixes of the same name.
long double
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-string-length.C b/gcc/testsuite/g++.dg/cpp0x/udlit-string-length.C
index 86903e8355a..d8be7b78cb0 100644
--- a/gcc/testsuite/g++.dg/cpp0x/udlit-string-length.C
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-string-length.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// PR c++/50941
typedef decltype(sizeof(0)) size_type;
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-suffix-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-suffix-neg.C
index 56eab01d736..e3b7e96936b 100644
--- a/gcc/testsuite/g++.dg/cpp0x/udlit-suffix-neg.C
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-suffix-neg.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
#include <string>
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-systemheader.C b/gcc/testsuite/g++.dg/cpp0x/udlit-systemheader.C
index 599c8652a14..33dfb9e5d06 100644
--- a/gcc/testsuite/g++.dg/cpp0x/udlit-systemheader.C
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-systemheader.C
@@ -1,3 +1,3 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
#include "udlit_system_header"
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-template.C b/gcc/testsuite/g++.dg/cpp0x/udlit-template.C
index 6a28f74a22b..55dca2ff815 100644
--- a/gcc/testsuite/g++.dg/cpp0x/udlit-template.C
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-template.C
@@ -1,5 +1,5 @@
// { dg-do run }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// Test user-defined literals.
// Test template operator declaration and definition.
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-arg-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-arg-neg.C
index e8ccb6f545d..f2efdd7a658 100644
--- a/gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-arg-neg.C
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-arg-neg.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<char...>
int operator"" _xyz(unsigned long long); // { dg-error "has invalid argument list" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-arg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-arg.C
index 6324823fabb..fb21f281e10 100644
--- a/gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-arg.C
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-arg.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<char...>
int operator"" _abc();
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-parms-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-parms-neg.C
index 4dab4d2f6f0..729325473a1 100644
--- a/gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-parms-neg.C
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-parms-neg.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
class Foo { };
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-parms.C b/gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-parms.C
index 77456737c70..d83fee8723a 100644
--- a/gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-parms.C
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-parms.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
class Foo { };
diff --git a/gcc/testsuite/g++.dg/cpp0x/union1.C b/gcc/testsuite/g++.dg/cpp0x/union1.C
index cb0f01719c9..f83c89bdeec 100644
--- a/gcc/testsuite/g++.dg/cpp0x/union1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/union1.C
@@ -1,5 +1,5 @@
-// Negative test for C++0x unrestricted unions
-// { dg-options -std=c++0x }
+// Negative test for C++11 unrestricted unions
+// { dg-options -std=c++11 }
// { dg-prune-output "implicitly deleted because" }
struct A
diff --git a/gcc/testsuite/g++.dg/cpp0x/union2.C b/gcc/testsuite/g++.dg/cpp0x/union2.C
index 4f193e281c8..78d88b2b6d9 100644
--- a/gcc/testsuite/g++.dg/cpp0x/union2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/union2.C
@@ -1,5 +1,5 @@
-// Positive test for C++0x unrestricted unions
-// { dg-options -std=c++0x }
+// Positive test for C++11 unrestricted unions
+// { dg-options -std=c++11 }
struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/union3.C b/gcc/testsuite/g++.dg/cpp0x/union3.C
index f1e8ddb6109..a1212e1a93c 100644
--- a/gcc/testsuite/g++.dg/cpp0x/union3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/union3.C
@@ -1,5 +1,5 @@
-// Runtime test for C++0x unrestricted unions
-// { dg-options -std=c++0x }
+// Runtime test for C++11 unrestricted unions
+// { dg-options -std=c++11 }
// { dg-do run }
int c, d;
diff --git a/gcc/testsuite/g++.dg/cpp0x/union4.C b/gcc/testsuite/g++.dg/cpp0x/union4.C
index c82a81cdba8..fa3e97f9226 100644
--- a/gcc/testsuite/g++.dg/cpp0x/union4.C
+++ b/gcc/testsuite/g++.dg/cpp0x/union4.C
@@ -1,5 +1,5 @@
// PR c++/48537
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct SFoo
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/union5.C b/gcc/testsuite/g++.dg/cpp0x/union5.C
index 423b3482323..51780619af0 100644
--- a/gcc/testsuite/g++.dg/cpp0x/union5.C
+++ b/gcc/testsuite/g++.dg/cpp0x/union5.C
@@ -1,5 +1,5 @@
// PR c++/49803
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct X
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/unnamed_refs.C b/gcc/testsuite/g++.dg/cpp0x/unnamed_refs.C
index c5966764586..8afe7a7ff27 100644
--- a/gcc/testsuite/g++.dg/cpp0x/unnamed_refs.C
+++ b/gcc/testsuite/g++.dg/cpp0x/unnamed_refs.C
@@ -3,7 +3,7 @@
// Test: Unamed rvalue references are treated as lvalues.
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template <bool> struct sa;
template <> struct sa<true> {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-104.C b/gcc/testsuite/g++.dg/cpp0x/variadic-104.C
index c693b33f9a5..e7a032c1993 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic-104.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-104.C
@@ -1,5 +1,5 @@
// PR c++/45236
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template <class T, class S> class foo;
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-bind.C b/gcc/testsuite/g++.dg/cpp0x/variadic-bind.C
index abe445d4341..21ebb2ff9f9 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic-bind.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-bind.C
@@ -1,5 +1,5 @@
// { dg-do run }
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
// A basic implementation of TR1's bind using variadic teplates
// Contributed by Douglas Gregor <doug.gregor@gmail.com>
#include <cassert>
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-crash1.C b/gcc/testsuite/g++.dg/cpp0x/variadic-crash1.C
index f26aee2a91f..768f2ee3977 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic-crash1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-crash1.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
#define ONE
#define TWO
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-crash2.C b/gcc/testsuite/g++.dg/cpp0x/variadic-crash2.C
index f46b8e534e4..f6b31966482 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic-crash2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-crash2.C
@@ -1,7 +1,7 @@
// Contributed by Dodji Seketeli <dodji@redhat.com>
// Origin: PR c++/39637
// { dg-do compile }
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<class... Types>
void
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-default.C b/gcc/testsuite/g++.dg/cpp0x/variadic-default.C
index 2625e259f78..0653d2a2cf0 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic-default.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-default.C
@@ -1,5 +1,5 @@
// PR c++/49205
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
#include <initializer_list>
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ex1.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ex1.C
index 485fffa476c..0fd2ab969fb 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic-ex1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-ex1.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename ... Elements> class Tuple;
Tuple<>* t; // OK: Elements is empty
Tuple* u; // { dg-error "template-name" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ex10.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ex10.C
index e8b6b722148..4515453294b 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic-ex10.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-ex10.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename... Types> struct Tuple { };
Tuple<> t0; // Types contains no arguments
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ex11.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ex11.C
index 57ef2a3d30e..4d45d5e5a8e 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic-ex11.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-ex11.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename... Types>
void f(Types... args);
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ex12.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ex12.C
index b97df310203..35a71a9c9ca 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic-ex12.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-ex12.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename... Types>
void f(Types... rest);
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ex13.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ex13.C
index b742cb1d369..f024f8474c6 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic-ex13.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-ex13.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename T, typename U> struct is_same {
static const bool value = false;
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ex14.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ex14.C
index 105096a78bf..108d1111a69 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic-ex14.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-ex14.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<class T> class A { /* ... */ };
template<class T, class U = T> class B { /* ... */ };
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ex2.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ex2.C
index ca5fa271637..0eb029bcb3f 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic-ex2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-ex2.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<class... Types> struct B { // { dg-error "declaration of" }
void f3();
void f4();
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ex3.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ex3.C
index 018eaa3ed8b..25d80181d6d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic-ex3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-ex3.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<class X, class Y, class... Z> X f(Y); // { dg-message "note" }
void g()
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ex4.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ex4.C
index 0a777c4853b..b05ca57f3cf 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic-ex4.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-ex4.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<class X, class Y, class Z> X f(Y,Z); // { dg-message "note" }
template<class... Args> void f2();
void g()
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ex5.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ex5.C
index 2439a51c5a4..81b57971050 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic-ex5.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-ex5.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename... Types> void f(Types... values);
void g()
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ex6.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ex6.C
index 87b1bf20576..5bb01d5141d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic-ex6.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-ex6.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<class...> struct Tuple { };
template<class... Types> void f(Types&...);
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ex7.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ex7.C
index 7ca31f9c67b..69f94672b6b 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic-ex7.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-ex7.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename...> struct Tuple { };
template<typename... Types> char& g(Tuple<Types...>); // #1
template<typename T1, typename... Types> short& g(Tuple<T1, Types...>); // #2
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ex8.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ex8.C
index 03d28b82535..f7fb32ffe26 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic-ex8.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-ex8.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<class> struct X { static const bool primary = true; };
template<class R, class... ArgTypes> struct X<R(int, ArgTypes...)> {
static const bool primary = false;
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ex9.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ex9.C
index 74215c99727..8b68711b877 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic-ex9.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-ex9.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename... Args> char& f(Args... args); // #1
template<typename T1, typename... Args> short& f(T1 a1, Args... args); // #2
template<typename T1, typename T2> int& f(T1 a2, T2 a3); // #3
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-explicit1.C b/gcc/testsuite/g++.dg/cpp0x/variadic-explicit1.C
index a097f43d218..8a1e285ecdd 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic-explicit1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-explicit1.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<class T, class U> struct A { };
template<class... T, class ... U> void f( A<T,U>... p);
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-function.C b/gcc/testsuite/g++.dg/cpp0x/variadic-function.C
index eeb137705f2..4240b4f3284 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic-function.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-function.C
@@ -1,5 +1,5 @@
// { dg-do run }
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
// A basic implementation of TR1's function using variadic teplates
// Contributed by Douglas Gregor <doug.gregor@gmail.com>
#include <cassert>
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-init.C b/gcc/testsuite/g++.dg/cpp0x/variadic-init.C
index 34ade85e0f9..9972928d2cc 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic-init.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-init.C
@@ -1,5 +1,5 @@
// { dg-do run }
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
// PR c++/33510
#define SIZE_FROM_CTOR
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-lambda.C b/gcc/testsuite/g++.dg/cpp0x/variadic-lambda.C
index 705d441493e..51263fd57e6 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic-lambda.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-lambda.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
struct int_placeholder;
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-mem_fn.C b/gcc/testsuite/g++.dg/cpp0x/variadic-mem_fn.C
index 51c5c79ef9f..4e090d1e83f 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic-mem_fn.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-mem_fn.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
// { dg-do run }
// A basic implementation of TR1's mem_fn using variadic teplates
// Contributed by Douglas Gregor <doug.gregor@gmail.com>
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-new.C b/gcc/testsuite/g++.dg/cpp0x/variadic-new.C
index 5bbb9c81b0e..45d11bae286 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic-new.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-new.C
@@ -1,5 +1,5 @@
// { dg-do run }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// Contributed by Peter Dimov
// PR c++/32597
#include <assert.h>
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-new2.C b/gcc/testsuite/g++.dg/cpp0x/variadic-new2.C
index 81d333398bd..c47fbf43868 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic-new2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-new2.C
@@ -1,5 +1,5 @@
// { dg-do run }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// PR c++/32597
#include <assert.h>
#include <new>
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-nondeduce1.C b/gcc/testsuite/g++.dg/cpp0x/variadic-nondeduce1.C
index a64d7971c6e..c6e44bb77aa 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic-nondeduce1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-nondeduce1.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template <class... T>
void f(T..., int, T...) { }
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-rref.C b/gcc/testsuite/g++.dg/cpp0x/variadic-rref.C
index 08221b460fe..609868475fa 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic-rref.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-rref.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// PR c++/33939
template<typename T>
struct refs_only;
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-throw.C b/gcc/testsuite/g++.dg/cpp0x/variadic-throw.C
index 8363c2a73f9..4c3bd95bf33 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic-throw.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-throw.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
// { dg-prune-output "note" }
// PR c++/33509
template<int M, int N> struct pair
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ttp.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ttp.C
index 41f1c1db43d..d8f14cb16aa 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic-ttp.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-ttp.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
// PR c++/34101
template<typename> struct A {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-tuple.C b/gcc/testsuite/g++.dg/cpp0x/variadic-tuple.C
index 11ce14af28c..4ad2cc39a7b 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic-tuple.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-tuple.C
@@ -1,5 +1,5 @@
// { dg-do run }
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
// An implementation of TR1's <tuple> using variadic teplates
// Contributed by Douglas Gregor <doug.gregor@gmail.com>
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-unify-2.C b/gcc/testsuite/g++.dg/cpp0x/variadic-unify-2.C
index 80c9f5d2c3a..33920a9a1a7 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic-unify-2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-unify-2.C
@@ -1,6 +1,6 @@
// Contributed by Dodji Seketeli <dodji@redhat.com>
// Origin: PR c++/40155
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// { dg-do compile }
template <typename T> struct identity
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-unify.C b/gcc/testsuite/g++.dg/cpp0x/variadic-unify.C
index 54234391e64..5213dbbabf3 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic-unify.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-unify.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<typename...> struct tuple { };
template<typename... Args1, typename... Args2>
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-unresolved.C b/gcc/testsuite/g++.dg/cpp0x/variadic-unresolved.C
index a8463de1980..2fc3471dded 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic-unresolved.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-unresolved.C
@@ -1,5 +1,5 @@
// PR c++/50086
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<typename T> void tfun();
template<typename T> void fun1(T);
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic1.C b/gcc/testsuite/g++.dg/cpp0x/variadic1.C
index f87d53ca386..884ef886239 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic1.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename...>
class tuple;
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic10.C b/gcc/testsuite/g++.dg/cpp0x/variadic10.C
index 5f73eba8d68..6a03df053a7 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic10.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic10.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename T1, typename T2>
struct pair {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic100.C b/gcc/testsuite/g++.dg/cpp0x/variadic100.C
index a364bbc9116..654c4e9013b 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic100.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic100.C
@@ -1,5 +1,5 @@
// PR c++/43143
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<typename T>
T&& declval();
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic101.C b/gcc/testsuite/g++.dg/cpp0x/variadic101.C
index 445a770afa1..d028a570eaa 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic101.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic101.C
@@ -1,5 +1,5 @@
// PR c++/43382
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<class T>
struct Container
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic102.C b/gcc/testsuite/g++.dg/cpp0x/variadic102.C
index dc9c4aea8cb..e656886fc3e 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic102.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic102.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
struct nAny {
template<class... T>
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic103.C b/gcc/testsuite/g++.dg/cpp0x/variadic103.C
index 9d6b5ea20b8..cab73d7647d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic103.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic103.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<class T>
T&& create();
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic105.C b/gcc/testsuite/g++.dg/cpp0x/variadic105.C
index 66d24a7efe3..ecd2410f4bb 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic105.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic105.C
@@ -1,5 +1,5 @@
// PR c++/47289
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
// { dg-prune-output "note" }
template <template <typename... __ARGS> class _F, typename... _ARGS>
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic106.C b/gcc/testsuite/g++.dg/cpp0x/variadic106.C
index 80ec0844fbf..d68b9ff011a 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic106.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic106.C
@@ -1,5 +1,5 @@
// Origin: PR c++/47326
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// { dg-do compile }
template <int _N>
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic107.C b/gcc/testsuite/g++.dg/cpp0x/variadic107.C
index 5c3f468515d..0d6923f4fd1 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic107.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic107.C
@@ -1,5 +1,5 @@
// PR c++/48451
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
namespace std {
template <class T> T&& declval();
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic108.C b/gcc/testsuite/g++.dg/cpp0x/variadic108.C
index 3ad5af45717..0986516415c 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic108.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic108.C
@@ -1,5 +1,5 @@
// PR c++/48736
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<class T>
T&& create();
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic109.C b/gcc/testsuite/g++.dg/cpp0x/variadic109.C
index 0ec69af812e..8acdfb8c819 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic109.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic109.C
@@ -1,5 +1,5 @@
// PR c++/48292
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template <typename... Args> int g(Args...);
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic11.C b/gcc/testsuite/g++.dg/cpp0x/variadic11.C
index 3c27de0fb19..58eb1636f04 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic11.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic11.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename...> struct count;
template<>
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic110.C b/gcc/testsuite/g++.dg/cpp0x/variadic110.C
index 86f1bb1543c..556594c3b74 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic110.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic110.C
@@ -1,5 +1,5 @@
// PR c++/45698
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template <class... Ts> struct tuple { };
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic111.C b/gcc/testsuite/g++.dg/cpp0x/variadic111.C
index cb94ce69755..01a6653612f 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic111.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic111.C
@@ -1,5 +1,5 @@
// PR c++/48424
-// { dg-options "-std=c++0x -fabi-version=0" }
+// { dg-options "-std=c++11 -fabi-version=0" }
template<typename... Args1>
struct S
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic112.C b/gcc/testsuite/g++.dg/cpp0x/variadic112.C
index 1640657d950..be435542643 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic112.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic112.C
@@ -1,5 +1,5 @@
// PR c++/49420
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct A { };
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic113.C b/gcc/testsuite/g++.dg/cpp0x/variadic113.C
index 3f1bb2ad04a..bee367e947d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic113.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic113.C
@@ -1,5 +1,5 @@
// PR c++/49251
-// { dg-options "-std=c++0x -Wunused-parameter" }
+// { dg-options "-std=c++11 -Wunused-parameter" }
struct A {};
template <int> int f(A);
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic114.C b/gcc/testsuite/g++.dg/cpp0x/variadic114.C
index 3ffede5c507..80f546a82b4 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic114.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic114.C
@@ -1,5 +1,5 @@
// PR c++/49785
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template <typename, typename ...> struct B { };
template <typename> class A;
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic115.C b/gcc/testsuite/g++.dg/cpp0x/variadic115.C
index fa032e3b022..8c59a79497d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic115.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic115.C
@@ -1,5 +1,5 @@
// PR c++/49593
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<typename... T> void f(T...) { }
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic116.C b/gcc/testsuite/g++.dg/cpp0x/variadic116.C
index 079d751cb46..ab4ed45f9b7 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic116.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic116.C
@@ -1,5 +1,5 @@
// Origin: PR c++/48320
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<class... T>
struct tuple
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic117.C b/gcc/testsuite/g++.dg/cpp0x/variadic117.C
index 22f2fc5ae2d..477a9f1e275 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic117.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic117.C
@@ -1,4 +1,4 @@
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template <class T> struct A { typedef T type; };
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic118.C b/gcc/testsuite/g++.dg/cpp0x/variadic118.C
index 43bf9bab213..75ee1cdcabe 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic118.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic118.C
@@ -1,5 +1,5 @@
// This should fail deduction, before it produces a candidate.
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template <class... T>
void f(T... ts); // { dg-message "deduction" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic12.C b/gcc/testsuite/g++.dg/cpp0x/variadic12.C
index 30108c99932..4b56b0117e8 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic12.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic12.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
// A tuple type
template<typename... Args> struct tuple { };
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic121.C b/gcc/testsuite/g++.dg/cpp0x/variadic121.C
index 805c0065fe9..1d086fc8ccd 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic121.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic121.C
@@ -1,5 +1,5 @@
// PR c++/51507
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<typename ...>
struct foo { typedef void type; };
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic13.C b/gcc/testsuite/g++.dg/cpp0x/variadic13.C
index 7794e8a3dc9..24601e03ab2 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic13.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic13.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename... Args> struct tuple1 { };
template<typename... Args> struct tuple2 { };
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic135.C b/gcc/testsuite/g++.dg/cpp0x/variadic135.C
index fbf5dec4797..841f7ceebbe 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic135.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic135.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template <typename ...> struct S;
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic14.C b/gcc/testsuite/g++.dg/cpp0x/variadic14.C
index 3c1bb0d6d23..339d5f921d4 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic14.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic14.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename R, typename... ArgTypes>
struct make_function_type
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic143.C b/gcc/testsuite/g++.dg/cpp0x/variadic143.C
index 7737b4cacf4..da3e7c4789e 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic143.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic143.C
@@ -1,5 +1,5 @@
// PR c++/56782
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<class T>
T&& declval();
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic144.C b/gcc/testsuite/g++.dg/cpp0x/variadic144.C
new file mode 100644
index 00000000000..5d05d3d52bd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic144.C
@@ -0,0 +1,15 @@
+// PR c++/56060
+// { dg-do compile { target c++11 } }
+
+template<typename T> struct baz { };
+template<typename T> T bar();
+
+template<typename T, typename ... U>
+baz<decltype(bar<T>()(bar<U> ...))> // { dg-error "cannot be used" }
+foo();
+
+int main()
+{
+ foo<int>(); // { dg-error "no matching" }
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic15.C b/gcc/testsuite/g++.dg/cpp0x/variadic15.C
index 68786cb8229..c7dadc6276d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic15.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic15.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename R, typename... ArgTypes>
struct make_function_type
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic16.C b/gcc/testsuite/g++.dg/cpp0x/variadic16.C
index 001919d469f..23a5710760b 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic16.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic16.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename R, typename... ArgTypes>
struct make_function_type
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic17.C b/gcc/testsuite/g++.dg/cpp0x/variadic17.C
index 986721bbec3..cc1a5f02125 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic17.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic17.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename R, typename... ArgTypes>
struct make_function_type
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic18.C b/gcc/testsuite/g++.dg/cpp0x/variadic18.C
index 147ed8e4bfc..cfacd7a7910 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic18.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic18.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename...> class tuple { };
template<typename T, template<typename T> class... Metafunctions>
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic19.C b/gcc/testsuite/g++.dg/cpp0x/variadic19.C
index 92e7a953aba..7a0864504c7 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic19.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic19.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename... Args>
struct tuple {
static const int value = 0;
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic2.C b/gcc/testsuite/g++.dg/cpp0x/variadic2.C
index 207a80648f3..023cb08316d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic2.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename... Args = int> // { dg-error "default argument" }
class tuple2;
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic20.C b/gcc/testsuite/g++.dg/cpp0x/variadic20.C
index bfb42bea09c..e8bdf121bf4 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic20.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic20.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename T> struct add_pointer;
template<typename T> struct add_reference;
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic21.C b/gcc/testsuite/g++.dg/cpp0x/variadic21.C
index b65e995b9a1..e2115f1362c 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic21.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic21.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename T, int... Dims>
struct array { };
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic22.C b/gcc/testsuite/g++.dg/cpp0x/variadic22.C
index 1d26e40d981..c37f056c2bb 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic22.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic22.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename R, typename... ArgTypes>
struct make_function_type
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic23.C b/gcc/testsuite/g++.dg/cpp0x/variadic23.C
index 43309a1e1f8..ea0d31c5007 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic23.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic23.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename T, int... Dims>
struct array {
static const int value = 0;
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic24.C b/gcc/testsuite/g++.dg/cpp0x/variadic24.C
index 6ef8e8a77d0..fe953bc150e 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic24.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic24.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename T, T... Values>
struct vector_c { };
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic25.C b/gcc/testsuite/g++.dg/cpp0x/variadic25.C
index 6589e7f60af..a5f1eee7054 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic25.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic25.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<int... Values>
struct sum;
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic26.C b/gcc/testsuite/g++.dg/cpp0x/variadic26.C
index 7f9f6bc8052..9150e429958 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic26.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic26.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<template<int, int> class Meta, int Initial, int... Values>
struct accumulate {
static const int value = Initial;
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic27.C b/gcc/testsuite/g++.dg/cpp0x/variadic27.C
index 45a897ce2c9..f4b4470a39c 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic27.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic27.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename Signature>
struct function_traits;
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic28.C b/gcc/testsuite/g++.dg/cpp0x/variadic28.C
index 167088b4945..4e60d9f2815 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic28.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic28.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename Signature>
struct function_traits;
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic29.C b/gcc/testsuite/g++.dg/cpp0x/variadic29.C
index aaed595831d..a7bc877c73c 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic29.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic29.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename Signature>
struct function_traits;
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic3.C b/gcc/testsuite/g++.dg/cpp0x/variadic3.C
index 42ba8ab47ea..f08ff62b8fb 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic3.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename... Args>
class tuple {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic30.C b/gcc/testsuite/g++.dg/cpp0x/variadic30.C
index 66cbe9f6272..36d93c12f3e 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic30.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic30.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename... T>
void eat(T...);
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic31.C b/gcc/testsuite/g++.dg/cpp0x/variadic31.C
index db8daa89858..48ae5604c92 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic31.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic31.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x -g" }
+// { dg-options "-std=gnu++11 -g" }
template<typename... T>
void eat(T...) { }
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic32.C b/gcc/testsuite/g++.dg/cpp0x/variadic32.C
index c5bee55ccb7..0f620ecbd13 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic32.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic32.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename... T>
void eat(const T&...) { }
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic33.C b/gcc/testsuite/g++.dg/cpp0x/variadic33.C
index 5784be887ac..d962f5a1da9 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic33.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic33.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
void print_all() {}
template<typename T, typename... Rest>
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic34.C b/gcc/testsuite/g++.dg/cpp0x/variadic34.C
index 5eee3f13c62..e266b603e82 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic34.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic34.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<int I, typename... Args>
void get_ith(const Args&... args);
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic35.C b/gcc/testsuite/g++.dg/cpp0x/variadic35.C
index 666a1f5d039..518edec4145 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic35.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic35.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<int I, typename... Args>
void get_ith(const Args&... args); // { dg-message "note" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic36.C b/gcc/testsuite/g++.dg/cpp0x/variadic36.C
index 90636020401..bbd2159b65f 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic36.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic36.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename T, typename... Args>
void f(const T&, const Args&... args)
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic37.C b/gcc/testsuite/g++.dg/cpp0x/variadic37.C
index a6e5f613fcd..2f6042ec27c 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic37.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic37.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename... Values>
struct tuple
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic38.C b/gcc/testsuite/g++.dg/cpp0x/variadic38.C
index e4ae4a6305d..b320a8a3c5c 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic38.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic38.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<int... Values>
struct int_vec {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic39.C b/gcc/testsuite/g++.dg/cpp0x/variadic39.C
index bd656ba8504..4ee19552711 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic39.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic39.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename... Args>
struct tuple {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic4.C b/gcc/testsuite/g++.dg/cpp0x/variadic4.C
index 1bdad3256fb..5371a860bfa 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic4.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic4.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x -fabi-version=0" }
+// { dg-options "-std=gnu++11 -fabi-version=0" }
// { dg-do compile }
template<typename... Args>
class tuple {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic40.C b/gcc/testsuite/g++.dg/cpp0x/variadic40.C
index 6cc9273a897..c6512e90192 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic40.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic40.C
@@ -1,3 +1,3 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename... Values, typename T>
struct backward_tuple {}; // { dg-error "end" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic41.C b/gcc/testsuite/g++.dg/cpp0x/variadic41.C
index 9cfd847f318..3eee1f572c3 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic41.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic41.C
@@ -1,5 +1,5 @@
// A function parameter pack is only deduced if it's at the end
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename... Args>
void f(const Args&... args, int oops);
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic42.C b/gcc/testsuite/g++.dg/cpp0x/variadic42.C
index 3ec68e8b1ff..b5d917f186a 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic42.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic42.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x -fabi-version=5" }
+// { dg-options "-std=gnu++11 -fabi-version=5" }
// { dg-do compile }
template<typename... Args>
void f(Args...) { }
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic43.C b/gcc/testsuite/g++.dg/cpp0x/variadic43.C
index fce81ae0dd1..7310660752c 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic43.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic43.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename... Args>
int f(const Args&...);
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic44.C b/gcc/testsuite/g++.dg/cpp0x/variadic44.C
index 8452a96cc21..1e314be8b19 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic44.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic44.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
// { dg-do compile }
template<typename... Args>
int f(const Args&...);
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic45.C b/gcc/testsuite/g++.dg/cpp0x/variadic45.C
index c5a66ab2062..a36a56b7491 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic45.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic45.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename... Args>
int& f(Args...);
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic46.C b/gcc/testsuite/g++.dg/cpp0x/variadic46.C
index 8b81a363bf1..1fe0e60e0ea 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic46.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic46.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename... Args>
int& f(Args&...);
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic47.C b/gcc/testsuite/g++.dg/cpp0x/variadic47.C
index d80371c0eee..252a4e7b1a5 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic47.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic47.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename T> struct wrap { };
template<typename... Args>
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic48.C b/gcc/testsuite/g++.dg/cpp0x/variadic48.C
index ab3f777f795..ca562c22e6f 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic48.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic48.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename T, typename... Args>
int& f(const T&, Args...);
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic49.C b/gcc/testsuite/g++.dg/cpp0x/variadic49.C
index 7e2215f2c23..4ccedb1cd12 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic49.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic49.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
int& f(...);
template<typename... Args>
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic5.C b/gcc/testsuite/g++.dg/cpp0x/variadic5.C
index d1f333566d8..b2a35106195 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic5.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic5.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename... Args>
struct tuple {
static const int value = 0;
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic50.C b/gcc/testsuite/g++.dg/cpp0x/variadic50.C
index a2c3b7c908f..32fbb65f42d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic50.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic50.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
int& f(int, double, ...);
template<typename... Args>
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic51.C b/gcc/testsuite/g++.dg/cpp0x/variadic51.C
index e2e2d630a7b..9b2fa218dd6 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic51.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic51.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename T1, typename T2>
float& f(T1, T2);
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic52.C b/gcc/testsuite/g++.dg/cpp0x/variadic52.C
index 12b121fe4ec..9293d86878a 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic52.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic52.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename T, T... Values>
struct vector_c { };
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic53.C b/gcc/testsuite/g++.dg/cpp0x/variadic53.C
index 09a3879b420..b595df5db56 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic53.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic53.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename F, typename... BoundArgs>
class bound_functor
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic54.C b/gcc/testsuite/g++.dg/cpp0x/variadic54.C
index db750d76511..dd3ab109da8 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic54.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic54.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename F, typename... BoundArgs>
class bound_functor
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic55.C b/gcc/testsuite/g++.dg/cpp0x/variadic55.C
index b9c8cffb027..e22a16bb8a1 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic55.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic55.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename F, typename... BoundArgs>
class bound_functor
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic56.C b/gcc/testsuite/g++.dg/cpp0x/variadic56.C
index 77846e51321..f0c1beb7894 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic56.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic56.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename... Elements>
struct tuple { };
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic57.C b/gcc/testsuite/g++.dg/cpp0x/variadic57.C
index 9833b1bb359..ca12a2d1a3e 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic57.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic57.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename T, int... Dims>
struct array {
int foo();
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic58.C b/gcc/testsuite/g++.dg/cpp0x/variadic58.C
index 5da0730b5aa..3099ef6808f 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic58.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic58.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
#include <typeinfo>
template<typename... Args>
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic59.C b/gcc/testsuite/g++.dg/cpp0x/variadic59.C
index 6d6e52f9319..e7abf8b78a8 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic59.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic59.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<class T, typename... VarArgs>
void print(T t, VarArgs args); // { dg-error "packs not expanded" }
// { dg-message "VarArgs" "note" { target *-*-* } 3 }
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic6.C b/gcc/testsuite/g++.dg/cpp0x/variadic6.C
index 105550bb903..bf6350e1dd5 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic6.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic6.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename ... Args>
struct tuple_base {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic63.C b/gcc/testsuite/g++.dg/cpp0x/variadic63.C
index 359def1cd10..83db8fc43b4 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic63.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic63.C
@@ -1,2 +1,2 @@
-// { dg-options "-std=gnu++0x -pedantic" }
+// { dg-options "-std=gnu++11 -pedantic" }
template<typename... Args> class tuple;
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic64.C b/gcc/testsuite/g++.dg/cpp0x/variadic64.C
index c9212e2e959..fdc53540613 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic64.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic64.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<int... Indexes>
struct _Index_tuple { };
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic65.C b/gcc/testsuite/g++.dg/cpp0x/variadic65.C
index 77be10676ae..4544f9289ca 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic65.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic65.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
struct unused;
template<typename T1 = unused, typename T2 = unused, typename T3 = unused,
typename T4 = unused, typename T5 = unused, typename T6 = unused>
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic66.C b/gcc/testsuite/g++.dg/cpp0x/variadic66.C
index 5c31ae06fd4..943bd70d0aa 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic66.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic66.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename Result, typename Functor, typename... ArgTypes>
Result bind(Functor, ArgTypes...) { }
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic67.C b/gcc/testsuite/g++.dg/cpp0x/variadic67.C
index e496bfc176c..5538bc911e2 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic67.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic67.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename... Elements> struct tuple {};
template<typename... Args>
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic68.C b/gcc/testsuite/g++.dg/cpp0x/variadic68.C
index 07cf8e3896a..22b3444a0ec 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic68.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic68.C
@@ -1,5 +1,5 @@
// { dg-do run }
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
extern "C" void abort();
template<typename T, T... Values>
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic69.C b/gcc/testsuite/g++.dg/cpp0x/variadic69.C
index 5fe9a1950ff..eb8626524be 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic69.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic69.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename T>
struct stored_value
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic7.C b/gcc/testsuite/g++.dg/cpp0x/variadic7.C
index 3ba37bfb66e..68358f06717 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic7.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic7.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename... Args>
struct tuple_base {
static const int value = 0;
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic70.C b/gcc/testsuite/g++.dg/cpp0x/variadic70.C
index 15bed461dc7..cc269915f42 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic70.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic70.C
@@ -1,5 +1,5 @@
// { dg-do run }
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template <typename T, T... Args> struct bomb;
template <typename T>
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic71.C b/gcc/testsuite/g++.dg/cpp0x/variadic71.C
index bea3cc34631..879321593bc 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic71.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic71.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename...> struct list {};
template<typename Sequence, typename Head>
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic72.C b/gcc/testsuite/g++.dg/cpp0x/variadic72.C
index b1a620d5386..77520b301c2 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic72.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic72.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
struct A {};
struct B {};
struct C {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic73.C b/gcc/testsuite/g++.dg/cpp0x/variadic73.C
index 05925e7aa57..00e8fb46330 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic73.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic73.C
@@ -1,5 +1,5 @@
// { dg-do run }
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
struct A {};
struct B {};
struct C {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic75.C b/gcc/testsuite/g++.dg/cpp0x/variadic75.C
index f57f8b3ef47..32df43fd116 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic75.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic75.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename...> struct tuple { };
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic76.C b/gcc/testsuite/g++.dg/cpp0x/variadic76.C
index ff0211ded15..df147fdcb7a 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic76.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic76.C
@@ -1,6 +1,6 @@
// PR c++/33496
// { dg-do compile }
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<int... N> int foo ()
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic77.C b/gcc/testsuite/g++.dg/cpp0x/variadic77.C
index 8c6119ff160..49b5684b3e3 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic77.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic77.C
@@ -1,6 +1,6 @@
// PR c++/33496
// { dg-do compile }
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<int M, int N> struct pair
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic78.C b/gcc/testsuite/g++.dg/cpp0x/variadic78.C
index 9e2b84ad0a6..4d3d5428c0a 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic78.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic78.C
@@ -1,6 +1,6 @@
// PR c++/33496
// { dg-do compile }
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<int M, int N> struct pair
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic79.C b/gcc/testsuite/g++.dg/cpp0x/variadic79.C
index c6479e04fe5..e7a2a15c049 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic79.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic79.C
@@ -1,6 +1,6 @@
// PR c++/33213
// { dg-do compile }
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<template<typename> class...> struct A;
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic8.C b/gcc/testsuite/g++.dg/cpp0x/variadic8.C
index c3a1340cf26..96fbfad7e79 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic8.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic8.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename... Args>
struct tuple_base {
static const int value = 0;
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic80.C b/gcc/testsuite/g++.dg/cpp0x/variadic80.C
index a56cdb404c0..a8bb9023a68 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic80.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic80.C
@@ -1,6 +1,6 @@
// PR c++/31434
// { dg-do run }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
extern "C" void abort ();
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic81.C b/gcc/testsuite/g++.dg/cpp0x/variadic81.C
index cce61b31649..e282394145c 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic81.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic81.C
@@ -1,5 +1,5 @@
// PR c++/33461
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename> struct A;
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic82.C b/gcc/testsuite/g++.dg/cpp0x/variadic82.C
index 03aec80211d..50be75db557 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic82.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic82.C
@@ -1,5 +1,5 @@
// PR c++/33461
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename> struct A;
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic83.C b/gcc/testsuite/g++.dg/cpp0x/variadic83.C
index c446e697420..3293d813a89 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic83.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic83.C
@@ -1,5 +1,5 @@
// PR c++/31441
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename> struct A;
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic84.C b/gcc/testsuite/g++.dg/cpp0x/variadic84.C
index ce31267954f..8e0dc4475fe 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic84.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic84.C
@@ -1,6 +1,6 @@
// PR c++/32565
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<typename...> struct A1;
template<template<int...> class T> struct A1<T<0> > {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic85.C b/gcc/testsuite/g++.dg/cpp0x/variadic85.C
index facb263910f..6f6cb8a17bf 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic85.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic85.C
@@ -1,6 +1,6 @@
// PR c++/32565
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<typename...> struct A1;
template<template<int, int...> class T> struct A1<T<0, 1> > {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic86.C b/gcc/testsuite/g++.dg/cpp0x/variadic86.C
index d8fcd620e95..73400548a96 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic86.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic86.C
@@ -1,6 +1,6 @@
// PR c++/33943
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<typename... A> struct foo {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic87.C b/gcc/testsuite/g++.dg/cpp0x/variadic87.C
index 1defa23da29..7e82f37a663 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic87.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic87.C
@@ -1,5 +1,5 @@
// PR c++/33965
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<typename T>
struct foo
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic88.C b/gcc/testsuite/g++.dg/cpp0x/variadic88.C
index b14cabe3218..a917b530212 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic88.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic88.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<template<typename...> class TT>
TT<int, float, double> foo(TT<int, float>)
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic89.C b/gcc/testsuite/g++.dg/cpp0x/variadic89.C
index b943771a6de..b5bedeba7e6 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic89.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic89.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// Contributed by Eric Niebler
template<typename T, typename U>
struct pair
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic9.C b/gcc/testsuite/g++.dg/cpp0x/variadic9.C
index c5db6af6a89..2d12de5fdf1 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic9.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic9.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
template<typename T1, typename T2>
struct pair {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic90.C b/gcc/testsuite/g++.dg/cpp0x/variadic90.C
index 632e166c346..0529057e623 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic90.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic90.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<template<typename...> class TT>
struct X { };
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic91.C b/gcc/testsuite/g++.dg/cpp0x/variadic91.C
index d78b791fbf4..a5ebdfe7aa2 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic91.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic91.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<int N> struct Int2Type { };
template<typename... T>
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic92.C b/gcc/testsuite/g++.dg/cpp0x/variadic92.C
index d382912c91f..b7fa0006b34 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic92.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic92.C
@@ -1,5 +1,5 @@
// Various tests for variadic templates and partial specialization.
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// PR c++/36846
template<typename A, typename B>
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic93.C b/gcc/testsuite/g++.dg/cpp0x/variadic93.C
index 7d8c3298e61..c17988490fa 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic93.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic93.C
@@ -1,5 +1,5 @@
// PR c++/35297
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template <class T=int, class... ARGS>
struct test2 {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic94.C b/gcc/testsuite/g++.dg/cpp0x/variadic94.C
index 8420f73a6a6..213e53cab58 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic94.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic94.C
@@ -1,5 +1,5 @@
// PR c++/40595
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<int N>
struct S
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic95.C b/gcc/testsuite/g++.dg/cpp0x/variadic95.C
index ebb04ebc10b..b84489aa593 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic95.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic95.C
@@ -1,5 +1,5 @@
// PR c++/39863
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template <typename... T>
struct A {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic96.C b/gcc/testsuite/g++.dg/cpp0x/variadic96.C
index d4709d074b6..e5e7df14729 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic96.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic96.C
@@ -1,6 +1,6 @@
// Contributed by Dodji Seketeli <dodji@redhat.com>
// Origin: PR c++/41785
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
struct a {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic97.C b/gcc/testsuite/g++.dg/cpp0x/variadic97.C
index a2070319ebd..8c3783251df 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic97.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic97.C
@@ -1,5 +1,5 @@
// PR c++/42266
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
template<typename... _Elements>
class tuple;
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic98.C b/gcc/testsuite/g++.dg/cpp0x/variadic98.C
index 6af599fcaa0..a29ee8e4211 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic98.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic98.C
@@ -1,6 +1,6 @@
// PR c++/42358
// { dg-do assemble }
-// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
typedef __PTRDIFF_TYPE__ ptrdiff_t;
typedef __SIZE_TYPE__ size_t;
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic99.C b/gcc/testsuite/g++.dg/cpp0x/variadic99.C
index 457212712bd..f6544310bc5 100644
--- a/gcc/testsuite/g++.dg/cpp0x/variadic99.C
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic99.C
@@ -1,5 +1,5 @@
// PR c++/43054
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<typename R> struct future { };
diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-33964.C b/gcc/testsuite/g++.dg/cpp0x/vt-33964.C
index 0b84b6cec89..9ba9367e8da 100644
--- a/gcc/testsuite/g++.dg/cpp0x/vt-33964.C
+++ b/gcc/testsuite/g++.dg/cpp0x/vt-33964.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<typename ... Args>
struct foo
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-34050.C b/gcc/testsuite/g++.dg/cpp0x/vt-34050.C
index cb19b3914c0..fba340abfd5 100644
--- a/gcc/testsuite/g++.dg/cpp0x/vt-34050.C
+++ b/gcc/testsuite/g++.dg/cpp0x/vt-34050.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
struct A {};
template<typename... T> struct B : T...
diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-34051-2.C b/gcc/testsuite/g++.dg/cpp0x/vt-34051-2.C
index 2c7bb50f081..02373f89027 100644
--- a/gcc/testsuite/g++.dg/cpp0x/vt-34051-2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/vt-34051-2.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<typename... T> struct A
{
int i __attribute__((aligned(__alignof(T)))); // { dg-error "parameter packs|T" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-34051.C b/gcc/testsuite/g++.dg/cpp0x/vt-34051.C
index 88ae5670323..7d37bf27181 100644
--- a/gcc/testsuite/g++.dg/cpp0x/vt-34051.C
+++ b/gcc/testsuite/g++.dg/cpp0x/vt-34051.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
struct A
{
operator int();
diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-34052.C b/gcc/testsuite/g++.dg/cpp0x/vt-34052.C
index 15310cfe74d..a2e44b6cde7 100644
--- a/gcc/testsuite/g++.dg/cpp0x/vt-34052.C
+++ b/gcc/testsuite/g++.dg/cpp0x/vt-34052.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<typename... T, typename = T> struct A {}; // { dg-error "must be at the end" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-34055.C b/gcc/testsuite/g++.dg/cpp0x/vt-34055.C
index c50778430e0..3caee091862 100644
--- a/gcc/testsuite/g++.dg/cpp0x/vt-34055.C
+++ b/gcc/testsuite/g++.dg/cpp0x/vt-34055.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// PR c++/34055
template<typename...> struct A;
diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-34102.C b/gcc/testsuite/g++.dg/cpp0x/vt-34102.C
index 00f0b4f4aac..90ef7728058 100644
--- a/gcc/testsuite/g++.dg/cpp0x/vt-34102.C
+++ b/gcc/testsuite/g++.dg/cpp0x/vt-34102.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// PR c++/34102
struct A {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-34103.C b/gcc/testsuite/g++.dg/cpp0x/vt-34103.C
index 3bbbb46a012..e1a8574d27e 100644
--- a/gcc/testsuite/g++.dg/cpp0x/vt-34103.C
+++ b/gcc/testsuite/g++.dg/cpp0x/vt-34103.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// PR c++/34103
template<typename> struct A {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-34219-2.C b/gcc/testsuite/g++.dg/cpp0x/vt-34219-2.C
index 193bc0c6cf9..4f145ca2721 100644
--- a/gcc/testsuite/g++.dg/cpp0x/vt-34219-2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/vt-34219-2.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<template<typename... T> class Comp, typename... T> void f( T... Value)
{
static_assert( Comp<T>::value > 0, "" ); // { dg-error "parameter packs|T" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-34219.C b/gcc/testsuite/g++.dg/cpp0x/vt-34219.C
index fb3584ea88d..0cf603e8872 100644
--- a/gcc/testsuite/g++.dg/cpp0x/vt-34219.C
+++ b/gcc/testsuite/g++.dg/cpp0x/vt-34219.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<typename T, T a, T... Params>
struct max
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-34314.C b/gcc/testsuite/g++.dg/cpp0x/vt-34314.C
index 4a935b367d6..6f3d0159392 100644
--- a/gcc/testsuite/g++.dg/cpp0x/vt-34314.C
+++ b/gcc/testsuite/g++.dg/cpp0x/vt-34314.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<typename Fun, typename... Args> // { dg-error "template parameter" }
struct call;
diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-34399.C b/gcc/testsuite/g++.dg/cpp0x/vt-34399.C
index 542fae586ca..11e7391372d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/vt-34399.C
+++ b/gcc/testsuite/g++.dg/cpp0x/vt-34399.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<int...> struct A
{
void foo();
diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-34606.C b/gcc/testsuite/g++.dg/cpp0x/vt-34606.C
index 46794335442..679bb9a7a24 100644
--- a/gcc/testsuite/g++.dg/cpp0x/vt-34606.C
+++ b/gcc/testsuite/g++.dg/cpp0x/vt-34606.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<typename...> struct A;
template<typename T, typename... U> struct A<T, U> // { dg-error "parameter packs|U" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-34751.C b/gcc/testsuite/g++.dg/cpp0x/vt-34751.C
index e3ca39e798d..f500396fc94 100644
--- a/gcc/testsuite/g++.dg/cpp0x/vt-34751.C
+++ b/gcc/testsuite/g++.dg/cpp0x/vt-34751.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// PR c++/34751
struct A {};
diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-34753.C b/gcc/testsuite/g++.dg/cpp0x/vt-34753.C
index 15eaebebc88..d435138d1c3 100644
--- a/gcc/testsuite/g++.dg/cpp0x/vt-34753.C
+++ b/gcc/testsuite/g++.dg/cpp0x/vt-34753.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<typename... T> struct A
{
template<T> struct B {}; // { dg-error "not expanded|T" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-34754.C b/gcc/testsuite/g++.dg/cpp0x/vt-34754.C
index 97c0065328f..ae0c4ec71da 100644
--- a/gcc/testsuite/g++.dg/cpp0x/vt-34754.C
+++ b/gcc/testsuite/g++.dg/cpp0x/vt-34754.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<template<int> class... T> struct A
{
void foo(T<0>); // { dg-error "not expanded|T" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-34755.C b/gcc/testsuite/g++.dg/cpp0x/vt-34755.C
index 9d5a3d1ca4d..c642b776cb7 100644
--- a/gcc/testsuite/g++.dg/cpp0x/vt-34755.C
+++ b/gcc/testsuite/g++.dg/cpp0x/vt-34755.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<typename> struct A {};
template<template<typename> class... T> void foo(T<int>) {} // { dg-error "not expanded|T" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-34919.C b/gcc/testsuite/g++.dg/cpp0x/vt-34919.C
index 829579918e1..94de312bf9c 100644
--- a/gcc/testsuite/g++.dg/cpp0x/vt-34919.C
+++ b/gcc/testsuite/g++.dg/cpp0x/vt-34919.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<int... N> struct A
{
static void foo()
diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-34961.C b/gcc/testsuite/g++.dg/cpp0x/vt-34961.C
index 3a872146e25..368a4530951 100644
--- a/gcc/testsuite/g++.dg/cpp0x/vt-34961.C
+++ b/gcc/testsuite/g++.dg/cpp0x/vt-34961.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<typename... T> struct A
{
static const int i __attribute__((aligned(__alignof(T)))) = 0; // { dg-error "not expanded|T" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-35023.C b/gcc/testsuite/g++.dg/cpp0x/vt-35023.C
index 9db20503e7e..4646b7a74b5 100644
--- a/gcc/testsuite/g++.dg/cpp0x/vt-35023.C
+++ b/gcc/testsuite/g++.dg/cpp0x/vt-35023.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<typename... T> int foo()
{
T t; // { dg-error "parameter packs|T" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-35024.C b/gcc/testsuite/g++.dg/cpp0x/vt-35024.C
index 77f0b66bdc0..3e2654f1e36 100644
--- a/gcc/testsuite/g++.dg/cpp0x/vt-35024.C
+++ b/gcc/testsuite/g++.dg/cpp0x/vt-35024.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<typename... T> int foo()
{
typename T::X x; // { dg-error "parameter packs|T" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-35026.C b/gcc/testsuite/g++.dg/cpp0x/vt-35026.C
index 643a416c578..491537df977 100644
--- a/gcc/testsuite/g++.dg/cpp0x/vt-35026.C
+++ b/gcc/testsuite/g++.dg/cpp0x/vt-35026.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<typename... T> struct A
{
T* x[1]; // { dg-error "parameter packs|T" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-35147.C b/gcc/testsuite/g++.dg/cpp0x/vt-35147.C
index fecb36ec8c9..3b2250baeef 100644
--- a/gcc/testsuite/g++.dg/cpp0x/vt-35147.C
+++ b/gcc/testsuite/g++.dg/cpp0x/vt-35147.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<typename _Tp>
_Tp&& forward(_Tp&& __t) { return __t; } // { dg-message "note" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-35242.C b/gcc/testsuite/g++.dg/cpp0x/vt-35242.C
index 9cc859b875e..2df4bae4922 100644
--- a/gcc/testsuite/g++.dg/cpp0x/vt-35242.C
+++ b/gcc/testsuite/g++.dg/cpp0x/vt-35242.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
struct A
{
template<typename... T> struct B;
diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-35243.C b/gcc/testsuite/g++.dg/cpp0x/vt-35243.C
index 4b555744269..a425528b233 100644
--- a/gcc/testsuite/g++.dg/cpp0x/vt-35243.C
+++ b/gcc/testsuite/g++.dg/cpp0x/vt-35243.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
struct A {};
template<typename... T> struct B : T...
diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-35331.C b/gcc/testsuite/g++.dg/cpp0x/vt-35331.C
index 0add9819bd0..06fda619102 100644
--- a/gcc/testsuite/g++.dg/cpp0x/vt-35331.C
+++ b/gcc/testsuite/g++.dg/cpp0x/vt-35331.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<typename...> struct A;
template<typename...T> struct A<T*> // { dg-error "not expanded|T" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-37737-1.C b/gcc/testsuite/g++.dg/cpp0x/vt-37737-1.C
index de11b1651b4..8745dde372e 100644
--- a/gcc/testsuite/g++.dg/cpp0x/vt-37737-1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/vt-37737-1.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
// { dg-prune-output "note" }
void f() { }
diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-37737-2.C b/gcc/testsuite/g++.dg/cpp0x/vt-37737-2.C
index 5514259ec3f..178db4f7c19 100644
--- a/gcc/testsuite/g++.dg/cpp0x/vt-37737-2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/vt-37737-2.C
@@ -1,4 +1,4 @@
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template<class U, class... T>
void f() // { dg-message "note" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-40092.C b/gcc/testsuite/g++.dg/cpp0x/vt-40092.C
index ecb69806130..f3b53d00229 100644
--- a/gcc/testsuite/g++.dg/cpp0x/vt-40092.C
+++ b/gcc/testsuite/g++.dg/cpp0x/vt-40092.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-std=c++0x" }
+// { dg-options "-std=c++11" }
template <typename... Types> struct package {};
diff --git a/gcc/testsuite/g++.dg/cpp1y/attr-deprecated-neg.C b/gcc/testsuite/g++.dg/cpp1y/attr-deprecated-neg.C
new file mode 100644
index 00000000000..b2f0e1238d7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/attr-deprecated-neg.C
@@ -0,0 +1,59 @@
+// { dg-do compile }
+// { dg-options -std=c++11 }
+
+class [[deprecated]] A // { dg-warning "attribute directive ignored" }
+{
+};
+
+[[deprecated]]
+int
+foo(int n) // { dg-warning "attribute directive ignored" }
+{
+ return 42 + n;
+}
+
+class [[deprecated("B has been superceded by C")]] B // { dg-warning "attribute directive ignored" }
+{
+};
+
+[[deprecated("bar is unsafe; use foobar instead")]]
+int
+bar(int n) // { dg-warning "attribute directive ignored" }
+{
+ return 42 + n - 1;
+}
+
+#if __cplusplus > 201103L
+
+// Deprecate C for C++14 onwards.
+class [[deprecated]] C;
+
+// Deprecate foobar for C++14 onwards.
+[[deprecated]]
+int
+foobar(int n);
+
+#endif
+
+class C
+{
+};
+
+int
+foobar(int n)
+{
+ return 43 + n - 1;
+}
+
+int
+main()
+{
+ A aaa;
+ int n = foo(12);
+
+ B bbb;
+ int m = bar(666);
+
+ C ccc;
+ int l = foobar(8);
+}
diff --git a/gcc/testsuite/g++.dg/cpp1y/attr-deprecated.C b/gcc/testsuite/g++.dg/cpp1y/attr-deprecated.C
new file mode 100644
index 00000000000..8cd09c7bb7c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/attr-deprecated.C
@@ -0,0 +1,59 @@
+// { dg-do compile }
+// { dg-options -std=c++1y }
+
+class [[deprecated]] A
+{
+};
+
+[[deprecated]]
+int
+foo(int n)
+{
+ return 42 + n;
+}
+
+class [[deprecated("B has been superceded by C")]] B
+{
+};
+
+[[deprecated("bar is unsafe; use foobar instead")]]
+int
+bar(int n)
+{
+ return 42 + n - 1;
+}
+
+#if __cplusplus > 201103L
+
+// Deprecate C for C++14 onwards.
+class [[deprecated]] C;
+
+// Deprecate foobar for C++14 onwards.
+[[deprecated]]
+int
+foobar(int n);
+
+#endif
+
+class C
+{
+};
+
+int
+foobar(int n)
+{
+ return 43 + n - 1;
+}
+
+int
+main()
+{
+ A aaa; // { dg-warning "is deprecated" }
+ int n = foo(12); // { dg-warning "is deprecated" }
+
+ B bbb; // { dg-warning "is deprecated" "B has been superceded by C" }
+ int m = bar(666); // { dg-warning "is deprecated" "bar is unsafe; use foobar instead" }
+
+ C ccc; // { dg-warning "is deprecated" }
+ int l = foobar(8); // { dg-warning "is deprecated" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp1y/digit-sep-cxx11-neg.C b/gcc/testsuite/g++.dg/cpp1y/digit-sep-cxx11-neg.C
new file mode 100644
index 00000000000..a078fa2a33f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/digit-sep-cxx11-neg.C
@@ -0,0 +1,12 @@
+// { dg-options -std=c++11 }
+
+#define assert(E) if(!(E))__builtin_abort();
+
+#define m(x) 0
+
+int
+main()
+{
+ int i = m(1'2)+(3'4);
+ assert(i == 0);
+}
diff --git a/gcc/testsuite/g++.dg/cpp1y/digit-sep-neg.C b/gcc/testsuite/g++.dg/cpp1y/digit-sep-neg.C
new file mode 100644
index 00000000000..371e675577c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/digit-sep-neg.C
@@ -0,0 +1,26 @@
+// { dg-options -std=c++1y }
+
+int
+main()
+{
+ int i = 0;
+ i = 1048''576; // { dg-error "adjacent digit separators" }
+ i = 0X'100000; // { dg-error "digit separator after base indicator" }
+ i = 0x'100000; // { dg-error "digit separator after base indicator" }
+ i = 0004''000'000); // { dg-error "adjacent digit separators" }
+ i = 0B1'0'0'0'0'0'0'0'0'0'0'0'0'0'0'0'0'0'0'0'0; // OK
+ i = 0b'0001'0000'0000'0000'0000'0000; // { dg-error "digit separator after base indicator" }
+ i = 0b0001'0000'0000'0000'0000'0000'; // { dg-error "digit separator outside digit sequence" }
+ unsigned u = 0b0001'0000'0000'0000'0000'0000'U; // { dg-error "digit separator outside digit sequence" }
+
+ double d = 0.0;
+ d = 1'.602'176'565e-19; // { dg-error "digit separator adjacent to decimal point" }
+ d = 1.'602'176'565e-19; // { dg-error "digit separator adjacent to decimal point" }
+ d = 1.602''176'565e-19; // { dg-error "adjacent digit separators" }
+ d = 1.602'176'565'e-19; // { dg-error "digit separator adjacent to exponent" }
+ d = 1.602'176'565e'-19; // { dg-error "digit separator adjacent to exponent" }
+ d = 1.602'176'565e-'19; // { dg-error "digit separator adjacent to exponent" }
+ d = 1.602'176'565e-1'9; // OK
+ d = 1.602'176'565e-19'; // { dg-error "digit separator outside digit sequence" }
+ float f = 1.602'176'565e-19'F; // { dg-error "digit separator outside digit sequence" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp1y/digit-sep.C b/gcc/testsuite/g++.dg/cpp1y/digit-sep.C
new file mode 100644
index 00000000000..69b1c691014
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/digit-sep.C
@@ -0,0 +1,22 @@
+// { dg-options -std=c++1y }
+
+#define assert(E) if(!(E))__builtin_abort();
+
+#define m(x) 0
+
+int
+main()
+{
+ assert(1048576 == 1'048'576);
+ assert(1048576 == 0X100000);
+ assert(1048576 == 0x10'0000);
+ assert(1048576 == 0'004'000'000);
+ assert(1048576 == 0B100000000000000000000);
+ assert(1048576 == 0b0001'0000'0000'0000'0000'0000);
+
+ assert(1.602'176'565e-19 == 1.602176565e-19);
+ assert(1.602'176'565e-1'9 == 1.602176565e-19);
+
+ int i = m(1'2)+(3'4);
+ assert(i == 34);
+}
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr58500.C b/gcc/testsuite/g++.dg/cpp1y/pr58500.C
new file mode 100644
index 00000000000..b9d4a26d415
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/pr58500.C
@@ -0,0 +1,8 @@
+// { dg-do compile }
+// { dg-options "-std=gnu++1y" }
+
+// PR c++/58500
+
+struct A {};
+
+void foo(auto (A::*)());
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr58535.C b/gcc/testsuite/g++.dg/cpp1y/pr58535.C
new file mode 100644
index 00000000000..2bf62b0b3d8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/pr58535.C
@@ -0,0 +1,7 @@
+// PR c++/58535
+// { dg-options "-std=gnu++1y" }
+
+struct A
+{
+ virtual void foo(auto); // { dg-error "templates" }
+};
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr58708.C b/gcc/testsuite/g++.dg/cpp1y/pr58708.C
new file mode 100644
index 00000000000..a9c19ebb6c3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/pr58708.C
@@ -0,0 +1,60 @@
+// { dg-options -std=c++1y }
+// { dg-do run }
+
+template<typename, typename>
+ struct is_same
+ {
+ static constexpr bool value = false;
+ };
+
+template<typename _Tp>
+ struct is_same<_Tp, _Tp>
+ {
+ static constexpr bool value = true;
+ };
+
+template<typename CharT, CharT... Str>
+ struct Foo
+ {
+ using char_type = CharT;
+ char_type chars[sizeof...(Str)]{Str...};
+ };
+
+template<typename CharT, CharT... Str>
+ Foo<CharT, Str...>
+ operator""_foo()
+ {
+ return Foo<CharT, Str...>();
+ }
+
+int
+main()
+{
+ auto fooU = U"\x10000\x10001\x10002"_foo;
+ if (is_same<decltype(fooU)::char_type, char32_t>::value != true) __builtin_abort();
+ if (sizeof(fooU.chars)/sizeof(char32_t) != 3) __builtin_abort();
+ if (fooU.chars[0] != 65536) __builtin_abort();
+ if (fooU.chars[1] != 65537) __builtin_abort();
+ if (fooU.chars[2] != 65538) __builtin_abort();
+
+ auto foo = "\x61\x62\x63"_foo;
+ if (is_same<decltype(foo)::char_type, char>::value != true) __builtin_abort();
+ if (sizeof(foo.chars)/sizeof(char) != 3) __builtin_abort();
+ if (foo.chars[0] != 97) __builtin_abort();
+ if (foo.chars[1] != 98) __builtin_abort();
+ if (foo.chars[2] != 99) __builtin_abort();
+
+ auto wfoo = L"\x01020304\x05060708"_foo;
+ if (is_same<decltype(wfoo)::char_type, wchar_t>::value != true) __builtin_abort();
+ if (sizeof(wfoo.chars)/sizeof(wchar_t) != 2) __builtin_abort();
+ if (wfoo.chars[0] != 16909060) __builtin_abort();
+ if (wfoo.chars[1] != 84281096) __builtin_abort();
+
+ auto foou = u"\x0102\x0304\x0506\x0708"_foo;
+ if (is_same<decltype(foou)::char_type, char16_t>::value != true) __builtin_abort();
+ if (sizeof(foou.chars)/sizeof(char16_t) != 4) __builtin_abort();
+ if (foou.chars[0] != 258) __builtin_abort();
+ if (foou.chars[1] != 772) __builtin_abort();
+ if (foou.chars[2] != 1286) __builtin_abort();
+ if (foou.chars[3] != 1800) __builtin_abort();
+}
diff --git a/gcc/testsuite/g++.dg/diagnostic/pr58979.C b/gcc/testsuite/g++.dg/diagnostic/pr58979.C
new file mode 100644
index 00000000000..6be3f143693
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/pr58979.C
@@ -0,0 +1,4 @@
+// PR c++/58979
+// { dg-do compile }
+
+int i = 0->*0; // { dg-error "invalid type argument of" }
diff --git a/gcc/testsuite/g++.dg/ext/altivec-7.C b/gcc/testsuite/g++.dg/ext/altivec-7.C
index 7c458fb003f..038335433f4 100644
--- a/gcc/testsuite/g++.dg/ext/altivec-7.C
+++ b/gcc/testsuite/g++.dg/ext/altivec-7.C
@@ -20,17 +20,17 @@ void foo(int) { }
void foo(unsigned int) { }
void foo(float) { }
-/* { dg-final { scan-assembler "_Z3fooU8__vectorh" } } */
-/* { dg-final { scan-assembler "_Z3fooU8__vectora" } } */
-/* { dg-final { scan-assembler "_Z3fooU8__vectorU6__boolc" } } */
-/* { dg-final { scan-assembler "_Z3fooU8__vectort" } } */
-/* { dg-final { scan-assembler "_Z3fooU8__vectors" } } */
-/* { dg-final { scan-assembler "_Z3fooU8__vectorU6__bools" } } */
-/* { dg-final { scan-assembler "_Z3fooU8__vectorj" } } */
-/* { dg-final { scan-assembler "_Z3fooU8__vectori" } } */
-/* { dg-final { scan-assembler "_Z3fooU8__vectorU6__booli" } } */
-/* { dg-final { scan-assembler "_Z3fooU8__vectorf" } } */
-/* { dg-final { scan-assembler "_Z3fooU8__vectoru7__pixel" } } */
+/* { dg-final { scan-assembler "_Z3fooDv16_h" } } */
+/* { dg-final { scan-assembler "_Z3fooDv16_a" } } */
+/* { dg-final { scan-assembler "_Z3fooDv16_U6__boolc" } } */
+/* { dg-final { scan-assembler "_Z3fooDv8_t" } } */
+/* { dg-final { scan-assembler "_Z3fooDv8_s" } } */
+/* { dg-final { scan-assembler "_Z3fooDv8_U6__bools" } } */
+/* { dg-final { scan-assembler "_Z3fooDv4_j" } } */
+/* { dg-final { scan-assembler "_Z3fooDv4_i" } } */
+/* { dg-final { scan-assembler "_Z3fooDv4_U6__booli" } } */
+/* { dg-final { scan-assembler "_Z3fooDv4_f" } } */
+/* { dg-final { scan-assembler "_Z3fooDv8_u7__pixel" } } */
/* { dg-final { scan-assembler "_Z3fooi" } } */
/* { dg-final { scan-assembler "_Z3fooj" } } */
/* { dg-final { scan-assembler "_Z3foof" } } */
diff --git a/gcc/testsuite/g++.dg/ext/anon-struct4.C b/gcc/testsuite/g++.dg/ext/anon-struct4.C
index 5d0bf71ae63..9c8e887dacc 100644
--- a/gcc/testsuite/g++.dg/ext/anon-struct4.C
+++ b/gcc/testsuite/g++.dg/ext/anon-struct4.C
@@ -1,5 +1,5 @@
// PR c++/14401
-struct { struct { int& i ; } bar ; } foo ; // { dg-error "uninitialized" "uninit" }
+struct { struct { int& i ; } bar ; } foo ; // { dg-error "deleted|uninitialized" "uninit" }
// { dg-warning "anonymous" "anon" { target c++98 } 3 }
-// { dg-message "should be initialized" "ref-uninit" { target *-*-* } 3 }
+// { dg-message "should be initialized" "ref-uninit" { target c++98 } 3 }
diff --git a/gcc/testsuite/g++.dg/ext/attrib47.C b/gcc/testsuite/g++.dg/ext/attrib47.C
new file mode 100644
index 00000000000..22f49084bcc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/attrib47.C
@@ -0,0 +1,21 @@
+// { dg-do compile }
+// { dg-options "-O2" }
+
+class A
+{
+ public:
+ template <class T>
+ T foo(T a) __attribute__ ((noinline));
+};
+
+template <class T>
+ T A::foo(T a)
+ {
+ return a+1;
+ }
+
+int bar(A a) {
+ return a.foo(1);
+}
+
+// { dg-final { scan-assembler "_ZN1A3fooIiEET_S1_" } }
diff --git a/gcc/testsuite/g++.dg/ext/pr58834.C b/gcc/testsuite/g++.dg/ext/pr58834.C
new file mode 100644
index 00000000000..02930333170
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/pr58834.C
@@ -0,0 +1,5 @@
+template<typename> void foo()
+{
+ int i __attribute__((vector_size(2*sizeof(int))));
+ (void) __builtin_shuffle(i, i);
+}
diff --git a/gcc/testsuite/g++.dg/ext/sync-4.C b/gcc/testsuite/g++.dg/ext/sync-4.C
new file mode 100644
index 00000000000..14ed27337fb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/sync-4.C
@@ -0,0 +1,122 @@
+/* { dg-do run { target hppa*-*-hpux* *-*-linux* *-*-gnu* powerpc*-*-darwin* *-*-darwin[912]* } } */
+/* { dg-require-effective-target sync_long_long_runtime } */
+/* { dg-options "-fexceptions -fnon-call-exceptions -O2" } */
+
+/* Verify that the builtin functions are correctly marked as trapping
+ when using -fnon-call-exceptions. */
+
+#include <stdlib.h>
+#include <signal.h>
+
+typedef int int32_t __attribute__ ((mode (SI)));
+typedef int int64_t __attribute__ ((mode (DI)));
+
+#define FN(IDX, RET, CALL) \
+static RET f ## IDX (void *p) __attribute__ ((noinline)); \
+static RET \
+f ## IDX (void *p) \
+{ \
+ return CALL; \
+} \
+static void \
+t ## IDX () \
+{ \
+ try \
+ { \
+ f ## IDX(0); \
+ } \
+ catch (...) \
+ { \
+ return; \
+ } \
+ abort(); \
+}
+
+FN(1, int64_t, (__sync_fetch_and_add((int64_t*)p, 1)))
+FN(2, int64_t, (__sync_fetch_and_sub((int64_t*)p, 1)))
+FN(3, int64_t, (__sync_fetch_and_or((int64_t*)p, 1)))
+FN(4, int64_t, (__sync_fetch_and_and((int64_t*)p, 1)))
+FN(5, int64_t, (__sync_fetch_and_xor((int64_t*)p, 1)))
+FN(6, int64_t, (__sync_fetch_and_nand((int64_t*)p, 1)))
+
+FN( 7, int64_t, (__sync_add_and_fetch((int64_t*)p, 1)))
+FN( 8, int64_t, (__sync_sub_and_fetch((int64_t*)p, 1)))
+FN( 9, int64_t, (__sync_or_and_fetch((int64_t*)p, 1)))
+FN(10, int64_t, (__sync_and_and_fetch((int64_t*)p, 1)))
+FN(11, int64_t, (__sync_xor_and_fetch((int64_t*)p, 1)))
+FN(12, int64_t, (__sync_nand_and_fetch((int64_t*)p, 1)))
+
+FN(13, bool, (__sync_bool_compare_and_swap((int64_t*)p, 1, 2)))
+FN(14, int64_t, (__sync_val_compare_and_swap((int64_t*)p, 1, 2)))
+
+FN(15, int64_t, (__sync_lock_test_and_set((int64_t*)p, 1)))
+FN(16, void, (__sync_lock_release((int64_t*)p)))
+
+FN(17, bool, (__atomic_test_and_set((int64_t*)p, __ATOMIC_SEQ_CST)))
+FN(18, void, (__atomic_clear((int64_t*)p, __ATOMIC_SEQ_CST)))
+
+FN(19, void, (__atomic_exchange((int64_t*)p, (int64_t*)0, (int64_t*)0, __ATOMIC_SEQ_CST)))
+FN(20, int64_t, (__atomic_exchange_n((int64_t*)p, 1, 2)))
+
+FN(21, void, (__atomic_load((int64_t*)p, (int64_t*)0, __ATOMIC_SEQ_CST)))
+FN(22, int64_t, (__atomic_load_n((int64_t*)p, __ATOMIC_SEQ_CST)))
+
+FN(23, bool, (__atomic_compare_exchange((int64_t*)p, (int64_t*)0, (int64_t*)0, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)))
+FN(24, bool, (__atomic_compare_exchange_n((int64_t*)p, (int64_t*)0, 1, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)))
+
+FN(25, void, (__atomic_store((int64_t*)p, (int64_t*)0, __ATOMIC_SEQ_CST)))
+FN(26, void, (__atomic_store_n((int64_t*)p, 1, __ATOMIC_SEQ_CST)))
+
+FN(27, int64_t, (__atomic_add_fetch((int64_t*)p, 1, __ATOMIC_SEQ_CST)))
+FN(28, int64_t, (__atomic_sub_fetch((int64_t*)p, 1, __ATOMIC_SEQ_CST)))
+FN(29, int64_t, (__atomic_and_fetch((int64_t*)p, 1, __ATOMIC_SEQ_CST)))
+FN(30, int64_t, (__atomic_nand_fetch((int64_t*)p, 1, __ATOMIC_SEQ_CST)))
+FN(31, int64_t, (__atomic_xor_fetch((int64_t*)p, 1, __ATOMIC_SEQ_CST)))
+FN(32, int64_t, (__atomic_or_fetch((int64_t*)p, 1, __ATOMIC_SEQ_CST)))
+
+FN(33, int64_t, (__atomic_fetch_add((int64_t*)p, 1, __ATOMIC_SEQ_CST)))
+FN(34, int64_t, (__atomic_fetch_sub((int64_t*)p, 1, __ATOMIC_SEQ_CST)))
+FN(35, int64_t, (__atomic_fetch_and((int64_t*)p, 1, __ATOMIC_SEQ_CST)))
+FN(36, int64_t, (__atomic_fetch_nand((int64_t*)p, 1, __ATOMIC_SEQ_CST)))
+FN(37, int64_t, (__atomic_fetch_xor((int64_t*)p, 1, __ATOMIC_SEQ_CST)))
+FN(38, int64_t, (__atomic_fetch_or((int64_t*)p, 1, __ATOMIC_SEQ_CST)))
+
+static void
+handler(int)
+{
+ sigset_t clear;
+
+ sigfillset (&clear);
+ sigprocmask (SIG_UNBLOCK, &clear, NULL);
+ throw 0;
+}
+
+int
+main ()
+{
+ signal (SIGSEGV, handler);
+ signal (SIGBUS, handler);
+
+ t1();
+ t2();
+ t3();
+ t4();
+ t5();
+ t6();
+ t7();
+ t8();
+ t9();
+ t10();
+ t11();
+ t12();
+ t13();
+ t14();
+ t15();
+ t16();
+ t17();
+ t18();
+ t19();
+ t20();
+
+ exit(0);
+}
diff --git a/gcc/testsuite/g++.dg/gomp/block-0.C b/gcc/testsuite/g++.dg/gomp/block-0.C
index fa7865d8b93..86af0404ab3 100644
--- a/gcc/testsuite/g++.dg/gomp/block-0.C
+++ b/gcc/testsuite/g++.dg/gomp/block-0.C
@@ -22,8 +22,10 @@ void foo()
bar ();
#pragma omp parallel sections
{
- bar ();
- bar ();
+ {
+ bar ();
+ bar ();
+ }
#pragma omp section
bar ();
}
diff --git a/gcc/testsuite/g++.dg/gomp/block-3.C b/gcc/testsuite/g++.dg/gomp/block-3.C
index aeb0c7795a0..ff281752843 100644
--- a/gcc/testsuite/g++.dg/gomp/block-3.C
+++ b/gcc/testsuite/g++.dg/gomp/block-3.C
@@ -35,8 +35,10 @@ void foo()
#pragma omp sections
{
- goto ok1;
- ok1:;
+ {
+ goto ok1;
+ ok1:;
+ }
#pragma omp section
for (i = 0; i < 10; ++i)
diff --git a/gcc/testsuite/g++.dg/gomp/clause-3.C b/gcc/testsuite/g++.dg/gomp/clause-3.C
index a048c60b8af..1a20440d7c2 100644
--- a/gcc/testsuite/g++.dg/gomp/clause-3.C
+++ b/gcc/testsuite/g++.dg/gomp/clause-3.C
@@ -11,7 +11,7 @@ int t;
void
foo (int x)
{
- char *p;
+ char *pp;
struct S { int i; int j; } s;
char a[32];
double d;
@@ -42,18 +42,18 @@ foo (int x)
;
#pragma omp p firstprivate (bar) // { dg-error "is not a variable" }
;
-#pragma omp p reduction (+:p) // { dg-error "has invalid type for" }
+#pragma omp p reduction (+:pp) // { dg-error "user defined reduction not found for" }
;
-#pragma omp p reduction (*:s) // { dg-error "has invalid type for" }
+#pragma omp p reduction (*:s) // { dg-error "user defined reduction not found for" }
;
#pragma omp p reduction (-:a) // { dg-error "has invalid type for" }
;
d = 0;
#pragma omp p reduction (*:d)
;
-#pragma omp p reduction (|:d) // { dg-error "has invalid type for" }
+#pragma omp p reduction (|:d) // { dg-error "user defined reduction not found for" }
;
-#pragma omp p reduction (&&:d) // { dg-error "has invalid type for" }
+#pragma omp p reduction (&&:d) // { dg-error "user defined reduction not found for" }
;
#pragma omp p copyin (d) // { dg-error "must be 'threadprivate'" }
;
diff --git a/gcc/testsuite/g++.dg/gomp/declare-simd-1.C b/gcc/testsuite/g++.dg/gomp/declare-simd-1.C
new file mode 100644
index 00000000000..e9be161948e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/declare-simd-1.C
@@ -0,0 +1,243 @@
+// Test parsing of #pragma omp declare simd
+// { dg-do compile }
+
+#pragma omp declare simd uniform (a) aligned (b : 8 * sizeof (int)) \
+ linear (c : 4) simdlen (8) notinbranch
+#pragma omp declare simd uniform (c) aligned (b : 4 * sizeof (int)) linear (a \
+ : 4) simdlen (4) inbranch
+int f1 (int a, int *b, int c);
+
+#pragma omp declare simd uniform (a) aligned (b : 8 * sizeof (int)) linear (c : 4) simdlen (8)
+int f2 (int a, int *b, int c)
+{
+ return a + *b + c;
+}
+
+#pragma omp declare simd uniform (c) aligned (b : 4 * sizeof (int)) linear (a : 4) simdlen (4)
+template <typename T>
+T f3 (int a, int *b, T c);
+
+template <>
+int f3 (int, int *, int);
+
+#pragma omp declare simd uniform (c) aligned (b : 4 * sizeof (int)) linear (a : 4) notinbranch simdlen (4)
+template <typename T>
+int f4 (int a, int *b, T c)
+{
+ return a + *b + c;
+}
+
+template <>
+int f4 (int, int *, int);
+
+template <typename T>
+int f5 (int a, int *b, T c);
+
+#pragma omp declare simd uniform (c) aligned (b : 4 * sizeof (int)) linear (a : 4) simdlen (4)
+template <>
+int f5 (int a, int *b, int c);
+
+template <int N>
+int f6 (int a, int *b, int c);
+
+#pragma omp declare simd uniform (c) aligned (b : 4 * sizeof (int)) linear (a : 4) inbranch simdlen (4)
+template <>
+int f6<3> (int a, int *b, int c);
+
+#pragma omp declare simd uniform (a) aligned (b : 8 * sizeof (long long)) linear (c : 4) simdlen (8)
+__extension__
+long long f7 (long long a, long long *b, long long c);
+
+#pragma omp declare simd uniform (a) aligned (b : 8 * sizeof (int)) linear (c : 4) notinbranch simdlen (8)
+extern "C"
+int f8 (int a, int *b, int c);
+
+extern "C"
+{
+ #pragma omp declare simd
+ int f9 (int a, int *b, int c);
+}
+
+namespace N1
+{
+ namespace N2
+ {
+ #pragma omp declare simd simdlen (2) aligned (b : sizeof (long long) * 2)
+ __extension__ long long
+ f10 (long long *b)
+ {
+ return *b;
+ }
+ }
+}
+
+struct A
+{
+ #pragma omp declare simd uniform (a) aligned (b : 8 * sizeof (int)) linear (c : 4) simdlen (8)
+ #pragma omp declare simd uniform (c) aligned (b : 4 * sizeof (int)) linear (a : 4) simdlen (4)
+ int f11 (int a, int *b, int c);
+
+ #pragma omp declare simd
+ template <int N>
+ int f12 (int a, int *b, int c);
+
+ #pragma omp declare simd uniform (a) aligned (b : 8 * sizeof (int)) linear (c : 4) notinbranch simdlen (8)
+ #pragma omp declare simd uniform (c) aligned (b : 4 * sizeof (int)) linear (a : 4) simdlen (4) inbranch
+ static int f13 (int a, int *b, int c);
+
+ #pragma omp declare simd uniform (a) aligned (b : 8 * sizeof (int)) linear (c : 4) simdlen (8)
+ #pragma omp declare simd uniform (c) aligned (b : 4 * sizeof (int)) linear (a : 4) simdlen (4)
+ int f14 (int a, int *b, int c) { return a + *b + c; }
+
+ #pragma omp declare simd
+ template <int N>
+ int f15 (int a, int *b, int c) { return a + *b + c; }
+
+ #pragma omp declare simd uniform (a) aligned (b : 8 * sizeof (int)) linear (c : 4) simdlen (8)
+ #pragma omp declare simd uniform (c) aligned (b : 4 * sizeof (int)) linear (a : 4) simdlen (4)
+ static int f16 (int a, int *b, int c) { return a + *b + c; }
+};
+
+template <>
+int A::f12<2> (int, int *, int);
+
+template <>
+int A::f15<2> (int, int *, int);
+
+template <typename T>
+struct B
+{
+ #pragma omp declare simd uniform (a) aligned (b : 8 * sizeof (int)) linear (c : 4) simdlen (8) notinbranch
+ #pragma omp declare simd uniform (c) aligned (b : 4 * sizeof (int)) linear (a : 4) simdlen (4) inbranch
+ int f17 (int a, int *b, int c);
+
+ #pragma omp declare simd
+ template <int N>
+ int f18 (int a, int *b, int c);
+
+ #pragma omp declare simd uniform (a) aligned (b : 8 * sizeof (int)) linear (c : 4) simdlen (8)
+ #pragma omp declare simd uniform (c) aligned (b : 4 * sizeof (int)) linear (a : 4) simdlen (4)
+ static int f19 (int a, int *b, int c);
+
+ #pragma omp declare simd uniform (a) aligned (b : 8 * sizeof (int)) linear (c : 4) simdlen (8)
+ #pragma omp declare simd uniform (c) aligned (b : 4 * sizeof (int)) linear (a : 4) simdlen (4)
+ int f20 (int a, int *b, int c) { return a + *b + c; }
+
+ #pragma omp declare simd
+ template <int N>
+ int f21 (int a, int *b, int c) { return a + *b + c; }
+
+ #pragma omp declare simd uniform (a) aligned (b : 8 * sizeof (int)) linear (c : 4) simdlen (8)
+ #pragma omp declare simd uniform (c) aligned (b : 4 * sizeof (int)) linear (a : 4) simdlen (4)
+ static int f22 (int a, int *b, int c) { return a + *b + c; }
+
+ template <int N>
+ int f23 (int, int *, int);
+
+ template <int N>
+ static int f24 (int, int *, int);
+
+ template <int N>
+ int f25 (int, int *, int);
+
+ template <int N>
+ static int f26 (int, int *, int);
+};
+
+B <int> b;
+
+template <>
+template <>
+int B<int>::f18<0> (int, int *, int);
+
+template <>
+template <>
+int B<int>::f21<9> (int, int *, int);
+
+#pragma omp declare simd simdlen (8) aligned (b : 8 * sizeof (int)) uniform (a, c)
+template <>
+template <>
+int B<int>::f23<7> (int a, int *b, int c);
+
+#pragma omp declare simd simdlen (4) aligned (b : 8 * sizeof (int)) linear (a, c : 2)
+template <>
+template <>
+int B<int>::f24<-1> (int a, int *b, int c);
+
+#pragma omp declare simd simdlen (8) aligned (b : 8 * sizeof (int)) uniform (a, c)
+template <>
+template <>
+int B<int>::f25<7> (int a, int *b, int c)
+{
+ return a + *b + c;
+}
+
+#pragma omp declare simd simdlen (4) aligned (b : 8 * sizeof (int)) linear (a, c : 2)
+template <>
+template <>
+int B<int>::f26<-1> (int a, int *b, int c)
+{
+ return a + *b + c;
+}
+
+int
+f27 (int x)
+{
+ #pragma omp declare simd simdlen (8) aligned (b : 8 * sizeof (int))
+ extern int f28 (int a, int *b, int c);
+ {
+ x++;
+ #pragma omp declare simd simdlen (4) linear (c)
+ extern int f29 (int a, int *b, int c);
+ }
+ return x;
+}
+
+#pragma omp declare simd simdlen (16)
+int
+f30 (int x)
+{
+ #pragma omp declare simd simdlen (8) aligned (b : 8 * sizeof (int))
+ extern int f31 (int a, int *b, int c);
+ return x;
+}
+
+template <int N>
+struct C
+{
+ #pragma omp declare simd simdlen (N) aligned (b : N * sizeof (int)) linear (c : N) notinbranch
+ int f32 (int a, int *b, int c);
+};
+
+C <2> c;
+
+int
+f33 (int x)
+{
+ if (x)
+ #pragma omp declare simd simdlen (8) aligned (b : 8 * sizeof (int))
+ extern int f34 (int a, int *b, int c);
+ while (x < 10)
+ #pragma omp declare simd simdlen (8) aligned (b : 8 * sizeof (int))
+ extern int f35 (int a, int *b, int c);
+ return x;
+}
+
+#pragma omp declare simd simdlen (N)
+template <int N>
+int f36 (int);
+
+struct D
+{
+ int d;
+ #pragma omp declare simd simdlen (N) linear (a : sizeof (a) + sizeof (d) + sizeof (this) + sizeof (this->d))
+ template <int N>
+ int f37 (int a);
+ int e;
+};
+
+void
+f38 (D &d)
+{
+ d.f37 <12> (6);
+}
diff --git a/gcc/testsuite/g++.dg/gomp/declare-simd-2.C b/gcc/testsuite/g++.dg/gomp/declare-simd-2.C
new file mode 100644
index 00000000000..a6151015bae
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/declare-simd-2.C
@@ -0,0 +1,98 @@
+// Test parsing of #pragma omp declare simd
+// { dg-do compile }
+
+#pragma omp declare simd
+int a; // { dg-error "not immediately followed by function declaration or definition" }
+
+#pragma omp declare simd
+int fn1 (int a), fn2 (int a); // { dg-error "not immediately followed by a single function declaration or definition" }
+
+#pragma omp declare simd
+int b, fn3 (int a); // { dg-error "not immediately followed by function declaration or definition" }
+
+#pragma omp declare simd linear (a)
+int fn4 (int a), c; // { dg-error "not immediately followed by function declaration or definition" }
+
+#pragma omp declare simd
+extern "C" // { dg-error "not immediately followed by function declaration or definition" }
+{
+ int fn5 (int a);
+}
+
+#pragma omp declare simd // { dg-error "not immediately followed by function declaration or definition" }
+namespace N1
+{
+ int fn6 (int a);
+}
+
+#pragma omp declare simd simdlen (4)
+struct A
+{ // { dg-error "not immediately followed by function declaration or definition" }
+ int fn7 (int a);
+};
+
+#pragma omp declare simd
+template <typename T>
+struct B
+{ // { dg-error "not immediately followed by function declaration or definition" }
+ int fn8 (int a);
+};
+
+struct C
+{
+#pragma omp declare simd // { dg-error "not immediately followed by function declaration or definition" }
+ public: // { dg-error "expected unqualified-id before" }
+ int fn9 (int a);
+};
+
+int t;
+
+#pragma omp declare simd
+#pragma omp declare simd
+#pragma omp threadprivate(t) // { dg-error "not immediately followed by function declaration or definition" }
+int fn10 (int a);
+
+#pragma omp declare simd inbranch notinbranch // { dg-error "clause is incompatible with" }
+int fn11 (int);
+
+struct D
+{
+ int d;
+ #pragma omp declare simd simdlen (N) linear (a : sizeof (e) + sizeof (this->e)) // { dg-error "was not declared" }
+ template <int N>
+ int fn12 (int a);
+ int e;
+};
+
+#pragma omp declare simd aligned (a, b, c, d)
+int fn13 (int *a, int b[64], int *&c, int (&d)[64]);
+
+#pragma omp declare simd aligned (a) // { dg-error "neither a pointer nor an array" }
+int fn14 (int a);
+
+#pragma omp declare simd aligned (b) // { dg-error "neither a pointer nor an array" }
+int fn14 (int &b);
+
+#pragma omp declare simd aligned (c) // { dg-error "neither a pointer nor an array" }
+int fn14 (float c);
+
+#pragma omp declare simd aligned (d) // { dg-error "neither a pointer nor an array" }
+int fn14 (double &d);
+
+#pragma omp declare simd aligned (e) // { dg-error "neither a pointer nor an array" }
+int fn14 (D e);
+
+#pragma omp declare simd linear(a:7) uniform(a) // { dg-error "appears more than once" }
+int f15 (int a);
+#pragma omp declare simd linear(a) linear(a) // { dg-error "appears more than once" }
+int f16 (int a);
+#pragma omp declare simd linear(a) linear(a:7) // { dg-error "appears more than once" }
+int f17 (int a);
+#pragma omp declare simd linear(a:6) linear(a:6)// { dg-error "appears more than once" }
+int f18 (int a);
+#pragma omp declare simd uniform(a) uniform(a) // { dg-error "appears more than once" }
+int f19 (int a);
+#pragma omp declare simd uniform(a) aligned (a: 32)
+int f20 (int *a);
+
+// { dg-error "has no member" "" { target *-*-* } 61 }
diff --git a/gcc/testsuite/g++.dg/gomp/depend-1.C b/gcc/testsuite/g++.dg/gomp/depend-1.C
new file mode 100644
index 00000000000..33027de552a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/depend-1.C
@@ -0,0 +1,70 @@
+// { dg-do compile }
+// { dg-options "-fopenmp" }
+
+extern int a[][10], a2[][10];
+int b[10], c[10][2], d[10], e[10], f[10];
+int b2[10], c2[10][2], d2[10], e2[10], f2[10];
+int k[10], l[10], m[10], n[10], o;
+int *p;
+void bar (void);
+int t[10];
+#pragma omp threadprivate (t)
+
+template <int N>
+void
+foo (int g[3][10], int h[4][8], int i[2][10], int j[][9],
+ int g2[3][10], int h2[4][8], int i2[2][10], int j2[][9])
+{
+ #pragma omp task depend(out: t[2:5])
+ ;
+ #pragma omp task depend(inout: k[0.5:]) // { dg-error "low bound \[^\n\r]* of array section does not have integral type" }
+ ;
+ #pragma omp task depend(in: l[:7.5f]) // { dg-error "length \[^\n\r]* of array section does not have integral type" }
+ ;
+ #pragma omp task depend(out: m[p:]) // { dg-error "low bound \[^\n\r]* of array section does not have integral type" }
+ ;
+ #pragma omp task depend(inout: n[:p]) // { dg-error "length \[^\n\r]* of array section does not have integral type" }
+ ;
+ #pragma omp task depend(in: o[2:5]) // { dg-error "does not have pointer or array type" }
+ ;
+ #pragma omp task depend(out: a[:][2:4]) // { dg-error "array type length expression must be specified" }
+ ;
+ #pragma omp task depend(in: d[11:]) // { dg-error "low bound \[^\n\r]* above array section size" }
+ ;
+ #pragma omp task depend(out: e[:11]) // { dg-error "length \[^\n\r]* above array section size" }
+ ;
+ #pragma omp task depend(out: f[1:10]) // { dg-error "high bound \[^\n\r]* above array section size" }
+ ;
+ #pragma omp task depend(in: g[:][2:4]) // { dg-error "for pointer type length expression must be specified" }
+ ;
+ #pragma omp task depend(out: i[:1][11:]) // { dg-error "low bound \[^\n\r]* above array section size" }
+ ;
+ #pragma omp task depend(in: j[3:4][:10]) // { dg-error "length \[^\n\r]* above array section size" }
+ ;
+ #pragma omp task depend(out: j[30:10][5:5]) // { dg-error "high bound \[^\n\r]* above array section size" }
+ ;
+ #pragma omp task depend(out: a2[:3][2:4])
+ ;
+ #pragma omp task depend(inout: b2[0:])
+ ;
+ #pragma omp task depend(inout: c2[:3][1:1])
+ ;
+ #pragma omp task depend(in: d2[9:])
+ ;
+ #pragma omp task depend(out: e2[:10])
+ ;
+ #pragma omp task depend(out: f2[1:9])
+ ;
+ #pragma omp task depend(in: g2[:2][2:4])
+ ;
+ #pragma omp task depend(in: h2[2:2][0:])
+ ;
+ #pragma omp task depend(inout: h2[:1][:3])
+ ;
+ #pragma omp task depend(out: i2[:1][9:])
+ ;
+ #pragma omp task depend(in: j2[3:4][:9])
+ ;
+ #pragma omp task depend(out: j2[30:10][5:4])
+ ;
+}
diff --git a/gcc/testsuite/g++.dg/gomp/depend-2.C b/gcc/testsuite/g++.dg/gomp/depend-2.C
new file mode 100644
index 00000000000..c3f19658c5a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/depend-2.C
@@ -0,0 +1,87 @@
+// { dg-do compile }
+// { dg-options "-fopenmp" }
+
+extern int a[][10], a2[][10];
+int b[10], c[10][2], d[10], e[10], f[10];
+int b2[10], c2[10][2], d2[10], e2[10], f2[10];
+int k[10], l[10], m[10], n[10], o;
+int *p;
+void bar (void);
+int t[10];
+#pragma omp threadprivate (t)
+
+template <int N>
+void
+foo (int g[3][10], int h[4][8], int i[2][10], int j[][9],
+ int g2[3][10], int h2[4][8], int i2[2][10], int j2[][9])
+{
+ #pragma omp task depend(in: bar[2:5]) // { dg-error "is not a variable" }
+ ;
+ #pragma omp task depend(out: t[2:5])
+ ;
+ #pragma omp task depend(inout: k[0.5:]) // { dg-error "low bound \[^\n\r]* of array section does not have integral type" }
+ ;
+ #pragma omp task depend(in: l[:7.5f]) // { dg-error "length \[^\n\r]* of array section does not have integral type" }
+ ;
+ #pragma omp task depend(out: m[p:]) // { dg-error "low bound \[^\n\r]* of array section does not have integral type" }
+ ;
+ #pragma omp task depend(inout: n[:p]) // { dg-error "length \[^\n\r]* of array section does not have integral type" }
+ ;
+ #pragma omp task depend(in: o[2:5]) // { dg-error "does not have pointer or array type" }
+ ;
+ #pragma omp task depend(out: a[:][2:4]) // { dg-error "array type length expression must be specified" }
+ ;
+ #pragma omp task depend(inout: b[-1:]) // { dg-error "negative low bound in array section" }
+ ;
+ #pragma omp task depend(inout: c[:-3][1:1]) // { dg-error "negative length in array section" }
+ ;
+ #pragma omp task depend(in: d[11:]) // { dg-error "low bound \[^\n\r]* above array section size" }
+ ;
+ #pragma omp task depend(out: e[:11]) // { dg-error "length \[^\n\r]* above array section size" }
+ ;
+ #pragma omp task depend(out: f[1:10]) // { dg-error "high bound \[^\n\r]* above array section size" }
+ ;
+ #pragma omp task depend(in: g[:][2:4]) // { dg-error "for pointer type length expression must be specified" }
+ ;
+ #pragma omp task depend(in: h[2:2][-1:]) // { dg-error "negative low bound in array section" }
+ ;
+ #pragma omp task depend(inout: h[:1][:-3]) // { dg-error "negative length in array section" }
+ ;
+ #pragma omp task depend(out: i[:1][11:]) // { dg-error "low bound \[^\n\r]* above array section size" }
+ ;
+ #pragma omp task depend(in: j[3:4][:10]) // { dg-error "length \[^\n\r]* above array section size" }
+ ;
+ #pragma omp task depend(out: j[30:10][5:5]) // { dg-error "high bound \[^\n\r]* above array section size" }
+ ;
+ #pragma omp task depend(out: a2[:3][2:4])
+ ;
+ #pragma omp task depend(inout: b2[0:])
+ ;
+ #pragma omp task depend(inout: c2[:3][1:1])
+ ;
+ #pragma omp task depend(in: d2[9:])
+ ;
+ #pragma omp task depend(out: e2[:10])
+ ;
+ #pragma omp task depend(out: f2[1:9])
+ ;
+ #pragma omp task depend(in: g2[:2][2:4])
+ ;
+ #pragma omp task depend(in: h2[2:2][0:])
+ ;
+ #pragma omp task depend(inout: h2[:1][:3])
+ ;
+ #pragma omp task depend(out: i2[:1][9:])
+ ;
+ #pragma omp task depend(in: j2[3:4][:9])
+ ;
+ #pragma omp task depend(out: j2[30:10][5:4])
+ ;
+}
+
+void
+baz (int g[3][10], int h[4][8], int i[2][10], int j[][9],
+ int g2[3][10], int h2[4][8], int i2[2][10], int j2[][9])
+{
+ foo<0> (g, h, i, j, g2, h2, i2, j2);
+}
diff --git a/gcc/testsuite/g++.dg/gomp/gomp.exp b/gcc/testsuite/g++.dg/gomp/gomp.exp
index d0199cb36f8..e783bdb0550 100644
--- a/gcc/testsuite/g++.dg/gomp/gomp.exp
+++ b/gcc/testsuite/g++.dg/gomp/gomp.exp
@@ -27,7 +27,9 @@ if ![check_effective_target_fopenmp] {
dg-init
# Main loop.
-g++-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.C $srcdir/c-c++-common/gomp/*.c]] "-fopenmp"
+g++-dg-runtest [lsort [concat \
+ [find $srcdir/$subdir *.C] \
+ [find $srcdir/c-c++-common/gomp *.c]]] "-fopenmp"
# All done.
dg-finish
diff --git a/gcc/testsuite/g++.dg/gomp/openmp-simd-1.C b/gcc/testsuite/g++.dg/gomp/openmp-simd-1.C
new file mode 100644
index 00000000000..fedb186fedf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/openmp-simd-1.C
@@ -0,0 +1,46 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp-simd -fdump-tree-original" } */
+
+#pragma omp declare simd
+float bar(float b) {
+ return b*b;
+}
+
+void foo(int n, float *a, float *b)
+{
+ int i;
+#pragma omp simd
+ for (i = 0; i < n ; i++)
+ a[i] = b[i];
+#pragma omp for simd
+ for (i = 0; i < n ; i++)
+ a[i] = b[i];
+#pragma omp distribute simd
+ for (i = 0; i < n ; i++)
+ a[i] = b[i];
+#pragma omp distribute parallel for simd
+ for (i = 0; i < n ; i++)
+ a[i] = b[i];
+#pragma omp parallel for simd
+ for (i = 0; i < n ; i++)
+ a[i] = b[i];
+#pragma omp teams distribute simd
+ for (i = 0; i < n ; i++)
+ a[i] = b[i];
+#pragma omp target teams distribute simd
+ for (i = 0; i < n ; i++)
+ a[i] = b[i];
+#pragma omp teams distribute parallel for simd
+ for (i = 0; i < n ; i++)
+ a[i] = b[i];
+#pragma omp target teams distribute parallel for simd
+ for (i = 0; i < n ; i++)
+ a[i] = b[i];
+}
+
+/* { dg-final { scan-tree-dump-times "pragma omp simd" 9 "original" } } */
+/* { dg-final { scan-tree-dump-not "omp for" "original" } } */
+/* { dg-final { scan-tree-dump-not "omp distribute" "original" } } */
+/* { dg-final { scan-tree-dump-not "omp teams" "original" } } */
+/* { dg-final { scan-tree-dump-not "omp target" "original" } } */
+/* { dg-final { scan-tree-dump-not "omp parallel" "original" } } */
diff --git a/gcc/testsuite/g++.dg/gomp/openmp-simd-2.C b/gcc/testsuite/g++.dg/gomp/openmp-simd-2.C
new file mode 100644
index 00000000000..e31c1ebecf9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/openmp-simd-2.C
@@ -0,0 +1,44 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp-simd -fdump-tree-original" } */
+
+extern void abort ();
+int a[1024] __attribute__((aligned (32))) = { 1 };
+struct S { int s; };
+#pragma omp declare reduction (+:struct S:omp_out.s += omp_in.s)
+#pragma omp declare reduction (foo:struct S:omp_out.s += omp_in.s)
+#pragma omp declare reduction (foo:int:omp_out += omp_in)
+
+__attribute__((noinline, noclone)) int
+foo (void)
+{
+ int i, u = 0;
+ struct S s, t;
+ s.s = 0; t.s = 0;
+ #pragma omp simd aligned(a : 32) reduction(+:s) reduction(foo:t, u)
+ for (i = 0; i < 1024; i++)
+ {
+ int x = a[i];
+ s.s += x;
+ t.s += x;
+ u += x;
+ }
+ if (t.s != s.s || u != s.s)
+ abort ();
+ return s.s;
+}
+
+
+void bar(int n, float *a, float *b)
+{
+ int i;
+#pragma omp parallel for simd num_threads(4) safelen(64)
+ for (i = 0; i < n ; i++)
+ a[i] = b[i];
+}
+
+/* { dg-final { scan-tree-dump-times "Function void omp declare reduction operator\\+" 1 "original" } } */
+/* { dg-final { scan-tree-dump-times "Function void omp declare reduction foo" 2 "original" } } */
+/* { dg-final { scan-tree-dump-times "pragma omp simd reduction\\(u\\) reduction\\(t\\) reduction\\(\\+:s\\) aligned\\(a:32\\)" 1 "original" } } */
+/* { dg-final { scan-tree-dump-times "pragma omp simd safelen\\(64\\)" 1 "original" } } */
+/* { dg-final { scan-tree-dump-not "omp parallel" "original" } } */
+/* { dg-final { scan-tree-dump-not "omp for" "original" } } */
diff --git a/gcc/testsuite/g++.dg/gomp/simd-1.C b/gcc/testsuite/g++.dg/gomp/simd-1.C
new file mode 100644
index 00000000000..c9c2e73bb40
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/simd-1.C
@@ -0,0 +1,31 @@
+// { dg-do compile }
+// { dg-options "-fopenmp" }
+
+extern int a[1024];
+int (&b)[1024] = a;
+
+struct S { int s; } s, &t = s;
+
+void
+f1 (int &x, float &f, int *&p)
+{
+ int i;
+ #pragma omp simd aligned(x : 32) // { dg-error "neither a pointer nor an array" }
+ for (i = 0; i < 1024; i++)
+ a[i]++;
+ #pragma omp simd aligned(f) // { dg-error "neither a pointer nor an array" }
+ for (i = 0; i < 1024; i++)
+ a[i]++;
+ #pragma omp simd aligned(t : 16) // { dg-error "neither a pointer nor an array" }
+ for (i = 0; i < 1024; i++)
+ a[i]++;
+ #pragma omp simd aligned(a : 8)
+ for (i = 0; i < 1024; i++)
+ a[i]++;
+ #pragma omp simd aligned(b : 8)
+ for (i = 0; i < 1024; i++)
+ b[i]++;
+ #pragma omp simd aligned(p : 8)
+ for (i = 0; i < 1024; i++)
+ a[i]++;
+}
diff --git a/gcc/testsuite/g++.dg/gomp/target-1.C b/gcc/testsuite/g++.dg/gomp/target-1.C
new file mode 100644
index 00000000000..b6ed4f89cd8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/target-1.C
@@ -0,0 +1,32 @@
+// { dg-do compile }
+
+void
+foo (int x)
+{
+ bad1: // { dg-error "jump to label" }
+ #pragma omp target
+ goto bad1; // { dg-error "from here|exits OpenMP" }
+
+ goto bad2; // { dg-error "from here" }
+ #pragma omp target
+ {
+ bad2: ; // { dg-error "jump to label|enters OpenMP" }
+ }
+
+ #pragma omp target
+ {
+ int i;
+ goto ok1;
+ for (i = 0; i < 10; ++i)
+ { ok1: break; }
+ }
+
+ switch (x)
+ {
+ #pragma omp target
+ { case 0:; } // { dg-error "jump|enters" }
+ }
+}
+
+// { dg-error "invalid branch to/from an OpenMP structured block" "" { target *-*-* } 8 }
+// { dg-error "invalid entry to OpenMP structured block" "" { target *-*-* } 10 }
diff --git a/gcc/testsuite/g++.dg/gomp/target-2.C b/gcc/testsuite/g++.dg/gomp/target-2.C
new file mode 100644
index 00000000000..6a14f53cff6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/target-2.C
@@ -0,0 +1,32 @@
+// { dg-do compile }
+
+void
+foo (int x, int y)
+{
+ bad1: // { dg-error "jump to label" }
+ #pragma omp target data map(tofrom: y)
+ goto bad1; // { dg-error "from here|exits OpenMP" }
+
+ goto bad2; // { dg-error "from here" }
+ #pragma omp target data map(tofrom: y)
+ {
+ bad2: ; // { dg-error "jump to label|enters OpenMP" }
+ }
+
+ #pragma omp target data map(tofrom: y)
+ {
+ int i;
+ goto ok1;
+ for (i = 0; i < 10; ++i)
+ { ok1: break; }
+ }
+
+ switch (x)
+ {
+ #pragma omp target data map(tofrom: y)
+ { case 0:; } // { dg-error "jump|enters" }
+ }
+}
+
+// { dg-error "invalid branch to/from an OpenMP structured block" "" { target *-*-* } 8 }
+// { dg-error "invalid entry to OpenMP structured block" "" { target *-*-* } 10 }
diff --git a/gcc/testsuite/g++.dg/gomp/taskgroup-1.C b/gcc/testsuite/g++.dg/gomp/taskgroup-1.C
new file mode 100644
index 00000000000..dcab0bb6466
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/taskgroup-1.C
@@ -0,0 +1,32 @@
+// { dg-do compile }
+
+void
+foo (int x)
+{
+ bad1: // { dg-error "jump to label" }
+ #pragma omp taskgroup
+ goto bad1; // { dg-error "from here|exits OpenMP" }
+
+ goto bad2; // { dg-error "from here" }
+ #pragma omp taskgroup
+ {
+ bad2: ; // { dg-error "jump to label|enters OpenMP" }
+ }
+
+ #pragma omp taskgroup
+ {
+ int i;
+ goto ok1;
+ for (i = 0; i < 10; ++i)
+ { ok1: break; }
+ }
+
+ switch (x)
+ {
+ #pragma omp taskgroup
+ { case 0:; } // { dg-error "jump|enters" }
+ }
+}
+
+// { dg-error "invalid branch to/from an OpenMP structured block" "" { target *-*-* } 8 }
+// { dg-error "invalid entry to OpenMP structured block" "" { target *-*-* } 10 }
diff --git a/gcc/testsuite/g++.dg/gomp/teams-1.C b/gcc/testsuite/g++.dg/gomp/teams-1.C
new file mode 100644
index 00000000000..ce40b55ca15
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/teams-1.C
@@ -0,0 +1,66 @@
+// { dg-do compile }
+
+void
+foo (int x)
+{
+ bad1: // { dg-error "jump to label" }
+ #pragma omp target teams
+ goto bad1; // { dg-error "from here|exits OpenMP" }
+
+ goto bad2; // { dg-error "from here" }
+ #pragma omp target teams
+ {
+ bad2: ; // { dg-error "jump to label|enters OpenMP" }
+ }
+
+ #pragma omp target teams
+ {
+ int i;
+ goto ok1;
+ for (i = 0; i < 10; ++i)
+ { ok1: break; }
+ }
+
+ switch (x)
+ {
+ #pragma omp target teams
+ { case 0:; } // { dg-error "jump|enters" }
+ }
+}
+
+void
+bar (int x)
+{
+ bad1: // { dg-error "jump to label" }
+ #pragma omp target
+ #pragma omp teams
+ goto bad1; // { dg-error "from here|exits OpenMP" }
+
+ goto bad2; // { dg-error "from here" }
+ #pragma omp target
+ #pragma omp teams
+ {
+ bad2: ; // { dg-error "jump to label|enters OpenMP" }
+ }
+
+ #pragma omp target
+ #pragma omp teams
+ {
+ int i;
+ goto ok1;
+ for (i = 0; i < 10; ++i)
+ { ok1: break; }
+ }
+
+ switch (x)
+ {
+ #pragma omp target
+ #pragma omp teams
+ { case 0:; } // { dg-error "jump|enters" }
+ }
+}
+
+// { dg-error "invalid branch to/from an OpenMP structured block" "" { target *-*-* } 8 }
+// { dg-error "invalid entry to OpenMP structured block" "" { target *-*-* } 10 }
+// { dg-error "invalid branch to/from an OpenMP structured block" "" { target *-*-* } 37 }
+// { dg-error "invalid entry to OpenMP structured block" "" { target *-*-* } 39 }
diff --git a/gcc/testsuite/g++.dg/gomp/udr-1.C b/gcc/testsuite/g++.dg/gomp/udr-1.C
new file mode 100644
index 00000000000..10c1c8dab92
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/udr-1.C
@@ -0,0 +1,119 @@
+// { dg-do compile }
+// { dg-options "-fopenmp" }
+
+namespace N1
+{
+ #pragma omp declare reduction (| : long int : omp_out |= omp_in) // { dg-error "predeclared arithmetic type" }
+ #pragma omp declare reduction (+ : char : omp_out += omp_in) // { dg-error "predeclared arithmetic type" }
+ typedef short T;
+ #pragma omp declare reduction (min : T : omp_out += omp_in) // { dg-error "predeclared arithmetic type" }
+ #pragma omp declare reduction (* : _Complex double : omp_out *= omp_in)// { dg-error "predeclared arithmetic type" }
+}
+namespace N2
+{
+ template <typename T1, typename T2, typename T3, typename T4>
+ struct S
+ {
+ #pragma omp declare reduction (| : T1 : omp_out |= omp_in) // { dg-error "predeclared arithmetic type" }
+ #pragma omp declare reduction (+ : T2 : omp_out += omp_in) // { dg-error "predeclared arithmetic type" }
+ typedef T3 T;
+ #pragma omp declare reduction (min : T : omp_out += omp_in) // { dg-error "predeclared arithmetic type" }
+ #pragma omp declare reduction (* : T4 : omp_out *= omp_in) // { dg-error "predeclared arithmetic type" }
+ };
+ S<long int, char, short, _Complex double> s;
+ template <typename T1, typename T2, typename T3, typename T4>
+ int foo ()
+ {
+ #pragma omp declare reduction (| : T1 : omp_out |= omp_in) // { dg-error "predeclared arithmetic type" }
+ #pragma omp declare reduction (+ : T2 : omp_out += omp_in) // { dg-error "predeclared arithmetic type" }
+ typedef T3 T;
+ #pragma omp declare reduction (min : T : omp_out += omp_in) // { dg-error "predeclared arithmetic type" }
+ #pragma omp declare reduction (* : T4 : omp_out *= omp_in) // { dg-error "predeclared arithmetic type" }
+ return 0;
+ }
+ int x = foo <long int, char, short, _Complex double> ();
+}
+namespace N3
+{
+ void bar ();
+ #pragma omp declare reduction (| : __typeof (bar) : omp_out |= omp_in)// { dg-error "function or array type" }
+ #pragma omp declare reduction (+ : char () : omp_out += omp_in) // { dg-error "function or array type" }
+ typedef short T;
+ #pragma omp declare reduction (min : T[2] : omp_out += omp_in) // { dg-error "function or array type" }
+ #pragma omp declare reduction (baz : char & : omp_out *= omp_in) // { dg-error "reference type" }
+}
+namespace N4
+{
+ void bar ();
+ template <typename T1, typename T2, typename T3, typename T4>
+ struct S
+ {
+ #pragma omp declare reduction (| : T1 : omp_out |= omp_in) // { dg-error "function or array type" }
+ #pragma omp declare reduction (+ : T2 : omp_out += omp_in) // { dg-error "function or array type" }
+ typedef T3 T;
+ #pragma omp declare reduction (min : T : omp_out += omp_in) // { dg-error "function or array type" }
+ #pragma omp declare reduction (baz : T4 : omp_out *= omp_in) // { dg-error "function or array type" }
+ };
+ S<__typeof (bar), char (), short [3], char []> s;
+ template <typename T1, typename T2, typename T3, typename T4>
+ int foo ()
+ {
+ #pragma omp declare reduction (| : T1 : omp_out |= omp_in) // { dg-error "function or array type" }
+ #pragma omp declare reduction (+ : T2 : omp_out += omp_in) // { dg-error "function or array type" }
+ typedef T3 T;
+ #pragma omp declare reduction (min : T : omp_out += omp_in) // { dg-error "function or array type" }
+ #pragma omp declare reduction (baz : T4 : omp_out *= omp_in) // { dg-error "function or array type" }
+ return 0;
+ }
+ int x = foo <__typeof (bar), char (), short[], char [2]> ();
+}
+namespace N5
+{
+ template <typename T>
+ struct S
+ {
+ #pragma omp declare reduction (baz : T : omp_out *= omp_in) // { dg-error "reference type" }
+ };
+ S<char &> s;
+ template <typename T>
+ int foo ()
+ {
+ #pragma omp declare reduction (baz : T : omp_out *= omp_in) // { dg-error "reference type" }
+ return 0;
+ }
+ int x = foo <char &> ();
+}
+namespace N6
+{
+ struct A { int a; A () : a (0) {} };
+ #pragma omp declare reduction (| : const A : omp_out.a |= omp_in.a) // { dg-error "const, volatile or __restrict" }
+ #pragma omp declare reduction (+ : __const A : omp_out.a += omp_in.a) // { dg-error "const, volatile or __restrict" }
+ typedef volatile A T;
+ #pragma omp declare reduction (min : T : omp_out.a += omp_in.a) // { dg-error "const, volatile or __restrict" }
+ #pragma omp declare reduction (* : A *__restrict : omp_out->a *= omp_in->a)// { dg-error "const, volatile or __restrict" }
+}
+namespace N7
+{
+ struct A { int a; A () : a (0) {} };
+ template <typename T1, typename T2, typename T3, typename T4>
+ struct S
+ {
+ #pragma omp declare reduction (| : T1 : omp_out |= omp_in) // { dg-error "const, volatile or __restrict" }
+ #pragma omp declare reduction (+ : T2 : omp_out += omp_in) // { dg-error "const, volatile or __restrict" }
+ typedef T3 T;
+ #pragma omp declare reduction (min : T : omp_out += omp_in) // { dg-error "const, volatile or __restrict" }
+ #pragma omp declare reduction (* : T4 : omp_out *= omp_in) // { dg-error "const, volatile or __restrict" }
+ };
+ S<const A, __const A, volatile A, A *__restrict> s;
+ template <typename T1, typename T2, typename T3, typename T4>
+ int foo ()
+ {
+ #pragma omp declare reduction (| : T1 : omp_out |= omp_in) // { dg-error "const, volatile or __restrict" }
+ #pragma omp declare reduction (+ : T2 : omp_out += omp_in) // { dg-error "const, volatile or __restrict" }
+ typedef T3 T;
+ #pragma omp declare reduction (min : T : omp_out += omp_in) // { dg-error "const, volatile or __restrict" }
+ #pragma omp declare reduction (* : T4 : omp_out *= omp_in) // { dg-error "const, volatile or __restrict" }
+ return 0;
+ }
+ int x = foo <const A, __const A, volatile A, A *__restrict> ();
+}
diff --git a/gcc/testsuite/g++.dg/gomp/udr-2.C b/gcc/testsuite/g++.dg/gomp/udr-2.C
new file mode 100644
index 00000000000..48451c4fc0a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/udr-2.C
@@ -0,0 +1,119 @@
+// { dg-do compile }
+// { dg-options "-fopenmp" }
+
+struct W { int w; W () : w (0) {} W (int x) : w (x) {} };
+namespace N1
+{
+ int v;
+ #pragma omp declare reduction (foo : long int : omp_out |= v) // { dg-error "combiner refers to variable" }
+ #pragma omp declare reduction (foo : char : omp_out = v) // { dg-error "combiner refers to variable" }
+ typedef short T;
+ #pragma omp declare reduction (foo : T : omp_out += N1::v) // { dg-error "combiner refers to variable" }
+ #pragma omp declare reduction (foo : int : v *= omp_in) // { dg-error "combiner refers to variable" }
+ #pragma omp declare reduction (foo : W : omp_out.w *= omp_in.w + v) // { dg-error "combiner refers to variable" }
+}
+namespace N2
+{
+ int v;
+ template <typename T1, typename T2, typename T3, typename T4, typename T5>
+ struct S
+ {
+ #pragma omp declare reduction (foo : T1 : omp_out |= v) // { dg-error "combiner refers to variable" }
+ #pragma omp declare reduction (foo : T2 : omp_out = v) // { dg-error "combiner refers to variable" }
+ typedef T3 T;
+ #pragma omp declare reduction (foo : T : omp_out += N1::v) // { dg-error "combiner refers to variable" }
+ #pragma omp declare reduction (foo : T4 : v *= omp_in) // { dg-error "combiner refers to variable" }
+ #pragma omp declare reduction (foo : T5 : omp_out.w *= omp_in.w + v) // { dg-error "combiner refers to variable" }
+ };
+ S<long int, char, short, _Complex double, W> s;
+ template <typename T1, typename T2, typename T3, typename T4, typename T5>
+ int foo ()
+ {
+ #pragma omp declare reduction (foo : T1 : omp_out |= v) // { dg-error "combiner refers to variable" }
+ #pragma omp declare reduction (foo : T2 : omp_out = v) // { dg-error "combiner refers to variable" }
+ typedef T3 T;
+ #pragma omp declare reduction (foo : T : omp_out += N1::v) // { dg-error "combiner refers to variable" }
+ #pragma omp declare reduction (foo : T4 : v *= omp_in) // { dg-error "combiner refers to variable" }
+ #pragma omp declare reduction (foo : T5 : omp_out.w *= omp_in.w + v) // { dg-error "combiner refers to variable" }
+ return 0;
+ }
+ int x = foo <long int, char, short, _Complex double, W> ();
+}
+namespace N3
+{
+ int v;
+ #pragma omp declare reduction (foo : long int : omp_out |= omp_in) initializer (omp_priv = v) // { dg-error "initializer refers to variable" }
+ #pragma omp declare reduction (foo : char : omp_out += omp_in) initializer (omp_priv ((char) N3::v)) // { dg-error "initializer refers to variable" }
+ typedef short T;
+ #pragma omp declare reduction (foo : T : omp_out += omp_in) initializer (omp_priv = (short) v) // { dg-error "initializer refers to variable" }
+ #pragma omp declare reduction (foo : _Complex double : omp_out *= omp_in) initializer (omp_priv (v)) // { dg-error "initializer refers to variable" }
+ #pragma omp declare reduction (foo : W : omp_out.w *= omp_in.w) initializer (omp_priv (N3::v)) // { dg-error "initializer refers to variable" }
+}
+namespace N4
+{
+ int v;
+ template <typename T1, typename T2, typename T3, typename T4, typename T5>
+ struct S
+ {
+ #pragma omp declare reduction (foo : T1 : omp_out |= omp_in) initializer (omp_priv = v) // { dg-error "initializer refers to variable" }
+ #pragma omp declare reduction (foo : T2 : omp_out += omp_in) initializer (omp_priv ((char) N3::v)) // { dg-error "initializer refers to variable" }
+ typedef T3 T;
+ #pragma omp declare reduction (foo : T : omp_out += omp_in) initializer (omp_priv = (short) v) // { dg-error "initializer refers to variable" }
+ #pragma omp declare reduction (foo : T4 : omp_out *= omp_in) initializer (omp_priv (v)) // { dg-error "initializer refers to variable" }
+ #pragma omp declare reduction (foo : T5 : omp_out.w *= omp_in.w) initializer (omp_priv (N3::v)) // { dg-error "initializer refers to variable" }
+ };
+ S<long int, char, short, _Complex double, W> s;
+ template <typename T1, typename T2, typename T3, typename T4, typename T5>
+ int foo ()
+ {
+ #pragma omp declare reduction (foo : T1 : omp_out |= omp_in) initializer (omp_priv = v) // { dg-error "initializer refers to variable" }
+ #pragma omp declare reduction (foo : T2 : omp_out += omp_in) initializer (omp_priv ((char) N3::v)) // { dg-error "initializer refers to variable" }
+ typedef T3 T;
+ #pragma omp declare reduction (foo : T : omp_out += omp_in) initializer (omp_priv = (short) v) // { dg-error "initializer refers to variable" }
+ #pragma omp declare reduction (foo : T4 : omp_out *= omp_in) initializer (omp_priv (v)) // { dg-error "initializer refers to variable" }
+ #pragma omp declare reduction (foo : T5 : omp_out.w *= omp_in.w) initializer (omp_priv (N3::v)) // { dg-error "initializer refers to variable" }
+ return 0;
+ }
+ int x = foo <long int, char, short, _Complex double, W> ();
+}
+template <typename T>
+void init (T &, int &);
+template <typename T>
+void initializer (T, int &);
+namespace N5
+{
+ int v;
+ #pragma omp declare reduction (foo : long int : omp_out |= omp_in) initializer (init (omp_priv, v)) // { dg-error "initializer refers to variable" }
+ #pragma omp declare reduction (foo : char : omp_out += omp_in) initializer (initializer (&omp_priv, N3::v)) // { dg-error "initializer refers to variable" }
+ typedef short T;
+ #pragma omp declare reduction (foo : T : omp_out += omp_in) initializer (init (omp_priv, v)) // { dg-error "initializer refers to variable" }
+ #pragma omp declare reduction (foo : _Complex double : omp_out *= omp_in) initializer (initializer (&omp_priv, v)) // { dg-error "initializer refers to variable" }
+ #pragma omp declare reduction (foo : W : omp_out.w *= omp_in.w) initializer (init (omp_priv, N3::v)) // { dg-error "initializer refers to variable" }
+}
+namespace N6
+{
+ int v;
+ template <typename T1, typename T2, typename T3, typename T4, typename T5>
+ struct S
+ {
+ #pragma omp declare reduction (foo : T1 : omp_out |= omp_in) initializer (initializer (&omp_priv, v)) // { dg-error "initializer refers to variable" }
+ #pragma omp declare reduction (foo : T2 : omp_out += omp_in) initializer (init (omp_priv, N3::v)) // { dg-error "initializer refers to variable" }
+ typedef T3 T;
+ #pragma omp declare reduction (foo : T : omp_out += omp_in) initializer (init (omp_priv, v)) // { dg-error "initializer refers to variable" }
+ #pragma omp declare reduction (foo : T4 : omp_out *= omp_in) initializer (init (omp_priv, v)) // { dg-error "initializer refers to variable" }
+ #pragma omp declare reduction (foo : T5 : omp_out.w *= omp_in.w) initializer (initializer (&omp_priv, N3::v)) // { dg-error "initializer refers to variable" }
+ };
+ S<long int, char, short, _Complex double, W> s;
+ template <typename T1, typename T2, typename T3, typename T4, typename T5>
+ int foo ()
+ {
+ #pragma omp declare reduction (foo : T1 : omp_out |= omp_in) initializer (init (omp_priv, v)) // { dg-error "initializer refers to variable" }
+ #pragma omp declare reduction (foo : T2 : omp_out += omp_in) initializer (init (omp_priv, N3::v)) // { dg-error "initializer refers to variable" }
+ typedef T3 T;
+ #pragma omp declare reduction (foo : T : omp_out += omp_in) initializer (initializer (&omp_priv, v)) // { dg-error "initializer refers to variable" }
+ #pragma omp declare reduction (foo : T4 : omp_out *= omp_in) initializer (init (omp_priv, v)) // { dg-error "initializer refers to variable" }
+ #pragma omp declare reduction (foo : T5 : omp_out.w *= omp_in.w) initializer (initializer (omp_priv, N3::v)) // { dg-error "initializer refers to variable" }
+ return 0;
+ }
+ int x = foo <long int, char, short, _Complex double, W> ();
+}
diff --git a/gcc/testsuite/g++.dg/gomp/udr-3.C b/gcc/testsuite/g++.dg/gomp/udr-3.C
new file mode 100644
index 00000000000..a560fc1b537
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/udr-3.C
@@ -0,0 +1,191 @@
+// { dg-do compile }
+// { dg-options "-fopenmp" }
+
+struct S { int s; S () : s (0) {} S (int x) : s (x) {} ~S () {} };
+struct T { int t; T () : t (0) {} T (int x) : t (x) {} ~T () {} };
+
+#pragma omp declare reduction (+: ::S: omp_out.s += omp_in.s)
+#pragma omp declare reduction (*: S: omp_out.s *= omp_in.s) \
+ initializer (omp_priv (1))
+#pragma omp declare reduction (foo: S: omp_out.s += omp_in.s)
+
+void
+f1 ()
+{
+ S s, s2;
+ T t;
+ #pragma omp declare reduction (+: T: omp_out.t += omp_in.t)
+ #pragma omp parallel reduction (+: t) reduction (foo: s) reduction (*: s2)
+ s.s = 1, t.t = 1, s2.s = 2;
+ #pragma omp parallel reduction (::operator +: s)
+ s.s = 1;
+ #pragma omp parallel reduction (+: s)
+ s.s = 1;
+}
+
+template <int N>
+int
+f2 ()
+{
+ S s, s2;
+ T t;
+ #pragma omp declare reduction (+: T: omp_out.t += omp_in.t)
+ #pragma omp parallel reduction (+: t) reduction (foo: s) reduction (*: s2)
+ s.s = 1, t.t = 1, s2.s = 2;
+ #pragma omp parallel reduction (::operator +: s)
+ s.s = 1;
+ #pragma omp parallel reduction (+: s)
+ s.s = 1;
+ return 0;
+}
+
+int x = f2<0> ();
+
+void bar (S &);
+
+void
+f3 ()
+{
+ #pragma omp declare reduction (foo: S: omp_out.s += omp_in.s) initializer (bar (omp_priv))
+ #pragma omp declare reduction (bar: S: omp_out.s += omp_in.s) initializer (bar (omp_orig)) // { dg-error "one of the initializer call arguments should be" }
+}
+
+template <typename T>
+int
+f4 ()
+{
+ #pragma omp declare reduction (foo: T: omp_out.s += omp_in.s) initializer (bar (omp_priv))
+ #pragma omp declare reduction (bar: T: omp_out.s += omp_in.s) initializer (bar (omp_orig)) // { dg-error "one of the initializer call arguments should be" }
+ return 0;
+}
+
+int y = f4 <S> ();
+
+namespace N1
+{
+ #pragma omp declare reduction (+: ::S: omp_out.s *= omp_in.s) // { dg-error "previous" }
+ #pragma omp declare reduction (+: S: omp_out.s += omp_in.s) // { dg-error "redeclaration of" }
+ void
+ f5 ()
+ {
+ #pragma omp declare reduction (f5: S: omp_out.s *= omp_in.s) // { dg-error "previous" }
+ #pragma omp declare reduction (f5: ::S: omp_out.s += omp_in.s) // { dg-error "redeclaration of" }
+ }
+}
+
+namespace N2
+{
+ struct U
+ {
+ #pragma omp declare reduction (bar: S: omp_out.s *= omp_in.s) // { dg-error "with" }
+ #pragma omp declare reduction (bar: S: omp_out.s += omp_in.s) // { dg-error "cannot be overloaded" }
+ };
+}
+
+namespace N3
+{
+ #pragma omp declare reduction (+: ::S: omp_out.s *= omp_in.s) // { dg-error "previous" }
+ #pragma omp declare reduction (+: T: omp_out.t += omp_in.t)
+ #pragma omp declare reduction (+: S: omp_out.s += omp_in.s) // { dg-error "redeclaration of" }
+ #pragma omp declare reduction (n3: long: omp_out += omp_in) // { dg-error "previous" }
+ #pragma omp declare reduction (n3: long int: omp_out += omp_in) // { dg-error "redeclaration of" }
+ #pragma omp declare reduction (n3: short unsigned: omp_out += omp_in)
+ #pragma omp declare reduction (n3: short int: omp_out += omp_in)
+ void
+ f6 ()
+ {
+ #pragma omp declare reduction (f6: T: omp_out.t += omp_in.t)
+ #pragma omp declare reduction (f6: S: omp_out.s *= omp_in.s) // { dg-error "previous" }
+ #pragma omp declare reduction (f6: ::S: omp_out.s += omp_in.s) // { dg-error "redeclaration of" }
+ #pragma omp declare reduction (f6: long: omp_out += omp_in) // { dg-error "previous" }
+ #pragma omp declare reduction (f6: long int: omp_out += omp_in) // { dg-error "redeclaration of" }
+ #pragma omp declare reduction (f6: short unsigned: omp_out += omp_in)
+ #pragma omp declare reduction (f6: short int: omp_out += omp_in)
+ }
+}
+
+namespace N4
+{
+ struct U
+ {
+ #pragma omp declare reduction (bar: T: omp_out.t += omp_in.t)
+ #pragma omp declare reduction (bar: S: omp_out.s *= omp_in.s) // { dg-error "with" }
+ #pragma omp declare reduction (bar: S: omp_out.s += omp_in.s) // { dg-error "cannot be overloaded" }
+ #pragma omp declare reduction (bar: long: omp_out += omp_in) // { dg-error "with" }
+ #pragma omp declare reduction (bar: long int: omp_out += omp_in) // { dg-error "cannot be overloaded" }
+ #pragma omp declare reduction (bar: short unsigned: omp_out += omp_in)
+ #pragma omp declare reduction (bar: short int: omp_out += omp_in)
+ };
+}
+
+namespace N5
+{
+ template <typename T>
+ int
+ f7 ()
+ {
+ #pragma omp declare reduction (f7: T: omp_out.s *= omp_in.s) // { dg-error "previous" }
+ #pragma omp declare reduction (f7: T: omp_out.s += omp_in.s) // { dg-error "redeclaration of" }
+ return 0;
+ }
+ int x = f7 <S> ();
+ template <typename T>
+ struct U
+ {
+ #pragma omp declare reduction (bar: T: omp_out.s *= omp_in.s) // { dg-error "with" }
+ #pragma omp declare reduction (bar: T: omp_out.s += omp_in.s) // { dg-error "cannot be overloaded" }
+ };
+ U<S> u;
+}
+
+namespace N6
+{
+ template <typename U>
+ int
+ f8 ()
+ {
+ #pragma omp declare reduction (f8: T: omp_out.t += omp_in.t)
+ #pragma omp declare reduction (f8: U: omp_out.s *= omp_in.s) // { dg-error "previous" }
+ #pragma omp declare reduction (f8: ::S: omp_out.s += omp_in.s) // { dg-error "redeclaration of" }
+ #pragma omp declare reduction (f8: long: omp_out += omp_in) // { dg-error "previous" }
+ #pragma omp declare reduction (f8: long int: omp_out += omp_in) // { dg-error "redeclaration of" }
+ #pragma omp declare reduction (f8: short unsigned: omp_out += omp_in)
+ #pragma omp declare reduction (f8: short int: omp_out += omp_in)
+ return 0;
+ }
+ int x = f8 <S> ();
+ template <typename V>
+ struct U
+ {
+ typedef V V2;
+ #pragma omp declare reduction (bar: T: omp_out.t += omp_in.t)
+ #pragma omp declare reduction (bar: V: omp_out.s *= omp_in.s) // { dg-error "with" }
+ #pragma omp declare reduction (bar: V2: omp_out.s += omp_in.s) // { dg-error "cannot be overloaded" }
+ #pragma omp declare reduction (bar: long: omp_out += omp_in) // { dg-error "with" }
+ #pragma omp declare reduction (bar: long int: omp_out += omp_in) // { dg-error "cannot be overloaded" }
+ #pragma omp declare reduction (bar: short unsigned: omp_out += omp_in)
+ #pragma omp declare reduction (bar: short int: omp_out += omp_in)
+ };
+ U<S> u;
+}
+
+namespace N7
+{
+ #pragma omp declare reduction (+: S: omp_out.s += omp_in.s) initializer (omp_priv) // { dg-error "invalid initializer clause" }
+ #pragma omp declare reduction (+: T: omp_out.t += omp_in.t) initializer (omp_priv ()) // { dg-error "invalid initializer clause" }
+}
+
+namespace N8
+{
+ struct A { int a; A (); ~A (); };
+ struct B { int b; B (); ~B (); B (int); };
+ struct C : public A, B { int c; C (); ~C (); };
+ #pragma omp declare reduction (+:B:omp_out.b += omp_in.b) initializer (omp_priv (4))
+ void bar (C &);
+ void baz ()
+ {
+ C a;
+ #pragma omp parallel reduction (+:a) // { dg-error "user defined reduction with constructor initializer for base class" }
+ bar (a);
+ }
+}
diff --git a/gcc/testsuite/g++.dg/gomp/udr-4.C b/gcc/testsuite/g++.dg/gomp/udr-4.C
new file mode 100644
index 00000000000..f1b388bbd91
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/udr-4.C
@@ -0,0 +1,14 @@
+// { dg-do compile }
+
+struct S; // { dg-error "forward declaration" }
+#pragma omp declare reduction (+:S:omp_out.s += omp_in.s) // { dg-error "invalid use of incomplete type" }
+struct S { int s; S () : s (1) {} };
+#pragma omp declare reduction (*:S:omp_out.s *= omp_in.s)
+
+void
+foo ()
+{
+ S s;
+ #pragma omp parallel reduction (S::~S:s) // { dg-error "invalid reduction-identifier" }
+ s.s = 1;
+}
diff --git a/gcc/testsuite/g++.dg/gomp/udr-5.C b/gcc/testsuite/g++.dg/gomp/udr-5.C
new file mode 100644
index 00000000000..425f8e95cd9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/udr-5.C
@@ -0,0 +1,41 @@
+// { dg-do compile }
+
+struct S
+{
+ int s;
+ S () : s (0) {}
+private:
+ #pragma omp declare reduction (+:S:omp_out.s += omp_in.s) // { dg-error "is private" }
+protected:
+ #pragma omp declare reduction (-:S:omp_out.s += omp_in.s) // { dg-error "is protected" }
+};
+
+struct T : public S
+{
+ void foo ()
+ {
+ S s;
+ #pragma omp parallel reduction (S::operator +:s) // { dg-error "within this context" }
+ s.s = 1;
+ S t;
+ #pragma omp parallel reduction (S::operator -:t)
+ t.s = 1;
+ S u;
+ #pragma omp parallel reduction (+:u) // { dg-error "within this context" }
+ u.s = 1;
+ S v;
+ #pragma omp parallel reduction (-:v)
+ v.s = 1;
+ }
+};
+
+void
+foo ()
+{
+ S s;
+ #pragma omp parallel reduction (S::operator +:s) // { dg-error "within this context" }
+ s.s = 1;
+ S t;
+ #pragma omp parallel reduction (S::operator -:t) // { dg-error "within this context" }
+ t.s = 1;
+}
diff --git a/gcc/testsuite/g++.dg/gomp/udr-6.C b/gcc/testsuite/g++.dg/gomp/udr-6.C
new file mode 100644
index 00000000000..9060c87a542
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/udr-6.C
@@ -0,0 +1,59 @@
+// { dg-do compile }
+
+struct A { int a; A () : a (0) {} };
+struct B { int b; B () : b (0) {} };
+struct C : public A, B { int c; C () : c (0) {} };
+struct D { int d; D () : d (0) {} };
+struct E { int e; E () : e (0) {} };
+struct F : public D, E { int f; F () : f (0) {} };
+struct G : public C, F { int g; G () : g (0) {} };
+
+#pragma omp declare reduction (+: A : omp_out.a += omp_in.a) // { dg-message "operator" }
+#pragma omp declare reduction (+: B : omp_out.b += omp_in.b) // { dg-message "operator" }
+#pragma omp declare reduction (+: D : omp_out.d += omp_in.d)
+#pragma omp declare reduction (+: E : omp_out.e += omp_in.e)
+#pragma omp declare reduction (+: F : omp_out.f += omp_in.f) // { dg-message "operator" }
+
+void
+f1 ()
+{
+ G g;
+ #pragma omp parallel reduction (+: g) // { dg-error "user defined reduction lookup is ambiguous" }
+ {
+ g.g++;
+ }
+}
+
+#pragma omp declare reduction (*: A : omp_out.a += omp_in.a)
+#pragma omp declare reduction (*: B : omp_out.b += omp_in.b)
+#pragma omp declare reduction (*: D : omp_out.d += omp_in.d)
+#pragma omp declare reduction (*: E : omp_out.e += omp_in.e)
+#pragma omp declare reduction (*: F : omp_out.f += omp_in.f)
+#pragma omp declare reduction (*: G : omp_out.g += omp_in.g)
+
+void
+f2 ()
+{
+ G g;
+ #pragma omp parallel reduction (*: g)
+ {
+ g.g++;
+ }
+}
+
+#pragma omp declare reduction (|: A : omp_out.a += omp_in.a)
+#pragma omp declare reduction (|: B : omp_out.b += omp_in.b)
+#pragma omp declare reduction (|: C : omp_out.c += omp_in.c) // { dg-message "operator" }
+#pragma omp declare reduction (|: D : omp_out.d += omp_in.d)
+#pragma omp declare reduction (|: E : omp_out.e += omp_in.e)
+#pragma omp declare reduction (|: F : omp_out.f += omp_in.f) // { dg-message "operator" }
+
+void
+f3 ()
+{
+ G g;
+ #pragma omp parallel reduction (|: g) // { dg-error "user defined reduction lookup is ambiguous" }
+ {
+ g.g++;
+ }
+}
diff --git a/gcc/testsuite/g++.dg/init/array35.C b/gcc/testsuite/g++.dg/init/array35.C
new file mode 100644
index 00000000000..6ce6d5cc956
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/array35.C
@@ -0,0 +1,3 @@
+// PR c++/58868
+
+static struct { const int i; } a[] = { 1 };
diff --git a/gcc/testsuite/g++.dg/init/ctor8.C b/gcc/testsuite/g++.dg/init/ctor8.C
index 3491f6a1d2c..7eb72eb833f 100644
--- a/gcc/testsuite/g++.dg/init/ctor8.C
+++ b/gcc/testsuite/g++.dg/init/ctor8.C
@@ -1,9 +1,10 @@
// PR c++/29039
-typedef struct S {
+typedef struct S { // { dg-error "reference" "" { target c++11 } }
int &r;
}; // { dg-warning "'typedef' was ignored" }
+
S f () {
- return S (); // { dg-error "reference" }
+ return S (); // { dg-error "reference|deleted" }
}
diff --git a/gcc/testsuite/g++.dg/init/pr25811.C b/gcc/testsuite/g++.dg/init/pr25811.C
index c906a9bbd35..e8945dafe93 100644
--- a/gcc/testsuite/g++.dg/init/pr25811.C
+++ b/gcc/testsuite/g++.dg/init/pr25811.C
@@ -1,51 +1,51 @@
// PR c++/25811
// { dg-do compile }
-struct A1
+struct A1 // { dg-error "uninitialized" "" { target c++11 } }
{
- int const j; // { dg-message "should be initialized" }
+ int const j; // { dg-message "should be initialized" "" { target c++98 } }
};
-struct A2
+struct A2 // { dg-error "uninitialized" "" { target c++11 } }
{
- int const volatile i; // { dg-message "should be initialized" }
+ int const volatile i; // { dg-message "should be initialized" "" { target c++98 } }
};
-struct A3
+struct A3 // { dg-error "uninitialized" "" { target c++11 } }
{
- int& ref; // { dg-message "should be initialized" }
+ int& ref; // { dg-message "should be initialized" "" { target c++98 } }
};
-struct A4
+struct A4 // { dg-error "uninitialized" "" { target c++11 } }
{
- int const& ref; // { dg-message "should be initialized" }
+ int const& ref; // { dg-message "should be initialized" "" { target c++98 } }
};
-struct A5
+struct A5 // { dg-error "uninitialized" "" { target c++11 } }
{
- int& ref; // { dg-message "should be initialized" }
- int const i; // { dg-message "should be initialized" }
+ int& ref; // { dg-message "should be initialized" "" { target c++98 } }
+ int const i; // { dg-message "should be initialized" "" { target c++98 } }
};
-template <class T> struct S1
+template <class T> struct S1 // { dg-error "uninitialized" "" { target c++11 } }
{
- T const i; // { dg-message "should be initialized" }
+ T const i; // { dg-message "should be initialized" "" { target c++98 } }
};
-template <class T> struct S2
+template <class T> struct S2 // { dg-error "uninitialized" "" { target c++11 } }
{
- T const volatile i; // { dg-message "should be initialized" }
+ T const volatile i; // { dg-message "should be initialized" "" { target c++98 } }
};
-template <class T> struct S3
+template <class T> struct S3 // { dg-error "uninitialized" "" { target c++11 } }
{
- T& ref; // { dg-message "should be initialized" }
+ T& ref; // { dg-message "should be initialized" "" { target c++98 } }
};
-template <class T> struct S4
+template <class T> struct S4 // { dg-error "uninitialized" "" { target c++11 } }
{
- T const i; // { dg-message "should be initialized" }
- T& ref; // { dg-message "should be initialized" }
+ T const i; // { dg-message "should be initialized" "" { target c++98 } }
+ T& ref; // { dg-message "should be initialized" "" { target c++98 } }
};
struct X
@@ -55,44 +55,44 @@ struct X
int const& r;
};
-struct Y11
+struct Y11 // { dg-error "uninitialized" "" { target c++11 } }
{
- int const i; // { dg-message "should be initialized" }
+ int const i; // { dg-message "should be initialized" "" { target c++98 } }
};
-struct Y1
+struct Y1 // { dg-error "deleted" "" { target c++11 } }
{
Y11 a[1];
};
-struct Y22
+struct Y22 // { dg-error "uninitialized" "" { target c++11 } }
{
- int& ref; // { dg-message "should be initialized" }
+ int& ref; // { dg-message "should be initialized" "" { target c++98 } }
};
-struct Y2
+struct Y2 // { dg-error "deleted" "" { target c++11 } }
{
Y22 a[1];
};
-struct Z1
+struct Z1 // { dg-error "uninitialized" "" { target c++11 } }
{
- int const i; // { dg-message "should be initialized" }
+ int const i; // { dg-message "should be initialized" "" { target c++98 } }
};
-struct Z2
+struct Z2 // { dg-error "uninitialized" "" { target c++11 } }
{
- int& ref; // { dg-message "should be initialized" }
+ int& ref; // { dg-message "should be initialized" "" { target c++98 } }
};
-struct Z3
+struct Z3 // { dg-error "uninitialized" "" { target c++11 } }
{
- int const i; // { dg-message "should be initialized" }
+ int const i; // { dg-message "should be initialized" "" { target c++98 } }
};
-struct Z4
+struct Z4 // { dg-error "uninitialized" "" { target c++11 } }
{
- int& ref; // { dg-message "should be initialized" }
+ int& ref; // { dg-message "should be initialized" "" { target c++98 } }
};
struct Z5
@@ -100,7 +100,7 @@ struct Z5
int i;
};
-struct Z
+struct Z // { dg-error "deleted" "" { target c++11 } }
{
Z1 z1;
Z2 z2;
@@ -109,54 +109,54 @@ struct Z
Z5 z5;
};
-union U
+union U // { dg-error "uninitialized" "" { target c++11 } }
{
- int const i; // { dg-message "should be initialized" }
+ int const i; // { dg-message "should be initialized" "" { target c++98 } }
};
void f1 ()
{
- new A1; // { dg-error "uninitialized const member" }
+ new A1; // { dg-error "deleted|uninitialized const member" }
}
void f2 ()
{
- new A2; // { dg-error "uninitialized const member" }
+ new A2; // { dg-error "deleted|uninitialized const member" }
}
void f3 ()
{
- new A3; // { dg-error "uninitialized reference member" }
+ new A3; // { dg-error "deleted|uninitialized reference member" }
}
void f4 ()
{
- new A4; // { dg-error "uninitialized reference member" }
+ new A4; // { dg-error "deleted|uninitialized reference member" }
}
void f5 ()
{
- new A5; // { dg-error "uninitialized reference member|uninitialized const member" }
+ new A5; // { dg-error "deleted|uninitialized reference member|uninitialized const member" }
}
void f6 ()
{
- new S1<int>; // { dg-error "uninitialized const member" }
+ new S1<int>; // { dg-error "deleted|uninitialized const member" }
}
void f7 ()
{
- new S2<int>; // { dg-error "uninitialized const member" }
+ new S2<int>; // { dg-error "deleted|uninitialized const member" }
}
void f8 ()
{
- new S3<int>; // { dg-error "uninitialized reference member" }
+ new S3<int>; // { dg-error "deleted|uninitialized reference member" }
}
void f9 ()
{
- new S4<int>; // { dg-error "uninitialized reference member|uninitialized const member" }
+ new S4<int>; // { dg-error "deleted|uninitialized reference member|uninitialized const member" }
}
void f10 ()
@@ -166,30 +166,30 @@ void f10 ()
void f11 ()
{
- new A1[1]; // { dg-error "uninitialized const member" }
+ new A1[1]; // { dg-error "deleted|uninitialized const member" }
}
void f12 ()
{
- new A3[1]; // { dg-error "uninitialized reference member" }
+ new A3[1]; // { dg-error "deleted|uninitialized reference member" }
}
void f13 ()
{
- new Y1; // { dg-error "uninitialized const member" }
+ new Y1; // { dg-error "deleted|uninitialized const member" }
}
void f14 ()
{
- new Y2; // { dg-error "uninitialized reference member" }
+ new Y2; // { dg-error "deleted|uninitialized reference member" }
}
void f15 ()
{
- new Z; // { dg-error "uninitialized reference member|uninitialized const member" }
+ new Z; // { dg-error "deleted|uninitialized reference member|uninitialized const member" }
}
void f16 ()
{
- new U; // { dg-error "uninitialized const member" }
+ new U; // { dg-error "deleted|uninitialized const member" }
}
diff --git a/gcc/testsuite/g++.dg/init/pr29043.C b/gcc/testsuite/g++.dg/init/pr29043.C
index 6ed31b5d6b5..f868dfb91a4 100644
--- a/gcc/testsuite/g++.dg/init/pr29043.C
+++ b/gcc/testsuite/g++.dg/init/pr29043.C
@@ -1,27 +1,27 @@
// PR c++/29043
// { dg-do compile }
-struct S
+struct S // { dg-error "uninitialized" "" { target c++11 } }
{
- int const i; // { dg-message "should be initialized" }
+ int const i; // { dg-message "should be initialized" "" { target c++98 } }
};
class C
{
public:
- C() {} // { dg-error "uninitialized const member" }
+ C() {} // { dg-error "uninitialized const member|deleted" }
S s;
};
-struct S2
+struct S2 // { dg-error "uninitialized" "" { target c++11 } }
{
- int& ref; // { dg-message "should be initialized" }
+ int& ref; // { dg-message "should be initialized" "" { target c++98 } }
};
class C2
{
public:
- C2() {} // { dg-error "uninitialized reference member" }
+ C2() {} // { dg-error "uninitialized reference member|deleted" }
S2 s;
};
@@ -33,14 +33,14 @@ class C3
};
};
-struct S4
+struct S4 // { dg-error "uninitialized" "" { target c++11 } }
{
- int const i; // { dg-message "should be initialized" }
+ int const i; // { dg-message "should be initialized" "" { target c++98 } }
};
struct C4
{
- C4() {} // { dg-error "uninitialized const member" }
+ C4() {} // { dg-error "uninitialized const member|deleted" }
S4 s4[ 1 ];
};
diff --git a/gcc/testsuite/g++.dg/init/pr43719.C b/gcc/testsuite/g++.dg/init/pr43719.C
index d3487c94a09..13a82210bc6 100644
--- a/gcc/testsuite/g++.dg/init/pr43719.C
+++ b/gcc/testsuite/g++.dg/init/pr43719.C
@@ -1,51 +1,51 @@
// PR c++/43719
// { dg-do compile }
-struct A1
+struct A1 // { dg-error "uninitialized" "" { target c++11 } }
{
- int const j; // { dg-message "should be initialized" }
+ int const j; // { dg-message "should be initialized" "" { target c++98 } }
};
-struct A2
+struct A2 // { dg-error "uninitialized" "" { target c++11 } }
{
- int const volatile i; // { dg-message "should be initialized" }
+ int const volatile i; // { dg-message "should be initialized" "" { target c++98 } }
};
-struct A3
+struct A3 // { dg-error "uninitialized" "" { target c++11 } }
{
- int& ref; // { dg-message "should be initialized" }
+ int& ref; // { dg-message "should be initialized" "" { target c++98 } }
};
-struct A4
+struct A4 // { dg-error "uninitialized" "" { target c++11 } }
{
- int const& ref; // { dg-message "should be initialized" }
+ int const& ref; // { dg-message "should be initialized" "" { target c++98 } }
};
-struct A5
+struct A5 // { dg-error "uninitialized" "" { target c++11 } }
{
- int& ref; // { dg-message "should be initialized" }
- int const i; // { dg-message "should be initialized" }
+ int& ref; // { dg-message "should be initialized" "" { target c++98 } }
+ int const i; // { dg-message "should be initialized" "" { target c++98 } }
};
-template <class T> struct S1
+template <class T> struct S1 // { dg-error "uninitialized" "" { target c++11 } }
{
- T const i; // { dg-message "should be initialized" }
+ T const i; // { dg-message "should be initialized" "" { target c++98 } }
};
-template <class T> struct S2
+template <class T> struct S2 // { dg-error "uninitialized" "" { target c++11 } }
{
- T const volatile i; // { dg-message "should be initialized" }
+ T const volatile i; // { dg-message "should be initialized" "" { target c++98 } }
};
-template <class T> struct S3
+template <class T> struct S3 // { dg-error "uninitialized" "" { target c++11 } }
{
- T& ref; // { dg-message "should be initialized" }
+ T& ref; // { dg-message "should be initialized" "" { target c++98 } }
};
-template <class T> struct S4
+template <class T> struct S4 // { dg-error "uninitialized" "" { target c++11 } }
{
- T const i; // { dg-message "should be initialized" }
- T& ref; // { dg-message "should be initialized" }
+ T const i; // { dg-message "should be initialized" "" { target c++98 } }
+ T& ref; // { dg-message "should be initialized" "" { target c++98 } }
};
struct X
@@ -55,44 +55,44 @@ struct X
int const& r;
};
-struct Y11
+struct Y11 // { dg-error "uninitialized" "" { target c++11 } }
{
- int const i; // { dg-message "should be initialized" }
+ int const i; // { dg-message "should be initialized" "" { target c++98 } }
};
-struct Y1
+struct Y1 // { dg-error "deleted" "" { target c++11 } }
{
Y11 a[1];
};
-struct Y22
+struct Y22 // { dg-error "uninitialized" "" { target c++11 } }
{
- int& ref; // { dg-message "should be initialized" }
+ int& ref; // { dg-message "should be initialized" "" { target c++98 } }
};
-struct Y2
+struct Y2 // { dg-error "deleted" "" { target c++11 } }
{
Y22 a[1];
};
-struct Z1
+struct Z1 // { dg-error "uninitialized" "" { target c++11 } }
{
- int const i; // { dg-message "should be initialized" }
+ int const i; // { dg-message "should be initialized" "" { target c++98 } }
};
-struct Z2
+struct Z2 // { dg-error "uninitialized" "" { target c++11 } }
{
- int& ref; // { dg-message "should be initialized" }
+ int& ref; // { dg-message "should be initialized" "" { target c++98 } }
};
-struct Z3
+struct Z3 // { dg-error "uninitialized" "" { target c++11 } }
{
- int const i; // { dg-message "should be initialized" }
+ int const i; // { dg-message "should be initialized" "" { target c++98 } }
};
-struct Z4
+struct Z4 // { dg-error "uninitialized" "" { target c++11 } }
{
- int& ref; // { dg-message "should be initialized" }
+ int& ref; // { dg-message "should be initialized" "" { target c++98 } }
};
struct Z5
@@ -100,7 +100,7 @@ struct Z5
int i;
};
-struct Z
+struct Z // { dg-error "deleted" "" { target c++11 } }
{
Z1 z1;
Z2 z2;
@@ -109,55 +109,55 @@ struct Z
Z5 z5;
};
-union U
+union U // { dg-error "uninitialized" "" { target c++11 } }
{
- int const i; // { dg-message "should be initialized" }
+ int const i; // { dg-message "should be initialized" "" { target c++98 } }
};
void f1 ()
{
- A1 a1; // { dg-error "uninitialized const member" }
+ A1 a1; // { dg-error "uninitialized const member|deleted" }
}
void f2 ()
{
- A2 a2; // { dg-error "uninitialized const member" }
+ A2 a2; // { dg-error "uninitialized const member|deleted" }
}
void f3 ()
{
- A3 a3; // { dg-error "uninitialized reference member" }
+ A3 a3; // { dg-error "uninitialized reference member|deleted" }
}
void f4 ()
{
- A4 a4; // { dg-error "uninitialized reference member" }
+ A4 a4; // { dg-error "uninitialized reference member|deleted" }
}
void f5 ()
{
- A5 a5; // { dg-error "uninitialized reference member|uninitialized const member" }
+ A5 a5; // { dg-error "uninitialized reference member|uninitialized const member|deleted" }
}
void f6 ()
{
- S1<int> s; // { dg-error "uninitialized const member" }
+ S1<int> s; // { dg-error "uninitialized const member|deleted" }
}
void f7 ()
{
- S2<int> s; // { dg-error "uninitialized const member" }
+ S2<int> s; // { dg-error "uninitialized const member|deleted" }
}
void f8 ()
{
- S3<int> s; // { dg-error "uninitialized reference member" }
+ S3<int> s; // { dg-error "uninitialized reference member|deleted" }
}
void f9 ()
{
- S4<int> s; // { dg-error "uninitialized reference member|uninitialized const member" }
+ S4<int> s; // { dg-error "uninitialized reference member|uninitialized const member|deleted" }
}
void f10 ()
@@ -167,31 +167,31 @@ void f10 ()
void f11 ()
{
- A1 a[ 1 ]; // { dg-error "uninitialized const member" }
+ A1 a[ 1 ]; // { dg-error "uninitialized const member|deleted" }
}
void f12 ()
{
- A3 a[ 1 ]; // { dg-error "uninitialized reference member" }
+ A3 a[ 1 ]; // { dg-error "uninitialized reference member|deleted" }
}
void f13 ()
{
- Y1 y1; // { dg-error "uninitialized const member" }
+ Y1 y1; // { dg-error "uninitialized const member|deleted" }
}
void f14 ()
{
- Y2 y2; // { dg-error "uninitialized reference member" }
+ Y2 y2; // { dg-error "uninitialized reference member|deleted" }
}
void f15 ()
{
- Z z; // { dg-error "uninitialized reference member|uninitialized const member" }
+ Z z; // { dg-error "uninitialized reference member|uninitialized const member|deleted" }
}
void f16 ()
{
- U u; // { dg-error "uninitialized const member" }
+ U u; // { dg-error "uninitialized const member|deleted" }
}
diff --git a/gcc/testsuite/g++.dg/init/pr44086.C b/gcc/testsuite/g++.dg/init/pr44086.C
index e3304f4a27b..b4b0833dd69 100644
--- a/gcc/testsuite/g++.dg/init/pr44086.C
+++ b/gcc/testsuite/g++.dg/init/pr44086.C
@@ -1,15 +1,15 @@
// PR c++/44086
// { dg-do compile }
-struct A
+struct A // { dg-error "uninitialized" "" { target c++11 } }
{
- int const i : 2; // { dg-message "should be initialized" }
+ int const i : 2; // { dg-message "should be initialized" "" { target c++98 } }
};
void f()
{
- A a; // { dg-error "uninitialized const" }
- new A; // { dg-error "uninitialized const" }
- A();
- new A();
+ A a; // { dg-error "deleted|uninitialized const" }
+ new A; // { dg-error "deleted|uninitialized const" }
+ A(); // { dg-error "deleted" "" { target c++11 } }
+ new A(); // { dg-error "deleted" "" { target c++11 } }
}
diff --git a/gcc/testsuite/g++.dg/init/ref14.C b/gcc/testsuite/g++.dg/init/ref14.C
index 212e6e95d7e..6ac42415b43 100644
--- a/gcc/testsuite/g++.dg/init/ref14.C
+++ b/gcc/testsuite/g++.dg/init/ref14.C
@@ -1,4 +1,6 @@
// PR c++/33459
+// { dg-prune-output "uninitialized" }
+// { dg-prune-output "deleted" }
union A
{
diff --git a/gcc/testsuite/g++.dg/init/uninitialized1.C b/gcc/testsuite/g++.dg/init/uninitialized1.C
new file mode 100644
index 00000000000..1e4f7ae84e2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/uninitialized1.C
@@ -0,0 +1,12 @@
+// PR c++/58126
+
+struct A { // { dg-error "uninitialized" "" { target c++11 } }
+ const int value1;
+ int& value2;
+};
+
+struct B : A { }; // { dg-error "deleted" "" { target c++11 } }
+
+A a; // { dg-error "deleted|uninitialized const member in 'struct A'|uninitialized reference member in 'struct A'" }
+
+B b; // { dg-error "deleted|uninitialized const member in base 'struct A' of 'struct B'|uninitialized reference member in base 'struct A' of 'struct B'" }
diff --git a/gcc/testsuite/g++.dg/lookup/name-clash10.C b/gcc/testsuite/g++.dg/lookup/name-clash10.C
new file mode 100644
index 00000000000..0a089be257a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/name-clash10.C
@@ -0,0 +1,8 @@
+// PR c++/38313
+
+struct foo { };
+struct bar { };
+
+struct baz {
+ static foo (bar)();
+};
diff --git a/gcc/testsuite/g++.dg/lto/lto.exp b/gcc/testsuite/g++.dg/lto/lto.exp
index 29cf3be991d..0c6025dd962 100644
--- a/gcc/testsuite/g++.dg/lto/lto.exp
+++ b/gcc/testsuite/g++.dg/lto/lto.exp
@@ -48,7 +48,7 @@ if { ![check_effective_target_lto] } {
}
# Main loop.
-foreach src [lsort [find $srcdir/$subdir *_0.C]] {
+foreach src [lsort [find $srcdir/$subdir *_0.\[cC\]]] {
# If we're only testing specific files and this isn't one of them, skip it.
if ![runtest_file_p $runtests $src] then {
continue
diff --git a/gcc/testsuite/gcc.dg/lto/pr54625-1_0.c b/gcc/testsuite/g++.dg/lto/pr54625-1_0.c
index 5ab90ddddee..5ab90ddddee 100644
--- a/gcc/testsuite/gcc.dg/lto/pr54625-1_0.c
+++ b/gcc/testsuite/g++.dg/lto/pr54625-1_0.c
diff --git a/gcc/testsuite/gcc.dg/lto/pr54625-1_1.C b/gcc/testsuite/g++.dg/lto/pr54625-1_1.C
index 2d0d5bfbadf..2d0d5bfbadf 100644
--- a/gcc/testsuite/gcc.dg/lto/pr54625-1_1.C
+++ b/gcc/testsuite/g++.dg/lto/pr54625-1_1.C
diff --git a/gcc/testsuite/gcc.dg/lto/pr54625-2_0.c b/gcc/testsuite/g++.dg/lto/pr54625-2_0.c
index 6511ba5cc62..6511ba5cc62 100644
--- a/gcc/testsuite/gcc.dg/lto/pr54625-2_0.c
+++ b/gcc/testsuite/g++.dg/lto/pr54625-2_0.c
diff --git a/gcc/testsuite/gcc.dg/lto/pr54625-2_1.C b/gcc/testsuite/g++.dg/lto/pr54625-2_1.C
index 09c365d2354..09c365d2354 100644
--- a/gcc/testsuite/gcc.dg/lto/pr54625-2_1.C
+++ b/gcc/testsuite/g++.dg/lto/pr54625-2_1.C
diff --git a/gcc/testsuite/g++.dg/opt/devirt3.C b/gcc/testsuite/g++.dg/opt/devirt3.C
new file mode 100644
index 00000000000..673867361c1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/devirt3.C
@@ -0,0 +1,24 @@
+// { dg-do compile }
+// { dg-options "-O2" }
+
+class ert_RefCounter {
+ protected:
+ int refCounterE;
+ virtual ~ert_RefCounter() {}
+};
+
+class ebs_Object : virtual public ert_RefCounter {
+};
+
+class dpr_App : public ebs_Object {
+ public:
+ virtual void run();
+};
+
+class dpr_Job : public ebs_Object {};
+
+void dpr_run(ebs_Object& objectA) {
+ ((dpr_App&)objectA).run();
+ dpr_Job jobL;
+ dpr_run(jobL);
+}
diff --git a/gcc/testsuite/g++.dg/other/java3.C b/gcc/testsuite/g++.dg/other/java3.C
new file mode 100644
index 00000000000..1bc0a8874fe
--- /dev/null
+++ b/gcc/testsuite/g++.dg/other/java3.C
@@ -0,0 +1,7 @@
+// PR c++/11006
+
+typedef int* jclass;
+
+void foo () {
+ new __java_boolean; // { dg-error "valid" }
+}
diff --git a/gcc/testsuite/g++.dg/other/warning1.C b/gcc/testsuite/g++.dg/other/warning1.C
index c65ae0ff6ef..a23d0ca6cba 100644
--- a/gcc/testsuite/g++.dg/other/warning1.C
+++ b/gcc/testsuite/g++.dg/other/warning1.C
@@ -7,8 +7,8 @@ extern "C" int printf(const char *, ...);
struct S
{
- static const float inf = 1.0f / 0.0f; // { dg-warning "1.0|float|initializ" }
- static const float nan = 0.0f / 0.0f; // { dg-warning "0.0|float|initializ" }
+ static const float inf = 1.0f / 0.0f; // { dg-error "1.0|float|initializ" }
+ static const float nan = 0.0f / 0.0f; // { dg-error "0.0|float|initializ" }
};
int main()
diff --git a/gcc/testsuite/g++.dg/parse/crash64.C b/gcc/testsuite/g++.dg/parse/crash64.C
new file mode 100644
index 00000000000..9e1dfea6c32
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/crash64.C
@@ -0,0 +1,7 @@
+// PR c++/58565
+// { dg-options "" }
+
+void foo()
+{
+ int i = ({ L: ; }); // { dg-error "void value not ignored" }
+}
diff --git a/gcc/testsuite/g++.dg/parse/crash65.C b/gcc/testsuite/g++.dg/parse/crash65.C
new file mode 100644
index 00000000000..04154f40cd5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/crash65.C
@@ -0,0 +1,6 @@
+// PR c++/58535
+
+struct A
+{
+ template<int> virtual void foo(); // { dg-error "templates" }
+};
diff --git a/gcc/testsuite/g++.dg/parse/ivdep.C b/gcc/testsuite/g++.dg/parse/ivdep.C
new file mode 100644
index 00000000000..23d51de9fe3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/ivdep.C
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+
+/* PR other/33426 */
+
+void foo(int n, int *a, int *b, int *c, int *d, int *e) {
+ int i, j;
+#pragma GCC ivdep
+ for (i = 0; ; ++i) { /* { dg-error "missing loop condition in loop with 'GCC ivdep' pragma before ';' token" } */
+ a[i] = b[i] + c[i];
+ }
+}
diff --git a/gcc/testsuite/g++.dg/parse/pr29234.C b/gcc/testsuite/g++.dg/parse/pr29234.C
new file mode 100644
index 00000000000..d2dc735f226
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/pr29234.C
@@ -0,0 +1,16 @@
+// PR c++/29234
+
+struct S { void operator()(); };
+
+void foo ()
+{
+ ( S()() );
+}
+
+struct C { void operator[](C); };
+
+void bar ()
+{
+ C x;
+ ( C()[x] );
+}
diff --git a/gcc/testsuite/g++.dg/parse/pr52071.C b/gcc/testsuite/g++.dg/parse/pr52071.C
new file mode 100644
index 00000000000..99456c0041a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/pr52071.C
@@ -0,0 +1,23 @@
+// PR c++/52071
+
+struct C1 {
+ C1(int);
+};
+
+struct C2 {
+ C2();
+ C2(C1);
+};
+
+void f()
+{
+ int x;
+ int y = 1;
+ C2 vc;
+
+ vc = C2(C1(x = y));
+
+ vc = (C2(C1(x = y)));
+
+ vc = (C2(C1((0, x = y))));
+}
diff --git a/gcc/testsuite/g++.dg/parse/pr56037.C b/gcc/testsuite/g++.dg/parse/pr56037.C
new file mode 100644
index 00000000000..10f145ae5ee
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/pr56037.C
@@ -0,0 +1,12 @@
+// PR c++/56037
+
+struct T
+{
+ T(int, int);
+};
+
+int main()
+{
+ static const int zero = 0;
+ (T(int(zero), int(zero)));
+}
diff --git a/gcc/testsuite/g++.dg/parse/pr58705.C b/gcc/testsuite/g++.dg/parse/pr58705.C
new file mode 100644
index 00000000000..de2b396a5e4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/pr58705.C
@@ -0,0 +1,5 @@
+// PR c++/58705
+// { dg-do compile }
+// { dg-options "-Wnarrowing" }
+
+_Complex float f = {{}};
diff --git a/gcc/testsuite/g++.dg/plugin/header_plugin.c b/gcc/testsuite/g++.dg/plugin/header_plugin.c
index a464827dee9..a024194e19f 100644
--- a/gcc/testsuite/g++.dg/plugin/header_plugin.c
+++ b/gcc/testsuite/g++.dg/plugin/header_plugin.c
@@ -17,7 +17,6 @@
#include "c-family/c-pretty-print.h"
#include "tree-iterator.h"
#include "plugin.h"
-#include "tree-flow.h"
#include "langhooks.h"
#include "cp/cxx-pretty-print.h"
#include "cp/name-lookup.h"
diff --git a/gcc/testsuite/g++.dg/plugin/selfassign.c b/gcc/testsuite/g++.dg/plugin/selfassign.c
index 7235089c7d3..5331f792cb2 100644
--- a/gcc/testsuite/g++.dg/plugin/selfassign.c
+++ b/gcc/testsuite/g++.dg/plugin/selfassign.c
@@ -7,6 +7,7 @@
#include "system.h"
#include "coretypes.h"
#include "tm.h"
+#include "tree.h"
#include "toplev.h"
#include "basic-block.h"
#include "gimple.h"
diff --git a/gcc/testsuite/g++.dg/template/nontype26.C b/gcc/testsuite/g++.dg/template/nontype26.C
new file mode 100644
index 00000000000..763d987dd39
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/nontype26.C
@@ -0,0 +1,20 @@
+// PR c++/31671
+
+template<int& i> void doit() {
+ i = 0;
+}
+
+template<const int& i> class X {
+public:
+ void foo() {
+ doit<i>(); // { dg-error "cv-qualification|no matching" }
+ }
+};
+
+int i = 0;
+
+X<i> x;
+
+int main() {
+ x.foo();
+}
diff --git a/gcc/testsuite/g++.dg/template/pr58878.C b/gcc/testsuite/g++.dg/template/pr58878.C
new file mode 100644
index 00000000000..adad9fe5b07
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/pr58878.C
@@ -0,0 +1,61 @@
+// PR c++/58878
+
+// Template-members of non-template class
+struct A
+{
+ template <typename t> // { dg-error "shadows" }
+ void f()
+ {
+ int t = 1; // { dg-error "declaration" }
+ }
+
+ template <typename t>
+ void g();
+};
+
+template <typename t> // { dg-error "shadows" }
+void A::g()
+{
+ int t = 2; // { dg-error "declaration" }
+}
+
+// (Non-template) Members of template class
+template <typename t> // { dg-error "shadows" }
+struct B
+{
+ void f()
+ {
+ int t = 3; // { dg-error "declaration" }
+ }
+
+ void g();
+};
+
+template <typename t> // { dg-error "shadows" }
+void B<t>::g()
+{
+ int t = 4; // { dg-error "declaration" }
+}
+
+// Template members of template class
+template <typename t> // { dg-error "shadows" }
+struct C
+{
+ template <typename s> // { dg-error "shadows" }
+ void f()
+ {
+ int t = 5; // { dg-error "declaration" }
+ int s = 6; // { dg-error "declaration" }
+ }
+
+ template <typename s>
+ void g();
+};
+
+template <typename t> // { dg-error "shadows" }
+template <typename s> // { dg-error "shadows" }
+void C<t>::g()
+{
+ int t = 7; // { dg-error "declaration" }
+ int s = 8; // { dg-error "declaration" }
+}
diff --git a/gcc/testsuite/g++.dg/tm/pr58516.C b/gcc/testsuite/g++.dg/tm/pr58516.C
new file mode 100644
index 00000000000..b1ada3c8c1d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tm/pr58516.C
@@ -0,0 +1,7 @@
+// { dg-do compile }
+// { dg-options "-std=c++11 -fgnu-tm" }
+
+void foo()
+{
+ __transaction_atomic noexcept(false) {}
+}
diff --git a/gcc/testsuite/g++.dg/tm/pr58635-1.C b/gcc/testsuite/g++.dg/tm/pr58635-1.C
new file mode 100644
index 00000000000..9287e1b8eec
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tm/pr58635-1.C
@@ -0,0 +1,14 @@
+// { dg-do compile }
+// { dg-options "-std=c++11 -fgnu-tm" }
+
+int
+foo (void)
+{
+ return __transaction_atomic noexcept(false) (false);
+}
+
+int
+bar (int i)
+{
+ return __transaction_atomic noexcept(false) (i);
+}
diff --git a/gcc/testsuite/g++.dg/tm/pr58635-2.C b/gcc/testsuite/g++.dg/tm/pr58635-2.C
new file mode 100644
index 00000000000..8a27bc45288
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tm/pr58635-2.C
@@ -0,0 +1,8 @@
+// { dg-do compile }
+// { dg-options "-std=c++11 -fgnu-tm" }
+
+int
+foo (void)
+{
+ return __transaction_atomic noexcept(false) (x); // { dg-error "was not declared in this scope" }
+}
diff --git a/gcc/testsuite/g++.dg/torture/pr49309.C b/gcc/testsuite/g++.dg/torture/pr49309.C
deleted file mode 100644
index f96967ddd34..00000000000
--- a/gcc/testsuite/g++.dg/torture/pr49309.C
+++ /dev/null
@@ -1,16 +0,0 @@
-// PR tree-optimization/49309
-// { dg-do compile }
-// { dg-skip-if "" { *-*-* } { "-flto" } { "" } }
-// { dg-options "-fpreprocessed -fmudflap" }
-
-struct A
-{
- int i;
-
- A();
- A(const A&);
-};
-
-inline void foo(A a) { a = A(); }
-
-void bar() { foo(A()); }
diff --git a/gcc/testsuite/g++.dg/torture/pr58369.C b/gcc/testsuite/g++.dg/torture/pr58369.C
new file mode 100644
index 00000000000..9284e2ca768
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr58369.C
@@ -0,0 +1,109 @@
+// { dg-do compile }
+// Reduced from boost-1.54
+
+int pow(int, int);
+int sqrt(int);
+
+class PolicyA { };
+
+template <class>
+int max_value() { return 0x7fffffff; }
+
+template <class>
+int min_value() { return 1; }
+
+void raise_denorm_error();
+
+template <class T>
+void raise_domain_error(int, int, const T &, const PolicyA &);
+
+template <class>
+int check_overflow(long double p1) {
+ long double __trans_tmp_2 = __builtin_fabsl(p1);
+ if (__trans_tmp_2 > max_value<int>())
+ return 1;
+ return 0;
+}
+
+template <class>
+int check_underflow(long double p1) {
+ if (p1 && (double)p1)
+ return 1;
+ return 0;
+}
+
+template <class>
+int check_denorm(long double p1) {
+ long double __trans_tmp_3 = __builtin_fabsl(p1);
+ if (__trans_tmp_3 < min_value<int>() && (double)p1) {
+ raise_denorm_error();
+ return 1;
+ }
+ return 0;
+}
+
+template <class, class>
+double checked_narrowing_cast(long double p1) {
+ if (check_overflow<int>(p1))
+ return 0;
+ if (check_underflow<int>(p1))
+ return 0;
+ if (check_denorm<int>(p1))
+ return 0;
+ return (double)p1;
+}
+
+long double ellint_rf_imp(long double, long double, long double);
+
+template <typename T, typename Policy>
+T ellint_rj_imp(T p1, T p2, T p3, T p4, Policy &p5) {
+ T value, tolerance, P, S3;
+ if (p4)
+ return 0;
+ if (p3 || p1)
+ raise_domain_error(0, 0, 0, p5);
+ tolerance = pow(0, 0);
+ if (p4) {
+ T q = -p4;
+ {
+ long double q6 = ellint_rj_imp((long double)p1, (long double)(double)p2, (long double)(double)p3, (long double)(int)0, p5);
+ value = checked_narrowing_cast<T, int>(q6);
+ }
+ {
+ long double q7 = ellint_rf_imp((long double)p1, (long double)(double)p2, (long double)(double)p3);
+ value -= checked_narrowing_cast<T, const int>(q7);
+ }
+ value += p1 * p3 + p4 * q;
+ return value;
+ }
+ do {
+ P = p4 / p1;
+ if (0 < tolerance)
+ break;
+ sqrt(p3);
+ } while (1);
+ S3 = P * p2 * 0;
+ value = S3 / p1;
+ return value;
+}
+
+template <typename Policy>
+void ellint_pi_imp4(double, double p3, Policy &p4) {
+ double x, y, z;
+ ellint_rj_imp(x, y, z, p3, p4);
+}
+
+template <typename Policy>
+double ellint_pi_imp5(double, double p3, double p4, Policy &p5) {
+ double x, y, z, p;
+ if (p3 > 0)
+ return 0;
+ ellint_rj_imp(x, y, z, p, p5);
+ ellint_pi_imp4((double)0, p4, p5);
+}
+
+void boost_ellint_3f() {
+ PolicyA p4;
+ ellint_pi_imp5((double)0, (double)0, (double)0, p4);
+}
+
diff --git a/gcc/testsuite/g++.dg/torture/pr58464.C b/gcc/testsuite/g++.dg/torture/pr58464.C
new file mode 100644
index 00000000000..3d9a2279d99
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr58464.C
@@ -0,0 +1,268 @@
+// { dg-do compile }
+
+typedef __SIZE_TYPE__ size_t;
+extern "C" void *memcpy(void *, const void *, size_t);
+void *xmalloc(size_t);
+enum {
+ _sch_isdigit, _sch_isidst, _sch_isidnum
+};
+extern const unsigned _sch_istable[256];
+typedef struct ht cpp_hash_table;
+typedef struct ht_identifier *hashnode;
+enum ht_lookup_option {
+ HT_NO_INSERT
+};
+struct ht {
+ struct cpp_reader *pfile;
+};
+hashnode ht_lookup_with_hash(cpp_hash_table *, unsigned char *, size_t, unsigned, ht_lookup_option);
+typedef unsigned source_location;
+enum cpp_ttype {
+ CPP_OTHER, CPP_STRING, CPP_STRING16, CPP_UTF8STRING
+};
+struct cpp_token {
+ source_location src_loc;
+};
+typedef int cppchar_t;
+struct cpp_options {
+ char user_literals;
+ unsigned warn_literal_suffix;
+};
+enum node_type { };
+struct cpp_hashnode {
+ node_type type:6;
+};
+enum {
+ CPP_DL_ERROR
+};
+enum {
+ CPP_W_LITERAL_SUFFIX
+};
+bool cpp_error_with_line(cpp_reader *, int, source_location, unsigned, ...);
+bool cpp_warning_with_line(cpp_reader *, int, source_location, unsigned, const char *);
+cpp_ttype cpp_userdef_string_add_type(cpp_ttype);
+cpp_ttype cpp_userdef_char_add_type(cpp_ttype);
+typedef unsigned char uchar;
+struct _cpp_buff {
+ _cpp_buff *next;
+ unsigned char *base, *cur, *limit;
+};
+_cpp_buff *_cpp_get_buff(cpp_reader *, size_t);
+void _cpp_release_buff(cpp_reader *, _cpp_buff *);
+unsigned char *_cpp_unaligned_alloc(cpp_reader *, size_t);
+struct lexer_state {
+ unsigned skipping;
+ unsigned angled_headers;
+};
+struct _cpp_line_note {
+ unsigned pos;
+ unsigned type;
+};
+struct cpp_buffer {
+ unsigned char *cur;
+ unsigned char *line_base;
+ _cpp_line_note *notes;
+ unsigned cur_note;
+};
+struct cpp_reader {
+ cpp_buffer *buffer;
+ lexer_state state;
+ _cpp_buff *u_buff;
+ _cpp_buff *free_buffs;
+ ht *hash_table;
+ cpp_options opts;
+};
+static void create_literal(cpp_reader *pfile, cpp_token *, uchar *, unsigned len, cpp_ttype type)
+{
+ uchar *dest = _cpp_unaligned_alloc(pfile, len + 1);
+ dest[len] = type;
+}
+static void bufring_append(cpp_reader *pfile, uchar *base, size_t len, _cpp_buff **first_buff_p, _cpp_buff **last_buff_p)
+{
+ _cpp_buff *first_buff = *first_buff_p;
+ _cpp_buff *last_buff = *last_buff_p;
+ if (!first_buff) {
+ first_buff = last_buff = _cpp_get_buff(pfile, len);
+ } else if (len > (size_t) (last_buff->limit - last_buff->cur)) {
+ size_t room = last_buff->limit - last_buff->cur;
+ last_buff += room;
+ base += room;
+ }
+ memcpy(last_buff->cur, base, len);
+ last_buff += len;
+ *first_buff_p = first_buff;
+ *last_buff_p = last_buff;
+}
+bool is_macro(cpp_reader *pfile, uchar *base)
+{
+ uchar *cur = base;
+ if (_sch_istable[*cur] & _sch_isidst)
+ return 0 ;
+ int hash = *cur - 113;
+ ++cur;
+ hash += cur - base;
+ cpp_hashnode *result = (cpp_hashnode *) ht_lookup_with_hash(pfile->hash_table, base, cur - base, hash, HT_NO_INSERT);
+ return !result ? 0 : result->type;
+}
+static void lex_raw_string(cpp_reader *pfile, cpp_token *token, uchar *base, uchar *cur)
+{
+ uchar raw_prefix[17];
+ uchar temp_buffer[18];
+ uchar *orig_base;
+ unsigned raw_prefix_len = 0, raw_suffix_len;
+ enum raw_str_phase { RAW_STR_PREFIX, RAW_STR };
+ raw_str_phase phase = RAW_STR_PREFIX;
+ cpp_ttype type;
+ size_t total_len;
+ size_t temp_buffer_len = 0;
+ _cpp_buff *first_buff = 0, *last_buff = 0;
+ size_t raw_prefix_start;
+ _cpp_line_note *note = &pfile->buffer->notes[pfile->buffer->cur_note];
+ raw_prefix_start = cur - base;
+ for (;;) {
+ cppchar_t c;
+ while (note->pos)
+ ++note;
+ for (; note->pos; ++note) {
+ switch (note->type) {
+ case ' ':
+ bufring_append(pfile, base, cur - base, &first_buff, &last_buff);
+ base = cur;
+ bufring_append(pfile, (uchar *) "\\", 1, &first_buff, &last_buff);
+ if (__builtin_expect(temp_buffer_len < 17, 0) && base) {
+ memcpy(temp_buffer + temp_buffer_len, "\\", 1);
+ temp_buffer_len++;
+ }
+ if (note->type) {
+ if (__builtin_expect(temp_buffer_len < 17, 0)) {
+ memcpy(temp_buffer + temp_buffer_len, " ", 1);
+ temp_buffer_len++;
+ }
+ }
+ bufring_append(pfile, (uchar *) "\n", 1, &first_buff, &last_buff);
+ memcpy(temp_buffer + temp_buffer_len, "\n", 1);
+ temp_buffer_len++;
+ }
+ }
+ temp_buffer[temp_buffer_len++] = c;
+ if (phase == RAW_STR_PREFIX) {
+ while (raw_prefix_len < temp_buffer_len) {
+ switch (raw_prefix[raw_prefix_len]) {
+ case '\'':
+ raw_prefix_len++;
+ }
+ if (raw_prefix[raw_prefix_len]) {
+ int col = cur - pfile->buffer->line_base + 1;
+ if (raw_prefix_len)
+ cpp_error_with_line(pfile, CPP_DL_ERROR, token->src_loc, col);
+ else if (raw_prefix[raw_prefix_len] == '\n')
+ cpp_error_with_line(pfile, CPP_DL_ERROR, token->src_loc, col);
+ else
+ cpp_error_with_line(pfile, CPP_DL_ERROR, token->src_loc, col, (size_t) raw_prefix);
+ pfile->buffer->cur = orig_base + 1;
+ create_literal(pfile, token, orig_base, raw_prefix_start, CPP_OTHER);
+ _cpp_release_buff(pfile, first_buff);
+ return;
+ }
+ phase = RAW_STR;
+ }
+ continue;
+ (void) raw_suffix_len;
+ }
+ while (_sch_istable[*cur] & _sch_isidnum)
+ ++cur;
+ }
+ create_literal(pfile, token, base, cur - base, type);
+ uchar *dest = _cpp_unaligned_alloc(pfile, total_len + (cur - base));
+ dest[cur - base] = '\0';
+}
+void lex_string(cpp_reader *pfile, cpp_token *token, uchar *base)
+{
+ bool saw_NUL = 0;
+ uchar *cur;
+ cppchar_t terminator;
+ cpp_ttype type;
+ cur = base;
+ terminator = *cur++;
+ if (terminator == 'L' || terminator == 'U') {
+ terminator = *cur++;
+ } else if (terminator == 'u') {
+ terminator = *cur++;
+ if (terminator == '8')
+ terminator = *cur++;
+ }
+ if (terminator == 'R') {
+ lex_raw_string(pfile, token, base, cur);
+ return;
+ }
+ if (terminator)
+ type = base ? (base[1] ? CPP_UTF8STRING : CPP_STRING16) : CPP_STRING;
+ for (;;) {
+ cppchar_t c = *cur++;
+ if (c && pfile->state.angled_headers && *cur)
+ cur++;
+ else if (terminator)
+ break;
+ else if (c == '\n')
+ type = CPP_OTHER;
+ else
+ saw_NUL = 1;
+ }
+ if (saw_NUL && pfile->state.skipping)
+ if (pfile->opts.user_literals) {
+ if (is_macro(pfile, cur))
+ if (pfile->opts.warn_literal_suffix)
+ cpp_warning_with_line(pfile, CPP_W_LITERAL_SUFFIX, token->src_loc, 0, "invalid suffix on literal; C++11 requires ");
+ if (_sch_istable[*cur] & _sch_isidst) {
+ type = cpp_userdef_char_add_type(type);
+ type = cpp_userdef_string_add_type(type);
+ ++cur;
+ while (_sch_istable[*cur] & _sch_isidnum)
+ ++cur;
+ }
+ }
+ pfile->buffer->cur = cur;
+ create_literal(pfile, token, base, cur - base, type);
+}
+_cpp_buff *new_buff(size_t len)
+{
+ _cpp_buff *result;
+ unsigned char *base;
+ if (len < 8000)
+ len = 8000;
+ base = (unsigned char *) xmalloc(sizeof(char) * (len + sizeof(_cpp_buff)));
+ result = (_cpp_buff *) (base + len);
+ result->cur = base;
+ return result;
+}
+void _cpp_release_buff(cpp_reader *pfile, _cpp_buff *buff)
+{
+ _cpp_buff *end = buff;
+ while (end->next)
+ end = end->next;
+ end->next = pfile->free_buffs;
+}
+_cpp_buff *_cpp_get_buff(cpp_reader *pfile, size_t min_size)
+{
+ _cpp_buff *result, **p = &pfile->free_buffs;
+ for (;;) {
+ size_t size;
+ if (*p)
+ return new_buff(min_size);
+ size = result->limit - result->base;
+ if (size && size + min_size * 3 / 2)
+ return result;
+ }
+}
+unsigned char *_cpp_unaligned_alloc(cpp_reader *pfile, size_t len)
+{
+ _cpp_buff *buff = pfile->u_buff;
+ unsigned char *result = buff->cur;
+ if (len > (size_t) (buff->limit - result)) {
+ buff = _cpp_get_buff(pfile, len);
+ buff->next = pfile->u_buff;
+ result = buff->cur;
+ }
+ buff->cur = result + len;
+ return result;
+}
diff --git a/gcc/testsuite/g++.dg/torture/pr58552.C b/gcc/testsuite/g++.dg/torture/pr58552.C
new file mode 100644
index 00000000000..17c0d1cf624
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr58552.C
@@ -0,0 +1,29 @@
+// { dg-do compile }
+// { dg-additional-options "-fcompare-debug" }
+
+extern void fancy_abort () __attribute__ ((__noreturn__));
+extern "C" {
+ struct __jmp_buf_tag { };
+ typedef struct __jmp_buf_tag jmp_buf[1];
+ extern int _setjmp (struct __jmp_buf_tag __env[1]) throw ();
+}
+extern void *gfc_state_stack;
+static jmp_buf eof_buf;
+static void push_state ()
+{
+ if (!gfc_state_stack)
+ fancy_abort ();
+}
+bool gfc_parse_file (void)
+{
+ int seen_program=0;
+ if (_setjmp (eof_buf))
+ return false;
+ if (seen_program)
+ goto duplicate_main;
+ seen_program = 1;
+ push_state ();
+ push_state ();
+duplicate_main:
+ return true;
+}
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr19476-1.C b/gcc/testsuite/g++.dg/tree-ssa/pr19476-1.C
new file mode 100644
index 00000000000..cbdad90d16b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tree-ssa/pr19476-1.C
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-ccp1" } */
+
+// See pr19476-5.C for a version without including <new>.
+#include <new>
+
+int f(){
+ return 33 + (0 == new(std::nothrow) int);
+}
+int g(){
+ return 42 + (0 == new int[50]);
+}
+
+/* { dg-final { scan-tree-dump "return 42" "ccp1" } } */
+/* { dg-final { scan-tree-dump-not "return 33" "ccp1" } } */
+/* { dg-final { cleanup-tree-dump "ccp1" } } */
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr19476-2.C b/gcc/testsuite/g++.dg/tree-ssa/pr19476-2.C
new file mode 100644
index 00000000000..70002dbb5ea
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tree-ssa/pr19476-2.C
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+#include <new>
+
+int f(){
+ int *p = new(std::nothrow) int;
+ return 33 + (0 == p);
+}
+int g(){
+ int *p = new int[50];
+ return 42 + (0 == p);
+}
+
+/* { dg-final { scan-tree-dump "return 42" "optimized" } } */
+/* { dg-final { scan-tree-dump-not "return 33" "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr19476-3.C b/gcc/testsuite/g++.dg/tree-ssa/pr19476-3.C
new file mode 100644
index 00000000000..051866e13c1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tree-ssa/pr19476-3.C
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fcheck-new -fdump-tree-optimized" } */
+
+#include <new>
+
+int g(){
+ return 42 + (0 == new int);
+}
+
+/* { dg-final { scan-tree-dump-not "return 42" "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr19476-4.C b/gcc/testsuite/g++.dg/tree-ssa/pr19476-4.C
new file mode 100644
index 00000000000..8ae16140d64
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tree-ssa/pr19476-4.C
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fno-delete-null-pointer-checks -fdump-tree-optimized" } */
+
+#include <new>
+
+int g(){
+ return 42 + (0 == new int);
+}
+
+/* { dg-final { scan-tree-dump-not "return 42" "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr19476-5.C b/gcc/testsuite/g++.dg/tree-ssa/pr19476-5.C
new file mode 100644
index 00000000000..bec0bb58b6c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tree-ssa/pr19476-5.C
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-ccp1" } */
+
+// See pr19476-1.C for a version that includes <new>.
+
+int g(){
+ return 42 + (0 == new int[50]);
+}
+
+/* { dg-final { scan-tree-dump "return 42" "ccp1" } } */
+/* { dg-final { cleanup-tree-dump "ccp1" } } */
diff --git a/gcc/testsuite/g++.dg/ubsan/cxx1y-vla.C b/gcc/testsuite/g++.dg/ubsan/cxx1y-vla.C
new file mode 100644
index 00000000000..350db3f3473
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ubsan/cxx1y-vla.C
@@ -0,0 +1,13 @@
+/* { dg-do run } */
+/* { dg-options "-fsanitize=vla-bound -w -std=c++1y" } */
+/* { dg-shouldfail "ubsan" } */
+
+int
+main (void)
+{
+ int y = -18;
+ int a[y];
+ return 0;
+}
+
+/* { dg-output "terminate called after throwing an instance" } */
diff --git a/gcc/testsuite/g++.dg/vect/pr33426-ivdep-2.cc b/gcc/testsuite/g++.dg/vect/pr33426-ivdep-2.cc
new file mode 100644
index 00000000000..3d042301f96
--- /dev/null
+++ b/gcc/testsuite/g++.dg/vect/pr33426-ivdep-2.cc
@@ -0,0 +1,39 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_float } */
+/* { dg-additional-options "-O3 -fopt-info-vec-optimized -fdump-tree-original -fdump-tree-gimple" } */
+
+/* PR other/33426 */
+/* Testing whether #pragma ivdep is working. */
+
+void foo(int n, int *a, int *b, int *c) {
+ int i;
+ i = 0;
+#pragma GCC ivdep
+ while(i < n)
+ {
+ a[i] = b[i] + c[i];
+ ++i;
+ }
+}
+
+void bar(int n, int *a, int *b, int *c) {
+ int i;
+ i = 0;
+#pragma GCC ivdep
+ do
+ {
+ a[i] = b[i] + c[i];
+ ++i;
+ }
+ while(i < n);
+}
+
+/* { dg-message "loop vectorized" "" { target *-*-* } 0 } */
+/* { dg-bogus " version" "" { target *-*-* } 0 } */
+/* { dg-bogus " alias" "" { target *-*-* } 0 } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
+
+/* { dg-final { scan-tree-dump-times "ANNOTATE_EXPR " 2 "original" } } */
+/* { dg-final { cleanup-tree-dump "original" } } */
+/* { dg-final { scan-tree-dump-times "ANNOTATE " 2 "gimple" } } */
+/* { dg-final { cleanup-tree-dump "gimple" } } */
diff --git a/gcc/testsuite/g++.dg/vect/pr33426-ivdep-3.cc b/gcc/testsuite/g++.dg/vect/pr33426-ivdep-3.cc
new file mode 100644
index 00000000000..35de3b285e7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/vect/pr33426-ivdep-3.cc
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_float } */
+/* { dg-additional-options "-std=c++11 -O3 -fopt-info-vec-optimized -fdump-tree-original -fdump-tree-gimple" } */
+
+/* PR other/33426 */
+/* Testing whether #pragma ivdep is working. */
+
+int ar[100];
+
+void foo(int *a) {
+#pragma GCC ivdep
+ for (auto &i : ar) {
+ i *= *a;
+ }
+}
+
+/* { dg-message "loop vectorized" "" { target *-*-* } 0 } */
+/* { dg-bogus " version" "" { target *-*-* } 0 } */
+/* { dg-bogus " alias" "" { target *-*-* } 0 } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
+
+/* { dg-final { scan-tree-dump-times "ANNOTATE_EXPR " 1 "original" } } */
+/* { dg-final { cleanup-tree-dump "original" } } */
+/* { dg-final { scan-tree-dump-times "ANNOTATE " 1 "gimple" } } */
+/* { dg-final { cleanup-tree-dump "gimple" } } */
diff --git a/gcc/testsuite/g++.dg/vect/pr33426-ivdep-4.cc b/gcc/testsuite/g++.dg/vect/pr33426-ivdep-4.cc
new file mode 100644
index 00000000000..8850505ac1f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/vect/pr33426-ivdep-4.cc
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_float } */
+/* { dg-additional-options "-std=c++11 -O3 -fopt-info-vec-optimized -fdump-tree-original -fdump-tree-gimple" } */
+
+/* PR other/33426 */
+/* Testing whether #pragma ivdep is working. */
+
+#include <vector>
+
+template<class T, class T2>
+void Loop(T *b, T2 c) {
+#pragma GCC ivdep
+ for (auto &i : *b) {
+ i *= *c;
+ }
+}
+
+void foo(std::vector<int> *ar, int *b) {
+ Loop<std::vector<int>, int*>(ar, b);
+}
+
+/* { dg-message "loop vectorized" "" { target *-*-* } 0 } */
+/* FIXME: dg-bogus " version" "" { target *-*-* } 0 */
+/* FIXME: dg-bogus " alias" "" { target *-*-* } 0 */
+/* { dg-final { cleanup-tree-dump "vect" } } */
+
+/* { dg-final { scan-tree-dump-times "ANNOTATE_EXPR " 1 "original" } } */
+/* { dg-final { cleanup-tree-dump "original" } } */
+/* { dg-final { scan-tree-dump-times "ANNOTATE " 1 "gimple" } } */
+/* { dg-final { cleanup-tree-dump "gimple" } } */
diff --git a/gcc/testsuite/g++.dg/vect/pr33426-ivdep.cc b/gcc/testsuite/g++.dg/vect/pr33426-ivdep.cc
new file mode 100644
index 00000000000..9715e9423f4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/vect/pr33426-ivdep.cc
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_float } */
+/* { dg-additional-options "-O3 -fopt-info-vec-optimized" } */
+
+/* PR other/33426 */
+/* Testing whether #pragma ivdep is working. */
+
+void foo(int n, int *a, int *b, int *c, int *d, int *e) {
+ int i;
+#pragma GCC ivdep
+ for (i = 0; i < n; ++i) {
+ a[i] = b[i] + c[i];
+ }
+}
+
+/* { dg-message "loop vectorized" "" { target *-*-* } 0 } */
+/* { dg-bogus " version" "" { target *-*-* } 0 } */
+/* { dg-bogus " alias" "" { target *-*-* } 0 } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
diff --git a/gcc/testsuite/g++.dg/vect/pr58513.cc b/gcc/testsuite/g++.dg/vect/pr58513.cc
new file mode 100644
index 00000000000..08a175c8e74
--- /dev/null
+++ b/gcc/testsuite/g++.dg/vect/pr58513.cc
@@ -0,0 +1,13 @@
+// { dg-do compile }
+// { dg-require-effective-target vect_int }
+
+static int op (const int& x, const int& y) { return x + y; }
+
+void foo(int* a)
+{
+ for (int i = 0; i < 1000; ++i)
+ a[i] = op(a[i], 1);
+}
+
+// { dg-final { scan-tree-dump "vectorized 1 loops" "vect" } }
+// { dg-final { cleanup-tree-dump "vect" } }
diff --git a/gcc/testsuite/g++.dg/vect/slp-pr56812.cc b/gcc/testsuite/g++.dg/vect/slp-pr56812.cc
index e98abc89df0..9c0b2b8b78b 100644
--- a/gcc/testsuite/g++.dg/vect/slp-pr56812.cc
+++ b/gcc/testsuite/g++.dg/vect/slp-pr56812.cc
@@ -1,7 +1,7 @@
/* { dg-do compile } */
/* { dg-require-effective-target vect_float } */
/* { dg-require-effective-target vect_hw_misalign } */
-/* { dg-additional-options "-O3 -funroll-loops -fvect-cost-model" } */
+/* { dg-additional-options "-O3 -funroll-loops -fvect-cost-model=dynamic" } */
class mydata {
public:
diff --git a/gcc/testsuite/g++.dg/warn/pr33738.C b/gcc/testsuite/g++.dg/warn/pr33738.C
index e84fece13f6..60ee0b48412 100644
--- a/gcc/testsuite/g++.dg/warn/pr33738.C
+++ b/gcc/testsuite/g++.dg/warn/pr33738.C
@@ -18,6 +18,7 @@ int main() {
if (a2 == -1) { // { dg-warning "always false due" }
link_error ();
}
+ a2 = static_cast<Alpha>(GetM1());
if (-1 == a2) { // { dg-warning "always false due" }
link_error ();
}
diff --git a/gcc/testsuite/g++.dg/warn/wdate-time.C b/gcc/testsuite/g++.dg/warn/wdate-time.C
new file mode 100644
index 00000000000..0ff27b4cd6f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/wdate-time.C
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-Wdate-time" } */
+
+const char time[] = __TIME__; /* { dg-warning "might prevent reproducible builds" } */
+const char date[] = __DATE__; /* { dg-warning "might prevent reproducible builds" } */
+const char timestamp[] = __TIMESTAMP__; /* { dg-warning "might prevent reproducible builds" } */
diff --git a/gcc/testsuite/g++.old-deja/g++.mike/misc9.C b/gcc/testsuite/g++.old-deja/g++.mike/misc9.C
index 3d8858cf64a..7b9a86cbf4a 100644
--- a/gcc/testsuite/g++.old-deja/g++.mike/misc9.C
+++ b/gcc/testsuite/g++.old-deja/g++.mike/misc9.C
@@ -8,6 +8,6 @@ class bee {
class foo {
public:
- int bee::bar; // { dg-error "not derived" } you cannot do this
+ int bee::bar; // { dg-error "invalid use" } you cannot do this
int me();
};
diff --git a/gcc/testsuite/gcc.c-torture/compile/20010327-1.c b/gcc/testsuite/gcc.c-torture/compile/20010327-1.c
index ce68f78df1d..7e9c0c73a02 100644
--- a/gcc/testsuite/gcc.c-torture/compile/20010327-1.c
+++ b/gcc/testsuite/gcc.c-torture/compile/20010327-1.c
@@ -1,7 +1,4 @@
-/* { dg-skip-if "non-SI pointers" { m32c-*-* } { "*" } { "" } } */
-/* { dg-skip-if "HI mode pointer for avr" { "avr-*-*" } { "*" } { "" } } */
-/* { dg-skip-if "HI mode pointer for pdp11" { "pdp11-*-*" } { "*" } { "" } } */
-/* { dg-skip-if "non-SI pointers for w64" { "x86_64-*-mingw*" } { "*" } { "" } } */
+/* { dg-require-effective-target ptr32plus } */
/* This testcase tests whether GCC can produce static initialized data
that references addresses of size 'unsigned long', even if that's not
diff --git a/gcc/testsuite/gcc.c-torture/compile/20020604-1.c b/gcc/testsuite/gcc.c-torture/compile/20020604-1.c
index 9486583e973..d2e186a7182 100644
--- a/gcc/testsuite/gcc.c-torture/compile/20020604-1.c
+++ b/gcc/testsuite/gcc.c-torture/compile/20020604-1.c
@@ -1,7 +1,6 @@
/* { dg-do assemble } */
-/* { dg-skip-if "The array is too big" { "avr-*-*" "pdp11-*-*" } { "*" } { "" } } */
+/* { dg-require-effective-target ptr32plus } */
/* { dg-xfail-if "The array too big" { "h8300-*-*" } { "-mno-h" "-mn" } { "" } } */
-/* { dg-skip-if "" { m32c-*-* } { } { } } */
/* PR c/6957
This testcase ICEd at -O2 on IA-32, because
diff --git a/gcc/testsuite/gcc.c-torture/compile/20080625-1.c b/gcc/testsuite/gcc.c-torture/compile/20080625-1.c
index 16def2c8a37..4b3b7c2c142 100644
--- a/gcc/testsuite/gcc.c-torture/compile/20080625-1.c
+++ b/gcc/testsuite/gcc.c-torture/compile/20080625-1.c
@@ -1,4 +1,5 @@
-/* { dg-skip-if "too much data" { "avr-*-*" "m32c-*-*" "pdp11-*-*" } { "*" } { "" } } */
+/* { dg-require-effective-target int32plus } */
+
struct peakbufStruct {
unsigned int lnum [5000];
int lscan [5000][4000];
diff --git a/gcc/testsuite/gcc.c-torture/compile/990617-1.c b/gcc/testsuite/gcc.c-torture/compile/990617-1.c
index e9d3cf336fc..350b96a61c8 100644
--- a/gcc/testsuite/gcc.c-torture/compile/990617-1.c
+++ b/gcc/testsuite/gcc.c-torture/compile/990617-1.c
@@ -1,7 +1,5 @@
-/* 0x70000000 is too large a constant to become a pointer on
- xstormy16. */
/* { dg-do assemble } */
-/* { dg-xfail-if "" { xstormy16-*-* } { "*" } { "" } } */
+/* { dg-require-effective-target ptr32plus } */
int main()
{
diff --git a/gcc/testsuite/gcc.c-torture/compile/calls.c b/gcc/testsuite/gcc.c-torture/compile/calls.c
index 1582c0e92fa..1241058a073 100644
--- a/gcc/testsuite/gcc.c-torture/compile/calls.c
+++ b/gcc/testsuite/gcc.c-torture/compile/calls.c
@@ -1,3 +1,4 @@
+/* { dg-require-effective-target ptr32plus } */
typedef void *(*T)(void);
f1 ()
{
diff --git a/gcc/testsuite/gcc.c-torture/compile/limits-externdecl.c b/gcc/testsuite/gcc.c-torture/compile/limits-externdecl.c
index 6899d4b097d..17afe730883 100644
--- a/gcc/testsuite/gcc.c-torture/compile/limits-externdecl.c
+++ b/gcc/testsuite/gcc.c-torture/compile/limits-externdecl.c
@@ -1,3 +1,4 @@
+/* { dg-require-effective-target int32plus } */
/* Inspired by the test case for PR middle-end/52640. */
typedef struct
@@ -52,4 +53,4 @@ LIM5 (X);
REFERENCE references[] = {
LIM5 (X)
0
-}; /* { dg-error "size of array is too large" "" { target avr-*-* } } */
+};
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr41181.c b/gcc/testsuite/gcc.c-torture/compile/pr41181.c
index 5fafb020ea5..e1e48063a94 100644
--- a/gcc/testsuite/gcc.c-torture/compile/pr41181.c
+++ b/gcc/testsuite/gcc.c-torture/compile/pr41181.c
@@ -1,3 +1,4 @@
+/* { dg-require-effective-target ptr32plus } */
/* { dg-skip-if "The array is too big" { "avr-*-*" "pdp11-*-*" } { "*" } { "" } } */
char paths[1024];
static void x264_slicetype_path(char (*best_paths)[250], int n, int length)
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr55955.c b/gcc/testsuite/gcc.c-torture/compile/pr55955.c
index 2656ffb94fb..cd96d56e8bb 100644
--- a/gcc/testsuite/gcc.c-torture/compile/pr55955.c
+++ b/gcc/testsuite/gcc.c-torture/compile/pr55955.c
@@ -1,3 +1,4 @@
+/* { dg-require-effective-target int32plus } */
/* PR tree-optimization/55955 */
int b;
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr58775.c b/gcc/testsuite/gcc.c-torture/compile/pr58775.c
new file mode 100644
index 00000000000..8de06ddc05c
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr58775.c
@@ -0,0 +1,26 @@
+/* PR tree-optimization/58775 */
+
+void bar (void);
+
+void
+foo (char *x)
+{
+ char a;
+ _Bool b, c, d, e, f, g, h, i, j, k, l, m;
+
+ a = *x;
+ b = a == 100;
+ c = a == 105;
+ d = b | c;
+ e = a != 111;
+ f = !d;
+ g = e & f;
+ h = a != 117;
+ i = g & h;
+ j = a != 120;
+ k = i & j;
+ l = a != 88;
+ m = k & l;
+ if (m == 0)
+ bar ();
+}
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr58946.c b/gcc/testsuite/gcc.c-torture/compile/pr58946.c
new file mode 100644
index 00000000000..0ec5eba16f0
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr58946.c
@@ -0,0 +1,20 @@
+/* PR tree-optimization/58946 */
+
+int
+foo (unsigned int c)
+{
+ unsigned int d, e, f;
+ if ((int) c < 0)
+ d = 0;
+ else
+ d = c;
+ if (d == 0)
+ e = __INT_MAX__ + 1U;
+ else
+ e = d;
+ if ((int) e < 0)
+ f = 0;
+ else
+ f = e;
+ return f;
+}
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr58970-1.c b/gcc/testsuite/gcc.c-torture/compile/pr58970-1.c
new file mode 100644
index 00000000000..45aad2b2e65
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr58970-1.c
@@ -0,0 +1,11 @@
+/* PR middle-end/58970 */
+
+struct T { int b : 1; };
+struct S { struct T t[1]; };
+
+void
+foo (int x, struct S *s)
+{
+ if (x == -1)
+ s->t[x].b = 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr58970-2.c b/gcc/testsuite/gcc.c-torture/compile/pr58970-2.c
new file mode 100644
index 00000000000..3103b31e179
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr58970-2.c
@@ -0,0 +1,11 @@
+/* PR middle-end/58970 */
+
+struct T { char a : 8; char b : 1; };
+struct S { char x; struct T t[1]; };
+
+void
+foo (int x, struct S *s)
+{
+ if (x == -1)
+ s->t[x].b = 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr58978.c b/gcc/testsuite/gcc.c-torture/compile/pr58978.c
new file mode 100644
index 00000000000..721801da16b
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr58978.c
@@ -0,0 +1,16 @@
+/* PR tree-optimization/58978 */
+
+int
+foo (int x)
+{
+ switch (x)
+ {
+ case 0:
+ case 1:
+ case 9:
+ break;
+ default:
+ __builtin_unreachable ();
+ }
+ return x;
+}
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr58997.c b/gcc/testsuite/gcc.c-torture/compile/pr58997.c
new file mode 100644
index 00000000000..2c7a0f82c8a
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr58997.c
@@ -0,0 +1,19 @@
+/* PR rtl-optimization/58997 */
+
+int a, b, c, e;
+short d;
+char h;
+
+void
+foo ()
+{
+ while (b)
+ {
+ d = a ? c : 1 % a;
+ c = d;
+ h = d;
+ if (!h)
+ while (e)
+ ;
+ }
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/20030125-1.c b/gcc/testsuite/gcc.c-torture/execute/20030125-1.c
index 8eb9a4211a8..28cfbd10b4c 100644
--- a/gcc/testsuite/gcc.c-torture/execute/20030125-1.c
+++ b/gcc/testsuite/gcc.c-torture/execute/20030125-1.c
@@ -44,11 +44,11 @@ __attribute__ ((noinline))
double
sin(double a)
{
- abort ();
+ return a;
}
__attribute__ ((noinline))
float
sinf(float a)
{
- return a;
+ abort ();
}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strncmp-2.c b/gcc/testsuite/gcc.c-torture/execute/builtins/strncmp-2.c
index fe3462724ea..508b2d3309a 100644
--- a/gcc/testsuite/gcc.c-torture/execute/builtins/strncmp-2.c
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strncmp-2.c
@@ -12,7 +12,7 @@ extern int strncmp (const char *, const char *, size_t);
void
main_test (void)
{
-#if !defined(__OPTIMIZE__) || ((defined(__i386__) || defined (__x86_64__)) && !defined(__OPTIMIZE_SIZE__))
+#if !defined(__OPTIMIZE__) || ((defined(__sh__) || defined(__i386__) || defined (__x86_64__)) && !defined(__OPTIMIZE_SIZE__))
/* These tests work on platforms which support cmpstrsi. We test it
at -O0 on all platforms to ensure the strncmp logic is correct. */
const char *const s1 = "hello world";
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr58564.c b/gcc/testsuite/gcc.c-torture/execute/pr58564.c
new file mode 100644
index 00000000000..967ee95d4ab
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr58564.c
@@ -0,0 +1,14 @@
+/* PR middle-end/58564 */
+
+extern void abort (void);
+int a, b;
+short *c, **d = &c;
+
+int
+main ()
+{
+ b = (0, 0 > ((&c == d) & (1 && (a ^ 1)))) | 0U;
+ if (b != 0)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr58570.c b/gcc/testsuite/gcc.c-torture/execute/pr58570.c
new file mode 100644
index 00000000000..6d5116d9ea5
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr58570.c
@@ -0,0 +1,22 @@
+#pragma pack(1)
+struct S
+{
+ int f0:15;
+ int f1:29;
+};
+
+int e = 1, i;
+static struct S d[6];
+
+int
+main (void)
+{
+ if (e)
+ {
+ d[i].f0 = 1;
+ d[i].f1 = 1;
+ }
+ if (d[0].f1 != 1)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr58574.c b/gcc/testsuite/gcc.c-torture/execute/pr58574.c
new file mode 100644
index 00000000000..44827eb7819
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr58574.c
@@ -0,0 +1,219 @@
+/* PR target/58574 */
+
+__attribute__((noinline, noclone)) double
+foo (double x)
+{
+ double t;
+ switch ((int) x)
+ {
+ case 0:
+ t = 2 * x - 1;
+ return 0.70878e-3 + (0.71234e-3 + (0.35779e-5 + (0.17403e-7 + (0.81710e-10 + (0.36885e-12 + 0.15917e-14 * t) * t) * t) * t) * t) * t;
+ case 1:
+ t = 2 * x - 3;
+ return 0.21479e-2 + (0.72686e-3 + (0.36843e-5 + (0.18071e-7 + (0.85496e-10 + (0.38852e-12 + 0.16868e-14 * t) * t) * t) * t) * t) * t;
+ case 2:
+ t = 2 * x - 5;
+ return 0.36165e-2 + (0.74182e-3 + (0.37948e-5 + (0.18771e-7 + (0.89484e-10 + (0.40935e-12 + 0.17872e-14 * t) * t) * t) * t) * t) * t;
+ case 3:
+ t = 2 * x - 7;
+ return 0.51154e-2 + (0.75722e-3 + (0.39096e-5 + (0.19504e-7 + (0.93687e-10 + (0.43143e-12 + 0.18939e-14 * t) * t) * t) * t) * t) * t;
+ case 4:
+ t = 2 * x - 9;
+ return 0.66457e-2 + (0.77310e-3 + (0.40289e-5 + (0.20271e-7 + (0.98117e-10 + (0.45484e-12 + 0.20076e-14 * t) * t) * t) * t) * t) * t;
+ case 5:
+ t = 2 * x - 11;
+ return 0.82082e-2 + (0.78946e-3 + (0.41529e-5 + (0.21074e-7 + (0.10278e-9 + (0.47965e-12 + 0.21285e-14 * t) * t) * t) * t) * t) * t;
+ case 6:
+ t = 2 * x - 13;
+ return 0.98039e-2 + (0.80633e-3 + (0.42819e-5 + (0.21916e-7 + (0.10771e-9 + (0.50595e-12 + 0.22573e-14 * t) * t) * t) * t) * t) * t;
+ case 7:
+ t = 2 * x - 15;
+ return 0.11433e-1 + (0.82372e-3 + (0.44160e-5 + (0.22798e-7 + (0.11291e-9 + (0.53386e-12 + 0.23944e-14 * t) * t) * t) * t) * t) * t;
+ case 8:
+ t = 2 * x - 17;
+ return 0.13099e-1 + (0.84167e-3 + (0.45555e-5 + (0.23723e-7 + (0.11839e-9 + (0.56346e-12 + 0.25403e-14 * t) * t) * t) * t) * t) * t;
+ case 9:
+ t = 2 * x - 19;
+ return 0.14800e-1 + (0.86018e-3 + (0.47008e-5 + (0.24694e-7 + (0.12418e-9 + (0.59486e-12 + 0.26957e-14 * t) * t) * t) * t) * t) * t;
+ case 10:
+ t = 2 * x - 21;
+ return 0.16540e-1 + (0.87928e-3 + (0.48520e-5 + (0.25711e-7 + (0.13030e-9 + (0.62820e-12 + 0.28612e-14 * t) * t) * t) * t) * t) * t;
+ case 11:
+ t = 2 * x - 23;
+ return 0.18318e-1 + (0.89900e-3 + (0.50094e-5 + (0.26779e-7 + (0.13675e-9 + (0.66358e-12 + 0.30375e-14 * t) * t) * t) * t) * t) * t;
+ case 12:
+ t = 2 * x - 25;
+ return 0.20136e-1 + (0.91936e-3 + (0.51734e-5 + (0.27900e-7 + (0.14357e-9 + (0.70114e-12 + 0.32252e-14 * t) * t) * t) * t) * t) * t;
+ case 13:
+ t = 2 * x - 27;
+ return 0.21996e-1 + (0.94040e-3 + (0.53443e-5 + (0.29078e-7 + (0.15078e-9 + (0.74103e-12 + 0.34251e-14 * t) * t) * t) * t) * t) * t;
+ case 14:
+ t = 2 * x - 29;
+ return 0.23898e-1 + (0.96213e-3 + (0.55225e-5 + (0.30314e-7 + (0.15840e-9 + (0.78340e-12 + 0.36381e-14 * t) * t) * t) * t) * t) * t;
+ case 15:
+ t = 2 * x - 31;
+ return 0.25845e-1 + (0.98459e-3 + (0.57082e-5 + (0.31613e-7 + (0.16646e-9 + (0.82840e-12 + 0.38649e-14 * t) * t) * t) * t) * t) * t;
+ case 16:
+ t = 2 * x - 33;
+ return 0.27837e-1 + (0.10078e-2 + (0.59020e-5 + (0.32979e-7 + (0.17498e-9 + (0.87622e-12 + 0.41066e-14 * t) * t) * t) * t) * t) * t;
+ case 17:
+ t = 2 * x - 35;
+ return 0.29877e-1 + (0.10318e-2 + (0.61041e-5 + (0.34414e-7 + (0.18399e-9 + (0.92703e-12 + 0.43639e-14 * t) * t) * t) * t) * t) * t;
+ case 18:
+ t = 2 * x - 37;
+ return 0.31965e-1 + (0.10566e-2 + (0.63151e-5 + (0.35924e-7 + (0.19353e-9 + (0.98102e-12 + 0.46381e-14 * t) * t) * t) * t) * t) * t;
+ case 19:
+ t = 2 * x - 39;
+ return 0.34104e-1 + (0.10823e-2 + (0.65354e-5 + (0.37512e-7 + (0.20362e-9 + (0.10384e-11 + 0.49300e-14 * t) * t) * t) * t) * t) * t;
+ case 20:
+ t = 2 * x - 41;
+ return 0.36295e-1 + (0.11089e-2 + (0.67654e-5 + (0.39184e-7 + (0.21431e-9 + (0.10994e-11 + 0.52409e-14 * t) * t) * t) * t) * t) * t;
+ case 21:
+ t = 2 * x - 43;
+ return 0.38540e-1 + (0.11364e-2 + (0.70058e-5 + (0.40943e-7 + (0.22563e-9 + (0.11642e-11 + 0.55721e-14 * t) * t) * t) * t) * t) * t;
+ case 22:
+ t = 2 * x - 45;
+ return 0.40842e-1 + (0.11650e-2 + (0.72569e-5 + (0.42796e-7 + (0.23761e-9 + (0.12332e-11 + 0.59246e-14 * t) * t) * t) * t) * t) * t;
+ case 23:
+ t = 2 * x - 47;
+ return 0.43201e-1 + (0.11945e-2 + (0.75195e-5 + (0.44747e-7 + (0.25030e-9 + (0.13065e-11 + 0.63000e-14 * t) * t) * t) * t) * t) * t;
+ case 24:
+ t = 2 * x - 49;
+ return 0.45621e-1 + (0.12251e-2 + (0.77941e-5 + (0.46803e-7 + (0.26375e-9 + (0.13845e-11 + 0.66996e-14 * t) * t) * t) * t) * t) * t;
+ case 25:
+ t = 2 * x - 51;
+ return 0.48103e-1 + (0.12569e-2 + (0.80814e-5 + (0.48969e-7 + (0.27801e-9 + (0.14674e-11 + 0.71249e-14 * t) * t) * t) * t) * t) * t;
+ case 26:
+ t = 2 * x - 59;
+ return 0.58702e-1 + (0.13962e-2 + (0.93714e-5 + (0.58882e-7 + (0.34414e-9 + (0.18552e-11 + 0.91160e-14 * t) * t) * t) * t) * t) * t;
+ case 30:
+ t = 2 * x - 79;
+ return 0.90908e-1 + (0.18544e-2 + (0.13903e-4 + (0.95549e-7 + (0.59752e-9 + (0.33656e-11 + 0.16815e-13 * t) * t) * t) * t) * t) * t;
+ case 40:
+ t = 2 * x - 99;
+ return 0.13443e0 + (0.25474e-2 + (0.21385e-4 + (0.15996e-6 + (0.10585e-8 + (0.61258e-11 + 0.30412e-13 * t) * t) * t) * t) * t) * t;
+ case 50:
+ t = 2 * x - 119;
+ return 0.19540e0 + (0.36342e-2 + (0.34096e-4 + (0.27479e-6 + (0.18934e-8 + (0.11021e-10 + 0.52931e-13 * t) * t) * t) * t) * t) * t;
+ case 60:
+ t = 2 * x - 121;
+ return 0.20281e0 + (0.37739e-2 + (0.35791e-4 + (0.29038e-6 + (0.20068e-8 + (0.11673e-10 + 0.55790e-13 * t) * t) * t) * t) * t) * t;
+ case 61:
+ t = 2 * x - 123;
+ return 0.21050e0 + (0.39206e-2 + (0.37582e-4 + (0.30691e-6 + (0.21270e-8 + (0.12361e-10 + 0.58770e-13 * t) * t) * t) * t) * t) * t;
+ case 62:
+ t = 2 * x - 125;
+ return 0.21849e0 + (0.40747e-2 + (0.39476e-4 + (0.32443e-6 + (0.22542e-8 + (0.13084e-10 + 0.61873e-13 * t) * t) * t) * t) * t) * t;
+ case 63:
+ t = 2 * x - 127;
+ return 0.22680e0 + (0.42366e-2 + (0.41477e-4 + (0.34300e-6 + (0.23888e-8 + (0.13846e-10 + 0.65100e-13 * t) * t) * t) * t) * t) * t;
+ case 64:
+ t = 2 * x - 129;
+ return 0.23545e0 + (0.44067e-2 + (0.43594e-4 + (0.36268e-6 + (0.25312e-8 + (0.14647e-10 + 0.68453e-13 * t) * t) * t) * t) * t) * t;
+ case 65:
+ t = 2 * x - 131;
+ return 0.24444e0 + (0.45855e-2 + (0.45832e-4 + (0.38352e-6 + (0.26819e-8 + (0.15489e-10 + 0.71933e-13 * t) * t) * t) * t) * t) * t;
+ case 66:
+ t = 2 * x - 133;
+ return 0.25379e0 + (0.47735e-2 + (0.48199e-4 + (0.40561e-6 + (0.28411e-8 + (0.16374e-10 + 0.75541e-13 * t) * t) * t) * t) * t) * t;
+ case 67:
+ t = 2 * x - 135;
+ return 0.26354e0 + (0.49713e-2 + (0.50702e-4 + (0.42901e-6 + (0.30095e-8 + (0.17303e-10 + 0.79278e-13 * t) * t) * t) * t) * t) * t;
+ case 68:
+ t = 2 * x - 137;
+ return 0.27369e0 + (0.51793e-2 + (0.53350e-4 + (0.45379e-6 + (0.31874e-8 + (0.18277e-10 + 0.83144e-13 * t) * t) * t) * t) * t) * t;
+ case 69:
+ t = 2 * x - 139;
+ return 0.28426e0 + (0.53983e-2 + (0.56150e-4 + (0.48003e-6 + (0.33752e-8 + (0.19299e-10 + 0.87139e-13 * t) * t) * t) * t) * t) * t;
+ case 70:
+ t = 2 * x - 141;
+ return 0.29529e0 + (0.56288e-2 + (0.59113e-4 + (0.50782e-6 + (0.35735e-8 + (0.20369e-10 + 0.91262e-13 * t) * t) * t) * t) * t) * t;
+ case 71:
+ t = 2 * x - 143;
+ return 0.30679e0 + (0.58714e-2 + (0.62248e-4 + (0.53724e-6 + (0.37827e-8 + (0.21490e-10 + 0.95513e-13 * t) * t) * t) * t) * t) * t;
+ case 72:
+ t = 2 * x - 145;
+ return 0.31878e0 + (0.61270e-2 + (0.65564e-4 + (0.56837e-6 + (0.40035e-8 + (0.22662e-10 + 0.99891e-13 * t) * t) * t) * t) * t) * t;
+ case 73:
+ t = 2 * x - 147;
+ return 0.33130e0 + (0.63962e-2 + (0.69072e-4 + (0.60133e-6 + (0.42362e-8 + (0.23888e-10 + 0.10439e-12 * t) * t) * t) * t) * t) * t;
+ case 74:
+ t = 2 * x - 149;
+ return 0.34438e0 + (0.66798e-2 + (0.72783e-4 + (0.63619e-6 + (0.44814e-8 + (0.25168e-10 + 0.10901e-12 * t) * t) * t) * t) * t) * t;
+ case 75:
+ t = 2 * x - 151;
+ return 0.35803e0 + (0.69787e-2 + (0.76710e-4 + (0.67306e-6 + (0.47397e-8 + (0.26505e-10 + 0.11376e-12 * t) * t) * t) * t) * t) * t;
+ case 76:
+ t = 2 * x - 153;
+ return 0.37230e0 + (0.72938e-2 + (0.80864e-4 + (0.71206e-6 + (0.50117e-8 + (0.27899e-10 + 0.11862e-12 * t) * t) * t) * t) * t) * t;
+ case 77:
+ t = 2 * x - 155;
+ return 0.38722e0 + (0.76260e-2 + (0.85259e-4 + (0.75329e-6 + (0.52979e-8 + (0.29352e-10 + 0.12360e-12 * t) * t) * t) * t) * t) * t;
+ case 78:
+ t = 2 * x - 157;
+ return 0.40282e0 + (0.79762e-2 + (0.89909e-4 + (0.79687e-6 + (0.55989e-8 + (0.30866e-10 + 0.12868e-12 * t) * t) * t) * t) * t) * t;
+ case 79:
+ t = 2 * x - 159;
+ return 0.41914e0 + (0.83456e-2 + (0.94827e-4 + (0.84291e-6 + (0.59154e-8 + (0.32441e-10 + 0.13387e-12 * t) * t) * t) * t) * t) * t;
+ case 80:
+ t = 2 * x - 161;
+ return 0.43621e0 + (0.87352e-2 + (0.10002e-3 + (0.89156e-6 + (0.62480e-8 + (0.34079e-10 + 0.13917e-12 * t) * t) * t) * t) * t) * t;
+ case 81:
+ t = 2 * x - 163;
+ return 0.45409e0 + (0.91463e-2 + (0.10553e-3 + (0.94293e-6 + (0.65972e-8 + (0.35782e-10 + 0.14455e-12 * t) * t) * t) * t) * t) * t;
+ case 82:
+ t = 2 * x - 165;
+ return 0.47282e0 + (0.95799e-2 + (0.11135e-3 + (0.99716e-6 + (0.69638e-8 + (0.37549e-10 + 0.15003e-12 * t) * t) * t) * t) * t) * t;
+ case 83:
+ t = 2 * x - 167;
+ return 0.49243e0 + (0.10037e-1 + (0.11750e-3 + (0.10544e-5 + (0.73484e-8 + (0.39383e-10 + 0.15559e-12 * t) * t) * t) * t) * t) * t;
+ case 84:
+ t = 2 * x - 169;
+ return 0.51298e0 + (0.10520e-1 + (0.12400e-3 + (0.11147e-5 + (0.77517e-8 + (0.41283e-10 + 0.16122e-12 * t) * t) * t) * t) * t) * t;
+ case 85:
+ t = 2 * x - 171;
+ return 0.53453e0 + (0.11030e-1 + (0.13088e-3 + (0.11784e-5 + (0.81743e-8 + (0.43252e-10 + 0.16692e-12 * t) * t) * t) * t) * t) * t;
+ case 86:
+ t = 2 * x - 173;
+ return 0.55712e0 + (0.11568e-1 + (0.13815e-3 + (0.12456e-5 + (0.86169e-8 + (0.45290e-10 + 0.17268e-12 * t) * t) * t) * t) * t) * t;
+ case 87:
+ t = 2 * x - 175;
+ return 0.58082e0 + (0.12135e-1 + (0.14584e-3 + (0.13164e-5 + (0.90803e-8 + (0.47397e-10 + 0.17850e-12 * t) * t) * t) * t) * t) * t;
+ case 88:
+ t = 2 * x - 177;
+ return 0.60569e0 + (0.12735e-1 + (0.15396e-3 + (0.13909e-5 + (0.95651e-8 + (0.49574e-10 + 0.18435e-12 * t) * t) * t) * t) * t) * t;
+ case 89:
+ t = 2 * x - 179;
+ return 0.63178e0 + (0.13368e-1 + (0.16254e-3 + (0.14695e-5 + (0.10072e-7 + (0.51822e-10 + 0.19025e-12 * t) * t) * t) * t) * t) * t;
+ case 90:
+ t = 2 * x - 181;
+ return 0.65918e0 + (0.14036e-1 + (0.17160e-3 + (0.15521e-5 + (0.10601e-7 + (0.54140e-10 + 0.19616e-12 * t) * t) * t) * t) * t) * t;
+ case 91:
+ t = 2 * x - 183;
+ return 0.68795e0 + (0.14741e-1 + (0.18117e-3 + (0.16392e-5 + (0.11155e-7 + (0.56530e-10 + 0.20209e-12 * t) * t) * t) * t) * t) * t;
+ case 92:
+ t = 2 * x - 185;
+ return 0.71818e0 + (0.15486e-1 + (0.19128e-3 + (0.17307e-5 + (0.11732e-7 + (0.58991e-10 + 0.20803e-12 * t) * t) * t) * t) * t) * t;
+ case 93:
+ t = 2 * x - 187;
+ return 0.74993e0 + (0.16272e-1 + (0.20195e-3 + (0.18269e-5 + (0.12335e-7 + (0.61523e-10 + 0.21395e-12 * t) * t) * t) * t) * t) * t;
+ }
+ return 1.0;
+}
+
+int
+main ()
+{
+#ifdef __s390x__
+ {
+ register unsigned long r5 __asm ("r5");
+ r5 = 0xdeadbeefUL;
+ asm volatile ("":"+r" (r5));
+ }
+#endif
+ double d = foo (78.4);
+ if (d < 0.38 || d > 0.42)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr58640-2.c b/gcc/testsuite/gcc.c-torture/execute/pr58640-2.c
new file mode 100644
index 00000000000..3fc3a55ce27
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr58640-2.c
@@ -0,0 +1,35 @@
+extern void abort (void);
+
+int a[20], b, c;
+
+int
+fn1 ()
+{
+ int d, e, f, g = 0;
+
+ a[12] = 1;
+ for (e = 0; e < 3; e++)
+ for (d = 0; d < 2; d++)
+ {
+ for (f = 0; f < 2; f++)
+ {
+ g ^= a[12] > 1;
+ if (g)
+ return 0;
+ if (b)
+ break;
+ }
+ for (c = 0; c < 1; c++)
+ a[d] = a[e * 3 + 9];
+ }
+ return 0;
+}
+
+int
+main ()
+{
+ fn1 ();
+ if (a[0] != 0)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr58640.c b/gcc/testsuite/gcc.c-torture/execute/pr58640.c
new file mode 100644
index 00000000000..7786b8d0c9f
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr58640.c
@@ -0,0 +1,32 @@
+int a, b, c, d = 1, e;
+
+static signed char
+foo ()
+{
+ int f, g = a;
+
+ for (f = 1; f < 3; f++)
+ for (; b < 1; b++)
+ {
+ if (d)
+ for (c = 0; c < 4; c++)
+ for (f = 0; f < 3; f++)
+ {
+ for (e = 0; e < 1; e++)
+ a = g;
+ if (f)
+ break;
+ }
+ else if (f)
+ continue;
+ return 0;
+ }
+ return 0;
+}
+
+int
+main ()
+{
+ foo ();
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr58662.c b/gcc/testsuite/gcc.c-torture/execute/pr58662.c
new file mode 100644
index 00000000000..dc0d5f02aca
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr58662.c
@@ -0,0 +1,22 @@
+extern void abort (void);
+
+int a, c, d;
+volatile int b;
+
+static int
+foo (int p1, short p2)
+{
+ return p1 / p2;
+}
+
+int
+main ()
+{
+ char e;
+ d = foo (a == 0, (0, 35536));
+ e = d % 14;
+ b = e && c;
+ if (b != 0)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr58831.c b/gcc/testsuite/gcc.c-torture/execute/pr58831.c
new file mode 100644
index 00000000000..a40cd54d222
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr58831.c
@@ -0,0 +1,40 @@
+#include <assert.h>
+
+int a, *b, c, d, f, **i, p, q, *r;
+short o, j;
+
+static int __attribute__((noinline, noclone))
+fn1 (int *p1, int **p2)
+{
+ int **e = &b;
+ for (; p; p++)
+ *p1 = 1;
+ *e = *p2 = &d;
+
+ assert (r);
+
+ return c;
+}
+
+static int ** __attribute__((noinline, noclone))
+fn2 (void)
+{
+ for (f = 0; f != 42; f++)
+ {
+ int *g[3] = {0, 0, 0};
+ for (o = 0; o; o--)
+ for (; a > 1;)
+ {
+ int **h[1] = { &g[2] };
+ }
+ }
+ return &r;
+}
+
+int
+main (void)
+{
+ i = fn2 ();
+ fn1 (b, i);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr58984.c b/gcc/testsuite/gcc.c-torture/execute/pr58984.c
new file mode 100644
index 00000000000..e0f7669c78d
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr58984.c
@@ -0,0 +1,57 @@
+/* PR tree-optimization/58984 */
+
+struct S { int f0 : 8; int : 6; int f1 : 5; };
+struct T { char f0; int : 6; int f1 : 5; };
+
+int a, *c = &a, e, n, b, m;
+
+static int
+foo (struct S p)
+{
+ const unsigned short *f[36];
+ for (; e < 2; e++)
+ {
+ const unsigned short **i = &f[0];
+ *c ^= 1;
+ if (p.f1)
+ {
+ *i = 0;
+ return b;
+ }
+ }
+ return 0;
+}
+
+static int
+bar (struct T p)
+{
+ const unsigned short *f[36];
+ for (; e < 2; e++)
+ {
+ const unsigned short **i = &f[0];
+ *c ^= 1;
+ if (p.f1)
+ {
+ *i = 0;
+ return b;
+ }
+ }
+ return 0;
+}
+
+int
+main ()
+{
+ struct S o = { 1, 1 };
+ foo (o);
+ m = n || o.f0;
+ if (a != 1)
+ __builtin_abort ();
+ e = 0;
+ struct T p = { 1, 1 };
+ bar (p);
+ m |= n || p.f0;
+ if (a != 0)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/20020312-2.c b/gcc/testsuite/gcc.dg/20020312-2.c
index 633da5be189..299910047f5 100644
--- a/gcc/testsuite/gcc.dg/20020312-2.c
+++ b/gcc/testsuite/gcc.dg/20020312-2.c
@@ -96,6 +96,10 @@ extern void abort (void);
#endif
#elif defined (__aarch64__)
/* No pic register -- yet. */
+#elif defined(__RL78__)
+/* No pic register. */
+#elif defined(__MSP430__)
+/* No pic register. */
#else
# error "Modify the test for your target."
#endif
diff --git a/gcc/testsuite/gcc.dg/20050922-1.c b/gcc/testsuite/gcc.dg/20050922-1.c
index ed5a3c63e9d..982f82011ba 100644
--- a/gcc/testsuite/gcc.dg/20050922-1.c
+++ b/gcc/testsuite/gcc.dg/20050922-1.c
@@ -4,7 +4,7 @@
/* { dg-do run } */
/* { dg-options "-O1 -std=c99" } */
-#include <stdlib.h>
+extern void abort (void);
#if __INT_MAX__ == 2147483647
typedef unsigned int uint32_t;
diff --git a/gcc/testsuite/gcc.dg/20050922-2.c b/gcc/testsuite/gcc.dg/20050922-2.c
index c2974d03d9c..2e8db829e29 100644
--- a/gcc/testsuite/gcc.dg/20050922-2.c
+++ b/gcc/testsuite/gcc.dg/20050922-2.c
@@ -4,7 +4,8 @@
/* { dg-do run } */
/* { dg-options "-O1 -std=c99" } */
-#include <stdlib.h>
+extern void abort (void);
+extern void exit (int);
#if __INT_MAX__ == 2147483647
typedef unsigned int uint32_t;
diff --git a/gcc/testsuite/gcc.dg/atomic-compare-exchange-1.c b/gcc/testsuite/gcc.dg/atomic-compare-exchange-1.c
index 2ac54e80887..4b999c682f2 100644
--- a/gcc/testsuite/gcc.dg/atomic-compare-exchange-1.c
+++ b/gcc/testsuite/gcc.dg/atomic-compare-exchange-1.c
@@ -16,6 +16,7 @@ char zero = 0;
#define STRONG 0
#define WEAK 1
+int
main ()
{
diff --git a/gcc/testsuite/gcc.dg/atomic-compare-exchange-2.c b/gcc/testsuite/gcc.dg/atomic-compare-exchange-2.c
index 73b25977748..736e358a6df 100644
--- a/gcc/testsuite/gcc.dg/atomic-compare-exchange-2.c
+++ b/gcc/testsuite/gcc.dg/atomic-compare-exchange-2.c
@@ -16,6 +16,7 @@ short zero = 0;
#define STRONG 0
#define WEAK 1
+int
main ()
{
diff --git a/gcc/testsuite/gcc.dg/atomic-compare-exchange-3.c b/gcc/testsuite/gcc.dg/atomic-compare-exchange-3.c
index 26097288c9d..91a67cd7423 100644
--- a/gcc/testsuite/gcc.dg/atomic-compare-exchange-3.c
+++ b/gcc/testsuite/gcc.dg/atomic-compare-exchange-3.c
@@ -16,6 +16,7 @@ int zero = 0;
#define STRONG 0
#define WEAK 1
+int
main ()
{
diff --git a/gcc/testsuite/gcc.dg/atomic-compare-exchange-4.c b/gcc/testsuite/gcc.dg/atomic-compare-exchange-4.c
index b6c783ddaba..ac9531b7823 100644
--- a/gcc/testsuite/gcc.dg/atomic-compare-exchange-4.c
+++ b/gcc/testsuite/gcc.dg/atomic-compare-exchange-4.c
@@ -18,6 +18,7 @@ long long zero = 0;
#define STRONG 0
#define WEAK 1
+int
main ()
{
diff --git a/gcc/testsuite/gcc.dg/atomic-compare-exchange-5.c b/gcc/testsuite/gcc.dg/atomic-compare-exchange-5.c
index 4cc0209b33f..f5d071affe8 100644
--- a/gcc/testsuite/gcc.dg/atomic-compare-exchange-5.c
+++ b/gcc/testsuite/gcc.dg/atomic-compare-exchange-5.c
@@ -17,6 +17,7 @@ __int128_t zero = 0;
#define STRONG 0
#define WEAK 1
+int
main ()
{
diff --git a/gcc/testsuite/gcc.dg/atomic-exchange-1.c b/gcc/testsuite/gcc.dg/atomic-exchange-1.c
index fb78cdbca54..ec8a09c8cc3 100644
--- a/gcc/testsuite/gcc.dg/atomic-exchange-1.c
+++ b/gcc/testsuite/gcc.dg/atomic-exchange-1.c
@@ -9,25 +9,31 @@ extern void abort(void);
char v, count, ret;
+int
main ()
{
v = 0;
count = 0;
- if (__atomic_exchange_n (&v, count + 1, __ATOMIC_RELAXED) != count++)
+ if (__atomic_exchange_n (&v, count + 1, __ATOMIC_RELAXED) != count)
abort ();
+ count++;
- if (__atomic_exchange_n (&v, count + 1, __ATOMIC_ACQUIRE) != count++)
+ if (__atomic_exchange_n (&v, count + 1, __ATOMIC_ACQUIRE) != count)
abort ();
+ count++;
- if (__atomic_exchange_n (&v, count + 1, __ATOMIC_RELEASE) != count++)
+ if (__atomic_exchange_n (&v, count + 1, __ATOMIC_RELEASE) != count)
abort ();
+ count++;
- if (__atomic_exchange_n (&v, count + 1, __ATOMIC_ACQ_REL) != count++)
+ if (__atomic_exchange_n (&v, count + 1, __ATOMIC_ACQ_REL) != count)
abort ();
+ count++;
- if (__atomic_exchange_n (&v, count + 1, __ATOMIC_SEQ_CST) != count++)
+ if (__atomic_exchange_n (&v, count + 1, __ATOMIC_SEQ_CST) != count)
abort ();
+ count++;
/* Now test the generic version. */
diff --git a/gcc/testsuite/gcc.dg/atomic-exchange-2.c b/gcc/testsuite/gcc.dg/atomic-exchange-2.c
index 153771a2cdc..0de2e68208f 100644
--- a/gcc/testsuite/gcc.dg/atomic-exchange-2.c
+++ b/gcc/testsuite/gcc.dg/atomic-exchange-2.c
@@ -9,25 +9,31 @@ extern void abort(void);
short v, count, ret;
+int
main ()
{
v = 0;
count = 0;
- if (__atomic_exchange_n (&v, count + 1, __ATOMIC_RELAXED) != count++)
+ if (__atomic_exchange_n (&v, count + 1, __ATOMIC_RELAXED) != count)
abort ();
+ count++;
- if (__atomic_exchange_n (&v, count + 1, __ATOMIC_ACQUIRE) != count++)
+ if (__atomic_exchange_n (&v, count + 1, __ATOMIC_ACQUIRE) != count)
abort ();
+ count++;
- if (__atomic_exchange_n (&v, count + 1, __ATOMIC_RELEASE) != count++)
+ if (__atomic_exchange_n (&v, count + 1, __ATOMIC_RELEASE) != count)
abort ();
+ count++;
- if (__atomic_exchange_n (&v, count + 1, __ATOMIC_ACQ_REL) != count++)
+ if (__atomic_exchange_n (&v, count + 1, __ATOMIC_ACQ_REL) != count)
abort ();
+ count++;
- if (__atomic_exchange_n (&v, count + 1, __ATOMIC_SEQ_CST) != count++)
+ if (__atomic_exchange_n (&v, count + 1, __ATOMIC_SEQ_CST) != count)
abort ();
+ count++;
/* Now test the generic version. */
diff --git a/gcc/testsuite/gcc.dg/atomic-exchange-3.c b/gcc/testsuite/gcc.dg/atomic-exchange-3.c
index fbf8f6b966c..63a68cf473a 100644
--- a/gcc/testsuite/gcc.dg/atomic-exchange-3.c
+++ b/gcc/testsuite/gcc.dg/atomic-exchange-3.c
@@ -9,25 +9,31 @@ extern void abort(void);
int v, count, ret;
+int
main ()
{
v = 0;
count = 0;
- if (__atomic_exchange_n (&v, count + 1, __ATOMIC_RELAXED) != count++)
+ if (__atomic_exchange_n (&v, count + 1, __ATOMIC_RELAXED) != count)
abort ();
+ count++;
- if (__atomic_exchange_n (&v, count + 1, __ATOMIC_ACQUIRE) != count++)
+ if (__atomic_exchange_n (&v, count + 1, __ATOMIC_ACQUIRE) != count)
abort ();
+ count++;
- if (__atomic_exchange_n (&v, count + 1, __ATOMIC_RELEASE) != count++)
+ if (__atomic_exchange_n (&v, count + 1, __ATOMIC_RELEASE) != count)
abort ();
+ count++;
- if (__atomic_exchange_n (&v, count + 1, __ATOMIC_ACQ_REL) != count++)
+ if (__atomic_exchange_n (&v, count + 1, __ATOMIC_ACQ_REL) != count)
abort ();
+ count++;
- if (__atomic_exchange_n (&v, count + 1, __ATOMIC_SEQ_CST) != count++)
+ if (__atomic_exchange_n (&v, count + 1, __ATOMIC_SEQ_CST) != count)
abort ();
+ count++;
/* Now test the generic version. */
diff --git a/gcc/testsuite/gcc.dg/atomic-exchange-4.c b/gcc/testsuite/gcc.dg/atomic-exchange-4.c
index 13022dd38d2..fc1e5081a07 100644
--- a/gcc/testsuite/gcc.dg/atomic-exchange-4.c
+++ b/gcc/testsuite/gcc.dg/atomic-exchange-4.c
@@ -11,25 +11,31 @@ extern void abort(void);
long long v, count, ret;
+int
main ()
{
v = 0;
count = 0;
- if (__atomic_exchange_n (&v, count + 1, __ATOMIC_RELAXED) != count++)
+ if (__atomic_exchange_n (&v, count + 1, __ATOMIC_RELAXED) != count)
abort ();
+ count++;
- if (__atomic_exchange_n (&v, count + 1, __ATOMIC_ACQUIRE) != count++)
+ if (__atomic_exchange_n (&v, count + 1, __ATOMIC_ACQUIRE) != count)
abort ();
+ count++;
- if (__atomic_exchange_n (&v, count + 1, __ATOMIC_RELEASE) != count++)
+ if (__atomic_exchange_n (&v, count + 1, __ATOMIC_RELEASE) != count)
abort ();
+ count++;
- if (__atomic_exchange_n (&v, count + 1, __ATOMIC_ACQ_REL) != count++)
+ if (__atomic_exchange_n (&v, count + 1, __ATOMIC_ACQ_REL) != count)
abort ();
+ count++;
- if (__atomic_exchange_n (&v, count + 1, __ATOMIC_SEQ_CST) != count++)
+ if (__atomic_exchange_n (&v, count + 1, __ATOMIC_SEQ_CST) != count)
abort ();
+ count++;
/* Now test the generic version. */
diff --git a/gcc/testsuite/gcc.dg/atomic-exchange-5.c b/gcc/testsuite/gcc.dg/atomic-exchange-5.c
index b0c84b17fd3..190377f0cd5 100644
--- a/gcc/testsuite/gcc.dg/atomic-exchange-5.c
+++ b/gcc/testsuite/gcc.dg/atomic-exchange-5.c
@@ -10,25 +10,31 @@ extern void abort(void);
__int128_t v, count, ret;
+int
main ()
{
v = 0;
count = 0;
- if (__atomic_exchange_n (&v, count + 1, __ATOMIC_RELAXED) != count++)
+ if (__atomic_exchange_n (&v, count + 1, __ATOMIC_RELAXED) != count)
abort ();
+ count++;
- if (__atomic_exchange_n (&v, count + 1, __ATOMIC_ACQUIRE) != count++)
+ if (__atomic_exchange_n (&v, count + 1, __ATOMIC_ACQUIRE) != count)
abort ();
+ count++;
- if (__atomic_exchange_n (&v, count + 1, __ATOMIC_RELEASE) != count++)
+ if (__atomic_exchange_n (&v, count + 1, __ATOMIC_RELEASE) != count)
abort ();
+ count++;
- if (__atomic_exchange_n (&v, count + 1, __ATOMIC_ACQ_REL) != count++)
+ if (__atomic_exchange_n (&v, count + 1, __ATOMIC_ACQ_REL) != count)
abort ();
+ count++;
- if (__atomic_exchange_n (&v, count + 1, __ATOMIC_SEQ_CST) != count++)
+ if (__atomic_exchange_n (&v, count + 1, __ATOMIC_SEQ_CST) != count)
abort ();
+ count++;
/* Now test the generic version. */
diff --git a/gcc/testsuite/gcc.dg/atomic-fence.c b/gcc/testsuite/gcc.dg/atomic-fence.c
index 1f6d1871a0b..ab5c7d62c9c 100644
--- a/gcc/testsuite/gcc.dg/atomic-fence.c
+++ b/gcc/testsuite/gcc.dg/atomic-fence.c
@@ -6,6 +6,7 @@
/* Test that __atomic_{thread,signal}_fence builtins execute. */
+int
main ()
{
__atomic_thread_fence (__ATOMIC_RELAXED);
diff --git a/gcc/testsuite/gcc.dg/atomic-flag.c b/gcc/testsuite/gcc.dg/atomic-flag.c
index b81cd7832af..6e79b902720 100644
--- a/gcc/testsuite/gcc.dg/atomic-flag.c
+++ b/gcc/testsuite/gcc.dg/atomic-flag.c
@@ -7,6 +7,7 @@
extern void abort(void);
unsigned char a;
+int
main ()
{
int b;
diff --git a/gcc/testsuite/gcc.dg/atomic-generic.c b/gcc/testsuite/gcc.dg/atomic-generic.c
index d77e97dbf8a..9b09f87b84c 100644
--- a/gcc/testsuite/gcc.dg/atomic-generic.c
+++ b/gcc/testsuite/gcc.dg/atomic-generic.c
@@ -23,6 +23,7 @@ test_struct a,b;
int size = sizeof (test_struct);
/* Test for consistency on sizes 1, 2, 4, 8, 16 and 32. */
+int
main ()
{
test_struct c;
diff --git a/gcc/testsuite/gcc.dg/atomic-invalid.c b/gcc/testsuite/gcc.dg/atomic-invalid.c
index 48de91f6c75..4d040e1d572 100644
--- a/gcc/testsuite/gcc.dg/atomic-invalid.c
+++ b/gcc/testsuite/gcc.dg/atomic-invalid.c
@@ -10,6 +10,7 @@ int i, e, b;
size_t s;
bool x;
+int
main ()
{
__atomic_compare_exchange_n (&i, &e, 1, 0, __ATOMIC_RELAXED, __ATOMIC_SEQ_CST); /* { dg-error "failure memory model cannot be stronger" } */
diff --git a/gcc/testsuite/gcc.dg/atomic-load-1.c b/gcc/testsuite/gcc.dg/atomic-load-1.c
index 928f9b0f10b..72ca317f209 100644
--- a/gcc/testsuite/gcc.dg/atomic-load-1.c
+++ b/gcc/testsuite/gcc.dg/atomic-load-1.c
@@ -10,6 +10,7 @@ extern void abort(void);
char v, count;
+int
main ()
{
v = 0;
diff --git a/gcc/testsuite/gcc.dg/atomic-load-2.c b/gcc/testsuite/gcc.dg/atomic-load-2.c
index 3d1df1cfffa..e937a2dab8b 100644
--- a/gcc/testsuite/gcc.dg/atomic-load-2.c
+++ b/gcc/testsuite/gcc.dg/atomic-load-2.c
@@ -11,6 +11,7 @@ extern void abort(void);
short v, count;
+int
main ()
{
v = 0;
diff --git a/gcc/testsuite/gcc.dg/atomic-load-3.c b/gcc/testsuite/gcc.dg/atomic-load-3.c
index ec238be9e51..3e70ef429f6 100644
--- a/gcc/testsuite/gcc.dg/atomic-load-3.c
+++ b/gcc/testsuite/gcc.dg/atomic-load-3.c
@@ -8,6 +8,7 @@ extern void abort(void);
int v, count;
+int
main ()
{
v = 0;
diff --git a/gcc/testsuite/gcc.dg/atomic-load-4.c b/gcc/testsuite/gcc.dg/atomic-load-4.c
index 032ad246fd0..750623dcb63 100644
--- a/gcc/testsuite/gcc.dg/atomic-load-4.c
+++ b/gcc/testsuite/gcc.dg/atomic-load-4.c
@@ -9,6 +9,7 @@ extern void abort(void);
long long v, count;
+int
main ()
{
v = 0;
diff --git a/gcc/testsuite/gcc.dg/atomic-load-5.c b/gcc/testsuite/gcc.dg/atomic-load-5.c
index 31d806633e1..d37d6424892 100644
--- a/gcc/testsuite/gcc.dg/atomic-load-5.c
+++ b/gcc/testsuite/gcc.dg/atomic-load-5.c
@@ -8,6 +8,7 @@ extern void abort(void);
__int128_t v, count;
+int
main ()
{
v = 0;
diff --git a/gcc/testsuite/gcc.dg/atomic-lockfree.c b/gcc/testsuite/gcc.dg/atomic-lockfree.c
index 225428223ea..093aee9199f 100644
--- a/gcc/testsuite/gcc.dg/atomic-lockfree.c
+++ b/gcc/testsuite/gcc.dg/atomic-lockfree.c
@@ -17,6 +17,7 @@ extern void abort();
int r1, r2;
/* Test for consistency on sizes 1, 2, 4, 8, 16 and 32. */
+int
main ()
{
diff --git a/gcc/testsuite/gcc.dg/atomic-noinline.c b/gcc/testsuite/gcc.dg/atomic-noinline.c
index 626254d8a9a..b3490ea3260 100644
--- a/gcc/testsuite/gcc.dg/atomic-noinline.c
+++ b/gcc/testsuite/gcc.dg/atomic-noinline.c
@@ -16,6 +16,7 @@ extern void abort();
short as,bs,cs;
char ac,bc,cc;
+int
main ()
{
diff --git a/gcc/testsuite/gcc.dg/atomic-op-1.c b/gcc/testsuite/gcc.dg/atomic-op-1.c
index bc1716f7799..a8a97c401b7 100644
--- a/gcc/testsuite/gcc.dg/atomic-op-1.c
+++ b/gcc/testsuite/gcc.dg/atomic-op-1.c
@@ -527,6 +527,7 @@ test_or ()
abort ();
}
+int
main ()
{
test_fetch_add ();
diff --git a/gcc/testsuite/gcc.dg/atomic-op-2.c b/gcc/testsuite/gcc.dg/atomic-op-2.c
index 8755340cca2..949850345b5 100644
--- a/gcc/testsuite/gcc.dg/atomic-op-2.c
+++ b/gcc/testsuite/gcc.dg/atomic-op-2.c
@@ -528,6 +528,7 @@ test_or ()
abort ();
}
+int
main ()
{
test_fetch_add ();
diff --git a/gcc/testsuite/gcc.dg/atomic-op-3.c b/gcc/testsuite/gcc.dg/atomic-op-3.c
index 69db4894b63..9a54a2a4178 100644
--- a/gcc/testsuite/gcc.dg/atomic-op-3.c
+++ b/gcc/testsuite/gcc.dg/atomic-op-3.c
@@ -527,6 +527,7 @@ test_or ()
abort ();
}
+int
main ()
{
test_fetch_add ();
diff --git a/gcc/testsuite/gcc.dg/atomic-op-4.c b/gcc/testsuite/gcc.dg/atomic-op-4.c
index 7c4a819bfaa..6990b0e2d75 100644
--- a/gcc/testsuite/gcc.dg/atomic-op-4.c
+++ b/gcc/testsuite/gcc.dg/atomic-op-4.c
@@ -529,6 +529,7 @@ test_or ()
abort ();
}
+int
main ()
{
test_fetch_add ();
diff --git a/gcc/testsuite/gcc.dg/atomic-op-5.c b/gcc/testsuite/gcc.dg/atomic-op-5.c
index e78d8150997..1407f3fe3b2 100644
--- a/gcc/testsuite/gcc.dg/atomic-op-5.c
+++ b/gcc/testsuite/gcc.dg/atomic-op-5.c
@@ -528,6 +528,7 @@ test_or ()
abort ();
}
+int
main ()
{
test_fetch_add ();
diff --git a/gcc/testsuite/gcc.dg/atomic-param.c b/gcc/testsuite/gcc.dg/atomic-param.c
index a1bfc6be87c..1f2b12690fa 100644
--- a/gcc/testsuite/gcc.dg/atomic-param.c
+++ b/gcc/testsuite/gcc.dg/atomic-param.c
@@ -5,6 +5,7 @@
int i;
+int
main ()
{
diff --git a/gcc/testsuite/gcc.dg/atomic-store-1.c b/gcc/testsuite/gcc.dg/atomic-store-1.c
index f99eb9c844f..1ca5febcf81 100644
--- a/gcc/testsuite/gcc.dg/atomic-store-1.c
+++ b/gcc/testsuite/gcc.dg/atomic-store-1.c
@@ -9,6 +9,7 @@ extern void abort(void);
char v, count;
+int
main ()
{
v = 0;
diff --git a/gcc/testsuite/gcc.dg/atomic-store-2.c b/gcc/testsuite/gcc.dg/atomic-store-2.c
index da346fd7de4..c7b1e211a19 100644
--- a/gcc/testsuite/gcc.dg/atomic-store-2.c
+++ b/gcc/testsuite/gcc.dg/atomic-store-2.c
@@ -9,6 +9,7 @@ extern void abort(void);
short v, count;
+int
main ()
{
v = 0;
diff --git a/gcc/testsuite/gcc.dg/atomic-store-3.c b/gcc/testsuite/gcc.dg/atomic-store-3.c
index b691da4592f..52b30faacdc 100644
--- a/gcc/testsuite/gcc.dg/atomic-store-3.c
+++ b/gcc/testsuite/gcc.dg/atomic-store-3.c
@@ -9,6 +9,7 @@ extern void abort(void);
int v, count;
+int
main ()
{
v = 0;
diff --git a/gcc/testsuite/gcc.dg/atomic-store-4.c b/gcc/testsuite/gcc.dg/atomic-store-4.c
index 0863be99d01..ca37fdc4628 100644
--- a/gcc/testsuite/gcc.dg/atomic-store-4.c
+++ b/gcc/testsuite/gcc.dg/atomic-store-4.c
@@ -11,6 +11,7 @@ extern void abort(void);
long long v, count;
+int
main ()
{
v = 0;
diff --git a/gcc/testsuite/gcc.dg/atomic-store-5.c b/gcc/testsuite/gcc.dg/atomic-store-5.c
index 763d29e240c..a855182bf49 100644
--- a/gcc/testsuite/gcc.dg/atomic-store-5.c
+++ b/gcc/testsuite/gcc.dg/atomic-store-5.c
@@ -10,6 +10,7 @@ extern void abort(void);
__int128_t v, count;
+int
main ()
{
v = 0;
diff --git a/gcc/testsuite/gcc.dg/atomic-store-6.c b/gcc/testsuite/gcc.dg/atomic-store-6.c
new file mode 100644
index 00000000000..81499cd716b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/atomic-store-6.c
@@ -0,0 +1,13 @@
+/* { dg-do run } */
+/* { dg-require-effective-target sync_int_128_runtime } */
+/* { dg-options "-mcx16" { target { i?86-*-* x86_64-*-* } } } */
+
+__int128_t i;
+
+int main()
+{
+ __atomic_store_16(&i, -1, 0);
+ if (i != -1)
+ __builtin_abort();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/atomic/atomic.exp b/gcc/testsuite/gcc.dg/atomic/atomic.exp
new file mode 100644
index 00000000000..ac2ca729d1d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/atomic/atomic.exp
@@ -0,0 +1,34 @@
+# Copyright (C) 2012-2013 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/>.
+
+# GCC testsuite that uses the `dg.exp' driver.
+
+# Load support procs.
+load_lib gcc-dg.exp
+load_lib atomic-dg.exp
+
+# Initialize `dg'.
+dg-init
+if [atomic_init] {
+ # Main loop.
+ gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] ""
+}
+
+# All done.
+atomic_finish
+dg-finish
diff --git a/gcc/testsuite/gcc.dg/atomic/c11-atomic-exec-1.c b/gcc/testsuite/gcc.dg/atomic/c11-atomic-exec-1.c
new file mode 100644
index 00000000000..c0db93f07dc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/atomic/c11-atomic-exec-1.c
@@ -0,0 +1,88 @@
+/* Test for _Atomic in C11. Basic execution tests for atomic loads
+ and stores. */
+/* { dg-do run } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+extern void abort (void);
+extern void exit (int);
+extern int memcmp (const void *, const void *, __SIZE_TYPE__);
+
+#define CMPLX(X, Y) __builtin_complex ((X), (Y))
+
+#define TEST_SIMPLE_ASSIGN(TYPE, VALUE) \
+ do \
+ { \
+ static volatile _Atomic (TYPE) a, b = (TYPE) (VALUE); \
+ if (a != 0) \
+ abort (); \
+ if (b != ((TYPE) (VALUE))) \
+ abort (); \
+ if ((a = b) != ((TYPE) (VALUE))) \
+ abort (); \
+ if (a != ((TYPE) (VALUE))) \
+ abort (); \
+ } \
+ while (0)
+
+#define TEST_SIMPLE_ASSIGN_ARITH(VALUE) \
+ do \
+ { \
+ TEST_SIMPLE_ASSIGN (_Bool, (VALUE)); \
+ TEST_SIMPLE_ASSIGN (char, (VALUE)); \
+ TEST_SIMPLE_ASSIGN (signed char, (VALUE)); \
+ TEST_SIMPLE_ASSIGN (unsigned char, (VALUE)); \
+ TEST_SIMPLE_ASSIGN (signed short, (VALUE)); \
+ TEST_SIMPLE_ASSIGN (unsigned short, (VALUE)); \
+ TEST_SIMPLE_ASSIGN (signed int, (VALUE)); \
+ TEST_SIMPLE_ASSIGN (unsigned int, (VALUE)); \
+ TEST_SIMPLE_ASSIGN (signed long, (VALUE)); \
+ TEST_SIMPLE_ASSIGN (unsigned long, (VALUE)); \
+ TEST_SIMPLE_ASSIGN (signed long long, (VALUE)); \
+ TEST_SIMPLE_ASSIGN (unsigned long long, (VALUE)); \
+ TEST_SIMPLE_ASSIGN (float, (VALUE)); \
+ TEST_SIMPLE_ASSIGN (double, (VALUE)); \
+ TEST_SIMPLE_ASSIGN (long double, (VALUE)); \
+ TEST_SIMPLE_ASSIGN (_Complex float, (VALUE)); \
+ TEST_SIMPLE_ASSIGN (_Complex double, (VALUE)); \
+ TEST_SIMPLE_ASSIGN (_Complex long double, (VALUE)); \
+ } \
+ while (0)
+
+static void
+test_simple_assign (void)
+{
+ TEST_SIMPLE_ASSIGN_ARITH (0);
+ TEST_SIMPLE_ASSIGN_ARITH (1);
+ TEST_SIMPLE_ASSIGN_ARITH (2);
+ TEST_SIMPLE_ASSIGN_ARITH (-1);
+ TEST_SIMPLE_ASSIGN_ARITH (1ULL << 63);
+ TEST_SIMPLE_ASSIGN_ARITH (1.5);
+ TEST_SIMPLE_ASSIGN_ARITH (CMPLX (2.5, 3.5));
+ static int i;
+ TEST_SIMPLE_ASSIGN (int *, 0);
+ TEST_SIMPLE_ASSIGN (int *, &i);
+ struct s { short a[1024]; };
+ struct s init, copy;
+ _Atomic struct s s1, s2;
+ for (int j = 0; j < 1024; j++)
+ init.a[j] = j;
+ copy = (s1 = init);
+ if (memcmp (&init, &copy, sizeof init) != 0)
+ abort ();
+ copy = (s2 = s1);
+ if (memcmp (&init, &copy, sizeof init) != 0)
+ abort ();
+ copy = s1;
+ if (memcmp (&init, &copy, sizeof init) != 0)
+ abort ();
+ copy = s2;
+ if (memcmp (&init, &copy, sizeof init) != 0)
+ abort ();
+}
+
+int
+main (void)
+{
+ test_simple_assign ();
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/atomic/c11-atomic-exec-2.c b/gcc/testsuite/gcc.dg/atomic/c11-atomic-exec-2.c
new file mode 100644
index 00000000000..9ee56b60193
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/atomic/c11-atomic-exec-2.c
@@ -0,0 +1,171 @@
+/* Test for _Atomic in C11. Basic execution tests for atomic compound
+ assignment. */
+/* { dg-do run } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+extern void abort (void);
+extern void exit (int);
+
+#define CMPLX(X, Y) __builtin_complex ((X), (Y))
+
+#define TEST_COMPOUND(TYPE, LHSVAL, RHSVAL, OP) \
+ do \
+ { \
+ static volatile _Atomic (TYPE) a = (TYPE) (LHSVAL); \
+ if ((a OP##= (RHSVAL)) != (TYPE) ((TYPE) (LHSVAL) OP (RHSVAL))) \
+ abort (); \
+ if (a != (TYPE) ((TYPE) (LHSVAL) OP (RHSVAL))) \
+ abort (); \
+ } \
+ while (0)
+
+#define TEST_COMPOUND_ARITH(LHSVAL, RHSVAL, OP) \
+ do \
+ { \
+ TEST_COMPOUND (_Bool, (LHSVAL), (RHSVAL), OP); \
+ TEST_COMPOUND (char, (LHSVAL), (RHSVAL), OP); \
+ TEST_COMPOUND (signed char, (LHSVAL), (RHSVAL), OP); \
+ TEST_COMPOUND (unsigned char, (LHSVAL), (RHSVAL), OP); \
+ TEST_COMPOUND (signed short, (LHSVAL), (RHSVAL), OP); \
+ TEST_COMPOUND (unsigned short, (LHSVAL), (RHSVAL), OP); \
+ TEST_COMPOUND (signed int, (LHSVAL), (RHSVAL), OP); \
+ TEST_COMPOUND (unsigned int, (LHSVAL), (RHSVAL), OP); \
+ TEST_COMPOUND (signed long, (LHSVAL), (RHSVAL), OP); \
+ TEST_COMPOUND (unsigned long, (LHSVAL), (RHSVAL), OP); \
+ TEST_COMPOUND (signed long long, (LHSVAL), (RHSVAL), OP); \
+ TEST_COMPOUND (unsigned long long, (LHSVAL), (RHSVAL), OP); \
+ TEST_COMPOUND (float, (LHSVAL), (RHSVAL), OP); \
+ TEST_COMPOUND (double, (LHSVAL), (RHSVAL), OP); \
+ TEST_COMPOUND (long double, (LHSVAL), (RHSVAL), OP); \
+ TEST_COMPOUND (_Complex float, (LHSVAL), (RHSVAL), OP); \
+ TEST_COMPOUND (_Complex double, (LHSVAL), (RHSVAL), OP); \
+ TEST_COMPOUND (_Complex long double, (LHSVAL), (RHSVAL), OP); \
+ } \
+ while (0)
+
+#define TEST_COMPOUND_INT(LHSVAL, RHSVAL, OP) \
+ do \
+ { \
+ TEST_COMPOUND (_Bool, (LHSVAL), (RHSVAL), OP); \
+ TEST_COMPOUND (char, (LHSVAL), (RHSVAL), OP); \
+ TEST_COMPOUND (signed char, (LHSVAL), (RHSVAL), OP); \
+ TEST_COMPOUND (unsigned char, (LHSVAL), (RHSVAL), OP); \
+ TEST_COMPOUND (signed short, (LHSVAL), (RHSVAL), OP); \
+ TEST_COMPOUND (unsigned short, (LHSVAL), (RHSVAL), OP); \
+ TEST_COMPOUND (signed int, (LHSVAL), (RHSVAL), OP); \
+ TEST_COMPOUND (unsigned int, (LHSVAL), (RHSVAL), OP); \
+ TEST_COMPOUND (signed long, (LHSVAL), (RHSVAL), OP); \
+ TEST_COMPOUND (unsigned long, (LHSVAL), (RHSVAL), OP); \
+ TEST_COMPOUND (signed long long, (LHSVAL), (RHSVAL), OP); \
+ TEST_COMPOUND (unsigned long long, (LHSVAL), (RHSVAL), OP); \
+ } \
+ while (0)
+
+static void
+test_mult (void)
+{
+ TEST_COMPOUND_ARITH (1, 2, *);
+ TEST_COMPOUND_ARITH (-3, 5, *);
+ TEST_COMPOUND_ARITH (-7, -20, *);
+ TEST_COMPOUND_ARITH (1.25, 3.5, *);
+ TEST_COMPOUND_ARITH (CMPLX (1.5, 2.5), CMPLX (3.5, 4.5), *);
+ TEST_COMPOUND_ARITH (CMPLX (1.5, 2.5), 2, *);
+}
+
+static void
+test_div (void)
+{
+ TEST_COMPOUND_ARITH (1, 2, /);
+ TEST_COMPOUND_ARITH (-6, 3, /);
+ TEST_COMPOUND_ARITH (-70, -10, /);
+ TEST_COMPOUND_ARITH (1.25, 2.5, /);
+ TEST_COMPOUND_ARITH (CMPLX (1.0, 1.0), CMPLX (0.5, 0.5), /);
+ TEST_COMPOUND_ARITH (CMPLX (1.5, 2.5), 2, /);
+}
+
+static void
+test_mod (void)
+{
+ TEST_COMPOUND_INT (1, 2, %);
+ TEST_COMPOUND_INT (-3, 5, %);
+ TEST_COMPOUND_INT (-7, -2, %);
+}
+
+static void
+test_plus (void)
+{
+ TEST_COMPOUND_ARITH (1, 2, +);
+ TEST_COMPOUND_ARITH (-3, 5, +);
+ TEST_COMPOUND_ARITH (-7, -20, +);
+ TEST_COMPOUND_ARITH (1.25, 3.5, +);
+ TEST_COMPOUND_ARITH (CMPLX (1.5, 2.5), CMPLX (3.5, 4.5), +);
+ TEST_COMPOUND_ARITH (CMPLX (1.5, 2.5), 2, +);
+ static int ia[2];
+ TEST_COMPOUND (int *, &ia[1], 1, +);
+ TEST_COMPOUND (int *, &ia[1], -1, +);
+}
+
+static void
+test_minus (void)
+{
+ TEST_COMPOUND_ARITH (1, 2, -);
+ TEST_COMPOUND_ARITH (-3, 5, -);
+ TEST_COMPOUND_ARITH (-7, -20, -);
+ TEST_COMPOUND_ARITH (3.5, 1.25, -);
+ TEST_COMPOUND_ARITH (CMPLX (3.5, 4.5), CMPLX (1.5, 2.5), -);
+ TEST_COMPOUND_ARITH (CMPLX (3.5, 2.5), 2, -);
+ static int ia[2];
+ TEST_COMPOUND (int *, &ia[1], 1, -);
+ TEST_COMPOUND (int *, &ia[1], -1, -);
+}
+
+static void
+test_lshift (void)
+{
+ TEST_COMPOUND_INT (1, 7, <<);
+ TEST_COMPOUND_INT (15, 3, <<);
+}
+
+static void
+test_rshift (void)
+{
+ TEST_COMPOUND_INT (1, 1, >>);
+ TEST_COMPOUND_INT (127, 4, >>);
+}
+
+static void
+test_and (void)
+{
+ TEST_COMPOUND_INT (0x1234, 0x7856, &);
+ TEST_COMPOUND_INT (-1, 0x12345678, &);
+}
+
+static void
+test_xor (void)
+{
+ TEST_COMPOUND_INT (0x1234, 0x7856, ^);
+ TEST_COMPOUND_INT (-1, 0x12345678, ^);
+}
+
+static void
+test_or (void)
+{
+ TEST_COMPOUND_INT (0x1234, 0x7856, |);
+ TEST_COMPOUND_INT (-12345, 0x12345678, |);
+}
+
+int
+main (void)
+{
+ test_mult ();
+ test_div ();
+ test_mod ();
+ test_plus ();
+ test_minus ();
+ test_lshift ();
+ test_rshift ();
+ test_and ();
+ test_xor ();
+ test_or ();
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/atomic/c11-atomic-exec-3.c b/gcc/testsuite/gcc.dg/atomic/c11-atomic-exec-3.c
new file mode 100644
index 00000000000..7bfa8c05f96
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/atomic/c11-atomic-exec-3.c
@@ -0,0 +1,85 @@
+/* Test for _Atomic in C11. Basic execution tests for atomic
+ increment and decrement. */
+/* { dg-do run } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+extern void abort (void);
+extern void exit (int);
+
+#define TEST_INCDEC(TYPE, VALUE, PREOP, POSTOP, PRE_P, CHANGE) \
+ do \
+ { \
+ static volatile _Atomic (TYPE) a = (TYPE) (VALUE); \
+ if (PREOP a POSTOP != (PRE_P \
+ ? (TYPE) ((TYPE) (VALUE) + (CHANGE)) \
+ : (TYPE) (VALUE))) \
+ abort (); \
+ if (a != (TYPE) ((TYPE) (VALUE) + (CHANGE))) \
+ abort (); \
+ } \
+ while (0)
+
+#define TEST_INCDEC_ARITH(VALUE, PREOP, POSTOP, PRE_P, CHANGE) \
+ do \
+ { \
+ TEST_INCDEC (_Bool, (VALUE), PREOP, POSTOP, (PRE_P), (CHANGE)); \
+ TEST_INCDEC (char, (VALUE), PREOP, POSTOP, (PRE_P), (CHANGE)); \
+ TEST_INCDEC (signed char, (VALUE), PREOP, POSTOP, (PRE_P), \
+ (CHANGE)); \
+ TEST_INCDEC (unsigned char, (VALUE), PREOP, POSTOP, (PRE_P), \
+ (CHANGE)); \
+ TEST_INCDEC (signed short, (VALUE), PREOP, POSTOP, (PRE_P), \
+ (CHANGE)); \
+ TEST_INCDEC (unsigned short, (VALUE), PREOP, POSTOP, (PRE_P), \
+ (CHANGE)); \
+ TEST_INCDEC (signed int, (VALUE), PREOP, POSTOP, (PRE_P), \
+ (CHANGE)); \
+ TEST_INCDEC (unsigned int, (VALUE), PREOP, POSTOP, (PRE_P), \
+ (CHANGE)); \
+ TEST_INCDEC (signed long, (VALUE), PREOP, POSTOP, (PRE_P), \
+ (CHANGE)); \
+ TEST_INCDEC (unsigned long, (VALUE), PREOP, POSTOP, (PRE_P), \
+ (CHANGE)); \
+ TEST_INCDEC (signed long long, (VALUE), PREOP, POSTOP, (PRE_P), \
+ (CHANGE)); \
+ TEST_INCDEC (unsigned long long, (VALUE), PREOP, POSTOP, (PRE_P), \
+ (CHANGE)); \
+ TEST_INCDEC (float, (VALUE), PREOP, POSTOP, (PRE_P), (CHANGE)); \
+ TEST_INCDEC (double, (VALUE), PREOP, POSTOP, (PRE_P), (CHANGE)); \
+ TEST_INCDEC (long double, (VALUE), PREOP, POSTOP, (PRE_P), \
+ (CHANGE)); \
+ } \
+ while (0)
+
+#define TEST_ALL_INCDEC_ARITH(VALUE) \
+ do \
+ { \
+ TEST_INCDEC_ARITH ((VALUE), ++, , 1, 1); \
+ TEST_INCDEC_ARITH ((VALUE), --, , 1, -1); \
+ TEST_INCDEC_ARITH ((VALUE), , ++, 0, 1); \
+ TEST_INCDEC_ARITH ((VALUE), , --, 0, -1); \
+ } \
+ while (0)
+
+static void
+test_incdec (void)
+{
+ TEST_ALL_INCDEC_ARITH (0);
+ TEST_ALL_INCDEC_ARITH (1);
+ TEST_ALL_INCDEC_ARITH (2);
+ TEST_ALL_INCDEC_ARITH (-1);
+ TEST_ALL_INCDEC_ARITH (1ULL << 60);
+ TEST_ALL_INCDEC_ARITH (1.5);
+ static int ia[2];
+ TEST_INCDEC (int *, &ia[1], ++, , 1, 1);
+ TEST_INCDEC (int *, &ia[1], --, , 1, -1);
+ TEST_INCDEC (int *, &ia[1], , ++, 0, 1);
+ TEST_INCDEC (int *, &ia[1], , --, 0, -1);
+}
+
+int
+main (void)
+{
+ test_incdec ();
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/atomic/c11-atomic-exec-4.c b/gcc/testsuite/gcc.dg/atomic/c11-atomic-exec-4.c
new file mode 100644
index 00000000000..02bb3cb7960
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/atomic/c11-atomic-exec-4.c
@@ -0,0 +1,208 @@
+/* Test for _Atomic in C11. Test that compare-and-exchange is
+ operating properly when operations on the same variable are carried
+ out in two threads. */
+/* { dg-do run } */
+/* { dg-options "-std=c11 -pedantic-errors -pthread -D_POSIX_C_SOURCE=200809L" } */
+/* { dg-require-effective-target pthread } */
+
+#include <stdint.h>
+#include <pthread.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define ITER_COUNT 10000
+
+static volatile _Atomic bool thread_ready;
+
+/* Generate test code (with NAME used to name functions and variables)
+ for atomic compound assignments to a variable of type LHSTYPE. The
+ variable is initialized to INIT, then PRE var POST is executed
+ ITER_COUNT times in each of two threads, and the final result
+ should be FINAL. A function test_main_##NAME is generated that
+ returns nonzero on failure, zero on success. */
+
+#define TEST_FUNCS(NAME, LHSTYPE, PRE, POST, INIT, FINAL) \
+ \
+static volatile _Atomic LHSTYPE var_##NAME = (INIT); \
+ \
+static void * \
+test_thread_##NAME (void *arg) \
+{ \
+ thread_ready = true; \
+ for (int i = 0; i < ITER_COUNT; i++) \
+ PRE var_##NAME POST; \
+ return NULL; \
+} \
+ \
+static int \
+test_main_##NAME (void) \
+{ \
+ thread_ready = false; \
+ pthread_t thread_id; \
+ int pret = pthread_create (&thread_id, NULL, test_thread_##NAME, \
+ NULL); \
+ if (pret != 0) \
+ { \
+ printf ("pthread_create failed: %d\n", pret); \
+ return 1; \
+ } \
+ while (!thread_ready) \
+ ; \
+ for (int i = 0; i < ITER_COUNT; i++) \
+ PRE var_##NAME POST; \
+ pthread_join (thread_id, NULL); \
+ if (var_##NAME != (FINAL)) \
+ { \
+ printf (#NAME " failed\n"); \
+ return 1; \
+ } \
+ else \
+ { \
+ printf (#NAME " passed\n"); \
+ return 0; \
+ } \
+}
+
+TEST_FUNCS (uint8_add, uint8_t, , += 1, 0, (uint8_t) 20000)
+TEST_FUNCS (uint8_add_3, uint8_t, , += 3, 0, (uint8_t) 60000)
+TEST_FUNCS (uint16_add, uint16_t, , += 1, 0, (uint16_t) 20000)
+TEST_FUNCS (uint16_add_3, uint16_t, , += 3, 0, (uint16_t) 60000)
+TEST_FUNCS (uint32_add, uint32_t, , += 1, 0, (uint32_t) 20000)
+TEST_FUNCS (uint32_add_3, uint32_t, , += 3, 0, (uint32_t) 60000)
+TEST_FUNCS (uint64_add, uint64_t, , += 1, 0, (uint64_t) 20000)
+TEST_FUNCS (uint64_add_3, uint64_t, , += 3, 0, (uint64_t) 60000)
+TEST_FUNCS (uint64_add_neg, uint64_t, , += 1, -10000, (uint64_t) 10000)
+TEST_FUNCS (float_add, float, , += 1, 0, 20000)
+TEST_FUNCS (double_add, double, , += 1, 0, 20000)
+TEST_FUNCS (long_double_add, long double, , += 1, 0, 20000)
+TEST_FUNCS (complex_float_add, _Complex float, , += 1, 0, 20000)
+TEST_FUNCS (complex_double_add, _Complex double, , += 1, 0, 20000)
+TEST_FUNCS (complex_long_double_add, _Complex long double, , += 1, 0, 20000)
+TEST_FUNCS (uint8_postinc, uint8_t, , ++, 0, (uint8_t) 20000)
+TEST_FUNCS (uint16_postinc, uint16_t, , ++, 0, (uint16_t) 20000)
+TEST_FUNCS (uint32_postinc, uint32_t, , ++, 0, (uint32_t) 20000)
+TEST_FUNCS (uint64_postinc, uint64_t, , ++, 0, (uint64_t) 20000)
+TEST_FUNCS (uint64_postinc_neg, uint64_t, , ++, -10000, (uint64_t) 10000)
+TEST_FUNCS (float_postinc, float, , ++, 0, 20000)
+TEST_FUNCS (double_postinc, double, , ++, 0, 20000)
+TEST_FUNCS (long_double_postinc, long double, , ++, 0, 20000)
+TEST_FUNCS (uint8_preinc, uint8_t, ++, , 0, (uint8_t) 20000)
+TEST_FUNCS (uint16_preinc, uint16_t, ++, , 0, (uint16_t) 20000)
+TEST_FUNCS (uint32_preinc, uint32_t, ++, , 0, (uint32_t) 20000)
+TEST_FUNCS (uint64_preinc, uint64_t, ++, , 0, (uint64_t) 20000)
+TEST_FUNCS (uint64_preinc_neg, uint64_t, ++, , -10000, (uint64_t) 10000)
+TEST_FUNCS (float_preinc, float, ++, , 0, 20000)
+TEST_FUNCS (double_preinc, double, ++, , 0, 20000)
+TEST_FUNCS (long_double_preinc, long double, ++, , 0, 20000)
+TEST_FUNCS (uint8_sub, uint8_t, , -= 1, 0, (uint8_t) -20000)
+TEST_FUNCS (uint8_sub_3, uint8_t, , -= 3, 0, (uint8_t) -60000)
+TEST_FUNCS (uint16_sub, uint16_t, , -= 1, 0, (uint16_t) -20000)
+TEST_FUNCS (uint16_sub_3, uint16_t, , -= 3, 0, (uint16_t) -60000)
+TEST_FUNCS (uint32_sub, uint32_t, , -= 1, 0, (uint32_t) -20000)
+TEST_FUNCS (uint32_sub_3, uint32_t, , -= 3, 0, (uint32_t) -60000)
+TEST_FUNCS (uint64_sub, uint64_t, , -= 1, 0, (uint64_t) -20000)
+TEST_FUNCS (uint64_sub_3, uint64_t, , -= 3, 0, (uint64_t) -60000)
+TEST_FUNCS (uint64_sub_neg, uint64_t, , -= 1, 10000, (uint64_t) -10000)
+TEST_FUNCS (float_sub, float, , -= 1, 0, -20000)
+TEST_FUNCS (double_sub, double, , -= 1, 0, -20000)
+TEST_FUNCS (long_double_sub, long double, , -= 1, 0, -20000)
+TEST_FUNCS (complex_float_sub, _Complex float, , -= 1, 0, -20000)
+TEST_FUNCS (complex_double_sub, _Complex double, , -= 1, 0, -20000)
+TEST_FUNCS (complex_long_double_sub, _Complex long double, , -= 1, 0, -20000)
+TEST_FUNCS (uint8_postdec, uint8_t, , --, 0, (uint8_t) -20000)
+TEST_FUNCS (uint16_postdec, uint16_t, , --, 0, (uint16_t) -20000)
+TEST_FUNCS (uint32_postdec, uint32_t, , --, 0, (uint32_t) -20000)
+TEST_FUNCS (uint64_postdec, uint64_t, , --, 0, (uint64_t) -20000)
+TEST_FUNCS (uint64_postdec_neg, uint64_t, , --, 10000, (uint64_t) -10000)
+TEST_FUNCS (float_postdec, float, , --, 0, -20000)
+TEST_FUNCS (double_postdec, double, , --, 0, -20000)
+TEST_FUNCS (long_double_postdec, long double, , --, 0, -20000)
+TEST_FUNCS (uint8_predec, uint8_t, --, , 0, (uint8_t) -20000)
+TEST_FUNCS (uint16_predec, uint16_t, --, , 0, (uint16_t) -20000)
+TEST_FUNCS (uint32_predec, uint32_t, --, , 0, (uint32_t) -20000)
+TEST_FUNCS (uint64_predec, uint64_t, --, , 0, (uint64_t) -20000)
+TEST_FUNCS (uint64_predec_neg, uint64_t, --, , 10000, (uint64_t) -10000)
+TEST_FUNCS (float_predec, float, --, , 0, -20000)
+TEST_FUNCS (double_predec, double, --, , 0, -20000)
+TEST_FUNCS (long_double_predec, long double, --, , 0, -20000)
+TEST_FUNCS (uint8_mul, uint8_t, , *= 3, 1, (uint8_t) 0x81)
+TEST_FUNCS (uint16_mul, uint16_t, , *= 3, 1, (uint16_t) 0x9681)
+TEST_FUNCS (uint32_mul, uint32_t, , *= 3, 1, (uint32_t) 0x62b49681U)
+TEST_FUNCS (uint64_mul, uint64_t, , *= 3, 1, (uint64_t) 0xcd926beb62b49681ULL)
+
+int
+main (void)
+{
+ int ret = 0;
+ ret |= test_main_uint8_add ();
+ ret |= test_main_uint8_add_3 ();
+ ret |= test_main_uint16_add ();
+ ret |= test_main_uint16_add_3 ();
+ ret |= test_main_uint32_add ();
+ ret |= test_main_uint32_add_3 ();
+ ret |= test_main_uint64_add ();
+ ret |= test_main_uint64_add_3 ();
+ ret |= test_main_uint64_add_neg ();
+ ret |= test_main_float_add ();
+ ret |= test_main_double_add ();
+ ret |= test_main_long_double_add ();
+ ret |= test_main_complex_float_add ();
+ ret |= test_main_complex_double_add ();
+ ret |= test_main_complex_long_double_add ();
+ ret |= test_main_uint8_postinc ();
+ ret |= test_main_uint16_postinc ();
+ ret |= test_main_uint32_postinc ();
+ ret |= test_main_uint64_postinc ();
+ ret |= test_main_uint64_postinc_neg ();
+ ret |= test_main_float_postinc ();
+ ret |= test_main_double_postinc ();
+ ret |= test_main_long_double_postinc ();
+ ret |= test_main_uint8_preinc ();
+ ret |= test_main_uint16_preinc ();
+ ret |= test_main_uint32_preinc ();
+ ret |= test_main_uint64_preinc ();
+ ret |= test_main_uint64_preinc_neg ();
+ ret |= test_main_float_preinc ();
+ ret |= test_main_double_preinc ();
+ ret |= test_main_long_double_preinc ();
+ ret |= test_main_uint8_sub ();
+ ret |= test_main_uint8_sub_3 ();
+ ret |= test_main_uint16_sub ();
+ ret |= test_main_uint16_sub_3 ();
+ ret |= test_main_uint32_sub ();
+ ret |= test_main_uint32_sub_3 ();
+ ret |= test_main_uint64_sub ();
+ ret |= test_main_uint64_sub_3 ();
+ ret |= test_main_uint64_sub_neg ();
+ ret |= test_main_float_sub ();
+ ret |= test_main_double_sub ();
+ ret |= test_main_long_double_sub ();
+ ret |= test_main_complex_float_sub ();
+ ret |= test_main_complex_double_sub ();
+ ret |= test_main_complex_long_double_sub ();
+ ret |= test_main_uint8_postdec ();
+ ret |= test_main_uint16_postdec ();
+ ret |= test_main_uint32_postdec ();
+ ret |= test_main_uint64_postdec ();
+ ret |= test_main_uint64_postdec_neg ();
+ ret |= test_main_float_postdec ();
+ ret |= test_main_double_postdec ();
+ ret |= test_main_long_double_postdec ();
+ ret |= test_main_uint8_predec ();
+ ret |= test_main_uint16_predec ();
+ ret |= test_main_uint32_predec ();
+ ret |= test_main_uint64_predec ();
+ ret |= test_main_uint64_predec_neg ();
+ ret |= test_main_float_predec ();
+ ret |= test_main_double_predec ();
+ ret |= test_main_long_double_predec ();
+ ret |= test_main_uint8_mul ();
+ ret |= test_main_uint16_mul ();
+ ret |= test_main_uint32_mul ();
+ ret |= test_main_uint64_mul ();
+ if (ret)
+ abort ();
+ else
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/atomic/c11-atomic-exec-5.c b/gcc/testsuite/gcc.dg/atomic/c11-atomic-exec-5.c
new file mode 100644
index 00000000000..9e6977b4286
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/atomic/c11-atomic-exec-5.c
@@ -0,0 +1,541 @@
+/* Test for _Atomic in C11. Test floating-point exceptions for
+ compound assignment are consistent with result (so that if multiple
+ iterations of the compare-and-exchange loop are needed, exceptions
+ get properly cleared). */
+/* { dg-do run } */
+/* { dg-options "-std=c11 -pedantic-errors -pthread -D_POSIX_C_SOURCE=200809L" } */
+/* { dg-require-effective-target fenv_exceptions } */
+/* { dg-require-effective-target pthread } */
+
+#include <fenv.h>
+#include <float.h>
+#include <pthread.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define TEST_ALL_EXCEPT (FE_DIVBYZERO \
+ | FE_INEXACT \
+ | FE_INVALID \
+ | FE_OVERFLOW \
+ | FE_UNDERFLOW)
+
+#define ITER_COUNT 10000
+
+static volatile _Atomic bool thread_ready, thread_stop;
+
+/* Generate test code (with NAME used to name functions and variables)
+ for atomic compound assignments to a variable of type LHSTYPE. One
+ thread repeatedly stores the values INIT1 and INIT2 in a variable,
+ while the other repeatedly executes PRE var POST having set
+ floating-point exceptions to BEXC. If the value of the assignment
+ operation satisfies VALTEST1 (var), the floating-point exceptions
+ should be BEXC | EXC1; otherwise, they should be BEXC | EXC2. A
+ function test_main_##NAME is generated that returns nonzero on
+ failure, zero on success. */
+
+#define TEST_FUNCS(NAME, LHSTYPE, PRE, POST, BEXC, \
+ INIT1, VALTEST1, EXC1, INIT2, EXC2) \
+ \
+static volatile _Atomic LHSTYPE var_##NAME; \
+ \
+static void * \
+test_thread_##NAME (void *arg) \
+{ \
+ thread_ready = true; \
+ while (!thread_stop) \
+ { \
+ var_##NAME = (INIT1); \
+ var_##NAME = (INIT2); \
+ } \
+ return NULL; \
+} \
+ \
+static int \
+test_main_##NAME (void) \
+{ \
+ thread_stop = false; \
+ thread_ready = false; \
+ var_##NAME = (INIT1); \
+ pthread_t thread_id; \
+ int pret = pthread_create (&thread_id, NULL, test_thread_##NAME, \
+ NULL); \
+ if (pret != 0) \
+ { \
+ printf ("pthread_create failed: %d\n", pret); \
+ return 1; \
+ } \
+ int num_1_pass = 0, num_1_fail = 0, num_2_pass = 0, num_2_fail = 0; \
+ while (!thread_ready) \
+ ; \
+ for (int i = 0; i < ITER_COUNT; i++) \
+ { \
+ feclearexcept (FE_ALL_EXCEPT); \
+ feraiseexcept (BEXC); \
+ LHSTYPE r = (PRE var_##NAME POST); \
+ int rexc = fetestexcept (TEST_ALL_EXCEPT); \
+ if (VALTEST1 (r)) \
+ { \
+ if (rexc == ((BEXC) | (EXC1))) \
+ num_1_pass++; \
+ else \
+ num_1_fail++; \
+ var_##NAME = (INIT2); \
+ } \
+ else \
+ { \
+ if (rexc == ((BEXC) | (EXC2))) \
+ num_2_pass++; \
+ else \
+ num_2_fail++; \
+ var_##NAME = (INIT1); \
+ } \
+ } \
+ thread_stop = true; \
+ pthread_join (thread_id, NULL); \
+ printf (#NAME " (a) %d pass, %d fail; (b) %d pass, %d fail\n", \
+ num_1_pass, num_1_fail, num_2_pass, num_2_fail); \
+ return num_1_fail || num_2_fail; \
+}
+
+TEST_FUNCS (float_add_invalid, float, , += __builtin_inff (), 0,
+ 0, __builtin_isinf, 0,
+ -__builtin_inff (), FE_INVALID)
+TEST_FUNCS (float_add_invalid_prev, float, , += __builtin_inff (),
+ FE_DIVBYZERO | FE_INEXACT | FE_OVERFLOW | FE_UNDERFLOW,
+ 0, __builtin_isinf, 0,
+ -__builtin_inff (), FE_INVALID)
+TEST_FUNCS (float_add_overflow, float, , += FLT_MAX, 0,
+ FLT_MAX, __builtin_isinf, FE_OVERFLOW | FE_INEXACT,
+ 0, 0)
+TEST_FUNCS (float_add_overflow_prev, float, , += FLT_MAX, FE_INVALID,
+ FLT_MAX, __builtin_isinf, FE_OVERFLOW | FE_INEXACT,
+ 0, 0)
+TEST_FUNCS (float_add_overflow_double, float, , += (double) FLT_MAX, 0,
+ FLT_MAX, __builtin_isinf, FE_OVERFLOW | FE_INEXACT,
+ 0, 0)
+TEST_FUNCS (float_add_overflow_long_double, float, , += (long double) FLT_MAX, 0,
+ FLT_MAX, __builtin_isinf, FE_OVERFLOW | FE_INEXACT,
+ 0, 0)
+#define NOT_FLT_EPSILON_2(X) ((X) != FLT_EPSILON / 2)
+TEST_FUNCS (float_add_inexact, float, , += FLT_EPSILON / 2, 0,
+ 1.0f, NOT_FLT_EPSILON_2, FE_INEXACT,
+ 0, 0)
+#define NOT_0(X) ((X) != 0)
+TEST_FUNCS (float_add_inexact_int, float, , += 1, 0,
+ FLT_EPSILON / 2, NOT_0, FE_INEXACT,
+ -1, 0)
+TEST_FUNCS (float_preinc_inexact, float, ++, , 0,
+ FLT_EPSILON / 2, NOT_0, FE_INEXACT,
+ -1, 0)
+#define NOT_MINUS_1(X) ((X) != -1)
+TEST_FUNCS (float_postinc_inexact, float, , ++, 0,
+ FLT_EPSILON / 2, NOT_MINUS_1, FE_INEXACT,
+ -1, 0)
+#if FLT_EVAL_METHOD == 0
+TEST_FUNCS (long_add_float_inexact, long, , += 2 / FLT_EPSILON, 0,
+ 1, NOT_0, FE_INEXACT,
+ -2 / FLT_EPSILON, 0)
+#endif
+#define REAL_ISINF(X) (__builtin_isinf (__real__ (X)))
+TEST_FUNCS (complex_float_add_overflow, _Complex float, , += FLT_MAX, 0,
+ FLT_MAX, REAL_ISINF, FE_OVERFLOW | FE_INEXACT,
+ 0, 0)
+TEST_FUNCS (float_sub_invalid, float, , -= __builtin_inff (), 0,
+ 0, __builtin_isinf, 0,
+ __builtin_inff (), FE_INVALID)
+TEST_FUNCS (float_sub_overflow, float, , -= FLT_MAX, 0,
+ -FLT_MAX, __builtin_isinf, FE_OVERFLOW | FE_INEXACT,
+ 0, 0)
+#define NOT_MINUS_FLT_EPSILON_2(X) ((X) != -FLT_EPSILON / 2)
+TEST_FUNCS (float_sub_inexact, float, , -= FLT_EPSILON / 2, 0,
+ -1.0f, NOT_MINUS_FLT_EPSILON_2, FE_INEXACT,
+ 0, 0)
+#define NOT_0(X) ((X) != 0)
+TEST_FUNCS (float_sub_inexact_int, float, , -= 1, 0,
+ -FLT_EPSILON / 2, NOT_0, FE_INEXACT,
+ 1, 0)
+TEST_FUNCS (float_predec_inexact, float, --, , 0,
+ -FLT_EPSILON / 2, NOT_0, FE_INEXACT,
+ 1, 0)
+#define NOT_1(X) ((X) != 1)
+TEST_FUNCS (float_postdec_inexact, float, , --, 0,
+ -FLT_EPSILON / 2, NOT_1, FE_INEXACT,
+ 1, 0)
+#if FLT_EVAL_METHOD == 0
+TEST_FUNCS (long_sub_float_inexact, long, , -= 2 / FLT_EPSILON, 0,
+ -1, NOT_0, FE_INEXACT,
+ 2 / FLT_EPSILON, 0)
+#endif
+TEST_FUNCS (complex_float_sub_overflow, _Complex float, , -= FLT_MAX, 0,
+ -FLT_MAX, REAL_ISINF, FE_OVERFLOW | FE_INEXACT,
+ 0, 0)
+TEST_FUNCS (float_mul_invalid, float, , *= __builtin_inff (), 0,
+ __builtin_inff (), __builtin_isinf, 0,
+ 0, FE_INVALID)
+TEST_FUNCS (float_mul_overflow, float, , *= FLT_MAX, 0,
+ FLT_MAX, __builtin_isinf, FE_OVERFLOW | FE_INEXACT,
+ 0, 0)
+#define IS_0(X) ((X) == 0)
+TEST_FUNCS (float_mul_underflow, float, , *= FLT_MIN, 0,
+ FLT_MIN, IS_0, FE_UNDERFLOW | FE_INEXACT,
+ 1, 0)
+TEST_FUNCS (float_mul_inexact, float, , *= 1 + FLT_EPSILON, 0,
+ 1 + FLT_EPSILON, NOT_0, FE_INEXACT,
+ 0, 0)
+TEST_FUNCS (float_mul_inexact_int, float, , *= 3, 0,
+ 1 + FLT_EPSILON, NOT_0, FE_INEXACT,
+ 0, 0)
+#if FLT_EVAL_METHOD == 0
+TEST_FUNCS(long_mul_float_inexact, long, , *= 3.0f, 0,
+ 1 + 1 / FLT_EPSILON, NOT_0, FE_INEXACT,
+ 0, 0)
+#endif
+TEST_FUNCS (complex_float_mul_overflow, _Complex float, , *= FLT_MAX, 0,
+ FLT_MAX, REAL_ISINF, FE_OVERFLOW | FE_INEXACT,
+ 0, 0)
+TEST_FUNCS (float_div_invalid_divbyzero, float, , /= 0.0f, 0,
+ 1, __builtin_isinf, FE_DIVBYZERO,
+ 0, FE_INVALID)
+TEST_FUNCS (float_div_overflow, float, , /= FLT_MIN, 0,
+ FLT_MAX, __builtin_isinf, FE_OVERFLOW | FE_INEXACT,
+ 0, 0)
+TEST_FUNCS (float_div_underflow, float, , /= FLT_MAX, 0,
+ FLT_MIN, IS_0, FE_UNDERFLOW | FE_INEXACT,
+ FLT_MAX, 0)
+TEST_FUNCS (float_div_inexact, float, , /= 3.0f, 0,
+ 1, NOT_0, FE_INEXACT,
+ 0, 0)
+TEST_FUNCS (float_div_inexact_int, float, , /= 3, 0,
+ 1, NOT_0, FE_INEXACT,
+ 0, 0)
+TEST_FUNCS (int_div_float_inexact, int, , /= 3.0f, 0,
+ 4, NOT_0, FE_INEXACT,
+ 0, 0)
+TEST_FUNCS (complex_float_div_overflow, _Complex float, , /= FLT_MIN, 0,
+ FLT_MAX, REAL_ISINF, FE_OVERFLOW | FE_INEXACT,
+ 0, 0)
+
+TEST_FUNCS (double_add_invalid, double, , += __builtin_inf (), 0,
+ 0, __builtin_isinf, 0,
+ -__builtin_inf (), FE_INVALID)
+TEST_FUNCS (double_add_overflow, double, , += DBL_MAX, 0,
+ DBL_MAX, __builtin_isinf, FE_OVERFLOW | FE_INEXACT,
+ 0, 0)
+TEST_FUNCS (double_add_overflow_long_double, double, , += (long double) DBL_MAX, 0,
+ DBL_MAX, __builtin_isinf, FE_OVERFLOW | FE_INEXACT,
+ 0, 0)
+#define NOT_DBL_EPSILON_2(X) ((X) != DBL_EPSILON / 2)
+TEST_FUNCS (double_add_inexact, double, , += DBL_EPSILON / 2, 0,
+ 1.0, NOT_DBL_EPSILON_2, FE_INEXACT,
+ 0, 0)
+TEST_FUNCS (double_add_inexact_int, double, , += 1, 0,
+ DBL_EPSILON / 2, NOT_0, FE_INEXACT,
+ -1, 0)
+TEST_FUNCS (double_preinc_inexact, double, ++, , 0,
+ DBL_EPSILON / 2, NOT_0, FE_INEXACT,
+ -1, 0)
+TEST_FUNCS (double_postinc_inexact, double, , ++, 0,
+ DBL_EPSILON / 2, NOT_MINUS_1, FE_INEXACT,
+ -1, 0)
+#if FLT_EVAL_METHOD == 0
+TEST_FUNCS (long_long_add_double_inexact, long long, , += 2 / DBL_EPSILON, 0,
+ 1, NOT_0, FE_INEXACT,
+ -2 / DBL_EPSILON, 0)
+#endif
+TEST_FUNCS (complex_double_add_overflow, _Complex double, , += DBL_MAX, 0,
+ DBL_MAX, REAL_ISINF, FE_OVERFLOW | FE_INEXACT,
+ 0, 0)
+TEST_FUNCS (double_sub_invalid, double, , -= __builtin_inf (), 0,
+ 0, __builtin_isinf, 0,
+ __builtin_inf (), FE_INVALID)
+TEST_FUNCS (double_sub_overflow, double, , -= DBL_MAX, 0,
+ -DBL_MAX, __builtin_isinf, FE_OVERFLOW | FE_INEXACT,
+ 0, 0)
+#define NOT_MINUS_DBL_EPSILON_2(X) ((X) != -DBL_EPSILON / 2)
+TEST_FUNCS (double_sub_inexact, double, , -= DBL_EPSILON / 2, 0,
+ -1.0, NOT_MINUS_DBL_EPSILON_2, FE_INEXACT,
+ 0, 0)
+TEST_FUNCS (double_sub_inexact_int, double, , -= 1, 0,
+ -DBL_EPSILON / 2, NOT_0, FE_INEXACT,
+ 1, 0)
+TEST_FUNCS (double_predec_inexact, double, --, , 0,
+ -DBL_EPSILON / 2, NOT_0, FE_INEXACT,
+ 1, 0)
+TEST_FUNCS (double_postdec_inexact, double, , --, 0,
+ -DBL_EPSILON / 2, NOT_1, FE_INEXACT,
+ 1, 0)
+#if FLT_EVAL_METHOD == 0
+TEST_FUNCS (long_long_sub_double_inexact, long long, , -= 2 / DBL_EPSILON, 0,
+ -1, NOT_0, FE_INEXACT,
+ 2 / DBL_EPSILON, 0)
+#endif
+TEST_FUNCS (complex_double_sub_overflow, _Complex double, , -= DBL_MAX, 0,
+ -DBL_MAX, REAL_ISINF, FE_OVERFLOW | FE_INEXACT,
+ 0, 0)
+TEST_FUNCS (double_mul_invalid, double, , *= __builtin_inf (), 0,
+ __builtin_inf (), __builtin_isinf, 0,
+ 0, FE_INVALID)
+TEST_FUNCS (double_mul_overflow, double, , *= DBL_MAX, 0,
+ DBL_MAX, __builtin_isinf, FE_OVERFLOW | FE_INEXACT,
+ 0, 0)
+TEST_FUNCS (double_mul_overflow_float, double, , *= FLT_MAX, 0,
+ DBL_MAX, __builtin_isinf, FE_OVERFLOW | FE_INEXACT,
+ 0, 0)
+TEST_FUNCS (double_mul_underflow, double, , *= DBL_MIN, 0,
+ DBL_MIN, IS_0, FE_UNDERFLOW | FE_INEXACT,
+ 1, 0)
+TEST_FUNCS (double_mul_inexact, double, , *= 1 + DBL_EPSILON, 0,
+ 1 + DBL_EPSILON, NOT_0, FE_INEXACT,
+ 0, 0)
+TEST_FUNCS (double_mul_inexact_int, double, , *= 3, 0,
+ 1 + DBL_EPSILON, NOT_0, FE_INEXACT,
+ 0, 0)
+#if FLT_EVAL_METHOD == 0
+TEST_FUNCS(long_long_mul_double_inexact, long long, , *= 3.0, 0,
+ 1 + 1 / DBL_EPSILON, NOT_0, FE_INEXACT,
+ 0, 0)
+#endif
+TEST_FUNCS (complex_double_mul_overflow, _Complex double, , *= DBL_MAX, 0,
+ DBL_MAX, REAL_ISINF, FE_OVERFLOW | FE_INEXACT,
+ 0, 0)
+TEST_FUNCS (double_div_invalid_divbyzero, double, , /= 0.0, 0,
+ 1, __builtin_isinf, FE_DIVBYZERO,
+ 0, FE_INVALID)
+TEST_FUNCS (double_div_overflow, double, , /= DBL_MIN, 0,
+ DBL_MAX, __builtin_isinf, FE_OVERFLOW | FE_INEXACT,
+ 0, 0)
+TEST_FUNCS (double_div_underflow, double, , /= DBL_MAX, 0,
+ DBL_MIN, IS_0, FE_UNDERFLOW | FE_INEXACT,
+ DBL_MAX, 0)
+TEST_FUNCS (double_div_inexact, double, , /= 3.0, 0,
+ 1, NOT_0, FE_INEXACT,
+ 0, 0)
+TEST_FUNCS (double_div_inexact_int, double, , /= 3, 0,
+ 1, NOT_0, FE_INEXACT,
+ 0, 0)
+TEST_FUNCS (int_div_double_inexact, int, , /= 3.0, 0,
+ 4, NOT_0, FE_INEXACT,
+ 0, 0)
+TEST_FUNCS (complex_double_div_overflow, _Complex double, , /= DBL_MIN, 0,
+ DBL_MAX, REAL_ISINF, FE_OVERFLOW | FE_INEXACT,
+ 0, 0)
+
+TEST_FUNCS (long_double_add_invalid, long double, , += __builtin_infl (), 0,
+ 0, __builtin_isinf, 0,
+ -__builtin_infl (), FE_INVALID)
+TEST_FUNCS (long_double_add_overflow, long double, , += LDBL_MAX, 0,
+ LDBL_MAX, __builtin_isinf, FE_OVERFLOW | FE_INEXACT,
+ 0, 0)
+#define NOT_LDBL_EPSILON_2(X) ((X) != LDBL_EPSILON / 2)
+#if LDBL_MANT_DIG != 106
+TEST_FUNCS (long_double_add_inexact, long double, , += LDBL_EPSILON / 2, 0,
+ 1.0L, NOT_LDBL_EPSILON_2, FE_INEXACT,
+ 0, 0)
+TEST_FUNCS (long_double_add_inexact_int, long double, , += 1, 0,
+ LDBL_EPSILON / 2, NOT_0, FE_INEXACT,
+ -1, 0)
+TEST_FUNCS (long_double_preinc_inexact, long double, ++, , 0,
+ LDBL_EPSILON / 2, NOT_0, FE_INEXACT,
+ -1, 0)
+TEST_FUNCS (long_double_postinc_inexact, long double, , ++, 0,
+ LDBL_EPSILON / 2, NOT_MINUS_1, FE_INEXACT,
+ -1, 0)
+#endif
+TEST_FUNCS (complex_long_double_add_overflow, _Complex long double, , += LDBL_MAX, 0,
+ LDBL_MAX, REAL_ISINF, FE_OVERFLOW | FE_INEXACT,
+ 0, 0)
+TEST_FUNCS (long_double_sub_invalid, long double, , -= __builtin_infl (), 0,
+ 0, __builtin_isinf, 0,
+ __builtin_infl (), FE_INVALID)
+TEST_FUNCS (long_double_sub_overflow, long double, , -= LDBL_MAX, 0,
+ -LDBL_MAX, __builtin_isinf, FE_OVERFLOW | FE_INEXACT,
+ 0, 0)
+#define NOT_MINUS_LDBL_EPSILON_2(X) ((X) != -LDBL_EPSILON / 2)
+#if LDBL_MANT_DIG != 106
+TEST_FUNCS (long_double_sub_inexact, long double, , -= LDBL_EPSILON / 2, 0,
+ -1.0L, NOT_MINUS_LDBL_EPSILON_2, FE_INEXACT,
+ 0, 0)
+TEST_FUNCS (long_double_sub_inexact_int, long double, , -= 1, 0,
+ -LDBL_EPSILON / 2, NOT_0, FE_INEXACT,
+ 1, 0)
+TEST_FUNCS (long_double_predec_inexact, long double, --, , 0,
+ -LDBL_EPSILON / 2, NOT_0, FE_INEXACT,
+ 1, 0)
+TEST_FUNCS (long_double_postdec_inexact, long double, , --, 0,
+ -LDBL_EPSILON / 2, NOT_1, FE_INEXACT,
+ 1, 0)
+#endif
+TEST_FUNCS (complex_long_double_sub_overflow, _Complex long double, , -= LDBL_MAX, 0,
+ -LDBL_MAX, REAL_ISINF, FE_OVERFLOW | FE_INEXACT,
+ 0, 0)
+TEST_FUNCS (long_double_mul_invalid, long double, , *= __builtin_infl (), 0,
+ __builtin_infl (), __builtin_isinf, 0,
+ 0, FE_INVALID)
+TEST_FUNCS (long_double_mul_overflow, long double, , *= LDBL_MAX, 0,
+ LDBL_MAX, __builtin_isinf, FE_OVERFLOW | FE_INEXACT,
+ 0, 0)
+TEST_FUNCS (long_double_mul_overflow_float, long double, , *= FLT_MAX, 0,
+ LDBL_MAX, __builtin_isinf, FE_OVERFLOW | FE_INEXACT,
+ 0, 0)
+TEST_FUNCS (long_double_mul_overflow_double, long double, , *= DBL_MAX, 0,
+ LDBL_MAX, __builtin_isinf, FE_OVERFLOW | FE_INEXACT,
+ 0, 0)
+TEST_FUNCS (long_double_mul_underflow, long double, , *= LDBL_MIN, 0,
+ LDBL_MIN, IS_0, FE_UNDERFLOW | FE_INEXACT,
+ 1, 0)
+#if LDBL_MANT_DIG != 106
+TEST_FUNCS (long_double_mul_inexact, long double, , *= 1 + LDBL_EPSILON, 0,
+ 1 + LDBL_EPSILON, NOT_0, FE_INEXACT,
+ 0, 0)
+TEST_FUNCS (long_double_mul_inexact_int, long double, , *= 3, 0,
+ 1 + LDBL_EPSILON, NOT_0, FE_INEXACT,
+ 0, 0)
+#endif
+TEST_FUNCS (complex_long_double_mul_overflow, _Complex long double, , *= LDBL_MAX, 0,
+ LDBL_MAX, REAL_ISINF, FE_OVERFLOW | FE_INEXACT,
+ 0, 0)
+TEST_FUNCS (long_double_div_invalid_divbyzero, long double, , /= 0.0L, 0,
+ 1, __builtin_isinf, FE_DIVBYZERO,
+ 0, FE_INVALID)
+TEST_FUNCS (long_double_div_overflow, long double, , /= LDBL_MIN, 0,
+ LDBL_MAX, __builtin_isinf, FE_OVERFLOW | FE_INEXACT,
+ 0, 0)
+TEST_FUNCS (long_double_div_underflow, long double, , /= LDBL_MAX, 0,
+ LDBL_MIN, IS_0, FE_UNDERFLOW | FE_INEXACT,
+ LDBL_MAX, 0)
+TEST_FUNCS (long_double_div_inexact, long double, , /= 3.0L, 0,
+ 1, NOT_0, FE_INEXACT,
+ 0, 0)
+TEST_FUNCS (long_double_div_inexact_int, long double, , /= 3, 0,
+ 1, NOT_0, FE_INEXACT,
+ 0, 0)
+TEST_FUNCS (int_div_long_double_inexact, int, , /= 3.0L, 0,
+ 4, NOT_0, FE_INEXACT,
+ 0, 0)
+TEST_FUNCS (complex_long_double_div_overflow, _Complex long double, , /= LDBL_MIN, 0,
+ LDBL_MAX, REAL_ISINF, FE_OVERFLOW | FE_INEXACT,
+ 0, 0)
+
+int
+main (void)
+{
+ int ret = 0;
+ ret |= test_main_float_add_invalid ();
+ ret |= test_main_float_add_invalid_prev ();
+ ret |= test_main_float_add_overflow ();
+ ret |= test_main_float_add_overflow_prev ();
+ ret |= test_main_float_add_overflow_double ();
+ ret |= test_main_float_add_overflow_long_double ();
+ ret |= test_main_float_add_inexact ();
+ ret |= test_main_float_add_inexact_int ();
+ ret |= test_main_float_preinc_inexact ();
+ ret |= test_main_float_postinc_inexact ();
+#if FLT_EVAL_METHOD == 0
+ ret |= test_main_long_add_float_inexact ();
+#endif
+ ret |= test_main_complex_float_add_overflow ();
+ ret |= test_main_float_sub_invalid ();
+ ret |= test_main_float_sub_overflow ();
+ ret |= test_main_float_sub_inexact ();
+ ret |= test_main_float_sub_inexact_int ();
+ ret |= test_main_float_predec_inexact ();
+ ret |= test_main_float_postdec_inexact ();
+#if FLT_EVAL_METHOD == 0
+ ret |= test_main_long_sub_float_inexact ();
+#endif
+ ret |= test_main_complex_float_sub_overflow ();
+ ret |= test_main_float_mul_invalid ();
+ ret |= test_main_float_mul_overflow ();
+ ret |= test_main_float_mul_underflow ();
+ ret |= test_main_float_mul_inexact ();
+ ret |= test_main_float_mul_inexact_int ();
+#if FLT_EVAL_METHOD == 0
+ ret |= test_main_long_mul_float_inexact ();
+#endif
+ ret |= test_main_complex_float_mul_overflow ();
+ ret |= test_main_float_div_invalid_divbyzero ();
+ ret |= test_main_float_div_overflow ();
+ ret |= test_main_float_div_underflow ();
+ ret |= test_main_float_div_inexact ();
+ ret |= test_main_float_div_inexact_int ();
+ ret |= test_main_int_div_float_inexact ();
+ ret |= test_main_complex_float_div_overflow ();
+ ret |= test_main_double_add_invalid ();
+ ret |= test_main_double_add_overflow ();
+ ret |= test_main_double_add_overflow_long_double ();
+ ret |= test_main_double_add_inexact ();
+ ret |= test_main_double_add_inexact_int ();
+ ret |= test_main_double_preinc_inexact ();
+ ret |= test_main_double_postinc_inexact ();
+#if FLT_EVAL_METHOD == 0
+ ret |= test_main_long_long_add_double_inexact ();
+#endif
+ ret |= test_main_complex_double_add_overflow ();
+ ret |= test_main_double_sub_invalid ();
+ ret |= test_main_double_sub_overflow ();
+ ret |= test_main_double_sub_inexact ();
+ ret |= test_main_double_sub_inexact_int ();
+ ret |= test_main_double_predec_inexact ();
+ ret |= test_main_double_postdec_inexact ();
+#if FLT_EVAL_METHOD == 0
+ ret |= test_main_long_long_sub_double_inexact ();
+#endif
+ ret |= test_main_complex_double_sub_overflow ();
+ ret |= test_main_double_mul_invalid ();
+ ret |= test_main_double_mul_overflow ();
+ ret |= test_main_double_mul_overflow_float ();
+ ret |= test_main_double_mul_underflow ();
+ ret |= test_main_double_mul_inexact ();
+ ret |= test_main_double_mul_inexact_int ();
+#if FLT_EVAL_METHOD == 0
+ ret |= test_main_long_long_mul_double_inexact ();
+#endif
+ ret |= test_main_complex_double_mul_overflow ();
+ ret |= test_main_double_div_invalid_divbyzero ();
+ ret |= test_main_double_div_overflow ();
+ ret |= test_main_double_div_underflow ();
+ ret |= test_main_double_div_inexact ();
+ ret |= test_main_double_div_inexact_int ();
+ ret |= test_main_int_div_double_inexact ();
+ ret |= test_main_complex_double_div_overflow ();
+ ret |= test_main_long_double_add_invalid ();
+ ret |= test_main_long_double_add_overflow ();
+#if LDBL_MANT_DIG != 106
+ ret |= test_main_long_double_add_inexact ();
+ ret |= test_main_long_double_add_inexact_int ();
+ ret |= test_main_long_double_preinc_inexact ();
+ ret |= test_main_long_double_postinc_inexact ();
+#endif
+ ret |= test_main_complex_long_double_add_overflow ();
+ ret |= test_main_long_double_sub_invalid ();
+ ret |= test_main_long_double_sub_overflow ();
+#if LDBL_MANT_DIG != 106
+ ret |= test_main_long_double_sub_inexact ();
+ ret |= test_main_long_double_sub_inexact_int ();
+ ret |= test_main_long_double_predec_inexact ();
+ ret |= test_main_long_double_postdec_inexact ();
+#endif
+ ret |= test_main_complex_long_double_sub_overflow ();
+ ret |= test_main_long_double_mul_invalid ();
+ ret |= test_main_long_double_mul_overflow ();
+ ret |= test_main_long_double_mul_overflow_float ();
+ ret |= test_main_long_double_mul_overflow_double ();
+ ret |= test_main_long_double_mul_underflow ();
+#if LDBL_MANT_DIG != 106
+ ret |= test_main_long_double_mul_inexact ();
+ ret |= test_main_long_double_mul_inexact_int ();
+#endif
+ ret |= test_main_complex_long_double_mul_overflow ();
+ ret |= test_main_long_double_div_invalid_divbyzero ();
+ ret |= test_main_long_double_div_overflow ();
+ ret |= test_main_long_double_div_underflow ();
+ ret |= test_main_long_double_div_inexact ();
+ ret |= test_main_long_double_div_inexact_int ();
+ ret |= test_main_int_div_long_double_inexact ();
+ ret |= test_main_complex_long_double_div_overflow ();
+ if (ret != 0)
+ abort ();
+ else
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/atomic/stdatomic-compare-exchange-1.c b/gcc/testsuite/gcc.dg/atomic/stdatomic-compare-exchange-1.c
new file mode 100644
index 00000000000..d44c17dd60f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/atomic/stdatomic-compare-exchange-1.c
@@ -0,0 +1,81 @@
+/* Test atomic_compare_exchange routines for existence and proper
+ execution on 1-byte values with each valid memory model. */
+/* { dg-do run } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+#include <stdatomic.h>
+
+extern void abort (void);
+
+_Atomic char v = ATOMIC_VAR_INIT (0);
+char expected = 0;
+char max = ~0;
+char desired = ~0;
+char zero = 0;
+
+int
+main ()
+{
+
+ if (!atomic_compare_exchange_strong_explicit (&v, &expected, max, memory_order_relaxed, memory_order_relaxed))
+ abort ();
+ if (expected != 0)
+ abort ();
+
+ if (atomic_compare_exchange_strong_explicit (&v, &expected, 0, memory_order_acquire, memory_order_relaxed))
+ abort ();
+ if (expected != max)
+ abort ();
+
+ if (!atomic_compare_exchange_strong_explicit (&v, &expected, 0, memory_order_release, memory_order_acquire))
+ abort ();
+ if (expected != max)
+ abort ();
+ if (v != 0)
+ abort ();
+
+ if (atomic_compare_exchange_weak_explicit (&v, &expected, desired, memory_order_acq_rel, memory_order_acquire))
+ abort ();
+ if (expected != 0)
+ abort ();
+
+ if (!atomic_compare_exchange_strong_explicit (&v, &expected, desired, memory_order_seq_cst, memory_order_seq_cst))
+ abort ();
+ if (expected != 0)
+ abort ();
+ if (v != max)
+ abort ();
+
+ v = 0;
+
+ if (!atomic_compare_exchange_strong (&v, &expected, max))
+ abort ();
+ if (expected != 0)
+ abort ();
+
+ if (atomic_compare_exchange_strong (&v, &expected, zero))
+ abort ();
+ if (expected != max)
+ abort ();
+
+ if (!atomic_compare_exchange_strong (&v, &expected, zero))
+ abort ();
+ if (expected != max)
+ abort ();
+ if (v != 0)
+ abort ();
+
+ if (atomic_compare_exchange_weak (&v, &expected, desired))
+ abort ();
+ if (expected != 0)
+ abort ();
+
+ if (!atomic_compare_exchange_strong (&v, &expected, desired))
+ abort ();
+ if (expected != 0)
+ abort ();
+ if (v != max)
+ abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/atomic/stdatomic-compare-exchange-2.c b/gcc/testsuite/gcc.dg/atomic/stdatomic-compare-exchange-2.c
new file mode 100644
index 00000000000..5647ee66335
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/atomic/stdatomic-compare-exchange-2.c
@@ -0,0 +1,81 @@
+/* Test atomic_compare_exchange routines for existence and proper
+ execution on 2-byte values with each valid memory model. */
+/* { dg-do run } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+#include <stdatomic.h>
+
+extern void abort (void);
+
+_Atomic short v = ATOMIC_VAR_INIT (0);
+short expected = 0;
+short max = ~0;
+short desired = ~0;
+short zero = 0;
+
+int
+main ()
+{
+
+ if (!atomic_compare_exchange_strong_explicit (&v, &expected, max, memory_order_relaxed, memory_order_relaxed))
+ abort ();
+ if (expected != 0)
+ abort ();
+
+ if (atomic_compare_exchange_strong_explicit (&v, &expected, 0, memory_order_acquire, memory_order_relaxed))
+ abort ();
+ if (expected != max)
+ abort ();
+
+ if (!atomic_compare_exchange_strong_explicit (&v, &expected, 0, memory_order_release, memory_order_acquire))
+ abort ();
+ if (expected != max)
+ abort ();
+ if (v != 0)
+ abort ();
+
+ if (atomic_compare_exchange_weak_explicit (&v, &expected, desired, memory_order_acq_rel, memory_order_acquire))
+ abort ();
+ if (expected != 0)
+ abort ();
+
+ if (!atomic_compare_exchange_strong_explicit (&v, &expected, desired, memory_order_seq_cst, memory_order_seq_cst))
+ abort ();
+ if (expected != 0)
+ abort ();
+ if (v != max)
+ abort ();
+
+ v = 0;
+
+ if (!atomic_compare_exchange_strong (&v, &expected, max))
+ abort ();
+ if (expected != 0)
+ abort ();
+
+ if (atomic_compare_exchange_strong (&v, &expected, zero))
+ abort ();
+ if (expected != max)
+ abort ();
+
+ if (!atomic_compare_exchange_strong (&v, &expected, zero))
+ abort ();
+ if (expected != max)
+ abort ();
+ if (v != 0)
+ abort ();
+
+ if (atomic_compare_exchange_weak (&v, &expected, desired))
+ abort ();
+ if (expected != 0)
+ abort ();
+
+ if (!atomic_compare_exchange_strong (&v, &expected, desired))
+ abort ();
+ if (expected != 0)
+ abort ();
+ if (v != max)
+ abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/atomic/stdatomic-compare-exchange-3.c b/gcc/testsuite/gcc.dg/atomic/stdatomic-compare-exchange-3.c
new file mode 100644
index 00000000000..e29784e5b21
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/atomic/stdatomic-compare-exchange-3.c
@@ -0,0 +1,81 @@
+/* Test atomic_compare_exchange routines for existence and proper
+ execution on 2-byte values with each valid memory model. */
+/* { dg-do run } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+#include <stdatomic.h>
+
+extern void abort (void);
+
+_Atomic int v = ATOMIC_VAR_INIT (0);
+int expected = 0;
+int max = ~0;
+int desired = ~0;
+int zero = 0;
+
+int
+main ()
+{
+
+ if (!atomic_compare_exchange_strong_explicit (&v, &expected, max, memory_order_relaxed, memory_order_relaxed))
+ abort ();
+ if (expected != 0)
+ abort ();
+
+ if (atomic_compare_exchange_strong_explicit (&v, &expected, 0, memory_order_acquire, memory_order_relaxed))
+ abort ();
+ if (expected != max)
+ abort ();
+
+ if (!atomic_compare_exchange_strong_explicit (&v, &expected, 0, memory_order_release, memory_order_acquire))
+ abort ();
+ if (expected != max)
+ abort ();
+ if (v != 0)
+ abort ();
+
+ if (atomic_compare_exchange_weak_explicit (&v, &expected, desired, memory_order_acq_rel, memory_order_acquire))
+ abort ();
+ if (expected != 0)
+ abort ();
+
+ if (!atomic_compare_exchange_strong_explicit (&v, &expected, desired, memory_order_seq_cst, memory_order_seq_cst))
+ abort ();
+ if (expected != 0)
+ abort ();
+ if (v != max)
+ abort ();
+
+ v = 0;
+
+ if (!atomic_compare_exchange_strong (&v, &expected, max))
+ abort ();
+ if (expected != 0)
+ abort ();
+
+ if (atomic_compare_exchange_strong (&v, &expected, zero))
+ abort ();
+ if (expected != max)
+ abort ();
+
+ if (!atomic_compare_exchange_strong (&v, &expected, zero))
+ abort ();
+ if (expected != max)
+ abort ();
+ if (v != 0)
+ abort ();
+
+ if (atomic_compare_exchange_weak (&v, &expected, desired))
+ abort ();
+ if (expected != 0)
+ abort ();
+
+ if (!atomic_compare_exchange_strong (&v, &expected, desired))
+ abort ();
+ if (expected != 0)
+ abort ();
+ if (v != max)
+ abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/atomic/stdatomic-compare-exchange-4.c b/gcc/testsuite/gcc.dg/atomic/stdatomic-compare-exchange-4.c
new file mode 100644
index 00000000000..e052dca0c94
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/atomic/stdatomic-compare-exchange-4.c
@@ -0,0 +1,81 @@
+/* Test atomic_compare_exchange routines for existence and proper
+ execution on 2-byte values with each valid memory model. */
+/* { dg-do run } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+#include <stdatomic.h>
+
+extern void abort (void);
+
+_Atomic long long v = ATOMIC_VAR_INIT (0);
+long long expected = 0;
+long long max = ~0LL;
+long long desired = ~0LL;
+long long zero = 0;
+
+int
+main ()
+{
+
+ if (!atomic_compare_exchange_strong_explicit (&v, &expected, max, memory_order_relaxed, memory_order_relaxed))
+ abort ();
+ if (expected != 0)
+ abort ();
+
+ if (atomic_compare_exchange_strong_explicit (&v, &expected, 0, memory_order_acquire, memory_order_relaxed))
+ abort ();
+ if (expected != max)
+ abort ();
+
+ if (!atomic_compare_exchange_strong_explicit (&v, &expected, 0, memory_order_release, memory_order_acquire))
+ abort ();
+ if (expected != max)
+ abort ();
+ if (v != 0)
+ abort ();
+
+ if (atomic_compare_exchange_weak_explicit (&v, &expected, desired, memory_order_acq_rel, memory_order_acquire))
+ abort ();
+ if (expected != 0)
+ abort ();
+
+ if (!atomic_compare_exchange_strong_explicit (&v, &expected, desired, memory_order_seq_cst, memory_order_seq_cst))
+ abort ();
+ if (expected != 0)
+ abort ();
+ if (v != max)
+ abort ();
+
+ v = 0;
+
+ if (!atomic_compare_exchange_strong (&v, &expected, max))
+ abort ();
+ if (expected != 0)
+ abort ();
+
+ if (atomic_compare_exchange_strong (&v, &expected, zero))
+ abort ();
+ if (expected != max)
+ abort ();
+
+ if (!atomic_compare_exchange_strong (&v, &expected, zero))
+ abort ();
+ if (expected != max)
+ abort ();
+ if (v != 0)
+ abort ();
+
+ if (atomic_compare_exchange_weak (&v, &expected, desired))
+ abort ();
+ if (expected != 0)
+ abort ();
+
+ if (!atomic_compare_exchange_strong (&v, &expected, desired))
+ abort ();
+ if (expected != 0)
+ abort ();
+ if (v != max)
+ abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/atomic/stdatomic-exchange-1.c b/gcc/testsuite/gcc.dg/atomic/stdatomic-exchange-1.c
new file mode 100644
index 00000000000..d7c751a34fe
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/atomic/stdatomic-exchange-1.c
@@ -0,0 +1,46 @@
+/* Test atomic_exchange routines for existence and proper execution on
+ 1-byte values with each valid memory model. */
+/* { dg-do run } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+#include <stdatomic.h>
+
+extern void abort (void);
+
+_Atomic char v;
+char count, ret;
+
+int
+main ()
+{
+ v = 0;
+ count = 0;
+
+ if (atomic_exchange_explicit (&v, count + 1, memory_order_relaxed) != count)
+ abort ();
+ count++;
+
+ if (atomic_exchange_explicit (&v, count + 1, memory_order_acquire) != count)
+ abort ();
+ count++;
+
+ if (atomic_exchange_explicit (&v, count + 1, memory_order_release) != count)
+ abort ();
+ count++;
+
+ if (atomic_exchange_explicit (&v, count + 1, memory_order_acq_rel) != count)
+ abort ();
+ count++;
+
+ if (atomic_exchange_explicit (&v, count + 1, memory_order_seq_cst) != count)
+ abort ();
+ count++;
+
+ count++;
+
+ ret = atomic_exchange (&v, count);
+ if (ret != count - 1 || v != count)
+ abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/atomic/stdatomic-exchange-2.c b/gcc/testsuite/gcc.dg/atomic/stdatomic-exchange-2.c
new file mode 100644
index 00000000000..2f1f7e2359d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/atomic/stdatomic-exchange-2.c
@@ -0,0 +1,46 @@
+/* Test atomic_exchange routines for existence and proper execution on
+ 2-byte values with each valid memory model. */
+/* { dg-do run } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+#include <stdatomic.h>
+
+extern void abort (void);
+
+_Atomic short v;
+short count, ret;
+
+int
+main ()
+{
+ v = 0;
+ count = 0;
+
+ if (atomic_exchange_explicit (&v, count + 1, memory_order_relaxed) != count)
+ abort ();
+ count++;
+
+ if (atomic_exchange_explicit (&v, count + 1, memory_order_acquire) != count)
+ abort ();
+ count++;
+
+ if (atomic_exchange_explicit (&v, count + 1, memory_order_release) != count)
+ abort ();
+ count++;
+
+ if (atomic_exchange_explicit (&v, count + 1, memory_order_acq_rel) != count)
+ abort ();
+ count++;
+
+ if (atomic_exchange_explicit (&v, count + 1, memory_order_seq_cst) != count)
+ abort ();
+ count++;
+
+ count++;
+
+ ret = atomic_exchange (&v, count);
+ if (ret != count - 1 || v != count)
+ abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/atomic/stdatomic-exchange-3.c b/gcc/testsuite/gcc.dg/atomic/stdatomic-exchange-3.c
new file mode 100644
index 00000000000..a62c5718785
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/atomic/stdatomic-exchange-3.c
@@ -0,0 +1,46 @@
+/* Test atomic_exchange routines for existence and proper execution on
+ 4-byte values with each valid memory model. */
+/* { dg-do run } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+#include <stdatomic.h>
+
+extern void abort (void);
+
+_Atomic int v;
+int count, ret;
+
+int
+main ()
+{
+ v = 0;
+ count = 0;
+
+ if (atomic_exchange_explicit (&v, count + 1, memory_order_relaxed) != count)
+ abort ();
+ count++;
+
+ if (atomic_exchange_explicit (&v, count + 1, memory_order_acquire) != count)
+ abort ();
+ count++;
+
+ if (atomic_exchange_explicit (&v, count + 1, memory_order_release) != count)
+ abort ();
+ count++;
+
+ if (atomic_exchange_explicit (&v, count + 1, memory_order_acq_rel) != count)
+ abort ();
+ count++;
+
+ if (atomic_exchange_explicit (&v, count + 1, memory_order_seq_cst) != count)
+ abort ();
+ count++;
+
+ count++;
+
+ ret = atomic_exchange (&v, count);
+ if (ret != count - 1 || v != count)
+ abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/atomic/stdatomic-exchange-4.c b/gcc/testsuite/gcc.dg/atomic/stdatomic-exchange-4.c
new file mode 100644
index 00000000000..1be9b299948
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/atomic/stdatomic-exchange-4.c
@@ -0,0 +1,46 @@
+/* Test atomic_exchange routines for existence and proper execution on
+ 8-byte values with each valid memory model. */
+/* { dg-do run } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+#include <stdatomic.h>
+
+extern void abort (void);
+
+_Atomic long long v;
+long long count, ret;
+
+int
+main ()
+{
+ v = 0;
+ count = 0;
+
+ if (atomic_exchange_explicit (&v, count + 1, memory_order_relaxed) != count)
+ abort ();
+ count++;
+
+ if (atomic_exchange_explicit (&v, count + 1, memory_order_acquire) != count)
+ abort ();
+ count++;
+
+ if (atomic_exchange_explicit (&v, count + 1, memory_order_release) != count)
+ abort ();
+ count++;
+
+ if (atomic_exchange_explicit (&v, count + 1, memory_order_acq_rel) != count)
+ abort ();
+ count++;
+
+ if (atomic_exchange_explicit (&v, count + 1, memory_order_seq_cst) != count)
+ abort ();
+ count++;
+
+ count++;
+
+ ret = atomic_exchange (&v, count);
+ if (ret != count - 1 || v != count)
+ abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/atomic/stdatomic-fence.c b/gcc/testsuite/gcc.dg/atomic/stdatomic-fence.c
new file mode 100644
index 00000000000..5f6c4e0f9d7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/atomic/stdatomic-fence.c
@@ -0,0 +1,26 @@
+/* Test atomic_*_fence routines for existence and execution with each
+ valid memory model. */
+/* { dg-do run } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+#include <stdatomic.h>
+
+int
+main ()
+{
+ atomic_thread_fence (memory_order_relaxed);
+ atomic_thread_fence (memory_order_consume);
+ atomic_thread_fence (memory_order_acquire);
+ atomic_thread_fence (memory_order_release);
+ atomic_thread_fence (memory_order_acq_rel);
+ atomic_thread_fence (memory_order_seq_cst);
+
+ atomic_signal_fence (memory_order_relaxed);
+ atomic_signal_fence (memory_order_consume);
+ atomic_signal_fence (memory_order_acquire);
+ atomic_signal_fence (memory_order_release);
+ atomic_signal_fence (memory_order_acq_rel);
+ atomic_signal_fence (memory_order_seq_cst);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/atomic/stdatomic-flag.c b/gcc/testsuite/gcc.dg/atomic/stdatomic-flag.c
new file mode 100644
index 00000000000..32f9e9bb631
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/atomic/stdatomic-flag.c
@@ -0,0 +1,38 @@
+/* Test atomic_flag routines for existence and execution. */
+/* { dg-do run } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+#include <stdatomic.h>
+
+extern void abort (void);
+atomic_flag a = ATOMIC_FLAG_INIT;
+
+int
+main ()
+{
+ int b;
+
+ if (!atomic_is_lock_free (&a))
+ abort ();
+
+ if (atomic_flag_test_and_set (&a))
+ abort ();
+ atomic_flag_clear_explicit (&a, memory_order_relaxed);
+ if (atomic_flag_test_and_set (&a))
+ abort ();
+ atomic_flag_clear (&a);
+
+ b = atomic_flag_test_and_set_explicit (&a, memory_order_seq_cst);
+ if (!atomic_flag_test_and_set (&a) || b != 0)
+ abort ();
+
+ b = atomic_flag_test_and_set_explicit (&a, memory_order_acq_rel);
+ if (!atomic_flag_test_and_set (&a) || b != 1)
+ abort ();
+
+ atomic_flag_clear_explicit (&a, memory_order_seq_cst);
+ if (atomic_flag_test_and_set (&a))
+ abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/atomic/stdatomic-generic.c b/gcc/testsuite/gcc.dg/atomic/stdatomic-generic.c
new file mode 100644
index 00000000000..8033c53739d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/atomic/stdatomic-generic.c
@@ -0,0 +1,52 @@
+/* Test generic atomic routines for proper function calling. */
+/* { dg-do run } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+#include <stdatomic.h>
+
+extern void abort ();
+extern int memcmp (const void *, const void *, __SIZE_TYPE__);
+
+typedef struct test {
+ int array[10];
+} test_struct;
+
+test_struct zero = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+test_struct ones = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
+_Atomic test_struct a;
+test_struct b;
+
+int size = sizeof (test_struct);
+/* Test for consistency on sizes 1, 2, 4, 8, 16 and 32. */
+int
+main ()
+{
+ test_struct c;
+
+ atomic_store_explicit (&a, zero, memory_order_relaxed);
+ if (memcmp (&a, &zero, size))
+ abort ();
+
+ c = atomic_exchange_explicit (&a, ones, memory_order_seq_cst);
+ if (memcmp (&c, &zero, size))
+ abort ();
+ if (memcmp (&a, &ones, size))
+ abort ();
+
+ b = atomic_load_explicit (&a, memory_order_relaxed);
+ if (memcmp (&b, &ones, size))
+ abort ();
+
+ if (!atomic_compare_exchange_strong_explicit (&a, &b, zero, memory_order_seq_cst, memory_order_acquire))
+ abort ();
+ if (memcmp (&a, &zero, size))
+ abort ();
+
+ if (atomic_compare_exchange_weak_explicit (&a, &b, ones, memory_order_seq_cst, memory_order_acquire))
+ abort ();
+ if (memcmp (&b, &zero, size))
+ abort ();
+
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.dg/atomic/stdatomic-kill-dep.c b/gcc/testsuite/gcc.dg/atomic/stdatomic-kill-dep.c
new file mode 100644
index 00000000000..fda7fe7d1f0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/atomic/stdatomic-kill-dep.c
@@ -0,0 +1,19 @@
+/* Test atomic_kill_dependency. */
+/* { dg-do run } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+#include <stdatomic.h>
+
+extern void abort (void);
+
+_Atomic int a = ATOMIC_VAR_INIT (1), b;
+
+int
+main ()
+{
+ b = kill_dependency (a);
+ if (b != 1)
+ abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/atomic/stdatomic-load-1.c b/gcc/testsuite/gcc.dg/atomic/stdatomic-load-1.c
new file mode 100644
index 00000000000..16bea684cb3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/atomic/stdatomic-load-1.c
@@ -0,0 +1,44 @@
+/* Test atomic_load routines for existence and proper execution on
+ 1-byte values with each valid memory model. */
+/* { dg-do run } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+#include <stdatomic.h>
+
+extern void abort (void);
+
+_Atomic char v;
+char count;
+
+int
+main ()
+{
+ v = 0;
+ count = 0;
+
+ if (atomic_load_explicit (&v, memory_order_relaxed) != count++)
+ abort ();
+ else
+ v++;
+
+ if (atomic_load_explicit (&v, memory_order_acquire) != count++)
+ abort ();
+ else
+ v++;
+
+ if (atomic_load_explicit (&v, memory_order_consume) != count++)
+ abort ();
+ else
+ v++;
+
+ if (atomic_load_explicit (&v, memory_order_seq_cst) != count++)
+ abort ();
+ else
+ v++;
+
+ if (atomic_load (&v) != count)
+ abort ();
+
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.dg/atomic/stdatomic-load-2.c b/gcc/testsuite/gcc.dg/atomic/stdatomic-load-2.c
new file mode 100644
index 00000000000..6b492d8c2ce
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/atomic/stdatomic-load-2.c
@@ -0,0 +1,44 @@
+/* Test atomic_load routines for existence and proper execution on
+ 2-byte values with each valid memory model. */
+/* { dg-do run } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+#include <stdatomic.h>
+
+extern void abort (void);
+
+_Atomic short v;
+short count;
+
+int
+main ()
+{
+ v = 0;
+ count = 0;
+
+ if (atomic_load_explicit (&v, memory_order_relaxed) != count++)
+ abort ();
+ else
+ v++;
+
+ if (atomic_load_explicit (&v, memory_order_acquire) != count++)
+ abort ();
+ else
+ v++;
+
+ if (atomic_load_explicit (&v, memory_order_consume) != count++)
+ abort ();
+ else
+ v++;
+
+ if (atomic_load_explicit (&v, memory_order_seq_cst) != count++)
+ abort ();
+ else
+ v++;
+
+ if (atomic_load (&v) != count)
+ abort ();
+
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.dg/atomic/stdatomic-load-3.c b/gcc/testsuite/gcc.dg/atomic/stdatomic-load-3.c
new file mode 100644
index 00000000000..c6f2e4b09ec
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/atomic/stdatomic-load-3.c
@@ -0,0 +1,44 @@
+/* Test atomic_load routines for existence and proper execution on
+ 4-byte values with each valid memory model. */
+/* { dg-do run } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+#include <stdatomic.h>
+
+extern void abort (void);
+
+_Atomic int v;
+int count;
+
+int
+main ()
+{
+ v = 0;
+ count = 0;
+
+ if (atomic_load_explicit (&v, memory_order_relaxed) != count++)
+ abort ();
+ else
+ v++;
+
+ if (atomic_load_explicit (&v, memory_order_acquire) != count++)
+ abort ();
+ else
+ v++;
+
+ if (atomic_load_explicit (&v, memory_order_consume) != count++)
+ abort ();
+ else
+ v++;
+
+ if (atomic_load_explicit (&v, memory_order_seq_cst) != count++)
+ abort ();
+ else
+ v++;
+
+ if (atomic_load (&v) != count)
+ abort ();
+
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.dg/atomic/stdatomic-load-4.c b/gcc/testsuite/gcc.dg/atomic/stdatomic-load-4.c
new file mode 100644
index 00000000000..bc26a5238df
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/atomic/stdatomic-load-4.c
@@ -0,0 +1,44 @@
+/* Test atomic_load routines for existence and proper execution on
+ 8-byte values with each valid memory model. */
+/* { dg-do run } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+#include <stdatomic.h>
+
+extern void abort (void);
+
+_Atomic long long v;
+long long count;
+
+int
+main ()
+{
+ v = 0;
+ count = 0;
+
+ if (atomic_load_explicit (&v, memory_order_relaxed) != count++)
+ abort ();
+ else
+ v++;
+
+ if (atomic_load_explicit (&v, memory_order_acquire) != count++)
+ abort ();
+ else
+ v++;
+
+ if (atomic_load_explicit (&v, memory_order_consume) != count++)
+ abort ();
+ else
+ v++;
+
+ if (atomic_load_explicit (&v, memory_order_seq_cst) != count++)
+ abort ();
+ else
+ v++;
+
+ if (atomic_load (&v) != count)
+ abort ();
+
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.dg/atomic/stdatomic-lockfree.c b/gcc/testsuite/gcc.dg/atomic/stdatomic-lockfree.c
new file mode 100644
index 00000000000..29310e9ce2a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/atomic/stdatomic-lockfree.c
@@ -0,0 +1,68 @@
+/* Test atomic_is_lock_free. */
+/* { dg-do run } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+#include <stdatomic.h>
+#include <stdint.h>
+
+extern void abort ();
+
+_Atomic _Bool aba;
+atomic_bool abt;
+_Atomic char aca;
+atomic_char act;
+_Atomic __CHAR16_TYPE__ ac16a;
+atomic_char16_t ac16t;
+_Atomic __CHAR32_TYPE__ ac32a;
+atomic_char32_t ac32t;
+_Atomic __WCHAR_TYPE__ awca;
+atomic_wchar_t awct;
+_Atomic short asa;
+atomic_short ast;
+_Atomic int aia;
+atomic_int ait;
+_Atomic long ala;
+atomic_long alt;
+_Atomic long long alla;
+atomic_llong allt;
+void *_Atomic apa;
+
+#define CHECK_TYPE(MACRO, V1, V2) \
+ do \
+ { \
+ int r1 = MACRO; \
+ int r2 = atomic_is_lock_free (&V1); \
+ int r3 = atomic_is_lock_free (&V2); \
+ if (r1 != 0 && r1 != 1 && r1 != 2) \
+ abort (); \
+ if (r2 != 0 && r2 != 1) \
+ abort (); \
+ if (r3 != 0 && r3 != 1) \
+ abort (); \
+ if (r1 == 2 && r2 != 1) \
+ abort (); \
+ if (r1 == 2 && r3 != 1) \
+ abort (); \
+ if (r1 == 0 && r2 != 0) \
+ abort (); \
+ if (r1 == 0 && r3 != 0) \
+ abort (); \
+ } \
+ while (0)
+
+int
+main ()
+{
+ CHECK_TYPE (ATOMIC_BOOL_LOCK_FREE, aba, abt);
+ CHECK_TYPE (ATOMIC_CHAR_LOCK_FREE, aca, act);
+ CHECK_TYPE (ATOMIC_CHAR16_T_LOCK_FREE, ac16a, ac16t);
+ CHECK_TYPE (ATOMIC_CHAR32_T_LOCK_FREE, ac32a, ac32t);
+ CHECK_TYPE (ATOMIC_WCHAR_T_LOCK_FREE, awca, awct);
+ CHECK_TYPE (ATOMIC_SHORT_LOCK_FREE, asa, ast);
+ CHECK_TYPE (ATOMIC_INT_LOCK_FREE, aia, ait);
+ CHECK_TYPE (ATOMIC_LONG_LOCK_FREE, ala, alt);
+ CHECK_TYPE (ATOMIC_LLONG_LOCK_FREE, alla, allt);
+ CHECK_TYPE (ATOMIC_POINTER_LOCK_FREE, apa, apa);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/atomic/stdatomic-op-1.c b/gcc/testsuite/gcc.dg/atomic/stdatomic-op-1.c
new file mode 100644
index 00000000000..6513a53402e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/atomic/stdatomic-op-1.c
@@ -0,0 +1,341 @@
+/* Test atomic_fetch routines for existence and proper execution on
+ 1-byte values with each valid memory model. */
+/* { dg-do run } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+#include <stdatomic.h>
+
+extern void abort (void);
+
+_Atomic char v;
+char count, res;
+const char init = ~0;
+
+void
+test_fetch_add ()
+{
+ v = 0;
+ count = 1;
+
+ if (atomic_fetch_add_explicit (&v, count, memory_order_relaxed) != 0)
+ abort ();
+
+ if (atomic_fetch_add_explicit (&v, 1, memory_order_consume) != 1)
+ abort ();
+
+ if (atomic_fetch_add_explicit (&v, count, memory_order_acquire) != 2)
+ abort ();
+
+ if (atomic_fetch_add_explicit (&v, 1, memory_order_release) != 3)
+ abort ();
+
+ if (atomic_fetch_add_explicit (&v, count, memory_order_acq_rel) != 4)
+ abort ();
+
+ if (atomic_fetch_add_explicit (&v, 1, memory_order_seq_cst) != 5)
+ abort ();
+
+ if (atomic_fetch_add (&v, 1) != 6)
+ abort ();
+}
+
+void
+test_fetch_sub ()
+{
+ v = res = 20;
+ count = 0;
+
+ if (atomic_fetch_sub_explicit (&v, count + 1, memory_order_relaxed) != res--)
+ abort ();
+
+ if (atomic_fetch_sub_explicit (&v, 1, memory_order_consume) != res--)
+ abort ();
+
+ if (atomic_fetch_sub_explicit (&v, count + 1, memory_order_acquire) != res--)
+ abort ();
+
+ if (atomic_fetch_sub_explicit (&v, 1, memory_order_release) != res--)
+ abort ();
+
+ if (atomic_fetch_sub_explicit (&v, count + 1, memory_order_acq_rel) != res--)
+ abort ();
+
+ if (atomic_fetch_sub_explicit (&v, 1, memory_order_seq_cst) != res--)
+ abort ();
+
+ if (atomic_fetch_sub (&v, 1) != res--)
+ abort ();
+}
+
+void
+test_fetch_and ()
+{
+ v = init;
+
+ if (atomic_fetch_and_explicit (&v, 0, memory_order_relaxed) != init)
+ abort ();
+
+ if (atomic_fetch_and_explicit (&v, init, memory_order_consume) != 0)
+ abort ();
+
+ if (atomic_fetch_and_explicit (&v, 0, memory_order_acquire) != 0)
+ abort ();
+
+ v = ~v;
+ if (atomic_fetch_and_explicit (&v, init, memory_order_release) != init)
+ abort ();
+
+ if (atomic_fetch_and_explicit (&v, 0, memory_order_acq_rel) != init)
+ abort ();
+
+ if (atomic_fetch_and_explicit (&v, 0, memory_order_seq_cst) != 0)
+ abort ();
+
+ if (atomic_fetch_and (&v, 0) != 0)
+ abort ();
+}
+
+void
+test_fetch_xor ()
+{
+ v = init;
+ count = 0;
+
+ if (atomic_fetch_xor_explicit (&v, count, memory_order_relaxed) != init)
+ abort ();
+
+ if (atomic_fetch_xor_explicit (&v, ~count, memory_order_consume) != init)
+ abort ();
+
+ if (atomic_fetch_xor_explicit (&v, 0, memory_order_acquire) != 0)
+ abort ();
+
+ if (atomic_fetch_xor_explicit (&v, ~count, memory_order_release) != 0)
+ abort ();
+
+ if (atomic_fetch_xor_explicit (&v, 0, memory_order_acq_rel) != init)
+ abort ();
+
+ if (atomic_fetch_xor_explicit (&v, ~count, memory_order_seq_cst) != init)
+ abort ();
+
+ if (atomic_fetch_xor (&v, ~count) != 0)
+ abort ();
+}
+
+void
+test_fetch_or ()
+{
+ v = 0;
+ count = 1;
+
+ if (atomic_fetch_or_explicit (&v, count, memory_order_relaxed) != 0)
+ abort ();
+
+ count *= 2;
+ if (atomic_fetch_or_explicit (&v, 2, memory_order_consume) != 1)
+ abort ();
+
+ count *= 2;
+ if (atomic_fetch_or_explicit (&v, count, memory_order_acquire) != 3)
+ abort ();
+
+ count *= 2;
+ if (atomic_fetch_or_explicit (&v, 8, memory_order_release) != 7)
+ abort ();
+
+ count *= 2;
+ if (atomic_fetch_or_explicit (&v, count, memory_order_acq_rel) != 15)
+ abort ();
+
+ count *= 2;
+ if (atomic_fetch_or_explicit (&v, count, memory_order_seq_cst) != 31)
+ abort ();
+
+ count *= 2;
+ if (atomic_fetch_or (&v, count) != 63)
+ abort ();
+}
+
+
+/* Test the OP routines with a result which isn't used. */
+
+void
+test_add ()
+{
+ v = 0;
+ count = 1;
+
+ atomic_fetch_add (&v, count);
+ if (v != 1)
+ abort ();
+
+ atomic_fetch_add_explicit (&v, count, memory_order_consume);
+ if (v != 2)
+ abort ();
+
+ atomic_fetch_add (&v, 1);
+ if (v != 3)
+ abort ();
+
+ atomic_fetch_add_explicit (&v, 1, memory_order_release);
+ if (v != 4)
+ abort ();
+
+ atomic_fetch_add (&v, 1);
+ if (v != 5)
+ abort ();
+
+ atomic_fetch_add_explicit (&v, count, memory_order_seq_cst);
+ if (v != 6)
+ abort ();
+}
+
+void
+test_sub ()
+{
+ v = res = 20;
+ count = 0;
+
+ atomic_fetch_sub (&v, count + 1);
+ if (v != --res)
+ abort ();
+
+ atomic_fetch_sub_explicit (&v, count + 1, memory_order_consume);
+ if (v != --res)
+ abort ();
+
+ atomic_fetch_sub (&v, 1);
+ if (v != --res)
+ abort ();
+
+ atomic_fetch_sub_explicit (&v, 1, memory_order_release);
+ if (v != --res)
+ abort ();
+
+ atomic_fetch_sub (&v, count + 1);
+ if (v != --res)
+ abort ();
+
+ atomic_fetch_sub_explicit (&v, count + 1, memory_order_seq_cst);
+ if (v != --res)
+ abort ();
+}
+
+void
+test_and ()
+{
+ v = init;
+
+ atomic_fetch_and (&v, 0);
+ if (v != 0)
+ abort ();
+
+ v = init;
+ atomic_fetch_and_explicit (&v, init, memory_order_consume);
+ if (v != init)
+ abort ();
+
+ atomic_fetch_and (&v, 0);
+ if (v != 0)
+ abort ();
+
+ v = ~v;
+ atomic_fetch_and_explicit (&v, init, memory_order_release);
+ if (v != init)
+ abort ();
+
+ atomic_fetch_and (&v, 0);
+ if (v != 0)
+ abort ();
+
+ v = ~v;
+ atomic_fetch_and_explicit (&v, 0, memory_order_seq_cst);
+ if (v != 0)
+ abort ();
+}
+
+void
+test_xor ()
+{
+ v = init;
+ count = 0;
+
+ atomic_fetch_xor (&v, count);
+ if (v != init)
+ abort ();
+
+ atomic_fetch_xor_explicit (&v, ~count, memory_order_consume);
+ if (v != 0)
+ abort ();
+
+ atomic_fetch_xor (&v, 0);
+ if (v != 0)
+ abort ();
+
+ atomic_fetch_xor_explicit (&v, ~count, memory_order_release);
+ if (v != init)
+ abort ();
+
+ atomic_fetch_xor_explicit (&v, 0, memory_order_acq_rel);
+ if (v != init)
+ abort ();
+
+ atomic_fetch_xor (&v, ~count);
+ if (v != 0)
+ abort ();
+}
+
+void
+test_or ()
+{
+ v = 0;
+ count = 1;
+
+ atomic_fetch_or (&v, count);
+ if (v != 1)
+ abort ();
+
+ count *= 2;
+ atomic_fetch_or_explicit (&v, count, memory_order_consume);
+ if (v != 3)
+ abort ();
+
+ count *= 2;
+ atomic_fetch_or (&v, 4);
+ if (v != 7)
+ abort ();
+
+ count *= 2;
+ atomic_fetch_or_explicit (&v, 8, memory_order_release);
+ if (v != 15)
+ abort ();
+
+ count *= 2;
+ atomic_fetch_or (&v, count);
+ if (v != 31)
+ abort ();
+
+ count *= 2;
+ atomic_fetch_or_explicit (&v, count, memory_order_seq_cst);
+ if (v != 63)
+ abort ();
+}
+
+int
+main ()
+{
+ test_fetch_add ();
+ test_fetch_sub ();
+ test_fetch_and ();
+ test_fetch_xor ();
+ test_fetch_or ();
+
+ test_add ();
+ test_sub ();
+ test_and ();
+ test_xor ();
+ test_or ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/atomic/stdatomic-op-2.c b/gcc/testsuite/gcc.dg/atomic/stdatomic-op-2.c
new file mode 100644
index 00000000000..05edafff0bd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/atomic/stdatomic-op-2.c
@@ -0,0 +1,341 @@
+/* Test atomic_fetch routines for existence and proper execution on
+ 2-byte values with each valid memory model. */
+/* { dg-do run } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+#include <stdatomic.h>
+
+extern void abort (void);
+
+_Atomic short v;
+short count, res;
+const short init = ~0;
+
+void
+test_fetch_add ()
+{
+ v = 0;
+ count = 1;
+
+ if (atomic_fetch_add_explicit (&v, count, memory_order_relaxed) != 0)
+ abort ();
+
+ if (atomic_fetch_add_explicit (&v, 1, memory_order_consume) != 1)
+ abort ();
+
+ if (atomic_fetch_add_explicit (&v, count, memory_order_acquire) != 2)
+ abort ();
+
+ if (atomic_fetch_add_explicit (&v, 1, memory_order_release) != 3)
+ abort ();
+
+ if (atomic_fetch_add_explicit (&v, count, memory_order_acq_rel) != 4)
+ abort ();
+
+ if (atomic_fetch_add_explicit (&v, 1, memory_order_seq_cst) != 5)
+ abort ();
+
+ if (atomic_fetch_add (&v, 1) != 6)
+ abort ();
+}
+
+void
+test_fetch_sub ()
+{
+ v = res = 20;
+ count = 0;
+
+ if (atomic_fetch_sub_explicit (&v, count + 1, memory_order_relaxed) != res--)
+ abort ();
+
+ if (atomic_fetch_sub_explicit (&v, 1, memory_order_consume) != res--)
+ abort ();
+
+ if (atomic_fetch_sub_explicit (&v, count + 1, memory_order_acquire) != res--)
+ abort ();
+
+ if (atomic_fetch_sub_explicit (&v, 1, memory_order_release) != res--)
+ abort ();
+
+ if (atomic_fetch_sub_explicit (&v, count + 1, memory_order_acq_rel) != res--)
+ abort ();
+
+ if (atomic_fetch_sub_explicit (&v, 1, memory_order_seq_cst) != res--)
+ abort ();
+
+ if (atomic_fetch_sub (&v, 1) != res--)
+ abort ();
+}
+
+void
+test_fetch_and ()
+{
+ v = init;
+
+ if (atomic_fetch_and_explicit (&v, 0, memory_order_relaxed) != init)
+ abort ();
+
+ if (atomic_fetch_and_explicit (&v, init, memory_order_consume) != 0)
+ abort ();
+
+ if (atomic_fetch_and_explicit (&v, 0, memory_order_acquire) != 0)
+ abort ();
+
+ v = ~v;
+ if (atomic_fetch_and_explicit (&v, init, memory_order_release) != init)
+ abort ();
+
+ if (atomic_fetch_and_explicit (&v, 0, memory_order_acq_rel) != init)
+ abort ();
+
+ if (atomic_fetch_and_explicit (&v, 0, memory_order_seq_cst) != 0)
+ abort ();
+
+ if (atomic_fetch_and (&v, 0) != 0)
+ abort ();
+}
+
+void
+test_fetch_xor ()
+{
+ v = init;
+ count = 0;
+
+ if (atomic_fetch_xor_explicit (&v, count, memory_order_relaxed) != init)
+ abort ();
+
+ if (atomic_fetch_xor_explicit (&v, ~count, memory_order_consume) != init)
+ abort ();
+
+ if (atomic_fetch_xor_explicit (&v, 0, memory_order_acquire) != 0)
+ abort ();
+
+ if (atomic_fetch_xor_explicit (&v, ~count, memory_order_release) != 0)
+ abort ();
+
+ if (atomic_fetch_xor_explicit (&v, 0, memory_order_acq_rel) != init)
+ abort ();
+
+ if (atomic_fetch_xor_explicit (&v, ~count, memory_order_seq_cst) != init)
+ abort ();
+
+ if (atomic_fetch_xor (&v, ~count) != 0)
+ abort ();
+}
+
+void
+test_fetch_or ()
+{
+ v = 0;
+ count = 1;
+
+ if (atomic_fetch_or_explicit (&v, count, memory_order_relaxed) != 0)
+ abort ();
+
+ count *= 2;
+ if (atomic_fetch_or_explicit (&v, 2, memory_order_consume) != 1)
+ abort ();
+
+ count *= 2;
+ if (atomic_fetch_or_explicit (&v, count, memory_order_acquire) != 3)
+ abort ();
+
+ count *= 2;
+ if (atomic_fetch_or_explicit (&v, 8, memory_order_release) != 7)
+ abort ();
+
+ count *= 2;
+ if (atomic_fetch_or_explicit (&v, count, memory_order_acq_rel) != 15)
+ abort ();
+
+ count *= 2;
+ if (atomic_fetch_or_explicit (&v, count, memory_order_seq_cst) != 31)
+ abort ();
+
+ count *= 2;
+ if (atomic_fetch_or (&v, count) != 63)
+ abort ();
+}
+
+
+/* Test the OP routines with a result which isn't used. */
+
+void
+test_add ()
+{
+ v = 0;
+ count = 1;
+
+ atomic_fetch_add (&v, count);
+ if (v != 1)
+ abort ();
+
+ atomic_fetch_add_explicit (&v, count, memory_order_consume);
+ if (v != 2)
+ abort ();
+
+ atomic_fetch_add (&v, 1);
+ if (v != 3)
+ abort ();
+
+ atomic_fetch_add_explicit (&v, 1, memory_order_release);
+ if (v != 4)
+ abort ();
+
+ atomic_fetch_add (&v, 1);
+ if (v != 5)
+ abort ();
+
+ atomic_fetch_add_explicit (&v, count, memory_order_seq_cst);
+ if (v != 6)
+ abort ();
+}
+
+void
+test_sub ()
+{
+ v = res = 20;
+ count = 0;
+
+ atomic_fetch_sub (&v, count + 1);
+ if (v != --res)
+ abort ();
+
+ atomic_fetch_sub_explicit (&v, count + 1, memory_order_consume);
+ if (v != --res)
+ abort ();
+
+ atomic_fetch_sub (&v, 1);
+ if (v != --res)
+ abort ();
+
+ atomic_fetch_sub_explicit (&v, 1, memory_order_release);
+ if (v != --res)
+ abort ();
+
+ atomic_fetch_sub (&v, count + 1);
+ if (v != --res)
+ abort ();
+
+ atomic_fetch_sub_explicit (&v, count + 1, memory_order_seq_cst);
+ if (v != --res)
+ abort ();
+}
+
+void
+test_and ()
+{
+ v = init;
+
+ atomic_fetch_and (&v, 0);
+ if (v != 0)
+ abort ();
+
+ v = init;
+ atomic_fetch_and_explicit (&v, init, memory_order_consume);
+ if (v != init)
+ abort ();
+
+ atomic_fetch_and (&v, 0);
+ if (v != 0)
+ abort ();
+
+ v = ~v;
+ atomic_fetch_and_explicit (&v, init, memory_order_release);
+ if (v != init)
+ abort ();
+
+ atomic_fetch_and (&v, 0);
+ if (v != 0)
+ abort ();
+
+ v = ~v;
+ atomic_fetch_and_explicit (&v, 0, memory_order_seq_cst);
+ if (v != 0)
+ abort ();
+}
+
+void
+test_xor ()
+{
+ v = init;
+ count = 0;
+
+ atomic_fetch_xor (&v, count);
+ if (v != init)
+ abort ();
+
+ atomic_fetch_xor_explicit (&v, ~count, memory_order_consume);
+ if (v != 0)
+ abort ();
+
+ atomic_fetch_xor (&v, 0);
+ if (v != 0)
+ abort ();
+
+ atomic_fetch_xor_explicit (&v, ~count, memory_order_release);
+ if (v != init)
+ abort ();
+
+ atomic_fetch_xor_explicit (&v, 0, memory_order_acq_rel);
+ if (v != init)
+ abort ();
+
+ atomic_fetch_xor (&v, ~count);
+ if (v != 0)
+ abort ();
+}
+
+void
+test_or ()
+{
+ v = 0;
+ count = 1;
+
+ atomic_fetch_or (&v, count);
+ if (v != 1)
+ abort ();
+
+ count *= 2;
+ atomic_fetch_or_explicit (&v, count, memory_order_consume);
+ if (v != 3)
+ abort ();
+
+ count *= 2;
+ atomic_fetch_or (&v, 4);
+ if (v != 7)
+ abort ();
+
+ count *= 2;
+ atomic_fetch_or_explicit (&v, 8, memory_order_release);
+ if (v != 15)
+ abort ();
+
+ count *= 2;
+ atomic_fetch_or (&v, count);
+ if (v != 31)
+ abort ();
+
+ count *= 2;
+ atomic_fetch_or_explicit (&v, count, memory_order_seq_cst);
+ if (v != 63)
+ abort ();
+}
+
+int
+main ()
+{
+ test_fetch_add ();
+ test_fetch_sub ();
+ test_fetch_and ();
+ test_fetch_xor ();
+ test_fetch_or ();
+
+ test_add ();
+ test_sub ();
+ test_and ();
+ test_xor ();
+ test_or ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/atomic/stdatomic-op-3.c b/gcc/testsuite/gcc.dg/atomic/stdatomic-op-3.c
new file mode 100644
index 00000000000..dc745d40591
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/atomic/stdatomic-op-3.c
@@ -0,0 +1,341 @@
+/* Test atomic_fetch routines for existence and proper execution on
+ 4-byte values with each valid memory model. */
+/* { dg-do run } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+#include <stdatomic.h>
+
+extern void abort (void);
+
+_Atomic int v;
+int count, res;
+const int init = ~0;
+
+void
+test_fetch_add ()
+{
+ v = 0;
+ count = 1;
+
+ if (atomic_fetch_add_explicit (&v, count, memory_order_relaxed) != 0)
+ abort ();
+
+ if (atomic_fetch_add_explicit (&v, 1, memory_order_consume) != 1)
+ abort ();
+
+ if (atomic_fetch_add_explicit (&v, count, memory_order_acquire) != 2)
+ abort ();
+
+ if (atomic_fetch_add_explicit (&v, 1, memory_order_release) != 3)
+ abort ();
+
+ if (atomic_fetch_add_explicit (&v, count, memory_order_acq_rel) != 4)
+ abort ();
+
+ if (atomic_fetch_add_explicit (&v, 1, memory_order_seq_cst) != 5)
+ abort ();
+
+ if (atomic_fetch_add (&v, 1) != 6)
+ abort ();
+}
+
+void
+test_fetch_sub ()
+{
+ v = res = 20;
+ count = 0;
+
+ if (atomic_fetch_sub_explicit (&v, count + 1, memory_order_relaxed) != res--)
+ abort ();
+
+ if (atomic_fetch_sub_explicit (&v, 1, memory_order_consume) != res--)
+ abort ();
+
+ if (atomic_fetch_sub_explicit (&v, count + 1, memory_order_acquire) != res--)
+ abort ();
+
+ if (atomic_fetch_sub_explicit (&v, 1, memory_order_release) != res--)
+ abort ();
+
+ if (atomic_fetch_sub_explicit (&v, count + 1, memory_order_acq_rel) != res--)
+ abort ();
+
+ if (atomic_fetch_sub_explicit (&v, 1, memory_order_seq_cst) != res--)
+ abort ();
+
+ if (atomic_fetch_sub (&v, 1) != res--)
+ abort ();
+}
+
+void
+test_fetch_and ()
+{
+ v = init;
+
+ if (atomic_fetch_and_explicit (&v, 0, memory_order_relaxed) != init)
+ abort ();
+
+ if (atomic_fetch_and_explicit (&v, init, memory_order_consume) != 0)
+ abort ();
+
+ if (atomic_fetch_and_explicit (&v, 0, memory_order_acquire) != 0)
+ abort ();
+
+ v = ~v;
+ if (atomic_fetch_and_explicit (&v, init, memory_order_release) != init)
+ abort ();
+
+ if (atomic_fetch_and_explicit (&v, 0, memory_order_acq_rel) != init)
+ abort ();
+
+ if (atomic_fetch_and_explicit (&v, 0, memory_order_seq_cst) != 0)
+ abort ();
+
+ if (atomic_fetch_and (&v, 0) != 0)
+ abort ();
+}
+
+void
+test_fetch_xor ()
+{
+ v = init;
+ count = 0;
+
+ if (atomic_fetch_xor_explicit (&v, count, memory_order_relaxed) != init)
+ abort ();
+
+ if (atomic_fetch_xor_explicit (&v, ~count, memory_order_consume) != init)
+ abort ();
+
+ if (atomic_fetch_xor_explicit (&v, 0, memory_order_acquire) != 0)
+ abort ();
+
+ if (atomic_fetch_xor_explicit (&v, ~count, memory_order_release) != 0)
+ abort ();
+
+ if (atomic_fetch_xor_explicit (&v, 0, memory_order_acq_rel) != init)
+ abort ();
+
+ if (atomic_fetch_xor_explicit (&v, ~count, memory_order_seq_cst) != init)
+ abort ();
+
+ if (atomic_fetch_xor (&v, ~count) != 0)
+ abort ();
+}
+
+void
+test_fetch_or ()
+{
+ v = 0;
+ count = 1;
+
+ if (atomic_fetch_or_explicit (&v, count, memory_order_relaxed) != 0)
+ abort ();
+
+ count *= 2;
+ if (atomic_fetch_or_explicit (&v, 2, memory_order_consume) != 1)
+ abort ();
+
+ count *= 2;
+ if (atomic_fetch_or_explicit (&v, count, memory_order_acquire) != 3)
+ abort ();
+
+ count *= 2;
+ if (atomic_fetch_or_explicit (&v, 8, memory_order_release) != 7)
+ abort ();
+
+ count *= 2;
+ if (atomic_fetch_or_explicit (&v, count, memory_order_acq_rel) != 15)
+ abort ();
+
+ count *= 2;
+ if (atomic_fetch_or_explicit (&v, count, memory_order_seq_cst) != 31)
+ abort ();
+
+ count *= 2;
+ if (atomic_fetch_or (&v, count) != 63)
+ abort ();
+}
+
+
+/* Test the OP routines with a result which isn't used. */
+
+void
+test_add ()
+{
+ v = 0;
+ count = 1;
+
+ atomic_fetch_add (&v, count);
+ if (v != 1)
+ abort ();
+
+ atomic_fetch_add_explicit (&v, count, memory_order_consume);
+ if (v != 2)
+ abort ();
+
+ atomic_fetch_add (&v, 1);
+ if (v != 3)
+ abort ();
+
+ atomic_fetch_add_explicit (&v, 1, memory_order_release);
+ if (v != 4)
+ abort ();
+
+ atomic_fetch_add (&v, 1);
+ if (v != 5)
+ abort ();
+
+ atomic_fetch_add_explicit (&v, count, memory_order_seq_cst);
+ if (v != 6)
+ abort ();
+}
+
+void
+test_sub ()
+{
+ v = res = 20;
+ count = 0;
+
+ atomic_fetch_sub (&v, count + 1);
+ if (v != --res)
+ abort ();
+
+ atomic_fetch_sub_explicit (&v, count + 1, memory_order_consume);
+ if (v != --res)
+ abort ();
+
+ atomic_fetch_sub (&v, 1);
+ if (v != --res)
+ abort ();
+
+ atomic_fetch_sub_explicit (&v, 1, memory_order_release);
+ if (v != --res)
+ abort ();
+
+ atomic_fetch_sub (&v, count + 1);
+ if (v != --res)
+ abort ();
+
+ atomic_fetch_sub_explicit (&v, count + 1, memory_order_seq_cst);
+ if (v != --res)
+ abort ();
+}
+
+void
+test_and ()
+{
+ v = init;
+
+ atomic_fetch_and (&v, 0);
+ if (v != 0)
+ abort ();
+
+ v = init;
+ atomic_fetch_and_explicit (&v, init, memory_order_consume);
+ if (v != init)
+ abort ();
+
+ atomic_fetch_and (&v, 0);
+ if (v != 0)
+ abort ();
+
+ v = ~v;
+ atomic_fetch_and_explicit (&v, init, memory_order_release);
+ if (v != init)
+ abort ();
+
+ atomic_fetch_and (&v, 0);
+ if (v != 0)
+ abort ();
+
+ v = ~v;
+ atomic_fetch_and_explicit (&v, 0, memory_order_seq_cst);
+ if (v != 0)
+ abort ();
+}
+
+void
+test_xor ()
+{
+ v = init;
+ count = 0;
+
+ atomic_fetch_xor (&v, count);
+ if (v != init)
+ abort ();
+
+ atomic_fetch_xor_explicit (&v, ~count, memory_order_consume);
+ if (v != 0)
+ abort ();
+
+ atomic_fetch_xor (&v, 0);
+ if (v != 0)
+ abort ();
+
+ atomic_fetch_xor_explicit (&v, ~count, memory_order_release);
+ if (v != init)
+ abort ();
+
+ atomic_fetch_xor_explicit (&v, 0, memory_order_acq_rel);
+ if (v != init)
+ abort ();
+
+ atomic_fetch_xor (&v, ~count);
+ if (v != 0)
+ abort ();
+}
+
+void
+test_or ()
+{
+ v = 0;
+ count = 1;
+
+ atomic_fetch_or (&v, count);
+ if (v != 1)
+ abort ();
+
+ count *= 2;
+ atomic_fetch_or_explicit (&v, count, memory_order_consume);
+ if (v != 3)
+ abort ();
+
+ count *= 2;
+ atomic_fetch_or (&v, 4);
+ if (v != 7)
+ abort ();
+
+ count *= 2;
+ atomic_fetch_or_explicit (&v, 8, memory_order_release);
+ if (v != 15)
+ abort ();
+
+ count *= 2;
+ atomic_fetch_or (&v, count);
+ if (v != 31)
+ abort ();
+
+ count *= 2;
+ atomic_fetch_or_explicit (&v, count, memory_order_seq_cst);
+ if (v != 63)
+ abort ();
+}
+
+int
+main ()
+{
+ test_fetch_add ();
+ test_fetch_sub ();
+ test_fetch_and ();
+ test_fetch_xor ();
+ test_fetch_or ();
+
+ test_add ();
+ test_sub ();
+ test_and ();
+ test_xor ();
+ test_or ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/atomic/stdatomic-op-4.c b/gcc/testsuite/gcc.dg/atomic/stdatomic-op-4.c
new file mode 100644
index 00000000000..84b83e44f8e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/atomic/stdatomic-op-4.c
@@ -0,0 +1,341 @@
+/* Test atomic_fetch routines for existence and proper execution on
+ 8-byte values with each valid memory model. */
+/* { dg-do run } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+#include <stdatomic.h>
+
+extern void abort (void);
+
+_Atomic long long v;
+long long count, res;
+const long long init = ~0;
+
+void
+test_fetch_add ()
+{
+ v = 0;
+ count = 1;
+
+ if (atomic_fetch_add_explicit (&v, count, memory_order_relaxed) != 0)
+ abort ();
+
+ if (atomic_fetch_add_explicit (&v, 1, memory_order_consume) != 1)
+ abort ();
+
+ if (atomic_fetch_add_explicit (&v, count, memory_order_acquire) != 2)
+ abort ();
+
+ if (atomic_fetch_add_explicit (&v, 1, memory_order_release) != 3)
+ abort ();
+
+ if (atomic_fetch_add_explicit (&v, count, memory_order_acq_rel) != 4)
+ abort ();
+
+ if (atomic_fetch_add_explicit (&v, 1, memory_order_seq_cst) != 5)
+ abort ();
+
+ if (atomic_fetch_add (&v, 1) != 6)
+ abort ();
+}
+
+void
+test_fetch_sub ()
+{
+ v = res = 20;
+ count = 0;
+
+ if (atomic_fetch_sub_explicit (&v, count + 1, memory_order_relaxed) != res--)
+ abort ();
+
+ if (atomic_fetch_sub_explicit (&v, 1, memory_order_consume) != res--)
+ abort ();
+
+ if (atomic_fetch_sub_explicit (&v, count + 1, memory_order_acquire) != res--)
+ abort ();
+
+ if (atomic_fetch_sub_explicit (&v, 1, memory_order_release) != res--)
+ abort ();
+
+ if (atomic_fetch_sub_explicit (&v, count + 1, memory_order_acq_rel) != res--)
+ abort ();
+
+ if (atomic_fetch_sub_explicit (&v, 1, memory_order_seq_cst) != res--)
+ abort ();
+
+ if (atomic_fetch_sub (&v, 1) != res--)
+ abort ();
+}
+
+void
+test_fetch_and ()
+{
+ v = init;
+
+ if (atomic_fetch_and_explicit (&v, 0, memory_order_relaxed) != init)
+ abort ();
+
+ if (atomic_fetch_and_explicit (&v, init, memory_order_consume) != 0)
+ abort ();
+
+ if (atomic_fetch_and_explicit (&v, 0, memory_order_acquire) != 0)
+ abort ();
+
+ v = ~v;
+ if (atomic_fetch_and_explicit (&v, init, memory_order_release) != init)
+ abort ();
+
+ if (atomic_fetch_and_explicit (&v, 0, memory_order_acq_rel) != init)
+ abort ();
+
+ if (atomic_fetch_and_explicit (&v, 0, memory_order_seq_cst) != 0)
+ abort ();
+
+ if (atomic_fetch_and (&v, 0) != 0)
+ abort ();
+}
+
+void
+test_fetch_xor ()
+{
+ v = init;
+ count = 0;
+
+ if (atomic_fetch_xor_explicit (&v, count, memory_order_relaxed) != init)
+ abort ();
+
+ if (atomic_fetch_xor_explicit (&v, ~count, memory_order_consume) != init)
+ abort ();
+
+ if (atomic_fetch_xor_explicit (&v, 0, memory_order_acquire) != 0)
+ abort ();
+
+ if (atomic_fetch_xor_explicit (&v, ~count, memory_order_release) != 0)
+ abort ();
+
+ if (atomic_fetch_xor_explicit (&v, 0, memory_order_acq_rel) != init)
+ abort ();
+
+ if (atomic_fetch_xor_explicit (&v, ~count, memory_order_seq_cst) != init)
+ abort ();
+
+ if (atomic_fetch_xor (&v, ~count) != 0)
+ abort ();
+}
+
+void
+test_fetch_or ()
+{
+ v = 0;
+ count = 1;
+
+ if (atomic_fetch_or_explicit (&v, count, memory_order_relaxed) != 0)
+ abort ();
+
+ count *= 2;
+ if (atomic_fetch_or_explicit (&v, 2, memory_order_consume) != 1)
+ abort ();
+
+ count *= 2;
+ if (atomic_fetch_or_explicit (&v, count, memory_order_acquire) != 3)
+ abort ();
+
+ count *= 2;
+ if (atomic_fetch_or_explicit (&v, 8, memory_order_release) != 7)
+ abort ();
+
+ count *= 2;
+ if (atomic_fetch_or_explicit (&v, count, memory_order_acq_rel) != 15)
+ abort ();
+
+ count *= 2;
+ if (atomic_fetch_or_explicit (&v, count, memory_order_seq_cst) != 31)
+ abort ();
+
+ count *= 2;
+ if (atomic_fetch_or (&v, count) != 63)
+ abort ();
+}
+
+
+/* Test the OP routines with a result which isn't used. */
+
+void
+test_add ()
+{
+ v = 0;
+ count = 1;
+
+ atomic_fetch_add (&v, count);
+ if (v != 1)
+ abort ();
+
+ atomic_fetch_add_explicit (&v, count, memory_order_consume);
+ if (v != 2)
+ abort ();
+
+ atomic_fetch_add (&v, 1);
+ if (v != 3)
+ abort ();
+
+ atomic_fetch_add_explicit (&v, 1, memory_order_release);
+ if (v != 4)
+ abort ();
+
+ atomic_fetch_add (&v, 1);
+ if (v != 5)
+ abort ();
+
+ atomic_fetch_add_explicit (&v, count, memory_order_seq_cst);
+ if (v != 6)
+ abort ();
+}
+
+void
+test_sub ()
+{
+ v = res = 20;
+ count = 0;
+
+ atomic_fetch_sub (&v, count + 1);
+ if (v != --res)
+ abort ();
+
+ atomic_fetch_sub_explicit (&v, count + 1, memory_order_consume);
+ if (v != --res)
+ abort ();
+
+ atomic_fetch_sub (&v, 1);
+ if (v != --res)
+ abort ();
+
+ atomic_fetch_sub_explicit (&v, 1, memory_order_release);
+ if (v != --res)
+ abort ();
+
+ atomic_fetch_sub (&v, count + 1);
+ if (v != --res)
+ abort ();
+
+ atomic_fetch_sub_explicit (&v, count + 1, memory_order_seq_cst);
+ if (v != --res)
+ abort ();
+}
+
+void
+test_and ()
+{
+ v = init;
+
+ atomic_fetch_and (&v, 0);
+ if (v != 0)
+ abort ();
+
+ v = init;
+ atomic_fetch_and_explicit (&v, init, memory_order_consume);
+ if (v != init)
+ abort ();
+
+ atomic_fetch_and (&v, 0);
+ if (v != 0)
+ abort ();
+
+ v = ~v;
+ atomic_fetch_and_explicit (&v, init, memory_order_release);
+ if (v != init)
+ abort ();
+
+ atomic_fetch_and (&v, 0);
+ if (v != 0)
+ abort ();
+
+ v = ~v;
+ atomic_fetch_and_explicit (&v, 0, memory_order_seq_cst);
+ if (v != 0)
+ abort ();
+}
+
+void
+test_xor ()
+{
+ v = init;
+ count = 0;
+
+ atomic_fetch_xor (&v, count);
+ if (v != init)
+ abort ();
+
+ atomic_fetch_xor_explicit (&v, ~count, memory_order_consume);
+ if (v != 0)
+ abort ();
+
+ atomic_fetch_xor (&v, 0);
+ if (v != 0)
+ abort ();
+
+ atomic_fetch_xor_explicit (&v, ~count, memory_order_release);
+ if (v != init)
+ abort ();
+
+ atomic_fetch_xor_explicit (&v, 0, memory_order_acq_rel);
+ if (v != init)
+ abort ();
+
+ atomic_fetch_xor (&v, ~count);
+ if (v != 0)
+ abort ();
+}
+
+void
+test_or ()
+{
+ v = 0;
+ count = 1;
+
+ atomic_fetch_or (&v, count);
+ if (v != 1)
+ abort ();
+
+ count *= 2;
+ atomic_fetch_or_explicit (&v, count, memory_order_consume);
+ if (v != 3)
+ abort ();
+
+ count *= 2;
+ atomic_fetch_or (&v, 4);
+ if (v != 7)
+ abort ();
+
+ count *= 2;
+ atomic_fetch_or_explicit (&v, 8, memory_order_release);
+ if (v != 15)
+ abort ();
+
+ count *= 2;
+ atomic_fetch_or (&v, count);
+ if (v != 31)
+ abort ();
+
+ count *= 2;
+ atomic_fetch_or_explicit (&v, count, memory_order_seq_cst);
+ if (v != 63)
+ abort ();
+}
+
+int
+main ()
+{
+ test_fetch_add ();
+ test_fetch_sub ();
+ test_fetch_and ();
+ test_fetch_xor ();
+ test_fetch_or ();
+
+ test_add ();
+ test_sub ();
+ test_and ();
+ test_xor ();
+ test_or ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/atomic/stdatomic-store-1.c b/gcc/testsuite/gcc.dg/atomic/stdatomic-store-1.c
new file mode 100644
index 00000000000..f7936dabc1e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/atomic/stdatomic-store-1.c
@@ -0,0 +1,43 @@
+/* Test atomic_store routines for existence and proper execution on
+ 1-byte values with each valid memory model. */
+/* { dg-do run } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+#include <stdatomic.h>
+
+extern void abort (void);
+
+_Atomic char v;
+char count;
+
+int
+main ()
+{
+ v = 0;
+ count = 0;
+
+ atomic_init (&v, count + 1);
+ if (v != ++count)
+ abort ();
+
+ atomic_store_explicit (&v, count + 1, memory_order_relaxed);
+ if (v != ++count)
+ abort ();
+
+ atomic_store_explicit (&v, count + 1, memory_order_release);
+ if (v != ++count)
+ abort ();
+
+ atomic_store_explicit (&v, count + 1, memory_order_seq_cst);
+ if (v != ++count)
+ abort ();
+
+ count++;
+
+ atomic_store (&v, count);
+ if (v != count)
+ abort ();
+
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.dg/atomic/stdatomic-store-2.c b/gcc/testsuite/gcc.dg/atomic/stdatomic-store-2.c
new file mode 100644
index 00000000000..0bbba1cef89
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/atomic/stdatomic-store-2.c
@@ -0,0 +1,43 @@
+/* Test atomic_store routines for existence and proper execution on
+ 2-byte values with each valid memory model. */
+/* { dg-do run } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+#include <stdatomic.h>
+
+extern void abort (void);
+
+_Atomic short v;
+short count;
+
+int
+main ()
+{
+ v = 0;
+ count = 0;
+
+ atomic_init (&v, count + 1);
+ if (v != ++count)
+ abort ();
+
+ atomic_store_explicit (&v, count + 1, memory_order_relaxed);
+ if (v != ++count)
+ abort ();
+
+ atomic_store_explicit (&v, count + 1, memory_order_release);
+ if (v != ++count)
+ abort ();
+
+ atomic_store_explicit (&v, count + 1, memory_order_seq_cst);
+ if (v != ++count)
+ abort ();
+
+ count++;
+
+ atomic_store (&v, count);
+ if (v != count)
+ abort ();
+
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.dg/atomic/stdatomic-store-3.c b/gcc/testsuite/gcc.dg/atomic/stdatomic-store-3.c
new file mode 100644
index 00000000000..86c1b2aa886
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/atomic/stdatomic-store-3.c
@@ -0,0 +1,43 @@
+/* Test atomic_store routines for existence and proper execution on
+ 4-byte values with each valid memory model. */
+/* { dg-do run } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+#include <stdatomic.h>
+
+extern void abort (void);
+
+_Atomic int v;
+int count;
+
+int
+main ()
+{
+ v = 0;
+ count = 0;
+
+ atomic_init (&v, count + 1);
+ if (v != ++count)
+ abort ();
+
+ atomic_store_explicit (&v, count + 1, memory_order_relaxed);
+ if (v != ++count)
+ abort ();
+
+ atomic_store_explicit (&v, count + 1, memory_order_release);
+ if (v != ++count)
+ abort ();
+
+ atomic_store_explicit (&v, count + 1, memory_order_seq_cst);
+ if (v != ++count)
+ abort ();
+
+ count++;
+
+ atomic_store (&v, count);
+ if (v != count)
+ abort ();
+
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.dg/atomic/stdatomic-store-4.c b/gcc/testsuite/gcc.dg/atomic/stdatomic-store-4.c
new file mode 100644
index 00000000000..fe96469a9be
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/atomic/stdatomic-store-4.c
@@ -0,0 +1,43 @@
+/* Test atomic_store routines for existence and proper execution on
+ 8-byte values with each valid memory model. */
+/* { dg-do run } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+#include <stdatomic.h>
+
+extern void abort (void);
+
+_Atomic long long v;
+long long count;
+
+int
+main ()
+{
+ v = 0;
+ count = 0;
+
+ atomic_init (&v, count + 1);
+ if (v != ++count)
+ abort ();
+
+ atomic_store_explicit (&v, count + 1, memory_order_relaxed);
+ if (v != ++count)
+ abort ();
+
+ atomic_store_explicit (&v, count + 1, memory_order_release);
+ if (v != ++count)
+ abort ();
+
+ atomic_store_explicit (&v, count + 1, memory_order_seq_cst);
+ if (v != ++count)
+ abort ();
+
+ count++;
+
+ atomic_store (&v, count);
+ if (v != count)
+ abort ();
+
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.dg/autopar/outer-1.c b/gcc/testsuite/gcc.dg/autopar/outer-1.c
index 913d390f684..a9d2185f0ce 100644
--- a/gcc/testsuite/gcc.dg/autopar/outer-1.c
+++ b/gcc/testsuite/gcc.dg/autopar/outer-1.c
@@ -28,6 +28,6 @@ int main(void)
/* Check that outer loop is parallelized. */
/* { dg-final { scan-tree-dump-times "parallelizing outer loop" 1 "parloops" } } */
-/* { dg-final { scan-tree-dump-times "loopfn" 5 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "loopfn" 4 "optimized" } } */
/* { dg-final { cleanup-tree-dump "parloops" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/autopar/outer-2.c b/gcc/testsuite/gcc.dg/autopar/outer-2.c
index b2e51598203..e0a142f0d11 100644
--- a/gcc/testsuite/gcc.dg/autopar/outer-2.c
+++ b/gcc/testsuite/gcc.dg/autopar/outer-2.c
@@ -28,6 +28,6 @@ int main(void)
}
/* { dg-final { scan-tree-dump-times "parallelizing outer loop" 1 "parloops" } } */
-/* { dg-final { scan-tree-dump-times "loopfn" 5 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "loopfn" 4 "optimized" } } */
/* { dg-final { cleanup-tree-dump "parloops" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/autopar/outer-3.c b/gcc/testsuite/gcc.dg/autopar/outer-3.c
index 2f1033f9830..c6e0adbffdf 100644
--- a/gcc/testsuite/gcc.dg/autopar/outer-3.c
+++ b/gcc/testsuite/gcc.dg/autopar/outer-3.c
@@ -28,6 +28,6 @@ int main(void)
/* Check that outer loop is parallelized. */
/* { dg-final { scan-tree-dump-times "parallelizing outer loop" 1 "parloops" } } */
-/* { dg-final { scan-tree-dump-times "loopfn" 5 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "loopfn" 4 "optimized" } } */
/* { dg-final { cleanup-tree-dump "parloops" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/autopar/outer-4.c b/gcc/testsuite/gcc.dg/autopar/outer-4.c
index 56f6123385d..d60023f5d86 100644
--- a/gcc/testsuite/gcc.dg/autopar/outer-4.c
+++ b/gcc/testsuite/gcc.dg/autopar/outer-4.c
@@ -32,6 +32,6 @@ int main(void)
/* { dg-final { scan-tree-dump-times "parallelizing outer loop" 1 "parloops" { xfail *-*-* } } } */
-/* { dg-final { scan-tree-dump-times "loopfn" 5 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "loopfn" 4 "optimized" } } */
/* { dg-final { cleanup-tree-dump "parloops" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/autopar/outer-5.c b/gcc/testsuite/gcc.dg/autopar/outer-5.c
index 3a542988c26..fa80293263c 100644
--- a/gcc/testsuite/gcc.dg/autopar/outer-5.c
+++ b/gcc/testsuite/gcc.dg/autopar/outer-5.c
@@ -45,6 +45,6 @@ int main(void)
}
/* { dg-final { scan-tree-dump-times "parallelizing outer loop" 1 "parloops" { xfail *-*-* } } } */
-/* { dg-final { scan-tree-dump-times "loopfn" 5 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "loopfn" 4 "optimized" } } */
/* { dg-final { cleanup-tree-dump "parloops" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/autopar/outer-6.c b/gcc/testsuite/gcc.dg/autopar/outer-6.c
index 6e027d2f69a..b16366932fe 100644
--- a/gcc/testsuite/gcc.dg/autopar/outer-6.c
+++ b/gcc/testsuite/gcc.dg/autopar/outer-6.c
@@ -46,6 +46,6 @@ int main(void)
/* Check that outer loop is parallelized. */
/* { dg-final { scan-tree-dump-times "parallelizing outer loop" 1 "parloops" } } */
/* { dg-final { scan-tree-dump-times "parallelizing inner loop" 0 "parloops" } } */
-/* { dg-final { scan-tree-dump-times "loopfn" 5 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "loopfn" 4 "optimized" } } */
/* { dg-final { cleanup-tree-dump "parloops" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/autopar/parallelization-1.c b/gcc/testsuite/gcc.dg/autopar/parallelization-1.c
index f53be8598db..de2a0f3cc71 100644
--- a/gcc/testsuite/gcc.dg/autopar/parallelization-1.c
+++ b/gcc/testsuite/gcc.dg/autopar/parallelization-1.c
@@ -28,6 +28,6 @@ int main(void)
/* Check that the first loop in parloop got parallelized. */
/* { dg-final { scan-tree-dump-times "SUCCESS: may be parallelized" 1 "parloops" } } */
-/* { dg-final { scan-tree-dump-times "loopfn" 5 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "loopfn" 4 "optimized" } } */
/* { dg-final { cleanup-tree-dump "parloops" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/builtin-apply2.c b/gcc/testsuite/gcc.dg/builtin-apply2.c
index daaef477894..869f337a9a5 100644
--- a/gcc/testsuite/gcc.dg/builtin-apply2.c
+++ b/gcc/testsuite/gcc.dg/builtin-apply2.c
@@ -1,6 +1,6 @@
/* { dg-do run } */
/* { dg-skip-if "Variadic funcs have all args on stack. Normal funcs have args in registers." { "aarch64*-*-* avr-*-* " } { "*" } { "" } } */
-/* { dg-skip-if "Variadic funcs use Base AAPCS. Normal funcs use VFP variant." { "arm*-*-*" } { "-mfloat-abi=hard" } { "" } } */
+/* { dg-skip-if "Variadic funcs use Base AAPCS. Normal funcs use VFP variant." { arm*-*-* && arm_hf_eabi } { "*" } { "" } } */
/* PR target/12503 */
/* Origin: <pierre.nguyen-tuong@asim.lip6.fr> */
diff --git a/gcc/testsuite/gcc.dg/builtin-complex-err-1.c b/gcc/testsuite/gcc.dg/builtin-complex-err-1.c
index 3ef50da9278..ddc72b583cb 100644
--- a/gcc/testsuite/gcc.dg/builtin-complex-err-1.c
+++ b/gcc/testsuite/gcc.dg/builtin-complex-err-1.c
@@ -1,6 +1,6 @@
/* Test __builtin_complex errors. */
/* { dg-do compile } */
-/* { dg-options "-std=c1x -pedantic-errors" } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
typedef double D;
diff --git a/gcc/testsuite/gcc.dg/c11-align-1.c b/gcc/testsuite/gcc.dg/c11-align-1.c
new file mode 100644
index 00000000000..e0058c38007
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-align-1.c
@@ -0,0 +1,41 @@
+/* Test C11 alignment support. Test valid code. */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+#include <stddef.h>
+
+_Alignas (_Alignof (max_align_t)) char c;
+extern _Alignas (max_align_t) char c;
+extern char c;
+
+extern _Alignas (max_align_t) short s;
+_Alignas (max_align_t) short s;
+
+_Alignas (int) int i;
+extern int i;
+
+_Alignas (max_align_t) long l;
+
+_Alignas (max_align_t) long long ll;
+
+_Alignas (max_align_t) float f;
+
+_Alignas (max_align_t) double d;
+
+_Alignas (max_align_t) _Complex long double cld;
+
+_Alignas (0) _Alignas (int) _Alignas (char) char ca[10];
+
+_Alignas ((int) _Alignof (max_align_t) + 0) int x;
+
+enum e { E = _Alignof (max_align_t) };
+_Alignas (E) int y;
+
+void
+func (void)
+{
+ _Alignas (max_align_t) long long auto_ll;
+}
+
+/* Valid, but useless. */
+_Alignas (0) struct s; /* { dg-warning "useless" } */
diff --git a/gcc/testsuite/gcc.dg/c11-align-2.c b/gcc/testsuite/gcc.dg/c11-align-2.c
new file mode 100644
index 00000000000..a1750ac547a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-align-2.c
@@ -0,0 +1,92 @@
+/* Test C11 alignment support. Test valid code using stdalign.h. */
+/* { dg-do run } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+#include <stdalign.h>
+#include <stddef.h>
+
+extern int strcmp (const char *, const char *);
+
+extern void exit (int);
+extern void abort (void);
+
+alignas (alignof (max_align_t)) char c;
+extern alignas (max_align_t) char c;
+extern char c;
+
+extern alignas (max_align_t) short s;
+alignas (max_align_t) short s;
+
+alignas (int) int i;
+extern int i;
+
+alignas (max_align_t) long l;
+
+alignas (max_align_t) long long ll;
+
+alignas (max_align_t) float f;
+
+alignas (max_align_t) double d;
+
+alignas (max_align_t) _Complex long double cld;
+
+alignas (0) alignas (int) alignas (char) char ca[10];
+
+alignas ((int) alignof (max_align_t) + 0) int x;
+
+enum e { E = alignof (max_align_t) };
+alignas (E) int y;
+
+void
+func (void)
+{
+ alignas (max_align_t) long long auto_ll;
+}
+
+/* Valid, but useless. */
+alignas (0) struct s; /* { dg-warning "useless" } */
+
+#ifndef alignas
+#error "alignas not defined"
+#endif
+
+#ifndef alignof
+#error "alignof not defined"
+#endif
+
+#ifndef __alignas_is_defined
+#error "__alignas_is_defined not defined"
+#endif
+
+#if __alignas_is_defined != 1
+#error "__alignas_is_defined not 1"
+#endif
+
+#ifndef __alignof_is_defined
+#error "__alignof_is_defined not defined"
+#endif
+
+#if __alignof_is_defined != 1
+#error "__alignof_is_defined not 1"
+#endif
+
+#define str(x) #x
+#define xstr(x) str(x)
+
+const char *s1 = xstr(alignas);
+const char *s2 = xstr(alignof);
+const char *s3 = xstr(__alignas_is_defined);
+const char *s4 = xstr(__alignof_is_defined);
+
+int
+main (void)
+{
+ if (strcmp (s1, "_Alignas") != 0)
+ abort ();
+ if (strcmp (s2, "_Alignof") != 0)
+ abort ();
+ if (strcmp (s3, "1") != 0)
+ abort ();
+ if (strcmp (s4, "1") != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.dg/c11-align-3.c b/gcc/testsuite/gcc.dg/c11-align-3.c
new file mode 100644
index 00000000000..39b81ef6f57
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-align-3.c
@@ -0,0 +1,43 @@
+/* Test C11 alignment support. Test invalid code. */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+int a = _Alignof (void (void)); /* { dg-error "function" } */
+struct s;
+int b = _Alignof (struct s); /* { dg-error "incomplete" } */
+int c = _Alignof (void); /* { dg-error "void" } */
+int d = _Alignof (a); /* { dg-error "expression" } */
+
+_Alignas (void (void)) char e; /* { dg-error "function" } */
+_Alignas (struct s) char f; /* { dg-error "incomplete" } */
+_Alignas (void) char g; /* { dg-error "void" } */
+
+_Alignas (-__INT_MAX__-1) char h; /* { dg-error "too large|power of 2" } */
+_Alignas (-__INT_MAX__) char h2; /* { dg-error "too large|power of 2" } */
+_Alignas ((-__INT_MAX__-1)/2) char h3; /* { dg-error "too large|power of 2" } */
+_Alignas ((-__INT_MAX__-1)/4) char h4; /* { dg-error "too large|power of 2" } */
+_Alignas ((-__INT_MAX__-1)/8) char h5; /* { dg-error "too large|power of 2" } */
+_Alignas (-__LONG_LONG_MAX__-1) char i; /* { dg-error "too large|power of 2" } */
+_Alignas (-(__LONG_LONG_MAX__-1)/2) char i2; /* { dg-error "too large|power of 2" } */
+_Alignas (-(__LONG_LONG_MAX__-1)/4) char i3; /* { dg-error "too large|power of 2" } */
+_Alignas (-(__LONG_LONG_MAX__-1)/8) char i4; /* { dg-error "too large|power of 2" } */
+_Alignas (-(__LONG_LONG_MAX__-1)/16) char i5; /* { dg-error "too large|power of 2" } */
+_Alignas (-1) char j; /* { dg-error "power of 2" } */
+_Alignas (-2) char j; /* { dg-error "positive power of 2" } */
+_Alignas (3) char k; /* { dg-error "power of 2" } */
+
+_Alignas ((void *) 1) char k; /* { dg-error "integer constant" } */
+int x;
+_Alignas (x) char l; /* { dg-error "integer constant" } */
+
+_Alignas (0) struct s; /* { dg-error "does not redeclare tag" } */
+
+_Alignas (0) typedef int T; /* { dg-error "alignment specified for typedef" } */
+void func (_Alignas (0) int); /* { dg-error "alignment specified for unnamed parameter" } */
+void f2 (_Alignas (0) int parm2) {} /* { dg-error "alignment specified for parameter" } */
+void
+f3 (void)
+{
+ register _Alignas (0) int reg; /* { dg-error "register" } */
+}
+_Alignas (0) void f4 (void); /* { dg-error "alignment specified for function" } */
diff --git a/gcc/testsuite/gcc.dg/c11-align-4.c b/gcc/testsuite/gcc.dg/c11-align-4.c
new file mode 100644
index 00000000000..6377db6edf3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-align-4.c
@@ -0,0 +1,9 @@
+/* Test C11 alignment support. Test reducing alignment (assumes there
+ are at least some alignment constraints). */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+/* { dg-skip-if "no alignment constraints" { "avr-*-*" } { "*" } { "" } } */
+
+#include <stddef.h>
+
+_Alignas (_Alignof (char)) max_align_t x; /* { dg-error "reduce alignment" } */
diff --git a/gcc/testsuite/gcc.dg/c11-align-5.c b/gcc/testsuite/gcc.dg/c11-align-5.c
new file mode 100644
index 00000000000..f3a14779ff8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-align-5.c
@@ -0,0 +1,28 @@
+/* Test C11 alignment support. Test invalid code. */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+void foo (int []);
+void bar1 (int [_Alignas (double) 10]); /* { dg-error "expected expression before" } */
+void bar2 (int [static _Alignas (double) 10]); /* { dg-error "expected expression before" } */
+void bar3 (int [static const _Alignas (double) 10]); /* { dg-error "expected expression before" } */
+void bar4 (int [const _Alignas (double) 10]); /* { dg-error "expected expression before" } */
+void bar5 (int [_Alignas (0) *]); /* { dg-error "expected expression before" } */
+
+void foo (int a[_Alignas (0) 10]) { } /* { dg-error "expected expression before" } */
+
+void
+test (void)
+{
+ int *_Alignas (long) p; /* { dg-error "expected" } */
+ int *const _Alignas (long) *q; /* { dg-error "expected" } */
+ struct s { int n; };
+ __builtin_offsetof (struct s _Alignas (int), n); /* { dg-error "expected" } */
+ __typeof (long double _Alignas (0)) e; /* { dg-error "expected" } */
+ sizeof (int _Alignas (int)); /* { dg-error "expected" } */
+ _Alignas (int _Alignas (float)) int t; /* { dg-error "expected" } */
+ __builtin_types_compatible_p (signed _Alignas (0), unsigned); /* { dg-error "expected" } */
+ int a[_Alignas (int) 10]; /* { dg-error "expected expression before" } */
+ int b[10];
+ foo (b);
+}
diff --git a/gcc/testsuite/gcc.dg/c11-anon-struct-1.c b/gcc/testsuite/gcc.dg/c11-anon-struct-1.c
new file mode 100644
index 00000000000..779ae66b7e1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-anon-struct-1.c
@@ -0,0 +1,72 @@
+/* Test for anonymous structures and unions in C11. */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+#include <stddef.h>
+
+struct s1
+{
+ int a;
+ union
+ {
+ int i;
+ };
+ struct
+ {
+ int b;
+ };
+};
+
+union u1
+{
+ int b;
+ struct
+ {
+ int i;
+ };
+ union
+ {
+ int c;
+ };
+};
+
+struct s2
+{
+ struct
+ {
+ int a;
+ };
+};
+
+struct s3
+{
+ union
+ {
+ int i;
+ };
+};
+
+struct s4
+{
+ struct
+ {
+ int i;
+ };
+ int a[];
+};
+
+struct s1 x =
+ {
+ .b = 1,
+ .i = 2,
+ .a = 3
+ };
+
+int o = offsetof (struct s1, i);
+
+void
+f (void)
+{
+ x.i = 3;
+ (&x)->i = 4;
+}
diff --git a/gcc/testsuite/gcc.dg/c11-anon-struct-2.c b/gcc/testsuite/gcc.dg/c11-anon-struct-2.c
new file mode 100644
index 00000000000..d954b4b1270
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-anon-struct-2.c
@@ -0,0 +1,57 @@
+/* Test for anonymous structures and unions in C11. Test for invalid
+ cases. */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+typedef struct s0
+{
+ int i;
+} s0;
+
+struct s1
+{
+ int a;
+ struct s0; /* { dg-error "declaration does not declare anything" } */
+};
+
+struct s2
+{
+ int a;
+ s0; /* { dg-error "declaration does not declare anything" } */
+};
+
+struct s3
+{
+ struct
+ {
+ int i;
+ };
+ struct
+ {
+ int i; /* { dg-error "duplicate member" } */
+ };
+};
+
+struct s4
+{
+ int a;
+ struct s
+ {
+ int i;
+ }; /* { dg-error "declaration does not declare anything" } */
+};
+
+struct s5
+{
+ struct
+ {
+ int i;
+ } a;
+ int b;
+} x;
+
+void
+f (void)
+{
+ x.i = 0; /* { dg-error "has no member" } */
+}
diff --git a/gcc/testsuite/gcc.dg/c11-anon-struct-3.c b/gcc/testsuite/gcc.dg/c11-anon-struct-3.c
new file mode 100644
index 00000000000..05cc3660cb8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-anon-struct-3.c
@@ -0,0 +1,34 @@
+/* Test for anonymous structures and unions in C11. Test for invalid
+ cases: typedefs disallowed by N1549. */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+typedef struct
+{
+ int i;
+} s0;
+
+typedef union
+{
+ int i;
+} u0;
+
+struct s1
+{
+ int a;
+ u0; /* { dg-error "declaration does not declare anything" } */
+ struct
+ {
+ int b;
+ };
+};
+
+union u1
+{
+ int b;
+ s0; /* { dg-error "declaration does not declare anything" } */
+ union
+ {
+ int c;
+ };
+};
diff --git a/gcc/testsuite/gcc.dg/c11-atomic-1.c b/gcc/testsuite/gcc.dg/c11-atomic-1.c
new file mode 100644
index 00000000000..c7f9a1ef464
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-atomic-1.c
@@ -0,0 +1,267 @@
+/* Test for _Atomic in C11. Test of valid code. See c11-atomic-2.c
+ for more exhaustive tests of assignment cases. */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+/* The use of _Atomic as a qualifier, and of _Atomic (type-name), give
+ the same type. */
+extern _Atomic int a;
+extern _Atomic (int) a;
+extern int *_Atomic b;
+extern _Atomic (int *) b;
+extern void f (int [_Atomic]);
+extern void f (int *_Atomic);
+
+/* _Atomic may be applied to arbitrary types, with or without other
+ qualifiers, and assignments may be made as with non-atomic
+ types. Structure and union elements may be atomic. */
+_Atomic int ai1, ai2;
+int i1;
+volatile _Atomic long double ald1;
+const _Atomic long double ald2;
+long double ld1;
+_Atomic _Complex double acd1, acd2;
+_Complex double d1;
+_Atomic volatile _Bool ab1;
+int *p;
+int *_Atomic restrict ap;
+struct s { char c[1000]; };
+_Atomic struct s as1;
+struct s s1;
+struct t { _Atomic int i; };
+_Atomic struct t at1;
+_Atomic struct t *atp1;
+struct t t1;
+union u { char c[1000]; };
+_Atomic union u au1;
+union u u1;
+union v { _Atomic int i; };
+_Atomic union v av1;
+union v v1;
+
+void
+func (_Atomic volatile long al1)
+{
+ ai1 = ai2;
+ ai1 = i1;
+ i1 = ai2;
+ ai1 = ald2;
+ ald1 = d1;
+ ld1 = acd2;
+ acd1 += ab1;
+ acd2 /= ai1;
+ p = ap;
+ ap = p;
+ ab1 = p;
+ as1 = s1;
+ s1 = as1;
+ at1 = t1;
+ t1 = at1;
+ /* It's unclear whether the undefined behavior (6.5.2.3#5) for
+ accessing elements of atomic structures and unions is at
+ translation or execution time; presume here that it's at
+ execution time. */
+ t1.i = at1.i;
+ at1.i = t1.i;
+ atp1->i = t1.i;
+ au1 = u1;
+ u1 = au1;
+ av1 = v1;
+ v1 = av1;
+ v1.i = av1.i;
+ av1.i = v1.i;
+ /* _Atomic is valid on register variables, even if not particularly
+ useful. */
+ register _Atomic volatile int ra1 = 1, ra2 = 2;
+ ra1 = ra2;
+ ra2 = ra1;
+ /* And on parameters. */
+ al1 = ra1;
+ ra2 = al1;
+}
+
+/* A function may return an atomic type. */
+_Atomic int
+func2 (int i)
+{
+ return i;
+}
+
+/* Casts may specify atomic type. */
+int
+func3 (int i)
+{
+ return func2 ((_Atomic long) i);
+}
+
+/* The _Atomic void type is valid. */
+_Atomic void *avp;
+
+/* An array of atomic elements is valid (the elements being atomic,
+ not the array). */
+_Atomic int aa[10];
+int
+func4 (void)
+{
+ return aa[2];
+}
+
+/* Increment and decrement are valid for atomic types when they are
+ valid for non-atomic types. */
+void
+func5 (void)
+{
+ ald1++;
+ ald1--;
+ ++ald1;
+ --ald1;
+ ai1++;
+ ai1--;
+ ++ai1;
+ --ai1;
+ ab1++;
+ ab1--;
+ ++ab1;
+ --ab1;
+ ap++;
+ ap--;
+ ++ap;
+ --ap;
+}
+
+/* Compound literals may have atomic type. */
+_Atomic int *aiclp = &(_Atomic int) { 1 };
+
+/* Test unary & and *. */
+void
+func6 (void)
+{
+ int i = *aiclp;
+ _Atomic int *p = &ai2;
+}
+
+/* Casts to atomic type are valid (although the _Atomic has little
+ effect because the result is an rvalue). */
+int i2 = (_Atomic int) 1.0;
+
+/* For pointer subtraction and comparisons, _Atomic does not count as
+ a qualifier. Likewise for conditional expressions. */
+_Atomic int *xaip1;
+volatile _Atomic int *xaip2;
+void *xvp1;
+
+void
+func7 (void)
+{
+ int r;
+ r = xaip1 - xaip2;
+ r = xaip1 < xaip2;
+ r = xaip1 > xaip2;
+ r = xaip1 <= xaip2;
+ r = xaip1 >= xaip2;
+ r = xaip1 == xaip2;
+ r = xaip1 != xaip2;
+ r = xaip1 == xvp1;
+ r = xaip1 != xvp1;
+ r = xvp1 == xaip1;
+ r = xvp1 != xaip1;
+ r = xaip1 == 0;
+ r = ((void *) 0) == xaip2;
+ (void) (r ? xaip1 : xaip2);
+ (void) (r ? xvp1 : xaip2);
+ (void) (r ? xaip2 : xvp1);
+ (void) (r ? xaip1 : 0);
+ (void) (r ? 0 : xaip1);
+ /* The result of a conditional expression between a pointer to
+ qualified or unqualified (but not atomic) void, and a pointer to
+ an atomic type, is a pointer to appropriately qualified, not
+ atomic, void. As such, it is valid to use further in conditional
+ expressions with other pointer types. */
+ (void) (r ? xaip1 : (r ? xaip1 : xvp1));
+}
+
+/* Pointer += and -= integer is valid. */
+void
+func8 (void)
+{
+ b += 1;
+ b -= 2ULL;
+ ap += 3;
+}
+
+/* Various other cases of simple assignment are valid (some already
+ tested above). */
+void
+func9 (void)
+{
+ ap = 0;
+ ap = (void *) 0;
+ xvp1 = atp1;
+ atp1 = xvp1;
+}
+
+/* Test compatibility of function types in cases where _Atomic matches
+ (see c11-atomic-3.c for corresponding cases where it doesn't
+ match). */
+void fc0a (int const);
+void fc0a (int);
+void fc0b (int _Atomic);
+void fc0b (int _Atomic);
+void fc1a (int);
+void
+fc1a (x)
+ volatile int x;
+{
+}
+void fc1b (_Atomic int);
+void
+fc1b (x)
+ volatile _Atomic int x;
+{
+}
+void
+fc2a (x)
+ const int x;
+{
+}
+void fc2a (int); /* { dg-warning "follows non-prototype" } */
+void
+fc2b (x)
+ _Atomic int x;
+{
+}
+void fc2b (_Atomic int); /* { dg-warning "follows non-prototype" } */
+void fc3a (int);
+void
+fc3a (x)
+ volatile short x;
+{
+}
+void fc3b (_Atomic int);
+void
+fc3b (x)
+ _Atomic short x;
+{
+}
+void
+fc4a (x)
+ const short x;
+{
+}
+void fc4a (int); /* { dg-warning "follows non-prototype" } */
+void
+fc4b (x)
+ _Atomic short x;
+{
+}
+void fc4b (_Atomic int); /* { dg-warning "follows non-prototype" } */
+
+/* Test cases involving C_MAYBE_CONST_EXPR work. */
+void
+func10 (_Atomic int *p)
+{
+ p[0 / 0] = 1; /* { dg-warning "division by zero" } */
+ p[0 / 0] += 1; /* { dg-warning "division by zero" } */
+ *p = 0 / 0; /* { dg-warning "division by zero" } */
+ *p += 0 / 0; /* { dg-warning "division by zero" } */
+}
diff --git a/gcc/testsuite/gcc.dg/c11-atomic-2.c b/gcc/testsuite/gcc.dg/c11-atomic-2.c
new file mode 100644
index 00000000000..34ee081d421
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-atomic-2.c
@@ -0,0 +1,165 @@
+/* Test for _Atomic in C11. Test of valid assignment cases for
+ arithmetic types. */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+#define TEST_ASSIGN(TYPE1, OP, TYPE2) \
+ do \
+ { \
+ _Atomic TYPE1 a = 0; \
+ TYPE2 b = 0; \
+ _Atomic TYPE2 c = 0; \
+ a OP b; \
+ a OP c; \
+ } \
+ while (0)
+
+#define TEST_ASSIGN_ARITHR(TYPE1, OP) \
+ do \
+ { \
+ TEST_ASSIGN (TYPE1, OP, _Bool); \
+ TEST_ASSIGN (TYPE1, OP, char); \
+ TEST_ASSIGN (TYPE1, OP, signed char); \
+ TEST_ASSIGN (TYPE1, OP, unsigned char); \
+ TEST_ASSIGN (TYPE1, OP, signed short); \
+ TEST_ASSIGN (TYPE1, OP, unsigned short); \
+ TEST_ASSIGN (TYPE1, OP, signed int); \
+ TEST_ASSIGN (TYPE1, OP, unsigned int); \
+ TEST_ASSIGN (TYPE1, OP, signed long); \
+ TEST_ASSIGN (TYPE1, OP, unsigned long); \
+ TEST_ASSIGN (TYPE1, OP, signed long long); \
+ TEST_ASSIGN (TYPE1, OP, unsigned long long); \
+ TEST_ASSIGN (TYPE1, OP, float); \
+ TEST_ASSIGN (TYPE1, OP, double); \
+ TEST_ASSIGN (TYPE1, OP, long double); \
+ TEST_ASSIGN (TYPE1, OP, _Complex float); \
+ TEST_ASSIGN (TYPE1, OP, _Complex double); \
+ TEST_ASSIGN (TYPE1, OP, _Complex long double); \
+ } \
+ while (0)
+
+#define TEST_ASSIGN_ARITHBOTH(OP) \
+ do \
+ { \
+ TEST_ASSIGN_ARITHR (_Bool, OP); \
+ TEST_ASSIGN_ARITHR (char, OP); \
+ TEST_ASSIGN_ARITHR (signed char, OP); \
+ TEST_ASSIGN_ARITHR (unsigned char, OP); \
+ TEST_ASSIGN_ARITHR (signed short, OP); \
+ TEST_ASSIGN_ARITHR (unsigned short, OP); \
+ TEST_ASSIGN_ARITHR (signed int, OP); \
+ TEST_ASSIGN_ARITHR (unsigned int, OP); \
+ TEST_ASSIGN_ARITHR (signed long, OP); \
+ TEST_ASSIGN_ARITHR (unsigned long, OP); \
+ TEST_ASSIGN_ARITHR (signed long long, OP); \
+ TEST_ASSIGN_ARITHR (unsigned long long, OP); \
+ TEST_ASSIGN_ARITHR (float, OP); \
+ TEST_ASSIGN_ARITHR (double, OP); \
+ TEST_ASSIGN_ARITHR (long double, OP); \
+ TEST_ASSIGN_ARITHR (_Complex float, OP); \
+ TEST_ASSIGN_ARITHR (_Complex double, OP); \
+ TEST_ASSIGN_ARITHR (_Complex long double, OP); \
+ } \
+ while (0)
+
+#define TEST_ASSIGN_INTR(TYPE1, OP) \
+ do \
+ { \
+ TEST_ASSIGN (TYPE1, OP, _Bool); \
+ TEST_ASSIGN (TYPE1, OP, char); \
+ TEST_ASSIGN (TYPE1, OP, signed char); \
+ TEST_ASSIGN (TYPE1, OP, unsigned char); \
+ TEST_ASSIGN (TYPE1, OP, signed short); \
+ TEST_ASSIGN (TYPE1, OP, unsigned short); \
+ TEST_ASSIGN (TYPE1, OP, signed int); \
+ TEST_ASSIGN (TYPE1, OP, unsigned int); \
+ TEST_ASSIGN (TYPE1, OP, signed long); \
+ TEST_ASSIGN (TYPE1, OP, unsigned long); \
+ TEST_ASSIGN (TYPE1, OP, signed long long); \
+ TEST_ASSIGN (TYPE1, OP, unsigned long long); \
+ } \
+ while (0)
+
+#define TEST_ASSIGN_INTBOTH(OP) \
+ do \
+ { \
+ TEST_ASSIGN_INTR (_Bool, OP); \
+ TEST_ASSIGN_INTR (char, OP); \
+ TEST_ASSIGN_INTR (signed char, OP); \
+ TEST_ASSIGN_INTR (unsigned char, OP); \
+ TEST_ASSIGN_INTR (signed short, OP); \
+ TEST_ASSIGN_INTR (unsigned short, OP); \
+ TEST_ASSIGN_INTR (signed int, OP); \
+ TEST_ASSIGN_INTR (unsigned int, OP); \
+ TEST_ASSIGN_INTR (signed long, OP); \
+ TEST_ASSIGN_INTR (unsigned long, OP); \
+ TEST_ASSIGN_INTR (signed long long, OP); \
+ TEST_ASSIGN_INTR (unsigned long long, OP); \
+ } \
+ while (0)
+
+void
+test_simple (void)
+{
+ TEST_ASSIGN_ARITHBOTH (=);
+}
+
+void
+test_mult (void)
+{
+ TEST_ASSIGN_ARITHBOTH (*=);
+}
+
+void
+test_div (void)
+{
+ TEST_ASSIGN_ARITHBOTH (/=);
+}
+
+void
+test_mod (void)
+{
+ TEST_ASSIGN_INTBOTH (%=);
+}
+
+void
+test_plus (void)
+{
+ TEST_ASSIGN_ARITHBOTH (+=);
+}
+
+void
+test_minus (void)
+{
+ TEST_ASSIGN_ARITHBOTH (-=);
+}
+
+void
+test_lshift (void)
+{
+ TEST_ASSIGN_INTBOTH (<<=);
+}
+
+void
+test_rshift (void)
+{
+ TEST_ASSIGN_INTBOTH (>>=);
+}
+
+void
+test_and (void)
+{
+ TEST_ASSIGN_INTBOTH (&=);
+}
+
+void
+test_xor (void)
+{
+ TEST_ASSIGN_INTBOTH (^=);
+}
+
+void
+test_or (void)
+{
+ TEST_ASSIGN_INTBOTH (|=);
+}
diff --git a/gcc/testsuite/gcc.dg/c11-atomic-3.c b/gcc/testsuite/gcc.dg/c11-atomic-3.c
new file mode 100644
index 00000000000..4b314e88ad5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-atomic-3.c
@@ -0,0 +1,174 @@
+/* Test for _Atomic in C11. Test of invalid code. */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+/* Increment and decrement are invalid for atomic complex types and
+ atomic pointers to incomplete types, just as for the corresponding
+ non-atomic types. Likewise for types on which arithmetic is
+ invalid. */
+_Atomic _Complex float acf;
+void *_Atomic apv;
+struct s *_Atomic aps;
+_Atomic struct t { char c; } as;
+
+void
+func (void)
+{
+ acf++; /* { dg-error "complex types" } */
+ acf--; /* { dg-error "complex types" } */
+ ++acf; /* { dg-error "complex types" } */
+ --acf; /* { dg-error "complex types" } */
+ apv++; /* { dg-error "wrong type|pointer of type" } */
+ apv--; /* { dg-error "wrong type|pointer of type" } */
+ ++apv; /* { dg-error "wrong type|pointer of type" } */
+ --apv; /* { dg-error "wrong type|pointer of type" } */
+ aps++; /* { dg-error "pointer to|invalid use of undefined type" } */
+ aps--; /* { dg-error "pointer to|invalid use of undefined type" } */
+ ++aps; /* { dg-error "pointer to|invalid use of undefined type" } */
+ --aps; /* { dg-error "pointer to|invalid use of undefined type" } */
+ as++; /* { dg-error "wrong type" } */
+ as--; /* { dg-error "wrong type" } */
+ ++as; /* { dg-error "wrong type" } */
+ --as; /* { dg-error "wrong type" } */
+}
+
+/* Pointer subtraction and comparisons differing in _Atomic are
+ invalid where such subtraction and comparisons differing in
+ qualifiers are valid. There is no special allowance for equality
+ comparisons of pointers to atomic void to pointers to object
+ types. Likewise for conditional expressions. */
+int *pi;
+_Atomic int *pai;
+_Atomic void *pav;
+int r;
+
+void
+func2 (void)
+{
+ r = pai - pi; /* { dg-error "invalid operands" } */
+ r = pi - pai; /* { dg-error "invalid operands" } */
+ r = pi < pai; /* { dg-error "distinct pointer types" } */
+ r = pi > pai; /* { dg-error "distinct pointer types" } */
+ r = pi <= pai; /* { dg-error "distinct pointer types" } */
+ r = pi >= pai; /* { dg-error "distinct pointer types" } */
+ r = pai < pi; /* { dg-error "distinct pointer types" } */
+ r = pai > pi; /* { dg-error "distinct pointer types" } */
+ r = pai <= pi; /* { dg-error "distinct pointer types" } */
+ r = pai >= pi; /* { dg-error "distinct pointer types" } */
+ r = pav == pi; /* { dg-error "distinct pointer types" } */
+ r = pav != pi; /* { dg-error "distinct pointer types" } */
+ r = pi == pav; /* { dg-error "distinct pointer types" } */
+ r = pi != pav; /* { dg-error "distinct pointer types" } */
+ (void) (r ? pai : pi); /* { dg-error "pointer type mismatch" } */
+ (void) (r ? pi : pai); /* { dg-error "pointer type mismatch" } */
+ (void) (r ? pai : pav); /* { dg-error "pointer type mismatch" } */
+ (void) (r ? pav : pai); /* { dg-error "pointer type mismatch" } */
+}
+
+/* Likewise for pointer assignment. */
+void
+func3 (void)
+{
+ pai = pi; /* { dg-error "incompatible pointer type" } */
+ pi = pai; /* { dg-error "incompatible pointer type" } */
+ pav = pai; /* { dg-error "incompatible pointer type" } */
+ pai = pav; /* { dg-error "incompatible pointer type" } */
+}
+
+/* Cases that are invalid for normal assignments are just as invalid
+ (and should not ICE) when the LHS is atomic. */
+void
+func4 (void)
+{
+ as = acf; /* { dg-error "incompatible types" } */
+ apv = as; /* { dg-error "incompatible types" } */
+ as += 1; /* { dg-error "invalid operands" } */
+ apv -= 1; /* { dg-error "pointer of type" } */
+ apv *= 1; /* { dg-error "invalid operands" } */
+ apv /= 1; /* { dg-error "invalid operands" } */
+ apv %= 1; /* { dg-error "invalid operands" } */
+ apv <<= 1; /* { dg-error "invalid operands" } */
+ apv >>= 1; /* { dg-error "invalid operands" } */
+ apv &= 1; /* { dg-error "invalid operands" } */
+ apv ^= 1; /* { dg-error "invalid operands" } */
+ apv |= 1; /* { dg-error "invalid operands" } */
+}
+
+/* We don't allow atomic bit-fields in GCC (implementation-defined
+ whether they are permitted). */
+struct abf
+{
+ _Atomic int i : 1; /* { dg-error "atomic type" } */
+ _Atomic int : 0; /* { dg-error "atomic type" } */
+};
+
+/* _Atomic (type-name) may not use a name for an array, function,
+ qualified or atomic type. */
+_Atomic (int [2]) v0; /* { dg-error "array type" } */
+_Atomic (void (void)) v1; /* { dg-error "function type" } */
+_Atomic (_Atomic int) v2; /* { dg-error "applied to a qualified type" } */
+_Atomic (const int) v3; /* { dg-error "applied to a qualified type" } */
+_Atomic (volatile int) v4; /* { dg-error "applied to a qualified type" } */
+_Atomic (int *restrict) v5; /* { dg-error "applied to a qualified type" } */
+
+/* _Atomic, used as a qualifier, may not be applied to a function or
+ array type. */
+typedef int arraytype[2];
+typedef void functiontype (void);
+_Atomic arraytype v6; /* { dg-error "array type" } */
+_Atomic arraytype *v7; /* { dg-error "array type" } */
+typedef _Atomic arraytype v8; /* { dg-error "array type" } */
+int v9 = sizeof (_Atomic arraytype); /* { dg-error "array type" } */
+void v10 (_Atomic arraytype parm); /* { dg-error "array type" } */
+struct v11 { _Atomic arraytype f; }; /* { dg-error "array type" } */
+_Atomic functiontype v12; /* { dg-error "function type" } */
+_Atomic functiontype *v13; /* { dg-error "function type" } */
+typedef _Atomic functiontype *v14; /* { dg-error "function type" } */
+void v15 (_Atomic functiontype parm); /* { dg-error "function type" } */
+
+/* Function parameters, when function types are required to be
+ compatible, may not differ in the presence of _Atomic. See
+ c11-atomic-1.c for corresponding tests where _Atomic matches. */
+void fc0 (int _Atomic); /* { dg-message "previous declaration" } */
+void fc0 (int); /* { dg-error "conflicting types" } */
+void fc1 (int); /* { dg-message "prototype declaration" } */
+void
+fc1 (x)
+ _Atomic int x; /* { dg-error "match prototype" } */
+{
+}
+void
+fc2 (x) /* { dg-message "previous definition" } */
+ _Atomic int x;
+{
+}
+void fc2 (int); /* { dg-error "incompatible type" } */
+void fc3 (int); /* { dg-message "prototype declaration" } */
+void
+fc3 (x)
+ _Atomic short x; /* { dg-error "match prototype" } */
+{
+}
+void
+fc4 (x) /* { dg-message "previous definition" } */
+ _Atomic short x;
+{
+}
+void fc4 (int); /* { dg-error "incompatible type" } */
+
+/* Arrays of atomic elements cannot be initialized with string
+ literals. */
+_Atomic char si0[] = ""; /* { dg-error "inappropriate type" } */
+_Atomic char si1[] = u8""; /* { dg-error "inappropriate type" } */
+_Atomic signed char si2[] = ""; /* { dg-error "inappropriate type" } */
+_Atomic signed char si3[] = u8""; /* { dg-error "inappropriate type" } */
+_Atomic unsigned char si4[] = ""; /* { dg-error "inappropriate type" } */
+_Atomic unsigned char si5[] = u8""; /* { dg-error "inappropriate type" } */
+_Atomic __WCHAR_TYPE__ si6[] = L""; /* { dg-error "inappropriate type" } */
+_Atomic __CHAR16_TYPE__ si7[] = u""; /* { dg-error "inappropriate type" } */
+_Atomic __CHAR32_TYPE__ si8[] = U""; /* { dg-error "inappropriate type" } */
+
+/* Anything that is syntactically a qualifier applied to the (void)
+ parameter list results in undefined behavior, which we
+ diagnose. */
+void fv (_Atomic void); /* { dg-error "may not be qualified" } */
diff --git a/gcc/testsuite/gcc.dg/c11-float-1.c b/gcc/testsuite/gcc.dg/c11-float-1.c
new file mode 100644
index 00000000000..376c44d3e78
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-float-1.c
@@ -0,0 +1,169 @@
+/* Test for <float.h> C11 macros. */
+/* Origin: Joseph Myers <joseph@codesourcery.com> */
+/* { dg-do preprocess } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+/* This test checks that the C11 macros are defined;
+ it does not check the correctness of their values. */
+
+#include <float.h>
+
+#ifndef FLT_ROUNDS
+#error "FLT_ROUNDS undefined"
+#endif
+
+#ifndef FLT_RADIX
+#error "FLT_RADIX undefined"
+#endif
+
+#ifndef FLT_MANT_DIG
+#error "FLT_MANT_DIG undefined"
+#endif
+
+#ifndef FLT_DIG
+#error "FLT_DIG undefined"
+#endif
+
+#ifndef FLT_MIN_EXP
+#error "FLT_MIN_EXP undefined"
+#endif
+
+#ifndef FLT_MIN_10_EXP
+#error "FLT_MIN_10_EXP undefined"
+#endif
+
+#ifndef FLT_MAX_EXP
+#error "FLT_MAX_EXP undefined"
+#endif
+
+#ifndef FLT_MAX_10_EXP
+#error "FLT_MAX_10_EXP undefined"
+#endif
+
+#ifndef FLT_MAX
+#error "FLT_MAX undefined"
+#endif
+
+#ifndef FLT_EPSILON
+#error "FLT_EPSILON undefined"
+#endif
+
+#ifndef FLT_MIN
+#error "FLT_MIN undefined"
+#endif
+
+#ifndef DBL_MANT_DIG
+#error "DBL_MANT_DIG undefined"
+#endif
+
+#ifndef DBL_DIG
+#error "DBL_DIG undefined"
+#endif
+
+#ifndef DBL_MIN_EXP
+#error "DBL_MIN_EXP undefined"
+#endif
+
+#ifndef DBL_MIN_10_EXP
+#error "DBL_MIN_10_EXP undefined"
+#endif
+
+#ifndef DBL_MAX_EXP
+#error "DBL_MAX_EXP undefined"
+#endif
+
+#ifndef DBL_MAX_10_EXP
+#error "DBL_MAX_10_EXP undefined"
+#endif
+
+#ifndef DBL_MAX
+#error "DBL_MAX undefined"
+#endif
+
+#ifndef DBL_EPSILON
+#error "DBL_EPSILON undefined"
+#endif
+
+#ifndef DBL_MIN
+#error "DBL_MIN undefined"
+#endif
+
+#ifndef LDBL_MANT_DIG
+#error "LDBL_MANT_DIG undefined"
+#endif
+
+#ifndef LDBL_DIG
+#error "LDBL_DIG undefined"
+#endif
+
+#ifndef LDBL_MIN_EXP
+#error "LDBL_MIN_EXP undefined"
+#endif
+
+#ifndef LDBL_MIN_10_EXP
+#error "LDBL_MIN_10_EXP undefined"
+#endif
+
+#ifndef LDBL_MAX_EXP
+#error "LDBL_MAX_EXP undefined"
+#endif
+
+#ifndef LDBL_MAX_10_EXP
+#error "LDBL_MAX_10_EXP undefined"
+#endif
+
+#ifndef LDBL_MAX
+#error "LDBL_MAX undefined"
+#endif
+
+#ifndef LDBL_EPSILON
+#error "LDBL_EPSILON undefined"
+#endif
+
+#ifndef LDBL_MIN
+#error "LDBL_MIN undefined"
+#endif
+
+#ifndef FLT_EVAL_METHOD
+#error "FLT_EVAL_METHOD undefined"
+#endif
+
+#ifndef DECIMAL_DIG
+#error "DECIMAL_DIG undefined"
+#endif
+
+#ifndef FLT_DECIMAL_DIG
+#error "FLT_DECIMAL_DIG undefined"
+#endif
+
+#ifndef DBL_DECIMAL_DIG
+#error "DBL_DECIMAL_DIG undefined"
+#endif
+
+#ifndef LDBL_DECIMAL_DIG
+#error "LDBL_DECIMAL_DIG undefined"
+#endif
+
+#ifndef FLT_HAS_SUBNORM
+#error "FLT_HAS_SUBNORM undefined"
+#endif
+
+#ifndef DBL_HAS_SUBNORM
+#error "DBL_HAS_SUBNORM undefined"
+#endif
+
+#ifndef LDBL_HAS_SUBNORM
+#error "LDBL_HAS_SUBNORM undefined"
+#endif
+
+#ifndef FLT_TRUE_MIN
+#error "FLT_TRUE_MIN undefined"
+#endif
+
+#ifndef DBL_TRUE_MIN
+#error "DBL_TRUE_MIN undefined"
+#endif
+
+#ifndef LDBL_TRUE_MIN
+#error "LDBL_TRUE_MIN undefined"
+#endif
diff --git a/gcc/testsuite/gcc.dg/c11-noreturn-1.c b/gcc/testsuite/gcc.dg/c11-noreturn-1.c
new file mode 100644
index 00000000000..e92c5ae0456
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-noreturn-1.c
@@ -0,0 +1,59 @@
+/* Test C11 _Noreturn. Test valid code. */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+_Noreturn void exit (int);
+
+_Noreturn int f1 (void);
+
+_Noreturn void f2 (void);
+
+static void _Noreturn f3 (void) { exit (0); }
+
+/* Returning from a noreturn function is undefined at runtime, not a
+ constraint violation, but recommended practice is to diagnose if
+ such a return appears possible. */
+
+_Noreturn int
+f4 (void)
+{
+ return 1; /* { dg-warning "has a 'return' statement" } */
+ /* { dg-warning "does return" "second warning" { target *-*-* } 20 } */
+}
+
+_Noreturn void
+f5 (void)
+{
+ return; /* { dg-warning "has a 'return' statement" } */
+ /* { dg-warning "does return" "second warning" { target *-*-* } 27 } */
+}
+
+_Noreturn void
+f6 (void)
+{
+} /* { dg-warning "does return" } */
+
+_Noreturn void
+f7 (int a)
+{
+ if (a)
+ exit (0);
+} /* { dg-warning "does return" } */
+
+/* Declarations need not all have _Noreturn. */
+
+void f2 (void);
+
+void f8 (void);
+_Noreturn void f8 (void);
+
+/* Duplicate _Noreturn is OK. */
+_Noreturn _Noreturn void _Noreturn f9 (void);
+
+/* _Noreturn does not affect type compatibility. */
+
+void (*fp) (void) = f5;
+
+/* noreturn is an ordinary identifier. */
+
+int noreturn;
diff --git a/gcc/testsuite/gcc.dg/c11-noreturn-2.c b/gcc/testsuite/gcc.dg/c11-noreturn-2.c
new file mode 100644
index 00000000000..951d028f7ae
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-noreturn-2.c
@@ -0,0 +1,77 @@
+/* Test C11 _Noreturn. Test valid code using stdnoreturn.h. */
+/* { dg-do run } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+#include <stdnoreturn.h>
+
+extern int strcmp (const char *, const char *);
+
+noreturn void exit (int);
+noreturn void abort (void);
+
+noreturn int f1 (void);
+
+noreturn void f2 (void);
+
+static void noreturn f3 (void) { exit (0); }
+
+/* Returning from a noreturn function is undefined at runtime, not a
+ constraint violation, but recommended practice is to diagnose if
+ such a return appears possible. */
+
+noreturn int
+f4 (void)
+{
+ return 1; /* { dg-warning "has a 'return' statement" } */
+ /* { dg-warning "does return" "second warning" { target *-*-* } 25 } */
+}
+
+noreturn void
+f5 (void)
+{
+ return; /* { dg-warning "has a 'return' statement" } */
+ /* { dg-warning "does return" "second warning" { target *-*-* } 32 } */
+}
+
+noreturn void
+f6 (void)
+{
+} /* { dg-warning "does return" } */
+
+noreturn void
+f7 (int a)
+{
+ if (a)
+ exit (0);
+} /* { dg-warning "does return" } */
+
+/* Declarations need not all have noreturn. */
+
+void f2 (void);
+
+void f8 (void);
+noreturn void f8 (void);
+
+/* Duplicate noreturn is OK. */
+noreturn noreturn void noreturn f9 (void);
+
+/* noreturn does not affect type compatibility. */
+
+void (*fp) (void) = f5;
+
+#ifndef noreturn
+#error "noreturn not defined"
+#endif
+
+#define str(x) #x
+#define xstr(x) str(x)
+
+const char *s = xstr(noreturn);
+
+int
+main (void)
+{
+ if (strcmp (s, "_Noreturn") != 0)
+ abort ();
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/c11-noreturn-3.c b/gcc/testsuite/gcc.dg/c11-noreturn-3.c
new file mode 100644
index 00000000000..168d012a3f0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-noreturn-3.c
@@ -0,0 +1,11 @@
+/* Test C11 _Noreturn. Test _Noreturn on main, hosted. */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic-errors -fhosted" } */
+
+_Noreturn void exit (int);
+
+_Noreturn int
+main (void) /* { dg-error "'main' declared '_Noreturn'" } */
+{
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/c11-noreturn-4.c b/gcc/testsuite/gcc.dg/c11-noreturn-4.c
new file mode 100644
index 00000000000..a92a1140f67
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-noreturn-4.c
@@ -0,0 +1,11 @@
+/* Test C11 _Noreturn. Test _Noreturn on main, freestanding. */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic-errors -ffreestanding" } */
+
+_Noreturn void exit (int);
+
+_Noreturn int
+main (void)
+{
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/c11-noreturn-5.c b/gcc/testsuite/gcc.dg/c11-noreturn-5.c
new file mode 100644
index 00000000000..d1c0949f32b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-noreturn-5.c
@@ -0,0 +1,17 @@
+/* Test C11 _Noreturn. Test invalid uses. */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+_Noreturn struct s; /* { dg-error "empty declaration" } */
+
+typedef _Noreturn void f (void); /* { dg-error "typedef" } */
+
+void g (_Noreturn void fp (void)); /* { dg-error "parameter" } */
+
+_Noreturn void (*p) (void); /* { dg-error "variable" } */
+
+struct t { int a; _Noreturn void (*f) (void); }; /* { dg-error "expected" } */
+
+int *_Noreturn *q; /* { dg-error "expected" } */
+
+int i = sizeof (_Noreturn int (*) (void)); /* { dg-error "expected" } */
diff --git a/gcc/testsuite/gcc.dg/c11-pointer-float-1.c b/gcc/testsuite/gcc.dg/c11-pointer-float-1.c
new file mode 100644
index 00000000000..8c241658777
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-pointer-float-1.c
@@ -0,0 +1,28 @@
+/* Test C11 constraint against pointer / floating-point casts. */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+void *p;
+float f;
+double d;
+long double ld;
+_Complex float cf;
+_Complex double cd;
+_Complex long double cld;
+
+void
+func (void)
+{
+ f = (float) p; /* { dg-error "pointer" } */
+ d = (double) p; /* { dg-error "pointer" } */
+ ld = (long double) p; /* { dg-error "pointer" } */
+ cf = (_Complex float) p; /* { dg-error "pointer" } */
+ cd = (_Complex double) p; /* { dg-error "pointer" } */
+ cld = (_Complex long double) p; /* { dg-error "pointer" } */
+ p = (void *) f; /* { dg-error "pointer" } */
+ p = (void *) d; /* { dg-error "pointer" } */
+ p = (void *) ld; /* { dg-error "pointer" } */
+ p = (void *) cf; /* { dg-error "pointer" } */
+ p = (void *) cd; /* { dg-error "pointer" } */
+ p = (void *) cld; /* { dg-error "pointer" } */
+}
diff --git a/gcc/testsuite/gcc.dg/c11-static-assert-1.c b/gcc/testsuite/gcc.dg/c11-static-assert-1.c
new file mode 100644
index 00000000000..9209a7a4076
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-static-assert-1.c
@@ -0,0 +1,41 @@
+/* Test C11 static assertions. Valid assertions. */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+_Static_assert (1, "foo");
+
+enum e { E0, E1 };
+
+_Static_assert (E1, L"bar");
+
+_Static_assert (-1, "foo" L"bar");
+
+struct s
+{
+ int a;
+ _Static_assert (3, "s");
+ int b;
+};
+
+union u
+{
+ int i;
+ _Static_assert ((int)1.0, L"");
+};
+
+void
+f (void)
+{
+ int i;
+ i = 1;
+ _Static_assert (0 + 1, "f");
+ i = 2;
+}
+
+void
+g (void)
+{
+ int i = 0;
+ for (_Static_assert (1, ""); i < 10; i++)
+ ;
+}
diff --git a/gcc/testsuite/gcc.dg/c11-static-assert-2.c b/gcc/testsuite/gcc.dg/c11-static-assert-2.c
new file mode 100644
index 00000000000..de2f573cb8c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-static-assert-2.c
@@ -0,0 +1,41 @@
+/* Test C11 static assertions. Failed assertions. */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+_Static_assert (0, "assert1"); /* { dg-error "static assertion failed: \"assert1\"" } */
+
+enum e { E0, E1 };
+
+_Static_assert (E0, L"assert2"); /* { dg-error "static assertion failed: \"assert2\"" } */
+
+_Static_assert (-0, "ass" L"ert3"); /* { dg-error "static assertion failed: \"assert3\"" } */
+
+struct s
+{
+ int a;
+ _Static_assert (0, "assert4"); /* { dg-error "static assertion failed: \"assert4\"" } */
+ int b;
+};
+
+union u
+{
+ int i;
+ _Static_assert ((int)0.0, L"assert5"); /* { dg-error "static assertion failed: \"assert5\"" } */
+};
+
+void
+f (void)
+{
+ int i;
+ i = 1;
+ _Static_assert (0 + 0, "assert6"); /* { dg-error "static assertion failed: \"assert6\"" } */
+ i = 2;
+}
+
+void
+g (void)
+{
+ int i = 0;
+ for (_Static_assert (0, "assert7"); i < 10; i++) /* { dg-error "static assertion failed: \"assert7\"" } */
+ ;
+}
diff --git a/gcc/testsuite/gcc.dg/c11-static-assert-3.c b/gcc/testsuite/gcc.dg/c11-static-assert-3.c
new file mode 100644
index 00000000000..79448a533e5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-static-assert-3.c
@@ -0,0 +1,28 @@
+/* Test C11 static assertions. Invalid assertions. */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+_Static_assert (__INT_MAX__ * 2, "overflow"); /* { dg-warning "integer overflow in expression" } */
+/* { dg-error "overflow in constant expression" "error" { target *-*-* } 5 } */
+
+_Static_assert ((void *)(__SIZE_TYPE__)16, "non-integer"); /* { dg-error "not an integer" } */
+
+_Static_assert (1.0, "non-integer"); /* { dg-error "not an integer" } */
+
+_Static_assert ((int)(1.0 + 1.0), "non-constant-expression"); /* { dg-error "not an integer constant expression" } */
+
+int i;
+
+_Static_assert (i, "non-constant"); /* { dg-error "not constant" } */
+
+void
+f (void)
+{
+ int j = 0;
+ for (_Static_assert (sizeof (struct s { int k; }), ""); j < 10; j++) /* { dg-error "loop initial declaration" } */
+ ;
+}
+
+_Static_assert (1, 1); /* { dg-error "expected" } */
+
+_Static_assert (1, ("")); /* { dg-error "expected" } */
diff --git a/gcc/testsuite/gcc.dg/c11-static-assert-4.c b/gcc/testsuite/gcc.dg/c11-static-assert-4.c
new file mode 100644
index 00000000000..ddab440ff48
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-static-assert-4.c
@@ -0,0 +1,13 @@
+/* Test C11 static assertions. More invalid assertions. */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+/* Static assertions not valid in old-style parameter declarations
+ because declarations there must have declarators. */
+
+void
+f (i)
+ int i;
+ _Static_assert (1, ""); /* { dg-error "expected" } */
+{
+}
diff --git a/gcc/testsuite/gcc.dg/c11-static-assert-5.c b/gcc/testsuite/gcc.dg/c11-static-assert-5.c
new file mode 100644
index 00000000000..e88b8167a19
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-static-assert-5.c
@@ -0,0 +1,5 @@
+/* Test C11 static assertions. Non-constant-expression without -pedantic. */
+/* { dg-do compile } */
+/* { dg-options "-std=c11" } */
+
+_Static_assert ((int)(1.0 + 1.0), "non-constant-expression");
diff --git a/gcc/testsuite/gcc.dg/c11-static-assert-6.c b/gcc/testsuite/gcc.dg/c11-static-assert-6.c
new file mode 100644
index 00000000000..ac7e14114db
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-static-assert-6.c
@@ -0,0 +1,5 @@
+/* Test C11 static assertions. Non-constant-expression with -pedantic. */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic" } */
+
+_Static_assert ((int)(1.0 + 1.0), "non-constant-expression"); /* { dg-warning "not an integer constant expression" } */
diff --git a/gcc/testsuite/gcc.dg/c11-stdatomic-1.c b/gcc/testsuite/gcc.dg/c11-stdatomic-1.c
new file mode 100644
index 00000000000..79909c055a7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-stdatomic-1.c
@@ -0,0 +1,119 @@
+/* Test stdatomic.h header contents. */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+#include <stdatomic.h>
+
+#ifndef ATOMIC_BOOL_LOCK_FREE
+# error ATOMIC_BOOL_LOCK_FREE not defined
+#endif
+
+#ifndef ATOMIC_CHAR_LOCK_FREE
+# error ATOMIC_CHAR_LOCK_FREE not defined
+#endif
+
+#ifndef ATOMIC_CHAR16_T_LOCK_FREE
+# error ATOMIC_CHAR16_T_LOCK_FREE not defined
+#endif
+
+#ifndef ATOMIC_CHAR32_T_LOCK_FREE
+# error ATOMIC_CHAR32_T_LOCK_FREE not defined
+#endif
+
+#ifndef ATOMIC_WCHAR_T_LOCK_FREE
+# error ATOMIC_WCHAR_T_LOCK_FREE not defined
+#endif
+
+#ifndef ATOMIC_SHORT_LOCK_FREE
+# error ATOMIC_SHORT_LOCK_FREE not defined
+#endif
+
+#ifndef ATOMIC_INT_LOCK_FREE
+# error ATOMIC_INT_LOCK_FREE not defined
+#endif
+
+#ifndef ATOMIC_LONG_LOCK_FREE
+# error ATOMIC_LONG_LOCK_FREE not defined
+#endif
+
+#ifndef ATOMIC_LLONG_LOCK_FREE
+# error ATOMIC_LLONG_LOCK_FREE not defined
+#endif
+
+#ifndef ATOMIC_POINTER_LOCK_FREE
+# error ATOMIC_POINTER_LOCK_FREE not defined
+#endif
+
+memory_order m0 = memory_order_relaxed;
+memory_order m1 = memory_order_consume;
+memory_order m2 = memory_order_acquire;
+memory_order m3 = memory_order_release;
+memory_order m4 = memory_order_acq_rel;
+memory_order m5 = memory_order_seq_cst;
+
+atomic_flag af = ATOMIC_FLAG_INIT;
+
+struct s { int i[100]; } sv;
+void
+f (void)
+{
+ _Atomic struct s sva = ATOMIC_VAR_INIT (sv);
+}
+
+#ifndef kill_dependency
+# error kill_dependency not defined
+#endif
+
+#define CHECK_ATOMIC_TYPEDEF(A, B) \
+ do \
+ { \
+ A v; \
+ char array1[sizeof (A) == sizeof (B) ? 1 : -1]; \
+ char array2[_Alignof (A) == _Alignof (B) ? 1 : -1]; \
+ } \
+ while (0)
+
+#include <stddef.h>
+#include <stdint.h>
+
+void
+check_typedefs (void)
+{
+ CHECK_ATOMIC_TYPEDEF (atomic_bool, _Atomic _Bool);
+ CHECK_ATOMIC_TYPEDEF (atomic_char, _Atomic char);
+ CHECK_ATOMIC_TYPEDEF (atomic_schar, _Atomic signed char);
+ CHECK_ATOMIC_TYPEDEF (atomic_uchar, _Atomic unsigned char);
+ CHECK_ATOMIC_TYPEDEF (atomic_short, _Atomic short);
+ CHECK_ATOMIC_TYPEDEF (atomic_ushort, _Atomic unsigned short);
+ CHECK_ATOMIC_TYPEDEF (atomic_int, _Atomic int);
+ CHECK_ATOMIC_TYPEDEF (atomic_uint, _Atomic unsigned int);
+ CHECK_ATOMIC_TYPEDEF (atomic_long, _Atomic long);
+ CHECK_ATOMIC_TYPEDEF (atomic_ulong, _Atomic unsigned long);
+ CHECK_ATOMIC_TYPEDEF (atomic_llong, _Atomic long long);
+ CHECK_ATOMIC_TYPEDEF (atomic_ullong, _Atomic unsigned long long);
+ CHECK_ATOMIC_TYPEDEF (atomic_char16_t, _Atomic __CHAR16_TYPE__);
+ CHECK_ATOMIC_TYPEDEF (atomic_char32_t, _Atomic __CHAR32_TYPE__);
+ CHECK_ATOMIC_TYPEDEF (atomic_wchar_t, _Atomic wchar_t);
+ CHECK_ATOMIC_TYPEDEF (atomic_int_least8_t, _Atomic int_least8_t);
+ CHECK_ATOMIC_TYPEDEF (atomic_uint_least8_t, _Atomic uint_least8_t);
+ CHECK_ATOMIC_TYPEDEF (atomic_int_least16_t, _Atomic int_least16_t);
+ CHECK_ATOMIC_TYPEDEF (atomic_uint_least16_t, _Atomic uint_least16_t);
+ CHECK_ATOMIC_TYPEDEF (atomic_int_least32_t, _Atomic int_least32_t);
+ CHECK_ATOMIC_TYPEDEF (atomic_uint_least32_t, _Atomic uint_least32_t);
+ CHECK_ATOMIC_TYPEDEF (atomic_int_least64_t, _Atomic int_least64_t);
+ CHECK_ATOMIC_TYPEDEF (atomic_uint_least64_t, _Atomic uint_least64_t);
+ CHECK_ATOMIC_TYPEDEF (atomic_int_fast8_t, _Atomic int_fast8_t);
+ CHECK_ATOMIC_TYPEDEF (atomic_uint_fast8_t, _Atomic uint_fast8_t);
+ CHECK_ATOMIC_TYPEDEF (atomic_int_fast16_t, _Atomic int_fast16_t);
+ CHECK_ATOMIC_TYPEDEF (atomic_uint_fast16_t, _Atomic uint_fast16_t);
+ CHECK_ATOMIC_TYPEDEF (atomic_int_fast32_t, _Atomic int_fast32_t);
+ CHECK_ATOMIC_TYPEDEF (atomic_uint_fast32_t, _Atomic uint_fast32_t);
+ CHECK_ATOMIC_TYPEDEF (atomic_int_fast64_t, _Atomic int_fast64_t);
+ CHECK_ATOMIC_TYPEDEF (atomic_uint_fast64_t, _Atomic uint_fast64_t);
+ CHECK_ATOMIC_TYPEDEF (atomic_intptr_t, _Atomic intptr_t);
+ CHECK_ATOMIC_TYPEDEF (atomic_uintptr_t, _Atomic uintptr_t);
+ CHECK_ATOMIC_TYPEDEF (atomic_size_t, _Atomic size_t);
+ CHECK_ATOMIC_TYPEDEF (atomic_ptrdiff_t, _Atomic ptrdiff_t);
+ CHECK_ATOMIC_TYPEDEF (atomic_intmax_t, _Atomic intmax_t);
+ CHECK_ATOMIC_TYPEDEF (atomic_uintmax_t, _Atomic uintmax_t);
+}
diff --git a/gcc/testsuite/gcc.dg/c11-typedef-1.c b/gcc/testsuite/gcc.dg/c11-typedef-1.c
new file mode 100644
index 00000000000..3224ba5a418
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-typedef-1.c
@@ -0,0 +1,70 @@
+/* Test typedef redeclaration in C11. */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+/* C11 permits typedefs to be redeclared to the same type, but not to
+ different-but-compatible types, and not when the type is variably
+ modified. */
+
+#include <limits.h>
+
+typedef int TI;
+typedef int TI2;
+typedef TI2 TI;
+typedef TI TI2;
+
+enum e { E1 = 0, E2 = INT_MAX, E3 = -1 };
+typedef enum e TE;
+typedef enum e TE; /* { dg-message "previous declaration" } */
+typedef int TE; /* { dg-error "with different type" } */
+
+struct s;
+typedef struct s TS;
+struct s { int i; };
+typedef struct s TS;
+
+typedef int IA[];
+typedef TI2 IA[]; /* { dg-message "previous declaration" } */
+typedef int A2[2];
+typedef TI A2[2]; /* { dg-message "previous declaration" } */
+typedef IA A2; /* { dg-error "with different type" } */
+typedef int A3[3];
+typedef A3 IA; /* { dg-error "with different type" } */
+
+typedef void F(int);
+typedef void F(TI); /* { dg-message "previous declaration" } */
+typedef void F(enum e); /* { dg-error "with different type" } */
+
+typedef int G(void);
+typedef TI G(void); /* { dg-message "previous declaration" } */
+typedef enum e G(void); /* { dg-error "with different type" } */
+
+typedef int *P;
+typedef TI *P; /* { dg-message "previous declaration" } */
+typedef enum e *P; /* { dg-error "with different type" } */
+
+typedef void F2();
+typedef void F2(); /* { dg-message "previous declaration" } */
+typedef void F2(int); /* { dg-error "with different type" } */
+
+void
+f (void)
+{
+ int a = 1;
+ int b = 2;
+ typedef void FN(int (*p)[a]);
+ typedef void FN(int (*p)[b]);
+ typedef void FN(int (*p)[*]); /* { dg-message "previous declaration" } */
+ typedef void FN(int (*p)[1]); /* { dg-error "with different type" } */
+ typedef void FN2(int (*p)[a]);
+ typedef void FN2(int (*p)[b]);
+ typedef void FN2(int (*p)[*]); /* { dg-message "previous declaration" } */
+ typedef void FN2(int (*p)[]); /* { dg-error "with different type" } */
+ typedef int AV[a]; /* { dg-message "previous declaration" } */
+ typedef int AV[b-1]; /* { dg-error "redefinition" } */
+ typedef int AAa[a]; /* { dg-message "previous declaration" } */
+ typedef int AAb[b-1];
+ typedef AAa *VF(void); /* { dg-message "previous declaration" } */
+ typedef AAb *VF(void); /* { dg-error "redefinition" } */
+ typedef AAa AAa; /* { dg-error "redefinition" } */
+}
diff --git a/gcc/testsuite/gcc.dg/c11-uni-string-1.c b/gcc/testsuite/gcc.dg/c11-uni-string-1.c
new file mode 100644
index 00000000000..9f86bea826b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-uni-string-1.c
@@ -0,0 +1,112 @@
+/* Test Unicode strings in C11. Test valid code. */
+/* { dg-do run } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+/* More thorough tests are in c-c++-common/raw-string-*.c; this test
+ verifies the particular subset (Unicode but not raw strings) that
+ is in C11. */
+
+typedef __CHAR16_TYPE__ char16_t;
+typedef __CHAR32_TYPE__ char32_t;
+typedef __SIZE_TYPE__ size_t;
+
+extern void abort (void);
+extern void exit (int);
+extern int memcmp (const void *, const void *, size_t);
+
+#define R "(R)"
+#define u8R "(u8R)"
+#define uR "(uR)"
+#define UR "(UR)"
+#define LR "(LR)"
+#define u8 randomu8
+#define u randomu
+#define U randomU
+
+const char su8[] = u8"a\u010d";
+const char su8a[] = "a\xc4\x8d";
+
+const char16_t su16[] = u"\u0567";
+const char16_t su16a[] = { 0x0567, 0 };
+
+const char32_t su32[] = U"\u0123";
+const char32_t su32a[] = { 0x0123, 0 };
+
+const char tu[] = R"a";
+const char tua[] = "(R)a";
+
+const char tu8[] = u8R"b";
+const char tu8a[] = "(u8R)b";
+
+const char tu16[] = uR"c";
+const char tu16a[] = "(uR)c";
+
+const char tu32[] = UR"d";
+const char tu32a[] = "(UR)d";
+
+const char tl[] = LR"e";
+const char tla[] = "(LR)e";
+
+#define str(x) #x
+const char ts[] = str(u"a" U"b" u8"c");
+const char tsa[] = "u\"a\" U\"b\" u8\"c\"";
+
+/* GCC always uses UTF-16 and UTF-32 for char16_t and char32_t. */
+#ifndef __STDC_UTF_16__
+#error "__STDC_UTF_16__ not defined"
+#endif
+#ifndef __STDC_UTF_32__
+#error "__STDC_UTF_32__ not defined"
+#endif
+#define xstr(x) str(x)
+const char tm16[] = xstr(__STDC_UTF_16__);
+const char tm16a[] = "1";
+const char tm32[] = xstr(__STDC_UTF_32__);
+const char tm32a[] = "1";
+
+int
+main (void)
+{
+ if (sizeof (su8) != sizeof (su8a)
+ || memcmp (su8, su8a, sizeof (su8)) != 0)
+ abort ();
+ if (sizeof (su16) != sizeof (su16a)
+ || memcmp (su16, su16a, sizeof (su16)) != 0)
+ abort ();
+ if (sizeof (su32) != sizeof (su32a)
+ || memcmp (su32, su32a, sizeof (su32)) != 0)
+ abort ();
+ if (sizeof (tu) != sizeof (tua)
+ || memcmp (tu, tua, sizeof (tu)) != 0)
+ abort ();
+ if (sizeof (tu8) != sizeof (tu8a)
+ || memcmp (tu8, tu8a, sizeof (tu8)) != 0)
+ abort ();
+ if (sizeof (tu16) != sizeof (tu16a)
+ || memcmp (tu16, tu16a, sizeof (tu16)) != 0)
+ abort ();
+ if (sizeof (tu32) != sizeof (tu32a)
+ || memcmp (tu32, tu32a, sizeof (tu32)) != 0)
+ abort ();
+ if (sizeof (tl) != sizeof (tla)
+ || memcmp (tl, tla, sizeof (tl)) != 0)
+ abort ();
+ if (sizeof (ts) != sizeof (tsa)
+ || memcmp (ts, tsa, sizeof (ts)) != 0)
+ abort ();
+ if (sizeof (tm16) != sizeof (tm16a)
+ || memcmp (tm16, tm16a, sizeof (tm16)) != 0)
+ abort ();
+ if (sizeof (tm32) != sizeof (tm32a)
+ || memcmp (tm32, tm32a, sizeof (tm32)) != 0)
+ abort ();
+ if (u'\u0123' != 0x0123)
+ abort ();
+ if (U'\u0456' != 0x0456)
+ abort ();
+#undef u8
+#define u8
+ if (u8'a' != 'a')
+ abort ();
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/c11-uni-string-2.c b/gcc/testsuite/gcc.dg/c11-uni-string-2.c
new file mode 100644
index 00000000000..583c38a87e2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-uni-string-2.c
@@ -0,0 +1,8 @@
+/* Test Unicode strings in C11. Test constraint. */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+const void *p1 = L"a" u8"b"; /* { dg-error "concatenation" } */
+const void *p2 = L"a" "b" u8"c"; /* { dg-error "concatenation" } */
+const void *p3 = u8"a" L"b"; /* { dg-error "concatenation" } */
+const void *p4 = u8"a" "b" L"c"; /* { dg-error "concatenation" } */
diff --git a/gcc/testsuite/gcc.dg/c1x-align-1.c b/gcc/testsuite/gcc.dg/c1x-align-1.c
deleted file mode 100644
index 9fe5757bed0..00000000000
--- a/gcc/testsuite/gcc.dg/c1x-align-1.c
+++ /dev/null
@@ -1,41 +0,0 @@
-/* Test C1X alignment support. Test valid code. */
-/* { dg-do compile } */
-/* { dg-options "-std=c1x -pedantic-errors" } */
-
-#include <stddef.h>
-
-_Alignas (_Alignof (max_align_t)) char c;
-extern _Alignas (max_align_t) char c;
-extern char c;
-
-extern _Alignas (max_align_t) short s;
-_Alignas (max_align_t) short s;
-
-_Alignas (int) int i;
-extern int i;
-
-_Alignas (max_align_t) long l;
-
-_Alignas (max_align_t) long long ll;
-
-_Alignas (max_align_t) float f;
-
-_Alignas (max_align_t) double d;
-
-_Alignas (max_align_t) _Complex long double cld;
-
-_Alignas (0) _Alignas (int) _Alignas (char) char ca[10];
-
-_Alignas ((int) _Alignof (max_align_t) + 0) int x;
-
-enum e { E = _Alignof (max_align_t) };
-_Alignas (E) int y;
-
-void
-func (void)
-{
- _Alignas (max_align_t) long long auto_ll;
-}
-
-/* Valid, but useless. */
-_Alignas (0) struct s; /* { dg-warning "useless" } */
diff --git a/gcc/testsuite/gcc.dg/c1x-align-2.c b/gcc/testsuite/gcc.dg/c1x-align-2.c
deleted file mode 100644
index 19f7dd67214..00000000000
--- a/gcc/testsuite/gcc.dg/c1x-align-2.c
+++ /dev/null
@@ -1,92 +0,0 @@
-/* Test C1X alignment support. Test valid code using stdalign.h. */
-/* { dg-do run } */
-/* { dg-options "-std=c1x -pedantic-errors" } */
-
-#include <stdalign.h>
-#include <stddef.h>
-
-extern int strcmp (const char *, const char *);
-
-extern void exit (int);
-extern void abort (void);
-
-alignas (alignof (max_align_t)) char c;
-extern alignas (max_align_t) char c;
-extern char c;
-
-extern alignas (max_align_t) short s;
-alignas (max_align_t) short s;
-
-alignas (int) int i;
-extern int i;
-
-alignas (max_align_t) long l;
-
-alignas (max_align_t) long long ll;
-
-alignas (max_align_t) float f;
-
-alignas (max_align_t) double d;
-
-alignas (max_align_t) _Complex long double cld;
-
-alignas (0) alignas (int) alignas (char) char ca[10];
-
-alignas ((int) alignof (max_align_t) + 0) int x;
-
-enum e { E = alignof (max_align_t) };
-alignas (E) int y;
-
-void
-func (void)
-{
- alignas (max_align_t) long long auto_ll;
-}
-
-/* Valid, but useless. */
-alignas (0) struct s; /* { dg-warning "useless" } */
-
-#ifndef alignas
-#error "alignas not defined"
-#endif
-
-#ifndef alignof
-#error "alignof not defined"
-#endif
-
-#ifndef __alignas_is_defined
-#error "__alignas_is_defined not defined"
-#endif
-
-#if __alignas_is_defined != 1
-#error "__alignas_is_defined not 1"
-#endif
-
-#ifndef __alignof_is_defined
-#error "__alignof_is_defined not defined"
-#endif
-
-#if __alignof_is_defined != 1
-#error "__alignof_is_defined not 1"
-#endif
-
-#define str(x) #x
-#define xstr(x) str(x)
-
-const char *s1 = xstr(alignas);
-const char *s2 = xstr(alignof);
-const char *s3 = xstr(__alignas_is_defined);
-const char *s4 = xstr(__alignof_is_defined);
-
-int
-main (void)
-{
- if (strcmp (s1, "_Alignas") != 0)
- abort ();
- if (strcmp (s2, "_Alignof") != 0)
- abort ();
- if (strcmp (s3, "1") != 0)
- abort ();
- if (strcmp (s4, "1") != 0)
- abort ();
-}
diff --git a/gcc/testsuite/gcc.dg/c1x-align-3.c b/gcc/testsuite/gcc.dg/c1x-align-3.c
deleted file mode 100644
index b97351cdeaf..00000000000
--- a/gcc/testsuite/gcc.dg/c1x-align-3.c
+++ /dev/null
@@ -1,43 +0,0 @@
-/* Test C1X alignment support. Test invalid code. */
-/* { dg-do compile } */
-/* { dg-options "-std=c1x -pedantic-errors" } */
-
-int a = _Alignof (void (void)); /* { dg-error "function" } */
-struct s;
-int b = _Alignof (struct s); /* { dg-error "incomplete" } */
-int c = _Alignof (void); /* { dg-error "void" } */
-int d = _Alignof (a); /* { dg-error "expression" } */
-
-_Alignas (void (void)) char e; /* { dg-error "function" } */
-_Alignas (struct s) char f; /* { dg-error "incomplete" } */
-_Alignas (void) char g; /* { dg-error "void" } */
-
-_Alignas (-__INT_MAX__-1) char h; /* { dg-error "too large|power of 2" } */
-_Alignas (-__INT_MAX__) char h2; /* { dg-error "too large|power of 2" } */
-_Alignas ((-__INT_MAX__-1)/2) char h3; /* { dg-error "too large|power of 2" } */
-_Alignas ((-__INT_MAX__-1)/4) char h4; /* { dg-error "too large|power of 2" } */
-_Alignas ((-__INT_MAX__-1)/8) char h5; /* { dg-error "too large|power of 2" } */
-_Alignas (-__LONG_LONG_MAX__-1) char i; /* { dg-error "too large|power of 2" } */
-_Alignas (-(__LONG_LONG_MAX__-1)/2) char i2; /* { dg-error "too large|power of 2" } */
-_Alignas (-(__LONG_LONG_MAX__-1)/4) char i3; /* { dg-error "too large|power of 2" } */
-_Alignas (-(__LONG_LONG_MAX__-1)/8) char i4; /* { dg-error "too large|power of 2" } */
-_Alignas (-(__LONG_LONG_MAX__-1)/16) char i5; /* { dg-error "too large|power of 2" } */
-_Alignas (-1) char j; /* { dg-error "power of 2" } */
-_Alignas (-2) char j; /* { dg-error "positive power of 2" } */
-_Alignas (3) char k; /* { dg-error "power of 2" } */
-
-_Alignas ((void *) 1) char k; /* { dg-error "integer constant" } */
-int x;
-_Alignas (x) char l; /* { dg-error "integer constant" } */
-
-_Alignas (0) struct s; /* { dg-error "does not redeclare tag" } */
-
-_Alignas (0) typedef int T; /* { dg-error "alignment specified for typedef" } */
-void func (_Alignas (0) int); /* { dg-error "alignment specified for unnamed parameter" } */
-void f2 (_Alignas (0) int parm2) {} /* { dg-error "alignment specified for parameter" } */
-void
-f3 (void)
-{
- register _Alignas (0) int reg; /* { dg-error "register" } */
-}
-_Alignas (0) void f4 (void); /* { dg-error "alignment specified for function" } */
diff --git a/gcc/testsuite/gcc.dg/c1x-align-4.c b/gcc/testsuite/gcc.dg/c1x-align-4.c
deleted file mode 100644
index cc13f93d9c0..00000000000
--- a/gcc/testsuite/gcc.dg/c1x-align-4.c
+++ /dev/null
@@ -1,9 +0,0 @@
-/* Test C1X alignment support. Test reducing alignment (assumes there
- are at least some alignment constraints). */
-/* { dg-do compile } */
-/* { dg-options "-std=c1x -pedantic-errors" } */
-/* { dg-skip-if "no alignment constraints" { "avr-*-*" } { "*" } { "" } } */
-
-#include <stddef.h>
-
-_Alignas (_Alignof (char)) max_align_t x; /* { dg-error "reduce alignment" } */
diff --git a/gcc/testsuite/gcc.dg/c1x-anon-struct-1.c b/gcc/testsuite/gcc.dg/c1x-anon-struct-1.c
deleted file mode 100644
index 6d4b433d733..00000000000
--- a/gcc/testsuite/gcc.dg/c1x-anon-struct-1.c
+++ /dev/null
@@ -1,72 +0,0 @@
-/* Test for anonymous structures and unions in C1X. */
-/* { dg-do compile } */
-/* { dg-options "-std=c1x -pedantic-errors" } */
-
-#include <stddef.h>
-
-struct s1
-{
- int a;
- union
- {
- int i;
- };
- struct
- {
- int b;
- };
-};
-
-union u1
-{
- int b;
- struct
- {
- int i;
- };
- union
- {
- int c;
- };
-};
-
-struct s2
-{
- struct
- {
- int a;
- };
-};
-
-struct s3
-{
- union
- {
- int i;
- };
-};
-
-struct s4
-{
- struct
- {
- int i;
- };
- int a[];
-};
-
-struct s1 x =
- {
- .b = 1,
- .i = 2,
- .a = 3
- };
-
-int o = offsetof (struct s1, i);
-
-void
-f (void)
-{
- x.i = 3;
- (&x)->i = 4;
-}
diff --git a/gcc/testsuite/gcc.dg/c1x-anon-struct-2.c b/gcc/testsuite/gcc.dg/c1x-anon-struct-2.c
deleted file mode 100644
index cb8043117d5..00000000000
--- a/gcc/testsuite/gcc.dg/c1x-anon-struct-2.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/* Test for anonymous structures and unions in C1X. Test for invalid
- cases. */
-/* { dg-do compile } */
-/* { dg-options "-std=c1x -pedantic-errors" } */
-
-typedef struct s0
-{
- int i;
-} s0;
-
-struct s1
-{
- int a;
- struct s0; /* { dg-error "declaration does not declare anything" } */
-};
-
-struct s2
-{
- int a;
- s0; /* { dg-error "declaration does not declare anything" } */
-};
-
-struct s3
-{
- struct
- {
- int i;
- };
- struct
- {
- int i; /* { dg-error "duplicate member" } */
- };
-};
-
-struct s4
-{
- int a;
- struct s
- {
- int i;
- }; /* { dg-error "declaration does not declare anything" } */
-};
-
-struct s5
-{
- struct
- {
- int i;
- } a;
- int b;
-} x;
-
-void
-f (void)
-{
- x.i = 0; /* { dg-error "has no member" } */
-}
diff --git a/gcc/testsuite/gcc.dg/c1x-anon-struct-3.c b/gcc/testsuite/gcc.dg/c1x-anon-struct-3.c
deleted file mode 100644
index 1841eddd0a1..00000000000
--- a/gcc/testsuite/gcc.dg/c1x-anon-struct-3.c
+++ /dev/null
@@ -1,34 +0,0 @@
-/* Test for anonymous structures and unions in C1X. Test for invalid
- cases: typedefs disallowed by N1549. */
-/* { dg-do compile } */
-/* { dg-options "-std=c1x -pedantic-errors" } */
-
-typedef struct
-{
- int i;
-} s0;
-
-typedef union
-{
- int i;
-} u0;
-
-struct s1
-{
- int a;
- u0; /* { dg-error "declaration does not declare anything" } */
- struct
- {
- int b;
- };
-};
-
-union u1
-{
- int b;
- s0; /* { dg-error "declaration does not declare anything" } */
- union
- {
- int c;
- };
-};
diff --git a/gcc/testsuite/gcc.dg/c1x-float-1.c b/gcc/testsuite/gcc.dg/c1x-float-1.c
deleted file mode 100644
index 75233ac8227..00000000000
--- a/gcc/testsuite/gcc.dg/c1x-float-1.c
+++ /dev/null
@@ -1,169 +0,0 @@
-/* Test for <float.h> C1X macros. */
-/* Origin: Joseph Myers <joseph@codesourcery.com> */
-/* { dg-do preprocess } */
-/* { dg-options "-std=c1x -pedantic-errors" } */
-
-/* This test checks that the C1X macros are defined;
- it does not check the correctness of their values. */
-
-#include <float.h>
-
-#ifndef FLT_ROUNDS
-#error "FLT_ROUNDS undefined"
-#endif
-
-#ifndef FLT_RADIX
-#error "FLT_RADIX undefined"
-#endif
-
-#ifndef FLT_MANT_DIG
-#error "FLT_MANT_DIG undefined"
-#endif
-
-#ifndef FLT_DIG
-#error "FLT_DIG undefined"
-#endif
-
-#ifndef FLT_MIN_EXP
-#error "FLT_MIN_EXP undefined"
-#endif
-
-#ifndef FLT_MIN_10_EXP
-#error "FLT_MIN_10_EXP undefined"
-#endif
-
-#ifndef FLT_MAX_EXP
-#error "FLT_MAX_EXP undefined"
-#endif
-
-#ifndef FLT_MAX_10_EXP
-#error "FLT_MAX_10_EXP undefined"
-#endif
-
-#ifndef FLT_MAX
-#error "FLT_MAX undefined"
-#endif
-
-#ifndef FLT_EPSILON
-#error "FLT_EPSILON undefined"
-#endif
-
-#ifndef FLT_MIN
-#error "FLT_MIN undefined"
-#endif
-
-#ifndef DBL_MANT_DIG
-#error "DBL_MANT_DIG undefined"
-#endif
-
-#ifndef DBL_DIG
-#error "DBL_DIG undefined"
-#endif
-
-#ifndef DBL_MIN_EXP
-#error "DBL_MIN_EXP undefined"
-#endif
-
-#ifndef DBL_MIN_10_EXP
-#error "DBL_MIN_10_EXP undefined"
-#endif
-
-#ifndef DBL_MAX_EXP
-#error "DBL_MAX_EXP undefined"
-#endif
-
-#ifndef DBL_MAX_10_EXP
-#error "DBL_MAX_10_EXP undefined"
-#endif
-
-#ifndef DBL_MAX
-#error "DBL_MAX undefined"
-#endif
-
-#ifndef DBL_EPSILON
-#error "DBL_EPSILON undefined"
-#endif
-
-#ifndef DBL_MIN
-#error "DBL_MIN undefined"
-#endif
-
-#ifndef LDBL_MANT_DIG
-#error "LDBL_MANT_DIG undefined"
-#endif
-
-#ifndef LDBL_DIG
-#error "LDBL_DIG undefined"
-#endif
-
-#ifndef LDBL_MIN_EXP
-#error "LDBL_MIN_EXP undefined"
-#endif
-
-#ifndef LDBL_MIN_10_EXP
-#error "LDBL_MIN_10_EXP undefined"
-#endif
-
-#ifndef LDBL_MAX_EXP
-#error "LDBL_MAX_EXP undefined"
-#endif
-
-#ifndef LDBL_MAX_10_EXP
-#error "LDBL_MAX_10_EXP undefined"
-#endif
-
-#ifndef LDBL_MAX
-#error "LDBL_MAX undefined"
-#endif
-
-#ifndef LDBL_EPSILON
-#error "LDBL_EPSILON undefined"
-#endif
-
-#ifndef LDBL_MIN
-#error "LDBL_MIN undefined"
-#endif
-
-#ifndef FLT_EVAL_METHOD
-#error "FLT_EVAL_METHOD undefined"
-#endif
-
-#ifndef DECIMAL_DIG
-#error "DECIMAL_DIG undefined"
-#endif
-
-#ifndef FLT_DECIMAL_DIG
-#error "FLT_DECIMAL_DIG undefined"
-#endif
-
-#ifndef DBL_DECIMAL_DIG
-#error "DBL_DECIMAL_DIG undefined"
-#endif
-
-#ifndef LDBL_DECIMAL_DIG
-#error "LDBL_DECIMAL_DIG undefined"
-#endif
-
-#ifndef FLT_HAS_SUBNORM
-#error "FLT_HAS_SUBNORM undefined"
-#endif
-
-#ifndef DBL_HAS_SUBNORM
-#error "DBL_HAS_SUBNORM undefined"
-#endif
-
-#ifndef LDBL_HAS_SUBNORM
-#error "LDBL_HAS_SUBNORM undefined"
-#endif
-
-#ifndef FLT_TRUE_MIN
-#error "FLT_TRUE_MIN undefined"
-#endif
-
-#ifndef DBL_TRUE_MIN
-#error "DBL_TRUE_MIN undefined"
-#endif
-
-#ifndef LDBL_TRUE_MIN
-#error "LDBL_TRUE_MIN undefined"
-#endif
diff --git a/gcc/testsuite/gcc.dg/c1x-noreturn-1.c b/gcc/testsuite/gcc.dg/c1x-noreturn-1.c
deleted file mode 100644
index d9c141d5326..00000000000
--- a/gcc/testsuite/gcc.dg/c1x-noreturn-1.c
+++ /dev/null
@@ -1,59 +0,0 @@
-/* Test C1X _Noreturn. Test valid code. */
-/* { dg-do compile } */
-/* { dg-options "-std=c1x -pedantic-errors" } */
-
-_Noreturn void exit (int);
-
-_Noreturn int f1 (void);
-
-_Noreturn void f2 (void);
-
-static void _Noreturn f3 (void) { exit (0); }
-
-/* Returning from a noreturn function is undefined at runtime, not a
- constraint violation, but recommended practice is to diagnose if
- such a return appears possible. */
-
-_Noreturn int
-f4 (void)
-{
- return 1; /* { dg-warning "has a 'return' statement" } */
- /* { dg-warning "does return" "second warning" { target *-*-* } 20 } */
-}
-
-_Noreturn void
-f5 (void)
-{
- return; /* { dg-warning "has a 'return' statement" } */
- /* { dg-warning "does return" "second warning" { target *-*-* } 27 } */
-}
-
-_Noreturn void
-f6 (void)
-{
-} /* { dg-warning "does return" } */
-
-_Noreturn void
-f7 (int a)
-{
- if (a)
- exit (0);
-} /* { dg-warning "does return" } */
-
-/* Declarations need not all have _Noreturn. */
-
-void f2 (void);
-
-void f8 (void);
-_Noreturn void f8 (void);
-
-/* Duplicate _Noreturn is OK. */
-_Noreturn _Noreturn void _Noreturn f9 (void);
-
-/* _Noreturn does not affect type compatibility. */
-
-void (*fp) (void) = f5;
-
-/* noreturn is an ordinary identifier. */
-
-int noreturn;
diff --git a/gcc/testsuite/gcc.dg/c1x-noreturn-2.c b/gcc/testsuite/gcc.dg/c1x-noreturn-2.c
deleted file mode 100644
index 81972f1e8be..00000000000
--- a/gcc/testsuite/gcc.dg/c1x-noreturn-2.c
+++ /dev/null
@@ -1,77 +0,0 @@
-/* Test C1X _Noreturn. Test valid code using stdnoreturn.h. */
-/* { dg-do run } */
-/* { dg-options "-std=c1x -pedantic-errors" } */
-
-#include <stdnoreturn.h>
-
-extern int strcmp (const char *, const char *);
-
-noreturn void exit (int);
-noreturn void abort (void);
-
-noreturn int f1 (void);
-
-noreturn void f2 (void);
-
-static void noreturn f3 (void) { exit (0); }
-
-/* Returning from a noreturn function is undefined at runtime, not a
- constraint violation, but recommended practice is to diagnose if
- such a return appears possible. */
-
-noreturn int
-f4 (void)
-{
- return 1; /* { dg-warning "has a 'return' statement" } */
- /* { dg-warning "does return" "second warning" { target *-*-* } 25 } */
-}
-
-noreturn void
-f5 (void)
-{
- return; /* { dg-warning "has a 'return' statement" } */
- /* { dg-warning "does return" "second warning" { target *-*-* } 32 } */
-}
-
-noreturn void
-f6 (void)
-{
-} /* { dg-warning "does return" } */
-
-noreturn void
-f7 (int a)
-{
- if (a)
- exit (0);
-} /* { dg-warning "does return" } */
-
-/* Declarations need not all have noreturn. */
-
-void f2 (void);
-
-void f8 (void);
-noreturn void f8 (void);
-
-/* Duplicate noreturn is OK. */
-noreturn noreturn void noreturn f9 (void);
-
-/* noreturn does not affect type compatibility. */
-
-void (*fp) (void) = f5;
-
-#ifndef noreturn
-#error "noreturn not defined"
-#endif
-
-#define str(x) #x
-#define xstr(x) str(x)
-
-const char *s = xstr(noreturn);
-
-int
-main (void)
-{
- if (strcmp (s, "_Noreturn") != 0)
- abort ();
- exit (0);
-}
diff --git a/gcc/testsuite/gcc.dg/c1x-noreturn-3.c b/gcc/testsuite/gcc.dg/c1x-noreturn-3.c
deleted file mode 100644
index b12c23efafc..00000000000
--- a/gcc/testsuite/gcc.dg/c1x-noreturn-3.c
+++ /dev/null
@@ -1,11 +0,0 @@
-/* Test C1X _Noreturn. Test _Noreturn on main, hosted. */
-/* { dg-do compile } */
-/* { dg-options "-std=c1x -pedantic-errors -fhosted" } */
-
-_Noreturn void exit (int);
-
-_Noreturn int
-main (void) /* { dg-error "'main' declared '_Noreturn'" } */
-{
- exit (0);
-}
diff --git a/gcc/testsuite/gcc.dg/c1x-noreturn-4.c b/gcc/testsuite/gcc.dg/c1x-noreturn-4.c
deleted file mode 100644
index 72dceafba19..00000000000
--- a/gcc/testsuite/gcc.dg/c1x-noreturn-4.c
+++ /dev/null
@@ -1,11 +0,0 @@
-/* Test C1X _Noreturn. Test _Noreturn on main, freestanding. */
-/* { dg-do compile } */
-/* { dg-options "-std=c1x -pedantic-errors -ffreestanding" } */
-
-_Noreturn void exit (int);
-
-_Noreturn int
-main (void)
-{
- exit (0);
-}
diff --git a/gcc/testsuite/gcc.dg/c1x-noreturn-5.c b/gcc/testsuite/gcc.dg/c1x-noreturn-5.c
deleted file mode 100644
index 73f22165cb0..00000000000
--- a/gcc/testsuite/gcc.dg/c1x-noreturn-5.c
+++ /dev/null
@@ -1,17 +0,0 @@
-/* Test C1X _Noreturn. Test invalid uses. */
-/* { dg-do compile } */
-/* { dg-options "-std=c1x -pedantic-errors" } */
-
-_Noreturn struct s; /* { dg-error "empty declaration" } */
-
-typedef _Noreturn void f (void); /* { dg-error "typedef" } */
-
-void g (_Noreturn void fp (void)); /* { dg-error "parameter" } */
-
-_Noreturn void (*p) (void); /* { dg-error "variable" } */
-
-struct t { int a; _Noreturn void (*f) (void); }; /* { dg-error "expected" } */
-
-int *_Noreturn *q; /* { dg-error "expected" } */
-
-int i = sizeof (_Noreturn int (*) (void)); /* { dg-error "expected" } */
diff --git a/gcc/testsuite/gcc.dg/c1x-pointer-float-1.c b/gcc/testsuite/gcc.dg/c1x-pointer-float-1.c
deleted file mode 100644
index 57c5be88736..00000000000
--- a/gcc/testsuite/gcc.dg/c1x-pointer-float-1.c
+++ /dev/null
@@ -1,28 +0,0 @@
-/* Test C1X constraint against pointer / floating-point casts. */
-/* { dg-do compile } */
-/* { dg-options "-std=c1x -pedantic-errors" } */
-
-void *p;
-float f;
-double d;
-long double ld;
-_Complex float cf;
-_Complex double cd;
-_Complex long double cld;
-
-void
-func (void)
-{
- f = (float) p; /* { dg-error "pointer" } */
- d = (double) p; /* { dg-error "pointer" } */
- ld = (long double) p; /* { dg-error "pointer" } */
- cf = (_Complex float) p; /* { dg-error "pointer" } */
- cd = (_Complex double) p; /* { dg-error "pointer" } */
- cld = (_Complex long double) p; /* { dg-error "pointer" } */
- p = (void *) f; /* { dg-error "pointer" } */
- p = (void *) d; /* { dg-error "pointer" } */
- p = (void *) ld; /* { dg-error "pointer" } */
- p = (void *) cf; /* { dg-error "pointer" } */
- p = (void *) cd; /* { dg-error "pointer" } */
- p = (void *) cld; /* { dg-error "pointer" } */
-}
diff --git a/gcc/testsuite/gcc.dg/c1x-static-assert-1.c b/gcc/testsuite/gcc.dg/c1x-static-assert-1.c
deleted file mode 100644
index bf7aa594511..00000000000
--- a/gcc/testsuite/gcc.dg/c1x-static-assert-1.c
+++ /dev/null
@@ -1,41 +0,0 @@
-/* Test C1X static assertions. Valid assertions. */
-/* { dg-do compile } */
-/* { dg-options "-std=c1x -pedantic-errors" } */
-
-_Static_assert (1, "foo");
-
-enum e { E0, E1 };
-
-_Static_assert (E1, L"bar");
-
-_Static_assert (-1, "foo" L"bar");
-
-struct s
-{
- int a;
- _Static_assert (3, "s");
- int b;
-};
-
-union u
-{
- int i;
- _Static_assert ((int)1.0, L"");
-};
-
-void
-f (void)
-{
- int i;
- i = 1;
- _Static_assert (0 + 1, "f");
- i = 2;
-}
-
-void
-g (void)
-{
- int i = 0;
- for (_Static_assert (1, ""); i < 10; i++)
- ;
-}
diff --git a/gcc/testsuite/gcc.dg/c1x-static-assert-2.c b/gcc/testsuite/gcc.dg/c1x-static-assert-2.c
deleted file mode 100644
index 9a48ca7e861..00000000000
--- a/gcc/testsuite/gcc.dg/c1x-static-assert-2.c
+++ /dev/null
@@ -1,41 +0,0 @@
-/* Test C1X static assertions. Failed assertions. */
-/* { dg-do compile } */
-/* { dg-options "-std=c1x -pedantic-errors" } */
-
-_Static_assert (0, "assert1"); /* { dg-error "static assertion failed: \"assert1\"" } */
-
-enum e { E0, E1 };
-
-_Static_assert (E0, L"assert2"); /* { dg-error "static assertion failed: \"assert2\"" } */
-
-_Static_assert (-0, "ass" L"ert3"); /* { dg-error "static assertion failed: \"assert3\"" } */
-
-struct s
-{
- int a;
- _Static_assert (0, "assert4"); /* { dg-error "static assertion failed: \"assert4\"" } */
- int b;
-};
-
-union u
-{
- int i;
- _Static_assert ((int)0.0, L"assert5"); /* { dg-error "static assertion failed: \"assert5\"" } */
-};
-
-void
-f (void)
-{
- int i;
- i = 1;
- _Static_assert (0 + 0, "assert6"); /* { dg-error "static assertion failed: \"assert6\"" } */
- i = 2;
-}
-
-void
-g (void)
-{
- int i = 0;
- for (_Static_assert (0, "assert7"); i < 10; i++) /* { dg-error "static assertion failed: \"assert7\"" } */
- ;
-}
diff --git a/gcc/testsuite/gcc.dg/c1x-static-assert-3.c b/gcc/testsuite/gcc.dg/c1x-static-assert-3.c
deleted file mode 100644
index 81b504e2ab1..00000000000
--- a/gcc/testsuite/gcc.dg/c1x-static-assert-3.c
+++ /dev/null
@@ -1,28 +0,0 @@
-/* Test C1X static assertions. Invalid assertions. */
-/* { dg-do compile } */
-/* { dg-options "-std=c1x -pedantic-errors" } */
-
-_Static_assert (__INT_MAX__ * 2, "overflow"); /* { dg-warning "integer overflow in expression" } */
-/* { dg-error "overflow in constant expression" "error" { target *-*-* } 5 } */
-
-_Static_assert ((void *)(__SIZE_TYPE__)16, "non-integer"); /* { dg-error "not an integer" } */
-
-_Static_assert (1.0, "non-integer"); /* { dg-error "not an integer" } */
-
-_Static_assert ((int)(1.0 + 1.0), "non-constant-expression"); /* { dg-error "not an integer constant expression" } */
-
-int i;
-
-_Static_assert (i, "non-constant"); /* { dg-error "not constant" } */
-
-void
-f (void)
-{
- int j = 0;
- for (_Static_assert (sizeof (struct s { int k; }), ""); j < 10; j++) /* { dg-error "loop initial declaration" } */
- ;
-}
-
-_Static_assert (1, 1); /* { dg-error "expected" } */
-
-_Static_assert (1, ("")); /* { dg-error "expected" } */
diff --git a/gcc/testsuite/gcc.dg/c1x-static-assert-4.c b/gcc/testsuite/gcc.dg/c1x-static-assert-4.c
deleted file mode 100644
index ebc95f5f906..00000000000
--- a/gcc/testsuite/gcc.dg/c1x-static-assert-4.c
+++ /dev/null
@@ -1,13 +0,0 @@
-/* Test C1X static assertions. More invalid assertions. */
-/* { dg-do compile } */
-/* { dg-options "-std=c1x -pedantic-errors" } */
-
-/* Static assertions not valid in old-style parameter declarations
- because declarations there must have declarators. */
-
-void
-f (i)
- int i;
- _Static_assert (1, ""); /* { dg-error "expected" } */
-{
-}
diff --git a/gcc/testsuite/gcc.dg/c1x-static-assert-5.c b/gcc/testsuite/gcc.dg/c1x-static-assert-5.c
deleted file mode 100644
index d4d0821f0e3..00000000000
--- a/gcc/testsuite/gcc.dg/c1x-static-assert-5.c
+++ /dev/null
@@ -1,5 +0,0 @@
-/* Test C1X static assertions. Non-constant-expression without -pedantic. */
-/* { dg-do compile } */
-/* { dg-options "-std=c1x" } */
-
-_Static_assert ((int)(1.0 + 1.0), "non-constant-expression");
diff --git a/gcc/testsuite/gcc.dg/c1x-static-assert-6.c b/gcc/testsuite/gcc.dg/c1x-static-assert-6.c
deleted file mode 100644
index c544cadc268..00000000000
--- a/gcc/testsuite/gcc.dg/c1x-static-assert-6.c
+++ /dev/null
@@ -1,5 +0,0 @@
-/* Test C1X static assertions. Non-constant-expression with -pedantic. */
-/* { dg-do compile } */
-/* { dg-options "-std=c1x -pedantic" } */
-
-_Static_assert ((int)(1.0 + 1.0), "non-constant-expression"); /* { dg-warning "not an integer constant expression" } */
diff --git a/gcc/testsuite/gcc.dg/c1x-typedef-1.c b/gcc/testsuite/gcc.dg/c1x-typedef-1.c
deleted file mode 100644
index a68b23ff5e6..00000000000
--- a/gcc/testsuite/gcc.dg/c1x-typedef-1.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/* Test typedef redeclaration in C1X. */
-/* { dg-do compile } */
-/* { dg-options "-std=c1x -pedantic-errors" } */
-
-/* C1X permits typedefs to be redeclared to the same type, but not to
- different-but-compatible types, and not when the type is variably
- modified. */
-
-#include <limits.h>
-
-typedef int TI;
-typedef int TI2;
-typedef TI2 TI;
-typedef TI TI2;
-
-enum e { E1 = 0, E2 = INT_MAX, E3 = -1 };
-typedef enum e TE;
-typedef enum e TE; /* { dg-message "previous declaration" } */
-typedef int TE; /* { dg-error "with different type" } */
-
-struct s;
-typedef struct s TS;
-struct s { int i; };
-typedef struct s TS;
-
-typedef int IA[];
-typedef TI2 IA[]; /* { dg-message "previous declaration" } */
-typedef int A2[2];
-typedef TI A2[2]; /* { dg-message "previous declaration" } */
-typedef IA A2; /* { dg-error "with different type" } */
-typedef int A3[3];
-typedef A3 IA; /* { dg-error "with different type" } */
-
-typedef void F(int);
-typedef void F(TI); /* { dg-message "previous declaration" } */
-typedef void F(enum e); /* { dg-error "with different type" } */
-
-typedef int G(void);
-typedef TI G(void); /* { dg-message "previous declaration" } */
-typedef enum e G(void); /* { dg-error "with different type" } */
-
-typedef int *P;
-typedef TI *P; /* { dg-message "previous declaration" } */
-typedef enum e *P; /* { dg-error "with different type" } */
-
-typedef void F2();
-typedef void F2(); /* { dg-message "previous declaration" } */
-typedef void F2(int); /* { dg-error "with different type" } */
-
-void
-f (void)
-{
- int a = 1;
- int b = 2;
- typedef void FN(int (*p)[a]);
- typedef void FN(int (*p)[b]);
- typedef void FN(int (*p)[*]); /* { dg-message "previous declaration" } */
- typedef void FN(int (*p)[1]); /* { dg-error "with different type" } */
- typedef void FN2(int (*p)[a]);
- typedef void FN2(int (*p)[b]);
- typedef void FN2(int (*p)[*]); /* { dg-message "previous declaration" } */
- typedef void FN2(int (*p)[]); /* { dg-error "with different type" } */
- typedef int AV[a]; /* { dg-message "previous declaration" } */
- typedef int AV[b-1]; /* { dg-error "redefinition" } */
- typedef int AAa[a]; /* { dg-message "previous declaration" } */
- typedef int AAb[b-1];
- typedef AAa *VF(void); /* { dg-message "previous declaration" } */
- typedef AAb *VF(void); /* { dg-error "redefinition" } */
- typedef AAa AAa; /* { dg-error "redefinition" } */
-}
diff --git a/gcc/testsuite/gcc.dg/c1x-uni-string-1.c b/gcc/testsuite/gcc.dg/c1x-uni-string-1.c
deleted file mode 100644
index 30a98c1d669..00000000000
--- a/gcc/testsuite/gcc.dg/c1x-uni-string-1.c
+++ /dev/null
@@ -1,112 +0,0 @@
-/* Test Unicode strings in C1X. Test valid code. */
-/* { dg-do run } */
-/* { dg-options "-std=c1x -pedantic-errors" } */
-
-/* More thorough tests are in c-c++-common/raw-string-*.c; this test
- verifies the particular subset (Unicode but not raw strings) that
- is in C1X. */
-
-typedef __CHAR16_TYPE__ char16_t;
-typedef __CHAR32_TYPE__ char32_t;
-typedef __SIZE_TYPE__ size_t;
-
-extern void abort (void);
-extern void exit (int);
-extern int memcmp (const void *, const void *, size_t);
-
-#define R "(R)"
-#define u8R "(u8R)"
-#define uR "(uR)"
-#define UR "(UR)"
-#define LR "(LR)"
-#define u8 randomu8
-#define u randomu
-#define U randomU
-
-const char su8[] = u8"a\u010d";
-const char su8a[] = "a\xc4\x8d";
-
-const char16_t su16[] = u"\u0567";
-const char16_t su16a[] = { 0x0567, 0 };
-
-const char32_t su32[] = U"\u0123";
-const char32_t su32a[] = { 0x0123, 0 };
-
-const char tu[] = R"a";
-const char tua[] = "(R)a";
-
-const char tu8[] = u8R"b";
-const char tu8a[] = "(u8R)b";
-
-const char tu16[] = uR"c";
-const char tu16a[] = "(uR)c";
-
-const char tu32[] = UR"d";
-const char tu32a[] = "(UR)d";
-
-const char tl[] = LR"e";
-const char tla[] = "(LR)e";
-
-#define str(x) #x
-const char ts[] = str(u"a" U"b" u8"c");
-const char tsa[] = "u\"a\" U\"b\" u8\"c\"";
-
-/* GCC always uses UTF-16 and UTF-32 for char16_t and char32_t. */
-#ifndef __STDC_UTF_16__
-#error "__STDC_UTF_16__ not defined"
-#endif
-#ifndef __STDC_UTF_32__
-#error "__STDC_UTF_32__ not defined"
-#endif
-#define xstr(x) str(x)
-const char tm16[] = xstr(__STDC_UTF_16__);
-const char tm16a[] = "1";
-const char tm32[] = xstr(__STDC_UTF_32__);
-const char tm32a[] = "1";
-
-int
-main (void)
-{
- if (sizeof (su8) != sizeof (su8a)
- || memcmp (su8, su8a, sizeof (su8)) != 0)
- abort ();
- if (sizeof (su16) != sizeof (su16a)
- || memcmp (su16, su16a, sizeof (su16)) != 0)
- abort ();
- if (sizeof (su32) != sizeof (su32a)
- || memcmp (su32, su32a, sizeof (su32)) != 0)
- abort ();
- if (sizeof (tu) != sizeof (tua)
- || memcmp (tu, tua, sizeof (tu)) != 0)
- abort ();
- if (sizeof (tu8) != sizeof (tu8a)
- || memcmp (tu8, tu8a, sizeof (tu8)) != 0)
- abort ();
- if (sizeof (tu16) != sizeof (tu16a)
- || memcmp (tu16, tu16a, sizeof (tu16)) != 0)
- abort ();
- if (sizeof (tu32) != sizeof (tu32a)
- || memcmp (tu32, tu32a, sizeof (tu32)) != 0)
- abort ();
- if (sizeof (tl) != sizeof (tla)
- || memcmp (tl, tla, sizeof (tl)) != 0)
- abort ();
- if (sizeof (ts) != sizeof (tsa)
- || memcmp (ts, tsa, sizeof (ts)) != 0)
- abort ();
- if (sizeof (tm16) != sizeof (tm16a)
- || memcmp (tm16, tm16a, sizeof (tm16)) != 0)
- abort ();
- if (sizeof (tm32) != sizeof (tm32a)
- || memcmp (tm32, tm32a, sizeof (tm32)) != 0)
- abort ();
- if (u'\u0123' != 0x0123)
- abort ();
- if (U'\u0456' != 0x0456)
- abort ();
-#undef u8
-#define u8
- if (u8'a' != 'a')
- abort ();
- exit (0);
-}
diff --git a/gcc/testsuite/gcc.dg/c1x-uni-string-2.c b/gcc/testsuite/gcc.dg/c1x-uni-string-2.c
deleted file mode 100644
index 698b0c1df39..00000000000
--- a/gcc/testsuite/gcc.dg/c1x-uni-string-2.c
+++ /dev/null
@@ -1,8 +0,0 @@
-/* Test Unicode strings in C1X. Test constraint. */
-/* { dg-do compile } */
-/* { dg-options "-std=c1x -pedantic-errors" } */
-
-const void *p1 = L"a" u8"b"; /* { dg-error "concatenation" } */
-const void *p2 = L"a" "b" u8"c"; /* { dg-error "concatenation" } */
-const void *p3 = u8"a" L"b"; /* { dg-error "concatenation" } */
-const void *p4 = u8"a" "b" L"c"; /* { dg-error "concatenation" } */
diff --git a/gcc/testsuite/gcc.dg/c90-atomic-1.c b/gcc/testsuite/gcc.dg/c90-atomic-1.c
new file mode 100644
index 00000000000..3506563940d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c90-atomic-1.c
@@ -0,0 +1,7 @@
+/* Test for _Atomic: not in C90. */
+/* { dg-do compile } */
+/* { dg-options "-std=c90 -pedantic-errors" } */
+
+_Atomic int i; /* { dg-error "_Atomic" } */
+_Atomic (int) j; /* { dg-error "_Atomic" } */
+int *_Atomic p; /* { dg-error "_Atomic" } */
diff --git a/gcc/testsuite/gcc.dg/c90-float-1.c b/gcc/testsuite/gcc.dg/c90-float-1.c
index 5a2cab657a3..649cddfa071 100644
--- a/gcc/testsuite/gcc.dg/c90-float-1.c
+++ b/gcc/testsuite/gcc.dg/c90-float-1.c
@@ -3,7 +3,7 @@
/* { dg-do preprocess } */
/* { dg-options "-std=iso9899:1990 -pedantic-errors" } */
-/* This test checks that the C90 macros (but not the C99 or C1X ones)
+/* This test checks that the C90 macros (but not the C99 or C11 ones)
are defined; it does not check the correctness of their values. */
#include <float.h>
diff --git a/gcc/testsuite/gcc.dg/c99-atomic-1.c b/gcc/testsuite/gcc.dg/c99-atomic-1.c
new file mode 100644
index 00000000000..3a13f777122
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c99-atomic-1.c
@@ -0,0 +1,8 @@
+/* Test for _Atomic: not in C99. */
+/* { dg-do compile } */
+/* { dg-options "-std=c99 -pedantic-errors" } */
+
+_Atomic int i; /* { dg-error "_Atomic" } */
+_Atomic (int) j; /* { dg-error "_Atomic" } */
+int *_Atomic p; /* { dg-error "_Atomic" } */
+void f (int a[_Atomic]); /* { dg-error "_Atomic" } */
diff --git a/gcc/testsuite/gcc.dg/c99-float-1.c b/gcc/testsuite/gcc.dg/c99-float-1.c
index f0dc39136e9..7ee87a564a4 100644
--- a/gcc/testsuite/gcc.dg/c99-float-1.c
+++ b/gcc/testsuite/gcc.dg/c99-float-1.c
@@ -3,7 +3,7 @@
/* { dg-do preprocess } */
/* { dg-options "-std=iso9899:1999 -pedantic-errors" } */
-/* This test checks that the C99 macros (but not the C1X ones) are defined;
+/* This test checks that the C99 macros (but not the C11 ones) are defined;
it does not check the correctness of their values. */
#include <float.h>
diff --git a/gcc/testsuite/gcc.dg/c99-stdint-1.c b/gcc/testsuite/gcc.dg/c99-stdint-1.c
index 89bdec809f8..530d13025e7 100644
--- a/gcc/testsuite/gcc.dg/c99-stdint-1.c
+++ b/gcc/testsuite/gcc.dg/c99-stdint-1.c
@@ -9,6 +9,7 @@
version). */
/* { dg-do compile } */
/* { dg-options "-std=iso9899:1999 -pedantic-errors -fhosted" } */
+/* { dg-require-effective-target ptr32plus } */
#include <limits.h>
#include <stdint.h>
@@ -214,7 +215,6 @@ test_max (void)
void
test_misc_limits (void)
{
-/* { dg-bogus "size" "ptrdiff is 16bits" { xfail avr-*-* } 56 } */
CHECK_SIGNED_LIMITS_2(__PTRDIFF_TYPE__, PTRDIFF_MIN, PTRDIFF_MAX, -65535L, 65535L);
#ifndef SIGNAL_SUPPRESS
CHECK_LIMITS_2(sig_atomic_t, SIG_ATOMIC_MIN, SIG_ATOMIC_MAX, -127, 127, 255);
diff --git a/gcc/testsuite/gcc.dg/c99-stdint-2.c b/gcc/testsuite/gcc.dg/c99-stdint-2.c
index d1be0fb6332..1784b0c413e 100644
--- a/gcc/testsuite/gcc.dg/c99-stdint-2.c
+++ b/gcc/testsuite/gcc.dg/c99-stdint-2.c
@@ -2,7 +2,7 @@
Freestanding version. */
/* { dg-do compile } */
/* { dg-options "-std=iso9899:1999 -pedantic-errors -ffreestanding" } */
-/* { dg-xfail-if "ptrdiff size is 16bits" { avr-*-* } } */
+/* { dg-require-effective-target ptr32plus } */
/* The test is that there are no diagnostics, so just include the
hosted version. */
#include "c99-stdint-1.c"
diff --git a/gcc/testsuite/gcc.dg/cdce1.c b/gcc/testsuite/gcc.dg/cdce1.c
index 3bd35ecb786..2123f7fd8e9 100644
--- a/gcc/testsuite/gcc.dg/cdce1.c
+++ b/gcc/testsuite/gcc.dg/cdce1.c
@@ -1,6 +1,7 @@
/* { dg-do run } */
/* { dg-options "-O2 -fmath-errno -fdump-tree-cdce-details -lm" } */
-/* { dg-final { scan-tree-dump "cdce1.c:16: note: function call is shrink-wrapped into error conditions\." "cdce" } } */
+/* { dg-require-effective-target int32plus } */
+/* { dg-final { scan-tree-dump "cdce1.c:17: note: function call is shrink-wrapped into error conditions\." "cdce" } } */
/* { dg-final { cleanup-tree-dump "cdce" } } */
/* { dg-require-effective-target large_double } */
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/cilk-plus.exp b/gcc/testsuite/gcc.dg/cilk-plus/cilk-plus.exp
index 2533febc8ab..3a3cba80a70 100644
--- a/gcc/testsuite/gcc.dg/cilk-plus/cilk-plus.exp
+++ b/gcc/testsuite/gcc.dg/cilk-plus/cilk-plus.exp
@@ -23,27 +23,33 @@ if { ![check_effective_target_cilkplus] } {
return;
}
+verbose "$tool $libdir" 1
+set library_var [get_multilibs]
+# Pointing the ld_library_path to the Cilk Runtime library binaries.
+set ld_library_path "${library_var}/libcilkrts/.libs"
+
+set ALWAYS_CFLAGS ""
+lappend ALWAYS_CFLAGS "-L${library_var}/libcilkrts/.libs"
+
dg-init
dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -fcilkplus" " "
-dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -O0 -fcilkplus" " "
dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -O1 -fcilkplus" " "
-dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -O2 -ftree-vectorize -fcilkplus" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -O2 -fcilkplus" " "
dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -O3 -fcilkplus" " "
dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -g -fcilkplus" " "
-dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -g -O0 -fcilkplus" " "
-dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -g -O1 -fcilkplus" " "
dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -g -O2 -ftree-vectorize -fcilkplus" " "
-dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -g -O3 -fcilkplus" " "
-dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -O3 -ftree-vectorize -fcilkplus -g" " "
dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -fcilkplus -std=c99" " "
-dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -fcilkplus -O0 -std=c99" " "
-dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -fcilkplus -O1 -std=c99" " "
-dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -fcilkplus -O2 -ftree-vectorize -std=c99" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -fcilkplus -O2 -std=c99" " "
dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -fcilkplus -O3 -std=c99" " "
-dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -fcilkplus -g -std=c99" " "
dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -fcilkplus -g -O0 -std=c99" " "
-dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -fcilkplus -g -O1 -std=c99" " "
-dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -fcilkplus -g -O2 -ftree-vectorize -std=c99" " "
-dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -fcilkplus -g -O3 -std=c99" " "
-dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -O3 -ftree-vectorize -std=c99 -g -fcilkplus" " "
+
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -g -fcilkplus $ALWAYS_CFLAGS " " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -O1 -fcilkplus $ALWAYS_CFLAGS" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -O2 -std=c99 -fcilkplus $ALWAYS_CFLAGS" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -O2 -ftree-vectorize -fcilkplus $ALWAYS_CFLAGS" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -O3 -g -fcilkplus $ALWAYS_CFLAGS" " "
+dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -O3 -flto -g -fcilkplus $ALWAYS_CFLAGS" " "
+
+
+
dg-finish
diff --git a/gcc/testsuite/gcc.dg/dfp/pr35739.c b/gcc/testsuite/gcc.dg/dfp/pr35739.c
deleted file mode 100644
index 0fc9d478f5f..00000000000
--- a/gcc/testsuite/gcc.dg/dfp/pr35739.c
+++ /dev/null
@@ -1,16 +0,0 @@
-/* PR c/35739 */
-/* { dg-do compile { target *-*-linux* *-*-gnu* } } */
-/* { dg-options "-O -fpreprocessed -fmudflap" } */
-
-_Decimal128
-foo (int n, ...)
-{
- int i;
- _Decimal128 j = 0;
- __builtin_va_list ap;
- __builtin_va_start (ap, n);
- for (i = 0; i < n; i++)
- j += __builtin_va_arg (ap, _Decimal128);
- __builtin_va_end (ap);
- return j;
-}
diff --git a/gcc/testsuite/gcc.dg/fold-overflow-1.c b/gcc/testsuite/gcc.dg/fold-overflow-1.c
index 8fddc9fc0ee..4f45b35ee45 100644
--- a/gcc/testsuite/gcc.dg/fold-overflow-1.c
+++ b/gcc/testsuite/gcc.dg/fold-overflow-1.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-skip-if "consts are shorts, not longs" { "m32c-*-*" "avr-*-*" } { "*" } { "" } } */
+/* { dg-require-effective-target int32plus } */
/* { dg-skip-if "No Inf support" { spu-*-* } } */
/* { dg-options "-O -ftrapping-math" } */
diff --git a/gcc/testsuite/gcc.dg/ftrapv-1.c b/gcc/testsuite/gcc.dg/ftrapv-1.c
index 44eb176b50d..86bd802cf13 100644
--- a/gcc/testsuite/gcc.dg/ftrapv-1.c
+++ b/gcc/testsuite/gcc.dg/ftrapv-1.c
@@ -7,6 +7,7 @@
/* { dg-do run } */
/* { dg-options "-ftrapv" } */
+/* { dg-require-effective-target trapping } */
__attribute__((noinline)) int
mulv(int a, int b)
diff --git a/gcc/testsuite/gcc.dg/ftrapv-2.c b/gcc/testsuite/gcc.dg/ftrapv-2.c
index d79b86dde9c..7d765747c9c 100644
--- a/gcc/testsuite/gcc.dg/ftrapv-2.c
+++ b/gcc/testsuite/gcc.dg/ftrapv-2.c
@@ -8,6 +8,7 @@
/* { dg-do run } */
/* { dg-options "-ftrapv" } */
+/* { dg-require-effective-target trapping } */
extern void abort(void);
extern long labs(long);
diff --git a/gcc/testsuite/gcc.dg/gomp/appendix-a/a.35.1.c b/gcc/testsuite/gcc.dg/gomp/appendix-a/a.35.1.c
index 4196b2d1521..f2c4a672fe4 100644
--- a/gcc/testsuite/gcc.dg/gomp/appendix-a/a.35.1.c
+++ b/gcc/testsuite/gcc.dg/gomp/appendix-a/a.35.1.c
@@ -15,7 +15,7 @@ wrong1 (int n)
for (i = 0; i < n; i++)
{
/* incorrect nesting of loop regions */
-#pragma omp for /* { dg-warning "may not be closely nested" } */
+#pragma omp for /* { dg-error "may not be closely nested" } */
for (j = 0; j < n; j++)
work (i, j);
}
diff --git a/gcc/testsuite/gcc.dg/gomp/appendix-a/a.35.3.c b/gcc/testsuite/gcc.dg/gomp/appendix-a/a.35.3.c
index 31b2ddf0367..64005b3074b 100644
--- a/gcc/testsuite/gcc.dg/gomp/appendix-a/a.35.3.c
+++ b/gcc/testsuite/gcc.dg/gomp/appendix-a/a.35.3.c
@@ -12,7 +12,7 @@ wrong3 (int n)
for (i = 0; i < n; i++)
{
/* incorrect nesting of regions */
-#pragma omp single /* { dg-warning "may not be closely nested" } */
+#pragma omp single /* { dg-error "may not be closely nested" } */
work (i, 0);
}
}
diff --git a/gcc/testsuite/gcc.dg/gomp/appendix-a/a.35.4.c b/gcc/testsuite/gcc.dg/gomp/appendix-a/a.35.4.c
index d7579e6e735..5bb6b80b396 100644
--- a/gcc/testsuite/gcc.dg/gomp/appendix-a/a.35.4.c
+++ b/gcc/testsuite/gcc.dg/gomp/appendix-a/a.35.4.c
@@ -11,7 +11,7 @@ wrong4 (int n)
{
work (i, 0);
/* incorrect nesting of barrier region in a loop region */
-#pragma omp barrier /* { dg-warning "may not be closely nested" } */
+#pragma omp barrier /* { dg-error "may not be closely nested" } */
work (i, 1);
}
}
diff --git a/gcc/testsuite/gcc.dg/gomp/appendix-a/a.35.5.c b/gcc/testsuite/gcc.dg/gomp/appendix-a/a.35.5.c
index 7b53015571e..7b4aee1c06b 100644
--- a/gcc/testsuite/gcc.dg/gomp/appendix-a/a.35.5.c
+++ b/gcc/testsuite/gcc.dg/gomp/appendix-a/a.35.5.c
@@ -9,7 +9,7 @@ wrong5 (int n)
{
work (n, 0);
/* incorrect nesting of barrier region in a critical region */
-#pragma omp barrier
+#pragma omp barrier /* { dg-error "may not be closely nested" } */
work (n, 1);
}
}
diff --git a/gcc/testsuite/gcc.dg/gomp/appendix-a/a.35.6.c b/gcc/testsuite/gcc.dg/gomp/appendix-a/a.35.6.c
index ac850e5410a..d18188b1752 100644
--- a/gcc/testsuite/gcc.dg/gomp/appendix-a/a.35.6.c
+++ b/gcc/testsuite/gcc.dg/gomp/appendix-a/a.35.6.c
@@ -9,7 +9,7 @@ wrong6 (int n)
{
work (n, 0);
/* incorrect nesting of barrier region in a single region */
-#pragma omp barrier /* { dg-warning "may not be closely nested" } */
+#pragma omp barrier /* { dg-error "may not be closely nested" } */
work (n, 1);
}
}
diff --git a/gcc/testsuite/gcc.dg/gomp/block-3.c b/gcc/testsuite/gcc.dg/gomp/block-3.c
index c72b04c35d0..b4530e9d06c 100644
--- a/gcc/testsuite/gcc.dg/gomp/block-3.c
+++ b/gcc/testsuite/gcc.dg/gomp/block-3.c
@@ -35,9 +35,10 @@ void foo()
#pragma omp sections
{
- goto ok1;
- ok1:;
-
+ {
+ goto ok1;
+ ok1:;
+ }
#pragma omp section
for (i = 0; i < 10; ++i)
if (test(i))
diff --git a/gcc/testsuite/gcc.dg/gomp/clause-1.c b/gcc/testsuite/gcc.dg/gomp/clause-1.c
index ba189896c62..fc7d72b7cd2 100644
--- a/gcc/testsuite/gcc.dg/gomp/clause-1.c
+++ b/gcc/testsuite/gcc.dg/gomp/clause-1.c
@@ -11,7 +11,7 @@ int t;
void
foo (int x)
{
- char *p;
+ char *pp;
struct S { int i; int j; } s;
char a[32];
double d;
@@ -42,11 +42,11 @@ foo (int x)
;
#pragma omp p firstprivate (bar) /* { dg-error "is not a variable" } */
;
-#pragma omp p reduction (+:p) /* { dg-error "has invalid type for" } */
+#pragma omp p reduction (+:pp) /* { dg-error "user defined reduction not found for" } */
;
-#pragma omp p reduction (*:s) /* { dg-error "has invalid type for" } */
+#pragma omp p reduction (*:s) /* { dg-error "user defined reduction not found for" } */
;
-#pragma omp p reduction (-:a) /* { dg-error "has invalid type for" } */
+#pragma omp p reduction (-:a) /* { dg-error "user defined reduction not found for" } */
;
d = 0;
#pragma omp p reduction (*:d)
diff --git a/gcc/testsuite/gcc.dg/gomp/combined-1.c b/gcc/testsuite/gcc.dg/gomp/combined-1.c
index dfed647371f..7e23c3256cb 100644
--- a/gcc/testsuite/gcc.dg/gomp/combined-1.c
+++ b/gcc/testsuite/gcc.dg/gomp/combined-1.c
@@ -20,5 +20,5 @@ int foo (void)
}
}
-/* { dg-final { scan-tree-dump-times "GOMP_parallel_loop_runtime_start" 3 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "GOMP_parallel_loop_runtime" 3 "optimized" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/gomp/declare-simd-1.c b/gcc/testsuite/gcc.dg/gomp/declare-simd-1.c
new file mode 100644
index 00000000000..259e2c0ae92
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gomp/declare-simd-1.c
@@ -0,0 +1,100 @@
+/* Test parsing of #pragma omp declare simd */
+/* { dg-do compile } */
+
+#pragma omp declare simd uniform (a) aligned (b : 8 * sizeof (int)) \
+ linear (c : 4) simdlen (8) notinbranch
+#pragma omp declare simd uniform (c) aligned (b : 4 * sizeof (int)) linear (a \
+ : 4) simdlen (4) inbranch
+int f1 (int a, int *b, int c);
+
+#pragma omp declare simd uniform (a) aligned (b : 8 * sizeof (int)) linear (c : 4) simdlen (8)
+int f2 (int a, int *b, int c)
+{
+ return a + *b + c;
+}
+
+#pragma omp declare simd uniform (a) aligned (b : 8 * sizeof (long long)) linear (c : 4) simdlen (8)
+__extension__
+long long f3 (long long a, long long *b, long long c);
+
+int
+f4 (int x)
+{
+ #pragma omp declare simd simdlen (8) aligned (b : 8 * sizeof (int))
+ __extension__ __extension__ __extension__
+ extern int f5 (int a, int *b, int c);
+ {
+ x++;
+ #pragma omp declare simd simdlen (4) linear (c)
+ extern int f6 (int a, int *b, int c);
+ }
+ return x;
+}
+
+#pragma omp declare simd simdlen (16)
+int
+f7 (int x)
+{
+ #pragma omp declare simd simdlen (8) aligned (b : 8 * sizeof (int))
+ extern int f8 (int a, int *b, int c);
+ return x;
+}
+
+int
+f9 (int x)
+{
+ if (x)
+ #pragma omp declare simd simdlen (8) aligned (b : 8 * sizeof (int))
+ extern int f10 (int a, int *b, int c);
+ while (x < 10)
+ #pragma omp declare simd simdlen (8) aligned (b : 8 * sizeof (int))
+ extern int f11 (int a, int *b, int c);
+ return x;
+}
+
+#pragma omp declare simd uniform (a) aligned (b : 8 * sizeof (int)) linear (c : 4) simdlen (8)
+int f12 (int c; int *b; int a; int a, int *b, int c);
+
+#pragma omp declare simd uniform (a) aligned (b : 8 * sizeof (int)) linear (c : 4) simdlen (8)
+int
+f13 (int c; int *b; int a; int a, int *b, int c)
+{
+ return a + *b + c;
+}
+
+#pragma omp declare simd uniform (a) aligned (b : 8 * sizeof (int)) linear (c : 4) simdlen (8)
+int
+f14 (a, b, c)
+ int a, c;
+ int *b;
+{
+ return a + *b + c;
+}
+
+#pragma omp declare simd uniform (a) aligned (b : 8 * sizeof (int)) linear (c : 4) simdlen (8)
+int
+f15 (int a, int *b, int c)
+{
+ return a + *b + c;
+}
+
+#pragma omp declare simd uniform (d) aligned (e : 8 * sizeof (int)) linear (f : 4) simdlen (8)
+int f15 (int d, int *e, int f);
+
+#pragma omp declare simd aligned (g : sizeof (*g)) linear (h : 2 * sizeof (g[0]) + sizeof (h)) simdlen (4)
+int f16 (long *g, int h);
+
+#pragma omp declare simd aligned (h : sizeof (*h)) linear (g : 2 * sizeof (h[0]) + sizeof (g)) simdlen (4)
+int f17 (int g, long *h)
+{
+ return g + h[0];
+}
+
+#pragma omp declare simd aligned (i : sizeof (*i)) linear (j : 2 * sizeof (i[0]) + sizeof (j)) simdlen (4)
+int
+f18 (j, i)
+ long *i;
+ int j;
+{
+ return j + i[0];
+}
diff --git a/gcc/testsuite/gcc.dg/gomp/declare-simd-2.c b/gcc/testsuite/gcc.dg/gomp/declare-simd-2.c
new file mode 100644
index 00000000000..c0a42a2ef46
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gomp/declare-simd-2.c
@@ -0,0 +1,54 @@
+/* Test parsing of #pragma omp declare simd */
+/* { dg-do compile } */
+
+#pragma omp declare simd
+int a; /* { dg-error "not immediately followed by a function declaration or definition" } */
+
+#pragma omp declare simd
+int fn1 (int a), fn2 (int a); /* { dg-error "not immediately followed by a single function declaration or definition" } */
+
+#pragma omp declare simd
+int b, fn3 (int a); /* { dg-error "not immediately followed by a function declaration or definition" } */
+
+#pragma omp declare simd linear (a)
+int fn4 (int a), c; /* { dg-error "not immediately followed by a function declaration or definition" } */
+
+int t;
+
+#pragma omp declare simd
+#pragma omp declare simd
+#pragma omp threadprivate(t) /* { dg-error "must be followed by function declaration or definition or another" } */
+int fn5 (int a);
+
+#pragma omp declare simd inbranch notinbranch /* { dg-error "clause is incompatible with" } */
+int fn6 (int);
+
+#pragma omp declare simd aligned (a, b)
+int fn7 (int *a, int b[64]);
+
+#pragma omp declare simd aligned (a) /* { dg-error "neither a pointer nor an array" } */
+int fn8 (int a);
+
+#pragma omp declare simd aligned (c) /* { dg-error "neither a pointer nor an array" } */
+int fn9 (float c);
+
+#pragma omp declare simd aligned (d) /* { dg-error "neither a pointer nor an array" } */
+int fn10 (double d);
+
+struct D { int d; };
+
+#pragma omp declare simd aligned (e) /* { dg-error "neither a pointer nor an array" } */
+int fn11 (struct D e);
+
+#pragma omp declare simd linear(a:7) uniform(a) /* { dg-error "appears more than once" } */
+int f12 (int a);
+#pragma omp declare simd linear(a) linear(a) /* { dg-error "appears more than once" } */
+int f13 (int a);
+#pragma omp declare simd linear(a) linear(a:7) /* { dg-error "appears more than once" } */
+int f14 (int a);
+#pragma omp declare simd linear(a:6) linear(a:6)/* { dg-error "appears more than once" } */
+int f15 (int a);
+#pragma omp declare simd uniform(a) uniform(a) /* { dg-error "appears more than once" } */
+int f16 (int a);
+#pragma omp declare simd uniform(a) aligned (a: 32)
+int f17 (int *a);
diff --git a/gcc/testsuite/gcc.dg/gomp/gomp.exp b/gcc/testsuite/gcc.dg/gomp/gomp.exp
index ca8aefd3c4e..cc2cd8ed089 100644
--- a/gcc/testsuite/gcc.dg/gomp/gomp.exp
+++ b/gcc/testsuite/gcc.dg/gomp/gomp.exp
@@ -29,7 +29,9 @@ if ![check_effective_target_fopenmp] {
dg-init
# Main loop.
-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c $srcdir/c-c++-common/gomp/*.c]] "" "-fopenmp"
+dg-runtest [lsort [concat \
+ [find $srcdir/$subdir *.c] \
+ [find $srcdir/c-c++-common/gomp *.c]]] "" "-fopenmp"
# All done.
dg-finish
diff --git a/gcc/testsuite/gcc.dg/gomp/nesting-1.c b/gcc/testsuite/gcc.dg/gomp/nesting-1.c
index df57ac845f7..52fcda741ea 100644
--- a/gcc/testsuite/gcc.dg/gomp/nesting-1.c
+++ b/gcc/testsuite/gcc.dg/gomp/nesting-1.c
@@ -28,17 +28,58 @@ f1 (void)
#pragma omp for /* { dg-error "may not be closely nested" } */
for (j = 0; j < 3; j++)
;
+ }
+ #pragma omp sections
+ {
#pragma omp sections /* { dg-error "may not be closely nested" } */
{
;
#pragma omp section
;
}
+ }
+ #pragma omp sections
+ {
#pragma omp single /* { dg-error "may not be closely nested" } */
;
+ }
+ #pragma omp sections
+ {
#pragma omp master /* { dg-error "may not be closely nested" } */
;
+ }
+ #pragma omp sections
+ {
+ #pragma omp section
+ ;
+ }
+ #pragma omp sections
+ {
#pragma omp section
+ #pragma omp for /* { dg-error "may not be closely nested" } */
+ for (j = 0; j < 3; j++)
+ ;
+ }
+ #pragma omp sections
+ {
+ #pragma omp section
+ #pragma omp sections /* { dg-error "may not be closely nested" } */
+ {
+ ;
+ #pragma omp section
+ ;
+ }
+ }
+ #pragma omp sections
+ {
+ #pragma omp section
+ #pragma omp single /* { dg-error "may not be closely nested" } */
+ ;
+ }
+ #pragma omp sections
+ {
+ #pragma omp section
+ #pragma omp master /* { dg-error "may not be closely nested" } */
;
}
#pragma omp single
diff --git a/gcc/testsuite/gcc.dg/gomp/openmp-simd-1.c b/gcc/testsuite/gcc.dg/gomp/openmp-simd-1.c
new file mode 100644
index 00000000000..fedb186fedf
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gomp/openmp-simd-1.c
@@ -0,0 +1,46 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp-simd -fdump-tree-original" } */
+
+#pragma omp declare simd
+float bar(float b) {
+ return b*b;
+}
+
+void foo(int n, float *a, float *b)
+{
+ int i;
+#pragma omp simd
+ for (i = 0; i < n ; i++)
+ a[i] = b[i];
+#pragma omp for simd
+ for (i = 0; i < n ; i++)
+ a[i] = b[i];
+#pragma omp distribute simd
+ for (i = 0; i < n ; i++)
+ a[i] = b[i];
+#pragma omp distribute parallel for simd
+ for (i = 0; i < n ; i++)
+ a[i] = b[i];
+#pragma omp parallel for simd
+ for (i = 0; i < n ; i++)
+ a[i] = b[i];
+#pragma omp teams distribute simd
+ for (i = 0; i < n ; i++)
+ a[i] = b[i];
+#pragma omp target teams distribute simd
+ for (i = 0; i < n ; i++)
+ a[i] = b[i];
+#pragma omp teams distribute parallel for simd
+ for (i = 0; i < n ; i++)
+ a[i] = b[i];
+#pragma omp target teams distribute parallel for simd
+ for (i = 0; i < n ; i++)
+ a[i] = b[i];
+}
+
+/* { dg-final { scan-tree-dump-times "pragma omp simd" 9 "original" } } */
+/* { dg-final { scan-tree-dump-not "omp for" "original" } } */
+/* { dg-final { scan-tree-dump-not "omp distribute" "original" } } */
+/* { dg-final { scan-tree-dump-not "omp teams" "original" } } */
+/* { dg-final { scan-tree-dump-not "omp target" "original" } } */
+/* { dg-final { scan-tree-dump-not "omp parallel" "original" } } */
diff --git a/gcc/testsuite/gcc.dg/gomp/openmp-simd-2.c b/gcc/testsuite/gcc.dg/gomp/openmp-simd-2.c
new file mode 100644
index 00000000000..e66806845b7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gomp/openmp-simd-2.c
@@ -0,0 +1,42 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp-simd -fdump-tree-original" } */
+
+extern void abort ();
+int a[1024] __attribute__((aligned (32))) = { 1 };
+struct S { int s; };
+#pragma omp declare reduction (+:struct S:omp_out.s += omp_in.s)
+#pragma omp declare reduction (foo:struct S:omp_out.s += omp_in.s)
+#pragma omp declare reduction (foo:int:omp_out += omp_in)
+
+__attribute__((noinline, noclone)) int
+foo (void)
+{
+ int i, u = 0;
+ struct S s, t;
+ s.s = 0; t.s = 0;
+ #pragma omp simd aligned(a : 32) reduction(+:s) reduction(foo:t, u)
+ for (i = 0; i < 1024; i++)
+ {
+ int x = a[i];
+ s.s += x;
+ t.s += x;
+ u += x;
+ }
+ if (t.s != s.s || u != s.s)
+ abort ();
+ return s.s;
+}
+
+
+void bar(int n, float *a, float *b)
+{
+ int i;
+#pragma omp parallel for simd num_threads(4) safelen(64)
+ for (i = 0; i < n ; i++)
+ a[i] = b[i];
+}
+
+/* { dg-final { scan-tree-dump-times "pragma omp simd reduction\\(u\\) reduction\\(t\\) reduction\\(\\+:s\\) aligned\\(a:32\\)" 1 "original" } } */
+/* { dg-final { scan-tree-dump-times "pragma omp simd safelen\\(64\\)" 1 "original" } } */
+/* { dg-final { scan-tree-dump-not "omp parallel" "original" } } */
+/* { dg-final { scan-tree-dump-not "omp for" "original" } } */
diff --git a/gcc/testsuite/gcc.dg/gomp/pr58809.c b/gcc/testsuite/gcc.dg/gomp/pr58809.c
new file mode 100644
index 00000000000..5dc02f65aa8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gomp/pr58809.c
@@ -0,0 +1,13 @@
+/* PR middle-end/58809 */
+/* { dg-do compile } */
+/* { dg-options "-fopenmp -O" } */
+
+int i;
+#pragma omp threadprivate (i)
+
+void foo()
+{
+ _Complex int j;
+#pragma omp parallel copyin (i) reduction (&&:j)
+ ;
+}
diff --git a/gcc/testsuite/gcc.dg/gomp/target-1.c b/gcc/testsuite/gcc.dg/gomp/target-1.c
new file mode 100644
index 00000000000..09e65bd3115
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gomp/target-1.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+
+void
+foo (int x)
+{
+ bad1:
+ #pragma omp target
+ goto bad1; /* { dg-error "invalid branch" } */
+
+ goto bad2; /* { dg-error "invalid entry" } */
+ #pragma omp target
+ {
+ bad2: ;
+ }
+
+ #pragma omp target
+ {
+ int i;
+ goto ok1;
+ for (i = 0; i < 10; ++i)
+ { ok1: break; }
+ }
+
+ switch (x) /* { dg-error "invalid entry" } */
+ {
+ #pragma omp target
+ { case 0:; }
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/gomp/target-2.c b/gcc/testsuite/gcc.dg/gomp/target-2.c
new file mode 100644
index 00000000000..546a1d0c157
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gomp/target-2.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+
+void
+foo (int x, int y)
+{
+ bad1:
+ #pragma omp target data map(tofrom: y)
+ goto bad1; /* { dg-error "invalid branch" } */
+
+ goto bad2; /* { dg-error "invalid entry" } */
+ #pragma omp target data map(tofrom: y)
+ {
+ bad2: ;
+ }
+
+ #pragma omp target data map(tofrom: y)
+ {
+ int i;
+ goto ok1;
+ for (i = 0; i < 10; ++i)
+ { ok1: break; }
+ }
+
+ switch (x) /* { dg-error "invalid entry" } */
+ {
+ #pragma omp target data map(tofrom: y)
+ { case 0:; }
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/gomp/taskgroup-1.c b/gcc/testsuite/gcc.dg/gomp/taskgroup-1.c
new file mode 100644
index 00000000000..e301efc19c4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gomp/taskgroup-1.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+
+void
+foo (int x)
+{
+ bad1:
+ #pragma omp taskgroup
+ goto bad1; /* { dg-error "invalid branch" } */
+
+ goto bad2; /* { dg-error "invalid entry" } */
+ #pragma omp taskgroup
+ {
+ bad2: ;
+ }
+
+ #pragma omp taskgroup
+ {
+ int i;
+ goto ok1;
+ for (i = 0; i < 10; ++i)
+ { ok1: break; }
+ }
+
+ switch (x) /* { dg-error "invalid entry" } */
+ {
+ #pragma omp taskgroup
+ { case 0:; }
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/gomp/teams-1.c b/gcc/testsuite/gcc.dg/gomp/teams-1.c
new file mode 100644
index 00000000000..73c00ded78b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gomp/teams-1.c
@@ -0,0 +1,61 @@
+/* { dg-do compile } */
+
+void
+foo (int x)
+{
+ bad1:
+ #pragma omp target teams
+ goto bad1; /* { dg-error "invalid branch" } */
+
+ goto bad2; /* { dg-error "invalid entry" } */
+ #pragma omp target teams
+ {
+ bad2: ;
+ }
+
+ #pragma omp target teams
+ {
+ int i;
+ goto ok1;
+ for (i = 0; i < 10; ++i)
+ { ok1: break; }
+ }
+
+ switch (x) /* { dg-error "invalid entry" } */
+ {
+ #pragma omp target teams
+ { case 0:; }
+ }
+}
+
+void
+bar (int x)
+{
+ bad1:
+ #pragma omp target
+ #pragma omp teams
+ goto bad1; /* { dg-error "invalid branch" } */
+
+ goto bad2; /* { dg-error "invalid entry" } */
+ #pragma omp target
+ #pragma omp teams
+ {
+ bad2: ;
+ }
+
+ #pragma omp target
+ #pragma omp teams
+ {
+ int i;
+ goto ok1;
+ for (i = 0; i < 10; ++i)
+ { ok1: break; }
+ }
+
+ switch (x) /* { dg-error "invalid entry" } */
+ {
+ #pragma omp target
+ #pragma omp teams
+ { case 0:; }
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/gomp/udr-1.c b/gcc/testsuite/gcc.dg/gomp/udr-1.c
new file mode 100644
index 00000000000..4948a984f69
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gomp/udr-1.c
@@ -0,0 +1,46 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp" } */
+
+#pragma omp declare reduction (| : long int : omp_out |= omp_in) /* { dg-error "predeclared arithmetic type" } */
+#pragma omp declare reduction (+ : char : omp_out += omp_in) /* { dg-error "predeclared arithmetic type" } */
+typedef short T;
+#pragma omp declare reduction (min : T : omp_out += omp_in) /* { dg-error "predeclared arithmetic type" } */
+#pragma omp declare reduction (* : _Complex double : omp_out *= omp_in) /* { dg-error "predeclared arithmetic type" } */
+
+void
+foo (void)
+{
+ #pragma omp declare reduction (| : long int : omp_out |= omp_in) /* { dg-error "predeclared arithmetic type" } */
+ #pragma omp declare reduction (+ : char : omp_out += omp_in) /* { dg-error "predeclared arithmetic type" } */
+ #pragma omp declare reduction (min : T : omp_out += omp_in) /* { dg-error "predeclared arithmetic type" } */
+ #pragma omp declare reduction (* : _Complex double : omp_out *= omp_in) /* { dg-error "predeclared arithmetic type" } */
+}
+
+#pragma omp declare reduction (| : __typeof (foo) : omp_out |= omp_in) /* { dg-error "function or array" } */
+#pragma omp declare reduction (+ : char () : omp_out += omp_in) /* { dg-error "function or array" } */
+#pragma omp declare reduction (min : T[2] : omp_out += omp_in) /* { dg-error "function or array" } */
+
+void
+bar (void)
+{
+ #pragma omp declare reduction (| : __typeof (foo) : omp_out |= omp_in)/* { dg-error "function or array" } */
+ #pragma omp declare reduction (+ : char () : omp_out += omp_in) /* { dg-error "function or array" } */
+ #pragma omp declare reduction (min : T[2] : omp_out += omp_in) /* { dg-error "function or array" } */
+}
+
+struct A { int a; };
+#pragma omp declare reduction (| : const struct A : omp_out.a |= omp_in.a) /* { dg-error "const, volatile or restrict" } */
+#pragma omp declare reduction (+ : __const struct A : omp_out.a += omp_in.a) /* { dg-error "const, volatile or restrict" } */
+typedef volatile struct A T2;
+#pragma omp declare reduction (min : T2 : omp_out.a += omp_in.a) /* { dg-error "const, volatile or restrict" } */
+#pragma omp declare reduction (* : struct A *__restrict : omp_out->a *= omp_in->a)/* { dg-error "const, volatile or restrict" } */
+
+void
+baz (void)
+{
+ #pragma omp declare reduction (| : const struct A : omp_out.a |= omp_in.a) /* { dg-error "const, volatile or restrict" } */
+ #pragma omp declare reduction (+ : __const struct A : omp_out.a += omp_in.a) /* { dg-error "const, volatile or restrict" } */
+ typedef volatile struct A T3;
+ #pragma omp declare reduction (min : T3 : omp_out.a += omp_in.a) /* { dg-error "const, volatile or restrict" } */
+ #pragma omp declare reduction (* : struct A *__restrict : omp_out->a *= omp_in->a)/* { dg-error "const, volatile or restrict" } */
+}
diff --git a/gcc/testsuite/gcc.dg/gomp/udr-2.c b/gcc/testsuite/gcc.dg/gomp/udr-2.c
new file mode 100644
index 00000000000..87992d7c6ed
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gomp/udr-2.c
@@ -0,0 +1,42 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp" } */
+
+struct W { int w; };
+void init (struct W *, int, int *);
+int v;
+#pragma omp declare reduction (foo : long int : omp_out |= v) /* { dg-error "combiner refers to variable" } */
+#pragma omp declare reduction (foo : char : omp_out = v) /* { dg-error "combiner refers to variable" } */
+typedef short T;
+#pragma omp declare reduction (foo : T : omp_out += v) /* { dg-error "combiner refers to variable" } */
+#pragma omp declare reduction (foo : int : v *= omp_in) /* { dg-error "combiner refers to variable" } */
+#pragma omp declare reduction (foo : struct W : omp_out.w *= omp_in.w + v) /* { dg-error "combiner refers to variable" } */
+
+void
+foo (int v)
+{
+ #pragma omp declare reduction (foo : long int : omp_out |= v) /* { dg-error "combiner refers to variable" } */
+ #pragma omp declare reduction (foo : char : omp_out = v) /* { dg-error "combiner refers to variable" } */
+ #pragma omp declare reduction (foo : T : omp_out += v) /* { dg-error "combiner refers to variable" } */
+ #pragma omp declare reduction (foo : int : v *= omp_in) /* { dg-error "combiner refers to variable" } */
+ #pragma omp declare reduction (foo : struct W : omp_out.w *= omp_in.w + v) /* { dg-error "combiner refers to variable" } */
+}
+
+#pragma omp declare reduction (bar : long int : omp_out |= omp_in) initializer (omp_priv = v) /* { dg-error "initializer refers to variable" } */
+#pragma omp declare reduction (bar : char : omp_out += omp_in) initializer (omp_priv = ((char) v)) /* { dg-error "initializer refers to variable" } */
+#pragma omp declare reduction (bar : T : omp_out += omp_in) initializer (omp_priv = (short) v) /* { dg-error "initializer refers to variable" } */
+#pragma omp declare reduction (bar : _Complex double : omp_out *= omp_in) initializer (omp_priv = (v)) /* { dg-error "initializer refers to variable" } */
+#pragma omp declare reduction (bar : struct W : omp_out.w *= omp_in.w) initializer (omp_priv = { v } ) /* { dg-error "initializer refers to variable" } */
+#pragma omp declare reduction (bar2 : struct W : omp_out.w *= omp_in.w) initializer (init (&omp_priv, v, (int *) 0)) /* { dg-error "initializer refers to variable" } */
+#pragma omp declare reduction (bar3 : struct W : omp_out.w *= omp_in.w) initializer (init (&omp_priv, 0, &v)) /* { dg-error "initializer refers to variable" } */
+
+void
+bar (int v)
+{
+ #pragma omp declare reduction (bar : long int : omp_out |= omp_in) initializer (omp_priv = v) /* { dg-error "initializer refers to variable" } */
+ #pragma omp declare reduction (bar : char : omp_out += omp_in) initializer (omp_priv = ((char) v)) /* { dg-error "initializer refers to variable" } */
+ #pragma omp declare reduction (bar : T : omp_out += omp_in) initializer (omp_priv = (short) v) /* { dg-error "initializer refers to variable" } */
+ #pragma omp declare reduction (bar : _Complex double : omp_out *= omp_in) initializer (omp_priv = (v)) /* { dg-error "initializer refers to variable" } */
+ #pragma omp declare reduction (bar : struct W : omp_out.w *= omp_in.w) initializer (omp_priv = { v }) /* { dg-error "initializer refers to variable" } */
+ #pragma omp declare reduction (bar2 : struct W : omp_out.w *= omp_in.w) initializer (init (&omp_priv, v, (int *) 0)) /* { dg-error "initializer refers to variable" } */
+ #pragma omp declare reduction (bar3 : struct W : omp_out.w *= omp_in.w) initializer (init (&omp_priv, 0, &v)) /* { dg-error "initializer refers to variable" } */
+}
diff --git a/gcc/testsuite/gcc.dg/gomp/udr-3.c b/gcc/testsuite/gcc.dg/gomp/udr-3.c
new file mode 100644
index 00000000000..bdfcce1d0b6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gomp/udr-3.c
@@ -0,0 +1,77 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp" } */
+
+struct S { int s; };
+struct T { int t; };
+struct U { int u; };
+
+#pragma omp declare reduction (+: struct S: omp_out.s += omp_in.s)
+#pragma omp declare reduction (*: struct S: omp_out.s *= omp_in.s) \
+ initializer (omp_priv = {1})
+#pragma omp declare reduction (foo: struct S: omp_out.s += omp_in.s)
+
+void
+f1 ()
+{
+ struct S s, s2;
+ struct T t;
+ #pragma omp declare reduction (+: struct T: omp_out.t += omp_in.t)
+ #pragma omp parallel reduction (+: t) reduction (foo: s) reduction (*: s2)
+ s.s = 1, t.t = 1, s2.s = 2;
+ #pragma omp parallel reduction (+: s)
+ s.s = 1;
+}
+
+void bar (struct S *);
+
+void
+f2 ()
+{
+ #pragma omp declare reduction (foo: struct S: omp_out.s += omp_in.s) initializer (bar (&omp_priv))
+ #pragma omp declare reduction (bar: struct S: omp_out.s += omp_in.s) initializer (bar (&omp_orig)) /* { dg-error "one of the initializer call arguments should be" } */
+}
+
+#pragma omp declare reduction (+: struct U: omp_out.u *= omp_in.u) /* { dg-error "previous" } */
+#pragma omp declare reduction (+: struct U: omp_out.u += omp_in.u) /* { dg-error "redeclaration of" } */
+
+void
+f3 ()
+{
+ #pragma omp declare reduction (f3: struct U: omp_out.u *= omp_in.u) /* { dg-error "previous" } */
+ #pragma omp declare reduction (f3: struct U: omp_out.u += omp_in.u) /* { dg-error "redeclaration of" } */
+}
+
+struct V
+{
+ #pragma omp declare reduction (bar: struct S: omp_out.s *= omp_in.s) /* { dg-error "not at file or block scope" } */
+ #pragma omp declare reduction (bar: struct S: omp_out.s += omp_in.s) /* { dg-error "not at file or block scope" } */
+};
+
+#pragma omp declare reduction (n3: long: omp_out += omp_in) /* { dg-error "previous" } */
+#pragma omp declare reduction (n3: long int: omp_out += omp_in) /* { dg-error "redeclaration of" } */
+#pragma omp declare reduction (n3: short unsigned: omp_out += omp_in)
+#pragma omp declare reduction (n3: short int: omp_out += omp_in)
+
+void
+f4 (void)
+{
+ #pragma omp declare reduction (f4: long: omp_out += omp_in) /* { dg-error "previous" } */
+ #pragma omp declare reduction (f4: long int: omp_out += omp_in) /* { dg-error "redeclaration of" } */
+ #pragma omp declare reduction (f4: short unsigned: omp_out += omp_in)
+ #pragma omp declare reduction (f4: short int: omp_out += omp_in)
+}
+
+void
+f5 (void)
+{
+ #pragma omp declare reduction (+: struct S: omp_out.s += omp_in.s) initializer (omp_priv) /* { dg-error "expected" } */
+ #pragma omp declare reduction (+: struct T: omp_out.t += omp_in.t) initializer (omp_priv ()) /* { dg-error "expected" } */
+}
+
+void
+f6 (a, b)
+#pragma omp declare reduction (bar: struct S: omp_out.s *= omp_in.s) /* { dg-error "expected declaration specifiers before" } */
+ int a;
+ int b;
+{
+}
diff --git a/gcc/testsuite/gcc.dg/gomp/udr-4.c b/gcc/testsuite/gcc.dg/gomp/udr-4.c
new file mode 100644
index 00000000000..3758f91e851
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gomp/udr-4.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+
+struct S;
+#pragma omp declare reduction (+:struct S:omp_out.s += omp_in.s) /* { dg-error "invalid use of undefined type" } */
+struct S { int s; };
+#pragma omp declare reduction (*:struct S:omp_out.s *= omp_in.s)
diff --git a/gcc/testsuite/gcc.dg/guality/pr58791-1.c b/gcc/testsuite/gcc.dg/guality/pr58791-1.c
new file mode 100644
index 00000000000..62ce881bfc2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/guality/pr58791-1.c
@@ -0,0 +1,34 @@
+/* PR tree-optimization/58791 */
+/* { dg-do run } */
+/* { dg-options "-g" } */
+
+#include "../nop.h"
+
+__attribute__((noinline, noclone)) int
+foo (int x, int y)
+{
+ _Bool a = x != 0;
+ _Bool b = y != 2;
+ _Bool c = a & b;
+ _Bool d = !c;
+ int ret;
+ if (c)
+ {
+ if (y < 3 || y > 4)
+ ret = 1;
+ else
+ ret = 0;
+ }
+ else
+ ret = 0;
+ asm volatile (NOP : : : "memory"); /* { dg-final { gdb-test pr58791-1.c:25 "c & 1" "1" } } */
+ asm volatile (NOP : : : "memory"); /* { dg-final { gdb-test pr58791-1.c:25 "d & 1" "0" } } */
+ return ret;
+}
+
+int
+main ()
+{
+ foo (1, 3);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/guality/pr58791-2.c b/gcc/testsuite/gcc.dg/guality/pr58791-2.c
new file mode 100644
index 00000000000..d7da69b48c4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/guality/pr58791-2.c
@@ -0,0 +1,36 @@
+/* PR tree-optimization/58791 */
+/* { dg-do run } */
+/* { dg-options "-g" } */
+
+#include "../nop.h"
+
+__attribute__((noinline, noclone)) int
+foo (unsigned char c)
+{
+ int ret;
+ _Bool a, b, d, e, f;
+
+ a = c == 34;
+ b = c == 32;
+ d = a | b;
+ f = !d;
+ if (d)
+ ret = 1;
+ else
+ {
+ e = c <= 31;
+ ret = e;
+ }
+
+ asm volatile (NOP : : : "memory"); /* { dg-final { gdb-test pr58791-2.c:27 "d & 1" "1" } } */
+ asm volatile (NOP : : : "memory"); /* { dg-final { gdb-test pr58791-2.c:27 "f & 1" "0" } } */
+ return ret;
+}
+
+
+int
+main ()
+{
+ foo (32);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/guality/pr58791-3.c b/gcc/testsuite/gcc.dg/guality/pr58791-3.c
new file mode 100644
index 00000000000..6316ace5667
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/guality/pr58791-3.c
@@ -0,0 +1,28 @@
+/* PR tree-optimization/58791 */
+/* { dg-do run } */
+/* { dg-options "-g" } */
+
+#include "../nop.h"
+
+__attribute__((noinline, noclone)) unsigned
+foo (unsigned a, unsigned b, unsigned c, unsigned d, unsigned e)
+{
+ unsigned f = b + c; /* { dg-final { gdb-test pr58791-3.c:19 "f" "5" } } */
+ unsigned g = a - f; /* { dg-final { gdb-test pr58791-3.c:19 "g" "24" } } */
+ unsigned h = d + e; /* { dg-final { gdb-test pr58791-3.c:19 "h" "9" } } */
+ unsigned i = g - h; /* { dg-final { gdb-test pr58791-3.c:19 "i" "15" } } */
+ unsigned j = f + 1; /* { dg-final { gdb-test pr58791-3.c:19 "j" "6" } } */
+ unsigned k = g + 1; /* { dg-final { gdb-test pr58791-3.c:19 "k" "25" } } */
+ unsigned l = h + 1; /* { dg-final { gdb-test pr58791-3.c:19 "l" "10" } } */
+ unsigned m = i + 1; /* { dg-final { gdb-test pr58791-3.c:19 "m" "16" } } */
+ asm volatile (NOP : : : "memory");
+ asm volatile (NOP : : : "memory");
+ return i;
+}
+
+int
+main ()
+{
+ foo (29, 2, 3, 4, 5);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/guality/pr58791-4.c b/gcc/testsuite/gcc.dg/guality/pr58791-4.c
new file mode 100644
index 00000000000..d988a9cfbbe
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/guality/pr58791-4.c
@@ -0,0 +1,41 @@
+/* PR tree-optimization/58791 */
+/* { dg-do run } */
+/* { dg-options "-g -ffast-math" } */
+
+#include "../nop.h"
+
+__attribute__((noinline, noclone)) double
+foo (float a, float b, float c, float d, float l, double u)
+{
+ float e = a * d;
+ float f = d * e;
+ double g = (double) f;
+ double h = (double) b;
+ double i = g * h; /* { dg-final { gdb-test pr58791-4.c:32 "i" "486" { target { x86_64-*-* && lp64 } } } } */
+ double i2 = i + 1.0; /* { dg-final { gdb-test pr58791-4.c:32 "i2" "487" { target { x86_64-*-* && lp64 } } } } */
+ double j = i * 3.25;
+ double k = h + j;
+ float m = l * 8.75;
+ double n = (double) m;
+ double o = (double) a;
+ double p = n * o;
+ double q = h * p;
+ double r = q * 2.5;
+ double s = k - r;
+ double t = (double) c;
+ double v = o * u;
+ double w = o * v;
+ double x = h * w;
+ double y = h * x;
+ double z = y * 8.5;
+ asm volatile (NOP : : : "memory");
+ asm volatile (NOP : : : "memory");
+ return s - z;
+}
+
+int
+main ()
+{
+ foo (3.0f, 2.0f, -1.0f, 9.0f, 1.0f, 2.0);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/guality/pr58791-5.c b/gcc/testsuite/gcc.dg/guality/pr58791-5.c
new file mode 100644
index 00000000000..c2377691940
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/guality/pr58791-5.c
@@ -0,0 +1,29 @@
+/* PR tree-optimization/58791 */
+/* { dg-do run } */
+/* { dg-options "-g" } */
+
+#include "../nop.h"
+
+__attribute__((noinline, noclone)) unsigned int
+foo (unsigned int a0, unsigned int a1, unsigned int a2,
+ unsigned int a3, unsigned int a4)
+{
+ unsigned int b0, b1, b2, b3, b4, e;
+ /* this can be optimized to four additions... */
+ b4 = a4 + a3 + a2 + a1 + a0; /* { dg-final { gdb-test pr58791-5.c:20 "b4" "4681" } } */
+ b3 = a3 + a2 + a1 + a0; /* { dg-final { gdb-test pr58791-5.c:20 "b3" "585" } } */
+ b2 = a2 + a1 + a0; /* { dg-final { gdb-test pr58791-5.c:20 "b2" "73" } } */
+ b1 = a1 + a0; /* { dg-final { gdb-test pr58791-5.c:20 "b1" "9" } } */
+ /* This is actually 0 */
+ e = b4 - b3 + b2 - b1 - a4 - a2; /* { dg-final { gdb-test pr58791-5.c:20 "e" "0" } } */
+ asm volatile (NOP : : : "memory");
+ asm volatile (NOP : : : "memory");
+ return e;
+}
+
+int
+main ()
+{
+ foo (1, 8, 64, 512, 4096);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/iec-559-macros-1.c b/gcc/testsuite/gcc.dg/iec-559-macros-1.c
new file mode 100644
index 00000000000..bd5d037afc4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/iec-559-macros-1.c
@@ -0,0 +1,16 @@
+/* Test __GCC_IEC_559 and __GCC_IEC_559_COMPLEX macros values. */
+/* { dg-do preprocess } */
+/* { dg-options "" } */
+
+#ifndef __GCC_IEC_559
+# error "__GCC_IEC_559 not defined"
+#endif
+#ifndef __GCC_IEC_559_COMPLEX
+# error "__GCC_IEC_559_COMPLEX not defined"
+#endif
+#if __GCC_IEC_559_COMPLEX > __GCC_IEC_559
+# error "__GCC_IEC_559_COMPLEX > __GCC_IEC_559"
+#endif
+#if __GCC_IEC_559_COMPLEX < 0
+# error "__GCC_IEC_559_COMPLEX < 0"
+#endif
diff --git a/gcc/testsuite/gcc.dg/iec-559-macros-2.c b/gcc/testsuite/gcc.dg/iec-559-macros-2.c
new file mode 100644
index 00000000000..5a28574ac99
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/iec-559-macros-2.c
@@ -0,0 +1,23 @@
+/* Test __GCC_IEC_559 and __GCC_IEC_559_COMPLEX macros values. */
+/* { dg-do preprocess } */
+/* { dg-options "-funsafe-math-optimizations" } */
+
+#ifndef __GCC_IEC_559
+# error "__GCC_IEC_559 not defined"
+#endif
+#ifndef __GCC_IEC_559_COMPLEX
+# error "__GCC_IEC_559_COMPLEX not defined"
+#endif
+#if __GCC_IEC_559_COMPLEX > __GCC_IEC_559
+# error "__GCC_IEC_559_COMPLEX > __GCC_IEC_559"
+#endif
+#if __GCC_IEC_559_COMPLEX < 0
+# error "__GCC_IEC_559_COMPLEX < 0"
+#endif
+
+#if __GCC_IEC_559 != 0
+# error "__GCC_IEC_559 != 0 with -funsafe-math-optimizations"
+#endif
+#if __GCC_IEC_559_COMPLEX != 0
+# error "__GCC_IEC_559_COMPLEX != 0 with -funsafe-math-optimizations"
+#endif
diff --git a/gcc/testsuite/gcc.dg/iec-559-macros-3.c b/gcc/testsuite/gcc.dg/iec-559-macros-3.c
new file mode 100644
index 00000000000..5eeb34503fe
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/iec-559-macros-3.c
@@ -0,0 +1,23 @@
+/* Test __GCC_IEC_559 and __GCC_IEC_559_COMPLEX macros values. */
+/* { dg-do preprocess } */
+/* { dg-options "-freciprocal-math" } */
+
+#ifndef __GCC_IEC_559
+# error "__GCC_IEC_559 not defined"
+#endif
+#ifndef __GCC_IEC_559_COMPLEX
+# error "__GCC_IEC_559_COMPLEX not defined"
+#endif
+#if __GCC_IEC_559_COMPLEX > __GCC_IEC_559
+# error "__GCC_IEC_559_COMPLEX > __GCC_IEC_559"
+#endif
+#if __GCC_IEC_559_COMPLEX < 0
+# error "__GCC_IEC_559_COMPLEX < 0"
+#endif
+
+#if __GCC_IEC_559 != 0
+# error "__GCC_IEC_559 != 0 with -freciprocal-math"
+#endif
+#if __GCC_IEC_559_COMPLEX != 0
+# error "__GCC_IEC_559_COMPLEX != 0 with -freciprocal-math"
+#endif
diff --git a/gcc/testsuite/gcc.dg/iec-559-macros-4.c b/gcc/testsuite/gcc.dg/iec-559-macros-4.c
new file mode 100644
index 00000000000..7bf6b9c30bc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/iec-559-macros-4.c
@@ -0,0 +1,23 @@
+/* Test __GCC_IEC_559 and __GCC_IEC_559_COMPLEX macros values. */
+/* { dg-do preprocess } */
+/* { dg-options "-ffinite-math-only" } */
+
+#ifndef __GCC_IEC_559
+# error "__GCC_IEC_559 not defined"
+#endif
+#ifndef __GCC_IEC_559_COMPLEX
+# error "__GCC_IEC_559_COMPLEX not defined"
+#endif
+#if __GCC_IEC_559_COMPLEX > __GCC_IEC_559
+# error "__GCC_IEC_559_COMPLEX > __GCC_IEC_559"
+#endif
+#if __GCC_IEC_559_COMPLEX < 0
+# error "__GCC_IEC_559_COMPLEX < 0"
+#endif
+
+#if __GCC_IEC_559 != 0
+# error "__GCC_IEC_559 != 0 with -ffinite-math-only"
+#endif
+#if __GCC_IEC_559_COMPLEX != 0
+# error "__GCC_IEC_559_COMPLEX != 0 with -ffinite-math-only"
+#endif
diff --git a/gcc/testsuite/gcc.dg/iec-559-macros-5.c b/gcc/testsuite/gcc.dg/iec-559-macros-5.c
new file mode 100644
index 00000000000..ea37474fd1e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/iec-559-macros-5.c
@@ -0,0 +1,23 @@
+/* Test __GCC_IEC_559 and __GCC_IEC_559_COMPLEX macros values. */
+/* { dg-do preprocess } */
+/* { dg-options "-fno-signed-zeros" } */
+
+#ifndef __GCC_IEC_559
+# error "__GCC_IEC_559 not defined"
+#endif
+#ifndef __GCC_IEC_559_COMPLEX
+# error "__GCC_IEC_559_COMPLEX not defined"
+#endif
+#if __GCC_IEC_559_COMPLEX > __GCC_IEC_559
+# error "__GCC_IEC_559_COMPLEX > __GCC_IEC_559"
+#endif
+#if __GCC_IEC_559_COMPLEX < 0
+# error "__GCC_IEC_559_COMPLEX < 0"
+#endif
+
+#if __GCC_IEC_559 != 0
+# error "__GCC_IEC_559 != 0 with -fno-signed-zeros"
+#endif
+#if __GCC_IEC_559_COMPLEX != 0
+# error "__GCC_IEC_559_COMPLEX != 0 with -fno-signed-zeros"
+#endif
diff --git a/gcc/testsuite/gcc.dg/iec-559-macros-6.c b/gcc/testsuite/gcc.dg/iec-559-macros-6.c
new file mode 100644
index 00000000000..e2be757f86c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/iec-559-macros-6.c
@@ -0,0 +1,23 @@
+/* Test __GCC_IEC_559 and __GCC_IEC_559_COMPLEX macros values. */
+/* { dg-do preprocess } */
+/* { dg-options "-fsingle-precision-constant" } */
+
+#ifndef __GCC_IEC_559
+# error "__GCC_IEC_559 not defined"
+#endif
+#ifndef __GCC_IEC_559_COMPLEX
+# error "__GCC_IEC_559_COMPLEX not defined"
+#endif
+#if __GCC_IEC_559_COMPLEX > __GCC_IEC_559
+# error "__GCC_IEC_559_COMPLEX > __GCC_IEC_559"
+#endif
+#if __GCC_IEC_559_COMPLEX < 0
+# error "__GCC_IEC_559_COMPLEX < 0"
+#endif
+
+#if __GCC_IEC_559 != 0
+# error "__GCC_IEC_559 != 0 with -fsingle-precision-constant"
+#endif
+#if __GCC_IEC_559_COMPLEX != 0
+# error "__GCC_IEC_559_COMPLEX != 0 with -fsingle-precision-constant"
+#endif
diff --git a/gcc/testsuite/gcc.dg/iec-559-macros-7.c b/gcc/testsuite/gcc.dg/iec-559-macros-7.c
new file mode 100644
index 00000000000..3b1f79172d7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/iec-559-macros-7.c
@@ -0,0 +1,20 @@
+/* Test __GCC_IEC_559 and __GCC_IEC_559_COMPLEX macros values. */
+/* { dg-do preprocess } */
+/* { dg-options "-fcx-limited-range" } */
+
+#ifndef __GCC_IEC_559
+# error "__GCC_IEC_559 not defined"
+#endif
+#ifndef __GCC_IEC_559_COMPLEX
+# error "__GCC_IEC_559_COMPLEX not defined"
+#endif
+#if __GCC_IEC_559_COMPLEX > __GCC_IEC_559
+# error "__GCC_IEC_559_COMPLEX > __GCC_IEC_559"
+#endif
+#if __GCC_IEC_559_COMPLEX < 0
+# error "__GCC_IEC_559_COMPLEX < 0"
+#endif
+
+#if __GCC_IEC_559_COMPLEX != 0
+# error "__GCC_IEC_559_COMPLEX != 0 with -fcx-limited-range"
+#endif
diff --git a/gcc/testsuite/gcc.dg/iec-559-macros-8.c b/gcc/testsuite/gcc.dg/iec-559-macros-8.c
new file mode 100644
index 00000000000..1990b944dc5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/iec-559-macros-8.c
@@ -0,0 +1,20 @@
+/* Test __GCC_IEC_559 and __GCC_IEC_559_COMPLEX macros values. */
+/* { dg-do preprocess } */
+/* { dg-options "-fcx-fortran-rules" } */
+
+#ifndef __GCC_IEC_559
+# error "__GCC_IEC_559 not defined"
+#endif
+#ifndef __GCC_IEC_559_COMPLEX
+# error "__GCC_IEC_559_COMPLEX not defined"
+#endif
+#if __GCC_IEC_559_COMPLEX > __GCC_IEC_559
+# error "__GCC_IEC_559_COMPLEX > __GCC_IEC_559"
+#endif
+#if __GCC_IEC_559_COMPLEX < 0
+# error "__GCC_IEC_559_COMPLEX < 0"
+#endif
+
+#if __GCC_IEC_559_COMPLEX != 0
+# error "__GCC_IEC_559_COMPLEX != 0 with -fcx-fortran-rules"
+#endif
diff --git a/gcc/testsuite/gcc.dg/iec-559-macros-9.c b/gcc/testsuite/gcc.dg/iec-559-macros-9.c
new file mode 100644
index 00000000000..6179a3bfe45
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/iec-559-macros-9.c
@@ -0,0 +1,23 @@
+/* Test __GCC_IEC_559 and __GCC_IEC_559_COMPLEX macros values. */
+/* { dg-do preprocess { target i?86-*-linux* x86_64-*-linux* powerpc*-*-linux* } } */
+/* { dg-options "-std=c11" } */
+
+#ifndef __GCC_IEC_559
+# error "__GCC_IEC_559 not defined"
+#endif
+#ifndef __GCC_IEC_559_COMPLEX
+# error "__GCC_IEC_559_COMPLEX not defined"
+#endif
+#if __GCC_IEC_559_COMPLEX > __GCC_IEC_559
+# error "__GCC_IEC_559_COMPLEX > __GCC_IEC_559"
+#endif
+#if __GCC_IEC_559_COMPLEX < 0
+# error "__GCC_IEC_559_COMPLEX < 0"
+#endif
+
+#if __GCC_IEC_559 < 2
+# error "__GCC_IEC_559 < 2"
+#endif
+#if __GCC_IEC_559_COMPLEX < 2
+# error "__GCC_IEC_559_COMPLEX < 2"
+#endif
diff --git a/gcc/testsuite/gcc.dg/ipa/pr58492.c b/gcc/testsuite/gcc.dg/ipa/pr58492.c
new file mode 100644
index 00000000000..79958d5640a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/ipa/pr58492.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fipa-pta" } */
+
+void f(int p, short q)
+{
+ f(0, 0);
+}
diff --git a/gcc/testsuite/gcc.dg/ivdep.c b/gcc/testsuite/gcc.dg/ivdep.c
new file mode 100644
index 00000000000..23d51de9fe3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/ivdep.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+
+/* PR other/33426 */
+
+void foo(int n, int *a, int *b, int *c, int *d, int *e) {
+ int i, j;
+#pragma GCC ivdep
+ for (i = 0; ; ++i) { /* { dg-error "missing loop condition in loop with 'GCC ivdep' pragma before ';' token" } */
+ a[i] = b[i] + c[i];
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/mismatch-decl-1.c b/gcc/testsuite/gcc.dg/mismatch-decl-1.c
new file mode 100644
index 00000000000..da4db0a57f0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/mismatch-decl-1.c
@@ -0,0 +1,22 @@
+/* This test assumes -fbuiltin and not -fansi to get "index" and "memchr" builtin DECLs. */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+/* The bug this is testing is that if a new decl conflicts with an
+ explicit decl, you don't get the "changes type of builtin" message,
+ but if there was *also* a builtin, you *also* don't get the
+ "previous declaration was here" message, leaving you with no clue
+ where the previous declaration came from. */
+
+extern char foo(int,int); /* { dg-message "previous declaration of 'foo' was here" } */
+extern char *index(const char *,int); /* { dg-message "previous declaration of 'index' was here" } */
+
+/* This changes the type of "index", which is both a builtin and an
+ explicit decl. */
+int index; /* { dg-error "redeclared as different kind of symbol" } */
+
+/* This changes the type of "memchr", which is only a builtin. */
+int memchr; /* { dg-warning "built-in function 'memchr' declared as non-function" } */
+
+/* This changes the type of "foo", which is only an explicit decl. */
+int foo; /* { dg-error "redeclared as different kind of symbol" } */
diff --git a/gcc/testsuite/gcc.dg/plugin/finish_unit_plugin.c b/gcc/testsuite/gcc.dg/plugin/finish_unit_plugin.c
index 26496a2e695..72d724063e4 100644
--- a/gcc/testsuite/gcc.dg/plugin/finish_unit_plugin.c
+++ b/gcc/testsuite/gcc.dg/plugin/finish_unit_plugin.c
@@ -6,6 +6,7 @@
#include "system.h"
#include "coretypes.h"
#include "tm.h"
+#include "tree.h"
#include "toplev.h"
#include "basic-block.h"
#include "gimple.h"
diff --git a/gcc/testsuite/gcc.dg/plugin/ggcplug.c b/gcc/testsuite/gcc.dg/plugin/ggcplug.c
index 3094b2ebb63..eb61ece4522 100644
--- a/gcc/testsuite/gcc.dg/plugin/ggcplug.c
+++ b/gcc/testsuite/gcc.dg/plugin/ggcplug.c
@@ -5,6 +5,7 @@
#include "system.h"
#include "coretypes.h"
#include "tm.h"
+#include "tree.h"
#include "toplev.h"
#include "basic-block.h"
#include "gimple.h"
diff --git a/gcc/testsuite/gcc.dg/plugin/one_time_plugin.c b/gcc/testsuite/gcc.dg/plugin/one_time_plugin.c
index c4dace5ab27..1e601a63c90 100644
--- a/gcc/testsuite/gcc.dg/plugin/one_time_plugin.c
+++ b/gcc/testsuite/gcc.dg/plugin/one_time_plugin.c
@@ -3,6 +3,7 @@
#include "gcc-plugin.h"
#include "system.h"
#include "coretypes.h"
+#include "tree.h"
#include "tm.h"
#include "toplev.h"
#include "gimple.h"
diff --git a/gcc/testsuite/gcc.dg/plugin/selfassign.c b/gcc/testsuite/gcc.dg/plugin/selfassign.c
index 7235089c7d3..5331f792cb2 100644
--- a/gcc/testsuite/gcc.dg/plugin/selfassign.c
+++ b/gcc/testsuite/gcc.dg/plugin/selfassign.c
@@ -7,6 +7,7 @@
#include "system.h"
#include "coretypes.h"
#include "tm.h"
+#include "tree.h"
#include "toplev.h"
#include "basic-block.h"
#include "gimple.h"
diff --git a/gcc/testsuite/gcc.dg/plugin/start_unit_plugin.c b/gcc/testsuite/gcc.dg/plugin/start_unit_plugin.c
index 852ab88bfc7..257aad85a8a 100644
--- a/gcc/testsuite/gcc.dg/plugin/start_unit_plugin.c
+++ b/gcc/testsuite/gcc.dg/plugin/start_unit_plugin.c
@@ -10,6 +10,7 @@
#include "system.h"
#include "coretypes.h"
#include "tm.h"
+#include "tree.h"
#include "toplev.h"
#include "basic-block.h"
#include "gimple.h"
diff --git a/gcc/testsuite/gcc.dg/pr19340.c b/gcc/testsuite/gcc.dg/pr19340.c
index 4a665910a91..c75d35d1d01 100644
--- a/gcc/testsuite/gcc.dg/pr19340.c
+++ b/gcc/testsuite/gcc.dg/pr19340.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-O1 -fschedule-insns2 -fsched2-use-superblocks" } */
-/* { dg-skip-if "No scheduling" { mmix-*-* cris-*-* crisv32-*-* fido-*-* m68k-*-* m32c-*-* avr-*-* moxie-*-* } { "*" } { "" } } */
+/* { dg-require-effective-target scheduling } */
extern double f (double x);
diff --git a/gcc/testsuite/gcc.dg/pr30286.c b/gcc/testsuite/gcc.dg/pr30286.c
index 9ec49b4231a..d35eacd807a 100644
--- a/gcc/testsuite/gcc.dg/pr30286.c
+++ b/gcc/testsuite/gcc.dg/pr30286.c
@@ -1,6 +1,7 @@
/* PR middle-end/30286 */
/* { dg-do run } */
/* { dg-options "-O2 -ftrapv" } */
+/* { dg-require-effective-target trapping } */
extern void abort (void);
struct S { struct S *s; };
diff --git a/gcc/testsuite/gcc.dg/pr38364.c b/gcc/testsuite/gcc.dg/pr38364.c
index 23f72de74ee..6b22e9d78e9 100644
--- a/gcc/testsuite/gcc.dg/pr38364.c
+++ b/gcc/testsuite/gcc.dg/pr38364.c
@@ -1,6 +1,7 @@
/* PR middle-end/38364 */
/* { dg-do run } */
/* { dg-options "-O2 -ftrapv" } */
+/* { dg-require-effective-target trapping } */
extern void abort (void);
diff --git a/gcc/testsuite/gcc.dg/pr38984.c b/gcc/testsuite/gcc.dg/pr38984.c
index 11f1e7f211a..0c031805ea8 100644
--- a/gcc/testsuite/gcc.dg/pr38984.c
+++ b/gcc/testsuite/gcc.dg/pr38984.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fno-delete-null-pointer-checks -fdump-tree-optimized" }
+/* { dg-options "-O2 -fno-delete-null-pointer-checks -fdump-tree-optimized -fno-isolate-erroneous-paths" }
* */
int f(int *p)
diff --git a/gcc/testsuite/gcc.dg/pr57518.c b/gcc/testsuite/gcc.dg/pr57518.c
index 47e819c3e44..8eb714d8c55 100644
--- a/gcc/testsuite/gcc.dg/pr57518.c
+++ b/gcc/testsuite/gcc.dg/pr57518.c
@@ -1,8 +1,8 @@
-/* PR rtl-optimization/57130 */
+/* PR rtl-optimization/57518 */
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-rtl-ira" } */
-/* { dg-final { scan-rtl-dump-not "REG_EQUIV\[^\n\]*mem\[^\n\]*\"ip\"" "ira" } } */
+/* { dg-final { scan-rtl-dump-not "REG_EQUIV\[^\n\]*mem\[^\n\]*\"ip\".*subreg" "ira" } } */
char ip[10];
int total;
diff --git a/gcc/testsuite/gcc.dg/pr58463.c b/gcc/testsuite/gcc.dg/pr58463.c
new file mode 100644
index 00000000000..e2b44119347
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr58463.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-tree-ealias-details -O2" } */
+
+typedef struct
+{
+ int data16;
+}
+list_data;
+void
+fn1 (list_data * p1)
+{
+ p1->data16 = p1->data16 & 1 & p1->data16 >> 1;
+}
+
+/* { dg-final { cleanup-tree-dump "ealias" } } */
diff --git a/gcc/testsuite/gcc.dg/pr58805.c b/gcc/testsuite/gcc.dg/pr58805.c
new file mode 100644
index 00000000000..dda0e4bdf4b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr58805.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-tail-merge -fdump-tree-pre" } */
+
+/* Type that matches the 'p' constraint. */
+#define TYPE void *
+
+static inline
+void bar (TYPE *r)
+{
+ TYPE t;
+ __asm__ ("" : "=&p" (t), "=p" (*r));
+}
+
+void
+foo (int n, TYPE *x, TYPE *y)
+{
+ if (n == 0)
+ bar (x);
+ else
+ bar (y);
+}
+
+/* { dg-final { scan-tree-dump-times "__asm__" 2 "pre"} } */
+/* { dg-final { cleanup-tree-dump "pre" } } */
diff --git a/gcc/testsuite/gcc.dg/pr58981.c b/gcc/testsuite/gcc.dg/pr58981.c
new file mode 100644
index 00000000000..1c8293e4985
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr58981.c
@@ -0,0 +1,55 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+/* { dg-additional-options "-minline-all-stringops" { target { i?86-*-* x86_64-*-* } } } */
+
+extern void abort (void);
+
+#define MAX_OFFSET (sizeof (long long))
+#define MAX_COPY (8 * sizeof (long long))
+#define MAX_EXTRA (sizeof (long long))
+
+#define MAX_LENGTH (MAX_OFFSET + MAX_COPY + MAX_EXTRA)
+
+static union {
+ char buf[MAX_LENGTH];
+ long long align_int;
+ long double align_fp;
+} u;
+
+char A[MAX_LENGTH];
+
+int
+main ()
+{
+ int off, len, i;
+ char *p, *q;
+
+ for (i = 0; i < MAX_LENGTH; i++)
+ A[i] = 'A';
+
+ for (off = 0; off < MAX_OFFSET; off++)
+ for (len = 1; len < MAX_COPY; len++)
+ {
+ for (i = 0; i < MAX_LENGTH; i++)
+ u.buf[i] = 'a';
+
+ p = __builtin_memcpy (u.buf + off, A, len);
+ if (p != u.buf + off)
+ abort ();
+
+ q = u.buf;
+ for (i = 0; i < off; i++, q++)
+ if (*q != 'a')
+ abort ();
+
+ for (i = 0; i < len; i++, q++)
+ if (*q != 'A')
+ abort ();
+
+ for (i = 0; i < MAX_EXTRA; i++, q++)
+ if (*q != 'a')
+ abort ();
+ }
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/superblock.c b/gcc/testsuite/gcc.dg/superblock.c
index 2b9aedfdac4..272d161f058 100644
--- a/gcc/testsuite/gcc.dg/superblock.c
+++ b/gcc/testsuite/gcc.dg/superblock.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fno-asynchronous-unwind-tables -fsched2-use-superblocks -fdump-rtl-sched2 -fdump-rtl-bbro" } */
+/* { dg-require-effective-target scheduling } */
typedef int aligned __attribute__ ((aligned (64)));
extern void abort (void);
diff --git a/gcc/testsuite/gcc.dg/tls/pr42894.c b/gcc/testsuite/gcc.dg/tls/pr42894.c
index c3bd76c91c4..2875b494c05 100644
--- a/gcc/testsuite/gcc.dg/tls/pr42894.c
+++ b/gcc/testsuite/gcc.dg/tls/pr42894.c
@@ -1,6 +1,5 @@
/* PR target/42894 */
/* { dg-do compile } */
-/* { dg-options "-march=armv5te -mthumb" { target arm*-*-* } } */
/* { dg-require-effective-target tls } */
extern __thread int t;
diff --git a/gcc/testsuite/gcc.dg/torture/builtin-complex-1.c b/gcc/testsuite/gcc.dg/torture/builtin-complex-1.c
index 20dc4c48a28..0d26c9cc707 100644
--- a/gcc/testsuite/gcc.dg/torture/builtin-complex-1.c
+++ b/gcc/testsuite/gcc.dg/torture/builtin-complex-1.c
@@ -1,6 +1,6 @@
/* Test __builtin_complex semantics. */
/* { dg-do run } */
-/* { dg-options "-std=c1x -pedantic-errors" } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
/* { dg-add-options ieee } */
extern void exit (int);
diff --git a/gcc/testsuite/gcc.dg/torture/builtin-self.c b/gcc/testsuite/gcc.dg/torture/builtin-self.c
new file mode 100644
index 00000000000..6d1719f7517
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/builtin-self.c
@@ -0,0 +1,10 @@
+/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
+/* Check that we can use this idiom to define out-of-line copies of built-in
+ functions. This is used by libgcc/sync.c, for example. */
+void __sync_synchronize (void)
+{
+ __sync_synchronize ();
+}
+/* { dg-final { scan-assembler "__sync_synchronize" } } */
+/* { dg-final { scan-assembler "\t(lock|mfence)" } } */
+/* { dg-final { scan-assembler-not "\tcall" } } */
diff --git a/gcc/testsuite/gcc.dg/torture/c99-contract-1.c b/gcc/testsuite/gcc.dg/torture/c99-contract-1.c
new file mode 100644
index 00000000000..60230830807
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/c99-contract-1.c
@@ -0,0 +1,21 @@
+/* Test floating-point contraction occurs only within source language
+ expressions. */
+/* { dg-do run } */
+/* { dg-options "-std=c99 -pedantic-errors" } */
+
+extern void abort (void);
+extern void exit (int);
+
+volatile float a = 1 + 0x1p-23f, b = 1 - 0x1p-23f, c = -1;
+
+int
+main (void)
+{
+ float av = a, bv = b, cv = c;
+ float p = av * bv;
+ float r = p + cv;
+ if (r == 0)
+ exit (0);
+ else
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.dg/torture/float128-cmp-invalid.c b/gcc/testsuite/gcc.dg/torture/float128-cmp-invalid.c
new file mode 100644
index 00000000000..53ef7ed01b3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/float128-cmp-invalid.c
@@ -0,0 +1,18 @@
+/* Test for "invalid" exceptions from __float128 comparisons. */
+/* { dg-do run { target i?86-*-* x86_64-*-* ia64-*-* } } */
+/* { dg-options "" } */
+
+#include <fenv.h>
+#include <stdlib.h>
+
+int
+main (void)
+{
+ volatile __float128 a = __builtin_nan (""), b = 0;
+ volatile int r = a < b;
+ if (!fetestexcept (FE_INVALID))
+ abort ();
+ if (r)
+ abort ();
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/torture/float128-div-underflow.c b/gcc/testsuite/gcc.dg/torture/float128-div-underflow.c
new file mode 100644
index 00000000000..43d350f4e44
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/float128-div-underflow.c
@@ -0,0 +1,18 @@
+/* Test for spurious underflow from __float128 division. */
+/* { dg-do run { target i?86-*-* x86_64-*-* ia64-*-* } } */
+/* { dg-options "" } */
+
+#include <fenv.h>
+#include <stdlib.h>
+
+int
+main (void)
+{
+ volatile __float128 a = 0x0.fffp-16382q, b = 0x0.fffp0q, c;
+ c = a / b;
+ if (fetestexcept (FE_UNDERFLOW | FE_INEXACT))
+ abort ();
+ if (c != 0x1p-16382q)
+ abort ();
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/torture/float128-extend-nan.c b/gcc/testsuite/gcc.dg/torture/float128-extend-nan.c
new file mode 100644
index 00000000000..1942d80f190
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/float128-extend-nan.c
@@ -0,0 +1,22 @@
+/* Test extensions to __float128 quiet signaling NaNs. */
+/* { dg-do run { target i?86-*-* x86_64-*-* ia64-*-* } } */
+/* { dg-options "-fsignaling-nans" } */
+
+#include <fenv.h>
+#include <float.h>
+#include <stdlib.h>
+
+volatile long double a = __builtin_nansl ("");
+
+int
+main (void)
+{
+#if LDBL_MANT_DIG < 113
+ volatile __float128 r = a;
+ feclearexcept (FE_INVALID);
+ r += 1;
+ if (fetestexcept (FE_INVALID))
+ abort ();
+#endif
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-float128-timode-3.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float128-timode-3.c
new file mode 100644
index 00000000000..944494d9bcc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float128-timode-3.c
@@ -0,0 +1,23 @@
+/* Test for correct rounding of conversions from __int128 to
+ __float128. */
+/* { dg-do run { target i?86-*-* x86_64-*-* ia64-*-* } } */
+/* { dg-require-effective-target int128 } */
+/* { dg-options "-frounding-math" } */
+
+#include <fenv.h>
+#include <stdlib.h>
+
+int
+main (void)
+{
+ volatile unsigned long long h = -1ULL;
+ volatile unsigned __int128 u128 = (((unsigned __int128) h) << 64) | h;
+ volatile __int128 s128 = u128 >> 1;
+ fesetround (FE_TOWARDZERO);
+ __float128 ru = u128, rs = s128;
+ if (ru != 0x1.ffffffffffffffffffffffffffffp127q)
+ abort ();
+ if (rs != 0x1.ffffffffffffffffffffffffffffp126q)
+ abort ();
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr51244-21.c b/gcc/testsuite/gcc.dg/torture/pr51244-21.c
new file mode 100644
index 00000000000..fbb02db28e0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr51244-21.c
@@ -0,0 +1,75 @@
+/* { dg-do run } */
+#include <assert.h>
+
+static inline int
+blk_oversized_queue (int* q)
+{
+ if (q[2])
+ return q[1] != 0;
+ return q[0] == 0;
+}
+
+int __attribute__ ((noinline))
+get_request (int* q, int rw)
+{
+ if (blk_oversized_queue (q))
+ {
+ if ((rw == 1) || (rw == 0))
+ return -33;
+
+ return 0;
+ }
+
+ return -100;
+}
+
+int main (void)
+{
+ int x[3];
+ int r;
+
+ x[0] = 0; x[1] = 1; x[2] = 1;
+ r = get_request (x, 0);
+ assert (r == -33);
+
+ r = get_request (x, 1);
+ assert (r == -33);
+
+ r = get_request (x, 2);
+ assert (r == 0);
+
+
+ x[0] = 0; x[1] = 0; x[2] = 1;
+ r = get_request (x, 0);
+ assert (r == -100);
+
+ r = get_request (x, 1);
+ assert (r == -100);
+
+ r = get_request (x, 2);
+ assert (r == -100);
+
+
+ x[0] = 0; x[1] = 0; x[2] = 0;
+ r = get_request (x, 0);
+ assert (r == -33);
+
+ r = get_request (x, 1);
+ assert (r == -33);
+
+ r = get_request (x, 2);
+ assert (r == 0);
+
+
+ x[0] = 0; x[1] = 0; x[2] = 0;
+ r = get_request (x, 0);
+ assert (r == -33);
+
+ r = get_request (x, 1);
+ assert (r == -33);
+
+ r = get_request (x, 2);
+ assert (r == 0);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr57748-1.c b/gcc/testsuite/gcc.dg/torture/pr57748-1.c
new file mode 100644
index 00000000000..dc0fcdc3b85
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr57748-1.c
@@ -0,0 +1,49 @@
+/* PR middle-end/57748 */
+/* { dg-do run } */
+/* ICE in expand_assignment:
+ misalignp == true, !MEM_P (to_rtx), offset != 0,
+ => gcc_assert (TREE_CODE (offset) == INTEGER_CST) */
+
+#include <stdlib.h>
+
+extern void abort (void);
+
+typedef long long V
+ __attribute__ ((vector_size (2 * sizeof (long long)), may_alias));
+
+typedef struct S { V a; V b[0]; } P __attribute__((aligned (1)));
+
+struct __attribute__((packed)) T { char c; P s; };
+
+void __attribute__((noinline, noclone))
+check (struct T *t)
+{
+ if (t->s.b[0][0] != 3 || t->s.b[0][1] != 4)
+ abort ();
+}
+
+int __attribute__((noinline, noclone))
+get_i (void)
+{
+ return 0;
+}
+
+void __attribute__((noinline, noclone))
+foo (P *p)
+{
+ V a = { 3, 4 };
+ int i = get_i ();
+ p->b[i] = a;
+}
+
+int
+main ()
+{
+ struct T *t = (struct T *) calloc (128, 1);
+
+ foo (&t->s);
+ check (t);
+
+ free (t);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr57748-2.c b/gcc/testsuite/gcc.dg/torture/pr57748-2.c
new file mode 100644
index 00000000000..4e3b4b88468
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr57748-2.c
@@ -0,0 +1,43 @@
+/* PR middle-end/57748 */
+/* { dg-do run } */
+/* wrong code in expand_assignment:
+ misalignp == true, !MEM_P (to_rtx),
+ offset == 0, bitpos >= GET_MODE_PRECISION,
+ => result = NULL. */
+
+#include <stdlib.h>
+
+extern void abort (void);
+
+typedef long long V
+ __attribute__ ((vector_size (2 * sizeof (long long)), may_alias));
+
+typedef struct S { V a; V b[0]; } P __attribute__((aligned (1)));
+
+struct __attribute__((packed)) T { char c; P s; };
+
+void __attribute__((noinline, noclone))
+check (struct T *t)
+{
+ if (t->s.b[0][0] != 3 || t->s.b[0][1] != 4)
+ abort ();
+}
+
+void __attribute__((noinline, noclone))
+foo (P *p)
+{
+ V a = { 3, 4 };
+ p->b[0] = a;
+}
+
+int
+main ()
+{
+ struct T *t = (struct T *) calloc (128, 1);
+
+ foo (&t->s);
+ check (t);
+
+ free (t);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr58143-1.c b/gcc/testsuite/gcc.dg/torture/pr58143-1.c
new file mode 100644
index 00000000000..855515edb97
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr58143-1.c
@@ -0,0 +1,51 @@
+/* { dg-do run } */
+/* { dg-additional-options "-fstrict-overflow" } */
+
+extern void abort (void);
+
+int a, b, c, d, e, f, g, h = 1, i;
+
+int foo (int p)
+{
+ return p < 0 && a < - __INT_MAX__ - 1 - p ? 0 : 1;
+}
+
+int *bar ()
+{
+ int j;
+ i = h ? 0 : 1 % h;
+ for (j = 0; j < 1; j++)
+ for (d = 0; d; d++)
+ for (e = 1; e;)
+ return 0;
+ return 0;
+}
+
+int baz ()
+{
+ for (; b >= 0; b--)
+ for (c = 1; c >= 0; c--)
+ {
+ int *k = &c;
+ for (;;)
+ {
+ for (f = 0; f < 1; f++)
+ {
+ g = foo (*k);
+ bar ();
+ }
+ if (*k)
+ break;
+ return 0;
+ }
+ }
+ return 0;
+}
+
+int main ()
+{
+ baz ();
+ if (b != 0)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr58143-2.c b/gcc/testsuite/gcc.dg/torture/pr58143-2.c
new file mode 100644
index 00000000000..dd0dae1efe0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr58143-2.c
@@ -0,0 +1,34 @@
+/* { dg-do run } */
+/* { dg-additional-options "-fstrict-overflow" } */
+
+int a, b, d, e, f, *g, h, i;
+volatile int c;
+
+char foo (unsigned char p)
+{
+ return p + 1;
+}
+
+int bar ()
+{
+ for (h = 0; h < 3; h = foo (h))
+ {
+ c;
+ for (f = 0; f < 1; f++)
+ {
+ i = a && 0 < -__INT_MAX__ - h ? 0 : 1;
+ if (e)
+ for (; d;)
+ b = 0;
+ else
+ g = 0;
+ }
+ }
+ return 0;
+}
+
+int main ()
+{
+ bar ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr58143-3.c b/gcc/testsuite/gcc.dg/torture/pr58143-3.c
new file mode 100644
index 00000000000..23ae9cd39ce
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr58143-3.c
@@ -0,0 +1,18 @@
+/* { dg-do run } */
+/* { dg-additional-options "-fstrict-overflow" } */
+
+int a, b, c, d, e;
+
+int
+main ()
+{
+ for (b = 4; b > -30; b--)
+ for (; c;)
+ for (;;)
+ {
+ e = a > __INT_MAX__ - b;
+ if (d)
+ break;
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr58539.c b/gcc/testsuite/gcc.dg/torture/pr58539.c
new file mode 100644
index 00000000000..a016150f18e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr58539.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-g" } */
+
+int a, b;
+
+extern void baz (int);
+
+int foo (int p)
+{
+ return p ? p : 1;
+}
+
+void bar ()
+{
+ int *c = &a, *d = &a;
+ for (b = 0; b < 12; b++)
+ *d |= 1;
+ foo (*c);
+ baz (*c && 1);
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr58553.c b/gcc/testsuite/gcc.dg/torture/pr58553.c
new file mode 100644
index 00000000000..542bf3f1018
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr58553.c
@@ -0,0 +1,28 @@
+/* { dg-do run } */
+
+#define MAX_LENGTH 96
+#define SEQUENCE_LENGTH 31
+
+static struct {
+ char buf[MAX_LENGTH + 1];
+} u1, u2;
+
+extern void abort (void);
+
+int main ()
+{
+ int i;
+ char c;
+
+ for (i = 0, c = 'A'; i < MAX_LENGTH; i++, c++)
+ {
+ u1.buf[i] = 'a';
+ if (c >= 'A' + SEQUENCE_LENGTH)
+ c = 'A';
+ u2.buf[i] = c;
+ }
+ if (u1.buf[MAX_LENGTH] != '\0')
+ abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr58554.c b/gcc/testsuite/gcc.dg/torture/pr58554.c
new file mode 100644
index 00000000000..269171ae941
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr58554.c
@@ -0,0 +1,20 @@
+/* { dg-do run } */
+
+extern void abort (void);
+void __attribute__((noinline,noclone))
+clear_board(unsigned char *board, int board_size)
+{
+ int k;
+ for (k = 0; k < 421; k++)
+ if (k < board_size )
+ board[k] = 3;
+}
+int main()
+{
+ unsigned char board[421];
+ board[420] = 1;
+ clear_board (board, 420);
+ if (board[420] != 1)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr58626.c b/gcc/testsuite/gcc.dg/torture/pr58626.c
new file mode 100644
index 00000000000..1416384b7a6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr58626.c
@@ -0,0 +1,20 @@
+/* { dg-do run } */
+
+extern void abort (void);
+
+int a[8][6] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
+int b;
+
+int main(void)
+{
+ for (b = 0; b <= 1; b++) {
+ a[1][3] = 0;
+ int c;
+ for (c = 0; c <= 1; c++) {
+ a[c + 1][b] = a[c + 2][b];
+ }
+ }
+ if (a[1][1] != 1)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr58670.c b/gcc/testsuite/gcc.dg/torture/pr58670.c
new file mode 100644
index 00000000000..ba9fce71f9e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr58670.c
@@ -0,0 +1,47 @@
+/* PR middle-end/58670 */
+/* { dg-do run { target i?86-*-* x86_64-*-* } } */
+
+#if defined (__i386__) || defined (__x86_64__)
+#define ASM_STR "btsl $1, %0; jc %l[lab]"
+#endif
+
+__attribute__((noinline, noclone)) int
+foo (int a, int b)
+{
+ if (a)
+ return -3;
+#ifdef ASM_STR
+ asm volatile goto (ASM_STR : : "m" (b) : "memory" : lab);
+ return 0;
+lab:
+#endif
+ return 0;
+}
+
+int
+bar (int a, int b)
+{
+ if (a)
+ return -3;
+#ifdef ASM_STR
+ asm volatile goto (ASM_STR : : "m" (b) : "memory" : lab);
+ return 0;
+lab:
+#endif
+ return 0;
+}
+
+int
+main ()
+{
+ if (foo (1, 0) != -3
+ || foo (0, 3) != 0
+ || foo (1, 0) != -3
+ || foo (0, 0) != 0
+ || bar (1, 0) != -3
+ || bar (0, 3) != 0
+ || bar (1, 0) != -3
+ || bar (0, 0) != 0)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr58779.c b/gcc/testsuite/gcc.dg/torture/pr58779.c
new file mode 100644
index 00000000000..b0c0c869513
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr58779.c
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+
+int a, c;
+
+int main ()
+{
+ int e = -1;
+ short d = (c <= 0) ^ e;
+ if ((unsigned int) a - (a || d) <= (unsigned int) a)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr58830.c b/gcc/testsuite/gcc.dg/torture/pr58830.c
new file mode 100644
index 00000000000..8081f8b2c27
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr58830.c
@@ -0,0 +1,42 @@
+/* { dg-do run } */
+/* { dg-additional-options "-ftree-pre -ftree-partial-pre" } */
+
+extern void abort (void);
+
+int b, c, d, f, g, h, i, j[6], *l = &b, *m, n, *o, r;
+char k;
+
+static int
+foo ()
+{
+ char *p = &k;
+
+ for (; d; d++)
+ if (i)
+ h = 0;
+ else
+ h = c || (r = 0);
+
+ for (f = 0; f < 2; f++)
+ {
+ unsigned int q;
+ *l = 0;
+ if (n)
+ *m = g;
+ if (g)
+ o = 0;
+ for (q = -8; q >= 5; q++)
+ (*p)--;
+ }
+
+ return 0;
+}
+
+int
+main ()
+{
+ foo ();
+ if (j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[0]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] ^ (k & 15)] != 0)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr58941.c b/gcc/testsuite/gcc.dg/torture/pr58941.c
new file mode 100644
index 00000000000..c0eea073165
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr58941.c
@@ -0,0 +1,33 @@
+/* { dg-do run } */
+
+extern void abort (void);
+
+typedef struct {
+ int msgLength;
+ unsigned char data[1000];
+} SMsg;
+
+typedef struct {
+ int dummy;
+ int d[0];
+} SData;
+
+int condition = 3;
+
+int main()
+{
+ SMsg msg;
+ SData *pData = (SData*)(msg.data);
+ unsigned int i = 0;
+ for (i = 0; i < 1; i++)
+ {
+ pData->d[i] = 0;
+ if(condition & 1)
+ pData->d[i] |= 0x55;
+ if(condition & 2)
+ pData->d[i] |= 0xaa;
+ }
+ if (pData->d[0] != 0xff)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr58955-1.c b/gcc/testsuite/gcc.dg/torture/pr58955-1.c
new file mode 100644
index 00000000000..a79f42f0b38
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr58955-1.c
@@ -0,0 +1,20 @@
+/* { dg-do run } */
+
+extern void abort (void);
+
+int a, b, c, d[4] = { 0, 0, 0, 1 };
+
+int
+main ()
+{
+ for (; a < 4; a++)
+ {
+ int e = d[a];
+ for (c = 1; c < 1; c++);
+ b = e;
+ d[a] = 0;
+ }
+ if (b != 1)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr58955-2.c b/gcc/testsuite/gcc.dg/torture/pr58955-2.c
new file mode 100644
index 00000000000..a43860e9b02
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr58955-2.c
@@ -0,0 +1,18 @@
+/* { dg-do run } */
+
+extern void abort (void);
+
+int a, b[10];
+
+int
+main ()
+{
+ for (; a < 2; a++)
+ {
+ b[a] = 1;
+ b[a + 1] = 0;
+ }
+ if (b[1] != 1)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr59038.c b/gcc/testsuite/gcc.dg/torture/pr59038.c
new file mode 100644
index 00000000000..1694eca4300
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr59038.c
@@ -0,0 +1,25 @@
+/* { dg-do run } */
+
+extern void abort (void);
+
+unsigned char first_ones_8bit[256];
+unsigned char connected_passed[256];
+
+int
+main ()
+{
+ int i, j;
+ for (i=0;i<256;i++){
+ connected_passed[i]=0;
+ first_ones_8bit[i]=0;
+ for (j=7;j>0;j--){
+ if ((i & (3<<(7-j))) == (3<<(7-j))){
+ connected_passed[i]=j;
+ break;
+ }
+ }
+ }
+ if (connected_passed[3] != 7)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr59047.c b/gcc/testsuite/gcc.dg/torture/pr59047.c
new file mode 100644
index 00000000000..fcedfcba870
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr59047.c
@@ -0,0 +1,39 @@
+/* { dg-do run } */
+
+extern void abort (void);
+
+struct
+{
+ int f0;
+ int f1:1;
+ int f2:2;
+} a = {0, 0, 1};
+
+int b, c, *d, e, f;
+
+int
+fn1 ()
+{
+ for (; b < 1; ++b)
+ {
+ for (e = 0; e < 1; e = 1)
+ {
+ int **g = &d;
+ *g = &c;
+ }
+ *d = 0;
+ f = a.f1;
+ if (f)
+ return 0;
+ }
+ return 0;
+}
+
+int
+main ()
+{
+ fn1 ();
+ if (b != 1)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/restrict-2.c b/gcc/testsuite/gcc.dg/torture/restrict-2.c
new file mode 100644
index 00000000000..ec51ade6163
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/restrict-2.c
@@ -0,0 +1,27 @@
+/* { dg-do run } */
+
+extern void abort (void);
+
+static inline void
+foo (int * p)
+{
+ int * __restrict pr = p;
+ *pr = 1;
+}
+
+int __attribute__((noinline,noclone))
+bar (int *q)
+{
+ int * __restrict qr = q;
+ *qr = 0;
+ foo (qr);
+ return *qr;
+}
+
+int main()
+{
+ int i;
+ if (bar (&i) != 1)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/restrict-3.c b/gcc/testsuite/gcc.dg/torture/restrict-3.c
new file mode 100644
index 00000000000..d815b8076e6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/restrict-3.c
@@ -0,0 +1,26 @@
+/* { dg-do run } */
+
+extern void abort (void);
+
+static inline void
+foo (int * __restrict pr)
+{
+ *pr = 1;
+}
+
+int __attribute__((noinline,noclone))
+bar (int *q)
+{
+ int * __restrict qr = q;
+ *qr = 0;
+ foo (qr);
+ return *qr;
+}
+
+int main()
+{
+ int i;
+ if (bar (&i) != 1)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/restrict-4.c b/gcc/testsuite/gcc.dg/torture/restrict-4.c
new file mode 100644
index 00000000000..52994d48b2e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/restrict-4.c
@@ -0,0 +1,26 @@
+/* { dg-do run } */
+
+extern void abort (void);
+
+static inline void
+foo (int * p)
+{
+ int * __restrict pr = p;
+ *pr = 1;
+}
+
+int __attribute__((noinline,noclone))
+bar (int * __restrict qr)
+{
+ *qr = 0;
+ foo (qr);
+ return *qr;
+}
+
+int main()
+{
+ int i;
+ if (bar (&i) != 1)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/restrict-5.c b/gcc/testsuite/gcc.dg/torture/restrict-5.c
new file mode 100644
index 00000000000..233a9075f96
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/restrict-5.c
@@ -0,0 +1,25 @@
+/* { dg-do run } */
+
+extern void abort (void);
+
+static inline void
+foo (int * __restrict pr)
+{
+ *pr = 1;
+}
+
+int __attribute__((noinline,noclone))
+bar (int * __restrict qr)
+{
+ *qr = 0;
+ foo (qr);
+ return *qr;
+}
+
+int main()
+{
+ int i;
+ if (bar (&i) != 1)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-prof/time-profiler-1.c b/gcc/testsuite/gcc.dg/tree-prof/time-profiler-1.c
new file mode 100644
index 00000000000..c61b534a250
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-prof/time-profiler-1.c
@@ -0,0 +1,22 @@
+/* { dg-options "-O2 -fdump-ipa-profile" } */
+
+__attribute__ ((noinline))
+int foo()
+{
+ return 0;
+}
+
+__attribute__ ((noinline))
+int bar()
+{
+ return 1;
+}
+
+int main ()
+{
+ return foo ();
+}
+/* { dg-final-use { scan-ipa-dump-times "Read tp_first_run: 0" 1 "profile"} } */
+/* { dg-final-use { scan-ipa-dump-times "Read tp_first_run: 1" 1 "profile"} } */
+/* { dg-final-use { scan-ipa-dump-times "Read tp_first_run: 2" 1 "profile"} } */
+/* { dg-final-use { cleanup-ipa-dump "profile" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-prof/time-profiler-2.c b/gcc/testsuite/gcc.dg/tree-prof/time-profiler-2.c
new file mode 100644
index 00000000000..04113419753
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-prof/time-profiler-2.c
@@ -0,0 +1,50 @@
+/* { dg-options "-O2 -fdump-ipa-profile" } */
+
+#include <unistd.h>
+
+__attribute__ ((noinline))
+int foo()
+{
+ return 1;
+}
+
+__attribute__ ((noinline))
+int bar()
+{
+ return 1;
+}
+
+__attribute__ ((noinline))
+int baz()
+{
+ return 1;
+}
+
+__attribute__ ((noinline))
+int baz1()
+{
+ return 1;
+}
+
+int main ()
+{
+ int f = fork();
+ int r = 0;
+
+ foo ();
+
+ if (f < 0)
+ return 1; /* Fork failed. */
+
+ if(f == 0) /* Child process. */
+ r = bar() - foo();
+ else /* Parent process. */
+ r = foo() - foo();
+
+ return r;
+}
+/* { dg-final-use { scan-ipa-dump-times "Read tp_first_run: 0" 2 "profile"} } */
+/* { dg-final-use { scan-ipa-dump-times "Read tp_first_run: 1" 1 "profile"} } */
+/* { dg-final-use { scan-ipa-dump-times "Read tp_first_run: 2" 1 "profile"} } */
+/* { dg-final-use { scan-ipa-dump-times "Read tp_first_run: 3" 1 "profile"} } */
+/* { dg-final-use { cleanup-ipa-dump "profile" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-prof/tree-prof.exp b/gcc/testsuite/gcc.dg/tree-prof/tree-prof.exp
index 1f50eb3221b..141959aae8a 100644
--- a/gcc/testsuite/gcc.dg/tree-prof/tree-prof.exp
+++ b/gcc/testsuite/gcc.dg/tree-prof/tree-prof.exp
@@ -15,7 +15,7 @@
# <http://www.gnu.org/licenses/>.
# Test the functionality of programs compiled with profile-directed block
-# ordering using -fprofile-generate followed by -fbranch-use.
+# ordering using -fprofile-generate followed by -fprofile-use.
load_lib target-supports.exp
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-23.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-23.c
new file mode 100644
index 00000000000..9d0dd32061f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-23.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+typedef struct A { int i; double d; } A;
+
+void f1 (const char *c)
+{
+ A *s = (A*) __builtin_malloc (sizeof (A));
+ double *p = &s->d;
+ s->i = 42;
+ __builtin_memcpy (p, c, sizeof (double));
+ int j = s->i;
+ if (j != 42) __builtin_abort();
+}
+
+/* { dg-final { scan-tree-dump-not "abort" "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
+
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-24.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-24.c
new file mode 100644
index 00000000000..0edd51f85cd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-24.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+void f (const char *c, int *i)
+{
+ *i = 42;
+ __builtin_memcpy (i + 1, c, sizeof (int));
+ if (*i != 42) __builtin_abort();
+}
+
+extern void keepit ();
+void g (const char *c, int *i)
+{
+ *i = 33;
+ __builtin_memcpy (i - 1, c, 3 * sizeof (int));
+ if (*i != 33) keepit();
+}
+
+/* { dg-final { scan-tree-dump-not "abort" "optimized" } } */
+/* { dg-final { scan-tree-dump "keepit" "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
+
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-25.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-25.c
new file mode 100644
index 00000000000..f5705d03cd9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-25.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -fdump-tree-optimized" } */
+
+void f (long *p) {
+ *p = 42;
+ p[4] = 42;
+ __builtin_free (p);
+}
+
+/* { dg-final { scan-tree-dump-not "= 42" "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
+
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-26.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-26.c
new file mode 100644
index 00000000000..a1eb8f7d0a8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-26.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+void f (const char *c, int *i)
+{
+ *i = 42;
+ __builtin_memcpy (i - 1, c, sizeof (int));
+ if (*i != 42) __builtin_abort();
+}
+
+/* { dg-final { scan-tree-dump-not "abort" "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
+
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-27.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-27.c
new file mode 100644
index 00000000000..91c737eae25
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-27.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -fdump-tree-optimized" } */
+
+void f (long *p) {
+ *p = 42;
+ p[4] = 42;
+ __builtin_memset (p, 0, 100);
+}
+
+/* { dg-final { scan-tree-dump-not "= 42" "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/coalesce-2.c b/gcc/testsuite/gcc.dg/tree-ssa/coalesce-2.c
new file mode 100644
index 00000000000..56c5ccccc7f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/coalesce-2.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-rtl-expand-details" } */
+
+float total = 0.2;
+void foo(int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ total += i;
+}
+
+/* Verify that out-of-ssa coalescing did its job by verifying there are not
+ any partition copies inserted. */
+
+/* { dg-final { scan-rtl-dump-not "partition copy" "expand"} } */
+/* { dg-final { cleanup-rtl-dump "expand" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-28.c b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-28.c
index a64987bfdfa..06b406fc690 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-28.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-28.c
@@ -1,4 +1,4 @@
-/* { dg-do compile { target { ! "m68k*-*-* mmix*-*-* mep*-*-* bfin*-*-* v850*-*-* picochip*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-*"} } } */
+/* { dg-do compile { target { ! "m68k*-*-* mmix*-*-* mep*-*-* bfin*-*-* v850*-*-* picochip*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-* arc*-*-*"} } } */
/* { dg-options "-O2 -fdump-tree-forwprop1" } */
extern char *frob (void);
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-11.c b/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-11.c
index be3a49dfaca..e5019c01259 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-11.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-11.c
@@ -1,6 +1,6 @@
/* { dg-do run { target vect_cmdline_needed } } */
-/* { dg-options "-O2 -ftree-vectorize -fwrapv -fdump-tree-vect-details" } */
-/* { dg-options "-O2 -ftree-vectorize -fwrapv -fdump-tree-vect-details -mno-sse" { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-options "-O2 -ftree-vectorize -fwrapv -fdump-tree-vect-details -fvect-cost-model=dynamic" } */
+/* { dg-options "-O2 -ftree-vectorize -fwrapv -fdump-tree-vect-details -fvect-cost-model=dynamic -mno-sse" { target { i?86-*-* x86_64-*-* } } } */
#include <stdlib.h>
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-11a.c b/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-11a.c
index 7af5fd07238..8344fdf59f3 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-11a.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-11a.c
@@ -1,6 +1,6 @@
/* { dg-do run { target vect_cmdline_needed } } */
-/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-details" } */
-/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-details -mno-sse" { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-details -fvect-cost-model=dynamic" } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-details -fvect-cost-model=dynamic -mno-sse" { target { i?86-*-* x86_64-*-* } } } */
#include <stdlib.h>
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-2.c b/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-2.c
index ad6f4b5af53..0888ecf59a3 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-2.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-2.c
@@ -1,6 +1,6 @@
/* { dg-do run { target vect_cmdline_needed } } */
-/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-details" } */
-/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-details -mno-sse" { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-details -fvect-cost-model=dynamic" } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-details -fvect-cost-model=dynamic -mno-sse" { target { i?86-*-* x86_64-*-* } } } */
#include <stdlib.h>
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-25.c b/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-25.c
index c96ee001e06..85bbc0b76f3 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-25.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-25.c
@@ -1,6 +1,6 @@
/* { dg-do run { target vect_cmdline_needed } } */
-/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-details" } */
-/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-details -mno-sse" { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-details -fvect-cost-model=dynamic" } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-details -fvect-cost-model=dynamic -mno-sse" { target { i?86-*-* x86_64-*-* } } } */
#include <stdlib.h>
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-26.c b/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-26.c
index f14bf837afa..dadeb073d3a 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-26.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-26.c
@@ -1,6 +1,6 @@
/* { dg-do run { target vect_cmdline_needed } } */
-/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-details" } */
-/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-details -mno-sse" { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-details -fvect-cost-model=dynamic" } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-details -fvect-cost-model=dynamic -mno-sse" { target { i?86-*-* x86_64-*-* } } } */
#include <stdlib.h>
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-28.c b/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-28.c
index d90520eff67..f314b28d3d4 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-28.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-28.c
@@ -1,6 +1,6 @@
/* { dg-do run { target vect_cmdline_needed } } */
-/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-details" } */
-/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-details -mno-sse" { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-details -fvect-cost-model=dynamic" } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-details -fvect-cost-model=dynamic -mno-sse" { target { i?86-*-* x86_64-*-* } } } */
#include <stdlib.h>
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ipa-split-5.c b/gcc/testsuite/gcc.dg/tree-ssa/ipa-split-5.c
index abf1e07e2b8..8fc1244e1ad 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ipa-split-5.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ipa-split-5.c
@@ -1,5 +1,5 @@
/* { dg-do compile { target nonpic } } */
-/* { dg-options "-O3 -fdump-tree-fnsplit -fdump-tree-optimized" } */
+/* { dg-options "-O3 -fdump-tree-fnsplit -fdump-tree-optimized --param=builtin-expect-probability=100" } */
struct a {int a,b;};
struct a make_me_big (int a);
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ipa-split-6.c b/gcc/testsuite/gcc.dg/tree-ssa/ipa-split-6.c
index 12070fa3362..fcdf79d7027 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ipa-split-6.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ipa-split-6.c
@@ -1,6 +1,6 @@
/* PR tree-optimization/52019 */
/* { dg-do compile } */
-/* { dg-options "-O3 -fno-tree-sra -fdump-tree-fnsplit -fdump-tree-optimized" } */
+/* { dg-options "-O3 -fno-tree-sra -fdump-tree-fnsplit -fdump-tree-optimized --param=builtin-expect-probability=100" } */
#include "ipa-split-5.c"
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/isolate-1.c b/gcc/testsuite/gcc.dg/tree-ssa/isolate-1.c
new file mode 100644
index 00000000000..6b779b4a4bc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/isolate-1.c
@@ -0,0 +1,58 @@
+
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-isolate-paths" } */
+
+
+struct demangle_component
+{
+
+ int type;
+ int zzz;
+
+};
+
+
+struct d_info
+{
+ struct demangle_component *comps;
+ int next_comp;
+ int num_comps;
+};
+
+
+static struct demangle_component *
+d_make_empty (struct d_info *di)
+{
+ struct demangle_component *p;
+
+ if (di->next_comp >= di->num_comps)
+ return ((void *)0);
+ p = &di->comps[di->next_comp];
+ return p;
+}
+
+
+
+struct demangle_component *
+d_type (struct d_info *di)
+{
+ struct demangle_component *ret;
+ ret = d_make_empty (di);
+ ret->type = 42;
+ ret->zzz = -1;
+ return ret;
+}
+
+/* We're testing two aspects of isolation here. First that isolation
+ occurs, second that if we have two null dereferences in a block that
+ that we delete everything from the first dereferece to the end of the
+ block, regardless of which comes first in the immediate use iterator. */
+/* { dg-final { scan-tree-dump-times "__builtin_trap" 1 "isolate-paths"} } */
+/* { dg-final { scan-tree-dump-times "->type" 1 "isolate-paths"} } */
+/* { dg-final { scan-tree-dump-times "->zzz" 1 "isolate-paths"} } */
+/* { dg-final { cleanup-tree-dump "isolate-paths" } } */
+
+
+
+
+
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/isolate-2.c b/gcc/testsuite/gcc.dg/tree-ssa/isolate-2.c
new file mode 100644
index 00000000000..290b44c5bd4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/isolate-2.c
@@ -0,0 +1,43 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-isolate-paths -fdump-tree-phicprop1" } */
+
+
+int z;
+int y;
+
+int * foo(int a) __attribute__((returns_nonnull));
+int * bar(void) __attribute__((returns_nonnull));
+
+int *
+foo(int a)
+
+{
+ switch (a)
+ {
+ case 0:
+ return &z;
+ default:
+ return (int *)0;
+ }
+}
+
+
+int *
+bar (void)
+{
+ return 0;
+}
+
+/* We testing that the path isolation code can take advantage of the
+ returns non-null attribute to isolate a path where NULL flows into
+ a return statement. We test this twice, once where the NULL flows
+ from a PHI, the second with an explicit return 0 in the IL.
+
+ We also verify that after isolation phi-cprop simplifies the
+ return statement so that it returns &z directly.
+/* { dg-final { scan-tree-dump-times "__builtin_trap" 2 "isolate-paths"} } */
+/* { dg-final { scan-tree-dump-times "return &z;" 1 "phicprop1"} } */
+/* { dg-final { cleanup-tree-dump "isolate-paths" } } */
+/* { dg-final { cleanup-tree-dump "phicprop1" } } */
+
+
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/isolate-3.c b/gcc/testsuite/gcc.dg/tree-ssa/isolate-3.c
new file mode 100644
index 00000000000..7dddd8062c0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/isolate-3.c
@@ -0,0 +1,65 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-isolate-paths" } */
+
+
+typedef long unsigned int size_t;
+extern void *memset (void *__s, int __c, size_t __n)
+ __attribute__ ((__nothrow__, __leaf__)) __attribute__ ((__nonnull__ (1)));
+struct rtx_def;
+typedef struct rtx_def *rtx;
+typedef struct VEC_rtx_base
+
+{
+ unsigned num;
+ unsigned alloc;
+ rtx vec[1];
+} VEC_rtx_base;
+static __inline__ rtx *
+VEC_rtx_base_address (VEC_rtx_base * vec_)
+{
+ return vec_ ? vec_->vec : 0;
+}
+typedef struct VEC_rtx_gc
+{
+ VEC_rtx_base base;
+} VEC_rtx_gc;
+
+static __inline__ void
+VEC_rtx_gc_safe_grow (VEC_rtx_gc ** vec_, int size_, const char *file_,
+ unsigned line_, const char *function_)
+{
+ ((*vec_) ? &(*vec_)->base : 0)->num = size_;
+}
+
+static __inline__ void
+VEC_rtx_gc_safe_grow_cleared (VEC_rtx_gc ** vec_, int size_,
+ const char *file_, unsigned line_,
+ const char *function_, int oldsize)
+{
+ VEC_rtx_gc_safe_grow (vec_, size_, file_, line_, function_);
+ memset (&(VEC_rtx_base_address ((*vec_) ? &(*vec_)->base : 0))[oldsize], 0,
+ sizeof (rtx) * (size_ - oldsize));
+}
+
+static VEC_rtx_gc *reg_base_value;
+void
+init_alias_analysis (void)
+{
+ unsigned int maxreg = max_reg_num ();
+ (VEC_rtx_gc_safe_grow_cleared
+ (&(reg_base_value), maxreg, "../../../gcc-4.6.0/gcc/alias.c", 2755,
+ __FUNCTION__, arf ()));
+}
+
+
+
+/* This is an example of how a NULL pointer dereference can show up
+ without a PHI. Note VEC_rtx_gcc_safe_grow. If an earlier pass
+ (such as VRP) isolates the NULL path for some reason or another
+ we end up with an explicit NULL dereference in the IL. Yes, it
+ started with a PHI, but by the time the path isolation code runs
+ its explicit in the IL. */
+/* { dg-final { scan-tree-dump-times "__builtin_trap" 1 "isolate-paths"} } */
+/* { dg-final { cleanup-tree-dump "isolate-paths" } } */
+
+
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/isolate-4.c b/gcc/testsuite/gcc.dg/tree-ssa/isolate-4.c
new file mode 100644
index 00000000000..6937d25580a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/isolate-4.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-isolate-paths -fdump-tree-phicprop1" } */
+
+
+extern void foo(void *) __attribute__ ((__nonnull__ (1)));
+
+int z;
+
+void
+com (int a)
+{
+ foo (a == 42 ? &z : (void *) 0);
+}
+
+void
+bar (void)
+{
+ foo ((void *)0);
+}
+
+/* We testing that the path isolation code can take advantage of the
+ returns non-null attribute to isolate a path where NULL flows into
+ a return statement.
+
+ We also verify that after isolation phi-cprop simplifies the
+ return statement so that it returns &z directly.
+/* { dg-final { scan-tree-dump-times "__builtin_trap" 2 "isolate-paths"} } */
+/* { dg-final { scan-tree-dump-times "foo .&z.;" 1 "phicprop1"} } */
+/* { dg-final { cleanup-tree-dump "isolate-paths" } } */
+/* { dg-final { cleanup-tree-dump "phicprop1" } } */
+
+
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ivopt_infer_2.c b/gcc/testsuite/gcc.dg/tree-ssa/ivopt_infer_2.c
index 4c5a54b9af4..c0f6398d827 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ivopt_infer_2.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ivopt_infer_2.c
@@ -7,7 +7,8 @@
extern char a[];
-/* Can not infer loop iteration from array -- exit test can not be replaced. */
+/* Can not infer loop iteration from array -- exit test can not be
+ replaced by the array address. */
void foo (unsigned int i_width, TYPE dst)
{
unsigned long long i = 0;
@@ -21,5 +22,5 @@ void foo (unsigned int i_width, TYPE dst)
}
}
-/* { dg-final { scan-tree-dump-times "Replacing" 0 "ivopts"} } */
+/* { dg-final { scan-tree-dump-times "\[^:\]*if \\(.*j_\[0-9\]+.*\\)" 1 "ivopts"} } */
/* { dg-final { cleanup-tree-dump "ivopts" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ivopt_mult_3.c b/gcc/testsuite/gcc.dg/tree-ssa/ivopt_mult_3.c
index dc78a43f73f..25ae845f71e 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ivopt_mult_3.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ivopt_mult_3.c
@@ -18,5 +18,5 @@ long foo(long* p, long* p2, int N1, int N2)
return s;
}
-/* { dg-final { scan-tree-dump-times "Replacing" 1 "ivopts"} } */
+/* { dg-final { scan-tree-dump-times "Replacing exit test: if \\(.*p2.*\\)" 1 "ivopts"} } */
/* { dg-final { cleanup-tree-dump "ivopts" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ldist-11.c b/gcc/testsuite/gcc.dg/tree-ssa/ldist-11.c
index e55a1b64ecc..902c25b1553 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ldist-11.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ldist-11.c
@@ -28,6 +28,6 @@ void foo (int * __restrict__ ia,
*/
}
-/* { dg-final { scan-tree-dump-times "distributed: split to 2 loops" 1 "ldist" } } */
+/* { dg-final { scan-tree-dump-times "distributed: split to 1 loops and 1 library calls" 1 "ldist" } } */
/* { dg-final { scan-tree-dump-times "generated memset zero" 1 "ldist" } } */
/* { dg-final { cleanup-tree-dump "ldist" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ldist-17.c b/gcc/testsuite/gcc.dg/tree-ssa/ldist-17.c
index 5c280b3f0c4..bbf54db2be9 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ldist-17.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ldist-17.c
@@ -45,6 +45,6 @@ mad_synth_mute (struct mad_synth *synth)
return;
}
-/* { dg-final { scan-tree-dump "distributed: split to 4" "ldist" } } */
+/* { dg-final { scan-tree-dump "distributed: split to 0 loops and 4 library calls" "ldist" } } */
/* { dg-final { scan-tree-dump-times "generated memset zero" 4 "ldist" } } */
/* { dg-final { cleanup-tree-dump "ldist" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ldist-23.c b/gcc/testsuite/gcc.dg/tree-ssa/ldist-23.c
new file mode 100644
index 00000000000..0e7609bdb57
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ldist-23.c
@@ -0,0 +1,34 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -fdump-tree-ldist-details" } */
+
+extern void abort (void);
+
+int a[128], b[128], c[128], d[128];
+
+void __attribute__((noinline,noclone))
+foo (void)
+{
+ int i;
+ for (i = 0; i < 128; ++i)
+ {
+ a[i] = a[i] + 1;
+ b[i] = d[i];
+ c[i] = a[i] / d[i];
+ }
+}
+int main()
+{
+ int i;
+ for (i = 0; i < 128; ++i)
+ a[i] = i;
+ for (i = 0; i < 128; ++i)
+ d[i] = 1;
+ foo ();
+ if (c[0] != 1)
+ abort ();
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump "split to 1 loops and 1 library call" "ldist" } } */
+/* { dg-final { scan-tree-dump "generated memcpy" "ldist" } } */
+/* { dg-final { cleanup-tree-dump "ldist" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ldist-pr45948.c b/gcc/testsuite/gcc.dg/tree-ssa/ldist-pr45948.c
index da3c7b626f9..f25a9106430 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ldist-pr45948.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ldist-pr45948.c
@@ -18,6 +18,6 @@ foo (int i, int n)
/* We should apply loop distribution and generate 2 memset (0). */
-/* { dg-final { scan-tree-dump "distributed: split to 2" "ldist" } } */
+/* { dg-final { scan-tree-dump "distributed: split to 0 loops and 2 library calls" "ldist" } } */
/* { dg-final { scan-tree-dump-times "generated memset zero" 2 "ldist" } } */
/* { dg-final { cleanup-tree-dump "ldist" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-2.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-2.c
index 3426827783c..f43a6d8eb77 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/loop-2.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-2.c
@@ -27,7 +27,7 @@ void xxx(void)
/* { dg-final { scan-tree-dump-times " \\* \[^\\n\\r\]*=" 0 "optimized" } } */
/* { dg-final { scan-tree-dump-times "\[^\\n\\r\]*= \\* " 0 "optimized" } } */
-/* { dg-final { scan-tree-dump-times "MEM" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "MEM\\\[base" 1 "optimized" } } */
/* 17 * iter should be strength reduced. */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-39.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-39.c
new file mode 100644
index 00000000000..1f6bba42fd4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-39.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-sccp-details" } */
+
+int
+foo (unsigned int n)
+{
+ int i, r = 1;
+ if (n > 0)
+ {
+ asm ("");
+ if (n < 10)
+ {
+ asm ("");
+ do
+ {
+ --n;
+ r *= 2;
+ }
+ while (n > 0);
+ }
+ }
+ return r + n;
+}
+
+/* { dg-final { scan-tree-dump "# of iterations \[^\n\r]*, bounded by 8" "sccp" } } */
+/* { dg-final { cleanup-tree-dump "sccp" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-11.c b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-11.c
new file mode 100644
index 00000000000..7c83007e7f1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-11.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -fdump-tree-optimized" } */
+
+int f(int a, int b, int c)
+{
+ if (a == 0 && b > c)
+ return 0;
+ return a;
+}
+
+int g(int a, int b, int c)
+{
+ if (a == 42 && b > c)
+ return 42;
+ return a;
+}
+
+int h(int a, int b, int c, int d)
+{
+ if (a == d && b > c)
+ return d;
+ return a;
+}
+/* { dg-final { scan-tree-dump-times "if" 0 "optimized"} } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-9.c b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-9.c
index dccea7b0506..a224788f5d8 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-9.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-9.c
@@ -2,13 +2,14 @@
/* { dg-options "-O -fdump-tree-optimized" } */
int g(int,int);
+int h(int);
int f(int t, int c)
{
int d = 0;
int e = 0;
if (t)
{
- d = c+1;
+ d = h(c);
e = t;
}
else d = 0, e = 0;
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr20318.c b/gcc/testsuite/gcc.dg/tree-ssa/pr20318.c
new file mode 100644
index 00000000000..1b302aedefa
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr20318.c
@@ -0,0 +1,19 @@
+/* { dg-do compile { target { ! keeps_null_pointer_checks } } } */
+/* { dg-options "-O2 -fdump-tree-original -fdump-tree-vrp1" } */
+
+extern int* f(int) __attribute__((returns_nonnull));
+extern void eliminate ();
+void g () {
+ if (f (2) == 0)
+ eliminate ();
+}
+void h () {
+ int *p = f (2);
+ if (p == 0)
+ eliminate ();
+}
+
+/* { dg-final { scan-tree-dump-times "== 0" 1 "original" } } */
+/* { dg-final { scan-tree-dump-times "Folding predicate\[^\\n\]*to 0" 1 "vrp1" } } */
+/* { dg-final { cleanup-tree-dump "original" } } */
+/* { dg-final { cleanup-tree-dump "vrp1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr58480.c b/gcc/testsuite/gcc.dg/tree-ssa/pr58480.c
new file mode 100644
index 00000000000..a42edf973cb
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr58480.c
@@ -0,0 +1,19 @@
+/* { dg-do compile { target { ! keeps_null_pointer_checks } } } */
+/* { dg-options "-O2 -fdump-tree-vrp1" } */
+
+extern void eliminate (void);
+extern void* f1 (void *a, void *b) __attribute__((nonnull));
+extern void* f2 (void *a, void *b) __attribute__((nonnull(2)));
+void g1 (void*p, void*q){
+ f1 (q, p);
+ if (p == 0)
+ eliminate ();
+}
+void g2 (void*p, void*q){
+ f2 (q, p);
+ if (p == 0)
+ eliminate ();
+}
+
+/* { dg-final { scan-tree-dump-times "Folding predicate\[^\\n\]*to 0" 2 "vrp1" } } */
+/* { dg-final { cleanup-tree-dump "vrp1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr58958.c b/gcc/testsuite/gcc.dg/tree-ssa/pr58958.c
new file mode 100644
index 00000000000..faf377fb87e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr58958.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+double a[10];
+int f(int n){
+ a[3]=9;
+ __builtin_memset(&a[n],3,sizeof(double));
+ return a[3]==9;
+}
+
+/* { dg-final { scan-tree-dump " == 9" "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/predcom-6.c b/gcc/testsuite/gcc.dg/tree-ssa/predcom-6.c
new file mode 100644
index 00000000000..96d9bf93ef7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/predcom-6.c
@@ -0,0 +1,13 @@
+/* { dg-do run } */
+
+int a, c, e[5][2];
+unsigned int d;
+
+int
+main ()
+{
+ for (d = 0; d < 2; d++)
+ if (a ? 0 : e[c + 3][d] & e[c + 4][d])
+ break;
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/predcom-7.c b/gcc/testsuite/gcc.dg/tree-ssa/predcom-7.c
new file mode 100644
index 00000000000..e7ae87ccc7a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/predcom-7.c
@@ -0,0 +1,18 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -fdump-tree-pcom-details" } */
+
+int b, f, d[5][2];
+unsigned int c;
+
+int
+main ()
+{
+ for (c = 0; c < 2; c++)
+ if (d[b + 3][c] & d[b + 4][c])
+ if (f)
+ break;
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump "Executing predictive commoning" "pcom" } } */
+/* { dg-final { cleanup-tree-dump "pcom" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-28.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-28.c
index 3d10b49ccaf..2e999860148 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-28.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-28.c
@@ -1,5 +1,5 @@
/* { dg-do run} */
-/* { dg-options "-O2 -fdump-tree-reassoc1-details" } */
+/* { dg-options "-O2" } */
#define LENGTH 4
void abort (void);
@@ -30,8 +30,3 @@ int main() {
abort ();
return 0;
}
-
-/* Verify one stmt has been moved to another BB to ensure correct dependences. */
-/* { dg-final { scan-tree-dump-times "to a different BB" 1 "reassoc1"} }*/
-/* { dg-final { scan-tree-dump-times "within same BB" 2 "reassoc1"} }*/
-/* { dg-final { cleanup-tree-dump "reassoc1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-32.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-32.c
new file mode 100644
index 00000000000..303b3f32bd9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-32.c
@@ -0,0 +1,29 @@
+/* { dg-do run { target { ! "m68k*-*-* mmix*-*-* mep*-*-* bfin*-*-* v850*-*-* picochip*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-*"} } } */
+
+/* { dg-options "-O2 -fno-inline -fdump-tree-reassoc1-details" } */
+/* { dg-additional-options "-mbranch-cost=2" { target avr-*-* } } */
+
+
+int test (int a, int b, int c)
+{
+ if ( a == 10 || a == 12 || a == 26)
+ return b;
+ else
+ return c;
+}
+
+int main ()
+{
+ if (test (10, 20, 30) != 20)
+ __builtin_abort ();
+ if (test (12, 20, 30) != 20)
+ __builtin_abort ();
+ if (test (26, 20, 30) != 20)
+ __builtin_abort ();
+ if (test (30, 20, 30) != 30)
+ __builtin_abort ();
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "Optimizing range tests .* 26" 1 "reassoc1"} }*/
+/* { dg-final { cleanup-tree-dump "reassoc1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-33.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-33.c
new file mode 100644
index 00000000000..bb27daa8c14
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-33.c
@@ -0,0 +1,27 @@
+/* { dg-do run { target { ! "m68k*-*-* mmix*-*-* mep*-*-* bfin*-*-* v850*-*-* picochip*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-*"} } } */
+
+/* { dg-options "-O2 -fno-inline -fdump-tree-reassoc1-details" } */
+/* { dg-additional-options "-mbranch-cost=2" { target avr-*-* } } */
+
+int test (int a, int b, int c)
+{
+ if (a == 43 || a == 75 || a == 44 || a == 78
+ || a == 77 || a == 46 || a == 76 || a == 45)
+ return b;
+ else
+ return c;
+}
+
+int
+main ()
+{
+ volatile int n43, n47, n75, n79;
+ n43 = 43; n47 = n43 + 4; n75 = 75; n79 = n75 + 4;
+ int i;
+ for (i = -10; i <= 100; i++)
+ if (test (i, 2, 3) != 3 - ((i >= n43 && i < n47) || (i >= n75 && i < n79)))
+ __builtin_abort ();
+ return 0;
+}
+/* { dg-final { scan-tree-dump-times "Optimizing range tests" 3 "reassoc1"} }*/
+/* { dg-final { cleanup-tree-dump "reassoc1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-34.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-34.c
new file mode 100644
index 00000000000..156e1824222
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-34.c
@@ -0,0 +1,24 @@
+/* { dg-do run { target { ! "m68k*-*-* mmix*-*-* mep*-*-* bfin*-*-* v850*-*-* picochip*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-*"} } } */
+
+/* { dg-options "-O2 -fno-inline -fdump-tree-reassoc1-details" } */
+/* { dg-additional-options "-mbranch-cost=2" { target avr-*-* } } */
+
+int test (int a, int b, int c)
+{
+ if (a == 10 || a == 12)
+ return b;
+ else
+ return c;
+}
+int main ()
+{
+ if (test (10, 20, 30) != 20)
+ __builtin_abort ();
+ if (test (12, 20, 30) != 20)
+ __builtin_abort ();
+ if (test (26, 20, 30) != 30)
+ __builtin_abort ();
+ return 0;
+}
+/* { dg-final { scan-tree-dump-times "Optimizing range tests" 1 "reassoc1"} }*/
+/* { dg-final { cleanup-tree-dump "reassoc1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-35.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-35.c
new file mode 100644
index 00000000000..c486b783dce
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-35.c
@@ -0,0 +1,26 @@
+/* { dg-do run { target { ! "m68k*-*-* mmix*-*-* mep*-*-* bfin*-*-* v850*-*-* picochip*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-*"} } } */
+
+/* { dg-options "-O2 -fno-inline -fdump-tree-reassoc1-details" } */
+/* { dg-additional-options "-mbranch-cost=2" { target avr-*-* } } */
+
+int test (unsigned int a, int b, int c)
+{
+ if ((a - 43) <= 3 || (a - 75) <= 3)
+ return b;
+ else
+ return c;
+}
+int
+main ()
+{
+ volatile int n43, n47, n75, n79;
+ n43 = 43; n47 = n43 + 4; n75 = 75; n79 = n75 + 4;
+ int i;
+ for (i = -10; i <= 100; i++)
+ if (test (i, 2, 3) != 3 - ((i >= n43 && i < n47) || (i >= n75 && i < n79)))
+ __builtin_abort ();
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "Optimizing range tests" 1 "reassoc1"} }*/
+/* { dg-final { cleanup-tree-dump "reassoc1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-36.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-36.c
new file mode 100644
index 00000000000..930dbe289fb
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-36.c
@@ -0,0 +1,25 @@
+/* { dg-do run { target { ! "m68k*-*-* mmix*-*-* mep*-*-* bfin*-*-* v850*-*-* picochip*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-*"} } } */
+
+/* { dg-options "-O2 -fno-inline -fdump-tree-reassoc1-details" } */
+/* { dg-additional-options "-mbranch-cost=2" { target avr-*-* } } */
+
+int test (int a, int b, int c)
+{
+ if (a != 10 && a != 12)
+ return b;
+ else
+ return c;
+}
+int main ()
+{
+ if (test (10, 20, 30) != 30)
+ __builtin_abort ();
+ if (test (12, 20, 30) != 30)
+ __builtin_abort ();
+ if (test (26, 20, 30) != 20)
+ __builtin_abort ();
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "Optimizing range tests" 1 "reassoc1"} }*/
+/* { dg-final { cleanup-tree-dump "reassoc1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/slsr-40.c b/gcc/testsuite/gcc.dg/tree-ssa/slsr-40.c
new file mode 100644
index 00000000000..72726a3aa3b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/slsr-40.c
@@ -0,0 +1,27 @@
+/* Verify straight-line strength reduction for array
+ subscripting.
+
+ elems[n-1] is reduced to elems + n * 4 + 0xffffffff * 4, only when
+ pointers are of the same size as that of int (assuming 4 bytes). */
+
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+struct data
+{
+ unsigned long elms[1];
+} gData;
+
+void __attribute__((noinline))
+foo (struct data *dst, unsigned int n)
+{
+ dst->elms[n - 1] &= 1;
+}
+
+int
+main ()
+{
+ foo (&gData, 1);
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-3.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-3.c
deleted file mode 100644
index c2efd15eb33..00000000000
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-3.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-dom1-details -fno-short-enums" } */
-
-extern void abort (void) __attribute__ ((__noreturn__));
-union tree_node;
-typedef union tree_node *tree;
-enum tree_code
-{
- VAR_DECL,
- SSA_NAME,
- MAX_TREE_CODES
-};
-extern unsigned char tree_contains_struct[MAX_TREE_CODES][64];
-struct tree_base
-{
- enum tree_code code:16;
-};
-enum tree_node_structure_enum
-{
- TS_DECL_COMMON
-};
-struct tree_ssa_name
-{
- tree var;
-};
-union tree_node
-{
- struct tree_base base;
- struct tree_ssa_name ssa_name;
-};
-long
-expand_one_var (tree var, unsigned char toplevel, unsigned char really_expand)
-{
- tree origvar = var;
- var = var->ssa_name.var;
- if (((enum tree_code) (origvar)->base.code) == SSA_NAME
- && !((var->base.code != VAR_DECL)))
- abort ();
- if ((var->base.code) != VAR_DECL && ((origvar)->base.code) != SSA_NAME)
- ;
- else if (tree_contains_struct[(var->base.code)][(TS_DECL_COMMON)] != 1)
- abort ();
-}
-/* We should thread the jump, through an intermediate block. */
-/* { dg-final { scan-tree-dump-times "Threaded" 1 "dom1"} } */
-/* { dg-final { scan-tree-dump-times "Registering jump thread .through joiner block.: \\(.*\\); \\(.*\\); \\(.*\\);" 1 "dom1"} } */
-
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-4.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-4.c
index e97719f9c13..fec3075618f 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-4.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-4.c
@@ -61,7 +61,7 @@ bitmap_ior_and_compl (bitmap dst, const_bitmap a, const_bitmap b,
zero. */
/* ARM Cortex-M0 defined LOGICAL_OP_NON_SHORT_CIRCUIT to false,
so skip below test. */
-/* { dg-final { scan-tree-dump-times "Threaded" 3 "dom1" { target { ! { { mips*-*-* avr-*-* } || { arm_cortex_m && arm_thumb1 } } } } } } */
+/* { dg-final { scan-tree-dump-times "Threaded" 3 "dom1" { target { ! { { mips*-*-* avr-*-* arc*-*-* } || { arm_cortex_m && arm_thumb1 } } } } } } */
/* MIPS defines LOGICAL_OP_NON_SHORT_CIRCUIT to 0, so we split both
"a_elt || b_elt" and "b_elt && kill_elt" into two conditions each,
rather than using "(var1 != 0) op (var2 != 0)". Also, as on other targets,
@@ -81,8 +81,9 @@ bitmap_ior_and_compl (bitmap dst, const_bitmap a, const_bitmap b,
-> "kill_elt->indx == b_elt->indx" in the second condition,
skipping the known-true "b_elt && kill_elt" in the second
condition. */
+/* Likewise for arc. */
/* For avr, BRANCH_COST is by default 0, so the default
LOGICAL_OP_NON_SHORT_CIRCUIT definition also computes as 0. */
-/* { dg-final { scan-tree-dump-times "Threaded" 6 "dom1" { target mips*-*-* avr-*-* } } } */
+/* { dg-final { scan-tree-dump-times "Threaded" 6 "dom1" { target mips*-*-* avr-*-* arc*-*-* } } } */
/* { dg-final { cleanup-tree-dump "dom1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-ccmp-1.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-ccmp-1.c
new file mode 100644
index 00000000000..efc8a7133c9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-ccmp-1.c
@@ -0,0 +1,14 @@
+/* { dg-do compile { target { ! "m68k*-*-* mmix*-*-* mep*-*-* bfin*-*-* v850*-*-* picochip*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-* arc*-*-*"} } } */
+
+/* { dg-options "-O2 -g -fdump-tree-optimized" } */
+/* { dg-additional-options "-mbranch-cost=2" { target avr-*-* } } */
+
+int t (int a, int b)
+{
+ if (a > 0)
+ if (b > 0)
+ return 0;
+ return 1;
+}
+/* { dg-final { scan-tree-dump "\&" "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-ccmp-2.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-ccmp-2.c
new file mode 100644
index 00000000000..3273bcc5f38
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-ccmp-2.c
@@ -0,0 +1,17 @@
+/* { dg-do compile { target { ! "m68k*-*-* mmix*-*-* mep*-*-* bfin*-*-* v850*-*-* picochip*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-*"} } } */
+
+/* { dg-options "-O2 -g -fdump-tree-optimized" } */
+/* { dg-additional-options "-mbranch-cost=2" { target avr-*-* } } */
+
+int t (int a, int b)
+{
+ if (a > 0)
+ goto L1;
+ if (b > 0)
+ goto L1;
+ return 0;
+L1:
+ return 1;
+}
+/* { dg-final { scan-tree-dump "\|" "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-ccmp-3.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-ccmp-3.c
new file mode 100644
index 00000000000..500cb011708
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-ccmp-3.c
@@ -0,0 +1,20 @@
+/* { dg-do compile { target { ! "m68k*-*-* mmix*-*-* mep*-*-* bfin*-*-* v850*-*-* picochip*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-*"} } } */
+
+/* { dg-options "-O2 -g -fdump-tree-optimized" } */
+/* { dg-additional-options "-mbranch-cost=2" { target avr-*-* } } */
+
+int t (int a, int b)
+{
+ if (a > 0)
+ goto L1;
+ else
+ goto L2;
+L1:
+ if (b > 0)
+ goto L2;
+ return 5;
+L2:
+ return 6;
+}
+/* { dg-final { scan-tree-dump "\|" "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-ccmp-4.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-ccmp-4.c
new file mode 100644
index 00000000000..3be2310e9b5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-ccmp-4.c
@@ -0,0 +1,18 @@
+/* { dg-do compile { target { ! "m68k*-*-* mmix*-*-* mep*-*-* bfin*-*-* v850*-*-* picochip*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-* arc*-*-*"} } } */
+
+/* { dg-options "-O2 -g -fdump-tree-optimized" } */
+/* { dg-additional-options "-mbranch-cost=2" { target avr-*-* } } */
+
+int t (int a, int b)
+{
+ if (a > 0)
+ goto L1;
+ if (b > 0)
+ goto L2;
+L1:
+ return 0;
+L2:
+ return 1;
+}
+/* { dg-final { scan-tree-dump "\&" "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-ccmp-5.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-ccmp-5.c
new file mode 100644
index 00000000000..c22a0e04c11
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-ccmp-5.c
@@ -0,0 +1,13 @@
+/* { dg-do compile { target { ! "m68k*-*-* mmix*-*-* mep*-*-* bfin*-*-* v850*-*-* picochip*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-* arc*-*-*"} } } */
+
+/* { dg-options "-O2 -g -fdump-tree-optimized" } */
+/* { dg-additional-options "-mbranch-cost=2" { target avr-*-* } } */
+
+int t (int a, int b, int c)
+{
+ if (a > 0 && b > 0 && c > 0)
+ return 0;
+ return 1;
+}
+/* { dg-final { scan-tree-dump-times "\&" 2 "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-ccmp-6.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-ccmp-6.c
new file mode 100644
index 00000000000..aa0970dee7f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-ccmp-6.c
@@ -0,0 +1,13 @@
+/* { dg-do compile { target { ! "m68k*-*-* mmix*-*-* mep*-*-* bfin*-*-* v850*-*-* picochip*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-* arc*-*-*"} } } */
+
+/* { dg-options "-O2 -g -fdump-tree-optimized" } */
+/* { dg-additional-options "-mbranch-cost=2" { target avr-*-* } } */
+
+int t (int a, int b, int c)
+{
+ if (a > 0 || b > 0 || c > 0)
+ return 0;
+ return 1;
+}
+/* { dg-final { scan-tree-dump-times "\\|" 2 "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-31.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-31.c
new file mode 100644
index 00000000000..2094de4ca89
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-31.c
@@ -0,0 +1,47 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-pre" } */
+
+typedef struct {
+ unsigned int key;
+} S;
+typedef struct s1 {
+ unsigned int key;
+ unsigned int bits;
+ struct s1 *left, *right;
+}S1;
+extern S a[1024];
+static inline int bar( S* p, S1* n )
+{
+ S1 *curr;
+ S1 *next;
+
+ if ( n->left == n )
+ return (int)(p->key == n->key);
+
+ curr = n;
+ next = n->left;
+
+ while (curr->bits > next->bits ) {
+ curr = next;
+ if (p->key & (1 << curr->bits))
+ next = curr->right;
+ else
+ next = curr->left;
+ }
+
+ return (int)(p->key == next->key);
+
+}
+
+int foo (S1 *root, int N)
+{
+ volatile int r;
+ int i,j;
+ for (i=0; i<N; i++)
+ for (j=0;j<1024; j++)
+ r = bar(&a[j], root);
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "key" 4 "pre" } } */
+/* { dg-final { cleanup-tree-dump "pre" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp47.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp47.c
index d8c5841eb58..74b520b5f54 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/vrp47.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp47.c
@@ -1,9 +1,9 @@
-/* Skip on MIPS, where LOGICAL_OP_NON_SHORT_CIRCUIT inhibits the setcc
+/* Skip on MIPS/ARC, where LOGICAL_OP_NON_SHORT_CIRCUIT inhibits the setcc
optimizations that expose the VRP opportunity. */
/* Skip on S/390 and avr. Lower values in BRANCH_COST lead to two conditional
jumps when evaluating an && condition. VRP is not able to optimize
this. */
-/* { dg-do compile { target { ! "mips*-*-* s390*-*-* avr-*-* mn10300-*-*" } } } */
+/* { dg-do compile { target { ! "mips*-*-* arc*-*-* s390*-*-* avr-*-* mn10300-*-*" } } } */
/* { dg-options "-O2 -fdump-tree-vrp1 -fdump-tree-dom1 -fdump-tree-vrp2" } */
/* { dg-additional-options "-march=i586" { target { { i?86-*-* x86_64-*-* } && ia32 } } } */
/* Skip on ARM Cortex-M0, where LOGICAL_OP_NON_SHORT_CIRCUIT is set to false,
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp87.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp87.c
index 7339823f480..aa85191419e 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/vrp87.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp87.c
@@ -1,4 +1,4 @@
-/* { dg-do compile { target { ! "m68k*-*-* mmix*-*-* mep*-*-* bfin*-*-* v850*-*-* picochip*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-*"} } } */
+/* { dg-do compile { target { ! "m68k*-*-* mmix*-*-* mep*-*-* bfin*-*-* v850*-*-* picochip*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-* arc*-*-*"} } } */
/* { dg-options "-O2 -fdump-tree-vrp2-details -fdump-tree-cddce2-details" } */
/* { dg-additional-options "-mbranch-cost=2" { target avr-*-* } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp90.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp90.c
new file mode 100644
index 00000000000..836c335b698
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp90.c
@@ -0,0 +1,36 @@
+/* { dg-do link } */
+/* { dg-options "-O2 -fdump-tree-vrp1" } */
+/* { dg-final { scan-tree-dump-not "link_error" "vrp1"} } */
+/* { dg-final { cleanup-tree-dump "vrp1" } } */
+
+extern void link_error (void);
+
+__attribute__((noinline, noclone)) int
+foo (unsigned int n, int r)
+{
+ int i;
+ if (n > 0)
+ {
+ asm ("");
+ if (n < 10)
+ {
+ asm ("");
+ do
+ {
+ --n;
+ r *= 2;
+ if (n >= 9)
+ link_error ();
+ }
+ while (n > 0);
+ }
+ }
+ return r + n;
+}
+
+int
+main ()
+{
+ foo (7, 2);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/ubsan/c-shift-1.c b/gcc/testsuite/gcc.dg/ubsan/c-shift-1.c
new file mode 100644
index 00000000000..61b90105364
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/ubsan/c-shift-1.c
@@ -0,0 +1,18 @@
+/* { dg-do compile} */
+/* { dg-options "-fsanitize=shift -w" } */
+/* { dg-shouldfail "ubsan" } */
+
+int x;
+int
+main (void)
+{
+ /* None of the following should pass. */
+ int A[1 >> -1] = {}; /* { dg-error "variable-sized object may not be initialized" } */
+ int B[-1 >> -1] = {}; /* { dg-error "variable-sized object may not be initialized" } */
+ int D[1 << -1] = {}; /* { dg-error "variable-sized object may not be initialized" } */
+ int E[-1 << -1] = {}; /* { dg-error "variable-sized object may not be initialized" } */
+ int F[-1 >> 200] = {}; /* { dg-error "variable-sized object may not be initialized" } */
+ int G[1 << 200] = {}; /* { dg-error "variable-sized object may not be initialized" } */
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/unroll_1.c b/gcc/testsuite/gcc.dg/unroll_1.c
index 154c78e4bf9..378f819ed68 100644
--- a/gcc/testsuite/gcc.dg/unroll_1.c
+++ b/gcc/testsuite/gcc.dg/unroll_1.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-rtl-loop2_unroll=stderr -fno-peel-loops -fdisable-tree-cunroll -fdisable-tree-cunrolli -fenable-rtl-loop2_unroll" } */
+/* { dg-options "-O2 -fdump-rtl-loop2_unroll=stderr -fno-peel-loops -fno-tree-vrp -fdisable-tree-cunroll -fdisable-tree-cunrolli -fenable-rtl-loop2_unroll" } */
unsigned a[100], b[100];
inline void bar()
diff --git a/gcc/testsuite/gcc.dg/unroll_2.c b/gcc/testsuite/gcc.dg/unroll_2.c
index 601b38705c1..2322a494012 100644
--- a/gcc/testsuite/gcc.dg/unroll_2.c
+++ b/gcc/testsuite/gcc.dg/unroll_2.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-rtl-loop2_unroll -fno-peel-loops -fdisable-tree-cunroll=foo -fdisable-tree-cunrolli=foo -fenable-rtl-loop2_unroll" } */
+/* { dg-options "-O2 -fdump-rtl-loop2_unroll -fno-peel-loops -fno-tree-vrp -fdisable-tree-cunroll=foo -fdisable-tree-cunrolli=foo -fenable-rtl-loop2_unroll" } */
unsigned a[100], b[100];
inline void bar()
diff --git a/gcc/testsuite/gcc.dg/unroll_3.c b/gcc/testsuite/gcc.dg/unroll_3.c
index 1f4216b6068..310bf064c97 100644
--- a/gcc/testsuite/gcc.dg/unroll_3.c
+++ b/gcc/testsuite/gcc.dg/unroll_3.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-rtl-loop2_unroll -fno-peel-loops -fdisable-tree-cunroll -fdisable-tree-cunrolli -fenable-rtl-loop2_unroll=foo" } */
+/* { dg-options "-O2 -fdump-rtl-loop2_unroll -fno-peel-loops -fno-tree-vrp -fdisable-tree-cunroll -fdisable-tree-cunrolli -fenable-rtl-loop2_unroll=foo" } */
unsigned a[100], b[100];
inline void bar()
diff --git a/gcc/testsuite/gcc.dg/unroll_4.c b/gcc/testsuite/gcc.dg/unroll_4.c
index 33d6edee2cc..fbffbb0d5f3 100644
--- a/gcc/testsuite/gcc.dg/unroll_4.c
+++ b/gcc/testsuite/gcc.dg/unroll_4.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-rtl-loop2_unroll -fno-peel-loops -fdisable-tree-cunroll -fdisable-tree-cunrolli -fenable-rtl-loop2_unroll=foo2" } */
+/* { dg-options "-O2 -fdump-rtl-loop2_unroll -fno-peel-loops -fno-tree-vrp -fdisable-tree-cunroll -fdisable-tree-cunrolli -fenable-rtl-loop2_unroll=foo2" } */
unsigned a[100], b[100];
inline void bar()
diff --git a/gcc/testsuite/gcc.dg/utf-cvt.c b/gcc/testsuite/gcc.dg/utf-cvt.c
index 7f51179eeb4..d6f18eeade7 100644
--- a/gcc/testsuite/gcc.dg/utf-cvt.c
+++ b/gcc/testsuite/gcc.dg/utf-cvt.c
@@ -1,7 +1,7 @@
/* Contributed by Kris Van Hees <kris.van.hees@oracle.com> */
/* Test the char16_t and char32_t promotion rules. */
/* { dg-do compile } */
-/* { dg-excess-errors "short and int are 16bit" { target { "avr-*-*" } } } */
+/* { dg-require-effective-target int32plus } */
/* { dg-options "-std=gnu99 -Wall -Wconversion -Wsign-conversion" } */
typedef __CHAR16_TYPE__ char16_t;
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-31.c b/gcc/testsuite/gcc.dg/vect/bb-slp-31.c
index bbddb0ac28c..7ea341216d6 100644
--- a/gcc/testsuite/gcc.dg/vect/bb-slp-31.c
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-31.c
@@ -10,3 +10,4 @@ void f(){
}
/* { dg-final { scan-tree-dump "basic block vectorized" "slp" } } */
+/* { dg-final { cleanup-tree-dump "slp" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-32.c b/gcc/testsuite/gcc.dg/vect/bb-slp-32.c
index 765f842ec8c..6d69d15c965 100644
--- a/gcc/testsuite/gcc.dg/vect/bb-slp-32.c
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-32.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-require-effective-target vect_int } */
-/* { dg-additional-options "-fvect-cost-model" } */
+/* { dg-additional-options "-fvect-cost-model=dynamic" } */
void bar (int *);
int foo (int *p)
diff --git a/gcc/testsuite/gcc.dg/vect/costmodel/i386/i386-costmodel-vect.exp b/gcc/testsuite/gcc.dg/vect/costmodel/i386/i386-costmodel-vect.exp
index da80bba9d6c..93ad2759468 100644
--- a/gcc/testsuite/gcc.dg/vect/costmodel/i386/i386-costmodel-vect.exp
+++ b/gcc/testsuite/gcc.dg/vect/costmodel/i386/i386-costmodel-vect.exp
@@ -28,7 +28,7 @@ if { ![istarget i?86*-*-*] && ![istarget x86_64-*-*] } then {
set DEFAULT_VECTCFLAGS ""
# These flags are used for all targets.
-lappend DEFAULT_VECTCFLAGS "-O2" "-ftree-vectorize" "-fvect-cost-model"
+lappend DEFAULT_VECTCFLAGS "-O2" "-ftree-vectorize" "-fvect-cost-model=dynamic"
# If the target system supports vector instructions, the default action
# for a test is 'run', otherwise it's 'compile'. Save current default.
diff --git a/gcc/testsuite/gcc.dg/vect/costmodel/ppc/ppc-costmodel-vect.exp b/gcc/testsuite/gcc.dg/vect/costmodel/ppc/ppc-costmodel-vect.exp
index 010d7459a1e..f77caec669f 100644
--- a/gcc/testsuite/gcc.dg/vect/costmodel/ppc/ppc-costmodel-vect.exp
+++ b/gcc/testsuite/gcc.dg/vect/costmodel/ppc/ppc-costmodel-vect.exp
@@ -33,7 +33,7 @@ if ![is-effective-target powerpc_altivec_ok] {
set DEFAULT_VECTCFLAGS ""
# These flags are used for all targets.
-lappend DEFAULT_VECTCFLAGS "-O2" "-ftree-vectorize" "-fvect-cost-model" "-fno-common"
+lappend DEFAULT_VECTCFLAGS "-O2" "-ftree-vectorize" "-fvect-cost-model=dynamic" "-fno-common"
# If the target system supports vector instructions, the default action
# for a test is 'run', otherwise it's 'compile'. Save current default.
diff --git a/gcc/testsuite/gcc.dg/vect/costmodel/spu/spu-costmodel-vect.exp b/gcc/testsuite/gcc.dg/vect/costmodel/spu/spu-costmodel-vect.exp
index cb18c15fa59..b56e7c8a064 100644
--- a/gcc/testsuite/gcc.dg/vect/costmodel/spu/spu-costmodel-vect.exp
+++ b/gcc/testsuite/gcc.dg/vect/costmodel/spu/spu-costmodel-vect.exp
@@ -29,7 +29,7 @@ if { ![istarget spu*-*-*] } then {
set DEFAULT_VECTCFLAGS ""
# These flags are used for all targets.
-lappend DEFAULT_VECTCFLAGS "-O2" "-ftree-vectorize" "-fvect-cost-model"
+lappend DEFAULT_VECTCFLAGS "-O2" "-ftree-vectorize" "-fvect-cost-model=dynamic"
# If the target system supports vector instructions, the default action
# for a test is 'run', otherwise it's 'compile'. Save current default.
diff --git a/gcc/testsuite/gcc.dg/vect/costmodel/x86_64/x86_64-costmodel-vect.exp b/gcc/testsuite/gcc.dg/vect/costmodel/x86_64/x86_64-costmodel-vect.exp
index e32e33bb4fe..7afbf6a5238 100644
--- a/gcc/testsuite/gcc.dg/vect/costmodel/x86_64/x86_64-costmodel-vect.exp
+++ b/gcc/testsuite/gcc.dg/vect/costmodel/x86_64/x86_64-costmodel-vect.exp
@@ -29,7 +29,7 @@ if { (![istarget x86_64-*-*] && ![istarget i?86-*-*])
set DEFAULT_VECTCFLAGS ""
# These flags are used for all targets.
-lappend DEFAULT_VECTCFLAGS "-O2" "-ftree-vectorize" "-fvect-cost-model"
+lappend DEFAULT_VECTCFLAGS "-O2" "-ftree-vectorize" "-fvect-cost-model=dynamic"
# If the target system supports vector instructions, the default action
# for a test is 'run', otherwise it's 'compile'. Save current default.
diff --git a/gcc/testsuite/gcc.dg/vect/pr58508.c b/gcc/testsuite/gcc.dg/vect/pr58508.c
new file mode 100644
index 00000000000..c4921bb768f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr58508.c
@@ -0,0 +1,70 @@
+/* { dg-require-effective-target vect_int } */
+/* { dg-do compile } */
+
+
+/* The GCC vectorizer generates loop versioning for the following loop
+ since there may exist aliasing between A and B. The predicate checks
+ if A may alias with B across all iterations. Then for the loop in
+ the true body, we can assert that *B is a loop invariant so that
+ we can hoist the load of *B before the loop body. */
+
+void test1 (int* a, int* b)
+{
+ int i;
+ for (i = 0; i < 100000; ++i)
+ a[i] = *b + 1;
+}
+
+/* A test case with nested loops. The load of b[j+1] in the inner
+ loop should be hoisted. */
+
+void test2 (int* a, int* b)
+{
+ int i, j;
+ for (j = 0; j < 100000; ++j)
+ for (i = 0; i < 100000; ++i)
+ a[i] = b[j+1] + 1;
+}
+
+/* A test case with ifcvt transformation. */
+
+void test3 (int* a, int* b)
+{
+ int i, t;
+ for (i = 0; i < 10000; ++i)
+ {
+ if (*b > 0)
+ t = *b * 2;
+ else
+ t = *b / 2;
+ a[i] = t;
+ }
+}
+
+/* A test case in which the store in the loop can be moved outside
+ in the versioned loop with alias checks. Note this loop won't
+ be vectorized. */
+
+void test4 (int* a, int* b)
+{
+ int i;
+ for (i = 0; i < 100000; ++i)
+ *a += b[i];
+}
+
+/* A test case in which the load and store in the loop to b
+ can be moved outside in the versioned loop with alias checks.
+ Note this loop won't be vectorized. */
+
+void test5 (int* a, int* b)
+{
+ int i;
+ for (i = 0; i < 100000; ++i)
+ {
+ *b += a[i];
+ a[i] = *b;
+ }
+}
+
+/* { dg-final { scan-tree-dump-times "hoist" 8 "vect" } } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-alias-check.c b/gcc/testsuite/gcc.dg/vect/vect-alias-check.c
new file mode 100644
index 00000000000..64a4e0ce05c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-alias-check.c
@@ -0,0 +1,18 @@
+/* { dg-require-effective-target vect_int } */
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize --param=vect-max-version-for-alias-checks=2 -fdump-tree-vect-details" } */
+
+/* A test case showing three potential alias checks between
+ a[i] and b[i], b[i+7], b[i+14]. With alias checks merging
+ enabled, those tree checks can be merged into one, and the
+ loop will be vectorized with vect-max-version-for-alias-checks=2. */
+
+void foo (int *a, int *b)
+{
+ int i;
+ for (i = 0; i < 1000; ++i)
+ a[i] = b[i] + b[i+7] + b[i+14];
+}
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-align-3.c b/gcc/testsuite/gcc.dg/vect/vect-align-3.c
new file mode 100644
index 00000000000..a8d3e485e6c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-align-3.c
@@ -0,0 +1,54 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_int } */
+
+int a[2048];
+
+void
+f1 (int x, int y)
+{
+ int i;
+ x &= -256;
+ y &= -256;
+ for (i = x + 256; i < y; i++)
+ a[i]++;
+}
+
+void
+f2 (int x, int y)
+{
+ int i;
+ if (x & 31)
+ __builtin_unreachable ();
+ if (y & 31)
+ __builtin_unreachable ();
+ for (i = x + 256; i < x + y; i++)
+ a[i]++;
+}
+
+void
+f3 (int x, int y)
+{
+ int i;
+ if (x % 256)
+ __builtin_unreachable ();
+ if (y % 256)
+ __builtin_unreachable ();
+ for (i = x + 256; i < x + y; i++)
+ a[i]++;
+}
+
+void
+f4 (int x, int y)
+{
+ int i;
+ if ((x % 256) != 0)
+ __builtin_unreachable ();
+ if ((y % 256) != 0)
+ __builtin_unreachable ();
+ for (i = x + 256; i < x + y; i++)
+ a[i]++;
+}
+
+/* { dg-final { scan-tree-dump-not "vect_do_peeling_for_loop_bound" "vect" } } */
+/* { dg-final { scan-tree-dump-not "loop peeled for vectorization" "vect" } } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-ivdep-1.c b/gcc/testsuite/gcc.dg/vect/vect-ivdep-1.c
new file mode 100644
index 00000000000..f51b044dfc9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-ivdep-1.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_float } */
+/* { dg-additional-options "-O3 -fopt-info-vec-optimized" } */
+
+/* PR other/33426 */
+/* Testing whether #pragma ivdep is working. */
+
+void foo(int n, int *a, int *b, int *c, int *d, int *e) {
+ int i, j;
+#pragma GCC ivdep
+ for (i = 0; i < n; ++i) {
+ a[i] = b[i] + c[i];
+ }
+}
+
+/* { dg-message "loop vectorized" "" { target *-*-* } 0 } */
+/* { dg-bogus " version" "" { target *-*-* } 0 } */
+/* { dg-bogus " alias" "" { target *-*-* } 0 } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-ivdep-2.c b/gcc/testsuite/gcc.dg/vect/vect-ivdep-2.c
new file mode 100644
index 00000000000..ff9cb20ccb1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-ivdep-2.c
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_float } */
+/* { dg-additional-options "-O3 -fopt-info-vec-optimized" } */
+
+/* PR other/33426 */
+/* Testing whether #pragma ivdep is working. */
+
+void foo(int n, int *a, int *b, int *c) {
+ int i;
+ i = 0;
+#pragma GCC ivdep
+ while(i < n)
+ {
+ a[i] = b[i] + c[i];
+ ++i;
+ }
+}
+
+void bar(int n, int *a, int *b, int *c) {
+ int i;
+ i = 0;
+#pragma GCC ivdep
+ do
+ {
+ a[i] = b[i] + c[i];
+ ++i;
+ }
+ while(i < n);
+}
+
+
+/* { dg-message "loop vectorized" "" { target *-*-* } 0 } */
+/* { dg-bogus " version" "" { target *-*-* } 0 } */
+/* { dg-bogus " alias" "" { target *-*-* } 0 } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-reduc-pattern-3.c b/gcc/testsuite/gcc.dg/vect/vect-reduc-pattern-3.c
new file mode 100644
index 00000000000..06a94168cd0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-reduc-pattern-3.c
@@ -0,0 +1,41 @@
+/* { dg-require-effective-target vect_int } */
+
+#include <stdarg.h>
+#include "tree-vect.h"
+
+#define N 10
+#define RES 1024
+
+/* A reduction pattern in which there is no data ref in
+ the loop and one operand is defined outside of the loop. */
+
+__attribute__ ((noinline)) int
+foo (int v)
+{
+ int i;
+ int result = 1;
+
+ ++v;
+ for (i = 0; i < N; i++)
+ result *= v;
+
+ return result;
+}
+
+int
+main (void)
+{
+ int res;
+
+ check_vect ();
+
+ res = foo (1);
+ if (res != RES)
+ abort ();
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
+
diff --git a/gcc/testsuite/gcc.dg/vmx/eg-5.c b/gcc/testsuite/gcc.dg/vmx/eg-5.c
index 0b37e69d194..eb43e846b79 100644
--- a/gcc/testsuite/gcc.dg/vmx/eg-5.c
+++ b/gcc/testsuite/gcc.dg/vmx/eg-5.c
@@ -7,10 +7,17 @@ matvecmul4 (vector float c0, vector float c1, vector float c2,
/* Set result to a vector of f32 0's */
vector float result = ((vector float){0.,0.,0.,0.});
+#ifdef __LITTLE_ENDIAN__
+ result = vec_madd (c0, vec_splat (v, 3), result);
+ result = vec_madd (c1, vec_splat (v, 2), result);
+ result = vec_madd (c2, vec_splat (v, 1), result);
+ result = vec_madd (c3, vec_splat (v, 0), result);
+#else
result = vec_madd (c0, vec_splat (v, 0), result);
result = vec_madd (c1, vec_splat (v, 1), result);
result = vec_madd (c2, vec_splat (v, 2), result);
result = vec_madd (c3, vec_splat (v, 3), result);
+#endif
return result;
}
diff --git a/gcc/testsuite/gcc.dg/vmx/gcc-bug-i.c b/gcc/testsuite/gcc.dg/vmx/gcc-bug-i.c
index 97ef1448819..3e0e6a0793e 100644
--- a/gcc/testsuite/gcc.dg/vmx/gcc-bug-i.c
+++ b/gcc/testsuite/gcc.dg/vmx/gcc-bug-i.c
@@ -13,12 +13,27 @@
#define DO_INLINE __attribute__ ((always_inline))
#define DONT_INLINE __attribute__ ((noinline))
+#ifdef __LITTLE_ENDIAN__
+static inline DO_INLINE int inline_me(vector signed short data)
+{
+ union {vector signed short v; signed short s[8];} u;
+ signed short x;
+ unsigned char x1, x2;
+
+ u.v = data;
+ x = u.s[7];
+ x1 = (x >> 8) & 0xff;
+ x2 = x & 0xff;
+ return ((x2 << 8) | x1);
+}
+#else
static inline DO_INLINE int inline_me(vector signed short data)
{
union {vector signed short v; signed short s[8];} u;
u.v = data;
return u.s[7];
}
+#endif
static DONT_INLINE int foo(vector signed short data)
{
diff --git a/gcc/testsuite/gcc.dg/vmx/vec-set.c b/gcc/testsuite/gcc.dg/vmx/vec-set.c
new file mode 100644
index 00000000000..fa11c47a122
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vmx/vec-set.c
@@ -0,0 +1,14 @@
+#include "harness.h"
+
+vector short
+vec_set (short m)
+{
+ return (vector short){m, 0, 0, 0, 0, 0, 0, 0};
+}
+
+static void test()
+{
+ check (vec_all_eq (vec_set (7),
+ ((vector short){7, 0, 0, 0, 0, 0, 0, 0})),
+ "vec_set");
+}
diff --git a/gcc/testsuite/gcc.dg/wdate-time.c b/gcc/testsuite/gcc.dg/wdate-time.c
new file mode 100644
index 00000000000..0ff27b4cd6f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/wdate-time.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-Wdate-time" } */
+
+const char time[] = __TIME__; /* { dg-warning "might prevent reproducible builds" } */
+const char date[] = __DATE__; /* { dg-warning "might prevent reproducible builds" } */
+const char timestamp[] = __TIMESTAMP__; /* { dg-warning "might prevent reproducible builds" } */
diff --git a/gcc/testsuite/gcc.dg/wmul-1.c b/gcc/testsuite/gcc.dg/wmul-1.c
new file mode 100644
index 00000000000..3e762f4c18c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/wmul-1.c
@@ -0,0 +1,19 @@
+/* Not to fuse widening multiply with accumulate if the multiply has more than
+ one uses.
+ Note that for targets where pointer and int are of the same size or
+ widening multiply-and-accumulate is not available, this test just passes. */
+
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-widening_mul" } */
+
+typedef int ArrT [10][10];
+
+void
+foo (ArrT Arr, int Idx)
+{
+ Arr[Idx][Idx] = 1;
+ Arr[Idx + 10][Idx] = 2;
+}
+
+/* { dg-final { scan-tree-dump-not "WIDEN_MULT_PLUS_EXPR" "widening_mul" } } */
+/* { dg-final { cleanup-tree-dump "widening_mul" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/c-output-template-2.c b/gcc/testsuite/gcc.target/aarch64/c-output-template-2.c
new file mode 100644
index 00000000000..ced96d04542
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/c-output-template-2.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+
+void
+test (void)
+{
+ __asm__ ("@ %c0" : : "S" (test));
+}
+
+/* { dg-final { scan-assembler "@ test" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/c-output-template-3.c b/gcc/testsuite/gcc.target/aarch64/c-output-template-3.c
new file mode 100644
index 00000000000..c28837cd501
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/c-output-template-3.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-Wno-pointer-arith" } */
+
+void
+test (void)
+{
+ __asm__ ("@ %c0" : : "S" (&test + 4));
+}
+
+/* { dg-final { scan-assembler "@ test\\+4" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/c-output-template.c b/gcc/testsuite/gcc.target/aarch64/c-output-template.c
new file mode 100644
index 00000000000..1b67c9169e3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/c-output-template.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+
+void
+test (void)
+{
+ __asm__ ("@ %c0" : : "i" (42));
+}
+
+/* { dg-final { scan-assembler "@ 42" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/pr58460.c b/gcc/testsuite/gcc.target/aarch64/pr58460.c
new file mode 100644
index 00000000000..a7e149a371c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/pr58460.c
@@ -0,0 +1,35 @@
+/* { dg-do run } */
+/* { dg-options "-O" } */
+extern unsigned long x1;
+
+char *
+f (char *a, char *b)
+{
+ return a;
+}
+
+int
+g (char *a)
+{
+ return 2;
+}
+
+void
+h (char *p[])
+{
+ char n[x1][512];
+ char *l = f (p[1], " ");
+ if (g (p[0]))
+ n[0][0] = '\0';
+ while (l && *l)
+ {
+ }
+}
+
+unsigned long x1;
+
+int
+main ()
+{
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/vadd_f64.c b/gcc/testsuite/gcc.target/aarch64/vadd_f64.c
new file mode 100644
index 00000000000..c3bf7349597
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/vadd_f64.c
@@ -0,0 +1,114 @@
+/* Test vadd works correctly. */
+/* { dg-do run } */
+/* { dg-options "--save-temps" } */
+
+#include <arm_neon.h>
+
+#define FLT_EPSILON __FLT_EPSILON__
+#define DBL_EPSILON __DBL_EPSILON__
+
+#define TESTA0 0.33333
+#define TESTA1 -1.7777
+#define TESTA2 0
+#define TESTA3 1.23456
+/* 2^54, double has 53 significand bits
+ according to Double-precision floating-point format. */
+#define TESTA4 18014398509481984
+#define TESTA5 (1.0 / TESTA4)
+
+#define TESTB0 0.66667
+#define TESTB1 2
+#define TESTB2 0
+#define TESTB3 -2
+#define TESTB4 1.0
+#define TESTB5 2.0
+
+#define ANSW0 1
+#define ANSW1 0.2223
+#define ANSW2 0
+#define ANSW3 -0.76544
+#define ANSW4 TESTA4
+#define ANSW5 2.0
+
+extern void abort (void);
+
+#define EPSILON __DBL_EPSILON__
+#define ABS(a) __builtin_fabs (a)
+#define ISNAN(a) __builtin_isnan (a)
+#define FP_equals(a, b, epsilon) \
+ ( \
+ ((a) == (b)) \
+ || (ISNAN (a) && ISNAN (b)) \
+ || (ABS (a - b) < epsilon) \
+ )
+
+int
+test_vadd_f64 ()
+{
+ float64x1_t a;
+ float64x1_t b;
+ float64x1_t c;
+
+ a = TESTA0;
+ b = TESTB0;
+ c = ANSW0;
+
+ a = vadd_f64 (a, b);
+ if (!FP_equals (a, c, EPSILON))
+ return 1;
+
+ a = TESTA1;
+ b = TESTB1;
+ c = ANSW1;
+
+ a = vadd_f64 (a, b);
+ if (!FP_equals (a, c, EPSILON))
+ return 1;
+
+ a = TESTA2;
+ b = TESTB2;
+ c = ANSW2;
+
+ a = vadd_f64 (a, b);
+ if (!FP_equals (a, c, EPSILON))
+ return 1;
+
+ a = TESTA3;
+ b = TESTB3;
+ c = ANSW3;
+
+ a = vadd_f64 (a, b);
+ if (!FP_equals (a, c, EPSILON))
+ return 1;
+
+ a = TESTA4;
+ b = TESTB4;
+ c = ANSW4;
+
+ a = vadd_f64 (a, b);
+ if (!FP_equals (a, c, EPSILON))
+ return 1;
+
+ a = TESTA5;
+ b = TESTB5;
+ c = ANSW5;
+
+ a = vadd_f64 (a, b);
+ if (!FP_equals (a, c, EPSILON))
+ return 1;
+
+ return 0;
+}
+
+/* { dg-final { scan-assembler-times "fadd\\td\[0-9\]+, d\[0-9\]+, d\[0-9\]+" 6 } } */
+
+int
+main (int argc, char **argv)
+{
+ if (test_vadd_f64 ())
+ abort ();
+
+ return 0;
+}
+
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/vclz.c b/gcc/testsuite/gcc.target/aarch64/vclz.c
new file mode 100644
index 00000000000..006f80d77b5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/vclz.c
@@ -0,0 +1,574 @@
+/* Test vclz works correctly. */
+/* { dg-do run } */
+/* { dg-options "-std=gnu99 -O3 -Wno-div-by-zero --save-temps" } */
+#include <arm_neon.h>
+
+extern void abort (void);
+
+/* Tests in binary should look like:
+ 0
+ 1
+ 10
+ 101
+ 1010
+ 10101
+ etc. */
+
+#define TEST0 0
+#define TEST1 0x1
+#define TEST2 0x2
+#define TEST3 0x5
+#define TEST4 0xa
+#define TEST5 0x15
+#define TEST6 0x2a
+#define TEST7 0x55
+#define TEST8 0xaa
+#define TEST9 0x155
+#define TEST10 0x2aa
+#define TEST11 0x555
+#define TEST12 0xaaa
+#define TEST13 0x1555
+#define TEST14 0x2aaa
+#define TEST15 0x5555
+#define TEST16 0xaaaa
+#define TEST17 0x15555
+#define TEST18 0x2aaaa
+#define TEST19 0x55555
+#define TEST20 0xaaaaa
+#define TEST21 0x155555
+#define TEST22 0x2aaaaa
+#define TEST23 0x555555
+#define TEST24 0xaaaaaa
+#define TEST25 0x1555555
+#define TEST26 0x2aaaaaa
+#define TEST27 0x5555555
+#define TEST28 0xaaaaaaa
+#define TEST29 0x15555555
+#define TEST30 0x2aaaaaaa
+#define TEST31 0x55555555
+#define TEST32 0xaaaaaaaa
+
+#define INHIB_OPTIMIZATION asm volatile ("" : : : "memory")
+
+#define CONCAT(a, b) a##b
+#define CONCAT1(a, b) CONCAT (a, b)
+#define REG_INFEX64 _
+#define REG_INFEX128 q_
+#define SIGNED0 u
+#define SIGNED1 s
+#define SIGNED(x) SIGNED##x
+#define REG_INFEX(reg_len) REG_INFEX##reg_len
+#define POSTFIX(reg_len, data_len, is_signed) \
+ CONCAT1 (REG_INFEX (reg_len), CONCAT1 (SIGNED (is_signed), data_len))
+#define DATA_TYPE(data_len) DATA_TYPE_##data_len
+#define LOAD_INST(reg_len, data_len, is_signed) \
+ CONCAT1 (vld1, POSTFIX (reg_len, data_len, is_signed))
+#define CLZ_INST(reg_len, data_len, is_signed) \
+ CONCAT1 (vclz, POSTFIX (reg_len, data_len, is_signed))
+
+#define RUN_TEST(test_set, answ_set, reg_len, data_len, is_signed, n) \
+ a = LOAD_INST (reg_len, data_len, is_signed) (test_set); \
+ b = LOAD_INST (reg_len, data_len, is_signed) (answ_set); \
+ INHIB_OPTIMIZATION; \
+ a = CLZ_INST (reg_len, data_len, is_signed) (a); \
+ for (i = 0; i < n; i++) \
+ { \
+ INHIB_OPTIMIZATION; \
+ if (a [i] != b [i]) \
+ { \
+ return 1; \
+ } \
+ }
+
+int
+test_vclz_s8 ()
+{
+ int i;
+ int8x8_t a;
+ int8x8_t b;
+
+ int8_t test_set0[8] = {
+ TEST0, TEST1, TEST2, TEST3,
+ TEST4, TEST5, TEST6, TEST7
+ };
+ int8_t test_set1[8] = {
+ TEST8, TEST8, TEST8, TEST8,
+ TEST8, TEST8, TEST8, TEST8
+ };
+ int8_t answ_set0[8] = {
+ 8, 7, 6, 5,
+ 4, 3, 2, 1
+ };
+ int8_t answ_set1[8] = {
+ 0, 0, 0, 0,
+ 0, 0, 0, 0
+ };
+ RUN_TEST (test_set0, answ_set0, 64, 8, 1, 8);
+ RUN_TEST (test_set1, answ_set1, 64, 8, 1, 1);
+
+ return 0;
+}
+
+/* Double scan-assembler-times to take account of unsigned functions. */
+/* { dg-final { scan-assembler-times "clz\\tv\[0-9\]+\.8b, v\[0-9\]+\.8b" 4 } } */
+
+int
+test_vclz_s16 ()
+{
+ int i;
+ int16x4_t a;
+ int16x4_t b;
+
+ int16_t test_set0[4] = { TEST0, TEST1, TEST2, TEST3 };
+ int16_t test_set1[4] = { TEST4, TEST5, TEST6, TEST7 };
+ int16_t test_set2[4] = { TEST8, TEST9, TEST10, TEST11 };
+ int16_t test_set3[4] = { TEST12, TEST13, TEST14, TEST15 };
+ int16_t test_set4[4] = { TEST16, TEST16, TEST16, TEST16 };
+
+ int16_t answ_set0[4] = { 16, 15, 14, 13 };
+ int16_t answ_set1[4] = { 12, 11, 10, 9 };
+ int16_t answ_set2[4] = { 8, 7, 6, 5 };
+ int16_t answ_set3[4] = { 4, 3, 2, 1 };
+ int16_t answ_set4[4] = { 0, 0, 0, 0 };
+
+ RUN_TEST (test_set0, answ_set0, 64, 16, 1, 4);
+ RUN_TEST (test_set1, answ_set1, 64, 16, 1, 4);
+ RUN_TEST (test_set2, answ_set2, 64, 16, 1, 4);
+ RUN_TEST (test_set3, answ_set3, 64, 16, 1, 4);
+ RUN_TEST (test_set4, answ_set4, 64, 16, 1, 1);
+
+ return 0;
+}
+
+/* Double scan-assembler-times to take account of unsigned functions. */
+/* { dg-final { scan-assembler-times "clz\\tv\[0-9\]+\.4h, v\[0-9\]+\.4h" 10} } */
+
+int
+test_vclz_s32 ()
+{
+ int i;
+ int32x2_t a;
+ int32x2_t b;
+
+ int32_t test_set0[2] = { TEST0, TEST1 };
+ int32_t test_set1[2] = { TEST2, TEST3 };
+ int32_t test_set2[2] = { TEST4, TEST5 };
+ int32_t test_set3[2] = { TEST6, TEST7 };
+ int32_t test_set4[2] = { TEST8, TEST9 };
+ int32_t test_set5[2] = { TEST10, TEST11 };
+ int32_t test_set6[2] = { TEST12, TEST13 };
+ int32_t test_set7[2] = { TEST14, TEST15 };
+ int32_t test_set8[2] = { TEST16, TEST17 };
+ int32_t test_set9[2] = { TEST18, TEST19 };
+ int32_t test_set10[2] = { TEST20, TEST21 };
+ int32_t test_set11[2] = { TEST22, TEST23 };
+ int32_t test_set12[2] = { TEST24, TEST25 };
+ int32_t test_set13[2] = { TEST26, TEST27 };
+ int32_t test_set14[2] = { TEST28, TEST29 };
+ int32_t test_set15[2] = { TEST30, TEST31 };
+ int32_t test_set16[2] = { TEST32, TEST32 };
+
+ int32_t answ_set0[2] = { 32, 31 };
+ int32_t answ_set1[2] = { 30, 29 };
+ int32_t answ_set2[2] = { 28, 27 };
+ int32_t answ_set3[2] = { 26, 25 };
+ int32_t answ_set4[2] = { 24, 23 };
+ int32_t answ_set5[2] = { 22, 21 };
+ int32_t answ_set6[2] = { 20, 19 };
+ int32_t answ_set7[2] = { 18, 17 };
+ int32_t answ_set8[2] = { 16, 15 };
+ int32_t answ_set9[2] = { 14, 13 };
+ int32_t answ_set10[2] = { 12, 11 };
+ int32_t answ_set11[2] = { 10, 9 };
+ int32_t answ_set12[2] = { 8, 7 };
+ int32_t answ_set13[2] = { 6, 5 };
+ int32_t answ_set14[2] = { 4, 3 };
+ int32_t answ_set15[2] = { 2, 1 };
+ int32_t answ_set16[2] = { 0, 0 };
+
+ RUN_TEST (test_set0, answ_set0, 64, 32, 1, 2);
+ RUN_TEST (test_set1, answ_set1, 64, 32, 1, 2);
+ RUN_TEST (test_set2, answ_set2, 64, 32, 1, 2);
+ RUN_TEST (test_set3, answ_set3, 64, 32, 1, 2);
+ RUN_TEST (test_set4, answ_set4, 64, 32, 1, 2);
+ RUN_TEST (test_set5, answ_set5, 64, 32, 1, 2);
+ RUN_TEST (test_set6, answ_set6, 64, 32, 1, 2);
+ RUN_TEST (test_set7, answ_set7, 64, 32, 1, 2);
+ RUN_TEST (test_set8, answ_set8, 64, 32, 1, 2);
+ RUN_TEST (test_set9, answ_set9, 64, 32, 1, 2);
+ RUN_TEST (test_set10, answ_set10, 64, 32, 1, 2);
+ RUN_TEST (test_set11, answ_set11, 64, 32, 1, 2);
+ RUN_TEST (test_set12, answ_set12, 64, 32, 1, 2);
+ RUN_TEST (test_set13, answ_set13, 64, 32, 1, 2);
+ RUN_TEST (test_set14, answ_set14, 64, 32, 1, 2);
+ RUN_TEST (test_set15, answ_set15, 64, 32, 1, 2);
+ RUN_TEST (test_set16, answ_set16, 64, 32, 1, 1);
+
+ return 0;
+}
+
+/* Double scan-assembler-times to take account of unsigned functions. */
+/* { dg-final { scan-assembler-times "clz\\tv\[0-9\]+\.2s, v\[0-9\]+\.2s" 34 } } */
+
+int
+test_vclzq_s8 ()
+{
+ int i;
+ int8x16_t a;
+ int8x16_t b;
+
+ int8_t test_set0[16] = {
+ TEST0, TEST1, TEST2, TEST3, TEST4, TEST5, TEST6, TEST7,
+ TEST8, TEST8, TEST8, TEST8, TEST8, TEST8, TEST8, TEST8
+ };
+ int8_t answ_set0[16] = {
+ 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+ RUN_TEST (test_set0, answ_set0, 128, 8, 1, 9);
+ return 0;
+}
+
+/* Double scan-assembler-times to take account of unsigned functions. */
+/* { dg-final { scan-assembler-times "clz\\tv\[0-9\]+\.16b, v\[0-9\]+\.16b" 2 } } */
+
+int
+test_vclzq_s16 ()
+{
+ int i;
+ int16x8_t a;
+ int16x8_t b;
+
+ int16_t test_set0[8] = {
+ TEST0, TEST1, TEST2, TEST3, TEST4, TEST5, TEST6, TEST7
+ };
+ int16_t test_set1[8] = {
+ TEST8, TEST9, TEST10, TEST11, TEST12, TEST13, TEST14, TEST15
+ };
+ int16_t test_set2[8] = {
+ TEST16, TEST16, TEST16, TEST16, TEST16, TEST16, TEST16, TEST16
+ };
+
+ int16_t answ_set0[8] = {
+ 16, 15, 14, 13, 12, 11, 10, 9
+ };
+ int16_t answ_set1[8] = {
+ 8, 7, 6, 5, 4, 3, 2, 1
+ };
+ int16_t answ_set2[8] = {
+ 0, 0, 0, 0, 0, 0, 0, 0
+ };
+ RUN_TEST (test_set0, answ_set0, 128, 16, 1, 8);
+ RUN_TEST (test_set1, answ_set1, 128, 16, 1, 8);
+ RUN_TEST (test_set2, answ_set2, 128, 16, 1, 1);
+
+ return 0;
+}
+
+/* Double scan-assembler-times to take account of unsigned functions. */
+/* { dg-final { scan-assembler-times "clz\\tv\[0-9\]+\.8h, v\[0-9\]+\.8h" 6 } } */
+
+int
+test_vclzq_s32 ()
+{
+ int i;
+ int32x4_t a;
+ int32x4_t b;
+
+ int32_t test_set0[4] = { TEST0, TEST1, TEST2, TEST3 };
+ int32_t test_set1[4] = { TEST4, TEST5, TEST6, TEST7 };
+ int32_t test_set2[4] = { TEST8, TEST9, TEST10, TEST11 };
+ int32_t test_set3[4] = { TEST12, TEST13, TEST14, TEST15 };
+ int32_t test_set4[4] = { TEST16, TEST17, TEST18, TEST19 };
+ int32_t test_set5[4] = { TEST20, TEST21, TEST22, TEST23 };
+ int32_t test_set6[4] = { TEST24, TEST25, TEST26, TEST27 };
+ int32_t test_set7[4] = { TEST28, TEST29, TEST30, TEST31 };
+ int32_t test_set8[4] = { TEST32, TEST32, TEST32, TEST32 };
+
+ int32_t answ_set0[4] = { 32, 31, 30, 29 };
+ int32_t answ_set1[4] = { 28, 27, 26, 25 };
+ int32_t answ_set2[4] = { 24, 23, 22, 21 };
+ int32_t answ_set3[4] = { 20, 19, 18, 17 };
+ int32_t answ_set4[4] = { 16, 15, 14, 13 };
+ int32_t answ_set5[4] = { 12, 11, 10, 9 };
+ int32_t answ_set6[4] = { 8, 7, 6, 5 };
+ int32_t answ_set7[4] = { 4, 3, 2, 1 };
+ int32_t answ_set8[4] = { 0, 0, 0, 0 };
+
+ RUN_TEST (test_set0, answ_set0, 128, 32, 1, 4);
+ RUN_TEST (test_set1, answ_set1, 128, 32, 1, 4);
+ RUN_TEST (test_set2, answ_set2, 128, 32, 1, 4);
+ RUN_TEST (test_set3, answ_set3, 128, 32, 1, 4);
+ RUN_TEST (test_set4, answ_set4, 128, 32, 1, 1);
+
+ return 0;
+}
+
+/* Double scan-assembler-times to take account of unsigned functions. */
+/* { dg-final { scan-assembler-times "clz\\tv\[0-9\]+\.4s, v\[0-9\]+\.4s" 10 } } */
+
+/* Unsigned versions. */
+
+int
+test_vclz_u8 ()
+{
+ int i;
+ uint8x8_t a;
+ uint8x8_t b;
+
+ uint8_t test_set0[8] = {
+ TEST0, TEST1, TEST2, TEST3, TEST4, TEST5, TEST6, TEST7
+ };
+ uint8_t test_set1[8] = {
+ TEST8, TEST8, TEST8, TEST8, TEST8, TEST8, TEST8, TEST8
+ };
+ uint8_t answ_set0[8] = {
+ 8, 7, 6, 5, 4, 3, 2, 1
+ };
+ uint8_t answ_set1[8] = {
+ 0, 0, 0, 0, 0, 0, 0, 0
+ };
+
+ RUN_TEST (test_set0, answ_set0, 64, 8, 0, 8);
+ RUN_TEST (test_set1, answ_set1, 64, 8, 0, 1);
+
+ return 0;
+}
+
+/* ASM scan near test for signed version. */
+
+int
+test_vclz_u16 ()
+{
+ int i;
+ uint16x4_t a;
+ uint16x4_t b;
+
+ uint16_t test_set0[4] = { TEST0, TEST1, TEST2, TEST3 };
+ uint16_t test_set1[4] = { TEST4, TEST5, TEST6, TEST7 };
+ uint16_t test_set2[4] = { TEST8, TEST9, TEST10, TEST11 };
+ uint16_t test_set3[4] = { TEST12, TEST13, TEST14, TEST15 };
+ uint16_t test_set4[4] = { TEST16, TEST16, TEST16, TEST16 };
+
+ uint16_t answ_set0[4] = { 16, 15, 14, 13 };
+ uint16_t answ_set1[4] = { 12, 11, 10, 9 };
+ uint16_t answ_set2[4] = { 8, 7, 6, 5 };
+ uint16_t answ_set3[4] = { 4, 3, 2, 1 };
+ uint16_t answ_set4[4] = { 0, 0, 0, 0 };
+
+ RUN_TEST (test_set0, answ_set0, 64, 16, 0, 4);
+ RUN_TEST (test_set1, answ_set1, 64, 16, 0, 4);
+ RUN_TEST (test_set2, answ_set2, 64, 16, 0, 4);
+ RUN_TEST (test_set3, answ_set3, 64, 16, 0, 4);
+ RUN_TEST (test_set4, answ_set4, 64, 16, 0, 1);
+
+ return 0;
+}
+
+/* ASM scan near test for signed version. */
+
+int
+test_vclz_u32 ()
+{
+ int i;
+ uint32x2_t a;
+ uint32x2_t b;
+
+ uint32_t test_set0[2] = { TEST0, TEST1 };
+ uint32_t test_set1[2] = { TEST2, TEST3 };
+ uint32_t test_set2[2] = { TEST4, TEST5 };
+ uint32_t test_set3[2] = { TEST6, TEST7 };
+ uint32_t test_set4[2] = { TEST8, TEST9 };
+ uint32_t test_set5[2] = { TEST10, TEST11 };
+ uint32_t test_set6[2] = { TEST12, TEST13 };
+ uint32_t test_set7[2] = { TEST14, TEST15 };
+ uint32_t test_set8[2] = { TEST16, TEST17 };
+ uint32_t test_set9[2] = { TEST18, TEST19 };
+ uint32_t test_set10[2] = { TEST20, TEST21 };
+ uint32_t test_set11[2] = { TEST22, TEST23 };
+ uint32_t test_set12[2] = { TEST24, TEST25 };
+ uint32_t test_set13[2] = { TEST26, TEST27 };
+ uint32_t test_set14[2] = { TEST28, TEST29 };
+ uint32_t test_set15[2] = { TEST30, TEST31 };
+ uint32_t test_set16[2] = { TEST32, TEST32 };
+
+ uint32_t answ_set0[2] = { 32, 31 };
+ uint32_t answ_set1[2] = { 30, 29 };
+ uint32_t answ_set2[2] = { 28, 27 };
+ uint32_t answ_set3[2] = { 26, 25 };
+ uint32_t answ_set4[2] = { 24, 23 };
+ uint32_t answ_set5[2] = { 22, 21 };
+ uint32_t answ_set6[2] = { 20, 19 };
+ uint32_t answ_set7[2] = { 18, 17 };
+ uint32_t answ_set8[2] = { 16, 15 };
+ uint32_t answ_set9[2] = { 14, 13 };
+ uint32_t answ_set10[2] = { 12, 11 };
+ uint32_t answ_set11[2] = { 10, 9 };
+ uint32_t answ_set12[2] = { 8, 7 };
+ uint32_t answ_set13[2] = { 6, 5 };
+ uint32_t answ_set14[2] = { 4, 3 };
+ uint32_t answ_set15[2] = { 2, 1 };
+ uint32_t answ_set16[2] = { 0, 0 };
+
+ RUN_TEST (test_set0, answ_set0, 64, 32, 0, 2);
+ RUN_TEST (test_set1, answ_set1, 64, 32, 0, 2);
+ RUN_TEST (test_set2, answ_set2, 64, 32, 0, 2);
+ RUN_TEST (test_set3, answ_set3, 64, 32, 0, 2);
+ RUN_TEST (test_set4, answ_set4, 64, 32, 0, 2);
+ RUN_TEST (test_set5, answ_set5, 64, 32, 0, 2);
+ RUN_TEST (test_set6, answ_set6, 64, 32, 0, 2);
+ RUN_TEST (test_set7, answ_set7, 64, 32, 0, 2);
+ RUN_TEST (test_set8, answ_set8, 64, 32, 0, 2);
+ RUN_TEST (test_set9, answ_set9, 64, 32, 0, 2);
+ RUN_TEST (test_set10, answ_set10, 64, 32, 0, 2);
+ RUN_TEST (test_set11, answ_set11, 64, 32, 0, 2);
+ RUN_TEST (test_set12, answ_set12, 64, 32, 0, 2);
+ RUN_TEST (test_set13, answ_set13, 64, 32, 0, 2);
+ RUN_TEST (test_set14, answ_set14, 64, 32, 0, 2);
+ RUN_TEST (test_set15, answ_set15, 64, 32, 0, 2);
+ RUN_TEST (test_set16, answ_set16, 64, 32, 0, 1);
+
+ return 0;
+}
+
+/* ASM scan near test for signed version. */
+
+int
+test_vclzq_u8 ()
+{
+ int i;
+ uint8x16_t a;
+ uint8x16_t b;
+
+ uint8_t test_set0[16] = {
+ TEST0, TEST1, TEST2, TEST3, TEST4, TEST5, TEST6, TEST7,
+ TEST8, TEST8, TEST8, TEST8, TEST8, TEST8, TEST8, TEST8
+ };
+ uint8_t answ_set0[16] = {
+ 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+ RUN_TEST (test_set0, answ_set0, 128, 8, 0, 9);
+
+ return 0;
+}
+
+/* ASM scan near test for signed version. */
+
+int
+test_vclzq_u16 ()
+{
+ int i;
+ uint16x8_t a;
+ uint16x8_t b;
+
+ uint16_t test_set0[8] = {
+ TEST0, TEST1, TEST2, TEST3, TEST4, TEST5, TEST6, TEST7
+ };
+ uint16_t test_set1[8] = {
+ TEST8, TEST9, TEST10, TEST11, TEST12, TEST13, TEST14, TEST15
+ };
+ uint16_t test_set2[8] = {
+ TEST16, TEST16, TEST16, TEST16, TEST16, TEST16, TEST16, TEST16
+ };
+
+ uint16_t answ_set0[8] = {
+ 16, 15, 14, 13, 12, 11, 10, 9
+ };
+
+ uint16_t answ_set1[8] = {
+ 8, 7, 6, 5, 4, 3, 2, 1
+ };
+ uint16_t answ_set2[8] = {
+ 0, 0, 0, 0, 0, 0, 0, 0
+ };
+
+ RUN_TEST (test_set0, answ_set0, 128, 16, 0, 8);
+ RUN_TEST (test_set1, answ_set1, 128, 16, 0, 8);
+ RUN_TEST (test_set2, answ_set2, 128, 16, 0, 1);
+
+ return 0;
+}
+
+/* ASM scan near test for signed version. */
+
+int
+test_vclzq_u32 ()
+{
+ int i;
+ uint32x4_t a;
+ uint32x4_t b;
+
+ uint32_t test_set0[4] = { TEST0, TEST1, TEST2, TEST3 };
+ uint32_t test_set1[4] = { TEST4, TEST5, TEST6, TEST7 };
+ uint32_t test_set2[4] = { TEST8, TEST9, TEST10, TEST11 };
+ uint32_t test_set3[4] = { TEST12, TEST13, TEST14, TEST15 };
+ uint32_t test_set4[4] = { TEST16, TEST17, TEST18, TEST19 };
+ uint32_t test_set5[4] = { TEST20, TEST21, TEST22, TEST23 };
+ uint32_t test_set6[4] = { TEST24, TEST25, TEST26, TEST27 };
+ uint32_t test_set7[4] = { TEST28, TEST29, TEST30, TEST31 };
+ uint32_t test_set8[4] = { TEST32, TEST32, TEST32, TEST32 };
+
+ uint32_t answ_set0[4] = { 32, 31, 30, 29 };
+ uint32_t answ_set1[4] = { 28, 27, 26, 25 };
+ uint32_t answ_set2[4] = { 24, 23, 22, 21 };
+ uint32_t answ_set3[4] = { 20, 19, 18, 17 };
+ uint32_t answ_set4[4] = { 16, 15, 14, 13 };
+ uint32_t answ_set5[4] = { 12, 11, 10, 9 };
+ uint32_t answ_set6[4] = { 8, 7, 6, 5 };
+ uint32_t answ_set7[4] = { 4, 3, 2, 1 };
+ uint32_t answ_set8[4] = { 0, 0, 0, 0 };
+
+ RUN_TEST (test_set0, answ_set0, 128, 32, 0, 4);
+ RUN_TEST (test_set1, answ_set1, 128, 32, 0, 4);
+ RUN_TEST (test_set2, answ_set2, 128, 32, 0, 4);
+ RUN_TEST (test_set3, answ_set3, 128, 32, 0, 4);
+ RUN_TEST (test_set4, answ_set4, 128, 32, 0, 1);
+
+ return 0;
+}
+
+/* ASM scan near test for signed version. */
+
+int
+main (int argc, char **argv)
+{
+
+ if (test_vclz_s8 ())
+ abort ();
+
+ if (test_vclz_s16 ())
+ abort ();
+
+ if (test_vclz_s32 ())
+ abort ();
+
+ if (test_vclzq_s8 ())
+ abort ();
+
+ if (test_vclzq_s16 ())
+ abort ();
+
+ if (test_vclzq_s32 ())
+ abort ();
+
+ if (test_vclz_u8 ())
+ abort ();
+
+ if (test_vclz_u16 ())
+ abort ();
+
+ if (test_vclz_u32 ())
+ abort ();
+
+ if (test_vclzq_u8 ())
+ abort ();
+
+ if (test_vclzq_u16 ())
+ abort ();
+
+ if (test_vclzq_u32 ())
+ abort ();
+
+ return 0;
+}
+
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/vdiv_f.c b/gcc/testsuite/gcc.target/aarch64/vdiv_f.c
new file mode 100644
index 00000000000..cc3a9570c0f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/vdiv_f.c
@@ -0,0 +1,361 @@
+/* Test vdiv works correctly. */
+/* { dg-do run } */
+/* { dg-options "-O3 --save-temps" } */
+
+#include <arm_neon.h>
+
+#define FLT_INFINITY (__builtin_inff ())
+#define DBL_INFINITY (__builtin_inf ())
+
+#define NAN (0.0 / 0.0)
+
+#define PI 3.141592653589793
+#define PI_4 0.7853981633974483
+#define SQRT2 1.4142135623730951
+#define SQRT1_2 0.7071067811865475
+
+#define TESTA0 PI
+#define TESTA1 -PI
+#define TESTA2 PI
+#define TESTA3 -PI
+#define TESTA4 1.0
+#define TESTA5 -1.0
+#define TESTA6 1.0
+#define TESTA7 -1.0
+/* 2^25+1, float has 24 significand bits
+ according to Single-precision floating-point format. */
+#define TESTA8_FLT 33554433
+/* 2^54+1, double has 53 significand bits
+ according to Double-precision floating-point format. */
+#define TESTA8_DBL 18014398509481985
+#define TESTA9 -TESTA8
+#define TESTA10 TESTA8
+#define TESTA11 -TESTA8
+#define TESTA12 NAN
+#define TESTA13 1.0
+#define TESTA14 INFINITY
+#define TESTA15 -INFINITY
+#define TESTA16 INFINITY
+#define TESTA17 9.0
+#define TESTA18 11.0
+#define TESTA19 13.0
+
+#define TESTB0 4.0
+#define TESTB1 4.0
+#define TESTB2 -4.0
+#define TESTB3 -4.0
+#define TESTB4 SQRT2
+#define TESTB5 SQRT2
+#define TESTB6 -SQRT2
+#define TESTB7 -SQRT2
+#define TESTB8 2.0
+#define TESTB9 2.0
+#define TESTB10 -2.0
+#define TESTB11 -2.0
+#define TESTB12 3.0
+#define TESTB13 NAN
+#define TESTB14 5.0
+#define TESTB15 7.0
+#define TESTB16 INFINITY
+#define TESTB17 INFINITY
+#define TESTB18 -INFINITY
+#define TESTB19 0
+
+#define ANSW0 PI_4
+#define ANSW1 -PI_4
+#define ANSW2 -PI_4
+#define ANSW3 PI_4
+#define ANSW4 SQRT1_2
+#define ANSW5 -SQRT1_2
+#define ANSW6 -SQRT1_2
+#define ANSW7 SQRT1_2
+#define ANSW8_FLT 16777216
+#define ANSW8_DBL 9007199254740992
+#define ANSW9 -ANSW8
+#define ANSW10 -ANSW8
+#define ANSW11 ANSW8
+#define ANSW12 NAN
+#define ANSW13 NAN
+#define ANSW14 INFINITY
+#define ANSW15 -INFINITY
+#define ANSW16 NAN
+#define ANSW17 0
+#define ANSW18 0
+#define ANSW19 INFINITY
+
+#define CONCAT(a, b) a##b
+#define CONCAT1(a, b) CONCAT (a, b)
+#define REG_INFEX64 _
+#define REG_INFEX128 q_
+#define REG_INFEX(reg_len) REG_INFEX##reg_len
+#define POSTFIX(reg_len, data_len) \
+ CONCAT1 (REG_INFEX (reg_len), f##data_len)
+
+#define DATA_TYPE_32 float
+#define DATA_TYPE_64 double
+#define DATA_TYPE(data_len) DATA_TYPE_##data_len
+
+#define EPSILON_32 __FLT_EPSILON__
+#define EPSILON_64 __DBL_EPSILON__
+#define EPSILON(data_len) EPSILON_##data_len
+
+#define INDEX64_32 [i]
+#define INDEX64_64
+#define INDEX128_32 [i]
+#define INDEX128_64 [i]
+#define INDEX(reg_len, data_len) \
+ CONCAT1 (INDEX, reg_len##_##data_len)
+
+#define LOAD_INST(reg_len, data_len) \
+ CONCAT1 (vld1, POSTFIX (reg_len, data_len))
+#define DIV_INST(reg_len, data_len) \
+ CONCAT1 (vdiv, POSTFIX (reg_len, data_len))
+
+#define ABS(a) __builtin_fabs (a)
+#define ISNAN(a) __builtin_isnan (a)
+#define FP_equals(a, b, epsilon) \
+ ( \
+ ((a) == (b)) \
+ || (ISNAN (a) && ISNAN (b)) \
+ || (ABS (a - b) < epsilon) \
+ )
+
+#define INHIB_OPTIMIZATION asm volatile ("" : : : "memory")
+
+#define RUN_TEST(a, b, c, testseta, testsetb, answset, count, \
+ reg_len, data_len, n) \
+{ \
+ int i; \
+ INHIB_OPTIMIZATION; \
+ (a) = LOAD_INST (reg_len, data_len) (testseta[count]); \
+ (b) = LOAD_INST (reg_len, data_len) (testsetb[count]); \
+ (c) = LOAD_INST (reg_len, data_len) (answset[count]); \
+ INHIB_OPTIMIZATION; \
+ (a) = DIV_INST (reg_len, data_len) (a, b); \
+ for (i = 0; i < n; i++) \
+ { \
+ INHIB_OPTIMIZATION; \
+ if (!FP_equals ((a) INDEX (reg_len, data_len), \
+ (c) INDEX (reg_len, data_len), \
+ EPSILON (data_len))) \
+ return 1; \
+ } \
+}
+
+extern void abort (void);
+
+#define TESTA8 TESTA8_FLT
+#define ANSW8 ANSW8_FLT
+#define INFINITY FLT_INFINITY
+
+int
+test_vdiv_f32 ()
+{
+ int count;
+ float32x2_t a;
+ float32x2_t b;
+ float32x2_t c;
+
+ float32_t testseta[10][2] = {
+ { TESTA0, TESTA1 }, { TESTA2, TESTA3 },
+ { TESTA4, TESTA5 }, { TESTA6, TESTA7 },
+ { TESTA8, TESTA9 }, { TESTA10, TESTA11 },
+ { TESTA12, TESTA13 }, { TESTA14, TESTA15 },
+ { TESTA16, TESTA17 }, { TESTA18, TESTA19 }
+ };
+
+ float32_t testsetb[10][2] = {
+ { TESTB0, TESTB1 }, { TESTB2, TESTB3 },
+ { TESTB4, TESTB5 }, { TESTB6, TESTB7 },
+ { TESTB8, TESTB9 }, { TESTB10, TESTB11 },
+ { TESTB12, TESTB13 }, { TESTB14, TESTB15 },
+ { TESTB16, TESTB17 }, { TESTB18, TESTB19 }
+ };
+
+ float32_t answset[10][2] = {
+ { ANSW0, ANSW1 }, { ANSW2, ANSW3 },
+ { ANSW4, ANSW5 }, { ANSW6, ANSW7 },
+ { ANSW8, ANSW9 }, { ANSW10, ANSW11 },
+ { ANSW12, ANSW13 }, { ANSW14, ANSW15 },
+ { ANSW16, ANSW17 }, { ANSW18, ANSW19 }
+ };
+
+ for (count = 0; count < 10; count++)
+ {
+ RUN_TEST (a, b, c, testseta, testsetb, answset, count, 64, 32, 2);
+ }
+
+ return 0;
+}
+
+/* { dg-final { scan-assembler-times "fdiv\\tv\[0-9\]+\.2s, v\[0-9\]+\.2s, v\[0-9\]+\.2s" 1 } } */
+
+#undef TESTA8
+#undef ANSW8
+#undef INFINITY
+
+#define TESTA8 TESTA8_DBL
+#define ANSW8 ANSW8_DBL
+#define INFINITY DBL_INFINITY
+
+int
+test_vdiv_f64 ()
+{
+ int count;
+ float64x1_t a;
+ float64x1_t b;
+ float64x1_t c;
+
+ float64_t testseta[20][1] = {
+ { TESTA0 }, { TESTA1 }, { TESTA2 }, { TESTA3 },
+ { TESTA4 }, { TESTA5 }, { TESTA6 }, { TESTA7 },
+ { TESTA8 }, { TESTA9 }, { TESTA10 }, { TESTA11 },
+ { TESTA12 }, { TESTA13 }, { TESTA14 }, { TESTA15 },
+ { TESTA16 }, { TESTA17 }, { TESTA18 }, { TESTA19 }
+ };
+
+ float64_t testsetb[20][1] = {
+ { TESTB0 }, { TESTB1 }, { TESTB2 }, { TESTB3 },
+ { TESTB4 }, { TESTB5 }, { TESTB6 }, { TESTB7 },
+ { TESTB8 }, { TESTB9 }, { TESTB10 }, { TESTB11 },
+ { TESTB12 }, { TESTB13 }, { TESTB14 }, { TESTB15 },
+ { TESTB16 }, { TESTB17 }, { TESTB18 }, { TESTB19 }
+ };
+
+ float64_t answset[20][1] = {
+ { ANSW0 }, { ANSW1 }, { ANSW2 }, { ANSW3 },
+ { ANSW4 }, { ANSW5 }, { ANSW6 }, { ANSW7 },
+ { ANSW8 }, { ANSW9 }, { ANSW10 }, { ANSW11 },
+ { ANSW12 }, { ANSW13 }, { ANSW14 }, { ANSW15 },
+ { ANSW16 }, { ANSW17 }, { ANSW18 }, { ANSW19 }
+ };
+
+ for (count = 0; count < 20; count++)
+ {
+ RUN_TEST (a, b, c, testseta, testsetb, answset, count, 64, 64, 1);
+ }
+ return 0;
+}
+
+/* The following assembly should match 2 more times,
+ in 64bit NAN generation. */
+/* { dg-final { scan-assembler-times "fdiv\\td\[0-9\]+, d\[0-9\]+, d\[0-9\]+" 3 } } */
+
+#undef TESTA8
+#undef ANSW8
+#undef INFINITY
+
+#define TESTA8 TESTA8_FLT
+#define ANSW8 ANSW8_FLT
+#define INFINITY FLT_INFINITY
+
+int
+test_vdivq_f32 ()
+{
+ int count;
+ float32x4_t a;
+ float32x4_t b;
+ float32x4_t c;
+
+ float32_t testseta[5][4] = {
+ { TESTA0, TESTA1, TESTA2, TESTA3 },
+ { TESTA4, TESTA5, TESTA6, TESTA7 },
+ { TESTA8, TESTA9, TESTA10, TESTA11 },
+ { TESTA12, TESTA13, TESTA14, TESTA15 },
+ { TESTA16, TESTA17, TESTA18, TESTA19 }
+ };
+
+ float32_t testsetb[5][4] = {
+ { TESTB0, TESTB1, TESTB2, TESTB3 },
+ { TESTB4, TESTB5, TESTB6, TESTB7 },
+ { TESTB8, TESTB9, TESTB10, TESTB11 },
+ { TESTB12, TESTB13, TESTB14, TESTB15 },
+ { TESTB16, TESTB17, TESTB18, TESTB19 }
+ };
+
+ float32_t answset[5][4] = {
+ { ANSW0, ANSW1, ANSW2, ANSW3 },
+ { ANSW4, ANSW5, ANSW6, ANSW7 },
+ { ANSW8, ANSW9, ANSW10, ANSW11 },
+ { ANSW12, ANSW13, ANSW14, ANSW15 },
+ { ANSW16, ANSW17, ANSW18, ANSW19 }
+ };
+
+ for (count = 0; count < 5; count++)
+ {
+ RUN_TEST (a, b, c, testseta, testsetb, answset, count, 128, 32, 4);
+ }
+ return 0;
+}
+
+/* { dg-final { scan-assembler-times "fdiv\\tv\[0-9\]+\.4s, v\[0-9\]+\.4s, v\[0-9\]+\.4s" 1 } } */
+
+#undef TESTA8
+#undef ANSW8
+#undef INFINITY
+
+#define TESTA8 TESTA8_DBL
+#define ANSW8 ANSW8_DBL
+#define INFINITY DBL_INFINITY
+
+int
+test_vdivq_f64 ()
+{
+ int count;
+ float64x2_t a;
+ float64x2_t b;
+ float64x2_t c;
+
+ float64_t testseta[10][2] = {
+ { TESTA0, TESTA1 }, { TESTA2, TESTA3 },
+ { TESTA4, TESTA5 }, { TESTA6, TESTA7 },
+ { TESTA8, TESTA9 }, { TESTA10, TESTA11 },
+ { TESTA12, TESTA13 }, { TESTA14, TESTA15 },
+ { TESTA16, TESTA17 }, { TESTA18, TESTA19 }
+ };
+
+ float64_t testsetb[10][2] = {
+ { TESTB0, TESTB1 }, { TESTB2, TESTB3 },
+ { TESTB4, TESTB5 }, { TESTB6, TESTB7 },
+ { TESTB8, TESTB9 }, { TESTB10, TESTB11 },
+ { TESTB12, TESTB13 }, { TESTB14, TESTB15 },
+ { TESTB16, TESTB17 }, { TESTB18, TESTB19 }
+ };
+
+ float64_t answset[10][2] = {
+ { ANSW0, ANSW1 }, { ANSW2, ANSW3 },
+ { ANSW4, ANSW5 }, { ANSW6, ANSW7 },
+ { ANSW8, ANSW9 }, { ANSW10, ANSW11 },
+ { ANSW12, ANSW13 }, { ANSW14, ANSW15 },
+ { ANSW16, ANSW17 }, { ANSW18, ANSW19 }
+ };
+
+ for (count = 0; count < 10; count++)
+ {
+ RUN_TEST (a, b, c, testseta, testsetb, answset, count, 128, 64, 2);
+ }
+
+ return 0;
+}
+
+/* { dg-final { scan-assembler-times "fdiv\\tv\[0-9\]+\.2d, v\[0-9\]+\.2d, v\[0-9\]+\.2d" 1 } } */
+
+int
+main (int argc, char **argv)
+{
+ if (test_vdiv_f32 ())
+ abort ();
+
+ if (test_vdiv_f64 ())
+ abort ();
+
+ if (test_vdivq_f32 ())
+ abort ();
+
+ if (test_vdivq_f64 ())
+ abort ();
+
+ return 0;
+}
+
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/vect_saddl_1.c b/gcc/testsuite/gcc.target/aarch64/vect_saddl_1.c
new file mode 100644
index 00000000000..ecbd8a8af60
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/vect_saddl_1.c
@@ -0,0 +1,315 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -fno-inline -save-temps -fno-vect-cost-model" } */
+
+typedef signed char S8_t;
+typedef signed short S16_t;
+typedef signed int S32_t;
+typedef signed long long S64_t;
+
+typedef signed char *__restrict__ pS8_t;
+typedef signed short *__restrict__ pS16_t;
+typedef signed int *__restrict__ pS32_t;
+typedef signed long long *__restrict__ pS64_t;
+
+typedef unsigned char U8_t;
+typedef unsigned short U16_t;
+typedef unsigned int U32_t;
+typedef unsigned long long U64_t;
+
+typedef unsigned char *__restrict__ pU8_t;
+typedef unsigned short *__restrict__ pU16_t;
+typedef unsigned int *__restrict__ pU32_t;
+typedef unsigned long long *__restrict__ pU64_t;
+
+extern void abort ();
+
+void
+test_addl_S64_S32_4 (pS64_t a, pS32_t b, pS32_t c)
+{
+ int i;
+ for (i = 0; i < 4; i++)
+ a[i] = (S64_t) b[i] + (S64_t) c[i];
+}
+/* "saddl\tv\[0-9\]+\.2d,\ v\[0-9\]+\.2s,\ v\[0-9\]+\.2s" */
+/* "saddl2\tv\[0-9\]+\.2d,\ v\[0-9\]+\.4s,\ v\[0-9\]+\.4s" */
+
+/* a = -b + c => a = c - b */
+void
+test_addl_S64_S32_4_neg0 (pS64_t a, pS32_t b, pS32_t c)
+{
+ int i;
+ for (i = 0; i < 4; i++)
+ a[i] = -(S64_t) b[i] + (S64_t) c[i];
+}
+/* "ssubl\tv\[0-9\]+\.2d,\ v\[0-9\]+\.2s,\ v\[0-9\]+\.2s" */
+/* "ssubl2\tv\[0-9\]+\.2d,\ v\[0-9\]+\.4s,\ v\[0-9\]+\.4s" */
+
+/* a = b + -c => a = b - c */
+void
+test_addl_S64_S32_4_neg1 (pS64_t a, pS32_t b, pS32_t c)
+{
+ int i;
+ for (i = 0; i < 4; i++)
+ a[i] = (S64_t) b[i] + -(S64_t) c[i];
+}
+/* "ssubl\tv\[0-9\]+\.2d,\ v\[0-9\]+\.2s,\ v\[0-9\]+\.2s" */
+/* "ssubl2\tv\[0-9\]+\.2d,\ v\[0-9\]+\.4s,\ v\[0-9\]+\.4s" */
+
+void
+test_addl_S32_S16_8 (pS32_t a, pS16_t b, pS16_t c)
+{
+ int i;
+ for (i = 0; i < 8; i++)
+ a[i] = (S32_t) b[i] + (S32_t) c[i];
+}
+/* { dg-final { scan-assembler "saddl\tv\[0-9\]+\.4s,\ v\[0-9\]+\.4h,\ v\[0-9\]+\.4h" } } */
+/* { dg-final { scan-assembler "saddl2\tv\[0-9\]+\.4s,\ v\[0-9\]+\.8h,\ v\[0-9\]+\.8h" } } */
+
+void
+test_addl_S16_S8_16 (pS16_t a, pS8_t b, pS8_t c)
+{
+ int i;
+ for (i = 0; i < 16; i++)
+ a[i] = (S16_t) b[i] + (S16_t) c[i];
+}
+/* { dg-final { scan-assembler "saddl\tv\[0-9\]+\.8h,\ v\[0-9\]+\.8b,\ v\[0-9\]+\.8b" } } */
+/* { dg-final { scan-assembler "saddl2\tv\[0-9\]+\.8h,\ v\[0-9\]+\.16b,\ v\[0-9\]+\.16b" } } */
+
+void
+test_addl_U64_U32_4 (pU64_t a, pU32_t b, pU32_t c)
+{
+ int i;
+ for (i = 0; i < 4; i++)
+ a[i] = (U64_t) b[i] + (U64_t) c[i];
+}
+/* { dg-final { scan-assembler "uaddl\tv\[0-9\]+\.2d,\ v\[0-9\]+\.2s,\ v\[0-9\]+\.2s" } } */
+/* { dg-final { scan-assembler "uaddl2\tv\[0-9\]+\.2d,\ v\[0-9\]+\.4s,\ v\[0-9\]+\.4s" } } */
+
+void
+test_addl_U32_U16_8 (pU32_t a, pU16_t b, pU16_t c)
+{
+ int i;
+ for (i = 0; i < 8; i++)
+ a[i] = (U32_t) b[i] + (U32_t) c[i];
+}
+/* { dg-final { scan-assembler "uaddl\tv\[0-9\]+\.4s,\ v\[0-9\]+\.4h,\ v\[0-9\]+\.4h" } } */
+/* { dg-final { scan-assembler "uaddl2\tv\[0-9\]+\.4s,\ v\[0-9\]+\.8h,\ v\[0-9\]+\.8h" } } */
+
+void
+test_addl_U16_U8_16 (pU16_t a, pU8_t b, pU8_t c)
+{
+ int i;
+ for (i = 0; i < 16; i++)
+ a[i] = (U16_t) b[i] + (U16_t) c[i];
+}
+/* { dg-final { scan-assembler "uaddl\tv\[0-9\]+\.8h,\ v\[0-9\]+\.8b,\ v\[0-9\]+\.8b" } } */
+/* { dg-final { scan-assembler "uaddl2\tv\[0-9\]+\.8h,\ v\[0-9\]+\.16b,\ v\[0-9\]+\.16b" } } */
+
+void
+test_subl_S64_S32_4 (pS64_t a, pS32_t b, pS32_t c)
+{
+ int i;
+ for (i = 0; i < 4; i++)
+ a[i] = (S64_t) b[i] - (S64_t) c[i];
+}
+/* "ssubl\tv\[0-9\]+\.2d,\ v\[0-9\]+\.2s,\ v\[0-9\]+\.2s" */
+/* "ssubl2\tv\[0-9\]+\.2d,\ v\[0-9\]+\.4s,\ v\[0-9\]+\.4s" */
+
+/* a = b - -c => a = b + c */
+void
+test_subl_S64_S32_4_neg0 (pS64_t a, pS32_t b, pS32_t c)
+{
+ int i;
+ for (i = 0; i < 4; i++)
+ a[i] = (S64_t) b[i] - -(S64_t) c[i];
+}
+/* { dg-final { scan-assembler-times "saddl\tv\[0-9\]+\.2d,\ v\[0-9\]+\.2s,\ v\[0-9\]+\.2s" 2 } } */
+/* { dg-final { scan-assembler-times "saddl2\tv\[0-9\]+\.2d,\ v\[0-9\]+\.4s,\ v\[0-9\]+\.4s" 2 } } */
+
+/* a = -b - -c => a = c - b */
+void
+test_subl_S64_S32_4_neg1 (pS64_t a, pS32_t b, pS32_t c)
+{
+ int i;
+ for (i = 0; i < 4; i++)
+ a[i] = -(S64_t) b[i] - -(S64_t) c[i];
+}
+/* "ssubl\tv\[0-9\]+\.2d,\ v\[0-9\]+\.2s,\ v\[0-9\]+\.2s" */
+/* "ssubl2\tv\[0-9\]+\.2d,\ v\[0-9\]+\.4s,\ v\[0-9\]+\.4s" */
+
+/* a = -(b - c) => a = c - b */
+void
+test_subl_S64_S32_4_neg2 (pS64_t a, pS32_t b, pS32_t c)
+{
+ int i;
+ for (i = 0; i < 4; i++)
+ a[i] = -((S64_t) b[i] - (S64_t) c[i]);
+}
+/* { dg-final { scan-assembler-times "ssubl\tv\[0-9\]+\.2d,\ v\[0-9\]+\.2s,\ v\[0-9\]+\.2s" 5 } } */
+/* { dg-final { scan-assembler-times "ssubl2\tv\[0-9\]+\.2d,\ v\[0-9\]+\.4s,\ v\[0-9\]+\.4s" 5 } } */
+
+void
+test_subl_S32_S16_8 (pS32_t a, pS16_t b, pS16_t c)
+{
+ int i;
+ for (i = 0; i < 8; i++)
+ a[i] = (S32_t) b[i] - (S32_t) c[i];
+}
+/* { dg-final { scan-assembler "ssubl\tv\[0-9\]+\.4s,\ v\[0-9\]+\.4h,\ v\[0-9\]+\.4h" } } */
+/* { dg-final { scan-assembler "ssubl2\tv\[0-9\]+\.4s,\ v\[0-9\]+\.8h,\ v\[0-9\]+\.8h" } } */
+
+void
+test_subl_S16_S8_16 (pS16_t a, pS8_t b, pS8_t c)
+{
+ int i;
+ for (i = 0; i < 16; i++)
+ a[i] = (S16_t) b[i] - (S16_t) c[i];
+}
+/* { dg-final { scan-assembler "ssubl\tv\[0-9\]+\.8h,\ v\[0-9\]+\.8b,\ v\[0-9\]+\.8b" } } */
+/* { dg-final { scan-assembler "ssubl2\tv\[0-9\]+\.8h,\ v\[0-9\]+\.16b,\ v\[0-9\]+\.16b" } } */
+
+void
+test_subl_U64_U32_4 (pU64_t a, pU32_t b, pU32_t c)
+{
+ int i;
+ for (i = 0; i < 4; i++)
+ a[i] = (U64_t) b[i] - (U64_t) c[i];
+}
+/* { dg-final { scan-assembler "usubl\tv\[0-9\]+\.2d,\ v\[0-9\]+\.2s,\ v\[0-9\]+\.2s" } } */
+/* { dg-final { scan-assembler "usubl2\tv\[0-9\]+\.2d,\ v\[0-9\]+\.4s,\ v\[0-9\]+\.4s" } } */
+
+void
+test_subl_U32_U16_8 (pU32_t a, pU16_t b, pU16_t c)
+{
+ int i;
+ for (i = 0; i < 8; i++)
+ a[i] = (U32_t) b[i] - (U32_t) c[i];
+}
+/* { dg-final { scan-assembler "usubl\tv\[0-9\]+\.4s,\ v\[0-9\]+\.4h,\ v\[0-9\]+\.4h" } } */
+/* { dg-final { scan-assembler "usubl2\tv\[0-9\]+\.4s,\ v\[0-9\]+\.8h,\ v\[0-9\]+\.8h" } } */
+
+void
+test_subl_U16_U8_16 (pU16_t a, pU8_t b, pU8_t c)
+{
+ int i;
+ for (i = 0; i < 16; i++)
+ a[i] = (U16_t) b[i] - (U16_t) c[i];
+}
+/* { dg-final { scan-assembler "usubl\tv\[0-9\]+\.8h,\ v\[0-9\]+\.8b,\ v\[0-9\]+\.8b" } } */
+/* { dg-final { scan-assembler "usubl2\tv\[0-9\]+\.8h,\ v\[0-9\]+\.16b,\ v\[0-9\]+\.16b" } } */
+
+/* input values */
+
+S64_t S64_ta[4];
+S32_t S32_tb[4] = { 0, 1, 2, 3 };
+S32_t S32_tc[4] = { 2, 2, -2, -2 };
+
+S32_t S32_ta[8];
+S16_t S16_tb[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };
+S16_t S16_tc[8] = { 2, 2, -2, -2, 2, 2, -2, -2 };
+
+S16_t S16_ta[16];
+S8_t S8_tb[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
+S8_t S8_tc[16] = { 2, 2, -2, -2, 2, 2, -2, -2, 2, 2, -2, -2, 2, 2, -2, -2 };
+
+/* expected output */
+
+S64_t addl_rS64[] = { 2, 3, 0, 1 };
+S64_t neg_r[] = { 2, 1, -4, -5 };
+S32_t addl_rS32[] = { 2, 3, 0, 1, 6, 7, 4, 5 };
+S16_t addl_rS16[] = { 2, 3, 0, 1, 6, 7, 4, 5, 10, 11, 8, 9, 14, 15, 12, 13 };
+S64_t subl_rS64[] = { -2, -1, 4, 5 };
+S32_t subl_rS32[] = { -2, -1, 4, 5, 2, 3, 8, 9 };
+S16_t subl_rS16[] =
+ { -2, -1, 4, 5, 2, 3, 8, 9, 6, 7, 12, 13, 10, 11, 16, 17 };
+U64_t addl_rU64[] = { 2, 3, 0x100000000, 0x100000001 };
+U32_t addl_rU32[] = { 2, 3, 0x10000, 0x10001, 6, 7, 0x10004, 0x10005 };
+U16_t addl_rU16[] =
+{
+ 0x0002, 0x0003, 0x0100, 0x0101, 0x0006, 0x0007, 0x0104, 0x0105,
+ 0x000a, 0x000b, 0x0108, 0x0109, 0x000e, 0x000f, 0x010c, 0x010d
+};
+U64_t subl_rU64[] =
+{
+ 0xfffffffffffffffe, 0xffffffffffffffff,
+ 0xffffffff00000004, 0xffffffff00000005
+};
+U32_t subl_rU32[] =
+{
+ 0xfffffffe, 0xffffffff, 0xffff0004, 0xffff0005,
+ 0x00000002, 0x00000003, 0xffff0008, 0xffff0009
+};
+U16_t subl_rU16[] =
+{
+ 0xfffe, 0xffff, 0xff04, 0xff05, 0x0002, 0x0003, 0xff08, 0xff09,
+ 0x0006, 0x0007, 0xff0c, 0xff0d, 0x000a, 0x000b, 0xff10, 0xff11
+};
+
+#define CHECK(T,N,AS,US) \
+do \
+ { \
+ for (i = 0; i < N; i++) \
+ if ((US##T##_t)S##T##_ta[i] != AS##_##r##US##T[i]) \
+ abort(); \
+ } \
+while (0)
+
+#define NCHECK(RES) \
+do \
+ { \
+ for (i = 0; i < 4; i++) \
+ if (S64_ta[i] != RES[i]) \
+ abort (); \
+ } \
+while (0)
+
+#define SCHECK(T,N,AS) CHECK(T,N,AS,S)
+#define UCHECK(T,N,AS) CHECK(T,N,AS,U)
+
+int
+main ()
+{
+ int i;
+
+ test_addl_S64_S32_4 (S64_ta, S32_tb, S32_tc);
+ SCHECK (64, 4, addl);
+ test_addl_S32_S16_8 (S32_ta, S16_tb, S16_tc);
+ SCHECK (32, 8, addl);
+ test_addl_S16_S8_16 (S16_ta, S8_tb, S8_tc);
+ SCHECK (16, 16, addl);
+ test_subl_S64_S32_4 (S64_ta, S32_tb, S32_tc);
+ SCHECK (64, 4, subl);
+ test_subl_S32_S16_8 (S32_ta, S16_tb, S16_tc);
+ SCHECK (32, 8, subl);
+ test_subl_S16_S8_16 (S16_ta, S8_tb, S8_tc);
+ SCHECK (16, 16, subl);
+
+ test_addl_U64_U32_4 (S64_ta, S32_tb, S32_tc);
+ UCHECK (64, 4, addl);
+ test_addl_U32_U16_8 (S32_ta, S16_tb, S16_tc);
+ UCHECK (32, 8, addl);
+ test_addl_U16_U8_16 (S16_ta, S8_tb, S8_tc);
+ UCHECK (16, 16, addl);
+ test_subl_U64_U32_4 (S64_ta, S32_tb, S32_tc);
+ UCHECK (64, 4, subl);
+ test_subl_U32_U16_8 (S32_ta, S16_tb, S16_tc);
+ UCHECK (32, 8, subl);
+ test_subl_U16_U8_16 (S16_ta, S8_tb, S8_tc);
+ UCHECK (16, 16, subl);
+
+ test_addl_S64_S32_4_neg0 (S64_ta, S32_tb, S32_tc);
+ NCHECK (neg_r);
+ test_addl_S64_S32_4_neg1 (S64_ta, S32_tb, S32_tc);
+ NCHECK (subl_rS64);
+ test_subl_S64_S32_4_neg0 (S64_ta, S32_tb, S32_tc);
+ NCHECK (addl_rS64);
+ test_subl_S64_S32_4_neg1 (S64_ta, S32_tb, S32_tc);
+ NCHECK (neg_r);
+ test_subl_S64_S32_4_neg2 (S64_ta, S32_tb, S32_tc);
+ NCHECK (neg_r);
+
+ return 0;
+}
+
+/* { dg-final { cleanup-saved-temps } } */
+
diff --git a/gcc/testsuite/gcc.target/aarch64/vneg_f.c b/gcc/testsuite/gcc.target/aarch64/vneg_f.c
new file mode 100644
index 00000000000..1eaf21d34eb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/vneg_f.c
@@ -0,0 +1,273 @@
+/* Test vneg works correctly. */
+/* { dg-do run } */
+/* { dg-options "--save-temps" } */
+
+#include <arm_neon.h>
+
+#define FLT_EPSILON __FLT_EPSILON__
+#define DBL_EPSILON __DBL_EPSILON__
+#define FLT_MAX __FLT_MAX__
+#define FLT_MIN __FLT_MIN__
+#define DBL_MAX __DBL_MAX__
+#define DBL_MIN __DBL_MIN__
+
+#define TEST0 0
+/* 6 digits of pi. */
+#define TEST1 3.14159
+/* 6 digits of -e. */
+#define TEST2 -2.71828
+/* 2^25, float has 24 significand bits
+ according to Single-precision floating-point format. */
+#define TEST3_FLT 33554432
+/* 2^54, double has 53 significand bits
+ according to Double-precision floating-point format. */
+#define TEST3_DBL 18014398509481984
+
+extern void abort (void);
+
+#define FLT_INFINITY (__builtin_inff ())
+#define DBL_INFINITY (__builtin_inf ())
+
+#ifndef NAN
+#define NAN (0.0 / 0.0)
+#endif
+
+#define CONCAT(a, b) a##b
+#define CONCAT1(a, b) CONCAT (a, b)
+#define REG_INFEX64 _
+#define REG_INFEX128 q_
+#define REG_INFEX(reg_len) REG_INFEX##reg_len
+#define POSTFIX(reg_len, data_len) \
+ CONCAT1 (REG_INFEX (reg_len), f##data_len)
+
+#define DATA_TYPE_32 float
+#define DATA_TYPE_64 double
+#define DATA_TYPE(data_len) DATA_TYPE_##data_len
+
+#define INDEX64_32 [i]
+#define INDEX64_64
+#define INDEX128_32 [i]
+#define INDEX128_64 [i]
+#define INDEX(reg_len, data_len) \
+ CONCAT1 (INDEX, reg_len##_##data_len)
+
+#define LOAD_INST(reg_len, data_len) \
+ CONCAT1 (vld1, POSTFIX (reg_len, data_len))
+#define NEG_INST(reg_len, data_len) \
+ CONCAT1 (vneg, POSTFIX (reg_len, data_len))
+
+#define INHIB_OPTIMIZATION asm volatile ("" : : : "memory")
+
+#define RUN_TEST(test_set, reg_len, data_len, n, a, b) \
+ { \
+ int i; \
+ (a) = LOAD_INST (reg_len, data_len) (test_set); \
+ (b) = NEG_INST (reg_len, data_len) (a); \
+ for (i = 0; i < n; i++) \
+ { \
+ DATA_TYPE (data_len) diff; \
+ INHIB_OPTIMIZATION; \
+ diff \
+ = a INDEX (reg_len, data_len) \
+ + b INDEX (reg_len, data_len); \
+ if (diff > EPSILON) \
+ return 1; \
+ } \
+ }
+
+#define TEST3 TEST3_FLT
+#define EPSILON FLT_EPSILON
+#define VAR_MIN FLT_MIN
+#define VAR_MAX FLT_MAX
+#define INFINITY FLT_INFINITY
+
+int
+test_vneg_f32 ()
+{
+ float test_set0[2] = { TEST0, TEST1 };
+ float test_set1[2] = { TEST2, TEST3 };
+ float test_set2[2] = { VAR_MAX, VAR_MIN };
+ float test_set3[2] = { INFINITY, NAN };
+
+ float32x2_t a;
+ float32x2_t b;
+
+ RUN_TEST (test_set0, 64, 32, 2, a, b);
+ RUN_TEST (test_set1, 64, 32, 2, a, b);
+ RUN_TEST (test_set2, 64, 32, 2, a, b);
+ RUN_TEST (test_set3, 64, 32, 0, a, b);
+
+ /* Since last test cannot be checked in a uniform way by adding
+ negation result to original value, the number of lanes to be
+ checked in RUN_TEST is 0 (last argument). Instead, result
+ will be checked manually. */
+
+ if (b[0] != -INFINITY)
+ return 1;
+
+ if (!__builtin_isnan (b[1]))
+ return 1;
+
+ return 0;
+}
+
+/* { dg-final { scan-assembler-times "fneg\\tv\[0-9\]+\.2s, v\[0-9\]+\.2s" 4 } } */
+
+#undef TEST3
+#undef EPSILON
+#undef VAR_MIN
+#undef VAR_MAX
+#undef INFINITY
+
+#define TEST3 TEST3_DBL
+#define EPSILON DBL_EPSILON
+#define VAR_MIN DBL_MIN
+#define VAR_MAX DBL_MAX
+#define INFINITY DBL_INFINITY
+
+int
+test_vneg_f64 ()
+{
+ float64x1_t a;
+ float64x1_t b;
+
+ double test_set0[1] = { TEST0 };
+ double test_set1[1] = { TEST1 };
+ double test_set2[1] = { TEST2 };
+ double test_set3[1] = { TEST3 };
+ double test_set4[1] = { VAR_MAX };
+ double test_set5[1] = { VAR_MIN };
+ double test_set6[1] = { INFINITY };
+ double test_set7[1] = { NAN };
+
+ RUN_TEST (test_set0, 64, 64, 1, a, b);
+ RUN_TEST (test_set1, 64, 64, 1, a, b);
+ RUN_TEST (test_set2, 64, 64, 1, a, b);
+ RUN_TEST (test_set3, 64, 64, 1, a, b);
+ RUN_TEST (test_set4, 64, 64, 1, a, b);
+ RUN_TEST (test_set5, 64, 64, 1, a, b);
+ RUN_TEST (test_set6, 64, 64, 0, a, b);
+
+ /* Since last test cannot be checked in a uniform way by adding
+ negation result to original value, the number of lanes to be
+ checked in RUN_TEST is 0 (last argument). Instead, result
+ will be checked manually. */
+
+ if (b != -INFINITY)
+ return 1;
+
+ /* Same as above. */
+
+ RUN_TEST (test_set7, 64, 64, 0, a, b);
+
+ if (!__builtin_isnan (b))
+ return 1;
+
+ return 0;
+}
+
+/* { dg-final { scan-assembler-times "fneg\\td\[0-9\]+, d\[0-9\]+" 8 } } */
+
+#undef TEST3
+#undef EPSILON
+#undef VAR_MIN
+#undef VAR_MAX
+#undef INFINITY
+
+#define TEST3 TEST3_FLT
+#define EPSILON FLT_EPSILON
+#define VAR_MIN FLT_MIN
+#define VAR_MAX FLT_MAX
+#define INFINITY FLT_INFINITY
+
+int
+test_vnegq_f32 ()
+{
+ float32x4_t a;
+ float32x4_t b;
+
+ float test_set0[4] = { TEST0, TEST1, TEST2, TEST3 };
+ float test_set1[4] = { FLT_MAX, FLT_MIN, INFINITY, NAN };
+
+ RUN_TEST (test_set0, 128, 32, 4, a, b);
+ RUN_TEST (test_set1, 128, 32, 2, a, b);
+
+ /* Since last test cannot be fully checked in a uniform way by
+ adding negation result to original value, the number of lanes
+ to be checked in RUN_TEST is 0 (last argument). Instead, result
+ will be checked manually. */
+
+ if (b[2] != -INFINITY)
+ return 1;
+
+ if (!__builtin_isnan (b[3]))
+ return 1;
+
+ return 0;
+}
+
+/* { dg-final { scan-assembler-times "fneg\\tv\[0-9\]+\.4s, v\[0-9\]+\.4s" 2 } } */
+
+#undef TEST3
+#undef EPSILON
+#undef VAR_MIN
+#undef VAR_MAX
+#undef INFINITY
+
+#define TEST3 TEST3_DBL
+#define EPSILON DBL_EPSILON
+#define VAR_MIN DBL_MIN
+#define VAR_MAX DBL_MAX
+#define INFINITY DBL_INFINITY
+
+int
+test_vnegq_f64 ()
+{
+ float64x2_t a;
+ float64x2_t b;
+
+ double test_set0[2] = { TEST0, TEST1 };
+ double test_set1[2] = { TEST2, TEST3 };
+ double test_set2[2] = { FLT_MAX, FLT_MIN };
+ double test_set3[2] = { INFINITY, NAN };
+
+ RUN_TEST (test_set0, 128, 64, 2, a, b);
+ RUN_TEST (test_set1, 128, 64, 2, a, b);
+ RUN_TEST (test_set2, 128, 64, 2, a, b);
+ RUN_TEST (test_set3, 128, 64, 0, a, b);
+
+ /* Since last test cannot be checked in a uniform way by adding
+ negation result to original value, the number of lanes to be
+ checked in RUN_TEST is 0 (last argument). Instead, result
+ will be checked manually. */
+
+ if (b[0] != -INFINITY)
+ return 1;
+
+ if (!__builtin_isnan (b[1]))
+ return 1;
+
+ return 0;
+}
+
+/* { dg-final { scan-assembler-times "fneg\\tv\[0-9\]+\.2d, v\[0-9\]+\.2d" 4 } } */
+
+int
+main (int argc, char **argv)
+{
+ if (test_vneg_f32 ())
+ abort ();
+
+ if (test_vneg_f64 ())
+ abort ();
+
+ if (test_vnegq_f32 ())
+ abort ();
+
+ if (test_vnegq_f64 ())
+ abort ();
+
+ return 0;
+}
+
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/vneg_s.c b/gcc/testsuite/gcc.target/aarch64/vneg_s.c
new file mode 100644
index 00000000000..accbf14074b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/vneg_s.c
@@ -0,0 +1,309 @@
+/* Test vneg works correctly. */
+/* { dg-do run } */
+/* { dg-options "-std=gnu99 -O3 -Wno-div-by-zero --save-temps" } */
+
+#include <arm_neon.h>
+#include <limits.h>
+
+/* Used to force a variable to a SIMD register. */
+#define force_simd(V1) asm volatile ("mov %d0, %1.d[0]" \
+ : "=w"(V1) \
+ : "w"(V1) \
+ : /* No clobbers */);
+#define INHIB_OPTIMIZATION asm volatile ("" : : : "memory")
+
+#define TEST0 0
+#define TEST1 1
+#define TEST2 -1
+#define TEST3 10
+#define TEST4 -10
+#define TEST5 0
+
+#define ANSW0 0
+#define ANSW1 -1
+#define ANSW2 1
+#define ANSW3 -10
+#define ANSW4 10
+#define ANSW5 0
+
+extern void abort (void);
+
+#define CONCAT(a, b) a##b
+#define CONCAT1(a, b) CONCAT (a, b)
+#define REG_INFEX64 _
+#define REG_INFEX128 q_
+#define REG_INFEX(reg_len) REG_INFEX##reg_len
+#define POSTFIX(reg_len, data_len) \
+ CONCAT1 (REG_INFEX (reg_len), s##data_len)
+#define DATA_TYPE_32 float
+#define DATA_TYPE_64 double
+#define DATA_TYPE(data_len) DATA_TYPE_##data_len
+#define INDEX64_8 [i]
+#define INDEX64_16 [i]
+#define INDEX64_32 [i]
+#define INDEX64_64
+#define INDEX128_8 [i]
+#define INDEX128_16 [i]
+#define INDEX128_32 [i]
+#define INDEX128_64 [i]
+
+#define FORCE_SIMD_INST64_8(data)
+#define FORCE_SIMD_INST64_16(data)
+#define FORCE_SIMD_INST64_32(data)
+#define FORCE_SIMD_INST64_64(data) force_simd (data)
+#define FORCE_SIMD_INST128_8(data)
+#define FORCE_SIMD_INST128_16(data)
+#define FORCE_SIMD_INST128_32(data)
+#define FORCE_SIMD_INST128_64(data)
+
+#define INDEX(reg_len, data_len) \
+ CONCAT1 (INDEX, reg_len##_##data_len)
+#define FORCE_SIMD_INST(reg_len, data_len, data) \
+ CONCAT1 (FORCE_SIMD_INST, reg_len##_##data_len) (data)
+#define LOAD_INST(reg_len, data_len) \
+ CONCAT1 (vld1, POSTFIX (reg_len, data_len))
+#define NEG_INST(reg_len, data_len) \
+ CONCAT1 (vneg, POSTFIX (reg_len, data_len))
+
+#define RUN_TEST(test_set, answ_set, reg_len, data_len, n, a, b) \
+ { \
+ int i; \
+ INHIB_OPTIMIZATION; \
+ (a) = LOAD_INST (reg_len, data_len) (test_set); \
+ (b) = LOAD_INST (reg_len, data_len) (answ_set); \
+ FORCE_SIMD_INST (reg_len, data_len, a) \
+ a = NEG_INST (reg_len, data_len) (a); \
+ FORCE_SIMD_INST (reg_len, data_len, a) \
+ for (i = 0; i < n; i++) \
+ { \
+ INHIB_OPTIMIZATION; \
+ if (a INDEX (reg_len, data_len) \
+ != b INDEX (reg_len, data_len)) \
+ return 1; \
+ } \
+ }
+
+int
+test_vneg_s8 ()
+{
+ int8x8_t a;
+ int8x8_t b;
+
+ int8_t test_set0[8] = {
+ TEST0, TEST1, TEST2, TEST3, TEST4, TEST5, SCHAR_MAX, SCHAR_MIN
+ };
+ int8_t answ_set0[8] = {
+ ANSW0, ANSW1, ANSW2, ANSW3, ANSW4, ANSW5, SCHAR_MIN + 1, SCHAR_MIN
+ };
+
+ RUN_TEST (test_set0, answ_set0, 64, 8, 8, a, b);
+
+ return 0;
+}
+
+/* { dg-final { scan-assembler-times "neg\\tv\[0-9\]+\.8b, v\[0-9\]+\.8b" 1 } } */
+
+int
+test_vneg_s16 ()
+{
+ int16x4_t a;
+ int16x4_t b;
+
+ int16_t test_set0[4] = { TEST0, TEST1, TEST2, TEST3 };
+ int16_t test_set1[4] = { TEST4, TEST5, SHRT_MAX, SHRT_MIN };
+
+ int16_t answ_set0[4] = { ANSW0, ANSW1, ANSW2, ANSW3 };
+ int16_t answ_set1[4] = { ANSW4, ANSW5, SHRT_MIN + 1, SHRT_MIN };
+
+ RUN_TEST (test_set0, answ_set0, 64, 16, 4, a, b);
+ RUN_TEST (test_set1, answ_set1, 64, 16, 4, a, b);
+
+ return 0;
+}
+
+/* { dg-final { scan-assembler-times "neg\\tv\[0-9\]+\.4h, v\[0-9\]+\.4h" 2 } } */
+
+int
+test_vneg_s32 ()
+{
+ int32x2_t a;
+ int32x2_t b;
+
+ int32_t test_set0[2] = { TEST0, TEST1 };
+ int32_t test_set1[2] = { TEST2, TEST3 };
+ int32_t test_set2[2] = { TEST4, TEST5 };
+ int32_t test_set3[2] = { INT_MAX, INT_MIN };
+
+ int32_t answ_set0[2] = { ANSW0, ANSW1 };
+ int32_t answ_set1[2] = { ANSW2, ANSW3 };
+ int32_t answ_set2[2] = { ANSW4, ANSW5 };
+ int32_t answ_set3[2] = { INT_MIN + 1, INT_MIN };
+
+ RUN_TEST (test_set0, answ_set0, 64, 32, 2, a, b);
+ RUN_TEST (test_set1, answ_set1, 64, 32, 2, a, b);
+ RUN_TEST (test_set2, answ_set2, 64, 32, 2, a, b);
+ RUN_TEST (test_set3, answ_set3, 64, 32, 2, a, b);
+
+ return 0;
+}
+
+/* { dg-final { scan-assembler-times "neg\\tv\[0-9\]+\.2s, v\[0-9\]+\.2s" 4 } } */
+
+int
+test_vneg_s64 ()
+{
+ int64x1_t a;
+ int64x1_t b;
+
+ int64_t test_set0[1] = { TEST0 };
+ int64_t test_set1[1] = { TEST1 };
+ int64_t test_set2[1] = { TEST2 };
+ int64_t test_set3[1] = { TEST3 };
+ int64_t test_set4[1] = { TEST4 };
+ int64_t test_set5[1] = { TEST5 };
+ int64_t test_set6[1] = { LLONG_MAX };
+ int64_t test_set7[1] = { LLONG_MIN };
+
+ int64_t answ_set0[1] = { ANSW0 };
+ int64_t answ_set1[1] = { ANSW1 };
+ int64_t answ_set2[1] = { ANSW2 };
+ int64_t answ_set3[1] = { ANSW3 };
+ int64_t answ_set4[1] = { ANSW4 };
+ int64_t answ_set5[1] = { ANSW5 };
+ int64_t answ_set6[1] = { LLONG_MIN + 1 };
+ int64_t answ_set7[1] = { LLONG_MIN };
+
+ RUN_TEST (test_set0, answ_set0, 64, 64, 1, a, b);
+ RUN_TEST (test_set1, answ_set1, 64, 64, 1, a, b);
+ RUN_TEST (test_set2, answ_set2, 64, 64, 1, a, b);
+ RUN_TEST (test_set3, answ_set3, 64, 64, 1, a, b);
+ RUN_TEST (test_set4, answ_set4, 64, 64, 1, a, b);
+ RUN_TEST (test_set5, answ_set5, 64, 64, 1, a, b);
+ RUN_TEST (test_set6, answ_set6, 64, 64, 1, a, b);
+ RUN_TEST (test_set7, answ_set7, 64, 64, 1, a, b);
+
+ return 0;
+}
+
+/* { dg-final { scan-assembler-times "neg\\td\[0-9\]+, d\[0-9\]+" 8 } } */
+
+int
+test_vnegq_s8 ()
+{
+ int8x16_t a;
+ int8x16_t b;
+
+ int8_t test_set0[16] = {
+ TEST0, TEST1, TEST2, TEST3, TEST4, TEST5, SCHAR_MAX, SCHAR_MIN,
+ 4, 8, 15, 16, 23, 42, -1, -2
+ };
+
+ int8_t answ_set0[16] = {
+ ANSW0, ANSW1, ANSW2, ANSW3, ANSW4, ANSW5, SCHAR_MIN + 1, SCHAR_MIN,
+ -4, -8, -15, -16, -23, -42, 1, 2
+ };
+
+ RUN_TEST (test_set0, answ_set0, 128, 8, 8, a, b);
+
+ return 0;
+}
+
+/* { dg-final { scan-assembler-times "neg\\tv\[0-9\]+\.16b, v\[0-9\]+\.16b" 1 } } */
+
+int
+test_vnegq_s16 ()
+{
+ int16x8_t a;
+ int16x8_t b;
+
+ int16_t test_set0[8] = {
+ TEST0, TEST1, TEST2, TEST3, TEST4, TEST5, SHRT_MAX, SHRT_MIN
+ };
+ int16_t answ_set0[8] = {
+ ANSW0, ANSW1, ANSW2, ANSW3, ANSW4, ANSW5, SHRT_MIN + 1, SHRT_MIN
+ };
+
+ RUN_TEST (test_set0, answ_set0, 128, 16, 8, a, b);
+
+ return 0;
+}
+
+/* { dg-final { scan-assembler-times "neg\\tv\[0-9\]+\.8h, v\[0-9\]+\.8h" 1 } } */
+
+int
+test_vnegq_s32 ()
+{
+ int32x4_t a;
+ int32x4_t b;
+
+ int32_t test_set0[4] = { TEST0, TEST1, TEST2, TEST3 };
+ int32_t test_set1[4] = { TEST4, TEST5, INT_MAX, INT_MIN };
+
+ int32_t answ_set0[4] = { ANSW0, ANSW1, ANSW2, ANSW3 };
+ int32_t answ_set1[4] = { ANSW4, ANSW5, INT_MIN + 1, INT_MIN };
+
+ RUN_TEST (test_set0, answ_set0, 128, 32, 4, a, b);
+ RUN_TEST (test_set1, answ_set1, 128, 32, 4, a, b);
+
+ return 0;
+}
+
+/* { dg-final { scan-assembler-times "neg\\tv\[0-9\]+\.4s, v\[0-9\]+\.4s" 2 } } */
+
+int
+test_vnegq_s64 ()
+{
+ int64x2_t a;
+ int64x2_t b;
+
+ int64_t test_set0[2] = { TEST0, TEST1 };
+ int64_t test_set1[2] = { TEST2, TEST3 };
+ int64_t test_set2[2] = { TEST4, TEST5 };
+ int64_t test_set3[2] = { LLONG_MAX, LLONG_MIN };
+
+ int64_t answ_set0[2] = { ANSW0, ANSW1 };
+ int64_t answ_set1[2] = { ANSW2, ANSW3 };
+ int64_t answ_set2[2] = { ANSW4, ANSW5 };
+ int64_t answ_set3[2] = { LLONG_MIN + 1, LLONG_MIN };
+
+ RUN_TEST (test_set0, answ_set0, 128, 64, 2, a, b);
+ RUN_TEST (test_set1, answ_set1, 128, 64, 2, a, b);
+ RUN_TEST (test_set2, answ_set2, 128, 64, 2, a, b);
+ RUN_TEST (test_set3, answ_set3, 128, 64, 2, a, b);
+
+ return 0;
+}
+
+/* { dg-final { scan-assembler-times "neg\\tv\[0-9\]+\.2d, v\[0-9\]+\.2d" 4 } } */
+
+int
+main (int argc, char **argv)
+{
+ if (test_vneg_s8 ())
+ abort ();
+
+ if (test_vneg_s16 ())
+ abort ();
+
+ if (test_vneg_s32 ())
+ abort ();
+
+ if (test_vneg_s64 ())
+ abort ();
+
+ if (test_vnegq_s8 ())
+ abort ();
+
+ if (test_vnegq_s16 ())
+ abort ();
+
+ if (test_vnegq_s32 ())
+ abort ();
+
+ if (test_vnegq_s64 ())
+ abort ();
+
+ return 0;
+}
+
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/vsub_f64.c b/gcc/testsuite/gcc.target/aarch64/vsub_f64.c
new file mode 100644
index 00000000000..abf4fc42d49
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/vsub_f64.c
@@ -0,0 +1,116 @@
+/* Test vsub works correctly. */
+/* { dg-do run } */
+/* { dg-options "--save-temps" } */
+
+#include <arm_neon.h>
+
+#define FLT_EPSILON __FLT_EPSILON__
+#define DBL_EPSILON __DBL_EPSILON__
+
+#define TESTA0 1
+#define TESTA1 0.2223
+#define TESTA2 0
+#define TESTA3 -0.76544
+/* 2^54, double has 53 significand bits
+ according to Double-precision floating-point format. */
+#define TESTA4 18014398509481984
+#define TESTA5 2.0
+
+#define TESTB0 0.66667
+#define TESTB1 2
+#define TESTB2 0
+#define TESTB3 -2
+#define TESTB4 1.0
+#define TESTB5 (1.0 / TESTA4)
+
+#define ANSW0 0.33333
+#define ANSW1 -1.7777
+#define ANSW2 0
+#define ANSW3 1.23456
+#define ANSW4 TESTA4
+#define ANSW5 2.0
+
+extern void abort (void);
+
+#define EPSILON __DBL_EPSILON__
+#define ISNAN(a) __builtin_isnan (a)
+/* FP_equals is implemented like this to execute subtraction
+ exectly once during a single test run. */
+#define FP_equals(a, b, epsilon) \
+( \
+ ((a) == (b)) \
+ || (ISNAN (a) && ISNAN (b)) \
+ || (((a > b) && (a < (b + epsilon))) \
+ || ((b > a) && (b < (a + epsilon)))) \
+)
+
+int
+test_vsub_f64 ()
+{
+ float64x1_t a;
+ float64x1_t b;
+ float64x1_t c;
+
+ a = TESTA0;
+ b = TESTB0;
+ c = ANSW0;
+
+ a = vsub_f64 (a, b);
+ if (!FP_equals (a, c, EPSILON))
+ return 1;
+
+ a = TESTA1;
+ b = TESTB1;
+ c = ANSW1;
+
+ a = vsub_f64 (a, b);
+ if (!FP_equals (a, c, EPSILON))
+ return 1;
+
+ a = TESTA2;
+ b = TESTB2;
+ c = ANSW2;
+
+ a = vsub_f64 (a, b);
+ if (!FP_equals (a, c, EPSILON))
+ return 1;
+
+ a = TESTA3;
+ b = TESTB3;
+ c = ANSW3;
+
+ a = vsub_f64 (a, b);
+ if (!FP_equals (a, c, EPSILON))
+ return 1;
+
+ a = TESTA4;
+ b = TESTB4;
+ c = ANSW4;
+
+ a = vsub_f64 (a, b);
+ if (!FP_equals (a, c, EPSILON))
+ return 1;
+
+ a = TESTA5;
+ b = TESTB5;
+ c = ANSW5;
+
+ a = vsub_f64 (a, b);
+ if (!FP_equals (a, c, EPSILON))
+ return 1;
+
+ return 0;
+}
+
+/* { dg-final { scan-assembler-times "fsub\\td\[0-9\]+, d\[0-9\]+, d\[0-9\]+" 6 } } */
+
+int
+main (int argc, char **argv)
+{
+ if (test_vsub_f64 ())
+ abort ();
+
+ return 0;
+}
+
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/arc/barrel-shifter-1.c b/gcc/testsuite/gcc.target/arc/barrel-shifter-1.c
new file mode 100644
index 00000000000..a0eb6d70c39
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/barrel-shifter-1.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mcpu=ARC601 -mbarrel-shifter" } */
+int i;
+
+int f (void)
+{
+ i >>= 2;
+}
+
+/* { dg-final { scan-assembler "asr_s" } } */
diff --git a/gcc/testsuite/gcc.target/arc/barrel-shifter-2.c b/gcc/testsuite/gcc.target/arc/barrel-shifter-2.c
new file mode 100644
index 00000000000..97998fbf1a3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/barrel-shifter-2.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+int i;
+
+int f (void)
+{
+ i >>= 2;
+}
+
+/* { dg-final { scan-assembler "asr_s" } } */
diff --git a/gcc/testsuite/gcc.target/arc/jump-around-jump.c b/gcc/testsuite/gcc.target/arc/jump-around-jump.c
new file mode 100644
index 00000000000..1b453283656
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/jump-around-jump.c
@@ -0,0 +1,123 @@
+/* { dg-do compile } */
+/* { dg-options "-Os -mlock -mswape -mrtsc -fno-reorder-blocks" } */
+
+/* This caused an ICE in arc_ifcvt when the 1->3 state change was not
+ implemented for TYPE_UNCOND_BRANCH in arc_ccfsm_post_advance. */
+
+typedef long __kernel_long_t;
+typedef __kernel_long_t __kernel_time_t;
+
+struct timespec {
+ __kernel_time_t tv_sec;
+ long tv_nsec;
+};
+
+
+struct module;
+struct device {
+ struct device *parent;
+};
+
+struct rtc_time {
+ int tm_sec;
+ int tm_min;
+ int tm_hour;
+ int tm_mday;
+ int tm_mon;
+ int tm_year;
+ int tm_wday;
+ int tm_yday;
+ int tm_isdst;
+};
+struct rtc_wkalrm {
+ unsigned char enabled;
+ unsigned char pending;
+ struct rtc_time time;
+};
+
+struct rtc_class_ops {
+ int (*open)(struct device *);
+ void (*release)(struct device *);
+ int (*ioctl)(struct device *, unsigned int, unsigned long);
+ int (*read_time)(struct device *, struct rtc_time *);
+ int (*set_time)(struct device *, struct rtc_time *);
+ int (*read_alarm)(struct device *, struct rtc_wkalrm *);
+ int (*set_alarm)(struct device *, struct rtc_wkalrm *);
+ //int (*proc)(struct device *, struct seq_file *);
+ int (*set_mmss)(struct device *, unsigned long secs);
+ int (*read_callback)(struct device *, int data);
+ int (*alarm_irq_enable)(struct device *, unsigned int enabled);
+};
+
+struct rtc_device
+{
+ struct device dev;
+ struct module *owner;
+
+ int id;
+ char name[20];
+
+ const struct rtc_class_ops *ops;
+ // struct mutex ops_lock;
+
+ // struct cdev char_dev;
+ unsigned long flags;
+
+ unsigned long irq_data;
+ //spinlock_t irq_lock;
+ //wait_queue_head_t irq_queue;
+ //struct fasync_struct *async_queue;
+
+ //struct rtc_task *irq_task;
+ //spinlock_t irq_task_lock;
+ int irq_freq;
+ int max_user_freq;
+
+ //struct timerqueue_head timerqueue;
+ //struct rtc_timer aie_timer;
+ //struct rtc_timer uie_rtctimer;
+ //struct hrtimer pie_timer;
+ int pie_enabled;
+ //struct work_struct irqwork;
+
+ int uie_unsupported;
+
+
+ //struct work_struct uie_task;
+ //struct timer_list uie_timer;
+
+ unsigned int oldsecs;
+ unsigned int uie_irq_active:1;
+ unsigned int stop_uie_polling:1;
+ unsigned int uie_task_active:1;
+ unsigned int uie_timer_active:1;
+
+};
+
+extern void rtc_time_to_tm(unsigned long time, struct rtc_time *tm);
+extern struct rtc_device *rtc_class_open(const char *name);
+extern void rtc_class_close(struct rtc_device *rtc);
+
+
+int rtc_set_ntp_time(struct timespec now)
+{
+ struct rtc_device *rtc;
+ struct rtc_time tm;
+ int err = -19;
+
+ if (now.tv_nsec < (1000000000L >> 1))
+ rtc_time_to_tm(now.tv_sec, &tm);
+ else
+ rtc_time_to_tm(now.tv_sec + 1, &tm);
+
+ rtc = rtc_class_open("rtc0");
+ if (rtc) {
+
+
+ if (rtc->ops && (rtc->ops->set_time || rtc->ops->set_mmss))
+ err = rtc_set_time(rtc, &tm);
+ rtc_class_close(rtc);
+ }
+
+ return err;
+}
diff --git a/gcc/testsuite/gcc.target/arc/long-calls.c b/gcc/testsuite/gcc.target/arc/long-calls.c
new file mode 100644
index 00000000000..63fafbcc674
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/long-calls.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mlong-calls" } */
+
+int g (void);
+
+int f (void)
+{
+ g();
+}
+
+/* { dg-final { scan-assembler "j @g" } } */
diff --git a/gcc/testsuite/gcc.target/arc/mA6.c b/gcc/testsuite/gcc.target/arc/mA6.c
new file mode 100644
index 00000000000..2e15a86f8a4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/mA6.c
@@ -0,0 +1,4 @@
+/* { dg-do compile } */
+/* { dg-options "-mA6" } */
+
+/* { dg-final { scan-assembler ".cpu ARC600" } } */
diff --git a/gcc/testsuite/gcc.target/arc/mA7.c b/gcc/testsuite/gcc.target/arc/mA7.c
new file mode 100644
index 00000000000..c4430f43b41
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/mA7.c
@@ -0,0 +1,4 @@
+/* { dg-do compile } */
+/* { dg-options "-mA7" } */
+
+/* { dg-final { scan-assembler ".cpu ARC700" } } */
diff --git a/gcc/testsuite/gcc.target/arc/mARC600.c b/gcc/testsuite/gcc.target/arc/mARC600.c
new file mode 100644
index 00000000000..20e086aa754
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/mARC600.c
@@ -0,0 +1,4 @@
+/* { dg-do compile } */
+/* { dg-options "-mARC600" } */
+
+/* { dg-final { scan-assembler ".cpu ARC600" } } */
diff --git a/gcc/testsuite/gcc.target/arc/mARC601.c b/gcc/testsuite/gcc.target/arc/mARC601.c
new file mode 100644
index 00000000000..1d30da4cafb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/mARC601.c
@@ -0,0 +1,4 @@
+/* { dg-do compile } */
+/* { dg-options "-mARC601" } */
+
+/* { dg-final { scan-assembler ".cpu ARC601" } } */
diff --git a/gcc/testsuite/gcc.target/arc/mARC700.c b/gcc/testsuite/gcc.target/arc/mARC700.c
new file mode 100644
index 00000000000..43e9baa3f30
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/mARC700.c
@@ -0,0 +1,4 @@
+/* { dg-do compile } */
+/* { dg-options "-mARC700" } */
+
+/* { dg-final { scan-assembler ".cpu ARC700" } } */
diff --git a/gcc/testsuite/gcc.target/arc/mcpu-arc600.c b/gcc/testsuite/gcc.target/arc/mcpu-arc600.c
new file mode 100644
index 00000000000..4c915fda0e3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/mcpu-arc600.c
@@ -0,0 +1,4 @@
+/* { dg-do compile } */
+/* { dg-options "-mcpu=ARC600" } */
+
+/* { dg-final { scan-assembler ".cpu ARC600" } } */
diff --git a/gcc/testsuite/gcc.target/arc/mcpu-arc601.c b/gcc/testsuite/gcc.target/arc/mcpu-arc601.c
new file mode 100644
index 00000000000..7c93c9dc4ac
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/mcpu-arc601.c
@@ -0,0 +1,4 @@
+/* { dg-do compile } */
+/* { dg-options "-mcpu=ARC601" } */
+
+/* { dg-final { scan-assembler ".cpu ARC601" } } */
diff --git a/gcc/testsuite/gcc.target/arc/mcpu-arc700.c b/gcc/testsuite/gcc.target/arc/mcpu-arc700.c
new file mode 100644
index 00000000000..c805a5af76b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/mcpu-arc700.c
@@ -0,0 +1,4 @@
+/* { dg-do compile } */
+/* { dg-options "-mcpu=ARC700" } */
+
+/* { dg-final { scan-assembler ".cpu ARC700" } } */
diff --git a/gcc/testsuite/gcc.target/arc/mcrc.c b/gcc/testsuite/gcc.target/arc/mcrc.c
new file mode 100644
index 00000000000..d3780bb00d6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/mcrc.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-mcrc" } */
+/* { dg-do assemble } */
+
+int f (int i)
+{
+ __asm__("crc %1, %1, %1" : "=r"(i) : "r"(i));
+ return i;
+}
diff --git a/gcc/testsuite/gcc.target/arc/mdpfp.c b/gcc/testsuite/gcc.target/arc/mdpfp.c
new file mode 100644
index 00000000000..4bbc9057b85
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/mdpfp.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mdpfp" } */
+
+double i;
+
+int f (void)
+{
+ i *= 2.0;
+}
+
+/* { dg-final { scan-assembler "daddh" } } */
diff --git a/gcc/testsuite/gcc.target/arc/mdsp-packa.c b/gcc/testsuite/gcc.target/arc/mdsp-packa.c
new file mode 100644
index 00000000000..f013a6dd1ea
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/mdsp-packa.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-mdsp-packa" } */
+/* { dg-do assemble } */
+
+int f (int i)
+{
+ __asm__("minidl %1, %1, %1" : "=r"(i) : "r"(i));
+ return i;
+}
diff --git a/gcc/testsuite/gcc.target/arc/mdvbf.c b/gcc/testsuite/gcc.target/arc/mdvbf.c
new file mode 100644
index 00000000000..e2e545e8bb3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/mdvbf.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-mdvbf" } */
+/* { dg-do assemble } */
+
+int f (int i)
+{
+ __asm__("vbfdw %1, %1" : "=r"(i) : "r"(i));
+ return i;
+}
diff --git a/gcc/testsuite/gcc.target/arc/mlock.c b/gcc/testsuite/gcc.target/arc/mlock.c
new file mode 100644
index 00000000000..3a8b050c30e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/mlock.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-mlock" } */
+/* { dg-do assemble } */
+
+int f (void *p)
+{
+ int i;
+
+ __asm__("llock %0, [%1]\n\t"
+ "scond %0, [%1]" : "=&r"(i) : "r"(p));
+ return i;
+}
diff --git a/gcc/testsuite/gcc.target/arc/mmac-24.c b/gcc/testsuite/gcc.target/arc/mmac-24.c
new file mode 100644
index 00000000000..30cb6981a03
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/mmac-24.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-mmac-24" } */
+/* { dg-do assemble } */
+
+int f (int i)
+{
+ __asm__("mult %1, %1, %1" : "=r"(i) : "r"(i));
+ return i;
+}
diff --git a/gcc/testsuite/gcc.target/arc/mmac-d16.c b/gcc/testsuite/gcc.target/arc/mmac-d16.c
new file mode 100644
index 00000000000..0570011fd26
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/mmac-d16.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-mmac-d16" } */
+/* { dg-do assemble } */
+
+int f (int i)
+{
+ __asm__("muldw %1, %1, %1" : "=r"(i) : "r"(i));
+ return i;
+}
diff --git a/gcc/testsuite/gcc.target/arc/mno-crc.c b/gcc/testsuite/gcc.target/arc/mno-crc.c
new file mode 100644
index 00000000000..70ab9c11761
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/mno-crc.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-mno-crc" } */
+/* Would also like to assemble and check that we get the expected
+ "Error: bad instruction" assembler messages, but at the moment our
+ testharness can't do that. */
+
+int f (int i)
+{
+ __asm__("crc %1, %1, %1" : "=r"(i) : "r"(i));
+ return i;
+}
diff --git a/gcc/testsuite/gcc.target/arc/mno-dsp-packa.c b/gcc/testsuite/gcc.target/arc/mno-dsp-packa.c
new file mode 100644
index 00000000000..eb21522af06
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/mno-dsp-packa.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-mno-dsp-packa" } */
+/* Would also like to assemble and check that we get the expected
+ "Error: bad instruction" assembler messages, but at the moment our
+ testharness can't do that. */
+
+int f (int i)
+{
+ __asm__("minidl %1, %1, %1" : "=r"(i) : "r"(i));
+ return i;
+}
diff --git a/gcc/testsuite/gcc.target/arc/mno-dvbf.c b/gcc/testsuite/gcc.target/arc/mno-dvbf.c
new file mode 100644
index 00000000000..ea96d987c18
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/mno-dvbf.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-mno-dvbf" } */
+/* Would also like to assemble and check that we get the expected
+ "Error: bad instruction" assembler messages, but at the moment our
+ testharness can't do that. */
+
+int f (int i)
+{
+ __asm__("vbfdw %1, %1" : "=r"(i) : "r"(i));
+ return i;
+}
diff --git a/gcc/testsuite/gcc.target/arc/mno-lock.c b/gcc/testsuite/gcc.target/arc/mno-lock.c
new file mode 100644
index 00000000000..62ac885ba99
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/mno-lock.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-mno-lock" } */
+/* Would also like to assemble and check that we get the expected
+ "Error: bad instruction" assembler messages, but at the moment our
+ testharness can't do that. */
+
+int f (void *p)
+{
+ int i;
+
+ __asm__("llock %0, [%1]\n\t"
+ "scond %0, [%1]" : "=&r"(i) : "r"(p));
+ return i;
+}
diff --git a/gcc/testsuite/gcc.target/arc/mno-mac-24.c b/gcc/testsuite/gcc.target/arc/mno-mac-24.c
new file mode 100644
index 00000000000..b4839579b12
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/mno-mac-24.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-mno-mac-24" } */
+/* Would also like to assemble and check that we get the expected
+ "Error: bad instruction" assembler messages, but at the moment our
+ testharness can't do that. */
+
+int f (int i)
+{
+ __asm__("mult %1, %1, %1" : "=r"(i) : "r"(i));
+ return i;
+}
diff --git a/gcc/testsuite/gcc.target/arc/mno-mac-d16.c b/gcc/testsuite/gcc.target/arc/mno-mac-d16.c
new file mode 100644
index 00000000000..68a20f4f55a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/mno-mac-d16.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-mno-mac-d16" } */
+/* Would also like to assemble and check that we get the expected
+ "Error: bad instruction" assembler messages, but at the moment our
+ testharness can't do that. */
+
+int f (int i)
+{
+ __asm__("muldw %1, %1, %1" : "=r"(i) : "r"(i));
+ return i;
+}
diff --git a/gcc/testsuite/gcc.target/arc/mno-rtsc.c b/gcc/testsuite/gcc.target/arc/mno-rtsc.c
new file mode 100644
index 00000000000..d74a60e9351
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/mno-rtsc.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-mno-rtsc" } */
+/* Would also like to assemble and check that we get the expected
+ "Error: bad instruction" assembler messages, but at the moment our
+ testharness can't do that. */
+
+int f (int i)
+{
+ __asm__("rtsc %1, %1" : "=r"(i) : "r"(i));
+ return i;
+}
diff --git a/gcc/testsuite/gcc.target/arc/mno-swape.c b/gcc/testsuite/gcc.target/arc/mno-swape.c
new file mode 100644
index 00000000000..c853ab4bdcc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/mno-swape.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-mno-swape" } */
+/* Would also like to assemble and check that we get the expected
+ "Error: bad instruction" assembler messages, but at the moment our
+ testharness can't do that. */
+
+int f (int i)
+{
+ __asm__("swape %1, %1" : "=r"(i) : "r"(i));
+ return i;
+}
diff --git a/gcc/testsuite/gcc.target/arc/mno-xy.c b/gcc/testsuite/gcc.target/arc/mno-xy.c
new file mode 100644
index 00000000000..e378b3fc9b6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/mno-xy.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-mno-xy" } */
+/* Would also like to assemble and check that we get the expected
+ "Error: bad instruction" assembler messages, but at the moment our
+ testharness can't do that. */
+
+void f (int i)
+{
+ __asm__("add x0_u0, x0_u0, %0" : : "r" (i));
+}
diff --git a/gcc/testsuite/gcc.target/arc/mrtsc.c b/gcc/testsuite/gcc.target/arc/mrtsc.c
new file mode 100644
index 00000000000..31852a5e479
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/mrtsc.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-mrtsc" } */
+/* { dg-do assemble } */
+
+int f (int i)
+{
+ __asm__("rtsc %1, %1" : "=r"(i) : "r"(i));
+ return i;
+}
diff --git a/gcc/testsuite/gcc.target/arc/mspfp.c b/gcc/testsuite/gcc.target/arc/mspfp.c
new file mode 100644
index 00000000000..0e41ff89d35
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/mspfp.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mspfp" } */
+
+float i;
+
+int f (void)
+{
+ i *= 2.0;
+}
+
+/* { dg-final { scan-assembler "fadd" } } */
diff --git a/gcc/testsuite/gcc.target/arc/mswape.c b/gcc/testsuite/gcc.target/arc/mswape.c
new file mode 100644
index 00000000000..692e6a2bb6e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/mswape.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-mswape" } */
+/* { dg-do assemble } */
+
+int f (int i)
+{
+ __asm__("swape %1, %1" : "=r"(i) : "r"(i));
+ return i;
+}
diff --git a/gcc/testsuite/gcc.target/arc/mtune-ARC600.c b/gcc/testsuite/gcc.target/arc/mtune-ARC600.c
new file mode 100644
index 00000000000..a483d1435ca
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/mtune-ARC600.c
@@ -0,0 +1,4 @@
+/* { dg-do compile } */
+/* { dg-options "-mtune=ARC600" } */
+
+/* { dg-final { scan-assembler ".cpu ARC700" } } */
diff --git a/gcc/testsuite/gcc.target/arc/mtune-ARC601.c b/gcc/testsuite/gcc.target/arc/mtune-ARC601.c
new file mode 100644
index 00000000000..ed57bd7092d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/mtune-ARC601.c
@@ -0,0 +1,4 @@
+/* { dg-do compile } */
+/* { dg-options "-mtune=ARC601" } */
+
+/* { dg-final { scan-assembler ".cpu ARC700" } } */
diff --git a/gcc/testsuite/gcc.target/arc/mtune-ARC700-xmac b/gcc/testsuite/gcc.target/arc/mtune-ARC700-xmac
new file mode 100644
index 00000000000..2f1e137be4d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/mtune-ARC700-xmac
@@ -0,0 +1,4 @@
+/* { dg-do compile } */
+/* { dg-options "-mtune=ARC700-xmac" } */
+
+/* { dg-final { scan-assembler ".cpu ARC700" } } */
diff --git a/gcc/testsuite/gcc.target/arc/mtune-ARC700.c b/gcc/testsuite/gcc.target/arc/mtune-ARC700.c
new file mode 100644
index 00000000000..851ea7305e0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/mtune-ARC700.c
@@ -0,0 +1,4 @@
+/* { dg-do compile } */
+/* { dg-options "-mtune=ARC700" } */
+
+/* { dg-final { scan-assembler ".cpu ARC700" } } */
diff --git a/gcc/testsuite/gcc.target/arc/mtune-ARC725D.c b/gcc/testsuite/gcc.target/arc/mtune-ARC725D.c
new file mode 100644
index 00000000000..e2aa4846291
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/mtune-ARC725D.c
@@ -0,0 +1,4 @@
+/* { dg-do compile } */
+/* { dg-options "-mtune=ARC725D" } */
+
+/* { dg-final { scan-assembler ".cpu ARC700" } } */
diff --git a/gcc/testsuite/gcc.target/arc/mtune-ARC750D.c b/gcc/testsuite/gcc.target/arc/mtune-ARC750D.c
new file mode 100644
index 00000000000..20923300ee1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/mtune-ARC750D.c
@@ -0,0 +1,4 @@
+/* { dg-do compile } */
+/* { dg-options "-mtune=ARC750D" } */
+
+/* { dg-final { scan-assembler ".cpu ARC700" } } */
diff --git a/gcc/testsuite/gcc.target/arc/mul64.c b/gcc/testsuite/gcc.target/arc/mul64.c
new file mode 100644
index 00000000000..3678b2799d5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/mul64.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mcpu=ARC600 -mmul64" } */
+#include <stdint.h>
+
+int64_t i;
+int j, k;
+
+int f (void)
+{
+ i = j * k;
+}
+
+/* { dg-final { scan-assembler "mul64" } } */
diff --git a/gcc/testsuite/gcc.target/arc/mxy.c b/gcc/testsuite/gcc.target/arc/mxy.c
new file mode 100644
index 00000000000..1ecc34d2bdb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/mxy.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-mxy" } */
+/* { dg-do assemble } */
+
+void f (int i)
+{
+ __asm__("add x0_u0, x0_u0, %0" : : "r" (i));
+}
diff --git a/gcc/testsuite/gcc.target/arc/no-dpfp-lrsr.c b/gcc/testsuite/gcc.target/arc/no-dpfp-lrsr.c
new file mode 100644
index 00000000000..e4e23e4a40f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/no-dpfp-lrsr.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mdpfp -mno-dpfp-lrsr" } */
+
+double i;
+
+int f (void)
+{
+ i *= 2.0;
+}
+
+/* { dg-final { scan-assembler-not "\tlr" } } */
diff --git a/gcc/testsuite/gcc.target/arm/atomic-comp-swap-release-acquire.c b/gcc/testsuite/gcc.target/arm/atomic-comp-swap-release-acquire.c
index 1eabb26ef4d..ea6fdd96db1 100644
--- a/gcc/testsuite/gcc.target/arm/atomic-comp-swap-release-acquire.c
+++ b/gcc/testsuite/gcc.target/arm/atomic-comp-swap-release-acquire.c
@@ -5,6 +5,6 @@
#include "../aarch64/atomic-comp-swap-release-acquire.x"
-/* { dg-final { scan-assembler-times "ldaex\tr\[0-9\]+, \\\[r\[0-9\]+\\\]" 4 } } */
+/* { dg-final { scan-assembler-times "ldaex" 4 } } */
/* { dg-final { scan-assembler-times "stlex" 4 } } */
/* { dg-final { scan-assembler-not "dmb" } } */
diff --git a/gcc/testsuite/gcc.target/arm/lp1243022.c b/gcc/testsuite/gcc.target/arm/lp1243022.c
new file mode 100644
index 00000000000..91a544d1b7d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/lp1243022.c
@@ -0,0 +1,201 @@
+/* { dg-do compile { target arm_thumb2 } } */
+/* { dg-options "-O2 -fdump-rtl-subreg2" } */
+
+/* { dg-final { scan-rtl-dump "REG_INC" "subreg2" } } */
+/* { dg-final { cleanup-rtl-dump "subreg2" } } */
+struct device;
+typedef unsigned int __u32;
+typedef unsigned long long u64;
+typedef __u32 __le32;
+typedef u64 dma_addr_t;
+typedef unsigned gfp_t;
+int dev_warn (const struct device *dev, const char *fmt, ...);
+struct usb_bus
+{
+ struct device *controller;
+};
+struct usb_hcd
+{
+ struct usb_bus self;
+};
+struct xhci_generic_trb
+{
+ __le32 field[4];
+};
+union xhci_trb
+{
+ struct xhci_generic_trb generic;
+};
+struct xhci_segment
+{
+ union xhci_trb *trbs;
+ dma_addr_t dma;
+};
+struct xhci_ring
+{
+ struct xhci_segment *first_seg;
+};
+struct xhci_hcd
+{
+ struct xhci_ring *cmd_ring;
+ struct xhci_ring *event_ring;
+};
+struct usb_hcd *xhci_to_hcd (struct xhci_hcd *xhci)
+{
+}
+dma_addr_t xhci_trb_virt_to_dma (struct xhci_segment * seg,
+ union xhci_trb * trb);
+struct xhci_segment *trb_in_td (struct xhci_segment *start_seg,
+ dma_addr_t suspect_dma);
+xhci_test_trb_in_td (struct xhci_hcd *xhci, struct xhci_segment *input_seg,
+ union xhci_trb *start_trb, union xhci_trb *end_trb,
+ dma_addr_t input_dma, struct xhci_segment *result_seg,
+ char *test_name, int test_number)
+{
+ unsigned long long start_dma;
+ unsigned long long end_dma;
+ struct xhci_segment *seg;
+ start_dma = xhci_trb_virt_to_dma (input_seg, start_trb);
+ end_dma = xhci_trb_virt_to_dma (input_seg, end_trb);
+ {
+ dev_warn (xhci_to_hcd (xhci)->self.controller,
+ "%d\n", test_number);
+ dev_warn (xhci_to_hcd (xhci)->self.controller,
+ "Expected seg %p, got seg %p\n", result_seg, seg);
+ }
+}
+xhci_check_trb_in_td_math (struct xhci_hcd *xhci, gfp_t mem_flags)
+{
+ struct
+ {
+ dma_addr_t input_dma;
+ struct xhci_segment *result_seg;
+ }
+ simple_test_vector[] =
+ {
+ {
+ 0, ((void *) 0)
+ }
+ ,
+ {
+ xhci->event_ring->first_seg->dma - 16, ((void *) 0)}
+ ,
+ {
+ xhci->event_ring->first_seg->dma - 1, ((void *) 0)}
+ ,
+ {
+ xhci->event_ring->first_seg->dma, xhci->event_ring->first_seg}
+ ,
+ {
+ xhci->event_ring->first_seg->dma + (64 - 1) * 16,
+ xhci->event_ring->first_seg
+ }
+ ,
+ {
+ xhci->event_ring->first_seg->dma + (64 - 1) * 16 + 1, ((void *) 0)}
+ ,
+ {
+ xhci->event_ring->first_seg->dma + (64) * 16, ((void *) 0)}
+ ,
+ {
+ (dma_addr_t) (~0), ((void *) 0)
+ }
+ };
+ struct
+ {
+ struct xhci_segment *input_seg;
+ union xhci_trb *start_trb;
+ union xhci_trb *end_trb;
+ dma_addr_t input_dma;
+ struct xhci_segment *result_seg;
+ }
+ complex_test_vector[] =
+ {
+ {
+ .input_seg = xhci->event_ring->first_seg,.start_trb =
+ xhci->event_ring->first_seg->trbs,.end_trb =
+ &xhci->event_ring->first_seg->trbs[64 - 1],.input_dma =
+ xhci->cmd_ring->first_seg->dma,.result_seg = ((void *) 0),
+ }
+ ,
+ {
+ .input_seg = xhci->event_ring->first_seg,.start_trb =
+ xhci->event_ring->first_seg->trbs,.end_trb =
+ &xhci->cmd_ring->first_seg->trbs[64 - 1],.input_dma =
+ xhci->cmd_ring->first_seg->dma,.result_seg = ((void *) 0),
+ }
+ ,
+ {
+ .input_seg = xhci->event_ring->first_seg,.start_trb =
+ xhci->cmd_ring->first_seg->trbs,.end_trb =
+ &xhci->cmd_ring->first_seg->trbs[64 - 1],.input_dma =
+ xhci->cmd_ring->first_seg->dma,.result_seg = ((void *) 0),
+ }
+ ,
+ {
+ .input_seg = xhci->event_ring->first_seg,.start_trb =
+ &xhci->event_ring->first_seg->trbs[0],.end_trb =
+ &xhci->event_ring->first_seg->trbs[3],.input_dma =
+ xhci->event_ring->first_seg->dma + 4 * 16,.result_seg = ((void *) 0),
+ }
+ ,
+ {
+ .input_seg = xhci->event_ring->first_seg,.start_trb =
+ &xhci->event_ring->first_seg->trbs[3],.end_trb =
+ &xhci->event_ring->first_seg->trbs[6],.input_dma =
+ xhci->event_ring->first_seg->dma + 2 * 16,.result_seg = ((void *) 0),
+ }
+ ,
+ {
+ .input_seg = xhci->event_ring->first_seg,.start_trb =
+ &xhci->event_ring->first_seg->trbs[64 - 3],.end_trb =
+ &xhci->event_ring->first_seg->trbs[1],.input_dma =
+ xhci->event_ring->first_seg->dma + 2 * 16,.result_seg = ((void *) 0),
+ }
+ ,
+ {
+ .input_seg = xhci->event_ring->first_seg,.start_trb =
+ &xhci->event_ring->first_seg->trbs[64 - 3],.end_trb =
+ &xhci->event_ring->first_seg->trbs[1],.input_dma =
+ xhci->event_ring->first_seg->dma + (64 - 4) * 16,.result_seg =
+ ((void *) 0),
+ }
+ ,
+ {
+ .input_seg = xhci->event_ring->first_seg,.start_trb =
+ &xhci->event_ring->first_seg->trbs[64 - 3],.end_trb =
+ &xhci->event_ring->first_seg->trbs[1],.input_dma =
+ xhci->cmd_ring->first_seg->dma + 2 * 16,.result_seg = ((void *) 0),
+ }
+ };
+ unsigned int num_tests;
+ int i, ret;
+ num_tests =
+ (sizeof (simple_test_vector) / sizeof ((simple_test_vector)[0]) +
+ (sizeof (struct
+ {
+ }
+ )));
+ for (i = 0; i < num_tests; i++)
+ {
+ ret =
+ xhci_test_trb_in_td (xhci, xhci->event_ring->first_seg,
+ xhci->event_ring->first_seg->trbs,
+ &xhci->event_ring->first_seg->trbs[64 - 1],
+ simple_test_vector[i].input_dma,
+ simple_test_vector[i].result_seg, "Simple", i);
+ if (ret < 0)
+ return ret;
+ }
+ for (i = 0; i < num_tests; i++)
+ {
+ ret =
+ xhci_test_trb_in_td (xhci, complex_test_vector[i].input_seg,
+ complex_test_vector[i].start_trb,
+ complex_test_vector[i].end_trb,
+ complex_test_vector[i].input_dma,
+ complex_test_vector[i].result_seg, "Complex", i);
+ if (ret < 0)
+ return ret;
+ }
+}
diff --git a/gcc/testsuite/gcc.target/arm/minmax_minus.c b/gcc/testsuite/gcc.target/arm/minmax_minus.c
index 4c2dcdf8ec0..906342a87cf 100644
--- a/gcc/testsuite/gcc.target/arm/minmax_minus.c
+++ b/gcc/testsuite/gcc.target/arm/minmax_minus.c
@@ -1,4 +1,5 @@
/* { dg-do compile } */
+/* { dg-require-effective-target arm_cond_exec } */
/* { dg-options "-O2" } */
#define MAX(a, b) (a > b ? a : b)
diff --git a/gcc/testsuite/gcc.target/arm/neon-vcond-gt.c b/gcc/testsuite/gcc.target/arm/neon-vcond-gt.c
index 86ccf95ada6..8e9f3785169 100644
--- a/gcc/testsuite/gcc.target/arm/neon-vcond-gt.c
+++ b/gcc/testsuite/gcc.target/arm/neon-vcond-gt.c
@@ -14,4 +14,4 @@ void foo (int ilast,float* w, float* w2)
}
/* { dg-final { scan-assembler "vcgt\\.f32\[\\t \]*q\[0-9\]+,\[\\t \]*q\[0-9\]+,\[\\t \]*q\[0-9\]+" } } */
-/* { dg-final { scan-assembler "vbit\[\\t \]*q\[0-9\]+,\[\\t \]*q\[0-9\]+,\[\\t \]*q\[0-9\]+" } } */
+/* { dg-final { scan-assembler "vbsl|vbit|vbif\[\\t \]*q\[0-9\]+,\[\\t \]*q\[0-9\]+,\[\\t \]*q\[0-9\]+" } } */
diff --git a/gcc/testsuite/gcc.target/arm/neon-vcond-ltgt.c b/gcc/testsuite/gcc.target/arm/neon-vcond-ltgt.c
index acb23a947ff..c8306e364a3 100644
--- a/gcc/testsuite/gcc.target/arm/neon-vcond-ltgt.c
+++ b/gcc/testsuite/gcc.target/arm/neon-vcond-ltgt.c
@@ -15,4 +15,4 @@ void foo (int ilast,float* w, float* w2)
/* { dg-final { scan-assembler-times "vcgt\\.f32\[\\t \]*q\[0-9\]+,\[\\t \]*q\[0-9\]+,\[\\t \]*q\[0-9\]+" 2 } } */
/* { dg-final { scan-assembler "vorr\[\\t \]*q\[0-9\]+,\[\\t \]*q\[0-9\]+,\[\\t \]*q\[0-9\]+" } } */
-/* { dg-final { scan-assembler "vbsl\[\\t \]*q\[0-9\]+,\[\\t \]*q\[0-9\]+,\[\\t \]*q\[0-9\]+" } } */
+/* { dg-final { scan-assembler "vbsl|vbit|vbif\[\\t \]*q\[0-9\]+,\[\\t \]*q\[0-9\]+,\[\\t \]*q\[0-9\]+" } } */
diff --git a/gcc/testsuite/gcc.target/arm/neon-vcond-unordered.c b/gcc/testsuite/gcc.target/arm/neon-vcond-unordered.c
index c3e448d621b..3bb67d3afe3 100644
--- a/gcc/testsuite/gcc.target/arm/neon-vcond-unordered.c
+++ b/gcc/testsuite/gcc.target/arm/neon-vcond-unordered.c
@@ -16,4 +16,4 @@ void foo (int ilast,float* w, float* w2)
/* { dg-final { scan-assembler "vcgt\\.f32\[\\t \]*q\[0-9\]+,\[\\t \]*q\[0-9\]+,\[\\t \]*q\[0-9\]+" } } */
/* { dg-final { scan-assembler "vcge\\.f32\[\\t \]*q\[0-9\]+,\[\\t \]*q\[0-9\]+,\[\\t \]*q\[0-9\]+" } } */
/* { dg-final { scan-assembler "vorr\[\\t \]*q\[0-9\]+,\[\\t \]*q\[0-9\]+,\[\\t \]*q\[0-9\]+" } } */
-/* { dg-final { scan-assembler "vbsl\[\\t \]*q\[0-9\]+,\[\\t \]*q\[0-9\]+,\[\\t \]*q\[0-9\]+" } } */
+/* { dg-final { scan-assembler "vbsl|vbit|vbif\[\\t \]*q\[0-9\]+,\[\\t \]*q\[0-9\]+,\[\\t \]*q\[0-9\]+" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pr58578.c b/gcc/testsuite/gcc.target/arm/pr58578.c
new file mode 100644
index 00000000000..2b474f544f2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pr58578.c
@@ -0,0 +1,54 @@
+
+/* PR target/58578 */
+/* { dg-do run } */
+/* { dg-options "-O1" } */
+
+#include <stdlib.h>
+
+typedef struct {
+ long _prec;
+ int _flag;
+ long _exp;
+} __my_st_t;
+
+typedef __my_st_t *__my_st_ptr;
+
+int
+_test_fn (__my_st_ptr y, const __my_st_ptr xt)
+{
+ int inexact;
+ if (xt->_exp != -2147483647L)
+ {
+ (y->_flag = xt->_flag);
+ }
+
+ do {
+ __my_st_ptr _y = y;
+ long _err1 = -2 * xt->_exp;
+ long _err2 = 2;
+ if (0 < _err1)
+ {
+ unsigned long _err = (unsigned long) _err1 + _err2;
+ if (__builtin_expect(!!(_err > _y->_prec + 1), 0))
+ return 2;
+ return 3;
+ }
+ } while (0);
+
+ return 0;
+}
+
+int main ()
+{
+ __my_st_t x, y;
+ long pz;
+ int inex;
+
+ x._prec = 914;
+ y._exp = 18;
+ if (_test_fn (&x, &y))
+ {
+ abort();
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/arm/pr58784.c b/gcc/testsuite/gcc.target/arm/pr58784.c
new file mode 100644
index 00000000000..e3ef950b499
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pr58784.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-march=armv7-a -mfloat-abi=hard -mfpu=neon -marm -O2" } */
+
+typedef struct __attribute__ ((__packed__))
+{
+ char valueField[2];
+} ptp_tlv_t;
+typedef struct __attribute__ ((__packed__))
+{
+ char stepsRemoved;
+ ptp_tlv_t tlv[1];
+} ptp_message_announce_t;
+int ptplib_send_announce(int sequenceId, int i)
+{
+ ptp_message_announce_t tx_packet;
+ ((long long *)tx_packet.tlv[0].valueField)[sequenceId] = i;
+ f(&tx_packet);
+}
diff --git a/gcc/testsuite/gcc.target/arm/require-pic-register-loc.c b/gcc/testsuite/gcc.target/arm/require-pic-register-loc.c
new file mode 100644
index 00000000000..bd85e8640c2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/require-pic-register-loc.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-g -fPIC" } */
+
+void *v;
+void a (void *x) { }
+void b (void) { }
+ /* line 7. */
+int /* line 8. */
+main (int argc) /* line 9. */
+{ /* line 10. */
+ if (argc == 12345) /* line 11. */
+ {
+ a (v);
+ return 1;
+ }
+ b ();
+
+ return 0;
+}
+
+/* { dg-final { scan-assembler-not "\.loc 1 7 0" } } */
+/* { dg-final { scan-assembler-not "\.loc 1 8 0" } } */
+/* { dg-final { scan-assembler-not "\.loc 1 9 0" } } */
+
+/* The loc at the start of the prologue. */
+/* { dg-final { scan-assembler-times "\.loc 1 10 0" 1 } } */
+
+/* The loc at the end of the prologue, with the first user line. */
+/* { dg-final { scan-assembler-times "\.loc 1 11 0" 1 } } */
diff --git a/gcc/testsuite/gcc.target/arm/thumb-ltu.c b/gcc/testsuite/gcc.target/arm/thumb-ltu.c
index 24671213e5f..d057ea34d25 100644
--- a/gcc/testsuite/gcc.target/arm/thumb-ltu.c
+++ b/gcc/testsuite/gcc.target/arm/thumb-ltu.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-skip-if "incompatible options" { arm*-*-* } { "-march=*" } { "-march=armv6" "-march=armv6j" "-march=armv6z" } } */
+/* { dg-require-effective-target arm_thumb1_ok } */
/* { dg-options "-mcpu=arm1136jf-s -mthumb -O2" } */
void f(unsigned a, unsigned b, unsigned c, unsigned d)
diff --git a/gcc/testsuite/gcc.target/avr/pr58545.c b/gcc/testsuite/gcc.target/avr/pr58545.c
new file mode 100644
index 00000000000..d1b8461f7cf
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/pr58545.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-Os -mmcu=atmega8" } */
+
+typedef unsigned char uint8_t;
+typedef unsigned int uint16_t;
+
+extern uint8_t f1 (const uint8_t*);
+extern void f2 (uint8_t*, uint8_t);
+
+void func (uint16_t parameter, uint8_t *addr, uint8_t data)
+{
+ uint8_t status;
+
+ status = f1 (addr + 8);
+
+ addr++;
+
+ if (*addr == parameter + 8)
+ *addr = parameter;
+
+ f2 (addr, data);
+ f2 (addr + 8, status + 1);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-1.c b/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-1.c
index e7eef6d7a90..1fe52bbb598 100644
--- a/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-1.c
@@ -14,6 +14,6 @@ avx_test (void)
c[i] = a[i] * b[i+3];
}
-/* { dg-final { scan-assembler-not "avx_loadups256" } } */
-/* { dg-final { scan-assembler "sse_loadups" } } */
+/* { dg-final { scan-assembler-not "(avx_loadups256|vmovups\[^\n\r]*movv8sf_internal)" } } */
+/* { dg-final { scan-assembler "(sse_loadups|movv4sf_internal)" } } */
/* { dg-final { scan-assembler "vinsertf128" } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-2.c b/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-2.c
index e3ec8542e01..933f265eed5 100644
--- a/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-2.c
+++ b/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-2.c
@@ -10,6 +10,6 @@ avx_test (char **cp, char **ep)
*ap++ = *cp++;
}
-/* { dg-final { scan-assembler-not "avx_loaddqu256" } } */
-/* { dg-final { scan-assembler "sse2_loaddqu" } } */
+/* { dg-final { scan-assembler-not "(avx_loaddqu256|vmovdqu\[^\n\r]*movv32qi_internal)" } } */
+/* { dg-final { scan-assembler "(sse2_loaddqu|vmovdqu\[^\n\r]*movv16qi_internal)" } } */
/* { dg-final { scan-assembler "vinsert.128" } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-3.c b/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-3.c
index b0e0e79bdd8..fe66e0b1713 100644
--- a/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-3.c
+++ b/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-3.c
@@ -14,6 +14,6 @@ avx_test (void)
c[i] = a[i] * b[i+3];
}
-/* { dg-final { scan-assembler-not "avx_loadupd256" } } */
-/* { dg-final { scan-assembler "sse2_loadupd" } } */
+/* { dg-final { scan-assembler-not "(avx_loadupd256|vmovupd\[^\n\r]*movv4df_internal)" } } */
+/* { dg-final { scan-assembler "(sse2_loadupd|vmovupd\[^\n\r]*movv2df_internal)" } } */
/* { dg-final { scan-assembler "vinsertf128" } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-4.c b/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-4.c
index c5afa061963..1d35ef57b48 100644
--- a/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-4.c
+++ b/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-4.c
@@ -14,6 +14,6 @@ avx_test (void)
b[i] = a[i+3] * 2;
}
-/* { dg-final { scan-assembler "avx_loadups256" } } */
-/* { dg-final { scan-assembler-not "sse_loadups" } } */
+/* { dg-final { scan-assembler "(avx_loadups256|vmovups\[^\n\r]*movv8sf_internal)" } } */
+/* { dg-final { scan-assembler-not "(sse_loadups|vmovups\[^\n\r]*movv4sf_internal)" } } */
/* { dg-final { scan-assembler-not "vinsertf128" } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-2.c b/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-2.c
index 977662beb34..48e2efa1382 100644
--- a/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-2.c
+++ b/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-2.c
@@ -24,5 +24,5 @@ avx_test (void)
}
/* { dg-final { scan-assembler-not "avx_storedqu256" } } */
-/* { dg-final { scan-assembler "vmovdqu.*\\*movv16qi_internal/3" } } */
+/* { dg-final { scan-assembler "vmovups.*\\*movv16qi_internal/3" } } */
/* { dg-final { scan-assembler "vextract.128" } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-3.c b/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-3.c
index e6744a892bc..6175d521764 100644
--- a/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-3.c
+++ b/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-3.c
@@ -18,5 +18,5 @@ avx_test (void)
}
/* { dg-final { scan-assembler-not "avx_storeupd256" } } */
-/* { dg-final { scan-assembler "vmovupd.*\\*movv2df_internal/3" } } */
+/* { dg-final { scan-assembler "vmovups.*\\*movv2df_internal/3" } } */
/* { dg-final { scan-assembler "vextractf128" } } */
diff --git a/gcc/testsuite/gcc.target/i386/builtin-ucmp.c b/gcc/testsuite/gcc.target/i386/builtin-ucmp.c
new file mode 100644
index 00000000000..709804c35f6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/builtin-ucmp.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ffast-math -mfpmath=sse -msse2" } */
+
+double foo(double a)
+{
+ return __builtin_round(a);
+}
+
+/* { dg-final { scan-assembler-not "ucom" } } */
diff --git a/gcc/testsuite/gcc.target/i386/cold-attribute-2.c b/gcc/testsuite/gcc.target/i386/cold-attribute-2.c
index 93ea906614f..4b61b9d56d8 100644
--- a/gcc/testsuite/gcc.target/i386/cold-attribute-2.c
+++ b/gcc/testsuite/gcc.target/i386/cold-attribute-2.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2" } */
+/* { dg-options "-O2 --param=builtin-expect-probability=100" } */
#include <string.h>
t(int c)
{
diff --git a/gcc/testsuite/gcc.target/i386/fma_double_3.c b/gcc/testsuite/gcc.target/i386/fma_double_3.c
index ac69684fee0..3a04777c6bf 100644
--- a/gcc/testsuite/gcc.target/i386/fma_double_3.c
+++ b/gcc/testsuite/gcc.target/i386/fma_double_3.c
@@ -8,11 +8,7 @@
#include "fma_3.h"
-/* { dg-final { scan-assembler-times "vfmadd132sd" 4 } } */
-/* { dg-final { scan-assembler-times "vfmadd231sd" 4 } } */
-/* { dg-final { scan-assembler-times "vfmsub132sd" 4 } } */
-/* { dg-final { scan-assembler-times "vfmsub231sd" 4 } } */
-/* { dg-final { scan-assembler-times "vfnmadd132sd" 4 } } */
-/* { dg-final { scan-assembler-times "vfnmadd231sd" 4 } } */
-/* { dg-final { scan-assembler-times "vfnmsub132sd" 4 } } */
-/* { dg-final { scan-assembler-times "vfnmsub231sd" 4 } } */
+/* { dg-final { scan-assembler-times "vfmadd\[123\]+sd" 8 } } */
+/* { dg-final { scan-assembler-times "vfmsub\[132\]+sd" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmadd\[132\]+sd" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmsub\[132\]+sd" 8 } } */
diff --git a/gcc/testsuite/gcc.target/i386/fma_double_5.c b/gcc/testsuite/gcc.target/i386/fma_double_5.c
index 3eca38c1494..640b552b0f0 100644
--- a/gcc/testsuite/gcc.target/i386/fma_double_5.c
+++ b/gcc/testsuite/gcc.target/i386/fma_double_5.c
@@ -8,7 +8,7 @@
#include "fma_5.h"
-/* { dg-final { scan-assembler-times "vfmadd132sd" 8 } } */
-/* { dg-final { scan-assembler-times "vfmsub132sd" 8 } } */
-/* { dg-final { scan-assembler-times "vfnmadd132sd" 8 } } */
-/* { dg-final { scan-assembler-times "vfnmsub132sd" 8 } } */
+/* { dg-final { scan-assembler-times "vfmadd\[132\]+sd" 8 } } */
+/* { dg-final { scan-assembler-times "vfmsub\[132\]+sd" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmadd\[132\]+sd" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmsub\[132\]+sd" 8 } } */
diff --git a/gcc/testsuite/gcc.target/i386/fma_float_3.c b/gcc/testsuite/gcc.target/i386/fma_float_3.c
index afb88b60745..7986ce4ee76 100644
--- a/gcc/testsuite/gcc.target/i386/fma_float_3.c
+++ b/gcc/testsuite/gcc.target/i386/fma_float_3.c
@@ -8,11 +8,7 @@
#include "fma_3.h"
-/* { dg-final { scan-assembler-times "vfmadd132ss" 4 } } */
-/* { dg-final { scan-assembler-times "vfmadd231ss" 4 } } */
-/* { dg-final { scan-assembler-times "vfmsub132ss" 4 } } */
-/* { dg-final { scan-assembler-times "vfmsub231ss" 4 } } */
-/* { dg-final { scan-assembler-times "vfnmadd132ss" 4 } } */
-/* { dg-final { scan-assembler-times "vfnmadd231ss" 4 } } */
-/* { dg-final { scan-assembler-times "vfnmsub132ss" 4 } } */
-/* { dg-final { scan-assembler-times "vfnmsub231ss" 4 } } */
+/* { dg-final { scan-assembler-times "vfmadd\[132\]+ss" 8 } } */
+/* { dg-final { scan-assembler-times "vfmsub\[132\]+ss" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmadd\[132\]+ss" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmsub\[132\]+ss" 8 } } */
diff --git a/gcc/testsuite/gcc.target/i386/fma_float_5.c b/gcc/testsuite/gcc.target/i386/fma_float_5.c
index cb067ca4a91..2105ae627f0 100644
--- a/gcc/testsuite/gcc.target/i386/fma_float_5.c
+++ b/gcc/testsuite/gcc.target/i386/fma_float_5.c
@@ -8,7 +8,7 @@
#include "fma_5.h"
-/* { dg-final { scan-assembler-times "vfmadd132ss" 8 } } */
-/* { dg-final { scan-assembler-times "vfmsub132ss" 8 } } */
-/* { dg-final { scan-assembler-times "vfnmadd132ss" 8 } } */
-/* { dg-final { scan-assembler-times "vfnmsub132ss" 8 } } */
+/* { dg-final { scan-assembler-times "vfmadd\[132\]+ss" 8 } } */
+/* { dg-final { scan-assembler-times "vfmsub\[132\]+ss" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmadd\[132\]+ss" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmsub\[132\]+ss" 8 } } */
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_double_1.c b/gcc/testsuite/gcc.target/i386/l_fma_double_1.c
index 3ceababec10..1d99b4caa5b 100644
--- a/gcc/testsuite/gcc.target/i386/l_fma_double_1.c
+++ b/gcc/testsuite/gcc.target/i386/l_fma_double_1.c
@@ -9,19 +9,11 @@ typedef double adouble __attribute__((aligned(sizeof (double))));
#include "l_fma_1.h"
-/* { dg-final { scan-assembler-times "vfmadd132pd" 4 } } */
-/* { dg-final { scan-assembler-times "vfmadd231pd" 4 } } */
-/* { dg-final { scan-assembler-times "vfmsub132pd" 4 } } */
-/* { dg-final { scan-assembler-times "vfmsub231pd" 4 } } */
-/* { dg-final { scan-assembler-times "vfnmadd132pd" 4 } } */
-/* { dg-final { scan-assembler-times "vfnmadd231pd" 4 } } */
-/* { dg-final { scan-assembler-times "vfnmsub132pd" 4 } } */
-/* { dg-final { scan-assembler-times "vfnmsub231pd" 4 } } */
-/* { dg-final { scan-assembler-times "vfmadd132sd" 28 } } */
-/* { dg-final { scan-assembler-times "vfmadd213sd" 28 } } */
-/* { dg-final { scan-assembler-times "vfmsub132sd" 28 } } */
-/* { dg-final { scan-assembler-times "vfmsub213sd" 28 } } */
-/* { dg-final { scan-assembler-times "vfnmadd132sd" 28 } } */
-/* { dg-final { scan-assembler-times "vfnmadd213sd" 28 } } */
-/* { dg-final { scan-assembler-times "vfnmsub132sd" 28 } } */
-/* { dg-final { scan-assembler-times "vfnmsub213sd" 28 } } */
+/* { dg-final { scan-assembler-times "vfmadd\[123\]+pd" 8 } } */
+/* { dg-final { scan-assembler-times "vfmsub\[123\]+pd" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmadd\[123\]+pd" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmsub\[123\]+pd" 8 } } */
+/* { dg-final { scan-assembler-times "vfmadd\[123\]+sd" 56 } } */
+/* { dg-final { scan-assembler-times "vfmsub\[123\]+sd" 56 } } */
+/* { dg-final { scan-assembler-times "vfnmadd\[123\]+sd" 56 } } */
+/* { dg-final { scan-assembler-times "vfnmsub\[123\]+sd" 56 } } */
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_double_2.c b/gcc/testsuite/gcc.target/i386/l_fma_double_2.c
index 713b24b7c27..e10110006f3 100644
--- a/gcc/testsuite/gcc.target/i386/l_fma_double_2.c
+++ b/gcc/testsuite/gcc.target/i386/l_fma_double_2.c
@@ -9,11 +9,11 @@ typedef double adouble __attribute__((aligned(sizeof (double))));
#include "l_fma_2.h"
-/* { dg-final { scan-assembler-times "vfmadd132pd" 8 } } */
-/* { dg-final { scan-assembler-times "vfmsub132pd" 8 } } */
-/* { dg-final { scan-assembler-times "vfnmadd132pd" 8 } } */
-/* { dg-final { scan-assembler-times "vfnmsub132pd" 8 } } */
-/* { dg-final { scan-assembler-times "vfmadd132sd" 56 } } */
-/* { dg-final { scan-assembler-times "vfmsub132sd" 56 } } */
-/* { dg-final { scan-assembler-times "vfnmadd132sd" 56 } } */
-/* { dg-final { scan-assembler-times "vfnmsub132sd" 56 } } */
+/* { dg-final { scan-assembler-times "vfmadd\[123\]+pd" 8 } } */
+/* { dg-final { scan-assembler-times "vfmsub\[123\]+pd" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmadd\[123\]+pd" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmsub\[123\]+pd" 8 } } */
+/* { dg-final { scan-assembler-times "vfmadd\[123\]+sd" 56 } } */
+/* { dg-final { scan-assembler-times "vfmsub\[123\]+sd" 56 } } */
+/* { dg-final { scan-assembler-times "vfnmadd\[123\]+sd" 56 } } */
+/* { dg-final { scan-assembler-times "vfnmsub\[123\]+sd" 56 } } */
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_double_3.c b/gcc/testsuite/gcc.target/i386/l_fma_double_3.c
index 74e3e1c55df..f099e25f8ed 100644
--- a/gcc/testsuite/gcc.target/i386/l_fma_double_3.c
+++ b/gcc/testsuite/gcc.target/i386/l_fma_double_3.c
@@ -9,19 +9,11 @@ typedef double adouble __attribute__((aligned(sizeof (double))));
#include "l_fma_3.h"
-/* { dg-final { scan-assembler-times "vfmadd132pd" 4 } } */
-/* { dg-final { scan-assembler-times "vfmadd231pd" 4 } } */
-/* { dg-final { scan-assembler-times "vfmsub132pd" 4 } } */
-/* { dg-final { scan-assembler-times "vfmsub231pd" 4 } } */
-/* { dg-final { scan-assembler-times "vfnmadd132pd" 4 } } */
-/* { dg-final { scan-assembler-times "vfnmadd231pd" 4 } } */
-/* { dg-final { scan-assembler-times "vfnmsub132pd" 4 } } */
-/* { dg-final { scan-assembler-times "vfnmsub231pd" 4 } } */
-/* { dg-final { scan-assembler-times "vfmadd132sd" 28 } } */
-/* { dg-final { scan-assembler-times "vfmadd213sd" 28 } } */
-/* { dg-final { scan-assembler-times "vfmsub132sd" 28 } } */
-/* { dg-final { scan-assembler-times "vfmsub213sd" 28 } } */
-/* { dg-final { scan-assembler-times "vfnmadd132sd" 28 } } */
-/* { dg-final { scan-assembler-times "vfnmadd213sd" 28 } } */
-/* { dg-final { scan-assembler-times "vfnmsub132sd" 28 } } */
-/* { dg-final { scan-assembler-times "vfnmsub213sd" 28 } } */
+/* { dg-final { scan-assembler-times "vfmadd\[123\]+pd" 8 } } */
+/* { dg-final { scan-assembler-times "vfmsub\[123\]+pd" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmadd\[123\]+pd" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmsub\[123\]+pd" 8 } } */
+/* { dg-final { scan-assembler-times "vfmadd\[123\]+sd" 56 } } */
+/* { dg-final { scan-assembler-times "vfmsub\[123\]+sd" 56 } } */
+/* { dg-final { scan-assembler-times "vfnmadd\[123\]+sd" 56 } } */
+/* { dg-final { scan-assembler-times "vfnmsub\[123\]+sd" 56 } } */
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_double_4.c b/gcc/testsuite/gcc.target/i386/l_fma_double_4.c
index d571aca1b01..969f31c7f35 100644
--- a/gcc/testsuite/gcc.target/i386/l_fma_double_4.c
+++ b/gcc/testsuite/gcc.target/i386/l_fma_double_4.c
@@ -9,11 +9,11 @@ typedef double adouble __attribute__((aligned(sizeof (double))));
#include "l_fma_4.h"
-/* { dg-final { scan-assembler-times "vfmadd132pd" 8 } } */
-/* { dg-final { scan-assembler-times "vfmsub132pd" 8 } } */
-/* { dg-final { scan-assembler-times "vfnmadd132pd" 8 } } */
-/* { dg-final { scan-assembler-times "vfnmsub132pd" 8 } } */
-/* { dg-final { scan-assembler-times "vfmadd132sd" 56 } } */
-/* { dg-final { scan-assembler-times "vfmsub132sd" 56 } } */
-/* { dg-final { scan-assembler-times "vfnmadd132sd" 56 } } */
-/* { dg-final { scan-assembler-times "vfnmsub132sd" 56 } } */
+/* { dg-final { scan-assembler-times "vfmadd\[123\]+pd" 8 } } */
+/* { dg-final { scan-assembler-times "vfmsub\[123\]+pd" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmadd\[123\]+pd" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmsub\[123\]+pd" 8 } } */
+/* { dg-final { scan-assembler-times "vfmadd\[123\]+sd" 56 } } */
+/* { dg-final { scan-assembler-times "vfmsub\[123\]+sd" 56 } } */
+/* { dg-final { scan-assembler-times "vfnmadd\[123\]+sd" 56 } } */
+/* { dg-final { scan-assembler-times "vfnmsub\[123\]+sd" 56 } } */
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_double_5.c b/gcc/testsuite/gcc.target/i386/l_fma_double_5.c
index 56d86369bc3..85ccdd0da44 100644
--- a/gcc/testsuite/gcc.target/i386/l_fma_double_5.c
+++ b/gcc/testsuite/gcc.target/i386/l_fma_double_5.c
@@ -9,11 +9,11 @@ typedef double adouble __attribute__((aligned(sizeof (double))));
#include "l_fma_5.h"
-/* { dg-final { scan-assembler-times "vfmadd132pd" 8 } } */
-/* { dg-final { scan-assembler-times "vfmsub132pd" 8 } } */
-/* { dg-final { scan-assembler-times "vfnmadd132pd" 8 } } */
-/* { dg-final { scan-assembler-times "vfnmsub132pd" 8 } } */
-/* { dg-final { scan-assembler-times "vfmadd132sd" 56 } } */
-/* { dg-final { scan-assembler-times "vfmsub132sd" 56 } } */
-/* { dg-final { scan-assembler-times "vfnmadd132sd" 56 } } */
-/* { dg-final { scan-assembler-times "vfnmsub132sd" 56 } } */
+/* { dg-final { scan-assembler-times "vfmadd\[123\]+pd" 8 } } */
+/* { dg-final { scan-assembler-times "vfmsub\[123\]+pd" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmadd\[123\]+pd" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmsub\[123\]+pd" 8 } } */
+/* { dg-final { scan-assembler-times "vfmadd\[123\]+sd" 56 } } */
+/* { dg-final { scan-assembler-times "vfmsub\[123\]+sd" 56 } } */
+/* { dg-final { scan-assembler-times "vfnmadd\[123\]+sd" 56 } } */
+/* { dg-final { scan-assembler-times "vfnmsub\[123\]+sd" 56 } } */
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_double_6.c b/gcc/testsuite/gcc.target/i386/l_fma_double_6.c
index f22763d6f99..019ed9ad028 100644
--- a/gcc/testsuite/gcc.target/i386/l_fma_double_6.c
+++ b/gcc/testsuite/gcc.target/i386/l_fma_double_6.c
@@ -9,11 +9,11 @@ typedef double adouble __attribute__((aligned(sizeof (double))));
#include "l_fma_6.h"
-/* { dg-final { scan-assembler-times "vfmadd132pd" 8 } } */
-/* { dg-final { scan-assembler-times "vfmsub132pd" 8 } } */
-/* { dg-final { scan-assembler-times "vfnmadd132pd" 8 } } */
-/* { dg-final { scan-assembler-times "vfnmsub132pd" 8 } } */
-/* { dg-final { scan-assembler-times "vfmadd132sd" 56 } } */
-/* { dg-final { scan-assembler-times "vfmsub132sd" 56 } } */
-/* { dg-final { scan-assembler-times "vfnmadd132sd" 56 } } */
-/* { dg-final { scan-assembler-times "vfnmsub132sd" 56 } } */
+/* { dg-final { scan-assembler-times "vfmadd\[123\]+pd" 8 } } */
+/* { dg-final { scan-assembler-times "vfmsub\[123\]+pd" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmadd\[123\]+pd" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmsub\[123\]+pd" 8 } } */
+/* { dg-final { scan-assembler-times "vfmadd\[123\]+sd" 56 } } */
+/* { dg-final { scan-assembler-times "vfmsub\[123\]+sd" 56 } } */
+/* { dg-final { scan-assembler-times "vfnmadd\[123\]+sd" 56 } } */
+/* { dg-final { scan-assembler-times "vfnmsub\[123\]+sd" 56 } } */
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_float_1.c b/gcc/testsuite/gcc.target/i386/l_fma_float_1.c
index 4a7ca95930e..d1913d7683f 100644
--- a/gcc/testsuite/gcc.target/i386/l_fma_float_1.c
+++ b/gcc/testsuite/gcc.target/i386/l_fma_float_1.c
@@ -8,19 +8,11 @@
#include "l_fma_1.h"
-/* { dg-final { scan-assembler-times "vfmadd132ps" 4 } } */
-/* { dg-final { scan-assembler-times "vfmadd231ps" 4 } } */
-/* { dg-final { scan-assembler-times "vfmsub132ps" 4 } } */
-/* { dg-final { scan-assembler-times "vfmsub231ps" 4 } } */
-/* { dg-final { scan-assembler-times "vfnmadd132ps" 4 } } */
-/* { dg-final { scan-assembler-times "vfnmadd231ps" 4 } } */
-/* { dg-final { scan-assembler-times "vfnmsub132ps" 4 } } */
-/* { dg-final { scan-assembler-times "vfnmsub231ps" 4 } } */
-/* { dg-final { scan-assembler-times "vfmadd132ss" 60 } } */
-/* { dg-final { scan-assembler-times "vfmadd213ss" 60 } } */
-/* { dg-final { scan-assembler-times "vfmsub132ss" 60 } } */
-/* { dg-final { scan-assembler-times "vfmsub213ss" 60 } } */
-/* { dg-final { scan-assembler-times "vfnmadd132ss" 60 } } */
-/* { dg-final { scan-assembler-times "vfnmadd213ss" 60 } } */
-/* { dg-final { scan-assembler-times "vfnmsub132ss" 60 } } */
-/* { dg-final { scan-assembler-times "vfnmsub213ss" 60 } } */
+/* { dg-final { scan-assembler-times "vfmadd\[123\]+ps" 8 } } */
+/* { dg-final { scan-assembler-times "vfmsub\[123\]+ps" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmadd\[123\]+ps" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmsub\[123\]+ps" 8 } } */
+/* { dg-final { scan-assembler-times "vfmadd\[123\]+ss" 120 } } */
+/* { dg-final { scan-assembler-times "vfmsub\[123\]+ss" 120 } } */
+/* { dg-final { scan-assembler-times "vfnmadd\[123\]+ss" 120 } } */
+/* { dg-final { scan-assembler-times "vfnmsub\[123\]+ss" 120 } } */
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_float_2.c b/gcc/testsuite/gcc.target/i386/l_fma_float_2.c
index 6377585bffe..5e0142545c8 100644
--- a/gcc/testsuite/gcc.target/i386/l_fma_float_2.c
+++ b/gcc/testsuite/gcc.target/i386/l_fma_float_2.c
@@ -8,11 +8,11 @@
#include "l_fma_2.h"
-/* { dg-final { scan-assembler-times "vfmadd132ps" 8 } } */
-/* { dg-final { scan-assembler-times "vfmsub132ps" 8 } } */
-/* { dg-final { scan-assembler-times "vfnmadd132ps" 8 } } */
-/* { dg-final { scan-assembler-times "vfnmsub132ps" 8 } } */
-/* { dg-final { scan-assembler-times "vfmadd132ss" 120 } } */
-/* { dg-final { scan-assembler-times "vfmsub132ss" 120 } } */
-/* { dg-final { scan-assembler-times "vfnmadd132ss" 120 } } */
-/* { dg-final { scan-assembler-times "vfnmsub132ss" 120 } } */
+/* { dg-final { scan-assembler-times "vfmadd\[123\]+ps" 8 } } */
+/* { dg-final { scan-assembler-times "vfmsub\[123\]+ps" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmadd\[123\]+ps" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmsub\[123\]+ps" 8 } } */
+/* { dg-final { scan-assembler-times "vfmadd\[123\]+ss" 120 } } */
+/* { dg-final { scan-assembler-times "vfmsub\[123\]+ss" 120 } } */
+/* { dg-final { scan-assembler-times "vfnmadd\[123\]+ss" 120 } } */
+/* { dg-final { scan-assembler-times "vfnmsub\[123\]+ss" 120 } } */
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_float_3.c b/gcc/testsuite/gcc.target/i386/l_fma_float_3.c
index f3fa74f98bd..7b9e3f54528 100644
--- a/gcc/testsuite/gcc.target/i386/l_fma_float_3.c
+++ b/gcc/testsuite/gcc.target/i386/l_fma_float_3.c
@@ -8,19 +8,11 @@
#include "l_fma_3.h"
-/* { dg-final { scan-assembler-times "vfmadd132ps" 4 } } */
-/* { dg-final { scan-assembler-times "vfmadd231ps" 4 } } */
-/* { dg-final { scan-assembler-times "vfmsub132ps" 4 } } */
-/* { dg-final { scan-assembler-times "vfmsub231ps" 4 } } */
-/* { dg-final { scan-assembler-times "vfnmadd132ps" 4 } } */
-/* { dg-final { scan-assembler-times "vfnmadd231ps" 4 } } */
-/* { dg-final { scan-assembler-times "vfnmsub132ps" 4 } } */
-/* { dg-final { scan-assembler-times "vfnmsub231ps" 4 } } */
-/* { dg-final { scan-assembler-times "vfmadd132ss" 60 } } */
-/* { dg-final { scan-assembler-times "vfmadd213ss" 60 } } */
-/* { dg-final { scan-assembler-times "vfmsub132ss" 60 } } */
-/* { dg-final { scan-assembler-times "vfmsub213ss" 60 } } */
-/* { dg-final { scan-assembler-times "vfnmadd132ss" 60 } } */
-/* { dg-final { scan-assembler-times "vfnmadd213ss" 60 } } */
-/* { dg-final { scan-assembler-times "vfnmsub132ss" 60 } } */
-/* { dg-final { scan-assembler-times "vfnmsub213ss" 60 } } */
+/* { dg-final { scan-assembler-times "vfmadd\[123\]+ps" 8 } } */
+/* { dg-final { scan-assembler-times "vfmsub\[123\]+ps" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmadd\[123\]+ps" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmsub\[123\]+ps" 8 } } */
+/* { dg-final { scan-assembler-times "vfmadd\[123\]+ss" 120 } } */
+/* { dg-final { scan-assembler-times "vfmsub\[123\]+ss" 120 } } */
+/* { dg-final { scan-assembler-times "vfnmadd\[123\]+ss" 120 } } */
+/* { dg-final { scan-assembler-times "vfnmsub\[123\]+ss" 120 } } */
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_float_4.c b/gcc/testsuite/gcc.target/i386/l_fma_float_4.c
index bacb01e7f3f..cc675c14aae 100644
--- a/gcc/testsuite/gcc.target/i386/l_fma_float_4.c
+++ b/gcc/testsuite/gcc.target/i386/l_fma_float_4.c
@@ -8,11 +8,11 @@
#include "l_fma_4.h"
-/* { dg-final { scan-assembler-times "vfmadd132ps" 8 } } */
-/* { dg-final { scan-assembler-times "vfmsub132ps" 8 } } */
-/* { dg-final { scan-assembler-times "vfnmadd132ps" 8 } } */
-/* { dg-final { scan-assembler-times "vfnmsub132ps" 8 } } */
-/* { dg-final { scan-assembler-times "vfmadd132ss" 120 } } */
-/* { dg-final { scan-assembler-times "vfmsub132ss" 120 } } */
-/* { dg-final { scan-assembler-times "vfnmadd132ss" 120 } } */
-/* { dg-final { scan-assembler-times "vfnmsub132ss" 120 } } */
+/* { dg-final { scan-assembler-times "vfmadd\[123\]+ps" 8 } } */
+/* { dg-final { scan-assembler-times "vfmsub\[123\]+ps" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmadd\[123\]+ps" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmsub\[123\]+ps" 8 } } */
+/* { dg-final { scan-assembler-times "vfmadd\[123\]+ss" 120 } } */
+/* { dg-final { scan-assembler-times "vfmsub\[123\]+ss" 120 } } */
+/* { dg-final { scan-assembler-times "vfnmadd\[123\]+ss" 120 } } */
+/* { dg-final { scan-assembler-times "vfnmsub\[123\]+ss" 120 } } */
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_float_5.c b/gcc/testsuite/gcc.target/i386/l_fma_float_5.c
index a32fc41d9f9..ac0b361475a 100644
--- a/gcc/testsuite/gcc.target/i386/l_fma_float_5.c
+++ b/gcc/testsuite/gcc.target/i386/l_fma_float_5.c
@@ -8,11 +8,11 @@
#include "l_fma_5.h"
-/* { dg-final { scan-assembler-times "vfmadd132ps" 8 } } */
-/* { dg-final { scan-assembler-times "vfmsub132ps" 8 } } */
-/* { dg-final { scan-assembler-times "vfnmadd132ps" 8 } } */
-/* { dg-final { scan-assembler-times "vfnmsub132ps" 8 } } */
-/* { dg-final { scan-assembler-times "vfmadd132ss" 120 } } */
-/* { dg-final { scan-assembler-times "vfmsub132ss" 120 } } */
-/* { dg-final { scan-assembler-times "vfnmadd132ss" 120 } } */
-/* { dg-final { scan-assembler-times "vfnmsub132ss" 120 } } */
+/* { dg-final { scan-assembler-times "vfmadd\[123\]+ps" 8 } } */
+/* { dg-final { scan-assembler-times "vfmsub\[123\]+ps" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmadd\[123\]+ps" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmsub\[123\]+ps" 8 } } */
+/* { dg-final { scan-assembler-times "vfmadd\[123\]+ss" 120 } } */
+/* { dg-final { scan-assembler-times "vfmsub\[123\]+ss" 120 } } */
+/* { dg-final { scan-assembler-times "vfnmadd\[123\]+ss" 120 } } */
+/* { dg-final { scan-assembler-times "vfnmsub\[123\]+ss" 120 } } */
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_float_6.c b/gcc/testsuite/gcc.target/i386/l_fma_float_6.c
index a7a74fb4222..c84ac1196b4 100644
--- a/gcc/testsuite/gcc.target/i386/l_fma_float_6.c
+++ b/gcc/testsuite/gcc.target/i386/l_fma_float_6.c
@@ -8,11 +8,11 @@
#include "l_fma_6.h"
-/* { dg-final { scan-assembler-times "vfmadd132ps" 8 } } */
-/* { dg-final { scan-assembler-times "vfmsub132ps" 8 } } */
-/* { dg-final { scan-assembler-times "vfnmadd132ps" 8 } } */
-/* { dg-final { scan-assembler-times "vfnmsub132ps" 8 } } */
-/* { dg-final { scan-assembler-times "vfmadd132ss" 120 } } */
-/* { dg-final { scan-assembler-times "vfmsub132ss" 120 } } */
-/* { dg-final { scan-assembler-times "vfnmadd132ss" 120 } } */
-/* { dg-final { scan-assembler-times "vfnmsub132ss" 120 } } */
+/* { dg-final { scan-assembler-times "vfmadd\[123\]+ps" 8 } } */
+/* { dg-final { scan-assembler-times "vfmsub\[123\]+ps" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmadd\[123\]+ps" 8 } } */
+/* { dg-final { scan-assembler-times "vfnmsub\[123\]+ps" 8 } } */
+/* { dg-final { scan-assembler-times "vfmadd\[123\]+ss" 120 } } */
+/* { dg-final { scan-assembler-times "vfmsub\[123\]+ss" 120 } } */
+/* { dg-final { scan-assembler-times "vfnmadd\[123\]+ss" 120 } } */
+/* { dg-final { scan-assembler-times "vfnmsub\[123\]+ss" 120 } } */
diff --git a/gcc/testsuite/gcc.target/i386/memset-vector_loop-1.c b/gcc/testsuite/gcc.target/i386/memset-vector_loop-1.c
new file mode 100644
index 00000000000..ad0d130371b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/memset-vector_loop-1.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=atom -minline-all-stringops -mstringop-strategy=vector_loop" } */
+/* { dg-final { scan-assembler-times "movdqa" 4 } } */
+
+char a[2048];
+void t (void)
+{
+ __builtin_memset (a, 0, 2048);
+}
+
+
diff --git a/gcc/testsuite/gcc.target/i386/memset-vector_loop-2.c b/gcc/testsuite/gcc.target/i386/memset-vector_loop-2.c
new file mode 100644
index 00000000000..f2ceb442c7b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/memset-vector_loop-2.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=atom -minline-all-stringops -mstringop-strategy=vector_loop" } */
+/* { dg-final { scan-assembler-times "movdqa" 4} } */
+
+char *a;
+void t (void)
+{
+ __builtin_memset (a, 0, 2048);
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/pr30315.c b/gcc/testsuite/gcc.target/i386/pr30315.c
index 998d5071e5c..557b4f75174 100644
--- a/gcc/testsuite/gcc.target/i386/pr30315.c
+++ b/gcc/testsuite/gcc.target/i386/pr30315.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-O2" } */
-/* { dg-final { scan-assembler-times "cmp" 4 } } */
+/* { dg-final { scan-assembler-not "cmp" } } */
extern void abort (void);
int c;
@@ -34,39 +34,10 @@ void pluscconly##t##C (T a, T b) \
}
#define PLUSCCONLY(T, t) PLUSCCONLY1(T, t, a) PLUSCCONLY1(T, t, b)
-#define MINUSCC(T, t) \
-T minuscc##t (T a, T b) \
-{ \
- T difference = a - b; \
- if (difference > a) \
- abort (); \
- return difference; \
-}
-
-#define DECCC(T, t) \
-T deccc##t (T a, T b) \
-{ \
- T difference = a - b; \
- if (difference > a) \
- c --; \
- return difference; \
-}
-
-#define MINUSCCONLY(T, t) \
-void minuscconly##t (T a, T b) \
-{ \
- T difference = a - b; \
- if (difference > a) \
- abort (); \
-}
-
#define TEST(T, t) \
PLUSCC(T, t) \
PLUSCCONLY(T, t) \
- INCCC(T, t) \
- MINUSCC(T, t) \
- MINUSCCONLY(T, t) \
- DECCC(T, t)
+ INCCC(T, t)
TEST (unsigned long, l)
TEST (unsigned int, i)
@@ -84,14 +55,3 @@ unsigned long pluscczext##C (unsigned int a, unsigned int b) \
PLUSCCZEXT(a)
PLUSCCZEXT(b)
-
-#define MINUSCCZEXT \
-unsigned long minuscczext (unsigned int a, unsigned int b) \
-{ \
- unsigned int difference = a - b; \
- if (difference > a) \
- abort (); \
- return difference; \
-}
-
-MINUSCCZEXT
diff --git a/gcc/testsuite/gcc.target/i386/pr49002-2.c b/gcc/testsuite/gcc.target/i386/pr49002-2.c
index b0e10091b5c..9f21a2d17d9 100644
--- a/gcc/testsuite/gcc.target/i386/pr49002-2.c
+++ b/gcc/testsuite/gcc.target/i386/pr49002-2.c
@@ -11,4 +11,5 @@ void foo(const __m128d from, __m256d *to)
/* Ensure we store ymm, not xmm. */
/* { dg-final { scan-assembler-not "vmovapd\[\t \]*%xmm\[0-9\]\+,\[^,\]*" } } */
-/* { dg-final { scan-assembler "vmovapd\[\t \]*%ymm\[0-9\]\+,\[^,\]*" } } */
+/* { dg-final { scan-assembler-not "vmovaps\[\t \]*%xmm\[0-9\]\+,\[^,\]*" } } */
+/* { dg-final { scan-assembler "vmovaps\[\t \]*%ymm\[0-9\]\+,\[^,\]*" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr49168-1.c b/gcc/testsuite/gcc.target/i386/pr49168-1.c
index 9676dc85a8e..4ca5e34d9cb 100644
--- a/gcc/testsuite/gcc.target/i386/pr49168-1.c
+++ b/gcc/testsuite/gcc.target/i386/pr49168-1.c
@@ -2,7 +2,8 @@
/* { dg-do compile } */
/* { dg-options "-O2 -msse2 -mtune=generic" } */
/* { dg-final { scan-assembler-not "movdqa\[\t \]*%xmm\[0-9\]\+,\[^,\]*" } } */
-/* { dg-final { scan-assembler "movdqu\[\t \]*%xmm\[0-9\]\+,\[^,\]*" } } */
+/* { dg-final { scan-assembler-not "movaps\[\t \]*%xmm\[0-9\]\+,\[^,\]*" } } */
+/* { dg-final { scan-assembler "movups\[\t \]*%xmm\[0-9\]\+,\[^,\]*" } } */
void
flt128_va (void *mem, __float128 d)
diff --git a/gcc/testsuite/gcc.target/i386/pr57756.c b/gcc/testsuite/gcc.target/i386/pr57756.c
new file mode 100644
index 00000000000..81d53bfd565
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr57756.c
@@ -0,0 +1,22 @@
+/* callee cannot be inlined into caller because it has a higher
+ target ISA. */
+/* { dg-do compile } */
+
+__attribute__((always_inline,target("sse4.2")))
+__inline int callee () /* { dg-error "inlining failed in call to always_inline" } */
+{
+ return 0;
+}
+
+__attribute__((target("sse")))
+__inline int caller ()
+{
+ return callee(); /* { dg-error "called from here" } */
+}
+
+int main ()
+{
+ return caller();
+}
+/* callee cannot be inlined into caller because it has a higher
+ target ISA. */
diff --git a/gcc/testsuite/gcc.target/i386/pr57756_2.c b/gcc/testsuite/gcc.target/i386/pr57756_2.c
new file mode 100644
index 00000000000..0227d8ff402
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr57756_2.c
@@ -0,0 +1,132 @@
+/* { dg-do run } */
+/* { dg-options "-mno-sse2 -mno-popcnt -mno-avx" } */
+
+
+__attribute__((always_inline,target("avx2")))
+__inline int c1 ()
+{
+ return 0;
+}
+
+__attribute__((always_inline,target("avx")))
+__inline int c2 ()
+{
+ return 0;
+}
+
+__attribute__((always_inline,target("popcnt")))
+__inline int c3 ()
+{
+ return 0;
+}
+
+__attribute__((always_inline,target("sse4.2")))
+__inline int c4 ()
+{
+ return 0;
+}
+
+__attribute__((always_inline,target("sse4.1")))
+__inline int c5 ()
+{
+ return 0;
+}
+
+__attribute__((always_inline,target("ssse3")))
+__inline int c6 ()
+{
+ return 0;
+}
+
+__attribute__((always_inline,target("sse3")))
+__inline int c7 ()
+{
+ return 0;
+}
+
+__attribute__((always_inline,target("sse2")))
+__inline int c8 ()
+{
+ return 0;
+}
+
+int nop ()
+{
+ return 1;
+}
+
+#pragma GCC push_options
+#pragma GCC target("sse2")
+int C8 ()
+{
+ return c8 ();
+}
+#pragma GCC pop_options
+
+
+#pragma GCC push_options
+#pragma GCC target("sse3")
+int C7 ()
+{
+ return c7 ();
+}
+#pragma GCC pop_options
+
+
+#pragma GCC push_options
+#pragma GCC target("ssse3")
+int C6 ()
+{
+ return c6 ();
+}
+#pragma GCC pop_options
+
+
+#pragma GCC push_options
+#pragma GCC target("sse4.1")
+int C5 ()
+{
+ return c5 ();
+}
+#pragma GCC pop_options
+
+
+#pragma GCC push_options
+#pragma GCC target("sse4.2")
+int C4 ()
+{
+ return c4 ();
+}
+#pragma GCC pop_options
+
+
+#pragma GCC push_options
+#pragma GCC target("popcnt")
+int C3 ()
+{
+ return c3 ();
+}
+#pragma GCC pop_options
+
+
+#pragma GCC push_options
+#pragma GCC target("avx")
+int C2 ()
+{
+ return c2 ();
+}
+#pragma GCC pop_options
+
+
+#pragma GCC push_options
+#pragma GCC target("avx2")
+int C1 ()
+{
+ return c1 ();
+}
+#pragma GCC pop_options
+
+int main ()
+{
+ return C1 () + C2 () + C3 () + C4 () + C5 () + C6 () + C7 () + C8 ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr58679-1.c b/gcc/testsuite/gcc.target/i386/pr58679-1.c
new file mode 100644
index 00000000000..91db8e63e7f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr58679-1.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx" } */
+
+typedef struct { char a; long long b; } S;
+
+S foo (S x, S y)
+{
+ S z;
+
+ z.a = 0;
+ z.b = x.b / y.b;
+ return z;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr58679-2.c b/gcc/testsuite/gcc.target/i386/pr58679-2.c
new file mode 100644
index 00000000000..b63545bc076
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr58679-2.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx" } */
+
+int f (long long a, long long b)
+{
+ return (a * b) >> 16;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr58690.c b/gcc/testsuite/gcc.target/i386/pr58690.c
new file mode 100644
index 00000000000..87a87cc9c90
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr58690.c
@@ -0,0 +1,14 @@
+/* { dg-do compile { target { ! { ia32 } } } } */
+/* { dg-require-effective-target maybe_x32 } */
+/* { dg-options "-O2 -mx32 -maddress-mode=short" } */
+
+struct gomp_thread
+{
+ char foo[41];
+};
+extern __thread struct gomp_thread gomp_tls_data;
+void
+foo (void)
+{
+ __builtin_memset (&gomp_tls_data, '\0', sizeof (gomp_tls_data));
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr58759.c b/gcc/testsuite/gcc.target/i386/pr58759.c
new file mode 100644
index 00000000000..8257dde533d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr58759.c
@@ -0,0 +1,38 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+
+int a, b, c, d, e, f, h, l, m, n, k, o;
+long long g;
+
+struct S
+{
+ int f1;
+ int f2;
+ int f3;
+ int f4;
+};
+
+static struct S i = {0,0,0,0}, j;
+
+void
+foo ()
+{
+ m = 1 & d;
+ n = b + c;
+ o = k >> 1;
+ f = 0 == e;
+}
+
+int
+main ()
+{
+ for (; h < 1; h++)
+ {
+ g = 1 | (0 > 1 - a ? 0 : a);
+ foo ();
+ for (l = 0; l < 3; l++)
+ j = i;
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr58853.c b/gcc/testsuite/gcc.target/i386/pr58853.c
new file mode 100644
index 00000000000..046da8bee5f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr58853.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-minline-all-stringops" } */
+/* { dg-additional-options "-mtune=pentiumpro" { target { ia32 } } } */
+
+void
+my_memcpy (char *dest, const char *src, int n)
+{
+ __builtin_memcpy (dest, src, n);
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr59021.c b/gcc/testsuite/gcc.target/i386/pr59021.c
new file mode 100644
index 00000000000..a1df27b105e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr59021.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx -mvzeroupper" } */
+
+extern void abort (void);
+
+struct S {
+ int i1;
+ int i2;
+ int i3;
+};
+
+typedef double v4df __attribute__ ((vector_size (32)));
+
+extern int foo (v4df, int i1, int i2, int i3, int i4, int i5, struct S s);
+
+void bar (v4df v, struct S s)
+{
+ int r = foo (v, 1, 2, 3, 4, 5, s);
+ if (r)
+ abort ();
+}
+
+/* { dg-final { scan-assembler-not "vzeroupper" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr59034-1.c b/gcc/testsuite/gcc.target/i386/pr59034-1.c
new file mode 100644
index 00000000000..1f4c4e04a23
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr59034-1.c
@@ -0,0 +1,10 @@
+/* { dg-do compile { target { ! { ia32 } } } } */
+/* { dg-require-effective-target maybe_x32 } */
+/* { dg-options "-O -mx32 -mtune=corei7 -maddress-mode=short" } */
+
+extern int foo(int, ...);
+int bar(void) {
+ long double l = 1.2345E6;
+ foo(0, l);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr59034-2.c b/gcc/testsuite/gcc.target/i386/pr59034-2.c
new file mode 100644
index 00000000000..14e594ba608
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr59034-2.c
@@ -0,0 +1,10 @@
+/* { dg-do compile { target { ! { ia32 } } } } */
+/* { dg-require-effective-target maybe_x32 } */
+/* { dg-options "-O -mx32 -mtune=corei7 -maddress-mode=long" } */
+
+extern int foo(int, ...);
+int bar(void) {
+ long double l = 1.2345E6;
+ foo(0, l);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/vect-abs-s16.c b/gcc/testsuite/gcc.target/i386/vect-abs-s16.c
new file mode 100644
index 00000000000..191ae3434e4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/vect-abs-s16.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -msse2 -mno-sse3 -fdump-tree-vect-details" } */
+
+
+void test (short* a, short* b)
+{
+ int i;
+ for (i = 0; i < 10000; ++i)
+ a[i] = abs (b[i]);
+}
+
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
diff --git a/gcc/testsuite/gcc.target/i386/vect-abs-s32.c b/gcc/testsuite/gcc.target/i386/vect-abs-s32.c
new file mode 100644
index 00000000000..575e8efe0a8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/vect-abs-s32.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -msse2 -mno-sse3 -fdump-tree-vect-details" } */
+
+
+void test (int* a, int* b)
+{
+ int i;
+ for (i = 0; i < 10000; ++i)
+ a[i] = abs (b[i]);
+}
+
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
diff --git a/gcc/testsuite/gcc.target/i386/vect-abs-s8.c b/gcc/testsuite/gcc.target/i386/vect-abs-s8.c
new file mode 100644
index 00000000000..3f3f3facb79
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/vect-abs-s8.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -msse2 -mno-sse3 -fdump-tree-vect-details" } */
+
+
+void test (char* a, char* b)
+{
+ int i;
+ for (i = 0; i < 10000; ++i)
+ a[i] = abs (b[i]);
+}
+
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
diff --git a/gcc/testsuite/gcc.target/i386/vect-div-1.c b/gcc/testsuite/gcc.target/i386/vect-div-1.c
new file mode 100644
index 00000000000..b3eed19c7d7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/vect-div-1.c
@@ -0,0 +1,43 @@
+/* { dg-do compile { target sse2 } } */
+/* { dg-options "-O2 -ftree-vectorize -fno-common -msse2" } */
+
+unsigned short b[1024] = { 0 };
+int a[1024] = { 0 };
+
+int
+f1 (int x)
+{
+ int i;
+ for (i = 0; i < 1024; i++)
+ a[i] = (b[i] + 7) / 15;
+}
+
+int
+f2 (int x)
+{
+ int i;
+ for (i = 0; i < 1024; i++)
+ a[i] = (b[i] + 7) % 15;
+}
+
+int
+f3 (int x)
+{
+ int i;
+ for (i = 0; i < 1024; i++)
+ a[i] = (b[i] - 66000) / 15;
+}
+
+int
+f4 (int x)
+{
+ int i;
+ for (i = 0; i < 1024; i++)
+ a[i] = (b[i] - 66000) % 15;
+}
+
+/* In f1 and f2, VRP can prove the first operand of division or modulo
+ is always non-negative, so there is no need to do >> 31 shift
+ etc. to check if it is. And in f3 and f4, VRP can prove it is always
+ negative. */
+/* { dg-final { scan-assembler-not "psrad\[^\n\r\]*\\\$31" } } */
diff --git a/gcc/testsuite/gcc.target/mips/bswap-1.c b/gcc/testsuite/gcc.target/mips/bswap-1.c
new file mode 100644
index 00000000000..24016f26931
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/bswap-1.c
@@ -0,0 +1,10 @@
+/* { dg-options "isa_rev>=2" } */
+/* { dg-skip-if "bswap recognition needs expensive optimizations" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+NOMIPS16 unsigned short
+foo (unsigned short x)
+{
+ return ((x << 8) & 0xff00) | ((x >> 8) & 0xff);
+}
+
+/* { dg-final { scan-assembler "\twsbh\t" } } */
diff --git a/gcc/testsuite/gcc.target/mips/bswap-2.c b/gcc/testsuite/gcc.target/mips/bswap-2.c
new file mode 100644
index 00000000000..e0ca496b6d1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/bswap-2.c
@@ -0,0 +1,9 @@
+/* { dg-options "isa_rev>=2" } */
+
+NOMIPS16 unsigned short
+foo (unsigned short x)
+{
+ return __builtin_bswap16 (x);
+}
+
+/* { dg-final { scan-assembler "\twsbh\t" } } */
diff --git a/gcc/testsuite/gcc.target/mips/bswap-3.c b/gcc/testsuite/gcc.target/mips/bswap-3.c
new file mode 100644
index 00000000000..5d2086fd324
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/bswap-3.c
@@ -0,0 +1,14 @@
+/* { dg-options "isa_rev>=2" } */
+/* { dg-skip-if "bswap recognition needs expensive optimizations" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+NOMIPS16 unsigned int
+foo (unsigned int x)
+{
+ return (((x << 24) & 0xff000000)
+ | ((x << 8) & 0xff0000)
+ | ((x >> 8) & 0xff00)
+ | ((x >> 24) & 0xff));
+}
+
+/* { dg-final { scan-assembler "\twsbh\t" } } */
+/* { dg-final { scan-assembler "\tror\t" } } */
diff --git a/gcc/testsuite/gcc.target/mips/bswap-4.c b/gcc/testsuite/gcc.target/mips/bswap-4.c
new file mode 100644
index 00000000000..ac37a011440
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/bswap-4.c
@@ -0,0 +1,10 @@
+/* { dg-options "isa_rev>=2" } */
+
+NOMIPS16 unsigned int
+foo (unsigned int x)
+{
+ return __builtin_bswap32 (x);
+}
+
+/* { dg-final { scan-assembler "\twsbh\t" } } */
+/* { dg-final { scan-assembler "\tror\t" } } */
diff --git a/gcc/testsuite/gcc.target/mips/bswap-5.c b/gcc/testsuite/gcc.target/mips/bswap-5.c
new file mode 100644
index 00000000000..45520e4ab85
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/bswap-5.c
@@ -0,0 +1,20 @@
+/* { dg-options "isa_rev>=2 -mgp64" } */
+/* { dg-skip-if "bswap recognition needs expensive optimizations" { *-*-* } { "-O0" "-O1" } { "" } } */
+
+typedef unsigned long long uint64_t;
+
+NOMIPS16 uint64_t
+foo (uint64_t x)
+{
+ return (((x << 56) & 0xff00000000000000ull)
+ | ((x << 40) & 0xff000000000000ull)
+ | ((x << 24) & 0xff0000000000ull)
+ | ((x << 8) & 0xff00000000ull)
+ | ((x >> 8) & 0xff000000)
+ | ((x >> 24) & 0xff0000)
+ | ((x >> 40) & 0xff00)
+ | ((x >> 56) & 0xff));
+}
+
+/* { dg-final { scan-assembler "\tdsbh\t" } } */
+/* { dg-final { scan-assembler "\tdshd\t" } } */
diff --git a/gcc/testsuite/gcc.target/mips/bswap-6.c b/gcc/testsuite/gcc.target/mips/bswap-6.c
new file mode 100644
index 00000000000..1145357fef1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/bswap-6.c
@@ -0,0 +1,12 @@
+/* { dg-options "isa_rev>=2 -mgp64" } */
+
+typedef unsigned long long uint64_t;
+
+NOMIPS16 uint64_t
+foo (uint64_t x)
+{
+ return __builtin_bswap64 (x);
+}
+
+/* { dg-final { scan-assembler "\tdsbh\t" } } */
+/* { dg-final { scan-assembler "\tdshd\t" } } */
diff --git a/gcc/testsuite/gcc.target/mips/mips-ps-5.c b/gcc/testsuite/gcc.target/mips/mips-ps-5.c
index 6bf908ee976..077076f4736 100644
--- a/gcc/testsuite/gcc.target/mips/mips-ps-5.c
+++ b/gcc/testsuite/gcc.target/mips/mips-ps-5.c
@@ -2,7 +2,9 @@
/* { dg-options "-mpaired-single -mgp64 -ftree-vectorize" } */
/* { dg-skip-if "requires vectorization" { *-*-* } { "-O0" "-Os" } { "" } } */
-extern float a[], b[], c[];
+extern float a[] __attribute__ ((aligned (8)));
+extern float b[] __attribute__ ((aligned (8)));
+extern float c[] __attribute__ ((aligned (8)));
NOMIPS16 void
foo (void)
diff --git a/gcc/testsuite/gcc.target/mips/mips-ps-7.c b/gcc/testsuite/gcc.target/mips/mips-ps-7.c
index 35d25fdc89c..3b4e5308598 100644
--- a/gcc/testsuite/gcc.target/mips/mips-ps-7.c
+++ b/gcc/testsuite/gcc.target/mips/mips-ps-7.c
@@ -3,7 +3,9 @@
/* { dg-options "-mgp32 -mpaired-single -ftree-vectorize" } */
/* { dg-skip-if "requires vectorization" { *-*-* } { "-O0" "-Os" } { "" } } */
-extern float a[], b[], c[];
+extern float a[] __attribute__ ((aligned (8)));
+extern float b[] __attribute__ ((aligned (8)));
+extern float c[] __attribute__ ((aligned (8)));
NOMIPS16 void
foo (void)
diff --git a/gcc/testsuite/gcc.target/mips/nor.c b/gcc/testsuite/gcc.target/mips/nor.c
new file mode 100644
index 00000000000..e71791ba31f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/nor.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+/* { dg-final { scan-assembler-times "\tnor\t" 1 } } */
+/* { dg-final { scan-assembler-not "\tor" } } */
+
+/* Test that we generate a 'nor' instruction and no 'or' instructions. */
+
+NOMIPS16 int f (int a, int b)
+{
+ return ~(a|b);
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/altivec-perm-1.c b/gcc/testsuite/gcc.target/powerpc/altivec-perm-1.c
index ee5c5eee900..c3cf67e44f4 100644
--- a/gcc/testsuite/gcc.target/powerpc/altivec-perm-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/altivec-perm-1.c
@@ -19,19 +19,6 @@ V b4(V x)
return __builtin_shuffle(x, (V){ 4,5,6,7, 4,5,6,7, 4,5,6,7, 4,5,6,7, });
}
-V p2(V x, V y)
-{
- return __builtin_shuffle(x, y,
- (V){ 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31 });
-
-}
-
-V p4(V x, V y)
-{
- return __builtin_shuffle(x, y,
- (V){ 2, 3, 6, 7, 10, 11, 14, 15, 18, 19, 22, 23, 26, 27, 30, 31 });
-}
-
V h1(V x, V y)
{
return __builtin_shuffle(x, y,
@@ -72,5 +59,3 @@ V l4(V x, V y)
/* { dg-final { scan-assembler "vspltb" } } */
/* { dg-final { scan-assembler "vsplth" } } */
/* { dg-final { scan-assembler "vspltw" } } */
-/* { dg-final { scan-assembler "vpkuhum" } } */
-/* { dg-final { scan-assembler "vpkuwum" } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/altivec-perm-3.c b/gcc/testsuite/gcc.target/powerpc/altivec-perm-3.c
new file mode 100644
index 00000000000..d0b671eac77
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/altivec-perm-3.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target powerpc_altivec_ok } */
+/* { dg-skip-if "" { powerpc*le-*-* } { "*" } { "" } } */
+/* { dg-options "-O -maltivec -mno-vsx" } */
+
+typedef unsigned char V __attribute__((vector_size(16)));
+
+V p2(V x, V y)
+{
+ return __builtin_shuffle(x, y,
+ (V){ 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31 });
+
+}
+
+V p4(V x, V y)
+{
+ return __builtin_shuffle(x, y,
+ (V){ 2, 3, 6, 7, 10, 11, 14, 15, 18, 19, 22, 23, 26, 27, 30, 31 });
+}
+
+/* { dg-final { scan-assembler-not "vperm" } } */
+/* { dg-final { scan-assembler "vpkuhum" } } */
+/* { dg-final { scan-assembler "vpkuwum" } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/crypto-builtin-1.c b/gcc/testsuite/gcc.target/powerpc/crypto-builtin-1.c
index 87291954ee3..ce5da6a03d1 100644
--- a/gcc/testsuite/gcc.target/powerpc/crypto-builtin-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/crypto-builtin-1.c
@@ -1,7 +1,7 @@
/* { dg-do compile { target { powerpc*-*-* } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
/* { dg-require-effective-target powerpc_p8vector_ok } */
-/* { dg-options "-mcpu=power8 -O2 -ftree-vectorize -fvect-cost-model -fno-unroll-loops -fno-unroll-all-loops" } */
+/* { dg-options "-mcpu=power8 -O2 -ftree-vectorize -fvect-cost-model=dynamic -fno-unroll-loops -fno-unroll-all-loops" } */
typedef vector unsigned long long crypto_t;
typedef vector unsigned long long v2di_t;
diff --git a/gcc/testsuite/gcc.target/powerpc/direct-move.h b/gcc/testsuite/gcc.target/powerpc/direct-move.h
index 4e84fd678bb..c1709e6c7ef 100644
--- a/gcc/testsuite/gcc.target/powerpc/direct-move.h
+++ b/gcc/testsuite/gcc.target/powerpc/direct-move.h
@@ -1,5 +1,7 @@
/* Test functions for direct move support. */
+#include <math.h>
+extern void abort (void);
void __attribute__((__noinline__))
copy (TYPE *a, TYPE *b)
@@ -107,7 +109,7 @@ const struct test_struct test_functions[] = {
void __attribute__((__noinline__))
test_value (TYPE a)
{
- size_t i;
+ long i;
for (i = 0; i < sizeof (test_functions) / sizeof (test_functions[0]); i++)
{
@@ -123,8 +125,7 @@ test_value (TYPE a)
int
main (void)
{
- size_t i;
- long j;
+ long i,j;
union {
TYPE value;
unsigned char bytes[sizeof (TYPE)];
diff --git a/gcc/testsuite/gcc.target/powerpc/fusion.c b/gcc/testsuite/gcc.target/powerpc/fusion.c
index 3bea1c9f5a8..60e635972c4 100644
--- a/gcc/testsuite/gcc.target/powerpc/fusion.c
+++ b/gcc/testsuite/gcc.target/powerpc/fusion.c
@@ -1,5 +1,6 @@
/* { dg-do compile { target { powerpc*-*-* } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-skip-if "" { powerpc*le-*-* } { "*" } { "" } } */
/* { dg-require-effective-target powerpc_p8vector_ok } */
/* { dg-options "-mcpu=power7 -mtune=power8 -O3" } */
diff --git a/gcc/testsuite/gcc.target/powerpc/p8vector-builtin-1.c b/gcc/testsuite/gcc.target/powerpc/p8vector-builtin-1.c
index 6fd3acc2a9d..f0a68ec8845 100644
--- a/gcc/testsuite/gcc.target/powerpc/p8vector-builtin-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/p8vector-builtin-1.c
@@ -1,7 +1,7 @@
/* { dg-do compile { target { powerpc*-*-* } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
/* { dg-require-effective-target powerpc_p8vector_ok } */
-/* { dg-options "-mcpu=power8 -O2 -ftree-vectorize -fvect-cost-model -fno-unroll-loops -fno-unroll-all-loops" } */
+/* { dg-options "-mcpu=power8 -O2 -ftree-vectorize -fvect-cost-model=dynamic -fno-unroll-loops -fno-unroll-all-loops" } */
#ifndef TYPE
#define TYPE long long
diff --git a/gcc/testsuite/gcc.target/powerpc/p8vector-builtin-2.c b/gcc/testsuite/gcc.target/powerpc/p8vector-builtin-2.c
index 412040bfa05..394f416403f 100644
--- a/gcc/testsuite/gcc.target/powerpc/p8vector-builtin-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/p8vector-builtin-2.c
@@ -1,7 +1,7 @@
/* { dg-do compile { target { powerpc*-*-* } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
/* { dg-require-effective-target powerpc_p8vector_ok } */
-/* { dg-options "-mcpu=power8 -O2 -ftree-vectorize -fvect-cost-model -fno-unroll-loops -fno-unroll-all-loops" } */
+/* { dg-options "-mcpu=power8 -O2 -ftree-vectorize -fvect-cost-model=dynamic -fno-unroll-loops -fno-unroll-all-loops" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/p8vector-builtin-3.c b/gcc/testsuite/gcc.target/powerpc/p8vector-builtin-3.c
index b3f725f2d96..cb8a5b8afeb 100644
--- a/gcc/testsuite/gcc.target/powerpc/p8vector-builtin-3.c
+++ b/gcc/testsuite/gcc.target/powerpc/p8vector-builtin-3.c
@@ -1,7 +1,7 @@
/* { dg-do compile { target { powerpc*-*-* } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
/* { dg-require-effective-target powerpc_p8vector_ok } */
-/* { dg-options "-mcpu=power8 -O3 -ftree-vectorize -fvect-cost-model" } */
+/* { dg-options "-mcpu=power8 -O3 -ftree-vectorize -fvect-cost-model=dynamic" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/p8vector-builtin-4.c b/gcc/testsuite/gcc.target/powerpc/p8vector-builtin-4.c
index 518a6aa5e64..8aaa6eacaab 100644
--- a/gcc/testsuite/gcc.target/powerpc/p8vector-builtin-4.c
+++ b/gcc/testsuite/gcc.target/powerpc/p8vector-builtin-4.c
@@ -1,7 +1,7 @@
/* { dg-do compile { target { powerpc*-*-* } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
/* { dg-require-effective-target powerpc_p8vector_ok } */
-/* { dg-options "-mcpu=power8 -O3 -ftree-vectorize -fvect-cost-model" } */
+/* { dg-options "-mcpu=power8 -O3 -ftree-vectorize -fvect-cost-model=dynamic" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/p8vector-builtin-5.c b/gcc/testsuite/gcc.target/powerpc/p8vector-builtin-5.c
index 2e64551ff68..36de9eb9bf0 100644
--- a/gcc/testsuite/gcc.target/powerpc/p8vector-builtin-5.c
+++ b/gcc/testsuite/gcc.target/powerpc/p8vector-builtin-5.c
@@ -1,7 +1,7 @@
/* { dg-do compile { target { powerpc*-*-* } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
/* { dg-require-effective-target powerpc_p8vector_ok } */
-/* { dg-options "-mcpu=power8 -O2 -ftree-vectorize -fvect-cost-model -fno-unroll-loops -fno-unroll-all-loops" } */
+/* { dg-options "-mcpu=power8 -O2 -ftree-vectorize -fvect-cost-model=dynamic -fno-unroll-loops -fno-unroll-all-loops" } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/p8vector-fp.c b/gcc/testsuite/gcc.target/powerpc/p8vector-fp.c
new file mode 100644
index 00000000000..3cfd8161dd6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/p8vector-fp.c
@@ -0,0 +1,139 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_p8vector_ok } */
+/* { dg-options "-mcpu=power8 -O2 -mupper-regs-df -mupper-regs-sf -fno-math-errno" } */
+
+float abs_sf (float *p)
+{
+ float f = *p;
+ __asm__ ("# reg %x0" : "+v" (f));
+ return __builtin_fabsf (f);
+}
+
+float nabs_sf (float *p)
+{
+ float f = *p;
+ __asm__ ("# reg %x0" : "+v" (f));
+ return - __builtin_fabsf (f);
+}
+
+float neg_sf (float *p)
+{
+ float f = *p;
+ __asm__ ("# reg %x0" : "+v" (f));
+ return - f;
+}
+
+float add_sf (float *p, float *q)
+{
+ float f1 = *p;
+ float f2 = *q;
+ __asm__ ("# reg %x0, %x1" : "+v" (f1), "+v" (f2));
+ return f1 + f2;
+}
+
+float sub_sf (float *p, float *q)
+{
+ float f1 = *p;
+ float f2 = *q;
+ __asm__ ("# reg %x0, %x1" : "+v" (f1), "+v" (f2));
+ return f1 - f2;
+}
+
+float mul_sf (float *p, float *q)
+{
+ float f1 = *p;
+ float f2 = *q;
+ __asm__ ("# reg %x0, %x1" : "+v" (f1), "+v" (f2));
+ return f1 * f2;
+}
+
+float div_sf (float *p, float *q)
+{
+ float f1 = *p;
+ float f2 = *q;
+ __asm__ ("# reg %x0, %x1" : "+v" (f1), "+v" (f2));
+ return f1 / f2;
+}
+
+float sqrt_sf (float *p)
+{
+ float f = *p;
+ __asm__ ("# reg %x0" : "+v" (f));
+ return __builtin_sqrtf (f);
+}
+
+
+double abs_df (double *p)
+{
+ double d = *p;
+ __asm__ ("# reg %x0" : "+v" (d));
+ return __builtin_fabs (d);
+}
+
+double nabs_df (double *p)
+{
+ double d = *p;
+ __asm__ ("# reg %x0" : "+v" (d));
+ return - __builtin_fabs (d);
+}
+
+double neg_df (double *p)
+{
+ double d = *p;
+ __asm__ ("# reg %x0" : "+v" (d));
+ return - d;
+}
+
+double add_df (double *p, double *q)
+{
+ double d1 = *p;
+ double d2 = *q;
+ __asm__ ("# reg %x0, %x1" : "+v" (d1), "+v" (d2));
+ return d1 + d2;
+}
+
+double sub_df (double *p, double *q)
+{
+ double d1 = *p;
+ double d2 = *q;
+ __asm__ ("# reg %x0, %x1" : "+v" (d1), "+v" (d2));
+ return d1 - d2;
+}
+
+double mul_df (double *p, double *q)
+{
+ double d1 = *p;
+ double d2 = *q;
+ __asm__ ("# reg %x0, %x1" : "+v" (d1), "+v" (d2));
+ return d1 * d2;
+}
+
+double div_df (double *p, double *q)
+{
+ double d1 = *p;
+ double d2 = *q;
+ __asm__ ("# reg %x0, %x1" : "+v" (d1), "+v" (d2));
+ return d1 / d2;
+}
+
+double sqrt_df (float *p)
+{
+ double d = *p;
+ __asm__ ("# reg %x0" : "+v" (d));
+ return __builtin_sqrt (d);
+}
+
+/* { dg-final { scan-assembler "xsabsdp" } } */
+/* { dg-final { scan-assembler "xsadddp" } } */
+/* { dg-final { scan-assembler "xsaddsp" } } */
+/* { dg-final { scan-assembler "xsdivdp" } } */
+/* { dg-final { scan-assembler "xsdivsp" } } */
+/* { dg-final { scan-assembler "xsmuldp" } } */
+/* { dg-final { scan-assembler "xsmulsp" } } */
+/* { dg-final { scan-assembler "xsnabsdp" } } */
+/* { dg-final { scan-assembler "xsnegdp" } } */
+/* { dg-final { scan-assembler "xssqrtdp" } } */
+/* { dg-final { scan-assembler "xssqrtsp" } } */
+/* { dg-final { scan-assembler "xssubdp" } } */
+/* { dg-final { scan-assembler "xssubsp" } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/p8vector-ldst.c b/gcc/testsuite/gcc.target/powerpc/p8vector-ldst.c
new file mode 100644
index 00000000000..d0b3eb09ef7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/p8vector-ldst.c
@@ -0,0 +1,42 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_p8vector_ok } */
+/* { dg-options "-mcpu=power8 -O2 -mupper-regs-df -mupper-regs-sf" } */
+
+float load_sf (float *p)
+{
+ float f = *p;
+ __asm__ ("# reg %x0" : "+v" (f));
+ return f;
+}
+
+double load_df (double *p)
+{
+ double d = *p;
+ __asm__ ("# reg %x0" : "+v" (d));
+ return d;
+}
+
+double load_dfsf (float *p)
+{
+ double d = (double) *p;
+ __asm__ ("# reg %x0" : "+v" (d));
+ return d;
+}
+
+void store_sf (float *p, float f)
+{
+ __asm__ ("# reg %x0" : "+v" (f));
+ *p = f;
+}
+
+void store_df (double *p, double d)
+{
+ __asm__ ("# reg %x0" : "+v" (d));
+ *p = d;
+}
+
+/* { dg-final { scan-assembler-times "lxsspx" 2 } } */
+/* { dg-final { scan-assembler-times "lxsdx" 1 } } */
+/* { dg-final { scan-assembler-times "stxsspx" 1 } } */
+/* { dg-final { scan-assembler-times "stxsdx" 1 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/p8vector-vectorize-1.c b/gcc/testsuite/gcc.target/powerpc/p8vector-vectorize-1.c
index 9a975bd6fe2..99b7ddfb2d9 100644
--- a/gcc/testsuite/gcc.target/powerpc/p8vector-vectorize-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/p8vector-vectorize-1.c
@@ -1,7 +1,7 @@
/* { dg-do compile { target { powerpc*-*-* } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
/* { dg-require-effective-target powerpc_p8vector_ok } */
-/* { dg-options "-mcpu=power8 -O2 -ftree-vectorize -fvect-cost-model -fno-unroll-loops -fno-unroll-all-loops" } */
+/* { dg-options "-mcpu=power8 -O2 -ftree-vectorize -fvect-cost-model=dynamic -fno-unroll-loops -fno-unroll-all-loops" } */
#ifndef SIZE
#define SIZE 1024
diff --git a/gcc/testsuite/gcc.target/powerpc/p8vector-vectorize-2.c b/gcc/testsuite/gcc.target/powerpc/p8vector-vectorize-2.c
index 8feba0a1347..a29240754f6 100644
--- a/gcc/testsuite/gcc.target/powerpc/p8vector-vectorize-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/p8vector-vectorize-2.c
@@ -1,7 +1,7 @@
/* { dg-do compile { target { powerpc*-*-* } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
/* { dg-require-effective-target powerpc_p8vector_ok } */
-/* { dg-options "-mcpu=power8 -O2 -ftree-vectorize -fvect-cost-model" } */
+/* { dg-options "-mcpu=power8 -O2 -ftree-vectorize -fvect-cost-model=dynamic" } */
#include <stddef.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/p8vector-vectorize-3.c b/gcc/testsuite/gcc.target/powerpc/p8vector-vectorize-3.c
index 570f2e5991c..b86f7de816b 100644
--- a/gcc/testsuite/gcc.target/powerpc/p8vector-vectorize-3.c
+++ b/gcc/testsuite/gcc.target/powerpc/p8vector-vectorize-3.c
@@ -1,7 +1,7 @@
/* { dg-do compile { target { powerpc*-*-* } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
/* { dg-require-effective-target powerpc_p8vector_ok } */
-/* { dg-options "-mcpu=power8 -O2 -ftree-vectorize -fvect-cost-model" } */
+/* { dg-options "-mcpu=power8 -O2 -ftree-vectorize -fvect-cost-model=dynamic" } */
#include <stddef.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/p8vector-vectorize-4.c b/gcc/testsuite/gcc.target/powerpc/p8vector-vectorize-4.c
index 90df8868051..1e886387ee7 100644
--- a/gcc/testsuite/gcc.target/powerpc/p8vector-vectorize-4.c
+++ b/gcc/testsuite/gcc.target/powerpc/p8vector-vectorize-4.c
@@ -1,7 +1,7 @@
/* { dg-do compile { target { powerpc*-*-* } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
/* { dg-require-effective-target powerpc_p8vector_ok } */
-/* { dg-options "-mcpu=power8 -O2 -ftree-vectorize -fvect-cost-model -fno-unroll-loops -fno-unroll-all-loops" } */
+/* { dg-options "-mcpu=power8 -O2 -ftree-vectorize -fvect-cost-model=dynamic -fno-unroll-loops -fno-unroll-all-loops" } */
#ifndef SIZE
#define SIZE 1024
diff --git a/gcc/testsuite/gcc.target/powerpc/p8vector-vectorize-5.c b/gcc/testsuite/gcc.target/powerpc/p8vector-vectorize-5.c
index 17563bf477a..0102510dadb 100644
--- a/gcc/testsuite/gcc.target/powerpc/p8vector-vectorize-5.c
+++ b/gcc/testsuite/gcc.target/powerpc/p8vector-vectorize-5.c
@@ -1,7 +1,7 @@
/* { dg-do compile { target { powerpc*-*-* } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
/* { dg-require-effective-target powerpc_p8vector_ok } */
-/* { dg-options "-mcpu=power8 -O2 -ftree-vectorize -fvect-cost-model -fno-unroll-loops -fno-unroll-all-loops" } */
+/* { dg-options "-mcpu=power8 -O2 -ftree-vectorize -fvect-cost-model=dynamic -fno-unroll-loops -fno-unroll-all-loops" } */
#ifndef SIZE
#define SIZE 1024
diff --git a/gcc/testsuite/gcc.target/powerpc/ppc-target-1.c b/gcc/testsuite/gcc.target/powerpc/ppc-target-1.c
index c98666c47a0..b39fe4115bc 100644
--- a/gcc/testsuite/gcc.target/powerpc/ppc-target-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/ppc-target-1.c
@@ -5,8 +5,7 @@
/* { dg-final { scan-assembler-times "fabs" 3 } } */
/* { dg-final { scan-assembler-times "fnabs" 3 } } */
/* { dg-final { scan-assembler-times "fsel" 3 } } */
-/* { dg-final { scan-assembler-times "fcpsgn" 3 } } */
-/* { dg-final { scan-assembler-times "xscpsgndp" 1 } } */
+/* { dg-final { scan-assembler-times "fcpsgn\|xscpsgndp" 4 } } */
double normal1 (double, double);
double power5 (double, double) __attribute__((__target__("cpu=power5")));
diff --git a/gcc/testsuite/gcc.target/powerpc/ppc-target-2.c b/gcc/testsuite/gcc.target/powerpc/ppc-target-2.c
index 8ef95b7a15b..e8a2de3636a 100644
--- a/gcc/testsuite/gcc.target/powerpc/ppc-target-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/ppc-target-2.c
@@ -5,8 +5,7 @@
/* { dg-final { scan-assembler-times "fabs" 3 } } */
/* { dg-final { scan-assembler-times "fnabs" 3 } } */
/* { dg-final { scan-assembler-times "fsel" 3 } } */
-/* { dg-final { scan-assembler-times "fcpsgn" 3 } } */
-/* { dg-final { scan-assembler-times "xscpsgndp" 1 } } */
+/* { dg-final { scan-assembler-times "fcpsgn\|xscpsgndp" 4 } } */
/* fabs/fnabs/fsel */
double normal1 (double a, double b) { return __builtin_copysign (a, b); }
diff --git a/gcc/testsuite/gcc.target/powerpc/pr42747.c b/gcc/testsuite/gcc.target/powerpc/pr42747.c
index 9e7310e1767..41362db1774 100644
--- a/gcc/testsuite/gcc.target/powerpc/pr42747.c
+++ b/gcc/testsuite/gcc.target/powerpc/pr42747.c
@@ -5,4 +5,4 @@
double foo (double x) { return __builtin_sqrt (x); }
-/* { dg-final { scan-assembler "xssqrtdp" } } */
+/* { dg-final { scan-assembler "xssqrtdp\|fsqrt" } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/pr43154.c b/gcc/testsuite/gcc.target/powerpc/pr43154.c
index d083e977b2f..eb1919743b5 100644
--- a/gcc/testsuite/gcc.target/powerpc/pr43154.c
+++ b/gcc/testsuite/gcc.target/powerpc/pr43154.c
@@ -1,5 +1,6 @@
/* { dg-do compile { target { powerpc*-*-* } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-skip-if "" { powerpc*le-*-* } { "*" } { "" } } */
/* { dg-require-effective-target powerpc_vsx_ok } */
/* { dg-options "-O2 -mcpu=power7" } */
diff --git a/gcc/testsuite/gcc.target/powerpc/pr58673-1.c b/gcc/testsuite/gcc.target/powerpc/pr58673-1.c
new file mode 100644
index 00000000000..6f7838f8dde
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr58673-1.c
@@ -0,0 +1,78 @@
+/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_p8vector_ok } */
+/* { dg-options "-mcpu=power8 -m64 -O1" } */
+
+enum typecode
+{
+ QIcode, QUcode, HIcode, HUcode, SIcode, SUcode, DIcode, DUcode, SFcode,
+ DFcode, XFcode, Pcode, Tcode, LAST_AND_UNUSED_TYPECODE
+};
+enum bytecode_opcode
+{
+ neverneverland, drop, duplicate, over, setstackSI, adjstackSI, constQI,
+ constHI, constSI, constDI, constSF, constDF, constXF, constP, loadQI,
+ loadHI, loadSI, loadDI, loadSF, loadDF, loadXF, loadP, storeQI, storeHI,
+ storeSI, storeDI, storeSF, storeDF, storeXF, storeP, storeBLK, clearBLK,
+ addconstPSI, newlocalSI, localP, argP, convertQIHI, convertHISI,
+ convertSIDI, convertQISI, convertQUHU, convertHUSU, convertSUDU,
+ convertQUSU, convertSFDF, convertDFXF, convertHIQI, convertSIHI,
+ convertDISI, convertSIQI, convertSUQU, convertDFSF, convertXFDF,
+ convertSISF, convertSIDF, convertSIXF, convertSUSF, convertSUDF,
+ convertSUXF, convertDISF, convertDIDF, convertDIXF, convertDUSF,
+ convertDUDF, convertDUXF, convertSFSI, convertDFSI, convertXFSI,
+ convertSFSU, convertDFSU, convertXFSU, convertSFDI, convertDFDI,
+ convertXFDI, convertSFDU, convertDFDU, convertXFDU, convertPSI,
+ convertSIP, convertSIT, convertDIT, convertSFT, convertDFT, convertXFT,
+ convertPT, zxloadBI, sxloadBI, sstoreBI, addSI, addDI, addSF, addDF,
+ addXF, addPSI, subSI, subDI, subSF, subDF, subXF, subPP, mulSI, mulDI,
+ mulSU, mulDU, mulSF, mulDF, mulXF, divSI, divDI, divSU, divDU, divSF,
+ divDF, divXF, modSI, modDI, modSU, modDU, andSI, andDI, iorSI, iorDI,
+ xorSI, xorDI, lshiftSI, lshiftSU, lshiftDI, lshiftDU, rshiftSI, rshiftSU,
+ rshiftDI, rshiftDU, ltSI, ltSU, ltDI, ltDU, ltSF, ltDF, ltXF, ltP, leSI,
+ leSU, leDI, leDU, leSF, leDF, leXF, leP, geSI, geSU, geDI, geDU, geSF,
+ geDF, geXF, geP, gtSI, gtSU, gtDI, gtDU, gtSF, gtDF, gtXF, gtP, eqSI,
+ eqDI, eqSF, eqDF, eqXF, eqP, neSI, neDI, neSF, neDF, neXF, neP, negSI,
+ negDI, negSF, negDF, negXF, notSI, notDI, notT, predecQI, predecHI,
+ predecSI, predecDI, predecP, predecSF, predecDF, predecXF, predecBI,
+ preincQI, preincHI, preincSI, preincDI, preincP, preincSF, preincDF,
+ preincXF, preincBI, postdecQI, postdecHI, postdecSI, postdecDI, postdecP,
+ postdecSF, postdecDF, postdecXF, postdecBI, postincQI, postincHI,
+ postincSI, postincDI, postincP, postincSF, postincDF, postincXF,
+ postincBI, xjumpif, xjumpifnot, jump, jumpP, caseSI, caseSU, caseDI,
+ caseDU, call, returnP, ret, linenote, LAST_AND_UNUSED_OPCODE
+};
+struct binary_operator
+{
+ enum bytecode_opcode opcode;
+ enum typecode arg0;
+};
+static struct conversion_recipe
+{
+ unsigned char *opcodes;
+ int cost;
+}
+conversion_recipe[((int) LAST_AND_UNUSED_TYPECODE)][((int)
+ LAST_AND_UNUSED_TYPECODE)];
+static struct conversion_recipe
+deduce_conversion (from, to)
+ enum typecode from, to;
+{
+ (conversion_recipe[(int) from][(int) to].
+ opcodes ? 0 : (conversion_recipe[(int) from][(int) to] =
+ deduce_conversion (from, to), 0));
+}
+
+void
+bc_expand_binary_operation (optab, resulttype, arg0, arg1)
+ struct binary_operator optab[];
+{
+ int i, besti, cost, bestcost;
+ enum typecode resultcode, arg0code;
+ for (i = 0; optab[i].opcode != -1; ++i)
+ {
+ (conversion_recipe[(int) arg0code][(int) optab[i].arg0].
+ opcodes ? 0 : (conversion_recipe[(int) arg0code][(int) optab[i].arg0] =
+ deduce_conversion (arg0code, optab[i].arg0), 0));
+ }
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/pr58673-2.c b/gcc/testsuite/gcc.target/powerpc/pr58673-2.c
new file mode 100644
index 00000000000..b70d2eed88c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr58673-2.c
@@ -0,0 +1,217 @@
+/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_p8vector_ok } */
+/* { dg-options "-mcpu=power8 -O3 -m64 -funroll-loops" } */
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+
+typedef long unsigned int size_t;
+typedef struct _IO_FILE FILE;
+typedef float real;
+typedef real rvec[3];
+typedef real matrix[3][3];
+typedef real tensor[3][3];
+enum
+{
+ F_BONDS, F_G96BONDS, F_MORSE, F_CUBICBONDS, F_CONNBONDS, F_HARMONIC,
+ F_ANGLES, F_G96ANGLES, F_PDIHS, F_RBDIHS, F_IDIHS, F_LJ14, F_COUL14, F_LJ,
+ F_BHAM, F_LJLR, F_DISPCORR, F_SR, F_LR, F_WPOL, F_POSRES, F_DISRES,
+ F_DISRESVIOL, F_ORIRES, F_ORIRESDEV, F_ANGRES, F_ANGRESZ, F_SHAKE,
+ F_SHAKENC, F_SETTLE, F_DUMMY2, F_DUMMY3, F_DUMMY3FD, F_DUMMY3FAD,
+ F_DUMMY3OUT, F_DUMMY4FD, F_EQM, F_EPOT, F_EKIN, F_ETOT, F_TEMP, F_PRES,
+ F_DVDL, F_DVDLKIN, F_NRE
+};
+typedef union
+{
+ struct
+ {
+ }
+ bham;
+ struct
+ {
+ real rA, krA, rB, krB;
+ }
+ harmonic;
+}
+t_iparams;
+typedef struct
+{
+ t_iparams *iparams;
+}
+t_idef;
+typedef struct
+{
+}
+t_inputrec;
+typedef struct
+{
+}
+t_commrec;
+typedef struct
+{
+}
+t_forcerec;
+typedef struct
+{
+}
+t_mdatoms;
+typedef struct
+{
+}
+t_filenm;
+enum
+{
+ eoPres, eoEpot, eoVir, eoDist, eoMu, eoForce, eoFx, eoFy, eoFz, eoPx, eoPy,
+ eoPz, eoPolarizability, eoDipole, eoObsNR, eoMemory =
+ eoObsNR, eoInter, eoUseVirial, eoNR
+};
+extern char *eoNames[eoNR];
+typedef struct
+{
+ int bPrint;
+}
+t_coupl_LJ;
+typedef struct
+{
+ int eObs;
+ t_iparams xi;
+}
+t_coupl_iparams;
+typedef struct
+{
+ real act_value[eoObsNR];
+ real av_value[eoObsNR];
+ real ref_value[eoObsNR];
+ int bObsUsed[eoObsNR];
+ int nLJ, nBU, nQ, nIP;
+ t_coupl_LJ *tcLJ;
+}
+t_coupl_rec;
+static void
+pr_ff (t_coupl_rec * tcr, real time, t_idef * idef, t_commrec * cr, int nfile,
+ t_filenm fnm[])
+{
+ static FILE *prop;
+ static FILE **out = ((void *) 0);
+ static FILE **qq = ((void *) 0);
+ static FILE **ip = ((void *) 0);
+ char buf[256];
+ char *leg[] = {
+ "C12", "C6"
+ };
+ char **raleg;
+ int i, j, index;
+ if ((prop == ((void *) 0)) && (out == ((void *) 0)) && (qq == ((void *) 0))
+ && (ip == ((void *) 0)))
+ {
+ for (i = j = 0; (i < eoObsNR); i++)
+ {
+ if (tcr->bObsUsed[i])
+ {
+ raleg[j++] =
+ (__extension__
+ (__builtin_constant_p (eoNames[i])
+ && ((size_t) (const void *) ((eoNames[i]) + 1) -
+ (size_t) (const void *) (eoNames[i]) ==
+ 1) ? (((const char *) (eoNames[i]))[0] ==
+ '\0' ? (char *) calloc ((size_t) 1,
+ (size_t) 1) : (
+ {
+ size_t
+ __len
+ =
+ strlen
+ (eoNames
+ [i])
+ +
+ 1;
+ char
+ *__retval
+ =
+ (char
+ *)
+ malloc
+ (__len);
+ __retval;}
+ )): __strdup (eoNames[i])));
+ raleg[j++] =
+ (__extension__
+ (__builtin_constant_p (buf)
+ && ((size_t) (const void *) ((buf) + 1) -
+ (size_t) (const void *) (buf) ==
+ 1) ? (((const char *) (buf))[0] ==
+ '\0' ? (char *) calloc ((size_t) 1,
+ (size_t) 1) : (
+ {
+ size_t
+ __len
+ =
+ strlen
+ (buf)
+ +
+ 1;
+ char
+ *__retval
+ =
+ (char
+ *)
+ malloc
+ (__len);
+ __retval;}
+ )): __strdup (buf)));
+ }
+ }
+ if (tcr->nLJ)
+ {
+ for (i = 0; (i < tcr->nLJ); i++)
+ {
+ if (tcr->tcLJ[i].bPrint)
+ {
+ xvgr_legend (out[i], (sizeof (leg) / sizeof ((leg)[0])),
+ leg);
+ }
+ }
+ }
+ }
+}
+
+void
+do_coupling (FILE * log, int nfile, t_filenm fnm[], t_coupl_rec * tcr, real t,
+ int step, real ener[], t_forcerec * fr, t_inputrec * ir,
+ int bMaster, t_mdatoms * md, t_idef * idef, real mu_aver,
+ int nmols, t_commrec * cr, matrix box, tensor virial,
+ tensor pres, rvec mu_tot, rvec x[], rvec f[], int bDoIt)
+{
+ int i, j, ati, atj, atnr2, type, ftype;
+ real deviation[eoObsNR], prdev[eoObsNR], epot0, dist, rmsf;
+ real ff6, ff12, ffa, ffb, ffc, ffq, factor, dt, mu_ind;
+ int bTest, bPrint;
+ t_coupl_iparams *tip;
+ if (bPrint)
+ {
+ pr_ff (tcr, t, idef, cr, nfile, fnm);
+ }
+ for (i = 0; (i < eoObsNR); i++)
+ {
+ deviation[i] =
+ calc_deviation (tcr->av_value[i], tcr->act_value[i],
+ tcr->ref_value[i]);
+ prdev[i] = tcr->ref_value[i] - tcr->act_value[i];
+ }
+ if (bPrint)
+ pr_dev (tcr, t, prdev, cr, nfile, fnm);
+ for (i = 0; (i < atnr2); i++)
+ {
+ factor = dt * deviation[tip->eObs];
+ switch (ftype)
+ {
+ case F_BONDS:
+ if (fabs (tip->xi.harmonic.krA) > 1.2e-38)
+ idef->iparams[type].harmonic.krA *=
+ (1 + factor / tip->xi.harmonic.krA);
+ }
+ }
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/recip-3.c b/gcc/testsuite/gcc.target/powerpc/recip-3.c
index 56ab371985b..1f8e30572b2 100644
--- a/gcc/testsuite/gcc.target/powerpc/recip-3.c
+++ b/gcc/testsuite/gcc.target/powerpc/recip-3.c
@@ -1,14 +1,14 @@
/* { dg-do compile { target { { powerpc*-*-* } && { ! powerpc*-apple-darwin* } } } } */
/* { dg-require-effective-target powerpc_fprs } */
/* { dg-options "-O2 -mrecip -ffast-math -mcpu=power7" } */
-/* { dg-final { scan-assembler-times "xsrsqrtedp" 1 } } */
+/* { dg-final { scan-assembler-times "xsrsqrtedp\|frsqrte\ " 1 } } */
/* { dg-final { scan-assembler-times "xsmsub.dp\|fmsub\ " 1 } } */
-/* { dg-final { scan-assembler-times "xsmuldp" 4 } } */
+/* { dg-final { scan-assembler-times "xsmuldp\|fmul\ " 4 } } */
/* { dg-final { scan-assembler-times "xsnmsub.dp\|fnmsub\ " 2 } } */
-/* { dg-final { scan-assembler-times "frsqrtes" 1 } } */
-/* { dg-final { scan-assembler-times "fmsubs" 1 } } */
-/* { dg-final { scan-assembler-times "fmuls" 2 } } */
-/* { dg-final { scan-assembler-times "fnmsubs" 1 } } */
+/* { dg-final { scan-assembler-times "xsrsqrtesp\|frsqrtes" 1 } } */
+/* { dg-final { scan-assembler-times "xsmsub.sp\|fmsubs" 1 } } */
+/* { dg-final { scan-assembler-times "xsmulsp\|fmuls" 2 } } */
+/* { dg-final { scan-assembler-times "xsnmsub.sp\|fnmsubs" 1 } } */
double
rsqrt_d (double a)
diff --git a/gcc/testsuite/gcc.target/powerpc/recip-5.c b/gcc/testsuite/gcc.target/powerpc/recip-5.c
index 0e89075bbe9..11d125c110e 100644
--- a/gcc/testsuite/gcc.target/powerpc/recip-5.c
+++ b/gcc/testsuite/gcc.target/powerpc/recip-5.c
@@ -4,12 +4,12 @@
/* { dg-options "-O3 -ftree-vectorize -mrecip=all -ffast-math -mcpu=power7 -fno-unroll-loops" } */
/* { dg-final { scan-assembler-times "xvredp" 4 } } */
/* { dg-final { scan-assembler-times "xvresp" 5 } } */
-/* { dg-final { scan-assembler-times "xsredp" 2 } } */
-/* { dg-final { scan-assembler-times "fres" 2 } } */
-/* { dg-final { scan-assembler-times "fmuls" 2 } } */
-/* { dg-final { scan-assembler-times "fnmsubs" 2 } } */
-/* { dg-final { scan-assembler-times "xsmuldp" 2 } } */
-/* { dg-final { scan-assembler-times "xsnmsub.dp" 4 } } */
+/* { dg-final { scan-assembler-times "xsredp\|fre\ " 2 } } */
+/* { dg-final { scan-assembler-times "fres\|xsresp" 2 } } */
+/* { dg-final { scan-assembler-times "fmuls\|xsmulsp" 2 } } */
+/* { dg-final { scan-assembler-times "fnmsubs\|xsnmsub.sp" 2 } } */
+/* { dg-final { scan-assembler-times "xsmuldp\|fmul\ " 2 } } */
+/* { dg-final { scan-assembler-times "xsnmsub.dp\|fnmsub\ " 4 } } */
/* { dg-final { scan-assembler-times "xvmulsp" 7 } } */
/* { dg-final { scan-assembler-times "xvnmsub.sp" 5 } } */
/* { dg-final { scan-assembler-times "xvmuldp" 6 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/vsx-builtin-3.c b/gcc/testsuite/gcc.target/powerpc/vsx-builtin-3.c
index 8450920ec0c..7aeba6cb563 100644
--- a/gcc/testsuite/gcc.target/powerpc/vsx-builtin-3.c
+++ b/gcc/testsuite/gcc.target/powerpc/vsx-builtin-3.c
@@ -16,9 +16,9 @@
/* { dg-final { scan-assembler "xvrspiz" } } */
/* { dg-final { scan-assembler "xsrdpi" } } */
/* { dg-final { scan-assembler "xsrdpic" } } */
-/* { dg-final { scan-assembler "xsrdpim" } } */
-/* { dg-final { scan-assembler "xsrdpip" } } */
-/* { dg-final { scan-assembler "xsrdpiz" } } */
+/* { dg-final { scan-assembler "xsrdpim\|frim" } } */
+/* { dg-final { scan-assembler "xsrdpip\|frip" } } */
+/* { dg-final { scan-assembler "xsrdpiz\|friz" } } */
/* { dg-final { scan-assembler "xsmaxdp" } } */
/* { dg-final { scan-assembler "xsmindp" } } */
/* { dg-final { scan-assembler "xxland" } } */
diff --git a/gcc/testsuite/gcc.target/s390/htm-1.c b/gcc/testsuite/gcc.target/s390/htm-1.c
index e6321de071e..245ba2c7ef9 100644
--- a/gcc/testsuite/gcc.target/s390/htm-1.c
+++ b/gcc/testsuite/gcc.target/s390/htm-1.c
@@ -7,11 +7,12 @@
#include <stdint.h>
#include <htmintrin.h>
-int a = 0;
+int global = 0;
uint64_t g;
+struct __htm_tdb global_tdb;
int
-foo (struct __htm_tdb* tdb)
+foo (struct __htm_tdb* tdb, int reg, int *mem, uint64_t *mem64)
{
int cc;
@@ -19,19 +20,54 @@ foo (struct __htm_tdb* tdb)
cc = __builtin_tbegin (0);
cc = __builtin_tbegin (tdb);
+ cc = __builtin_tbegin (&global_tdb);
+
cc = __builtin_tbegin_nofloat (0);
- cc = __builtin_tbegin_nofloat (tdb);
+ cc = __builtin_tbegin_nofloat (&global_tdb);
+
cc = __builtin_tbegin_retry (0, 42);
+ cc = __builtin_tbegin_retry (0, reg);
+ cc = __builtin_tbegin_retry (0, *mem);
+ cc = __builtin_tbegin_retry (0, global);
cc = __builtin_tbegin_retry (tdb, 42);
+ cc = __builtin_tbegin_retry (&global_tdb, 42);
+
cc = __builtin_tbegin_retry_nofloat (0, 42);
- cc = __builtin_tbegin_retry_nofloat (tdb, 42);
+ cc = __builtin_tbegin_retry_nofloat (0, reg);
+ cc = __builtin_tbegin_retry_nofloat (0, *mem);
+ cc = __builtin_tbegin_retry_nofloat (0, global);
+ cc = __builtin_tbegin_retry_nofloat (&global_tdb, 42);
+
__builtin_tbeginc ();
+
n = __builtin_tx_nesting_depth();
- __builtin_non_tx_store(&g, n);
+
+ __builtin_non_tx_store(&g, 23);
+ __builtin_non_tx_store(mem64, 23);
+ __builtin_non_tx_store(&g, reg);
+ __builtin_non_tx_store(&g, *mem);
+ __builtin_non_tx_store(&g, global);
+
__builtin_tabort (42 + 255);
+ __builtin_tabort (reg);
+ /* { dg-final { scan-assembler-times "tabort\t255" 1 } } */
+ __builtin_tabort (reg + 255);
+ __builtin_tabort (*mem);
+ __builtin_tabort (global);
+ /* Here global + 255 gets reloaded into a reg. Better would be to
+ just reload global or *mem and get the +255 for free as address
+ arithmetic. */
+ __builtin_tabort (*mem + 255);
+ __builtin_tabort (global + 255);
+
__builtin_tend();
+
__builtin_tx_assist (23);
+ __builtin_tx_assist (reg);
+ __builtin_tx_assist (*mem);
+ __builtin_tx_assist (global);
}
+
/* Make sure the tdb NULL argument ends up as immediate value in the
instruction. */
-/* { dg-final { scan-assembler-times "tbegin\t0," 4 } } */
+/* { dg-final { scan-assembler-times "tbegin\t0," 10 } } */
diff --git a/gcc/testsuite/gcc.target/s390/htm-nofloat-2.c b/gcc/testsuite/gcc.target/s390/htm-nofloat-2.c
new file mode 100644
index 00000000000..59621a4c19b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/htm-nofloat-2.c
@@ -0,0 +1,55 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -mhtm -Wa,-march=zEC12,-mzarch --save-temps" } */
+
+/* __builtin_tbegin has to emit clobbers for all FPRs since the tbegin
+ instruction does not automatically preserves them. If the
+ transaction body is fully contained in a function the backend tries
+ after reload to get rid of the FPR save/restore operations
+ triggered by the clobbers. This testcase failed since the backend
+ was able to get rid of all FPR saves/restores and since these were
+ the only stack operations also of the entire stack space. So even
+ the save/restore of the stack pointer was omitted in the end.
+ However, since the frame layout has been fixed before, the prologue
+ still generated the stack pointer decrement making foo return with
+ a modified stack pointer. */
+
+void abort(void);
+
+void __attribute__((noinline))
+foo (int a)
+{
+ /* This is just to prevent the tbegin code from actually being
+ executed. That way the test may even run on machines prior to
+ zEC12. */
+ if (a == 42)
+ return;
+
+ if (__builtin_tbegin (0) == 0)
+ __builtin_tend ();
+}
+
+#ifdef __s390x__
+#define GET_STACK_POINTER(SP) \
+ asm volatile ("stg %%r15, %0" : "=QRST" (SP));
+#else
+#define GET_STACK_POINTER(SP) \
+ asm volatile ("st %%r15, %0" : "=QR" (SP));
+#endif
+
+int main(void)
+{
+ unsigned long new_sp, old_sp;
+
+ GET_STACK_POINTER (old_sp);
+ foo(42);
+ GET_STACK_POINTER (new_sp);
+
+ if (old_sp != new_sp)
+ abort ();
+
+ return 0;
+}
+
+/* Make sure no FPR saves/restores are emitted. */
+/* { dg-final { scan-assembler-not "\tstd\t" } } */
+/* { dg-final { scan-assembler-not "\tld\t" } } */
diff --git a/gcc/testsuite/gcc.target/sh/20080410-1.c b/gcc/testsuite/gcc.target/sh/20080410-1.c
index 63e517e94d5..c398674c2aa 100644
--- a/gcc/testsuite/gcc.target/sh/20080410-1.c
+++ b/gcc/testsuite/gcc.target/sh/20080410-1.c
@@ -1,4 +1,4 @@
-/* { dg-do compile { target "sh-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O0" } */
/* { dg-skip-if "" { "sh*-*-*" } "-mb" "" } */
/* { dg-final { scan-assembler-not "add\tr0,r0" } } */
diff --git a/gcc/testsuite/gcc.target/sh/attr-isr-trap_exit.c b/gcc/testsuite/gcc.target/sh/attr-isr-trap_exit.c
index ad61aaa1db5..a45e92f8c6f 100644
--- a/gcc/testsuite/gcc.target/sh/attr-isr-trap_exit.c
+++ b/gcc/testsuite/gcc.target/sh/attr-isr-trap_exit.c
@@ -1,6 +1,6 @@
/* Check that trapa / interrput_handler attributes can paired in
either order. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*" } { "" } } */
/* { dg-options "-O" } */
/* { dg-final { scan-assembler "trapa\[ \t\]\[ \t\]*#4"} } */
diff --git a/gcc/testsuite/gcc.target/sh/cmpstr.c b/gcc/testsuite/gcc.target/sh/cmpstr.c
new file mode 100644
index 00000000000..4d638cc3e70
--- /dev/null
+++ b/gcc/testsuite/gcc.target/sh/cmpstr.c
@@ -0,0 +1,27 @@
+/* Check that the __builtin_strcmp function is inlined with cmp/str
+ when optimizing for speed. */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-skip-if "" { "sh*-*-*" } { "-m5*" } { "" } } */
+/* { dg-final { scan-assembler-not "jmp" } } */
+/* { dg-final { scan-assembler-times "cmp/str" 3 } } */
+/* { dg-final { scan-assembler-times "tst\t#3" 2 } } */
+
+test00 (const char *s1, const char *s2)
+{
+ return __builtin_strcmp (s1, s2);
+}
+
+/* NB: This might change as further optimisation might detect the
+ max length and fallback to cmpstrn. */
+test01(const char *s2)
+{
+ return __builtin_strcmp ("abc", s2);
+}
+
+/* Check that no test for alignment is needed. */
+test03(const char *s1, const char *s2)
+{
+ return __builtin_strcmp (__builtin_assume_aligned (s1, 4),
+ __builtin_assume_aligned (s2, 4));
+}
diff --git a/gcc/testsuite/gcc.target/sh/cmpstrn.c b/gcc/testsuite/gcc.target/sh/cmpstrn.c
new file mode 100644
index 00000000000..bc72b2c51d2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/sh/cmpstrn.c
@@ -0,0 +1,21 @@
+/* Check that the __builtin_strncmp function is inlined
+ when optimizing for speed. */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-skip-if "" { "sh*-*-*" } { "-m5*" } { "" } } */
+/* { dg-final { scan-assembler-not "jmp" } } */
+/* { dg-final { scan-assembler-times "cmp/str" 1 } } */
+
+/* Test that the cmp/str loop is optimized out. */
+test01(const char *s1, const char *s2, int n)
+{
+ return __builtin_strncmp (s1, "abcde", 3);
+}
+
+/* Test that the cmp/str loop is used. */
+test02(const char *s1, const char *s2, int n)
+{
+ return __builtin_strncmp (s1, "abcdefghi", 8);
+}
+
+
diff --git a/gcc/testsuite/gcc.target/sh/fpul-usage-1.c b/gcc/testsuite/gcc.target/sh/fpul-usage-1.c
index 394e7ef81ca..5c3bb196de0 100644
--- a/gcc/testsuite/gcc.target/sh/fpul-usage-1.c
+++ b/gcc/testsuite/gcc.target/sh/fpul-usage-1.c
@@ -1,6 +1,6 @@
/* Check that the FPUL register is used when reading a float as an int and
vice versa, as opposed to pushing and popping the values over the stack. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O1" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m1" "-m2" "-m4al" "*nofpu" "-m4-340*" "-m4-400*" "-m4-500*" "-m5*" } { "" } } */
/* { dg-final { scan-assembler "fpul" } } */
diff --git a/gcc/testsuite/gcc.target/sh/mfmovd.c b/gcc/testsuite/gcc.target/sh/mfmovd.c
index 3b7564aeb33..ce3e99332e3 100644
--- a/gcc/testsuite/gcc.target/sh/mfmovd.c
+++ b/gcc/testsuite/gcc.target/sh/mfmovd.c
@@ -1,6 +1,6 @@
/* Verify that we generate fmov.d instructions to move doubles when -mfmovd
option is enabled. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-require-effective-target hard_float } */
/* { dg-options "-mfmovd" } */
/* { dg-skip-if "" { *-*-* } { "*-single-only" } { "" } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr21255-1.c b/gcc/testsuite/gcc.target/sh/pr21255-1.c
index 5d5b6d7f9a6..3e9b78515f9 100644
--- a/gcc/testsuite/gcc.target/sh/pr21255-1.c
+++ b/gcc/testsuite/gcc.target/sh/pr21255-1.c
@@ -1,4 +1,4 @@
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O2 -fomit-frame-pointer" } */
/* { dg-final { scan-assembler "mov fr4,fr.; mov fr5,fr." { target sh-*-* } } } */
/* { dg-final { scan-assembler "mov fr4,fr.; mov fr5,fr." { target sh[1234lb]*-*-* } } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr21255-2-mb.c b/gcc/testsuite/gcc.target/sh/pr21255-2-mb.c
index ac2ce687e1e..531ed3979d1 100644
--- a/gcc/testsuite/gcc.target/sh/pr21255-2-mb.c
+++ b/gcc/testsuite/gcc.target/sh/pr21255-2-mb.c
@@ -1,4 +1,4 @@
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-mb -O2 -fomit-frame-pointer" } */
/* { dg-final { scan-assembler "mov @r.,r.; mov @\\(4,r.\\),r." } } */
double d;
diff --git a/gcc/testsuite/gcc.target/sh/pr21255-2-ml.c b/gcc/testsuite/gcc.target/sh/pr21255-2-ml.c
index 570e7dd0b50..6948f475ea3 100644
--- a/gcc/testsuite/gcc.target/sh/pr21255-2-ml.c
+++ b/gcc/testsuite/gcc.target/sh/pr21255-2-ml.c
@@ -1,4 +1,4 @@
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O2 -fomit-frame-pointer" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-mb" && "-m5*"} { "" } } */
/* { dg-final { scan-assembler "mov @\\(4,r.\\),r.; mov @r.,r." } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr21255-3.c b/gcc/testsuite/gcc.target/sh/pr21255-3.c
index 58d7849cf94..a6727841837 100644
--- a/gcc/testsuite/gcc.target/sh/pr21255-3.c
+++ b/gcc/testsuite/gcc.target/sh/pr21255-3.c
@@ -1,4 +1,4 @@
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O2 -fomit-frame-pointer" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m2e" "-m3e" "*single-only" } { "" } } */
/* { dg-final { scan-assembler "mov #?0,r.*; mov #?20,r" } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr33135-1.c b/gcc/testsuite/gcc.target/sh/pr33135-1.c
index 6c28e8c3b2b..cc6a3f984d3 100644
--- a/gcc/testsuite/gcc.target/sh/pr33135-1.c
+++ b/gcc/testsuite/gcc.target/sh/pr33135-1.c
@@ -1,6 +1,6 @@
/* Check that fcmp/eq and fcmp/gt instructions are generated by default
(implicit -mieee). */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O1" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m1" "-m2" "-m3" "-m4al" "*nofpu" "-m4-340*" "-m4-400*" "-m4-500*" "-m5*" } { "" } } */
/* { dg-final { scan-assembler-times "fcmp/eq" 4 } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr33135-2.c b/gcc/testsuite/gcc.target/sh/pr33135-2.c
index 37c4035deca..b93ecb81e48 100644
--- a/gcc/testsuite/gcc.target/sh/pr33135-2.c
+++ b/gcc/testsuite/gcc.target/sh/pr33135-2.c
@@ -1,6 +1,6 @@
/* Check that only the fcmp/gt instruction is generated when specifying
-ffinite-math-only (implicit -mno-ieee). */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O1 -ffinite-math-only" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m1" "-m2" "-m3" "-m4al" "*nofpu" "-m4-340*" "-m4-400*" "-m4-500*" "-m5*" } { "" } } */
/* { dg-final { scan-assembler-not "fcmp/eq" } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr33135-3.c b/gcc/testsuite/gcc.target/sh/pr33135-3.c
index cbda922e103..f5f9a5b9227 100644
--- a/gcc/testsuite/gcc.target/sh/pr33135-3.c
+++ b/gcc/testsuite/gcc.target/sh/pr33135-3.c
@@ -1,6 +1,6 @@
/* Check that fcmp/eq and fcmp/gt instructions are generated when specifying
-ffinite-math-only and -mieee. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O1 -ffinite-math-only -mieee" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m1" "-m2" "-m3" "-m4al" "*nofpu" "-m4-340*" "-m4-400*" "-m4-500*" "-m5*" } { "" } } */
/* { dg-final { scan-assembler-times "fcmp/eq" 4 } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr33135-4.c b/gcc/testsuite/gcc.target/sh/pr33135-4.c
index 3e4aa51cd9b..20178d7e493 100644
--- a/gcc/testsuite/gcc.target/sh/pr33135-4.c
+++ b/gcc/testsuite/gcc.target/sh/pr33135-4.c
@@ -1,6 +1,6 @@
/* Check that only the fcmp/gt instruction is generated when specifying
-fno-finite-math-only and -mno-ieee. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O1 -fno-finite-math-only -mno-ieee" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m1" "-m2" "-m3" "-m4al" "*nofpu" "-m4-340*" "-m4-400*" "-m4-500*" "-m5*" } { "" } } */
/* { dg-final { scan-assembler-not "fcmp/eq" } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr39423-1.c b/gcc/testsuite/gcc.target/sh/pr39423-1.c
index dac0f89eea3..1e02937ccba 100644
--- a/gcc/testsuite/gcc.target/sh/pr39423-1.c
+++ b/gcc/testsuite/gcc.target/sh/pr39423-1.c
@@ -1,6 +1,6 @@
/* Check that displacement addressing is used for indexed addresses with a
small offset, instead of re-calculating the index. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
/* { dg-final { scan-assembler-not "add\t#1" } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr39423-2.c b/gcc/testsuite/gcc.target/sh/pr39423-2.c
index 8e71505f21d..702384dc27a 100644
--- a/gcc/testsuite/gcc.target/sh/pr39423-2.c
+++ b/gcc/testsuite/gcc.target/sh/pr39423-2.c
@@ -1,7 +1,7 @@
/* Check that displacement addressing is used for indexed addresses with a
small offset, instead of re-calculating the index and that the movu.w
instruction is used on SH2A. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-skip-if "" { "sh*-*-*" } { "*" } { "-m2a*" } } */
/* { dg-final { scan-assembler-not "add\t#1" } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr49263.c b/gcc/testsuite/gcc.target/sh/pr49263.c
index b5ffe714fa8..783d865592c 100644
--- a/gcc/testsuite/gcc.target/sh/pr49263.c
+++ b/gcc/testsuite/gcc.target/sh/pr49263.c
@@ -2,7 +2,7 @@
allows it. Under some circumstances another compare instruction might
be selected, which is also fine. Any AND instructions are considered
counter productive and fail the test. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-final { scan-assembler-not "and" } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr49468-di.c b/gcc/testsuite/gcc.target/sh/pr49468-di.c
index 1b485c0cebe..4b17fce30bd 100644
--- a/gcc/testsuite/gcc.target/sh/pr49468-di.c
+++ b/gcc/testsuite/gcc.target/sh/pr49468-di.c
@@ -1,6 +1,6 @@
/* Check that 64 bit integer abs is generated as negc instruction pairs
and conditional branch instead of default branch-free code. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O1" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
/* { dg-final { scan-assembler-times "negc" 4 } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr49468-si.c b/gcc/testsuite/gcc.target/sh/pr49468-si.c
index 144eef4d6cc..8c771ed20b6 100644
--- a/gcc/testsuite/gcc.target/sh/pr49468-si.c
+++ b/gcc/testsuite/gcc.target/sh/pr49468-si.c
@@ -1,6 +1,6 @@
/* Check that 32 bit integer abs is generated as neg instruction and
conditional branch instead of default branch-free code. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O1" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
/* { dg-final { scan-assembler-times "neg" 2 } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr49880-1.c b/gcc/testsuite/gcc.target/sh/pr49880-1.c
index e19f1bf38a1..249fae00284 100644
--- a/gcc/testsuite/gcc.target/sh/pr49880-1.c
+++ b/gcc/testsuite/gcc.target/sh/pr49880-1.c
@@ -1,5 +1,5 @@
/* Check that the option -mdiv=call-div1 works. */
-/* { dg-do link { target "sh*-*-*" } } */
+/* { dg-do link } */
/* { dg-options "-mdiv=call-div1" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr49880-2.c b/gcc/testsuite/gcc.target/sh/pr49880-2.c
index eef832e30db..35e23dec438 100644
--- a/gcc/testsuite/gcc.target/sh/pr49880-2.c
+++ b/gcc/testsuite/gcc.target/sh/pr49880-2.c
@@ -1,5 +1,5 @@
/* Check that the option -mdiv=call-fp works. */
-/* { dg-do link { target "sh*-*-*" } } */
+/* { dg-do link } */
/* { dg-options "-mdiv=call-fp" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr49880-3.c b/gcc/testsuite/gcc.target/sh/pr49880-3.c
index 80a7df548a8..be6ea523ca8 100644
--- a/gcc/testsuite/gcc.target/sh/pr49880-3.c
+++ b/gcc/testsuite/gcc.target/sh/pr49880-3.c
@@ -1,5 +1,5 @@
/* Check that the option -mdiv=call-table works. */
-/* { dg-do link { target "sh*-*-*" } } */
+/* { dg-do link } */
/* { dg-options "-mdiv=call-table" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr49880-4.c b/gcc/testsuite/gcc.target/sh/pr49880-4.c
index 998a8b69fdd..5b5af1e4014 100644
--- a/gcc/testsuite/gcc.target/sh/pr49880-4.c
+++ b/gcc/testsuite/gcc.target/sh/pr49880-4.c
@@ -1,7 +1,7 @@
/* Check that the option -mdiv=call-fp does not produce calls to the
library function that uses FPU to implement integer division if FPU insns
are not supported or are disabled. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-mdiv=call-fp" } */
/* { dg-skip-if "" { "sh*-*-*" } { "*"} { "-m1" "-m2" "-m3" "-m4al" "*nofpu" "-m4-340*" "-m4-400*" "-m4-500*" } } */
/* { dg-final { scan-assembler-not "sdivsi3_i4\n|udivsi3_i4\n" } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr49880-5.c b/gcc/testsuite/gcc.target/sh/pr49880-5.c
index 09e99a85f63..bff9f331f9a 100644
--- a/gcc/testsuite/gcc.target/sh/pr49880-5.c
+++ b/gcc/testsuite/gcc.target/sh/pr49880-5.c
@@ -1,6 +1,6 @@
/* Check that the option -mdiv=call-fp results in the corresponding library
function calls on targets that have a double precision FPU. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-mdiv=call-fp" } */
/* { dg-skip-if "" { "sh*-*-*" } { "*"} { "-m2a" "-m4" "-m4a" "*single-only" } } */
/* { dg-final { scan-assembler "sdivsi3_i4\n" } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr50749-qihisi-postinc-1.c b/gcc/testsuite/gcc.target/sh/pr50749-qihisi-postinc-1.c
index 8852b8f87f2..90db97a273d 100644
--- a/gcc/testsuite/gcc.target/sh/pr50749-qihisi-postinc-1.c
+++ b/gcc/testsuite/gcc.target/sh/pr50749-qihisi-postinc-1.c
@@ -1,5 +1,5 @@
/* PR target/50749: Verify that post-increment addressing is generated. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-final { scan-assembler-times "mov.b\t@r\[0-9]\+\\+,r\[0-9]\+" 1 } } */
/* { dg-final { scan-assembler-times "mov.w\t@r\[0-9]\+\\+,r\[0-9]\+" 1 } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr50749-qihisi-postinc-2.c b/gcc/testsuite/gcc.target/sh/pr50749-qihisi-postinc-2.c
index b101e8d04c8..b695db173fe 100644
--- a/gcc/testsuite/gcc.target/sh/pr50749-qihisi-postinc-2.c
+++ b/gcc/testsuite/gcc.target/sh/pr50749-qihisi-postinc-2.c
@@ -1,6 +1,6 @@
/* PR target/50749: Verify that subsequent post-increment addressings
are generated. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-final { scan-assembler-times "mov.b\t@r\[0-9]\+\\+,r\[0-9]\+" 5 { xfail *-*-*} } } */
/* { dg-final { scan-assembler-times "mov.w\t@r\[0-9]\+\\+,r\[0-9]\+" 5 { xfail *-*-*} } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr50749-qihisi-postinc-3.c b/gcc/testsuite/gcc.target/sh/pr50749-qihisi-postinc-3.c
index 99f16b60c18..6e54d4dd721 100644
--- a/gcc/testsuite/gcc.target/sh/pr50749-qihisi-postinc-3.c
+++ b/gcc/testsuite/gcc.target/sh/pr50749-qihisi-postinc-3.c
@@ -1,6 +1,6 @@
/* PR target/50749: Verify that post-increment addressing is generated
inside a loop. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-final { scan-assembler-times "mov.b\t@r\[0-9]\+\\+,r\[0-9]\+" 1 } } */
/* { dg-final { scan-assembler-times "mov.w\t@r\[0-9]\+\\+,r\[0-9]\+" 1 } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr50749-qihisi-postinc-4.c b/gcc/testsuite/gcc.target/sh/pr50749-qihisi-postinc-4.c
index 01050c60269..fc6fa8da037 100644
--- a/gcc/testsuite/gcc.target/sh/pr50749-qihisi-postinc-4.c
+++ b/gcc/testsuite/gcc.target/sh/pr50749-qihisi-postinc-4.c
@@ -1,6 +1,6 @@
/* PR target/50749: Verify that post-increment addressing is generated
inside a loop. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-final { scan-assembler-times "mov.b\t@r\[0-9]\+\\+,r\[0-9]\+" 3 { xfail *-*-*} } } */
/* { dg-final { scan-assembler-times "mov.w\t@r\[0-9]\+\\+,r\[0-9]\+" 3 { xfail *-*-*} } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr50749-qihisi-predec-1.c b/gcc/testsuite/gcc.target/sh/pr50749-qihisi-predec-1.c
index 5f816e91cbb..4f455743cfc 100644
--- a/gcc/testsuite/gcc.target/sh/pr50749-qihisi-predec-1.c
+++ b/gcc/testsuite/gcc.target/sh/pr50749-qihisi-predec-1.c
@@ -1,5 +1,5 @@
/* PR target/50749: Verify that pre-decrement addressing is generated. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-final { scan-assembler-times "mov.b\tr\[0-9]\+,@-r\[0-9]\+" 1 { xfail *-*-*} } } */
/* { dg-final { scan-assembler-times "mov.w\tr\[0-9]\+,@-r\[0-9]\+" 1 { xfail *-*-*} } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr50749-qihisi-predec-2.c b/gcc/testsuite/gcc.target/sh/pr50749-qihisi-predec-2.c
index 73e19f378e6..beda957fa89 100644
--- a/gcc/testsuite/gcc.target/sh/pr50749-qihisi-predec-2.c
+++ b/gcc/testsuite/gcc.target/sh/pr50749-qihisi-predec-2.c
@@ -1,6 +1,6 @@
/* PR target/50749: Verify that subsequent pre-decrement addressings
are generated. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-final { scan-assembler-times "mov.b\tr\[0-9]\+,@-r\[0-9]\+" 5 { xfail *-*-*} } } */
/* { dg-final { scan-assembler-times "mov.w\tr\[0-9]\+,@-r\[0-9]\+" 5 { xfail *-*-*} } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr50749-qihisi-predec-3.c b/gcc/testsuite/gcc.target/sh/pr50749-qihisi-predec-3.c
index f242bf37827..541749750e0 100644
--- a/gcc/testsuite/gcc.target/sh/pr50749-qihisi-predec-3.c
+++ b/gcc/testsuite/gcc.target/sh/pr50749-qihisi-predec-3.c
@@ -1,6 +1,6 @@
/* PR target/50749: Verify that pre-decrement addressing is generated
inside a loop. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-final { scan-assembler-times "mov.b\tr\[0-9]\+,@-r\[0-9]\+" 1 } } */
/* { dg-final { scan-assembler-times "mov.w\tr\[0-9]\+,@-r\[0-9]\+" 1 } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr50749-qihisi-predec-4.c b/gcc/testsuite/gcc.target/sh/pr50749-qihisi-predec-4.c
index 24601ca6bff..e8c03481e2f 100644
--- a/gcc/testsuite/gcc.target/sh/pr50749-qihisi-predec-4.c
+++ b/gcc/testsuite/gcc.target/sh/pr50749-qihisi-predec-4.c
@@ -1,6 +1,6 @@
/* PR target/50749: Verify that pre-decrement addressing is generated
inside a loop. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-final { scan-assembler-times "mov.b\tr\[0-9]\+,@-r\[0-9]\+" 3 { xfail *-*-*} } } */
/* { dg-final { scan-assembler-times "mov.w\tr\[0-9]\+,@-r\[0-9]\+" 3 { xfail *-*-*} } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr50749-sf-postinc-1.c b/gcc/testsuite/gcc.target/sh/pr50749-sf-postinc-1.c
index 98b71b2bedf..41e3bdd2834 100644
--- a/gcc/testsuite/gcc.target/sh/pr50749-sf-postinc-1.c
+++ b/gcc/testsuite/gcc.target/sh/pr50749-sf-postinc-1.c
@@ -1,5 +1,5 @@
/* PR target/50749: Verify that post-increment addressing is generated. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m1" "-m2" "-m3" "-m4al" "*nofpu" "-m4-340*" "-m4-400*" "-m4-500*" "-m5*" } { "" } } */
/* { dg-final { scan-assembler-times "fmov.s\t@r\[0-9]\+\\+,fr\[0-9]\+" 1 } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr50749-sf-postinc-2.c b/gcc/testsuite/gcc.target/sh/pr50749-sf-postinc-2.c
index b40becd3317..304ed11c428 100644
--- a/gcc/testsuite/gcc.target/sh/pr50749-sf-postinc-2.c
+++ b/gcc/testsuite/gcc.target/sh/pr50749-sf-postinc-2.c
@@ -1,6 +1,6 @@
/* PR target/50749: Verify that subsequent post-increment addressings
are generated. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m1" "-m2*" "-m4al" "*nofpu" "-m4-340*" "-m4-400*" "-m4-500*" "-m5*" } { "" } } */
/* { dg-final { scan-assembler-times "fmov.s\t@r\[0-9]\+\\+,fr\[0-9]\+" 5 { xfail *-*-*} } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr50749-sf-postinc-3.c b/gcc/testsuite/gcc.target/sh/pr50749-sf-postinc-3.c
index 27d13e8d378..7461bedb4a6 100644
--- a/gcc/testsuite/gcc.target/sh/pr50749-sf-postinc-3.c
+++ b/gcc/testsuite/gcc.target/sh/pr50749-sf-postinc-3.c
@@ -1,6 +1,6 @@
/* PR target/50749: Verify that post-increment addressing is generated
inside a loop. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m1" "-m2" "-m3" "-m4al" "*nofpu" "-m4-340*" "-m4-400*" "-m4-500*" "-m5*" } { "" } } */
/* { dg-final { scan-assembler-times "fmov.s\t@r\[0-9]\+\\+,fr\[0-9]\+" 1 } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr50749-sf-postinc-4.c b/gcc/testsuite/gcc.target/sh/pr50749-sf-postinc-4.c
index 66d29f0a440..b6dce42fca7 100644
--- a/gcc/testsuite/gcc.target/sh/pr50749-sf-postinc-4.c
+++ b/gcc/testsuite/gcc.target/sh/pr50749-sf-postinc-4.c
@@ -1,6 +1,6 @@
/* PR target/50749: Verify that post-increment addressing is generated
inside a loop. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m1" "-m2*" "-m4al" "*nofpu" "-m4-340*" "-m4-400*" "-m4-500*" "-m5*" } { "" } } */
/* { dg-final { scan-assembler-times "fmov.s\t@r\[0-9]\+\\+,fr\[0-9]\+" 3 { xfail *-*-*} } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr50749-sf-predec-1.c b/gcc/testsuite/gcc.target/sh/pr50749-sf-predec-1.c
index d7d129a7cec..d51aa9e09a6 100644
--- a/gcc/testsuite/gcc.target/sh/pr50749-sf-predec-1.c
+++ b/gcc/testsuite/gcc.target/sh/pr50749-sf-predec-1.c
@@ -1,5 +1,5 @@
/* PR target/50749: Verify that pre-decrement addressing is generated. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m1" "-m2" "-m3" "-m4al" "*nofpu" "-m4-340*" "-m4-400*" "-m4-500*" "-m5*" } { "" } } */
/* { dg-final { scan-assembler-times "fmov.s\tfr\[0-9]\+,@-r\[0-9]\+" 1 } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr50749-sf-predec-2.c b/gcc/testsuite/gcc.target/sh/pr50749-sf-predec-2.c
index 96d9a6c183e..cd87ce95f8f 100644
--- a/gcc/testsuite/gcc.target/sh/pr50749-sf-predec-2.c
+++ b/gcc/testsuite/gcc.target/sh/pr50749-sf-predec-2.c
@@ -1,6 +1,6 @@
/* PR target/50749: Verify that subsequent pre-decrement addressings
are generated. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m1" "-m2*" "-m4al" "*nofpu" "-m4-340*" "-m4-400*" "-m4-500*" "-m5*" } { "" } } */
/* { dg-final { scan-assembler-times "fmov.s\tfr\[0-9]\+,@-r\[0-9]\+" 5 { xfail *-*-*} } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr50749-sf-predec-3.c b/gcc/testsuite/gcc.target/sh/pr50749-sf-predec-3.c
index b3023b7a85b..a772b23a4ba 100644
--- a/gcc/testsuite/gcc.target/sh/pr50749-sf-predec-3.c
+++ b/gcc/testsuite/gcc.target/sh/pr50749-sf-predec-3.c
@@ -1,6 +1,6 @@
/* PR target/50749: Verify that pre-decrement addressing is generated
inside a loop. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m1" "-m2" "-m3" "-m4al" "*nofpu" "-m4-340*" "-m4-400*" "-m4-500*" "-m5*" } { "" } } */
/* { dg-final { scan-assembler-times "fmov.s\tfr\[0-9]\+,@-r\[0-9]\+" 1 } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr50749-sf-predec-4.c b/gcc/testsuite/gcc.target/sh/pr50749-sf-predec-4.c
index 6d7b90534dc..9d080387d2e 100644
--- a/gcc/testsuite/gcc.target/sh/pr50749-sf-predec-4.c
+++ b/gcc/testsuite/gcc.target/sh/pr50749-sf-predec-4.c
@@ -1,6 +1,6 @@
/* PR target/50749: Verify that pre-decrement addressing is generated
inside a loop. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m1" "-m2*" "-m4al" "*nofpu" "-m4-340*" "-m4-400*" "-m4-500*" "-m5*" } { "" } } */
/* { dg-final { scan-assembler-times "fmov.s\tfr\[0-9]\+,@-r\[0-9]\+" 3 { xfail *-*-*} } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr50751-1.c b/gcc/testsuite/gcc.target/sh/pr50751-1.c
index 3793bd0d4eb..80c63fb3652 100644
--- a/gcc/testsuite/gcc.target/sh/pr50751-1.c
+++ b/gcc/testsuite/gcc.target/sh/pr50751-1.c
@@ -1,7 +1,7 @@
/* Check that the mov.b displacement addressing insn is generated.
If the insn is generated as expected, there should be no address
calculations outside the mov insns. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O1" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
/* { dg-final { scan-assembler-not "add|sub" } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr50751-2.c b/gcc/testsuite/gcc.target/sh/pr50751-2.c
index ae4b0af5d41..cd716426112 100644
--- a/gcc/testsuite/gcc.target/sh/pr50751-2.c
+++ b/gcc/testsuite/gcc.target/sh/pr50751-2.c
@@ -2,7 +2,7 @@
base address is adjusted only once. On SH2A this test is skipped because
there is a 4 byte mov.b insn that can handle larger displacements. Thus
on SH2A the base address will not be adjusted in this case. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O1" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*" "-m2a*" } { "" } } */
/* { dg-final { scan-assembler-times "add" 2 } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr50751-3.c b/gcc/testsuite/gcc.target/sh/pr50751-3.c
index 58c85f83312..5b8d3514e4d 100644
--- a/gcc/testsuite/gcc.target/sh/pr50751-3.c
+++ b/gcc/testsuite/gcc.target/sh/pr50751-3.c
@@ -1,7 +1,7 @@
/* Check that on SH2A the 4 byte mov.b displacement insn is generated to
handle larger displacements. If it is generated correctly, there should
be no base address adjustments outside the mov.b insns. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O1" } */
/* { dg-skip-if "" { "sh*-*-*" } { "*" } { "-m2a*" } } */
/* { dg-final { scan-assembler-not "add|sub" } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr50751-4.c b/gcc/testsuite/gcc.target/sh/pr50751-4.c
index f3f0357707a..e0f3ab799eb 100644
--- a/gcc/testsuite/gcc.target/sh/pr50751-4.c
+++ b/gcc/testsuite/gcc.target/sh/pr50751-4.c
@@ -1,7 +1,7 @@
/* Check that the mov.w displacement addressing insn is generated.
If the insn is generated as expected, there should be no address
calculations outside the mov insns. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O1" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
/* { dg-final { scan-assembler-not "add|sub" } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr50751-5.c b/gcc/testsuite/gcc.target/sh/pr50751-5.c
index 48d5403b2d4..5da9ac2a128 100644
--- a/gcc/testsuite/gcc.target/sh/pr50751-5.c
+++ b/gcc/testsuite/gcc.target/sh/pr50751-5.c
@@ -2,7 +2,7 @@
base address is adjusted only once. On SH2A this test is skipped because
there is a 4 byte mov.w insn that can handle larger displacements. Thus
on SH2A the base address will not be adjusted in this case. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O1" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*" "-m2a*" } { "" } } */
/* { dg-final { scan-assembler-times "add" 2 } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr50751-6.c b/gcc/testsuite/gcc.target/sh/pr50751-6.c
index 83fb5abeafe..129729037e2 100644
--- a/gcc/testsuite/gcc.target/sh/pr50751-6.c
+++ b/gcc/testsuite/gcc.target/sh/pr50751-6.c
@@ -1,7 +1,7 @@
/* Check that on SH2A the 4 byte mov.w displacement insn is generated to
handle larger displacements. If it is generated correctly, there should
be no base address adjustments outside the mov.w insns. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O1" } */
/* { dg-skip-if "" { "sh*-*-*" } { "*" } { "-m2a*" } } */
/* { dg-final { scan-assembler-not "add|sub" } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr50751-7.c b/gcc/testsuite/gcc.target/sh/pr50751-7.c
index 859cba42f61..014575ad0d4 100644
--- a/gcc/testsuite/gcc.target/sh/pr50751-7.c
+++ b/gcc/testsuite/gcc.target/sh/pr50751-7.c
@@ -1,7 +1,7 @@
/* Check that mov.b and mov.w displacement insns are generated.
If this is working properly, there should be no base address adjustments
outside the mov insns. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O1" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
/* { dg-final { scan-assembler-not "add|sub" } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr50751-8.c b/gcc/testsuite/gcc.target/sh/pr50751-8.c
index bced631a17e..d9eda44f041 100644
--- a/gcc/testsuite/gcc.target/sh/pr50751-8.c
+++ b/gcc/testsuite/gcc.target/sh/pr50751-8.c
@@ -1,7 +1,7 @@
/* Check that on SH2A the 4 byte movu.b and movu.w displacement insns are
generated. This has to be checked with -O2 because some of the patterns
rely on peepholes. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-skip-if "" { "sh*-*-*" } { "*" } { "-m2a*" } } */
/* { dg-final { scan-assembler-times "movu.b" 4 } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr51244-1.c b/gcc/testsuite/gcc.target/sh/pr51244-1.c
index 601c1c1c269..15e2ebd1bfc 100644
--- a/gcc/testsuite/gcc.target/sh/pr51244-1.c
+++ b/gcc/testsuite/gcc.target/sh/pr51244-1.c
@@ -1,7 +1,7 @@
/* Check that inverted conditional branch logic does not generate
unnecessary explicit T bit extractions, inversions and
test instructions. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O1 -mbranch-cost=2" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
/* { dg-final { scan-assembler-not "movt|tst|negc|extu" } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr51244-10.c b/gcc/testsuite/gcc.target/sh/pr51244-10.c
index 20f052eedda..ef16b75ff79 100644
--- a/gcc/testsuite/gcc.target/sh/pr51244-10.c
+++ b/gcc/testsuite/gcc.target/sh/pr51244-10.c
@@ -10,7 +10,7 @@
tst r0,r0
bt .L195
*/
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*" } { "" } } */
/* { dg-final { scan-assembler-not "shll|subc|and" } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr51244-11.c b/gcc/testsuite/gcc.target/sh/pr51244-11.c
index 4a9c93c932c..b673e9ac48b 100644
--- a/gcc/testsuite/gcc.target/sh/pr51244-11.c
+++ b/gcc/testsuite/gcc.target/sh/pr51244-11.c
@@ -1,6 +1,6 @@
/* Check that zero-displacement branches are used instead of branch-free
execution patterns. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O1 -mzdcbranch" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*" } { "" } } */
/* { dg-final { scan-assembler-not "subc|and" } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr51244-12.c b/gcc/testsuite/gcc.target/sh/pr51244-12.c
index ca8e2d4b3bf..da941015cc8 100644
--- a/gcc/testsuite/gcc.target/sh/pr51244-12.c
+++ b/gcc/testsuite/gcc.target/sh/pr51244-12.c
@@ -1,7 +1,7 @@
/* Check that the negc instruction is generated as expected for the cases
below. If we see a movrt or #-1 negc sequence it means that the pattern
which handles the inverted case does not work properly. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O1" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*" } { "" } } */
/* { dg-final { scan-assembler-times "negc" 10 } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr51244-13.c b/gcc/testsuite/gcc.target/sh/pr51244-13.c
index 7e823dc030c..41d23eb9438 100644
--- a/gcc/testsuite/gcc.target/sh/pr51244-13.c
+++ b/gcc/testsuite/gcc.target/sh/pr51244-13.c
@@ -8,7 +8,7 @@
branch condition. The tested function contains two other tst insns. If
everything goes as expected we will be seeing only those other two tst
insns. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*" } { "" } } */
/* { dg-final { scan-assembler-times "tst" 2 } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr51244-14.c b/gcc/testsuite/gcc.target/sh/pr51244-14.c
index 0ff7008fbc9..844eb3a5693 100644
--- a/gcc/testsuite/gcc.target/sh/pr51244-14.c
+++ b/gcc/testsuite/gcc.target/sh/pr51244-14.c
@@ -9,7 +9,7 @@
bf/s .L35
where the negated T bit store did not combine properly. Since there are
other movt insns we only check for the xor and the extu. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*" } { "" } } */
/* { dg-final { scan-assembler-not "xor|extu" } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr51244-15.c b/gcc/testsuite/gcc.target/sh/pr51244-15.c
index ec98d5e6138..e99963f8f99 100644
--- a/gcc/testsuite/gcc.target/sh/pr51244-15.c
+++ b/gcc/testsuite/gcc.target/sh/pr51244-15.c
@@ -1,7 +1,7 @@
/* Check that the redundant test removal code in the *cbranch_t split works
as expected on non-SH2A targets. Because on SH2A the movrt instruction
is used, this test is re-used and checked differently in pr51244-16.c. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*" "-m2a*" } { "" } } */
/* { dg-final { scan-assembler-times "tst" 6 } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr51244-16.c b/gcc/testsuite/gcc.target/sh/pr51244-16.c
index 8717df7f34a..5132f7433f3 100644
--- a/gcc/testsuite/gcc.target/sh/pr51244-16.c
+++ b/gcc/testsuite/gcc.target/sh/pr51244-16.c
@@ -1,6 +1,6 @@
/* Check that the redundant test removal code in the *cbranch_t split works
as expected on SH2A targets. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-skip-if "" { "sh*-*-*" } { "*" } { "-m2a*" } } */
/* { dg-final { scan-assembler-times "tst" 6 } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr51244-17.c b/gcc/testsuite/gcc.target/sh/pr51244-17.c
index e7d1ddd2ad0..621abb788a9 100644
--- a/gcc/testsuite/gcc.target/sh/pr51244-17.c
+++ b/gcc/testsuite/gcc.target/sh/pr51244-17.c
@@ -1,6 +1,6 @@
/* Check that no unnecessary zero extensions are done on values that are
results of arithmetic with T bit inputs. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O1" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*" } { "" } } */
/* { dg-final { scan-assembler-not "extu|exts" } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr51244-18.c b/gcc/testsuite/gcc.target/sh/pr51244-18.c
index dbfb9901c2b..19b244cea10 100644
--- a/gcc/testsuite/gcc.target/sh/pr51244-18.c
+++ b/gcc/testsuite/gcc.target/sh/pr51244-18.c
@@ -12,7 +12,7 @@
not working as expected. This test requires -O2 because the T bit stores
in question will be eliminated in additional insn split passes after
reload. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*" } { "" } } */
/* { dg-final { scan-assembler-not "movt|tst" } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr51244-19.c b/gcc/testsuite/gcc.target/sh/pr51244-19.c
index 4d4f781ed5c..5845d93f60a 100644
--- a/gcc/testsuite/gcc.target/sh/pr51244-19.c
+++ b/gcc/testsuite/gcc.target/sh/pr51244-19.c
@@ -23,7 +23,7 @@
working as expected. This test requires -O2 because the T bit stores
in question will be eliminated in additional insn split passes after
reload. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*" } { "" } } */
/* { dg-final { scan-assembler-not "movt" } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr51244-2.c b/gcc/testsuite/gcc.target/sh/pr51244-2.c
index d984676102f..a81ee7ed9d6 100644
--- a/gcc/testsuite/gcc.target/sh/pr51244-2.c
+++ b/gcc/testsuite/gcc.target/sh/pr51244-2.c
@@ -2,7 +2,7 @@
instruction pattern, the constant -1 is loaded only once.
On SH2A this test is skipped because the movrt instruction is used
to get the complement of the T bit. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O1 -mbranch-cost=2" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*" "-m2a*" } { "" } } */
/* { dg-final { scan-assembler-times "mov\t#-1" 1 } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr51244-20-sh2a.c b/gcc/testsuite/gcc.target/sh/pr51244-20-sh2a.c
new file mode 100644
index 00000000000..f2cd2de04f9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/sh/pr51244-20-sh2a.c
@@ -0,0 +1,14 @@
+/* Check that the SH specific sh_treg_combine RTL optimization pass works as
+ expected. */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-skip-if "" { "sh*-*-*" } { "*" } { "-m2a*" } } */
+/* { dg-final { scan-assembler-times "tst" 5 } } */
+/* { dg-final { scan-assembler-times "movt" 0 } } */
+/* { dg-final { scan-assembler-times "nott" 1 } } */
+/* { dg-final { scan-assembler-times "cmp/eq" 2 } } */
+/* { dg-final { scan-assembler-times "cmp/hi" 4 } } */
+/* { dg-final { scan-assembler-times "cmp/gt" 3 } } */
+/* { dg-final { scan-assembler-times "not\t" 1 } } */
+
+#include "pr51244-20.c"
diff --git a/gcc/testsuite/gcc.target/sh/pr51244-20.c b/gcc/testsuite/gcc.target/sh/pr51244-20.c
new file mode 100644
index 00000000000..a9ded463511
--- /dev/null
+++ b/gcc/testsuite/gcc.target/sh/pr51244-20.c
@@ -0,0 +1,103 @@
+/* Check that the SH specific sh_treg_combine RTL optimization pass works as
+ expected. On SH2A the expected insns are slightly different, see
+ pr51244-21.c. */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-skip-if "" { "sh*-*-*" } { "-m5*" "-m2a*" } { "" } } */
+/* { dg-final { scan-assembler-times "tst" 6 } } */
+/* { dg-final { scan-assembler-times "movt" 1 } } */
+/* { dg-final { scan-assembler-times "cmp/eq" 2 } } */
+/* { dg-final { scan-assembler-times "cmp/hi" 4 } } */
+/* { dg-final { scan-assembler-times "cmp/gt" 2 } } */
+/* { dg-final { scan-assembler-times "not\t" 1 } } */
+
+
+/* non-SH2A: 2x tst, 1x movt, 2x cmp/eq, 1x cmp/hi
+ SH2A: 1x tst, 1x nott, 2x cmp/eq, 1x cmp/hi */
+static inline int
+blk_oversized_queue_0 (int* q)
+{
+ if (q[2])
+ return q[1] == 5;
+ return (q[0] != 5);
+}
+
+int __attribute__ ((noinline))
+get_request_0 (int* q, int rw)
+{
+ if (blk_oversized_queue_0 (q))
+ {
+ if ((rw == 1) || (rw == 0))
+ return -33;
+ return 0;
+ }
+ return -100;
+}
+
+
+/* 1x tst, 1x cmp/gt, 1x cmp/hi
+ On SH2A mem loads/stores have a wrong length of 4 bytes and thus will
+ not be placed in a delay slot. This introduces an extra cmp/gt insn. */
+static inline int
+blk_oversized_queue_1 (int* q)
+{
+ if (q[2])
+ return q[1] > 5;
+ return (q[0] > 5);
+}
+
+int __attribute__ ((noinline))
+get_request_1 (int* q, int rw)
+{
+ if (blk_oversized_queue_1 (q))
+ {
+ if ((rw == 1) || (rw == 0))
+ return -33;
+ return 0;
+ }
+ return -100;
+}
+
+
+/* 1x tst, 1x cmp/gt, 1x cmp/hi, 1x cmp/hi */
+static inline int
+blk_oversized_queue_2 (int* q)
+{
+ if (q[2])
+ return q[1] > 5;
+ return (q[0] < 5);
+}
+
+int __attribute__ ((noinline))
+get_request_2 (int* q, int rw)
+{
+ if (blk_oversized_queue_2 (q))
+ {
+ if ((rw == 1) || (rw == 0))
+ return -33;
+ return 0;
+ }
+ return -100;
+}
+
+
+/* 2x tst, 1x cmp/hi, 1x not */
+static inline int
+blk_oversized_queue_5 (int* q)
+{
+ if (q[2])
+ return q[1] != 0;
+ return q[0] == 0;
+}
+
+int __attribute__ ((noinline))
+get_request_5 (int* q, int rw)
+{
+ if (blk_oversized_queue_5 (q))
+ {
+ if ((rw == 1) || (rw == 0))
+ return -33;
+ return 0;
+ }
+ return -100;
+}
diff --git a/gcc/testsuite/gcc.target/sh/pr51244-3.c b/gcc/testsuite/gcc.target/sh/pr51244-3.c
index ebb3c3ae4c2..92963c4bec9 100644
--- a/gcc/testsuite/gcc.target/sh/pr51244-3.c
+++ b/gcc/testsuite/gcc.target/sh/pr51244-3.c
@@ -1,6 +1,6 @@
/* Check that when taking the complement of the T bit on SH2A,
the movrt instruction is being generated. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O1 -mbranch-cost=2" } */
/* { dg-skip-if "" { "sh*-*-*" } { "*" } { "-m2a*" } } */
/* { dg-final { scan-assembler-times "movrt" 4 } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr51244-4.c b/gcc/testsuite/gcc.target/sh/pr51244-4.c
index f3073780aea..a11429b15e4 100644
--- a/gcc/testsuite/gcc.target/sh/pr51244-4.c
+++ b/gcc/testsuite/gcc.target/sh/pr51244-4.c
@@ -1,7 +1,7 @@
/* Check that storing the (negated) T bit as all ones or zeros in a reg
uses the subc instruction. On SH2A a sequence with the movrt instruction
is also OK instead of subc. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O1 -mbranch-cost=2" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
/* { dg-final { scan-assembler-not "movt|tst|negc" } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr51244-5.c b/gcc/testsuite/gcc.target/sh/pr51244-5.c
index a99889df3c0..c0f05a10520 100644
--- a/gcc/testsuite/gcc.target/sh/pr51244-5.c
+++ b/gcc/testsuite/gcc.target/sh/pr51244-5.c
@@ -1,6 +1,6 @@
/* Check that no unnecessary sign or zero extension insn is generated after
a negc or movrt insn that stores the inverted T bit in a reg. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*" } { "" } } */
/* { dg-final { scan-assembler-not "extu|exts" } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr51244-6.c b/gcc/testsuite/gcc.target/sh/pr51244-6.c
index cfd466197d9..3f9aafb7d87 100644
--- a/gcc/testsuite/gcc.target/sh/pr51244-6.c
+++ b/gcc/testsuite/gcc.target/sh/pr51244-6.c
@@ -1,6 +1,6 @@
/* Check that no unnecessary sign or zero extension insn is generated after
a negc or movrt insn that stores the inverted T bit in a reg. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O1" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m1" "-m2" "-m3" "-m4al" "*nofpu" "-m4-340*" "-m4-400*" "-m4-500*" "-m5*" } { "" } } */
/* { dg-final { scan-assembler-not "extu|exts" } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr51244-7.c b/gcc/testsuite/gcc.target/sh/pr51244-7.c
index e7e3ac1385c..d4d39745dac 100644
--- a/gcc/testsuite/gcc.target/sh/pr51244-7.c
+++ b/gcc/testsuite/gcc.target/sh/pr51244-7.c
@@ -10,7 +10,7 @@
bra .L197
nop
*/
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*" } { "" } } */
/* { dg-final { scan-assembler-not "cmp/hi" } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr51244-8.c b/gcc/testsuite/gcc.target/sh/pr51244-8.c
index 9d95ae3f87a..d8c1269bb31 100644
--- a/gcc/testsuite/gcc.target/sh/pr51244-8.c
+++ b/gcc/testsuite/gcc.target/sh/pr51244-8.c
@@ -6,7 +6,7 @@
tst #1,r0
bf .L47
*/
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*" } { "" } } */
/* { dg-final { scan-assembler-not "shad|neg" } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr51244-9.c b/gcc/testsuite/gcc.target/sh/pr51244-9.c
index 13639bdc87d..cca90a84397 100644
--- a/gcc/testsuite/gcc.target/sh/pr51244-9.c
+++ b/gcc/testsuite/gcc.target/sh/pr51244-9.c
@@ -8,7 +8,7 @@
cmp/hi r2,r7 bt .L534
bf .L534
*/
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*" } { "" } } */
/* { dg-final { scan-assembler-not "mov\t#0" } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr52483-1.c b/gcc/testsuite/gcc.target/sh/pr52483-1.c
index 6538a0570b2..ca64a0a2c63 100644
--- a/gcc/testsuite/gcc.target/sh/pr52483-1.c
+++ b/gcc/testsuite/gcc.target/sh/pr52483-1.c
@@ -1,9 +1,9 @@
-/* Check that loads from volatile mems don't result in redundant sign
- extensions. */
-/* { dg-do compile { target "sh*-*-*" } } */
-/* { dg-options "-O1" } */
+/* Check that loads/stores from/to volatile mems don't result in redundant
+ sign/zero extensions. */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
-/* { dg-final { scan-assembler-not "exts" } } */
+/* { dg-final { scan-assembler-not "exts|extu" } } */
int
test_00 (volatile char* x)
@@ -11,20 +11,44 @@ test_00 (volatile char* x)
return *x;
}
+void
+test_100 (volatile char* x, char y)
+{
+ *x = y;
+}
+
int
test_01 (volatile short* x)
{
return *x;
}
+void
+test_101 (volatile unsigned char* x, unsigned char y)
+{
+ *x = y;
+}
+
int
test_02 (volatile unsigned char* x)
{
return *x == 0x80;
}
+void
+test_102 (volatile short* x, short y)
+{
+ *x = y;
+}
+
int
test_03 (volatile unsigned short* x)
{
return *x == 0xFF80;
}
+
+void
+test_103 (volatile unsigned short* x, unsigned short y)
+{
+ *x = y;
+}
diff --git a/gcc/testsuite/gcc.target/sh/pr52483-2.c b/gcc/testsuite/gcc.target/sh/pr52483-2.c
index 5681039db4d..68e7f8e2516 100644
--- a/gcc/testsuite/gcc.target/sh/pr52483-2.c
+++ b/gcc/testsuite/gcc.target/sh/pr52483-2.c
@@ -1,14 +1,15 @@
-/* Check that loads from volatile mems utilize displacement addressing
- modes and do not result in redundant sign extensions. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* Check that loads/stores from/to volatile mems utilize displacement
+ addressing modes and do not result in redundant sign/zero extensions. */
+/* { dg-do compile } */
/* { dg-options "-O1" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
-/* { dg-final { scan-assembler-times "@\\(5," 2 } } */
-/* { dg-final { scan-assembler-times "@\\(10," 2 } } */
-/* { dg-final { scan-assembler-times "@\\(20," 2 } } */
-/* { dg-final { scan-assembler-times "@\\(40," 2 } } */
-/* { dg-final { scan-assembler-times "@\\(44," 2 } } */
+/* { dg-final { scan-assembler-times "@\\(5," 4 } } */
+/* { dg-final { scan-assembler-times "@\\(10," 4 } } */
+/* { dg-final { scan-assembler-times "@\\(20," 4 } } */
+/* { dg-final { scan-assembler-times "@\\(40," 4 } } */
+/* { dg-final { scan-assembler-times "@\\(44," 4 } } */
/* { dg-final { scan-assembler-not "exts" } } */
+/* { dg-final { scan-assembler-times "extu|movu" 2 } } */
int
test_00 (volatile char* x)
@@ -16,35 +17,73 @@ test_00 (volatile char* x)
return x[5];
}
+void
+test_100 (volatile char* x, char y)
+{
+ x[5] = y;
+}
+
int
test_01 (volatile short* x)
{
return x[5];
}
+void
+test_101 (volatile short* x, short y)
+{
+ x[5] = y;
+}
+
int
test_02 (volatile int* x)
{
return x[5];
}
+void
+test_102 (volatile int* x, int y)
+{
+ x[5] = y;
+}
+
long long
test_03 (volatile long long* x)
{
return x[5];
}
+void
+test_103 (volatile long long* x, long long y)
+{
+ x[5] = y;
+}
+
unsigned int
test_04 (volatile unsigned char* x)
{
+ // expected 1x extu.b or movu.b
return x[5];
}
+void
+test_104 (volatile unsigned char* x, unsigned char y)
+{
+ x[5] = y;
+}
+
unsigned int
test_05 (volatile unsigned short* x)
{
+ // expected 1x extu.w or movu.w
return x[5];
}
+
+void
+test_105 (volatile unsigned short* x, unsigned short y)
+{
+ x[5] = y;
+}
unsigned int
test_06 (volatile unsigned int* x)
@@ -52,8 +91,20 @@ test_06 (volatile unsigned int* x)
return x[5];
}
+void
+test_106 (volatile unsigned int* x, unsigned int y)
+{
+ x[5] = y;
+}
+
unsigned long long
test_07 (volatile unsigned long long* x)
{
return x[5];
}
+
+void
+test_107 (volatile unsigned long long* x, unsigned long long y)
+{
+ x[5] = y;
+}
diff --git a/gcc/testsuite/gcc.target/sh/pr52483-3.c b/gcc/testsuite/gcc.target/sh/pr52483-3.c
index 4d04193eb45..baeec334331 100644
--- a/gcc/testsuite/gcc.target/sh/pr52483-3.c
+++ b/gcc/testsuite/gcc.target/sh/pr52483-3.c
@@ -1,10 +1,10 @@
-/* Check that loads from volatile mems utilize indexed addressing
- modes and do not result in redundant sign extensions. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* Check that loads/stores from/to volatile mems utilize indexed addressing
+ modes and do not result in redundant sign/zero extensions. */
+/* { dg-do compile } */
/* { dg-options "-O1" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
-/* { dg-final { scan-assembler-times "@\\(r0," 3 } } */
-/* { dg-final { scan-assembler-not "exts" } } */
+/* { dg-final { scan-assembler-times "@\\(r0," 6 } } */
+/* { dg-final { scan-assembler-not "exts|extu" } } */
int
test_00 (volatile char* x, unsigned int y)
@@ -12,14 +12,32 @@ test_00 (volatile char* x, unsigned int y)
return x[y];
}
+void
+test_100 (volatile char* x, unsigned int y, char z)
+{
+ x[y] = z;
+}
+
int
test_01 (volatile short* x, unsigned int y)
{
return x[y];
}
+void
+test_101 (volatile short* x, unsigned int y, short z)
+{
+ x[y] = z;
+}
+
int
test_02 (volatile int* x, unsigned int y)
{
return x[y];
}
+
+int
+test_102 (volatile int* x, unsigned int y, int z)
+{
+ x[y] = z;
+}
diff --git a/gcc/testsuite/gcc.target/sh/pr52483-4.c b/gcc/testsuite/gcc.target/sh/pr52483-4.c
index 8bf8626f148..743e8dc546e 100644
--- a/gcc/testsuite/gcc.target/sh/pr52483-4.c
+++ b/gcc/testsuite/gcc.target/sh/pr52483-4.c
@@ -1,12 +1,18 @@
-/* Check that loads from volatile floating point mems utilize indexed
- addressing modes. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* Check that loads/stores from/to volatile floating point mems utilize
+ indexed addressing modes. */
+/* { dg-do compile } */
/* { dg-options "-O1" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m1" "-m2" "-m3" "-m4al" "*nofpu" "-m4-340*" "-m4-400*" "-m4-500*" "-m5*" } { "" } } */
-/* { dg-final { scan-assembler-times "@\\(r0," 1 } } */
+/* { dg-final { scan-assembler-times "@\\(r0," 2 } } */
float
test_00 (volatile float* x, unsigned int y)
{
return x[y];
}
+
+void
+test_100 (volatile float* x, unsigned int y, float z)
+{
+ x[y] = z;
+}
diff --git a/gcc/testsuite/gcc.target/sh/pr52483-5.c b/gcc/testsuite/gcc.target/sh/pr52483-5.c
index fd106456020..50aefe2cdde 100644
--- a/gcc/testsuite/gcc.target/sh/pr52483-5.c
+++ b/gcc/testsuite/gcc.target/sh/pr52483-5.c
@@ -1,6 +1,6 @@
/* Check that loads from volatile mems utilize post-increment addressing
modes and do not result in redundant sign extensions. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O1" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
/* { dg-final { scan-assembler-times "@r\[0-9\]\+\\+," 3 } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr52933-1.c b/gcc/testsuite/gcc.target/sh/pr52933-1.c
index 037f916f34f..b65707ee40b 100644
--- a/gcc/testsuite/gcc.target/sh/pr52933-1.c
+++ b/gcc/testsuite/gcc.target/sh/pr52933-1.c
@@ -2,7 +2,7 @@
Each test case is expected to emit at least one div0s insn.
Problems when combining the div0s comparison result with surrounding
logic usually show up as redundant tst insns. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*" } { "" } } */
/* { dg-final { scan-assembler-times "div0s" 25 } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr52933-2.c b/gcc/testsuite/gcc.target/sh/pr52933-2.c
index b0e650bf0a5..865cb370913 100644
--- a/gcc/testsuite/gcc.target/sh/pr52933-2.c
+++ b/gcc/testsuite/gcc.target/sh/pr52933-2.c
@@ -3,7 +3,7 @@
Each test case is expected to emit at least one div0s insn.
Problems when combining the div0s comparison result with surrounding
logic usually show up as redundant tst insns. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O2 -mpretend-cmove" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*" } { "" } } */
/* { dg-final { scan-assembler-times "div0s" 25 } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr53511-1.c b/gcc/testsuite/gcc.target/sh/pr53511-1.c
index 5295d95f40f..d58a72c3b2b 100644
--- a/gcc/testsuite/gcc.target/sh/pr53511-1.c
+++ b/gcc/testsuite/gcc.target/sh/pr53511-1.c
@@ -1,5 +1,5 @@
/* Verify that the fmac insn is used for the standard fmaf function. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O1" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m1" "-m2" "-m3" "-m4al" "*nofpu" "-m4-340*" "-m4-400*" "-m4-500*" "-m5*" } { "" } } */
/* { dg-final { scan-assembler "fmac" } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr53512-1.c b/gcc/testsuite/gcc.target/sh/pr53512-1.c
index 0813d595921..c54671bd20c 100644
--- a/gcc/testsuite/gcc.target/sh/pr53512-1.c
+++ b/gcc/testsuite/gcc.target/sh/pr53512-1.c
@@ -1,6 +1,6 @@
/* Verify that the fsca insn is used when specifying -mfsca and
-funsafe-math-optimizations. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O1 -mfsca -funsafe-math-optimizations" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m1" "-m2*" "-m3*" "-m4al" "*nofpu" "-m4-340*" "-m4-400*" "-m4-500*" "-m5*" } { "" } } */
/* { dg-final { scan-assembler-times "fsca" 3 } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr53512-2.c b/gcc/testsuite/gcc.target/sh/pr53512-2.c
index d629ee71292..ed410116c67 100644
--- a/gcc/testsuite/gcc.target/sh/pr53512-2.c
+++ b/gcc/testsuite/gcc.target/sh/pr53512-2.c
@@ -1,6 +1,6 @@
/* Verify that the fsca insn is not used when specifying -mno-fsca and
-funsafe-math-optimizations. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O1 -mno-fsca -funsafe-math-optimizations" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m1" "-m2*" "-m4al" "*nofpu" "-m4-340*" "-m4-400*" "-m4-500*" "-m5*" } { "" } } */
/* { dg-final { scan-assembler-not "fsca" } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr53512-3.c b/gcc/testsuite/gcc.target/sh/pr53512-3.c
index 21801bb6df7..71522c8d964 100644
--- a/gcc/testsuite/gcc.target/sh/pr53512-3.c
+++ b/gcc/testsuite/gcc.target/sh/pr53512-3.c
@@ -1,6 +1,6 @@
/* Verify that the fsrra insn is used when specifying -mfsrra and
-funsafe-math-optimizations and -ffinite-math-only. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O1 -mfsrra -funsafe-math-optimizations -ffinite-math-only" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m1" "-m2*" "-m3*" "-m4al" "*nofpu" "-m4-340*" "-m4-400*" "-m4-500*" "-m5*" } { "" } } */
/* { dg-final { scan-assembler "fsrra" } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr53512-4.c b/gcc/testsuite/gcc.target/sh/pr53512-4.c
index 9ddad38b212..1645eed528f 100644
--- a/gcc/testsuite/gcc.target/sh/pr53512-4.c
+++ b/gcc/testsuite/gcc.target/sh/pr53512-4.c
@@ -1,6 +1,6 @@
/* Verify that the fsrra insn is not used when specifying -mno-fsrra and
-funsafe-math-optimizations and -ffinite-math-only. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O1 -mno-fsrra -funsafe-math-optimizations -ffinite-math-only" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m1" "-m2*" "-m4al" "*nofpu" "-m4-340*" "-m4-400*" "-m4-500*" "-m5*" } { "" } } */
/* { dg-final { scan-assembler-not "fsrra" } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr53568-1.c b/gcc/testsuite/gcc.target/sh/pr53568-1.c
index 22f836ef892..e274170fe1f 100644
--- a/gcc/testsuite/gcc.target/sh/pr53568-1.c
+++ b/gcc/testsuite/gcc.target/sh/pr53568-1.c
@@ -1,6 +1,6 @@
/* Check that the bswap32 pattern is generated as swap.b and swap.w
instructions. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
/* { dg-final { scan-assembler-times "swap.w" 7 } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr53988.c b/gcc/testsuite/gcc.target/sh/pr53988.c
index 4bade1efb73..a2e7213cd8f 100644
--- a/gcc/testsuite/gcc.target/sh/pr53988.c
+++ b/gcc/testsuite/gcc.target/sh/pr53988.c
@@ -2,7 +2,7 @@
values loaded from memory. If everything goes as expected we won't see
any sign/zero extensions or and ops. On SH2A we don't expect to see the
movu insn. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O1" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
/* { dg-final { scan-assembler-times "tst\tr" 8 } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr54089-1.c b/gcc/testsuite/gcc.target/sh/pr54089-1.c
index 399b0a53e22..3eb700ad267 100644
--- a/gcc/testsuite/gcc.target/sh/pr54089-1.c
+++ b/gcc/testsuite/gcc.target/sh/pr54089-1.c
@@ -1,5 +1,5 @@
/* Check that the rotcr instruction is generated. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O1" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
/* { dg-final { scan-assembler-times "rotcr" 24 } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr54089-2.c b/gcc/testsuite/gcc.target/sh/pr54089-2.c
index 61b703d4dfe..17466f3e19e 100644
--- a/gcc/testsuite/gcc.target/sh/pr54089-2.c
+++ b/gcc/testsuite/gcc.target/sh/pr54089-2.c
@@ -9,7 +9,7 @@
mov r4,r0
rts
rotcr r0 */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-skip-if "" { "sh*-*-*" } { "*"} { "-m3* -m2a* -m4*" } } */
/* { dg-final { scan-assembler-not "neg" } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr54089-3.c b/gcc/testsuite/gcc.target/sh/pr54089-3.c
index ffb976ba11b..abdb021cade 100644
--- a/gcc/testsuite/gcc.target/sh/pr54089-3.c
+++ b/gcc/testsuite/gcc.target/sh/pr54089-3.c
@@ -1,11 +1,11 @@
/* The dynamic shift library functions truncate the shift count to 5 bits.
Verify that this is taken into account and no extra shift count
truncations are generated before the library call. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O1" } */
/* { dg-skip-if "" { "sh*-*-*" } { "*" } { "-m1*" "-m2" "-m2e*" } } */
/* { dg-final { scan-assembler-not "and" } } */
-/* { dg-final { scan-assembler-not "31" } } */
+/* { dg-final { scan-assembler-not "#31" } } */
int
test00 (unsigned int a, int* b, int c, int* d, unsigned int e)
diff --git a/gcc/testsuite/gcc.target/sh/pr54089-4.c b/gcc/testsuite/gcc.target/sh/pr54089-4.c
index 4617c3a5f1d..e01e51c0a36 100644
--- a/gcc/testsuite/gcc.target/sh/pr54089-4.c
+++ b/gcc/testsuite/gcc.target/sh/pr54089-4.c
@@ -1,6 +1,6 @@
/* Check that the rotcr instruction is generated when shifting the
negated T bit on non-SH2A. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O1" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*" "-m2a*" } { "" } } */
/* { dg-final { scan-assembler-times "rotcr" 1 } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr54089-5.c b/gcc/testsuite/gcc.target/sh/pr54089-5.c
index f781acabf8e..decb9db9504 100644
--- a/gcc/testsuite/gcc.target/sh/pr54089-5.c
+++ b/gcc/testsuite/gcc.target/sh/pr54089-5.c
@@ -1,6 +1,6 @@
/* Check that the movrt rotr instruction sequence is generated when shifting
the negated T bit on SH2A. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O1" } */
/* { dg-skip-if "" { "sh*-*-*" } { "*" } { "-m2a*" } } */
/* { dg-final { scan-assembler-times "movrt" 1 } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr54089-6.c b/gcc/testsuite/gcc.target/sh/pr54089-6.c
index a12a0e93044..577690dd832 100644
--- a/gcc/testsuite/gcc.target/sh/pr54089-6.c
+++ b/gcc/testsuite/gcc.target/sh/pr54089-6.c
@@ -1,9 +1,9 @@
/* Check that the rotr and rotl instructions are generated. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O1" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*" } { "" } } */
/* { dg-final { scan-assembler-times "rotr" 2 } } */
-/* { dg-final { scan-assembler-times "rotl" 2 } } */
+/* { dg-final { scan-assembler-times "rotl" 3 } } */
int
test_00 (int a)
@@ -28,3 +28,9 @@ test_03 (int a)
{
return ((a >> 1) & 0x7FFFFFFF) | (a << 31);
}
+
+int
+test_04 (int a)
+{
+ return a + a + ((a >> 31) & 1);
+}
diff --git a/gcc/testsuite/gcc.target/sh/pr54089-7.c b/gcc/testsuite/gcc.target/sh/pr54089-7.c
index 40ca8219a2f..0476f75d199 100644
--- a/gcc/testsuite/gcc.target/sh/pr54089-7.c
+++ b/gcc/testsuite/gcc.target/sh/pr54089-7.c
@@ -1,5 +1,5 @@
/* Check that the rotcr instruction is generated. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O1" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
/* { dg-final { scan-assembler-times "rotcr" 4 } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr54089-8.c b/gcc/testsuite/gcc.target/sh/pr54089-8.c
index fa9e8f38380..d2cced75a58 100644
--- a/gcc/testsuite/gcc.target/sh/pr54089-8.c
+++ b/gcc/testsuite/gcc.target/sh/pr54089-8.c
@@ -1,5 +1,5 @@
/* Check that the rotcl instruction is generated. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O1" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
/* { dg-final { scan-assembler-times "rotcl" 28 } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr54089-9.c b/gcc/testsuite/gcc.target/sh/pr54089-9.c
index bd889dc34be..8aa15df8605 100644
--- a/gcc/testsuite/gcc.target/sh/pr54089-9.c
+++ b/gcc/testsuite/gcc.target/sh/pr54089-9.c
@@ -1,5 +1,5 @@
/* Check that the rotcr instruction is generated. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O1" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
/* { dg-final { scan-assembler-times "rotcl" 4 } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr54236-1.c b/gcc/testsuite/gcc.target/sh/pr54236-1.c
index 748b6c9f237..f7568a92c59 100644
--- a/gcc/testsuite/gcc.target/sh/pr54236-1.c
+++ b/gcc/testsuite/gcc.target/sh/pr54236-1.c
@@ -1,7 +1,7 @@
/* Tests to check the utilization of addc, subc and negc instructions in
special cases. If everything works as expected we won't see any
movt instructions in these cases. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O1" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
/* { dg-final { scan-assembler-times "addc" 4 } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr54236-2.c b/gcc/testsuite/gcc.target/sh/pr54236-2.c
new file mode 100644
index 00000000000..b3cf48c9d32
--- /dev/null
+++ b/gcc/testsuite/gcc.target/sh/pr54236-2.c
@@ -0,0 +1,270 @@
+/* Tests to check the utilization of the addc instruction in special cases.
+ If everything works as expected we won't see any movt instructions in
+ these cases. */
+/* { dg-do compile } */
+/* { dg-options "-O1" } */
+/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
+/* { dg-final { scan-assembler-times "addc" 37 } } */
+/* { dg-final { scan-assembler-times "shlr" 23 } } */
+/* { dg-final { scan-assembler-times "shll" 14 } } */
+/* { dg-final { scan-assembler-times "add\t" 12 } } */
+/* { dg-final { scan-assembler-not "movt" } } */
+
+int
+test_000 (int a, int c, int b, int d)
+{
+ // 1x shlr, 1x addc
+ return a + (b & 1);
+}
+
+int
+test_001 (int a, int c, int b, int d)
+{
+ // 1x shlr, 1x addc
+ return a + b + (c & 1);
+}
+
+int
+test_002 (int a, int c, int b, int d)
+{
+ // 1x shlr, 1x add, 1x addc
+ return a + b + c + (d & 1);
+}
+
+int
+test_003 (int a, int c, int b, int d)
+{
+ // 1x shlr, 1x addc
+ return (b & 1) + a;
+}
+
+int
+test_004 (int a, int c, int b, int d)
+{
+ // 1x shlr, 1x addc
+ return a + (c & 1) + b;
+}
+
+int
+test_005 (int a, int c, int b, int d)
+{
+ // 1x shlr, 1x add, 1x addc
+ return a + b + (d & 1) + c;
+}
+
+int
+test_006 (int a, int c, int b, int d)
+{
+ // 1x shlr, 1x addc
+ return (c & 1) + a + b;
+}
+
+int
+test_007 (int a, int c, int b, int d)
+{
+ // 1x shlr, 1x add, 1x addc
+ return a + (d & 1) + b + c;
+}
+
+int
+test_008 (int a, int c, int b, int d)
+{
+ // 1x shlr, 1x add, 1x addc
+ return (d & 1) + a + b + c;
+}
+
+int
+test_009 (int a, int c, int b, int d)
+{
+ // 1x shlr, 1x addc
+ return a + b + (b & 1);
+}
+
+int
+test_010 (int a, int c, int b, int d)
+{
+ // 1x shlr, 1x addc
+ return a + (b & 1) + b;
+}
+
+int
+test_011 (int a, int c, int b, int d)
+{
+ // 1x shlr, 1x addc
+ return (b & 1) + a + b;
+}
+
+int
+test_012 (int a, int c, int b, int d)
+{
+ // 1x shlr, 1x add, 1x addc
+ return a + b + d + (b & 1);
+}
+
+int
+test_013 (int a, int c, int b, int d)
+{
+ // 1x shlr, 1x add, 1x addc
+ return a + d + (b & 1) + b;
+}
+
+int
+test_014 (int a, int c, int b, int d)
+{
+ // 1x shlr, 1x add, 1x addc
+ return a + (b & 1) + d + b;
+}
+
+int
+test_015 (int a, int c, int b, int d)
+{
+ // 1x shlr, 1x add, 1x addc
+ return (b & 1) + a + d + b;
+}
+
+int
+test_016 (int a, int b, int c, int d)
+{
+ // 1x shlr, 1x addc
+ return a + (a & 1);
+}
+
+int
+test_017 (int a, int b, int c, int d)
+{
+ // 1x shlr, 1x addc
+ return a + a + (a & 1);
+}
+
+int
+test_018 (int a, int b, int c, int d)
+{
+ // 1x shlr, 1x addc
+ return a + (a & 1) + a;
+}
+
+int
+test_019 (int a, int b, int c, int d)
+{
+ // 1x shlr, 1x addc
+ return (a & 1) + a + a;
+}
+
+int
+test_020 (int a, int b, int c, int d)
+{
+ // 1x shlr, 1x addc
+ return b + b + (a & 1);
+}
+
+int
+test_021 (int a, int b, int c, int d)
+{
+ // 1x shlr, 1x addc
+ return b + (a & 1) + b;
+}
+
+int
+test_022 (int a, int b, int c, int d)
+{
+ // 1x shlr, 1x addc
+ return (a & 1) + b + b;
+}
+
+int
+test_023 (int a, int b, int c, int d)
+{
+ // 1x shll, 1x addc
+ return a + ((b >> 31) & 1);
+}
+
+int
+test_024 (int a, int b, int c, int d)
+{
+ // 1x shll, 1x addc
+ return ((b >> 31) & 1) + a;
+}
+
+int
+test_025 (int a, int b, int c, int d)
+{
+ // 1x shll, 1x addc
+ return ((a >> 31) & 1) + a;
+}
+
+int
+test_026 (int a, int b, int c, int d)
+{
+ // 1x shll, 1x addc
+ return a + ((a >> 31) & 1);
+}
+
+int
+test_027 (int a, int b, int c, int d)
+{
+ // 1x shll, 1x addc
+ return a + b + ((c >> 31) & 1);
+}
+
+int
+test_028 (int a, int b, int c, int d)
+{
+ // 1x shll, 1x addc
+ return a + ((c >> 31) & 1) + b;
+}
+
+int
+test_029 (int a, int b, int c, int d)
+{
+ // 1x shll, 1x addc
+ return ((c >> 31) & 1) + a + b;
+}
+
+int
+test_030 (int a, int b, int c, int d)
+{
+ // 1x shll, 1x addc, 1x add
+ return a + b + c + ((d >> 31) & 1);
+}
+
+int
+test_031 (int a, int b, int c, int d)
+{
+ // 1x shll, 1x addc, 1x add
+ return a + b + ((d >> 31) & 1) + c;
+}
+
+int
+test_032 (int a, int b, int c, int d)
+{
+ // 1x shll, 1x addc, 1x add
+ return a + ((d >> 31) & 1) + b + c;
+}
+
+int
+test_033 (int a, int b, int c, int d)
+{
+ // 1x shll, 1x addc, 1x add
+ return ((d >> 31) & 1) + a + b + c;
+}
+
+int
+test_034 (int a, int b, int c, int d)
+{
+ // 1x shll, 1x addc
+ return a + a + ((d >> 31) & 1);
+}
+
+int
+test_035 (int a, int b, int c, int d)
+{
+ // 1x shll, 1x addc
+ return a + ((d >> 31) & 1) + a;
+}
+
+int
+test_036 (int a, int b, int c, int d)
+{
+ // 1x shll, 1x addc
+ return ((d >> 31) & 1) + a + a;
+}
diff --git a/gcc/testsuite/gcc.target/sh/pr54386.c b/gcc/testsuite/gcc.target/sh/pr54386.c
index 4e17f37b09f..ec52d89405a 100644
--- a/gcc/testsuite/gcc.target/sh/pr54386.c
+++ b/gcc/testsuite/gcc.target/sh/pr54386.c
@@ -1,5 +1,5 @@
/* Check that the inlined mem load is not handled as unaligned load. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
/* { dg-final { scan-assembler-not "shll|extu|or" } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr54602-1.c b/gcc/testsuite/gcc.target/sh/pr54602-1.c
index e5c035708e4..bd402b3a0c1 100644
--- a/gcc/testsuite/gcc.target/sh/pr54602-1.c
+++ b/gcc/testsuite/gcc.target/sh/pr54602-1.c
@@ -1,7 +1,7 @@
/* Verify that the delay slot is stuffed with register pop insns for normal
(i.e. not interrupt handler) function returns. If everything goes as
expected we won't see any nop insns. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O1" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
/* { dg-final { scan-assembler-not "nop" } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr54602-2.c b/gcc/testsuite/gcc.target/sh/pr54602-2.c
index 4f3877c41b1..05592ddbfdd 100644
--- a/gcc/testsuite/gcc.target/sh/pr54602-2.c
+++ b/gcc/testsuite/gcc.target/sh/pr54602-2.c
@@ -1,7 +1,7 @@
/* Verify that the delay slot is not stuffed with register pop insns for
interrupt handler function returns on SH1* and SH2* targets, where the
rte insn uses the stack pointer. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O1" } */
/* { dg-skip-if "" { "sh*-*-*" } { "*" } { "-m1*" "-m2*" } } */
/* { dg-final { scan-assembler-times "nop" 1 } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr54602-3.c b/gcc/testsuite/gcc.target/sh/pr54602-3.c
index 29292589c62..5d6a75a70ae 100644
--- a/gcc/testsuite/gcc.target/sh/pr54602-3.c
+++ b/gcc/testsuite/gcc.target/sh/pr54602-3.c
@@ -1,6 +1,6 @@
/* Verify that the rte delay slot is not stuffed with register pop insns
which touch the banked registers r0..r7 on SH3* and SH4* targets. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O1" } */
/* { dg-skip-if "" { "sh*-*-*" } { "*" } { "-m3*" "-m4*" } } */
/* { dg-final { scan-assembler-times "nop" 1 } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr54602-4.c b/gcc/testsuite/gcc.target/sh/pr54602-4.c
index 0b77d0983ae..78fb9096e93 100644
--- a/gcc/testsuite/gcc.target/sh/pr54602-4.c
+++ b/gcc/testsuite/gcc.target/sh/pr54602-4.c
@@ -1,7 +1,7 @@
/* Verify that the delay slot is stuffed with register pop insns on SH3* and
SH4* targets, where the stack pointer is not used by the rte insn. If
everything works out, we won't see a nop insn. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O1" } */
/* { dg-skip-if "" { "sh*-*-*" } { "*" } { "-m3*" "-m4*" } } */
/* { dg-final { scan-assembler-not "nop" } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr54680.c b/gcc/testsuite/gcc.target/sh/pr54680.c
index 27c44d3ca4d..9171eeaf65c 100644
--- a/gcc/testsuite/gcc.target/sh/pr54680.c
+++ b/gcc/testsuite/gcc.target/sh/pr54680.c
@@ -1,7 +1,7 @@
/* Verify that the fsca input value is not converted to float and then back
to int. Notice that we can't count just "lds" insns because mode switches
use "lds.l". */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O2 -mfsca -funsafe-math-optimizations" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m1" "-m2*" "-m3*" "-m4al" "*nofpu" "-m4-340*" "-m4-400*" "-m4-500*" "-m5*" } { "" } } */
/* { dg-final { scan-assembler-times "fsca" 7 } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr54685.c b/gcc/testsuite/gcc.target/sh/pr54685.c
index 38a1410fbe1..111a12013d6 100644
--- a/gcc/testsuite/gcc.target/sh/pr54685.c
+++ b/gcc/testsuite/gcc.target/sh/pr54685.c
@@ -1,6 +1,6 @@
/* Check that a comparison 'unsigned int <= 0x7FFFFFFF' results in code
utilizing the cmp/pz instruction. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O1" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
/* { dg-final { scan-assembler-not "not\[ \t\]" } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr54760-1.c b/gcc/testsuite/gcc.target/sh/pr54760-1.c
index 9108a3fde8a..4437511cf7c 100644
--- a/gcc/testsuite/gcc.target/sh/pr54760-1.c
+++ b/gcc/testsuite/gcc.target/sh/pr54760-1.c
@@ -1,6 +1,6 @@
/* Check that the __builtin_thread_pointer and __builtin_set_thread_pointer
built-in functions result in gbr store / load instructions. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O1" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
/* { dg-final { scan-assembler-times "ldc" 1 } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr54760-2.c b/gcc/testsuite/gcc.target/sh/pr54760-2.c
index 91f3648a599..4a3561a56e9 100644
--- a/gcc/testsuite/gcc.target/sh/pr54760-2.c
+++ b/gcc/testsuite/gcc.target/sh/pr54760-2.c
@@ -1,7 +1,7 @@
/* Check that thread pointer relative memory accesses are converted to
gbr displacement address modes. If we see a gbr register store
instruction something is not working properly. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O1" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
/* { dg-final { scan-assembler-times "stc\tgbr" 0 } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr54760-3.c b/gcc/testsuite/gcc.target/sh/pr54760-3.c
index 2b6f1861783..678fb395426 100644
--- a/gcc/testsuite/gcc.target/sh/pr54760-3.c
+++ b/gcc/testsuite/gcc.target/sh/pr54760-3.c
@@ -2,7 +2,7 @@
surrounding code.
These should be moved to C torture tests once there are target
independent thread_pointer built-in functions available. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O1" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr54760-4.c b/gcc/testsuite/gcc.target/sh/pr54760-4.c
index 1b2c71b670d..d21828196b6 100644
--- a/gcc/testsuite/gcc.target/sh/pr54760-4.c
+++ b/gcc/testsuite/gcc.target/sh/pr54760-4.c
@@ -1,7 +1,7 @@
/* Check that the GBR address optimization does not combine a gbr store
and its use when a function call is in between, when GBR is a call used
register, i.e. it is invalidated by function calls. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O1 -fcall-used-gbr" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
/* { dg-final { scan-assembler "stc\tgbr" } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr55146.c b/gcc/testsuite/gcc.target/sh/pr55146.c
index 11dd49ff6e4..91f09359d1c 100644
--- a/gcc/testsuite/gcc.target/sh/pr55146.c
+++ b/gcc/testsuite/gcc.target/sh/pr55146.c
@@ -1,5 +1,5 @@
/* Check that the 'extu.b' instruction is generated for short jump tables. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-Os" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
/* { dg-final { scan-assembler "extu.b" } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr55160.c b/gcc/testsuite/gcc.target/sh/pr55160.c
index ae0d83aa7cf..dca15c9b5ab 100644
--- a/gcc/testsuite/gcc.target/sh/pr55160.c
+++ b/gcc/testsuite/gcc.target/sh/pr55160.c
@@ -1,5 +1,5 @@
/* Check that the decrement-and-test instruction is generated. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O1" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
/* { dg-final { scan-assembler-times "dt\tr" 2 } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr55303-1.c b/gcc/testsuite/gcc.target/sh/pr55303-1.c
index 06151e8675c..b77c5e10ee5 100644
--- a/gcc/testsuite/gcc.target/sh/pr55303-1.c
+++ b/gcc/testsuite/gcc.target/sh/pr55303-1.c
@@ -1,6 +1,6 @@
/* Verify that the SH2A clips and clipu instructions are generated as
expected. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-skip-if "" { "sh*-*-*" } { "*" } { "-m2a*" } } */
/* { dg-final { scan-assembler-times "clips.b" 2 } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr55303-2.c b/gcc/testsuite/gcc.target/sh/pr55303-2.c
index a70a30aa212..34f706327df 100644
--- a/gcc/testsuite/gcc.target/sh/pr55303-2.c
+++ b/gcc/testsuite/gcc.target/sh/pr55303-2.c
@@ -1,7 +1,7 @@
/* Verify that for SH2A smax/smin -> cbranch conversion is done properly
if the clips insn is not used and the expected comparison insns are
generated. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-skip-if "" { "sh*-*-*" } { "*" } { "-m2a*" } } */
/* { dg-final { scan-assembler-times "cmp/pl" 4 } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr55303-3.c b/gcc/testsuite/gcc.target/sh/pr55303-3.c
index b353539be77..57c2f403e71 100644
--- a/gcc/testsuite/gcc.target/sh/pr55303-3.c
+++ b/gcc/testsuite/gcc.target/sh/pr55303-3.c
@@ -1,6 +1,6 @@
/* Verify that the special case (umin (reg const_int 1)) results in the
expected instruction sequence on SH2A. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-skip-if "" { "sh*-*-*" } { "*" } { "-m2a*" } } */
/* { dg-final { scan-assembler-times "tst" 1 } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr56547-1.c b/gcc/testsuite/gcc.target/sh/pr56547-1.c
index 0ba21a685a4..0c7c97e81dd 100644
--- a/gcc/testsuite/gcc.target/sh/pr56547-1.c
+++ b/gcc/testsuite/gcc.target/sh/pr56547-1.c
@@ -1,7 +1,7 @@
/* Verify that the fmac insn is used for the expression 'a * b + a' and
'a * a + a'.
This assumes that the default compiler setting is -ffp-contract=fast. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O1" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m1" "-m2" "-m3" "-m4al" "*nofpu" "-m4-340*" "-m4-400*" "-m4-500*" "-m5*" } { "" } } */
/* { dg-final { scan-assembler-times "fmac" 2 } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr56547-2.c b/gcc/testsuite/gcc.target/sh/pr56547-2.c
index 02e1a0f86f4..2d36fa9c568 100644
--- a/gcc/testsuite/gcc.target/sh/pr56547-2.c
+++ b/gcc/testsuite/gcc.target/sh/pr56547-2.c
@@ -1,6 +1,6 @@
/* Verify that the fmac insn is used for the expression 'a * b + a' and
'a * a + a' when -ffast-math is specified. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O1 -ffast-math" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m1" "-m2" "-m3" "-m4al" "*nofpu" "-m4-340*" "-m4-400*" "-m4-500*" "-m5*" } { "" } } */
/* { dg-final { scan-assembler-times "fmac" 2 } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr6526.c b/gcc/testsuite/gcc.target/sh/pr6526.c
index a7dd6d87af6..a49b877b576 100644
--- a/gcc/testsuite/gcc.target/sh/pr6526.c
+++ b/gcc/testsuite/gcc.target/sh/pr6526.c
@@ -1,6 +1,6 @@
/* Check that the XF registers are not clobbered by an integer division
that is done using double precision FPU division. */
-/* { dg-do run { target "sh*-*-*" } } */
+/* { dg-do run } */
/* { dg-options "-O1 -mdiv=call-fp" } */
/* { dg-skip-if "" { "sh*-*-*" } { "*" } { "-m4*-single" "-m4*-single-only" } } */
diff --git a/gcc/testsuite/gcc.target/sh/pragma-isr-trap-exit.c b/gcc/testsuite/gcc.target/sh/pragma-isr-trap-exit.c
index 823eb967b41..6dbd8e7c932 100644
--- a/gcc/testsuite/gcc.target/sh/pragma-isr-trap-exit.c
+++ b/gcc/testsuite/gcc.target/sh/pragma-isr-trap-exit.c
@@ -1,5 +1,5 @@
/* Check whether trapa is generated only for an ISR. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*" } { "" } } */
/* { dg-options "-O" } */
/* { dg-final { scan-assembler-times "trapa\[ \t\]\[ \t\]*#4" 1 } } */
diff --git a/gcc/testsuite/gcc.target/sh/prefetch.c b/gcc/testsuite/gcc.target/sh/prefetch.c
index e0873737453..fb580bde87a 100644
--- a/gcc/testsuite/gcc.target/sh/prefetch.c
+++ b/gcc/testsuite/gcc.target/sh/prefetch.c
@@ -1,6 +1,6 @@
/* Testcase to check generation of a SH4 and SH2A operand cache prefetch
instruction PREF @Rm. */
-/* { dg-do assemble {target sh*-*-*}} */
+/* { dg-do assemble } */
/* { dg-options "-O0" } */
/* { dg-skip-if "" { "sh*-*-*" } { "*" } { "-m2a*" "-m3*" "-m4*" } } */
/* { dg-final { scan-assembler "pref"} } */
diff --git a/gcc/testsuite/gcc.target/sh/rte-delay-slot.c b/gcc/testsuite/gcc.target/sh/rte-delay-slot.c
index eca5db94355..48f1b13b0d3 100644
--- a/gcc/testsuite/gcc.target/sh/rte-delay-slot.c
+++ b/gcc/testsuite/gcc.target/sh/rte-delay-slot.c
@@ -1,4 +1,4 @@
-/* { dg-do compile { target "sh-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-skip-if "" { "sh*-*-*" } "*" "-m1 -m2*" } */
/* { dg-final { scan-assembler-not "\trte\t\n\tmov.l\t@r15\\+" } } */
diff --git a/gcc/testsuite/gcc.target/sh/sh2a-band.c b/gcc/testsuite/gcc.target/sh/sh2a-band.c
index 34862b7256d..a5096262c87 100644
--- a/gcc/testsuite/gcc.target/sh/sh2a-band.c
+++ b/gcc/testsuite/gcc.target/sh/sh2a-band.c
@@ -1,6 +1,6 @@
/* Testcase to check generation of a SH2A specific instruction for
"BAND.B #imm3, @(disp12, Rn)". */
-/* { dg-do assemble {target sh*-*-*}} */
+/* { dg-do assemble } */
/* { dg-options "-O1 -mbitops" } */
/* { dg-skip-if "" { "sh*-*-*" } "*" "-m2a -m2a-nofpu -m2a-single -m2a-single-only" } */
/* { dg-final { scan-assembler "band.b"} } */
diff --git a/gcc/testsuite/gcc.target/sh/sh2a-bclr.c b/gcc/testsuite/gcc.target/sh/sh2a-bclr.c
index d4e11f95298..ab1e3ddab20 100644
--- a/gcc/testsuite/gcc.target/sh/sh2a-bclr.c
+++ b/gcc/testsuite/gcc.target/sh/sh2a-bclr.c
@@ -1,6 +1,6 @@
/* Testcase to check generation of a SH2A specific instruction
'BCLR #imm3,Rn'. */
-/* { dg-do assemble {target sh*-*-*}} */
+/* { dg-do assemble } */
/* { dg-options "-O1" } */
/* { dg-skip-if "" { "sh*-*-*" } "*" "-m2a -m2a-nofpu -m2a-single -m2a-single-only" } */
/* { dg-final { scan-assembler "bclr"} } */
diff --git a/gcc/testsuite/gcc.target/sh/sh2a-bclrmem.c b/gcc/testsuite/gcc.target/sh/sh2a-bclrmem.c
index 41cb3bdfedd..9c99c592980 100644
--- a/gcc/testsuite/gcc.target/sh/sh2a-bclrmem.c
+++ b/gcc/testsuite/gcc.target/sh/sh2a-bclrmem.c
@@ -1,6 +1,6 @@
/* Testcase to check generation of a SH2A specific instruction
"BCLR #imm3,@(disp12,Rn)". */
-/* { dg-do assemble {target sh*-*-*}} */
+/* { dg-do assemble } */
/* { dg-options "-O2 -mbitops" } */
/* { dg-skip-if "" { "sh*-*-*" } "*" "-m2a -m2a-nofpu -m2a-single -m2a-single-only" } */
/* { dg-final { scan-assembler "bclr"} } */
diff --git a/gcc/testsuite/gcc.target/sh/sh2a-bld.c b/gcc/testsuite/gcc.target/sh/sh2a-bld.c
index 1cf56fe2714..d0c74c9c72c 100644
--- a/gcc/testsuite/gcc.target/sh/sh2a-bld.c
+++ b/gcc/testsuite/gcc.target/sh/sh2a-bld.c
@@ -4,7 +4,7 @@
BLD #imm3, Rn
BLD.B #imm3, @(disp12, Rn)
*/
-/* { dg-do assemble {target sh*-*-*}} */
+/* { dg-do assemble } */
/* { dg-options "-Os -mbitops" } */
/* { dg-skip-if "" { "sh*-*-*" } "*" "-m2a -m2a-nofpu -m2a-single -m2a-single-only" } */
/* { dg-final { scan-assembler "bld"} } */
diff --git a/gcc/testsuite/gcc.target/sh/sh2a-bor.c b/gcc/testsuite/gcc.target/sh/sh2a-bor.c
index c3803c6b9ca..8db43770997 100644
--- a/gcc/testsuite/gcc.target/sh/sh2a-bor.c
+++ b/gcc/testsuite/gcc.target/sh/sh2a-bor.c
@@ -1,6 +1,6 @@
/* Testcase to check generation of a SH2A specific instruction for
"BOR.B #imm3, @(disp12, Rn)". */
-/* { dg-do assemble {target sh*-*-*}} */
+/* { dg-do assemble } */
/* { dg-options "-O1 -mbitops" } */
/* { dg-skip-if "" { "sh*-*-*" } "*" "-m2a -m2a-nofpu -m2a-single -m2a-single-only" } */
/* { dg-final { scan-assembler "bor.b"} } */
diff --git a/gcc/testsuite/gcc.target/sh/sh2a-bset.c b/gcc/testsuite/gcc.target/sh/sh2a-bset.c
index b64852b4c36..322821b5acc 100644
--- a/gcc/testsuite/gcc.target/sh/sh2a-bset.c
+++ b/gcc/testsuite/gcc.target/sh/sh2a-bset.c
@@ -1,6 +1,6 @@
/* Testcase to check generation of a SH2A specific instruction
'BSET #imm3,Rn'. */
-/* { dg-do assemble {target sh*-*-*}} */
+/* { dg-do assemble } */
/* { dg-options "-O1" } */
/* { dg-skip-if "" { "sh*-*-*" } "*" "-m2a -m2a-nofpu -m2a-single -m2a-single-only" } */
/* { dg-final { scan-assembler "bset"} } */
diff --git a/gcc/testsuite/gcc.target/sh/sh2a-bsetmem.c b/gcc/testsuite/gcc.target/sh/sh2a-bsetmem.c
index b0ebf0851dc..cf35ed632bf 100644
--- a/gcc/testsuite/gcc.target/sh/sh2a-bsetmem.c
+++ b/gcc/testsuite/gcc.target/sh/sh2a-bsetmem.c
@@ -1,6 +1,6 @@
/* Testcase to check generation of a SH2A specific instruction
"BSET #imm3,@(disp12,Rn)". */
-/* { dg-do assemble {target sh*-*-*}} */
+/* { dg-do assemble } */
/* { dg-options "-O2 -mbitops" } */
/* { dg-skip-if "" { "sh*-*-*" } "*" "-m2a -m2a-nofpu -m2a-single -m2a-single-only" } */
/* { dg-final { scan-assembler "bset"} } */
diff --git a/gcc/testsuite/gcc.target/sh/sh2a-bxor.c b/gcc/testsuite/gcc.target/sh/sh2a-bxor.c
index afe0a5ec979..6cca825e612 100644
--- a/gcc/testsuite/gcc.target/sh/sh2a-bxor.c
+++ b/gcc/testsuite/gcc.target/sh/sh2a-bxor.c
@@ -1,6 +1,6 @@
/* Testcase to check generation of a SH2A specific instruction for
"BXOR.B #imm3, @(disp12, Rn)". */
-/* { dg-do assemble {target sh*-*-*}} */
+/* { dg-do assemble } */
/* { dg-options "-O1 -mbitops" } */
/* { dg-skip-if "" { "sh*-*-*" } "*" "-m2a -m2a-nofpu -m2a-single -m2a-single-only" } */
/* { dg-final { scan-assembler "bxor.b"} } */
diff --git a/gcc/testsuite/gcc.target/sh/sh2a-jsrn.c b/gcc/testsuite/gcc.target/sh/sh2a-jsrn.c
index 9b9b92cb920..3f55327f0d7 100644
--- a/gcc/testsuite/gcc.target/sh/sh2a-jsrn.c
+++ b/gcc/testsuite/gcc.target/sh/sh2a-jsrn.c
@@ -1,6 +1,6 @@
/* Testcase to check generation of a SH2A specific instruction for
'JSR/N @Rm'. */
-/* { dg-do assemble {target sh*-*-*}} */
+/* { dg-do assemble } */
/* { dg-options "-O0" } */
/* { dg-skip-if "" { "sh*-*-*" } "*" "-m2a -m2a-nofpu -m2a-single -m2a-single-only" } */
/* { dg-final { scan-assembler "jsr/n"} } */
diff --git a/gcc/testsuite/gcc.target/sh/sh2a-movi20s.c b/gcc/testsuite/gcc.target/sh/sh2a-movi20s.c
index 55d2f665b3b..fe3226e2514 100644
--- a/gcc/testsuite/gcc.target/sh/sh2a-movi20s.c
+++ b/gcc/testsuite/gcc.target/sh/sh2a-movi20s.c
@@ -1,5 +1,5 @@
/* Testcase to check generation of 'MOVI20S #imm20, Rn'. */
-/* { dg-do assemble {target sh*-*-*}} */
+/* { dg-do assemble } */
/* { dg-options "-O0" } */
/* { dg-skip-if "" { "sh*-*-*" } "*" "-m2a -m2a-nofpu -m2a-single -m2a-single-only" } */
/* { dg-final { scan-assembler "movi20s"} } */
diff --git a/gcc/testsuite/gcc.target/sh/sh2a-movrt.c b/gcc/testsuite/gcc.target/sh/sh2a-movrt.c
index 9df9f4ba976..3e72930ca64 100644
--- a/gcc/testsuite/gcc.target/sh/sh2a-movrt.c
+++ b/gcc/testsuite/gcc.target/sh/sh2a-movrt.c
@@ -1,6 +1,6 @@
/* Testcase to check generation of a SH2A specific instruction for
'MOVRT Rn'. */
-/* { dg-do assemble {target sh*-*-*}} */
+/* { dg-do assemble } */
/* { dg-options "-O1" } */
/* { dg-skip-if "" { "sh*-*-*" } "*" "-m2a -m2a-nofpu -m2a-single -m2a-single-only" } */
/* { dg-final { scan-assembler "movrt"} } */
diff --git a/gcc/testsuite/gcc.target/sh/sh2a-resbank.c b/gcc/testsuite/gcc.target/sh/sh2a-resbank.c
index aab6852f336..a12a711afa6 100644
--- a/gcc/testsuite/gcc.target/sh/sh2a-resbank.c
+++ b/gcc/testsuite/gcc.target/sh/sh2a-resbank.c
@@ -1,5 +1,5 @@
/* Test for resbank attribute. */
-/* { dg-do assemble {target sh*-*-*}} */
+/* { dg-do assemble } */
/* { dg-skip-if "" { "sh*-*-*" } "*" "-m2a -m2a-nofpu -m2a-single -m2a-single-only" } */
/* { dg-final { scan-assembler "resbank" } } */
diff --git a/gcc/testsuite/gcc.target/sh/sh2a-rtsn.c b/gcc/testsuite/gcc.target/sh/sh2a-rtsn.c
index 2601ced5cff..612c3032de1 100644
--- a/gcc/testsuite/gcc.target/sh/sh2a-rtsn.c
+++ b/gcc/testsuite/gcc.target/sh/sh2a-rtsn.c
@@ -1,6 +1,6 @@
/* Testcase to check generation of a SH2A specific instruction for
'RTS/N'. */
-/* { dg-do assemble {target sh*-*-*}} */
+/* { dg-do assemble } */
/* { dg-options "-O0" } */
/* { dg-skip-if "" { "sh*-*-*" } "*" "-m2a -m2a-nofpu -m2a-single -m2a-single-only" } */
/* { dg-final { scan-assembler "rts/n"} } */
diff --git a/gcc/testsuite/gcc.target/sh/sh2a-tbr-jump.c b/gcc/testsuite/gcc.target/sh/sh2a-tbr-jump.c
index 8029b03dd4a..24b57febe63 100644
--- a/gcc/testsuite/gcc.target/sh/sh2a-tbr-jump.c
+++ b/gcc/testsuite/gcc.target/sh/sh2a-tbr-jump.c
@@ -1,6 +1,6 @@
/* Testcase to check generation of a SH2A specific,
TBR relative jump instruction - 'JSR @@(disp8,TBR)'. */
-/* { dg-do assemble {target sh*-*-*}} */
+/* { dg-do assemble } */
/* { dg-options "" } */
/* { dg-skip-if "" { "sh*-*-*" } "*" "-m2a -m2a-nofpu -m2a-single -m2a-single-only" } */
/* { dg-final { scan-assembler-times "jsr/n\\t@@\\(40,tbr\\)" 1} } */
diff --git a/gcc/testsuite/gcc.target/sh/sh4a-bitmovua.c b/gcc/testsuite/gcc.target/sh/sh4a-bitmovua.c
index 7912fbc551d..35ebf5cd3e6 100644
--- a/gcc/testsuite/gcc.target/sh/sh4a-bitmovua.c
+++ b/gcc/testsuite/gcc.target/sh/sh4a-bitmovua.c
@@ -1,5 +1,5 @@
/* Verify that we generate movua to load unaligned 32-bit values on SH4A. */
-/* { dg-do run { target "sh*-*-*" } } */
+/* { dg-do run } */
/* { dg-options "-O1 -save-temps -fno-inline" } */
/* { dg-skip-if "" { "sh*-*-*" } { "*" } { "-m4a*" } } */
/* { dg-final { scan-assembler-times "movua.l" 6 } } */
diff --git a/gcc/testsuite/gcc.target/sh/sh4a-cosf.c b/gcc/testsuite/gcc.target/sh/sh4a-cosf.c
index 68bb20f2c33..d6277da7e9a 100644
--- a/gcc/testsuite/gcc.target/sh/sh4a-cosf.c
+++ b/gcc/testsuite/gcc.target/sh/sh4a-cosf.c
@@ -1,6 +1,6 @@
/* Verify that we generate single-precision sine and cosine approximate
(fsca) in fast math mode on SH4A with FPU. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O -ffast-math" } */
/* { dg-skip-if "" { "sh*-*-*" } { "*" } { "-m4a" "-m4a-single" "-m4a-single-only" } } */
/* { dg-final { scan-assembler "fsca" } } */
diff --git a/gcc/testsuite/gcc.target/sh/sh4a-fsrra.c b/gcc/testsuite/gcc.target/sh/sh4a-fsrra.c
index 4ce2e28e22f..0bd7d8773bb 100644
--- a/gcc/testsuite/gcc.target/sh/sh4a-fsrra.c
+++ b/gcc/testsuite/gcc.target/sh/sh4a-fsrra.c
@@ -1,6 +1,6 @@
/* Verify that we generate single-precision square root reciprocal
approximate (fsrra) in fast math mode on SH4A with FPU. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O -ffast-math" } */
/* { dg-skip-if "" { "sh*-*-*" } { "*" } { "-m4a" "-m4a-single" "-m4a-single-only" } } */
/* { dg-final { scan-assembler "fsrra" } } */
diff --git a/gcc/testsuite/gcc.target/sh/sh4a-sincosf.c b/gcc/testsuite/gcc.target/sh/sh4a-sincosf.c
index 0ca33e30a0f..b85fa86a278 100644
--- a/gcc/testsuite/gcc.target/sh/sh4a-sincosf.c
+++ b/gcc/testsuite/gcc.target/sh/sh4a-sincosf.c
@@ -1,7 +1,7 @@
/* Verify that we generate a single single-precision sine and cosine
approximate (fsca) in fast math mode when a function computes both
sine and cosine. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O -ffast-math" } */
/* { dg-skip-if "" { "sh*-*-*" } { "*" } { "-m4a" "-m4a-single" "-m4a-single-only" } } */
/* { dg-final { scan-assembler-times "fsca" 1 } } */
diff --git a/gcc/testsuite/gcc.target/sh/sh4a-sinf.c b/gcc/testsuite/gcc.target/sh/sh4a-sinf.c
index 4d9abea045b..0ce13263ec1 100644
--- a/gcc/testsuite/gcc.target/sh/sh4a-sinf.c
+++ b/gcc/testsuite/gcc.target/sh/sh4a-sinf.c
@@ -1,6 +1,6 @@
/* Verify that we generate single-precision sine and cosine approximate
(fsca) in fast math mode on SH4A with FPU. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-O -ffast-math" } */
/* { dg-skip-if "" { "sh*-*-*" } { "*" } { "-m4a" "-m4a-single" "-m4a-single-only" } } */
/* { dg-final { scan-assembler "fsca" } } */
diff --git a/gcc/testsuite/gcc.target/sh/sp-switch.c b/gcc/testsuite/gcc.target/sh/sp-switch.c
index 1bfe6a7de69..aad6ba001c0 100644
--- a/gcc/testsuite/gcc.target/sh/sp-switch.c
+++ b/gcc/testsuite/gcc.target/sh/sp-switch.c
@@ -1,4 +1,4 @@
-/* { dg-do compile { target "sh-*-*" } } */
+/* { dg-do compile } */
/* { dg-final { scan-assembler "mov\tr0,r15" } } */
/* { dg-final { scan-assembler ".long\t_alt_stack" } } */
diff --git a/gcc/testsuite/gcc.target/sh/strlen.c b/gcc/testsuite/gcc.target/sh/strlen.c
new file mode 100644
index 00000000000..115baba99cd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/sh/strlen.c
@@ -0,0 +1,19 @@
+/* Check that the __builtin_strlen function is inlined with cmp/str
+ when optimizing for speed. */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-skip-if "" { "sh*-*-*" } { "-m5*" } { "" } } */
+/* { dg-final { scan-assembler-not "jmp" } } */
+/* { dg-final { scan-assembler-times "cmp/str" 2 } } */
+/* { dg-final { scan-assembler-times "tst\t#3" 1 } } */
+
+test00 (const char *s1)
+{
+ return __builtin_strlen (s1);
+}
+
+/* Check that no test for alignment is needed. */
+test03(const char *s1)
+{
+ return __builtin_strlen (__builtin_assume_aligned (s1, 4));
+}
diff --git a/gcc/testsuite/gcc.target/sh/struct-arg-dw2.c b/gcc/testsuite/gcc.target/sh/struct-arg-dw2.c
index 81f80df1e68..50c8f34c3e6 100644
--- a/gcc/testsuite/gcc.target/sh/struct-arg-dw2.c
+++ b/gcc/testsuite/gcc.target/sh/struct-arg-dw2.c
@@ -1,6 +1,6 @@
/* Verify that we don't generate frame related insn against stack adjustment
for the object sent partially in registers. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-g" } */
/* { dg-final { scan-assembler-not "\t.cfi_def_cfa_offset 16" } } */
diff --git a/gcc/testsuite/gcc.target/sh/torture/pr30807.c b/gcc/testsuite/gcc.target/sh/torture/pr30807.c
new file mode 100644
index 00000000000..c9cc771b685
--- /dev/null
+++ b/gcc/testsuite/gcc.target/sh/torture/pr30807.c
@@ -0,0 +1,218 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-fpic -std=c99" } */
+/* { dg-skip-if "" { "sh*-*-*" } { "-m5*" } { "" } } */
+
+typedef unsigned int size_t;
+typedef struct
+{
+ unsigned long __val[(1024 / (8 * sizeof (unsigned long)))];
+} __sigset_t;
+struct __jmp_buf_tag
+{
+ __sigset_t __saved_mask;
+};
+typedef struct __jmp_buf_tag sigjmp_buf[1];
+struct stat
+{
+ long long st_dev;
+ unsigned short int __pad1;
+ int tm_isdst;
+ long int tm_gmtoff;
+ char *tm_zone;
+};
+
+typedef size_t STRLEN;
+typedef struct op OP;
+typedef struct cop COP;
+typedef struct interpreter PerlInterpreter;
+typedef struct sv SV;
+typedef struct av AV;
+typedef struct cv CV;
+typedef struct gp GP;
+typedef struct gv GV;
+typedef struct xpv XPV;
+typedef struct xpvio XPVIO;
+typedef union any ANY;
+typedef unsigned char U8;
+typedef long I32;
+typedef unsigned long U32;
+typedef U32 line_t;
+typedef struct _PerlIO PerlIOl;
+typedef PerlIOl *PerlIO;
+struct sv
+{
+ void *sv_any;
+ U32 sv_flags;
+ union
+ {
+ char *svu_pv;
+ } sv_u;
+};
+struct gv
+{
+ U32 sv_flags;
+ union
+ {
+ GP *svu_gp;
+ } sv_u;
+};
+struct io
+{
+ XPVIO *sv_any;
+};
+struct xpv
+{
+ STRLEN xpv_cur;
+};
+struct xpvio
+{
+ PerlIO *xio_ofp;
+};
+struct gp
+{
+ SV *gp_sv;
+ struct io *gp_io;
+};
+struct jmpenv
+{
+ struct jmpenv *je_prev;
+ sigjmp_buf je_buf;
+ int je_ret;
+};
+typedef struct jmpenv JMPENV;
+struct cop
+{
+ line_t cop_line;
+ struct refcounted_he *cop_hints_hash;
+};
+struct interpreter
+{
+ SV **Istack_sp;
+ OP *Iop;
+ SV **Icurpad;
+ SV **Istack_base;
+ SV **Istack_max;
+ I32 *Iscopestack;
+ I32 Iscopestack_ix;
+ I32 Iscopestack_max;
+ ANY *Isavestack;
+ I32 Isavestack_ix;
+ I32 Isavestack_max;
+ SV **Itmps_stack;
+ I32 Itmps_ix;
+ I32 Itmps_floor;
+ I32 Itmps_max;
+ I32 Imodcount;
+ I32 *Imarkstack;
+ I32 *Imarkstack_ptr;
+ I32 *Imarkstack_max;
+ SV *ISv;
+ XPV *IXpv;
+ STRLEN Ina;
+ struct stat Istatbuf;
+ struct stat Istatcache;
+ OP *Irestartop;
+ COP *volatile Icurcop;
+ JMPENV *Itop_env;
+ U8 Iexit_flags;
+ I32 Istatusvalue;
+ I32 Istatusvalue_posix;
+ GV *Istderrgv;
+ GV *Ierrgv;
+ AV *Ibeginav;
+ AV *Iunitcheckav;
+ COP Icompiling;
+ char Isavebegin;
+ volatile U32 Idebug;
+ AV *Ibeginav_save;
+ AV *Icheckav_save;
+ AV *Iunitcheckav_save;
+};
+
+void S_my_exit_jump (PerlInterpreter *my_perl __attribute__((unused)))
+ __attribute__((noreturn));
+
+int Perl_av_len (PerlInterpreter*, AV*);
+void Perl_av_create_and_push (PerlInterpreter*, AV**, SV*);
+int __sigsetjmp (sigjmp_buf env, int savemask);
+void Perl_sv_2pv_flags (PerlInterpreter*, SV*, STRLEN*, int);
+void Perl_deb (PerlInterpreter*,
+ const char*, const char*, int, const char*, int);
+void Perl_croak (PerlInterpreter*, const char*, void*);
+void foo (void);
+
+void
+Perl_call_list (PerlInterpreter *my_perl __attribute__((unused)),
+ I32 oldscope, AV *paramList)
+{
+ SV *atsv;
+ CV *cv;
+ STRLEN len;
+ int ret;
+ JMPENV cur_env;
+ GV *shplep;
+ volatile line_t oldline;
+
+ oldline = (my_perl->Icurcop) ? my_perl->Icurcop->cop_line : 0;
+
+ while (Perl_av_len (my_perl, paramList) >= 0)
+ {
+ if (my_perl->Isavebegin)
+ {
+ if (paramList == my_perl->Ibeginav)
+ {
+ Perl_av_create_and_push (my_perl, &my_perl->Ibeginav_save,
+ (SV*) cv);
+ Perl_av_create_and_push(my_perl, &my_perl->Icheckav_save,
+ (SV*) cv);
+ }
+ else if (paramList == my_perl->Iunitcheckav)
+ Perl_av_create_and_push(my_perl, &my_perl->Iunitcheckav_save,
+ (SV*) cv);
+ }
+
+ cur_env.je_ret = __sigsetjmp (cur_env.je_buf, 0);
+
+ switch (ret)
+ {
+ case 0:
+ shplep = (GV *) my_perl->Ierrgv;
+ *my_perl->Imarkstack_ptr = my_perl->Istack_sp - my_perl->Istack_base;
+ atsv = shplep->sv_u.svu_gp->gp_sv;
+ if (atsv->sv_flags & 0x00000400 == 0x00000400)
+ len = ((XPV*) ((SV *) atsv)->sv_any)->xpv_cur;
+ else
+ Perl_sv_2pv_flags (my_perl, atsv, &len, 2|32);
+
+ if (len)
+ {
+ my_perl->Icurcop = &my_perl->Icompiling;
+ while (my_perl->Iscopestack_ix > oldscope)
+ {
+ if (my_perl->Idebug & 0x00000004)
+ Perl_deb (my_perl, "scope", "LEAVE",
+ my_perl->Iscopestack_ix, "perl.c", 5166);
+ (my_perl->Itop_env) = cur_env.je_prev;
+ }
+
+ Perl_croak (my_perl, "%""-p""", (void*) atsv);
+ }
+
+ case 1:
+ my_perl->Istatusvalue = 1;
+ my_perl->Istatusvalue_posix = 1;
+ case 2:
+ while (my_perl->Iscopestack_ix > oldscope)
+ if (my_perl->Idebug & 0x00000004)
+ foo ();
+ my_perl->Icurcop = &my_perl->Icompiling;
+ my_perl->Icurcop->cop_line = oldline;
+ if (my_perl->Idebug & 0x00000004)
+ foo ();
+ S_my_exit_jump (my_perl);
+ case 3:
+ if (my_perl->Irestartop)
+ foo ();
+ }
+ }
+}
diff --git a/gcc/testsuite/gcc.target/sh/torture/pr34777.c b/gcc/testsuite/gcc.target/sh/torture/pr34777.c
index b2ec56adff7..de6ba028c87 100644
--- a/gcc/testsuite/gcc.target/sh/torture/pr34777.c
+++ b/gcc/testsuite/gcc.target/sh/torture/pr34777.c
@@ -1,4 +1,4 @@
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-additional-options "-fschedule-insns -fPIC -mprefergot" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*" } { "" } } */
diff --git a/gcc/testsuite/gcc.target/sh/torture/pr58314.c b/gcc/testsuite/gcc.target/sh/torture/pr58314.c
index 61447d84ff9..7a11508405b 100644
--- a/gcc/testsuite/gcc.target/sh/torture/pr58314.c
+++ b/gcc/testsuite/gcc.target/sh/torture/pr58314.c
@@ -1,4 +1,4 @@
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-options "-Os" } */
typedef unsigned short __u16;
diff --git a/gcc/testsuite/gcc.target/sh/torture/pr58475.c b/gcc/testsuite/gcc.target/sh/torture/pr58475.c
new file mode 100644
index 00000000000..f44780d297a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/sh/torture/pr58475.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+
+int
+kerninfo(int __bsx, double tscale)
+{
+ return (
+ (int)(__extension__
+ ({
+ ((((__bsx) & 0xff000000u) >> 24)
+ | (((__bsx) & 0x00ff0000) >> 8)
+ | (((__bsx) & 0x0000ff00) << 8)
+ | (((__bsx) & 0x000000ff) << 24)
+ ); }))
+ * tscale);
+}
diff --git a/gcc/testsuite/gcc.target/sh/torture/pragma-isr.c b/gcc/testsuite/gcc.target/sh/torture/pragma-isr.c
index 3c917bc6577..9e665bafb48 100644
--- a/gcc/testsuite/gcc.target/sh/torture/pragma-isr.c
+++ b/gcc/testsuite/gcc.target/sh/torture/pragma-isr.c
@@ -1,5 +1,5 @@
/* Check whether rte is generated for two ISRs. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*" } { "" } } */
/* { dg-final { scan-assembler-times "rte" 2 } } */
diff --git a/gcc/testsuite/gcc.target/sh/torture/pragma-isr2.c b/gcc/testsuite/gcc.target/sh/torture/pragma-isr2.c
index 89d70084ed9..ce984e73fbd 100644
--- a/gcc/testsuite/gcc.target/sh/torture/pragma-isr2.c
+++ b/gcc/testsuite/gcc.target/sh/torture/pragma-isr2.c
@@ -1,5 +1,5 @@
/* Check whether rte is generated only for an ISRs. */
-/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-do compile } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*" } { "" } } */
/* { dg-final { scan-assembler-times "rte" 1 } } */
diff --git a/gcc/testsuite/gcc.target/vax/pr56875.c b/gcc/testsuite/gcc.target/vax/pr56875.c
new file mode 100644
index 00000000000..f409afe88e7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/pr56875.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+/* { dg-final { scan-assembler "ashq .*,\\\$0xffffffffffffffff," } } */
+/* { dg-final { scan-assembler-not "ashq .*,\\\$-1," } } */
+
+void
+a (void)
+{
+ unsigned long i = 1;
+ unsigned long long v;
+
+ v = ~ (unsigned long long) 0 << i;
+}
diff --git a/gcc/testsuite/gcc.target/vax/vax.exp b/gcc/testsuite/gcc.target/vax/vax.exp
new file mode 100644
index 00000000000..2aec4eec192
--- /dev/null
+++ b/gcc/testsuite/gcc.target/vax/vax.exp
@@ -0,0 +1,41 @@
+# Copyright (C) 2013 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 of the License, 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 GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+# GCC testsuite that uses the `dg.exp' driver.
+
+# Exit immediately if this isn't a VAX target.
+if ![istarget vax-*-*] then {
+ return
+}
+
+# Load support procs.
+load_lib gcc-dg.exp
+
+# If a testcase doesn't have special options, use these.
+global DEFAULT_CFLAGS
+if ![info exists DEFAULT_CFLAGS] then {
+ set DEFAULT_CFLAGS " -ansi -pedantic-errors"
+}
+
+# Initialize `dg'.
+dg-init
+
+# Main loop.
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cS\]]] \
+ "" $DEFAULT_CFLAGS
+
+# All done.
+dg-finish
diff --git a/gcc/testsuite/gfortran.dg/assumed_type_8.f90 b/gcc/testsuite/gfortran.dg/assumed_type_8.f90
new file mode 100644
index 00000000000..543e693bb4b
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/assumed_type_8.f90
@@ -0,0 +1,19 @@
+! { dg-do compile }
+!
+! Issue came up during the review of PR fortran/58793
+!
+! Test for TS29113:2012's C407b.
+!
+program test
+ use iso_c_binding
+ integer,target ::aa
+ call up(c_loc(aa))
+contains
+ subroutine up(x)
+ class(*) :: x
+ end subroutine
+ subroutine bar(x)
+ type(*) :: x
+ call up(x) ! { dg-error "Assumed-type actual argument at .1. requires that dummy argument 'x' is of assumed type" }
+ end subroutine bar
+end program test
diff --git a/gcc/testsuite/gfortran.dg/blockdata_8.f90 b/gcc/testsuite/gfortran.dg/blockdata_8.f90
new file mode 100644
index 00000000000..d3f992564ad
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/blockdata_8.f90
@@ -0,0 +1,48 @@
+! { dg-do compile }
+!
+! PR fortran/44350
+!
+! Fortran 2008, C1116 only permits a small subset of statements in BLOCK DATA
+!
+! Part of the test case was contributed by Vittorio Zecca
+!
+module m
+end module m
+
+BLOCK DATA valid2
+ use m
+ implicit integer(a-z)
+ intrinsic :: sin
+ common /one/ a, c
+ bind(C) :: /one/
+ dimension c(5)
+ parameter (g = 7)
+END BLOCK DATA valid2
+
+BLOCK DATA valid
+ use m
+ implicit none
+ type t
+ sequence
+ end type t
+ type(t), save :: x
+ integer :: y
+ real :: q
+ save :: y
+ dimension :: q(5)
+! class(*) :: zz ! See PR fortran/58857
+! pointer :: zz
+ target :: q
+ volatile y
+ asynchronous q
+END BLOCK DATA valid
+
+block data invalid
+ common x
+ f(x)=x ! { dg-error "STATEMENT FUNCTION statement is not allowed inside of BLOCK DATA" }
+ interface ! { dg-error "INTERFACE statement is not allowed inside of BLOCK DATA" }
+ end interface
+1 format() ! { dg-error "FORMAT statement is not allowed inside of BLOCK DATA" }
+end block invalid ! { dg-error "Expecting END BLOCK DATA statement" }
+
+! { dg-error "Unexpected end of file" "" { target "*-*-*" } 0 }
diff --git a/gcc/testsuite/gfortran.dg/char_length_19.f90 b/gcc/testsuite/gfortran.dg/char_length_19.f90
new file mode 100644
index 00000000000..e52d018b7c3
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/char_length_19.f90
@@ -0,0 +1,44 @@
+! { dg-do compile }
+!
+! PR fortran/58579
+!
+! Contributed by Joost VandeVondele
+!
+! Was ICEing before due to the patch for PR 58593
+!
+ subroutine test
+ CHARACTER(len=20) :: tmpStr
+ CHARACTER(len=20, kind=4) :: tmpStr4
+ INTEGER :: output_unit=6
+ WRITE (UNIT=output_unit,FMT="(T2,A,T61,A20)")&
+ "DFT| Self-interaction correction (SIC)",ADJUSTR(TRIM(tmpstr))
+ WRITE (UNIT=output_unit,FMT="(T2,A,T61,A20)")&
+ 4_"DFT| Self-interaction correction (SIC)",ADJUSTR(TRIM(tmpstr4))
+ END
+
+!
+! PR fortran/58593
+! Contributed by Albert Bartok
+!
+! The PR was overallocating memory. I placed it here to check for a
+! variant of the test case above, which takes a slightly differnt code
+! patch. Thus, its purpose is just to ensure that it won't ICE.
+!
+program test_char
+
+ implicit none
+ integer :: i
+
+ read*, i
+ print*, trim(test(i))
+
+ contains
+
+ function test(i)
+ integer, intent(in) :: i
+ character(len=i) :: test
+
+ test(1:1) = "A"
+ endfunction test
+
+endprogram test_char
diff --git a/gcc/testsuite/gfortran.dg/constructor_9.f90 b/gcc/testsuite/gfortran.dg/constructor_9.f90
new file mode 100644
index 00000000000..5196703031a
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/constructor_9.f90
@@ -0,0 +1,22 @@
+! { dg-do compile }
+! { dg-options "-Wall" }
+!
+! PR 58471: [4.8/4.9 Regression] ICE on invalid with missing type constructor and -Wall
+!
+! Contributed by Andrew Benson <abensonca@gmail.com>
+
+module cf
+ implicit none
+ type :: cfmde
+ end type
+ interface cfmde
+ module procedure mdedc ! { dg-error "is neither function nor subroutine" }
+ end interface
+contains
+ subroutine cfi()
+ type(cfmde), pointer :: cfd
+ cfd=cfmde() ! { dg-error "Can't convert" }
+ end subroutine
+end module
+
+! { dg-final { cleanup-modules "cf" } }
diff --git a/gcc/testsuite/gfortran.dg/defined_assignment_8.f90 b/gcc/testsuite/gfortran.dg/defined_assignment_8.f90
new file mode 100644
index 00000000000..aab808583ad
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/defined_assignment_8.f90
@@ -0,0 +1,40 @@
+! { dg-do compile }
+!
+! PR fortran/58469
+!
+! Related: PR fortran/57697
+!
+! Was ICEing before
+!
+module m0
+ implicit none
+ type :: component
+ integer :: i = 42
+ contains
+ procedure :: assign0
+ generic :: assignment(=) => assign0
+ end type
+ type, extends(component) :: comp2
+ real :: aa
+ end type comp2
+ type parent
+ type(comp2) :: foo
+ end type
+contains
+ elemental subroutine assign0(lhs,rhs)
+ class(component), intent(INout) :: lhs
+ class(component), intent(in) :: rhs
+ lhs%i = 20
+ end subroutine
+end module
+
+program main
+ use m0
+ implicit none
+ type(parent), allocatable :: left
+ type(parent) :: right
+ print *, right%foo
+ left = right
+ print *, left%foo
+ if (left%foo%i /= 42) call abort()
+end
diff --git a/gcc/testsuite/gfortran.dg/defined_assignment_9.f90 b/gcc/testsuite/gfortran.dg/defined_assignment_9.f90
new file mode 100644
index 00000000000..50fa0070f18
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/defined_assignment_9.f90
@@ -0,0 +1,45 @@
+! { dg-do run }
+!
+! PR fortran/57697
+!
+! Further test of typebound defined assignment
+!
+module m0
+ implicit none
+ type component
+ integer :: i = 42
+ contains
+ procedure :: assign0
+ generic :: assignment(=) => assign0
+ end type
+ type parent
+ type(component) :: foo
+ end type
+contains
+ elemental subroutine assign0(lhs,rhs)
+ class(component), intent(INout) :: lhs
+ class(component), intent(in) :: rhs
+ lhs%i = 20
+ end subroutine
+end module
+
+program main
+ use m0
+ implicit none
+ block
+ type(parent), allocatable :: left
+ type(parent) :: right
+! print *, right%foo
+ left = right
+! print *, left%foo
+ if (left%foo%i /= 20) call abort()
+ end block
+ block
+ type(parent), allocatable :: left(:)
+ type(parent) :: right(5)
+! print *, right%foo
+ left = right
+! print *, left%foo
+ if (any (left%foo%i /= 20)) call abort()
+ end block
+end
diff --git a/gcc/testsuite/gfortran.dg/derived_external_function_1.f90 b/gcc/testsuite/gfortran.dg/derived_external_function_1.f90
new file mode 100644
index 00000000000..7421c4c0f22
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/derived_external_function_1.f90
@@ -0,0 +1,27 @@
+! { dg-do run }
+!
+! PR fortran/58771
+!
+! Contributed by Vittorio Secca <zeccav@gmail.com>
+!
+! ICEd on the write statement with f() because the derived type backend
+! declaration not built.
+!
+module m
+ type t
+ integer(4) g
+ end type
+end
+
+type(t) function f() result(ff)
+ use m
+ ff%g = 42
+end
+
+ use m
+ character (20) :: line1, line2
+ type(t) f
+ write (line1, *) f()
+ write (line2, *) 42_4
+ if (line1 .ne. line2) call abort
+end
diff --git a/gcc/testsuite/gfortran.dg/extends_15.f90 b/gcc/testsuite/gfortran.dg/extends_15.f90
new file mode 100644
index 00000000000..06c31799a00
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/extends_15.f90
@@ -0,0 +1,16 @@
+! { dg-do compile }
+!
+! PR 58355: [4.7/4.8/4.9 Regression] [F03] ICE with TYPE, EXTENDS before parent TYPE defined
+!
+! Contributed by Andrew Benson <abensonca@gmail.com>
+
+module ct
+ public :: t1
+
+ type, extends(t1) :: t2 ! { dg-error "has not been previously defined" }
+
+ type :: t1
+ end type
+end
+
+! { dg-final { cleanup-modules "ct" } }
diff --git a/gcc/testsuite/gfortran.dg/finalize_21.f90 b/gcc/testsuite/gfortran.dg/finalize_21.f90
new file mode 100644
index 00000000000..6f6ede3e46a
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/finalize_21.f90
@@ -0,0 +1,12 @@
+! { dg-do compile }
+! { dg-options "-fdump-tree-original" }
+!
+! PR fortran/58436
+!
+! The following was ICEing and lacking _final=0
+!
+class(*), allocatable :: var
+end
+
+! { dg-final { scan-tree-dump "static struct __vtype__STAR __vtab__STAR = {._hash=0, ._size=., ._extends=0B, ._def_init=0B, ._copy=0B, ._final=0B};" "original" } }
+! { dg-final { cleanup-tree-dump "original" } }
diff --git a/gcc/testsuite/gfortran.dg/gomp/appendix-a/a.35.5.f90 b/gcc/testsuite/gfortran.dg/gomp/appendix-a/a.35.5.f90
index 083c0b3b723..a580a3baf66 100644
--- a/gcc/testsuite/gfortran.dg/gomp/appendix-a/a.35.5.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/appendix-a/a.35.5.f90
@@ -6,7 +6,7 @@
!$OMP CRITICAL
CALL WORK(N,1)
! incorrect nesting of barrier region in a critical region
-!$OMP BARRIER
+!$OMP BARRIER ! { dg-error "region may not be closely nested inside of" }
CALL WORK(N,2)
!$OMP END CRITICAL
!$OMP END PARALLEL
diff --git a/gcc/testsuite/gfortran.dg/ldist-pr45199.f b/gcc/testsuite/gfortran.dg/ldist-pr45199.f
index 22b202e07e6..e01d32f2664 100644
--- a/gcc/testsuite/gfortran.dg/ldist-pr45199.f
+++ b/gcc/testsuite/gfortran.dg/ldist-pr45199.f
@@ -22,6 +22,6 @@
! GCC should apply memset zero loop distribution and it should not ICE.
-! { dg-final { scan-tree-dump "distributed: split to 9 loops" "ldist" } }
+! { dg-final { scan-tree-dump "distributed: split to 0 loops and 9 library calls" "ldist" } }
! { dg-final { scan-tree-dump-times "generated memset zero" 9 "ldist" } }
! { dg-final { cleanup-tree-dump "ldist" } }
diff --git a/gcc/testsuite/gfortran.dg/openmp-define-1.f90 b/gcc/testsuite/gfortran.dg/openmp-define-1.f90
new file mode 100644
index 00000000000..4e1c076f305
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/openmp-define-1.f90
@@ -0,0 +1,7 @@
+! { dg-options "-cpp" }
+! { dg-do preprocess }
+! { dg-require-effective-target fopenmp }
+
+#ifdef _OPENMP
+# error _OPENMP defined
+#endif
diff --git a/gcc/testsuite/gfortran.dg/openmp-define-2.f90 b/gcc/testsuite/gfortran.dg/openmp-define-2.f90
new file mode 100644
index 00000000000..cd167eabd89
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/openmp-define-2.f90
@@ -0,0 +1,7 @@
+! { dg-options "-cpp -fno-openmp" }
+! { dg-do preprocess }
+! { dg-require-effective-target fopenmp }
+
+#ifdef _OPENMP
+# error _OPENMP defined
+#endif
diff --git a/gcc/testsuite/gfortran.dg/openmp-define-3.f90 b/gcc/testsuite/gfortran.dg/openmp-define-3.f90
new file mode 100644
index 00000000000..3d559864faf
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/openmp-define-3.f90
@@ -0,0 +1,11 @@
+! { dg-options "-cpp -fopenmp" }
+! { dg-do preprocess }
+! { dg-require-effective-target fopenmp }
+
+#ifndef _OPENMP
+# error _OPENMP not defined
+#endif
+
+#if _OPENMP != 201107
+# error _OPENMP defined to wrong value
+#endif
diff --git a/gcc/testsuite/gfortran.dg/optional_class_1.f90 b/gcc/testsuite/gfortran.dg/optional_class_1.f90
new file mode 100644
index 00000000000..589fc6023e7
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/optional_class_1.f90
@@ -0,0 +1,45 @@
+! { dg-do run }
+!
+! PR fortran/57445
+!
+! Contributed by Tobias Burnus <burnus@gcc.gnu.org>
+!
+! Spurious assert was added at revision 192495
+!
+module m
+ implicit none
+ type t
+ integer :: i
+ end type t
+contains
+ subroutine opt(xa, xc, xaa, xca)
+ type(t), allocatable, intent(out), optional :: xa
+ class(t), allocatable, intent(out), optional :: xc
+ type(t), allocatable, intent(out), optional :: xaa(:)
+ class(t), allocatable, intent(out), optional :: xca(:)
+ if (present (xca)) call foo_opt(xca=xca)
+ end subroutine opt
+ subroutine foo_opt(xa, xc, xaa, xca)
+ type(t), allocatable, intent(out), optional :: xa
+ class(t), allocatable, intent(out), optional :: xc
+ type(t), allocatable, intent(out), optional :: xaa(:)
+ class(t), allocatable, intent(out), optional :: xca(:)
+ if (present (xca)) then
+ if (allocated (xca)) deallocate (xca)
+ allocate (xca(3), source = [t(9),t(99),t(999)])
+ end if
+ end subroutine foo_opt
+end module m
+ use m
+ class(t), allocatable :: xca(:)
+ allocate (xca(1), source = t(42))
+ select type (xca)
+ type is (t)
+ if (any (xca%i .ne. [42])) call abort
+ end select
+ call opt (xca = xca)
+ select type (xca)
+ type is (t)
+ if (any (xca%i .ne. [9,99,999])) call abort
+ end select
+end
diff --git a/gcc/testsuite/gfortran.dg/pr58484.f b/gcc/testsuite/gfortran.dg/pr58484.f
new file mode 100644
index 00000000000..2fd791347e9
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr58484.f
@@ -0,0 +1,15 @@
+! { dg-do compile }
+! { dg-options "-O2" }
+ SUBROUTINE UMPSE(AIBJ,NOC,NDIM,NOCA,NVIRA,NOCCA,E2)
+ DIMENSION AIBJ(NOC,NDIM,*)
+ DO 20 MA=1,NVIRA
+ DO 20 MI=1,NOCA
+ DO 10 MB=1,MA
+ MBI = MI+NOCA*(MB-1)
+ DO 10 MJ=1,NOCCA
+ DUM = AIBJ(MJ,MAI,MB)-AIBJ(MJ,MBI,MA)
+ E2A = E2A-DUM
+ 10 CONTINUE
+ 20 CONTINUE
+ E2 = E2+E2A
+ END
diff --git a/gcc/testsuite/gfortran.dg/pr58968.f b/gcc/testsuite/gfortran.dg/pr58968.f
new file mode 100644
index 00000000000..db06d50fa27
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr58968.f
@@ -0,0 +1,96 @@
+C PR rtl-optimization/58968.f
+C { dg-do compile { target powerpc*-*-*} }
+C { dg-options "-mcpu=power7 -O3 -w -ffast-math -funroll-loops" }
+ SUBROUTINE MAKTABS(IW,SOME,LBOX1,LBOX2,LBOX3,NSPACE,NA,NB,
+ * LBST,X,
+ * NX,IAMA,IAMI,IBMA,IBMI,MNUM,IDIM,MSTA,IBO,
+ * IDSYM,ISYM1,NSYM,
+ * NACT,LWRK,KTAB,LGMUL,
+ * LCON,LCOA,LCOB,
+ * LANDET,LBNDET,NAST,NBST,LSYMA,LSYMB,LGCOM,
+ * MINI,MAXI,LSPA,LSPB,LDISB,
+ * LSAS,LSBS,LSAC,LSBC,
+ * ITGA,ITGB,IAST,IBST,NCI,NA1EX,NB1EX,FDIRCT)
+ IMPLICIT DOUBLE PRECISION(A-H,O-Z)
+ LOGICAL SOME
+ DIMENSION LBOX1(NSPACE),LBOX2(NSPACE),LBOX3(NSPACE),LBST(NSPACE)
+ DIMENSION X(NX)
+ DIMENSION IAMA(NSPACE),IAMI(NSPACE),IBMA(NSPACE),IBMI(NSPACE)
+ DIMENSION MNUM(NSPACE),IDIM(NSPACE),MSTA(NSPACE+1),IBO(NACT)
+ DIMENSION LWRK(43),KTAB(NSYM),LGMUL(NSYM,NSYM)
+ DIMENSION LCON(NA)
+ DIMENSION LCOA(NSYM,ITGA),LCOB(NSYM,ITGB)
+ DIMENSION LANDET(NSPACE,ITGA),LBNDET(NSPACE,ITGB)
+ DIMENSION NAST(ITGA+1),NBST(ITGB+1)
+ DIMENSION LSYMA(IAST),LSYMB(IBST)
+ DIMENSION LGCOM(ITGB,ITGA)
+ DIMENSION MINI(NSPACE),MAXI(NSPACE)
+ DIMENSION LSPA(IAST),LSPB(IBST)
+ DIMENSION LDISB(NSYM,ITGB,ITGA)
+ DIMENSION LSAS(NSYM+1,ITGA),LSBS(NSYM+1,ITGB)
+ DIMENSION LSAC(IAST),LSBC(IBST)
+ LOGICAL FDIRCT
+ LCOA = 0
+ LCOB = 0
+ ISTA1 = LBST(1)
+ CALL RESETCO(LBOX1,NSPACE,NB,IBMA,IBMI,LBOX2)
+ NAST(1) = 0
+ NBST(1) = 0
+ DO II=1,ITGA
+ ITOT = 1
+ DO JJ=1,NSPACE
+ ITOT = ITOT * LANDET(JJ,II)
+ ENDDO
+ NAST(II+1) = NAST(II) + ITOT
+ ENDDO
+ DO II=1,ITGB
+ ITOT = 1
+ DO JJ=1,NSPACE
+ ITOT = ITOT * LBNDET(JJ,II)
+ ENDDO
+ NBST(II+1) = NBST(II) + ITOT
+ ENDDO
+ ICOMP = 0
+ CALL RESETCO(LBOX1,NSPACE,NA,IAMA,IAMI,LBOX3)
+ NA1EX = 0
+ NB1EX = 0
+ CALL RESETCO(LBOX1,NSPACE,NB,IBMA,IBMI,LBOX3)
+ DO IIB = 1,ITGB
+ CALL RESETDE(LBOX1,NSPACE,NB,MSTA,LCON)
+ DO KKB=NBST(IIB)+1,NBST(IIB+1)
+ DO II=1,NSPACE
+ LBOX2(II) = LBOX1(II)
+ ENDDO
+ IEBS = NB+1
+ DO ISPB1=NSPACE,1,-1
+ IOC1 = LBOX1(ISPB1)
+ IEBE = IEBS - 1
+ IEBS = IEBS - IOC1
+ LBOX2(ISPB1) = LBOX2(ISPB1)-1
+ DO IB1=IEBE,IEBS,-1
+ IO1 = LCON(IB1)
+ IGBE = IEBE - LBOX1(ISPB1)
+ DO ISPB2=ISPB1,NSPACE
+ IGBS = IGBE + 1
+ IGBE = IGBE + LBOX1(ISPB2)
+ LBOX2(ISPB2) = LBOX2(ISPB2) + 1
+ IGBA = MAX(IB1+1,IGBS)
+ DO IGAP=IGBA,IGBE+1
+ DO JJ=ISTA,IEND
+ NB1EX = NB1EX + 1
+ ENDDO
+ ISTA = LCON(IGAP)+1
+ IEND = LCON(IGAP+1)-1
+ IF (IGAP.EQ.IGBE) IEND=MSTA(ISPB2+1)-1
+ ENDDO
+ LBOX2(ISPB2) = LBOX2(ISPB2) - 1
+ ENDDO
+ ENDDO
+ LBOX2(ISPB1) = LBOX2(ISPB1) + 1
+ ENDDO
+ CALL MOVEUP2(LBOX1,NSPACE,NB,MSTA,LCON)
+ ENDDO
+ CALL PUSHCO(LBOX1,NSPACE,NB,IBMA,IBMI,LBOX3,IEND)
+ ENDDO
+ RETURN
+ END
diff --git a/gcc/testsuite/gfortran.dg/proc_ptr_comp_38.f90 b/gcc/testsuite/gfortran.dg/proc_ptr_comp_38.f90
new file mode 100644
index 00000000000..2a71ca052cd
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/proc_ptr_comp_38.f90
@@ -0,0 +1,12 @@
+! { dg-do compile }
+!
+! PR fortran/58803
+!
+! Contributed by Vittorio Zecca
+!
+! Was before ICEing due to a double free
+!
+ type t
+ procedure(real), pointer, nopass :: f1, f2
+ end type
+ end
diff --git a/gcc/testsuite/gfortran.dg/reshape_6.f90 b/gcc/testsuite/gfortran.dg/reshape_6.f90
new file mode 100644
index 00000000000..149f31efe7a
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/reshape_6.f90
@@ -0,0 +1,19 @@
+! { dg-do compile }
+! PR fortran/58989
+!
+program test
+
+ real(8), dimension(4,4) :: fluxes
+ real(8), dimension(2,2,2,2) :: f
+ integer, dimension(3) :: dmmy
+ integer, parameter :: indx(4)=(/2,2,2,2/)
+
+ fluxes = 1
+
+ dmmy = (/2,2,2/)
+
+ f = reshape(fluxes,(/dmmy,2/)) ! Caused an ICE
+ f = reshape(fluxes,(/2,2,2,2/)) ! Works as expected
+ f = reshape(fluxes,indx) ! Works as expected
+
+end program test
diff --git a/gcc/testsuite/gfortran.dg/round_4.f90 b/gcc/testsuite/gfortran.dg/round_4.f90
index 8a7d95bb456..093d04ea796 100644
--- a/gcc/testsuite/gfortran.dg/round_4.f90
+++ b/gcc/testsuite/gfortran.dg/round_4.f90
@@ -6,12 +6,18 @@
! Test whether I/O rounding works. Uses internally (libgfortran) strtod
! for the conversion - and sets the CPU rounding mode accordingly.
!
+! Only few strtod implementations currently support rounding. Therefore
+! we use a heuristic to determine if the rounding support is available.
+! The assumption is that if strtod gives *different* results for up/down
+! rounding, then it will give *correct* results for nearest/zero/up/down
+! rounding too. And that is what is effectively checked.
+!
! If it doesn't work on your system, please check whether strtod handles
-! rounding and whether your system is supported in libgfortran/config/fpu*.c
+! rounding correctly and whether your system is supported in
+! libgfortran/config/fpu*.c
!
! Please only add ... run { target { ! { triplets } } } if it is unfixable
-! on your target - and a note why (strtod doesn't handle it, no rounding
-! support, etc.)
+! on your target - and a note why (strtod has broken rounding support, etc.)
!
program main
use iso_fortran_env
@@ -27,6 +33,17 @@ program main
real(xp) :: r10p, r10m, ref10u, ref10d
real(qp) :: r16p, r16m, ref16u, ref16d
character(len=20) :: str, round
+ logical :: rnd4, rnd8, rnd10, rnd16
+
+ ! Test for which types glibc's strtod function supports rounding
+ str = '0.01 0.01 0.01 0.01'
+ read (str, *, round='up') r4p, r8p, r10p, r16p
+ read (str, *, round='down') r4m, r8m, r10m, r16m
+ rnd4 = r4p /= r4m
+ rnd8 = r8p /= r8m
+ rnd10 = r10p /= r10m
+ rnd16 = r16p /= r16m
+! write (*, *) rnd4, rnd8, rnd10, rnd16
ref4u = 0.100000001_4
ref8u = 0.10000000000000001_8
@@ -55,40 +72,40 @@ program main
round = 'up'
call t()
- if (r4p /= ref4u .or. r4m /= -ref4d) call abort()
- if (r8p /= ref8u .or. r8m /= -ref8d) call abort()
- if (r10p /= ref10u .or. r10m /= -ref10d) call abort()
- if (r16p /= ref16u .or. r16m /= -ref16d) call abort()
+ if (rnd4 .and. (r4p /= ref4u .or. r4m /= -ref4d)) call abort()
+ if (rnd8 .and. (r8p /= ref8u .or. r8m /= -ref8d)) call abort()
+ if (rnd10 .and. (r10p /= ref10u .or. r10m /= -ref10d)) call abort()
+ if (rnd16 .and. (r16p /= ref16u .or. r16m /= -ref16d)) call abort()
round = 'down'
call t()
- if (r4p /= ref4d .or. r4m /= -ref4u) call abort()
- if (r8p /= ref8d .or. r8m /= -ref8u) call abort()
- if (r10p /= ref10d .or. r10m /= -ref10u) call abort()
- if (r16p /= ref16d .or. r16m /= -ref16u) call abort()
+ if (rnd4 .and. (r4p /= ref4d .or. r4m /= -ref4u)) call abort()
+ if (rnd8 .and. (r8p /= ref8d .or. r8m /= -ref8u)) call abort()
+ if (rnd10 .and. (r10p /= ref10d .or. r10m /= -ref10u)) call abort()
+ if (rnd16 .and. (r16p /= ref16d .or. r16m /= -ref16u)) call abort()
round = 'zero'
call t()
- if (r4p /= ref4d .or. r4m /= -ref4d) call abort()
- if (r8p /= ref8d .or. r8m /= -ref8d) call abort()
- if (r10p /= ref10d .or. r10m /= -ref10d) call abort()
- if (r16p /= ref16d .or. r16m /= -ref16d) call abort()
+ if (rnd4 .and. (r4p /= ref4d .or. r4m /= -ref4d)) call abort()
+ if (rnd8 .and. (r8p /= ref8d .or. r8m /= -ref8d)) call abort()
+ if (rnd10 .and. (r10p /= ref10d .or. r10m /= -ref10d)) call abort()
+ if (rnd16 .and. (r16p /= ref16d .or. r16m /= -ref16d)) call abort()
round = 'nearest'
call t()
- if (r4p /= ref4u .or. r4m /= -ref4u) call abort()
- if (r8p /= ref8u .or. r8m /= -ref8u) call abort()
- if (r10p /= ref10u .or. r10m /= -ref10u) call abort()
- if (r16p /= ref16u .or. r16m /= -ref16u) call abort()
+ if (rnd4 .and. (r4p /= ref4u .or. r4m /= -ref4u)) call abort()
+ if (rnd8 .and. (r8p /= ref8u .or. r8m /= -ref8u)) call abort()
+ if (rnd10 .and. (r10p /= ref10u .or. r10m /= -ref10u)) call abort()
+ if (rnd16 .and. (r16p /= ref16u .or. r16m /= -ref16u)) call abort()
! Same as nearest (but rounding towards zero if there is a tie
! [does not apply here])
round = 'compatible'
call t()
- if (r4p /= ref4u .or. r4m /= -ref4u) call abort()
- if (r8p /= ref8u .or. r8m /= -ref8u) call abort()
- if (r10p /= ref10u .or. r10m /= -ref10u) call abort()
- if (r16p /= ref16u .or. r16m /= -ref16u) call abort()
+ if (rnd4 .and. (r4p /= ref4u .or. r4m /= -ref4u)) call abort()
+ if (rnd8 .and. (r8p /= ref8u .or. r8m /= -ref8u)) call abort()
+ if (rnd10 .and. (r10p /= ref10u .or. r10m /= -ref10u)) call abort()
+ if (rnd16 .and. (r16p /= ref16u .or. r16m /= -ref16u)) call abort()
contains
subroutine t()
! print *, round
diff --git a/gcc/testsuite/gfortran.dg/unlimited_polymorphic_10.f90 b/gcc/testsuite/gfortran.dg/unlimited_polymorphic_10.f90
new file mode 100644
index 00000000000..04518d6c941
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/unlimited_polymorphic_10.f90
@@ -0,0 +1,10 @@
+! { dg-do compile }
+!
+! PR fortran/58658
+!
+! Contributed by Vladimír Fuka
+!
+subroutine sub(a)
+ class(*),allocatable :: a
+ a => null() ! { dg-error "Non-POINTER in pointer association context \\(pointer assignment\\)" }
+end subroutine
diff --git a/gcc/testsuite/gfortran.dg/unlimited_polymorphic_11.f90 b/gcc/testsuite/gfortran.dg/unlimited_polymorphic_11.f90
new file mode 100644
index 00000000000..5b73b3281d5
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/unlimited_polymorphic_11.f90
@@ -0,0 +1,14 @@
+! { dg-do compile }
+! { dg-options "-fdump-tree-original" }
+!
+! PR fortran/58652
+!
+! Contributed by Vladimir Fuka
+!
+ class(*),allocatable :: a
+ class(*),allocatable :: c
+ call move_alloc(a,c)
+end
+
+! { dg-final { scan-tree-dump "\\(struct __vtype__STAR \\*\\) c._vptr = \\(struct __vtype__STAR \\*\\) a._vptr;" "original" } }
+! { dg-final { cleanup-tree-dump "original" } }
diff --git a/gcc/testsuite/gfortran.dg/unlimited_polymorphic_12.f90 b/gcc/testsuite/gfortran.dg/unlimited_polymorphic_12.f90
new file mode 100644
index 00000000000..c583c6bbf5e
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/unlimited_polymorphic_12.f90
@@ -0,0 +1,44 @@
+! { dg-do compile }
+!
+! PR fortran/58652
+!
+! Contributed by Vladimir Fuka
+!
+! The passing of a CLASS(*) to a CLASS(*) was reject before
+!
+module gen_lists
+ type list_node
+ class(*),allocatable :: item
+ contains
+ procedure :: move_alloc => list_move_alloc
+ end type
+
+ contains
+
+ subroutine list_move_alloc(self,item)
+ class(list_node),intent(inout) :: self
+ class(*),intent(inout),allocatable :: item
+
+ call move_alloc(item, self%item)
+ end subroutine
+end module
+
+module lists
+ use gen_lists, only: node => list_node
+end module lists
+
+
+module sexp
+ use lists
+contains
+ subroutine parse(ast)
+ class(*), allocatable, intent(out) :: ast
+ class(*), allocatable :: expr
+ integer :: ierr
+ allocate(node::ast)
+ select type (ast)
+ type is (node)
+ call ast%move_alloc(expr)
+ end select
+ end subroutine
+end module
diff --git a/gcc/testsuite/gfortran.dg/unlimited_polymorphic_13.f90 b/gcc/testsuite/gfortran.dg/unlimited_polymorphic_13.f90
new file mode 100644
index 00000000000..0e27b172fb8
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/unlimited_polymorphic_13.f90
@@ -0,0 +1,67 @@
+! { dg-do run }
+!
+! PR fortran/58793
+!
+! Contributed by Vladimir Fuka
+!
+! Had the wrong value for the storage_size for complex
+!
+module m
+ use iso_fortran_env
+ implicit none
+ integer, parameter :: c1 = real_kinds(1)
+ integer, parameter :: c2 = real_kinds(2)
+ integer, parameter :: c3 = real_kinds(size(real_kinds)-1)
+ integer, parameter :: c4 = real_kinds(size(real_kinds))
+ real(c1) :: r1
+ real(c2) :: r2
+ real(c3) :: r3
+ real(c4) :: r4
+contains
+ subroutine s(o, k)
+ class(*) :: o
+ integer :: k
+ integer :: sz
+
+ select case (k)
+ case (4)
+ sz = storage_size(r1)*2
+ case (8)
+ sz = storage_size(r2)*2
+ case (10)
+ sz = storage_size(r3)*2
+ case (16)
+ sz = storage_size(r4)*2
+ case default
+ call abort()
+ end select
+
+ if (storage_size(o) /= sz) call abort()
+
+! Break up the SELECT TYPE to pre-empt collisions in the value of 'cn'
+ select type (o)
+ type is (complex(c1))
+ if (storage_size(o) /= sz) call abort()
+ end select
+ select type (o)
+ type is (complex(c2))
+ if (storage_size(o) /= sz) call abort()
+ end select
+ select type (o)
+ type is (complex(c3))
+ if (storage_size(o) /= sz) call abort()
+ end select
+ select type (o)
+ type is (complex(c4))
+ if (storage_size(o) /= sz) call abort()
+ end select
+ end subroutine s
+end module m
+
+program p
+ use m
+ call s((1._c1, 2._c1), c1)
+ call s((1._c2, 2._c2), c2)
+ call s((1._c3, 2._c3), c3)
+ call s((1._c4, 2._c4), c4)
+end program p
diff --git a/gcc/testsuite/gfortran.dg/unlimited_polymorphic_14.f90 b/gcc/testsuite/gfortran.dg/unlimited_polymorphic_14.f90
new file mode 100644
index 00000000000..215b03f64ee
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/unlimited_polymorphic_14.f90
@@ -0,0 +1,26 @@
+! { dg-do run }
+!
+! Uncovered in fixing PR fortran/58793
+!
+! Contributed by Tobias Burnus <burnus@gcc.gnu.org>
+!
+! Barfed on the hollerith argument
+!
+program test
+ logical l
+ call up("abc", l)
+ if (l) call abort
+ call up(3habc, l) ! { dg-warning "Legacy Extension" }
+ if (.not. l) call abort
+contains
+ subroutine up(x, l)
+ class(*) :: x
+ logical l
+ select type(x)
+ type is (character(*))
+ l = .false.
+ class default
+ l = .true.
+ end select
+ end subroutine
+end program test
diff --git a/gcc/testsuite/gfortran.dg/vect/vect-do-concurrent-1.f90 b/gcc/testsuite/gfortran.dg/vect/vect-do-concurrent-1.f90
new file mode 100644
index 00000000000..287dfe1d177
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/vect/vect-do-concurrent-1.f90
@@ -0,0 +1,17 @@
+! { dg-do compile }
+! { dg-require-effective-target vect_float }
+! { dg-additional-options "-O3 -fopt-info-vec-optimized" }
+
+subroutine test(n, a, b, c)
+ integer, value :: n
+ real, contiguous, pointer :: a(:), b(:), c(:)
+ integer :: i
+ do concurrent (i = 1:n)
+ a(i) = b(i) + c(i)
+ end do
+end subroutine test
+
+! { dg-message "loop vectorized" "" { target *-*-* } 0 }
+! { dg-bogus " version" "" { target *-*-* } 0 }
+! { dg-bogus " alias" "" { target *-*-* } 0 }
+! { dg-final { cleanup-tree-dump "vect" } }
diff --git a/gcc/testsuite/gfortran.dg/vect/vect.exp b/gcc/testsuite/gfortran.dg/vect/vect.exp
index daa81c87801..2d593cee35c 100644
--- a/gcc/testsuite/gfortran.dg/vect/vect.exp
+++ b/gcc/testsuite/gfortran.dg/vect/vect.exp
@@ -25,7 +25,7 @@ global DEFAULT_VECTCFLAGS
set DEFAULT_VECTCFLAGS ""
# These flags are used for all targets.
-lappend DEFAULT_VECTCFLAGS "-O2" "-ftree-vectorize" "-fno-vect-cost-model" \
+lappend DEFAULT_VECTCFLAGS "-O2" "-ftree-vectorize" "-fvect-cost-model=unlimited" \
"-fdump-tree-vect-details"
# If the target system supports vector instructions, the default action
@@ -68,7 +68,7 @@ dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/fast-math-real8*.\[fF\]{,90,
# -fvect-cost-model tests
set DEFAULT_VECTCFLAGS $SAVED_DEFAULT_VECTCFLAGS
-lappend DEFAULT_VECTCFLAGS "-fvect-cost-model"
+lappend DEFAULT_VECTCFLAGS "-fvect-cost-model=dynamic"
dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/cost-model-*.\[fF\]{,90,95,03,08} ]] \
"" $DEFAULT_VECTCFLAGS
diff --git a/gcc/testsuite/gfortran.dg/wdate-time.F90 b/gcc/testsuite/gfortran.dg/wdate-time.F90
new file mode 100644
index 00000000000..d84fd9abd73
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/wdate-time.F90
@@ -0,0 +1,6 @@
+! { dg-do compile }
+! { dg-options "-Wdate-time" }
+print *, __TIMESTAMP__ ! { dg-warning "might prevent reproducible builds" }
+print *, __TIME__ ! { dg-warning "might prevent reproducible builds" }
+print *, __DATE__ ! { dg-warning "might prevent reproducible builds" }
+end
diff --git a/gcc/testsuite/gnat.dg/opt28.adb b/gcc/testsuite/gnat.dg/opt28.adb
new file mode 100644
index 00000000000..74a4c5c3be9
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/opt28.adb
@@ -0,0 +1,31 @@
+with Opt28_Pkg; use Opt28_Pkg;
+
+package body Opt28 is
+
+ function Full_Filename (Filename : String) return String is
+ Path : constant String := "PATH";
+ Posix_Path : constant Posix_String := To_Posix (Path);
+ begin
+
+ declare
+ M : constant Posix_String := Value_Of (Posix_Path);
+ N : constant Posix_String (1 .. M'Length) := M;
+ Var : constant String := To_String (Str => N);
+ Start_Pos : Natural := 1;
+ End_Pos : Natural := 1;
+ begin
+ while Start_Pos <= Var'Length loop
+ End_Pos := Position (Var (Start_Pos .. Var'Length));
+
+ if Is_File (To_Posix (Var (Start_Pos .. End_Pos - 1) & Filename)) then
+ return Var (Start_Pos .. End_Pos - 1) & Filename;
+ else
+ Start_Pos := End_Pos + 1;
+ end if;
+ end loop;
+ end;
+
+ return "";
+ end;
+
+end Opt28;
diff --git a/gcc/testsuite/gnat.dg/opt28.ads b/gcc/testsuite/gnat.dg/opt28.ads
new file mode 100644
index 00000000000..4887c214845
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/opt28.ads
@@ -0,0 +1,8 @@
+-- { dg-do compile }
+-- { dg-options "-O2" }
+
+package Opt28 is
+
+ function Full_Filename (Filename : String) return String;
+
+end Opt28;
diff --git a/gcc/testsuite/gnat.dg/opt28_pkg.ads b/gcc/testsuite/gnat.dg/opt28_pkg.ads
new file mode 100644
index 00000000000..c3c32fe1c34
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/opt28_pkg.ads
@@ -0,0 +1,11 @@
+package Opt28_Pkg is
+
+ type Posix_String is array (Positive range <>) of aliased Character;
+
+ function To_Posix (Str : String) return Posix_String;
+ function To_String (Str : Posix_String) return String;
+ function Is_File (Str : Posix_String) return Boolean;
+ function Value_Of (Name : Posix_String) return Posix_String;
+ function Position (In_Line : String) return Natural;
+
+end Opt28_Pkg;
diff --git a/gcc/testsuite/gnat.dg/specs/linker_alias.ads b/gcc/testsuite/gnat.dg/specs/linker_alias.ads
index 0f7980eb54f..a4867fd6955 100644
--- a/gcc/testsuite/gnat.dg/specs/linker_alias.ads
+++ b/gcc/testsuite/gnat.dg/specs/linker_alias.ads
@@ -1,5 +1,5 @@
-- { dg-do compile }
--- { dg-skip-if "missing alias support" { *-*-darwin* } }
+-- { dg-skip-if "missing alias support" { *-*-darwin* hppa*-*-hpux* } }
package Linker_Alias is
diff --git a/gcc/testsuite/gnat.dg/specs/linker_section.ads b/gcc/testsuite/gnat.dg/specs/linker_section.ads
index 73e89aa48e1..376bd751a71 100644
--- a/gcc/testsuite/gnat.dg/specs/linker_section.ads
+++ b/gcc/testsuite/gnat.dg/specs/linker_section.ads
@@ -3,7 +3,7 @@ package Linker_Section is
pragma Linker_Section (Entity => Data1,
Section => ".eeprom");
type EEPROM_String is new String;
- pragma Linker_Section (Entity => EEPROM_String, -- { dg-error "objects" }
+ pragma Linker_Section (Entity => EEPROM_String,
Section => ".eeprom");
Data2 : constant EEPROM_String := "12345678901234567";
package Inner is end;
diff --git a/gcc/testsuite/gnat.dg/specs/opt1.ads b/gcc/testsuite/gnat.dg/specs/opt1.ads
new file mode 100644
index 00000000000..89a405c3457
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/specs/opt1.ads
@@ -0,0 +1,28 @@
+-- { dg-do compile }
+-- { dg-options "-O2" }
+
+with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
+
+package Opt1 is
+
+ type Ptr is access all Integer;
+
+ type R1 is record
+ I1 : Integer;
+ I2 : Integer := 0;
+ I3 : Integer;
+ end record;
+
+ type R2 is record
+ P : Ptr;
+ F1 : R1;
+ end record;
+
+ type R3 is record
+ S : Unbounded_String;
+ F1 : R2;
+ I : Integer := 0;
+ F2 : R2;
+ end record;
+
+end Opt1;
diff --git a/gcc/testsuite/gnat.dg/uninit_array.adb b/gcc/testsuite/gnat.dg/uninit_array.adb
new file mode 100644
index 00000000000..910bdaf431a
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/uninit_array.adb
@@ -0,0 +1,22 @@
+-- { dg-do compile }
+-- { dg-options "-gnatws" }
+
+with Uninit_Array_Pkg; use Uninit_Array_Pkg;
+
+package body Uninit_Array is
+
+ function F1 return Integer;
+ pragma Inline_Always (F1);
+
+ function F1 return Integer is
+ Var : Arr;
+ begin
+ return F (Var(Var'First(1)));
+ end;
+
+ function F2 return Integer is
+ begin
+ return F1;
+ end;
+
+end Uninit_Array;
diff --git a/gcc/testsuite/gnat.dg/uninit_array.ads b/gcc/testsuite/gnat.dg/uninit_array.ads
new file mode 100644
index 00000000000..72452213e02
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/uninit_array.ads
@@ -0,0 +1,5 @@
+package Uninit_Array is
+
+ function F2 return Integer;
+
+end Uninit_Array;
diff --git a/gcc/testsuite/gnat.dg/uninit_array_pkg.ads b/gcc/testsuite/gnat.dg/uninit_array_pkg.ads
new file mode 100644
index 00000000000..566632a270d
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/uninit_array_pkg.ads
@@ -0,0 +1,11 @@
+package Uninit_Array_Pkg Is
+
+ type Rec is record
+ B1, B2, B3, B4: Boolean;
+ end record;
+
+ type Arr is array (Boolean) of Rec;
+
+ function F (R : Rec) return Integer;
+
+end Uninit_Array_Pkg;
diff --git a/gcc/testsuite/go.test/go-test.exp b/gcc/testsuite/go.test/go-test.exp
index 6f397343e0f..1a636573d73 100644
--- a/gcc/testsuite/go.test/go-test.exp
+++ b/gcc/testsuite/go.test/go-test.exp
@@ -90,6 +90,21 @@ proc errchk { test opts } {
puts $fdout $copy_line
continue
}
+
+ # Combine quoted strings in comments, so that
+ # // ERROR "first error" "second error"
+ # turns into
+ # // ERROR "first error|second error"
+ # This format is used by the master testsuite to recognize
+ # multiple errors on a single line. We don't require that all
+ # the errors be present, but we do want to accept any of them.
+ set changed ""
+ while { $changed != $copy_line } {
+ set changed $copy_line
+ regsub "\(// \[^\"\]*\"\[^\"\]*\)\" \"" $copy_line "\\1|" out_line
+ set copy_line $out_line
+ }
+
regsub "// \(GCCGO_\)?ERROR \"\(\[^\"\]*\)\".*$" $copy_line "// \{ dg-error \"\\2\" \}" out_line
if [string match "*dg-error*\\\[*" $out_line] {
set index [string first "dg-error" $out_line]
@@ -242,6 +257,42 @@ proc go-set-goarch { } {
setenv GOARCH $goarch
}
+# Take a list of files and return a lists of lists, where each list is
+# the set of files in the same package.
+proc go-find-packages { test name files } {
+ set packages [list]
+ foreach f $files {
+ set fd [open $f r]
+ while 1 {
+ if { [gets $fd line] < 0 } {
+ close $fd
+ clone_output "$test: could not read $f"
+ unresolved $name
+ return [list]
+ }
+
+ if { [regexp "^package (\\w+)" $line match package] } {
+ set len [llength $packages]
+ for { set i 0 } { $i < $len } { incr i } {
+ set p [lindex $packages $i]
+ if { [lindex $p 0] == $package } {
+ lappend p $f
+ lset packages $i $p
+ break
+ }
+ }
+ if { $i >= $len } {
+ lappend packages [list $package $f]
+ }
+
+ close $fd
+ break
+ }
+ }
+ }
+ return $packages
+}
+
proc go-gc-tests { } {
global srcdir subdir
global runtests
@@ -286,12 +337,28 @@ proc go-gc-tests { } {
continue
}
+ # Skip the files in stress; they are not tests.
+ if [string match "*go.test/test/stress/*" $test] {
+ continue
+ }
+
+ # Skip the files in safe; gccgo does not support safe mode.
+ if [string match "*go.test/test/safe/*" $test] {
+ continue
+ }
+
# Skip files in sub-subdirectories: they are components of
# other tests.
if [string match "*go.test/test/*/*/*" $test] {
continue
}
+ # Skip files in *.dir subdirectories: they are components of
+ # other tests.
+ if [string match "*go.test/test/*.dir/*" $test] {
+ continue
+ }
+
set name [dg-trim-dirname $srcdir $test]
# Skip certain tests if target is RTEMS OS.
@@ -379,6 +446,21 @@ proc go-gc-tests { } {
continue
}
+ if { [ string match "// +build *" $test_line ] } {
+ if { [ string match "*[getenv GOARCH]*" $test_line ] } {
+ continue
+ }
+ if { [ string match "*linux*" $test_line ] } {
+ continue
+ }
+ if { [ string match "*!windows*" $test_line ] } {
+ continue
+ }
+ close $fd
+ unsupported $name
+ set lines_ok 0
+ }
+
break
}
@@ -407,7 +489,8 @@ proc go-gc-tests { } {
set go_compile_args ""
set go_execute_args ""
- if { [regexp ".*\\\$A.out (\[^|&>2\].*)\$" $test_line match progargs] } {
+ if { [regexp "// run (\[^|&>2\].*)\$" $test_line match progargs] \
+ && ! [string match "*.go*" "$progargs"] } {
set go_execute_args $progargs
verbose -log "$test: go_execute_args is $go_execute_args"
set index [string last " $progargs" $test_line]
@@ -515,6 +598,27 @@ proc go-gc-tests { } {
go-execute-xfail $test
} elseif { $test_line == "// errorcheck" } {
errchk $test ""
+ } elseif { $test_line == "// errorcheckdir" } {
+ set hold_runtests $runtests
+ set runtests "go-test.exp"
+ set dir "[file rootname $test].dir"
+ set files [lsort [glob "$dir/*.go"]]
+ set packages [go-find-packages $test $name $files]
+ if { [llength $packages] > 0 } {
+ set dg-do-what-default "assemble"
+ set del [list]
+ set last [lindex $packages end]
+ set packages [lreplace $packages end end]
+ foreach p $packages {
+ dg-test -keep-output [lrange $p 1 end] "-O" "-w $DEFAULT_GOCFLAGS"
+ lappend del "[file rootname [file tail [lindex $p 1]]].o"
+ }
+ errchk [lindex $last 1] "[lrange $last 2 end]"
+ foreach f $del {
+ file delete $f
+ }
+ }
+ set runtests $hold_runtests
} elseif { [string match "// errorcheckoutput*" $test_line] } {
# Run the test to get a .go program to error check.
set go_execute_args ""
@@ -557,21 +661,62 @@ proc go-gc-tests { } {
} elseif { $test_line == "// rundir" } {
set hold_runtests $runtests
set runtests "go-test.exp"
- set dg-do-what-default "assemble"
set dir "[file rootname $test].dir"
- set del {}
set files [lsort [glob "$dir/*.go"]]
- set last [lindex $files end]
- set files [lreplace $files end end]
- foreach f $files {
- dg-test -keep-output $f "-O" "-w $DEFAULT_GOCFLAGS"
- lappend del "[file rootname [file tail $f]].o"
+ set packages [go-find-packages $test $name $files]
+ if { [llength $packages] > 0 } {
+ set dg-do-what-default "assemble"
+ set del [list]
+ set last [lindex $packages end]
+ set packages [lreplace $packages end end]
+ foreach p $packages {
+ dg-test -keep-output [lrange $p 1 end] "-O" "-w $DEFAULT_GOCFLAGS"
+ lappend del "[file rootname [file tail [lindex $p 1]]].o"
+ }
+ set dg-do-what-default "link"
+ set go_compile_args $del
+ go-torture-execute [lrange $last 1 end]
+ foreach f $del {
+ file delete $f
+ }
}
- set dg-do-what-default "link"
- set go_compile_args $del
- go-torture-execute $last
- foreach f $del {
- file delete $f
+ set runtests $hold_runtests
+ } elseif { $test_line == "// rundircmpout" } {
+ set hold_runtests $runtests
+ set runtests "go-test.exp"
+ set dir "[file rootname $test].dir"
+ set files [lsort [glob "$dir/*.go"]]
+ set packages [go-find-packages $test $name $files]
+ if { [llength $packages] > 0 } {
+ set dg-do-what-default "assemble"
+ set del [list]
+ set last [lindex $packages end]
+ set packages [lreplace $packages end end]
+ foreach p $packages {
+ dg-test -keep-output [lrange $p 1 end] "-O" "-w $DEFAULT_GOCFLAGS"
+ lappend del "[file rootname [file tail [lindex $p 1]]].o"
+ }
+ set dg-do-what-default "link"
+ dg-test -keep-output [lrange $last 1 end] "$del -O" "-w $DEFAULT_GOCFLAGS"
+ set base "[file rootname [file tail [lindex $last 1]]]"
+ set output_file "./$base.exe"
+ lappend del $output_file
+ if [isnative] {
+ verbose -log "$output_file >$base.p 2>&1"
+ if { [catch "exec $output_file 2>$base.p" catcherr] != 0 } {
+ verbose -log $catcherr
+ fail "$name execution"
+ untested "$name compare"
+ } else {
+ pass "$name execution"
+ regsub "\\.go$" "$test" ".out" expect
+ filecmp $expect $base.p "$name compare"
+ }
+ lappend del $base.p
+ }
+ foreach f $del {
+ file delete $f
+ }
}
set runtests $hold_runtests
} elseif { "$test_line" == ""
@@ -709,33 +854,6 @@ proc go-gc-tests { } {
file delete $ofile1 $ofile2 $ofile3 $output_file
set runtests $hold_runtests
} elseif { [string match \
- "// \$G \$D/bug191.dir/a.go && \$G \$D/bug191.dir/b.go && \$G \$D/\$F.go && \$L \$F.\$A" \
- $test_line] } {
- set hold_runtests $runtests
- set runtests "go-test.exp"
- set dg-do-what-default "assemble"
- regsub "\\.go$" $test ".dir/a.go" file1
- dg-test -keep-output $file1 "-O" "-w $DEFAULT_GOCFLAGS"
- set ofile1 "[file rootname [file tail $file1]].o"
- regsub "\\.go$" $test ".dir/b.go" file2
- dg-test -keep-output $file2 "-O" "-w $DEFAULT_GOCFLAGS"
- set ofile2 "[file rootname [file tail $file2]].o"
- dg-test -keep-output "$test" "-O" "-w $DEFAULT_GOCFLAGS"
- set ofile3 "[file rootname [file tail $test]].o"
- set dg-do-what-default "link"
- set output_file "./[file rootname [file tail $test]].exe"
- set comp_output [go_target_compile "$ofile1 $ofile2 $ofile3" \
- $output_file "executable" "$options"]
- set comp_output [go-dg-prune $target_triplet $comp_output]
- if [string match "" $comp_output] {
- pass $name
- } else {
- verbose -log $comp_output
- fail $name
- }
- file delete $ofile1 $ofile2 $ofile3 $output_file
- set runtests $hold_runtests
- } elseif { [string match \
"// \$G \$D/embed0.go && \$G \$D/\$F.go && \$L \$F.\$A && ./\$A.out" \
$test_line ] } {
set hold_runtests $runtests
@@ -949,10 +1067,6 @@ proc go-gc-tests { } {
regsub "\\.go$" $test ".dir/a.go" file1
regsub "\\.go$" $test ".dir/b.go" file2
errchk "$file1" "$file2"
- } elseif { $test_line == "// \$G \$D/\$F.go \$D/z*.go && \$L \$F.\$A && ./\$A.out" } {
- set dir [file dirname $test]
- set go_compile_args [glob $dir/z*.go]
- go-torture-execute $test
} elseif { $test_line == "// \$G -N -o slow.\$A \$D/bug369.dir/pkg.go &&" \
&& $test_line2 == "// \$G -o fast.\$A \$D/bug369.dir/pkg.go &&" \
&& $test_line3 == "// run" } {
diff --git a/gcc/testsuite/go.test/test/alias1.go b/gcc/testsuite/go.test/test/alias1.go
index 4219af8cd58..42cf6934096 100644
--- a/gcc/testsuite/go.test/test/alias1.go
+++ b/gcc/testsuite/go.test/test/alias1.go
@@ -17,7 +17,7 @@ func main() {
case uint8:
// ok
default:
- println("byte != uint8")
+ panic("byte != uint8")
}
x = uint8(2)
@@ -25,7 +25,7 @@ func main() {
case byte:
// ok
default:
- println("uint8 != byte")
+ panic("uint8 != byte")
}
rune32 := false
@@ -37,7 +37,7 @@ func main() {
// must be new code
rune32 = true
default:
- println("rune != int and rune != int32")
+ panic("rune != int and rune != int32")
}
if rune32 {
@@ -49,6 +49,6 @@ func main() {
case rune:
// ok
default:
- println("int (or int32) != rune")
+ panic("int (or int32) != rune")
}
}
diff --git a/gcc/testsuite/go.test/test/args.go b/gcc/testsuite/go.test/test/args.go
index 9cfddc338b0..0ffe8101e9d 100644
--- a/gcc/testsuite/go.test/test/args.go
+++ b/gcc/testsuite/go.test/test/args.go
@@ -1,7 +1,4 @@
-// $G $F.go && $L $F.$A && ./$A.out arg1 arg2
-
-// NOTE: This test is not run by 'run.go' and so not run by all.bash.
-// To run this test you must use the ./run shell script.
+// run arg1 arg2
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
diff --git a/gcc/testsuite/go.test/test/bench/garbage/parser.go b/gcc/testsuite/go.test/test/bench/garbage/parser.go
index b91e0248f53..d85110b63d4 100644
--- a/gcc/testsuite/go.test/test/bench/garbage/parser.go
+++ b/gcc/testsuite/go.test/test/bench/garbage/parser.go
@@ -134,20 +134,31 @@ func main() {
}
}
+// find . -type d -not -path "./exp" -not -path "./exp/*" -printf "\t\"%p\",\n" | sort | sed "s/\.\///" | grep -v testdata
var packages = []string{
+ "archive",
"archive/tar",
- "encoding/asn1",
- "math/big",
+ "archive/zip",
"bufio",
+ "builtin",
"bytes",
- "math/cmplx",
+ "compress",
+ "compress/bzip2",
"compress/flate",
"compress/gzip",
+ "compress/lzw",
"compress/zlib",
+ "container",
"container/heap",
"container/list",
"container/ring",
+ "crypto",
"crypto/aes",
+ "crypto/cipher",
+ "crypto/des",
+ "crypto/dsa",
+ "crypto/ecdsa",
+ "crypto/elliptic",
"crypto/hmac",
"crypto/md5",
"crypto/rand",
@@ -159,64 +170,111 @@ var packages = []string{
"crypto/subtle",
"crypto/tls",
"crypto/x509",
+ "crypto/x509/pkix",
+ "database",
+ "database/sql",
+ "database/sql/driver",
+ "debug",
"debug/dwarf",
- "debug/macho",
"debug/elf",
"debug/gosym",
- "exp/ebnf",
+ "debug/macho",
+ "debug/pe",
+ "encoding",
"encoding/ascii85",
+ "encoding/asn1",
+ "encoding/base32",
"encoding/base64",
"encoding/binary",
+ "encoding/csv",
+ "encoding/gob",
"encoding/hex",
+ "encoding/json",
"encoding/pem",
- "os/exec",
+ "encoding/xml",
+ "errors",
+ "expvar",
"flag",
"fmt",
+ "go",
"go/ast",
+ "go/build",
"go/doc",
+ "go/format",
"go/parser",
"go/printer",
"go/scanner",
"go/token",
- "encoding/gob",
"hash",
"hash/adler32",
"hash/crc32",
"hash/crc64",
- "net/http",
+ "hash/fnv",
+ "html",
+ "html/template",
"image",
+ "image/color",
+ "image/draw",
+ "image/gif",
"image/jpeg",
"image/png",
+ "index",
+ "index/suffixarray",
"io",
"io/ioutil",
- "encoding/json",
"log",
+ "log/syslog",
"math",
+ "math/big",
+ "math/cmplx",
+ "math/rand",
"mime",
+ "mime/multipart",
"net",
+ "net/http",
+ "net/http/cgi",
+ "net/http/cookiejar",
+ "net/http/fcgi",
+ "net/http/httptest",
+ "net/http/httputil",
+ "net/http/pprof",
+ "net/mail",
+ "net/rpc",
+ "net/rpc/jsonrpc",
+ "net/smtp",
+ "net/textproto",
+ "net/url",
"os",
+ "os/exec",
+ "os/signal",
+ "os/user",
"path",
- "math/rand",
+ "path/filepath",
"reflect",
"regexp",
- "net/rpc",
+ "regexp/syntax",
"runtime",
- "text/scanner",
+ "runtime/cgo",
+ "runtime/debug",
+ "runtime/pprof",
+ "runtime/race",
"sort",
- "net/smtp",
"strconv",
"strings",
"sync",
+ "sync/atomic",
"syscall",
- "log/syslog",
- "text/tabwriter",
- "text/template",
"testing",
"testing/iotest",
"testing/quick",
+ "text",
+ "text/scanner",
+ "text/tabwriter",
+ "text/template",
+ "text/template/parse",
"time",
"unicode",
- "unicode/utf8",
"unicode/utf16",
- "encoding/xml",
+ "unicode/utf8",
+ "unsafe",
}
diff --git a/gcc/testsuite/go.test/test/bench/go1/fmt_test.go b/gcc/testsuite/go.test/test/bench/go1/fmt_test.go
new file mode 100644
index 00000000000..d3c695669c0
--- /dev/null
+++ b/gcc/testsuite/go.test/test/bench/go1/fmt_test.go
@@ -0,0 +1,68 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package go1
+
+// benchmark based on fmt/fmt_test.go
+
+import (
+ "bytes"
+ "fmt"
+ "testing"
+)
+
+func BenchmarkFmtFprintfEmpty(b *testing.B) {
+ var buf bytes.Buffer
+ for i := 0; i < b.N; i++ {
+ fmt.Fprintf(&buf, "")
+ }
+}
+
+func BenchmarkFmtFprintfString(b *testing.B) {
+ var buf bytes.Buffer
+ for i := 0; i < b.N; i++ {
+ buf.Reset()
+ fmt.Fprintf(&buf, "%s", "hello")
+ }
+}
+
+func BenchmarkFmtFprintfInt(b *testing.B) {
+ var buf bytes.Buffer
+ for i := 0; i < b.N; i++ {
+ buf.Reset()
+ fmt.Fprintf(&buf, "%d", 5)
+ }
+}
+
+func BenchmarkFmtFprintfIntInt(b *testing.B) {
+ var buf bytes.Buffer
+ for i := 0; i < b.N; i++ {
+ buf.Reset()
+ fmt.Fprintf(&buf, "%d %d", 5, 6)
+ }
+}
+
+func BenchmarkFmtFprintfPrefixedInt(b *testing.B) {
+ var buf bytes.Buffer
+ for i := 0; i < b.N; i++ {
+ buf.Reset()
+ fmt.Fprintf(&buf, "This is some meaningless prefix text that needs to be scanned %d", 6)
+ }
+}
+
+func BenchmarkFmtFprintfFloat(b *testing.B) {
+ var buf bytes.Buffer
+ for i := 0; i < b.N; i++ {
+ buf.Reset()
+ fmt.Fprintf(&buf, "%g", 5.23184)
+ }
+}
+
+func BenchmarkFmtManyArgs(b *testing.B) {
+ var buf bytes.Buffer
+ for i := 0; i < b.N; i++ {
+ buf.Reset()
+ fmt.Fprintf(&buf, "%2d/%2d/%2d %d:%d:%d %s %s\n", 3, 4, 5, 11, 12, 13, "hello", "world")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/bench/go1/http_test.go b/gcc/testsuite/go.test/test/bench/go1/http_test.go
new file mode 100644
index 00000000000..34e789f6658
--- /dev/null
+++ b/gcc/testsuite/go.test/test/bench/go1/http_test.go
@@ -0,0 +1,45 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package go1
+
+import (
+ "bytes"
+ "io/ioutil"
+ "net/http"
+ "net/http/httptest"
+ "testing"
+)
+
+// BenchmarkHTTPClientServer benchmarks both the HTTP client and the HTTP server,
+// on small requests.
+func BenchmarkHTTPClientServer(b *testing.B) {
+ msg := []byte("Hello world.\n")
+ ts := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
+ rw.Write(msg)
+ }))
+ defer ts.Close()
+
+ tr := &http.Transport{}
+ defer tr.CloseIdleConnections()
+ cl := &http.Client{
+ Transport: tr,
+ }
+
+ b.ResetTimer()
+
+ for i := 0; i < b.N; i++ {
+ res, err := cl.Get(ts.URL)
+ if err != nil {
+ b.Fatal("Get:", err)
+ }
+ all, err := ioutil.ReadAll(res.Body)
+ if err != nil {
+ b.Fatal("ReadAll:", err)
+ }
+ if !bytes.Equal(all, msg) {
+ b.Fatalf("Got body %q; want %q", all, msg)
+ }
+ }
+}
diff --git a/gcc/testsuite/go.test/test/bench/go1/json_test.go b/gcc/testsuite/go.test/test/bench/go1/json_test.go
index 614e24a810c..1d42619bdeb 100644
--- a/gcc/testsuite/go.test/test/bench/go1/json_test.go
+++ b/gcc/testsuite/go.test/test/bench/go1/json_test.go
@@ -7,12 +7,12 @@
package go1
import (
+ "bytes"
"compress/bzip2"
"encoding/base64"
"encoding/json"
"io"
"io/ioutil"
- "strings"
"testing"
)
@@ -23,7 +23,7 @@ var (
func makeJsonBytes() []byte {
var r io.Reader
- r = strings.NewReader(jsonbz2_base64)
+ r = bytes.NewReader(bytes.Replace(jsonbz2_base64, []byte{'\n'}, nil, -1))
r = base64.NewDecoder(base64.StdEncoding, r)
r = bzip2.NewReader(r)
b, err := ioutil.ReadAll(r)
diff --git a/gcc/testsuite/go.test/test/bench/go1/jsondata_test.go b/gcc/testsuite/go.test/test/bench/go1/jsondata_test.go
index 7d42c966579..cf0fac14806 100644
--- a/gcc/testsuite/go.test/test/bench/go1/jsondata_test.go
+++ b/gcc/testsuite/go.test/test/bench/go1/jsondata_test.go
@@ -13,1806 +13,1807 @@
package go1
-var jsonbz2_base64 = "QlpoOTFBWSZTWZ0H0LkG0bxfgFH8UAf/8D////q////6YSvJveAAAAAH3ddt7gAN" +
- "FrKppN9gw0gA++fGB9xKkUpX0YWTENCgqzUW1tlsyMB2w9nnvNSigNyS+3cui5zA" +
- "AAAAAAAAAI4kILu6ytuWTLBbaPXfc+A+PQEgNAG1ZMBYWnWwPoFrGjoBnYMumlUF" +
- "UKA7NVBQgut30zzu8eM2tsoapJ7u41djLsxZarplSoJouxrdfHrHPSiqAGgkAD6D" +
- "QfT0ABu7gG1qDtdVHVXp7vWuBoBk2wEOjKChQ5bvbh3riupXZycASbaiQEECRKib" +
- "ZFJFtqWjR7bsGoaa1lIFPRoKVQKoJFyqbWr5OB1Aie2pobm1EJKqVBU1EE2lCg6a" +
- "AUBV9hqL00q9btQ0J9hqu2zavWVdjI6aAusU22tNa+8m70GjRqarKRWtUDW2yFBI" +
- "1kBrrqrxeX3AyB9AD0wAAAeZ6weqV1rVu8UVICgAAABeDn2cAAd9gAACI+7DvjHo" +
- "j73u8X2dDXT2x6adeFOTNe7BvavozFezkV1xXtJzu8H0983QAHr5aPT42iem53fX" +
- "23IDr7YejQNtVVZr24gGgB0VQffPXH18g9DoaDW8vt729h9bt72XsKth0ANxgodG" +
- "iRxvYclAAAAAnpqRtgGvcbo9ABpy6aPQADRZ3aACjyox4NawKCqNdA6offa1WtPc" +
- "fdjQUPvauprcLoPe2oaplp2w7cnOHdlF27xvPY1QU67vc8goBRttLYKaHXkPAAAA" +
- "AAdyFFaYCVClAVSlCqVSilFUKEgoNT0CAQCBAk00g1T0jQNNPSbKADQxAJEBESIg" +
- "Seomk9EB6mjQ0NNGgAAAAkEgkiGk0CR6U9CNNNNNPQRo0ANAaAAk9UpEQmoNNRqe" +
- "U02o00AAADQABoACJEAlKamUCjZT9UGnqAAG1AGgAAAFRJCAQCBA0SYjTKbQmqea" +
- "p6YU2o09Q9TT00nAlwPEuSelCeXl28B3IYIQHEwXUMSCvlAYS5LkrZn+XhHHAXZz" +
- "FTJHAzrKZzYWC0pthA9SCmbkyVzoHbSUjhnAfBrYpwWYIB7GRjOjDQqokMbJENSO" +
- "SBCN0WhaRhQWpVuoOLN0NPRed7eO5eW2lv5L+X/jf7EpJkEUNMJKZREogmkjMgZJ" +
- "BiEEEliRIUKAoiaSEoDQZJBhKEZEQySQCAIIFNIMwCiSYRSYzKMkSSlI0xZMZKko" +
- "RKlRtkmWJIrNNIBEJEYiJBhGMMkWYxRqUsmjKJMmCFJMaSmiyDSaEJtBIJpANKMN" +
- "JEkpGQAYjLNETGUBRAlBKURgsC0wzKZhRmhiYIQZIsZCIIMiiNmFCCiSZNjI0khE" +
- "AYSEUkjTMSZskZKRQWJoRNBI2IojZmMhTIkQEgyREEMoomDSiYxAZMECFCSKIkGg" +
- "kIDIw2MNAlgyA0SmKWSSyIaRCSDDIkZmNGghgyAEoERokkWTA0xZBEQhmUSBGmaQ" +
- "aQBFmRJMokwxIyRSWbAkbCUFlAhgUISJIRkySYhAxoUARCSaIJMkyiZJNBMyGRIh" +
- "Y0komKImgMDI/038qLf/av/bWSNVEtmFRx/2aaDVmKkY0NkIRDGJEWoEGLf9g9MV" +
- "UJWGSu0pWVpSOdWDVjQJGRSChGBGDGhNNMYYwjEsaFISGPT3TbFXk873Xq8vPa9b" +
- "0dcco0UEPXIl/+em0IMHNYJaXBEsiKQh/7QwsC9gAauDvWtMEBWhGBIBAerIYlBU" +
- "SzPasze15BfAyGrr284QNjGNEmaUphiMxEMwCZjAYRpMiZBMpEMkkQzIwTDu5zru" +
- "Xd1xdQ6A6E7m7d03OLnXOxd3HBu50dl0JOhxS4HdHczuO647uuLu6650O67t3Duu" +
- "3DucukzRKIMhsUjSQQxDIzQJgxohEkYTYkZsAxSDGCJJERhpEAygoZRESSEjMpFE" +
- "0UpJlBkIYwoyQ7/2f9H/Py8roY3wEn8nr7+72ybZtybdqY06yp1tjGVmsmJvG48y" +
- "89EXnvy9F6OvX0vpBSIEiSRAmgSASYSkCGBkyc5J63pgiRBNsJW2xjGmmNsf9v7R" +
- "z1rueFmZcfXzw/zTGRYxsYm2NjbbfXD64GtivKx5t9eubzmsMTbf9rTfKRsYx7YR" +
- "jHWL7OoAJpsFBJgyAEzSJiLHxfJKWQgSlJjGduRqRxDIoETG4wj+VgUjnMt5PXnm" +
- "vEQwO7ojzu7lxu7uasg9T00zjrtcaG2RKIwyHx2vUcbjd0OXXvfNafFE3u3t7bu9" +
- "TpJ1t6SKh9vi13hQUX4d307pPHt553zxxHMGb4KrbbvJGTCcNs3WmOyG2fg5vsuZ" +
- "jMi+lacpNcvr0XeKDnafDcIvhyL7927rr7/Pzfj7qLVW5dFKIg8+fKpuxf+vfhB+" +
- "73vWXz3qCPPfw32Mn4c/9mtONctW/fc1sYad9JYn/D1DlDPoyyc7D5bSi3ncMPNH" +
- "bWmvm42eODHImqooiuXwn95XZlmKYKGK7KdA6lrgzZpEiUccypzKofPy4kbjq6Nh" +
- "o/ou++j5g2i5alDG/G3Cb0yaOY3lH7wd83fLG1uQ0nDG18UHnnOOsy+Y4u2Nv5Hl" +
- "jTCKmSJYyBhnB1Lbbafjgaat8zzctvDjPPy7e5IdyZHPSTxq/zkHjinrI5v0/nmG" +
- "Pp+JUz4odkc9b4/cze19oRNOjG2wb+PkWtt4RRjbBsfupHPO3Mmgc18az57U+TM7" +
- "gQsH90UPHJCZN4WsaY383qkbxxO20pI23JHbCr3ssnqkVFJG/lN5x6yQydwiaSA6" +
- "rcgBoSxEDRKIuS1slJsq1MtS6koA5+jFGb17XFu0owrTZZSqsjrkmLVo2tSN44ac" +
- "fvD3aWfOerth5lG/Jlkfp6bqUbOZs2FpVptDIwCuWVgqIgkgJMtDBFi+2FpRDhEI" +
- "JAKJtPXloMoKGWpU0YvH9h2nx/hxra8/8UoaoWbia9EeoTlN7Bd5PNdcCDKemn+L" +
- "cY2qMUXGibc0a33/wjqMN0s8PmTeeup76JA7aKr1nMbhIkn1aX4m5rTPH4aOBlTQ" +
- "I35HXHwtJ9z1XuF9EQDwDnCS3S9W358a/E4pTeTSVvyKGWTK/n4Xp7V4dB64Ua3Q" +
- "BIaDtzTsXpXV1k9E54ousxG/XtEhuaGmyCefTL/r3478anc78deNRjg9uchGVxVD" +
- "Fq6cMZqIdp0ihq0xoIf1zldyBS011SFzq08qfSxV8u0cT70dZgp8ebjk800pU8m2" +
- "s1kKdj+zvmBEEU+P0+FlzrhOf/ifG2tOsmrlp7B88bbCY9u1VFK7YavjSQ7xtE94" +
- "3aiJb59/et60wn2vrgeV/jeNd+O/Wt/fp6dNf7iJA5QICcGyiKgpFEFQiCjEGEQC" +
- "LBIioACSIqiCxSCqIxJIw1GQ0Ua1Vam2qYsmg1rVTbQlmjVbWbaGLbU1kWtlqWrN" +
- "LVNNaaQICZqIhD/QiASyQCUEBKiRKRAJSUiASySKRAJSD/zAgJUghMIgEojKiCf+" +
- "CIBP9wICfq+/889/0uxkuba/pJdybzbJvEsZ/CpEx89uGn3OONVtyYDHCGIxNyIx" +
- "JsYgJYbH+I5RK73DuMZminldjp3e8QpDJju1QToo7pQFEpABpEV4CLQo2QicBAbo" +
- "SEINjsMsDt9BO4nJzGstqAmgEJwhRyggJYoMJE0sJoa0zOdEgXdwiQssy4L3pzbM" +
- "CwOaLEYFDBQKzaJCjFh2yhQOHbgLVMHXFUf7jhKTXPWsNDuEPXRHfJuLlKqls5Tx" +
- "pCC1IgIHnTm5PeWkwwjobODcCdTCa0YoDvMlcZwvmQTkg8KC06oALrhzZqrQmQq6" +
- "E28rdrSUxBeLkBshIKRh04g4LDdsmTCpNKSszbu9lHOoAwkmTDrOKCmSqExdOsOV" +
- "D1XsAQpFVMukLCcGYGVFpAp4Bg0VnXFFjjdC8avBE6BepA3q6bOgot8LtHTiIlkb" +
- "ARVEcldJoYt4Pimls9rpBzDNzeMwOdNAdSkWo4CrsTZ065yPaODXMCkcZCarR0LU" +
- "voX1R3nDEsLtlyklMo3qrYHIguO1Ci7xRXFwJZjfTrtZfAyzUKhgJcLOIzeTvWjG" +
- "zDE27OYME6dM3Z2kVeKcV1I4jKga0x3vCKlcUmkjRE1Zzsmxsq7L3zOnQ8wzeGDZ" +
- "pQO0uN0NpZhcQSuVETbLL2zvKTzqjtBhwIXGaksi8rYKx2Wi6C1J3Ulb1dwqkjat" +
- "FU6mO1F5Ii+bGnOMaOlc5EKekFDaQ9tjCU1yqcE66xRVh1ndLcBt7ThNI8LbowKP" +
- "Md0AHRNhdYOJksYIQETYuK3ytX1UEkFHZLCghijoBdFzCgKJmlJSADdF5CnsMoIp" +
- "pMjeqUgBrXACCcshXWsqyAgenB7IMoT6ZghKl5ljwkJTUVQuhTp3YIWgQCl8eBO7" +
- "FTzwWGBEw8BDaLuSqMmM0wWE6QVsFIpRwmCRA128BCKpdaVunHbkyuScBsqeFjLJ" +
- "qAw0WUUIhMN3S5Keua7Wynjnew31G8jecPcVIYxGw3trGziGoCdTHKPOEpO5732V" +
- "4lnVA4VvKsc+R4OHHQz2JkHFdwSzeiDBUGBiQAJcznd7Z0oCmMykE5KjZuKCyKhd" +
- "5nTSBBtu1sj6s2JCiZBgpYdOIM4luy6evBlYUYldUQQZKOoAiZL4d7fe003l07CD" +
- "omKNzZgXiveIrzXjCZel4BcyY752rec3eRoT6jAGZAGEc3kkZQhLcVNCq+qVFSim" +
- "BuCKZeQr5FF85WTJZzIXXwto0cB2CpntlWr0xWTfLt1yrDg8503VJAdH0uqes4bJ" +
- "d5wsYFakMZlVS7lsEko6gj0LqyENh3rvG7qYJiQ9xoY33UthsUwRtEF6HUjtHWGA" +
- "1q5N1HNgiI7rFa5QiEzuCDZ03KzKswfM7185zaRUkRyiUUssQSPAwlc6CAaa2KwB" +
- "CwsOVTUrpamy4uS+mkF2pVMrpWpG7eYkYjcqSMY+pyDKhDILMmR5HGGc5ml4LJEa" +
- "A2sxQOlwRDZ0WyiDjMTFnLRKRw6sK02ph9cZnMe8fZrmsJ0710vNY0uY4QFbSrzd" +
- "WY7FvR2oW0ZI0zyUKMETaoJFAUTUyWuaSjAQt4DbxyqAYcj2ysQneAWKMQAWMoBB" +
- "hIT0HPY5ne8L49gqYBFQhCXlCmzuzQImhRcjCApqiwAmbWJbzsY5reBB1xT5l5T1" +
- "ybWy6V0tnJKrLM5WHNy+RpkM2cyZ5hebCcdg7aCc7IdY80lCFwSGCAXNmQXb2QRQ" +
- "x7k3NRDGXELYQ1gsQhhUDum3ZE72ughHRdRDe5Te6qw1u1LB7lbNrJow7QT1uAV3" +
- "LMgyxdGjCMORl8Gn2BQuwIUzm8BtHWJnZGBtieoICDTvKJbIMisQ2U1BCZoZlhQX" +
- "ygQBW0jtgQdslCYNcrXVNnBA+zLTmqmqYeS9YapA12zNGgCPsUFmdoio3ByWaNXs" +
- "7NrZuGMrSZWRJA0vOHdOWzMw8kjKrskdtyHLanDtiyJzpWVgjo+aaaAkqTKWLcdw" +
- "xANHQyoZ1XdCK2biAxFgjnDMsxEk4wrWTKgmoae5DQbpESptb1u3Dbpe6qOAZBKa" +
- "UBJKBZeiCwEJ0WgjFAInS4JGF6SCWBfA6F3ud3YtJTVontzKvsRDk5lipuE0+KVI" +
- "KnHbGmhhDdShYAZ20BJi8hNs22nd3MxNWKTyqlNVdr1vFs1kiRRBRoZYJt1SAw2W" +
- "IVY7gXmtBFNaclgFQFjwnNh/g2AZt0p2YbFHgZ1ZkUHIuCAEMTDITBEMBgx4Ecgg" +
- "OwyuETQ7GUQsGRFZENlWXORDAZBg5I2Qg0CU0NEcuCVhf8E4pyCmHivNaJAP8Dg6" +
- "HMU/BCCcRX/CAZi3FTsR+gqagg7gfXVQF3AFS45ig+iMnICOKROLlQG9QyjKyxqt" +
- "rL7DL2NWEoOARpsJENtjCQigyaiVbD8RcRpvD0dJYxh4KmINWGAOAshCD2ihhCBU" +
- "w7Rz2iEeFpgIN0kKqUcbsJC1I9OQR1ARqIJlDBA9OIaiEhhK4RqJxpaG4HNX26+L" +
- "L2uVbzYr6uxSpDYDItapRNSDSPMC40zShplaragEHVTTzmCYzRWDaG4boqxNVpQe" +
- "/U/8feVF+H1z3Iy2hnvDyeOt5n1QI23zarZHe9m7tUTEm75vIImeGztcNqf8/DK0" +
- "7AS3hyuujbWlvld0RqQIdaW8VAyyAqKpJUEU5BBqICLiixEH2fZwoinThP1ruaww" +
- "Wxs79RpIWIc1I6VkHrWTkb36HKsT8aCEdYQp8dyc8nHc5Tn1GZ9DqfXs+w6jU5vi" +
- "5KOwjHVB4s9RJbGxesXpEnueovCTuXRSXfPMqMjxq9le4We74avJg7nrh8fkY4r3" +
- "uTybuqrI5WCNRuBiLUVuMAR02HDRwNFmhVQC0wOxtAjoECQdIAuc+ZfaLo6O0IVM" +
- "EV4FEtlx4W2FCCd0Phvqkylm+T5VSzgZCqK7UNZc+X11LEfD369NnPNn684h236W" +
- "bTiIcgobiiYguzQoGj4YxXj++cs4Tz0qdHkwXXYuqOxh4RlKlgXcTb+ZT58LL54/" +
- "X5UkWd6UwSUtKWg8ezAgn3LlVGy99KvHea5jdcQUuTpOwzdqe2VOu9t12gz7+79S" +
- "tp9hZGnb9KZ0+UWVGOfa8PL8MePzZ2jpXPc6c8Sz56UZnuR7VyqryWOdve7uxH+f" +
- "7i9zTaJuakt23DIbPPKW3WvwvI5hyr5WOMzSpMgcRs3ZkcLrNrzmzOP/kkQSPs/c" +
- "fx/623+62xX7H7t/15ZmW2yT/C26fxC/1B/Nm/4vHf4Y/W83vZdxnDDNatLLf4zJ" +
- "2SOOSTXtmh6bgfkM/aUg/9rYz+ROs5f0f7Np83tXE0ON27ynOf4eduzHucnkr/bP" +
- "/xPo+Tm1N30cm7RXZ2cox/U5Js3cZ8ctGrXWkfP6/AuC4YHo+wmtGj+jDpRjOnhC" +
- "Rui6MS/oi+aX3Nt6cccYzh37RNxmjpw854P83H24dWtaabtnmK/F6q09XRzP6HOT" +
- "UEd6oETQUHmXUt2toYLMjFiMiAgDhaE2Dii0fPTcNGH7p5jf0kPg3fXkttKDMGej" +
- "3IKP2KJOlt/R+CT7PcY3AZxsoa+WREFD5vk4TdXR6uRq+MzKxSvDrq2ak+c2275m" +
- "d5ettnJp+4/Y+HV6qxudXLdedt6uSdTKGaMJP6jNbZZww68/M8PzplDqYusu8ZQB" +
- "AFQUJ8y9CB2DjMriYXiyEoiFRoNAmCWWSMuP4EvGSYUfk7ut8CD78n+j+iqqihWU" +
- "fmZb8RVjX9LiIokXhgfqc+hjbZR8xHTSG2NvltyeEkBoz+i+EBqwZMS3bqJsEaIa" +
- "GhUYwpTgGQIwCHFSPHf9PH5soVQwNtyu3LdB4H7h7qHvPtJPgw2vhhBmwPscrZ9i" +
- "B0ofZ8/K22LZTR+R6NBmMbWj+o8N5NK4btPxmPo3Yvl53M08zTwps2Ux8n29W7or" +
- "ecnOTH4LDyKfk9eenmurrptb6EDAylMSyCFoPt68A+P2W2rxpvgRO7eOTE06p78T" +
- "pM095szdT5dJNkqV9yvdk2KjRq7ZNv2M/zD1uISNH5LRt2dPbXxwgg+aSTdJarr4" +
- "+t4IO5+isaqdYSfl2IOJ0ntA756tsBY3I66SOBHlU+0+8bWUbHdtxa1P2y83z5Pv" +
- "NqJ29h6ymz5tztPN04yw5+OsUx767u+t4Wb68vvztvPsCb27OnbrgHffegij8Dbt" +
- "R+cpqFnrpoO2jCj+dtrCBfwtFtxfNrZd9ZcQzVPa9qbeq8duMYmVfF+2cTONb3u2" +
- "m+N7LwZwK24TMUPA/s1xS2PJ211vg1JfBUXQLO2tMacGtLJmttPE59YWnForCNrr" +
- "vbv4+/xy7+NG7BfXbnqKVTuo0DMuFW6c/DBvb4i5+crr56qLSmCHWi131w0DRNem" +
- "G8J8mWF6/BavOE5YJruAqh/e19oRd79a8j2xXHhVteYnEW9a1AvE2WHFHnr7Wf43" +
- "p9q/GjSGtZb51XBDR5fZe/afXwzt1jTi0aTqd5pQ9xPS9+tflc68V3+R30RS3anM" +
- "Z7/OYoK83au2vY962u/PmnmvWmcymeWxxPne1H49bc+va/KVHaqJxTgrqcN7zDZ2" +
- "TweudXvavlknvqpsg6zC6+IavvB2enbrx754TjNRir97rpG62S7VPnth+nn9KvmF" +
- "thTinXkTrfbYcr54eVPbFQRF11vTW9+CcB+4r3XRpMtsKWHnhn3dFDF7PYpQoLeU" +
- "zh639UyDF5ouhQerfW+FKROlO2lJwm+UDcwvkjwQ51nx2aQ+iINt/lkDDTrmb2vr" +
- "xryHii648Xu/tF6QHbUcIFxgYRp4+V7eaLG64b2su+ONNxKEDlYjMR1Fuhvauj8z" +
- "eus/aeYa2iB/Va1tuuH2zjOvxxxonwsbYInfrnTPNs504yedSRkJR0jeaBvNr5mG" +
- "nFr5TFHNub0FVE3034E+q7tfF5n54uuT4o+28bYpzjhtI6mfB4jbVMEd31VAR4vi" +
- "GN8Tu4umaeq9qLGLNUsvpQu/8faJd34UW2pXhjvaq0NFmKDNZ7UjVrNM4aXvd5pS" +
- "g7LW/5p7955Vtvf6tsMfFl9rs3VvkKnfvemaXnFPGd4je+Y3iU3nXv37xz8/Ot5b" +
- "nc6a2J+dPSXnLYpvqfBk7ZifA8RiUeNNauSKONwZWKpMDsKhPt+f5X25+dAjco/6" +
- "X52E/Ys3128FfCeI+sV1Ngs+8/j7+sqrWwKe/0ydfK2xlW+++7Sx8Nr09NQEOaq5" +
- "Z21TVe+3euawND9LPk1eaTWOD2M1bXSfq32fH5WrqCSRodPHmm85a3Gq8/ldR8zn" +
- "NtO6s/E5oRyyZ1pX09q7BTxk/n5j1O8Yr8nSj+qezJTO/bzuIo9vLwYbxnRYVVut" +
- "OL7dQJYPFNnRyNDLjWmONtQBd1AxDZA39o0QEps8eiBrSOQO+M2yN/b3A0Mr9bVG" +
- "5A42A3LcI0uBvqcxzal1tziFTfaXakSnUaaNpTxpS+3avWO1hvyyUtPUe+uu45yi" +
- "4aeNNM2GnS0nrucvjF/OGhoOnW1aB+Lxnmzq3GyztaXeuQpomp1FUXt7Rffavj8e" +
- "Jxqux8eyex3ftOU4rXxtxMYwPRqwXX3Rcbx8dn9s3YtPa1XrnZx3dqikI3E1b3fP" +
- "b83aGWPme0CcoGvA1o2PWLs1K+ceH4fTFuVHzrGWGpHci+dabeFi0V6m3aE68H73" +
- "Zw10nviGOyJI6DzqzFDysrN7Vt3elS/jFreqKx+UpRu/mfHbO2Jz7663zp9WvTov" +
- "vvvi14Hr7KrTbRduDN4R+UTmqrtsy2L5ZVHyb3Y6t0R06bVXuuJsOJpv5TdGqPBn" +
- "vjuRp2u8z2WyNdKcny5v9uOfk2vv7aaeetW8z7wtz15nB6WenehxSnftgbkj3tWd" +
- "Mah+7rRbrONx6m49l1arhpoQIQzabRKaTwFVPoKPOmlsaT9tWeFUp8/XrDuFrtXT" +
- "1Ap74Ub+kFY8KMkmQ4I7OOw17bYmTediZ0ZtqXZakoO7cey6d0rpPrCrpmfgHM/b" +
- "a7hjUcJ7c3OM2GCCHLLJ9KNHOb1c199tbZc8EKX0o9vETvYazOKX1tnTN9u/0fij" +
- "7WpVRTrmmb7c73x2zlpOsWq3PBNjMryyVim+k6qIHV8cZzrm1NNNtGG3WiU222+q" +
- "WvilXLVPDTtuujYqnq92HkjtPrnhn8wfFVRtPKbMlam+ja2nZNWzVGx40FOJoI1m" +
- "jzX8RMGuvpd/eu+lF81TFb00pDIz9nRKTd6RSnvt2s+s7+qqt/jhaRHwyffKQ/z0" +
- "/tG3K+dUXivrmu3jC03fjSsNvPfd9sob+3xr8iPBlBljpK63v6fnbHtxKpDNFNx4" +
- "fWXi+m1XLycVHAWwI7iooCKfX4XX8vjqgNOk/E9udJqie7fMu3gr4Snj7XtqUiPX" +
- "k/dmGsfHvAp85erxqS/xs1bwlgkOcUNz9VxavzsJ6RvKmczE3Qfa3x8N7dfP19fV" +
- "5zBafd0+t4Gv1r9dSf3T6+afWJ0nyP0YagjzqAokAsvA5HMvICycScGRH5DZSUA+" +
- "4yHCgQfxOdfUK0SiI3A5uCNvta9mxHytvJydnbe2vh3ekY7Rp0aKfJeTkcPDZ8Nm" +
- "PB3NTaen67W1s5nLDjLOzJpdra8zzbuJp5Pt6W7cnZU5vM2/Y6dMPz9e5Tcsdwed" +
- "g3dJ1jb2DdpxJIz0Z0kNPqBsn92/s4FF+N/glGnYgij0wPhQuH0EH5P7jwhh/JyC" +
- "zw+Z3IMdOXTp3K3ZOHCvyezHJs5atrTSjQcMZLMtxWHd4dXKNgxw4aZq3nzb+1vu" +
- "cjpvN/b6mqqpFQxWMPRn6H4LFK8ID7PD0s4SMs9KL0KMPT9CxUqLPxoSUfQf0KPy" +
- "Lhh9D1vz6H9jW/B0emjPs4eCR1R8HP7MbkZSDnGyW2fQzpoFHCz0g/k0/c8XzYzM" +
- "Xg5v2dmmnecnavJvG6+L5VVNPmrir5NP/86vZ5HJ8Nnbq3mj04tjyV4Y9nm2eh0f" +
- "qafNu7Pns6K05Gnm+zfa1ps3fD43tuO76Gt3pHDu2Z4fN0c3eclcM5W46KqvgrfL" +
- "ZZ8Ozk5zj2t+GJ1OZux01LfBLof2MVLIb+iTTw/Qko8MWFEI2oiP1WGGjYyKLrbb" +
- "fh6PuDD7yk3srttD0dPqECggsURwgcKHFYVt9Z+a1C4nm6Upa9L3uLtW7mx0YcK4" +
- "Kx0dfZa/Ltw8n9hXZ89reu1qDcLLcHUQNwHtoWoGtuURwwrIGERCPzCr0EbZJDNy" +
- "QYwp37N0hT9ZQ2foLh0PmQ4bKfLwekfRti0fBA/YfU4d3PrbbDZ6xtdCy8gjwLiJ" +
- "ERJhI2+1B1WIF0FdF1DCwjKkl0UI4z0M6fVMf6venWbllsbtgcPvILqxNlq6efK2" +
- "Sq6vRw6K51ebu01V9Z5ui4IUOJjUBhQUeqIhoDPBJAf0TLYPoToLip4WdGkzxt/Z" +
- "762yzA4Qhhh4oHIv3KIDT5KmZlTKwtaWOeREM8623/B6elo8Q1JxiWAgQncQECgM" +
- "LAiWAQRUxWNHd3dxdjkaybr2VslNjq7NlVT2j4cJ2ejho/Rk05YtfCzu1xat+Hdu" +
- "91cvNxDspIbRFIVURFCyHQYewlUKLjAgdUHOqqFXQdDAGooOZKIyENwSUKq4sEFR" +
- "yNRMUadp0PLpEZlE3GfqYaDKGQcHDf7nD8kmHDRh4fwWWYffjxw24caYWfk0mkeN" +
- "D4SFGhHiVFbu2EkgtHFezxIqaWnaEdzJFsqSNEFKpZXphid250aNmnZo7ZMVlx7m" +
- "zFVXDo03KvK3TTdqZZZ0j34LqeGyvh6K8ns4bdrequzHYrNt5jMmO7tq3Hk9GTU6" +
- "GMOGnzTTgbO08zq5PJjdy74zObhx6M8nJu5Vc+Lbm9uVj1ezk3q17t3D0exwYMKB" +
- "pTOURDWRGaXREECYuJhxzxhETUu8mXv9Vjp48d1lC0/f0WGgxkH1HjiPyUUeFBGO" +
- "am8bm7o07t3Vu5lah4OzS3020qqBK4ICgQPb8h8fj69n+3hleET5+1Kk1maNSlav" +
- "R9c8+++/Pnenwej1erxtb6HV2SCSSdrJHVYHikZUg1ZVkDtUEypDVQZTN8kDSwll" +
- "keMwS78akNOMiJQQc3dihLlKj+oCG7aEM7oG4kZW1NVLsxIVjJxmQMVBiUTaWsgY" +
- "DYxiQYyPuBXhdUKWrZb79D15ra7uMfLW1eW8dXOaiNhdxQslkuUzMFKgagC1Ehom" +
- "iOOZC4AyO5qNxXMVogEhIpqSNRe4grNtR7emHctEhpNtsXLSm9xOTBmOSDYeNILY" +
- "2DG2ibk3hUFnKtvTMXYBFsiI1xxoHjiBJg0ZhC2Vig602I1PKTNWvbUbYm/JAG0U" +
- "aUsNNFafJHs1SpG5rY8UsGwe7VRhp+PJFmpjr15ahtvTFpqhuKWCg24WKj7kpybZ" +
- "c6V5CsG96jMayx1GWUOgDVCIZKqhixI3lLuejpuwX0E8/UR6+vsvzdYqEqnmqYPr" +
- "ynyiMGXW2W+XV42wNasYmujHR/B20ne7B8uftj52a23ykGf0r2Fya3xEEDcibiTQ" +
- "0lZLgyC2ePfZkNiK8bqa+t/uN5kVHlxN3dckC7FJia9ve/Uugg2wm6UBkqXOGuys" +
- "qBJmITKhYQIImk5o5EECZQKpHrRxXGOTi2LXQmqWh6LhdyTi01SqSQ3VOEDXmHyx" +
- "eGS7oe6mzQZ5CDD00rOtqeKJjKBw+ee+cWoiUVDVLJ/FhK0iGh1VeKiES0TeYm9Y" +
- "aEWwQmDQoQiRwvF1pOMzCkqwS5CmptDqzik403jShJgqi2UaBbWZmCIlgrKzuoHE" +
- "I80UvVUMTR9bJIWy6iiIAxXukg2P4TDx8uds7uzmTTj2cu9+82j892bLO1fYjuV1" +
- "nOX+0ET1+9s/q59/SSQJI/0pffnnpk32yWNNLZIyLEInER1S3+6lv+L1te04VnqI" +
- "JI1eRIDos0ygqI/u84V/ySnvUfr5/o6avXhuP26/+dG413/yfDY/hOza/3m6353D" +
- "FQf4gPLyckmNf0/Z+79v75+CaSQkY8In6aqSH03WX6Z0X9VQB/vFWq6C5csRuvBZ" +
- "nX9ytV12MkIm7FR+DLJ9H6IBOuiLogQGQ/eRgyJJAx+aYLFFoFE+nXZEmdeEk51K" +
- "K8zR4ejlk1Rjyd9OlGOU1IHRC4Twt1lj8fuDSl+toyn7KlPBdN9GfhbdlfyOpi2j" +
- "7n1z3jf4hxzT5xvpenii/OQ9atPRJOV8YpWSsyBkCMSKpoqNVJ4qi6kbGS0oTp5U" +
- "Ze+1/H5LYmU6Uu362dTHpJsyInEO5DvTRhC0noXDbUrY0aAqh/N252CZJLYxRLww" +
- "eDIgJvhTpSsrEJ4SVDvd9S6BwlgfShNMd9KmGrWk3I52ZEqkIKJiiDZgpwVrTuGm" +
- "0Uo/ZLXM3bFdFTPSQCOxHSpDGrWnDhd5Y05Lm5qtLILG02ERoixRXRkaboZjM9Fm" +
- "XShtFC7OcoJwLVrbJ2vpmlco5wxxJm17X2pWtUowXbS88ViaVfl1mbDdKMZhHFFV" +
- "CHEiCc2ed3C08Xm0T2nd6Uv1K0yITQlBsslUGWxQP4OXJVEfYPWUXA+kdcuh/+HP" +
- "wWUH7diyuFPB1lyF6ZrDIprJE4SEZ7msK+k6P1h5hh3qskj4roZNzZTZjCbg2ePa" +
- "UWtQoyUuGzm+j26e5Sjd6d8bPnh8J/3oPU17aMyljAcLyiBhr8j7ZOg/Q3IF/0Ta" +
- "f6XwNY0RdbAzegLT47336Ne7qtUughSk2m77D7Kk/viknCAADCufnfnmfRa+PuZ8" +
- "GbDsi+jRFrzw3ixPHSw07DIXufXiw4eHq9LyQfWZnFx+S0TQXRM1QT6QbNSZJj8m" +
- "7UMbjp4V/ZPnp3lbJ4dvxkSfH+zJaG1+r41D+t7jCD0giVFEsaiSGe8yzuQcIPsg" +
- "7JTIOFnT68Mlm/XtHO4/DVboellFEFwpf9tkkmQRHs6yXoRCkuKPxU4Z4SueGdIi" +
- "CB3cE9RKuhrCdlwcyTChsiIXrJwrTvs9M61zkDIsOaTPnYckuRlvrVGxZx0zpzzt" +
- "8L7s4WtdLbRACW2FaHvN2uU7i5n0qt00Kgy9iK7Jba3/3pNiLNMrM1XhIIBPZHET" +
- "RypdGC5pZhk1rtje4i3zM6TWPeYQEE2ICad2RgNnBwoZOXY1T9NwigxKQAH9P9Hz" +
- "7gx+I7Cg/gWYSkB3Ml8YRVoO+7qZcd04606nOv7+wkB9/5D9dwJKJD9w/pOUxtmf" +
- "p+39YZxm/5BaSsnQxtYbRsXraiFwqdRNWIdK5L46DjXUSMMKSKJGX16puhl1MLFs" +
- "NjnoaUBMXnCJ+Kus2EV8F1F0KGG54HeshTQt8laFCKcUvV0VSQaPOy1KydMvj2Ez" +
- "AewDB4P7DzDchscafa/a6vq62dZRm3G2jIrBxhr3MevBrYhskfQQhIEa0BTQhzBU" +
- "xFWQUuAIPIiFQc+2IfQGI/BwLEPA90bT/w9O6Hlgj+ABZZYIk4UKMgIv5BFETg9o" +
- "QqCd/YV/CKsIEgWiK+Iqgr+QaKBHSWPIIpYAYOlqJTAzWgXcJAWQkSQfBkVzkTkt" +
- "EBuCK4412dduYOlRLbTkd6BOG9mJ3lkOMIivftOjRKpUQ1n8N8AXRv85sESi9I3B" +
- "wqNAL+SbEH87kA4Q0iLxfAXQzIiiJA+Dio0PfHBFET4KwoGEuhuF0X0+Od6iPDZB" +
- "vqe2ZbNmwwwQNnblG4ZREfEADnQldENc+vyD2hPFPDVaTmO6ErcB2CSrJHawjBeT" +
- "Lu1HHXecOXpfFifajXzf803to/li3IQraCMnXE7aNaF+UhNCJJ6bST1yCMSEkvrk" +
- "EZsiJnq9YnIRyfoE3qs1+5g4qCjgAB/d3LXII3r+NecgG/A/EBhNc2cEhOijxJO0" +
- "FJewHGBzK1YnNiLkAPBkUztU2GMpL0j31B6VEaAuiEtObw0ViA2Qo2CQrPgdgapv" +
- "FCGKU5zwAX48rSmSGfCh0sBAp5Vw+mHYBmgyfBvQ2gE9Qiw2eCK950Urem/KrOD7" +
- "tAApA2iLxtGRmFUGVZgNFMIQi7APICVtlUdVP5fqGLX9TEJBSYcWuJiEgyD+whr8" +
- "Qt4j0BCvhFy3AUJAHpE2ATCfY/XP0YM68EHwJaHTWChL8gPdCT9IoJW04ShPtj4h" +
- "rXUO1N+9eNBzh958PwJ3onum3eftLwTIIDagDw+o2Baej5qT77qlol7lfPlQODAr" +
- "7Qiue8ErGKQIVtOQ+yuebQ9jz0QHR0XSF1f1oB0wm+nhBsV5Dgxx5TjC7ifRJgWQ" +
- "JQKDKZ5QcF8aA+2FRB9siyFbQEtXEFsiyD1KeYp4vn1kdk65sBN3fx5t3nO/Y59A" +
- "R189AT77u6pOAXgcINOFPg0rAnT4ODvDpDvB+Q6AjhNjrJ2a9VBRzOAGZ6eDgd4b" +
- "NoM0UeBxPD5FreuGt6Dwo9RFdb8nAiAa2R1p49xif5Sm4cGGg5x+6ZreF2MUxiIK" +
- "+gryR/PfnDI6Q9Gn57KlMJ5766E3pkiWtHqD0EedIKlAC3QaBfbl/j82SCLdu7yW" +
- "v6Hmk/T9Y/qXglgiQ/aIREU3sfkhFsOhToBSbFaUQBrYeBo78wWrCIiT9D1wcVo4" +
- "GjuBz3joxqZU7bQDFwmjB5e74MBLoK0PA4QkclbwijNF7qEEoFkFRROi0IZfN0sI" +
- "zwihRtDz4T7ibJnxZdmKq4qOeIUAbh8KmERXb9nKQ+5QdzgDPcJjvxw6bZ3TBIWY" +
- "SSeN4U3EZkhKxct8oIiTDi7lqOt3Kvi/tFCQEsImhN98ZBnWjLEBK6dw+FxgB1I+" +
- "dDUAkMR8mm+NWReOPvBhDZjk4boMpjxoBGF5Lqkt7tL3kyTUNCK+PoZx3oUqB7h4" +
- "5wEXO/lduTg4NfIqAh8ZfJSAcG/jGkuHA8qr7Ro13OwIJLia9u+yBZ0dicUAxwCA" +
- "kEDreMjHsNGLghIQjFyrYc98oQaGSKediKrHfuebY7DkhSaKvv+X/oH7Ij+oKSLw" +
- "2kgfoPv0+vpfWeMjRqQk6L7QtAATi0oNZJzgYxP1w4HgU8+oYPhFESAjAyvt302e" +
- "CDaAWgGAh7Xub6oUY6dMeNnQh4yl+Nm1AA19panR4CYHnOGiidVdfdsdGvhv6Zx0" +
- "jjJBqQawcqukBR4Ux34pXobqCIL3lHdgOad5nLqYjUZgE4QvtAltbhvPRFES+goc" +
- "QfyAkiF/e4WiKYNUIFjKWJZA5fwJczRRibFGT6zCHofhgW8eydxvZ1UFHu97Toow" +
- "8FguNJpiKoCc0GQAn4ceHt3K0i1feYVcihrJaNBCZJgh3FO6ENqkEW9eLD7vi6wf" +
- "fT7OU2J7Zn4VPfXdnohaADg6HCzQSKlLKttUpsb9HGGYyM1kdbG3LRyKBaAlAEQi" +
- "6K3SwEpXNuY3BAQX+wSMOhQK6JuJ9BbiQxBRmAuim0FUeeYULAUKioFQBh8aR3Mo" +
- "71V1gxByA7oX2gGDQe8klFNQQNSjx5kWPD8XwbJrOHhrmPG1eVz2hyCeCzw70QRm" +
- "PBaXfmHpq4d6Cj30CwL4FmzRhVE1Z3PXGd4oUT3RT2fXIk3Tn6hAxuw6R4ZKzAfB" +
- "E2O4JIhAk0YDAlY3e4AHkEgAr74ycQwAnQW7rtlcpF6JZA7VNu66JrCcgjUCEFCE" +
- "RpghIiGj2TWA7EMd0aiCjpcIQOLL43hkAKrIRD57bdINOGQ01LwiQc32iwDYCMaA" +
- "kHwImA5vu3GtiupPVup02YPe4G+iICJJzomO2gryY5W3M5zx7DfU8YCDsEXiG6zV" +
- "+xuOJIG8KOYoQjJHHsGD13J0uAvNmGVfCbv+KJrzyu7cZk07DszWZjii34Z5Oq4J" +
- "YoGxovONSVdyqdDaiI5o1E9gZEO+MOknbKrd3vCGjWOSCrnI7Ux2qgrF1ozkJ12i" +
- "qiB+Qq2iQl6eKyIKevnnG4vy6vIfKJt1EpCX9n+P6PQpAeBRKJQ1sOYCWlkXAgV6" +
- "zM7YJl8sa21D2vb7geeO2SpmkzN+KTwlzt0iohA2AcDPLw1FWDBUJvFW9ggVk6Dx" +
- "nW8ShTWwRlT1sHHJyMsXFDhNL6q7kI6WJJzpELbUQNVIhmsRVy0ajWqqiK9NrXLa" +
- "rEhagikVJEOvbHSFh2axoim1j1bJkioWVpJnTIwotJdInhXvflf6SU/PPQX0bTPh" +
- "CdsP29ywEL0SWUfTCD7EJL6ETkKMZq+XfvOV9/V1w3yP6vw8Bs00Num+z8M7mbcc" +
- "Nyaf49zDIxUaQ2EvqlaeEBsxpWMXnJV3xw2Tk85CvjXKxcvj69eMUfMr8bW8bRbU" +
- "onKyW5YZYTLbI2sO+23t750Nk8klcxbgYLeIcQe/QCQJFkWj+oMfqaThzaIrMI2P" +
- "7OfFp/TvReP9gGjSGXxEeEVFAmDkEvv9VUZSkBPbMF8w/60D9GpeH1QCFw55QkLu" +
- "z9IAXDqKnNMEC9ziBCmelf4wfDqr8bOBhgIc0RJII4qPuV5Nz9AAJ6ARU+oPi6hT" +
- "+q8gwvYgoidW+M0fbI8rtLFtXO8iTUFlJvXeyFxmJtnkC7zuiaT8nGztzQSqBLOU" +
- "ovW3gp+vzfBxm7PhlVblQM2bd+/Rh4dPRBvEDSXngueiAwyDAY7g52aB58+eG+XC" +
- "rEW8lGS1QUeWOAT3cakjvwRHNevLrWRGxOBmTNeUHz5BNT4o+AkxZAgM8CgQuYt7" +
- "U5ikqOco13h+zN5A3dAfUbWApJdeQtkMkEkG1iAUlofiG95daxu0Xul4UwF56lZ8" +
- "3m8LyQBioWOMnxAZw8H19FHnTZSfCQ8UKukI6IKbgi2EROEVBFDkVQRmNCWiK5gK" +
- "gjqIqofRAygkWCEQQOEBE3AUBUywFE+iCoPxHKo4qQYSR0uWSDgsC3LBC2FUgIbA" +
- "gEIgr0IFBFEV2beEGgOV2VCEkasTeUI35YWoqjQQJBJsaVFsgnIIYIegAZiYinAC" +
- "KCHIB8L9aSU2jqpgHDRm0jioEdaHayC8iYiN6RSgqyRLYbpYJZUhzsQdYEVBA3EU" +
- "HoIwQQ3BFaiKBRPagNKp4YAbiYCICDIIOliTxeOOGnL2EcaOMNDMGJjKNGgchDj/" +
- "BKwYSZqRlgLQR7nzcAWpLACURHNK7oqAsUjajiiYMTUESEVX6ICF+TFgwSIL3tKF" +
- "+9aliQFdBBB/IK0AryCL37njuaj74l8yZNHN1lSjgfcTgmPsJRZVGcrSr8IEjldQ" +
- "KtmKapHX0QlsIki0IuSRcABgN0Gs+4HbDqPIFBxJiVh3OSukGiQvd5nogLDQRteh" +
- "2MyW2SI9oRhikH4T0jXdxNxJF2Xnskl3AVffHjA67x2y8y73Yo5mAE1DhsMmXJEc" +
- "XQigaZcogCwOAJSmvkK59/AZt5r6CHoKYtZF6XRWBxO/0HFiG/lmwBS0IXvAvwXw" +
- "uNK56cJCuiEUIhAnVsVC0oQ/LDomFtpZXfIu324pRnto5FdNUA7OBqemCvdxU76w" +
- "rnterFGPG+6Q45tXnD6WRacT+nbNIk1JCPpi9vz6KPo0aWTYVCFR78pPNQgpwlQo" +
- "7nZl96ldo0qhd6oAriD7PYX3YjYi6+KtyURx0Dh5o389ggNbU0B+KOiBJNO/YO34" +
- "6a7wfKK5PBjVqgozX5yrvYe4b+g/eQESyAJYADkx6QeCQZ6hHDToVxoz61c19ymI" +
- "QUB4ySSEGSTHhMs0Tr7Of7v5ZHrYzWRqmxy/D2PVnfrHr7nmk6vMiLt6Pfbbft76" +
- "NqFfrnncwD0EdL8qWqmCRcAGdrsAgwQV6XyemW3csQRzF17hRM8sNaA5u41TovvJ" +
- "lL6Jmj0Qdj3rXVUPYlIJEIbMcN6Qo+y6+Gy6V0pk2Gw6o2eXyfFnBOzAXCDYADzR" +
- "CSnRaQYZ+hwQZ0h7sXXIQK0DQwbFchiJ7Akq/buuqEJT+FvwSPhCs1JX34emWkc1" +
- "+0JlH7mgV6fdrze3n1BaU/HP0Ip6Az60FlmH0F+FDieRNSpsh3JnZieg899kMapx" +
- "A2AgedvbfYhjt7fwdfgTf5O/lUCeRAZEpJHwvsvi+d3wMBEna+Z6+GGGgCoek/BW" +
- "dQo/JYryYiLihedIULrmV2fAYIU15yOAfqwHuI8EwYI7aM8kO0X6aYygiiUvGaA5" +
- "AqKrb3bLK3Bu/ws6awNQMldRV/OihvSGeGuLuQ5zhdKQyvBbunGHiqbSVBLCBBR3" +
- "sJmkCunDAXHHd4eQxhEGRYdBzZu7UXXMiBb3M0jRVaMN1xw04qyJ8G6DCyAXnHwZ" +
- "RDcJFX32jyXoosS3eitAOfuZFfqdLyQBCCB3aIfY2OMhjfbVA5gUvI4NI0ulOm0b" +
- "1FDfrFHR10hZU+ODKMCViSStxuklLxyrOzBrvpkTD7nncH/YWN/xZ/cWB4MEWMjo" +
- "uNq+pDjINyCJIMft7GzDNPmQMmfKO8C3BCupq3ah8aC+3PLydaANlYxbybhnNhxC" +
- "RTyS5wfe8lJ5C60b3pGVdQBEF12XTIjMtk1B3sJLjW843JTV6tmmB3szzW8PCNWR" +
- "3yd28o27CnITe6LTd1rriEPv+r+W/Lr2jtO7uzN3c4O+Tfc02jcUkrJR8QctADA0" +
- "gXSiA676RwOkRHURdCHLXIqelq5LOSTVlo0mrcKsbgjhEjApzpaorkBLDgWikaMD" +
- "WBmkEQLF3ZzJGd55Vbo6iJbSXTzOm0HEagBiaN6SrGSjgMe8kJ1BRvIDKb2rTVuv" +
- "UjayCQnFgki2WkEJGRQCMRewEqK/x1GDBcgGSKNrCGtI59lyNKkdOrQ0UCJT/tYC" +
- "QsXuKTErgmB/L7qWQAgjObGxtYRpoNAhObSe0Yb86I/8koc5eNsi+mHWzWtVmg20" +
- "+QHoAlFmGJHkyHlQ13uGhptHj5jDJQi8LDIbkOBvKk72hX8sJ7ueW16GHGq4y9iI" +
- "j3yMYtSIbDhrWwlmqZXVJRCqouUAUhKKoGCwqjpq43WTfM2qub+jk2T4GKHeyOVj" +
- "tYdlk++2vs+/+x5NvlJOLPYmGRLWSHhDrPt8vLxjo69Xl+W2ESbJz6o+epO91qFW" +
- "HfEcnfU/36UAcqgbZ7xi7DdKjmP6OdAd8+vBt/QtBnxhQ5Y55yjps21VoCjTyYLL" +
- "1CSAQTQgB7K2FHCvBzdvNMXNbRQpcZKHabwUfuGc374PhwMYpCQXoDnJZi+6wEgi" +
- "AiX71dMRdTfvYRIwt14Tk5HPrJ9sRIYwCUOkZlDd4TvtfPdgHxB1w21pzT08CJyh" +
- "7Xc8oYd9ZaSpdBvqDRYUDhA4KO7b0HDw6Hwa7XttFLJvwUIDpRXAcDIRWHS+aUSz" +
- "xocp5qowJUFyIVcKHx7WHevE5XHZxO+4peTzkklyu0YuiXbLEIJQUcsg9pabkI/h" +
- "od3gISwZ4fwv1Xzc/OeFHgwtN7OIIX02fD0/FYKloiIWHTB7PYJwBsz1ERDlrZJE" +
- "YDEhYassKO0HhjnoW2l4pHuKoFBPAi0IHcnEsMNIUlBMw4wqCkAz69wRdbCpCqYV" +
- "IiZOnuCR9k4a5ZjWNKYUSxiFzpNQQUVwU0iIm9GbESmCr3RFQr1Uigjc4jisu4pJ" +
- "puPoO5yOeZt1LgztDDSQtUkU+DXS9idDpAhOhoTBeU7AAikkj6CLUxCIImIIc+BM" +
- "GVzqBtTlqMISI1Sc4AgyKiD4gcWAivyJqEowpHETkhIOIUiJAsq4g6inSDsxKRWg" +
- "Yt+3owIGgQI7FgKRip6JhDOMYUVRT0TqgKJELhtSrt5BLVIqtKhEQLggZJ4QhiQR" +
- "Gq0Cqrhtk6wQnTdrZdiQdLJbBMJNwoI5yOuHOpAbHCioJ0J6YhibSGY1HllCJmB4" +
- "jcrMaFD0ewXkW4ejjFIZTGKo4JHcpSBBPtd0Qxs1vmR1w4jyA/Q8IHSlHwHq+Ee/" +
- "WKYiGSG4HC6NiRUCLF32CGopcnwE7g8WC7D27ysTrEzHoRC9BQyGYAhkqhOQBwpF" +
- "wUlY3keYQrRXorRFPA+GhTj5pDpAE7BLgAlbrkDpk7XdBkMCe7aC56ythMcLyB5M" +
- "qB1IiizVK6jgSzmXFAgGIgqwIgA6EtEewNxEDMEKsvoUzTnlKA5iDnmtY0XrFdi7" +
- "oO1avSIz4+XbDYhpYNbXls12lualldWW6Rmvp3XiSn4tr7H2DBIdge2UHx5TmHNI" +
- "B0iD6NlFC9gO0A7Si+DLWvYUsE7DYKO6BRETeHLcg6SAFuaZ2hO+UAetihqZiOFA" +
- "GI9nCa1gvgaJXoNNThLNEDOVQpTOKJxUxb7ouRUN5KMOSuV3bdQuokVEdMKFDQPm" +
- "AmkMhmx1/f2bHBC8ijYJk50C6E0XqgwMJ6K9wOKaAATyGEoaSjjPogj2CyAOQRZk" +
- "JxFQViYRM0i+Ei8gAZiihW1WUkg7JgoKGBijbIMenRopoooFjRhdB5EbkD0B3K05" +
- "69Q6zqcbkOM1FpwnoGyJMqYsuqUojv8cZ1sKM4tO5+rCm9ZZJCE6fbttA7APREM1" +
- "9CSIPRp816UCN9JJBPsHGQVvYZdivqFy+EDnwVAwp4cGED2KJDVUXA7yrAlwDiMK" +
- "5xTOPCYrIplcSlucCUpqSpZoxggu32wzjnF2FlIidoAllPOFbJzD2SICWniGwEiA" +
- "3QNDcV1ngXIKepNW41sRWLhvPSg1vwFIhjFd0VnVLBR9WMhksUIIoiX6b6aI6gwm" +
- "eWGTazqFhRbYz6BwdaC+k9L6lESGVK0KgKYufORB0fYYzTnBemj4BH2gEaHaaIrv" +
- "fxwDWvTnqdY6WgKUpgSoZrcEXkiQwPFhy9jFIQUORTJpUAFrhENwKQV1OLa5FQdh" +
- "FEEkFVhFQCQVCRUlRhtibMFYg7DmjWQ0vBThVntDVh0KBEg8z0VFZ1dnlwvOxCyV" +
- "yFg6KORRzKtb9eVaU6PsPpQ6vqCxMQymmlu1MoOofNGJrbSJqCnCG0ZkU3SmgEqj" +
- "ljqxILxoC0NXXqMYPKZsTNGgseiQX1Um+tDnWCzEFM5KYaQwiK2hebBFtFvWbIKl" +
- "A0gySQIKEVUFY1qkKQisEBDEYcpVOMqLjVHCwFV4coAKcGYVaniPIi0IDFCEO6py" +
- "iK3Sb5QtwUTkeVRqSZvgtiPRiC9YmOGphARNmQ6kLF5Mm9RN5UknKirNlCkLBMDw" +
- "LZGwouEWmYel0VvPJk0f9vqDgB1OMRmKZKIzWahOGd6NWRFAnCIXEL6B0Uc2fl5P" +
- "sIeQC1FobsyuXXTiCpCs4yTW8WkdGVi02BNTSDmtnKPWeq9Y4twF4gEpDgiKRGKA" +
- "rATvQoMREzE7FMRAK9ixd+aTuQoIDMYQZSoQTcKEAaDgwLsSRHUTmeBlwAjqJW12" +
- "haMGnPdB7Rko8t7UYLQRAzDoHldEqn4zfIlR+ahTFDj40bkEs7N9ubb1r5Pkz4P7" +
- "KmacMbzsQ60kjr28eWZT5fOlM3PVqKOMRxDR3mUfp54ZLqzcSJorg+9hoxMGzVzk" +
- "E32DW2JtbU2qrPLpN5Xpxamjzu8wb1lW8jakUx6dIsLnCxQwpEzLzYbSCTWTEZrw" +
- "p0sG2G5EvMnZyhFFF5tTkG1AZohFJveaYcvskKd5SozIJ5nClUEHKNtLZSLNdA29" +
- "uDYo7sXxjC44bazLkkiHu8qrYzJnnJ2oQ08SqTZVlzXJN05fOLkVt9y4SAdhsUds" +
- "ETItUioA4xSCJRd2ihTicgxYcOnBhN2OXCLbNOTBhkqTgh2g0U4XAdMYmaJDRnHR" +
- "R4Lu3sBvFYojVUFkFCHnDpF0yh0wkgezuLUwW6maOnVNAne9DRbH+AAHETar2+Ft" +
- "41Wuaum2jm5bd3WKQkCQUMg9FB/ynAQTMVeIB8oh6CKP0EAQxoFOUgEEvm7+N6n5" +
- "WSrmuWdsdiR+nu8pv3szvUcbeXbM8Y2rYHrC4l+zyLjDfmIMYVsENPkK9m6v+lyT" +
- "5D1f3aEZuONmS117lX6NWkjPZo21sYFwu55fns3WZHrU9bIXYmXLdyesJJhtZsyP" +
- "8XuYeY2qPLzk8i2eMXprLlTUee8pZwCQX5F0LaW8MCu2YWI+FoVCAHBD2BOl9jQc" +
- "oGoiISmkexUTRuFCkqlW4ITOGyomsKYHBjZrY5wncn7k8ejM3ET0XYlJU8VglCrh" +
- "D1mEVbUgnLS6ENcMUAAwOwooznxlE7lPuAKOBPjKFlnYC6ADqLSrEfFWgZgi07lQ" +
- "JqzHsmsUg1ZBbG7lW9a5qOWxHURNRDgomOIhVc+e4RuBqAVWjExp9ZXgMJ2l+KEV" +
- "vOwwHQfplT6irimoKktr1mTvMn1AI6Nj8IOjnF6dHXSm3bQx3SNAEqFigcKwa6F/" +
- "BubLQ9vcq85KsS6AydGpaE6qtgkARpz1BKuNSoGBOgBQ5A1kBa73YHOdtULNUiHq" +
- "pDygDESZngsBXWfdQdUGGBnhtbsFzJEXO68eFC4N2M3gCnwhLjo2sgkKuQ/2GLWH" +
- "g0I67776B8O/3enHovnD5QgD5SX19KJhml4fQjZ7+0Q5JZrA6YidgWYyY4jl8xSV" +
- "sK0myHtg0AKidGTG7nAv1K6y5UVikEpJJeVcrzdb0hpFKVRzLlSn17KMaMkjCTLM" +
- "QQ0FPTr0SQkXhEVoyWhvoQ9yPsIB3yDPeHXPwPw9rkIoDOGz49jxbEtALl682Rhs" +
- "0JwxZeyKgGTMoB+YAhZz8Qa9iOMdcWRB55QGYQwryLwiXDkQLgYR9ATDOHVU8lId" +
- "eOvOCO8PhtQKPJPaSS5gH9u2h8QPjqFhzWX1iUDkBGGRdQFORGvidcljOQQDzVBl" +
- "TGG2UR07istKQkPDezFCw0PURkJVk1fFtUDEY3CtDUhqIFYmbk+TNC9bRLgC1B2Q" +
- "hmoGNNdEXHTlVNGEVIJL1zKJJcvOiDo0nuITwMO7aogoMQulp1Uzxq+a5SU07uZm" +
- "vE1CJnZZ70OyN16aWcbe7CfhB0W5dv9C6SR3sHAFMHzkGZVhljT9BtpAZFGb0IBh" +
- "iANn4yVtUWWNjZlODZOyQgvvs4J4XQtR3HQo1zIKaCGoA3MHDeDBQRyGSIusq+Iu" +
- "UOnPeNgBZsMVdUK/MA7M74eXN+cCMybrgKkJpI2AViGsH9t9NE2mTXEAH2u1lnrn" +
- "3EhxUTGqz2uqtiqAhUVEQ7IFAI05ncwTfKHWxRzwOqtWiKznM7zWPbVzw4j5iIaD" +
- "SHW84UBRM2Z3vmt3R7bnF9KAsRXK5MOIWdxy1IhO4yIpyYRjiTl6klPndDcCERED" +
- "fIAlT9GeQO/FHYQ4IvbAcQGRxYyPYeZewWBoEX3dzOxpl0F2A6Xk4RptVObwVYvR" +
- "JgUdJSoUBw0WAB93YAWGu4uiaiu2D0oQ6CQqYz2svjWxM5GLngT4hPu9PIny6IsR" +
- "ZwrtKctQEYHDXdoRqg5oQ2uSsX4bCJ3NGGNxFpY9K9jfyTMPt60P9tHlUE941bvY" +
- "0CWQSCsNUdyq41StOyY05v6ryYNfhWLruNAJjmG6yfUmfUshkQw5BAYqlskE4XZZ" +
- "0rCcTJIRvQcxBsbodFNqdCpMhmSYhrWBxkg7XIf371jehCbUwexm4dGgVDsU5gmy" +
- "ARYrMvjRHnRAjrEi0GYc5Y6OiwRdCNAUhDcJxjcBNIBhrUp2G6ndXbO7n1V1kivl" +
- "8XxGjFDj0HsLjFztVYhL2gQARiRjzTgeTHDnuVV3Z6EWdEVx3o6ECjQ5rCJk6KO7" +
- "JyyngW7FaBI8Q0m90Hkz6/HSOXw7wPcGEkM3MXsytQGxEqIOeR5s569+9oW4M1qt" +
- "CS6KKEewSrVVQ9Z2x1nmgZsV5A2G0sh3RXUp64xy5NrrMXvw/jH9rrG9Vbajixah" +
- "aXPO4PyEx5aentlmgg3UzPNcyQmn8jm7WpaxrIJeGcWmiyb2JVHMgUcgNYWQZ8qR" +
- "l9nHMTRw3MikGYWca2t3QhhaYddzCOLk1SxmG3vec1U7jhzaLKrbNpl7cveuJ4GT" +
- "VKmHNOGIKDJJCa1hZpVTd9ddzdqXynyK3LQF/1fvHvFwDEEAgG7s21nIU4+UAFqO" +
- "BOzZXxvafGAJlsTLa0vUiRYNbsqb6jMCVwky24SylLvbtzhy4U047dzRIGiqxGqI" +
- "kIjQID2qNEqudsyoALL7RxclL04W5tQJ5QDpK7RHXccMSIKzBREj6ROmSpdaVrt4" +
- "adqfw1EQX0QzEHsCa660tktLxhOLIkn2OyUnq6l1++dxH9/n3L2c8+25+V4ffTlL" +
- "WbIZ6mIoWFkymTGcEwjhh9wUdmPPecx/I04eIAX8Pfv3s8Jw7Rz+F57P356BfL1E" +
- "2R485lDJBs/Jx45HbNb+1znkLrlQVg2n3Z3ePSJuR7bhMxd8mt5Ml7Cna2v47Av2" +
- "ShobDchLus/dr8YRijOCfI/aoS1CEk62/SwaX0d+zqSS4TLcKBNHf3WDoO6NgvqD" +
- "AcAR82hL32rdu4FRZaPc4BSzInYiK90PsiBLMdwBZzGeZDD4g5u3gUBylQUbarAR" +
- "BUBIVnQqbgplEWh9veEZod7p4BlUkk5VEijGEoh0dAiX2FHNFOZcC5CaW4XLEDTI" +
- "SgogmLJAKIqAY78+xmDgxem8eRwYA+e+7Gs7BLa59uFG8ZoVeVgy9USRkUkhykQ2" +
- "gdhQBuNLAzEGQWz6uWiSqgkgPFhL1X2+0eYLcIcj3iZyxIJ5vmkDHss1UAY9Kwmu" +
- "cUvi7vEKuyu0GwhCTA/yoyJyKgfHT7x1mgrpxkN4KkOQXU5C2Mg4GpNJatXYSKiD" +
- "qMyBxJCb3pESGxB3ecBzpYGNW/OquelOkMMQhLMNvp2CszyQXClDLJFNasPABkrG" +
- "Mqh3NC4P2iBrGm2BOkclnvhVhaRISz3tcWC4e3pxcma792AaxCl7oESlxfjoIKJ7" +
- "a2FiDuAweHtnbwXS5c7GQzEPRFNwEFkCQFcwLhdUKEAz2x8RGVU4dMOHfKVIFIhm" +
- "2iWtGuVMhENpjLWFciSZlotHBr+3aNL0JXa8XgqPAEd6EVpKnkMUG11O6XJWr5Yd" +
- "e1Z9xlu5eR7mJ0wHvDupi0w9qHg0QgciAVh2IX6IXeOlrntOQTFZdBawzrREld3j" +
- "PlFqXVGJkUYTNlohLiPDOszjjML0boQtWicWm1LQfEJgpwVZEwVAf1rpwKDiWeW2" +
- "T44FofGx9X7FflnTv57B7RWfe+Ko/xh7BrfbW16MdhYNV5PvlOkBqBZnJhkCwWXb" +
- "ALoENInGVVyEpJHrMH1FM5yhFxZi6xvmHQaSOdy8vvLlDQ0cip0Q10A0glmjphjg" +
- "AtXhh5sC2DuE7wOi1ogHvNgoaKThOzB1lxriiGCeshTQvqL89HPQ+io6J1Omxss5" +
- "Zv6kfi67wFWe2dNZFCyzJZwresuVNd9sV2RTnE5N7GjnjtGhDOLCGejhEM4VqEAY" +
- "I4iKBkRFL4BZuzJlfc28UAYvBA0puE6ZecsRdO8V2w3M1t4YGKaBMQ9gzlCEQ22W" +
- "BSqbwKaRdjkQHC4ixmWzxGIaJQxyRAxHr6FlXRHCtOM7Ur2KSG17m5xIKQuaUIjp" +
- "KPU4oul3DGBPUe9XNE5SjJ7usYsvJroDQcDTaLFrKnCLS1aqHqo1vSGEySRhymq1" +
- "0Ub2JdLjui5Cg0OgAyFwRzuTtrLIETnek84awMtCp9ESClI6GC70L6VcHG5I5VRM" +
- "DxkDYaht0wnKaDRTpUruQQOhrJt5eU9zwnDZsQC8XLboLBCToaxiPIoixht299g1" +
- "eAN4RdbBM3PFsKrg6ERTws9wPEE53AHu9HnSjwnUOBSNrBA70oCmilLYPe+DGDgh" +
- "6AG94FT/EZfpoKj3EISVg8QpAngqM8vmA3SBJCvRSw6yhCJNdyVUolCjZPDeXsG9" +
- "6bxkCEDL4kgQb0NHSghSvjbgTCRImOgQX9g5YQnK1JnCHQir06levMFKVYkHy0hY" +
- "Iko0oj33Fl52C2vKsBIXYs0AwtC0BAVsqkEI2A51DCQ4czmzpfPFmm+b8ANnSoK6" +
- "NuBO5JsE9wB54ZFkSd6awB68gOzx6BZkU0W41kPJp0tdlQoNWMl5ouXnVwAAOBQV" +
- "QtmwACYSMN8JJSXDEpDDXCxMzIoc1vtUCyI83wsQowQmOdEQeu+6wUTUVTUZ6V0G" +
- "BjiUxQLwwVYDEAdoXZoZo9PK2kLxhW04FenMCowg8QhwJC6ISvJoZdAMI4RxmXl9" +
- "WGpq1m5QDogASIegEgDIpUXcDP6wOlBb2oB2J7FIYiZ3rGZXNIJf2atRcQbYVDkx" +
- "Cz1D0GsdMvIO8NzFYSwtpbyZ1nGAWozaQYNERCAeNIRK/KCxiAvTnMSeKBcSoITt" +
- "OIamG40xIsICd7QGYq7g5yMZSfYIBjSC8cIthVOmEmzl5cjRRQSFEKnIqSKUG2y0" +
- "d4pDaUQkJ5CMiAKrdvrMLFEIFbQrfWW0hD7GB2FrFcwCpSROwIDjxYYPX3mjKzEA" +
- "oiIESUYpR3ygcvabgvYb5JsUBDar6xA08yYdnJ3dmc8KkH6un9F+sESctLBFkQGm" +
- "Ta0bPig+sM/K4rcNlicUhXGvkeO2yqSZ5oKmK7mzQnIIpTd6txohrPWxC+w7O7Xd" +
- "9LQtO6uqZLhzsHZpRcxYOi1CFignFLhwDuxorIb1rsUMRBHkUkH9+wAqL2aiyPoA" +
- "lLwUclJO0yK/pNNLRBkAgxgRJDowL+MDbn7aFmDs3Zum7TMmpl6eNnnKXjW+cIZL" +
- "KTUDBhEK8ciqkQeV7o9nO+RdjYhyConjMQRTBWmeLu3GkKYbSDZ+NFythpRclB0u" +
- "+MM9hIPy379/P5JvRp9K7Hh8rACxIThkR9bC/mjT79r7kMrZfL3DsQq9dPzd80jy" +
- "omUQ0MGQccce3Fj7MWzP6VNxLUm/pBuxmmyioIE45y9suzCqg25nIpkvY49evNI1" +
- "vdkD9EHHY32D6/Wt95wXiY14QGHv6Tupr4QlovqZsUxN/gppAOiLCJKKRQoB3Tq7" +
- "wOD2KVRzt/RlCRyIOQHSOSr3uh4krxkmwT/BsrQ79YvUxmCBsaLPe3BE9rd44cRs" +
- "EtHttA6UiBxgHNHMBs2t3WoqicOUCJ/pdOhWwXx0xzvjx3O0KVN84or1DOx3VbmY" +
- "XBKjiLHHQ6cosigwdb8KKicNL3O90EPY3XkwoBs5FPf48Tw4m8Z4osEyHXmsb2fA" +
- "Ok4HFRdQRcU7OGXaHlQhmiCfcEzj2hQNDNA6MRu4t68O2Z1CjKZpojvIZ6gSyZPH" +
- "rL9rdnsgo9LEDXNXd1XbuepmStaOYiD4/r5zmElX0N6F0Tz3VCoRv4sIsFhYUIgI" +
- "numbH4pN2G+IcL7ABCaNu1mNj6QkUIMAhtoR0MMPiEUwHvdwMF50hG8QYCTnhfkt" +
- "UMX5FQVzDOdATVLQbTBOoetSGcCjNrjgN51GgITFdoNWnL64lJHbNklnJKcjAsED" +
- "6LlEuu3zlPY6SEcibIy1pLUAd0IHMRZuIwhRlzAXsU1wRK4F5NYIkTsbgaGKAOrk" +
- "3mDdrs9oHE5vbz3eO7IwqJxcJxDru7DPr5kZnfTpXLnLVEx7eQEex5Vc10EW/bNS" +
- "/UN3fOWkQhgOwHG8e4Yi8HiGe47HhLNWwnMlMsrBHoa5VyAyXB8ny2xOvMcOHDgH" +
- "b3EqkrzSChHUyZmLI+6hu7wISKUqFFKTFWDllLromzIiucDwBOQQ1kp6KGChwrGN" +
- "IdiidKkg6IolNojcrO0BeJ7r7kxA8TUb1OsJ0DwXlDQCiVkWTKjwgEQoLqhDMXRo" +
- "Qo9pGorE3XPYHlVcm/Fl0ZUNWuXAbPgxVowsObJtykwDZmd3Rs9kF7ovtgP9gQ+4" +
- "ImoCUYDVbTqWeNIfHhQ3fcGSykKPKGvzG0gw0ZETg97odgi+CtWJvpYu2qwoTAIs" +
- "E9R6CGlAcEl9tTTwETIhk6KNV2KAPhQLimtCFryG/Hiw3nYgO3u3TfEJHQuFVBHi" +
- "QGsiLqgzs4bdm1MO8CUwBqvDVp0jQlTrbg64FHW97NcVIgioHQCAjzim4h2byc6c" +
- "ANEWA7Wm3xWoYIRbEHeZqnzzDMAxmjmtCjoyJRko4E6qJSoabUiR5UHY4rwkhjGi" +
- "57nGCJQGyYa6EIE1ZkbQuFKKxvM0KGlAUTD2PCxzTTr3sa2oAwP2Ie5M1JRb4eh8" +
- "NazCTDn7w1nJjXI8EDCKsUADgQVYSIv0oS9b+UA6gPIs1SOiIhCIbAeri0sZgp2q" +
- "Cjt1qVoBinB93WUFd3i+GNTr0BMoqCtDIo66aNKIkZtiCtBFYTxRAkbRGHW4E2Qa" +
- "wGELRMBSlDORfaNHjJo8HetTIRdgB0R/fXAbO2dWJb6DfUEsipYiw5A0GnF8Ezhv" +
- "GlTxeCaEA4SjJdyifLMm9GUIqQiABhBNrSrnBJZwcLnsUPG8AVmRARIaJRIAl2Aq" +
- "vN8GsE1zgnAAG4OQm/dxkQHKoewTW3RsFeU7RIFDvSeKq6tmLIwK8gvYW2oipkRT" +
- "wRjRc2uNOhMZYE5yw8o4PRldld0CRW1Do6zyeWGLAfbpCqPTGDSqcoJXE1eKBT20" +
- "VES/Gir1g0EQCpg7m5ZtoK5GATGOZsXKcwCUdiYw78huOate6CDObwFxCKBgXHBB" +
- "V6vNFaO1koc5AG7nTRtcl9SatzUT+2esG3qOOQchoqjI0MZiYEGiTyVZp67hPaez" +
- "0Y0m6xKBzy6R5ZAO9vJiMqshjhrIky5HVSaeZ5qEyNVLWOJtWG+4jGMGDZuXubu+" +
- "1BVxAySGWyePnaGc7uXgXUFUo7J3BHWdzfN0ndx97DRHhMuD3FIbtcmDu9FIUiHM" +
- "wvJzV1rl7V3DAElvIjuzuAN5aVFegjAg8oRCh3gtOg4EUlSNQ+g+YCsNL0DFoWiB" +
- "8GhSYOOE2b5zZHnFEUAwcmIWCMHBxMSoJhWMWrtE4EJmAmGLhxoTvSHCijrgpjFw" +
- "YaJ00WnSJr+RmC5jFqtEbUiI3kQFaXgg7vKLYF/fBgwaV+EnRk9XQKQPOgkBdnA8" +
- "kKDUtNQ28kWcA2LCiCujWK5nSsg+u2au4siUCIIuFgTFpAqiDAnZW7L63Tx5sg/t" +
- "IR5eMo5HINaaOXDMrHyG8ytg+NvLtlHBkBo9kRnrKYt8/qyVqWjj5VEqVy3GpUqV" +
- "hixKBqJGzkfhHgoFl/X1yrlEscB5vLEAKPAYyGQRirBKEZm6RZfA9cJGIMRHO5ca" +
- "CEW/DnIynaC2XohJQkB3yhFrMFq3qxHJ4+QOtEUb2wG1dJBDDTr2sZrvJ4RcRMbT" +
- "qH2Jdooaxt0NjDiScucKju2YzYaBBzvUkkz7Rs5QxX2gwjkdYD4UtQubOAigAFmX" +
- "wNXZ4di59KNNkgtapzDO5Ze1RNDg3lGlzmLiBgSsl48e7xxrPEEVA8DigDOnCoWC" +
- "NyRTfSavpnxLQ91Rqpqq7DJKoyD2FuCLkgrmASASJuqhEdivR0jzeV9CZNSuy7ox" +
- "U34bo3ZBM43NBAmhDigDK71FQEKZjWNaenQQjAhUwtFmR3diUG9KvqSEILrtcrnK" +
- "JYMYsRyZAMUMhxGC3SmHeUddC8aQDaajNAGHbXfMJnKQ3Io5u809jIeOAiCmGwEc" +
- "SGxFf2Mh3Ck7Q8NmAQs8MQPGwLfoDFgfOCTl3U4o3sLxM3kkQktElpUOIQi8KGes" +
- "JJoQV1lFdBdVKBU8i65cXjg3ziOG1RVyGUA5EA1Bz2PdlZvXiVd3sCFzpi7ZkuuA" +
- "okzCH5e60sadzfeQCtFe9t3jHrFGwPRHJzHlWiIzEmgstR6IY+MDjh98XwynDQJ9" +
- "BcV2odeecqlvFnFC/t9u3NHjnIqGa7bYikVnM+yf5vO/or7fvUJSIr379aG/2n64" +
- "/p2BO0/o9sxrOt3vIpd9x5yvc+etFPveVHuePsUB3DIaidl4CxRx010k46whEN0I" +
- "g9O0ug506JYDlFzQbuZEuMBAWvO6IBV8LQl756E4B76UHCsGLzEOHBSd+XvXk9WI" +
- "YMbfg56ndwHELY0vRDPXRQ99d6bL5OdJIUUzbJDqWMfi11tQANmXKblIsgFamLRx" +
- "GwxzOeJQdSQi75cWKugYgDTZ3sYwfDRyoBTFJzhNZdKia3kOBcotQFEQCbS2nCSC" +
- "TtEiEuncq5ywL4jCuAjum3CYQzZnvAElVp2RRCOSGjCgOCgk5JdEY3YqtbGzSJKS" +
- "UdKYzo16eoPENGLo0phETPJZ6OIkAK9m+kPCOQTXKwGmFeO3Qo9mYJjmt47wpZ4n" +
- "OUCpkBXxs5+EADfPu0KwMIEgyIE6Rn15vJ9n2j32MTvEFNRG+O5FKG2lrAqyh+Tf" +
- "Rzh4eWFJaDwsQTEaSEdaoYgZ1LlWfjUAeC8q2dWnJ0LQ8IrFg6vYcrdprGOfYLx4" +
- "1uAB00NBrexzAOhxEV0hJgfdnNpAR2yetGXXTyUK7POeMFSwUcyK0k54TYZ3BFZc" +
- "82vsHiaF0rspFEpTTqjrGMohOJwo131kTcrGNoxl7VJWqRTYNtAAJC7V+xyyGxzg" +
- "D6IYN9WtIiQNBELyUK0RY7CBDsyDhV4eNdSOX7wMOkXgGQkRysCNmAEPpdYUaOma" +
- "XGtvRVaKBTpnHMGXsHRzNvcHtrkV4qMS3LQYC7AFDRgeIQXw4+CQaigKJZLolFEe" +
- "ynETG9VkDEWb3PCLQWZvtb1uyQ9OCb2ljqdYeYVQUVrlhSmZCCLoCzeq3qihdKlC" +
- "FCVu9GdtanaDaeoee8Gh0XfV746AG0mFR3grOkNaEV4oAxcwugi+5mLavDgNyeab" +
- "aPNUAdaRx6GueEE8UgBraaEPEBA90Hd0IoiYKzzLeyC+QP86S24oNGgPN7VEZLkc" +
- "3KKB9yaO3suM7dsqIyXBAyaPJIVawzuyNy8Uis1TN6MwDW+Sc8Jp63uyww2NEo+W" +
- "pXWbpGdzmc2qkqcY5CJNMqipmJnZ7lPXMBYk5A0CO8LEGgRCLCyFEGqDni6GFwh4" +
- "ISrK96I0lzDiiuVYcpktYea5V0fSBQQ4HLSCYxVJEIpIEG1ivgPWGQ9zRCT5pzks" +
- "lUdNyhMqyFLVbXZ+dbaAL5MolnGQ0f2Y0lbErTW9N9zvnf1PL7QhIQj5Qqg9+9Ze" +
- "cP2k9FIfAnPPeCQEemCDu+PpovnNLGt2xn12fm+7k++eYUe5zI3I85qKYoJjmjnl" +
- "nmGtQxhZ8OrjWLs29chu705lyXsj00pO0r01isVaNX6Hs8cRtAzPRBUpl8Xo2aUU" +
- "RMFSH1bMAjgAzlpfCL5AHePjDzgQW5sEzApAHGDajlxaEJMRENKpBhNAm92ON0Jo" +
- "cKOslyv1CmpWvaQTDp2e7sgwMWOxFETVedrRILOecthi4+kHbXO7UCGYShLGHMPL" +
- "BFyJnklnbddyTMMgm68FBsVzHACN16/QBHAADr0hyZ57ivEsZjdscOB4MukOoq75" +
- "3Sm6oznxvBWSoYDs0mM85hVF3AUJAQhIC+IAnAQ0nYeBojTtDDu9fb2ZgfOvvEtI" +
- "Ir4U3SSAbviqYgJSp4BnTGwbatDG9A3mGF9hEO+hcZwvmsmKw4IUUYSm04b969eJ" +
- "yhd9UFNe3iSa87znSZ8uMCA9unXVOthwgCtrI694ULz3RAeRPJ0dGGH4cQq8+E1k" +
- "N2XKOIV8b7t0k3pInQ2SYhUaCSxLkRMIbumyj4sTVz8/OCjnFqV6iuYCrEQETZhg" +
- "aTaO1M91eVU+0dN5lIKE0hY+6ZhdH8xPatSu9IGjiSBRxdlYhnVgx3DM3OmAAPUh" +
- "oivOGZEA50UKDKlBGKmuKZHM7ZnaIrey9kZzbWmTBux5hLriaXv3sCjh3RSQN2Km" +
- "seQirWUXffY2PUwR4ix73JkV2Xnrhe5wc7ATvBMNCGsQ9s1jt3XLtQAW0gIAsK7i" +
- "GYMN4XZoBFGRARR6qCjNIi9RgC+TuutUGw5urUrW9IBs3WmZh5j0JAQtReBHKKCw" +
- "Ao1BYPjdMlMyTuA3z3s5HrzxCD7DNUpI9NKK1QCbU3u6DYiKaA7sOUSYFvgSL2GV" +
- "56raInCNge3z1vokDQ4oBA7DVZChDpWQ6HOcrY+5Qi5tmkDUUFPEQNwVKiIBqChg" +
- "igm4JIiXEAJEBKiKBIihiUjIdguH3TxtEV8CLnCZZJXuZrns5yGzNcQqb5nRD8Kf" +
- "Ejj1uLimHfFsXzlUZzvk7zxYPeGzkRdgYzYoe7Nc34mq1NfS0+Tpc572vBToIi+h" +
- "NC8Ksk0wShGEgp3jOt0s2159erxfPx1eTb02DQXSuDB5AkTVTpTmMjNgcOdrKEzr" +
- "tc4aYgDJqgdKhmhE3HZulPmAHB7632oFlcTlmCvKgosDR7ft7TOgZfTYJwR7AXuW" +
- "/S8+gIFeKNjkv3u7oLzAyBFiIY4bJOh4OuYdqgOIWvESJAdRUwkRH0TBzeSHfdN6" +
- "Bz4E9oSSCWPhUXvDkFmbZ2uSLokHIEKenMqeTFXgg3poKBEk9zF2SbQhJap4uGJJ" +
- "FC6V1rXoCFhRw7YcnMjkezOEULe98ME6Ds0IYzERWbF33DHNcyL7qBnaeKKU8Wx9" +
- "AYMaYwHMmO44OFPK1nebx24PdpQEPFOIOCGGRgnfbPFFecB7CSMybA7NNoCJdWkq" +
- "A6uxgQHTSlzjN02jfYhsKEJKfK3grm8IX6/ZCr04RBTyJ2sbuCdybNeEICJ26MbJ" +
- "jeDS6wgqPaR9ormfdmFDLWdBF0bbY2212EiKqJfXchQkdNNXrLktUifqXfCq84+8" +
- "Z6VhYN5i5hktLGeDvDyUvWWAs27y4SHHMOtg0Rag4RHHJZJzJpVzqEypuBMu2xKI" +
- "MQEgIgDMNB440aFxBiGgVIhdjaNkyK8RRKsepNlmwLGE3pI5dmBEqgxMdV0KaHO8" +
- "HhyQ2xG2KGDGNoGzBt7biE+kQ6Bod7WXByC2xtI4zTaLsEoGd3XlmZdylWF1alnb" +
- "M69mJMgnkxqru4Oogy+Ri7zgqVzMxct3GGZgXGSdkzJjhyAuE2PZ723DJwTyMnjh" +
- "l3tHY5VDpUieCoJmSC8uhRWOsIvHrs3IcXRWXW5dAv7/778fUJpA9gUVtiDse9fX" +
- "eLqjFjg9tC9YHmeTlFWicKAUpOimCqgEtGlSNGcpe3u66YHC5aNSJLww2kUhcBCo" +
- "sQJBzkAYmK7l1EZTiK2JEzDnWILQWZzI5NHO5yHsQScKeLA3Y1UxANcWcBcAXTZC" +
- "nG3WEshvETCEE/bPauJ2LcYYpkGUUtAj4AMoK/tv6dyS4In1VQtIbiS0kHqwagwE" +
- "s2PM5itnuLiqWW680Rhkknpn2RxZA/NquFxL9qJ+MWTj/aqbZM1Eg28nmVVm5HKs" +
- "lPLjlU2yZl+lLy2b+bKSNUYSElldBP7yb+gMMPeIR9GJowRgkgRoYVdqHQlwIDLQ" +
- "aiI6H1XmnDYFAee304yulhRgMIl8rODvjPsYDh4FRB4lS0XTd85zYMBdO9uA1XQj" +
- "EQiIrzFbmDjy+83gvNdxScSEU2bnSmgAjjhZ0eHKQtVyg3vI5fSCEKUQLGWCcN64" +
- "SoBE1gka0aWw7IlYUoJeMdqQ5ytWEITjsqzKm8ZQESwE6E2CN4IIUSEnUYdM0vGl" +
- "bHppfLXOIXBTSfWIgFSl6IChy+B0e4/JZIPYtHBc8xqqNyEaYZAWKNvfjpvJ6pXN" +
- "iRCGxlbePrTJreU3HXYA2d8CBSRKa51BpHeF0vGi5yH3vMvA8hjcyHuijgTurUuj" +
- "QcspGgZqbDJsCwLljxYqwh0UedgzggA1oQPI1qSzDKyyTLBusjazKdKbN8Mpiiht" +
- "tahHCFFJFECD5lOaLBoYNnSA5Vo0uVRGun3s3jbMCD8MAOHpiyBtrvGjhr1I4Kam" +
- "hC90hDDgrxsCgbMgmSDrjyPJSVi0W46roi+Blde3oaM85BCOMlkvxXOBKzLEV9tx" +
- "jdKcCx5V102vHRvAEBovGic6QBeiErtETJWKgpIgxvYmMdZt+YQ8c1CsakICg2WZ" +
- "YJ1wKg5NIYcsHI7TKYIG9UiK5Dh3nMiYQyjsFTApEA2cmsjhUIqrYHeoS28gi1UT" +
- "O+eZXGRAHUG1Gwk33qXWInhbyo5dSTqBDuQtgRSK2UpGW9OB04oooTkj1I1XpEzE" +
- "sEzSF8gCdoVyiYDkYCLfSn0SyX2hCQQsiaxSyGKpCEVn+T+7ACroi7X8aJopBWVZ" +
- "ZWHIQaTx4SNUeLDFSxevebd+cHKoaR+Uldj4hZiyxAxiEJPs55pQEVzsqkE5E3EK" +
- "C8Zrl12Z6ZyL3XJIIiYtC1Axc5KDSj612cHXeoDiFrcpuKKB6LCLGCsgEWAcjIYi" +
- "7hqF7Haj4908uyiAKrcawQQ5bsgLte4FvgR3kPuHtlEgneUBi6RqG4DiDmJiBIgS" +
- "VKzW6RQTsDZDRB7vFB/Npbn3thjxnOfz03l8o4iPr5vcTXayIrevu4elRUVaMYKB" +
- "TVWh4hpU3OBfMUdpqaMvN5RfQRHEA5SRsCqgNvSaSWAjxg2Sce8tmpLwQTzaEJKY" +
- "a7vw4DMq4BBwDCYqTySZ5Y4qUEBqrTyjRBdDSeJIR3x93G24dW0Fsfb52b53LqcB" +
- "LxkrVu+jOgAOVeWKSAPYajZnWDo8DQrwVXMRLreCHM8HdKQ7MnILkIj3MoONh0TW" +
- "CXGY8bOCBgAXDflHcvJbxkD4icpcbMiA0ObDPeZMm9qh4TsxeYSrNdsERNogpnNA" +
- "iWcLBMk3AFNaaFs84CFDeDFXxodhl7a9MyVyMFFD0AIGiNGCvoSCLqpw0errcmtJ" +
- "ZMaVMLAkEC6A0HNHB9bcXzSDliqUfebISAiIRkyhvuGM41wC0GZ9e14N0k1dvH2j" +
- "IIzL0HDgOgo2Teq2QOrLViXLanCQRVQkcYimjkTcFagkgFwMQzjIhkESKoRYDARO" +
- "OUM3MEMWezt6GgSuFhS2HQXOveJgcUGzsH1FZhnVaE8D1kRDjrF+riAwE0VbuVvu" +
- "Wx0Vo0Ivo3snYbRflxgcfJwR3m0ICx85dsSDvT3cZ29Q4CWGBQLggyCKEiARitqr" +
- "sNm0fTrW3Krxa102dakYpVhqwhVCrC2SGOlkRk1UlqBaSVYVJYN7ERi1FAbW+G3z" +
- "51re5VjVbm5W5UlbmrUmM9t/6/T6vv9Po7vhq+xJDxqrZJCSN4A9ebXxyczXxmoN" +
- "33VoVPS3BLDLLHbi5spPNZK0uCZvZgZzc23MBvtLdad1ruTZJGVJwaelJw113fR8" +
- "rnExqR0PrSFjAyjjVUETBCGwkwwK3s287kNjE+yu0Hbm242i5VRLlk0STTSgxaFK" +
- "RQ77zTcyWsiGy8yIrLiHHJjtG1A2Yw3W9UlzdFd2HcNCqkQgyani4Bu3NroVFnYL" +
- "2HzDRFdvTmig2HcOnFxATrA0TnGma3YZz0ymbsQAYJGBFbqwZSEku3x21FBfCArF" +
- "0wi6MyRrQQhzxXZCortLApgcocDruDxkuASSjkkCRHHVa1oVlDu7SymYTanF4+3W" +
- "eROwxPvSBh9NNJ8ik1JAnwJivP2b/k6eXnnoQc+e3REtcmUhKCgg9oIgj3cO94cZ" +
- "1/yZZPYXmLsEVzL9wyayYqdoLf7u7cMaiHlnOXVcjK1tFvlVLZVUn6CtS/Dc2MGy" +
- "jQgfhC2Kdjr3P4oF82DpTA7dJI8fmoIQcC1skeRzKgLQfdKJKWsxDeDRAOkVD1Uj" +
- "6REe5pkkFtcBVDyBmsYcJiDPKL4QYIAKg3pFBYsEheQysfqhKb7Z5Wjm10jpNiZp" +
- "B5IyQBQMUV05k5WF025JblIlxOjYPTSQS14ht99a4g4RAIMEXBQ9VYdUOnAHboCb" +
- "AM8xBqUidwUIqCaNuDndlLcheCQRzyDZsza6jpcC8J5t93uI52DOCUmxyBWG6xjU" +
- "DfvcQN2R3loD2RQpUCyjb0Nnj8jM44gOI4HkYOhJNFBUaBwiiugHBtgmVWWcPJ2v" +
- "AGlYg8pB1knDeEQyYzoFW+nZieSuAOXHdpQnYHIIvsnV62gW62oGOQSq0ZHQmkz6" +
- "ve09eR6+As6PaDEAPBAjCRxHiizSKSWE3lI8fDOCDmGnmVpNbi8eUVoBcnjVYXJH" +
- "Wy5Y+Ig8gsiDUDTA6xDbTXjDHGKyNg20+8AoKRpUzjVgeIneyymHNIhlOlRveBNb" +
- "AyNu+YZy5q7JQKKSSPDgYkgOZ54N9vTDVhqc6UhuwvCADsV5z0KRpEITXj4+mgml" +
- "oIZg4a71Zlm7m0gkdp4U3zAnK2iHrqjsxi8S8sDdGDo9ucdGhjq81Jfa1MiJSKcB" +
- "A701FV6aw8Hp7V9EURNiZNADwG3dhrhp2xsMQdoNaPWpg17FE8O8dR1VHRzpUzs4" +
- "oW8uITBTDYPLynlwZDIItG+CIpXe2AKuCI7Qs1rnC94AEyGbMuhIPF1HgmbONCmS" +
- "5k7bSMjXhXQp1OCjmkAGTvLOmI0HOAt3YzBQRFgqFp2bepbOC2EIwJLOpBSCVEHI" +
- "kdNxHOkAQs0VIpgJl4XMHMjEgid0t3FO8MJhYYXY8sERIghdxq3vQKeC72BkdCeG" +
- "xRxAiGkDGK5LYsCK3AWW+AM5VQaWqrkJ3NiK8HR0Oyaird7M0013PrNY4oA67ZPe" +
- "zuDTrV0oZMsRpR7ZipzQ1jzg4Ut53oN2DS2qHRF3Qms17VFoJ5zQGLHnTQ1WhcBQ" +
- "uEUTQhQjEQUHI85hT5R2UYC3twsue/zOINAzYK9Mg24cwzR4rXfuB43f5g0wg+ma" +
- "n54RRErdutOia0EPZPBoCriZ3WIjYiAiY9ycBy8PvV0fdNCtr1kSkUTFpWjZQ33A" +
- "Gh0a7ep6g4nkWoASDIDjZq/BgHfve9jgEEhzWCeQR7Hli6A20uwCorkhnm7lK6hw" +
- "1GyiXCVzPlIK80MpCjwRAoagLZOVxmZA+eBSGhCIL9tBXabrpw47c5zKNaAKO4sL" +
- "7KvUaVGgeYA4XSjsTXG+b3fBFtoGLhoKvIHohI5zzHSwDMUyPCJ8Zjolsa6FJ1An" +
- "5EizYQKcpor6HHhk6GdulzXbHMekayul6RlzuOIXQHGhtCOsOrdgh5yBUI4QD6cJ" +
- "CNmU1QYJoXJADgxaZvbMMEEkHSPshs7OGaJOF613Nd0CBj2PIi+PXV5W90bvAECz" +
- "SV7CKiJiGUeZErQbfUGQNmjhny5vomzEBFviHjwiiJ0o1E52tFzGaXbdCZ4hwwYE" +
- "QPQQkQZFRB5oqVQlVfs5E1NSQq6LJmIhqJUJBkSTmKRwxxBG4hmGYgYhOlbgcIM3" +
- "Qhnd3c1BbjEYvIhbZzEQRGBE2cgI5W4RhHpgCsRsjcdWFMN0olQDA5nd4AckRPbG" +
- "2+i25y8WqkxW8Wupq+jB2ymQckBbjqGGJ2AtMuBuG4BrSNp5MsuWwgXbcCXcIAxo" +
- "J5BTSW05do8jzcwVXNZNxgxuimapGRGRMeE3YqpoRFQVEB1gVMQgYxo7G7bmRDES" +
- "u71hcZac1QBCRIHe0LZAbAbHxDwuLIhFlGQ311uRlODv9YkCQRH+Eh/r6Q/7bT83" +
- "9x/Fr+4/N+xjJ/ef+if6dubx/+uT/af5yl/qO7x5v6rVWuWZlZjM5eZ/VustitjY" +
- "3HC0dHExsx/qOenTOnMdJLi6X+gqTDD7MX/BpCpmFwf/C6fg79fommh7CkD5icKI" +
- "rVSTX/Uh8fGFGKs+lPgrQH+bz8pu235HwdPyPCs0aP60bPSYwmirZ/oP34xfQ1wP" +
- "pnDAX5KPS23/G6nZ/TKCJiCNS5oIRTN0GCKEmhG9kYgIrr/UH+fx/tEuBL+6UPJP" +
- "b3bTrJphJ0Vu8PmOnIeyvm4J8dKtpVV7Nxk1Ldm7r2f9z6VbD/lVr/jIa0/ZP2/6" +
- "fsPJ4euM7/l/w/Hbe2qPmk4Gye8+XFXSsxt8HE/hOObeMcPpNPb7slXdTm6OZ/v/" +
- "5dVzU58rFtJ4e3yv9l6buQsjiD1R2Np9hTyeTt6+038W47SRy6PY06E+P3JOgWaQ" +
- "hHAkkR/Xh/2ncXif2afyf4Svf5NvY3/UP3JXCqfaxkZRL/J3CPDzFxNGAzKcQTnd" +
- "cHPayzzbvLxDd1UnVvMbTw9BywcPDfsc2zm/nyMfDmf932T7p87KrxgyeFftQ+tf" +
- "Cfh7HZyeE2aj8Ld3bXw43xb83/u3I6WSftIeD/xbZE/8bwT5H1OjB9vDc2fr8Q+u" +
- "397X9Gf+PSdnVOzpP8PP+c7z52c3SP5Gtkn9kn/w7H1cp+5o+HrPZPv7uTykTn4t" +
- "qMW5ktlnN5X7r3/GJDMMmGVMJN7siu/yfnqffmvSXMu6ft6bOJlTaKqp/L3k/g2n" +
- "c/7fv5SH4e7wSNdHTnGSe7brKd9m2+rfs+75c1sWpbaXqOkkpTo6LvZVDoKaaPJd" +
- "rf6/wabfy//P+Ses/dNe1Wv4P05eaf0Xg/vluP7Okm/5eu4+LJMnvJ6vyfdiuNK0" +
- "Wbn2ZOW7k/O5dVV1S0twqcn6SMKzp/2y3c5D8U7EssiWcxtqybtlfi2p2J1xcn7G" +
- "nI/NwcrP+tfj8/scv7QZ8v3tjkfXsw7Hk28PhyNkcPY3e7To4dLZXs52SnOcp+0v" +
- "BzIaa0rMZV/r4j+X7dHd5OqeK/l2Ng6ZCf3R4MsiMaozClqv621/Cfwfp/G2c4GO" +
- "dLV9XSfLMq1YzWaxrDFXxLOJ3YfCa+Wpzeb8XWTm+JzP+IICf93/kNaqLaNrWSqi" +
- "ttajRqjbapmqtpS2qxVk1bUlWpNqLRWpZqtJNKo1U0ttRsy20zVJqrG2wBY1sVoL" +
- "FUWJs1ikLFTK0am2RVFYUrYNFpNtTCoNYjWpaFbG0TKLTDY1RrJSWwCVU1K0mkrG" +
- "yUpUbZDVikMW0bZkYotZMmZGLRsY0KIViLGjRsUWxtRUzFiTQaisJEzIaWTNYIjU" +
- "RhTZsyUWxsUUlY2oyRsm1G1k1MhLM2Q2gWRRMpDGE0zA0ktFBaZGyBETCCMgSEaj" +
- "EWjaJKU2NqZFooxiokSIyMMUIWEaiMhQoIiiqQmIYEkRhFpEhYqSGCLFCKEMEEGT" +
- "9mvzf2fuM6SFZC4Qd9fugRia8BBCIvlh/UPmUoYBieRgSMiPA/zM5kG80OwWXxVB" +
- "kDKCgX+vVRm/7UQIDInnOZ/vuDq/4D8+p51Kq1Jw/kWTzvI4d9a7SyLfWstuvCsR" +
- "8vO+Ve9WpNJv7s7+fuL8JV+dboUuDPzER7chJZ58smGb6bfHJ+/wytuIdr6d7a47" +
- "bq+tvU9ubKTxSujpWpbkOGArKSYHFiSSfHgG2RPcG5lSlkRGbrdlTVFVeA1pC41W" +
- "V8XE0QYWbMrorO7DWTBoBRpgyaqKdSFItuzQ+QpmRRpSUkgkAkgVhutQk5vCYVVC" +
- "2pCBtTYcnZA1HRmQ5KEKUJCjE441UykKrp04rW12EaksMjEqCmiOKKAiIoVAjHHG" +
- "4Oy2vMLFphr2skmltbAj2yHto+/C1qRSHQI0oYJy4xPAK0hBhkBkzKGIDKfqR5fu" +
- "9Rb6jriPwFfrT57/BORRUS2uxaWe/23vw/VDRJUNDKbcoql9hR1STaoUKFJAhAE0" +
- "AZZLjCTR5qxIgYLhyUQktqwQ0LakMUoDZaYvf1dL7/UTZGZSt/h0bF8bOrkShINm" +
- "UC5JVQoULQdWFmExZOwxx6b/nrJEIzcATXe9RX4uAjQuZbT7+8dvCcTe970nE51j" +
- "cmac2WktrRIBr8KKqmFiShChQWsTPnID4M0CSyZe7rltE0/bIvrM+YcPthAH85JJ" +
- "219mY5mjPQZhiZDYZA1DzBlAjUcjXvLL8BABMGVQh/A/vPwUfqX/5kl6UGGJn8FC" +
- "P2GG+QceVRTNvxzts75paBK7NzM7TzVVUzlIqqif8NJKRImR08cg2cHrQWxKYcNh" +
- "OjnHzz+YPyaL9PWNrPR37fFaHr23fpcy+YYGWlsuQf4q7bXFjzjZ66t5DEnZsqLU" +
- "ixYlKiy0ibZsjalZamaizKs1laSpmk2ratltZbWSta0bazUrFJs0ttalazaQUhKg" +
- "lSUAqyQoWSKtotVYtSmoyW220arUsoo1tpLaNtMsmtaaYsVTbS2UtJgram22rCkS" +
- "qQSxISyQS0FSSyM1KaS2laa0lhNFGhYWigRULZFiyykqoCxFBKRFSItCrIUWLKak" +
- "ppY2WbY2tps1pm2ymqbabbLNiZojaZkrFMKZrKzaWVptZtppijZNM2SzKmmxsRab" +
- "LZs2K1NVqWqEzMlJtmqVRjVNZWllSVLM0LNNZpalZokSlltLasJRUqopUpZIElIE" +
- "lkqrYjVi0aSNqWmLKpslJtFRBbSbbMy1KoplRspaNlNUrNUaaak2mpVFTZVGxk2a" +
- "GTSWmzaCpKbNJW2WqWqKMmNk1GkKUtk2ysrLNs2WwyrMqKpqZmmmKxtmqayKZlUk" +
- "qNltKlRSm2StUtbLWxTNUqlspo1ZtltNKRIqGm0tlRtNmmalNGZYybMozNNKkxpI" +
- "2i2ULJqUrGyyxJslNGpZmtNSsrNWZY222yttmrVNTbWZZMms2lllbKstpmrNMUmp" +
- "KqUtptKyaplKbRSbJbLNplZtqM1KKbabU1ZSUAmUaxpZjUkhUmyZmxbRSltNsrMq" +
- "qVbNtslSptEzVrMqaazNpmkqZsxExpJSk1itlWqay1KppYopMUkkkmbLNlMymsxS" +
- "0TKlNjKbA1TLLLU0lTWalTNMilKmys2ZY2mqViUVKSyksmapVNqSJRqxZSyylMlS" +
- "yLFSWRUliWKLJPR487tzxPbvpf6y887/zT6h9UmfSx2PLPXLE2t67TNb+d8616jt" +
- "tPkeNmjOnd2bULjnN/5x19I3dES+7KaAHB8sg9OaIHogcFmowcPkd56v4UKiqJhg" +
- "oAU9AHxYiJSboAuO2tYkauzYowUsXVGVlc0nYOpihEKtGCELstXcQR40ZwxcKms+" +
- "7pFjCoGnlWDFSsNDI2M37zbDfLv3avdlnZZ+BC52UzTjZKLth+XpejoaOcVlvLIp" +
- "Bt0bICZGx12W3MemDI+BEABpXP87P4rJiq/on3ucmKl3H2qkVoDOXeBVIHThRlRW" +
- "oIeneSsFb5P81QBgJOLBARAX3nH8/r/f8w3ilqIGYIs2ETpWjUrVBz3ap+abPKWH" +
- "pLM3ltPx/+N/Wbt1NbzHN6yn49NkVXLjHsi0YsxWYxt0mpP5liJ0D/BK861JPxVJ" +
- "KrrKd1DEsjkf2fd+E1sqc+0G02nKaZP3/wWYV/JKhVSKU/9f2kP+Es6z7k/gUksW" +
- "JYe1an/921pBsrUdXyfSH+6h3N4k/jE5ItS1VTkajSXnZgf5UtgpKk2jaxZibyd4" +
- "83LeR6x6+RPw/T0lWWVLOy4k54wllqVWtTTUvHd5G6VXZwcLVpZCyOySqT/VUqI2" +
- "a3OjB+BJ/c5vJ17xaYezrA2WTu8JipWJ34en5WSThOGGFkqslgxWw1Riyit2TjUk" +
- "4m2SJs+3WFSYNQcR9lN+j4j1noP93VyHCfI7cNMSZzH2ZNRThulseIk/yU5KdXt9" +
- "v7zmbk+gjtO690cSQSoFfmmeBxfI+vqGsirzNH5C+xTw2WGGHE0X+u176U0uLoPT" +
- "OEn+qsbDvaA4s+lX8EqpJzPrH0sloeXR1c9OiqmXer0zgSe5ZrT6ScTDZPxHCbPN" +
- "0R5uo6u07SaTyP+1LS2qfontI4sTqU/nOnq3gQE3PlZlmWZRJYUsqyJ2P6PJ+L5/" +
- "D8Jssqnh8+u+2ca0nxwRAJ32knCcvhmYySY8DlHwPRZOyxVSqrmc5yn+vVN35FkO" +
- "yvNZM/ORPMmjIkxNtLVRf1qQ3ksieqJL38h25PbeROj0cV6GFHWIPN2qxXorv7Oc" +
- "ifauTZXzYwjFM+LPNWr/a58p5xuD9uXn6b8HdXj7TiR9vZIw7HVkmGI8569eqqvk" +
- "P0vhi5cxU9euWvzV52lG6lLCSmYWK8coeiN0jxImMiT1bT9FffylTz7SRs5vwq1O" +
- "E1BPxdk4PSI/RJu9WoSzsTH6v0nJ8nrzi+ITko3SqSvxOJ2nukqKkpNLHec/hfS3" +
- "JEnzWJ39PoktklpWMyyPh/0Tc9E9Kdo5IemeY1NR+smI8T/dPNYrc5nXv9t9sHUa" +
- "mQsqCq1PemmmTVTeR5UqqSopSlKWFOYaL87JVmxycMd8wy5fM2Yw/RXl8vbb5SVb" +
- "u3zORyjjG3DhlMKM111l6sSk+BAMLpSjqdn8I5U+moXwXX5p0Z+Ev8Zh48/wLRnq" +
- "sVOvKupu7tEKFfaNwYH8/Ci1xHTYAbREOEoEoBMbtSSnI7QnHvPpNvIrSaUlVwno" +
- "cA2T6JPxOc9Hjj805OqKqKTKMtvz7PuSa/Ze7Y4TXj0keaMVJIBO6TUtNbu22/rK" +
- "Ik20pV+zX62sR+LTYvA/nP8S/x/z/y/t/m/n/s/ozh/TTT0zNN8l832eeZrP1ft7" +
- "l855ZP0+7P2fht+Mct5xlvGpyPw3YySSq45XU1bSyrab5ycrjjicbfT6o/FPun2h" +
- "kqLVQZw1OrdGyq/AmFG8iUYmGjHDOy2YstLLBnKVZJvoZpv/dskjgWfX0jmmn+XT" +
- "9EpEKhcAUlB/eYz+SbNu4qNSSEC7hItGyfhotsOAf9SwdHA8hOJqR/DyaGA0EVqI" +
- "SKD6AWMbIK+iFwiWZNpCAwgFlSy1TRu/m2NnOmMXFK6UuExRVkRZMoar/6uXRP9P" +
- "7ZP87LZwYx0FWaYU5vlVTqmnh1eev7szJOiq4leaII1cL9t51vM2+LzXlfVqKWyp" +
- "WvCVPQwScjU2St+kOba054lwkpIqTJm2mrtWuoYNioqjXh9ZCcg4fauRyifOQnf6" +
- "SGRSfxqdVrKlWU2qUzZplGsprUmLRsRajVG1FqI0mwhqNsVY0VqNYxgASIkzAhPb" +
- "KKjCrJLVvcYYOJOH+vt9D6MOVhCbzFWO4yRsEfXvzBp0P+0m6q/l61TUNMPwDbP4" +
- "A4ZborpXA29kUhELXpos8r3drnud3G50Si5VJtefj+9ZVvVRlXCz1Xg6KThMk4mm" +
- "/BxViVUbKrUw0nSUxVm8OjGchs/DpN495AGe5+K5OvXzvbUNNMVStZlSc5ucwd3W" +
- "l4u1dm3WlJobdG41bAbKyodIBU0lRgRgW0aw1kwVrIutSyFWNio1Fc3UKqqpRju5" +
- "Aadp5fl5udRTjI1JPdwpAh5+pEn8lE/gwPC4SP7yQ/wfmhzK6WLcLLBfzaejXg5N" +
- "ROtJbDGTLY1NWSMQ3kPP8tNlbsFLO0khJHEnOD8iIBLHY5E5Vaioqq6mHOzViRnO" +
- "TJDV5noj3lYCpbB/UKCPiSPRFBjGEsHZXWOmMUqqoqjVmVmoGFKNXF5UqRqditja" +
- "VqjRtTTJJCSNK2SIBLIlcoL93JoaGmSYppju7taVJZUVshVKnwaD0EH7hMmp/h+o" +
- "Pbiejj/LCXLxi+sY57t+Gq/cILqWSklksgVasVYdKi3aLGlcq4fh/b/0JI17/hz9" +
- "I5p2kpb6oqMezcw1GWkqUylkKqYsxkpUqrKj6ahmlf3ytR/QMwpaUHB8iNiv9K/z" +
- "0K6HAP93CkfDPEO0tLILS0pZtCxDEo+smm6SnpFqPN8mB8k84m6eFkLPr2/b9vvq" +
- "30sMxTJbKbV41vETNRjrYhAm0Kmypb2ozMJGlqo0oyt7s1+ZqRGE5GDhx9HdIoQm" +
- "hH5pdOT8GMwPVn9cd2LOKocJYqpE2fJibmxMRhVjdipjJLKxv8lUwhE3F+9vM/Z+" +
- "96zDku8juRY8ZkygVpQhCSGE5vWjeiSSO8ZFx43qYwI0q4xeFMojCEBoYwhDwpBe" +
- "iHCkNkSihsIJhUNuES4aChQwWFNLDYrSqqVumBhK0xiN2qw02aBvWoQRkbNJJAkj" +
- "HBk/f0jBi0Qj3trasZSWJAABGGhpyETY2mx2GGObpTObWrb351Vt6QURN7vvOMuZ" +
- "MryvV8esvd69S9JGxrTRiEw0k5hoCqjCFy3INRaqNJwakaGEikSrNSYRWTRj019T" +
- "4CORqY4ubfHfS36+r2c6tibQpT7uqxK5TMRXftJ83l0OEKb1aVXy8jZKtwphii1E" +
- "32XPN122+997zbb3qg2rFWEspycmx5fi63iHJ04NMLBsItv9IBqEOmT9g+SGvcbp" +
- "+/hdEfGRojRGhaIFKIYxkBlxKkgcNtjbaQ3UpIqYgYoKWc8GtGtpwV4rXQ74tWyW" +
- "WrSqxFk4NRFSeaScu5yP8VExZEm6XE4chWxqNGXXVJkYnR2cdHk8WdGYy2vCmNjq" +
- "ybrMN1FOOcToskqqI6hQJYpkEaNCNn6FTLldFQjIRVoB+utwbXmdbmWEDBprGCfA" +
- "JCZRpKqRYfq2e+7Cq5cNSfueE8nT0BAAmYe3/Q5/hbbwssFCXp+OE9EkGFrg00fG" +
- "yXabHiy3EqpTo/Z9bfo+ZtPrQAuNWcI9+eSwSa/nYd7oXFadmUYi1ukq/ac5AAQE" +
- "7du1t6q7K4YbOHkbtuq8NNGMZw/VibN2MKnJyZJzVzbk8nnizzY8nI5Pu2KrwXrL" +
- "dm6nQ57aXMY8TsVyIDC5bX0WfDw+jTpp6QuEj7W1TMvq8Zyu9vdXFD+nVQXfaj5R" +
- "BRz2fkfnvWnhDIyYKVitWiZZUs64DB3WmYY2xUAXs0Cakm2Wq5otBR1e9IE4xR6I" +
- "UQ1xETvEmN8IlSLEh0Um6u2FSoE1m8LDpW1Hm4TFaGovlKmdEOVumVxam7bCipxu" +
- "T6y5i4+SRHYrzydyzSvjm0vMKixJqmXoTSKKjLRTRkxS7yrSDPFa3nQXLkJi0PGz" +
- "Ue3b6kGdih7KjMMNAjQzQTDB/OKQ8KFuO0yGQmIsJJJLKKGQAQmMosKAsZY1R0kL" +
- "PhQaaKZWN45u7TtPs7uvVu7uqsd2mxpMjs4adWm7k2YxhWGOTRjkw3YppSco2dSD" +
- "nDT6F8LNCzhHRwSHThhZCw/JCkWC0Z4GlllmHQk0JGWItJaemBYmSUfC/CzGtdOZ" +
- "glpafCCzTTeNljGYrTsbK77srM0abuHRsdXENonRVgs/PvuqzvZPJURUwfRVTFTL" +
- "HP5c+u4dT7LGDtNFEMwhcRariKthqTD1vPM95zBVA62rlBLfaioIouD1obsxmY4/" +
- "SLbB1fe/WE5wvNs4XW/dM+pCuTReSLHk06DGF0WkGUHXGlrLY4aDxn3fHt8HuzrJ" +
- "2+aMDPlI78q6bHxj5uF2TCFwbZMGRZ9YDJhIWy5Kgdxy7a9+tDiflePrabvyHDj9" +
- "YiBjKMXYZIRdTNJHAOT6taIRRhwL6k4WH8MdqdOHDZ5XET0kKmF2Bk/gCivPTwLD" +
- "D6OnV3Btj6vA6NAoRYdIDZ/GwT5X5/HRth0F6JgMp8aAo/b8aP0dVD3bWzoGD9jA" +
- "IdGjWJpqFEIwOEjh+nBfY8Pv9ThAfIA+v1W1zDh98+IKpRNs2Kmxah79W223bEUj" +
- "8FgfYebzbUyGl4S8AJvIixBOhDSmA2GYKhWeUS6ADRDvpmoClc1nZxo2BcF8lMAq" +
- "GbIksqALJKpZprIel0G/UM0/NROWO2EHdl8baxjfvVc1Dz9VKlRqHhPwoX/hRooL" +
- "hYtcLETvFJPN1IgE2b15FDZI8kftKHm25vocSMiWe502fv/5wLI7POSTnpHiVNkn" +
- "KN0f5ylSllDaC8/EnNMn8bMOXdHDBEkioNT/Kpjl5T/FSNstpVTGKjCyZJilljk0" +
- "WCJtTbKttU1vQ16RREbZJVRVnrJY8VbpfQ4jCfGExUvOtzOch1jTc+c6fhbzdJ+T" +
- "ZjocHhp7tOTg0hqFHEdpzHf3mFU3tGUGnq9aOgRXwlMPc4oqofnnzkevPke8ocXV" +
- "cWn5KA/wBIoOBRh4tKPhq0owg6MZB0JF0/BAeEjICzw6dNpJCSLZwqAGV7MVmZlz" +
- "FW3GuSbWrY1tbz6cEBX5/031t5Xq26tD0eeTKPanZz5maen48Hmfm+rh8R/tsevt" +
- "95vOVW8muQ0/dwn6qkVSPxsTydUx6UtRVtlfoqMjse8kMZUj0SSye7/KVZXR81mz" +
- "STUJXk04fITUm7Y+EeH1SIBLCfsshViYpJybG/429HOeflhiyJoizZZJqnHAaUfl" +
- "IkvOJH3SKlVJFWbJPqT6ux9pskzdwrJy6NBxBPGkSiqK9nE/6yaHtOaOIlPR5ned" +
- "BwjqrLOVGfdvOzy8zy6OTpB8JJ5O35aTvUnmpOHOTST7q5Tt4SqsKqrKU8ZMLO59" +
- "VefKuttZmLKmGsVuzxJ4xtmOsbzj7jrHOnDaObg2tvZVLY2bG06W4xJ2PRXowWn6" +
- "Q2qskgjIGgwGL/Z/7+qho/gPTXh36jmR1w9demMo4Y8k1PnrL5bLq5qtlHMrhcTx" +
- "qkjHMqVQDGMFtMg0tkKYtmljaZTJIMj9NFIipt2BtNmmpK5MDFVUUwrJvjElbUrM" +
- "i23kbNn7H7hCiP4ZebpITlFV4hhqmRLE7Z94lSPPmM6+HR5PY6k0ntVq21Nlhixw" +
- "sJ52ZHpNNQajs6c9vfpv6ZntOE9LGPhh91dhtbjq2MjZvtil0zo6r+jL2H8eLj18" +
- "yGzWRNcm9I5GokcOjGnDG7SaaFYxVOitW1Wmzf9NOstsnBXsVhrLaczNWymFZQmR" +
- "BAR4hXFLIMn8tE0KNiGlQnWdm5TOjQdS2GXGiCBhAiR3+IuNtczrWRxLegSYOFQ8" +
- "aNwQ5pS1bOmZvMuM2Titbss3zVUdd41y8iQI3cC+BYszD3iyYZAxufkk+P8nXHL9" +
- "uAF6kyiw54eRvOBZOAlO2Jkks3WNzvOHZTF8wXjOnz157FNv8IdeqWn4QqxyMzjd" +
- "ovNzuHBnGNqB8UypLJspmo/PZrnERR2PqVzauvfqDryP7Z+vQD7IISU+56T4JDTE" +
- "q+pP9KlpI+PV4dT1ixJrec504hI0p0ainusxoch3Rf1aTnA9yf8ixfufD/nGTaR+" +
- "r9Yxn56qBqi9vX5hPpZKpLI37GNPZmMfbbfbh2nCcj2D8Z5XfTA5tD/UrkhsSybh" +
- "P3xy2n8vXr3+fHF+jbhrfffrgpMdwyKsEIABftZxWHn6eRPx3H4XyvkzMnSq9ves" +
- "52gWBe8WN0R5UW63ukJQWFQ4oKhAJyCJnQEqDppQlchLgECaszI1WAe5g4MUFyh0" +
- "anCQg4mSNdSo2xtqgYJ+eC6eYyu+bd9QOSufIb1aqsFPuqFWSpbKUpWlKojFKpSj" +
- "ujZZcdbOTOI0xFWRNkIpGoH4pGFJpP3gr/zxFkAWoqElVYP4Gt/X38U271ZrEysV" +
- "o23KuyJZatOZ0Kp4TXVYhqbvrZeRB/cPmRH1kRtuErUZW4UhQwwgBj0NR/V3kMY7" +
- "EobIBcOQukBiqbEGpMmJiq+WZWm2LXZ6qn6+3RY7yG3Jww0zZ0a0T9xZo9U2SMjs" +
- "PDENqfk7N482T5PLSV+d2a1f1eexrCMfZXsuIkyj/nLJDF6pYr8eHJ6TBVV87tmm" +
- "a7bz+ky6PN897u1CATUrOcfrYT7WLUnZUkfzoytVKsFSxI3TkSuWTSN9Jpp5QZrw" +
- "J9vP1+nTbT6eldk/oc3RMOhp4yJZ4IUQxBgmiHJjtlz2GvOHReN9+iGp4Jktksd2" +
- "Fk4SV2/JatrxIFOH9wap6FtHEfVGhB1sDwiGOwtcvTAgVkF6fh/XVVVUQaOqOQog" +
- "5PKIzrA2mJiXdzzLWRbIZCyUxgbN2zVNiK1HWZJuqUsH34W6Tk5MbyVmv9jI2aSL" +
- "I2VKRQpzmQyE8pC1C1EUiox5RWwS9UwZLy63VpJNJfEm63WubJNNHJJO5+RurZhi" +
- "qlWMUlah+7hqpN26aksmYnEl+2jDzy2sWVaxhxo0sy3GKzqg4dVFnqiH/Afo6ZOB" +
- "w6/25A/kKKi+ipEIiyL9rIz61tdfOz5b9tOLlSqe0SxNVPNTFk/XTHSxksktjnfv" +
- "TFaebEYVxUzjImU3vFMtuuFx2WDCnNvkJhZJpZDkrlXW3eZtcuKZcvAedJhwsO8s" +
- "JvKWfGcuMmSVOdMuPtO5iTO25qE9ntOJ7c8nKZfwxh1UZJbaturhTFgc4VklKumu" +
- "lWXlu5AcQCTBIkaKGFUrEV2UU/n8/HpxHWKqpiLFVxDTtu0ZLFI6kEKTsGEUPGDF" +
- "OyKFmi9fCJPgqu54sCIJ6uD6eDlOsdVOSppKzATwfi2t4CPHgfLsRZAITsgfqQ3S" +
- "VryjsJs6HWRGyuXSEjvQFceInojgi66B/Jn9YGev5OSROQPgpDM311czh5pv7QH1" +
- "mjYdG88T0Y6lKoky/ahYfzsf2FLP37iw0iHVc4G1T+qGtRbbYqpbLVXmWjUYsWtd" +
- "3blc3NcosbFotRq1lJaLZLMX+yeAaVGqxZhXrnN4O7p233eKV527HTl3dF67ngUT" +
- "DIWkYklBhCDIYMo0DsbYvZpkT5KZKN0lGEqTdkzEsUySxKGyAtr23/mYGEIYA2ic" +
- "NDzgWF6BTisD+sxSj0YjKCGUBhaU0dbAuSAVMAWdJKS0UVTIyJw03tpPFQtSP5Zb" +
- "pmLpJw4T+ko4c5H5d37d2YZYsw/VekqVFiu6LIkAnOUupHbpVuhXVTePKxVB0bps" +
- "xhwtW3SVTpJP4oliflH2jl+CLI6HIdidSOtEWxPwTYaOFsTDdMOO9lshLUSxbIu5" +
- "uldYJIE/CVEfQGnw3KR8rEXXfhMiZYN1TKw6ox209eLH1yz6Qd55slpUwKmJGhpV" +
- "YEWZi/Z/B+/mfovmdoZ+b+KH47xRdEr1MjJ+9ZGEk8zDzXfoia3VNrVu2HqivcwY" +
- "3Cn7tM3ujFGxSqYs/dy22jfJLV3mNSTmx6I9vwKifsrmelJXD6zmOk4e/y1x5u6N" +
- "kaNqieX17yTTwyGtH46H4Fak1c3Kk5z/ZZaK7PU4mLKJZX6ySfl593p1JU4nVzP4" +
- "uonn80Sf8PxBATaSfrZLZLbUFOifY8b/OQOkPKRJYuHzE80n8kWiVZVKKsiPyj7f" +
- "1czhH4I6GHur5ngfJsPHxaVDwbH4JEAnRdt8Mbc25sbc26WpK369rsq2Jk7ybJJ7" +
- "nc7O76eHpxPLzn7OkGqH8mmR+h6xJVRVTckP3rP/RST+xYn6JzHM8ErZP8IJf7oK" +
- "am6yrFq3COr+Gv1fkE1ZskzBUlfkrr8b8hzk8yxE2fNMfNrmi187J8z+Bmx2Wzuo" +
- "upumHT834f0K/hL3SkSzQ2U85TkrZYbKMVKVsprfbMMsmUWyWP1W3DVjWss1MNMa" +
- "H1WP6OTaGllrnZoiAS6ssfNp5sy3o6d+z1Phfsunc9WPbpmXPm3eqbeJ3nCllcoS" +
- "R9y0sQeiKPWxdMHSL5yAm6DOmnZx9/de80IwLgMAwP8AgoIErJWSGzBhMaRbyCyG" +
- "/KI3YnIr+zatN5zJm9iJx5FlEPllZszjniMMODP1NDhIdNGSUoDpyr2MFiNFAp7m" +
- "dhmsM3rn7xcKDPsQKdNOmEcqRWE10Vn0f5jdKeQdD+sX9BD/gPSY95PtG5r5T0HY" +
- "ruV86045uEMRVSihTsyZa8MesmkTJVlLKqkjBRhG+JG9NNZ4h9alqTnNfxllQNGA" +
- "0GINwKMDY0ZDqh5V+GFsqw2G6lfuxMZjyPPPVzVO+/y341ul3m+NvxltY2IqNsRY" +
- "1tTEiANRtZmKiypqJVJKtpSltTk/sPm7/O/dRNKm7YOQYxq6uWOcR7KE3fYnBOUc" +
- "rZ8tbxGpQnw+T1h+E9UnrJ+6E4e77/fdEqziI7b4QxqWvgPVY2JuUihvCTzqWzax" +
- "J8k0/ueZNn2cHv/723l7vkvl321HbIYegUM+f6eVz7iFR6+P17uMwF+AHuHwfOrG" +
- "7J7tnlJLoqxiJZp7OkanzOMm8/JPR9k3N9px0iV2kiN/2MZWOp+Dmehw93hD9FiR" +
- "9EvPnH5sfKX5VzOWREnZyUU+va6YuauVpl1jSzGGKqpqKIOVA2BEIIMpS3xoVbiJ" +
- "DZ+4+ep9reEaqbrqJ9X9jOrrvJSr+/C3LCqZIomMTTGl5droWwvUnqT7fVasJ7Q3" +
- "Vdshbp9jH8pBJ6bD2U+Cd/hZbX9ay6kU8KxTu8ttbZlm1Zpptjy1hjMVabYxkKUR" +
- "gyjKMrbFpVVpilVWFxd4lsXb8MOW7fVipDJxhwVyRmzTVLLxkzco2dz5NnmsjnxG" +
- "SQ0xLOUGItVGqYkjaPOd1ixXJ8pvAbHrxPhNAgJ168Kvepi5THZi1Orm5ld4ad8r" +
- "162e8Lnx2rLKuWUXYSACKn+0Q+UPkiWkUT/jy4+mbc//nw1tlzru26a16nw/ipmj" +
- "oukAwgMmggdSKdGbGU/Iprgvjn77Ct2WhTTOcy5KZMORZMZRWwQ6QquGZW1JTVlg" +
- "QmM8osKKGDGMJIGMIBsiwhShSkqxMPy+3NPLDrbgVBbDqzyCBgWZKJrEQiRzR54q" +
- "wia4gUepCJo2SzrcVXl3bH+sTOvr0qFHlmMYpGEQaiFZjEgQmdarIu7T2kdmRlAF" +
- "SkKsnConJTZVYwmzOAdnDjWUlQbpLqEmzOttyWq429ehDBlMRRpyaUji5o2uW/LZ" +
- "8wQgAFSMYB0Wdnuk9X8nH0naSH9JI+g9o2Gzu5nUVw9VrujeRN048OjNoP8LOjhS" +
- "uG/rTtFPk8g307qhpyc48W4wop6dLpbpG62VarE1XE8iOyVK9ztXvOYw0JoSwJZJ" +
- "Ftfft+V8JibSreNomUqaifeYC3fJ5fCnZQIMR8DDQUIxtbZGzGjKKNDyRspoqZqZ" +
- "ossZ6UUDMFZKUgwYwsMaaYqaYrCr66wtypjY2abpVSX/mXeSNkaJPqgQhw2mmMjH" +
- "EHymdzJLzYsvmuuvVbsqy6m7aYqyZnGoerqj3UePiyIVZIoqKthYOZ6vGFsYpWJz" +
- "5ns4SY/yi4BSSyktv0dXbf1b1fl9fp9+36YjGvdRRMDFkx6Pp9wzFt1H2f0Y5CMb" +
- "VjGyUszErxN3k9ks0S1Zk8IeitT1VrI3R37ye53Th502X+9254a+co8o7nMnWdCi" +
- "wosHYmvktSVSyC6P4FSTb4evj8e+aNQ/gr3by2tmlU3bI5CjjaesCuuOTInFMxR6" +
- "BGGiWW1NjQqsYxKUlU0qtak2QF9FdGkKOPTjiqoqd6H0PuA+KaOAwX65yfbt0Uu2" +
- "t+9+OvxwswtdK+Z6T46z9ur6JavYqrVySsYUxinbay2mTZRVK1bWMy8Hm/TRaetZ" +
- "W+L6HJ1GI7KbTEnokj3nzVNViyloqqryY4aU20msYtW5mTfBtWDH/fMFA6MUxGMR" +
- "NFAuSNrZk1GrtLMg2RpFCqVUaUsYRZMiN2Nim9bnyPI1L5d7amo7nk142ZMm73SJ" +
- "/eoPU902bpY5T5yQ6ffJkrLbKvs844reynK6fNsroOIGSOqTdhDZO0IlkpYiq6Oz" +
- "Fkc0U/fPTYvU9bxWXZeLi5F902sZZU2ysGSmlVu0qcXTGyX5KS21VKrYw87pVnOc" +
- "iN204sTwOM8R5cJLXpE8sT3gdCaTqejSJPFnanubqkqvQ5+EkEjrFki/syRPSKqx" +
- "ixHNf1x69+Xp6t6l5LGF8d0xI7umlRgxkIYgsKQGahBGMdwkbbIclCjg2oW00iZA" +
- "hDSVAoDGhqhIDTC4UGjDNVSwINaWT7/c+6B936RGV91beaH+tFpClUqVar6a57xS" +
- "1YsdOxwxj98iTq3teHw5yT2NnV6Ms+s+NR8b24bKw/NWKKqqZhiqnM8QftpfQb+C" +
- "Vs3lZLSSASqcfM7yVxGYledbnrN50XJBATYaCsBtFYJlZR2SKwb21+jqRiNFI0Sa" +
- "rSjgiATZnWelW7O0mbziCfju7ylzo7WSqylsYp0JpjJU0qaMlJUUVhGilWTZudCx" +
- "M+kc+l5uTSG84qLYv2ZJMli2qrILI2Tqln4cMqNhAj4gogAncslWOiwaV+BwnPnE" +
- "jdp7E6UlqPtYJYV9Tg3WI95FkO6beZO8nlbeyYVc7od2tLylZPKLTp1I35t2iLsk" +
- "ipSBQqtbUX19H2kWD8z2PyVPmh9rLUcrDSKQsTJIfukqY7Hl5DzdPLdUqq1+LJp5" +
- "emzvHWPLN9YtWeh+2WzylkbFNlTCyVWKZpKyQ4YwqnWq3kKzCwje4lWdzTuDbTZx" +
- "x4bJ8tzHGu7m3prWSakaVZncMwY02dcu7kznctvM5MknBXCmwVtKfU0xWphkowpi" +
- "VsxiVW7I2rWqtRhwpcXDoaZN1MN6tYlKrh3GpWUlJLvXd43OuslSWQ0fVcxqeL+B" +
- "Xv1rpQyBqdm7e1Ra8loulyubVzbXOGoNVpN1/mjcbxaAiUP6xnhT7z2IJaTCQVgt" +
- "DpQcGFJgWSBTA5batqKV5l3ruu7XC3NyZRFeT486vWm68lRqMyRNpSzSpsi1KyzL" +
- "GmTS2azSVMZqtq2bay1a0raVmmyq2yqikIVCwBSIqSpJJKsVBYgSKsBLSopRkS2t" +
- "tKmrVKmA1rSpZU2JTWWSGtUtmsrMWKVLLVRCkSkEqQS0GpKlKZllNtK0WFGTNpZY" +
- "2lmmZKZLbWbabW0ttZTSTFMklmzbbTaajUNZaVNKzWaipYqKmU2mMk2lilaVplhZ" +
- "MykpmlSwamzZsrUtUJCNs2xE2zWbLJpmmmlSyzaYzNqWpssspZTaqtm1VbJlmm01" +
- "kzUtDKks1LIK020pKUpNRlKTSlmUprKzRSmk1NTZZJrNhJIZMlSpNJDMktbNVDEs" +
- "mpKFKVJtllm0ps2WzabGsbM2aQtmsJaMkNaVJmssNbZtbMprNYqWVKlaTUapJmGz" +
- "RClCZhpmEmZpEympqWZmWbRs0SaY0lNTU2lqbLNtts1tsrNtKqSWmGWWW0tZrNiG" +
- "Uy2ylLU2jJWUySmlNmpspWFKJrTVkE1lJmakWTZmUtpS0rKyqpVsilmsNrWWbLMq" +
- "aVLFlNmazabZtNppoZJEkxlJIlplYbNUMaaVKhIUylmxaWkEslm2WoAZmYGmm02k" +
- "mZ9vNcym/zYZ1m/E+UySfg39LUVVWb+0CAnu+IVnzkTYexs7ufDm0VjDZ7mmLPDC" +
- "jvRkCK4NH4KYIPfTEsxAJVJTCY4MNNqKqTgrJkmjRkVkyN9MMuNskxW0mmjTSlSs" +
- "RiUzxDKZmvWVXm9Y8a6VLqbbWXtSMLsZGTNoSqYkyYjI2VEskoLRRUbRRsbWkqSt" +
- "Sau0WgopMsq6V0SZehQ82kyxbJsqq2k6xbaqqpy8chxElkKVybMPBqa1jIGLJqNa" +
- "WSNnw5w5rJRVJ8pXQahwWUzyp0wnz/U0hIEiEYfzEVFZGtr8GqLFqNUUa0pVZVFV" +
- "lLVsEy7VF1qILVeGEk2aS+WJki7F2pqD7InRyG/WjNbxTzY7E029eTdr/1ZJlhzx" +
- "xZEk7TYxZI2Vk4yI8WLZEUcfOpyzjm2I50sicpFjzHRZKelYLMxipnrpolbK2wP3" +
- "Gj5QrZ3mE7dW70dJN3aTWPvGzFnLOYscQkecNk/KdSbVattW/g8tatRJ9BbaVmTU" +
- "cNkbE5NiRgCjqJjBFYYMQEpXT39BIxlLWwvLhFGpGWUqKViqxkcZkznhqQLSNrGQ" +
- "hBUdGYxN2kbWNpAzdTVXSs46S3TNK5yd26mxXO7tXNdm0m6bRbSTJvK6rpKW2TFt" +
- "vPLvJbNaSixoxKyEmNk0kWK0SdjZs2NohYnAsejhFowruXCQlUVFqVGpE0UGZIZE" +
- "c3lktTo03a6N+EiflSdFScJJ0xKRxN5+ZDlCLZB9FWySZUtkhL9OWNS5Kx7HmGk3" +
- "Zm+vn/kuSquatyCwYtGGhIxpQKVBh9sws7qnJ2thu+NtlbJbljpdXFmFp6I0cN3V" +
- "hW7RqTNacWNJ80k/pbIVr82CR/iVzKp1fJPyjz7u0PGnOl53LbDvYakR0ZJD8qm5" +
- "9mWLpEWRzhu+1n9OUKT1kn8VOh3p4lv5ZjCqf3P82pWjKmxUzVvxpOH8eDZPhDwf" +
- "ii4JZZPcJ67Ts94+JJ8JN6n2RXJ/iPpDEN5uehqR3Yxju2bXbGDrRv6T0R5vdxJO" +
- "R2mD+4dUjVjZFQf6RFZJ8rFskqu7VMy3EjDuzE2K5wH1nnG971lZjE1GMMpMLzVo" +
- "tmMJoN2gv8yApnCpgihcVoiUFH+c9nnbz+momOTD2WTT5sRko0skZYttki1bLSVY" +
- "mmMY0wqhWnGhdSllSSW9z4amEW8VfPq+6qyaeu2jZNvXtEl6ptryvUoxwqtXN1Fm" +
- "Yqyc7Jqlsb2TXkulki/galjcAwqxIxJEkIZjxWvohjDLbjDg3VHCdKtlCUmTvHq1" +
- "g1bKsb1nufaqpD0uQWNon9Cdrrb3LTMlSbUTSbK0ohajIvgjH+99Bt8p3n6qleSV" +
- "ZE6o9h2eHZRzpwc3OYmK009E9R328jxMbJvFH6StQnM1NNmLDBWdD/DwdQc+bD7v" +
- "Uoz8D4pQaY3jgmo4UpCiqrGzZpNbC5h/TXGpNqn1Vaok4ZPk4KphiwyWJy5ZHRwf" +
- "oiZC34h6SrVlWif7FRHs1+Nuh+L5Hs6k7WWyNKyald2mpMaNp8+jr5z3H5HpDpU/" +
- "yqPXPAk91O6UFo2PK2u5jy7lWy35Kw+iPIqfOySOpNDJ1k4nqsilXhkeZbW8c56z" +
- "Rx1kbkR1nBpJ1VUPWotkR0rdsQsexSuL+5pk+Mk2l/i7Oi6XGwkvE5JyD6Ifc0l8" +
- "iIBO6c0DixXt8Wk0H6+6WxFliWWWhO5P1UUsfx/o/JZJ9iprtPkmjEsfWdqnbtat" +
- "q24OckqqqnQw+6k7EfBZHMentbUafUcOiqVVVYFUlFKKqejEY6Y+lfo+ubdLJdCu" +
- "RFXLgVQwrGW3GIYJWGCYwwtWWlUskYxZ+emKaZHyQfWMWTUkP9FV7wTx+WRVUrZI" +
- "0/KPlYWlUqaINRpIxmMlMfoeftr+7+JP2H69M/jD8xaKRKgSrdibLHI0VxjbdHGN" +
- "jQd0aMDA0QIQWEpTRDGZrq3R00OH8GFjuAD9iwhU2MP6wiGD+jp0Ymd06Ksv5piO" +
- "Uq1rMkwZkiw2SmZIUHD5pP5P1qcNmkgD9vum0hi+X4S/PJ3/mfi9rbspyye2Fk1Y" +
- "tSqo+5O33q0nAeTHbg7lc2zBxS2K2xjL/dLmkWZGHQNxp9NkyrGxuvp9akHp3+A3" +
- "ROSdXUb1air5yyvdI8km6PrIgEskaR1ceOmv5q4dpNp4dofKup3NzUTxsvxlZbZ/" +
- "V7KshwsVcSqwxapT6487uYnOE9IdPT5DshyR8GTg8yZIxO7D2Xoe8wbPD2vkrki1" +
- "J6oe6xXDYppjTbDezUkdjZXVjE75bVWXRUdldu05D4OvVbD8SxVZLZ009nJEkSTN" +
- "7Y8kpPWH5pUvT49iIMA9AfIDJEZQpYI0oY5HlZOHxMMSe9WuihVMpamSnEH4RE9Z" +
- "aWlkKsWrVSPdFT2zJGJOHBVlVUrpTJRywuMlV0T9myzARkClqiJX70kgpcYzsakR" +
- "kiRXw/k/H9sfrouz/j/oVDN7/u1hxCRIRZULOfq+KvHsxm1M2jkhY7WeUc1j/ARD" +
- "X9g55b0y0OAkCC5cP+IWkuBkJyInN3reK6uz5oJ3cmh5kk5SOROSWbV3cz6GtQbZ" +
- "KFKWuNFtiyrDpfLMzGSYWFVpVVZYebEEsBqBXBsjMbarG2x/fZQ+jLYbHHqNwzdK" +
- "EarMZjYxuuOPbI9sySN6HDIRKMbSRBlKUoJjSMbaV15eryvBqvJXDYi8l107GrKu" +
- "rrePql/G999PfuvQQNubc1orFGJnz9/3e/n38NvhXHdrlX0hVyULe2vF4tSELMby" +
- "nXaVdIyzVzptzbpG0kYyrYmUstRUilMV6qhiUaXUqU2t22sqVUgIrrtLQ1QdExSK" +
- "lSKNIKNDYBCEhONtcvec081daISsVrnNwhsmVFh9UnkeSpU/Ucu0cHJG1Tws6MbG" +
- "5/FVq2qhSlIpMbqkdPrfnJsRP5LJP3kl8j+YotqNDkj+2rYWxbJPER5OzzamSJYm" +
- "ofxdXtOqPt84dU9J+/4gPBe8BUHiJMP6uXrNpwqwttVSaxGF+jEifCpFfxSkr9mc" +
- "32c3S3Szbd2ZoiFIb5ZGYtnEkdJ+Try/CPL9Mi5mMdh+Ug/lZFsslk+ZJ6Es33Tm" +
- "ZHKzR+qo+jHqk0bPR7vVXJrn+XaeaslpRZLB6fWTy0fm4NJO9fzVkjpKW2+cmMea" +
- "KKivw3yNm0nsxo0qY/JPx9o926TeJg2Itr4mV3UibG6zyzGVVRZRZzUmJYrYjeJP" +
- "tG57vdmClZ7rv1y8228aKmVl6+qvZfKRcLOG6ldOqd/Vu6vnzdTvHSaWdJCUkjhk" +
- "kn7Gk+eiZHzRJjshqSwqyDyZ80X6SPqx722PQanWebyOhb9n7djstjZ4dY2OQxL8" +
- "hdS7hgfQ+5CDkj7o7K4g5yNpyOpPqRywlpQRSDKSubGQjFYyaHIAwiqRam0sMSLC" +
- "sJviL0yJ2OkeKEslhZYLLIdXuqTrJIqKaZP1acJCcH4eh1+kfB93b1WTnIpa+SDt" +
- "JnSUSfEhNliaKTnK6bk2NUtOpwxwxVUbNmx5x8lIqppySP7fkeJPkfA/GZNlaB85" +
- "U/xOGz7nG7VxLbFvOJRc267dY5TS32y82q967Sok5Aw3FStphVLMYoq5nJ05S7XG" +
- "3bTWXLtislaIjwcKpUlVZ5bNl3MjhW/1ibOUVX6bGO9ltr3qNM4ZOuTmdlJHaTrd" +
- "opbJmZI0WRqsr4Q/tfrZ3oi2RVBaIqi1MzEkmVJ0pnG2r43k6qGCL9Kkpczv4SeP" +
- "sFeTIEBc3DtAZcH6XxGW7Yaw+DznoSqyrouIMcMHbjD/FBny/X179rvtjikQCcgQ" +
- "E4HS222zVI+KD/aP1IS0pJSBYzn2USdPSTTu868arlGQodZ/tyxVyU5RrlBdEqjR" +
- "+4KCHQDi6aQjlScf+T5kjee1Xoxo/SOOyTCd1xDlX+YN/MVvtOj2tXZXckMqqZHZ" +
- "EKEQlkdnL7Jdydlgmev89uU78j5cSJ/l8dkmE7rhzD8qadHMH4jZj3nDGPdwajh7" +
- "sMdnVu5ujXXl+T1/u4LOHgw0+z8FGBY2M89iIokYQvh0gpDsMgXC5N6MMVWqIDKF" +
- "k7Bhi7LCa12ZnoYVi5gcGP9X5TyVn5jjpmK38e0H0yNy9sy6krJx2NyXEkufYjPY" +
- "35HJdzHaIWeWpGch1C2GpaeIIyAyJiVK/Gotmvs6vH4XixysdNfO67ZuafPse3Xt" +
- "czmeH1mHV6i2qvNHrsuyeFJj1OGjd4Zq4YLjGTExlUsVV/xcbG0nNuxlxTLllUUB" +
- "hE0vYrX0AxuvoyLWYktLUDBX8H5cYsLkOfeXyz9A4QbZ7J00FTnG94VNve5NkYen" +
- "LptnR61av5SHOPZVdEI2fk5/k3VxOX5PckzZv1ec8TchyRzOOqs5zOUkm0wWPJVW" +
- "TC1sxMVVTWOfpWxnsx/JmyBRsFWNsiIqoVUFReZrK80s5jqpOqvOS43zEuyOx1cp" +
- "0Y8OhOW7ME8lk6LCeFLjEsFSqpSyelXJhXAcdpsp0Y6/OqpWhUMVm2xjyTgU6nrw" +
- "6yszFUttktLZVtnXi3kuDRtDz/sJ5OxXV22LVZKMYxihA2Q/Dq/NjZ+535t7PF0a" +
- "3E6sM0t90PBzJHT5SRrz+MtSHquWXGSMc07ChTvJ7sjSm49U8JK0NlKrXIMbnnPC" +
- "0qUqjU5Jxyt7ynN5e/kM7y2YxjGrVeTE5xqbVT8LiY6bpo+ZdRG82/fr1m22xZSB" +
- "38PxIyNMShQiH6G9hXLOZK6w3N5+X72HFAxu5NSfRpW6afRXqo8VJGH9x5ObPuVJ" +
- "QLAiFlH6/u/FbMJ3EnnDq7T0En449m8JHNPxcyzXSV7BCP9JENSIjTahAiKfMpQX" +
- "fhvwg6xjTyfA09UakjGjZSMkcm0k69uDQkz5aTWCW2iz7hlcSciTjD3IoFZBYmNt" +
- "odoFMMIkDWQjASGk0NA76DcIySAGLYwAZPQkVbS9raOCXx0N4NPJAcpTE24YEIYy" +
- "g7CfLWmi2E1TDcjdkTMXE0qKsqvYI1Rc1zUWKjBt3dZMYLSc1V8teNrSwW867u67" +
- "u3XWz3uiTDJ7uup6aktGEa9d1hTNubvV2q883d3IoqVnZHRyRZT547K2nlbs57pm" +
- "7cLQoYwF2iZPBBH+5LQ7dYkkhI6u5sNK9nPxux2bnayrYrkTq+u7erJbBUNziMaP" +
- "rppVcY3SxyySyySfFXkjZSuA61FVMKi5jFHB+UxNKWOqcRzfOSQki42nkQs97JyK" +
- "5amm58SFk3LVSU0uj7SQfqwEfho1r92H6uG22K2lVz+Uf5sqP0dLN/GejmK0sxrP" +
- "xz1m2/05yx4ONjCbJH9A+8QkhIqoJKiRIQWkkRKAK20HGfR9lFGh2vmzMyyCig/w" +
- "mlAinByNccszHu826vNs08OjdXU3GzSpwG2/sZ6SHoyTSVw0slcGjSBnq4UMw08I" +
- "tvw4uHqDA/w6OSCRnyIh/MH46rxmTFxdHacVc+uD3HvflqHvL7RI7e5edJqb4ZU4" +
- "09uYztwe+W/IpAaOoyLcwQVPk3k69Fffn6zXZ3kION0cYOXDuS+3vzTOm/K7Mq6H" +
- "OlZUd7Pxxdl9t69NorsK6eU6442+am88vu73UsgRoV5Z211tTDr33RPyM6/XfL5U" +
- "EDhtlOMGIOhqVFDMLDExeDQGHON0fZdtpnTpZ6cD6JBkGJpUx0Y0WuppUjCvDGzH" +
- "Jsmjd0VyNNnRZ1Y1MNHaMbOGzcp3VttssZwsk0gsTGWj6gLXG8FJpoGGjp6NmZZI" +
- "mQYvcYoaIEFW2vkM2ui4SWaSMLtv6RnW2Q1A4FIHgMRpRK4eNjfwZ5oqGaaSMo5b" +
- "dknhw4SbOELPGyXLyqGoGSSqSomY1HBBVkQqys9MCWL1YjTEvrT/lW/HvnSpG2HG" +
- "W0YwPtoufZQEsPWkFdi4q6Bs3tkoppX5Eiaqo5JX1UtH2/gzrxnmXNzE5gfF8iGh" +
- "wMagId9OeGfjPxGKTtKHVVJ7vT6eMIaVB+wH3n3+jxV4Svh6l0hS2vo/Hxp46W8T" +
- "mStcsHMrio8lNypolKYqrT5AyFDChtZGHuINKBspBGKg7kJt6Bo8fNBswFHISJJt" +
- "PcLdHk1+NWshZCgqnMZITrDX2VnDFGhCe+9um2kaWy3BLFDrBte5ISqMa3whRNX2" +
- "hdsSnCgdmnJiwaaFmqxgEhoSkmS4W5nnc2pOkjMCi0Pn4WGjUumeTCfLJJ1jYrHx" +
- "jaFRrCj5qXWxkTinm7fk9Hu2JvELPk8MMVKpWKtKq1iVVKKUxXlx31G9Tw/vO6Mb" +
- "E80lYmSJp0FRrDJyLJ51U9ZI6GiLTUsTlnZqBqxHcOldSSip2iosJI2Ehx0kHxDZ" +
- "/AZNzYUGDTXrMplachkVuS1tsiYIYyt2mzZDErJJWTTEalrQplZC7YM+li2SUoxV" +
- "VZY0yZkycNIiDcCJMaGNe5kXBpN+8HIUgoKqYnY1JISR6tshCE6JhknVjg6cMhWn" +
- "JNlbSdppsotV9zG202HYjiEnmTz+E7xXhSrLv5ZtdazVbW2hjEYNKDGEBkJ9/vy+" +
- "vnrFURs1YvpvLuyE245w0VLL1kr7cOg/Ba/Qf0QM8JPxZLLOStL5KZ+faXr7LE9j" +
- "17oH4+OiR8orIu4h/RAagtxGICYpOWtBCN8eXMu7rl485VKQmKi+aU6rwbyfLXpr" +
- "161+qbettfqWN0pL88tJbgpKWur4a8ki2arIszGhZJVK03h6o84nieE+RSDA2EJn" +
- "ygppzrRHjjDHHjQ3oAGNIa0QIJjBiGd8s3glSnsMZSEY1I4BqCBOrFtgXZ7YoGff" +
- "5SOeYkWToVOR6a7/Dmyl7pPebOTUlLEYebR5Ikzr5O+azEJXRy731dGOXtcW5mTx" +
- "HG7GnHVxIbSbnuyUslYdMltVhpO7tytjo3Cx2IyGZDKmmWOxCaYRisSq0VhSVpit" +
- "JWkrS3VY0DcaigxKkRFVBNRkkg1UhOMurldw8knJjznZobpJOCnNMtmM9JI/gses" +
- "Dl0es/T0c4b+aSO5yy8it57PtER7yQ49svq6K2KoqVhjFUqmm02P9rP+enbyTaJy" +
- "k7zyB5VdEyRHyqE2jlT/N+4jPJHNVfOPajFtvo+bRIhxDIiAREIBEBHmAseJvCKp" +
- "aWSr3OREAnaST8LJp9TClbcGN022eOxs0mObY5x+f0+u0ck5RKKUopJrgB87bebv" +
- "yv5u7W3q/fvzQ+JGypskPUreRLIrmybatMsX0a/RksaxtIKIX8sn739qsebzOZiG" +
- "by7s3vdaJR6Dj2macG0WSRT7SDN9KC4xmGSRgRYwaf7MbwGIOPrP6Rb8N/DY1I1H" +
- "JIkrMaQbxJHdIbifDkh15l2d27BHRHVPKch+6RBzeUnBMtctc4pKUyuu2upJrlrq" +
- "667pW6+1t+6Vk20JkkpYV59A5unxbofu3vn21Ey/s+HYx9zasPu1JNm5an1x85Hp" +
- "GG1LFk0RAJ1kfSK+E9UPntJMsjrKWnc/YuFg5pe8Oyx5qIpZEbwKh7e7yTBhymws" +
- "JtGzb8PDzkfvPfLZJ5yR/o9pH2H9KqdtVVX7VbbWI2Nmr22lllliKehVTXVI09Cd" +
- "Z/Ou/e1aKs8lfvPiSD3/Bks8PeYcuVmGgTKW2WyVY/isZRxJN2T4vyfP0vRyfZZK" +
- "rbaZNZsTidKX8ofEcnunxzNEJWu9xbuQ3w1er3T4Y3g7/gteJ4WVbTtmn85O7lJ/" +
- "VEnkTJ9atqsYYYeujDUxIwoxR56sknNj7SbuGneRs8nq4fJO2cpuiWKioslVKlRS" +
- "pJZ/ULtdlKi0b+Z81+yixKtJIPDdvJ+LvDu0SyY/h7/w/FiNs+mias1cSpOznIPK" +
- "yrHt1CY942YTzH+yrZIoqhOEiZIT845d3T6Pps/6Ofl4bEm9vIZB/UJBbEtgRgyB" +
- "QrgTP96/o80lj8FrpZ3WuiX6brraSSqxRuxjTFUbWarrGGKMDbBcSioFSqf3ZLaC" +
- "XBlKqfB9CZLWcmutdlVXXxEzqHZVo2a5uZjrbE5X5CvSKi2WpbDaOR0OqaV2Vjxq" +
- "myEND13YGGgTBqRBqAkgipVktsk1bJm28lu2ll5dkUpklpVLKkqjThs7SaJqeWRG" +
- "VasWSxZLZu4aIgE5GtmzUkyWRexTG+WO1qi40I7X+GXLi6g1d5IU5Kydn5ZoeE4k" +
- "iNK7HJJHZ32hk/RzVTRzKwrOelrcXxZCb6V8ambb6i+3z7g8vV7o2qRK3bNfx+d9" +
- "az5ZypWyvNOJkq2zTDGW3I2kxsrRVg0qaU6NmxvJVssZPf5Ch3jJZiNskkJC5thW" +
- "jziKca5yYTlK0RAJy2l5f1mHrY2Dc6OkI2TTTy2TGVsRATPxGssjZRlnpIg3iSRi" +
- "xI5OR2SOZJPl5/ncvR8vln1Y/uaaeTGFSl5VO11Z1vnvja5W9Kw09ahkgtDDYyAY" +
- "Qw/WRKMp5aFVusKrZpjSKdZ3v58tazxmJb6NXQlD2AabBtG1MLD6P6xKQChW0XsB" +
- "77Y5z/JBkkMXpKgXiWquYcP3Pv6+I4oBI7HediIrxI/Ei95EsFOQPxkk78pP8rbI" +
- "tJ+v+lu6eiHk6+Kqz+L5PSR4npITj7fgsgl+q1VWGLPweJJjUnC/Grtc/J2G01ZT" +
- "LW5ObQ+bnkr8xJ/5P/vSSP+C1jG1YK0Y1sao1qoiqxtFbG1bFRtUa1sVo1trGrG1" +
- "RZKNo0UFSilTNtRtGjYIEClGbbBQhUJBpCDY1o0bFbGCxY1MoNG2zTaLUEKzFBMN" +
- "tUbFY2iqKIjEUlZKixqNsW0UY22i2g0agirFbYrFtJiNJbSao1sWMUUUUbWNslpL" +
- "WNjajFopFMhJGxRRttjbBtYNtoo0YrRqAKKLUkmqi2sSVY2oNFaNotsVoyQVaNGo" +
- "o2ooqxaNUUbFQoYQ1o1WLUG2xVgybYtGtFRgmVk1iqZFQlJrG1sbWTajRaLFaTUU" +
- "VRtSW0bVFWxasFWIsVosatiqii1GLaNaNGpINqg2jVoihmxFti2DGqiqNFrFslti" +
- "qMZJm2sYTbGLaiKiNYrRRGsbWLbQWoi0WNGo21irG2RMpRo1GK2Koo1ii1i22C1i" +
- "1RqA2o2jbRRjWi1jatG0lUBWzNUWo2xpRTRVG1G1Ftii2pLWTahQqKi1otitJqNU" +
- "lGjJNKqI0Rq2i2yaxjbRqMUVYjQaKwVRtFjWiCyFiKsRbUWiosmsaiqjY22iqLQb" +
- "X5/99f4p/uUf0tf5/9K/qseg/3/8O3Ejr31kY1gc5A1pvXCxCkNiwvOQZYLITeUx" +
- "5CNobGwqJ5o3bWtQ2oqajkZRrRj1prYW5TG2RkzhxibIud1zezbDrRBn8s2xsbHZ" +
- "Ilaaujw873Rttris4cJCx42DgiHZM67LEm5mczQU0zdbGxtvENm4RY8axrs0rvvB" +
- "2Lmhu9ZH1rnXlfnhQMwstTWMgZ24VXZJdzdKmphdlKOvHF5Ypc1co3WpPG5UchDH" +
- "HthGXu6jHcIFa8oQrWt53ErY2jQyDFGQGaaj15BbvaLTDPKU2xY9Mj2zrW2Hba2J" +
- "jEwZb1mshmPWcZdXPGGDOQ4hqWsZbxqyLQ6ysx+Pu9UmOHJEyavWvHjbPPnsX1XI" +
- "iq+W3w8Tu+Ry16Js2+QVNGKUjZLWwXGBxtiE2hFTSXGBGkBjMu6xtIYNFQM1yBbp" +
- "9u0ksTStorHkolJ3E5XN5tOFjhjhwmVcOxEtLHxyyr7N9lk1DJaN0qwpiCBpBAPG" +
- "3V0ccPvd0Avs82rSKmAnj7RQAdYSdYbzJjI4URnJfO3TT4xQ26ahpseRDUtS+MKb" +
- "aVjQ9wg3lnedmecmuQV2y44ptKaHyuZcF1u1JXKJlu6pRPSTudsbp5qixXfWcnpx" +
- "PboouIu6q3vjI6ci2PuVosvF0bH3kaaLyFWNsiaLGxxWqGnvHH4d8MyQpjfcyGZA" +
- "6+PHVbTd22SxshNhjBvMiBiocsG2M5zFRj1yyQh5C7vZX53zDy85X19hw6XAhSc4" +
- "4HRB2w2Jzqalk90qqeRM9JrLjIlc2+tvhMyT2eUuq4MdumMqyCenJRHTk1OZudfS" +
- "+VfKOcyA5HHezeQrJxq2piOM5vIJjY0fYvMt9eOLt3WsvDtG97S85zOs8DAjs7dX" +
- "vmFFxB5l4hvFFWKjG6TIUmyWmMme3cQzNyatha2CUx7UUluGUDYW7GzYGPvUZVUN" +
- "2QruGNDbQ2NtNsoEDGs5S4Sw7tuXObFDTJmQpdzuUSm7gDGi7IElwyNbNWUW5apw" +
- "r1xMC2oS5tUYZA2cHGiAzve7XardJ2IuYysvZR0Ku5Ck+2RL65bzSHlFlxDxNMK5" +
- "TWUzcfeFomjrOXGkuCogWNpZb5Tmyes2YdxqRBmU6GoIV0TPJNojDDaqLiTC92lI" +
- "44VORRdd7f/n2zez072fHsVc0lJBrBTJO0dTCCHBnnJ7l4TDb0xvuQrWjqhowcNm" +
- "KETZaeWn2MKO9JNMjipkZF31GWlSxcYpJydb5hSnINMGPuEOnRLL4UV1hvIPGKBl" +
- "ZvS4ydl0W3uRzvMAxgqY2gIYc5EjKevtHG5vkRZfTi704pm64VOlm9mnddnhX1d8" +
- "i11nlLfO43hvIUvkhnaDTed1UYzb4SQy8iOZJY0OXGtwdkbrl6UMLqQoOxj6wqcm" +
- "67PRzUcwOOdgLJgvlpWuyLe1MNGlSR9cdZItEm9xaWRy5l21raQcOMenbGPjUtId" +
- "5L5rfXWQr2NbGd5BXI6+tVcA2rcJgTsa6HJhyR9JZrTaSuTN7tG94c7fN54bJ5gK" +
- "AteSmybgHEB3lSGHTGcmecrPGjWNw+WA2uNR0erioM73usN6veTkgxmQtzC+7W1C" +
- "52SQlmXcODt80oUQQutphmedzHoa0Pb5uGiUik1kXE7ZGybH16ydOZNOpe5Sgesh" +
- "jsIhgWSTnObvd7JYyX1O5WwQQTtFWii2tYujUsWbw0ezmrTNw5aVPbIMBpLsctzL" +
- "3e82boiMG5yOnOmm8fMsldyWw025uHyFFYaQ8uhZTsWKiNp8JA35OM6ztkc5IRzb" +
- "yi5eshOO7RfQUENxDrF3qvnKutTq2OI2Axlgzi73va5to5kVtHbQ7Y32Dd1k3HCj" +
- "LIPSN73VuOclVLYXpmseBJzbNvLSDWByI7kReScm2jiac6ztXZGkbaiCAyO2QzIX" +
- "Td7J06xss3ieAXL4jMoKMHsszhnY2tu+PYncmERURzYjb7rVmXU5FSXuzzzvke8r" +
- "flq8UMwGzmKayKZkWIVa8gdUzJzlgqDkEC5XJt6MpysuebzMk5crS96OkqQR3Dkz" +
- "ElgmcLoCwfLTbkIR3GXy81m+S4PlrND69sIGpuN6O4g2ktmwgkuHKu9wyznIiYqH" +
- "xh287t87BEPFkERt85JvWK2OrjtJEX2u3Obs84debd0rw7zdeXMFzOZDJ3NvLmvO" +
- "W98l52eec8Ovx3URCkNEx+BY1uglDVhy3y0UPJcKyiDZjGbewQ+bM3Edm6FJOvzz" +
- "azuclkGaGMcYNlfJEmxcZb4M0d5vObBOO3PN5hD0onSZ5O7GGzFbRbOZzlE2Rhka" +
- "wphx0zrlixjRccimW65Ok1uZQ8tkA7rSLGbUGzJIZew32hAFkPnNVhE9MqWiOw47" +
- "zozjty6kNk1N83UI0ZAZmzwzHu5NUqQyQow0vktdqtUDtNuQOWVDBrlBzZMzs4tf" +
- "bbgLjvOVlw1POknTok9nX1y1i108eGb3lqIbyXdFm5ZQ1N1rdRtQsbwYcJmHBeXW" +
- "2qMDeacg55NcqOxlx5mVneeFYjRYeJ0ckbFCkO9HPGh6Uz0YirAec3cAaT2SN9TI" +
- "dhI4eu6xRjeuwlnHtcd9I6I7mnNQujxohaKtvuAQd6d17CIoMjnTcYTJ0gzDnLog" +
- "y87zLa4RIWrjb3QJV4OaRG3hmhxMjBaozkkzdTcUbRtJzGncsju30dDubirvs7xZ" +
- "JuXdqYd7zsWQFdt5eUcWbvOEb3hdO1zObnI7UeWd7m7t8zw5eWdMmpq9lvkl1O2s" +
- "33XNPfK3sTSyZwcbL7OVx6ZFd7y47nYjGcfOl5WUbFK6jGO85fdlu+Oj//MUFZJl" +
- "NZf1tARwa8BV+AQDgQB3/wP+ffir////pgsXwAAAAAAAAAAAADkAFvAB9CgCqKvh" +
- "wIIRClJBQGt931KcB7ue29fOM4xl8OCCgCOsAD4gAMCCqAgigO4wANPNs0ABQWrw" +
- "W94D7vhh57CBAWsPbK21bY1p2NSlc29vnvroj5VJCRUilcbPtq+nc7762bq+rYxo" +
- "GIRFFTW+199fPB8oqqVSlUqJfA6522q9YIUQr2e0dTolBEUApKpKdxdyiq9PcxXp" +
- "pT7XA1zw2DoUqJQtbhzOqiUFUEnrTwsJplFOzKlPLNubxmlvLabHh70vPbs9VSlU" +
- "C2aInZnWUtKa6kV06iV7xWDfctwDvZfbVSHSMzex1T1Xu3dbtgdcgV00eRqTtivM" +
- "xlkDWp3c5VXc0tLhitmrNiVChF12zldtJ3W27okKoCs8t8djvZ9jdAPWi0r3HoNJ" +
- "bs1XKl3dVs7jAPbHmZ03gFeUl02d2aYcR6bmqg6173G4GXhqegQBAgTQSUPUEGEP" +
- "UZGTAA1PCCSJVT9owqPVMeqfiQAIxGJkYAEmkSIQjRRphCT1GTygAPU9TTTEACT1" +
- "SkiFPIj1MSaNAAAAAAAApSICIoiTMqepgUaeyoaaAaMgBiBUSIIIgRoEJkmqaek2" +
- "po0BkZAPU+d9mfOtn2399/UaZITRTREBAJMILEUSZiSKkYAEmGm0IokQKAYlDGAS" +
- "ykCCmWJBQBpkaKQLBIiZhJpSzJEhDTRCEkUETEKMxQRSIxiaGQREwxpZEg0KYgAa" +
- "EkAGJGE0ilIIhQZFLKTCMSQMkBYoRIUkFIkmkQMZhGYyJkQwIUUkTQwJslEQk0IA" +
- "pAEEkJCIRQLAGUhJM0NCzNDKbFlk0QYEaSCihZRNABJhCZRFKJFkxIKRmDJEZZSi" +
- "mhJRNkEjGUIIIGFMpgaQMaSRjJEYTCYoGlEQpmzGZLISlRlCGEIIyYMaZKkpiCNI" +
- "jIURTTTGkmkaGUWKRNiEM1ERkZEjIyMxIQJRjBkKTBJiUyzM0BhkLMYkJEwQBQGh" +
- "pGWTRjKIE0SYCUjDSIhmGkyEZlMZjCAYYkpimEBMZlEghCUskyWQyUZiGYJlEmSz" +
- "MmKRiQMLMxTTBlJoiJphJImIigzIpSYzFIo2MUASSpKIRJiaBiFAGGmgIUlEgSMm" +
- "BGIZqYzQIwIpIljMJIKSZE0FmAxg2IjIaNLAaEhIsCyTEgyGYokNMEzTMUiNiMNg" +
- "jRMMYSSQQhMghBgAGCEoEY0SkZlCiRhRQSiZEQgKMGQFIkkGIySy0CZQEqIshpMx" +
- "jGSUUKGSQogUJJAMg0YhCooUJTKEgJoUopZCiYLEUsIkGESLIajJokJjEQJgDSli" +
- "QhGIaADEBsWJJAYmkoDQjIJNCNGUEwGZIEkqYjAsbMbGjBAZkgkBKRjQGUQQTKZg" +
- "ymhiQIhECNhhmMyEMgjBMYCJTZBEhSMpk0zGlEyZSjGFFRQpIykkjFCoJoxhpIQS" +
- "JoRZIZMRmiLJEMwSJgibCaJghRAEyggkQySTISQBSIJJMyjWKAQSQKQYKLDSDRFg" +
- "gaYDJhkRBqJiSBkSyBmQJhFNBESMWJkmpEwkjEQxQomI0wJiRijNKCQQNNhaYhlk" +
- "whhLKEYJKExEESAzLCSURhIAQIJEpiQklAmZ/txdd3XdcOzl3Oc4ca53bsdc53c7" +
- "k7runOugoiVLVlto221GpSpUtitttttEqtCirbVttrWLW0VsraQEkhMxSAMkmAyS" +
- "CjDSRDJCCJBly6RMJSkkEJIMhCAo0wEkgYIkQzrd2YCBRMZSmJTCjKhmJIEiTDJM" +
- "0SUsIxIEkkRTRMyEhJCSBIBsKBMmAohgwmJIkkCQaYkkCGSJkxCMCTruhzdNjaVq" +
- "NGI1qqn/H/D+f92/9N7/nf+x/T/BM7+j/3Df5s4H91tC/+oosD+/gYNHpnVNy5J2" +
- "alEaZU/66SB3/PXf/7//et/nu+/f9KKr9VSKdhIptIjKzARQZZiqimGUFLMlVWMj" +
- "MSUU2oif8IKKYIhlVIpkBgFFMIYCimSU/8VUimSiVoFFMUof/mCin/KqkU/1/2/7" +
- "ipn+uSn/P/jZ/qZLjiqHKWmltwNK6udN0mKLpTbnFbHSxf6h/6WePKShwUl1VbdK" +
- "GyqU5ooa/vt32BeA5cSpdlPaWguWZVUxZht422i4WJpNsWzjjnNrttYxBLESWBXA" +
- "to5UMFuThmsrEMqjbDpYOmG3M9440VM3kpxzZ0ZLjiqHSXODDEyJisUWWKaaZVEW" +
- "drHTWsbg1ZFVRmRGCMFFhITKNXhUhsLAnAXFVTa2xYZviazvp7z20VOkudsVqq3j" +
- "OeGtvWOVhDnvvuoOynI6VhVKbaPHLclddm+VRwsd9tpyhwG6KG0tNMuNM0w1YZC1" +
- "SUMAuLhnLQOupddA65UOXPDKoZRXMpLJUsrlyDY2utozHDrg6uimKZS0WgtDKos4" +
- "KnPMppbMLnNIaySc5TMHGbaxTuqd6qpHacO527Xh33/xUTIdWeKTmjbsg0PYKnmC" +
- "1lVSd88uqKGOW10E52BMkmKtkyldBFsScY1nFJZktZQvRzSd5S0O9PG43nhMOVRs" +
- "OXHDbwU5iQ1kkWZEeZGOqNqS6xHOJZZIhTExGkq6rcObBbGrBOaqc8OmmJTzI751" +
- "Vi7Tx0LbY0JUgoOEmzhjjnptxIKus546uBtXLO4JkyYP+eAcAAHOD6fr9j9V+RH2" +
- "S/L/QXTV3dz8SL/T8qH5noZQLPqGwlvR6dhx2TVtfs9W4cn6VF1Rfst5hq6EbM2q" +
- "dokF7YlT+AevC278qkbLKawmh4pJzRaPv9leNe26uHhSuwBuLK+a3xCu7uCt8ICc" +
- "hqAubTDuymwW6zBsaun77TDCZizuwBP7lwSttmpSykZaG/3IVw50MThjdLpDuH0k" +
- "DTDN0e2mvqqKkAmVy9EDwysGysaREKB2NormNHUwj0vgO6IiGsJpEuyQETJyWsUL" +
- "zZWvlFrieCawpUQgzlKTRwiZJXKyzbD3ulpxiGZ3uqqknBCteytK6wxraGufXo4j" +
- "6Ql84X68MHo9PTm7GxF43W97OVuPemu2nSInel9rnXmRB4ZmN2FaIWPHWBY1gskI" +
- "XduCgbTFmxaE5YSihkBIUBZk43EhJxOAqFTkTEgZg/58BOXSVo8zbqfJfApfLFzo" +
- "w/f/d25jXyxD+I/OeU0dcx/x/aRkaa7TXU9oVlOfGYMm7+LW4ifNnrp1XifHFxMu" +
- "5IbmiCprTZzImVSR0Qa8znKbkRuKQuyr1cokqPHOIDMit4yc4kkbdortTU60qgIp" +
- "BnSrVsKMeuZ4NPFFXo3ratpwLFLGtrbRUbc6dxjlHMt30iALUHtqu5g6R2+W8fwX" +
- "w/9tjnDISkwpFIFITGooZI4IpEG2wm2m2Gk22+NttNFNpstJJJJL4r7Fo9BaHfpy" +
- "dVdT9v6/JXtG67C17waENSlYvNK2F2WomFGFDQgRHIUKMGMIWE4Qp1LPYVOJ3ajX" +
- "ij0R2SiUikUutMpXscLDown53VRa5NdNBc3ojNNaETWjiHFD0SSCCSSSCDKT2PSI" +
- "aiwTiy0mbTO6iKbZNVIZ/GZuWsmDvZ2jyAcoTPVEi8HyYNj0fsH+BpVN61a8JAiY" +
- "SJvPsFnwgTI1HXbhbNF1FnpCTeho7rSi2EUjT83q/Cmc4nETmio0AIuw3CbLSbKx" +
- "plU6HxSnZ2X76jMxwG6zEfg/GT47sv4GvUeZiImjSpzqWhp1koVUQmYgZfQYMrIw" +
- "zgqXzPClmVSyPgXckhxZXzdVcKyu4Qi0aa7hpB4IJs6THDITGdymCiiMCFZjbbD1" +
- "Zs2RDWNrUlQ/P8x6SH7v7Pz/8fq/1tn9U3lWuTf1JnUUMBZ0zXwlfGtzjVdDGdNw" +
- "/Wb/TcYvZhOV0yvddt9942XK1inv3hKPY1yG22ftVJYGIHecMa1WHrVRdWNFu82a" +
- "cxAgPKsqap3SvCX1k9lfXPem9N6bX0uaUbPfM+K4StqpjulMkJsnYV74vTdMY1Ed" +
- "oFSIZ4/h6sOvXBROO5iA46Ydg4cPQkTnMmYnMTmTOZL0JQOVaKsWLsGxYqhdCCQM" +
- "UGxBBBEJ7+U3578j0euaooSZ6QPtSOwWKBXnFoZlecqTfq1/RtQ4OItiMpbHqNXS" +
- "LBpu9xQ9UiKIOt8lmoPPrrV81xoI5KWxvXhM3vY8pR7qqK4YLstYwxOVYstg0KRO" +
- "i1fLX6rgTrxlmqlbrkE9LEGeIed9k26rGnWed6Nh06p11O87aBEwmLoD3HcEEAkE" +
- "GRBBBBBEkFZVQUUkTHdrccRvm2/fthj1pS2KWAbKGFox0dOmXvOlr51nWKGJum43" +
- "BBBIJBq/KsYn0ippp9W01W5ZRjbTSfDNkM7isVOp5Wk82WrJNLTsbRZZzsMYDiQS" +
- "QQGRB573Pe988yZmZmaB0HgHcz7ZHJKFgkEgyIkiSS9eHnk2SvPDryK1aqqqmtW4" +
- "PSycD/w8sflE+v8v83/dyIplqpb1llszKa0Kl8tWXbMGzMy8XWnF0X937o/wO4fq" +
- "0+r7tk9qe2FJ6z3CkozLYqzEKiqUFDKGP7kqsHaWq1aDYcCQokp/eU+vt7uZp4fD" +
- "vw29FcKUSuratW2rX7I00/UcnqCIfPyP4ftqCVUyNaqZi2P7Lo2/nvtw1Ntxu2Ov" +
- "M1cLOMOjTdl/Jw/jqwjhrHX7ljvTS0Ng9YWklWliFUpZUiCjOKclNiKmjWdFMjuo" +
- "dSAo96JmslmGgyCeUmmjEtITqi4DqWXTg4318osVuX2Vfa63aYJNvvZpHIUVXXbr" +
- "pPMYqxKrXRvoXCGuFnXhSb4SVZtAm6ojtvuIBkdOcqdgEZ6lcZZFN1kPKhJJhRBr" +
- "WEQyIWkl1hnFU3uys63k4eJJlSIMlKqoErDI6G4EEUnpZfaOrlixLp9DvOUpB4Ta" +
- "n2/ZW/q+fvPhH07t9H4MT16XESiARMKUE/rVVU3KNwDooJ7dlAzgnD7EhScMIYxZ" +
- "/mOidHDestpVUIAEgC0t7/m9fLzzvPVb1fK+s+Y+f0Pon6xzJ9vzOD8R9GeLf1T5" +
- "3aq222kVRIqwftW1VyfHRO+89MPe5zaktbKQr49+/jZmajwxNu3Zk7fVWkSWG+K2" +
- "a1xZlKFOw5BlJpDTgyzEORiGVhmzt4tctufPV1DsnIxdsV3SbUdlXBrTgwnt41HJ" +
- "0263X9faPss1y+iNSMUfp/X6ff7/6/TW98cccp1bYjhzq/3uXPJj5bT8/7W+nhNo" +
- "/69v1+jGyfY/aaf9UV6T6SQPl1Bq30rH6H4yV69J/bdqqKoSHon4AEpmUtPAez+t" +
- "92Y5lOj2CJ7CYdkZxf0D3R/XfsuFMS/C43Nv5T9sfMZV4L/G9pvd03/3mq9yzlm2" +
- "xVJVkOV0LvETLzsJRx4cqu6dXdXXuPQcCHb7ePRk7He904sDcwdra7Nt9q7VFY9l" +
- "7jUQJW14xnuJPn7/TMw/3fPn4+Pj6o/Cx3cXKtqlrD9PRbmYZme3mP9E/y7G36I/" +
- "LH+Z9Pht8Afun7v7tJGbXiaeU0eH+Gn5fst6/K+NqmUrWijbu3DZSH3hD6nZ+o9S" +
- "qiIxVVjIQnk5/AzMrhcclKH4STg5bfDDGO33aTpJ0rlQeHwTE4GVRAlhOxMpdgNv" +
- "3ajAlCIVM6Qe6uKg9yOwUV9eRvl2dAWQKng+meXZoWhDqzCyCFDwHzqlW653rPFy" +
- "aXH00S9/SI7ZIaPaDOu/U2err6Wt0/RGxFCJ/FfXywJ+Z0NuUscckrzN2LlS+4To" +
- "ymv403aBj+06Tl0T6Xne5mhKZXrsbvOuKiXR7e6HiOm9CknWsik7Lmvsvrn08oTa" +
- "aD3VS6R5uebW2codGHht9KN5dWRYyrvSKCuOIvhyuzboi48y0eX0b1ZEk7XR2mzQ" +
- "lIxgob6yp54pmGTlmwZ30l56vdry8vuvXD4hdHdkDKTAhgiUo5KUmzxNmilIqOOR" +
- "j4IT356J9N4UeHHbOSSOyBPJ7lSGRJEjG2PX7P+mxdE4E9kZhSbrNHt+LR6oxuXC" +
- "xtS3UxPlEzA5XpdlqQj4iqskZZ3pmdTpI2hJsTma3b8RF/EoYxU2m5oFB5TT0rss" +
- "2w8zlr3Bw9jYwgtNtPCzmmpqJwmZzfsew9o+/u+NCiXjuaEvhdu9cDRPzPZbreMo" +
- "pkxCrlWTi29L4pZEMIlfLbK+xSL0Zqy7IjaLss0ZGYsGcMGrgagM+zilXFMbIldU" +
- "QarxUPisyxhSqeew68PlX96+Vn81ovsttNN7r2tOwJnj1OGZ6GmypFEL/OURjEXj" +
- "xamLJXj4pVTillprNqvk5OqCY8vVrvLm3qoKGDgxzLgEkqry6tOg257kmNzyTdlj" +
- "Q8tAmWAyU3697unetmwupGywUXVcTN9MqL1479u2I2tsRZbvyj68/LNRM01plhvS" +
- "bN5NcjrrccL8Htyj+BCrHefe9PVPN5zrUH+1Pb6rXdo22uWWd/EfwZZbUr34gOaZ" +
- "1MdLqLC9RP7u6RSO3a3RxXP8X0wBLkn9FRxLMv9CJEbYsiOpgpUSoa5GSlIQU0ym" +
- "1JJSRLorCY+OqjQVlihaqBciZcOS7lgmERMS0iZQTN2xVFERDdrxbKJtzCzbbXC5" +
- "bTm3j1zMs1uqI3AHShpYzQRbTYKYrZRILVpDLWCCHKKFK04Pz6l9+B8QwVBx3HZ3" +
- "pHj9L3wPqk8LV2RT9q1kZcelVkMztswvhMxRjp826SggOKFASfzLUZH+Trbl452C" +
- "rv71T9Wht51YV3hXG4QPJdqV3uZz13mwrzVZnjVLbVn+YVe62EzchMqtzShLkKPE" +
- "dMnTiMTvOqRJbzVhxDI1dd1rQhiTqmcLOhwiEgTPFVyLB/BYxVVJ0qTbe0X+E2NJ" +
- "5FQil9Im2yK4hAhROqTbaIFD7Kzyqk3ny25Hm6dGXKvdrsl+j9LTNJyMbczUREDG" +
- "XgVzlti/gxxcK9lmrQmuXy00nPZ1ZnYMCOztzV44ehTr4++n1Tt21RvA1/+natOd" +
- "+etlwD45o3FOGbqiF43Vsp2VA9kWCP6ERX78Jds3aZdJHuSiVaYad/n73gTnNOq8" +
- "bUvQV1ck9/tFEv8o/X7P+1ZhaugDmvV+7UkaQ/vHB7fX5WVgRokFFMNzV0S7rpL5" +
- "fPt5HpdvXdsa8XNCJ3dO64RjAXp5PJc5siQE7p10k7q5MlxQkHbwYYb37js+uXMr" +
- "XQD53nebkY+JEQ3Kr6j5LcbHtxRKez7rjvN74ZI/binYF32Tatmu8Be6TXLsrqtU" +
- "SyjpPtDkefbc/yap8EMZR59eNbE1KJt1yzjkr8IrBj8d5+WZHW1FCToyAsXOUEXr" +
- "Wtq1r5tZb+GoluBz2+U8FT3va2RkKc6WR3ZeNn4iq1okKrUThD2MqptNGqiTJ4M2" +
- "f9u45+/nwFAQyTz4I8lDKWkdQxJJEruEVFU6mHlMh/SyVffytduOEYY+qcVewuWR" +
- "7sCx2jKWaQSEq05Vh2otTsmLP8nxVuGAJlL6CQ0fXzP22Mn0O/dc+RzxqdnXq/N3" +
- "KIZUKGEwHCFgyKwJcqXSyY9+KkWLMIVwWZW84+AK/Bz5wnaLI44LmU90x/EkyBYo" +
- "YS1EJA9jWfE+/5tRUV1ipCoof2zsjgKQ8vpHUIwQU4hNNSOW4tYulfaqfz6P4wYH" +
- "GDM4DID3+NqN1ONUA/PfuPMRXS88tk7zKq/wt5RmaVy9WAxsjPw3pHVUomq01Y27" +
- "q1V1m7Yd2KfWl+O5Zq7729d9zZ0l0p3fEcrJ5YgfbvWje7O3f3xZrowIWRkq4O+T" +
- "FRyxJpiWo4lFPH3WrGdl4cvrRgQWOs7e+Rm7Fg5SGPs7K8wII3++tGhUMYuglST7" +
- "5KtdoyntNOHVVlYkvFyJtG6k2rcPNYnRazDvM0jtv9e0GxHtPw9lbsVHo999iMnW" +
- "ySQyREBBJkSLp6BsnvG/p9faVUKlPzdQ/ZVIRVFqLwVZA3bCzzChJo/VG3vBX5SF" +
- "rWK1RZmzbONI5WDQJSoSvFrWQPYWLVWpk4wJi851alamk1f8QZvBepyqUITCUW1M" +
- "PO3E+bYpbGJWorqrG+spHFPy6ovW+piPxPDpvMK9cLBMXT02D897907tO7q6Tqpw" +
- "mu19VLVj5w68m9aLxrh5pRd60Z1Y7OPlnWyT67h8VWsGO4nUUKiC8Pu5yxhCT898" +
- "xuvPfY+fhoRK5T5qvf5+ore9q8fDLTyk2u/mia2vXGhbTXwjpwro94vOKUYpdrNK" +
- "/ilIKJN59XedxQPPGvYqUmlTpq88kgneW7DHmiG23HMo7Zsh04+H7xMdo7xOJJtY" +
- "eizcYZdt7XbKVK6OL4vQLe/M+3jq86SgU5889oFKfPVuxF3wlFrkIun9efjz79d+" +
- "wYeN/C+u3m1rd0jFGq9X89KmLLXN2C5Po/veZd64ndf3MKIxsceKwWTeL7MD3i1L" +
- "FVj6xz2pzr8QKCFNCFKpIp+xTH6JnyBsNsPitQloYgqd1l5g4jhq6cPDUvHlmwrI" +
- "oOhRQkOJcJfIaDs0KhNWaJJhi4g5WXdYcDKbkpiy7o20IRRpRFyOFooQ42GI3+Su" +
- "oMuUwozR5RSK47UcIoQsIwhhRiAXHRoVM/c+S9/l9R47JC+j+m/Feaff6jz8TUQc" +
- "fBu36cbfXyrsgqiUIyVfLNwCKvgnlBRwKKm+brfbFcOClV8LfTPJElZDw+Yw7n3R" +
- "/39I96pWacn74akmCfZk9N7Hnbmfnm+G9N9IIVf233Vjv2K+dmOqXTgm/cpSxjx5" +
- "NoTM+aO9xtTisCE1pRXSdT2doOxqKdUb7MQGth/hkgx+xCAlvCV3TRG0Ce6IyQW7" +
- "O5ROkRaOiwj2YN2coi/fFuizw675bLOfJnWg2VO7rRIEXexnFH3XUPPfxRcRGzXs" +
- "xpAtbS7eu63smcY2W+6RTU1psvDNdHE51pxd+N1FlWJbYbvu4qRoHx0s6pEIRV8N" +
- "xbCsclUVRe1t0Tr9/qt689+zMRbOMBXqvBVD8KyFEO9HimPzqLzwaL5e+3ZBPN5Y" +
- "7c/Kfp4kQCKdTjmOa/v154+n3TBe7/D3+v6r+/voinkqWoitVotACCo664ufF4Po" +
- "3J6cfruz8fcQTLL13Kd1yNXLle7zzhNiNjuuwY3dvT6en4e/3/ffT7fX3eKmQXX0" +
- "/wDQj59+yNfHDLb2ngE11HTs1D00z1Rmnx+dfhwbhbzuLp0qd0QHMBspKuzzC3ON" +
- "dfyL9+3rQfBoYPjz4zsDVN+WG7vLnXx9Tr2sSvtE8MUa1li7Bpqrgl9mbKWWkUrS" +
- "xt51NbR1yPPlQlNbX2vpMO6OipAZVCnOzMdCcdMd8ANNA3fU9nxFkfotXt+qp9oP" +
- "k+AQUQa8iUvJUoSVIGwuzKjMpmM+3+Z0JJ9oAjV234RfrNBxtZMos3vCkrhlcmZX" +
- "JZqK1aqYUg1pqK4fwfD1WX0eSASEKQ/xP5j5X1rQTbnv3OI8ip3bm/IdSENUwIVV" +
- "CBlkpUlnZ2REw9p9/blysnsiOzjy+3xKhFfg6Y9VKDt267q3dT8u8J9NhYJotAkH" +
- "UBPU1WdVV2dPq97X2saP9b/I78+d+hJa9dsO8Dq7uuiXBGuVPDdiDl5sgMgCCkTR" +
- "ucudbu90qcSryhxzaniH091sPgD3KHqWgJEDwpMCgIuFF5DDtnI77sGMf+eGrB8U" +
- "CUkTW1qLEWR7RSwstGmUIlsNwAQgEqgykQQLO1knr6u1ttq21Hb6I+XSd9/RPL0/" +
- "pE9I8J/gr8OkY248frxb8ffHG2a4zitLxY9lPyn2k/bD85+59xlp+/KfS6jzTDGV" +
- "KlCSXUKDuGBA2GxzjS7K6hA7uoAgSlLYS2qL/6jhPn+y2y2u3o2Tt0/s8v7+lrl/" +
- "tPT9O/Fvbfdk0V+HtoX6P4/h5fh/Zzr65P+z5dyH9HPb4K1fuqT5PuQMhcP2210T" +
- "TD6Tx8InpqHwj333mVmPK+Lfw/Zy/VOHTmPh/Y4e230Y6cunLw2flSdvb90NP4n7" +
- "P7x+yfRP3enyjwH7P7Pb7p+s+0w6WTLFVJtJ7fRw+3jh93hw0r/PVq20NKhwUT+m" +
- "nppNp/lXTSUy24lK/p9p+x+7bhT5Y/39es1H9J9h/LTt/Ha6djhODEY0qtFflRyn" +
- "0FY5fsE/Dp0+HL/Lb9lnh6YcP0Ym32Y/Rwp+H3k/Kf3z7vTy8I+K+yj22wqny+Ps" +
- "dv3/tbwj0m1dOmO2g8Kfo4emjSqXi3tw+KtNzhy7Y8PwY/U/sn9o/l8PSD+utZcW" +
- "37Ph7krkPur4qw0fu31nGszW2itKPy7n5Y+v8W+vzZf2Onp4K8qjB+bb8v8tOH1H" +
- "B8o/l+O9+G0tG1pa21taN/eU7knnyMCjBUlf4T4Nvg4a8W9DpG34af0dOXz/L8Bt" +
- "/Lo8d/GXPh9HDFcPhj+ngr92if2dHMPk+xw0x+XptPtbdPTbXxbFcOvGltuZktu3" +
- "B29JpHD9/l+75T24fcjp/93tG58fLFy/Nc1mOE2PTw+O7a/KsP1dPKz1Ielp65m3" +
- "Lly5mZmOW2qiqrJOg0SUOpO/Ym4AUdn91ovgujOz4FB0MBZWJO4mPoNtb+7266rf" +
- "z9zM1txqittGlEv4/jbbCTioBO/q3CKi49u7fnvTo05uxVVX8Y0CiogUNx5JLet3" +
- "YPFu7NOEC+62c7AwsFCz2reusG9vMFWax1VlAwU1dUyIEhit6aC7Du7M7VdNstC1" +
- "lXlm7XRkSLM0jajTZqNBA9IW4mqEa7U3XwsODHDZVYjuyTqypLVdoZbqcyjdlRjo" +
- "dkyjWpGBmkajVWlJ1DzMPPfJIIJJJJPAQDIGiiFDI221bW79r+Dx4685zOUWtrbb" +
- "fyOzogfCvL38Olr2TVKbaW0vvu6QF5fnnbMxw4f2Y/dynRyqptyw2Smnj++v21rW" +
- "uHL/Sh6afEfd+rg7tq21/aO38mnw4SfDyY9KYm/9rcSPu/X7Jy8DtpVNp/s39X6P" +
- "xVjyn28Mf2culqrID0/Z9WNK9+LbXseXB+yp9IezTttsnsw0m2J9HPXrTWa1mZcr" +
- "Y5Fj9fX8f16/rtx/W/7ccT29K9P8fS2fRp+r4CerERJEebBr/HVX8Y2yv6ZK4N87" +
- "Oc3/UFSf54kQJDPt4hEQISiNsJ19vv6d5ePOXnLnKlVRMqnKJRN8HOc4eHnBzoIH" +
- "MpAZ5mOq2Kzf1XTznObSPHfYLFdt2e53f+MGA8zED54z4hfEg7rRJfbXkeq33bpR" +
- "ebgJAwUvLQPVZKKFSSDRYI4wwgQCBcqqHmqrcrro/+ISKcn/1pVyxUc+791ve+Gi" +
- "7f91U5/UtURLrEFwxif/K7mLJLLBmTJklllMbAuMlEryqfWitYksSyFR0c9WGSW2" +
- "NMjKZLbGmSTzVb7Jbba9lttvnPje29ykZaxopllRLYrTpUlc4iY8qqyI5d705MZv" +
- "u1ZllGstGZYT7z6Z6plQwqduumGQywMcHwrK86pav3RTHhW18XfjLFYyWbjorjna" +
- "TttpVOBUpg27Ou7MrMMyszLdHBzymitUJ4Tz0dVMpiyXRJDbskep0BN7JGO8mdHV" +
- "Pd1TStUzfsg4eXuWE9PVt2juEFWDZr24eiXW5DE7KjZzEOuNZG7I2ocWRlLYLVvF" +
- "GIucZOLIbpOKjLLUtRat4sjIGnHJoJtX59aGaxoZtSn3kjr/BfvvEueqYoavHjKx" +
- "lfTkQc9PwqlPyjh+1Tjaztea0tZo/XVFD512U2EDj9tVTpSLeu7zGstZacdMaS3H" +
- "LvcS+9fHUcNsArlVO3L8To+YZW3QdvX46+4ZlyqnDs2vzrkqcOL7lnnrnu8/OY54" +
- "O1Vp+VBoMO5sxa7ODUmwnEJvqyTdRq22yZN7KutPTVelXigrJvTW7bYeEeJUxwNk" +
- "NlWq21IcSHn3w6MTx68cHTacUEfeN4zPFzT3uFY7X3XTNafe0tNeKqbVU8s+c5mt" +
- "7E7erU+HTx2Su+OmvhpwPmcIeHwW7qx29oNMLvh0fHz44pNODegO6ZMEIgYczrCT" +
- "WdKk8MDFGSiuOOdBzS1zZzVoqio5kOTtbKzi7aNMZgoHKdbV9Dlq7N0h523x9+6i" +
- "49cdHhy5L3Kdee8uTrlo5JI8MkRs0xx3Jy2Vtbxbho8Fzs+RYy555fVjxRvjk17q" +
- "u+TeMhUNSCJxOGSaXOJIampROLhmaO2zc6CyY2kbd7PgiY9Mkmm76s3Tx7yp8fnf" +
- "E1+NlrW6nhoz1fPXb3ymeTtuRGa89uIgybYSRnch0uU2n5K6nymfCrxsnUc7yc9N" +
- "gY+UCpqeMhw3YTjNExOOB6OpwmBt07D27E2yOkgo92SedsjGFb5T4cKHWuV2M8cF" +
- "8zMy4FsuJXHLaRIdimuHBprXH3TZTtjDi8eLZ0dKHf427eFdKGF72HenvID6MMOn" +
- "bCLWNsgpUEoZZG/vyoPxPnHd+D3Y+H3rpjqclZUisODjFbL69xIOG+QclTpogxxw" +
- "qNO9m2ni+V9vD2uz1tpoxtt5t1PjrlVPhy7WwKnZHuC3ruTKRLY2yUlqGlKqWkiW" +
- "y9iHnhPZO0rN94N2brW8hut0yR51BrPKXs7JGxb5AnRiZTl2Xq1hpiXy8iczq1p0" +
- "4OUvW9g8WPrtcenxbXL58ic8LgbnL1I0m4MeNSM4zVJrWW9uI3DW3tqHzluUwxR9" +
- "+s0Vc0hpweORY4VOtNXbALUCyXLqNFcCR7xxw8jTkStO873DPfY017vHfEhE5xAu" +
- "lh+U9Pt+W9++O/u05zeb4c7pzjRaWurtlU91y/Pj38bnSo+8PfvF8I5SNJ62aL20" +
- "QZtJUXrrTO3rYPXw+NeuFWmevi1C41Gt1m2DMqHmySGsXd4XEMFkBpCUlZSTWAUm" +
- "a5gWmZLEQcLCwtjR0rZplkWrZuMqsNpWrMyvBJ5/Gff5lT3FTnKql0x9H4PU/DTX" +
- "OxAXime7qULq7DqoaFW7tVaVWymOAghDdEltpIwwyIooHivfPjSHoqKy0NCBIRpB" +
- "IGQK8fXhPBpMTMhc4OCJWMuxlIYammJ2sgEEXEs8oDopthFpLOUlVTJVAqKGFoiu" +
- "fFmCKtsq1oM33uOW59vV16cDSvt7p7+u80IySXnVy5lF3Mz5ZLDu9ZrDzoUPrekc" +
- "9Ie3XnPlekWLviZo7sWzm9WT4r4vmvd4+Mn1zI9eadvv8/FYv0fllb9OdHfmF98c" +
- "xiihhSVRBRSemqq32pgz4bzMD6OjNYamHHHp0WsLbYyKxZ3mLD52kY91zW6fPB9d" +
- "GObcd2fPPjX0d4du7bA4tvfmSzb6t9NouC2GU+LHHGJNXK4s3xiY6MfbxT4Z83cZ" +
- "UuZDLGk0mY/Z/iHrRxSY3S1SG9mvzS+bvxc44Th6JqNHLLC4ZR+p+NfpU+sMTeHg" +
- "a67ZI7LO0gsjRa278NqHpyOH+PRsdMcqF5x65vjp0KeJjqR4dknzo+Zsle+oZmSN" +
- "f8ttztuTWnh+4V2fpXP02u7ttibExiUsNhbdfPzh1+rQ09U+enFtXS5qQkjjxMd8" +
- "MkkY56cYwqZcb6vi222vU9cyYersXMh7cOOI2Y7Viz6BNspac/J9fjp3RQw/gqpU" +
- "1kIPpx1mbn6DEJI5wLjKElOj3z3XAvFr+HD+fSn8rhs166dJp1CBw82PeVw26dIv" +
- "7MUi/KQbLXXHt4nPh0fSOYs35zI1WtZGrbfqaOvlNp6VywnitCl7G/RjngwTGOXw" +
- "v3ThnnFFDb8PHJ2lL1vMzxiXS7Hci9P169PULTtp8MorSZB25VNA4Pw6X609+3Vz" +
- "WTVcyRy2dbt8H177mEWSRvh8M+vSerjnx/SZfuZ0beIXSUuzna/Om+czLbbbVfTz" +
- "54naAdd+pE26qa+jh4iOkG3g+U1FmjxmGX6Gj40+jLEntyrIn7/D+T8fy1+Pjjup" +
- "Bc3CtbNuXO2tRdulIu21ItGsL9ccDt6aEtrxfwXjqcDx58HqqhesQkkFR5Hw5s+Y" +
- "95rjxZ49Zxzzzs55zny5Y/Trf42ninShp2tC5MykPXPDq/HSuOcy/Hrg+uXOZjhw" +
- "qpi7evQ+G3aueLbIW2pPLBOXPB2k0qeWcvH8dPX3537NGVVjFVhhjKxliVkqkjay" +
- "ptqZq2S1WktJVZNtVJa0VtCm2mzbZsiNNZVVSy2ti1tS2Sq3md9hy4638z5PHNMz" +
- "Ix3IfMkD8jgU/hevg0z6O9vrhfx2u0pdXi4ooddn1WwLTt3u0dtfx13/DwegMQYQ" +
- "wdp85zgwAfA3hJq69eh7Lu7zLGHl5V6eivCu1elHunTwnjRy61p714uThUcOOcz8" +
- "O1cqxabWOunLt5Rw9iSJHt3F3y3WWZdtujHhx50iRPHtKachw2vnz8eK369x98Ov" +
- "hw2vztQt4JRlnK9QFCycOHEpchMB0Ym5SeIlIUMnPFcafA3klDSwWSTX9VVFP3k/" +
- "KQ0+nzF4rj5wtvArh604+dqCN3Qjz0VcqypVmrlXVlSVcqyiSeckRld1JlJlRlJB" +
- "zmlk1LS0RqoTfWN3vzzprfXjY+ZUWT9c+ednqsvvSSJCkAXphQSFpCgXIwRJFQeP" +
- "HfxpU2Op7pg4ZhX80D8P0HcE+tvtafe0PslS2h6bEUphB+Trt9zcMySlFfrXx8s6" +
- "aKGUneDdfjQ99/yYfX7l9meCDI/bvJDJAQgdu6SzNW3eZlBQykZoKrwo37d0TaW2" +
- "0DnfHOPJfg278PvnXg+re/l0U+vfj83QmJIyIhDN53JH5Px9XhPr2/DXcY+NzGJO" +
- "6t1p8J77+GH2+xfbwXyN7S7ySU8e36ZcY2cmX9ZqJVTbyyJ9LNd2Hy9pFJjOJx48" +
- "YJh9fxDDVU7nuPtjdzVxq4025elJxy5kTGLIXu3JDla90qnLmi/u/hOXSqnQu+mf" +
- "lpHZt8sRqH7saHSSEQXU251XwY4dOFRt18lS6cUnTgWreu+m18JO/RkmYWb9Oofm" +
- "aH1PPXk244ZeFEhws+fI7cknaR6D4fDdfBuITwr5+BweumnDtjA5GjvZpuOHS0si" +
- "Djw9vK9vVXw3M4takTts7RicqcARg31RQ03CvXwCPOWh+DxPrrPL04oI3S1HWXPL" +
- "V28NsefHEu5KGKEqe8NJPYLCCHQMJCQ7PR5y21rbPLh6zyKm7rpxn60/GG3l6l0b" +
- "Mqm2VCL8CsOWG2Qe5VVUemVS2xUlz8FNVTjEzB3gTsxNJ2NL8fkcfOEhUaCuYPW1" +
- "wuNRLHrVBHPnUBbfGqqnLbx2unVlEqcfFU674T6+c8eHON8cbcPxnVY79dPSQXrj" +
- "j02ctOXInljHDTacJEg5ZB5GNDvHrWNOquSOU5GHgGIrXB8Q3PTh49XFuZnMke3D" +
- "Pi349tnTc2x78ZbabfvzMff1Q00qpoqlPdKqaqUObw73hT5rm2u3Djb92qrt3QRw" +
- "acoV3xS8qpNypaaM8CBy9599F75+N8/OM7xre29w+OXpOnjtyeGSEgrypPNCAvLz" +
- "gjvv0nE4N8L06x27SNPjUeRJEjXk3zlzOGsVtiMq9O5Hkcp2VPh8K+XJ7XZx9Zvt" +
- "531nPHGb550jpsrvKpnZ7X182tPp4nB2m23Dj50a+PuHwWvHvJzCvWfD1elNOsfN" +
- "SEgw75bTbwkkc52410eGuLbzmZkZvvVmtPrz195lSMXTdO+GvWa25VN0UMpetNG+" +
- "NwU07IY+Tmk5PCX1drtxw6VwlEnsyq9FxYhCRtIhPTOT09a7ZutZpiLA6pDtYY3V" +
- "5igfFU4zU4brTy7ejat64Qejh0SJHTSTZ3u3h212EB3mgeekTleTDmSOOVnfrh6P" +
- "Y8ntJJ7Pr2KTqnMOYbga2JznETGW1bGqmrY4zLwt8niQD18xElWURb94FyqjnAZ3" +
- "z6YJ1iOcC2nMPuqLNVQhSiLLqoyCroXV+YwVxq9cddcOZJtS0iqScZGJbLQOBQXO" +
- "HE9q+9mbo5znrM8crxzyCVKhGIK9qoKpR4L0FF29epznKxmhKoosQGVDU2h3Ay47" +
- "SFIJE+nw88FX5l03vzu+JfbrzePF0kBSZvDVsr5KaIWZmJzqUoIpQrMhASe/z86c" +
- "6HyL3ZqezLvn2w0+aVZ7vTMRFUZPLRe7Rk+Uox4XrFfp8/Xz18+/jybiRw7VvURT" +
- "5MeVT3Td4+Ma5xHFTVt3xxqcror7cx5cZbWPo78+Fcp3j1jCSRIxTy4+XByxM192" +
- "To8aO6enDlp8Tpwnp5LwvE56l2zffqYlRPPQ4gQywiSLYYacvPXtw/DHocyrt2j0" +
- "e/enNm57m0qsB8YrRH1Lrhwgi85HTIViqnpHjX5odbWnqdJNpywNzy5F55CTpz3b" +
- "Offvji3GWujD788zPCvnTt/r5SH4mbMvVznmrtcufVxUd3tFD8H+XCVA9+aArHR5" +
- "t2MPNpfFspyylwe0mEjs5oJOvfjxfnnNXNbdJPJ5YcaYgXzEbNNe/DNpS95PXWbX" +
- "Lj5me++lriwkeI4ck6bca2nHauuzfPTyrxRXIm23TPacNjajfNUa97T754q3c0rP" +
- "IE5Nere/DaZzyBPTHL667M6YMUiwUw84c4W+5rlfVR6zxCzaeKly9x9x6DhaooPI" +
- "1CNpPHVtq129Z3bpzpOM14nhw8c8mvgVGdYiu3n1jtni6FPTxEt8uOLVAnqxzGvU" +
- "4XXlc09EDkrS68VHEuLovfh0kKjn16nx2624KnuSnHXYVkIprh8uKrXkxp5Z3aqc" +
- "aeE59GkSJ0a8drt6aX+06Y9W1WYqdPi+di9Pw6evm8zGnrTzvvv+GSuG79/XDiov" +
- "H0qepaxPYPTbhXBj1xR4w6Tg6NcOybV4+Om+3X41ItLvfGlU341TWO2R7tSuZO+O" +
- "3asyajzIENvnh5J4Xw8OuDlfBN8GUCx4420ZVU52z250coXTppy6fELl7Rjpy+nP" +
- "x28cG3ng7sNCRkisEe3Ltzt62dtbszTgXpLw27ePvRw+vlFcKR0ekbTaMSHDJB5e" +
- "nZ8vLbTt78dG25fCwkJ//etW1scxPdFsVVsi0tFqS177RsuXJMklSkhrEjSwORa5" +
- "3WlxTnZfjFJJ8qqYtJkGIYaQX+CRXd/3dKH8uAJ8Y9cu+OcSSPAL6Gs336Z468Zz" +
- "vNxQRIyXt3dm7s0SAwKIJ5wEk8AwcCHFznBwg8o1kzNO72t3vAPY+sfngZ9dFb0o" +
- "+X4H6XmWneYezTTiKIZ4CUUD4QEQCdPGmwTwkyTaXmJ2d+i8PAPAvDjERepd2Z2U" +
- "tFeZqfopOh7VAjAeQ8BPpenxxACAkEQhEExObQ9XlR+e37Iw1mN+ICD34z4TEzKK" +
- "dyQ5oUQnsRgHH1l1ker09IZ4KIqyrFUOLmqZbKLYUGaGAgOcGgdbwVvRho1lbYNU" +
- "cdPj1zU4ogY7l1TxfNNPT+zP92ta1Xu6TpY6QeISM9/hrny59kjOErh+Ht2BPj57" +
- "6L5BzgoCDQAx6HNqd9+Dyvbt27Lq3osAuFDt/Zv5zu78vxMXPz5rDDqp1z+Pi2nh" +
- "zxuQkFAnqvWm2HD09db9dvJvpZ775mY/Nd5n5du34vVU6F+N+jTb5SesToqJfaen" +
- "DXwdO+bu81I8knny2dLk+lPtFD493Hx70x8+ZnD/LrkygIFr4AcZGrTDQcMwVWSB" +
- "UIKC4cStoBZZEzt+9tptwYhbUixKXVLSo3XvhOmipnoTQ+XBJCdfHJ8r47yZmPlN" +
- "tp88W+HnzreZnj2dX2cPfT3zCQm3ifI8tvCeDfBNnl0nnzDynndrPNObjUhIM70k" +
- "+Phvzu5niebfbE8NY1HHuJBzqbt41px6TjT2wnuOfnskTlZwenlVTqj+HnLFtEu3" +
- "oQOnRi96VHqH1D1c+g/IZ9nQp1cZlfv1606UPjEUVw/C6dh+Pz4Dro+bIdOl2OTP" +
- "vLTZ5+7/XSX29Bv0PSCdHY28GJ5eY3ddXvTet3d8H187Yn31vrt8fNKu1D4+cOuX" +
- "InT13p65ql8fJv74217Pm/vXbqk3NtnkqrqnTkK7wpfdhA+r975xmcNIp7Twznji" +
- "evTlp74w9peduGxXiNdczaymNYnPSSSSFdH57db5cA+GzcQeEkOBjPVentzlrtHQ" +
- "fBtWJ18UIb3yjguww+BUcg8J5eHbljZU09Ja1euOjrmjp59ooZ2hzKN2Qay4mLA1" +
- "pTOLMipVkiB0k7w4rISoDm5vGxYTTI8ymFxmtm+OGuNY5ZPbcqyxJP8qLkqcrsuN" +
- "XvVCjgr1Q3zy6o5T0ZznGJlVeY1Td52qu2m5V2aq1GXbu10ddY3rOrpy0u3G0gaI" +
- "oCqoGaZwMADnKp1up7vrdzvSOe91CCUrW9pWJcngyfSVtIngw8zxCUFzpAJs+tb5" +
- "Zsn1j4Dp7628zYe6Rgm2wa9FYc1vkPNMB5NQ8Ic3l160dXv1c6zek8W9yRs1O1TS" +
- "z1rN1EhwklOMD2NGX6ryTXTqgq+B6Y+TGD0AgzsO3XvudNp0bcBy7fASeOUcunRo" +
- "167Ew2GNnFZG/O7eEsenI5SHrvvWZ2addPjD+TtfXdODuwvq5huPLaODCtE0ntOn" +
- "L4e8t7dJ5M07bNC1FSRtpsdzzppPfI7dxw1640x8bjJekxsa5Y8VNtjEcBtCWwcl" +
- "ZTbCJcD8HrfbHN5KHTo4Fp819fe92ONY4erddMSl2w76PG6tcHtZwrlPXKVGjFac" +
- "1j+rOTbp5jOXJwuP10ofsoU9Td33dv3n1t2cqdfj9Pvyqk2efPmZ48XTl0KlODvM" +
- "5h0nx+MfdEOnxtt86WaVU/eucz4+eu3ZVKY+v3r850xVTdadrjormihyN/evHXTl" +
- "OFR1cY65NTCcRp8FenYLLIlUW8sJOnpScPWt7tZIJtsSOmHB33atvt8eF2+HHiQg" +
- "NCRxrt5ejjpt8Lh0U4HvntHLtejv64WuYovx4cvjudsIfUUV5bOXl6xXKF8KXjpP" +
- "vQ+fOmXao1fF8OImWnu/i1atr4deV54zS60z0kRUkUeKm8HijJ0r4pFq7Fh+ZW0p" +
- "aNBfXr10NlfrR0278/Td06Kxn1/HSm+H8Kqdssebvr9V00fgPx9owrAzk/h42KL1" +
- "67fvfB4VPiUIfGBcH0P4etPoVyKa5fXxT68OOsAuVItPWj1w165dPPO3Prp1euH7" +
- "9fds6coXoqU5gR9Lj1cVXDfOfUFnHKJcn73553ve94fphI76boE5x5eZtBy+Ht3z" +
- "2NsO2PGCnbwrDt+Pq4KodNhA28Ozw9e3Tlac0vVRrljGXXjK74Z2eHlKbXHRrpJ2" +
- "M2gxJI5S8WzbWJB5fOzzK0ngIDK6THQVqb+66e221x72x9UW+rxDexdJ8d+/O9Zr" +
- "M1mXw8jyxjie+j29RJENvabZofCnhWL1wD3ljj4BcQ54OO0GkHSQe/IN7t4HfjuD" +
- "tPHLp3KlkOazq8sUy9Y3tjOLJlCzMmaWi4d78Kd+VQ0sVjFFisKSwqlNNSpaCyMY" +
- "JhUqbN41WLJEmRFsshFLI70wpzxVDVJQOGVDMCz+Yz50FeeCnxee+p0OKhjnr5nP" +
- "et8cb4wgYO5ud9c665eXro2ZltpaqQ2VAWc7xIg8F9WbmVmuss1wH46NPSq6o+75" +
- "r6ndGvN2auHmEkDx6GEenCEQjUVKH6S7o7nqeTy/VH1TrvmVfi24LBBw8xYwSNpE" +
- "8sJnV1c5fbaj7DwBMORMfPLNZvLOcobrd4s2vvkgcp4VXw0SckHZ8PbX4yw2pF80" +
- "01SGzT3e1kxTTTd04UOGN4uYNHi8W+3ItR+t5UkOHvho7WGOo9fXnnm5jU28kkcn" +
- "h8ar34DKQz8PS+0UNLpvX12vxVVT4FixZRLGVTCKg7d6NpMKY20fHFHbPHAd9cW8" +
- "W3B6uvHn1lut71682+3b0eekCcIhIfPBfemlNvtyBHAV/OuTYkcsZ7vxb3PCthAc" +
- "J5Tp8ErwsxlI0n3rzjvR4rr5meB17QHbhSBLIyHa1ZzsIKrDw6gTDhlwJiwFxV7C" +
- "TiTvjH4uOQLhBYpFs7g9iZz1eObpyecFTp09Ydve/h67KmyAMb5631VNtmzEgiaH" +
- "voEEA9jOcHBB6Y5jttTflN4ntsbyJB2kkiqnekzu324+Oz6u+mggPLyZ359BJ5B0" +
- "H75vv+O98cccbcv12976z0kU9dPnSF745HyYQ33cpPXoOXLOhUp0DfHblUbbed8u" +
- "lr64ejy5Ydw69Z2I9N+ed8a3ve9zh58tTm3kTpI2VpN8Mb84XPTbiYlSnHxsVKd7" +
- "5NOQ9jvhPHro9jznCFWeydPNaNzME08nR6LWss1Ouel7em2Jvht075zNukuFDuk1" +
- "adIWgfePGTgVKdrr4ziPTO8PPDtjuAh51atsnp486Ws04OcX3GrzMsVSx9Po989d" +
- "4u9uULJywb+G3r10Y9F054GPrm4+L04ZJJkqxvxw8zVtr078cZmaVPNF8eWOnzjt" +
- "m+Dzp6MOXKqbXT5aKmzzblVTg1w8Fy8+g7bfFrpVSnXPW1fHbb1XDGGpmJERNfAa" +
- "YbUdLIY1MzGDJvWaVJua1NSM8i0YiLdVbblrW5bVtO8YJSMqFKEhgmDmWUhjLJDM" +
- "DKMoiZY0CluHGm7ksuQolpmExItaAGFEt1JhFAmUBNrbKCiJTAyJZtArEMXRREHC" +
- "ZTHBRGRExxlmSkstEbmFe7IABXoWWFGHTOoGks2lkVQKlwsertIkulaYxU1YkYar" +
- "IugRakIpIA20qUYZmFcabhmNazfPjwNMIdbaUG3czeq/mv+/sp9452V9fRjeX3nA" +
- "+uetKRd6dGlzfHRVjgAwXV1frY5IFJFDJHyc4IKXOHll1l7lpW8epW5ML2nMCWfF" +
- "zdoNoJaHyyw0D1bEtW98yTVcnh6l4fNM870OjJT1pY+N9aOlHSOoPVAjvfOy6XY2" +
- "YjllLzgBwOAG54zy9JMd5d5Q8hgek7RpQ8GnkrxxqqbKdNcHfWnS55Ncmdbrjhq8" +
- "o7ZUGlvWBfCumh2vHI1+9s962fXxMfAcquYF86TrDOPl1vW8b/pXKecTuBeH0U+L" +
- "2fGp45XJw718Z9c+sP5PnLvB4ymlt2KlHLXaTto+Lz741xvN7za4jqJInjts1qe5" +
- "S8qL8mlDH49Q5+dZrXjzpsqcd5m9LldKpvtv4EDZ8DPrN/Putb32490+paWvg7pO" +
- "vrlKWmnnI72+pedYn31Y0duGm3a9uBOGOHp0h1SV29OedcZxres3mbt32npptw7E" +
- "xetpdUUOnblLt5m2eaqlyh4KfAeqHL66aztyzHfh69Zol/TfR5kRkieuPNq2+3lo" +
- "JODHljhPalUp+OsY+bVGsXp3+KNK9OtuXLOAJqZoZPU24tuyRwnGurXKohrzvvvN" +
- "a1ts2nXKnipqQDwxOu8bJI6ZfCCZCNw6XfbiBozK29Oz5zmLqvm1x9cipT7Klty8" +
- "pOF329uON9fPvbr1pzeMpPe+Hr3sIHq4+uc3mZ3PLvZO09OHTzESDs426htwdn3f" +
- "VRW3ZttTnnnM+rHbw7G+GlU7XPMqrzx1qcbOsdvGePMYn1vf33e97bkXTF7M1573" +
- "x3nTpy0frx3VKHxzqqHTh4ED3htxzp0rR7w7XpnFbjBaMsMAti2WdMGWWphmA3IG" +
- "ILJKMBLTKBQMAVWSsjIorJMWW8bZqzbphIxqPLNyrUqhpj+j5VOekvjvVUYBwAAa" +
- "KM8rSbnby5mMvMGZKspWru7uiVau7t3V3cu7uqaSIWAE8B4eAc8bruXXY8ta9Ryl" +
- "s10jpy+y++675d2EUSCjzzqZO093qYXV3T5vii7tdBPVdZIj3ygmbS4u+tw9U5gd" +
- "efWVrXZ6tawSHPWTXMsxnk4iq+i56tphw8+ToZ4O5ATgW0MkEcLw296lNsfrDk50" +
- "J1jPLRV90fWN0hz8XrpcPBenvXi8edeZs4mllq+utW458+TOnpnKJE+E9OPI7Lq6" +
- "OG1pjRt3w5fVc9jp+Ncu5Uh7FTth7vi3HHbwktHIvTl5d+3CHhU0LhwySh1NMXTX" +
- "faqcvPWZmV6OkmSyxFrWcJrWi1kksrvvgqr6xW9zj1ymeq4dcNajmbSDkR2mTlry" +
- "5AnE7fgk9Tk978Fs2pXhPvjltkl3AXoF93yfjrr84+98655556eaKe/TcvX8+tDp" +
- "+Pi1RQ8fdUu2pvFdMbdPAQGNN8ivU7S9Ryc166k8yJc5IdVFdb88+uu+/zeZveuG" +
- "j1wuL35UllCnrTCt7IYcNxThFFbQtqjNZgXr60baY2hffWp4+ubvM/NIWzW5Uj1D" +
- "p8eU+ZTg3naukLoZzl+a1n3vGta8samSFp7nvlKVuVxKevXTjTg2duJ3SfNK066b" +
- "lwcPF5xw2+0cZJzrx68c3veNZrGOHXbTSSRwPSDE242fCWz4vTsVKYqOF4bx775p" +
- "0xeOddrOpVXqcPaqqOW22WtV88c4xmZY7dL6ei956V67bbVtWu+nzM5fLQ6pS9sJ" +
- "RXrzSp0cNSpHqF1oswXg7xoeipTO2OO3gSMFkwqyWwWmzzmd5mSrkIb9W0R4V052" +
- "4SQ8m/L07yCFN+NEinDh32PHfHDzfDTYp2pF9vXXneZ84x6vcPRzRtDb1rS9KNoj" +
- "G3tt8trVSm4nKzy3R6xxhOMVR5krVhMyjGXOrVEkqjaow3ghlCSpZNWBcVaxL3Fc" +
- "Y9ZJpkrnJzlzh3m8wze+XP8uV2KlNuHovYPm99afPmu8VUqUJ47l3jmZl5eHCqbb" +
- "HO7xlEBFcBA5Jb3t32Zl9tPvd2smGycKE9uyfDQQPDS8Ltb4qBF9a8qnudmpDwX4" +
- "+wdtdWPrzp5ZJ51IafAcnZAsPkypcqpRFBAcxIYWs3vTR50fEtvnqdcUo/dUXwei" +
- "bTydGiJ4PFIOWjex8NM77ddunuIT3rfm5Wc23BHly1Kmmj152czh1j2qUpWYqJEq" +
- "vL10rcCedpLOreZEjlnPpzu3bt2Pe9pIbbhG5VdskX49R4c9PrbZr3tVMdOn17de" +
- "nw+aNedrTuVI+Pjo67O359n1jijiSSJ9jstJAwAWh6D6ObOekTEOeh3nAr2g7ynr" +
- "8xXTOMYFcwj5xiIpx8cwczh8LfyjzhSPBt74x6zvdzHlySLo8nCSRsk0eS6TRbxm" +
- "Z3wnmxmnHMkNhygxjtJKwkU83mOviqqNjty5d4e44KmUaw855t7i6cPI8nbp5Sqj" +
- "jbpFk2djdy3yk88pG+mJSHbOXfhw58IK24kkSC+DzcXXnNW612O4HXcPOwd+O0Fl" +
- "8PvuZjsCx5376uzwIG+WIPHLtDGueXTEg7dMzfR0JnnGHYm9idAqLLCyKsqxZVXx" +
- "lbdLKpppSUky2SmfGld42pFyh9d+861rCugePr6r6xOggdtdPr4hx457uTlQ/lju" +
- "vcrnltjnbtqu9rUk6cL7e+9cX1mt71d5mJrs2PD2zySR16d72kTx67dPB2rKOy76" +
- "78XpyWhUp8dXq0t/AX04768zWa18ejz5cuUnls27TZy4O2rxRtxcg11S6cfNoYO+" +
- "+madlcs6drb67VY8K3zSk4YqtLvupO/Da6JNXUsg3mJLapKtWFixTMIxiMYqYxW1" +
- "DMkpmVKMqXrbSzMt9/sqIqP+t/93+I/0n5Sn7T+QT8zf0X7f+TD+B4CttqUP4hlE" +
- "RRRTARIfupD+YUw/Q0KfxO/YVFVv5cOFw/8J24f+hMf6Mf+DF/3MXL//P7Nv+9/D" +
- "R8PD7NE/L5Y0/73/Q5TalV9v/fbLbfTY6Wd/hbKsn7vhvhcttfh9p/Rx9F7ThpoO" +
- "zo/of+imn7jnrLbavsef4r/UcA+RPuf3Q+f9UqkU/8ap/+MFIjMqlZkqslsVZsrV" +
- "JUlRZLa2yy2qaRaWWqRTKzaZooGCAwg+x/nV+FYg+fi2+gz8s/Z89W73ufUfZfMZ" +
- "rG5jSeX2+tXiLy5tM25ZFqjVUHVXHVO7t3Rjfk7WWV5Xd3zfCC7d74/Bsvzb8BBp" +
- "uu3U3zvXOnzxjyszB3F1Lpzy88Auvjt8OJfX88hg8tvPa23zrze8IBCEkACBACSe" +
- "svoy46IiKqqiKiKrmbpczNUAkJJCTVerLbqur773rXpy1c6c7tea+Z7XygAnXQEQ" +
- "RJmCo+i1VHsgGMnt6oTG4h52C6u8SvLrMP/waB4Bwc2A8sBaDwhBB/o7aeobMefe" +
- "uPi73vZt7rVet2rb0T0fQ/9rykNCbO/hd3LcnNv0nxbJpOOM9dbX3aauDKzP4RVk" +
- "8gGChiP3tin+2Ko0zGvv8rm997r3xV1pt67QJwiEFqEG2tbkdFH93DBwDjIPBfPi" +
- "1V5aFeIAHWiKoxX7fYcN7XsJzs2YByCqCB9JkFUVQVTA6PRvzz5effmf8/OC9PMp" +
- "C+ZtzACFV1K3GMDvG5p00Ri2rRwdRGfGJGZluZmRrhVWSvlPXhbVm0jUeerZfHWX" +
- "OyPb4dvG7fq7d2YuV64ePXrvx6mb41zvjnrfDiqrwFcQ9VbJCMKmIWYsyFKsKZAp" +
- "mGYZYsykKYZSrJYGZBVZVDChZKsAxJMKFRiFQZVKxBZKLJJhJTbbapSlmzRec3cV" +
- "XShD4BDzmq1wkRIYPpUFVy20DjqcYA1wAOHwq+O9r3vWre0sCbAG9xdKyeSrfivb" +
- "QO34ZArRrbCmGhJ6LPbla+t+POc5nw7qzbdSzdq7p0eJSUbVXZtq6NOrQouWy7TR" +
- "Es2HZNRu1Stu7Ysi26gMq7VS751zzvXPF5506HQJCRi6HLltz9uN8Xm7zDLmXMwz" +
- "p7a33LluY0zKuVZCe1T/O/Vl8LrrrqrrpOIUG2dJip/z1f+mv/K98HqwOlWunXPV" +
- "64nVSTpZbdoyVil8PHTcq/c4iSP+Kkth+WA/sxSm2JD/tMfEf8rSNT+n1kfxMmZY" +
- "y5UmMVMVJ8ZbwcyYSf/ThUxkMMoOz+R2qaP6HTarlv9RaiqxhI8PDkHT+8nW3ZOm" +
- "t1jbpR/acHDtXbA6Tww1EzKi2KTySO7N2ZTCkq7jYh702RpxAodJwef/IaXmsXK/" +
- "lMbLbeD/FpyuGQfEv6LSrGVZhmSxSSgoikttRbLU9uW0NrwxmKrwfsj9zZ07ekki" +
- "Ej2irVcqtMxjTEjVXdf6P9p/KOcsyr/syrMkfUEhI+3yT4fG7atVVren4qxU6V/T" +
- "taOFf5Mj/xYPqwPYq8bLlYHT7x9X86t2frOsP+5UnmbJUjANvKTCvZwkj4T2/Xbt" +
- "J9f3uJLlxpGGJJwQ+9LUNxUfu/pLKj7vl9RwfBGH822fqJ8ukk8mkR2V7eCdNCih" +
- "4rqR/FLZ4nb6xyNCn1IfeRyyRO0OnsT1CDQ+jZX2q4iaXcThcJadGG5K+NMY2w4X" +
- "V16pdJLb4bb6ykpDJjVVSiyDx2/Ppatf7fHfqTzbxrUmrdbU+rGg1FD5mI/V8tSf" +
- "V8o1D9E2nlH/Sfrsr/yHD/OP4SeoUU/V+sYwlSp/5mPQ/3D64aVkKRGlSewWP9VC" +
- "GFgUGZCQwsROn6CqH9BPpvLYlK20kmjUqRVZgh9aaGzdo/4oxbVDFP9/xGOTxP+x" +
- "g6H8uhV0ykMME8OXjcocLSqeqxYyhl2P6/5Hp5nNLf8IonRUqUNjY/DbO5llxWJF" +
- "SKUSsy3EiYhPJ+cGHd98MzE64M+DAkD4YiKRisRkTDMpmR+sxk9icopWw4WnC1/0" +
- "5aVMf79WMpaf9tje5Pm9MTeot7xUVJUoSR1ibG8TG+mE9pDBpFKsllWe3HKtI8x6" +
- "SfEmFttpJpEsCWDSlS/NdtwJ44ls8MVRi1bmLU08xzI4bQf8lyf3o/X58cfuZXke" +
- "jA9K/Wkv/oCpOX8AoptO3imxpWsWZVKaPlFYOn5ekY1bMWGWYopWjCWGKaLTIGkP" +
- "wFSZp1BRTc+o1ds/D/mY0uThaKlVSilOHlj2XFcG5JxLZUjayIhAAACEhJTX703r" +
- "bKxG0kYoRihhijZMYwxZWGEbWSBqVDlZMpZTZStskllbfWleql5taVJKGgnkxRrC" +
- "VSqptInylG2SrIwx+wwoppFCiU2sGh/NQbbQhTFWSmMltqpy9NIxK+lX6Y+UYTIb" +
- "ZDzMDN6G/c8HjdYsVEVWSZxbtU0dN3q1u3bFRfC4kqOpVSPLo0pZSIiQOFnZ0d4q" +
- "sQkz4Qqa1DlekfEJApicdLA4a9OMxhyvFegkCmuM2yHU5NScI25iY4U24jHLltts" +
- "7StNCk4frJzwu0Y6VjDDFk5RppNKqlRASOcpVq3MyVYiVt25mTCT+oTRDRPR2CKq" +
- "KWrVqlUrlqaNSrjDopxKbp6upXldb1PU9s4hJGJA1VbLTiRJ7eok2sM+UHLbthMQ" +
- "UFfLLbZVqqyVK+p1Equ3tpthzYl7KWLEMTEq4Ll3YoV5stLbid+m7alklmvcxMyY" +
- "aGFGVGL1wYwx7R6xjFy7cn0pouDotHyZkzo/hptTZOkPyO1emWMxhjZLl04IdDYK" +
- "mkh1kK4y2TMxcjHDmvtbZMWE+zDHXCnuD8yQLIjg4UlcKxjHr9gopzYxfuda1rEs" +
- "eHCK6OCQ6xT4Pju3n5/X9kkiEj6cN+/vl+uaZ5gYN/g5JlAUHSDiUhoOAhwMFMVB" +
- "c3DDHMN3DFulS0xrgWmW4W5cMuZhWta1rW21tbbRzrJVtBe+ulvYM/s8dPjcuY66" +
- "qqqisgnSPat2gVwbVEysKVgXdk1QJsk8RJCBD2v8tenlrnM3edFeqa8Zu7mq1raU" +
- "mEZP6xTGt6zMkdvq9uZwdp7PTR2nSvKidMcnTDZCbRQfLpsjVtrN222z1LI9jbbS" +
- "Yde7dtk6DgycBMmW9OTcaTFMfB8NtuYiTvVscobNGKRo6Wb4zDniY3e2mSmsjJQJ" +
- "4EQ2vqQkRVGM8qYh3v0q2rPteqmFz2k1KQNMUOrLk2hBsGYs7NRoFGZ5rKHrKVFW" +
- "Up3oJ4GS+bM2pvedTh2+z59qcemFaIM+lnMKY/XLM2leOJtTiZEVfbeon1+vwZOB" +
- "hQgviaCMyAjYhRqyLmywXa6sJtAjY0ekbBVdHErI5ucHJgQ4jsRIimS+VhHvLz2P" +
- "o9PoKp4fLy9uDHljDyKyG7cVtjlTlwPJ2wD56Xk02ttipijbGTs6TRK6R26babRK" +
- "3K25I5U6OTolR0fLt24J9HaeVeHM4svhpuNNlYp5eDRNLKaWrGQiqmZbs0Tlo8Bp" +
- "tppto4ThGn0cT6OnAeX+R8K25e3KOzaUpVttKUnlUhZWFTasOmERzfpmb6O47lt3" +
- "Whna6EmiB7nAKT0eA/sERTa2uhyCini85zJ/DpU/B/+m3fJ/wH9Y9AkiPcclOX2Y" +
- "n/g2elK/4y2ikYKwUzMZcuJVFe362bbaGluwykCmE8ysyzLFrmryuvj1Xz/S9/AA" +
- "AF15cn4TbNPgsRs7cOFV/dG3g0p+7T5dL60/tdkgpyzk/3v8imkP80cFiv6KUxX9" +
- "LGz9Vfy9n0NI+HBMGjFPGRfU20/oK/wT+7+V6CiR4ktktkvJP6O5j9KtpUGP1T4k" +
- "kf+7GZWMJ/d/NKP8Ksq/q7hRyh+q/vOT/iN1f/NGJt/f9yWf5H9z+wKWITjGZjP2" +
- "GmInSyTkRo2qVStSThT8HxX8MximI2dIqo04dIbQvxbWO2MVGkVTxHSI0R/h0eev" +
- "LpWSyT2p9GP8P1y2m2c1q8325VIvE485eDI9AlOHKGBw4JhDiv5HUmnSO00Q40Je" +
- "rcSSy5GXLGVUp2n0eDpFE6T4Y/r+er5YqJai+n4MphhmLSwD8QKQoGSRJ/o+6YvW" +
- "aSVmfLS2qpnMM9WmHTRzMJxy0qHVaVETOYZ1ScEwOJ9g0NPAmjGk0rStNtsbQ5MG" +
- "2BivKYNI9Fvbiqv8b+qqdv6PL9GI+O0lco7fpI4cEi8XLlw2kn5YnpWFTwgTabky" +
- "liH7Ax+fy+323r5BIEhez17ddXMxVVQFUOdlCkEiQJigNAR9MV9a+Xx16vk7dzgH" +
- "lDoGcCQ74xnfnz3rzzvXO4dlaYNK5NOUkh4fqSweoaJidvSK2eXFtkPPEfCh9Gkm" +
- "XRyk9PzmZVzMqjDGleXlHlJE5ZMZSrZt/Vu5MHK/2HZNP2ivmSPQ/6qw/Hu3mR+n" +
- "CmQgJH8fUlH/NlVMZjKHCWNsfyX3+p/53h/1MZA1UFrEx/2ManCu/BiYs5NIwfyV" +
- "9hsjSn/V9nhY5PhjI7Ullm1JVllLfJtZNrGVSVH0hBWtW0eniUKWCpQplb1tteSG" +
- "W0qTK02llaKdJIwk+rhGI29xHeDU7WszdtKrDKsoRP1Geg1MyhiYmBApJgHZ+sFf" +
- "yDkcXDK/ydg+VJSP5sSdLVsKtSHjkwmzZhbIuvbvTXnHN1BiMYylZk7k/LKCYDYH" +
- "X13JBDq8YZURZWoixpkaIyJuN7+dTwztXv57+nThHDDHBkYhVKpPSK0UGMMYTbsK" +
- "VqDzx4I8qh0+G90AAla9VKVWaW0s7IZmGGCsGJhhSnC6DSPacu07EkRI5jWcLUjw" +
- "/d2+p5LbfLw/ft4tspaVjDMYWjCpQqLBUhDSjgT+k9T8hNA7KVTkkn2GnDBRs4gq" +
- "HgJXCnB8vaJ5e0/l/WLbZbFLFUpVRJECIT7iSv69sHJkTAi1mJkzExpMsxUqaYaU" +
- "miWTRpNtI5UcttEXFPVdQaiwV/wNOFTaFSaL45y+41lrMYcvR0CijhslcNI/0x5X" +
- "Yo0kXy7cq/RMSNtOU8qn+U1IPp+mXMmZbhJ0PZ5BISOpVSySG3jR/pLeKmXKxwbv" +
- "w08D+N6WzGTJkSeyhTax4Km0mkp+2qVI0rFU2n8SvhDnkx7T+ba3mQuaiT5PhZj/" +
- "BPIPTKvh1If7V05H+Z/nVSKcn+SK/2dX9F/Uvj+tYktW6Y9SJs9U8H2+uGZNORKn" +
- "w6+2/Cqtq2vpfTblsuXEmsGzllqypVLFYDCVIQ9J3NuEfwGnxGlfyMeYjQf6WRG+" +
- "x+JPz9kl/QyP6sMY0xZf5xV/I/U5f+p6o7h0sRjp934eHA9K9T3ZcSNLGkno0CQk" +
- "YVp8JT0vFuFfq7kInwp9TyTE+k95/GX6qj9zhqP1y390T8OTsAJxZv0pBjS09ndu" +
- "/queeVeI9GunPNTJtIrybqni5552x0a9g4GMHRBAAhHYgg4OGOTGIx0md24x2cp1" +
- "ws56tnBhyqW7W22GlI2+w+z4NJHpLENNvsSMmLVcLMVj9GSBNLTXNtfwxi4U4bKw" +
- "MhtuWyY+2mWYp5ttKqpA6paj8vKRxEawvhY0NIfgfiH9z+yajt60n97P+eZ9rS0x" +
- "W0+VV/0sP8sevxzxZkupTbH8sPl/D6tcrSqnhp05PlHCOok2cFqHB+kTvuQ+xWMY" +
- "xjkg4SNqTWUt19K/fat9iuFW5XN8JyNMVvGVP7r82PqvjL7jtfwP8yYr+QqSfsJ/" +
- "jvt2zClUVYzM/e1n9tRN7Zd5buwMVVKqRKoVR2YxVWrU0/hHBU0sekk5eWPDSfeZ" +
- "dQOaqRT0r4rFtLHeZaEkiKs8vN+vcjw/CGRlxRVkq1SPDFexPt0FOvhPFuY6Tbab" +
- "lve6MycQ4l0tzYO2m5eZhoWcZUOk7NTTLtwdLblt25Jy6YaTDpixoPYKKYtMSx4V" +
- "/I+Nn+ZdTDBNJM+LfQOkttkfVOk7faSBw+y2ei5ZhaxgYP9nmnNi2FstI8cfri5j" +
- "4bHPFumZbbbybHMpMg5WROgw+Q29S8lhiiGULhSjSdtjNpsyIlsyhYqxbcJrYw+o" +
- "k8CH6HRjSvDSMVFQqqko0xiIclqrGrAw0hpi/ouV/i2foVy/oK1INsn/LKzEnZt0" +
- "0/TfY/WWsZMkwqJFKpVKpSGE5kJD5cnT5T6BPRj2k+rIH3fSdvy2kEdD9W0T4tsh" +
- "+40PbR+xRPpJN8azaR9OJJrfGcJHGHBw2OTGMmHPduPz+ryTH3/TGTMY0bTThPa/" +
- "xbhjyxUTFkr8JJwYmivf1xmZJq2ySlSoJPBIfK/rASBSF+cM/nZk213bMmBX5laT" +
- "Tg0VqrbakxFiRzCeLg1rQx4xf2Vq/pUjo01d0k/Vy7frMy3JIUqSKj8lG44ZP1xk" +
- "y5bcTEsHL9YMZLGF+0n1bjZ+MHj6OXau8pg6GVof9Cv/Y9BbWvn632UMYJoMElJr" +
- "W1JQhbfu5MliIQxxyxlFWYJJSo/lsdkj/9Utg244/f72xHsUqlRVMGPuJWipOBhj" +
- "qEkxqGNgop68j+4/mhRTtlWMEwwuUKKdDCxGGldP8X8NFUz85NW01rD7NpifMq2W" +
- "o7dpQsUxivU9S0/zYuHDin8gytmwSEj4WYqVwrKqFn2kfvYWyx06X1X93T+Vj5iv" +
- "X+C0fH6nAMNqMKFVXg8nuEYKKk2Rtat7V7zXsSJCUSSRT1tPuvGtNOFnGGB1Pnt/" +
- "MW1VDT4EQ56UUWLFFBZqjHB69cXANNLJbE0k2zdlNHR0OU056txtowmLOO1WSsa6" +
- "mpA1B7TlxdF+0uvItZVay3b0whrGdccXinUpEidgaTHSdubVUqqtqqabViKw14Em" +
- "JmDeVXXLyvKySljtLGMq1t/wTEMgWhujLDJRJgxkJlQy5UMlB40srBFeLlq7bpq9" +
- "ptq0rbSxohSrCmSRMyzLLLMSFMMqVksswFVkqTKplkqwklGCsCyqplQsWLGMZZmT" +
- "JwN3COMLWLVtt2fFUij5Hs/SR03sfZ5nglZWZjJSqn822RTBpyxvWHlVKjTbGVtS" +
- "KqskrbRpKaRWKlUqSk4VwY4cYMNTGkW1bk5Mk2jbg0RUmojT0wxxKQVYhbbLZbFB" +
- "oqok2slvxSlrqul/g7aXHwxix/68Toof7qkpOaD4wC2yq1EwXZiapV6/hsyJvBiy" +
- "EnDHppUrseSqqll+rGDc5R6WrvWH+G9by3kboLdJKq9H7sVW0OfMc6vWl01qZLMZ" +
- "GXXa6QEItcit7KxXTeedbF5N5WV5LJkt1ZLKLEMplYlj+iTA1EdNMJwtIUTETRhJ" +
- "/Shi7iTFIxhiMSWYFgxhilFclagZLPw+zk+h+o0bMSmKxOFfTOrm2TbWXbWV6uG2" +
- "zX+jEamLH9lX+6Yr/YLxH1w5c28qRqX++P6v9czJ/Bpq0wP7uyQ7eB+Vf7n/N/A4" +
- "I+n6Oyqaf8ybStl8Wgvg5aMWKcsqRmLCpH+JHY7+o/ZUcf8bQ0syoa0yWdpVOGka" +
- "ZNpjvIUVJ+ZH6qhX3fZFanSyHdkYpGWGxtjGKcNMNKwlSpDgp8KdD2cj9bMv9zY2" +
- "4SHDkmkf2xkDCf6LKQfCpoFaOJ9BoH5TDi2/9rCRhPqSKlR9EcmpFLro0rH4U5fo" +
- "dOMs3lzLMZaKYNommiU6RuIh0nD/kT7lH58Cz8XLMuKhGo2V06T/Rhf9p9apP5P0" +
- "/xq2rWqv1erT/PLMqx/K0O2Dg/csyqf8VH92myX+Z8BRTxbZHaYmgsP/J9QmCR+7" +
- "y/0+qv0fCnyiPJSHCaH4SEiYfT7Hsxa06QsXGmMqTClIxIpRFUn8jGqv7oxG3iH0" +
- "WUiCZpN8b6/n1+1fkq7ffeV5XQXGJARn3MyZKRCosJhcTJSYUEP9MYaSlQxKRSo4" +
- "T/usWhVI0Ps/HwzGMyRhR1q2WLastVljMZmYxjw3K6VX+qMduROGGFymqf4nekcJ" +
- "jClisYLIPl8mk0rZwHtB+viyyk+VPL1HuRApl/cZMDw+MZfZt7Tx7LCpLZS/LK6S" +
- "W2SkqS0scvTSTnLcGk28PRKVpMSUr4PizlmNNE8YGrZq/51JSfi7Ts2T+5Tuf5cL" +
- "UaX6LUnQaR5PlE+ZyTiUqVaOZTHx9XDIqqOjpwldJmO7TbfS5VtUwninQ/6Jhf1N" +
- "p/3sSnS7Y/q9Btj4/60tF5xmT9MwRXPy8PM4fiKUOh/FVVREYiiQhAhEa3qu3nv2" +
- "d7+q9S8O8rb0Bs06WlE0arExG4ZViJk4YG2Gl1NmRsyoMpaZV7PclFEkhkSN7T1+" +
- "jx5uV62pGsk5ajBRIogIzWpucxals3vLLZmGWmKYUqcpZRpGE2OC4rasjHDE4E3a" +
- "VkxkzLZJSckySoFD8JNDSmOGxNtM2uJgwFUYSjFFUqlFGExq2zQorAowoxy2rlV/" +
- "wdJPWk8RjHBV2lsFjhYX+gysyZkxh0f3RhVg/4UcJ6TuScH1VPy29yH5DloLCqpU" +
- "qInySSwxRKrl+50K0qqo24TykjydiqiUngn5KlPjr2zMmZmZlXDMt/QmnwPDD7q8" +
- "JHcLH4WjVHYxiwsKx8JjVH90Yz02rRwptHkY4fT6Ksmn8HZHweLk7kPRGKpyh/eq" +
- "bPRt8Jw9H0f9riJN29Ik05PjeYzM7a+qenD4QbH4OfJwfZMB9ytJtyhXEiMJiVNH" +
- "cUPwV4H6o7H3fBXSflFn+Sn3kdp9U/HhSqjtSP/YlJJT9D1KWFG1D7Gn2HR9iD60" +
- "4ZhiiTUjaPujNmxMUhRQMUxVYpiKFSJkVJXJrRuOpD+nmZJ/LmR07HlWk3VZMyK/" +
- "m/D6vP7Ztqy2BISPUCQkdu9bzXnqeuj9E79X9hjUSttuMzBuJcLcpmDmXFzLmW0a" +
- "Nra22stGjRo3xd71/j7CrbuqNuCV+Pn7RiTiM9JJIEgAeHxJdEfM80MFtPnBMxsr" +
- "AgcxJUHBQgNneHDhd46b0pvHTJccMlKYUIk+5RcOXp7Ryfl0Nnc0n5iTGzpiTkxo" +
- "FCf/H09mHBodkFJS2Z2cs427TqZEjg2XKgms0uWP9EwnyRTKCH4BWvY2oHETm/gw" +
- "zIiIJE4SQGl2Ck88xdoqynSIaAsnIZAHItqcqEkc5usa5371h9/ghm6wvaD++Ev8" +
- "O9O1aUzFPwkL4FbXvIfOvp571rp7GmKUGlYdK/70n+m237Stjy2V0w2w6YfZFPh9" +
- "Hg06PAx0ppwTTGGySp/LydK8/p8z7d2Zmabu+zmXHZJtVDh9axBEEQczHKc39VaV" +
- "T4x8bLS/TE/iYRwjwdM0rY+rUH8HTgw/pHI4Jporpt5nzbKmLJH82WyJNK5mnJ4D" +
- "eABtlKSyi0srSV+jHaGkaf0oL5Xqr49f2cO3KPHdVlOlxT2Lbotv5H7Pq5pfnuZz" +
- "/dmMfvq7Hqnxosaf5U5j9bbH6/WKPbcO7bK+EPh5IfmR4cj2lOqW0RIh+qOFlpQ4" +
- "QPJP14ba1ay0a5WMszhMV5f9J609T6PlI9nB/Z+ltJpZfELlyFYfUpiTUrTJy1Ra" +
- "mlkyy1arGFKjH1SmRptiNFKlHlOxTypVNuJAVJ4ErlpVbYWdnGukOx25SUDvhmkJ" +
- "SKvuGWZYZZExglQqFSfb9gSRHe26lLJVfZjBJ/oiPHr3rq/pJEQkegQkCw6m6pxf" +
- "vmXePsQvn9xLQI6KSRQIAG3bEGfh7NUKcK53UPq8OHUkcacJyvTMdOk6aVZtbeXD" +
- "JrDQwQRBjBWHXQ31cy5mBlRZ6IYlcEmEU04Y4cGEw43ZacPubU5VthDlicPuw5tq" +
- "27YxgrGOOrbLbUDHk2YqK5Y+iuHLp5DT4+JNH2/Z8HtbEa9pifS5hRZbRbRJLmJk" +
- "tJK4MBO+IfGu7xq/hYNWnTpGnT2zPJAB7pIdsgDnjwae+mHsZcy3KXSR8U8MMHx3" +
- "67L6cwtaVLbW0oONWeD2UwAhlkYAd9PyGVl2b951gXi5PVcb8QkPLMTq0gBWTz4K" +
- "b75X2bmGXKOkz4+PNebXzvhX0lvnW92FLBBb7Y5NtIVito4Viq+U3q3G5KxpPY05" +
- "fL8uNtqqVHwkaYHg7TTw5Y28GPVWo6bO3c2dGOmk5G3CG38p48S6HjlsNF2N5UG3" +
- "rhMMNpgtTb7iCOst5UUraeXaRgqdGFNmIlmjFNDbT2JT0+HDbb6fWUsvKq43XF85" +
- "mSaaDRzytq8wj6ofRCj5SpbawpLGJ941qyZFjLKFSaYxiaJLLaQhJJAkhvLrtqoC" +
- "ttttq21FiQaI9vwrDxA5e0qy21HycDgaRwSPs8Q8LbbbaEEqJAA+29r5V87e9va2" +
- "19Eb4CSiIivrXz3xYwYxlsMdqma+mXMuMrKWCsMVUFYvUsRaVppRgxw1JXOMb3mL" +
- "yozTBtdtNjDDApBMAoSHCRowphkwjDBucNtDaRKMMYKomhyNY0ck0nxv7WzTGIgK" +
- "aWfqbVi/VMlGxYTH9BkkfLWrfruDbbbdSUqaY2JUcG9pYR+O0/p+5jB/JZUMKxWI" +
- "qpUVIKVEVQxZMcum5tZISSZskAD4W+H59LNJklKlfGlrqabJQptdXKqVKsqlUqOA" +
- "aRSiVP6PeBAlSQJCTLBC22236NPq6ejHcSd2rZE7YfVPKyfUT4b7fr8WyefXfb6N" +
- "MyWzwG2mEp4bur6pan33d8BXGubpOl5ed4jcsltUaNEoRiM8GkA0MS2li5l+V2vw" +
- "4XIm74fHps8HR/jS/q+HQ8pSv0K84J8+flIn1SJ6+UsU+C0c9Aop1HStKsYGMDKx" +
- "VVbVX8PI4Q6YTdhxS2Nirbpbf9Rt6er8OQx00quK/pxvKLQgCMAPno3LmmAsuG5c" +
- "3ARCCJ9nkfLTE07UWQ+xE4dfZtP3VPs7YjtMjphyP+UhGz0R9z8FYVLWVdq/Htqr" +
- "8qLbe2t9wr6vumCB9f/1f4sdo/2GBgKKf9A+qrofyy5yaOmGMYh/zf7gpXixGz8L" +
- "+5/xfK/0YL8tv7GR+gqTsvxJ9Ht9VkkLIxYsKqMPDNH2Sv8q0SrVcBPlIf3fwNJ/" +
- "tUtJJygp7lJ+qPdeOJP8PnGm0/cbR/Cu1iq/DodIqyKlElfh9ROO50qsVPQ/KWck" +
- "mmleZE/KwjD935YnpOIH6pJJkrJ2Ojg/KkmBVi22RUNKkxWowxU7iMnlaqlgNpJ8" +
- "pj7iYnkVUWTvh03PCvJ5UwWAO+/U+8rwtQ/m/pYcu7dSLkkqlUIKb4AdxPxWQX6d" +
- "K8cR/srlNn5QkJHSlU6YlWNKsqyjRa1ZMrLLMYBj6NRJ0TlhNqV6ntwbHC0tcGIM" +
- "SikWx6q/J86IAjICaXDPuClJRcO8kmItQriaGCUlFzXDGSLiFQTqmfrNOzl03Ole" +
- "IMWrYKKbCrtOGYDoM00bf+1W6hV/xyoRH9H1kIxEKqEqwhOh0fbf3XzNt1ZIaQ/Z" +
- "Tcp8CVPCpx/rV4xb9LJRO2FfAhRPU75RFAhEnDwrLCvgVkHFpWj6sNJo0rweXtOp" +
- "yT+x5Tl0wTwqLD3pVXSJ+5+RtPl5TqEhVD+w7piTk2lwGKf1bfq5W39Vr75V8q/9" +
- "/wWTBGo2g0WqS2itFWqKtY1WosWrRVYrUaxWiqxasa220FtqxFVbQaNUaotGxFsb" +
- "axtbSaLbG2tYrRrVGoitRVEa2iitFFbRqi2xWxVtitrFaqNrRbGrVFWsVtrFqoBZ" +
- "kqzAMyJmCrMpSsxarGraooi2o1WxaqxYkirFkFgSQP+X9/8v5ZP6G0/tc4bk13k3" +
- "JrvDkTm8Quc3Qw/xo2mMqVokQel047gDu6KK9vXSItvS8kwSVIXbC5SCkWVJiFZg" +
- "hUtoVKxalLbdMKjlWErKlStSeOmTUeNgu7o2dzriub3bxvGBNRCbu64Y4kT37cPB" +
- "IVhFJFkUhs5l65OBc/xyiJn9pvMTp04GA55Yats2p3krH/20yE1IIqJ4GE72HU7u" +
- "YYM8Ubq87w0emUBOg4KzHejc5vnlBVjwWj2JDp78uxUmIZjGSSXv2+C+Vk2buCu5" +
- "waLzxxtCqTeYuYkzGRiwWkxWMbuiWxbDiVZW3Hey4sc9aW7DLDfXXvBO8UcMOrE6" +
- "ZHKIJJkSMuZM51ZhDeUpVpMillJZpvURzSaUu8TxmWyQ4sN1HLGJuVCyo1rGYzbr" +
- "G6nipyrXO7Z7vS43pcWFeb5bU4saY8yVux4640jFLmIWjVTaVtUu6xHFmprC7jGK" +
- "0oY3kblGmTI1k3ubEQo4klMaSc87iGrnc67p0dLLSaMM8WbgykoqxHuhUIiSVgcN" +
- "s4ReusZ2W9pwcOl7l6OFfAh11ZNRZnWh576MW2q1bFKxVnLe+3xhp5sO/llybe2u" +
- "6vZwQiJ63JuaKKNCGBLFFoua715rvMY1dJZyLBbrOZ5XV5qeIKQWC7JDCltJRnjc" +
- "MWVKILJ3QpiLVSjwUMweGw6NEzJrF1i1Fr4tLGZjFiWmbSyagjBTJHzlDjD4ecQ6" +
- "82snBkEBIfIt4B0kgWTyUekmpzCiQ5yh1wM4G8SeOG+NNwKdjDrIdZ3nnxc5azJS" +
- "gWIWMigBFTrbdrcC3d1FulyStyYtcJGJReZlFmTVNTS4yPGPG6m4mU4UpUnHfhrr" +
- "wWZWNdRvxxpo63XA16Gk8d9EE0Xhw0MmKiDFJNWV25mGqnfPHiSZDmy0tLVotC9m" +
- "E3s7B8efHiO2NasFiqCyLUrMVTLjOkidBUijvl11NMuFdid4Pnq556pj0CZeWiKi" +
- "RE4EFhe7nIB0MWSoVFVEKlEgdTKChKRIxmMBSnnMiG9dA90RI90p4oXnQyoVOzwO" +
- "XmFFm7kU1EJfOeLl7pwCnXR2AkONIgVXEixG8HO3zk2uUXZ4KDRPGOMQcFigu6MB" +
- "AynwUr5tMSp4Zm3S97lkYwrKbmYdS7N0thbaW8cMcuPGm2iNlkxeVSsrDdwwNvjm" +
- "OMsQWV0bYCzEe/EuduWNOYe4t4neTnLWQ7yaysyt7Nq5jW3w84tro7rFbxrm3ROc" +
- "yItTKia31oMVVVzMmKibuKkZYOb3Z3UnBYN1JxUtiasqwcnVw0qRd45sTvWJOrIZ" +
- "cp3W8pbyud6rMm8TWW/KOlHvrjW2vNJMEmW6wk8+aSBDqHZe3wLGK4+WYxQYao+a" +
- "FMLu3Zia4DJiYsHLW8vWVSaquNQVVUQ7dSGGWs7cgmMXdseVDzwzwgEvmRsCB5fB" +
- "QVQXq0Zj5wJrB6UFaTgUTjAXmHe6AjIdsFIpFIYZ5zPJpMFN97axjrOebjescSIe" +
- "OlxIjJYuYzMCWWMVihKxiTtW+9a1edTMrhldTnO8F0E1nhOr4yVONeDjTro3vk4e" +
- "VFXbfM/6MUFZJlNZZ+RMiADvEl+AAvwQB3/wP//fyr////pgQg94DwHe94+e89AU" +
- "H2NBDuwvr6eX3b72JJyiefd58+Vd8GQIqkiC6wJSbBm5uQAAAKq7u5JKoSaaqQKQ" +
- "l21VBRUlVJEKkqkqklKlVSiCooVFg+BcYAA+7T5I+gBL4hzdzp5AMgOtGq4ADa13" +
- "bYpbuB97AXvu0OR1329gffKPus6EiQIGhBMJE8hNE02U9Q0NDQGhp+qYgkgCIklT" +
- "0IaaZADQAAAAAAaeiIiUn6JqJgaI2hNGAA0Bk9QAmgk9VJJEyZJ6npNlNNBoZoTC" +
- "NDaTRkD1BiBEiAiKRKekw0mIBpo0aMTQZMjI00YIkiARpomQhkE1EfqnqNA02oAA" +
- "Bo53OJuRwkNrkuMUJOhNQiCKMocWFChEEQrUGVTGgg0sMW2bqgkJBgahUxttdb03" +
- "1poJEQAhSSeqS4RwucrgpgGDRopQUVIkNExkDQSGATIZGCmTCKIkUjZJZESZSaMx" +
- "BmaRQQFlNGJKRIQihnBz6Pqb1dXa7ucrjgmcuCGgbYNpgK8AKEFIr8o4gKQFwMGj" +
- "vveHmstx7CuEmmgYnRQhB3iu/mzlcrWdLQASIoDpmY0D1WpCxNppg6VoTStS8btY" +
- "ssBpPUaC7k8vu+aXzwycRqJj4XNyCaEL8W6PxaWpQ2NtCG2kMTE6TpoDCHUaLpoa" +
- "W1Dm0upHlZaDritXaTgmhQQNtsojjagMpMIthjtQ0xZUttPCv+T0I+nD/mkZQ8ZD" +
- "zjB4ZdHI+/AJQaEvDFvWEt9eecKhyJv73XRVYff5934ryHcPuxRvk/OTX8AQBAXI" +
- "YIooDEBEg2yTSZqtrWliJNFtWstQg22mzaljNU2WpmzNipNtVbdVtq9Gq1bKqplA" +
- "FijAQQWAEEEFi/vVAFgAq0IILEWRBPH+qAgv4VAEvYexHwNTvPzKQKnq9pQt7ith" +
- "SFQE3KoT92BcQS5rF1INoi0BQOEBIieUUBAgVIw0feYQlJIxilA5IyloT2iIDEdI" +
- "qoG946hlU0gdFhujgx6GOFTZJSSpDwQuVTcllZOqH4ZyZC0BlmkC4cCwsYRI2uGk" +
- "ouXauJiysgW2UY5iFJOlmzOCGH4iZGZYXJxDLdJ5I+okgLjdFcGyxGcTuXzC2QNL" +
- "MmgZDlHJwpxaWwzw0jjTdXZYSK7Qr5tMVE1KLGpqexpkXBFICAcNsKQUZzMFIgVm" +
- "knN2YKiGSuBbRzatIQgm+KaQZAS8uDHTnWrudlkM5iRrvStxKFwKKVWkrxS0Gc5b" +
- "46jB4beDQDNZhiAYwuRpE1mlIxJctXj6hyy5cxgiVA40kzeEpxsaUJjkvd5gjFhh" +
- "XMuSAhJw0YIxgxczl8mAJ0klHCWrkkchWY7a9j4Nu7SQ0sThJQxDvI40wEU4mYE8" +
- "5vWPNKDdBTZq8WAka53apCRSSNpCqgUBIEqkKIRCCLDdFlqlxAohLqDOd5oy51ju" +
- "LwUEYBLpqiqzTi6CEFgheJY6jhnYUa1qiwwzdN4qAkZJTTMxtG2YbaURoLQYUs8E" +
- "LNMt81O4S4MhIrqC8Y2RJqiBikskgX1Ls0fwJ4OCaGBlINkgmKE6hXECwCkyUOuw" +
- "dQqIBJJNGXYw2m6AgaYHhuJJJCxy4jkmrBKJZbYWNXa3ElQyVBKsZAmKeWFLmqL/" +
- "aqWV6VDzrw/jTfYq6/bw8pT5+4NHZ5DpJIDo3mpeN6SJGMka7izeeoko43C2Epfp" +
- "g4TpoXY3puxOTFNpHLlJkTMJ/cig8exbJ4wXM1wqI/cnSPX4zRN3hNeGDNBlDPCc" +
- "RjKdSlEXMcLYVo5zrESzdhn5oQgF7Vy7d/xXre3+0a929Re2659oOIpGmnWprpit" +
- "uWOpOh/bvzdU3UXeNVH5d/XiT9umGfzpTP5/9FU8nQ2l+WGPykDtzW8+x9V9eEZL" +
- "xXZrntkuw70ekWyrvMhHrucZm9KfynpN9pZTE+0MTHTPffeZ6Ne/Z488WceGj41e" +
- "xPJ4/IOaZmtZu7us13BA3KgkZGgZhXkEnmKKSCdMrtunVFC2hCzVzNmb4pa9MrfR" +
- "5L368R+A5cTbzcuFIBItqqa9ZJWrv440HQdtONRRNMqQLRvCoXjJsHsNjp3oqjTU" +
- "nuUk+tSSqY06SBeONJjOPZlitBWP2Y/a4myrWhja8Y48ITl3w70cPAUvOLu3N73x" +
- "oNCWxRXKJMZBOcsIiYNsbb6IqgA1MYWCyzFLX46tyDIsrZmBdV11KBpmbcG2jSmW" +
- "klZqbJwQmXHcfS+kqBbvzhoFYwQVevOaUWDtMkiQ4OL3wfiGhdLDJF2oWKWCGRKi" +
- "hQlR9vBWB8QPr7h+/XlnwgBkZ6IHoruquvYHPb3d2c9Vu1qFs4DoTfPOZy5eaTfG" +
- "EbeW2TVkZWcjbLyy5fXm3YKb4ufb/wb81JfR8qaTCaWBkN5OAgOisFhTR2+eXXkc" +
- "3pGtx5da9R7O60uzr4vD1ctQeFni4kxCBF61C2yR4amYWm6emxGhMsrBSNygglLJ" +
- "ju41nhlzS1oTvHIJ3iKAtp6aslyLp2Xz4u2mDjOOFZxL3c45xPx8u1djCMsttzHL" +
- "vlwW7OA48Dxvhzz0vTvl3lSnfgXC1bTvQOQPN9u0GMqUZDiUu+0SqNTncw4JrOJd" +
- "C5ae2h229JhHJcsamPYtGY2nqSYKK7ZkCWcOaeo6wnA5uE6UmOicOKSlx01thtO2" +
- "U5RWOvTw6+Fysmd8Kd83F6zpjTvnstmbnM78jhR6FmzlfenLa9NuMaGgsxrWUpGv" +
- "xczOq5bXKtNQPDHEHk5QkHLA7Ei3HDC6vuGTk25mxRUpKKkrlGpasCNz44/k+3tD" +
- "wDe5wjgdDHrPy8gsg2W5zWGfiMkjEJmgQcnm7BcPMOgmPy6pIvZOyXeDh5m5rpxh" +
- "u2O72A7GexroWfc4Pg/Hs7+FoQ8r9jIQtaxoXODg+TR8z0PRzeAOoeeRuMi7hdOS" +
- "81h4GqNyguIRmNhQKnFMJWaZLQzV+urXgFRWKiY8ZIxJo6GynpoUkgAnNj57hPkk" +
- "CiIEgKoYhUZF/EFX75QYsoLiXAfylQHsFzFbiMlVTCoUCVRu0SOlVOuaqN2WvP1c" +
- "77nObXJxriiMINSQogBTFkqqmEoC2VXvQXneIkUdJiMdJihT4fO2rWLdy1y9kXJW" +
- "wjNZBRy2pfGS/8Lwdy9Cmq8fh9iYjz/X4mvTlzXpX65f5J38LH6DNGfi2efIIvIZ" +
- "10n5NE1kN59vlWXnOfKiq7ER8fWpiWWAkhS+t+LrfbL2atTnX7FlB6UvlXavrdWX" +
- "HX4WKTvtWbyZlXdbue7pYypbJ5UnERU0llbaJ5ZvPfC98s8bTLO12ZXNItLa866P" +
- "2611pp3tR1vrwgjnvvzhWTmUw9oSQv1dZnBnZnRGfK8QzR5ObplZCCc5ujfT9R6v" +
- "JL1s8iD5lDfnIokmLJsX6RI1PafLCcKs/Tg4AkOMBDBIQit/raxnAKMUBAZBr9yq" +
- "s1/QXIbVpWgIAgmEILgYvh0yWOUmv3jAUfKBfkdBqK0fOeYVyHCSZHQ6VMFk2HIr" +
- "sD0RNdD7WUaPgRyIZcjoUkiB+YRfCWIeIcpVQPm6Q1BfgQaJofhQUEMgZOGDeJA9" +
- "IPcCCRV4AUgAYPdw6IdQASI4FnXKQHmcg2w6ALxIMpE3ZaAxxeCoTJ0HTJEbxQOz" +
- "vOl4O5xZ05zeiMkPQD3Jg7lQsvJS7KCkLTfpQmQlEPQs76EiGVGr9s8U7Q7yKUh6" +
- "XQJAgcEPOW6rmfKxk0kYB6NnWeroUq8BmBHowHKGqH4gESifAlozD0+eQ0j4kT02" +
- "LZ4WaPDW2w+IYtHZeImTcCWCRQLWBxyHfijRhjIpsF6jmAN08BB4SheIvMCQv3O9" +
- "IBxhPz0SkvgHt3FCKbZGAMBDgJArIhI9BSIY8gc5jHmj+E+p9S/UAPryP36WOYnx" +
- "34Ii7m5qkMm9mPRFNHfnTkYoj0GQr4OOeHrNeCzAYlhhc5B9Dx8dhsYr6Q8qgkWn" +
- "ZzILYoTDz4BIKReoEWCYEF+GtaVpIuJ9O+zUiaxtJE68pepgbqZg0bMuPgcmlPnY" +
- "g6RPUYjuCge0Uj8+CFpsWlfLghvvAgHOAUAaHOuBCwTEJ1iNdj0An37bTZlzLF7r" +
- "i8nzHeJWS8Y6zJjrLCcqH4JHhRMidIZSkw8EIub4C6LDowDzJO0NYq0kILgV0Xug" +
- "kCCZveXnig8iigRgdCLAPCpCoaA8AMX+M94icjIEiHwoKCEQhEX3HtmPnzHMo4T8" +
- "NPcs2WZJYUlDwPX7E5AKIDuKSJ5wxZlKKsPwLwU8KDrAPQyZ+Jla9ISK/IHBC8hL" +
- "AJi8KMiPQXfpqpK+sINQSQJGgioXVwYxvvIhV0sJEIsZpIely4rWA1B7CQPyZJLQ" +
- "OahcYOxhvMPiDui49WezMfDbrdT686aJ+EQ2kJErap94yg2ISh+eqqB0QQPpBERM" +
- "BBR+wkAAH2CA+KJEV+wAFcxBkBfIpkCZ2gULsgCIciHoB1hJQ9gIEguUgoVulKgg" +
- "ntUcGAJr0oJHR6UMgdYB4JHEEfADtXgvEGyLL8+ama2oQMkPuYKfH8tziwAEEz7M" +
- "qXYXsAoQHsjwQYik4/RunvQcfeEFs6nFYUjPo+WPguYCD9BY7j7j/PYGCWLpEvWu" +
- "7/IZokD080Zk5wSD1AVqPRbsHEFBSr0sXtjlDoV5UI6IgNFeEvHffv4n0LiGvfQ5" +
- "KFaH4Gqpz0Mxh9UDG/SNxy6H6DRQBcV+sBle8GiGx3QAXgqTMlrqSTAkr2SSQEFV" +
- "9QEYOxHymNgdkGXw8Y+fRsHrgXw0GR09kMpCq5MlDiZDzgGOLxJuHDgRqQOet5Kp" +
- "ezggkS1jSF0MO0JZ2yqQKSLF7UIgkEZK5OM/HYXOHJeOW9vBr8HHbkuWPxox6fms" +
- "GumVzMqBnqecSQsuBDogwNRVQM9eBnKY0b2gZRHesEG2rOE4hkmdWB6V5y1KgqA1" +
- "BGhikPMUQmrL7akye+mkvllmGuOkpMekkiTCSRACmrhLIlulAF9N5rthlpQ/XQkp" +
- "01zssYOxeeIYRSTWbG2KBe2SOKBXQ5DU55aOtIvBbCk+zYig+CBkc6wH3bQOiaPv" +
- "iscLEZjILNSSmX9OdgQXgna+HtgT0K4DwhmvgWOYSV0NSQuh8OHmg/ExtAoX4Pob" +
- "q+dVHoXJ7hVNiGlVA2bGEGEH1bRIRBDhCQDs2oQtWIbppQHsVDJEQ2qoEALIiIJh" +
- "iA5Ibr489zs18KLdIk2wVcpFRBx6+tiaCCj5EMxEzMCxQyTxJ8gAo5ZcS4gmZqKG" +
- "0IlJiAbs+AEAgERPIieEQN50HzB2KnFiLFTJR7Q0qNQ4QXyCtKqBvJY82LSiEDtD" +
- "SMDyDTVAlMx1KR0pMIRUiJ7YF7xSGDGU8MEIMgEjhWgojVGuXwHA5gtwUckHgZqo" +
- "ezI2FDLsfUAQ3ZjoWaTPcjarhqjpVVrhZIQ6SsgnCohVS0itMJYhS0GK7o0K+ky5" +
- "Y7gH3tCGO3xVQLLkMHlUMsfgQTLECRQxOLscliplNO4omhGOIJICZNgKF+kPDnyh" +
- "3ErwNoatDOLWiFE0bhwyOBJEYDfGHjaG8xFtMBoWYA6HNgFycuim5Q7p2qoGrMrZ" +
- "iV9I6DYoCVwCNjaBmh9VIACEQL8wi1kyAWKD09rwynBSL7BDbiUwABZHykpFUzkw" +
- "tIaZSwCn04GkNoQOlasfSOXAYa64AHCJyMVG81eg8guTY5JtM+Empxh2Tu34PTsv" +
- "KYzszJQ7oZY4pJ7Ci6JrOjEozq8F0gbgliwihrt8mJA2tda3aqkAfanxBmq2ZHU5" +
- "0MvBycGZje43sNn5CYiGYNwJBIRNj/EqmR34YYffKj41OKr74Ihj1OnAC82B5rJS" +
- "xuPCk5SnOICrQbAWFCMDZEMllsNkyUZkhMzrWJAiQm+4YC0K62MK0mlrmIc8DWIE" +
- "FjI4sXzhL8vpkYEZwSigrGArDcBGj0gGFAr4FqGFQ1SOjTvH0TulJ1XWHAIDBQFU" +
- "2BL7SBXa+99dSAvxCgIPnOIVhPMmTqqgYRFDUUEsUuxDfjmwMpaAek0+O9i+KyRp" +
- "AG8DGE3qEdlsT9H5BPmUugch5YLMiAwTAkdnj7Y3zvRe4V3q41uohGNQNXT1Czcw" +
- "ZOHoCYis+EOsTzziYOV5ZAwqoHrl2ATKFHnpRssDzmLdSlJDg7CCwocglqhuE+Eo" +
- "jpsHOFogASPtXBwKZ802h3flM1s1tZA8sM4cPDnAT6uS6umbSt9nww6rDoI6wdYP" +
- "ABwCkD4MpyWUDjtRIBzdU79HbBiX3vcZZGYTeQOlZsLH/hj78oFxFCAR3XQLAaGA" +
- "dDiPltBD5eyxp0sa6DUCQ9yB3omnTqYzNOQ7dGkZocqlwqH9pIRCGyUGWBqQyCxy" +
- "ehq7n/X63fbu3lvZivHbt2xc3MNMke2l6Uc4OiBRsMViTMcmSUZzTiouB0cMzMDc" +
- "MhAn5DyXqlkdoH6TOX/ia/RnX2fHg6KQTF18xSwHCgLERnIs7MqnDBCuu5uA3wgA" +
- "RixX8J05hR8PDApxlQIJmGtpRVjPTQ4WhDIBRyoZ5o1kdEjBho15A6uhLHeFCwXL" +
- "+9soCWWtfZsFJSQSLh/i4cADpq1VAz4GFTiJjhUbKosgl7B751ekmAW8qEBkjrpJ" +
- "Tsj2D0AkIBD0X4qoEMX0AA0zQzao5o5TTzd5LNDKrnPfRfO1p44OgI4xIzjnvqR2" +
- "Kz5Gwg+DJUL4dAjsyge+pYSePvEmKovgUXXilLjBfO4fT3oTYGwHVC0J2gKaO2qo" +
- "GfZ3ymu7AqTWofKKHc998pr01xD2hKFgCFCO1eIWDjYeGgvGgWPaFTjzJlNzf2GX" +
- "XyGuBywpbCI9aM6UO+tOtaQSqpWu2BesY5kXgwTFHTUPCg+y8oeXVwQ7yjsYrMak" +
- "XS4XXDAJlUBAhUGk7oKAYdKTLFPcGom1CBxTjSRRsoYbfcOs9iE2BKVx8w4aN9z7" +
- "7xds1BTpEnKyEY4TEIk3XeTS9hcaRANIX4k22qCDj84dwRJjo5YkxitJJAO9xXTk" +
- "OFA/MS7JYZDxNviHhoYrl0bDxFvhTQwSQimhAnQFiYoaaHrMgkYrCOGBtDa5Bmne" +
- "OFKwdG8DmOpCyvhqGYNRcB69KAlJSFA5hCUHKDE4GFcRwyRmEbfPPpveJJIDaQgw" +
- "rWJ/P78yCMO9svE7GZpvnPSWaCtoEgL2jLabbxBVKIsbSY3YtJJ+NjNh8b8AilDw" +
- "UPusGoZAu82EYImSRSk5GnwVIKWpSvFeBQnOAdAMuTV9DgEQgQgvrro7JHSHZZfM" +
- "JCKmTtQFOCceAYcT265PCAg2SE+XhMkKlPgHB9+HTOoLI8s4BJuk9F7wqDCjRw6y" +
- "D8yVeukRZ7qrFZYrAMMmhmgFDKEdZztkqFY4HuEkfuhz9pTsXzFtqqB5Tv5gsZ8h" +
- "mh8x8wAfZSHNyDX0vZDTySL94fOjqfD0KHsVflvrWX5ow8Q0QhFVMbcpmX80Ezgf" +
- "HYjMuA8wLy42E7Sz3rziuCIB2DsghxkkRy0Bzp6FVAA8MKcFvSjqknlxdHAT0wDn" +
- "07kBQcd9oLK7tKmnZYnZZrh6DrhvciJ0ss6vdzXdwMQKJMWT7tXSHPByoD9hWNqM" +
- "OwE85ypXmQLQwbXSkJWY6qxCwo6HFcFLCAk6bCVHFyYQc5H6Ezm+mNHD03wkk6j7" +
- "m480R07W+QkhCKSnJVvGUvBBlRzDZDeeaNvGwHd0PT2wTy2HnkWtuMhkklgK66LZ" +
- "BC6hKMJnOxOpo4YaB5V7rgiiWQXGCiJrYk4Y59qslhcA8/XJNJQLb+5tUzHJCBgj" +
- "Qx3GrzzHn6xmZ9A0PtV9dbezpCHExoEDwlrH8dllA4YEY1mhsA0dIPPsj4Mi73vz" +
- "nrsvJLs5YqABDfroHBg+ShQ0IgOs44NI4F8CIIsVXHQ6z3KS4MOhdxigYOImz2UG" +
- "gJAuBhpsgLrldXnhNQ4jLCUyTxyhrIrwuyYrqo6MJzQ2Wl3AdDzKOb3Cydryz5Do" +
- "pHBHMKBNdAOAdXJhYMgMb2s9Fp70MSClw9KpTbdzhHAuMGAtobHQJ2SURvgbbhyt" +
- "BecsuXl+2jKigzt7goBTjmpC8RowanZdxJOhWjwhwrm99FSiJ2OgLLnm8pnjT1Fc" +
- "CXCc0JaZijcmjpDACeVTrZneXxGRA+184I985kcHQIQIEFMgWfO635rg0SZSO/at" +
- "HtcUKa3TZ8OJoImYsgRoKAhiZKIBUsG7yTOFlDFncMU9EG4CMLUKMxbiCaMDYdhs" +
- "JSKdyLFJCQmviCCLgGuUz81ptojXx2oe4d2iHnAkVSdhzcfH2K2UnIQ9u0F30MHB" +
- "OBY0UHMYYjgCQTAWMbwXTZQXaOgnfjckJ+BO475Zyfo8/R0NlEMBq8c94sZJiNrn" +
- "yJ8OoMIDQPjt9uJK8Rk5aFDYbJfWSynwRhgIbQoB0+IsZPFGy4yADzZLYokaBywD" +
- "CRmTeH5tmhDzPmA2rD32gaqneqHMNqA3FgsMePDM9KB69ebN4HOAhc26eoGFI1QJ" +
- "m898wsO5qZxBxcWUgvtw5Q8AMEOOJJ8HEEk6B45ZyIoFaB5KW8FLb/M4KYSZIP/T" +
- "y/DoMk5Ami3wPAH8EyWhTaUsFlQ+g6AEFdgHlJWNLpOCvdk3q+hWdqbTJWRS1dey" +
- "wOAQwQUmsxpFozUQbFTRcPzhmHw0BxsEHFHdI2kUHjDkRPSGAp3SUo8BEdPPPTw4" +
- "44KbQ4SZsIKdYe3WCo1EtM7zKTu1VAoZ7hPFDfU88SlCY2aHVSnVAOBA5wzuGlcH" +
- "Rs8STcvGCu0xIzUFjkwcvlheRAzgRbJkzf/N0YjQwJYrJ16VzC1gueMTW4Rt5rYT" +
- "IRNwYQYtHOtSD6ShBHOQzP37jm+TT/gvnq0DgyDuezyZv7FGKF8j4kpFLwakHPsy" +
- "LSDphCyxQLl7xgnr+Pl8wbTsF8dx04kwB75wFRLdNRIBmhw2pH3UCbB9EgE9z5eI" +
- "BPN3vYxzTZ4nEgVR4qoGQtM+BuGwlgV1WoHG4EaoNASMhGBgXYFRVYIXlASg6LSg" +
- "GqeHmiyAsDilBBOqQsS4Og5rap1miKqAdUA6AdYTWmgTRQWeULDLBzlSEcEEDJbB" +
- "4nTaBTC2glnEXi2haNhLoJcdgCNAkhcqbCc44gFrBrre1RE7eydRrtb9wdNITgOo" +
- "j4QWulZiLl9z7V6DbnFmgcimAjOFhQs7UI75C551aKdXmUEHKSvEOCldH1YzE3wo" +
- "E42BxwHl9Xk7YSa0g1vV9CriIWOztgqD6DgKN3AvOkS3ODdnTdtll+abk1SRIIGv" +
- "fALBUOBR7ZFBZ4BUpBnSQ4hFHFEZ473Y3P+zY7O60Rs1LaWqHHIcwa8txlB4jJJE" +
- "w5YZFHWAZUEtKyoIGdMwDYlA+A9mFgSZbOw4M6OOSmPkMl1OYzvpRASmvvXmUjTp" +
- "8joGG1lR1cQpEEugzJBUyZnlygzInkeR9IZ+wHyATZQgPmd1ZmIUecB8pAzd6P0t" +
- "AUK45zvDzCusNxdKPDohseJeeAI6ZvadwEcFQCRCgsXNcDfG6wqIm732cGQgwkIA" +
- "SKEgydIjIZQ4a2thurU6wysrTQQglytZnEFtKoQOjdqfOmiDah274ym7EDxm9s9L" +
- "CegGgMopkIt4LQ1Xtb9yBS7B2LUpK7hUpgHQVCXmwmbMOQqGHhGVvfpgEjVDoew6" +
- "qNbwaB5vajnexW8pSBC73poOsSDMENqjGDoVUvvCS9M4jdfRrEmuQYwM5KDSHMK3" +
- "B64lqG9DhQ0JoNQHlDlAPccRKnfODi2TDOoYNSZAcBzrUAVglyHGRUI0bMziEWOU" +
- "JYnAOUMt6Rku3X2Za5l+nJIHiJXNq4xzccGdzaqu4qJJiDRBAN2TBKurol+bv9SB" +
- "CSAX8+8Hl/r7sZnxy9PYe6Z7cvs98YtZ/SwPrgMD9OXynBh/XzxwXwdWFeXp/iVD" +
- "kMgNriWpJDP1n5azCg6/xxxEvwpxkfhIP9s+2nQ/fn4vF9+jJ+ngfdWL4CPb5czf" +
- "UQwvVtZEuz7Om9iWrwP/ePX0KAP0+V9inRoSgybccCP6dPd+K+f24YnQ9YpYUGst" +
- "TKKFMYQdT2HL0fr+fbVW3qvv1NLVbRWSUrVJUxgSVjWktRaoqKNrFWmUUVMjUUmp" +
- "li0zKazDabQ0YKDYxZMGg1BpRpYUwpQCMhoC8nsJe4+Dy3Xr8S8ifkOz/vaP7ETx" +
- "FiYoqdkOeLbBtH+bHadmz2QGsccbGX7OU2D+LhZDxGPjMsOyV+DZO9PSeDPkEcZO" +
- "SS8UzBJ+ecnUZhlZ9ZyM/ad22YYrjBcAz/3V2B8/JiuT7ED9kw+rGGSGmqTbJiMm" +
- "LSysmTaS0aks2bSzWlZtg1EpSSYlNkqItCalNFstNttqaprSmpS0pqU1LNFgKpZV" +
- "srWWrM0lJM1bEW0qbEmiLVtRGZUbSprWbNaLUqaks021KtbS2RlllbMsywtspLGj" +
- "SaVEzMYk2NmzWptlrJWmSoRZSsptlZZLRGTaNKm2LJmmyUmSWRk0WpqlUZJJiWlp" +
- "tkjGjUy01TaUkrKzSlLTMzAbNg2KlpJMl63e7/d+ENF1fgGLHuf56NGdqOvg7hSN" +
- "iHHED5NKzQnm2yaAQJTIxieFJM3ij3X3qh5AHBhk2riuNRvBd1dJNK/o55W5e1NX" +
- "ks/nngBUDz7INtUfFdK0JrgNgbjAdgkJGRczQCngL6Zh4BT2UW6xEWOCC4FzQuaj" +
- "OxoBErUsV1z6K8cAICwJGRj6fB5iCC6h8QhiZB9qLr5NFyCenPzIPnc0WwotMInx" +
- "4sAoHfMU5HgU6hhRBkppj/FgHNLt0ubr4APQXPI06DXqSSyDZid8zuPuLwXKN4cj" +
- "jq/w8zETQQQXn+w0DiEJEiKh7fzQ5LMfgQXmXrdtA+sBzTIigGxVCwsOYhmJycnC" +
- "CGplhE8/sdAhQXcsIRJFJISEJE8flHQO6cgR0ZCoE/TcCd+BBP7orIml5zlZgw9K" +
- "QKKpGkiwgESxpnXK9pYwUAa89ij5sPoUYZjQ0lyAcxQc/xtRzIOJISJHL7Ny0JDw" +
- "BwZa4MDUFR8D5CCCwzTyVsZejnQapAVGYICC5dDXtXOsmZXMO7mFWN7P56mEGIAc" +
- "JHHBsharUAUcAp9UrviBIAxJ08i+RBO3Ah2QAgiK4kThwo8sDCf0aftxqENQKMTv" +
- "TZBCNMVoDJwdi4fVhYNQyMy4KjH6SlEAvexZaMCmxViqK0e1JpDA33Zg0xuGQl9E" +
- "hiQvQ2FHNA6XqGDe6CB3obIHAhBD+L/2H7JweCnNu3h8F/bQAgQghowH1UAW3ICg" +
- "LRMWh9MD3nL6B5zvW/rtbABAW7j9J/ubhTjE1Dh6fjPlrh4F1mHx9l6oKaKdL9MC" +
- "Czogscg9WEHR1P1lXLtPyv2av6+Uc38L73W4ynzSHQzT7n4a9fw9G0pHvHQQT3Ww" +
- "CpsYtnkcGJdhEoMqdwTQQQWf8H7l+Sm0erEmuPTqAC3f/RC5LqgrQdfyPN+J3eTy" +
- "V4GlQVzdO0KeqEArm/KUORmgILgIYcAUkDE9WuptiUObqmYfnmExHY8cNvsWx4o2" +
- "QtFrwFybGSaII/YzOu4hsM00VwmYOAJQ3KQY+rag56UiZKVHIpnxryUn41uF8d2K" +
- "fszLbyzAkMTuQc1BJQQHPuhBBej0s+yiFTpnRcrVGp26/SPoGgGLAjmBAhpnAPYi" +
- "hGHgg8hN+hAh0NObgHp2R/M6Jo+S9Uw80pUFedRU1bYFRVog6sTPEHADwMAG0oUe" +
- "ZTzCfk4pmd1M7BJIMNGsaaugBm+bdBpLDSNwIBiBVKx5dQgre1pCrhP2FD5vX9bb" +
- "a28/PP14155vN5a8GIiRRgLCSaKIJMBu9u1u/IdZNWhKp6tcoZGbueNNIlSQLYOV" +
- "guF/I1QEFvm6liJuQ/g648tjVjId/WMg6iEQnkcuhltYdGxoELryIDySIMiK9wD4" +
- "MbBiPihigLkeo0OhARBcol9jMSNhf2ITsgILYNseps5hodZnnUYfDxJFi4UQzXNx" +
- "EsQsWIsPUhf4XvqFHwQ+WPfTBIHct1LIZYv2+juqALF8D9dhxOkM18bdDBT3QEFx" +
- "IIWRNxv+UV8R+J/0R2XJbrEIOYHU+pkgRzsDEdIZEebTO4gQJeqofJbdkqra4esL" +
- "roGjHL6Gsy4rZI+PElgZlHIH1++YJmDEhF6psaR1U3IWVmpF3VwE9oiTMpi8Nzz+" +
- "aHRDUDwW+WIdt3zPNOewJzPCB9E6jmCYHFX8LoITudMz7/N1SyV8kTcL0XLh4A7N" +
- "JzfBgyjFkYbKgC8xPTQ2NEVHr3NX3I8oB8QLJn4JCrIRrrR5SSiELOBCqIlECSOq" +
- "AgtNF/5UYIUAbvmgBgPL1xIT9UkTRqqrX53ixpCNGKHEwP1PwJh+ma3ptrBwODbq" +
- "SORcDEiR6PVwOxokOUEsjBbkzcaucQzU4IBkiIQDSXJdCotjbIzzDs8lfNscXA3I" +
- "EjvBoCBmX1Xq+IE6m5+HREB7xUkefMhRTIUUVEoGUY2sxAvjsdB3GZnYoMTuuOZk" +
- "0IILqZh+sKgLQ1ULBUF4SYf1u+nDkki7SjNoBQWIGv3PuY3TIDM1QtuJ3SNep/DE" +
- "5GEdQMHhYWdISJCEh+RRD7S+bd8OK+sbha0qU3NES7e5JJCEsxa4lA5ucJdrboo7" +
- "v42uXj7XKXZXimppWTWQJDU2Uks0imZSWU2bLZWUpEzCgmWQzZKmlstNa2pqlKaa" +
- "aU0pppMDbLLVlqzSSa2lTEtKzZJmtWpNSkylFpqsptkZrNNSzS1S2bNoqllIpMmS" +
- "lmYDKLKzVm1LKVNkglKVKmyy0EstNixZmkjEiWms2xGFpVEWVNNKkSaWUpmMKLNQ" +
- "l1leHUD7BQQf0nxooh+rfDYdYFRbCkgUOlBI6EukdLgodLEh6iosAIZUDGcFIBnT" +
- "5PfxeXIybIEK3a2JhwXN4a5XZyCUN1QHKuKm53cudZGkYw+CUhgAg4jiFUxQcoWX" +
- "ZiDnC1kcAxisjx4FhBuB1RLpkW/L1JdQMQyPlqBhAGDxWuoWKaLLctSBSGSu4x/U" +
- "+UGMFxxCH7+CQBDUTBsMAfQX99QooSAcCZEiD6vqNtZoMtphkjx94b82mEcdDU6C" +
- "GIfhpBNHRGdiSEhKQ5wXmRP0FuHscjHIQQXE+/JA9QIe5u/rPZ7iGp3RjqDlESQZ" +
- "JCQm/LYfclj52MSyQjrCotj6Nhs9YNtpjG0eYiFHs4e+RkLZGv6lQVs25H8UcydI" +
- "dBwSSJWZ2GkMV5JBvs3IEHqRvh5VCbiosL1RQbNSevAFkgodQSGXyDwMAKI48pbY" +
- "nKYY5o3AkxfgcNu/2TS8/z4OpVwpwYLoslFDS0dpbVLklyLktcy0qrt1rkkVDQKa" +
- "U5mIfn7qbHUwB+pUzzDYgdOwHNMsQqIeAQgWJ7CdQLne/Uch/L74GbnkIeSHVY7B" +
- "6HzdzDBZDLh9FDDd7l51/E5mJCBgdFYeAu3YglszcA0yVJwA+V7zU+xXQdNIJq0w" +
- "kfMItgm3gj2uGRgGUX4BpO2ZVeDftfXE9vP1ve16wzwEEF4VAF3VrV67Ndd89m7O" +
- "GA6EokveXN9MfaQsQ3ZZKcK50mcwJlSsZTgk98c5KYw84IzEZbkvNTsNqzPLKyHo" +
- "Px0sFlfMO5q7Gy/RLjgGa3WwaF0oI5J5CEBrzAuFdT9Mc82Cdw1XLYdAocXnucxw" +
- "MDq4Gb5ImDg/Y1aNUuciSSLGs30w7o64wiPJkCOJGESEZEDZGBLmOHlrwGGQG1zj" +
- "MtuCoxq7RpQlgtQ/YQ5xHKBJJHiia0FHVsRLGQe6Aj+2KgIUQACACiJEFxCraZaP" +
- "BqeGpHqJ2lIlZ0RymyqrLMZVKEz6wYDwNnVwEvXcGMYxgkEpwJK03QsQ0IAGhJqy" +
- "CBkmqpjC2e6t4I+Zf0JUTC8cgiBBIMOpm5aNIYWCqlcG2GZjNkLK8i6B/LSEtoDR" +
- "RIJtyOGwPFu5CEb0Y2d1QVrHSAerk2mlwOR0esAyQ5waYkWyRMAgkNlX1WA43hGO" +
- "YdDY3OWXJQzDIuXC51atcCh9k/jjTxk4r31uGHUMNV7DyEEFu9aoidiNHFzHFW3k" +
- "pl23DYUqswRQLrmUK++C6OIeCEEGO4Oxqcy5rvYfEQIEszhUi+UBMa/NHV+bZCGB" +
- "BmDsfjN+oGAKjwgfAOjBz3eAT0JSBhgZHiXA7HejAOj31UJ0cC5soXLOxcOBUy41" +
- "LJM6Q8Jwpx4F2KjgcPvn3BRaXEe2Z4vPu2/yeP+aH5JvaiC4fKQAcndicHNDcD9b" +
- "ShgrZAQXSGTpCSlPzKD5gwnhsz+p8ujoewiFBY3pKLSeXXMDRxzJq44NJzlzG7rV" +
- "oWrj1/nLbhdUFc+SIUCENGZwNenyhKIbAqfWTOCRY+YUj3gzmpUR68AgUjUPy+0G" +
- "2hIxUaJCNpMRpoFYjY0WIzNmFoMaNFtEYklpFixGtGxg0UUVJoKiwYNaTRqTKQRU" +
- "G1Bo221i1VFhYBqNjRFIKqgpJIRS7/L9Xk8v315svJO9OR4u/ONn5FGPE3fMqdtS" +
- "xkZBu7kta5NbuU8MxyZMYMgmsNmMhnKfGmtyIG2LzBpqWYIbdmCYi0lYLJxwCFFa" +
- "zJE6zEudHD27ZzbOeSgpk/HnkQbT7twqaaJXNvUzMuUt1hyhU7ceZcph42+VTlXU" +
- "cZ9UZZJyYojLjaeJHfJU1UZUEmBfLumu8yW5skuyE9uh2BmVxJZi6KxaXBNwSolw" +
- "BqBcQLj3ucNZIYZLYtirLu3brW6UYgZgZJiDIGiwpsgg7g1AITkgM6FHITxDDnGt" +
- "4SDHzZbL5s8fec5PCq5DOzDRdWS+0h5Y2INZak1D29cpVyb2aVrV3Wlt7rQhLa3e" +
- "m3ZwPNcXywE2Qesk1XN24HvZ2Xa6nlm8Pf/xdyRThQkO1NjuAA=="
+var jsonbz2_base64 = []byte(`
+QlpoOTFBWSZTWZ0H0LkG0bxfgFH8UAf/8D////q////6YSvJveAAAAAH3ddt7gAN
+FrKppN9gw0gA++fGB9xKkUpX0YWTENCgqzUW1tlsyMB2w9nnvNSigNyS+3cui5zA
+AAAAAAAAAI4kILu6ytuWTLBbaPXfc+A+PQEgNAG1ZMBYWnWwPoFrGjoBnYMumlUF
+UKA7NVBQgut30zzu8eM2tsoapJ7u41djLsxZarplSoJouxrdfHrHPSiqAGgkAD6D
+QfT0ABu7gG1qDtdVHVXp7vWuBoBk2wEOjKChQ5bvbh3riupXZycASbaiQEECRKib
+ZFJFtqWjR7bsGoaa1lIFPRoKVQKoJFyqbWr5OB1Aie2pobm1EJKqVBU1EE2lCg6a
+AUBV9hqL00q9btQ0J9hqu2zavWVdjI6aAusU22tNa+8m70GjRqarKRWtUDW2yFBI
+1kBrrqrxeX3AyB9AD0wAAAeZ6weqV1rVu8UVICgAAABeDn2cAAd9gAACI+7DvjHo
+j73u8X2dDXT2x6adeFOTNe7BvavozFezkV1xXtJzu8H0983QAHr5aPT42iem53fX
+23IDr7YejQNtVVZr24gGgB0VQffPXH18g9DoaDW8vt729h9bt72XsKth0ANxgodG
+iRxvYclAAAAAnpqRtgGvcbo9ABpy6aPQADRZ3aACjyox4NawKCqNdA6offa1WtPc
+fdjQUPvauprcLoPe2oaplp2w7cnOHdlF27xvPY1QU67vc8goBRttLYKaHXkPAAAA
+AAdyFFaYCVClAVSlCqVSilFUKEgoNT0CAQCBAk00g1T0jQNNPSbKADQxAJEBESIg
+Seomk9EB6mjQ0NNGgAAAAkEgkiGk0CR6U9CNNNNNPQRo0ANAaAAk9UpEQmoNNRqe
+U02o00AAADQABoACJEAlKamUCjZT9UGnqAAG1AGgAAAFRJCAQCBA0SYjTKbQmqea
+p6YU2o09Q9TT00nAlwPEuSelCeXl28B3IYIQHEwXUMSCvlAYS5LkrZn+XhHHAXZz
+FTJHAzrKZzYWC0pthA9SCmbkyVzoHbSUjhnAfBrYpwWYIB7GRjOjDQqokMbJENSO
+SBCN0WhaRhQWpVuoOLN0NPRed7eO5eW2lv5L+X/jf7EpJkEUNMJKZREogmkjMgZJ
+BiEEEliRIUKAoiaSEoDQZJBhKEZEQySQCAIIFNIMwCiSYRSYzKMkSSlI0xZMZKko
+RKlRtkmWJIrNNIBEJEYiJBhGMMkWYxRqUsmjKJMmCFJMaSmiyDSaEJtBIJpANKMN
+JEkpGQAYjLNETGUBRAlBKURgsC0wzKZhRmhiYIQZIsZCIIMiiNmFCCiSZNjI0khE
+AYSEUkjTMSZskZKRQWJoRNBI2IojZmMhTIkQEgyREEMoomDSiYxAZMECFCSKIkGg
+kIDIw2MNAlgyA0SmKWSSyIaRCSDDIkZmNGghgyAEoERokkWTA0xZBEQhmUSBGmaQ
+aQBFmRJMokwxIyRSWbAkbCUFlAhgUISJIRkySYhAxoUARCSaIJMkyiZJNBMyGRIh
+Y0komKImgMDI/038qLf/av/bWSNVEtmFRx/2aaDVmKkY0NkIRDGJEWoEGLf9g9MV
+UJWGSu0pWVpSOdWDVjQJGRSChGBGDGhNNMYYwjEsaFISGPT3TbFXk873Xq8vPa9b
+0dcco0UEPXIl/+em0IMHNYJaXBEsiKQh/7QwsC9gAauDvWtMEBWhGBIBAerIYlBU
+SzPasze15BfAyGrr284QNjGNEmaUphiMxEMwCZjAYRpMiZBMpEMkkQzIwTDu5zru
+Xd1xdQ6A6E7m7d03OLnXOxd3HBu50dl0JOhxS4HdHczuO647uuLu6650O67t3Duu
+3DucukzRKIMhsUjSQQxDIzQJgxohEkYTYkZsAxSDGCJJERhpEAygoZRESSEjMpFE
+0UpJlBkIYwoyQ7/2f9H/Py8roY3wEn8nr7+72ybZtybdqY06yp1tjGVmsmJvG48y
+89EXnvy9F6OvX0vpBSIEiSRAmgSASYSkCGBkyc5J63pgiRBNsJW2xjGmmNsf9v7R
+z1rueFmZcfXzw/zTGRYxsYm2NjbbfXD64GtivKx5t9eubzmsMTbf9rTfKRsYx7YR
+jHWL7OoAJpsFBJgyAEzSJiLHxfJKWQgSlJjGduRqRxDIoETG4wj+VgUjnMt5PXnm
+vEQwO7ojzu7lxu7uasg9T00zjrtcaG2RKIwyHx2vUcbjd0OXXvfNafFE3u3t7bu9
+TpJ1t6SKh9vi13hQUX4d307pPHt553zxxHMGb4KrbbvJGTCcNs3WmOyG2fg5vsuZ
+jMi+lacpNcvr0XeKDnafDcIvhyL7927rr7/Pzfj7qLVW5dFKIg8+fKpuxf+vfhB+
+73vWXz3qCPPfw32Mn4c/9mtONctW/fc1sYad9JYn/D1DlDPoyyc7D5bSi3ncMPNH
+bWmvm42eODHImqooiuXwn95XZlmKYKGK7KdA6lrgzZpEiUccypzKofPy4kbjq6Nh
+o/ou++j5g2i5alDG/G3Cb0yaOY3lH7wd83fLG1uQ0nDG18UHnnOOsy+Y4u2Nv5Hl
+jTCKmSJYyBhnB1Lbbafjgaat8zzctvDjPPy7e5IdyZHPSTxq/zkHjinrI5v0/nmG
+Pp+JUz4odkc9b4/cze19oRNOjG2wb+PkWtt4RRjbBsfupHPO3Mmgc18az57U+TM7
+gQsH90UPHJCZN4WsaY383qkbxxO20pI23JHbCr3ssnqkVFJG/lN5x6yQydwiaSA6
+rcgBoSxEDRKIuS1slJsq1MtS6koA5+jFGb17XFu0owrTZZSqsjrkmLVo2tSN44ac
+fvD3aWfOerth5lG/Jlkfp6bqUbOZs2FpVptDIwCuWVgqIgkgJMtDBFi+2FpRDhEI
+JAKJtPXloMoKGWpU0YvH9h2nx/hxra8/8UoaoWbia9EeoTlN7Bd5PNdcCDKemn+L
+cY2qMUXGibc0a33/wjqMN0s8PmTeeup76JA7aKr1nMbhIkn1aX4m5rTPH4aOBlTQ
+I35HXHwtJ9z1XuF9EQDwDnCS3S9W358a/E4pTeTSVvyKGWTK/n4Xp7V4dB64Ua3Q
+BIaDtzTsXpXV1k9E54ousxG/XtEhuaGmyCefTL/r3478anc78deNRjg9uchGVxVD
+Fq6cMZqIdp0ihq0xoIf1zldyBS011SFzq08qfSxV8u0cT70dZgp8ebjk800pU8m2
+s1kKdj+zvmBEEU+P0+FlzrhOf/ifG2tOsmrlp7B88bbCY9u1VFK7YavjSQ7xtE94
+3aiJb59/et60wn2vrgeV/jeNd+O/Wt/fp6dNf7iJA5QICcGyiKgpFEFQiCjEGEQC
+LBIioACSIqiCxSCqIxJIw1GQ0Ua1Vam2qYsmg1rVTbQlmjVbWbaGLbU1kWtlqWrN
+LVNNaaQICZqIhD/QiASyQCUEBKiRKRAJSUiASySKRAJSD/zAgJUghMIgEojKiCf+
+CIBP9wICfq+/889/0uxkuba/pJdybzbJvEsZ/CpEx89uGn3OONVtyYDHCGIxNyIx
+JsYgJYbH+I5RK73DuMZminldjp3e8QpDJju1QToo7pQFEpABpEV4CLQo2QicBAbo
+SEINjsMsDt9BO4nJzGstqAmgEJwhRyggJYoMJE0sJoa0zOdEgXdwiQssy4L3pzbM
+CwOaLEYFDBQKzaJCjFh2yhQOHbgLVMHXFUf7jhKTXPWsNDuEPXRHfJuLlKqls5Tx
+pCC1IgIHnTm5PeWkwwjobODcCdTCa0YoDvMlcZwvmQTkg8KC06oALrhzZqrQmQq6
+E28rdrSUxBeLkBshIKRh04g4LDdsmTCpNKSszbu9lHOoAwkmTDrOKCmSqExdOsOV
+D1XsAQpFVMukLCcGYGVFpAp4Bg0VnXFFjjdC8avBE6BepA3q6bOgot8LtHTiIlkb
+ARVEcldJoYt4Pimls9rpBzDNzeMwOdNAdSkWo4CrsTZ065yPaODXMCkcZCarR0LU
+voX1R3nDEsLtlyklMo3qrYHIguO1Ci7xRXFwJZjfTrtZfAyzUKhgJcLOIzeTvWjG
+zDE27OYME6dM3Z2kVeKcV1I4jKga0x3vCKlcUmkjRE1Zzsmxsq7L3zOnQ8wzeGDZ
+pQO0uN0NpZhcQSuVETbLL2zvKTzqjtBhwIXGaksi8rYKx2Wi6C1J3Ulb1dwqkjat
+FU6mO1F5Ii+bGnOMaOlc5EKekFDaQ9tjCU1yqcE66xRVh1ndLcBt7ThNI8LbowKP
+Md0AHRNhdYOJksYIQETYuK3ytX1UEkFHZLCghijoBdFzCgKJmlJSADdF5CnsMoIp
+pMjeqUgBrXACCcshXWsqyAgenB7IMoT6ZghKl5ljwkJTUVQuhTp3YIWgQCl8eBO7
+FTzwWGBEw8BDaLuSqMmM0wWE6QVsFIpRwmCRA128BCKpdaVunHbkyuScBsqeFjLJ
+qAw0WUUIhMN3S5Keua7Wynjnew31G8jecPcVIYxGw3trGziGoCdTHKPOEpO5732V
+4lnVA4VvKsc+R4OHHQz2JkHFdwSzeiDBUGBiQAJcznd7Z0oCmMykE5KjZuKCyKhd
+5nTSBBtu1sj6s2JCiZBgpYdOIM4luy6evBlYUYldUQQZKOoAiZL4d7fe003l07CD
+omKNzZgXiveIrzXjCZel4BcyY752rec3eRoT6jAGZAGEc3kkZQhLcVNCq+qVFSim
+BuCKZeQr5FF85WTJZzIXXwto0cB2CpntlWr0xWTfLt1yrDg8503VJAdH0uqes4bJ
+d5wsYFakMZlVS7lsEko6gj0LqyENh3rvG7qYJiQ9xoY33UthsUwRtEF6HUjtHWGA
+1q5N1HNgiI7rFa5QiEzuCDZ03KzKswfM7185zaRUkRyiUUssQSPAwlc6CAaa2KwB
+CwsOVTUrpamy4uS+mkF2pVMrpWpG7eYkYjcqSMY+pyDKhDILMmR5HGGc5ml4LJEa
+A2sxQOlwRDZ0WyiDjMTFnLRKRw6sK02ph9cZnMe8fZrmsJ0710vNY0uY4QFbSrzd
+WY7FvR2oW0ZI0zyUKMETaoJFAUTUyWuaSjAQt4DbxyqAYcj2ysQneAWKMQAWMoBB
+hIT0HPY5ne8L49gqYBFQhCXlCmzuzQImhRcjCApqiwAmbWJbzsY5reBB1xT5l5T1
+ybWy6V0tnJKrLM5WHNy+RpkM2cyZ5hebCcdg7aCc7IdY80lCFwSGCAXNmQXb2QRQ
+x7k3NRDGXELYQ1gsQhhUDum3ZE72ughHRdRDe5Te6qw1u1LB7lbNrJow7QT1uAV3
+LMgyxdGjCMORl8Gn2BQuwIUzm8BtHWJnZGBtieoICDTvKJbIMisQ2U1BCZoZlhQX
+ygQBW0jtgQdslCYNcrXVNnBA+zLTmqmqYeS9YapA12zNGgCPsUFmdoio3ByWaNXs
+7NrZuGMrSZWRJA0vOHdOWzMw8kjKrskdtyHLanDtiyJzpWVgjo+aaaAkqTKWLcdw
+xANHQyoZ1XdCK2biAxFgjnDMsxEk4wrWTKgmoae5DQbpESptb1u3Dbpe6qOAZBKa
+UBJKBZeiCwEJ0WgjFAInS4JGF6SCWBfA6F3ud3YtJTVontzKvsRDk5lipuE0+KVI
+KnHbGmhhDdShYAZ20BJi8hNs22nd3MxNWKTyqlNVdr1vFs1kiRRBRoZYJt1SAw2W
+IVY7gXmtBFNaclgFQFjwnNh/g2AZt0p2YbFHgZ1ZkUHIuCAEMTDITBEMBgx4Ecgg
+OwyuETQ7GUQsGRFZENlWXORDAZBg5I2Qg0CU0NEcuCVhf8E4pyCmHivNaJAP8Dg6
+HMU/BCCcRX/CAZi3FTsR+gqagg7gfXVQF3AFS45ig+iMnICOKROLlQG9QyjKyxqt
+rL7DL2NWEoOARpsJENtjCQigyaiVbD8RcRpvD0dJYxh4KmINWGAOAshCD2ihhCBU
+w7Rz2iEeFpgIN0kKqUcbsJC1I9OQR1ARqIJlDBA9OIaiEhhK4RqJxpaG4HNX26+L
+L2uVbzYr6uxSpDYDItapRNSDSPMC40zShplaragEHVTTzmCYzRWDaG4boqxNVpQe
+/U/8feVF+H1z3Iy2hnvDyeOt5n1QI23zarZHe9m7tUTEm75vIImeGztcNqf8/DK0
+7AS3hyuujbWlvld0RqQIdaW8VAyyAqKpJUEU5BBqICLiixEH2fZwoinThP1ruaww
+Wxs79RpIWIc1I6VkHrWTkb36HKsT8aCEdYQp8dyc8nHc5Tn1GZ9DqfXs+w6jU5vi
+5KOwjHVB4s9RJbGxesXpEnueovCTuXRSXfPMqMjxq9le4We74avJg7nrh8fkY4r3
+uTybuqrI5WCNRuBiLUVuMAR02HDRwNFmhVQC0wOxtAjoECQdIAuc+ZfaLo6O0IVM
+EV4FEtlx4W2FCCd0Phvqkylm+T5VSzgZCqK7UNZc+X11LEfD369NnPNn684h236W
+bTiIcgobiiYguzQoGj4YxXj++cs4Tz0qdHkwXXYuqOxh4RlKlgXcTb+ZT58LL54/
+X5UkWd6UwSUtKWg8ezAgn3LlVGy99KvHea5jdcQUuTpOwzdqe2VOu9t12gz7+79S
+tp9hZGnb9KZ0+UWVGOfa8PL8MePzZ2jpXPc6c8Sz56UZnuR7VyqryWOdve7uxH+f
+7i9zTaJuakt23DIbPPKW3WvwvI5hyr5WOMzSpMgcRs3ZkcLrNrzmzOP/kkQSPs/c
+fx/623+62xX7H7t/15ZmW2yT/C26fxC/1B/Nm/4vHf4Y/W83vZdxnDDNatLLf4zJ
+2SOOSTXtmh6bgfkM/aUg/9rYz+ROs5f0f7Np83tXE0ON27ynOf4eduzHucnkr/bP
+/xPo+Tm1N30cm7RXZ2cox/U5Js3cZ8ctGrXWkfP6/AuC4YHo+wmtGj+jDpRjOnhC
+Rui6MS/oi+aX3Nt6cccYzh37RNxmjpw854P83H24dWtaabtnmK/F6q09XRzP6HOT
+UEd6oETQUHmXUt2toYLMjFiMiAgDhaE2Dii0fPTcNGH7p5jf0kPg3fXkttKDMGej
+3IKP2KJOlt/R+CT7PcY3AZxsoa+WREFD5vk4TdXR6uRq+MzKxSvDrq2ak+c2275m
+d5ettnJp+4/Y+HV6qxudXLdedt6uSdTKGaMJP6jNbZZww68/M8PzplDqYusu8ZQB
+AFQUJ8y9CB2DjMriYXiyEoiFRoNAmCWWSMuP4EvGSYUfk7ut8CD78n+j+iqqihWU
+fmZb8RVjX9LiIokXhgfqc+hjbZR8xHTSG2NvltyeEkBoz+i+EBqwZMS3bqJsEaIa
+GhUYwpTgGQIwCHFSPHf9PH5soVQwNtyu3LdB4H7h7qHvPtJPgw2vhhBmwPscrZ9i
+B0ofZ8/K22LZTR+R6NBmMbWj+o8N5NK4btPxmPo3Yvl53M08zTwps2Ux8n29W7or
+ecnOTH4LDyKfk9eenmurrptb6EDAylMSyCFoPt68A+P2W2rxpvgRO7eOTE06p78T
+pM095szdT5dJNkqV9yvdk2KjRq7ZNv2M/zD1uISNH5LRt2dPbXxwgg+aSTdJarr4
++t4IO5+isaqdYSfl2IOJ0ntA756tsBY3I66SOBHlU+0+8bWUbHdtxa1P2y83z5Pv
+NqJ29h6ymz5tztPN04yw5+OsUx767u+t4Wb68vvztvPsCb27OnbrgHffegij8Dbt
+R+cpqFnrpoO2jCj+dtrCBfwtFtxfNrZd9ZcQzVPa9qbeq8duMYmVfF+2cTONb3u2
+m+N7LwZwK24TMUPA/s1xS2PJ211vg1JfBUXQLO2tMacGtLJmttPE59YWnForCNrr
+vbv4+/xy7+NG7BfXbnqKVTuo0DMuFW6c/DBvb4i5+crr56qLSmCHWi131w0DRNem
+G8J8mWF6/BavOE5YJruAqh/e19oRd79a8j2xXHhVteYnEW9a1AvE2WHFHnr7Wf43
+p9q/GjSGtZb51XBDR5fZe/afXwzt1jTi0aTqd5pQ9xPS9+tflc68V3+R30RS3anM
+Z7/OYoK83au2vY962u/PmnmvWmcymeWxxPne1H49bc+va/KVHaqJxTgrqcN7zDZ2
+TweudXvavlknvqpsg6zC6+IavvB2enbrx754TjNRir97rpG62S7VPnth+nn9KvmF
+thTinXkTrfbYcr54eVPbFQRF11vTW9+CcB+4r3XRpMtsKWHnhn3dFDF7PYpQoLeU
+zh639UyDF5ouhQerfW+FKROlO2lJwm+UDcwvkjwQ51nx2aQ+iINt/lkDDTrmb2vr
+xryHii648Xu/tF6QHbUcIFxgYRp4+V7eaLG64b2su+ONNxKEDlYjMR1Fuhvauj8z
+eus/aeYa2iB/Va1tuuH2zjOvxxxonwsbYInfrnTPNs504yedSRkJR0jeaBvNr5mG
+nFr5TFHNub0FVE3034E+q7tfF5n54uuT4o+28bYpzjhtI6mfB4jbVMEd31VAR4vi
+GN8Tu4umaeq9qLGLNUsvpQu/8faJd34UW2pXhjvaq0NFmKDNZ7UjVrNM4aXvd5pS
+g7LW/5p7955Vtvf6tsMfFl9rs3VvkKnfvemaXnFPGd4je+Y3iU3nXv37xz8/Ot5b
+nc6a2J+dPSXnLYpvqfBk7ZifA8RiUeNNauSKONwZWKpMDsKhPt+f5X25+dAjco/6
+X52E/Ys3128FfCeI+sV1Ngs+8/j7+sqrWwKe/0ydfK2xlW+++7Sx8Nr09NQEOaq5
+Z21TVe+3euawND9LPk1eaTWOD2M1bXSfq32fH5WrqCSRodPHmm85a3Gq8/ldR8zn
+NtO6s/E5oRyyZ1pX09q7BTxk/n5j1O8Yr8nSj+qezJTO/bzuIo9vLwYbxnRYVVut
+OL7dQJYPFNnRyNDLjWmONtQBd1AxDZA39o0QEps8eiBrSOQO+M2yN/b3A0Mr9bVG
+5A42A3LcI0uBvqcxzal1tziFTfaXakSnUaaNpTxpS+3avWO1hvyyUtPUe+uu45yi
+4aeNNM2GnS0nrucvjF/OGhoOnW1aB+Lxnmzq3GyztaXeuQpomp1FUXt7Rffavj8e
+Jxqux8eyex3ftOU4rXxtxMYwPRqwXX3Rcbx8dn9s3YtPa1XrnZx3dqikI3E1b3fP
+b83aGWPme0CcoGvA1o2PWLs1K+ceH4fTFuVHzrGWGpHci+dabeFi0V6m3aE68H73
+Zw10nviGOyJI6DzqzFDysrN7Vt3elS/jFreqKx+UpRu/mfHbO2Jz7663zp9WvTov
+vvvi14Hr7KrTbRduDN4R+UTmqrtsy2L5ZVHyb3Y6t0R06bVXuuJsOJpv5TdGqPBn
+vjuRp2u8z2WyNdKcny5v9uOfk2vv7aaeetW8z7wtz15nB6WenehxSnftgbkj3tWd
+Mah+7rRbrONx6m49l1arhpoQIQzabRKaTwFVPoKPOmlsaT9tWeFUp8/XrDuFrtXT
+1Ap74Ub+kFY8KMkmQ4I7OOw17bYmTediZ0ZtqXZakoO7cey6d0rpPrCrpmfgHM/b
+a7hjUcJ7c3OM2GCCHLLJ9KNHOb1c199tbZc8EKX0o9vETvYazOKX1tnTN9u/0fij
+7WpVRTrmmb7c73x2zlpOsWq3PBNjMryyVim+k6qIHV8cZzrm1NNNtGG3WiU222+q
+WvilXLVPDTtuujYqnq92HkjtPrnhn8wfFVRtPKbMlam+ja2nZNWzVGx40FOJoI1m
+jzX8RMGuvpd/eu+lF81TFb00pDIz9nRKTd6RSnvt2s+s7+qqt/jhaRHwyffKQ/z0
+/tG3K+dUXivrmu3jC03fjSsNvPfd9sob+3xr8iPBlBljpK63v6fnbHtxKpDNFNx4
+fWXi+m1XLycVHAWwI7iooCKfX4XX8vjqgNOk/E9udJqie7fMu3gr4Snj7XtqUiPX
+k/dmGsfHvAp85erxqS/xs1bwlgkOcUNz9VxavzsJ6RvKmczE3Qfa3x8N7dfP19fV
+5zBafd0+t4Gv1r9dSf3T6+afWJ0nyP0YagjzqAokAsvA5HMvICycScGRH5DZSUA+
+4yHCgQfxOdfUK0SiI3A5uCNvta9mxHytvJydnbe2vh3ekY7Rp0aKfJeTkcPDZ8Nm
+PB3NTaen67W1s5nLDjLOzJpdra8zzbuJp5Pt6W7cnZU5vM2/Y6dMPz9e5Tcsdwed
+g3dJ1jb2DdpxJIz0Z0kNPqBsn92/s4FF+N/glGnYgij0wPhQuH0EH5P7jwhh/JyC
+zw+Z3IMdOXTp3K3ZOHCvyezHJs5atrTSjQcMZLMtxWHd4dXKNgxw4aZq3nzb+1vu
+cjpvN/b6mqqpFQxWMPRn6H4LFK8ID7PD0s4SMs9KL0KMPT9CxUqLPxoSUfQf0KPy
+Lhh9D1vz6H9jW/B0emjPs4eCR1R8HP7MbkZSDnGyW2fQzpoFHCz0g/k0/c8XzYzM
+Xg5v2dmmnecnavJvG6+L5VVNPmrir5NP/86vZ5HJ8Nnbq3mj04tjyV4Y9nm2eh0f
+qafNu7Pns6K05Gnm+zfa1ps3fD43tuO76Gt3pHDu2Z4fN0c3eclcM5W46KqvgrfL
+ZZ8Ozk5zj2t+GJ1OZux01LfBLof2MVLIb+iTTw/Qko8MWFEI2oiP1WGGjYyKLrbb
+fh6PuDD7yk3srttD0dPqECggsURwgcKHFYVt9Z+a1C4nm6Upa9L3uLtW7mx0YcK4
+Kx0dfZa/Ltw8n9hXZ89reu1qDcLLcHUQNwHtoWoGtuURwwrIGERCPzCr0EbZJDNy
+QYwp37N0hT9ZQ2foLh0PmQ4bKfLwekfRti0fBA/YfU4d3PrbbDZ6xtdCy8gjwLiJ
+ERJhI2+1B1WIF0FdF1DCwjKkl0UI4z0M6fVMf6venWbllsbtgcPvILqxNlq6efK2
+Sq6vRw6K51ebu01V9Z5ui4IUOJjUBhQUeqIhoDPBJAf0TLYPoToLip4WdGkzxt/Z
+762yzA4Qhhh4oHIv3KIDT5KmZlTKwtaWOeREM8623/B6elo8Q1JxiWAgQncQECgM
+LAiWAQRUxWNHd3dxdjkaybr2VslNjq7NlVT2j4cJ2ejho/Rk05YtfCzu1xat+Hdu
+91cvNxDspIbRFIVURFCyHQYewlUKLjAgdUHOqqFXQdDAGooOZKIyENwSUKq4sEFR
+yNRMUadp0PLpEZlE3GfqYaDKGQcHDf7nD8kmHDRh4fwWWYffjxw24caYWfk0mkeN
+D4SFGhHiVFbu2EkgtHFezxIqaWnaEdzJFsqSNEFKpZXphid250aNmnZo7ZMVlx7m
+zFVXDo03KvK3TTdqZZZ0j34LqeGyvh6K8ns4bdrequzHYrNt5jMmO7tq3Hk9GTU6
+GMOGnzTTgbO08zq5PJjdy74zObhx6M8nJu5Vc+Lbm9uVj1ezk3q17t3D0exwYMKB
+pTOURDWRGaXREECYuJhxzxhETUu8mXv9Vjp48d1lC0/f0WGgxkH1HjiPyUUeFBGO
+am8bm7o07t3Vu5lah4OzS3020qqBK4ICgQPb8h8fj69n+3hleET5+1Kk1maNSlav
+R9c8+++/Pnenwej1erxtb6HV2SCSSdrJHVYHikZUg1ZVkDtUEypDVQZTN8kDSwll
+keMwS78akNOMiJQQc3dihLlKj+oCG7aEM7oG4kZW1NVLsxIVjJxmQMVBiUTaWsgY
+DYxiQYyPuBXhdUKWrZb79D15ra7uMfLW1eW8dXOaiNhdxQslkuUzMFKgagC1Ehom
+iOOZC4AyO5qNxXMVogEhIpqSNRe4grNtR7emHctEhpNtsXLSm9xOTBmOSDYeNILY
+2DG2ibk3hUFnKtvTMXYBFsiI1xxoHjiBJg0ZhC2Vig602I1PKTNWvbUbYm/JAG0U
+aUsNNFafJHs1SpG5rY8UsGwe7VRhp+PJFmpjr15ahtvTFpqhuKWCg24WKj7kpybZ
+c6V5CsG96jMayx1GWUOgDVCIZKqhixI3lLuejpuwX0E8/UR6+vsvzdYqEqnmqYPr
+ynyiMGXW2W+XV42wNasYmujHR/B20ne7B8uftj52a23ykGf0r2Fya3xEEDcibiTQ
+0lZLgyC2ePfZkNiK8bqa+t/uN5kVHlxN3dckC7FJia9ve/Uugg2wm6UBkqXOGuys
+qBJmITKhYQIImk5o5EECZQKpHrRxXGOTi2LXQmqWh6LhdyTi01SqSQ3VOEDXmHyx
+eGS7oe6mzQZ5CDD00rOtqeKJjKBw+ee+cWoiUVDVLJ/FhK0iGh1VeKiES0TeYm9Y
+aEWwQmDQoQiRwvF1pOMzCkqwS5CmptDqzik403jShJgqi2UaBbWZmCIlgrKzuoHE
+I80UvVUMTR9bJIWy6iiIAxXukg2P4TDx8uds7uzmTTj2cu9+82j892bLO1fYjuV1
+nOX+0ET1+9s/q59/SSQJI/0pffnnpk32yWNNLZIyLEInER1S3+6lv+L1te04VnqI
+JI1eRIDos0ygqI/u84V/ySnvUfr5/o6avXhuP26/+dG413/yfDY/hOza/3m6353D
+FQf4gPLyckmNf0/Z+79v75+CaSQkY8In6aqSH03WX6Z0X9VQB/vFWq6C5csRuvBZ
+nX9ytV12MkIm7FR+DLJ9H6IBOuiLogQGQ/eRgyJJAx+aYLFFoFE+nXZEmdeEk51K
+K8zR4ejlk1Rjyd9OlGOU1IHRC4Twt1lj8fuDSl+toyn7KlPBdN9GfhbdlfyOpi2j
+7n1z3jf4hxzT5xvpenii/OQ9atPRJOV8YpWSsyBkCMSKpoqNVJ4qi6kbGS0oTp5U
+Ze+1/H5LYmU6Uu362dTHpJsyInEO5DvTRhC0noXDbUrY0aAqh/N252CZJLYxRLww
+eDIgJvhTpSsrEJ4SVDvd9S6BwlgfShNMd9KmGrWk3I52ZEqkIKJiiDZgpwVrTuGm
+0Uo/ZLXM3bFdFTPSQCOxHSpDGrWnDhd5Y05Lm5qtLILG02ERoixRXRkaboZjM9Fm
+XShtFC7OcoJwLVrbJ2vpmlco5wxxJm17X2pWtUowXbS88ViaVfl1mbDdKMZhHFFV
+CHEiCc2ed3C08Xm0T2nd6Uv1K0yITQlBsslUGWxQP4OXJVEfYPWUXA+kdcuh/+HP
+wWUH7diyuFPB1lyF6ZrDIprJE4SEZ7msK+k6P1h5hh3qskj4roZNzZTZjCbg2ePa
+UWtQoyUuGzm+j26e5Sjd6d8bPnh8J/3oPU17aMyljAcLyiBhr8j7ZOg/Q3IF/0Ta
+f6XwNY0RdbAzegLT47336Ne7qtUughSk2m77D7Kk/viknCAADCufnfnmfRa+PuZ8
+GbDsi+jRFrzw3ixPHSw07DIXufXiw4eHq9LyQfWZnFx+S0TQXRM1QT6QbNSZJj8m
+7UMbjp4V/ZPnp3lbJ4dvxkSfH+zJaG1+r41D+t7jCD0giVFEsaiSGe8yzuQcIPsg
+7JTIOFnT68Mlm/XtHO4/DVboellFEFwpf9tkkmQRHs6yXoRCkuKPxU4Z4SueGdIi
+CB3cE9RKuhrCdlwcyTChsiIXrJwrTvs9M61zkDIsOaTPnYckuRlvrVGxZx0zpzzt
+8L7s4WtdLbRACW2FaHvN2uU7i5n0qt00Kgy9iK7Jba3/3pNiLNMrM1XhIIBPZHET
+RypdGC5pZhk1rtje4i3zM6TWPeYQEE2ICad2RgNnBwoZOXY1T9NwigxKQAH9P9Hz
+7gx+I7Cg/gWYSkB3Ml8YRVoO+7qZcd04606nOv7+wkB9/5D9dwJKJD9w/pOUxtmf
+p+39YZxm/5BaSsnQxtYbRsXraiFwqdRNWIdK5L46DjXUSMMKSKJGX16puhl1MLFs
+NjnoaUBMXnCJ+Kus2EV8F1F0KGG54HeshTQt8laFCKcUvV0VSQaPOy1KydMvj2Ez
+AewDB4P7DzDchscafa/a6vq62dZRm3G2jIrBxhr3MevBrYhskfQQhIEa0BTQhzBU
+xFWQUuAIPIiFQc+2IfQGI/BwLEPA90bT/w9O6Hlgj+ABZZYIk4UKMgIv5BFETg9o
+QqCd/YV/CKsIEgWiK+Iqgr+QaKBHSWPIIpYAYOlqJTAzWgXcJAWQkSQfBkVzkTkt
+EBuCK4412dduYOlRLbTkd6BOG9mJ3lkOMIivftOjRKpUQ1n8N8AXRv85sESi9I3B
+wqNAL+SbEH87kA4Q0iLxfAXQzIiiJA+Dio0PfHBFET4KwoGEuhuF0X0+Od6iPDZB
+vqe2ZbNmwwwQNnblG4ZREfEADnQldENc+vyD2hPFPDVaTmO6ErcB2CSrJHawjBeT
+Lu1HHXecOXpfFifajXzf803to/li3IQraCMnXE7aNaF+UhNCJJ6bST1yCMSEkvrk
+EZsiJnq9YnIRyfoE3qs1+5g4qCjgAB/d3LXII3r+NecgG/A/EBhNc2cEhOijxJO0
+FJewHGBzK1YnNiLkAPBkUztU2GMpL0j31B6VEaAuiEtObw0ViA2Qo2CQrPgdgapv
+FCGKU5zwAX48rSmSGfCh0sBAp5Vw+mHYBmgyfBvQ2gE9Qiw2eCK950Urem/KrOD7
+tAApA2iLxtGRmFUGVZgNFMIQi7APICVtlUdVP5fqGLX9TEJBSYcWuJiEgyD+whr8
+Qt4j0BCvhFy3AUJAHpE2ATCfY/XP0YM68EHwJaHTWChL8gPdCT9IoJW04ShPtj4h
+rXUO1N+9eNBzh958PwJ3onum3eftLwTIIDagDw+o2Baej5qT77qlol7lfPlQODAr
+7Qiue8ErGKQIVtOQ+yuebQ9jz0QHR0XSF1f1oB0wm+nhBsV5Dgxx5TjC7ifRJgWQ
+JQKDKZ5QcF8aA+2FRB9siyFbQEtXEFsiyD1KeYp4vn1kdk65sBN3fx5t3nO/Y59A
+R189AT77u6pOAXgcINOFPg0rAnT4ODvDpDvB+Q6AjhNjrJ2a9VBRzOAGZ6eDgd4b
+NoM0UeBxPD5FreuGt6Dwo9RFdb8nAiAa2R1p49xif5Sm4cGGg5x+6ZreF2MUxiIK
++gryR/PfnDI6Q9Gn57KlMJ5766E3pkiWtHqD0EedIKlAC3QaBfbl/j82SCLdu7yW
+v6Hmk/T9Y/qXglgiQ/aIREU3sfkhFsOhToBSbFaUQBrYeBo78wWrCIiT9D1wcVo4
+GjuBz3joxqZU7bQDFwmjB5e74MBLoK0PA4QkclbwijNF7qEEoFkFRROi0IZfN0sI
+zwihRtDz4T7ibJnxZdmKq4qOeIUAbh8KmERXb9nKQ+5QdzgDPcJjvxw6bZ3TBIWY
+SSeN4U3EZkhKxct8oIiTDi7lqOt3Kvi/tFCQEsImhN98ZBnWjLEBK6dw+FxgB1I+
+dDUAkMR8mm+NWReOPvBhDZjk4boMpjxoBGF5Lqkt7tL3kyTUNCK+PoZx3oUqB7h4
+5wEXO/lduTg4NfIqAh8ZfJSAcG/jGkuHA8qr7Ro13OwIJLia9u+yBZ0dicUAxwCA
+kEDreMjHsNGLghIQjFyrYc98oQaGSKediKrHfuebY7DkhSaKvv+X/oH7Ij+oKSLw
+2kgfoPv0+vpfWeMjRqQk6L7QtAATi0oNZJzgYxP1w4HgU8+oYPhFESAjAyvt302e
+CDaAWgGAh7Xub6oUY6dMeNnQh4yl+Nm1AA19panR4CYHnOGiidVdfdsdGvhv6Zx0
+jjJBqQawcqukBR4Ux34pXobqCIL3lHdgOad5nLqYjUZgE4QvtAltbhvPRFES+goc
+QfyAkiF/e4WiKYNUIFjKWJZA5fwJczRRibFGT6zCHofhgW8eydxvZ1UFHu97Toow
+8FguNJpiKoCc0GQAn4ceHt3K0i1feYVcihrJaNBCZJgh3FO6ENqkEW9eLD7vi6wf
+fT7OU2J7Zn4VPfXdnohaADg6HCzQSKlLKttUpsb9HGGYyM1kdbG3LRyKBaAlAEQi
+6K3SwEpXNuY3BAQX+wSMOhQK6JuJ9BbiQxBRmAuim0FUeeYULAUKioFQBh8aR3Mo
+71V1gxByA7oX2gGDQe8klFNQQNSjx5kWPD8XwbJrOHhrmPG1eVz2hyCeCzw70QRm
+PBaXfmHpq4d6Cj30CwL4FmzRhVE1Z3PXGd4oUT3RT2fXIk3Tn6hAxuw6R4ZKzAfB
+E2O4JIhAk0YDAlY3e4AHkEgAr74ycQwAnQW7rtlcpF6JZA7VNu66JrCcgjUCEFCE
+RpghIiGj2TWA7EMd0aiCjpcIQOLL43hkAKrIRD57bdINOGQ01LwiQc32iwDYCMaA
+kHwImA5vu3GtiupPVup02YPe4G+iICJJzomO2gryY5W3M5zx7DfU8YCDsEXiG6zV
++xuOJIG8KOYoQjJHHsGD13J0uAvNmGVfCbv+KJrzyu7cZk07DszWZjii34Z5Oq4J
+YoGxovONSVdyqdDaiI5o1E9gZEO+MOknbKrd3vCGjWOSCrnI7Ux2qgrF1ozkJ12i
+qiB+Qq2iQl6eKyIKevnnG4vy6vIfKJt1EpCX9n+P6PQpAeBRKJQ1sOYCWlkXAgV6
+zM7YJl8sa21D2vb7geeO2SpmkzN+KTwlzt0iohA2AcDPLw1FWDBUJvFW9ggVk6Dx
+nW8ShTWwRlT1sHHJyMsXFDhNL6q7kI6WJJzpELbUQNVIhmsRVy0ajWqqiK9NrXLa
+rEhagikVJEOvbHSFh2axoim1j1bJkioWVpJnTIwotJdInhXvflf6SU/PPQX0bTPh
+CdsP29ywEL0SWUfTCD7EJL6ETkKMZq+XfvOV9/V1w3yP6vw8Bs00Num+z8M7mbcc
+Nyaf49zDIxUaQ2EvqlaeEBsxpWMXnJV3xw2Tk85CvjXKxcvj69eMUfMr8bW8bRbU
+onKyW5YZYTLbI2sO+23t750Nk8klcxbgYLeIcQe/QCQJFkWj+oMfqaThzaIrMI2P
+7OfFp/TvReP9gGjSGXxEeEVFAmDkEvv9VUZSkBPbMF8w/60D9GpeH1QCFw55QkLu
+z9IAXDqKnNMEC9ziBCmelf4wfDqr8bOBhgIc0RJII4qPuV5Nz9AAJ6ARU+oPi6hT
++q8gwvYgoidW+M0fbI8rtLFtXO8iTUFlJvXeyFxmJtnkC7zuiaT8nGztzQSqBLOU
+ovW3gp+vzfBxm7PhlVblQM2bd+/Rh4dPRBvEDSXngueiAwyDAY7g52aB58+eG+XC
+rEW8lGS1QUeWOAT3cakjvwRHNevLrWRGxOBmTNeUHz5BNT4o+AkxZAgM8CgQuYt7
+U5ikqOco13h+zN5A3dAfUbWApJdeQtkMkEkG1iAUlofiG95daxu0Xul4UwF56lZ8
+3m8LyQBioWOMnxAZw8H19FHnTZSfCQ8UKukI6IKbgi2EROEVBFDkVQRmNCWiK5gK
+gjqIqofRAygkWCEQQOEBE3AUBUywFE+iCoPxHKo4qQYSR0uWSDgsC3LBC2FUgIbA
+gEIgr0IFBFEV2beEGgOV2VCEkasTeUI35YWoqjQQJBJsaVFsgnIIYIegAZiYinAC
+KCHIB8L9aSU2jqpgHDRm0jioEdaHayC8iYiN6RSgqyRLYbpYJZUhzsQdYEVBA3EU
+HoIwQQ3BFaiKBRPagNKp4YAbiYCICDIIOliTxeOOGnL2EcaOMNDMGJjKNGgchDj/
+BKwYSZqRlgLQR7nzcAWpLACURHNK7oqAsUjajiiYMTUESEVX6ICF+TFgwSIL3tKF
++9aliQFdBBB/IK0AryCL37njuaj74l8yZNHN1lSjgfcTgmPsJRZVGcrSr8IEjldQ
+KtmKapHX0QlsIki0IuSRcABgN0Gs+4HbDqPIFBxJiVh3OSukGiQvd5nogLDQRteh
+2MyW2SI9oRhikH4T0jXdxNxJF2Xnskl3AVffHjA67x2y8y73Yo5mAE1DhsMmXJEc
+XQigaZcogCwOAJSmvkK59/AZt5r6CHoKYtZF6XRWBxO/0HFiG/lmwBS0IXvAvwXw
+uNK56cJCuiEUIhAnVsVC0oQ/LDomFtpZXfIu324pRnto5FdNUA7OBqemCvdxU76w
+rnterFGPG+6Q45tXnD6WRacT+nbNIk1JCPpi9vz6KPo0aWTYVCFR78pPNQgpwlQo
+7nZl96ldo0qhd6oAriD7PYX3YjYi6+KtyURx0Dh5o389ggNbU0B+KOiBJNO/YO34
+6a7wfKK5PBjVqgozX5yrvYe4b+g/eQESyAJYADkx6QeCQZ6hHDToVxoz61c19ymI
+QUB4ySSEGSTHhMs0Tr7Of7v5ZHrYzWRqmxy/D2PVnfrHr7nmk6vMiLt6Pfbbft76
+NqFfrnncwD0EdL8qWqmCRcAGdrsAgwQV6XyemW3csQRzF17hRM8sNaA5u41TovvJ
+lL6Jmj0Qdj3rXVUPYlIJEIbMcN6Qo+y6+Gy6V0pk2Gw6o2eXyfFnBOzAXCDYADzR
+CSnRaQYZ+hwQZ0h7sXXIQK0DQwbFchiJ7Akq/buuqEJT+FvwSPhCs1JX34emWkc1
++0JlH7mgV6fdrze3n1BaU/HP0Ip6Az60FlmH0F+FDieRNSpsh3JnZieg899kMapx
+A2AgedvbfYhjt7fwdfgTf5O/lUCeRAZEpJHwvsvi+d3wMBEna+Z6+GGGgCoek/BW
+dQo/JYryYiLihedIULrmV2fAYIU15yOAfqwHuI8EwYI7aM8kO0X6aYygiiUvGaA5
+AqKrb3bLK3Bu/ws6awNQMldRV/OihvSGeGuLuQ5zhdKQyvBbunGHiqbSVBLCBBR3
+sJmkCunDAXHHd4eQxhEGRYdBzZu7UXXMiBb3M0jRVaMN1xw04qyJ8G6DCyAXnHwZ
+RDcJFX32jyXoosS3eitAOfuZFfqdLyQBCCB3aIfY2OMhjfbVA5gUvI4NI0ulOm0b
+1FDfrFHR10hZU+ODKMCViSStxuklLxyrOzBrvpkTD7nncH/YWN/xZ/cWB4MEWMjo
+uNq+pDjINyCJIMft7GzDNPmQMmfKO8C3BCupq3ah8aC+3PLydaANlYxbybhnNhxC
+RTyS5wfe8lJ5C60b3pGVdQBEF12XTIjMtk1B3sJLjW843JTV6tmmB3szzW8PCNWR
+3yd28o27CnITe6LTd1rriEPv+r+W/Lr2jtO7uzN3c4O+Tfc02jcUkrJR8QctADA0
+gXSiA676RwOkRHURdCHLXIqelq5LOSTVlo0mrcKsbgjhEjApzpaorkBLDgWikaMD
+WBmkEQLF3ZzJGd55Vbo6iJbSXTzOm0HEagBiaN6SrGSjgMe8kJ1BRvIDKb2rTVuv
+UjayCQnFgki2WkEJGRQCMRewEqK/x1GDBcgGSKNrCGtI59lyNKkdOrQ0UCJT/tYC
+QsXuKTErgmB/L7qWQAgjObGxtYRpoNAhObSe0Yb86I/8koc5eNsi+mHWzWtVmg20
++QHoAlFmGJHkyHlQ13uGhptHj5jDJQi8LDIbkOBvKk72hX8sJ7ueW16GHGq4y9iI
+j3yMYtSIbDhrWwlmqZXVJRCqouUAUhKKoGCwqjpq43WTfM2qub+jk2T4GKHeyOVj
+tYdlk++2vs+/+x5NvlJOLPYmGRLWSHhDrPt8vLxjo69Xl+W2ESbJz6o+epO91qFW
+HfEcnfU/36UAcqgbZ7xi7DdKjmP6OdAd8+vBt/QtBnxhQ5Y55yjps21VoCjTyYLL
+1CSAQTQgB7K2FHCvBzdvNMXNbRQpcZKHabwUfuGc374PhwMYpCQXoDnJZi+6wEgi
+AiX71dMRdTfvYRIwt14Tk5HPrJ9sRIYwCUOkZlDd4TvtfPdgHxB1w21pzT08CJyh
+7Xc8oYd9ZaSpdBvqDRYUDhA4KO7b0HDw6Hwa7XttFLJvwUIDpRXAcDIRWHS+aUSz
+xocp5qowJUFyIVcKHx7WHevE5XHZxO+4peTzkklyu0YuiXbLEIJQUcsg9pabkI/h
+od3gISwZ4fwv1Xzc/OeFHgwtN7OIIX02fD0/FYKloiIWHTB7PYJwBsz1ERDlrZJE
+YDEhYassKO0HhjnoW2l4pHuKoFBPAi0IHcnEsMNIUlBMw4wqCkAz69wRdbCpCqYV
+IiZOnuCR9k4a5ZjWNKYUSxiFzpNQQUVwU0iIm9GbESmCr3RFQr1Uigjc4jisu4pJ
+puPoO5yOeZt1LgztDDSQtUkU+DXS9idDpAhOhoTBeU7AAikkj6CLUxCIImIIc+BM
+GVzqBtTlqMISI1Sc4AgyKiD4gcWAivyJqEowpHETkhIOIUiJAsq4g6inSDsxKRWg
+Yt+3owIGgQI7FgKRip6JhDOMYUVRT0TqgKJELhtSrt5BLVIqtKhEQLggZJ4QhiQR
+Gq0Cqrhtk6wQnTdrZdiQdLJbBMJNwoI5yOuHOpAbHCioJ0J6YhibSGY1HllCJmB4
+jcrMaFD0ewXkW4ejjFIZTGKo4JHcpSBBPtd0Qxs1vmR1w4jyA/Q8IHSlHwHq+Ee/
+WKYiGSG4HC6NiRUCLF32CGopcnwE7g8WC7D27ysTrEzHoRC9BQyGYAhkqhOQBwpF
+wUlY3keYQrRXorRFPA+GhTj5pDpAE7BLgAlbrkDpk7XdBkMCe7aC56ythMcLyB5M
+qB1IiizVK6jgSzmXFAgGIgqwIgA6EtEewNxEDMEKsvoUzTnlKA5iDnmtY0XrFdi7
+oO1avSIz4+XbDYhpYNbXls12lualldWW6Rmvp3XiSn4tr7H2DBIdge2UHx5TmHNI
+B0iD6NlFC9gO0A7Si+DLWvYUsE7DYKO6BRETeHLcg6SAFuaZ2hO+UAetihqZiOFA
+GI9nCa1gvgaJXoNNThLNEDOVQpTOKJxUxb7ouRUN5KMOSuV3bdQuokVEdMKFDQPm
+AmkMhmx1/f2bHBC8ijYJk50C6E0XqgwMJ6K9wOKaAATyGEoaSjjPogj2CyAOQRZk
+JxFQViYRM0i+Ei8gAZiihW1WUkg7JgoKGBijbIMenRopoooFjRhdB5EbkD0B3K05
+69Q6zqcbkOM1FpwnoGyJMqYsuqUojv8cZ1sKM4tO5+rCm9ZZJCE6fbttA7APREM1
+9CSIPRp816UCN9JJBPsHGQVvYZdivqFy+EDnwVAwp4cGED2KJDVUXA7yrAlwDiMK
+5xTOPCYrIplcSlucCUpqSpZoxggu32wzjnF2FlIidoAllPOFbJzD2SICWniGwEiA
+3QNDcV1ngXIKepNW41sRWLhvPSg1vwFIhjFd0VnVLBR9WMhksUIIoiX6b6aI6gwm
+eWGTazqFhRbYz6BwdaC+k9L6lESGVK0KgKYufORB0fYYzTnBemj4BH2gEaHaaIrv
+fxwDWvTnqdY6WgKUpgSoZrcEXkiQwPFhy9jFIQUORTJpUAFrhENwKQV1OLa5FQdh
+FEEkFVhFQCQVCRUlRhtibMFYg7DmjWQ0vBThVntDVh0KBEg8z0VFZ1dnlwvOxCyV
+yFg6KORRzKtb9eVaU6PsPpQ6vqCxMQymmlu1MoOofNGJrbSJqCnCG0ZkU3SmgEqj
+ljqxILxoC0NXXqMYPKZsTNGgseiQX1Um+tDnWCzEFM5KYaQwiK2hebBFtFvWbIKl
+A0gySQIKEVUFY1qkKQisEBDEYcpVOMqLjVHCwFV4coAKcGYVaniPIi0IDFCEO6py
+iK3Sb5QtwUTkeVRqSZvgtiPRiC9YmOGphARNmQ6kLF5Mm9RN5UknKirNlCkLBMDw
+LZGwouEWmYel0VvPJk0f9vqDgB1OMRmKZKIzWahOGd6NWRFAnCIXEL6B0Uc2fl5P
+sIeQC1FobsyuXXTiCpCs4yTW8WkdGVi02BNTSDmtnKPWeq9Y4twF4gEpDgiKRGKA
+rATvQoMREzE7FMRAK9ixd+aTuQoIDMYQZSoQTcKEAaDgwLsSRHUTmeBlwAjqJW12
+haMGnPdB7Rko8t7UYLQRAzDoHldEqn4zfIlR+ahTFDj40bkEs7N9ubb1r5Pkz4P7
+KmacMbzsQ60kjr28eWZT5fOlM3PVqKOMRxDR3mUfp54ZLqzcSJorg+9hoxMGzVzk
+E32DW2JtbU2qrPLpN5Xpxamjzu8wb1lW8jakUx6dIsLnCxQwpEzLzYbSCTWTEZrw
+p0sG2G5EvMnZyhFFF5tTkG1AZohFJveaYcvskKd5SozIJ5nClUEHKNtLZSLNdA29
+uDYo7sXxjC44bazLkkiHu8qrYzJnnJ2oQ08SqTZVlzXJN05fOLkVt9y4SAdhsUds
+ETItUioA4xSCJRd2ihTicgxYcOnBhN2OXCLbNOTBhkqTgh2g0U4XAdMYmaJDRnHR
+R4Lu3sBvFYojVUFkFCHnDpF0yh0wkgezuLUwW6maOnVNAne9DRbH+AAHETar2+Ft
+41Wuaum2jm5bd3WKQkCQUMg9FB/ynAQTMVeIB8oh6CKP0EAQxoFOUgEEvm7+N6n5
+WSrmuWdsdiR+nu8pv3szvUcbeXbM8Y2rYHrC4l+zyLjDfmIMYVsENPkK9m6v+lyT
+5D1f3aEZuONmS117lX6NWkjPZo21sYFwu55fns3WZHrU9bIXYmXLdyesJJhtZsyP
+8XuYeY2qPLzk8i2eMXprLlTUee8pZwCQX5F0LaW8MCu2YWI+FoVCAHBD2BOl9jQc
+oGoiISmkexUTRuFCkqlW4ITOGyomsKYHBjZrY5wncn7k8ejM3ET0XYlJU8VglCrh
+D1mEVbUgnLS6ENcMUAAwOwooznxlE7lPuAKOBPjKFlnYC6ADqLSrEfFWgZgi07lQ
+JqzHsmsUg1ZBbG7lW9a5qOWxHURNRDgomOIhVc+e4RuBqAVWjExp9ZXgMJ2l+KEV
+vOwwHQfplT6irimoKktr1mTvMn1AI6Nj8IOjnF6dHXSm3bQx3SNAEqFigcKwa6F/
+BubLQ9vcq85KsS6AydGpaE6qtgkARpz1BKuNSoGBOgBQ5A1kBa73YHOdtULNUiHq
+pDygDESZngsBXWfdQdUGGBnhtbsFzJEXO68eFC4N2M3gCnwhLjo2sgkKuQ/2GLWH
+g0I67776B8O/3enHovnD5QgD5SX19KJhml4fQjZ7+0Q5JZrA6YidgWYyY4jl8xSV
+sK0myHtg0AKidGTG7nAv1K6y5UVikEpJJeVcrzdb0hpFKVRzLlSn17KMaMkjCTLM
+QQ0FPTr0SQkXhEVoyWhvoQ9yPsIB3yDPeHXPwPw9rkIoDOGz49jxbEtALl682Rhs
+0JwxZeyKgGTMoB+YAhZz8Qa9iOMdcWRB55QGYQwryLwiXDkQLgYR9ATDOHVU8lId
+eOvOCO8PhtQKPJPaSS5gH9u2h8QPjqFhzWX1iUDkBGGRdQFORGvidcljOQQDzVBl
+TGG2UR07istKQkPDezFCw0PURkJVk1fFtUDEY3CtDUhqIFYmbk+TNC9bRLgC1B2Q
+hmoGNNdEXHTlVNGEVIJL1zKJJcvOiDo0nuITwMO7aogoMQulp1Uzxq+a5SU07uZm
+vE1CJnZZ70OyN16aWcbe7CfhB0W5dv9C6SR3sHAFMHzkGZVhljT9BtpAZFGb0IBh
+iANn4yVtUWWNjZlODZOyQgvvs4J4XQtR3HQo1zIKaCGoA3MHDeDBQRyGSIusq+Iu
+UOnPeNgBZsMVdUK/MA7M74eXN+cCMybrgKkJpI2AViGsH9t9NE2mTXEAH2u1lnrn
+3EhxUTGqz2uqtiqAhUVEQ7IFAI05ncwTfKHWxRzwOqtWiKznM7zWPbVzw4j5iIaD
+SHW84UBRM2Z3vmt3R7bnF9KAsRXK5MOIWdxy1IhO4yIpyYRjiTl6klPndDcCERED
+fIAlT9GeQO/FHYQ4IvbAcQGRxYyPYeZewWBoEX3dzOxpl0F2A6Xk4RptVObwVYvR
+JgUdJSoUBw0WAB93YAWGu4uiaiu2D0oQ6CQqYz2svjWxM5GLngT4hPu9PIny6IsR
+ZwrtKctQEYHDXdoRqg5oQ2uSsX4bCJ3NGGNxFpY9K9jfyTMPt60P9tHlUE941bvY
+0CWQSCsNUdyq41StOyY05v6ryYNfhWLruNAJjmG6yfUmfUshkQw5BAYqlskE4XZZ
+0rCcTJIRvQcxBsbodFNqdCpMhmSYhrWBxkg7XIf371jehCbUwexm4dGgVDsU5gmy
+ARYrMvjRHnRAjrEi0GYc5Y6OiwRdCNAUhDcJxjcBNIBhrUp2G6ndXbO7n1V1kivl
+8XxGjFDj0HsLjFztVYhL2gQARiRjzTgeTHDnuVV3Z6EWdEVx3o6ECjQ5rCJk6KO7
+JyyngW7FaBI8Q0m90Hkz6/HSOXw7wPcGEkM3MXsytQGxEqIOeR5s569+9oW4M1qt
+CS6KKEewSrVVQ9Z2x1nmgZsV5A2G0sh3RXUp64xy5NrrMXvw/jH9rrG9Vbajixah
+aXPO4PyEx5aentlmgg3UzPNcyQmn8jm7WpaxrIJeGcWmiyb2JVHMgUcgNYWQZ8qR
+l9nHMTRw3MikGYWca2t3QhhaYddzCOLk1SxmG3vec1U7jhzaLKrbNpl7cveuJ4GT
+VKmHNOGIKDJJCa1hZpVTd9ddzdqXynyK3LQF/1fvHvFwDEEAgG7s21nIU4+UAFqO
+BOzZXxvafGAJlsTLa0vUiRYNbsqb6jMCVwky24SylLvbtzhy4U047dzRIGiqxGqI
+kIjQID2qNEqudsyoALL7RxclL04W5tQJ5QDpK7RHXccMSIKzBREj6ROmSpdaVrt4
+adqfw1EQX0QzEHsCa660tktLxhOLIkn2OyUnq6l1++dxH9/n3L2c8+25+V4ffTlL
+WbIZ6mIoWFkymTGcEwjhh9wUdmPPecx/I04eIAX8Pfv3s8Jw7Rz+F57P356BfL1E
+2R485lDJBs/Jx45HbNb+1znkLrlQVg2n3Z3ePSJuR7bhMxd8mt5Ml7Cna2v47Av2
+ShobDchLus/dr8YRijOCfI/aoS1CEk62/SwaX0d+zqSS4TLcKBNHf3WDoO6NgvqD
+AcAR82hL32rdu4FRZaPc4BSzInYiK90PsiBLMdwBZzGeZDD4g5u3gUBylQUbarAR
+BUBIVnQqbgplEWh9veEZod7p4BlUkk5VEijGEoh0dAiX2FHNFOZcC5CaW4XLEDTI
+SgogmLJAKIqAY78+xmDgxem8eRwYA+e+7Gs7BLa59uFG8ZoVeVgy9USRkUkhykQ2
+gdhQBuNLAzEGQWz6uWiSqgkgPFhL1X2+0eYLcIcj3iZyxIJ5vmkDHss1UAY9Kwmu
+cUvi7vEKuyu0GwhCTA/yoyJyKgfHT7x1mgrpxkN4KkOQXU5C2Mg4GpNJatXYSKiD
+qMyBxJCb3pESGxB3ecBzpYGNW/OquelOkMMQhLMNvp2CszyQXClDLJFNasPABkrG
+Mqh3NC4P2iBrGm2BOkclnvhVhaRISz3tcWC4e3pxcma792AaxCl7oESlxfjoIKJ7
+a2FiDuAweHtnbwXS5c7GQzEPRFNwEFkCQFcwLhdUKEAz2x8RGVU4dMOHfKVIFIhm
+2iWtGuVMhENpjLWFciSZlotHBr+3aNL0JXa8XgqPAEd6EVpKnkMUG11O6XJWr5Yd
+e1Z9xlu5eR7mJ0wHvDupi0w9qHg0QgciAVh2IX6IXeOlrntOQTFZdBawzrREld3j
+PlFqXVGJkUYTNlohLiPDOszjjML0boQtWicWm1LQfEJgpwVZEwVAf1rpwKDiWeW2
+T44FofGx9X7FflnTv57B7RWfe+Ko/xh7BrfbW16MdhYNV5PvlOkBqBZnJhkCwWXb
+ALoENInGVVyEpJHrMH1FM5yhFxZi6xvmHQaSOdy8vvLlDQ0cip0Q10A0glmjphjg
+AtXhh5sC2DuE7wOi1ogHvNgoaKThOzB1lxriiGCeshTQvqL89HPQ+io6J1Omxss5
+Zv6kfi67wFWe2dNZFCyzJZwresuVNd9sV2RTnE5N7GjnjtGhDOLCGejhEM4VqEAY
+I4iKBkRFL4BZuzJlfc28UAYvBA0puE6ZecsRdO8V2w3M1t4YGKaBMQ9gzlCEQ22W
+BSqbwKaRdjkQHC4ixmWzxGIaJQxyRAxHr6FlXRHCtOM7Ur2KSG17m5xIKQuaUIjp
+KPU4oul3DGBPUe9XNE5SjJ7usYsvJroDQcDTaLFrKnCLS1aqHqo1vSGEySRhymq1
+0Ub2JdLjui5Cg0OgAyFwRzuTtrLIETnek84awMtCp9ESClI6GC70L6VcHG5I5VRM
+DxkDYaht0wnKaDRTpUruQQOhrJt5eU9zwnDZsQC8XLboLBCToaxiPIoixht299g1
+eAN4RdbBM3PFsKrg6ERTws9wPEE53AHu9HnSjwnUOBSNrBA70oCmilLYPe+DGDgh
+6AG94FT/EZfpoKj3EISVg8QpAngqM8vmA3SBJCvRSw6yhCJNdyVUolCjZPDeXsG9
+6bxkCEDL4kgQb0NHSghSvjbgTCRImOgQX9g5YQnK1JnCHQir06levMFKVYkHy0hY
+Iko0oj33Fl52C2vKsBIXYs0AwtC0BAVsqkEI2A51DCQ4czmzpfPFmm+b8ANnSoK6
+NuBO5JsE9wB54ZFkSd6awB68gOzx6BZkU0W41kPJp0tdlQoNWMl5ouXnVwAAOBQV
+QtmwACYSMN8JJSXDEpDDXCxMzIoc1vtUCyI83wsQowQmOdEQeu+6wUTUVTUZ6V0G
+BjiUxQLwwVYDEAdoXZoZo9PK2kLxhW04FenMCowg8QhwJC6ISvJoZdAMI4RxmXl9
+WGpq1m5QDogASIegEgDIpUXcDP6wOlBb2oB2J7FIYiZ3rGZXNIJf2atRcQbYVDkx
+Cz1D0GsdMvIO8NzFYSwtpbyZ1nGAWozaQYNERCAeNIRK/KCxiAvTnMSeKBcSoITt
+OIamG40xIsICd7QGYq7g5yMZSfYIBjSC8cIthVOmEmzl5cjRRQSFEKnIqSKUG2y0
+d4pDaUQkJ5CMiAKrdvrMLFEIFbQrfWW0hD7GB2FrFcwCpSROwIDjxYYPX3mjKzEA
+oiIESUYpR3ygcvabgvYb5JsUBDar6xA08yYdnJ3dmc8KkH6un9F+sESctLBFkQGm
+Ta0bPig+sM/K4rcNlicUhXGvkeO2yqSZ5oKmK7mzQnIIpTd6txohrPWxC+w7O7Xd
+9LQtO6uqZLhzsHZpRcxYOi1CFignFLhwDuxorIb1rsUMRBHkUkH9+wAqL2aiyPoA
+lLwUclJO0yK/pNNLRBkAgxgRJDowL+MDbn7aFmDs3Zum7TMmpl6eNnnKXjW+cIZL
+KTUDBhEK8ciqkQeV7o9nO+RdjYhyConjMQRTBWmeLu3GkKYbSDZ+NFythpRclB0u
++MM9hIPy379/P5JvRp9K7Hh8rACxIThkR9bC/mjT79r7kMrZfL3DsQq9dPzd80jy
+omUQ0MGQccce3Fj7MWzP6VNxLUm/pBuxmmyioIE45y9suzCqg25nIpkvY49evNI1
+vdkD9EHHY32D6/Wt95wXiY14QGHv6Tupr4QlovqZsUxN/gppAOiLCJKKRQoB3Tq7
+wOD2KVRzt/RlCRyIOQHSOSr3uh4krxkmwT/BsrQ79YvUxmCBsaLPe3BE9rd44cRs
+EtHttA6UiBxgHNHMBs2t3WoqicOUCJ/pdOhWwXx0xzvjx3O0KVN84or1DOx3VbmY
+XBKjiLHHQ6cosigwdb8KKicNL3O90EPY3XkwoBs5FPf48Tw4m8Z4osEyHXmsb2fA
+Ok4HFRdQRcU7OGXaHlQhmiCfcEzj2hQNDNA6MRu4t68O2Z1CjKZpojvIZ6gSyZPH
+rL9rdnsgo9LEDXNXd1XbuepmStaOYiD4/r5zmElX0N6F0Tz3VCoRv4sIsFhYUIgI
+numbH4pN2G+IcL7ABCaNu1mNj6QkUIMAhtoR0MMPiEUwHvdwMF50hG8QYCTnhfkt
+UMX5FQVzDOdATVLQbTBOoetSGcCjNrjgN51GgITFdoNWnL64lJHbNklnJKcjAsED
+6LlEuu3zlPY6SEcibIy1pLUAd0IHMRZuIwhRlzAXsU1wRK4F5NYIkTsbgaGKAOrk
+3mDdrs9oHE5vbz3eO7IwqJxcJxDru7DPr5kZnfTpXLnLVEx7eQEex5Vc10EW/bNS
+/UN3fOWkQhgOwHG8e4Yi8HiGe47HhLNWwnMlMsrBHoa5VyAyXB8ny2xOvMcOHDgH
+b3EqkrzSChHUyZmLI+6hu7wISKUqFFKTFWDllLromzIiucDwBOQQ1kp6KGChwrGN
+IdiidKkg6IolNojcrO0BeJ7r7kxA8TUb1OsJ0DwXlDQCiVkWTKjwgEQoLqhDMXRo
+Qo9pGorE3XPYHlVcm/Fl0ZUNWuXAbPgxVowsObJtykwDZmd3Rs9kF7ovtgP9gQ+4
+ImoCUYDVbTqWeNIfHhQ3fcGSykKPKGvzG0gw0ZETg97odgi+CtWJvpYu2qwoTAIs
+E9R6CGlAcEl9tTTwETIhk6KNV2KAPhQLimtCFryG/Hiw3nYgO3u3TfEJHQuFVBHi
+QGsiLqgzs4bdm1MO8CUwBqvDVp0jQlTrbg64FHW97NcVIgioHQCAjzim4h2byc6c
+ANEWA7Wm3xWoYIRbEHeZqnzzDMAxmjmtCjoyJRko4E6qJSoabUiR5UHY4rwkhjGi
+57nGCJQGyYa6EIE1ZkbQuFKKxvM0KGlAUTD2PCxzTTr3sa2oAwP2Ie5M1JRb4eh8
+NazCTDn7w1nJjXI8EDCKsUADgQVYSIv0oS9b+UA6gPIs1SOiIhCIbAeri0sZgp2q
+Cjt1qVoBinB93WUFd3i+GNTr0BMoqCtDIo66aNKIkZtiCtBFYTxRAkbRGHW4E2Qa
+wGELRMBSlDORfaNHjJo8HetTIRdgB0R/fXAbO2dWJb6DfUEsipYiw5A0GnF8Ezhv
+GlTxeCaEA4SjJdyifLMm9GUIqQiABhBNrSrnBJZwcLnsUPG8AVmRARIaJRIAl2Aq
+vN8GsE1zgnAAG4OQm/dxkQHKoewTW3RsFeU7RIFDvSeKq6tmLIwK8gvYW2oipkRT
+wRjRc2uNOhMZYE5yw8o4PRldld0CRW1Do6zyeWGLAfbpCqPTGDSqcoJXE1eKBT20
+VES/Gir1g0EQCpg7m5ZtoK5GATGOZsXKcwCUdiYw78huOate6CDObwFxCKBgXHBB
+V6vNFaO1koc5AG7nTRtcl9SatzUT+2esG3qOOQchoqjI0MZiYEGiTyVZp67hPaez
+0Y0m6xKBzy6R5ZAO9vJiMqshjhrIky5HVSaeZ5qEyNVLWOJtWG+4jGMGDZuXubu+
+1BVxAySGWyePnaGc7uXgXUFUo7J3BHWdzfN0ndx97DRHhMuD3FIbtcmDu9FIUiHM
+wvJzV1rl7V3DAElvIjuzuAN5aVFegjAg8oRCh3gtOg4EUlSNQ+g+YCsNL0DFoWiB
+8GhSYOOE2b5zZHnFEUAwcmIWCMHBxMSoJhWMWrtE4EJmAmGLhxoTvSHCijrgpjFw
+YaJ00WnSJr+RmC5jFqtEbUiI3kQFaXgg7vKLYF/fBgwaV+EnRk9XQKQPOgkBdnA8
+kKDUtNQ28kWcA2LCiCujWK5nSsg+u2au4siUCIIuFgTFpAqiDAnZW7L63Tx5sg/t
+IR5eMo5HINaaOXDMrHyG8ytg+NvLtlHBkBo9kRnrKYt8/qyVqWjj5VEqVy3GpUqV
+hixKBqJGzkfhHgoFl/X1yrlEscB5vLEAKPAYyGQRirBKEZm6RZfA9cJGIMRHO5ca
+CEW/DnIynaC2XohJQkB3yhFrMFq3qxHJ4+QOtEUb2wG1dJBDDTr2sZrvJ4RcRMbT
+qH2Jdooaxt0NjDiScucKju2YzYaBBzvUkkz7Rs5QxX2gwjkdYD4UtQubOAigAFmX
+wNXZ4di59KNNkgtapzDO5Ze1RNDg3lGlzmLiBgSsl48e7xxrPEEVA8DigDOnCoWC
+NyRTfSavpnxLQ91Rqpqq7DJKoyD2FuCLkgrmASASJuqhEdivR0jzeV9CZNSuy7ox
+U34bo3ZBM43NBAmhDigDK71FQEKZjWNaenQQjAhUwtFmR3diUG9KvqSEILrtcrnK
+JYMYsRyZAMUMhxGC3SmHeUddC8aQDaajNAGHbXfMJnKQ3Io5u809jIeOAiCmGwEc
+SGxFf2Mh3Ck7Q8NmAQs8MQPGwLfoDFgfOCTl3U4o3sLxM3kkQktElpUOIQi8KGes
+JJoQV1lFdBdVKBU8i65cXjg3ziOG1RVyGUA5EA1Bz2PdlZvXiVd3sCFzpi7ZkuuA
+okzCH5e60sadzfeQCtFe9t3jHrFGwPRHJzHlWiIzEmgstR6IY+MDjh98XwynDQJ9
+BcV2odeecqlvFnFC/t9u3NHjnIqGa7bYikVnM+yf5vO/or7fvUJSIr379aG/2n64
+/p2BO0/o9sxrOt3vIpd9x5yvc+etFPveVHuePsUB3DIaidl4CxRx010k46whEN0I
+g9O0ug506JYDlFzQbuZEuMBAWvO6IBV8LQl756E4B76UHCsGLzEOHBSd+XvXk9WI
+YMbfg56ndwHELY0vRDPXRQ99d6bL5OdJIUUzbJDqWMfi11tQANmXKblIsgFamLRx
+GwxzOeJQdSQi75cWKugYgDTZ3sYwfDRyoBTFJzhNZdKia3kOBcotQFEQCbS2nCSC
+TtEiEuncq5ywL4jCuAjum3CYQzZnvAElVp2RRCOSGjCgOCgk5JdEY3YqtbGzSJKS
+UdKYzo16eoPENGLo0phETPJZ6OIkAK9m+kPCOQTXKwGmFeO3Qo9mYJjmt47wpZ4n
+OUCpkBXxs5+EADfPu0KwMIEgyIE6Rn15vJ9n2j32MTvEFNRG+O5FKG2lrAqyh+Tf
+Rzh4eWFJaDwsQTEaSEdaoYgZ1LlWfjUAeC8q2dWnJ0LQ8IrFg6vYcrdprGOfYLx4
+1uAB00NBrexzAOhxEV0hJgfdnNpAR2yetGXXTyUK7POeMFSwUcyK0k54TYZ3BFZc
+82vsHiaF0rspFEpTTqjrGMohOJwo131kTcrGNoxl7VJWqRTYNtAAJC7V+xyyGxzg
+D6IYN9WtIiQNBELyUK0RY7CBDsyDhV4eNdSOX7wMOkXgGQkRysCNmAEPpdYUaOma
+XGtvRVaKBTpnHMGXsHRzNvcHtrkV4qMS3LQYC7AFDRgeIQXw4+CQaigKJZLolFEe
+ynETG9VkDEWb3PCLQWZvtb1uyQ9OCb2ljqdYeYVQUVrlhSmZCCLoCzeq3qihdKlC
+FCVu9GdtanaDaeoee8Gh0XfV746AG0mFR3grOkNaEV4oAxcwugi+5mLavDgNyeab
+aPNUAdaRx6GueEE8UgBraaEPEBA90Hd0IoiYKzzLeyC+QP86S24oNGgPN7VEZLkc
+3KKB9yaO3suM7dsqIyXBAyaPJIVawzuyNy8Uis1TN6MwDW+Sc8Jp63uyww2NEo+W
+pXWbpGdzmc2qkqcY5CJNMqipmJnZ7lPXMBYk5A0CO8LEGgRCLCyFEGqDni6GFwh4
+ISrK96I0lzDiiuVYcpktYea5V0fSBQQ4HLSCYxVJEIpIEG1ivgPWGQ9zRCT5pzks
+lUdNyhMqyFLVbXZ+dbaAL5MolnGQ0f2Y0lbErTW9N9zvnf1PL7QhIQj5Qqg9+9Ze
+cP2k9FIfAnPPeCQEemCDu+PpovnNLGt2xn12fm+7k++eYUe5zI3I85qKYoJjmjnl
+nmGtQxhZ8OrjWLs29chu705lyXsj00pO0r01isVaNX6Hs8cRtAzPRBUpl8Xo2aUU
+RMFSH1bMAjgAzlpfCL5AHePjDzgQW5sEzApAHGDajlxaEJMRENKpBhNAm92ON0Jo
+cKOslyv1CmpWvaQTDp2e7sgwMWOxFETVedrRILOecthi4+kHbXO7UCGYShLGHMPL
+BFyJnklnbddyTMMgm68FBsVzHACN16/QBHAADr0hyZ57ivEsZjdscOB4MukOoq75
+3Sm6oznxvBWSoYDs0mM85hVF3AUJAQhIC+IAnAQ0nYeBojTtDDu9fb2ZgfOvvEtI
+Ir4U3SSAbviqYgJSp4BnTGwbatDG9A3mGF9hEO+hcZwvmsmKw4IUUYSm04b969eJ
+yhd9UFNe3iSa87znSZ8uMCA9unXVOthwgCtrI694ULz3RAeRPJ0dGGH4cQq8+E1k
+N2XKOIV8b7t0k3pInQ2SYhUaCSxLkRMIbumyj4sTVz8/OCjnFqV6iuYCrEQETZhg
+aTaO1M91eVU+0dN5lIKE0hY+6ZhdH8xPatSu9IGjiSBRxdlYhnVgx3DM3OmAAPUh
+oivOGZEA50UKDKlBGKmuKZHM7ZnaIrey9kZzbWmTBux5hLriaXv3sCjh3RSQN2Km
+seQirWUXffY2PUwR4ix73JkV2Xnrhe5wc7ATvBMNCGsQ9s1jt3XLtQAW0gIAsK7i
+GYMN4XZoBFGRARR6qCjNIi9RgC+TuutUGw5urUrW9IBs3WmZh5j0JAQtReBHKKCw
+Ao1BYPjdMlMyTuA3z3s5HrzxCD7DNUpI9NKK1QCbU3u6DYiKaA7sOUSYFvgSL2GV
+56raInCNge3z1vokDQ4oBA7DVZChDpWQ6HOcrY+5Qi5tmkDUUFPEQNwVKiIBqChg
+igm4JIiXEAJEBKiKBIihiUjIdguH3TxtEV8CLnCZZJXuZrns5yGzNcQqb5nRD8Kf
+Ejj1uLimHfFsXzlUZzvk7zxYPeGzkRdgYzYoe7Nc34mq1NfS0+Tpc572vBToIi+h
+NC8Ksk0wShGEgp3jOt0s2159erxfPx1eTb02DQXSuDB5AkTVTpTmMjNgcOdrKEzr
+tc4aYgDJqgdKhmhE3HZulPmAHB7632oFlcTlmCvKgosDR7ft7TOgZfTYJwR7AXuW
+/S8+gIFeKNjkv3u7oLzAyBFiIY4bJOh4OuYdqgOIWvESJAdRUwkRH0TBzeSHfdN6
+Bz4E9oSSCWPhUXvDkFmbZ2uSLokHIEKenMqeTFXgg3poKBEk9zF2SbQhJap4uGJJ
+FC6V1rXoCFhRw7YcnMjkezOEULe98ME6Ds0IYzERWbF33DHNcyL7qBnaeKKU8Wx9
+AYMaYwHMmO44OFPK1nebx24PdpQEPFOIOCGGRgnfbPFFecB7CSMybA7NNoCJdWkq
+A6uxgQHTSlzjN02jfYhsKEJKfK3grm8IX6/ZCr04RBTyJ2sbuCdybNeEICJ26MbJ
+jeDS6wgqPaR9ormfdmFDLWdBF0bbY2212EiKqJfXchQkdNNXrLktUifqXfCq84+8
+Z6VhYN5i5hktLGeDvDyUvWWAs27y4SHHMOtg0Rag4RHHJZJzJpVzqEypuBMu2xKI
+MQEgIgDMNB440aFxBiGgVIhdjaNkyK8RRKsepNlmwLGE3pI5dmBEqgxMdV0KaHO8
+HhyQ2xG2KGDGNoGzBt7biE+kQ6Bod7WXByC2xtI4zTaLsEoGd3XlmZdylWF1alnb
+M69mJMgnkxqru4Oogy+Ri7zgqVzMxct3GGZgXGSdkzJjhyAuE2PZ723DJwTyMnjh
+l3tHY5VDpUieCoJmSC8uhRWOsIvHrs3IcXRWXW5dAv7/778fUJpA9gUVtiDse9fX
+eLqjFjg9tC9YHmeTlFWicKAUpOimCqgEtGlSNGcpe3u66YHC5aNSJLww2kUhcBCo
+sQJBzkAYmK7l1EZTiK2JEzDnWILQWZzI5NHO5yHsQScKeLA3Y1UxANcWcBcAXTZC
+nG3WEshvETCEE/bPauJ2LcYYpkGUUtAj4AMoK/tv6dyS4In1VQtIbiS0kHqwagwE
+s2PM5itnuLiqWW680Rhkknpn2RxZA/NquFxL9qJ+MWTj/aqbZM1Eg28nmVVm5HKs
+lPLjlU2yZl+lLy2b+bKSNUYSElldBP7yb+gMMPeIR9GJowRgkgRoYVdqHQlwIDLQ
+aiI6H1XmnDYFAee304yulhRgMIl8rODvjPsYDh4FRB4lS0XTd85zYMBdO9uA1XQj
+EQiIrzFbmDjy+83gvNdxScSEU2bnSmgAjjhZ0eHKQtVyg3vI5fSCEKUQLGWCcN64
+SoBE1gka0aWw7IlYUoJeMdqQ5ytWEITjsqzKm8ZQESwE6E2CN4IIUSEnUYdM0vGl
+bHppfLXOIXBTSfWIgFSl6IChy+B0e4/JZIPYtHBc8xqqNyEaYZAWKNvfjpvJ6pXN
+iRCGxlbePrTJreU3HXYA2d8CBSRKa51BpHeF0vGi5yH3vMvA8hjcyHuijgTurUuj
+QcspGgZqbDJsCwLljxYqwh0UedgzggA1oQPI1qSzDKyyTLBusjazKdKbN8Mpiiht
+tahHCFFJFECD5lOaLBoYNnSA5Vo0uVRGun3s3jbMCD8MAOHpiyBtrvGjhr1I4Kam
+hC90hDDgrxsCgbMgmSDrjyPJSVi0W46roi+Blde3oaM85BCOMlkvxXOBKzLEV9tx
+jdKcCx5V102vHRvAEBovGic6QBeiErtETJWKgpIgxvYmMdZt+YQ8c1CsakICg2WZ
+YJ1wKg5NIYcsHI7TKYIG9UiK5Dh3nMiYQyjsFTApEA2cmsjhUIqrYHeoS28gi1UT
+O+eZXGRAHUG1Gwk33qXWInhbyo5dSTqBDuQtgRSK2UpGW9OB04oooTkj1I1XpEzE
+sEzSF8gCdoVyiYDkYCLfSn0SyX2hCQQsiaxSyGKpCEVn+T+7ACroi7X8aJopBWVZ
+ZWHIQaTx4SNUeLDFSxevebd+cHKoaR+Uldj4hZiyxAxiEJPs55pQEVzsqkE5E3EK
+C8Zrl12Z6ZyL3XJIIiYtC1Axc5KDSj612cHXeoDiFrcpuKKB6LCLGCsgEWAcjIYi
+7hqF7Haj4908uyiAKrcawQQ5bsgLte4FvgR3kPuHtlEgneUBi6RqG4DiDmJiBIgS
+VKzW6RQTsDZDRB7vFB/Npbn3thjxnOfz03l8o4iPr5vcTXayIrevu4elRUVaMYKB
+TVWh4hpU3OBfMUdpqaMvN5RfQRHEA5SRsCqgNvSaSWAjxg2Sce8tmpLwQTzaEJKY
+a7vw4DMq4BBwDCYqTySZ5Y4qUEBqrTyjRBdDSeJIR3x93G24dW0Fsfb52b53LqcB
+LxkrVu+jOgAOVeWKSAPYajZnWDo8DQrwVXMRLreCHM8HdKQ7MnILkIj3MoONh0TW
+CXGY8bOCBgAXDflHcvJbxkD4icpcbMiA0ObDPeZMm9qh4TsxeYSrNdsERNogpnNA
+iWcLBMk3AFNaaFs84CFDeDFXxodhl7a9MyVyMFFD0AIGiNGCvoSCLqpw0errcmtJ
+ZMaVMLAkEC6A0HNHB9bcXzSDliqUfebISAiIRkyhvuGM41wC0GZ9e14N0k1dvH2j
+IIzL0HDgOgo2Teq2QOrLViXLanCQRVQkcYimjkTcFagkgFwMQzjIhkESKoRYDARO
+OUM3MEMWezt6GgSuFhS2HQXOveJgcUGzsH1FZhnVaE8D1kRDjrF+riAwE0VbuVvu
+Wx0Vo0Ivo3snYbRflxgcfJwR3m0ICx85dsSDvT3cZ29Q4CWGBQLggyCKEiARitqr
+sNm0fTrW3Krxa102dakYpVhqwhVCrC2SGOlkRk1UlqBaSVYVJYN7ERi1FAbW+G3z
+51re5VjVbm5W5UlbmrUmM9t/6/T6vv9Po7vhq+xJDxqrZJCSN4A9ebXxyczXxmoN
+33VoVPS3BLDLLHbi5spPNZK0uCZvZgZzc23MBvtLdad1ruTZJGVJwaelJw113fR8
+rnExqR0PrSFjAyjjVUETBCGwkwwK3s287kNjE+yu0Hbm242i5VRLlk0STTSgxaFK
+RQ77zTcyWsiGy8yIrLiHHJjtG1A2Yw3W9UlzdFd2HcNCqkQgyani4Bu3NroVFnYL
+2HzDRFdvTmig2HcOnFxATrA0TnGma3YZz0ymbsQAYJGBFbqwZSEku3x21FBfCArF
+0wi6MyRrQQhzxXZCortLApgcocDruDxkuASSjkkCRHHVa1oVlDu7SymYTanF4+3W
+eROwxPvSBh9NNJ8ik1JAnwJivP2b/k6eXnnoQc+e3REtcmUhKCgg9oIgj3cO94cZ
+1/yZZPYXmLsEVzL9wyayYqdoLf7u7cMaiHlnOXVcjK1tFvlVLZVUn6CtS/Dc2MGy
+jQgfhC2Kdjr3P4oF82DpTA7dJI8fmoIQcC1skeRzKgLQfdKJKWsxDeDRAOkVD1Uj
+6REe5pkkFtcBVDyBmsYcJiDPKL4QYIAKg3pFBYsEheQysfqhKb7Z5Wjm10jpNiZp
+B5IyQBQMUV05k5WF025JblIlxOjYPTSQS14ht99a4g4RAIMEXBQ9VYdUOnAHboCb
+AM8xBqUidwUIqCaNuDndlLcheCQRzyDZsza6jpcC8J5t93uI52DOCUmxyBWG6xjU
+DfvcQN2R3loD2RQpUCyjb0Nnj8jM44gOI4HkYOhJNFBUaBwiiugHBtgmVWWcPJ2v
+AGlYg8pB1knDeEQyYzoFW+nZieSuAOXHdpQnYHIIvsnV62gW62oGOQSq0ZHQmkz6
+ve09eR6+As6PaDEAPBAjCRxHiizSKSWE3lI8fDOCDmGnmVpNbi8eUVoBcnjVYXJH
+Wy5Y+Ig8gsiDUDTA6xDbTXjDHGKyNg20+8AoKRpUzjVgeIneyymHNIhlOlRveBNb
+AyNu+YZy5q7JQKKSSPDgYkgOZ54N9vTDVhqc6UhuwvCADsV5z0KRpEITXj4+mgml
+oIZg4a71Zlm7m0gkdp4U3zAnK2iHrqjsxi8S8sDdGDo9ucdGhjq81Jfa1MiJSKcB
+A701FV6aw8Hp7V9EURNiZNADwG3dhrhp2xsMQdoNaPWpg17FE8O8dR1VHRzpUzs4
+oW8uITBTDYPLynlwZDIItG+CIpXe2AKuCI7Qs1rnC94AEyGbMuhIPF1HgmbONCmS
+5k7bSMjXhXQp1OCjmkAGTvLOmI0HOAt3YzBQRFgqFp2bepbOC2EIwJLOpBSCVEHI
+kdNxHOkAQs0VIpgJl4XMHMjEgid0t3FO8MJhYYXY8sERIghdxq3vQKeC72BkdCeG
+xRxAiGkDGK5LYsCK3AWW+AM5VQaWqrkJ3NiK8HR0Oyaird7M0013PrNY4oA67ZPe
+zuDTrV0oZMsRpR7ZipzQ1jzg4Ut53oN2DS2qHRF3Qms17VFoJ5zQGLHnTQ1WhcBQ
+uEUTQhQjEQUHI85hT5R2UYC3twsue/zOINAzYK9Mg24cwzR4rXfuB43f5g0wg+ma
+n54RRErdutOia0EPZPBoCriZ3WIjYiAiY9ycBy8PvV0fdNCtr1kSkUTFpWjZQ33A
+Gh0a7ep6g4nkWoASDIDjZq/BgHfve9jgEEhzWCeQR7Hli6A20uwCorkhnm7lK6hw
+1GyiXCVzPlIK80MpCjwRAoagLZOVxmZA+eBSGhCIL9tBXabrpw47c5zKNaAKO4sL
+7KvUaVGgeYA4XSjsTXG+b3fBFtoGLhoKvIHohI5zzHSwDMUyPCJ8Zjolsa6FJ1An
+5EizYQKcpor6HHhk6GdulzXbHMekayul6RlzuOIXQHGhtCOsOrdgh5yBUI4QD6cJ
+CNmU1QYJoXJADgxaZvbMMEEkHSPshs7OGaJOF613Nd0CBj2PIi+PXV5W90bvAECz
+SV7CKiJiGUeZErQbfUGQNmjhny5vomzEBFviHjwiiJ0o1E52tFzGaXbdCZ4hwwYE
+QPQQkQZFRB5oqVQlVfs5E1NSQq6LJmIhqJUJBkSTmKRwxxBG4hmGYgYhOlbgcIM3
+Qhnd3c1BbjEYvIhbZzEQRGBE2cgI5W4RhHpgCsRsjcdWFMN0olQDA5nd4AckRPbG
+2+i25y8WqkxW8Wupq+jB2ymQckBbjqGGJ2AtMuBuG4BrSNp5MsuWwgXbcCXcIAxo
+J5BTSW05do8jzcwVXNZNxgxuimapGRGRMeE3YqpoRFQVEB1gVMQgYxo7G7bmRDES
+u71hcZac1QBCRIHe0LZAbAbHxDwuLIhFlGQ311uRlODv9YkCQRH+Eh/r6Q/7bT83
+9x/Fr+4/N+xjJ/ef+if6dubx/+uT/af5yl/qO7x5v6rVWuWZlZjM5eZ/VustitjY
+3HC0dHExsx/qOenTOnMdJLi6X+gqTDD7MX/BpCpmFwf/C6fg79fommh7CkD5icKI
+rVSTX/Uh8fGFGKs+lPgrQH+bz8pu235HwdPyPCs0aP60bPSYwmirZ/oP34xfQ1wP
+pnDAX5KPS23/G6nZ/TKCJiCNS5oIRTN0GCKEmhG9kYgIrr/UH+fx/tEuBL+6UPJP
+b3bTrJphJ0Vu8PmOnIeyvm4J8dKtpVV7Nxk1Ldm7r2f9z6VbD/lVr/jIa0/ZP2/6
+fsPJ4euM7/l/w/Hbe2qPmk4Gye8+XFXSsxt8HE/hOObeMcPpNPb7slXdTm6OZ/v/
+5dVzU58rFtJ4e3yv9l6buQsjiD1R2Np9hTyeTt6+038W47SRy6PY06E+P3JOgWaQ
+hHAkkR/Xh/2ncXif2afyf4Svf5NvY3/UP3JXCqfaxkZRL/J3CPDzFxNGAzKcQTnd
+cHPayzzbvLxDd1UnVvMbTw9BywcPDfsc2zm/nyMfDmf932T7p87KrxgyeFftQ+tf
+Cfh7HZyeE2aj8Ld3bXw43xb83/u3I6WSftIeD/xbZE/8bwT5H1OjB9vDc2fr8Q+u
+397X9Gf+PSdnVOzpP8PP+c7z52c3SP5Gtkn9kn/w7H1cp+5o+HrPZPv7uTykTn4t
+qMW5ktlnN5X7r3/GJDMMmGVMJN7siu/yfnqffmvSXMu6ft6bOJlTaKqp/L3k/g2n
+c/7fv5SH4e7wSNdHTnGSe7brKd9m2+rfs+75c1sWpbaXqOkkpTo6LvZVDoKaaPJd
+rf6/wabfy//P+Ses/dNe1Wv4P05eaf0Xg/vluP7Okm/5eu4+LJMnvJ6vyfdiuNK0
+Wbn2ZOW7k/O5dVV1S0twqcn6SMKzp/2y3c5D8U7EssiWcxtqybtlfi2p2J1xcn7G
+nI/NwcrP+tfj8/scv7QZ8v3tjkfXsw7Hk28PhyNkcPY3e7To4dLZXs52SnOcp+0v
+BzIaa0rMZV/r4j+X7dHd5OqeK/l2Ng6ZCf3R4MsiMaozClqv621/Cfwfp/G2c4GO
+dLV9XSfLMq1YzWaxrDFXxLOJ3YfCa+Wpzeb8XWTm+JzP+IICf93/kNaqLaNrWSqi
+ttajRqjbapmqtpS2qxVk1bUlWpNqLRWpZqtJNKo1U0ttRsy20zVJqrG2wBY1sVoL
+FUWJs1ikLFTK0am2RVFYUrYNFpNtTCoNYjWpaFbG0TKLTDY1RrJSWwCVU1K0mkrG
+yUpUbZDVikMW0bZkYotZMmZGLRsY0KIViLGjRsUWxtRUzFiTQaisJEzIaWTNYIjU
+RhTZsyUWxsUUlY2oyRsm1G1k1MhLM2Q2gWRRMpDGE0zA0ktFBaZGyBETCCMgSEaj
+EWjaJKU2NqZFooxiokSIyMMUIWEaiMhQoIiiqQmIYEkRhFpEhYqSGCLFCKEMEEGT
+9mvzf2fuM6SFZC4Qd9fugRia8BBCIvlh/UPmUoYBieRgSMiPA/zM5kG80OwWXxVB
+kDKCgX+vVRm/7UQIDInnOZ/vuDq/4D8+p51Kq1Jw/kWTzvI4d9a7SyLfWstuvCsR
+8vO+Ve9WpNJv7s7+fuL8JV+dboUuDPzER7chJZ58smGb6bfHJ+/wytuIdr6d7a47
+bq+tvU9ubKTxSujpWpbkOGArKSYHFiSSfHgG2RPcG5lSlkRGbrdlTVFVeA1pC41W
+V8XE0QYWbMrorO7DWTBoBRpgyaqKdSFItuzQ+QpmRRpSUkgkAkgVhutQk5vCYVVC
+2pCBtTYcnZA1HRmQ5KEKUJCjE441UykKrp04rW12EaksMjEqCmiOKKAiIoVAjHHG
+4Oy2vMLFphr2skmltbAj2yHto+/C1qRSHQI0oYJy4xPAK0hBhkBkzKGIDKfqR5fu
+9Rb6jriPwFfrT57/BORRUS2uxaWe/23vw/VDRJUNDKbcoql9hR1STaoUKFJAhAE0
+AZZLjCTR5qxIgYLhyUQktqwQ0LakMUoDZaYvf1dL7/UTZGZSt/h0bF8bOrkShINm
+UC5JVQoULQdWFmExZOwxx6b/nrJEIzcATXe9RX4uAjQuZbT7+8dvCcTe970nE51j
+cmac2WktrRIBr8KKqmFiShChQWsTPnID4M0CSyZe7rltE0/bIvrM+YcPthAH85JJ
+219mY5mjPQZhiZDYZA1DzBlAjUcjXvLL8BABMGVQh/A/vPwUfqX/5kl6UGGJn8FC
+P2GG+QceVRTNvxzts75paBK7NzM7TzVVUzlIqqif8NJKRImR08cg2cHrQWxKYcNh
+OjnHzz+YPyaL9PWNrPR37fFaHr23fpcy+YYGWlsuQf4q7bXFjzjZ66t5DEnZsqLU
+ixYlKiy0ibZsjalZamaizKs1laSpmk2ratltZbWSta0bazUrFJs0ttalazaQUhKg
+lSUAqyQoWSKtotVYtSmoyW220arUsoo1tpLaNtMsmtaaYsVTbS2UtJgram22rCkS
+qQSxISyQS0FSSyM1KaS2laa0lhNFGhYWigRULZFiyykqoCxFBKRFSItCrIUWLKak
+ppY2WbY2tps1pm2ymqbabbLNiZojaZkrFMKZrKzaWVptZtppijZNM2SzKmmxsRab
+LZs2K1NVqWqEzMlJtmqVRjVNZWllSVLM0LNNZpalZokSlltLasJRUqopUpZIElIE
+lkqrYjVi0aSNqWmLKpslJtFRBbSbbMy1KoplRspaNlNUrNUaaak2mpVFTZVGxk2a
+GTSWmzaCpKbNJW2WqWqKMmNk1GkKUtk2ysrLNs2WwyrMqKpqZmmmKxtmqayKZlUk
+qNltKlRSm2StUtbLWxTNUqlspo1ZtltNKRIqGm0tlRtNmmalNGZYybMozNNKkxpI
+2i2ULJqUrGyyxJslNGpZmtNSsrNWZY222yttmrVNTbWZZMms2lllbKstpmrNMUmp
+KqUtptKyaplKbRSbJbLNplZtqM1KKbabU1ZSUAmUaxpZjUkhUmyZmxbRSltNsrMq
+qVbNtslSptEzVrMqaazNpmkqZsxExpJSk1itlWqay1KppYopMUkkkmbLNlMymsxS
+0TKlNjKbA1TLLLU0lTWalTNMilKmys2ZY2mqViUVKSyksmapVNqSJRqxZSyylMlS
+yLFSWRUliWKLJPR487tzxPbvpf6y887/zT6h9UmfSx2PLPXLE2t67TNb+d8616jt
+tPkeNmjOnd2bULjnN/5x19I3dES+7KaAHB8sg9OaIHogcFmowcPkd56v4UKiqJhg
+oAU9AHxYiJSboAuO2tYkauzYowUsXVGVlc0nYOpihEKtGCELstXcQR40ZwxcKms+
+7pFjCoGnlWDFSsNDI2M37zbDfLv3avdlnZZ+BC52UzTjZKLth+XpejoaOcVlvLIp
+Bt0bICZGx12W3MemDI+BEABpXP87P4rJiq/on3ucmKl3H2qkVoDOXeBVIHThRlRW
+oIeneSsFb5P81QBgJOLBARAX3nH8/r/f8w3ilqIGYIs2ETpWjUrVBz3ap+abPKWH
+pLM3ltPx/+N/Wbt1NbzHN6yn49NkVXLjHsi0YsxWYxt0mpP5liJ0D/BK861JPxVJ
+KrrKd1DEsjkf2fd+E1sqc+0G02nKaZP3/wWYV/JKhVSKU/9f2kP+Es6z7k/gUksW
+JYe1an/921pBsrUdXyfSH+6h3N4k/jE5ItS1VTkajSXnZgf5UtgpKk2jaxZibyd4
+83LeR6x6+RPw/T0lWWVLOy4k54wllqVWtTTUvHd5G6VXZwcLVpZCyOySqT/VUqI2
+a3OjB+BJ/c5vJ17xaYezrA2WTu8JipWJ34en5WSThOGGFkqslgxWw1Riyit2TjUk
+4m2SJs+3WFSYNQcR9lN+j4j1noP93VyHCfI7cNMSZzH2ZNRThulseIk/yU5KdXt9
+v7zmbk+gjtO690cSQSoFfmmeBxfI+vqGsirzNH5C+xTw2WGGHE0X+u176U0uLoPT
+OEn+qsbDvaA4s+lX8EqpJzPrH0sloeXR1c9OiqmXer0zgSe5ZrT6ScTDZPxHCbPN
+0R5uo6u07SaTyP+1LS2qfontI4sTqU/nOnq3gQE3PlZlmWZRJYUsqyJ2P6PJ+L5/
+D8Jssqnh8+u+2ca0nxwRAJ32knCcvhmYySY8DlHwPRZOyxVSqrmc5yn+vVN35FkO
+yvNZM/ORPMmjIkxNtLVRf1qQ3ksieqJL38h25PbeROj0cV6GFHWIPN2qxXorv7Oc
+ifauTZXzYwjFM+LPNWr/a58p5xuD9uXn6b8HdXj7TiR9vZIw7HVkmGI8569eqqvk
+P0vhi5cxU9euWvzV52lG6lLCSmYWK8coeiN0jxImMiT1bT9FffylTz7SRs5vwq1O
+E1BPxdk4PSI/RJu9WoSzsTH6v0nJ8nrzi+ITko3SqSvxOJ2nukqKkpNLHec/hfS3
+JEnzWJ39PoktklpWMyyPh/0Tc9E9Kdo5IemeY1NR+smI8T/dPNYrc5nXv9t9sHUa
+mQsqCq1PemmmTVTeR5UqqSopSlKWFOYaL87JVmxycMd8wy5fM2Yw/RXl8vbb5SVb
+u3zORyjjG3DhlMKM111l6sSk+BAMLpSjqdn8I5U+moXwXX5p0Z+Ev8Zh48/wLRnq
+sVOvKupu7tEKFfaNwYH8/Ci1xHTYAbREOEoEoBMbtSSnI7QnHvPpNvIrSaUlVwno
+cA2T6JPxOc9Hjj805OqKqKTKMtvz7PuSa/Ze7Y4TXj0keaMVJIBO6TUtNbu22/rK
+Ik20pV+zX62sR+LTYvA/nP8S/x/z/y/t/m/n/s/ozh/TTT0zNN8l832eeZrP1ft7
+l855ZP0+7P2fht+Mct5xlvGpyPw3YySSq45XU1bSyrab5ycrjjicbfT6o/FPun2h
+kqLVQZw1OrdGyq/AmFG8iUYmGjHDOy2YstLLBnKVZJvoZpv/dskjgWfX0jmmn+XT
+9EpEKhcAUlB/eYz+SbNu4qNSSEC7hItGyfhotsOAf9SwdHA8hOJqR/DyaGA0EVqI
+SKD6AWMbIK+iFwiWZNpCAwgFlSy1TRu/m2NnOmMXFK6UuExRVkRZMoar/6uXRP9P
+7ZP87LZwYx0FWaYU5vlVTqmnh1eev7szJOiq4leaII1cL9t51vM2+LzXlfVqKWyp
+WvCVPQwScjU2St+kOba054lwkpIqTJm2mrtWuoYNioqjXh9ZCcg4fauRyifOQnf6
+SGRSfxqdVrKlWU2qUzZplGsprUmLRsRajVG1FqI0mwhqNsVY0VqNYxgASIkzAhPb
+KKjCrJLVvcYYOJOH+vt9D6MOVhCbzFWO4yRsEfXvzBp0P+0m6q/l61TUNMPwDbP4
+A4ZborpXA29kUhELXpos8r3drnud3G50Si5VJtefj+9ZVvVRlXCz1Xg6KThMk4mm
+/BxViVUbKrUw0nSUxVm8OjGchs/DpN495AGe5+K5OvXzvbUNNMVStZlSc5ucwd3W
+l4u1dm3WlJobdG41bAbKyodIBU0lRgRgW0aw1kwVrIutSyFWNio1Fc3UKqqpRju5
+Aadp5fl5udRTjI1JPdwpAh5+pEn8lE/gwPC4SP7yQ/wfmhzK6WLcLLBfzaejXg5N
+ROtJbDGTLY1NWSMQ3kPP8tNlbsFLO0khJHEnOD8iIBLHY5E5Vaioqq6mHOzViRnO
+TJDV5noj3lYCpbB/UKCPiSPRFBjGEsHZXWOmMUqqoqjVmVmoGFKNXF5UqRqditja
+VqjRtTTJJCSNK2SIBLIlcoL93JoaGmSYppju7taVJZUVshVKnwaD0EH7hMmp/h+o
+Pbiejj/LCXLxi+sY57t+Gq/cILqWSklksgVasVYdKi3aLGlcq4fh/b/0JI17/hz9
+I5p2kpb6oqMezcw1GWkqUylkKqYsxkpUqrKj6ahmlf3ytR/QMwpaUHB8iNiv9K/z
+0K6HAP93CkfDPEO0tLILS0pZtCxDEo+smm6SnpFqPN8mB8k84m6eFkLPr2/b9vvq
+30sMxTJbKbV41vETNRjrYhAm0Kmypb2ozMJGlqo0oyt7s1+ZqRGE5GDhx9HdIoQm
+hH5pdOT8GMwPVn9cd2LOKocJYqpE2fJibmxMRhVjdipjJLKxv8lUwhE3F+9vM/Z+
+96zDku8juRY8ZkygVpQhCSGE5vWjeiSSO8ZFx43qYwI0q4xeFMojCEBoYwhDwpBe
+iHCkNkSihsIJhUNuES4aChQwWFNLDYrSqqVumBhK0xiN2qw02aBvWoQRkbNJJAkj
+HBk/f0jBi0Qj3trasZSWJAABGGhpyETY2mx2GGObpTObWrb351Vt6QURN7vvOMuZ
+MryvV8esvd69S9JGxrTRiEw0k5hoCqjCFy3INRaqNJwakaGEikSrNSYRWTRj019T
+4CORqY4ubfHfS36+r2c6tibQpT7uqxK5TMRXftJ83l0OEKb1aVXy8jZKtwphii1E
+32XPN122+997zbb3qg2rFWEspycmx5fi63iHJ04NMLBsItv9IBqEOmT9g+SGvcbp
++/hdEfGRojRGhaIFKIYxkBlxKkgcNtjbaQ3UpIqYgYoKWc8GtGtpwV4rXQ74tWyW
+WrSqxFk4NRFSeaScu5yP8VExZEm6XE4chWxqNGXXVJkYnR2cdHk8WdGYy2vCmNjq
+ybrMN1FOOcToskqqI6hQJYpkEaNCNn6FTLldFQjIRVoB+utwbXmdbmWEDBprGCfA
+JCZRpKqRYfq2e+7Cq5cNSfueE8nT0BAAmYe3/Q5/hbbwssFCXp+OE9EkGFrg00fG
+yXabHiy3EqpTo/Z9bfo+ZtPrQAuNWcI9+eSwSa/nYd7oXFadmUYi1ukq/ac5AAQE
+7du1t6q7K4YbOHkbtuq8NNGMZw/VibN2MKnJyZJzVzbk8nnizzY8nI5Pu2KrwXrL
+dm6nQ57aXMY8TsVyIDC5bX0WfDw+jTpp6QuEj7W1TMvq8Zyu9vdXFD+nVQXfaj5R
+BRz2fkfnvWnhDIyYKVitWiZZUs64DB3WmYY2xUAXs0Cakm2Wq5otBR1e9IE4xR6I
+UQ1xETvEmN8IlSLEh0Um6u2FSoE1m8LDpW1Hm4TFaGovlKmdEOVumVxam7bCipxu
+T6y5i4+SRHYrzydyzSvjm0vMKixJqmXoTSKKjLRTRkxS7yrSDPFa3nQXLkJi0PGz
+Ue3b6kGdih7KjMMNAjQzQTDB/OKQ8KFuO0yGQmIsJJJLKKGQAQmMosKAsZY1R0kL
+PhQaaKZWN45u7TtPs7uvVu7uqsd2mxpMjs4adWm7k2YxhWGOTRjkw3YppSco2dSD
+nDT6F8LNCzhHRwSHThhZCw/JCkWC0Z4GlllmHQk0JGWItJaemBYmSUfC/CzGtdOZ
+glpafCCzTTeNljGYrTsbK77srM0abuHRsdXENonRVgs/PvuqzvZPJURUwfRVTFTL
+HP5c+u4dT7LGDtNFEMwhcRariKthqTD1vPM95zBVA62rlBLfaioIouD1obsxmY4/
+SLbB1fe/WE5wvNs4XW/dM+pCuTReSLHk06DGF0WkGUHXGlrLY4aDxn3fHt8HuzrJ
+2+aMDPlI78q6bHxj5uF2TCFwbZMGRZ9YDJhIWy5Kgdxy7a9+tDiflePrabvyHDj9
+YiBjKMXYZIRdTNJHAOT6taIRRhwL6k4WH8MdqdOHDZ5XET0kKmF2Bk/gCivPTwLD
+D6OnV3Btj6vA6NAoRYdIDZ/GwT5X5/HRth0F6JgMp8aAo/b8aP0dVD3bWzoGD9jA
+IdGjWJpqFEIwOEjh+nBfY8Pv9ThAfIA+v1W1zDh98+IKpRNs2Kmxah79W223bEUj
+8FgfYebzbUyGl4S8AJvIixBOhDSmA2GYKhWeUS6ADRDvpmoClc1nZxo2BcF8lMAq
+GbIksqALJKpZprIel0G/UM0/NROWO2EHdl8baxjfvVc1Dz9VKlRqHhPwoX/hRooL
+hYtcLETvFJPN1IgE2b15FDZI8kftKHm25vocSMiWe502fv/5wLI7POSTnpHiVNkn
+KN0f5ylSllDaC8/EnNMn8bMOXdHDBEkioNT/Kpjl5T/FSNstpVTGKjCyZJilljk0
+WCJtTbKttU1vQ16RREbZJVRVnrJY8VbpfQ4jCfGExUvOtzOch1jTc+c6fhbzdJ+T
+ZjocHhp7tOTg0hqFHEdpzHf3mFU3tGUGnq9aOgRXwlMPc4oqofnnzkevPke8ocXV
+cWn5KA/wBIoOBRh4tKPhq0owg6MZB0JF0/BAeEjICzw6dNpJCSLZwqAGV7MVmZlz
+FW3GuSbWrY1tbz6cEBX5/031t5Xq26tD0eeTKPanZz5maen48Hmfm+rh8R/tsevt
+95vOVW8muQ0/dwn6qkVSPxsTydUx6UtRVtlfoqMjse8kMZUj0SSye7/KVZXR81mz
+STUJXk04fITUm7Y+EeH1SIBLCfsshViYpJybG/429HOeflhiyJoizZZJqnHAaUfl
+IkvOJH3SKlVJFWbJPqT6ux9pskzdwrJy6NBxBPGkSiqK9nE/6yaHtOaOIlPR5ned
+BwjqrLOVGfdvOzy8zy6OTpB8JJ5O35aTvUnmpOHOTST7q5Tt4SqsKqrKU8ZMLO59
+VefKuttZmLKmGsVuzxJ4xtmOsbzj7jrHOnDaObg2tvZVLY2bG06W4xJ2PRXowWn6
+Q2qskgjIGgwGL/Z/7+qho/gPTXh36jmR1w9demMo4Y8k1PnrL5bLq5qtlHMrhcTx
+qkjHMqVQDGMFtMg0tkKYtmljaZTJIMj9NFIipt2BtNmmpK5MDFVUUwrJvjElbUrM
+i23kbNn7H7hCiP4ZebpITlFV4hhqmRLE7Z94lSPPmM6+HR5PY6k0ntVq21Nlhixw
+sJ52ZHpNNQajs6c9vfpv6ZntOE9LGPhh91dhtbjq2MjZvtil0zo6r+jL2H8eLj18
+yGzWRNcm9I5GokcOjGnDG7SaaFYxVOitW1Wmzf9NOstsnBXsVhrLaczNWymFZQmR
+BAR4hXFLIMn8tE0KNiGlQnWdm5TOjQdS2GXGiCBhAiR3+IuNtczrWRxLegSYOFQ8
+aNwQ5pS1bOmZvMuM2Titbss3zVUdd41y8iQI3cC+BYszD3iyYZAxufkk+P8nXHL9
+uAF6kyiw54eRvOBZOAlO2Jkks3WNzvOHZTF8wXjOnz157FNv8IdeqWn4QqxyMzjd
+ovNzuHBnGNqB8UypLJspmo/PZrnERR2PqVzauvfqDryP7Z+vQD7IISU+56T4JDTE
+q+pP9KlpI+PV4dT1ixJrec504hI0p0ainusxoch3Rf1aTnA9yf8ixfufD/nGTaR+
+r9Yxn56qBqi9vX5hPpZKpLI37GNPZmMfbbfbh2nCcj2D8Z5XfTA5tD/UrkhsSybh
+P3xy2n8vXr3+fHF+jbhrfffrgpMdwyKsEIABftZxWHn6eRPx3H4XyvkzMnSq9ves
+52gWBe8WN0R5UW63ukJQWFQ4oKhAJyCJnQEqDppQlchLgECaszI1WAe5g4MUFyh0
+anCQg4mSNdSo2xtqgYJ+eC6eYyu+bd9QOSufIb1aqsFPuqFWSpbKUpWlKojFKpSj
+ujZZcdbOTOI0xFWRNkIpGoH4pGFJpP3gr/zxFkAWoqElVYP4Gt/X38U271ZrEysV
+o23KuyJZatOZ0Kp4TXVYhqbvrZeRB/cPmRH1kRtuErUZW4UhQwwgBj0NR/V3kMY7
+EobIBcOQukBiqbEGpMmJiq+WZWm2LXZ6qn6+3RY7yG3Jww0zZ0a0T9xZo9U2SMjs
+PDENqfk7N482T5PLSV+d2a1f1eexrCMfZXsuIkyj/nLJDF6pYr8eHJ6TBVV87tmm
+a7bz+ky6PN897u1CATUrOcfrYT7WLUnZUkfzoytVKsFSxI3TkSuWTSN9Jpp5QZrw
+J9vP1+nTbT6eldk/oc3RMOhp4yJZ4IUQxBgmiHJjtlz2GvOHReN9+iGp4Jktksd2
+Fk4SV2/JatrxIFOH9wap6FtHEfVGhB1sDwiGOwtcvTAgVkF6fh/XVVVUQaOqOQog
+5PKIzrA2mJiXdzzLWRbIZCyUxgbN2zVNiK1HWZJuqUsH34W6Tk5MbyVmv9jI2aSL
+I2VKRQpzmQyE8pC1C1EUiox5RWwS9UwZLy63VpJNJfEm63WubJNNHJJO5+RurZhi
+qlWMUlah+7hqpN26aksmYnEl+2jDzy2sWVaxhxo0sy3GKzqg4dVFnqiH/Afo6ZOB
+w6/25A/kKKi+ipEIiyL9rIz61tdfOz5b9tOLlSqe0SxNVPNTFk/XTHSxksktjnfv
+TFaebEYVxUzjImU3vFMtuuFx2WDCnNvkJhZJpZDkrlXW3eZtcuKZcvAedJhwsO8s
+JvKWfGcuMmSVOdMuPtO5iTO25qE9ntOJ7c8nKZfwxh1UZJbaturhTFgc4VklKumu
+lWXlu5AcQCTBIkaKGFUrEV2UU/n8/HpxHWKqpiLFVxDTtu0ZLFI6kEKTsGEUPGDF
+OyKFmi9fCJPgqu54sCIJ6uD6eDlOsdVOSppKzATwfi2t4CPHgfLsRZAITsgfqQ3S
+VryjsJs6HWRGyuXSEjvQFceInojgi66B/Jn9YGev5OSROQPgpDM311czh5pv7QH1
+mjYdG88T0Y6lKoky/ahYfzsf2FLP37iw0iHVc4G1T+qGtRbbYqpbLVXmWjUYsWtd
+3blc3NcosbFotRq1lJaLZLMX+yeAaVGqxZhXrnN4O7p233eKV527HTl3dF67ngUT
+DIWkYklBhCDIYMo0DsbYvZpkT5KZKN0lGEqTdkzEsUySxKGyAtr23/mYGEIYA2ic
+NDzgWF6BTisD+sxSj0YjKCGUBhaU0dbAuSAVMAWdJKS0UVTIyJw03tpPFQtSP5Zb
+pmLpJw4T+ko4c5H5d37d2YZYsw/VekqVFiu6LIkAnOUupHbpVuhXVTePKxVB0bps
+xhwtW3SVTpJP4oliflH2jl+CLI6HIdidSOtEWxPwTYaOFsTDdMOO9lshLUSxbIu5
+uldYJIE/CVEfQGnw3KR8rEXXfhMiZYN1TKw6ox209eLH1yz6Qd55slpUwKmJGhpV
+YEWZi/Z/B+/mfovmdoZ+b+KH47xRdEr1MjJ+9ZGEk8zDzXfoia3VNrVu2HqivcwY
+3Cn7tM3ujFGxSqYs/dy22jfJLV3mNSTmx6I9vwKifsrmelJXD6zmOk4e/y1x5u6N
+kaNqieX17yTTwyGtH46H4Fak1c3Kk5z/ZZaK7PU4mLKJZX6ySfl593p1JU4nVzP4
+uonn80Sf8PxBATaSfrZLZLbUFOifY8b/OQOkPKRJYuHzE80n8kWiVZVKKsiPyj7f
+1czhH4I6GHur5ngfJsPHxaVDwbH4JEAnRdt8Mbc25sbc26WpK369rsq2Jk7ybJJ7
+nc7O76eHpxPLzn7OkGqH8mmR+h6xJVRVTckP3rP/RST+xYn6JzHM8ErZP8IJf7oK
+am6yrFq3COr+Gv1fkE1ZskzBUlfkrr8b8hzk8yxE2fNMfNrmi187J8z+Bmx2Wzuo
+upumHT834f0K/hL3SkSzQ2U85TkrZYbKMVKVsprfbMMsmUWyWP1W3DVjWss1MNMa
+H1WP6OTaGllrnZoiAS6ssfNp5sy3o6d+z1Phfsunc9WPbpmXPm3eqbeJ3nCllcoS
+R9y0sQeiKPWxdMHSL5yAm6DOmnZx9/de80IwLgMAwP8AgoIErJWSGzBhMaRbyCyG
+/KI3YnIr+zatN5zJm9iJx5FlEPllZszjniMMODP1NDhIdNGSUoDpyr2MFiNFAp7m
+dhmsM3rn7xcKDPsQKdNOmEcqRWE10Vn0f5jdKeQdD+sX9BD/gPSY95PtG5r5T0HY
+ruV86045uEMRVSihTsyZa8MesmkTJVlLKqkjBRhG+JG9NNZ4h9alqTnNfxllQNGA
+0GINwKMDY0ZDqh5V+GFsqw2G6lfuxMZjyPPPVzVO+/y341ul3m+NvxltY2IqNsRY
+1tTEiANRtZmKiypqJVJKtpSltTk/sPm7/O/dRNKm7YOQYxq6uWOcR7KE3fYnBOUc
+rZ8tbxGpQnw+T1h+E9UnrJ+6E4e77/fdEqziI7b4QxqWvgPVY2JuUihvCTzqWzax
+J8k0/ueZNn2cHv/723l7vkvl321HbIYegUM+f6eVz7iFR6+P17uMwF+AHuHwfOrG
+7J7tnlJLoqxiJZp7OkanzOMm8/JPR9k3N9px0iV2kiN/2MZWOp+Dmehw93hD9FiR
+9EvPnH5sfKX5VzOWREnZyUU+va6YuauVpl1jSzGGKqpqKIOVA2BEIIMpS3xoVbiJ
+DZ+4+ep9reEaqbrqJ9X9jOrrvJSr+/C3LCqZIomMTTGl5droWwvUnqT7fVasJ7Q3
+Vdshbp9jH8pBJ6bD2U+Cd/hZbX9ay6kU8KxTu8ttbZlm1Zpptjy1hjMVabYxkKUR
+gyjKMrbFpVVpilVWFxd4lsXb8MOW7fVipDJxhwVyRmzTVLLxkzco2dz5NnmsjnxG
+SQ0xLOUGItVGqYkjaPOd1ixXJ8pvAbHrxPhNAgJ168Kvepi5THZi1Orm5ld4ad8r
+162e8Lnx2rLKuWUXYSACKn+0Q+UPkiWkUT/jy4+mbc//nw1tlzru26a16nw/ipmj
+oukAwgMmggdSKdGbGU/Iprgvjn77Ct2WhTTOcy5KZMORZMZRWwQ6QquGZW1JTVlg
+QmM8osKKGDGMJIGMIBsiwhShSkqxMPy+3NPLDrbgVBbDqzyCBgWZKJrEQiRzR54q
+wia4gUepCJo2SzrcVXl3bH+sTOvr0qFHlmMYpGEQaiFZjEgQmdarIu7T2kdmRlAF
+SkKsnConJTZVYwmzOAdnDjWUlQbpLqEmzOttyWq429ehDBlMRRpyaUji5o2uW/LZ
+8wQgAFSMYB0Wdnuk9X8nH0naSH9JI+g9o2Gzu5nUVw9VrujeRN048OjNoP8LOjhS
+uG/rTtFPk8g307qhpyc48W4wop6dLpbpG62VarE1XE8iOyVK9ztXvOYw0JoSwJZJ
+Ftfft+V8JibSreNomUqaifeYC3fJ5fCnZQIMR8DDQUIxtbZGzGjKKNDyRspoqZqZ
+ossZ6UUDMFZKUgwYwsMaaYqaYrCr66wtypjY2abpVSX/mXeSNkaJPqgQhw2mmMjH
+EHymdzJLzYsvmuuvVbsqy6m7aYqyZnGoerqj3UePiyIVZIoqKthYOZ6vGFsYpWJz
+5ns4SY/yi4BSSyktv0dXbf1b1fl9fp9+36YjGvdRRMDFkx6Pp9wzFt1H2f0Y5CMb
+VjGyUszErxN3k9ks0S1Zk8IeitT1VrI3R37ye53Th502X+9254a+co8o7nMnWdCi
+wosHYmvktSVSyC6P4FSTb4evj8e+aNQ/gr3by2tmlU3bI5CjjaesCuuOTInFMxR6
+BGGiWW1NjQqsYxKUlU0qtak2QF9FdGkKOPTjiqoqd6H0PuA+KaOAwX65yfbt0Uu2
+t+9+OvxwswtdK+Z6T46z9ur6JavYqrVySsYUxinbay2mTZRVK1bWMy8Hm/TRaetZ
+W+L6HJ1GI7KbTEnokj3nzVNViyloqqryY4aU20msYtW5mTfBtWDH/fMFA6MUxGMR
+NFAuSNrZk1GrtLMg2RpFCqVUaUsYRZMiN2Nim9bnyPI1L5d7amo7nk142ZMm73SJ
+/eoPU902bpY5T5yQ6ffJkrLbKvs844reynK6fNsroOIGSOqTdhDZO0IlkpYiq6Oz
+Fkc0U/fPTYvU9bxWXZeLi5F902sZZU2ysGSmlVu0qcXTGyX5KS21VKrYw87pVnOc
+iN204sTwOM8R5cJLXpE8sT3gdCaTqejSJPFnanubqkqvQ5+EkEjrFki/syRPSKqx
+ixHNf1x69+Xp6t6l5LGF8d0xI7umlRgxkIYgsKQGahBGMdwkbbIclCjg2oW00iZA
+hDSVAoDGhqhIDTC4UGjDNVSwINaWT7/c+6B936RGV91beaH+tFpClUqVar6a57xS
+1YsdOxwxj98iTq3teHw5yT2NnV6Ms+s+NR8b24bKw/NWKKqqZhiqnM8QftpfQb+C
+Vs3lZLSSASqcfM7yVxGYledbnrN50XJBATYaCsBtFYJlZR2SKwb21+jqRiNFI0Sa
+rSjgiATZnWelW7O0mbziCfju7ylzo7WSqylsYp0JpjJU0qaMlJUUVhGilWTZudCx
+M+kc+l5uTSG84qLYv2ZJMli2qrILI2Tqln4cMqNhAj4gogAncslWOiwaV+BwnPnE
+jdp7E6UlqPtYJYV9Tg3WI95FkO6beZO8nlbeyYVc7od2tLylZPKLTp1I35t2iLsk
+ipSBQqtbUX19H2kWD8z2PyVPmh9rLUcrDSKQsTJIfukqY7Hl5DzdPLdUqq1+LJp5
+emzvHWPLN9YtWeh+2WzylkbFNlTCyVWKZpKyQ4YwqnWq3kKzCwje4lWdzTuDbTZx
+x4bJ8tzHGu7m3prWSakaVZncMwY02dcu7kznctvM5MknBXCmwVtKfU0xWphkowpi
+VsxiVW7I2rWqtRhwpcXDoaZN1MN6tYlKrh3GpWUlJLvXd43OuslSWQ0fVcxqeL+B
+Xv1rpQyBqdm7e1Ra8loulyubVzbXOGoNVpN1/mjcbxaAiUP6xnhT7z2IJaTCQVgt
+DpQcGFJgWSBTA5batqKV5l3ruu7XC3NyZRFeT486vWm68lRqMyRNpSzSpsi1KyzL
+GmTS2azSVMZqtq2bay1a0raVmmyq2yqikIVCwBSIqSpJJKsVBYgSKsBLSopRkS2t
+tKmrVKmA1rSpZU2JTWWSGtUtmsrMWKVLLVRCkSkEqQS0GpKlKZllNtK0WFGTNpZY
+2lmmZKZLbWbabW0ttZTSTFMklmzbbTaajUNZaVNKzWaipYqKmU2mMk2lilaVplhZ
+MykpmlSwamzZsrUtUJCNs2xE2zWbLJpmmmlSyzaYzNqWpssspZTaqtm1VbJlmm01
+kzUtDKks1LIK020pKUpNRlKTSlmUprKzRSmk1NTZZJrNhJIZMlSpNJDMktbNVDEs
+mpKFKVJtllm0ps2WzabGsbM2aQtmsJaMkNaVJmssNbZtbMprNYqWVKlaTUapJmGz
+RClCZhpmEmZpEympqWZmWbRs0SaY0lNTU2lqbLNtts1tsrNtKqSWmGWWW0tZrNiG
+Uy2ylLU2jJWUySmlNmpspWFKJrTVkE1lJmakWTZmUtpS0rKyqpVsilmsNrWWbLMq
+aVLFlNmazabZtNppoZJEkxlJIlplYbNUMaaVKhIUylmxaWkEslm2WoAZmYGmm02k
+mZ9vNcym/zYZ1m/E+UySfg39LUVVWb+0CAnu+IVnzkTYexs7ufDm0VjDZ7mmLPDC
+jvRkCK4NH4KYIPfTEsxAJVJTCY4MNNqKqTgrJkmjRkVkyN9MMuNskxW0mmjTSlSs
+RiUzxDKZmvWVXm9Y8a6VLqbbWXtSMLsZGTNoSqYkyYjI2VEskoLRRUbRRsbWkqSt
+Sau0WgopMsq6V0SZehQ82kyxbJsqq2k6xbaqqpy8chxElkKVybMPBqa1jIGLJqNa
+WSNnw5w5rJRVJ8pXQahwWUzyp0wnz/U0hIEiEYfzEVFZGtr8GqLFqNUUa0pVZVFV
+lLVsEy7VF1qILVeGEk2aS+WJki7F2pqD7InRyG/WjNbxTzY7E029eTdr/1ZJlhzx
+xZEk7TYxZI2Vk4yI8WLZEUcfOpyzjm2I50sicpFjzHRZKelYLMxipnrpolbK2wP3
+Gj5QrZ3mE7dW70dJN3aTWPvGzFnLOYscQkecNk/KdSbVattW/g8tatRJ9BbaVmTU
+cNkbE5NiRgCjqJjBFYYMQEpXT39BIxlLWwvLhFGpGWUqKViqxkcZkznhqQLSNrGQ
+hBUdGYxN2kbWNpAzdTVXSs46S3TNK5yd26mxXO7tXNdm0m6bRbSTJvK6rpKW2TFt
+vPLvJbNaSixoxKyEmNk0kWK0SdjZs2NohYnAsejhFowruXCQlUVFqVGpE0UGZIZE
+c3lktTo03a6N+EiflSdFScJJ0xKRxN5+ZDlCLZB9FWySZUtkhL9OWNS5Kx7HmGk3
+Zm+vn/kuSquatyCwYtGGhIxpQKVBh9sws7qnJ2thu+NtlbJbljpdXFmFp6I0cN3V
+hW7RqTNacWNJ80k/pbIVr82CR/iVzKp1fJPyjz7u0PGnOl53LbDvYakR0ZJD8qm5
+9mWLpEWRzhu+1n9OUKT1kn8VOh3p4lv5ZjCqf3P82pWjKmxUzVvxpOH8eDZPhDwf
+ii4JZZPcJ67Ts94+JJ8JN6n2RXJ/iPpDEN5uehqR3Yxju2bXbGDrRv6T0R5vdxJO
+R2mD+4dUjVjZFQf6RFZJ8rFskqu7VMy3EjDuzE2K5wH1nnG971lZjE1GMMpMLzVo
+tmMJoN2gv8yApnCpgihcVoiUFH+c9nnbz+momOTD2WTT5sRko0skZYttki1bLSVY
+mmMY0wqhWnGhdSllSSW9z4amEW8VfPq+6qyaeu2jZNvXtEl6ptryvUoxwqtXN1Fm
+Yqyc7Jqlsb2TXkulki/galjcAwqxIxJEkIZjxWvohjDLbjDg3VHCdKtlCUmTvHq1
+g1bKsb1nufaqpD0uQWNon9Cdrrb3LTMlSbUTSbK0ohajIvgjH+99Bt8p3n6qleSV
+ZE6o9h2eHZRzpwc3OYmK009E9R328jxMbJvFH6StQnM1NNmLDBWdD/DwdQc+bD7v
+Uoz8D4pQaY3jgmo4UpCiqrGzZpNbC5h/TXGpNqn1Vaok4ZPk4KphiwyWJy5ZHRwf
+oiZC34h6SrVlWif7FRHs1+Nuh+L5Hs6k7WWyNKyald2mpMaNp8+jr5z3H5HpDpU/
+yqPXPAk91O6UFo2PK2u5jy7lWy35Kw+iPIqfOySOpNDJ1k4nqsilXhkeZbW8c56z
+Rx1kbkR1nBpJ1VUPWotkR0rdsQsexSuL+5pk+Mk2l/i7Oi6XGwkvE5JyD6Ifc0l8
+iIBO6c0DixXt8Wk0H6+6WxFliWWWhO5P1UUsfx/o/JZJ9iprtPkmjEsfWdqnbtat
+q24OckqqqnQw+6k7EfBZHMentbUafUcOiqVVVYFUlFKKqejEY6Y+lfo+ubdLJdCu
+RFXLgVQwrGW3GIYJWGCYwwtWWlUskYxZ+emKaZHyQfWMWTUkP9FV7wTx+WRVUrZI
+0/KPlYWlUqaINRpIxmMlMfoeftr+7+JP2H69M/jD8xaKRKgSrdibLHI0VxjbdHGN
+jQd0aMDA0QIQWEpTRDGZrq3R00OH8GFjuAD9iwhU2MP6wiGD+jp0Ymd06Ksv5piO
+Uq1rMkwZkiw2SmZIUHD5pP5P1qcNmkgD9vum0hi+X4S/PJ3/mfi9rbspyye2Fk1Y
+tSqo+5O33q0nAeTHbg7lc2zBxS2K2xjL/dLmkWZGHQNxp9NkyrGxuvp9akHp3+A3
+ROSdXUb1air5yyvdI8km6PrIgEskaR1ceOmv5q4dpNp4dofKup3NzUTxsvxlZbZ/
+V7KshwsVcSqwxapT6487uYnOE9IdPT5DshyR8GTg8yZIxO7D2Xoe8wbPD2vkrki1
+J6oe6xXDYppjTbDezUkdjZXVjE75bVWXRUdldu05D4OvVbD8SxVZLZ009nJEkSTN
+7Y8kpPWH5pUvT49iIMA9AfIDJEZQpYI0oY5HlZOHxMMSe9WuihVMpamSnEH4RE9Z
+aWlkKsWrVSPdFT2zJGJOHBVlVUrpTJRywuMlV0T9myzARkClqiJX70kgpcYzsakR
+kiRXw/k/H9sfrouz/j/oVDN7/u1hxCRIRZULOfq+KvHsxm1M2jkhY7WeUc1j/ARD
+X9g55b0y0OAkCC5cP+IWkuBkJyInN3reK6uz5oJ3cmh5kk5SOROSWbV3cz6GtQbZ
+KFKWuNFtiyrDpfLMzGSYWFVpVVZYebEEsBqBXBsjMbarG2x/fZQ+jLYbHHqNwzdK
+EarMZjYxuuOPbI9sySN6HDIRKMbSRBlKUoJjSMbaV15eryvBqvJXDYi8l107GrKu
+rrePql/G999PfuvQQNubc1orFGJnz9/3e/n38NvhXHdrlX0hVyULe2vF4tSELMby
+nXaVdIyzVzptzbpG0kYyrYmUstRUilMV6qhiUaXUqU2t22sqVUgIrrtLQ1QdExSK
+lSKNIKNDYBCEhONtcvec081daISsVrnNwhsmVFh9UnkeSpU/Ucu0cHJG1Tws6MbG
+5/FVq2qhSlIpMbqkdPrfnJsRP5LJP3kl8j+YotqNDkj+2rYWxbJPER5OzzamSJYm
+ofxdXtOqPt84dU9J+/4gPBe8BUHiJMP6uXrNpwqwttVSaxGF+jEifCpFfxSkr9mc
+32c3S3Szbd2ZoiFIb5ZGYtnEkdJ+Try/CPL9Mi5mMdh+Ug/lZFsslk+ZJ6Es33Tm
+ZHKzR+qo+jHqk0bPR7vVXJrn+XaeaslpRZLB6fWTy0fm4NJO9fzVkjpKW2+cmMea
+KKivw3yNm0nsxo0qY/JPx9o926TeJg2Itr4mV3UibG6zyzGVVRZRZzUmJYrYjeJP
+tG57vdmClZ7rv1y8228aKmVl6+qvZfKRcLOG6ldOqd/Vu6vnzdTvHSaWdJCUkjhk
+kn7Gk+eiZHzRJjshqSwqyDyZ80X6SPqx722PQanWebyOhb9n7djstjZ4dY2OQxL8
+hdS7hgfQ+5CDkj7o7K4g5yNpyOpPqRywlpQRSDKSubGQjFYyaHIAwiqRam0sMSLC
+sJviL0yJ2OkeKEslhZYLLIdXuqTrJIqKaZP1acJCcH4eh1+kfB93b1WTnIpa+SDt
+JnSUSfEhNliaKTnK6bk2NUtOpwxwxVUbNmx5x8lIqppySP7fkeJPkfA/GZNlaB85
+U/xOGz7nG7VxLbFvOJRc267dY5TS32y82q967Sok5Aw3FStphVLMYoq5nJ05S7XG
+3bTWXLtislaIjwcKpUlVZ5bNl3MjhW/1ibOUVX6bGO9ltr3qNM4ZOuTmdlJHaTrd
+opbJmZI0WRqsr4Q/tfrZ3oi2RVBaIqi1MzEkmVJ0pnG2r43k6qGCL9Kkpczv4SeP
+sFeTIEBc3DtAZcH6XxGW7Yaw+DznoSqyrouIMcMHbjD/FBny/X179rvtjikQCcgQ
+E4HS222zVI+KD/aP1IS0pJSBYzn2USdPSTTu868arlGQodZ/tyxVyU5RrlBdEqjR
++4KCHQDi6aQjlScf+T5kjee1Xoxo/SOOyTCd1xDlX+YN/MVvtOj2tXZXckMqqZHZ
+EKEQlkdnL7Jdydlgmev89uU78j5cSJ/l8dkmE7rhzD8qadHMH4jZj3nDGPdwajh7
+sMdnVu5ujXXl+T1/u4LOHgw0+z8FGBY2M89iIokYQvh0gpDsMgXC5N6MMVWqIDKF
+k7Bhi7LCa12ZnoYVi5gcGP9X5TyVn5jjpmK38e0H0yNy9sy6krJx2NyXEkufYjPY
+35HJdzHaIWeWpGch1C2GpaeIIyAyJiVK/Gotmvs6vH4XixysdNfO67ZuafPse3Xt
+czmeH1mHV6i2qvNHrsuyeFJj1OGjd4Zq4YLjGTExlUsVV/xcbG0nNuxlxTLllUUB
+hE0vYrX0AxuvoyLWYktLUDBX8H5cYsLkOfeXyz9A4QbZ7J00FTnG94VNve5NkYen
+LptnR61av5SHOPZVdEI2fk5/k3VxOX5PckzZv1ec8TchyRzOOqs5zOUkm0wWPJVW
+TC1sxMVVTWOfpWxnsx/JmyBRsFWNsiIqoVUFReZrK80s5jqpOqvOS43zEuyOx1cp
+0Y8OhOW7ME8lk6LCeFLjEsFSqpSyelXJhXAcdpsp0Y6/OqpWhUMVm2xjyTgU6nrw
+6yszFUttktLZVtnXi3kuDRtDz/sJ5OxXV22LVZKMYxihA2Q/Dq/NjZ+535t7PF0a
+3E6sM0t90PBzJHT5SRrz+MtSHquWXGSMc07ChTvJ7sjSm49U8JK0NlKrXIMbnnPC
+0qUqjU5Jxyt7ynN5e/kM7y2YxjGrVeTE5xqbVT8LiY6bpo+ZdRG82/fr1m22xZSB
+38PxIyNMShQiH6G9hXLOZK6w3N5+X72HFAxu5NSfRpW6afRXqo8VJGH9x5ObPuVJ
+QLAiFlH6/u/FbMJ3EnnDq7T0En449m8JHNPxcyzXSV7BCP9JENSIjTahAiKfMpQX
+fhvwg6xjTyfA09UakjGjZSMkcm0k69uDQkz5aTWCW2iz7hlcSciTjD3IoFZBYmNt
+odoFMMIkDWQjASGk0NA76DcIySAGLYwAZPQkVbS9raOCXx0N4NPJAcpTE24YEIYy
+g7CfLWmi2E1TDcjdkTMXE0qKsqvYI1Rc1zUWKjBt3dZMYLSc1V8teNrSwW867u67
+u3XWz3uiTDJ7uup6aktGEa9d1hTNubvV2q883d3IoqVnZHRyRZT547K2nlbs57pm
+7cLQoYwF2iZPBBH+5LQ7dYkkhI6u5sNK9nPxux2bnayrYrkTq+u7erJbBUNziMaP
+rppVcY3SxyySyySfFXkjZSuA61FVMKi5jFHB+UxNKWOqcRzfOSQki42nkQs97JyK
+5amm58SFk3LVSU0uj7SQfqwEfho1r92H6uG22K2lVz+Uf5sqP0dLN/GejmK0sxrP
+xz1m2/05yx4ONjCbJH9A+8QkhIqoJKiRIQWkkRKAK20HGfR9lFGh2vmzMyyCig/w
+mlAinByNccszHu826vNs08OjdXU3GzSpwG2/sZ6SHoyTSVw0slcGjSBnq4UMw08I
+tvw4uHqDA/w6OSCRnyIh/MH46rxmTFxdHacVc+uD3HvflqHvL7RI7e5edJqb4ZU4
+09uYztwe+W/IpAaOoyLcwQVPk3k69Fffn6zXZ3kION0cYOXDuS+3vzTOm/K7Mq6H
+OlZUd7Pxxdl9t69NorsK6eU6442+am88vu73UsgRoV5Z211tTDr33RPyM6/XfL5U
+EDhtlOMGIOhqVFDMLDExeDQGHON0fZdtpnTpZ6cD6JBkGJpUx0Y0WuppUjCvDGzH
+Jsmjd0VyNNnRZ1Y1MNHaMbOGzcp3VttssZwsk0gsTGWj6gLXG8FJpoGGjp6NmZZI
+mQYvcYoaIEFW2vkM2ui4SWaSMLtv6RnW2Q1A4FIHgMRpRK4eNjfwZ5oqGaaSMo5b
+dknhw4SbOELPGyXLyqGoGSSqSomY1HBBVkQqys9MCWL1YjTEvrT/lW/HvnSpG2HG
+W0YwPtoufZQEsPWkFdi4q6Bs3tkoppX5Eiaqo5JX1UtH2/gzrxnmXNzE5gfF8iGh
+wMagId9OeGfjPxGKTtKHVVJ7vT6eMIaVB+wH3n3+jxV4Svh6l0hS2vo/Hxp46W8T
+mStcsHMrio8lNypolKYqrT5AyFDChtZGHuINKBspBGKg7kJt6Bo8fNBswFHISJJt
+PcLdHk1+NWshZCgqnMZITrDX2VnDFGhCe+9um2kaWy3BLFDrBte5ISqMa3whRNX2
+hdsSnCgdmnJiwaaFmqxgEhoSkmS4W5nnc2pOkjMCi0Pn4WGjUumeTCfLJJ1jYrHx
+jaFRrCj5qXWxkTinm7fk9Hu2JvELPk8MMVKpWKtKq1iVVKKUxXlx31G9Tw/vO6Mb
+E80lYmSJp0FRrDJyLJ51U9ZI6GiLTUsTlnZqBqxHcOldSSip2iosJI2Ehx0kHxDZ
+/AZNzYUGDTXrMplachkVuS1tsiYIYyt2mzZDErJJWTTEalrQplZC7YM+li2SUoxV
+VZY0yZkycNIiDcCJMaGNe5kXBpN+8HIUgoKqYnY1JISR6tshCE6JhknVjg6cMhWn
+JNlbSdppsotV9zG202HYjiEnmTz+E7xXhSrLv5ZtdazVbW2hjEYNKDGEBkJ9/vy+
+vnrFURs1YvpvLuyE245w0VLL1kr7cOg/Ba/Qf0QM8JPxZLLOStL5KZ+faXr7LE9j
+17oH4+OiR8orIu4h/RAagtxGICYpOWtBCN8eXMu7rl485VKQmKi+aU6rwbyfLXpr
+161+qbettfqWN0pL88tJbgpKWur4a8ki2arIszGhZJVK03h6o84nieE+RSDA2EJn
+ygppzrRHjjDHHjQ3oAGNIa0QIJjBiGd8s3glSnsMZSEY1I4BqCBOrFtgXZ7YoGff
+5SOeYkWToVOR6a7/Dmyl7pPebOTUlLEYebR5Ikzr5O+azEJXRy731dGOXtcW5mTx
+HG7GnHVxIbSbnuyUslYdMltVhpO7tytjo3Cx2IyGZDKmmWOxCaYRisSq0VhSVpit
+JWkrS3VY0DcaigxKkRFVBNRkkg1UhOMurldw8knJjznZobpJOCnNMtmM9JI/gses
+Dl0es/T0c4b+aSO5yy8it57PtER7yQ49svq6K2KoqVhjFUqmm02P9rP+enbyTaJy
+k7zyB5VdEyRHyqE2jlT/N+4jPJHNVfOPajFtvo+bRIhxDIiAREIBEBHmAseJvCKp
+aWSr3OREAnaST8LJp9TClbcGN022eOxs0mObY5x+f0+u0ck5RKKUopJrgB87bebv
+yv5u7W3q/fvzQ+JGypskPUreRLIrmybatMsX0a/RksaxtIKIX8sn739qsebzOZiG
+by7s3vdaJR6Dj2macG0WSRT7SDN9KC4xmGSRgRYwaf7MbwGIOPrP6Rb8N/DY1I1H
+JIkrMaQbxJHdIbifDkh15l2d27BHRHVPKch+6RBzeUnBMtctc4pKUyuu2upJrlrq
+667pW6+1t+6Vk20JkkpYV59A5unxbofu3vn21Ey/s+HYx9zasPu1JNm5an1x85Hp
+GG1LFk0RAJ1kfSK+E9UPntJMsjrKWnc/YuFg5pe8Oyx5qIpZEbwKh7e7yTBhymws
+JtGzb8PDzkfvPfLZJ5yR/o9pH2H9KqdtVVX7VbbWI2Nmr22lllliKehVTXVI09Cd
+Z/Ou/e1aKs8lfvPiSD3/Bks8PeYcuVmGgTKW2WyVY/isZRxJN2T4vyfP0vRyfZZK
+rbaZNZsTidKX8ofEcnunxzNEJWu9xbuQ3w1er3T4Y3g7/gteJ4WVbTtmn85O7lJ/
+VEnkTJ9atqsYYYeujDUxIwoxR56sknNj7SbuGneRs8nq4fJO2cpuiWKioslVKlRS
+pJZ/ULtdlKi0b+Z81+yixKtJIPDdvJ+LvDu0SyY/h7/w/FiNs+mias1cSpOznIPK
+yrHt1CY942YTzH+yrZIoqhOEiZIT845d3T6Pps/6Ofl4bEm9vIZB/UJBbEtgRgyB
+QrgTP96/o80lj8FrpZ3WuiX6brraSSqxRuxjTFUbWarrGGKMDbBcSioFSqf3ZLaC
+XBlKqfB9CZLWcmutdlVXXxEzqHZVo2a5uZjrbE5X5CvSKi2WpbDaOR0OqaV2Vjxq
+myEND13YGGgTBqRBqAkgipVktsk1bJm28lu2ll5dkUpklpVLKkqjThs7SaJqeWRG
+VasWSxZLZu4aIgE5GtmzUkyWRexTG+WO1qi40I7X+GXLi6g1d5IU5Kydn5ZoeE4k
+iNK7HJJHZ32hk/RzVTRzKwrOelrcXxZCb6V8ambb6i+3z7g8vV7o2qRK3bNfx+d9
+az5ZypWyvNOJkq2zTDGW3I2kxsrRVg0qaU6NmxvJVssZPf5Ch3jJZiNskkJC5thW
+jziKca5yYTlK0RAJy2l5f1mHrY2Dc6OkI2TTTy2TGVsRATPxGssjZRlnpIg3iSRi
+xI5OR2SOZJPl5/ncvR8vln1Y/uaaeTGFSl5VO11Z1vnvja5W9Kw09ahkgtDDYyAY
+Qw/WRKMp5aFVusKrZpjSKdZ3v58tazxmJb6NXQlD2AabBtG1MLD6P6xKQChW0XsB
+77Y5z/JBkkMXpKgXiWquYcP3Pv6+I4oBI7HediIrxI/Ei95EsFOQPxkk78pP8rbI
+tJ+v+lu6eiHk6+Kqz+L5PSR4npITj7fgsgl+q1VWGLPweJJjUnC/Grtc/J2G01ZT
+LW5ObQ+bnkr8xJ/5P/vSSP+C1jG1YK0Y1sao1qoiqxtFbG1bFRtUa1sVo1trGrG1
+RZKNo0UFSilTNtRtGjYIEClGbbBQhUJBpCDY1o0bFbGCxY1MoNG2zTaLUEKzFBMN
+tUbFY2iqKIjEUlZKixqNsW0UY22i2g0agirFbYrFtJiNJbSao1sWMUUUUbWNslpL
+WNjajFopFMhJGxRRttjbBtYNtoo0YrRqAKKLUkmqi2sSVY2oNFaNotsVoyQVaNGo
+o2ooqxaNUUbFQoYQ1o1WLUG2xVgybYtGtFRgmVk1iqZFQlJrG1sbWTajRaLFaTUU
+VRtSW0bVFWxasFWIsVosatiqii1GLaNaNGpINqg2jVoihmxFti2DGqiqNFrFslti
+qMZJm2sYTbGLaiKiNYrRRGsbWLbQWoi0WNGo21irG2RMpRo1GK2Koo1ii1i22C1i
+1RqA2o2jbRRjWi1jatG0lUBWzNUWo2xpRTRVG1G1Ftii2pLWTahQqKi1otitJqNU
+lGjJNKqI0Rq2i2yaxjbRqMUVYjQaKwVRtFjWiCyFiKsRbUWiosmsaiqjY22iqLQb
+X5/99f4p/uUf0tf5/9K/qseg/3/8O3Ejr31kY1gc5A1pvXCxCkNiwvOQZYLITeUx
+5CNobGwqJ5o3bWtQ2oqajkZRrRj1prYW5TG2RkzhxibIud1zezbDrRBn8s2xsbHZ
+Ilaaujw873Rttris4cJCx42DgiHZM67LEm5mczQU0zdbGxtvENm4RY8axrs0rvvB
+2Lmhu9ZH1rnXlfnhQMwstTWMgZ24VXZJdzdKmphdlKOvHF5Ypc1co3WpPG5UchDH
+HthGXu6jHcIFa8oQrWt53ErY2jQyDFGQGaaj15BbvaLTDPKU2xY9Mj2zrW2Hba2J
+jEwZb1mshmPWcZdXPGGDOQ4hqWsZbxqyLQ6ysx+Pu9UmOHJEyavWvHjbPPnsX1XI
+iq+W3w8Tu+Ry16Js2+QVNGKUjZLWwXGBxtiE2hFTSXGBGkBjMu6xtIYNFQM1yBbp
+9u0ksTStorHkolJ3E5XN5tOFjhjhwmVcOxEtLHxyyr7N9lk1DJaN0qwpiCBpBAPG
+3V0ccPvd0Avs82rSKmAnj7RQAdYSdYbzJjI4URnJfO3TT4xQ26ahpseRDUtS+MKb
+aVjQ9wg3lnedmecmuQV2y44ptKaHyuZcF1u1JXKJlu6pRPSTudsbp5qixXfWcnpx
+PboouIu6q3vjI6ci2PuVosvF0bH3kaaLyFWNsiaLGxxWqGnvHH4d8MyQpjfcyGZA
+6+PHVbTd22SxshNhjBvMiBiocsG2M5zFRj1yyQh5C7vZX53zDy85X19hw6XAhSc4
+4HRB2w2Jzqalk90qqeRM9JrLjIlc2+tvhMyT2eUuq4MdumMqyCenJRHTk1OZudfS
++VfKOcyA5HHezeQrJxq2piOM5vIJjY0fYvMt9eOLt3WsvDtG97S85zOs8DAjs7dX
+vmFFxB5l4hvFFWKjG6TIUmyWmMme3cQzNyatha2CUx7UUluGUDYW7GzYGPvUZVUN
+2QruGNDbQ2NtNsoEDGs5S4Sw7tuXObFDTJmQpdzuUSm7gDGi7IElwyNbNWUW5apw
+r1xMC2oS5tUYZA2cHGiAzve7XardJ2IuYysvZR0Ku5Ck+2RL65bzSHlFlxDxNMK5
+TWUzcfeFomjrOXGkuCogWNpZb5Tmyes2YdxqRBmU6GoIV0TPJNojDDaqLiTC92lI
+44VORRdd7f/n2zez072fHsVc0lJBrBTJO0dTCCHBnnJ7l4TDb0xvuQrWjqhowcNm
+KETZaeWn2MKO9JNMjipkZF31GWlSxcYpJydb5hSnINMGPuEOnRLL4UV1hvIPGKBl
+ZvS4ydl0W3uRzvMAxgqY2gIYc5EjKevtHG5vkRZfTi704pm64VOlm9mnddnhX1d8
+i11nlLfO43hvIUvkhnaDTed1UYzb4SQy8iOZJY0OXGtwdkbrl6UMLqQoOxj6wqcm
+67PRzUcwOOdgLJgvlpWuyLe1MNGlSR9cdZItEm9xaWRy5l21raQcOMenbGPjUtId
+5L5rfXWQr2NbGd5BXI6+tVcA2rcJgTsa6HJhyR9JZrTaSuTN7tG94c7fN54bJ5gK
+AteSmybgHEB3lSGHTGcmecrPGjWNw+WA2uNR0erioM73usN6veTkgxmQtzC+7W1C
+52SQlmXcODt80oUQQutphmedzHoa0Pb5uGiUik1kXE7ZGybH16ydOZNOpe5Sgesh
+jsIhgWSTnObvd7JYyX1O5WwQQTtFWii2tYujUsWbw0ezmrTNw5aVPbIMBpLsctzL
+3e82boiMG5yOnOmm8fMsldyWw025uHyFFYaQ8uhZTsWKiNp8JA35OM6ztkc5IRzb
+yi5eshOO7RfQUENxDrF3qvnKutTq2OI2Axlgzi73va5to5kVtHbQ7Y32Dd1k3HCj
+LIPSN73VuOclVLYXpmseBJzbNvLSDWByI7kReScm2jiac6ztXZGkbaiCAyO2QzIX
+Td7J06xss3ieAXL4jMoKMHsszhnY2tu+PYncmERURzYjb7rVmXU5FSXuzzzvke8r
+flq8UMwGzmKayKZkWIVa8gdUzJzlgqDkEC5XJt6MpysuebzMk5crS96OkqQR3Dkz
+ElgmcLoCwfLTbkIR3GXy81m+S4PlrND69sIGpuN6O4g2ktmwgkuHKu9wyznIiYqH
+xh287t87BEPFkERt85JvWK2OrjtJEX2u3Obs84debd0rw7zdeXMFzOZDJ3NvLmvO
+W98l52eec8Ovx3URCkNEx+BY1uglDVhy3y0UPJcKyiDZjGbewQ+bM3Edm6FJOvzz
+azuclkGaGMcYNlfJEmxcZb4M0d5vObBOO3PN5hD0onSZ5O7GGzFbRbOZzlE2Rhka
+wphx0zrlixjRccimW65Ok1uZQ8tkA7rSLGbUGzJIZew32hAFkPnNVhE9MqWiOw47
+zozjty6kNk1N83UI0ZAZmzwzHu5NUqQyQow0vktdqtUDtNuQOWVDBrlBzZMzs4tf
+bbgLjvOVlw1POknTok9nX1y1i108eGb3lqIbyXdFm5ZQ1N1rdRtQsbwYcJmHBeXW
+2qMDeacg55NcqOxlx5mVneeFYjRYeJ0ckbFCkO9HPGh6Uz0YirAec3cAaT2SN9TI
+dhI4eu6xRjeuwlnHtcd9I6I7mnNQujxohaKtvuAQd6d17CIoMjnTcYTJ0gzDnLog
+y87zLa4RIWrjb3QJV4OaRG3hmhxMjBaozkkzdTcUbRtJzGncsju30dDubirvs7xZ
+JuXdqYd7zsWQFdt5eUcWbvOEb3hdO1zObnI7UeWd7m7t8zw5eWdMmpq9lvkl1O2s
+33XNPfK3sTSyZwcbL7OVx6ZFd7y47nYjGcfOl5WUbFK6jGO85fdlu+Oj//MUFZJl
+NZf1tARwa8BV+AQDgQB3/wP+ffir////pgsXwAAAAAAAAAAAADkAFvAB9CgCqKvh
+wIIRClJBQGt931KcB7ue29fOM4xl8OCCgCOsAD4gAMCCqAgigO4wANPNs0ABQWrw
+W94D7vhh57CBAWsPbK21bY1p2NSlc29vnvroj5VJCRUilcbPtq+nc7762bq+rYxo
+GIRFFTW+199fPB8oqqVSlUqJfA6522q9YIUQr2e0dTolBEUApKpKdxdyiq9PcxXp
+pT7XA1zw2DoUqJQtbhzOqiUFUEnrTwsJplFOzKlPLNubxmlvLabHh70vPbs9VSlU
+C2aInZnWUtKa6kV06iV7xWDfctwDvZfbVSHSMzex1T1Xu3dbtgdcgV00eRqTtivM
+xlkDWp3c5VXc0tLhitmrNiVChF12zldtJ3W27okKoCs8t8djvZ9jdAPWi0r3HoNJ
+bs1XKl3dVs7jAPbHmZ03gFeUl02d2aYcR6bmqg6173G4GXhqegQBAgTQSUPUEGEP
+UZGTAA1PCCSJVT9owqPVMeqfiQAIxGJkYAEmkSIQjRRphCT1GTygAPU9TTTEACT1
+SkiFPIj1MSaNAAAAAAAApSICIoiTMqepgUaeyoaaAaMgBiBUSIIIgRoEJkmqaek2
+po0BkZAPU+d9mfOtn2399/UaZITRTREBAJMILEUSZiSKkYAEmGm0IokQKAYlDGAS
+ykCCmWJBQBpkaKQLBIiZhJpSzJEhDTRCEkUETEKMxQRSIxiaGQREwxpZEg0KYgAa
+EkAGJGE0ilIIhQZFLKTCMSQMkBYoRIUkFIkmkQMZhGYyJkQwIUUkTQwJslEQk0IA
+pAEEkJCIRQLAGUhJM0NCzNDKbFlk0QYEaSCihZRNABJhCZRFKJFkxIKRmDJEZZSi
+mhJRNkEjGUIIIGFMpgaQMaSRjJEYTCYoGlEQpmzGZLISlRlCGEIIyYMaZKkpiCNI
+jIURTTTGkmkaGUWKRNiEM1ERkZEjIyMxIQJRjBkKTBJiUyzM0BhkLMYkJEwQBQGh
+pGWTRjKIE0SYCUjDSIhmGkyEZlMZjCAYYkpimEBMZlEghCUskyWQyUZiGYJlEmSz
+MmKRiQMLMxTTBlJoiJphJImIigzIpSYzFIo2MUASSpKIRJiaBiFAGGmgIUlEgSMm
+BGIZqYzQIwIpIljMJIKSZE0FmAxg2IjIaNLAaEhIsCyTEgyGYokNMEzTMUiNiMNg
+jRMMYSSQQhMghBgAGCEoEY0SkZlCiRhRQSiZEQgKMGQFIkkGIySy0CZQEqIshpMx
+jGSUUKGSQogUJJAMg0YhCooUJTKEgJoUopZCiYLEUsIkGESLIajJokJjEQJgDSli
+QhGIaADEBsWJJAYmkoDQjIJNCNGUEwGZIEkqYjAsbMbGjBAZkgkBKRjQGUQQTKZg
+ymhiQIhECNhhmMyEMgjBMYCJTZBEhSMpk0zGlEyZSjGFFRQpIykkjFCoJoxhpIQS
+JoRZIZMRmiLJEMwSJgibCaJghRAEyggkQySTISQBSIJJMyjWKAQSQKQYKLDSDRFg
+gaYDJhkRBqJiSBkSyBmQJhFNBESMWJkmpEwkjEQxQomI0wJiRijNKCQQNNhaYhlk
+whhLKEYJKExEESAzLCSURhIAQIJEpiQklAmZ/txdd3XdcOzl3Oc4ca53bsdc53c7
+k7runOugoiVLVlto221GpSpUtitttttEqtCirbVttrWLW0VsraQEkhMxSAMkmAyS
+CjDSRDJCCJBly6RMJSkkEJIMhCAo0wEkgYIkQzrd2YCBRMZSmJTCjKhmJIEiTDJM
+0SUsIxIEkkRTRMyEhJCSBIBsKBMmAohgwmJIkkCQaYkkCGSJkxCMCTruhzdNjaVq
+NGI1qqn/H/D+f92/9N7/nf+x/T/BM7+j/3Df5s4H91tC/+oosD+/gYNHpnVNy5J2
+alEaZU/66SB3/PXf/7//et/nu+/f9KKr9VSKdhIptIjKzARQZZiqimGUFLMlVWMj
+MSUU2oif8IKKYIhlVIpkBgFFMIYCimSU/8VUimSiVoFFMUof/mCin/KqkU/1/2/7
+ipn+uSn/P/jZ/qZLjiqHKWmltwNK6udN0mKLpTbnFbHSxf6h/6WePKShwUl1VbdK
+GyqU5ooa/vt32BeA5cSpdlPaWguWZVUxZht422i4WJpNsWzjjnNrttYxBLESWBXA
+to5UMFuThmsrEMqjbDpYOmG3M9440VM3kpxzZ0ZLjiqHSXODDEyJisUWWKaaZVEW
+drHTWsbg1ZFVRmRGCMFFhITKNXhUhsLAnAXFVTa2xYZviazvp7z20VOkudsVqq3j
+OeGtvWOVhDnvvuoOynI6VhVKbaPHLclddm+VRwsd9tpyhwG6KG0tNMuNM0w1YZC1
+SUMAuLhnLQOupddA65UOXPDKoZRXMpLJUsrlyDY2utozHDrg6uimKZS0WgtDKos4
+KnPMppbMLnNIaySc5TMHGbaxTuqd6qpHacO527Xh33/xUTIdWeKTmjbsg0PYKnmC
+1lVSd88uqKGOW10E52BMkmKtkyldBFsScY1nFJZktZQvRzSd5S0O9PG43nhMOVRs
+OXHDbwU5iQ1kkWZEeZGOqNqS6xHOJZZIhTExGkq6rcObBbGrBOaqc8OmmJTzI751
+Vi7Tx0LbY0JUgoOEmzhjjnptxIKus546uBtXLO4JkyYP+eAcAAHOD6fr9j9V+RH2
+S/L/QXTV3dz8SL/T8qH5noZQLPqGwlvR6dhx2TVtfs9W4cn6VF1Rfst5hq6EbM2q
+dokF7YlT+AevC278qkbLKawmh4pJzRaPv9leNe26uHhSuwBuLK+a3xCu7uCt8ICc
+hqAubTDuymwW6zBsaun77TDCZizuwBP7lwSttmpSykZaG/3IVw50MThjdLpDuH0k
+DTDN0e2mvqqKkAmVy9EDwysGysaREKB2NormNHUwj0vgO6IiGsJpEuyQETJyWsUL
+zZWvlFrieCawpUQgzlKTRwiZJXKyzbD3ulpxiGZ3uqqknBCteytK6wxraGufXo4j
+6Ql84X68MHo9PTm7GxF43W97OVuPemu2nSInel9rnXmRB4ZmN2FaIWPHWBY1gskI
+XduCgbTFmxaE5YSihkBIUBZk43EhJxOAqFTkTEgZg/58BOXSVo8zbqfJfApfLFzo
+w/f/d25jXyxD+I/OeU0dcx/x/aRkaa7TXU9oVlOfGYMm7+LW4ifNnrp1XifHFxMu
+5IbmiCprTZzImVSR0Qa8znKbkRuKQuyr1cokqPHOIDMit4yc4kkbdortTU60qgIp
+BnSrVsKMeuZ4NPFFXo3ratpwLFLGtrbRUbc6dxjlHMt30iALUHtqu5g6R2+W8fwX
+w/9tjnDISkwpFIFITGooZI4IpEG2wm2m2Gk22+NttNFNpstJJJJL4r7Fo9BaHfpy
+dVdT9v6/JXtG67C17waENSlYvNK2F2WomFGFDQgRHIUKMGMIWE4Qp1LPYVOJ3ajX
+ij0R2SiUikUutMpXscLDown53VRa5NdNBc3ojNNaETWjiHFD0SSCCSSSCDKT2PSI
+aiwTiy0mbTO6iKbZNVIZ/GZuWsmDvZ2jyAcoTPVEi8HyYNj0fsH+BpVN61a8JAiY
+SJvPsFnwgTI1HXbhbNF1FnpCTeho7rSi2EUjT83q/Cmc4nETmio0AIuw3CbLSbKx
+plU6HxSnZ2X76jMxwG6zEfg/GT47sv4GvUeZiImjSpzqWhp1koVUQmYgZfQYMrIw
+zgqXzPClmVSyPgXckhxZXzdVcKyu4Qi0aa7hpB4IJs6THDITGdymCiiMCFZjbbD1
+Zs2RDWNrUlQ/P8x6SH7v7Pz/8fq/1tn9U3lWuTf1JnUUMBZ0zXwlfGtzjVdDGdNw
+/Wb/TcYvZhOV0yvddt9942XK1inv3hKPY1yG22ftVJYGIHecMa1WHrVRdWNFu82a
+cxAgPKsqap3SvCX1k9lfXPem9N6bX0uaUbPfM+K4StqpjulMkJsnYV74vTdMY1Ed
+oFSIZ4/h6sOvXBROO5iA46Ydg4cPQkTnMmYnMTmTOZL0JQOVaKsWLsGxYqhdCCQM
+UGxBBBEJ7+U3578j0euaooSZ6QPtSOwWKBXnFoZlecqTfq1/RtQ4OItiMpbHqNXS
+LBpu9xQ9UiKIOt8lmoPPrrV81xoI5KWxvXhM3vY8pR7qqK4YLstYwxOVYstg0KRO
+i1fLX6rgTrxlmqlbrkE9LEGeIed9k26rGnWed6Nh06p11O87aBEwmLoD3HcEEAkE
+GRBBBBBEkFZVQUUkTHdrccRvm2/fthj1pS2KWAbKGFox0dOmXvOlr51nWKGJum43
+BBBIJBq/KsYn0ippp9W01W5ZRjbTSfDNkM7isVOp5Wk82WrJNLTsbRZZzsMYDiQS
+QQGRB573Pe988yZmZmaB0HgHcz7ZHJKFgkEgyIkiSS9eHnk2SvPDryK1aqqqmtW4
+PSycD/w8sflE+v8v83/dyIplqpb1llszKa0Kl8tWXbMGzMy8XWnF0X937o/wO4fq
+0+r7tk9qe2FJ6z3CkozLYqzEKiqUFDKGP7kqsHaWq1aDYcCQokp/eU+vt7uZp4fD
+vw29FcKUSuratW2rX7I00/UcnqCIfPyP4ftqCVUyNaqZi2P7Lo2/nvtw1Ntxu2Ov
+M1cLOMOjTdl/Jw/jqwjhrHX7ljvTS0Ng9YWklWliFUpZUiCjOKclNiKmjWdFMjuo
+dSAo96JmslmGgyCeUmmjEtITqi4DqWXTg4318osVuX2Vfa63aYJNvvZpHIUVXXbr
+pPMYqxKrXRvoXCGuFnXhSb4SVZtAm6ojtvuIBkdOcqdgEZ6lcZZFN1kPKhJJhRBr
+WEQyIWkl1hnFU3uys63k4eJJlSIMlKqoErDI6G4EEUnpZfaOrlixLp9DvOUpB4Ta
+n2/ZW/q+fvPhH07t9H4MT16XESiARMKUE/rVVU3KNwDooJ7dlAzgnD7EhScMIYxZ
+/mOidHDestpVUIAEgC0t7/m9fLzzvPVb1fK+s+Y+f0Pon6xzJ9vzOD8R9GeLf1T5
+3aq222kVRIqwftW1VyfHRO+89MPe5zaktbKQr49+/jZmajwxNu3Zk7fVWkSWG+K2
+a1xZlKFOw5BlJpDTgyzEORiGVhmzt4tctufPV1DsnIxdsV3SbUdlXBrTgwnt41HJ
+0263X9faPss1y+iNSMUfp/X6ff7/6/TW98cccp1bYjhzq/3uXPJj5bT8/7W+nhNo
+/69v1+jGyfY/aaf9UV6T6SQPl1Bq30rH6H4yV69J/bdqqKoSHon4AEpmUtPAez+t
+92Y5lOj2CJ7CYdkZxf0D3R/XfsuFMS/C43Nv5T9sfMZV4L/G9pvd03/3mq9yzlm2
+xVJVkOV0LvETLzsJRx4cqu6dXdXXuPQcCHb7ePRk7He904sDcwdra7Nt9q7VFY9l
+7jUQJW14xnuJPn7/TMw/3fPn4+Pj6o/Cx3cXKtqlrD9PRbmYZme3mP9E/y7G36I/
+LH+Z9Pht8Afun7v7tJGbXiaeU0eH+Gn5fst6/K+NqmUrWijbu3DZSH3hD6nZ+o9S
+qiIxVVjIQnk5/AzMrhcclKH4STg5bfDDGO33aTpJ0rlQeHwTE4GVRAlhOxMpdgNv
+3ajAlCIVM6Qe6uKg9yOwUV9eRvl2dAWQKng+meXZoWhDqzCyCFDwHzqlW653rPFy
+aXH00S9/SI7ZIaPaDOu/U2err6Wt0/RGxFCJ/FfXywJ+Z0NuUscckrzN2LlS+4To
+ymv403aBj+06Tl0T6Xne5mhKZXrsbvOuKiXR7e6HiOm9CknWsik7Lmvsvrn08oTa
+aD3VS6R5uebW2codGHht9KN5dWRYyrvSKCuOIvhyuzboi48y0eX0b1ZEk7XR2mzQ
+lIxgob6yp54pmGTlmwZ30l56vdry8vuvXD4hdHdkDKTAhgiUo5KUmzxNmilIqOOR
+j4IT356J9N4UeHHbOSSOyBPJ7lSGRJEjG2PX7P+mxdE4E9kZhSbrNHt+LR6oxuXC
+xtS3UxPlEzA5XpdlqQj4iqskZZ3pmdTpI2hJsTma3b8RF/EoYxU2m5oFB5TT0rss
+2w8zlr3Bw9jYwgtNtPCzmmpqJwmZzfsew9o+/u+NCiXjuaEvhdu9cDRPzPZbreMo
+pkxCrlWTi29L4pZEMIlfLbK+xSL0Zqy7IjaLss0ZGYsGcMGrgagM+zilXFMbIldU
+QarxUPisyxhSqeew68PlX96+Vn81ovsttNN7r2tOwJnj1OGZ6GmypFEL/OURjEXj
+xamLJXj4pVTillprNqvk5OqCY8vVrvLm3qoKGDgxzLgEkqry6tOg257kmNzyTdlj
+Q8tAmWAyU3697unetmwupGywUXVcTN9MqL1479u2I2tsRZbvyj68/LNRM01plhvS
+bN5NcjrrccL8Htyj+BCrHefe9PVPN5zrUH+1Pb6rXdo22uWWd/EfwZZbUr34gOaZ
+1MdLqLC9RP7u6RSO3a3RxXP8X0wBLkn9FRxLMv9CJEbYsiOpgpUSoa5GSlIQU0ym
+1JJSRLorCY+OqjQVlihaqBciZcOS7lgmERMS0iZQTN2xVFERDdrxbKJtzCzbbXC5
+bTm3j1zMs1uqI3AHShpYzQRbTYKYrZRILVpDLWCCHKKFK04Pz6l9+B8QwVBx3HZ3
+pHj9L3wPqk8LV2RT9q1kZcelVkMztswvhMxRjp826SggOKFASfzLUZH+Trbl452C
+rv71T9Wht51YV3hXG4QPJdqV3uZz13mwrzVZnjVLbVn+YVe62EzchMqtzShLkKPE
+dMnTiMTvOqRJbzVhxDI1dd1rQhiTqmcLOhwiEgTPFVyLB/BYxVVJ0qTbe0X+E2NJ
+5FQil9Im2yK4hAhROqTbaIFD7Kzyqk3ny25Hm6dGXKvdrsl+j9LTNJyMbczUREDG
+XgVzlti/gxxcK9lmrQmuXy00nPZ1ZnYMCOztzV44ehTr4++n1Tt21RvA1/+natOd
++etlwD45o3FOGbqiF43Vsp2VA9kWCP6ERX78Jds3aZdJHuSiVaYad/n73gTnNOq8
+bUvQV1ck9/tFEv8o/X7P+1ZhaugDmvV+7UkaQ/vHB7fX5WVgRokFFMNzV0S7rpL5
+fPt5HpdvXdsa8XNCJ3dO64RjAXp5PJc5siQE7p10k7q5MlxQkHbwYYb37js+uXMr
+XQD53nebkY+JEQ3Kr6j5LcbHtxRKez7rjvN74ZI/binYF32Tatmu8Be6TXLsrqtU
+SyjpPtDkefbc/yap8EMZR59eNbE1KJt1yzjkr8IrBj8d5+WZHW1FCToyAsXOUEXr
+Wtq1r5tZb+GoluBz2+U8FT3va2RkKc6WR3ZeNn4iq1okKrUThD2MqptNGqiTJ4M2
+f9u45+/nwFAQyTz4I8lDKWkdQxJJEruEVFU6mHlMh/SyVffytduOEYY+qcVewuWR
+7sCx2jKWaQSEq05Vh2otTsmLP8nxVuGAJlL6CQ0fXzP22Mn0O/dc+RzxqdnXq/N3
+KIZUKGEwHCFgyKwJcqXSyY9+KkWLMIVwWZW84+AK/Bz5wnaLI44LmU90x/EkyBYo
+YS1EJA9jWfE+/5tRUV1ipCoof2zsjgKQ8vpHUIwQU4hNNSOW4tYulfaqfz6P4wYH
+GDM4DID3+NqN1ONUA/PfuPMRXS88tk7zKq/wt5RmaVy9WAxsjPw3pHVUomq01Y27
+q1V1m7Yd2KfWl+O5Zq7729d9zZ0l0p3fEcrJ5YgfbvWje7O3f3xZrowIWRkq4O+T
+FRyxJpiWo4lFPH3WrGdl4cvrRgQWOs7e+Rm7Fg5SGPs7K8wII3++tGhUMYuglST7
+5KtdoyntNOHVVlYkvFyJtG6k2rcPNYnRazDvM0jtv9e0GxHtPw9lbsVHo999iMnW
+ySQyREBBJkSLp6BsnvG/p9faVUKlPzdQ/ZVIRVFqLwVZA3bCzzChJo/VG3vBX5SF
+rWK1RZmzbONI5WDQJSoSvFrWQPYWLVWpk4wJi851alamk1f8QZvBepyqUITCUW1M
+PO3E+bYpbGJWorqrG+spHFPy6ovW+piPxPDpvMK9cLBMXT02D897907tO7q6Tqpw
+mu19VLVj5w68m9aLxrh5pRd60Z1Y7OPlnWyT67h8VWsGO4nUUKiC8Pu5yxhCT898
+xuvPfY+fhoRK5T5qvf5+ore9q8fDLTyk2u/mia2vXGhbTXwjpwro94vOKUYpdrNK
+/ilIKJN59XedxQPPGvYqUmlTpq88kgneW7DHmiG23HMo7Zsh04+H7xMdo7xOJJtY
+eizcYZdt7XbKVK6OL4vQLe/M+3jq86SgU5889oFKfPVuxF3wlFrkIun9efjz79d+
+wYeN/C+u3m1rd0jFGq9X89KmLLXN2C5Po/veZd64ndf3MKIxsceKwWTeL7MD3i1L
+FVj6xz2pzr8QKCFNCFKpIp+xTH6JnyBsNsPitQloYgqd1l5g4jhq6cPDUvHlmwrI
+oOhRQkOJcJfIaDs0KhNWaJJhi4g5WXdYcDKbkpiy7o20IRRpRFyOFooQ42GI3+Su
+oMuUwozR5RSK47UcIoQsIwhhRiAXHRoVM/c+S9/l9R47JC+j+m/Feaff6jz8TUQc
+fBu36cbfXyrsgqiUIyVfLNwCKvgnlBRwKKm+brfbFcOClV8LfTPJElZDw+Yw7n3R
+/39I96pWacn74akmCfZk9N7Hnbmfnm+G9N9IIVf233Vjv2K+dmOqXTgm/cpSxjx5
+NoTM+aO9xtTisCE1pRXSdT2doOxqKdUb7MQGth/hkgx+xCAlvCV3TRG0Ce6IyQW7
+O5ROkRaOiwj2YN2coi/fFuizw675bLOfJnWg2VO7rRIEXexnFH3XUPPfxRcRGzXs
+xpAtbS7eu63smcY2W+6RTU1psvDNdHE51pxd+N1FlWJbYbvu4qRoHx0s6pEIRV8N
+xbCsclUVRe1t0Tr9/qt689+zMRbOMBXqvBVD8KyFEO9HimPzqLzwaL5e+3ZBPN5Y
+7c/Kfp4kQCKdTjmOa/v154+n3TBe7/D3+v6r+/voinkqWoitVotACCo664ufF4Po
+3J6cfruz8fcQTLL13Kd1yNXLle7zzhNiNjuuwY3dvT6en4e/3/ffT7fX3eKmQXX0
+/wDQj59+yNfHDLb2ngE11HTs1D00z1Rmnx+dfhwbhbzuLp0qd0QHMBspKuzzC3ON
+dfyL9+3rQfBoYPjz4zsDVN+WG7vLnXx9Tr2sSvtE8MUa1li7Bpqrgl9mbKWWkUrS
+xt51NbR1yPPlQlNbX2vpMO6OipAZVCnOzMdCcdMd8ANNA3fU9nxFkfotXt+qp9oP
+k+AQUQa8iUvJUoSVIGwuzKjMpmM+3+Z0JJ9oAjV234RfrNBxtZMos3vCkrhlcmZX
+JZqK1aqYUg1pqK4fwfD1WX0eSASEKQ/xP5j5X1rQTbnv3OI8ip3bm/IdSENUwIVV
+CBlkpUlnZ2REw9p9/blysnsiOzjy+3xKhFfg6Y9VKDt267q3dT8u8J9NhYJotAkH
+UBPU1WdVV2dPq97X2saP9b/I78+d+hJa9dsO8Dq7uuiXBGuVPDdiDl5sgMgCCkTR
+ucudbu90qcSryhxzaniH091sPgD3KHqWgJEDwpMCgIuFF5DDtnI77sGMf+eGrB8U
+CUkTW1qLEWR7RSwstGmUIlsNwAQgEqgykQQLO1knr6u1ttq21Hb6I+XSd9/RPL0/
+pE9I8J/gr8OkY248frxb8ffHG2a4zitLxY9lPyn2k/bD85+59xlp+/KfS6jzTDGV
+KlCSXUKDuGBA2GxzjS7K6hA7uoAgSlLYS2qL/6jhPn+y2y2u3o2Tt0/s8v7+lrl/
+tPT9O/Fvbfdk0V+HtoX6P4/h5fh/Zzr65P+z5dyH9HPb4K1fuqT5PuQMhcP2210T
+TD6Tx8InpqHwj333mVmPK+Lfw/Zy/VOHTmPh/Y4e230Y6cunLw2flSdvb90NP4n7
+P7x+yfRP3enyjwH7P7Pb7p+s+0w6WTLFVJtJ7fRw+3jh93hw0r/PVq20NKhwUT+m
+nppNp/lXTSUy24lK/p9p+x+7bhT5Y/39es1H9J9h/LTt/Ha6djhODEY0qtFflRyn
+0FY5fsE/Dp0+HL/Lb9lnh6YcP0Ym32Y/Rwp+H3k/Kf3z7vTy8I+K+yj22wqny+Ps
+dv3/tbwj0m1dOmO2g8Kfo4emjSqXi3tw+KtNzhy7Y8PwY/U/sn9o/l8PSD+utZcW
+37Ph7krkPur4qw0fu31nGszW2itKPy7n5Y+v8W+vzZf2Onp4K8qjB+bb8v8tOH1H
+B8o/l+O9+G0tG1pa21taN/eU7knnyMCjBUlf4T4Nvg4a8W9DpG34af0dOXz/L8Bt
+/Lo8d/GXPh9HDFcPhj+ngr92if2dHMPk+xw0x+XptPtbdPTbXxbFcOvGltuZktu3
+B29JpHD9/l+75T24fcjp/93tG58fLFy/Nc1mOE2PTw+O7a/KsP1dPKz1Ielp65m3
+Lly5mZmOW2qiqrJOg0SUOpO/Ym4AUdn91ovgujOz4FB0MBZWJO4mPoNtb+7266rf
+z9zM1txqittGlEv4/jbbCTioBO/q3CKi49u7fnvTo05uxVVX8Y0CiogUNx5JLet3
+YPFu7NOEC+62c7AwsFCz2reusG9vMFWax1VlAwU1dUyIEhit6aC7Du7M7VdNstC1
+lXlm7XRkSLM0jajTZqNBA9IW4mqEa7U3XwsODHDZVYjuyTqypLVdoZbqcyjdlRjo
+dkyjWpGBmkajVWlJ1DzMPPfJIIJJJJPAQDIGiiFDI221bW79r+Dx4685zOUWtrbb
+fyOzogfCvL38Olr2TVKbaW0vvu6QF5fnnbMxw4f2Y/dynRyqptyw2Smnj++v21rW
+uHL/Sh6afEfd+rg7tq21/aO38mnw4SfDyY9KYm/9rcSPu/X7Jy8DtpVNp/s39X6P
+xVjyn28Mf2culqrID0/Z9WNK9+LbXseXB+yp9IezTttsnsw0m2J9HPXrTWa1mZcr
+Y5Fj9fX8f16/rtx/W/7ccT29K9P8fS2fRp+r4CerERJEebBr/HVX8Y2yv6ZK4N87
+Oc3/UFSf54kQJDPt4hEQISiNsJ19vv6d5ePOXnLnKlVRMqnKJRN8HOc4eHnBzoIH
+MpAZ5mOq2Kzf1XTznObSPHfYLFdt2e53f+MGA8zED54z4hfEg7rRJfbXkeq33bpR
+ebgJAwUvLQPVZKKFSSDRYI4wwgQCBcqqHmqrcrro/+ISKcn/1pVyxUc+791ve+Gi
+7f91U5/UtURLrEFwxif/K7mLJLLBmTJklllMbAuMlEryqfWitYksSyFR0c9WGSW2
+NMjKZLbGmSTzVb7Jbba9lttvnPje29ykZaxopllRLYrTpUlc4iY8qqyI5d705MZv
+u1ZllGstGZYT7z6Z6plQwqduumGQywMcHwrK86pav3RTHhW18XfjLFYyWbjorjna
+TttpVOBUpg27Ou7MrMMyszLdHBzymitUJ4Tz0dVMpiyXRJDbskep0BN7JGO8mdHV
+Pd1TStUzfsg4eXuWE9PVt2juEFWDZr24eiXW5DE7KjZzEOuNZG7I2ocWRlLYLVvF
+GIucZOLIbpOKjLLUtRat4sjIGnHJoJtX59aGaxoZtSn3kjr/BfvvEueqYoavHjKx
+lfTkQc9PwqlPyjh+1Tjaztea0tZo/XVFD512U2EDj9tVTpSLeu7zGstZacdMaS3H
+LvcS+9fHUcNsArlVO3L8To+YZW3QdvX46+4ZlyqnDs2vzrkqcOL7lnnrnu8/OY54
+O1Vp+VBoMO5sxa7ODUmwnEJvqyTdRq22yZN7KutPTVelXigrJvTW7bYeEeJUxwNk
+NlWq21IcSHn3w6MTx68cHTacUEfeN4zPFzT3uFY7X3XTNafe0tNeKqbVU8s+c5mt
+7E7erU+HTx2Su+OmvhpwPmcIeHwW7qx29oNMLvh0fHz44pNODegO6ZMEIgYczrCT
+WdKk8MDFGSiuOOdBzS1zZzVoqio5kOTtbKzi7aNMZgoHKdbV9Dlq7N0h523x9+6i
+49cdHhy5L3Kdee8uTrlo5JI8MkRs0xx3Jy2Vtbxbho8Fzs+RYy555fVjxRvjk17q
+u+TeMhUNSCJxOGSaXOJIampROLhmaO2zc6CyY2kbd7PgiY9Mkmm76s3Tx7yp8fnf
+E1+NlrW6nhoz1fPXb3ymeTtuRGa89uIgybYSRnch0uU2n5K6nymfCrxsnUc7yc9N
+gY+UCpqeMhw3YTjNExOOB6OpwmBt07D27E2yOkgo92SedsjGFb5T4cKHWuV2M8cF
+8zMy4FsuJXHLaRIdimuHBprXH3TZTtjDi8eLZ0dKHf427eFdKGF72HenvID6MMOn
+bCLWNsgpUEoZZG/vyoPxPnHd+D3Y+H3rpjqclZUisODjFbL69xIOG+QclTpogxxw
+qNO9m2ni+V9vD2uz1tpoxtt5t1PjrlVPhy7WwKnZHuC3ruTKRLY2yUlqGlKqWkiW
+y9iHnhPZO0rN94N2brW8hut0yR51BrPKXs7JGxb5AnRiZTl2Xq1hpiXy8iczq1p0
+4OUvW9g8WPrtcenxbXL58ic8LgbnL1I0m4MeNSM4zVJrWW9uI3DW3tqHzluUwxR9
++s0Vc0hpweORY4VOtNXbALUCyXLqNFcCR7xxw8jTkStO873DPfY017vHfEhE5xAu
+lh+U9Pt+W9++O/u05zeb4c7pzjRaWurtlU91y/Pj38bnSo+8PfvF8I5SNJ62aL20
+QZtJUXrrTO3rYPXw+NeuFWmevi1C41Gt1m2DMqHmySGsXd4XEMFkBpCUlZSTWAUm
+a5gWmZLEQcLCwtjR0rZplkWrZuMqsNpWrMyvBJ5/Gff5lT3FTnKql0x9H4PU/DTX
+OxAXime7qULq7DqoaFW7tVaVWymOAghDdEltpIwwyIooHivfPjSHoqKy0NCBIRpB
+IGQK8fXhPBpMTMhc4OCJWMuxlIYammJ2sgEEXEs8oDopthFpLOUlVTJVAqKGFoiu
+fFmCKtsq1oM33uOW59vV16cDSvt7p7+u80IySXnVy5lF3Mz5ZLDu9ZrDzoUPrekc
+9Ie3XnPlekWLviZo7sWzm9WT4r4vmvd4+Mn1zI9eadvv8/FYv0fllb9OdHfmF98c
+xiihhSVRBRSemqq32pgz4bzMD6OjNYamHHHp0WsLbYyKxZ3mLD52kY91zW6fPB9d
+GObcd2fPPjX0d4du7bA4tvfmSzb6t9NouC2GU+LHHGJNXK4s3xiY6MfbxT4Z83cZ
+UuZDLGk0mY/Z/iHrRxSY3S1SG9mvzS+bvxc44Th6JqNHLLC4ZR+p+NfpU+sMTeHg
+a67ZI7LO0gsjRa278NqHpyOH+PRsdMcqF5x65vjp0KeJjqR4dknzo+Zsle+oZmSN
+f8ttztuTWnh+4V2fpXP02u7ttibExiUsNhbdfPzh1+rQ09U+enFtXS5qQkjjxMd8
+MkkY56cYwqZcb6vi222vU9cyYersXMh7cOOI2Y7Viz6BNspac/J9fjp3RQw/gqpU
+1kIPpx1mbn6DEJI5wLjKElOj3z3XAvFr+HD+fSn8rhs166dJp1CBw82PeVw26dIv
+7MUi/KQbLXXHt4nPh0fSOYs35zI1WtZGrbfqaOvlNp6VywnitCl7G/RjngwTGOXw
+v3ThnnFFDb8PHJ2lL1vMzxiXS7Hci9P169PULTtp8MorSZB25VNA4Pw6X609+3Vz
+WTVcyRy2dbt8H177mEWSRvh8M+vSerjnx/SZfuZ0beIXSUuzna/Om+czLbbbVfTz
+54naAdd+pE26qa+jh4iOkG3g+U1FmjxmGX6Gj40+jLEntyrIn7/D+T8fy1+Pjjup
+Bc3CtbNuXO2tRdulIu21ItGsL9ccDt6aEtrxfwXjqcDx58HqqhesQkkFR5Hw5s+Y
+95rjxZ49Zxzzzs55zny5Y/Trf42ninShp2tC5MykPXPDq/HSuOcy/Hrg+uXOZjhw
+qpi7evQ+G3aueLbIW2pPLBOXPB2k0qeWcvH8dPX3537NGVVjFVhhjKxliVkqkjay
+ptqZq2S1WktJVZNtVJa0VtCm2mzbZsiNNZVVSy2ti1tS2Sq3md9hy4638z5PHNMz
+Ix3IfMkD8jgU/hevg0z6O9vrhfx2u0pdXi4ooddn1WwLTt3u0dtfx13/DwegMQYQ
+wdp85zgwAfA3hJq69eh7Lu7zLGHl5V6eivCu1elHunTwnjRy61p714uThUcOOcz8
+O1cqxabWOunLt5Rw9iSJHt3F3y3WWZdtujHhx50iRPHtKachw2vnz8eK369x98Ov
+hw2vztQt4JRlnK9QFCycOHEpchMB0Ym5SeIlIUMnPFcafA3klDSwWSTX9VVFP3k/
+KQ0+nzF4rj5wtvArh604+dqCN3Qjz0VcqypVmrlXVlSVcqyiSeckRld1JlJlRlJB
+zmlk1LS0RqoTfWN3vzzprfXjY+ZUWT9c+ednqsvvSSJCkAXphQSFpCgXIwRJFQeP
+HfxpU2Op7pg4ZhX80D8P0HcE+tvtafe0PslS2h6bEUphB+Trt9zcMySlFfrXx8s6
+aKGUneDdfjQ99/yYfX7l9meCDI/bvJDJAQgdu6SzNW3eZlBQykZoKrwo37d0TaW2
+0DnfHOPJfg278PvnXg+re/l0U+vfj83QmJIyIhDN53JH5Px9XhPr2/DXcY+NzGJO
+6t1p8J77+GH2+xfbwXyN7S7ySU8e36ZcY2cmX9ZqJVTbyyJ9LNd2Hy9pFJjOJx48
+YJh9fxDDVU7nuPtjdzVxq4025elJxy5kTGLIXu3JDla90qnLmi/u/hOXSqnQu+mf
+lpHZt8sRqH7saHSSEQXU251XwY4dOFRt18lS6cUnTgWreu+m18JO/RkmYWb9Oofm
+aH1PPXk244ZeFEhws+fI7cknaR6D4fDdfBuITwr5+BweumnDtjA5GjvZpuOHS0si
+Djw9vK9vVXw3M4takTts7RicqcARg31RQ03CvXwCPOWh+DxPrrPL04oI3S1HWXPL
+V28NsefHEu5KGKEqe8NJPYLCCHQMJCQ7PR5y21rbPLh6zyKm7rpxn60/GG3l6l0b
+Mqm2VCL8CsOWG2Qe5VVUemVS2xUlz8FNVTjEzB3gTsxNJ2NL8fkcfOEhUaCuYPW1
+wuNRLHrVBHPnUBbfGqqnLbx2unVlEqcfFU674T6+c8eHON8cbcPxnVY79dPSQXrj
+j02ctOXInljHDTacJEg5ZB5GNDvHrWNOquSOU5GHgGIrXB8Q3PTh49XFuZnMke3D
+Pi349tnTc2x78ZbabfvzMff1Q00qpoqlPdKqaqUObw73hT5rm2u3Djb92qrt3QRw
+acoV3xS8qpNypaaM8CBy9599F75+N8/OM7xre29w+OXpOnjtyeGSEgrypPNCAvLz
+gjvv0nE4N8L06x27SNPjUeRJEjXk3zlzOGsVtiMq9O5Hkcp2VPh8K+XJ7XZx9Zvt
+531nPHGb550jpsrvKpnZ7X182tPp4nB2m23Dj50a+PuHwWvHvJzCvWfD1elNOsfN
+SEgw75bTbwkkc52410eGuLbzmZkZvvVmtPrz195lSMXTdO+GvWa25VN0UMpetNG+
+NwU07IY+Tmk5PCX1drtxw6VwlEnsyq9FxYhCRtIhPTOT09a7ZutZpiLA6pDtYY3V
+5igfFU4zU4brTy7ejat64Qejh0SJHTSTZ3u3h212EB3mgeekTleTDmSOOVnfrh6P
+Y8ntJJ7Pr2KTqnMOYbga2JznETGW1bGqmrY4zLwt8niQD18xElWURb94FyqjnAZ3
+z6YJ1iOcC2nMPuqLNVQhSiLLqoyCroXV+YwVxq9cddcOZJtS0iqScZGJbLQOBQXO
+HE9q+9mbo5znrM8crxzyCVKhGIK9qoKpR4L0FF29epznKxmhKoosQGVDU2h3Ay47
+SFIJE+nw88FX5l03vzu+JfbrzePF0kBSZvDVsr5KaIWZmJzqUoIpQrMhASe/z86c
+6HyL3ZqezLvn2w0+aVZ7vTMRFUZPLRe7Rk+Uox4XrFfp8/Xz18+/jybiRw7VvURT
+5MeVT3Td4+Ma5xHFTVt3xxqcror7cx5cZbWPo78+Fcp3j1jCSRIxTy4+XByxM192
+To8aO6enDlp8Tpwnp5LwvE56l2zffqYlRPPQ4gQywiSLYYacvPXtw/DHocyrt2j0
+e/enNm57m0qsB8YrRH1Lrhwgi85HTIViqnpHjX5odbWnqdJNpywNzy5F55CTpz3b
+Offvji3GWujD788zPCvnTt/r5SH4mbMvVznmrtcufVxUd3tFD8H+XCVA9+aArHR5
+t2MPNpfFspyylwe0mEjs5oJOvfjxfnnNXNbdJPJ5YcaYgXzEbNNe/DNpS95PXWbX
+Lj5me++lriwkeI4ck6bca2nHauuzfPTyrxRXIm23TPacNjajfNUa97T754q3c0rP
+IE5Nere/DaZzyBPTHL667M6YMUiwUw84c4W+5rlfVR6zxCzaeKly9x9x6DhaooPI
+1CNpPHVtq129Z3bpzpOM14nhw8c8mvgVGdYiu3n1jtni6FPTxEt8uOLVAnqxzGvU
+4XXlc09EDkrS68VHEuLovfh0kKjn16nx2624KnuSnHXYVkIprh8uKrXkxp5Z3aqc
+aeE59GkSJ0a8drt6aX+06Y9W1WYqdPi+di9Pw6evm8zGnrTzvvv+GSuG79/XDiov
+H0qepaxPYPTbhXBj1xR4w6Tg6NcOybV4+Om+3X41ItLvfGlU341TWO2R7tSuZO+O
+3asyajzIENvnh5J4Xw8OuDlfBN8GUCx4420ZVU52z250coXTppy6fELl7Rjpy+nP
+x28cG3ng7sNCRkisEe3Ltzt62dtbszTgXpLw27ePvRw+vlFcKR0ekbTaMSHDJB5e
+nZ8vLbTt78dG25fCwkJ//etW1scxPdFsVVsi0tFqS177RsuXJMklSkhrEjSwORa5
+3WlxTnZfjFJJ8qqYtJkGIYaQX+CRXd/3dKH8uAJ8Y9cu+OcSSPAL6Gs336Z468Zz
+vNxQRIyXt3dm7s0SAwKIJ5wEk8AwcCHFznBwg8o1kzNO72t3vAPY+sfngZ9dFb0o
++X4H6XmWneYezTTiKIZ4CUUD4QEQCdPGmwTwkyTaXmJ2d+i8PAPAvDjERepd2Z2U
+tFeZqfopOh7VAjAeQ8BPpenxxACAkEQhEExObQ9XlR+e37Iw1mN+ICD34z4TEzKK
+dyQ5oUQnsRgHH1l1ker09IZ4KIqyrFUOLmqZbKLYUGaGAgOcGgdbwVvRho1lbYNU
+cdPj1zU4ogY7l1TxfNNPT+zP92ta1Xu6TpY6QeISM9/hrny59kjOErh+Ht2BPj57
+6L5BzgoCDQAx6HNqd9+Dyvbt27Lq3osAuFDt/Zv5zu78vxMXPz5rDDqp1z+Pi2nh
+zxuQkFAnqvWm2HD09db9dvJvpZ775mY/Nd5n5du34vVU6F+N+jTb5SesToqJfaen
+DXwdO+bu81I8knny2dLk+lPtFD493Hx70x8+ZnD/LrkygIFr4AcZGrTDQcMwVWSB
+UIKC4cStoBZZEzt+9tptwYhbUixKXVLSo3XvhOmipnoTQ+XBJCdfHJ8r47yZmPlN
+tp88W+HnzreZnj2dX2cPfT3zCQm3ifI8tvCeDfBNnl0nnzDynndrPNObjUhIM70k
++Phvzu5niebfbE8NY1HHuJBzqbt41px6TjT2wnuOfnskTlZwenlVTqj+HnLFtEu3
+oQOnRi96VHqH1D1c+g/IZ9nQp1cZlfv1606UPjEUVw/C6dh+Pz4Dro+bIdOl2OTP
+vLTZ5+7/XSX29Bv0PSCdHY28GJ5eY3ddXvTet3d8H187Yn31vrt8fNKu1D4+cOuX
+InT13p65ql8fJv74217Pm/vXbqk3NtnkqrqnTkK7wpfdhA+r975xmcNIp7Twznji
+evTlp74w9peduGxXiNdczaymNYnPSSSSFdH57db5cA+GzcQeEkOBjPVentzlrtHQ
+fBtWJ18UIb3yjguww+BUcg8J5eHbljZU09Ja1euOjrmjp59ooZ2hzKN2Qay4mLA1
+pTOLMipVkiB0k7w4rISoDm5vGxYTTI8ymFxmtm+OGuNY5ZPbcqyxJP8qLkqcrsuN
+XvVCjgr1Q3zy6o5T0ZznGJlVeY1Td52qu2m5V2aq1GXbu10ddY3rOrpy0u3G0gaI
+oCqoGaZwMADnKp1up7vrdzvSOe91CCUrW9pWJcngyfSVtIngw8zxCUFzpAJs+tb5
+Zsn1j4Dp7628zYe6Rgm2wa9FYc1vkPNMB5NQ8Ic3l160dXv1c6zek8W9yRs1O1TS
+z1rN1EhwklOMD2NGX6ryTXTqgq+B6Y+TGD0AgzsO3XvudNp0bcBy7fASeOUcunRo
+167Ew2GNnFZG/O7eEsenI5SHrvvWZ2addPjD+TtfXdODuwvq5huPLaODCtE0ntOn
+L4e8t7dJ5M07bNC1FSRtpsdzzppPfI7dxw1640x8bjJekxsa5Y8VNtjEcBtCWwcl
+ZTbCJcD8HrfbHN5KHTo4Fp819fe92ONY4erddMSl2w76PG6tcHtZwrlPXKVGjFac
+1j+rOTbp5jOXJwuP10ofsoU9Td33dv3n1t2cqdfj9Pvyqk2efPmZ48XTl0KlODvM
+5h0nx+MfdEOnxtt86WaVU/eucz4+eu3ZVKY+v3r850xVTdadrjormihyN/evHXTl
+OFR1cY65NTCcRp8FenYLLIlUW8sJOnpScPWt7tZIJtsSOmHB33atvt8eF2+HHiQg
+NCRxrt5ejjpt8Lh0U4HvntHLtejv64WuYovx4cvjudsIfUUV5bOXl6xXKF8KXjpP
+vQ+fOmXao1fF8OImWnu/i1atr4deV54zS60z0kRUkUeKm8HijJ0r4pFq7Fh+ZW0p
+aNBfXr10NlfrR0278/Td06Kxn1/HSm+H8Kqdssebvr9V00fgPx9owrAzk/h42KL1
+67fvfB4VPiUIfGBcH0P4etPoVyKa5fXxT68OOsAuVItPWj1w165dPPO3Prp1euH7
+9fds6coXoqU5gR9Lj1cVXDfOfUFnHKJcn73553ve94fphI76boE5x5eZtBy+Ht3z
+2NsO2PGCnbwrDt+Pq4KodNhA28Ozw9e3Tlac0vVRrljGXXjK74Z2eHlKbXHRrpJ2
+M2gxJI5S8WzbWJB5fOzzK0ngIDK6THQVqb+66e221x72x9UW+rxDexdJ8d+/O9Zr
+M1mXw8jyxjie+j29RJENvabZofCnhWL1wD3ljj4BcQ54OO0GkHSQe/IN7t4HfjuD
+tPHLp3KlkOazq8sUy9Y3tjOLJlCzMmaWi4d78Kd+VQ0sVjFFisKSwqlNNSpaCyMY
+JhUqbN41WLJEmRFsshFLI70wpzxVDVJQOGVDMCz+Yz50FeeCnxee+p0OKhjnr5nP
+et8cb4wgYO5ud9c665eXro2ZltpaqQ2VAWc7xIg8F9WbmVmuss1wH46NPSq6o+75
+r6ndGvN2auHmEkDx6GEenCEQjUVKH6S7o7nqeTy/VH1TrvmVfi24LBBw8xYwSNpE
+8sJnV1c5fbaj7DwBMORMfPLNZvLOcobrd4s2vvkgcp4VXw0SckHZ8PbX4yw2pF80
+01SGzT3e1kxTTTd04UOGN4uYNHi8W+3ItR+t5UkOHvho7WGOo9fXnnm5jU28kkcn
+h8ar34DKQz8PS+0UNLpvX12vxVVT4FixZRLGVTCKg7d6NpMKY20fHFHbPHAd9cW8
+W3B6uvHn1lut71682+3b0eekCcIhIfPBfemlNvtyBHAV/OuTYkcsZ7vxb3PCthAc
+J5Tp8ErwsxlI0n3rzjvR4rr5meB17QHbhSBLIyHa1ZzsIKrDw6gTDhlwJiwFxV7C
+TiTvjH4uOQLhBYpFs7g9iZz1eObpyecFTp09Ydve/h67KmyAMb5631VNtmzEgiaH
+voEEA9jOcHBB6Y5jttTflN4ntsbyJB2kkiqnekzu324+Oz6u+mggPLyZ359BJ5B0
+H75vv+O98cccbcv12976z0kU9dPnSF745HyYQ33cpPXoOXLOhUp0DfHblUbbed8u
+lr64ejy5Ydw69Z2I9N+ed8a3ve9zh58tTm3kTpI2VpN8Mb84XPTbiYlSnHxsVKd7
+5NOQ9jvhPHro9jznCFWeydPNaNzME08nR6LWss1Ouel7em2Jvht075zNukuFDuk1
+adIWgfePGTgVKdrr4ziPTO8PPDtjuAh51atsnp486Ws04OcX3GrzMsVSx9Po989d
+4u9uULJywb+G3r10Y9F054GPrm4+L04ZJJkqxvxw8zVtr078cZmaVPNF8eWOnzjt
+m+Dzp6MOXKqbXT5aKmzzblVTg1w8Fy8+g7bfFrpVSnXPW1fHbb1XDGGpmJERNfAa
+YbUdLIY1MzGDJvWaVJua1NSM8i0YiLdVbblrW5bVtO8YJSMqFKEhgmDmWUhjLJDM
+DKMoiZY0CluHGm7ksuQolpmExItaAGFEt1JhFAmUBNrbKCiJTAyJZtArEMXRREHC
+ZTHBRGRExxlmSkstEbmFe7IABXoWWFGHTOoGks2lkVQKlwsertIkulaYxU1YkYar
+IugRakIpIA20qUYZmFcabhmNazfPjwNMIdbaUG3czeq/mv+/sp9452V9fRjeX3nA
++uetKRd6dGlzfHRVjgAwXV1frY5IFJFDJHyc4IKXOHll1l7lpW8epW5ML2nMCWfF
+zdoNoJaHyyw0D1bEtW98yTVcnh6l4fNM870OjJT1pY+N9aOlHSOoPVAjvfOy6XY2
+YjllLzgBwOAG54zy9JMd5d5Q8hgek7RpQ8GnkrxxqqbKdNcHfWnS55Ncmdbrjhq8
+o7ZUGlvWBfCumh2vHI1+9s962fXxMfAcquYF86TrDOPl1vW8b/pXKecTuBeH0U+L
+2fGp45XJw718Z9c+sP5PnLvB4ymlt2KlHLXaTto+Lz741xvN7za4jqJInjts1qe5
+S8qL8mlDH49Q5+dZrXjzpsqcd5m9LldKpvtv4EDZ8DPrN/Putb32490+paWvg7pO
+vrlKWmnnI72+pedYn31Y0duGm3a9uBOGOHp0h1SV29OedcZxres3mbt32npptw7E
+xetpdUUOnblLt5m2eaqlyh4KfAeqHL66aztyzHfh69Zol/TfR5kRkieuPNq2+3lo
+JODHljhPalUp+OsY+bVGsXp3+KNK9OtuXLOAJqZoZPU24tuyRwnGurXKohrzvvvN
+a1ts2nXKnipqQDwxOu8bJI6ZfCCZCNw6XfbiBozK29Oz5zmLqvm1x9cipT7Klty8
+pOF329uON9fPvbr1pzeMpPe+Hr3sIHq4+uc3mZ3PLvZO09OHTzESDs426htwdn3f
+VRW3ZttTnnnM+rHbw7G+GlU7XPMqrzx1qcbOsdvGePMYn1vf33e97bkXTF7M1573
+x3nTpy0frx3VKHxzqqHTh4ED3htxzp0rR7w7XpnFbjBaMsMAti2WdMGWWphmA3IG
+ILJKMBLTKBQMAVWSsjIorJMWW8bZqzbphIxqPLNyrUqhpj+j5VOekvjvVUYBwAAa
+KM8rSbnby5mMvMGZKspWru7uiVau7t3V3cu7uqaSIWAE8B4eAc8bruXXY8ta9Ryl
+s10jpy+y++675d2EUSCjzzqZO093qYXV3T5vii7tdBPVdZIj3ygmbS4u+tw9U5gd
+efWVrXZ6tawSHPWTXMsxnk4iq+i56tphw8+ToZ4O5ATgW0MkEcLw296lNsfrDk50
+J1jPLRV90fWN0hz8XrpcPBenvXi8edeZs4mllq+utW458+TOnpnKJE+E9OPI7Lq6
+OG1pjRt3w5fVc9jp+Ncu5Uh7FTth7vi3HHbwktHIvTl5d+3CHhU0LhwySh1NMXTX
+faqcvPWZmV6OkmSyxFrWcJrWi1kksrvvgqr6xW9zj1ymeq4dcNajmbSDkR2mTlry
+5AnE7fgk9Tk978Fs2pXhPvjltkl3AXoF93yfjrr84+98655556eaKe/TcvX8+tDp
++Pi1RQ8fdUu2pvFdMbdPAQGNN8ivU7S9Ryc166k8yJc5IdVFdb88+uu+/zeZveuG
+j1wuL35UllCnrTCt7IYcNxThFFbQtqjNZgXr60baY2hffWp4+ubvM/NIWzW5Uj1D
+p8eU+ZTg3naukLoZzl+a1n3vGta8samSFp7nvlKVuVxKevXTjTg2duJ3SfNK066b
+lwcPF5xw2+0cZJzrx68c3veNZrGOHXbTSSRwPSDE242fCWz4vTsVKYqOF4bx775p
+0xeOddrOpVXqcPaqqOW22WtV88c4xmZY7dL6ei956V67bbVtWu+nzM5fLQ6pS9sJ
+RXrzSp0cNSpHqF1oswXg7xoeipTO2OO3gSMFkwqyWwWmzzmd5mSrkIb9W0R4V052
+4SQ8m/L07yCFN+NEinDh32PHfHDzfDTYp2pF9vXXneZ84x6vcPRzRtDb1rS9KNoj
+G3tt8trVSm4nKzy3R6xxhOMVR5krVhMyjGXOrVEkqjaow3ghlCSpZNWBcVaxL3Fc
+Y9ZJpkrnJzlzh3m8wze+XP8uV2KlNuHovYPm99afPmu8VUqUJ47l3jmZl5eHCqbb
+HO7xlEBFcBA5Jb3t32Zl9tPvd2smGycKE9uyfDQQPDS8Ltb4qBF9a8qnudmpDwX4
++wdtdWPrzp5ZJ51IafAcnZAsPkypcqpRFBAcxIYWs3vTR50fEtvnqdcUo/dUXwei
+bTydGiJ4PFIOWjex8NM77ddunuIT3rfm5Wc23BHly1Kmmj152czh1j2qUpWYqJEq
+vL10rcCedpLOreZEjlnPpzu3bt2Pe9pIbbhG5VdskX49R4c9PrbZr3tVMdOn17de
+nw+aNedrTuVI+Pjo67O359n1jijiSSJ9jstJAwAWh6D6ObOekTEOeh3nAr2g7ynr
+8xXTOMYFcwj5xiIpx8cwczh8LfyjzhSPBt74x6zvdzHlySLo8nCSRsk0eS6TRbxm
+Z3wnmxmnHMkNhygxjtJKwkU83mOviqqNjty5d4e44KmUaw855t7i6cPI8nbp5Sqj
+jbpFk2djdy3yk88pG+mJSHbOXfhw58IK24kkSC+DzcXXnNW612O4HXcPOwd+O0Fl
+8PvuZjsCx5376uzwIG+WIPHLtDGueXTEg7dMzfR0JnnGHYm9idAqLLCyKsqxZVXx
+lbdLKpppSUky2SmfGld42pFyh9d+861rCugePr6r6xOggdtdPr4hx457uTlQ/lju
+vcrnltjnbtqu9rUk6cL7e+9cX1mt71d5mJrs2PD2zySR16d72kTx67dPB2rKOy76
+78XpyWhUp8dXq0t/AX04768zWa18ejz5cuUnls27TZy4O2rxRtxcg11S6cfNoYO+
++madlcs6drb67VY8K3zSk4YqtLvupO/Da6JNXUsg3mJLapKtWFixTMIxiMYqYxW1
+DMkpmVKMqXrbSzMt9/sqIqP+t/93+I/0n5Sn7T+QT8zf0X7f+TD+B4CttqUP4hlE
+RRRTARIfupD+YUw/Q0KfxO/YVFVv5cOFw/8J24f+hMf6Mf+DF/3MXL//P7Nv+9/D
+R8PD7NE/L5Y0/73/Q5TalV9v/fbLbfTY6Wd/hbKsn7vhvhcttfh9p/Rx9F7ThpoO
+zo/of+imn7jnrLbavsef4r/UcA+RPuf3Q+f9UqkU/8ap/+MFIjMqlZkqslsVZsrV
+JUlRZLa2yy2qaRaWWqRTKzaZooGCAwg+x/nV+FYg+fi2+gz8s/Z89W73ufUfZfMZ
+rG5jSeX2+tXiLy5tM25ZFqjVUHVXHVO7t3Rjfk7WWV5Xd3zfCC7d74/Bsvzb8BBp
+uu3U3zvXOnzxjyszB3F1Lpzy88Auvjt8OJfX88hg8tvPa23zrze8IBCEkACBACSe
+svoy46IiKqqiKiKrmbpczNUAkJJCTVerLbqur773rXpy1c6c7tea+Z7XygAnXQEQ
+RJmCo+i1VHsgGMnt6oTG4h52C6u8SvLrMP/waB4Bwc2A8sBaDwhBB/o7aeobMefe
+uPi73vZt7rVet2rb0T0fQ/9rykNCbO/hd3LcnNv0nxbJpOOM9dbX3aauDKzP4RVk
+8gGChiP3tin+2Ko0zGvv8rm997r3xV1pt67QJwiEFqEG2tbkdFH93DBwDjIPBfPi
+1V5aFeIAHWiKoxX7fYcN7XsJzs2YByCqCB9JkFUVQVTA6PRvzz5effmf8/OC9PMp
+C+ZtzACFV1K3GMDvG5p00Ri2rRwdRGfGJGZluZmRrhVWSvlPXhbVm0jUeerZfHWX
+OyPb4dvG7fq7d2YuV64ePXrvx6mb41zvjnrfDiqrwFcQ9VbJCMKmIWYsyFKsKZAp
+mGYZYsykKYZSrJYGZBVZVDChZKsAxJMKFRiFQZVKxBZKLJJhJTbbapSlmzRec3cV
+XShD4BDzmq1wkRIYPpUFVy20DjqcYA1wAOHwq+O9r3vWre0sCbAG9xdKyeSrfivb
+QO34ZArRrbCmGhJ6LPbla+t+POc5nw7qzbdSzdq7p0eJSUbVXZtq6NOrQouWy7TR
+Es2HZNRu1Stu7Ysi26gMq7VS751zzvXPF5506HQJCRi6HLltz9uN8Xm7zDLmXMwz
+p7a33LluY0zKuVZCe1T/O/Vl8LrrrqrrpOIUG2dJip/z1f+mv/K98HqwOlWunXPV
+64nVSTpZbdoyVil8PHTcq/c4iSP+Kkth+WA/sxSm2JD/tMfEf8rSNT+n1kfxMmZY
+y5UmMVMVJ8ZbwcyYSf/ThUxkMMoOz+R2qaP6HTarlv9RaiqxhI8PDkHT+8nW3ZOm
+t1jbpR/acHDtXbA6Tww1EzKi2KTySO7N2ZTCkq7jYh702RpxAodJwef/IaXmsXK/
+lMbLbeD/FpyuGQfEv6LSrGVZhmSxSSgoikttRbLU9uW0NrwxmKrwfsj9zZ07ekki
+Ej2irVcqtMxjTEjVXdf6P9p/KOcsyr/syrMkfUEhI+3yT4fG7atVVren4qxU6V/T
+taOFf5Mj/xYPqwPYq8bLlYHT7x9X86t2frOsP+5UnmbJUjANvKTCvZwkj4T2/Xbt
+J9f3uJLlxpGGJJwQ+9LUNxUfu/pLKj7vl9RwfBGH822fqJ8ukk8mkR2V7eCdNCih
+4rqR/FLZ4nb6xyNCn1IfeRyyRO0OnsT1CDQ+jZX2q4iaXcThcJadGG5K+NMY2w4X
+V16pdJLb4bb6ykpDJjVVSiyDx2/Ppatf7fHfqTzbxrUmrdbU+rGg1FD5mI/V8tSf
+V8o1D9E2nlH/Sfrsr/yHD/OP4SeoUU/V+sYwlSp/5mPQ/3D64aVkKRGlSewWP9VC
+GFgUGZCQwsROn6CqH9BPpvLYlK20kmjUqRVZgh9aaGzdo/4oxbVDFP9/xGOTxP+x
+g6H8uhV0ykMME8OXjcocLSqeqxYyhl2P6/5Hp5nNLf8IonRUqUNjY/DbO5llxWJF
+SKUSsy3EiYhPJ+cGHd98MzE64M+DAkD4YiKRisRkTDMpmR+sxk9icopWw4WnC1/0
+5aVMf79WMpaf9tje5Pm9MTeot7xUVJUoSR1ibG8TG+mE9pDBpFKsllWe3HKtI8x6
+SfEmFttpJpEsCWDSlS/NdtwJ44ls8MVRi1bmLU08xzI4bQf8lyf3o/X58cfuZXke
+jA9K/Wkv/oCpOX8AoptO3imxpWsWZVKaPlFYOn5ekY1bMWGWYopWjCWGKaLTIGkP
+wFSZp1BRTc+o1ds/D/mY0uThaKlVSilOHlj2XFcG5JxLZUjayIhAAACEhJTX703r
+bKxG0kYoRihhijZMYwxZWGEbWSBqVDlZMpZTZStskllbfWleql5taVJKGgnkxRrC
+VSqptInylG2SrIwx+wwoppFCiU2sGh/NQbbQhTFWSmMltqpy9NIxK+lX6Y+UYTIb
+ZDzMDN6G/c8HjdYsVEVWSZxbtU0dN3q1u3bFRfC4kqOpVSPLo0pZSIiQOFnZ0d4q
+sQkz4Qqa1DlekfEJApicdLA4a9OMxhyvFegkCmuM2yHU5NScI25iY4U24jHLltts
+7StNCk4frJzwu0Y6VjDDFk5RppNKqlRASOcpVq3MyVYiVt25mTCT+oTRDRPR2CKq
+KWrVqlUrlqaNSrjDopxKbp6upXldb1PU9s4hJGJA1VbLTiRJ7eok2sM+UHLbthMQ
+UFfLLbZVqqyVK+p1Equ3tpthzYl7KWLEMTEq4Ll3YoV5stLbid+m7alklmvcxMyY
+aGFGVGL1wYwx7R6xjFy7cn0pouDotHyZkzo/hptTZOkPyO1emWMxhjZLl04IdDYK
+mkh1kK4y2TMxcjHDmvtbZMWE+zDHXCnuD8yQLIjg4UlcKxjHr9gopzYxfuda1rEs
+eHCK6OCQ6xT4Pju3n5/X9kkiEj6cN+/vl+uaZ5gYN/g5JlAUHSDiUhoOAhwMFMVB
+c3DDHMN3DFulS0xrgWmW4W5cMuZhWta1rW21tbbRzrJVtBe+ulvYM/s8dPjcuY66
+qqqisgnSPat2gVwbVEysKVgXdk1QJsk8RJCBD2v8tenlrnM3edFeqa8Zu7mq1raU
+mEZP6xTGt6zMkdvq9uZwdp7PTR2nSvKidMcnTDZCbRQfLpsjVtrN222z1LI9jbbS
+Yde7dtk6DgycBMmW9OTcaTFMfB8NtuYiTvVscobNGKRo6Wb4zDniY3e2mSmsjJQJ
+4EQ2vqQkRVGM8qYh3v0q2rPteqmFz2k1KQNMUOrLk2hBsGYs7NRoFGZ5rKHrKVFW
+Up3oJ4GS+bM2pvedTh2+z59qcemFaIM+lnMKY/XLM2leOJtTiZEVfbeon1+vwZOB
+hQgviaCMyAjYhRqyLmywXa6sJtAjY0ekbBVdHErI5ucHJgQ4jsRIimS+VhHvLz2P
+o9PoKp4fLy9uDHljDyKyG7cVtjlTlwPJ2wD56Xk02ttipijbGTs6TRK6R26babRK
+3K25I5U6OTolR0fLt24J9HaeVeHM4svhpuNNlYp5eDRNLKaWrGQiqmZbs0Tlo8Bp
+tppto4ThGn0cT6OnAeX+R8K25e3KOzaUpVttKUnlUhZWFTasOmERzfpmb6O47lt3
+Whna6EmiB7nAKT0eA/sERTa2uhyCini85zJ/DpU/B/+m3fJ/wH9Y9AkiPcclOX2Y
+n/g2elK/4y2ikYKwUzMZcuJVFe362bbaGluwykCmE8ysyzLFrmryuvj1Xz/S9/AA
+AF15cn4TbNPgsRs7cOFV/dG3g0p+7T5dL60/tdkgpyzk/3v8imkP80cFiv6KUxX9
+LGz9Vfy9n0NI+HBMGjFPGRfU20/oK/wT+7+V6CiR4ktktkvJP6O5j9KtpUGP1T4k
+kf+7GZWMJ/d/NKP8Ksq/q7hRyh+q/vOT/iN1f/NGJt/f9yWf5H9z+wKWITjGZjP2
+GmInSyTkRo2qVStSThT8HxX8MximI2dIqo04dIbQvxbWO2MVGkVTxHSI0R/h0eev
+LpWSyT2p9GP8P1y2m2c1q8325VIvE485eDI9AlOHKGBw4JhDiv5HUmnSO00Q40Je
+rcSSy5GXLGVUp2n0eDpFE6T4Y/r+er5YqJai+n4MphhmLSwD8QKQoGSRJ/o+6YvW
+aSVmfLS2qpnMM9WmHTRzMJxy0qHVaVETOYZ1ScEwOJ9g0NPAmjGk0rStNtsbQ5MG
+2BivKYNI9Fvbiqv8b+qqdv6PL9GI+O0lco7fpI4cEi8XLlw2kn5YnpWFTwgTabky
+liH7Ax+fy+323r5BIEhez17ddXMxVVQFUOdlCkEiQJigNAR9MV9a+Xx16vk7dzgH
+lDoGcCQ74xnfnz3rzzvXO4dlaYNK5NOUkh4fqSweoaJidvSK2eXFtkPPEfCh9Gkm
+XRyk9PzmZVzMqjDGleXlHlJE5ZMZSrZt/Vu5MHK/2HZNP2ivmSPQ/6qw/Hu3mR+n
+CmQgJH8fUlH/NlVMZjKHCWNsfyX3+p/53h/1MZA1UFrEx/2ManCu/BiYs5NIwfyV
+9hsjSn/V9nhY5PhjI7Ullm1JVllLfJtZNrGVSVH0hBWtW0eniUKWCpQplb1tteSG
+W0qTK02llaKdJIwk+rhGI29xHeDU7WszdtKrDKsoRP1Geg1MyhiYmBApJgHZ+sFf
+yDkcXDK/ydg+VJSP5sSdLVsKtSHjkwmzZhbIuvbvTXnHN1BiMYylZk7k/LKCYDYH
+X13JBDq8YZURZWoixpkaIyJuN7+dTwztXv57+nThHDDHBkYhVKpPSK0UGMMYTbsK
+VqDzx4I8qh0+G90AAla9VKVWaW0s7IZmGGCsGJhhSnC6DSPacu07EkRI5jWcLUjw
+/d2+p5LbfLw/ft4tspaVjDMYWjCpQqLBUhDSjgT+k9T8hNA7KVTkkn2GnDBRs4gq
+HgJXCnB8vaJ5e0/l/WLbZbFLFUpVRJECIT7iSv69sHJkTAi1mJkzExpMsxUqaYaU
+miWTRpNtI5UcttEXFPVdQaiwV/wNOFTaFSaL45y+41lrMYcvR0CijhslcNI/0x5X
+Yo0kXy7cq/RMSNtOU8qn+U1IPp+mXMmZbhJ0PZ5BISOpVSySG3jR/pLeKmXKxwbv
+w08D+N6WzGTJkSeyhTax4Km0mkp+2qVI0rFU2n8SvhDnkx7T+ba3mQuaiT5PhZj/
+BPIPTKvh1If7V05H+Z/nVSKcn+SK/2dX9F/Uvj+tYktW6Y9SJs9U8H2+uGZNORKn
+w6+2/Cqtq2vpfTblsuXEmsGzllqypVLFYDCVIQ9J3NuEfwGnxGlfyMeYjQf6WRG+
+x+JPz9kl/QyP6sMY0xZf5xV/I/U5f+p6o7h0sRjp934eHA9K9T3ZcSNLGkno0CQk
+YVp8JT0vFuFfq7kInwp9TyTE+k95/GX6qj9zhqP1y390T8OTsAJxZv0pBjS09ndu
+/queeVeI9GunPNTJtIrybqni5552x0a9g4GMHRBAAhHYgg4OGOTGIx0md24x2cp1
+ws56tnBhyqW7W22GlI2+w+z4NJHpLENNvsSMmLVcLMVj9GSBNLTXNtfwxi4U4bKw
+MhtuWyY+2mWYp5ttKqpA6paj8vKRxEawvhY0NIfgfiH9z+yajt60n97P+eZ9rS0x
+W0+VV/0sP8sevxzxZkupTbH8sPl/D6tcrSqnhp05PlHCOok2cFqHB+kTvuQ+xWMY
+xjkg4SNqTWUt19K/fat9iuFW5XN8JyNMVvGVP7r82PqvjL7jtfwP8yYr+QqSfsJ/
+jvt2zClUVYzM/e1n9tRN7Zd5buwMVVKqRKoVR2YxVWrU0/hHBU0sekk5eWPDSfeZ
+dQOaqRT0r4rFtLHeZaEkiKs8vN+vcjw/CGRlxRVkq1SPDFexPt0FOvhPFuY6Tbab
+lve6MycQ4l0tzYO2m5eZhoWcZUOk7NTTLtwdLblt25Jy6YaTDpixoPYKKYtMSx4V
+/I+Nn+ZdTDBNJM+LfQOkttkfVOk7faSBw+y2ei5ZhaxgYP9nmnNi2FstI8cfri5j
+4bHPFumZbbbybHMpMg5WROgw+Q29S8lhiiGULhSjSdtjNpsyIlsyhYqxbcJrYw+o
+k8CH6HRjSvDSMVFQqqko0xiIclqrGrAw0hpi/ouV/i2foVy/oK1INsn/LKzEnZt0
+0/TfY/WWsZMkwqJFKpVKpSGE5kJD5cnT5T6BPRj2k+rIH3fSdvy2kEdD9W0T4tsh
++40PbR+xRPpJN8azaR9OJJrfGcJHGHBw2OTGMmHPduPz+ryTH3/TGTMY0bTThPa/
+xbhjyxUTFkr8JJwYmivf1xmZJq2ySlSoJPBIfK/rASBSF+cM/nZk213bMmBX5laT
+Tg0VqrbakxFiRzCeLg1rQx4xf2Vq/pUjo01d0k/Vy7frMy3JIUqSKj8lG44ZP1xk
+y5bcTEsHL9YMZLGF+0n1bjZ+MHj6OXau8pg6GVof9Cv/Y9BbWvn632UMYJoMElJr
+W1JQhbfu5MliIQxxyxlFWYJJSo/lsdkj/9Utg244/f72xHsUqlRVMGPuJWipOBhj
+qEkxqGNgop68j+4/mhRTtlWMEwwuUKKdDCxGGldP8X8NFUz85NW01rD7NpifMq2W
+o7dpQsUxivU9S0/zYuHDin8gytmwSEj4WYqVwrKqFn2kfvYWyx06X1X93T+Vj5iv
+X+C0fH6nAMNqMKFVXg8nuEYKKk2Rtat7V7zXsSJCUSSRT1tPuvGtNOFnGGB1Pnt/
+MW1VDT4EQ56UUWLFFBZqjHB69cXANNLJbE0k2zdlNHR0OU056txtowmLOO1WSsa6
+mpA1B7TlxdF+0uvItZVay3b0whrGdccXinUpEidgaTHSdubVUqqtqqabViKw14Em
+JmDeVXXLyvKySljtLGMq1t/wTEMgWhujLDJRJgxkJlQy5UMlB40srBFeLlq7bpq9
+ptq0rbSxohSrCmSRMyzLLLMSFMMqVksswFVkqTKplkqwklGCsCyqplQsWLGMZZmT
+JwN3COMLWLVtt2fFUij5Hs/SR03sfZ5nglZWZjJSqn822RTBpyxvWHlVKjTbGVtS
+KqskrbRpKaRWKlUqSk4VwY4cYMNTGkW1bk5Mk2jbg0RUmojT0wxxKQVYhbbLZbFB
+oqok2slvxSlrqul/g7aXHwxix/68Toof7qkpOaD4wC2yq1EwXZiapV6/hsyJvBiy
+EnDHppUrseSqqll+rGDc5R6WrvWH+G9by3kboLdJKq9H7sVW0OfMc6vWl01qZLMZ
+GXXa6QEItcit7KxXTeedbF5N5WV5LJkt1ZLKLEMplYlj+iTA1EdNMJwtIUTETRhJ
+/Shi7iTFIxhiMSWYFgxhilFclagZLPw+zk+h+o0bMSmKxOFfTOrm2TbWXbWV6uG2
+zX+jEamLH9lX+6Yr/YLxH1w5c28qRqX++P6v9czJ/Bpq0wP7uyQ7eB+Vf7n/N/A4
+I+n6Oyqaf8ybStl8Wgvg5aMWKcsqRmLCpH+JHY7+o/ZUcf8bQ0syoa0yWdpVOGka
+ZNpjvIUVJ+ZH6qhX3fZFanSyHdkYpGWGxtjGKcNMNKwlSpDgp8KdD2cj9bMv9zY2
+4SHDkmkf2xkDCf6LKQfCpoFaOJ9BoH5TDi2/9rCRhPqSKlR9EcmpFLro0rH4U5fo
+dOMs3lzLMZaKYNommiU6RuIh0nD/kT7lH58Cz8XLMuKhGo2V06T/Rhf9p9apP5P0
+/xq2rWqv1erT/PLMqx/K0O2Dg/csyqf8VH92myX+Z8BRTxbZHaYmgsP/J9QmCR+7
+y/0+qv0fCnyiPJSHCaH4SEiYfT7Hsxa06QsXGmMqTClIxIpRFUn8jGqv7oxG3iH0
+WUiCZpN8b6/n1+1fkq7ffeV5XQXGJARn3MyZKRCosJhcTJSYUEP9MYaSlQxKRSo4
+T/usWhVI0Ps/HwzGMyRhR1q2WLastVljMZmYxjw3K6VX+qMduROGGFymqf4nekcJ
+jClisYLIPl8mk0rZwHtB+viyyk+VPL1HuRApl/cZMDw+MZfZt7Tx7LCpLZS/LK6S
+W2SkqS0scvTSTnLcGk28PRKVpMSUr4PizlmNNE8YGrZq/51JSfi7Ts2T+5Tuf5cL
+UaX6LUnQaR5PlE+ZyTiUqVaOZTHx9XDIqqOjpwldJmO7TbfS5VtUwninQ/6Jhf1N
+p/3sSnS7Y/q9Btj4/60tF5xmT9MwRXPy8PM4fiKUOh/FVVREYiiQhAhEa3qu3nv2
+d7+q9S8O8rb0Bs06WlE0arExG4ZViJk4YG2Gl1NmRsyoMpaZV7PclFEkhkSN7T1+
+jx5uV62pGsk5ajBRIogIzWpucxals3vLLZmGWmKYUqcpZRpGE2OC4rasjHDE4E3a
+VkxkzLZJSckySoFD8JNDSmOGxNtM2uJgwFUYSjFFUqlFGExq2zQorAowoxy2rlV/
+wdJPWk8RjHBV2lsFjhYX+gysyZkxh0f3RhVg/4UcJ6TuScH1VPy29yH5DloLCqpU
+qInySSwxRKrl+50K0qqo24TykjydiqiUngn5KlPjr2zMmZmZlXDMt/QmnwPDD7q8
+JHcLH4WjVHYxiwsKx8JjVH90Yz02rRwptHkY4fT6Ksmn8HZHweLk7kPRGKpyh/eq
+bPRt8Jw9H0f9riJN29Ik05PjeYzM7a+qenD4QbH4OfJwfZMB9ytJtyhXEiMJiVNH
+cUPwV4H6o7H3fBXSflFn+Sn3kdp9U/HhSqjtSP/YlJJT9D1KWFG1D7Gn2HR9iD60
+4ZhiiTUjaPujNmxMUhRQMUxVYpiKFSJkVJXJrRuOpD+nmZJ/LmR07HlWk3VZMyK/
+m/D6vP7Ztqy2BISPUCQkdu9bzXnqeuj9E79X9hjUSttuMzBuJcLcpmDmXFzLmW0a
+Nra22stGjRo3xd71/j7CrbuqNuCV+Pn7RiTiM9JJIEgAeHxJdEfM80MFtPnBMxsr
+AgcxJUHBQgNneHDhd46b0pvHTJccMlKYUIk+5RcOXp7Ryfl0Nnc0n5iTGzpiTkxo
+FCf/H09mHBodkFJS2Z2cs427TqZEjg2XKgms0uWP9EwnyRTKCH4BWvY2oHETm/gw
+zIiIJE4SQGl2Ck88xdoqynSIaAsnIZAHItqcqEkc5usa5371h9/ghm6wvaD++Ev8
+O9O1aUzFPwkL4FbXvIfOvp571rp7GmKUGlYdK/70n+m237Stjy2V0w2w6YfZFPh9
+Hg06PAx0ppwTTGGySp/LydK8/p8z7d2Zmabu+zmXHZJtVDh9axBEEQczHKc39VaV
+T4x8bLS/TE/iYRwjwdM0rY+rUH8HTgw/pHI4Jporpt5nzbKmLJH82WyJNK5mnJ4D
+eABtlKSyi0srSV+jHaGkaf0oL5Xqr49f2cO3KPHdVlOlxT2Lbotv5H7Pq5pfnuZz
+/dmMfvq7Hqnxosaf5U5j9bbH6/WKPbcO7bK+EPh5IfmR4cj2lOqW0RIh+qOFlpQ4
+QPJP14ba1ay0a5WMszhMV5f9J609T6PlI9nB/Z+ltJpZfELlyFYfUpiTUrTJy1Ra
+mlkyy1arGFKjH1SmRptiNFKlHlOxTypVNuJAVJ4ErlpVbYWdnGukOx25SUDvhmkJ
+SKvuGWZYZZExglQqFSfb9gSRHe26lLJVfZjBJ/oiPHr3rq/pJEQkegQkCw6m6pxf
+vmXePsQvn9xLQI6KSRQIAG3bEGfh7NUKcK53UPq8OHUkcacJyvTMdOk6aVZtbeXD
+JrDQwQRBjBWHXQ31cy5mBlRZ6IYlcEmEU04Y4cGEw43ZacPubU5VthDlicPuw5tq
+27YxgrGOOrbLbUDHk2YqK5Y+iuHLp5DT4+JNH2/Z8HtbEa9pifS5hRZbRbRJLmJk
+tJK4MBO+IfGu7xq/hYNWnTpGnT2zPJAB7pIdsgDnjwae+mHsZcy3KXSR8U8MMHx3
+67L6cwtaVLbW0oONWeD2UwAhlkYAd9PyGVl2b951gXi5PVcb8QkPLMTq0gBWTz4K
+b75X2bmGXKOkz4+PNebXzvhX0lvnW92FLBBb7Y5NtIVito4Viq+U3q3G5KxpPY05
+fL8uNtqqVHwkaYHg7TTw5Y28GPVWo6bO3c2dGOmk5G3CG38p48S6HjlsNF2N5UG3
+rhMMNpgtTb7iCOst5UUraeXaRgqdGFNmIlmjFNDbT2JT0+HDbb6fWUsvKq43XF85
+mSaaDRzytq8wj6ofRCj5SpbawpLGJ941qyZFjLKFSaYxiaJLLaQhJJAkhvLrtqoC
+ttttq21FiQaI9vwrDxA5e0qy21HycDgaRwSPs8Q8LbbbaEEqJAA+29r5V87e9va2
+19Eb4CSiIivrXz3xYwYxlsMdqma+mXMuMrKWCsMVUFYvUsRaVppRgxw1JXOMb3mL
+yozTBtdtNjDDApBMAoSHCRowphkwjDBucNtDaRKMMYKomhyNY0ck0nxv7WzTGIgK
+aWfqbVi/VMlGxYTH9BkkfLWrfruDbbbdSUqaY2JUcG9pYR+O0/p+5jB/JZUMKxWI
+qpUVIKVEVQxZMcum5tZISSZskAD4W+H59LNJklKlfGlrqabJQptdXKqVKsqlUqOA
+aRSiVP6PeBAlSQJCTLBC22236NPq6ejHcSd2rZE7YfVPKyfUT4b7fr8WyefXfb6N
+MyWzwG2mEp4bur6pan33d8BXGubpOl5ed4jcsltUaNEoRiM8GkA0MS2li5l+V2vw
+4XIm74fHps8HR/jS/q+HQ8pSv0K84J8+flIn1SJ6+UsU+C0c9Aop1HStKsYGMDKx
+VVbVX8PI4Q6YTdhxS2Nirbpbf9Rt6er8OQx00quK/pxvKLQgCMAPno3LmmAsuG5c
+3ARCCJ9nkfLTE07UWQ+xE4dfZtP3VPs7YjtMjphyP+UhGz0R9z8FYVLWVdq/Htqr
+8qLbe2t9wr6vumCB9f/1f4sdo/2GBgKKf9A+qrofyy5yaOmGMYh/zf7gpXixGz8L
++5/xfK/0YL8tv7GR+gqTsvxJ9Ht9VkkLIxYsKqMPDNH2Sv8q0SrVcBPlIf3fwNJ/
+tUtJJygp7lJ+qPdeOJP8PnGm0/cbR/Cu1iq/DodIqyKlElfh9ROO50qsVPQ/KWck
+mmleZE/KwjD935YnpOIH6pJJkrJ2Ojg/KkmBVi22RUNKkxWowxU7iMnlaqlgNpJ8
+pj7iYnkVUWTvh03PCvJ5UwWAO+/U+8rwtQ/m/pYcu7dSLkkqlUIKb4AdxPxWQX6d
+K8cR/srlNn5QkJHSlU6YlWNKsqyjRa1ZMrLLMYBj6NRJ0TlhNqV6ntwbHC0tcGIM
+SikWx6q/J86IAjICaXDPuClJRcO8kmItQriaGCUlFzXDGSLiFQTqmfrNOzl03Ole
+IMWrYKKbCrtOGYDoM00bf+1W6hV/xyoRH9H1kIxEKqEqwhOh0fbf3XzNt1ZIaQ/Z
+Tcp8CVPCpx/rV4xb9LJRO2FfAhRPU75RFAhEnDwrLCvgVkHFpWj6sNJo0rweXtOp
+yT+x5Tl0wTwqLD3pVXSJ+5+RtPl5TqEhVD+w7piTk2lwGKf1bfq5W39Vr75V8q/9
+/wWTBGo2g0WqS2itFWqKtY1WosWrRVYrUaxWiqxasa220FtqxFVbQaNUaotGxFsb
+axtbSaLbG2tYrRrVGoitRVEa2iitFFbRqi2xWxVtitrFaqNrRbGrVFWsVtrFqoBZ
+kqzAMyJmCrMpSsxarGraooi2o1WxaqxYkirFkFgSQP+X9/8v5ZP6G0/tc4bk13k3
+JrvDkTm8Quc3Qw/xo2mMqVokQel047gDu6KK9vXSItvS8kwSVIXbC5SCkWVJiFZg
+hUtoVKxalLbdMKjlWErKlStSeOmTUeNgu7o2dzriub3bxvGBNRCbu64Y4kT37cPB
+IVhFJFkUhs5l65OBc/xyiJn9pvMTp04GA55Yats2p3krH/20yE1IIqJ4GE72HU7u
+YYM8Ubq87w0emUBOg4KzHejc5vnlBVjwWj2JDp78uxUmIZjGSSXv2+C+Vk2buCu5
+waLzxxtCqTeYuYkzGRiwWkxWMbuiWxbDiVZW3Hey4sc9aW7DLDfXXvBO8UcMOrE6
+ZHKIJJkSMuZM51ZhDeUpVpMillJZpvURzSaUu8TxmWyQ4sN1HLGJuVCyo1rGYzbr
+G6nipyrXO7Z7vS43pcWFeb5bU4saY8yVux4640jFLmIWjVTaVtUu6xHFmprC7jGK
+0oY3kblGmTI1k3ubEQo4klMaSc87iGrnc67p0dLLSaMM8WbgykoqxHuhUIiSVgcN
+s4ReusZ2W9pwcOl7l6OFfAh11ZNRZnWh576MW2q1bFKxVnLe+3xhp5sO/llybe2u
+6vZwQiJ63JuaKKNCGBLFFoua715rvMY1dJZyLBbrOZ5XV5qeIKQWC7JDCltJRnjc
+MWVKILJ3QpiLVSjwUMweGw6NEzJrF1i1Fr4tLGZjFiWmbSyagjBTJHzlDjD4ecQ6
+82snBkEBIfIt4B0kgWTyUekmpzCiQ5yh1wM4G8SeOG+NNwKdjDrIdZ3nnxc5azJS
+gWIWMigBFTrbdrcC3d1FulyStyYtcJGJReZlFmTVNTS4yPGPG6m4mU4UpUnHfhrr
+wWZWNdRvxxpo63XA16Gk8d9EE0Xhw0MmKiDFJNWV25mGqnfPHiSZDmy0tLVotC9m
+E3s7B8efHiO2NasFiqCyLUrMVTLjOkidBUijvl11NMuFdid4Pnq556pj0CZeWiKi
+RE4EFhe7nIB0MWSoVFVEKlEgdTKChKRIxmMBSnnMiG9dA90RI90p4oXnQyoVOzwO
+XmFFm7kU1EJfOeLl7pwCnXR2AkONIgVXEixG8HO3zk2uUXZ4KDRPGOMQcFigu6MB
+AynwUr5tMSp4Zm3S97lkYwrKbmYdS7N0thbaW8cMcuPGm2iNlkxeVSsrDdwwNvjm
+OMsQWV0bYCzEe/EuduWNOYe4t4neTnLWQ7yaysyt7Nq5jW3w84tro7rFbxrm3ROc
+yItTKia31oMVVVzMmKibuKkZYOb3Z3UnBYN1JxUtiasqwcnVw0qRd45sTvWJOrIZ
+cp3W8pbyud6rMm8TWW/KOlHvrjW2vNJMEmW6wk8+aSBDqHZe3wLGK4+WYxQYao+a
+FMLu3Zia4DJiYsHLW8vWVSaquNQVVUQ7dSGGWs7cgmMXdseVDzwzwgEvmRsCB5fB
+QVQXq0Zj5wJrB6UFaTgUTjAXmHe6AjIdsFIpFIYZ5zPJpMFN97axjrOebjescSIe
+OlxIjJYuYzMCWWMVihKxiTtW+9a1edTMrhldTnO8F0E1nhOr4yVONeDjTro3vk4e
+VFXbfM/6MUFZJlNZZ+RMiADvEl+AAvwQB3/wP//fyr////pgQg94DwHe94+e89AU
+H2NBDuwvr6eX3b72JJyiefd58+Vd8GQIqkiC6wJSbBm5uQAAAKq7u5JKoSaaqQKQ
+l21VBRUlVJEKkqkqklKlVSiCooVFg+BcYAA+7T5I+gBL4hzdzp5AMgOtGq4ADa13
+bYpbuB97AXvu0OR1329gffKPus6EiQIGhBMJE8hNE02U9Q0NDQGhp+qYgkgCIklT
+0IaaZADQAAAAAAaeiIiUn6JqJgaI2hNGAA0Bk9QAmgk9VJJEyZJ6npNlNNBoZoTC
+NDaTRkD1BiBEiAiKRKekw0mIBpo0aMTQZMjI00YIkiARpomQhkE1EfqnqNA02oAA
+Bo53OJuRwkNrkuMUJOhNQiCKMocWFChEEQrUGVTGgg0sMW2bqgkJBgahUxttdb03
+1poJEQAhSSeqS4RwucrgpgGDRopQUVIkNExkDQSGATIZGCmTCKIkUjZJZESZSaMx
+BmaRQQFlNGJKRIQihnBz6Pqb1dXa7ucrjgmcuCGgbYNpgK8AKEFIr8o4gKQFwMGj
+vveHmstx7CuEmmgYnRQhB3iu/mzlcrWdLQASIoDpmY0D1WpCxNppg6VoTStS8btY
+ssBpPUaC7k8vu+aXzwycRqJj4XNyCaEL8W6PxaWpQ2NtCG2kMTE6TpoDCHUaLpoa
+W1Dm0upHlZaDritXaTgmhQQNtsojjagMpMIthjtQ0xZUttPCv+T0I+nD/mkZQ8ZD
+zjB4ZdHI+/AJQaEvDFvWEt9eecKhyJv73XRVYff5934ryHcPuxRvk/OTX8AQBAXI
+YIooDEBEg2yTSZqtrWliJNFtWstQg22mzaljNU2WpmzNipNtVbdVtq9Gq1bKqplA
+FijAQQWAEEEFi/vVAFgAq0IILEWRBPH+qAgv4VAEvYexHwNTvPzKQKnq9pQt7ith
+SFQE3KoT92BcQS5rF1INoi0BQOEBIieUUBAgVIw0feYQlJIxilA5IyloT2iIDEdI
+qoG946hlU0gdFhujgx6GOFTZJSSpDwQuVTcllZOqH4ZyZC0BlmkC4cCwsYRI2uGk
+ouXauJiysgW2UY5iFJOlmzOCGH4iZGZYXJxDLdJ5I+okgLjdFcGyxGcTuXzC2QNL
+MmgZDlHJwpxaWwzw0jjTdXZYSK7Qr5tMVE1KLGpqexpkXBFICAcNsKQUZzMFIgVm
+knN2YKiGSuBbRzatIQgm+KaQZAS8uDHTnWrudlkM5iRrvStxKFwKKVWkrxS0Gc5b
+46jB4beDQDNZhiAYwuRpE1mlIxJctXj6hyy5cxgiVA40kzeEpxsaUJjkvd5gjFhh
+XMuSAhJw0YIxgxczl8mAJ0klHCWrkkchWY7a9j4Nu7SQ0sThJQxDvI40wEU4mYE8
+5vWPNKDdBTZq8WAka53apCRSSNpCqgUBIEqkKIRCCLDdFlqlxAohLqDOd5oy51ju
+LwUEYBLpqiqzTi6CEFgheJY6jhnYUa1qiwwzdN4qAkZJTTMxtG2YbaURoLQYUs8E
+LNMt81O4S4MhIrqC8Y2RJqiBikskgX1Ls0fwJ4OCaGBlINkgmKE6hXECwCkyUOuw
+dQqIBJJNGXYw2m6AgaYHhuJJJCxy4jkmrBKJZbYWNXa3ElQyVBKsZAmKeWFLmqL/
+aqWV6VDzrw/jTfYq6/bw8pT5+4NHZ5DpJIDo3mpeN6SJGMka7izeeoko43C2Epfp
+g4TpoXY3puxOTFNpHLlJkTMJ/cig8exbJ4wXM1wqI/cnSPX4zRN3hNeGDNBlDPCc
+RjKdSlEXMcLYVo5zrESzdhn5oQgF7Vy7d/xXre3+0a929Re2659oOIpGmnWprpit
+uWOpOh/bvzdU3UXeNVH5d/XiT9umGfzpTP5/9FU8nQ2l+WGPykDtzW8+x9V9eEZL
+xXZrntkuw70ekWyrvMhHrucZm9KfynpN9pZTE+0MTHTPffeZ6Ne/Z488WceGj41e
+xPJ4/IOaZmtZu7us13BA3KgkZGgZhXkEnmKKSCdMrtunVFC2hCzVzNmb4pa9MrfR
+5L368R+A5cTbzcuFIBItqqa9ZJWrv440HQdtONRRNMqQLRvCoXjJsHsNjp3oqjTU
+nuUk+tSSqY06SBeONJjOPZlitBWP2Y/a4myrWhja8Y48ITl3w70cPAUvOLu3N73x
+oNCWxRXKJMZBOcsIiYNsbb6IqgA1MYWCyzFLX46tyDIsrZmBdV11KBpmbcG2jSmW
+klZqbJwQmXHcfS+kqBbvzhoFYwQVevOaUWDtMkiQ4OL3wfiGhdLDJF2oWKWCGRKi
+hQlR9vBWB8QPr7h+/XlnwgBkZ6IHoruquvYHPb3d2c9Vu1qFs4DoTfPOZy5eaTfG
+EbeW2TVkZWcjbLyy5fXm3YKb4ufb/wb81JfR8qaTCaWBkN5OAgOisFhTR2+eXXkc
+3pGtx5da9R7O60uzr4vD1ctQeFni4kxCBF61C2yR4amYWm6emxGhMsrBSNygglLJ
+ju41nhlzS1oTvHIJ3iKAtp6aslyLp2Xz4u2mDjOOFZxL3c45xPx8u1djCMsttzHL
+vlwW7OA48Dxvhzz0vTvl3lSnfgXC1bTvQOQPN9u0GMqUZDiUu+0SqNTncw4JrOJd
+C5ae2h229JhHJcsamPYtGY2nqSYKK7ZkCWcOaeo6wnA5uE6UmOicOKSlx01thtO2
+U5RWOvTw6+Fysmd8Kd83F6zpjTvnstmbnM78jhR6FmzlfenLa9NuMaGgsxrWUpGv
+xczOq5bXKtNQPDHEHk5QkHLA7Ei3HDC6vuGTk25mxRUpKKkrlGpasCNz44/k+3tD
+wDe5wjgdDHrPy8gsg2W5zWGfiMkjEJmgQcnm7BcPMOgmPy6pIvZOyXeDh5m5rpxh
+u2O72A7GexroWfc4Pg/Hs7+FoQ8r9jIQtaxoXODg+TR8z0PRzeAOoeeRuMi7hdOS
+81h4GqNyguIRmNhQKnFMJWaZLQzV+urXgFRWKiY8ZIxJo6GynpoUkgAnNj57hPkk
+CiIEgKoYhUZF/EFX75QYsoLiXAfylQHsFzFbiMlVTCoUCVRu0SOlVOuaqN2WvP1c
+77nObXJxriiMINSQogBTFkqqmEoC2VXvQXneIkUdJiMdJihT4fO2rWLdy1y9kXJW
+wjNZBRy2pfGS/8Lwdy9Cmq8fh9iYjz/X4mvTlzXpX65f5J38LH6DNGfi2efIIvIZ
+10n5NE1kN59vlWXnOfKiq7ER8fWpiWWAkhS+t+LrfbL2atTnX7FlB6UvlXavrdWX
+HX4WKTvtWbyZlXdbue7pYypbJ5UnERU0llbaJ5ZvPfC98s8bTLO12ZXNItLa866P
+2611pp3tR1vrwgjnvvzhWTmUw9oSQv1dZnBnZnRGfK8QzR5ObplZCCc5ujfT9R6v
+JL1s8iD5lDfnIokmLJsX6RI1PafLCcKs/Tg4AkOMBDBIQit/raxnAKMUBAZBr9yq
+s1/QXIbVpWgIAgmEILgYvh0yWOUmv3jAUfKBfkdBqK0fOeYVyHCSZHQ6VMFk2HIr
+sD0RNdD7WUaPgRyIZcjoUkiB+YRfCWIeIcpVQPm6Q1BfgQaJofhQUEMgZOGDeJA9
+IPcCCRV4AUgAYPdw6IdQASI4FnXKQHmcg2w6ALxIMpE3ZaAxxeCoTJ0HTJEbxQOz
+vOl4O5xZ05zeiMkPQD3Jg7lQsvJS7KCkLTfpQmQlEPQs76EiGVGr9s8U7Q7yKUh6
+XQJAgcEPOW6rmfKxk0kYB6NnWeroUq8BmBHowHKGqH4gESifAlozD0+eQ0j4kT02
+LZ4WaPDW2w+IYtHZeImTcCWCRQLWBxyHfijRhjIpsF6jmAN08BB4SheIvMCQv3O9
+IBxhPz0SkvgHt3FCKbZGAMBDgJArIhI9BSIY8gc5jHmj+E+p9S/UAPryP36WOYnx
+34Ii7m5qkMm9mPRFNHfnTkYoj0GQr4OOeHrNeCzAYlhhc5B9Dx8dhsYr6Q8qgkWn
+ZzILYoTDz4BIKReoEWCYEF+GtaVpIuJ9O+zUiaxtJE68pepgbqZg0bMuPgcmlPnY
+g6RPUYjuCge0Uj8+CFpsWlfLghvvAgHOAUAaHOuBCwTEJ1iNdj0An37bTZlzLF7r
+i8nzHeJWS8Y6zJjrLCcqH4JHhRMidIZSkw8EIub4C6LDowDzJO0NYq0kILgV0Xug
+kCCZveXnig8iigRgdCLAPCpCoaA8AMX+M94icjIEiHwoKCEQhEX3HtmPnzHMo4T8
+NPcs2WZJYUlDwPX7E5AKIDuKSJ5wxZlKKsPwLwU8KDrAPQyZ+Jla9ISK/IHBC8hL
+AJi8KMiPQXfpqpK+sINQSQJGgioXVwYxvvIhV0sJEIsZpIely4rWA1B7CQPyZJLQ
+OahcYOxhvMPiDui49WezMfDbrdT686aJ+EQ2kJErap94yg2ISh+eqqB0QQPpBERM
+BBR+wkAAH2CA+KJEV+wAFcxBkBfIpkCZ2gULsgCIciHoB1hJQ9gIEguUgoVulKgg
+ntUcGAJr0oJHR6UMgdYB4JHEEfADtXgvEGyLL8+ama2oQMkPuYKfH8tziwAEEz7M
+qXYXsAoQHsjwQYik4/RunvQcfeEFs6nFYUjPo+WPguYCD9BY7j7j/PYGCWLpEvWu
+7/IZokD080Zk5wSD1AVqPRbsHEFBSr0sXtjlDoV5UI6IgNFeEvHffv4n0LiGvfQ5
+KFaH4Gqpz0Mxh9UDG/SNxy6H6DRQBcV+sBle8GiGx3QAXgqTMlrqSTAkr2SSQEFV
+9QEYOxHymNgdkGXw8Y+fRsHrgXw0GR09kMpCq5MlDiZDzgGOLxJuHDgRqQOet5Kp
+ezggkS1jSF0MO0JZ2yqQKSLF7UIgkEZK5OM/HYXOHJeOW9vBr8HHbkuWPxox6fms
+GumVzMqBnqecSQsuBDogwNRVQM9eBnKY0b2gZRHesEG2rOE4hkmdWB6V5y1KgqA1
+BGhikPMUQmrL7akye+mkvllmGuOkpMekkiTCSRACmrhLIlulAF9N5rthlpQ/XQkp
+01zssYOxeeIYRSTWbG2KBe2SOKBXQ5DU55aOtIvBbCk+zYig+CBkc6wH3bQOiaPv
+iscLEZjILNSSmX9OdgQXgna+HtgT0K4DwhmvgWOYSV0NSQuh8OHmg/ExtAoX4Pob
+q+dVHoXJ7hVNiGlVA2bGEGEH1bRIRBDhCQDs2oQtWIbppQHsVDJEQ2qoEALIiIJh
+iA5Ibr489zs18KLdIk2wVcpFRBx6+tiaCCj5EMxEzMCxQyTxJ8gAo5ZcS4gmZqKG
+0IlJiAbs+AEAgERPIieEQN50HzB2KnFiLFTJR7Q0qNQ4QXyCtKqBvJY82LSiEDtD
+SMDyDTVAlMx1KR0pMIRUiJ7YF7xSGDGU8MEIMgEjhWgojVGuXwHA5gtwUckHgZqo
+ezI2FDLsfUAQ3ZjoWaTPcjarhqjpVVrhZIQ6SsgnCohVS0itMJYhS0GK7o0K+ky5
+Y7gH3tCGO3xVQLLkMHlUMsfgQTLECRQxOLscliplNO4omhGOIJICZNgKF+kPDnyh
+3ErwNoatDOLWiFE0bhwyOBJEYDfGHjaG8xFtMBoWYA6HNgFycuim5Q7p2qoGrMrZ
+iV9I6DYoCVwCNjaBmh9VIACEQL8wi1kyAWKD09rwynBSL7BDbiUwABZHykpFUzkw
+tIaZSwCn04GkNoQOlasfSOXAYa64AHCJyMVG81eg8guTY5JtM+Empxh2Tu34PTsv
+KYzszJQ7oZY4pJ7Ci6JrOjEozq8F0gbgliwihrt8mJA2tda3aqkAfanxBmq2ZHU5
+0MvBycGZje43sNn5CYiGYNwJBIRNj/EqmR34YYffKj41OKr74Ihj1OnAC82B5rJS
+xuPCk5SnOICrQbAWFCMDZEMllsNkyUZkhMzrWJAiQm+4YC0K62MK0mlrmIc8DWIE
+FjI4sXzhL8vpkYEZwSigrGArDcBGj0gGFAr4FqGFQ1SOjTvH0TulJ1XWHAIDBQFU
+2BL7SBXa+99dSAvxCgIPnOIVhPMmTqqgYRFDUUEsUuxDfjmwMpaAek0+O9i+KyRp
+AG8DGE3qEdlsT9H5BPmUugch5YLMiAwTAkdnj7Y3zvRe4V3q41uohGNQNXT1Czcw
+ZOHoCYis+EOsTzziYOV5ZAwqoHrl2ATKFHnpRssDzmLdSlJDg7CCwocglqhuE+Eo
+jpsHOFogASPtXBwKZ802h3flM1s1tZA8sM4cPDnAT6uS6umbSt9nww6rDoI6wdYP
+ABwCkD4MpyWUDjtRIBzdU79HbBiX3vcZZGYTeQOlZsLH/hj78oFxFCAR3XQLAaGA
+dDiPltBD5eyxp0sa6DUCQ9yB3omnTqYzNOQ7dGkZocqlwqH9pIRCGyUGWBqQyCxy
+ehq7n/X63fbu3lvZivHbt2xc3MNMke2l6Uc4OiBRsMViTMcmSUZzTiouB0cMzMDc
+MhAn5DyXqlkdoH6TOX/ia/RnX2fHg6KQTF18xSwHCgLERnIs7MqnDBCuu5uA3wgA
+RixX8J05hR8PDApxlQIJmGtpRVjPTQ4WhDIBRyoZ5o1kdEjBho15A6uhLHeFCwXL
++9soCWWtfZsFJSQSLh/i4cADpq1VAz4GFTiJjhUbKosgl7B751ekmAW8qEBkjrpJ
+Tsj2D0AkIBD0X4qoEMX0AA0zQzao5o5TTzd5LNDKrnPfRfO1p44OgI4xIzjnvqR2
+Kz5Gwg+DJUL4dAjsyge+pYSePvEmKovgUXXilLjBfO4fT3oTYGwHVC0J2gKaO2qo
+GfZ3ymu7AqTWofKKHc998pr01xD2hKFgCFCO1eIWDjYeGgvGgWPaFTjzJlNzf2GX
+XyGuBywpbCI9aM6UO+tOtaQSqpWu2BesY5kXgwTFHTUPCg+y8oeXVwQ7yjsYrMak
+XS4XXDAJlUBAhUGk7oKAYdKTLFPcGom1CBxTjSRRsoYbfcOs9iE2BKVx8w4aN9z7
+7xds1BTpEnKyEY4TEIk3XeTS9hcaRANIX4k22qCDj84dwRJjo5YkxitJJAO9xXTk
+OFA/MS7JYZDxNviHhoYrl0bDxFvhTQwSQimhAnQFiYoaaHrMgkYrCOGBtDa5Bmne
+OFKwdG8DmOpCyvhqGYNRcB69KAlJSFA5hCUHKDE4GFcRwyRmEbfPPpveJJIDaQgw
+rWJ/P78yCMO9svE7GZpvnPSWaCtoEgL2jLabbxBVKIsbSY3YtJJ+NjNh8b8AilDw
+UPusGoZAu82EYImSRSk5GnwVIKWpSvFeBQnOAdAMuTV9DgEQgQgvrro7JHSHZZfM
+JCKmTtQFOCceAYcT265PCAg2SE+XhMkKlPgHB9+HTOoLI8s4BJuk9F7wqDCjRw6y
+D8yVeukRZ7qrFZYrAMMmhmgFDKEdZztkqFY4HuEkfuhz9pTsXzFtqqB5Tv5gsZ8h
+mh8x8wAfZSHNyDX0vZDTySL94fOjqfD0KHsVflvrWX5ow8Q0QhFVMbcpmX80Ezgf
+HYjMuA8wLy42E7Sz3rziuCIB2DsghxkkRy0Bzp6FVAA8MKcFvSjqknlxdHAT0wDn
+07kBQcd9oLK7tKmnZYnZZrh6DrhvciJ0ss6vdzXdwMQKJMWT7tXSHPByoD9hWNqM
+OwE85ypXmQLQwbXSkJWY6qxCwo6HFcFLCAk6bCVHFyYQc5H6Ezm+mNHD03wkk6j7
+m480R07W+QkhCKSnJVvGUvBBlRzDZDeeaNvGwHd0PT2wTy2HnkWtuMhkklgK66LZ
+BC6hKMJnOxOpo4YaB5V7rgiiWQXGCiJrYk4Y59qslhcA8/XJNJQLb+5tUzHJCBgj
+Qx3GrzzHn6xmZ9A0PtV9dbezpCHExoEDwlrH8dllA4YEY1mhsA0dIPPsj4Mi73vz
+nrsvJLs5YqABDfroHBg+ShQ0IgOs44NI4F8CIIsVXHQ6z3KS4MOhdxigYOImz2UG
+gJAuBhpsgLrldXnhNQ4jLCUyTxyhrIrwuyYrqo6MJzQ2Wl3AdDzKOb3Cydryz5Do
+pHBHMKBNdAOAdXJhYMgMb2s9Fp70MSClw9KpTbdzhHAuMGAtobHQJ2SURvgbbhyt
+BecsuXl+2jKigzt7goBTjmpC8RowanZdxJOhWjwhwrm99FSiJ2OgLLnm8pnjT1Fc
+CXCc0JaZijcmjpDACeVTrZneXxGRA+184I985kcHQIQIEFMgWfO635rg0SZSO/at
+HtcUKa3TZ8OJoImYsgRoKAhiZKIBUsG7yTOFlDFncMU9EG4CMLUKMxbiCaMDYdhs
+JSKdyLFJCQmviCCLgGuUz81ptojXx2oe4d2iHnAkVSdhzcfH2K2UnIQ9u0F30MHB
+OBY0UHMYYjgCQTAWMbwXTZQXaOgnfjckJ+BO475Zyfo8/R0NlEMBq8c94sZJiNrn
+yJ8OoMIDQPjt9uJK8Rk5aFDYbJfWSynwRhgIbQoB0+IsZPFGy4yADzZLYokaBywD
+CRmTeH5tmhDzPmA2rD32gaqneqHMNqA3FgsMePDM9KB69ebN4HOAhc26eoGFI1QJ
+m898wsO5qZxBxcWUgvtw5Q8AMEOOJJ8HEEk6B45ZyIoFaB5KW8FLb/M4KYSZIP/T
+y/DoMk5Ami3wPAH8EyWhTaUsFlQ+g6AEFdgHlJWNLpOCvdk3q+hWdqbTJWRS1dey
+wOAQwQUmsxpFozUQbFTRcPzhmHw0BxsEHFHdI2kUHjDkRPSGAp3SUo8BEdPPPTw4
+44KbQ4SZsIKdYe3WCo1EtM7zKTu1VAoZ7hPFDfU88SlCY2aHVSnVAOBA5wzuGlcH
+Rs8STcvGCu0xIzUFjkwcvlheRAzgRbJkzf/N0YjQwJYrJ16VzC1gueMTW4Rt5rYT
+IRNwYQYtHOtSD6ShBHOQzP37jm+TT/gvnq0DgyDuezyZv7FGKF8j4kpFLwakHPsy
+LSDphCyxQLl7xgnr+Pl8wbTsF8dx04kwB75wFRLdNRIBmhw2pH3UCbB9EgE9z5eI
+BPN3vYxzTZ4nEgVR4qoGQtM+BuGwlgV1WoHG4EaoNASMhGBgXYFRVYIXlASg6LSg
+GqeHmiyAsDilBBOqQsS4Og5rap1miKqAdUA6AdYTWmgTRQWeULDLBzlSEcEEDJbB
+4nTaBTC2glnEXi2haNhLoJcdgCNAkhcqbCc44gFrBrre1RE7eydRrtb9wdNITgOo
+j4QWulZiLl9z7V6DbnFmgcimAjOFhQs7UI75C551aKdXmUEHKSvEOCldH1YzE3wo
+E42BxwHl9Xk7YSa0g1vV9CriIWOztgqD6DgKN3AvOkS3ODdnTdtll+abk1SRIIGv
+fALBUOBR7ZFBZ4BUpBnSQ4hFHFEZ473Y3P+zY7O60Rs1LaWqHHIcwa8txlB4jJJE
+w5YZFHWAZUEtKyoIGdMwDYlA+A9mFgSZbOw4M6OOSmPkMl1OYzvpRASmvvXmUjTp
+8joGG1lR1cQpEEugzJBUyZnlygzInkeR9IZ+wHyATZQgPmd1ZmIUecB8pAzd6P0t
+AUK45zvDzCusNxdKPDohseJeeAI6ZvadwEcFQCRCgsXNcDfG6wqIm732cGQgwkIA
+SKEgydIjIZQ4a2thurU6wysrTQQglytZnEFtKoQOjdqfOmiDah274ym7EDxm9s9L
+CegGgMopkIt4LQ1Xtb9yBS7B2LUpK7hUpgHQVCXmwmbMOQqGHhGVvfpgEjVDoew6
+qNbwaB5vajnexW8pSBC73poOsSDMENqjGDoVUvvCS9M4jdfRrEmuQYwM5KDSHMK3
+B64lqG9DhQ0JoNQHlDlAPccRKnfODi2TDOoYNSZAcBzrUAVglyHGRUI0bMziEWOU
+JYnAOUMt6Rku3X2Za5l+nJIHiJXNq4xzccGdzaqu4qJJiDRBAN2TBKurol+bv9SB
+CSAX8+8Hl/r7sZnxy9PYe6Z7cvs98YtZ/SwPrgMD9OXynBh/XzxwXwdWFeXp/iVD
+kMgNriWpJDP1n5azCg6/xxxEvwpxkfhIP9s+2nQ/fn4vF9+jJ+ngfdWL4CPb5czf
+UQwvVtZEuz7Om9iWrwP/ePX0KAP0+V9inRoSgybccCP6dPd+K+f24YnQ9YpYUGst
+TKKFMYQdT2HL0fr+fbVW3qvv1NLVbRWSUrVJUxgSVjWktRaoqKNrFWmUUVMjUUmp
+li0zKazDabQ0YKDYxZMGg1BpRpYUwpQCMhoC8nsJe4+Dy3Xr8S8ifkOz/vaP7ETx
+FiYoqdkOeLbBtH+bHadmz2QGsccbGX7OU2D+LhZDxGPjMsOyV+DZO9PSeDPkEcZO
+SS8UzBJ+ecnUZhlZ9ZyM/ad22YYrjBcAz/3V2B8/JiuT7ED9kw+rGGSGmqTbJiMm
+LSysmTaS0aks2bSzWlZtg1EpSSYlNkqItCalNFstNttqaprSmpS0pqU1LNFgKpZV
+srWWrM0lJM1bEW0qbEmiLVtRGZUbSprWbNaLUqaks021KtbS2RlllbMsywtspLGj
+SaVEzMYk2NmzWptlrJWmSoRZSsptlZZLRGTaNKm2LJmmyUmSWRk0WpqlUZJJiWlp
+tkjGjUy01TaUkrKzSlLTMzAbNg2KlpJMl63e7/d+ENF1fgGLHuf56NGdqOvg7hSN
+iHHED5NKzQnm2yaAQJTIxieFJM3ij3X3qh5AHBhk2riuNRvBd1dJNK/o55W5e1NX
+ks/nngBUDz7INtUfFdK0JrgNgbjAdgkJGRczQCngL6Zh4BT2UW6xEWOCC4FzQuaj
+OxoBErUsV1z6K8cAICwJGRj6fB5iCC6h8QhiZB9qLr5NFyCenPzIPnc0WwotMInx
+4sAoHfMU5HgU6hhRBkppj/FgHNLt0ubr4APQXPI06DXqSSyDZid8zuPuLwXKN4cj
+jq/w8zETQQQXn+w0DiEJEiKh7fzQ5LMfgQXmXrdtA+sBzTIigGxVCwsOYhmJycnC
+CGplhE8/sdAhQXcsIRJFJISEJE8flHQO6cgR0ZCoE/TcCd+BBP7orIml5zlZgw9K
+QKKpGkiwgESxpnXK9pYwUAa89ij5sPoUYZjQ0lyAcxQc/xtRzIOJISJHL7Ny0JDw
+BwZa4MDUFR8D5CCCwzTyVsZejnQapAVGYICC5dDXtXOsmZXMO7mFWN7P56mEGIAc
+JHHBsharUAUcAp9UrviBIAxJ08i+RBO3Ah2QAgiK4kThwo8sDCf0aftxqENQKMTv
+TZBCNMVoDJwdi4fVhYNQyMy4KjH6SlEAvexZaMCmxViqK0e1JpDA33Zg0xuGQl9E
+hiQvQ2FHNA6XqGDe6CB3obIHAhBD+L/2H7JweCnNu3h8F/bQAgQghowH1UAW3ICg
+LRMWh9MD3nL6B5zvW/rtbABAW7j9J/ubhTjE1Dh6fjPlrh4F1mHx9l6oKaKdL9MC
+Czogscg9WEHR1P1lXLtPyv2av6+Uc38L73W4ynzSHQzT7n4a9fw9G0pHvHQQT3Ww
+CpsYtnkcGJdhEoMqdwTQQQWf8H7l+Sm0erEmuPTqAC3f/RC5LqgrQdfyPN+J3eTy
+V4GlQVzdO0KeqEArm/KUORmgILgIYcAUkDE9WuptiUObqmYfnmExHY8cNvsWx4o2
+QtFrwFybGSaII/YzOu4hsM00VwmYOAJQ3KQY+rag56UiZKVHIpnxryUn41uF8d2K
+fszLbyzAkMTuQc1BJQQHPuhBBej0s+yiFTpnRcrVGp26/SPoGgGLAjmBAhpnAPYi
+hGHgg8hN+hAh0NObgHp2R/M6Jo+S9Uw80pUFedRU1bYFRVog6sTPEHADwMAG0oUe
+ZTzCfk4pmd1M7BJIMNGsaaugBm+bdBpLDSNwIBiBVKx5dQgre1pCrhP2FD5vX9bb
+a28/PP14155vN5a8GIiRRgLCSaKIJMBu9u1u/IdZNWhKp6tcoZGbueNNIlSQLYOV
+guF/I1QEFvm6liJuQ/g648tjVjId/WMg6iEQnkcuhltYdGxoELryIDySIMiK9wD4
+MbBiPihigLkeo0OhARBcol9jMSNhf2ITsgILYNseps5hodZnnUYfDxJFi4UQzXNx
+EsQsWIsPUhf4XvqFHwQ+WPfTBIHct1LIZYv2+juqALF8D9dhxOkM18bdDBT3QEFx
+IIWRNxv+UV8R+J/0R2XJbrEIOYHU+pkgRzsDEdIZEebTO4gQJeqofJbdkqra4esL
+roGjHL6Gsy4rZI+PElgZlHIH1++YJmDEhF6psaR1U3IWVmpF3VwE9oiTMpi8Nzz+
+aHRDUDwW+WIdt3zPNOewJzPCB9E6jmCYHFX8LoITudMz7/N1SyV8kTcL0XLh4A7N
+JzfBgyjFkYbKgC8xPTQ2NEVHr3NX3I8oB8QLJn4JCrIRrrR5SSiELOBCqIlECSOq
+AgtNF/5UYIUAbvmgBgPL1xIT9UkTRqqrX53ixpCNGKHEwP1PwJh+ma3ptrBwODbq
+SORcDEiR6PVwOxokOUEsjBbkzcaucQzU4IBkiIQDSXJdCotjbIzzDs8lfNscXA3I
+EjvBoCBmX1Xq+IE6m5+HREB7xUkefMhRTIUUVEoGUY2sxAvjsdB3GZnYoMTuuOZk
+0IILqZh+sKgLQ1ULBUF4SYf1u+nDkki7SjNoBQWIGv3PuY3TIDM1QtuJ3SNep/DE
+5GEdQMHhYWdISJCEh+RRD7S+bd8OK+sbha0qU3NES7e5JJCEsxa4lA5ucJdrboo7
+v42uXj7XKXZXimppWTWQJDU2Uks0imZSWU2bLZWUpEzCgmWQzZKmlstNa2pqlKaa
+aU0pppMDbLLVlqzSSa2lTEtKzZJmtWpNSkylFpqsptkZrNNSzS1S2bNoqllIpMmS
+lmYDKLKzVm1LKVNkglKVKmyy0EstNixZmkjEiWms2xGFpVEWVNNKkSaWUpmMKLNQ
+l1leHUD7BQQf0nxooh+rfDYdYFRbCkgUOlBI6EukdLgodLEh6iosAIZUDGcFIBnT
+5PfxeXIybIEK3a2JhwXN4a5XZyCUN1QHKuKm53cudZGkYw+CUhgAg4jiFUxQcoWX
+ZiDnC1kcAxisjx4FhBuB1RLpkW/L1JdQMQyPlqBhAGDxWuoWKaLLctSBSGSu4x/U
++UGMFxxCH7+CQBDUTBsMAfQX99QooSAcCZEiD6vqNtZoMtphkjx94b82mEcdDU6C
+GIfhpBNHRGdiSEhKQ5wXmRP0FuHscjHIQQXE+/JA9QIe5u/rPZ7iGp3RjqDlESQZ
+JCQm/LYfclj52MSyQjrCotj6Nhs9YNtpjG0eYiFHs4e+RkLZGv6lQVs25H8UcydI
+dBwSSJWZ2GkMV5JBvs3IEHqRvh5VCbiosL1RQbNSevAFkgodQSGXyDwMAKI48pbY
+nKYY5o3AkxfgcNu/2TS8/z4OpVwpwYLoslFDS0dpbVLklyLktcy0qrt1rkkVDQKa
+U5mIfn7qbHUwB+pUzzDYgdOwHNMsQqIeAQgWJ7CdQLne/Uch/L74GbnkIeSHVY7B
+6HzdzDBZDLh9FDDd7l51/E5mJCBgdFYeAu3YglszcA0yVJwA+V7zU+xXQdNIJq0w
+kfMItgm3gj2uGRgGUX4BpO2ZVeDftfXE9vP1ve16wzwEEF4VAF3VrV67Ndd89m7O
+GA6EokveXN9MfaQsQ3ZZKcK50mcwJlSsZTgk98c5KYw84IzEZbkvNTsNqzPLKyHo
+Px0sFlfMO5q7Gy/RLjgGa3WwaF0oI5J5CEBrzAuFdT9Mc82Cdw1XLYdAocXnucxw
+MDq4Gb5ImDg/Y1aNUuciSSLGs30w7o64wiPJkCOJGESEZEDZGBLmOHlrwGGQG1zj
+MtuCoxq7RpQlgtQ/YQ5xHKBJJHiia0FHVsRLGQe6Aj+2KgIUQACACiJEFxCraZaP
+BqeGpHqJ2lIlZ0RymyqrLMZVKEz6wYDwNnVwEvXcGMYxgkEpwJK03QsQ0IAGhJqy
+CBkmqpjC2e6t4I+Zf0JUTC8cgiBBIMOpm5aNIYWCqlcG2GZjNkLK8i6B/LSEtoDR
+RIJtyOGwPFu5CEb0Y2d1QVrHSAerk2mlwOR0esAyQ5waYkWyRMAgkNlX1WA43hGO
+YdDY3OWXJQzDIuXC51atcCh9k/jjTxk4r31uGHUMNV7DyEEFu9aoidiNHFzHFW3k
+pl23DYUqswRQLrmUK++C6OIeCEEGO4Oxqcy5rvYfEQIEszhUi+UBMa/NHV+bZCGB
+BmDsfjN+oGAKjwgfAOjBz3eAT0JSBhgZHiXA7HejAOj31UJ0cC5soXLOxcOBUy41
+LJM6Q8Jwpx4F2KjgcPvn3BRaXEe2Z4vPu2/yeP+aH5JvaiC4fKQAcndicHNDcD9b
+ShgrZAQXSGTpCSlPzKD5gwnhsz+p8ujoewiFBY3pKLSeXXMDRxzJq44NJzlzG7rV
+oWrj1/nLbhdUFc+SIUCENGZwNenyhKIbAqfWTOCRY+YUj3gzmpUR68AgUjUPy+0G
+2hIxUaJCNpMRpoFYjY0WIzNmFoMaNFtEYklpFixGtGxg0UUVJoKiwYNaTRqTKQRU
+G1Bo221i1VFhYBqNjRFIKqgpJIRS7/L9Xk8v315svJO9OR4u/ONn5FGPE3fMqdtS
+xkZBu7kta5NbuU8MxyZMYMgmsNmMhnKfGmtyIG2LzBpqWYIbdmCYi0lYLJxwCFFa
+zJE6zEudHD27ZzbOeSgpk/HnkQbT7twqaaJXNvUzMuUt1hyhU7ceZcph42+VTlXU
+cZ9UZZJyYojLjaeJHfJU1UZUEmBfLumu8yW5skuyE9uh2BmVxJZi6KxaXBNwSolw
+BqBcQLj3ucNZIYZLYtirLu3brW6UYgZgZJiDIGiwpsgg7g1AITkgM6FHITxDDnGt
+4SDHzZbL5s8fec5PCq5DOzDRdWS+0h5Y2INZak1D29cpVyb2aVrV3Wlt7rQhLa3e
+m3ZwPNcXywE2Qesk1XN24HvZ2Xa6nlm8Pf/xdyRThQkO1NjuAA== `)
diff --git a/gcc/testsuite/go.test/test/bench/go1/parser_test.go b/gcc/testsuite/go.test/test/bench/go1/parser_test.go
index 26580b88725..7848cadd228 100644
--- a/gcc/testsuite/go.test/test/bench/go1/parser_test.go
+++ b/gcc/testsuite/go.test/test/bench/go1/parser_test.go
@@ -33,7 +33,7 @@ func makeParserBytes() []byte {
return b
}
-func BenchmarkParse(b *testing.B) {
+func BenchmarkGoParse(b *testing.B) {
b.SetBytes(int64(len(parserbytes)))
for i := 0; i < b.N; i++ {
if _, err := parser.ParseFile(token.NewFileSet(), "", parserbytes, parser.ParseComments); err != nil {
diff --git a/gcc/testsuite/go.test/test/bench/go1/regexp_test.go b/gcc/testsuite/go.test/test/bench/go1/regexp_test.go
new file mode 100644
index 00000000000..3ce9f3a2c67
--- /dev/null
+++ b/gcc/testsuite/go.test/test/bench/go1/regexp_test.go
@@ -0,0 +1,59 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package go1
+
+import (
+ "math/rand"
+ "regexp"
+ "testing"
+)
+
+// benchmark based on regexp/exec_test.go
+
+var regexpText []byte
+
+func makeRegexpText(n int) []byte {
+ rand.Seed(0) // For reproducibility.
+ if len(regexpText) >= n {
+ return regexpText[:n]
+ }
+ regexpText = make([]byte, n)
+ for i := range regexpText {
+ if rand.Intn(30) == 0 {
+ regexpText[i] = '\n'
+ } else {
+ regexpText[i] = byte(rand.Intn(0x7E+1-0x20) + 0x20)
+ }
+ }
+ return regexpText
+}
+
+func benchmark(b *testing.B, re string, n int) {
+ r := regexp.MustCompile(re)
+ t := makeRegexpText(n)
+ b.ResetTimer()
+ b.SetBytes(int64(n))
+ for i := 0; i < b.N; i++ {
+ if r.Match(t) {
+ b.Fatal("match!")
+ }
+ }
+}
+
+const (
+ easy0 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ$"
+ easy1 = "A[AB]B[BC]C[CD]D[DE]E[EF]F[FG]G[GH]H[HI]I[IJ]J$"
+ medium = "[XYZ]ABCDEFGHIJKLMNOPQRSTUVWXYZ$"
+ hard = "[ -~]*ABCDEFGHIJKLMNOPQRSTUVWXYZ$"
+)
+
+func BenchmarkRegexpMatchEasy0_32(b *testing.B) { benchmark(b, easy0, 32<<0) }
+func BenchmarkRegexpMatchEasy0_1K(b *testing.B) { benchmark(b, easy0, 1<<10) }
+func BenchmarkRegexpMatchEasy1_32(b *testing.B) { benchmark(b, easy1, 32<<0) }
+func BenchmarkRegexpMatchEasy1_1K(b *testing.B) { benchmark(b, easy1, 1<<10) }
+func BenchmarkRegexpMatchMedium_32(b *testing.B) { benchmark(b, medium, 1<<0) }
+func BenchmarkRegexpMatchMedium_1K(b *testing.B) { benchmark(b, medium, 1<<10) }
+func BenchmarkRegexpMatchHard_32(b *testing.B) { benchmark(b, hard, 32<<0) }
+func BenchmarkRegexpMatchHard_1K(b *testing.B) { benchmark(b, hard, 1<<10) }
diff --git a/gcc/testsuite/go.test/test/bench/go1/time_test.go b/gcc/testsuite/go.test/test/bench/go1/time_test.go
new file mode 100644
index 00000000000..4687de31c13
--- /dev/null
+++ b/gcc/testsuite/go.test/test/bench/go1/time_test.go
@@ -0,0 +1,25 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package go1
+
+// benchmark based on time/time_test.go
+
+import (
+ "testing"
+ "time"
+)
+
+func BenchmarkTimeParse(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ time.Parse(time.ANSIC, "Mon Jan 2 15:04:05 2006")
+ }
+}
+
+func BenchmarkTimeFormat(b *testing.B) {
+ t := time.Unix(1265346057, 0)
+ for i := 0; i < b.N; i++ {
+ t.Format("Mon Jan 2 15:04:05 2006")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/bench/shootout/timing.sh b/gcc/testsuite/go.test/test/bench/shootout/timing.sh
index d269b875680..2db895c2630 100755
--- a/gcc/testsuite/go.test/test/bench/shootout/timing.sh
+++ b/gcc/testsuite/go.test/test/bench/shootout/timing.sh
@@ -10,6 +10,14 @@ O=$GOCHAR
GC="go tool ${O}g"
LD="go tool ${O}l"
+gccm=""
+case "$O" in
+8)
+ gccm=-m32;;
+6)
+ gccm=-m64;;
+esac
+
PATH=.:$PATH
havegccgo=false
@@ -78,7 +86,7 @@ run() {
fasta() {
runonly echo 'fasta -n 25000000'
- run 'gcc -O2 fasta.c' a.out 25000000
+ run "gcc $gccm -O2 fasta.c" a.out 25000000
run 'gccgo -O2 fasta.go' a.out -n 25000000 #commented out until WriteString is in bufio
run 'gc fasta' $O.out -n 25000000
run 'gc_B fasta' $O.out -n 25000000
@@ -88,7 +96,7 @@ revcomp() {
runonly gcc -O2 fasta.c
runonly a.out 25000000 > x
runonly echo 'reverse-complement < output-of-fasta-25000000'
- run 'gcc -O2 reverse-complement.c' a.out < x
+ run "gcc $gccm -O2 reverse-complement.c" a.out < x
run 'gccgo -O2 reverse-complement.go' a.out < x
run 'gc reverse-complement' $O.out < x
run 'gc_B reverse-complement' $O.out < x
@@ -97,7 +105,7 @@ revcomp() {
nbody() {
runonly echo 'nbody -n 50000000'
- run 'gcc -O2 nbody.c -lm' a.out 50000000
+ run "gcc $gccm -O2 nbody.c -lm" a.out 50000000
run 'gccgo -O2 nbody.go' a.out -n 50000000
run 'gc nbody' $O.out -n 50000000
run 'gc_B nbody' $O.out -n 50000000
@@ -105,7 +113,7 @@ nbody() {
binarytree() {
runonly echo 'binary-tree 15 # too slow to use 20'
- run 'gcc -O2 binary-tree.c -lm' a.out 15
+ run "gcc $gccm -O2 binary-tree.c -lm" a.out 15
run 'gccgo -O2 binary-tree.go' a.out -n 15
run 'gccgo -O2 binary-tree-freelist.go' a.out -n 15
run 'gc binary-tree' $O.out -n 15
@@ -114,7 +122,7 @@ binarytree() {
fannkuch() {
runonly echo 'fannkuch 12'
- run 'gcc -O2 fannkuch.c' a.out 12
+ run "gcc $gccm -O2 fannkuch.c" a.out 12
run 'gccgo -O2 fannkuch.go' a.out -n 12
run 'gccgo -O2 fannkuch-parallel.go' a.out -n 12
run 'gc fannkuch' $O.out -n 12
@@ -126,7 +134,7 @@ regexdna() {
runonly gcc -O2 fasta.c
runonly a.out 100000 > x
runonly echo 'regex-dna 100000'
- run 'gcc -O2 regex-dna.c -lpcre' a.out <x
+ run "gcc $gccm -O2 regex-dna.c -lpcre" a.out <x
run 'gccgo -O2 regex-dna.go' a.out <x
run 'gccgo -O2 regex-dna-parallel.go' a.out <x
run 'gc regex-dna' $O.out <x
@@ -137,7 +145,7 @@ regexdna() {
spectralnorm() {
runonly echo 'spectral-norm 5500'
- run 'gcc -O2 spectral-norm.c -lm' a.out 5500
+ run "gcc $gccm -O2 spectral-norm.c -lm" a.out 5500
run 'gccgo -O2 spectral-norm.go' a.out -n 5500
run 'gc spectral-norm' $O.out -n 5500
run 'gc_B spectral-norm' $O.out -n 5500
@@ -160,7 +168,7 @@ knucleotide() {
mandelbrot() {
runonly echo 'mandelbrot 16000'
- run 'gcc -O2 mandelbrot.c' a.out 16000
+ run "gcc $gccm -O2 mandelbrot.c" a.out 16000
run 'gccgo -O2 mandelbrot.go' a.out -n 16000
run 'gc mandelbrot' $O.out -n 16000
run 'gc_B mandelbrot' $O.out -n 16000
@@ -168,7 +176,7 @@ mandelbrot() {
meteor() {
runonly echo 'meteor 2098'
- run 'gcc -O2 meteor-contest.c' a.out 2098
+ run "gcc $gccm -O2 meteor-contest.c" a.out 2098
run 'gccgo -O2 meteor-contest.go' a.out -n 2098
run 'gc meteor-contest' $O.out -n 2098
run 'gc_B meteor-contest' $O.out -n 2098
@@ -176,7 +184,7 @@ meteor() {
pidigits() {
runonly echo 'pidigits 10000'
- run 'gcc -O2 pidigits.c -lgmp' a.out 10000
+ run "gcc $gccm -O2 pidigits.c -lgmp" a.out 10000
run 'gccgo -O2 pidigits.go' a.out -n 10000
run 'gc pidigits' $O.out -n 10000
run 'gc_B pidigits' $O.out -n 10000
@@ -184,14 +192,14 @@ pidigits() {
threadring() {
runonly echo 'threadring 50000000'
- run 'gcc -O2 threadring.c -lpthread' a.out 50000000
+ run "gcc $gccm -O2 threadring.c -lpthread" a.out 50000000
run 'gccgo -O2 threadring.go' a.out -n 50000000
run 'gc threadring' $O.out -n 50000000
}
chameneos() {
runonly echo 'chameneos 6000000'
- run 'gcc -O2 chameneosredux.c -lpthread' a.out 6000000
+ run "gcc $gccm -O2 chameneosredux.c -lpthread" a.out 6000000
run 'gccgo -O2 chameneosredux.go' a.out 6000000
run 'gc chameneosredux' $O.out 6000000
}
diff --git a/gcc/testsuite/go.test/test/bigalg.go b/gcc/testsuite/go.test/test/bigalg.go
index 55a15c30abe..60e822942e2 100644
--- a/gcc/testsuite/go.test/test/bigalg.go
+++ b/gcc/testsuite/go.test/test/bigalg.go
@@ -15,18 +15,21 @@ type T struct {
d byte
}
-var a = []int{ 1, 2, 3 }
+var a = []int{1, 2, 3}
var NIL []int
func arraycmptest() {
if NIL != nil {
println("fail1:", NIL, "!= nil")
+ panic("bigalg")
}
if nil != NIL {
println("fail2: nil !=", NIL)
+ panic("bigalg")
}
if a == nil || nil == a {
println("fail3:", a, "== nil")
+ panic("bigalg")
}
}
@@ -49,12 +52,14 @@ func maptest() {
t1 := mt[0]
if t1.a != t.a || t1.b != t.b || t1.c != t.c || t1.d != t.d {
println("fail: map val struct", t1.a, t1.b, t1.c, t1.d)
+ panic("bigalg")
}
ma[1] = a
a1 := ma[1]
if !SameArray(a, a1) {
println("fail: map val array", a, a1)
+ panic("bigalg")
}
}
@@ -72,15 +77,18 @@ func chantest() {
t1 := <-ct
if t1.a != t.a || t1.b != t.b || t1.c != t.c || t1.d != t.d {
println("fail: map val struct", t1.a, t1.b, t1.c, t1.d)
+ panic("bigalg")
}
a1 := <-ca
if !SameArray(a, a1) {
println("fail: map val array", a, a1)
+ panic("bigalg")
}
}
-type E struct { }
+type E struct{}
+
var e E
func interfacetest() {
@@ -90,6 +98,7 @@ func interfacetest() {
a1 := i.([]int)
if !SameArray(a, a1) {
println("interface <-> []int", a, a1)
+ panic("bigalg")
}
pa := new([]int)
*pa = a
@@ -97,12 +106,14 @@ func interfacetest() {
a1 = *i.(*[]int)
if !SameArray(a, a1) {
println("interface <-> *[]int", a, a1)
+ panic("bigalg")
}
i = t
t1 := i.(T)
if t1.a != t.a || t1.b != t.b || t1.c != t.c || t1.d != t.d {
println("interface <-> struct", t1.a, t1.b, t1.c, t1.d)
+ panic("bigalg")
}
i = e
diff --git a/gcc/testsuite/go.test/test/blank.go b/gcc/testsuite/go.test/test/blank.go
index ee618b14858..7f7d9f6f7fb 100644
--- a/gcc/testsuite/go.test/test/blank.go
+++ b/gcc/testsuite/go.test/test/blank.go
@@ -8,6 +8,11 @@
package main
+import (
+ "os"
+ "unsafe"
+)
+
import _ "fmt"
var call string
@@ -102,8 +107,19 @@ func main() {
panic(sum)
}
+ // exp/ssa/interp doesn't yet skip blank fields in struct
+ // equivalence. It also cannot support unsafe.Pointer.
+ if os.Getenv("GOSSAINTERP") == "" {
+ type T1 struct{ x, y, z int }
+ t1 := *(*T)(unsafe.Pointer(&T1{1, 2, 3}))
+ t2 := *(*T)(unsafe.Pointer(&T1{4, 5, 6}))
+ if t1 != t2 {
+ panic("T{} != T{}")
+ }
+ }
+
h(a, b)
-
+
m()
}
@@ -133,14 +149,13 @@ func fp1(x, y int) {
}
}
-
func m() {
var i I
-
+
i = TI{}
i.M(1, 1)
i.M(2, 2)
-
+
fp(1, 1)
fp(2, 2)
}
@@ -162,4 +177,3 @@ func _() {
func ff() {
var _ int = 1
}
-
diff --git a/gcc/testsuite/go.test/test/blank1.go b/gcc/testsuite/go.test/test/blank1.go
index c6e038a0d92..f7e98b44168 100644
--- a/gcc/testsuite/go.test/test/blank1.go
+++ b/gcc/testsuite/go.test/test/blank1.go
@@ -9,8 +9,13 @@
package _ // ERROR "invalid package name _"
+var t struct {
+ _ int
+}
+
func main() {
_() // ERROR "cannot use _ as value"
x := _+1 // ERROR "cannot use _ as value"
_ = x
+ _ = t._ // ERROR "cannot refer to blank field|invalid use of"
}
diff --git a/gcc/testsuite/go.test/test/bugs/bug434.go b/gcc/testsuite/go.test/test/bugs/bug434.go
deleted file mode 100644
index 5eec7a577e7..00000000000
--- a/gcc/testsuite/go.test/test/bugs/bug434.go
+++ /dev/null
@@ -1,10 +0,0 @@
-// $G $D/$F.dir/one.go && $G $D/$F.dir/two.go || echo BUG:bug434
-
-// NOTE: This test is not run by 'run.go' and so not run by all.bash.
-// To run this test you must use the ./run shell script.
-
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package ignored
diff --git a/gcc/testsuite/go.test/test/chan/select2.go b/gcc/testsuite/go.test/test/chan/select2.go
index 40bc357b5d7..4a081391261 100644
--- a/gcc/testsuite/go.test/test/chan/select2.go
+++ b/gcc/testsuite/go.test/test/chan/select2.go
@@ -47,7 +47,7 @@ func main() {
runtime.GC()
runtime.ReadMemStats(memstats)
- if memstats.Alloc-alloc > 1e5 {
+ if memstats.Alloc-alloc > 1.1e5 {
println("BUG: too much memory for 100,000 selects:", memstats.Alloc-alloc)
}
}
diff --git a/gcc/testsuite/go.test/test/cmp.go b/gcc/testsuite/go.test/test/cmp.go
index a56ca6eaddd..5be64561d59 100644
--- a/gcc/testsuite/go.test/test/cmp.go
+++ b/gcc/testsuite/go.test/test/cmp.go
@@ -8,9 +8,13 @@
package main
-import "unsafe"
+import (
+ "os"
+ "unsafe"
+)
var global bool
+
func use(b bool) { global = b }
func stringptr(s string) uintptr { return *(*uintptr)(unsafe.Pointer(&s)) }
@@ -38,8 +42,12 @@ func main() {
var c string = "hello"
var d string = "hel" // try to get different pointer
d = d + "lo"
- if stringptr(c) == stringptr(d) {
- panic("compiler too smart -- got same string")
+
+ // exp/ssa/interp can't handle unsafe.Pointer.
+ if os.Getenv("GOSSAINTERP") != "" {
+ if stringptr(c) == stringptr(d) {
+ panic("compiler too smart -- got same string")
+ }
}
var e = make(chan int)
@@ -283,7 +291,7 @@ func main() {
isfalse(ix != z)
isfalse(iz != x)
}
-
+
// structs with _ fields
{
var x = struct {
@@ -296,7 +304,7 @@ func main() {
x: 1, y: 2, z: 3,
}
var ix interface{} = x
-
+
istrue(x == x)
istrue(x == ix)
istrue(ix == x)
diff --git a/gcc/testsuite/go.test/test/cmplx.go b/gcc/testsuite/go.test/test/cmplx.go
index 248672e7dd5..2d8a6229d62 100644
--- a/gcc/testsuite/go.test/test/cmplx.go
+++ b/gcc/testsuite/go.test/test/cmplx.go
@@ -9,12 +9,23 @@
package main
+type (
+ Float32 float32
+ Float64 float64
+ Complex64 complex64
+ Complex128 complex128
+)
+
var (
f32 float32
f64 float64
+ F32 Float32
+ F64 Float64
c64 complex64
c128 complex128
+ C64 Complex64
+ C128 Complex128
)
func main() {
@@ -25,4 +36,19 @@ func main() {
_ = complex128(0) // ok
_ = complex(f32, f64) // ERROR "complex"
_ = complex(f64, f32) // ERROR "complex"
+ _ = complex(f32, F32) // ERROR "complex"
+ _ = complex(F32, f32) // ERROR "complex"
+ _ = complex(f64, F64) // ERROR "complex"
+ _ = complex(F64, f64) // ERROR "complex"
+
+ c128 = complex(f32, f32) // ERROR "cannot use"
+ c64 = complex(f64, f64) // ERROR "cannot use"
+
+ c64 = complex(1.0, 2.0) // ok, constant is untyped
+ c128 = complex(1.0, 2.0)
+ C64 = complex(1.0, 2.0)
+ C128 = complex(1.0, 2.0)
+
+ C64 = complex(f32, f32) // ERROR "cannot use"
+ C128 = complex(f64, f64) // ERROR "cannot use"
}
diff --git a/gcc/testsuite/go.test/test/cmplxdivide.go b/gcc/testsuite/go.test/test/cmplxdivide.go
index 92a98356d0a..40c84486da0 100644
--- a/gcc/testsuite/go.test/test/cmplxdivide.go
+++ b/gcc/testsuite/go.test/test/cmplxdivide.go
@@ -45,4 +45,7 @@ func main() {
fmt.Printf("%v/%v: expected %v error; got %v\n", t.f, t.g, t.out, x)
}
}
+ if bad {
+ panic("cmplxdivide failed.")
+ }
}
diff --git a/gcc/testsuite/go.test/test/const.go b/gcc/testsuite/go.test/test/const.go
index 80fbfaf3ea0..d583659c6c3 100644
--- a/gcc/testsuite/go.test/test/const.go
+++ b/gcc/testsuite/go.test/test/const.go
@@ -8,27 +8,29 @@
package main
+import "os"
+
const (
- c0 = 0
- cm1 = -1
- chuge = 1 << 100
+ c0 = 0
+ cm1 = -1
+ chuge = 1 << 100
chuge_1 = chuge - 1
- c1 = chuge >> 100
- c3div2 = 3/2
- c1e3 = 1e3
+ c1 = chuge >> 100
+ c3div2 = 3 / 2
+ c1e3 = 1e3
- ctrue = true
+ ctrue = true
cfalse = !ctrue
)
const (
- f0 = 0.0
- fm1 = -1.
- fhuge float64 = 1 << 100
+ f0 = 0.0
+ fm1 = -1.
+ fhuge float64 = 1 << 100
fhuge_1 float64 = chuge - 1
- f1 float64 = chuge >> 100
- f3div2 = 3./2.
- f1e3 float64 = 1e3
+ f1 float64 = chuge >> 100
+ f3div2 = 3. / 2.
+ f1e3 float64 = 1e3
)
func assert(t bool, s string) {
@@ -41,8 +43,8 @@ func ints() {
assert(c0 == 0, "c0")
assert(c1 == 1, "c1")
assert(chuge > chuge_1, "chuge")
- assert(chuge_1 + 1 == chuge, "chuge 1")
- assert(chuge + cm1 +1 == chuge, "cm1")
+ assert(chuge_1+1 == chuge, "chuge 1")
+ assert(chuge+cm1+1 == chuge, "cm1")
assert(c3div2 == 1, "3/2")
assert(c1e3 == 1000, "c1e3 int")
assert(c1e3 == 1e3, "c1e3 float")
@@ -81,9 +83,12 @@ func ints() {
func floats() {
assert(f0 == c0, "f0")
assert(f1 == c1, "f1")
- assert(fhuge == fhuge_1, "fhuge") // float64 can't distinguish fhuge, fhuge_1.
- assert(fhuge_1 + 1 == fhuge, "fhuge 1")
- assert(fhuge + fm1 +1 == fhuge, "fm1")
+ // TODO(gri): exp/ssa/interp constant folding is incorrect.
+ if os.Getenv("GOSSAINTERP") == "" {
+ assert(fhuge == fhuge_1, "fhuge") // float64 can't distinguish fhuge, fhuge_1.
+ }
+ assert(fhuge_1+1 == fhuge, "fhuge 1")
+ assert(fhuge+fm1+1 == fhuge, "fm1")
assert(f3div2 == 1.5, "3./2.")
assert(f1e3 == 1000, "f1e3 int")
assert(f1e3 == 1.e3, "f1e3 float")
diff --git a/gcc/testsuite/go.test/test/const1.go b/gcc/testsuite/go.test/test/const1.go
index 1580b76c683..58bddee7e07 100644
--- a/gcc/testsuite/go.test/test/const1.go
+++ b/gcc/testsuite/go.test/test/const1.go
@@ -9,6 +9,8 @@
package main
+import "unsafe"
+
type I interface{}
const (
@@ -86,3 +88,7 @@ func main() {
}
const ptr = nil // ERROR "const.*nil"
+const _ = string([]byte(nil)) // ERROR "is not a? ?constant"
+const _ = uintptr(unsafe.Pointer((*int)(nil))) // ERROR "is not a? ?constant"
+const _ = unsafe.Pointer((*int)(nil)) // ERROR "cannot be nil|invalid constant type"
+const _ = (*int)(nil) // ERROR "cannot be nil|invalid constant type"
diff --git a/gcc/testsuite/go.test/test/const4.go b/gcc/testsuite/go.test/test/const4.go
index 677fcefa750..2fb2d0664e8 100644
--- a/gcc/testsuite/go.test/test/const4.go
+++ b/gcc/testsuite/go.test/test/const4.go
@@ -9,7 +9,7 @@
package main
var b struct {
- a[10]int
+ a [10]int
}
var m map[string][20]int
@@ -61,17 +61,22 @@ var c1 = func() chan *[70]int {
func main() {
if n1 != 10 || n2 != 20 || n3 != 30 || n4 != 40 || n5 != 50 || n6 != 60 || n7 != 70 {
println("BUG:", n1, n2, n3, n4, n5, n6, n7)
+ panic("fail")
}
if !calledF {
println("BUG: did not call f")
+ panic("fail")
}
if <-c == nil {
println("BUG: did not receive from c")
+ panic("fail")
}
if !calledG {
println("BUG: did not call g")
+ panic("fail")
}
if <-c1 == nil {
println("BUG: did not receive from c1")
+ panic("fail")
}
}
diff --git a/gcc/testsuite/go.test/test/const5.go b/gcc/testsuite/go.test/test/const5.go
index d0eed137d1a..87fe33a3855 100644
--- a/gcc/testsuite/go.test/test/const5.go
+++ b/gcc/testsuite/go.test/test/const5.go
@@ -24,10 +24,10 @@ const (
n2 = len(m[""])
n3 = len(s[10])
- n4 = len(f()) // ERROR "must be constant|is not constant"
- n5 = len(<-c) // ERROR "must be constant|is not constant"
+ n4 = len(f()) // ERROR "is not a constant|is not constant"
+ n5 = len(<-c) // ERROR "is not a constant|is not constant"
- n6 = cap(f()) // ERROR "must be constant|is not constant"
- n7 = cap(<-c) // ERROR "must be constant|is not constant"
+ n6 = cap(f()) // ERROR "is not a constant|is not constant"
+ n7 = cap(<-c) // ERROR "is not a constant|is not constant"
)
diff --git a/gcc/testsuite/go.test/test/const6.go b/gcc/testsuite/go.test/test/const6.go
new file mode 100644
index 00000000000..c005ac3696d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/const6.go
@@ -0,0 +1,30 @@
+// errorcheck
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Ideal vs non-ideal bool. See issue 3915, 3923.
+
+package p
+
+type mybool bool
+type mybool1 bool
+
+var (
+ x, y int = 1, 2
+ c1 bool = x < y
+ c2 mybool = x < y
+ c3 mybool = c2 == (x < y)
+ c4 mybool = c2 == (1 < 2)
+ c5 mybool = 1 < 2
+ c6 mybool1 = x < y
+ c7 = c1 == c2 // ERROR "mismatched types|incompatible types"
+ c8 = c2 == c6 // ERROR "mismatched types|incompatible types"
+ c9 = c1 == c6 // ERROR "mismatched types|incompatible types"
+ _ = c2 && (x < y)
+ _ = c2 && (1 < 2)
+ _ = c1 && c2 // ERROR "mismatched types|incompatible types"
+ _ = c2 && c6 // ERROR "mismatched types|incompatible types"
+ _ = c1 && c6 // ERROR "mismatched types|incompatible types"
+)
diff --git a/gcc/testsuite/go.test/test/copy.go b/gcc/testsuite/go.test/test/copy.go
index 65ffb6ff8f5..e6108d905d1 100644
--- a/gcc/testsuite/go.test/test/copy.go
+++ b/gcc/testsuite/go.test/test/copy.go
@@ -132,6 +132,7 @@ func verify8(length, in, out, m int) {
n := ncopied(length, in, out)
if m != n {
fmt.Printf("count bad(%d %d %d): %d not %d\n", length, in, out, m, n)
+ os.Exit(1)
return
}
// before
@@ -172,6 +173,7 @@ func verifyS(length, in, out, m int) {
n := ncopied(length, in, out)
if m != n {
fmt.Printf("count bad(%d %d %d): %d not %d\n", length, in, out, m, n)
+ os.Exit(1)
return
}
// before
@@ -212,6 +214,7 @@ func verify16(length, in, out, m int) {
n := ncopied(length, in, out)
if m != n {
fmt.Printf("count bad(%d %d %d): %d not %d\n", length, in, out, m, n)
+ os.Exit(1)
return
}
// before
@@ -252,6 +255,7 @@ func verify32(length, in, out, m int) {
n := ncopied(length, in, out)
if m != n {
fmt.Printf("count bad(%d %d %d): %d not %d\n", length, in, out, m, n)
+ os.Exit(1)
return
}
// before
@@ -292,6 +296,7 @@ func verify64(length, in, out, m int) {
n := ncopied(length, in, out)
if m != n {
fmt.Printf("count bad(%d %d %d): %d not %d\n", length, in, out, m, n)
+ os.Exit(1)
return
}
// before
diff --git a/gcc/testsuite/go.test/test/ddd2.dir/ddd2.go b/gcc/testsuite/go.test/test/ddd2.dir/ddd2.go
new file mode 100644
index 00000000000..c9a26759260
--- /dev/null
+++ b/gcc/testsuite/go.test/test/ddd2.dir/ddd2.go
@@ -0,0 +1,16 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file is compiled and then imported by ddd3.go.
+
+package ddd
+
+func Sum(args ...int) int {
+ s := 0
+ for _, v := range args {
+ s += v
+ }
+ return s
+}
+
diff --git a/gcc/testsuite/go.test/test/ddd2.dir/ddd3.go b/gcc/testsuite/go.test/test/ddd2.dir/ddd3.go
new file mode 100644
index 00000000000..5486fe8a049
--- /dev/null
+++ b/gcc/testsuite/go.test/test/ddd2.dir/ddd3.go
@@ -0,0 +1,28 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test that variadic functions work across package boundaries.
+
+package main
+
+import "./ddd2"
+
+func main() {
+ if x := ddd.Sum(1, 2, 3); x != 6 {
+ println("ddd.Sum 6", x)
+ panic("fail")
+ }
+ if x := ddd.Sum(); x != 0 {
+ println("ddd.Sum 0", x)
+ panic("fail")
+ }
+ if x := ddd.Sum(10); x != 10 {
+ println("ddd.Sum 10", x)
+ panic("fail")
+ }
+ if x := ddd.Sum(1, 8); x != 9 {
+ println("ddd.Sum 9", x)
+ panic("fail")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/ddd2.go b/gcc/testsuite/go.test/test/ddd2.go
index a141a39c766..0d9f634ab60 100644
--- a/gcc/testsuite/go.test/test/ddd2.go
+++ b/gcc/testsuite/go.test/test/ddd2.go
@@ -1,18 +1,9 @@
-// skip
+// rundir
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// This file is compiled and then imported by ddd3.go.
-
-package ddd
-
-func Sum(args ...int) int {
- s := 0
- for _, v := range args {
- s += v
- }
- return s
-}
+// Test that variadic functions work across package boundaries.
+package ignored
diff --git a/gcc/testsuite/go.test/test/ddd3.go b/gcc/testsuite/go.test/test/ddd3.go
deleted file mode 100644
index d8de0a77e90..00000000000
--- a/gcc/testsuite/go.test/test/ddd3.go
+++ /dev/null
@@ -1,33 +0,0 @@
-// $G $D/ddd2.go && $G $D/$F.go && $L $F.$A && ./$A.out
-
-// NOTE: This test is not run by 'run.go' and so not run by all.bash.
-// To run this test you must use the ./run shell script.
-
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Test that variadic functions work across package boundaries.
-
-package main
-
-import "./ddd2"
-
-func main() {
- if x := ddd.Sum(1, 2, 3); x != 6 {
- println("ddd.Sum 6", x)
- panic("fail")
- }
- if x := ddd.Sum(); x != 0 {
- println("ddd.Sum 0", x)
- panic("fail")
- }
- if x := ddd.Sum(10); x != 10 {
- println("ddd.Sum 10", x)
- panic("fail")
- }
- if x := ddd.Sum(1, 8); x != 9 {
- println("ddd.Sum 9", x)
- panic("fail")
- }
-}
diff --git a/gcc/testsuite/go.test/test/decl.go b/gcc/testsuite/go.test/test/decl.go
index 6f84245f152..e2f126adb21 100644
--- a/gcc/testsuite/go.test/test/decl.go
+++ b/gcc/testsuite/go.test/test/decl.go
@@ -33,8 +33,9 @@ func main() {
m, h, s := f3()
_, _, _, _, _, _, _, _, _ = i, f, s, j, k, m, g, s, h
}
- if x() != "3" {
- println("x() failed")
+ if y := x(); y != "3" {
+ println("x() failed", y)
+ panic("fail")
}
_, _, _, _, _, _, _, _, _ = i, f, s, j, k, m, g, s, h
}
diff --git a/gcc/testsuite/go.test/test/declbad.go b/gcc/testsuite/go.test/test/declbad.go
index ff53ab0d7c5..728eceb7f1e 100644
--- a/gcc/testsuite/go.test/test/declbad.go
+++ b/gcc/testsuite/go.test/test/declbad.go
@@ -41,7 +41,8 @@ func main() {
{
// multiline no new variables
i := f1
- i := func() { // ERROR "redeclared|no new|incompatible"
+ i := func() int { // ERROR "redeclared|no new|incompatible"
+ return 0
}
_ = i
}
diff --git a/gcc/testsuite/go.test/test/defer.go b/gcc/testsuite/go.test/test/defer.go
index 2f67d356091..6731ab7ee8b 100644
--- a/gcc/testsuite/go.test/test/defer.go
+++ b/gcc/testsuite/go.test/test/defer.go
@@ -25,6 +25,7 @@ func test1() {
test1helper()
if result != "9876543210" {
fmt.Printf("test1: bad defer result (should be 9876543210): %q\n", result)
+ panic("defer")
}
}
@@ -41,6 +42,7 @@ func test2() {
test2helper()
if result != "9876543210" {
fmt.Printf("test2: bad defer result (should be 9876543210): %q\n", result)
+ panic("defer")
}
}
diff --git a/gcc/testsuite/go.test/test/divide.go b/gcc/testsuite/go.test/test/divide.go
index c91a33e9db2..b20f1062f62 100644
--- a/gcc/testsuite/go.test/test/divide.go
+++ b/gcc/testsuite/go.test/test/divide.go
@@ -13,36 +13,44 @@ import "fmt"
func f8(x, y, q, r int8) {
if t := x / y; t != q {
fmt.Printf("%d/%d = %d, want %d\n", x, y, t, q)
+ panic("divide")
}
if t := x % y; t != r {
fmt.Printf("%d%%%d = %d, want %d\n", x, y, t, r)
+ panic("divide")
}
}
func f16(x, y, q, r int16) {
if t := x / y; t != q {
fmt.Printf("%d/%d = %d, want %d\n", x, y, t, q)
+ panic("divide")
}
if t := x % y; t != r {
fmt.Printf("%d%%%d = %d, want %d\n", x, y, t, r)
+ panic("divide")
}
}
func f32(x, y, q, r int32) {
if t := x / y; t != q {
fmt.Printf("%d/%d = %d, want %d\n", x, y, t, q)
+ panic("divide")
}
if t := x % y; t != r {
fmt.Printf("%d%%%d = %d, want %d\n", x, y, t, r)
+ panic("divide")
}
}
func f64(x, y, q, r int64) {
if t := x / y; t != q {
fmt.Printf("%d/%d = %d, want %d\n", x, y, t, q)
+ panic("divide")
}
if t := x % y; t != r {
fmt.Printf("%d%%%d = %d, want %d\n", x, y, t, r)
+ panic("divide")
}
}
diff --git a/gcc/testsuite/go.test/test/dwarf/main.go b/gcc/testsuite/go.test/test/dwarf/dwarf.dir/main.go
index 175a09c7799..175a09c7799 100644
--- a/gcc/testsuite/go.test/test/dwarf/main.go
+++ b/gcc/testsuite/go.test/test/dwarf/dwarf.dir/main.go
diff --git a/gcc/testsuite/go.test/test/dwarf/z1.go b/gcc/testsuite/go.test/test/dwarf/dwarf.dir/z1.go
index 7f163e9a1d9..7f163e9a1d9 100644
--- a/gcc/testsuite/go.test/test/dwarf/z1.go
+++ b/gcc/testsuite/go.test/test/dwarf/dwarf.dir/z1.go
diff --git a/gcc/testsuite/go.test/test/dwarf/z10.go b/gcc/testsuite/go.test/test/dwarf/dwarf.dir/z10.go
index 19c70020e0c..19c70020e0c 100644
--- a/gcc/testsuite/go.test/test/dwarf/z10.go
+++ b/gcc/testsuite/go.test/test/dwarf/dwarf.dir/z10.go
diff --git a/gcc/testsuite/go.test/test/dwarf/z11.go b/gcc/testsuite/go.test/test/dwarf/dwarf.dir/z11.go
index c1d2f9180f1..c1d2f9180f1 100644
--- a/gcc/testsuite/go.test/test/dwarf/z11.go
+++ b/gcc/testsuite/go.test/test/dwarf/dwarf.dir/z11.go
diff --git a/gcc/testsuite/go.test/test/dwarf/z12.go b/gcc/testsuite/go.test/test/dwarf/dwarf.dir/z12.go
index 7455f189468..7455f189468 100644
--- a/gcc/testsuite/go.test/test/dwarf/z12.go
+++ b/gcc/testsuite/go.test/test/dwarf/dwarf.dir/z12.go
diff --git a/gcc/testsuite/go.test/test/dwarf/z13.go b/gcc/testsuite/go.test/test/dwarf/dwarf.dir/z13.go
index ecb3c4c8c71..ecb3c4c8c71 100644
--- a/gcc/testsuite/go.test/test/dwarf/z13.go
+++ b/gcc/testsuite/go.test/test/dwarf/dwarf.dir/z13.go
diff --git a/gcc/testsuite/go.test/test/dwarf/z14.go b/gcc/testsuite/go.test/test/dwarf/dwarf.dir/z14.go
index 134b39b64e2..134b39b64e2 100644
--- a/gcc/testsuite/go.test/test/dwarf/z14.go
+++ b/gcc/testsuite/go.test/test/dwarf/dwarf.dir/z14.go
diff --git a/gcc/testsuite/go.test/test/dwarf/z15.go b/gcc/testsuite/go.test/test/dwarf/dwarf.dir/z15.go
index d73819b443b..d73819b443b 100644
--- a/gcc/testsuite/go.test/test/dwarf/z15.go
+++ b/gcc/testsuite/go.test/test/dwarf/dwarf.dir/z15.go
diff --git a/gcc/testsuite/go.test/test/dwarf/z16.go b/gcc/testsuite/go.test/test/dwarf/dwarf.dir/z16.go
index 6c31651baa8..6c31651baa8 100644
--- a/gcc/testsuite/go.test/test/dwarf/z16.go
+++ b/gcc/testsuite/go.test/test/dwarf/dwarf.dir/z16.go
diff --git a/gcc/testsuite/go.test/test/dwarf/z17.go b/gcc/testsuite/go.test/test/dwarf/dwarf.dir/z17.go
index b742d167260..b742d167260 100644
--- a/gcc/testsuite/go.test/test/dwarf/z17.go
+++ b/gcc/testsuite/go.test/test/dwarf/dwarf.dir/z17.go
diff --git a/gcc/testsuite/go.test/test/dwarf/z18.go b/gcc/testsuite/go.test/test/dwarf/dwarf.dir/z18.go
index 84150ff0a35..84150ff0a35 100644
--- a/gcc/testsuite/go.test/test/dwarf/z18.go
+++ b/gcc/testsuite/go.test/test/dwarf/dwarf.dir/z18.go
diff --git a/gcc/testsuite/go.test/test/dwarf/z19.go b/gcc/testsuite/go.test/test/dwarf/dwarf.dir/z19.go
index bb2e2968417..bb2e2968417 100644
--- a/gcc/testsuite/go.test/test/dwarf/z19.go
+++ b/gcc/testsuite/go.test/test/dwarf/dwarf.dir/z19.go
diff --git a/gcc/testsuite/go.test/test/dwarf/z2.go b/gcc/testsuite/go.test/test/dwarf/dwarf.dir/z2.go
index 68bd58257d9..68bd58257d9 100644
--- a/gcc/testsuite/go.test/test/dwarf/z2.go
+++ b/gcc/testsuite/go.test/test/dwarf/dwarf.dir/z2.go
diff --git a/gcc/testsuite/go.test/test/dwarf/z20.go b/gcc/testsuite/go.test/test/dwarf/dwarf.dir/z20.go
index 03111e18452..03111e18452 100644
--- a/gcc/testsuite/go.test/test/dwarf/z20.go
+++ b/gcc/testsuite/go.test/test/dwarf/dwarf.dir/z20.go
diff --git a/gcc/testsuite/go.test/test/dwarf/z3.go b/gcc/testsuite/go.test/test/dwarf/dwarf.dir/z3.go
index 5e4ad3ae257..5e4ad3ae257 100644
--- a/gcc/testsuite/go.test/test/dwarf/z3.go
+++ b/gcc/testsuite/go.test/test/dwarf/dwarf.dir/z3.go
diff --git a/gcc/testsuite/go.test/test/dwarf/z4.go b/gcc/testsuite/go.test/test/dwarf/dwarf.dir/z4.go
index 1f28465c577..1f28465c577 100644
--- a/gcc/testsuite/go.test/test/dwarf/z4.go
+++ b/gcc/testsuite/go.test/test/dwarf/dwarf.dir/z4.go
diff --git a/gcc/testsuite/go.test/test/dwarf/z5.go b/gcc/testsuite/go.test/test/dwarf/dwarf.dir/z5.go
index 7f4eeb419a3..7f4eeb419a3 100644
--- a/gcc/testsuite/go.test/test/dwarf/z5.go
+++ b/gcc/testsuite/go.test/test/dwarf/dwarf.dir/z5.go
diff --git a/gcc/testsuite/go.test/test/dwarf/z6.go b/gcc/testsuite/go.test/test/dwarf/dwarf.dir/z6.go
index 241791dff2b..241791dff2b 100644
--- a/gcc/testsuite/go.test/test/dwarf/z6.go
+++ b/gcc/testsuite/go.test/test/dwarf/dwarf.dir/z6.go
diff --git a/gcc/testsuite/go.test/test/dwarf/z7.go b/gcc/testsuite/go.test/test/dwarf/dwarf.dir/z7.go
index 68c1ad0c243..68c1ad0c243 100644
--- a/gcc/testsuite/go.test/test/dwarf/z7.go
+++ b/gcc/testsuite/go.test/test/dwarf/dwarf.dir/z7.go
diff --git a/gcc/testsuite/go.test/test/dwarf/z8.go b/gcc/testsuite/go.test/test/dwarf/dwarf.dir/z8.go
index 16eed32a28d..16eed32a28d 100644
--- a/gcc/testsuite/go.test/test/dwarf/z8.go
+++ b/gcc/testsuite/go.test/test/dwarf/dwarf.dir/z8.go
diff --git a/gcc/testsuite/go.test/test/dwarf/z9.go b/gcc/testsuite/go.test/test/dwarf/dwarf.dir/z9.go
index cbb94b4d2be..cbb94b4d2be 100644
--- a/gcc/testsuite/go.test/test/dwarf/z9.go
+++ b/gcc/testsuite/go.test/test/dwarf/dwarf.dir/z9.go
diff --git a/gcc/testsuite/go.test/test/dwarf/dwarf.go b/gcc/testsuite/go.test/test/dwarf/dwarf.go
new file mode 100644
index 00000000000..32dd7d3d576
--- /dev/null
+++ b/gcc/testsuite/go.test/test/dwarf/dwarf.go
@@ -0,0 +1,10 @@
+// rundir
+
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// See issue 2241 and issue 1878: dwarf include stack size
+// issues in linker.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/errchk b/gcc/testsuite/go.test/test/errchk
index 6b00570bdec..b8b312a9237 100755
--- a/gcc/testsuite/go.test/test/errchk
+++ b/gcc/testsuite/go.test/test/errchk
@@ -31,7 +31,7 @@ if(@ARGV < 1) {
# Grab SOURCEFILES
foreach(reverse 0 .. @ARGV-1) {
- unless($ARGV[$_] =~ /\.go$/) {
+ unless($ARGV[$_] =~ /\.(go|s)$/) {
@file = @ARGV[$_+1 .. @ARGV-1];
last;
}
diff --git a/gcc/testsuite/go.test/test/escape.go b/gcc/testsuite/go.test/test/escape.go
index e8ede52760a..252a1e59cc8 100644
--- a/gcc/testsuite/go.test/test/escape.go
+++ b/gcc/testsuite/go.test/test/escape.go
@@ -52,9 +52,11 @@ func chk(p, q *int, v int, s string) {
func chkalias(p, q *int, v int, s string) {
if p != q {
println("want aliased pointers but got different after", s)
+ bad = true
}
if *q != v+1 {
println("wrong value want", v+1, "got", *q, "after", s)
+ bad = true
}
}
diff --git a/gcc/testsuite/go.test/test/escape2.go b/gcc/testsuite/go.test/test/escape2.go
index 8db12d99131..511b74a1cca 100644
--- a/gcc/testsuite/go.test/test/escape2.go
+++ b/gcc/testsuite/go.test/test/escape2.go
@@ -80,7 +80,9 @@ func foo12(yyy **int) { // ERROR "leaking param: yyy"
xxx = yyy
}
-func foo13(yyy **int) { // ERROR "yyy does not escape"
+// Must treat yyy as leaking because *yyy leaks, and the escape analysis
+// summaries in exported metadata do not distinguish these two cases.
+func foo13(yyy **int) { // ERROR "leaking param: yyy"
*xxx = *yyy
}
@@ -142,13 +144,13 @@ func (b Bar) AlsoLeak() *int { // ERROR "leaking param: b"
}
func (b Bar) LeaksToo() *int { // ERROR "leaking param: b"
- v := 0 // ERROR "moved to heap: v"
+ v := 0 // ERROR "moved to heap: v"
b.ii = &v // ERROR "&v escapes"
return b.ii
}
func (b *Bar) LeaksABit() *int { // ERROR "b does not escape"
- v := 0 // ERROR "moved to heap: v"
+ v := 0 // ERROR "moved to heap: v"
b.ii = &v // ERROR "&v escapes"
return b.ii
}
@@ -299,7 +301,8 @@ func (f *Foo) foo45() { // ERROR "f does not escape"
F.x = f.x
}
-func (f *Foo) foo46() { // ERROR "f does not escape"
+// See foo13 above for explanation of why f leaks.
+func (f *Foo) foo46() { // ERROR "leaking param: f"
F.xx = f.xx
}
@@ -561,12 +564,21 @@ func myprint1(y *int, x ...interface{}) *interface{} { // ERROR "y does not esca
return &x[0] // ERROR "&x.0. escapes to heap"
}
-func foo75(z *int) { // ERROR "leaking param: z"
+func foo75(z *int) { // ERROR "z does not escape"
myprint(z, 1, 2, 3) // ERROR "[.][.][.] argument does not escape"
}
func foo75a(z *int) { // ERROR "z does not escape"
- myprint1(z, 1, 2, 3) // ERROR "[.][.][.] argument escapes to heap"
+ myprint1(z, 1, 2, 3) // ERROR "[.][.][.] argument does not escape"
+}
+
+func foo75esc(z *int) { // ERROR "leaking param: z"
+ gxx = myprint(z, 1, 2, 3) // ERROR "[.][.][.] argument does not escape"
+}
+
+func foo75aesc(z *int) { // ERROR "z does not escape"
+ var ppi **interface{} // assignments to pointer dereferences lose track
+ *ppi = myprint1(z, 1, 2, 3) // ERROR "[.][.][.] argument escapes to heap"
}
func foo76(z *int) { // ERROR "leaking param: z"
@@ -574,7 +586,7 @@ func foo76(z *int) { // ERROR "leaking param: z"
}
func foo76a(z *int) { // ERROR "leaking param: z"
- myprint1(nil, z) // ERROR "[.][.][.] argument escapes to heap"
+ myprint1(nil, z) // ERROR "[.][.][.] argument does not escape"
}
func foo76b() {
@@ -582,7 +594,7 @@ func foo76b() {
}
func foo76c() {
- myprint1(nil, 1, 2, 3) // ERROR "[.][.][.] argument escapes to heap"
+ myprint1(nil, 1, 2, 3) // ERROR "[.][.][.] argument does not escape"
}
func foo76d() {
@@ -590,7 +602,7 @@ func foo76d() {
}
func foo76e() {
- defer myprint1(nil, 1, 2, 3) // ERROR "[.][.][.] argument escapes to heap"
+ defer myprint1(nil, 1, 2, 3) // ERROR "[.][.][.] argument does not escape"
}
func foo76f() {
@@ -610,10 +622,15 @@ func foo77(z []interface{}) { // ERROR "z does not escape"
myprint(nil, z...) // z does not escape
}
-func foo77a(z []interface{}) { // ERROR "leaking param: z"
+func foo77a(z []interface{}) { // ERROR "z does not escape"
myprint1(nil, z...)
}
+func foo77b(z []interface{}) { // ERROR "leaking param: z"
+ var ppi **interface{}
+ *ppi = myprint1(nil, z...)
+}
+
func foo78(z int) *int { // ERROR "moved to heap: z"
return &z // ERROR "&z escapes to heap"
}
@@ -646,6 +663,21 @@ func foo81() *int {
return nil
}
+func tee(p *int) (x, y *int) { return p, p } // ERROR "leaking param"
+
+func noop(x, y *int) {} // ERROR "does not escape"
+
+func foo82() {
+ var x, y, z int // ERROR "moved to heap"
+ go noop(tee(&z)) // ERROR "&z escapes to heap"
+ go noop(&x, &y) // ERROR "escapes to heap"
+ for {
+ var u, v, w int // ERROR "moved to heap"
+ defer noop(tee(&u)) // ERROR "&u escapes to heap"
+ defer noop(&v, &w) // ERROR "escapes to heap"
+ }
+}
+
type Fooer interface {
Foo()
}
@@ -1079,29 +1111,29 @@ L1:
_ = i
}
-func foo124(x **int) { // ERROR "x does not escape"
- var i int // ERROR "moved to heap: i"
- p := &i // ERROR "&i escapes"
- func() { // ERROR "func literal does not escape"
- *x = p // ERROR "leaking closure reference p"
+func foo124(x **int) { // ERROR "x does not escape"
+ var i int // ERROR "moved to heap: i"
+ p := &i // ERROR "&i escapes"
+ func() { // ERROR "func literal does not escape"
+ *x = p // ERROR "leaking closure reference p"
}()
}
-func foo125(ch chan *int) { // ERROR "does not escape"
- var i int // ERROR "moved to heap"
- p := &i // ERROR "&i escapes to heap"
- func() { // ERROR "func literal does not escape"
- ch <- p // ERROR "leaking closure reference p"
+func foo125(ch chan *int) { // ERROR "does not escape"
+ var i int // ERROR "moved to heap"
+ p := &i // ERROR "&i escapes to heap"
+ func() { // ERROR "func literal does not escape"
+ ch <- p // ERROR "leaking closure reference p"
}()
}
func foo126() {
- var px *int // loopdepth 0
+ var px *int // loopdepth 0
for {
// loopdepth 1
- var i int // ERROR "moved to heap"
+ var i int // ERROR "moved to heap"
func() { // ERROR "func literal does not escape"
- px = &i // ERROR "&i escapes"
+ px = &i // ERROR "&i escapes"
}()
}
}
@@ -1109,8 +1141,8 @@ func foo126() {
var px *int
func foo127() {
- var i int // ERROR "moved to heap: i"
- p := &i // ERROR "&i escapes to heap"
+ var i int // ERROR "moved to heap: i"
+ p := &i // ERROR "&i escapes to heap"
q := p
px = q
}
@@ -1123,12 +1155,12 @@ func foo128() {
}
func foo129() {
- var i int // ERROR "moved to heap: i"
- p := &i // ERROR "&i escapes to heap"
+ var i int // ERROR "moved to heap: i"
+ p := &i // ERROR "&i escapes to heap"
func() { // ERROR "func literal does not escape"
- q := p // ERROR "leaking closure reference p"
- func() { // ERROR "func literal does not escape"
- r := q // ERROR "leaking closure reference q"
+ q := p // ERROR "leaking closure reference p"
+ func() { // ERROR "func literal does not escape"
+ r := q // ERROR "leaking closure reference q"
px = r
}()
}()
@@ -1136,40 +1168,40 @@ func foo129() {
func foo130() {
for {
- var i int // ERROR "moved to heap"
+ var i int // ERROR "moved to heap"
func() { // ERROR "func literal does not escape"
- px = &i // ERROR "&i escapes" "leaking closure reference i"
+ px = &i // ERROR "&i escapes" "leaking closure reference i"
}()
}
}
func foo131() {
- var i int // ERROR "moved to heap"
+ var i int // ERROR "moved to heap"
func() { // ERROR "func literal does not escape"
- px = &i // ERROR "&i escapes" "leaking closure reference i"
+ px = &i // ERROR "&i escapes" "leaking closure reference i"
}()
}
func foo132() {
- var i int // ERROR "moved to heap"
- go func() { // ERROR "func literal escapes to heap"
- px = &i // ERROR "&i escapes" "leaking closure reference i"
+ var i int // ERROR "moved to heap"
+ go func() { // ERROR "func literal escapes to heap"
+ px = &i // ERROR "&i escapes" "leaking closure reference i"
}()
}
func foo133() {
- var i int // ERROR "moved to heap"
- defer func() { // ERROR "func literal does not escape"
- px = &i // ERROR "&i escapes" "leaking closure reference i"
+ var i int // ERROR "moved to heap"
+ defer func() { // ERROR "func literal does not escape"
+ px = &i // ERROR "&i escapes" "leaking closure reference i"
}()
}
func foo134() {
var i int
p := &i // ERROR "&i does not escape"
- func() { // ERROR "func literal does not escape"
+ func() { // ERROR "func literal does not escape"
q := p
- func() { // ERROR "func literal does not escape"
+ func() { // ERROR "func literal does not escape"
r := q
_ = r
}()
@@ -1177,11 +1209,11 @@ func foo134() {
}
func foo135() {
- var i int // ERROR "moved to heap: i"
- p := &i // ERROR "&i escapes to heap" "moved to heap: p"
- go func() { // ERROR "func literal escapes to heap"
- q := p // ERROR "&p escapes to heap"
- func() { // ERROR "func literal does not escape"
+ var i int // ERROR "moved to heap: i"
+ p := &i // ERROR "&i escapes to heap" "moved to heap: p"
+ go func() { // ERROR "func literal escapes to heap"
+ q := p // ERROR "&p escapes to heap"
+ func() { // ERROR "func literal does not escape"
r := q
_ = r
}()
@@ -1189,11 +1221,11 @@ func foo135() {
}
func foo136() {
- var i int // ERROR "moved to heap: i"
- p := &i // ERROR "&i escapes to heap" "moved to heap: p"
- go func() { // ERROR "func literal escapes to heap"
- q := p // ERROR "&p escapes to heap" "leaking closure reference p"
- func() { // ERROR "func literal does not escape"
+ var i int // ERROR "moved to heap: i"
+ p := &i // ERROR "&i escapes to heap" "moved to heap: p"
+ go func() { // ERROR "func literal escapes to heap"
+ q := p // ERROR "&p escapes to heap" "leaking closure reference p"
+ func() { // ERROR "func literal does not escape"
r := q // ERROR "leaking closure reference q"
px = r
}()
@@ -1201,12 +1233,12 @@ func foo136() {
}
func foo137() {
- var i int // ERROR "moved to heap: i"
- p := &i // ERROR "&i escapes to heap"
+ var i int // ERROR "moved to heap: i"
+ p := &i // ERROR "&i escapes to heap"
func() { // ERROR "func literal does not escape"
- q := p // ERROR "leaking closure reference p" "moved to heap: q"
+ q := p // ERROR "leaking closure reference p" "moved to heap: q"
go func() { // ERROR "func literal escapes to heap"
- r := q // ERROR "&q escapes to heap"
+ r := q // ERROR "&q escapes to heap"
_ = r
}()
}()
@@ -1216,7 +1248,7 @@ func foo138() *byte {
type T struct {
x [1]byte
}
- t := new(T) // ERROR "new.T. escapes to heap"
+ t := new(T) // ERROR "new.T. escapes to heap"
return &t.x[0] // ERROR "&t.x.0. escapes to heap"
}
@@ -1226,6 +1258,70 @@ func foo139() *byte {
y byte
}
}
- t := new(T) // ERROR "new.T. escapes to heap"
+ t := new(T) // ERROR "new.T. escapes to heap"
return &t.x.y // ERROR "&t.x.y escapes to heap"
}
+
+// issue 4751
+func foo140() interface{} {
+ type T struct {
+ X string
+ }
+ type U struct {
+ X string
+ T *T
+ }
+ t := &T{} // ERROR "&T literal escapes to heap"
+ return U{
+ X: t.X,
+ T: t,
+ }
+}
+
+//go:noescape
+
+func F1([]byte)
+
+func F2([]byte)
+
+//go:noescape
+
+func F3(x []byte) // ERROR "F3 x does not escape"
+
+func F4(x []byte)
+
+func G() {
+ var buf1 [10]byte
+ F1(buf1[:]) // ERROR "buf1 does not escape"
+
+ var buf2 [10]byte // ERROR "moved to heap: buf2"
+ F2(buf2[:]) // ERROR "buf2 escapes to heap"
+
+ var buf3 [10]byte
+ F3(buf3[:]) // ERROR "buf3 does not escape"
+
+ var buf4 [10]byte // ERROR "moved to heap: buf4"
+ F4(buf4[:]) // ERROR "buf4 escapes to heap"
+}
+
+type Tm struct {
+ x int
+}
+
+func (t *Tm) M() { // ERROR "t does not escape"
+}
+
+func foo141() {
+ var f func()
+
+ t := new(Tm) // ERROR "escapes to heap"
+ f = t.M // ERROR "t.M does not escape"
+ _ = f
+}
+
+var gf func()
+
+func foo142() {
+ t := new(Tm) // ERROR "escapes to heap"
+ gf = t.M // ERROR "t.M escapes to heap"
+}
diff --git a/gcc/testsuite/go.test/test/escape5.go b/gcc/testsuite/go.test/test/escape5.go
new file mode 100644
index 00000000000..6b327fe9e31
--- /dev/null
+++ b/gcc/testsuite/go.test/test/escape5.go
@@ -0,0 +1,144 @@
+// errorcheck -0 -m -l
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test, using compiler diagnostic flags, that the escape analysis is working.
+// Compiles but does not run. Inlining is disabled.
+
+package foo
+
+func noleak(p *int) int { // ERROR "p does not escape"
+ return *p
+}
+
+func leaktoret(p *int) *int { // ERROR "leaking param: p to result"
+ return p
+}
+
+func leaktoret2(p *int) (*int, *int) { // ERROR "leaking param: p to result .anon1" "leaking param: p to result .anon2"
+ return p, p
+}
+
+func leaktoret22(p, q *int) (*int, *int) { // ERROR "leaking param: p to result .anon2" "leaking param: q to result .anon3"
+ return p, q
+}
+
+func leaktoret22b(p, q *int) (*int, *int) { // ERROR "leaking param: p to result .anon3" "leaking param: q to result .anon2"
+ return leaktoret22(q, p)
+}
+
+func leaktoret22c(p, q *int) (*int, *int) { // ERROR "leaking param: p to result .anon3" "leaking param: q to result .anon2"
+ r, s := leaktoret22(q, p)
+ return r, s
+}
+
+func leaktoret22d(p, q *int) (r, s *int) { // ERROR "leaking param: p to result s" "leaking param: q to result r"
+ r, s = leaktoret22(q, p)
+ return
+}
+
+func leaktoret22e(p, q *int) (r, s *int) { // ERROR "leaking param: p to result s" "leaking param: q to result r"
+ r, s = leaktoret22(q, p)
+ return r, s
+}
+
+func leaktoret22f(p, q *int) (r, s *int) { // ERROR "leaking param: p to result s" "leaking param: q to result r"
+ rr, ss := leaktoret22(q, p)
+ return rr, ss
+}
+
+var gp *int
+
+func leaktosink(p *int) *int { // ERROR "leaking param: p"
+ gp = p
+ return p
+}
+
+func f1() {
+ var x int
+ p := noleak(&x) // ERROR "&x does not escape"
+ _ = p
+}
+
+func f2() {
+ var x int
+ p := leaktoret(&x) // ERROR "&x does not escape"
+ _ = p
+}
+
+func f3() {
+ var x int // ERROR "moved to heap: x"
+ p := leaktoret(&x) // ERROR "&x escapes to heap"
+ gp = p
+}
+
+func f4() {
+ var x int // ERROR "moved to heap: x"
+ p, q := leaktoret2(&x) // ERROR "&x escapes to heap"
+ gp = p
+ gp = q
+}
+
+func f5() {
+ var x int
+ leaktoret22(leaktoret2(&x)) // ERROR "&x does not escape"
+}
+
+func f6() {
+ var x int // ERROR "moved to heap: x"
+ px1, px2 := leaktoret22(leaktoret2(&x)) // ERROR "&x escapes to heap"
+ gp = px1
+ _ = px2
+}
+
+type T struct{ x int }
+
+func (t *T) Foo(u int) (*T, bool) { // ERROR "leaking param: t to result"
+ t.x += u
+ return t, true
+}
+
+func f7() *T {
+ r, _ := new(T).Foo(42) // ERROR "new.T. escapes to heap"
+ return r
+}
+
+func leakrecursive1(p, q *int) (*int, *int) { // ERROR "leaking param: p" "leaking param: q"
+ return leakrecursive2(q, p)
+}
+
+func leakrecursive2(p, q *int) (*int, *int) { // ERROR "leaking param: p" "leaking param: q"
+ if *p > *q {
+ return leakrecursive1(q, p)
+ }
+ // without this, leakrecursive? are safe for p and q, b/c in fact their graph does not have leaking edges.
+ return p, q
+}
+
+
+var global interface{}
+
+type T1 struct {
+ X *int
+}
+
+type T2 struct {
+ Y *T1
+}
+
+func f8(p *T1) (k T2) { // ERROR "leaking param: p to result k" "leaking param: p"
+ if p == nil {
+ k = T2{}
+ return
+ }
+
+ global = p // should make p leak always
+ return T2{p}
+}
+
+func f9() {
+ var j T1 // ERROR "moved to heap: j"
+ f8(&j) // ERROR "&j escapes to heap"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug040.go b/gcc/testsuite/go.test/test/fixedbugs/bug040.go
index 007f47f9f56..d2cf88afcb2 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug040.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug040.go
@@ -7,5 +7,5 @@
package main
func f (x, // GCCGO_ERROR "previous"
- x int) { // ERROR "redeclared|redefinition" "duplicate"
+ x int) { // ERROR "duplicate argument|redefinition"
}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug083.go b/gcc/testsuite/go.test/test/fixedbugs/bug083.go
index 8bdecaadb51..54a17423a08 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug083.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug083.go
@@ -1,10 +1,7 @@
-// $G $D/$F.dir/bug0.go && errchk $G $D/$F.dir/bug1.go
-
-// NOTE: This test is not run by 'run.go' and so not run by all.bash.
-// To run this test you must use the ./run shell script.
+// errorcheckdir
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-ignored
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug085.go b/gcc/testsuite/go.test/test/fixedbugs/bug085.go
index 93ae7e0a496..dae83f8a498 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug085.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug085.go
@@ -20,7 +20,7 @@ Bus error
/* expected scope hierarchy (outermost to innermost)
-universe scope (contains predeclared identifiers int, float, int32, len, etc.)
+universe scope (contains predeclared identifiers int, float32, int32, len, etc.)
"solar" scope (just holds the package name P so it can be found but doesn't conflict)
global scope (the package global scope)
local scopes (function scopes)
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug133.go b/gcc/testsuite/go.test/test/fixedbugs/bug133.go
index a6baac26ca3..54a17423a08 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug133.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug133.go
@@ -1,10 +1,7 @@
-// $G $D/$F.dir/bug0.go && $G $D/$F.dir/bug1.go && errchk $G $D/$F.dir/bug2.go
-
-// NOTE: This test is not run by 'run.go' and so not run by all.bash.
-// To run this test you must use the ./run shell script.
+// errorcheckdir
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-ignored
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug160.go b/gcc/testsuite/go.test/test/fixedbugs/bug160.go
index c5e166a0cf9..fde797bfcd2 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug160.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug160.go
@@ -1,10 +1,7 @@
-// $G $D/bug160.dir/x.go && $G $D/bug160.dir/y.go && $L y.$A && ./$A.out
-
-// NOTE: This test is not run by 'run.go' and so not run by all.bash.
-// To run this test you must use the ./run shell script.
+// rundir
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-nothing to see here
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug191.dir/main.go b/gcc/testsuite/go.test/test/fixedbugs/bug191.dir/main.go
new file mode 100644
index 00000000000..995134ccfcb
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug191.dir/main.go
@@ -0,0 +1,14 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import . "./a"
+import . "./b"
+
+var _ T
+var _ V
+
+func main() {
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug191.go b/gcc/testsuite/go.test/test/fixedbugs/bug191.go
index 11a6e58e516..248e23edfc6 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug191.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug191.go
@@ -1,19 +1,9 @@
-// $G $D/bug191.dir/a.go && $G $D/bug191.dir/b.go && $G $D/$F.go && $L $F.$A
-
-// NOTE: This test is not run by 'run.go' and so not run by all.bash.
-// To run this test you must use the ./run shell script.
+// rundir
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package main
-
-import . "./a"
-import . "./b"
-
-var _ T
-var _ V
+// Tests bug with dot imports.
-func main() {
-}
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug205.go b/gcc/testsuite/go.test/test/fixedbugs/bug205.go
index de17cb69841..1e0d9d1f34d 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug205.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug205.go
@@ -11,8 +11,8 @@ var s string;
var m map[string]int;
func main() {
- println(t["hi"]); // ERROR "integer"
- println(s["hi"]); // ERROR "integer" "to type uint"
- println(m[0]); // ERROR "map index"
+ println(t["hi"]); // ERROR "non-integer slice index|must be integer"
+ println(s["hi"]); // ERROR "non-integer string index|must be integer"
+ println(m[0]); // ERROR "cannot use.*as type string"
}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug228.go b/gcc/testsuite/go.test/test/fixedbugs/bug228.go
index f2dd54556bf..3fccd172888 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug228.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug228.go
@@ -12,7 +12,7 @@ func g(x int, y float32) (...) // ERROR "[.][.][.]" "final argument"
func h(x, y ...int) // ERROR "[.][.][.]"
-func i(x int, y ...int, z float) // ERROR "[.][.][.]"
+func i(x int, y ...int, z float32) // ERROR "[.][.][.]"
var x ...int; // ERROR "[.][.][.]|syntax|type"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug255.go b/gcc/testsuite/go.test/test/fixedbugs/bug255.go
index dbd41cc6ab3..acf4f23910d 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug255.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug255.go
@@ -12,4 +12,4 @@ var c [1.5]int // ERROR "truncated"
var d ["abc"]int // ERROR "invalid array bound|not numeric"
var e [nil]int // ERROR "invalid array bound|not numeric"
var f [e]int // ERROR "invalid array bound|not constant"
-var g [1<<65]int // ERROR "overflows"
+var g [1<<65]int // ERROR "array bound is too large|overflows"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug297.go b/gcc/testsuite/go.test/test/fixedbugs/bug297.go
index b5dfa8d878e..ee2ff92437d 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug297.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug297.go
@@ -11,5 +11,5 @@ package main
type ByteSize float64
const (
_ = iota; // ignore first value by assigning to blank identifier
- KB ByteSize = 1<<(10*X) // ERROR "undefined" "as type ByteSize"
+ KB ByteSize = 1<<(10*X) // ERROR "undefined" "is not a constant|as type ByteSize"
)
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug313.go b/gcc/testsuite/go.test/test/fixedbugs/bug313.go
index 9009c5e8ffc..a7c1d3627bf 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug313.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug313.go
@@ -1,7 +1,4 @@
-// errchk $G -e $D/$F.dir/[ab].go
-
-// NOTE: This test is not run by 'run.go' and so not run by all.bash.
-// To run this test you must use the ./run shell script.
+// errorcheckdir
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug322.go b/gcc/testsuite/go.test/test/fixedbugs/bug322.go
index 401a8600a9e..21efbb55935 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug322.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug322.go
@@ -1,11 +1,8 @@
-// $G $D/$F.dir/lib.go && $G $D/$F.dir/main.go && $L main.$A && ./$A.out || echo BUG: fails incorrectly
-
-// NOTE: This test is not run by 'run.go' and so not run by all.bash.
-// To run this test you must use the ./run shell script.
+// rundir
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Test case for issue 1402.
-ignored
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug324.dir/main.go b/gcc/testsuite/go.test/test/fixedbugs/bug324.dir/prog.go
index 3ab61f3eb5e..3ab61f3eb5e 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug324.dir/main.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug324.dir/prog.go
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug324.go b/gcc/testsuite/go.test/test/fixedbugs/bug324.go
index ee090ae42f4..36b8b56d123 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug324.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug324.go
@@ -1,11 +1,10 @@
-// $G $D/$F.dir/p.go && $G $D/$F.dir/main.go && $L main.$A && ./$A.out
-
-// NOTE: This test is not run by 'run.go' and so not run by all.bash.
-// To run this test you must use the ./run shell script.
+// rundir
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Test case for issue 1550
-ignored
+// Test case for issue 1550: a type cannot implement an interface
+// from another package with a private method, and type assertions
+// should fail.
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug342.go b/gcc/testsuite/go.test/test/fixedbugs/bug342.go
index 5f1efbdfe1e..ffcb6681160 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug342.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug342.go
@@ -9,11 +9,7 @@
package p
type a interface {
- foo(x int) (x int) // ERROR "redeclared|redefinition"
-}
-
-var b interface {
- bar(y int) (y int) // ERROR "redeclared|redefinition"
+ foo(x int) (x int) // ERROR "duplicate argument|redefinition"
}
/*
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug357.go b/gcc/testsuite/go.test/test/fixedbugs/bug357.go
index 2ac64a80b64..ceb2009be51 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug357.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug357.go
@@ -15,7 +15,7 @@ func bla1() bool {
func bla5() bool {
_ = 1
- false // ERROR "false not used|value computed is not used"
+ false // ERROR "false evaluated but not used|value computed is not used"
_ = 2
return false
}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug367.dir/main.go b/gcc/testsuite/go.test/test/fixedbugs/bug367.dir/prog.go
index c278e4dd95f..c278e4dd95f 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug367.dir/main.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug367.dir/prog.go
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug367.go b/gcc/testsuite/go.test/test/fixedbugs/bug367.go
index bf8edcd1b85..05252cd9a6d 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug367.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug367.go
@@ -1,10 +1,10 @@
-// $G $D/$F.dir/p.go && $G $D/$F.dir/main.go && $L main.$A && ./$A.out || echo BUG: should not fail
-
-// NOTE: This test is not run by 'run.go' and so not run by all.bash.
-// To run this test you must use the ./run shell script.
+// rundir
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// Issue 1536: bug when handling imported interfaces with
+// private methods.
+
package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug379.go b/gcc/testsuite/go.test/test/fixedbugs/bug379.go
index 81e9c266ee4..14abe469bec 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug379.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug379.go
@@ -14,5 +14,5 @@
package main
func main() {
- 1 + 2 // ERROR "1 \+ 2 not used|value computed is not used"
+ 1 + 2 // ERROR "1 \+ 2 evaluated but not used|value computed is not used"
}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug382.dir/prog.go b/gcc/testsuite/go.test/test/fixedbugs/bug382.dir/prog.go
new file mode 100644
index 00000000000..b74a82d8241
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug382.dir/prog.go
@@ -0,0 +1,13 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file
+
+// Issue 2529
+
+package main
+
+import "./pkg"
+
+var x = pkg.E
+
+var fo = struct{ F pkg.T }{F: x}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug382.go b/gcc/testsuite/go.test/test/fixedbugs/bug382.go
index 10c71d46624..6039939eeb8 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug382.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug382.go
@@ -1,17 +1,9 @@
-// $G $D/$F.dir/pkg.go && $G $D/$F.go || echo "Bug 382"
-
-// NOTE: This test is not run by 'run.go' and so not run by all.bash.
-// To run this test you must use the ./run shell script.
+// compiledir
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file
-// Issue 2529
-
-package main
-import "./pkg"
-
-var x = pkg.E
+// Issue 2529.
-var fo = struct {F pkg.T}{F: x}
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug385_32.go b/gcc/testsuite/go.test/test/fixedbugs/bug385_32.go
index 5ac4136e7dc..4c3cad7798e 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug385_32.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug385_32.go
@@ -1,7 +1,5 @@
-// [ $A == 6 ] || errchk $G -e $D/$F.go
-
-// NOTE: This test is not run by 'run.go' and so not run by all.bash.
-// To run this test you must use the ./run shell script.
+// +build 386 arm
+// errorcheck
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
@@ -11,7 +9,7 @@
package main
func main() {
- var arr [1000200030]int // ERROR "type .* too large"
+ var arr [1000200030]int // GC_ERROR "type .* too large"
arr_bkup := arr
_ = arr_bkup
-} \ No newline at end of file
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug385_64.go b/gcc/testsuite/go.test/test/fixedbugs/bug385_64.go
index 8c7b9d52081..b593cd53cf1 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug385_64.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug385_64.go
@@ -1,18 +1,22 @@
-// [ $A != 6 ] || errchk $G -e $D/$F.go
-
-// NOTE: This test is not run by 'run.go' and so not run by all.bash.
-// To run this test you must use the ./run shell script.
+// +build amd64
+// errorcheck
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Issue 2444
+// Issue 4666: issue with arrays of exactly 4GB.
package main
-func main() { // ERROR "stack frame too large"
+
+func main() { // GC_ERROR "stack frame too large"
var arr [1000200030]int32
arr_bkup := arr
_ = arr_bkup
}
+func F() { // GC_ERROR "stack frame too large"
+ var arr [1 << 30]int32
+ _ = arr[42]
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug412.go b/gcc/testsuite/go.test/test/fixedbugs/bug412.go
index 8dd0a5fcc15..c7ddc0cac83 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug412.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug412.go
@@ -7,8 +7,8 @@
package p
type t struct {
- x int // ERROR "duplicate field x|duplicate field name .x."
- x int
+ x int // GCCGO_ERROR "duplicate field name .x."
+ x int // GC_ERROR "duplicate field x"
}
func f(t *t) int {
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug414.dir/main.go b/gcc/testsuite/go.test/test/fixedbugs/bug414.dir/main.go
deleted file mode 100644
index 52001233c62..00000000000
--- a/gcc/testsuite/go.test/test/fixedbugs/bug414.dir/main.go
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
- package main
-
- import "./p1"
-
- type MyObject struct {
- p1.Fer
- }
-
- func main() {
- var b p1.Fer = &p1.Object{}
- p1.PrintFer(b)
- var c p1.Fer = &MyObject{b}
- p1.PrintFer(c)
- }
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug414.dir/p1.go b/gcc/testsuite/go.test/test/fixedbugs/bug414.dir/p1.go
index 7768818bf9f..24638348433 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug414.dir/p1.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug414.dir/p1.go
@@ -2,20 +2,20 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
- package p1
-
- import "fmt"
-
- type Fer interface {
- f() string
- }
-
- type Object struct {}
-
- func (this *Object) f() string {
- return "Object.f"
- }
-
- func PrintFer(fer Fer) {
- fmt.Sprintln(fer.f())
- }
+package p1
+
+import "fmt"
+
+type Fer interface {
+ f() string
+}
+
+type Object struct{}
+
+func (this *Object) f() string {
+ return "Object.f"
+}
+
+func PrintFer(fer Fer) {
+ fmt.Sprintln(fer.f())
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug414.dir/prog.go b/gcc/testsuite/go.test/test/fixedbugs/bug414.dir/prog.go
new file mode 100644
index 00000000000..f55d9469689
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug414.dir/prog.go
@@ -0,0 +1,18 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "./p1"
+
+type MyObject struct {
+ p1.Fer
+}
+
+func main() {
+ var b p1.Fer = &p1.Object{}
+ p1.PrintFer(b)
+ var c p1.Fer = &MyObject{b}
+ p1.PrintFer(c)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug414.go b/gcc/testsuite/go.test/test/fixedbugs/bug414.go
index 5612fd5c233..35e19be38e2 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug414.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug414.go
@@ -1,10 +1,9 @@
-// $G $D/$F.dir/p1.go && $G $D/$F.dir/main.go && $L main.$A && ./$A.out
-
-// NOTE: This test is not run by 'run.go' and so not run by all.bash.
-// To run this test you must use the ./run shell script.
+// rundir
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// Issue 1743: test embedding of imported types with private methods.
+
package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug424.dir/main.go b/gcc/testsuite/go.test/test/fixedbugs/bug424.dir/main.go
new file mode 100644
index 00000000000..c2fe1463cd6
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug424.dir/main.go
@@ -0,0 +1,97 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Tests that method calls through an interface always
+// call the locally defined method localT.m independent
+// at which embedding level it is and in which order
+// embedding is done.
+
+package main
+
+import "./lib"
+import "reflect"
+import "fmt"
+
+type localI interface {
+ m() string
+}
+
+type localT struct{}
+
+func (t *localT) m() string {
+ return "main.localT.m"
+}
+
+type myT1 struct {
+ localT
+}
+
+type myT2 struct {
+ localT
+ lib.T
+}
+
+type myT3 struct {
+ lib.T
+ localT
+}
+
+func main() {
+ var i localI
+
+ i = new(localT)
+ if i.m() != "main.localT.m" {
+ println("BUG: localT:", i.m(), "called")
+ }
+
+ i = new(myT1)
+ if i.m() != "main.localT.m" {
+ println("BUG: myT1:", i.m(), "called")
+ }
+
+ i = new(myT2)
+ if i.m() != "main.localT.m" {
+ println("BUG: myT2:", i.m(), "called")
+ }
+
+ t3 := new(myT3)
+ if t3.m() != "main.localT.m" {
+ println("BUG: t3:", t3.m(), "called")
+ }
+
+ i = new(myT3)
+ if i.m() != "main.localT.m" {
+ t := reflect.TypeOf(i)
+ n := t.NumMethod()
+ for j := 0; j < n; j++ {
+ m := t.Method(j)
+ fmt.Printf("#%d: %s.%s %s\n", j, m.PkgPath, m.Name, m.Type)
+ }
+ println("BUG: myT3:", i.m(), "called")
+ }
+
+ var t4 struct {
+ localT
+ lib.T
+ }
+ if t4.m() != "main.localT.m" {
+ println("BUG: t4:", t4.m(), "called")
+ }
+ i = &t4
+ if i.m() != "main.localT.m" {
+ println("BUG: myT4:", i.m(), "called")
+ }
+
+ var t5 struct {
+ lib.T
+ localT
+ }
+ if t5.m() != "main.localT.m" {
+ println("BUG: t5:", t5.m(), "called")
+ }
+ i = &t5
+ if i.m() != "main.localT.m" {
+ println("BUG: myT5:", i.m(), "called")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug424.go b/gcc/testsuite/go.test/test/fixedbugs/bug424.go
index 41524543a84..59c2cd35c4c 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug424.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug424.go
@@ -1,7 +1,4 @@
-// $G $D/$F.dir/lib.go && $G $D/$F.go && $L $F.$A && ./$A.out
-
-// NOTE: This test is not run by 'run.go' and so not run by all.bash.
-// To run this test you must use the ./run shell script.
+// rundir
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
@@ -12,91 +9,5 @@
// at which embedding level it is and in which order
// embedding is done.
-package main
-
-import "./lib"
-import "reflect"
-import "fmt"
-
-type localI interface {
- m() string
-}
-
-type localT struct{}
-
-func (t *localT) m() string {
- return "main.localT.m"
-}
-
-type myT1 struct {
- localT
-}
-
-type myT2 struct {
- localT
- lib.T
-}
-
-type myT3 struct {
- lib.T
- localT
-}
-
-func main() {
- var i localI
-
- i = new(localT)
- if i.m() != "main.localT.m" {
- println("BUG: localT:", i.m(), "called")
- }
-
- i = new(myT1)
- if i.m() != "main.localT.m" {
- println("BUG: myT1:", i.m(), "called")
- }
-
- i = new(myT2)
- if i.m() != "main.localT.m" {
- println("BUG: myT2:", i.m(), "called")
- }
+package ignored
- t3 := new(myT3)
- if t3.m() != "main.localT.m" {
- println("BUG: t3:", t3.m(), "called")
- }
-
- i = new(myT3)
- if i.m() != "main.localT.m" {
- t := reflect.TypeOf(i)
- n := t.NumMethod()
- for j := 0; j < n; j++ {
- m := t.Method(j)
- fmt.Printf("#%d: %s.%s %s\n", j, m.PkgPath, m.Name, m.Type)
- }
- println("BUG: myT3:", i.m(), "called")
- }
-
- var t4 struct {
- localT
- lib.T
- }
- if t4.m() != "main.localT.m" {
- println("BUG: t4:", t4.m(), "called")
- }
- i = &t4
- if i.m() != "main.localT.m" {
- println("BUG: myT4:", i.m(), "called")
- }
-
- var t5 struct {
- lib.T
- localT
- }
- if t5.m() != "main.localT.m" {
- println("BUG: t5:", t5.m(), "called")
- }
- i = &t5
- if i.m() != "main.localT.m" {
- println("BUG: myT5:", i.m(), "called")
- }
-}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug437.dir/x.go b/gcc/testsuite/go.test/test/fixedbugs/bug437.dir/x.go
new file mode 100644
index 00000000000..364d017afa7
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug437.dir/x.go
@@ -0,0 +1,25 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test converting a type defined in a different package to an
+// interface defined in a third package, where the interface has a
+// hidden method. This used to cause a link error with gccgo.
+
+package main
+
+import (
+ "./one"
+ "./two"
+)
+
+func F(i1 one.I1) {
+ switch v := i1.(type) {
+ case two.S2:
+ one.F1(v)
+ }
+}
+
+func main() {
+ F(nil)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug437.go b/gcc/testsuite/go.test/test/fixedbugs/bug437.go
index b1e76a6a744..5c4a2ad0dcf 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug437.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug437.go
@@ -1,7 +1,4 @@
-// $G $D/$F.dir/one.go && $G $D/$F.dir/two.go && $G $D/$F.go && $L $F.$A && ./$A.out
-
-// NOTE: This test is not run by 'run.go' and so not run by all.bash.
-// To run this test you must use the ./run shell script.
+// rundir
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
@@ -11,20 +8,4 @@
// interface defined in a third package, where the interface has a
// hidden method. This used to cause a link error with gccgo.
-package main
-
-import (
- "./one"
- "./two"
-)
-
-func F(i1 one.I1) {
- switch v := i1.(type) {
- case two.S2:
- one.F1(v)
- }
-}
-
-func main() {
- F(nil)
-}
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug453.go b/gcc/testsuite/go.test/test/fixedbugs/bug453.go
new file mode 100644
index 00000000000..136abefb7d2
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug453.go
@@ -0,0 +1,39 @@
+// run
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 4138: bug in floating-point registers numbering.
+// Makes 6g unable to use more than 11 registers.
+
+package main
+
+func formula() float32 {
+ mA := [1]float32{1.0}
+ det1 := mA[0]
+ det2 := mA[0]
+ det3 := mA[0]
+ det4 := mA[0]
+ det5 := mA[0]
+ det6 := mA[0]
+ det7 := mA[0]
+ det8 := mA[0]
+ det9 := mA[0]
+ det10 := mA[0]
+ det11 := mA[0]
+ det12 := mA[0]
+
+ return det1 + det2*det3 +
+ det4*det5 + det6*det7 +
+ det8*det9 + det10*det11 +
+ det12
+}
+
+func main() {
+ x := formula()
+ if x != 7.0 {
+ println(x, 7.0)
+ panic("x != 7.0")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug454.go b/gcc/testsuite/go.test/test/fixedbugs/bug454.go
new file mode 100644
index 00000000000..a10abba8b28
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug454.go
@@ -0,0 +1,21 @@
+// run
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 4173
+
+package main
+
+func main() {
+ var arr *[10]int
+ s := 0
+ for i, _ := range arr {
+ // used to panic trying to access arr[i]
+ s += i
+ }
+ if s != 45 {
+ println("BUG")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug455.go b/gcc/testsuite/go.test/test/fixedbugs/bug455.go
new file mode 100644
index 00000000000..8e3c7701be0
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug455.go
@@ -0,0 +1,54 @@
+// run
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 4156: out of fixed registers when chaining method calls.
+// Used to happen with 6g.
+
+package main
+
+type test_i interface {
+ Test() test_i
+ Result() bool
+}
+
+type test_t struct {
+}
+
+func newTest() *test_t {
+ return &test_t{}
+}
+
+type testFn func(string) testFn
+
+func main() {
+ test := newTest()
+
+ switch {
+ case test.
+ Test().
+ Test().
+ Test().
+ Test().
+ Test().
+ Test().
+ Test().
+ Test().
+ Test().
+ Test().
+ Result():
+ // case worked
+ default:
+ panic("Result returned false unexpectedly")
+ }
+}
+
+func (t *test_t) Test() test_i {
+ return t
+}
+
+func (t *test_t) Result() bool {
+ return true
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug456.go b/gcc/testsuite/go.test/test/fixedbugs/bug456.go
new file mode 100644
index 00000000000..064e1aa0281
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug456.go
@@ -0,0 +1,26 @@
+// run
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 3907: out of fixed registers in nested byte multiply.
+// Used to happen with both 6g and 8g.
+
+package main
+
+func F(a, b, c, d uint8) uint8 {
+ return a * (b * (c * (d *
+ (a * (b * (c * (d *
+ (a * (b * (c * (d *
+ a * (b * (c * d)))))))))))))
+}
+
+func main() {
+ var a, b, c, d uint8 = 1, 1, 1, 1
+ x := F(a, b, c, d)
+ if x != 1 {
+ println(x)
+ panic("x != 1")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug457.go b/gcc/testsuite/go.test/test/fixedbugs/bug457.go
new file mode 100644
index 00000000000..ee7048972af
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug457.go
@@ -0,0 +1,15 @@
+// run
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 4197: growing a slice of zero-width elements
+// panics on a division by zero.
+
+package main
+
+func main() {
+ var x []struct{}
+ x = append(x, struct{}{})
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug458.go b/gcc/testsuite/go.test/test/fixedbugs/bug458.go
new file mode 100644
index 00000000000..ddc97bdb0cc
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug458.go
@@ -0,0 +1,22 @@
+// compile
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 4200: 6g crashes when a type is larger than 4GB.
+
+package main
+
+import "unsafe"
+
+// N=16 on 32-bit arches, 256 on 64-bit arches.
+// On 32-bit arches we don't want to test types
+// that are over 4GB large.
+const N = 1 << unsafe.Sizeof(uintptr(0))
+
+type T [N][10][10][10][10][3]byte
+
+func F(t *T) byte {
+ return t[0][0][0][0][0][0]
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug459.go b/gcc/testsuite/go.test/test/fixedbugs/bug459.go
new file mode 100644
index 00000000000..014f2ef01f7
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug459.go
@@ -0,0 +1,35 @@
+// errorcheck
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 3890: missing detection of init loop involving
+// method calls in function bodies.
+
+package flag
+
+var commandLine = NewFlagSet() // ERROR "loop|depends upon itself"
+
+type FlagSet struct {
+}
+
+func (f *FlagSet) failf(format string, a ...interface{}) {
+ f.usage()
+}
+
+func (f *FlagSet) usage() {
+ if f == commandLine {
+ panic(3)
+ }
+}
+
+func NewFlagSet() *FlagSet {
+ f := &FlagSet{}
+ f.setErrorHandling(true)
+ return f
+}
+
+func (f *FlagSet) setErrorHandling(b bool) {
+ f.failf("DIE")
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug460.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/bug460.dir/a.go
new file mode 100644
index 00000000000..02a287b3177
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug460.dir/a.go
@@ -0,0 +1,9 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+type Foo struct {
+ int
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug460.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/bug460.dir/b.go
new file mode 100644
index 00000000000..1868afe073e
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug460.dir/b.go
@@ -0,0 +1,14 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package b
+
+import "./a"
+
+var x a.Foo
+
+func main() {
+ x.int = 20 // ERROR "unexported field"
+}
+
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug460.go b/gcc/testsuite/go.test/test/fixedbugs/bug460.go
new file mode 100644
index 00000000000..79234a3b963
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug460.go
@@ -0,0 +1,10 @@
+// errorcheckdir
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// part one of issue 4124. Make sure that the compiler rejects access attempts.
+
+package ignored
+
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug461.go b/gcc/testsuite/go.test/test/fixedbugs/bug461.go
new file mode 100644
index 00000000000..f0f7b0e69b6
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug461.go
@@ -0,0 +1,23 @@
+// run
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// part two of issue 4124. Make sure reflect doesn't mark the field as exported.
+
+package main
+
+import "reflect"
+
+var T struct {
+ int
+}
+
+func main() {
+ v := reflect.ValueOf(&T)
+ v = v.Elem().Field(0)
+ if v.CanSet() {
+ panic("int should be unexported")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug462.go b/gcc/testsuite/go.test/test/fixedbugs/bug462.go
new file mode 100644
index 00000000000..1a23ad064dc
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug462.go
@@ -0,0 +1,19 @@
+// errorcheck
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "os"
+
+type T struct {
+ File int
+}
+
+func main() {
+ _ = T {
+ os.File: 1, // ERROR "unknown T? ?field"
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug463.go b/gcc/testsuite/go.test/test/fixedbugs/bug463.go
new file mode 100644
index 00000000000..3e7a1848270
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug463.go
@@ -0,0 +1,22 @@
+// errorcheck
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 3757: unhelpful typechecking loop message
+// for constants that refer to themselves.
+
+package main
+
+const a = a // ERROR "refers to itself|definition loop"
+
+const (
+ X = A
+ A = B // ERROR "refers to itself|definition loop"
+ B = D
+ C, D = 1, A
+)
+
+func main() {
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug464.go b/gcc/testsuite/go.test/test/fixedbugs/bug464.go
new file mode 100644
index 00000000000..582193997a1
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug464.go
@@ -0,0 +1,12 @@
+// errorcheck
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 3937: unhelpful typechecking loop message
+// for identifiers wrongly used as types.
+
+package main
+
+func foo(x foo) {} // ERROR "expected type|not a type"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug465.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/bug465.dir/a.go
new file mode 100644
index 00000000000..a9a8614bb33
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug465.dir/a.go
@@ -0,0 +1,76 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+type T struct{ A, B int }
+
+type A []int
+
+type M map[int]int
+
+func F1() int {
+ if (T{1, 2}) == (T{3, 4}) {
+ return 1
+ }
+ return 0
+}
+
+func F2() int {
+ if (M{1: 2}) == nil {
+ return 1
+ }
+ return 0
+}
+
+func F3() int {
+ if nil == (A{}) {
+ return 1
+ }
+ return 0
+}
+
+func F4() int {
+ if a := (A{}); a == nil {
+ return 1
+ }
+ return 0
+}
+
+func F5() int {
+ for k, v := range (M{1: 2}) {
+ return v - k
+ }
+ return 0
+}
+
+func F6() int {
+ switch a := (T{1, 1}); a == (T{1, 2}) {
+ default:
+ return 1
+ }
+ return 0
+}
+
+func F7() int {
+ for m := (M{}); len(m) < (T{1, 2}).A; m[1] = (A{1})[0] {
+ return 1
+ }
+ return 0
+}
+
+func F8() int {
+ if a := (&T{1, 1}); a != nil {
+ return 1
+ }
+ return 0
+}
+
+func F9() int {
+ var a *T
+ if a = (&T{1, 1}); a != nil {
+ return 1
+ }
+ return 0
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug465.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/bug465.dir/b.go
new file mode 100644
index 00000000000..c84c6836d62
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug465.dir/b.go
@@ -0,0 +1,17 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "./a"
+
+func main() {
+ for _, f := range []func() int{
+ a.F1, a.F2, a.F3, a.F4,
+ a.F5, a.F6, a.F7, a.F8, a.F9} {
+ if f() > 1 {
+ panic("f() > 1")
+ }
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug465.go b/gcc/testsuite/go.test/test/fixedbugs/bug465.go
new file mode 100644
index 00000000000..a6ef5876ab6
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug465.go
@@ -0,0 +1,10 @@
+// rundir
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 4230: inlining bug for composite literal in
+// if, for, switch statements.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug466.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/bug466.dir/a.go
new file mode 100644
index 00000000000..b9de63edabe
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug466.dir/a.go
@@ -0,0 +1,15 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+const N = 2+3i
+
+func Func() []complex128 {
+ return []complex128{1, complex(2, 3), complex(4, 5)}
+}
+
+func Mul(z complex128) complex128 {
+ return z * (3 + 4i)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug466.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/bug466.dir/b.go
new file mode 100644
index 00000000000..82d66eacef9
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug466.dir/b.go
@@ -0,0 +1,30 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "./a"
+
+func main() {
+ s := a.Func()
+ if s[0] != 1 {
+ println(s[0])
+ panic("s[0] != 1")
+ }
+ if s[1] != 2+3i {
+ println(s[1])
+ panic("s[1] != 2+3i")
+ }
+ if s[2] != 4+5i {
+ println(s[2])
+ panic("s[2] != 4+5i")
+ }
+
+ x := 1 + 2i
+ y := a.Mul(x)
+ if y != (1+2i)*(3+4i) {
+ println(y)
+ panic("y != (1+2i)*(3+4i)")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug466.go b/gcc/testsuite/go.test/test/fixedbugs/bug466.go
new file mode 100644
index 00000000000..6b65b33b0a8
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug466.go
@@ -0,0 +1,11 @@
+// rundir
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 4159: exported inlinable functions squash
+// complex literals "a+bi" to "a+b".
+
+package ignored
+
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug467.dir/p1.go b/gcc/testsuite/go.test/test/fixedbugs/bug467.dir/p1.go
new file mode 100644
index 00000000000..538b554f8e3
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug467.dir/p1.go
@@ -0,0 +1,5 @@
+package p1
+
+type SockaddrUnix int
+
+func (s SockaddrUnix) Error() string { return "blah" }
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug467.dir/p2.go b/gcc/testsuite/go.test/test/fixedbugs/bug467.dir/p2.go
new file mode 100644
index 00000000000..d80d3a30b18
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug467.dir/p2.go
@@ -0,0 +1,5 @@
+package p2
+
+import "./p1"
+
+func SockUnix() error { var s *p1.SockaddrUnix; return s }
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug467.dir/p3.go b/gcc/testsuite/go.test/test/fixedbugs/bug467.dir/p3.go
new file mode 100644
index 00000000000..c795646472f
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug467.dir/p3.go
@@ -0,0 +1,7 @@
+package main
+
+import "./p2"
+
+func main() {
+ _ = p2.SockUnix()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug467.go b/gcc/testsuite/go.test/test/fixedbugs/bug467.go
new file mode 100644
index 00000000000..d73adbadffc
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug467.go
@@ -0,0 +1,10 @@
+// compiledir
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Exported data for inlining could forget types of
+// local variables declared in inlinable bodies.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug468.dir/p1.go b/gcc/testsuite/go.test/test/fixedbugs/bug468.dir/p1.go
new file mode 100644
index 00000000000..ca175770fc1
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug468.dir/p1.go
@@ -0,0 +1,7 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p1
+
+type S struct { X, Y int }
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug468.dir/p2.go b/gcc/testsuite/go.test/test/fixedbugs/bug468.dir/p2.go
new file mode 100644
index 00000000000..1793c0e534e
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug468.dir/p2.go
@@ -0,0 +1,25 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "reflect"
+
+ "./p1"
+)
+
+func main() {
+ var v1 = p1.S{1, 2}
+ var v2 = struct { X, Y int }{1, 2}
+ v1 = v2
+ t1 := reflect.TypeOf(v1)
+ t2 := reflect.TypeOf(v2)
+ if !t1.AssignableTo(t2) {
+ panic(0)
+ }
+ if !t2.AssignableTo(t1) {
+ panic(1)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug468.go b/gcc/testsuite/go.test/test/fixedbugs/bug468.go
new file mode 100644
index 00000000000..12e4997d36b
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug468.go
@@ -0,0 +1,10 @@
+// rundir
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// The reflect package was not correctly checking field names
+// when checking for struct assignability.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug470.go b/gcc/testsuite/go.test/test/fixedbugs/bug470.go
new file mode 100644
index 00000000000..0a359184c60
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug470.go
@@ -0,0 +1,26 @@
+// run
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Converting constants between types must introduce rounding.
+
+package main
+
+import "fmt"
+
+const (
+ F32 = 0.00999999977648258209228515625
+ F64 = 0.01000000000000000020816681711721685132943093776702880859375
+)
+
+var F = float64(float32(0.01))
+
+func main() {
+ // 0.01 rounded to float32 then to float64 is F32.
+ // 0.01 represented directly in float64 is F64.
+ if F != F32 {
+ panic(fmt.Sprintf("F=%.1000g, want %.1000g", F, F32))
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug471.go b/gcc/testsuite/go.test/test/fixedbugs/bug471.go
new file mode 100644
index 00000000000..e4542596e9a
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug471.go
@@ -0,0 +1,18 @@
+// compile
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Caused an internal compiler error in gccgo.
+
+package p
+
+type C chan struct{}
+
+func (c C) F() {
+ select {
+ case c <- struct{}{}:
+ default:
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug472.dir/p1.go b/gcc/testsuite/go.test/test/fixedbugs/bug472.dir/p1.go
new file mode 100644
index 00000000000..9d47fd84a72
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug472.dir/p1.go
@@ -0,0 +1,17 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p1
+
+import "runtime"
+
+func E() func() int { return runtime.NumCPU }
+
+func F() func() { return runtime.Gosched }
+
+func G() func() string { return runtime.GOROOT }
+
+func H() func() { return runtime.GC }
+
+func I() func() string { return runtime.Version }
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug472.dir/p2.go b/gcc/testsuite/go.test/test/fixedbugs/bug472.dir/p2.go
new file mode 100644
index 00000000000..34a3f0487a4
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug472.dir/p2.go
@@ -0,0 +1,17 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p2
+
+import "runtime"
+
+func E() func() int { return runtime.NumCPU }
+
+func F() func() { return runtime.GC }
+
+func G() func() string { return runtime.GOROOT }
+
+func H() func() { return runtime.Gosched }
+
+func I() func() string { return runtime.Version }
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug472.dir/z.go b/gcc/testsuite/go.test/test/fixedbugs/bug472.dir/z.go
new file mode 100644
index 00000000000..6c29dd08c61
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug472.dir/z.go
@@ -0,0 +1,13 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ _ "./p1"
+ _ "./p2"
+)
+
+func main() {
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug472.go b/gcc/testsuite/go.test/test/fixedbugs/bug472.go
new file mode 100644
index 00000000000..c79c64ca1ff
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug472.go
@@ -0,0 +1,10 @@
+// rundir
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Linker would incorrectly parse export data and think
+// definitions are inconsistent.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug473.go b/gcc/testsuite/go.test/test/fixedbugs/bug473.go
new file mode 100644
index 00000000000..49ce7d73791
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug473.go
@@ -0,0 +1,69 @@
+// run
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Used to be miscompiled by gccgo, due to a bug in handling
+// initialization ordering.
+
+package main
+
+func F(a ...interface{}) interface{} {
+ s := 0
+ for _, v := range a {
+ s += v.(int)
+ }
+ return s
+}
+
+var V1 = F(V10, V4, V3, V11)
+
+var V2 = F(V1)
+
+var V3 = F(1)
+
+var V4 = F(2)
+
+var V5 = F(3)
+
+var V6 = F(4)
+
+var V7 = F(5)
+
+var V8 = F(V14, V7, V3, V6, V5)
+
+var V9 = F(V4, F(V12))
+
+var V10 = F(V4, V9)
+
+var V11 = F(6)
+
+var V12 = F(V5, V3, V8)
+
+var V13 = F(7)
+
+var V14 = F(8)
+
+func expect(name string, a interface{}, b int) {
+ if a.(int) != b {
+ panic(name)
+ }
+}
+
+func main() {
+ expect("V1", V1, 38)
+ expect("V2", V2, 38)
+ expect("V3", V3, 1)
+ expect("V4", V4, 2)
+ expect("V5", V5, 3)
+ expect("V6", V6, 4)
+ expect("V7", V7, 5)
+ expect("V8", V8, 21)
+ expect("V9", V9, 27)
+ expect("V10", V10, 29)
+ expect("V11", V11, 6)
+ expect("V12", V12, 25)
+ expect("V13", V13, 7)
+ expect("V14", V14, 8)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug474.go b/gcc/testsuite/go.test/test/fixedbugs/bug474.go
new file mode 100644
index 00000000000..b8264872a98
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug474.go
@@ -0,0 +1,29 @@
+// run
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Bug in method values: escape analysis was off.
+
+package main
+
+import "sync"
+
+var called = false
+
+type T struct {
+ once sync.Once
+}
+
+func (t *T) M() {
+ called = true
+}
+
+func main() {
+ var t T
+ t.once.Do(t.M)
+ if !called {
+ panic("not called")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue2615.go b/gcc/testsuite/go.test/test/fixedbugs/issue2615.go
new file mode 100644
index 00000000000..686e1e1ada3
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue2615.go
@@ -0,0 +1,547 @@
+// run
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 2615: a long chain of else if's causes an overflow
+// in the parser stack.
+
+package main
+
+// test returns the index of the lowest set bit in a 256-bit vector.
+func test(x [4]uint64) int {
+ if x[0]&(1<<0) != 0 {
+ return 0
+ } else if x[0]&(1<<1) != 0 {
+ return 1
+ } else if x[0]&(1<<2) != 0 {
+ return 2
+ } else if x[0]&(1<<3) != 0 {
+ return 3
+ } else if x[0]&(1<<4) != 0 {
+ return 4
+ } else if x[0]&(1<<5) != 0 {
+ return 5
+ } else if x[0]&(1<<6) != 0 {
+ return 6
+ } else if x[0]&(1<<7) != 0 {
+ return 7
+ } else if x[0]&(1<<8) != 0 {
+ return 8
+ } else if x[0]&(1<<9) != 0 {
+ return 9
+ } else if x[0]&(1<<10) != 0 {
+ return 10
+ } else if x[0]&(1<<11) != 0 {
+ return 11
+ } else if x[0]&(1<<12) != 0 {
+ return 12
+ } else if x[0]&(1<<13) != 0 {
+ return 13
+ } else if x[0]&(1<<14) != 0 {
+ return 14
+ } else if x[0]&(1<<15) != 0 {
+ return 15
+ } else if x[0]&(1<<16) != 0 {
+ return 16
+ } else if x[0]&(1<<17) != 0 {
+ return 17
+ } else if x[0]&(1<<18) != 0 {
+ return 18
+ } else if x[0]&(1<<19) != 0 {
+ return 19
+ } else if x[0]&(1<<20) != 0 {
+ return 20
+ } else if x[0]&(1<<21) != 0 {
+ return 21
+ } else if x[0]&(1<<22) != 0 {
+ return 22
+ } else if x[0]&(1<<23) != 0 {
+ return 23
+ } else if x[0]&(1<<24) != 0 {
+ return 24
+ } else if x[0]&(1<<25) != 0 {
+ return 25
+ } else if x[0]&(1<<26) != 0 {
+ return 26
+ } else if x[0]&(1<<27) != 0 {
+ return 27
+ } else if x[0]&(1<<28) != 0 {
+ return 28
+ } else if x[0]&(1<<29) != 0 {
+ return 29
+ } else if x[0]&(1<<30) != 0 {
+ return 30
+ } else if x[0]&(1<<31) != 0 {
+ return 31
+ } else if x[0]&(1<<32) != 0 {
+ return 32
+ } else if x[0]&(1<<33) != 0 {
+ return 33
+ } else if x[0]&(1<<34) != 0 {
+ return 34
+ } else if x[0]&(1<<35) != 0 {
+ return 35
+ } else if x[0]&(1<<36) != 0 {
+ return 36
+ } else if x[0]&(1<<37) != 0 {
+ return 37
+ } else if x[0]&(1<<38) != 0 {
+ return 38
+ } else if x[0]&(1<<39) != 0 {
+ return 39
+ } else if x[0]&(1<<40) != 0 {
+ return 40
+ } else if x[0]&(1<<41) != 0 {
+ return 41
+ } else if x[0]&(1<<42) != 0 {
+ return 42
+ } else if x[0]&(1<<43) != 0 {
+ return 43
+ } else if x[0]&(1<<44) != 0 {
+ return 44
+ } else if x[0]&(1<<45) != 0 {
+ return 45
+ } else if x[0]&(1<<46) != 0 {
+ return 46
+ } else if x[0]&(1<<47) != 0 {
+ return 47
+ } else if x[0]&(1<<48) != 0 {
+ return 48
+ } else if x[0]&(1<<49) != 0 {
+ return 49
+ } else if x[0]&(1<<50) != 0 {
+ return 50
+ } else if x[0]&(1<<51) != 0 {
+ return 51
+ } else if x[0]&(1<<52) != 0 {
+ return 52
+ } else if x[0]&(1<<53) != 0 {
+ return 53
+ } else if x[0]&(1<<54) != 0 {
+ return 54
+ } else if x[0]&(1<<55) != 0 {
+ return 55
+ } else if x[0]&(1<<56) != 0 {
+ return 56
+ } else if x[0]&(1<<57) != 0 {
+ return 57
+ } else if x[0]&(1<<58) != 0 {
+ return 58
+ } else if x[0]&(1<<59) != 0 {
+ return 59
+ } else if x[0]&(1<<60) != 0 {
+ return 60
+ } else if x[0]&(1<<61) != 0 {
+ return 61
+ } else if x[0]&(1<<62) != 0 {
+ return 62
+ } else if x[0]&(1<<63) != 0 {
+ return 63
+ } else if x[1]&(1<<0) != 0 {
+ return 64
+ } else if x[1]&(1<<1) != 0 {
+ return 65
+ } else if x[1]&(1<<2) != 0 {
+ return 66
+ } else if x[1]&(1<<3) != 0 {
+ return 67
+ } else if x[1]&(1<<4) != 0 {
+ return 68
+ } else if x[1]&(1<<5) != 0 {
+ return 69
+ } else if x[1]&(1<<6) != 0 {
+ return 70
+ } else if x[1]&(1<<7) != 0 {
+ return 71
+ } else if x[1]&(1<<8) != 0 {
+ return 72
+ } else if x[1]&(1<<9) != 0 {
+ return 73
+ } else if x[1]&(1<<10) != 0 {
+ return 74
+ } else if x[1]&(1<<11) != 0 {
+ return 75
+ } else if x[1]&(1<<12) != 0 {
+ return 76
+ } else if x[1]&(1<<13) != 0 {
+ return 77
+ } else if x[1]&(1<<14) != 0 {
+ return 78
+ } else if x[1]&(1<<15) != 0 {
+ return 79
+ } else if x[1]&(1<<16) != 0 {
+ return 80
+ } else if x[1]&(1<<17) != 0 {
+ return 81
+ } else if x[1]&(1<<18) != 0 {
+ return 82
+ } else if x[1]&(1<<19) != 0 {
+ return 83
+ } else if x[1]&(1<<20) != 0 {
+ return 84
+ } else if x[1]&(1<<21) != 0 {
+ return 85
+ } else if x[1]&(1<<22) != 0 {
+ return 86
+ } else if x[1]&(1<<23) != 0 {
+ return 87
+ } else if x[1]&(1<<24) != 0 {
+ return 88
+ } else if x[1]&(1<<25) != 0 {
+ return 89
+ } else if x[1]&(1<<26) != 0 {
+ return 90
+ } else if x[1]&(1<<27) != 0 {
+ return 91
+ } else if x[1]&(1<<28) != 0 {
+ return 92
+ } else if x[1]&(1<<29) != 0 {
+ return 93
+ } else if x[1]&(1<<30) != 0 {
+ return 94
+ } else if x[1]&(1<<31) != 0 {
+ return 95
+ } else if x[1]&(1<<32) != 0 {
+ return 96
+ } else if x[1]&(1<<33) != 0 {
+ return 97
+ } else if x[1]&(1<<34) != 0 {
+ return 98
+ } else if x[1]&(1<<35) != 0 {
+ return 99
+ } else if x[1]&(1<<36) != 0 {
+ return 100
+ } else if x[1]&(1<<37) != 0 {
+ return 101
+ } else if x[1]&(1<<38) != 0 {
+ return 102
+ } else if x[1]&(1<<39) != 0 {
+ return 103
+ } else if x[1]&(1<<40) != 0 {
+ return 104
+ } else if x[1]&(1<<41) != 0 {
+ return 105
+ } else if x[1]&(1<<42) != 0 {
+ return 106
+ } else if x[1]&(1<<43) != 0 {
+ return 107
+ } else if x[1]&(1<<44) != 0 {
+ return 108
+ } else if x[1]&(1<<45) != 0 {
+ return 109
+ } else if x[1]&(1<<46) != 0 {
+ return 110
+ } else if x[1]&(1<<47) != 0 {
+ return 111
+ } else if x[1]&(1<<48) != 0 {
+ return 112
+ } else if x[1]&(1<<49) != 0 {
+ return 113
+ } else if x[1]&(1<<50) != 0 {
+ return 114
+ } else if x[1]&(1<<51) != 0 {
+ return 115
+ } else if x[1]&(1<<52) != 0 {
+ return 116
+ } else if x[1]&(1<<53) != 0 {
+ return 117
+ } else if x[1]&(1<<54) != 0 {
+ return 118
+ } else if x[1]&(1<<55) != 0 {
+ return 119
+ } else if x[1]&(1<<56) != 0 {
+ return 120
+ } else if x[1]&(1<<57) != 0 {
+ return 121
+ } else if x[1]&(1<<58) != 0 {
+ return 122
+ } else if x[1]&(1<<59) != 0 {
+ return 123
+ } else if x[1]&(1<<60) != 0 {
+ return 124
+ } else if x[1]&(1<<61) != 0 {
+ return 125
+ } else if x[1]&(1<<62) != 0 {
+ return 126
+ } else if x[1]&(1<<63) != 0 {
+ return 127
+ } else if x[2]&(1<<0) != 0 {
+ return 128
+ } else if x[2]&(1<<1) != 0 {
+ return 129
+ } else if x[2]&(1<<2) != 0 {
+ return 130
+ } else if x[2]&(1<<3) != 0 {
+ return 131
+ } else if x[2]&(1<<4) != 0 {
+ return 132
+ } else if x[2]&(1<<5) != 0 {
+ return 133
+ } else if x[2]&(1<<6) != 0 {
+ return 134
+ } else if x[2]&(1<<7) != 0 {
+ return 135
+ } else if x[2]&(1<<8) != 0 {
+ return 136
+ } else if x[2]&(1<<9) != 0 {
+ return 137
+ } else if x[2]&(1<<10) != 0 {
+ return 138
+ } else if x[2]&(1<<11) != 0 {
+ return 139
+ } else if x[2]&(1<<12) != 0 {
+ return 140
+ } else if x[2]&(1<<13) != 0 {
+ return 141
+ } else if x[2]&(1<<14) != 0 {
+ return 142
+ } else if x[2]&(1<<15) != 0 {
+ return 143
+ } else if x[2]&(1<<16) != 0 {
+ return 144
+ } else if x[2]&(1<<17) != 0 {
+ return 145
+ } else if x[2]&(1<<18) != 0 {
+ return 146
+ } else if x[2]&(1<<19) != 0 {
+ return 147
+ } else if x[2]&(1<<20) != 0 {
+ return 148
+ } else if x[2]&(1<<21) != 0 {
+ return 149
+ } else if x[2]&(1<<22) != 0 {
+ return 150
+ } else if x[2]&(1<<23) != 0 {
+ return 151
+ } else if x[2]&(1<<24) != 0 {
+ return 152
+ } else if x[2]&(1<<25) != 0 {
+ return 153
+ } else if x[2]&(1<<26) != 0 {
+ return 154
+ } else if x[2]&(1<<27) != 0 {
+ return 155
+ } else if x[2]&(1<<28) != 0 {
+ return 156
+ } else if x[2]&(1<<29) != 0 {
+ return 157
+ } else if x[2]&(1<<30) != 0 {
+ return 158
+ } else if x[2]&(1<<31) != 0 {
+ return 159
+ } else if x[2]&(1<<32) != 0 {
+ return 160
+ } else if x[2]&(1<<33) != 0 {
+ return 161
+ } else if x[2]&(1<<34) != 0 {
+ return 162
+ } else if x[2]&(1<<35) != 0 {
+ return 163
+ } else if x[2]&(1<<36) != 0 {
+ return 164
+ } else if x[2]&(1<<37) != 0 {
+ return 165
+ } else if x[2]&(1<<38) != 0 {
+ return 166
+ } else if x[2]&(1<<39) != 0 {
+ return 167
+ } else if x[2]&(1<<40) != 0 {
+ return 168
+ } else if x[2]&(1<<41) != 0 {
+ return 169
+ } else if x[2]&(1<<42) != 0 {
+ return 170
+ } else if x[2]&(1<<43) != 0 {
+ return 171
+ } else if x[2]&(1<<44) != 0 {
+ return 172
+ } else if x[2]&(1<<45) != 0 {
+ return 173
+ } else if x[2]&(1<<46) != 0 {
+ return 174
+ } else if x[2]&(1<<47) != 0 {
+ return 175
+ } else if x[2]&(1<<48) != 0 {
+ return 176
+ } else if x[2]&(1<<49) != 0 {
+ return 177
+ } else if x[2]&(1<<50) != 0 {
+ return 178
+ } else if x[2]&(1<<51) != 0 {
+ return 179
+ } else if x[2]&(1<<52) != 0 {
+ return 180
+ } else if x[2]&(1<<53) != 0 {
+ return 181
+ } else if x[2]&(1<<54) != 0 {
+ return 182
+ } else if x[2]&(1<<55) != 0 {
+ return 183
+ } else if x[2]&(1<<56) != 0 {
+ return 184
+ } else if x[2]&(1<<57) != 0 {
+ return 185
+ } else if x[2]&(1<<58) != 0 {
+ return 186
+ } else if x[2]&(1<<59) != 0 {
+ return 187
+ } else if x[2]&(1<<60) != 0 {
+ return 188
+ } else if x[2]&(1<<61) != 0 {
+ return 189
+ } else if x[2]&(1<<62) != 0 {
+ return 190
+ } else if x[2]&(1<<63) != 0 {
+ return 191
+ } else if x[3]&(1<<0) != 0 {
+ return 192
+ } else if x[3]&(1<<1) != 0 {
+ return 193
+ } else if x[3]&(1<<2) != 0 {
+ return 194
+ } else if x[3]&(1<<3) != 0 {
+ return 195
+ } else if x[3]&(1<<4) != 0 {
+ return 196
+ } else if x[3]&(1<<5) != 0 {
+ return 197
+ } else if x[3]&(1<<6) != 0 {
+ return 198
+ } else if x[3]&(1<<7) != 0 {
+ return 199
+ } else if x[3]&(1<<8) != 0 {
+ return 200
+ } else if x[3]&(1<<9) != 0 {
+ return 201
+ } else if x[3]&(1<<10) != 0 {
+ return 202
+ } else if x[3]&(1<<11) != 0 {
+ return 203
+ } else if x[3]&(1<<12) != 0 {
+ return 204
+ } else if x[3]&(1<<13) != 0 {
+ return 205
+ } else if x[3]&(1<<14) != 0 {
+ return 206
+ } else if x[3]&(1<<15) != 0 {
+ return 207
+ } else if x[3]&(1<<16) != 0 {
+ return 208
+ } else if x[3]&(1<<17) != 0 {
+ return 209
+ } else if x[3]&(1<<18) != 0 {
+ return 210
+ } else if x[3]&(1<<19) != 0 {
+ return 211
+ } else if x[3]&(1<<20) != 0 {
+ return 212
+ } else if x[3]&(1<<21) != 0 {
+ return 213
+ } else if x[3]&(1<<22) != 0 {
+ return 214
+ } else if x[3]&(1<<23) != 0 {
+ return 215
+ } else if x[3]&(1<<24) != 0 {
+ return 216
+ } else if x[3]&(1<<25) != 0 {
+ return 217
+ } else if x[3]&(1<<26) != 0 {
+ return 218
+ } else if x[3]&(1<<27) != 0 {
+ return 219
+ } else if x[3]&(1<<28) != 0 {
+ return 220
+ } else if x[3]&(1<<29) != 0 {
+ return 221
+ } else if x[3]&(1<<30) != 0 {
+ return 222
+ } else if x[3]&(1<<31) != 0 {
+ return 223
+ } else if x[3]&(1<<32) != 0 {
+ return 224
+ } else if x[3]&(1<<33) != 0 {
+ return 225
+ } else if x[3]&(1<<34) != 0 {
+ return 226
+ } else if x[3]&(1<<35) != 0 {
+ return 227
+ } else if x[3]&(1<<36) != 0 {
+ return 228
+ } else if x[3]&(1<<37) != 0 {
+ return 229
+ } else if x[3]&(1<<38) != 0 {
+ return 230
+ } else if x[3]&(1<<39) != 0 {
+ return 231
+ } else if x[3]&(1<<40) != 0 {
+ return 232
+ } else if x[3]&(1<<41) != 0 {
+ return 233
+ } else if x[3]&(1<<42) != 0 {
+ return 234
+ } else if x[3]&(1<<43) != 0 {
+ return 235
+ } else if x[3]&(1<<44) != 0 {
+ return 236
+ } else if x[3]&(1<<45) != 0 {
+ return 237
+ } else if x[3]&(1<<46) != 0 {
+ return 238
+ } else if x[3]&(1<<47) != 0 {
+ return 239
+ } else if x[3]&(1<<48) != 0 {
+ return 240
+ } else if x[3]&(1<<49) != 0 {
+ return 241
+ } else if x[3]&(1<<50) != 0 {
+ return 242
+ } else if x[3]&(1<<51) != 0 {
+ return 243
+ } else if x[3]&(1<<52) != 0 {
+ return 244
+ } else if x[3]&(1<<53) != 0 {
+ return 245
+ } else if x[3]&(1<<54) != 0 {
+ return 246
+ } else if x[3]&(1<<55) != 0 {
+ return 247
+ } else if x[3]&(1<<56) != 0 {
+ return 248
+ } else if x[3]&(1<<57) != 0 {
+ return 249
+ } else if x[3]&(1<<58) != 0 {
+ return 250
+ } else if x[3]&(1<<59) != 0 {
+ return 251
+ } else if x[3]&(1<<60) != 0 {
+ return 252
+ } else if x[3]&(1<<61) != 0 {
+ return 253
+ } else if x[3]&(1<<62) != 0 {
+ return 254
+ } else if x[3]&(1<<63) != 0 {
+ return 255
+ }
+ return -1
+}
+
+func main() {
+ const ones = ^uint64(0)
+ for i := 0; i < 256; i++ {
+ bits := [4]uint64{ones, ones, ones, ones}
+
+ // clear bottom i bits
+ bits[i/64] ^= 1<<(uint(i)&63) - 1
+ for j := i/64 - 1; j >= 0; j-- {
+ bits[j] = 0
+ }
+
+ k := test(bits)
+ if k != i {
+ print("test(bits)=", k, " want ", i, "\n")
+ panic("failed")
+ }
+ }
+}
diff --git a/gcc/testsuite/go.test/test/bugs/bug434.dir/one.go b/gcc/testsuite/go.test/test/fixedbugs/issue3552.dir/one.go
index 491ada1d9c4..491ada1d9c4 100644
--- a/gcc/testsuite/go.test/test/bugs/bug434.dir/one.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue3552.dir/one.go
diff --git a/gcc/testsuite/go.test/test/bugs/bug434.dir/two.go b/gcc/testsuite/go.test/test/fixedbugs/issue3552.dir/two.go
index 1366d244d3e..1366d244d3e 100644
--- a/gcc/testsuite/go.test/test/bugs/bug434.dir/two.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue3552.dir/two.go
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue3552.go b/gcc/testsuite/go.test/test/fixedbugs/issue3552.go
new file mode 100644
index 00000000000..a198dbe971f
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue3552.go
@@ -0,0 +1,10 @@
+// compiledir
+
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 3552: cross-package inlining misbehaves when
+// referencing embedded builtins.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue3705.go b/gcc/testsuite/go.test/test/fixedbugs/issue3705.go
new file mode 100644
index 00000000000..64ef38b10d5
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue3705.go
@@ -0,0 +1,9 @@
+// errorcheck
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func init() // ERROR "missing function body|cannot declare init"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue3783.go b/gcc/testsuite/go.test/test/fixedbugs/issue3783.go
new file mode 100644
index 00000000000..d7a4a2e8f3c
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue3783.go
@@ -0,0 +1,12 @@
+// errorcheck
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package foo
+
+var i int
+
+func (*i) bar() // ERROR "not a type|expected type"
+
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue3924.go b/gcc/testsuite/go.test/test/fixedbugs/issue3924.go
new file mode 100644
index 00000000000..d4739b21c90
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue3924.go
@@ -0,0 +1,13 @@
+// errorcheck
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package foo
+
+type mybool bool
+
+var x, y = 1, 2
+var _ mybool = x < y && x < y // ERROR "cannot use"
+var _ mybool = x < y || x < y // ERROR "cannot use"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue3925.go b/gcc/testsuite/go.test/test/fixedbugs/issue3925.go
new file mode 100644
index 00000000000..a62d4392e6f
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue3925.go
@@ -0,0 +1,23 @@
+// errorcheck
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 3925: wrong line number for error message "missing key in map literal"
+
+// also a test for correct line number in other malformed composite literals.
+
+package foo
+
+var _ = map[string]string{
+ "1": "2",
+ "3", "4", // ERROR "missing key|must have keys"
+}
+
+var _ = []string{
+ "foo",
+ "bar",
+ 20, // ERROR "cannot use|incompatible type"
+}
+
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4066.go b/gcc/testsuite/go.test/test/fixedbugs/issue4066.go
new file mode 100644
index 00000000000..19cfe6651a7
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4066.go
@@ -0,0 +1,37 @@
+// run
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// issue 4066: return values not being spilled eagerly enough
+
+package main
+
+func main() {
+ n := foo()
+ if n != 2 {
+ println(n)
+ panic("wrong return value")
+ }
+}
+
+type terr struct{}
+
+func foo() (val int) {
+ val = 0
+ defer func() {
+ if x := recover(); x != nil {
+ _ = x.(terr)
+ }
+ }()
+ for {
+ val = 2
+ foo1()
+ }
+ panic("unreachable")
+}
+
+func foo1() {
+ panic(terr{})
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4085a.go b/gcc/testsuite/go.test/test/fixedbugs/issue4085a.go
new file mode 100644
index 00000000000..1d8e57cb7c7
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4085a.go
@@ -0,0 +1,18 @@
+// errorcheck
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+type T []int
+
+func main() {
+ _ = make(T, -1) // ERROR "negative"
+ _ = make(T, 0.5) // ERROR "constant 0.5 truncated to integer|non-integer"
+ _ = make(T, 1.0) // ok
+ _ = make(T, 1<<63) // ERROR "len argument too large"
+ _ = make(T, 0, -1) // ERROR "negative cap"
+ _ = make(T, 10, 0) // ERROR "len larger than cap"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4085b.go b/gcc/testsuite/go.test/test/fixedbugs/issue4085b.go
new file mode 100644
index 00000000000..63aca2378ee
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4085b.go
@@ -0,0 +1,49 @@
+// run
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "strings"
+ "unsafe"
+)
+
+type T []int
+
+func main() {
+ n := -1
+ shouldPanic("len out of range", func() {_ = make(T, n)})
+ shouldPanic("cap out of range", func() {_ = make(T, 0, n)})
+ var t *byte
+ if unsafe.Sizeof(t) == 8 {
+ n = 1<<20
+ n <<= 20
+ shouldPanic("len out of range", func() {_ = make(T, n)})
+ shouldPanic("cap out of range", func() {_ = make(T, 0, n)})
+ n <<= 20
+ shouldPanic("len out of range", func() {_ = make(T, n)})
+ shouldPanic("cap out of range", func() {_ = make(T, 0, n)})
+ } else {
+ n = 1<<31 - 1
+ shouldPanic("len out of range", func() {_ = make(T, n)})
+ shouldPanic("cap out of range", func() {_ = make(T, 0, n)})
+ }
+}
+
+func shouldPanic(str string, f func()) {
+ defer func() {
+ err := recover()
+ if err == nil {
+ panic("did not panic")
+ }
+ s := err.(error).Error()
+ if !strings.Contains(s, str) {
+ panic("got panic " + s + ", want " + str)
+ }
+ }()
+
+ f()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4097.go b/gcc/testsuite/go.test/test/fixedbugs/issue4097.go
new file mode 100644
index 00000000000..c2b7d9b4fbf
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4097.go
@@ -0,0 +1,11 @@
+// errorcheck
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package foo
+
+var s [][10]int
+const m = len(s[len(s)-1]) // ERROR "is not a constant|is not constant"
+
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4099.go b/gcc/testsuite/go.test/test/fixedbugs/issue4099.go
new file mode 100644
index 00000000000..89392bfff1d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4099.go
@@ -0,0 +1,26 @@
+// errorcheck -0 -m
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check go:noescape annotations.
+
+package p
+
+// The noescape comment only applies to the next func,
+// which must not have a body.
+
+//go:noescape
+
+func F1([]byte)
+
+func F2([]byte)
+
+func G() {
+ var buf1 [10]byte
+ F1(buf1[:]) // ERROR "buf1 does not escape"
+
+ var buf2 [10]byte // ERROR "moved to heap: buf2"
+ F2(buf2[:]) // ERROR "buf2 escapes to heap"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4162.go b/gcc/testsuite/go.test/test/fixedbugs/issue4162.go
new file mode 100644
index 00000000000..c2a8338c705
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4162.go
@@ -0,0 +1,17 @@
+// compile
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 4162. Trailing commas now allowed in conversions.
+
+package p
+
+// All these are valid now.
+var (
+ _ = int(1.0,) // comma was always permitted (like function call)
+ _ = []byte("foo",) // was syntax error: unexpected comma
+ _ = chan int(nil,) // was syntax error: unexpected comma
+ _ = (func())(nil,) // was syntax error: unexpected comma
+)
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4167.go b/gcc/testsuite/go.test/test/fixedbugs/issue4167.go
new file mode 100644
index 00000000000..4e353312b87
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4167.go
@@ -0,0 +1,50 @@
+// run
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 4167: inlining of a (*T).Method expression taking
+// its arguments from a multiple return breaks the compiler.
+
+package main
+
+type pa []int
+
+type p int
+
+func (this *pa) func1() (v *p, c int) {
+ for _ = range *this {
+ c++
+ }
+ v = (*p)(&c)
+ return
+}
+
+func (this *pa) func2() p {
+ return (*p).func3(this.func1())
+}
+
+func (this *p) func3(f int) p {
+ return *this
+}
+
+func (this *pa) func2dots() p {
+ return (*p).func3(this.func1())
+}
+
+func (this *p) func3dots(f ...int) p {
+ return *this
+}
+
+func main() {
+ arr := make(pa, 13)
+ length := arr.func2()
+ if int(length) != len(arr) {
+ panic("length != len(arr)")
+ }
+ length = arr.func2dots()
+ if int(length) != len(arr) {
+ panic("length != len(arr)")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4232.go b/gcc/testsuite/go.test/test/fixedbugs/issue4232.go
new file mode 100644
index 00000000000..e5daa656235
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4232.go
@@ -0,0 +1,33 @@
+// errorcheck
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func f() {
+ var a [10]int
+ _ = a[-1] // ERROR "invalid array index -1|index out of bounds"
+ _ = a[-1:] // ERROR "invalid slice index -1|index out of bounds"
+ _ = a[:-1] // ERROR "invalid slice index -1|index out of bounds"
+ _ = a[10] // ERROR "invalid array index 10|index out of bounds"
+
+ var s []int
+ _ = s[-1] // ERROR "invalid slice index -1|index out of bounds"
+ _ = s[-1:] // ERROR "invalid slice index -1|index out of bounds"
+ _ = s[:-1] // ERROR "invalid slice index -1|index out of bounds"
+ _ = s[10]
+
+ const c = "foo"
+ _ = c[-1] // ERROR "invalid string index -1|index out of bounds"
+ _ = c[-1:] // ERROR "invalid slice index -1|index out of bounds"
+ _ = c[:-1] // ERROR "invalid slice index -1|index out of bounds"
+ _ = c[3] // ERROR "invalid string index 3|index out of bounds"
+
+ var t string
+ _ = t[-1] // ERROR "invalid string index -1|index out of bounds"
+ _ = t[-1:] // ERROR "invalid slice index -1|index out of bounds"
+ _ = t[:-1] // ERROR "invalid slice index -1|index out of bounds"
+ _ = t[3]
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4251.go b/gcc/testsuite/go.test/test/fixedbugs/issue4251.go
new file mode 100644
index 00000000000..a14e0896a47
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4251.go
@@ -0,0 +1,21 @@
+// errorcheck
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 4251: slice with inverted range is an error.
+
+package p
+
+func F1(s []byte) []byte {
+ return s[2:1] // ERROR "inverted"
+}
+
+func F2(a [10]byte) []byte {
+ return a[2:1] // ERROR "inverted"
+}
+
+func F3(s string) string {
+ return s[2:1] // ERROR "inverted"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4252.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue4252.dir/a.go
new file mode 100644
index 00000000000..089b6f20f42
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4252.dir/a.go
@@ -0,0 +1,35 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// A package that redeclares common builtin names.
+package a
+
+var true = 0 == 1
+var false = 0 == 0
+var nil = 1
+
+const append = 42
+
+type error bool
+type int interface{}
+
+func len(interface{}) int32 { return 42 }
+
+func Test() {
+ var array [append]int
+ if true {
+ panic("unexpected builtin true instead of redeclared one")
+ }
+ if !false {
+ panic("unexpected builtin false instead of redeclared one")
+ }
+ if len(array) != 42 {
+ println(len(array))
+ panic("unexpected call of builtin len")
+ }
+}
+
+func InlinedFakeTrue() error { return error(true) }
+func InlinedFakeFalse() error { return error(false) }
+func InlinedFakeNil() int { return nil }
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4252.dir/main.go b/gcc/testsuite/go.test/test/fixedbugs/issue4252.dir/main.go
new file mode 100644
index 00000000000..28e43422478
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4252.dir/main.go
@@ -0,0 +1,20 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "./a"
+
+func main() {
+ if a.InlinedFakeTrue() {
+ panic("returned true was the real one")
+ }
+ if !a.InlinedFakeFalse() {
+ panic("returned false was the real one")
+ }
+ if a.InlinedFakeNil() == nil {
+ panic("returned nil was the real one")
+ }
+ a.Test()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4252.go b/gcc/testsuite/go.test/test/fixedbugs/issue4252.go
new file mode 100644
index 00000000000..1b0e5b20289
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4252.go
@@ -0,0 +1,11 @@
+// rundir
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 4252: tests that fixing the issue still allow
+// builtins to be redeclared and are not corrupted
+// in export data.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4264.go b/gcc/testsuite/go.test/test/fixedbugs/issue4264.go
new file mode 100644
index 00000000000..627393211ee
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4264.go
@@ -0,0 +1,19 @@
+// errorcheck
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// issue 4264: reject int division by const 0
+
+package main
+
+func main() {
+ var x int
+ var y float64
+ var z complex128
+
+ println(x/0) // ERROR "division by zero"
+ println(y/0)
+ println(z/0)
+} \ No newline at end of file
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4283.go b/gcc/testsuite/go.test/test/fixedbugs/issue4283.go
new file mode 100644
index 00000000000..128c87231ab
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4283.go
@@ -0,0 +1,17 @@
+// errorcheck
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 4283: nil == nil can't be done as the type is unknown.
+
+package p
+
+func F1() bool {
+ return nil == nil // ERROR "invalid"
+}
+
+func F2() bool {
+ return nil != nil // ERROR "invalid"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4313.go b/gcc/testsuite/go.test/test/fixedbugs/issue4313.go
new file mode 100644
index 00000000000..b2f69dbfa41
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4313.go
@@ -0,0 +1,28 @@
+// run
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Order of operations in select.
+
+package main
+
+func main() {
+ c := make(chan int, 1)
+ x := 0
+ select {
+ case c <- x: // should see x = 0, not x = 42 (after makec)
+ case <-makec(&x): // should be evaluated only after c and x on previous line
+ }
+ y := <-c
+ if y != 0 {
+ panic(y)
+ }
+}
+
+func makec(px *int) chan bool {
+ if false { for {} }
+ *px = 42
+ return make(chan bool, 0)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4316.go b/gcc/testsuite/go.test/test/fixedbugs/issue4316.go
new file mode 100644
index 00000000000..bb18a089624
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4316.go
@@ -0,0 +1,64 @@
+// run
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 4316: the stack overflow check in the linker
+// is confused when it encounters a split-stack function
+// that needs 0 bytes of stack space.
+
+package main
+
+type Peano *Peano
+
+func makePeano(n int) *Peano {
+ if n == 0 {
+ return nil
+ }
+ p := Peano(makePeano(n - 1))
+ return &p
+}
+
+var countArg Peano
+var countResult int
+
+func countPeano() {
+ if countArg == nil {
+ countResult = 0
+ return
+ }
+ countArg = *countArg
+ countPeano()
+ countResult++
+}
+
+var s = "(())"
+var pT = 0
+
+func p() {
+ if pT >= len(s) {
+ return
+ }
+ if s[pT] == '(' {
+ pT += 1
+ p()
+ if pT < len(s) && s[pT] == ')' {
+ pT += 1
+ } else {
+ return
+ }
+ p()
+ }
+}
+
+func main() {
+ countArg = makePeano(4096)
+ countPeano()
+ if countResult != 4096 {
+ println("countResult =", countResult)
+ panic("countResult != 4096")
+ }
+
+ p()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4323.go b/gcc/testsuite/go.test/test/fixedbugs/issue4323.go
new file mode 100644
index 00000000000..6bb78f43cf8
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4323.go
@@ -0,0 +1,31 @@
+// compile
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 4323: inlining of functions with local variables
+// forgets to typecheck the declarations in the inlined copy.
+
+package main
+
+type reader struct {
+ C chan T
+}
+
+type T struct{ C chan []byte }
+
+var r = newReader()
+
+func newReader() *reader { return new(reader) }
+
+func (r *reader) Read(n int) ([]byte, error) {
+ req := T{C: make(chan []byte)}
+ r.C <- req
+ return <-req.C, nil
+}
+
+func main() {
+ s, err := r.Read(1)
+ _, _ = s, err
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4326.dir/p1.go b/gcc/testsuite/go.test/test/fixedbugs/issue4326.dir/p1.go
new file mode 100644
index 00000000000..ab214befb4b
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4326.dir/p1.go
@@ -0,0 +1,12 @@
+package p1
+
+type O map[string]map[string]string
+
+func (opts O) RemoveOption(sect, opt string) bool {
+ if _, ok := opts[sect]; !ok {
+ return false
+ }
+ _, ok := opts[sect][opt]
+ delete(opts[sect], opt)
+ return ok
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4326.dir/p2.go b/gcc/testsuite/go.test/test/fixedbugs/issue4326.dir/p2.go
new file mode 100644
index 00000000000..8e86266dd8d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4326.dir/p2.go
@@ -0,0 +1,5 @@
+package p2
+
+import "./p1"
+
+func NewO() p1.O { return nil }
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4326.dir/q1.go b/gcc/testsuite/go.test/test/fixedbugs/issue4326.dir/q1.go
new file mode 100644
index 00000000000..f118eb09252
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4326.dir/q1.go
@@ -0,0 +1,8 @@
+package q1
+
+func Deref(typ interface{}) interface{} {
+ if typ, ok := typ.(*int); ok {
+ return *typ
+ }
+ return typ
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4326.dir/q2.go b/gcc/testsuite/go.test/test/fixedbugs/issue4326.dir/q2.go
new file mode 100644
index 00000000000..075e2b21e7a
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4326.dir/q2.go
@@ -0,0 +1,11 @@
+package main
+
+import "./q1"
+
+func main() {
+ x := 1
+ y := q1.Deref(&x)
+ if y != 1 {
+ panic("y != 1")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4326.dir/z.go b/gcc/testsuite/go.test/test/fixedbugs/issue4326.dir/z.go
new file mode 100644
index 00000000000..9b222e8b402
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4326.dir/z.go
@@ -0,0 +1,7 @@
+package z
+
+import "./p2"
+
+func main() {
+ p2.NewO().RemoveOption("hello", "world")
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4326.go b/gcc/testsuite/go.test/test/fixedbugs/issue4326.go
new file mode 100644
index 00000000000..5ce2eea2661
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4326.go
@@ -0,0 +1,9 @@
+// compiledir
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Printing local variables in inliner shadows global names.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4348.go b/gcc/testsuite/go.test/test/fixedbugs/issue4348.go
new file mode 100644
index 00000000000..3dac8f7685c
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4348.go
@@ -0,0 +1,29 @@
+// compile
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 4348. After switch to 64-bit ints the compiler generates
+// illegal instructions when using large array bounds or indexes.
+
+package main
+
+// 1<<32 on a 64-bit machine, 1 otherwise.
+const LARGE = ^uint(0)>>32 + 1
+
+func A() int {
+ var a []int
+ return a[LARGE]
+}
+
+var b [LARGE]int
+
+func B(i int) int {
+ return b[i]
+}
+
+func main() {
+ n := A()
+ B(n)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4353.go b/gcc/testsuite/go.test/test/fixedbugs/issue4353.go
new file mode 100644
index 00000000000..defe7c324c2
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4353.go
@@ -0,0 +1,19 @@
+// run
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 4353. An optimizer bug in 8g triggers a runtime fault
+// instead of an out of bounds panic.
+
+package main
+
+var aib [100000]int
+var paib *[100000]int = &aib
+var i64 int64 = 100023
+
+func main() {
+ defer func() { recover() }()
+ _ = paib[i64]
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4359.go b/gcc/testsuite/go.test/test/fixedbugs/issue4359.go
new file mode 100644
index 00000000000..b5adb4010b8
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4359.go
@@ -0,0 +1,19 @@
+// errorcheck
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 4359: wrong handling of broken struct fields
+// causes "internal compiler error: lookdot badwidth".
+
+package main
+
+type T struct {
+ x T1 // ERROR "undefined"
+}
+
+func f() {
+ var t *T
+ _ = t.x
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4370.dir/p1.go b/gcc/testsuite/go.test/test/fixedbugs/issue4370.dir/p1.go
new file mode 100644
index 00000000000..d732c8b363e
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4370.dir/p1.go
@@ -0,0 +1,20 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p1
+
+type Magic int
+
+type T struct {
+ x interface{}
+}
+
+func (t *T) M() bool {
+ _, ok := t.x.(Magic)
+ return ok
+}
+
+func F(t *T) {
+ println(t)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4370.dir/p2.go b/gcc/testsuite/go.test/test/fixedbugs/issue4370.dir/p2.go
new file mode 100644
index 00000000000..33370d07a4e
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4370.dir/p2.go
@@ -0,0 +1,16 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p2
+
+import "./p1"
+
+type T struct {
+ p1.T
+}
+
+func F() {
+ var t T
+ p1.F(&t.T)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4370.dir/p3.go b/gcc/testsuite/go.test/test/fixedbugs/issue4370.dir/p3.go
new file mode 100644
index 00000000000..13c996bc229
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4370.dir/p3.go
@@ -0,0 +1,13 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p3
+
+import "./p2"
+
+func F() {
+ p2.F()
+ var t p2.T
+ println(t.T.M())
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4370.go b/gcc/testsuite/go.test/test/fixedbugs/issue4370.go
new file mode 100644
index 00000000000..76b47e1a6d5
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4370.go
@@ -0,0 +1,9 @@
+// compiledir
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Re-exporting inlined function bodies missed types in x, ok := v.(Type)
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4396a.go b/gcc/testsuite/go.test/test/fixedbugs/issue4396a.go
new file mode 100644
index 00000000000..11ae1f7c6c6
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4396a.go
@@ -0,0 +1,27 @@
+// run
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 4396. Arrays of bytes are not required to be
+// word aligned. 5g should use MOVB to load the address
+// of s.g[0] for its nil check.
+//
+// This test _may_ fail on arm, but requires the host to
+// trap unaligned loads. This is generally done with
+//
+// echo "4" > /proc/cpu/alignment
+
+package main
+
+var s = struct {
+ // based on lzw.decoder
+ a, b, c, d, e uint16
+ f [4096]uint8
+ g [4096]uint8
+}{}
+
+func main() {
+ s.g[0] = 1
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4396b.go b/gcc/testsuite/go.test/test/fixedbugs/issue4396b.go
new file mode 100644
index 00000000000..d0bf28fac28
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4396b.go
@@ -0,0 +1,29 @@
+// run
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This test _may_ fail on arm, but requires the host to
+// trap unaligned loads. This is generally done with
+//
+// echo "4" > /proc/cpu/alignment
+
+package main
+
+type T struct {
+ U uint16
+ V T2
+}
+
+type T2 struct {
+ pad [4096]byte
+ A, B byte
+}
+
+var s, t = new(T), new(T)
+
+func main() {
+ var u, v *T2 = &s.V, &t.V
+ u.B = v.B
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4399.go b/gcc/testsuite/go.test/test/fixedbugs/issue4399.go
new file mode 100644
index 00000000000..6674db9ec30
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4399.go
@@ -0,0 +1,15 @@
+// compile
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 4399: 8g would print "gins LEAQ nil *A".
+
+package main
+
+type A struct{ a int }
+
+func main() {
+ println(((*A)(nil)).a)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4405.go b/gcc/testsuite/go.test/test/fixedbugs/issue4405.go
new file mode 100644
index 00000000000..b8458d77647
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4405.go
@@ -0,0 +1,15 @@
+// errorcheck
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+const (
+ _ = iota
+ _ // ERROR "illegal character|invalid character"
+ _ // ERROR "illegal character|invalid character"
+ _ // ERROR "illegal character|invalid character"
+ _ // ERROR "illegal character|invalid character"
+)
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4429.go b/gcc/testsuite/go.test/test/fixedbugs/issue4429.go
new file mode 100644
index 00000000000..6822760ef8c
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4429.go
@@ -0,0 +1,16 @@
+// errorcheck
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type a struct {
+ a int
+}
+
+func main() {
+ av := a{};
+ _ = *a(av); // ERROR "invalid indirect|expected pointer"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4448.go b/gcc/testsuite/go.test/test/fixedbugs/issue4448.go
new file mode 100644
index 00000000000..fa1d9fe49d3
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4448.go
@@ -0,0 +1,37 @@
+// run
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 4448: 64-bit indices that are statically known
+// to be bounded make 5g and 8g generate a dangling branch.
+
+package main
+
+const b26 uint64 = 0x022fdd63cc95386d
+
+var bitPos [64]int
+
+func init() {
+ for p := uint(0); p < 64; p++ {
+ bitPos[b26<<p>>58] = int(p)
+ }
+}
+
+func MinPos(w uint64) int {
+ if w == 0 {
+ panic("bit: MinPos(0) undefined")
+ }
+ return bitPos[((w&-w)*b26)>>58]
+}
+
+func main() {
+ const one = uint64(1)
+ for i := 0; i < 64; i++ {
+ if MinPos(1<<uint(i)) != i {
+ println("i =", i)
+ panic("MinPos(1<<uint(i)) != i")
+ }
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4452.go b/gcc/testsuite/go.test/test/fixedbugs/issue4452.go
new file mode 100644
index 00000000000..54dd214d69f
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4452.go
@@ -0,0 +1,13 @@
+// errorcheck
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 4452. Used to print many errors, now just one.
+
+package main
+
+func main() {
+ _ = [...]int(4) // ERROR "\[\.\.\.\].*outside of array literal"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4458.go b/gcc/testsuite/go.test/test/fixedbugs/issue4458.go
new file mode 100644
index 00000000000..820f18cb8d7
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4458.go
@@ -0,0 +1,20 @@
+// errorcheck
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 4458: gc accepts invalid method expressions
+// like (**T).Method.
+
+package main
+
+type T struct{}
+
+func (T) foo() {}
+
+func main() {
+ av := T{}
+ pav := &av
+ (**T).foo(&pav) // ERROR "no method foo|requires named type or pointer to named"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4463.go b/gcc/testsuite/go.test/test/fixedbugs/issue4463.go
new file mode 100644
index 00000000000..70977ceb782
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4463.go
@@ -0,0 +1,87 @@
+// errorcheck
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 4463: test builtin functions in statement context and in
+// go/defer functions.
+
+package p
+
+import "unsafe"
+
+func F() {
+ var a []int
+ var c chan int
+ var m map[int]int
+ var s struct{ f int }
+
+ append(a, 0) // ERROR "not used"
+ cap(a) // ERROR "not used"
+ complex(1, 2) // ERROR "not used"
+ imag(1i) // ERROR "not used"
+ len(a) // ERROR "not used"
+ make([]int, 10) // ERROR "not used"
+ new(int) // ERROR "not used"
+ real(1i) // ERROR "not used"
+ unsafe.Alignof(a) // ERROR "not used"
+ unsafe.Offsetof(s.f) // ERROR "not used"
+ unsafe.Sizeof(a) // ERROR "not used"
+
+ close(c)
+ copy(a, a)
+ delete(m, 0)
+ panic(0)
+ print("foo")
+ println("bar")
+ recover()
+
+ (close(c))
+ (copy(a, a))
+ (delete(m, 0))
+ (panic(0))
+ (print("foo"))
+ (println("bar"))
+ (recover())
+
+ go append(a, 0) // ERROR "not used|discards result"
+ go cap(a) // ERROR "not used|discards result"
+ go complex(1, 2) // ERROR "not used|discards result"
+ go imag(1i) // ERROR "not used|discards result"
+ go len(a) // ERROR "not used|discards result"
+ go make([]int, 10) // ERROR "not used|discards result"
+ go new(int) // ERROR "not used|discards result"
+ go real(1i) // ERROR "not used|discards result"
+ go unsafe.Alignof(a) // ERROR "not used|discards result"
+ go unsafe.Offsetof(s.f) // ERROR "not used|discards result"
+ go unsafe.Sizeof(a) // ERROR "not used|discards result"
+
+ go close(c)
+ go copy(a, a)
+ go delete(m, 0)
+ go panic(0)
+ go print("foo")
+ go println("bar")
+ go recover()
+
+ defer append(a, 0) // ERROR "not used|discards result"
+ defer cap(a) // ERROR "not used|discards result"
+ defer complex(1, 2) // ERROR "not used|discards result"
+ defer imag(1i) // ERROR "not used|discards result"
+ defer len(a) // ERROR "not used|discards result"
+ defer make([]int, 10) // ERROR "not used|discards result"
+ defer new(int) // ERROR "not used|discards result"
+ defer real(1i) // ERROR "not used|discards result"
+ defer unsafe.Alignof(a) // ERROR "not used|discards result"
+ defer unsafe.Offsetof(s.f) // ERROR "not used|discards result"
+ defer unsafe.Sizeof(a) // ERROR "not used|discards result"
+
+ defer close(c)
+ defer copy(a, a)
+ defer delete(m, 0)
+ defer panic(0)
+ defer print("foo")
+ defer println("bar")
+ defer recover()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4468.go b/gcc/testsuite/go.test/test/fixedbugs/issue4468.go
new file mode 100644
index 00000000000..ef0b46bcf68
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4468.go
@@ -0,0 +1,28 @@
+// errorcheck
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 4468: go/defer calls may not be parenthesized.
+
+package p
+
+type T int
+
+func (t *T) F() T {
+ return *t
+}
+
+type S struct {
+ t T
+}
+
+func F() {
+ go (F()) // ERROR "must be function call"
+ defer (F()) // ERROR "must be function call"
+ var s S
+ (&s.t).F()
+ go (&s.t).F()
+ defer (&s.t).F()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4470.go b/gcc/testsuite/go.test/test/fixedbugs/issue4470.go
new file mode 100644
index 00000000000..5ed09ca554b
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4470.go
@@ -0,0 +1,16 @@
+// errorcheck
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 4470: parens are not allowed around .(type) "expressions"
+
+package main
+
+func main() {
+ var i interface{}
+ switch (i.(type)) { // ERROR "outside type switch"
+ default:
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4495.go b/gcc/testsuite/go.test/test/fixedbugs/issue4495.go
new file mode 100644
index 00000000000..7ec1134d7b6
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4495.go
@@ -0,0 +1,29 @@
+// run
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+type I interface {
+ m() int
+}
+
+type T struct{}
+
+func (T) m() int {
+ return 3
+}
+
+var t T
+
+var ret = I.m(t)
+
+func main() {
+ if ret != 3 {
+ println("ret = ", ret)
+ panic("ret != 3")
+ }
+}
+
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4510.dir/f1.go b/gcc/testsuite/go.test/test/fixedbugs/issue4510.dir/f1.go
new file mode 100644
index 00000000000..7e2cffa5dd8
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4510.dir/f1.go
@@ -0,0 +1,9 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+import "fmt" // ERROR "fmt redeclared|imported"
+
+var _ = fmt.Printf
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4510.dir/f2.go b/gcc/testsuite/go.test/test/fixedbugs/issue4510.dir/f2.go
new file mode 100644
index 00000000000..895fc342ba1
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4510.dir/f2.go
@@ -0,0 +1,7 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func fmt() {}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4510.go b/gcc/testsuite/go.test/test/fixedbugs/issue4510.go
new file mode 100644
index 00000000000..003f9e8e163
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4510.go
@@ -0,0 +1,7 @@
+// errorcheckdir
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4517a.go b/gcc/testsuite/go.test/test/fixedbugs/issue4517a.go
new file mode 100644
index 00000000000..a1b6b57e974
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4517a.go
@@ -0,0 +1,9 @@
+// errorcheck
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+var init = 1 // ERROR "cannot declare init - must be func"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4517b.go b/gcc/testsuite/go.test/test/fixedbugs/issue4517b.go
new file mode 100644
index 00000000000..f04103ff5b2
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4517b.go
@@ -0,0 +1,9 @@
+// errorcheck
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+const init = 1 // ERROR "cannot declare init - must be func"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4517c.go b/gcc/testsuite/go.test/test/fixedbugs/issue4517c.go
new file mode 100644
index 00000000000..47b21cf4084
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4517c.go
@@ -0,0 +1,9 @@
+// errorcheck
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type init byte // ERROR "cannot declare init - must be func"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4518.go b/gcc/testsuite/go.test/test/fixedbugs/issue4518.go
new file mode 100644
index 00000000000..e64b069bb99
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4518.go
@@ -0,0 +1,67 @@
+// run
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 4518. In some circumstances "return F(...)"
+// where F has multiple returns is miscompiled by 6g due to
+// bold assumptions in componentgen.
+
+package main
+
+func DontInline() {}
+
+func F(e interface{}) (int, int) {
+ DontInline()
+ return 3, 7
+}
+
+func G() (int, int) {
+ DontInline()
+ return 3, 7
+}
+
+func bogus1(d interface{}) (int, int) {
+ switch {
+ default:
+ return F(d)
+ }
+ return 0, 0
+}
+
+func bogus2() (int, int) {
+ switch {
+ default:
+ return F(3)
+ }
+ return 0, 0
+}
+
+func bogus3(d interface{}) (int, int) {
+ switch {
+ default:
+ return G()
+ }
+ return 0, 0
+}
+
+func bogus4() (int, int) {
+ switch {
+ default:
+ return G()
+ }
+ return 0, 0
+}
+
+func check(a, b int) {
+ if a != 3 || b != 7 {
+ println(a, b)
+ panic("a != 3 || b != 7")
+ }
+}
+
+func main() {
+ check(bogus1(42))
+ check(bogus2())
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4529.go b/gcc/testsuite/go.test/test/fixedbugs/issue4529.go
new file mode 100644
index 00000000000..4f37e7c36b6
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4529.go
@@ -0,0 +1,33 @@
+// compile
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 4529: escape analysis crashes on "go f(g())"
+// when g has multiple returns.
+
+package main
+
+type M interface{}
+
+type A struct {
+ a string
+ b chan M
+}
+
+func (a *A) I() (b <-chan M, c chan<- M) {
+ a.b, c = make(chan M), make(chan M)
+ b = a.b
+
+ return
+}
+
+func Init(a string, b *A, c interface {
+ I() (<-chan M, chan<- M)
+}) {
+ b.a = a
+ go b.c(c.I())
+}
+
+func (a *A) c(b <-chan M, _ chan<- M) {}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4545.go b/gcc/testsuite/go.test/test/fixedbugs/issue4545.go
new file mode 100644
index 00000000000..c37ccef7cbf
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4545.go
@@ -0,0 +1,19 @@
+// errorcheck
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 4545: untyped constants are incorrectly coerced
+// to concrete types when used in interface{} context.
+
+package main
+
+import "fmt"
+
+func main() {
+ var s uint
+ fmt.Println(1.0 + 1<<s) // ERROR "invalid operation|non-integer type|incompatible type"
+ x := 1.0 + 1<<s // ERROR "invalid operation|non-integer type"
+ _ = x
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4562.go b/gcc/testsuite/go.test/test/fixedbugs/issue4562.go
new file mode 100644
index 00000000000..29d98b0283d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4562.go
@@ -0,0 +1,49 @@
+// run
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "fmt"
+ "runtime"
+ "strings"
+)
+
+type T struct {
+ val int
+}
+
+func main() {
+ defer expectError(22)
+ var pT *T
+ switch pT.val { // error should be here - line 22
+ case 0:
+ fmt.Println("0")
+ case 1: // used to show up here instead
+ fmt.Println("1")
+ case 2:
+ fmt.Println("2")
+ }
+ fmt.Println("finished")
+}
+
+func expectError(expectLine int) {
+ if recover() == nil {
+ panic("did not crash")
+ }
+ for i := 1;; i++ {
+ _, file, line, ok := runtime.Caller(i)
+ if !ok {
+ panic("cannot find issue4562.go on stack")
+ }
+ if strings.HasSuffix(file, "issue4562.go") {
+ if line != expectLine {
+ panic(fmt.Sprintf("crashed at line %d, wanted line %d", line, expectLine))
+ }
+ break
+ }
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4585.go b/gcc/testsuite/go.test/test/fixedbugs/issue4585.go
new file mode 100644
index 00000000000..ad1242d1e5f
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4585.go
@@ -0,0 +1,151 @@
+// run
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 4585: comparisons and hashes process blank
+// fields and padding in structs.
+
+package main
+
+import "unsafe"
+
+// T is a structure with padding.
+type T struct {
+ A int16
+ B int64
+ C int16
+ D int64
+ Dummy [64]byte
+}
+
+// U is a structure with a blank field
+type U struct {
+ A, _, B int
+ Dummy [64]byte
+}
+
+// USmall is like U but the frontend will inline comparison
+// instead of calling the generated eq function.
+type USmall struct {
+ A, _, B int32
+}
+
+// V has padding but not on the first field.
+type V struct {
+ A1, A2, A3 int32
+ B int16
+ C int32
+}
+
+// W has padding at the end.
+type W struct {
+ A1, A2, A3 int32
+ B int32
+ C int8
+}
+
+func test1() {
+ var a, b U
+ m := make(map[U]int)
+ copy((*[16]byte)(unsafe.Pointer(&a))[:], "hello world!")
+ a.A, a.B = 1, 2
+ b.A, b.B = 1, 2
+ if a != b {
+ panic("broken equality: a != b")
+ }
+
+ m[a] = 1
+ m[b] = 2
+ if len(m) == 2 {
+ panic("broken hash: len(m) == 2")
+ }
+ if m[a] != 2 {
+ panic("m[a] != 2")
+ }
+}
+
+func test2() {
+ var a, b T
+ m := make(map[T]int)
+
+ copy((*[16]byte)(unsafe.Pointer(&a))[:], "hello world!")
+ a.A, a.B, a.C, a.D = 1, 2, 3, 4
+ b.A, b.B, b.C, b.D = 1, 2, 3, 4
+
+ if a != b {
+ panic("broken equality: a != b")
+ }
+
+ m[a] = 1
+ m[b] = 2
+ if len(m) == 2 {
+ panic("broken hash: len(m) == 2")
+ }
+ if m[a] != 2 {
+ panic("m[a] != 2")
+ }
+}
+
+func test3() {
+ var a, b USmall
+ copy((*[12]byte)(unsafe.Pointer(&a))[:], "hello world!")
+ a.A, a.B = 1, 2
+ b.A, b.B = 1, 2
+ if a != b {
+ panic("broken equality: a != b")
+ }
+}
+
+func test4() {
+ var a, b V
+ m := make(map[V]int)
+
+ copy((*[20]byte)(unsafe.Pointer(&a))[:], "Hello World, Gopher!")
+ a.A1, a.A2, a.A3, a.B, a.C = 1, 2, 3, 4, 5
+ b.A1, b.A2, b.A3, b.B, b.C = 1, 2, 3, 4, 5
+
+ if a != b {
+ panic("broken equality: a != b")
+ }
+
+ m[a] = 1
+ m[b] = 2
+ if len(m) == 2 {
+ panic("broken hash: len(m) == 2")
+ }
+ if m[a] != 2 {
+ panic("m[a] != 2")
+ }
+}
+
+func test5() {
+ var a, b W
+ m := make(map[W]int)
+
+ copy((*[20]byte)(unsafe.Pointer(&a))[:], "Hello World, Gopher!")
+ a.A1, a.A2, a.A3, a.B, a.C = 1, 2, 3, 4, 5
+ b.A1, b.A2, b.A3, b.B, b.C = 1, 2, 3, 4, 5
+
+ if a != b {
+ panic("broken equality: a != b")
+ }
+
+ m[a] = 1
+ m[b] = 2
+ if len(m) == 2 {
+ panic("broken hash: len(m) == 2")
+ }
+ if m[a] != 2 {
+ panic("m[a] != 2")
+ }
+}
+
+func main() {
+ test1()
+ test2()
+ test3()
+ test4()
+ test5()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4590.dir/pkg1.go b/gcc/testsuite/go.test/test/fixedbugs/issue4590.dir/pkg1.go
new file mode 100644
index 00000000000..c447371c1ab
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4590.dir/pkg1.go
@@ -0,0 +1,26 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package pkg1
+
+type A interface {
+ Write() error
+}
+
+type B interface {
+ Hello()
+ world()
+}
+
+type C struct{}
+
+func (c C) Write() error { return nil }
+
+var T = struct{ A }{nil}
+var U = struct{ B }{nil}
+var V A = struct{ *C }{nil}
+var W = interface {
+ Write() error
+ Hello()
+}(nil)
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4590.dir/pkg2.go b/gcc/testsuite/go.test/test/fixedbugs/issue4590.dir/pkg2.go
new file mode 100644
index 00000000000..61c01d7aec2
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4590.dir/pkg2.go
@@ -0,0 +1,15 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package pkg2
+
+import "./pkg1"
+
+var T = struct{ pkg1.A }{nil}
+var U = struct{ pkg1.B }{nil}
+var V pkg1.A = struct{ *pkg1.C }{nil}
+var W = interface {
+ Write() error
+ Hello()
+}(nil)
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4590.dir/prog.go b/gcc/testsuite/go.test/test/fixedbugs/issue4590.dir/prog.go
new file mode 100644
index 00000000000..3220e85d3a6
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4590.dir/prog.go
@@ -0,0 +1,25 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "./pkg1"
+ "./pkg2"
+)
+
+func main() {
+ if pkg1.T != pkg2.T {
+ panic("pkg1.T != pkg2.T")
+ }
+ if pkg1.U != pkg2.U {
+ panic("pkg1.U != pkg2.U")
+ }
+ if pkg1.V != pkg2.V {
+ panic("pkg1.V != pkg2.V")
+ }
+ if pkg1.W != pkg2.W {
+ panic("pkg1.W != pkg2.W")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4590.go b/gcc/testsuite/go.test/test/fixedbugs/issue4590.go
new file mode 100644
index 00000000000..faeb1adef23
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4590.go
@@ -0,0 +1,10 @@
+// rundir
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 4590: linker fails on multiple imports of
+// an anonymous struct with methods.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4610.go b/gcc/testsuite/go.test/test/fixedbugs/issue4610.go
new file mode 100644
index 00000000000..d56c6d3e8cd
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4610.go
@@ -0,0 +1,17 @@
+// errorcheck
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+type bar struct {
+ x int
+}
+
+func main() {
+ var foo bar
+ _ = &foo{} // ERROR "is not a type|expected .;."
+} // GCCGO_ERROR "expected declaration"
+
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4614.go b/gcc/testsuite/go.test/test/fixedbugs/issue4614.go
new file mode 100644
index 00000000000..1aa318c2b23
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4614.go
@@ -0,0 +1,20 @@
+// compile
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 4614: slicing of nil slices confuses the compiler
+// with a uintptr(nil) node.
+
+package p
+
+import "unsafe"
+
+var n int
+
+var _ = []int(nil)[1:]
+var _ = []int(nil)[n:]
+
+var _ = uintptr(unsafe.Pointer(nil))
+var _ = unsafe.Pointer(uintptr(0))
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4618.go b/gcc/testsuite/go.test/test/fixedbugs/issue4618.go
new file mode 100644
index 00000000000..ff91ae70673
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4618.go
@@ -0,0 +1,41 @@
+// run
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "fmt"
+ "os"
+ "runtime"
+ "testing"
+)
+
+type T struct { int }
+
+var globl *T
+
+func F() {
+ t := &T{}
+ globl = t
+}
+
+func G() {
+ t := &T{}
+ _ = t
+}
+
+func main() {
+ nf := testing.AllocsPerRun(100, F)
+ ng := testing.AllocsPerRun(100, G)
+ if int(nf) != 1 {
+ fmt.Printf("AllocsPerRun(100, F) = %v, want 1\n", nf)
+ os.Exit(1)
+ }
+ if int(ng) != 0 && (runtime.Compiler != "gccgo" || int(ng) != 1) {
+ fmt.Printf("AllocsPerRun(100, G) = %v, want 0\n", ng)
+ os.Exit(1)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4620.go b/gcc/testsuite/go.test/test/fixedbugs/issue4620.go
new file mode 100644
index 00000000000..7b4ebf944d6
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4620.go
@@ -0,0 +1,21 @@
+// run
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 4620: map indexes are not evaluated before assignment of other elements
+
+package main
+
+import "fmt"
+
+func main() {
+ m := map[int]int{0:1}
+ i := 0
+ i, m[i] = 1, 2
+ if m[0] != 2 {
+ fmt.Println(m)
+ panic("m[i] != 2")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4654.go b/gcc/testsuite/go.test/test/fixedbugs/issue4654.go
new file mode 100644
index 00000000000..d3f582b20c6
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4654.go
@@ -0,0 +1,71 @@
+// errorcheck
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 4654.
+// Check error for conversion and 'not used' in defer/go.
+
+package p
+
+import "unsafe"
+
+func f() {
+ defer int(0) // ERROR "defer requires function call, not conversion|is not used"
+ go string([]byte("abc")) // ERROR "go requires function call, not conversion|is not used"
+
+ var c complex128
+ var f float64
+ var t struct {X int}
+
+ var x []int
+ defer append(x, 1) // ERROR "defer discards result of append|is not used"
+ defer cap(x) // ERROR "defer discards result of cap|is not used"
+ defer complex(1, 2) // ERROR "defer discards result of complex|is not used"
+ defer complex(f, 1) // ERROR "defer discards result of complex|is not used"
+ defer imag(1i) // ERROR "defer discards result of imag|is not used"
+ defer imag(c) // ERROR "defer discards result of imag|is not used"
+ defer len(x) // ERROR "defer discards result of len|is not used"
+ defer make([]int, 1) // ERROR "defer discards result of make|is not used"
+ defer make(chan bool) // ERROR "defer discards result of make|is not used"
+ defer make(map[string]int) // ERROR "defer discards result of make|is not used"
+ defer new(int) // ERROR "defer discards result of new|is not used"
+ defer real(1i) // ERROR "defer discards result of real|is not used"
+ defer real(c) // ERROR "defer discards result of real|is not used"
+ defer append(x, 1) // ERROR "defer discards result of append|is not used"
+ defer append(x, 1) // ERROR "defer discards result of append|is not used"
+ defer unsafe.Alignof(t.X) // ERROR "defer discards result of unsafe.Alignof|is not used"
+ defer unsafe.Offsetof(t.X) // ERROR "defer discards result of unsafe.Offsetof|is not used"
+ defer unsafe.Sizeof(t) // ERROR "defer discards result of unsafe.Sizeof|is not used"
+
+ defer copy(x, x) // ok
+ m := make(map[int]int)
+ defer delete(m, 1) // ok
+ defer panic(1) // ok
+ defer print(1) // ok
+ defer println(1) // ok
+ defer recover() // ok
+
+ int(0) // ERROR "int\(0\) evaluated but not used|is not used"
+ string([]byte("abc")) // ERROR "string\(.*\) evaluated but not used|is not used"
+
+ append(x, 1) // ERROR "not used"
+ cap(x) // ERROR "not used"
+ complex(1, 2) // ERROR "not used"
+ complex(f, 1) // ERROR "not used"
+ imag(1i) // ERROR "not used"
+ imag(c) // ERROR "not used"
+ len(x) // ERROR "not used"
+ make([]int, 1) // ERROR "not used"
+ make(chan bool) // ERROR "not used"
+ make(map[string]int) // ERROR "not used"
+ new(int) // ERROR "not used"
+ real(1i) // ERROR "not used"
+ real(c) // ERROR "not used"
+ append(x, 1) // ERROR "not used"
+ append(x, 1) // ERROR "not used"
+ unsafe.Alignof(t.X) // ERROR "not used"
+ unsafe.Offsetof(t.X) // ERROR "not used"
+ unsafe.Sizeof(t) // ERROR "not used"
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4663.go b/gcc/testsuite/go.test/test/fixedbugs/issue4663.go
new file mode 100644
index 00000000000..edaee93c5b7
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4663.go
@@ -0,0 +1,15 @@
+// errorcheck
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 4663.
+// Make sure 'not used' message is placed correctly.
+
+package main
+
+func a(b int) int64 {
+ b // ERROR "not used"
+ return 0
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4667.go b/gcc/testsuite/go.test/test/fixedbugs/issue4667.go
new file mode 100644
index 00000000000..3a00a31952c
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4667.go
@@ -0,0 +1,37 @@
+// run
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "fmt"
+ "os"
+ "testing"
+)
+
+var globl *int
+
+func G() {
+ F()
+}
+
+func F() {
+ var x int
+ globl = &x
+}
+
+func main() {
+ nf := testing.AllocsPerRun(100, F)
+ ng := testing.AllocsPerRun(100, G)
+ if int(nf) != 1 {
+ fmt.Printf("AllocsPerRun(100, F) = %v, want 1\n", nf)
+ os.Exit(1)
+ }
+ if int(ng) != 1 {
+ fmt.Printf("AllocsPerRun(100, G) = %v, want 1\n", ng)
+ os.Exit(1)
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4734.go b/gcc/testsuite/go.test/test/fixedbugs/issue4734.go
new file mode 100644
index 00000000000..69f66f2129f
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4734.go
@@ -0,0 +1,21 @@
+// compile
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Caused gccgo to emit multiple definitions of the same symbol.
+
+package p
+
+type S1 struct{}
+
+func (s *S1) M() {}
+
+type S2 struct {
+ F struct{ *S1 }
+}
+
+func F() {
+ _ = struct{ *S1 }{}
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4748.go b/gcc/testsuite/go.test/test/fixedbugs/issue4748.go
new file mode 100644
index 00000000000..73c75393cf4
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4748.go
@@ -0,0 +1,20 @@
+// run
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 4748.
+// This program used to complain because inlining created two exit labels.
+
+package main
+
+func jump() {
+ goto exit
+exit:
+ return
+}
+func main() {
+ jump()
+ jump()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4752.go b/gcc/testsuite/go.test/test/fixedbugs/issue4752.go
new file mode 100644
index 00000000000..d6781e39a22
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4752.go
@@ -0,0 +1,26 @@
+// run
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func F(xi, yi interface{}) uint64 {
+ x, y := xi.(uint64), yi.(uint64)
+ return x &^ y
+}
+
+func G(xi, yi interface{}) uint64 {
+ return xi.(uint64) &^ yi.(uint64) // generates incorrect code
+}
+
+func main() {
+ var x, y uint64 = 0, 1 << 63
+ f := F(x, y)
+ g := G(x, y)
+ if f != 0 || g != 0 {
+ println("F", f, "G", g)
+ panic("bad")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4785.go b/gcc/testsuite/go.test/test/fixedbugs/issue4785.go
new file mode 100644
index 00000000000..c3dd6297d85
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4785.go
@@ -0,0 +1,20 @@
+// run
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// issue 4785: used to fail to compile
+
+package main
+
+func t(x, y interface{}) interface{} {
+ return x.(float64) > y.(float64)
+}
+
+func main() {
+ v := t(1.0, 2.0)
+ if v != false {
+ panic("bad comparison")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4813.go b/gcc/testsuite/go.test/test/fixedbugs/issue4813.go
new file mode 100644
index 00000000000..f560b2fac98
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4813.go
@@ -0,0 +1,52 @@
+// errorcheck
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 4813: use of constant floats as indices.
+
+package main
+
+var A [3]int
+var S []int
+var T string
+
+const (
+ i = 1
+ f = 2.0
+ f2 = 2.1
+ c = complex(2, 0)
+ c2 = complex(2, 1)
+)
+
+var (
+ vf = f
+ vc = c
+)
+
+var (
+ a1 = A[i]
+ a2 = A[f]
+ a3 = A[f2] // ERROR "truncated|must be integer"
+ a4 = A[c]
+ a5 = A[c2] // ERROR "truncated|must be integer"
+ a6 = A[vf] // ERROR "non-integer|must be integer"
+ a7 = A[vc] // ERROR "non-integer|must be integer"
+
+ s1 = S[i]
+ s2 = S[f]
+ s3 = S[f2] // ERROR "truncated|must be integer"
+ s4 = S[c]
+ s5 = S[c2] // ERROR "truncated|must be integer"
+ s6 = S[vf] // ERROR "non-integer|must be integer"
+ s7 = S[vc] // ERROR "non-integer|must be integer"
+
+ t1 = T[i]
+ t2 = T[f]
+ t3 = T[f2] // ERROR "truncated|must be integer"
+ t4 = T[c]
+ t5 = T[c2] // ERROR "truncated|must be integer"
+ t6 = T[vf] // ERROR "non-integer|must be integer"
+ t7 = T[vc] // ERROR "non-integer|must be integer"
+)
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4879.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue4879.dir/a.go
new file mode 100644
index 00000000000..7ee7c486047
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4879.dir/a.go
@@ -0,0 +1,33 @@
+package a
+
+import (
+ "unsafe"
+)
+
+type Collection struct {
+ root unsafe.Pointer
+}
+
+type nodeLoc struct{}
+
+type slice []int
+
+type maptype map[int]int
+
+func MakePrivateCollection() *Collection {
+ return &Collection{
+ root: unsafe.Pointer(&nodeLoc{}),
+ }
+}
+
+func MakePrivateCollection2() *Collection {
+ return &Collection{
+ root: unsafe.Pointer(&slice{}),
+ }
+}
+func MakePrivateCollection3() *Collection {
+ return &Collection{
+ root: unsafe.Pointer(&maptype{}),
+ }
+}
+
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4879.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/issue4879.dir/b.go
new file mode 100644
index 00000000000..d8fb5693db9
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4879.dir/b.go
@@ -0,0 +1,9 @@
+package b
+
+import "./a"
+
+func F() {
+ a.MakePrivateCollection()
+ a.MakePrivateCollection2()
+ a.MakePrivateCollection3()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4879.go b/gcc/testsuite/go.test/test/fixedbugs/issue4879.go
new file mode 100644
index 00000000000..842c8117ff1
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4879.go
@@ -0,0 +1,10 @@
+// compiledir
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 4879: export data misses the '&' for some
+// composite literals in inlined bodies.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4909a.go b/gcc/testsuite/go.test/test/fixedbugs/issue4909a.go
new file mode 100644
index 00000000000..aefe2d64557
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4909a.go
@@ -0,0 +1,35 @@
+// errorcheck
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 4909: compiler incorrectly accepts unsafe.Offsetof(t.x)
+// where x is a field of an embedded pointer field.
+
+package p
+
+import (
+ "unsafe"
+)
+
+type T struct {
+ A int
+ *B
+}
+
+func (t T) Method() {}
+
+type B struct {
+ X, Y int
+}
+
+var t T
+var p *T
+
+const N1 = unsafe.Offsetof(t.X) // ERROR "indirection"
+const N2 = unsafe.Offsetof(p.X) // ERROR "indirection"
+const N3 = unsafe.Offsetof(t.B.X) // valid
+const N4 = unsafe.Offsetof(p.B.X) // valid
+const N5 = unsafe.Offsetof(t.Method) // ERROR "method value"
+const N6 = unsafe.Offsetof(p.Method) // ERROR "method value"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4909b.go b/gcc/testsuite/go.test/test/fixedbugs/issue4909b.go
new file mode 100644
index 00000000000..0f594e3db67
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4909b.go
@@ -0,0 +1,80 @@
+// errorcheckoutput
+
+package main
+
+import "fmt"
+
+// We are going to define 256 types T(n),
+// such that T(n) embeds T(2n) and *T(2n+1).
+
+func main() {
+ fmt.Printf("// errorcheck\n\n")
+ fmt.Printf("package p\n\n")
+ fmt.Println(`import "unsafe"`)
+
+ // Dump types.
+ for n := 1; n < 256; n++ {
+ writeStruct(n)
+ }
+ // Dump leaves
+ for n := 256; n < 512; n++ {
+ fmt.Printf("type T%d int\n", n)
+ }
+
+ fmt.Printf("var t T1\n")
+ fmt.Printf("var p *T1\n")
+
+ // Simple selectors
+ for n := 2; n < 256; n++ {
+ writeDot(n)
+ }
+
+ // Double selectors
+ for n := 128; n < 256; n++ {
+ writeDot(n/16, n)
+ }
+
+ // Triple selectors
+ for n := 128; n < 256; n++ {
+ writeDot(n/64, n/8, n)
+ }
+}
+
+const structTpl = `
+type T%d struct {
+ A%d int
+ T%d
+ *T%d
+}
+`
+
+func writeStruct(n int) {
+ fmt.Printf(structTpl, n, n, 2*n, 2*n+1)
+}
+
+func writeDot(ns ...int) {
+ for _, root := range []string{"t", "p"} {
+ fmt.Printf("const _ = unsafe.Offsetof(%s", root)
+ for _, n := range ns {
+ fmt.Printf(".T%d", n)
+ }
+ // Does it involve an indirection?
+ nlast := ns[len(ns)-1]
+ nprev := 1
+ if len(ns) > 1 {
+ nprev = ns[len(ns)-2]
+ }
+ isIndirect := false
+ for n := nlast / 2; n > nprev; n /= 2 {
+ if n%2 == 1 {
+ isIndirect = true
+ break
+ }
+ }
+ fmt.Print(")")
+ if isIndirect {
+ fmt.Print(` // ERROR "indirection"`)
+ }
+ fmt.Print("\n")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4932.dir/foo.go b/gcc/testsuite/go.test/test/fixedbugs/issue4932.dir/foo.go
new file mode 100644
index 00000000000..19b73a0e038
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4932.dir/foo.go
@@ -0,0 +1,7 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package foo
+
+type Op struct{}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4932.dir/state.go b/gcc/testsuite/go.test/test/fixedbugs/issue4932.dir/state.go
new file mode 100644
index 00000000000..c017b9649d4
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4932.dir/state.go
@@ -0,0 +1,28 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package state
+
+import "./foo"
+
+func Public() {
+ var s Settings
+ s.op()
+}
+
+type State struct{}
+
+func (s *State) x(*Settings) {}
+
+type Settings struct{}
+
+func (c *Settings) x() {
+ run([]foo.Op{{}})
+}
+
+func run([]foo.Op) {}
+
+func (s *Settings) op() foo.Op {
+ return foo.Op{}
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4932.dir/state2.go b/gcc/testsuite/go.test/test/fixedbugs/issue4932.dir/state2.go
new file mode 100644
index 00000000000..50f75db2cea
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4932.dir/state2.go
@@ -0,0 +1,9 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package state2
+
+import "./state"
+
+type Foo *state.State
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4932.go b/gcc/testsuite/go.test/test/fixedbugs/issue4932.go
new file mode 100644
index 00000000000..2a6bc699f0f
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4932.go
@@ -0,0 +1,9 @@
+// compiledir
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 4932: regression in export of composite literals.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4964.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue4964.dir/a.go
new file mode 100644
index 00000000000..2b9e44e351a
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4964.dir/a.go
@@ -0,0 +1,27 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+var global, global2 *int
+
+type T struct {
+ Pointer *int
+}
+
+func dontinline() {}
+
+func Store(t *T) {
+ global = t.Pointer
+ dontinline()
+}
+
+func Store2(t *T) {
+ global2 = t.Pointer
+ dontinline()
+}
+
+func Get() *int {
+ return global
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4964.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/issue4964.dir/b.go
new file mode 100644
index 00000000000..42a6f1d761a
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4964.dir/b.go
@@ -0,0 +1,34 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "./a"
+
+func F() {
+ // store 1 in a.global
+ x, y := 1, 2
+ t := a.T{Pointer: &x}
+ a.Store(&t)
+ _ = y
+}
+
+func G() {
+ // store 4 in a.global2
+ x, y := 3, 4
+ t := a.T{Pointer: &y}
+ a.Store2(&t)
+ _ = x
+}
+
+func main() {
+ F()
+ G()
+ p := a.Get()
+ n := *p
+ if n != 1 {
+ println(n, "!= 1")
+ panic("n != 1")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4964.go b/gcc/testsuite/go.test/test/fixedbugs/issue4964.go
new file mode 100644
index 00000000000..8291d1bb97d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue4964.go
@@ -0,0 +1,10 @@
+// rundir
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 4964: exported escape analysis result is not enough
+// for cross package analysis.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue5002.go b/gcc/testsuite/go.test/test/fixedbugs/issue5002.go
new file mode 100644
index 00000000000..1e74fa1a1f6
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue5002.go
@@ -0,0 +1,16 @@
+// build
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 5002: 8g produces invalid CMPL $0, $0.
+// Used to fail at link time.
+
+package main
+
+func main() {
+ var y int64
+ if y%1 == 0 {
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue5056.go b/gcc/testsuite/go.test/test/fixedbugs/issue5056.go
new file mode 100644
index 00000000000..a2cde2a501e
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue5056.go
@@ -0,0 +1,34 @@
+// run
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// issue 5056: escape analysis not applied to wrapper functions
+
+package main
+
+type Foo int16
+
+func (f Foo) Esc() *int{
+ x := int(f)
+ return &x
+}
+
+type iface interface {
+ Esc() *int
+}
+
+var bar, foobar *int
+
+func main() {
+ var quux iface
+ var x Foo
+
+ quux = x
+ bar = quux.Esc()
+ foobar = quux.Esc()
+ if bar == foobar {
+ panic("bar == foobar")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue5089.go b/gcc/testsuite/go.test/test/fixedbugs/issue5089.go
new file mode 100644
index 00000000000..81b9f0521f9
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue5089.go
@@ -0,0 +1,15 @@
+// errorcheck
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// issue 5089: gc allows methods on non-locals if symbol already exists
+
+package p
+
+import "bufio" // GCCGO_ERROR "previous"
+
+func (b *bufio.Reader) Buffered() int { // ERROR "non-local|redefinition"
+ return -1
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue5105.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue5105.dir/a.go
new file mode 100644
index 00000000000..f20abb98bfa
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue5105.dir/a.go
@@ -0,0 +1,7 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+var A = [2]string{"hello", "world"}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue5105.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/issue5105.dir/b.go
new file mode 100644
index 00000000000..b12e739e33a
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue5105.dir/b.go
@@ -0,0 +1,15 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "./a"
+
+var B = [2]string{"world", "hello"}
+
+func main() {
+ if a.A[0] != B[1] {
+ panic("bad hello")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue5105.go b/gcc/testsuite/go.test/test/fixedbugs/issue5105.go
new file mode 100644
index 00000000000..e3e5e5caa46
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue5105.go
@@ -0,0 +1,10 @@
+// rundir
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 5105: linker segfaults on duplicate definition
+// of a type..hash.* function.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue5125.dir/bug.go b/gcc/testsuite/go.test/test/fixedbugs/issue5125.dir/bug.go
new file mode 100644
index 00000000000..2fdf0f9bb8b
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue5125.dir/bug.go
@@ -0,0 +1,17 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package bug
+
+type Node interface {
+ Eval(s *Scene)
+}
+
+type plug struct {
+ node Node
+}
+
+type Scene struct {
+ changed map[plug]bool
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue5125.dir/main.go b/gcc/testsuite/go.test/test/fixedbugs/issue5125.dir/main.go
new file mode 100644
index 00000000000..47acdeba8a9
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue5125.dir/main.go
@@ -0,0 +1,10 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import _ "./bug"
+
+func main() {
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue5125.go b/gcc/testsuite/go.test/test/fixedbugs/issue5125.go
new file mode 100644
index 00000000000..c049df3e2f7
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue5125.go
@@ -0,0 +1,10 @@
+// compiledir
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 5125: cyclic dependencies between types confuse
+// the hashability test during import.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue5162.go b/gcc/testsuite/go.test/test/fixedbugs/issue5162.go
new file mode 100644
index 00000000000..b14eae7863d
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue5162.go
@@ -0,0 +1,88 @@
+// runoutput
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// issue 5162: bad array equality when multiple comparisons
+// happen in the same expression.
+
+package main
+
+import (
+ "fmt"
+ "strings"
+)
+
+const template = `
+func CheckEqNNN_TTT() {
+ onesA := [NNN]ttt{ONES}
+ onesB := [NNN]ttt{ONES}
+ twos := [NNN]ttt{TWOS}
+ if onesA != onesB {
+ println("onesA != onesB in CheckEqNNN_TTT")
+ }
+ if onesA == twos {
+ println("onesA == twos in CheckEqNNN_TTT")
+ }
+ if onesB == twos {
+ println("onesB == twos in CheckEqNNN_TTT")
+ }
+ if s := fmt.Sprint(onesA == onesB, onesA != twos, onesB != twos); s != "true true true" {
+ println("fail in CheckEqNNN_TTT:", s)
+ }
+}
+
+func CheckEqNNN_TTTExtraVar() {
+ onesA := [NNN]ttt{ONES}
+ onesB := [NNN]ttt{ONES}
+ twos := [NNN]ttt{TWOS}
+ onesX := onesA
+ if onesA != onesB {
+ println("onesA != onesB in CheckEqNNN_TTTExtraVar")
+ }
+ if onesA == twos {
+ println("onesA == twos in CheckEqNNN_TTTExtraVar")
+ }
+ if onesB == twos {
+ println("onesB == twos in CheckEqNNN_TTTExtraVar")
+ }
+ if s := fmt.Sprint(onesA == onesB, onesA != twos, onesB != twos); s != "true true true" {
+ println("fail in CheckEqNNN_TTTExtraVar:", s)
+ }
+ if s := fmt.Sprint(onesB == onesX); s != "true" {
+ println("extra var fail in CheckEqNNN_TTTExtraVar")
+ }
+}
+`
+
+func main() {
+ fmt.Print("// run\n\n")
+ fmt.Print("// THIS FILE IS AUTO-GENERATED\n\n")
+ fmt.Print("package main\n\n")
+ fmt.Println(`import "fmt"`)
+
+ types := []string{
+ "int", "int8", "int16", "int32", "int64",
+ "uint", "uint8", "uint16", "uint32", "uint64",
+ "float32", "float64"}
+ tocall := make([]string, 0, 32*len(types))
+ for i := 1; i <= 32; i++ {
+ for _, typ := range types {
+ src := template
+ src = strings.Replace(src, "NNN", fmt.Sprint(i), -1)
+ src = strings.Replace(src, "TTT", strings.Title(typ), -1)
+ src = strings.Replace(src, "ttt", typ, -1)
+ src = strings.Replace(src, "ONES", "1"+strings.Repeat(", 1", i-1), -1)
+ src = strings.Replace(src, "TWOS", "2"+strings.Repeat(", 2", i-1), -1)
+ fmt.Print(src)
+ tocall = append(tocall, fmt.Sprintf("CheckEq%d_%s", i, strings.Title(typ)))
+ }
+ }
+ fmt.Println("func main() {")
+ for _, fun := range tocall {
+ fmt.Printf("\t%s()\n", fun)
+ fmt.Printf("\t%sExtraVar()\n", fun)
+ }
+ fmt.Println("}")
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue5231.go b/gcc/testsuite/go.test/test/fixedbugs/issue5231.go
new file mode 100644
index 00000000000..4039913dc90
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue5231.go
@@ -0,0 +1,45 @@
+// compile
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 5231: method values lose their variadic property.
+
+package p
+
+type T int
+
+func (t T) NotVariadic(s []int) int {
+ return int(t) + s[0]
+}
+
+func (t T) Variadic(s ...int) int {
+ return int(t) + s[0]
+}
+
+type I interface {
+ NotVariadic(s []int) int
+ Variadic(s ...int) int
+}
+
+func F() {
+ var t T
+ var p *T = &t
+ var i I = p
+
+ nv := t.NotVariadic
+ nv = p.NotVariadic
+ nv = i.NotVariadic
+ var s int = nv([]int{1, 2, 3})
+
+ v := t.Variadic
+ v = p.Variadic
+ v = i.Variadic
+ s = v(1, 2, 3)
+
+ var f1 func([]int) int = nv
+ var f2 func(...int) int = v
+
+ _, _, _ = f1, f2, s
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue5244.go b/gcc/testsuite/go.test/test/fixedbugs/issue5244.go
new file mode 100644
index 00000000000..e26c7b8c45e
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue5244.go
@@ -0,0 +1,18 @@
+// run
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 5244: the init order computation uses the wrong
+// order for top-level blank identifier assignments.
+// The example used to panic because it tries calling a
+// nil function instead of assigning to f before.
+
+package main
+
+var f = func() int { return 1 }
+var _ = f() + g()
+var g = func() int { return 2 }
+
+func main() {}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue5259.dir/bug.go b/gcc/testsuite/go.test/test/fixedbugs/issue5259.dir/bug.go
new file mode 100644
index 00000000000..8512461686b
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue5259.dir/bug.go
@@ -0,0 +1,17 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package bug
+
+type S struct {
+ F func()
+}
+
+type X interface {
+ Bar()
+}
+
+func Foo(x X) *S {
+ return &S{F: x.Bar}
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue5259.dir/main.go b/gcc/testsuite/go.test/test/fixedbugs/issue5259.dir/main.go
new file mode 100644
index 00000000000..ad1da78f5fc
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue5259.dir/main.go
@@ -0,0 +1,16 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "./bug"
+
+type foo int
+
+func (f *foo) Bar() {
+}
+
+func main() {
+ bug.Foo(new(foo))
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue5259.go b/gcc/testsuite/go.test/test/fixedbugs/issue5259.go
new file mode 100644
index 00000000000..00fe19ff947
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue5259.go
@@ -0,0 +1,9 @@
+// compiledir
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 5259: Inlining of method value causes internal compiler error
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue5260.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue5260.dir/a.go
new file mode 100644
index 00000000000..5a2c99f65c7
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue5260.dir/a.go
@@ -0,0 +1,7 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+const BOM = "\uFEFF"
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue5260.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/issue5260.dir/b.go
new file mode 100644
index 00000000000..299b75e4a7c
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue5260.dir/b.go
@@ -0,0 +1,11 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "./a"
+
+func main() {
+ _ = a.BOM
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue5260.go b/gcc/testsuite/go.test/test/fixedbugs/issue5260.go
new file mode 100644
index 00000000000..11fd5d04815
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue5260.go
@@ -0,0 +1,10 @@
+// rundir
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 5260: Unicode BOM in exported string constant
+// cannot be read back during package import.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue5291.dir/pkg1.go b/gcc/testsuite/go.test/test/fixedbugs/issue5291.dir/pkg1.go
new file mode 100644
index 00000000000..b1c893ac83e
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue5291.dir/pkg1.go
@@ -0,0 +1,34 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package pkg1
+
+import (
+ "runtime"
+)
+
+type T2 *[]string
+
+type Data struct {
+ T1 *[]T2
+}
+
+func CrashCall() (err error) {
+ var d Data
+
+ for count := 0; count < 10; count++ {
+ runtime.GC()
+
+ len := 2 // crash when >=2
+ x := make([]T2, len)
+
+ d = Data{T1: &x}
+
+ for j := 0; j < len; j++ {
+ y := make([]string, 1)
+ (*d.T1)[j] = &y
+ }
+ }
+ return nil
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue5291.dir/prog.go b/gcc/testsuite/go.test/test/fixedbugs/issue5291.dir/prog.go
new file mode 100644
index 00000000000..8301091bd88
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue5291.dir/prog.go
@@ -0,0 +1,17 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "./pkg1"
+)
+
+type message struct { // Presence of this creates a crash
+ data pkg1.Data
+}
+
+func main() {
+ pkg1.CrashCall()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue5291.go b/gcc/testsuite/go.test/test/fixedbugs/issue5291.go
new file mode 100644
index 00000000000..00d2ada4cc8
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue5291.go
@@ -0,0 +1,9 @@
+// rundir
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 5291: GC crash
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue5470.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue5470.dir/a.go
new file mode 100644
index 00000000000..302822d2387
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue5470.dir/a.go
@@ -0,0 +1,27 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+type Foo interface {
+ Hi() string
+}
+
+func Test1() Foo { return make(tst1) }
+
+type tst1 map[string]bool
+
+func (r tst1) Hi() string { return "Hi!" }
+
+func Test2() Foo { return make(tst2, 0) }
+
+type tst2 []string
+
+func (r tst2) Hi() string { return "Hi!" }
+
+func Test3() Foo { return make(tst3) }
+
+type tst3 chan string
+
+func (r tst3) Hi() string { return "Hi!" }
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue5470.dir/b.go b/gcc/testsuite/go.test/test/fixedbugs/issue5470.dir/b.go
new file mode 100644
index 00000000000..0801c149cfe
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue5470.dir/b.go
@@ -0,0 +1,13 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package b
+
+import "./a"
+
+func main() {
+ a.Test1()
+ a.Test2()
+ a.Test3()
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue5470.go b/gcc/testsuite/go.test/test/fixedbugs/issue5470.go
new file mode 100644
index 00000000000..6123c0983a8
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue5470.go
@@ -0,0 +1,10 @@
+// compiledir
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 5470: exported data for inlining may miss
+// the type argument of make.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue5493.go b/gcc/testsuite/go.test/test/fixedbugs/issue5493.go
new file mode 100644
index 00000000000..bbc62ffac0a
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue5493.go
@@ -0,0 +1,59 @@
+// run
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "runtime"
+ "sync"
+ "sync/atomic"
+ "time"
+)
+
+const N = 10
+var count int64
+
+func run() error {
+ f1 := func() {}
+ f2 := func() {
+ func() {
+ f1()
+ }()
+ }
+ runtime.SetFinalizer(&f1, func(f *func()) {
+ atomic.AddInt64(&count, -1)
+ })
+ go f2()
+ return nil
+}
+
+func main() {
+ // Does not work on 32-bits, or with gccgo, due to partially
+ // conservative GC.
+ // Try to enable when we have fully precise GC.
+ if runtime.GOARCH != "amd64" || runtime.Compiler == "gccgo" {
+ return
+ }
+ count = N
+ var wg sync.WaitGroup
+ wg.Add(N)
+ for i := 0; i < N; i++ {
+ go func() {
+ run()
+ wg.Done()
+ }()
+ }
+ wg.Wait()
+ for i := 0; i < 2*N; i++ {
+ time.Sleep(10 * time.Millisecond)
+ runtime.GC()
+ }
+ if count != 0 {
+ println(count, "out of", N, "finalizer are called")
+ panic("not all finalizers are called")
+ }
+}
+
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue5515.go b/gcc/testsuite/go.test/test/fixedbugs/issue5515.go
new file mode 100644
index 00000000000..053abf6f7cf
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue5515.go
@@ -0,0 +1,34 @@
+// run
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// issue 5515: miscompilation doing inlining in generated method wrapper
+
+package main
+
+type T uint32
+
+func main() {
+ b := make([]T, 8)
+ b[0] = 0xdeadbeef
+ rs := Slice(b)
+ sort(rs)
+}
+
+type Slice []T
+
+func (s Slice) Swap(i, j int) {
+ tmp := s[i]
+ s[i] = s[j]
+ s[j] = tmp
+}
+
+type Interface interface {
+ Swap(i, j int)
+}
+
+func sort(data Interface) {
+ data.Swap(0, 4)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue5607.go b/gcc/testsuite/go.test/test/fixedbugs/issue5607.go
new file mode 100644
index 00000000000..785be7a2c76
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue5607.go
@@ -0,0 +1,36 @@
+// run
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 5607: generation of init() function incorrectly
+// uses initializers of blank variables inside closures.
+
+package main
+
+var Test = func() {
+ var mymap = map[string]string{"a": "b"}
+
+ var innerTest = func() {
+ // Used to crash trying to compile this line as
+ // part of init() (funcdepth mismatch).
+ var _, x = mymap["a"]
+ println(x)
+ }
+ innerTest()
+}
+
+var Test2 = func() {
+ // The following initializer should not be part of init()
+ // The compiler used to generate a call to Panic() in init().
+ var _, x = Panic()
+ _ = x
+}
+
+func Panic() (int, int) {
+ panic("omg")
+ return 1, 2
+}
+
+func main() {}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue5614.dir/rethinkgo.go b/gcc/testsuite/go.test/test/fixedbugs/issue5614.dir/rethinkgo.go
new file mode 100644
index 00000000000..4ae66d679ea
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue5614.dir/rethinkgo.go
@@ -0,0 +1,16 @@
+package rethinkgo
+
+type Session struct {
+}
+
+func (s *Session) Run(query Exp) *int { return nil }
+
+type List []interface{}
+
+type Exp struct {
+ args []interface{}
+}
+
+func (e Exp) UseOutdated(useOutdated bool) Exp {
+ return Exp{args: List{e, useOutdated}}
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue5614.dir/x.go b/gcc/testsuite/go.test/test/fixedbugs/issue5614.dir/x.go
new file mode 100644
index 00000000000..7e4f3a7e6b9
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue5614.dir/x.go
@@ -0,0 +1,7 @@
+package x
+
+import "./rethinkgo"
+
+var S *rethinkgo.Session
+
+
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue5614.dir/y.go b/gcc/testsuite/go.test/test/fixedbugs/issue5614.dir/y.go
new file mode 100644
index 00000000000..97cc93a79d5
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue5614.dir/y.go
@@ -0,0 +1,5 @@
+package y
+
+import "./x"
+
+var T = x.S
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue5614.go b/gcc/testsuite/go.test/test/fixedbugs/issue5614.go
new file mode 100644
index 00000000000..f2518d2a0c1
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue5614.go
@@ -0,0 +1,11 @@
+// compiledir
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 5614: exported data for inlining may miss
+// named types when used in implicit conversion to
+// their underlying type.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue5753.go b/gcc/testsuite/go.test/test/fixedbugs/issue5753.go
new file mode 100644
index 00000000000..230a1e8c3bd
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue5753.go
@@ -0,0 +1,29 @@
+// run
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// issue 5753: bad typecheck info causes escape analysis to
+// not run on method thunks.
+
+package main
+
+type Thing struct{}
+
+func (t *Thing) broken(s string) []string {
+ foo := [1]string{s}
+ return foo[:]
+}
+
+func main() {
+ t := &Thing{}
+
+ f := t.broken
+ s := f("foo")
+ _ = f("bar")
+ if s[0] != "foo" {
+ panic(`s[0] != "foo"`)
+ }
+
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue5755.dir/a.go b/gcc/testsuite/go.test/test/fixedbugs/issue5755.dir/a.go
new file mode 100644
index 00000000000..aa398e82b25
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue5755.dir/a.go
@@ -0,0 +1,60 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+type I interface {
+ F()
+}
+
+type foo1 []byte
+type foo2 []rune
+type foo3 []uint8
+type foo4 []int32
+type foo5 string
+type foo6 string
+type foo7 string
+type foo8 string
+type foo9 string
+
+func (f foo1) F() { return }
+func (f foo2) F() { return }
+func (f foo3) F() { return }
+func (f foo4) F() { return }
+func (f foo5) F() { return }
+func (f foo6) F() { return }
+func (f foo7) F() { return }
+func (f foo8) F() { return }
+func (f foo9) F() { return }
+
+func Test1(s string) I { return foo1(s) }
+func Test2(s string) I { return foo2(s) }
+func Test3(s string) I { return foo3(s) }
+func Test4(s string) I { return foo4(s) }
+func Test5(s []byte) I { return foo5(s) }
+func Test6(s []rune) I { return foo6(s) }
+func Test7(s []uint8) I { return foo7(s) }
+func Test8(s []int32) I { return foo8(s) }
+func Test9(s int) I { return foo9(s) }
+
+type bar map[int]int
+
+func (b bar) F() { return }
+
+func TestBar() I { return bar{1: 2} }
+
+type baz int
+
+func IsBaz(x interface{}) bool { _, ok := x.(baz); return ok }
+
+type baz2 int
+
+func IsBaz2(x interface{}) bool {
+ switch x.(type) {
+ case baz2:
+ return true
+ default:
+ return false
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue5755.dir/main.go b/gcc/testsuite/go.test/test/fixedbugs/issue5755.dir/main.go
new file mode 100644
index 00000000000..6d515f26a63
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue5755.dir/main.go
@@ -0,0 +1,23 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "./a"
+
+func main() {
+ a.Test1("frumious")
+ a.Test2("frumious")
+ a.Test3("frumious")
+ a.Test4("frumious")
+
+ a.Test5(nil)
+ a.Test6(nil)
+ a.Test7(nil)
+ a.Test8(nil)
+ a.Test9(0)
+
+ a.TestBar()
+ a.IsBaz(nil)
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue5755.go b/gcc/testsuite/go.test/test/fixedbugs/issue5755.go
new file mode 100644
index 00000000000..fa7ea4d204c
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue5755.go
@@ -0,0 +1,10 @@
+// compiledir
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 5755: exported data for inlining may miss
+// named types when used in string conversions.
+
+package ignored
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue5809.go b/gcc/testsuite/go.test/test/fixedbugs/issue5809.go
new file mode 100644
index 00000000000..ca060b55de6
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue5809.go
@@ -0,0 +1,27 @@
+// run
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// issue 5809: 6g and 8g attempted to constant propagate indexed LEA
+
+package main
+
+import "fmt"
+
+func main() {
+ const d16 = "0123456789ABCDEF"
+ k := 0x1234
+ var x [4]byte
+
+ x[0] = d16[k>>12&0xf]
+ x[1] = d16[k>>8&0xf]
+ x[2] = d16[k>>4&0xf]
+ x[3] = d16[k&0xf]
+
+ if x != [4]byte{'1','2','3','4'} {
+ fmt.Println(x)
+ panic("x != [4]byte{'1','2','3','4'}")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue5820.go b/gcc/testsuite/go.test/test/fixedbugs/issue5820.go
new file mode 100644
index 00000000000..94de06d57db
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue5820.go
@@ -0,0 +1,18 @@
+// run
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// issue 5820: register clobber when clearfat and 64 bit arithmetic is interleaved.
+
+package main
+
+func main() {
+ array := make([][]int, 2)
+ index := uint64(1)
+ array[index] = nil
+ if array[1] != nil {
+ panic("array[1] != nil")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue5841.go b/gcc/testsuite/go.test/test/fixedbugs/issue5841.go
new file mode 100644
index 00000000000..cfc4a504c5a
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue5841.go
@@ -0,0 +1,16 @@
+// build
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 5841: 8g produces invalid CMPL $0, $0.
+// Similar to issue 5002, used to fail at link time.
+
+package main
+
+func main() {
+ var y int
+ if y%1 == 0 {
+ }
+}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue887.go b/gcc/testsuite/go.test/test/fixedbugs/issue887.go
new file mode 100644
index 00000000000..5bc193bf96f
--- /dev/null
+++ b/gcc/testsuite/go.test/test/fixedbugs/issue887.go
@@ -0,0 +1,36 @@
+// compile
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Used to leak registers on 8g.
+
+package p
+
+func f(x byte, y uint64) {
+ var r byte
+ switch y {
+ case 1:
+ r = x << y // '>>' triggers it too
+ case 2:
+ r = x << y
+ case 3:
+ r = x << y
+ case 4:
+ r = x << y
+ case 5:
+ r = x << y
+ case 6:
+ r = x << y
+ case 7:
+ r = x << y
+ case 8:
+ r = x << y
+ case 9:
+ r = x << y
+ case 10:
+ r = x << y
+ }
+ _ = r
+}
diff --git a/gcc/testsuite/go.test/test/float_lit.go b/gcc/testsuite/go.test/test/float_lit.go
index 2912c3749c2..4efae2362da 100644
--- a/gcc/testsuite/go.test/test/float_lit.go
+++ b/gcc/testsuite/go.test/test/float_lit.go
@@ -196,4 +196,8 @@ func main() {
if !close(-210.012e19, -210012, 1000, 19) {
print("-210.012e19 is ", -210.012e19, "\n")
}
+
+ if bad {
+ panic("float_lit")
+ }
}
diff --git a/gcc/testsuite/go.test/test/floatcmp.go b/gcc/testsuite/go.test/test/floatcmp.go
index f9f59a937f2..6c424ccd909 100644
--- a/gcc/testsuite/go.test/test/floatcmp.go
+++ b/gcc/testsuite/go.test/test/floatcmp.go
@@ -87,4 +87,7 @@ func main() {
println(t.name, "=", t.expr, "want", t.want)
}
}
+ if bad {
+ panic("floatcmp failed")
+ }
}
diff --git a/gcc/testsuite/go.test/test/func1.go b/gcc/testsuite/go.test/test/func1.go
index c89f7ff2eae..fb6f56184fa 100644
--- a/gcc/testsuite/go.test/test/func1.go
+++ b/gcc/testsuite/go.test/test/func1.go
@@ -14,6 +14,6 @@ func f1(a int) (int, float32) {
}
-func f2(a int) (a int, b float32) { // ERROR "redeclared|definition"
+func f2(a int) (a int, b float32) { // ERROR "duplicate argument a|definition"
return 8, 8.0
}
diff --git a/gcc/testsuite/go.test/test/func7.go b/gcc/testsuite/go.test/test/func7.go
index 6f6766f29f6..2d646b67860 100644
--- a/gcc/testsuite/go.test/test/func7.go
+++ b/gcc/testsuite/go.test/test/func7.go
@@ -17,7 +17,7 @@ func f() int {
func g() int {
if !calledf {
- println("BUG: func7 - called g before f")
+ panic("BUG: func7 - called g before f")
}
return 0
}
@@ -28,4 +28,3 @@ func main() {
panic("wrong answer")
}
}
-
diff --git a/gcc/testsuite/go.test/test/func8.go b/gcc/testsuite/go.test/test/func8.go
index 7defe265b58..13051802ecd 100644
--- a/gcc/testsuite/go.test/test/func8.go
+++ b/gcc/testsuite/go.test/test/func8.go
@@ -37,13 +37,13 @@ func y() string {
func main() {
if f() == g() {
- println("wrong f,g order")
+ panic("wrong f,g order")
}
if x() == (y() == "abc") {
panic("wrong compare")
}
if xy != "xy" {
- println("wrong x,y order")
+ panic("wrong x,y order")
}
}
diff --git a/gcc/testsuite/go.test/test/funcdup.go b/gcc/testsuite/go.test/test/funcdup.go
new file mode 100644
index 00000000000..d15d685792f
--- /dev/null
+++ b/gcc/testsuite/go.test/test/funcdup.go
@@ -0,0 +1,27 @@
+// errorcheck
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type T interface {
+ F1(i int) (i int) // ERROR "duplicate argument i|redefinition|previous"
+ F2(i, i int) // ERROR "duplicate argument i|redefinition|previous"
+ F3() (i, i int) // ERROR "duplicate argument i|redefinition|previous"
+}
+
+type T1 func(i, i int) // ERROR "duplicate argument i|redefinition|previous"
+type T2 func(i int) (i int) // ERROR "duplicate argument i|redefinition|previous"
+type T3 func() (i, i int) // ERROR "duplicate argument i|redefinition|previous"
+
+type R struct{}
+
+func (i *R) F1(i int) {} // ERROR "duplicate argument i|redefinition|previous"
+func (i *R) F2() (i int) {return 0} // ERROR "duplicate argument i|redefinition|previous"
+func (i *R) F3(j int) (j int) {return 0} // ERROR "duplicate argument j|redefinition|previous"
+
+func F1(i, i int) {} // ERROR "duplicate argument i|redefinition|previous"
+func F2(i int) (i int) {return 0} // ERROR "duplicate argument i|redefinition|previous"
+func F3() (i, i int) {return 0, 0} // ERROR "duplicate argument i|redefinition|previous"
diff --git a/gcc/testsuite/go.test/test/funcdup2.go b/gcc/testsuite/go.test/test/funcdup2.go
new file mode 100644
index 00000000000..1db1a396b2e
--- /dev/null
+++ b/gcc/testsuite/go.test/test/funcdup2.go
@@ -0,0 +1,17 @@
+// errorcheck
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+var T interface {
+ F1(i int) (i int) // ERROR "duplicate argument i|redefinition|previous"
+ F2(i, i int) // ERROR "duplicate argument i|redefinition|previous"
+ F3() (i, i int) // ERROR "duplicate argument i|redefinition|previous"
+}
+
+var T1 func(i, i int) // ERROR "duplicate argument i|redefinition|previous"
+var T2 func(i int) (i int) // ERROR "duplicate argument i|redefinition|previous"
+var T3 func() (i, i int) // ERROR "duplicate argument i|redefinition|previous"
diff --git a/gcc/testsuite/go.test/test/golden.out b/gcc/testsuite/go.test/test/golden.out
index 3e44e04c6aa..742a5d3f634 100644
--- a/gcc/testsuite/go.test/test/golden.out
+++ b/gcc/testsuite/go.test/test/golden.out
@@ -16,13 +16,9 @@
== fixedbugs/
=========== fixedbugs/bug429.go
-throw: all goroutines are asleep - deadlock!
+fatal error: all goroutines are asleep - deadlock!
== bugs/
=========== bugs/bug395.go
bug395 is broken
-
-=========== bugs/bug434.go
-bugs/bug434.dir/two.go:10: one.t.int undefined (cannot refer to unexported field or method one.int)
-BUG:bug434
diff --git a/gcc/testsuite/go.test/test/goprint.go b/gcc/testsuite/go.test/test/goprint.go
index 2f0d3c3904d..cdaccf4f796 100644
--- a/gcc/testsuite/go.test/test/goprint.go
+++ b/gcc/testsuite/go.test/test/goprint.go
@@ -12,5 +12,5 @@ import "time"
func main() {
go println(42, true, false, true, 1.5, "world", (chan int)(nil), []int(nil), (map[string]int)(nil), (func())(nil), byte(255))
- time.Sleep(1e6)
+ time.Sleep(100*time.Millisecond)
}
diff --git a/gcc/testsuite/go.test/test/import2.dir/import2.go b/gcc/testsuite/go.test/test/import2.dir/import2.go
new file mode 100644
index 00000000000..8bb1eb91913
--- /dev/null
+++ b/gcc/testsuite/go.test/test/import2.dir/import2.go
@@ -0,0 +1,42 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Various declarations of exported variables and functions.
+
+package p
+
+var C1 chan <- chan int = (chan<- (chan int))(nil)
+var C2 chan (<- chan int) = (chan (<-chan int))(nil)
+var C3 <- chan chan int = (<-chan (chan int))(nil)
+var C4 chan chan <- int = (chan (chan<- int))(nil)
+
+var C5 <- chan <- chan int = (<-chan (<-chan int))(nil)
+var C6 chan <- <- chan int = (chan<- (<-chan int))(nil)
+var C7 chan <- chan <- int = (chan<- (chan<- int))(nil)
+
+var C8 <- chan <- chan chan int = (<-chan (<-chan (chan int)))(nil)
+var C9 <- chan chan <- chan int = (<-chan (chan<- (chan int)))(nil)
+var C10 chan <- <- chan chan int = (chan<- (<-chan (chan int)))(nil)
+var C11 chan <- chan <- chan int = (chan<- (chan<- (chan int)))(nil)
+var C12 chan chan <- <- chan int = (chan (chan<- (<-chan int)))(nil)
+var C13 chan chan <- chan <- int = (chan (chan<- (chan<- int)))(nil)
+
+var R1 chan<- (chan int) = (chan <- chan int)(nil)
+var R3 <-chan (chan int) = (<- chan chan int)(nil)
+var R4 chan (chan<- int) = (chan chan <- int)(nil)
+
+var R5 <-chan (<-chan int) = (<- chan <- chan int)(nil)
+var R6 chan<- (<-chan int) = (chan <- <- chan int)(nil)
+var R7 chan<- (chan<- int) = (chan <- chan <- int)(nil)
+
+var R8 <-chan (<-chan (chan int)) = (<- chan <- chan chan int)(nil)
+var R9 <-chan (chan<- (chan int)) = (<- chan chan <- chan int)(nil)
+var R10 chan<- (<-chan (chan int)) = (chan <- <- chan chan int)(nil)
+var R11 chan<- (chan<- (chan int)) = (chan <- chan <- chan int)(nil)
+var R12 chan (chan<- (<-chan int)) = (chan chan <- <- chan int)(nil)
+var R13 chan (chan<- (chan<- int)) = (chan chan <- chan <- int)(nil)
+
+var F1 func() func() int
+func F2() func() func() int
+func F3(func() func() int)
diff --git a/gcc/testsuite/go.test/test/import2.dir/import3.go b/gcc/testsuite/go.test/test/import2.dir/import3.go
new file mode 100644
index 00000000000..d7fe37b1996
--- /dev/null
+++ b/gcc/testsuite/go.test/test/import2.dir/import3.go
@@ -0,0 +1,52 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test that all the types from import2.go made it
+// intact and with the same meaning, by assigning to or using them.
+
+package main
+
+import "./import2"
+
+func f3(func() func() int)
+
+func main() {
+ p.F3(p.F1)
+ p.F3(p.F2())
+ f3(p.F1)
+ f3(p.F2())
+
+ p.C1 = (chan<- (chan int))(nil)
+ p.C2 = (chan (<-chan int))(nil)
+ p.C3 = (<-chan (chan int))(nil)
+ p.C4 = (chan (chan<- int))(nil)
+
+ p.C5 = (<-chan (<-chan int))(nil)
+ p.C6 = (chan<- (<-chan int))(nil)
+ p.C7 = (chan<- (chan<- int))(nil)
+
+ p.C8 = (<-chan (<-chan (chan int)))(nil)
+ p.C9 = (<-chan (chan<- (chan int)))(nil)
+ p.C10 = (chan<- (<-chan (chan int)))(nil)
+ p.C11 = (chan<- (chan<- (chan int)))(nil)
+ p.C12 = (chan (chan<- (<-chan int)))(nil)
+ p.C13 = (chan (chan<- (chan<- int)))(nil)
+
+ p.R1 = (chan <- chan int)(nil)
+ p.R3 = (<- chan chan int)(nil)
+ p.R4 = (chan chan <- int)(nil)
+
+ p.R5 = (<- chan <- chan int)(nil)
+ p.R6 = (chan <- <- chan int)(nil)
+ p.R7 = (chan <- chan <- int)(nil)
+
+ p.R8 = (<- chan <- chan chan int)(nil)
+ p.R9 = (<- chan chan <- chan int)(nil)
+ p.R10 = (chan <- <- chan chan int)(nil)
+ p.R11 = (chan <- chan <- chan int)(nil)
+ p.R12 = (chan chan <- <- chan int)(nil)
+ p.R13 = (chan chan <- chan <- int)(nil)
+
+}
+
diff --git a/gcc/testsuite/go.test/test/import2.go b/gcc/testsuite/go.test/test/import2.go
index 5c275f34b36..f8d0b0a0fd9 100644
--- a/gcc/testsuite/go.test/test/import2.go
+++ b/gcc/testsuite/go.test/test/import2.go
@@ -1,45 +1,8 @@
-// skip # used by import3
+// compiledir
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Various declarations of exported variables and functions.
-// Imported by import3.go.
-
-package p
-
-var C1 chan <- chan int = (chan<- (chan int))(nil)
-var C2 chan (<- chan int) = (chan (<-chan int))(nil)
-var C3 <- chan chan int = (<-chan (chan int))(nil)
-var C4 chan chan <- int = (chan (chan<- int))(nil)
-
-var C5 <- chan <- chan int = (<-chan (<-chan int))(nil)
-var C6 chan <- <- chan int = (chan<- (<-chan int))(nil)
-var C7 chan <- chan <- int = (chan<- (chan<- int))(nil)
-
-var C8 <- chan <- chan chan int = (<-chan (<-chan (chan int)))(nil)
-var C9 <- chan chan <- chan int = (<-chan (chan<- (chan int)))(nil)
-var C10 chan <- <- chan chan int = (chan<- (<-chan (chan int)))(nil)
-var C11 chan <- chan <- chan int = (chan<- (chan<- (chan int)))(nil)
-var C12 chan chan <- <- chan int = (chan (chan<- (<-chan int)))(nil)
-var C13 chan chan <- chan <- int = (chan (chan<- (chan<- int)))(nil)
-
-var R1 chan<- (chan int) = (chan <- chan int)(nil)
-var R3 <-chan (chan int) = (<- chan chan int)(nil)
-var R4 chan (chan<- int) = (chan chan <- int)(nil)
-
-var R5 <-chan (<-chan int) = (<- chan <- chan int)(nil)
-var R6 chan<- (<-chan int) = (chan <- <- chan int)(nil)
-var R7 chan<- (chan<- int) = (chan <- chan <- int)(nil)
-
-var R8 <-chan (<-chan (chan int)) = (<- chan <- chan chan int)(nil)
-var R9 <-chan (chan<- (chan int)) = (<- chan chan <- chan int)(nil)
-var R10 chan<- (<-chan (chan int)) = (chan <- <- chan chan int)(nil)
-var R11 chan<- (chan<- (chan int)) = (chan <- chan <- chan int)(nil)
-var R12 chan (chan<- (<-chan int)) = (chan chan <- <- chan int)(nil)
-var R13 chan (chan<- (chan<- int)) = (chan chan <- chan <- int)(nil)
-
-var F1 func() func() int
-func F2() func() func() int
-func F3(func() func() int)
+// Tests that export data does not corrupt type syntax.
+package ignored
diff --git a/gcc/testsuite/go.test/test/import3.go b/gcc/testsuite/go.test/test/import3.go
deleted file mode 100644
index 0a5ba1d01ac..00000000000
--- a/gcc/testsuite/go.test/test/import3.go
+++ /dev/null
@@ -1,57 +0,0 @@
-// $G $D/import2.go && $G $D/$F.go
-
-// NOTE: This test is not run by 'run.go' and so not run by all.bash.
-// To run this test you must use the ./run shell script.
-
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Test that all the types from import2.go made it
-// intact and with the same meaning, by assigning to or using them.
-
-package main
-
-import "./import2"
-
-func f3(func() func() int)
-
-func main() {
- p.F3(p.F1)
- p.F3(p.F2())
- f3(p.F1)
- f3(p.F2())
-
- p.C1 = (chan<- (chan int))(nil)
- p.C2 = (chan (<-chan int))(nil)
- p.C3 = (<-chan (chan int))(nil)
- p.C4 = (chan (chan<- int))(nil)
-
- p.C5 = (<-chan (<-chan int))(nil)
- p.C6 = (chan<- (<-chan int))(nil)
- p.C7 = (chan<- (chan<- int))(nil)
-
- p.C8 = (<-chan (<-chan (chan int)))(nil)
- p.C9 = (<-chan (chan<- (chan int)))(nil)
- p.C10 = (chan<- (<-chan (chan int)))(nil)
- p.C11 = (chan<- (chan<- (chan int)))(nil)
- p.C12 = (chan (chan<- (<-chan int)))(nil)
- p.C13 = (chan (chan<- (chan<- int)))(nil)
-
- p.R1 = (chan <- chan int)(nil)
- p.R3 = (<- chan chan int)(nil)
- p.R4 = (chan chan <- int)(nil)
-
- p.R5 = (<- chan <- chan int)(nil)
- p.R6 = (chan <- <- chan int)(nil)
- p.R7 = (chan <- chan <- int)(nil)
-
- p.R8 = (<- chan <- chan chan int)(nil)
- p.R9 = (<- chan chan <- chan int)(nil)
- p.R10 = (chan <- <- chan chan int)(nil)
- p.R11 = (chan <- chan <- chan int)(nil)
- p.R12 = (chan chan <- <- chan int)(nil)
- p.R13 = (chan chan <- chan <- int)(nil)
-
-}
-
diff --git a/gcc/testsuite/go.test/test/import4.dir/empty.go b/gcc/testsuite/go.test/test/import4.dir/empty.go
new file mode 100644
index 00000000000..1dffa170dfc
--- /dev/null
+++ b/gcc/testsuite/go.test/test/import4.dir/empty.go
@@ -0,0 +1,10 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package empty
+
+import ( )
+const ( )
+var ( )
+type ( )
diff --git a/gcc/testsuite/go.test/test/import4.dir/import4.go b/gcc/testsuite/go.test/test/import4.dir/import4.go
new file mode 100644
index 00000000000..f92c663d04b
--- /dev/null
+++ b/gcc/testsuite/go.test/test/import4.dir/import4.go
@@ -0,0 +1,24 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Verify that various kinds of "imported and not used"
+// errors are caught by the compiler.
+// Does not compile.
+
+package main
+
+// standard
+import "fmt" // ERROR "imported and not used.*fmt"
+
+// renamed
+import X "math" // ERROR "imported and not used.*math"
+
+// import dot
+import . "bufio" // ERROR "imported and not used.*bufio"
+
+// again, package without anything in it
+import "./empty" // GC_ERROR "imported and not used.*empty"
+import Z "./empty" // GC_ERROR "imported and not used.*empty"
+import . "./empty" // ERROR "imported and not used.*empty"
+
diff --git a/gcc/testsuite/go.test/test/import4.go b/gcc/testsuite/go.test/test/import4.go
index f35f5678184..875bf894302 100644
--- a/gcc/testsuite/go.test/test/import4.go
+++ b/gcc/testsuite/go.test/test/import4.go
@@ -1,7 +1,4 @@
-// $G $D/empty.go && errchk $G $D/$F.go
-
-// NOTE: This test is not run by 'run.go' and so not run by all.bash.
-// To run this test you must use the ./run shell script.
+// errorcheckdir
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
@@ -11,19 +8,4 @@
// errors are caught by the compiler.
// Does not compile.
-package main
-
-// standard
-import "fmt" // ERROR "imported and not used.*fmt"
-
-// renamed
-import X "math" // ERROR "imported and not used.*math"
-
-// import dot
-import . "bufio" // ERROR "imported and not used.*bufio"
-
-// again, package without anything in it
-import "./empty" // ERROR "imported and not used.*empty"
-import Z "./empty" // ERROR "imported and not used.*empty"
-import . "./empty" // ERROR "imported and not used.*empty"
-
+package ignored
diff --git a/gcc/testsuite/go.test/test/index.go b/gcc/testsuite/go.test/test/index.go
index daab45f7a17..a8c471bb3bf 100644
--- a/gcc/testsuite/go.test/test/index.go
+++ b/gcc/testsuite/go.test/test/index.go
@@ -36,6 +36,8 @@ const (
ci64big int64 = 1<<31
ci64bigger int64 = 1<<32
chuge = 1<<100
+ cfgood = 2.0
+ cfbad = 2.1
cnj = -2
cni int = -3
@@ -46,6 +48,8 @@ const (
cni64big int64 = -1<<31
cni64bigger int64 = -1<<32
cnhuge = -1<<100
+ cnfgood = -2.0
+ cnfbad = -2.1
)
var j int = 100020
@@ -57,6 +61,8 @@ var i64 int64 = 100023
var i64big int64 = 1<<31
var i64bigger int64 = 1<<32
var huge uint64 = 1<<64 - 1
+var fgood float64 = 2.0
+var fbad float64 = 2.1
var nj int = -10
var ni int = -11
@@ -67,6 +73,8 @@ var ni64 int64 = -13
var ni64big int64 = -1<<31
var ni64bigger int64 = -1<<32
var nhuge int64 = -1<<63
+var nfgood float64 = -2.0
+var nfbad float64 = -2.1
var si []int = make([]int, 10)
var ai [10]int
@@ -156,7 +164,7 @@ func testExpr(b *bufio.Writer, expr string) {
if pass == 0 {
fmt.Fprintf(b, "\ttest(func(){use(%s)}, %q)\n", expr, expr)
} else {
- fmt.Fprintf(b, "\tuse(%s) // ERROR \"index|overflow\"\n", expr)
+ fmt.Fprintf(b, "\tuse(%s) // ERROR \"index|overflow|truncated|must be integer\"\n", expr)
}
}
@@ -169,15 +177,15 @@ func main() {
fmt.Fprint(b, "// errorcheck\n\n")
}
fmt.Fprint(b, prolog)
-
+
var choices = [][]string{
// Direct value, fetch from struct, fetch from struct pointer.
// The last two cases get us to oindex_const_sudo in gsubr.c.
[]string{"", "t.", "pt."},
-
+
// Array, pointer to array, slice.
[]string{"a", "pa", "s"},
-
+
// Element is int, element is quad (struct).
// This controls whether we end up in gsubr.c (i) or cgen.c (q).
[]string{"i", "q"},
@@ -192,9 +200,9 @@ func main() {
[]string{"", "n"},
// Size of index.
- []string{"j", "i", "i8", "i16", "i32", "i64", "i64big", "i64bigger", "huge"},
+ []string{"j", "i", "i8", "i16", "i32", "i64", "i64big", "i64bigger", "huge", "fgood", "fbad"},
}
-
+
forall(choices, func(x []string) {
p, a, e, big, c, n, i := x[0], x[1], x[2], x[3], x[4], x[5], x[6]
@@ -206,7 +214,7 @@ func main() {
// negative constant
// large constant
thisPass := 0
- if c == "c" && (a == "a" || a == "pa" || n == "n" || i == "i64big" || i == "i64bigger" || i == "huge") {
+ if c == "c" && (a == "a" || a == "pa" || n == "n" || i == "i64big" || i == "i64bigger" || i == "huge" || i == "fbad") {
if i == "huge" {
// Due to a detail of 6g's internals,
// the huge constant errors happen in an
@@ -223,27 +231,50 @@ func main() {
thisPass = 2
}
}
-
+
+ pae := p + a + e + big
+ cni := c + n + i
+
// If we're using the big-len data, positive int8 and int16 cannot overflow.
if big == "b" && n == "" && (i == "i8" || i == "i16") {
+ if pass == 0 {
+ fmt.Fprintf(b, "\tuse(%s[%s])\n", pae, cni)
+ fmt.Fprintf(b, "\tuse(%s[0:%s])\n", pae, cni)
+ fmt.Fprintf(b, "\tuse(%s[1:%s])\n", pae, cni)
+ fmt.Fprintf(b, "\tuse(%s[%s:])\n", pae, cni)
+ fmt.Fprintf(b, "\tuse(%s[%s:%s])\n", pae, cni, cni)
+ }
+ return
+ }
+
+ // Float variables cannot be used as indices.
+ if c == "" && (i == "fgood" || i == "fbad") {
+ return
+ }
+ // Integral float constat is ok.
+ if c == "c" && n == "" && i == "fgood" {
+ if pass == 0 {
+ fmt.Fprintf(b, "\tuse(%s[%s])\n", pae, cni)
+ fmt.Fprintf(b, "\tuse(%s[0:%s])\n", pae, cni)
+ fmt.Fprintf(b, "\tuse(%s[1:%s])\n", pae, cni)
+ fmt.Fprintf(b, "\tuse(%s[%s:])\n", pae, cni)
+ fmt.Fprintf(b, "\tuse(%s[%s:%s])\n", pae, cni, cni)
+ }
return
}
// Only print the test case if it is appropriate for this pass.
if thisPass == pass {
- pae := p+a+e+big
- cni := c+n+i
-
// Index operation
- testExpr(b, pae + "[" + cni + "]")
-
+ testExpr(b, pae+"["+cni+"]")
+
// Slice operation.
// Low index 0 is a special case in ggen.c
// so test both 0 and 1.
- testExpr(b, pae + "[0:" + cni + "]")
- testExpr(b, pae + "[1:" + cni + "]")
- testExpr(b, pae + "[" + cni + ":]")
- testExpr(b, pae + "[" + cni + ":" + cni + "]")
+ testExpr(b, pae+"[0:"+cni+"]")
+ testExpr(b, pae+"[1:"+cni+"]")
+ testExpr(b, pae+"["+cni+":]")
+ testExpr(b, pae+"["+cni+":"+cni+"]")
}
})
@@ -253,7 +284,7 @@ func main() {
func forall(choices [][]string, f func([]string)) {
x := make([]string, len(choices))
-
+
var recurse func(d int)
recurse = func(d int) {
if d >= len(choices) {
@@ -261,7 +292,7 @@ func forall(choices [][]string, f func([]string)) {
return
}
for _, x[d] = range choices[d] {
- recurse(d+1)
+ recurse(d + 1)
}
}
recurse(0)
diff --git a/gcc/testsuite/go.test/test/init1.go b/gcc/testsuite/go.test/test/init1.go
index a888ad7440c..f6eda6edfea 100644
--- a/gcc/testsuite/go.test/test/init1.go
+++ b/gcc/testsuite/go.test/test/init1.go
@@ -33,6 +33,7 @@ func init() {
sys1 := memstats.Sys
if sys1-sys > chunk*50 {
println("allocated 1000 chunks of", chunk, "and used ", sys1-sys, "memory")
+ panic("init1")
}
}
diff --git a/gcc/testsuite/go.test/test/initializerr.go b/gcc/testsuite/go.test/test/initializerr.go
index 48908c34786..ca05414554d 100644
--- a/gcc/testsuite/go.test/test/initializerr.go
+++ b/gcc/testsuite/go.test/test/initializerr.go
@@ -26,3 +26,15 @@ var a5 = []byte { x: 2 } // ERROR "index"
var ok1 = S { } // should be ok
var ok2 = T { S: ok1 } // should be ok
+
+// These keys can be computed at compile time but they are
+// not constants as defined by the spec, so they do not trigger
+// compile-time errors about duplicate key values.
+// See issue 4555.
+
+type Key struct {X, Y int}
+
+var _ = map[Key]string{
+ Key{1,2}: "hello",
+ Key{1,2}: "world",
+}
diff --git a/gcc/testsuite/go.test/test/interface/embed0.go b/gcc/testsuite/go.test/test/interface/embed0.go
deleted file mode 100644
index e2ee20adeba..00000000000
--- a/gcc/testsuite/go.test/test/interface/embed0.go
+++ /dev/null
@@ -1,29 +0,0 @@
-// skip # used by embed1.go
-
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Test that embedded interface types can have local methods.
-
-package p
-
-type T int
-func (t T) m() {}
-
-type I interface { m() }
-type J interface { I }
-
-func main() {
- var i I
- var j J
- var t T
- i = t
- j = t
- _ = i
- _ = j
- i = j
- _ = i
- j = i
- _ = j
-}
diff --git a/gcc/testsuite/go.test/test/interface/embed1.dir/embed0.go b/gcc/testsuite/go.test/test/interface/embed1.dir/embed0.go
new file mode 100644
index 00000000000..728bec74e87
--- /dev/null
+++ b/gcc/testsuite/go.test/test/interface/embed1.dir/embed0.go
@@ -0,0 +1,27 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test that embedded interface types can have local methods.
+
+package p
+
+type T int
+func (t T) m() {}
+
+type I interface { m() }
+type J interface { I }
+
+func main() {
+ var i I
+ var j J
+ var t T
+ i = t
+ j = t
+ _ = i
+ _ = j
+ i = j
+ _ = i
+ j = i
+ _ = j
+}
diff --git a/gcc/testsuite/go.test/test/interface/embed1.dir/embed1.go b/gcc/testsuite/go.test/test/interface/embed1.dir/embed1.go
new file mode 100644
index 00000000000..7dfb1dbc0ad
--- /dev/null
+++ b/gcc/testsuite/go.test/test/interface/embed1.dir/embed1.go
@@ -0,0 +1,43 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test that embedded interface types can have local methods.
+
+package main
+
+import "./embed0"
+
+type T int
+func (t T) m() {}
+
+type I interface { m() }
+type J interface { I }
+
+type PI interface { p.I }
+type PJ interface { p.J }
+
+func main() {
+ var i I
+ var j J
+ var t T
+ i = t
+ j = t
+ _ = i
+ _ = j
+ i = j
+ _ = i
+ j = i
+ _ = j
+ var pi PI
+ var pj PJ
+ var pt p.T
+ pi = pt
+ pj = pt
+ _ = pi
+ _ = pj
+ pi = pj
+ _ = pi
+ pj = pi
+ _ = pj
+}
diff --git a/gcc/testsuite/go.test/test/interface/embed1.go b/gcc/testsuite/go.test/test/interface/embed1.go
index 07b873a633b..784b82bb072 100644
--- a/gcc/testsuite/go.test/test/interface/embed1.go
+++ b/gcc/testsuite/go.test/test/interface/embed1.go
@@ -1,7 +1,4 @@
-// $G $D/embed0.go && $G $D/$F.go && $L $F.$A && ./$A.out
-
-// NOTE: This test is not run by 'run.go' and so not run by all.bash.
-// To run this test you must use the ./run shell script.
+// rundir
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
@@ -9,40 +6,4 @@
// Test that embedded interface types can have local methods.
-package main
-
-import "./embed0"
-
-type T int
-func (t T) m() {}
-
-type I interface { m() }
-type J interface { I }
-
-type PI interface { p.I }
-type PJ interface { p.J }
-
-func main() {
- var i I
- var j J
- var t T
- i = t
- j = t
- _ = i
- _ = j
- i = j
- _ = i
- j = i
- _ = j
- var pi PI
- var pj PJ
- var pt p.T
- pi = pt
- pj = pt
- _ = pi
- _ = pj
- pi = pj
- _ = pi
- pj = pi
- _ = pj
-}
+package ignored
diff --git a/gcc/testsuite/go.test/test/interface/private.dir/private1.go b/gcc/testsuite/go.test/test/interface/private.dir/private1.go
new file mode 100644
index 00000000000..75eee51f5a0
--- /dev/null
+++ b/gcc/testsuite/go.test/test/interface/private.dir/private1.go
@@ -0,0 +1,18 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Imported by private.go, which should not be able to see the private method.
+
+package p
+
+type Exported interface {
+ private()
+}
+
+type Implementation struct{}
+
+func (p *Implementation) private() {}
+
+var X = new(Implementation)
+
diff --git a/gcc/testsuite/go.test/test/interface/private.dir/prog.go b/gcc/testsuite/go.test/test/interface/private.dir/prog.go
new file mode 100644
index 00000000000..abea7d625c7
--- /dev/null
+++ b/gcc/testsuite/go.test/test/interface/private.dir/prog.go
@@ -0,0 +1,33 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test that unexported methods are not visible outside the package.
+// Does not compile.
+
+package main
+
+import "./private1"
+
+type Exported interface {
+ private()
+}
+
+type Implementation struct{}
+
+func (p *Implementation) private() {}
+
+func main() {
+ var x Exported
+ x = new(Implementation)
+ x.private()
+
+ var px p.Exported
+ px = p.X
+
+ px.private() // ERROR "private"
+
+ px = new(Implementation) // ERROR "private"
+
+ x = px // ERROR "private"
+}
diff --git a/gcc/testsuite/go.test/test/interface/private.go b/gcc/testsuite/go.test/test/interface/private.go
index 0a42385ea7b..a0da249c92c 100644
--- a/gcc/testsuite/go.test/test/interface/private.go
+++ b/gcc/testsuite/go.test/test/interface/private.go
@@ -1,7 +1,4 @@
-// $G $D/${F}1.go && errchk $G $D/$F.go
-
-// NOTE: This test is not run by 'run.go' and so not run by all.bash.
-// To run this test you must use the ./run shell script.
+// errorcheckdir
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
@@ -10,29 +7,4 @@
// Test that unexported methods are not visible outside the package.
// Does not compile.
-package main
-
-import "./private1"
-
-type Exported interface {
- private()
-}
-
-type Implementation struct{}
-
-func (p *Implementation) private() {}
-
-func main() {
- var x Exported
- x = new(Implementation)
- x.private()
-
- var px p.Exported
- px = p.X
-
- px.private() // ERROR "private"
-
- px = new(Implementation) // ERROR "private"
-
- x = px // ERROR "private"
-}
+package ignored
diff --git a/gcc/testsuite/go.test/test/interface/private1.go b/gcc/testsuite/go.test/test/interface/private1.go
deleted file mode 100644
index 3281c38be60..00000000000
--- a/gcc/testsuite/go.test/test/interface/private1.go
+++ /dev/null
@@ -1,20 +0,0 @@
-// skip # used by private.go
-
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Imported by private.go, which should not be able to see the private method.
-
-package p
-
-type Exported interface {
- private()
-}
-
-type Implementation struct{}
-
-func (p *Implementation) private() {}
-
-var X = new(Implementation)
-
diff --git a/gcc/testsuite/go.test/test/interface/recursive1.dir/recursive1.go b/gcc/testsuite/go.test/test/interface/recursive1.dir/recursive1.go
new file mode 100644
index 00000000000..441f0ecaa5a
--- /dev/null
+++ b/gcc/testsuite/go.test/test/interface/recursive1.dir/recursive1.go
@@ -0,0 +1,15 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Mutually recursive type definitions imported and used by recursive1.go.
+
+package p
+
+type I1 interface {
+ F() I2
+}
+
+type I2 interface {
+ I1
+}
diff --git a/gcc/testsuite/go.test/test/interface/recursive1.dir/recursive2.go b/gcc/testsuite/go.test/test/interface/recursive1.dir/recursive2.go
new file mode 100644
index 00000000000..e8048c672b2
--- /dev/null
+++ b/gcc/testsuite/go.test/test/interface/recursive1.dir/recursive2.go
@@ -0,0 +1,20 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test that the mutually recursive types in recursive1.go made it
+// intact and with the same meaning, by assigning to or using them.
+
+package main
+
+import "./recursive1"
+
+func main() {
+ var i1 p.I1
+ var i2 p.I2
+ i1 = i2
+ i2 = i1
+ i1 = i2.F()
+ i2 = i1.F()
+ _, _ = i1, i2
+}
diff --git a/gcc/testsuite/go.test/test/interface/recursive1.go b/gcc/testsuite/go.test/test/interface/recursive1.go
index cc3cdc37f1a..62f61088441 100644
--- a/gcc/testsuite/go.test/test/interface/recursive1.go
+++ b/gcc/testsuite/go.test/test/interface/recursive1.go
@@ -1,4 +1,4 @@
-// skip # used by recursive2
+// compiledir
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
@@ -6,12 +6,4 @@
// Mutually recursive type definitions imported and used by recursive1.go.
-package p
-
-type I1 interface {
- F() I2
-}
-
-type I2 interface {
- I1
-}
+package ignored
diff --git a/gcc/testsuite/go.test/test/interface/recursive2.go b/gcc/testsuite/go.test/test/interface/recursive2.go
deleted file mode 100644
index 3a1059960cf..00000000000
--- a/gcc/testsuite/go.test/test/interface/recursive2.go
+++ /dev/null
@@ -1,25 +0,0 @@
-// $G $D/recursive1.go && $G $D/$F.go
-
-// NOTE: This test is not run by 'run.go' and so not run by all.bash.
-// To run this test you must use the ./run shell script.
-
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Test that the mutually recursive types in recursive1.go made it
-// intact and with the same meaning, by assigning to or using them.
-
-package main
-
-import "./recursive1"
-
-func main() {
- var i1 p.I1
- var i2 p.I2
- i1 = i2
- i2 = i1
- i1 = i2.F()
- i2 = i1.F()
- _, _ = i1, i2
-}
diff --git a/gcc/testsuite/go.test/test/literal.go b/gcc/testsuite/go.test/test/literal.go
index ba185fc9ace..c3d6bc123a6 100644
--- a/gcc/testsuite/go.test/test/literal.go
+++ b/gcc/testsuite/go.test/test/literal.go
@@ -24,7 +24,6 @@ func equal(a, b float32) bool {
return a == b
}
-
func main() {
// bool
var t bool = true
@@ -225,6 +224,6 @@ func main() {
assert(sj0 == sj3, "sj3")
if nbad > 0 {
- println()
+ panic("literal failed")
}
}
diff --git a/gcc/testsuite/go.test/test/map.go b/gcc/testsuite/go.test/test/map.go
index 6dec0dfd719..485e743fe46 100644
--- a/gcc/testsuite/go.test/test/map.go
+++ b/gcc/testsuite/go.test/test/map.go
@@ -5,6 +5,7 @@
// license that can be found in the LICENSE file.
// Test maps, almost exhaustively.
+// NaN complexity test is in mapnan.go.
package main
@@ -12,7 +13,6 @@ import (
"fmt"
"math"
"strconv"
- "time"
)
const count = 100
@@ -41,7 +41,7 @@ func testbasic() {
for i := 0; i < len(mlit); i++ {
s := string([]byte{byte(i) + '0'})
if mlit[s] != i {
- fmt.Printf("mlit[%s] = %d\n", s, mlit[s])
+ panic(fmt.Sprintf("mlit[%s] = %d\n", s, mlit[s]))
}
}
@@ -102,46 +102,46 @@ func testbasic() {
// test len
if len(mib) != count {
- fmt.Printf("len(mib) = %d\n", len(mib))
+ panic(fmt.Sprintf("len(mib) = %d\n", len(mib)))
}
if len(mii) != count {
- fmt.Printf("len(mii) = %d\n", len(mii))
+ panic(fmt.Sprintf("len(mii) = %d\n", len(mii)))
}
if len(mfi) != count {
- fmt.Printf("len(mfi) = %d\n", len(mfi))
+ panic(fmt.Sprintf("len(mfi) = %d\n", len(mfi)))
}
if len(mif) != count {
- fmt.Printf("len(mif) = %d\n", len(mif))
+ panic(fmt.Sprintf("len(mif) = %d\n", len(mif)))
}
if len(msi) != count {
- fmt.Printf("len(msi) = %d\n", len(msi))
+ panic(fmt.Sprintf("len(msi) = %d\n", len(msi)))
}
if len(mis) != count {
- fmt.Printf("len(mis) = %d\n", len(mis))
+ panic(fmt.Sprintf("len(mis) = %d\n", len(mis)))
}
if len(mss) != count {
- fmt.Printf("len(mss) = %d\n", len(mss))
+ panic(fmt.Sprintf("len(mss) = %d\n", len(mss)))
}
if len(mspa) != count {
- fmt.Printf("len(mspa) = %d\n", len(mspa))
+ panic(fmt.Sprintf("len(mspa) = %d\n", len(mspa)))
}
if len(mipT) != count {
- fmt.Printf("len(mipT) = %d\n", len(mipT))
+ panic(fmt.Sprintf("len(mipT) = %d\n", len(mipT)))
}
if len(mpTi) != count {
- fmt.Printf("len(mpTi) = %d\n", len(mpTi))
+ panic(fmt.Sprintf("len(mpTi) = %d\n", len(mpTi)))
}
// if len(mti) != count {
- // fmt.Printf("len(mti) = %d\n", len(mti))
+ // panic(fmt.Sprintf("len(mti) = %d\n", len(mti)))
// }
if len(mipM) != count {
- fmt.Printf("len(mipM) = %d\n", len(mipM))
+ panic(fmt.Sprintf("len(mipM) = %d\n", len(mipM)))
}
// if len(mti) != count {
- // fmt.Printf("len(mti) = %d\n", len(mti))
+ // panic(fmt.Sprintf("len(mti) = %d\n", len(mti)))
// }
if len(mit) != count {
- fmt.Printf("len(mit) = %d\n", len(mit))
+ panic(fmt.Sprintf("len(mit) = %d\n", len(mit)))
}
// test construction directly
@@ -151,48 +151,48 @@ func testbasic() {
f := float32(i)
// BUG m := M(i, i+1)
if mib[i] != (i != 0) {
- fmt.Printf("mib[%d] = %t\n", i, mib[i])
+ panic(fmt.Sprintf("mib[%d] = %t\n", i, mib[i]))
}
if mii[i] != 10*i {
- fmt.Printf("mii[%d] = %d\n", i, mii[i])
+ panic(fmt.Sprintf("mii[%d] = %d\n", i, mii[i]))
}
if mfi[f] != 10*i {
- fmt.Printf("mfi[%d] = %d\n", i, mfi[f])
+ panic(fmt.Sprintf("mfi[%d] = %d\n", i, mfi[f]))
}
if mif[i] != 10.0*f {
- fmt.Printf("mif[%d] = %g\n", i, mif[i])
+ panic(fmt.Sprintf("mif[%d] = %g\n", i, mif[i]))
}
if mis[i] != s {
- fmt.Printf("mis[%d] = %s\n", i, mis[i])
+ panic(fmt.Sprintf("mis[%d] = %s\n", i, mis[i]))
}
if msi[s] != i {
- fmt.Printf("msi[%s] = %d\n", s, msi[s])
+ panic(fmt.Sprintf("msi[%s] = %d\n", s, msi[s]))
}
if mss[s] != s10 {
- fmt.Printf("mss[%s] = %g\n", s, mss[s])
+ panic(fmt.Sprintf("mss[%s] = %g\n", s, mss[s]))
}
for j := 0; j < len(mspa[s]); j++ {
if mspa[s][j] != s10 {
- fmt.Printf("mspa[%s][%d] = %s\n", s, j, mspa[s][j])
+ panic(fmt.Sprintf("mspa[%s][%d] = %s\n", s, j, mspa[s][j]))
}
}
if mipT[i].i != int64(i) || mipT[i].f != f {
- fmt.Printf("mipT[%d] = %v\n", i, mipT[i])
+ panic(fmt.Sprintf("mipT[%d] = %v\n", i, mipT[i]))
}
if mpTi[apT[i]] != i {
- fmt.Printf("mpTi[apT[%d]] = %d\n", i, mpTi[apT[i]])
+ panic(fmt.Sprintf("mpTi[apT[%d]] = %d\n", i, mpTi[apT[i]]))
}
// if(mti[t] != i) {
- // fmt.Printf("mti[%s] = %s\n", s, mti[t])
+ // panic(fmt.Sprintf("mti[%s] = %s\n", s, mti[t]))
// }
if mipM[i][i] != i+1 {
- fmt.Printf("mipM[%d][%d] = %d\n", i, i, mipM[i][i])
+ panic(fmt.Sprintf("mipM[%d][%d] = %d\n", i, i, mipM[i][i]))
}
// if(mti[t] != i) {
- // fmt.Printf("mti[%v] = %d\n", t, mti[t])
+ // panic(fmt.Sprintf("mti[%v] = %d\n", t, mti[t]))
// }
if mit[i].i != int64(i) || mit[i].f != f {
- fmt.Printf("mit[%d] = {%d %g}\n", i, mit[i].i, mit[i].f)
+ panic(fmt.Sprintf("mit[%d] = {%d %g}\n", i, mit[i].i, mit[i].f))
}
}
@@ -204,131 +204,131 @@ func testbasic() {
{
_, b := mib[i]
if !b {
- fmt.Printf("tuple existence decl: mib[%d]\n", i)
+ panic(fmt.Sprintf("tuple existence decl: mib[%d]\n", i))
}
_, b = mib[i]
if !b {
- fmt.Printf("tuple existence assign: mib[%d]\n", i)
+ panic(fmt.Sprintf("tuple existence assign: mib[%d]\n", i))
}
}
{
_, b := mii[i]
if !b {
- fmt.Printf("tuple existence decl: mii[%d]\n", i)
+ panic(fmt.Sprintf("tuple existence decl: mii[%d]\n", i))
}
_, b = mii[i]
if !b {
- fmt.Printf("tuple existence assign: mii[%d]\n", i)
+ panic(fmt.Sprintf("tuple existence assign: mii[%d]\n", i))
}
}
{
_, b := mfi[f]
if !b {
- fmt.Printf("tuple existence decl: mfi[%d]\n", i)
+ panic(fmt.Sprintf("tuple existence decl: mfi[%d]\n", i))
}
_, b = mfi[f]
if !b {
- fmt.Printf("tuple existence assign: mfi[%d]\n", i)
+ panic(fmt.Sprintf("tuple existence assign: mfi[%d]\n", i))
}
}
{
_, b := mif[i]
if !b {
- fmt.Printf("tuple existence decl: mif[%d]\n", i)
+ panic(fmt.Sprintf("tuple existence decl: mif[%d]\n", i))
}
_, b = mif[i]
if !b {
- fmt.Printf("tuple existence assign: mif[%d]\n", i)
+ panic(fmt.Sprintf("tuple existence assign: mif[%d]\n", i))
}
}
{
_, b := mis[i]
if !b {
- fmt.Printf("tuple existence decl: mis[%d]\n", i)
+ panic(fmt.Sprintf("tuple existence decl: mis[%d]\n", i))
}
_, b = mis[i]
if !b {
- fmt.Printf("tuple existence assign: mis[%d]\n", i)
+ panic(fmt.Sprintf("tuple existence assign: mis[%d]\n", i))
}
}
{
_, b := msi[s]
if !b {
- fmt.Printf("tuple existence decl: msi[%d]\n", i)
+ panic(fmt.Sprintf("tuple existence decl: msi[%d]\n", i))
}
_, b = msi[s]
if !b {
- fmt.Printf("tuple existence assign: msi[%d]\n", i)
+ panic(fmt.Sprintf("tuple existence assign: msi[%d]\n", i))
}
}
{
_, b := mss[s]
if !b {
- fmt.Printf("tuple existence decl: mss[%d]\n", i)
+ panic(fmt.Sprintf("tuple existence decl: mss[%d]\n", i))
}
_, b = mss[s]
if !b {
- fmt.Printf("tuple existence assign: mss[%d]\n", i)
+ panic(fmt.Sprintf("tuple existence assign: mss[%d]\n", i))
}
}
{
_, b := mspa[s]
if !b {
- fmt.Printf("tuple existence decl: mspa[%d]\n", i)
+ panic(fmt.Sprintf("tuple existence decl: mspa[%d]\n", i))
}
_, b = mspa[s]
if !b {
- fmt.Printf("tuple existence assign: mspa[%d]\n", i)
+ panic(fmt.Sprintf("tuple existence assign: mspa[%d]\n", i))
}
}
{
_, b := mipT[i]
if !b {
- fmt.Printf("tuple existence decl: mipT[%d]\n", i)
+ panic(fmt.Sprintf("tuple existence decl: mipT[%d]\n", i))
}
_, b = mipT[i]
if !b {
- fmt.Printf("tuple existence assign: mipT[%d]\n", i)
+ panic(fmt.Sprintf("tuple existence assign: mipT[%d]\n", i))
}
}
{
_, b := mpTi[apT[i]]
if !b {
- fmt.Printf("tuple existence decl: mpTi[apT[%d]]\n", i)
+ panic(fmt.Sprintf("tuple existence decl: mpTi[apT[%d]]\n", i))
}
_, b = mpTi[apT[i]]
if !b {
- fmt.Printf("tuple existence assign: mpTi[apT[%d]]\n", i)
+ panic(fmt.Sprintf("tuple existence assign: mpTi[apT[%d]]\n", i))
}
}
{
_, b := mipM[i]
if !b {
- fmt.Printf("tuple existence decl: mipM[%d]\n", i)
+ panic(fmt.Sprintf("tuple existence decl: mipM[%d]\n", i))
}
_, b = mipM[i]
if !b {
- fmt.Printf("tuple existence assign: mipM[%d]\n", i)
+ panic(fmt.Sprintf("tuple existence assign: mipM[%d]\n", i))
}
}
{
_, b := mit[i]
if !b {
- fmt.Printf("tuple existence decl: mit[%d]\n", i)
+ panic(fmt.Sprintf("tuple existence decl: mit[%d]\n", i))
}
_, b = mit[i]
if !b {
- fmt.Printf("tuple existence assign: mit[%d]\n", i)
+ panic(fmt.Sprintf("tuple existence assign: mit[%d]\n", i))
}
}
// {
// _, b := mti[t]
// if !b {
- // fmt.Printf("tuple existence decl: mti[%d]\n", i)
+ // panic(fmt.Sprintf("tuple existence decl: mti[%d]\n", i))
// }
// _, b = mti[t]
// if !b {
- // fmt.Printf("tuple existence assign: mti[%d]\n", i)
+ // panic(fmt.Sprintf("tuple existence assign: mti[%d]\n", i))
// }
// }
}
@@ -341,131 +341,131 @@ func testbasic() {
{
_, b := mib[i]
if b {
- fmt.Printf("tuple nonexistence decl: mib[%d]", i)
+ panic(fmt.Sprintf("tuple nonexistence decl: mib[%d]", i))
}
_, b = mib[i]
if b {
- fmt.Printf("tuple nonexistence assign: mib[%d]", i)
+ panic(fmt.Sprintf("tuple nonexistence assign: mib[%d]", i))
}
}
{
_, b := mii[i]
if b {
- fmt.Printf("tuple nonexistence decl: mii[%d]", i)
+ panic(fmt.Sprintf("tuple nonexistence decl: mii[%d]", i))
}
_, b = mii[i]
if b {
- fmt.Printf("tuple nonexistence assign: mii[%d]", i)
+ panic(fmt.Sprintf("tuple nonexistence assign: mii[%d]", i))
}
}
{
_, b := mfi[f]
if b {
- fmt.Printf("tuple nonexistence decl: mfi[%d]", i)
+ panic(fmt.Sprintf("tuple nonexistence decl: mfi[%d]", i))
}
_, b = mfi[f]
if b {
- fmt.Printf("tuple nonexistence assign: mfi[%d]", i)
+ panic(fmt.Sprintf("tuple nonexistence assign: mfi[%d]", i))
}
}
{
_, b := mif[i]
if b {
- fmt.Printf("tuple nonexistence decl: mif[%d]", i)
+ panic(fmt.Sprintf("tuple nonexistence decl: mif[%d]", i))
}
_, b = mif[i]
if b {
- fmt.Printf("tuple nonexistence assign: mif[%d]", i)
+ panic(fmt.Sprintf("tuple nonexistence assign: mif[%d]", i))
}
}
{
_, b := mis[i]
if b {
- fmt.Printf("tuple nonexistence decl: mis[%d]", i)
+ panic(fmt.Sprintf("tuple nonexistence decl: mis[%d]", i))
}
_, b = mis[i]
if b {
- fmt.Printf("tuple nonexistence assign: mis[%d]", i)
+ panic(fmt.Sprintf("tuple nonexistence assign: mis[%d]", i))
}
}
{
_, b := msi[s]
if b {
- fmt.Printf("tuple nonexistence decl: msi[%d]", i)
+ panic(fmt.Sprintf("tuple nonexistence decl: msi[%d]", i))
}
_, b = msi[s]
if b {
- fmt.Printf("tuple nonexistence assign: msi[%d]", i)
+ panic(fmt.Sprintf("tuple nonexistence assign: msi[%d]", i))
}
}
{
_, b := mss[s]
if b {
- fmt.Printf("tuple nonexistence decl: mss[%d]", i)
+ panic(fmt.Sprintf("tuple nonexistence decl: mss[%d]", i))
}
_, b = mss[s]
if b {
- fmt.Printf("tuple nonexistence assign: mss[%d]", i)
+ panic(fmt.Sprintf("tuple nonexistence assign: mss[%d]", i))
}
}
{
_, b := mspa[s]
if b {
- fmt.Printf("tuple nonexistence decl: mspa[%d]", i)
+ panic(fmt.Sprintf("tuple nonexistence decl: mspa[%d]", i))
}
_, b = mspa[s]
if b {
- fmt.Printf("tuple nonexistence assign: mspa[%d]", i)
+ panic(fmt.Sprintf("tuple nonexistence assign: mspa[%d]", i))
}
}
{
_, b := mipT[i]
if b {
- fmt.Printf("tuple nonexistence decl: mipT[%d]", i)
+ panic(fmt.Sprintf("tuple nonexistence decl: mipT[%d]", i))
}
_, b = mipT[i]
if b {
- fmt.Printf("tuple nonexistence assign: mipT[%d]", i)
+ panic(fmt.Sprintf("tuple nonexistence assign: mipT[%d]", i))
}
}
{
_, b := mpTi[apT[i]]
if b {
- fmt.Printf("tuple nonexistence decl: mpTi[apt[%d]]", i)
+ panic(fmt.Sprintf("tuple nonexistence decl: mpTi[apt[%d]]", i))
}
_, b = mpTi[apT[i]]
if b {
- fmt.Printf("tuple nonexistence assign: mpTi[apT[%d]]", i)
+ panic(fmt.Sprintf("tuple nonexistence assign: mpTi[apT[%d]]", i))
}
}
{
_, b := mipM[i]
if b {
- fmt.Printf("tuple nonexistence decl: mipM[%d]", i)
+ panic(fmt.Sprintf("tuple nonexistence decl: mipM[%d]", i))
}
_, b = mipM[i]
if b {
- fmt.Printf("tuple nonexistence assign: mipM[%d]", i)
+ panic(fmt.Sprintf("tuple nonexistence assign: mipM[%d]", i))
}
}
// {
// _, b := mti[t]
// if b {
- // fmt.Printf("tuple nonexistence decl: mti[%d]", i)
+ // panic(fmt.Sprintf("tuple nonexistence decl: mti[%d]", i))
// }
// _, b = mti[t]
// if b {
- // fmt.Printf("tuple nonexistence assign: mti[%d]", i)
+ // panic(fmt.Sprintf("tuple nonexistence assign: mti[%d]", i))
// }
// }
{
_, b := mit[i]
if b {
- fmt.Printf("tuple nonexistence decl: mit[%d]", i)
+ panic(fmt.Sprintf("tuple nonexistence decl: mit[%d]", i))
}
_, b = mit[i]
if b {
- fmt.Printf("tuple nonexistence assign: mit[%d]", i)
+ panic(fmt.Sprintf("tuple nonexistence assign: mit[%d]", i))
}
}
}
@@ -475,21 +475,25 @@ func testbasic() {
s := strconv.Itoa(i)
mspa[s][i%2] = "deleted"
if mspa[s][i%2] != "deleted" {
- fmt.Printf("update mspa[%s][%d] = %s\n", s, i%2, mspa[s][i%2])
+ panic(fmt.Sprintf("update mspa[%s][%d] = %s\n", s, i%2, mspa[s][i%2]))
+
}
mipT[i].i += 1
if mipT[i].i != int64(i)+1 {
- fmt.Printf("update mipT[%d].i = %d\n", i, mipT[i].i)
+ panic(fmt.Sprintf("update mipT[%d].i = %d\n", i, mipT[i].i))
+
}
mipT[i].f = float32(i + 1)
if mipT[i].f != float32(i+1) {
- fmt.Printf("update mipT[%d].f = %g\n", i, mipT[i].f)
+ panic(fmt.Sprintf("update mipT[%d].f = %g\n", i, mipT[i].f))
+
}
mipM[i][i]++
if mipM[i][i] != (i+1)+1 {
- fmt.Printf("update mipM[%d][%d] = %d\n", i, i, mipM[i][i])
+ panic(fmt.Sprintf("update mipM[%d][%d] = %d\n", i, i, mipM[i][i]))
+
}
}
@@ -519,29 +523,29 @@ func testfloat() {
nanb: "NaN",
}
if m[pz] != "+0" {
- fmt.Println("float32 map cannot read back m[+0]:", m[pz])
+ panic(fmt.Sprintln("float32 map cannot read back m[+0]:", m[pz]))
}
if m[nz] != "+0" {
- fmt.Println("float32 map does not treat", pz, "and", nz, "as equal for read")
- fmt.Println("float32 map does not treat -0 and +0 as equal for read")
+ fmt.Sprintln("float32 map does not treat", pz, "and", nz, "as equal for read")
+ panic(fmt.Sprintln("float32 map does not treat -0 and +0 as equal for read"))
}
m[nz] = "-0"
if m[pz] != "-0" {
- fmt.Println("float32 map does not treat -0 and +0 as equal for write")
+ panic(fmt.Sprintln("float32 map does not treat -0 and +0 as equal for write"))
}
if _, ok := m[nana]; ok {
- fmt.Println("float32 map allows NaN lookup (a)")
+ panic(fmt.Sprintln("float32 map allows NaN lookup (a)"))
}
if _, ok := m[nanb]; ok {
- fmt.Println("float32 map allows NaN lookup (b)")
+ panic(fmt.Sprintln("float32 map allows NaN lookup (b)"))
}
if len(m) != 3 {
- fmt.Println("float32 map should have 3 entries:", m)
+ panic(fmt.Sprintln("float32 map should have 3 entries:", m))
}
m[nana] = "NaN"
m[nanb] = "NaN"
if len(m) != 5 {
- fmt.Println("float32 map should have 5 entries:", m)
+ panic(fmt.Sprintln("float32 map should have 5 entries:", m))
}
}
@@ -559,25 +563,25 @@ func testfloat() {
nanb: "NaN",
}
if m[nz] != "+0" {
- fmt.Println("float64 map does not treat -0 and +0 as equal for read")
+ panic(fmt.Sprintln("float64 map does not treat -0 and +0 as equal for read"))
}
m[nz] = "-0"
if m[pz] != "-0" {
- fmt.Println("float64 map does not treat -0 and +0 as equal for write")
+ panic(fmt.Sprintln("float64 map does not treat -0 and +0 as equal for write"))
}
if _, ok := m[nana]; ok {
- fmt.Println("float64 map allows NaN lookup (a)")
+ panic(fmt.Sprintln("float64 map allows NaN lookup (a)"))
}
if _, ok := m[nanb]; ok {
- fmt.Println("float64 map allows NaN lookup (b)")
+ panic(fmt.Sprintln("float64 map allows NaN lookup (b)"))
}
if len(m) != 3 {
- fmt.Println("float64 map should have 3 entries:", m)
+ panic(fmt.Sprintln("float64 map should have 3 entries:", m))
}
m[nana] = "NaN"
m[nanb] = "NaN"
if len(m) != 5 {
- fmt.Println("float64 map should have 5 entries:", m)
+ panic(fmt.Sprintln("float64 map should have 5 entries:", m))
}
}
@@ -595,25 +599,25 @@ func testfloat() {
nanb: "NaN",
}
if m[nz] != "+0" {
- fmt.Println("complex64 map does not treat -0 and +0 as equal for read")
+ panic(fmt.Sprintln("complex64 map does not treat -0 and +0 as equal for read"))
}
m[nz] = "-0"
if m[pz] != "-0" {
- fmt.Println("complex64 map does not treat -0 and +0 as equal for write")
+ panic(fmt.Sprintln("complex64 map does not treat -0 and +0 as equal for write"))
}
if _, ok := m[nana]; ok {
- fmt.Println("complex64 map allows NaN lookup (a)")
+ panic(fmt.Sprintln("complex64 map allows NaN lookup (a)"))
}
if _, ok := m[nanb]; ok {
- fmt.Println("complex64 map allows NaN lookup (b)")
+ panic(fmt.Sprintln("complex64 map allows NaN lookup (b)"))
}
if len(m) != 3 {
- fmt.Println("complex64 map should have 3 entries:", m)
+ panic(fmt.Sprintln("complex64 map should have 3 entries:", m))
}
m[nana] = "NaN"
m[nanb] = "NaN"
if len(m) != 5 {
- fmt.Println("complex64 map should have 5 entries:", m)
+ panic(fmt.Sprintln("complex64 map should have 5 entries:", m))
}
}
@@ -631,63 +635,50 @@ func testfloat() {
nanb: "NaN",
}
if m[nz] != "+0" {
- fmt.Println("complex128 map does not treat -0 and +0 as equal for read")
+ panic(fmt.Sprintln("complex128 map does not treat -0 and +0 as equal for read"))
}
m[nz] = "-0"
if m[pz] != "-0" {
- fmt.Println("complex128 map does not treat -0 and +0 as equal for write")
+ panic(fmt.Sprintln("complex128 map does not treat -0 and +0 as equal for write"))
}
if _, ok := m[nana]; ok {
- fmt.Println("complex128 map allows NaN lookup (a)")
+ panic(fmt.Sprintln("complex128 map allows NaN lookup (a)"))
}
if _, ok := m[nanb]; ok {
- fmt.Println("complex128 map allows NaN lookup (b)")
+ panic(fmt.Sprintln("complex128 map allows NaN lookup (b)"))
}
if len(m) != 3 {
- fmt.Println("complex128 map should have 3 entries:", m)
+ panic(fmt.Sprintln("complex128 map should have 3 entries:", m))
}
m[nana] = "NaN"
m[nanb] = "NaN"
if len(m) != 5 {
- fmt.Println("complex128 map should have 5 entries:", m)
+ panic(fmt.Sprintln("complex128 map should have 5 entries:", m))
}
}
}
func testnan() {
- // Test that NaNs in maps don't go quadratic.
- t := func(n int) time.Duration {
- t0 := time.Now()
- m := map[float64]int{}
- nan := math.NaN()
- for i := 0; i < n; i++ {
- m[nan] = 1
- }
- if len(m) != n {
- panic("wrong size map after nan insertion")
- }
- return time.Since(t0)
+ n := 500
+ m := map[float64]int{}
+ nan := math.NaN()
+ for i := 0; i < n; i++ {
+ m[nan] = 1
}
-
- // Depending on the machine and OS, this test might be too fast
- // to measure with accurate enough granularity. On failure,
- // make it run longer, hoping that the timing granularity
- // is eventually sufficient.
-
- n := 30000 // 0.02 seconds on a MacBook Air
- fails := 0
- for {
- t1 := t(n)
- t2 := t(2 * n)
- // should be 2x (linear); allow up to 3x
- if t2 < 3*t1 {
- return
- }
- fails++
- if fails == 4 {
- fmt.Printf("too slow: %d inserts: %v; %d inserts: %v\n", n, t1, 2*n, t2)
- return
- }
- n *= 2
+ if len(m) != n {
+ panic("wrong size map after nan insertion")
+ }
+ iters := 0
+ for k, v := range m {
+ iters++
+ if !math.IsNaN(k) {
+ panic("not NaN")
+ }
+ if v != 1 {
+ panic("wrong value")
+ }
+ }
+ if iters != n {
+ panic("wrong number of nan range iters")
}
}
diff --git a/gcc/testsuite/go.test/test/mapnan.go b/gcc/testsuite/go.test/test/mapnan.go
new file mode 100644
index 00000000000..60b35fbeaf4
--- /dev/null
+++ b/gcc/testsuite/go.test/test/mapnan.go
@@ -0,0 +1,64 @@
+// +build darwin linux
+// run
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test that NaNs in maps don't go quadratic.
+
+package main
+
+import (
+ "fmt"
+ "math"
+ "time"
+ "syscall"
+)
+
+func main() {
+
+ // Test that NaNs in maps don't go quadratic.
+ t := func(n int) time.Duration {
+ var u0 syscall.Rusage
+ if err := syscall.Getrusage(0, &u0); err != nil {
+ panic(err)
+ }
+ m := map[float64]int{}
+ nan := math.NaN()
+ for i := 0; i < n; i++ {
+ m[nan] = 1
+ }
+ if len(m) != n {
+ panic("wrong size map after nan insertion")
+ }
+ var u1 syscall.Rusage
+ if err := syscall.Getrusage(0, &u1); err != nil {
+ panic(err)
+ }
+ return time.Duration(u1.Utime.Nano() - u0.Utime.Nano())
+ }
+
+ // Depending on the machine and OS, this test might be too fast
+ // to measure with accurate enough granularity. On failure,
+ // make it run longer, hoping that the timing granularity
+ // is eventually sufficient.
+
+ n := 30000 // ~8ms user time on a Mid 2011 MacBook Air (1.8 GHz Core i7)
+ fails := 0
+ for {
+ t1 := t(n)
+ t2 := t(2 * n)
+ // should be 2x (linear); allow up to 3x
+ if t2 < 3*t1 {
+ return
+ }
+ fails++
+ if fails == 6 {
+ panic(fmt.Sprintf("too slow: %d inserts: %v; %d inserts: %v\n", n, t1, 2*n, t2))
+ }
+ if fails < 4 {
+ n *= 2
+ }
+ }
+}
diff --git a/gcc/testsuite/go.test/test/method.go b/gcc/testsuite/go.test/test/method.go
index 0c239afbd19..d97bc4a7d09 100644
--- a/gcc/testsuite/go.test/test/method.go
+++ b/gcc/testsuite/go.test/test/method.go
@@ -128,13 +128,13 @@ func main() {
panic("fail")
}
- var zs struct { S }
- var zps struct { *S1 }
- var zi struct { I }
- var zpi struct { *I1 }
- var zpt struct { *T1 }
- var zt struct { T }
- var zv struct { Val }
+ var zs struct{ S }
+ var zps struct{ *S1 }
+ var zi struct{ I }
+ var zpi struct{ *I1 }
+ var zpt struct{ *T1 }
+ var zt struct{ T }
+ var zv struct{ Val }
if zs.val() != 1 {
println("zs.val:", zs.val())
@@ -247,4 +247,61 @@ func main() {
println("zv.val():", zv.val())
panic("fail")
}
+
+ promotion()
+}
+
+type A struct{ B }
+type B struct {
+ C
+ *D
+}
+type C int
+
+func (C) f() {} // value receiver, direct field of A
+func (*C) g() {} // pointer receiver
+
+type D int
+
+func (D) h() {} // value receiver, indirect field of A
+func (*D) i() {} // pointer receiver
+
+func expectPanic() {
+ if r := recover(); r == nil {
+ panic("expected nil dereference")
+ }
+}
+
+func promotion() {
+ var a A
+ // Addressable value receiver.
+ a.f()
+ a.g()
+ func() {
+ defer expectPanic()
+ a.h() // dynamic error: nil dereference in a.B.D->f()
+ }()
+ a.i()
+
+ // Non-addressable value receiver.
+ A(a).f()
+ // A(a).g() // static error: cannot call pointer method on A literal.B.C
+ func() {
+ defer expectPanic()
+ A(a).h() // dynamic error: nil dereference in A().B.D->f()
+ }()
+ A(a).i()
+
+ // Pointer receiver.
+ (&a).f()
+ (&a).g()
+ func() {
+ defer expectPanic()
+ (&a).h() // dynamic error: nil deref: nil dereference in (&a).B.D->f()
+ }()
+ (&a).i()
+
+ c := new(C)
+ c.f() // makes a copy
+ c.g()
}
diff --git a/gcc/testsuite/go.test/test/method4.dir/method4a.go b/gcc/testsuite/go.test/test/method4.dir/method4a.go
new file mode 100644
index 00000000000..a7df04cec36
--- /dev/null
+++ b/gcc/testsuite/go.test/test/method4.dir/method4a.go
@@ -0,0 +1,37 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test method expressions with arguments.
+
+package method4a
+
+type T1 int
+
+type T2 struct {
+ F int
+}
+
+type I1 interface {
+ Sum([]int, int) int
+}
+
+type I2 interface {
+ Sum(a []int, b int) int
+}
+
+func (i T1) Sum(a []int, b int) int {
+ r := int(i) + b
+ for _, v := range a {
+ r += v
+ }
+ return r
+}
+
+func (p *T2) Sum(a []int, b int) int {
+ r := p.F + b
+ for _, v := range a {
+ r += v
+ }
+ return r
+}
diff --git a/gcc/testsuite/go.test/test/method4.dir/prog.go b/gcc/testsuite/go.test/test/method4.dir/prog.go
new file mode 100644
index 00000000000..77d580cffc5
--- /dev/null
+++ b/gcc/testsuite/go.test/test/method4.dir/prog.go
@@ -0,0 +1,104 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test method expressions with arguments.
+
+package main
+
+import "./method4a"
+
+type T1 int
+
+type T2 struct {
+ f int
+}
+
+type I1 interface {
+ Sum([]int, int) int
+}
+
+type I2 interface {
+ Sum(a []int, b int) int
+}
+
+func (i T1) Sum(a []int, b int) int {
+ r := int(i) + b
+ for _, v := range a {
+ r += v
+ }
+ return r
+}
+
+func (p *T2) Sum(a []int, b int) int {
+ r := p.f + b
+ for _, v := range a {
+ r += v
+ }
+ return r
+}
+
+func eq(v1, v2 int) {
+ if v1 != v2 {
+ panic(0)
+ }
+}
+
+func main() {
+ a := []int{1, 2, 3}
+ t1 := T1(4)
+ t2 := &T2{4}
+
+ eq(t1.Sum(a, 5), 15)
+ eq(t2.Sum(a, 6), 16)
+
+ eq(T1.Sum(t1, a, 7), 17)
+ eq((*T2).Sum(t2, a, 8), 18)
+
+ f1 := T1.Sum
+ eq(f1(t1, a, 9), 19)
+ f2 := (*T2).Sum
+ eq(f2(t2, a, 10), 20)
+
+ eq(I1.Sum(t1, a, 11), 21)
+ eq(I1.Sum(t2, a, 12), 22)
+
+ f3 := I1.Sum
+ eq(f3(t1, a, 13), 23)
+ eq(f3(t2, a, 14), 24)
+
+ eq(I2.Sum(t1, a, 15), 25)
+ eq(I2.Sum(t2, a, 16), 26)
+
+ f4 := I2.Sum
+ eq(f4(t1, a, 17), 27)
+ eq(f4(t2, a, 18), 28)
+
+ mt1 := method4a.T1(4)
+ mt2 := &method4a.T2{4}
+
+ eq(mt1.Sum(a, 30), 40)
+ eq(mt2.Sum(a, 31), 41)
+
+ eq(method4a.T1.Sum(mt1, a, 32), 42)
+ eq((*method4a.T2).Sum(mt2, a, 33), 43)
+
+ g1 := method4a.T1.Sum
+ eq(g1(mt1, a, 34), 44)
+ g2 := (*method4a.T2).Sum
+ eq(g2(mt2, a, 35), 45)
+
+ eq(method4a.I1.Sum(mt1, a, 36), 46)
+ eq(method4a.I1.Sum(mt2, a, 37), 47)
+
+ g3 := method4a.I1.Sum
+ eq(g3(mt1, a, 38), 48)
+ eq(g3(mt2, a, 39), 49)
+
+ eq(method4a.I2.Sum(mt1, a, 40), 50)
+ eq(method4a.I2.Sum(mt2, a, 41), 51)
+
+ g4 := method4a.I2.Sum
+ eq(g4(mt1, a, 42), 52)
+ eq(g4(mt2, a, 43), 53)
+}
diff --git a/gcc/testsuite/go.test/test/method4.go b/gcc/testsuite/go.test/test/method4.go
index 7e7b1ff3b96..813892bc830 100644
--- a/gcc/testsuite/go.test/test/method4.go
+++ b/gcc/testsuite/go.test/test/method4.go
@@ -1,109 +1,8 @@
-// $G $D/method4a.go && $G $D/$F.go && $L $F.$A && ./$A.out
-
-// NOTE: This test is not run by 'run.go' and so not run by all.bash.
-// To run this test you must use the ./run shell script.
+// rundir
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Test method expressions with arguments.
-
-package main
-
-import "./method4a"
-
-type T1 int
-
-type T2 struct {
- f int
-}
-
-type I1 interface {
- Sum([]int, int) int
-}
-
-type I2 interface {
- Sum(a []int, b int) int
-}
-
-func (i T1) Sum(a []int, b int) int {
- r := int(i) + b
- for _, v := range a {
- r += v
- }
- return r
-}
-
-func (p *T2) Sum(a []int, b int) int {
- r := p.f + b
- for _, v := range a {
- r += v
- }
- return r
-}
-
-func eq(v1, v2 int) {
- if v1 != v2 {
- panic(0)
- }
-}
-
-func main() {
- a := []int{1, 2, 3}
- t1 := T1(4)
- t2 := &T2{4}
-
- eq(t1.Sum(a, 5), 15)
- eq(t2.Sum(a, 6), 16)
-
- eq(T1.Sum(t1, a, 7), 17)
- eq((*T2).Sum(t2, a, 8), 18)
-
- f1 := T1.Sum
- eq(f1(t1, a, 9), 19)
- f2 := (*T2).Sum
- eq(f2(t2, a, 10), 20)
-
- eq(I1.Sum(t1, a, 11), 21)
- eq(I1.Sum(t2, a, 12), 22)
-
- f3 := I1.Sum
- eq(f3(t1, a, 13), 23)
- eq(f3(t2, a, 14), 24)
-
- eq(I2.Sum(t1, a, 15), 25)
- eq(I2.Sum(t2, a, 16), 26)
-
- f4 := I2.Sum
- eq(f4(t1, a, 17), 27)
- eq(f4(t2, a, 18), 28)
-
- mt1 := method4a.T1(4)
- mt2 := &method4a.T2{4}
-
- eq(mt1.Sum(a, 30), 40)
- eq(mt2.Sum(a, 31), 41)
-
- eq(method4a.T1.Sum(mt1, a, 32), 42)
- eq((*method4a.T2).Sum(mt2, a, 33), 43)
-
- g1 := method4a.T1.Sum
- eq(g1(mt1, a, 34), 44)
- g2 := (*method4a.T2).Sum
- eq(g2(mt2, a, 35), 45)
-
- eq(method4a.I1.Sum(mt1, a, 36), 46)
- eq(method4a.I1.Sum(mt2, a, 37), 47)
-
- g3 := method4a.I1.Sum
- eq(g3(mt1, a, 38), 48)
- eq(g3(mt2, a, 39), 49)
-
- eq(method4a.I2.Sum(mt1, a, 40), 50)
- eq(method4a.I2.Sum(mt2, a, 41), 51)
-
- g4 := method4a.I2.Sum
- eq(g4(mt1, a, 42), 52)
- eq(g4(mt2, a, 43), 53)
-}
+package ignored
diff --git a/gcc/testsuite/go.test/test/method4a.go b/gcc/testsuite/go.test/test/method4a.go
deleted file mode 100644
index d23039bfaaa..00000000000
--- a/gcc/testsuite/go.test/test/method4a.go
+++ /dev/null
@@ -1,40 +0,0 @@
-// skip
-
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Test method expressions with arguments.
-// This file is not tested by itself; it is imported by method4.go.
-
-package method4a
-
-type T1 int
-
-type T2 struct {
- F int
-}
-
-type I1 interface {
- Sum([]int, int) int
-}
-
-type I2 interface {
- Sum(a []int, b int) int
-}
-
-func (i T1) Sum(a []int, b int) int {
- r := int(i) + b
- for _, v := range a {
- r += v
- }
- return r
-}
-
-func (p *T2) Sum(a []int, b int) int {
- r := p.F + b
- for _, v := range a {
- r += v
- }
- return r
-}
diff --git a/gcc/testsuite/go.test/test/method5.go b/gcc/testsuite/go.test/test/method5.go
new file mode 100644
index 00000000000..36508f2e76f
--- /dev/null
+++ b/gcc/testsuite/go.test/test/method5.go
@@ -0,0 +1,297 @@
+// run
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+// Concrete types implementing M method.
+// Smaller than a word, word-sized, larger than a word.
+// Value and pointer receivers.
+
+type Tinter interface {
+ M(int, byte) (byte, int)
+}
+
+type Tsmallv byte
+
+func (v Tsmallv) M(x int, b byte) (byte, int) { return b, x+int(v) }
+
+type Tsmallp byte
+
+func (p *Tsmallp) M(x int, b byte) (byte, int) { return b, x+int(*p) }
+
+type Twordv uintptr
+
+func (v Twordv) M(x int, b byte) (byte, int) { return b, x+int(v) }
+
+type Twordp uintptr
+
+func (p *Twordp) M(x int, b byte) (byte, int) { return b, x+int(*p) }
+
+type Tbigv [2]uintptr
+
+func (v Tbigv) M(x int, b byte) (byte, int) { return b, x+int(v[0])+int(v[1]) }
+
+type Tbigp [2]uintptr
+
+func (p *Tbigp) M(x int, b byte) (byte, int) { return b, x+int(p[0])+int(p[1]) }
+
+// Again, with an unexported method.
+
+type tsmallv byte
+
+func (v tsmallv) m(x int, b byte) (byte, int) { return b, x+int(v) }
+
+type tsmallp byte
+
+func (p *tsmallp) m(x int, b byte) (byte, int) { return b, x+int(*p) }
+
+type twordv uintptr
+
+func (v twordv) m(x int, b byte) (byte, int) { return b, x+int(v) }
+
+type twordp uintptr
+
+func (p *twordp) m(x int, b byte) (byte, int) { return b, x+int(*p) }
+
+type tbigv [2]uintptr
+
+func (v tbigv) m(x int, b byte) (byte, int) { return b, x+int(v[0])+int(v[1]) }
+
+type tbigp [2]uintptr
+
+func (p *tbigp) m(x int, b byte) (byte, int) { return b, x+int(p[0])+int(p[1]) }
+
+type tinter interface {
+ m(int, byte) (byte, int)
+}
+
+// Embedding via pointer.
+
+type T1 struct {
+ T2
+}
+
+type T2 struct {
+ *T3
+}
+
+type T3 struct {
+ *T4
+}
+
+type T4 struct {
+}
+
+func (t4 T4) M(x int, b byte) (byte, int) { return b, x+40 }
+
+var failed = false
+
+func CheckI(name string, i Tinter, inc int) {
+ b, x := i.M(1000, 99)
+ if b != 99 || x != 1000+inc {
+ failed = true
+ print(name, ".M(1000, 99) = ", b, ", ", x, " want 99, ", 1000+inc, "\n")
+ }
+
+ CheckF("(i="+name+")", i.M, inc)
+}
+
+func CheckF(name string, f func(int, byte) (byte, int), inc int) {
+ b, x := f(1000, 99)
+ if b != 99 || x != 1000+inc {
+ failed = true
+ print(name, "(1000, 99) = ", b, ", ", x, " want 99, ", 1000+inc, "\n")
+ }
+}
+
+func checkI(name string, i tinter, inc int) {
+ b, x := i.m(1000, 99)
+ if b != 99 || x != 1000+inc {
+ failed = true
+ print(name, ".m(1000, 99) = ", b, ", ", x, " want 99, ", 1000+inc, "\n")
+ }
+
+ checkF("(i="+name+")", i.m, inc)
+}
+
+func checkF(name string, f func(int, byte) (byte, int), inc int) {
+ b, x := f(1000, 99)
+ if b != 99 || x != 1000+inc {
+ failed = true
+ print(name, "(1000, 99) = ", b, ", ", x, " want 99, ", 1000+inc, "\n")
+ }
+}
+
+func shouldPanic(f func()) {
+ defer func() {
+ if recover() == nil {
+ panic("not panicking")
+ }
+ }()
+ f()
+}
+
+func shouldNotPanic(f func()) {
+ f()
+}
+
+func main() {
+ sv := Tsmallv(1)
+ CheckI("sv", sv, 1)
+ CheckF("sv.M", sv.M, 1)
+ CheckF("(&sv).M", (&sv).M, 1)
+ psv := &sv
+ CheckI("psv", psv, 1)
+ CheckF("psv.M", psv.M, 1)
+ CheckF("(*psv).M", (*psv).M, 1)
+
+ sp := Tsmallp(2)
+ CheckI("&sp", &sp, 2)
+ CheckF("sp.M", sp.M, 2)
+ CheckF("(&sp).M", (&sp).M, 2)
+ psp := &sp
+ CheckI("psp", psp, 2)
+ CheckF("psp.M", psp.M, 2)
+ CheckF("(*psp).M", (*psp).M, 2)
+
+ wv := Twordv(3)
+ CheckI("wv", wv, 3)
+ CheckF("wv.M", wv.M, 3)
+ CheckF("(&wv).M", (&wv).M, 3)
+ pwv := &wv
+ CheckI("pwv", pwv, 3)
+ CheckF("pwv.M", pwv.M, 3)
+ CheckF("(*pwv).M", (*pwv).M, 3)
+
+ wp := Twordp(4)
+ CheckI("&wp", &wp, 4)
+ CheckF("wp.M", wp.M, 4)
+ CheckF("(&wp).M", (&wp).M, 4)
+ pwp := &wp
+ CheckI("pwp", pwp, 4)
+ CheckF("pwp.M", pwp.M, 4)
+ CheckF("(*pwp).M", (*pwp).M, 4)
+
+ bv := Tbigv([2]uintptr{5, 6})
+ pbv := &bv
+ CheckI("bv", bv, 11)
+ CheckF("bv.M", bv.M, 11)
+ CheckF("(&bv).M", (&bv).M, 11)
+ CheckI("pbv", pbv, 11)
+ CheckF("pbv.M", pbv.M, 11)
+ CheckF("(*pbv).M", (*pbv).M, 11)
+
+ bp := Tbigp([2]uintptr{7,8})
+ CheckI("&bp", &bp, 15)
+ CheckF("bp.M", bp.M, 15)
+ CheckF("(&bp).M", (&bp).M, 15)
+ pbp := &bp
+ CheckI("pbp", pbp, 15)
+ CheckF("pbp.M", pbp.M, 15)
+ CheckF("(*pbp).M", (*pbp).M, 15)
+
+ _sv := tsmallv(1)
+ checkI("_sv", _sv, 1)
+ checkF("_sv.m", _sv.m, 1)
+ checkF("(&_sv).m", (&_sv).m, 1)
+ _psv := &_sv
+ checkI("_psv", _psv, 1)
+ checkF("_psv.m", _psv.m, 1)
+ checkF("(*_psv).m", (*_psv).m, 1)
+
+ _sp := tsmallp(2)
+ checkI("&_sp", &_sp, 2)
+ checkF("_sp.m", _sp.m, 2)
+ checkF("(&_sp).m", (&_sp).m, 2)
+ _psp := &_sp
+ checkI("_psp", _psp, 2)
+ checkF("_psp.m", _psp.m, 2)
+ checkF("(*_psp).m", (*_psp).m, 2)
+
+ _wv := twordv(3)
+ checkI("_wv", _wv, 3)
+ checkF("_wv.m", _wv.m, 3)
+ checkF("(&_wv).m", (&_wv).m, 3)
+ _pwv := &_wv
+ checkI("_pwv", _pwv, 3)
+ checkF("_pwv.m", _pwv.m, 3)
+ checkF("(*_pwv).m", (*_pwv).m, 3)
+
+ _wp := twordp(4)
+ checkI("&_wp", &_wp, 4)
+ checkF("_wp.m", _wp.m, 4)
+ checkF("(&_wp).m", (&_wp).m, 4)
+ _pwp := &_wp
+ checkI("_pwp", _pwp, 4)
+ checkF("_pwp.m", _pwp.m, 4)
+ checkF("(*_pwp).m", (*_pwp).m, 4)
+
+ _bv := tbigv([2]uintptr{5, 6})
+ _pbv := &_bv
+ checkI("_bv", _bv, 11)
+ checkF("_bv.m", _bv.m, 11)
+ checkF("(&_bv).m", (&_bv).m, 11)
+ checkI("_pbv", _pbv, 11)
+ checkF("_pbv.m", _pbv.m, 11)
+ checkF("(*_pbv).m", (*_pbv).m, 11)
+
+ _bp := tbigp([2]uintptr{7,8})
+ checkI("&_bp", &_bp, 15)
+ checkF("_bp.m", _bp.m, 15)
+ checkF("(&_bp).m", (&_bp).m, 15)
+ _pbp := &_bp
+ checkI("_pbp", _pbp, 15)
+ checkF("_pbp.m", _pbp.m, 15)
+ checkF("(*_pbp).m", (*_pbp).m, 15)
+
+ t4 := T4{}
+ t3 := T3{&t4}
+ t2 := T2{&t3}
+ t1 := T1{t2}
+ CheckI("t4", t4, 40)
+ CheckI("&t4", &t4, 40)
+ CheckI("t3", t3, 40)
+ CheckI("&t3", &t3, 40)
+ CheckI("t2", t2, 40)
+ CheckI("&t2", &t2, 40)
+ CheckI("t1", t1, 40)
+ CheckI("&t1", &t1, 40)
+
+ // x.M panics if x is an interface type and is nil,
+ // or if x.M expands to (*x).M where x is nil,
+ // or if x.M expands to x.y.z.w.M where something
+ // along the evaluation of x.y.z.w is nil.
+ var f func(int, byte) (byte, int)
+ shouldPanic(func() { psv = nil; f = psv.M })
+ shouldPanic(func() { pwv = nil; f = pwv.M })
+ shouldPanic(func() { pbv = nil; f = pbv.M })
+ shouldPanic(func() { var i Tinter; f = i.M })
+ shouldPanic(func() { _psv = nil; f = _psv.m })
+ shouldPanic(func() { _pwv = nil; f = _pwv.m })
+ shouldPanic(func() { _pbv = nil; f = _pbv.m })
+ shouldPanic(func() { var _i tinter; f = _i.m })
+ shouldPanic(func() { var t1 T1; f = t1.M })
+ shouldPanic(func() { var t2 T2; f = t2.M })
+ shouldPanic(func() { var t3 *T3; f = t3.M })
+ shouldPanic(func() { var t3 T3; f = t3.M })
+
+ if f != nil {
+ panic("something set f")
+ }
+
+ // x.M does not panic if x is a nil pointer and
+ // M is a method with a pointer receiver.
+ shouldNotPanic(func() { psp = nil; f = psp.M })
+ shouldNotPanic(func() { pwp = nil; f = pwp.M })
+ shouldNotPanic(func() { pbp = nil; f = pbp.M })
+ shouldNotPanic(func() { _psp = nil; f = _psp.m })
+ shouldNotPanic(func() { _pwp = nil; f = _pwp.m })
+ shouldNotPanic(func() { _pbp = nil; f = _pbp.m })
+ shouldNotPanic(func() { var t4 T4; f = t4.M })
+ if f == nil {
+ panic("nothing set f")
+ }
+}
diff --git a/gcc/testsuite/go.test/test/nil.go b/gcc/testsuite/go.test/test/nil.go
index aa558fa3f49..f8300bf56af 100644
--- a/gcc/testsuite/go.test/test/nil.go
+++ b/gcc/testsuite/go.test/test/nil.go
@@ -115,7 +115,7 @@ func chantest() {
})
shouldBlock(func() {
x, ok := <-ch
- println(x, ok)
+ println(x, ok) // unreachable
})
if len(ch) != 0 {
@@ -147,12 +147,13 @@ func maptest() {
panic(v)
}
+ // can delete (non-existent) entries
+ delete(m, 2)
+
// but cannot be written to
shouldPanic(func() {
m[2] = 3
})
- // can delete (non-existent) entries
- delete(m, 2)
}
// nil slice
diff --git a/gcc/testsuite/go.test/test/nilptr.go b/gcc/testsuite/go.test/test/nilptr.go
index b784914e590..793e9967368 100644
--- a/gcc/testsuite/go.test/test/nilptr.go
+++ b/gcc/testsuite/go.test/test/nilptr.go
@@ -38,6 +38,8 @@ func main() {
shouldPanic(p8)
shouldPanic(p9)
shouldPanic(p10)
+ shouldPanic(p11)
+ shouldPanic(p12)
}
func shouldPanic(f func()) {
@@ -130,3 +132,23 @@ func p10() {
var t *T
println(t.i) // should crash
}
+
+type T1 struct {
+ T
+}
+
+type T2 struct {
+ *T1
+}
+
+func p11() {
+ t := &T2{}
+ p := &t.i
+ println(*p)
+}
+
+// ADDR(DOT(IND(p))) needs a check also
+func p12() {
+ var p *T = nil
+ println(*(&((*p).i)))
+}
diff --git a/gcc/testsuite/go.test/test/nul1.go b/gcc/testsuite/go.test/test/nul1.go
index 968c9529513..20426b4fa08 100644
--- a/gcc/testsuite/go.test/test/nul1.go
+++ b/gcc/testsuite/go.test/test/nul1.go
@@ -1,10 +1,4 @@
-// [ "$GORUN" == "" ] || exit 0 # Android runner gets confused by the NUL output
-// $G $D/$F.go && $L $F.$A && ./$A.out >tmp.go &&
-// errchk $G -e tmp.go
-// rm -f tmp.go
-
-// NOTE: This test is not run by 'run.go' and so not run by all.bash.
-// To run this test you must use the ./run shell script.
+// errorcheckoutput
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
diff --git a/gcc/testsuite/go.test/test/range.go b/gcc/testsuite/go.test/test/range.go
index 68b0c9a2f33..8effbe9c53a 100644
--- a/gcc/testsuite/go.test/test/range.go
+++ b/gcc/testsuite/go.test/test/range.go
@@ -55,10 +55,10 @@ func testslice() {
panic("fail")
}
if s != 15 {
- println("wrong sum ranging over makeslice")
+ println("wrong sum ranging over makeslice", s)
panic("fail")
}
-
+
x := []int{10, 20}
y := []int{99}
i := 1
@@ -82,7 +82,7 @@ func testslice1() {
panic("fail")
}
if s != 10 {
- println("wrong sum ranging over makeslice")
+ println("wrong sum ranging over makeslice", s)
panic("fail")
}
}
@@ -106,7 +106,7 @@ func testarray() {
panic("fail")
}
if s != 15 {
- println("wrong sum ranging over makearray")
+ println("wrong sum ranging over makearray", s)
panic("fail")
}
}
@@ -122,7 +122,7 @@ func testarray1() {
panic("fail")
}
if s != 10 {
- println("wrong sum ranging over makearray")
+ println("wrong sum ranging over makearray", s)
panic("fail")
}
}
@@ -155,7 +155,7 @@ func testarrayptr() {
panic("fail")
}
if s != 15 {
- println("wrong sum ranging over makearrayptr")
+ println("wrong sum ranging over makearrayptr", s)
panic("fail")
}
}
@@ -171,7 +171,7 @@ func testarrayptr1() {
panic("fail")
}
if s != 10 {
- println("wrong sum ranging over makearrayptr")
+ println("wrong sum ranging over makearrayptr", s)
panic("fail")
}
}
@@ -195,7 +195,7 @@ func teststring() {
panic("fail")
}
if s != 'a'+'b'+'c'+'d'+'☺' {
- println("wrong sum ranging over makestring")
+ println("wrong sum ranging over makestring", s)
panic("fail")
}
}
@@ -211,7 +211,7 @@ func teststring1() {
panic("fail")
}
if s != 10 {
- println("wrong sum ranging over makestring")
+ println("wrong sum ranging over makestring", s)
panic("fail")
}
}
@@ -235,7 +235,7 @@ func testmap() {
panic("fail")
}
if s != 'a'+'b'+'c'+'d'+'☺' {
- println("wrong sum ranging over makemap")
+ println("wrong sum ranging over makemap", s)
panic("fail")
}
}
@@ -251,7 +251,7 @@ func testmap1() {
panic("fail")
}
if s != 10 {
- println("wrong sum ranging over makemap")
+ println("wrong sum ranging over makemap", s)
panic("fail")
}
}
diff --git a/gcc/testsuite/go.test/test/recover.go b/gcc/testsuite/go.test/test/recover.go
index eea655ec578..7c27d7c4d63 100644
--- a/gcc/testsuite/go.test/test/recover.go
+++ b/gcc/testsuite/go.test/test/recover.go
@@ -8,15 +8,21 @@
package main
-import "runtime"
+import (
+ "os"
+ "runtime"
+)
func main() {
test1()
test1WithClosures()
test2()
test3()
- test4()
- test5()
+ // exp/ssa/interp still has some bugs in recover().
+ if os.Getenv("GOSSAINTERP") == "" {
+ test4()
+ test5()
+ }
test6()
test6WithClosures()
test7()
diff --git a/gcc/testsuite/go.test/test/recover3.go b/gcc/testsuite/go.test/test/recover3.go
index 98700231ef5..ebfa0a30757 100644
--- a/gcc/testsuite/go.test/test/recover3.go
+++ b/gcc/testsuite/go.test/test/recover3.go
@@ -71,6 +71,10 @@ func main() {
inter = 1
check("type-concrete", func() { println(inter.(string)) }, "int, not string")
check("type-interface", func() { println(inter.(m)) }, "missing method m")
+
+ if didbug {
+ panic("recover3")
+ }
}
type m interface {
diff --git a/gcc/testsuite/go.test/test/rename.go b/gcc/testsuite/go.test/test/rename.go
index e5442745538..dc4341718dc 100644
--- a/gcc/testsuite/go.test/test/rename.go
+++ b/gcc/testsuite/go.test/test/rename.go
@@ -8,7 +8,10 @@
package main
-import "fmt"
+import (
+ "fmt"
+ "runtime"
+)
func main() {
n :=
@@ -52,6 +55,7 @@ func main() {
iota
if n != NUM*(NUM-1)/2 {
fmt.Println("BUG: wrong n", n, NUM*(NUM-1)/2)
+ runtime.Breakpoint() // panic is inaccessible
}
}
diff --git a/gcc/testsuite/go.test/test/reorder.go b/gcc/testsuite/go.test/test/reorder.go
index 0cdeebd0f31..8fd623c1c70 100644
--- a/gcc/testsuite/go.test/test/reorder.go
+++ b/gcc/testsuite/go.test/test/reorder.go
@@ -19,7 +19,6 @@ func main() {
p6()
p7()
p8()
- p9()
}
var gx []int
@@ -43,7 +42,7 @@ func check3(x, y, z, xx, yy, zz int) {
}
func p1() {
- x := []int{1,2,3}
+ x := []int{1, 2, 3}
i := 0
i, x[i] = 1, 100
_ = i
@@ -51,7 +50,7 @@ func p1() {
}
func p2() {
- x := []int{1,2,3}
+ x := []int{1, 2, 3}
i := 0
x[i], i = 100, 1
_ = i
@@ -59,7 +58,7 @@ func p2() {
}
func p3() {
- x := []int{1,2,3}
+ x := []int{1, 2, 3}
y := x
gx = x
x[1], y[0] = f(0), f(1)
@@ -67,7 +66,7 @@ func p3() {
}
func p4() {
- x := []int{1,2,3}
+ x := []int{1, 2, 3}
y := x
gx = x
x[1], y[0] = gx[0], gx[1]
@@ -75,7 +74,7 @@ func p4() {
}
func p5() {
- x := []int{1,2,3}
+ x := []int{1, 2, 3}
y := x
p := &x[0]
q := &x[1]
@@ -90,7 +89,7 @@ func p6() {
px := &x
py := &y
*px, *py = y, x
- check3(x, y, z, 2, 1, 3)
+ check3(x, y, z, 2, 1, 3)
}
func f1(x, y, z int) (xx, yy, zz int) {
@@ -107,21 +106,6 @@ func p7() {
}
func p8() {
- x := []int{1,2,3}
-
- defer func() {
- err := recover()
- if err == nil {
- panic("not panicking")
- }
- check(x, 100, 2, 3)
- }()
-
- i := 0
- i, x[i], x[5] = 1, 100, 500
-}
-
-func p9() {
m := make(map[int]int)
m[0] = len(m)
if m[0] != 0 {
diff --git a/gcc/testsuite/go.test/test/return.go b/gcc/testsuite/go.test/test/return.go
new file mode 100644
index 00000000000..482f22bd5f4
--- /dev/null
+++ b/gcc/testsuite/go.test/test/return.go
@@ -0,0 +1,2821 @@
+// errorcheck
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test compiler diagnosis of function missing return statements.
+// See issue 65 and golang.org/s/go11return.
+
+package p
+
+type T int
+
+var x interface{}
+var c chan int
+
+func external() int // ok
+
+func _() int {
+} // ERROR "missing return"
+
+func _() int {
+ print(1)
+} // ERROR "missing return"
+
+// return is okay
+func _() int {
+ print(1)
+ return 2
+}
+
+// goto is okay
+func _() int {
+L:
+ print(1)
+ goto L
+}
+
+// panic is okay
+func _() int {
+ print(1)
+ panic(2)
+}
+
+// but only builtin panic
+func _() int {
+ var panic = func(int) {}
+ print(1)
+ panic(2)
+} // ERROR "missing return"
+
+// block ending in terminating statement is okay
+func _() int {
+ {
+ print(1)
+ return 2
+ }
+}
+
+// block ending in terminating statement is okay
+func _() int {
+L:
+ {
+ print(1)
+ goto L
+ }
+}
+
+// block ending in terminating statement is okay
+func _() int {
+ print(1)
+ {
+ panic(2)
+ }
+}
+
+// adding more code - even though it is dead - now requires a return
+
+func _() int {
+ print(1)
+ return 2
+ print(3)
+} // ERROR "missing return"
+
+func _() int {
+L:
+ print(1)
+ goto L
+ print(3)
+} // ERROR "missing return"
+
+func _() int {
+ print(1)
+ panic(2)
+ print(3)
+} // ERROR "missing return"
+
+func _() int {
+ {
+ print(1)
+ return 2
+ print(3)
+ }
+} // ERROR "missing return"
+
+func _() int {
+L:
+ {
+ print(1)
+ goto L
+ print(3)
+ }
+} // ERROR "missing return"
+
+func _() int {
+ print(1)
+ {
+ panic(2)
+ print(3)
+ }
+} // ERROR "missing return"
+
+func _() int {
+ {
+ print(1)
+ return 2
+ }
+ print(3)
+} // ERROR "missing return"
+
+func _() int {
+L:
+ {
+ print(1)
+ goto L
+ }
+ print(3)
+} // ERROR "missing return"
+
+func _() int {
+ print(1)
+ {
+ panic(2)
+ }
+ print(3)
+} // ERROR "missing return"
+
+// even an empty dead block triggers the message, because it
+// becomes the final statement.
+
+func _() int {
+ print(1)
+ return 2
+ {}
+} // ERROR "missing return"
+
+func _() int {
+L:
+ print(1)
+ goto L
+ {}
+} // ERROR "missing return"
+
+func _() int {
+ print(1)
+ panic(2)
+ {}
+} // ERROR "missing return"
+
+func _() int {
+ {
+ print(1)
+ return 2
+ {}
+ }
+} // ERROR "missing return"
+
+func _() int {
+L:
+ {
+ print(1)
+ goto L
+ {}
+ }
+} // ERROR "missing return"
+
+func _() int {
+ print(1)
+ {
+ panic(2)
+ {}
+ }
+} // ERROR "missing return"
+
+func _() int {
+ {
+ print(1)
+ return 2
+ }
+ {}
+} // ERROR "missing return"
+
+func _() int {
+L:
+ {
+ print(1)
+ goto L
+ }
+ {}
+} // ERROR "missing return"
+
+func _() int {
+ print(1)
+ {
+ panic(2)
+ }
+ {}
+} // ERROR "missing return"
+
+// if-else chain with final else and all terminating is okay
+
+func _() int {
+ print(1)
+ if x == nil {
+ panic(2)
+ } else {
+ panic(3)
+ }
+}
+
+func _() int {
+L:
+ print(1)
+ if x == nil {
+ panic(2)
+ } else {
+ goto L
+ }
+}
+
+func _() int {
+L:
+ print(1)
+ if x == nil {
+ panic(2)
+ } else if x == 1 {
+ return 0
+ } else if x != 2 {
+ panic(3)
+ } else {
+ goto L
+ }
+}
+
+// if-else chain missing final else is not okay, even if the
+// conditions cover every possible case.
+
+func _() int {
+ print(1)
+ if x == nil {
+ panic(2)
+ } else if x != nil {
+ panic(3)
+ }
+} // ERROR "missing return"
+
+func _() int {
+ print(1)
+ if x == nil {
+ panic(2)
+ }
+} // ERROR "missing return"
+
+func _() int {
+ print(1)
+ if x == nil {
+ panic(2)
+ } else if x == 1 {
+ return 0
+ } else if x != 1 {
+ panic(3)
+ }
+} // ERROR "missing return"
+
+
+// for { loops that never break are okay.
+
+func _() int {
+ print(1)
+ for {}
+}
+
+func _() int {
+ for {
+ for {
+ break
+ }
+ }
+}
+
+func _() int {
+ for {
+ L:
+ for {
+ break L
+ }
+ }
+}
+
+// for { loops that break are not okay.
+
+func _() int {
+ print(1)
+ for { break }
+} // ERROR "missing return"
+
+func _() int {
+ for {
+ for {
+ }
+ break
+ }
+} // ERROR "missing return"
+
+func _() int {
+L:
+ for {
+ for {
+ break L
+ }
+ }
+} // ERROR "missing return"
+
+// if there's a condition - even "true" - the loops are no longer syntactically terminating
+
+func _() int {
+ print(1)
+ for x == nil {}
+} // ERROR "missing return"
+
+func _() int {
+ for x == nil {
+ for {
+ break
+ }
+ }
+} // ERROR "missing return"
+
+func _() int {
+ for x == nil {
+ L:
+ for {
+ break L
+ }
+ }
+} // ERROR "missing return"
+
+func _() int {
+ print(1)
+ for true {}
+} // ERROR "missing return"
+
+func _() int {
+ for true {
+ for {
+ break
+ }
+ }
+} // ERROR "missing return"
+
+func _() int {
+ for true {
+ L:
+ for {
+ break L
+ }
+ }
+} // ERROR "missing return"
+
+// select in which all cases terminate and none break are okay.
+
+func _() int {
+ print(1)
+ select{}
+}
+
+func _() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ }
+}
+
+func _() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ for{}
+ }
+}
+
+func _() int {
+L:
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ case c <- 1:
+ print(2)
+ goto L
+ }
+}
+
+func _() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ default:
+ select{}
+ }
+}
+
+// if any cases don't terminate, the select isn't okay anymore
+
+func _() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ }
+} // ERROR "missing return"
+
+func _() int {
+L:
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ goto L
+ case c <- 1:
+ print(2)
+ }
+} // ERROR "missing return"
+
+
+func _() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ default:
+ print(2)
+ }
+} // ERROR "missing return"
+
+
+// if any breaks refer to the select, the select isn't okay anymore, even if they're dead
+
+func _() int {
+ print(1)
+ select{ default: break }
+} // ERROR "missing return"
+
+func _() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ break
+ }
+} // ERROR "missing return"
+
+func _() int {
+ print(1)
+L:
+ select {
+ case <-c:
+ print(2)
+ for{ break L }
+ }
+} // ERROR "missing return"
+
+func _() int {
+ print(1)
+L:
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ case c <- 1:
+ print(2)
+ break L
+ }
+} // ERROR "missing return"
+
+func _() int {
+ print(1)
+ select {
+ case <-c:
+ print(1)
+ panic("abc")
+ default:
+ select{}
+ break
+ }
+} // ERROR "missing return"
+
+// switch with default in which all cases terminate is okay
+
+func _() int {
+ print(1)
+ switch x {
+ case 1:
+ print(2)
+ panic(3)
+ default:
+ return 4
+ }
+}
+
+func _() int {
+ print(1)
+ switch x {
+ default:
+ return 4
+ case 1:
+ print(2)
+ panic(3)
+ }
+}
+
+func _() int {
+ print(1)
+ switch x {
+ case 1:
+ print(2)
+ fallthrough
+ default:
+ return 4
+ }
+}
+
+// if no default or some case doesn't terminate, switch is no longer okay
+
+func _() int {
+ print(1)
+ switch {
+ }
+} // ERROR "missing return"
+
+
+func _() int {
+ print(1)
+ switch x {
+ case 1:
+ print(2)
+ panic(3)
+ case 2:
+ return 4
+ }
+} // ERROR "missing return"
+
+func _() int {
+ print(1)
+ switch x {
+ case 2:
+ return 4
+ case 1:
+ print(2)
+ panic(3)
+ }
+} // ERROR "missing return"
+
+func _() int {
+ print(1)
+ switch x {
+ case 1:
+ print(2)
+ fallthrough
+ case 2:
+ return 4
+ }
+} // ERROR "missing return"
+
+func _() int {
+ print(1)
+ switch x {
+ case 1:
+ print(2)
+ panic(3)
+ }
+} // ERROR "missing return"
+
+// if any breaks refer to the switch, switch is no longer okay
+
+func _() int {
+ print(1)
+L:
+ switch x {
+ case 1:
+ print(2)
+ panic(3)
+ break L
+ default:
+ return 4
+ }
+} // ERROR "missing return"
+
+func _() int {
+ print(1)
+ switch x {
+ default:
+ return 4
+ break
+ case 1:
+ print(2)
+ panic(3)
+ }
+} // ERROR "missing return"
+
+func _() int {
+ print(1)
+L:
+ switch x {
+ case 1:
+ print(2)
+ for {
+ break L
+ }
+ default:
+ return 4
+ }
+} // ERROR "missing return"
+
+// type switch with default in which all cases terminate is okay
+
+func _() int {
+ print(1)
+ switch x.(type) {
+ case int:
+ print(2)
+ panic(3)
+ default:
+ return 4
+ }
+}
+
+func _() int {
+ print(1)
+ switch x.(type) {
+ default:
+ return 4
+ case int:
+ print(2)
+ panic(3)
+ }
+}
+
+// if no default or some case doesn't terminate, switch is no longer okay
+
+func _() int {
+ print(1)
+ switch {
+ }
+} // ERROR "missing return"
+
+
+func _() int {
+ print(1)
+ switch x.(type) {
+ case int:
+ print(2)
+ panic(3)
+ case float64:
+ return 4
+ }
+} // ERROR "missing return"
+
+func _() int {
+ print(1)
+ switch x.(type) {
+ case float64:
+ return 4
+ case int:
+ print(2)
+ panic(3)
+ }
+} // ERROR "missing return"
+
+func _() int {
+ print(1)
+ switch x.(type) {
+ case int:
+ print(2)
+ panic(3)
+ }
+} // ERROR "missing return"
+
+// if any breaks refer to the switch, switch is no longer okay
+
+func _() int {
+ print(1)
+L:
+ switch x.(type) {
+ case int:
+ print(2)
+ panic(3)
+ break L
+ default:
+ return 4
+ }
+} // ERROR "missing return"
+
+func _() int {
+ print(1)
+ switch x.(type) {
+ default:
+ return 4
+ break
+ case int:
+ print(2)
+ panic(3)
+ }
+} // ERROR "missing return"
+
+func _() int {
+ print(1)
+L:
+ switch x.(type) {
+ case int:
+ print(2)
+ for {
+ break L
+ }
+ default:
+ return 4
+ }
+} // ERROR "missing return"
+
+// again, but without the leading print(1).
+// testing that everything works when the terminating statement is first.
+
+func _() int {
+} // ERROR "missing return"
+
+// return is okay
+func _() int {
+ return 2
+}
+
+// goto is okay
+func _() int {
+L:
+ goto L
+}
+
+// panic is okay
+func _() int {
+ panic(2)
+}
+
+// but only builtin panic
+func _() int {
+ var panic = func(int) {}
+ panic(2)
+} // ERROR "missing return"
+
+// block ending in terminating statement is okay
+func _() int {
+ {
+ return 2
+ }
+}
+
+// block ending in terminating statement is okay
+func _() int {
+L:
+ {
+ goto L
+ }
+}
+
+// block ending in terminating statement is okay
+func _() int {
+ {
+ panic(2)
+ }
+}
+
+// adding more code - even though it is dead - now requires a return
+
+func _() int {
+ return 2
+ print(3)
+} // ERROR "missing return"
+
+func _() int {
+L:
+ goto L
+ print(3)
+} // ERROR "missing return"
+
+func _() int {
+ panic(2)
+ print(3)
+} // ERROR "missing return"
+
+func _() int {
+ {
+ return 2
+ print(3)
+ }
+} // ERROR "missing return"
+
+func _() int {
+L:
+ {
+ goto L
+ print(3)
+ }
+} // ERROR "missing return"
+
+func _() int {
+ {
+ panic(2)
+ print(3)
+ }
+} // ERROR "missing return"
+
+func _() int {
+ {
+ return 2
+ }
+ print(3)
+} // ERROR "missing return"
+
+func _() int {
+L:
+ {
+ goto L
+ }
+ print(3)
+} // ERROR "missing return"
+
+func _() int {
+ {
+ panic(2)
+ }
+ print(3)
+} // ERROR "missing return"
+
+// even an empty dead block triggers the message, because it
+// becomes the final statement.
+
+func _() int {
+ return 2
+ {}
+} // ERROR "missing return"
+
+func _() int {
+L:
+ goto L
+ {}
+} // ERROR "missing return"
+
+func _() int {
+ panic(2)
+ {}
+} // ERROR "missing return"
+
+func _() int {
+ {
+ return 2
+ {}
+ }
+} // ERROR "missing return"
+
+func _() int {
+L:
+ {
+ goto L
+ {}
+ }
+} // ERROR "missing return"
+
+func _() int {
+ {
+ panic(2)
+ {}
+ }
+} // ERROR "missing return"
+
+func _() int {
+ {
+ return 2
+ }
+ {}
+} // ERROR "missing return"
+
+func _() int {
+L:
+ {
+ goto L
+ }
+ {}
+} // ERROR "missing return"
+
+func _() int {
+ {
+ panic(2)
+ }
+ {}
+} // ERROR "missing return"
+
+// if-else chain with final else and all terminating is okay
+
+func _() int {
+ if x == nil {
+ panic(2)
+ } else {
+ panic(3)
+ }
+}
+
+func _() int {
+L:
+ if x == nil {
+ panic(2)
+ } else {
+ goto L
+ }
+}
+
+func _() int {
+L:
+ if x == nil {
+ panic(2)
+ } else if x == 1 {
+ return 0
+ } else if x != 2 {
+ panic(3)
+ } else {
+ goto L
+ }
+}
+
+// if-else chain missing final else is not okay, even if the
+// conditions cover every possible case.
+
+func _() int {
+ if x == nil {
+ panic(2)
+ } else if x != nil {
+ panic(3)
+ }
+} // ERROR "missing return"
+
+func _() int {
+ if x == nil {
+ panic(2)
+ }
+} // ERROR "missing return"
+
+func _() int {
+ if x == nil {
+ panic(2)
+ } else if x == 1 {
+ return 0
+ } else if x != 1 {
+ panic(3)
+ }
+} // ERROR "missing return"
+
+
+// for { loops that never break are okay.
+
+func _() int {
+ for {}
+}
+
+func _() int {
+ for {
+ for {
+ break
+ }
+ }
+}
+
+func _() int {
+ for {
+ L:
+ for {
+ break L
+ }
+ }
+}
+
+// for { loops that break are not okay.
+
+func _() int {
+ for { break }
+} // ERROR "missing return"
+
+func _() int {
+ for {
+ for {
+ }
+ break
+ }
+} // ERROR "missing return"
+
+func _() int {
+L:
+ for {
+ for {
+ break L
+ }
+ }
+} // ERROR "missing return"
+
+// if there's a condition - even "true" - the loops are no longer syntactically terminating
+
+func _() int {
+ for x == nil {}
+} // ERROR "missing return"
+
+func _() int {
+ for x == nil {
+ for {
+ break
+ }
+ }
+} // ERROR "missing return"
+
+func _() int {
+ for x == nil {
+ L:
+ for {
+ break L
+ }
+ }
+} // ERROR "missing return"
+
+func _() int {
+ for true {}
+} // ERROR "missing return"
+
+func _() int {
+ for true {
+ for {
+ break
+ }
+ }
+} // ERROR "missing return"
+
+func _() int {
+ for true {
+ L:
+ for {
+ break L
+ }
+ }
+} // ERROR "missing return"
+
+// select in which all cases terminate and none break are okay.
+
+func _() int {
+ select{}
+}
+
+func _() int {
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ }
+}
+
+func _() int {
+ select {
+ case <-c:
+ print(2)
+ for{}
+ }
+}
+
+func _() int {
+L:
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ case c <- 1:
+ print(2)
+ goto L
+ }
+}
+
+func _() int {
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ default:
+ select{}
+ }
+}
+
+// if any cases don't terminate, the select isn't okay anymore
+
+func _() int {
+ select {
+ case <-c:
+ print(2)
+ }
+} // ERROR "missing return"
+
+func _() int {
+L:
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ goto L
+ case c <- 1:
+ print(2)
+ }
+} // ERROR "missing return"
+
+
+func _() int {
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ default:
+ print(2)
+ }
+} // ERROR "missing return"
+
+
+// if any breaks refer to the select, the select isn't okay anymore, even if they're dead
+
+func _() int {
+ select{ default: break }
+} // ERROR "missing return"
+
+func _() int {
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ break
+ }
+} // ERROR "missing return"
+
+func _() int {
+L:
+ select {
+ case <-c:
+ print(2)
+ for{ break L }
+ }
+} // ERROR "missing return"
+
+func _() int {
+L:
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ case c <- 1:
+ print(2)
+ break L
+ }
+} // ERROR "missing return"
+
+func _() int {
+ select {
+ case <-c:
+ panic("abc")
+ default:
+ select{}
+ break
+ }
+} // ERROR "missing return"
+
+// switch with default in which all cases terminate is okay
+
+func _() int {
+ switch x {
+ case 1:
+ print(2)
+ panic(3)
+ default:
+ return 4
+ }
+}
+
+func _() int {
+ switch x {
+ default:
+ return 4
+ case 1:
+ print(2)
+ panic(3)
+ }
+}
+
+func _() int {
+ switch x {
+ case 1:
+ print(2)
+ fallthrough
+ default:
+ return 4
+ }
+}
+
+// if no default or some case doesn't terminate, switch is no longer okay
+
+func _() int {
+ switch {
+ }
+} // ERROR "missing return"
+
+
+func _() int {
+ switch x {
+ case 1:
+ print(2)
+ panic(3)
+ case 2:
+ return 4
+ }
+} // ERROR "missing return"
+
+func _() int {
+ switch x {
+ case 2:
+ return 4
+ case 1:
+ print(2)
+ panic(3)
+ }
+} // ERROR "missing return"
+
+func _() int {
+ switch x {
+ case 1:
+ print(2)
+ fallthrough
+ case 2:
+ return 4
+ }
+} // ERROR "missing return"
+
+func _() int {
+ switch x {
+ case 1:
+ print(2)
+ panic(3)
+ }
+} // ERROR "missing return"
+
+// if any breaks refer to the switch, switch is no longer okay
+
+func _() int {
+L:
+ switch x {
+ case 1:
+ print(2)
+ panic(3)
+ break L
+ default:
+ return 4
+ }
+} // ERROR "missing return"
+
+func _() int {
+ switch x {
+ default:
+ return 4
+ break
+ case 1:
+ print(2)
+ panic(3)
+ }
+} // ERROR "missing return"
+
+func _() int {
+L:
+ switch x {
+ case 1:
+ print(2)
+ for {
+ break L
+ }
+ default:
+ return 4
+ }
+} // ERROR "missing return"
+
+// type switch with default in which all cases terminate is okay
+
+func _() int {
+ switch x.(type) {
+ case int:
+ print(2)
+ panic(3)
+ default:
+ return 4
+ }
+}
+
+func _() int {
+ switch x.(type) {
+ default:
+ return 4
+ case int:
+ print(2)
+ panic(3)
+ }
+}
+
+// if no default or some case doesn't terminate, switch is no longer okay
+
+func _() int {
+ switch {
+ }
+} // ERROR "missing return"
+
+
+func _() int {
+ switch x.(type) {
+ case int:
+ print(2)
+ panic(3)
+ case float64:
+ return 4
+ }
+} // ERROR "missing return"
+
+func _() int {
+ switch x.(type) {
+ case float64:
+ return 4
+ case int:
+ print(2)
+ panic(3)
+ }
+} // ERROR "missing return"
+
+func _() int {
+ switch x.(type) {
+ case int:
+ print(2)
+ panic(3)
+ }
+} // ERROR "missing return"
+
+// if any breaks refer to the switch, switch is no longer okay
+
+func _() int {
+L:
+ switch x.(type) {
+ case int:
+ print(2)
+ panic(3)
+ break L
+ default:
+ return 4
+ }
+} // ERROR "missing return"
+
+func _() int {
+ switch x.(type) {
+ default:
+ return 4
+ break
+ case int:
+ print(2)
+ panic(3)
+ }
+} // ERROR "missing return"
+
+func _() int {
+L:
+ switch x.(type) {
+ case int:
+ print(2)
+ for {
+ break L
+ }
+ default:
+ return 4
+ }
+} // ERROR "missing return"
+
+func _() int {
+ switch x.(type) {
+ default:
+ return 4
+ case int, float64:
+ print(2)
+ panic(3)
+ }
+}
+
+// again, with func literals
+
+var _ = func() int {
+} // ERROR "missing return"
+
+var _ = func() int {
+ print(1)
+} // ERROR "missing return"
+
+// return is okay
+var _ = func() int {
+ print(1)
+ return 2
+}
+
+// goto is okay
+var _ = func() int {
+L:
+ print(1)
+ goto L
+}
+
+// panic is okay
+var _ = func() int {
+ print(1)
+ panic(2)
+}
+
+// but only builtin panic
+var _ = func() int {
+ var panic = func(int) {}
+ print(1)
+ panic(2)
+} // ERROR "missing return"
+
+// block ending in terminating statement is okay
+var _ = func() int {
+ {
+ print(1)
+ return 2
+ }
+}
+
+// block ending in terminating statement is okay
+var _ = func() int {
+L:
+ {
+ print(1)
+ goto L
+ }
+}
+
+// block ending in terminating statement is okay
+var _ = func() int {
+ print(1)
+ {
+ panic(2)
+ }
+}
+
+// adding more code - even though it is dead - now requires a return
+
+var _ = func() int {
+ print(1)
+ return 2
+ print(3)
+} // ERROR "missing return"
+
+var _ = func() int {
+L:
+ print(1)
+ goto L
+ print(3)
+} // ERROR "missing return"
+
+var _ = func() int {
+ print(1)
+ panic(2)
+ print(3)
+} // ERROR "missing return"
+
+var _ = func() int {
+ {
+ print(1)
+ return 2
+ print(3)
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+L:
+ {
+ print(1)
+ goto L
+ print(3)
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ print(1)
+ {
+ panic(2)
+ print(3)
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ {
+ print(1)
+ return 2
+ }
+ print(3)
+} // ERROR "missing return"
+
+var _ = func() int {
+L:
+ {
+ print(1)
+ goto L
+ }
+ print(3)
+} // ERROR "missing return"
+
+var _ = func() int {
+ print(1)
+ {
+ panic(2)
+ }
+ print(3)
+} // ERROR "missing return"
+
+// even an empty dead block triggers the message, because it
+// becomes the final statement.
+
+var _ = func() int {
+ print(1)
+ return 2
+ {}
+} // ERROR "missing return"
+
+var _ = func() int {
+L:
+ print(1)
+ goto L
+ {}
+} // ERROR "missing return"
+
+var _ = func() int {
+ print(1)
+ panic(2)
+ {}
+} // ERROR "missing return"
+
+var _ = func() int {
+ {
+ print(1)
+ return 2
+ {}
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+L:
+ {
+ print(1)
+ goto L
+ {}
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ print(1)
+ {
+ panic(2)
+ {}
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ {
+ print(1)
+ return 2
+ }
+ {}
+} // ERROR "missing return"
+
+var _ = func() int {
+L:
+ {
+ print(1)
+ goto L
+ }
+ {}
+} // ERROR "missing return"
+
+var _ = func() int {
+ print(1)
+ {
+ panic(2)
+ }
+ {}
+} // ERROR "missing return"
+
+// if-else chain with final else and all terminating is okay
+
+var _ = func() int {
+ print(1)
+ if x == nil {
+ panic(2)
+ } else {
+ panic(3)
+ }
+}
+
+var _ = func() int {
+L:
+ print(1)
+ if x == nil {
+ panic(2)
+ } else {
+ goto L
+ }
+}
+
+var _ = func() int {
+L:
+ print(1)
+ if x == nil {
+ panic(2)
+ } else if x == 1 {
+ return 0
+ } else if x != 2 {
+ panic(3)
+ } else {
+ goto L
+ }
+}
+
+// if-else chain missing final else is not okay, even if the
+// conditions cover every possible case.
+
+var _ = func() int {
+ print(1)
+ if x == nil {
+ panic(2)
+ } else if x != nil {
+ panic(3)
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ print(1)
+ if x == nil {
+ panic(2)
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ print(1)
+ if x == nil {
+ panic(2)
+ } else if x == 1 {
+ return 0
+ } else if x != 1 {
+ panic(3)
+ }
+} // ERROR "missing return"
+
+
+// for { loops that never break are okay.
+
+var _ = func() int {
+ print(1)
+ for {}
+}
+
+var _ = func() int {
+ for {
+ for {
+ break
+ }
+ }
+}
+
+var _ = func() int {
+ for {
+ L:
+ for {
+ break L
+ }
+ }
+}
+
+// for { loops that break are not okay.
+
+var _ = func() int {
+ print(1)
+ for { break }
+} // ERROR "missing return"
+
+var _ = func() int {
+ for {
+ for {
+ }
+ break
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+L:
+ for {
+ for {
+ break L
+ }
+ }
+} // ERROR "missing return"
+
+// if there's a condition - even "true" - the loops are no longer syntactically terminating
+
+var _ = func() int {
+ print(1)
+ for x == nil {}
+} // ERROR "missing return"
+
+var _ = func() int {
+ for x == nil {
+ for {
+ break
+ }
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ for x == nil {
+ L:
+ for {
+ break L
+ }
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ print(1)
+ for true {}
+} // ERROR "missing return"
+
+var _ = func() int {
+ for true {
+ for {
+ break
+ }
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ for true {
+ L:
+ for {
+ break L
+ }
+ }
+} // ERROR "missing return"
+
+// select in which all cases terminate and none break are okay.
+
+var _ = func() int {
+ print(1)
+ select{}
+}
+
+var _ = func() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ }
+}
+
+var _ = func() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ for{}
+ }
+}
+
+var _ = func() int {
+L:
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ case c <- 1:
+ print(2)
+ goto L
+ }
+}
+
+var _ = func() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ default:
+ select{}
+ }
+}
+
+// if any cases don't terminate, the select isn't okay anymore
+
+var _ = func() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+L:
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ goto L
+ case c <- 1:
+ print(2)
+ }
+} // ERROR "missing return"
+
+
+var _ = func() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ default:
+ print(2)
+ }
+} // ERROR "missing return"
+
+
+// if any breaks refer to the select, the select isn't okay anymore, even if they're dead
+
+var _ = func() int {
+ print(1)
+ select{ default: break }
+} // ERROR "missing return"
+
+var _ = func() int {
+ print(1)
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ break
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ print(1)
+L:
+ select {
+ case <-c:
+ print(2)
+ for{ break L }
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ print(1)
+L:
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ case c <- 1:
+ print(2)
+ break L
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ print(1)
+ select {
+ case <-c:
+ print(1)
+ panic("abc")
+ default:
+ select{}
+ break
+ }
+} // ERROR "missing return"
+
+// switch with default in which all cases terminate is okay
+
+var _ = func() int {
+ print(1)
+ switch x {
+ case 1:
+ print(2)
+ panic(3)
+ default:
+ return 4
+ }
+}
+
+var _ = func() int {
+ print(1)
+ switch x {
+ default:
+ return 4
+ case 1:
+ print(2)
+ panic(3)
+ }
+}
+
+var _ = func() int {
+ print(1)
+ switch x {
+ case 1:
+ print(2)
+ fallthrough
+ default:
+ return 4
+ }
+}
+
+// if no default or some case doesn't terminate, switch is no longer okay
+
+var _ = func() int {
+ print(1)
+ switch {
+ }
+} // ERROR "missing return"
+
+
+var _ = func() int {
+ print(1)
+ switch x {
+ case 1:
+ print(2)
+ panic(3)
+ case 2:
+ return 4
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ print(1)
+ switch x {
+ case 2:
+ return 4
+ case 1:
+ print(2)
+ panic(3)
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ print(1)
+ switch x {
+ case 1:
+ print(2)
+ fallthrough
+ case 2:
+ return 4
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ print(1)
+ switch x {
+ case 1:
+ print(2)
+ panic(3)
+ }
+} // ERROR "missing return"
+
+// if any breaks refer to the switch, switch is no longer okay
+
+var _ = func() int {
+ print(1)
+L:
+ switch x {
+ case 1:
+ print(2)
+ panic(3)
+ break L
+ default:
+ return 4
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ print(1)
+ switch x {
+ default:
+ return 4
+ break
+ case 1:
+ print(2)
+ panic(3)
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ print(1)
+L:
+ switch x {
+ case 1:
+ print(2)
+ for {
+ break L
+ }
+ default:
+ return 4
+ }
+} // ERROR "missing return"
+
+// type switch with default in which all cases terminate is okay
+
+var _ = func() int {
+ print(1)
+ switch x.(type) {
+ case int:
+ print(2)
+ panic(3)
+ default:
+ return 4
+ }
+}
+
+var _ = func() int {
+ print(1)
+ switch x.(type) {
+ default:
+ return 4
+ case int:
+ print(2)
+ panic(3)
+ }
+}
+
+// if no default or some case doesn't terminate, switch is no longer okay
+
+var _ = func() int {
+ print(1)
+ switch {
+ }
+} // ERROR "missing return"
+
+
+var _ = func() int {
+ print(1)
+ switch x.(type) {
+ case int:
+ print(2)
+ panic(3)
+ case float64:
+ return 4
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ print(1)
+ switch x.(type) {
+ case float64:
+ return 4
+ case int:
+ print(2)
+ panic(3)
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ print(1)
+ switch x.(type) {
+ case int:
+ print(2)
+ panic(3)
+ }
+} // ERROR "missing return"
+
+// if any breaks refer to the switch, switch is no longer okay
+
+var _ = func() int {
+ print(1)
+L:
+ switch x.(type) {
+ case int:
+ print(2)
+ panic(3)
+ break L
+ default:
+ return 4
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ print(1)
+ switch x.(type) {
+ default:
+ return 4
+ break
+ case int:
+ print(2)
+ panic(3)
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ print(1)
+L:
+ switch x.(type) {
+ case int:
+ print(2)
+ for {
+ break L
+ }
+ default:
+ return 4
+ }
+} // ERROR "missing return"
+
+// again, but without the leading print(1).
+// testing that everything works when the terminating statement is first.
+
+var _ = func() int {
+} // ERROR "missing return"
+
+// return is okay
+var _ = func() int {
+ return 2
+}
+
+// goto is okay
+var _ = func() int {
+L:
+ goto L
+}
+
+// panic is okay
+var _ = func() int {
+ panic(2)
+}
+
+// but only builtin panic
+var _ = func() int {
+ var panic = func(int) {}
+ panic(2)
+} // ERROR "missing return"
+
+// block ending in terminating statement is okay
+var _ = func() int {
+ {
+ return 2
+ }
+}
+
+// block ending in terminating statement is okay
+var _ = func() int {
+L:
+ {
+ goto L
+ }
+}
+
+// block ending in terminating statement is okay
+var _ = func() int {
+ {
+ panic(2)
+ }
+}
+
+// adding more code - even though it is dead - now requires a return
+
+var _ = func() int {
+ return 2
+ print(3)
+} // ERROR "missing return"
+
+var _ = func() int {
+L:
+ goto L
+ print(3)
+} // ERROR "missing return"
+
+var _ = func() int {
+ panic(2)
+ print(3)
+} // ERROR "missing return"
+
+var _ = func() int {
+ {
+ return 2
+ print(3)
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+L:
+ {
+ goto L
+ print(3)
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ {
+ panic(2)
+ print(3)
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ {
+ return 2
+ }
+ print(3)
+} // ERROR "missing return"
+
+var _ = func() int {
+L:
+ {
+ goto L
+ }
+ print(3)
+} // ERROR "missing return"
+
+var _ = func() int {
+ {
+ panic(2)
+ }
+ print(3)
+} // ERROR "missing return"
+
+// even an empty dead block triggers the message, because it
+// becomes the final statement.
+
+var _ = func() int {
+ return 2
+ {}
+} // ERROR "missing return"
+
+var _ = func() int {
+L:
+ goto L
+ {}
+} // ERROR "missing return"
+
+var _ = func() int {
+ panic(2)
+ {}
+} // ERROR "missing return"
+
+var _ = func() int {
+ {
+ return 2
+ {}
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+L:
+ {
+ goto L
+ {}
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ {
+ panic(2)
+ {}
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ {
+ return 2
+ }
+ {}
+} // ERROR "missing return"
+
+var _ = func() int {
+L:
+ {
+ goto L
+ }
+ {}
+} // ERROR "missing return"
+
+var _ = func() int {
+ {
+ panic(2)
+ }
+ {}
+} // ERROR "missing return"
+
+// if-else chain with final else and all terminating is okay
+
+var _ = func() int {
+ if x == nil {
+ panic(2)
+ } else {
+ panic(3)
+ }
+}
+
+var _ = func() int {
+L:
+ if x == nil {
+ panic(2)
+ } else {
+ goto L
+ }
+}
+
+var _ = func() int {
+L:
+ if x == nil {
+ panic(2)
+ } else if x == 1 {
+ return 0
+ } else if x != 2 {
+ panic(3)
+ } else {
+ goto L
+ }
+}
+
+// if-else chain missing final else is not okay, even if the
+// conditions cover every possible case.
+
+var _ = func() int {
+ if x == nil {
+ panic(2)
+ } else if x != nil {
+ panic(3)
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ if x == nil {
+ panic(2)
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ if x == nil {
+ panic(2)
+ } else if x == 1 {
+ return 0
+ } else if x != 1 {
+ panic(3)
+ }
+} // ERROR "missing return"
+
+
+// for { loops that never break are okay.
+
+var _ = func() int {
+ for {}
+}
+
+var _ = func() int {
+ for {
+ for {
+ break
+ }
+ }
+}
+
+var _ = func() int {
+ for {
+ L:
+ for {
+ break L
+ }
+ }
+}
+
+// for { loops that break are not okay.
+
+var _ = func() int {
+ for { break }
+} // ERROR "missing return"
+
+var _ = func() int {
+ for {
+ for {
+ }
+ break
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+L:
+ for {
+ for {
+ break L
+ }
+ }
+} // ERROR "missing return"
+
+// if there's a condition - even "true" - the loops are no longer syntactically terminating
+
+var _ = func() int {
+ for x == nil {}
+} // ERROR "missing return"
+
+var _ = func() int {
+ for x == nil {
+ for {
+ break
+ }
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ for x == nil {
+ L:
+ for {
+ break L
+ }
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ for true {}
+} // ERROR "missing return"
+
+var _ = func() int {
+ for true {
+ for {
+ break
+ }
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ for true {
+ L:
+ for {
+ break L
+ }
+ }
+} // ERROR "missing return"
+
+// select in which all cases terminate and none break are okay.
+
+var _ = func() int {
+ select{}
+}
+
+var _ = func() int {
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ }
+}
+
+var _ = func() int {
+ select {
+ case <-c:
+ print(2)
+ for{}
+ }
+}
+
+var _ = func() int {
+L:
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ case c <- 1:
+ print(2)
+ goto L
+ }
+}
+
+var _ = func() int {
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ default:
+ select{}
+ }
+}
+
+// if any cases don't terminate, the select isn't okay anymore
+
+var _ = func() int {
+ select {
+ case <-c:
+ print(2)
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+L:
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ goto L
+ case c <- 1:
+ print(2)
+ }
+} // ERROR "missing return"
+
+
+var _ = func() int {
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ default:
+ print(2)
+ }
+} // ERROR "missing return"
+
+
+// if any breaks refer to the select, the select isn't okay anymore, even if they're dead
+
+var _ = func() int {
+ select{ default: break }
+} // ERROR "missing return"
+
+var _ = func() int {
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ break
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+L:
+ select {
+ case <-c:
+ print(2)
+ for{ break L }
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+L:
+ select {
+ case <-c:
+ print(2)
+ panic("abc")
+ case c <- 1:
+ print(2)
+ break L
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ select {
+ case <-c:
+ panic("abc")
+ default:
+ select{}
+ break
+ }
+} // ERROR "missing return"
+
+// switch with default in which all cases terminate is okay
+
+var _ = func() int {
+ switch x {
+ case 1:
+ print(2)
+ panic(3)
+ default:
+ return 4
+ }
+}
+
+var _ = func() int {
+ switch x {
+ default:
+ return 4
+ case 1:
+ print(2)
+ panic(3)
+ }
+}
+
+var _ = func() int {
+ switch x {
+ case 1:
+ print(2)
+ fallthrough
+ default:
+ return 4
+ }
+}
+
+// if no default or some case doesn't terminate, switch is no longer okay
+
+var _ = func() int {
+ switch {
+ }
+} // ERROR "missing return"
+
+
+var _ = func() int {
+ switch x {
+ case 1:
+ print(2)
+ panic(3)
+ case 2:
+ return 4
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ switch x {
+ case 2:
+ return 4
+ case 1:
+ print(2)
+ panic(3)
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ switch x {
+ case 1:
+ print(2)
+ fallthrough
+ case 2:
+ return 4
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ switch x {
+ case 1:
+ print(2)
+ panic(3)
+ }
+} // ERROR "missing return"
+
+// if any breaks refer to the switch, switch is no longer okay
+
+var _ = func() int {
+L:
+ switch x {
+ case 1:
+ print(2)
+ panic(3)
+ break L
+ default:
+ return 4
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ switch x {
+ default:
+ return 4
+ break
+ case 1:
+ print(2)
+ panic(3)
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+L:
+ switch x {
+ case 1:
+ print(2)
+ for {
+ break L
+ }
+ default:
+ return 4
+ }
+} // ERROR "missing return"
+
+// type switch with default in which all cases terminate is okay
+
+var _ = func() int {
+ switch x.(type) {
+ case int:
+ print(2)
+ panic(3)
+ default:
+ return 4
+ }
+}
+
+var _ = func() int {
+ switch x.(type) {
+ default:
+ return 4
+ case int:
+ print(2)
+ panic(3)
+ }
+}
+
+// if no default or some case doesn't terminate, switch is no longer okay
+
+var _ = func() int {
+ switch {
+ }
+} // ERROR "missing return"
+
+
+var _ = func() int {
+ switch x.(type) {
+ case int:
+ print(2)
+ panic(3)
+ case float64:
+ return 4
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ switch x.(type) {
+ case float64:
+ return 4
+ case int:
+ print(2)
+ panic(3)
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ switch x.(type) {
+ case int:
+ print(2)
+ panic(3)
+ }
+} // ERROR "missing return"
+
+// if any breaks refer to the switch, switch is no longer okay
+
+var _ = func() int {
+L:
+ switch x.(type) {
+ case int:
+ print(2)
+ panic(3)
+ break L
+ default:
+ return 4
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ switch x.(type) {
+ default:
+ return 4
+ break
+ case int:
+ print(2)
+ panic(3)
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+L:
+ switch x.(type) {
+ case int:
+ print(2)
+ for {
+ break L
+ }
+ default:
+ return 4
+ }
+} // ERROR "missing return"
+
+var _ = func() int {
+ switch x.(type) {
+ default:
+ return 4
+ case int, float64:
+ print(2)
+ panic(3)
+ }
+}
+
+/**/
diff --git a/gcc/testsuite/go.test/test/rotate.go b/gcc/testsuite/go.test/test/rotate.go
index aa334b4218c..1d7149702a8 100644
--- a/gcc/testsuite/go.test/test/rotate.go
+++ b/gcc/testsuite/go.test/test/rotate.go
@@ -1,9 +1,6 @@
-// $G $D/$F.go && $L $F.$A &&
-// ./$A.out >tmp.go && $G tmp.go && $L -o $A.out1 tmp.$A && ./$A.out1
-// rm -f tmp.go $A.out1
+// skip
-// NOTE: This test is not run by 'run.go' and so not run by all.bash.
-// To run this test you must use the ./run shell script.
+// NOTE: the actual tests to run are rotate[0123].go
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
@@ -12,8 +9,8 @@
// Generate test of shift and rotate by constants.
// The output is compiled and run.
//
-// The output takes around a gigabyte of memory to compile, link, and run
-// but it is only done during ./run, not in normal builds using run.go.
+// The integer type depends on the value of mode (rotate direction,
+// signedness).
package main
@@ -37,9 +34,7 @@ func main() {
typ := fmt.Sprintf("int%d", 1<<logBits)
fmt.Fprint(b, strings.Replace(checkFunc, "XXX", typ, -1))
fmt.Fprint(b, strings.Replace(checkFunc, "XXX", "u"+typ, -1))
- for mode := 0; mode < 1<<2; mode++ {
- gentest(b, 1<<logBits, mode&1 != 0, mode&2 != 0)
- }
+ gentest(b, 1<<logBits, mode&1 != 0, mode&2 != 0)
}
}
diff --git a/gcc/testsuite/go.test/test/rotate0.go b/gcc/testsuite/go.test/test/rotate0.go
new file mode 100644
index 00000000000..400b225cf7b
--- /dev/null
+++ b/gcc/testsuite/go.test/test/rotate0.go
@@ -0,0 +1,12 @@
+// runoutput ./rotate.go
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Generate test of bit rotations.
+// The output is compiled and run.
+
+package main
+
+const mode = 0
diff --git a/gcc/testsuite/go.test/test/rotate1.go b/gcc/testsuite/go.test/test/rotate1.go
new file mode 100644
index 00000000000..98b0b1c849e
--- /dev/null
+++ b/gcc/testsuite/go.test/test/rotate1.go
@@ -0,0 +1,12 @@
+// runoutput ./rotate.go
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Generate test of bit rotations.
+// The output is compiled and run.
+
+package main
+
+const mode = 1
diff --git a/gcc/testsuite/go.test/test/rotate2.go b/gcc/testsuite/go.test/test/rotate2.go
new file mode 100644
index 00000000000..c50f8ce73bd
--- /dev/null
+++ b/gcc/testsuite/go.test/test/rotate2.go
@@ -0,0 +1,12 @@
+// runoutput ./rotate.go
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Generate test of bit rotations.
+// The output is compiled and run.
+
+package main
+
+const mode = 2
diff --git a/gcc/testsuite/go.test/test/rotate3.go b/gcc/testsuite/go.test/test/rotate3.go
new file mode 100644
index 00000000000..73d47d8524c
--- /dev/null
+++ b/gcc/testsuite/go.test/test/rotate3.go
@@ -0,0 +1,12 @@
+// runoutput ./rotate.go
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Generate test of bit rotations.
+// The output is compiled and run.
+
+package main
+
+const mode = 3
diff --git a/gcc/testsuite/go.test/test/run.go b/gcc/testsuite/go.test/test/run.go
index 10dbceff5d4..5e167d6b0cc 100644
--- a/gcc/testsuite/go.test/test/run.go
+++ b/gcc/testsuite/go.test/test/run.go
@@ -5,7 +5,7 @@
// license that can be found in the LICENSE file.
// Run runs tests in the test directory.
-//
+//
// TODO(bradfitz): docs of some sort, once we figure out how we're changing
// headers of files
package main
@@ -30,10 +30,11 @@ import (
)
var (
- verbose = flag.Bool("v", false, "verbose. if set, parallelism is set to 1.")
- numParallel = flag.Int("n", runtime.NumCPU(), "number of parallel tests to run")
- summary = flag.Bool("summary", false, "show summary of results")
- showSkips = flag.Bool("show_skips", false, "show skipped tests")
+ verbose = flag.Bool("v", false, "verbose. if set, parallelism is set to 1.")
+ numParallel = flag.Int("n", runtime.NumCPU(), "number of parallel tests to run")
+ summary = flag.Bool("summary", false, "show summary of results")
+ showSkips = flag.Bool("show_skips", false, "show skipped tests")
+ runoutputLimit = flag.Int("l", defaultRunOutputLimit(), "number of parallel runoutput tests to run")
)
var (
@@ -53,6 +54,10 @@ var (
// toRun is the channel of tests to run.
// It is nil until the first test is started.
toRun chan *test
+
+ // rungatec controls the max number of runoutput tests
+ // executed in parallel as they can each consume a lot of memory.
+ rungatec chan bool
)
// maxTests is an upper bound on the total number of tests.
@@ -68,6 +73,7 @@ func main() {
}
ratec = make(chan bool, *numParallel)
+ rungatec = make(chan bool, *runoutputLimit)
var err error
letter, err = build.ArchChar(build.Default.GOARCH)
check(err)
@@ -128,7 +134,7 @@ func main() {
if !*verbose && test.err == nil {
continue
}
- fmt.Printf("%-10s %-20s: %s\n", test.action, test.goFileName(), errStr)
+ fmt.Printf("%-20s %-20s: %s\n", test.action, test.goFileName(), errStr)
}
if *summary {
@@ -165,6 +171,26 @@ func goFiles(dir string) []string {
return names
}
+type runCmd func(...string) ([]byte, error)
+
+func compileFile(runcmd runCmd, longname string) (out []byte, err error) {
+ return runcmd("go", "tool", gc, "-e", longname)
+}
+
+func compileInDir(runcmd runCmd, dir string, names ...string) (out []byte, err error) {
+ cmd := []string{"go", "tool", gc, "-e", "-D", ".", "-I", "."}
+ for _, name := range names {
+ cmd = append(cmd, filepath.Join(dir, name))
+ }
+ return runcmd(cmd...)
+}
+
+func linkFile(runcmd runCmd, goname string) (err error) {
+ pfile := strings.Replace(goname, ".go", "."+letter, -1)
+ _, err = runcmd("go", "tool", ld, "-o", "a.exe", "-L", ".", pfile)
+ return
+}
+
// skipError describes why a test was skipped.
type skipError string
@@ -182,13 +208,13 @@ type test struct {
donec chan bool // closed when done
src string
- action string // "compile", "build", "run", "errorcheck", "skip", "runoutput", "compiledir"
+ action string // "compile", "build", etc.
tempDir string
err error
}
-// startTest
+// startTest
func startTest(dir, gofile string) *test {
t := &test{
dir: dir,
@@ -230,6 +256,93 @@ func (t *test) goDirName() string {
return filepath.Join(t.dir, strings.Replace(t.gofile, ".go", ".dir", -1))
}
+func goDirFiles(longdir string) (filter []os.FileInfo, err error) {
+ files, dirErr := ioutil.ReadDir(longdir)
+ if dirErr != nil {
+ return nil, dirErr
+ }
+ for _, gofile := range files {
+ if filepath.Ext(gofile.Name()) == ".go" {
+ filter = append(filter, gofile)
+ }
+ }
+ return
+}
+
+var packageRE = regexp.MustCompile(`(?m)^package (\w+)`)
+
+func goDirPackages(longdir string) ([][]string, error) {
+ files, err := goDirFiles(longdir)
+ if err != nil {
+ return nil, err
+ }
+ var pkgs [][]string
+ m := make(map[string]int)
+ for _, file := range files {
+ name := file.Name()
+ data, err := ioutil.ReadFile(filepath.Join(longdir, name))
+ if err != nil {
+ return nil, err
+ }
+ pkgname := packageRE.FindStringSubmatch(string(data))
+ if pkgname == nil {
+ return nil, fmt.Errorf("cannot find package name in %s", name)
+ }
+ i, ok := m[pkgname[1]]
+ if !ok {
+ i = len(pkgs)
+ pkgs = append(pkgs, nil)
+ m[pkgname[1]] = i
+ }
+ pkgs[i] = append(pkgs[i], name)
+ }
+ return pkgs, nil
+}
+
+// shouldTest looks for build tags in a source file and returns
+// whether the file should be used according to the tags.
+func shouldTest(src string, goos, goarch string) (ok bool, whyNot string) {
+ if idx := strings.Index(src, "\npackage"); idx >= 0 {
+ src = src[:idx]
+ }
+ notgoos := "!" + goos
+ notgoarch := "!" + goarch
+ for _, line := range strings.Split(src, "\n") {
+ line = strings.TrimSpace(line)
+ if strings.HasPrefix(line, "//") {
+ line = line[2:]
+ } else {
+ continue
+ }
+ line = strings.TrimSpace(line)
+ if len(line) == 0 || line[0] != '+' {
+ continue
+ }
+ words := strings.Fields(line)
+ if words[0] == "+build" {
+ for _, word := range words {
+ switch word {
+ case goos, goarch:
+ return true, ""
+ case notgoos, notgoarch:
+ continue
+ default:
+ if word[0] == '!' {
+ // NOT something-else
+ return true, ""
+ }
+ }
+ }
+ // no matching tag found.
+ return false, line
+ }
+ }
+ // no build tags.
+ return true, ""
+}
+
+func init() { checkShouldTest() }
+
// run runs a test.
func (t *test) run() {
defer close(t.donec)
@@ -249,7 +362,18 @@ func (t *test) run() {
t.err = errors.New("double newline not found")
return
}
+ if ok, why := shouldTest(t.src, runtime.GOOS, runtime.GOARCH); !ok {
+ t.action = "skip"
+ if *showSkips {
+ fmt.Printf("%-20s %-20s: %s\n", t.action, t.goFileName(), why)
+ }
+ return
+ }
action := t.src[:pos]
+ if nl := strings.Index(action, "\n"); nl >= 0 && strings.Contains(action[:nl], "+build") {
+ // skip first line
+ action = action[nl+1:]
+ }
if strings.HasPrefix(action, "//") {
action = action[2:]
}
@@ -263,12 +387,15 @@ func (t *test) run() {
}
switch action {
+ case "rundircmpout":
+ action = "rundir"
+ t.action = "rundir"
case "cmpout":
action = "run" // the run case already looks for <dir>/<test>.out files
fallthrough
- case "compile", "compiledir", "build", "run", "runoutput":
+ case "compile", "compiledir", "build", "run", "runoutput", "rundir":
t.action = action
- case "errorcheck":
+ case "errorcheck", "errorcheckdir", "errorcheckoutput":
t.action = action
wantError = true
for len(args) > 0 && strings.HasPrefix(args[0], "-") {
@@ -306,8 +433,12 @@ func (t *test) run() {
cmd.Stderr = &buf
if useTmp {
cmd.Dir = t.tempDir
+ cmd.Env = envForDir(cmd.Dir)
}
err := cmd.Run()
+ if err != nil {
+ err = fmt.Errorf("%s\n%s", err, buf.Bytes())
+ }
return buf.Bytes(), err
}
@@ -328,7 +459,7 @@ func (t *test) run() {
}
} else {
if err != nil {
- t.err = fmt.Errorf("%s\n%s", err, out)
+ t.err = err
return
}
}
@@ -336,66 +467,156 @@ func (t *test) run() {
return
case "compile":
- out, err := runcmd("go", "tool", gc, "-e", "-o", "a."+letter, long)
- if err != nil {
- t.err = fmt.Errorf("%s\n%s", err, out)
- }
+ _, t.err = compileFile(runcmd, long)
case "compiledir":
// Compile all files in the directory in lexicographic order.
longdir := filepath.Join(cwd, t.goDirName())
- files, dirErr := ioutil.ReadDir(longdir)
- if dirErr != nil {
- t.err = dirErr
+ pkgs, err := goDirPackages(longdir)
+ if err != nil {
+ t.err = err
return
}
- for _, gofile := range files {
- if filepath.Ext(gofile.Name()) != ".go" {
- continue
+ for _, gofiles := range pkgs {
+ _, t.err = compileInDir(runcmd, longdir, gofiles...)
+ if t.err != nil {
+ return
}
- afile := strings.Replace(gofile.Name(), ".go", "."+letter, -1)
- out, err := runcmd("go", "tool", gc, "-e", "-D.", "-I.", "-o", afile, filepath.Join(longdir, gofile.Name()))
- if err != nil {
- t.err = fmt.Errorf("%s\n%s", err, out)
+ }
+
+ case "errorcheckdir":
+ // errorcheck all files in lexicographic order
+ // useful for finding importing errors
+ longdir := filepath.Join(cwd, t.goDirName())
+ pkgs, err := goDirPackages(longdir)
+ if err != nil {
+ t.err = err
+ return
+ }
+ for i, gofiles := range pkgs {
+ out, err := compileInDir(runcmd, longdir, gofiles...)
+ if i == len(pkgs)-1 {
+ if wantError && err == nil {
+ t.err = fmt.Errorf("compilation succeeded unexpectedly\n%s", out)
+ return
+ } else if !wantError && err != nil {
+ t.err = err
+ return
+ }
+ } else if err != nil {
+ t.err = err
+ return
+ }
+ var fullshort []string
+ for _, name := range gofiles {
+ fullshort = append(fullshort, filepath.Join(longdir, name), name)
+ }
+ t.err = t.errorCheck(string(out), fullshort...)
+ if t.err != nil {
break
}
}
+ case "rundir":
+ // Compile all files in the directory in lexicographic order.
+ // then link as if the last file is the main package and run it
+ longdir := filepath.Join(cwd, t.goDirName())
+ pkgs, err := goDirPackages(longdir)
+ if err != nil {
+ t.err = err
+ return
+ }
+ for i, gofiles := range pkgs {
+ _, err := compileInDir(runcmd, longdir, gofiles...)
+ if err != nil {
+ t.err = err
+ return
+ }
+ if i == len(pkgs)-1 {
+ err = linkFile(runcmd, gofiles[0])
+ if err != nil {
+ t.err = err
+ return
+ }
+ out, err := runcmd(append([]string{filepath.Join(t.tempDir, "a.exe")}, args...)...)
+ if err != nil {
+ t.err = err
+ return
+ }
+ if strings.Replace(string(out), "\r\n", "\n", -1) != t.expectedOutput() {
+ t.err = fmt.Errorf("incorrect output\n%s", out)
+ }
+ }
+ }
+
case "build":
- out, err := runcmd("go", "build", "-o", "a.exe", long)
+ _, err := runcmd("go", "build", "-o", "a.exe", long)
if err != nil {
- t.err = fmt.Errorf("%s\n%s", err, out)
+ t.err = err
}
case "run":
useTmp = false
out, err := runcmd(append([]string{"go", "run", t.goFileName()}, args...)...)
if err != nil {
- t.err = fmt.Errorf("%s\n%s", err, out)
+ t.err = err
}
if strings.Replace(string(out), "\r\n", "\n", -1) != t.expectedOutput() {
t.err = fmt.Errorf("incorrect output\n%s", out)
}
case "runoutput":
+ rungatec <- true
+ defer func() {
+ <-rungatec
+ }()
useTmp = false
- out, err := runcmd("go", "run", t.goFileName())
+ out, err := runcmd(append([]string{"go", "run", t.goFileName()}, args...)...)
if err != nil {
- t.err = fmt.Errorf("%s\n%s", err, out)
+ t.err = err
}
tfile := filepath.Join(t.tempDir, "tmp__.go")
- err = ioutil.WriteFile(tfile, out, 0666)
- if err != nil {
+ if err := ioutil.WriteFile(tfile, out, 0666); err != nil {
t.err = fmt.Errorf("write tempfile:%s", err)
return
}
out, err = runcmd("go", "run", tfile)
if err != nil {
- t.err = fmt.Errorf("%s\n%s", err, out)
+ t.err = err
}
if string(out) != t.expectedOutput() {
t.err = fmt.Errorf("incorrect output\n%s", out)
}
+
+ case "errorcheckoutput":
+ useTmp = false
+ out, err := runcmd(append([]string{"go", "run", t.goFileName()}, args...)...)
+ if err != nil {
+ t.err = err
+ }
+ tfile := filepath.Join(t.tempDir, "tmp__.go")
+ err = ioutil.WriteFile(tfile, out, 0666)
+ if err != nil {
+ t.err = fmt.Errorf("write tempfile:%s", err)
+ return
+ }
+ cmdline := []string{"go", "tool", gc, "-e", "-o", "a." + letter}
+ cmdline = append(cmdline, flags...)
+ cmdline = append(cmdline, tfile)
+ out, err = runcmd(cmdline...)
+ if wantError {
+ if err == nil {
+ t.err = fmt.Errorf("compilation succeeded unexpectedly\n%s", out)
+ return
+ }
+ } else {
+ if err != nil {
+ t.err = err
+ return
+ }
+ }
+ t.err = t.errorCheck(string(out), tfile, "tmp__.go")
+ return
}
}
@@ -417,7 +638,7 @@ func (t *test) expectedOutput() string {
return string(b)
}
-func (t *test) errorCheck(outStr string, full, short string) (err error) {
+func (t *test) errorCheck(outStr string, fullshort ...string) (err error) {
defer func() {
if *verbose && err != nil {
log.Printf("%s gc output:\n%s", t, outStr)
@@ -434,17 +655,28 @@ func (t *test) errorCheck(outStr string, full, short string) (err error) {
}
if strings.HasPrefix(line, "\t") {
out[len(out)-1] += "\n" + line
- } else {
+ } else if strings.HasPrefix(line, "go tool") {
+ continue
+ } else if strings.TrimSpace(line) != "" {
out = append(out, line)
}
}
// Cut directory name.
for i := range out {
- out[i] = strings.Replace(out[i], full, short, -1)
+ for j := 0; j < len(fullshort); j += 2 {
+ full, short := fullshort[j], fullshort[j+1]
+ out[i] = strings.Replace(out[i], full, short, -1)
+ }
}
- for _, we := range t.wantedErrors() {
+ var want []wantedError
+ for j := 0; j < len(fullshort); j += 2 {
+ full, short := fullshort[j], fullshort[j+1]
+ want = append(want, t.wantedErrors(full, short)...)
+ }
+
+ for _, we := range want {
var errmsgs []string
errmsgs, out = partitionStrings(we.filterRe, out)
if len(errmsgs) == 0 {
@@ -452,6 +684,7 @@ func (t *test) errorCheck(outStr string, full, short string) (err error) {
continue
}
matched := false
+ n := len(out)
for _, errmsg := range errmsgs {
if we.re.MatchString(errmsg) {
matched = true
@@ -460,11 +693,18 @@ func (t *test) errorCheck(outStr string, full, short string) (err error) {
}
}
if !matched {
- errs = append(errs, fmt.Errorf("%s:%d: no match for %q in%s", we.file, we.lineNum, we.reStr, strings.Join(out, "\n")))
+ errs = append(errs, fmt.Errorf("%s:%d: no match for %#q in:\n\t%s", we.file, we.lineNum, we.reStr, strings.Join(out[n:], "\n\t")))
continue
}
}
+ if len(out) > 0 {
+ errs = append(errs, fmt.Errorf("Unmatched Errors:"))
+ for _, errLine := range out {
+ errs = append(errs, fmt.Errorf("%s", errLine))
+ }
+ }
+
if len(errs) == 0 {
return nil
}
@@ -505,8 +745,9 @@ var (
lineRx = regexp.MustCompile(`LINE(([+-])([0-9]+))?`)
)
-func (t *test) wantedErrors() (errs []wantedError) {
- for i, line := range strings.Split(t.src, "\n") {
+func (t *test) wantedErrors(file, short string) (errs []wantedError) {
+ src, _ := ioutil.ReadFile(file)
+ for i, line := range strings.Split(string(src), "\n") {
lineNum := i + 1
if strings.Contains(line, "////") {
// double comment disables ERROR
@@ -519,7 +760,7 @@ func (t *test) wantedErrors() (errs []wantedError) {
all := m[1]
mm := errQuotesRx.FindAllStringSubmatch(all, -1)
if mm == nil {
- log.Fatalf("invalid errchk line in %s: %s", t.goFileName(), line)
+ log.Fatalf("%s:%d: invalid errchk line: %s", t.goFileName(), lineNum, line)
}
for _, m := range mm {
rx := lineRx.ReplaceAllStringFunc(m[1], func(m string) string {
@@ -531,15 +772,19 @@ func (t *test) wantedErrors() (errs []wantedError) {
delta, _ := strconv.Atoi(m[5:])
n -= delta
}
- return fmt.Sprintf("%s:%d", t.gofile, n)
+ return fmt.Sprintf("%s:%d", short, n)
})
- filterPattern := fmt.Sprintf(`^(\w+/)?%s:%d[:[]`, t.gofile, lineNum)
+ re, err := regexp.Compile(rx)
+ if err != nil {
+ log.Fatalf("%s:%d: invalid regexp in ERROR line: %v", t.goFileName(), lineNum, err)
+ }
+ filterPattern := fmt.Sprintf(`^(\w+/)?%s:%d[:[]`, regexp.QuoteMeta(short), lineNum)
errs = append(errs, wantedError{
reStr: rx,
- re: regexp.MustCompile(rx),
+ re: re,
filterRe: regexp.MustCompile(filterPattern),
lineNum: lineNum,
- file: t.gofile,
+ file: short,
})
}
}
@@ -548,60 +793,56 @@ func (t *test) wantedErrors() (errs []wantedError) {
}
var skipOkay = map[string]bool{
- "args.go": true,
- "ddd3.go": true,
- "import3.go": true,
- "import4.go": true,
- "index.go": true,
- "linkx.go": true,
- "method4.go": true,
- "nul1.go": true,
- "rotate.go": true,
- "sigchld.go": true,
- "sinit.go": true,
- "interface/embed1.go": true,
- "interface/private.go": true,
- "interface/recursive2.go": true,
- "dwarf/main.go": true,
- "dwarf/z1.go": true,
- "dwarf/z10.go": true,
- "dwarf/z11.go": true,
- "dwarf/z12.go": true,
- "dwarf/z13.go": true,
- "dwarf/z14.go": true,
- "dwarf/z15.go": true,
- "dwarf/z16.go": true,
- "dwarf/z17.go": true,
- "dwarf/z18.go": true,
- "dwarf/z19.go": true,
- "dwarf/z2.go": true,
- "dwarf/z20.go": true,
- "dwarf/z3.go": true,
- "dwarf/z4.go": true,
- "dwarf/z5.go": true,
- "dwarf/z6.go": true,
- "dwarf/z7.go": true,
- "dwarf/z8.go": true,
- "dwarf/z9.go": true,
- "fixedbugs/bug083.go": true,
- "fixedbugs/bug133.go": true,
- "fixedbugs/bug160.go": true,
- "fixedbugs/bug191.go": true,
- "fixedbugs/bug248.go": true,
- "fixedbugs/bug302.go": true,
- "fixedbugs/bug313.go": true,
- "fixedbugs/bug322.go": true,
- "fixedbugs/bug324.go": true,
- "fixedbugs/bug345.go": true,
- "fixedbugs/bug367.go": true,
- "fixedbugs/bug369.go": true,
- "fixedbugs/bug382.go": true,
- "fixedbugs/bug385_32.go": true,
- "fixedbugs/bug385_64.go": true,
- "fixedbugs/bug414.go": true,
- "fixedbugs/bug424.go": true,
- "fixedbugs/bug429.go": true,
- "fixedbugs/bug437.go": true,
- "bugs/bug395.go": true,
- "bugs/bug434.go": true,
+ "linkx.go": true, // like "run" but wants linker flags
+ "sinit.go": true,
+ "fixedbugs/bug248.go": true, // combines errorcheckdir and rundir in the same dir.
+ "fixedbugs/bug302.go": true, // tests both .$O and .a imports.
+ "fixedbugs/bug345.go": true, // needs the appropriate flags in gc invocation.
+ "fixedbugs/bug369.go": true, // needs compiler flags.
+ "fixedbugs/bug429.go": true, // like "run" but program should fail
+ "bugs/bug395.go": true,
+}
+
+// defaultRunOutputLimit returns the number of runoutput tests that
+// can be executed in parallel.
+func defaultRunOutputLimit() int {
+ const maxArmCPU = 2
+
+ cpu := runtime.NumCPU()
+ if runtime.GOARCH == "arm" && cpu > maxArmCPU {
+ cpu = maxArmCPU
+ }
+ return cpu
+}
+
+// checkShouldTest runs canity checks on the shouldTest function.
+func checkShouldTest() {
+ assert := func(ok bool, _ string) {
+ if !ok {
+ panic("fail")
+ }
+ }
+ assertNot := func(ok bool, _ string) { assert(!ok, "") }
+ assert(shouldTest("// +build linux", "linux", "arm"))
+ assert(shouldTest("// +build !windows", "linux", "arm"))
+ assertNot(shouldTest("// +build !windows", "windows", "amd64"))
+ assertNot(shouldTest("// +build arm 386", "linux", "amd64"))
+ assert(shouldTest("// This is a test.", "os", "arch"))
+}
+
+// envForDir returns a copy of the environment
+// suitable for running in the given directory.
+// The environment is the current process's environment
+// but with an updated $PWD, so that an os.Getwd in the
+// child will be faster.
+func envForDir(dir string) []string {
+ env := os.Environ()
+ for i, kv := range env {
+ if strings.HasPrefix(kv, "PWD=") {
+ env[i] = "PWD=" + dir
+ return env
+ }
+ }
+ env = append(env, "PWD="+dir)
+ return env
}
diff --git a/gcc/testsuite/go.test/test/safe/nousesafe.go b/gcc/testsuite/go.test/test/safe/nousesafe.go
index f61e7fe4f09..fcd25af3154 100644
--- a/gcc/testsuite/go.test/test/safe/nousesafe.go
+++ b/gcc/testsuite/go.test/test/safe/nousesafe.go
@@ -1,4 +1,4 @@
-// $G $D/pkg.go && pack grc pkg.a pkg.$A 2> /dev/null && rm pkg.$A && errchk $G -I. -u $D/main.go
+// $G $D/pkg.go && pack grc pkg.a pkg.$A 2> /dev/null && rm pkg.$A && errchk $G -I . -u $D/main.go
// rm -f pkg.a
// Copyright 2012 The Go Authors. All rights reserved.
diff --git a/gcc/testsuite/go.test/test/safe/usesafe.go b/gcc/testsuite/go.test/test/safe/usesafe.go
index 07c13c1c3a1..5d0829e290b 100644
--- a/gcc/testsuite/go.test/test/safe/usesafe.go
+++ b/gcc/testsuite/go.test/test/safe/usesafe.go
@@ -1,4 +1,4 @@
-// $G $D/pkg.go && pack grcS pkg.a pkg.$A 2> /dev/null && rm pkg.$A && $G -I. -u $D/main.go
+// $G $D/pkg.go && pack grcS pkg.a pkg.$A 2> /dev/null && rm pkg.$A && $G -I . -u $D/main.go
// rm -f pkg.a
// Copyright 2012 The Go Authors. All rights reserved.
diff --git a/gcc/testsuite/go.test/test/sigchld.go b/gcc/testsuite/go.test/test/sigchld.go
index c1cfc2a8d0c..a60d28deaab 100644
--- a/gcc/testsuite/go.test/test/sigchld.go
+++ b/gcc/testsuite/go.test/test/sigchld.go
@@ -1,8 +1,5 @@
-// [ "$GOOS" == windows ] ||
-// ($G $D/$F.go && $L $F.$A && ./$A.out 2>&1 | cmp - $D/$F.out)
-
-// NOTE: This test is not run by 'run.go' and so not run by all.bash.
-// To run this test you must use the ./run shell script.
+// +build !windows
+// cmpout
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
diff --git a/gcc/testsuite/go.test/test/sinit.go b/gcc/testsuite/go.test/test/sinit.go
index ffb8ef75110..5e50e1100a8 100644
--- a/gcc/testsuite/go.test/test/sinit.go
+++ b/gcc/testsuite/go.test/test/sinit.go
@@ -259,3 +259,13 @@ var copy_pt0a = pt0a
var copy_pt0b = pt0b
var copy_pt1 = pt1
var copy_pt1a = pt1a
+
+var _ interface{} = 1
+
+type T1 int
+
+func (t *T1) M() {}
+
+type Mer interface { M() }
+
+var _ Mer = (*T1)(nil)
diff --git a/gcc/testsuite/go.test/test/sizeof.go b/gcc/testsuite/go.test/test/sizeof.go
index a6abdd5c657..9aa95677d47 100644
--- a/gcc/testsuite/go.test/test/sizeof.go
+++ b/gcc/testsuite/go.test/test/sizeof.go
@@ -4,8 +4,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Test unsafe.Sizeof, unsafe.Alignof, and unsafe.Offsetof all return uintptr.
-
package main
import "unsafe"
@@ -18,8 +16,143 @@ var t T
func isUintptr(uintptr) {}
+type T2 struct {
+ A int32
+ U2
+}
+
+type U2 struct {
+ B int32
+ C int32
+}
+
+var t2 T2
+var p2 *T2
+
func main() {
+ // Test unsafe.Sizeof, unsafe.Alignof, and unsafe.Offsetof all return uintptr.
isUintptr(unsafe.Sizeof(t))
isUintptr(unsafe.Alignof(t))
isUintptr(unsafe.Offsetof(t.X))
+
+ // Test correctness of Offsetof with respect to embedded fields (issue 4909).
+ if unsafe.Offsetof(t2.C) != 8 {
+ println(unsafe.Offsetof(t2.C), "!= 8")
+ panic("unsafe.Offsetof(t2.C) != 8")
+ }
+ if unsafe.Offsetof(p2.C) != 8 {
+ println(unsafe.Offsetof(p2.C), "!= 8")
+ panic("unsafe.Offsetof(p2.C) != 8")
+ }
+ if unsafe.Offsetof(t2.U2.C) != 4 {
+ println(unsafe.Offsetof(t2.U2.C), "!= 4")
+ panic("unsafe.Offsetof(t2.U2.C) != 4")
+ }
+ if unsafe.Offsetof(p2.U2.C) != 4 {
+ println(unsafe.Offsetof(p2.U2.C), "!= 4")
+ panic("unsafe.Offsetof(p2.U2.C) != 4")
+ }
+ testDeep()
+ testNotEmbedded()
+}
+
+type (
+ S1 struct {
+ A int32
+ S2
+ }
+ S2 struct {
+ B int32
+ S3
+ }
+ S3 struct {
+ C int32
+ S4
+ }
+ S4 struct {
+ D int32
+ S5
+ }
+ S5 struct {
+ E int32
+ S6
+ }
+ S6 struct {
+ F int32
+ S7
+ }
+ S7 struct {
+ G int32
+ S8
+ }
+ S8 struct {
+ H int32
+ *S1
+ }
+)
+
+func testDeep() {
+ var s1 S1
+ switch {
+ case unsafe.Offsetof(s1.A) != 0:
+ panic("unsafe.Offsetof(s1.A) != 0")
+ case unsafe.Offsetof(s1.B) != 4:
+ panic("unsafe.Offsetof(s1.B) != 4")
+ case unsafe.Offsetof(s1.C) != 8:
+ panic("unsafe.Offsetof(s1.C) != 8")
+ case unsafe.Offsetof(s1.D) != 12:
+ panic("unsafe.Offsetof(s1.D) != 12")
+ case unsafe.Offsetof(s1.E) != 16:
+ panic("unsafe.Offsetof(s1.E) != 16")
+ case unsafe.Offsetof(s1.F) != 20:
+ panic("unsafe.Offsetof(s1.F) != 20")
+ case unsafe.Offsetof(s1.G) != 24:
+ panic("unsafe.Offsetof(s1.G) != 24")
+ case unsafe.Offsetof(s1.H) != 28:
+ panic("unsafe.Offsetof(s1.H) != 28")
+ case unsafe.Offsetof(s1.S1) != 32:
+ panic("unsafe.Offsetof(s1.S1) != 32")
+ case unsafe.Offsetof(s1.S1.S2.S3.S4.S5.S6.S7.S8.S1.S2) != 4:
+ panic("unsafe.Offsetof(s1.S1.S2.S3.S4.S5.S6.S7.S8.S1.S2) != 4")
+ }
+}
+
+func testNotEmbedded() {
+ type T2 struct {
+ B int32
+ C int32
+ }
+ type T1 struct {
+ A int32
+ T2
+ }
+ type T struct {
+ Dummy int32
+ F T1
+ P *T1
+ }
+
+ var t T
+ var p *T
+ switch {
+ case unsafe.Offsetof(t.F.B) != 4:
+ panic("unsafe.Offsetof(t.F.B) != 4")
+ case unsafe.Offsetof(t.F.C) != 8:
+ panic("unsafe.Offsetof(t.F.C) != 8")
+
+ case unsafe.Offsetof(t.P.B) != 4:
+ panic("unsafe.Offsetof(t.P.B) != 4")
+ case unsafe.Offsetof(t.P.C) != 8:
+ panic("unsafe.Offsetof(t.P.C) != 8")
+
+ case unsafe.Offsetof(p.F.B) != 4:
+ panic("unsafe.Offsetof(p.F.B) != 4")
+ case unsafe.Offsetof(p.F.C) != 8:
+ panic("unsafe.Offsetof(p.F.C) != 8")
+
+ case unsafe.Offsetof(p.P.B) != 4:
+ panic("unsafe.Offsetof(p.P.B) != 4")
+ case unsafe.Offsetof(p.P.C) != 8:
+ panic("unsafe.Offsetof(p.P.C) != 8")
+ }
}
diff --git a/gcc/testsuite/go.test/test/stress/maps.go b/gcc/testsuite/go.test/test/stress/maps.go
new file mode 100644
index 00000000000..d022e19ade0
--- /dev/null
+++ b/gcc/testsuite/go.test/test/stress/maps.go
@@ -0,0 +1,111 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "math/rand"
+ "runtime"
+ "sync"
+)
+
+func mapTypes() []MapType {
+ // TODO(bradfitz): bunch more map types of all different key and value types.
+ // Use reflect.MapOf and a program to generate lots of types & struct types.
+ // For now, just one:
+ return []MapType{intMapType{}}
+}
+
+type MapType interface {
+ NewMap() Map
+}
+
+type Map interface {
+ AddItem()
+ DelItem()
+ Len() int
+ GetItem()
+ RangeAll()
+}
+
+func stressMapType(mt MapType, done func()) {
+ defer done()
+ m := mt.NewMap()
+ for m.Len() < 10000 {
+ Println("map at ", m.Len())
+ if m.Len()%100 == 0 {
+ runtime.Gosched()
+ }
+ m.AddItem()
+ m.AddItem()
+ m.DelItem()
+ var wg sync.WaitGroup
+ const numGets = 10
+ wg.Add(numGets)
+ for i := 0; i < numGets; i++ {
+ go func(i int) {
+ if i&1 == 0 {
+ m.GetItem()
+ } else {
+ m.RangeAll()
+ }
+ wg.Done()
+ }(i)
+ }
+ wg.Wait()
+ }
+ for m.Len() > 0 {
+ m.DelItem()
+ }
+}
+
+type intMapType struct{}
+
+func (intMapType) NewMap() Map {
+ return make(intMap)
+}
+
+var deadcafe = []byte("\xDE\xAD\xCA\xFE")
+
+type intMap map[int][]byte
+
+func (m intMap) AddItem() {
+ s0 := len(m)
+ for len(m) == s0 {
+ key := rand.Intn(s0 + 1)
+ m[key] = make([]byte, rand.Intn(64<<10))
+ }
+}
+
+func (m intMap) DelItem() {
+ for k := range m {
+ delete(m, k)
+ return
+ }
+}
+
+func (m intMap) GetItem() {
+ key := rand.Intn(len(m))
+ if s, ok := m[key]; ok {
+ copy(s, deadcafe)
+ }
+}
+
+func (m intMap) Len() int { return len(m) }
+
+func (m intMap) RangeAll() {
+ for _ = range m {
+ }
+}
+
+func stressMaps() {
+ for {
+ var wg sync.WaitGroup
+ for _, mt := range mapTypes() {
+ wg.Add(1)
+ go stressMapType(mt, wg.Done)
+ }
+ wg.Wait()
+ }
+}
diff --git a/gcc/testsuite/go.test/test/stress/parsego.go b/gcc/testsuite/go.test/test/stress/parsego.go
new file mode 100644
index 00000000000..a781f19937b
--- /dev/null
+++ b/gcc/testsuite/go.test/test/stress/parsego.go
@@ -0,0 +1,220 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "go/ast"
+ "go/parser"
+ "go/token"
+ "os"
+ "path"
+ "runtime"
+ "strings"
+)
+
+func isGoFile(dir os.FileInfo) bool {
+ return !dir.IsDir() &&
+ !strings.HasPrefix(dir.Name(), ".") && // ignore .files
+ path.Ext(dir.Name()) == ".go"
+}
+
+func isPkgFile(dir os.FileInfo) bool {
+ return isGoFile(dir) &&
+ !strings.HasSuffix(dir.Name(), "_test.go") // ignore test files
+}
+
+func pkgName(filename string) string {
+ file, err := parser.ParseFile(token.NewFileSet(), filename, nil, parser.PackageClauseOnly)
+ if err != nil || file == nil {
+ return ""
+ }
+ return file.Name.Name
+}
+
+func parseDir(dirpath string) map[string]*ast.Package {
+ // the package name is the directory name within its parent.
+ // (use dirname instead of path because dirname is clean; it
+ // has no trailing '/')
+ _, pkgname := path.Split(dirpath)
+
+ // filter function to select the desired .go files
+ filter := func(d os.FileInfo) bool {
+ if isPkgFile(d) {
+ // Some directories contain main packages: Only accept
+ // files that belong to the expected package so that
+ // parser.ParsePackage doesn't return "multiple packages
+ // found" errors.
+ // Additionally, accept the special package name
+ // fakePkgName if we are looking at cmd documentation.
+ name := pkgName(dirpath + "/" + d.Name())
+ return name == pkgname
+ }
+ return false
+ }
+
+ // get package AST
+ pkgs, err := parser.ParseDir(token.NewFileSet(), dirpath, filter, parser.ParseComments)
+ if err != nil {
+ println("parse", dirpath, err.Error())
+ panic("go ParseDir fail: " + err.Error())
+ }
+ return pkgs
+}
+
+func stressParseGo() {
+ pkgroot := runtime.GOROOT() + "/src/pkg/"
+ for {
+ m := make(map[string]map[string]*ast.Package)
+ for _, pkg := range packages {
+ m[pkg] = parseDir(pkgroot + pkg)
+ Println("parsed go package", pkg)
+ }
+ }
+}
+
+// find . -type d -not -path "./exp" -not -path "./exp/*" -printf "\t\"%p\",\n" | sort | sed "s/\.\///" | grep -v testdata
+var packages = []string{
+ "archive",
+ "archive/tar",
+ "archive/zip",
+ "bufio",
+ "builtin",
+ "bytes",
+ "compress",
+ "compress/bzip2",
+ "compress/flate",
+ "compress/gzip",
+ "compress/lzw",
+ "compress/zlib",
+ "container",
+ "container/heap",
+ "container/list",
+ "container/ring",
+ "crypto",
+ "crypto/aes",
+ "crypto/cipher",
+ "crypto/des",
+ "crypto/dsa",
+ "crypto/ecdsa",
+ "crypto/elliptic",
+ "crypto/hmac",
+ "crypto/md5",
+ "crypto/rand",
+ "crypto/rc4",
+ "crypto/rsa",
+ "crypto/sha1",
+ "crypto/sha256",
+ "crypto/sha512",
+ "crypto/subtle",
+ "crypto/tls",
+ "crypto/x509",
+ "crypto/x509/pkix",
+ "database",
+ "database/sql",
+ "database/sql/driver",
+ "debug",
+ "debug/dwarf",
+ "debug/elf",
+ "debug/gosym",
+ "debug/macho",
+ "debug/pe",
+ "encoding",
+ "encoding/ascii85",
+ "encoding/asn1",
+ "encoding/base32",
+ "encoding/base64",
+ "encoding/binary",
+ "encoding/csv",
+ "encoding/gob",
+ "encoding/hex",
+ "encoding/json",
+ "encoding/pem",
+ "encoding/xml",
+ "errors",
+ "expvar",
+ "flag",
+ "fmt",
+ "go",
+ "go/ast",
+ "go/build",
+ "go/doc",
+ "go/format",
+ "go/parser",
+ "go/printer",
+ "go/scanner",
+ "go/token",
+ "hash",
+ "hash/adler32",
+ "hash/crc32",
+ "hash/crc64",
+ "hash/fnv",
+ "html",
+ "html/template",
+ "image",
+ "image/color",
+ "image/draw",
+ "image/gif",
+ "image/jpeg",
+ "image/png",
+ "index",
+ "index/suffixarray",
+ "io",
+ "io/ioutil",
+ "log",
+ "log/syslog",
+ "math",
+ "math/big",
+ "math/cmplx",
+ "math/rand",
+ "mime",
+ "mime/multipart",
+ "net",
+ "net/http",
+ "net/http/cgi",
+ "net/http/cookiejar",
+ "net/http/fcgi",
+ "net/http/httptest",
+ "net/http/httputil",
+ "net/http/pprof",
+ "net/mail",
+ "net/rpc",
+ "net/rpc/jsonrpc",
+ "net/smtp",
+ "net/textproto",
+ "net/url",
+ "os",
+ "os/exec",
+ "os/signal",
+ "os/user",
+ "path",
+ "path/filepath",
+ "reflect",
+ "regexp",
+ "regexp/syntax",
+ "runtime",
+ "runtime/cgo",
+ "runtime/debug",
+ "runtime/pprof",
+ "runtime/race",
+ "sort",
+ "strconv",
+ "strings",
+ "sync",
+ "sync/atomic",
+ "syscall",
+ "testing",
+ "testing/iotest",
+ "testing/quick",
+ "text",
+ "text/scanner",
+ "text/tabwriter",
+ "text/template",
+ "text/template/parse",
+ "time",
+ "unicode",
+ "unicode/utf16",
+ "unicode/utf8",
+ "unsafe",
+}
diff --git a/gcc/testsuite/go.test/test/stress/runstress.go b/gcc/testsuite/go.test/test/stress/runstress.go
new file mode 100644
index 00000000000..b5adf6a4a56
--- /dev/null
+++ b/gcc/testsuite/go.test/test/stress/runstress.go
@@ -0,0 +1,164 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// The runstress tool stresses the runtime.
+//
+// It runs forever and should never fail. It tries to stress the garbage collector,
+// maps, channels, the network, and everything else provided by the runtime.
+package main
+
+import (
+ "flag"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "log"
+ "math/rand"
+ "net"
+ "net/http"
+ "net/http/httptest"
+ "os/exec"
+ "strconv"
+ "time"
+)
+
+var (
+ v = flag.Bool("v", false, "verbose")
+ doMaps = flag.Bool("maps", true, "stress maps")
+ doExec = flag.Bool("exec", true, "stress exec")
+ doChan = flag.Bool("chan", true, "stress channels")
+ doNet = flag.Bool("net", true, "stress networking")
+ doParseGo = flag.Bool("parsego", true, "stress parsing Go (generates garbage)")
+)
+
+func Println(a ...interface{}) {
+ if *v {
+ log.Println(a...)
+ }
+}
+
+func dialStress(a net.Addr) {
+ for {
+ d := net.Dialer{Timeout: time.Duration(rand.Intn(1e9))}
+ c, err := d.Dial("tcp", a.String())
+ if err == nil {
+ Println("did dial")
+ go func() {
+ time.Sleep(time.Duration(rand.Intn(500)) * time.Millisecond)
+ c.Close()
+ Println("closed dial")
+ }()
+ }
+ // Don't run out of ephermeral ports too quickly:
+ time.Sleep(250 * time.Millisecond)
+ }
+}
+
+func stressNet() {
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ size, _ := strconv.Atoi(r.FormValue("size"))
+ w.Write(make([]byte, size))
+ }))
+ go dialStress(ts.Listener.Addr())
+ for {
+ size := rand.Intn(128 << 10)
+ res, err := http.Get(fmt.Sprintf("%s/?size=%d", ts.URL, size))
+ if err != nil {
+ log.Fatalf("stressNet: http Get error: %v", err)
+ }
+ if res.StatusCode != 200 {
+ log.Fatalf("stressNet: Status code = %d", res.StatusCode)
+ }
+ n, err := io.Copy(ioutil.Discard, res.Body)
+ if err != nil {
+ log.Fatalf("stressNet: io.Copy: %v", err)
+ }
+ if n != int64(size) {
+ log.Fatalf("stressNet: copied = %d; want %d", n, size)
+ }
+ res.Body.Close()
+ Println("did http", size)
+ }
+}
+
+func doAnExec() {
+ exit := rand.Intn(2)
+ wantOutput := fmt.Sprintf("output-%d", rand.Intn(1e9))
+ cmd := exec.Command("/bin/sh", "-c", fmt.Sprintf("echo %s; exit %d", wantOutput, exit))
+ out, err := cmd.CombinedOutput()
+ if exit == 1 {
+ if err == nil {
+ log.Fatal("stressExec: unexpected exec success")
+ }
+ return
+ }
+ if err != nil {
+ log.Fatalf("stressExec: exec failure: %v: %s", err, out)
+ }
+ wantOutput += "\n"
+ if string(out) != wantOutput {
+ log.Fatalf("stressExec: exec output = %q; want %q", out, wantOutput)
+ }
+ Println("did exec")
+}
+
+func stressExec() {
+ gate := make(chan bool, 10) // max execs at once
+ for {
+ gate <- true
+ go func() {
+ doAnExec()
+ <-gate
+ }()
+ }
+}
+
+func ringf(in <-chan int, out chan<- int, donec chan<- bool) {
+ for {
+ n := <-in
+ if n == 0 {
+ donec <- true
+ return
+ }
+ out <- n - 1
+ }
+}
+
+func threadRing(bufsize int) {
+ const N = 100
+ donec := make(chan bool)
+ one := make(chan int, bufsize) // will be input to thread 1
+ var in, out chan int = nil, one
+ for i := 1; i <= N-1; i++ {
+ in, out = out, make(chan int, bufsize)
+ go ringf(in, out, donec)
+ }
+ go ringf(out, one, donec)
+ one <- N
+ <-donec
+ Println("did threadring of", bufsize)
+}
+
+func stressChannels() {
+ for {
+ threadRing(0)
+ threadRing(1)
+ }
+}
+
+func main() {
+ flag.Parse()
+ for want, f := range map[*bool]func(){
+ doMaps: stressMaps,
+ doNet: stressNet,
+ doExec: stressExec,
+ doChan: stressChannels,
+ doParseGo: stressParseGo,
+ } {
+ if *want {
+ go f()
+ }
+ }
+ select {}
+}
diff --git a/gcc/testsuite/go.test/test/string_lit.go b/gcc/testsuite/go.test/test/string_lit.go
index 457faaa88cd..fea6f553d10 100644
--- a/gcc/testsuite/go.test/test/string_lit.go
+++ b/gcc/testsuite/go.test/test/string_lit.go
@@ -33,6 +33,7 @@ func assert(a, b, c string) {
print("\ta[", i, "] = ", ac, "; b[", i, "] =", bc, "\n")
}
}
+ panic("string_lit")
}
}
@@ -110,7 +111,7 @@ func main() {
r = -1
s = string(r)
assert(s, "\xef\xbf\xbd", "negative rune")
-
+
// the large rune tests again, this time using constants instead of a variable.
// these conversions will be done at compile time.
s = string(0x10ffff) // largest rune value
diff --git a/gcc/testsuite/go.test/test/switch.go b/gcc/testsuite/go.test/test/switch.go
index fd8748b9bce..5e1d85bb687 100644
--- a/gcc/testsuite/go.test/test/switch.go
+++ b/gcc/testsuite/go.test/test/switch.go
@@ -305,11 +305,40 @@ func main() {
assert(false, "i should be true")
}
+ // switch on interface with constant cases differing by type.
+ // was rejected by compiler: see issue 4781
+ type T int
+ type B bool
+ type F float64
+ type S string
+ switch i := interface{}(float64(1.0)); i {
+ case nil:
+ assert(false, "i should be float64(1.0)")
+ case (*int)(nil):
+ assert(false, "i should be float64(1.0)")
+ case 1:
+ assert(false, "i should be float64(1.0)")
+ case T(1):
+ assert(false, "i should be float64(1.0)")
+ case F(1.0):
+ assert(false, "i should be float64(1.0)")
+ case 1.0:
+ assert(true, "true")
+ case "hello":
+ assert(false, "i should be float64(1.0)")
+ case S("hello"):
+ assert(false, "i should be float64(1.0)")
+ case true, B(false):
+ assert(false, "i should be float64(1.0)")
+ case false, B(true):
+ assert(false, "i should be float64(1.0)")
+ }
+
// switch on array.
switch ar := [3]int{1, 2, 3}; ar {
- case [3]int{1,2,3}:
+ case [3]int{1, 2, 3}:
assert(true, "[1 2 3]")
- case [3]int{4,5,6}:
+ case [3]int{4, 5, 6}:
assert(false, "ar should be [1 2 3]")
default:
assert(false, "ar should be [1 2 3]")
@@ -327,12 +356,48 @@ func main() {
assert(false, "c1 did not match itself")
}
+ // empty switch
+ switch {
+ }
+
+ // empty switch with default case.
+ fired = false
+ switch {
+ default:
+ fired = true
+ }
+ assert(fired, "fail")
+
+ // Default and fallthrough.
+ count = 0
+ switch {
+ default:
+ count++
+ fallthrough
+ case false:
+ count++
+ }
+ assert(count == 2, "fail")
+
+ // fallthrough to default, which is not at end.
+ count = 0
+ switch i5 {
+ case 5:
+ count++
+ fallthrough
+ default:
+ count++
+ case 6:
+ count++
+ }
+ assert(count == 2, "fail")
+
i := 0
switch x := 5; {
- case i < x:
- os.Exit(0)
- case i == x:
- case i > x:
- os.Exit(1)
+ case i < x:
+ os.Exit(0)
+ case i == x:
+ case i > x:
+ os.Exit(1)
}
}
diff --git a/gcc/testsuite/go.test/test/switch4.go b/gcc/testsuite/go.test/test/switch4.go
new file mode 100644
index 00000000000..f38efe68c6e
--- /dev/null
+++ b/gcc/testsuite/go.test/test/switch4.go
@@ -0,0 +1,36 @@
+// errorcheck
+
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Verify that erroneous switch statements are detected by the compiler.
+// Does not compile.
+
+package main
+
+type I interface {
+ M()
+}
+
+func bad() {
+
+ i5 := 5
+ switch i5 {
+ case 5:
+ fallthrough // ERROR "cannot fallthrough final case in switch"
+ }
+}
+
+func good() {
+ var i interface{}
+ var s string
+
+ switch i {
+ case s:
+ }
+
+ switch s {
+ case i:
+ }
+}
diff --git a/gcc/testsuite/go.test/test/testlib b/gcc/testsuite/go.test/test/testlib
index 29de7672ce1..de138b1d19d 100644
--- a/gcc/testsuite/go.test/test/testlib
+++ b/gcc/testsuite/go.test/test/testlib
@@ -5,23 +5,101 @@
# These function names are also known to
# (and are the plan for transitioning to) run.go.
+# helper (not known to run.go)
+# group file list by packages and return list of packages
+# each package is a comma-separated list of go files.
+pkgs() {
+ pkglist=$(grep -h '^package ' $* | awk '{print $2}' | sort -u)
+ for p in $pkglist
+ do
+ echo $(grep -l "^package $p\$" $*) | tr ' ' ,
+ done | sort
+}
+
+# +build aborts execution if the supplied tags don't match,
+# i.e. none of the tags (x or !x) matches GOARCH or GOOS.
++build() {
+ if (( $# == 0 )); then
+ return
+ fi
+ for tag; do
+ case $tag in
+ $GOARCH|$GOOS)
+ #echo >&2 "match $tag in $1"
+ return # don't exclude.
+ ;;
+ '!'$GOARCH|'!'$GOOS)
+ ;;
+ '!'*)
+ # not x where x is neither GOOS nor GOARCH.
+ #echo >&2 "match $tag in $1"
+ return # don't exclude
+ ;;
+ esac
+ done
+ # no match.
+ exit 0
+}
+
compile() {
$G $D/$F.go
}
compiledir() {
- for gofile in $D/$F.dir/*.go
+ for pkg in $(pkgs $D/$F.dir/*.go)
+ do
+ $G -I . $(echo $pkg | tr , ' ') || return 1
+ done
+}
+
+errorcheckdir() {
+ lastzero=""
+ if [ "$1" = "-0" ]; then
+ lastzero="-0"
+ fi
+ pkgs=$(pkgs $D/$F.dir/*.go)
+ for pkg in $pkgs.last
do
- $G -I. "$gofile" || return 1
+ zero="-0"
+ case $pkg in
+ *.last)
+ pkg=$(echo $pkg |sed 's/\.last$//')
+ zero=$lastzero
+ esac
+ errchk $zero $G -D . -I . -e $(echo $pkg | tr , ' ')
done
}
+rundir() {
+ lastfile=""
+ for pkg in $(pkgs $D/$F.dir/*.go)
+ do
+ name=$(echo $pkg | sed 's/\.go.*//; s/.*\///')
+ $G -D . -I . -e $(echo $pkg | tr , ' ') || return 1
+ lastfile=$name
+ done
+ $L -o $A.out -L . $lastfile.$A
+ ./$A.out
+}
+
+rundircmpout() {
+ lastfile=""
+ for pkg in $(pkgs $D/$F.dir/*.go)
+ do
+ name=$(echo $pkg | sed 's/\.go.*//; s/.*\///')
+ $G -D . -I . -e $(echo $pkg | tr , ' ') || return 1
+ lastfile=$name
+ done
+ $L -o $A.out -L . $lastfile.$A
+ ./$A.out 2>&1 | cmp - $D/$F.out
+}
+
build() {
$G $D/$F.go && $L $F.$A
}
runoutput() {
- go run "$D/$F.go" > tmp.go
+ go run "$D/$F.go" "$@" > tmp.go
go run tmp.go
}
@@ -56,6 +134,16 @@ errorcheck() {
errchk $zero $G -e $* $D/$F.go
}
+errorcheckoutput() {
+ zero=""
+ if [ "$1" = "-0" ]; then
+ zero="-0"
+ shift
+ fi
+ go run "$D/$F.go" "$@" > tmp.go
+ errchk $zero $G -e tmp.go
+}
+
skip() {
true
}
diff --git a/gcc/testsuite/go.test/test/torture.go b/gcc/testsuite/go.test/test/torture.go
new file mode 100644
index 00000000000..bbf6d347d99
--- /dev/null
+++ b/gcc/testsuite/go.test/test/torture.go
@@ -0,0 +1,339 @@
+// compile
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Various tests for expressions with high complexity.
+
+package main
+
+// Concatenate 16 4-bit integers into a 64-bit number.
+func concat(s *[16]byte) uint64 {
+ r := (((((((((((((((uint64(s[0])<<4|
+ uint64(s[1]))<<4|
+ uint64(s[2]))<<4|
+ uint64(s[3]))<<4|
+ uint64(s[4]))<<4|
+ uint64(s[5]))<<4|
+ uint64(s[6]))<<4|
+ uint64(s[7]))<<4|
+ uint64(s[8]))<<4|
+ uint64(s[9]))<<4|
+ uint64(s[10]))<<4|
+ uint64(s[11]))<<4|
+ uint64(s[12]))<<4|
+ uint64(s[13]))<<4|
+ uint64(s[14]))<<4 |
+ uint64(s[15]))
+ return r
+}
+
+// Compute the determinant of a 4x4-matrix by the sum
+// over all index permutations.
+func determinant(m [4][4]float64) float64 {
+ return m[0][0]*m[1][1]*m[2][2]*m[3][3] -
+ m[0][0]*m[1][1]*m[2][3]*m[3][2] -
+ m[0][0]*m[1][2]*m[2][1]*m[3][3] +
+ m[0][0]*m[1][2]*m[2][3]*m[3][1] +
+ m[0][0]*m[1][3]*m[2][1]*m[3][2] -
+ m[0][0]*m[1][3]*m[2][2]*m[3][1] -
+ m[0][1]*m[1][0]*m[2][2]*m[3][3] +
+ m[0][1]*m[1][0]*m[2][3]*m[3][2] +
+ m[0][1]*m[1][2]*m[2][0]*m[3][3] -
+ m[0][1]*m[1][2]*m[2][3]*m[3][0] -
+ m[0][1]*m[1][3]*m[2][0]*m[3][2] +
+ m[0][1]*m[1][3]*m[2][2]*m[3][0] +
+ m[0][2]*m[1][0]*m[2][1]*m[3][3] -
+ m[0][2]*m[1][0]*m[2][3]*m[3][1] -
+ m[0][2]*m[1][1]*m[2][0]*m[3][3] +
+ m[0][2]*m[1][1]*m[2][3]*m[3][0] +
+ m[0][2]*m[1][3]*m[2][0]*m[3][1] -
+ m[0][2]*m[1][3]*m[2][1]*m[3][0] -
+ m[0][3]*m[1][0]*m[2][1]*m[3][2] +
+ m[0][3]*m[1][0]*m[2][2]*m[3][1] +
+ m[0][3]*m[1][1]*m[2][0]*m[3][2] -
+ m[0][3]*m[1][1]*m[2][2]*m[3][0] -
+ m[0][3]*m[1][2]*m[2][0]*m[3][1] +
+ m[0][3]*m[1][2]*m[2][1]*m[3][0]
+}
+
+// Compute the determinant of a 4x4-matrix by the sum
+// over all index permutations.
+func determinantInt(m [4][4]int) int {
+ return m[0][0]*m[1][1]*m[2][2]*m[3][3] -
+ m[0][0]*m[1][1]*m[2][3]*m[3][2] -
+ m[0][0]*m[1][2]*m[2][1]*m[3][3] +
+ m[0][0]*m[1][2]*m[2][3]*m[3][1] +
+ m[0][0]*m[1][3]*m[2][1]*m[3][2] -
+ m[0][0]*m[1][3]*m[2][2]*m[3][1] -
+ m[0][1]*m[1][0]*m[2][2]*m[3][3] +
+ m[0][1]*m[1][0]*m[2][3]*m[3][2] +
+ m[0][1]*m[1][2]*m[2][0]*m[3][3] -
+ m[0][1]*m[1][2]*m[2][3]*m[3][0] -
+ m[0][1]*m[1][3]*m[2][0]*m[3][2] +
+ m[0][1]*m[1][3]*m[2][2]*m[3][0] +
+ m[0][2]*m[1][0]*m[2][1]*m[3][3] -
+ m[0][2]*m[1][0]*m[2][3]*m[3][1] -
+ m[0][2]*m[1][1]*m[2][0]*m[3][3] +
+ m[0][2]*m[1][1]*m[2][3]*m[3][0] +
+ m[0][2]*m[1][3]*m[2][0]*m[3][1] -
+ m[0][2]*m[1][3]*m[2][1]*m[3][0] -
+ m[0][3]*m[1][0]*m[2][1]*m[3][2] +
+ m[0][3]*m[1][0]*m[2][2]*m[3][1] +
+ m[0][3]*m[1][1]*m[2][0]*m[3][2] -
+ m[0][3]*m[1][1]*m[2][2]*m[3][0] -
+ m[0][3]*m[1][2]*m[2][0]*m[3][1] +
+ m[0][3]*m[1][2]*m[2][1]*m[3][0]
+}
+
+// Compute the determinant of a 4x4-matrix by the sum
+// over all index permutations.
+func determinantByte(m [4][4]byte) byte {
+ return m[0][0]*m[1][1]*m[2][2]*m[3][3] -
+ m[0][0]*m[1][1]*m[2][3]*m[3][2] -
+ m[0][0]*m[1][2]*m[2][1]*m[3][3] +
+ m[0][0]*m[1][2]*m[2][3]*m[3][1] +
+ m[0][0]*m[1][3]*m[2][1]*m[3][2] -
+ m[0][0]*m[1][3]*m[2][2]*m[3][1] -
+ m[0][1]*m[1][0]*m[2][2]*m[3][3] +
+ m[0][1]*m[1][0]*m[2][3]*m[3][2] +
+ m[0][1]*m[1][2]*m[2][0]*m[3][3] -
+ m[0][1]*m[1][2]*m[2][3]*m[3][0] -
+ m[0][1]*m[1][3]*m[2][0]*m[3][2] +
+ m[0][1]*m[1][3]*m[2][2]*m[3][0] +
+ m[0][2]*m[1][0]*m[2][1]*m[3][3] -
+ m[0][2]*m[1][0]*m[2][3]*m[3][1] -
+ m[0][2]*m[1][1]*m[2][0]*m[3][3] +
+ m[0][2]*m[1][1]*m[2][3]*m[3][0] +
+ m[0][2]*m[1][3]*m[2][0]*m[3][1] -
+ m[0][2]*m[1][3]*m[2][1]*m[3][0] -
+ m[0][3]*m[1][0]*m[2][1]*m[3][2] +
+ m[0][3]*m[1][0]*m[2][2]*m[3][1] +
+ m[0][3]*m[1][1]*m[2][0]*m[3][2] -
+ m[0][3]*m[1][1]*m[2][2]*m[3][0] -
+ m[0][3]*m[1][2]*m[2][0]*m[3][1] +
+ m[0][3]*m[1][2]*m[2][1]*m[3][0]
+}
+
+type A []A
+
+// A sequence of constant indexings.
+func IndexChain1(s A) A {
+ return s[0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0]
+}
+
+// A sequence of non-constant indexings.
+func IndexChain2(s A, i int) A {
+ return s[i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i]
+}
+
+// Another sequence of indexings.
+func IndexChain3(s []int) int {
+ return s[s[s[s[s[s[s[s[s[s[s[s[s[s[s[s[s[s[s[s[s[0]]]]]]]]]]]]]]]]]]]]]
+}
+
+// A right-leaning tree of byte multiplications.
+func righttree(a, b, c, d uint8) uint8 {
+ return a * (b * (c * (d *
+ (a * (b * (c * (d *
+ (a * (b * (c * (d *
+ (a * (b * (c * (d *
+ (a * (b * (c * (d *
+ a * (b * (c * d)))))))))))))))))))))
+
+}
+
+// A left-leaning tree of byte multiplications.
+func lefttree(a, b, c, d uint8) uint8 {
+ return ((((((((((((((((((a * b) * c) * d *
+ a) * b) * c) * d *
+ a) * b) * c) * d *
+ a) * b) * c) * d *
+ a) * b) * c) * d *
+ a) * b) * c) * d)
+}
+
+type T struct {
+ Next I
+}
+
+type I interface{}
+
+// A chains of type assertions.
+func ChainT(t *T) *T {
+ return t.
+ Next.(*T).
+ Next.(*T).
+ Next.(*T).
+ Next.(*T).
+ Next.(*T).
+ Next.(*T).
+ Next.(*T).
+ Next.(*T).
+ Next.(*T).
+ Next.(*T).
+ Next.(*T).
+ Next.(*T).
+ Next.(*T).
+ Next.(*T).
+ Next.(*T).
+ Next.(*T).
+ Next.(*T).
+ Next.(*T).
+ Next.(*T).
+ Next.(*T)
+}
+
+type U struct {
+ Children []J
+}
+
+func (u *U) Child(n int) J { return u.Children[n] }
+
+type J interface {
+ Child(n int) J
+}
+
+func ChainUAssert(u *U) *U {
+ return u.Child(0).(*U).
+ Child(0).(*U).
+ Child(0).(*U).
+ Child(0).(*U).
+ Child(0).(*U).
+ Child(0).(*U).
+ Child(0).(*U).
+ Child(0).(*U).
+ Child(0).(*U).
+ Child(0).(*U).
+ Child(0).(*U).
+ Child(0).(*U).
+ Child(0).(*U).
+ Child(0).(*U).
+ Child(0).(*U).
+ Child(0).(*U).
+ Child(0).(*U).
+ Child(0).(*U).
+ Child(0).(*U).
+ Child(0).(*U).
+ Child(0).(*U).
+ Child(0).(*U)
+}
+
+func ChainUNoAssert(u *U) *U {
+ return u.Child(0).
+ Child(0).
+ Child(0).
+ Child(0).
+ Child(0).
+ Child(0).
+ Child(0).
+ Child(0).
+ Child(0).
+ Child(0).
+ Child(0).
+ Child(0).
+ Child(0).
+ Child(0).
+ Child(0).
+ Child(0).
+ Child(0).
+ Child(0).
+ Child(0).
+ Child(0).
+ Child(0).
+ Child(0).(*U)
+}
+
+// Type assertions and slice indexing. See issue 4207.
+func ChainAssertIndex(u *U) J {
+ return u.
+ Children[0].(*U).
+ Children[0].(*U).
+ Children[0].(*U).
+ Children[0].(*U).
+ Children[0].(*U).
+ Children[0].(*U).
+ Children[0].(*U).
+ Children[0].(*U).
+ Children[0].(*U).
+ Children[0].(*U).
+ Children[0].(*U).
+ Children[0].(*U).
+ Children[0].(*U).
+ Children[0]
+}
+
+type UArr struct {
+ Children [2]J
+}
+
+func (u *UArr) Child(n int) J { return u.Children[n] }
+
+func ChainAssertArrayIndex(u *UArr) J {
+ return u.
+ Children[0].(*UArr).
+ Children[0].(*UArr).
+ Children[0].(*UArr).
+ Children[0].(*UArr).
+ Children[0].(*UArr).
+ Children[0].(*UArr).
+ Children[0].(*UArr).
+ Children[0].(*UArr).
+ Children[0].(*UArr).
+ Children[0].(*UArr).
+ Children[0].(*UArr).
+ Children[0].(*UArr).
+ Children[0].(*UArr).
+ Children[0]
+}
+
+type UArrPtr struct {
+ Children *[2]J
+}
+
+func (u *UArrPtr) Child(n int) J { return u.Children[n] }
+
+func ChainAssertArrayptrIndex(u *UArrPtr) J {
+ return u.
+ Children[0].(*UArrPtr).
+ Children[0].(*UArrPtr).
+ Children[0].(*UArrPtr).
+ Children[0].(*UArrPtr).
+ Children[0].(*UArrPtr).
+ Children[0].(*UArrPtr).
+ Children[0].(*UArrPtr).
+ Children[0].(*UArrPtr).
+ Children[0].(*UArrPtr).
+ Children[0].(*UArrPtr).
+ Children[0].(*UArrPtr).
+ Children[0].(*UArrPtr).
+ Children[0].(*UArrPtr).
+ Children[0]
+}
+
+// Chains of divisions. See issue 4201.
+
+func ChainDiv(a, b int) int {
+ return a / b / a / b / a / b / a / b /
+ a / b / a / b / a / b / a / b /
+ a / b / a / b / a / b / a / b
+}
+
+func ChainDivRight(a, b int) int {
+ return a / (b / (a / (b /
+ (a / (b / (a / (b /
+ (a / (b / (a / (b /
+ (a / (b / (a / (b /
+ (a / (b / (a / b))))))))))))))))))
+}
+
+func ChainDivConst(a int) int {
+ return a / 17 / 17 / 17 /
+ 17 / 17 / 17 / 17 /
+ 17 / 17 / 17 / 17
+}
+
+func ChainMulBytes(a, b, c byte) byte {
+ return a*(a*(a*(a*(a*(a*(a*(a*(a*b+c)+c)+c)+c)+c)+c)+c)+c) + c
+}
diff --git a/gcc/testsuite/go.test/test/typecheck.go b/gcc/testsuite/go.test/test/typecheck.go
new file mode 100644
index 00000000000..a2ad91ff4c3
--- /dev/null
+++ b/gcc/testsuite/go.test/test/typecheck.go
@@ -0,0 +1,18 @@
+// errorcheck
+
+// Verify that the Go compiler will not
+// die after running into an undefined
+// type in the argument list for a
+// function.
+// Does not compile.
+
+package main
+
+func mine(int b) int { // ERROR "undefined.*b"
+ return b + 2 // ERROR "undefined.*b"
+}
+
+func main() {
+ mine() // GCCGO_ERROR "not enough arguments"
+ c = mine() // ERROR "undefined.*c|not enough arguments" "cannot assign to c"
+}
diff --git a/gcc/testsuite/go.test/test/zerodivide.go b/gcc/testsuite/go.test/test/zerodivide.go
index 673d1d18d81..9ab27135359 100644
--- a/gcc/testsuite/go.test/test/zerodivide.go
+++ b/gcc/testsuite/go.test/test/zerodivide.go
@@ -237,4 +237,7 @@ func main() {
fmt.Printf("%v/%v: expected %g error; got %g\n", t.f, t.g, t.out, x)
}
}
+ if bad {
+ panic("zerodivide")
+ }
}
diff --git a/gcc/testsuite/lib/atomic-dg.exp b/gcc/testsuite/lib/atomic-dg.exp
new file mode 100644
index 00000000000..c1317e47c2f
--- /dev/null
+++ b/gcc/testsuite/lib/atomic-dg.exp
@@ -0,0 +1,104 @@
+# Copyright (C) 2013 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 of the License, 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 GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+#
+# atomic_link_flags -- compute library path and flags to find libatomic.
+# (originally from g++.exp)
+#
+
+proc atomic_link_flags { paths } {
+ global srcdir
+ global ld_library_path
+ global shlib_ext
+
+ set gccpath ${paths}
+ set flags ""
+
+ set shlib_ext [get_shlib_extension]
+
+ if { $gccpath != "" } {
+ if { [file exists "${gccpath}/libatomic/.libs/libatomic.a"]
+ || [file exists "${gccpath}/libatomic/.libs/libatomic.${shlib_ext}"] } {
+ append flags " -B${gccpath}/libatomic/ "
+ append flags " -L${gccpath}/libatomic/.libs"
+ append ld_library_path ":${gccpath}/libatomic/.libs"
+ }
+ } else {
+ global tool_root_dir
+
+ set libatomic [lookfor_file ${tool_root_dir} libatomic]
+ if { $libatomic != "" } {
+ append flags "-L${libatomic} "
+ append ld_library_path ":${libatomic}"
+ }
+ }
+
+ set_ld_library_path_env_vars
+
+ append flags " -latomic "
+ return "$flags"
+}
+
+#
+# atomic_init -- called at the start of each subdir of tests
+#
+
+proc atomic_init { args } {
+ global TEST_ALWAYS_FLAGS
+ global ALWAYS_CXXFLAGS
+ global TOOL_OPTIONS
+ global atomic_saved_TEST_ALWAYS_FLAGS
+
+ set link_flags ""
+ if ![is_remote host] {
+ if [info exists TOOL_OPTIONS] {
+ set link_flags "[atomic_link_flags [get_multilibs ${TOOL_OPTIONS}]]"
+ } else {
+ set link_flags "[atomic_link_flags [get_multilibs]]"
+ }
+ }
+
+ if [info exists TEST_ALWAYS_FLAGS] {
+ set atomic_saved_TEST_ALWAYS_FLAGS $TEST_ALWAYS_FLAGS
+ }
+ if [info exists ALWAYS_CXXFLAGS] {
+ set ALWAYS_CXXFLAGS [concat "{ldflags=$link_flags}" $ALWAYS_CXXFLAGS]
+ } else {
+ if [info exists TEST_ALWAYS_FLAGS] {
+ set TEST_ALWAYS_FLAGS "$link_flags $TEST_ALWAYS_FLAGS"
+ } else {
+ set TEST_ALWAYS_FLAGS "$link_flags"
+ }
+ }
+ return [check_no_compiler_messages_nocache libatomic_available executable {
+ int main (void) { return 0; }
+ }]
+}
+
+#
+# atomic_finish -- called at the end of each subdir of tests
+#
+
+proc atomic_finish { args } {
+ global TEST_ALWAYS_FLAGS
+ global atomic_saved_TEST_ALWAYS_FLAGS
+
+ if [info exists atomic_saved_TEST_ALWAYS_FLAGS] {
+ set TEST_ALWAYS_FLAGS $atomic_saved_TEST_ALWAYS_FLAGS
+ } else {
+ unset TEST_ALWAYS_FLAGS
+ }
+}
diff --git a/gcc/testsuite/lib/gcc-defs.exp b/gcc/testsuite/lib/gcc-defs.exp
index b2db164bc4b..0fe9cb28df2 100644
--- a/gcc/testsuite/lib/gcc-defs.exp
+++ b/gcc/testsuite/lib/gcc-defs.exp
@@ -245,7 +245,7 @@ proc dg-additional-files-options { options source } {
set additional_sources ""
}
if { $additional_files != "" } then {
- regsub -all " " $additional_files " [file dirname $source]/" additional_files
+ regsub -all "^| " $additional_files " [file dirname $source]/" additional_files
set to_download [concat $to_download $additional_files]
set additional_files ""
}
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index e6e9d7795f0..c3d9712772e 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -494,13 +494,6 @@ proc check_profiling_available { test_what } {
return 0
}
- # We don't yet support profiling for AArch64.
- if { [istarget aarch64*-*-*]
- && ([lindex $test_what 1] == "-p"
- || [lindex $test_what 1] == "-pg") } {
- return 0
- }
-
# cygwin does not support -p.
if { [istarget *-*-cygwin*] && $test_what == "-p" } {
return 0
@@ -708,6 +701,14 @@ proc check_effective_target_scheduling {} {
} "-fschedule-insns"]
}
+# Return 1 if trapping arithmetic is available, 0 otherwise.
+
+proc check_effective_target_trapping {} {
+ return [check_no_compiler_messages scheduling object {
+ add (int a, int b) { return a + b; }
+ } "-ftrapv"]
+}
+
# Return 1 if compilation with -fgraphite is error-free for trivial
# code, 0 otherwise.
@@ -1758,6 +1759,13 @@ proc check_effective_target_int32plus { } {
# options, 0 otherwise.
proc check_effective_target_ptr32plus { } {
+ # The msp430 has 16-bit or 20-bit pointers. The 20-bit pointer is stored
+ # in a 32-bit slot when in memory, so sizeof(void *) returns 4, but it
+ # cannot really hold a 32-bit address, so we always return false here.
+ if { [istarget msp430-*-*] } {
+ return 0
+ }
+
return [check_no_compiler_messages ptr32plus object {
int dummy[sizeof (void *) >= 4 ? 1 : -1];
}]
@@ -2467,6 +2475,11 @@ proc check_effective_target_arm_fp16_ok_nocache { } {
# Must generate floating-point instructions.
return 0
}
+ if [check_effective_target_arm_hf_eabi] {
+ # Use existing float-abi and force an fpu which supports fp16
+ set et_arm_fp16_flags "-mfpu=vfpv4"
+ return 1;
+ }
if [check-flags [list "" { *-*-* } { "-mfpu=*" } { "" } ]] {
# The existing -mfpu value is OK; use it, but add softfp.
set et_arm_fp16_flags "-mfloat-abi=softfp"
@@ -2599,6 +2612,17 @@ proc check_effective_target_arm_thumb2 { } {
} ""]
}
+# Return 1 if this is an ARM target where conditional execution is available.
+
+proc check_effective_target_arm_cond_exec { } {
+ return [check_no_compiler_messages arm_cond_exec assembly {
+ #if defined(__arm__) && defined(__thumb__) && !defined(__thumb2__)
+ #error FOO
+ #endif
+ int i;
+ } ""]
+}
+
# Return 1 if this is an ARM cortex-M profile cpu
proc check_effective_target_arm_cortex_m { } {
@@ -4497,6 +4521,7 @@ proc check_effective_target_sync_int_128_runtime { } {
proc check_effective_target_sync_long_long { } {
if { [istarget x86_64-*-*]
|| [istarget i?86-*-*])
+ || [istarget aarch64*-*-*]
|| [istarget arm*-*-*]
|| [istarget alpha*-*-*]
|| ([istarget sparc*-*-*] && [check_effective_target_lp64]) } {
@@ -4526,6 +4551,8 @@ proc check_effective_target_sync_long_long_runtime { } {
}
} ""
}]
+ } elseif { [istarget aarch64*-*-*] } {
+ return 1
} elseif { [istarget arm*-*-linux-*] } {
return [check_runtime sync_longlong_runtime {
#include <stdlib.h>
@@ -5450,3 +5477,40 @@ proc check_effective_target_aarch64_large { } {
return 0
}
}
+
+# Return 1 if <fenv.h> is available with all the standard IEEE
+# exceptions and floating-point exceptions are raised by arithmetic
+# operations. (If the target requires special options for "inexact"
+# exceptions, those need to be specified in the testcases.)
+
+proc check_effective_target_fenv_exceptions {} {
+ return [check_runtime fenv_exceptions {
+ #include <fenv.h>
+ #include <stdlib.h>
+ #ifndef FE_DIVBYZERO
+ # error Missing FE_DIVBYZERO
+ #endif
+ #ifndef FE_INEXACT
+ # error Missing FE_INEXACT
+ #endif
+ #ifndef FE_INVALID
+ # error Missing FE_INVALID
+ #endif
+ #ifndef FE_OVERFLOW
+ # error Missing FE_OVERFLOW
+ #endif
+ #ifndef FE_UNDERFLOW
+ # error Missing FE_UNDERFLOW
+ #endif
+ volatile float a = 0.0f, r;
+ int
+ main (void)
+ {
+ r = a / a;
+ if (fetestexcept (FE_INVALID))
+ exit (0);
+ else
+ abort ();
+ }
+ } "-std=gnu99"]
+}
diff --git a/gcc/timevar.def b/gcc/timevar.def
index 5a880a8a364..897f66dd82e 100644
--- a/gcc/timevar.def
+++ b/gcc/timevar.def
@@ -144,6 +144,7 @@ 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_SRA , "tree SRA")
+DEFTIMEVAR (TV_ISOLATE_ERRONEOUS_PATHS , "isolate eroneous paths")
DEFTIMEVAR (TV_TREE_CCP , "tree CCP")
DEFTIMEVAR (TV_TREE_PHI_CPROP , "tree PHI const/copy prop")
DEFTIMEVAR (TV_TREE_SPLIT_EDGES , "tree split crit edges")
@@ -221,9 +222,9 @@ DEFTIMEVAR (TV_CSE2 , "CSE 2")
DEFTIMEVAR (TV_BRANCH_PROB , "branch prediction")
DEFTIMEVAR (TV_COMBINE , "combiner")
DEFTIMEVAR (TV_IFCVT , "if-conversion")
-DEFTIMEVAR (TV_REGMOVE , "regmove")
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_IRA , "integrated RA")
DEFTIMEVAR (TV_LRA , "LRA non-specific")
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 6f3ca9d804b..d1e695e00cd 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -68,7 +68,6 @@ along with GCC; see the file COPYING3. If not see
#include "coverage.h"
#include "value-prof.h"
#include "alloc-pool.h"
-#include "tree-mudflap.h"
#include "asan.h"
#include "tsan.h"
#include "gimple.h"
@@ -421,15 +420,15 @@ wrapup_global_declaration_2 (tree decl)
if (!node && flag_ltrans)
needed = false;
- else if (node && node->symbol.definition)
+ else if (node && node->definition)
needed = false;
- else if (node && node->symbol.alias)
+ else if (node && node->alias)
needed = false;
else if (!cgraph_global_info_ready
&& (TREE_USED (decl)
|| TREE_USED (DECL_ASSEMBLER_NAME (decl))))
/* needed */;
- else if (node && node->symbol.analyzed)
+ else if (node && node->analyzed)
/* needed */;
else if (DECL_COMDAT (decl))
needed = false;
@@ -594,10 +593,6 @@ compile_file (void)
basically finished. */
if (in_lto_p || !flag_lto || flag_fat_lto_objects)
{
- /* Likewise for mudflap static object registrations. */
- if (flag_mudflap)
- mudflap_finish_file ();
-
/* File-scope initialization for AddressSanitizer. */
if (flag_sanitize & SANITIZE_ADDRESS)
asan_finish_file ();
@@ -732,17 +727,19 @@ print_version (FILE *file, const char *indent)
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_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)
+#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)
+#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
fprintf (file,
file == stderr ? _(fmt2) : fmt2,
@@ -1214,11 +1211,11 @@ general_init (const char *argv0)
/* This must be done after global_init_params but before argument
processing. */
- init_ggc_heuristics();
+ init_ggc_heuristics ();
/* Create the singleton holder for global state.
Doing so also creates the pass manager and with it the passes. */
- g = new gcc::context();
+ g = new gcc::context ();
statistics_early_init ();
finish_params ();
@@ -1329,8 +1326,11 @@ process_options (void)
"and -ftree-loop-linear)");
#endif
- if (flag_mudflap && flag_lto)
- sorry ("mudflap cannot be used together with link-time optimization");
+ if (flag_check_pointer_bounds)
+ {
+ if (targetm.chkp_bound_mode () == VOIDmode)
+ error ("-fcheck-pointers is not supported for this target");
+ }
/* One region RA really helps to decrease the code size. */
if (flag_ira_region == IRA_REGION_AUTODETECT)
@@ -1617,7 +1617,7 @@ process_options (void)
DK_ERROR, UNKNOWN_LOCATION);
/* Save the current optimization options. */
- optimization_default_node = build_optimization_node ();
+ optimization_default_node = build_optimization_node (&global_options);
optimization_current_node = optimization_default_node;
}
@@ -2029,16 +2029,17 @@ toplev_main (int argc, char **argv)
if (warningcount || errorcount || werrorcount)
print_ignored_options ();
- diagnostic_finish (global_dc);
- /* Invoke registered plugin callbacks if any. */
+ /* Invoke registered plugin callbacks if any. Some plugins could
+ emit some diagnostics here. */
invoke_plugin_callbacks (PLUGIN_FINISH, NULL);
-
- /* finalize melt if needed */
+ /* finalize MELT if needed. */
if (nbmeltarg > 0)
melt_finalize();
+ diagnostic_finish (global_dc);
+
finalize_plugins ();
location_adhoc_data_fini (line_table);
if (seen_error () || werrorcount)
diff --git a/gcc/tracer.c b/gcc/tracer.c
index aa1736c685e..86557febab7 100644
--- a/gcc/tracer.c
+++ b/gcc/tracer.c
@@ -46,6 +46,8 @@
#include "params.h"
#include "coverage.h"
#include "tree-pass.h"
+#include "gimple.h"
+#include "tree-cfg.h"
#include "tree-ssa.h"
#include "tree-inline.h"
#include "cfgloop.h"
@@ -417,8 +419,8 @@ const pass_data pass_data_tracer =
class pass_tracer : public gimple_opt_pass
{
public:
- pass_tracer(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_tracer, ctxt)
+ pass_tracer (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_tracer, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/trans-mem.c b/gcc/trans-mem.c
index fbc876a5386..784ff247e9d 100644
--- a/gcc/trans-mem.c
+++ b/gcc/trans-mem.c
@@ -23,7 +23,11 @@
#include "hash-table.h"
#include "tree.h"
#include "gimple.h"
-#include "tree-ssa.h"
+#include "gimple-ssa.h"
+#include "cgraph.h"
+#include "tree-cfg.h"
+#include "tree-ssanames.h"
+#include "tree-into-ssa.h"
#include "tree-pass.h"
#include "tree-inline.h"
#include "diagnostic-core.h"
@@ -35,6 +39,7 @@
#include "langhooks.h"
#include "gimple-pretty-print.h"
#include "cfgloop.h"
+#include "tree-ssa-address.h"
#define PROB_VERY_UNLIKELY (REG_BR_PROB_BASE / 2000 - 1)
@@ -587,6 +592,12 @@ diagnose_tm_1_op (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
return NULL_TREE;
}
+static inline bool
+is_tm_safe_or_pure (const_tree x)
+{
+ return is_tm_safe (x) || is_tm_pure (x);
+}
+
static tree
diagnose_tm_1 (gimple_stmt_iterator *gsi, bool *handled_ops_p,
struct walk_stmt_info *wi)
@@ -821,8 +832,8 @@ const pass_data pass_data_diagnose_tm_blocks =
class pass_diagnose_tm_blocks : public gimple_opt_pass
{
public:
- pass_diagnose_tm_blocks(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_diagnose_tm_blocks, ctxt)
+ pass_diagnose_tm_blocks (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_diagnose_tm_blocks, ctxt)
{}
/* opt_pass methods: */
@@ -1631,7 +1642,7 @@ lower_transaction (gimple_stmt_iterator *gsi, struct walk_stmt_info *wi)
/* If the transaction calls abort or if this is an outer transaction,
add an "over" label afterwards. */
if ((this_state & (GTMA_HAVE_ABORT))
- || (gimple_transaction_subcode(stmt) & GTMA_IS_OUTER))
+ || (gimple_transaction_subcode (stmt) & GTMA_IS_OUTER))
{
tree label = create_artificial_label (UNKNOWN_LOCATION);
gimple_transaction_set_label (stmt, label);
@@ -1744,8 +1755,8 @@ const pass_data pass_data_lower_tm =
class pass_lower_tm : public gimple_opt_pass
{
public:
- pass_lower_tm(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_lower_tm, ctxt)
+ pass_lower_tm (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_lower_tm, ctxt)
{}
/* opt_pass methods: */
@@ -2024,8 +2035,8 @@ const pass_data pass_data_tm_init =
class pass_tm_init : public gimple_opt_pass
{
public:
- pass_tm_init(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_tm_init, ctxt)
+ pass_tm_init (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_tm_init, ctxt)
{}
/* opt_pass methods: */
@@ -2753,8 +2764,8 @@ expand_transaction (struct tm_region *region, void *data ATTRIBUTE_UNUSED)
ei->probability = PROB_ALWAYS;
et->probability = PROB_LIKELY;
ef->probability = PROB_UNLIKELY;
- et->count = apply_probability(test_bb->count, et->probability);
- ef->count = apply_probability(test_bb->count, ef->probability);
+ et->count = apply_probability (test_bb->count, et->probability);
+ ef->count = apply_probability (test_bb->count, ef->probability);
code_bb->count = et->count;
code_bb->frequency = EDGE_FREQUENCY (et);
@@ -2793,14 +2804,14 @@ expand_transaction (struct tm_region *region, void *data ATTRIBUTE_UNUSED)
fallthru_edge->flags = EDGE_FALSE_VALUE;
fallthru_edge->probability = PROB_VERY_LIKELY;
fallthru_edge->count
- = apply_probability(test_bb->count, fallthru_edge->probability);
+ = apply_probability (test_bb->count, fallthru_edge->probability);
// Abort/over edge.
redirect_edge_pred (abort_edge, test_bb);
abort_edge->flags = EDGE_TRUE_VALUE;
abort_edge->probability = PROB_VERY_UNLIKELY;
abort_edge->count
- = apply_probability(test_bb->count, abort_edge->probability);
+ = apply_probability (test_bb->count, abort_edge->probability);
transaction_bb = test_bb;
}
@@ -2842,13 +2853,13 @@ expand_transaction (struct tm_region *region, void *data ATTRIBUTE_UNUSED)
inst_edge->flags = EDGE_FALSE_VALUE;
inst_edge->probability = REG_BR_PROB_BASE / 2;
inst_edge->count
- = apply_probability(test_bb->count, inst_edge->probability);
+ = apply_probability (test_bb->count, inst_edge->probability);
redirect_edge_pred (uninst_edge, test_bb);
uninst_edge->flags = EDGE_TRUE_VALUE;
uninst_edge->probability = REG_BR_PROB_BASE / 2;
uninst_edge->count
- = apply_probability(test_bb->count, uninst_edge->probability);
+ = apply_probability (test_bb->count, uninst_edge->probability);
}
// If we have no previous special cases, and we have PHIs at the beginning
@@ -3000,8 +3011,8 @@ const pass_data pass_data_tm_mark =
class pass_tm_mark : public gimple_opt_pass
{
public:
- pass_tm_mark(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_tm_mark, ctxt)
+ pass_tm_mark (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_tm_mark, ctxt)
{}
/* opt_pass methods: */
@@ -3183,8 +3194,8 @@ const pass_data pass_data_tm_edges =
class pass_tm_edges : public gimple_opt_pass
{
public:
- pass_tm_edges(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_tm_edges, ctxt)
+ pass_tm_edges (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_tm_edges, ctxt)
{}
/* opt_pass methods: */
@@ -3923,8 +3934,8 @@ const pass_data pass_data_tm_memopt =
class pass_tm_memopt : public gimple_opt_pass
{
public:
- pass_tm_memopt(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_tm_memopt, ctxt)
+ pass_tm_memopt (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_tm_memopt, ctxt)
{}
/* opt_pass methods: */
@@ -4035,16 +4046,16 @@ get_cg_data (struct cgraph_node **node, bool traverse_aliases)
{
struct tm_ipa_cg_data *d;
- if (traverse_aliases && (*node)->symbol.alias)
+ if (traverse_aliases && (*node)->alias)
*node = cgraph_alias_target (*node);
- d = (struct tm_ipa_cg_data *) (*node)->symbol.aux;
+ d = (struct tm_ipa_cg_data *) (*node)->aux;
if (d == NULL)
{
d = (struct tm_ipa_cg_data *)
obstack_alloc (&tm_obstack.obstack, sizeof (*d));
- (*node)->symbol.aux = (void *) d;
+ (*node)->aux = (void *) d;
memset (d, 0, sizeof (*d));
}
@@ -4187,7 +4198,7 @@ static void
ipa_tm_scan_calls_clone (struct cgraph_node *node,
cgraph_node_queue *callees_p)
{
- struct function *fn = DECL_STRUCT_FUNCTION (node->symbol.decl);
+ struct function *fn = DECL_STRUCT_FUNCTION (node->decl);
basic_block bb;
FOR_EACH_BB_FN (bb, fn)
@@ -4216,7 +4227,7 @@ ipa_tm_note_irrevocable (struct cgraph_node *node,
continue;
/* Even if we think we can go irrevocable, believe the user
above all. */
- if (is_tm_safe_or_pure (e->caller->symbol.decl))
+ if (is_tm_safe_or_pure (e->caller->decl))
continue;
caller = e->caller;
@@ -4287,7 +4298,7 @@ ipa_tm_scan_irr_block (basic_block bb)
if (find_tm_replacement_function (fn))
break;
- node = cgraph_get_node(fn);
+ node = cgraph_get_node (fn);
d = get_cg_data (&node, true);
/* Return true if irrevocable, but above all, believe
@@ -4488,11 +4499,11 @@ ipa_tm_scan_irr_function (struct cgraph_node *node, bool for_clone)
bool ret = false;
/* Builtin operators (operator new, and such). */
- if (DECL_STRUCT_FUNCTION (node->symbol.decl) == NULL
- || DECL_STRUCT_FUNCTION (node->symbol.decl)->cfg == NULL)
+ if (DECL_STRUCT_FUNCTION (node->decl) == NULL
+ || DECL_STRUCT_FUNCTION (node->decl)->cfg == NULL)
return false;
- push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
+ push_cfun (DECL_STRUCT_FUNCTION (node->decl));
calculate_dominance_info (CDI_DOMINATORS);
d = get_cg_data (&node, true);
@@ -4578,7 +4589,7 @@ ipa_tm_mayenterirr_function (struct cgraph_node *node)
unsigned flags;
d = get_cg_data (&node, true);
- decl = node->symbol.decl;
+ decl = node->decl;
flags = flags_from_decl_or_type (decl);
/* Handle some TM builtins. Ordinarily these aren't actually generated
@@ -4621,7 +4632,7 @@ ipa_tm_mayenterirr_function (struct cgraph_node *node)
/* Recurse on the main body for aliases. In general, this will
result in one of the bits above being set so that we will not
have to recurse next time. */
- if (node->symbol.alias)
+ if (node->alias)
return ipa_tm_mayenterirr_function (cgraph_get_node (node->thunk.alias));
/* What remains is unmarked local functions without items that force
@@ -4638,11 +4649,11 @@ ipa_tm_diagnose_tm_safe (struct cgraph_node *node)
struct cgraph_edge *e;
for (e = node->callees; e ; e = e->next_callee)
- if (!is_tm_callable (e->callee->symbol.decl)
+ if (!is_tm_callable (e->callee->decl)
&& e->callee->local.tm_may_enter_irr)
error_at (gimple_location (e->call_stmt),
"unsafe function call %qD within "
- "%<transaction_safe%> function", e->callee->symbol.decl);
+ "%<transaction_safe%> function", e->callee->decl);
}
/* Diagnose call from atomic transactions to unmarked functions
@@ -4781,14 +4792,14 @@ static inline void
ipa_tm_mark_force_output_node (struct cgraph_node *node)
{
cgraph_mark_force_output_node (node);
- node->symbol.analyzed = true;
+ node->analyzed = true;
}
static inline void
ipa_tm_mark_forced_by_abi_node (struct cgraph_node *node)
{
- node->symbol.forced_by_abi = true;
- node->symbol.analyzed = true;
+ node->forced_by_abi = true;
+ node->analyzed = true;
}
/* Callback data for ipa_tm_create_version_alias. */
@@ -4809,10 +4820,10 @@ ipa_tm_create_version_alias (struct cgraph_node *node, void *data)
tree old_decl, new_decl, tm_name;
struct cgraph_node *new_node;
- if (!node->symbol.cpp_implicit_alias)
+ if (!node->cpp_implicit_alias)
return false;
- old_decl = node->symbol.decl;
+ old_decl = node->decl;
tm_name = tm_mangle (DECL_ASSEMBLER_NAME (old_decl));
new_decl = build_decl (DECL_SOURCE_LOCATION (old_decl),
TREE_CODE (old_decl), tm_name,
@@ -4838,16 +4849,16 @@ ipa_tm_create_version_alias (struct cgraph_node *node, void *data)
new_node = cgraph_same_body_alias (NULL, new_decl, info->new_decl);
new_node->tm_clone = true;
- new_node->symbol.externally_visible = info->old_node->symbol.externally_visible;
+ new_node->externally_visible = info->old_node->externally_visible;
/* ?? Do not traverse aliases here. */
get_cg_data (&node, false)->clone = new_node;
record_tm_clone_pair (old_decl, new_decl);
- if (info->old_node->symbol.force_output
- || ipa_ref_list_first_referring (&info->old_node->symbol.ref_list))
+ if (info->old_node->force_output
+ || ipa_ref_list_first_referring (&info->old_node->ref_list))
ipa_tm_mark_force_output_node (new_node);
- if (info->old_node->symbol.forced_by_abi)
+ if (info->old_node->forced_by_abi)
ipa_tm_mark_forced_by_abi_node (new_node);
return false;
}
@@ -4861,7 +4872,7 @@ ipa_tm_create_version (struct cgraph_node *old_node)
tree new_decl, old_decl, tm_name;
struct cgraph_node *new_node;
- old_decl = old_node->symbol.decl;
+ old_decl = old_node->decl;
new_decl = copy_node (old_decl);
/* DECL_ASSEMBLER_NAME needs to be set before we call
@@ -4878,7 +4889,7 @@ ipa_tm_create_version (struct cgraph_node *old_node)
new_node = cgraph_copy_node_for_versioning (old_node, new_decl, vNULL, NULL);
new_node->local.local = false;
- new_node->symbol.externally_visible = old_node->symbol.externally_visible;
+ new_node->externally_visible = old_node->externally_visible;
new_node->lowered = true;
new_node->tm_clone = 1;
get_cg_data (&old_node, true)->clone = new_node;
@@ -4902,10 +4913,10 @@ ipa_tm_create_version (struct cgraph_node *old_node)
record_tm_clone_pair (old_decl, new_decl);
cgraph_call_function_insertion_hooks (new_node);
- if (old_node->symbol.force_output
- || ipa_ref_list_first_referring (&old_node->symbol.ref_list))
+ if (old_node->force_output
+ || ipa_ref_list_first_referring (&old_node->ref_list))
ipa_tm_mark_force_output_node (new_node);
- if (old_node->symbol.forced_by_abi)
+ if (old_node->forced_by_abi)
ipa_tm_mark_forced_by_abi_node (new_node);
/* Do the same thing, but for any aliases of the original node. */
@@ -4940,7 +4951,7 @@ ipa_tm_insert_irr_call (struct cgraph_node *node, struct tm_region *region,
cgraph_get_create_node
(builtin_decl_explicit (BUILT_IN_TM_IRREVOCABLE)),
g, 0,
- compute_call_stmt_bb_frequency (node->symbol.decl,
+ compute_call_stmt_bb_frequency (node->decl,
gimple_bb (g)));
}
@@ -4990,8 +5001,8 @@ ipa_tm_insert_gettmclone_call (struct cgraph_node *node,
gsi_insert_before (gsi, g, GSI_SAME_STMT);
cgraph_create_edge (node, cgraph_get_create_node (gettm_fn), g, 0,
- compute_call_stmt_bb_frequency (node->symbol.decl,
- gimple_bb(g)));
+ compute_call_stmt_bb_frequency (node->decl,
+ gimple_bb (g)));
/* Cast return value from tm_gettmclone* into appropriate function
pointer. */
@@ -5117,7 +5128,7 @@ ipa_tm_transform_calls_redirect (struct cgraph_node *node,
return;
}
- fndecl = new_node->symbol.decl;
+ fndecl = new_node->decl;
}
cgraph_redirect_edge_callee (e, new_node);
@@ -5211,7 +5222,7 @@ ipa_tm_transform_transaction (struct cgraph_node *node)
d = get_cg_data (&node, true);
- push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
+ push_cfun (DECL_STRUCT_FUNCTION (node->decl));
calculate_dominance_info (CDI_DOMINATORS);
for (region = d->all_tm_regions; region; region = region->next)
@@ -5254,7 +5265,7 @@ ipa_tm_transform_clone (struct cgraph_node *node)
if (!node->callees && !node->indirect_calls && !d->irrevocable_blocks_clone)
return;
- push_cfun (DECL_STRUCT_FUNCTION (d->clone->symbol.decl));
+ push_cfun (DECL_STRUCT_FUNCTION (d->clone->decl));
calculate_dominance_info (CDI_DOMINATORS);
need_ssa_rename =
@@ -5272,9 +5283,9 @@ ipa_tm_transform_clone (struct cgraph_node *node)
static unsigned int
ipa_tm_execute (void)
{
- cgraph_node_queue tm_callees = cgraph_node_queue();
+ cgraph_node_queue tm_callees = cgraph_node_queue ();
/* List of functions that will go irrevocable. */
- cgraph_node_queue irr_worklist = cgraph_node_queue();
+ cgraph_node_queue irr_worklist = cgraph_node_queue ();
struct cgraph_node *node;
struct tm_ipa_cg_data *d;
@@ -5290,7 +5301,7 @@ ipa_tm_execute (void)
/* For all local functions marked tm_callable, queue them. */
FOR_EACH_DEFINED_FUNCTION (node)
- if (is_tm_callable (node->symbol.decl)
+ if (is_tm_callable (node->decl)
&& cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE)
{
d = get_cg_data (&node, true);
@@ -5305,14 +5316,14 @@ ipa_tm_execute (void)
/* ... marked tm_pure, record that fact for the runtime by
indicating that the pure function is its own tm_callable.
No need to do this if the function's address can't be taken. */
- if (is_tm_pure (node->symbol.decl))
+ if (is_tm_pure (node->decl))
{
if (!node->local.local)
- record_tm_clone_pair (node->symbol.decl, node->symbol.decl);
+ record_tm_clone_pair (node->decl, node->decl);
continue;
}
- push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
+ push_cfun (DECL_STRUCT_FUNCTION (node->decl));
calculate_dominance_info (CDI_DOMINATORS);
tm_region_init (NULL);
@@ -5350,20 +5361,20 @@ ipa_tm_execute (void)
/* Some callees cannot be arbitrarily cloned. These will always be
irrevocable. Mark these now, so that we need not scan them. */
- if (is_tm_irrevocable (node->symbol.decl))
+ if (is_tm_irrevocable (node->decl))
ipa_tm_note_irrevocable (node, &irr_worklist);
else if (a <= AVAIL_NOT_AVAILABLE
- && !is_tm_safe_or_pure (node->symbol.decl))
+ && !is_tm_safe_or_pure (node->decl))
ipa_tm_note_irrevocable (node, &irr_worklist);
else if (a >= AVAIL_OVERWRITABLE)
{
- if (!tree_versionable_function_p (node->symbol.decl))
+ if (!tree_versionable_function_p (node->decl))
ipa_tm_note_irrevocable (node, &irr_worklist);
else if (!d->is_irrevocable)
{
/* If this is an alias, make sure its base is queued as well.
we need not scan the callees now, as the base will do. */
- if (node->symbol.alias)
+ if (node->alias)
{
node = cgraph_get_node (node->thunk.alias);
d = get_cg_data (&node, true);
@@ -5441,7 +5452,7 @@ ipa_tm_execute (void)
for (e = node->callers; e ; e = e->next_caller)
{
caller = e->caller;
- if (!is_tm_safe_or_pure (caller->symbol.decl)
+ if (!is_tm_safe_or_pure (caller->decl)
&& !caller->local.tm_may_enter_irr)
{
d = get_cg_data (&caller, true);
@@ -5450,7 +5461,7 @@ ipa_tm_execute (void)
}
/* Propagate back to referring aliases as well. */
- for (j = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list, j, ref); j++)
+ for (j = 0; ipa_ref_list_referring_iterate (&node->ref_list, j, ref); j++)
{
caller = cgraph (ref->referring);
if (ref->use == IPA_REF_ALIAS
@@ -5470,7 +5481,7 @@ ipa_tm_execute (void)
&& cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE)
{
d = get_cg_data (&node, true);
- if (is_tm_safe (node->symbol.decl))
+ if (is_tm_safe (node->decl))
ipa_tm_diagnose_tm_safe (node);
else if (d->all_tm_regions)
ipa_tm_diagnose_transaction (node, d->all_tm_regions);
@@ -5484,15 +5495,15 @@ ipa_tm_execute (void)
bool doit = false;
node = tm_callees[i];
- if (node->symbol.cpp_implicit_alias)
+ if (node->cpp_implicit_alias)
continue;
a = cgraph_function_body_availability (node);
d = get_cg_data (&node, true);
if (a <= AVAIL_NOT_AVAILABLE)
- doit = is_tm_callable (node->symbol.decl);
- else if (a <= AVAIL_AVAILABLE && is_tm_callable (node->symbol.decl))
+ doit = is_tm_callable (node->decl);
+ else if (a <= AVAIL_AVAILABLE && is_tm_callable (node->decl))
doit = true;
else if (!d->is_irrevocable
&& d->tm_callers_normal + d->tm_callers_clone > 0)
@@ -5506,7 +5517,7 @@ ipa_tm_execute (void)
for (i = 0; i < tm_callees.length (); ++i)
{
node = tm_callees[i];
- if (node->symbol.analyzed)
+ if (node->analyzed)
{
d = get_cg_data (&node, true);
if (d->clone)
@@ -5529,7 +5540,7 @@ ipa_tm_execute (void)
free_original_copy_tables ();
FOR_EACH_FUNCTION (node)
- node->symbol.aux = NULL;
+ node->aux = NULL;
#ifdef ENABLE_CHECKING
verify_cgraph ();
@@ -5558,8 +5569,8 @@ const pass_data pass_data_ipa_tm =
class pass_ipa_tm : public simple_ipa_opt_pass
{
public:
- pass_ipa_tm(gcc::context *ctxt)
- : simple_ipa_opt_pass(pass_data_ipa_tm, ctxt)
+ pass_ipa_tm (gcc::context *ctxt)
+ : simple_ipa_opt_pass (pass_data_ipa_tm, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/tree-affine.c b/gcc/tree-affine.c
index 81da521277f..b492ff0a211 100644
--- a/gcc/tree-affine.c
+++ b/gcc/tree-affine.c
@@ -874,10 +874,11 @@ debug_aff (aff_tree *val)
fprintf (stderr, "\n");
}
-/* Returns address of the reference REF in ADDR. The size of the accessed
- location is stored to SIZE. */
+/* Computes address of the reference REF in ADDR. The size of the accessed
+ location is stored to SIZE. Returns the ultimate containing object to
+ which REF refers. */
-void
+tree
get_inner_reference_aff (tree ref, aff_tree *addr, double_int *size)
{
HOST_WIDE_INT bitsize, bitpos;
@@ -904,6 +905,8 @@ get_inner_reference_aff (tree ref, aff_tree *addr, double_int *size)
aff_combination_add (addr, &tmp);
*size = double_int::from_shwi ((bitsize + BITS_PER_UNIT - 1) / BITS_PER_UNIT);
+
+ return base;
}
/* Returns true if a region of size SIZE1 at position 0 and a region of
diff --git a/gcc/tree-affine.h b/gcc/tree-affine.h
index b2558f7a4bd..86f90d82da0 100644
--- a/gcc/tree-affine.h
+++ b/gcc/tree-affine.h
@@ -74,7 +74,7 @@ bool aff_combination_constant_multiple_p (aff_tree *, aff_tree *, double_int *);
void aff_combination_expand (aff_tree *, struct pointer_map_t **);
void tree_to_aff_combination_expand (tree, tree, aff_tree *,
struct pointer_map_t **);
-void get_inner_reference_aff (tree, aff_tree *, double_int *);
+tree get_inner_reference_aff (tree, aff_tree *, double_int *);
void free_affine_expand_cache (struct pointer_map_t **);
bool aff_comb_cannot_overlap_p (aff_tree *, double_int, double_int);
diff --git a/gcc/tree-browser.c b/gcc/tree-browser.c
index b236cabd8df..dad06a5175a 100644
--- a/gcc/tree-browser.c
+++ b/gcc/tree-browser.c
@@ -46,7 +46,7 @@ struct tb_command {
TB_CODE comm_code;
};
-#define DEFTBCODE(code, str, help) { help, str, sizeof(str) - 1, code },
+#define DEFTBCODE(code, str, help) { help, str, sizeof (str) - 1, code },
static const struct tb_command tb_commands[] =
{
#include "tree-browser.def"
diff --git a/gcc/tree-call-cdce.c b/gcc/tree-call-cdce.c
index cf4116e68ae..eec1b0fb739 100644
--- a/gcc/tree-call-cdce.c
+++ b/gcc/tree-call-cdce.c
@@ -25,8 +25,11 @@ along with GCC; see the file COPYING3. If not see
#include "basic-block.h"
#include "tree.h"
#include "gimple-pretty-print.h"
-#include "tree-ssa.h"
#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-cfg.h"
+#include "tree-ssanames.h"
+#include "tree-into-ssa.h"
#include "tree-pass.h"
#include "flags.h"
@@ -710,7 +713,6 @@ shrink_wrap_one_built_in_call (gimple bi_call)
basic_block bi_call_bb, join_tgt_bb, guard_bb, guard_bb0;
edge join_tgt_in_edge_from_call, join_tgt_in_edge_fall_thru;
edge bi_call_in_edge0, guard_bb_in_edge;
- vec<gimple> conds;
unsigned tn_cond_stmts, nconds;
unsigned ci;
gimple cond_expr = NULL;
@@ -718,7 +720,7 @@ shrink_wrap_one_built_in_call (gimple bi_call)
tree bi_call_label_decl;
gimple bi_call_label;
- conds.create (12);
+ stack_vec<gimple, 12> conds;
gen_shrink_wrap_conditions (bi_call, conds, &nconds);
/* This can happen if the condition generator decides
@@ -726,10 +728,7 @@ shrink_wrap_one_built_in_call (gimple bi_call)
return false and do not do any transformation for
the call. */
if (nconds == 0)
- {
- conds.release ();
- return false;
- }
+ return false;
bi_call_bb = gimple_bb (bi_call);
@@ -740,10 +739,7 @@ shrink_wrap_one_built_in_call (gimple bi_call)
it could e.g. have EH edges. */
join_tgt_in_edge_from_call = find_fallthru_edge (bi_call_bb->succs);
if (join_tgt_in_edge_from_call == NULL)
- {
- conds.release ();
- return false;
- }
+ return false;
}
else
join_tgt_in_edge_from_call = split_block (bi_call_bb, bi_call);
@@ -829,7 +825,6 @@ shrink_wrap_one_built_in_call (gimple bi_call)
guard_bb_in_edge->count = guard_bb->count - bi_call_in_edge->count;
}
- conds.release ();
if (dump_file && (dump_flags & TDF_DETAILS))
{
location_t loc;
@@ -946,8 +941,8 @@ const pass_data pass_data_call_cdce =
class pass_call_cdce : public gimple_opt_pass
{
public:
- pass_call_cdce(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_call_cdce, ctxt)
+ pass_call_cdce (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_call_cdce, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 70930a3592a..d6466939032 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -30,6 +30,17 @@ along with GCC; see the file COPYING3. If not see
#include "function.h"
#include "ggc.h"
#include "gimple-pretty-print.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "cgraph.h"
+#include "tree-cfg.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
+#include "tree-ssa-loop-manip.h"
+#include "tree-ssa-loop-niter.h"
+#include "tree-into-ssa.h"
+#include "tree-dfa.h"
#include "tree-ssa.h"
#include "tree-dump.h"
#include "tree-pass.h"
@@ -41,6 +52,9 @@ along with GCC; see the file COPYING3. If not see
#include "pointer-set.h"
#include "tree-inline.h"
#include "target.h"
+#include "tree-ssa-live.h"
+#include "omp-low.h"
+#include "tree-cfgcleanup.h"
/* This file contains functions for building the Control Flow Graph (CFG)
for a function tree. */
@@ -236,6 +250,72 @@ build_gimple_cfg (gimple_seq seq)
discriminator_per_locus.dispose ();
}
+
+/* Search for ANNOTATE call with annot_expr_ivdep_kind; if found, remove
+ it and set loop->safelen to INT_MAX. We assume that the annotation
+ comes immediately before the condition. */
+
+static void
+replace_loop_annotate ()
+{
+ struct loop *loop;
+ loop_iterator li;
+ basic_block bb;
+ gimple_stmt_iterator gsi;
+ gimple stmt;
+
+ FOR_EACH_LOOP (li, loop, 0)
+ {
+ gsi = gsi_last_bb (loop->header);
+ stmt = gsi_stmt (gsi);
+ if (stmt && gimple_code (stmt) == GIMPLE_COND)
+ {
+ gsi_prev_nondebug (&gsi);
+ if (gsi_end_p (gsi))
+ continue;
+ stmt = gsi_stmt (gsi);
+ if (gimple_code (stmt) != GIMPLE_CALL)
+ continue;
+ if (!gimple_call_internal_p (stmt)
+ || gimple_call_internal_fn (stmt) != IFN_ANNOTATE)
+ continue;
+ if ((annot_expr_kind) tree_low_cst (gimple_call_arg (stmt, 1), 0)
+ != annot_expr_ivdep_kind)
+ continue;
+ stmt = gimple_build_assign (gimple_call_lhs (stmt),
+ gimple_call_arg (stmt, 0));
+ gsi_replace (&gsi, stmt, true);
+ loop->safelen = INT_MAX;
+ }
+ }
+
+ /* Remove IFN_ANNOTATE. Safeguard for the case loop->latch == NULL. */
+ FOR_EACH_BB (bb)
+ {
+ gsi = gsi_last_bb (bb);
+ stmt = gsi_stmt (gsi);
+ if (stmt && gimple_code (stmt) == GIMPLE_COND)
+ gsi_prev_nondebug (&gsi);
+ if (gsi_end_p (gsi))
+ continue;
+ stmt = gsi_stmt (gsi);
+ if (gimple_code (stmt) != GIMPLE_CALL)
+ continue;
+ if (!gimple_call_internal_p (stmt)
+ || gimple_call_internal_fn (stmt) != IFN_ANNOTATE)
+ continue;
+ if ((annot_expr_kind) tree_low_cst (gimple_call_arg (stmt, 1), 0)
+ != annot_expr_ivdep_kind)
+ continue;
+ warning_at (gimple_location (stmt), 0, "ignoring %<GCC ivdep%> "
+ "annotation");
+ stmt = gimple_build_assign (gimple_call_lhs (stmt),
+ gimple_call_arg (stmt, 0));
+ gsi_replace (&gsi, stmt, true);
+ }
+}
+
+
static unsigned int
execute_build_cfg (void)
{
@@ -250,6 +330,7 @@ execute_build_cfg (void)
}
cleanup_tree_cfg ();
loop_optimizer_init (AVOID_CFG_MODIFICATIONS);
+ replace_loop_annotate ();
return 0;
}
@@ -273,8 +354,8 @@ const pass_data pass_data_build_cfg =
class pass_build_cfg : public gimple_opt_pass
{
public:
- pass_build_cfg(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_build_cfg, ctxt)
+ pass_build_cfg (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_build_cfg, ctxt)
{}
/* opt_pass methods: */
@@ -300,6 +381,50 @@ computed_goto_p (gimple t)
&& TREE_CODE (gimple_goto_dest (t)) != LABEL_DECL);
}
+/* Returns true for edge E where e->src ends with a GIMPLE_COND and
+ the other edge points to a bb with just __builtin_unreachable ().
+ I.e. return true for C->M edge in:
+ <bb C>:
+ ...
+ if (something)
+ goto <bb N>;
+ else
+ goto <bb M>;
+ <bb N>:
+ __builtin_unreachable ();
+ <bb M>: */
+
+bool
+assert_unreachable_fallthru_edge_p (edge e)
+{
+ basic_block pred_bb = e->src;
+ gimple last = last_stmt (pred_bb);
+ if (last && gimple_code (last) == GIMPLE_COND)
+ {
+ basic_block other_bb = EDGE_SUCC (pred_bb, 0)->dest;
+ if (other_bb == e->dest)
+ other_bb = EDGE_SUCC (pred_bb, 1)->dest;
+ if (EDGE_COUNT (other_bb->succs) == 0)
+ {
+ gimple_stmt_iterator gsi = gsi_after_labels (other_bb);
+ gimple stmt;
+
+ if (gsi_end_p (gsi))
+ return false;
+ stmt = gsi_stmt (gsi);
+ if (is_gimple_debug (stmt))
+ {
+ gsi_next_nondebug (&gsi);
+ if (gsi_end_p (gsi))
+ return false;
+ stmt = gsi_stmt (gsi);
+ }
+ return gimple_call_builtin_p (stmt, BUILT_IN_UNREACHABLE);
+ }
+ }
+ return false;
+}
+
/* Search the CFG for any computed gotos. If found, factor them to a
common computed goto site. Also record the location of that site so
@@ -606,88 +731,8 @@ make_edges (void)
fallthru = true;
break;
- case GIMPLE_OMP_PARALLEL:
- case GIMPLE_OMP_TASK:
- case GIMPLE_OMP_FOR:
- case GIMPLE_OMP_SINGLE:
- case GIMPLE_OMP_MASTER:
- case GIMPLE_OMP_ORDERED:
- case GIMPLE_OMP_CRITICAL:
- case GIMPLE_OMP_SECTION:
- cur_region = new_omp_region (bb, code, cur_region);
- fallthru = true;
- break;
-
- case GIMPLE_OMP_SECTIONS:
- cur_region = new_omp_region (bb, code, cur_region);
- fallthru = true;
- break;
-
- case GIMPLE_OMP_SECTIONS_SWITCH:
- fallthru = false;
- break;
-
- case GIMPLE_OMP_ATOMIC_LOAD:
- case GIMPLE_OMP_ATOMIC_STORE:
- fallthru = true;
- break;
-
- case GIMPLE_OMP_RETURN:
- /* In the case of a GIMPLE_OMP_SECTION, the edge will go
- somewhere other than the next block. This will be
- created later. */
- cur_region->exit = bb;
- fallthru = cur_region->type != GIMPLE_OMP_SECTION;
- cur_region = cur_region->outer;
- break;
-
- case GIMPLE_OMP_CONTINUE:
- cur_region->cont = bb;
- switch (cur_region->type)
- {
- case GIMPLE_OMP_FOR:
- /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
- succs edges as abnormal to prevent splitting
- them. */
- single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
- /* Make the loopback edge. */
- make_edge (bb, single_succ (cur_region->entry),
- EDGE_ABNORMAL);
-
- /* Create an edge from GIMPLE_OMP_FOR to exit, which
- corresponds to the case that the body of the loop
- is not executed at all. */
- make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
- make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
- fallthru = false;
- break;
-
- case GIMPLE_OMP_SECTIONS:
- /* Wire up the edges into and out of the nested sections. */
- {
- basic_block switch_bb = single_succ (cur_region->entry);
-
- struct omp_region *i;
- for (i = cur_region->inner; i ; i = i->next)
- {
- gcc_assert (i->type == GIMPLE_OMP_SECTION);
- make_edge (switch_bb, i->entry, 0);
- make_edge (i->exit, bb, EDGE_FALLTHRU);
- }
-
- /* Make the loopback edge to the block with
- GIMPLE_OMP_SECTIONS_SWITCH. */
- make_edge (bb, switch_bb, 0);
-
- /* Make the edge from the switch to exit. */
- make_edge (switch_bb, bb->next_bb, 0);
- fallthru = false;
- }
- break;
-
- default:
- gcc_unreachable ();
- }
+ CASE_GIMPLE_OMP:
+ fallthru = make_gimple_omp_edges (bb, &cur_region);
break;
case GIMPLE_TRANSACTION:
@@ -711,8 +756,7 @@ make_edges (void)
make_edge (bb, bb->next_bb, EDGE_FALLTHRU);
}
- if (root_omp_region)
- free_omp_regions ();
+ free_omp_regions ();
/* Fold COND_EXPR_COND of each COND_EXPR. */
fold_cond_expr_cond ();
@@ -1013,6 +1057,9 @@ make_abnormal_goto_edges (basic_block bb, bool for_call)
break;
}
}
+ if (!gsi_end_p (gsi)
+ && is_gimple_debug (gsi_stmt (gsi)))
+ gsi_next_nondebug (&gsi);
if (!gsi_end_p (gsi))
{
/* Make an edge to every setjmp-like call. */
@@ -1513,49 +1560,6 @@ gimple_can_merge_blocks_p (basic_block a, basic_block b)
return true;
}
-/* Return true if the var whose chain of uses starts at PTR has no
- nondebug uses. */
-bool
-has_zero_uses_1 (const ssa_use_operand_t *head)
-{
- const ssa_use_operand_t *ptr;
-
- for (ptr = head->next; ptr != head; ptr = ptr->next)
- if (!is_gimple_debug (USE_STMT (ptr)))
- return false;
-
- return true;
-}
-
-/* Return true if the var whose chain of uses starts at PTR has a
- single nondebug use. Set USE_P and STMT to that single nondebug
- use, if so, or to NULL otherwise. */
-bool
-single_imm_use_1 (const ssa_use_operand_t *head,
- use_operand_p *use_p, gimple *stmt)
-{
- ssa_use_operand_t *ptr, *single_use = 0;
-
- for (ptr = head->next; ptr != head; ptr = ptr->next)
- if (!is_gimple_debug (USE_STMT (ptr)))
- {
- if (single_use)
- {
- single_use = NULL;
- break;
- }
- single_use = ptr;
- }
-
- if (use_p)
- *use_p = single_use;
-
- if (stmt)
- *stmt = single_use ? single_use->loc.stmt : NULL;
-
- return !!single_use;
-}
-
/* Replaces all uses of NAME by VAL. */
void
@@ -3360,7 +3364,7 @@ verify_gimple_assign_unary (gimple stmt)
{
if ((!INTEGRAL_TYPE_P (rhs1_type) || !SCALAR_FLOAT_TYPE_P (lhs_type))
&& (!VECTOR_INTEGER_TYPE_P (rhs1_type)
- || !VECTOR_FLOAT_TYPE_P(lhs_type)))
+ || !VECTOR_FLOAT_TYPE_P (lhs_type)))
{
error ("invalid types in conversion to floating point");
debug_generic_expr (lhs_type);
@@ -3375,7 +3379,7 @@ verify_gimple_assign_unary (gimple stmt)
{
if ((!INTEGRAL_TYPE_P (lhs_type) || !SCALAR_FLOAT_TYPE_P (rhs1_type))
&& (!VECTOR_INTEGER_TYPE_P (lhs_type)
- || !VECTOR_FLOAT_TYPE_P(rhs1_type)))
+ || !VECTOR_FLOAT_TYPE_P (rhs1_type)))
{
error ("invalid types in conversion to integer");
debug_generic_expr (lhs_type);
@@ -4489,7 +4493,7 @@ verify_gimple_in_seq (gimple_seq stmts)
/* Return true when the T can be shared. */
-bool
+static bool
tree_node_can_be_shared (tree t)
{
if (IS_TYPE_OR_DECL_P (t)
@@ -5499,7 +5503,7 @@ gimple_move_block_after (basic_block bb, basic_block after)
/* Return TRUE if block BB has no executable statements, otherwise return
FALSE. */
-bool
+static bool
gimple_empty_block_p (basic_block bb)
{
/* BB must have no executable statements. */
@@ -6662,12 +6666,13 @@ move_sese_region_to_fn (struct function *dest_cfun, basic_block entry_bb,
struct function *saved_cfun = cfun;
int *entry_flag, *exit_flag;
unsigned *entry_prob, *exit_prob;
- unsigned i, num_entry_edges, num_exit_edges;
+ unsigned i, num_entry_edges, num_exit_edges, num_nodes;
edge e;
edge_iterator ei;
htab_t new_label_map;
struct pointer_map_t *vars_map, *eh_map;
struct loop *loop = entry_bb->loop_father;
+ struct loop *loop0 = get_loop (saved_cfun, 0);
struct move_stmt_d d;
/* If ENTRY does not strictly dominate EXIT, this cannot be an SESE
@@ -6760,16 +6765,29 @@ move_sese_region_to_fn (struct function *dest_cfun, basic_block entry_bb,
set_loops_for_fn (dest_cfun, loops);
/* Move the outlined loop tree part. */
+ num_nodes = bbs.length ();
FOR_EACH_VEC_ELT (bbs, i, bb)
{
- if (bb->loop_father->header == bb
- && loop_outer (bb->loop_father) == loop)
+ if (bb->loop_father->header == bb)
{
struct loop *this_loop = bb->loop_father;
- flow_loop_tree_node_remove (bb->loop_father);
- flow_loop_tree_node_add (get_loop (dest_cfun, 0), this_loop);
- fixup_loop_arrays_after_move (saved_cfun, cfun, this_loop);
+ struct loop *outer = loop_outer (this_loop);
+ if (outer == loop
+ /* If the SESE region contains some bbs ending with
+ a noreturn call, those are considered to belong
+ to the outermost loop in saved_cfun, rather than
+ the entry_bb's loop_father. */
+ || outer == loop0)
+ {
+ if (outer != loop)
+ num_nodes -= this_loop->num_nodes;
+ flow_loop_tree_node_remove (bb->loop_father);
+ flow_loop_tree_node_add (get_loop (dest_cfun, 0), this_loop);
+ fixup_loop_arrays_after_move (saved_cfun, cfun, this_loop);
+ }
}
+ else if (bb->loop_father == loop0 && loop0 != loop)
+ num_nodes--;
/* Remove loop exits from the outlined region. */
if (loops_for_fn (saved_cfun)->exits)
@@ -6789,6 +6807,7 @@ move_sese_region_to_fn (struct function *dest_cfun, basic_block entry_bb,
/* Setup a mapping to be used by move_block_to_fn. */
loop->aux = current_loops->tree_root;
+ loop0->aux = current_loops->tree_root;
pop_cfun ();
@@ -6817,11 +6836,13 @@ move_sese_region_to_fn (struct function *dest_cfun, basic_block entry_bb,
}
loop->aux = NULL;
+ loop0->aux = NULL;
/* Loop sizes are no longer correct, fix them up. */
- loop->num_nodes -= bbs.length ();
+ loop->num_nodes -= num_nodes;
for (struct loop *outer = loop_outer (loop);
outer; outer = loop_outer (outer))
- outer->num_nodes -= bbs.length ();
+ outer->num_nodes -= num_nodes;
+ loop0->num_nodes -= bbs.length () - num_nodes;
if (saved_cfun->has_simduid_loops || saved_cfun->has_force_vect_loops)
{
@@ -7940,14 +7961,14 @@ const pass_data pass_data_split_crit_edges =
class pass_split_crit_edges : public gimple_opt_pass
{
public:
- pass_split_crit_edges(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_split_crit_edges, ctxt)
+ pass_split_crit_edges (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_split_crit_edges, ctxt)
{}
/* opt_pass methods: */
unsigned int execute () { return split_critical_edges (); }
- opt_pass * clone () { return new pass_split_crit_edges (ctxt_); }
+ opt_pass * clone () { return new pass_split_crit_edges (m_ctxt); }
}; // class pass_split_crit_edges
} // anon namespace
@@ -8112,8 +8133,8 @@ const pass_data pass_data_warn_function_return =
class pass_warn_function_return : public gimple_opt_pass
{
public:
- pass_warn_function_return(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_warn_function_return, ctxt)
+ pass_warn_function_return (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_warn_function_return, ctxt)
{}
/* opt_pass methods: */
@@ -8129,62 +8150,6 @@ make_pass_warn_function_return (gcc::context *ctxt)
return new pass_warn_function_return (ctxt);
}
-/* Emit noreturn warnings. */
-
-static unsigned int
-execute_warn_function_noreturn (void)
-{
- if (!TREE_THIS_VOLATILE (current_function_decl)
- && EDGE_COUNT (EXIT_BLOCK_PTR->preds) == 0)
- warn_function_noreturn (current_function_decl);
- return 0;
-}
-
-static bool
-gate_warn_function_noreturn (void)
-{
- return warn_suggest_attribute_noreturn;
-}
-
-namespace {
-
-const pass_data pass_data_warn_function_noreturn =
-{
- GIMPLE_PASS, /* type */
- "*warn_function_noreturn", /* name */
- OPTGROUP_NONE, /* optinfo_flags */
- true, /* has_gate */
- true, /* has_execute */
- TV_NONE, /* tv_id */
- PROP_cfg, /* properties_required */
- 0, /* properties_provided */
- 0, /* properties_destroyed */
- 0, /* todo_flags_start */
- 0, /* todo_flags_finish */
-};
-
-class pass_warn_function_noreturn : public gimple_opt_pass
-{
-public:
- pass_warn_function_noreturn(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_warn_function_noreturn, ctxt)
- {}
-
- /* opt_pass methods: */
- bool gate () { return gate_warn_function_noreturn (); }
- unsigned int execute () { return execute_warn_function_noreturn (); }
-
-}; // class pass_warn_function_noreturn
-
-} // anon namespace
-
-gimple_opt_pass *
-make_pass_warn_function_noreturn (gcc::context *ctxt)
-{
- return new pass_warn_function_noreturn (ctxt);
-}
-
-
/* Walk a gimplified function and warn for functions whose return value is
ignored and attribute((warn_unused_result)) is set. This is done before
inlining, so we don't have to worry about that. */
@@ -8283,8 +8248,8 @@ const pass_data pass_data_warn_unused_result =
class pass_warn_unused_result : public gimple_opt_pass
{
public:
- pass_warn_unused_result(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_warn_unused_result, ctxt)
+ pass_warn_unused_result (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_warn_unused_result, ctxt)
{}
/* opt_pass methods: */
@@ -8301,6 +8266,146 @@ make_pass_warn_unused_result (gcc::context *ctxt)
return new pass_warn_unused_result (ctxt);
}
+/* IPA passes, compilation of earlier functions or inlining
+ might have changed some properties, such as marked functions nothrow,
+ pure, const or noreturn.
+ Remove redundant edges and basic blocks, and create new ones if necessary.
+
+ This pass can't be executed as stand alone pass from pass manager, because
+ in between inlining and this fixup the verify_flow_info would fail. */
+
+unsigned int
+execute_fixup_cfg (void)
+{
+ basic_block bb;
+ gimple_stmt_iterator gsi;
+ int todo = gimple_in_ssa_p (cfun) ? TODO_verify_ssa : 0;
+ gcov_type count_scale;
+ edge e;
+ edge_iterator ei;
+
+ count_scale
+ = GCOV_COMPUTE_SCALE (cgraph_get_node (current_function_decl)->count,
+ ENTRY_BLOCK_PTR->count);
+
+ ENTRY_BLOCK_PTR->count = cgraph_get_node (current_function_decl)->count;
+ EXIT_BLOCK_PTR->count = apply_scale (EXIT_BLOCK_PTR->count,
+ count_scale);
+
+ FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs)
+ e->count = apply_scale (e->count, count_scale);
+
+ FOR_EACH_BB (bb)
+ {
+ bb->count = apply_scale (bb->count, count_scale);
+ for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ gimple stmt = gsi_stmt (gsi);
+ tree decl = is_gimple_call (stmt)
+ ? gimple_call_fndecl (stmt)
+ : NULL;
+ if (decl)
+ {
+ int flags = gimple_call_flags (stmt);
+ if (flags & (ECF_CONST | ECF_PURE | ECF_LOOPING_CONST_OR_PURE))
+ {
+ if (gimple_purge_dead_abnormal_call_edges (bb))
+ todo |= TODO_cleanup_cfg;
+
+ if (gimple_in_ssa_p (cfun))
+ {
+ todo |= TODO_update_ssa | TODO_cleanup_cfg;
+ update_stmt (stmt);
+ }
+ }
+
+ if (flags & ECF_NORETURN
+ && fixup_noreturn_call (stmt))
+ todo |= TODO_cleanup_cfg;
+ }
+
+ if (maybe_clean_eh_stmt (stmt)
+ && gimple_purge_dead_eh_edges (bb))
+ todo |= TODO_cleanup_cfg;
+ }
+
+ FOR_EACH_EDGE (e, ei, bb->succs)
+ e->count = apply_scale (e->count, count_scale);
+
+ /* If we have a basic block with no successors that does not
+ end with a control statement or a noreturn call end it with
+ a call to __builtin_unreachable. This situation can occur
+ when inlining a noreturn call that does in fact return. */
+ if (EDGE_COUNT (bb->succs) == 0)
+ {
+ gimple stmt = last_stmt (bb);
+ if (!stmt
+ || (!is_ctrl_stmt (stmt)
+ && (!is_gimple_call (stmt)
+ || (gimple_call_flags (stmt) & ECF_NORETURN) == 0)))
+ {
+ stmt = gimple_build_call
+ (builtin_decl_implicit (BUILT_IN_UNREACHABLE), 0);
+ gimple_stmt_iterator gsi = gsi_last_bb (bb);
+ gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
+ }
+ }
+ }
+ if (count_scale != REG_BR_PROB_BASE)
+ compute_function_frequency ();
+
+ /* We just processed all calls. */
+ if (cfun->gimple_df)
+ vec_free (MODIFIED_NORETURN_CALLS (cfun));
+
+ /* Dump a textual representation of the flowgraph. */
+ if (dump_file)
+ gimple_dump_cfg (dump_file, dump_flags);
+
+ if (current_loops
+ && (todo & TODO_cleanup_cfg))
+ loops_state_set (LOOPS_NEED_FIXUP);
+
+ return todo;
+}
+
+namespace {
+
+const pass_data pass_data_fixup_cfg =
+{
+ GIMPLE_PASS, /* type */
+ "*free_cfg_annotations", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
+ false, /* has_gate */
+ true, /* has_execute */
+ TV_NONE, /* tv_id */
+ PROP_cfg, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ 0, /* todo_flags_finish */
+};
+
+class pass_fixup_cfg : public gimple_opt_pass
+{
+public:
+ pass_fixup_cfg (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_fixup_cfg, ctxt)
+ {}
+
+ /* opt_pass methods: */
+ opt_pass * clone () { return new pass_fixup_cfg (m_ctxt); }
+ unsigned int execute () { return execute_fixup_cfg (); }
+
+}; // class pass_fixup_cfg
+
+} // anon namespace
+
+gimple_opt_pass *
+make_pass_fixup_cfg (gcc::context *ctxt)
+{
+ return new pass_fixup_cfg (ctxt);
+}
/* Garbage collection support for edge_def. */
diff --git a/gcc/tree-cfg.h b/gcc/tree-cfg.h
new file mode 100644
index 00000000000..c5c105dbdaa
--- /dev/null
+++ b/gcc/tree-cfg.h
@@ -0,0 +1,97 @@
+/* Data and Control Flow Analysis for Trees.
+ Copyright (C) 2001-2013 Free Software Foundation, Inc.
+ Contributed by Diego Novillo <dnovillo@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 _TREE_CFG_H
+#define _TREE_CFG_H
+
+/* Location to track pending stmt for edge insertion. */
+#define PENDING_STMT(e) ((e)->insns.g)
+
+extern void init_empty_tree_cfg_for_function (struct function *);
+extern void init_empty_tree_cfg (void);
+extern void fold_cond_expr_cond (void);
+extern void start_recording_case_labels (void);
+extern void end_recording_case_labels (void);
+extern basic_block label_to_block_fn (struct function *, tree);
+#define label_to_block(t) (label_to_block_fn (cfun, t))
+extern void make_abnormal_goto_edges (basic_block, bool);
+extern void cleanup_dead_labels (void);
+extern void group_case_labels_stmt (gimple);
+extern void group_case_labels (void);
+extern void replace_uses_by (tree, tree);
+extern basic_block single_noncomplex_succ (basic_block bb);
+extern void notice_special_calls (gimple);
+extern void clear_special_calls (void);
+extern edge find_taken_edge (basic_block, tree);
+extern void gimple_debug_bb (basic_block);
+extern basic_block gimple_debug_bb_n (int);
+extern void gimple_debug_cfg (int);
+extern void gimple_dump_cfg (FILE *, int);
+extern void dump_cfg_stats (FILE *);
+extern void debug_cfg_stats (void);
+extern bool stmt_can_make_abnormal_goto (gimple);
+extern bool is_ctrl_stmt (gimple);
+extern bool is_ctrl_altering_stmt (gimple);
+extern bool simple_goto_p (gimple);
+extern bool stmt_ends_bb_p (gimple);
+extern bool assert_unreachable_fallthru_edge_p (edge);
+extern void delete_tree_cfg_annotations (void);
+extern gimple first_stmt (basic_block);
+extern gimple last_stmt (basic_block);
+extern gimple last_and_only_stmt (basic_block);
+extern void verify_gimple_in_seq (gimple_seq);
+extern void verify_gimple_in_cfg (struct function *);
+extern tree gimple_block_label (basic_block);
+extern void add_phi_args_after_copy_bb (basic_block);
+extern void add_phi_args_after_copy (basic_block *, unsigned, edge);
+extern bool gimple_duplicate_sese_region (edge, edge, basic_block *, unsigned,
+ basic_block *, bool);
+extern bool gimple_duplicate_sese_tail (edge, edge, basic_block *, unsigned,
+ basic_block *);
+extern void gather_blocks_in_sese_region (basic_block entry, basic_block exit,
+ vec<basic_block> *bbs_p);
+extern basic_block move_sese_region_to_fn (struct function *, basic_block,
+ basic_block, tree);
+extern void dump_function_to_file (tree, FILE *, int);
+extern void debug_function (tree, int) ;
+extern void print_loops_bb (FILE *, basic_block, int, int);
+extern void print_loops (FILE *, int);
+extern void debug (struct loop &ref);
+extern void debug (struct loop *ptr);
+extern void debug_verbose (struct loop &ref);
+extern void debug_verbose (struct loop *ptr);
+extern void debug_loops (int);
+extern void debug_loop (struct loop *, int);
+extern void debug_loop_num (unsigned, int);
+extern void remove_edge_and_dominated_blocks (edge);
+extern bool gimple_purge_dead_eh_edges (basic_block);
+extern bool gimple_purge_all_dead_eh_edges (const_bitmap);
+extern bool gimple_purge_dead_abnormal_call_edges (basic_block);
+extern bool gimple_purge_all_dead_abnormal_call_edges (const_bitmap);
+extern tree gimplify_build3 (gimple_stmt_iterator *, enum tree_code,
+ tree, tree, tree, tree);
+extern tree gimplify_build2 (gimple_stmt_iterator *, enum tree_code,
+ tree, tree, tree);
+extern tree gimplify_build1 (gimple_stmt_iterator *, enum tree_code,
+ tree, tree);
+extern void extract_true_false_edges_from_block (basic_block, edge *, edge *);
+extern unsigned int execute_fixup_cfg (void);
+
+#endif /* _TREE_CFG_H */
diff --git a/gcc/tree-cfgcleanup.c b/gcc/tree-cfgcleanup.c
index e0acbed8ef2..c627d2cac57 100644
--- a/gcc/tree-cfgcleanup.c
+++ b/gcc/tree-cfgcleanup.c
@@ -29,6 +29,14 @@ along with GCC; see the file COPYING3. If not see
#include "function.h"
#include "ggc.h"
#include "langhooks.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-cfg.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
+#include "tree-ssa-loop-manip.h"
+#include "tree-dfa.h"
#include "tree-ssa.h"
#include "tree-pass.h"
#include "except.h"
@@ -1009,12 +1017,12 @@ const pass_data pass_data_merge_phi =
class pass_merge_phi : public gimple_opt_pass
{
public:
- pass_merge_phi(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_merge_phi, ctxt)
+ pass_merge_phi (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_merge_phi, ctxt)
{}
/* opt_pass methods: */
- opt_pass * clone () { return new pass_merge_phi (ctxt_); }
+ opt_pass * clone () { return new pass_merge_phi (m_ctxt); }
bool gate () { return gate_merge_phi (); }
unsigned int execute () { return merge_phi_nodes (); }
@@ -1027,3 +1035,90 @@ make_pass_merge_phi (gcc::context *ctxt)
{
return new pass_merge_phi (ctxt);
}
+
+/* Pass: cleanup the CFG just before expanding trees to RTL.
+ This is just a round of label cleanups and case node grouping
+ because after the tree optimizers have run such cleanups may
+ be necessary. */
+
+static unsigned int
+execute_cleanup_cfg_post_optimizing (void)
+{
+ unsigned int todo = 0;
+ if (cleanup_tree_cfg ())
+ todo |= TODO_update_ssa;
+ maybe_remove_unreachable_handlers ();
+ cleanup_dead_labels ();
+ group_case_labels ();
+ if ((flag_compare_debug_opt || flag_compare_debug)
+ && flag_dump_final_insns)
+ {
+ FILE *final_output = fopen (flag_dump_final_insns, "a");
+
+ if (!final_output)
+ {
+ error ("could not open final insn dump file %qs: %m",
+ flag_dump_final_insns);
+ flag_dump_final_insns = NULL;
+ }
+ else
+ {
+ int save_unnumbered = flag_dump_unnumbered;
+ int save_noaddr = flag_dump_noaddr;
+
+ flag_dump_noaddr = flag_dump_unnumbered = 1;
+ fprintf (final_output, "\n");
+ dump_enumerated_decls (final_output, dump_flags | TDF_NOUID);
+ flag_dump_noaddr = save_noaddr;
+ flag_dump_unnumbered = save_unnumbered;
+ if (fclose (final_output))
+ {
+ error ("could not close final insn dump file %qs: %m",
+ flag_dump_final_insns);
+ flag_dump_final_insns = NULL;
+ }
+ }
+ }
+ return todo;
+}
+
+namespace {
+
+const pass_data pass_data_cleanup_cfg_post_optimizing =
+{
+ GIMPLE_PASS, /* type */
+ "optimized", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
+ false, /* has_gate */
+ true, /* has_execute */
+ TV_TREE_CLEANUP_CFG, /* tv_id */
+ PROP_cfg, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ TODO_remove_unused_locals, /* todo_flags_finish */
+};
+
+class pass_cleanup_cfg_post_optimizing : public gimple_opt_pass
+{
+public:
+ pass_cleanup_cfg_post_optimizing (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_cleanup_cfg_post_optimizing, ctxt)
+ {}
+
+ /* opt_pass methods: */
+ unsigned int execute () {
+ return execute_cleanup_cfg_post_optimizing ();
+ }
+
+}; // class pass_cleanup_cfg_post_optimizing
+
+} // anon namespace
+
+gimple_opt_pass *
+make_pass_cleanup_cfg_post_optimizing (gcc::context *ctxt)
+{
+ return new pass_cleanup_cfg_post_optimizing (ctxt);
+}
+
+
diff --git a/gcc/tree-cfgcleanup.h b/gcc/tree-cfgcleanup.h
new file mode 100644
index 00000000000..6bd3c3940ec
--- /dev/null
+++ b/gcc/tree-cfgcleanup.h
@@ -0,0 +1,28 @@
+/* Header file for CFG cleanup for trees.
+ Copyright (C) 2013 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_CFGCLEANUP_H
+#define GCC_TREE_CFGCLEANUP_H
+
+/* In tree-cfgcleanup.c */
+extern bitmap cfgcleanup_altered_bbs;
+extern bool cleanup_tree_cfg (void);
+extern bool fixup_noreturn_call (gimple stmt);
+
+#endif /* GCC_TREE_CFGCLEANUP_H */
diff --git a/gcc/tree-chrec.c b/gcc/tree-chrec.c
index 16df51bbbef..afc1a6a5f64 100644
--- a/gcc/tree-chrec.c
+++ b/gcc/tree-chrec.c
@@ -26,9 +26,12 @@ along with GCC; see the file COPYING3. If not see
#include "config.h"
#include "system.h"
#include "coretypes.h"
+#include "tree.h"
#include "tree-pretty-print.h"
#include "cfgloop.h"
-#include "tree-ssa.h"
+#include "gimple.h"
+#include "tree-ssa-loop-ivopts.h"
+#include "tree-ssa-loop-niter.h"
#include "tree-chrec.h"
#include "dumpfile.h"
#include "params.h"
diff --git a/gcc/tree-chrec.h b/gcc/tree-chrec.h
index ad39a6b22d3..2c689d8839c 100644
--- a/gcc/tree-chrec.h
+++ b/gcc/tree-chrec.h
@@ -52,6 +52,8 @@ tree_is_chrec (const_tree expr)
}
+enum ev_direction {EV_DIR_GROWS, EV_DIR_DECREASES, EV_DIR_UNKNOWN};
+enum ev_direction scev_direction (const_tree);
/* Chrec folding functions. */
extern tree chrec_fold_plus (tree, tree, tree);
@@ -72,6 +74,8 @@ extern tree hide_evolution_in_other_loops_than_loop (tree, unsigned);
extern tree reset_evolution_in_loop (unsigned, tree, tree);
extern tree chrec_merge (tree, tree);
extern void for_each_scev_op (tree *, bool (*) (tree *, void *), void *);
+extern bool convert_affine_scev (struct loop *, tree, tree *, tree *, gimple,
+ bool);
/* Observers. */
extern bool eq_evolutions_p (const_tree, const_tree);
@@ -137,15 +141,18 @@ build_polynomial_chrec (unsigned loop_num,
|| !val)
return chrec_dont_know;
- /* Pointer types should occur only on the left hand side, i.e. in
- the base of the chrec, and not in the step. */
- gcc_assert (!POINTER_TYPE_P (TREE_TYPE (right)));
-
- /* Types of left and right sides of a chrec should be compatible. */
+ /* Types of left and right sides of a chrec should be compatible, but
+ pointer CHRECs are special in that the evolution is of ptroff type. */
if (POINTER_TYPE_P (TREE_TYPE (left)))
- gcc_assert (ptrofftype_p (TREE_TYPE (right)));
+ gcc_checking_assert (ptrofftype_p (TREE_TYPE (right)));
else
- gcc_assert (TREE_TYPE (left) == TREE_TYPE (right));
+ {
+ /* Pointer types should occur only on the left hand side, i.e. in
+ the base of the chrec, and not in the step. */
+ gcc_checking_assert (!POINTER_TYPE_P (TREE_TYPE (right))
+ && types_compatible_p (TREE_TYPE (left),
+ TREE_TYPE (right)));
+ }
if (chrec_zerop (right))
return left;
diff --git a/gcc/tree-complex.c b/gcc/tree-complex.c
index 91798ecdee6..6439402ba75 100644
--- a/gcc/tree-complex.c
+++ b/gcc/tree-complex.c
@@ -23,8 +23,14 @@ along with GCC; see the file COPYING3. If not see
#include "tm.h"
#include "tree.h"
#include "flags.h"
-#include "tree-ssa.h"
#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-cfg.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
+#include "tree-dfa.h"
+#include "tree-ssa.h"
#include "tree-iterator.h"
#include "tree-pass.h"
#include "tree-ssa-propagate.h"
@@ -1657,12 +1663,12 @@ const pass_data pass_data_lower_complex =
class pass_lower_complex : public gimple_opt_pass
{
public:
- pass_lower_complex(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_lower_complex, ctxt)
+ pass_lower_complex (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_lower_complex, ctxt)
{}
/* opt_pass methods: */
- opt_pass * clone () { return new pass_lower_complex (ctxt_); }
+ opt_pass * clone () { return new pass_lower_complex (m_ctxt); }
unsigned int execute () { return tree_lower_complex (); }
}; // class pass_lower_complex
@@ -1704,8 +1710,8 @@ const pass_data pass_data_lower_complex_O0 =
class pass_lower_complex_O0 : public gimple_opt_pass
{
public:
- pass_lower_complex_O0(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_lower_complex_O0, ctxt)
+ pass_lower_complex_O0 (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_lower_complex_O0, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/tree-core.h b/gcc/tree-core.h
index 69777dc2796..94ff7f85b16 100644
--- a/gcc/tree-core.h
+++ b/gcc/tree-core.h
@@ -43,6 +43,7 @@ struct function;
struct real_value;
struct fixed_value;
struct ptr_info_def;
+struct range_info_def;
struct die_struct;
struct pointer_set_t;
@@ -242,9 +243,27 @@ enum omp_clause_code {
/* OpenMP clause: linear (variable-list[:linear-step]). */
OMP_CLAUSE_LINEAR,
+ /* OpenMP clause: aligned (variable-list[:alignment]). */
+ OMP_CLAUSE_ALIGNED,
+
+ /* OpenMP clause: depend ({in,out,inout}:variable-list). */
+ OMP_CLAUSE_DEPEND,
+
/* OpenMP clause: uniform (argument-list). */
OMP_CLAUSE_UNIFORM,
+ /* OpenMP clause: from (variable-list). */
+ OMP_CLAUSE_FROM,
+
+ /* OpenMP clause: to (variable-list). */
+ OMP_CLAUSE_TO,
+
+ /* OpenMP clause: map ({alloc:,to:,from:,tofrom:,}variable-list). */
+ OMP_CLAUSE_MAP,
+
+ /* Internal clause: temporary for combined loops expansion. */
+ OMP_CLAUSE__LOOPTEMP_,
+
/* OpenMP clause: if (scalar-expression). */
OMP_CLAUSE_IF,
@@ -275,9 +294,45 @@ enum omp_clause_code {
/* 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: for. */
+ OMP_CLAUSE_FOR,
+
+ /* OpenMP clause: parallel. */
+ OMP_CLAUSE_PARALLEL,
+
+ /* OpenMP clause: sections. */
+ OMP_CLAUSE_SECTIONS,
+
+ /* OpenMP clause: taskgroup. */
+ OMP_CLAUSE_TASKGROUP,
+
/* Internally used only clause, holding SIMD uid. */
OMP_CLAUSE__SIMDUID_
};
@@ -313,7 +368,8 @@ enum cv_qualifier {
TYPE_UNQUALIFIED = 0x0,
TYPE_QUAL_CONST = 0x1,
TYPE_QUAL_VOLATILE = 0x2,
- TYPE_QUAL_RESTRICT = 0x4
+ TYPE_QUAL_RESTRICT = 0x4,
+ TYPE_QUAL_ATOMIC = 0x8
};
/* Enumerate visibility settings. */
@@ -342,6 +398,12 @@ enum tree_index {
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,
@@ -393,6 +455,8 @@ enum tree_index {
TI_FILEPTR_TYPE,
TI_POINTER_SIZED_TYPE,
+ TI_POINTER_BOUNDS_TYPE,
+
TI_DFLOAT32_TYPE,
TI_DFLOAT64_TYPE,
TI_DFLOAT128_TYPE,
@@ -592,6 +656,10 @@ enum tree_node_kind {
all_kinds
};
+enum annot_expr_kind {
+ annot_expr_ivdep_kind
+};
+
/*---------------------------------------------------------------------------
Type definitions
@@ -677,7 +745,8 @@ struct GTY(()) tree_base {
unsigned packed_flag : 1;
unsigned user_align : 1;
unsigned nameless_flag : 1;
- unsigned spare0 : 4;
+ unsigned atomic_flag : 1;
+ unsigned spare0 : 3;
unsigned spare1 : 8;
@@ -762,6 +831,9 @@ struct GTY(()) tree_base {
VAR_DECL, FUNCTION_DECL
IDENTIFIER_NODE
+ CONSTRUCTOR_NO_CLEARING in
+ CONSTRUCTOR
+
ASM_VOLATILE_P in
ASM_EXPR
@@ -783,6 +855,12 @@ struct GTY(()) tree_base {
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_REDUCTION
+
TRANSACTION_EXPR_RELAXED in
TRANSACTION_EXPR
@@ -800,6 +878,9 @@ struct GTY(()) tree_base {
OMP_PARALLEL_COMBINED in
OMP_PARALLEL
+ OMP_ATOMIC_SEQ_CST in
+ OMP_ATOMIC*
+
OMP_CLAUSE_PRIVATE_OUTER_REF in
OMP_CLAUSE_PRIVATE
@@ -1019,6 +1100,35 @@ struct GTY(()) tree_constructor {
vec<constructor_elt, va_gc> *elts;
};
+enum omp_clause_depend_kind
+{
+ OMP_CLAUSE_DEPEND_IN,
+ OMP_CLAUSE_DEPEND_OUT,
+ OMP_CLAUSE_DEPEND_INOUT
+};
+
+enum omp_clause_map_kind
+{
+ OMP_CLAUSE_MAP_ALLOC,
+ OMP_CLAUSE_MAP_TO,
+ OMP_CLAUSE_MAP_FROM,
+ OMP_CLAUSE_MAP_TOFROM,
+ /* The following kind is an internal only map kind, used for pointer based
+ array sections. OMP_CLAUSE_SIZE for these is not the pointer size,
+ which is implicitly POINTER_SIZE / BITS_PER_UNIT, but the bias. */
+ OMP_CLAUSE_MAP_POINTER
+};
+
+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_MASTER = 2,
+ OMP_CLAUSE_PROC_BIND_CLOSE = 3,
+ OMP_CLAUSE_PROC_BIND_SPREAD = 4
+};
+
struct GTY(()) tree_exp {
struct tree_typed typed;
location_t locus;
@@ -1050,8 +1160,14 @@ struct GTY(()) tree_ssa_name {
/* Statement that defines this SSA name. */
gimple def_stmt;
- /* Pointer attributes used for alias analysis. */
- struct ptr_info_def *ptr_info;
+ /* 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_d imm_uses;
@@ -1070,9 +1186,12 @@ struct GTY(()) tree_omp_clause {
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 tree_code reduction_code;
+ enum omp_clause_default_kind default_kind;
+ enum omp_clause_schedule_kind schedule_kind;
+ enum omp_clause_depend_kind depend_kind;
+ enum omp_clause_map_kind map_kind;
+ enum omp_clause_proc_bind_kind proc_bind_kind;
+ enum tree_code reduction_code;
} GTY ((skip)) subcode;
/* The gimplification of OMP_CLAUSE_REDUCTION_{INIT,MERGE} for omp-low's
@@ -1651,9 +1770,6 @@ 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[];
-/* Names of tree components. */
-extern const char *const tree_code_name[];
-
/* Vector of all alias pairs for global symbols. */
extern GTY(()) vec<alias_pair, va_gc> *alias_pairs;
diff --git a/gcc/tree-data-ref.c b/gcc/tree-data-ref.c
index 71d6d6774c2..ffa4cbf14d7 100644
--- a/gcc/tree-data-ref.c
+++ b/gcc/tree-data-ref.c
@@ -76,7 +76,11 @@ along with GCC; see the file COPYING3. If not see
#include "config.h"
#include "system.h"
#include "coretypes.h"
+#include "tree.h"
#include "gimple-pretty-print.h"
+#include "gimple.h"
+#include "tree-ssa-loop-niter.h"
+#include "tree-ssa-loop.h"
#include "tree-ssa.h"
#include "cfgloop.h"
#include "tree-data-ref.h"
@@ -1136,13 +1140,13 @@ common_affine_function (conflict_function *cf)
affine_fn comm;
if (!CF_NONTRIVIAL_P (cf))
- return affine_fn();
+ return affine_fn ();
comm = cf->fns[0];
for (i = 1; i < cf->n; i++)
if (!affine_function_equal_p (comm, cf->fns[i]))
- return affine_fn();
+ return affine_fn ();
return comm;
}
@@ -1637,12 +1641,12 @@ conflict_fn (unsigned n, ...)
va_list ap;
gcc_assert (0 < n && n <= MAX_DIM);
- va_start(ap, n);
+ va_start (ap, n);
ret->n = n;
for (i = 0; i < n; i++)
ret->fns[i] = va_arg (ap, affine_fn);
- va_end(ap);
+ va_end (ap);
return ret;
}
@@ -4321,7 +4325,7 @@ typedef struct data_ref_loc_d
true if STMT clobbers memory, false otherwise. */
static bool
-get_references_in_stmt (gimple stmt, vec<data_ref_loc, va_stack> *references)
+get_references_in_stmt (gimple stmt, vec<data_ref_loc, va_heap> *references)
{
bool clobbers_memory = false;
data_ref_loc ref;
@@ -4413,17 +4417,13 @@ find_data_references_in_stmt (struct loop *nest, gimple stmt,
vec<data_reference_p> *datarefs)
{
unsigned i;
- vec<data_ref_loc, va_stack> references;
+ stack_vec<data_ref_loc, 2> references;
data_ref_loc *ref;
bool ret = true;
data_reference_p dr;
- vec_stack_alloc (data_ref_loc, references, 2);
if (get_references_in_stmt (stmt, &references))
- {
- references.release ();
- return false;
- }
+ return false;
FOR_EACH_VEC_ELT (references, i, ref)
{
@@ -4447,17 +4447,13 @@ graphite_find_data_references_in_stmt (loop_p nest, loop_p loop, gimple stmt,
vec<data_reference_p> *datarefs)
{
unsigned i;
- vec<data_ref_loc, va_stack> references;
+ stack_vec<data_ref_loc, 2> references;
data_ref_loc *ref;
bool ret = true;
data_reference_p dr;
- vec_stack_alloc (data_ref_loc, references, 2);
if (get_references_in_stmt (stmt, &references))
- {
- references.release ();
- return false;
- }
+ return false;
FOR_EACH_VEC_ELT (references, i, ref)
{
diff --git a/gcc/tree-data-ref.h b/gcc/tree-data-ref.h
index 0763382bf8c..8cd7ef801da 100644
--- a/gcc/tree-data-ref.h
+++ b/gcc/tree-data-ref.h
@@ -144,7 +144,7 @@ struct access_matrix
#define AM_NB_INDUCTION_VARS(M) (M)->nb_induction_vars
#define AM_PARAMETERS(M) (M)->parameters
#define AM_MATRIX(M) (M)->matrix
-#define AM_NB_PARAMETERS(M) (AM_PARAMETERS(M)).length ()
+#define AM_NB_PARAMETERS(M) (AM_PARAMETERS (M)).length ()
#define AM_CONST_COLUMN_INDEX(M) (AM_NB_INDUCTION_VARS (M) + AM_NB_PARAMETERS (M))
#define AM_NB_COLUMNS(M) (AM_NB_INDUCTION_VARS (M) + AM_NB_PARAMETERS (M) + 1)
#define AM_GET_SUBSCRIPT_ACCESS_VECTOR(M, I) AM_MATRIX (M)[I]
@@ -162,7 +162,7 @@ am_vector_index_for_loop (struct access_matrix *access_matrix, int loop_num)
if (l->num == loop_num)
return i;
- gcc_unreachable();
+ gcc_unreachable ();
}
struct data_reference
@@ -406,6 +406,7 @@ extern bool dr_may_alias_p (const struct data_reference *,
const struct data_reference *, bool);
extern bool dr_equal_offsets_p (struct data_reference *,
struct data_reference *);
+extern void tree_check_data_deps (void);
/* Return true when the base objects of data references A and B are
diff --git a/gcc/tree-dfa.c b/gcc/tree-dfa.c
index bc825be8232..a31a0a28161 100644
--- a/gcc/tree-dfa.c
+++ b/gcc/tree-dfa.c
@@ -33,12 +33,15 @@ along with GCC; see the file COPYING3. If not see
#include "function.h"
#include "tree-pretty-print.h"
#include "gimple.h"
-#include "tree-ssa.h"
+#include "gimple-ssa.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
+#include "tree-dfa.h"
#include "tree-inline.h"
#include "tree-pass.h"
#include "convert.h"
#include "params.h"
-#include "cgraph.h"
/* Build and maintain data flow information for trees. */
@@ -386,7 +389,6 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
double_int bit_offset = double_int_zero;
HOST_WIDE_INT hbit_offset;
bool seen_variable_array_ref = false;
- tree base_type;
/* First get the final access size from just the outermost expression. */
if (TREE_CODE (exp) == COMPONENT_REF)
@@ -417,8 +419,6 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
and find the ultimate containing object. */
while (1)
{
- base_type = TREE_TYPE (exp);
-
switch (TREE_CODE (exp))
{
case BIT_FIELD_REF:
@@ -541,7 +541,38 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
case VIEW_CONVERT_EXPR:
break;
+ case TARGET_MEM_REF:
+ /* Via the variable index or index2 we can reach the
+ whole object. Still hand back the decl here. */
+ if (TREE_CODE (TMR_BASE (exp)) == ADDR_EXPR
+ && (TMR_INDEX (exp) || TMR_INDEX2 (exp)))
+ {
+ exp = TREE_OPERAND (TMR_BASE (exp), 0);
+ bit_offset = double_int_zero;
+ maxsize = -1;
+ goto done;
+ }
+ /* Fallthru. */
case MEM_REF:
+ /* We need to deal with variable arrays ending structures such as
+ struct { int length; int a[1]; } x; x.a[d]
+ struct { struct { int a; int b; } a[1]; } x; x.a[d].a
+ struct { struct { int a[1]; } a[1]; } x; x.a[0][d], x.a[d][0]
+ struct { int len; union { int a[1]; struct X x; } u; } x; x.u.a[d]
+ where we do not know maxsize for variable index accesses to
+ the array. The simplest way to conservatively deal with this
+ is to punt in the case that offset + maxsize reaches the
+ base type boundary. This needs to include possible trailing
+ padding that is there for alignment purposes. */
+ if (seen_variable_array_ref
+ && maxsize != -1
+ && (!bit_offset.fits_shwi ()
+ || !host_integerp (TYPE_SIZE (TREE_TYPE (exp)), 1)
+ || (bit_offset.to_shwi () + maxsize
+ == (HOST_WIDE_INT) TREE_INT_CST_LOW
+ (TYPE_SIZE (TREE_TYPE (exp))))))
+ maxsize = -1;
+
/* Hand back the decl for MEM[&decl, off]. */
if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR)
{
@@ -552,41 +583,11 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
double_int off = mem_ref_offset (exp);
off = off.lshift (BITS_PER_UNIT == 8
? 3 : exact_log2 (BITS_PER_UNIT));
- off = off + bit_offset;
- if (off.fits_shwi ())
- {
- bit_offset = off;
- exp = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
- }
- }
- }
- goto done;
-
- case TARGET_MEM_REF:
- /* Hand back the decl for MEM[&decl, off]. */
- if (TREE_CODE (TMR_BASE (exp)) == ADDR_EXPR)
- {
- /* Via the variable index or index2 we can reach the
- whole object. */
- if (TMR_INDEX (exp) || TMR_INDEX2 (exp))
- {
- exp = TREE_OPERAND (TMR_BASE (exp), 0);
- bit_offset = double_int_zero;
- maxsize = -1;
- goto done;
- }
- if (integer_zerop (TMR_OFFSET (exp)))
- exp = TREE_OPERAND (TMR_BASE (exp), 0);
- else
- {
- double_int off = mem_ref_offset (exp);
- off = off.lshift (BITS_PER_UNIT == 8
- ? 3 : exact_log2 (BITS_PER_UNIT));
off += bit_offset;
if (off.fits_shwi ())
{
bit_offset = off;
- exp = TREE_OPERAND (TMR_BASE (exp), 0);
+ exp = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
}
}
}
@@ -598,8 +599,18 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
exp = TREE_OPERAND (exp, 0);
}
- done:
+ /* We need to deal with variable arrays ending structures. */
+ if (seen_variable_array_ref
+ && maxsize != -1
+ && (!bit_offset.fits_shwi ()
+ || !host_integerp (TYPE_SIZE (TREE_TYPE (exp)), 1)
+ || (bit_offset.to_shwi () + maxsize
+ == (HOST_WIDE_INT) TREE_INT_CST_LOW
+ (TYPE_SIZE (TREE_TYPE (exp))))))
+ maxsize = -1;
+
+ done:
if (!bit_offset.fits_shwi ())
{
*poffset = 0;
@@ -611,24 +622,6 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
hbit_offset = bit_offset.to_shwi ();
- /* We need to deal with variable arrays ending structures such as
- struct { int length; int a[1]; } x; x.a[d]
- struct { struct { int a; int b; } a[1]; } x; x.a[d].a
- struct { struct { int a[1]; } a[1]; } x; x.a[0][d], x.a[d][0]
- struct { int len; union { int a[1]; struct X x; } u; } x; x.u.a[d]
- where we do not know maxsize for variable index accesses to
- the array. The simplest way to conservatively deal with this
- is to punt in the case that offset + maxsize reaches the
- base type boundary. This needs to include possible trailing padding
- that is there for alignment purposes. */
-
- if (seen_variable_array_ref
- && maxsize != -1
- && (!host_integerp (TYPE_SIZE (base_type), 1)
- || (hbit_offset + maxsize
- == (signed) TREE_INT_CST_LOW (TYPE_SIZE (base_type)))))
- maxsize = -1;
-
/* In case of a decl or constant base object we can do better. */
if (DECL_P (exp))
@@ -740,8 +733,7 @@ dump_enumerated_decls (FILE *file, int flags)
{
basic_block bb;
struct walk_stmt_info wi;
- vec<numbered_tree> decl_list;
- decl_list.create (40);
+ stack_vec<numbered_tree, 40> decl_list;
memset (&wi, '\0', sizeof (wi));
wi.info = (void *) &decl_list;
@@ -772,5 +764,4 @@ dump_enumerated_decls (FILE *file, int flags)
last = ntp->t;
}
}
- decl_list.release ();
}
diff --git a/gcc/tree-dfa.h b/gcc/tree-dfa.h
new file mode 100644
index 00000000000..7d0a47009f6
--- /dev/null
+++ b/gcc/tree-dfa.h
@@ -0,0 +1,184 @@
+/* Header file for tree data flow functions.
+ Copyright (C) 2013 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_DFA_H
+#define GCC_TREE_DFA_H
+
+extern void renumber_gimple_stmt_uids (void);
+extern void renumber_gimple_stmt_uids_in_blocks (basic_block *, int);
+extern void dump_variable (FILE *, tree);
+extern void debug_variable (tree);
+extern void dump_dfa_stats (FILE *);
+extern void debug_dfa_stats (void);
+extern tree ssa_default_def (struct function *, tree);
+extern void set_ssa_default_def (struct function *, tree, tree);
+extern tree get_or_create_ssa_default_def (struct function *, tree);
+extern tree get_ref_base_and_extent (tree, HOST_WIDE_INT *,
+ HOST_WIDE_INT *, HOST_WIDE_INT *);
+extern tree get_addr_base_and_unit_offset (tree, HOST_WIDE_INT *);
+extern bool stmt_references_abnormal_ssa_name (gimple);
+extern void dump_enumerated_decls (FILE *, int);
+
+/* Returns the base object and a constant BITS_PER_UNIT offset in *POFFSET that
+ denotes the starting address of the memory access EXP.
+ Returns NULL_TREE if the offset is not constant or any component
+ is not BITS_PER_UNIT-aligned.
+ VALUEIZE if non-NULL is used to valueize SSA names. It should return
+ its argument or a constant if the argument is known to be constant. */
+/* ??? This is a static inline here to avoid the overhead of the indirect calls
+ to VALUEIZE. But is this overhead really that significant? And should we
+ perhaps just rely on WHOPR to specialize the function? */
+
+static inline tree
+get_addr_base_and_unit_offset_1 (tree exp, HOST_WIDE_INT *poffset,
+ tree (*valueize) (tree))
+{
+ HOST_WIDE_INT byte_offset = 0;
+
+ /* Compute cumulative byte-offset for nested component-refs and array-refs,
+ and find the ultimate containing object. */
+ while (1)
+ {
+ switch (TREE_CODE (exp))
+ {
+ case BIT_FIELD_REF:
+ {
+ HOST_WIDE_INT this_off = TREE_INT_CST_LOW (TREE_OPERAND (exp, 2));
+ if (this_off % BITS_PER_UNIT)
+ return NULL_TREE;
+ byte_offset += this_off / BITS_PER_UNIT;
+ }
+ break;
+
+ case COMPONENT_REF:
+ {
+ tree field = TREE_OPERAND (exp, 1);
+ tree this_offset = component_ref_field_offset (exp);
+ HOST_WIDE_INT hthis_offset;
+
+ if (!this_offset
+ || TREE_CODE (this_offset) != INTEGER_CST
+ || (TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field))
+ % BITS_PER_UNIT))
+ return NULL_TREE;
+
+ hthis_offset = TREE_INT_CST_LOW (this_offset);
+ hthis_offset += (TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field))
+ / BITS_PER_UNIT);
+ byte_offset += hthis_offset;
+ }
+ break;
+
+ case ARRAY_REF:
+ case ARRAY_RANGE_REF:
+ {
+ tree index = TREE_OPERAND (exp, 1);
+ tree low_bound, unit_size;
+
+ if (valueize
+ && TREE_CODE (index) == SSA_NAME)
+ index = (*valueize) (index);
+
+ /* If the resulting bit-offset is constant, track it. */
+ if (TREE_CODE (index) == INTEGER_CST
+ && (low_bound = array_ref_low_bound (exp),
+ TREE_CODE (low_bound) == INTEGER_CST)
+ && (unit_size = array_ref_element_size (exp),
+ TREE_CODE (unit_size) == INTEGER_CST))
+ {
+ HOST_WIDE_INT hindex = TREE_INT_CST_LOW (index);
+
+ hindex -= TREE_INT_CST_LOW (low_bound);
+ hindex *= TREE_INT_CST_LOW (unit_size);
+ byte_offset += hindex;
+ }
+ else
+ return NULL_TREE;
+ }
+ break;
+
+ case REALPART_EXPR:
+ break;
+
+ case IMAGPART_EXPR:
+ byte_offset += TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (exp)));
+ break;
+
+ case VIEW_CONVERT_EXPR:
+ break;
+
+ case MEM_REF:
+ {
+ tree base = TREE_OPERAND (exp, 0);
+ if (valueize
+ && TREE_CODE (base) == SSA_NAME)
+ base = (*valueize) (base);
+
+ /* Hand back the decl for MEM[&decl, off]. */
+ if (TREE_CODE (base) == ADDR_EXPR)
+ {
+ if (!integer_zerop (TREE_OPERAND (exp, 1)))
+ {
+ double_int off = mem_ref_offset (exp);
+ gcc_assert (off.high == -1 || off.high == 0);
+ byte_offset += off.to_shwi ();
+ }
+ exp = TREE_OPERAND (base, 0);
+ }
+ goto done;
+ }
+
+ case TARGET_MEM_REF:
+ {
+ tree base = TREE_OPERAND (exp, 0);
+ if (valueize
+ && TREE_CODE (base) == SSA_NAME)
+ base = (*valueize) (base);
+
+ /* Hand back the decl for MEM[&decl, off]. */
+ if (TREE_CODE (base) == ADDR_EXPR)
+ {
+ if (TMR_INDEX (exp) || TMR_INDEX2 (exp))
+ return NULL_TREE;
+ if (!integer_zerop (TMR_OFFSET (exp)))
+ {
+ double_int off = mem_ref_offset (exp);
+ gcc_assert (off.high == -1 || off.high == 0);
+ byte_offset += off.to_shwi ();
+ }
+ exp = TREE_OPERAND (base, 0);
+ }
+ goto done;
+ }
+
+ default:
+ goto done;
+ }
+
+ exp = TREE_OPERAND (exp, 0);
+ }
+done:
+
+ *poffset = byte_offset;
+ return exp;
+}
+
+
+
+#endif /* GCC_TREE_DFA_H */
diff --git a/gcc/tree-dump.c b/gcc/tree-dump.c
index 12a2be7e49e..17db244da64 100644
--- a/gcc/tree-dump.c
+++ b/gcc/tree-dump.c
@@ -29,6 +29,7 @@ along with GCC; see the file COPYING3. If not see
#include "langhooks.h"
#include "tree-iterator.h"
#include "tree-pretty-print.h"
+#include "tree-cfg.h"
static unsigned int queue (dump_info_p, const_tree, int);
static void dump_index (dump_info_p, unsigned int);
@@ -277,7 +278,7 @@ dequeue_and_dump (dump_info_p di)
if (dni->binfo_p)
code_name = "binfo";
else
- code_name = tree_code_name[(int) TREE_CODE (t)];
+ code_name = get_tree_code_name (TREE_CODE (t));
fprintf (di->stream, "%-16s ", code_name);
di->column = 25;
diff --git a/gcc/tree-dump.h b/gcc/tree-dump.h
index b24b358503b..edd32e71601 100644
--- a/gcc/tree-dump.h
+++ b/gcc/tree-dump.h
@@ -90,7 +90,4 @@ extern void queue_and_dump_type (dump_info_p, const_tree);
extern void dump_function (int, tree);
extern int dump_flag (dump_info_p, int, const_tree);
-/* In tree-cfg.c */
-extern void dump_function_to_file (tree, FILE *, int);
-
#endif /* ! GCC_TREE_DUMP_H */
diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
index 51eab57c716..a489b61c3f2 100644
--- a/gcc/tree-eh.c
+++ b/gcc/tree-eh.c
@@ -27,29 +27,28 @@ along with GCC; see the file COPYING3. If not see
#include "function.h"
#include "except.h"
#include "pointer-set.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "cgraph.h"
+#include "tree-cfg.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
+#include "tree-into-ssa.h"
#include "tree-ssa.h"
#include "tree-inline.h"
#include "tree-pass.h"
#include "langhooks.h"
#include "ggc.h"
#include "diagnostic-core.h"
-#include "gimple.h"
#include "target.h"
#include "cfgloop.h"
+#include "gimple-low.h"
/* In some instances a tree and a gimple need to be stored in a same table,
i.e. in hash tables. This is a structure to do this. */
typedef union {tree *tp; tree t; gimple g;} treemple;
-/* Nonzero if we are using EH to handle cleanups. */
-static int using_eh_for_cleanups_p = 0;
-
-void
-using_eh_for_cleanups (void)
-{
- using_eh_for_cleanups_p = 1;
-}
-
/* Misc functions used in this file. */
/* Remember and lookup EH landing pad data for arbitrary statements.
@@ -66,7 +65,7 @@ using_eh_for_cleanups (void)
/* Add statement T in function IFUN to landing pad NUM. */
-void
+static void
add_stmt_to_eh_lp_fn (struct function *ifun, gimple t, int num)
{
struct throw_stmt_node *n;
@@ -1655,7 +1654,7 @@ lower_try_finally (struct leh_state *state, gimple tp)
this_tf.try_finally_expr = tp;
this_tf.top_p = tp;
this_tf.outer = state;
- if (using_eh_for_cleanups_p && !cleanup_is_dead_in (state->cur_region))
+ if (using_eh_for_cleanups_p () && !cleanup_is_dead_in (state->cur_region))
{
this_tf.region = gen_eh_region_cleanup (state->cur_region);
this_state.cur_region = this_tf.region;
@@ -1737,7 +1736,7 @@ lower_try_finally (struct leh_state *state, gimple tp)
{
gimple_seq new_eh_seq = eh_seq;
eh_seq = old_eh_seq;
- gimple_seq_add_seq(&eh_seq, new_eh_seq);
+ gimple_seq_add_seq (&eh_seq, new_eh_seq);
}
}
@@ -2177,8 +2176,8 @@ const pass_data pass_data_lower_eh =
class pass_lower_eh : public gimple_opt_pass
{
public:
- pass_lower_eh(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_lower_eh, ctxt)
+ pass_lower_eh (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_lower_eh, ctxt)
{}
/* opt_pass methods: */
@@ -2507,6 +2506,68 @@ operation_could_trap_p (enum tree_code op, bool fp_operation, bool honor_trapv,
&handled);
}
+
+/* Returns true if it is possible to prove that the index of
+ an array access REF (an ARRAY_REF expression) falls into the
+ array bounds. */
+
+static bool
+in_array_bounds_p (tree ref)
+{
+ tree idx = TREE_OPERAND (ref, 1);
+ tree min, max;
+
+ if (TREE_CODE (idx) != INTEGER_CST)
+ return false;
+
+ min = array_ref_low_bound (ref);
+ max = array_ref_up_bound (ref);
+ if (!min
+ || !max
+ || TREE_CODE (min) != INTEGER_CST
+ || TREE_CODE (max) != INTEGER_CST)
+ return false;
+
+ if (tree_int_cst_lt (idx, min)
+ || tree_int_cst_lt (max, idx))
+ return false;
+
+ return true;
+}
+
+/* Returns true if it is possible to prove that the range of
+ an array access REF (an ARRAY_RANGE_REF expression) falls
+ into the array bounds. */
+
+static bool
+range_in_array_bounds_p (tree ref)
+{
+ tree domain_type = TYPE_DOMAIN (TREE_TYPE (ref));
+ tree range_min, range_max, min, max;
+
+ range_min = TYPE_MIN_VALUE (domain_type);
+ range_max = TYPE_MAX_VALUE (domain_type);
+ if (!range_min
+ || !range_max
+ || TREE_CODE (range_min) != INTEGER_CST
+ || TREE_CODE (range_max) != INTEGER_CST)
+ return false;
+
+ min = array_ref_low_bound (ref);
+ max = array_ref_up_bound (ref);
+ if (!min
+ || !max
+ || TREE_CODE (min) != INTEGER_CST
+ || TREE_CODE (max) != INTEGER_CST)
+ return false;
+
+ if (tree_int_cst_lt (range_min, min)
+ || tree_int_cst_lt (max, range_max))
+ return false;
+
+ return true;
+}
+
/* Return true if EXPR can trap, as in dereferencing an invalid pointer
location or floating point arithmetic. C.f. the rtl version, may_trap_p.
This routine expects only GIMPLE lhs or rhs input. */
@@ -2603,7 +2664,7 @@ tree_could_trap_p (tree expr)
if (!DECL_EXTERNAL (expr))
return false;
node = cgraph_function_node (cgraph_get_node (expr), NULL);
- if (node && node->symbol.in_other_partition)
+ if (node && node->in_other_partition)
return false;
return true;
}
@@ -2619,7 +2680,7 @@ tree_could_trap_p (tree expr)
if (!DECL_EXTERNAL (expr))
return false;
node = varpool_variable_node (varpool_get_node (expr), NULL);
- if (node && node->symbol.in_other_partition)
+ if (node && node->in_other_partition)
return false;
return true;
}
@@ -3054,8 +3115,8 @@ const pass_data pass_data_refactor_eh =
class pass_refactor_eh : public gimple_opt_pass
{
public:
- pass_refactor_eh(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_refactor_eh, ctxt)
+ pass_refactor_eh (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_refactor_eh, ctxt)
{}
/* opt_pass methods: */
@@ -3281,8 +3342,8 @@ const pass_data pass_data_lower_resx =
class pass_lower_resx : public gimple_opt_pass
{
public:
- pass_lower_resx(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_lower_resx, ctxt)
+ pass_lower_resx (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_lower_resx, ctxt)
{}
/* opt_pass methods: */
@@ -3692,8 +3753,8 @@ const pass_data pass_data_lower_eh_dispatch =
class pass_lower_eh_dispatch : public gimple_opt_pass
{
public:
- pass_lower_eh_dispatch(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_lower_eh_dispatch, ctxt)
+ pass_lower_eh_dispatch (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_lower_eh_dispatch, ctxt)
{}
/* opt_pass methods: */
@@ -4536,12 +4597,12 @@ const pass_data pass_data_cleanup_eh =
class pass_cleanup_eh : public gimple_opt_pass
{
public:
- pass_cleanup_eh(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_cleanup_eh, ctxt)
+ pass_cleanup_eh (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_cleanup_eh, ctxt)
{}
/* opt_pass methods: */
- opt_pass * clone () { return new pass_cleanup_eh (ctxt_); }
+ opt_pass * clone () { return new pass_cleanup_eh (m_ctxt); }
bool gate () { return gate_cleanup_eh (); }
unsigned int execute () { return execute_cleanup_eh (); }
diff --git a/gcc/tree-eh.h b/gcc/tree-eh.h
new file mode 100644
index 00000000000..308f20f77ee
--- /dev/null
+++ b/gcc/tree-eh.h
@@ -0,0 +1,52 @@
+/* Header file for exception handling.
+ Copyright (C) 2013 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_EH_H
+#define GCC_TREE_EH_H
+
+extern void using_eh_for_cleanups (void);
+extern void add_stmt_to_eh_lp (gimple, int);
+extern bool remove_stmt_from_eh_lp_fn (struct function *, gimple);
+extern bool remove_stmt_from_eh_lp (gimple);
+extern int lookup_stmt_eh_lp_fn (struct function *, gimple);
+extern int lookup_stmt_eh_lp (gimple);
+extern bool make_eh_dispatch_edges (gimple);
+extern void make_eh_edges (gimple);
+extern edge redirect_eh_edge (edge, basic_block);
+extern void redirect_eh_dispatch_edge (gimple, edge, basic_block);
+extern bool operation_could_trap_helper_p (enum tree_code, bool, bool, bool,
+ bool, tree, bool *);
+extern bool operation_could_trap_p (enum tree_code, bool, bool, tree);
+extern bool tree_could_trap_p (tree);
+extern bool stmt_could_throw_p (gimple);
+extern bool tree_could_throw_p (tree);
+extern bool stmt_can_throw_external (gimple);
+extern bool stmt_can_throw_internal (gimple);
+extern bool maybe_clean_eh_stmt_fn (struct function *, gimple);
+extern bool maybe_clean_eh_stmt (gimple);
+extern bool maybe_clean_or_replace_eh_stmt (gimple, gimple);
+extern bool maybe_duplicate_eh_stmt_fn (struct function *, gimple,
+ struct function *, gimple,
+ struct pointer_map_t *, int);
+extern bool maybe_duplicate_eh_stmt (gimple, gimple);
+extern void maybe_remove_unreachable_handlers (void);
+extern bool verify_eh_edges (gimple);
+extern bool verify_eh_dispatch_edge (gimple);
+
+#endif /* GCC_TREE_EH_H */
diff --git a/gcc/tree-emutls.c b/gcc/tree-emutls.c
index 23d50389b98..b5ca407d62e 100644
--- a/gcc/tree-emutls.c
+++ b/gcc/tree-emutls.c
@@ -23,8 +23,11 @@ along with GCC; see the file COPYING3. If not see
#include "tree.h"
#include "gimple.h"
#include "tree-pass.h"
-#include "tree-ssa.h"
+#include "gimple-ssa.h"
#include "cgraph.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
#include "langhooks.h"
#include "target.h"
#include "targhooks.h"
@@ -337,7 +340,7 @@ new_emutls_decl (tree decl, tree alias_of)
else
varpool_create_variable_alias (to,
varpool_node_for_asm
- (DECL_ASSEMBLER_NAME (DECL_VALUE_EXPR (alias_of)))->symbol.decl);
+ (DECL_ASSEMBLER_NAME (DECL_VALUE_EXPR (alias_of)))->decl);
return to;
}
@@ -365,7 +368,7 @@ emutls_decl (tree decl)
i = emutls_index (decl);
var = control_vars[i];
- return var->symbol.decl;
+ return var->decl;
}
/* Generate a call statement to initialize CONTROL_DECL for TLS_DECL.
@@ -427,7 +430,7 @@ gen_emutls_addr (tree decl, struct lower_emutls_data *d)
gimple x;
cvar = control_vars[index];
- cdecl = cvar->symbol.decl;
+ cdecl = cvar->decl;
TREE_ADDRESSABLE (cdecl) = 1;
addr = create_tmp_var (build_pointer_type (TREE_TYPE (decl)), NULL);
@@ -444,7 +447,7 @@ gen_emutls_addr (tree decl, struct lower_emutls_data *d)
/* We may be adding a new reference to a new variable to the function.
This means we have to play with the ipa-reference web. */
- ipa_record_reference ((symtab_node)d->cfun_node, (symtab_node)cvar, IPA_REF_ADDR, x);
+ ipa_record_reference (d->cfun_node, cvar, IPA_REF_ADDR, x);
/* Record this ssa_name for possible use later in the basic block. */
access_vars[index] = addr;
@@ -606,7 +609,7 @@ static inline void
clear_access_vars (void)
{
memset (access_vars.address (), 0,
- access_vars.length () * sizeof(tree));
+ access_vars.length () * sizeof (tree));
}
/* Lower the entire function NODE. */
@@ -617,7 +620,7 @@ lower_emutls_function_body (struct cgraph_node *node)
struct lower_emutls_data d;
bool any_edge_inserts = false;
- push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
+ push_cfun (DECL_STRUCT_FUNCTION (node->decl));
d.cfun_node = node;
d.builtin_decl = builtin_decl_explicit (BUILT_IN_EMUTLS_GET_ADDRESS);
@@ -699,29 +702,29 @@ create_emultls_var (struct varpool_node *var, void *data)
tree cdecl;
struct varpool_node *cvar;
- cdecl = new_emutls_decl (var->symbol.decl,
- var->symbol.alias && var->symbol.analyzed
- ? varpool_alias_target (var)->symbol.decl : NULL);
+ cdecl = new_emutls_decl (var->decl,
+ var->alias && var->analyzed
+ ? varpool_alias_target (var)->decl : NULL);
cvar = varpool_get_node (cdecl);
control_vars.quick_push (cvar);
- if (!var->symbol.alias)
+ if (!var->alias)
{
/* Make sure the COMMON block control variable gets initialized.
Note that there's no point in doing this for aliases; we only
need to do this once for the main variable. */
- emutls_common_1 (var->symbol.decl, cdecl, (tree *)data);
+ emutls_common_1 (var->decl, cdecl, (tree *)data);
}
- if (var->symbol.alias && !var->symbol.analyzed)
- cvar->symbol.alias = true;
+ if (var->alias && !var->analyzed)
+ cvar->alias = true;
/* Indicate that the value of the TLS variable may be found elsewhere,
preventing the variable from re-appearing in the GIMPLE. We cheat
and use the control variable here (rather than a full call_expr),
which is special-cased inside the DWARF2 output routines. */
- SET_DECL_VALUE_EXPR (var->symbol.decl, cdecl);
- DECL_HAS_VALUE_EXPR_P (var->symbol.decl) = 1;
+ SET_DECL_VALUE_EXPR (var->decl, cdecl);
+ DECL_HAS_VALUE_EXPR_P (var->decl) = 1;
return false;
}
@@ -740,12 +743,12 @@ ipa_lower_emutls (void)
/* Examine all global variables for TLS variables. */
FOR_EACH_VARIABLE (var)
- if (DECL_THREAD_LOCAL_P (var->symbol.decl))
+ if (DECL_THREAD_LOCAL_P (var->decl))
{
- gcc_checking_assert (TREE_STATIC (var->symbol.decl)
- || DECL_EXTERNAL (var->symbol.decl));
+ gcc_checking_assert (TREE_STATIC (var->decl)
+ || DECL_EXTERNAL (var->decl));
varpool_node_set_add (tls_vars, var);
- if (var->symbol.alias && var->symbol.definition)
+ if (var->alias && var->definition)
varpool_node_set_add (tls_vars, varpool_variable_node (var, NULL));
}
@@ -769,9 +772,9 @@ ipa_lower_emutls (void)
{
var = tls_vars->nodes[i];
- if (var->symbol.alias && !var->symbol.analyzed)
+ if (var->alias && !var->analyzed)
any_aliases = true;
- else if (!var->symbol.alias)
+ else if (!var->alias)
varpool_for_node_and_aliases (var, create_emultls_var, &ctor_body, true);
}
@@ -831,8 +834,8 @@ const pass_data pass_data_ipa_lower_emutls =
class pass_ipa_lower_emutls : public simple_ipa_opt_pass
{
public:
- pass_ipa_lower_emutls(gcc::context *ctxt)
- : simple_ipa_opt_pass(pass_data_ipa_lower_emutls, ctxt)
+ pass_ipa_lower_emutls (gcc::context *ctxt)
+ : simple_ipa_opt_pass (pass_data_ipa_lower_emutls, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/tree-flow-inline.h b/gcc/tree-flow-inline.h
deleted file mode 100644
index 03c4840bf1a..00000000000
--- a/gcc/tree-flow-inline.h
+++ /dev/null
@@ -1,1306 +0,0 @@
-/* Inline functions for tree-flow.h
- Copyright (C) 2001-2013 Free Software Foundation, Inc.
- Contributed by Diego Novillo <dnovillo@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 _TREE_FLOW_INLINE_H
-#define _TREE_FLOW_INLINE_H 1
-
-/* Inline functions for manipulating various data structures defined in
- tree-flow.h. See tree-flow.h for documentation. */
-
-/* Return true when gimple SSA form was built.
- gimple_in_ssa_p is queried by gimplifier in various early stages before SSA
- infrastructure is initialized. Check for presence of the datastructures
- at first place. */
-static inline bool
-gimple_in_ssa_p (const struct function *fun)
-{
- return fun && fun->gimple_df && fun->gimple_df->in_ssa_p;
-}
-
-/* Artificial variable used for the virtual operand FUD chain. */
-static inline tree
-gimple_vop (const struct function *fun)
-{
- gcc_checking_assert (fun && fun->gimple_df);
- return fun->gimple_df->vop;
-}
-
-/* Initialize the hashtable iterator HTI to point to hashtable TABLE */
-
-static inline void *
-first_htab_element (htab_iterator *hti, htab_t table)
-{
- hti->htab = table;
- hti->slot = table->entries;
- hti->limit = hti->slot + htab_size (table);
- do
- {
- PTR x = *(hti->slot);
- if (x != HTAB_EMPTY_ENTRY && x != HTAB_DELETED_ENTRY)
- break;
- } while (++(hti->slot) < hti->limit);
-
- if (hti->slot < hti->limit)
- return *(hti->slot);
- return NULL;
-}
-
-/* Return current non-empty/deleted slot of the hashtable pointed to by HTI,
- or NULL if we have reached the end. */
-
-static inline bool
-end_htab_p (const htab_iterator *hti)
-{
- if (hti->slot >= hti->limit)
- return true;
- return false;
-}
-
-/* Advance the hashtable iterator pointed to by HTI to the next element of the
- hashtable. */
-
-static inline void *
-next_htab_element (htab_iterator *hti)
-{
- while (++(hti->slot) < hti->limit)
- {
- PTR x = *(hti->slot);
- if (x != HTAB_EMPTY_ENTRY && x != HTAB_DELETED_ENTRY)
- return x;
- };
- return NULL;
-}
-
-/* Get the number of the next statement uid to be allocated. */
-static inline unsigned int
-gimple_stmt_max_uid (struct function *fn)
-{
- return fn->last_stmt_uid;
-}
-
-/* Set the number of the next statement uid to be allocated. */
-static inline void
-set_gimple_stmt_max_uid (struct function *fn, unsigned int maxid)
-{
- fn->last_stmt_uid = maxid;
-}
-
-/* Set the number of the next statement uid to be allocated. */
-static inline unsigned int
-inc_gimple_stmt_max_uid (struct function *fn)
-{
- return fn->last_stmt_uid++;
-}
-
-/* Return the line number for EXPR, or return -1 if we have no line
- number information for it. */
-static inline int
-get_lineno (const_gimple stmt)
-{
- location_t loc;
-
- if (!stmt)
- return -1;
-
- loc = gimple_location (stmt);
- if (loc == UNKNOWN_LOCATION)
- return -1;
-
- return LOCATION_LINE (loc);
-}
-
-/* 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;
-#ifdef ENABLE_CHECKING
- imm->iter_node.next = imm->imm_use->next;
-#endif
- 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;
-
-#ifdef ENABLE_CHECKING
- /* 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. */
- gcc_assert (imm->iter_node.next == old->next);
- imm->iter_node.next = old->next->next;
-#endif
-
- imm->imm_use = old->next;
- if (end_readonly_imm_use_p (imm))
- return NULL_USE_OPERAND_P;
- return imm->imm_use;
-}
-
-/* tree-cfg.c */
-extern bool has_zero_uses_1 (const ssa_use_operand_t *head);
-extern bool single_imm_use_1 (const ssa_use_operand_t *head,
- use_operand_p *use_p, gimple *stmt);
-
-/* Return true if VAR has no nondebug uses. */
-static inline bool
-has_zero_uses (const_tree var)
-{
- const ssa_use_operand_t *const ptr = &(SSA_NAME_IMM_USE_NODE (var));
-
- /* A single use_operand means there is no items in the list. */
- if (ptr == ptr->next)
- return true;
-
- /* If there are debug stmts, we have to look at each use and see
- whether there are any nondebug uses. */
- if (!MAY_HAVE_DEBUG_STMTS)
- return false;
-
- return has_zero_uses_1 (ptr);
-}
-
-/* Return true if VAR has a single nondebug use. */
-static inline bool
-has_single_use (const_tree var)
-{
- 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;
-
- /* If there's a single use, check that it's not a debug stmt. */
- if (ptr == ptr->next->next)
- return !is_gimple_debug (USE_STMT (ptr->next));
-
- /* If there are debug stmts, we have to look at each of them. */
- if (!MAY_HAVE_DEBUG_STMTS)
- return false;
-
- return single_imm_use_1 (ptr, NULL, NULL);
-}
-
-
-/* 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 (!is_gimple_debug (USE_STMT (ptr->next)))
- {
- *use_p = ptr->next;
- *stmt = ptr->next->loc.stmt;
- return true;
- }
- else
- goto return_false;
- }
-
- /* If there are debug stmts, we have to look at each of them. */
- if (!MAY_HAVE_DEBUG_STMTS)
- 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_STMTS)
- for (ptr = start->next; ptr != start; ptr = ptr->next)
- num++;
- else
- for (ptr = start->next; ptr != start; ptr = ptr->next)
- if (!is_gimple_debug (USE_STMT (ptr)))
- num++;
-
- return num;
-}
-
-/* Return the tree pointed-to by USE. */
-static inline tree
-get_use_from_ptr (use_operand_p use)
-{
- return *(use->use);
-}
-
-/* Return the tree pointed-to by DEF. */
-static inline tree
-get_def_from_ptr (def_operand_p def)
-{
- return *def;
-}
-
-/* Return a use_operand_p pointer for argument I of PHI node GS. */
-
-static inline use_operand_p
-gimple_phi_arg_imm_use_ptr (gimple gs, int i)
-{
- return &gimple_phi_arg (gs, i)->imm_use;
-}
-
-/* Return the tree operand for argument I of PHI node GS. */
-
-static inline tree
-gimple_phi_arg_def (gimple gs, size_t index)
-{
- struct phi_arg_d *pd = gimple_phi_arg (gs, index);
- return get_use_from_ptr (&pd->imm_use);
-}
-
-/* Return a pointer to the tree operand for argument I of PHI node GS. */
-
-static inline tree *
-gimple_phi_arg_def_ptr (gimple gs, size_t index)
-{
- return &gimple_phi_arg (gs, index)->def;
-}
-
-/* Return the edge associated with argument I of phi node GS. */
-
-static inline edge
-gimple_phi_arg_edge (gimple gs, size_t i)
-{
- return EDGE_PRED (gimple_bb (gs), i);
-}
-
-/* Return the source location of gimple argument I of phi node GS. */
-
-static inline source_location
-gimple_phi_arg_location (gimple gs, size_t i)
-{
- return gimple_phi_arg (gs, i)->locus;
-}
-
-/* Return the source location of the argument on edge E of phi node GS. */
-
-static inline source_location
-gimple_phi_arg_location_from_edge (gimple gs, edge e)
-{
- return gimple_phi_arg (gs, e->dest_idx)->locus;
-}
-
-/* Set the source location of gimple argument I of phi node GS to LOC. */
-
-static inline void
-gimple_phi_arg_set_location (gimple gs, size_t i, source_location loc)
-{
- gimple_phi_arg (gs, i)->locus = loc;
-}
-
-/* Return TRUE if argument I of phi node GS has a location record. */
-
-static inline bool
-gimple_phi_arg_has_location (gimple gs, size_t i)
-{
- return gimple_phi_arg_location (gs, i) != UNKNOWN_LOCATION;
-}
-
-
-/* Return the PHI nodes for basic block BB, or NULL if there are no
- PHI nodes. */
-static inline gimple_seq
-phi_nodes (const_basic_block bb)
-{
- gcc_checking_assert (!(bb->flags & BB_RTL));
- return bb->il.gimple.phi_nodes;
-}
-
-static inline gimple_seq *
-phi_nodes_ptr (basic_block bb)
-{
- gcc_checking_assert (!(bb->flags & BB_RTL));
- return &bb->il.gimple.phi_nodes;
-}
-
-/* Set PHI nodes of a basic block BB to SEQ. */
-
-static inline void
-set_phi_nodes (basic_block bb, gimple_seq seq)
-{
- gimple_stmt_iterator i;
-
- gcc_checking_assert (!(bb->flags & BB_RTL));
- bb->il.gimple.phi_nodes = seq;
- if (seq)
- for (i = gsi_start (seq); !gsi_end_p (i); gsi_next (&i))
- gimple_set_bb (gsi_stmt (i), bb);
-}
-
-/* Return the phi argument which contains the specified use. */
-
-static inline int
-phi_arg_index_from_use (use_operand_p use)
-{
- struct phi_arg_d *element, *root;
- size_t index;
- gimple phi;
-
- /* Since the use is the first thing in a PHI argument element, we can
- calculate its index based on casting it to an argument, and performing
- pointer arithmetic. */
-
- phi = USE_STMT (use);
-
- element = (struct phi_arg_d *)use;
- root = gimple_phi_arg (phi, 0);
- index = element - root;
-
- /* Make sure the calculation doesn't have any leftover bytes. If it does,
- then imm_use is likely not the first element in phi_arg_d. */
- gcc_checking_assert ((((char *)element - (char *)root)
- % sizeof (struct phi_arg_d)) == 0
- && index < gimple_phi_capacity (phi));
-
- return index;
-}
-
-/* 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_STATIC (var) || TREE_PUBLIC (var) || DECL_EXTERNAL (var))
- && TREE_READONLY (var)
- && !TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (var)))
- && (TREE_PUBLIC (var)
- || DECL_EXTERNAL (var)
- || TREE_ADDRESSABLE (var)));
-}
-
-
-/* PHI nodes should contain only ssa_names and invariants. A test
- for ssa_name is definitely simpler; don't let invalid contents
- slip in in the meantime. */
-
-static inline bool
-phi_ssa_name_p (const_tree t)
-{
- if (TREE_CODE (t) == SSA_NAME)
- return true;
- gcc_checking_assert (is_gimple_min_invariant (t));
- return false;
-}
-
-
-/* Returns the loop of the statement STMT. */
-
-static inline struct loop *
-loop_containing_stmt (gimple stmt)
-{
- basic_block bb = gimple_bb (stmt);
- if (!bb)
- return NULL;
-
- return bb->loop_father;
-}
-
-
-/* ----------------------------------------------------------------------- */
-
-/* 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 (stmt);
- 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;
-}
-
-
-
-/* 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;
-}
-
-static inline use_operand_p
-op_iter_init_phiuse (ssa_op_iter *ptr, gimple phi, int flags);
-
-/* 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);
-}
-
-
-/* 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 (gimple 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, gimple 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, gimple 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 (gimple_code (head_stmt) == GIMPLE_PHI)
- {
- FOR_EACH_PHI_ARG (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 (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;
- }
-}
-
-/* Return true if VAR cannot be modified by the program. */
-
-static inline bool
-unmodifiable_var_p (const_tree var)
-{
- if (TREE_CODE (var) == SSA_NAME)
- var = SSA_NAME_VAR (var);
-
- return TREE_READONLY (var) && (TREE_STATIC (var) || DECL_EXTERNAL (var));
-}
-
-/* Return true if REF, a handled component reference, has an ARRAY_REF
- somewhere in it. */
-
-static inline bool
-ref_contains_array_ref (const_tree ref)
-{
- gcc_checking_assert (handled_component_p (ref));
-
- do {
- if (TREE_CODE (ref) == ARRAY_REF)
- return true;
- ref = TREE_OPERAND (ref, 0);
- } while (handled_component_p (ref));
-
- return false;
-}
-
-/* Return true if REF has an VIEW_CONVERT_EXPR somewhere in it. */
-
-static inline bool
-contains_view_convert_expr_p (const_tree ref)
-{
- while (handled_component_p (ref))
- {
- if (TREE_CODE (ref) == VIEW_CONVERT_EXPR)
- return true;
- ref = TREE_OPERAND (ref, 0);
- }
-
- return false;
-}
-
-/* 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 (unsigned HOST_WIDE_INT pos1,
- unsigned HOST_WIDE_INT size1,
- unsigned HOST_WIDE_INT pos2,
- unsigned HOST_WIDE_INT size2)
-{
- if (pos1 >= pos2
- && (size2 == (unsigned HOST_WIDE_INT)-1
- || pos1 < (pos2 + size2)))
- return true;
- if (pos2 >= pos1
- && (size1 == (unsigned HOST_WIDE_INT)-1
- || pos2 < (pos1 + size1)))
- return true;
-
- return false;
-}
-
-/* Accessor to tree-ssa-operands.c caches. */
-static inline struct ssa_operands *
-gimple_ssa_operands (const struct function *fun)
-{
- return &fun->gimple_df->ssa_operands;
-}
-
-
-/* Returns the base object and a constant BITS_PER_UNIT offset in *POFFSET that
- denotes the starting address of the memory access EXP.
- Returns NULL_TREE if the offset is not constant or any component
- is not BITS_PER_UNIT-aligned.
- VALUEIZE if non-NULL is used to valueize SSA names. It should return
- its argument or a constant if the argument is known to be constant. */
-/* ??? This is a static inline here to avoid the overhead of the indirect calls
- to VALUEIZE. But is this overhead really that significant? And should we
- perhaps just rely on WHOPR to specialize the function? */
-
-static inline tree
-get_addr_base_and_unit_offset_1 (tree exp, HOST_WIDE_INT *poffset,
- tree (*valueize) (tree))
-{
- HOST_WIDE_INT byte_offset = 0;
-
- /* Compute cumulative byte-offset for nested component-refs and array-refs,
- and find the ultimate containing object. */
- while (1)
- {
- switch (TREE_CODE (exp))
- {
- case BIT_FIELD_REF:
- {
- HOST_WIDE_INT this_off = TREE_INT_CST_LOW (TREE_OPERAND (exp, 2));
- if (this_off % BITS_PER_UNIT)
- return NULL_TREE;
- byte_offset += this_off / BITS_PER_UNIT;
- }
- break;
-
- case COMPONENT_REF:
- {
- tree field = TREE_OPERAND (exp, 1);
- tree this_offset = component_ref_field_offset (exp);
- HOST_WIDE_INT hthis_offset;
-
- if (!this_offset
- || TREE_CODE (this_offset) != INTEGER_CST
- || (TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field))
- % BITS_PER_UNIT))
- return NULL_TREE;
-
- hthis_offset = TREE_INT_CST_LOW (this_offset);
- hthis_offset += (TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field))
- / BITS_PER_UNIT);
- byte_offset += hthis_offset;
- }
- break;
-
- case ARRAY_REF:
- case ARRAY_RANGE_REF:
- {
- tree index = TREE_OPERAND (exp, 1);
- tree low_bound, unit_size;
-
- if (valueize
- && TREE_CODE (index) == SSA_NAME)
- index = (*valueize) (index);
-
- /* If the resulting bit-offset is constant, track it. */
- if (TREE_CODE (index) == INTEGER_CST
- && (low_bound = array_ref_low_bound (exp),
- TREE_CODE (low_bound) == INTEGER_CST)
- && (unit_size = array_ref_element_size (exp),
- TREE_CODE (unit_size) == INTEGER_CST))
- {
- HOST_WIDE_INT hindex = TREE_INT_CST_LOW (index);
-
- hindex -= TREE_INT_CST_LOW (low_bound);
- hindex *= TREE_INT_CST_LOW (unit_size);
- byte_offset += hindex;
- }
- else
- return NULL_TREE;
- }
- break;
-
- case REALPART_EXPR:
- break;
-
- case IMAGPART_EXPR:
- byte_offset += TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (exp)));
- break;
-
- case VIEW_CONVERT_EXPR:
- break;
-
- case MEM_REF:
- {
- tree base = TREE_OPERAND (exp, 0);
- if (valueize
- && TREE_CODE (base) == SSA_NAME)
- base = (*valueize) (base);
-
- /* Hand back the decl for MEM[&decl, off]. */
- if (TREE_CODE (base) == ADDR_EXPR)
- {
- if (!integer_zerop (TREE_OPERAND (exp, 1)))
- {
- double_int off = mem_ref_offset (exp);
- gcc_assert (off.high == -1 || off.high == 0);
- byte_offset += off.to_shwi ();
- }
- exp = TREE_OPERAND (base, 0);
- }
- goto done;
- }
-
- case TARGET_MEM_REF:
- {
- tree base = TREE_OPERAND (exp, 0);
- if (valueize
- && TREE_CODE (base) == SSA_NAME)
- base = (*valueize) (base);
-
- /* Hand back the decl for MEM[&decl, off]. */
- if (TREE_CODE (base) == ADDR_EXPR)
- {
- if (TMR_INDEX (exp) || TMR_INDEX2 (exp))
- return NULL_TREE;
- if (!integer_zerop (TMR_OFFSET (exp)))
- {
- double_int off = mem_ref_offset (exp);
- gcc_assert (off.high == -1 || off.high == 0);
- byte_offset += off.to_shwi ();
- }
- exp = TREE_OPERAND (base, 0);
- }
- goto done;
- }
-
- default:
- goto done;
- }
-
- exp = TREE_OPERAND (exp, 0);
- }
-done:
-
- *poffset = byte_offset;
- return exp;
-}
-
-#endif /* _TREE_FLOW_INLINE_H */
diff --git a/gcc/tree-flow.h b/gcc/tree-flow.h
deleted file mode 100644
index 2f64abc2bbd..00000000000
--- a/gcc/tree-flow.h
+++ /dev/null
@@ -1,696 +0,0 @@
-/* Data and Control Flow Analysis for Trees.
- Copyright (C) 2001-2013 Free Software Foundation, Inc.
- Contributed by Diego Novillo <dnovillo@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 _TREE_FLOW_H
-#define _TREE_FLOW_H 1
-
-#include "bitmap.h"
-#include "sbitmap.h"
-#include "basic-block.h"
-#include "hashtab.h"
-#include "gimple.h"
-#include "tree-ssa-operands.h"
-#include "cgraph.h"
-#include "ipa-reference.h"
-#include "tree-ssa-alias.h"
-
-
-/* This structure is used to map a gimple statement to a label,
- or list of labels to represent transaction restart. */
-
-struct GTY(()) tm_restart_node {
- gimple stmt;
- tree label_or_list;
-};
-
-/* Gimple dataflow datastructure. All publicly available fields shall have
- gimple_ accessor defined in tree-flow-inline.h, all publicly modifiable
- fields should have gimple_set accessor. */
-struct GTY(()) gimple_df {
- /* A vector of all the noreturn calls passed to modify_stmt.
- cleanup_control_flow uses it to detect cases where a mid-block
- indirect call has been turned into a noreturn call. When this
- happens, all the instructions after the call are no longer
- reachable and must be deleted as dead. */
- vec<gimple, va_gc> *modified_noreturn_calls;
-
- /* Array of all SSA_NAMEs used in the function. */
- vec<tree, va_gc> *ssa_names;
-
- /* Artificial variable used for the virtual operand FUD chain. */
- tree vop;
-
- /* The PTA solution for the ESCAPED artificial variable. */
- struct pt_solution escaped;
-
- /* A map of decls to artificial ssa-names that point to the partition
- of the decl. */
- struct pointer_map_t * GTY((skip(""))) decls_to_pointers;
-
- /* Free list of SSA_NAMEs. */
- vec<tree, va_gc> *free_ssanames;
-
- /* Hashtable holding definition for symbol. If this field is not NULL, it
- means that the first reference to this variable in the function is a
- USE or a VUSE. In those cases, the SSA renamer creates an SSA name
- for this variable with an empty defining statement. */
- htab_t GTY((param_is (union tree_node))) default_defs;
-
- /* True if there are any symbols that need to be renamed. */
- unsigned int ssa_renaming_needed : 1;
-
- /* True if all virtual operands need to be renamed. */
- unsigned int rename_vops : 1;
-
- /* True if the code is in ssa form. */
- unsigned int in_ssa_p : 1;
-
- /* True if IPA points-to information was computed for this function. */
- unsigned int ipa_pta : 1;
-
- struct ssa_operands ssa_operands;
-
- /* Map gimple stmt to tree label (or list of labels) for transaction
- restart and abort. */
- htab_t GTY ((param_is (struct tm_restart_node))) tm_restart;
-};
-
-
-typedef struct
-{
- htab_t htab;
- PTR *slot;
- PTR *limit;
-} htab_iterator;
-
-/* Iterate through the elements of hashtable HTAB, using htab_iterator ITER,
- storing each element in RESULT, which is of type TYPE. */
-#define FOR_EACH_HTAB_ELEMENT(HTAB, RESULT, TYPE, ITER) \
- for (RESULT = (TYPE) first_htab_element (&(ITER), (HTAB)); \
- !end_htab_p (&(ITER)); \
- RESULT = (TYPE) next_htab_element (&(ITER)))
-
-/* It is advantageous to avoid things like life analysis for variables which
- do not need PHI nodes. This enum describes whether or not a particular
- variable may need a PHI node. */
-
-enum need_phi_state {
- /* This is the default. If we are still in this state after finding
- all the definition and use sites, then we will assume the variable
- needs PHI nodes. This is probably an overly conservative assumption. */
- NEED_PHI_STATE_UNKNOWN,
-
- /* This state indicates that we have seen one or more sets of the
- variable in a single basic block and that the sets dominate all
- uses seen so far. If after finding all definition and use sites
- we are still in this state, then the variable does not need any
- PHI nodes. */
- NEED_PHI_STATE_NO,
-
- /* This state indicates that we have either seen multiple definitions of
- the variable in multiple blocks, or that we encountered a use in a
- block that was not dominated by the block containing the set(s) of
- this variable. This variable is assumed to need PHI nodes. */
- NEED_PHI_STATE_MAYBE
-};
-
-
-/* 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_d 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. */
-typedef struct immediate_use_iterator_d
-{
- /* 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;
-} imm_use_iterator;
-
-
-/* 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))))
-
-/* Use this iterator to visit each stmt which has a use of SSAVAR. */
-
-#define FOR_EACH_IMM_USE_STMT(STMT, ITER, SSAVAR) \
- for ((STMT) = first_imm_use_stmt (&(ITER), (SSAVAR)); \
- !end_imm_use_stmt_p (&(ITER)); \
- (void) ((STMT) = next_imm_use_stmt (&(ITER))))
-
-/* Use this to terminate the FOR_EACH_IMM_USE_STMT loop early. Failure to
- do so will result in leaving a iterator marker node in the immediate
- use list, and nothing good will come from that. */
-#define BREAK_FROM_IMM_USE_STMT(ITER) \
- { \
- end_imm_use_stmt_traverse (&(ITER)); \
- break; \
- }
-
-
-/* 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, var)
- {
- 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))))
-
-
-
-static inline void update_stmt (gimple);
-static inline int get_lineno (const_gimple);
-
-/* Accessors for basic block annotations. */
-static inline gimple_seq phi_nodes (const_basic_block);
-static inline void set_phi_nodes (basic_block, gimple_seq);
-
-/*---------------------------------------------------------------------------
- Global declarations
----------------------------------------------------------------------------*/
-struct int_tree_map {
- unsigned int uid;
- tree to;
-};
-
-/* Macros for showing usage statistics. */
-#define SCALE(x) ((unsigned long) ((x) < 1024*10 \
- ? (x) \
- : ((x) < 1024*1024*10 \
- ? (x) / 1024 \
- : (x) / (1024*1024))))
-
-#define LABEL(x) ((x) < 1024*10 ? 'b' : ((x) < 1024*1024*10 ? 'k' : 'M'))
-
-#define PERCENT(x,y) ((float)(x) * 100.0 / (float)(y))
-
-/*---------------------------------------------------------------------------
- OpenMP Region Tree
----------------------------------------------------------------------------*/
-
-/* Parallel region information. Every parallel and workshare
- directive is enclosed between two markers, the OMP_* directive
- and a corresponding OMP_RETURN statement. */
-
-struct omp_region
-{
- /* The enclosing region. */
- struct omp_region *outer;
-
- /* First child region. */
- struct omp_region *inner;
-
- /* Next peer region. */
- struct omp_region *next;
-
- /* Block containing the omp directive as its last stmt. */
- basic_block entry;
-
- /* Block containing the OMP_RETURN as its last stmt. */
- basic_block exit;
-
- /* Block containing the OMP_CONTINUE as its last stmt. */
- basic_block cont;
-
- /* If this is a combined parallel+workshare region, this is a list
- of additional arguments needed by the combined parallel+workshare
- library call. */
- vec<tree, va_gc> *ws_args;
-
- /* The code for the omp directive of this region. */
- enum gimple_code type;
-
- /* Schedule kind, only used for OMP_FOR type regions. */
- enum omp_clause_schedule_kind sched_kind;
-
- /* True if this is a combined parallel+workshare region. */
- bool is_combined_parallel;
-};
-
-extern struct omp_region *root_omp_region;
-extern struct omp_region *new_omp_region (basic_block, enum gimple_code,
- struct omp_region *);
-extern void free_omp_regions (void);
-void omp_expand_local (basic_block);
-tree copy_var_decl (tree, tree, tree);
-
-/*---------------------------------------------------------------------------
- Function prototypes
----------------------------------------------------------------------------*/
-/* In tree-cfg.c */
-
-/* Location to track pending stmt for edge insertion. */
-#define PENDING_STMT(e) ((e)->insns.g)
-
-extern void delete_tree_cfg_annotations (void);
-extern bool stmt_ends_bb_p (gimple);
-extern bool is_ctrl_stmt (gimple);
-extern bool is_ctrl_altering_stmt (gimple);
-extern bool simple_goto_p (gimple);
-extern bool stmt_can_make_abnormal_goto (gimple);
-extern basic_block single_noncomplex_succ (basic_block bb);
-extern void gimple_dump_bb (FILE *, basic_block, int, int);
-extern void gimple_debug_bb (basic_block);
-extern basic_block gimple_debug_bb_n (int);
-extern void gimple_dump_cfg (FILE *, int);
-extern void gimple_debug_cfg (int);
-extern void dump_cfg_stats (FILE *);
-extern void dot_cfg (void);
-extern void debug_cfg_stats (void);
-extern void debug_loops (int);
-extern void debug_loop (struct loop *, int);
-extern void debug (struct loop &ref);
-extern void debug (struct loop *ptr);
-extern void debug_verbose (struct loop &ref);
-extern void debug_verbose (struct loop *ptr);
-extern void debug_loop_num (unsigned, int);
-extern void print_loops (FILE *, int);
-extern void print_loops_bb (FILE *, basic_block, int, int);
-extern void cleanup_dead_labels (void);
-extern void group_case_labels_stmt (gimple);
-extern void group_case_labels (void);
-extern gimple first_stmt (basic_block);
-extern gimple last_stmt (basic_block);
-extern gimple last_and_only_stmt (basic_block);
-extern edge find_taken_edge (basic_block, tree);
-extern basic_block label_to_block_fn (struct function *, tree);
-#define label_to_block(t) (label_to_block_fn (cfun, t))
-extern void notice_special_calls (gimple);
-extern void clear_special_calls (void);
-extern void verify_gimple_in_seq (gimple_seq);
-extern void verify_gimple_in_cfg (struct function *);
-extern tree gimple_block_label (basic_block);
-extern void extract_true_false_edges_from_block (basic_block, edge *, edge *);
-extern bool gimple_duplicate_sese_region (edge, edge, basic_block *, unsigned,
- basic_block *, bool);
-extern bool gimple_duplicate_sese_tail (edge, edge, basic_block *, unsigned,
- basic_block *);
-extern void gather_blocks_in_sese_region (basic_block entry, basic_block exit,
- vec<basic_block> *bbs_p);
-extern void add_phi_args_after_copy_bb (basic_block);
-extern void add_phi_args_after_copy (basic_block *, unsigned, edge);
-extern bool gimple_purge_dead_eh_edges (basic_block);
-extern bool gimple_purge_all_dead_eh_edges (const_bitmap);
-extern bool gimple_purge_dead_abnormal_call_edges (basic_block);
-extern bool gimple_purge_all_dead_abnormal_call_edges (const_bitmap);
-extern tree gimplify_build1 (gimple_stmt_iterator *, enum tree_code,
- tree, tree);
-extern tree gimplify_build2 (gimple_stmt_iterator *, enum tree_code,
- tree, tree, tree);
-extern tree gimplify_build3 (gimple_stmt_iterator *, enum tree_code,
- tree, tree, tree, tree);
-extern void init_empty_tree_cfg (void);
-extern void init_empty_tree_cfg_for_function (struct function *);
-extern void fold_cond_expr_cond (void);
-extern void make_abnormal_goto_edges (basic_block, bool);
-extern void replace_uses_by (tree, tree);
-extern void start_recording_case_labels (void);
-extern void end_recording_case_labels (void);
-extern basic_block move_sese_region_to_fn (struct function *, basic_block,
- basic_block, tree);
-void remove_edge_and_dominated_blocks (edge);
-bool tree_node_can_be_shared (tree);
-
-/* In tree-cfgcleanup.c */
-extern bitmap cfgcleanup_altered_bbs;
-extern bool cleanup_tree_cfg (void);
-
-/* In tree-pretty-print.c. */
-extern void dump_generic_bb (FILE *, basic_block, int, int);
-extern int op_code_prio (enum tree_code);
-extern int op_prio (const_tree);
-extern const char *op_symbol_code (enum tree_code);
-
-/* In tree-dfa.c */
-extern void renumber_gimple_stmt_uids (void);
-extern void renumber_gimple_stmt_uids_in_blocks (basic_block *, int);
-extern void dump_dfa_stats (FILE *);
-extern void debug_dfa_stats (void);
-extern void dump_variable (FILE *, tree);
-extern void debug_variable (tree);
-extern void set_ssa_default_def (struct function *, tree, tree);
-extern tree ssa_default_def (struct function *, tree);
-extern tree get_or_create_ssa_default_def (struct function *, tree);
-extern bool stmt_references_abnormal_ssa_name (gimple);
-extern tree get_addr_base_and_unit_offset (tree, HOST_WIDE_INT *);
-extern void dump_enumerated_decls (FILE *, int);
-
-/* In tree-phinodes.c */
-extern void reserve_phi_args_for_new_edge (basic_block);
-extern void add_phi_node_to_bb (gimple phi, basic_block bb);
-extern gimple create_phi_node (tree, basic_block);
-extern void add_phi_arg (gimple, tree, edge, source_location);
-extern void remove_phi_args (edge);
-extern void remove_phi_node (gimple_stmt_iterator *, bool);
-extern void remove_phi_nodes (basic_block);
-extern void release_phi_node (gimple);
-extern void phinodes_print_statistics (void);
-
-/* In gimple-low.c */
-extern void record_vars_into (tree, tree);
-extern void record_vars (tree);
-extern bool gimple_seq_may_fallthru (gimple_seq);
-extern bool gimple_stmt_may_fallthru (gimple);
-extern bool gimple_check_call_matching_types (gimple, tree, bool);
-
-/* In tree-into-ssa.c */
-void update_ssa (unsigned);
-void delete_update_ssa (void);
-tree create_new_def_for (tree, gimple, def_operand_p);
-bool need_ssa_update_p (struct function *);
-bool name_registered_for_update_p (tree);
-void release_ssa_name_after_update_ssa (tree);
-void mark_virtual_operands_for_renaming (struct function *);
-tree get_current_def (tree);
-void set_current_def (tree, tree);
-
-/* In tree-ssa-ccp.c */
-tree fold_const_aggregate_ref (tree);
-tree gimple_fold_stmt_to_constant (gimple, tree (*)(tree));
-
-/* In tree-ssa-dom.c */
-extern void dump_dominator_optimization_stats (FILE *);
-extern void debug_dominator_optimization_stats (void);
-int loop_depth_of_name (tree);
-tree degenerate_phi_result (gimple);
-bool simple_iv_increment_p (gimple);
-
-/* In tree-ssa-copy.c */
-extern void propagate_value (use_operand_p, tree);
-extern void propagate_tree_value (tree *, tree);
-extern void propagate_tree_value_into_stmt (gimple_stmt_iterator *, tree);
-extern void replace_exp (use_operand_p, tree);
-extern bool may_propagate_copy (tree, tree);
-extern bool may_propagate_copy_into_stmt (gimple, tree);
-extern bool may_propagate_copy_into_asm (tree);
-
-/* In tree-ssa-loop-ch.c */
-bool do_while_loop_p (struct loop *);
-
-/* Affine iv. */
-
-typedef struct
-{
- /* Iv = BASE + STEP * i. */
- tree base, step;
-
- /* True if this iv does not overflow. */
- bool no_overflow;
-} affine_iv;
-
-/* Description of number of iterations of a loop. All the expressions inside
- the structure can be evaluated at the end of the loop's preheader
- (and due to ssa form, also anywhere inside the body of the loop). */
-
-struct tree_niter_desc
-{
- tree assumptions; /* The boolean expression. If this expression evaluates
- to false, then the other fields in this structure
- should not be used; there is no guarantee that they
- will be correct. */
- tree may_be_zero; /* The boolean expression. If it evaluates to true,
- the loop will exit in the first iteration (i.e.
- its latch will not be executed), even if the niter
- field says otherwise. */
- tree niter; /* The expression giving the number of iterations of
- a loop (provided that assumptions == true and
- may_be_zero == false), more precisely the number
- of executions of the latch of the loop. */
- double_int max; /* The upper bound on the number of iterations of
- the loop. */
-
- /* The simplified shape of the exit condition. The loop exits if
- CONTROL CMP BOUND is false, where CMP is one of NE_EXPR,
- LT_EXPR, or GT_EXPR, and step of CONTROL is positive if CMP is
- LE_EXPR and negative if CMP is GE_EXPR. This information is used
- by loop unrolling. */
- affine_iv control;
- tree bound;
- enum tree_code cmp;
-};
-
-/* In tree-ssa-phiopt.c */
-bool empty_block_p (basic_block);
-basic_block *blocks_in_phiopt_order (void);
-bool nonfreeing_call_p (gimple);
-
-/* In tree-ssa-loop*.c */
-
-unsigned int tree_ssa_lim (void);
-unsigned int tree_ssa_unswitch_loops (void);
-unsigned int canonicalize_induction_variables (void);
-unsigned int tree_unroll_loops_completely (bool, bool);
-unsigned int tree_ssa_prefetch_arrays (void);
-void tree_ssa_iv_optimize (void);
-unsigned tree_predictive_commoning (void);
-tree canonicalize_loop_ivs (struct loop *, tree *, bool);
-bool parallelize_loops (void);
-
-bool loop_only_exit_p (const struct loop *, const_edge);
-bool number_of_iterations_exit (struct loop *, edge,
- struct tree_niter_desc *niter, bool,
- bool every_iteration = true);
-tree find_loop_niter (struct loop *, edge *);
-tree loop_niter_by_eval (struct loop *, edge);
-tree find_loop_niter_by_eval (struct loop *, edge *);
-void estimate_numbers_of_iterations (void);
-bool scev_probably_wraps_p (tree, tree, gimple, struct loop *, bool);
-bool convert_affine_scev (struct loop *, tree, tree *, tree *, gimple, bool);
-
-bool nowrap_type_p (tree);
-enum ev_direction {EV_DIR_GROWS, EV_DIR_DECREASES, EV_DIR_UNKNOWN};
-enum ev_direction scev_direction (const_tree);
-
-void free_numbers_of_iterations_estimates (void);
-void free_numbers_of_iterations_estimates_loop (struct loop *);
-void rewrite_into_loop_closed_ssa (bitmap, unsigned);
-void verify_loop_closed_ssa (bool);
-bool for_each_index (tree *, bool (*) (tree, tree *, void *), void *);
-void create_iv (tree, tree, tree, struct loop *, gimple_stmt_iterator *, bool,
- tree *, tree *);
-basic_block split_loop_exit_edge (edge);
-void standard_iv_increment_position (struct loop *, gimple_stmt_iterator *,
- bool *);
-basic_block ip_end_pos (struct loop *);
-basic_block ip_normal_pos (struct loop *);
-bool gimple_duplicate_loop_to_header_edge (struct loop *, edge,
- unsigned int, sbitmap,
- edge, vec<edge> *,
- int);
-struct loop *slpeel_tree_duplicate_loop_to_edge_cfg (struct loop *, edge);
-tree expand_simple_operations (tree);
-void substitute_in_loop_info (struct loop *, tree, tree);
-edge single_dom_exit (struct loop *);
-bool can_unroll_loop_p (struct loop *loop, unsigned factor,
- struct tree_niter_desc *niter);
-void tree_unroll_loop (struct loop *, unsigned,
- edge, struct tree_niter_desc *);
-typedef void (*transform_callback)(struct loop *, void *);
-void tree_transform_and_unroll_loop (struct loop *, unsigned,
- edge, struct tree_niter_desc *,
- transform_callback, void *);
-bool contains_abnormal_ssa_name_p (tree);
-bool stmt_dominates_stmt_p (gimple, gimple);
-
-/* In tree-ssa-dce.c */
-void mark_virtual_operand_for_renaming (tree);
-void mark_virtual_phi_result_for_renaming (gimple);
-
-/* In tree-ssa-threadedge.c */
-extern void threadedge_initialize_values (void);
-extern void threadedge_finalize_values (void);
-extern vec<tree> ssa_name_values;
-#define SSA_NAME_VALUE(x) \
- (SSA_NAME_VERSION(x) < ssa_name_values.length () \
- ? ssa_name_values[SSA_NAME_VERSION(x)] \
- : NULL_TREE)
-extern void set_ssa_name_value (tree, tree);
-extern bool potentially_threadable_block (basic_block);
-extern void thread_across_edge (gimple, edge, bool,
- vec<tree> *, tree (*) (gimple, gimple));
-extern void propagate_threaded_block_debug_into (basic_block, basic_block);
-
-/* In tree-ssa-loop-im.c */
-/* The possibilities of statement movement. */
-
-enum move_pos
- {
- MOVE_IMPOSSIBLE, /* No movement -- side effect expression. */
- MOVE_PRESERVE_EXECUTION, /* Must not cause the non-executed statement
- become executed -- memory accesses, ... */
- MOVE_POSSIBLE /* Unlimited movement. */
- };
-extern enum move_pos movement_possibility (gimple);
-char *get_lsm_tmp_name (tree, unsigned);
-
-/* In tree-flow-inline.h */
-static inline bool unmodifiable_var_p (const_tree);
-static inline bool ref_contains_array_ref (const_tree);
-
-/* In tree-eh.c */
-extern void make_eh_edges (gimple);
-extern bool make_eh_dispatch_edges (gimple);
-extern edge redirect_eh_edge (edge, basic_block);
-extern void redirect_eh_dispatch_edge (gimple, edge, basic_block);
-extern bool stmt_could_throw_p (gimple);
-extern bool stmt_can_throw_internal (gimple);
-extern bool stmt_can_throw_external (gimple);
-extern void add_stmt_to_eh_lp_fn (struct function *, gimple, int);
-extern void add_stmt_to_eh_lp (gimple, int);
-extern bool remove_stmt_from_eh_lp (gimple);
-extern bool remove_stmt_from_eh_lp_fn (struct function *, gimple);
-extern int lookup_stmt_eh_lp_fn (struct function *, gimple);
-extern int lookup_stmt_eh_lp (gimple);
-extern bool maybe_clean_eh_stmt_fn (struct function *, gimple);
-extern bool maybe_clean_eh_stmt (gimple);
-extern bool maybe_clean_or_replace_eh_stmt (gimple, gimple);
-extern bool maybe_duplicate_eh_stmt_fn (struct function *, gimple,
- struct function *, gimple,
- struct pointer_map_t *, int);
-extern bool maybe_duplicate_eh_stmt (gimple, gimple);
-extern bool verify_eh_edges (gimple);
-extern bool verify_eh_dispatch_edge (gimple);
-extern void maybe_remove_unreachable_handlers (void);
-
-/* In tree-ssa-pre.c */
-void debug_value_expressions (unsigned int);
-
-/* In tree-loop-linear.c */
-extern void linear_transform_loops (void);
-extern unsigned perfect_loop_nest_depth (struct loop *);
-
-/* In graphite.c */
-extern void graphite_transform_loops (void);
-
-/* In tree-data-ref.c */
-extern void tree_check_data_deps (void);
-
-/* In tree-ssa-loop-ivopts.c */
-bool expr_invariant_in_loop_p (struct loop *, tree);
-bool stmt_invariant_in_loop_p (struct loop *, gimple);
-struct loop *outermost_invariant_loop_for_expr (struct loop *, tree);
-bool multiplier_allowed_in_address_p (HOST_WIDE_INT, enum machine_mode,
- addr_space_t);
-bool may_be_nonaddressable_p (tree expr);
-
-/* In tree-ssa-threadupdate.c. */
-extern bool thread_through_all_blocks (bool);
-extern void register_jump_thread (vec<edge>, bool);
-
-/* In gimplify.c */
-tree force_gimple_operand_1 (tree, gimple_seq *, gimple_predicate, tree);
-tree force_gimple_operand (tree, gimple_seq *, bool, tree);
-tree force_gimple_operand_gsi_1 (gimple_stmt_iterator *, tree,
- gimple_predicate, tree,
- bool, enum gsi_iterator_update);
-tree force_gimple_operand_gsi (gimple_stmt_iterator *, tree, bool, tree,
- bool, enum gsi_iterator_update);
-tree gimple_fold_indirect_ref (tree);
-
-/* In tree-ssa-live.c */
-extern void remove_unused_locals (void);
-extern void dump_scope_blocks (FILE *, int);
-extern void debug_scope_blocks (int);
-extern void debug_scope_block (tree, int);
-
-/* In tree-ssa-address.c */
-
-/* Description of a memory address. */
-
-struct mem_address
-{
- tree symbol, base, index, step, offset;
-};
-
-struct affine_tree_combination;
-tree create_mem_ref (gimple_stmt_iterator *, tree,
- struct affine_tree_combination *, tree, tree, tree, bool);
-rtx addr_for_mem_ref (struct mem_address *, addr_space_t, bool);
-void get_address_description (tree, struct mem_address *);
-tree maybe_fold_tmr (tree);
-
-unsigned int execute_fixup_cfg (void);
-bool fixup_noreturn_call (gimple stmt);
-
-/* In ipa-pure-const.c */
-void warn_function_noreturn (tree);
-
-/* In tree-ssa-ter.c */
-bool stmt_is_replaceable_p (gimple);
-
-/* In tree-parloops.c */
-bool parallelized_function_p (tree);
-
-#include "tree-flow-inline.h"
-
-void swap_tree_operands (gimple, tree *, tree *);
-
-#endif /* _TREE_FLOW_H */
diff --git a/gcc/tree-hasher.h b/gcc/tree-hasher.h
index e403c9fcbe4..ac4bb6e17b0 100644
--- a/gcc/tree-hasher.h
+++ b/gcc/tree-hasher.h
@@ -22,7 +22,11 @@ along with GCC; see the file COPYING3. If not see
#define GCC_TREE_HASHER_H 1
#include "hash-table.h"
-#include "tree-flow.h"
+
+struct int_tree_map {
+ unsigned int uid;
+ tree to;
+};
/* Hashtable helpers. */
diff --git a/gcc/tree-if-conv.c b/gcc/tree-if-conv.c
index 4851023d27f..bb8de6d6ad7 100644
--- a/gcc/tree-if-conv.c
+++ b/gcc/tree-if-conv.c
@@ -88,6 +88,13 @@ along with GCC; see the file COPYING3. If not see
#include "flags.h"
#include "basic-block.h"
#include "gimple-pretty-print.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-cfg.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
+#include "tree-into-ssa.h"
#include "tree-ssa.h"
#include "cfgloop.h"
#include "tree-chrec.h"
@@ -1158,7 +1165,6 @@ if_convertible_loop_p (struct loop *loop)
bool res = false;
vec<data_reference_p> refs;
vec<ddr_p> ddrs;
- vec<loop_p> loop_nest;
/* Handle only innermost loop. */
if (!loop || loop->inner)
@@ -1192,7 +1198,7 @@ if_convertible_loop_p (struct loop *loop)
refs.create (5);
ddrs.create (25);
- loop_nest.create (3);
+ stack_vec<loop_p, 3> loop_nest;
res = if_convertible_loop_p_1 (loop, &loop_nest, &refs, &ddrs);
if (flag_tree_loop_if_convert_stores)
@@ -1324,7 +1330,6 @@ predicate_scalar_phi (gimple phi, tree cond,
}
new_stmt = gimple_build_assign (res, rhs);
- SSA_NAME_DEF_STMT (gimple_phi_result (phi)) = new_stmt;
gsi_insert_before (gsi, new_stmt, GSI_SAME_STMT);
update_stmt (new_stmt);
@@ -1842,8 +1847,8 @@ const pass_data pass_data_if_conversion =
class pass_if_conversion : public gimple_opt_pass
{
public:
- pass_if_conversion(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_if_conversion, ctxt)
+ pass_if_conversion (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_if_conversion, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index ebb4b918813..77013b390cb 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -33,12 +33,17 @@ along with GCC; see the file COPYING3. If not see
#include "langhooks.h"
#include "basic-block.h"
#include "tree-iterator.h"
-#include "cgraph.h"
#include "intl.h"
-#include "tree-mudflap.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-cfg.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
+#include "tree-into-ssa.h"
+#include "tree-dfa.h"
#include "tree-ssa.h"
#include "function.h"
-#include "tree-ssa.h"
#include "tree-pretty-print.h"
#include "except.h"
#include "debug.h"
@@ -53,7 +58,6 @@ along with GCC; see the file COPYING3. If not see
/* I'm not real happy about this, but we need to handle gimple and
non-gimple trees. */
-#include "gimple.h"
/* Inlining, Cloning, Versioning, Parallelization
@@ -1345,6 +1349,11 @@ remap_gimple_stmt (gimple stmt, copy_body_data *id)
copy = gimple_build_omp_master (s1);
break;
+ case GIMPLE_OMP_TASKGROUP:
+ s1 = remap_gimple_seq (gimple_omp_body (stmt), id);
+ copy = gimple_build_omp_taskgroup (s1);
+ break;
+
case GIMPLE_OMP_ORDERED:
s1 = remap_gimple_seq (gimple_omp_body (stmt), id);
copy = gimple_build_omp_ordered (s1);
@@ -1367,6 +1376,19 @@ remap_gimple_stmt (gimple stmt, copy_body_data *id)
(s1, gimple_omp_single_clauses (stmt));
break;
+ case GIMPLE_OMP_TARGET:
+ s1 = remap_gimple_seq (gimple_omp_body (stmt), id);
+ copy = gimple_build_omp_target
+ (s1, gimple_omp_target_kind (stmt),
+ gimple_omp_target_clauses (stmt));
+ break;
+
+ case GIMPLE_OMP_TEAMS:
+ s1 = remap_gimple_seq (gimple_omp_body (stmt), id);
+ copy = gimple_build_omp_teams
+ (s1, gimple_omp_teams_clauses (stmt));
+ break;
+
case GIMPLE_OMP_CRITICAL:
s1 = remap_gimple_seq (gimple_omp_body (stmt), id);
copy
@@ -1724,7 +1746,7 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale,
/* We could also just rescale the frequency, but
doing so would introduce roundoff errors and make
verifier unhappy. */
- new_freq = compute_call_stmt_bb_frequency (id->dst_node->symbol.decl,
+ new_freq = compute_call_stmt_bb_frequency (id->dst_node->decl,
copy_basic_block);
/* Speculative calls consist of two edges - direct and indirect.
@@ -1749,7 +1771,7 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale,
(old_edge->frequency + indirect->frequency)),
CGRAPH_FREQ_MAX);
}
- ipa_clone_ref (ref, (symtab_node)id->dst_node, stmt);
+ ipa_clone_ref (ref, id->dst_node, stmt);
}
else
{
@@ -1794,7 +1816,7 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale,
if ((!edge
|| (edge->indirect_inlining_edge
&& id->transform_call_graph_edges == CB_CGE_MOVE_CLONES))
- && id->dst_node->symbol.definition
+ && id->dst_node->definition
&& (fn = gimple_call_fndecl (stmt)) != NULL)
{
struct cgraph_node *dest = cgraph_get_node (fn);
@@ -1805,21 +1827,21 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale,
producing dead clone (for further cloning). In all
other cases we hit a bug (incorrect node sharing is the
most common reason for missing edges). */
- gcc_assert (!dest->symbol.definition
- || dest->symbol.address_taken
- || !id->src_node->symbol.definition
- || !id->dst_node->symbol.definition);
+ gcc_assert (!dest->definition
+ || dest->address_taken
+ || !id->src_node->definition
+ || !id->dst_node->definition);
if (id->transform_call_graph_edges == CB_CGE_MOVE_CLONES)
cgraph_create_edge_including_clones
(id->dst_node, dest, orig_stmt, stmt, bb->count,
- compute_call_stmt_bb_frequency (id->dst_node->symbol.decl,
+ compute_call_stmt_bb_frequency (id->dst_node->decl,
copy_basic_block),
CIF_ORIGINALLY_INDIRECT_CALL);
else
cgraph_create_edge (id->dst_node, dest, stmt,
bb->count,
compute_call_stmt_bb_frequency
- (id->dst_node->symbol.decl,
+ (id->dst_node->decl,
copy_basic_block))->inline_failed
= CIF_ORIGINALLY_INDIRECT_CALL;
if (dump_file)
@@ -2090,7 +2112,10 @@ copy_phis_for_bb (basic_block bb, copy_body_data *id)
n = (tree *) pointer_map_contains (id->decl_map,
LOCATION_BLOCK (locus));
gcc_assert (n);
- locus = COMBINE_LOCATION_DATA (line_table, locus, *n);
+ if (*n)
+ locus = COMBINE_LOCATION_DATA (line_table, locus, *n);
+ else
+ locus = LOCATION_LOCUS (locus);
}
else
locus = LOCATION_LOCUS (locus);
@@ -3720,7 +3745,7 @@ estimate_num_insns (gimple stmt, eni_weights *weights)
/* Do not special case builtins where we see the body.
This just confuse inliner. */
- if (!decl || !(node = cgraph_get_node (decl)) || node->symbol.definition)
+ if (!decl || !(node = cgraph_get_node (decl)) || node->definition)
;
/* For buitins that are likely expanded to nothing or
inlined do not account operand costs. */
@@ -3828,10 +3853,13 @@ estimate_num_insns (gimple stmt, eni_weights *weights)
case GIMPLE_OMP_TASK:
case GIMPLE_OMP_CRITICAL:
case GIMPLE_OMP_MASTER:
+ case GIMPLE_OMP_TASKGROUP:
case GIMPLE_OMP_ORDERED:
case GIMPLE_OMP_SECTION:
case GIMPLE_OMP_SECTIONS:
case GIMPLE_OMP_SINGLE:
+ case GIMPLE_OMP_TARGET:
+ case GIMPLE_OMP_TEAMS:
return (weights->omp_cost
+ estimate_num_insns_seq (gimple_omp_body (stmt), weights));
@@ -3989,7 +4017,7 @@ expand_call_inline (basic_block bb, gimple stmt, copy_body_data *id)
If we cannot, then there is no hope of inlining the function. */
if (cg_edge->indirect_unknown_callee)
goto egress;
- fn = cg_edge->callee->symbol.decl;
+ fn = cg_edge->callee->decl;
gcc_checking_assert (fn);
/* If FN is a declaration of a function in a nested scope that was
@@ -4049,11 +4077,11 @@ expand_call_inline (basic_block bb, gimple stmt, copy_body_data *id)
}
goto egress;
}
- fn = cg_edge->callee->symbol.decl;
+ fn = cg_edge->callee->decl;
cgraph_get_body (cg_edge->callee);
#ifdef ENABLE_CHECKING
- if (cg_edge->callee->symbol.decl != id->dst_node->symbol.decl)
+ if (cg_edge->callee->decl != id->dst_node->decl)
verify_cgraph_node (cg_edge->callee);
#endif
@@ -4061,9 +4089,9 @@ expand_call_inline (basic_block bb, gimple stmt, copy_body_data *id)
id->eh_lp_nr = lookup_stmt_eh_lp (stmt);
/* Update the callers EH personality. */
- if (DECL_FUNCTION_PERSONALITY (cg_edge->callee->symbol.decl))
- DECL_FUNCTION_PERSONALITY (cg_edge->caller->symbol.decl)
- = DECL_FUNCTION_PERSONALITY (cg_edge->callee->symbol.decl);
+ if (DECL_FUNCTION_PERSONALITY (cg_edge->callee->decl))
+ DECL_FUNCTION_PERSONALITY (cg_edge->caller->decl)
+ = DECL_FUNCTION_PERSONALITY (cg_edge->callee->decl);
/* Split the block holding the GIMPLE_CALL. */
e = split_block (bb, stmt);
@@ -4311,7 +4339,7 @@ expand_call_inline (basic_block bb, gimple stmt, copy_body_data *id)
variables in the function when the blocks get blown away as soon as we
remove the cgraph node. */
if (gimple_block (stmt))
- (*debug_hooks->outlining_inline_function) (cg_edge->callee->symbol.decl);
+ (*debug_hooks->outlining_inline_function) (cg_edge->callee->decl);
/* Update callgraph if needed. */
cgraph_remove_node (cg_edge->callee);
@@ -4463,7 +4491,7 @@ optimize_inline_calls (tree fn)
memset (&id, 0, sizeof (id));
id.src_node = id.dst_node = cgraph_get_node (fn);
- gcc_assert (id.dst_node->symbol.definition);
+ gcc_assert (id.dst_node->definition);
id.dst_fn = fn;
/* Or any functions that aren't finished yet. */
if (current_function_decl)
@@ -4563,10 +4591,6 @@ copy_tree_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
/* Copy the node. */
new_tree = copy_node (*tp);
- /* Propagate mudflap marked-ness. */
- if (flag_mudflap && mf_marked_p (*tp))
- mf_mark (new_tree);
-
*tp = new_tree;
/* Now, restore the chain, if appropriate. That will cause
@@ -4588,11 +4612,6 @@ copy_tree_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
tree new_tree;
new_tree = copy_node (*tp);
-
- /* Propagate mudflap marked-ness. */
- if (flag_mudflap && mf_marked_p (*tp))
- mf_mark (new_tree);
-
CONSTRUCTOR_ELTS (new_tree) = vec_safe_copy (CONSTRUCTOR_ELTS (*tp));
*tp = new_tree;
}
@@ -5058,7 +5077,7 @@ delete_unreachable_blocks_update_callgraph (copy_body_data *id)
struct cgraph_edge *e;
struct cgraph_node *node;
- ipa_remove_stmt_references ((symtab_node)id->dst_node, gsi_stmt (bsi));
+ ipa_remove_stmt_references (id->dst_node, gsi_stmt (bsi));
if (gimple_code (gsi_stmt (bsi)) == GIMPLE_CALL
&&(e = cgraph_edge (id->dst_node, gsi_stmt (bsi))) != NULL)
@@ -5072,7 +5091,7 @@ delete_unreachable_blocks_update_callgraph (copy_body_data *id)
&& id->dst_node->clones)
for (node = id->dst_node->clones; node != id->dst_node;)
{
- ipa_remove_stmt_references ((symtab_node)node, gsi_stmt (bsi));
+ ipa_remove_stmt_references (node, gsi_stmt (bsi));
if (gimple_code (gsi_stmt (bsi)) == GIMPLE_CALL
&& (e = cgraph_edge (node, gsi_stmt (bsi))) != NULL)
{
@@ -5168,8 +5187,7 @@ tree_function_versioning (tree old_decl, tree new_decl,
unsigned i;
struct ipa_replace_map *replace_info;
basic_block old_entry_block, bb;
- vec<gimple> init_stmts;
- init_stmts.create (10);
+ stack_vec<gimple, 10> init_stmts;
tree vars = NULL_TREE;
gcc_assert (TREE_CODE (old_decl) == FUNCTION_DECL
@@ -5395,7 +5413,7 @@ tree_function_versioning (tree old_decl, tree new_decl,
pointer_set_destroy (id.statements_to_fold);
fold_cond_expr_cond ();
delete_unreachable_blocks_update_callgraph (&id);
- if (id.dst_node->symbol.definition)
+ if (id.dst_node->definition)
cgraph_rebuild_references ();
update_ssa (TODO_update_ssa);
@@ -5427,7 +5445,6 @@ tree_function_versioning (tree old_decl, tree new_decl,
free_dominance_info (CDI_POST_DOMINATORS);
gcc_assert (!id.debug_stmts.exists ());
- init_stmts.release ();
pop_cfun ();
return;
}
diff --git a/gcc/tree-inline.h b/gcc/tree-inline.h
index a78e4b69f0e..cd327154560 100644
--- a/gcc/tree-inline.h
+++ b/gcc/tree-inline.h
@@ -131,6 +131,10 @@ typedef struct copy_body_data
the originals have been mapped to a value rather than to a
variable. */
struct pointer_map_t *debug_map;
+
+ /* Cilk keywords currently need to replace some variables that
+ ordinary nested functions do not. */
+ bool remap_var_for_cilk;
} copy_body_data;
/* Weights of constructions for estimate_num_insns. */
diff --git a/gcc/tree-into-ssa.c b/gcc/tree-into-ssa.c
index 384d3b33cff..981e9f4bfb4 100644
--- a/gcc/tree-into-ssa.c
+++ b/gcc/tree-into-ssa.c
@@ -29,9 +29,15 @@ along with GCC; see the file COPYING3. If not see
#include "basic-block.h"
#include "function.h"
#include "gimple-pretty-print.h"
-#include "bitmap.h"
-#include "tree-ssa.h"
#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-cfg.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
+#include "tree-into-ssa.h"
+#include "tree-dfa.h"
+#include "tree-ssa.h"
#include "tree-inline.h"
#include "hash-table.h"
#include "tree-pass.h"
@@ -39,6 +45,7 @@ along with GCC; see the file COPYING3. If not see
#include "domwalk.h"
#include "params.h"
#include "diagnostic-core.h"
+#include "tree-into-ssa.h"
/* This file builds the SSA form for a function as described in:
@@ -128,6 +135,30 @@ struct mark_def_sites_global_data
bitmap kills;
};
+/* It is advantageous to avoid things like life analysis for variables which
+ do not need PHI nodes. This enum describes whether or not a particular
+ variable may need a PHI node. */
+
+enum need_phi_state {
+ /* This is the default. If we are still in this state after finding
+ all the definition and use sites, then we will assume the variable
+ needs PHI nodes. This is probably an overly conservative assumption. */
+ NEED_PHI_STATE_UNKNOWN,
+
+ /* This state indicates that we have seen one or more sets of the
+ variable in a single basic block and that the sets dominate all
+ uses seen so far. If after finding all definition and use sites
+ we are still in this state, then the variable does not need any
+ PHI nodes. */
+ NEED_PHI_STATE_NO,
+
+ /* This state indicates that we have either seen multiple definitions of
+ the variable in multiple blocks, or that we encountered a use in a
+ block that was not dominated by the block containing the set(s) of
+ this variable. This variable is assumed to need PHI nodes. */
+ NEED_PHI_STATE_MAYBE
+};
+
/* Information stored for both SSA names and decls. */
struct common_info_d
{
@@ -229,27 +260,6 @@ enum rewrite_mode {
REWRITE_UPDATE
};
-
-
-
-/* Prototypes for debugging functions. */
-extern void dump_tree_ssa (FILE *);
-extern void debug_tree_ssa (void);
-extern void debug_def_blocks (void);
-extern void dump_tree_ssa_stats (FILE *);
-extern void debug_tree_ssa_stats (void);
-extern void dump_update_ssa (FILE *);
-extern void debug_update_ssa (void);
-extern void dump_names_replaced_by (FILE *, tree);
-extern void debug_names_replaced_by (tree);
-extern void dump_var_infos (FILE *);
-extern void debug_var_infos (void);
-extern void dump_defs_stack (FILE *, int);
-extern void debug_defs_stack (int);
-extern void dump_currdefs (FILE *);
-extern void debug_currdefs (void);
-
-
/* The set of symbols we ought to re-write into SSA form in update_ssa. */
static bitmap symbols_to_rename_set;
static vec<tree> symbols_to_rename;
@@ -1494,31 +1504,6 @@ rewrite_dom_walker::after_dom_children (basic_block bb ATTRIBUTE_UNUSED)
/* Dump bitmap SET (assumed to contain VAR_DECLs) to FILE. */
-void
-dump_decl_set (FILE *file, bitmap set)
-{
- if (set)
- {
- bitmap_iterator bi;
- unsigned i;
-
- fprintf (file, "{ ");
-
- EXECUTE_IF_SET_IN_BITMAP (set, 0, i, bi)
- {
- fprintf (file, "D.%u", i);
- fprintf (file, " ");
- }
-
- fprintf (file, "}");
- }
- else
- fprintf (file, "NIL");
-}
-
-
-/* Dump bitmap SET (assumed to contain VAR_DECLs) to FILE. */
-
DEBUG_FUNCTION void
debug_decl_set (bitmap set)
{
@@ -2235,17 +2220,17 @@ private:
/* Notice that this bitmap is indexed using variable UIDs, so it must be
large enough to accommodate all the variables referenced in the
function, not just the ones we are renaming. */
- bitmap kills_;
+ bitmap m_kills;
};
mark_def_dom_walker::mark_def_dom_walker (cdi_direction direction)
- : dom_walker (direction), kills_ (BITMAP_ALLOC (NULL))
+ : dom_walker (direction), m_kills (BITMAP_ALLOC (NULL))
{
}
mark_def_dom_walker::~mark_def_dom_walker ()
{
- BITMAP_FREE (kills_);
+ BITMAP_FREE (m_kills);
}
/* Block processing routine for mark_def_sites. Clear the KILLS bitmap
@@ -2256,9 +2241,9 @@ mark_def_dom_walker::before_dom_children (basic_block bb)
{
gimple_stmt_iterator gsi;
- bitmap_clear (kills_);
+ bitmap_clear (m_kills);
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
- mark_def_sites (bb, gsi_stmt (gsi), kills_);
+ mark_def_sites (bb, gsi_stmt (gsi), m_kills);
}
/* Initialize internal data needed during renaming. */
@@ -2366,10 +2351,8 @@ rewrite_into_ssa (void)
if (decl
&& TREE_CODE (decl) == VAR_DECL
&& !VAR_DECL_IS_VIRTUAL_OPERAND (decl)
- && DECL_ARTIFICIAL (decl)
- && DECL_IGNORED_P (decl)
- && !DECL_NAME (decl))
- SET_SSA_NAME_VAR_OR_IDENTIFIER (name, NULL_TREE);
+ && DECL_IGNORED_P (decl))
+ SET_SSA_NAME_VAR_OR_IDENTIFIER (name, DECL_NAME (decl));
}
return 0;
@@ -2404,8 +2387,8 @@ const pass_data pass_data_build_ssa =
class pass_build_ssa : public gimple_opt_pass
{
public:
- pass_build_ssa(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_build_ssa, ctxt)
+ pass_build_ssa (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_build_ssa, ctxt)
{}
/* opt_pass methods: */
@@ -2892,6 +2875,46 @@ mark_virtual_operands_for_renaming (struct function *fn)
fn->gimple_df->rename_vops = 1;
}
+/* Replace all uses of NAME by underlying variable and mark it
+ for renaming. This assumes the defining statement of NAME is
+ going to be removed. */
+
+void
+mark_virtual_operand_for_renaming (tree name)
+{
+ tree name_var = SSA_NAME_VAR (name);
+ bool used = false;
+ imm_use_iterator iter;
+ use_operand_p use_p;
+ gimple stmt;
+
+ gcc_assert (VAR_DECL_IS_VIRTUAL_OPERAND (name_var));
+ FOR_EACH_IMM_USE_STMT (stmt, iter, name)
+ {
+ FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
+ SET_USE (use_p, name_var);
+ used = true;
+ }
+ if (used)
+ mark_virtual_operands_for_renaming (cfun);
+}
+
+/* Replace all uses of the virtual PHI result by its underlying variable
+ and mark it for renaming. This assumes the PHI node is going to be
+ removed. */
+
+void
+mark_virtual_phi_result_for_renaming (gimple phi)
+{
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "Marking result for renaming : ");
+ print_gimple_stmt (dump_file, phi, 0, TDF_SLIM);
+ fprintf (dump_file, "\n");
+ }
+
+ mark_virtual_operand_for_renaming (gimple_phi_result (phi));
+}
/* Return true if there is any work to be done by update_ssa
for function FN. */
diff --git a/gcc/tree-into-ssa.h b/gcc/tree-into-ssa.h
new file mode 100644
index 00000000000..c87fb63c351
--- /dev/null
+++ b/gcc/tree-into-ssa.h
@@ -0,0 +1,52 @@
+/* Header file for normal form into SSA.
+ Copyright (C) 2013 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_INTO_SSA_H
+#define GCC_TREE_INTO_SSA_H
+
+extern tree get_current_def (tree);
+extern void set_current_def (tree, tree);
+void delete_update_ssa (void);
+tree create_new_def_for (tree, gimple, def_operand_p);
+void mark_virtual_operands_for_renaming (struct function *);
+void mark_virtual_operand_for_renaming (tree);
+void mark_virtual_phi_result_for_renaming (gimple);
+bool need_ssa_update_p (struct function *);
+bool name_registered_for_update_p (tree);
+void release_ssa_name_after_update_ssa (tree);
+void update_ssa (unsigned);
+
+/* Prototypes for debugging functions. */
+extern void debug_decl_set (bitmap set);
+extern void dump_defs_stack (FILE *, int);
+extern void debug_defs_stack (int);
+extern void dump_currdefs (FILE *);
+extern void debug_currdefs (void);
+extern void dump_tree_ssa (FILE *);
+extern void debug_tree_ssa (void);
+extern void dump_tree_ssa_stats (FILE *);
+extern void debug_tree_ssa_stats (void);
+extern void dump_var_infos (FILE *);
+extern void debug_var_infos (void);
+extern void dump_names_replaced_by (FILE *, tree);
+extern void debug_names_replaced_by (tree);
+extern void dump_update_ssa (FILE *);
+extern void debug_update_ssa (void);
+
+#endif /* GCC_TREE_INTO_SSA_H */
diff --git a/gcc/tree-iterator.c b/gcc/tree-iterator.c
index 7359684cf3c..53347b54dc6 100644
--- a/gcc/tree-iterator.c
+++ b/gcc/tree-iterator.c
@@ -39,7 +39,7 @@ alloc_stmt_list (void)
if (!vec_safe_is_empty (stmt_list_cache))
{
list = stmt_list_cache->pop ();
- memset (list, 0, sizeof(struct tree_base));
+ memset (list, 0, sizeof (struct tree_base));
TREE_SET_CODE (list, STATEMENT_LIST);
}
else
diff --git a/gcc/tree-loop-distribution.c b/gcc/tree-loop-distribution.c
index 7482d8c68bc..45efad3f110 100644
--- a/gcc/tree-loop-distribution.c
+++ b/gcc/tree-loop-distribution.c
@@ -44,6 +44,16 @@ along with GCC; see the file COPYING3. If not see
#include "config.h"
#include "system.h"
#include "coretypes.h"
+#include "tree.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-cfg.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
+#include "tree-ssa-loop-manip.h"
+#include "tree-ssa-loop.h"
+#include "tree-into-ssa.h"
#include "tree-ssa.h"
#include "cfgloop.h"
#include "tree-chrec.h"
@@ -51,6 +61,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-scalar-evolution.h"
#include "tree-pass.h"
#include "gimple-pretty-print.h"
+#include "tree-vectorizer.h"
/* A Reduced Dependence Graph (RDG) vertex representing a statement. */
@@ -85,15 +96,6 @@ enum rdg_dep_type
/* Read After Write (RAW). */
flow_dd = 'f',
- /* Write After Read (WAR). */
- anti_dd = 'a',
-
- /* Write After Write (WAW). */
- output_dd = 'o',
-
- /* Read After Read (RAR). */
- input_dd = 'i',
-
/* Control dependence (execute conditional on). */
control_dd = 'c'
};
@@ -104,19 +106,9 @@ typedef struct rdg_edge
{
/* Type of the dependence. */
enum rdg_dep_type type;
-
- /* Levels of the dependence: the depth of the loops that carry the
- dependence. */
- unsigned level;
-
- /* Dependence relation between data dependences, NULL when one of
- the vertices is a scalar. */
- ddr_p relation;
} *rdg_edge_p;
#define RDGE_TYPE(E) ((struct rdg_edge *) ((E)->data))->type
-#define RDGE_LEVEL(E) ((struct rdg_edge *) ((E)->data))->level
-#define RDGE_RELATION(E) ((struct rdg_edge *) ((E)->data))->relation
/* Dump vertex I in RDG to FILE. */
@@ -204,23 +196,11 @@ dot_rdg_1 (FILE *file, struct graph *rdg)
for (e = v->succ; e; e = e->succ_next)
switch (RDGE_TYPE (e))
{
- case input_dd:
- fprintf (file, "%d -> %d [label=input] \n", i, e->dest);
- break;
-
- case output_dd:
- fprintf (file, "%d -> %d [label=output] \n", i, e->dest);
- break;
-
case flow_dd:
/* These are the most common dependences: don't print these. */
fprintf (file, "%d -> %d \n", i, e->dest);
break;
- case anti_dd:
- fprintf (file, "%d -> %d [label=anti] \n", i, e->dest);
- break;
-
case control_dd:
fprintf (file, "%d -> %d [label=control] \n", i, e->dest);
break;
@@ -240,7 +220,7 @@ dot_rdg (struct graph *rdg)
{
/* When debugging, you may want to enable the following code. */
#if 1
- FILE *file = popen("dot -Tx11", "w");
+ FILE *file = popen ("dot -Tx11", "w");
if (!file)
return;
dot_rdg_1 (file, rdg);
@@ -262,52 +242,6 @@ rdg_vertex_for_stmt (struct graph *rdg ATTRIBUTE_UNUSED, gimple stmt)
return index;
}
-/* Creates an edge in RDG for each distance vector from DDR. The
- order that we keep track of in the RDG is the order in which
- statements have to be executed. */
-
-static void
-create_rdg_edge_for_ddr (struct graph *rdg, ddr_p ddr)
-{
- struct graph_edge *e;
- int va, vb;
- data_reference_p dra = DDR_A (ddr);
- data_reference_p drb = DDR_B (ddr);
- unsigned level = ddr_dependence_level (ddr);
-
- /* For non scalar dependences, when the dependence is REVERSED,
- statement B has to be executed before statement A. */
- if (level > 0
- && !DDR_REVERSED_P (ddr))
- {
- data_reference_p tmp = dra;
- dra = drb;
- drb = tmp;
- }
-
- va = rdg_vertex_for_stmt (rdg, DR_STMT (dra));
- vb = rdg_vertex_for_stmt (rdg, DR_STMT (drb));
-
- if (va < 0 || vb < 0)
- return;
-
- e = add_edge (rdg, va, vb);
- e->data = XNEW (struct rdg_edge);
-
- RDGE_LEVEL (e) = level;
- RDGE_RELATION (e) = ddr;
-
- /* Determines the type of the data dependence. */
- if (DR_IS_READ (dra) && DR_IS_READ (drb))
- RDGE_TYPE (e) = input_dd;
- else if (DR_IS_WRITE (dra) && DR_IS_WRITE (drb))
- RDGE_TYPE (e) = output_dd;
- else if (DR_IS_WRITE (dra) && DR_IS_READ (drb))
- RDGE_TYPE (e) = flow_dd;
- else if (DR_IS_READ (dra) && DR_IS_WRITE (drb))
- RDGE_TYPE (e) = anti_dd;
-}
-
/* Creates dependence edges in RDG for all the uses of DEF. IDEF is
the index of DEF in RDG. */
@@ -328,7 +262,6 @@ create_rdg_edges_for_scalar (struct graph *rdg, tree def, int idef)
e = add_edge (rdg, idef, use);
e->data = XNEW (struct rdg_edge);
RDGE_TYPE (e) = flow_dd;
- RDGE_RELATION (e) = NULL;
}
}
@@ -355,7 +288,6 @@ create_edge_for_control_dependence (struct graph *rdg, basic_block bb,
e = add_edge (rdg, c, v);
e->data = XNEW (struct rdg_edge);
RDGE_TYPE (e) = control_dd;
- RDGE_RELATION (e) = NULL;
}
}
}
@@ -363,38 +295,38 @@ create_edge_for_control_dependence (struct graph *rdg, basic_block bb,
/* Creates the edges of the reduced dependence graph RDG. */
static void
-create_rdg_edges (struct graph *rdg, vec<ddr_p> ddrs, control_dependences *cd)
+create_rdg_flow_edges (struct graph *rdg)
{
int i;
- struct data_dependence_relation *ddr;
def_operand_p def_p;
ssa_op_iter iter;
- FOR_EACH_VEC_ELT (ddrs, i, ddr)
- if (DDR_ARE_DEPENDENT (ddr) == NULL_TREE)
- create_rdg_edge_for_ddr (rdg, ddr);
- else
- free_dependence_relation (ddr);
-
for (i = 0; i < rdg->n_vertices; i++)
FOR_EACH_PHI_OR_STMT_DEF (def_p, RDG_STMT (rdg, i),
iter, SSA_OP_DEF)
create_rdg_edges_for_scalar (rdg, DEF_FROM_PTR (def_p), i);
+}
- if (cd)
- for (i = 0; i < rdg->n_vertices; i++)
- {
- gimple stmt = RDG_STMT (rdg, i);
- if (gimple_code (stmt) == GIMPLE_PHI)
- {
- edge_iterator ei;
- edge e;
- FOR_EACH_EDGE (e, ei, gimple_bb (stmt)->preds)
+/* Creates the edges of the reduced dependence graph RDG. */
+
+static void
+create_rdg_cd_edges (struct graph *rdg, control_dependences *cd)
+{
+ int i;
+
+ for (i = 0; i < rdg->n_vertices; i++)
+ {
+ gimple stmt = RDG_STMT (rdg, i);
+ if (gimple_code (stmt) == GIMPLE_PHI)
+ {
+ edge_iterator ei;
+ edge e;
+ FOR_EACH_EDGE (e, ei, gimple_bb (stmt)->preds)
create_edge_for_control_dependence (rdg, e->src, i, cd);
- }
- else
- create_edge_for_control_dependence (rdg, gimple_bb (stmt), i, cd);
- }
+ }
+ else
+ create_edge_for_control_dependence (rdg, gimple_bb (stmt), i, cd);
+ }
}
/* Build the vertices of the reduced dependence graph RDG. Return false
@@ -470,17 +402,6 @@ stmts_from_loop (struct loop *loop, vec<gimple> *stmts)
free (bbs);
}
-/* Build the Reduced Dependence Graph (RDG) with one vertex per
- statement of the loop nest, and one edge per data dependence or
- scalar dependence. */
-
-struct graph *
-build_empty_rdg (int n_stmts)
-{
- struct graph *rdg = new_graph (n_stmts);
- return rdg;
-}
-
/* Free the reduced dependence graph RDG. */
static void
@@ -494,10 +415,7 @@ free_rdg (struct graph *rdg)
struct graph_edge *e;
for (e = v->succ; e; e = e->succ_next)
- {
- free_dependence_relation (RDGE_RELATION (e));
- free (e->data);
- }
+ free (e->data);
if (v->data)
{
@@ -518,37 +436,25 @@ static struct graph *
build_rdg (vec<loop_p> loop_nest, control_dependences *cd)
{
struct graph *rdg;
- vec<gimple> stmts;
vec<data_reference_p> datarefs;
- vec<ddr_p> dependence_relations;
/* Create the RDG vertices from the stmts of the loop nest. */
- stmts.create (10);
+ stack_vec<gimple, 10> stmts;
stmts_from_loop (loop_nest[0], &stmts);
- rdg = build_empty_rdg (stmts.length ());
+ rdg = new_graph (stmts.length ());
datarefs.create (10);
if (!create_rdg_vertices (rdg, stmts, loop_nest[0], &datarefs))
{
- stmts.release ();
datarefs.release ();
free_rdg (rdg);
return NULL;
}
stmts.release ();
- /* Create the RDG edges from the data dependences in the loop nest. */
- dependence_relations.create (100);
- if (!compute_all_dependences (datarefs, &dependence_relations, loop_nest,
- false)
- || !known_dependences_p (dependence_relations))
- {
- free_dependence_relations (dependence_relations);
- datarefs.release ();
- free_rdg (rdg);
- return NULL;
- }
- create_rdg_edges (rdg, dependence_relations, cd);
- dependence_relations.release ();
+ create_rdg_flow_edges (rdg);
+ if (cd)
+ create_rdg_cd_edges (rdg, cd);
+
datarefs.release ();
return rdg;
@@ -557,18 +463,19 @@ build_rdg (vec<loop_p> loop_nest, control_dependences *cd)
enum partition_kind {
- PKIND_NORMAL, PKIND_REDUCTION, PKIND_MEMSET, PKIND_MEMCPY
+ PKIND_NORMAL, PKIND_MEMSET, PKIND_MEMCPY
};
typedef struct partition_s
{
bitmap stmts;
bitmap loops;
- bool has_writes;
+ bool reduction_p;
enum partition_kind kind;
/* data-references a kind != PKIND_NORMAL partition is about. */
data_reference_p main_dr;
data_reference_p secondary_dr;
+ tree niter;
} *partition_t;
@@ -580,7 +487,7 @@ partition_alloc (bitmap stmts, bitmap loops)
partition_t partition = XCNEW (struct partition_s);
partition->stmts = stmts ? stmts : BITMAP_ALLOC (NULL);
partition->loops = loops ? loops : BITMAP_ALLOC (NULL);
- partition->has_writes = false;
+ partition->reduction_p = false;
partition->kind = PKIND_NORMAL;
return partition;
}
@@ -600,17 +507,29 @@ partition_free (partition_t partition)
static bool
partition_builtin_p (partition_t partition)
{
- return partition->kind > PKIND_REDUCTION;
+ return partition->kind != PKIND_NORMAL;
}
-/* Returns true if the partition has an writes. */
+/* Returns true if the partition contains a reduction. */
static bool
-partition_has_writes (partition_t partition)
+partition_reduction_p (partition_t partition)
+{
+ return partition->reduction_p;
+}
+
+/* Merge PARTITION into the partition DEST. */
+
+static void
+partition_merge_into (partition_t dest, partition_t partition)
{
- return partition->has_writes;
+ dest->kind = PKIND_NORMAL;
+ bitmap_ior_into (dest->stmts, partition->stmts);
+ if (partition_reduction_p (partition))
+ dest->reduction_p = true;
}
+
/* Returns true when DEF is an SSA_NAME defined in LOOP and used after
the LOOP. */
@@ -848,21 +767,17 @@ generate_memset_builtin (struct loop *loop, partition_t partition)
{
gimple_stmt_iterator gsi;
gimple stmt, fn_call;
- tree nb_iter, mem, fn, nb_bytes;
+ tree mem, fn, nb_bytes;
location_t loc;
tree val;
stmt = DR_STMT (partition->main_dr);
loc = gimple_location (stmt);
- if (gimple_bb (stmt) == loop->latch)
- nb_iter = number_of_latch_executions (loop);
- else
- nb_iter = number_of_exit_cond_executions (loop);
/* The new statements will be placed before LOOP. */
gsi = gsi_last_bb (loop_preheader_edge (loop)->src);
- nb_bytes = build_size_arg_loc (loc, partition->main_dr, nb_iter);
+ nb_bytes = build_size_arg_loc (loc, partition->main_dr, partition->niter);
nb_bytes = force_gimple_operand_gsi (&gsi, nb_bytes, true, NULL_TREE,
false, GSI_CONTINUE_LINKING);
mem = build_addr_arg_loc (loc, partition->main_dr, nb_bytes);
@@ -908,21 +823,17 @@ generate_memcpy_builtin (struct loop *loop, partition_t partition)
{
gimple_stmt_iterator gsi;
gimple stmt, fn_call;
- tree nb_iter, dest, src, fn, nb_bytes;
+ tree dest, src, fn, nb_bytes;
location_t loc;
enum built_in_function kind;
stmt = DR_STMT (partition->main_dr);
loc = gimple_location (stmt);
- if (gimple_bb (stmt) == loop->latch)
- nb_iter = number_of_latch_executions (loop);
- else
- nb_iter = number_of_exit_cond_executions (loop);
/* The new statements will be placed before LOOP. */
gsi = gsi_last_bb (loop_preheader_edge (loop)->src);
- nb_bytes = build_size_arg_loc (loc, partition->main_dr, nb_iter);
+ nb_bytes = build_size_arg_loc (loc, partition->main_dr, partition->niter);
nb_bytes = force_gimple_operand_gsi (&gsi, nb_bytes, true, NULL_TREE,
false, GSI_CONTINUE_LINKING);
dest = build_addr_arg_loc (loc, partition->main_dr, nb_bytes);
@@ -1005,108 +916,52 @@ generate_code_for_partition (struct loop *loop,
{
switch (partition->kind)
{
+ case PKIND_NORMAL:
+ /* Reductions all have to be in the last partition. */
+ gcc_assert (!partition_reduction_p (partition)
+ || !copy_p);
+ generate_loops_for_partition (loop, partition, copy_p);
+ return;
+
case PKIND_MEMSET:
generate_memset_builtin (loop, partition);
- /* If this is the last partition for which we generate code, we have
- to destroy the loop. */
- if (!copy_p)
- destroy_loop (loop);
break;
case PKIND_MEMCPY:
generate_memcpy_builtin (loop, partition);
- /* If this is the last partition for which we generate code, we have
- to destroy the loop. */
- if (!copy_p)
- destroy_loop (loop);
- break;
-
- case PKIND_REDUCTION:
- /* Reductions all have to be in the last partition. */
- gcc_assert (!copy_p);
- case PKIND_NORMAL:
- generate_loops_for_partition (loop, partition, copy_p);
break;
default:
gcc_unreachable ();
}
-}
-
-
-/* Returns true if the node V of RDG cannot be recomputed. */
-
-static bool
-rdg_cannot_recompute_vertex_p (struct graph *rdg, int v)
-{
- if (RDG_MEM_WRITE_STMT (rdg, v))
- return true;
-
- return false;
-}
-/* Returns true when the vertex V has already been generated in the
- current partition (V is in PROCESSED), or when V belongs to another
- partition and cannot be recomputed (V is not in REMAINING_STMTS). */
-
-static inline bool
-already_processed_vertex_p (bitmap processed, int v)
-{
- return bitmap_bit_p (processed, v);
+ /* Common tail for partitions we turn into a call. If this was the last
+ partition for which we generate code, we have to destroy the loop. */
+ if (!copy_p)
+ destroy_loop (loop);
}
-static void rdg_flag_vertex_and_dependent (struct graph *, int, partition_t,
- bitmap);
-/* Flag V from RDG as part of PARTITION, and also flag its loop number
- in LOOPS. */
-
-static void
-rdg_flag_vertex (struct graph *rdg, int v, partition_t partition)
-{
- struct loop *loop;
-
- if (!bitmap_set_bit (partition->stmts, v))
- return;
-
- loop = loop_containing_stmt (RDG_STMT (rdg, v));
- bitmap_set_bit (partition->loops, loop->num);
-
- if (rdg_cannot_recompute_vertex_p (rdg, v))
- partition->has_writes = true;
-}
-
-/* Flag in the bitmap PARTITION the vertex V and all its predecessors.
- Also flag their loop number in LOOPS. */
+/* Returns a partition with all the statements needed for computing
+ the vertex V of the RDG, also including the loop exit conditions. */
-static void
-rdg_flag_vertex_and_dependent (struct graph *rdg, int v, partition_t partition,
- bitmap processed)
+static partition_t
+build_rdg_partition_for_vertex (struct graph *rdg, int v)
{
+ partition_t partition = partition_alloc (NULL, NULL);
+ stack_vec<int, 3> nodes;
unsigned i;
- vec<int> nodes;
- nodes.create (3);
int x;
graphds_dfs (rdg, &v, 1, &nodes, false, NULL);
FOR_EACH_VEC_ELT (nodes, i, x)
- if (bitmap_set_bit (processed, x))
- rdg_flag_vertex (rdg, x, partition);
-
- nodes.release ();
-}
-
-/* Returns a partition with all the statements needed for computing
- the vertex V of the RDG, also including the loop exit conditions. */
+ {
+ bitmap_set_bit (partition->stmts, x);
+ bitmap_set_bit (partition->loops,
+ loop_containing_stmt (RDG_STMT (rdg, x))->num);
+ }
-static partition_t
-build_rdg_partition_for_vertex (struct graph *rdg, int v)
-{
- partition_t partition = partition_alloc (NULL, NULL);
- bitmap processed = BITMAP_ALLOC (NULL);
- rdg_flag_vertex_and_dependent (rdg, v, partition, processed);
- BITMAP_FREE (processed);
return partition;
}
@@ -1125,6 +980,7 @@ classify_partition (loop_p loop, struct graph *rdg, partition_t partition)
partition->kind = PKIND_NORMAL;
partition->main_dr = NULL;
partition->secondary_dr = NULL;
+ partition->niter = NULL_TREE;
EXECUTE_IF_SET_IN_BITMAP (partition->stmts, 0, i, bi)
{
@@ -1133,15 +989,10 @@ classify_partition (loop_p loop, struct graph *rdg, partition_t partition)
if (gimple_has_volatile_ops (stmt))
volatiles_p = true;
- /* If the stmt has uses outside of the loop fail.
- ??? If the stmt is generated in another partition that
- is not created as builtin we can ignore this. */
+ /* If the stmt has uses outside of the loop mark it as reduction. */
if (stmt_has_scalar_dependences_outside_loop (loop, stmt))
{
- if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, "not generating builtin, partition has "
- "scalar uses outside of the loop\n");
- partition->kind = PKIND_REDUCTION;
+ partition->reduction_p = true;
return;
}
}
@@ -1151,10 +1002,6 @@ classify_partition (loop_p loop, struct graph *rdg, partition_t partition)
|| !flag_tree_loop_distribute_patterns)
return;
- nb_iter = number_of_exit_cond_executions (loop);
- if (!nb_iter || nb_iter == chrec_dont_know)
- return;
-
/* Detect memset and memcpy. */
single_load = NULL;
single_store = NULL;
@@ -1193,6 +1040,17 @@ classify_partition (loop_p loop, struct graph *rdg, partition_t partition)
}
}
+ if (!single_store)
+ return;
+
+ if (!dominated_by_p (CDI_DOMINATORS, single_exit (loop)->src,
+ gimple_bb (DR_STMT (single_store))))
+ nb_iter = number_of_latch_executions (loop);
+ else
+ nb_iter = number_of_exit_cond_executions (loop);
+ if (!nb_iter || nb_iter == chrec_dont_know)
+ return;
+
if (single_store && !single_load)
{
gimple stmt = DR_STMT (single_store);
@@ -1206,10 +1064,13 @@ classify_partition (loop_p loop, struct graph *rdg, partition_t partition)
&& !SSA_NAME_IS_DEFAULT_DEF (rhs)
&& flow_bb_inside_loop_p (loop, gimple_bb (SSA_NAME_DEF_STMT (rhs))))
return;
- if (!adjacent_dr_p (single_store))
+ if (!adjacent_dr_p (single_store)
+ || !dominated_by_p (CDI_DOMINATORS,
+ loop->latch, gimple_bb (stmt)))
return;
partition->kind = PKIND_MEMSET;
partition->main_dr = single_store;
+ partition->niter = nb_iter;
}
else if (single_store && single_load)
{
@@ -1222,7 +1083,9 @@ classify_partition (loop_p loop, struct graph *rdg, partition_t partition)
if (!adjacent_dr_p (single_store)
|| !adjacent_dr_p (single_load)
|| !operand_equal_p (DR_STEP (single_store),
- DR_STEP (single_load), 0))
+ DR_STEP (single_load), 0)
+ || !dominated_by_p (CDI_DOMINATORS,
+ loop->latch, gimple_bb (store)))
return;
/* Now check that if there is a dependence this dependence is
of a suitable form for memmove. */
@@ -1264,6 +1127,7 @@ classify_partition (loop_p loop, struct graph *rdg, partition_t partition)
partition->kind = PKIND_MEMCPY;
partition->main_dr = single_store;
partition->secondary_dr = single_load;
+ partition->niter = nb_iter;
}
}
@@ -1333,54 +1197,34 @@ rdg_build_partitions (struct graph *rdg,
bitmap processed = BITMAP_ALLOC (NULL);
int i;
gimple stmt;
- partition_t partition = partition_alloc (NULL, NULL);
FOR_EACH_VEC_ELT (starting_stmts, i, stmt)
{
- partition_t np;
int v = rdg_vertex_for_stmt (rdg, stmt);
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file,
"ldist asked to generate code for vertex %d\n", v);
+ /* If the vertex is already contained in another partition so
+ is the partition rooted at it. */
if (bitmap_bit_p (processed, v))
continue;
- np = build_rdg_partition_for_vertex (rdg, v);
- bitmap_ior_into (partition->stmts, np->stmts);
- partition->has_writes = partition_has_writes (np);
- bitmap_ior_into (processed, np->stmts);
- partition_free (np);
-
- if (partition_has_writes (partition))
- {
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "ldist useful partition:\n");
- dump_bitmap (dump_file, partition->stmts);
- }
-
- partitions->safe_push (partition);
- partition = partition_alloc (NULL, NULL);
- }
- }
+ partition_t partition = build_rdg_partition_for_vertex (rdg, v);
+ bitmap_ior_into (processed, partition->stmts);
- /* All vertices should have been assigned to at least one partition now,
- other than vertices belonging to dead code. */
-
- if (!bitmap_empty_p (partition->stmts))
- {
if (dump_file && (dump_flags & TDF_DETAILS))
{
- fprintf (dump_file, "remaining partition:\n");
+ fprintf (dump_file, "ldist useful partition:\n");
dump_bitmap (dump_file, partition->stmts);
}
partitions->safe_push (partition);
}
- else
- partition_free (partition);
+
+ /* All vertices should have been assigned to at least one partition now,
+ other than vertices belonging to dead code. */
BITMAP_FREE (processed);
}
@@ -1465,6 +1309,79 @@ partition_contains_all_rw (struct graph *rdg,
return false;
}
+/* Compute partition dependence created by the data references in DRS1
+ and DRS2 and modify and return DIR according to that. */
+
+static int
+pg_add_dependence_edges (struct graph *rdg, vec<loop_p> loops, int dir,
+ vec<data_reference_p> drs1,
+ vec<data_reference_p> drs2)
+{
+ data_reference_p dr1, dr2;
+
+ /* dependence direction - 0 is no dependence, -1 is back,
+ 1 is forth, 2 is both (we can stop then, merging will occur). */
+ for (int ii = 0; drs1.iterate (ii, &dr1); ++ii)
+ for (int jj = 0; drs2.iterate (jj, &dr2); ++jj)
+ {
+ int this_dir = 1;
+ ddr_p ddr;
+ /* Re-shuffle data-refs to be in dominator order. */
+ if (rdg_vertex_for_stmt (rdg, DR_STMT (dr1))
+ > rdg_vertex_for_stmt (rdg, DR_STMT (dr2)))
+ {
+ data_reference_p tem = dr1;
+ dr1 = dr2;
+ dr2 = tem;
+ this_dir = -this_dir;
+ }
+ ddr = initialize_data_dependence_relation (dr1, dr2, loops);
+ compute_affine_dependence (ddr, loops[0]);
+ if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know)
+ this_dir = 2;
+ else if (DDR_ARE_DEPENDENT (ddr) == NULL_TREE)
+ {
+ if (DDR_REVERSED_P (ddr))
+ {
+ data_reference_p tem = dr1;
+ dr1 = dr2;
+ dr2 = tem;
+ this_dir = -this_dir;
+ }
+ /* Known dependences can still be unordered througout the
+ iteration space, see gcc.dg/tree-ssa/ldist-16.c. */
+ if (DDR_NUM_DIST_VECTS (ddr) != 1)
+ this_dir = 2;
+ /* If the overlap is exact preserve stmt order. */
+ else if (lambda_vector_zerop (DDR_DIST_VECT (ddr, 0), 1))
+ ;
+ else
+ {
+ /* Else as the distance vector is lexicographic positive
+ swap the dependence direction. */
+ this_dir = -this_dir;
+ }
+ }
+ else
+ this_dir = 0;
+ free_dependence_relation (ddr);
+ if (dir == 0)
+ dir = this_dir;
+ else if (dir != this_dir)
+ return 2;
+ }
+ return dir;
+}
+
+/* Compare postorder number of the partition graph vertices V1 and V2. */
+
+static int
+pgcmp (const void *v1_, const void *v2_)
+{
+ const vertex *v1 = (const vertex *)v1_;
+ const vertex *v2 = (const vertex *)v2_;
+ return v2->post - v1->post;
+}
/* Distributes the code from LOOP in such a way that producer
statements are placed before consumer statements. Tries to separate
@@ -1473,21 +1390,20 @@ partition_contains_all_rw (struct graph *rdg,
static int
distribute_loop (struct loop *loop, vec<gimple> stmts,
- control_dependences *cd)
+ control_dependences *cd, int *nb_calls)
{
struct graph *rdg;
- vec<loop_p> loop_nest;
vec<partition_t> partitions;
partition_t partition;
bool any_builtin;
int i, nbp;
+ graph *pg = NULL;
+ int num_sccs = 1;
- loop_nest.create (3);
+ *nb_calls = 0;
+ stack_vec<loop_p, 3> loop_nest;
if (!find_loop_nest (loop, &loop_nest))
- {
- loop_nest.release ();
- return 0;
- }
+ return 0;
rdg = build_rdg (loop_nest, cd);
if (!rdg)
@@ -1497,7 +1413,6 @@ distribute_loop (struct loop *loop, vec<gimple> stmts,
"Loop %d not distributed: failed to build the RDG.\n",
loop->num);
- loop_nest.release ();
return 0;
}
@@ -1514,96 +1429,197 @@ distribute_loop (struct loop *loop, vec<gimple> stmts,
any_builtin |= partition_builtin_p (partition);
}
+ /* If we are only distributing patterns but did not detect any,
+ simply bail out. */
+ if (!flag_tree_loop_distribution
+ && !any_builtin)
+ {
+ nbp = 0;
+ goto ldist_done;
+ }
+
/* If we are only distributing patterns fuse all partitions that
- were not properly classified as builtins. Else fuse partitions
- with similar memory accesses. */
+ were not classified as builtins. This also avoids chopping
+ a loop into pieces, separated by builtin calls. That is, we
+ only want no or a single loop body remaining. */
+ partition_t into;
if (!flag_tree_loop_distribution)
{
- partition_t into;
- /* If we did not detect any builtin simply bail out. */
- if (!any_builtin)
- {
- nbp = 0;
- goto ldist_done;
- }
- /* Only fuse adjacent non-builtin partitions, see PR53616.
- ??? Use dependence information to improve partition ordering. */
- i = 0;
- do
- {
- for (; partitions.iterate (i, &into); ++i)
- if (!partition_builtin_p (into))
- break;
- for (++i; partitions.iterate (i, &partition); ++i)
- if (!partition_builtin_p (partition))
+ for (i = 0; partitions.iterate (i, &into); ++i)
+ if (!partition_builtin_p (into))
+ break;
+ for (++i; partitions.iterate (i, &partition); ++i)
+ if (!partition_builtin_p (partition))
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
{
- bitmap_ior_into (into->stmts, partition->stmts);
- if (partition->kind == PKIND_REDUCTION)
- into->kind = PKIND_REDUCTION;
- partitions.ordered_remove (i);
- partition_free (partition);
- i--;
+ fprintf (dump_file, "fusing non-builtin partitions\n");
+ dump_bitmap (dump_file, into->stmts);
+ dump_bitmap (dump_file, partition->stmts);
}
- else
- break;
- }
- while ((unsigned) i < partitions.length ());
+ partition_merge_into (into, partition);
+ partitions.unordered_remove (i);
+ partition_free (partition);
+ i--;
+ }
}
- else
+
+ /* Due to limitations in the transform phase we have to fuse all
+ reduction partitions into the last partition so the existing
+ loop will contain all loop-closed PHI nodes. */
+ for (i = 0; partitions.iterate (i, &into); ++i)
+ if (partition_reduction_p (into))
+ break;
+ for (i = i + 1; partitions.iterate (i, &partition); ++i)
+ if (partition_reduction_p (partition))
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "fusing partitions\n");
+ dump_bitmap (dump_file, into->stmts);
+ dump_bitmap (dump_file, partition->stmts);
+ fprintf (dump_file, "because they have reductions\n");
+ }
+ partition_merge_into (into, partition);
+ partitions.unordered_remove (i);
+ partition_free (partition);
+ i--;
+ }
+
+ /* Apply our simple cost model - fuse partitions with similar
+ memory accesses. */
+ for (i = 0; partitions.iterate (i, &into); ++i)
{
- partition_t into;
- int j;
- for (i = 0; partitions.iterate (i, &into); ++i)
+ if (partition_builtin_p (into))
+ continue;
+ for (int j = i + 1;
+ partitions.iterate (j, &partition); ++j)
{
- if (partition_builtin_p (into))
- continue;
- for (j = i + 1;
- partitions.iterate (j, &partition); ++j)
+ if (!partition_builtin_p (partition)
+ && similar_memory_accesses (rdg, into, partition))
{
- if (!partition_builtin_p (partition)
- && similar_memory_accesses (rdg, into, partition))
+ if (dump_file && (dump_flags & TDF_DETAILS))
{
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "fusing partitions\n");
- dump_bitmap (dump_file, into->stmts);
- dump_bitmap (dump_file, partition->stmts);
- fprintf (dump_file, "because they have similar "
- "memory accesses\n");
- }
- bitmap_ior_into (into->stmts, partition->stmts);
- if (partition->kind == PKIND_REDUCTION)
- into->kind = PKIND_REDUCTION;
- partitions.ordered_remove (j);
- partition_free (partition);
- j--;
+ fprintf (dump_file, "fusing partitions\n");
+ dump_bitmap (dump_file, into->stmts);
+ dump_bitmap (dump_file, partition->stmts);
+ fprintf (dump_file, "because they have similar "
+ "memory accesses\n");
}
+ partition_merge_into (into, partition);
+ partitions.unordered_remove (j);
+ partition_free (partition);
+ j--;
}
}
}
- /* Fuse all reduction partitions into the last. */
+ /* Build the partition dependency graph. */
if (partitions.length () > 1)
{
- partition_t into = partitions.last ();
- for (i = partitions.length () - 2; i >= 0; --i)
+ pg = new_graph (partitions.length ());
+ struct pgdata {
+ partition_t partition;
+ vec<data_reference_p> writes;
+ vec<data_reference_p> reads;
+ };
+#define PGDATA(i) ((pgdata *)(pg->vertices[i].data))
+ for (i = 0; partitions.iterate (i, &partition); ++i)
{
- partition_t what = partitions[i];
- if (what->kind == PKIND_REDUCTION)
- {
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "fusing partitions\n");
- dump_bitmap (dump_file, into->stmts);
- dump_bitmap (dump_file, what->stmts);
- fprintf (dump_file, "because the latter has reductions\n");
- }
- bitmap_ior_into (into->stmts, what->stmts);
- into->kind = PKIND_REDUCTION;
- partitions.ordered_remove (i);
- partition_free (what);
- }
+ vertex *v = &pg->vertices[i];
+ pgdata *data = new pgdata;
+ data_reference_p dr;
+ /* FIXME - leaks. */
+ v->data = data;
+ bitmap_iterator bi;
+ unsigned j;
+ data->partition = partition;
+ data->reads = vNULL;
+ data->writes = vNULL;
+ EXECUTE_IF_SET_IN_BITMAP (partition->stmts, 0, j, bi)
+ for (int k = 0; RDG_DATAREFS (rdg, j).iterate (k, &dr); ++k)
+ if (DR_IS_READ (dr))
+ data->reads.safe_push (dr);
+ else
+ data->writes.safe_push (dr);
}
+ partition_t partition1, partition2;
+ for (i = 0; partitions.iterate (i, &partition1); ++i)
+ for (int j = i + 1; partitions.iterate (j, &partition2); ++j)
+ {
+ /* dependence direction - 0 is no dependence, -1 is back,
+ 1 is forth, 2 is both (we can stop then, merging will occur). */
+ int dir = 0;
+ dir = pg_add_dependence_edges (rdg, loop_nest, dir,
+ PGDATA(i)->writes,
+ PGDATA(j)->reads);
+ if (dir != 2)
+ dir = pg_add_dependence_edges (rdg, loop_nest, dir,
+ PGDATA(i)->reads,
+ PGDATA(j)->writes);
+ if (dir != 2)
+ dir = pg_add_dependence_edges (rdg, loop_nest, dir,
+ PGDATA(i)->writes,
+ PGDATA(j)->writes);
+ if (dir == 1 || dir == 2)
+ add_edge (pg, i, j);
+ if (dir == -1 || dir == 2)
+ add_edge (pg, j, i);
+ }
+
+ /* Add edges to the reduction partition (if any) to force it last. */
+ unsigned j;
+ for (j = 0; partitions.iterate (j, &partition); ++j)
+ if (partition_reduction_p (partition))
+ break;
+ if (j < partitions.length ())
+ {
+ for (unsigned i = 0; partitions.iterate (i, &partition); ++i)
+ if (i != j)
+ add_edge (pg, i, j);
+ }
+
+ /* Compute partitions we cannot separate and fuse them. */
+ num_sccs = graphds_scc (pg, NULL);
+ for (i = 0; i < num_sccs; ++i)
+ {
+ partition_t first;
+ int j;
+ for (j = 0; partitions.iterate (j, &first); ++j)
+ if (pg->vertices[j].component == i)
+ break;
+ for (j = j + 1; partitions.iterate (j, &partition); ++j)
+ if (pg->vertices[j].component == i)
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "fusing partitions\n");
+ dump_bitmap (dump_file, first->stmts);
+ dump_bitmap (dump_file, partition->stmts);
+ fprintf (dump_file, "because they are in the same "
+ "dependence SCC\n");
+ }
+ partition_merge_into (first, partition);
+ partitions[j] = NULL;
+ partition_free (partition);
+ PGDATA (j)->partition = NULL;
+ }
+ }
+
+ /* Now order the remaining nodes in postorder. */
+ qsort (pg->vertices, pg->n_vertices, sizeof (vertex), pgcmp);
+ partitions.truncate (0);
+ for (i = 0; i < pg->n_vertices; ++i)
+ {
+ pgdata *data = PGDATA (i);
+ if (data->partition)
+ partitions.safe_push (data->partition);
+ data->reads.release ();
+ data->writes.release ();
+ delete data;
+ }
+ gcc_assert (partitions.length () == (unsigned)num_sccs);
+ free_graph (pg);
}
nbp = partitions.length ();
@@ -1619,7 +1635,11 @@ distribute_loop (struct loop *loop, vec<gimple> stmts,
dump_rdg_partitions (dump_file, partitions);
FOR_EACH_VEC_ELT (partitions, i, partition)
- generate_code_for_partition (loop, partition, i < nbp - 1);
+ {
+ if (partition_builtin_p (partition))
+ (*nb_calls)++;
+ generate_code_for_partition (loop, partition, i < nbp - 1);
+ }
ldist_done:
@@ -1628,8 +1648,7 @@ distribute_loop (struct loop *loop, vec<gimple> stmts,
partitions.release ();
free_rdg (rdg);
- loop_nest.release ();
- return nbp;
+ return nbp - *nb_calls;
}
/* Distribute all loops in the current function. */
@@ -1659,7 +1678,6 @@ tree_loop_distribution (void)
vec<gimple> work_list = vNULL;
basic_block *bbs;
int num = loop->num;
- int nb_generated_loops = 0;
unsigned int i;
/* If the loop doesn't have a single exit we will fail anyway,
@@ -1714,28 +1732,32 @@ tree_loop_distribution (void)
out:
free (bbs);
+ int nb_generated_loops = 0;
+ int nb_generated_calls = 0;
+ location_t loc = find_loop_location (loop);
if (work_list.length () > 0)
{
if (!cd)
{
+ calculate_dominance_info (CDI_DOMINATORS);
calculate_dominance_info (CDI_POST_DOMINATORS);
cd = new control_dependences (create_edge_list ());
free_dominance_info (CDI_POST_DOMINATORS);
}
- nb_generated_loops = distribute_loop (loop, work_list, cd);
+ nb_generated_loops = distribute_loop (loop, work_list, cd,
+ &nb_generated_calls);
}
- if (nb_generated_loops > 0)
- changed = true;
-
- if (dump_file && (dump_flags & TDF_DETAILS))
+ if (nb_generated_loops + nb_generated_calls > 0)
{
- if (nb_generated_loops > 1)
- fprintf (dump_file, "Loop %d distributed: split to %d loops.\n",
- num, nb_generated_loops);
- else
- fprintf (dump_file, "Loop %d is the same.\n", num);
+ changed = true;
+ dump_printf_loc (MSG_OPTIMIZED_LOCATIONS,
+ loc, "Loop %d distributed: split to %d loops "
+ "and %d library calls.\n",
+ num, nb_generated_loops, nb_generated_calls);
}
+ else if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "Loop %d is the same.\n", num);
work_list.release ();
}
@@ -1783,8 +1805,8 @@ const pass_data pass_data_loop_distribution =
class pass_loop_distribution : public gimple_opt_pass
{
public:
- pass_loop_distribution(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_loop_distribution, ctxt)
+ pass_loop_distribution (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_loop_distribution, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/tree-mudflap.c b/gcc/tree-mudflap.c
deleted file mode 100644
index 439d22f312a..00000000000
--- a/gcc/tree-mudflap.c
+++ /dev/null
@@ -1,1450 +0,0 @@
-/* Mudflap: narrow-pointer bounds-checking by tree rewriting.
- Copyright (C) 2002-2013 Free Software Foundation, Inc.
- Contributed by Frank Ch. Eigler <fche@redhat.com>
- and Graydon Hoare <graydon@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 "tm.h"
-#include "tree.h"
-#include "tm_p.h"
-#include "basic-block.h"
-#include "flags.h"
-#include "function.h"
-#include "tree-inline.h"
-#include "gimple.h"
-#include "tree-iterator.h"
-#include "tree-ssa.h"
-#include "tree-mudflap.h"
-#include "tree-pass.h"
-#include "hashtab.h"
-#include "diagnostic.h"
-#include "demangle.h"
-#include "langhooks.h"
-#include "ggc.h"
-#include "cgraph.h"
-#include "gimple.h"
-
-extern void add_bb_to_loop (basic_block, struct loop *);
-
-/* Internal function decls */
-
-
-/* Options. */
-#define flag_mudflap_threads (flag_mudflap == 2)
-
-/* Helpers. */
-static tree mf_build_string (const char *string);
-static tree mf_varname_tree (tree);
-static tree mf_file_function_line_tree (location_t);
-
-/* Indirection-related instrumentation. */
-static void mf_decl_cache_locals (void);
-static void mf_decl_clear_locals (void);
-static void mf_xform_statements (void);
-static unsigned int execute_mudflap_function_ops (void);
-
-/* Addressable variables instrumentation. */
-static void mf_xform_decls (gimple_seq, tree);
-static tree mx_xfn_xform_decls (gimple_stmt_iterator *, bool *,
- struct walk_stmt_info *);
-static gimple_seq mx_register_decls (tree, gimple_seq, location_t);
-static unsigned int execute_mudflap_function_decls (void);
-
-/* Return true if DECL is artificial stub that shouldn't be instrumented by
- mf. We should instrument clones of non-artificial functions. */
-static inline bool
-mf_artificial (const_tree decl)
-{
- return DECL_ARTIFICIAL (DECL_ORIGIN (decl));
-}
-
-/* ------------------------------------------------------------------------ */
-/* Some generally helpful functions for mudflap instrumentation. */
-
-/* Build a reference to a literal string. */
-static tree
-mf_build_string (const char *string)
-{
- size_t len = strlen (string);
- tree result = mf_mark (build_string (len + 1, string));
-
- TREE_TYPE (result) = build_array_type
- (char_type_node, build_index_type (size_int (len)));
- TREE_CONSTANT (result) = 1;
- TREE_READONLY (result) = 1;
- TREE_STATIC (result) = 1;
-
- result = build1 (ADDR_EXPR, build_pointer_type (char_type_node), result);
-
- return mf_mark (result);
-}
-
-/* Create a properly typed STRING_CST node that describes the given
- declaration. It will be used as an argument for __mf_register().
- Try to construct a helpful string, including file/function/variable
- name. */
-
-static tree
-mf_varname_tree (tree decl)
-{
- const char *buf_contents;
- tree result;
-
- gcc_assert (decl);
-
- pretty_printer buf;
-
- /* Add FILENAME[:LINENUMBER[:COLUMNNUMBER]]. */
- {
- expanded_location xloc = expand_location (DECL_SOURCE_LOCATION (decl));
- const char *sourcefile;
- unsigned sourceline = xloc.line;
- unsigned sourcecolumn = 0;
- sourcecolumn = xloc.column;
- sourcefile = xloc.file;
- if (sourcefile == NULL && current_function_decl != NULL_TREE)
- sourcefile = DECL_SOURCE_FILE (current_function_decl);
- if (sourcefile == NULL)
- sourcefile = "<unknown file>";
-
- pp_string (&buf, sourcefile);
-
- if (sourceline != 0)
- {
- pp_colon (&buf);
- pp_decimal_int (&buf, sourceline);
-
- if (sourcecolumn != 0)
- {
- pp_colon (&buf);
- pp_decimal_int (&buf, sourcecolumn);
- }
- }
- }
-
- if (current_function_decl != NULL_TREE)
- {
- /* Add (FUNCTION) */
- pp_string (&buf, " (");
- {
- const char *funcname = NULL;
- if (DECL_NAME (current_function_decl))
- funcname = lang_hooks.decl_printable_name (current_function_decl, 1);
- if (funcname == NULL)
- funcname = "anonymous fn";
-
- pp_string (&buf, funcname);
- }
- pp_string (&buf, ") ");
- }
- else
- pp_space (&buf);
-
- /* Add <variable-declaration>, possibly demangled. */
- {
- const char *declname = NULL;
-
- if (DECL_NAME (decl) != NULL)
- {
- if (strcmp ("GNU C++", lang_hooks.name) == 0)
- {
- /* The gcc/cp decl_printable_name hook doesn't do as good a job as
- the libiberty demangler. */
- declname = cplus_demangle (IDENTIFIER_POINTER (DECL_NAME (decl)),
- DMGL_AUTO | DMGL_VERBOSE);
- }
- if (declname == NULL)
- declname = lang_hooks.decl_printable_name (decl, 3);
- }
- if (declname == NULL)
- declname = "<unnamed variable>";
-
- pp_string (&buf, declname);
- }
-
- /* Return the lot as a new STRING_CST. */
- buf_contents = ggc_strdup (pp_formatted_text (&buf));
- result = mf_build_string (buf_contents);
- pp_clear_output_area (&buf);
-
- return result;
-}
-
-
-/* And another friend, for producing a simpler message. */
-
-static tree
-mf_file_function_line_tree (location_t location)
-{
- expanded_location xloc = expand_location (location);
- const char *file = NULL, *colon, *line, *op, *name, *cp;
- char linecolbuf[30]; /* Enough for two decimal numbers plus a colon. */
- char *string;
- tree result;
-
- /* Add FILENAME[:LINENUMBER[:COLUMNNUMBER]]. */
- file = xloc.file;
- if (file == NULL && current_function_decl != NULL_TREE)
- file = DECL_SOURCE_FILE (current_function_decl);
- if (file == NULL)
- file = "<unknown file>";
-
- if (xloc.line > 0)
- {
- if (xloc.column > 0)
- sprintf (linecolbuf, "%d:%d", xloc.line, xloc.column);
- else
- sprintf (linecolbuf, "%d", xloc.line);
- colon = ":";
- line = linecolbuf;
- }
- else
- colon = line = "";
-
- /* Add (FUNCTION). */
- name = lang_hooks.decl_printable_name (current_function_decl, 1);
- if (name)
- {
- op = " (";
- cp = ")";
- }
- else
- op = name = cp = "";
-
- string = concat (file, colon, line, op, name, cp, NULL);
- result = mf_build_string (string);
- free (string);
-
- return result;
-}
-
-
-/* global tree nodes */
-
-/* Global tree objects for global variables and functions exported by
- mudflap runtime library. mf_init_extern_trees must be called
- before using these. */
-
-/* uintptr_t (usually "unsigned long") */
-static GTY (()) tree mf_uintptr_type;
-
-/* struct __mf_cache { uintptr_t low; uintptr_t high; }; */
-static GTY (()) tree mf_cache_struct_type;
-
-/* struct __mf_cache * const */
-static GTY (()) tree mf_cache_structptr_type;
-
-/* extern struct __mf_cache __mf_lookup_cache []; */
-static GTY (()) tree mf_cache_array_decl;
-
-/* extern unsigned char __mf_lc_shift; */
-static GTY (()) tree mf_cache_shift_decl;
-
-/* extern uintptr_t __mf_lc_mask; */
-static GTY (()) tree mf_cache_mask_decl;
-
-/* Their function-scope local shadows, used in single-threaded mode only. */
-
-/* auto const unsigned char __mf_lc_shift_l; */
-static GTY (()) tree mf_cache_shift_decl_l;
-
-/* auto const uintptr_t __mf_lc_mask_l; */
-static GTY (()) tree mf_cache_mask_decl_l;
-
-/* extern void __mf_check (void *ptr, size_t sz, int type, const char *); */
-static GTY (()) tree mf_check_fndecl;
-
-/* extern void __mf_register (void *ptr, size_t sz, int type, const char *); */
-static GTY (()) tree mf_register_fndecl;
-
-/* extern void __mf_unregister (void *ptr, size_t sz, int type); */
-static GTY (()) tree mf_unregister_fndecl;
-
-/* extern void __mf_init (); */
-static GTY (()) tree mf_init_fndecl;
-
-/* extern int __mf_set_options (const char*); */
-static GTY (()) tree mf_set_options_fndecl;
-
-
-/* Helper for mudflap_init: construct a decl with the given category,
- name, and type, mark it an external reference, and pushdecl it. */
-static inline tree
-mf_make_builtin (enum tree_code category, const char *name, tree type)
-{
- tree decl = mf_mark (build_decl (UNKNOWN_LOCATION,
- category, get_identifier (name), type));
- TREE_PUBLIC (decl) = 1;
- DECL_EXTERNAL (decl) = 1;
- lang_hooks.decls.pushdecl (decl);
- /* The decl was declared by the compiler. */
- DECL_ARTIFICIAL (decl) = 1;
- /* And we don't want debug info for it. */
- DECL_IGNORED_P (decl) = 1;
- return decl;
-}
-
-/* Helper for mudflap_init: construct a tree corresponding to the type
- struct __mf_cache { uintptr_t low; uintptr_t high; };
- where uintptr_t is the FIELD_TYPE argument. */
-static inline tree
-mf_make_mf_cache_struct_type (tree field_type)
-{
- /* There is, abominably, no language-independent way to construct a
- RECORD_TYPE. So we have to call the basic type construction
- primitives by hand. */
- tree fieldlo = build_decl (UNKNOWN_LOCATION,
- FIELD_DECL, get_identifier ("low"), field_type);
- tree fieldhi = build_decl (UNKNOWN_LOCATION,
- FIELD_DECL, get_identifier ("high"), field_type);
-
- tree struct_type = make_node (RECORD_TYPE);
- DECL_CONTEXT (fieldlo) = struct_type;
- DECL_CONTEXT (fieldhi) = struct_type;
- DECL_CHAIN (fieldlo) = fieldhi;
- TYPE_FIELDS (struct_type) = fieldlo;
- TYPE_NAME (struct_type) = get_identifier ("__mf_cache");
- layout_type (struct_type);
-
- return struct_type;
-}
-
-/* Initialize the global tree nodes that correspond to mf-runtime.h
- declarations. */
-void
-mudflap_init (void)
-{
- static bool done = false;
- tree mf_const_string_type;
- tree mf_cache_array_type;
- tree mf_check_register_fntype;
- tree mf_unregister_fntype;
- tree mf_init_fntype;
- tree mf_set_options_fntype;
-
- if (done)
- return;
- done = true;
-
- mf_uintptr_type = lang_hooks.types.type_for_mode (ptr_mode,
- /*unsignedp=*/true);
- mf_const_string_type
- = build_pointer_type (build_qualified_type
- (char_type_node, TYPE_QUAL_CONST));
-
- mf_cache_struct_type = mf_make_mf_cache_struct_type (mf_uintptr_type);
- mf_cache_structptr_type = build_pointer_type (mf_cache_struct_type);
- mf_cache_array_type = build_array_type (mf_cache_struct_type, 0);
- mf_check_register_fntype =
- build_function_type_list (void_type_node, ptr_type_node, size_type_node,
- integer_type_node, mf_const_string_type, NULL_TREE);
- mf_unregister_fntype =
- build_function_type_list (void_type_node, ptr_type_node, size_type_node,
- integer_type_node, NULL_TREE);
- mf_init_fntype =
- build_function_type_list (void_type_node, NULL_TREE);
- mf_set_options_fntype =
- build_function_type_list (integer_type_node, mf_const_string_type, NULL_TREE);
-
- mf_cache_array_decl = mf_make_builtin (VAR_DECL, "__mf_lookup_cache",
- mf_cache_array_type);
- mf_cache_shift_decl = mf_make_builtin (VAR_DECL, "__mf_lc_shift",
- unsigned_char_type_node);
- mf_cache_mask_decl = mf_make_builtin (VAR_DECL, "__mf_lc_mask",
- mf_uintptr_type);
- /* Don't process these in mudflap_enqueue_decl, should they come by
- there for some reason. */
- mf_mark (mf_cache_array_decl);
- mf_mark (mf_cache_shift_decl);
- mf_mark (mf_cache_mask_decl);
- mf_check_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_check",
- mf_check_register_fntype);
- mf_register_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_register",
- mf_check_register_fntype);
- mf_unregister_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_unregister",
- mf_unregister_fntype);
- mf_init_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_init",
- mf_init_fntype);
- mf_set_options_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_set_options",
- mf_set_options_fntype);
-}
-
-
-/* ------------------------------------------------------------------------ */
-/* This is the second part of the mudflap instrumentation. It works on
- low-level GIMPLE using the CFG, because we want to run this pass after
- tree optimizations have been performed, but we have to preserve the CFG
- for expansion from trees to RTL.
- Below is the list of transformations performed on statements in the
- current function.
-
- 1) Memory reference transforms: Perform the mudflap indirection-related
- tree transforms on memory references.
-
- 2) Mark BUILTIN_ALLOCA calls not inlineable.
-
- */
-
-static unsigned int
-execute_mudflap_function_ops (void)
-{
- struct gimplify_ctx gctx;
-
- /* Don't instrument functions such as the synthetic constructor
- built during mudflap_finish_file. */
- if (mf_marked_p (current_function_decl)
- || mf_artificial (current_function_decl))
- return 0;
-
- push_gimplify_context (&gctx);
-
- /* In multithreaded mode, don't cache the lookup cache parameters. */
- if (! flag_mudflap_threads)
- mf_decl_cache_locals ();
-
- mf_xform_statements ();
-
- if (! flag_mudflap_threads)
- mf_decl_clear_locals ();
-
- pop_gimplify_context (NULL);
- return 0;
-}
-
-/* Insert a gimple_seq SEQ on all the outgoing edges out of BB. Note that
- if BB has more than one edge, STMT will be replicated for each edge.
- Also, abnormal edges will be ignored. */
-
-static void
-insert_edge_copies_seq (gimple_seq seq, basic_block bb)
-{
- edge e;
- edge_iterator ei;
- unsigned n_copies = -1;
-
- FOR_EACH_EDGE (e, ei, bb->succs)
- if (!(e->flags & EDGE_ABNORMAL))
- n_copies++;
-
- FOR_EACH_EDGE (e, ei, bb->succs)
- if (!(e->flags & EDGE_ABNORMAL))
- gsi_insert_seq_on_edge (e, n_copies-- > 0 ? gimple_seq_copy (seq) : seq);
-}
-
-/* Create and initialize local shadow variables for the lookup cache
- globals. Put their decls in the *_l globals for use by
- mf_build_check_statement_for. */
-
-static void
-mf_decl_cache_locals (void)
-{
- gimple g;
- gimple_seq seq = NULL;
-
- /* Build the cache vars. */
- mf_cache_shift_decl_l
- = mf_mark (create_tmp_reg (TREE_TYPE (mf_cache_shift_decl),
- "__mf_lookup_shift_l"));
-
- mf_cache_mask_decl_l
- = mf_mark (create_tmp_reg (TREE_TYPE (mf_cache_mask_decl),
- "__mf_lookup_mask_l"));
-
- /* Build initialization nodes for the cache vars. We just load the
- globals into the cache variables. */
- g = gimple_build_assign (mf_cache_shift_decl_l, mf_cache_shift_decl);
- gimple_set_location (g, DECL_SOURCE_LOCATION (current_function_decl));
- gimple_seq_add_stmt (&seq, g);
-
- g = gimple_build_assign (mf_cache_mask_decl_l, mf_cache_mask_decl);
- gimple_set_location (g, DECL_SOURCE_LOCATION (current_function_decl));
- gimple_seq_add_stmt (&seq, g);
-
- insert_edge_copies_seq (seq, ENTRY_BLOCK_PTR);
-
- gsi_commit_edge_inserts ();
-}
-
-
-static void
-mf_decl_clear_locals (void)
-{
- /* Unset local shadows. */
- mf_cache_shift_decl_l = NULL_TREE;
- mf_cache_mask_decl_l = NULL_TREE;
-}
-
-static void
-mf_build_check_statement_for (tree base, tree limit,
- gimple_stmt_iterator *instr_gsi,
- location_t location, tree dirflag)
-{
- gimple_stmt_iterator gsi;
- basic_block cond_bb, then_bb, join_bb;
- edge e;
- tree cond, t, u, v;
- tree mf_base;
- tree mf_elem;
- tree mf_limit;
- gimple g;
- gimple_seq seq, stmts;
-
- /* We first need to split the current basic block, and start altering
- the CFG. This allows us to insert the statements we're about to
- construct into the right basic blocks. */
-
- cond_bb = gimple_bb (gsi_stmt (*instr_gsi));
- gsi = *instr_gsi;
- gsi_prev (&gsi);
- if (! gsi_end_p (gsi))
- e = split_block (cond_bb, gsi_stmt (gsi));
- else
- e = split_block_after_labels (cond_bb);
- cond_bb = e->src;
- join_bb = e->dest;
-
- /* A recap at this point: join_bb is the basic block at whose head
- is the gimple statement for which this check expression is being
- built. cond_bb is the (possibly new, synthetic) basic block the
- end of which will contain the cache-lookup code, and a
- conditional that jumps to the cache-miss code or, much more
- likely, over to join_bb. */
-
- /* Create the bb that contains the cache-miss fallback block (mf_check). */
- then_bb = create_empty_bb (cond_bb);
- make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
- make_single_succ_edge (then_bb, join_bb, EDGE_FALLTHRU);
-
- /* Mark the pseudo-fallthrough edge from cond_bb to join_bb. */
- e = find_edge (cond_bb, join_bb);
- e->flags = EDGE_FALSE_VALUE;
- e->count = cond_bb->count;
- e->probability = REG_BR_PROB_BASE;
-
- /* Update dominance info. Note that bb_join's data was
- updated by split_block. */
- if (dom_info_available_p (CDI_DOMINATORS))
- {
- set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
- set_immediate_dominator (CDI_DOMINATORS, join_bb, cond_bb);
- }
-
- /* Update loop info. */
- if (current_loops)
- add_bb_to_loop (then_bb, cond_bb->loop_father);
-
- /* Build our local variables. */
- mf_elem = create_tmp_reg (mf_cache_structptr_type, "__mf_elem");
- mf_base = create_tmp_reg (mf_uintptr_type, "__mf_base");
- mf_limit = create_tmp_reg (mf_uintptr_type, "__mf_limit");
-
- /* Build: __mf_base = (uintptr_t) <base address expression>. */
- seq = NULL;
- t = fold_convert_loc (location, mf_uintptr_type,
- unshare_expr (base));
- t = force_gimple_operand (t, &stmts, false, NULL_TREE);
- gimple_seq_add_seq (&seq, stmts);
- g = gimple_build_assign (mf_base, t);
- gimple_set_location (g, location);
- gimple_seq_add_stmt (&seq, g);
-
- /* Build: __mf_limit = (uintptr_t) <limit address expression>. */
- t = fold_convert_loc (location, mf_uintptr_type,
- unshare_expr (limit));
- t = force_gimple_operand (t, &stmts, false, NULL_TREE);
- gimple_seq_add_seq (&seq, stmts);
- g = gimple_build_assign (mf_limit, t);
- gimple_set_location (g, location);
- gimple_seq_add_stmt (&seq, g);
-
- /* Build: __mf_elem = &__mf_lookup_cache [(__mf_base >> __mf_shift)
- & __mf_mask]. */
- t = build2 (RSHIFT_EXPR, mf_uintptr_type, mf_base,
- flag_mudflap_threads ? mf_cache_shift_decl
- : mf_cache_shift_decl_l);
- t = build2 (BIT_AND_EXPR, mf_uintptr_type, t,
- flag_mudflap_threads ? mf_cache_mask_decl
- : mf_cache_mask_decl_l);
- t = build4 (ARRAY_REF,
- TREE_TYPE (TREE_TYPE (mf_cache_array_decl)),
- mf_cache_array_decl, t, NULL_TREE, NULL_TREE);
- t = build1 (ADDR_EXPR, mf_cache_structptr_type, t);
- t = force_gimple_operand (t, &stmts, false, NULL_TREE);
- gimple_seq_add_seq (&seq, stmts);
- g = gimple_build_assign (mf_elem, t);
- gimple_set_location (g, location);
- gimple_seq_add_stmt (&seq, g);
-
- /* Quick validity check.
-
- if (__mf_elem->low > __mf_base
- || (__mf_elem_high < __mf_limit))
- {
- __mf_check ();
- ... and only if single-threaded:
- __mf_lookup_shift_1 = f...;
- __mf_lookup_mask_l = ...;
- }
-
- It is expected that this body of code is rarely executed so we mark
- the edge to the THEN clause of the conditional jump as unlikely. */
-
- /* Construct t <-- '__mf_elem->low > __mf_base'. */
- t = build3 (COMPONENT_REF, mf_uintptr_type,
- build1 (INDIRECT_REF, mf_cache_struct_type, mf_elem),
- TYPE_FIELDS (mf_cache_struct_type), NULL_TREE);
- t = build2 (GT_EXPR, boolean_type_node, t, mf_base);
-
- /* Construct '__mf_elem->high < __mf_limit'.
-
- First build:
- 1) u <-- '__mf_elem->high'
- 2) v <-- '__mf_limit'.
-
- Then build 'u <-- (u < v). */
-
- u = build3 (COMPONENT_REF, mf_uintptr_type,
- build1 (INDIRECT_REF, mf_cache_struct_type, mf_elem),
- DECL_CHAIN (TYPE_FIELDS (mf_cache_struct_type)), NULL_TREE);
-
- v = mf_limit;
-
- u = build2 (LT_EXPR, boolean_type_node, u, v);
-
- /* Build the composed conditional: t <-- 't || u'. Then store the
- result of the evaluation of 't' in a temporary variable which we
- can use as the condition for the conditional jump. */
- t = build2 (TRUTH_OR_EXPR, boolean_type_node, t, u);
- t = force_gimple_operand (t, &stmts, false, NULL_TREE);
- gimple_seq_add_seq (&seq, stmts);
- cond = create_tmp_reg (boolean_type_node, "__mf_unlikely_cond");
- g = gimple_build_assign (cond, t);
- gimple_set_location (g, location);
- gimple_seq_add_stmt (&seq, g);
-
- /* Build the conditional jump. 'cond' is just a temporary so we can
- simply build a void COND_EXPR. We do need labels in both arms though. */
- g = gimple_build_cond (NE_EXPR, cond, boolean_false_node, NULL_TREE,
- NULL_TREE);
- gimple_set_location (g, location);
- gimple_seq_add_stmt (&seq, g);
-
- /* At this point, after so much hard work, we have only constructed
- the conditional jump,
-
- if (__mf_elem->low > __mf_base
- || (__mf_elem_high < __mf_limit))
-
- The lowered GIMPLE tree representing this code is in the statement
- list starting at 'head'.
-
- We can insert this now in the current basic block, i.e. the one that
- the statement we're instrumenting was originally in. */
- gsi = gsi_last_bb (cond_bb);
- gsi_insert_seq_after (&gsi, seq, GSI_CONTINUE_LINKING);
-
- /* Now build up the body of the cache-miss handling:
-
- __mf_check();
- refresh *_l vars.
-
- This is the body of the conditional. */
-
- seq = NULL;
- /* u is a string, so it is already a gimple value. */
- u = mf_file_function_line_tree (location);
- /* NB: we pass the overall [base..limit] range to mf_check. */
- v = fold_build2_loc (location, PLUS_EXPR, mf_uintptr_type,
- fold_build2_loc (location,
- MINUS_EXPR, mf_uintptr_type, mf_limit, mf_base),
- build_int_cst (mf_uintptr_type, 1));
- v = force_gimple_operand (v, &stmts, true, NULL_TREE);
- gimple_seq_add_seq (&seq, stmts);
- g = gimple_build_call (mf_check_fndecl, 4, mf_base, v, dirflag, u);
- gimple_seq_add_stmt (&seq, g);
-
- if (! flag_mudflap_threads)
- {
- if (stmt_ends_bb_p (g))
- {
- gsi = gsi_start_bb (then_bb);
- gsi_insert_seq_after (&gsi, seq, GSI_CONTINUE_LINKING);
- e = split_block (then_bb, g);
- then_bb = e->dest;
- seq = NULL;
- }
-
- g = gimple_build_assign (mf_cache_shift_decl_l, mf_cache_shift_decl);
- gimple_seq_add_stmt (&seq, g);
-
- g = gimple_build_assign (mf_cache_mask_decl_l, mf_cache_mask_decl);
- gimple_seq_add_stmt (&seq, g);
- }
-
- /* Insert the check code in the THEN block. */
- gsi = gsi_start_bb (then_bb);
- gsi_insert_seq_after (&gsi, seq, GSI_CONTINUE_LINKING);
-
- *instr_gsi = gsi_start_bb (join_bb);
-}
-
-
-/* Check whether the given decl, generally a VAR_DECL or PARM_DECL, is
- eligible for instrumentation. For the mudflap1 pass, this implies
- that it should be registered with the libmudflap runtime. For the
- mudflap2 pass this means instrumenting an indirection operation with
- respect to the object.
-*/
-static int
-mf_decl_eligible_p (tree decl)
-{
- return ((TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL)
- /* The decl must have its address taken. In the case of
- arrays, this flag is also set if the indexes are not
- compile-time known valid constants. */
- /* XXX: not sufficient: return-by-value structs! */
- && TREE_ADDRESSABLE (decl)
- /* The type of the variable must be complete. */
- && COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (decl))
- /* The decl hasn't been decomposed somehow. */
- && !DECL_HAS_VALUE_EXPR_P (decl));
-}
-
-
-static void
-mf_xform_derefs_1 (gimple_stmt_iterator *iter, tree *tp,
- location_t location, tree dirflag)
-{
- tree type, base, limit, addr, size, t;
-
- /* Don't instrument read operations. */
- if (dirflag == integer_zero_node && flag_mudflap_ignore_reads)
- return;
-
- /* Don't instrument marked nodes. */
- if (mf_marked_p (*tp))
- return;
-
- t = *tp;
- type = TREE_TYPE (t);
-
- if (type == error_mark_node)
- return;
-
- size = TYPE_SIZE_UNIT (type);
-
- switch (TREE_CODE (t))
- {
- case ARRAY_REF:
- case COMPONENT_REF:
- {
- /* This is trickier than it may first appear. The reason is
- that we are looking at expressions from the "inside out" at
- this point. We may have a complex nested aggregate/array
- expression (e.g. "a.b[i].c"), maybe with an indirection as
- the leftmost operator ("p->a.b.d"), where instrumentation
- is necessary. Or we may have an innocent "a.b.c"
- expression that must not be instrumented. We need to
- recurse all the way down the nesting structure to figure it
- out: looking just at the outer node is not enough. */
- tree var;
- int component_ref_only = (TREE_CODE (t) == COMPONENT_REF);
- /* If we have a bitfield component reference, we must note the
- innermost addressable object in ELT, from which we will
- construct the byte-addressable bounds of the bitfield. */
- tree elt = NULL_TREE;
- int bitfield_ref_p = (TREE_CODE (t) == COMPONENT_REF
- && DECL_BIT_FIELD_TYPE (TREE_OPERAND (t, 1)));
-
- /* Iterate to the top of the ARRAY_REF/COMPONENT_REF
- containment hierarchy to find the outermost VAR_DECL. */
- var = TREE_OPERAND (t, 0);
- while (1)
- {
- if (bitfield_ref_p && elt == NULL_TREE
- && (TREE_CODE (var) == ARRAY_REF
- || TREE_CODE (var) == COMPONENT_REF))
- elt = var;
-
- if (TREE_CODE (var) == ARRAY_REF)
- {
- component_ref_only = 0;
- var = TREE_OPERAND (var, 0);
- }
- else if (TREE_CODE (var) == COMPONENT_REF)
- var = TREE_OPERAND (var, 0);
- else if (INDIRECT_REF_P (var)
- || TREE_CODE (var) == MEM_REF)
- {
- base = TREE_OPERAND (var, 0);
- break;
- }
- else if (TREE_CODE (var) == VIEW_CONVERT_EXPR)
- {
- var = TREE_OPERAND (var, 0);
- if (CONSTANT_CLASS_P (var)
- && TREE_CODE (var) != STRING_CST)
- return;
- }
- else
- {
- gcc_assert (TREE_CODE (var) == VAR_DECL
- || TREE_CODE (var) == PARM_DECL
- || TREE_CODE (var) == RESULT_DECL
- || TREE_CODE (var) == STRING_CST);
- /* Don't instrument this access if the underlying
- variable is not "eligible". This test matches
- those arrays that have only known-valid indexes,
- and thus are not labeled TREE_ADDRESSABLE. */
- if (! mf_decl_eligible_p (var) || component_ref_only)
- return;
- else
- {
- base = build1 (ADDR_EXPR,
- build_pointer_type (TREE_TYPE (var)), var);
- break;
- }
- }
- }
-
- /* Handle the case of ordinary non-indirection structure
- accesses. These have only nested COMPONENT_REF nodes (no
- INDIRECT_REF), but pass through the above filter loop.
- Note that it's possible for such a struct variable to match
- the eligible_p test because someone else might take its
- address sometime. */
-
- /* We need special processing for bitfield components, because
- their addresses cannot be taken. */
- if (bitfield_ref_p)
- {
- tree field = TREE_OPERAND (t, 1);
-
- if (TREE_CODE (DECL_SIZE_UNIT (field)) == INTEGER_CST)
- size = DECL_SIZE_UNIT (field);
-
- if (elt)
- elt = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (elt)),
- elt);
- addr = fold_convert_loc (location, ptr_type_node, elt ? elt : base);
- addr = fold_build_pointer_plus_loc (location,
- addr, byte_position (field));
- }
- else
- addr = build1 (ADDR_EXPR, build_pointer_type (type), t);
-
- limit = fold_build2_loc (location, MINUS_EXPR, mf_uintptr_type,
- fold_build2_loc (location, PLUS_EXPR, mf_uintptr_type,
- fold_convert (mf_uintptr_type, addr),
- size),
- integer_one_node);
- }
- break;
-
- case INDIRECT_REF:
- addr = TREE_OPERAND (t, 0);
- base = addr;
- limit = fold_build_pointer_plus_hwi_loc
- (location, fold_build_pointer_plus_loc (location, base, size), -1);
- break;
-
- case MEM_REF:
- if (addr_expr_of_non_mem_decl_p (TREE_OPERAND (t, 0)))
- return;
-
- addr = fold_build_pointer_plus_loc (location, TREE_OPERAND (t, 0),
- TREE_OPERAND (t, 1));
- base = addr;
- limit = fold_build_pointer_plus_hwi_loc (location,
- fold_build_pointer_plus_loc (location,
- base, size), -1);
- break;
-
- case TARGET_MEM_REF:
- if (addr_expr_of_non_mem_decl_p (TMR_BASE (t)))
- return;
-
- addr = tree_mem_ref_addr (ptr_type_node, t);
- base = addr;
- limit = fold_build_pointer_plus_hwi_loc (location,
- fold_build_pointer_plus_loc (location,
- base, size), -1);
- break;
-
- case ARRAY_RANGE_REF:
- warning (OPT_Wmudflap,
- "mudflap checking not yet implemented for ARRAY_RANGE_REF");
- return;
-
- case BIT_FIELD_REF:
- /* ??? merge with COMPONENT_REF code above? */
- {
- tree ofs, rem, bpu;
-
- /* If we're not dereferencing something, then the access
- must be ok. */
- if (TREE_CODE (TREE_OPERAND (t, 0)) != INDIRECT_REF)
- return;
-
- bpu = bitsize_int (BITS_PER_UNIT);
- ofs = fold_convert (bitsizetype, TREE_OPERAND (t, 2));
- rem = size_binop_loc (location, TRUNC_MOD_EXPR, ofs, bpu);
- ofs = size_binop_loc (location, TRUNC_DIV_EXPR, ofs, bpu);
-
- size = fold_convert (bitsizetype, TREE_OPERAND (t, 1));
- size = size_binop_loc (location, PLUS_EXPR, size, rem);
- size = size_binop_loc (location, CEIL_DIV_EXPR, size, bpu);
- size = fold_convert (sizetype, size);
-
- addr = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
- addr = fold_convert (ptr_type_node, addr);
- addr = fold_build_pointer_plus_loc (location, addr, ofs);
-
- base = addr;
- limit = fold_build_pointer_plus_hwi_loc (location,
- fold_build_pointer_plus_loc (location,
- base, size), -1);
- }
- break;
-
- default:
- return;
- }
-
- mf_build_check_statement_for (base, limit, iter, location, dirflag);
-}
-/* Transform
- 1) Memory references.
-*/
-static void
-mf_xform_statements (void)
-{
- basic_block bb, next;
- gimple_stmt_iterator i;
- int saved_last_basic_block = last_basic_block;
- enum gimple_rhs_class grhs_class;
-
- bb = ENTRY_BLOCK_PTR ->next_bb;
- do
- {
- next = bb->next_bb;
- for (i = gsi_start_bb (bb); !gsi_end_p (i); gsi_next (&i))
- {
- gimple s = gsi_stmt (i);
-
- /* Only a few GIMPLE statements can reference memory. */
- switch (gimple_code (s))
- {
- case GIMPLE_ASSIGN:
- mf_xform_derefs_1 (&i, gimple_assign_lhs_ptr (s),
- gimple_location (s), integer_one_node);
- mf_xform_derefs_1 (&i, gimple_assign_rhs1_ptr (s),
- gimple_location (s), integer_zero_node);
- grhs_class = get_gimple_rhs_class (gimple_assign_rhs_code (s));
- if (grhs_class == GIMPLE_BINARY_RHS)
- mf_xform_derefs_1 (&i, gimple_assign_rhs2_ptr (s),
- gimple_location (s), integer_zero_node);
- break;
-
- case GIMPLE_RETURN:
- if (gimple_return_retval (s) != NULL_TREE)
- {
- mf_xform_derefs_1 (&i, gimple_return_retval_ptr (s),
- gimple_location (s),
- integer_zero_node);
- }
- break;
-
- default:
- ;
- }
- }
- bb = next;
- }
- while (bb && bb->index <= saved_last_basic_block);
-}
-
-/* ------------------------------------------------------------------------ */
-/* ADDR_EXPR transforms. Perform the declaration-related mudflap tree
- transforms on the current function.
-
- This is the first part of the mudflap instrumentation. It works on
- high-level GIMPLE because after lowering, all variables are moved out
- of their BIND_EXPR binding context, and we lose liveness information
- for the declarations we wish to instrument. */
-
-static unsigned int
-execute_mudflap_function_decls (void)
-{
- struct gimplify_ctx gctx;
-
- /* Don't instrument functions such as the synthetic constructor
- built during mudflap_finish_file. */
- if (mf_marked_p (current_function_decl)
- || mf_artificial (current_function_decl))
- return 0;
-
- push_gimplify_context (&gctx);
-
- mf_xform_decls (gimple_body (current_function_decl),
- DECL_ARGUMENTS (current_function_decl));
-
- pop_gimplify_context (NULL);
- return 0;
-}
-
-/* This struct is passed between mf_xform_decls to store state needed
- during the traversal searching for objects that have their
- addresses taken. */
-struct mf_xform_decls_data
-{
- tree param_decls;
-};
-
-
-/* Synthesize a CALL_EXPR and a TRY_FINALLY_EXPR, for this chain of
- _DECLs if appropriate. Arrange to call the __mf_register function
- now, and the __mf_unregister function later for each. Return the
- gimple sequence after synthesis. */
-gimple_seq
-mx_register_decls (tree decl, gimple_seq seq, location_t location)
-{
- gimple_seq finally_stmts = NULL;
- gimple_stmt_iterator initially_stmts = gsi_start (seq);
-
- while (decl != NULL_TREE)
- {
- if (mf_decl_eligible_p (decl)
- /* Not already processed. */
- && ! mf_marked_p (decl)
- /* Automatic variable. */
- && ! DECL_EXTERNAL (decl)
- && ! TREE_STATIC (decl))
- {
- tree size = NULL_TREE, variable_name;
- gimple unregister_fncall, register_fncall;
- tree unregister_fncall_param, register_fncall_param;
-
- /* Variable-sized objects should have sizes already been
- gimplified when we got here. */
- size = fold_convert (size_type_node,
- TYPE_SIZE_UNIT (TREE_TYPE (decl)));
- gcc_assert (is_gimple_val (size));
-
-
- unregister_fncall_param =
- mf_mark (build1 (ADDR_EXPR,
- build_pointer_type (TREE_TYPE (decl)),
- decl));
- /* __mf_unregister (&VARIABLE, sizeof (VARIABLE), __MF_TYPE_STACK) */
- unregister_fncall = gimple_build_call (mf_unregister_fndecl, 3,
- unregister_fncall_param,
- size,
- integer_three_node);
-
-
- variable_name = mf_varname_tree (decl);
- register_fncall_param =
- mf_mark (build1 (ADDR_EXPR,
- build_pointer_type (TREE_TYPE (decl)),
- decl));
- /* __mf_register (&VARIABLE, sizeof (VARIABLE), __MF_TYPE_STACK,
- "name") */
- register_fncall = gimple_build_call (mf_register_fndecl, 4,
- register_fncall_param,
- size,
- integer_three_node,
- variable_name);
-
-
- /* Accumulate the two calls. */
- gimple_set_location (register_fncall, location);
- gimple_set_location (unregister_fncall, location);
-
- /* Add the __mf_register call at the current appending point. */
- if (gsi_end_p (initially_stmts))
- {
- if (!mf_artificial (decl))
- warning (OPT_Wmudflap,
- "mudflap cannot track %qE in stub function",
- DECL_NAME (decl));
- }
- else
- {
- gsi_insert_before (&initially_stmts, register_fncall,
- GSI_SAME_STMT);
-
- /* Accumulate the FINALLY piece. */
- gimple_seq_add_stmt (&finally_stmts, unregister_fncall);
- }
- mf_mark (decl);
- }
-
- decl = DECL_CHAIN (decl);
- }
-
- /* Actually, (initially_stmts!=NULL) <=> (finally_stmts!=NULL) */
- if (finally_stmts != NULL)
- {
- gimple stmt = gimple_build_try (seq, finally_stmts, GIMPLE_TRY_FINALLY);
- gimple_seq new_seq = NULL;
-
- gimple_seq_add_stmt (&new_seq, stmt);
- return new_seq;
- }
- else
- return seq;
-}
-
-
-/* Process every variable mentioned in BIND_EXPRs. */
-static tree
-mx_xfn_xform_decls (gimple_stmt_iterator *gsi,
- bool *handled_operands_p ATTRIBUTE_UNUSED,
- struct walk_stmt_info *wi)
-{
- struct mf_xform_decls_data *d = (struct mf_xform_decls_data *) wi->info;
- gimple stmt = gsi_stmt (*gsi);
-
- switch (gimple_code (stmt))
- {
- case GIMPLE_BIND:
- {
- /* Process function parameters now (but only once). */
- if (d->param_decls)
- {
- gimple_bind_set_body (stmt,
- mx_register_decls (d->param_decls,
- gimple_bind_body (stmt),
- gimple_location (stmt)));
- d->param_decls = NULL_TREE;
- }
-
- gimple_bind_set_body (stmt,
- mx_register_decls (gimple_bind_vars (stmt),
- gimple_bind_body (stmt),
- gimple_location (stmt)));
- }
- break;
-
- default:
- break;
- }
-
- return NULL_TREE;
-}
-
-/* Perform the object lifetime tracking mudflap transform on the given function
- tree. The tree is mutated in place, with possibly copied subtree nodes.
-
- For every auto variable declared, if its address is ever taken
- within the function, then supply its lifetime to the mudflap
- runtime with the __mf_register and __mf_unregister calls.
-*/
-
-static void
-mf_xform_decls (gimple_seq fnbody, tree fnparams)
-{
- struct mf_xform_decls_data d;
- struct walk_stmt_info wi;
- struct pointer_set_t *pset = pointer_set_create ();
-
- d.param_decls = fnparams;
- memset (&wi, 0, sizeof (wi));
- wi.info = (void*) &d;
- wi.pset = pset;
- walk_gimple_seq (fnbody, mx_xfn_xform_decls, NULL, &wi);
- pointer_set_destroy (pset);
-}
-
-
-/* ------------------------------------------------------------------------ */
-/* Externally visible mudflap functions. */
-
-
-/* Mark and return the given tree node to prevent further mudflap
- transforms. */
-static GTY ((param_is (union tree_node))) htab_t marked_trees = NULL;
-
-tree
-mf_mark (tree t)
-{
- void **slot;
-
- if (marked_trees == NULL)
- marked_trees = htab_create_ggc (31, htab_hash_pointer, htab_eq_pointer,
- NULL);
-
- slot = htab_find_slot (marked_trees, t, INSERT);
- *slot = t;
- return t;
-}
-
-int
-mf_marked_p (tree t)
-{
- void *entry;
-
- if (marked_trees == NULL)
- return 0;
-
- entry = htab_find (marked_trees, t);
- return (entry != NULL);
-}
-
-/* Remember given node as a static of some kind: global data,
- function-scope static, or an anonymous constant. Its assembler
- label is given. */
-
-/* A list of globals whose incomplete declarations we encountered.
- Instead of emitting the __mf_register call for them here, it's
- delayed until program finish time. If they're still incomplete by
- then, warnings are emitted. */
-
-static GTY (()) vec<tree, va_gc> *deferred_static_decls;
-
-/* A list of statements for calling __mf_register() at startup time. */
-static GTY (()) tree enqueued_call_stmt_chain;
-
-static void
-mudflap_register_call (tree obj, tree object_size, tree varname)
-{
- tree arg, call_stmt;
-
- arg = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (obj)), obj);
- arg = fold_convert (ptr_type_node, arg);
-
- call_stmt = build_call_expr (mf_register_fndecl, 4,
- arg,
- fold_convert (size_type_node, object_size),
- /* __MF_TYPE_STATIC */
- build_int_cst (integer_type_node, 4),
- varname);
-
- append_to_statement_list (call_stmt, &enqueued_call_stmt_chain);
-}
-
-void
-mudflap_enqueue_decl (tree obj)
-{
- if (mf_marked_p (obj))
- return;
-
- /* We don't need to process variable decls that are internally
- generated extern. If we did, we'd end up with warnings for them
- during mudflap_finish_file (). That would confuse the user,
- since the text would refer to variables that don't show up in the
- user's source code. */
- if (DECL_P (obj) && DECL_EXTERNAL (obj) && mf_artificial (obj))
- return;
-
- vec_safe_push (deferred_static_decls, obj);
-}
-
-
-void
-mudflap_enqueue_constant (tree obj)
-{
- tree object_size, varname;
-
- if (mf_marked_p (obj))
- return;
-
- if (TREE_CODE (obj) == STRING_CST)
- object_size = size_int (TREE_STRING_LENGTH (obj));
- else
- object_size = size_in_bytes (TREE_TYPE (obj));
-
- if (TREE_CODE (obj) == STRING_CST)
- varname = mf_build_string ("string literal");
- else
- varname = mf_build_string ("constant");
-
- mudflap_register_call (obj, object_size, varname);
-}
-
-
-/* Emit any file-wide instrumentation. */
-void
-mudflap_finish_file (void)
-{
- tree ctor_statements = NULL_TREE;
-
- /* No need to continue when there were errors. */
- if (seen_error ())
- return;
-
- /* Insert a call to __mf_init. */
- {
- tree call2_stmt = build_call_expr (mf_init_fndecl, 0);
- append_to_statement_list (call2_stmt, &ctor_statements);
- }
-
- /* If appropriate, call __mf_set_options to pass along read-ignore mode. */
- if (flag_mudflap_ignore_reads)
- {
- tree arg = mf_build_string ("-ignore-reads");
- tree call_stmt = build_call_expr (mf_set_options_fndecl, 1, arg);
- append_to_statement_list (call_stmt, &ctor_statements);
- }
-
- /* Process all enqueued object decls. */
- if (deferred_static_decls)
- {
- size_t i;
- tree obj;
- FOR_EACH_VEC_ELT (*deferred_static_decls, i, obj)
- {
- gcc_assert (DECL_P (obj));
-
- if (mf_marked_p (obj))
- continue;
-
- /* Omit registration for static unaddressed objects. NB:
- Perform registration for non-static objects regardless of
- TREE_USED or TREE_ADDRESSABLE, because they may be used
- from other compilation units. */
- if (! TREE_PUBLIC (obj) && ! TREE_ADDRESSABLE (obj))
- continue;
-
- /* If we're neither emitting nor referencing the symbol,
- don't register it. We have to register external symbols
- if they happen to be in other files not compiled with
- mudflap (say system libraries), and we must not register
- internal symbols that we don't emit or they'll become
- dangling references or force symbols to be emitted that
- didn't have to. */
- if (!symtab_get_node (obj))
- continue;
-
- if (! COMPLETE_TYPE_P (TREE_TYPE (obj)))
- {
- warning (OPT_Wmudflap,
- "mudflap cannot track unknown size extern %qE",
- DECL_NAME (obj));
- continue;
- }
-
- mudflap_register_call (obj,
- size_in_bytes (TREE_TYPE (obj)),
- mf_varname_tree (obj));
- }
-
- deferred_static_decls->truncate (0);
- }
-
- /* Append all the enqueued registration calls. */
- if (enqueued_call_stmt_chain)
- {
- append_to_statement_list (enqueued_call_stmt_chain, &ctor_statements);
- enqueued_call_stmt_chain = NULL_TREE;
- }
-
- cgraph_build_static_cdtor ('I', ctor_statements,
- MAX_RESERVED_INIT_PRIORITY-1);
-}
-
-
-static bool
-gate_mudflap (void)
-{
- return flag_mudflap != 0;
-}
-
-namespace {
-
-const pass_data pass_data_mudflap_1 =
-{
- GIMPLE_PASS, /* type */
- "mudflap1", /* name */
- OPTGROUP_NONE, /* optinfo_flags */
- true, /* has_gate */
- true, /* has_execute */
- TV_NONE, /* tv_id */
- PROP_gimple_any, /* properties_required */
- 0, /* properties_provided */
- 0, /* properties_destroyed */
- 0, /* todo_flags_start */
- 0, /* todo_flags_finish */
-};
-
-class pass_mudflap_1 : public gimple_opt_pass
-{
-public:
- pass_mudflap_1(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_mudflap_1, ctxt)
- {}
-
- /* opt_pass methods: */
- bool gate () { return gate_mudflap (); }
- unsigned int execute () { return execute_mudflap_function_decls (); }
-
-}; // class pass_mudflap_1
-
-} // anon namespace
-
-gimple_opt_pass *
-make_pass_mudflap_1 (gcc::context *ctxt)
-{
- return new pass_mudflap_1 (ctxt);
-}
-
-namespace {
-
-const pass_data pass_data_mudflap_2 =
-{
- GIMPLE_PASS, /* type */
- "mudflap2", /* name */
- OPTGROUP_NONE, /* optinfo_flags */
- true, /* has_gate */
- true, /* has_execute */
- TV_NONE, /* tv_id */
- ( PROP_ssa | PROP_cfg | PROP_gimple_leh ), /* properties_required */
- 0, /* properties_provided */
- 0, /* properties_destroyed */
- 0, /* todo_flags_start */
- ( TODO_verify_flow | TODO_verify_stmts
- | TODO_update_ssa ), /* todo_flags_finish */
-};
-
-class pass_mudflap_2 : public gimple_opt_pass
-{
-public:
- pass_mudflap_2(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_mudflap_2, ctxt)
- {}
-
- /* opt_pass methods: */
- bool gate () { return gate_mudflap (); }
- unsigned int execute () { return execute_mudflap_function_ops (); }
-
-}; // class pass_mudflap_2
-
-} // anon namespace
-
-gimple_opt_pass *
-make_pass_mudflap_2 (gcc::context *ctxt)
-{
- return new pass_mudflap_2 (ctxt);
-}
-
-#include "gt-tree-mudflap.h"
diff --git a/gcc/tree-mudflap.h b/gcc/tree-mudflap.h
deleted file mode 100644
index 96f38c40c16..00000000000
--- a/gcc/tree-mudflap.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/* Mudflap: narrow-pointer bounds-checking by tree rewriting.
- Copyright (C) 2001-2013 Free Software Foundation, Inc.
- Contributed by Frank Ch. Eigler <fche@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 TREE_MUDFLAP_H
-#define TREE_MUDFLAP_H
-
-/* Instrumentation. */
-extern void mudflap_init (void);
-extern void mudflap_enqueue_decl (tree);
-extern void mudflap_enqueue_constant (tree);
-extern void mudflap_finish_file (void);
-
-/* Tree node marking. */
-extern int mf_marked_p (tree);
-extern tree mf_mark (tree);
-
-#endif /* TREE_MUDFLAP_H */
diff --git a/gcc/tree-nested.c b/gcc/tree-nested.c
index c4f9b808af5..dc63ef6902e 100644
--- a/gcc/tree-nested.c
+++ b/gcc/tree-nested.c
@@ -28,11 +28,13 @@
#include "tree-inline.h"
#include "gimple.h"
#include "tree-iterator.h"
-#include "tree-ssa.h"
+#include "bitmap.h"
#include "cgraph.h"
+#include "tree-cfg.h"
#include "expr.h" /* FIXME: For STACK_SAVEAREA_MODE and SAVE_NONLOCAL. */
#include "langhooks.h"
#include "pointer-set.h"
+#include "gimple-low.h"
/* The object of this pass is to lower the representation of a set of nested
@@ -699,11 +701,11 @@ check_for_nested_with_variably_modified (tree fndecl, tree orig_fndecl)
for (cgn = cgn->nested; cgn ; cgn = cgn->next_nested)
{
- for (arg = DECL_ARGUMENTS (cgn->symbol.decl); arg; arg = DECL_CHAIN (arg))
+ for (arg = DECL_ARGUMENTS (cgn->decl); arg; arg = DECL_CHAIN (arg))
if (variably_modified_type_p (TREE_TYPE (arg), orig_fndecl))
return true;
- if (check_for_nested_with_variably_modified (cgn->symbol.decl,
+ if (check_for_nested_with_variably_modified (cgn->decl,
orig_fndecl))
return true;
}
@@ -722,7 +724,7 @@ create_nesting_tree (struct cgraph_node *cgn)
info->var_map = pointer_map_create ();
info->mem_refs = pointer_set_create ();
info->suppress_expansion = BITMAP_ALLOC (&nesting_info_bitmap_obstack);
- info->context = cgn->symbol.decl;
+ info->context = cgn->decl;
for (cgn = cgn->nested; cgn ; cgn = cgn->next_nested)
{
@@ -1291,8 +1293,25 @@ convert_nonlocal_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
info->suppress_expansion = save_suppress;
break;
+ case GIMPLE_OMP_TARGET:
+ save_suppress = info->suppress_expansion;
+ convert_nonlocal_omp_clauses (gimple_omp_target_clauses_ptr (stmt), wi);
+ walk_body (convert_nonlocal_reference_stmt, convert_nonlocal_reference_op,
+ info, gimple_omp_body_ptr (stmt));
+ info->suppress_expansion = save_suppress;
+ break;
+
+ case GIMPLE_OMP_TEAMS:
+ save_suppress = info->suppress_expansion;
+ convert_nonlocal_omp_clauses (gimple_omp_teams_clauses_ptr (stmt), wi);
+ walk_body (convert_nonlocal_reference_stmt, convert_nonlocal_reference_op,
+ info, gimple_omp_body_ptr (stmt));
+ info->suppress_expansion = save_suppress;
+ break;
+
case GIMPLE_OMP_SECTION:
case GIMPLE_OMP_MASTER:
+ case GIMPLE_OMP_TASKGROUP:
case GIMPLE_OMP_ORDERED:
walk_body (convert_nonlocal_reference_stmt, convert_nonlocal_reference_op,
info, gimple_omp_body_ptr (stmt));
@@ -1714,8 +1733,25 @@ convert_local_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
info->suppress_expansion = save_suppress;
break;
+ case GIMPLE_OMP_TARGET:
+ save_suppress = info->suppress_expansion;
+ convert_local_omp_clauses (gimple_omp_target_clauses_ptr (stmt), wi);
+ walk_body (convert_local_reference_stmt, convert_local_reference_op,
+ info, gimple_omp_body_ptr (stmt));
+ info->suppress_expansion = save_suppress;
+ break;
+
+ case GIMPLE_OMP_TEAMS:
+ save_suppress = info->suppress_expansion;
+ convert_local_omp_clauses (gimple_omp_teams_clauses_ptr (stmt), wi);
+ walk_body (convert_local_reference_stmt, convert_local_reference_op,
+ info, gimple_omp_body_ptr (stmt));
+ info->suppress_expansion = save_suppress;
+ break;
+
case GIMPLE_OMP_SECTION:
case GIMPLE_OMP_MASTER:
+ case GIMPLE_OMP_TASKGROUP:
case GIMPLE_OMP_ORDERED:
walk_body (convert_local_reference_stmt, convert_local_reference_op,
info, gimple_omp_body_ptr (stmt));
@@ -2071,7 +2107,10 @@ convert_gimple_call (gimple_stmt_iterator *gsi, bool *handled_ops_p,
case GIMPLE_OMP_SECTIONS:
case GIMPLE_OMP_SECTION:
case GIMPLE_OMP_SINGLE:
+ case GIMPLE_OMP_TARGET:
+ case GIMPLE_OMP_TEAMS:
case GIMPLE_OMP_MASTER:
+ case GIMPLE_OMP_TASKGROUP:
case GIMPLE_OMP_ORDERED:
case GIMPLE_OMP_CRITICAL:
walk_body (convert_gimple_call, NULL, info, gimple_omp_body_ptr (stmt));
@@ -2304,7 +2343,7 @@ remap_vla_decls (tree block, struct nesting_info *root)
static bool
fold_mem_refs (const void *e, void *data ATTRIBUTE_UNUSED)
{
- tree *ref_p = CONST_CAST2(tree *, const tree *, (const tree *)e);
+ tree *ref_p = CONST_CAST2 (tree *, const tree *, (const tree *)e);
*ref_p = fold (*ref_p);
return true;
}
@@ -2591,8 +2630,8 @@ static void
gimplify_all_functions (struct cgraph_node *root)
{
struct cgraph_node *iter;
- if (!gimple_body (root->symbol.decl))
- gimplify_function_tree (root->symbol.decl);
+ if (!gimple_body (root->decl))
+ gimplify_function_tree (root->decl);
for (iter = root->nested; iter; iter = iter->next_nested)
gimplify_all_functions (iter);
}
diff --git a/gcc/tree-nomudflap.c b/gcc/tree-nomudflap.c
deleted file mode 100644
index 6659f05f5b1..00000000000
--- a/gcc/tree-nomudflap.c
+++ /dev/null
@@ -1,169 +0,0 @@
-/* Mudflap: narrow-pointer bounds-checking by tree rewriting.
- Copyright (C) 2001-2013 Free Software Foundation, Inc.
- Contributed by Frank Ch. Eigler <fche@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 "tm.h"
-#include "tree.h"
-#include "tree-inline.h"
-#include "gimple.h"
-#include "hashtab.h"
-#include "langhooks.h"
-#include "tree-mudflap.h"
-#include "tree-pass.h"
-#include "ggc.h"
-#include "diagnostic-core.h"
-
-
-
-/* This file contains placeholder functions, to be used only for
- language processors that cannot handle tree-mudflap.c directly.
- (e.g. Fortran). */
-
-static void
-nogo (void)
-{
- sorry ("mudflap: this language is not supported");
-}
-
-void
-mudflap_enqueue_decl (tree obj ATTRIBUTE_UNUSED)
-{
- nogo ();
-}
-
-void
-mudflap_enqueue_constant (tree obj ATTRIBUTE_UNUSED)
-{
- nogo ();
-}
-
-void
-mudflap_finish_file (void)
-{
- nogo ();
-}
-
-int
-mf_marked_p (tree t ATTRIBUTE_UNUSED)
-{
- nogo ();
- return 0;
-}
-
-tree
-mf_mark (tree t ATTRIBUTE_UNUSED)
-{
- nogo ();
- return NULL;
-}
-
-/* The pass structures must exist, but need not do anything. */
-
-static bool
-gate_mudflap (void)
-{
- return flag_mudflap != 0;
-}
-
-namespace {
-
-const pass_data pass_data_mudflap_1 =
-{
- GIMPLE_PASS, /* type */
- "mudflap1", /* name */
- OPTGROUP_NONE, /* optinfo_flags */
- true, /* has_gate */
- false, /* has_execute */
- TV_NONE, /* tv_id */
- 0, /* properties_required */
- 0, /* properties_provided */
- 0, /* properties_destroyed */
- 0, /* todo_flags_start */
- 0, /* todo_flags_finish */
-};
-
-class pass_mudflap_1 : public gimple_opt_pass
-{
-public:
- pass_mudflap_1(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_mudflap_1, ctxt)
- {}
-
- /* opt_pass methods: */
- bool gate () { return gate_mudflap (); }
-
-}; // class pass_mudflap_1
-
-} // anon namespace
-
-gimple_opt_pass *
-make_pass_mudflap_1 (gcc::context *ctxt)
-{
- return new pass_mudflap_1 (ctxt);
-}
-
-namespace {
-
-const pass_data pass_data_mudflap_2 =
-{
- GIMPLE_PASS, /* type */
- "mudflap2", /* name */
- OPTGROUP_NONE, /* optinfo_flags */
- true, /* has_gate */
- false, /* has_execute */
- TV_NONE, /* tv_id */
- 0, /* properties_required */
- 0, /* properties_provided */
- 0, /* properties_destroyed */
- 0, /* todo_flags_start */
- 0, /* todo_flags_finish */
-};
-
-class pass_mudflap_2 : public gimple_opt_pass
-{
-public:
- pass_mudflap_2(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_mudflap_2, ctxt)
- {}
-
- /* opt_pass methods: */
- bool gate () { return gate_mudflap (); }
-
-}; // class pass_mudflap_2
-
-} // anon namespace
-
-gimple_opt_pass *
-make_pass_mudflap_2 (gcc::context *ctxt)
-{
- return new pass_mudflap_2 (ctxt);
-}
-
-/* Instead of:
-#include "gt-tree-mudflap.h"
-We prepare a little dummy struct here.
-*/
-
-EXPORTED_CONST struct ggc_root_tab gt_ggc_r_gt_tree_mudflap_h[] = {
- LAST_GGC_ROOT_TAB
-};
diff --git a/gcc/tree-nrv.c b/gcc/tree-nrv.c
index 1961a297429..1425d195252 100644
--- a/gcc/tree-nrv.c
+++ b/gcc/tree-nrv.c
@@ -25,7 +25,9 @@ along with GCC; see the file COPYING3. If not see
#include "function.h"
#include "basic-block.h"
#include "tree-pretty-print.h"
-#include "tree-ssa.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-ssanames.h"
#include "tree-pass.h"
#include "langhooks.h"
#include "flags.h" /* For "optimize" in gate_pass_return_slot.
@@ -289,8 +291,8 @@ const pass_data pass_data_nrv =
class pass_nrv : public gimple_opt_pass
{
public:
- pass_nrv(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_nrv, ctxt)
+ pass_nrv (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_nrv, ctxt)
{}
/* opt_pass methods: */
@@ -393,8 +395,8 @@ const pass_data pass_data_return_slot =
class pass_return_slot : public gimple_opt_pass
{
public:
- pass_return_slot(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_return_slot, ctxt)
+ pass_return_slot (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_return_slot, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/tree-object-size.c b/gcc/tree-object-size.c
index 44da78eeddc..576dcb786ed 100644
--- a/gcc/tree-object-size.c
+++ b/gcc/tree-object-size.c
@@ -25,7 +25,10 @@ along with GCC; see the file COPYING3. If not see
#include "tree.h"
#include "diagnostic-core.h"
#include "gimple-pretty-print.h"
-#include "tree-ssa.h"
+#include "bitmap.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-ssanames.h"
#include "tree-pass.h"
#include "tree-ssa-propagate.h"
@@ -392,7 +395,8 @@ alloc_object_size (const_gimple call, int object_size_type)
if (!callee)
return unknown[object_size_type];
- alloc_size = lookup_attribute ("alloc_size", TYPE_ATTRIBUTES (TREE_TYPE(callee)));
+ alloc_size = lookup_attribute ("alloc_size",
+ TYPE_ATTRIBUTES (TREE_TYPE (callee)));
if (alloc_size && TREE_VALUE (alloc_size))
{
tree p = TREE_VALUE (alloc_size);
@@ -1177,7 +1181,7 @@ init_object_sizes (void)
/* Destroy data structures after the object size computation. */
-void
+static void
fini_object_sizes (void)
{
int object_size_type;
@@ -1282,12 +1286,12 @@ const pass_data pass_data_object_sizes =
class pass_object_sizes : public gimple_opt_pass
{
public:
- pass_object_sizes(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_object_sizes, ctxt)
+ pass_object_sizes (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_object_sizes, ctxt)
{}
/* opt_pass methods: */
- opt_pass * clone () { return new pass_object_sizes (ctxt_); }
+ opt_pass * clone () { return new pass_object_sizes (m_ctxt); }
unsigned int execute () { return compute_object_sizes (); }
}; // class pass_object_sizes
diff --git a/gcc/tree-optimize.c b/gcc/tree-optimize.c
deleted file mode 100644
index 0c278d0292c..00000000000
--- a/gcc/tree-optimize.c
+++ /dev/null
@@ -1,269 +0,0 @@
-/* Top-level control of tree optimizations.
- Copyright (C) 2001-2013 Free Software Foundation, Inc.
- Contributed by Diego Novillo <dnovillo@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 "tm.h"
-#include "tree.h"
-#include "tm_p.h"
-#include "basic-block.h"
-#include "flags.h"
-#include "tree-ssa.h"
-#include "function.h"
-#include "langhooks.h"
-#include "diagnostic-core.h"
-#include "toplev.h"
-#include "flags.h"
-#include "cgraph.h"
-#include "tree-inline.h"
-#include "tree-pass.h"
-#include "ggc.h"
-#include "cgraph.h"
-#include "cfgloop.h"
-#include "except.h"
-#include "plugin.h"
-
-
-/* Pass: cleanup the CFG just before expanding trees to RTL.
- This is just a round of label cleanups and case node grouping
- because after the tree optimizers have run such cleanups may
- be necessary. */
-
-static unsigned int
-execute_cleanup_cfg_post_optimizing (void)
-{
- unsigned int todo = 0;
- if (cleanup_tree_cfg ())
- todo |= TODO_update_ssa;
- maybe_remove_unreachable_handlers ();
- cleanup_dead_labels ();
- group_case_labels ();
- if ((flag_compare_debug_opt || flag_compare_debug)
- && flag_dump_final_insns)
- {
- FILE *final_output = fopen (flag_dump_final_insns, "a");
-
- if (!final_output)
- {
- error ("could not open final insn dump file %qs: %m",
- flag_dump_final_insns);
- flag_dump_final_insns = NULL;
- }
- else
- {
- int save_unnumbered = flag_dump_unnumbered;
- int save_noaddr = flag_dump_noaddr;
-
- flag_dump_noaddr = flag_dump_unnumbered = 1;
- fprintf (final_output, "\n");
- dump_enumerated_decls (final_output, dump_flags | TDF_NOUID);
- flag_dump_noaddr = save_noaddr;
- flag_dump_unnumbered = save_unnumbered;
- if (fclose (final_output))
- {
- error ("could not close final insn dump file %qs: %m",
- flag_dump_final_insns);
- flag_dump_final_insns = NULL;
- }
- }
- }
- return todo;
-}
-
-namespace {
-
-const pass_data pass_data_cleanup_cfg_post_optimizing =
-{
- GIMPLE_PASS, /* type */
- "optimized", /* name */
- OPTGROUP_NONE, /* optinfo_flags */
- false, /* has_gate */
- true, /* has_execute */
- TV_TREE_CLEANUP_CFG, /* tv_id */
- PROP_cfg, /* properties_required */
- 0, /* properties_provided */
- 0, /* properties_destroyed */
- 0, /* todo_flags_start */
- TODO_remove_unused_locals, /* todo_flags_finish */
-};
-
-class pass_cleanup_cfg_post_optimizing : public gimple_opt_pass
-{
-public:
- pass_cleanup_cfg_post_optimizing(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_cleanup_cfg_post_optimizing, ctxt)
- {}
-
- /* opt_pass methods: */
- unsigned int execute () {
- return execute_cleanup_cfg_post_optimizing ();
- }
-
-}; // class pass_cleanup_cfg_post_optimizing
-
-} // anon namespace
-
-gimple_opt_pass *
-make_pass_cleanup_cfg_post_optimizing (gcc::context *ctxt)
-{
- return new pass_cleanup_cfg_post_optimizing (ctxt);
-}
-
-/* IPA passes, compilation of earlier functions or inlining
- might have changed some properties, such as marked functions nothrow,
- pure, const or noreturn.
- Remove redundant edges and basic blocks, and create new ones if necessary.
-
- This pass can't be executed as stand alone pass from pass manager, because
- in between inlining and this fixup the verify_flow_info would fail. */
-
-unsigned int
-execute_fixup_cfg (void)
-{
- basic_block bb;
- gimple_stmt_iterator gsi;
- int todo = gimple_in_ssa_p (cfun) ? TODO_verify_ssa : 0;
- gcov_type count_scale;
- edge e;
- edge_iterator ei;
-
- count_scale
- = GCOV_COMPUTE_SCALE (cgraph_get_node (current_function_decl)->count,
- ENTRY_BLOCK_PTR->count);
-
- ENTRY_BLOCK_PTR->count = cgraph_get_node (current_function_decl)->count;
- EXIT_BLOCK_PTR->count = apply_scale (EXIT_BLOCK_PTR->count,
- count_scale);
-
- FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs)
- e->count = apply_scale (e->count, count_scale);
-
- FOR_EACH_BB (bb)
- {
- bb->count = apply_scale (bb->count, count_scale);
- for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
- {
- gimple stmt = gsi_stmt (gsi);
- tree decl = is_gimple_call (stmt)
- ? gimple_call_fndecl (stmt)
- : NULL;
- if (decl)
- {
- int flags = gimple_call_flags (stmt);
- if (flags & (ECF_CONST | ECF_PURE | ECF_LOOPING_CONST_OR_PURE))
- {
- if (gimple_purge_dead_abnormal_call_edges (bb))
- todo |= TODO_cleanup_cfg;
-
- if (gimple_in_ssa_p (cfun))
- {
- todo |= TODO_update_ssa | TODO_cleanup_cfg;
- update_stmt (stmt);
- }
- }
-
- if (flags & ECF_NORETURN
- && fixup_noreturn_call (stmt))
- todo |= TODO_cleanup_cfg;
- }
-
- if (maybe_clean_eh_stmt (stmt)
- && gimple_purge_dead_eh_edges (bb))
- todo |= TODO_cleanup_cfg;
- }
-
- FOR_EACH_EDGE (e, ei, bb->succs)
- e->count = apply_scale (e->count, count_scale);
-
- /* If we have a basic block with no successors that does not
- end with a control statement or a noreturn call end it with
- a call to __builtin_unreachable. This situation can occur
- when inlining a noreturn call that does in fact return. */
- if (EDGE_COUNT (bb->succs) == 0)
- {
- gimple stmt = last_stmt (bb);
- if (!stmt
- || (!is_ctrl_stmt (stmt)
- && (!is_gimple_call (stmt)
- || (gimple_call_flags (stmt) & ECF_NORETURN) == 0)))
- {
- stmt = gimple_build_call
- (builtin_decl_implicit (BUILT_IN_UNREACHABLE), 0);
- gimple_stmt_iterator gsi = gsi_last_bb (bb);
- gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
- }
- }
- }
- if (count_scale != REG_BR_PROB_BASE)
- compute_function_frequency ();
-
- /* We just processed all calls. */
- if (cfun->gimple_df)
- vec_free (MODIFIED_NORETURN_CALLS (cfun));
-
- /* Dump a textual representation of the flowgraph. */
- if (dump_file)
- gimple_dump_cfg (dump_file, dump_flags);
-
- if (current_loops
- && (todo & TODO_cleanup_cfg))
- loops_state_set (LOOPS_NEED_FIXUP);
-
- return todo;
-}
-
-namespace {
-
-const pass_data pass_data_fixup_cfg =
-{
- GIMPLE_PASS, /* type */
- "*free_cfg_annotations", /* name */
- OPTGROUP_NONE, /* optinfo_flags */
- false, /* has_gate */
- true, /* has_execute */
- TV_NONE, /* tv_id */
- PROP_cfg, /* properties_required */
- 0, /* properties_provided */
- 0, /* properties_destroyed */
- 0, /* todo_flags_start */
- 0, /* todo_flags_finish */
-};
-
-class pass_fixup_cfg : public gimple_opt_pass
-{
-public:
- pass_fixup_cfg(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_fixup_cfg, ctxt)
- {}
-
- /* opt_pass methods: */
- opt_pass * clone () { return new pass_fixup_cfg (ctxt_); }
- unsigned int execute () { return execute_fixup_cfg (); }
-
-}; // class pass_fixup_cfg
-
-} // anon namespace
-
-gimple_opt_pass *
-make_pass_fixup_cfg (gcc::context *ctxt)
-{
- return new pass_fixup_cfg (ctxt);
-}
diff --git a/gcc/tree-outof-ssa.c b/gcc/tree-outof-ssa.c
index 5ed145db024..4dc3f9e4a8d 100644
--- a/gcc/tree-outof-ssa.c
+++ b/gcc/tree-outof-ssa.c
@@ -27,15 +27,79 @@ along with GCC; see the file COPYING3. If not see
#include "basic-block.h"
#include "gimple-pretty-print.h"
#include "bitmap.h"
-#include "tree-ssa.h"
+#include "sbitmap.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-cfg.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
#include "dumpfile.h"
#include "diagnostic-core.h"
-#include "ssaexpand.h"
+#include "tree-ssa-live.h"
+#include "tree-ssa-ter.h"
+#include "tree-ssa-coalesce.h"
+#include "tree-outof-ssa.h"
/* FIXME: A lot of code here deals with expanding to RTL. All that code
should be in cfgexpand.c. */
#include "expr.h"
+/* Return TRUE if expression STMT is suitable for replacement. */
+
+bool
+ssa_is_replaceable_p (gimple stmt)
+{
+ use_operand_p use_p;
+ tree def;
+ gimple use_stmt;
+
+ /* Only consider modify stmts. */
+ if (!is_gimple_assign (stmt))
+ return false;
+
+ /* If the statement may throw an exception, it cannot be replaced. */
+ if (stmt_could_throw_p (stmt))
+ return false;
+
+ /* Punt if there is more than 1 def. */
+ def = SINGLE_SSA_TREE_OPERAND (stmt, SSA_OP_DEF);
+ if (!def)
+ return false;
+
+ /* Only consider definitions which have a single use. */
+ if (!single_imm_use (def, &use_p, &use_stmt))
+ return false;
+
+ /* Used in this block, but at the TOP of the block, not the end. */
+ if (gimple_code (use_stmt) == GIMPLE_PHI)
+ return false;
+
+ /* There must be no VDEFs. */
+ if (gimple_vdef (stmt))
+ return false;
+
+ /* Float expressions must go through memory if float-store is on. */
+ if (flag_float_store
+ && FLOAT_TYPE_P (gimple_expr_type (stmt)))
+ return false;
+
+ /* An assignment with a register variable on the RHS is not
+ replaceable. */
+ if (gimple_assign_rhs_code (stmt) == VAR_DECL
+ && DECL_HARD_REGISTER (gimple_assign_rhs1 (stmt)))
+ return false;
+
+ /* No function calls can be replaced. */
+ if (is_gimple_call (stmt))
+ return false;
+
+ /* Leave any stmt with volatile operands alone as well. */
+ if (gimple_has_volatile_ops (stmt))
+ return false;
+
+ return true;
+}
/* Used to hold all the components required to do SSA PHI elimination.
@@ -484,6 +548,23 @@ eliminate_name (elim_graph g, int T)
elim_graph_add_node (g, T);
}
+/* Return true if this phi argument T should have a copy queued when using
+ var_map MAP. PHI nodes should contain only ssa_names and invariants. A
+ test for ssa_name is definitely simpler, but don't let invalid contents
+ slip through in the meantime. */
+
+static inline bool
+queue_phi_copy_p (var_map map, tree t)
+{
+ if (TREE_CODE (t) == SSA_NAME)
+ {
+ if (var_to_partition (map, t) == NO_PARTITION)
+ return true;
+ return false;
+ }
+ gcc_checking_assert (is_gimple_min_invariant (t));
+ return true;
+}
/* Build elimination graph G for basic block BB on incoming PHI edge
G->e. */
@@ -513,9 +594,7 @@ eliminate_build (elim_graph g)
/* If this argument is a constant, or a SSA_NAME which is being
left in SSA form, just queue a copy to be emitted on this
edge. */
- if (!phi_ssa_name_p (Ti)
- || (TREE_CODE (Ti) == SSA_NAME
- && var_to_partition (g->map, Ti) == NO_PARTITION))
+ if (queue_phi_copy_p (g->map, Ti))
{
/* Save constant copies until all other copies have been emitted
on this edge. */
diff --git a/gcc/tree-outof-ssa.h b/gcc/tree-outof-ssa.h
new file mode 100644
index 00000000000..69a329f8b2f
--- /dev/null
+++ b/gcc/tree-outof-ssa.h
@@ -0,0 +1,78 @@
+/* Routines for expanding from SSA form to RTL.
+ Copyright (C) 2009-2013 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_OUTOF_SSA_H
+#define GCC_TREE_OUTOF_SSA_H
+
+
+/* This structure (of which only a singleton SA exists) is used to
+ pass around information between the outof-SSA functions, cfgexpand
+ and expand itself. */
+struct ssaexpand
+{
+ /* The computed partitions of SSA names are stored here. */
+ var_map map;
+
+ /* For an SSA name version V bit V is set iff TER decided that
+ its definition should be forwarded. */
+ bitmap values;
+
+ /* For a partition number I partition_to_pseudo[I] contains the
+ RTL expression of the allocated space of it (either a MEM or
+ a pseudos REG). */
+ rtx *partition_to_pseudo;
+
+ /* If partition I contains an SSA name that has a default def,
+ bit I will be set in this bitmap. */
+ bitmap partition_has_default_def;
+};
+
+/* This is the singleton described above. */
+extern struct ssaexpand SA;
+
+/* Returns the RTX expression representing the storage of the outof-SSA
+ partition that the SSA name EXP is a member of. */
+static inline rtx
+get_rtx_for_ssa_name (tree exp)
+{
+ int p = partition_find (SA.map->var_partition, SSA_NAME_VERSION (exp));
+ if (SA.map->partition_to_view)
+ p = SA.map->partition_to_view[p];
+ gcc_assert (p != NO_PARTITION);
+ return SA.partition_to_pseudo[p];
+}
+
+/* If TER decided to forward the definition of SSA name EXP this function
+ returns the defining statement, otherwise NULL. */
+static inline gimple
+get_gimple_for_ssa_name (tree exp)
+{
+ int v = SSA_NAME_VERSION (exp);
+ if (SA.values && bitmap_bit_p (SA.values, v))
+ return SSA_NAME_DEF_STMT (exp);
+ return NULL;
+}
+
+extern bool ssa_is_replaceable_p (gimple stmt);
+extern void finish_out_of_ssa (struct ssaexpand *sa);
+extern unsigned int rewrite_out_of_ssa (struct ssaexpand *sa);
+extern void expand_phi_nodes (struct ssaexpand *sa);
+
+#endif /* GCC_TREE_OUTOF_SSA_H */
diff --git a/gcc/tree-parloops.c b/gcc/tree-parloops.c
index 94843cae52b..c357f1fe14c 100644
--- a/gcc/tree-parloops.c
+++ b/gcc/tree-parloops.c
@@ -22,7 +22,18 @@ along with GCC; see the file COPYING3. If not see
#include "config.h"
#include "system.h"
#include "coretypes.h"
-#include "tree-ssa.h"
+#include "tree.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-cfg.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
+#include "tree-ssa-loop-ivopts.h"
+#include "tree-ssa-loop-manip.h"
+#include "tree-ssa-loop-niter.h"
+#include "tree-ssa-loop.h"
+#include "tree-into-ssa.h"
#include "cfgloop.h"
#include "tree-data-ref.h"
#include "tree-scalar-evolution.h"
@@ -31,6 +42,8 @@ along with GCC; see the file COPYING3. If not see
#include "langhooks.h"
#include "tree-vectorizer.h"
#include "tree-hasher.h"
+#include "tree-parloops.h"
+#include "omp-low.h"
/* This pass tries to distribute iterations of loops into several threads.
The implementation is straightforward -- for each loop we test whether its
@@ -382,7 +395,6 @@ lambda_transform_legal_p (lambda_trans_matrix trans,
static bool
loop_parallel_p (struct loop *loop, struct obstack * parloop_obstack)
{
- vec<loop_p> loop_nest;
vec<ddr_p> dependence_relations;
vec<data_reference_p> datarefs;
lambda_trans_matrix trans;
@@ -399,9 +411,9 @@ loop_parallel_p (struct loop *loop, struct obstack * parloop_obstack)
/* Check for problems with dependences. If the loop can be reversed,
the iterations are independent. */
+ stack_vec<loop_p, 3> loop_nest;
datarefs.create (10);
- dependence_relations.create (10 * 10);
- loop_nest.create (3);
+ dependence_relations.create (100);
if (! compute_data_dependences_for_loop (loop, true, &loop_nest, &datarefs,
&dependence_relations))
{
@@ -427,7 +439,6 @@ loop_parallel_p (struct loop *loop, struct obstack * parloop_obstack)
" FAILED: data dependencies exist across iterations\n");
end:
- loop_nest.release ();
free_dependence_relations (dependence_relations);
free_data_refs (datarefs);
@@ -728,8 +739,7 @@ static void
eliminate_local_variables (edge entry, edge exit)
{
basic_block bb;
- vec<basic_block> body;
- body.create (3);
+ stack_vec<basic_block, 3> body;
unsigned i;
gimple_stmt_iterator gsi;
bool has_debug_stmt = false;
@@ -759,7 +769,6 @@ eliminate_local_variables (edge entry, edge exit)
eliminate_local_variables_stmt (entry, &gsi, decl_address);
decl_address.dispose ();
- body.release ();
}
/* Returns true if expression EXPR is not defined between ENTRY and
@@ -1143,7 +1152,6 @@ create_loads_for_reductions (reduction_info **slot, struct clsn_data *clsn_data)
x = load_struct;
name = PHI_RESULT (red->keep_res);
stmt = gimple_build_assign (name, x);
- SSA_NAME_DEF_STMT (name) = stmt;
gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
@@ -1173,7 +1181,6 @@ create_final_loads_for_reduction (reduction_info_table_type reduction_list,
stmt = gimple_build_assign (ld_st_data->load, t);
gsi_insert_before (&gsi, stmt, GSI_NEW_STMT);
- SSA_NAME_DEF_STMT (ld_st_data->load) = stmt;
reduction_list
.traverse <struct clsn_data *, create_loads_for_reductions> (ld_st_data);
@@ -1227,7 +1234,6 @@ create_loads_and_stores_for_name (name_to_copy_elt **slot,
load_struct = build_simple_mem_ref (clsn_data->load);
t = build3 (COMPONENT_REF, type, load_struct, elt->field, NULL_TREE);
stmt = gimple_build_assign (elt->new_name, t);
- SSA_NAME_DEF_STMT (elt->new_name) = stmt;
gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
return 1;
@@ -1284,8 +1290,7 @@ separate_decls_in_region (edge entry, edge exit,
tree type, type_name, nvar;
gimple_stmt_iterator gsi;
struct clsn_data clsn_data;
- vec<basic_block> body;
- body.create (3);
+ stack_vec<basic_block, 3> body;
basic_block bb;
basic_block entry_bb = bb1;
basic_block exit_bb = exit->dest;
@@ -1343,8 +1348,6 @@ separate_decls_in_region (edge entry, edge exit,
}
}
- body.release ();
-
if (name_copies.elements () == 0 && reduction_list.elements () == 0)
{
/* It may happen that there is nothing to copy (if there are only
@@ -1588,7 +1591,6 @@ transform_to_exit_first_loop (struct loop *loop,
false, NULL_TREE, false, GSI_SAME_STMT);
stmt = gimple_build_assign (control_name, nit_1);
gsi_insert_before (&gsi, stmt, GSI_NEW_STMT);
- SSA_NAME_DEF_STMT (control_name) = stmt;
}
/* Create the parallel constructs for LOOP as described in gen_parallel_loop.
@@ -1629,12 +1631,10 @@ create_parallel_loop (struct loop *loop, tree loop_fn, tree data,
param = make_ssa_name (DECL_ARGUMENTS (loop_fn), NULL);
stmt = gimple_build_assign (param, build_fold_addr_expr (data));
gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
- SSA_NAME_DEF_STMT (param) = stmt;
stmt = gimple_build_assign (new_data,
fold_convert (TREE_TYPE (new_data), param));
gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
- SSA_NAME_DEF_STMT (new_data) = stmt;
}
/* Emit GIMPLE_OMP_RETURN for GIMPLE_OMP_PARALLEL. */
@@ -2240,4 +2240,62 @@ parallelize_loops (void)
return changed;
}
+/* Parallelization. */
+
+static bool
+gate_tree_parallelize_loops (void)
+{
+ return flag_tree_parallelize_loops > 1;
+}
+
+static unsigned
+tree_parallelize_loops (void)
+{
+ if (number_of_loops (cfun) <= 1)
+ return 0;
+
+ if (parallelize_loops ())
+ return TODO_cleanup_cfg | TODO_rebuild_alias;
+ return 0;
+}
+
+namespace {
+
+const pass_data pass_data_parallelize_loops =
+{
+ GIMPLE_PASS, /* type */
+ "parloops", /* name */
+ OPTGROUP_LOOP, /* optinfo_flags */
+ true, /* has_gate */
+ true, /* has_execute */
+ TV_TREE_PARALLELIZE_LOOPS, /* tv_id */
+ ( PROP_cfg | PROP_ssa ), /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ TODO_verify_flow, /* todo_flags_finish */
+};
+
+class pass_parallelize_loops : public gimple_opt_pass
+{
+public:
+ pass_parallelize_loops (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_parallelize_loops, ctxt)
+ {}
+
+ /* opt_pass methods: */
+ bool gate () { return gate_tree_parallelize_loops (); }
+ unsigned int execute () { return tree_parallelize_loops (); }
+
+}; // class pass_parallelize_loops
+
+} // anon namespace
+
+gimple_opt_pass *
+make_pass_parallelize_loops (gcc::context *ctxt)
+{
+ return new pass_parallelize_loops (ctxt);
+}
+
+
#include "gt-tree-parloops.h"
diff --git a/gcc/tree-parloops.h b/gcc/tree-parloops.h
new file mode 100644
index 00000000000..35926b64a63
--- /dev/null
+++ b/gcc/tree-parloops.h
@@ -0,0 +1,26 @@
+/* Header file for loop autoparallelization.
+ Copyright (C) 2013 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_PARLOOPS_H
+#define GCC_TREE_PARLOOPS_H
+
+extern bool parallelized_function_p (tree);
+extern bool parallelize_loops (void);
+
+#endif /* GCC_TREE_PARLOOPS_H */
diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
index ea1a62f4368..9efee1e7e00 100644
--- a/gcc/tree-pass.h
+++ b/gcc/tree-pass.h
@@ -102,7 +102,7 @@ public:
virtual unsigned int execute ();
protected:
- opt_pass(const pass_data&, gcc::context *);
+ opt_pass (const pass_data&, gcc::context *);
public:
/* A list of sub-passes to run, dependent on gate predicate. */
@@ -115,15 +115,15 @@ public:
int static_pass_number;
protected:
- gcc::context *ctxt_;
+ 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)
+ gimple_opt_pass (const pass_data& data, gcc::context *ctxt)
+ : opt_pass (data, ctxt)
{
}
};
@@ -132,8 +132,8 @@ protected:
class rtl_opt_pass : public opt_pass
{
protected:
- rtl_opt_pass(const pass_data& data, gcc::context *ctxt)
- : opt_pass(data, ctxt)
+ rtl_opt_pass (const pass_data& data, gcc::context *ctxt)
+ : opt_pass (data, ctxt)
{
}
};
@@ -174,27 +174,26 @@ public:
void (*variable_transform) (struct 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) (struct 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)
+ 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) (struct 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)
{
}
};
@@ -204,8 +203,8 @@ protected:
class simple_ipa_opt_pass : public opt_pass
{
protected:
- simple_ipa_opt_pass(const pass_data& data, gcc::context *ctxt)
- : opt_pass(data, ctxt)
+ simple_ipa_opt_pass (const pass_data& data, gcc::context *ctxt)
+ : opt_pass (data, ctxt)
{
}
};
@@ -339,8 +338,6 @@ 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_mudflap_1 (gcc::context *ctxt);
-extern gimple_opt_pass *make_pass_mudflap_2 (gcc::context *ctxt);
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);
@@ -428,6 +425,7 @@ 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_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);
@@ -527,13 +525,13 @@ extern rtl_opt_pass *make_pass_if_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_regmove (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_subreg2 (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_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);
diff --git a/gcc/tree-phinodes.c b/gcc/tree-phinodes.c
index 0bd5085ba99..2cef1c4ab23 100644
--- a/gcc/tree-phinodes.c
+++ b/gcc/tree-phinodes.c
@@ -24,9 +24,13 @@ along with GCC; see the file COPYING3. If not see
#include "tree.h"
#include "ggc.h"
#include "basic-block.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
#include "tree-ssa.h"
#include "diagnostic-core.h"
-#include "gimple.h"
/* Rewriting a function into SSA form can create a huge number of PHIs
many of which may be thrown away shortly after their creation if jumps
@@ -464,4 +468,41 @@ remove_phi_nodes (basic_block bb)
set_phi_nodes (bb, NULL);
}
+/* Given PHI, return its RHS if the PHI is a degenerate, otherwise return
+ NULL. */
+
+tree
+degenerate_phi_result (gimple phi)
+{
+ tree lhs = gimple_phi_result (phi);
+ tree val = NULL;
+ size_t i;
+
+ /* Ignoring arguments which are the same as LHS, if all the remaining
+ arguments are the same, then the PHI is a degenerate and has the
+ value of that common argument. */
+ for (i = 0; i < gimple_phi_num_args (phi); i++)
+ {
+ tree arg = gimple_phi_arg_def (phi, i);
+
+ if (arg == lhs)
+ continue;
+ else if (!arg)
+ break;
+ else if (!val)
+ val = arg;
+ else if (arg == val)
+ continue;
+ /* We bring in some of operand_equal_p not only to speed things
+ up, but also to avoid crashing when dereferencing the type of
+ a released SSA name. */
+ else if (TREE_CODE (val) != TREE_CODE (arg)
+ || TREE_CODE (val) == SSA_NAME
+ || !operand_equal_p (arg, val, 0))
+ break;
+ }
+ return (i == gimple_phi_num_args (phi) ? val : NULL);
+}
+
+
#include "gt-tree-phinodes.h"
diff --git a/gcc/tree-phinodes.h b/gcc/tree-phinodes.h
new file mode 100644
index 00000000000..ae6222b336e
--- /dev/null
+++ b/gcc/tree-phinodes.h
@@ -0,0 +1,83 @@
+/* Header file for PHI node routines
+ Copyright (C) 2013 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_PHINODES_H
+#define GCC_TREE_PHINODES_H
+
+extern void phinodes_print_statistics (void);
+extern void release_phi_node (gimple);
+extern void reserve_phi_args_for_new_edge (basic_block);
+extern void add_phi_node_to_bb (gimple phi, basic_block bb);
+extern gimple create_phi_node (tree, basic_block);
+extern void add_phi_arg (gimple, tree, edge, source_location);
+extern void remove_phi_args (edge);
+extern void remove_phi_node (gimple_stmt_iterator *, bool);
+extern void remove_phi_nodes (basic_block);
+extern tree degenerate_phi_result (gimple);
+
+/* Set PHI nodes of a basic block BB to SEQ. */
+
+static inline void
+set_phi_nodes (basic_block bb, gimple_seq seq)
+{
+ gimple_stmt_iterator i;
+
+ gcc_checking_assert (!(bb->flags & BB_RTL));
+ bb->il.gimple.phi_nodes = seq;
+ if (seq)
+ for (i = gsi_start (seq); !gsi_end_p (i); gsi_next (&i))
+ gimple_set_bb (gsi_stmt (i), bb);
+}
+
+
+static inline use_operand_p
+gimple_phi_arg_imm_use_ptr (gimple gs, int i)
+{
+ return &gimple_phi_arg (gs, i)->imm_use;
+}
+
+/* Return the phi argument which contains the specified use. */
+
+static inline int
+phi_arg_index_from_use (use_operand_p use)
+{
+ struct phi_arg_d *element, *root;
+ size_t index;
+ gimple phi;
+
+ /* Since the use is the first thing in a PHI argument element, we can
+ calculate its index based on casting it to an argument, and performing
+ pointer arithmetic. */
+
+ phi = USE_STMT (use);
+
+ element = (struct phi_arg_d *)use;
+ root = gimple_phi_arg (phi, 0);
+ index = element - root;
+
+ /* Make sure the calculation doesn't have any leftover bytes. If it does,
+ then imm_use is likely not the first element in phi_arg_d. */
+ gcc_checking_assert ((((char *)element - (char *)root)
+ % sizeof (struct phi_arg_d)) == 0
+ && index < gimple_phi_capacity (phi));
+
+ return index;
+}
+
+#endif /* GCC_TREE_PHINODES_H */
diff --git a/gcc/tree-predcom.c b/gcc/tree-predcom.c
index 2f21bb7404a..6084cf62ef6 100644
--- a/gcc/tree-predcom.c
+++ b/gcc/tree-predcom.c
@@ -191,6 +191,17 @@ along with GCC; see the file COPYING3. If not see
#include "tree.h"
#include "tm_p.h"
#include "cfgloop.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
+#include "tree-ssa-loop-ivopts.h"
+#include "tree-ssa-loop-manip.h"
+#include "tree-ssa-loop-niter.h"
+#include "tree-ssa-loop.h"
+#include "tree-into-ssa.h"
+#include "tree-dfa.h"
#include "tree-ssa.h"
#include "ggc.h"
#include "tree-data-ref.h"
@@ -1323,90 +1334,43 @@ replace_ref_with (gimple stmt, tree new_tree, bool set, bool in_lhs)
gsi_insert_after (&bsi, new_stmt, GSI_NEW_STMT);
}
-/* Returns the reference to the address of REF in the ITER-th iteration of
- LOOP, or NULL if we fail to determine it (ITER may be negative). We
- try to preserve the original shape of the reference (not rewrite it
- as an indirect ref to the address), to make tree_could_trap_p in
- prepare_initializers_chain return false more often. */
+/* Returns a memory reference to DR in the ITER-th iteration of
+ the loop it was analyzed in. Append init stmts to STMTS. */
-static tree
-ref_at_iteration (struct loop *loop, tree ref, int iter)
+static tree
+ref_at_iteration (data_reference_p dr, int iter, gimple_seq *stmts)
{
- tree idx, *idx_p, type, val, op0 = NULL_TREE, ret;
- affine_iv iv;
- bool ok;
-
- if (handled_component_p (ref))
- {
- op0 = ref_at_iteration (loop, TREE_OPERAND (ref, 0), iter);
- if (!op0)
- return NULL_TREE;
- }
- else if (!INDIRECT_REF_P (ref)
- && TREE_CODE (ref) != MEM_REF)
- return unshare_expr (ref);
-
- if (TREE_CODE (ref) == MEM_REF)
- {
- ret = unshare_expr (ref);
- idx = TREE_OPERAND (ref, 0);
- idx_p = &TREE_OPERAND (ret, 0);
- }
- else if (TREE_CODE (ref) == COMPONENT_REF)
- {
- /* Check that the offset is loop invariant. */
- if (TREE_OPERAND (ref, 2)
- && !expr_invariant_in_loop_p (loop, TREE_OPERAND (ref, 2)))
- return NULL_TREE;
-
- return build3 (COMPONENT_REF, TREE_TYPE (ref), op0,
- unshare_expr (TREE_OPERAND (ref, 1)),
- unshare_expr (TREE_OPERAND (ref, 2)));
- }
- else if (TREE_CODE (ref) == ARRAY_REF)
- {
- /* Check that the lower bound and the step are loop invariant. */
- if (TREE_OPERAND (ref, 2)
- && !expr_invariant_in_loop_p (loop, TREE_OPERAND (ref, 2)))
- return NULL_TREE;
- if (TREE_OPERAND (ref, 3)
- && !expr_invariant_in_loop_p (loop, TREE_OPERAND (ref, 3)))
- return NULL_TREE;
-
- ret = build4 (ARRAY_REF, TREE_TYPE (ref), op0, NULL_TREE,
- unshare_expr (TREE_OPERAND (ref, 2)),
- unshare_expr (TREE_OPERAND (ref, 3)));
- idx = TREE_OPERAND (ref, 1);
- idx_p = &TREE_OPERAND (ret, 1);
- }
+ tree off = DR_OFFSET (dr);
+ tree coff = DR_INIT (dr);
+ if (iter == 0)
+ ;
+ else if (TREE_CODE (DR_STEP (dr)) == INTEGER_CST)
+ coff = size_binop (PLUS_EXPR, coff,
+ size_binop (MULT_EXPR, DR_STEP (dr), ssize_int (iter)));
else
- return NULL_TREE;
-
- ok = simple_iv (loop, loop, idx, &iv, true);
- if (!ok)
- return NULL_TREE;
- iv.base = expand_simple_operations (iv.base);
- if (integer_zerop (iv.step))
- *idx_p = unshare_expr (iv.base);
- else
- {
- type = TREE_TYPE (iv.base);
- if (POINTER_TYPE_P (type))
- {
- val = fold_build2 (MULT_EXPR, sizetype, iv.step,
- size_int (iter));
- val = fold_build_pointer_plus (iv.base, val);
- }
- else
- {
- val = fold_build2 (MULT_EXPR, type, iv.step,
- build_int_cst_type (type, iter));
- val = fold_build2 (PLUS_EXPR, type, iv.base, val);
- }
- *idx_p = unshare_expr (val);
+ off = size_binop (PLUS_EXPR, off,
+ size_binop (MULT_EXPR, DR_STEP (dr), ssize_int (iter)));
+ tree addr = fold_build_pointer_plus (DR_BASE_ADDRESS (dr), off);
+ addr = force_gimple_operand_1 (addr, stmts, is_gimple_mem_ref_addr,
+ NULL_TREE);
+ tree alias_ptr = fold_convert (reference_alias_ptr_type (DR_REF (dr)), coff);
+ /* While data-ref analysis punts on bit offsets it still handles
+ bitfield accesses at byte boundaries. Cope with that. Note that
+ we cannot simply re-apply the outer COMPONENT_REF because the
+ byte-granular portion of it is already applied via DR_INIT and
+ DR_OFFSET, so simply build a BIT_FIELD_REF knowing that the bits
+ start at offset zero. */
+ if (TREE_CODE (DR_REF (dr)) == COMPONENT_REF
+ && DECL_BIT_FIELD (TREE_OPERAND (DR_REF (dr), 1)))
+ {
+ tree field = TREE_OPERAND (DR_REF (dr), 1);
+ return build3 (BIT_FIELD_REF, TREE_TYPE (DR_REF (dr)),
+ build2 (MEM_REF, DECL_BIT_FIELD_TYPE (field),
+ addr, alias_ptr),
+ DECL_SIZE (field), bitsize_zero_node);
}
-
- return ret;
+ else
+ return fold_build2 (MEM_REF, TREE_TYPE (DR_REF (dr)), addr, alias_ptr);
}
/* Get the initialization expression for the INDEX-th temporary variable
@@ -2365,14 +2329,10 @@ prepare_initializers_chain (struct loop *loop, chain_p chain)
if (chain->inits[i] != NULL_TREE)
continue;
- init = ref_at_iteration (loop, DR_REF (dr), (int) i - n);
- if (!init)
- return false;
-
+ init = ref_at_iteration (dr, (int) i - n, &stmts);
if (!chain->all_always_accessed && tree_could_trap_p (init))
return false;
- init = force_gimple_operand (init, &stmts, false, NULL_TREE);
if (stmts)
gsi_insert_seq_on_edge_immediate (entry, stmts);
@@ -2410,7 +2370,6 @@ prepare_initializers (struct loop *loop, vec<chain_p> chains)
static bool
tree_predictive_commoning_loop (struct loop *loop)
{
- vec<loop_p> loop_nest;
vec<data_reference_p> datarefs;
vec<ddr_p> dependences;
struct component *components;
@@ -2426,15 +2385,14 @@ tree_predictive_commoning_loop (struct loop *loop)
/* Find the data references and split them into components according to their
dependence relations. */
- datarefs.create (10);
+ stack_vec<loop_p, 3> loop_nest;
dependences.create (10);
- loop_nest.create (3);
+ datarefs.create (10);
if (! compute_data_dependences_for_loop (loop, true, &loop_nest, &datarefs,
&dependences))
{
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "Cannot analyze data dependencies\n");
- loop_nest.release ();
free_data_refs (datarefs);
free_dependence_relations (dependences);
return false;
@@ -2563,3 +2521,60 @@ tree_predictive_commoning (void)
return ret;
}
+
+/* Predictive commoning Pass. */
+
+static unsigned
+run_tree_predictive_commoning (void)
+{
+ if (!current_loops)
+ return 0;
+
+ return tree_predictive_commoning ();
+}
+
+static bool
+gate_tree_predictive_commoning (void)
+{
+ return flag_predictive_commoning != 0;
+}
+
+namespace {
+
+const pass_data pass_data_predcom =
+{
+ GIMPLE_PASS, /* type */
+ "pcom", /* name */
+ OPTGROUP_LOOP, /* optinfo_flags */
+ true, /* has_gate */
+ true, /* has_execute */
+ TV_PREDCOM, /* tv_id */
+ PROP_cfg, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ TODO_update_ssa_only_virtuals, /* todo_flags_finish */
+};
+
+class pass_predcom : public gimple_opt_pass
+{
+public:
+ pass_predcom (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_predcom, ctxt)
+ {}
+
+ /* opt_pass methods: */
+ bool gate () { return gate_tree_predictive_commoning (); }
+ unsigned int execute () { return run_tree_predictive_commoning (); }
+
+}; // class pass_predcom
+
+} // anon namespace
+
+gimple_opt_pass *
+make_pass_predcom (gcc::context *ctxt)
+{
+ return new pass_predcom (ctxt);
+}
+
+
diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
index 4c0481669ef..7cd578cf996 100644
--- a/gcc/tree-pretty-print.c
+++ b/gcc/tree-pretty-print.c
@@ -25,7 +25,8 @@ along with GCC; see the file COPYING3. If not see
#include "tree.h"
#include "tree-pretty-print.h"
#include "hashtab.h"
-#include "tree-ssa.h"
+#include "gimple.h"
+#include "cgraph.h"
#include "langhooks.h"
#include "tree-iterator.h"
#include "tree-chrec.h"
@@ -46,7 +47,7 @@ static void do_niy (pretty_printer *, const_tree);
#define INDENT(SPACE) do { \
int i; for (i = 0; i<SPACE; i++) pp_space (buffer); } while (0)
-#define NIY do_niy(buffer,node)
+#define NIY do_niy (buffer, node)
static pretty_printer buffer;
static int initialized = 0;
@@ -59,7 +60,7 @@ do_niy (pretty_printer *buffer, const_tree node)
int i, len;
pp_string (buffer, "<<< Unknown tree: ");
- pp_string (buffer, tree_code_name[(int) TREE_CODE (node)]);
+ pp_string (buffer, get_tree_code_name (TREE_CODE (node)));
if (EXPR_P (node))
{
@@ -319,6 +320,9 @@ dump_omp_clause (pretty_printer *buffer, tree clause, int spc, int flags)
case OMP_CLAUSE_UNIFORM:
name = "uniform";
goto print_remap;
+ case OMP_CLAUSE__LOOPTEMP_:
+ name = "_looptemp_";
+ goto print_remap;
print_remap:
pp_string (buffer, name);
pp_left_paren (buffer);
@@ -329,24 +333,28 @@ dump_omp_clause (pretty_printer *buffer, tree clause, int spc, int flags)
case OMP_CLAUSE_REDUCTION:
pp_string (buffer, "reduction(");
- pp_string (buffer, op_symbol_code (OMP_CLAUSE_REDUCTION_CODE (clause)));
- pp_colon (buffer);
+ if (OMP_CLAUSE_REDUCTION_CODE (clause) != ERROR_MARK)
+ {
+ pp_string (buffer,
+ op_symbol_code (OMP_CLAUSE_REDUCTION_CODE (clause)));
+ pp_colon (buffer);
+ }
dump_generic_node (buffer, OMP_CLAUSE_DECL (clause),
- spc, flags, false);
+ spc, flags, false);
pp_right_paren (buffer);
break;
case OMP_CLAUSE_IF:
pp_string (buffer, "if(");
dump_generic_node (buffer, OMP_CLAUSE_IF_EXPR (clause),
- spc, flags, false);
+ spc, flags, false);
pp_right_paren (buffer);
break;
case OMP_CLAUSE_NUM_THREADS:
pp_string (buffer, "num_threads(");
dump_generic_node (buffer, OMP_CLAUSE_NUM_THREADS_EXPR (clause),
- spc, flags, false);
+ spc, flags, false);
pp_right_paren (buffer);
break;
@@ -385,30 +393,29 @@ dump_omp_clause (pretty_printer *buffer, tree clause, int spc, int flags)
pp_string (buffer, "schedule(");
switch (OMP_CLAUSE_SCHEDULE_KIND (clause))
{
- case OMP_CLAUSE_SCHEDULE_STATIC:
- pp_string (buffer, "static");
- break;
- case OMP_CLAUSE_SCHEDULE_DYNAMIC:
- pp_string (buffer, "dynamic");
- break;
- case OMP_CLAUSE_SCHEDULE_GUIDED:
- pp_string (buffer, "guided");
- break;
- case OMP_CLAUSE_SCHEDULE_RUNTIME:
- pp_string (buffer, "runtime");
- break;
- case OMP_CLAUSE_SCHEDULE_AUTO:
- pp_string (buffer, "auto");
- break;
- default:
- gcc_unreachable ();
+ case OMP_CLAUSE_SCHEDULE_STATIC:
+ pp_string (buffer, "static");
+ break;
+ case OMP_CLAUSE_SCHEDULE_DYNAMIC:
+ pp_string (buffer, "dynamic");
+ break;
+ case OMP_CLAUSE_SCHEDULE_GUIDED:
+ pp_string (buffer, "guided");
+ break;
+ case OMP_CLAUSE_SCHEDULE_RUNTIME:
+ pp_string (buffer, "runtime");
+ break;
+ case OMP_CLAUSE_SCHEDULE_AUTO:
+ pp_string (buffer, "auto");
+ break;
+ default:
+ gcc_unreachable ();
}
if (OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (clause))
{
pp_comma (buffer);
- dump_generic_node (buffer,
- OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (clause),
- spc, flags, false);
+ dump_generic_node (buffer, OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (clause),
+ spc, flags, false);
}
pp_right_paren (buffer);
break;
@@ -419,8 +426,7 @@ dump_omp_clause (pretty_printer *buffer, tree clause, int spc, int flags)
case OMP_CLAUSE_COLLAPSE:
pp_string (buffer, "collapse(");
- dump_generic_node (buffer,
- OMP_CLAUSE_COLLAPSE_EXPR (clause),
+ dump_generic_node (buffer, OMP_CLAUSE_COLLAPSE_EXPR (clause),
spc, flags, false);
pp_right_paren (buffer);
break;
@@ -428,7 +434,7 @@ dump_omp_clause (pretty_printer *buffer, tree clause, int spc, int flags)
case OMP_CLAUSE_FINAL:
pp_string (buffer, "final(");
dump_generic_node (buffer, OMP_CLAUSE_FINAL_EXPR (clause),
- spc, flags, false);
+ spc, flags, false);
pp_right_paren (buffer);
break;
@@ -440,24 +446,187 @@ dump_omp_clause (pretty_printer *buffer, tree clause, int spc, int flags)
pp_string (buffer, "linear(");
dump_generic_node (buffer, OMP_CLAUSE_DECL (clause),
spc, flags, false);
- pp_character (buffer, ':');
+ pp_colon (buffer);
dump_generic_node (buffer, OMP_CLAUSE_LINEAR_STEP (clause),
spc, flags, false);
- pp_character (buffer, ')');
+ pp_right_paren (buffer);
+ break;
+
+ case OMP_CLAUSE_ALIGNED:
+ pp_string (buffer, "aligned(");
+ dump_generic_node (buffer, OMP_CLAUSE_DECL (clause),
+ spc, flags, false);
+ if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
+ {
+ pp_colon (buffer);
+ dump_generic_node (buffer, OMP_CLAUSE_ALIGNED_ALIGNMENT (clause),
+ spc, flags, false);
+ }
+ pp_right_paren (buffer);
+ break;
+
+ case OMP_CLAUSE_DEPEND:
+ pp_string (buffer, "depend(");
+ switch (OMP_CLAUSE_DEPEND_KIND (clause))
+ {
+ case OMP_CLAUSE_DEPEND_IN:
+ pp_string (buffer, "in");
+ break;
+ case OMP_CLAUSE_DEPEND_OUT:
+ pp_string (buffer, "out");
+ break;
+ case OMP_CLAUSE_DEPEND_INOUT:
+ pp_string (buffer, "inout");
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ pp_colon (buffer);
+ dump_generic_node (buffer, OMP_CLAUSE_DECL (clause),
+ spc, flags, false);
+ pp_right_paren (buffer);
+ break;
+
+ case OMP_CLAUSE_MAP:
+ pp_string (buffer, "map(");
+ switch (OMP_CLAUSE_MAP_KIND (clause))
+ {
+ case OMP_CLAUSE_MAP_ALLOC:
+ case OMP_CLAUSE_MAP_POINTER:
+ pp_string (buffer, "alloc");
+ break;
+ case OMP_CLAUSE_MAP_TO:
+ pp_string (buffer, "to");
+ break;
+ case OMP_CLAUSE_MAP_FROM:
+ pp_string (buffer, "from");
+ break;
+ case OMP_CLAUSE_MAP_TOFROM:
+ pp_string (buffer, "tofrom");
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ pp_colon (buffer);
+ dump_generic_node (buffer, OMP_CLAUSE_DECL (clause),
+ spc, flags, false);
+ print_clause_size:
+ if (OMP_CLAUSE_SIZE (clause))
+ {
+ if (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_MAP
+ && OMP_CLAUSE_MAP_KIND (clause) == OMP_CLAUSE_MAP_POINTER)
+ pp_string (buffer, " [pointer assign, bias: ");
+ else
+ pp_string (buffer, " [len: ");
+ dump_generic_node (buffer, OMP_CLAUSE_SIZE (clause),
+ spc, flags, false);
+ pp_right_bracket (buffer);
+ }
+ pp_right_paren (buffer);
+ break;
+
+ case OMP_CLAUSE_FROM:
+ pp_string (buffer, "from(");
+ dump_generic_node (buffer, OMP_CLAUSE_DECL (clause),
+ spc, flags, false);
+ goto print_clause_size;
+
+ case OMP_CLAUSE_TO:
+ pp_string (buffer, "to(");
+ dump_generic_node (buffer, OMP_CLAUSE_DECL (clause),
+ spc, flags, false);
+ goto print_clause_size;
+
+ case OMP_CLAUSE_NUM_TEAMS:
+ pp_string (buffer, "num_teams(");
+ dump_generic_node (buffer, OMP_CLAUSE_NUM_TEAMS_EXPR (clause),
+ spc, flags, false);
+ pp_right_paren (buffer);
+ break;
+
+ case OMP_CLAUSE_THREAD_LIMIT:
+ pp_string (buffer, "thread_limit(");
+ dump_generic_node (buffer, OMP_CLAUSE_THREAD_LIMIT_EXPR (clause),
+ spc, flags, false);
+ pp_right_paren (buffer);
+ break;
+
+ case OMP_CLAUSE_DEVICE:
+ pp_string (buffer, "device(");
+ dump_generic_node (buffer, OMP_CLAUSE_DEVICE_ID (clause),
+ spc, flags, false);
+ pp_right_paren (buffer);
+ break;
+
+ case OMP_CLAUSE_DIST_SCHEDULE:
+ pp_string (buffer, "dist_schedule(static");
+ if (OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (clause))
+ {
+ pp_comma (buffer);
+ dump_generic_node (buffer,
+ OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (clause),
+ spc, flags, false);
+ }
+ pp_right_paren (buffer);
+ break;
+
+ case OMP_CLAUSE_PROC_BIND:
+ pp_string (buffer, "proc_bind(");
+ switch (OMP_CLAUSE_PROC_BIND_KIND (clause))
+ {
+ case OMP_CLAUSE_PROC_BIND_MASTER:
+ pp_string (buffer, "master");
+ break;
+ case OMP_CLAUSE_PROC_BIND_CLOSE:
+ pp_string (buffer, "close");
+ break;
+ case OMP_CLAUSE_PROC_BIND_SPREAD:
+ pp_string (buffer, "spread");
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ pp_right_paren (buffer);
break;
case OMP_CLAUSE_SAFELEN:
pp_string (buffer, "safelen(");
dump_generic_node (buffer, OMP_CLAUSE_SAFELEN_EXPR (clause),
spc, flags, false);
- pp_character (buffer, ')');
+ pp_right_paren (buffer);
+ break;
+
+ case OMP_CLAUSE_SIMDLEN:
+ pp_string (buffer, "simdlen(");
+ dump_generic_node (buffer, OMP_CLAUSE_SIMDLEN_EXPR (clause),
+ spc, flags, false);
+ pp_right_paren (buffer);
break;
case OMP_CLAUSE__SIMDUID_:
pp_string (buffer, "_simduid_(");
dump_generic_node (buffer, OMP_CLAUSE__SIMDUID__DECL (clause),
spc, flags, false);
- pp_character (buffer, ')');
+ pp_right_paren (buffer);
+ break;
+
+ case OMP_CLAUSE_INBRANCH:
+ pp_string (buffer, "inbranch");
+ break;
+ case OMP_CLAUSE_NOTINBRANCH:
+ pp_string (buffer, "notinbranch");
+ break;
+ case OMP_CLAUSE_FOR:
+ pp_string (buffer, "for");
+ break;
+ case OMP_CLAUSE_PARALLEL:
+ pp_string (buffer, "parallel");
+ break;
+ case OMP_CLAUSE_SECTIONS:
+ pp_string (buffer, "sections");
+ break;
+ case OMP_CLAUSE_TASKGROUP:
+ pp_string (buffer, "taskgroup");
break;
default:
@@ -697,6 +866,7 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
break;
case VOID_TYPE:
+ case POINTER_BOUNDS_TYPE:
case INTEGER_TYPE:
case REAL_TYPE:
case FIXED_POINT_TYPE:
@@ -708,6 +878,8 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
unsigned int quals = TYPE_QUALS (node);
enum tree_code_class tclass;
+ if (quals & TYPE_QUAL_ATOMIC)
+ pp_string (buffer, "atomic ");
if (quals & TYPE_QUAL_CONST)
pp_string (buffer, "const ");
else if (quals & TYPE_QUAL_VOLATILE)
@@ -1009,6 +1181,8 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
{
unsigned int quals = TYPE_QUALS (node);
+ if (quals & TYPE_QUAL_ATOMIC)
+ pp_string (buffer, "atomic ");
if (quals & TYPE_QUAL_CONST)
pp_string (buffer, "const ");
if (quals & TYPE_QUAL_VOLATILE)
@@ -1062,29 +1236,11 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
pp_wide_integer (buffer, TREE_INT_CST_LOW (node));
pp_string (buffer, "B"); /* pseudo-unit */
}
- else if (host_integerp (node, 0))
- pp_wide_integer (buffer, TREE_INT_CST_LOW (node));
- else if (host_integerp (node, 1))
- pp_unsigned_wide_integer (buffer, TREE_INT_CST_LOW (node));
else
- {
- tree val = node;
- unsigned HOST_WIDE_INT low = TREE_INT_CST_LOW (val);
- HOST_WIDE_INT high = TREE_INT_CST_HIGH (val);
-
- if (tree_int_cst_sgn (val) < 0)
- {
- pp_minus (buffer);
- high = ~high + !low;
- low = -low;
- }
- /* Would "%x%0*x" or "%x%*0x" get zero-padding on all
- systems? */
- sprintf (pp_buffer (buffer)->digit_buffer,
- HOST_WIDE_INT_PRINT_DOUBLE_HEX,
- (unsigned HOST_WIDE_INT) high, low);
- pp_string (buffer, pp_buffer (buffer)->digit_buffer);
- }
+ pp_double_int (buffer, tree_to_double_int (node),
+ TYPE_UNSIGNED (TREE_TYPE (node)));
+ if (TREE_OVERFLOW (node))
+ pp_string (buffer, "(OVF)");
break;
case REAL_CST:
@@ -1944,6 +2100,18 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
pp_string (buffer, " predictor.");
break;
+ case ANNOTATE_EXPR:
+ pp_string (buffer, "ANNOTATE_EXPR <");
+ switch ((enum annot_expr_kind) TREE_INT_CST_LOW (TREE_OPERAND (node, 1)))
+ {
+ case annot_expr_ivdep_kind:
+ pp_string (buffer, "ivdep, ");
+ break;
+ }
+ dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
+ pp_greater (buffer);
+ break;
+
case RETURN_EXPR:
pp_string (buffer, "return");
op0 = TREE_OPERAND (node, 0);
@@ -2072,10 +2240,10 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
spc, flags, false);
pp_underscore (buffer);
pp_decimal_int (buffer, SSA_NAME_VERSION (node));
+ if (SSA_NAME_IS_DEFAULT_DEF (node))
+ pp_string (buffer, "(D)");
if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (node))
pp_string (buffer, "(ab)");
- else if (SSA_NAME_IS_DEFAULT_DEF (node))
- pp_string (buffer, "(D)");
break;
case WITH_SIZE_EXPR:
@@ -2212,6 +2380,31 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
pp_string (buffer, "#pragma omp simd");
goto dump_omp_loop;
+ case OMP_DISTRIBUTE:
+ pp_string (buffer, "#pragma omp distribute");
+ goto dump_omp_loop;
+
+ case OMP_TEAMS:
+ pp_string (buffer, "#pragma omp teams");
+ dump_omp_clauses (buffer, OMP_TEAMS_CLAUSES (node), spc, flags);
+ goto dump_omp_body;
+
+ case OMP_TARGET_DATA:
+ pp_string (buffer, "#pragma omp target data");
+ dump_omp_clauses (buffer, OMP_TARGET_DATA_CLAUSES (node), spc, flags);
+ goto dump_omp_body;
+
+ case OMP_TARGET:
+ pp_string (buffer, "#pragma omp target");
+ dump_omp_clauses (buffer, OMP_TARGET_CLAUSES (node), spc, flags);
+ goto dump_omp_body;
+
+ case OMP_TARGET_UPDATE:
+ pp_string (buffer, "#pragma omp target update");
+ dump_omp_clauses (buffer, OMP_TARGET_UPDATE_CLAUSES (node), spc, flags);
+ is_expr = false;
+ break;
+
dump_omp_loop:
dump_omp_clauses (buffer, OMP_FOR_CLAUSES (node), spc, flags);
@@ -2228,21 +2421,27 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
dump_generic_node (buffer, OMP_FOR_PRE_BODY (node),
spc, flags, false);
}
- spc -= 2;
- for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (node)); i++)
+ if (OMP_FOR_INIT (node))
{
- spc += 2;
- newline_and_indent (buffer, spc);
- pp_string (buffer, "for (");
- dump_generic_node (buffer, TREE_VEC_ELT (OMP_FOR_INIT (node), i),
- spc, flags, false);
- pp_string (buffer, "; ");
- dump_generic_node (buffer, TREE_VEC_ELT (OMP_FOR_COND (node), i),
- spc, flags, false);
- pp_string (buffer, "; ");
- dump_generic_node (buffer, TREE_VEC_ELT (OMP_FOR_INCR (node), i),
- spc, flags, false);
- pp_right_paren (buffer);
+ spc -= 2;
+ for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (node)); i++)
+ {
+ spc += 2;
+ newline_and_indent (buffer, spc);
+ pp_string (buffer, "for (");
+ dump_generic_node (buffer,
+ TREE_VEC_ELT (OMP_FOR_INIT (node), i),
+ spc, flags, false);
+ pp_string (buffer, "; ");
+ dump_generic_node (buffer,
+ TREE_VEC_ELT (OMP_FOR_COND (node), i),
+ spc, flags, false);
+ pp_string (buffer, "; ");
+ dump_generic_node (buffer,
+ TREE_VEC_ELT (OMP_FOR_INCR (node), i),
+ spc, flags, false);
+ pp_right_paren (buffer);
+ }
}
if (OMP_FOR_BODY (node))
{
@@ -2254,7 +2453,8 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
newline_and_indent (buffer, spc + 2);
pp_right_brace (buffer);
}
- spc -= 2 * TREE_VEC_LENGTH (OMP_FOR_INIT (node)) - 2;
+ if (OMP_FOR_INIT (node))
+ spc -= 2 * TREE_VEC_LENGTH (OMP_FOR_INIT (node)) - 2;
if (OMP_FOR_PRE_BODY (node))
{
spc -= 4;
@@ -2278,6 +2478,10 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
pp_string (buffer, "#pragma omp master");
goto dump_omp_body;
+ case OMP_TASKGROUP:
+ pp_string (buffer, "#pragma omp taskgroup");
+ goto dump_omp_body;
+
case OMP_ORDERED:
pp_string (buffer, "#pragma omp ordered");
goto dump_omp_body;
@@ -2296,6 +2500,8 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
case OMP_ATOMIC:
pp_string (buffer, "#pragma omp atomic");
+ if (OMP_ATOMIC_SEQ_CST (node))
+ pp_string (buffer, " seq_cst");
newline_and_indent (buffer, spc + 2);
dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
pp_space (buffer);
@@ -2306,6 +2512,8 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
case OMP_ATOMIC_READ:
pp_string (buffer, "#pragma omp atomic read");
+ if (OMP_ATOMIC_SEQ_CST (node))
+ pp_string (buffer, " seq_cst");
newline_and_indent (buffer, spc + 2);
dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
pp_space (buffer);
@@ -2314,6 +2522,8 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
case OMP_ATOMIC_CAPTURE_OLD:
case OMP_ATOMIC_CAPTURE_NEW:
pp_string (buffer, "#pragma omp atomic capture");
+ if (OMP_ATOMIC_SEQ_CST (node))
+ pp_string (buffer, " seq_cst");
newline_and_indent (buffer, spc + 2);
dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
pp_space (buffer);
@@ -2377,7 +2587,7 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
case VEC_WIDEN_LSHIFT_HI_EXPR:
case VEC_WIDEN_LSHIFT_LO_EXPR:
pp_space (buffer);
- for (str = tree_code_name [code]; *str; str++)
+ for (str = get_tree_code_name (code); *str; str++)
pp_character (buffer, TOUPPER (*str));
pp_string (buffer, " < ");
dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
@@ -2438,6 +2648,15 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
dump_block_node (buffer, node, spc, flags);
break;
+ case CILK_SPAWN_STMT:
+ pp_string (buffer, "_Cilk_spawn ");
+ dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
+ break;
+
+ case CILK_SYNC_STMT:
+ pp_string (buffer, "_Cilk_sync");
+ break;
+
default:
NIY;
}
@@ -3184,7 +3403,7 @@ dump_function_header (FILE *dump_file, tree fdecl, int flags)
fprintf (dump_file, ", decl_uid=%d", DECL_UID (fdecl));
if (node)
{
- fprintf (dump_file, ", symbol_order=%d)%s\n\n", node->symbol.order,
+ fprintf (dump_file, ", symbol_order=%d)%s\n\n", node->order,
node->frequency == NODE_FREQUENCY_HOT
? " (hot)"
: node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED
@@ -3196,3 +3415,31 @@ dump_function_header (FILE *dump_file, tree fdecl, int flags)
else
fprintf (dump_file, ")\n\n");
}
+
+/* Dump double_int D to pretty_printer PP. UNS is true
+ if D is unsigned and false otherwise. */
+void
+pp_double_int (pretty_printer *pp, double_int d, bool uns)
+{
+ if (d.fits_shwi ())
+ pp_wide_integer (pp, d.low);
+ else if (d.fits_uhwi ())
+ pp_unsigned_wide_integer (pp, d.low);
+ else
+ {
+ unsigned HOST_WIDE_INT low = d.low;
+ HOST_WIDE_INT high = d.high;
+ if (!uns && d.is_negative ())
+ {
+ pp_minus (pp);
+ high = ~high + !low;
+ low = -low;
+ }
+ /* Would "%x%0*x" or "%x%*0x" get zero-padding on all
+ systems? */
+ sprintf (pp_buffer (pp)->digit_buffer,
+ HOST_WIDE_INT_PRINT_DOUBLE_HEX,
+ (unsigned HOST_WIDE_INT) high, low);
+ pp_string (pp, pp_buffer (pp)->digit_buffer);
+ }
+}
diff --git a/gcc/tree-pretty-print.h b/gcc/tree-pretty-print.h
index 7da8000d5b8..8754b0a2195 100644
--- a/gcc/tree-pretty-print.h
+++ b/gcc/tree-pretty-print.h
@@ -23,30 +23,32 @@ along with GCC; see the file COPYING3. If not see
#define GCC_TREE_PRETTY_PRINT_H
#include "pretty-print.h"
+#include "double-int.h"
#define pp_unsupported_tree(PP, T) \
pp_verbatim (PP, "#%qs not supported by %s#", \
- tree_code_name[(int) TREE_CODE (T)], __FUNCTION__)
+ get_tree_code_name (TREE_CODE (T)), __FUNCTION__)
#define pp_ti_abstract_origin(TI) ((tree *) (TI)->x_data)
-extern void pp_tree_identifier (pretty_printer *, tree);
-/* In tree-pretty-print.c */
-extern void print_declaration (pretty_printer *, tree, int, int);
-extern int dump_generic_node (pretty_printer *, tree, int, int, bool);
+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, int);
extern void print_generic_stmt (FILE *, tree, int);
extern void print_generic_stmt_indented (FILE *, tree, int, int);
extern void print_generic_expr (FILE *, tree, int);
-extern void print_generic_decl (FILE *, tree, int);
extern void dump_omp_clauses (pretty_printer *, tree, int, int);
+extern int dump_generic_node (pretty_printer *, tree, int, int, bool);
+extern void print_declaration (pretty_printer *, tree, int, int);
+extern int op_code_prio (enum tree_code);
+extern int op_prio (const_tree);
+extern const char *op_symbol_code (enum tree_code);
extern void print_call_name (pretty_printer *, tree, int);
-extern void debug_generic_expr (tree);
-extern void debug_generic_stmt (tree);
-extern void debug_tree_chain (tree);
extern void percent_K_format (text_info *);
+extern void pp_tree_identifier (pretty_printer *, tree);
extern void dump_function_header (FILE *, tree, int);
-/* In c-pretty-print.c */
-extern void debug_c_tree (tree);
+extern void pp_double_int (pretty_printer *pp, double_int d, bool uns);
#endif /* ! GCC_TREE_PRETTY_PRINT_H */
diff --git a/gcc/tree-profile.c b/gcc/tree-profile.c
index a2c4209646f..43d5b923e1f 100644
--- a/gcc/tree-profile.c
+++ b/gcc/tree-profile.c
@@ -34,21 +34,27 @@ along with GCC; see the file COPYING3. If not see
#include "diagnostic-core.h"
#include "coverage.h"
#include "tree.h"
-#include "tree-ssa.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "cgraph.h"
+#include "tree-cfg.h"
+#include "tree-ssanames.h"
+#include "tree-into-ssa.h"
#include "tree-pass.h"
#include "value-prof.h"
-#include "cgraph.h"
#include "profile.h"
#include "target.h"
+#include "tree-cfgcleanup.h"
static GTY(()) tree gcov_type_node;
static GTY(()) tree tree_interval_profiler_fn;
static GTY(()) tree tree_pow2_profiler_fn;
static GTY(()) tree tree_one_value_profiler_fn;
static GTY(()) tree tree_indirect_call_profiler_fn;
+static GTY(()) tree tree_time_profiler_fn;
static GTY(()) tree tree_average_profiler_fn;
static GTY(()) tree tree_ior_profiler_fn;
-
+
static GTY(()) tree ic_void_ptr_var;
static GTY(()) tree ic_gcov_type_ptr_var;
@@ -58,7 +64,8 @@ static GTY(()) tree ptr_void;
/* Add code:
__thread gcov* __gcov_indirect_call_counters; // pointer to actual counter
- __thread void* __gcov_indirect_call_callee; // actual callee address
+ __thread void* __gcov_indirect_call_callee; // actual callee address
+ __thread int __gcov_function_counter; // time profiler function counter
*/
static void
init_ic_make_global_vars (void)
@@ -140,6 +147,7 @@ gimple_init_edge_profiler (void)
tree gcov_type_ptr;
tree ic_profiler_fn_type;
tree average_profiler_fn_type;
+ tree time_profiler_fn_type;
if (!gcov_type_node)
{
@@ -217,6 +225,18 @@ gimple_init_edge_profiler (void)
= tree_cons (get_identifier ("leaf"), NULL,
DECL_ATTRIBUTES (tree_indirect_call_profiler_fn));
+ /* void (*) (gcov_type *, gcov_type, void *) */
+ time_profiler_fn_type
+ = build_function_type_list (void_type_node,
+ gcov_type_ptr, NULL_TREE);
+ tree_time_profiler_fn
+ = build_fn_decl ("__gcov_time_profiler",
+ time_profiler_fn_type);
+ TREE_NOTHROW (tree_time_profiler_fn) = 1;
+ DECL_ATTRIBUTES (tree_time_profiler_fn)
+ = tree_cons (get_identifier ("leaf"), NULL,
+ DECL_ATTRIBUTES (tree_time_profiler_fn));
+
/* void (*) (gcov_type *, gcov_type) */
average_profiler_fn_type
= build_function_type_list (void_type_node,
@@ -242,6 +262,7 @@ gimple_init_edge_profiler (void)
DECL_ASSEMBLER_NAME (tree_pow2_profiler_fn);
DECL_ASSEMBLER_NAME (tree_one_value_profiler_fn);
DECL_ASSEMBLER_NAME (tree_indirect_call_profiler_fn);
+ DECL_ASSEMBLER_NAME (tree_time_profiler_fn);
DECL_ASSEMBLER_NAME (tree_average_profiler_fn);
DECL_ASSEMBLER_NAME (tree_ior_profiler_fn);
}
@@ -450,6 +471,23 @@ gimple_gen_ic_func_profiler (void)
gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
}
+/* Output instructions as GIMPLE tree at the beginning for each function.
+ TAG is the tag of the section for counters, BASE is offset of the
+ counter position and GSI is the iterator we place the counter. */
+
+void
+gimple_gen_time_profiler (unsigned tag, unsigned base,
+ gimple_stmt_iterator &gsi)
+{
+ tree ref_ptr = tree_coverage_counter_addr (tag, base);
+ gimple call;
+
+ ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
+ true, NULL_TREE, true, GSI_SAME_STMT);
+ call = gimple_build_call (tree_time_profiler_fn, 1, ref_ptr);
+ gsi_insert_before (&gsi, call, GSI_NEW_STMT);
+}
+
/* Output instructions as GIMPLE trees for code to find the most common value
of a difference between two evaluations of an expression.
VALUE is the expression whose value is profiled. TAG is the tag of the
@@ -523,14 +561,14 @@ tree_profiling (void)
FOR_EACH_DEFINED_FUNCTION (node)
{
- if (!gimple_has_body_p (node->symbol.decl))
+ if (!gimple_has_body_p (node->decl))
continue;
/* Don't profile functions produced for builtin stuff. */
- if (DECL_SOURCE_LOCATION (node->symbol.decl) == BUILTINS_LOCATION)
+ if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION)
continue;
- push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
+ push_cfun (DECL_STRUCT_FUNCTION (node->decl));
/* Local pure-const may imply need to fixup the cfg. */
if (execute_fixup_cfg () & TODO_cleanup_cfg)
@@ -558,13 +596,13 @@ tree_profiling (void)
/* Drop pure/const flags from instrumented functions. */
FOR_EACH_DEFINED_FUNCTION (node)
{
- if (!gimple_has_body_p (node->symbol.decl)
+ if (!gimple_has_body_p (node->decl)
|| !(!node->clone_of
- || node->symbol.decl != node->clone_of->symbol.decl))
+ || node->decl != node->clone_of->decl))
continue;
/* Don't profile functions produced for builtin stuff. */
- if (DECL_SOURCE_LOCATION (node->symbol.decl) == BUILTINS_LOCATION)
+ if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION)
continue;
cgraph_set_const_flag (node, false, false);
@@ -576,16 +614,16 @@ tree_profiling (void)
{
basic_block bb;
- if (!gimple_has_body_p (node->symbol.decl)
+ if (!gimple_has_body_p (node->decl)
|| !(!node->clone_of
- || node->symbol.decl != node->clone_of->symbol.decl))
+ || node->decl != node->clone_of->decl))
continue;
/* Don't profile functions produced for builtin stuff. */
- if (DECL_SOURCE_LOCATION (node->symbol.decl) == BUILTINS_LOCATION)
+ if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION)
continue;
- push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
+ push_cfun (DECL_STRUCT_FUNCTION (node->decl));
FOR_EACH_BB (bb)
{
@@ -607,7 +645,7 @@ tree_profiling (void)
pop_cfun ();
}
- del_node_map();
+ del_node_map ();
return 0;
}
@@ -641,8 +679,8 @@ const pass_data pass_data_ipa_tree_profile =
class pass_ipa_tree_profile : public simple_ipa_opt_pass
{
public:
- pass_ipa_tree_profile(gcc::context *ctxt)
- : simple_ipa_opt_pass(pass_data_ipa_tree_profile, ctxt)
+ pass_ipa_tree_profile (gcc::context *ctxt)
+ : simple_ipa_opt_pass (pass_data_ipa_tree_profile, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/tree-scalar-evolution.c b/gcc/tree-scalar-evolution.c
index f15f91c31a4..cafc70cb54b 100644
--- a/gcc/tree-scalar-evolution.c
+++ b/gcc/tree-scalar-evolution.c
@@ -256,26 +256,37 @@ along with GCC; see the file COPYING3. If not see
#include "config.h"
#include "system.h"
#include "coretypes.h"
+#include "tree.h"
#include "hash-table.h"
#include "gimple-pretty-print.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-cfg.h"
+#include "tree-phinodes.h"
+#include "tree-ssanames.h"
+#include "tree-ssa-loop-ivopts.h"
+#include "tree-ssa-loop-manip.h"
+#include "tree-ssa-loop-niter.h"
+#include "tree-ssa-loop.h"
#include "tree-ssa.h"
#include "cfgloop.h"
#include "tree-chrec.h"
#include "tree-scalar-evolution.h"
#include "dumpfile.h"
#include "params.h"
+#include "tree-ssa-propagate.h"
static tree analyze_scalar_evolution_1 (struct loop *, tree, tree);
static tree analyze_scalar_evolution_for_address_of (struct loop *loop,
tree var);
-/* The cached information about an SSA name VAR, claiming that below
- basic block INSTANTIATED_BELOW, the value of VAR can be expressed
- as CHREC. */
+/* The cached information about an SSA name with version NAME_VERSION,
+ claiming that below basic block with index INSTANTIATED_BELOW, the
+ value of the SSA name can be expressed as CHREC. */
struct GTY(()) scev_info_str {
- basic_block instantiated_below;
- tree var;
+ unsigned int name_version;
+ int instantiated_below;
tree chrec;
};
@@ -309,9 +320,9 @@ new_scev_info_str (basic_block instantiated_below, tree var)
struct scev_info_str *res;
res = ggc_alloc_scev_info_str ();
- res->var = var;
+ res->name_version = SSA_NAME_VERSION (var);
res->chrec = chrec_not_analyzed_yet;
- res->instantiated_below = instantiated_below;
+ res->instantiated_below = instantiated_below->index;
return res;
}
@@ -319,9 +330,10 @@ new_scev_info_str (basic_block instantiated_below, tree var)
/* Computes a hash function for database element ELT. */
static inline hashval_t
-hash_scev_info (const void *elt)
+hash_scev_info (const void *elt_)
{
- return SSA_NAME_VERSION (((const struct scev_info_str *) elt)->var);
+ const struct scev_info_str *elt = (const struct scev_info_str *) elt_;
+ return elt->name_version ^ elt->instantiated_below;
}
/* Compares database elements E1 and E2. */
@@ -332,7 +344,7 @@ eq_scev_info (const void *e1, const void *e2)
const struct scev_info_str *elt1 = (const struct scev_info_str *) e1;
const struct scev_info_str *elt2 = (const struct scev_info_str *) e2;
- return (elt1->var == elt2->var
+ return (elt1->name_version == elt2->name_version
&& elt1->instantiated_below == elt2->instantiated_below);
}
@@ -355,8 +367,8 @@ find_var_scev_info (basic_block instantiated_below, tree var)
struct scev_info_str tmp;
PTR *slot;
- tmp.var = var;
- tmp.instantiated_below = instantiated_below;
+ tmp.name_version = SSA_NAME_VERSION (var);
+ tmp.instantiated_below = instantiated_below->index;
slot = htab_find_slot (scalar_evolution_info, &tmp, INSERT);
if (!*slot)
@@ -2065,18 +2077,12 @@ analyze_scalar_evolution_in_loop (struct loop *wrto_loop, struct loop *use_loop,
instantiating a CHREC or resolving mixers. For this use
instantiated_below is always the same. */
-struct instantiate_cache_entry
-{
- tree name;
- tree chrec;
-};
-
struct instantiate_cache_type
{
- pointer_map<unsigned> *map;
- vec<instantiate_cache_entry> entries;
+ htab_t map;
+ vec<scev_info_str> entries;
- instantiate_cache_type () : map (NULL), entries(vNULL) {}
+ instantiate_cache_type () : map (NULL), entries (vNULL) {}
~instantiate_cache_type ();
tree get (unsigned slot) { return entries[slot].chrec; }
void set (unsigned slot, tree chrec) { entries[slot].chrec = chrec; }
@@ -2086,40 +2092,60 @@ instantiate_cache_type::~instantiate_cache_type ()
{
if (map != NULL)
{
- delete map;
+ htab_delete (map);
entries.release ();
}
}
+/* Cache to avoid infinite recursion when instantiating an SSA name.
+ Live during the outermost instantiate_scev or resolve_mixers call. */
+static instantiate_cache_type *global_cache;
+
+/* Computes a hash function for database element ELT. */
+
+static inline hashval_t
+hash_idx_scev_info (const void *elt_)
+{
+ unsigned idx = ((size_t) elt_) - 2;
+ return hash_scev_info (&global_cache->entries[idx]);
+}
+
+/* Compares database elements E1 and E2. */
+
+static inline int
+eq_idx_scev_info (const void *e1, const void *e2)
+{
+ unsigned idx1 = ((size_t) e1) - 2;
+ return eq_scev_info (&global_cache->entries[idx1], e2);
+}
+
/* Returns from CACHE the slot number of the cached chrec for NAME. */
static unsigned
-get_instantiated_value_entry (instantiate_cache_type &cache, tree name)
+get_instantiated_value_entry (instantiate_cache_type &cache,
+ tree name, basic_block instantiate_below)
{
if (!cache.map)
{
- cache.map = new pointer_map<unsigned>;
+ cache.map = htab_create (10, hash_idx_scev_info, eq_idx_scev_info, NULL);
cache.entries.create (10);
}
- bool existed_p;
- unsigned *slot = cache.map->insert (name, &existed_p);
- if (!existed_p)
+ scev_info_str e;
+ e.name_version = SSA_NAME_VERSION (name);
+ e.instantiated_below = instantiate_below->index;
+ void **slot = htab_find_slot_with_hash (cache.map, &e,
+ hash_scev_info (&e), INSERT);
+ if (!*slot)
{
- struct instantiate_cache_entry e;
- e.name = name;
e.chrec = chrec_not_analyzed_yet;
- *slot = cache.entries.length ();
+ *slot = (void *)(size_t)(cache.entries.length () + 2);
cache.entries.safe_push (e);
}
- return *slot;
+ return ((size_t)*slot) - 2;
}
-/* Cache to avoid infinite recursion when instantiating an SSA name.
- Live during the outermost instantiate_scev or resolve_mixers call. */
-static instantiate_cache_type *global_cache;
-
/* Return the closed_loop_phi node for VAR. If there is none, return
NULL_TREE. */
@@ -2195,7 +2221,8 @@ instantiate_scev_name (basic_block instantiate_below,
| a_2 -> {0, +, 1, +, a_2}_1 */
- unsigned si = get_instantiated_value_entry (*global_cache, chrec);
+ unsigned si = get_instantiated_value_entry (*global_cache,
+ chrec, instantiate_below);
if (global_cache->get (si) != chrec_not_analyzed_yet)
return global_cache->get (si);
diff --git a/gcc/tree-scalar-evolution.h b/gcc/tree-scalar-evolution.h
index 55ba82c5dbd..db7ac4c66f0 100644
--- a/gcc/tree-scalar-evolution.h
+++ b/gcc/tree-scalar-evolution.h
@@ -36,7 +36,8 @@ extern tree resolve_mixers (struct loop *, tree);
extern void gather_stats_on_scev_database (void);
extern unsigned int scev_const_prop (void);
extern bool expression_expensive_p (tree);
-extern bool simple_iv (struct loop *, struct loop *, tree, affine_iv *, bool);
+extern bool simple_iv (struct loop *, struct loop *, tree, struct affine_iv_d *,
+ bool);
extern tree compute_overall_effect_of_inner_loop (struct loop *, tree);
/* Returns the basic block preceding LOOP or ENTRY_BLOCK_PTR when the
diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
index 58c7565dcf6..38da57700e2 100644
--- a/gcc/tree-sra.c
+++ b/gcc/tree-sra.c
@@ -79,7 +79,13 @@ along with GCC; see the file COPYING3. If not see
#include "tm.h"
#include "tree.h"
#include "gimple.h"
-#include "cgraph.h"
+#include "bitmap.h"
+#include "gimple-ssa.h"
+#include "tree-cfg.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
+#include "tree-dfa.h"
#include "tree-ssa.h"
#include "tree-pass.h"
#include "ipa-prop.h"
@@ -1009,6 +1015,21 @@ completely_scalarize_var (tree var)
completely_scalarize_record (var, var, 0, var);
}
+/* Return true if REF has an VIEW_CONVERT_EXPR somewhere in it. */
+
+static inline bool
+contains_view_convert_expr_p (const_tree ref)
+{
+ while (handled_component_p (ref))
+ {
+ if (TREE_CODE (ref) == VIEW_CONVERT_EXPR)
+ return true;
+ ref = TREE_OPERAND (ref, 0);
+ }
+
+ return false;
+}
+
/* Search the given tree for a declaration by skipping handled components and
exclude it from the candidates. */
@@ -3468,8 +3489,8 @@ const pass_data pass_data_sra_early =
class pass_sra_early : public gimple_opt_pass
{
public:
- pass_sra_early(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_sra_early, ctxt)
+ pass_sra_early (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_sra_early, ctxt)
{}
/* opt_pass methods: */
@@ -3506,8 +3527,8 @@ const pass_data pass_data_sra =
class pass_sra : public gimple_opt_pass
{
public:
- pass_sra(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_sra, ctxt)
+ pass_sra (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_sra, ctxt)
{}
/* opt_pass methods: */
@@ -4292,7 +4313,7 @@ analyze_all_param_acesses (void)
repr_state = splice_all_param_accesses (representatives);
if (repr_state == NO_GOOD_ACCESS)
- return ipa_parm_adjustment_vec();
+ return ipa_parm_adjustment_vec ();
/* If there are any parameters passed by reference which are not modified
directly, we need to check whether they can be modified indirectly. */
@@ -4356,7 +4377,7 @@ analyze_all_param_acesses (void)
adjustments = turn_representatives_into_adjustments (representatives,
adjustments_count);
else
- adjustments = ipa_parm_adjustment_vec();
+ adjustments = ipa_parm_adjustment_vec ();
representatives.release ();
return adjustments;
@@ -4817,14 +4838,14 @@ convert_callers_for_node (struct cgraph_node *node,
for (cs = node->callers; cs; cs = cs->next_caller)
{
- push_cfun (DECL_STRUCT_FUNCTION (cs->caller->symbol.decl));
+ push_cfun (DECL_STRUCT_FUNCTION (cs->caller->decl));
if (dump_file)
fprintf (dump_file, "Adjusting call %s/%i -> %s/%i\n",
xstrdup (cgraph_node_name (cs->caller)),
- cs->caller->symbol.order,
+ cs->caller->order,
xstrdup (cgraph_node_name (cs->callee)),
- cs->callee->symbol.order);
+ cs->callee->order);
ipa_modify_call_arguments (cs, cs->call_stmt, *adjustments);
@@ -4833,7 +4854,7 @@ convert_callers_for_node (struct cgraph_node *node,
for (cs = node->callers; cs; cs = cs->next_caller)
if (bitmap_set_bit (recomputed_callers, cs->caller->uid)
- && gimple_in_ssa_p (DECL_STRUCT_FUNCTION (cs->caller->symbol.decl)))
+ && gimple_in_ssa_p (DECL_STRUCT_FUNCTION (cs->caller->decl)))
compute_inline_parameters (cs->caller, true);
BITMAP_FREE (recomputed_callers);
@@ -4869,7 +4890,7 @@ convert_callers (struct cgraph_node *node, tree old_decl,
{
if (dump_file)
fprintf (dump_file, "Adjusting recursive call");
- gimple_call_set_fndecl (stmt, node->symbol.decl);
+ gimple_call_set_fndecl (stmt, node->decl);
ipa_modify_call_arguments (NULL, stmt, adjustments);
}
}
@@ -4897,11 +4918,11 @@ modify_function (struct cgraph_node *node, ipa_parm_adjustment_vec adjustments)
NULL, false, NULL, NULL, "isra");
redirect_callers.release ();
- push_cfun (DECL_STRUCT_FUNCTION (new_node->symbol.decl));
+ push_cfun (DECL_STRUCT_FUNCTION (new_node->decl));
ipa_modify_formal_parameters (current_function_decl, adjustments, "ISRA");
cfg_changed = ipa_sra_modify_function_body (adjustments);
sra_ipa_reset_debug_stmts (adjustments);
- convert_callers (new_node, node->symbol.decl, adjustments);
+ convert_callers (new_node, node->decl, adjustments);
cgraph_make_node_local (new_node);
return cfg_changed;
}
@@ -4937,7 +4958,7 @@ ipa_sra_preliminary_function_checks (struct cgraph_node *node)
return false;
}
- if (!tree_versionable_function_p (node->symbol.decl))
+ if (!tree_versionable_function_p (node->decl))
{
if (dump_file)
fprintf (dump_file, "Function is not versionable.\n");
@@ -4951,8 +4972,8 @@ ipa_sra_preliminary_function_checks (struct cgraph_node *node)
return false;
}
- if ((DECL_COMDAT (node->symbol.decl) || DECL_EXTERNAL (node->symbol.decl))
- && inline_summary(node)->size >= MAX_INLINE_INSNS_AUTO)
+ if ((DECL_COMDAT (node->decl) || DECL_EXTERNAL (node->decl))
+ && inline_summary (node)->size >= MAX_INLINE_INSNS_AUTO)
{
if (dump_file)
fprintf (dump_file, "Function too big to be made truly local.\n");
@@ -4974,7 +4995,7 @@ ipa_sra_preliminary_function_checks (struct cgraph_node *node)
return false;
}
- if (TYPE_ATTRIBUTES (TREE_TYPE (node->symbol.decl)))
+ if (TYPE_ATTRIBUTES (TREE_TYPE (node->decl)))
return false;
return true;
@@ -5088,8 +5109,8 @@ const pass_data pass_data_early_ipa_sra =
class pass_early_ipa_sra : public gimple_opt_pass
{
public:
- pass_early_ipa_sra(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_early_ipa_sra, ctxt)
+ pass_early_ipa_sra (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_early_ipa_sra, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/tree-ssa-address.c b/gcc/tree-ssa-address.c
index 1ea6d2d050b..146f909c7b1 100644
--- a/gcc/tree-ssa-address.c
+++ b/gcc/tree-ssa-address.c
@@ -28,7 +28,10 @@ along with GCC; see the file COPYING3. If not see
#include "tm_p.h"
#include "basic-block.h"
#include "tree-pretty-print.h"
-#include "tree-ssa.h"
+#include "gimple.h"
+#include "tree-ssanames.h"
+#include "tree-ssa-loop-ivopts.h"
+#include "tree-dfa.h"
#include "dumpfile.h"
#include "flags.h"
#include "tree-inline.h"
@@ -42,6 +45,7 @@ along with GCC; see the file COPYING3. If not see
#include "ggc.h"
#include "target.h"
#include "expmed.h"
+#include "tree-ssa-address.h"
/* TODO -- handling of symbols (according to Richard Hendersons
comments, http://gcc.gnu.org/ml/gcc-patches/2005-04/msg00949.html):
@@ -173,6 +177,13 @@ gen_addr_rtx (enum machine_mode address_mode,
*addr = const0_rtx;
}
+/* Description of a memory address. */
+
+struct mem_address
+{
+ tree symbol, base, index, step, offset;
+};
+
/* Returns address for TARGET_MEM_REF with parameters given by ADDR
in address space AS.
If REALLY_EXPAND is false, just make fake registers instead
@@ -256,6 +267,17 @@ addr_for_mem_ref (struct mem_address *addr, addr_space_t as,
return address;
}
+/* implement addr_for_mem_ref() directly from a tree, which avoids exporting
+ the mem_address structure. */
+
+rtx
+addr_for_mem_ref (tree exp, addr_space_t as, bool really_expand)
+{
+ struct mem_address addr;
+ get_address_description (exp, &addr);
+ return addr_for_mem_ref (&addr, as, really_expand);
+}
+
/* Returns address of MEM_REF in TYPE. */
tree
diff --git a/gcc/tree-ssa-address.h b/gcc/tree-ssa-address.h
new file mode 100644
index 00000000000..803f9c82fb1
--- /dev/null
+++ b/gcc/tree-ssa-address.h
@@ -0,0 +1,32 @@
+/* Header file for memory address lowering and mode selection.
+ Copyright (C) 2013 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_SSA_ADDRESS_H
+#define GCC_TREE_SSA_ADDRESS_H
+
+extern rtx addr_for_mem_ref (struct mem_address *, addr_space_t, bool);
+extern rtx addr_for_mem_ref (tree exp, addr_space_t as, bool really_expand);
+extern void get_address_description (tree, struct mem_address *);
+extern tree tree_mem_ref_addr (tree, tree);
+tree create_mem_ref (gimple_stmt_iterator *, tree,
+ struct affine_tree_combination *, tree, tree, tree, bool);
+extern void copy_ref_info (tree, tree);
+tree maybe_fold_tmr (tree);
+
+#endif /* GCC_TREE_SSA_ADDRESS_H */
diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c
index 9a6d5f448fb..161a66a8b74 100644
--- a/gcc/tree-ssa-alias.c
+++ b/gcc/tree-ssa-alias.c
@@ -34,14 +34,16 @@ along with GCC; see the file COPYING3. If not see
#include "tree-pretty-print.h"
#include "dumpfile.h"
#include "gimple.h"
-#include "tree-ssa.h"
+#include "gimple-ssa.h"
+#include "tree-ssanames.h"
+#include "tree-dfa.h"
#include "tree-inline.h"
#include "params.h"
#include "vec.h"
-#include "bitmap.h"
#include "pointer-set.h"
#include "alloc-pool.h"
#include "tree-ssa-alias.h"
+#include "ipa-reference.h"
/* Broad overview of how alias analysis on gimple works:
@@ -404,6 +406,7 @@ dump_alias_info (FILE *file)
struct ptr_info_def *pi;
if (ptr == NULL_TREE
+ || !POINTER_TYPE_P (TREE_TYPE (ptr))
|| SSA_NAME_IN_FREE_LIST (ptr))
continue;
@@ -556,28 +559,55 @@ ao_ref_alias_set (ao_ref *ref)
}
/* Init an alias-oracle reference representation from a gimple pointer
- PTR and a gimple size SIZE in bytes. If SIZE is NULL_TREE the the
+ PTR and a gimple size SIZE in bytes. If SIZE is NULL_TREE then the
size is assumed to be unknown. The access is assumed to be only
to or after of the pointer target, not before it. */
void
ao_ref_init_from_ptr_and_size (ao_ref *ref, tree ptr, tree size)
{
- HOST_WIDE_INT t1, t2;
+ HOST_WIDE_INT t, extra_offset = 0;
ref->ref = NULL_TREE;
+ if (TREE_CODE (ptr) == SSA_NAME)
+ {
+ gimple stmt = SSA_NAME_DEF_STMT (ptr);
+ if (gimple_assign_single_p (stmt)
+ && gimple_assign_rhs_code (stmt) == ADDR_EXPR)
+ ptr = gimple_assign_rhs1 (stmt);
+ else if (is_gimple_assign (stmt)
+ && gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR
+ && TREE_CODE (gimple_assign_rhs2 (stmt)) == INTEGER_CST)
+ {
+ ptr = gimple_assign_rhs1 (stmt);
+ extra_offset = BITS_PER_UNIT
+ * int_cst_value (gimple_assign_rhs2 (stmt));
+ }
+ }
+
if (TREE_CODE (ptr) == ADDR_EXPR)
- ref->base = get_ref_base_and_extent (TREE_OPERAND (ptr, 0),
- &ref->offset, &t1, &t2);
+ {
+ ref->base = get_addr_base_and_unit_offset (TREE_OPERAND (ptr, 0), &t);
+ if (ref->base)
+ ref->offset = BITS_PER_UNIT * t;
+ else
+ {
+ size = NULL_TREE;
+ ref->offset = 0;
+ ref->base = get_base_address (TREE_OPERAND (ptr, 0));
+ }
+ }
else
{
ref->base = build2 (MEM_REF, char_type_node,
ptr, null_pointer_node);
ref->offset = 0;
}
+ ref->offset += extra_offset;
if (size
&& host_integerp (size, 0)
- && TREE_INT_CST_LOW (size) * 8 / 8 == TREE_INT_CST_LOW (size))
- ref->max_size = ref->size = TREE_INT_CST_LOW (size) * 8;
+ && TREE_INT_CST_LOW (size) * BITS_PER_UNIT / BITS_PER_UNIT
+ == TREE_INT_CST_LOW (size))
+ ref->max_size = ref->size = TREE_INT_CST_LOW (size) * BITS_PER_UNIT;
else
ref->max_size = ref->size = -1;
ref->ref_alias_set = 0;
@@ -725,11 +755,8 @@ aliasing_component_refs_p (tree ref1,
static bool
nonoverlapping_component_refs_of_decl_p (tree ref1, tree ref2)
{
- vec<tree, va_stack> component_refs1;
- vec<tree, va_stack> component_refs2;
-
- vec_stack_alloc (tree, component_refs1, 16);
- vec_stack_alloc (tree, component_refs2, 16);
+ stack_vec<tree, 16> component_refs1;
+ stack_vec<tree, 16> component_refs2;
/* Create the stack of handled components for REF1. */
while (handled_component_p (ref1))
@@ -802,12 +829,13 @@ nonoverlapping_component_refs_of_decl_p (tree ref1, tree ref2)
if (type1 != type2 || TREE_CODE (type1) != RECORD_TYPE)
goto may_overlap;
- /* Different fields of the same record type cannot overlap. */
+ /* Different fields of the same record type cannot overlap.
+ ??? Bitfields can overlap at RTL level so punt on them. */
if (field1 != field2)
{
component_refs1.release ();
component_refs2.release ();
- return true;
+ return !(DECL_BIT_FIELD (field1) && DECL_BIT_FIELD (field2));
}
}
@@ -1512,16 +1540,19 @@ ref_maybe_used_by_call_p_1 (gimple call, ao_ref *ref)
case BUILT_IN_GOMP_ATOMIC_START:
case BUILT_IN_GOMP_ATOMIC_END:
case BUILT_IN_GOMP_BARRIER:
+ case BUILT_IN_GOMP_BARRIER_CANCEL:
case BUILT_IN_GOMP_TASKWAIT:
+ case BUILT_IN_GOMP_TASKGROUP_END:
case BUILT_IN_GOMP_CRITICAL_START:
case BUILT_IN_GOMP_CRITICAL_END:
case BUILT_IN_GOMP_CRITICAL_NAME_START:
case BUILT_IN_GOMP_CRITICAL_NAME_END:
case BUILT_IN_GOMP_LOOP_END:
+ case BUILT_IN_GOMP_LOOP_END_CANCEL:
case BUILT_IN_GOMP_ORDERED_START:
case BUILT_IN_GOMP_ORDERED_END:
- case BUILT_IN_GOMP_PARALLEL_END:
case BUILT_IN_GOMP_SECTIONS_END:
+ case BUILT_IN_GOMP_SECTIONS_END_CANCEL:
case BUILT_IN_GOMP_SINGLE_COPY_START:
case BUILT_IN_GOMP_SINGLE_COPY_END:
return true;
@@ -1856,16 +1887,19 @@ call_may_clobber_ref_p_1 (gimple call, ao_ref *ref)
case BUILT_IN_GOMP_ATOMIC_START:
case BUILT_IN_GOMP_ATOMIC_END:
case BUILT_IN_GOMP_BARRIER:
+ case BUILT_IN_GOMP_BARRIER_CANCEL:
case BUILT_IN_GOMP_TASKWAIT:
+ case BUILT_IN_GOMP_TASKGROUP_END:
case BUILT_IN_GOMP_CRITICAL_START:
case BUILT_IN_GOMP_CRITICAL_END:
case BUILT_IN_GOMP_CRITICAL_NAME_START:
case BUILT_IN_GOMP_CRITICAL_NAME_END:
case BUILT_IN_GOMP_LOOP_END:
+ case BUILT_IN_GOMP_LOOP_END_CANCEL:
case BUILT_IN_GOMP_ORDERED_START:
case BUILT_IN_GOMP_ORDERED_END:
- case BUILT_IN_GOMP_PARALLEL_END:
case BUILT_IN_GOMP_SECTIONS_END:
+ case BUILT_IN_GOMP_SECTIONS_END_CANCEL:
case BUILT_IN_GOMP_SINGLE_COPY_START:
case BUILT_IN_GOMP_SINGLE_COPY_END:
return true;
@@ -1974,9 +2008,10 @@ static bool
stmt_kills_ref_p_1 (gimple stmt, ao_ref *ref)
{
/* For a must-alias check we need to be able to constrain
- the access properly. */
- ao_ref_base (ref);
- if (ref->max_size == -1)
+ the access properly.
+ FIXME: except for BUILTIN_FREE. */
+ if (!ao_ref_base (ref)
+ || ref->max_size == -1)
return false;
if (gimple_has_lhs (stmt)
@@ -2042,6 +2077,16 @@ stmt_kills_ref_p_1 (gimple stmt, ao_ref *ref)
&& DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL)
switch (DECL_FUNCTION_CODE (callee))
{
+ case BUILT_IN_FREE:
+ {
+ tree ptr = gimple_call_arg (stmt, 0);
+ tree base = ao_ref_base (ref);
+ if (base && TREE_CODE (base) == MEM_REF
+ && TREE_OPERAND (base, 0) == ptr)
+ return true;
+ break;
+ }
+
case BUILT_IN_MEMCPY:
case BUILT_IN_MEMPCPY:
case BUILT_IN_MEMMOVE:
@@ -2053,23 +2098,33 @@ stmt_kills_ref_p_1 (gimple stmt, ao_ref *ref)
{
tree dest = gimple_call_arg (stmt, 0);
tree len = gimple_call_arg (stmt, 2);
- tree base = NULL_TREE;
- HOST_WIDE_INT offset = 0;
if (!host_integerp (len, 0))
return false;
- if (TREE_CODE (dest) == ADDR_EXPR)
- base = get_addr_base_and_unit_offset (TREE_OPERAND (dest, 0),
- &offset);
- else if (TREE_CODE (dest) == SSA_NAME)
- base = dest;
- if (base
- && base == ao_ref_base (ref))
+ tree rbase = ref->base;
+ double_int roffset = double_int::from_shwi (ref->offset);
+ ao_ref dref;
+ ao_ref_init_from_ptr_and_size (&dref, dest, len);
+ tree base = ao_ref_base (&dref);
+ double_int offset = double_int::from_shwi (dref.offset);
+ double_int bpu = double_int::from_uhwi (BITS_PER_UNIT);
+ if (!base || dref.size == -1)
+ return false;
+ if (TREE_CODE (base) == MEM_REF)
+ {
+ if (TREE_CODE (rbase) != MEM_REF)
+ return false;
+ // Compare pointers.
+ offset += bpu * mem_ref_offset (base);
+ roffset += bpu * mem_ref_offset (rbase);
+ base = TREE_OPERAND (base, 0);
+ rbase = TREE_OPERAND (rbase, 0);
+ }
+ if (base == rbase)
{
- HOST_WIDE_INT size = TREE_INT_CST_LOW (len);
- if (offset <= ref->offset / BITS_PER_UNIT
- && (offset + size
- >= ((ref->offset + ref->max_size + BITS_PER_UNIT - 1)
- / BITS_PER_UNIT)))
+ double_int size = bpu * tree_to_double_int (len);
+ double_int rsize = double_int::from_uhwi (ref->max_size);
+ if (offset.sle (roffset)
+ && (roffset + rsize).sle (offset + size))
return true;
}
break;
diff --git a/gcc/tree-ssa-alias.h b/gcc/tree-ssa-alias.h
index e560685028b..581cd82a5f3 100644
--- a/gcc/tree-ssa-alias.h
+++ b/gcc/tree-ssa-alias.h
@@ -141,5 +141,28 @@ 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 (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/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
index ea1269c53cd..b4dfd4928cd 100644
--- a/gcc/tree-ssa-ccp.c
+++ b/gcc/tree-ssa-ccp.c
@@ -119,7 +119,12 @@ along with GCC; see the file COPYING3. If not see
#include "basic-block.h"
#include "function.h"
#include "gimple-pretty-print.h"
-#include "tree-ssa.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-cfg.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
#include "tree-pass.h"
#include "tree-ssa-propagate.h"
#include "value-prof.h"
@@ -127,7 +132,6 @@ along with GCC; see the file COPYING3. If not see
#include "target.h"
#include "diagnostic-core.h"
#include "dbgcnt.h"
-#include "gimple-fold.h"
#include "params.h"
#include "hash-table.h"
@@ -164,7 +168,7 @@ typedef struct prop_value_d prop_value_t;
static prop_value_t *const_val;
static unsigned n_const_val;
-static void canonicalize_float_value (prop_value_t *);
+static void canonicalize_value (prop_value_t *);
static bool ccp_fold_stmt (gimple_stmt_iterator *);
/* Dump constant propagation value VAL to file OUTF prefixed by PREFIX. */
@@ -256,6 +260,19 @@ get_default_value (tree var)
{
val.lattice_val = VARYING;
val.mask = double_int_minus_one;
+ if (flag_tree_bit_ccp)
+ {
+ double_int nonzero_bits = get_nonzero_bits (var);
+ double_int mask
+ = double_int::mask (TYPE_PRECISION (TREE_TYPE (var)));
+ if (nonzero_bits != double_int_minus_one && nonzero_bits != mask)
+ {
+ val.lattice_val = CONSTANT;
+ val.value = build_zero_cst (TREE_TYPE (var));
+ /* CCP wants the bits above precision set. */
+ val.mask = nonzero_bits | ~mask;
+ }
+ }
}
}
else if (is_gimple_assign (stmt))
@@ -309,7 +326,7 @@ get_value (tree var)
if (val->lattice_val == UNINITIALIZED)
*val = get_default_value (var);
- canonicalize_float_value (val);
+ canonicalize_value (val);
return val;
}
@@ -361,17 +378,24 @@ set_value_varying (tree var)
that HONOR_NANS is false, and we try to change the value of x to 0,
causing an ICE. With HONOR_NANS being false, the real appearance of
NaN would cause undefined behavior, though, so claiming that y (and x)
- are UNDEFINED initially is correct. */
+ are UNDEFINED initially is correct.
+
+ For other constants, make sure to drop TREE_OVERFLOW. */
static void
-canonicalize_float_value (prop_value_t *val)
+canonicalize_value (prop_value_t *val)
{
enum machine_mode mode;
tree type;
REAL_VALUE_TYPE d;
- if (val->lattice_val != CONSTANT
- || TREE_CODE (val->value) != REAL_CST)
+ if (val->lattice_val != CONSTANT)
+ return;
+
+ if (TREE_OVERFLOW_P (val->value))
+ val->value = drop_tree_overflow (val->value);
+
+ if (TREE_CODE (val->value) != REAL_CST)
return;
d = TREE_REAL_CST (val->value);
@@ -437,7 +461,7 @@ set_lattice_value (tree var, prop_value_t new_val)
/* We can deal with old UNINITIALIZED values just fine here. */
prop_value_t *old_val = &const_val[SSA_NAME_VERSION (var)];
- canonicalize_float_value (&new_val);
+ canonicalize_value (&new_val);
/* We have to be careful to not go up the bitwise lattice
represented by the mask.
@@ -552,7 +576,7 @@ get_value_for_expr (tree expr, bool for_bits_p)
val.lattice_val = CONSTANT;
val.value = expr;
val.mask = double_int_zero;
- canonicalize_float_value (&val);
+ canonicalize_value (&val);
}
else if (TREE_CODE (expr) == ADDR_EXPR)
val = get_value_from_alignment (expr);
@@ -824,7 +848,8 @@ ccp_finalize (void)
do_dbg_cnt ();
/* Derive alignment and misalignment information from partially
- constant pointers in the lattice. */
+ constant pointers in the lattice or nonzero bits from partially
+ constant integers. */
for (i = 1; i < num_ssa_names; ++i)
{
tree name = ssa_name (i);
@@ -832,7 +857,11 @@ ccp_finalize (void)
unsigned int tem, align;
if (!name
- || !POINTER_TYPE_P (TREE_TYPE (name)))
+ || (!POINTER_TYPE_P (TREE_TYPE (name))
+ && (!INTEGRAL_TYPE_P (TREE_TYPE (name))
+ /* Don't record nonzero bits before IPA to avoid
+ using too much memory. */
+ || first_pass_instance)))
continue;
val = get_value (name);
@@ -840,13 +869,24 @@ ccp_finalize (void)
|| TREE_CODE (val->value) != INTEGER_CST)
continue;
- /* Trailing constant bits specify the alignment, trailing value
- bits the misalignment. */
- tem = val->mask.low;
- align = (tem & -tem);
- if (align > 1)
- set_ptr_info_alignment (get_ptr_info (name), align,
- TREE_INT_CST_LOW (val->value) & (align - 1));
+ if (POINTER_TYPE_P (TREE_TYPE (name)))
+ {
+ /* Trailing mask bits specify the alignment, trailing value
+ bits the misalignment. */
+ tem = val->mask.low;
+ align = (tem & -tem);
+ if (align > 1)
+ set_ptr_info_alignment (get_ptr_info (name), align,
+ (TREE_INT_CST_LOW (val->value)
+ & (align - 1)));
+ }
+ else
+ {
+ double_int nonzero_bits = val->mask;
+ nonzero_bits = nonzero_bits | tree_to_double_int (val->value);
+ nonzero_bits &= get_nonzero_bits (name);
+ set_nonzero_bits (name, nonzero_bits);
+ }
}
/* Perform substitutions based on the known constant values. */
@@ -1667,6 +1707,39 @@ evaluate_stmt (gimple stmt)
is_constant = (val.lattice_val == CONSTANT);
}
+ if (flag_tree_bit_ccp
+ && ((is_constant && TREE_CODE (val.value) == INTEGER_CST)
+ || (!is_constant && likelyvalue != UNDEFINED))
+ && gimple_get_lhs (stmt)
+ && TREE_CODE (gimple_get_lhs (stmt)) == SSA_NAME)
+ {
+ tree lhs = gimple_get_lhs (stmt);
+ double_int nonzero_bits = get_nonzero_bits (lhs);
+ double_int mask = double_int::mask (TYPE_PRECISION (TREE_TYPE (lhs)));
+ if (nonzero_bits != double_int_minus_one && nonzero_bits != mask)
+ {
+ if (!is_constant)
+ {
+ val.lattice_val = CONSTANT;
+ val.value = build_zero_cst (TREE_TYPE (lhs));
+ /* CCP wants the bits above precision set. */
+ val.mask = nonzero_bits | ~mask;
+ is_constant = true;
+ }
+ else
+ {
+ double_int valv = tree_to_double_int (val.value);
+ if (!(valv & ~nonzero_bits & mask).is_zero ())
+ val.value = double_int_to_tree (TREE_TYPE (lhs),
+ valv & nonzero_bits);
+ if (nonzero_bits.is_zero ())
+ val.mask = double_int_zero;
+ else
+ val.mask = val.mask & (nonzero_bits | ~mask);
+ }
+ }
+ }
+
if (!is_constant)
{
/* The statement produced a nonconstant value. If the statement
@@ -1728,6 +1801,9 @@ insert_clobber_before_stack_restore (tree saved_val, tree var,
insert_clobber_before_stack_restore (gimple_phi_result (stmt), var,
visited);
}
+ else if (gimple_assign_ssa_name_copy_p (stmt))
+ insert_clobber_before_stack_restore (gimple_assign_lhs (stmt), var,
+ visited);
else
gcc_assert (is_gimple_debug (stmt));
}
@@ -2163,12 +2239,12 @@ const pass_data pass_data_ccp =
class pass_ccp : public gimple_opt_pass
{
public:
- pass_ccp(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_ccp, ctxt)
+ pass_ccp (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_ccp, ctxt)
{}
/* opt_pass methods: */
- opt_pass * clone () { return new pass_ccp (ctxt_); }
+ opt_pass * clone () { return new pass_ccp (m_ctxt); }
bool gate () { return gate_ccp (); }
unsigned int execute () { return do_ssa_ccp (); }
@@ -2580,12 +2656,12 @@ const pass_data pass_data_fold_builtins =
class pass_fold_builtins : public gimple_opt_pass
{
public:
- pass_fold_builtins(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_fold_builtins, ctxt)
+ pass_fold_builtins (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_fold_builtins, ctxt)
{}
/* opt_pass methods: */
- opt_pass * clone () { return new pass_fold_builtins (ctxt_); }
+ opt_pass * clone () { return new pass_fold_builtins (m_ctxt); }
unsigned int execute () { return execute_fold_all_builtins (); }
}; // class pass_fold_builtins
diff --git a/gcc/tree-ssa-coalesce.c b/gcc/tree-ssa-coalesce.c
index d86e0b86560..c445c78626e 100644
--- a/gcc/tree-ssa-coalesce.c
+++ b/gcc/tree-ssa-coalesce.c
@@ -27,9 +27,14 @@ along with GCC; see the file COPYING3. If not see
#include "tree-pretty-print.h"
#include "bitmap.h"
#include "dumpfile.h"
-#include "tree-ssa.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
#include "hash-table.h"
#include "tree-ssa-live.h"
+#include "tree-ssa-coalesce.h"
#include "diagnostic-core.h"
@@ -635,7 +640,7 @@ new_live_track (var_map map)
ptr->map = map;
lim = num_basevars (map);
bitmap_obstack_initialize (&ptr->obstack);
- ptr->live_base_partitions = (bitmap *) xmalloc(sizeof (bitmap *) * lim);
+ ptr->live_base_partitions = (bitmap *) xmalloc (sizeof (bitmap *) * lim);
ptr->live_base_var = BITMAP_ALLOC (&ptr->obstack);
for (x = 0; x < lim; x++)
ptr->live_base_partitions[x] = BITMAP_ALLOC (&ptr->obstack);
@@ -980,10 +985,7 @@ create_outofssa_var_map (coalesce_list_p cl, bitmap used_in_copy)
{
tree lhs = gimple_assign_lhs (stmt);
tree rhs1 = gimple_assign_rhs1 (stmt);
-
- if (gimple_assign_copy_p (stmt)
- && TREE_CODE (lhs) == SSA_NAME
- && TREE_CODE (rhs1) == SSA_NAME
+ if (gimple_assign_ssa_name_copy_p (stmt)
&& gimple_can_coalesce_p (lhs, rhs1))
{
v1 = SSA_NAME_VERSION (lhs);
@@ -1336,38 +1338,3 @@ coalesce_ssa_name (void)
return map;
}
-
-/* Given SSA_NAMEs NAME1 and NAME2, return true if they are candidates for
- coalescing together, false otherwise.
-
- This must stay consistent with var_map_base_init in tree-ssa-live.c. */
-
-bool
-gimple_can_coalesce_p (tree name1, tree name2)
-{
- /* First check the SSA_NAME's associated DECL. We only want to
- coalesce if they have the same DECL or both have no associated DECL. */
- if (SSA_NAME_VAR (name1) != SSA_NAME_VAR (name2))
- return false;
-
- /* Now check the types. If the types are the same, then we should
- try to coalesce V1 and V2. */
- tree t1 = TREE_TYPE (name1);
- tree t2 = TREE_TYPE (name2);
- if (t1 == t2)
- return true;
-
- /* If the types are not the same, check for a canonical type match. This
- (for example) allows coalescing when the types are fundamentally the
- same, but just have different names.
-
- Note pointer types with different address spaces may have the same
- canonical type. Those are rejected for coalescing by the
- types_compatible_p check. */
- if (TYPE_CANONICAL (t1)
- && TYPE_CANONICAL (t1) == TYPE_CANONICAL (t2)
- && types_compatible_p (t1, t2))
- return true;
-
- return false;
-}
diff --git a/gcc/tree-ssa-coalesce.h b/gcc/tree-ssa-coalesce.h
new file mode 100644
index 00000000000..6b2831fc537
--- /dev/null
+++ b/gcc/tree-ssa-coalesce.h
@@ -0,0 +1,25 @@
+/* Header file for tree-ssa-coalesce.c exports.
+ Copyright (C) 2013 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_SSA_COALESCE_H
+#define GCC_TREE_SSA_COALESCE_H
+
+extern var_map coalesce_ssa_name (void);
+
+#endif /* GCC_TREE_SSA_COALESCE_H */
diff --git a/gcc/tree-ssa-copy.c b/gcc/tree-ssa-copy.c
index 31979177444..15c6896e945 100644
--- a/gcc/tree-ssa-copy.c
+++ b/gcc/tree-ssa-copy.c
@@ -27,12 +27,18 @@ along with GCC; see the file COPYING3. If not see
#include "basic-block.h"
#include "function.h"
#include "gimple-pretty-print.h"
-#include "tree-ssa.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-cfg.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
#include "tree-pass.h"
#include "tree-ssa-propagate.h"
#include "langhooks.h"
#include "cfgloop.h"
#include "tree-scalar-evolution.h"
+#include "tree-ssa-dom.h"
/* This file implements the copy propagation pass and provides a
handful of interfaces for performing const/copy propagation and
@@ -50,220 +56,6 @@ along with GCC; see the file COPYING3. If not see
replacements of one SSA_NAME with a different SSA_NAME to use the
APIs defined in this file. */
-/* Return true if we may propagate ORIG into DEST, false otherwise. */
-
-bool
-may_propagate_copy (tree dest, tree orig)
-{
- tree type_d = TREE_TYPE (dest);
- tree type_o = TREE_TYPE (orig);
-
- /* If ORIG flows in from an abnormal edge, it cannot be propagated. */
- if (TREE_CODE (orig) == SSA_NAME
- && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (orig)
- /* If it is the default definition and an automatic variable then
- we can though and it is important that we do to avoid
- uninitialized regular copies. */
- && !(SSA_NAME_IS_DEFAULT_DEF (orig)
- && (SSA_NAME_VAR (orig) == NULL_TREE
- || TREE_CODE (SSA_NAME_VAR (orig)) == VAR_DECL)))
- return false;
-
- /* If DEST is an SSA_NAME that flows from an abnormal edge, then it
- cannot be replaced. */
- if (TREE_CODE (dest) == SSA_NAME
- && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (dest))
- return false;
-
- /* Do not copy between types for which we *do* need a conversion. */
- if (!useless_type_conversion_p (type_d, type_o))
- return false;
-
- /* Generally propagating virtual operands is not ok as that may
- create overlapping life-ranges. */
- if (TREE_CODE (dest) == SSA_NAME && virtual_operand_p (dest))
- return false;
-
- /* Anything else is OK. */
- return true;
-}
-
-/* Like may_propagate_copy, but use as the destination expression
- the principal expression (typically, the RHS) contained in
- statement DEST. This is more efficient when working with the
- gimple tuples representation. */
-
-bool
-may_propagate_copy_into_stmt (gimple dest, tree orig)
-{
- tree type_d;
- tree type_o;
-
- /* If the statement is a switch or a single-rhs assignment,
- then the expression to be replaced by the propagation may
- be an SSA_NAME. Fortunately, there is an explicit tree
- for the expression, so we delegate to may_propagate_copy. */
-
- if (gimple_assign_single_p (dest))
- return may_propagate_copy (gimple_assign_rhs1 (dest), orig);
- else if (gimple_code (dest) == GIMPLE_SWITCH)
- return may_propagate_copy (gimple_switch_index (dest), orig);
-
- /* In other cases, the expression is not materialized, so there
- is no destination to pass to may_propagate_copy. On the other
- hand, the expression cannot be an SSA_NAME, so the analysis
- is much simpler. */
-
- if (TREE_CODE (orig) == SSA_NAME
- && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (orig))
- return false;
-
- if (is_gimple_assign (dest))
- type_d = TREE_TYPE (gimple_assign_lhs (dest));
- else if (gimple_code (dest) == GIMPLE_COND)
- type_d = boolean_type_node;
- else if (is_gimple_call (dest)
- && gimple_call_lhs (dest) != NULL_TREE)
- type_d = TREE_TYPE (gimple_call_lhs (dest));
- else
- gcc_unreachable ();
-
- type_o = TREE_TYPE (orig);
-
- if (!useless_type_conversion_p (type_d, type_o))
- return false;
-
- return true;
-}
-
-/* Similarly, but we know that we're propagating into an ASM_EXPR. */
-
-bool
-may_propagate_copy_into_asm (tree dest ATTRIBUTE_UNUSED)
-{
- return true;
-}
-
-
-/* Common code for propagate_value and replace_exp.
-
- Replace use operand OP_P with VAL. FOR_PROPAGATION indicates if the
- replacement is done to propagate a value or not. */
-
-static void
-replace_exp_1 (use_operand_p op_p, tree val,
- bool for_propagation ATTRIBUTE_UNUSED)
-{
-#if defined ENABLE_CHECKING
- tree op = USE_FROM_PTR (op_p);
-
- gcc_assert (!(for_propagation
- && TREE_CODE (op) == SSA_NAME
- && TREE_CODE (val) == SSA_NAME
- && !may_propagate_copy (op, val)));
-#endif
-
- if (TREE_CODE (val) == SSA_NAME)
- SET_USE (op_p, val);
- else
- SET_USE (op_p, unshare_expr (val));
-}
-
-
-/* Propagate the value VAL (assumed to be a constant or another SSA_NAME)
- into the operand pointed to by OP_P.
-
- Use this version for const/copy propagation as it will perform additional
- checks to ensure validity of the const/copy propagation. */
-
-void
-propagate_value (use_operand_p op_p, tree val)
-{
- replace_exp_1 (op_p, val, true);
-}
-
-/* Replace *OP_P with value VAL (assumed to be a constant or another SSA_NAME).
-
- Use this version when not const/copy propagating values. For example,
- PRE uses this version when building expressions as they would appear
- in specific blocks taking into account actions of PHI nodes.
-
- The statement in which an expression has been replaced should be
- folded using fold_stmt_inplace. */
-
-void
-replace_exp (use_operand_p op_p, tree val)
-{
- replace_exp_1 (op_p, val, false);
-}
-
-
-/* Propagate the value VAL (assumed to be a constant or another SSA_NAME)
- into the tree pointed to by OP_P.
-
- Use this version for const/copy propagation when SSA operands are not
- available. It will perform the additional checks to ensure validity of
- the const/copy propagation, but will not update any operand information.
- Be sure to mark the stmt as modified. */
-
-void
-propagate_tree_value (tree *op_p, tree val)
-{
- gcc_checking_assert (!(TREE_CODE (val) == SSA_NAME
- && *op_p
- && TREE_CODE (*op_p) == SSA_NAME
- && !may_propagate_copy (*op_p, val)));
-
- if (TREE_CODE (val) == SSA_NAME)
- *op_p = val;
- else
- *op_p = unshare_expr (val);
-}
-
-
-/* Like propagate_tree_value, but use as the operand to replace
- the principal expression (typically, the RHS) contained in the
- statement referenced by iterator GSI. Note that it is not
- always possible to update the statement in-place, so a new
- statement may be created to replace the original. */
-
-void
-propagate_tree_value_into_stmt (gimple_stmt_iterator *gsi, tree val)
-{
- gimple stmt = gsi_stmt (*gsi);
-
- if (is_gimple_assign (stmt))
- {
- tree expr = NULL_TREE;
- if (gimple_assign_single_p (stmt))
- expr = gimple_assign_rhs1 (stmt);
- propagate_tree_value (&expr, val);
- gimple_assign_set_rhs_from_tree (gsi, expr);
- }
- else if (gimple_code (stmt) == GIMPLE_COND)
- {
- tree lhs = NULL_TREE;
- tree rhs = build_zero_cst (TREE_TYPE (val));
- propagate_tree_value (&lhs, val);
- gimple_cond_set_code (stmt, NE_EXPR);
- gimple_cond_set_lhs (stmt, lhs);
- gimple_cond_set_rhs (stmt, rhs);
- }
- else if (is_gimple_call (stmt)
- && gimple_call_lhs (stmt) != NULL_TREE)
- {
- tree expr = NULL_TREE;
- bool res;
- propagate_tree_value (&expr, val);
- res = update_call_from_tree (gsi, expr);
- gcc_assert (res);
- }
- else if (gimple_code (stmt) == GIMPLE_SWITCH)
- propagate_tree_value (gimple_switch_index_ptr (stmt), val);
- else
- gcc_unreachable ();
-}
-
/*---------------------------------------------------------------------------
Copy propagation
---------------------------------------------------------------------------*/
@@ -767,11 +559,19 @@ fini_copy_prop (void)
of the representative to the first solution we find if
it doesn't have one already. */
if (copy_of[i].value != var
- && TREE_CODE (copy_of[i].value) == SSA_NAME
- && POINTER_TYPE_P (TREE_TYPE (var))
- && SSA_NAME_PTR_INFO (var)
- && !SSA_NAME_PTR_INFO (copy_of[i].value))
- duplicate_ssa_name_ptr_info (copy_of[i].value, SSA_NAME_PTR_INFO (var));
+ && TREE_CODE (copy_of[i].value) == SSA_NAME)
+ {
+ if (POINTER_TYPE_P (TREE_TYPE (var))
+ && SSA_NAME_PTR_INFO (var)
+ && !SSA_NAME_PTR_INFO (copy_of[i].value))
+ duplicate_ssa_name_ptr_info (copy_of[i].value,
+ SSA_NAME_PTR_INFO (var));
+ else if (!POINTER_TYPE_P (TREE_TYPE (var))
+ && SSA_NAME_RANGE_INFO (var)
+ && !SSA_NAME_RANGE_INFO (copy_of[i].value))
+ duplicate_ssa_name_range_info (copy_of[i].value,
+ SSA_NAME_RANGE_INFO (var));
+ }
}
/* Don't do DCE if SCEV is initialized. It would destroy the scev cache. */
@@ -850,12 +650,12 @@ const pass_data pass_data_copy_prop =
class pass_copy_prop : public gimple_opt_pass
{
public:
- pass_copy_prop(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_copy_prop, ctxt)
+ pass_copy_prop (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_copy_prop, ctxt)
{}
/* opt_pass methods: */
- opt_pass * clone () { return new pass_copy_prop (ctxt_); }
+ opt_pass * clone () { return new pass_copy_prop (m_ctxt); }
bool gate () { return gate_copy_prop (); }
unsigned int execute () { return execute_copy_prop (); }
diff --git a/gcc/tree-ssa-copyrename.c b/gcc/tree-ssa-copyrename.c
index f6e4b451541..30b339def7d 100644
--- a/gcc/tree-ssa-copyrename.c
+++ b/gcc/tree-ssa-copyrename.c
@@ -29,8 +29,9 @@ along with GCC; see the file COPYING3. If not see
#include "function.h"
#include "tree-pretty-print.h"
#include "bitmap.h"
-#include "tree-ssa.h"
-#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-ssanames.h"
+#include "tree-dfa.h"
#include "tree-inline.h"
#include "hashtab.h"
#include "tree-ssa-live.h"
@@ -455,12 +456,12 @@ const pass_data pass_data_rename_ssa_copies =
class pass_rename_ssa_copies : public gimple_opt_pass
{
public:
- pass_rename_ssa_copies(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_rename_ssa_copies, ctxt)
+ pass_rename_ssa_copies (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_rename_ssa_copies, ctxt)
{}
/* opt_pass methods: */
- opt_pass * clone () { return new pass_rename_ssa_copies (ctxt_); }
+ opt_pass * clone () { return new pass_rename_ssa_copies (m_ctxt); }
bool gate () { return gate_copyrename (); }
unsigned int execute () { return rename_ssa_copies (); }
diff --git a/gcc/tree-ssa-dce.c b/gcc/tree-ssa-dce.c
index 8e8f37ce8c8..72e2fb8fa65 100644
--- a/gcc/tree-ssa-dce.c
+++ b/gcc/tree-ssa-dce.c
@@ -50,8 +50,15 @@ along with GCC; see the file COPYING3. If not see
#include "tree.h"
#include "gimple-pretty-print.h"
#include "basic-block.h"
-#include "tree-ssa.h"
#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-cfg.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
+#include "tree-ssa-loop-niter.h"
+#include "tree-into-ssa.h"
+#include "tree-dfa.h"
#include "tree-pass.h"
#include "flags.h"
#include "cfgloop.h"
@@ -907,48 +914,6 @@ propagate_necessity (bool aggressive)
}
}
-/* Replace all uses of NAME by underlying variable and mark it
- for renaming. This assumes the defining statement of NAME is
- going to be removed. */
-
-void
-mark_virtual_operand_for_renaming (tree name)
-{
- tree name_var = SSA_NAME_VAR (name);
- bool used = false;
- imm_use_iterator iter;
- use_operand_p use_p;
- gimple stmt;
-
- gcc_assert (VAR_DECL_IS_VIRTUAL_OPERAND (name_var));
- FOR_EACH_IMM_USE_STMT (stmt, iter, name)
- {
- FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
- SET_USE (use_p, name_var);
- used = true;
- }
- if (used)
- mark_virtual_operands_for_renaming (cfun);
-}
-
-/* Replace all uses of the virtual PHI result by its underlying variable
- and mark it for renaming. This assumes the PHI node is going to be
- removed. */
-
-void
-mark_virtual_phi_result_for_renaming (gimple phi)
-{
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "Marking result for renaming : ");
- print_gimple_stmt (dump_file, phi, 0, TDF_SLIM);
- fprintf (dump_file, "\n");
- }
-
- mark_virtual_operand_for_renaming (gimple_phi_result (phi));
-}
-
-
/* Remove dead PHI nodes from block BB. */
static bool
@@ -1560,12 +1525,12 @@ const pass_data pass_data_dce =
class pass_dce : public gimple_opt_pass
{
public:
- pass_dce(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_dce, ctxt)
+ pass_dce (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_dce, ctxt)
{}
/* opt_pass methods: */
- opt_pass * clone () { return new pass_dce (ctxt_); }
+ opt_pass * clone () { return new pass_dce (m_ctxt); }
bool gate () { return gate_dce (); }
unsigned int execute () { return tree_ssa_dce (); }
@@ -1599,12 +1564,12 @@ const pass_data pass_data_dce_loop =
class pass_dce_loop : public gimple_opt_pass
{
public:
- pass_dce_loop(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_dce_loop, ctxt)
+ pass_dce_loop (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_dce_loop, ctxt)
{}
/* opt_pass methods: */
- opt_pass * clone () { return new pass_dce_loop (ctxt_); }
+ opt_pass * clone () { return new pass_dce_loop (m_ctxt); }
bool gate () { return gate_dce (); }
unsigned int execute () { return tree_ssa_dce_loop (); }
@@ -1638,12 +1603,12 @@ const pass_data pass_data_cd_dce =
class pass_cd_dce : public gimple_opt_pass
{
public:
- pass_cd_dce(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_cd_dce, ctxt)
+ pass_cd_dce (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_cd_dce, ctxt)
{}
/* opt_pass methods: */
- opt_pass * clone () { return new pass_cd_dce (ctxt_); }
+ opt_pass * clone () { return new pass_cd_dce (m_ctxt); }
bool gate () { return gate_dce (); }
unsigned int execute () { return tree_ssa_cd_dce (); }
diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c
index f5613862dcf..6a6f027e90c 100644
--- a/gcc/tree-ssa-dom.c
+++ b/gcc/tree-ssa-dom.c
@@ -30,12 +30,21 @@ along with GCC; see the file COPYING3. If not see
#include "cfgloop.h"
#include "function.h"
#include "gimple-pretty-print.h"
-#include "tree-ssa.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-cfg.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
+#include "tree-into-ssa.h"
#include "domwalk.h"
#include "tree-pass.h"
#include "tree-ssa-propagate.h"
+#include "tree-ssa-threadupdate.h"
#include "langhooks.h"
#include "params.h"
+#include "tree-ssa-threadedge.h"
+#include "tree-ssa-dom.h"
/* This file implements optimizations on the dominator tree. */
@@ -527,6 +536,29 @@ hashable_expr_equal_p (const struct hashable_expr *expr0,
}
}
+/* Generate a hash value for a pair of expressions. This can be used
+ iteratively by passing a previous result as the VAL argument.
+
+ The same hash value is always returned for a given pair of expressions,
+ regardless of the order in which they are presented. This is useful in
+ hashing the operands of commutative functions. */
+
+static hashval_t
+iterative_hash_exprs_commutative (const_tree t1,
+ const_tree t2, hashval_t val)
+{
+ hashval_t one = iterative_hash_expr (t1, 0);
+ hashval_t two = iterative_hash_expr (t2, 0);
+ hashval_t t;
+
+ if (one > two)
+ t = one, one = two, two = t;
+ val = iterative_hash_hashval_t (one, val);
+ val = iterative_hash_hashval_t (two, val);
+
+ return val;
+}
+
/* Compute a hash value for a hashable_expr value EXPR and a
previously accumulated hash value VAL. If two hashable_expr
values compare equal with hashable_expr_equal_p, they must
@@ -638,18 +670,18 @@ print_expr_hash_elt (FILE * stream, const struct expr_hash_elt *element)
break;
case EXPR_UNARY:
- fprintf (stream, "%s ", tree_code_name[element->expr.ops.unary.op]);
+ fprintf (stream, "%s ", get_tree_code_name (element->expr.ops.unary.op));
print_generic_expr (stream, element->expr.ops.unary.opnd, 0);
break;
case EXPR_BINARY:
print_generic_expr (stream, element->expr.ops.binary.opnd0, 0);
- fprintf (stream, " %s ", tree_code_name[element->expr.ops.binary.op]);
+ fprintf (stream, " %s ", get_tree_code_name (element->expr.ops.binary.op));
print_generic_expr (stream, element->expr.ops.binary.opnd1, 0);
break;
case EXPR_TERNARY:
- fprintf (stream, " %s <", tree_code_name[element->expr.ops.ternary.op]);
+ fprintf (stream, " %s <", get_tree_code_name (element->expr.ops.ternary.op));
print_generic_expr (stream, element->expr.ops.ternary.opnd0, 0);
fputs (", ", stream);
print_generic_expr (stream, element->expr.ops.ternary.opnd1, 0);
@@ -774,7 +806,7 @@ class dom_opt_dom_walker : public dom_walker
{
public:
dom_opt_dom_walker (cdi_direction direction)
- : dom_walker (direction), dummy_cond_ (NULL) {}
+ : dom_walker (direction), m_dummy_cond (NULL) {}
virtual void before_dom_children (basic_block);
virtual void after_dom_children (basic_block);
@@ -782,7 +814,7 @@ public:
private:
void thread_across_edge (edge);
- gimple dummy_cond_;
+ gimple m_dummy_cond;
};
/* Jump threading, redundancy elimination and const/copy propagation.
@@ -901,7 +933,6 @@ tree_ssa_dominator_optimize (void)
/* Free the value-handle array. */
threadedge_finalize_values ();
- ssa_name_values.release ();
return 0;
}
@@ -934,12 +965,12 @@ const pass_data pass_data_dominator =
class pass_dominator : public gimple_opt_pass
{
public:
- pass_dominator(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_dominator, ctxt)
+ pass_dominator (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_dominator, ctxt)
{}
/* opt_pass methods: */
- opt_pass * clone () { return new pass_dominator (ctxt_); }
+ opt_pass * clone () { return new pass_dominator (m_ctxt); }
bool gate () { return gate_dominator (); }
unsigned int execute () { return tree_ssa_dominator_optimize (); }
@@ -1070,6 +1101,10 @@ simplify_stmt_for_jump_threading (gimple stmt,
return lookup_avail_expr (stmt, false);
}
+/* Record into the equivalence tables any equivalences implied by
+ traversing edge E (which are cached in E->aux).
+
+ Callers are responsible for managing the unwinding markers. */
static void
record_temporary_equivalences (edge e)
{
@@ -1102,8 +1137,8 @@ record_temporary_equivalences (edge e)
void
dom_opt_dom_walker::thread_across_edge (edge e)
{
- if (! dummy_cond_)
- dummy_cond_ =
+ if (! m_dummy_cond)
+ m_dummy_cond =
gimple_build_cond (NE_EXPR,
integer_zero_node, integer_zero_node,
NULL, NULL);
@@ -1118,7 +1153,7 @@ dom_opt_dom_walker::thread_across_edge (edge e)
/* With all the edge equivalences in the tables, go ahead and attempt
to thread through E->dest. */
- ::thread_across_edge (dummy_cond_, e, false,
+ ::thread_across_edge (m_dummy_cond, e, false,
&const_and_copies_stack,
simplify_stmt_for_jump_threading);
@@ -2584,42 +2619,6 @@ avail_expr_hash (const void *p)
/* PHI-ONLY copy and constant propagation. This pass is meant to clean
up degenerate PHIs created by or exposed by jump threading. */
-/* Given PHI, return its RHS if the PHI is a degenerate, otherwise return
- NULL. */
-
-tree
-degenerate_phi_result (gimple phi)
-{
- tree lhs = gimple_phi_result (phi);
- tree val = NULL;
- size_t i;
-
- /* Ignoring arguments which are the same as LHS, if all the remaining
- arguments are the same, then the PHI is a degenerate and has the
- value of that common argument. */
- for (i = 0; i < gimple_phi_num_args (phi); i++)
- {
- tree arg = gimple_phi_arg_def (phi, i);
-
- if (arg == lhs)
- continue;
- else if (!arg)
- break;
- else if (!val)
- val = arg;
- else if (arg == val)
- continue;
- /* We bring in some of operand_equal_p not only to speed things
- up, but also to avoid crashing when dereferencing the type of
- a released SSA name. */
- else if (TREE_CODE (val) != TREE_CODE (arg)
- || TREE_CODE (val) == SSA_NAME
- || !operand_equal_p (arg, val, 0))
- break;
- }
- return (i == gimple_phi_num_args (phi) ? val : NULL);
-}
-
/* Given a statement STMT, which is either a PHI node or an assignment,
remove it from the IL. */
@@ -3123,12 +3122,12 @@ const pass_data pass_data_phi_only_cprop =
class pass_phi_only_cprop : public gimple_opt_pass
{
public:
- pass_phi_only_cprop(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_phi_only_cprop, ctxt)
+ pass_phi_only_cprop (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_phi_only_cprop, ctxt)
{}
/* opt_pass methods: */
- opt_pass * clone () { return new pass_phi_only_cprop (ctxt_); }
+ opt_pass * clone () { return new pass_phi_only_cprop (m_ctxt); }
bool gate () { return gate_dominator (); }
unsigned int execute () { return eliminate_degenerate_phis (); }
diff --git a/gcc/tree-ssa-dom.h b/gcc/tree-ssa-dom.h
new file mode 100644
index 00000000000..0115f9323b7
--- /dev/null
+++ b/gcc/tree-ssa-dom.h
@@ -0,0 +1,28 @@
+/* Header file for SSA dominator optimizations.
+ Copyright (C) 2013 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_SSA_DOM_H
+#define GCC_TREE_SSA_DOM_H
+
+extern void dump_dominator_optimization_stats (FILE *);
+extern void debug_dominator_optimization_stats (void);
+extern int loop_depth_of_name (tree);
+extern bool simple_iv_increment_p (gimple);
+
+#endif /* GCC_TREE_SSA_DOM_H */
diff --git a/gcc/tree-ssa-dse.c b/gcc/tree-ssa-dse.c
index d0669504325..202eb3e673b 100644
--- a/gcc/tree-ssa-dse.c
+++ b/gcc/tree-ssa-dse.c
@@ -26,11 +26,19 @@ along with GCC; see the file COPYING3. If not see
#include "tm_p.h"
#include "basic-block.h"
#include "gimple-pretty-print.h"
-#include "tree-ssa.h"
+#include "bitmap.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-cfg.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
+#include "tree-dfa.h"
#include "tree-pass.h"
#include "domwalk.h"
#include "flags.h"
#include "langhooks.h"
+#include "tree-cfgcleanup.h"
/* This file implements dead store elimination.
@@ -375,12 +383,12 @@ const pass_data pass_data_dse =
class pass_dse : public gimple_opt_pass
{
public:
- pass_dse(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_dse, ctxt)
+ pass_dse (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_dse, ctxt)
{}
/* opt_pass methods: */
- opt_pass * clone () { return new pass_dse (ctxt_); }
+ opt_pass * clone () { return new pass_dse (m_ctxt); }
bool gate () { return gate_dse (); }
unsigned int execute () { return tree_ssa_dse (); }
diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c
index f1a407774fb..93b89704a2f 100644
--- a/gcc/tree-ssa-forwprop.c
+++ b/gcc/tree-ssa-forwprop.c
@@ -25,15 +25,21 @@ along with GCC; see the file COPYING3. If not see
#include "tm_p.h"
#include "basic-block.h"
#include "gimple-pretty-print.h"
-#include "tree-ssa.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-cfg.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
+#include "tree-dfa.h"
#include "tree-pass.h"
#include "langhooks.h"
#include "flags.h"
-#include "gimple.h"
#include "expr.h"
#include "cfgloop.h"
#include "optabs.h"
#include "tree-ssa-propagate.h"
+#include "tree-ssa-dom.h"
/* This pass propagates the RHS of assignment statements into use
sites of the LHS of the assignment. It's basically a specialized
@@ -161,7 +167,7 @@ along with GCC; see the file COPYING3. If not see
This will (of course) be extended as other needs arise. */
-static bool forward_propagate_addr_expr (tree name, tree rhs);
+static bool forward_propagate_addr_expr (tree, tree, bool);
/* Set to true if we delete dead edges during the optimization. */
static bool cfg_changed;
@@ -714,36 +720,45 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs,
rhs_code = gimple_assign_rhs_code (use_stmt);
rhs = gimple_assign_rhs1 (use_stmt);
- /* Trivial cases. The use statement could be a trivial copy or a
- useless conversion. Recurse to the uses of the lhs as copyprop does
- not copy through different variant pointers and FRE does not catch
- all useless conversions. Treat the case of a single-use name and
+ /* Do not perform copy-propagation but recurse through copy chains. */
+ if (TREE_CODE (lhs) == SSA_NAME
+ && rhs_code == SSA_NAME)
+ return forward_propagate_addr_expr (lhs, def_rhs, single_use_p);
+
+ /* The use statement could be a conversion. Recurse to the uses of the
+ lhs as copyprop does not copy through pointer to integer to pointer
+ conversions and FRE does not catch all cases either.
+ Treat the case of a single-use name and
a conversion to def_rhs type separate, though. */
if (TREE_CODE (lhs) == SSA_NAME
- && ((rhs_code == SSA_NAME && rhs == name)
- || CONVERT_EXPR_CODE_P (rhs_code)))
+ && CONVERT_EXPR_CODE_P (rhs_code))
{
- /* Only recurse if we don't deal with a single use or we cannot
- do the propagation to the current statement. In particular
- we can end up with a conversion needed for a non-invariant
- address which we cannot do in a single statement. */
- if (!single_use_p
- || (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (def_rhs))
- && (!is_gimple_min_invariant (def_rhs)
- || (INTEGRAL_TYPE_P (TREE_TYPE (lhs))
- && POINTER_TYPE_P (TREE_TYPE (def_rhs))
- && (TYPE_PRECISION (TREE_TYPE (lhs))
- > TYPE_PRECISION (TREE_TYPE (def_rhs)))))))
- return forward_propagate_addr_expr (lhs, def_rhs);
-
- gimple_assign_set_rhs1 (use_stmt, unshare_expr (def_rhs));
- if (useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (def_rhs)))
- gimple_assign_set_rhs_code (use_stmt, TREE_CODE (def_rhs));
- else
- gimple_assign_set_rhs_code (use_stmt, NOP_EXPR);
- return true;
+ /* If there is a point in a conversion chain where the types match
+ so we can remove a conversion re-materialize the address here
+ and stop. */
+ if (single_use_p
+ && useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (def_rhs)))
+ {
+ gimple_assign_set_rhs1 (use_stmt, unshare_expr (def_rhs));
+ gimple_assign_set_rhs_code (use_stmt, TREE_CODE (def_rhs));
+ return true;
+ }
+
+ /* Else recurse if the conversion preserves the address value. */
+ if ((INTEGRAL_TYPE_P (TREE_TYPE (lhs))
+ || POINTER_TYPE_P (TREE_TYPE (lhs)))
+ && (TYPE_PRECISION (TREE_TYPE (lhs))
+ >= TYPE_PRECISION (TREE_TYPE (def_rhs))))
+ return forward_propagate_addr_expr (lhs, def_rhs, single_use_p);
+
+ return false;
}
+ /* If this isn't a conversion chain from this on we only can propagate
+ into compatible pointer contexts. */
+ if (!types_compatible_p (TREE_TYPE (name), TREE_TYPE (def_rhs)))
+ return false;
+
/* Propagate through constant pointer adjustments. */
if (TREE_CODE (lhs) == SSA_NAME
&& rhs_code == POINTER_PLUS_EXPR
@@ -768,7 +783,7 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs,
/* Recurse. If we could propagate into all uses of lhs do not
bother to replace into the current use but just pretend we did. */
if (TREE_CODE (new_def_rhs) == ADDR_EXPR
- && forward_propagate_addr_expr (lhs, new_def_rhs))
+ && forward_propagate_addr_expr (lhs, new_def_rhs, single_use_p))
return true;
if (useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (new_def_rhs)))
@@ -996,16 +1011,20 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs,
Try to forward propagate the ADDR_EXPR into all uses of the SSA_NAME.
Often this will allow for removal of an ADDR_EXPR and INDIRECT_REF
node or for recovery of array indexing from pointer arithmetic.
+
+ PARENT_SINGLE_USE_P tells if, when in a recursive invocation, NAME was
+ the single use in the previous invocation. Pass true when calling
+ this as toplevel.
+
Returns true, if all uses have been propagated into. */
static bool
-forward_propagate_addr_expr (tree name, tree rhs)
+forward_propagate_addr_expr (tree name, tree rhs, bool parent_single_use_p)
{
- int stmt_loop_depth = bb_loop_depth (gimple_bb (SSA_NAME_DEF_STMT (name)));
imm_use_iterator iter;
gimple use_stmt;
bool all = true;
- bool single_use_p = has_single_use (name);
+ bool single_use_p = parent_single_use_p && has_single_use (name);
FOR_EACH_IMM_USE_STMT (use_stmt, iter, name)
{
@@ -1014,37 +1033,24 @@ forward_propagate_addr_expr (tree name, tree rhs)
/* If the use is not in a simple assignment statement, then
there is nothing we can do. */
- if (gimple_code (use_stmt) != GIMPLE_ASSIGN)
+ if (!is_gimple_assign (use_stmt))
{
if (!is_gimple_debug (use_stmt))
all = false;
continue;
}
- /* If the use is in a deeper loop nest, then we do not want
- to propagate non-invariant ADDR_EXPRs into the loop as that
- is likely adding expression evaluations into the loop. */
- if (bb_loop_depth (gimple_bb (use_stmt)) > stmt_loop_depth
- && !is_gimple_min_invariant (rhs))
+ gimple_stmt_iterator gsi = gsi_for_stmt (use_stmt);
+ result = forward_propagate_addr_expr_1 (name, rhs, &gsi,
+ single_use_p);
+ /* If the use has moved to a different statement adjust
+ the update machinery for the old statement too. */
+ if (use_stmt != gsi_stmt (gsi))
{
- all = false;
- continue;
+ update_stmt (use_stmt);
+ use_stmt = gsi_stmt (gsi);
}
-
- {
- gimple_stmt_iterator gsi = gsi_for_stmt (use_stmt);
- result = forward_propagate_addr_expr_1 (name, rhs, &gsi,
- single_use_p);
- /* If the use has moved to a different statement adjust
- the update machinery for the old statement too. */
- if (use_stmt != gsi_stmt (gsi))
- {
- update_stmt (use_stmt);
- use_stmt = gsi_stmt (gsi);
- }
-
- update_stmt (use_stmt);
- }
+ update_stmt (use_stmt);
all &= result;
/* Remove intermediate now unused copy and conversion chains. */
@@ -3191,9 +3197,9 @@ simplify_permutation (gimple_stmt_iterator *gsi)
return 0;
arg1 = arg0;
}
- opt = fold_ternary (VEC_PERM_EXPR, TREE_TYPE(op0), arg0, arg1, op2);
+ opt = fold_ternary (VEC_PERM_EXPR, TREE_TYPE (op0), arg0, arg1, op2);
if (!opt
- || (TREE_CODE (opt) != CONSTRUCTOR && TREE_CODE(opt) != VECTOR_CST))
+ || (TREE_CODE (opt) != CONSTRUCTOR && TREE_CODE (opt) != VECTOR_CST))
return 0;
gimple_assign_set_rhs_from_tree (gsi, opt);
update_stmt (gsi_stmt (*gsi));
@@ -3350,7 +3356,7 @@ ssa_forward_propagate_and_combine (void)
|| !DECL_P (base)
|| decl_address_invariant_p (base))
&& !stmt_references_abnormal_ssa_name (stmt)
- && forward_propagate_addr_expr (lhs, rhs))
+ && forward_propagate_addr_expr (lhs, rhs, true))
{
release_defs (stmt);
gsi_remove (&gsi, true);
@@ -3374,7 +3380,7 @@ ssa_forward_propagate_and_combine (void)
TREE_TYPE (TREE_TYPE (rhs)),
rhs,
fold_convert (ptr_type_node,
- off)))))
+ off))), true))
{
release_defs (stmt);
gsi_remove (&gsi, true);
@@ -3574,12 +3580,12 @@ const pass_data pass_data_forwprop =
class pass_forwprop : public gimple_opt_pass
{
public:
- pass_forwprop(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_forwprop, ctxt)
+ pass_forwprop (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_forwprop, ctxt)
{}
/* opt_pass methods: */
- opt_pass * clone () { return new pass_forwprop (ctxt_); }
+ opt_pass * clone () { return new pass_forwprop (m_ctxt); }
bool gate () { return gate_forwprop (); }
unsigned int execute () { return ssa_forward_propagate_and_combine (); }
diff --git a/gcc/tree-ssa-ifcombine.c b/gcc/tree-ssa-ifcombine.c
index c45d42a891d..73ebfe8b24e 100644
--- a/gcc/tree-ssa-ifcombine.c
+++ b/gcc/tree-ssa-ifcombine.c
@@ -22,12 +22,26 @@ along with GCC; see the file COPYING3. If not see
#include "system.h"
#include "coretypes.h"
#include "tm.h"
+/* rtl is needed only because arm back-end requires it for
+ BRANCH_COST. */
+#include "rtl.h"
+#include "tm_p.h"
#include "tree.h"
#include "basic-block.h"
#include "tree-pretty-print.h"
-#include "tree-ssa.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-cfg.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
#include "tree-pass.h"
+#ifndef LOGICAL_OP_NON_SHORT_CIRCUIT
+#define LOGICAL_OP_NON_SHORT_CIRCUIT \
+ (BRANCH_COST (optimize_function_for_speed_p (cfun), \
+ false) >= 2)
+#endif
+
/* This pass combines COND_EXPRs to simplify control flow. It
currently recognizes bit tests and comparisons in chains that
represent logical and or logical or of two COND_EXPRs.
@@ -484,7 +498,35 @@ ifcombine_ifandif (basic_block inner_cond_bb, bool inner_inv,
outer_cond_code,
gimple_cond_lhs (outer_cond),
gimple_cond_rhs (outer_cond))))
- return false;
+ {
+ tree t1, t2;
+ gimple_stmt_iterator gsi;
+ if (!LOGICAL_OP_NON_SHORT_CIRCUIT)
+ return false;
+ /* Only do this optimization if the inner bb contains only the conditional. */
+ if (!gsi_one_before_end_p (gsi_start_nondebug_after_labels_bb (inner_cond_bb)))
+ return false;
+ t1 = fold_build2_loc (gimple_location (inner_cond),
+ inner_cond_code,
+ boolean_type_node,
+ gimple_cond_lhs (inner_cond),
+ gimple_cond_rhs (inner_cond));
+ t2 = fold_build2_loc (gimple_location (outer_cond),
+ outer_cond_code,
+ boolean_type_node,
+ gimple_cond_lhs (outer_cond),
+ gimple_cond_rhs (outer_cond));
+ t = fold_build2_loc (gimple_location (inner_cond),
+ TRUTH_AND_EXPR, boolean_type_node, t1, t2);
+ if (result_inv)
+ {
+ t = fold_build1 (TRUTH_NOT_EXPR, TREE_TYPE (t), t);
+ result_inv = false;
+ }
+ gsi = gsi_for_stmt (inner_cond);
+ t = force_gimple_operand_gsi_1 (&gsi, t, is_gimple_condexpr, NULL, true,
+ GSI_SAME_STMT);
+ }
if (result_inv)
t = fold_build1 (TRUTH_NOT_EXPR, TREE_TYPE (t), t);
t = canonicalize_cond_expr_cond (t);
@@ -624,10 +666,18 @@ tree_ssa_ifcombine (void)
bool cfg_changed = false;
int i;
- bbs = blocks_in_phiopt_order ();
+ bbs = single_pred_before_succ_order ();
calculate_dominance_info (CDI_DOMINATORS);
- for (i = 0; i < n_basic_blocks - NUM_FIXED_BLOCKS; ++i)
+ /* Search every basic block for COND_EXPR we may be able to optimize.
+
+ We walk the blocks in order that guarantees that a block with
+ a single predecessor is processed after the predecessor.
+ This ensures that we collapse outter ifs before visiting the
+ inner ones, and also that we do not try to visit a removed
+ block. This is opposite of PHI-OPT, because we cascade the
+ combining rather than cascading PHIs. */
+ for (i = n_basic_blocks - NUM_FIXED_BLOCKS - 1; i >= 0; i--)
{
basic_block bb = bbs[i];
gimple stmt = last_stmt (bb);
@@ -668,8 +718,8 @@ const pass_data pass_data_tree_ifcombine =
class pass_tree_ifcombine : public gimple_opt_pass
{
public:
- pass_tree_ifcombine(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_tree_ifcombine, ctxt)
+ pass_tree_ifcombine (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_tree_ifcombine, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/tree-ssa-live.c b/gcc/tree-ssa-live.c
index c21b2e87441..17849a21159 100644
--- a/gcc/tree-ssa-live.c
+++ b/gcc/tree-ssa-live.c
@@ -26,14 +26,19 @@ along with GCC; see the file COPYING3. If not see
#include "tree.h"
#include "gimple-pretty-print.h"
#include "bitmap.h"
-#include "tree-ssa.h"
+#include "sbitmap.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
+#include "tree-dfa.h"
#include "timevar.h"
#include "dumpfile.h"
#include "tree-ssa-live.h"
#include "diagnostic-core.h"
#include "debug.h"
#include "flags.h"
-#include "gimple.h"
#ifdef ENABLE_CHECKING
static void verify_live_on_entry (tree_live_info_p);
@@ -104,7 +109,9 @@ var_map_base_init (var_map map)
struct tree_int_map **slot;
unsigned baseindex;
var = partition_to_var (map, x);
- if (SSA_NAME_VAR (var))
+ if (SSA_NAME_VAR (var)
+ && (!VAR_P (SSA_NAME_VAR (var))
+ || !DECL_IGNORED_P (SSA_NAME_VAR (var))))
m->base.from = SSA_NAME_VAR (var);
else
/* This restricts what anonymous SSA names we can coalesce
@@ -990,9 +997,10 @@ loe_visit_block (tree_live_info_p live, basic_block bb, sbitmap visited,
edge_iterator ei;
basic_block pred_bb;
bitmap loe;
- gcc_assert (!bitmap_bit_p (visited, bb->index));
+ gcc_checking_assert (!bitmap_bit_p (visited, bb->index));
bitmap_set_bit (visited, bb->index);
+
loe = live_on_entry (live, bb);
FOR_EACH_EDGE (e, ei, bb->preds)
@@ -1234,7 +1242,7 @@ dump_var_map (FILE *f, var_map map)
{
if (t++ == 0)
{
- fprintf(f, "Partition %d (", x);
+ fprintf (f, "Partition %d (", x);
print_generic_expr (f, partition_to_var (map, p), TDF_SLIM);
fprintf (f, " - ");
}
diff --git a/gcc/tree-ssa-live.h b/gcc/tree-ssa-live.h
index 8fd1e80d549..0aa9f0c4331 100644
--- a/gcc/tree-ssa-live.h
+++ b/gcc/tree-ssa-live.h
@@ -70,12 +70,16 @@ typedef struct _var_map
extern var_map init_var_map (int);
extern void delete_var_map (var_map);
-extern void dump_var_map (FILE *, var_map);
-extern void debug (_var_map &ref);
-extern void debug (_var_map *ptr);
extern int var_union (var_map, tree, tree);
extern void partition_view_normal (var_map, bool);
extern void partition_view_bitmap (var_map, bitmap, bool);
+extern void dump_scope_blocks (FILE *, int);
+extern void debug_scope_block (tree, int);
+extern void debug_scope_blocks (int);
+extern void remove_unused_locals (void);
+extern void dump_var_map (FILE *, var_map);
+extern void debug (_var_map &ref);
+extern void debug (_var_map *ptr);
#ifdef ENABLE_CHECKING
extern void register_ssa_partition_check (tree ssa_var);
#endif
@@ -241,16 +245,15 @@ typedef struct tree_live_info_d
} *tree_live_info_p;
-extern tree_live_info_p calculate_live_ranges (var_map);
-extern void calculate_live_on_exit (tree_live_info_p);
-extern void delete_tree_live_info (tree_live_info_p);
-
#define LIVEDUMP_ENTRY 0x01
#define LIVEDUMP_EXIT 0x02
#define LIVEDUMP_ALL (LIVEDUMP_ENTRY | LIVEDUMP_EXIT)
-extern void dump_live_info (FILE *, tree_live_info_p, int);
+extern void delete_tree_live_info (tree_live_info_p);
+extern void calculate_live_on_exit (tree_live_info_p);
+extern tree_live_info_p calculate_live_ranges (var_map);
extern void debug (tree_live_info_d &ref);
extern void debug (tree_live_info_d *ptr);
+extern void dump_live_info (FILE *, tree_live_info_p, int);
/* Return TRUE if P is marked as a global in LIVE. */
@@ -321,14 +324,4 @@ make_live_on_entry (tree_live_info_p live, basic_block bb , int p)
bitmap_set_bit (live->global, p);
}
-
-/* From tree-ssa-coalesce.c */
-extern var_map coalesce_ssa_name (void);
-
-
-/* From tree-ssa-ter.c */
-extern bitmap find_replaceable_exprs (var_map);
-extern void dump_replaceable_exprs (FILE *, bitmap);
-
-
#endif /* _TREE_SSA_LIVE_H */
diff --git a/gcc/tree-ssa-loop-ch.c b/gcc/tree-ssa-loop-ch.c
index 0e87770b5b6..b74c56de330 100644
--- a/gcc/tree-ssa-loop-ch.c
+++ b/gcc/tree-ssa-loop-ch.c
@@ -24,12 +24,15 @@ along with GCC; see the file COPYING3. If not see
#include "tree.h"
#include "tm_p.h"
#include "basic-block.h"
-#include "tree-ssa.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-cfg.h"
+#include "tree-into-ssa.h"
#include "tree-pass.h"
#include "cfgloop.h"
#include "tree-inline.h"
#include "flags.h"
-#include "tree-inline.h"
+#include "tree-ssa-threadedge.h"
/* Duplicates headers of loops if they are small enough, so that the statements
in the loop body are always executed when the loop is entered. This
@@ -100,7 +103,7 @@ should_duplicate_loop_header_p (basic_block header, struct loop *loop,
/* Checks whether LOOP is a do-while style loop. */
-bool
+static bool
do_while_loop_p (struct loop *loop)
{
gimple stmt = last_stmt (loop->latch);
@@ -277,8 +280,8 @@ const pass_data pass_data_ch =
class pass_ch : public gimple_opt_pass
{
public:
- pass_ch(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_ch, ctxt)
+ pass_ch (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_ch, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c
index c12ed7fb590..2283b5b4dd7 100644
--- a/gcc/tree-ssa-loop-im.c
+++ b/gcc/tree-ssa-loop-im.c
@@ -25,7 +25,15 @@ along with GCC; see the file COPYING3. If not see
#include "tm_p.h"
#include "basic-block.h"
#include "gimple-pretty-print.h"
-#include "tree-ssa.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-cfg.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
+#include "tree-ssa-loop-manip.h"
+#include "tree-ssa-loop.h"
+#include "tree-into-ssa.h"
#include "cfgloop.h"
#include "domwalk.h"
#include "params.h"
@@ -227,7 +235,7 @@ get_lim_data (gimple stmt)
static void
free_lim_aux_data (struct lim_aux_data *data)
{
- data->depends.release();
+ data->depends.release ();
free (data);
}
@@ -242,98 +250,16 @@ clear_lim_data (gimple stmt)
*p = NULL;
}
-/* Calls CBCK for each index in memory reference ADDR_P. There are two
- kinds situations handled; in each of these cases, the memory reference
- and DATA are passed to the callback:
- Access to an array: ARRAY_{RANGE_}REF (base, index). In this case we also
- pass the pointer to the index to the callback.
-
- Pointer dereference: INDIRECT_REF (addr). In this case we also pass the
- pointer to addr to the callback.
-
- If the callback returns false, the whole search stops and false is returned.
- Otherwise the function returns true after traversing through the whole
- reference *ADDR_P. */
-
-bool
-for_each_index (tree *addr_p, bool (*cbck) (tree, tree *, void *), void *data)
-{
- tree *nxt, *idx;
-
- for (; ; addr_p = nxt)
- {
- switch (TREE_CODE (*addr_p))
- {
- case SSA_NAME:
- return cbck (*addr_p, addr_p, data);
-
- case MEM_REF:
- nxt = &TREE_OPERAND (*addr_p, 0);
- return cbck (*addr_p, nxt, data);
-
- case BIT_FIELD_REF:
- case VIEW_CONVERT_EXPR:
- case REALPART_EXPR:
- case IMAGPART_EXPR:
- nxt = &TREE_OPERAND (*addr_p, 0);
- break;
-
- case COMPONENT_REF:
- /* If the component has varying offset, it behaves like index
- as well. */
- idx = &TREE_OPERAND (*addr_p, 2);
- if (*idx
- && !cbck (*addr_p, idx, data))
- return false;
-
- nxt = &TREE_OPERAND (*addr_p, 0);
- break;
-
- case ARRAY_REF:
- case ARRAY_RANGE_REF:
- nxt = &TREE_OPERAND (*addr_p, 0);
- if (!cbck (*addr_p, &TREE_OPERAND (*addr_p, 1), data))
- return false;
- break;
-
- case VAR_DECL:
- case PARM_DECL:
- case CONST_DECL:
- case STRING_CST:
- case RESULT_DECL:
- case VECTOR_CST:
- case COMPLEX_CST:
- case INTEGER_CST:
- case REAL_CST:
- case FIXED_CST:
- case CONSTRUCTOR:
- return true;
-
- case ADDR_EXPR:
- gcc_assert (is_gimple_min_invariant (*addr_p));
- return true;
-
- case TARGET_MEM_REF:
- idx = &TMR_BASE (*addr_p);
- if (*idx
- && !cbck (*addr_p, idx, data))
- return false;
- idx = &TMR_INDEX (*addr_p);
- if (*idx
- && !cbck (*addr_p, idx, data))
- return false;
- idx = &TMR_INDEX2 (*addr_p);
- if (*idx
- && !cbck (*addr_p, idx, data))
- return false;
- return true;
+/* The possibilities of statement movement. */
+enum move_pos
+ {
+ MOVE_IMPOSSIBLE, /* No movement -- side effect expression. */
+ MOVE_PRESERVE_EXECUTION, /* Must not cause the non-executed statement
+ become executed -- memory accesses, ... */
+ MOVE_POSSIBLE /* Unlimited movement. */
+ };
- default:
- gcc_unreachable ();
- }
- }
-}
/* If it is possible to hoist the statement STMT unconditionally,
returns MOVE_POSSIBLE.
@@ -1199,6 +1125,67 @@ public:
unsigned int todo_;
};
+/* Return true if CODE is an operation that when operating on signed
+ integer types involves undefined behavior on overflow and the
+ operation can be expressed with unsigned arithmetic. */
+
+static bool
+arith_code_with_undefined_signed_overflow (tree_code code)
+{
+ switch (code)
+ {
+ case PLUS_EXPR:
+ case MINUS_EXPR:
+ case MULT_EXPR:
+ case NEGATE_EXPR:
+ case POINTER_PLUS_EXPR:
+ return true;
+ default:
+ return false;
+ }
+}
+
+/* Rewrite STMT, an assignment with a signed integer or pointer arithmetic
+ operation that can be transformed to unsigned arithmetic by converting
+ its operand, carrying out the operation in the corresponding unsigned
+ type and converting the result back to the original type.
+
+ Returns a sequence of statements that replace STMT and also contain
+ a modified form of STMT itself. */
+
+static gimple_seq
+rewrite_to_defined_overflow (gimple stmt)
+{
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "rewriting stmt with undefined signed "
+ "overflow ");
+ print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
+ }
+
+ tree lhs = gimple_assign_lhs (stmt);
+ tree type = unsigned_type_for (TREE_TYPE (lhs));
+ gimple_seq stmts = NULL;
+ for (unsigned i = 1; i < gimple_num_ops (stmt); ++i)
+ {
+ gimple_seq stmts2 = NULL;
+ gimple_set_op (stmt, i,
+ force_gimple_operand (fold_convert (type,
+ gimple_op (stmt, i)),
+ &stmts2, true, NULL_TREE));
+ gimple_seq_add_seq (&stmts, stmts2);
+ }
+ gimple_assign_set_lhs (stmt, make_ssa_name (type, stmt));
+ if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
+ gimple_assign_set_rhs_code (stmt, PLUS_EXPR);
+ gimple_seq_add_stmt (&stmts, stmt);
+ gimple cvt = gimple_build_assign_with_ops
+ (NOP_EXPR, lhs, gimple_assign_lhs (stmt), NULL_TREE);
+ gimple_seq_add_stmt (&stmts, cvt);
+
+ return stmts;
+}
+
/* Hoist the statements in basic block BB out of the loops prescribed by
data stored in LIM_DATA structures associated with each statement. Callback
for walk_dominator_tree. */
@@ -1251,7 +1238,6 @@ move_computations_dom_walker::before_dom_children (basic_block bb)
new_stmt = gimple_build_assign_with_ops (TREE_CODE (arg),
gimple_phi_result (stmt),
arg, NULL_TREE);
- SSA_NAME_DEF_STMT (gimple_phi_result (stmt)) = new_stmt;
}
else
{
@@ -1267,7 +1253,6 @@ move_computations_dom_walker::before_dom_children (basic_block bb)
new_stmt = gimple_build_assign_with_ops (COND_EXPR,
gimple_phi_result (stmt),
t, arg0, arg1);
- SSA_NAME_DEF_STMT (gimple_phi_result (stmt)) = new_stmt;
todo_ |= TODO_cleanup_cfg;
}
gsi_insert_on_edge (loop_preheader_edge (level), new_stmt);
@@ -1329,7 +1314,21 @@ move_computations_dom_walker::before_dom_children (basic_block bb)
}
}
gsi_remove (&bsi, false);
- gsi_insert_on_edge (e, stmt);
+ /* In case this is a stmt that is not unconditionally executed
+ when the target loop header is executed and the stmt may
+ invoke undefined integer or pointer overflow rewrite it to
+ unsigned arithmetic. */
+ if (is_gimple_assign (stmt)
+ && INTEGRAL_TYPE_P (TREE_TYPE (gimple_assign_lhs (stmt)))
+ && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (gimple_assign_lhs (stmt)))
+ && arith_code_with_undefined_signed_overflow
+ (gimple_assign_rhs_code (stmt))
+ && (!ALWAYS_EXECUTED_IN (bb)
+ || !(ALWAYS_EXECUTED_IN (bb) == level
+ || flow_loop_nested_p (ALWAYS_EXECUTED_IN (bb), level))))
+ gsi_insert_seq_on_edge (e, rewrite_to_defined_overflow (stmt));
+ else
+ gsi_insert_on_edge (e, stmt);
}
}
@@ -1695,12 +1694,12 @@ for_all_locs_in_loop (struct loop *loop, mem_ref_p ref, FN fn)
struct rewrite_mem_ref_loc
{
rewrite_mem_ref_loc (tree tmp_var_) : tmp_var (tmp_var_) {}
- bool operator()(mem_ref_loc_p loc);
+ bool operator () (mem_ref_loc_p loc);
tree tmp_var;
};
bool
-rewrite_mem_ref_loc::operator()(mem_ref_loc_p loc)
+rewrite_mem_ref_loc::operator () (mem_ref_loc_p loc)
{
*loc->ref = tmp_var;
update_stmt (loc->stmt);
@@ -1720,12 +1719,12 @@ rewrite_mem_refs (struct loop *loop, mem_ref_p ref, tree tmp_var)
struct first_mem_ref_loc_1
{
first_mem_ref_loc_1 (mem_ref_loc_p *locp_) : locp (locp_) {}
- bool operator()(mem_ref_loc_p loc);
+ bool operator () (mem_ref_loc_p loc);
mem_ref_loc_p *locp;
};
bool
-first_mem_ref_loc_1::operator()(mem_ref_loc_p loc)
+first_mem_ref_loc_1::operator () (mem_ref_loc_p loc)
{
*locp = loc;
return true;
@@ -1741,122 +1740,6 @@ first_mem_ref_loc (struct loop *loop, mem_ref_p ref)
return locp;
}
-/* The name and the length of the currently generated variable
- for lsm. */
-#define MAX_LSM_NAME_LENGTH 40
-static char lsm_tmp_name[MAX_LSM_NAME_LENGTH + 1];
-static int lsm_tmp_name_length;
-
-/* Adds S to lsm_tmp_name. */
-
-static void
-lsm_tmp_name_add (const char *s)
-{
- int l = strlen (s) + lsm_tmp_name_length;
- if (l > MAX_LSM_NAME_LENGTH)
- return;
-
- strcpy (lsm_tmp_name + lsm_tmp_name_length, s);
- lsm_tmp_name_length = l;
-}
-
-/* Stores the name for temporary variable that replaces REF to
- lsm_tmp_name. */
-
-static void
-gen_lsm_tmp_name (tree ref)
-{
- const char *name;
-
- switch (TREE_CODE (ref))
- {
- case MEM_REF:
- case TARGET_MEM_REF:
- gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
- lsm_tmp_name_add ("_");
- break;
-
- case ADDR_EXPR:
- gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
- break;
-
- case BIT_FIELD_REF:
- case VIEW_CONVERT_EXPR:
- case ARRAY_RANGE_REF:
- gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
- break;
-
- case REALPART_EXPR:
- gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
- lsm_tmp_name_add ("_RE");
- break;
-
- case IMAGPART_EXPR:
- gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
- lsm_tmp_name_add ("_IM");
- break;
-
- case COMPONENT_REF:
- gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
- lsm_tmp_name_add ("_");
- name = get_name (TREE_OPERAND (ref, 1));
- if (!name)
- name = "F";
- lsm_tmp_name_add (name);
- break;
-
- case ARRAY_REF:
- gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
- lsm_tmp_name_add ("_I");
- break;
-
- case SSA_NAME:
- case VAR_DECL:
- case PARM_DECL:
- name = get_name (ref);
- if (!name)
- name = "D";
- lsm_tmp_name_add (name);
- break;
-
- case STRING_CST:
- lsm_tmp_name_add ("S");
- break;
-
- case RESULT_DECL:
- lsm_tmp_name_add ("R");
- break;
-
- case INTEGER_CST:
- /* Nothing. */
- break;
-
- default:
- gcc_unreachable ();
- }
-}
-
-/* Determines name for temporary variable that replaces REF.
- The name is accumulated into the lsm_tmp_name variable.
- N is added to the name of the temporary. */
-
-char *
-get_lsm_tmp_name (tree ref, unsigned n)
-{
- char ns[2];
-
- lsm_tmp_name_length = 0;
- gen_lsm_tmp_name (ref);
- lsm_tmp_name_add ("_lsm");
- if (n < 10)
- {
- ns[0] = '0' + n;
- ns[1] = 0;
- lsm_tmp_name_add (ns);
- }
- return lsm_tmp_name;
-}
-
struct prev_flag_edges {
/* Edge to insert new flag comparison code. */
edge append_cond_position;
@@ -2001,12 +1884,12 @@ execute_sm_if_changed (edge ex, tree mem, tree tmp_var, tree flag)
struct sm_set_flag_if_changed
{
sm_set_flag_if_changed (tree flag_) : flag (flag_) {}
- bool operator()(mem_ref_loc_p loc);
+ bool operator () (mem_ref_loc_p loc);
tree flag;
};
bool
-sm_set_flag_if_changed::operator()(mem_ref_loc_p loc)
+sm_set_flag_if_changed::operator () (mem_ref_loc_p loc)
{
/* Only set the flag for writes. */
if (is_gimple_assign (loc->stmt)
@@ -2026,8 +1909,7 @@ static tree
execute_sm_if_changed_flag_set (struct loop *loop, mem_ref_p ref)
{
tree flag;
- char *str = get_lsm_tmp_name (ref->mem.ref, ~0);
- lsm_tmp_name_add ("_flag");
+ char *str = get_lsm_tmp_name (ref->mem.ref, ~0, "_flag");
flag = create_tmp_reg (boolean_type_node, str);
for_all_locs_in_loop (loop, ref, sm_set_flag_if_changed (flag));
return flag;
@@ -2064,7 +1946,7 @@ execute_sm (struct loop *loop, vec<edge> exits, mem_ref_p ref)
fmt_data.orig_loop = loop;
for_each_index (&ref->mem.ref, force_move_till, &fmt_data);
- if (block_in_transaction (loop_preheader_edge (loop)->src)
+ if (bb_in_transaction (loop_preheader_edge (loop)->src)
|| !PARAM_VALUE (PARAM_ALLOW_STORE_DATA_RACES))
multi_threaded_model_p = true;
@@ -2130,14 +2012,14 @@ struct ref_always_accessed
{
ref_always_accessed (struct loop *loop_, tree base_, bool stored_p_)
: loop (loop_), base (base_), stored_p (stored_p_) {}
- bool operator()(mem_ref_loc_p loc);
+ bool operator () (mem_ref_loc_p loc);
struct loop *loop;
tree base;
bool stored_p;
};
bool
-ref_always_accessed::operator()(mem_ref_loc_p loc)
+ref_always_accessed::operator () (mem_ref_loc_p loc)
{
struct loop *must_exec;
@@ -2639,3 +2521,61 @@ tree_ssa_lim (void)
return todo;
}
+
+/* Loop invariant motion pass. */
+
+static unsigned int
+tree_ssa_loop_im (void)
+{
+ if (number_of_loops (cfun) <= 1)
+ return 0;
+
+ return tree_ssa_lim ();
+}
+
+static bool
+gate_tree_ssa_loop_im (void)
+{
+ return flag_tree_loop_im != 0;
+}
+
+namespace {
+
+const pass_data pass_data_lim =
+{
+ GIMPLE_PASS, /* type */
+ "lim", /* name */
+ OPTGROUP_LOOP, /* optinfo_flags */
+ true, /* has_gate */
+ true, /* has_execute */
+ TV_LIM, /* tv_id */
+ PROP_cfg, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ 0, /* todo_flags_finish */
+};
+
+class pass_lim : public gimple_opt_pass
+{
+public:
+ pass_lim (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_lim, ctxt)
+ {}
+
+ /* opt_pass methods: */
+ opt_pass * clone () { return new pass_lim (m_ctxt); }
+ bool gate () { return gate_tree_ssa_loop_im (); }
+ unsigned int execute () { return tree_ssa_loop_im (); }
+
+}; // class pass_lim
+
+} // anon namespace
+
+gimple_opt_pass *
+make_pass_lim (gcc::context *ctxt)
+{
+ return new pass_lim (ctxt);
+}
+
+
diff --git a/gcc/tree-ssa-loop-ivcanon.c b/gcc/tree-ssa-loop-ivcanon.c
index d5249baeab0..6f8f04e457e 100644
--- a/gcc/tree-ssa-loop-ivcanon.c
+++ b/gcc/tree-ssa-loop-ivcanon.c
@@ -40,7 +40,17 @@ along with GCC; see the file COPYING3. If not see
#include "tm_p.h"
#include "basic-block.h"
#include "gimple-pretty-print.h"
-#include "tree-ssa.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "cgraph.h"
+#include "tree-cfg.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
+#include "tree-ssa-loop-manip.h"
+#include "tree-ssa-loop-niter.h"
+#include "tree-ssa-loop.h"
+#include "tree-into-ssa.h"
#include "cfgloop.h"
#include "tree-pass.h"
#include "tree-chrec.h"
@@ -49,6 +59,7 @@ along with GCC; see the file COPYING3. If not see
#include "flags.h"
#include "tree-inline.h"
#include "target.h"
+#include "tree-cfgcleanup.h"
/* Specifies types of loops that may be unrolled. */
@@ -107,23 +118,6 @@ create_canonical_iv (struct loop *loop, edge exit, tree niter)
update_stmt (cond);
}
-/* Computes an estimated number of insns in LOOP, weighted by WEIGHTS. */
-
-unsigned
-tree_num_loop_insns (struct loop *loop, eni_weights *weights)
-{
- basic_block *body = get_loop_body (loop);
- gimple_stmt_iterator gsi;
- unsigned size = 0, i;
-
- for (i = 0; i < loop->num_nodes; i++)
- for (gsi = gsi_start_bb (body[i]); !gsi_end_p (gsi); gsi_next (&gsi))
- size += estimate_num_insns (gsi_stmt (gsi), weights);
- free (body);
-
- return size;
-}
-
/* Describe size of loop as detected by tree_estimate_loop_size. */
struct loop_size
{
@@ -422,7 +416,7 @@ estimated_unrolled_size (struct loop_size *size,
loop-niter identified as having undefined effect in the last iteration.
The other cases are hopefully rare and will be cleaned up later. */
-edge
+static edge
loop_edge_to_cancel (struct loop *loop)
{
vec<edge> exits;
@@ -598,7 +592,7 @@ static vec<int> loops_to_unloop_nunroll;
LOOP_CLOSED_SSA_INVALIDATED is used to bookkepp the case
when we need to go into loop closed SSA form. */
-void
+static void
unloop_loops (bitmap loop_closed_ssa_invalidated,
bool *irred_invalidated)
{
@@ -1106,7 +1100,7 @@ propagate_constants_for_unrolling (basic_block bb)
static bool
tree_unroll_loops_completely_1 (bool may_increase_size, bool unroll_outer,
- vec<loop_p, va_stack>& father_stack,
+ vec<loop_p, va_heap>& father_stack,
struct loop *loop)
{
struct loop *loop_father;
@@ -1170,12 +1164,11 @@ tree_unroll_loops_completely_1 (bool may_increase_size, bool unroll_outer,
unsigned int
tree_unroll_loops_completely (bool may_increase_size, bool unroll_outer)
{
- vec<loop_p, va_stack> father_stack;
+ stack_vec<loop_p, 16> father_stack;
bool changed;
int iteration = 0;
bool irred_invalidated = false;
- vec_stack_alloc (loop_p, father_stack, 16);
do
{
changed = false;
@@ -1253,3 +1246,182 @@ tree_unroll_loops_completely (bool may_increase_size, bool unroll_outer)
return 0;
}
+
+/* Canonical induction variable creation pass. */
+
+static unsigned int
+tree_ssa_loop_ivcanon (void)
+{
+ if (number_of_loops (cfun) <= 1)
+ return 0;
+
+ return canonicalize_induction_variables ();
+}
+
+static bool
+gate_tree_ssa_loop_ivcanon (void)
+{
+ return flag_tree_loop_ivcanon != 0;
+}
+
+namespace {
+
+const pass_data pass_data_iv_canon =
+{
+ GIMPLE_PASS, /* type */
+ "ivcanon", /* name */
+ OPTGROUP_LOOP, /* optinfo_flags */
+ true, /* has_gate */
+ true, /* has_execute */
+ TV_TREE_LOOP_IVCANON, /* tv_id */
+ ( PROP_cfg | PROP_ssa ), /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ 0, /* todo_flags_finish */
+};
+
+class pass_iv_canon : public gimple_opt_pass
+{
+public:
+ pass_iv_canon (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_iv_canon, ctxt)
+ {}
+
+ /* opt_pass methods: */
+ bool gate () { return gate_tree_ssa_loop_ivcanon (); }
+ unsigned int execute () { return tree_ssa_loop_ivcanon (); }
+
+}; // class pass_iv_canon
+
+} // anon namespace
+
+gimple_opt_pass *
+make_pass_iv_canon (gcc::context *ctxt)
+{
+ return new pass_iv_canon (ctxt);
+}
+
+/* Complete unrolling of loops. */
+
+static unsigned int
+tree_complete_unroll (void)
+{
+ if (number_of_loops (cfun) <= 1)
+ return 0;
+
+ return tree_unroll_loops_completely (flag_unroll_loops
+ || flag_peel_loops
+ || optimize >= 3, true);
+}
+
+static bool
+gate_tree_complete_unroll (void)
+{
+ return true;
+}
+
+namespace {
+
+const pass_data pass_data_complete_unroll =
+{
+ GIMPLE_PASS, /* type */
+ "cunroll", /* name */
+ OPTGROUP_LOOP, /* optinfo_flags */
+ true, /* has_gate */
+ true, /* has_execute */
+ TV_COMPLETE_UNROLL, /* tv_id */
+ ( PROP_cfg | PROP_ssa ), /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ 0, /* todo_flags_finish */
+};
+
+class pass_complete_unroll : public gimple_opt_pass
+{
+public:
+ pass_complete_unroll (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_complete_unroll, ctxt)
+ {}
+
+ /* opt_pass methods: */
+ bool gate () { return gate_tree_complete_unroll (); }
+ unsigned int execute () { return tree_complete_unroll (); }
+
+}; // class pass_complete_unroll
+
+} // anon namespace
+
+gimple_opt_pass *
+make_pass_complete_unroll (gcc::context *ctxt)
+{
+ return new pass_complete_unroll (ctxt);
+}
+
+/* Complete unrolling of inner loops. */
+
+static unsigned int
+tree_complete_unroll_inner (void)
+{
+ unsigned ret = 0;
+
+ loop_optimizer_init (LOOPS_NORMAL
+ | LOOPS_HAVE_RECORDED_EXITS);
+ if (number_of_loops (cfun) > 1)
+ {
+ scev_initialize ();
+ ret = tree_unroll_loops_completely (optimize >= 3, false);
+ free_numbers_of_iterations_estimates ();
+ scev_finalize ();
+ }
+ loop_optimizer_finalize ();
+
+ return ret;
+}
+
+static bool
+gate_tree_complete_unroll_inner (void)
+{
+ return optimize >= 2;
+}
+
+namespace {
+
+const pass_data pass_data_complete_unrolli =
+{
+ GIMPLE_PASS, /* type */
+ "cunrolli", /* name */
+ OPTGROUP_LOOP, /* optinfo_flags */
+ true, /* has_gate */
+ true, /* has_execute */
+ TV_COMPLETE_UNROLL, /* tv_id */
+ ( PROP_cfg | PROP_ssa ), /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ TODO_verify_flow, /* todo_flags_finish */
+};
+
+class pass_complete_unrolli : public gimple_opt_pass
+{
+public:
+ pass_complete_unrolli (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_complete_unrolli, ctxt)
+ {}
+
+ /* opt_pass methods: */
+ bool gate () { return gate_tree_complete_unroll_inner (); }
+ unsigned int execute () { return tree_complete_unroll_inner (); }
+
+}; // class pass_complete_unrolli
+
+} // anon namespace
+
+gimple_opt_pass *
+make_pass_complete_unrolli (gcc::context *ctxt)
+{
+ return new pass_complete_unrolli (ctxt);
+}
+
+
diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c
index 5f80ce007c8..d024bb4c395 100644
--- a/gcc/tree-ssa-loop-ivopts.c
+++ b/gcc/tree-ssa-loop-ivopts.c
@@ -69,6 +69,18 @@ along with GCC; see the file COPYING3. If not see
#include "tm_p.h"
#include "basic-block.h"
#include "gimple-pretty-print.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "cgraph.h"
+#include "tree-cfg.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
+#include "tree-ssa-loop-ivopts.h"
+#include "tree-ssa-loop-manip.h"
+#include "tree-ssa-loop-niter.h"
+#include "tree-ssa-loop.h"
+#include "tree-dfa.h"
#include "tree-ssa.h"
#include "cfgloop.h"
#include "tree-pass.h"
@@ -86,6 +98,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-inline.h"
#include "tree-ssa-propagate.h"
#include "expmed.h"
+#include "tree-ssa-address.h"
/* FIXME: Expressions are expanded to RTL in this pass to determine the
cost of different addressing modes. This should be moved to a TBD
@@ -452,7 +465,6 @@ single_dom_exit (struct loop *loop)
/* Dumps information about the induction variable IV to FILE. */
-extern void dump_iv (FILE *, struct iv *);
void
dump_iv (FILE *file, struct iv *iv)
{
@@ -497,7 +509,6 @@ dump_iv (FILE *file, struct iv *iv)
/* Dumps information about the USE to FILE. */
-extern void dump_use (FILE *, struct iv_use *);
void
dump_use (FILE *file, struct iv_use *use)
{
@@ -541,7 +552,6 @@ dump_use (FILE *file, struct iv_use *use)
/* Dumps information about the uses to FILE. */
-extern void dump_uses (FILE *, struct ivopts_data *);
void
dump_uses (FILE *file, struct ivopts_data *data)
{
@@ -559,7 +569,6 @@ dump_uses (FILE *file, struct ivopts_data *data)
/* Dumps information about induction variable candidate CAND to FILE. */
-extern void dump_cand (FILE *, struct iv_cand *);
void
dump_cand (FILE *file, struct iv_cand *cand)
{
@@ -915,11 +924,30 @@ determine_base_object (tree expr)
static struct iv *
alloc_iv (tree base, tree step)
{
+ tree base_object = base;
struct iv *iv = XCNEW (struct iv);
gcc_assert (step != NULL_TREE);
+ /* Lower all address expressions except ones with DECL_P as operand.
+ By doing this:
+ 1) More accurate cost can be computed for address expressions;
+ 2) Duplicate candidates won't be created for bases in different
+ forms, like &a[0] and &a. */
+ STRIP_NOPS (base_object);
+ if (TREE_CODE (base_object) == ADDR_EXPR
+ && !DECL_P (TREE_OPERAND (base_object, 0)))
+ {
+ aff_tree comb;
+ double_int size;
+ base_object = get_inner_reference_aff (TREE_OPERAND (base_object, 0),
+ &comb, &size);
+ gcc_assert (base_object != NULL_TREE);
+ base_object = build_fold_addr_expr (base_object);
+ base = fold_convert (TREE_TYPE (base), aff_combination_to_tree (&comb));
+ }
+
iv->base = base;
- iv->base_object = determine_base_object (base);
+ iv->base_object = determine_base_object (base_object);
iv->step = step;
iv->biv_p = false;
iv->have_use_for = false;
@@ -1454,29 +1482,6 @@ expr_invariant_in_loop_p (struct loop *loop, tree expr)
return true;
}
-/* Returns true if statement STMT is obviously invariant in LOOP,
- i.e. if all its operands on the RHS are defined outside of the LOOP.
- LOOP should not be the function body. */
-
-bool
-stmt_invariant_in_loop_p (struct loop *loop, gimple stmt)
-{
- unsigned i;
- tree lhs;
-
- gcc_assert (loop_depth (loop) > 0);
-
- lhs = gimple_get_lhs (stmt);
- for (i = 0; i < gimple_num_ops (stmt); i++)
- {
- tree op = gimple_op (stmt, i);
- if (op != lhs && !expr_invariant_in_loop_p (loop, op))
- return false;
- }
-
- return true;
-}
-
/* Cumulates the steps of indices into DATA and replaces their values with the
initial ones. Returns false when the value of the index cannot be determined.
Callback for for_each_index. */
@@ -2037,12 +2042,12 @@ find_interesting_uses (struct ivopts_data *data)
static tree
strip_offset_1 (tree expr, bool inside_addr, bool top_compref,
- unsigned HOST_WIDE_INT *offset)
+ HOST_WIDE_INT *offset)
{
tree op0 = NULL_TREE, op1 = NULL_TREE, tmp, step;
enum tree_code code;
tree type, orig_type = TREE_TYPE (expr);
- unsigned HOST_WIDE_INT off0, off1, st;
+ HOST_WIDE_INT off0, off1, st;
tree orig_expr = expr;
STRIP_NOPS (expr);
@@ -2133,19 +2138,32 @@ strip_offset_1 (tree expr, bool inside_addr, bool top_compref,
break;
case COMPONENT_REF:
- if (!inside_addr)
- return orig_expr;
+ {
+ tree field;
- tmp = component_ref_field_offset (expr);
- if (top_compref
- && cst_and_fits_in_hwi (tmp))
- {
- /* Strip the component reference completely. */
- op0 = TREE_OPERAND (expr, 0);
- op0 = strip_offset_1 (op0, inside_addr, top_compref, &off0);
- *offset = off0 + int_cst_value (tmp);
- return op0;
- }
+ if (!inside_addr)
+ return orig_expr;
+
+ tmp = component_ref_field_offset (expr);
+ field = TREE_OPERAND (expr, 1);
+ if (top_compref
+ && cst_and_fits_in_hwi (tmp)
+ && cst_and_fits_in_hwi (DECL_FIELD_BIT_OFFSET (field)))
+ {
+ HOST_WIDE_INT boffset, abs_off;
+
+ /* Strip the component reference completely. */
+ op0 = TREE_OPERAND (expr, 0);
+ op0 = strip_offset_1 (op0, inside_addr, top_compref, &off0);
+ boffset = int_cst_value (DECL_FIELD_BIT_OFFSET (field));
+ abs_off = abs_hwi (boffset) / BITS_PER_UNIT;
+ if (boffset < 0)
+ abs_off = -abs_off;
+
+ *offset = off0 + int_cst_value (tmp) + abs_off;
+ return op0;
+ }
+ }
break;
case ADDR_EXPR:
@@ -2196,7 +2214,10 @@ strip_offset_1 (tree expr, bool inside_addr, bool top_compref,
static tree
strip_offset (tree expr, unsigned HOST_WIDE_INT *offset)
{
- return strip_offset_1 (expr, false, false, offset);
+ HOST_WIDE_INT off;
+ tree core = strip_offset_1 (expr, false, false, &off);
+ *offset = off;
+ return core;
}
/* Returns variant of TYPE that can be used as base for different uses.
@@ -3134,16 +3155,19 @@ multiplier_allowed_in_address_p (HOST_WIDE_INT ratio, enum machine_mode mode,
{
enum machine_mode address_mode = targetm.addr_space.address_mode (as);
rtx reg1 = gen_raw_REG (address_mode, LAST_VIRTUAL_REGISTER + 1);
- rtx addr;
+ rtx reg2 = gen_raw_REG (address_mode, LAST_VIRTUAL_REGISTER + 2);
+ rtx addr, scaled;
HOST_WIDE_INT i;
valid_mult = sbitmap_alloc (2 * MAX_RATIO + 1);
bitmap_clear (valid_mult);
- addr = gen_rtx_fmt_ee (MULT, address_mode, reg1, NULL_RTX);
+ scaled = gen_rtx_fmt_ee (MULT, address_mode, reg1, NULL_RTX);
+ addr = gen_rtx_fmt_ee (PLUS, address_mode, scaled, reg2);
for (i = -MAX_RATIO; i <= MAX_RATIO; i++)
{
- XEXP (addr, 1) = gen_int_mode (i, address_mode);
- if (memory_address_addr_space_p (mode, addr, as))
+ XEXP (scaled, 1) = gen_int_mode (i, address_mode);
+ if (memory_address_addr_space_p (mode, addr, as)
+ || memory_address_addr_space_p (mode, scaled, as))
bitmap_set_bit (valid_mult, i + MAX_RATIO);
}
@@ -3476,17 +3500,21 @@ get_shiftadd_cost (tree expr, enum machine_mode mode, comp_cost cost0,
int m = exact_log2 (int_cst_value (cst));
int maxm = MIN (BITS_PER_WORD, GET_MODE_BITSIZE (mode));
int sa_cost;
+ bool equal_p = false;
if (!(m >= 0 && m < maxm))
return false;
+ if (operand_equal_p (op1, mult, 0))
+ equal_p = true;
+
sa_cost = (TREE_CODE (expr) != MINUS_EXPR
? shiftadd_cost (speed, mode, m)
- : (mult == op1
+ : (equal_p
? shiftsub1_cost (speed, mode, m)
: shiftsub0_cost (speed, mode, m)));
res = new_cost (sa_cost, 0);
- res = add_costs (res, mult == op1 ? cost0 : cost1);
+ res = add_costs (res, equal_p ? cost0 : cost1);
STRIP_NOPS (multop);
if (!is_gimple_val (multop))
@@ -3580,30 +3608,13 @@ force_expr_to_var_cost (tree expr, bool speed)
op1 = TREE_OPERAND (expr, 1);
STRIP_NOPS (op0);
STRIP_NOPS (op1);
-
- if (is_gimple_val (op0))
- cost0 = no_cost;
- else
- cost0 = force_expr_to_var_cost (op0, speed);
-
- if (is_gimple_val (op1))
- cost1 = no_cost;
- else
- cost1 = force_expr_to_var_cost (op1, speed);
-
break;
+ CASE_CONVERT:
case NEGATE_EXPR:
op0 = TREE_OPERAND (expr, 0);
STRIP_NOPS (op0);
op1 = NULL_TREE;
-
- if (is_gimple_val (op0))
- cost0 = no_cost;
- else
- cost0 = force_expr_to_var_cost (op0, speed);
-
- cost1 = no_cost;
break;
default:
@@ -3611,6 +3622,18 @@ force_expr_to_var_cost (tree expr, bool speed)
return new_cost (target_spill_cost[speed], 0);
}
+ if (op0 == NULL_TREE
+ || TREE_CODE (op0) == SSA_NAME || CONSTANT_CLASS_P (op0))
+ cost0 = no_cost;
+ else
+ cost0 = force_expr_to_var_cost (op0, speed);
+
+ if (op1 == NULL_TREE
+ || TREE_CODE (op1) == SSA_NAME || CONSTANT_CLASS_P (op1))
+ cost1 = no_cost;
+ else
+ cost1 = force_expr_to_var_cost (op1, speed);
+
mode = TYPE_MODE (TREE_TYPE (expr));
switch (TREE_CODE (expr))
{
@@ -3636,6 +3659,16 @@ force_expr_to_var_cost (tree expr, bool speed)
}
break;
+ CASE_CONVERT:
+ {
+ tree inner_mode, outer_mode;
+ outer_mode = TREE_TYPE (expr);
+ inner_mode = TREE_TYPE (op0);
+ cost = new_cost (convert_cost (TYPE_MODE (outer_mode),
+ TYPE_MODE (inner_mode), speed), 0);
+ }
+ break;
+
case MULT_EXPR:
if (cst_and_fits_in_hwi (op0))
cost = new_cost (mult_by_coeff_cost (int_cst_value (op0),
@@ -3920,7 +3953,7 @@ get_loop_invariant_expr_id (struct ivopts_data *data, tree ubase,
if (ratio == 1)
{
- if(operand_equal_p (ubase, cbase, 0))
+ if (operand_equal_p (ubase, cbase, 0))
return -1;
if (TREE_CODE (ubase) == ADDR_EXPR
diff --git a/gcc/tree-ssa-loop-ivopts.h b/gcc/tree-ssa-loop-ivopts.h
new file mode 100644
index 00000000000..1af92be21a8
--- /dev/null
+++ b/gcc/tree-ssa-loop-ivopts.h
@@ -0,0 +1,36 @@
+/* Header file for Induction variable optimizations.
+ Copyright (C) 2013 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_SSA_LOOP_IVOPTS_H
+#define GCC_TREE_SSA_LOOP_IVOPTS_H
+
+extern edge single_dom_exit (struct loop *);
+extern void dump_iv (FILE *, struct iv *);
+extern void dump_use (FILE *, struct iv_use *);
+extern void dump_uses (FILE *, struct ivopts_data *);
+extern void dump_cand (FILE *, struct iv_cand *);
+extern bool contains_abnormal_ssa_name_p (tree);
+extern struct loop *outermost_invariant_loop_for_expr (struct loop *, tree);
+extern bool expr_invariant_in_loop_p (struct loop *, tree);
+bool may_be_nonaddressable_p (tree expr);
+bool multiplier_allowed_in_address_p (HOST_WIDE_INT, enum machine_mode,
+ addr_space_t);
+void tree_ssa_iv_optimize (void);
+
+#endif /* GCC_TREE_SSA_LOOP_IVOPTS_H */
diff --git a/gcc/tree-ssa-loop-manip.c b/gcc/tree-ssa-loop-manip.c
index e44458e4a0f..2bb225360dd 100644
--- a/gcc/tree-ssa-loop-manip.c
+++ b/gcc/tree-ssa-loop-manip.c
@@ -24,6 +24,17 @@ along with GCC; see the file COPYING3. If not see
#include "tree.h"
#include "tm_p.h"
#include "basic-block.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-cfg.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
+#include "tree-ssa-loop-ivopts.h"
+#include "tree-ssa-loop-manip.h"
+#include "tree-ssa-loop-niter.h"
+#include "tree-ssa-loop.h"
+#include "tree-into-ssa.h"
#include "tree-ssa.h"
#include "dumpfile.h"
#include "gimple-pretty-print.h"
@@ -1277,7 +1288,6 @@ rewrite_phi_with_iv (loop_p loop,
GSI_SAME_STMT);
stmt = gimple_build_assign (res, val);
gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
- SSA_NAME_DEF_STMT (res) = stmt;
}
/* Rewrite all the phi nodes of LOOP in function of the main induction
diff --git a/gcc/tree-ssa-loop-manip.h b/gcc/tree-ssa-loop-manip.h
new file mode 100644
index 00000000000..a1dcd22193d
--- /dev/null
+++ b/gcc/tree-ssa-loop-manip.h
@@ -0,0 +1,49 @@
+/* Header file for High-level loop manipulation functions.
+ Copyright (C) 2013 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_SSA_LOOP_MANIP_H
+#define GCC_TREE_SSA_LOOP_MANIP_H
+
+typedef void (*transform_callback)(struct loop *, void *);
+
+extern void create_iv (tree, tree, tree, struct loop *, gimple_stmt_iterator *,
+ bool, tree *, tree *);
+extern void rewrite_into_loop_closed_ssa (bitmap, unsigned);
+extern void verify_loop_closed_ssa (bool);
+extern basic_block split_loop_exit_edge (edge);
+extern basic_block ip_end_pos (struct loop *);
+extern basic_block ip_normal_pos (struct loop *);
+extern void standard_iv_increment_position (struct loop *,
+ gimple_stmt_iterator *, bool *);
+extern bool gimple_duplicate_loop_to_header_edge (struct loop *, edge,
+ unsigned int, sbitmap,
+ edge, vec<edge> *,
+ int);
+extern bool can_unroll_loop_p (struct loop *loop, unsigned factor,
+ struct tree_niter_desc *niter);
+extern void tree_transform_and_unroll_loop (struct loop *, unsigned,
+ edge, struct tree_niter_desc *,
+ transform_callback, void *);
+extern void tree_unroll_loop (struct loop *, unsigned,
+ edge, struct tree_niter_desc *);
+extern tree canonicalize_loop_ivs (struct loop *, tree *, bool);
+
+
+
+#endif /* GCC_TREE_SSA_LOOP_MANIP_H */
diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c
index adbfe8e8c21..3014faae796 100644
--- a/gcc/tree-ssa-loop-niter.c
+++ b/gcc/tree-ssa-loop-niter.c
@@ -26,7 +26,14 @@ along with GCC; see the file COPYING3. If not see
#include "basic-block.h"
#include "gimple-pretty-print.h"
#include "intl.h"
-#include "tree-ssa.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-cfg.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssa-loop-ivopts.h"
+#include "tree-ssa-loop-niter.h"
+#include "tree-ssa-loop.h"
#include "dumpfile.h"
#include "cfgloop.h"
#include "ggc.h"
@@ -38,6 +45,8 @@ along with GCC; see the file COPYING3. If not see
#include "diagnostic-core.h"
#include "tree-inline.h"
#include "tree-pass.h"
+#include "tree-ssanames.h"
+
#define SWAP(X, Y) do { affine_iv *tmp = (X); (X) = (Y); (Y) = tmp; } while (0)
@@ -111,9 +120,12 @@ split_to_var_and_offset (tree expr, tree *var, mpz_t offset)
in TYPE to MIN and MAX. */
static void
-determine_value_range (tree type, tree var, mpz_t off,
+determine_value_range (struct loop *loop, tree type, tree var, mpz_t off,
mpz_t min, mpz_t max)
{
+ double_int minv, maxv;
+ enum value_range_type rtype = VR_VARYING;
+
/* If the expression is a constant, we know its value exactly. */
if (integer_zerop (var))
{
@@ -122,9 +134,73 @@ determine_value_range (tree type, tree var, mpz_t off,
return;
}
+ get_type_static_bounds (type, min, max);
+
+ /* See if we have some range info from VRP. */
+ if (TREE_CODE (var) == SSA_NAME && INTEGRAL_TYPE_P (type))
+ {
+ edge e = loop_preheader_edge (loop);
+ gimple_stmt_iterator gsi;
+
+ /* Either for VAR itself... */
+ rtype = get_range_info (var, &minv, &maxv);
+ /* Or for PHI results in loop->header where VAR is used as
+ PHI argument from the loop preheader edge. */
+ for (gsi = gsi_start_phis (loop->header); !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ gimple phi = gsi_stmt (gsi);
+ double_int minc, maxc;
+ if (PHI_ARG_DEF_FROM_EDGE (phi, e) == var
+ && (get_range_info (gimple_phi_result (phi), &minc, &maxc)
+ == VR_RANGE))
+ {
+ if (rtype != VR_RANGE)
+ {
+ rtype = VR_RANGE;
+ minv = minc;
+ maxv = maxc;
+ }
+ else
+ {
+ minv = minv.max (minc, TYPE_UNSIGNED (type));
+ maxv = maxv.min (maxc, TYPE_UNSIGNED (type));
+ gcc_assert (minv.cmp (maxv, TYPE_UNSIGNED (type)) <= 0);
+ }
+ }
+ }
+ if (rtype == VR_RANGE)
+ {
+ mpz_t minm, maxm;
+ gcc_assert (minv.cmp (maxv, TYPE_UNSIGNED (type)) <= 0);
+ mpz_init (minm);
+ mpz_init (maxm);
+ mpz_set_double_int (minm, minv, TYPE_UNSIGNED (type));
+ mpz_set_double_int (maxm, maxv, TYPE_UNSIGNED (type));
+ mpz_add (minm, minm, off);
+ mpz_add (maxm, maxm, off);
+ /* If the computation may not wrap or off is zero, then this
+ is always fine. If off is negative and minv + off isn't
+ smaller than type's minimum, or off is positive and
+ maxv + off isn't bigger than type's maximum, use the more
+ precise range too. */
+ if (nowrap_type_p (type)
+ || mpz_sgn (off) == 0
+ || (mpz_sgn (off) < 0 && mpz_cmp (minm, min) >= 0)
+ || (mpz_sgn (off) > 0 && mpz_cmp (maxm, max) <= 0))
+ {
+ mpz_set (min, minm);
+ mpz_set (max, maxm);
+ mpz_clear (minm);
+ mpz_clear (maxm);
+ return;
+ }
+ mpz_clear (minm);
+ mpz_clear (maxm);
+ }
+ }
+
/* If the computation may wrap, we know nothing about the value, except for
the range of the type. */
- get_type_static_bounds (type, min, max);
if (!nowrap_type_p (type))
return;
@@ -397,8 +473,8 @@ bound_difference (struct loop *loop, tree x, tree y, bounds *bnds)
mpz_init (maxx);
mpz_init (miny);
mpz_init (maxy);
- determine_value_range (type, varx, offx, minx, maxx);
- determine_value_range (type, vary, offy, miny, maxy);
+ determine_value_range (loop, type, varx, offx, minx, maxx);
+ determine_value_range (loop, type, vary, offy, miny, maxy);
mpz_sub (bnds->below, minx, maxy);
mpz_sub (bnds->up, maxx, miny);
@@ -2507,40 +2583,6 @@ derive_constant_upper_bound_ops (tree type, tree op0,
}
}
-/* Records that every statement in LOOP is executed I_BOUND times.
- REALISTIC is true if I_BOUND is expected to be close to the real number
- of iterations. UPPER is true if we are sure the loop iterates at most
- I_BOUND times. */
-
-void
-record_niter_bound (struct loop *loop, double_int i_bound, bool realistic,
- bool upper)
-{
- /* Update the bounds only when there is no previous estimation, or when the
- current estimation is smaller. */
- if (upper
- && (!loop->any_upper_bound
- || i_bound.ult (loop->nb_iterations_upper_bound)))
- {
- loop->any_upper_bound = true;
- loop->nb_iterations_upper_bound = i_bound;
- }
- if (realistic
- && (!loop->any_estimate
- || i_bound.ult (loop->nb_iterations_estimate)))
- {
- loop->any_estimate = true;
- loop->nb_iterations_estimate = i_bound;
- }
-
- /* If an upper bound is smaller than the realistic estimate of the
- number of iterations, use the upper bound instead. */
- if (loop->any_upper_bound
- && loop->any_estimate
- && loop->nb_iterations_upper_bound.ult (loop->nb_iterations_estimate))
- loop->nb_iterations_estimate = loop->nb_iterations_upper_bound;
-}
-
/* Emit a -Waggressive-loop-optimizations warning if needed. */
static void
@@ -3008,26 +3050,11 @@ infer_loop_bounds_from_undefined (struct loop *loop)
free (bbs);
}
-/* Converts VAL to double_int. */
-static double_int
-gcov_type_to_double_int (gcov_type val)
-{
- double_int ret;
-
- ret.low = (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;
- ret.high = (unsigned HOST_WIDE_INT) val;
-
- return ret;
-}
/* Compare double ints, callback for qsort. */
-int
+static int
double_int_cmp (const void *p1, const void *p2)
{
const double_int *d1 = (const double_int *)p1;
@@ -3042,7 +3069,7 @@ double_int_cmp (const void *p1, const void *p2)
/* Return index of BOUND in BOUNDS array sorted in increasing order.
Lookup by binary search. */
-int
+static int
bound_index (vec<double_int> bounds, double_int bound)
{
unsigned int end = bounds.length ();
@@ -3349,7 +3376,7 @@ maybe_lower_iteration_bound (struct loop *loop)
/* Records estimates on numbers of iterations of LOOP. If USE_UNDEFINED_P
is true also use estimates derived from undefined behavior. */
-void
+static void
estimate_numbers_of_iterations_loop (struct loop *loop)
{
vec<edge> exits;
@@ -3433,39 +3460,7 @@ estimated_loop_iterations (struct loop *loop, double_int *nit)
if (scev_initialized_p ())
estimate_numbers_of_iterations_loop (loop);
- /* Even if the bound is not recorded, possibly we can derrive one from
- profile. */
- if (!loop->any_estimate)
- {
- if (loop->header->count)
- {
- *nit = gcov_type_to_double_int
- (expected_loop_iterations_unbounded (loop) + 1);
- return true;
- }
- return false;
- }
-
- *nit = loop->nb_iterations_estimate;
- return true;
-}
-
-/* Sets NIT to an upper bound for the maximum number of executions of the
- latch of the LOOP. If we have no reliable estimate, the function returns
- false, otherwise returns true. */
-
-bool
-max_loop_iterations (struct loop *loop, double_int *nit)
-{
- /* When SCEV information is available, try to update loop iterations
- estimate. Otherwise just return whatever we recorded earlier. */
- if (scev_initialized_p ())
- estimate_numbers_of_iterations_loop (loop);
- if (!loop->any_upper_bound)
- return false;
-
- *nit = loop->nb_iterations_upper_bound;
- return true;
+ return (get_estimated_loop_iterations (loop, nit));
}
/* Similar to estimated_loop_iterations, but returns the estimate only
@@ -3488,6 +3483,22 @@ estimated_loop_iterations_int (struct loop *loop)
return hwi_nit < 0 ? -1 : hwi_nit;
}
+
+/* Sets NIT to an upper bound for the maximum number of executions of the
+ latch of the LOOP. If we have no reliable estimate, the function returns
+ false, otherwise returns true. */
+
+bool
+max_loop_iterations (struct loop *loop, double_int *nit)
+{
+ /* When SCEV information is available, try to update loop iterations
+ estimate. Otherwise just return whatever we recorded earlier. */
+ if (scev_initialized_p ())
+ estimate_numbers_of_iterations_loop (loop);
+
+ return get_max_loop_iterations (loop, nit);
+}
+
/* Similar to max_loop_iterations, but returns the estimate only
if it fits to HOST_WIDE_INT. If this is not the case, or the estimate
on the number of iterations of LOOP could not be derived, returns -1. */
@@ -3508,25 +3519,6 @@ max_loop_iterations_int (struct loop *loop)
return hwi_nit < 0 ? -1 : hwi_nit;
}
-/* Returns an upper bound on the number of executions of statements
- in the LOOP. For statements before the loop exit, this exceeds
- the number of execution of the latch by one. */
-
-HOST_WIDE_INT
-max_stmt_executions_int (struct loop *loop)
-{
- HOST_WIDE_INT nit = max_loop_iterations_int (loop);
- HOST_WIDE_INT snit;
-
- if (nit == -1)
- return -1;
-
- snit = (HOST_WIDE_INT) ((unsigned HOST_WIDE_INT) nit + 1);
-
- /* If the computation overflows, return -1. */
- return snit < 0 ? -1 : snit;
-}
-
/* Returns an estimate for the number of executions of statements
in the LOOP. For statements before the loop exit, this exceeds
the number of execution of the latch by one. */
diff --git a/gcc/tree-ssa-loop-niter.h b/gcc/tree-ssa-loop-niter.h
new file mode 100644
index 00000000000..194550762d8
--- /dev/null
+++ b/gcc/tree-ssa-loop-niter.h
@@ -0,0 +1,48 @@
+/* Header file for loop interation estimates.
+ Copyright (C) 2013 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_SSA_LOOP_NITER_H
+#define GCC_TREE_SSA_LOOP_NITER_H
+
+extern tree expand_simple_operations (tree);
+extern bool loop_only_exit_p (const struct loop *, const_edge);
+extern bool number_of_iterations_exit (struct loop *, edge,
+ struct tree_niter_desc *niter, bool,
+ bool every_iteration = true);
+extern tree find_loop_niter (struct loop *, edge *);
+extern bool finite_loop_p (struct loop *);
+extern tree loop_niter_by_eval (struct loop *, edge);
+extern tree find_loop_niter_by_eval (struct loop *, edge *);
+extern bool estimated_loop_iterations (struct loop *, double_int *);
+extern HOST_WIDE_INT estimated_loop_iterations_int (struct loop *);
+extern bool max_loop_iterations (struct loop *, double_int *);
+extern HOST_WIDE_INT max_loop_iterations_int (struct loop *);
+extern HOST_WIDE_INT max_stmt_executions_int (struct loop *);
+extern HOST_WIDE_INT estimated_stmt_executions_int (struct loop *);
+extern bool max_stmt_executions (struct loop *, double_int *);
+extern bool estimated_stmt_executions (struct loop *, double_int *);
+extern void estimate_numbers_of_iterations (void);
+extern bool stmt_dominates_stmt_p (gimple, gimple);
+extern bool nowrap_type_p (tree);
+extern bool scev_probably_wraps_p (tree, tree, gimple, struct loop *, bool);
+extern void free_numbers_of_iterations_estimates_loop (struct loop *);
+extern void free_numbers_of_iterations_estimates (void);
+extern void substitute_in_loop_info (struct loop *, tree, tree);
+
+#endif /* GCC_TREE_SSA_LOOP_NITER_H */
diff --git a/gcc/tree-ssa-loop-prefetch.c b/gcc/tree-ssa-loop-prefetch.c
index bf313fe9152..5b7c0c2260c 100644
--- a/gcc/tree-ssa-loop-prefetch.c
+++ b/gcc/tree-ssa-loop-prefetch.c
@@ -25,7 +25,13 @@ along with GCC; see the file COPYING3. If not see
#include "tm_p.h"
#include "basic-block.h"
#include "tree-pretty-print.h"
-#include "tree-ssa.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-ssa-loop-ivopts.h"
+#include "tree-ssa-loop-manip.h"
+#include "tree-ssa-loop-niter.h"
+#include "tree-ssa-loop.h"
+#include "tree-into-ssa.h"
#include "cfgloop.h"
#include "tree-pass.h"
#include "insn-config.h"
@@ -555,7 +561,7 @@ gather_memory_references_ref (struct loop *loop, struct mem_ref_group **refs,
fprintf (dump_file, "Memory expression %p\n",(void *) ref );
print_generic_expr (dump_file, ref, TDF_TREE);
fprintf (dump_file,":");
- dump_mem_details( dump_file, base, step, delta, write_p);
+ dump_mem_details (dump_file, base, step, delta, write_p);
fprintf (dump_file,
"Ignoring %p, non-constant step prefetching is "
"limited to inner most loops \n",
@@ -572,7 +578,7 @@ gather_memory_references_ref (struct loop *loop, struct mem_ref_group **refs,
fprintf (dump_file, "Memory expression %p\n",(void *) ref );
print_generic_expr (dump_file, ref, TDF_TREE);
fprintf (dump_file,":");
- dump_mem_details(dump_file, base, step, delta, write_p);
+ dump_mem_details (dump_file, base, step, delta, write_p);
fprintf (dump_file,
"Not prefetching, ignoring %p due to "
"loop variant step\n",
@@ -1988,3 +1994,60 @@ tree_ssa_prefetch_arrays (void)
free_original_copy_tables ();
return todo_flags;
}
+
+/* Prefetching. */
+
+static unsigned int
+tree_ssa_loop_prefetch (void)
+{
+ if (number_of_loops (cfun) <= 1)
+ return 0;
+
+ return tree_ssa_prefetch_arrays ();
+}
+
+static bool
+gate_tree_ssa_loop_prefetch (void)
+{
+ return flag_prefetch_loop_arrays > 0;
+}
+
+namespace {
+
+const pass_data pass_data_loop_prefetch =
+{
+ GIMPLE_PASS, /* type */
+ "aprefetch", /* name */
+ OPTGROUP_LOOP, /* optinfo_flags */
+ true, /* has_gate */
+ true, /* has_execute */
+ TV_TREE_PREFETCH, /* tv_id */
+ ( PROP_cfg | PROP_ssa ), /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ 0, /* todo_flags_finish */
+};
+
+class pass_loop_prefetch : public gimple_opt_pass
+{
+public:
+ pass_loop_prefetch (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_loop_prefetch, ctxt)
+ {}
+
+ /* opt_pass methods: */
+ bool gate () { return gate_tree_ssa_loop_prefetch (); }
+ unsigned int execute () { return tree_ssa_loop_prefetch (); }
+
+}; // class pass_loop_prefetch
+
+} // anon namespace
+
+gimple_opt_pass *
+make_pass_loop_prefetch (gcc::context *ctxt)
+{
+ return new pass_loop_prefetch (ctxt);
+}
+
+
diff --git a/gcc/tree-ssa-loop-unswitch.c b/gcc/tree-ssa-loop-unswitch.c
index 6ce06c1326c..e2b1c0735ad 100644
--- a/gcc/tree-ssa-loop-unswitch.c
+++ b/gcc/tree-ssa-loop-unswitch.c
@@ -24,7 +24,14 @@ along with GCC; see the file COPYING3. If not see
#include "tree.h"
#include "tm_p.h"
#include "basic-block.h"
-#include "tree-ssa.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-cfg.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssa-loop-niter.h"
+#include "tree-ssa-loop.h"
+#include "tree-into-ssa.h"
#include "cfgloop.h"
#include "params.h"
#include "tree-pass.h"
@@ -388,3 +395,60 @@ tree_unswitch_loop (struct loop *loop,
NULL, prob_true, prob_true,
REG_BR_PROB_BASE - prob_true, false);
}
+
+/* Loop unswitching pass. */
+
+static unsigned int
+tree_ssa_loop_unswitch (void)
+{
+ if (number_of_loops (cfun) <= 1)
+ return 0;
+
+ return tree_ssa_unswitch_loops ();
+}
+
+static bool
+gate_tree_ssa_loop_unswitch (void)
+{
+ return flag_unswitch_loops != 0;
+}
+
+namespace {
+
+const pass_data pass_data_tree_unswitch =
+{
+ GIMPLE_PASS, /* type */
+ "unswitch", /* name */
+ OPTGROUP_LOOP, /* optinfo_flags */
+ true, /* has_gate */
+ true, /* has_execute */
+ TV_TREE_LOOP_UNSWITCH, /* tv_id */
+ PROP_cfg, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ 0, /* todo_flags_finish */
+};
+
+class pass_tree_unswitch : public gimple_opt_pass
+{
+public:
+ pass_tree_unswitch (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_tree_unswitch, ctxt)
+ {}
+
+ /* opt_pass methods: */
+ bool gate () { return gate_tree_ssa_loop_unswitch (); }
+ unsigned int execute () { return tree_ssa_loop_unswitch (); }
+
+}; // class pass_tree_unswitch
+
+} // anon namespace
+
+gimple_opt_pass *
+make_pass_tree_unswitch (gcc::context *ctxt)
+{
+ return new pass_tree_unswitch (ctxt);
+}
+
+
diff --git a/gcc/tree-ssa-loop.c b/gcc/tree-ssa-loop.c
index cb3eec8dd38..9bb002868be 100644
--- a/gcc/tree-ssa-loop.c
+++ b/gcc/tree-ssa-loop.c
@@ -24,7 +24,11 @@ along with GCC; see the file COPYING3. If not see
#include "tree.h"
#include "tm_p.h"
#include "basic-block.h"
-#include "tree-ssa.h"
+#include "gimple.h"
+#include "tree-ssa-loop-ivopts.h"
+#include "tree-ssa-loop-manip.h"
+#include "tree-ssa-loop-niter.h"
+#include "tree-ssa-loop.h"
#include "tree-pass.h"
#include "cfgloop.h"
#include "flags.h"
@@ -61,8 +65,8 @@ const pass_data pass_data_tree_loop =
class pass_tree_loop : public gimple_opt_pass
{
public:
- pass_tree_loop(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_tree_loop, ctxt)
+ pass_tree_loop (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_tree_loop, ctxt)
{}
/* opt_pass methods: */
@@ -117,8 +121,8 @@ const pass_data pass_data_tree_loop_init =
class pass_tree_loop_init : public gimple_opt_pass
{
public:
- pass_tree_loop_init(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_tree_loop_init, ctxt)
+ pass_tree_loop_init (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_tree_loop_init, ctxt)
{}
/* opt_pass methods: */
@@ -134,172 +138,6 @@ make_pass_tree_loop_init (gcc::context *ctxt)
return new pass_tree_loop_init (ctxt);
}
-/* Loop invariant motion pass. */
-
-static unsigned int
-tree_ssa_loop_im (void)
-{
- if (number_of_loops (cfun) <= 1)
- return 0;
-
- return tree_ssa_lim ();
-}
-
-static bool
-gate_tree_ssa_loop_im (void)
-{
- return flag_tree_loop_im != 0;
-}
-
-namespace {
-
-const pass_data pass_data_lim =
-{
- GIMPLE_PASS, /* type */
- "lim", /* name */
- OPTGROUP_LOOP, /* optinfo_flags */
- true, /* has_gate */
- true, /* has_execute */
- TV_LIM, /* tv_id */
- PROP_cfg, /* properties_required */
- 0, /* properties_provided */
- 0, /* properties_destroyed */
- 0, /* todo_flags_start */
- 0, /* todo_flags_finish */
-};
-
-class pass_lim : public gimple_opt_pass
-{
-public:
- pass_lim(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_lim, ctxt)
- {}
-
- /* opt_pass methods: */
- opt_pass * clone () { return new pass_lim (ctxt_); }
- bool gate () { return gate_tree_ssa_loop_im (); }
- unsigned int execute () { return tree_ssa_loop_im (); }
-
-}; // class pass_lim
-
-} // anon namespace
-
-gimple_opt_pass *
-make_pass_lim (gcc::context *ctxt)
-{
- return new pass_lim (ctxt);
-}
-
-/* Loop unswitching pass. */
-
-static unsigned int
-tree_ssa_loop_unswitch (void)
-{
- if (number_of_loops (cfun) <= 1)
- return 0;
-
- return tree_ssa_unswitch_loops ();
-}
-
-static bool
-gate_tree_ssa_loop_unswitch (void)
-{
- return flag_unswitch_loops != 0;
-}
-
-namespace {
-
-const pass_data pass_data_tree_unswitch =
-{
- GIMPLE_PASS, /* type */
- "unswitch", /* name */
- OPTGROUP_LOOP, /* optinfo_flags */
- true, /* has_gate */
- true, /* has_execute */
- TV_TREE_LOOP_UNSWITCH, /* tv_id */
- PROP_cfg, /* properties_required */
- 0, /* properties_provided */
- 0, /* properties_destroyed */
- 0, /* todo_flags_start */
- 0, /* todo_flags_finish */
-};
-
-class pass_tree_unswitch : public gimple_opt_pass
-{
-public:
- pass_tree_unswitch(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_tree_unswitch, ctxt)
- {}
-
- /* opt_pass methods: */
- bool gate () { return gate_tree_ssa_loop_unswitch (); }
- unsigned int execute () { return tree_ssa_loop_unswitch (); }
-
-}; // class pass_tree_unswitch
-
-} // anon namespace
-
-gimple_opt_pass *
-make_pass_tree_unswitch (gcc::context *ctxt)
-{
- return new pass_tree_unswitch (ctxt);
-}
-
-/* Predictive commoning. */
-
-static unsigned
-run_tree_predictive_commoning (void)
-{
- if (!current_loops)
- return 0;
-
- return tree_predictive_commoning ();
-}
-
-static bool
-gate_tree_predictive_commoning (void)
-{
- return flag_predictive_commoning != 0;
-}
-
-namespace {
-
-const pass_data pass_data_predcom =
-{
- GIMPLE_PASS, /* type */
- "pcom", /* name */
- OPTGROUP_LOOP, /* optinfo_flags */
- true, /* has_gate */
- true, /* has_execute */
- TV_PREDCOM, /* tv_id */
- PROP_cfg, /* properties_required */
- 0, /* properties_provided */
- 0, /* properties_destroyed */
- 0, /* todo_flags_start */
- TODO_update_ssa_only_virtuals, /* todo_flags_finish */
-};
-
-class pass_predcom : public gimple_opt_pass
-{
-public:
- pass_predcom(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_predcom, ctxt)
- {}
-
- /* opt_pass methods: */
- bool gate () { return gate_tree_predictive_commoning (); }
- unsigned int execute () { return run_tree_predictive_commoning (); }
-
-}; // class pass_predcom
-
-} // anon namespace
-
-gimple_opt_pass *
-make_pass_predcom (gcc::context *ctxt)
-{
- return new pass_predcom (ctxt);
-}
-
/* Loop autovectorization. */
static unsigned int
@@ -337,8 +175,8 @@ const pass_data pass_data_vectorize =
class pass_vectorize : public gimple_opt_pass
{
public:
- pass_vectorize(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_vectorize, ctxt)
+ pass_vectorize (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_vectorize, ctxt)
{}
/* opt_pass methods: */
@@ -355,110 +193,6 @@ make_pass_vectorize (gcc::context *ctxt)
return new pass_vectorize (ctxt);
}
-/* GRAPHITE optimizations. */
-
-static unsigned int
-graphite_transforms (void)
-{
- if (!current_loops)
- return 0;
-
- graphite_transform_loops ();
-
- return 0;
-}
-
-static bool
-gate_graphite_transforms (void)
-{
- /* Enable -fgraphite pass if any one of the graphite optimization flags
- is turned on. */
- if (flag_loop_block
- || flag_loop_interchange
- || flag_loop_strip_mine
- || flag_graphite_identity
- || flag_loop_parallelize_all
- || flag_loop_optimize_isl)
- flag_graphite = 1;
-
- return flag_graphite != 0;
-}
-
-namespace {
-
-const pass_data pass_data_graphite =
-{
- GIMPLE_PASS, /* type */
- "graphite0", /* name */
- OPTGROUP_LOOP, /* optinfo_flags */
- true, /* has_gate */
- false, /* has_execute */
- TV_GRAPHITE, /* tv_id */
- ( PROP_cfg | PROP_ssa ), /* properties_required */
- 0, /* properties_provided */
- 0, /* properties_destroyed */
- 0, /* todo_flags_start */
- 0, /* todo_flags_finish */
-};
-
-class pass_graphite : public gimple_opt_pass
-{
-public:
- pass_graphite(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_graphite, ctxt)
- {}
-
- /* opt_pass methods: */
- bool gate () { return gate_graphite_transforms (); }
-
-}; // class pass_graphite
-
-} // anon namespace
-
-gimple_opt_pass *
-make_pass_graphite (gcc::context *ctxt)
-{
- return new pass_graphite (ctxt);
-}
-
-namespace {
-
-const pass_data pass_data_graphite_transforms =
-{
- GIMPLE_PASS, /* type */
- "graphite", /* name */
- OPTGROUP_LOOP, /* optinfo_flags */
- true, /* has_gate */
- true, /* has_execute */
- TV_GRAPHITE_TRANSFORMS, /* tv_id */
- ( PROP_cfg | PROP_ssa ), /* properties_required */
- 0, /* properties_provided */
- 0, /* properties_destroyed */
- 0, /* todo_flags_start */
- 0, /* todo_flags_finish */
-};
-
-class pass_graphite_transforms : public gimple_opt_pass
-{
-public:
- pass_graphite_transforms(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_graphite_transforms, ctxt)
- {}
-
- /* opt_pass methods: */
- bool gate () { return gate_graphite_transforms (); }
- unsigned int execute () { return graphite_transforms (); }
-
-}; // class pass_graphite_transforms
-
-} // anon namespace
-
-gimple_opt_pass *
-make_pass_graphite_transforms (gcc::context *ctxt)
-{
- return new pass_graphite_transforms (ctxt);
-}
-
/* Check the correctness of the data dependence analyzers. */
static unsigned int
@@ -497,8 +231,8 @@ const pass_data pass_data_check_data_deps =
class pass_check_data_deps : public gimple_opt_pass
{
public:
- pass_check_data_deps(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_check_data_deps, ctxt)
+ pass_check_data_deps (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_check_data_deps, ctxt)
{}
/* opt_pass methods: */
@@ -515,61 +249,6 @@ make_pass_check_data_deps (gcc::context *ctxt)
return new pass_check_data_deps (ctxt);
}
-/* Canonical induction variable creation pass. */
-
-static unsigned int
-tree_ssa_loop_ivcanon (void)
-{
- if (number_of_loops (cfun) <= 1)
- return 0;
-
- return canonicalize_induction_variables ();
-}
-
-static bool
-gate_tree_ssa_loop_ivcanon (void)
-{
- return flag_tree_loop_ivcanon != 0;
-}
-
-namespace {
-
-const pass_data pass_data_iv_canon =
-{
- GIMPLE_PASS, /* type */
- "ivcanon", /* name */
- OPTGROUP_LOOP, /* optinfo_flags */
- true, /* has_gate */
- true, /* has_execute */
- TV_TREE_LOOP_IVCANON, /* tv_id */
- ( PROP_cfg | PROP_ssa ), /* properties_required */
- 0, /* properties_provided */
- 0, /* properties_destroyed */
- 0, /* todo_flags_start */
- 0, /* todo_flags_finish */
-};
-
-class pass_iv_canon : public gimple_opt_pass
-{
-public:
- pass_iv_canon(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_iv_canon, ctxt)
- {}
-
- /* opt_pass methods: */
- bool gate () { return gate_tree_ssa_loop_ivcanon (); }
- unsigned int execute () { return tree_ssa_loop_ivcanon (); }
-
-}; // class pass_iv_canon
-
-} // anon namespace
-
-gimple_opt_pass *
-make_pass_iv_canon (gcc::context *ctxt)
-{
- return new pass_iv_canon (ctxt);
-}
-
/* Propagation of constants using scev. */
static bool
@@ -599,8 +278,8 @@ const pass_data pass_data_scev_cprop =
class pass_scev_cprop : public gimple_opt_pass
{
public:
- pass_scev_cprop(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_scev_cprop, ctxt)
+ pass_scev_cprop (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_scev_cprop, ctxt)
{}
/* opt_pass methods: */
@@ -650,8 +329,8 @@ const pass_data pass_data_record_bounds =
class pass_record_bounds : public gimple_opt_pass
{
public:
- pass_record_bounds(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_record_bounds, ctxt)
+ pass_record_bounds (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_record_bounds, ctxt)
{}
/* opt_pass methods: */
@@ -667,340 +346,338 @@ make_pass_record_bounds (gcc::context *ctxt)
return new pass_record_bounds (ctxt);
}
-/* Complete unrolling of loops. */
+/* Induction variable optimizations. */
static unsigned int
-tree_complete_unroll (void)
+tree_ssa_loop_ivopts (void)
{
if (number_of_loops (cfun) <= 1)
return 0;
- return tree_unroll_loops_completely (flag_unroll_loops
- || flag_peel_loops
- || optimize >= 3, true);
+ tree_ssa_iv_optimize ();
+ return 0;
}
static bool
-gate_tree_complete_unroll (void)
+gate_tree_ssa_loop_ivopts (void)
{
- return true;
+ return flag_ivopts != 0;
}
namespace {
-const pass_data pass_data_complete_unroll =
+const pass_data pass_data_iv_optimize =
{
GIMPLE_PASS, /* type */
- "cunroll", /* name */
+ "ivopts", /* name */
OPTGROUP_LOOP, /* optinfo_flags */
true, /* has_gate */
true, /* has_execute */
- TV_COMPLETE_UNROLL, /* tv_id */
+ TV_TREE_LOOP_IVOPTS, /* tv_id */
( PROP_cfg | PROP_ssa ), /* properties_required */
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
- 0, /* todo_flags_finish */
+ TODO_update_ssa, /* todo_flags_finish */
};
-class pass_complete_unroll : public gimple_opt_pass
+class pass_iv_optimize : public gimple_opt_pass
{
public:
- pass_complete_unroll(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_complete_unroll, ctxt)
+ pass_iv_optimize (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_iv_optimize, ctxt)
{}
/* opt_pass methods: */
- bool gate () { return gate_tree_complete_unroll (); }
- unsigned int execute () { return tree_complete_unroll (); }
+ bool gate () { return gate_tree_ssa_loop_ivopts (); }
+ unsigned int execute () { return tree_ssa_loop_ivopts (); }
-}; // class pass_complete_unroll
+}; // class pass_iv_optimize
} // anon namespace
gimple_opt_pass *
-make_pass_complete_unroll (gcc::context *ctxt)
+make_pass_iv_optimize (gcc::context *ctxt)
{
- return new pass_complete_unroll (ctxt);
+ return new pass_iv_optimize (ctxt);
}
-/* Complete unrolling of inner loops. */
+/* Loop optimizer finalization. */
static unsigned int
-tree_complete_unroll_inner (void)
+tree_ssa_loop_done (void)
{
- unsigned ret = 0;
-
- loop_optimizer_init (LOOPS_NORMAL
- | LOOPS_HAVE_RECORDED_EXITS);
- if (number_of_loops (cfun) > 1)
- {
- scev_initialize ();
- ret = tree_unroll_loops_completely (optimize >= 3, false);
- free_numbers_of_iterations_estimates ();
- scev_finalize ();
- }
+ free_numbers_of_iterations_estimates ();
+ scev_finalize ();
loop_optimizer_finalize ();
-
- return ret;
-}
-
-static bool
-gate_tree_complete_unroll_inner (void)
-{
- return optimize >= 2;
+ return 0;
}
namespace {
-const pass_data pass_data_complete_unrolli =
+const pass_data pass_data_tree_loop_done =
{
GIMPLE_PASS, /* type */
- "cunrolli", /* name */
+ "loopdone", /* name */
OPTGROUP_LOOP, /* optinfo_flags */
- true, /* has_gate */
+ false, /* has_gate */
true, /* has_execute */
- TV_COMPLETE_UNROLL, /* tv_id */
- ( PROP_cfg | PROP_ssa ), /* properties_required */
+ TV_NONE, /* tv_id */
+ PROP_cfg, /* properties_required */
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
- TODO_verify_flow, /* todo_flags_finish */
+ ( TODO_cleanup_cfg | TODO_verify_flow ), /* todo_flags_finish */
};
-class pass_complete_unrolli : public gimple_opt_pass
+class pass_tree_loop_done : public gimple_opt_pass
{
public:
- pass_complete_unrolli(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_complete_unrolli, ctxt)
+ pass_tree_loop_done (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_tree_loop_done, ctxt)
{}
/* opt_pass methods: */
- bool gate () { return gate_tree_complete_unroll_inner (); }
- unsigned int execute () { return tree_complete_unroll_inner (); }
+ unsigned int execute () { return tree_ssa_loop_done (); }
-}; // class pass_complete_unrolli
+}; // class pass_tree_loop_done
} // anon namespace
gimple_opt_pass *
-make_pass_complete_unrolli (gcc::context *ctxt)
-{
- return new pass_complete_unrolli (ctxt);
-}
-
-/* Parallelization. */
-
-static bool
-gate_tree_parallelize_loops (void)
+make_pass_tree_loop_done (gcc::context *ctxt)
{
- return flag_tree_parallelize_loops > 1;
+ return new pass_tree_loop_done (ctxt);
}
-static unsigned
-tree_parallelize_loops (void)
-{
- if (number_of_loops (cfun) <= 1)
- return 0;
+/* Calls CBCK for each index in memory reference ADDR_P. There are two
+ kinds situations handled; in each of these cases, the memory reference
+ and DATA are passed to the callback:
- if (parallelize_loops ())
- return TODO_cleanup_cfg | TODO_rebuild_alias;
- return 0;
-}
+ Access to an array: ARRAY_{RANGE_}REF (base, index). In this case we also
+ pass the pointer to the index to the callback.
-namespace {
+ Pointer dereference: INDIRECT_REF (addr). In this case we also pass the
+ pointer to addr to the callback.
-const pass_data pass_data_parallelize_loops =
-{
- GIMPLE_PASS, /* type */
- "parloops", /* name */
- OPTGROUP_LOOP, /* optinfo_flags */
- true, /* has_gate */
- true, /* has_execute */
- TV_TREE_PARALLELIZE_LOOPS, /* tv_id */
- ( PROP_cfg | PROP_ssa ), /* properties_required */
- 0, /* properties_provided */
- 0, /* properties_destroyed */
- 0, /* todo_flags_start */
- TODO_verify_flow, /* todo_flags_finish */
-};
+ If the callback returns false, the whole search stops and false is returned.
+ Otherwise the function returns true after traversing through the whole
+ reference *ADDR_P. */
-class pass_parallelize_loops : public gimple_opt_pass
+bool
+for_each_index (tree *addr_p, bool (*cbck) (tree, tree *, void *), void *data)
{
-public:
- pass_parallelize_loops(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_parallelize_loops, ctxt)
- {}
-
- /* opt_pass methods: */
- bool gate () { return gate_tree_parallelize_loops (); }
- unsigned int execute () { return tree_parallelize_loops (); }
-
-}; // class pass_parallelize_loops
+ tree *nxt, *idx;
-} // anon namespace
-
-gimple_opt_pass *
-make_pass_parallelize_loops (gcc::context *ctxt)
-{
- return new pass_parallelize_loops (ctxt);
+ for (; ; addr_p = nxt)
+ {
+ switch (TREE_CODE (*addr_p))
+ {
+ case SSA_NAME:
+ return cbck (*addr_p, addr_p, data);
+
+ case MEM_REF:
+ nxt = &TREE_OPERAND (*addr_p, 0);
+ return cbck (*addr_p, nxt, data);
+
+ case BIT_FIELD_REF:
+ case VIEW_CONVERT_EXPR:
+ case REALPART_EXPR:
+ case IMAGPART_EXPR:
+ nxt = &TREE_OPERAND (*addr_p, 0);
+ break;
+
+ case COMPONENT_REF:
+ /* If the component has varying offset, it behaves like index
+ as well. */
+ idx = &TREE_OPERAND (*addr_p, 2);
+ if (*idx
+ && !cbck (*addr_p, idx, data))
+ return false;
+
+ nxt = &TREE_OPERAND (*addr_p, 0);
+ break;
+
+ case ARRAY_REF:
+ case ARRAY_RANGE_REF:
+ nxt = &TREE_OPERAND (*addr_p, 0);
+ if (!cbck (*addr_p, &TREE_OPERAND (*addr_p, 1), data))
+ return false;
+ break;
+
+ case VAR_DECL:
+ case PARM_DECL:
+ case CONST_DECL:
+ case STRING_CST:
+ case RESULT_DECL:
+ case VECTOR_CST:
+ case COMPLEX_CST:
+ case INTEGER_CST:
+ case REAL_CST:
+ case FIXED_CST:
+ case CONSTRUCTOR:
+ return true;
+
+ case ADDR_EXPR:
+ gcc_assert (is_gimple_min_invariant (*addr_p));
+ return true;
+
+ case TARGET_MEM_REF:
+ idx = &TMR_BASE (*addr_p);
+ if (*idx
+ && !cbck (*addr_p, idx, data))
+ return false;
+ idx = &TMR_INDEX (*addr_p);
+ if (*idx
+ && !cbck (*addr_p, idx, data))
+ return false;
+ idx = &TMR_INDEX2 (*addr_p);
+ if (*idx
+ && !cbck (*addr_p, idx, data))
+ return false;
+ return true;
+
+ default:
+ gcc_unreachable ();
+ }
+ }
}
-/* Prefetching. */
-static unsigned int
-tree_ssa_loop_prefetch (void)
-{
- if (number_of_loops (cfun) <= 1)
- return 0;
+/* The name and the length of the currently generated variable
+ for lsm. */
+#define MAX_LSM_NAME_LENGTH 40
+static char lsm_tmp_name[MAX_LSM_NAME_LENGTH + 1];
+static int lsm_tmp_name_length;
- return tree_ssa_prefetch_arrays ();
-}
+/* Adds S to lsm_tmp_name. */
-static bool
-gate_tree_ssa_loop_prefetch (void)
+static void
+lsm_tmp_name_add (const char *s)
{
- return flag_prefetch_loop_arrays > 0;
-}
+ int l = strlen (s) + lsm_tmp_name_length;
+ if (l > MAX_LSM_NAME_LENGTH)
+ return;
-namespace {
-
-const pass_data pass_data_loop_prefetch =
-{
- GIMPLE_PASS, /* type */
- "aprefetch", /* name */
- OPTGROUP_LOOP, /* optinfo_flags */
- true, /* has_gate */
- true, /* has_execute */
- TV_TREE_PREFETCH, /* tv_id */
- ( PROP_cfg | PROP_ssa ), /* properties_required */
- 0, /* properties_provided */
- 0, /* properties_destroyed */
- 0, /* todo_flags_start */
- 0, /* todo_flags_finish */
-};
-
-class pass_loop_prefetch : public gimple_opt_pass
-{
-public:
- pass_loop_prefetch(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_loop_prefetch, ctxt)
- {}
-
- /* opt_pass methods: */
- bool gate () { return gate_tree_ssa_loop_prefetch (); }
- unsigned int execute () { return tree_ssa_loop_prefetch (); }
-
-}; // class pass_loop_prefetch
-
-} // anon namespace
-
-gimple_opt_pass *
-make_pass_loop_prefetch (gcc::context *ctxt)
-{
- return new pass_loop_prefetch (ctxt);
+ strcpy (lsm_tmp_name + lsm_tmp_name_length, s);
+ lsm_tmp_name_length = l;
}
-/* Induction variable optimizations. */
+/* Stores the name for temporary variable that replaces REF to
+ lsm_tmp_name. */
-static unsigned int
-tree_ssa_loop_ivopts (void)
+static void
+gen_lsm_tmp_name (tree ref)
{
- if (number_of_loops (cfun) <= 1)
- return 0;
-
- tree_ssa_iv_optimize ();
- return 0;
-}
+ const char *name;
-static bool
-gate_tree_ssa_loop_ivopts (void)
-{
- return flag_ivopts != 0;
+ switch (TREE_CODE (ref))
+ {
+ case MEM_REF:
+ case TARGET_MEM_REF:
+ gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
+ lsm_tmp_name_add ("_");
+ break;
+
+ case ADDR_EXPR:
+ gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
+ break;
+
+ case BIT_FIELD_REF:
+ case VIEW_CONVERT_EXPR:
+ case ARRAY_RANGE_REF:
+ gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
+ break;
+
+ case REALPART_EXPR:
+ gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
+ lsm_tmp_name_add ("_RE");
+ break;
+
+ case IMAGPART_EXPR:
+ gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
+ lsm_tmp_name_add ("_IM");
+ break;
+
+ case COMPONENT_REF:
+ gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
+ lsm_tmp_name_add ("_");
+ name = get_name (TREE_OPERAND (ref, 1));
+ if (!name)
+ name = "F";
+ lsm_tmp_name_add (name);
+ break;
+
+ case ARRAY_REF:
+ gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
+ lsm_tmp_name_add ("_I");
+ break;
+
+ case SSA_NAME:
+ case VAR_DECL:
+ case PARM_DECL:
+ name = get_name (ref);
+ if (!name)
+ name = "D";
+ lsm_tmp_name_add (name);
+ break;
+
+ case STRING_CST:
+ lsm_tmp_name_add ("S");
+ break;
+
+ case RESULT_DECL:
+ lsm_tmp_name_add ("R");
+ break;
+
+ case INTEGER_CST:
+ /* Nothing. */
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
}
-namespace {
-
-const pass_data pass_data_iv_optimize =
-{
- GIMPLE_PASS, /* type */
- "ivopts", /* name */
- OPTGROUP_LOOP, /* optinfo_flags */
- true, /* has_gate */
- true, /* has_execute */
- TV_TREE_LOOP_IVOPTS, /* tv_id */
- ( PROP_cfg | PROP_ssa ), /* properties_required */
- 0, /* properties_provided */
- 0, /* properties_destroyed */
- 0, /* todo_flags_start */
- TODO_update_ssa, /* todo_flags_finish */
-};
+/* Determines name for temporary variable that replaces REF.
+ The name is accumulated into the lsm_tmp_name variable.
+ N is added to the name of the temporary. */
-class pass_iv_optimize : public gimple_opt_pass
+char *
+get_lsm_tmp_name (tree ref, unsigned n, const char *suffix)
{
-public:
- pass_iv_optimize(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_iv_optimize, ctxt)
- {}
+ char ns[2];
- /* opt_pass methods: */
- bool gate () { return gate_tree_ssa_loop_ivopts (); }
- unsigned int execute () { return tree_ssa_loop_ivopts (); }
-
-}; // class pass_iv_optimize
-
-} // anon namespace
-
-gimple_opt_pass *
-make_pass_iv_optimize (gcc::context *ctxt)
-{
- return new pass_iv_optimize (ctxt);
+ lsm_tmp_name_length = 0;
+ gen_lsm_tmp_name (ref);
+ lsm_tmp_name_add ("_lsm");
+ if (n < 10)
+ {
+ ns[0] = '0' + n;
+ ns[1] = 0;
+ lsm_tmp_name_add (ns);
+ }
+ return lsm_tmp_name;
+ if (suffix != NULL)
+ lsm_tmp_name_add (suffix);
}
-/* Loop optimizer finalization. */
+/* Computes an estimated number of insns in LOOP, weighted by WEIGHTS. */
-static unsigned int
-tree_ssa_loop_done (void)
+unsigned
+tree_num_loop_insns (struct loop *loop, eni_weights *weights)
{
- free_numbers_of_iterations_estimates ();
- scev_finalize ();
- loop_optimizer_finalize ();
- return 0;
-}
+ basic_block *body = get_loop_body (loop);
+ gimple_stmt_iterator gsi;
+ unsigned size = 0, i;
-namespace {
+ for (i = 0; i < loop->num_nodes; i++)
+ for (gsi = gsi_start_bb (body[i]); !gsi_end_p (gsi); gsi_next (&gsi))
+ size += estimate_num_insns (gsi_stmt (gsi), weights);
+ free (body);
-const pass_data pass_data_tree_loop_done =
-{
- GIMPLE_PASS, /* type */
- "loopdone", /* name */
- OPTGROUP_LOOP, /* optinfo_flags */
- false, /* has_gate */
- true, /* has_execute */
- TV_NONE, /* tv_id */
- PROP_cfg, /* properties_required */
- 0, /* properties_provided */
- 0, /* properties_destroyed */
- 0, /* todo_flags_start */
- ( TODO_cleanup_cfg | TODO_verify_flow ), /* todo_flags_finish */
-};
-
-class pass_tree_loop_done : public gimple_opt_pass
-{
-public:
- pass_tree_loop_done(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_tree_loop_done, ctxt)
- {}
-
- /* opt_pass methods: */
- unsigned int execute () { return tree_ssa_loop_done (); }
+ return size;
+}
-}; // class pass_tree_loop_done
-} // anon namespace
-gimple_opt_pass *
-make_pass_tree_loop_done (gcc::context *ctxt)
-{
- return new pass_tree_loop_done (ctxt);
-}
diff --git a/gcc/tree-ssa-loop.h b/gcc/tree-ssa-loop.h
new file mode 100644
index 00000000000..82799ff6adc
--- /dev/null
+++ b/gcc/tree-ssa-loop.h
@@ -0,0 +1,81 @@
+/* Header file for SSA loop optimizations.
+ Copyright (C) 2013 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_SSA_LOOP_H
+#define GCC_TREE_SSA_LOOP_H
+
+/* Affine iv. */
+
+typedef struct affine_iv_d
+{
+ /* Iv = BASE + STEP * i. */
+ tree base, step;
+
+ /* True if this iv does not overflow. */
+ bool no_overflow;
+} affine_iv;
+
+/* Description of number of iterations of a loop. All the expressions inside
+ the structure can be evaluated at the end of the loop's preheader
+ (and due to ssa form, also anywhere inside the body of the loop). */
+
+struct tree_niter_desc
+{
+ tree assumptions; /* The boolean expression. If this expression evaluates
+ to false, then the other fields in this structure
+ should not be used; there is no guarantee that they
+ will be correct. */
+ tree may_be_zero; /* The boolean expression. If it evaluates to true,
+ the loop will exit in the first iteration (i.e.
+ its latch will not be executed), even if the niter
+ field says otherwise. */
+ tree niter; /* The expression giving the number of iterations of
+ a loop (provided that assumptions == true and
+ may_be_zero == false), more precisely the number
+ of executions of the latch of the loop. */
+ double_int max; /* The upper bound on the number of iterations of
+ the loop. */
+
+ /* The simplified shape of the exit condition. The loop exits if
+ CONTROL CMP BOUND is false, where CMP is one of NE_EXPR,
+ LT_EXPR, or GT_EXPR, and step of CONTROL is positive if CMP is
+ LE_EXPR and negative if CMP is GE_EXPR. This information is used
+ by loop unrolling. */
+ affine_iv control;
+ tree bound;
+ enum tree_code cmp;
+};
+
+extern bool for_each_index (tree *, bool (*) (tree, tree *, void *), void *);
+extern char *get_lsm_tmp_name (tree ref, unsigned n, const char *suffix = NULL);
+extern unsigned tree_num_loop_insns (struct loop *, struct eni_weights_d *);
+
+/* Returns the loop of the statement STMT. */
+
+static inline struct loop *
+loop_containing_stmt (gimple stmt)
+{
+ basic_block bb = gimple_bb (stmt);
+ if (!bb)
+ return NULL;
+
+ return bb->loop_father;
+}
+
+#endif /* GCC_TREE_SSA_LOOP_H */
diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c
index 54445beee7c..9a294111945 100644
--- a/gcc/tree-ssa-math-opts.c
+++ b/gcc/tree-ssa-math-opts.c
@@ -90,6 +90,13 @@ along with GCC; see the file COPYING3. If not see
#include "tm.h"
#include "flags.h"
#include "tree.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-cfg.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
+#include "tree-dfa.h"
#include "tree-ssa.h"
#include "tree-pass.h"
#include "alloc-pool.h"
@@ -608,7 +615,7 @@ execute_cse_reciprocals (void)
if (fail)
continue;
- gimple_replace_lhs (stmt1, arg1);
+ gimple_replace_ssa_lhs (stmt1, arg1);
gimple_call_set_fndecl (stmt1, fndecl);
update_stmt (stmt1);
reciprocal_stats.rfuncs_inserted++;
@@ -657,8 +664,8 @@ const pass_data pass_data_cse_reciprocals =
class pass_cse_reciprocals : public gimple_opt_pass
{
public:
- pass_cse_reciprocals(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_cse_reciprocals, ctxt)
+ pass_cse_reciprocals (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_cse_reciprocals, ctxt)
{}
/* opt_pass methods: */
@@ -1575,8 +1582,8 @@ const pass_data pass_data_cse_sincos =
class pass_cse_sincos : public gimple_opt_pass
{
public:
- pass_cse_sincos(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_cse_sincos, ctxt)
+ pass_cse_sincos (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_cse_sincos, ctxt)
{}
/* opt_pass methods: */
@@ -2065,8 +2072,8 @@ const pass_data pass_data_optimize_bswap =
class pass_optimize_bswap : public gimple_opt_pass
{
public:
- pass_optimize_bswap(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_optimize_bswap, ctxt)
+ pass_optimize_bswap (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_optimize_bswap, ctxt)
{}
/* opt_pass methods: */
@@ -2425,20 +2432,25 @@ convert_plusminus_to_widen (gimple_stmt_iterator *gsi, gimple stmt,
It might also appear that it would be sufficient to use the existing
operands of the widening multiply, but that would limit the choice of
- multiply-and-accumulate instructions. */
+ multiply-and-accumulate instructions.
+
+ If the widened-multiplication result has more than one uses, it is
+ probably wiser not to do the conversion. */
if (code == PLUS_EXPR
&& (rhs1_code == MULT_EXPR || rhs1_code == WIDEN_MULT_EXPR))
{
- if (!is_widening_mult_p (rhs1_stmt, &type1, &mult_rhs1,
- &type2, &mult_rhs2))
+ if (!has_single_use (rhs1)
+ || !is_widening_mult_p (rhs1_stmt, &type1, &mult_rhs1,
+ &type2, &mult_rhs2))
return false;
add_rhs = rhs2;
conv_stmt = conv1_stmt;
}
else if (rhs2_code == MULT_EXPR || rhs2_code == WIDEN_MULT_EXPR)
{
- if (!is_widening_mult_p (rhs2_stmt, &type1, &mult_rhs1,
- &type2, &mult_rhs2))
+ if (!has_single_use (rhs2)
+ || !is_widening_mult_p (rhs2_stmt, &type1, &mult_rhs1,
+ &type2, &mult_rhs2))
return false;
add_rhs = rhs1;
conv_stmt = conv2_stmt;
@@ -2871,8 +2883,8 @@ const pass_data pass_data_optimize_widening_mul =
class pass_optimize_widening_mul : public gimple_opt_pass
{
public:
- pass_optimize_widening_mul(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_optimize_widening_mul, ctxt)
+ pass_optimize_widening_mul (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_optimize_widening_mul, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/tree-ssa-operands.c b/gcc/tree-ssa-operands.c
index 7e02bd8bfb5..4e05d2df046 100644
--- a/gcc/tree-ssa-operands.c
+++ b/gcc/tree-ssa-operands.c
@@ -25,7 +25,12 @@ along with GCC; see the file COPYING3. If not see
#include "flags.h"
#include "function.h"
#include "gimple-pretty-print.h"
-#include "tree-ssa.h"
+#include "bitmap.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
#include "tree-inline.h"
#include "timevar.h"
#include "dumpfile.h"
@@ -122,6 +127,13 @@ static void get_expr_operands (gimple, tree *, int);
/* Number of functions with initialized ssa_operands. */
static int n_initialized = 0;
+/* Accessor to tree-ssa-operands.c caches. */
+static inline struct ssa_operands *
+gimple_ssa_operands (const struct function *fun)
+{
+ return &fun->gimple_df->ssa_operands;
+}
+
/* Return true if the SSA operands cache is active. */
@@ -1092,18 +1104,19 @@ update_stmt_operands (gimple stmt)
to test the validity of the swap operation. */
void
-swap_tree_operands (gimple stmt, tree *exp0, tree *exp1)
+swap_ssa_operands (gimple stmt, tree *exp0, tree *exp1)
{
tree op0, op1;
op0 = *exp0;
op1 = *exp1;
- /* If the operand cache is active, attempt to preserve the relative
- positions of these two operands in their respective immediate use
- lists by adjusting their use pointer to point to the new
- operand position. */
- if (ssa_operands_active (cfun) && op0 != op1)
+ gcc_checking_assert (ssa_operands_active (cfun));
+
+ if (op0 != op1)
{
+ /* Attempt to preserve the relative positions of these two operands in
+ their * respective immediate use lists by adjusting their use pointer
+ to point to the new operand position. */
use_optype_p use0, use1, ptr;
use0 = use1 = NULL;
@@ -1128,11 +1141,11 @@ swap_tree_operands (gimple stmt, tree *exp0, tree *exp1)
USE_OP_PTR (use0)->use = exp1;
if (use1)
USE_OP_PTR (use1)->use = exp0;
- }
- /* Now swap the data. */
- *exp0 = op1;
- *exp1 = op0;
+ /* Now swap the data. */
+ *exp0 = op1;
+ *exp1 = op0;
+ }
}
@@ -1203,7 +1216,7 @@ verify_imm_links (FILE *f, tree var)
fprintf (f, " IMM ERROR : (use_p : tree - %p:%p)", (void *)ptr,
(void *)ptr->use);
print_generic_expr (f, USE_FROM_PTR (ptr), TDF_SLIM);
- fprintf(f, "\n");
+ fprintf (f, "\n");
return true;
}
@@ -1238,7 +1251,7 @@ dump_immediate_uses_for (FILE *file, tree var)
else
print_gimple_stmt (file, USE_STMT (use_p), 0, TDF_SLIM);
}
- fprintf(file, "\n");
+ fprintf (file, "\n");
}
@@ -1253,7 +1266,7 @@ dump_immediate_uses (FILE *file)
fprintf (file, "Immediate_uses: \n\n");
for (x = 1; x < num_ssa_names; x++)
{
- var = ssa_name(x);
+ var = ssa_name (x);
if (!var)
continue;
dump_immediate_uses_for (file, var);
@@ -1279,24 +1292,6 @@ debug_immediate_uses_for (tree var)
}
-/* Return true if OP, an SSA name or a DECL is a virtual operand. */
-
-bool
-virtual_operand_p (tree op)
-{
- if (TREE_CODE (op) == SSA_NAME)
- {
- op = SSA_NAME_VAR (op);
- if (!op)
- return false;
- }
-
- if (TREE_CODE (op) == VAR_DECL)
- return VAR_DECL_IS_VIRTUAL_OPERAND (op);
-
- return false;
-}
-
/* Unlink STMTs virtual definition from the IL by propagating its use. */
void
@@ -1322,3 +1317,47 @@ unlink_stmt_vdef (gimple stmt)
SSA_NAME_OCCURS_IN_ABNORMAL_PHI (vuse) = 1;
}
+
+/* Return true if the var whose chain of uses starts at PTR has no
+ nondebug uses. */
+bool
+has_zero_uses_1 (const ssa_use_operand_t *head)
+{
+ const ssa_use_operand_t *ptr;
+
+ for (ptr = head->next; ptr != head; ptr = ptr->next)
+ if (!is_gimple_debug (USE_STMT (ptr)))
+ return false;
+
+ return true;
+}
+
+
+/* Return true if the var whose chain of uses starts at PTR has a
+ single nondebug use. Set USE_P and STMT to that single nondebug
+ use, if so, or to NULL otherwise. */
+bool
+single_imm_use_1 (const ssa_use_operand_t *head,
+ use_operand_p *use_p, gimple *stmt)
+{
+ ssa_use_operand_t *ptr, *single_use = 0;
+
+ for (ptr = head->next; ptr != head; ptr = ptr->next)
+ if (!is_gimple_debug (USE_STMT (ptr)))
+ {
+ if (single_use)
+ {
+ single_use = NULL;
+ break;
+ }
+ single_use = ptr;
+ }
+
+ if (use_p)
+ *use_p = single_use;
+
+ if (stmt)
+ *stmt = single_use ? single_use->loc.stmt : NULL;
+
+ return single_use;
+}
diff --git a/gcc/tree-ssa-operands.h b/gcc/tree-ssa-operands.h
index 09a5a02ecf5..759b155a3e7 100644
--- a/gcc/tree-ssa-operands.h
+++ b/gcc/tree-ssa-operands.h
@@ -75,9 +75,11 @@ struct GTY(()) ssa_operands {
#define PHI_RESULT_PTR(PHI) gimple_phi_result_ptr (PHI)
#define PHI_RESULT(PHI) DEF_FROM_PTR (PHI_RESULT_PTR (PHI))
#define SET_PHI_RESULT(PHI, V) SET_DEF (PHI_RESULT_PTR (PHI), (V))
-
-#define PHI_ARG_DEF_PTR(PHI, I) gimple_phi_arg_imm_use_ptr ((PHI), (I))
+/*
#define PHI_ARG_DEF(PHI, I) USE_FROM_PTR (PHI_ARG_DEF_PTR ((PHI), (I)))
+*/
+#define PHI_ARG_DEF_PTR(PHI, I) gimple_phi_arg_imm_use_ptr ((PHI), (I))
+#define PHI_ARG_DEF(PHI, I) gimple_phi_arg_def ((PHI), (I))
#define SET_PHI_ARG_DEF(PHI, I, V) \
SET_USE (PHI_ARG_DEF_PTR ((PHI), (I)), (V))
#define PHI_ARG_DEF_FROM_EDGE(PHI, E) \
@@ -87,136 +89,34 @@ struct GTY(()) ssa_operands {
#define PHI_ARG_INDEX_FROM_USE(USE) phi_arg_index_from_use (USE)
+extern bool ssa_operands_active (struct function *);
extern void init_ssa_operands (struct function *fn);
extern void fini_ssa_operands (void);
-extern void update_stmt_operands (gimple);
+extern bool verify_ssa_operands (gimple stmt);
extern void free_stmt_operands (gimple);
+extern void update_stmt_operands (gimple);
+extern void swap_ssa_operands (gimple, tree *, tree *);
extern bool verify_imm_links (FILE *f, tree var);
-extern bool verify_ssa_operands (gimple stmt);
-extern void dump_immediate_uses (FILE *file);
extern void dump_immediate_uses_for (FILE *file, tree var);
+extern void dump_immediate_uses (FILE *file);
extern void debug_immediate_uses (void);
extern void debug_immediate_uses_for (tree var);
-extern void dump_decl_set (FILE *, bitmap);
-extern void debug_decl_set (bitmap);
-
-extern bool ssa_operands_active (struct function *);
-extern bool virtual_operand_p (tree);
extern void unlink_stmt_vdef (gimple);
-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. */
+/* Return the tree pointed-to by USE. */
+static inline tree
+get_use_from_ptr (use_operand_p use)
+{
+ return *(use->use);
+}
-typedef struct ssa_operand_iterator_d
+/* Return the tree pointed-to by DEF. */
+static inline tree
+get_def_from_ptr (def_operand_p def)
{
- enum ssa_op_iter_type iter_type;
- bool done;
- int flags;
- unsigned i;
- unsigned numops;
- use_optype_p uses;
- gimple stmt;
-} ssa_op_iter;
-
-/* 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), 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), 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)
+ return *def;
+}
#endif /* GCC_TREE_SSA_OPERANDS_H */
diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c
index 39d04ab2801..ef114a01a6d 100644
--- a/gcc/tree-ssa-phiopt.c
+++ b/gcc/tree-ssa-phiopt.c
@@ -27,7 +27,13 @@ along with GCC; see the file COPYING3. If not see
#include "flags.h"
#include "tm_p.h"
#include "basic-block.h"
-#include "tree-ssa.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-cfg.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
+#include "tree-dfa.h"
#include "tree-pass.h"
#include "langhooks.h"
#include "pointer-set.h"
@@ -110,6 +116,26 @@ static bool gate_hoist_loads (void);
This opportunity can sometimes occur as a result of other
optimizations.
+
+ Another case caught by value replacement looks like this:
+
+ bb0:
+ t1 = a == CONST;
+ t2 = b > c;
+ t3 = t1 & t2;
+ if (t3 != 0) goto bb1; else goto bb2;
+ bb1:
+ bb2:
+ x = PHI (CONST, a)
+
+ Gets replaced with:
+ bb0:
+ bb2:
+ t1 = a == CONST;
+ t2 = b > c;
+ t3 = t1 & t2;
+ x = a;
+
ABS Replacement
---------------
@@ -155,7 +181,7 @@ static bool gate_hoist_loads (void);
Adjacent Load Hoisting
----------------------
-
+
This transformation replaces
bb0:
@@ -286,7 +312,7 @@ single_non_singleton_phi_for_edges (gimple_seq seq, edge e0, edge e1)
phi optimizations. Both share much of the infrastructure in how
to match applicable basic block patterns. DO_STORE_ELIM is true
when we want to do conditional store replacement, false otherwise.
- DO_HOIST_LOADS is true when we want to hoist adjacent loads out
+ DO_HOIST_LOADS is true when we want to hoist adjacent loads out
of diamond control flow patterns, false otherwise. */
static unsigned int
tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads)
@@ -308,7 +334,7 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads)
This ensures that we collapse inner ifs before visiting the
outer ones, and also that we do not try to visit a removed
block. */
- bb_order = blocks_in_phiopt_order ();
+ bb_order = single_pred_before_succ_order ();
n = n_basic_blocks - NUM_FIXED_BLOCKS;
for (i = 0; i < n; i++)
@@ -389,7 +415,7 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads)
continue;
}
else
- continue;
+ continue;
e1 = EDGE_SUCC (bb1, 0);
@@ -437,7 +463,7 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads)
if (!candorest)
continue;
-
+
phi = single_non_singleton_phi_for_edges (phis, e1, e2);
if (!phi)
continue;
@@ -476,59 +502,6 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads)
return 0;
}
-/* Returns the list of basic blocks in the function in an order that guarantees
- that if a block X has just a single predecessor Y, then Y is after X in the
- ordering. */
-
-basic_block *
-blocks_in_phiopt_order (void)
-{
- basic_block x, y;
- basic_block *order = XNEWVEC (basic_block, n_basic_blocks);
- unsigned n = n_basic_blocks - NUM_FIXED_BLOCKS;
- unsigned np, i;
- sbitmap visited = sbitmap_alloc (last_basic_block);
-
-#define MARK_VISITED(BB) (bitmap_set_bit (visited, (BB)->index))
-#define VISITED_P(BB) (bitmap_bit_p (visited, (BB)->index))
-
- bitmap_clear (visited);
-
- MARK_VISITED (ENTRY_BLOCK_PTR);
- FOR_EACH_BB (x)
- {
- if (VISITED_P (x))
- continue;
-
- /* Walk the predecessors of x as long as they have precisely one
- predecessor and add them to the list, so that they get stored
- after x. */
- for (y = x, np = 1;
- single_pred_p (y) && !VISITED_P (single_pred (y));
- y = single_pred (y))
- np++;
- for (y = x, i = n - np;
- single_pred_p (y) && !VISITED_P (single_pred (y));
- y = single_pred (y), i++)
- {
- order[i] = y;
- MARK_VISITED (y);
- }
- order[i] = y;
- MARK_VISITED (y);
-
- gcc_assert (i == n - 1);
- n -= np;
- }
-
- sbitmap_free (visited);
- gcc_assert (n == 0);
- return order;
-
-#undef MARK_VISITED
-#undef VISITED_P
-}
-
/* Replace PHI node element whose edge is E in block BB with variable NEW.
Remove the edge from COND_BLOCK which does not lead to BB (COND_BLOCK
is known to have two edges, one of which must reach BB). */
@@ -725,6 +698,93 @@ jump_function_from_stmt (tree *arg, gimple stmt)
return false;
}
+/* RHS is a source argument in a BIT_AND_EXPR which feeds a conditional
+ of the form SSA_NAME NE 0.
+
+ If RHS is fed by a simple EQ_EXPR comparison of two values, see if
+ the two input values of the EQ_EXPR match arg0 and arg1.
+
+ If so update *code and return TRUE. Otherwise return FALSE. */
+
+static bool
+rhs_is_fed_for_value_replacement (const_tree arg0, const_tree arg1,
+ enum tree_code *code, const_tree rhs)
+{
+ /* Obviously if RHS is not an SSA_NAME, we can't look at the defining
+ statement. */
+ if (TREE_CODE (rhs) == SSA_NAME)
+ {
+ gimple def1 = SSA_NAME_DEF_STMT (rhs);
+
+ /* Verify the defining statement has an EQ_EXPR on the RHS. */
+ if (is_gimple_assign (def1) && gimple_assign_rhs_code (def1) == EQ_EXPR)
+ {
+ /* Finally verify the source operands of the EQ_EXPR are equal
+ to arg0 and arg1. */
+ tree op0 = gimple_assign_rhs1 (def1);
+ tree op1 = gimple_assign_rhs2 (def1);
+ if ((operand_equal_for_phi_arg_p (arg0, op0)
+ && operand_equal_for_phi_arg_p (arg1, op1))
+ || (operand_equal_for_phi_arg_p (arg0, op1)
+ && operand_equal_for_phi_arg_p (arg1, op0)))
+ {
+ /* We will perform the optimization. */
+ *code = gimple_assign_rhs_code (def1);
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+/* Return TRUE if arg0/arg1 are equal to the rhs/lhs or lhs/rhs of COND.
+
+ Also return TRUE if arg0/arg1 are equal to the source arguments of a
+ an EQ comparison feeding a BIT_AND_EXPR which feeds COND.
+
+ Return FALSE otherwise. */
+
+static bool
+operand_equal_for_value_replacement (const_tree arg0, const_tree arg1,
+ enum tree_code *code, gimple cond)
+{
+ gimple def;
+ tree lhs = gimple_cond_lhs (cond);
+ tree rhs = gimple_cond_rhs (cond);
+
+ if ((operand_equal_for_phi_arg_p (arg0, lhs)
+ && operand_equal_for_phi_arg_p (arg1, rhs))
+ || (operand_equal_for_phi_arg_p (arg1, lhs)
+ && operand_equal_for_phi_arg_p (arg0, rhs)))
+ return true;
+
+ /* Now handle more complex case where we have an EQ comparison
+ which feeds a BIT_AND_EXPR which feeds COND.
+
+ First verify that COND is of the form SSA_NAME NE 0. */
+ if (*code != NE_EXPR || !integer_zerop (rhs)
+ || TREE_CODE (lhs) != SSA_NAME)
+ return false;
+
+ /* Now ensure that SSA_NAME is set by a BIT_AND_EXPR. */
+ def = SSA_NAME_DEF_STMT (lhs);
+ if (!is_gimple_assign (def) || gimple_assign_rhs_code (def) != BIT_AND_EXPR)
+ return false;
+
+ /* Now verify arg0/arg1 correspond to the source arguments of an
+ EQ comparison feeding the BIT_AND_EXPR. */
+
+ tree tmp = gimple_assign_rhs1 (def);
+ if (rhs_is_fed_for_value_replacement (arg0, arg1, code, tmp))
+ return true;
+
+ tmp = gimple_assign_rhs2 (def);
+ if (rhs_is_fed_for_value_replacement (arg0, arg1, code, tmp))
+ return true;
+
+ return false;
+}
+
/* The function value_replacement does the main work of doing the value
replacement. Return non-zero if the replacement is done. Otherwise return
0. If we remove the middle basic block, return 2.
@@ -794,10 +854,7 @@ value_replacement (basic_block cond_bb, basic_block middle_bb,
We now need to verify that the two arguments in the PHI node match
the two arguments to the equality comparison. */
- if ((operand_equal_for_phi_arg_p (arg0, gimple_cond_lhs (cond))
- && operand_equal_for_phi_arg_p (arg1, gimple_cond_rhs (cond)))
- || (operand_equal_for_phi_arg_p (arg1, gimple_cond_lhs (cond))
- && operand_equal_for_phi_arg_p (arg0, gimple_cond_rhs (cond))))
+ if (operand_equal_for_value_replacement (arg0, arg1, &code, cond))
{
edge e;
tree arg;
@@ -1353,39 +1410,17 @@ add_or_mark_expr (basic_block bb, tree exp,
}
}
-/* Return true when CALL is a call stmt that definitely doesn't
- free any memory or makes it unavailable otherwise. */
-bool
-nonfreeing_call_p (gimple call)
-{
- if (gimple_call_builtin_p (call, BUILT_IN_NORMAL)
- && gimple_call_flags (call) & ECF_LEAF)
- switch (DECL_FUNCTION_CODE (gimple_call_fndecl (call)))
- {
- /* Just in case these become ECF_LEAF in the future. */
- case BUILT_IN_FREE:
- case BUILT_IN_TM_FREE:
- case BUILT_IN_REALLOC:
- case BUILT_IN_STACK_RESTORE:
- return false;
- default:
- return true;
- }
-
- return false;
-}
-
class nontrapping_dom_walker : public dom_walker
{
public:
nontrapping_dom_walker (cdi_direction direction, pointer_set_t *ps)
- : dom_walker (direction), nontrapping_ (ps) {}
+ : dom_walker (direction), m_nontrapping (ps) {}
virtual void before_dom_children (basic_block);
virtual void after_dom_children (basic_block);
private:
- pointer_set_t *nontrapping_;
+ pointer_set_t *m_nontrapping;
};
/* Called by walk_dominator_tree, when entering the block BB. */
@@ -1416,8 +1451,8 @@ nontrapping_dom_walker::before_dom_children (basic_block bb)
nt_call_phase++;
else if (gimple_assign_single_p (stmt) && !gimple_has_volatile_ops (stmt))
{
- add_or_mark_expr (bb, gimple_assign_lhs (stmt), nontrapping_, true);
- add_or_mark_expr (bb, gimple_assign_rhs1 (stmt), nontrapping_, false);
+ add_or_mark_expr (bb, gimple_assign_lhs (stmt), m_nontrapping, true);
+ add_or_mark_expr (bb, gimple_assign_rhs1 (stmt), m_nontrapping, false);
}
}
}
@@ -1645,7 +1680,6 @@ cond_if_else_store_replacement (basic_block then_bb, basic_block else_bb,
data_reference_p then_dr, else_dr;
int i, j;
tree then_lhs, else_lhs;
- vec<gimple> then_stores, else_stores;
basic_block blocks[3];
if (MAX_STORES_TO_SINK == 0)
@@ -1672,8 +1706,7 @@ cond_if_else_store_replacement (basic_block then_bb, basic_block else_bb,
}
/* Find pairs of stores with equal LHS. */
- then_stores.create (1);
- else_stores.create (1);
+ stack_vec<gimple, 1> then_stores, else_stores;
FOR_EACH_VEC_ELT (then_datarefs, i, then_dr)
{
if (DR_IS_READ (then_dr))
@@ -1711,8 +1744,6 @@ cond_if_else_store_replacement (basic_block then_bb, basic_block else_bb,
{
free_data_refs (then_datarefs);
free_data_refs (else_datarefs);
- then_stores.release ();
- else_stores.release ();
return false;
}
@@ -1728,8 +1759,6 @@ cond_if_else_store_replacement (basic_block then_bb, basic_block else_bb,
free_dependence_relations (else_ddrs);
free_data_refs (then_datarefs);
free_data_refs (else_datarefs);
- then_stores.release ();
- else_stores.release ();
return false;
}
blocks[0] = then_bb;
@@ -1755,8 +1784,6 @@ cond_if_else_store_replacement (basic_block then_bb, basic_block else_bb,
free_dependence_relations (else_ddrs);
free_data_refs (then_datarefs);
free_data_refs (else_datarefs);
- then_stores.release ();
- else_stores.release ();
return false;
}
}
@@ -1779,8 +1806,6 @@ cond_if_else_store_replacement (basic_block then_bb, basic_block else_bb,
free_dependence_relations (else_ddrs);
free_data_refs (then_datarefs);
free_data_refs (else_datarefs);
- then_stores.release ();
- else_stores.release ();
return false;
}
}
@@ -1798,8 +1823,6 @@ cond_if_else_store_replacement (basic_block then_bb, basic_block else_bb,
free_dependence_relations (else_ddrs);
free_data_refs (then_datarefs);
free_data_refs (else_datarefs);
- then_stores.release ();
- else_stores.release ();
return ok;
}
@@ -1821,7 +1844,7 @@ local_mem_dependence (gimple stmt, basic_block bb)
/* Given a "diamond" control-flow pattern where BB0 tests a condition,
BB1 and BB2 are "then" and "else" blocks dependent on this test,
- and BB3 rejoins control flow following BB1 and BB2, look for
+ and BB3 rejoins control flow following BB1 and BB2, look for
opportunities to hoist loads as follows. If BB3 contains a PHI of
two loads, one each occurring in BB1 and BB2, and the loads are
provably of adjacent fields in the same structure, then move both
@@ -1871,7 +1894,7 @@ hoist_adjacent_loads (basic_block bb0, basic_block bb1,
arg1 = gimple_phi_arg_def (phi_stmt, 0);
arg2 = gimple_phi_arg_def (phi_stmt, 1);
-
+
if (TREE_CODE (arg1) != SSA_NAME
|| TREE_CODE (arg2) != SSA_NAME
|| SSA_NAME_IS_DEFAULT_DEF (arg1)
@@ -2034,12 +2057,12 @@ const pass_data pass_data_phiopt =
class pass_phiopt : public gimple_opt_pass
{
public:
- pass_phiopt(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_phiopt, ctxt)
+ pass_phiopt (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_phiopt, ctxt)
{}
/* opt_pass methods: */
- opt_pass * clone () { return new pass_phiopt (ctxt_); }
+ opt_pass * clone () { return new pass_phiopt (m_ctxt); }
bool gate () { return gate_phiopt (); }
unsigned int execute () { return tree_ssa_phiopt (); }
@@ -2080,8 +2103,8 @@ const pass_data pass_data_cselim =
class pass_cselim : public gimple_opt_pass
{
public:
- pass_cselim(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_cselim, ctxt)
+ pass_cselim (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_cselim, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/tree-ssa-phiprop.c b/gcc/tree-ssa-phiprop.c
index 66b220fadd1..e0e682e5dc2 100644
--- a/gcc/tree-ssa-phiprop.c
+++ b/gcc/tree-ssa-phiprop.c
@@ -26,7 +26,11 @@ along with GCC; see the file COPYING3. If not see
#include "tm_p.h"
#include "basic-block.h"
#include "gimple-pretty-print.h"
-#include "tree-ssa.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
#include "tree-pass.h"
#include "langhooks.h"
#include "flags.h"
@@ -414,8 +418,8 @@ const pass_data pass_data_phiprop =
class pass_phiprop : public gimple_opt_pass
{
public:
- pass_phiprop(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_phiprop, ctxt)
+ pass_phiprop (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_phiprop, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c
index c53ec44913a..1f5ff23cb3f 100644
--- a/gcc/tree-ssa-pre.c
+++ b/gcc/tree-ssa-pre.c
@@ -27,15 +27,22 @@ along with GCC; see the file COPYING3. If not see
#include "basic-block.h"
#include "gimple-pretty-print.h"
#include "tree-inline.h"
-#include "tree-ssa.h"
#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-cfg.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
+#include "tree-ssa-loop.h"
+#include "tree-into-ssa.h"
+#include "tree-dfa.h"
+#include "tree-ssa.h"
#include "hash-table.h"
#include "tree-iterator.h"
#include "alloc-pool.h"
#include "obstack.h"
#include "tree-pass.h"
#include "flags.h"
-#include "bitmap.h"
#include "langhooks.h"
#include "cfgloop.h"
#include "tree-ssa-sccvn.h"
@@ -44,6 +51,7 @@ along with GCC; see the file COPYING3. If not see
#include "dbgcnt.h"
#include "domwalk.h"
#include "ipa-prop.h"
+#include "tree-ssa-propagate.h"
/* TODO:
@@ -360,10 +368,10 @@ typedef struct bitmap_set
} *bitmap_set_t;
#define FOR_EACH_EXPR_ID_IN_SET(set, id, bi) \
- EXECUTE_IF_SET_IN_BITMAP(&(set)->expressions, 0, (id), (bi))
+ EXECUTE_IF_SET_IN_BITMAP (&(set)->expressions, 0, (id), (bi))
#define FOR_EACH_VALUE_ID_IN_SET(set, id, bi) \
- EXECUTE_IF_SET_IN_BITMAP(&(set)->values, 0, (id), (bi))
+ EXECUTE_IF_SET_IN_BITMAP (&(set)->values, 0, (id), (bi))
/* Mapping from value id to expressions with that value_id. */
static vec<bitmap> value_expressions;
@@ -525,46 +533,31 @@ expr_pred_trans_d::equal (const value_type *ve1,
expression and predecessor. */
static hash_table <expr_pred_trans_d> phi_translate_table;
-/* Search in the phi translation table for the translation of
- expression E in basic block PRED.
- Return the translated value, if found, NULL otherwise. */
-
-static inline pre_expr
-phi_trans_lookup (pre_expr e, basic_block pred)
-{
- expr_pred_trans_t *slot;
- struct expr_pred_trans_d ept;
-
- ept.e = e;
- ept.pred = pred;
- ept.hashcode = iterative_hash_hashval_t (pre_expr_d::hash (e), pred->index);
- slot = phi_translate_table.find_slot_with_hash (&ept, ept.hashcode,
- NO_INSERT);
- if (!slot)
- return NULL;
- else
- return (*slot)->v;
-}
-
-
/* Add the tuple mapping from {expression E, basic block PRED} to
- value V, to the phi translation table. */
+ the phi translation table and return whether it pre-existed. */
-static inline void
-phi_trans_add (pre_expr e, pre_expr v, basic_block pred)
+static inline bool
+phi_trans_add (expr_pred_trans_t *entry, pre_expr e, basic_block pred)
{
expr_pred_trans_t *slot;
- expr_pred_trans_t new_pair = XNEW (struct expr_pred_trans_d);
- new_pair->e = e;
- new_pair->pred = pred;
- new_pair->v = v;
- new_pair->hashcode = iterative_hash_hashval_t (pre_expr_d::hash (e),
- pred->index);
-
- slot = phi_translate_table.find_slot_with_hash (new_pair,
- new_pair->hashcode, INSERT);
- free (*slot);
- *slot = new_pair;
+ expr_pred_trans_d tem;
+ hashval_t hash = iterative_hash_hashval_t (pre_expr_d::hash (e),
+ pred->index);
+ tem.e = e;
+ tem.pred = pred;
+ tem.hashcode = hash;
+ slot = phi_translate_table.find_slot_with_hash (&tem, hash, INSERT);
+ if (*slot)
+ {
+ *entry = *slot;
+ return true;
+ }
+
+ *entry = *slot = XNEW (struct expr_pred_trans_d);
+ (*entry)->e = e;
+ (*entry)->pred = pred;
+ (*entry)->hashcode = hash;
+ return false;
}
@@ -925,7 +918,7 @@ print_pre_expr (FILE *outfile, const pre_expr expr)
{
unsigned int i;
vn_nary_op_t nary = PRE_EXPR_NARY (expr);
- fprintf (outfile, "{%s,", tree_code_name [nary->opcode]);
+ fprintf (outfile, "{%s,", get_tree_code_name (nary->opcode));
for (i = 0; i < nary->length; i++)
{
print_generic_expr (outfile, nary->op[i], 0);
@@ -950,7 +943,7 @@ print_pre_expr (FILE *outfile, const pre_expr expr)
if (vro->opcode != SSA_NAME
&& TREE_CODE_CLASS (vro->opcode) != tcc_declaration)
{
- fprintf (outfile, "%s", tree_code_name [vro->opcode]);
+ fprintf (outfile, "%s", get_tree_code_name (vro->opcode));
if (vro->op0)
{
fprintf (outfile, "<");
@@ -1359,7 +1352,7 @@ get_expr_type (const pre_expr e)
case NARY:
return PRE_EXPR_NARY (e)->type;
}
- gcc_unreachable();
+ gcc_unreachable ();
}
/* Get a representative SSA_NAME for a given expression.
@@ -1420,7 +1413,7 @@ get_representative_for (const pre_expr e)
print_generic_expr (dump_file, name, 0);
fprintf (dump_file, " for expression:");
print_pre_expr (dump_file, e);
- fprintf (dump_file, "\n");
+ fprintf (dump_file, " (%04d)\n", value_id);
}
return name;
@@ -1503,7 +1496,7 @@ phi_translate_1 (pre_expr expr, bitmap_set_t set1, bitmap_set_t set2,
else
{
new_val_id = get_next_value_id ();
- value_expressions.safe_grow_cleared (get_max_value_id() + 1);
+ value_expressions.safe_grow_cleared (get_max_value_id () + 1);
nary = vn_nary_op_insert_pieces (newnary->length,
newnary->opcode,
newnary->type,
@@ -1561,23 +1554,16 @@ phi_translate_1 (pre_expr expr, bitmap_set_t set1, bitmap_set_t set2,
leader = find_leader_in_sets (op_val_id, set1, set2);
if (!leader)
break;
- /* Make sure we do not recursively translate ourselves
- like for translating a[n_1] with the leader for
- n_1 being a[n_1]. */
- if (get_expression_id (leader) != get_expression_id (expr))
+ opresult = phi_translate (leader, set1, set2, pred, phiblock);
+ if (!opresult)
+ break;
+ if (opresult != leader)
{
- opresult = phi_translate (leader, set1, set2,
- pred, phiblock);
- if (!opresult)
+ tree name = get_representative_for (opresult);
+ if (!name)
break;
- if (opresult != leader)
- {
- tree name = get_representative_for (opresult);
- if (!name)
- break;
- changed |= name != op[n];
- op[n] = name;
- }
+ changed |= name != op[n];
+ op[n] = name;
}
}
if (n != 3)
@@ -1695,7 +1681,8 @@ phi_translate_1 (pre_expr expr, bitmap_set_t set1, bitmap_set_t set2,
if (changed || !same_valid)
{
new_val_id = get_next_value_id ();
- value_expressions.safe_grow_cleared(get_max_value_id() + 1);
+ value_expressions.safe_grow_cleared
+ (get_max_value_id () + 1);
}
else
new_val_id = ref->value_id;
@@ -1751,6 +1738,7 @@ static pre_expr
phi_translate (pre_expr expr, bitmap_set_t set1, bitmap_set_t set2,
basic_block pred, basic_block phiblock)
{
+ expr_pred_trans_t slot = NULL;
pre_expr phitrans;
if (!expr)
@@ -1763,21 +1751,28 @@ phi_translate (pre_expr expr, bitmap_set_t set1, bitmap_set_t set2,
if (value_id_constant_p (get_expr_value_id (expr)))
return expr;
+ /* Don't add translations of NAMEs as those are cheap to translate. */
if (expr->kind != NAME)
{
- phitrans = phi_trans_lookup (expr, pred);
- if (phitrans)
- return phitrans;
+ if (phi_trans_add (&slot, expr, pred))
+ return slot->v;
+ /* Store NULL for the value we want to return in the case of
+ recursing. */
+ slot->v = NULL;
}
/* Translate. */
phitrans = phi_translate_1 (expr, set1, set2, pred, phiblock);
- /* Don't add empty translations to the cache. Neither add
- translations of NAMEs as those are cheap to translate. */
- if (phitrans
- && expr->kind != NAME)
- phi_trans_add (expr, phitrans, pred);
+ if (slot)
+ {
+ if (phitrans)
+ slot->v = phitrans;
+ else
+ /* Remove failed translations again, they cause insert
+ iteration to not pick up new opportunities reliably. */
+ phi_translate_table.remove_elt_with_hash (slot, slot->hashcode);
+ }
return phitrans;
}
@@ -1822,9 +1817,8 @@ phi_translate_set (bitmap_set_t dest, bitmap_set_t set, basic_block pred,
}
/* Find the leader for a value (i.e., the name representing that
- value) in a given set, and return it. If STMT is non-NULL it
- makes sure the defining statement for the leader dominates it.
- Return NULL if no leader is found. */
+ value) in a given set, and return it. Return NULL if no leader
+ is found. */
static pre_expr
bitmap_find_leader (bitmap_set_t set, unsigned int val)
@@ -3005,7 +2999,8 @@ create_expression_by_pieces (basic_block block, pre_expr expr,
{
fprintf (dump_file, "Inserted ");
print_gimple_stmt (dump_file, newstmt, 0, 0);
- fprintf (dump_file, " in predecessor %d\n", block->index);
+ fprintf (dump_file, " in predecessor %d (%04d)\n",
+ block->index, value_id);
}
return name;
@@ -3280,7 +3275,7 @@ insert_into_preds_of_block (basic_block block, unsigned int exprnum,
{
fprintf (dump_file, "Created phi ");
print_gimple_stmt (dump_file, phi, 0, 0);
- fprintf (dump_file, " in block %d\n", block->index);
+ fprintf (dump_file, " in block %d (%04d)\n", block->index, val);
}
pre_stats.phis++;
return true;
@@ -4121,7 +4116,6 @@ eliminate_dom_walker::before_dom_children (basic_block b)
if (!useless_type_conversion_p (TREE_TYPE (res), TREE_TYPE (sprime)))
sprime = fold_convert (TREE_TYPE (res), sprime);
stmt = gimple_build_assign (res, sprime);
- SSA_NAME_DEF_STMT (res) = stmt;
gimple_set_plf (stmt, NECESSARY, gimple_plf (phi, NECESSARY));
gsi2 = gsi_after_labels (b);
@@ -4650,7 +4644,7 @@ init_pre (void)
expressions.create (0);
expressions.safe_push (NULL);
value_expressions.create (get_max_value_id () + 1);
- value_expressions.safe_grow_cleared (get_max_value_id() + 1);
+ value_expressions.safe_grow_cleared (get_max_value_id () + 1);
name_to_id.create (0);
inserted_exprs = BITMAP_ALLOC (NULL);
@@ -4810,8 +4804,8 @@ const pass_data pass_data_pre =
class pass_pre : public gimple_opt_pass
{
public:
- pass_pre(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_pre, ctxt)
+ pass_pre (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_pre, ctxt)
{}
/* opt_pass methods: */
@@ -4880,12 +4874,12 @@ const pass_data pass_data_fre =
class pass_fre : public gimple_opt_pass
{
public:
- pass_fre(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_fre, ctxt)
+ pass_fre (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_fre, ctxt)
{}
/* opt_pass methods: */
- opt_pass * clone () { return new pass_fre (ctxt_); }
+ opt_pass * clone () { return new pass_fre (m_ctxt); }
bool gate () { return gate_fre (); }
unsigned int execute () { return execute_fre (); }
diff --git a/gcc/tree-ssa-propagate.c b/gcc/tree-ssa-propagate.c
index e5dfabcb41c..3456edbf5a0 100644
--- a/gcc/tree-ssa-propagate.c
+++ b/gcc/tree-ssa-propagate.c
@@ -29,12 +29,18 @@
#include "function.h"
#include "gimple-pretty-print.h"
#include "dumpfile.h"
+#include "sbitmap.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-cfg.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
#include "tree-ssa.h"
#include "tree-ssa-propagate.h"
#include "langhooks.h"
#include "vec.h"
#include "value-prof.h"
-#include "gimple.h"
/* This file implements a generic value propagation engine based on
the same propagation used by the SSA-CCP algorithm [1].
@@ -1073,7 +1079,6 @@ substitute_and_fold (ssa_prop_get_value_fn get_value_fn,
{
gimple new_stmt = gimple_build_assign (name, val);
gimple_stmt_iterator gsi2;
- SSA_NAME_DEF_STMT (name) = new_stmt;
gsi2 = gsi_after_labels (gimple_bb (def_stmt));
gsi_insert_before (&gsi2, new_stmt, GSI_SAME_STMT);
remove_phi_node (&gsi, false);
@@ -1226,4 +1231,219 @@ substitute_and_fold (ssa_prop_get_value_fn get_value_fn,
return something_changed;
}
+
+/* Return true if we may propagate ORIG into DEST, false otherwise. */
+
+bool
+may_propagate_copy (tree dest, tree orig)
+{
+ tree type_d = TREE_TYPE (dest);
+ tree type_o = TREE_TYPE (orig);
+
+ /* If ORIG flows in from an abnormal edge, it cannot be propagated. */
+ if (TREE_CODE (orig) == SSA_NAME
+ && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (orig)
+ /* If it is the default definition and an automatic variable then
+ we can though and it is important that we do to avoid
+ uninitialized regular copies. */
+ && !(SSA_NAME_IS_DEFAULT_DEF (orig)
+ && (SSA_NAME_VAR (orig) == NULL_TREE
+ || TREE_CODE (SSA_NAME_VAR (orig)) == VAR_DECL)))
+ return false;
+
+ /* If DEST is an SSA_NAME that flows from an abnormal edge, then it
+ cannot be replaced. */
+ if (TREE_CODE (dest) == SSA_NAME
+ && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (dest))
+ return false;
+
+ /* Do not copy between types for which we *do* need a conversion. */
+ if (!useless_type_conversion_p (type_d, type_o))
+ return false;
+
+ /* Generally propagating virtual operands is not ok as that may
+ create overlapping life-ranges. */
+ if (TREE_CODE (dest) == SSA_NAME && virtual_operand_p (dest))
+ return false;
+
+ /* Anything else is OK. */
+ return true;
+}
+
+/* Like may_propagate_copy, but use as the destination expression
+ the principal expression (typically, the RHS) contained in
+ statement DEST. This is more efficient when working with the
+ gimple tuples representation. */
+
+bool
+may_propagate_copy_into_stmt (gimple dest, tree orig)
+{
+ tree type_d;
+ tree type_o;
+
+ /* If the statement is a switch or a single-rhs assignment,
+ then the expression to be replaced by the propagation may
+ be an SSA_NAME. Fortunately, there is an explicit tree
+ for the expression, so we delegate to may_propagate_copy. */
+
+ if (gimple_assign_single_p (dest))
+ return may_propagate_copy (gimple_assign_rhs1 (dest), orig);
+ else if (gimple_code (dest) == GIMPLE_SWITCH)
+ return may_propagate_copy (gimple_switch_index (dest), orig);
+
+ /* In other cases, the expression is not materialized, so there
+ is no destination to pass to may_propagate_copy. On the other
+ hand, the expression cannot be an SSA_NAME, so the analysis
+ is much simpler. */
+
+ if (TREE_CODE (orig) == SSA_NAME
+ && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (orig))
+ return false;
+
+ if (is_gimple_assign (dest))
+ type_d = TREE_TYPE (gimple_assign_lhs (dest));
+ else if (gimple_code (dest) == GIMPLE_COND)
+ type_d = boolean_type_node;
+ else if (is_gimple_call (dest)
+ && gimple_call_lhs (dest) != NULL_TREE)
+ type_d = TREE_TYPE (gimple_call_lhs (dest));
+ else
+ gcc_unreachable ();
+
+ type_o = TREE_TYPE (orig);
+
+ if (!useless_type_conversion_p (type_d, type_o))
+ return false;
+
+ return true;
+}
+
+/* Similarly, but we know that we're propagating into an ASM_EXPR. */
+
+bool
+may_propagate_copy_into_asm (tree dest ATTRIBUTE_UNUSED)
+{
+ return true;
+}
+
+
+/* Common code for propagate_value and replace_exp.
+
+ Replace use operand OP_P with VAL. FOR_PROPAGATION indicates if the
+ replacement is done to propagate a value or not. */
+
+static void
+replace_exp_1 (use_operand_p op_p, tree val,
+ bool for_propagation ATTRIBUTE_UNUSED)
+{
+#if defined ENABLE_CHECKING
+ tree op = USE_FROM_PTR (op_p);
+
+ gcc_assert (!(for_propagation
+ && TREE_CODE (op) == SSA_NAME
+ && TREE_CODE (val) == SSA_NAME
+ && !may_propagate_copy (op, val)));
+#endif
+
+ if (TREE_CODE (val) == SSA_NAME)
+ SET_USE (op_p, val);
+ else
+ SET_USE (op_p, unshare_expr (val));
+}
+
+
+/* Propagate the value VAL (assumed to be a constant or another SSA_NAME)
+ into the operand pointed to by OP_P.
+
+ Use this version for const/copy propagation as it will perform additional
+ checks to ensure validity of the const/copy propagation. */
+
+void
+propagate_value (use_operand_p op_p, tree val)
+{
+ replace_exp_1 (op_p, val, true);
+}
+
+/* Replace *OP_P with value VAL (assumed to be a constant or another SSA_NAME).
+
+ Use this version when not const/copy propagating values. For example,
+ PRE uses this version when building expressions as they would appear
+ in specific blocks taking into account actions of PHI nodes.
+
+ The statement in which an expression has been replaced should be
+ folded using fold_stmt_inplace. */
+
+void
+replace_exp (use_operand_p op_p, tree val)
+{
+ replace_exp_1 (op_p, val, false);
+}
+
+
+/* Propagate the value VAL (assumed to be a constant or another SSA_NAME)
+ into the tree pointed to by OP_P.
+
+ Use this version for const/copy propagation when SSA operands are not
+ available. It will perform the additional checks to ensure validity of
+ the const/copy propagation, but will not update any operand information.
+ Be sure to mark the stmt as modified. */
+
+void
+propagate_tree_value (tree *op_p, tree val)
+{
+ gcc_checking_assert (!(TREE_CODE (val) == SSA_NAME
+ && *op_p
+ && TREE_CODE (*op_p) == SSA_NAME
+ && !may_propagate_copy (*op_p, val)));
+
+ if (TREE_CODE (val) == SSA_NAME)
+ *op_p = val;
+ else
+ *op_p = unshare_expr (val);
+}
+
+
+/* Like propagate_tree_value, but use as the operand to replace
+ the principal expression (typically, the RHS) contained in the
+ statement referenced by iterator GSI. Note that it is not
+ always possible to update the statement in-place, so a new
+ statement may be created to replace the original. */
+
+void
+propagate_tree_value_into_stmt (gimple_stmt_iterator *gsi, tree val)
+{
+ gimple stmt = gsi_stmt (*gsi);
+
+ if (is_gimple_assign (stmt))
+ {
+ tree expr = NULL_TREE;
+ if (gimple_assign_single_p (stmt))
+ expr = gimple_assign_rhs1 (stmt);
+ propagate_tree_value (&expr, val);
+ gimple_assign_set_rhs_from_tree (gsi, expr);
+ }
+ else if (gimple_code (stmt) == GIMPLE_COND)
+ {
+ tree lhs = NULL_TREE;
+ tree rhs = build_zero_cst (TREE_TYPE (val));
+ propagate_tree_value (&lhs, val);
+ gimple_cond_set_code (stmt, NE_EXPR);
+ gimple_cond_set_lhs (stmt, lhs);
+ gimple_cond_set_rhs (stmt, rhs);
+ }
+ else if (is_gimple_call (stmt)
+ && gimple_call_lhs (stmt) != NULL_TREE)
+ {
+ tree expr = NULL_TREE;
+ bool res;
+ propagate_tree_value (&expr, val);
+ res = update_call_from_tree (gsi, expr);
+ gcc_assert (res);
+ }
+ else if (gimple_code (stmt) == GIMPLE_SWITCH)
+ propagate_tree_value (gimple_switch_index_ptr (stmt), val);
+ else
+ gcc_unreachable ();
+}
+
#include "gt-tree-ssa-propagate.h"
diff --git a/gcc/tree-ssa-propagate.h b/gcc/tree-ssa-propagate.h
index cd6f0254b4a..1b8bf9042e5 100644
--- a/gcc/tree-ssa-propagate.h
+++ b/gcc/tree-ssa-propagate.h
@@ -68,13 +68,20 @@ typedef bool (*ssa_prop_fold_stmt_fn) (gimple_stmt_iterator *gsi);
typedef tree (*ssa_prop_get_value_fn) (tree);
-/* In tree-ssa-propagate.c */
-void ssa_propagate (ssa_prop_visit_stmt_fn, ssa_prop_visit_phi_fn);
-bool valid_gimple_rhs_p (tree);
-void move_ssa_defining_stmt_for_defs (gimple, gimple);
-bool update_gimple_call (gimple_stmt_iterator *, tree, int, ...);
-bool update_call_from_tree (gimple_stmt_iterator *, tree);
-bool stmt_makes_single_store (gimple);
-bool substitute_and_fold (ssa_prop_get_value_fn, ssa_prop_fold_stmt_fn, bool);
+extern bool valid_gimple_rhs_p (tree);
+extern void move_ssa_defining_stmt_for_defs (gimple, gimple);
+extern bool update_gimple_call (gimple_stmt_iterator *, tree, int, ...);
+extern bool update_call_from_tree (gimple_stmt_iterator *, tree);
+extern void ssa_propagate (ssa_prop_visit_stmt_fn, ssa_prop_visit_phi_fn);
+extern bool stmt_makes_single_store (gimple);
+extern bool substitute_and_fold (ssa_prop_get_value_fn, ssa_prop_fold_stmt_fn,
+ bool);
+extern bool may_propagate_copy (tree, tree);
+extern bool may_propagate_copy_into_stmt (gimple, tree);
+extern bool may_propagate_copy_into_asm (tree);
+extern void propagate_value (use_operand_p, tree);
+extern void replace_exp (use_operand_p, tree);
+extern void propagate_tree_value (tree *, tree);
+extern void propagate_tree_value_into_stmt (gimple_stmt_iterator *, tree);
#endif /* _TREE_SSA_PROPAGATE_H */
diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c
index 6dffe7e9a81..538a8ef0e4a 100644
--- a/gcc/tree-ssa-reassoc.c
+++ b/gcc/tree-ssa-reassoc.c
@@ -23,12 +23,22 @@ along with GCC; see the file COPYING3. If not see
#include "coretypes.h"
#include "hash-table.h"
#include "tm.h"
+#include "rtl.h"
+#include "tm_p.h"
#include "tree.h"
#include "basic-block.h"
#include "gimple-pretty-print.h"
#include "tree-inline.h"
-#include "tree-ssa.h"
#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-cfg.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
+#include "tree-ssa-loop-niter.h"
+#include "tree-ssa-loop.h"
+#include "tree-dfa.h"
+#include "tree-ssa.h"
#include "tree-iterator.h"
#include "tree-pass.h"
#include "alloc-pool.h"
@@ -1141,12 +1151,94 @@ zero_one_operation (tree *def, enum tree_code opcode, tree op)
while (1);
}
-/* Returns the UID of STMT if it is non-NULL. Otherwise return 1. */
+/* Returns true if statement S1 dominates statement S2. Like
+ stmt_dominates_stmt_p, but uses stmt UIDs to optimize. */
+
+static bool
+reassoc_stmt_dominates_stmt_p (gimple s1, gimple s2)
+{
+ basic_block bb1 = gimple_bb (s1), bb2 = gimple_bb (s2);
+
+ /* If bb1 is NULL, it should be a GIMPLE_NOP def stmt of an (D)
+ SSA_NAME. Assume it lives at the beginning of function and
+ thus dominates everything. */
+ if (!bb1 || s1 == s2)
+ return true;
+
+ /* If bb2 is NULL, it doesn't dominate any stmt with a bb. */
+ if (!bb2)
+ return false;
+
+ if (bb1 == bb2)
+ {
+ /* PHIs in the same basic block are assumed to be
+ executed all in parallel, if only one stmt is a PHI,
+ it dominates the other stmt in the same basic block. */
+ if (gimple_code (s1) == GIMPLE_PHI)
+ return true;
+
+ if (gimple_code (s2) == GIMPLE_PHI)
+ return false;
+
+ gcc_assert (gimple_uid (s1) && gimple_uid (s2));
+
+ if (gimple_uid (s1) < gimple_uid (s2))
+ return true;
+
+ if (gimple_uid (s1) > gimple_uid (s2))
+ return false;
+
+ gimple_stmt_iterator gsi = gsi_for_stmt (s1);
+ unsigned int uid = gimple_uid (s1);
+ for (gsi_next (&gsi); !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ gimple s = gsi_stmt (gsi);
+ if (gimple_uid (s) != uid)
+ break;
+ if (s == s2)
+ return true;
+ }
+
+ return false;
+ }
+
+ return dominated_by_p (CDI_DOMINATORS, bb2, bb1);
+}
+
+/* Insert STMT after INSERT_POINT. */
-static inline unsigned
-get_stmt_uid_with_default (gimple stmt)
+static void
+insert_stmt_after (gimple stmt, gimple insert_point)
{
- return stmt ? gimple_uid (stmt) : 1;
+ gimple_stmt_iterator gsi;
+ basic_block bb;
+
+ if (gimple_code (insert_point) == GIMPLE_PHI)
+ bb = gimple_bb (insert_point);
+ else if (!stmt_ends_bb_p (insert_point))
+ {
+ gsi = gsi_for_stmt (insert_point);
+ gimple_set_uid (stmt, gimple_uid (insert_point));
+ gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
+ return;
+ }
+ else
+ /* We assume INSERT_POINT is a SSA_NAME_DEF_STMT of some SSA_NAME,
+ thus if it must end a basic block, it should be a call that can
+ throw, or some assignment that can throw. If it throws, the LHS
+ of it will not be initialized though, so only valid places using
+ the SSA_NAME should be dominated by the fallthru edge. */
+ bb = find_fallthru_edge (gimple_bb (insert_point)->succs)->dest;
+ gsi = gsi_after_labels (bb);
+ if (gsi_end_p (gsi))
+ {
+ gimple_stmt_iterator gsi2 = gsi_last_bb (bb);
+ gimple_set_uid (stmt,
+ gsi_end_p (gsi2) ? 1 : gimple_uid (gsi_stmt (gsi2)));
+ }
+ else
+ gimple_set_uid (stmt, gimple_uid (gsi_stmt (gsi)));
+ gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
}
/* Builds one statement performing OP1 OPCODE OP2 using TMPVAR for
@@ -1174,64 +1266,27 @@ build_and_add_sum (tree type, tree op1, tree op2, enum tree_code opcode)
&& (!op2def || gimple_nop_p (op2def)))
{
gsi = gsi_after_labels (single_succ (ENTRY_BLOCK_PTR));
- gimple_set_uid (sum, get_stmt_uid_with_default (gsi_stmt (gsi)));
- gsi_insert_before (&gsi, sum, GSI_NEW_STMT);
- }
- else if ((!op1def || gimple_nop_p (op1def))
- || (op2def && !gimple_nop_p (op2def)
- && stmt_dominates_stmt_p (op1def, op2def)))
- {
- if (gimple_code (op2def) == GIMPLE_PHI)
+ if (gsi_end_p (gsi))
{
- gsi = gsi_after_labels (gimple_bb (op2def));
- gimple_set_uid (sum, get_stmt_uid_with_default (gsi_stmt (gsi)));
- gsi_insert_before (&gsi, sum, GSI_NEW_STMT);
+ gimple_stmt_iterator gsi2
+ = gsi_last_bb (single_succ (ENTRY_BLOCK_PTR));
+ gimple_set_uid (sum,
+ gsi_end_p (gsi2) ? 1 : gimple_uid (gsi_stmt (gsi2)));
}
else
- {
- if (!stmt_ends_bb_p (op2def))
- {
- gsi = gsi_for_stmt (op2def);
- gimple_set_uid (sum, gimple_uid (op2def));
- gsi_insert_after (&gsi, sum, GSI_NEW_STMT);
- }
- else
- {
- edge e;
- edge_iterator ei;
-
- FOR_EACH_EDGE (e, ei, gimple_bb (op2def)->succs)
- if (e->flags & EDGE_FALLTHRU)
- gsi_insert_on_edge_immediate (e, sum);
- }
- }
+ gimple_set_uid (sum, gimple_uid (gsi_stmt (gsi)));
+ gsi_insert_before (&gsi, sum, GSI_NEW_STMT);
}
else
{
- if (gimple_code (op1def) == GIMPLE_PHI)
- {
- gsi = gsi_after_labels (gimple_bb (op1def));
- gimple_set_uid (sum, get_stmt_uid_with_default (gsi_stmt (gsi)));
- gsi_insert_before (&gsi, sum, GSI_NEW_STMT);
- }
+ gimple insert_point;
+ if ((!op1def || gimple_nop_p (op1def))
+ || (op2def && !gimple_nop_p (op2def)
+ && reassoc_stmt_dominates_stmt_p (op1def, op2def)))
+ insert_point = op2def;
else
- {
- if (!stmt_ends_bb_p (op1def))
- {
- gsi = gsi_for_stmt (op1def);
- gimple_set_uid (sum, gimple_uid (op1def));
- gsi_insert_after (&gsi, sum, GSI_NEW_STMT);
- }
- else
- {
- edge e;
- edge_iterator ei;
-
- FOR_EACH_EDGE (e, ei, gimple_bb (op1def)->succs)
- if (e->flags & EDGE_FALLTHRU)
- gsi_insert_on_edge_immediate (e, sum);
- }
- }
+ insert_point = op1def;
+ insert_stmt_after (sum, insert_point);
}
update_stmt (sum);
@@ -1952,8 +2007,8 @@ range_entry_cmp (const void *a, const void *b)
true if the range merge has been successful.
If OPCODE is ERROR_MARK, this is called from within
maybe_optimize_range_tests and is performing inter-bb range optimization.
- Changes should be then performed right away, and whether an op is
- BIT_AND_EXPR or BIT_IOR_EXPR is found in oe->rank. */
+ In that case, whether an op is BIT_AND_EXPR or BIT_IOR_EXPR is found in
+ oe->rank. */
static bool
update_range_test (struct range_entry *range, struct range_entry *otherrange,
@@ -2009,36 +2064,12 @@ update_range_test (struct range_entry *range, struct range_entry *otherrange,
gsi = gsi_for_stmt (stmt);
tem = force_gimple_operand_gsi (&gsi, tem, true, NULL_TREE, true,
GSI_SAME_STMT);
+ for (gsi_prev (&gsi); !gsi_end_p (gsi); gsi_prev (&gsi))
+ if (gimple_uid (gsi_stmt (gsi)))
+ break;
+ else
+ gimple_set_uid (gsi_stmt (gsi), gimple_uid (stmt));
- /* If doing inter-bb range test optimization, update the
- stmts immediately. Start with changing the first range test
- immediate use to the new value (TEM), or, if the first range
- test is a GIMPLE_COND stmt, change that condition. */
- if (opcode == ERROR_MARK)
- {
- if (op)
- {
- imm_use_iterator iter;
- use_operand_p use_p;
- gimple use_stmt;
-
- FOR_EACH_IMM_USE_STMT (use_stmt, iter, op)
- {
- if (is_gimple_debug (use_stmt))
- continue;
- FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
- SET_USE (use_p, tem);
- update_stmt (use_stmt);
- }
- }
- else
- {
- gimple_cond_set_code (stmt, NE_EXPR);
- gimple_cond_set_lhs (stmt, tem);
- gimple_cond_set_rhs (stmt, boolean_false_node);
- update_stmt (stmt);
- }
- }
oe->op = tem;
range->exp = exp;
range->low = low;
@@ -2054,81 +2085,163 @@ update_range_test (struct range_entry *range, struct range_entry *otherrange,
if (opcode == ERROR_MARK)
{
if (oe->op)
- {
- imm_use_iterator iter;
- use_operand_p use_p;
- gimple use_stmt;
+ oe->op = build_int_cst (TREE_TYPE (oe->op),
+ oe->rank == BIT_IOR_EXPR ? 0 : 1);
+ else
+ oe->op = (oe->rank == BIT_IOR_EXPR
+ ? boolean_false_node : boolean_true_node);
+ }
+ else
+ oe->op = error_mark_node;
+ range->exp = NULL_TREE;
+ }
+ return true;
+}
- FOR_EACH_IMM_USE_STMT (use_stmt, iter, oe->op)
- {
- if (is_gimple_debug (use_stmt))
- continue;
- /* If imm use of _8 is a statement like _7 = _8 | _9;,
- adjust it into _7 = _9;. */
- if (is_gimple_assign (use_stmt)
- && gimple_assign_rhs_code (use_stmt) == oe->rank)
- {
- tree expr = NULL_TREE;
- if (oe->op == gimple_assign_rhs1 (use_stmt))
- expr = gimple_assign_rhs2 (use_stmt);
- else if (oe->op == gimple_assign_rhs2 (use_stmt))
- expr = gimple_assign_rhs1 (use_stmt);
- if (expr
- && expr != oe->op
- && TREE_CODE (expr) == SSA_NAME)
- {
- gimple_stmt_iterator gsi2 = gsi_for_stmt (use_stmt);
- gimple_assign_set_rhs_with_ops (&gsi2, SSA_NAME,
- expr, NULL_TREE);
- update_stmt (use_stmt);
- continue;
- }
- }
- /* If imm use of _8 is a statement like _7 = (int) _8;,
- adjust it into _7 = 0; or _7 = 1;. */
- if (gimple_assign_cast_p (use_stmt)
- && oe->op == gimple_assign_rhs1 (use_stmt))
- {
- tree lhs = gimple_assign_lhs (use_stmt);
- if (INTEGRAL_TYPE_P (TREE_TYPE (lhs)))
- {
- gimple_stmt_iterator gsi2
- = gsi_for_stmt (use_stmt);
- tree expr = build_int_cst (TREE_TYPE (lhs),
- oe->rank == BIT_IOR_EXPR
- ? 0 : 1);
- gimple_assign_set_rhs_with_ops (&gsi2,
- INTEGER_CST,
- expr, NULL_TREE);
- update_stmt (use_stmt);
- continue;
- }
- }
- /* Otherwise replace the use with 0 or 1. */
- FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
- SET_USE (use_p,
- build_int_cst (TREE_TYPE (oe->op),
- oe->rank == BIT_IOR_EXPR
- ? 0 : 1));
- update_stmt (use_stmt);
- }
- }
+/* Optimize X == CST1 || X == CST2
+ if popcount (CST1 ^ CST2) == 1 into
+ (X & ~(CST1 ^ CST2)) == (CST1 & ~(CST1 ^ CST2)).
+ Similarly for ranges. E.g.
+ X != 2 && X != 3 && X != 10 && X != 11
+ will be transformed by the previous optimization into
+ !((X - 2U) <= 1U || (X - 10U) <= 1U)
+ and this loop can transform that into
+ !(((X & ~8) - 2U) <= 1U). */
+
+static bool
+optimize_range_tests_xor (enum tree_code opcode, tree type,
+ tree lowi, tree lowj, tree highi, tree highj,
+ vec<operand_entry_t> *ops,
+ struct range_entry *rangei,
+ struct range_entry *rangej)
+{
+ tree lowxor, highxor, tem, exp;
+ /* Check highi ^ lowi == highj ^ lowj and
+ popcount (highi ^ lowi) == 1. */
+ lowxor = fold_binary (BIT_XOR_EXPR, type, lowi, lowj);
+ if (lowxor == NULL_TREE || TREE_CODE (lowxor) != INTEGER_CST)
+ return false;
+ if (tree_log2 (lowxor) < 0)
+ return false;
+ highxor = fold_binary (BIT_XOR_EXPR, type, highi, highj);
+ if (!tree_int_cst_equal (lowxor, highxor))
+ return false;
+
+ tem = fold_build1 (BIT_NOT_EXPR, type, lowxor);
+ exp = fold_build2 (BIT_AND_EXPR, type, rangei->exp, tem);
+ lowj = fold_build2 (BIT_AND_EXPR, type, lowi, tem);
+ highj = fold_build2 (BIT_AND_EXPR, type, highi, tem);
+ if (update_range_test (rangei, rangej, 1, opcode, ops, exp,
+ rangei->in_p, lowj, highj,
+ rangei->strict_overflow_p
+ || rangej->strict_overflow_p))
+ return true;
+ return false;
+}
+
+/* Optimize X == CST1 || X == CST2
+ if popcount (CST2 - CST1) == 1 into
+ ((X - CST1) & ~(CST2 - CST1)) == 0.
+ Similarly for ranges. E.g.
+ X == 43 || X == 76 || X == 44 || X == 78 || X == 77 || X == 46
+ || X == 75 || X == 45
+ will be transformed by the previous optimization into
+ (X - 43U) <= 3U || (X - 75U) <= 3U
+ and this loop can transform that into
+ ((X - 43U) & ~(75U - 43U)) <= 3U. */
+static bool
+optimize_range_tests_diff (enum tree_code opcode, tree type,
+ tree lowi, tree lowj, tree highi, tree highj,
+ vec<operand_entry_t> *ops,
+ struct range_entry *rangei,
+ struct range_entry *rangej)
+{
+ tree tem1, tem2, mask;
+ /* Check highi - lowi == highj - lowj. */
+ tem1 = fold_binary (MINUS_EXPR, type, highi, lowi);
+ if (tem1 == NULL_TREE || TREE_CODE (tem1) != INTEGER_CST)
+ return false;
+ tem2 = fold_binary (MINUS_EXPR, type, highj, lowj);
+ if (!tree_int_cst_equal (tem1, tem2))
+ return false;
+ /* Check popcount (lowj - lowi) == 1. */
+ tem1 = fold_binary (MINUS_EXPR, type, lowj, lowi);
+ if (tem1 == NULL_TREE || TREE_CODE (tem1) != INTEGER_CST)
+ return false;
+ if (tree_log2 (tem1) < 0)
+ return false;
+
+ mask = fold_build1 (BIT_NOT_EXPR, type, tem1);
+ tem1 = fold_binary (MINUS_EXPR, type, rangei->exp, lowi);
+ tem1 = fold_build2 (BIT_AND_EXPR, type, tem1, mask);
+ lowj = build_int_cst (type, 0);
+ if (update_range_test (rangei, rangej, 1, opcode, ops, tem1,
+ rangei->in_p, lowj, tem2,
+ rangei->strict_overflow_p
+ || rangej->strict_overflow_p))
+ return true;
+ return false;
+}
+
+/* It does some common checks for function optimize_range_tests_xor and
+ optimize_range_tests_diff.
+ If OPTIMIZE_XOR is TRUE, it calls optimize_range_tests_xor.
+ Else it calls optimize_range_tests_diff. */
+
+static bool
+optimize_range_tests_1 (enum tree_code opcode, int first, int length,
+ bool optimize_xor, vec<operand_entry_t> *ops,
+ struct range_entry *ranges)
+{
+ int i, j;
+ bool any_changes = false;
+ for (i = first; i < length; i++)
+ {
+ tree lowi, highi, lowj, highj, type, tem;
+
+ if (ranges[i].exp == NULL_TREE || ranges[i].in_p)
+ continue;
+ type = TREE_TYPE (ranges[i].exp);
+ if (!INTEGRAL_TYPE_P (type))
+ continue;
+ lowi = ranges[i].low;
+ if (lowi == NULL_TREE)
+ lowi = TYPE_MIN_VALUE (type);
+ highi = ranges[i].high;
+ if (highi == NULL_TREE)
+ continue;
+ for (j = i + 1; j < length && j < i + 64; j++)
+ {
+ bool changes;
+ if (ranges[i].exp != ranges[j].exp || ranges[j].in_p)
+ continue;
+ lowj = ranges[j].low;
+ if (lowj == NULL_TREE)
+ continue;
+ highj = ranges[j].high;
+ if (highj == NULL_TREE)
+ highj = TYPE_MAX_VALUE (type);
+ /* Check lowj > highi. */
+ tem = fold_binary (GT_EXPR, boolean_type_node,
+ lowj, highi);
+ if (tem == NULL_TREE || !integer_onep (tem))
+ continue;
+ if (optimize_xor)
+ changes = optimize_range_tests_xor (opcode, type, lowi, lowj,
+ highi, highj, ops,
+ ranges + i, ranges + j);
else
+ changes = optimize_range_tests_diff (opcode, type, lowi, lowj,
+ highi, highj, ops,
+ ranges + i, ranges + j);
+ if (changes)
{
- /* If range test was a GIMPLE_COND, simply change it
- into an always false or always true condition. */
- stmt = last_stmt (BASIC_BLOCK (oe->id));
- if (oe->rank == BIT_IOR_EXPR)
- gimple_cond_make_false (stmt);
- else
- gimple_cond_make_true (stmt);
- update_stmt (stmt);
+ any_changes = true;
+ break;
}
}
- oe->op = error_mark_node;
- range->exp = NULL_TREE;
}
- return true;
+ return any_changes;
}
/* Optimize range tests, similarly how fold_range_test optimizes
@@ -2140,7 +2253,7 @@ update_range_test (struct range_entry *range, struct range_entry *otherrange,
GIMPLE_COND is && or ||ed into the test, and oe->rank says
the actual opcode. */
-static void
+static bool
optimize_range_tests (enum tree_code opcode,
vec<operand_entry_t> *ops)
{
@@ -2150,7 +2263,7 @@ optimize_range_tests (enum tree_code opcode,
bool any_changes = false;
if (length == 1)
- return;
+ return false;
ranges = XNEWVEC (struct range_entry, length);
for (i = 0; i < length; i++)
@@ -2208,76 +2321,12 @@ optimize_range_tests (enum tree_code opcode,
++update_fail_count;
}
- /* Optimize X == CST1 || X == CST2
- if popcount (CST1 ^ CST2) == 1 into
- (X & ~(CST1 ^ CST2)) == (CST1 & ~(CST1 ^ CST2)).
- Similarly for ranges. E.g.
- X != 2 && X != 3 && X != 10 && X != 11
- will be transformed by the above loop into
- (X - 2U) <= 1U && (X - 10U) <= 1U
- and this loop can transform that into
- ((X & ~8) - 2U) <= 1U. */
- for (i = first; i < length; i++)
- {
- tree lowi, highi, lowj, highj, type, lowxor, highxor, tem, exp;
+ any_changes |= optimize_range_tests_1 (opcode, first, length, true,
+ ops, ranges);
- if (ranges[i].exp == NULL_TREE || ranges[i].in_p)
- continue;
- type = TREE_TYPE (ranges[i].exp);
- if (!INTEGRAL_TYPE_P (type))
- continue;
- lowi = ranges[i].low;
- if (lowi == NULL_TREE)
- lowi = TYPE_MIN_VALUE (type);
- highi = ranges[i].high;
- if (highi == NULL_TREE)
- continue;
- for (j = i + 1; j < length && j < i + 64; j++)
- {
- if (ranges[j].exp == NULL_TREE)
- continue;
- if (ranges[i].exp != ranges[j].exp)
- break;
- if (ranges[j].in_p)
- continue;
- lowj = ranges[j].low;
- if (lowj == NULL_TREE)
- continue;
- highj = ranges[j].high;
- if (highj == NULL_TREE)
- highj = TYPE_MAX_VALUE (type);
- tem = fold_binary (GT_EXPR, boolean_type_node,
- lowj, highi);
- if (tem == NULL_TREE || !integer_onep (tem))
- continue;
- lowxor = fold_binary (BIT_XOR_EXPR, type, lowi, lowj);
- if (lowxor == NULL_TREE || TREE_CODE (lowxor) != INTEGER_CST)
- continue;
- gcc_checking_assert (!integer_zerop (lowxor));
- tem = fold_binary (MINUS_EXPR, type, lowxor,
- build_int_cst (type, 1));
- if (tem == NULL_TREE)
- continue;
- tem = fold_binary (BIT_AND_EXPR, type, lowxor, tem);
- if (tem == NULL_TREE || !integer_zerop (tem))
- continue;
- highxor = fold_binary (BIT_XOR_EXPR, type, highi, highj);
- if (!tree_int_cst_equal (lowxor, highxor))
- continue;
- tem = fold_build1 (BIT_NOT_EXPR, type, lowxor);
- exp = fold_build2 (BIT_AND_EXPR, type, ranges[i].exp, tem);
- lowj = fold_build2 (BIT_AND_EXPR, type, lowi, tem);
- highj = fold_build2 (BIT_AND_EXPR, type, highi, tem);
- if (update_range_test (ranges + i, ranges + j, 1, opcode, ops, exp,
- ranges[i].in_p, lowj, highj,
- ranges[i].strict_overflow_p
- || ranges[j].strict_overflow_p))
- {
- any_changes = true;
- break;
- }
- }
- }
+ if (BRANCH_COST (optimize_function_for_speed_p (cfun), false) >= 2)
+ any_changes |= optimize_range_tests_1 (opcode, first, length, false,
+ ops, ranges);
if (any_changes && opcode != ERROR_MARK)
{
@@ -2294,6 +2343,7 @@ optimize_range_tests (enum tree_code opcode,
}
XDELETEVEC (ranges);
+ return any_changes;
}
/* Return true if STMT is a cast like:
@@ -2540,6 +2590,60 @@ get_ops (tree var, enum tree_code code, vec<operand_entry_t> *ops,
return true;
}
+/* Find the ops that were added by get_ops starting from VAR, see if
+ they were changed during update_range_test and if yes, create new
+ stmts. */
+
+static tree
+update_ops (tree var, enum tree_code code, vec<operand_entry_t> ops,
+ unsigned int *pidx, struct loop *loop)
+{
+ gimple stmt = SSA_NAME_DEF_STMT (var);
+ tree rhs[4];
+ int i;
+
+ if (!is_reassociable_op (stmt, code, loop))
+ return NULL;
+
+ rhs[0] = gimple_assign_rhs1 (stmt);
+ rhs[1] = gimple_assign_rhs2 (stmt);
+ rhs[2] = rhs[0];
+ rhs[3] = rhs[1];
+ for (i = 0; i < 2; i++)
+ if (TREE_CODE (rhs[i]) == SSA_NAME)
+ {
+ rhs[2 + i] = update_ops (rhs[i], code, ops, pidx, loop);
+ if (rhs[2 + i] == NULL_TREE)
+ {
+ if (has_single_use (rhs[i]))
+ rhs[2 + i] = ops[(*pidx)++]->op;
+ else
+ rhs[2 + i] = rhs[i];
+ }
+ }
+ if ((rhs[2] != rhs[0] || rhs[3] != rhs[1])
+ && (rhs[2] != rhs[1] || rhs[3] != rhs[0]))
+ {
+ gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
+ var = make_ssa_name (TREE_TYPE (var), NULL);
+ gimple g = gimple_build_assign_with_ops (gimple_assign_rhs_code (stmt),
+ var, rhs[2], rhs[3]);
+ gimple_set_uid (g, gimple_uid (stmt));
+ gimple_set_visited (g, true);
+ gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+ }
+ return var;
+}
+
+/* Structure to track the initial value passed to get_ops and
+ the range in the ops vector for each basic block. */
+
+struct inter_bb_range_test_entry
+{
+ tree op;
+ unsigned int first_idx, last_idx;
+};
+
/* Inter-bb range test optimization. */
static void
@@ -2552,6 +2656,8 @@ maybe_optimize_range_tests (gimple stmt)
edge_iterator ei;
edge e;
vec<operand_entry_t> ops = vNULL;
+ vec<inter_bb_range_test_entry> bbinfo = vNULL;
+ bool any_changes = false;
/* Consider only basic blocks that end with GIMPLE_COND or
a cast statement satisfying final_range_test_p. All
@@ -2653,7 +2759,11 @@ maybe_optimize_range_tests (gimple stmt)
{
enum tree_code code;
tree lhs, rhs;
+ inter_bb_range_test_entry bb_ent;
+ bb_ent.op = NULL_TREE;
+ bb_ent.first_idx = ops.length ();
+ bb_ent.last_idx = bb_ent.first_idx;
e = find_edge (bb, other_bb);
stmt = last_stmt (bb);
gimple_set_visited (stmt, true);
@@ -2710,7 +2820,12 @@ maybe_optimize_range_tests (gimple stmt)
oe->id = 0;
oe->count = 1;
ops.safe_push (oe);
+ bb_ent.last_idx++;
}
+ else
+ bb_ent.last_idx = ops.length ();
+ bb_ent.op = rhs;
+ bbinfo.safe_push (bb_ent);
continue;
}
/* Otherwise stmt is GIMPLE_COND. */
@@ -2743,12 +2858,119 @@ maybe_optimize_range_tests (gimple stmt)
oe->id = bb->index;
oe->count = 1;
ops.safe_push (oe);
+ bb_ent.op = NULL;
+ bb_ent.last_idx++;
+ }
+ else if (ops.length () > bb_ent.first_idx)
+ {
+ bb_ent.op = lhs;
+ bb_ent.last_idx = ops.length ();
}
+ bbinfo.safe_push (bb_ent);
if (bb == first_bb)
break;
}
if (ops.length () > 1)
- optimize_range_tests (ERROR_MARK, &ops);
+ any_changes = optimize_range_tests (ERROR_MARK, &ops);
+ if (any_changes)
+ {
+ unsigned int idx;
+ /* update_ops relies on has_single_use predicates returning the
+ same values as it did during get_ops earlier. Additionally it
+ never removes statements, only adds new ones and it should walk
+ from the single imm use and check the predicate already before
+ making those changes.
+ On the other side, the handling of GIMPLE_COND directly can turn
+ previously multiply used SSA_NAMEs into single use SSA_NAMEs, so
+ it needs to be done in a separate loop afterwards. */
+ for (bb = last_bb, idx = 0; ; bb = single_pred (bb), idx++)
+ {
+ if (bbinfo[idx].first_idx < bbinfo[idx].last_idx
+ && bbinfo[idx].op != NULL_TREE)
+ {
+ tree new_op;
+
+ stmt = last_stmt (bb);
+ new_op = update_ops (bbinfo[idx].op,
+ (enum tree_code)
+ ops[bbinfo[idx].first_idx]->rank,
+ ops, &bbinfo[idx].first_idx,
+ loop_containing_stmt (stmt));
+ if (new_op == NULL_TREE)
+ {
+ gcc_assert (bb == last_bb);
+ new_op = ops[bbinfo[idx].first_idx++]->op;
+ }
+ if (bbinfo[idx].op != new_op)
+ {
+ imm_use_iterator iter;
+ use_operand_p use_p;
+ gimple use_stmt, cast_stmt = NULL;
+
+ FOR_EACH_IMM_USE_STMT (use_stmt, iter, bbinfo[idx].op)
+ if (is_gimple_debug (use_stmt))
+ continue;
+ else if (gimple_code (use_stmt) == GIMPLE_COND
+ || gimple_code (use_stmt) == GIMPLE_PHI)
+ FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
+ SET_USE (use_p, new_op);
+ else if (gimple_assign_cast_p (use_stmt))
+ cast_stmt = use_stmt;
+ else
+ gcc_unreachable ();
+ if (cast_stmt)
+ {
+ gcc_assert (bb == last_bb);
+ tree lhs = gimple_assign_lhs (cast_stmt);
+ tree new_lhs = make_ssa_name (TREE_TYPE (lhs), NULL);
+ enum tree_code rhs_code
+ = gimple_assign_rhs_code (cast_stmt);
+ gimple g
+ = gimple_build_assign_with_ops (rhs_code, new_lhs,
+ new_op, NULL_TREE);
+ gimple_stmt_iterator gsi = gsi_for_stmt (cast_stmt);
+ gimple_set_uid (g, gimple_uid (cast_stmt));
+ gimple_set_visited (g, true);
+ gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+ FOR_EACH_IMM_USE_STMT (use_stmt, iter, lhs)
+ if (is_gimple_debug (use_stmt))
+ continue;
+ else if (gimple_code (use_stmt) == GIMPLE_COND
+ || gimple_code (use_stmt) == GIMPLE_PHI)
+ FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
+ SET_USE (use_p, new_lhs);
+ else
+ gcc_unreachable ();
+ }
+ }
+ }
+ if (bb == first_bb)
+ break;
+ }
+ for (bb = last_bb, idx = 0; ; bb = single_pred (bb), idx++)
+ {
+ if (bbinfo[idx].first_idx < bbinfo[idx].last_idx
+ && bbinfo[idx].op == NULL_TREE
+ && ops[bbinfo[idx].first_idx]->op != NULL_TREE)
+ {
+ stmt = last_stmt (bb);
+ if (integer_zerop (ops[bbinfo[idx].first_idx]->op))
+ gimple_cond_make_false (stmt);
+ else if (integer_onep (ops[bbinfo[idx].first_idx]->op))
+ gimple_cond_make_true (stmt);
+ else
+ {
+ gimple_cond_set_code (stmt, NE_EXPR);
+ gimple_cond_set_lhs (stmt, ops[bbinfo[idx].first_idx]->op);
+ gimple_cond_set_rhs (stmt, boolean_false_node);
+ }
+ update_stmt (stmt);
+ }
+ if (bb == first_bb)
+ break;
+ }
+ }
+ bbinfo.release ();
ops.release ();
}
@@ -2857,175 +3079,36 @@ swap_ops_for_binary_stmt (vec<operand_entry_t> ops,
oe2->op = oe1->op;
oe2->rank = oe1->rank;
oe1->op = temp.op;
- oe1->rank= temp.rank;
- }
-}
-
-/* Determine if stmt A is not dominated by stmt B. If A and B are in
- same basic block, then A's UID has to be less than B. If they are
- in different BB's, then A's BB must not be dominated by B's BB. */
-
-static inline bool
-not_dominated_by (gimple a, gimple b)
-{
- basic_block bb_a, bb_b;
- bb_a = gimple_bb (a);
- bb_b = gimple_bb (b);
- return ((bb_a == bb_b && gimple_uid (a) < gimple_uid (b))
- || (bb_a != bb_b
- && !dominated_by_p (CDI_DOMINATORS, bb_a, bb_b)));
-
-}
-
-/* Among STMT1 and STMT2, return the statement that appears later. Both
- statements are in same BB and have the same UID. */
-
-static gimple
-appears_later_in_bb (gimple stmt1, gimple stmt2)
-{
- unsigned uid = gimple_uid (stmt1);
- gimple_stmt_iterator gsi = gsi_for_stmt (stmt1);
- for (gsi_next (&gsi); !gsi_end_p (gsi); gsi_next (&gsi))
- {
- gimple stmt = gsi_stmt (gsi);
-
- /* If STMT has a different UID than STMT1 and we haven't seen
- STMT2 during traversal, we know STMT1 appears later. */
- if (gimple_uid (stmt) != uid)
- return stmt1;
- else if (stmt == stmt2)
- return stmt2;
+ oe1->rank = temp.rank;
}
- return stmt1;
-}
-
-/* Find the statement after which STMT must be moved so that the
- dependency from DEP_STMT to STMT is maintained. */
-
-static gimple
-find_insert_point (gimple stmt, gimple dep_stmt)
-{
- gimple insert_stmt = stmt;
- if (dep_stmt == NULL)
- return stmt;
- if (gimple_uid (insert_stmt) == gimple_uid (dep_stmt)
- && gimple_bb (insert_stmt) == gimple_bb (dep_stmt)
- && insert_stmt != dep_stmt)
- insert_stmt = appears_later_in_bb (insert_stmt, dep_stmt);
- else if (not_dominated_by (insert_stmt, dep_stmt))
- insert_stmt = dep_stmt;
- return insert_stmt;
}
-/* Insert STMT after INSERT_POINT. */
-
-static void
-insert_stmt_after (gimple stmt, gimple insert_point)
-{
- imm_use_iterator iter;
- tree lhs;
- gimple use_stmt;
- gimple_stmt_iterator gsistmt = gsi_for_stmt (stmt), gsi_insert;
- basic_block insert_bb = gimple_bb (insert_point);
- bool insert_bb_different = (insert_bb != gimple_bb (stmt));
- lhs = gimple_assign_lhs (stmt);
- /* If there are any debug uses of LHS, reset them. */
- FOR_EACH_IMM_USE_STMT (use_stmt, iter, lhs)
- {
- if (is_gimple_debug (use_stmt)
- && not_dominated_by (use_stmt, insert_point))
- {
- gimple_debug_bind_reset_value (use_stmt);
- update_stmt (use_stmt);
- }
- }
- /* If INSERT_STMT is a phi node, then do not insert just after that statement.
- Instead, find the first non-label gimple statement in BB and insert before
- that. */
- if (gimple_code (insert_point) == GIMPLE_PHI)
- {
- gsi_insert = gsi_after_labels (insert_bb);
- gsi_move_before (&gsistmt, &gsi_insert);
- }
- /* Statements marked for throw can not be in the middle of a basic block. So
- we can not insert a statement (not marked for throw) immediately after. */
- else if (stmt_ends_bb_p (insert_point))
- {
- edge succ_edge = find_fallthru_edge (insert_bb->succs);
- insert_bb = succ_edge->dest;
- insert_bb_different = (insert_bb != gimple_bb (stmt));
- /* Insert STMT at the beginning of the successor basic block. */
- gsi_insert = gsi_after_labels (insert_bb);
- gsi_move_before (&gsistmt, &gsi_insert);
- }
- else
- {
- gsi_insert = gsi_for_stmt (insert_point);
- gsi_move_after (&gsistmt, &gsi_insert);
- }
- /* Set the UID of STMT to that of INSERT_POINT so that subsequent comparisons
- of UIDs to determine dominance within a basic block works. */
- gimple_set_uid (stmt, gimple_uid (insert_point));
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "Moved stmt ");
- print_gimple_stmt (dump_file, stmt, 0, 0);
- fprintf (dump_file, " %s to satisfy dependences\n",
- insert_bb_different ? "to a different BB" : "within same BB");
- }
-
-}
-
-/* If OP is a SSA variable and is not the default definition, return the
- gimple statement that defines OP. Else return NULL. */
+/* If definition of RHS1 or RHS2 dominates STMT, return the later of those
+ two definitions, otherwise return STMT. */
static inline gimple
-get_def_stmt (tree op)
-{
- if (TREE_CODE (op) == SSA_NAME
- && !SSA_NAME_IS_DEFAULT_DEF (op))
- return SSA_NAME_DEF_STMT (op);
- else
- return NULL;
-}
-
-/* Ensure that operands in the OPS vector are available for STMT and all
- gimple statements on which STMT depends. */
-
-static void
-ensure_ops_are_available (gimple stmt, vec<operand_entry_t> ops, int opindex)
+find_insert_point (gimple stmt, tree rhs1, tree rhs2)
{
- unsigned int len = ops.length ();
- gimple insert_stmt = stmt;
- gimple dep_stmts[2];
- dep_stmts[0] = get_def_stmt (ops[opindex]->op);
- if (len - opindex == 2)
- {
- dep_stmts[1] = get_def_stmt (ops[opindex + 1]->op);
- }
- else
- {
- gimple stmt1 = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt));
- ensure_ops_are_available (stmt1, ops, opindex + 1);
- dep_stmts[1] = stmt1;
- }
- for (int i = 0; i < 2; i++)
- insert_stmt = find_insert_point (insert_stmt, dep_stmts[i]);
-
- if (insert_stmt != stmt)
- insert_stmt_after (stmt, insert_stmt);
+ if (TREE_CODE (rhs1) == SSA_NAME
+ && reassoc_stmt_dominates_stmt_p (stmt, SSA_NAME_DEF_STMT (rhs1)))
+ stmt = SSA_NAME_DEF_STMT (rhs1);
+ if (TREE_CODE (rhs2) == SSA_NAME
+ && reassoc_stmt_dominates_stmt_p (stmt, SSA_NAME_DEF_STMT (rhs2)))
+ stmt = SSA_NAME_DEF_STMT (rhs2);
+ return stmt;
}
/* Recursively rewrite our linearized statements so that the operators
match those in OPS[OPINDEX], putting the computation in rank
- order. */
+ order. Return new lhs. */
-static void
+static tree
rewrite_expr_tree (gimple stmt, unsigned int opindex,
- vec<operand_entry_t> ops, bool moved)
+ vec<operand_entry_t> ops, bool changed)
{
tree rhs1 = gimple_assign_rhs1 (stmt);
tree rhs2 = gimple_assign_rhs2 (stmt);
+ tree lhs = gimple_assign_lhs (stmt);
operand_entry_t oe;
/* The final recursion case for this function is that you have
@@ -3042,15 +3125,38 @@ rewrite_expr_tree (gimple stmt, unsigned int opindex,
if (rhs1 != oe1->op || rhs2 != oe2->op)
{
+ gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
+ unsigned int uid = gimple_uid (stmt);
+
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "Transforming ");
print_gimple_stmt (dump_file, stmt, 0, 0);
}
- gimple_assign_set_rhs1 (stmt, oe1->op);
- gimple_assign_set_rhs2 (stmt, oe2->op);
- update_stmt (stmt);
+ if (changed)
+ {
+ gimple insert_point = find_insert_point (stmt, oe1->op, oe2->op);
+ lhs = make_ssa_name (TREE_TYPE (lhs), NULL);
+ stmt
+ = gimple_build_assign_with_ops (gimple_assign_rhs_code (stmt),
+ lhs, oe1->op, oe2->op);
+ gimple_set_uid (stmt, uid);
+ gimple_set_visited (stmt, true);
+ if (insert_point == gsi_stmt (gsi))
+ gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
+ else
+ insert_stmt_after (stmt, insert_point);
+ }
+ else
+ {
+ gcc_checking_assert (find_insert_point (stmt, oe1->op, oe2->op)
+ == stmt);
+ gimple_assign_set_rhs1 (stmt, oe1->op);
+ gimple_assign_set_rhs2 (stmt, oe2->op);
+ update_stmt (stmt);
+ }
+
if (rhs1 != oe1->op && rhs1 != oe2->op)
remove_visited_stmt_chain (rhs1);
@@ -3060,7 +3166,7 @@ rewrite_expr_tree (gimple stmt, unsigned int opindex,
print_gimple_stmt (dump_file, stmt, 0, 0);
}
}
- return;
+ return lhs;
}
/* If we hit here, we should have 3 or more ops left. */
@@ -3069,22 +3175,51 @@ rewrite_expr_tree (gimple stmt, unsigned int opindex,
/* Rewrite the next operator. */
oe = ops[opindex];
- if (oe->op != rhs2)
- {
- if (!moved)
- {
- ensure_ops_are_available (stmt, ops, opindex);
- moved = true;
- }
+ /* Recurse on the LHS of the binary operator, which is guaranteed to
+ be the non-leaf side. */
+ tree new_rhs1
+ = rewrite_expr_tree (SSA_NAME_DEF_STMT (rhs1), opindex + 1, ops,
+ changed || oe->op != rhs2);
+ if (oe->op != rhs2 || new_rhs1 != rhs1)
+ {
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "Transforming ");
print_gimple_stmt (dump_file, stmt, 0, 0);
}
- gimple_assign_set_rhs2 (stmt, oe->op);
- update_stmt (stmt);
+ /* If changed is false, this is either opindex == 0
+ or all outer rhs2's were equal to corresponding oe->op,
+ and powi_result is NULL.
+ That means lhs is equivalent before and after reassociation.
+ Otherwise ensure the old lhs SSA_NAME is not reused and
+ create a new stmt as well, so that any debug stmts will be
+ properly adjusted. */
+ if (changed)
+ {
+ gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
+ unsigned int uid = gimple_uid (stmt);
+ gimple insert_point = find_insert_point (stmt, new_rhs1, oe->op);
+
+ lhs = make_ssa_name (TREE_TYPE (lhs), NULL);
+ stmt = gimple_build_assign_with_ops (gimple_assign_rhs_code (stmt),
+ lhs, new_rhs1, oe->op);
+ gimple_set_uid (stmt, uid);
+ gimple_set_visited (stmt, true);
+ if (insert_point == gsi_stmt (gsi))
+ gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
+ else
+ insert_stmt_after (stmt, insert_point);
+ }
+ else
+ {
+ gcc_checking_assert (find_insert_point (stmt, new_rhs1, oe->op)
+ == stmt);
+ gimple_assign_set_rhs1 (stmt, new_rhs1);
+ gimple_assign_set_rhs2 (stmt, oe->op);
+ update_stmt (stmt);
+ }
if (dump_file && (dump_flags & TDF_DETAILS))
{
@@ -3092,9 +3227,7 @@ rewrite_expr_tree (gimple stmt, unsigned int opindex,
print_gimple_stmt (dump_file, stmt, 0, 0);
}
}
- /* Recurse on the LHS of the binary operator, which is guaranteed to
- be the non-leaf side. */
- rewrite_expr_tree (SSA_NAME_DEF_STMT (rhs1), opindex + 1, ops, moved);
+ return lhs;
}
/* Find out how many cycles we need to compute statements chain.
@@ -3176,7 +3309,7 @@ get_reassociation_width (int ops_num, enum tree_code opc,
static void
rewrite_expr_tree_parallel (gimple stmt, int width,
- vec<operand_entry_t> ops)
+ vec<operand_entry_t> ops)
{
enum tree_code opcode = gimple_assign_rhs_code (stmt);
int op_num = ops.length ();
@@ -3272,24 +3405,28 @@ rewrite_expr_tree_parallel (gimple stmt, int width,
static void
linearize_expr (gimple stmt)
{
- gimple_stmt_iterator gsinow, gsirhs;
+ gimple_stmt_iterator gsi;
gimple binlhs = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt));
gimple binrhs = SSA_NAME_DEF_STMT (gimple_assign_rhs2 (stmt));
+ gimple oldbinrhs = binrhs;
enum tree_code rhscode = gimple_assign_rhs_code (stmt);
gimple newbinrhs = NULL;
struct loop *loop = loop_containing_stmt (stmt);
+ tree lhs = gimple_assign_lhs (stmt);
gcc_assert (is_reassociable_op (binlhs, rhscode, loop)
&& is_reassociable_op (binrhs, rhscode, loop));
- gsinow = gsi_for_stmt (stmt);
- gsirhs = gsi_for_stmt (binrhs);
- gsi_move_before (&gsirhs, &gsinow);
- gimple_set_uid (binrhs, gimple_uid (stmt));
+ gsi = gsi_for_stmt (stmt);
gimple_assign_set_rhs2 (stmt, gimple_assign_rhs1 (binrhs));
- gimple_assign_set_rhs1 (binrhs, gimple_assign_lhs (binlhs));
+ binrhs = gimple_build_assign_with_ops (gimple_assign_rhs_code (binrhs),
+ make_ssa_name (TREE_TYPE (lhs), NULL),
+ gimple_assign_lhs (binlhs),
+ gimple_assign_rhs2 (binrhs));
gimple_assign_set_rhs1 (stmt, gimple_assign_lhs (binrhs));
+ gsi_insert_before (&gsi, binrhs, GSI_SAME_STMT);
+ gimple_set_uid (binrhs, gimple_uid (stmt));
if (TREE_CODE (gimple_assign_rhs2 (stmt)) == SSA_NAME)
newbinrhs = SSA_NAME_DEF_STMT (gimple_assign_rhs2 (stmt));
@@ -3301,10 +3438,12 @@ linearize_expr (gimple stmt)
}
reassociate_stats.linearized++;
- update_stmt (binrhs);
- update_stmt (binlhs);
update_stmt (stmt);
+ gsi = gsi_for_stmt (oldbinrhs);
+ gsi_remove (&gsi, true);
+ release_defs (oldbinrhs);
+
gimple_set_visited (stmt, true);
gimple_set_visited (binlhs, true);
gimple_set_visited (binrhs, true);
@@ -3341,10 +3480,12 @@ get_single_immediate_use (tree lhs)
transform b_3 + b_4 into a_5 = -b_3 + -b_4. */
static tree
-negate_value (tree tonegate, gimple_stmt_iterator *gsi)
+negate_value (tree tonegate, gimple_stmt_iterator *gsip)
{
- gimple negatedefstmt= NULL;
+ gimple negatedefstmt = NULL;
tree resultofnegate;
+ gimple_stmt_iterator gsi;
+ unsigned int uid;
/* If we are trying to negate a name, defined by an add, negate the
add operands instead. */
@@ -3356,25 +3497,38 @@ negate_value (tree tonegate, gimple_stmt_iterator *gsi)
&& has_single_use (gimple_assign_lhs (negatedefstmt))
&& gimple_assign_rhs_code (negatedefstmt) == PLUS_EXPR)
{
- gimple_stmt_iterator gsi;
tree rhs1 = gimple_assign_rhs1 (negatedefstmt);
tree rhs2 = gimple_assign_rhs2 (negatedefstmt);
+ tree lhs = gimple_assign_lhs (negatedefstmt);
+ gimple g;
gsi = gsi_for_stmt (negatedefstmt);
rhs1 = negate_value (rhs1, &gsi);
- gimple_assign_set_rhs1 (negatedefstmt, rhs1);
gsi = gsi_for_stmt (negatedefstmt);
rhs2 = negate_value (rhs2, &gsi);
- gimple_assign_set_rhs2 (negatedefstmt, rhs2);
- update_stmt (negatedefstmt);
- return gimple_assign_lhs (negatedefstmt);
+ gsi = gsi_for_stmt (negatedefstmt);
+ lhs = make_ssa_name (TREE_TYPE (lhs), NULL);
+ gimple_set_visited (negatedefstmt, true);
+ g = gimple_build_assign_with_ops (PLUS_EXPR, lhs, rhs1, rhs2);
+ gimple_set_uid (g, gimple_uid (negatedefstmt));
+ gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+ return lhs;
}
tonegate = fold_build1 (NEGATE_EXPR, TREE_TYPE (tonegate), tonegate);
- resultofnegate = force_gimple_operand_gsi (gsi, tonegate, true,
+ resultofnegate = force_gimple_operand_gsi (gsip, tonegate, true,
NULL_TREE, true, GSI_SAME_STMT);
+ gsi = *gsip;
+ uid = gimple_uid (gsi_stmt (gsi));
+ for (gsi_prev (&gsi); !gsi_end_p (gsi); gsi_prev (&gsi))
+ {
+ gimple stmt = gsi_stmt (gsi);
+ if (gimple_uid (stmt) != 0)
+ break;
+ gimple_set_uid (stmt, uid);
+ }
return resultofnegate;
}
@@ -3580,9 +3734,9 @@ linearize_expr_tree (vec<operand_entry_t> *ops, gimple stmt,
print_gimple_stmt (dump_file, stmt, 0, 0);
}
- swap_tree_operands (stmt,
- gimple_assign_rhs1_ptr (stmt),
- gimple_assign_rhs2_ptr (stmt));
+ swap_ssa_operands (stmt,
+ gimple_assign_rhs1_ptr (stmt),
+ gimple_assign_rhs2_ptr (stmt));
update_stmt (stmt);
if (dump_file && (dump_flags & TDF_DETAILS))
@@ -3649,9 +3803,9 @@ repropagate_negates (void)
to force the negated operand to the RHS of the PLUS_EXPR. */
if (gimple_assign_rhs1 (user) == negate)
{
- swap_tree_operands (user,
- gimple_assign_rhs1_ptr (user),
- gimple_assign_rhs2_ptr (user));
+ swap_ssa_operands (user,
+ gimple_assign_rhs1_ptr (user),
+ gimple_assign_rhs2_ptr (user));
}
/* Now transform the PLUS_EXPR into a MINUS_EXPR and replace
@@ -3680,16 +3834,18 @@ repropagate_negates (void)
plus_negates vector. */
gimple feed = SSA_NAME_DEF_STMT (negate);
tree a = gimple_assign_rhs1 (feed);
- tree rhs2 = gimple_assign_rhs2 (user);
- gimple_stmt_iterator gsi = gsi_for_stmt (feed), gsi2;
- gimple_replace_lhs (feed, negate);
- gimple_assign_set_rhs_with_ops (&gsi, PLUS_EXPR, a, rhs2);
- update_stmt (gsi_stmt (gsi));
- gsi2 = gsi_for_stmt (user);
- gimple_assign_set_rhs_with_ops (&gsi2, NEGATE_EXPR, negate, NULL);
- update_stmt (gsi_stmt (gsi2));
- gsi_move_before (&gsi, &gsi2);
- plus_negates.safe_push (gimple_assign_lhs (gsi_stmt (gsi2)));
+ tree b = gimple_assign_rhs2 (user);
+ gimple_stmt_iterator gsi = gsi_for_stmt (feed);
+ gimple_stmt_iterator gsi2 = gsi_for_stmt (user);
+ tree x = make_ssa_name (TREE_TYPE (gimple_assign_lhs (feed)), NULL);
+ gimple g = gimple_build_assign_with_ops (PLUS_EXPR, x, a, b);
+ gsi_insert_before (&gsi2, g, GSI_SAME_STMT);
+ gimple_assign_set_rhs_with_ops (&gsi2, NEGATE_EXPR, x, NULL);
+ user = gsi_stmt (gsi2);
+ update_stmt (user);
+ gsi_remove (&gsi, true);
+ release_defs (feed);
+ plus_negates.safe_push (gimple_assign_lhs (user));
}
else
{
@@ -3736,18 +3892,21 @@ can_reassociate_p (tree op)
we want to break up k = t - q, but we won't until we've transformed q
= b - r, which won't be broken up until we transform b = c - d.
- En passant, clear the GIMPLE visited flag on every statement. */
+ En passant, clear the GIMPLE visited flag on every statement
+ and set UIDs within each basic block. */
static void
break_up_subtract_bb (basic_block bb)
{
gimple_stmt_iterator gsi;
basic_block son;
+ unsigned int uid = 1;
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
{
gimple stmt = gsi_stmt (gsi);
gimple_set_visited (stmt, false);
+ gimple_set_uid (stmt, uid++);
if (!is_gimple_assign (stmt)
|| !can_reassociate_p (gimple_assign_lhs (stmt)))
@@ -4283,6 +4442,7 @@ reassociate_bb (basic_block bb)
enum machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
int ops_num = ops.length ();
int width = get_reassociation_width (ops_num, rhs_code, mode);
+ tree new_lhs = lhs;
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file,
@@ -4300,7 +4460,8 @@ reassociate_bb (basic_block bb)
if (len >= 3)
swap_ops_for_binary_stmt (ops, len - 3, stmt);
- rewrite_expr_tree (stmt, 0, ops, false);
+ new_lhs = rewrite_expr_tree (stmt, 0, ops,
+ powi_result != NULL);
}
/* If we combined some repeated factors into a
@@ -4308,12 +4469,14 @@ reassociate_bb (basic_block bb)
reassociated operands. */
if (powi_result)
{
- gimple mul_stmt;
- tree type = TREE_TYPE (gimple_get_lhs (stmt));
+ gimple mul_stmt, lhs_stmt = SSA_NAME_DEF_STMT (lhs);
+ tree type = TREE_TYPE (lhs);
tree target_ssa = make_temp_ssa_name (type, NULL,
"reassocpow");
- gimple_set_lhs (stmt, target_ssa);
- update_stmt (stmt);
+ gimple_set_lhs (lhs_stmt, target_ssa);
+ update_stmt (lhs_stmt);
+ if (lhs != new_lhs)
+ target_ssa = new_lhs;
mul_stmt = gimple_build_assign_with_ops (MULT_EXPR, lhs,
powi_result,
target_ssa);
@@ -4362,7 +4525,6 @@ static void
do_reassoc (void)
{
break_up_subtract_bb (ENTRY_BLOCK_PTR);
- renumber_gimple_stmt_uids ();
reassociate_bb (EXIT_BLOCK_PTR);
}
@@ -4480,12 +4642,12 @@ const pass_data pass_data_reassoc =
class pass_reassoc : public gimple_opt_pass
{
public:
- pass_reassoc(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_reassoc, ctxt)
+ pass_reassoc (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_reassoc, ctxt)
{}
/* opt_pass methods: */
- opt_pass * clone () { return new pass_reassoc (ctxt_); }
+ opt_pass * clone () { return new pass_reassoc (m_ctxt); }
bool gate () { return gate_tree_ssa_reassoc (); }
unsigned int execute () { return execute_reassoc (); }
diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c
index bd2feb46ef2..ed4e1db718c 100644
--- a/gcc/tree-ssa-sccvn.c
+++ b/gcc/tree-ssa-sccvn.c
@@ -26,18 +26,21 @@ along with GCC; see the file COPYING3. If not see
#include "basic-block.h"
#include "gimple-pretty-print.h"
#include "tree-inline.h"
-#include "tree-ssa.h"
#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
+#include "tree-dfa.h"
+#include "tree-ssa.h"
#include "dumpfile.h"
#include "hash-table.h"
#include "alloc-pool.h"
#include "flags.h"
-#include "bitmap.h"
#include "cfgloop.h"
#include "params.h"
#include "tree-ssa-propagate.h"
#include "tree-ssa-sccvn.h"
-#include "gimple-fold.h"
/* This algorithm is based on the SCC algorithm presented by Keith
Cooper and L. Taylor Simpson in "SCC-Based Value numbering"
diff --git a/gcc/tree-ssa-sink.c b/gcc/tree-ssa-sink.c
index cc9cff886f7..a8b149287c9 100644
--- a/gcc/tree-ssa-sink.c
+++ b/gcc/tree-ssa-sink.c
@@ -26,14 +26,16 @@ along with GCC; see the file COPYING3. If not see
#include "basic-block.h"
#include "gimple-pretty-print.h"
#include "tree-inline.h"
-#include "tree-ssa.h"
#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-cfg.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
#include "hashtab.h"
#include "tree-iterator.h"
#include "alloc-pool.h"
#include "tree-pass.h"
#include "flags.h"
-#include "bitmap.h"
#include "cfgloop.h"
#include "params.h"
@@ -607,8 +609,8 @@ const pass_data pass_data_sink_code =
class pass_sink_code : public gimple_opt_pass
{
public:
- pass_sink_code(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_sink_code, ctxt)
+ pass_sink_code (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_sink_code, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c
index c30ab33ef28..ea73179eea8 100644
--- a/gcc/tree-ssa-strlen.c
+++ b/gcc/tree-ssa-strlen.c
@@ -21,8 +21,15 @@ along with GCC; see the file COPYING3. If not see
#include "config.h"
#include "system.h"
#include "coretypes.h"
+#include "tree.h"
#include "hash-table.h"
-#include "tree-ssa.h"
+#include "bitmap.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
+#include "tree-dfa.h"
#include "tree-pass.h"
#include "domwalk.h"
#include "alloc-pool.h"
@@ -2098,8 +2105,8 @@ const pass_data pass_data_strlen =
class pass_strlen : public gimple_opt_pass
{
public:
- pass_strlen(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_strlen, ctxt)
+ pass_strlen (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_strlen, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c
index 112fba636fb..6f3a4cee29f 100644
--- a/gcc/tree-ssa-structalias.c
+++ b/gcc/tree-ssa-structalias.c
@@ -25,21 +25,24 @@
#include "ggc.h"
#include "obstack.h"
#include "bitmap.h"
+#include "sbitmap.h"
#include "flags.h"
#include "basic-block.h"
#include "tree.h"
-#include "tree-ssa.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "cgraph.h"
+#include "tree-ssanames.h"
+#include "tree-into-ssa.h"
+#include "tree-dfa.h"
#include "tree-inline.h"
#include "diagnostic-core.h"
-#include "gimple.h"
#include "hash-table.h"
#include "function.h"
-#include "cgraph.h"
#include "tree-pass.h"
#include "alloc-pool.h"
#include "splay-tree.h"
#include "params.h"
-#include "cgraph.h"
#include "alias.h"
#include "pointer-set.h"
@@ -1747,7 +1750,7 @@ do_complex_constraint (constraint_graph_t graph, constraint_t c, bitmap delta)
{
if (c->rhs.type == ADDRESSOF)
{
- gcc_unreachable();
+ gcc_unreachable ();
}
else
{
@@ -2096,7 +2099,7 @@ label_visit (constraint_graph_t graph, struct scc_info *si, unsigned int n)
}
}
else
- bitmap_ior_into(graph->points_to[n], graph->points_to[w]);
+ bitmap_ior_into (graph->points_to[n], graph->points_to[w]);
}
}
@@ -2874,10 +2877,10 @@ get_constraint_for_ssa_var (tree t, vec<ce_s> *results, bool address_p)
&& (TREE_STATIC (t) || DECL_EXTERNAL (t)))
{
struct varpool_node *node = varpool_get_node (t);
- if (node && node->symbol.alias && node->symbol.analyzed)
+ if (node && node->alias && node->analyzed)
{
node = varpool_variable_node (node, NULL);
- t = node->symbol.decl;
+ t = node->decl;
}
}
@@ -4301,8 +4304,8 @@ find_func_aliases_for_builtin_call (gimple t)
rhsc.safe_push (nul);
get_constraint_for (gimple_call_lhs (t), &lhsc);
process_all_all_constraints (lhsc, rhsc);
- lhsc.release();
- rhsc.release();
+ lhsc.release ();
+ rhsc.release ();
}
return true;
/* Trampolines are special - they set up passing the static
@@ -5751,7 +5754,7 @@ create_variable_info_for (tree decl, const char *name)
/* If this is a global variable with an initializer and we are in
IPA mode generate constraints for it. */
if (DECL_INITIAL (decl)
- && vnode->symbol.definition)
+ && vnode->definition)
{
vec<ce_s> rhsc = vNULL;
struct constraint_expr lhs, *rhsp;
@@ -6980,8 +6983,8 @@ const pass_data pass_data_build_alias =
class pass_build_alias : public gimple_opt_pass
{
public:
- pass_build_alias(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_build_alias, ctxt)
+ pass_build_alias (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_build_alias, ctxt)
{}
/* opt_pass methods: */
@@ -7020,8 +7023,8 @@ const pass_data pass_data_build_ealias =
class pass_build_ealias : public gimple_opt_pass
{
public:
- pass_build_ealias(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_build_ealias, ctxt)
+ pass_build_ealias (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_build_ealias, ctxt)
{}
/* opt_pass methods: */
@@ -7057,9 +7060,9 @@ struct pt_solution ipa_escaped_pt
static bool
associate_varinfo_to_alias (struct cgraph_node *node, void *data)
{
- if ((node->symbol.alias || node->thunk.thunk_p)
- && node->symbol.analyzed)
- insert_vi_for_tree (node->symbol.decl, (varinfo_t)data);
+ if ((node->alias || node->thunk.thunk_p)
+ && node->analyzed)
+ insert_vi_for_tree (node->decl, (varinfo_t)data);
return false;
}
@@ -7094,18 +7097,18 @@ ipa_pta_execute (void)
gcc_assert (!node->clone_of);
- vi = create_function_info_for (node->symbol.decl,
- alias_get_name (node->symbol.decl));
+ vi = create_function_info_for (node->decl,
+ alias_get_name (node->decl));
cgraph_for_node_and_aliases (node, associate_varinfo_to_alias, vi, true);
}
/* Create constraints for global variables and their initializers. */
FOR_EACH_VARIABLE (var)
{
- if (var->symbol.alias && var->symbol.analyzed)
+ if (var->alias && var->analyzed)
continue;
- get_vi_for_tree (var->symbol.decl);
+ get_vi_for_tree (var->decl);
}
if (dump_file)
@@ -7130,32 +7133,32 @@ ipa_pta_execute (void)
{
fprintf (dump_file,
"Generating constraints for %s", cgraph_node_name (node));
- if (DECL_ASSEMBLER_NAME_SET_P (node->symbol.decl))
+ if (DECL_ASSEMBLER_NAME_SET_P (node->decl))
fprintf (dump_file, " (%s)",
IDENTIFIER_POINTER
- (DECL_ASSEMBLER_NAME (node->symbol.decl)));
+ (DECL_ASSEMBLER_NAME (node->decl)));
fprintf (dump_file, "\n");
}
- func = DECL_STRUCT_FUNCTION (node->symbol.decl);
+ func = DECL_STRUCT_FUNCTION (node->decl);
push_cfun (func);
/* For externally visible or attribute used annotated functions use
local constraints for their arguments.
For local functions we see all callers and thus do not need initial
constraints for parameters. */
- if (node->symbol.used_from_other_partition
- || node->symbol.externally_visible
- || node->symbol.force_output)
+ if (node->used_from_other_partition
+ || node->externally_visible
+ || node->force_output)
{
intra_create_variable_infos ();
/* We also need to make function return values escape. Nothing
escapes by returning from main though. */
- if (!MAIN_NAME_P (DECL_NAME (node->symbol.decl)))
+ if (!MAIN_NAME_P (DECL_NAME (node->decl)))
{
varinfo_t fi, rvi;
- fi = lookup_vi_for_tree (node->symbol.decl);
+ fi = lookup_vi_for_tree (node->decl);
rvi = first_vi_for_offset (fi, fi_result);
if (rvi && rvi->offset == fi_result)
{
@@ -7235,7 +7238,7 @@ ipa_pta_execute (void)
if (!cgraph_function_with_gimple_body_p (node) || node->clone_of)
continue;
- fn = DECL_STRUCT_FUNCTION (node->symbol.decl);
+ fn = DECL_STRUCT_FUNCTION (node->decl);
/* Compute the points-to sets for pointer SSA_NAMEs. */
FOR_EACH_VEC_ELT (*fn->gimple_df->ssa_names, i, ptr)
@@ -7246,7 +7249,7 @@ ipa_pta_execute (void)
}
/* Compute the call-use and call-clobber sets for all direct calls. */
- fi = lookup_vi_for_tree (node->symbol.decl);
+ fi = lookup_vi_for_tree (node->decl);
gcc_assert (fi->is_fn_info);
clobbers
= find_what_var_points_to (first_vi_for_offset (fi, fi_clobbers));
@@ -7414,8 +7417,8 @@ const pass_data pass_data_ipa_pta =
class pass_ipa_pta : public simple_ipa_opt_pass
{
public:
- pass_ipa_pta(gcc::context *ctxt)
- : simple_ipa_opt_pass(pass_data_ipa_pta, ctxt)
+ pass_ipa_pta (gcc::context *ctxt)
+ : simple_ipa_opt_pass (pass_data_ipa_pta, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/tree-ssa-tail-merge.c b/gcc/tree-ssa-tail-merge.c
index 4998b7e616c..db95ce1059c 100644
--- a/gcc/tree-ssa-tail-merge.c
+++ b/gcc/tree-ssa-tail-merge.c
@@ -194,8 +194,12 @@ along with GCC; see the file COPYING3. If not see
#include "basic-block.h"
#include "flags.h"
#include "function.h"
-#include "tree-ssa.h"
-#include "bitmap.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-cfg.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-into-ssa.h"
#include "tree-ssa-alias.h"
#include "params.h"
#include "hash-table.h"
@@ -300,7 +304,8 @@ stmt_local_def (gimple stmt)
tree val;
def_operand_p def_p;
- if (gimple_has_side_effects (stmt))
+ if (gimple_has_side_effects (stmt)
+ || gimple_vdef (stmt) != NULL_TREE)
return false;
def_p = SINGLE_SSA_DEF_OPERAND (stmt, SSA_OP_DEF);
@@ -1462,6 +1467,8 @@ static void
replace_block_by (basic_block bb1, basic_block bb2)
{
edge pred_edge;
+ edge e1, e2;
+ edge_iterator ei;
unsigned int i;
gimple bb2_phi;
@@ -1494,6 +1501,24 @@ replace_block_by (basic_block bb1, basic_block bb2)
bb2->count += bb1->count;
+ /* Merge the outgoing edge counts from bb1 onto bb2. */
+ gcov_type out_sum = 0;
+ FOR_EACH_EDGE (e1, ei, bb1->succs)
+ {
+ e2 = find_edge (bb2, e1->dest);
+ gcc_assert (e2);
+ e2->count += e1->count;
+ out_sum += e2->count;
+ }
+ /* Recompute the edge probabilities from the new merged edge count.
+ Use the sum of the new merged edge counts computed above instead
+ of bb2's merged count, in case there are profile count insanities
+ making the bb count inconsistent with the edge weights. */
+ FOR_EACH_EDGE (e2, ei, bb2->succs)
+ {
+ e2->probability = GCOV_COMPUTE_SCALE (e2->count, out_sum);
+ }
+
/* Do updates that use bb1, before deleting bb1. */
release_last_vdef (bb1);
same_succ_flush_bb (bb1);
diff --git a/gcc/tree-ssa-ter.c b/gcc/tree-ssa-ter.c
index ee18cd8f164..6090c5ff5f5 100644
--- a/gcc/tree-ssa-ter.c
+++ b/gcc/tree-ssa-ter.c
@@ -26,9 +26,15 @@ along with GCC; see the file COPYING3. If not see
#include "tree.h"
#include "gimple-pretty-print.h"
#include "bitmap.h"
-#include "tree-ssa.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
#include "dumpfile.h"
#include "tree-ssa-live.h"
+#include "tree-ssa-ter.h"
+#include "tree-outof-ssa.h"
#include "flags.h"
@@ -46,7 +52,7 @@ along with GCC; see the file COPYING3. If not see
information is tracked.
Variables which only have one use, and whose defining stmt is considered
- a replaceable expression (see is_replaceable_p) are tracked to see whether
+ a replaceable expression (see ssa_is_replaceable_p) are tracked to see whether
they can be replaced at their use location.
n_12 = C * 10
@@ -359,111 +365,6 @@ add_dependence (temp_expr_table_p tab, int version, tree var)
}
-/* Return TRUE if expression STMT is suitable for replacement.
- TER is true if is_replaceable_p is called from within TER, false
- when used from within stmt_is_replaceable_p, i.e. EXPAND_INITIALIZER
- expansion. The differences are that with !TER some tests are skipped
- to make it more aggressive (doesn't require the same bb, or for -O0
- same locus and same BLOCK), on the other side never considers memory
- loads as replaceable, because those don't ever lead into constant
- expressions. */
-
-static inline bool
-is_replaceable_p (gimple stmt, bool ter)
-{
- use_operand_p use_p;
- tree def;
- gimple use_stmt;
- location_t locus1, locus2;
- tree block1, block2;
-
- /* Only consider modify stmts. */
- if (!is_gimple_assign (stmt))
- return false;
-
- /* If the statement may throw an exception, it cannot be replaced. */
- if (stmt_could_throw_p (stmt))
- return false;
-
- /* Punt if there is more than 1 def. */
- def = SINGLE_SSA_TREE_OPERAND (stmt, SSA_OP_DEF);
- if (!def)
- return false;
-
- /* Only consider definitions which have a single use. */
- if (!single_imm_use (def, &use_p, &use_stmt))
- return false;
-
- /* If the use isn't in this block, it wont be replaced either. */
- if (ter && gimple_bb (use_stmt) != gimple_bb (stmt))
- return false;
-
- locus1 = gimple_location (stmt);
- block1 = LOCATION_BLOCK (locus1);
- locus1 = LOCATION_LOCUS (locus1);
-
- if (gimple_code (use_stmt) == GIMPLE_PHI)
- locus2 = gimple_phi_arg_location (use_stmt, PHI_ARG_INDEX_FROM_USE (use_p));
- else
- locus2 = gimple_location (use_stmt);
- block2 = LOCATION_BLOCK (locus2);
- locus2 = LOCATION_LOCUS (locus2);
-
- if ((!optimize || optimize_debug)
- && ter
- && ((locus1 != UNKNOWN_LOCATION
- && locus1 != locus2)
- || (block1 != NULL_TREE
- && block1 != block2)))
- return false;
-
- /* Used in this block, but at the TOP of the block, not the end. */
- if (gimple_code (use_stmt) == GIMPLE_PHI)
- return false;
-
- /* There must be no VDEFs. */
- if (gimple_vdef (stmt))
- return false;
-
- /* Without alias info we can't move around loads. */
- if ((!optimize || !ter)
- && gimple_assign_single_p (stmt)
- && !is_gimple_val (gimple_assign_rhs1 (stmt)))
- return false;
-
- /* Float expressions must go through memory if float-store is on. */
- if (flag_float_store
- && FLOAT_TYPE_P (gimple_expr_type (stmt)))
- return false;
-
- /* An assignment with a register variable on the RHS is not
- replaceable. */
- if (gimple_assign_rhs_code (stmt) == VAR_DECL
- && DECL_HARD_REGISTER (gimple_assign_rhs1 (stmt)))
- return false;
-
- /* No function calls can be replaced. */
- if (is_gimple_call (stmt))
- return false;
-
- /* Leave any stmt with volatile operands alone as well. */
- if (gimple_has_volatile_ops (stmt))
- return false;
-
- return true;
-}
-
-
-/* Variant of is_replaceable_p test for use in EXPAND_INITIALIZER
- expansion. */
-
-bool
-stmt_is_replaceable_p (gimple stmt)
-{
- return is_replaceable_p (stmt, false);
-}
-
-
/* This function will remove the expression for VERSION from replacement
consideration in table TAB. If FREE_EXPR is true, then remove the
expression from consideration as well by freeing the decl uid bitmap. */
@@ -487,6 +388,62 @@ finished_with_expr (temp_expr_table_p tab, int version, bool free_expr)
}
+/* Return TRUE if expression STMT is suitable for replacement.
+ In addition to ssa_is_replaceable_p, require the same bb, and for -O0
+ same locus and same BLOCK), Considers memory loads as replaceable if aliasing
+ is available. */
+
+static inline bool
+ter_is_replaceable_p (gimple stmt)
+{
+
+ if (ssa_is_replaceable_p (stmt))
+ {
+ use_operand_p use_p;
+ tree def;
+ gimple use_stmt;
+ location_t locus1, locus2;
+ tree block1, block2;
+
+ /* Only consider definitions which have a single use. ssa_is_replaceable_p
+ already performed this check, but the use stmt pointer is required for
+ further checks. */
+ def = SINGLE_SSA_TREE_OPERAND (stmt, SSA_OP_DEF);
+ if (!single_imm_use (def, &use_p, &use_stmt))
+ return false;
+
+ /* If the use isn't in this block, it wont be replaced either. */
+ if (gimple_bb (use_stmt) != gimple_bb (stmt))
+ return false;
+
+ locus1 = gimple_location (stmt);
+ block1 = LOCATION_BLOCK (locus1);
+ locus1 = LOCATION_LOCUS (locus1);
+
+ if (gimple_code (use_stmt) == GIMPLE_PHI)
+ locus2 = gimple_phi_arg_location (use_stmt,
+ PHI_ARG_INDEX_FROM_USE (use_p));
+ else
+ locus2 = gimple_location (use_stmt);
+ block2 = LOCATION_BLOCK (locus2);
+ locus2 = LOCATION_LOCUS (locus2);
+
+ if ((!optimize || optimize_debug)
+ && ((locus1 != UNKNOWN_LOCATION && locus1 != locus2)
+ || (block1 != NULL_TREE && block1 != block2)))
+ return false;
+
+ /* Without alias info we can't move around loads. */
+ if (!optimize && gimple_assign_single_p (stmt)
+ && !is_gimple_val (gimple_assign_rhs1 (stmt)))
+ return false;
+
+ return true;
+ }
+ return false;
+}
+
+
/* Create an expression entry for a replaceable expression. */
static void
@@ -497,7 +454,7 @@ process_replaceable (temp_expr_table_p tab, gimple stmt, int call_cnt)
ssa_op_iter iter;
bitmap def_vars, use_vars;
- gcc_checking_assert (is_replaceable_p (stmt, true));
+ gcc_checking_assert (ter_is_replaceable_p (stmt));
def = SINGLE_SSA_TREE_OPERAND (stmt, SSA_OP_DEF);
version = SSA_NAME_VERSION (def);
@@ -612,7 +569,7 @@ find_replaceable_in_bb (temp_expr_table_p tab, basic_block bb)
if (is_gimple_debug (stmt))
continue;
- stmt_replaceable = is_replaceable_p (stmt, true);
+ stmt_replaceable = ter_is_replaceable_p (stmt);
/* Determine if this stmt finishes an existing expression. */
FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE)
diff --git a/gcc/tree-ssa-ter.h b/gcc/tree-ssa-ter.h
new file mode 100644
index 00000000000..e71f78b492f
--- /dev/null
+++ b/gcc/tree-ssa-ter.h
@@ -0,0 +1,26 @@
+/* Header file for tree-ssa-ter.c exports.
+ Copyright (C) 2013 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_SSA_TER_H
+#define GCC_TREE_SSA_TER_H
+
+extern bitmap find_replaceable_exprs (var_map);
+extern void dump_replaceable_exprs (FILE *, bitmap);
+
+#endif /* GCC_TREE_SSA_TER_H */
diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c
index 47db2804117..cd2b34ae6ff 100644
--- a/gcc/tree-ssa-threadedge.c
+++ b/gcc/tree-ssa-threadedge.c
@@ -30,10 +30,17 @@ along with GCC; see the file COPYING3. If not see
#include "function.h"
#include "timevar.h"
#include "dumpfile.h"
-#include "tree-ssa.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-cfg.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
#include "tree-ssa-propagate.h"
+#include "tree-ssa-threadupdate.h"
#include "langhooks.h"
#include "params.h"
+#include "tree-ssa-threadedge.h"
/* To avoid code explosion due to jump threading, we limit the
number of statements we are going to copy. This variable
@@ -51,6 +58,8 @@ set_ssa_name_value (tree name, tree value)
{
if (SSA_NAME_VERSION (name) >= ssa_name_values.length ())
ssa_name_values.safe_grow_cleared (SSA_NAME_VERSION (name) + 1);
+ if (value && TREE_OVERFLOW_P (value))
+ value = drop_tree_overflow (value);
ssa_name_values[SSA_NAME_VERSION (name)] = value;
}
@@ -637,7 +646,7 @@ propagate_threaded_block_debug_into (basic_block dest, basic_block src)
i++;
}
- vec<tree, va_stack> fewvars = vNULL;
+ stack_vec<tree, alloc_count> fewvars;
pointer_set_t *vars = NULL;
/* If we're already starting with 3/4 of alloc_count, go for a
@@ -645,8 +654,6 @@ propagate_threaded_block_debug_into (basic_block dest, basic_block src)
VEC. */
if (i * 4 > alloc_count * 3)
vars = pointer_set_create ();
- else if (alloc_count)
- vec_stack_alloc (tree, fewvars, alloc_count);
/* Now go through the initial debug stmts in DEST again, this time
actually inserting in VARS or FEWVARS. Don't bother checking for
@@ -753,7 +760,7 @@ thread_around_empty_blocks (edge taken_edge,
bool handle_dominating_asserts,
tree (*simplify) (gimple, gimple),
bitmap visited,
- vec<edge> *path)
+ vec<jump_thread_edge *> *path)
{
basic_block bb = taken_edge->dest;
gimple_stmt_iterator gsi;
@@ -770,7 +777,7 @@ thread_around_empty_blocks (edge taken_edge,
gsi = gsi_start_nondebug_bb (bb);
/* If the block has no statements, but does have a single successor, then
- it's just a forwarding block and we can thread through it trivially.
+ it's just a forwarding block and we can thread through it trivially.
However, note that just threading through empty blocks with single
successors is not inherently profitable. For the jump thread to
@@ -778,7 +785,7 @@ thread_around_empty_blocks (edge taken_edge,
By taking the return value from the recursive call, we get the
desired effect of returning TRUE when we found a profitable jump
- threading opportunity and FALSE otherwise.
+ threading opportunity and FALSE otherwise.
This is particularly important when this routine is called after
processing a joiner block. Returning TRUE too aggressively in
@@ -791,8 +798,10 @@ thread_around_empty_blocks (edge taken_edge,
if ((taken_edge->flags & EDGE_DFS_BACK) == 0
&& !bitmap_bit_p (visited, taken_edge->dest->index))
{
+ jump_thread_edge *x
+ = new jump_thread_edge (taken_edge, EDGE_NO_COPY_SRC_BLOCK);
+ path->safe_push (x);
bitmap_set_bit (visited, taken_edge->dest->index);
- path->safe_push (taken_edge);
return thread_around_empty_blocks (taken_edge,
dummy_cond,
handle_dominating_asserts,
@@ -828,7 +837,11 @@ thread_around_empty_blocks (edge taken_edge,
if (bitmap_bit_p (visited, taken_edge->dest->index))
return false;
bitmap_set_bit (visited, taken_edge->dest->index);
- path->safe_push (taken_edge);
+
+ jump_thread_edge *x
+ = new jump_thread_edge (taken_edge, EDGE_NO_COPY_SRC_BLOCK);
+ path->safe_push (x);
+
thread_around_empty_blocks (taken_edge,
dummy_cond,
handle_dominating_asserts,
@@ -837,13 +850,16 @@ thread_around_empty_blocks (edge taken_edge,
path);
return true;
}
-
+
return false;
}
-
+
/* We are exiting E->src, see if E->dest ends with a conditional
jump which has a known value when reached via E.
+ E->dest can have arbitrary side effects which, if threading is
+ successful, will be maintained.
+
Special care is necessary if E is a back edge in the CFG as we
may have already recorded equivalences for E->dest into our
various tables, including the result of the conditional at
@@ -851,11 +867,6 @@ thread_around_empty_blocks (edge taken_edge,
limited in that case to avoid short-circuiting the loop
incorrectly.
- Note it is quite common for the first block inside a loop to
- end with a conditional which is either always true or always
- false when reached via the loop backedge. Thus we do not want
- to blindly disable threading across a loop backedge.
-
DUMMY_COND is a shared cond_expr used by condition simplification as scratch,
to avoid allocating memory.
@@ -866,17 +877,20 @@ thread_around_empty_blocks (edge taken_edge,
STACK is used to undo temporary equivalences created during the walk of
E->dest.
- SIMPLIFY is a pass-specific function used to simplify statements. */
+ SIMPLIFY is a pass-specific function used to simplify statements.
-void
-thread_across_edge (gimple dummy_cond,
- edge e,
- bool handle_dominating_asserts,
- vec<tree> *stack,
- tree (*simplify) (gimple, gimple))
-{
- gimple stmt;
+ Our caller is responsible for restoring the state of the expression
+ and const_and_copies stacks. */
+static bool
+thread_through_normal_block (edge e,
+ gimple dummy_cond,
+ bool handle_dominating_asserts,
+ vec<tree> *stack,
+ tree (*simplify) (gimple, gimple),
+ vec<jump_thread_edge *> *path,
+ bitmap visited)
+{
/* If E is a backedge, then we want to verify that the COND_EXPR,
SWITCH_EXPR or GOTO_EXPR at the end of e->dest is not affected
by any statements in e->dest. If it is affected, then it is not
@@ -884,20 +898,19 @@ thread_across_edge (gimple dummy_cond,
if (e->flags & EDGE_DFS_BACK)
{
if (cond_arg_set_in_bb (e, e->dest))
- goto fail;
+ return false;
}
- stmt_count = 0;
-
/* PHIs create temporary equivalences. */
if (!record_temporary_equivalences_from_phis (e, stack))
- goto fail;
+ return false;
/* Now walk each statement recording any context sensitive
temporary equivalences we can detect. */
- stmt = record_temporary_equivalences_from_stmts_at_dest (e, stack, simplify);
+ gimple stmt
+ = record_temporary_equivalences_from_stmts_at_dest (e, stack, simplify);
if (!stmt)
- goto fail;
+ return false;
/* If we stopped at a COND_EXPR or SWITCH_EXPR, see if we know which arm
will be taken. */
@@ -915,16 +928,18 @@ thread_across_edge (gimple dummy_cond,
{
edge taken_edge = find_taken_edge (e->dest, cond);
basic_block dest = (taken_edge ? taken_edge->dest : NULL);
- bitmap visited;
/* DEST could be NULL for a computed jump to an absolute
address. */
- if (dest == NULL || dest == e->dest)
- goto fail;
+ if (dest == NULL || dest == e->dest || bitmap_bit_p (visited, dest->index))
+ return false;
+
+ jump_thread_edge *x
+ = new jump_thread_edge (e, EDGE_START_JUMP_THREAD);
+ path->safe_push (x);
- vec<edge> path = vNULL;
- path.safe_push (e);
- path.safe_push (taken_edge);
+ x = new jump_thread_edge (taken_edge, EDGE_COPY_SRC_BLOCK);
+ path->safe_push (x);
/* See if we can thread through DEST as well, this helps capture
secondary effects of threading without having to re-run DOM or
@@ -934,7 +949,6 @@ thread_across_edge (gimple dummy_cond,
{
/* We don't want to thread back to a block we have already
visited. This may be overly conservative. */
- visited = BITMAP_ALLOC (NULL);
bitmap_set_bit (visited, dest->index);
bitmap_set_bit (visited, e->dest->index);
thread_around_empty_blocks (taken_edge,
@@ -942,18 +956,73 @@ thread_across_edge (gimple dummy_cond,
handle_dominating_asserts,
simplify,
visited,
- &path);
- BITMAP_FREE (visited);
+ path);
}
-
- remove_temporary_equivalences (stack);
- propagate_threaded_block_debug_into (path[path.length () - 1]->dest,
- e->dest);
- register_jump_thread (path, false);
- path.release ();
- return;
+ return true;
}
}
+ return false;
+}
+
+/* We are exiting E->src, see if E->dest ends with a conditional
+ jump which has a known value when reached via E.
+
+ Special care is necessary if E is a back edge in the CFG as we
+ may have already recorded equivalences for E->dest into our
+ various tables, including the result of the conditional at
+ the end of E->dest. Threading opportunities are severely
+ limited in that case to avoid short-circuiting the loop
+ incorrectly.
+
+ Note it is quite common for the first block inside a loop to
+ end with a conditional which is either always true or always
+ false when reached via the loop backedge. Thus we do not want
+ to blindly disable threading across a loop backedge.
+
+ DUMMY_COND is a shared cond_expr used by condition simplification as scratch,
+ to avoid allocating memory.
+
+ HANDLE_DOMINATING_ASSERTS is true if we should try to replace operands of
+ the simplified condition with left-hand sides of ASSERT_EXPRs they are
+ used in.
+
+ STACK is used to undo temporary equivalences created during the walk of
+ E->dest.
+
+ SIMPLIFY is a pass-specific function used to simplify statements. */
+
+void
+thread_across_edge (gimple dummy_cond,
+ edge e,
+ bool handle_dominating_asserts,
+ vec<tree> *stack,
+ tree (*simplify) (gimple, gimple))
+{
+ bitmap visited = BITMAP_ALLOC (NULL);
+
+ stmt_count = 0;
+
+ vec<jump_thread_edge *> *path = new vec<jump_thread_edge *> ();
+ bitmap_clear (visited);
+ bitmap_set_bit (visited, e->src->index);
+ bitmap_set_bit (visited, e->dest->index);
+ if (thread_through_normal_block (e, dummy_cond, handle_dominating_asserts,
+ stack, simplify, path, visited))
+ {
+ propagate_threaded_block_debug_into (path->last ()->e->dest,
+ e->dest);
+ remove_temporary_equivalences (stack);
+ BITMAP_FREE (visited);
+ register_jump_thread (path);
+ return;
+ }
+ else
+ {
+ /* There should be no edges on the path, so no need to walk through
+ the vector entries. */
+ gcc_assert (path->length () == 0);
+ path->release ();
+ }
/* We were unable to determine what out edge from E->dest is taken. However,
we might still be able to thread through successors of E->dest. This
@@ -970,7 +1039,16 @@ thread_across_edge (gimple dummy_cond,
edge taken_edge;
edge_iterator ei;
bool found;
- bitmap visited = BITMAP_ALLOC (NULL);
+
+ /* If E->dest has abnormal outgoing edges, then there's no guarantee
+ we can safely redirect any of the edges. Just punt those cases. */
+ FOR_EACH_EDGE (taken_edge, ei, e->dest->succs)
+ if (taken_edge->flags & EDGE_ABNORMAL)
+ {
+ remove_temporary_equivalences (stack);
+ BITMAP_FREE (visited);
+ return;
+ }
/* Look at each successor of E->dest to see if we can thread through it. */
FOR_EACH_EDGE (taken_edge, ei, e->dest->succs)
@@ -979,36 +1057,40 @@ thread_across_edge (gimple dummy_cond,
bitmap_clear (visited);
bitmap_set_bit (visited, taken_edge->dest->index);
bitmap_set_bit (visited, e->dest->index);
- vec<edge> path = vNULL;
+ vec<jump_thread_edge *> *path = new vec<jump_thread_edge *> ();
/* Record whether or not we were able to thread through a successor
of E->dest. */
- path.safe_push (e);
- path.safe_push (taken_edge);
+ jump_thread_edge *x = new jump_thread_edge (e, EDGE_START_JUMP_THREAD);
+ path->safe_push (x);
+
+ x = new jump_thread_edge (taken_edge, EDGE_COPY_SRC_JOINER_BLOCK);
+ path->safe_push (x);
found = false;
if ((e->flags & EDGE_DFS_BACK) == 0
- || ! cond_arg_set_in_bb (path[path.length () - 1], e->dest))
+ || ! cond_arg_set_in_bb (path->last ()->e, e->dest))
found = thread_around_empty_blocks (taken_edge,
dummy_cond,
handle_dominating_asserts,
simplify,
visited,
- &path);
+ path);
/* If we were able to thread through a successor of E->dest, then
record the jump threading opportunity. */
if (found)
{
- propagate_threaded_block_debug_into (path[path.length () - 1]->dest,
+ propagate_threaded_block_debug_into (path->last ()->e->dest,
taken_edge->dest);
- register_jump_thread (path, true);
+ register_jump_thread (path);
+ }
+ else
+ {
+ delete_jump_thread_path (path);
}
-
- path.release();
}
BITMAP_FREE (visited);
}
- fail:
remove_temporary_equivalences (stack);
}
diff --git a/gcc/tree-ssa-threadedge.h b/gcc/tree-ssa-threadedge.h
new file mode 100644
index 00000000000..5cdae0e6847
--- /dev/null
+++ b/gcc/tree-ssa-threadedge.h
@@ -0,0 +1,36 @@
+/* Header file for SSA jump threading.
+ Copyright (C) 2013 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_SSA_THREADEDGE_H
+#define GCC_TREE_SSA_THREADEDGE_H
+
+extern vec<tree> ssa_name_values;
+#define SSA_NAME_VALUE(x) \
+ (SSA_NAME_VERSION (x) < ssa_name_values.length () \
+ ? ssa_name_values[SSA_NAME_VERSION (x)] \
+ : NULL_TREE)
+extern void set_ssa_name_value (tree, tree);
+extern void threadedge_initialize_values (void);
+extern void threadedge_finalize_values (void);
+extern bool potentially_threadable_block (basic_block);
+extern void propagate_threaded_block_debug_into (basic_block, basic_block);
+extern void thread_across_edge (gimple, edge, bool,
+ vec<tree> *, tree (*) (gimple, gimple));
+
+#endif /* GCC_TREE_SSA_THREADEDGE_H */
diff --git a/gcc/tree-ssa-threadupdate.c b/gcc/tree-ssa-threadupdate.c
index 413112814d6..ac0d2d3bdd6 100644
--- a/gcc/tree-ssa-threadupdate.c
+++ b/gcc/tree-ssa-threadupdate.c
@@ -20,16 +20,19 @@ along with GCC; see the file COPYING3. If not see
#include "config.h"
#include "system.h"
#include "coretypes.h"
-#include "tm.h"
#include "tree.h"
#include "flags.h"
-#include "tm_p.h"
#include "basic-block.h"
#include "function.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-phinodes.h"
#include "tree-ssa.h"
+#include "tree-ssa-threadupdate.h"
#include "dumpfile.h"
#include "cfgloop.h"
#include "hash-table.h"
+#include "dbgcnt.h"
/* Given a block B, update the CFG and SSA graph to reflect redirecting
one or more in-edges to B to instead reach the destination of an
@@ -69,14 +72,14 @@ along with GCC; see the file COPYING3. If not see
set of unique destination blocks that the incoming edges should
be threaded to.
- Block duplication can be further minimized by using B instead of
+ Block duplication can be further minimized by using B instead of
creating B' for one destination if all edges into B are going to be
threaded to a successor of B. We had code to do this at one time, but
I'm not convinced it is correct with the changes to avoid mucking up
the loop structure (which may cancel threading requests, thus a block
which we thought was going to become unreachable may still be reachable).
This code was also going to get ugly with the introduction of the ability
- for a single jump thread request to bypass multiple blocks.
+ for a single jump thread request to bypass multiple blocks.
We further reduce the number of edges and statements we create by
not copying all the outgoing edges and the control statement in
@@ -115,14 +118,11 @@ struct redirection_data : typed_free_remove<redirection_data>
targets a single successor of B. */
basic_block dup_block;
- /* An outgoing edge from B. DUP_BLOCK will have OUTGOING_EDGE->dest as
- its single successor. */
- edge outgoing_edge;
+ /* The jump threading path. */
+ vec<jump_thread_edge *> *path;
- edge intermediate_edge;
-
- /* A list of incoming edges which we want to thread to
- OUTGOING_EDGE->dest. */
+ /* A list of incoming edges which we want to thread to the
+ same path. */
struct el *incoming_edges;
/* hash_table support. */
@@ -132,21 +132,36 @@ struct redirection_data : typed_free_remove<redirection_data>
static inline int equal (const value_type *, const compare_type *);
};
+/* Simple hashing function. For any given incoming edge E, we're going
+ to be most concerned with the final destination of its jump thread
+ path. So hash on the block index of the final edge in the path. */
+
inline hashval_t
redirection_data::hash (const value_type *p)
{
- edge e = p->outgoing_edge;
- return e->dest->index;
+ vec<jump_thread_edge *> *path = p->path;
+ return path->last ()->e->dest->index;
}
+/* Given two hash table entries, return true if they have the same
+ jump threading path. */
inline int
redirection_data::equal (const value_type *p1, const compare_type *p2)
{
- edge e1 = p1->outgoing_edge;
- edge e2 = p2->outgoing_edge;
- edge e3 = p1->intermediate_edge;
- edge e4 = p2->intermediate_edge;
- return e1 == e2 && e3 == e4;
+ vec<jump_thread_edge *> *path1 = p1->path;
+ vec<jump_thread_edge *> *path2 = p2->path;
+
+ if (path1->length () != path2->length ())
+ return false;
+
+ for (unsigned int i = 1; i < path1->length (); i++)
+ {
+ if ((*path1)[i]->type != (*path2)[i]->type
+ || (*path1)[i]->e != (*path2)[i]->e)
+ return false;
+ }
+
+ return true;
}
/* Data structure of information to pass to hash table traversal routines. */
@@ -167,13 +182,12 @@ struct ssa_local_info_t
opportunities as they are discovered. We keep the registered
jump threading opportunities in this vector as edge pairs
(original_edge, target_edge). */
-static vec<edge> threaded_edges;
+static vec<vec<jump_thread_edge *> *> paths;
/* When we start updating the CFG for threading, data necessary for jump
threading is attached to the AUX field for the incoming edge. Use these
macros to access the underlying structure attached to the AUX field. */
-#define THREAD_TARGET(E) ((edge *)(E)->aux)[0]
-#define THREAD_TARGET2(E) ((edge *)(E)->aux)[1]
+#define THREAD_PATH(E) ((vec<jump_thread_edge *> *)(E)->aux)
/* Jump threading statistics. */
@@ -254,13 +268,12 @@ lookup_redirection_data (edge e, enum insert_option insert)
{
struct redirection_data **slot;
struct redirection_data *elt;
+ vec<jump_thread_edge *> *path = THREAD_PATH (e);
/* Build a hash table element so we can see if E is already
in the table. */
elt = XNEW (struct redirection_data);
- elt->intermediate_edge = THREAD_TARGET2 (e) ? THREAD_TARGET (e) : NULL;
- elt->outgoing_edge = THREAD_TARGET2 (e) ? THREAD_TARGET2 (e)
- : THREAD_TARGET (e);
+ elt->path = path;
elt->dup_block = NULL;
elt->incoming_edges = NULL;
@@ -354,17 +367,28 @@ static void
create_edge_and_update_destination_phis (struct redirection_data *rd,
basic_block bb)
{
- edge e = make_edge (bb, rd->outgoing_edge->dest, EDGE_FALLTHRU);
+ edge e = make_edge (bb, rd->path->last ()->e->dest, EDGE_FALLTHRU);
rescan_loop_exit (e, true, false);
e->probability = REG_BR_PROB_BASE;
e->count = bb->count;
- if (rd->outgoing_edge->aux)
+ /* We have to copy path -- which means creating a new vector as well
+ as all the jump_thread_edge entries. */
+ if (rd->path->last ()->e->aux)
{
- e->aux = XNEWVEC (edge, 2);
- THREAD_TARGET(e) = THREAD_TARGET (rd->outgoing_edge);
- THREAD_TARGET2(e) = THREAD_TARGET2 (rd->outgoing_edge);
+ vec<jump_thread_edge *> *path = THREAD_PATH (rd->path->last ()->e);
+ vec<jump_thread_edge *> *copy = new vec<jump_thread_edge *> ();
+
+ /* Sadly, the elements of the vector are pointers and need to
+ be copied as well. */
+ for (unsigned int i = 0; i < path->length (); i++)
+ {
+ jump_thread_edge *x
+ = new jump_thread_edge ((*path)[i]->e, (*path)[i]->type);
+ copy->safe_push (x);
+ }
+ e->aux = (void *)copy;
}
else
{
@@ -375,7 +399,7 @@ create_edge_and_update_destination_phis (struct redirection_data *rd,
from the duplicate block, then we will need to add a new argument
to them. The argument should have the same value as the argument
associated with the outgoing edge stored in RD. */
- copy_phi_args (e->dest, rd->outgoing_edge, e);
+ copy_phi_args (e->dest, rd->path->last ()->e, e);
}
/* Wire up the outgoing edges from the duplicate block and
@@ -384,15 +408,17 @@ void
ssa_fix_duplicate_block_edges (struct redirection_data *rd,
ssa_local_info_t *local_info)
{
+ edge e = rd->incoming_edges->e;
+ vec<jump_thread_edge *> *path = THREAD_PATH (e);
+
/* If we were threading through an joiner block, then we want
to keep its control statement and redirect an outgoing edge.
Else we want to remove the control statement & edges, then create
a new outgoing edge. In both cases we may need to update PHIs. */
- if (THREAD_TARGET2 (rd->incoming_edges->e))
+ if ((*path)[1]->type == EDGE_COPY_SRC_JOINER_BLOCK)
{
edge victim;
edge e2;
- edge e = rd->incoming_edges->e;
/* This updates the PHIs at the destination of the duplicate
block. */
@@ -400,14 +426,15 @@ ssa_fix_duplicate_block_edges (struct redirection_data *rd,
/* Find the edge from the duplicate block to the block we're
threading through. That's the edge we want to redirect. */
- victim = find_edge (rd->dup_block, THREAD_TARGET (e)->dest);
- e2 = redirect_edge_and_branch (victim, THREAD_TARGET2 (e)->dest);
+ victim = find_edge (rd->dup_block, (*path)[1]->e->dest);
+ e2 = redirect_edge_and_branch (victim, path->last ()->e->dest);
+ e2->count = path->last ()->e->count;
/* If we redirected the edge, then we need to copy PHI arguments
at the target. If the edge already existed (e2 != victim case),
then the PHIs in the target already have the correct arguments. */
if (e2 == victim)
- copy_phi_args (e2->dest, THREAD_TARGET2 (e), e2);
+ copy_phi_args (e2->dest, path->last ()->e, e2);
}
else
{
@@ -488,6 +515,7 @@ ssa_redirect_edges (struct redirection_data **slot,
for (el = rd->incoming_edges; el; el = next)
{
edge e = el->e;
+ vec<jump_thread_edge *> *path = THREAD_PATH (e);
/* Go ahead and free this element from the list. Doing this now
avoids the need for another list walk when we destroy the hash
@@ -496,18 +524,8 @@ ssa_redirect_edges (struct redirection_data **slot,
free (el);
thread_stats.num_threaded_edges++;
- /* If we are threading through a joiner block, then we have to
- find the edge we want to redirect and update some PHI nodes. */
- if (THREAD_TARGET2 (e))
- {
- edge e2;
- /* We want to redirect the incoming edge to the joiner block (E)
- to instead reach the duplicate of the joiner block. */
- e2 = redirect_edge_and_branch (e, rd->dup_block);
- flush_pending_stmts (e2);
- }
- else if (rd->dup_block)
+ if (rd->dup_block)
{
edge e2;
@@ -521,9 +539,15 @@ ssa_redirect_edges (struct redirection_data **slot,
the computation overflows. */
if (rd->dup_block->frequency < BB_FREQ_MAX * 2)
rd->dup_block->frequency += EDGE_FREQUENCY (e);
- EDGE_SUCC (rd->dup_block, 0)->count += e->count;
- /* Redirect the incoming edge to the appropriate duplicate
- block. */
+
+ /* In the case of threading through a joiner block, the outgoing
+ edges from the duplicate block were updated when they were
+ redirected during ssa_fix_duplicate_block_edges. */
+ if ((*path)[1]->type != EDGE_COPY_SRC_JOINER_BLOCK)
+ EDGE_SUCC (rd->dup_block, 0)->count += e->count;
+
+ /* Redirect the incoming edge (possibly to the joiner block) to the
+ appropriate duplicate block. */
e2 = redirect_edge_and_branch (e, rd->dup_block);
gcc_assert (e == e2);
flush_pending_stmts (e2);
@@ -531,7 +555,7 @@ ssa_redirect_edges (struct redirection_data **slot,
/* Go ahead and clear E->aux. It's not needed anymore and failure
to clear it will cause all kinds of unpleasant problems later. */
- free (e->aux);
+ delete_jump_thread_path (path);
e->aux = NULL;
}
@@ -590,10 +614,12 @@ redirection_block_p (basic_block bb)
the appropriate duplicate of BB.
If NOLOOP_ONLY is true, we only perform the threading as long as it
- does not affect the structure of the loops in a nontrivial way. */
+ does not affect the structure of the loops in a nontrivial way.
+
+ If JOINERS is true, then thread through joiner blocks as well. */
static bool
-thread_block (basic_block bb, bool noloop_only)
+thread_block_1 (basic_block bb, bool noloop_only, bool joiners)
{
/* E is an incoming edge into BB that we may or may not want to
redirect to a duplicate of BB. */
@@ -614,17 +640,23 @@ thread_block (basic_block bb, bool noloop_only)
if (loop->header == bb)
{
e = loop_latch_edge (loop);
+ vec<jump_thread_edge *> *path = THREAD_PATH (e);
- if (e->aux)
- e2 = THREAD_TARGET (e);
- else
- e2 = NULL;
-
- if (e2 && loop_exit_edge_p (loop, e2))
+ if (path
+ && (((*path)[1]->type == EDGE_COPY_SRC_JOINER_BLOCK && joiners)
+ || ((*path)[1]->type == EDGE_COPY_SRC_BLOCK && !joiners)))
{
- loop->header = NULL;
- loop->latch = NULL;
- loops_state_set (LOOPS_NEED_FIXUP);
+ for (unsigned int i = 1; i < path->length (); i++)
+ {
+ edge e2 = (*path)[i]->e;
+
+ if (loop_exit_edge_p (loop, e2))
+ {
+ loop->header = NULL;
+ loop->latch = NULL;
+ loops_state_set (LOOPS_NEED_FIXUP);
+ }
+ }
}
}
@@ -635,15 +667,17 @@ thread_block (basic_block bb, bool noloop_only)
if (e->aux == NULL)
continue;
- if (THREAD_TARGET2 (e))
- e2 = THREAD_TARGET2 (e);
- else
- e2 = THREAD_TARGET (e);
+ vec<jump_thread_edge *> *path = THREAD_PATH (e);
+
+ if (((*path)[1]->type == EDGE_COPY_SRC_JOINER_BLOCK && !joiners)
+ || ((*path)[1]->type == EDGE_COPY_SRC_BLOCK && joiners))
+ continue;
+ e2 = path->last ()->e;
if (!e2 || noloop_only)
{
/* If NOLOOP_ONLY is true, we only allow threading through the
- header of a loop to exit edges.
+ header of a loop to exit edges.
There are two cases to consider. The first when BB is the
loop header. We will attempt to thread this elsewhere, so
@@ -651,7 +685,7 @@ thread_block (basic_block bb, bool noloop_only)
if (bb == bb->loop_father->header
&& (!loop_exit_edge_p (bb->loop_father, e2)
- || THREAD_TARGET2 (e)))
+ || (*path)[1]->type == EDGE_COPY_SRC_JOINER_BLOCK))
continue;
@@ -667,7 +701,7 @@ thread_block (basic_block bb, bool noloop_only)
/* Since this case is not handled by our special code
to thread through a loop header, we must explicitly
cancel the threading request here. */
- free (e->aux);
+ delete_jump_thread_path (path);
e->aux = NULL;
continue;
}
@@ -675,7 +709,7 @@ thread_block (basic_block bb, bool noloop_only)
if (e->dest == e2->src)
update_bb_profile_for_threading (e->dest, EDGE_FREQUENCY (e),
- e->count, THREAD_TARGET (e));
+ e->count, (*THREAD_PATH (e))[1]->e);
/* Insert the outgoing edge into the hash table if it is not
already in the hash table. */
@@ -733,6 +767,24 @@ thread_block (basic_block bb, bool noloop_only)
return local_info.jumps_threaded;
}
+/* Wrapper for thread_block_1 so that we can first handle jump
+ thread paths which do not involve copying joiner blocks, then
+ handle jump thread paths which have joiner blocks.
+
+ By doing things this way we can be as aggressive as possible and
+ not worry that copying a joiner block will create a jump threading
+ opportunity. */
+
+static bool
+thread_block (basic_block bb, bool noloop_only)
+{
+ bool retval;
+ retval = thread_block_1 (bb, noloop_only, false);
+ retval |= thread_block_1 (bb, noloop_only, true);
+ return retval;
+}
+
+
/* Threads edge E through E->dest to the edge THREAD_TARGET (E). Returns the
copy of E->dest created during threading, or E->dest if it was not necessary
to copy it (E is its single predecessor). */
@@ -741,10 +793,13 @@ static basic_block
thread_single_edge (edge e)
{
basic_block bb = e->dest;
- edge eto = THREAD_TARGET (e);
struct redirection_data rd;
+ vec<jump_thread_edge *> *path = THREAD_PATH (e);
+ edge eto = (*path)[1]->e;
- free (e->aux);
+ for (unsigned int i = 0; i < path->length (); i++)
+ delete (*path)[i];
+ delete path;
e->aux = NULL;
thread_stats.num_threaded_edges++;
@@ -766,7 +821,13 @@ thread_single_edge (edge e)
if (e->dest == eto->src)
update_bb_profile_for_threading (bb, EDGE_FREQUENCY (e), e->count, eto);
- rd.outgoing_edge = eto;
+ vec<jump_thread_edge *> *npath = new vec<jump_thread_edge *> ();
+ jump_thread_edge *x = new jump_thread_edge (e, EDGE_START_JUMP_THREAD);
+ npath->safe_push (x);
+
+ x = new jump_thread_edge (eto, EDGE_COPY_SRC_BLOCK);
+ npath->safe_push (x);
+ rd.path = npath;
create_block_for_threading (bb, &rd);
remove_ctrl_stmt_and_useless_edges (rd.dup_block, NULL);
@@ -965,9 +1026,10 @@ thread_through_loop_header (struct loop *loop, bool may_peel_loop_headers)
if (latch->aux)
{
- if (THREAD_TARGET2 (latch))
+ vec<jump_thread_edge *> *path = THREAD_PATH (latch);
+ if ((*path)[1]->type == EDGE_COPY_SRC_JOINER_BLOCK)
goto fail;
- tgt_edge = THREAD_TARGET (latch);
+ tgt_edge = (*path)[1]->e;
tgt_bb = tgt_edge->dest;
}
else if (!may_peel_loop_headers
@@ -990,9 +1052,11 @@ thread_through_loop_header (struct loop *loop, bool may_peel_loop_headers)
goto fail;
}
- if (THREAD_TARGET2 (e))
+ vec<jump_thread_edge *> *path = THREAD_PATH (e);
+
+ if ((*path)[1]->type == EDGE_COPY_SRC_JOINER_BLOCK)
goto fail;
- tgt_edge = THREAD_TARGET (e);
+ tgt_edge = (*path)[1]->e;
atgt_bb = tgt_edge->dest;
if (!tgt_bb)
tgt_bb = atgt_bb;
@@ -1087,15 +1151,13 @@ thread_through_loop_header (struct loop *loop, bool may_peel_loop_headers)
if (e->aux == NULL)
continue;
- if (THREAD_TARGET2 (e))
- e2 = THREAD_TARGET2 (e);
- else
- e2 = THREAD_TARGET (e);
+ vec<jump_thread_edge *> *path = THREAD_PATH (e);
+ e2 = path->last ()->e;
if (e->src->loop_father != e2->dest->loop_father
&& e2->dest != loop->header)
{
- free (e->aux);
+ delete_jump_thread_path (path);
e->aux = NULL;
}
}
@@ -1141,8 +1203,13 @@ fail:
/* We failed to thread anything. Cancel the requests. */
FOR_EACH_EDGE (e, ei, header->preds)
{
- free (e->aux);
- e->aux = NULL;
+ vec<jump_thread_edge *> *path = THREAD_PATH (e);
+
+ if (path)
+ {
+ delete_jump_thread_path (path);
+ e->aux = NULL;
+ }
}
return false;
}
@@ -1192,52 +1259,102 @@ mark_threaded_blocks (bitmap threaded_blocks)
edge e;
edge_iterator ei;
- /* It is possible to have jump threads in which one is a subpath
- of the other. ie, (A, B), (B, C), (C, D) where B is a joiner
- block and (B, C), (C, D) where no joiner block exists.
+ /* Move the jump threading requests from PATHS to each edge
+ which starts a jump thread path. */
+ for (i = 0; i < paths.length (); i++)
+ {
+ vec<jump_thread_edge *> *path = paths[i];
+ edge e = (*path)[0]->e;
+ e->aux = (void *)path;
+ bitmap_set_bit (tmp, e->dest->index);
+ }
- When this occurs ignore the jump thread request with the joiner
- block. It's totally subsumed by the simpler jump thread request.
- This results in less block copying, simpler CFGs. More improtantly,
- when we duplicate the joiner block, B, in this case we will create
- a new threading opportunity that we wouldn't be able to optimize
- until the next jump threading iteration.
- So first convert the jump thread requests which do not require a
- joiner block. */
- for (i = 0; i < threaded_edges.length (); i += 3)
+ /* If optimizing for size, only thread through block if we don't have
+ to duplicate it or it's an otherwise empty redirection block. */
+ if (optimize_function_for_size_p (cfun))
{
- edge e = threaded_edges[i];
-
- if (threaded_edges[i + 2] == NULL)
+ EXECUTE_IF_SET_IN_BITMAP (tmp, 0, i, bi)
{
- edge *x = XNEWVEC (edge, 2);
-
- e->aux = x;
- THREAD_TARGET (e) = threaded_edges[i + 1];
- THREAD_TARGET2 (e) = NULL;
- bitmap_set_bit (tmp, e->dest->index);
+ bb = BASIC_BLOCK (i);
+ if (EDGE_COUNT (bb->preds) > 1
+ && !redirection_block_p (bb))
+ {
+ FOR_EACH_EDGE (e, ei, bb->preds)
+ {
+ if (e->aux)
+ {
+ vec<jump_thread_edge *> *path = THREAD_PATH (e);
+ delete_jump_thread_path (path);
+ e->aux = NULL;
+ }
+ }
+ }
+ else
+ bitmap_set_bit (threaded_blocks, i);
}
}
+ else
+ bitmap_copy (threaded_blocks, tmp);
+ /* Look for jump threading paths which cross multiple loop headers.
- /* Now iterate again, converting cases where we threaded through
- a joiner block, but ignoring those where we have already
- threaded through the joiner block. */
- for (i = 0; i < threaded_edges.length (); i += 3)
- {
- edge e = threaded_edges[i];
+ The code to thread through loop headers will change the CFG in ways
+ that break assumptions made by the loop optimization code.
- if (threaded_edges[i + 2] != NULL
- && threaded_edges[i + 1]->aux == NULL)
+ We don't want to blindly cancel the requests. We can instead do better
+ by trimming off the end of the jump thread path. */
+ EXECUTE_IF_SET_IN_BITMAP (tmp, 0, i, bi)
+ {
+ basic_block bb = BASIC_BLOCK (i);
+ FOR_EACH_EDGE (e, ei, bb->preds)
{
- edge *x = XNEWVEC (edge, 2);
+ if (e->aux)
+ {
+ vec<jump_thread_edge *> *path = THREAD_PATH (e);
- e->aux = x;
- THREAD_TARGET (e) = threaded_edges[i + 1];
- THREAD_TARGET2 (e) = threaded_edges[i + 2];
- bitmap_set_bit (tmp, e->dest->index);
+ /* Basically we're looking for a situation where we can see
+ 3 or more loop structures on a jump threading path. */
+
+ struct loop *first_father = (*path)[0]->e->src->loop_father;
+ struct loop *second_father = NULL;
+ for (unsigned int i = 0; i < path->length (); i++)
+ {
+ /* See if this is a loop father we have not seen before. */
+ if ((*path)[i]->e->dest->loop_father != first_father
+ && (*path)[i]->e->dest->loop_father != second_father)
+ {
+ /* We've already seen two loop fathers, so we
+ need to trim this jump threading path. */
+ if (second_father != NULL)
+ {
+ /* Trim from entry I onwards. */
+ for (unsigned int j = i; j < path->length (); j++)
+ delete (*path)[j];
+ path->truncate (i);
+
+ /* Now that we've truncated the path, make sure
+ what's left is still valid. We need at least
+ two edges on the path and the last edge can not
+ be a joiner. This should never happen, but let's
+ be safe. */
+ if (path->length () < 2
+ || (path->last ()->type
+ == EDGE_COPY_SRC_JOINER_BLOCK))
+ {
+ delete_jump_thread_path (path);
+ e->aux = NULL;
+ }
+ break;
+ }
+ else
+ {
+ second_father = (*path)[i]->e->dest->loop_father;
+ }
+ }
+ }
+ }
}
}
@@ -1248,10 +1365,13 @@ mark_threaded_blocks (bitmap threaded_blocks)
We used to detect this prior to registering the jump thread, but
that prohibits propagation of edge equivalences into non-dominated
- PHI nodes as the equivalency test might occur before propagation.
+ PHI nodes as the equivalency test might occur before propagation.
+
+ This must also occur after we truncate any jump threading paths
+ as this scenario may only show up after truncation.
This works for now, but will need improvement as part of the FSA
- optimization.
+ optimization.
Note since we've moved the thread request data to the edges,
we have to iterate on those rather than the threaded_edges vector. */
@@ -1262,18 +1382,19 @@ mark_threaded_blocks (bitmap threaded_blocks)
{
if (e->aux)
{
- bool have_joiner = THREAD_TARGET2 (e) != NULL;
+ vec<jump_thread_edge *> *path = THREAD_PATH (e);
+ bool have_joiner = ((*path)[1]->type == EDGE_COPY_SRC_JOINER_BLOCK);
if (have_joiner)
{
basic_block joiner = e->dest;
- edge final_edge = THREAD_TARGET2 (e);
+ edge final_edge = path->last ()->e;
basic_block final_dest = final_edge->dest;
edge e2 = find_edge (joiner, final_dest);
if (e2 && !phi_args_equal_on_edges (e2, final_edge))
{
- free (e->aux);
+ delete_jump_thread_path (path);
e->aux = NULL;
}
}
@@ -1281,31 +1402,7 @@ mark_threaded_blocks (bitmap threaded_blocks)
}
}
-
- /* If optimizing for size, only thread through block if we don't have
- to duplicate it or it's an otherwise empty redirection block. */
- if (optimize_function_for_size_p (cfun))
- {
- EXECUTE_IF_SET_IN_BITMAP (tmp, 0, i, bi)
- {
- bb = BASIC_BLOCK (i);
- if (EDGE_COUNT (bb->preds) > 1
- && !redirection_block_p (bb))
- {
- FOR_EACH_EDGE (e, ei, bb->preds)
- {
- free (e->aux);
- e->aux = NULL;
- }
- }
- else
- bitmap_set_bit (threaded_blocks, i);
- }
- }
- else
- bitmap_copy (threaded_blocks, tmp);
-
- BITMAP_FREE(tmp);
+ BITMAP_FREE (tmp);
}
@@ -1333,7 +1430,7 @@ thread_through_all_blocks (bool may_peel_loop_headers)
/* We must know about loops in order to preserve them. */
gcc_assert (current_loops != NULL);
- if (!threaded_edges.exists ())
+ if (!paths.exists ())
return false;
threaded_blocks = BITMAP_ALLOC (NULL);
@@ -1365,6 +1462,37 @@ thread_through_all_blocks (bool may_peel_loop_headers)
retval |= thread_through_loop_header (loop, may_peel_loop_headers);
}
+ /* Assume we had a jump thread path which went from the latch to the exit
+ and a path which goes from outside to inside the same loop.
+
+ If the latch to exit was handled first, we will thread it and clear
+ loop->header.
+
+ The second path will be ignored by thread_block because we're going
+ through a loop header. It will also be ignored by the loop above
+ because loop->header is NULL.
+
+ This results in the second path never being threaded. The failure
+ mode is a dangling AUX field.
+
+ This is inherently a bit of a pain to fix, so we just walk all the
+ blocks and all the incoming edges to those blocks and clear their
+ AUX fields. */
+ basic_block bb;
+ edge_iterator ei;
+ edge e;
+ FOR_EACH_BB (bb)
+ {
+ FOR_EACH_EDGE (e, ei, bb->preds)
+ if (e->aux)
+ {
+ vec<jump_thread_edge *> *path = THREAD_PATH (e);
+
+ delete_jump_thread_path (path);
+ e->aux = NULL;
+ }
+ }
+
statistics_counter_event (cfun, "Jumps threaded",
thread_stats.num_threaded_edges);
@@ -1372,7 +1500,7 @@ thread_through_all_blocks (bool may_peel_loop_headers)
BITMAP_FREE (threaded_blocks);
threaded_blocks = NULL;
- threaded_edges.release ();
+ paths.release ();
if (retval)
loops_state_set (LOOPS_NEED_FIXUP);
@@ -1380,6 +1508,49 @@ thread_through_all_blocks (bool may_peel_loop_headers)
return retval;
}
+/* Delete the jump threading path PATH. We have to explcitly delete
+ each entry in the vector, then the container. */
+
+void
+delete_jump_thread_path (vec<jump_thread_edge *> *path)
+{
+ for (unsigned int i = 0; i < path->length (); i++)
+ delete (*path)[i];
+ path->release();
+}
+
+/* Dump a jump threading path, including annotations about each
+ edge in the path. */
+
+static void
+dump_jump_thread_path (FILE *dump_file, vec<jump_thread_edge *> path)
+{
+ fprintf (dump_file,
+ " Registering jump thread: (%d, %d) incoming edge; ",
+ path[0]->e->src->index, path[0]->e->dest->index);
+
+ for (unsigned int i = 1; i < path.length (); i++)
+ {
+ /* We can get paths with a NULL edge when the final destination
+ of a jump thread turns out to be a constant address. We dump
+ those paths when debugging, so we have to be prepared for that
+ possibility here. */
+ if (path[i]->e == NULL)
+ continue;
+
+ if (path[i]->type == EDGE_COPY_SRC_JOINER_BLOCK)
+ fprintf (dump_file, " (%d, %d) joiner; ",
+ path[i]->e->src->index, path[i]->e->dest->index);
+ if (path[i]->type == EDGE_COPY_SRC_BLOCK)
+ fprintf (dump_file, " (%d, %d) normal;",
+ path[i]->e->src->index, path[i]->e->dest->index);
+ if (path[i]->type == EDGE_NO_COPY_SRC_BLOCK)
+ fprintf (dump_file, " (%d, %d) nocopy;",
+ path[i]->e->src->index, path[i]->e->dest->index);
+ }
+ fputc ('\n', dump_file);
+}
+
/* Register a jump threading opportunity. We queue up all the jump
threading opportunities discovered by a pass and update the CFG
and SSA form all at once.
@@ -1389,43 +1560,35 @@ thread_through_all_blocks (bool may_peel_loop_headers)
after fixing the SSA graph. */
void
-register_jump_thread (vec<edge> path, bool through_joiner)
+register_jump_thread (vec<jump_thread_edge *> *path)
{
- /* Convert PATH into 3 edge representation we've been using. This
- is temporary until we convert this file to use a path representation
- throughout. */
- edge e = path[0];
- edge e2 = path[1];
- edge e3;
-
- if (!through_joiner)
- e3 = NULL;
- else
- e3 = path[path.length () - 1];
+ if (!dbg_cnt (registered_jump_thread))
+ {
+ delete_jump_thread_path (path);
+ return;
+ }
- /* This can occur if we're jumping to a constant address or
- or something similar. Just get out now. */
- if (e2 == NULL)
- return;
+ /* First make sure there are no NULL outgoing edges on the jump threading
+ path. That can happen for jumping to a constant address. */
+ for (unsigned int i = 0; i < path->length (); i++)
+ if ((*path)[i]->e == NULL)
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file,
+ "Found NULL edge in jump threading path. Cancelling jump thread:\n");
+ dump_jump_thread_path (dump_file, *path);
+ }
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- unsigned int i;
+ delete_jump_thread_path (path);
+ return;
+ }
- fprintf (dump_file,
- " Registering jump thread %s:",
- through_joiner ? "(through joiner block)" : "");
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ dump_jump_thread_path (dump_file, *path);
- for (i = 0; i < path.length (); i++)
- fprintf (dump_file, " (%d, %d); ",
- path[i]->src->index, path[i]->dest->index);
- fputc ('\n', dump_file);
- }
-
- if (!threaded_edges.exists ())
- threaded_edges.create (15);
+ if (!paths.exists ())
+ paths.create (5);
- threaded_edges.safe_push (e);
- threaded_edges.safe_push (e2);
- threaded_edges.safe_push (e3);
+ paths.safe_push (path);
}
diff --git a/gcc/tree-ssa-threadupdate.h b/gcc/tree-ssa-threadupdate.h
new file mode 100644
index 00000000000..4617b9c1d3e
--- /dev/null
+++ b/gcc/tree-ssa-threadupdate.h
@@ -0,0 +1,46 @@
+/* Communication between registering jump thread requests and
+ updating the SSA/CFG for jump threading.
+ Copyright (C) 2013 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 _TREE_SSA_THREADUPDATE_H
+#define _TREE_SSA_THREADUPDATE_H 1
+
+/* In tree-ssa-threadupdate.c. */
+extern bool thread_through_all_blocks (bool);
+enum jump_thread_edge_type
+{
+ EDGE_START_JUMP_THREAD,
+ EDGE_COPY_SRC_BLOCK,
+ EDGE_COPY_SRC_JOINER_BLOCK,
+ EDGE_NO_COPY_SRC_BLOCK
+};
+
+class jump_thread_edge
+{
+public:
+ jump_thread_edge (edge e, enum jump_thread_edge_type type)
+ : e (e), type (type) {}
+
+ edge e;
+ enum jump_thread_edge_type type;
+};
+
+extern void register_jump_thread (vec <class jump_thread_edge *> *);
+extern void delete_jump_thread_path (vec <class jump_thread_edge *> *);
+#endif
diff --git a/gcc/tree-ssa-uncprop.c b/gcc/tree-ssa-uncprop.c
index a13ccf01135..5255d7fb738 100644
--- a/gcc/tree-ssa-uncprop.c
+++ b/gcc/tree-ssa-uncprop.c
@@ -26,7 +26,11 @@ along with GCC; see the file COPYING3. If not see
#include "tm_p.h"
#include "basic-block.h"
#include "function.h"
-#include "tree-ssa.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-cfg.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
#include "domwalk.h"
#include "tree-pass.h"
#include "tree-ssa-propagate.h"
@@ -357,26 +361,18 @@ record_equiv (tree value, tree equivalence)
class uncprop_dom_walker : public dom_walker
{
public:
- uncprop_dom_walker (cdi_direction direction)
- : dom_walker (direction)
- {
- equiv_stack_.create (2);
- }
- ~uncprop_dom_walker ()
- {
- equiv_stack_.release ();
- }
+ uncprop_dom_walker (cdi_direction direction) : dom_walker (direction) {}
virtual void before_dom_children (basic_block);
virtual void after_dom_children (basic_block);
private:
-/* As we enter each block we record the value for any edge equivalency
- leading to this block. If no such edge equivalency exists, then we
- record NULL. These equivalences are live until we leave the dominator
- subtree rooted at the block where we record the equivalency. */
- vec<tree> equiv_stack_;
+ /* As we enter each block we record the value for any edge equivalency
+ leading to this block. If no such edge equivalency exists, then we
+ record NULL. These equivalences are live until we leave the dominator
+ subtree rooted at the block where we record the equivalency. */
+ stack_vec<tree, 2> m_equiv_stack;
};
/* Main driver for un-cprop. */
@@ -428,7 +424,7 @@ void
uncprop_dom_walker::after_dom_children (basic_block bb ATTRIBUTE_UNUSED)
{
/* Pop the topmost value off the equiv stack. */
- tree value = equiv_stack_.pop ();
+ tree value = m_equiv_stack.pop ();
/* If that value was non-null, then pop the topmost equivalency off
its equivalency stack. */
@@ -566,13 +562,13 @@ uncprop_dom_walker::before_dom_children (basic_block bb)
struct edge_equivalency *equiv = (struct edge_equivalency *) e->aux;
record_equiv (equiv->rhs, equiv->lhs);
- equiv_stack_.safe_push (equiv->rhs);
+ m_equiv_stack.safe_push (equiv->rhs);
recorded = true;
}
}
if (!recorded)
- equiv_stack_.safe_push (NULL_TREE);
+ m_equiv_stack.safe_push (NULL_TREE);
uncprop_into_successor_phis (bb);
}
@@ -603,12 +599,12 @@ const pass_data pass_data_uncprop =
class pass_uncprop : public gimple_opt_pass
{
public:
- pass_uncprop(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_uncprop, ctxt)
+ pass_uncprop (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_uncprop, ctxt)
{}
/* opt_pass methods: */
- opt_pass * clone () { return new pass_uncprop (ctxt_); }
+ opt_pass * clone () { return new pass_uncprop (m_ctxt); }
bool gate () { return gate_uncprop (); }
unsigned int execute () { return tree_ssa_uncprop (); }
diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c
index bd46ddfb18e..5e376a1df51 100644
--- a/gcc/tree-ssa-uninit.c
+++ b/gcc/tree-ssa-uninit.c
@@ -30,8 +30,11 @@ along with GCC; see the file COPYING3. If not see
#include "gimple-pretty-print.h"
#include "bitmap.h"
#include "pointer-set.h"
-#include "tree-ssa.h"
#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssa.h"
#include "tree-inline.h"
#include "hashtab.h"
#include "tree-pass.h"
@@ -2193,12 +2196,12 @@ const pass_data pass_data_late_warn_uninitialized =
class pass_late_warn_uninitialized : public gimple_opt_pass
{
public:
- pass_late_warn_uninitialized(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_late_warn_uninitialized, ctxt)
+ pass_late_warn_uninitialized (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_late_warn_uninitialized, ctxt)
{}
/* opt_pass methods: */
- opt_pass * clone () { return new pass_late_warn_uninitialized (ctxt_); }
+ opt_pass * clone () { return new pass_late_warn_uninitialized (m_ctxt); }
bool gate () { return gate_warn_uninitialized (); }
unsigned int execute () { return execute_late_warn_uninitialized (); }
@@ -2254,8 +2257,8 @@ const pass_data pass_data_early_warn_uninitialized =
class pass_early_warn_uninitialized : public gimple_opt_pass
{
public:
- pass_early_warn_uninitialized(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_early_warn_uninitialized, ctxt)
+ pass_early_warn_uninitialized (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_early_warn_uninitialized, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c
index 8146e1fed1d..ba8045d4702 100644
--- a/gcc/tree-ssa.c
+++ b/gcc/tree-ssa.c
@@ -30,10 +30,15 @@ along with GCC; see the file COPYING3. If not see
#include "basic-block.h"
#include "function.h"
#include "gimple-pretty-print.h"
-#include "bitmap.h"
#include "pointer-set.h"
-#include "tree-ssa.h"
#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
+#include "tree-ssa-loop-manip.h"
+#include "tree-into-ssa.h"
+#include "tree-ssa.h"
#include "tree-inline.h"
#include "hashtab.h"
#include "tree-pass.h"
@@ -231,6 +236,41 @@ flush_pending_stmts (edge e)
redirect_edge_var_map_clear (e);
}
+/* Replace the LHS of STMT, an assignment, either a GIMPLE_ASSIGN or a
+ GIMPLE_CALL, with NLHS, in preparation for modifying the RHS to an
+ expression with a different value.
+
+ This will update any annotations (say debug bind stmts) referring
+ to the original LHS, so that they use the RHS instead. This is
+ done even if NLHS and LHS are the same, for it is understood that
+ the RHS will be modified afterwards, and NLHS will not be assigned
+ an equivalent value.
+
+ Adjusting any non-annotation uses of the LHS, if needed, is a
+ responsibility of the caller.
+
+ The effect of this call should be pretty much the same as that of
+ inserting a copy of STMT before STMT, and then removing the
+ original stmt, at which time gsi_remove() would have update
+ annotations, but using this function saves all the inserting,
+ copying and removing. */
+
+void
+gimple_replace_ssa_lhs (gimple stmt, tree nlhs)
+{
+ if (MAY_HAVE_DEBUG_STMTS)
+ {
+ tree lhs = gimple_get_lhs (stmt);
+
+ gcc_assert (SSA_NAME_DEF_STMT (lhs) == stmt);
+
+ insert_debug_temp_for_var_def (NULL, lhs);
+ }
+
+ gimple_set_lhs (stmt, nlhs);
+}
+
+
/* Given a tree for an expression for which we might want to emit
locations or values in debug information (generally a variable, but
we might deal with other kinds of trees in the future), return the
@@ -1118,8 +1158,8 @@ const pass_data pass_data_init_datastructures =
class pass_init_datastructures : public gimple_opt_pass
{
public:
- pass_init_datastructures(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_init_datastructures, ctxt)
+ pass_init_datastructures (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_init_datastructures, ctxt)
{}
/* opt_pass methods: */
@@ -1218,115 +1258,6 @@ ssa_undefined_value_p (tree t)
}
-/* Internal helper for walk_use_def_chains. VAR, FN and DATA are as
- described in walk_use_def_chains.
-
- VISITED is a pointer set used to mark visited SSA_NAMEs to avoid
- infinite loops. We used to have a bitmap for this to just mark
- SSA versions we had visited. But non-sparse bitmaps are way too
- expensive, while sparse bitmaps may cause quadratic behavior.
-
- IS_DFS is true if the caller wants to perform a depth-first search
- when visiting PHI nodes. A DFS will visit each PHI argument and
- call FN after each one. Otherwise, all the arguments are
- visited first and then FN is called with each of the visited
- arguments in a separate pass. */
-
-static bool
-walk_use_def_chains_1 (tree var, walk_use_def_chains_fn fn, void *data,
- struct pointer_set_t *visited, bool is_dfs)
-{
- gimple def_stmt;
-
- if (pointer_set_insert (visited, var))
- return false;
-
- def_stmt = SSA_NAME_DEF_STMT (var);
-
- if (gimple_code (def_stmt) != GIMPLE_PHI)
- {
- /* If we reached the end of the use-def chain, call FN. */
- return fn (var, def_stmt, data);
- }
- else
- {
- size_t i;
-
- /* When doing a breadth-first search, call FN before following the
- use-def links for each argument. */
- if (!is_dfs)
- for (i = 0; i < gimple_phi_num_args (def_stmt); i++)
- if (fn (gimple_phi_arg_def (def_stmt, i), def_stmt, data))
- return true;
-
- /* Follow use-def links out of each PHI argument. */
- for (i = 0; i < gimple_phi_num_args (def_stmt); i++)
- {
- tree arg = gimple_phi_arg_def (def_stmt, i);
-
- /* ARG may be NULL for newly introduced PHI nodes. */
- if (arg
- && TREE_CODE (arg) == SSA_NAME
- && walk_use_def_chains_1 (arg, fn, data, visited, is_dfs))
- return true;
- }
-
- /* When doing a depth-first search, call FN after following the
- use-def links for each argument. */
- if (is_dfs)
- for (i = 0; i < gimple_phi_num_args (def_stmt); i++)
- if (fn (gimple_phi_arg_def (def_stmt, i), def_stmt, data))
- return true;
- }
-
- return false;
-}
-
-
-
-/* Walk use-def chains starting at the SSA variable VAR. Call
- function FN at each reaching definition found. FN takes three
- arguments: VAR, its defining statement (DEF_STMT) and a generic
- pointer to whatever state information that FN may want to maintain
- (DATA). FN is able to stop the walk by returning true, otherwise
- in order to continue the walk, FN should return false.
-
- Note, that if DEF_STMT is a PHI node, the semantics are slightly
- different. The first argument to FN is no longer the original
- variable VAR, but the PHI argument currently being examined. If FN
- wants to get at VAR, it should call PHI_RESULT (PHI).
-
- If IS_DFS is true, this function will:
-
- 1- walk the use-def chains for all the PHI arguments, and,
- 2- call (*FN) (ARG, PHI, DATA) on all the PHI arguments.
-
- If IS_DFS is false, the two steps above are done in reverse order
- (i.e., a breadth-first search). */
-
-void
-walk_use_def_chains (tree var, walk_use_def_chains_fn fn, void *data,
- bool is_dfs)
-{
- gimple def_stmt;
-
- gcc_assert (TREE_CODE (var) == SSA_NAME);
-
- def_stmt = SSA_NAME_DEF_STMT (var);
-
- /* We only need to recurse if the reaching definition comes from a PHI
- node. */
- if (gimple_code (def_stmt) != GIMPLE_PHI)
- (*fn) (var, def_stmt, data);
- else
- {
- struct pointer_set_t *visited = pointer_set_create ();
- walk_use_def_chains_1 (var, fn, data, visited, is_dfs);
- pointer_set_destroy (visited);
- }
-}
-
-
/* If necessary, rewrite the base of the reference tree *TP from
a MEM_REF to a plain or converted symbol. */
@@ -1758,8 +1689,8 @@ const pass_data pass_data_update_address_taken =
class pass_update_address_taken : public gimple_opt_pass
{
public:
- pass_update_address_taken(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_update_address_taken, ctxt)
+ pass_update_address_taken (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_update_address_taken, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/tree-ssa.h b/gcc/tree-ssa.h
index 1808b1c447a..89ea5c64c76 100644
--- a/gcc/tree-ssa.h
+++ b/gcc/tree-ssa.h
@@ -20,9 +20,6 @@ along with GCC; see the file COPYING3. If not see
#ifndef GCC_TREE_SSA_H
#define GCC_TREE_SSA_H
-#include "tree-flow.h"
-#include "tree-ssanames.h"
-
/* Mapping for redirected edges. */
struct _edge_var_map {
tree result; /* PHI result. */
@@ -42,6 +39,7 @@ extern edge_var_map_vector *redirect_edge_var_map_vector (edge);
extern void redirect_edge_var_map_destroy (void);
extern edge ssa_redirect_edge (edge, basic_block);
extern void flush_pending_stmts (edge);
+extern void gimple_replace_ssa_lhs (gimple, tree);
extern tree target_for_debug_bind (tree);
extern void insert_debug_temp_for_var_def (gimple_stmt_iterator *, tree);
extern void insert_debug_temps_for_defs (gimple_stmt_iterator *);
@@ -53,11 +51,6 @@ extern void delete_tree_ssa (void);
extern bool tree_ssa_useless_type_conversion (tree);
extern tree tree_ssa_strip_useless_type_conversions (tree);
-/* Call-back function for walk_use_def_chains(). At each reaching
- definition, a function with this prototype is called. */
-typedef bool (*walk_use_def_chains_fn) (tree, gimple, void *);
-extern void walk_use_def_chains (tree, walk_use_def_chains_fn, void *, bool);
-
extern bool ssa_undefined_value_p (tree);
extern void execute_update_addresses_taken (void);
diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c
index e64bd656dff..76358912569 100644
--- a/gcc/tree-ssanames.c
+++ b/gcc/tree-ssanames.c
@@ -22,6 +22,12 @@ along with GCC; see the file COPYING3. If not see
#include "coretypes.h"
#include "tm.h"
#include "tree.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
+#include "tree-into-ssa.h"
#include "tree-ssa.h"
#include "tree-pass.h"
@@ -154,7 +160,11 @@ make_ssa_name_fn (struct function *fn, tree var, gimple stmt)
SET_SSA_NAME_VAR_OR_IDENTIFIER (t, var);
}
SSA_NAME_DEF_STMT (t) = stmt;
- SSA_NAME_PTR_INFO (t) = NULL;
+ if (POINTER_TYPE_P (TREE_TYPE (t)))
+ SSA_NAME_PTR_INFO (t) = NULL;
+ else
+ SSA_NAME_RANGE_INFO (t) = NULL;
+
SSA_NAME_IN_FREE_LIST (t) = 0;
SSA_NAME_IS_DEFAULT_DEF (t) = 0;
imm = &(SSA_NAME_IMM_USE_NODE (t));
@@ -166,6 +176,122 @@ make_ssa_name_fn (struct function *fn, tree var, gimple stmt)
return t;
}
+/* Store range information MIN, and MAX to tree ssa_name NAME. */
+
+void
+set_range_info (tree name, double_int min, double_int max)
+{
+ gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name)));
+ range_info_def *ri = SSA_NAME_RANGE_INFO (name);
+
+ /* Allocate if not available. */
+ if (ri == NULL)
+ {
+ ri = ggc_alloc_cleared_range_info_def ();
+ SSA_NAME_RANGE_INFO (name) = ri;
+ ri->nonzero_bits = double_int::mask (TYPE_PRECISION (TREE_TYPE (name)));
+ }
+
+ /* Set the values. */
+ ri->min = min;
+ ri->max = max;
+
+ /* If it is a range, try to improve nonzero_bits from the min/max. */
+ if (min.cmp (max, TYPE_UNSIGNED (TREE_TYPE (name))) != 1)
+ {
+ int prec = TYPE_PRECISION (TREE_TYPE (name));
+ double_int xorv;
+
+ min = min.zext (prec);
+ max = max.zext (prec);
+ xorv = min ^ max;
+ if (xorv.high)
+ xorv = double_int::mask (2 * HOST_BITS_PER_WIDE_INT
+ - clz_hwi (xorv.high));
+ else if (xorv.low)
+ xorv = double_int::mask (HOST_BITS_PER_WIDE_INT
+ - clz_hwi (xorv.low));
+ ri->nonzero_bits = ri->nonzero_bits & (min | xorv);
+ }
+}
+
+
+/* Gets range information MIN, MAX and returns enum value_range_type
+ corresponding to tree ssa_name NAME. enum value_range_type returned
+ is used to determine if MIN and MAX are valid values. */
+
+enum value_range_type
+get_range_info (const_tree name, double_int *min, double_int *max)
+{
+ enum value_range_type range_type;
+ gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name)));
+ gcc_assert (min && max);
+ range_info_def *ri = SSA_NAME_RANGE_INFO (name);
+
+ /* Return VR_VARYING for SSA_NAMEs with NULL RANGE_INFO or SSA_NAMEs
+ with integral types width > 2 * HOST_BITS_PER_WIDE_INT precision. */
+ if (!ri || (GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (name)))
+ > 2 * HOST_BITS_PER_WIDE_INT))
+ return VR_VARYING;
+
+ /* If min > max, it is VR_ANTI_RANGE. */
+ if (ri->min.cmp (ri->max, TYPE_UNSIGNED (TREE_TYPE (name))) == 1)
+ {
+ /* VR_ANTI_RANGE ~[min, max] is encoded as [max + 1, min - 1]. */
+ range_type = VR_ANTI_RANGE;
+ *min = ri->max + double_int_one;
+ *max = ri->min - double_int_one;
+ }
+ else
+ {
+ /* Otherwise (when min <= max), it is VR_RANGE. */
+ range_type = VR_RANGE;
+ *min = ri->min;
+ *max = ri->max;
+ }
+ return range_type;
+}
+
+/* Change non-zero bits bitmask of NAME. */
+
+void
+set_nonzero_bits (tree name, double_int mask)
+{
+ gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name)));
+ if (SSA_NAME_RANGE_INFO (name) == NULL)
+ set_range_info (name,
+ tree_to_double_int (TYPE_MIN_VALUE (TREE_TYPE (name))),
+ tree_to_double_int (TYPE_MAX_VALUE (TREE_TYPE (name))));
+ range_info_def *ri = SSA_NAME_RANGE_INFO (name);
+ ri->nonzero_bits
+ = mask & double_int::mask (TYPE_PRECISION (TREE_TYPE (name)));
+}
+
+/* Return a double_int with potentially non-zero bits in SSA_NAME
+ NAME, or double_int_minus_one if unknown. */
+
+double_int
+get_nonzero_bits (const_tree name)
+{
+ if (POINTER_TYPE_P (TREE_TYPE (name)))
+ {
+ struct ptr_info_def *pi = SSA_NAME_PTR_INFO (name);
+ if (pi && pi->align)
+ {
+ double_int al = double_int::from_uhwi (pi->align - 1);
+ return ((double_int::mask (TYPE_PRECISION (TREE_TYPE (name))) & ~al)
+ | double_int::from_uhwi (pi->misalign));
+ }
+ return double_int_minus_one;
+ }
+
+ range_info_def *ri = SSA_NAME_RANGE_INFO (name);
+ if (!ri || (GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (name)))
+ > 2 * HOST_BITS_PER_WIDE_INT))
+ return double_int_minus_one;
+
+ return ri->nonzero_bits;
+}
/* We no longer need the SSA_NAME expression VAR, release it so that
it may be reused.
@@ -362,6 +488,26 @@ duplicate_ssa_name_ptr_info (tree name, struct ptr_info_def *ptr_info)
SSA_NAME_PTR_INFO (name) = new_ptr_info;
}
+/* Creates a duplicate of the range_info_def at RANGE_INFO for use by
+ the SSA name NAME. */
+void
+duplicate_ssa_name_range_info (tree name, struct range_info_def *range_info)
+{
+ struct range_info_def *new_range_info;
+
+ gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name)));
+ gcc_assert (!SSA_NAME_RANGE_INFO (name));
+
+ if (!range_info)
+ return;
+
+ new_range_info = ggc_alloc_range_info_def ();
+ *new_range_info = *range_info;
+
+ SSA_NAME_RANGE_INFO (name) = new_range_info;
+}
+
+
/* Creates a duplicate of a ssa name NAME tobe defined by statement STMT
in function FN. */
@@ -370,10 +516,20 @@ tree
duplicate_ssa_name_fn (struct function *fn, tree name, gimple stmt)
{
tree new_name = copy_ssa_name_fn (fn, name, stmt);
- struct ptr_info_def *old_ptr_info = SSA_NAME_PTR_INFO (name);
+ if (POINTER_TYPE_P (TREE_TYPE (name)))
+ {
+ struct ptr_info_def *old_ptr_info = SSA_NAME_PTR_INFO (name);
+
+ if (old_ptr_info)
+ duplicate_ssa_name_ptr_info (new_name, old_ptr_info);
+ }
+ else
+ {
+ struct range_info_def *old_range_info = SSA_NAME_RANGE_INFO (name);
- if (old_ptr_info)
- duplicate_ssa_name_ptr_info (new_name, old_ptr_info);
+ if (old_range_info)
+ duplicate_ssa_name_range_info (new_name, old_range_info);
+ }
return new_name;
}
@@ -463,8 +619,8 @@ const pass_data pass_data_release_ssa_names =
class pass_release_ssa_names : public gimple_opt_pass
{
public:
- pass_release_ssa_names(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_release_ssa_names, ctxt)
+ pass_release_ssa_names (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_release_ssa_names, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/tree-ssanames.h b/gcc/tree-ssanames.h
index 8cc3efd02b1..d0a65425211 100644
--- a/gcc/tree-ssanames.h
+++ b/gcc/tree-ssanames.h
@@ -45,6 +45,17 @@ struct GTY(()) ptr_info_def
unsigned int misalign;
};
+/* Value range information for SSA_NAMEs representing non-pointer variables. */
+
+struct GTY (()) range_info_def {
+ /* Minimum for value range. */
+ double_int min;
+ /* Maximum for value range. */
+ double_int max;
+ /* Non-zero bits - bits not set are guaranteed to be always zero. */
+ double_int nonzero_bits;
+};
+
#define SSANAMES(fun) (fun)->gimple_df->ssa_names
#define MODIFIED_NORETURN_CALLS(fun) (fun)->gimple_df->modified_noreturn_calls
@@ -54,6 +65,17 @@ struct GTY(()) ptr_info_def
#define ssa_name(i) ((*cfun->gimple_df->ssa_names)[(i)])
+/* Type of value ranges. See value_range_d In tree-vrp.c for a
+ description of these types. */
+enum value_range_type { VR_UNDEFINED, VR_RANGE, VR_ANTI_RANGE, VR_VARYING };
+
+/* Sets the value range to SSA. */
+extern void set_range_info (tree, double_int, double_int);
+/* Gets the value range from SSA. */
+extern enum value_range_type get_range_info (const_tree, double_int *,
+ double_int *);
+extern void set_nonzero_bits (tree, double_int);
+extern double_int get_nonzero_bits (const_tree);
extern void init_ssanames (struct function *, int);
extern void fini_ssanames (void);
extern void ssanames_print_statistics (void);
@@ -71,6 +93,7 @@ extern struct ptr_info_def *get_ptr_info (tree);
extern tree copy_ssa_name_fn (struct function *, tree, gimple);
extern void duplicate_ssa_name_ptr_info (tree, struct ptr_info_def *);
extern tree duplicate_ssa_name_fn (struct function *, tree, gimple);
+extern void duplicate_ssa_name_range_info (tree, struct range_info_def *);
extern void release_defs (gimple);
extern void replace_ssa_name_symbol (tree, tree);
diff --git a/gcc/tree-stdarg.c b/gcc/tree-stdarg.c
index 922835366b5..2c8aac289b6 100644
--- a/gcc/tree-stdarg.c
+++ b/gcc/tree-stdarg.c
@@ -27,7 +27,13 @@ along with GCC; see the file COPYING3. If not see
#include "langhooks.h"
#include "gimple-pretty-print.h"
#include "target.h"
-#include "tree-ssa.h"
+#include "bitmap.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
+#include "sbitmap.h"
#include "tree-pass.h"
#include "tree-stdarg.h"
@@ -1005,8 +1011,8 @@ const pass_data pass_data_stdarg =
class pass_stdarg : public gimple_opt_pass
{
public:
- pass_stdarg(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_stdarg, ctxt)
+ pass_stdarg (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_stdarg, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/tree-streamer-in.c b/gcc/tree-streamer-in.c
index c36d4f6368c..92598e39941 100644
--- a/gcc/tree-streamer-in.c
+++ b/gcc/tree-streamer-in.c
@@ -24,7 +24,7 @@ along with GCC; see the file COPYING3. If not see
#include "coretypes.h"
#include "diagnostic.h"
#include "tree.h"
-#include "tree-ssa.h"
+#include "gimple.h"
#include "tree-streamer.h"
#include "data-streamer.h"
#include "streamer-hooks.h"
diff --git a/gcc/tree-streamer-out.c b/gcc/tree-streamer-out.c
index 942ba1ee44f..ea1a0546516 100644
--- a/gcc/tree-streamer-out.c
+++ b/gcc/tree-streamer-out.c
@@ -25,6 +25,7 @@ along with GCC; see the file COPYING3. If not see
#include "tm.h"
#include "diagnostic.h"
#include "tree.h"
+#include "gimple.h"
#include "tree-streamer.h"
#include "data-streamer.h"
#include "streamer-hooks.h"
diff --git a/gcc/tree-streamer.c b/gcc/tree-streamer.c
index 8d532d9c250..8534f4a9b8b 100644
--- a/gcc/tree-streamer.c
+++ b/gcc/tree-streamer.c
@@ -23,6 +23,8 @@ along with GCC; see the file COPYING3. If not see
#include "config.h"
#include "system.h"
#include "coretypes.h"
+#include "tree.h"
+#include "gimple.h"
#include "streamer-hooks.h"
#include "tree-streamer.h"
diff --git a/gcc/tree-streamer.h b/gcc/tree-streamer.h
index 02f8f51a195..1ed215c9792 100644
--- a/gcc/tree-streamer.h
+++ b/gcc/tree-streamer.h
@@ -22,7 +22,6 @@ along with GCC; see the file COPYING3. If not see
#ifndef GCC_TREE_STREAMER_H
#define GCC_TREE_STREAMER_H
-#include "tree.h"
#include "streamer-hooks.h"
#include "lto-streamer.h"
diff --git a/gcc/tree-switch-conversion.c b/gcc/tree-switch-conversion.c
index 2dd13fc9a54..46b9efe3aa7 100644
--- a/gcc/tree-switch-conversion.c
+++ b/gcc/tree-switch-conversion.c
@@ -31,9 +31,12 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
#include "flags.h"
#include "tree.h"
#include "basic-block.h"
-#include "tree-ssa.h"
-#include "tree-flow-inline.h"
-#include "tree-ssa-operands.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "cgraph.h"
+#include "tree-cfg.h"
+#include "tree-phinodes.h"
+#include "tree-ssanames.h"
#include "tree-pass.h"
#include "gimple-pretty-print.h"
#include "cfgloop.h"
@@ -365,7 +368,7 @@ emit_case_bit_tests (gimple swtch, tree index_expr,
test[k].lo |= (HOST_WIDE_INT) 1 << j;
}
- qsort (test, count, sizeof(*test), case_bit_test_cmp);
+ qsort (test, count, sizeof (*test), case_bit_test_cmp);
/* We generate two jumps to the default case label.
Split the default edge, so that we don't have to do any PHI node
@@ -1485,8 +1488,8 @@ const pass_data pass_data_convert_switch =
class pass_convert_switch : public gimple_opt_pass
{
public:
- pass_convert_switch(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_convert_switch, ctxt)
+ pass_convert_switch (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_convert_switch, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/tree-tailcall.c b/gcc/tree-tailcall.c
index c91c9da0222..70d167a58e9 100644
--- a/gcc/tree-tailcall.c
+++ b/gcc/tree-tailcall.c
@@ -25,7 +25,13 @@ along with GCC; see the file COPYING3. If not see
#include "tm_p.h"
#include "basic-block.h"
#include "function.h"
-#include "tree-ssa.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-cfg.h"
+#include "tree-phinodes.h"
+#include "tree-ssanames.h"
+#include "tree-into-ssa.h"
+#include "tree-dfa.h"
#include "gimple-pretty-print.h"
#include "except.h"
#include "tree-pass.h"
@@ -446,7 +452,9 @@ find_tail_calls (basic_block bb, struct tailcall **ret)
/* We found the call, check whether it is suitable. */
tail_recursion = false;
func = gimple_call_fndecl (call);
- if (func && recursive_call_p (current_function_decl, func))
+ if (func
+ && !DECL_BUILT_IN (func)
+ && recursive_call_p (current_function_decl, func))
{
tree arg;
@@ -1083,12 +1091,12 @@ const pass_data pass_data_tail_recursion =
class pass_tail_recursion : public gimple_opt_pass
{
public:
- pass_tail_recursion(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_tail_recursion, ctxt)
+ pass_tail_recursion (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_tail_recursion, ctxt)
{}
/* opt_pass methods: */
- opt_pass * clone () { return new pass_tail_recursion (ctxt_); }
+ opt_pass * clone () { return new pass_tail_recursion (m_ctxt); }
bool gate () { return gate_tail_calls (); }
unsigned int execute () { return execute_tail_recursion (); }
@@ -1122,8 +1130,8 @@ const pass_data pass_data_tail_calls =
class pass_tail_calls : public gimple_opt_pass
{
public:
- pass_tail_calls(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_tail_calls, ctxt)
+ pass_tail_calls (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_tail_calls, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c
index 98055ae01f8..b7eb926494d 100644
--- a/gcc/tree-vect-data-refs.c
+++ b/gcc/tree-vect-data-refs.c
@@ -30,7 +30,14 @@ along with GCC; see the file COPYING3. If not see
#include "target.h"
#include "basic-block.h"
#include "gimple-pretty-print.h"
-#include "tree-ssa.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
+#include "tree-ssa-loop-ivopts.h"
+#include "tree-ssa-loop-manip.h"
+#include "tree-ssa-loop.h"
#include "dumpfile.h"
#include "cfgloop.h"
#include "tree-chrec.h"
@@ -128,41 +135,6 @@ vect_get_smallest_scalar_type (gimple stmt, HOST_WIDE_INT *lhs_size_unit,
}
-/* Check if data references pointed by DR_I and DR_J are same or
- belong to same interleaving group. Return FALSE if drs are
- different, otherwise return TRUE. */
-
-static bool
-vect_same_range_drs (data_reference_p dr_i, data_reference_p dr_j)
-{
- gimple stmt_i = DR_STMT (dr_i);
- gimple stmt_j = DR_STMT (dr_j);
-
- if (operand_equal_p (DR_REF (dr_i), DR_REF (dr_j), 0)
- || (GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt_i))
- && GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt_j))
- && (GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt_i))
- == GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt_j)))))
- return true;
- else
- return false;
-}
-
-/* If address ranges represented by DDR_I and DDR_J are equal,
- return TRUE, otherwise return FALSE. */
-
-static bool
-vect_vfa_range_equal (ddr_p ddr_i, ddr_p ddr_j)
-{
- if ((vect_same_range_drs (DDR_A (ddr_i), DDR_A (ddr_j))
- && vect_same_range_drs (DDR_B (ddr_i), DDR_B (ddr_j)))
- || (vect_same_range_drs (DDR_A (ddr_i), DDR_B (ddr_j))
- && vect_same_range_drs (DDR_B (ddr_i), DDR_A (ddr_j))))
- return true;
- else
- return false;
-}
-
/* Insert DDR into LOOP_VINFO list of ddrs that may alias and need to be
tested at run-time. Return TRUE if DDR was successfully inserted.
Return false if versioning is not supported. */
@@ -1115,7 +1087,7 @@ vect_peeling_hash_insert (loop_vec_info loop_vinfo, struct data_reference *dr,
*new_slot = slot;
}
- if (!supportable_dr_alignment && !flag_vect_cost_model)
+ if (!supportable_dr_alignment && unlimited_cost_model ())
slot->count += VECT_MAX_COST;
}
@@ -1223,9 +1195,9 @@ vect_peeling_hash_choose_best_peeling (loop_vec_info loop_vinfo,
struct _vect_peel_extended_info res;
res.peel_info.dr = NULL;
- res.body_cost_vec = stmt_vector_for_cost();
+ res.body_cost_vec = stmt_vector_for_cost ();
- if (flag_vect_cost_model)
+ if (!unlimited_cost_model ())
{
res.inside_cost = INT_MAX;
res.outside_cost = INT_MAX;
@@ -1358,7 +1330,7 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
unsigned possible_npeel_number = 1;
tree vectype;
unsigned int nelements, mis, same_align_drs_max = 0;
- stmt_vector_for_cost body_cost_vec = stmt_vector_for_cost();
+ stmt_vector_for_cost body_cost_vec = stmt_vector_for_cost ();
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location,
@@ -1454,7 +1426,7 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
vectorization factor.
We do this automtically for cost model, since we calculate cost
for every peeling option. */
- if (!flag_vect_cost_model)
+ if (unlimited_cost_model ())
possible_npeel_number = vf /nelements;
/* Handle the aligned case. We may decide to align some other
@@ -1462,7 +1434,7 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
if (DR_MISALIGNMENT (dr) == 0)
{
npeel_tmp = 0;
- if (!flag_vect_cost_model)
+ if (unlimited_cost_model ())
possible_npeel_number++;
}
@@ -1718,6 +1690,30 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
if (do_peeling)
{
+ unsigned max_allowed_peel
+ = PARAM_VALUE (PARAM_VECT_MAX_PEELING_FOR_ALIGNMENT);
+ if (max_allowed_peel != (unsigned)-1)
+ {
+ unsigned max_peel = npeel;
+ if (max_peel == 0)
+ {
+ gimple dr_stmt = DR_STMT (dr0);
+ stmt_vec_info vinfo = vinfo_for_stmt (dr_stmt);
+ tree vtype = STMT_VINFO_VECTYPE (vinfo);
+ max_peel = TYPE_VECTOR_SUBPARTS (vtype) - 1;
+ }
+ if (max_peel > max_allowed_peel)
+ {
+ do_peeling = false;
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "Disable peeling, max peels reached: %d\n", max_peel);
+ }
+ }
+ }
+
+ if (do_peeling)
+ {
stmt_info_for_cost *si;
void *data = LOOP_VINFO_TARGET_COST_DATA (loop_vinfo);
@@ -1771,16 +1767,14 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
/* (2) Versioning to force alignment. */
/* Try versioning if:
- 1) flag_tree_vect_loop_version is TRUE
- 2) optimize loop for speed
- 3) there is at least one unsupported misaligned data ref with an unknown
+ 1) optimize loop for speed
+ 2) there is at least one unsupported misaligned data ref with an unknown
misalignment, and
- 4) all misaligned data refs with a known misalignment are supported, and
- 5) the number of runtime alignment checks is within reason. */
+ 3) all misaligned data refs with a known misalignment are supported, and
+ 4) the number of runtime alignment checks is within reason. */
do_versioning =
- flag_tree_vect_loop_version
- && optimize_loop_nest_for_speed_p (loop)
+ optimize_loop_nest_for_speed_p (loop)
&& (!loop->inner); /* FORNOW */
if (do_versioning)
@@ -2516,7 +2510,7 @@ vect_analyze_data_ref_accesses (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo)
/* Sort the array of datarefs to make building the interleaving chains
linear. */
- qsort (datarefs.address(), datarefs.length (),
+ qsort (datarefs.address (), datarefs.length (),
sizeof (data_reference_p), dr_group_sort_cmp);
/* Build the interleaving chains. */
@@ -2625,69 +2619,320 @@ vect_analyze_data_ref_accesses (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo)
return true;
}
+
+/* Operator == between two dr_addr_with_seg_len objects.
+
+ This equality operator is used to make sure two data refs
+ are the same one so that we will consider to combine the
+ aliasing checks of those two pairs of data dependent data
+ refs. */
+
+static bool
+operator == (const dr_addr_with_seg_len& d1,
+ const dr_addr_with_seg_len& d2)
+{
+ return operand_equal_p (d1.basic_addr, d2.basic_addr, 0)
+ && compare_tree (d1.offset, d2.offset) == 0
+ && compare_tree (d1.seg_len, d2.seg_len) == 0;
+}
+
+/* Function comp_dr_addr_with_seg_len_pair.
+
+ Comparison function for sorting objects of dr_addr_with_seg_len_pair_t
+ so that we can combine aliasing checks in one scan. */
+
+static int
+comp_dr_addr_with_seg_len_pair (const void *p1_, const void *p2_)
+{
+ const dr_addr_with_seg_len_pair_t* p1 =
+ (const dr_addr_with_seg_len_pair_t *) p1_;
+ const dr_addr_with_seg_len_pair_t* p2 =
+ (const dr_addr_with_seg_len_pair_t *) p2_;
+
+ const dr_addr_with_seg_len &p11 = p1->first,
+ &p12 = p1->second,
+ &p21 = p2->first,
+ &p22 = p2->second;
+
+ int comp_res = compare_tree (p11.basic_addr, p21.basic_addr);
+ if (comp_res != 0)
+ return comp_res;
+
+ comp_res = compare_tree (p12.basic_addr, p22.basic_addr);
+ if (comp_res != 0)
+ return comp_res;
+
+ if (TREE_CODE (p11.offset) != INTEGER_CST
+ || TREE_CODE (p21.offset) != INTEGER_CST)
+ {
+ comp_res = compare_tree (p11.offset, p21.offset);
+ if (comp_res != 0)
+ return comp_res;
+ }
+ else if (tree_int_cst_compare (p11.offset, p21.offset) < 0)
+ return -1;
+ else if (tree_int_cst_compare (p11.offset, p21.offset) > 0)
+ return 1;
+ if (TREE_CODE (p12.offset) != INTEGER_CST
+ || TREE_CODE (p22.offset) != INTEGER_CST)
+ {
+ comp_res = compare_tree (p12.offset, p22.offset);
+ if (comp_res != 0)
+ return comp_res;
+ }
+ else if (tree_int_cst_compare (p12.offset, p22.offset) < 0)
+ return -1;
+ else if (tree_int_cst_compare (p12.offset, p22.offset) > 0)
+ return 1;
+
+ return 0;
+}
+
+template <class T> static void
+swap (T& a, T& b)
+{
+ T c (a);
+ a = b;
+ b = c;
+}
+
+/* Function vect_vfa_segment_size.
+
+ Create an expression that computes the size of segment
+ that will be accessed for a data reference. The functions takes into
+ account that realignment loads may access one more vector.
+
+ Input:
+ DR: The data reference.
+ LENGTH_FACTOR: segment length to consider.
+
+ Return an expression whose value is the size of segment which will be
+ accessed by DR. */
+
+static tree
+vect_vfa_segment_size (struct data_reference *dr, tree length_factor)
+{
+ tree segment_length;
+
+ if (integer_zerop (DR_STEP (dr)))
+ segment_length = TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dr)));
+ else
+ segment_length = size_binop (MULT_EXPR,
+ fold_convert (sizetype, DR_STEP (dr)),
+ fold_convert (sizetype, length_factor));
+
+ if (vect_supportable_dr_alignment (dr, false)
+ == dr_explicit_realign_optimized)
+ {
+ tree vector_size = TYPE_SIZE_UNIT
+ (STMT_VINFO_VECTYPE (vinfo_for_stmt (DR_STMT (dr))));
+
+ segment_length = size_binop (PLUS_EXPR, segment_length, vector_size);
+ }
+ return segment_length;
+}
+
/* Function vect_prune_runtime_alias_test_list.
Prune a list of ddrs to be tested at run-time by versioning for alias.
+ Merge several alias checks into one if possible.
Return FALSE if resulting list of ddrs is longer then allowed by
PARAM_VECT_MAX_VERSION_FOR_ALIAS_CHECKS, otherwise return TRUE. */
bool
vect_prune_runtime_alias_test_list (loop_vec_info loop_vinfo)
{
- vec<ddr_p> ddrs =
+ vec<ddr_p> may_alias_ddrs =
LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo);
- unsigned i, j;
+ vec<dr_addr_with_seg_len_pair_t>& comp_alias_ddrs =
+ LOOP_VINFO_COMP_ALIAS_DDRS (loop_vinfo);
+ int vect_factor = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
+ tree scalar_loop_iters = LOOP_VINFO_NITERS (loop_vinfo);
+
+ ddr_p ddr;
+ unsigned int i;
+ tree length_factor;
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location,
"=== vect_prune_runtime_alias_test_list ===\n");
- for (i = 0; i < ddrs.length (); )
+ if (may_alias_ddrs.is_empty ())
+ return true;
+
+ /* Basically, for each pair of dependent data refs store_ptr_0
+ and load_ptr_0, we create an expression:
+
+ ((store_ptr_0 + store_segment_length_0) <= load_ptr_0)
+ || (load_ptr_0 + load_segment_length_0) <= store_ptr_0))
+
+ for aliasing checks. However, in some cases we can decrease
+ the number of checks by combining two checks into one. For
+ example, suppose we have another pair of data refs store_ptr_0
+ and load_ptr_1, and if the following condition is satisfied:
+
+ load_ptr_0 < load_ptr_1 &&
+ load_ptr_1 - load_ptr_0 - load_segment_length_0 < store_segment_length_0
+
+ (this condition means, in each iteration of vectorized loop,
+ the accessed memory of store_ptr_0 cannot be between the memory
+ of load_ptr_0 and load_ptr_1.)
+
+ we then can use only the following expression to finish the
+ alising checks between store_ptr_0 & load_ptr_0 and
+ store_ptr_0 & load_ptr_1:
+
+ ((store_ptr_0 + store_segment_length_0) <= load_ptr_0)
+ || (load_ptr_1 + load_segment_length_1 <= store_ptr_0))
+
+ Note that we only consider that load_ptr_0 and load_ptr_1 have the
+ same basic address. */
+
+ comp_alias_ddrs.create (may_alias_ddrs.length ());
+
+ /* First, we collect all data ref pairs for aliasing checks. */
+ FOR_EACH_VEC_ELT (may_alias_ddrs, i, ddr)
{
- bool found;
- ddr_p ddr_i;
+ struct data_reference *dr_a, *dr_b;
+ gimple dr_group_first_a, dr_group_first_b;
+ tree segment_length_a, segment_length_b;
+ gimple stmt_a, stmt_b;
+
+ dr_a = DDR_A (ddr);
+ stmt_a = DR_STMT (DDR_A (ddr));
+ dr_group_first_a = GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt_a));
+ if (dr_group_first_a)
+ {
+ stmt_a = dr_group_first_a;
+ dr_a = STMT_VINFO_DATA_REF (vinfo_for_stmt (stmt_a));
+ }
- ddr_i = ddrs[i];
- found = false;
+ dr_b = DDR_B (ddr);
+ stmt_b = DR_STMT (DDR_B (ddr));
+ dr_group_first_b = GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt_b));
+ if (dr_group_first_b)
+ {
+ stmt_b = dr_group_first_b;
+ dr_b = STMT_VINFO_DATA_REF (vinfo_for_stmt (stmt_b));
+ }
- for (j = 0; j < i; j++)
- {
- ddr_p ddr_j = ddrs[j];
+ if (!operand_equal_p (DR_STEP (dr_a), DR_STEP (dr_b), 0))
+ length_factor = scalar_loop_iters;
+ else
+ length_factor = size_int (vect_factor);
+ segment_length_a = vect_vfa_segment_size (dr_a, length_factor);
+ segment_length_b = vect_vfa_segment_size (dr_b, length_factor);
+
+ dr_addr_with_seg_len_pair_t dr_with_seg_len_pair
+ (dr_addr_with_seg_len
+ (dr_a, DR_BASE_ADDRESS (dr_a),
+ size_binop (PLUS_EXPR, DR_OFFSET (dr_a), DR_INIT (dr_a)),
+ segment_length_a),
+ dr_addr_with_seg_len
+ (dr_b, DR_BASE_ADDRESS (dr_b),
+ size_binop (PLUS_EXPR, DR_OFFSET (dr_b), DR_INIT (dr_b)),
+ segment_length_b));
+
+ if (compare_tree (dr_with_seg_len_pair.first.basic_addr,
+ dr_with_seg_len_pair.second.basic_addr) > 0)
+ swap (dr_with_seg_len_pair.first, dr_with_seg_len_pair.second);
+
+ comp_alias_ddrs.safe_push (dr_with_seg_len_pair);
+ }
- if (vect_vfa_range_equal (ddr_i, ddr_j))
+ /* Second, we sort the collected data ref pairs so that we can scan
+ them once to combine all possible aliasing checks. */
+ comp_alias_ddrs.qsort (comp_dr_addr_with_seg_len_pair);
+
+ /* Third, we scan the sorted dr pairs and check if we can combine
+ alias checks of two neighbouring dr pairs. */
+ for (size_t i = 1; i < comp_alias_ddrs.length (); ++i)
+ {
+ /* Deal with two ddrs (dr_a1, dr_b1) and (dr_a2, dr_b2). */
+ dr_addr_with_seg_len *dr_a1 = &comp_alias_ddrs[i-1].first,
+ *dr_b1 = &comp_alias_ddrs[i-1].second,
+ *dr_a2 = &comp_alias_ddrs[i].first,
+ *dr_b2 = &comp_alias_ddrs[i].second;
+
+ /* Remove duplicate data ref pairs. */
+ if (*dr_a1 == *dr_a2 && *dr_b1 == *dr_b2)
+ {
+ if (dump_enabled_p ())
{
- if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_NOTE, vect_location,
- "found equal ranges ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM,
- DR_REF (DDR_A (ddr_i)));
- dump_printf (MSG_NOTE, ", ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM,
- DR_REF (DDR_B (ddr_i)));
- dump_printf (MSG_NOTE, " and ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM,
- DR_REF (DDR_A (ddr_j)));
- dump_printf (MSG_NOTE, ", ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM,
- DR_REF (DDR_B (ddr_j)));
- dump_printf (MSG_NOTE, "\n");
- }
- found = true;
- break;
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "found equal ranges ");
+ dump_generic_expr (MSG_NOTE, TDF_SLIM,
+ DR_REF (dr_a1->dr));
+ dump_printf (MSG_NOTE, ", ");
+ dump_generic_expr (MSG_NOTE, TDF_SLIM,
+ DR_REF (dr_b1->dr));
+ dump_printf (MSG_NOTE, " and ");
+ dump_generic_expr (MSG_NOTE, TDF_SLIM,
+ DR_REF (dr_a2->dr));
+ dump_printf (MSG_NOTE, ", ");
+ dump_generic_expr (MSG_NOTE, TDF_SLIM,
+ DR_REF (dr_b2->dr));
+ dump_printf (MSG_NOTE, "\n");
}
+
+ comp_alias_ddrs.ordered_remove (i--);
+ continue;
}
- if (found)
- {
- ddrs.ordered_remove (i);
- continue;
- }
- i++;
+ if (*dr_a1 == *dr_a2 || *dr_b1 == *dr_b2)
+ {
+ /* We consider the case that DR_B1 and DR_B2 are same memrefs,
+ and DR_A1 and DR_A2 are two consecutive memrefs. */
+ if (*dr_a1 == *dr_a2)
+ {
+ swap (dr_a1, dr_b1);
+ swap (dr_a2, dr_b2);
+ }
+
+ if (!operand_equal_p (dr_a1->basic_addr, dr_a2->basic_addr, 0)
+ || !host_integerp (dr_a1->offset, 0)
+ || !host_integerp (dr_a2->offset, 0))
+ continue;
+
+ HOST_WIDE_INT diff = TREE_INT_CST_LOW (dr_a2->offset) -
+ TREE_INT_CST_LOW (dr_a1->offset);
+
+
+ /* Now we check if the following condition is satisfied:
+
+ DIFF - SEGMENT_LENGTH_A < SEGMENT_LENGTH_B
+
+ where DIFF = DR_A2->OFFSET - DR_A1->OFFSET. However,
+ SEGMENT_LENGTH_A or SEGMENT_LENGTH_B may not be constant so we
+ have to make a best estimation. We can get the minimum value
+ of SEGMENT_LENGTH_B as a constant, represented by MIN_SEG_LEN_B,
+ then either of the following two conditions can guarantee the
+ one above:
+
+ 1: DIFF <= MIN_SEG_LEN_B
+ 2: DIFF - SEGMENT_LENGTH_A < MIN_SEG_LEN_B
+
+ */
+
+ HOST_WIDE_INT
+ min_seg_len_b = (TREE_CODE (dr_b1->seg_len) == INTEGER_CST) ?
+ TREE_INT_CST_LOW (dr_b1->seg_len) :
+ vect_factor;
+
+ if (diff <= min_seg_len_b
+ || (TREE_CODE (dr_a1->seg_len) == INTEGER_CST
+ && diff - (HOST_WIDE_INT) TREE_INT_CST_LOW (dr_a1->seg_len) <
+ min_seg_len_b))
+ {
+ dr_a1->seg_len = size_binop (PLUS_EXPR,
+ dr_a2->seg_len, size_int (diff));
+ comp_alias_ddrs.ordered_remove (i--);
+ }
+ }
}
- if (ddrs.length () >
- (unsigned) PARAM_VALUE (PARAM_VECT_MAX_VERSION_FOR_ALIAS_CHECKS))
+ if ((int) comp_alias_ddrs.length () >
+ PARAM_VALUE (PARAM_VECT_MAX_VERSION_FOR_ALIAS_CHECKS))
{
if (dump_enabled_p ())
{
@@ -2696,8 +2941,6 @@ vect_prune_runtime_alias_test_list (loop_vec_info loop_vinfo)
"generated checks exceeded.\n");
}
- LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo).truncate (0);
-
return false;
}
@@ -3732,7 +3975,7 @@ vect_create_data_ref_ptr (gimple stmt, tree aggr_type, struct loop *at_loop,
tree dr_base_type = TREE_TYPE (DR_BASE_OBJECT (dr));
dump_printf_loc (MSG_NOTE, vect_location,
"create %s-pointer variable to type: ",
- tree_code_name[(int) TREE_CODE (aggr_type)]);
+ get_tree_code_name (TREE_CODE (aggr_type)));
dump_generic_expr (MSG_NOTE, TDF_SLIM, aggr_type);
if (TREE_CODE (dr_base_type) == ARRAY_TYPE)
dump_printf (MSG_NOTE, " vectorizing an array ref: ");
diff --git a/gcc/tree-vect-generic.c b/gcc/tree-vect-generic.c
index 4f67ca02467..1521b2ba2c5 100644
--- a/gcc/tree-vect-generic.c
+++ b/gcc/tree-vect-generic.c
@@ -23,8 +23,10 @@ along with GCC; see the file COPYING3. If not see
#include "tree.h"
#include "tm.h"
#include "langhooks.h"
-#include "tree-ssa.h"
#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-cfg.h"
+#include "tree-ssanames.h"
#include "tree-iterator.h"
#include "tree-pass.h"
#include "flags.h"
@@ -1477,8 +1479,8 @@ const pass_data pass_data_lower_vector =
class pass_lower_vector : public gimple_opt_pass
{
public:
- pass_lower_vector(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_lower_vector, ctxt)
+ pass_lower_vector (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_lower_vector, ctxt)
{}
/* opt_pass methods: */
@@ -1518,12 +1520,12 @@ const pass_data pass_data_lower_vector_ssa =
class pass_lower_vector_ssa : public gimple_opt_pass
{
public:
- pass_lower_vector_ssa(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_lower_vector_ssa, ctxt)
+ pass_lower_vector_ssa (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_lower_vector_ssa, ctxt)
{}
/* opt_pass methods: */
- opt_pass * clone () { return new pass_lower_vector_ssa (ctxt_); }
+ opt_pass * clone () { return new pass_lower_vector_ssa (m_ctxt); }
unsigned int execute () { return expand_vector_operations (); }
}; // class pass_lower_vector_ssa
diff --git a/gcc/tree-vect-loop-manip.c b/gcc/tree-vect-loop-manip.c
index bd77473e9a3..fb34664960e 100644
--- a/gcc/tree-vect-loop-manip.c
+++ b/gcc/tree-vect-loop-manip.c
@@ -28,6 +28,14 @@ along with GCC; see the file COPYING3. If not see
#include "tree.h"
#include "basic-block.h"
#include "gimple-pretty-print.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-cfg.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
+#include "tree-ssa-loop-manip.h"
+#include "tree-into-ssa.h"
#include "tree-ssa.h"
#include "tree-pass.h"
#include "cfgloop.h"
@@ -107,7 +115,7 @@ typedef struct
with a PHI DEF that would soon become non-dominant, and when we got
to the suitable one, it wouldn't have anything to substitute any
more. */
-static vec<adjust_info, va_stack> adjust_vec;
+static vec<adjust_info, va_heap> adjust_vec;
/* Adjust any debug stmts that referenced AI->from values to use the
loop-closed AI->to, if the references are dominated by AI->bb and
@@ -923,10 +931,10 @@ set_prologue_iterations (basic_block bb_before_first_loop,
unshare_expr (LOOP_VINFO_NITERS_UNCHANGED (loop_vec_info_for_loop (loop)));
e = single_pred_edge (bb_before_first_loop);
- cond_bb = split_edge(e);
+ cond_bb = split_edge (e);
e = single_pred_edge (bb_before_first_loop);
- then_bb = split_edge(e);
+ then_bb = split_edge (e);
set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
e_false = make_single_succ_edge (cond_bb, bb_before_first_loop,
@@ -1125,7 +1133,7 @@ slpeel_tree_peel_loop_to_edge (struct loop *loop,
if (MAY_HAVE_DEBUG_STMTS)
{
gcc_assert (!adjust_vec.exists ());
- vec_stack_alloc (adjust_info, adjust_vec, 32);
+ adjust_vec.create (32);
}
if (e == exit_e)
@@ -1429,7 +1437,7 @@ vect_build_loop_niters (loop_vec_info loop_vinfo, gimple_seq seq)
and places them at the loop preheader edge or in COND_EXPR_STMT_LIST
if that is non-NULL. */
-static void
+void
vect_generate_tmps_on_preheader (loop_vec_info loop_vinfo,
tree *ni_name_ptr,
tree *ratio_mult_vf_name_ptr,
@@ -2211,44 +2219,6 @@ vect_create_cond_for_align_checks (loop_vec_info loop_vinfo,
*cond_expr = part_cond_expr;
}
-
-/* Function vect_vfa_segment_size.
-
- Create an expression that computes the size of segment
- that will be accessed for a data reference. The functions takes into
- account that realignment loads may access one more vector.
-
- Input:
- DR: The data reference.
- LENGTH_FACTOR: segment length to consider.
-
- Return an expression whose value is the size of segment which will be
- accessed by DR. */
-
-static tree
-vect_vfa_segment_size (struct data_reference *dr, tree length_factor)
-{
- tree segment_length;
-
- if (integer_zerop (DR_STEP (dr)))
- segment_length = TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dr)));
- else
- segment_length = size_binop (MULT_EXPR,
- fold_convert (sizetype, DR_STEP (dr)),
- fold_convert (sizetype, length_factor));
-
- if (vect_supportable_dr_alignment (dr, false)
- == dr_explicit_realign_optimized)
- {
- tree vector_size = TYPE_SIZE_UNIT
- (STMT_VINFO_VECTYPE (vinfo_for_stmt (DR_STMT (dr))));
-
- segment_length = size_binop (PLUS_EXPR, segment_length, vector_size);
- }
- return segment_length;
-}
-
-
/* Function vect_create_cond_for_alias_checks.
Create a conditional expression that represents the run-time checks for
@@ -2257,28 +2227,24 @@ vect_vfa_segment_size (struct data_reference *dr, tree length_factor)
Input:
COND_EXPR - input conditional expression. New conditions will be chained
- with logical AND operation.
+ with logical AND operation. If it is NULL, then the function
+ is used to return the number of alias checks.
LOOP_VINFO - field LOOP_VINFO_MAY_ALIAS_STMTS contains the list of ddrs
to be checked.
Output:
COND_EXPR - conditional expression.
- The returned value is the conditional expression to be used in the if
+ The returned COND_EXPR is the conditional expression to be used in the if
statement that controls which version of the loop gets executed at runtime.
*/
-static void
+void
vect_create_cond_for_alias_checks (loop_vec_info loop_vinfo, tree * cond_expr)
{
- vec<ddr_p> may_alias_ddrs =
- LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo);
- int vect_factor = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
- tree scalar_loop_iters = LOOP_VINFO_NITERS (loop_vinfo);
-
- ddr_p ddr;
- unsigned int i;
- tree part_cond_expr, length_factor;
+ vec<dr_addr_with_seg_len_pair_t> comp_alias_ddrs =
+ LOOP_VINFO_COMP_ALIAS_DDRS (loop_vinfo);
+ tree part_cond_expr;
/* Create expression
((store_ptr_0 + store_segment_length_0) <= load_ptr_0)
@@ -2289,70 +2255,39 @@ vect_create_cond_for_alias_checks (loop_vec_info loop_vinfo, tree * cond_expr)
((store_ptr_n + store_segment_length_n) <= load_ptr_n)
|| (load_ptr_n + load_segment_length_n) <= store_ptr_n)) */
- if (may_alias_ddrs.is_empty ())
+ if (comp_alias_ddrs.is_empty ())
return;
- FOR_EACH_VEC_ELT (may_alias_ddrs, i, ddr)
+ for (size_t i = 0, s = comp_alias_ddrs.length (); i < s; ++i)
{
- struct data_reference *dr_a, *dr_b;
- gimple dr_group_first_a, dr_group_first_b;
- tree addr_base_a, addr_base_b;
- tree segment_length_a, segment_length_b;
- gimple stmt_a, stmt_b;
- tree seg_a_min, seg_a_max, seg_b_min, seg_b_max;
-
- dr_a = DDR_A (ddr);
- stmt_a = DR_STMT (DDR_A (ddr));
- dr_group_first_a = GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt_a));
- if (dr_group_first_a)
- {
- stmt_a = dr_group_first_a;
- dr_a = STMT_VINFO_DATA_REF (vinfo_for_stmt (stmt_a));
- }
-
- dr_b = DDR_B (ddr);
- stmt_b = DR_STMT (DDR_B (ddr));
- dr_group_first_b = GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt_b));
- if (dr_group_first_b)
- {
- stmt_b = dr_group_first_b;
- dr_b = STMT_VINFO_DATA_REF (vinfo_for_stmt (stmt_b));
- }
+ const dr_addr_with_seg_len& dr_a = comp_alias_ddrs[i].first;
+ const dr_addr_with_seg_len& dr_b = comp_alias_ddrs[i].second;
+ tree segment_length_a = dr_a.seg_len;
+ tree segment_length_b = dr_b.seg_len;
- addr_base_a
- = fold_build_pointer_plus (DR_BASE_ADDRESS (dr_a),
- size_binop (PLUS_EXPR, DR_OFFSET (dr_a),
- DR_INIT (dr_a)));
- addr_base_b
- = fold_build_pointer_plus (DR_BASE_ADDRESS (dr_b),
- size_binop (PLUS_EXPR, DR_OFFSET (dr_b),
- DR_INIT (dr_b)));
-
- if (!operand_equal_p (DR_STEP (dr_a), DR_STEP (dr_b), 0))
- length_factor = scalar_loop_iters;
- else
- length_factor = size_int (vect_factor);
- segment_length_a = vect_vfa_segment_size (dr_a, length_factor);
- segment_length_b = vect_vfa_segment_size (dr_b, length_factor);
+ tree addr_base_a
+ = fold_build_pointer_plus (dr_a.basic_addr, dr_a.offset);
+ tree addr_base_b
+ = fold_build_pointer_plus (dr_b.basic_addr, dr_b.offset);
if (dump_enabled_p ())
{
dump_printf_loc (MSG_NOTE, vect_location,
- "create runtime check for data references ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dr_a));
+ "create runtime check for data references ");
+ dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dr_a.dr));
dump_printf (MSG_NOTE, " and ");
- dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dr_b));
- dump_printf (MSG_NOTE, "\n");
+ dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dr_b.dr));
+ dump_printf (MSG_NOTE, "\n");
}
- seg_a_min = addr_base_a;
- seg_a_max = fold_build_pointer_plus (addr_base_a, segment_length_a);
- if (tree_int_cst_compare (DR_STEP (dr_a), size_zero_node) < 0)
+ tree seg_a_min = addr_base_a;
+ tree seg_a_max = fold_build_pointer_plus (addr_base_a, segment_length_a);
+ if (tree_int_cst_compare (DR_STEP (dr_a.dr), size_zero_node) < 0)
seg_a_min = seg_a_max, seg_a_max = addr_base_a;
- seg_b_min = addr_base_b;
- seg_b_max = fold_build_pointer_plus (addr_base_b, segment_length_b);
- if (tree_int_cst_compare (DR_STEP (dr_b), size_zero_node) < 0)
+ tree seg_b_min = addr_base_b;
+ tree seg_b_max = fold_build_pointer_plus (addr_base_b, segment_length_b);
+ if (tree_int_cst_compare (DR_STEP (dr_b.dr), size_zero_node) < 0)
seg_b_min = seg_b_max, seg_b_max = addr_base_b;
part_cond_expr =
@@ -2370,7 +2305,9 @@ vect_create_cond_for_alias_checks (loop_vec_info loop_vinfo, tree * cond_expr)
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location,
"created %u versioning for alias checks.\n",
- may_alias_ddrs.length ());
+ comp_alias_ddrs.length ());
+
+ comp_alias_ddrs.release ();
}
@@ -2449,7 +2386,7 @@ vect_loop_versioning (loop_vec_info loop_vinfo,
"alignment\n");
}
- free_original_copy_tables();
+ free_original_copy_tables ();
/* Loop versioning violates an assumption we try to maintain during
vectorization - that the loop exit block has a single predecessor.
@@ -2477,6 +2414,73 @@ vect_loop_versioning (loop_vec_info loop_vinfo,
adjust_phi_and_debug_stmts (orig_phi, e, PHI_RESULT (new_phi));
}
+
+ /* Extract load statements on memrefs with zero-stride accesses. */
+
+ if (LOOP_REQUIRES_VERSIONING_FOR_ALIAS (loop_vinfo))
+ {
+ /* In the loop body, we iterate each statement to check if it is a load.
+ Then we check the DR_STEP of the data reference. If DR_STEP is zero,
+ then we will hoist the load statement to the loop preheader. */
+
+ basic_block *bbs = LOOP_VINFO_BBS (loop_vinfo);
+ int nbbs = loop->num_nodes;
+
+ for (int i = 0; i < nbbs; ++i)
+ {
+ for (gimple_stmt_iterator si = gsi_start_bb (bbs[i]);
+ !gsi_end_p (si);)
+ {
+ gimple stmt = gsi_stmt (si);
+ stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
+ struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
+
+ if (is_gimple_assign (stmt)
+ && (!dr
+ || (DR_IS_READ (dr) && integer_zerop (DR_STEP (dr)))))
+ {
+ bool hoist = true;
+ ssa_op_iter iter;
+ tree var;
+
+ /* We hoist a statement if all SSA uses in it are defined
+ outside of the loop. */
+ FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, SSA_OP_USE)
+ {
+ gimple def = SSA_NAME_DEF_STMT (var);
+ if (!gimple_nop_p (def)
+ && flow_bb_inside_loop_p (loop, gimple_bb (def)))
+ {
+ hoist = false;
+ break;
+ }
+ }
+
+ if (hoist)
+ {
+ if (dr)
+ gimple_set_vuse (stmt, NULL);
+
+ gsi_remove (&si, false);
+ gsi_insert_on_edge_immediate (loop_preheader_edge (loop),
+ stmt);
+
+ if (dump_enabled_p ())
+ {
+ dump_printf_loc
+ (MSG_NOTE, vect_location,
+ "hoisting out of the vectorized loop: ");
+ dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt, 0);
+ dump_printf (MSG_NOTE, "\n");
+ }
+ continue;
+ }
+ }
+ gsi_next (&si);
+ }
+ }
+ }
+
/* End loop-exit-fixes after versioning. */
if (cond_expr_stmt_list)
diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c
index 2871ba1ce75..6e71eea2436 100644
--- a/gcc/tree-vect-loop.c
+++ b/gcc/tree-vect-loop.c
@@ -28,7 +28,14 @@ along with GCC; see the file COPYING3. If not see
#include "tree.h"
#include "basic-block.h"
#include "gimple-pretty-print.h"
-#include "tree-ssa.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
+#include "tree-ssa-loop-ivopts.h"
+#include "tree-ssa-loop-manip.h"
+#include "tree-ssa-loop-niter.h"
#include "tree-pass.h"
#include "cfgloop.h"
#include "expr.h"
@@ -584,8 +591,7 @@ vect_analyze_scalar_cycles_1 (loop_vec_info loop_vinfo, struct loop *loop)
{
basic_block bb = loop->header;
tree init, step;
- vec<gimple> worklist;
- worklist.create (64);
+ stack_vec<gimple, 64> worklist;
gimple_stmt_iterator gsi;
bool double_reduc;
@@ -716,8 +722,6 @@ vect_analyze_scalar_cycles_1 (loop_vec_info loop_vinfo, struct loop *loop)
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
"Unknown def-use cycle pattern.\n");
}
-
- worklist.release ();
}
@@ -967,9 +971,9 @@ destroy_loop_vec_info (loop_vec_info loop_vinfo, bool clean_stmts)
|| code == POINTER_PLUS_EXPR
|| code == MULT_EXPR)
&& CONSTANT_CLASS_P (gimple_assign_rhs1 (stmt)))
- swap_tree_operands (stmt,
- gimple_assign_rhs1_ptr (stmt),
- gimple_assign_rhs2_ptr (stmt));
+ swap_ssa_operands (stmt,
+ gimple_assign_rhs1_ptr (stmt),
+ gimple_assign_rhs2_ptr (stmt));
}
/* Free stmt_vec_info. */
@@ -1579,9 +1583,9 @@ vect_analyze_loop_operations (loop_vec_info loop_vinfo, bool slp)
return false;
}
- if (!LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo)
- || LOOP_VINFO_INT_NITERS (loop_vinfo) % vectorization_factor != 0
- || LOOP_PEELING_FOR_ALIGNMENT (loop_vinfo))
+ if (LOOP_PEELING_FOR_ALIGNMENT (loop_vinfo)
+ || ((int) tree_ctz (LOOP_VINFO_NITERS (loop_vinfo))
+ < exact_log2 (vectorization_factor)))
{
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location, "epilog loop required.\n");
@@ -2056,9 +2060,9 @@ vect_is_slp_reduction (loop_vec_info loop_info, gimple phi, gimple first_stmt)
dump_printf (MSG_NOTE, "\n");
}
- swap_tree_operands (next_stmt,
- gimple_assign_rhs1_ptr (next_stmt),
- gimple_assign_rhs2_ptr (next_stmt));
+ swap_ssa_operands (next_stmt,
+ gimple_assign_rhs1_ptr (next_stmt),
+ gimple_assign_rhs2_ptr (next_stmt));
update_stmt (next_stmt);
if (CONSTANT_CLASS_P (gimple_assign_rhs1 (next_stmt)))
@@ -2091,6 +2095,13 @@ vect_is_slp_reduction (loop_vec_info loop_info, gimple phi, gimple first_stmt)
a3 = ...
a2 = operation (a3, a1)
+ or
+
+ a3 = ...
+ loop_header:
+ a1 = phi < a0, a2 >
+ a2 = operation (a3, a1)
+
such that:
1. operation is commutative and associative and it is safe to
change the order of the computation (if CHECK_REDUCTION is true)
@@ -2451,6 +2462,7 @@ vect_is_simple_reduction_1 (loop_vec_info loop_info, gimple phi,
if (def2 && def2 == phi
&& (code == COND_EXPR
|| !def1 || gimple_nop_p (def1)
+ || !flow_bb_inside_loop_p (loop, gimple_bb (def1))
|| (def1 && flow_bb_inside_loop_p (loop, gimple_bb (def1))
&& (is_gimple_assign (def1)
|| is_gimple_call (def1)
@@ -2469,6 +2481,7 @@ vect_is_simple_reduction_1 (loop_vec_info loop_info, gimple phi,
if (def1 && def1 == phi
&& (code == COND_EXPR
|| !def2 || gimple_nop_p (def2)
+ || !flow_bb_inside_loop_p (loop, gimple_bb (def2))
|| (def2 && flow_bb_inside_loop_p (loop, gimple_bb (def2))
&& (is_gimple_assign (def2)
|| is_gimple_call (def2)
@@ -2488,8 +2501,8 @@ vect_is_simple_reduction_1 (loop_vec_info loop_info, gimple phi,
report_vect_op (MSG_NOTE, def_stmt,
"detected reduction: need to swap operands: ");
- swap_tree_operands (def_stmt, gimple_assign_rhs1_ptr (def_stmt),
- gimple_assign_rhs2_ptr (def_stmt));
+ swap_ssa_operands (def_stmt, gimple_assign_rhs1_ptr (def_stmt),
+ gimple_assign_rhs2_ptr (def_stmt));
if (CONSTANT_CLASS_P (gimple_assign_rhs1 (def_stmt)))
LOOP_VINFO_OPERANDS_SWAPPED (loop_info) = true;
@@ -2680,7 +2693,7 @@ vect_estimate_min_profitable_iters (loop_vec_info loop_vinfo,
void *target_cost_data = LOOP_VINFO_TARGET_COST_DATA (loop_vinfo);
/* Cost model disabled. */
- if (!flag_vect_cost_model)
+ if (unlimited_cost_model ())
{
dump_printf_loc (MSG_NOTE, vect_location, "cost model disabled.\n");
*ret_min_profitable_niters = 0;
@@ -4314,7 +4327,6 @@ vect_finalize_reduction:
epilog_stmt = gimple_build_assign (new_dest, expr);
new_temp = make_ssa_name (new_dest, epilog_stmt);
gimple_assign_set_lhs (epilog_stmt, new_temp);
- SSA_NAME_DEF_STMT (new_temp) = epilog_stmt;
gsi_insert_before (&exit_gsi, epilog_stmt, GSI_SAME_STMT);
if (nested_in_vect_loop)
{
@@ -4411,7 +4423,8 @@ vect_finalize_reduction:
result. (The reduction result is expected to have two immediate uses -
one at the latch block, and one at the loop exit). */
FOR_EACH_IMM_USE_FAST (use_p, imm_iter, scalar_dest)
- if (!flow_bb_inside_loop_p (loop, gimple_bb (USE_STMT (use_p))))
+ if (!flow_bb_inside_loop_p (loop, gimple_bb (USE_STMT (use_p)))
+ && !is_gimple_debug (USE_STMT (use_p)))
phis.safe_push (USE_STMT (use_p));
/* While we expect to have found an exit_phi because of loop-closed-ssa
@@ -4541,7 +4554,10 @@ vect_finalize_reduction:
FOR_EACH_IMM_USE_FAST (use_p, imm_iter, scalar_dest)
{
if (!flow_bb_inside_loop_p (loop, gimple_bb (USE_STMT (use_p))))
- phis.safe_push (USE_STMT (use_p));
+ {
+ if (!is_gimple_debug (USE_STMT (use_p)))
+ phis.safe_push (USE_STMT (use_p));
+ }
else
{
if (double_reduc && gimple_code (USE_STMT (use_p)) == GIMPLE_PHI)
@@ -4551,7 +4567,8 @@ vect_finalize_reduction:
FOR_EACH_IMM_USE_FAST (phi_use_p, phi_imm_iter, phi_res)
{
if (!flow_bb_inside_loop_p (loop,
- gimple_bb (USE_STMT (phi_use_p))))
+ gimple_bb (USE_STMT (phi_use_p)))
+ && !is_gimple_debug (USE_STMT (phi_use_p)))
phis.safe_push (USE_STMT (phi_use_p));
}
}
@@ -5635,15 +5652,20 @@ vect_transform_loop (loop_vec_info loop_vinfo)
will remain scalar and will compute the remaining (n%VF) iterations.
(VF is the vectorization factor). */
- if (!LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo)
- || (LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo)
- && LOOP_VINFO_INT_NITERS (loop_vinfo) % vectorization_factor != 0)
- || LOOP_VINFO_PEELING_FOR_GAPS (loop_vinfo))
+ if ((int) tree_ctz (LOOP_VINFO_NITERS (loop_vinfo))
+ < exact_log2 (vectorization_factor)
+ || LOOP_VINFO_PEELING_FOR_GAPS (loop_vinfo))
vect_do_peeling_for_loop_bound (loop_vinfo, &ratio,
th, check_profitability);
- else
+ else if (LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo))
ratio = build_int_cst (TREE_TYPE (LOOP_VINFO_NITERS (loop_vinfo)),
LOOP_VINFO_INT_NITERS (loop_vinfo) / vectorization_factor);
+ else
+ {
+ tree ni_name, ratio_mult_vf;
+ vect_generate_tmps_on_preheader (loop_vinfo, &ni_name, &ratio_mult_vf,
+ &ratio, NULL);
+ }
/* 1) Make sure the loop header has exactly two entries
2) Make sure we have a preheader basic block. */
diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c
index 0a4e812fd82..099880488bc 100644
--- a/gcc/tree-vect-patterns.c
+++ b/gcc/tree-vect-patterns.c
@@ -27,7 +27,11 @@ along with GCC; see the file COPYING3. If not see
#include "target.h"
#include "basic-block.h"
#include "gimple-pretty-print.h"
-#include "tree-ssa.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
#include "cfgloop.h"
#include "expr.h"
#include "optabs.h"
@@ -2226,20 +2230,19 @@ vect_recog_divmod_pattern (vec<gimple> *stmts,
if (post_shift >= prec)
return NULL;
- /* t1 = oprnd1 h* ml; */
+ /* t1 = oprnd0 h* ml; */
t1 = vect_recog_temp_ssa_var (itype, NULL);
def_stmt
= gimple_build_assign_with_ops (MULT_HIGHPART_EXPR, t1, oprnd0,
build_int_cst (itype, ml));
- append_pattern_def_seq (stmt_vinfo, def_stmt);
if (add)
{
/* t2 = t1 + oprnd0; */
+ append_pattern_def_seq (stmt_vinfo, def_stmt);
t2 = vect_recog_temp_ssa_var (itype, NULL);
def_stmt
= gimple_build_assign_with_ops (PLUS_EXPR, t2, t1, oprnd0);
- append_pattern_def_seq (stmt_vinfo, def_stmt);
}
else
t2 = t1;
@@ -2247,27 +2250,57 @@ vect_recog_divmod_pattern (vec<gimple> *stmts,
if (post_shift)
{
/* t3 = t2 >> post_shift; */
+ append_pattern_def_seq (stmt_vinfo, def_stmt);
t3 = vect_recog_temp_ssa_var (itype, NULL);
def_stmt
= gimple_build_assign_with_ops (RSHIFT_EXPR, t3, t2,
build_int_cst (itype, post_shift));
- append_pattern_def_seq (stmt_vinfo, def_stmt);
}
else
t3 = t2;
- /* t4 = oprnd0 >> (prec - 1); */
- t4 = vect_recog_temp_ssa_var (itype, NULL);
- def_stmt
- = gimple_build_assign_with_ops (RSHIFT_EXPR, t4, oprnd0,
- build_int_cst (itype, prec - 1));
- append_pattern_def_seq (stmt_vinfo, def_stmt);
+ double_int oprnd0_min, oprnd0_max;
+ int msb = 1;
+ if (get_range_info (oprnd0, &oprnd0_min, &oprnd0_max) == VR_RANGE)
+ {
+ if (!oprnd0_min.is_negative ())
+ msb = 0;
+ else if (oprnd0_max.is_negative ())
+ msb = -1;
+ }
- /* q = t3 - t4; or q = t4 - t3; */
- q = vect_recog_temp_ssa_var (itype, NULL);
- pattern_stmt
- = gimple_build_assign_with_ops (MINUS_EXPR, q, d < 0 ? t4 : t3,
- d < 0 ? t3 : t4);
+ if (msb == 0 && d >= 0)
+ {
+ /* q = t3; */
+ q = t3;
+ pattern_stmt = def_stmt;
+ }
+ else
+ {
+ /* t4 = oprnd0 >> (prec - 1);
+ or if we know from VRP that oprnd0 >= 0
+ t4 = 0;
+ or if we know from VRP that oprnd0 < 0
+ t4 = -1; */
+ append_pattern_def_seq (stmt_vinfo, def_stmt);
+ t4 = vect_recog_temp_ssa_var (itype, NULL);
+ if (msb != 1)
+ def_stmt
+ = gimple_build_assign_with_ops (INTEGER_CST,
+ t4, build_int_cst (itype, msb),
+ NULL_TREE);
+ else
+ def_stmt
+ = gimple_build_assign_with_ops (RSHIFT_EXPR, t4, oprnd0,
+ build_int_cst (itype, prec - 1));
+ append_pattern_def_seq (stmt_vinfo, def_stmt);
+
+ /* q = t3 - t4; or q = t4 - t3; */
+ q = vect_recog_temp_ssa_var (itype, NULL);
+ pattern_stmt
+ = gimple_build_assign_with_ops (MINUS_EXPR, q, d < 0 ? t4 : t3,
+ d < 0 ? t3 : t4);
+ }
}
if (rhs_code == TRUNC_MOD_EXPR)
@@ -3174,8 +3207,7 @@ vect_pattern_recog (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo)
gimple_stmt_iterator si;
unsigned int i, j;
vect_recog_func_ptr vect_recog_func;
- vec<gimple> stmts_to_replace;
- stmts_to_replace.create (1);
+ stack_vec<gimple, 1> stmts_to_replace;
gimple stmt;
if (dump_enabled_p ())
@@ -3215,6 +3247,4 @@ vect_pattern_recog (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo)
}
}
}
-
- stmts_to_replace.release ();
}
diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c
index 8ed0fc58c59..825f73a429a 100644
--- a/gcc/tree-vect-slp.c
+++ b/gcc/tree-vect-slp.c
@@ -29,7 +29,11 @@ along with GCC; see the file COPYING3. If not see
#include "target.h"
#include "basic-block.h"
#include "gimple-pretty-print.h"
-#include "tree-ssa.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
#include "tree-pass.h"
#include "cfgloop.h"
#include "expr.h"
@@ -1930,7 +1934,7 @@ vect_slp_analyze_operations (bb_vec_info bb_vinfo)
static unsigned
vect_bb_slp_scalar_cost (basic_block bb,
- slp_tree node, vec<bool, va_stack> life)
+ slp_tree node, vec<bool, va_heap> *life)
{
unsigned scalar_cost = 0;
unsigned i;
@@ -1944,7 +1948,7 @@ vect_bb_slp_scalar_cost (basic_block bb,
def_operand_p def_p;
stmt_vec_info stmt_info;
- if (life[i])
+ if ((*life)[i])
continue;
/* If there is a non-vectorized use of the defs then the scalar
@@ -1961,11 +1965,11 @@ vect_bb_slp_scalar_cost (basic_block bb,
|| gimple_bb (use_stmt) != bb
|| !STMT_VINFO_VECTORIZABLE (vinfo_for_stmt (use_stmt)))
{
- life[i] = true;
+ (*life)[i] = true;
BREAK_FROM_IMM_USE_STMT (use_iter);
}
}
- if (life[i])
+ if ((*life)[i])
continue;
stmt_info = vinfo_for_stmt (stmt);
@@ -2019,13 +2023,11 @@ vect_bb_vectorization_profitable_p (bb_vec_info bb_vinfo)
/* Calculate scalar cost. */
FOR_EACH_VEC_ELT (slp_instances, i, instance)
{
- vec<bool, va_stack> life;
- vec_stack_alloc (bool, life, SLP_INSTANCE_GROUP_SIZE (instance));
- life.quick_grow_cleared (SLP_INSTANCE_GROUP_SIZE (instance));
+ stack_vec<bool, 20> life;
+ life.safe_grow_cleared (SLP_INSTANCE_GROUP_SIZE (instance));
scalar_cost += vect_bb_slp_scalar_cost (BB_VINFO_BB (bb_vinfo),
SLP_INSTANCE_TREE (instance),
- life);
- life.release ();
+ &life);
}
/* Complete the target-specific cost calculation. */
@@ -2168,7 +2170,7 @@ vect_slp_analyze_bb_1 (basic_block bb)
}
/* Cost model: check if the vectorization is worthwhile. */
- if (flag_vect_cost_model
+ if (!unlimited_cost_model ()
&& !vect_bb_vectorization_profitable_p (bb_vinfo))
{
if (dump_enabled_p ())
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index fcea4d0654b..5a2bbb51608 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -29,7 +29,13 @@ along with GCC; see the file COPYING3. If not see
#include "target.h"
#include "basic-block.h"
#include "gimple-pretty-print.h"
-#include "tree-ssa.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-cfg.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
+#include "tree-ssa-loop-manip.h"
#include "cfgloop.h"
#include "expr.h"
#include "recog.h" /* FIXME: for insn_data */
@@ -574,7 +580,6 @@ process_use (gimple stmt, tree use, loop_vec_info loop_vinfo, bool live_p,
bool
vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo)
{
- vec<gimple> worklist;
struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
basic_block *bbs = LOOP_VINFO_BBS (loop_vinfo);
unsigned int nbbs = loop->num_nodes;
@@ -592,7 +597,7 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo)
dump_printf_loc (MSG_NOTE, vect_location,
"=== vect_mark_stmts_to_be_vectorized ===\n");
- worklist.create (64);
+ stack_vec<gimple, 64> worklist;
/* 1. Init worklist. */
for (i = 0; i < nbbs; i++)
@@ -682,7 +687,6 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo)
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
"unsupported use of reduction.\n");
- worklist.release ();
return false;
}
@@ -698,7 +702,6 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo)
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
"unsupported use of nested cycle.\n");
- worklist.release ();
return false;
}
@@ -713,7 +716,6 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo)
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
"unsupported use of double reduction.\n");
- worklist.release ();
return false;
}
@@ -741,10 +743,7 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo)
live_p, relevant, &worklist, false)
|| !process_use (stmt, TREE_OPERAND (op, 1), loop_vinfo,
live_p, relevant, &worklist, false))
- {
- worklist.release ();
- return false;
- }
+ return false;
i = 2;
}
for (; i < gimple_num_ops (stmt); i++)
@@ -752,10 +751,7 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo)
op = gimple_op (stmt, i);
if (!process_use (stmt, op, loop_vinfo, live_p, relevant,
&worklist, false))
- {
- worklist.release ();
- return false;
- }
+ return false;
}
}
else if (is_gimple_call (stmt))
@@ -765,10 +761,7 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo)
tree arg = gimple_call_arg (stmt, i);
if (!process_use (stmt, arg, loop_vinfo, live_p, relevant,
&worklist, false))
- {
- worklist.release ();
- return false;
- }
+ return false;
}
}
}
@@ -778,10 +771,7 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo)
tree op = USE_FROM_PTR (use_p);
if (!process_use (stmt, op, loop_vinfo, live_p, relevant,
&worklist, false))
- {
- worklist.release ();
- return false;
- }
+ return false;
}
if (STMT_VINFO_GATHER_P (stmt_vinfo))
@@ -791,14 +781,10 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo)
gcc_assert (decl);
if (!process_use (stmt, off, loop_vinfo, live_p, relevant,
&worklist, true))
- {
- worklist.release ();
- return false;
- }
+ return false;
}
} /* while worklist */
- worklist.release ();
return true;
}
@@ -2118,7 +2104,6 @@ vectorizable_call (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
set_vinfo_for_stmt (stmt, NULL);
STMT_VINFO_STMT (stmt_info) = new_stmt;
gsi_replace (gsi, new_stmt, false);
- SSA_NAME_DEF_STMT (gimple_assign_lhs (new_stmt)) = new_stmt;
return true;
}
@@ -2675,7 +2660,7 @@ vectorizable_conversion (gimple stmt, gimple_stmt_iterator *gsi,
{
if (modifier == WIDEN)
{
- vec_oprnds0.create (multi_step_cvt ? vect_pow2(multi_step_cvt) : 1);
+ vec_oprnds0.create (multi_step_cvt ? vect_pow2 (multi_step_cvt) : 1);
if (op_type == binary_op)
vec_oprnds1.create (1);
}
@@ -4790,7 +4775,7 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
(unshare_expr (DR_BASE_ADDRESS (dr)),
size_binop (PLUS_EXPR,
convert_to_ptrofftype (unshare_expr (DR_OFFSET (dr))),
- convert_to_ptrofftype (DR_INIT(dr))));
+ convert_to_ptrofftype (DR_INIT (dr))));
stride_step = fold_convert (sizetype, unshare_expr (DR_STEP (dr)));
/* For a load with loop-invariant (but other than power-of-2)
@@ -5546,11 +5531,9 @@ vectorizable_condition (gimple stmt, gimple_stmt_iterator *gsi,
{
if (slp_node)
{
- vec<tree> ops;
- ops.create (4);
- vec<vec<tree> > vec_defs;
+ stack_vec<tree, 4> ops;
+ stack_vec<vec<tree>, 4> vec_defs;
- vec_defs.create (4);
ops.safe_push (TREE_OPERAND (cond_expr, 0));
ops.safe_push (TREE_OPERAND (cond_expr, 1));
ops.safe_push (then_clause);
diff --git a/gcc/tree-vectorizer.c b/gcc/tree-vectorizer.c
index 638c19b72ee..8e3190fa2c1 100644
--- a/gcc/tree-vectorizer.c
+++ b/gcc/tree-vectorizer.c
@@ -62,7 +62,12 @@ along with GCC; see the file COPYING3. If not see
#include "ggc.h"
#include "tree.h"
#include "tree-pretty-print.h"
-#include "tree-ssa.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "cgraph.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssa-loop-manip.h"
#include "cfgloop.h"
#include "tree-vectorizer.h"
#include "tree-pass.h"
@@ -111,7 +116,8 @@ simduid_to_vf::equal (const value_type *p1, const value_type *p2)
D.1737[_7] = stuff;
- This hash maps from the simduid.0 to OMP simd array (D.1737[]). */
+ This hash maps from the OMP simd array (D.1737[]) to DECL_UID of
+ simduid.0. */
struct simd_array_to_simduid : typed_free_remove<simd_array_to_simduid>
{
@@ -510,8 +516,8 @@ const pass_data pass_data_slp_vectorize =
class pass_slp_vectorize : public gimple_opt_pass
{
public:
- pass_slp_vectorize(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_slp_vectorize, ctxt)
+ pass_slp_vectorize (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_slp_vectorize, ctxt)
{}
/* opt_pass methods: */
@@ -546,11 +552,11 @@ increase_alignment (void)
/* Increase the alignment of all global arrays for vectorization. */
FOR_EACH_DEFINED_VARIABLE (vnode)
{
- tree vectype, decl = vnode->symbol.decl;
+ tree vectype, decl = vnode->decl;
tree t;
unsigned int alignment;
- t = TREE_TYPE(decl);
+ t = TREE_TYPE (decl);
if (TREE_CODE (t) != ARRAY_TYPE)
continue;
vectype = get_vectype_for_scalar_type (strip_array_types (t));
@@ -600,8 +606,8 @@ const pass_data pass_data_ipa_increase_alignment =
class pass_ipa_increase_alignment : public simple_ipa_opt_pass
{
public:
- pass_ipa_increase_alignment(gcc::context *ctxt)
- : simple_ipa_opt_pass(pass_data_ipa_increase_alignment, ctxt)
+ pass_ipa_increase_alignment (gcc::context *ctxt)
+ : simple_ipa_opt_pass (pass_data_ipa_increase_alignment, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
index 9c7753e2eaf..bbd50e1d993 100644
--- a/gcc/tree-vectorizer.h
+++ b/gcc/tree-vectorizer.h
@@ -27,7 +27,7 @@ along with GCC; see the file COPYING3. If not see
typedef source_location LOC;
#define UNKNOWN_LOC UNKNOWN_LOCATION
-#define EXPR_LOC(e) EXPR_LOCATION(e)
+#define EXPR_LOC(e) EXPR_LOCATION (e)
#define LOC_FILE(l) LOCATION_FILE (l)
#define LOC_LINE(l) LOCATION_LINE (l)
@@ -175,6 +175,36 @@ typedef struct _slp_oprnd_info
+/* This struct is used to store the information of a data reference,
+ including the data ref itself, its basic address, the access offset
+ and the segment length for aliasing checks. This is used to generate
+ alias checks. */
+
+struct dr_addr_with_seg_len
+{
+ dr_addr_with_seg_len (data_reference* d, tree addr, tree off, tree len)
+ : dr (d), basic_addr (addr), offset (off), seg_len (len) {}
+
+ data_reference *dr;
+ tree basic_addr;
+ tree offset;
+ tree seg_len;
+};
+
+/* This struct contains two dr_addr_with_seg_len objects with aliasing data
+ refs. Two comparisons are generated from them. */
+
+struct dr_addr_with_seg_len_pair_t
+{
+ dr_addr_with_seg_len_pair_t (const dr_addr_with_seg_len& d1,
+ const dr_addr_with_seg_len& d2)
+ : first (d1), second (d2) {}
+
+ dr_addr_with_seg_len first;
+ dr_addr_with_seg_len second;
+};
+
+
typedef struct _vect_peel_info
{
int npeel;
@@ -274,6 +304,10 @@ typedef struct _loop_vec_info {
for a run-time aliasing check. */
vec<ddr_p> may_alias_ddrs;
+ /* Data Dependence Relations defining address ranges together with segment
+ lengths from which the run-time aliasing check is built. */
+ vec<dr_addr_with_seg_len_pair_t> comp_alias_ddrs;
+
/* Statements in the loop that have data references that are candidates for a
runtime (loop versioning) misalignment check. */
vec<gimple> may_misalign_stmts;
@@ -336,6 +370,7 @@ typedef struct _loop_vec_info {
#define LOOP_VINFO_MAY_MISALIGN_STMTS(L) (L)->may_misalign_stmts
#define LOOP_VINFO_LOC(L) (L)->loop_line_number
#define LOOP_VINFO_MAY_ALIAS_DDRS(L) (L)->may_alias_ddrs
+#define LOOP_VINFO_COMP_ALIAS_DDRS(L) (L)->comp_alias_ddrs
#define LOOP_VINFO_GROUPED_STORES(L) (L)->grouped_stores
#define LOOP_VINFO_SLP_INSTANCES(L) (L)->slp_instances
#define LOOP_VINFO_SLP_UNROLLING_FACTOR(L) (L)->slp_unrolling_factor
@@ -356,7 +391,7 @@ typedef struct _loop_vec_info {
&& TREE_INT_CST_LOW ((n)) > 0)
#define LOOP_VINFO_NITERS_KNOWN_P(L) \
-NITERS_KNOWN_P((L)->num_iters)
+NITERS_KNOWN_P ((L)->num_iters)
static inline loop_vec_info
loop_vec_info_for_loop (struct loop *loop)
@@ -880,6 +915,14 @@ known_alignment_for_access_p (struct data_reference *data_ref_info)
return (DR_MISALIGNMENT (data_ref_info) != -1);
}
+
+/* Return true if the vect cost model is unlimited. */
+static inline bool
+unlimited_cost_model ()
+{
+ return flag_vect_cost_model == VECT_COST_MODEL_UNLIMITED;
+}
+
/* Source location */
extern LOC vect_location;
@@ -891,7 +934,10 @@ extern LOC vect_location;
in tree-vect-loop-manip.c. */
extern void slpeel_make_loop_iterate_ntimes (struct loop *, tree);
extern bool slpeel_can_duplicate_loop_p (const struct loop *, const_edge);
+struct loop *slpeel_tree_duplicate_loop_to_edge_cfg (struct loop *, edge);
extern void vect_loop_versioning (loop_vec_info, unsigned int, bool);
+extern void vect_generate_tmps_on_preheader (loop_vec_info, tree *, tree *,
+ tree *, gimple_seq);
extern void vect_do_peeling_for_loop_bound (loop_vec_info, tree *,
unsigned int, bool);
extern void vect_do_peeling_for_alignment (loop_vec_info, unsigned int, bool);
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index ae27dc48a2f..8f8b5ebada7 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -26,6 +26,16 @@ along with GCC; see the file COPYING3. If not see
#include "flags.h"
#include "tree.h"
#include "basic-block.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-cfg.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
+#include "tree-ssa-loop-manip.h"
+#include "tree-ssa-loop-niter.h"
+#include "tree-ssa-loop.h"
+#include "tree-into-ssa.h"
#include "tree-ssa.h"
#include "tree-pass.h"
#include "tree-dump.h"
@@ -36,14 +46,12 @@ along with GCC; see the file COPYING3. If not see
#include "tree-scalar-evolution.h"
#include "tree-ssa-propagate.h"
#include "tree-chrec.h"
-#include "gimple-fold.h"
+#include "tree-ssa-threadupdate.h"
#include "expr.h"
#include "optabs.h"
+#include "tree-ssa-threadedge.h"
-/* Type of value ranges. See value_range_d for a description of these
- types. */
-enum value_range_type { VR_UNDEFINED, VR_RANGE, VR_ANTI_RANGE, VR_VARYING };
/* Range of values that can be associated with an SSA_NAME after VRP
has executed. */
@@ -884,8 +892,8 @@ static inline bool
range_int_cst_singleton_p (value_range_t *vr)
{
return (range_int_cst_p (vr)
- && !TREE_OVERFLOW (vr->min)
- && !TREE_OVERFLOW (vr->max)
+ && !is_overflow_infinity (vr->min)
+ && !is_overflow_infinity (vr->max)
&& tree_int_cst_equal (vr->min, vr->max));
}
@@ -1041,7 +1049,7 @@ gimple_assign_nonzero_warnv_p (gimple stmt, bool *strict_overflow_p)
}
}
-/* Return true if STMT is know to to compute a non-zero value.
+/* Return true if STMT is known to compute a non-zero value.
If the return value is based on the assumption that signed overflow is
undefined, set *STRICT_OVERFLOW_P to true; otherwise, don't change
*STRICT_OVERFLOW_P.*/
@@ -1054,7 +1062,19 @@ gimple_stmt_nonzero_warnv_p (gimple stmt, bool *strict_overflow_p)
case GIMPLE_ASSIGN:
return gimple_assign_nonzero_warnv_p (stmt, strict_overflow_p);
case GIMPLE_CALL:
- return gimple_alloca_call_p (stmt);
+ {
+ tree fndecl = gimple_call_fndecl (stmt);
+ if (!fndecl) return false;
+ if (flag_delete_null_pointer_checks && !flag_check_new
+ && DECL_IS_OPERATOR_NEW (fndecl)
+ && !TREE_NOTHROW (fndecl))
+ return true;
+ if (flag_delete_null_pointer_checks &&
+ lookup_attribute ("returns_nonnull",
+ TYPE_ATTRIBUTES (gimple_call_fntype (stmt))))
+ return true;
+ return gimple_alloca_call_p (stmt);
+ }
default:
gcc_unreachable ();
}
@@ -1444,24 +1464,6 @@ value_range_nonnegative_p (value_range_t *vr)
return false;
}
-/* Return true if T, an SSA_NAME, is known to be nonnegative. Return
- false otherwise or if no value range information is available. */
-
-bool
-ssa_name_nonnegative_p (const_tree t)
-{
- value_range_t *vr = get_value_range (t);
-
- if (INTEGRAL_TYPE_P (t)
- && TYPE_UNSIGNED (t))
- return true;
-
- if (!vr)
- return false;
-
- return value_range_nonnegative_p (vr);
-}
-
/* If *VR has a value rante that is a single constant value return that,
otherwise return NULL_TREE. */
@@ -1721,7 +1723,7 @@ extract_range_from_assert (value_range_t *vr_p, tree expr)
all should be optimized away above us. */
if ((cond_code == LT_EXPR
&& compare_values (max, min) == 0)
- || (CONSTANT_CLASS_P (max) && TREE_OVERFLOW (max)))
+ || is_overflow_infinity (max))
set_value_range_to_varying (vr_p);
else
{
@@ -1761,7 +1763,7 @@ extract_range_from_assert (value_range_t *vr_p, tree expr)
all should be optimized away above us. */
if ((cond_code == GT_EXPR
&& compare_values (min, max) == 0)
- || (CONSTANT_CLASS_P (min) && TREE_OVERFLOW (min)))
+ || is_overflow_infinity (min))
set_value_range_to_varying (vr_p);
else
{
@@ -1978,8 +1980,8 @@ zero_nonzero_bits_from_vr (value_range_t *vr,
*may_be_nonzero = double_int_minus_one;
*must_be_nonzero = double_int_zero;
if (!range_int_cst_p (vr)
- || TREE_OVERFLOW (vr->min)
- || TREE_OVERFLOW (vr->max))
+ || is_overflow_infinity (vr->min)
+ || is_overflow_infinity (vr->max))
return false;
if (range_int_cst_singleton_p (vr))
@@ -3603,13 +3605,13 @@ extract_range_basic (value_range_t *vr, gimple stmt)
&& integer_nonzerop (vr0->min))
|| (vr0->type == VR_ANTI_RANGE
&& integer_zerop (vr0->min)))
- && !TREE_OVERFLOW (vr0->min))
+ && !is_overflow_infinity (vr0->min))
mini = 1;
/* If some high bits are known to be zero,
we can decrease the maximum. */
if (vr0->type == VR_RANGE
&& TREE_CODE (vr0->max) == INTEGER_CST
- && !TREE_OVERFLOW (vr0->max))
+ && !is_overflow_infinity (vr0->max))
maxi = tree_floor_log2 (vr0->max) + 1;
}
goto bitop_builtin;
@@ -3644,7 +3646,7 @@ extract_range_basic (value_range_t *vr, gimple stmt)
result maximum. */
if (vr0->type == VR_RANGE
&& TREE_CODE (vr0->min) == INTEGER_CST
- && !TREE_OVERFLOW (vr0->min))
+ && !is_overflow_infinity (vr0->min))
{
maxi = prec - 1 - tree_floor_log2 (vr0->min);
if (maxi != prec)
@@ -3652,7 +3654,7 @@ extract_range_basic (value_range_t *vr, gimple stmt)
}
else if (vr0->type == VR_ANTI_RANGE
&& integer_zerop (vr0->min)
- && !TREE_OVERFLOW (vr0->min))
+ && !is_overflow_infinity (vr0->min))
{
maxi = prec - 1;
mini = 0;
@@ -3663,7 +3665,7 @@ extract_range_basic (value_range_t *vr, gimple stmt)
result minimum. */
if (vr0->type == VR_RANGE
&& TREE_CODE (vr0->max) == INTEGER_CST
- && !TREE_OVERFLOW (vr0->max))
+ && !is_overflow_infinity (vr0->max))
{
mini = prec - 1 - tree_floor_log2 (vr0->max);
if (mini == prec)
@@ -3706,7 +3708,7 @@ extract_range_basic (value_range_t *vr, gimple stmt)
&& integer_nonzerop (vr0->min))
|| (vr0->type == VR_ANTI_RANGE
&& integer_zerop (vr0->min)))
- && !TREE_OVERFLOW (vr0->min))
+ && !is_overflow_infinity (vr0->min))
{
mini = 0;
maxi = prec - 1;
@@ -3715,7 +3717,7 @@ extract_range_basic (value_range_t *vr, gimple stmt)
we can decrease the result maximum. */
if (vr0->type == VR_RANGE
&& TREE_CODE (vr0->max) == INTEGER_CST
- && !TREE_OVERFLOW (vr0->max))
+ && !is_overflow_infinity (vr0->max))
{
maxi = tree_floor_log2 (vr0->max);
/* For vr0 [0, 0] give up. */
@@ -4456,7 +4458,6 @@ fp_predicate (gimple stmt)
return FLOAT_TYPE_P (TREE_TYPE (gimple_cond_lhs (stmt)));
}
-
/* If the range of values taken by OP can be inferred after STMT executes,
return the comparison code (COMP_CODE_P) and value (VAL_P) that
describes the inferred range. Return true if a range could be
@@ -4474,7 +4475,7 @@ infer_value_range (gimple stmt, tree op, enum tree_code *comp_code_p, tree *val_
return false;
/* Similarly, don't infer anything from statements that may throw
- exceptions. */
+ exceptions. ??? Relax this requirement? */
if (stmt_could_throw_p (stmt))
return false;
@@ -4485,21 +4486,11 @@ infer_value_range (gimple stmt, tree op, enum tree_code *comp_code_p, tree *val_
if (stmt_ends_bb_p (stmt) && EDGE_COUNT (gimple_bb (stmt)->succs) == 0)
return false;
- /* We can only assume that a pointer dereference will yield
- non-NULL if -fdelete-null-pointer-checks is enabled. */
- if (flag_delete_null_pointer_checks
- && POINTER_TYPE_P (TREE_TYPE (op))
- && gimple_code (stmt) != GIMPLE_ASM)
+ if (infer_nonnull_range (stmt, op))
{
- unsigned num_uses, num_loads, num_stores;
-
- count_uses_and_derefs (op, stmt, &num_uses, &num_loads, &num_stores);
- if (num_loads + num_stores > 0)
- {
- *val_p = build_int_cst (TREE_TYPE (op), 0);
- *comp_code_p = NE_EXPR;
- return true;
- }
+ *val_p = build_int_cst (TREE_TYPE (op), 0);
+ *comp_code_p = NE_EXPR;
+ return true;
}
return false;
@@ -4536,7 +4527,7 @@ dump_asserts_for (FILE *file, tree name)
}
fprintf (file, "\n\tPREDICATE: ");
print_generic_expr (file, name, 0);
- fprintf (file, " %s ", tree_code_name[(int)loc->comp_code]);
+ fprintf (file, " %s ", get_tree_code_name (loc->comp_code));
print_generic_expr (file, loc->val, 0);
fprintf (file, "\n\n");
loc = loc->next;
@@ -4610,10 +4601,8 @@ register_new_assert_for (tree name, tree expr,
/* Never build an assert comparing against an integer constant with
TREE_OVERFLOW set. This confuses our undefined overflow warning
machinery. */
- if (TREE_CODE (val) == INTEGER_CST
- && TREE_OVERFLOW (val))
- val = build_int_cst_wide (TREE_TYPE (val),
- TREE_INT_CST_LOW (val), TREE_INT_CST_HIGH (val));
+ if (TREE_OVERFLOW_P (val))
+ val = drop_tree_overflow (val);
/* The new assertion A will be inserted at BB or E. We need to
determine if the new location is dominated by a previously
@@ -5856,7 +5845,7 @@ find_assert_locations_1 (basic_block bb, sbitmap live)
}
/* Traverse all PHI nodes in BB, updating live. */
- for (si = gsi_start_phis (bb); !gsi_end_p(si); gsi_next (&si))
+ for (si = gsi_start_phis (bb); !gsi_end_p (si); gsi_next (&si))
{
use_operand_p arg_p;
ssa_op_iter i;
@@ -5897,6 +5886,34 @@ find_assert_locations (void)
for (i = 0; i < rpo_cnt; ++i)
bb_rpo[rpo[i]] = i;
+ /* Pre-seed loop latch liveness from loop header PHI nodes. Due to
+ the order we compute liveness and insert asserts we otherwise
+ fail to insert asserts into the loop latch. */
+ loop_p loop;
+ loop_iterator li;
+ FOR_EACH_LOOP (li, loop, 0)
+ {
+ i = loop->latch->index;
+ unsigned int j = single_succ_edge (loop->latch)->dest_idx;
+ for (gimple_stmt_iterator gsi = gsi_start_phis (loop->header);
+ !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ gimple phi = gsi_stmt (gsi);
+ if (virtual_operand_p (gimple_phi_result (phi)))
+ continue;
+ tree arg = gimple_phi_arg_def (phi, j);
+ if (TREE_CODE (arg) == SSA_NAME)
+ {
+ if (live[i] == NULL)
+ {
+ live[i] = sbitmap_alloc (num_ssa_names);
+ bitmap_clear (live[i]);
+ }
+ bitmap_set_bit (live[i], SSA_NAME_VERSION (arg));
+ }
+ }
+ }
+
need_asserts = false;
for (i = rpo_cnt - 1; i >= 0; --i)
{
@@ -6399,6 +6416,88 @@ check_all_array_refs (void)
}
}
+/* Return true if all imm uses of VAR are either in STMT, or
+ feed (optionally through a chain of single imm uses) GIMPLE_COND
+ in basic block COND_BB. */
+
+static bool
+all_imm_uses_in_stmt_or_feed_cond (tree var, gimple stmt, basic_block cond_bb)
+{
+ use_operand_p use_p, use2_p;
+ imm_use_iterator iter;
+
+ FOR_EACH_IMM_USE_FAST (use_p, iter, var)
+ if (USE_STMT (use_p) != stmt)
+ {
+ gimple use_stmt = USE_STMT (use_p), use_stmt2;
+ if (is_gimple_debug (use_stmt))
+ continue;
+ while (is_gimple_assign (use_stmt)
+ && TREE_CODE (gimple_assign_lhs (use_stmt)) == SSA_NAME
+ && single_imm_use (gimple_assign_lhs (use_stmt),
+ &use2_p, &use_stmt2))
+ use_stmt = use_stmt2;
+ if (gimple_code (use_stmt) != GIMPLE_COND
+ || gimple_bb (use_stmt) != cond_bb)
+ return false;
+ }
+ return true;
+}
+
+/* Handle
+ _4 = x_3 & 31;
+ if (_4 != 0)
+ goto <bb 6>;
+ else
+ goto <bb 7>;
+ <bb 6>:
+ __builtin_unreachable ();
+ <bb 7>:
+ x_5 = ASSERT_EXPR <x_3, ...>;
+ If x_3 has no other immediate uses (checked by caller),
+ var is the x_3 var from ASSERT_EXPR, we can clear low 5 bits
+ from the non-zero bitmask. */
+
+static void
+maybe_set_nonzero_bits (basic_block bb, tree var)
+{
+ edge e = single_pred_edge (bb);
+ basic_block cond_bb = e->src;
+ gimple stmt = last_stmt (cond_bb);
+ tree cst;
+
+ if (stmt == NULL
+ || gimple_code (stmt) != GIMPLE_COND
+ || gimple_cond_code (stmt) != ((e->flags & EDGE_TRUE_VALUE)
+ ? EQ_EXPR : NE_EXPR)
+ || TREE_CODE (gimple_cond_lhs (stmt)) != SSA_NAME
+ || !integer_zerop (gimple_cond_rhs (stmt)))
+ return;
+
+ stmt = SSA_NAME_DEF_STMT (gimple_cond_lhs (stmt));
+ if (!is_gimple_assign (stmt)
+ || gimple_assign_rhs_code (stmt) != BIT_AND_EXPR
+ || TREE_CODE (gimple_assign_rhs2 (stmt)) != INTEGER_CST)
+ return;
+ if (gimple_assign_rhs1 (stmt) != var)
+ {
+ gimple stmt2;
+
+ if (TREE_CODE (gimple_assign_rhs1 (stmt)) != SSA_NAME)
+ return;
+ stmt2 = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt));
+ if (!gimple_assign_cast_p (stmt2)
+ || gimple_assign_rhs1 (stmt2) != var
+ || !CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (stmt2))
+ || (TYPE_PRECISION (TREE_TYPE (gimple_assign_rhs1 (stmt)))
+ != TYPE_PRECISION (TREE_TYPE (var))))
+ return;
+ }
+ cst = gimple_assign_rhs2 (stmt);
+ set_nonzero_bits (var, (get_nonzero_bits (var)
+ & ~tree_to_double_int (cst)));
+}
+
/* Convert range assertion expressions into the implied copies and
copy propagate away the copies. Doing the trivial copy propagation
here avoids the need to run the full copy propagation pass after
@@ -6428,12 +6527,16 @@ remove_range_assertions (void)
{
basic_block bb;
gimple_stmt_iterator si;
+ /* 1 if looking at ASSERT_EXPRs immediately at the beginning of
+ a basic block preceeded by GIMPLE_COND branching to it and
+ __builtin_trap, -1 if not yet checked, 0 otherwise. */
+ int is_unreachable;
/* Note that the BSI iterator bump happens at the bottom of the
loop and no bump is necessary if we're removing the statement
referenced by the current BSI. */
FOR_EACH_BB (bb)
- for (si = gsi_start_bb (bb); !gsi_end_p (si);)
+ for (si = gsi_after_labels (bb), is_unreachable = -1; !gsi_end_p (si);)
{
gimple stmt = gsi_stmt (si);
gimple use_stmt;
@@ -6441,6 +6544,7 @@ remove_range_assertions (void)
if (is_gimple_assign (stmt)
&& gimple_assign_rhs_code (stmt) == ASSERT_EXPR)
{
+ tree lhs = gimple_assign_lhs (stmt);
tree rhs = gimple_assign_rhs1 (stmt);
tree var;
tree cond = fold (ASSERT_EXPR_COND (rhs));
@@ -6449,22 +6553,52 @@ remove_range_assertions (void)
gcc_assert (cond != boolean_false_node);
- /* Propagate the RHS into every use of the LHS. */
var = ASSERT_EXPR_VAR (rhs);
- FOR_EACH_IMM_USE_STMT (use_stmt, iter,
- gimple_assign_lhs (stmt))
+ gcc_assert (TREE_CODE (var) == SSA_NAME);
+
+ if (!POINTER_TYPE_P (TREE_TYPE (lhs))
+ && SSA_NAME_RANGE_INFO (lhs))
+ {
+ if (is_unreachable == -1)
+ {
+ is_unreachable = 0;
+ if (single_pred_p (bb)
+ && assert_unreachable_fallthru_edge_p
+ (single_pred_edge (bb)))
+ is_unreachable = 1;
+ }
+ /* Handle
+ if (x_7 >= 10 && x_7 < 20)
+ __builtin_unreachable ();
+ x_8 = ASSERT_EXPR <x_7, ...>;
+ if the only uses of x_7 are in the ASSERT_EXPR and
+ in the condition. In that case, we can copy the
+ range info from x_8 computed in this pass also
+ for x_7. */
+ if (is_unreachable
+ && all_imm_uses_in_stmt_or_feed_cond (var, stmt,
+ single_pred (bb)))
+ {
+ set_range_info (var, SSA_NAME_RANGE_INFO (lhs)->min,
+ SSA_NAME_RANGE_INFO (lhs)->max);
+ maybe_set_nonzero_bits (bb, var);
+ }
+ }
+
+ /* Propagate the RHS into every use of the LHS. */
+ FOR_EACH_IMM_USE_STMT (use_stmt, iter, lhs)
FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
- {
- SET_USE (use_p, var);
- gcc_assert (TREE_CODE (var) == SSA_NAME);
- }
+ SET_USE (use_p, var);
/* And finally, remove the copy, it is not needed. */
gsi_remove (&si, true);
release_defs (stmt);
}
else
- gsi_next (&si);
+ {
+ gsi_next (&si);
+ is_unreachable = 0;
+ }
}
}
@@ -6491,9 +6625,7 @@ stmt_interesting_for_vrp (gimple stmt)
if (lhs && TREE_CODE (lhs) == SSA_NAME
&& (INTEGRAL_TYPE_P (TREE_TYPE (lhs))
|| POINTER_TYPE_P (TREE_TYPE (lhs)))
- && ((is_gimple_call (stmt)
- && gimple_call_fndecl (stmt) != NULL_TREE
- && DECL_BUILT_IN (gimple_call_fndecl (stmt)))
+ && (is_gimple_call (stmt)
|| !gimple_vuse (stmt)))
return true;
}
@@ -7414,16 +7546,7 @@ vrp_visit_stmt (gimple stmt, edge *taken_edge_p, tree *output_p)
if (!stmt_interesting_for_vrp (stmt))
gcc_assert (stmt_ends_bb_p (stmt));
else if (is_gimple_assign (stmt) || is_gimple_call (stmt))
- {
- /* In general, assignments with virtual operands are not useful
- for deriving ranges, with the obvious exception of calls to
- builtin functions. */
- if ((is_gimple_call (stmt)
- && gimple_call_fndecl (stmt) != NULL_TREE
- && DECL_BUILT_IN (gimple_call_fndecl (stmt)))
- || !gimple_vuse (stmt))
- return vrp_visit_assignment_or_call (stmt, output_p);
- }
+ return vrp_visit_assignment_or_call (stmt, output_p);
else if (gimple_code (stmt) == GIMPLE_COND)
return vrp_visit_cond_stmt (stmt, taken_edge_p);
else if (gimple_code (stmt) == GIMPLE_SWITCH)
@@ -8205,10 +8328,7 @@ vrp_visit_phi_node (gimple phi)
else
{
if (is_overflow_infinity (arg))
- {
- arg = copy_node (arg);
- TREE_OVERFLOW (arg) = 0;
- }
+ arg = drop_tree_overflow (arg);
vr_arg.type = VR_RANGE;
vr_arg.min = arg;
@@ -9452,6 +9572,51 @@ vrp_finalize (void)
the datastructures built by VRP. */
identify_jump_threads ();
+ /* Set value range to non pointer SSA_NAMEs. */
+ for (i = 0; i < num_vr_values; i++)
+ if (vr_value[i])
+ {
+ tree name = ssa_name (i);
+
+ if (!name
+ || POINTER_TYPE_P (TREE_TYPE (name))
+ || (vr_value[i]->type == VR_VARYING)
+ || (vr_value[i]->type == VR_UNDEFINED))
+ continue;
+
+ if ((TREE_CODE (vr_value[i]->min) == INTEGER_CST)
+ && (TREE_CODE (vr_value[i]->max) == INTEGER_CST))
+ {
+ if (vr_value[i]->type == VR_RANGE)
+ set_range_info (name,
+ tree_to_double_int (vr_value[i]->min),
+ tree_to_double_int (vr_value[i]->max));
+ else if (vr_value[i]->type == VR_ANTI_RANGE)
+ {
+ /* VR_ANTI_RANGE ~[min, max] is encoded compactly as
+ [max + 1, min - 1] without additional attributes.
+ When min value > max value, we know that it is
+ VR_ANTI_RANGE; it is VR_RANGE otherwise. */
+
+ /* ~[0,0] anti-range is represented as
+ range. */
+ if (TYPE_UNSIGNED (TREE_TYPE (name))
+ && integer_zerop (vr_value[i]->min)
+ && integer_zerop (vr_value[i]->max))
+ set_range_info (name,
+ double_int_one,
+ double_int::max_value
+ (TYPE_PRECISION (TREE_TYPE (name)), true));
+ else
+ set_range_info (name,
+ tree_to_double_int (vr_value[i]->max)
+ + double_int_one,
+ tree_to_double_int (vr_value[i]->min)
+ - double_int_one);
+ }
+ }
+ }
+
/* Free allocated memory. */
for (i = 0; i < num_vr_values; i++)
if (vr_value[i])
@@ -9622,12 +9787,12 @@ const pass_data pass_data_vrp =
class pass_vrp : public gimple_opt_pass
{
public:
- pass_vrp(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_vrp, ctxt)
+ pass_vrp (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_vrp, ctxt)
{}
/* opt_pass methods: */
- opt_pass * clone () { return new pass_vrp (ctxt_); }
+ opt_pass * clone () { return new pass_vrp (m_ctxt); }
bool gate () { return gate_vrp (); }
unsigned int execute () { return execute_vrp (); }
diff --git a/gcc/tree.c b/gcc/tree.c
index 6593cf82018..686a680f94c 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -47,7 +47,13 @@ along with GCC; see the file COPYING3. If not see
#include "tree-inline.h"
#include "tree-iterator.h"
#include "basic-block.h"
-#include "tree-ssa.h"
+#include "bitmap.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "cgraph.h"
+#include "tree-phinodes.h"
+#include "tree-ssanames.h"
+#include "tree-dfa.h"
#include "params.h"
#include "pointer-set.h"
#include "tree-pass.h"
@@ -55,7 +61,6 @@ along with GCC; see the file COPYING3. If not see
#include "diagnostic.h"
#include "tree-diagnostic.h"
#include "tree-pretty-print.h"
-#include "cgraph.h"
#include "except.h"
#include "debug.h"
#include "intl.h"
@@ -91,7 +96,7 @@ const unsigned char tree_code_length[] = {
#define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME,
#define END_OF_BASE_TREE_CODES "@dummy",
-const char *const tree_code_name[] = {
+static const char *const tree_code_name[] = {
#include "all-tree.def"
};
@@ -237,7 +242,13 @@ unsigned const char omp_clause_num_ops[] =
1, /* OMP_CLAUSE_COPYIN */
1, /* OMP_CLAUSE_COPYPRIVATE */
2, /* OMP_CLAUSE_LINEAR */
+ 2, /* OMP_CLAUSE_ALIGNED */
+ 1, /* OMP_CLAUSE_DEPEND */
1, /* OMP_CLAUSE_UNIFORM */
+ 2, /* OMP_CLAUSE_FROM */
+ 2, /* OMP_CLAUSE_TO */
+ 2, /* OMP_CLAUSE_MAP */
+ 1, /* OMP_CLAUSE__LOOPTEMP_ */
1, /* OMP_CLAUSE_IF */
1, /* OMP_CLAUSE_NUM_THREADS */
1, /* OMP_CLAUSE_SCHEDULE */
@@ -248,7 +259,19 @@ unsigned const char omp_clause_num_ops[] =
0, /* OMP_CLAUSE_UNTIED */
1, /* OMP_CLAUSE_FINAL */
0, /* OMP_CLAUSE_MERGEABLE */
+ 1, /* OMP_CLAUSE_DEVICE */
+ 1, /* OMP_CLAUSE_DIST_SCHEDULE */
+ 0, /* OMP_CLAUSE_INBRANCH */
+ 0, /* OMP_CLAUSE_NOTINBRANCH */
+ 1, /* OMP_CLAUSE_NUM_TEAMS */
+ 1, /* OMP_CLAUSE_THREAD_LIMIT */
+ 0, /* OMP_CLAUSE_PROC_BIND */
1, /* OMP_CLAUSE_SAFELEN */
+ 1, /* OMP_CLAUSE_SIMDLEN */
+ 0, /* OMP_CLAUSE_FOR */
+ 0, /* OMP_CLAUSE_PARALLEL */
+ 0, /* OMP_CLAUSE_SECTIONS */
+ 0, /* OMP_CLAUSE_TASKGROUP */
1, /* OMP_CLAUSE__SIMDUID_ */
};
@@ -263,7 +286,13 @@ const char * const omp_clause_code_name[] =
"copyin",
"copyprivate",
"linear",
+ "aligned",
+ "depend",
"uniform",
+ "from",
+ "to",
+ "map",
+ "_looptemp_",
"if",
"num_threads",
"schedule",
@@ -274,7 +303,19 @@ const char * const omp_clause_code_name[] =
"untied",
"final",
"mergeable",
+ "device",
+ "dist_schedule",
+ "inbranch",
+ "notinbranch",
+ "num_teams",
+ "thread_limit",
+ "proc_bind",
"safelen",
+ "simdlen",
+ "for",
+ "parallel",
+ "sections",
+ "taskgroup",
"_simduid_"
};
@@ -547,82 +588,6 @@ decl_assembler_name (tree decl)
return DECL_WITH_VIS_CHECK (decl)->decl_with_vis.assembler_name;
}
-/* Compare ASMNAME with the DECL_ASSEMBLER_NAME of DECL. */
-
-bool
-decl_assembler_name_equal (tree decl, const_tree asmname)
-{
- tree decl_asmname = DECL_ASSEMBLER_NAME (decl);
- const char *decl_str;
- const char *asmname_str;
- bool test = false;
-
- if (decl_asmname == asmname)
- return true;
-
- decl_str = IDENTIFIER_POINTER (decl_asmname);
- asmname_str = IDENTIFIER_POINTER (asmname);
-
-
- /* If the target assembler name was set by the user, things are trickier.
- We have a leading '*' to begin with. After that, it's arguable what
- is the correct thing to do with -fleading-underscore. Arguably, we've
- historically been doing the wrong thing in assemble_alias by always
- printing the leading underscore. Since we're not changing that, make
- sure user_label_prefix follows the '*' before matching. */
- if (decl_str[0] == '*')
- {
- size_t ulp_len = strlen (user_label_prefix);
-
- decl_str ++;
-
- if (ulp_len == 0)
- test = true;
- else if (strncmp (decl_str, user_label_prefix, ulp_len) == 0)
- decl_str += ulp_len, test=true;
- else
- decl_str --;
- }
- if (asmname_str[0] == '*')
- {
- size_t ulp_len = strlen (user_label_prefix);
-
- asmname_str ++;
-
- if (ulp_len == 0)
- test = true;
- else if (strncmp (asmname_str, user_label_prefix, ulp_len) == 0)
- asmname_str += ulp_len, test=true;
- else
- asmname_str --;
- }
-
- if (!test)
- return false;
- return strcmp (decl_str, asmname_str) == 0;
-}
-
-/* Hash asmnames ignoring the user specified marks. */
-
-hashval_t
-decl_assembler_name_hash (const_tree asmname)
-{
- if (IDENTIFIER_POINTER (asmname)[0] == '*')
- {
- const char *decl_str = IDENTIFIER_POINTER (asmname) + 1;
- size_t ulp_len = strlen (user_label_prefix);
-
- if (ulp_len == 0)
- ;
- else if (strncmp (decl_str, user_label_prefix, ulp_len) == 0)
- decl_str += ulp_len;
-
- return htab_hash_string (decl_str);
- }
-
- return htab_hash_string (IDENTIFIER_POINTER (asmname));
-}
-
/* Compute the number of bytes occupied by a tree with code CODE.
This function cannot be used for nodes that have variable sizes,
including TREE_VEC, STRING_CST, and CALL_EXPR. */
@@ -1007,7 +972,7 @@ copy_node_stat (tree node MEM_STAT_DECL)
TYPE_SYMTAB_ADDRESS (t) = 0;
/* Do not copy the values cache. */
- if (TYPE_CACHED_VALUES_P(t))
+ if (TYPE_CACHED_VALUES_P (t))
{
TYPE_CACHED_VALUES_P (t) = 0;
TYPE_CACHED_VALUES (t) = NULL_TREE;
@@ -1112,7 +1077,7 @@ force_fit_type_double (tree type, double_int cst, int overflowable,
bool sign_extended_type = !TYPE_UNSIGNED (type);
/* If we need to set overflow flags, return a new unshared node. */
- if (overflowed || !double_int_fits_to_tree_p(type, cst))
+ if (overflowed || !double_int_fits_to_tree_p (type, cst))
{
if (overflowed
|| overflowable < 0
@@ -1180,7 +1145,8 @@ build_int_cst_wide (tree type, unsigned HOST_WIDE_INT low, HOST_WIDE_INT hi)
case POINTER_TYPE:
case REFERENCE_TYPE:
- /* Cache NULL pointer. */
+ case POINTER_BOUNDS_TYPE:
+ /* Cache NULL pointer and zero bounds. */
if (!hi && !low)
{
limit = 1;
@@ -1726,7 +1692,7 @@ build_one_cst (tree type)
case FIXED_POINT_TYPE:
/* We can only generate 1 for accum types. */
gcc_assert (ALL_SCALAR_ACCUM_MODE_P (TYPE_MODE (type)));
- return build_fixed (type, FCONST1(TYPE_MODE (type)));
+ return build_fixed (type, FCONST1 (TYPE_MODE (type)));
case VECTOR_TYPE:
{
@@ -2172,6 +2138,119 @@ tree_floor_log2 (const_tree expr)
: floor_log2 (low));
}
+/* Return number of known trailing zero bits in EXPR, or, if the value of
+ EXPR is known to be zero, the precision of it's type. */
+
+unsigned int
+tree_ctz (const_tree expr)
+{
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (expr))
+ && !POINTER_TYPE_P (TREE_TYPE (expr)))
+ return 0;
+
+ unsigned int ret1, ret2, prec = TYPE_PRECISION (TREE_TYPE (expr));
+ switch (TREE_CODE (expr))
+ {
+ case INTEGER_CST:
+ ret1 = tree_to_double_int (expr).trailing_zeros ();
+ return MIN (ret1, prec);
+ case SSA_NAME:
+ ret1 = get_nonzero_bits (expr).trailing_zeros ();
+ return MIN (ret1, prec);
+ case PLUS_EXPR:
+ case MINUS_EXPR:
+ case BIT_IOR_EXPR:
+ case BIT_XOR_EXPR:
+ case MIN_EXPR:
+ case MAX_EXPR:
+ ret1 = tree_ctz (TREE_OPERAND (expr, 0));
+ if (ret1 == 0)
+ return ret1;
+ ret2 = tree_ctz (TREE_OPERAND (expr, 1));
+ return MIN (ret1, ret2);
+ case POINTER_PLUS_EXPR:
+ ret1 = tree_ctz (TREE_OPERAND (expr, 0));
+ ret2 = tree_ctz (TREE_OPERAND (expr, 1));
+ /* Second operand is sizetype, which could be in theory
+ wider than pointer's precision. Make sure we never
+ return more than prec. */
+ ret2 = MIN (ret2, prec);
+ return MIN (ret1, ret2);
+ case BIT_AND_EXPR:
+ ret1 = tree_ctz (TREE_OPERAND (expr, 0));
+ ret2 = tree_ctz (TREE_OPERAND (expr, 1));
+ return MAX (ret1, ret2);
+ case MULT_EXPR:
+ ret1 = tree_ctz (TREE_OPERAND (expr, 0));
+ ret2 = tree_ctz (TREE_OPERAND (expr, 1));
+ return MIN (ret1 + ret2, prec);
+ case LSHIFT_EXPR:
+ ret1 = tree_ctz (TREE_OPERAND (expr, 0));
+ if (host_integerp (TREE_OPERAND (expr, 1), 1)
+ && ((unsigned HOST_WIDE_INT) tree_low_cst (TREE_OPERAND (expr, 1), 1)
+ < (unsigned HOST_WIDE_INT) prec))
+ {
+ ret2 = tree_low_cst (TREE_OPERAND (expr, 1), 1);
+ return MIN (ret1 + ret2, prec);
+ }
+ return ret1;
+ case RSHIFT_EXPR:
+ if (host_integerp (TREE_OPERAND (expr, 1), 1)
+ && ((unsigned HOST_WIDE_INT) tree_low_cst (TREE_OPERAND (expr, 1), 1)
+ < (unsigned HOST_WIDE_INT) prec))
+ {
+ ret1 = tree_ctz (TREE_OPERAND (expr, 0));
+ ret2 = tree_low_cst (TREE_OPERAND (expr, 1), 1);
+ if (ret1 > ret2)
+ return ret1 - ret2;
+ }
+ return 0;
+ case TRUNC_DIV_EXPR:
+ case CEIL_DIV_EXPR:
+ case FLOOR_DIV_EXPR:
+ case ROUND_DIV_EXPR:
+ case EXACT_DIV_EXPR:
+ if (TREE_CODE (TREE_OPERAND (expr, 1)) == INTEGER_CST
+ && tree_int_cst_sgn (TREE_OPERAND (expr, 1)) == 1)
+ {
+ int l = tree_log2 (TREE_OPERAND (expr, 1));
+ if (l >= 0)
+ {
+ ret1 = tree_ctz (TREE_OPERAND (expr, 0));
+ ret2 = l;
+ if (ret1 > ret2)
+ return ret1 - ret2;
+ }
+ }
+ return 0;
+ CASE_CONVERT:
+ ret1 = tree_ctz (TREE_OPERAND (expr, 0));
+ if (ret1 && ret1 == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (expr, 0))))
+ ret1 = prec;
+ return MIN (ret1, prec);
+ case SAVE_EXPR:
+ return tree_ctz (TREE_OPERAND (expr, 0));
+ case COND_EXPR:
+ ret1 = tree_ctz (TREE_OPERAND (expr, 1));
+ if (ret1 == 0)
+ return 0;
+ ret2 = tree_ctz (TREE_OPERAND (expr, 2));
+ return MIN (ret1, ret2);
+ case COMPOUND_EXPR:
+ return tree_ctz (TREE_OPERAND (expr, 1));
+ case ADDR_EXPR:
+ ret1 = get_pointer_alignment (CONST_CAST_TREE (expr));
+ if (ret1 > BITS_PER_UNIT)
+ {
+ ret1 = ctz_hwi (ret1 / BITS_PER_UNIT);
+ return MIN (ret1, prec);
+ }
+ return 0;
+ default:
+ return 0;
+ }
+}
+
/* Return 1 if EXPR is the real constant zero. Trailing zeroes matter for
decimal float constants, so don't return 1 for them. */
@@ -2231,35 +2310,6 @@ real_onep (const_tree expr)
}
}
-/* Return 1 if EXPR is the real constant two. Trailing zeroes matter
- for decimal float constants, so don't return 1 for them. */
-
-int
-real_twop (const_tree expr)
-{
- STRIP_NOPS (expr);
-
- switch (TREE_CODE (expr))
- {
- case REAL_CST:
- return REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst2)
- && !(DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (expr))));
- case COMPLEX_CST:
- return real_twop (TREE_REALPART (expr))
- && real_zerop (TREE_IMAGPART (expr));
- case VECTOR_CST:
- {
- unsigned i;
- for (i = 0; i < VECTOR_CST_NELTS (expr); ++i)
- if (!real_twop (VECTOR_CST_ELT (expr, i)))
- return false;
- return true;
- }
- default:
- return false;
- }
-}
-
/* Return 1 if EXPR is the real constant minus one. Trailing zeroes
matter for decimal float constants, so don't return 1 for them. */
@@ -2397,21 +2447,6 @@ list_length (const_tree t)
return len;
}
-/* Returns the number of FIELD_DECLs in TYPE. */
-
-int
-fields_length (const_tree type)
-{
- tree t = TYPE_FIELDS (type);
- int count = 0;
-
- for (; t; t = DECL_CHAIN (t))
- if (TREE_CODE (t) == FIELD_DECL)
- ++count;
-
- return count;
-}
-
/* Returns the first FIELD_DECL in the TYPE_FIELDS of the RECORD_TYPE or
UNION_TYPE TYPE, or NULL_TREE if none. */
@@ -2632,18 +2667,6 @@ max_int_size_in_bytes (const_tree type)
return size;
}
-
-/* Returns a tree for the size of EXP in bytes. */
-
-tree
-tree_expr_size (const_tree exp)
-{
- if (DECL_P (exp)
- && DECL_SIZE_UNIT (exp) != 0)
- return DECL_SIZE_UNIT (exp);
- else
- return size_in_bytes (TREE_TYPE (exp));
-}
/* Return the bit position of FIELD, in bits from the start of the record.
This is a tree of type bitsizetype. */
@@ -3232,6 +3255,7 @@ type_contains_placeholder_1 (const_tree type)
switch (TREE_CODE (type))
{
case VOID_TYPE:
+ case POINTER_BOUNDS_TYPE:
case COMPLEX_TYPE:
case ENUMERAL_TYPE:
case BOOLEAN_TYPE:
@@ -3746,6 +3770,88 @@ substitute_placeholder_in_expr (tree exp, tree obj)
return new_tree;
}
+
+/* Subroutine of stabilize_reference; this is called for subtrees of
+ references. Any expression with side-effects must be put in a SAVE_EXPR
+ to ensure that it is only evaluated once.
+
+ We don't put SAVE_EXPR nodes around everything, because assigning very
+ simple expressions to temporaries causes us to miss good opportunities
+ for optimizations. Among other things, the opportunity to fold in the
+ addition of a constant into an addressing mode often gets lost, e.g.
+ "y[i+1] += x;". In general, we take the approach that we should not make
+ an assignment unless we are forced into it - i.e., that any non-side effect
+ operator should be allowed, and that cse should take care of coalescing
+ multiple utterances of the same expression should that prove fruitful. */
+
+static tree
+stabilize_reference_1 (tree e)
+{
+ tree result;
+ enum tree_code code = TREE_CODE (e);
+
+ /* We cannot ignore const expressions because it might be a reference
+ to a const array but whose index contains side-effects. But we can
+ ignore things that are actual constant or that already have been
+ handled by this function. */
+
+ if (tree_invariant_p (e))
+ return e;
+
+ switch (TREE_CODE_CLASS (code))
+ {
+ case tcc_exceptional:
+ case tcc_type:
+ case tcc_declaration:
+ case tcc_comparison:
+ case tcc_statement:
+ case tcc_expression:
+ case tcc_reference:
+ case tcc_vl_exp:
+ /* If the expression has side-effects, then encase it in a SAVE_EXPR
+ so that it will only be evaluated once. */
+ /* The reference (r) and comparison (<) classes could be handled as
+ below, but it is generally faster to only evaluate them once. */
+ if (TREE_SIDE_EFFECTS (e))
+ return save_expr (e);
+ return e;
+
+ case tcc_constant:
+ /* Constants need no processing. In fact, we should never reach
+ here. */
+ return e;
+
+ case tcc_binary:
+ /* Division is slow and tends to be compiled with jumps,
+ especially the division by powers of 2 that is often
+ found inside of an array reference. So do it just once. */
+ if (code == TRUNC_DIV_EXPR || code == TRUNC_MOD_EXPR
+ || code == FLOOR_DIV_EXPR || code == FLOOR_MOD_EXPR
+ || code == CEIL_DIV_EXPR || code == CEIL_MOD_EXPR
+ || code == ROUND_DIV_EXPR || code == ROUND_MOD_EXPR)
+ return save_expr (e);
+ /* Recursively stabilize each operand. */
+ result = build_nt (code, stabilize_reference_1 (TREE_OPERAND (e, 0)),
+ stabilize_reference_1 (TREE_OPERAND (e, 1)));
+ break;
+
+ case tcc_unary:
+ /* Recursively stabilize each operand. */
+ result = build_nt (code, stabilize_reference_1 (TREE_OPERAND (e, 0)));
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ TREE_TYPE (result) = TREE_TYPE (e);
+ TREE_READONLY (result) = TREE_READONLY (e);
+ TREE_SIDE_EFFECTS (result) = TREE_SIDE_EFFECTS (e);
+ TREE_THIS_VOLATILE (result) = TREE_THIS_VOLATILE (e);
+
+ return result;
+}
+
/* Stabilize a reference so that we can use it any number of times
without causing its operands to be evaluated more than once.
Returns the stabilized reference. This works by means of save_expr,
@@ -3827,87 +3933,6 @@ stabilize_reference (tree ref)
return result;
}
-
-/* Subroutine of stabilize_reference; this is called for subtrees of
- references. Any expression with side-effects must be put in a SAVE_EXPR
- to ensure that it is only evaluated once.
-
- We don't put SAVE_EXPR nodes around everything, because assigning very
- simple expressions to temporaries causes us to miss good opportunities
- for optimizations. Among other things, the opportunity to fold in the
- addition of a constant into an addressing mode often gets lost, e.g.
- "y[i+1] += x;". In general, we take the approach that we should not make
- an assignment unless we are forced into it - i.e., that any non-side effect
- operator should be allowed, and that cse should take care of coalescing
- multiple utterances of the same expression should that prove fruitful. */
-
-tree
-stabilize_reference_1 (tree e)
-{
- tree result;
- enum tree_code code = TREE_CODE (e);
-
- /* We cannot ignore const expressions because it might be a reference
- to a const array but whose index contains side-effects. But we can
- ignore things that are actual constant or that already have been
- handled by this function. */
-
- if (tree_invariant_p (e))
- return e;
-
- switch (TREE_CODE_CLASS (code))
- {
- case tcc_exceptional:
- case tcc_type:
- case tcc_declaration:
- case tcc_comparison:
- case tcc_statement:
- case tcc_expression:
- case tcc_reference:
- case tcc_vl_exp:
- /* If the expression has side-effects, then encase it in a SAVE_EXPR
- so that it will only be evaluated once. */
- /* The reference (r) and comparison (<) classes could be handled as
- below, but it is generally faster to only evaluate them once. */
- if (TREE_SIDE_EFFECTS (e))
- return save_expr (e);
- return e;
-
- case tcc_constant:
- /* Constants need no processing. In fact, we should never reach
- here. */
- return e;
-
- case tcc_binary:
- /* Division is slow and tends to be compiled with jumps,
- especially the division by powers of 2 that is often
- found inside of an array reference. So do it just once. */
- if (code == TRUNC_DIV_EXPR || code == TRUNC_MOD_EXPR
- || code == FLOOR_DIV_EXPR || code == FLOOR_MOD_EXPR
- || code == CEIL_DIV_EXPR || code == CEIL_MOD_EXPR
- || code == ROUND_DIV_EXPR || code == ROUND_MOD_EXPR)
- return save_expr (e);
- /* Recursively stabilize each operand. */
- result = build_nt (code, stabilize_reference_1 (TREE_OPERAND (e, 0)),
- stabilize_reference_1 (TREE_OPERAND (e, 1)));
- break;
-
- case tcc_unary:
- /* Recursively stabilize each operand. */
- result = build_nt (code, stabilize_reference_1 (TREE_OPERAND (e, 0)));
- break;
-
- default:
- gcc_unreachable ();
- }
-
- TREE_TYPE (result) = TREE_TYPE (e);
- TREE_READONLY (result) = TREE_READONLY (e);
- TREE_SIDE_EFFECTS (result) = TREE_SIDE_EFFECTS (e);
- TREE_THIS_VOLATILE (result) = TREE_THIS_VOLATILE (e);
-
- return result;
-}
/* Low-level constructors for expressions. */
@@ -4118,8 +4143,8 @@ build2_stat (enum tree_code code, tree tt, tree arg0, tree arg1 MEM_STAT_DECL)
read_only = 1;
side_effects = TREE_SIDE_EFFECTS (t);
- PROCESS_ARG(0);
- PROCESS_ARG(1);
+ PROCESS_ARG (0);
+ PROCESS_ARG (1);
TREE_READONLY (t) = read_only;
TREE_CONSTANT (t) = constant;
@@ -4158,9 +4183,9 @@ build3_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
else
side_effects = TREE_SIDE_EFFECTS (t);
- PROCESS_ARG(0);
- PROCESS_ARG(1);
- PROCESS_ARG(2);
+ PROCESS_ARG (0);
+ PROCESS_ARG (1);
+ PROCESS_ARG (2);
if (code == COND_EXPR)
TREE_READONLY (t) = read_only;
@@ -4187,10 +4212,10 @@ build4_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
side_effects = TREE_SIDE_EFFECTS (t);
- PROCESS_ARG(0);
- PROCESS_ARG(1);
- PROCESS_ARG(2);
- PROCESS_ARG(3);
+ PROCESS_ARG (0);
+ PROCESS_ARG (1);
+ PROCESS_ARG (2);
+ PROCESS_ARG (3);
TREE_SIDE_EFFECTS (t) = side_effects;
TREE_THIS_VOLATILE (t)
@@ -4214,11 +4239,11 @@ build5_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
side_effects = TREE_SIDE_EFFECTS (t);
- PROCESS_ARG(0);
- PROCESS_ARG(1);
- PROCESS_ARG(2);
- PROCESS_ARG(3);
- PROCESS_ARG(4);
+ PROCESS_ARG (0);
+ PROCESS_ARG (1);
+ PROCESS_ARG (2);
+ PROCESS_ARG (3);
+ PROCESS_ARG (4);
TREE_SIDE_EFFECTS (t) = side_effects;
TREE_THIS_VOLATILE (t)
@@ -4263,24 +4288,6 @@ mem_ref_offset (const_tree t)
return tree_to_double_int (toff).sext (TYPE_PRECISION (TREE_TYPE (toff)));
}
-/* Return the pointer-type relevant for TBAA purposes from the
- gimple memory reference tree T. This is the type to be used for
- the offset operand of MEM_REF or TARGET_MEM_REF replacements of T. */
-
-tree
-reference_alias_ptr_type (const_tree t)
-{
- const_tree base = t;
- while (handled_component_p (base))
- base = TREE_OPERAND (base, 0);
- if (TREE_CODE (base) == MEM_REF)
- return TREE_TYPE (TREE_OPERAND (base, 1));
- else if (TREE_CODE (base) == TARGET_MEM_REF)
- return TREE_TYPE (TMR_OFFSET (base));
- else
- return build_pointer_type (TYPE_MAIN_VARIANT (TREE_TYPE (base)));
-}
-
/* Return an invariant ADDR_EXPR of type TYPE taking the address of BASE
offsetted by OFFSET units. */
@@ -4578,6 +4585,66 @@ build_type_attribute_qual_variant (tree ttype, tree attribute, int quals)
return ttype;
}
+/* Check if "omp declare simd" attribute arguments, CLAUSES1 and CLAUSES2, are
+ the same. */
+
+static bool
+omp_declare_simd_clauses_equal (tree clauses1, tree clauses2)
+{
+ tree cl1, cl2;
+ for (cl1 = clauses1, cl2 = clauses2;
+ cl1 && cl2;
+ cl1 = OMP_CLAUSE_CHAIN (cl1), cl2 = OMP_CLAUSE_CHAIN (cl2))
+ {
+ if (OMP_CLAUSE_CODE (cl1) != OMP_CLAUSE_CODE (cl2))
+ return false;
+ if (OMP_CLAUSE_CODE (cl1) != OMP_CLAUSE_SIMDLEN)
+ {
+ if (simple_cst_equal (OMP_CLAUSE_DECL (cl1),
+ OMP_CLAUSE_DECL (cl2)) != 1)
+ return false;
+ }
+ switch (OMP_CLAUSE_CODE (cl1))
+ {
+ case OMP_CLAUSE_ALIGNED:
+ if (simple_cst_equal (OMP_CLAUSE_ALIGNED_ALIGNMENT (cl1),
+ OMP_CLAUSE_ALIGNED_ALIGNMENT (cl2)) != 1)
+ return false;
+ break;
+ case OMP_CLAUSE_LINEAR:
+ if (simple_cst_equal (OMP_CLAUSE_LINEAR_STEP (cl1),
+ OMP_CLAUSE_LINEAR_STEP (cl2)) != 1)
+ return false;
+ break;
+ case OMP_CLAUSE_SIMDLEN:
+ if (simple_cst_equal (OMP_CLAUSE_SIMDLEN_EXPR (cl1),
+ OMP_CLAUSE_SIMDLEN_EXPR (cl2)) != 1)
+ return false;
+ default:
+ break;
+ }
+ }
+ return true;
+}
+
+/* Compare two constructor-element-type constants. Return 1 if the lists
+ are known to be equal; otherwise return 0. */
+
+static bool
+simple_cst_list_equal (const_tree l1, const_tree l2)
+{
+ while (l1 != NULL_TREE && l2 != NULL_TREE)
+ {
+ if (simple_cst_equal (TREE_VALUE (l1), TREE_VALUE (l2)) != 1)
+ return false;
+
+ l1 = TREE_CHAIN (l1);
+ l2 = TREE_CHAIN (l2);
+ }
+
+ return l1 == l2;
+}
+
/* Compare two attributes for their value identity. Return true if the
attribute values are known to be equal; otherwise return false.
*/
@@ -4595,6 +4662,13 @@ attribute_value_equal (const_tree attr1, const_tree attr2)
return (simple_cst_list_equal (TREE_VALUE (attr1),
TREE_VALUE (attr2)) == 1);
+ if ((flag_openmp || flag_openmp_simd)
+ && TREE_VALUE (attr1) && TREE_VALUE (attr2)
+ && TREE_CODE (TREE_VALUE (attr1)) == OMP_CLAUSE
+ && TREE_CODE (TREE_VALUE (attr2)) == OMP_CLAUSE)
+ return omp_declare_simd_clauses_equal (TREE_VALUE (attr1),
+ TREE_VALUE (attr2));
+
return (simple_cst_equal (TREE_VALUE (attr1), TREE_VALUE (attr2)) == 1);
}
@@ -4896,7 +4970,7 @@ free_lang_data_in_decl (tree decl)
{
struct cgraph_node *node;
if (!(node = cgraph_get_node (decl))
- || (!node->symbol.definition && !node->clones))
+ || (!node->definition && !node->clones))
{
if (node)
cgraph_release_function_body (node);
@@ -5310,14 +5384,14 @@ find_decls_types_in_node (struct cgraph_node *n, struct free_lang_data_d *fld)
unsigned ix;
tree t;
- find_decls_types (n->symbol.decl, fld);
+ find_decls_types (n->decl, fld);
- if (!gimple_has_body_p (n->symbol.decl))
+ if (!gimple_has_body_p (n->decl))
return;
gcc_assert (current_function_decl == NULL_TREE && cfun == NULL);
- fn = DECL_STRUCT_FUNCTION (n->symbol.decl);
+ fn = DECL_STRUCT_FUNCTION (n->decl);
/* Traverse locals. */
FOR_EACH_LOCAL_DECL (fn, ix, t)
@@ -5373,7 +5447,7 @@ find_decls_types_in_node (struct cgraph_node *n, struct free_lang_data_d *fld)
static void
find_decls_types_in_var (struct varpool_node *v, struct free_lang_data_d *fld)
{
- find_decls_types (v->symbol.decl, fld);
+ find_decls_types (v->decl, fld);
}
/* If T needs an assembler name, have one created for it. */
@@ -5533,8 +5607,8 @@ const pass_data pass_data_ipa_free_lang_data =
class pass_ipa_free_lang_data : public simple_ipa_opt_pass
{
public:
- pass_ipa_free_lang_data(gcc::context *ctxt)
- : simple_ipa_opt_pass(pass_data_ipa_free_lang_data, ctxt)
+ pass_ipa_free_lang_data (gcc::context *ctxt)
+ : simple_ipa_opt_pass (pass_data_ipa_free_lang_data, ctxt)
{}
/* opt_pass methods: */
@@ -5976,6 +6050,7 @@ set_type_quals (tree type, int type_quals)
TYPE_READONLY (type) = (type_quals & TYPE_QUAL_CONST) != 0;
TYPE_VOLATILE (type) = (type_quals & TYPE_QUAL_VOLATILE) != 0;
TYPE_RESTRICT (type) = (type_quals & TYPE_QUAL_RESTRICT) != 0;
+ TYPE_ATOMIC (type) = (type_quals & TYPE_QUAL_ATOMIC) != 0;
TYPE_ADDR_SPACE (type) = DECODE_QUAL_ADDR_SPACE (type_quals);
}
@@ -6009,6 +6084,48 @@ check_aligned_type (const_tree cand, const_tree base, unsigned int align)
TYPE_ATTRIBUTES (base)));
}
+/* This function checks to see if TYPE matches the size one of the built-in
+ atomic types, and returns that core atomic type. */
+
+static tree
+find_atomic_core_type (tree type)
+{
+ tree base_atomic_type;
+
+ /* Only handle complete types. */
+ if (TYPE_SIZE (type) == NULL_TREE)
+ return NULL_TREE;
+
+ HOST_WIDE_INT type_size = tree_low_cst (TYPE_SIZE (type), 1);
+ switch (type_size)
+ {
+ case 8:
+ base_atomic_type = atomicQI_type_node;
+ break;
+
+ case 16:
+ base_atomic_type = atomicHI_type_node;
+ break;
+
+ case 32:
+ base_atomic_type = atomicSI_type_node;
+ break;
+
+ case 64:
+ base_atomic_type = atomicDI_type_node;
+ break;
+
+ case 128:
+ base_atomic_type = atomicTI_type_node;
+ break;
+
+ default:
+ base_atomic_type = NULL_TREE;
+ }
+
+ return base_atomic_type;
+}
+
/* 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. */
@@ -6048,6 +6165,19 @@ build_qualified_type (tree type, int type_quals)
t = build_variant_type_copy (type);
set_type_quals (t, type_quals);
+ if (((type_quals & TYPE_QUAL_ATOMIC) == TYPE_QUAL_ATOMIC))
+ {
+ /* See if this object can map to a basic atomic type. */
+ tree atomic_type = find_atomic_core_type (type);
+ if (atomic_type)
+ {
+ /* Ensure the alignment of this type is compatible with
+ the required alignment of the atomic type. */
+ if (TYPE_ALIGN (atomic_type) > TYPE_ALIGN (t))
+ TYPE_ALIGN (t) = TYPE_ALIGN (atomic_type);
+ }
+ }
+
if (TYPE_STRUCTURAL_EQUALITY_P (type))
/* Propagate structural equality. */
SET_TYPE_STRUCTURAL_EQUALITY (t);
@@ -6698,9 +6828,11 @@ attribute_list_contained (const_tree l1, const_tree l2)
/* This CONST_CAST is okay because lookup_attribute does not
modify its argument and the return value is assigned to a
const_tree. */
- for (attr = lookup_ident_attribute (get_attribute_name (t2), CONST_CAST_TREE(l1));
+ for (attr = lookup_ident_attribute (get_attribute_name (t2),
+ CONST_CAST_TREE (l1));
attr != NULL_TREE && !attribute_value_equal (t2, attr);
- attr = lookup_ident_attribute (get_attribute_name (t2), TREE_CHAIN (attr)))
+ attr = lookup_ident_attribute (get_attribute_name (t2),
+ TREE_CHAIN (attr)))
;
if (attr == NULL_TREE)
@@ -6845,17 +6977,6 @@ tree_low_cst (const_tree t, int pos)
return TREE_INT_CST_LOW (t);
}
-/* Return the HOST_WIDE_INT least significant bits of T, a sizetype
- kind INTEGER_CST. This makes sure to properly sign-extend the
- constant. */
-
-HOST_WIDE_INT
-size_low_cst (const_tree t)
-{
- double_int d = tree_to_double_int (t);
- return d.sext (TYPE_PRECISION (TREE_TYPE (t))).low;
-}
-
/* Return the most significant (sign) bit of T. */
int
@@ -6917,24 +7038,6 @@ tree_int_cst_min_precision (tree value, bool unsignedp)
return tree_floor_log2 (value) + 1 + !unsignedp;
}
-/* Compare two constructor-element-type constants. Return 1 if the lists
- are known to be equal; otherwise return 0. */
-
-int
-simple_cst_list_equal (const_tree l1, const_tree l2)
-{
- while (l1 != NULL_TREE && l2 != NULL_TREE)
- {
- if (simple_cst_equal (TREE_VALUE (l1), TREE_VALUE (l2)) != 1)
- return 0;
-
- l1 = TREE_CHAIN (l1);
- l2 = TREE_CHAIN (l2);
- }
-
- return l1 == l2;
-}
-
/* Return truthvalue of whether T1 is the same tree structure as T2.
Return 1 if they are the same.
Return 0 if they are understandably different.
@@ -7298,21 +7401,6 @@ iterative_hash_expr (const_tree t, hashval_t val)
}
return val;
}
- case MEM_REF:
- {
- /* The type of the second operand is relevant, except for
- its top-level qualifiers. */
- tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (t, 1)));
-
- val = iterative_hash_object (TYPE_HASH (type), val);
-
- /* We could use the standard hash computation from this point
- on. */
- val = iterative_hash_object (code, val);
- val = iterative_hash_expr (TREE_OPERAND (t, 1), val);
- val = iterative_hash_expr (TREE_OPERAND (t, 0), val);
- return val;
- }
case FUNCTION_DECL:
/* When referring to a built-in FUNCTION_DECL, use the __builtin__ form.
Otherwise nodes that compare equal according to operand_equal_p might
@@ -7375,29 +7463,6 @@ iterative_hash_expr (const_tree t, hashval_t val)
}
}
-/* Generate a hash value for a pair of expressions. This can be used
- iteratively by passing a previous result as the VAL argument.
-
- The same hash value is always returned for a given pair of expressions,
- regardless of the order in which they are presented. This is useful in
- hashing the operands of commutative functions. */
-
-hashval_t
-iterative_hash_exprs_commutative (const_tree t1,
- const_tree t2, hashval_t val)
-{
- hashval_t one = iterative_hash_expr (t1, 0);
- hashval_t two = iterative_hash_expr (t2, 0);
- hashval_t t;
-
- if (one > two)
- t = one, one = two, two = t;
- val = iterative_hash_hashval_t (one, val);
- val = iterative_hash_hashval_t (two, val);
-
- return val;
-}
-
/* Constructors for pointer, array and function types.
(RECORD_TYPE, UNION_TYPE and ENUMERAL_TYPE nodes are
constructed by language-dependent code, not here.) */
@@ -7539,30 +7604,6 @@ build_reference_type (tree to_type)
return build_reference_type_for_mode (to_type, pointer_mode, false);
}
-/* Build a type that is compatible with t but has no cv quals anywhere
- in its type, thus
-
- const char *const *const * -> char ***. */
-
-tree
-build_type_no_quals (tree t)
-{
- switch (TREE_CODE (t))
- {
- case POINTER_TYPE:
- return build_pointer_type_for_mode (build_type_no_quals (TREE_TYPE (t)),
- TYPE_MODE (t),
- TYPE_REF_CAN_ALIAS_ALL (t));
- case REFERENCE_TYPE:
- return
- build_reference_type_for_mode (build_type_no_quals (TREE_TYPE (t)),
- TYPE_MODE (t),
- TYPE_REF_CAN_ALIAS_ALL (t));
- default:
- return TYPE_MAIN_VARIANT (t);
- }
-}
-
#define MAX_INT_CACHED_PREC \
(HOST_BITS_PER_WIDE_INT > 64 ? HOST_BITS_PER_WIDE_INT : 64)
static GTY(()) tree nonstandard_integer_type_cache[2 * MAX_INT_CACHED_PREC + 2];
@@ -7834,9 +7875,9 @@ strip_array_types (tree type)
true) or would not differ from ARGTYPES. */
static tree
-maybe_canonicalize_argtypes(tree argtypes,
- bool *any_structural_p,
- bool *any_noncanonical_p)
+maybe_canonicalize_argtypes (tree argtypes,
+ bool *any_structural_p,
+ bool *any_noncanonical_p)
{
tree arg;
bool any_noncanonical_argtypes_p = false;
@@ -7938,111 +7979,6 @@ build_function_type (tree value_type, tree arg_types)
return t;
}
-/* Build variant of function type ORIG_TYPE skipping ARGS_TO_SKIP and the
- return value if SKIP_RETURN is true. */
-
-static tree
-build_function_type_skip_args (tree orig_type, bitmap args_to_skip,
- bool skip_return)
-{
- tree new_type = NULL;
- tree args, new_args = NULL, t;
- tree new_reversed;
- int i = 0;
-
- for (args = TYPE_ARG_TYPES (orig_type); args && args != void_list_node;
- args = TREE_CHAIN (args), i++)
- if (!args_to_skip || !bitmap_bit_p (args_to_skip, i))
- new_args = tree_cons (NULL_TREE, TREE_VALUE (args), new_args);
-
- new_reversed = nreverse (new_args);
- if (args)
- {
- if (new_reversed)
- TREE_CHAIN (new_args) = void_list_node;
- else
- new_reversed = void_list_node;
- }
-
- /* Use copy_node to preserve as much as possible from original type
- (debug info, attribute lists etc.)
- Exception is METHOD_TYPEs must have THIS argument.
- When we are asked to remove it, we need to build new FUNCTION_TYPE
- instead. */
- if (TREE_CODE (orig_type) != METHOD_TYPE
- || !args_to_skip
- || !bitmap_bit_p (args_to_skip, 0))
- {
- new_type = build_distinct_type_copy (orig_type);
- TYPE_ARG_TYPES (new_type) = new_reversed;
- }
- else
- {
- new_type
- = build_distinct_type_copy (build_function_type (TREE_TYPE (orig_type),
- new_reversed));
- TYPE_CONTEXT (new_type) = TYPE_CONTEXT (orig_type);
- }
-
- if (skip_return)
- TREE_TYPE (new_type) = void_type_node;
-
- /* This is a new type, not a copy of an old type. Need to reassociate
- variants. We can handle everything except the main variant lazily. */
- t = TYPE_MAIN_VARIANT (orig_type);
- if (t != orig_type)
- {
- t = build_function_type_skip_args (t, args_to_skip, skip_return);
- TYPE_MAIN_VARIANT (new_type) = t;
- TYPE_NEXT_VARIANT (new_type) = TYPE_NEXT_VARIANT (t);
- TYPE_NEXT_VARIANT (t) = new_type;
- }
- else
- {
- TYPE_MAIN_VARIANT (new_type) = new_type;
- TYPE_NEXT_VARIANT (new_type) = NULL;
- }
-
- return new_type;
-}
-
-/* Build variant of function decl ORIG_DECL skipping ARGS_TO_SKIP and the
- return value if SKIP_RETURN is true.
-
- Arguments from DECL_ARGUMENTS list can't be removed now, since they are
- linked by TREE_CHAIN directly. The caller is responsible for eliminating
- them when they are being duplicated (i.e. copy_arguments_for_versioning). */
-
-tree
-build_function_decl_skip_args (tree orig_decl, bitmap args_to_skip,
- bool skip_return)
-{
- tree new_decl = copy_node (orig_decl);
- tree new_type;
-
- new_type = TREE_TYPE (orig_decl);
- if (prototype_p (new_type)
- || (skip_return && !VOID_TYPE_P (TREE_TYPE (new_type))))
- new_type
- = build_function_type_skip_args (new_type, args_to_skip, skip_return);
- TREE_TYPE (new_decl) = new_type;
-
- /* For declarations setting DECL_VINDEX (i.e. methods)
- we expect first argument to be THIS pointer. */
- if (args_to_skip && bitmap_bit_p (args_to_skip, 0))
- DECL_VINDEX (new_decl) = NULL_TREE;
-
- /* When signature changes, we need to clear builtin info. */
- if (DECL_BUILT_IN (new_decl)
- && args_to_skip
- && !bitmap_empty_p (args_to_skip))
- {
- DECL_BUILT_IN_CLASS (new_decl) = NOT_BUILT_IN;
- DECL_FUNCTION_CODE (new_decl) = (enum built_in_function) 0;
- }
- return new_decl;
-}
-
/* Build a function type. The RETURN_TYPE is the type returned by the
function. If VAARGS is set, no void_type_node is appended to the
the list. ARGP must be always be terminated be a NULL_TREE. */
@@ -9005,7 +8941,8 @@ dump_tree_statistics (void)
fprintf (stderr, "Code Nodes\n");
fprintf (stderr, "----------------------------\n");
for (i = 0; i < (int) MAX_TREE_CODES; i++)
- fprintf (stderr, "%-20s %7d\n", tree_code_name[i], tree_code_counts[i]);
+ fprintf (stderr, "%-20s %7d\n", get_tree_code_name ((enum tree_code) i),
+ tree_code_counts[i]);
fprintf (stderr, "----------------------------\n");
ssanames_print_statistics ();
phinodes_print_statistics ();
@@ -9175,11 +9112,11 @@ tree_check_failed (const_tree node, const char *file,
va_list args;
const char *buffer;
unsigned length = 0;
- int code;
+ enum tree_code code;
va_start (args, function);
- while ((code = va_arg (args, int)))
- length += 4 + strlen (tree_code_name[code]);
+ while ((code = (enum tree_code) va_arg (args, int)))
+ length += 4 + strlen (get_tree_code_name (code));
va_end (args);
if (length)
{
@@ -9188,14 +9125,14 @@ tree_check_failed (const_tree node, const char *file,
length += strlen ("expected ");
buffer = tmp = (char *) alloca (length);
length = 0;
- while ((code = va_arg (args, int)))
+ while ((code = (enum tree_code) va_arg (args, int)))
{
const char *prefix = length ? " or " : "expected ";
strcpy (tmp + length, prefix);
length += strlen (prefix);
- strcpy (tmp + length, tree_code_name[code]);
- length += strlen (tree_code_name[code]);
+ strcpy (tmp + length, get_tree_code_name (code));
+ length += strlen (get_tree_code_name (code));
}
va_end (args);
}
@@ -9203,7 +9140,7 @@ tree_check_failed (const_tree node, const char *file,
buffer = "unexpected node";
internal_error ("tree check: %s, have %s in %s, at %s:%d",
- buffer, tree_code_name[TREE_CODE (node)],
+ buffer, get_tree_code_name (TREE_CODE (node)),
function, trim_filename (file), line);
}
@@ -9218,29 +9155,29 @@ tree_not_check_failed (const_tree node, const char *file,
va_list args;
char *buffer;
unsigned length = 0;
- int code;
+ enum tree_code code;
va_start (args, function);
- while ((code = va_arg (args, int)))
- length += 4 + strlen (tree_code_name[code]);
+ while ((code = (enum tree_code) va_arg (args, int)))
+ length += 4 + strlen (get_tree_code_name (code));
va_end (args);
va_start (args, function);
buffer = (char *) alloca (length);
length = 0;
- while ((code = va_arg (args, int)))
+ while ((code = (enum tree_code) va_arg (args, int)))
{
if (length)
{
strcpy (buffer + length, " or ");
length += 4;
}
- strcpy (buffer + length, tree_code_name[code]);
- length += strlen (tree_code_name[code]);
+ strcpy (buffer + length, get_tree_code_name (code));
+ length += strlen (get_tree_code_name (code));
}
va_end (args);
internal_error ("tree check: expected none of %s, have %s in %s, at %s:%d",
- buffer, tree_code_name[TREE_CODE (node)],
+ buffer, get_tree_code_name (TREE_CODE (node)),
function, trim_filename (file), line);
}
@@ -9255,7 +9192,7 @@ tree_class_check_failed (const_tree node, const enum tree_code_class cl,
("tree check: expected class %qs, have %qs (%s) in %s, at %s:%d",
TREE_CODE_CLASS_STRING (cl),
TREE_CODE_CLASS_STRING (TREE_CODE_CLASS (TREE_CODE (node))),
- tree_code_name[TREE_CODE (node)], function, trim_filename (file), line);
+ get_tree_code_name (TREE_CODE (node)), function, trim_filename (file), line);
}
/* Similar to tree_check_failed, except that instead of specifying a
@@ -9271,7 +9208,7 @@ tree_range_check_failed (const_tree node, const char *file, int line,
unsigned int c;
for (c = c1; c <= c2; ++c)
- length += 4 + strlen (tree_code_name[c]);
+ length += 4 + strlen (get_tree_code_name ((enum tree_code) c));
length += strlen ("expected ");
buffer = (char *) alloca (length);
@@ -9283,12 +9220,12 @@ tree_range_check_failed (const_tree node, const char *file, int line,
strcpy (buffer + length, prefix);
length += strlen (prefix);
- strcpy (buffer + length, tree_code_name[c]);
- length += strlen (tree_code_name[c]);
+ strcpy (buffer + length, get_tree_code_name ((enum tree_code) c));
+ length += strlen (get_tree_code_name ((enum tree_code) c));
}
internal_error ("tree check: %s, have %s in %s, at %s:%d",
- buffer, tree_code_name[TREE_CODE (node)],
+ buffer, get_tree_code_name (TREE_CODE (node)),
function, trim_filename (file), line);
}
@@ -9304,7 +9241,7 @@ tree_not_class_check_failed (const_tree node, const enum tree_code_class cl,
("tree check: did not expect class %qs, have %qs (%s) in %s, at %s:%d",
TREE_CODE_CLASS_STRING (cl),
TREE_CODE_CLASS_STRING (TREE_CODE_CLASS (TREE_CODE (node))),
- tree_code_name[TREE_CODE (node)], function, trim_filename (file), line);
+ get_tree_code_name (TREE_CODE (node)), function, trim_filename (file), line);
}
@@ -9315,7 +9252,7 @@ omp_clause_check_failed (const_tree node, const char *file, int line,
const char *function, enum omp_clause_code code)
{
internal_error ("tree check: expected omp_clause %s, have %s in %s, at %s:%d",
- omp_clause_code_name[code], tree_code_name[TREE_CODE (node)],
+ omp_clause_code_name[code], get_tree_code_name (TREE_CODE (node)),
function, trim_filename (file), line);
}
@@ -9375,8 +9312,8 @@ tree_contains_struct_check_failed (const_tree node,
{
internal_error
("tree check: expected tree that contains %qs structure, have %qs in %s, at %s:%d",
- TS_ENUM_NAME(en),
- tree_code_name[TREE_CODE (node)], function, trim_filename (file), line);
+ TS_ENUM_NAME (en),
+ get_tree_code_name (TREE_CODE (node)), function, trim_filename (file), line);
}
@@ -9399,10 +9336,10 @@ void
tree_operand_check_failed (int idx, const_tree exp, const char *file,
int line, const char *function)
{
- int code = TREE_CODE (exp);
+ enum tree_code code = TREE_CODE (exp);
internal_error
("tree check: accessed operand %d of %s with %d operands in %s, at %s:%d",
- idx + 1, tree_code_name[code], TREE_OPERAND_LENGTH (exp),
+ idx + 1, get_tree_code_name (code), TREE_OPERAND_LENGTH (exp),
function, trim_filename (file), line);
}
@@ -9560,6 +9497,28 @@ make_or_reuse_accum_type (unsigned size, int unsignedp, int satp)
return make_accum_type (size, unsignedp, satp);
}
+
+/* Create an atomic variant node for TYPE. This routine is called
+ during initialization of data types to create the 5 basic atomic
+ types. The generic build_variant_type function requires these to
+ already be set up in order to function properly, so cannot be
+ called from there. */
+
+static tree
+build_atomic_base (tree type)
+{
+ tree t;
+
+ /* Make sure its not already registered. */
+ if ((t = get_qualified_type (type, TYPE_QUAL_ATOMIC)))
+ return t;
+
+ t = build_variant_type_copy (type);
+ set_type_quals (t, TYPE_QUAL_ATOMIC);
+
+ return t;
+}
+
/* Create nodes for all integer types (and error_mark_node) using the sizes
of C datatypes. SIGNED_CHAR specifies whether char is signed,
SHORT_DOUBLE specifies whether double should be of the same precision
@@ -9642,6 +9601,16 @@ build_common_tree_nodes (bool signed_char, bool short_double)
unsigned_intDI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (DImode), 1);
unsigned_intTI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (TImode), 1);
+ /* Don't call build_qualified type for atomics. That routine does
+ special processing for atomics, and until they are initialized
+ it's better not to make that call. */
+
+ atomicQI_type_node = build_atomic_base (unsigned_intQI_type_node);
+ atomicHI_type_node = build_atomic_base (unsigned_intHI_type_node);
+ atomicSI_type_node = build_atomic_base (unsigned_intSI_type_node);
+ atomicDI_type_node = build_atomic_base (unsigned_intDI_type_node);
+ atomicTI_type_node = build_atomic_base (unsigned_intTI_type_node);
+
access_public_node = get_identifier ("public");
access_protected_node = get_identifier ("protected");
access_private_node = get_identifier ("private");
@@ -9664,6 +9633,8 @@ build_common_tree_nodes (bool signed_char, bool short_double)
void_type_node = make_node (VOID_TYPE);
layout_type (void_type_node);
+ pointer_bounds_type_node = targetm.chkp_bound_type ();
+
/* We are not going to have real types in C with less than byte alignment,
so we might as well not have any types that claim to have it. */
TYPE_ALIGN (void_type_node) = BITS_PER_UNIT;
@@ -10477,68 +10448,6 @@ build_call_vec (tree return_type, tree fn, vec<tree, va_gc> *args)
return ret;
}
-
-/* Returns true if it is possible to prove that the index of
- an array access REF (an ARRAY_REF expression) falls into the
- array bounds. */
-
-bool
-in_array_bounds_p (tree ref)
-{
- tree idx = TREE_OPERAND (ref, 1);
- tree min, max;
-
- if (TREE_CODE (idx) != INTEGER_CST)
- return false;
-
- min = array_ref_low_bound (ref);
- max = array_ref_up_bound (ref);
- if (!min
- || !max
- || TREE_CODE (min) != INTEGER_CST
- || TREE_CODE (max) != INTEGER_CST)
- return false;
-
- if (tree_int_cst_lt (idx, min)
- || tree_int_cst_lt (max, idx))
- return false;
-
- return true;
-}
-
-/* Returns true if it is possible to prove that the range of
- an array access REF (an ARRAY_RANGE_REF expression) falls
- into the array bounds. */
-
-bool
-range_in_array_bounds_p (tree ref)
-{
- tree domain_type = TYPE_DOMAIN (TREE_TYPE (ref));
- tree range_min, range_max, min, max;
-
- range_min = TYPE_MIN_VALUE (domain_type);
- range_max = TYPE_MAX_VALUE (domain_type);
- if (!range_min
- || !range_max
- || TREE_CODE (range_min) != INTEGER_CST
- || TREE_CODE (range_max) != INTEGER_CST)
- return false;
-
- min = array_ref_low_bound (ref);
- max = array_ref_up_bound (ref);
- if (!min
- || !max
- || TREE_CODE (min) != INTEGER_CST
- || TREE_CODE (max) != INTEGER_CST)
- return false;
-
- if (tree_int_cst_lt (range_min, min)
- || tree_int_cst_lt (max, range_max))
- return false;
-
- return true;
-}
-
/* Return true if T (assumed to be a DECL) must be assigned a memory
location. */
@@ -11031,7 +10940,8 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data,
unsigned HOST_WIDE_INT idx;
constructor_elt *ce;
- for (idx = 0; vec_safe_iterate(CONSTRUCTOR_ELTS (*tp), idx, &ce); idx++)
+ for (idx = 0; vec_safe_iterate (CONSTRUCTOR_ELTS (*tp), idx, &ce);
+ idx++)
WALK_SUBTREE (ce->value);
}
break;
@@ -11077,7 +10987,14 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data,
case OMP_CLAUSE_NUM_THREADS:
case OMP_CLAUSE_SCHEDULE:
case OMP_CLAUSE_UNIFORM:
+ case OMP_CLAUSE_DEPEND:
+ case OMP_CLAUSE_NUM_TEAMS:
+ case OMP_CLAUSE_THREAD_LIMIT:
+ case OMP_CLAUSE_DEVICE:
+ case OMP_CLAUSE_DIST_SCHEDULE:
case OMP_CLAUSE_SAFELEN:
+ case OMP_CLAUSE_SIMDLEN:
+ case OMP_CLAUSE__LOOPTEMP_:
case OMP_CLAUSE__SIMDUID_:
WALK_SUBTREE (OMP_CLAUSE_OPERAND (*tp, 0));
/* FALLTHRU */
@@ -11087,6 +11004,13 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data,
case OMP_CLAUSE_DEFAULT:
case OMP_CLAUSE_UNTIED:
case OMP_CLAUSE_MERGEABLE:
+ case OMP_CLAUSE_PROC_BIND:
+ case OMP_CLAUSE_INBRANCH:
+ case OMP_CLAUSE_NOTINBRANCH:
+ case OMP_CLAUSE_FOR:
+ case OMP_CLAUSE_PARALLEL:
+ case OMP_CLAUSE_SECTIONS:
+ case OMP_CLAUSE_TASKGROUP:
WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp));
case OMP_CLAUSE_LASTPRIVATE:
@@ -11102,7 +11026,11 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data,
WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp));
}
+ case OMP_CLAUSE_ALIGNED:
case OMP_CLAUSE_LINEAR:
+ case OMP_CLAUSE_FROM:
+ case OMP_CLAUSE_TO:
+ case OMP_CLAUSE_MAP:
WALK_SUBTREE (OMP_CLAUSE_DECL (*tp));
WALK_SUBTREE (OMP_CLAUSE_OPERAND (*tp, 1));
WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp));
@@ -11337,7 +11265,7 @@ stdarg_p (const_tree fntype)
if (!fntype)
return false;
- FOREACH_FUNCTION_ARGS(fntype, t, args_iter)
+ FOREACH_FUNCTION_ARGS (fntype, t, args_iter)
{
n = t;
}
@@ -11486,10 +11414,10 @@ cl_option_hash_eq (const void *x, const void *y)
return (memcmp (xp, yp, len) == 0);
}
-/* Build an OPTIMIZATION_NODE based on the current options. */
+/* Build an OPTIMIZATION_NODE based on the options in OPTS. */
tree
-build_optimization_node (void)
+build_optimization_node (struct gcc_options *opts)
{
tree t;
void **slot;
@@ -11497,7 +11425,7 @@ build_optimization_node (void)
/* Use the cache of optimization nodes. */
cl_optimization_save (TREE_OPTIMIZATION (cl_optimization_node),
- &global_options);
+ opts);
slot = htab_find_slot (cl_option_hash_table, cl_optimization_node, INSERT);
t = (tree) *slot;
@@ -11514,10 +11442,10 @@ build_optimization_node (void)
return t;
}
-/* Build a TARGET_OPTION_NODE based on the current options. */
+/* Build a TARGET_OPTION_NODE based on the options in OPTS. */
tree
-build_target_option_node (void)
+build_target_option_node (struct gcc_options *opts)
{
tree t;
void **slot;
@@ -11525,7 +11453,7 @@ build_target_option_node (void)
/* Use the cache of optimization nodes. */
cl_target_option_save (TREE_TARGET_OPTION (cl_target_option_node),
- &global_options);
+ opts);
slot = htab_find_slot (cl_option_hash_table, cl_target_option_node, INSERT);
t = (tree) *slot;
@@ -11587,17 +11515,6 @@ block_ultimate_origin (const_tree block)
}
}
-/* Return true if T1 and T2 are equivalent lists. */
-
-bool
-list_equal_p (const_tree t1, const_tree t2)
-{
- for (; t1 && t2; t1 = TREE_CHAIN (t1) , t2 = TREE_CHAIN (t2))
- if (TREE_VALUE (t1) != TREE_VALUE (t2))
- return false;
- return !t1 && !t2;
-}
-
/* Return true iff conversion in EXP generates no instruction. Mark
it inline so that we fully inline into the stripping functions even
though we have two uses of this function. */
@@ -12155,4 +12072,175 @@ contains_bitfld_component_ref_p (const_tree ref)
return false;
}
+/* Try to determine whether a TRY_CATCH expression can fall through.
+ This is a subroutine of block_may_fallthru. */
+
+static bool
+try_catch_may_fallthru (const_tree stmt)
+{
+ tree_stmt_iterator i;
+
+ /* If the TRY block can fall through, the whole TRY_CATCH can
+ fall through. */
+ if (block_may_fallthru (TREE_OPERAND (stmt, 0)))
+ return true;
+
+ i = tsi_start (TREE_OPERAND (stmt, 1));
+ switch (TREE_CODE (tsi_stmt (i)))
+ {
+ case CATCH_EXPR:
+ /* We expect to see a sequence of CATCH_EXPR trees, each with a
+ catch expression and a body. The whole TRY_CATCH may fall
+ through iff any of the catch bodies falls through. */
+ for (; !tsi_end_p (i); tsi_next (&i))
+ {
+ if (block_may_fallthru (CATCH_BODY (tsi_stmt (i))))
+ return true;
+ }
+ return false;
+
+ case EH_FILTER_EXPR:
+ /* The exception filter expression only matters if there is an
+ exception. If the exception does not match EH_FILTER_TYPES,
+ we will execute EH_FILTER_FAILURE, and we will fall through
+ if that falls through. If the exception does match
+ EH_FILTER_TYPES, the stack unwinder will continue up the
+ stack, so we will not fall through. We don't know whether we
+ will throw an exception which matches EH_FILTER_TYPES or not,
+ so we just ignore EH_FILTER_TYPES and assume that we might
+ throw an exception which doesn't match. */
+ return block_may_fallthru (EH_FILTER_FAILURE (tsi_stmt (i)));
+
+ default:
+ /* This case represents statements to be executed when an
+ exception occurs. Those statements are implicitly followed
+ by a RESX statement to resume execution after the exception.
+ So in this case the TRY_CATCH never falls through. */
+ return false;
+ }
+}
+
+/* Try to determine if we can fall out of the bottom of BLOCK. This guess
+ need not be 100% accurate; simply be conservative and return true if we
+ don't know. This is used only to avoid stupidly generating extra code.
+ If we're wrong, we'll just delete the extra code later. */
+
+bool
+block_may_fallthru (const_tree block)
+{
+ /* This CONST_CAST is okay because expr_last returns its argument
+ unmodified and we assign it to a const_tree. */
+ const_tree stmt = expr_last (CONST_CAST_TREE (block));
+
+ switch (stmt ? TREE_CODE (stmt) : ERROR_MARK)
+ {
+ case GOTO_EXPR:
+ case RETURN_EXPR:
+ /* Easy cases. If the last statement of the block implies
+ control transfer, then we can't fall through. */
+ return false;
+
+ case SWITCH_EXPR:
+ /* If SWITCH_LABELS is set, this is lowered, and represents a
+ branch to a selected label and hence can not fall through.
+ Otherwise SWITCH_BODY is set, and the switch can fall
+ through. */
+ return SWITCH_LABELS (stmt) == NULL_TREE;
+
+ case COND_EXPR:
+ if (block_may_fallthru (COND_EXPR_THEN (stmt)))
+ return true;
+ return block_may_fallthru (COND_EXPR_ELSE (stmt));
+
+ case BIND_EXPR:
+ return block_may_fallthru (BIND_EXPR_BODY (stmt));
+
+ case TRY_CATCH_EXPR:
+ return try_catch_may_fallthru (stmt);
+
+ case TRY_FINALLY_EXPR:
+ /* The finally clause is always executed after the try clause,
+ so if it does not fall through, then the try-finally will not
+ fall through. Otherwise, if the try clause does not fall
+ through, then when the finally clause falls through it will
+ resume execution wherever the try clause was going. So the
+ whole try-finally will only fall through if both the try
+ clause and the finally clause fall through. */
+ return (block_may_fallthru (TREE_OPERAND (stmt, 0))
+ && block_may_fallthru (TREE_OPERAND (stmt, 1)));
+
+ case MODIFY_EXPR:
+ if (TREE_CODE (TREE_OPERAND (stmt, 1)) == CALL_EXPR)
+ stmt = TREE_OPERAND (stmt, 1);
+ else
+ return true;
+ /* FALLTHRU */
+
+ case CALL_EXPR:
+ /* Functions that do not return do not fall through. */
+ return (call_expr_flags (stmt) & ECF_NORETURN) == 0;
+
+ case CLEANUP_POINT_EXPR:
+ return block_may_fallthru (TREE_OPERAND (stmt, 0));
+
+ case TARGET_EXPR:
+ return block_may_fallthru (TREE_OPERAND (stmt, 1));
+
+ case ERROR_MARK:
+ return true;
+
+ default:
+ return lang_hooks.block_may_fallthru (stmt);
+ }
+}
+
+/* True if we are using EH to handle cleanups. */
+static bool using_eh_for_cleanups_flag = false;
+
+/* This routine is called from front ends to indicate eh should be used for
+ cleanups. */
+void
+using_eh_for_cleanups (void)
+{
+ using_eh_for_cleanups_flag = true;
+}
+
+/* Query whether EH is used for cleanups. */
+bool
+using_eh_for_cleanups_p (void)
+{
+ return using_eh_for_cleanups_flag;
+}
+
+/* Wrapper for tree_code_name to ensure that tree code is valid */
+const char *
+get_tree_code_name (enum tree_code code)
+{
+ const char *invalid = "<invalid tree code>";
+
+ if (code >= MAX_TREE_CODES)
+ return invalid;
+
+ return tree_code_name[code];
+}
+
+/* Drops the TREE_OVERFLOW flag from T. */
+
+tree
+drop_tree_overflow (tree t)
+{
+ gcc_checking_assert (TREE_OVERFLOW (t));
+
+ /* For tree codes with a sharing machinery re-build the result. */
+ if (TREE_CODE (t) == INTEGER_CST)
+ return build_int_cst_wide (TREE_TYPE (t),
+ TREE_INT_CST_LOW (t), TREE_INT_CST_HIGH (t));
+
+ /* Otherwise, as all tcc_constants are possibly shared, copy the node
+ and drop the flag. */
+ t = copy_node (t);
+ TREE_OVERFLOW (t) = 0;
+ return t;
+}
+
#include "gt-tree.h"
diff --git a/gcc/tree.def b/gcc/tree.def
index f825aad5355..6763e78835f 100644
--- a/gcc/tree.def
+++ b/gcc/tree.def
@@ -232,6 +232,11 @@ DEFTREECODE (QUAL_UNION_TYPE, "qual_union_type", tcc_type, 0)
/* The void type in C */
DEFTREECODE (VOID_TYPE, "void_type", tcc_type, 0)
+/* Type to hold bounds for a pointer.
+ Has TYPE_PRECISION component to specify number of bits used
+ by this type. */
+DEFTREECODE (POINTER_BOUNDS_TYPE, "pointer_bounds_type", tcc_type, 0)
+
/* Type of functions. Special fields:
TREE_TYPE type of value returned.
TYPE_ARG_TYPES list of types of arguments expected.
@@ -440,10 +445,12 @@ DEFTREECODE (INDIRECT_REF, "indirect_ref", tcc_reference, 1)
OBJ_TYPE_REF_TOKEN: An integer index to the virtual method table. */
DEFTREECODE (OBJ_TYPE_REF, "obj_type_ref", tcc_expression, 3)
-/* Constructor: return an aggregate value made from specified components.
- In C, this is used only for structure and array initializers.
- The operand is a sequence of component values made out of a VEC of
- struct constructor_elt.
+/* 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.
@@ -452,8 +459,9 @@ DEFTREECODE (OBJ_TYPE_REF, "obj_type_ref", tcc_expression, 3)
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.)
- For RECORD_TYPE, UNION_TYPE, or QUAL_UNION_TYPE:
- The field INDEX of each node is a FIELD_DECL. */
+ 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
@@ -1034,6 +1042,25 @@ DEFTREECODE (OMP_FOR, "omp_for", tcc_statement, 6)
Operands like for OMP_FOR. */
DEFTREECODE (OMP_SIMD, "omp_simd", tcc_statement, 6)
+/* OpenMP - #pragma omp distribute [clause1 ... clauseN]
+ Operands like for OMP_FOR. */
+DEFTREECODE (OMP_DISTRIBUTE, "omp_distribute", tcc_statement, 6)
+
+/* 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. */
@@ -1052,6 +1079,10 @@ DEFTREECODE (OMP_SECTION, "omp_section", tcc_statement, 1)
Operand 0: OMP_MASTER_BODY: Master section body. */
DEFTREECODE (OMP_MASTER, "omp_master", tcc_statement, 1)
+/* OpenMP - #pragma omp taskgroup
+ Operand 0: OMP_TASKGROUP_BODY: Taskgroup body. */
+DEFTREECODE (OMP_TASKGROUP, "omp_taskgroup", tcc_statement, 1)
+
/* OpenMP - #pragma omp ordered
Operand 0: OMP_ORDERED_BODY: Master section body. */
DEFTREECODE (OMP_ORDERED, "omp_ordered", tcc_statement, 1)
@@ -1061,6 +1092,13 @@ DEFTREECODE (OMP_ORDERED, "omp_ordered", tcc_statement, 1)
Operand 1: OMP_CRITICAL_NAME: Identifier for critical section. */
DEFTREECODE (OMP_CRITICAL, "omp_critical", tcc_statement, 2)
+/* 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)
+
+/* 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.
@@ -1231,6 +1269,18 @@ 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 id. */
+DEFTREECODE (ANNOTATE_EXPR, "annotate_expr", tcc_expression, 2)
+
+/* Cilk spawn statement
+ Operand 0 is the CALL_EXPR. */
+DEFTREECODE (CILK_SPAWN_STMT, "cilk_spawn_stmt", tcc_statement, 1)
+
+/* Cilk Sync statement: Does not have any operands. */
+DEFTREECODE (CILK_SYNC_STMT, "cilk_sync_stmt", tcc_statement, 0)
+
/*
Local variables:
mode:c
diff --git a/gcc/tree.h b/gcc/tree.h
index a263a2cf46a..3633caf1839 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -90,25 +90,25 @@ along with GCC; see the file COPYING3. If not see
#define TREE_CODE_CLASS(CODE) tree_code_type[(int) (CODE)]
-/* Nonzero if CODE represents an exceptional code. */
+/* Nonzero if NODE represents an exceptional code. */
-#define EXCEPTIONAL_CLASS_P(CODE)\
- (TREE_CODE_CLASS (TREE_CODE (CODE)) == tcc_exceptional)
+#define EXCEPTIONAL_CLASS_P(NODE)\
+ (TREE_CODE_CLASS (TREE_CODE (NODE)) == tcc_exceptional)
-/* Nonzero if CODE represents a constant. */
+/* Nonzero if NODE represents a constant. */
-#define CONSTANT_CLASS_P(CODE)\
- (TREE_CODE_CLASS (TREE_CODE (CODE)) == tcc_constant)
+#define CONSTANT_CLASS_P(NODE)\
+ (TREE_CODE_CLASS (TREE_CODE (NODE)) == tcc_constant)
-/* Nonzero if CODE represents a type. */
+/* Nonzero if NODE represents a type. */
-#define TYPE_P(CODE)\
- (TREE_CODE_CLASS (TREE_CODE (CODE)) == tcc_type)
+#define TYPE_P(NODE)\
+ (TREE_CODE_CLASS (TREE_CODE (NODE)) == tcc_type)
-/* Nonzero if CODE represents a declaration. */
+/* Nonzero if NODE represents a declaration. */
-#define DECL_P(CODE)\
- (TREE_CODE_CLASS (TREE_CODE (CODE)) == tcc_declaration)
+#define DECL_P(NODE)\
+ (TREE_CODE_CLASS (TREE_CODE (NODE)) == tcc_declaration)
/* True if NODE designates a variable declaration. */
#define VAR_P(NODE) \
@@ -119,52 +119,52 @@ along with GCC; see the file COPYING3. If not see
#define VAR_OR_FUNCTION_DECL_P(DECL)\
(TREE_CODE (DECL) == VAR_DECL || TREE_CODE (DECL) == FUNCTION_DECL)
-/* Nonzero if CODE represents a INDIRECT_REF. Keep these checks in
+/* Nonzero if NODE represents a INDIRECT_REF. Keep these checks in
ascending code order. */
-#define INDIRECT_REF_P(CODE)\
- (TREE_CODE (CODE) == INDIRECT_REF)
+#define INDIRECT_REF_P(NODE)\
+ (TREE_CODE (NODE) == INDIRECT_REF)
-/* Nonzero if CODE represents a reference. */
+/* Nonzero if NODE represents a reference. */
-#define REFERENCE_CLASS_P(CODE)\
- (TREE_CODE_CLASS (TREE_CODE (CODE)) == tcc_reference)
+#define REFERENCE_CLASS_P(NODE)\
+ (TREE_CODE_CLASS (TREE_CODE (NODE)) == tcc_reference)
-/* Nonzero if CODE represents a comparison. */
+/* Nonzero if NODE represents a comparison. */
-#define COMPARISON_CLASS_P(CODE)\
- (TREE_CODE_CLASS (TREE_CODE (CODE)) == tcc_comparison)
+#define COMPARISON_CLASS_P(NODE)\
+ (TREE_CODE_CLASS (TREE_CODE (NODE)) == tcc_comparison)
-/* Nonzero if CODE represents a unary arithmetic expression. */
+/* Nonzero if NODE represents a unary arithmetic expression. */
-#define UNARY_CLASS_P(CODE)\
- (TREE_CODE_CLASS (TREE_CODE (CODE)) == tcc_unary)
+#define UNARY_CLASS_P(NODE)\
+ (TREE_CODE_CLASS (TREE_CODE (NODE)) == tcc_unary)
-/* Nonzero if CODE represents a binary arithmetic expression. */
+/* Nonzero if NODE represents a binary arithmetic expression. */
-#define BINARY_CLASS_P(CODE)\
- (TREE_CODE_CLASS (TREE_CODE (CODE)) == tcc_binary)
+#define BINARY_CLASS_P(NODE)\
+ (TREE_CODE_CLASS (TREE_CODE (NODE)) == tcc_binary)
-/* Nonzero if CODE represents a statement expression. */
+/* Nonzero if NODE represents a statement expression. */
-#define STATEMENT_CLASS_P(CODE)\
- (TREE_CODE_CLASS (TREE_CODE (CODE)) == tcc_statement)
+#define STATEMENT_CLASS_P(NODE)\
+ (TREE_CODE_CLASS (TREE_CODE (NODE)) == tcc_statement)
-/* Nonzero if CODE represents a function call-like expression with a
+/* Nonzero if NODE represents a function call-like expression with a
variable-length operand vector. */
-#define VL_EXP_CLASS_P(CODE)\
- (TREE_CODE_CLASS (TREE_CODE (CODE)) == tcc_vl_exp)
+#define VL_EXP_CLASS_P(NODE)\
+ (TREE_CODE_CLASS (TREE_CODE (NODE)) == tcc_vl_exp)
-/* Nonzero if CODE represents any other expression. */
+/* Nonzero if NODE represents any other expression. */
-#define EXPRESSION_CLASS_P(CODE)\
- (TREE_CODE_CLASS (TREE_CODE (CODE)) == tcc_expression)
+#define EXPRESSION_CLASS_P(NODE)\
+ (TREE_CODE_CLASS (TREE_CODE (NODE)) == tcc_expression)
-/* Returns nonzero iff CODE represents a type or declaration. */
+/* Returns nonzero iff NODE represents a type or declaration. */
-#define IS_TYPE_OR_DECL_P(CODE)\
- (TYPE_P (CODE) || DECL_P (CODE))
+#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. */
@@ -542,6 +542,21 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int,
/* Nonzero if this type is a complete type. */
#define COMPLETE_TYPE_P(NODE) (TYPE_SIZE (NODE) != NULL_TREE)
+/* Nonzero if this type is a pointer bounds type. */
+#define POINTER_BOUNDS_TYPE_P(NODE) \
+ (TREE_CODE (NODE) == POINTER_BOUNDS_TYPE)
+
+/* Nonzero if this node has a pointer bounds type. */
+#define POINTER_BOUNDS_P(NODE) \
+ (POINTER_BOUNDS_TYPE_P (TREE_TYPE (NODE)))
+
+/* Nonzero if this type supposes bounds existence. */
+#define BOUNDED_TYPE_P(type) (POINTER_TYPE_P (type))
+
+/* Nonzero for objects with bounded type. */
+#define BOUNDED_P(node) \
+ BOUNDED_TYPE_P (TREE_TYPE (node))
+
/* Nonzero if this type is the (possibly qualified) void type. */
#define VOID_TYPE_P(NODE) (TREE_CODE (NODE) == VOID_TYPE)
@@ -577,7 +592,7 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int,
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)
+ (CALL_EXPR_CHECK (NODE)->base.addressable_flag)
/* Used as a temporary field on a CASE_LABEL_EXPR to indicate that the
CASE_LOW operand has been processed. */
@@ -585,9 +600,9 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int,
(CASE_LABEL_EXPR_CHECK (NODE)->base.addressable_flag)
#define PREDICT_EXPR_OUTCOME(NODE) \
- ((enum prediction) (PREDICT_EXPR_CHECK(NODE)->base.addressable_flag))
+ ((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)
+ (PREDICT_EXPR_CHECK (NODE)->base.addressable_flag = (int) OUTCOME)
#define PREDICT_EXPR_PREDICTOR(NODE) \
((enum br_predictor)tree_low_cst (TREE_OPERAND (PREDICT_EXPR_CHECK (NODE), 0), 0))
@@ -659,7 +674,7 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int,
/* 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)
+#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. */
@@ -669,7 +684,7 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int,
/* 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)
+ (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.
@@ -786,6 +801,9 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int,
#define CALL_EXPR_RETURN_SLOT_OPT(NODE) \
(CALL_EXPR_CHECK (NODE)->base.private_flag)
+/* Cilk keywords accessors. */
+#define CILK_SPAWN_FN(NODE) TREE_OPERAND (CILK_SPAWN_STMT_CHECK (NODE), 0)
+
/* 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). */
@@ -848,19 +866,19 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int,
/* 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)
+ (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)
+ (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)
+ (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)
+ (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)
+ (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)
+ (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)
+ (TREE_NOT_CHECK2 (NODE, TREE_VEC, SSA_NAME)->base.u.bits.lang_flag_6)
/* Define additional fields and accessors for nodes representing constants. */
@@ -939,6 +957,8 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int,
(&(*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
@@ -1131,7 +1151,7 @@ extern void protected_set_expr_location (tree, location_t);
#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_nargs(NODE) (VL_EXP_OPERAND_LENGTH (NODE) - 3)
/* 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
@@ -1167,12 +1187,13 @@ extern void protected_set_expr_location (tree, location_t);
#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_FOR_BODY(NODE) TREE_OPERAND (OMP_FOR_CHECK (NODE), 0)
-#define OMP_FOR_CLAUSES(NODE) TREE_OPERAND (OMP_FOR_CHECK (NODE), 1)
-#define OMP_FOR_INIT(NODE) TREE_OPERAND (OMP_FOR_CHECK (NODE), 2)
-#define OMP_FOR_COND(NODE) TREE_OPERAND (OMP_FOR_CHECK (NODE), 3)
-#define OMP_FOR_INCR(NODE) TREE_OPERAND (OMP_FOR_CHECK (NODE), 4)
-#define OMP_FOR_PRE_BODY(NODE) TREE_OPERAND (OMP_FOR_CHECK (NODE), 5)
+#define OMP_LOOP_CHECK(NODE) TREE_RANGE_CHECK (NODE, OMP_FOR, OMP_DISTRIBUTE)
+#define OMP_FOR_BODY(NODE) TREE_OPERAND (OMP_LOOP_CHECK (NODE), 0)
+#define OMP_FOR_CLAUSES(NODE) TREE_OPERAND (OMP_LOOP_CHECK (NODE), 1)
+#define OMP_FOR_INIT(NODE) TREE_OPERAND (OMP_LOOP_CHECK (NODE), 2)
+#define OMP_FOR_COND(NODE) TREE_OPERAND (OMP_LOOP_CHECK (NODE), 3)
+#define OMP_FOR_INCR(NODE) TREE_OPERAND (OMP_LOOP_CHECK (NODE), 4)
+#define OMP_FOR_PRE_BODY(NODE) TREE_OPERAND (OMP_LOOP_CHECK (NODE), 5)
#define OMP_SECTIONS_BODY(NODE) TREE_OPERAND (OMP_SECTIONS_CHECK (NODE), 0)
#define OMP_SECTIONS_CLAUSES(NODE) TREE_OPERAND (OMP_SECTIONS_CHECK (NODE), 1)
@@ -1184,16 +1205,37 @@ extern void protected_set_expr_location (tree, location_t);
#define OMP_MASTER_BODY(NODE) TREE_OPERAND (OMP_MASTER_CHECK (NODE), 0)
+#define OMP_TASKGROUP_BODY(NODE) TREE_OPERAND (OMP_TASKGROUP_CHECK (NODE), 0)
+
#define OMP_ORDERED_BODY(NODE) TREE_OPERAND (OMP_ORDERED_CHECK (NODE), 0)
#define OMP_CRITICAL_BODY(NODE) TREE_OPERAND (OMP_CRITICAL_CHECK (NODE), 0)
#define OMP_CRITICAL_NAME(NODE) TREE_OPERAND (OMP_CRITICAL_CHECK (NODE), 1)
+#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_CLAUSE_SIZE(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_RANGE_CHECK (OMP_CLAUSE_CHECK (NODE), \
+ OMP_CLAUSE_FROM, \
+ OMP_CLAUSE_MAP), 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_UNIFORM), 0)
+ OMP_CLAUSE__LOOPTEMP_), 0)
#define OMP_CLAUSE_HAS_LOCATION(NODE) \
(LOCATION_LOCUS ((OMP_CLAUSE_CHECK (NODE))->omp_clause.locus) \
!= UNKNOWN_LOCATION)
@@ -1209,6 +1251,12 @@ extern void protected_set_expr_location (tree, location_t);
#define OMP_PARALLEL_COMBINED(NODE) \
(OMP_PARALLEL_CHECK (NODE)->base.private_flag)
+/* True if OMP_ATOMIC* is supposed to be sequentially consistent
+ as opposed to relaxed. */
+#define OMP_ATOMIC_SEQ_CST(NODE) \
+ (TREE_RANGE_CHECK (NODE, OMP_ATOMIC, \
+ OMP_ATOMIC_CAPTURE_NEW)->base.private_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. */
@@ -1240,6 +1288,21 @@ extern void protected_set_expr_location (tree, location_t);
#define OMP_CLAUSE_SCHEDULE_CHUNK_EXPR(NODE) \
OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_SCHEDULE), 0)
+#define OMP_CLAUSE_DEPEND_KIND(NODE) \
+ (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_DEPEND)->omp_clause.subcode.depend_kind)
+
+#define OMP_CLAUSE_MAP_KIND(NODE) \
+ (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_MAP)->omp_clause.subcode.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
+ correspoidng OMP_CLAUSE_MAP_POINTER clause 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)
+
+#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_COLLAPSE_EXPR(NODE) \
OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_COLLAPSE), 0)
#define OMP_CLAUSE_COLLAPSE_ITERVAR(NODE) \
@@ -1260,6 +1323,11 @@ extern void protected_set_expr_location (tree, location_t);
#define OMP_CLAUSE_REDUCTION_PLACEHOLDER(NODE) \
OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_REDUCTION), 3)
+/* 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_SUBCODE_CHECK (NODE, OMP_CLAUSE_REDUCTION)->base.public_flag)
+
/* 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) \
@@ -1273,9 +1341,29 @@ extern void protected_set_expr_location (tree, location_t);
#define OMP_CLAUSE_LINEAR_STEP(NODE) \
OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_LINEAR), 1)
+#define OMP_CLAUSE_ALIGNED_ALIGNMENT(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_ALIGNED), 1)
+
+#define OMP_CLAUSE_NUM_TEAMS_EXPR(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_NUM_TEAMS), 0)
+
+#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)
@@ -1336,7 +1424,11 @@ extern void protected_set_expr_location (tree, location_t);
/* Attributes for SSA_NAMEs for pointer-type variables. */
#define SSA_NAME_PTR_INFO(N) \
- SSA_NAME_CHECK (N)->ssa_name.ptr_info
+ SSA_NAME_CHECK (N)->ssa_name.info.ptr_info
+
+/* 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
@@ -1347,9 +1439,6 @@ extern void protected_set_expr_location (tree, location_t);
#define OMP_CLAUSE_SET_CODE(NODE, CODE) \
((OMP_CLAUSE_CHECK (NODE))->omp_clause.code = (CODE))
-#define OMP_CLAUSE_CODE(NODE) \
- (OMP_CLAUSE_CHECK (NODE))->omp_clause.code
-
#define OMP_CLAUSE_OPERAND(NODE, I) \
OMP_CLAUSE_ELT_CHECK (NODE, I)
@@ -1511,6 +1600,9 @@ extern enum machine_mode vector_type_mode (const_tree);
/* 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)
@@ -1540,6 +1632,7 @@ extern enum machine_mode vector_type_mode (const_tree);
#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)))))
@@ -1547,6 +1640,14 @@ extern enum machine_mode vector_type_mode (const_tree);
#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. */
@@ -1650,10 +1751,10 @@ extern enum machine_mode vector_type_mode (const_tree);
#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_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_VALUES_RAW(NODE) (TYPE_CHECK (NODE)->type_non_common.values)
#define TYPE_METHODS(NODE) \
(RECORD_OR_UNION_CHECK (NODE)->type_non_common.maxval)
@@ -1682,11 +1783,11 @@ extern enum machine_mode vector_type_mode (const_tree);
/* 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.binfo)
+#define TYPE_BINFO(NODE) (RECORD_OR_UNION_CHECK (NODE)->type_non_common.binfo)
/* For non record and union types, used in a language-dependent way. */
#define TYPE_LANG_SLOT_1(NODE) \
- (NOT_RECORD_OR_UNION_CHECK(NODE)->type_non_common.binfo)
+ (NOT_RECORD_OR_UNION_CHECK (NODE)->type_non_common.binfo)
/* Define accessor macros for information about type inheritance
and basetypes.
@@ -1709,16 +1810,16 @@ extern enum machine_mode vector_type_mode (const_tree);
#define BINFO_VIRTUAL_P(NODE) (TREE_BINFO_CHECK (NODE)->base.static_flag)
/* Flags for language dependent use. */
-#define BINFO_MARKED(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))
+#define BINFO_MARKED(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))
+#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)
@@ -1726,19 +1827,19 @@ extern enum machine_mode vector_type_mode (const_tree);
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(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)
+#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)
+#define BINFO_VIRTUALS(NODE) (TREE_BINFO_CHECK (NODE)->binfo.virtuals)
/* A vector of binfos for the direct basetypes inherited by this
basetype.
@@ -1746,7 +1847,7 @@ extern enum machine_mode vector_type_mode (const_tree);
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)
+#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 ())
@@ -1764,12 +1865,13 @@ extern enum machine_mode vector_type_mode (const_tree);
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)
+#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_ACCESSES(NODE) \
+ (TREE_BINFO_CHECK (NODE)->binfo.base_accesses)
#define BINFO_BASE_ACCESS(NODE,N) \
(*BINFO_BASE_ACCESSES (NODE))[(N)]
@@ -1778,18 +1880,18 @@ extern enum machine_mode vector_type_mode (const_tree);
/* 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)
+#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)
+#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)
+ (TREE_BINFO_CHECK (NODE)->binfo.inheritance)
/* Define fields and accessors for nodes representing declared names. */
@@ -2584,16 +2686,16 @@ extern vec<tree, va_gc> **decl_debug_args_insert (tree);
#define TREE_OPTIMIZATION_BASE_OPTABS(NODE) \
(OPTIMIZATION_NODE_CHECK (NODE)->optimization.base_optabs)
-/* Return a tree node that encapsulates the current optimization options. */
-extern tree build_optimization_node (void);
+/* Return a tree node that encapsulates the optimization options in OPTS. */
+extern tree build_optimization_node (struct gcc_options *opts);
extern void init_tree_optimization_optabs (tree);
#define TREE_TARGET_OPTION(NODE) \
(&TARGET_OPTION_NODE_CHECK (NODE)->target_option.opts)
-/* Return a tree node that encapsulates the current target options. */
-extern tree build_target_option_node (void);
+/* Return a tree node that encapsulates the target options in OPTS. */
+extern tree build_target_option_node (struct gcc_options *opts);
#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
@@ -2714,7 +2816,7 @@ 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)
+ if (tree_contains_struct[TREE_CODE (__t)][__s] != 1)
tree_contains_struct_check_failed (__t, __s, __f, __l, __g);
return __t;
}
@@ -2723,7 +2825,7 @@ 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)
+ if (TREE_CODE_CLASS (TREE_CODE (__t)) != __class)
tree_class_check_failed (__t, __class, __f, __l, __g);
return __t;
}
@@ -2924,7 +3026,7 @@ 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)
+ if (tree_contains_struct[TREE_CODE (__t)][__s] != 1)
tree_contains_struct_check_failed (__t, __s, __f, __l, __g);
return __t;
}
@@ -2933,7 +3035,7 @@ 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)
+ if (TREE_CODE_CLASS (TREE_CODE (__t)) != __class)
tree_class_check_failed (__t, __class, __f, __l, __g);
return __t;
}
@@ -3088,6 +3190,12 @@ tree_operand_check_code (const_tree __t, enum tree_code __code, int __i,
#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]
@@ -3123,6 +3231,8 @@ tree_operand_check_code (const_tree __t, enum tree_code __code, int __i,
#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 pointer_bounds_type_node global_trees[TI_POINTER_BOUNDS_TYPE]
+
#define void_type_node global_trees[TI_VOID_TYPE]
/* The C type `void *'. */
#define ptr_type_node global_trees[TI_PTR_TYPE]
@@ -3277,8 +3387,6 @@ tree_operand_check_code (const_tree __t, enum tree_code __code, int __i,
|| ((NODE) && TREE_TYPE ((NODE)) == error_mark_node))
extern tree decl_assembler_name (tree);
-extern bool decl_assembler_name_equal (tree decl, const_tree asmname);
-extern hashval_t decl_assembler_name_hash (const_tree asmname);
/* 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. */
@@ -3472,21 +3580,20 @@ extern tree build_all_ones_cst (tree);
extern tree build_zero_cst (tree);
extern tree build_string (int, const char *);
extern tree build_tree_list_stat (tree, tree MEM_STAT_DECL);
-#define build_tree_list(t,q) build_tree_list_stat(t,q MEM_STAT_INFO)
+#define build_tree_list(t, q) build_tree_list_stat (t, q MEM_STAT_INFO)
extern tree build_tree_list_vec_stat (const vec<tree, va_gc> *MEM_STAT_DECL);
#define build_tree_list_vec(v) build_tree_list_vec_stat (v MEM_STAT_INFO)
extern tree build_decl_stat (location_t, enum tree_code,
tree, tree MEM_STAT_DECL);
extern tree build_fn_decl (const char *, tree);
-#define build_decl(l,c,t,q) build_decl_stat (l,c,t,q MEM_STAT_INFO)
+#define build_decl(l,c,t,q) build_decl_stat (l, c, t, q MEM_STAT_INFO)
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 find_omp_clause (tree, enum omp_clause_code);
extern tree build_vl_exp_stat (enum tree_code, int MEM_STAT_DECL);
-#define build_vl_exp(c,n) build_vl_exp_stat (c,n MEM_STAT_INFO)
+#define build_vl_exp(c, n) build_vl_exp_stat (c, n MEM_STAT_INFO)
extern tree build_call_nary (tree, tree, int, ...);
extern tree build_call_valist (tree, tree, int, va_list);
@@ -3512,14 +3619,12 @@ extern tree build_reference_type (tree);
extern tree build_vector_type_for_mode (tree, enum machine_mode);
extern tree build_vector_type (tree innertype, int nunits);
extern tree build_opaque_vector_type (tree innertype, int nunits);
-extern tree build_type_no_quals (tree);
extern tree build_index_type (tree);
extern tree build_array_type (tree, tree);
extern tree build_nonshared_array_type (tree, tree);
extern tree build_array_type_nelts (tree, unsigned HOST_WIDE_INT);
extern tree build_function_type (tree, tree);
extern tree build_function_type_list (tree, ...);
-extern tree build_function_decl_skip_args (tree, bitmap, bool);
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 *);
@@ -3533,8 +3638,6 @@ extern tree build_method_type (tree, tree);
extern tree build_offset_type (tree, tree);
extern tree build_complex_type (tree);
extern tree array_type_nelts (const_tree);
-extern bool in_array_bounds_p (tree);
-extern bool range_in_array_bounds_p (tree);
extern tree value_member (tree, tree);
extern tree purpose_member (const_tree, tree);
@@ -3560,7 +3663,6 @@ tree_low_cst (const_tree t, int pos)
return TREE_INT_CST_LOW (t);
}
#endif
-extern HOST_WIDE_INT size_low_cst (const_tree);
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, bool);
@@ -3792,7 +3894,6 @@ extern tree expr_last (tree);
extern tree size_in_bytes (const_tree);
extern HOST_WIDE_INT int_size_in_bytes (const_tree);
extern HOST_WIDE_INT max_int_size_in_bytes (const_tree);
-extern tree tree_expr_size (const_tree);
extern tree bit_position (const_tree);
extern HOST_WIDE_INT int_bit_position (const_tree);
extern tree byte_position (const_tree);
@@ -3853,10 +3954,6 @@ extern tree nreverse (tree);
extern int list_length (const_tree);
-/* Returns the number of FIELD_DECLs in a type. */
-
-extern int fields_length (const_tree);
-
/* Returns the first FIELD_DECL in a type. */
extern tree first_field (const_tree);
@@ -4017,12 +4114,6 @@ extern tree variable_size (tree);
extern tree stabilize_reference (tree);
-/* Subroutine of stabilize_reference; this is called for subtrees of
- references. Any expression with side-effects must be put in a SAVE_EXPR
- to ensure that it is only evaluated once. */
-
-extern tree stabilize_reference_1 (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.
@@ -4205,20 +4296,6 @@ extern tree unshare_expr_without_location (tree);
/* In stmt.c */
extern void expand_label (tree);
-extern void expand_goto (tree);
-
-extern rtx expand_stack_save (void);
-extern void expand_stack_restore (tree);
-extern void expand_return (tree);
-
-/* In tree-eh.c */
-extern void using_eh_for_cleanups (void);
-
-extern bool tree_could_trap_p (tree);
-extern bool operation_could_trap_helper_p (enum tree_code, bool, bool, bool,
- bool, tree, bool *);
-extern bool operation_could_trap_p (enum tree_code, bool, bool, tree);
-extern bool tree_could_throw_p (tree);
/* Compare and hash for any structure which begins with a canonical
pointer. Assumes all pointers are interchangeable, which is sort
@@ -4288,7 +4365,6 @@ extern tree fold_build3_stat_loc (location_t, enum tree_code, tree, tree, tree,
tree MEM_STAT_DECL);
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);
-extern tree fold_build3_initializer_loc (location_t, enum tree_code, tree, 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 *);
@@ -4297,7 +4373,7 @@ extern tree fold_build_call_array_loc (location_t, tree, tree, int, tree *);
extern tree fold_build_call_array_initializer_loc (location_t, tree, tree, int, tree *);
extern bool fold_convertible_p (const_tree, const_tree);
#define fold_convert(T1,T2)\
- fold_convert_loc(UNKNOWN_LOCATION, 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);
@@ -4317,7 +4393,7 @@ extern tree omit_one_operand_loc (location_t, tree, tree, tree);
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)
+ 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);
@@ -4341,7 +4417,6 @@ extern tree build_simple_mem_ref_loc (location_t, tree);
#define build_simple_mem_ref(T)\
build_simple_mem_ref_loc (UNKNOWN_LOCATION, T)
extern double_int mem_ref_offset (const_tree);
-extern tree reference_alias_ptr_type (const_tree);
extern tree build_invariant_address (tree, tree, HOST_WIDE_INT);
extern tree constant_boolean_node (bool, tree);
extern tree div_if_zero_remainder (enum tree_code, const_tree, const_tree);
@@ -4352,7 +4427,6 @@ extern enum tree_code swap_tree_comparison (enum tree_code);
extern bool ptr_difference_const (tree, tree, HOST_WIDE_INT *);
extern enum tree_code invert_tree_comparison (enum tree_code, bool);
-extern bool tree_expr_nonzero_p (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 *);
@@ -4361,11 +4435,8 @@ extern bool tree_unary_nonnegative_warnv_p (enum tree_code, tree, tree, bool *);
extern bool tree_binary_nonnegative_warnv_p (enum tree_code, tree, tree, tree,
bool *);
extern bool tree_single_nonnegative_warnv_p (tree t, bool *strict_overflow_p);
-extern bool tree_invalid_nonnegative_warnv_p (tree t, bool *strict_overflow_p);
extern bool tree_call_nonnegative_warnv_p (tree, tree, tree, tree, bool *);
-extern bool tree_expr_nonzero_warnv_p (tree, bool *);
-
extern bool fold_real_zero_addition_p (const_tree, const_tree, int);
extern tree combine_comparisons (location_t, enum tree_code, enum tree_code,
enum tree_code, tree, tree, tree);
@@ -4436,7 +4507,6 @@ extern tree fold_builtin_stxcpy_chk (location_t, tree, tree, tree, tree, tree, b
enum built_in_function);
extern tree fold_builtin_stxncpy_chk (location_t, tree, tree, tree, tree, tree, bool,
enum built_in_function);
-extern tree fold_builtin_snprintf_chk (location_t, tree, tree, enum built_in_function);
extern bool fold_builtin_next_arg (tree, bool);
extern enum built_in_function builtin_mathfn_code (const_tree);
extern tree fold_builtin_call_array (location_t, tree, tree, int, tree *);
@@ -4446,10 +4516,7 @@ extern tree build_call_expr_loc (location_t, tree, int, ...);
extern tree build_call_expr (tree, int, ...);
extern tree mathfn_built_in (tree, enum built_in_function fn);
extern tree c_strlen (tree, int);
-extern tree std_gimplify_va_arg_expr (tree, tree, gimple_seq *, gimple_seq *);
-extern tree build_va_arg_indirect_ref (tree);
extern tree build_string_literal (int, const char *);
-extern bool validate_arglist (const_tree, ...);
extern rtx builtin_memset_read_str (void *, HOST_WIDE_INT, enum machine_mode);
extern bool is_builtin_fn (tree);
extern bool get_object_alignment_1 (tree, unsigned int *,
@@ -4484,24 +4551,21 @@ extern void get_type_static_bounds (const_tree, mpz_t, mpz_t);
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);
extern hashval_t iterative_hash_expr (const_tree, hashval_t);
-extern hashval_t iterative_hash_exprs_commutative (const_tree,
- const_tree, hashval_t);
extern hashval_t iterative_hash_host_wide_int (HOST_WIDE_INT, hashval_t);
extern hashval_t iterative_hash_hashval_t (hashval_t, hashval_t);
extern hashval_t iterative_hash_host_wide_int (HOST_WIDE_INT, hashval_t);
extern int compare_tree_int (const_tree, unsigned HOST_WIDE_INT);
extern int type_list_equal (const_tree, const_tree);
extern int chain_member (const_tree, const_tree);
-extern int simple_cst_list_equal (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 int real_onep (const_tree);
-extern int real_twop (const_tree);
extern int real_minus_onep (const_tree);
extern void init_ttree (void);
extern void build_common_tree_nodes (bool, bool);
@@ -4524,19 +4588,20 @@ extern tree get_binfo_at_offset (tree, HOST_WIDE_INT, tree);
extern bool virtual_method_call_p (tree);
extern tree obj_type_ref_class (tree ref);
extern bool types_same_for_odr (tree type1, tree type2);
-extern tree get_ref_base_and_extent (tree, HOST_WIDE_INT *,
- HOST_WIDE_INT *, HOST_WIDE_INT *);
extern bool contains_bitfld_component_ref_p (const_tree);
extern bool type_in_anonymous_namespace_p (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);
/* In tree-nested.c */
extern tree build_addr (tree, tree);
/* In function.c */
-extern void expand_main_function (void);
extern void expand_function_end (void);
extern void expand_function_start (tree);
-extern void stack_protect_prologue (void);
extern void stack_protect_epilogue (void);
extern void init_dummy_function_start (void);
extern void expand_dummy_function_end (void);
@@ -4580,7 +4645,6 @@ 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);
-extern void print_vec_tree (FILE *, const char *, vec<tree, va_gc> *, int);
extern void print_node_brief (FILE *, const char *, const_tree, int);
extern void indent_to (FILE *, int);
#endif
@@ -4605,9 +4669,6 @@ extern bool must_pass_in_stack_var_size_or_pad (enum machine_mode, const_tree);
/* In attribs.c. */
extern const struct attribute_spec *lookup_attribute_spec (const_tree);
-extern const struct attribute_spec *lookup_scoped_attribute_spec (const_tree,
- const_tree);
-
extern void init_attributes (void);
/* Process the attributes listed in ATTRIBUTES and install them in *NODE,
@@ -4624,8 +4685,6 @@ 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);
/* In stor-layout.c */
@@ -4681,12 +4740,10 @@ extern bool initializer_constant_valid_for_bitfield_p (tree);
extern bool constructor_static_from_elts_p (const_tree);
/* In stmt.c */
-extern void expand_computed_goto (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 void expand_asm_stmt (gimple);
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. */
@@ -4716,10 +4773,10 @@ extern tree get_base_address (tree t);
extern void mark_addressable (tree);
/* In tree.c. */
+extern tree drop_tree_overflow (tree);
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 bool list_equal_p (const_tree, const_tree);
#define tree_map_eq tree_map_base_eq
extern unsigned int tree_map_hash (const void *);
@@ -4741,16 +4798,8 @@ extern unsigned int tree_decl_map_hash (const void *);
#define tree_vec_map_hash tree_decl_map_hash
#define tree_vec_map_marked_p tree_map_base_marked_p
-/* In tree-ssa-address.c. */
-extern tree tree_mem_ref_addr (tree, tree);
-extern void copy_ref_info (tree, tree);
-
-/* In tree-vrp.c */
-extern bool ssa_name_nonnegative_p (const_tree);
-
/* In tree-object-size.c. */
extern void init_object_sizes (void);
-extern void fini_object_sizes (void);
extern unsigned HOST_WIDE_INT compute_builtin_object_size (tree, int);
/* In expr.c. */
@@ -4760,9 +4809,6 @@ extern unsigned HOST_WIDE_INT compute_builtin_object_size (tree, int);
succeed. */
extern int can_move_by_pieces (unsigned HOST_WIDE_INT, unsigned int);
-/* Is it an ADDR_EXPR of a DECL that's not in memory? */
-extern bool addr_expr_of_non_mem_decl_p (tree);
-
extern unsigned HOST_WIDE_INT highest_pow2_factor (const_tree);
extern tree build_personality_function (const char *);
@@ -4775,12 +4821,6 @@ extern bool is_tm_ending_fndecl (tree);
extern void record_tm_replacement (tree, tree);
extern void tm_malloc_replacement (tree);
-static inline bool
-is_tm_safe_or_pure (const_tree x)
-{
- return is_tm_safe (x) || is_tm_pure (x);
-}
-
/* In tree-inline.c. */
void init_inline_once (void);
@@ -4853,12 +4893,6 @@ more_call_expr_args_p (const call_expr_arg_iterator *iter)
return (iter->i < iter->n);
}
-static inline bool
-more_const_call_expr_args_p (const 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) \
@@ -4876,12 +4910,6 @@ is_lang_specific (tree t)
return TREE_CODE (t) == LANG_TYPE || TREE_CODE (t) >= NUM_TREE_CODES;
}
-/* In gimple-low.c. */
-extern bool block_may_fallthru (const_tree);
-
-/* In vtable-verify.c. */
-extern void save_vtable_map_decl (tree);
-
/* Valid builtin number. */
#define BUILTIN_VALID_P(FNCODE) \
(IN_RANGE ((int)FNCODE, ((int)BUILT_IN_NONE) + 1, ((int) END_BUILTINS) - 1))
@@ -4958,6 +4986,31 @@ builtin_decl_implicit_p (enum built_in_function fncode)
&& builtin_info.implicit_p[uns_fncode]);
}
+/* 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_STATIC (var) || TREE_PUBLIC (var) || DECL_EXTERNAL (var))
+ && TREE_READONLY (var)
+ && !TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (var)))
+ && (TREE_PUBLIC (var)
+ || DECL_EXTERNAL (var)
+ || TREE_ADDRESSABLE (var)));
+}
+
/* 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. */
diff --git a/gcc/tsan.c b/gcc/tsan.c
index 1c642a6642b..bceb5979de1 100644
--- a/gcc/tsan.c
+++ b/gcc/tsan.c
@@ -28,14 +28,16 @@ along with GCC; see the file COPYING3. If not see
#include "basic-block.h"
#include "gimple.h"
#include "function.h"
-#include "tree-ssa.h"
+#include "gimple-ssa.h"
+#include "cgraph.h"
+#include "tree-cfg.h"
+#include "tree-ssanames.h"
#include "tree-pass.h"
#include "tree-iterator.h"
#include "langhooks.h"
#include "output.h"
#include "options.h"
#include "target.h"
-#include "cgraph.h"
#include "diagnostic.h"
#include "tree-ssa-propagate.h"
#include "tsan.h"
@@ -753,12 +755,12 @@ const pass_data pass_data_tsan =
class pass_tsan : public gimple_opt_pass
{
public:
- pass_tsan(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_tsan, ctxt)
+ pass_tsan (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_tsan, ctxt)
{}
/* opt_pass methods: */
- opt_pass * clone () { return new pass_tsan (ctxt_); }
+ opt_pass * clone () { return new pass_tsan (m_ctxt); }
bool gate () { return tsan_gate (); }
unsigned int execute () { return tsan_pass (); }
@@ -798,8 +800,8 @@ const pass_data pass_data_tsan_O0 =
class pass_tsan_O0 : public gimple_opt_pass
{
public:
- pass_tsan_O0(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_tsan_O0, ctxt)
+ pass_tsan_O0 (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_tsan_O0, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/tsystem.h b/gcc/tsystem.h
index 157bc225e12..bc628a076d8 100644
--- a/gcc/tsystem.h
+++ b/gcc/tsystem.h
@@ -129,7 +129,7 @@ extern int errno;
#define gcc_unreachable() (abort ())
#define CONST_CAST2(TOTYPE,FROMTYPE,X) ((__extension__(union {FROMTYPE _q; TOTYPE _nq;})(X))._nq)
-#define CONST_CAST(TYPE,X) CONST_CAST2(TYPE, const TYPE, (X))
+#define CONST_CAST(TYPE,X) CONST_CAST2 (TYPE, const TYPE, (X))
/* Filename handling macros. */
#include "filenames.h"
diff --git a/gcc/ubsan.c b/gcc/ubsan.c
index b8d40d52128..9dc19c9d29a 100644
--- a/gcc/ubsan.c
+++ b/gcc/ubsan.c
@@ -233,10 +233,9 @@ ubsan_source_location (location_t loc)
static unsigned short
get_ubsan_type_info_for_type (tree type)
{
- int prec = exact_log2 (TYPE_PRECISION (type));
- if (prec == -1)
- error ("unexpected size of type %qT", type);
-
+ gcc_assert (TYPE_SIZE (type) && host_integerp (TYPE_SIZE (type), 1));
+ int prec = exact_log2 (tree_low_cst (TYPE_SIZE (type), 1));
+ gcc_assert (prec != -1);
return (prec << 1) | !TYPE_UNSIGNED (type);
}
@@ -260,11 +259,18 @@ ubsan_type_descriptor (tree type)
unsigned short tkind, tinfo;
/* At least for INTEGER_TYPE/REAL_TYPE/COMPLEX_TYPE, this should work.
- ??? For e.g. type_unsigned_for (type), the TYPE_NAME would be NULL. */
+ For e.g. type_unsigned_for (type) or bit-fields, the TYPE_NAME
+ would be NULL. */
if (TYPE_NAME (type) != NULL)
- tname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
+ {
+ if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
+ tname = IDENTIFIER_POINTER (TYPE_NAME (type));
+ else
+ tname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
+ }
else
tname = "<unknown>";
+
if (TREE_CODE (type) == INTEGER_TYPE)
{
/* For INTEGER_TYPE, this is 0x0000. */
diff --git a/gcc/value-prof.c b/gcc/value-prof.c
index 160a416d4d3..40e72ab8c89 100644
--- a/gcc/value-prof.c
+++ b/gcc/value-prof.c
@@ -21,6 +21,7 @@ along with GCC; see the file COPYING3. If not see
#include "system.h"
#include "coretypes.h"
#include "tm.h"
+#include "tree.h"
#include "rtl.h"
#include "expr.h"
#include "hard-reg-set.h"
@@ -32,14 +33,17 @@ along with GCC; see the file COPYING3. If not see
#include "optabs.h"
#include "regs.h"
#include "ggc.h"
-#include "tree-ssa.h"
-#include "tree-flow-inline.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-cfg.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
#include "diagnostic.h"
#include "gimple-pretty-print.h"
#include "coverage.h"
#include "tree.h"
#include "gcov-io.h"
-#include "cgraph.h"
#include "timevar.h"
#include "dumpfile.h"
#include "pointer-set.h"
@@ -192,6 +196,7 @@ gimple_add_histogram_value (struct function *fun, gimple stmt,
{
hist->hvalue.next = gimple_histogram_value (fun, stmt);
set_histogram_value (fun, stmt, hist);
+ hist->fun = fun;
}
@@ -249,7 +254,7 @@ dump_histogram_value (FILE *dump_file, histogram_value hist)
if (hist->hvalue.counters)
{
unsigned int i;
- fprintf(dump_file, " [");
+ fprintf (dump_file, " [");
for (i = 0; i < hist->hdata.intvl.steps; i++)
fprintf (dump_file, " %d:"HOST_WIDEST_INT_PRINT_DEC,
hist->hdata.intvl.int_start + i,
@@ -334,6 +339,15 @@ dump_histogram_value (FILE *dump_file, histogram_value hist)
}
fprintf (dump_file, ".\n");
break;
+ case HIST_TYPE_TIME_PROFILE:
+ fprintf (dump_file, "Time profile ");
+ if (hist->hvalue.counters)
+ {
+ fprintf (dump_file, "time:"HOST_WIDEST_INT_PRINT_DEC,
+ (HOST_WIDEST_INT) hist->hvalue.counters[0]);
+ }
+ fprintf (dump_file, ".\n");
+ break;
case HIST_TYPE_MAX:
gcc_unreachable ();
}
@@ -407,6 +421,7 @@ stream_in_histogram_value (struct lto_input_block *ib, gimple stmt)
break;
case HIST_TYPE_IOR:
+ case HIST_TYPE_TIME_PROFILE:
ncounters = 1;
break;
case HIST_TYPE_MAX:
@@ -492,7 +507,9 @@ visit_hist (void **slot, void *data)
{
struct pointer_set_t *visited = (struct pointer_set_t *) data;
histogram_value hist = *(histogram_value *) slot;
- if (!pointer_set_contains (visited, hist))
+
+ if (!pointer_set_contains (visited, hist)
+ && hist->type != HIST_TYPE_TIME_PROFILE)
{
error ("dead histogram");
dump_histogram_value (stderr, hist);
@@ -1204,9 +1221,9 @@ init_node_map (bool local)
" with nodes %s/%i %s/%i\n",
n->profile_id,
cgraph_node_name (n),
- n->symbol.order,
- symtab_node_name (*(symtab_node*)val),
- (*(symtab_node *)val)->symbol.order);
+ n->order,
+ symtab_node_name (*(symtab_node **)val),
+ (*(symtab_node **)val)->order);
n->profile_id = (n->profile_id + 1) & 0x7fffffff;
}
}
@@ -1217,7 +1234,7 @@ init_node_map (bool local)
"Node %s/%i has no profile-id"
" (profile feedback missing?)\n",
cgraph_node_name (n),
- n->symbol.order);
+ n->order);
continue;
}
else if ((val = pointer_map_contains (cgraph_node_map,
@@ -1228,7 +1245,7 @@ init_node_map (bool local)
"Node %s/%i has IP profile-id %i conflict. "
"Giving up.\n",
cgraph_node_name (n),
- n->symbol.order,
+ n->order,
n->profile_id);
*val = NULL;
continue;
@@ -1269,7 +1286,7 @@ static bool
check_ic_target (gimple call_stmt, struct cgraph_node *target)
{
location_t locus;
- if (gimple_check_call_matching_types (call_stmt, target->symbol.decl, true))
+ if (gimple_check_call_matching_types (call_stmt, target->decl, true))
return true;
locus = gimple_location (call_stmt);
@@ -1312,7 +1329,7 @@ gimple_ic (gimple icall_stmt, struct cgraph_node *direct_call,
load_stmt = gimple_build_assign (tmp0, tmp);
gsi_insert_before (&gsi, load_stmt, GSI_SAME_STMT);
- tmp = fold_convert (optype, build_addr (direct_call->symbol.decl,
+ tmp = fold_convert (optype, build_addr (direct_call->decl,
current_function_decl));
load_stmt = gimple_build_assign (tmp1, tmp);
gsi_insert_before (&gsi, load_stmt, GSI_SAME_STMT);
@@ -1324,8 +1341,8 @@ gimple_ic (gimple icall_stmt, struct cgraph_node *direct_call,
gimple_set_vuse (icall_stmt, NULL_TREE);
update_stmt (icall_stmt);
dcall_stmt = gimple_copy (icall_stmt);
- gimple_call_set_fndecl (dcall_stmt, direct_call->symbol.decl);
- dflags = flags_from_decl_or_type (direct_call->symbol.decl);
+ gimple_call_set_fndecl (dcall_stmt, direct_call->decl);
+ dflags = flags_from_decl_or_type (direct_call->decl);
if ((dflags & ECF_NORETURN) != 0)
gimple_call_set_lhs (dcall_stmt, NULL_TREE);
gsi_insert_before (&gsi, dcall_stmt, GSI_SAME_STMT);
@@ -1490,7 +1507,7 @@ gimple_ic_transform (gimple_stmt_iterator *gsi)
fprintf (dump_file, "Indirect call -> direct call ");
print_generic_expr (dump_file, gimple_call_fn (stmt), TDF_SLIM);
fprintf (dump_file, "=> ");
- print_generic_expr (dump_file, direct_call->symbol.decl, TDF_SLIM);
+ print_generic_expr (dump_file, direct_call->decl, TDF_SLIM);
fprintf (dump_file, " transformation skipped because of type mismatch");
print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
}
@@ -1503,7 +1520,7 @@ gimple_ic_transform (gimple_stmt_iterator *gsi)
fprintf (dump_file, "Indirect call -> direct call ");
print_generic_expr (dump_file, gimple_call_fn (stmt), TDF_SLIM);
fprintf (dump_file, "=> ");
- print_generic_expr (dump_file, direct_call->symbol.decl, TDF_SLIM);
+ print_generic_expr (dump_file, direct_call->decl, TDF_SLIM);
fprintf (dump_file, " transformation on insn postponned to ipa-profile");
print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
fprintf (dump_file, "hist->count "HOST_WIDEST_INT_PRINT_DEC
@@ -1568,7 +1585,7 @@ gimple_stringop_fixed_value (gimple vcall_stmt, tree icall_size, int prob,
fndecl = gimple_call_fndecl (vcall_stmt);
if (!interesting_stringop_to_profile_p (fndecl, vcall_stmt, &size_arg))
- gcc_unreachable();
+ gcc_unreachable ();
cond_bb = gimple_bb (vcall_stmt);
gsi = gsi_for_stmt (vcall_stmt);
@@ -1915,12 +1932,14 @@ gimple_find_values_to_profile (histogram_values *values)
gimple_stmt_iterator gsi;
unsigned i;
histogram_value hist = NULL;
-
values->create (0);
+
FOR_EACH_BB (bb)
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
gimple_values_to_profile (gsi_stmt (gsi), values);
+ values->safe_push (gimple_alloc_histogram_value (cfun, HIST_TYPE_TIME_PROFILE, 0, 0));
+
FOR_EACH_VEC_ELT (*values, i, hist)
{
switch (hist->type)
@@ -1945,6 +1964,10 @@ gimple_find_values_to_profile (histogram_values *values)
hist->n_counters = 3;
break;
+ case HIST_TYPE_TIME_PROFILE:
+ hist->n_counters = 1;
+ break;
+
case HIST_TYPE_AVERAGE:
hist->n_counters = 2;
break;
diff --git a/gcc/value-prof.h b/gcc/value-prof.h
index 57f249d56ef..ef77af4395e 100644
--- a/gcc/value-prof.h
+++ b/gcc/value-prof.h
@@ -34,6 +34,7 @@ enum hist_type
called in indirect call */
HIST_TYPE_AVERAGE, /* Compute average value (sum of all values). */
HIST_TYPE_IOR, /* Used to compute expected alignment. */
+ HIST_TYPE_TIME_PROFILE, /* Used for time profile */
HIST_TYPE_MAX
};
@@ -54,6 +55,7 @@ struct histogram_value_t
} hvalue;
enum hist_type type; /* Type of information to measure. */
unsigned n_counters; /* Number of required counters. */
+ struct function *fun;
union
{
struct
@@ -97,6 +99,8 @@ extern void gimple_gen_pow2_profiler (histogram_value, unsigned, unsigned);
extern void gimple_gen_one_value_profiler (histogram_value, unsigned, unsigned);
extern void gimple_gen_ic_profiler (histogram_value, unsigned, unsigned);
extern void gimple_gen_ic_func_profiler (void);
+extern void gimple_gen_time_profiler (unsigned, unsigned,
+ gimple_stmt_iterator &);
extern void gimple_gen_const_delta_profiler (histogram_value,
unsigned, unsigned);
extern void gimple_gen_average_profiler (histogram_value, unsigned, unsigned);
diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c
index 5d39c500a51..8b07f9fbf9f 100644
--- a/gcc/var-tracking.c
+++ b/gcc/var-tracking.c
@@ -104,6 +104,8 @@
#include "regs.h"
#include "expr.h"
#include "tree-pass.h"
+#include "bitmap.h"
+#include "tree-dfa.h"
#include "tree-ssa.h"
#include "cselib.h"
#include "target.h"
@@ -2877,7 +2879,7 @@ variable_union (variable src, dataflow_set *set)
/* The most common case, much simpler, no qsort is needed. */
location_chain dstnode = dst->var_part[j].loc_chain;
dst->var_part[k].loc_chain = dstnode;
- VAR_PART_OFFSET (dst, k) = VAR_PART_OFFSET(dst, j);
+ VAR_PART_OFFSET (dst, k) = VAR_PART_OFFSET (dst, j);
node2 = dstnode;
for (node = src->var_part[i].loc_chain; node; node = node->next)
if (!((REG_P (dstnode->loc)
@@ -7905,7 +7907,7 @@ struct expand_loc_callback_data
/* Stack of values and debug_exprs under expansion, and their
children. */
- vec<rtx, va_stack> expanding;
+ stack_vec<rtx, 4> expanding;
/* Stack of values and debug_exprs whose expansion hit recursion
cycles. They will have VALUE_RECURSED_INTO marked when added to
@@ -7913,7 +7915,7 @@ struct expand_loc_callback_data
resolves to a valid location. So, if the flag remains set at the
end of the search, we know no valid location for this one can
possibly exist. */
- vec<rtx, va_stack> pending;
+ stack_vec<rtx, 4> pending;
/* The maximum depth among the sub-expressions under expansion.
Zero indicates no expansion so far. */
@@ -8415,11 +8417,11 @@ vt_expand_loc_callback (rtx x, bitmap regs,
This function performs this finalization of NULL locations. */
static void
-resolve_expansions_pending_recursion (vec<rtx, va_stack> pending)
+resolve_expansions_pending_recursion (vec<rtx, va_heap> *pending)
{
- while (!pending.is_empty ())
+ while (!pending->is_empty ())
{
- rtx x = pending.pop ();
+ rtx x = pending->pop ();
decl_or_value dv;
if (!VALUE_RECURSED_INTO (x))
@@ -8439,8 +8441,6 @@ resolve_expansions_pending_recursion (vec<rtx, va_stack> pending)
do \
{ \
(d).vars = (v); \
- vec_stack_alloc (rtx, (d).expanding, 4); \
- vec_stack_alloc (rtx, (d).pending, 4); \
(d).depth.complexity = (d).depth.entryvals = 0; \
} \
while (0)
@@ -8448,7 +8448,7 @@ resolve_expansions_pending_recursion (vec<rtx, va_stack> pending)
#define FINI_ELCD(d, l) \
do \
{ \
- resolve_expansions_pending_recursion ((d).pending); \
+ resolve_expansions_pending_recursion (&(d).pending); \
(d).pending.release (); \
(d).expanding.release (); \
\
@@ -8742,7 +8742,7 @@ emit_note_insn_var_location (variable_def **varp, emit_note_data *data)
int
var_track_values_to_stack (variable_def **slot,
- vec<rtx, va_stack> *changed_values_stack)
+ vec<rtx, va_heap> *changed_values_stack)
{
variable var = *slot;
@@ -8777,7 +8777,7 @@ remove_value_from_changed_variables (rtx val)
static void
notify_dependents_of_changed_value (rtx val, variable_table_type htab,
- vec<rtx, va_stack> *changed_values_stack)
+ vec<rtx, va_heap> *changed_values_stack)
{
variable_def **slot;
variable var;
@@ -8862,13 +8862,11 @@ process_changed_values (variable_table_type htab)
{
int i, n;
rtx val;
- vec<rtx, va_stack> changed_values_stack;
-
- vec_stack_alloc (rtx, changed_values_stack, 20);
+ stack_vec<rtx, 20> changed_values_stack;
/* Move values from changed_variables to changed_values_stack. */
changed_variables
- .traverse <vec<rtx, va_stack>*, var_track_values_to_stack>
+ .traverse <vec<rtx, va_heap>*, var_track_values_to_stack>
(&changed_values_stack);
/* Back-propagate change notifications in values while popping
@@ -8889,8 +8887,6 @@ process_changed_values (variable_table_type htab)
n--;
}
}
-
- changed_values_stack.release ();
}
/* Emit NOTE_INSN_VAR_LOCATION note for each variable from a chain
@@ -10256,8 +10252,8 @@ const pass_data pass_data_variable_tracking =
class pass_variable_tracking : public rtl_opt_pass
{
public:
- pass_variable_tracking(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_variable_tracking, ctxt)
+ pass_variable_tracking (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_variable_tracking, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 0504eeb4f39..22269122993 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -46,10 +46,10 @@ along with GCC; see the file COPYING3. If not see
#include "target.h"
#include "common/common-target.h"
#include "targhooks.h"
-#include "tree-mudflap.h"
#include "cgraph.h"
#include "pointer-set.h"
#include "asan.h"
+#include "basic-block.h"
#ifdef XCOFF_DEBUGGING_INFO
#include "xcoffout.h" /* Needed for external data
@@ -1246,10 +1246,6 @@ make_decl_rtl (tree decl)
&& SYMBOL_REF_HAS_BLOCK_INFO_P (XEXP (x, 0)))
change_symbol_block (XEXP (x, 0), get_block_for_decl (decl));
- /* Make this function static known to the mudflap runtime. */
- if (flag_mudflap && TREE_CODE (decl) == VAR_DECL)
- mudflap_enqueue_decl (decl);
-
return;
}
@@ -1386,10 +1382,6 @@ make_decl_rtl (tree decl)
If the name is changed, the macro ASM_OUTPUT_LABELREF
will have to know how to strip this information. */
targetm.encode_section_info (decl, DECL_RTL (decl), true);
-
- /* Make this function static known to the mudflap runtime. */
- if (flag_mudflap && TREE_CODE (decl) == VAR_DECL)
- mudflap_enqueue_decl (decl);
}
/* Like make_decl_rtl, but inhibit creation of new alias sets when
@@ -1399,7 +1391,7 @@ make_decl_rtl (tree decl)
rtx
make_decl_rtl_for_debug (tree decl)
{
- unsigned int save_aliasing_flag, save_mudflap_flag;
+ unsigned int save_aliasing_flag;
rtx rtl;
if (DECL_RTL_SET_P (decl))
@@ -1410,12 +1402,9 @@ make_decl_rtl_for_debug (tree decl)
we do not want to create alias sets that will throw the alias
numbers off in the comparison dumps. So... clearing
flag_strict_aliasing will keep new_alias_set() from creating a
- new set. It is undesirable to register decl with mudflap
- in this case as well. */
+ new set. */
save_aliasing_flag = flag_strict_aliasing;
flag_strict_aliasing = 0;
- save_mudflap_flag = flag_mudflap;
- flag_mudflap = 0;
rtl = DECL_RTL (decl);
/* Reset DECL_RTL back, as various parts of the compiler expects
@@ -1423,8 +1412,6 @@ make_decl_rtl_for_debug (tree decl)
SET_DECL_RTL (decl, NULL);
flag_strict_aliasing = save_aliasing_flag;
- flag_mudflap = save_mudflap_flag;
-
return rtl;
}
@@ -2370,7 +2357,7 @@ mark_decl_referenced (tree decl)
definition. */
struct cgraph_node *node = cgraph_get_create_node (decl);
if (!DECL_EXTERNAL (decl)
- && !node->symbol.definition)
+ && !node->definition)
cgraph_mark_force_output_node (node);
}
else if (TREE_CODE (decl) == VAR_DECL)
@@ -2378,7 +2365,7 @@ mark_decl_referenced (tree decl)
struct varpool_node *node = varpool_node_for_decl (decl);
/* C++ frontend use mark_decl_references to force COMDAT variables
to be output that might appear dead otherwise. */
- node->symbol.force_output = true;
+ node->force_output = true;
}
/* else do nothing - we can get various sorts of CST nodes here,
which do not need to be marked. */
@@ -3085,7 +3072,7 @@ compare_constant (const tree t1, const tree t2)
case MINUS_EXPR:
case RANGE_EXPR:
return (compare_constant (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0))
- && compare_constant(TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1)));
+ && compare_constant (TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1)));
CASE_CONVERT:
case VIEW_CONVERT_EXPR:
@@ -3205,10 +3192,6 @@ build_constant_desc (tree exp)
desc = ggc_alloc_constant_descriptor_tree ();
desc->value = copy_constant (exp);
- /* Propagate marked-ness to copied constant. */
- if (flag_mudflap && mf_marked_p (exp))
- mf_mark (desc->value);
-
/* Create a string containing the label name, in LABEL. */
labelno = const_labelno++;
ASM_GENERATE_INTERNAL_LABEL (label, "LC", labelno);
@@ -3404,8 +3387,6 @@ output_constant_def_contents (rtx symbol)
assemble_zeros (asan_red_zone_size (size));
}
}
- if (flag_mudflap)
- mudflap_enqueue_constant (exp);
}
/* Look up EXP in the table of constant descriptors. Return the rtl
@@ -4703,6 +4684,8 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
case REFERENCE_TYPE:
case OFFSET_TYPE:
case FIXED_POINT_TYPE:
+ case POINTER_BOUNDS_TYPE:
+ case NULLPTR_TYPE:
if (! assemble_integer (expand_expr (exp, NULL_RTX, VOIDmode,
EXPAND_INITIALIZER),
MIN (size, thissize), align, 0))
@@ -5400,9 +5383,9 @@ weak_finish_1 (tree decl)
static tree
find_decl (tree target)
{
- symtab_node node = symtab_node_for_asm (target);
+ symtab_node *node = symtab_node_for_asm (target);
if (node)
- return node->symbol.decl;
+ return node->decl;
return NULL_TREE;
}
@@ -5546,9 +5529,9 @@ void
do_assemble_alias (tree decl, tree target)
{
/* Emulated TLS had better not get this var. */
- gcc_assert(!(!targetm.have_tls
- && TREE_CODE (decl) == VAR_DECL
- && DECL_THREAD_LOCAL_P (decl)));
+ gcc_assert (!(!targetm.have_tls
+ && TREE_CODE (decl) == VAR_DECL
+ && DECL_THREAD_LOCAL_P (decl)));
if (TREE_ASM_WRITTEN (decl))
return;
@@ -5687,9 +5670,9 @@ assemble_alias (tree decl, tree target)
/* Allow aliases to aliases. */
if (TREE_CODE (decl) == FUNCTION_DECL)
- cgraph_get_create_node (decl)->symbol.alias = true;
+ cgraph_get_create_node (decl)->alias = true;
else
- varpool_node_for_decl (decl)->symbol.alias = true;
+ varpool_node_for_decl (decl)->alias = true;
/* If the target has already been emitted, we don't have to queue the
alias. This saves a tad of memory. */
@@ -5792,12 +5775,12 @@ dump_tm_clone_pairs (vec<tm_alias_pair> tm_alias_pairs)
TM_GETTMCLONE. If neither of these are true, we didn't generate
a clone, and we didn't call it indirectly... no sense keeping it
in the clone table. */
- if (!dst_n || !dst_n->symbol.definition)
+ if (!dst_n || !dst_n->definition)
continue;
/* This covers the case where we have optimized the original
function away, and only access the transactional clone. */
- if (!src_n || !src_n->symbol.definition)
+ if (!src_n || !src_n->definition)
continue;
if (!switched)
@@ -6292,9 +6275,8 @@ categorize_decl_for_section (const_tree decl, int reloc)
return SECCAT_TEXT;
else if (TREE_CODE (decl) == STRING_CST)
{
- if (flag_mudflap
- || ((flag_sanitize & SANITIZE_ADDRESS)
- && asan_protect_global (CONST_CAST_TREE (decl))))
+ if ((flag_sanitize & SANITIZE_ADDRESS)
+ && asan_protect_global (CONST_CAST_TREE (decl)))
/* or !flag_merge_constants */
return SECCAT_RODATA;
else
@@ -6319,7 +6301,7 @@ categorize_decl_for_section (const_tree decl, int reloc)
}
else if (reloc & targetm.asm_out.reloc_rw_mask ())
ret = reloc == 1 ? SECCAT_DATA_REL_RO_LOCAL : SECCAT_DATA_REL_RO;
- else if (reloc || flag_merge_constants < 2 || flag_mudflap
+ else if (reloc || flag_merge_constants < 2
|| ((flag_sanitize & SANITIZE_ADDRESS)
&& asan_protect_global (CONST_CAST_TREE (decl))))
/* C and C++ don't allow different variables to share the same
@@ -6743,20 +6725,20 @@ default_binds_local_p_1 (const_tree exp, int shlib)
&& (TREE_STATIC (exp) || DECL_EXTERNAL (exp)))
{
struct varpool_node *vnode = varpool_get_node (exp);
- if (vnode && resolution_local_p (vnode->symbol.resolution))
+ if (vnode && resolution_local_p (vnode->resolution))
resolved_locally = true;
if (vnode
- && resolution_to_local_definition_p (vnode->symbol.resolution))
+ && resolution_to_local_definition_p (vnode->resolution))
resolved_to_local_def = true;
}
else if (TREE_CODE (exp) == FUNCTION_DECL && TREE_PUBLIC (exp))
{
struct cgraph_node *node = cgraph_get_node (exp);
if (node
- && resolution_local_p (node->symbol.resolution))
+ && resolution_local_p (node->resolution))
resolved_locally = true;
if (node
- && resolution_to_local_definition_p (node->symbol.resolution))
+ && resolution_to_local_definition_p (node->resolution))
resolved_to_local_def = true;
}
@@ -6837,15 +6819,15 @@ decl_binds_to_current_def_p (tree decl)
{
struct varpool_node *vnode = varpool_get_node (decl);
if (vnode
- && vnode->symbol.resolution != LDPR_UNKNOWN)
- return resolution_to_local_definition_p (vnode->symbol.resolution);
+ && vnode->resolution != LDPR_UNKNOWN)
+ return resolution_to_local_definition_p (vnode->resolution);
}
else if (TREE_CODE (decl) == FUNCTION_DECL)
{
struct cgraph_node *node = cgraph_get_node (decl);
if (node
- && node->symbol.resolution != LDPR_UNKNOWN)
- return resolution_to_local_definition_p (node->symbol.resolution);
+ && node->resolution != LDPR_UNKNOWN)
+ return resolution_to_local_definition_p (node->resolution);
}
/* Otherwise we have to assume the worst for DECL_WEAK (hidden weaks
binds locally but still can be overwritten), DECL_COMMON (can be merged
diff --git a/gcc/varpool.c b/gcc/varpool.c
index d5324adb52b..1e4c823338c 100644
--- a/gcc/varpool.c
+++ b/gcc/varpool.c
@@ -33,7 +33,6 @@ along with GCC; see the file COPYING3. If not see
#include "target.h"
#include "output.h"
#include "gimple.h"
-#include "tree-ssa.h"
#include "flags.h"
/* List of hooks triggered on varpool_node events. */
@@ -136,7 +135,7 @@ struct varpool_node *
varpool_create_empty_node (void)
{
struct varpool_node *node = ggc_alloc_cleared_varpool_node ();
- node->symbol.type = SYMTAB_VARIABLE;
+ node->type = SYMTAB_VARIABLE;
return node;
}
@@ -150,8 +149,8 @@ varpool_node_for_decl (tree decl)
return node;
node = varpool_create_empty_node ();
- node->symbol.decl = decl;
- symtab_register_node ((symtab_node)node);
+ node->decl = decl;
+ symtab_register_node (node);
return node;
}
@@ -161,15 +160,15 @@ varpool_remove_node (struct varpool_node *node)
{
tree init;
varpool_call_node_removal_hooks (node);
- symtab_unregister_node ((symtab_node)node);
+ symtab_unregister_node (node);
/* Because we remove references from external functions before final compilation,
we may end up removing useful constructors.
FIXME: We probably want to trace boundaries better. */
- if ((init = ctor_for_folding (node->symbol.decl)) == error_mark_node)
+ if ((init = ctor_for_folding (node->decl)) == error_mark_node)
varpool_remove_initializer (node);
else
- DECL_INITIAL (node->symbol.decl) = init;
+ DECL_INITIAL (node->decl) = init;
ggc_free (node);
}
@@ -177,10 +176,10 @@ varpool_remove_node (struct varpool_node *node)
void
varpool_remove_initializer (struct varpool_node *node)
{
- if (DECL_INITIAL (node->symbol.decl)
- && !DECL_IN_CONSTANT_POOL (node->symbol.decl)
+ if (DECL_INITIAL (node->decl)
+ && !DECL_IN_CONSTANT_POOL (node->decl)
/* Keep vtables for BINFO folding. */
- && !DECL_VIRTUAL_P (node->symbol.decl)
+ && !DECL_VIRTUAL_P (node->decl)
/* FIXME: http://gcc.gnu.org/PR55395 */
&& debug_info_level == DINFO_LEVEL_NONE
/* When doing declaration merging we have duplicate
@@ -188,26 +187,26 @@ varpool_remove_initializer (struct varpool_node *node)
the boides, or we will end up remiving
wrong one. */
&& cgraph_state != CGRAPH_LTO_STREAMING)
- DECL_INITIAL (node->symbol.decl) = error_mark_node;
+ DECL_INITIAL (node->decl) = error_mark_node;
}
/* Dump given cgraph node. */
void
dump_varpool_node (FILE *f, struct varpool_node *node)
{
- dump_symtab_base (f, (symtab_node)node);
+ dump_symtab_base (f, node);
fprintf (f, " Availability: %s\n",
cgraph_function_flags_ready
? cgraph_availability_names[cgraph_variable_initializer_availability (node)]
: "not-ready");
fprintf (f, " Varpool flags:");
- if (DECL_INITIAL (node->symbol.decl))
+ if (DECL_INITIAL (node->decl))
fprintf (f, " initialized");
if (node->output)
fprintf (f, " output");
- if (TREE_READONLY (node->symbol.decl))
+ if (TREE_READONLY (node->decl))
fprintf (f, " read-only");
- if (ctor_for_folding (node->symbol.decl) != error_mark_node)
+ if (ctor_for_folding (node->decl) != error_mark_node)
fprintf (f, " const-value-known");
fprintf (f, "\n");
}
@@ -235,7 +234,7 @@ debug_varpool (void)
struct varpool_node *
varpool_node_for_asm (tree asmname)
{
- if (symtab_node node = symtab_node_for_asm (asmname))
+ if (symtab_node *node = symtab_node_for_asm (asmname))
return dyn_cast <varpool_node> (node);
else
return NULL;
@@ -276,7 +275,7 @@ ctor_for_folding (tree decl)
if (node)
{
real_node = varpool_variable_node (node);
- real_decl = real_node->symbol.decl;
+ real_decl = real_node->decl;
}
else
real_decl = decl;
@@ -293,7 +292,7 @@ ctor_for_folding (tree decl)
if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl)))
{
node = varpool_alias_target (node);
- decl = node->symbol.decl;
+ decl = node->decl;
}
}
@@ -305,7 +304,7 @@ ctor_for_folding (tree decl)
return DECL_INITIAL (real_decl);
}
- /* If thre is no constructor, we have nothing to do. */
+ /* If there is no constructor, we have nothing to do. */
if (DECL_INITIAL (real_decl) == error_mark_node)
return error_mark_node;
@@ -343,7 +342,7 @@ varpool_add_new_variable (tree decl)
node = varpool_node_for_decl (decl);
varpool_call_variable_insertion_hooks (node);
if (varpool_externally_visible_p (node))
- node->symbol.externally_visible = true;
+ node->externally_visible = true;
}
/* Return variable availability. See cgraph.h for description of individual
@@ -352,14 +351,14 @@ enum availability
cgraph_variable_initializer_availability (struct varpool_node *node)
{
gcc_assert (cgraph_function_flags_ready);
- if (!node->symbol.definition)
+ if (!node->definition)
return AVAIL_NOT_AVAILABLE;
- if (!TREE_PUBLIC (node->symbol.decl))
+ if (!TREE_PUBLIC (node->decl))
return AVAIL_AVAILABLE;
- if (DECL_IN_CONSTANT_POOL (node->symbol.decl)
- || DECL_VIRTUAL_P (node->symbol.decl))
+ if (DECL_IN_CONSTANT_POOL (node->decl)
+ || DECL_VIRTUAL_P (node->decl))
return AVAIL_AVAILABLE;
- if (node->symbol.alias && node->symbol.weakref)
+ if (node->alias && node->weakref)
{
enum availability avail;
@@ -370,8 +369,8 @@ cgraph_variable_initializer_availability (struct varpool_node *node)
/* If the variable can be overwritten, return OVERWRITABLE. Takes
care of at least one notable extension - the COMDAT variables
used to share template instantiations in C++. */
- if (decl_replaceable_p (node->symbol.decl)
- || DECL_EXTERNAL (node->symbol.decl))
+ if (decl_replaceable_p (node->decl)
+ || DECL_EXTERNAL (node->decl))
return AVAIL_OVERWRITABLE;
return AVAIL_AVAILABLE;
}
@@ -379,24 +378,24 @@ cgraph_variable_initializer_availability (struct varpool_node *node)
void
varpool_analyze_node (struct varpool_node *node)
{
- tree decl = node->symbol.decl;
+ tree decl = node->decl;
/* When reading back varpool at LTO time, we re-construct the queue in order
to have "needed" list right by inserting all needed nodes into varpool.
We however don't want to re-analyze already analyzed nodes. */
- if (!node->symbol.analyzed)
+ if (!node->analyzed)
{
gcc_assert (!in_lto_p || cgraph_function_flags_ready);
/* Compute the alignment early so function body expanders are
already informed about increased alignment. */
align_variable (decl, 0);
}
- if (node->symbol.alias)
+ if (node->alias)
symtab_resolve_alias
- ((symtab_node) node, (symtab_node) varpool_get_node (node->symbol.alias_target));
+ (node, varpool_get_node (node->alias_target));
else if (DECL_INITIAL (decl))
- record_references_in_initializer (decl, node->symbol.analyzed);
- node->symbol.analyzed = true;
+ record_references_in_initializer (decl, node->analyzed);
+ node->analyzed = true;
}
/* Assemble thunks and aliases associated to NODE. */
@@ -406,12 +405,12 @@ assemble_aliases (struct varpool_node *node)
{
int i;
struct ipa_ref *ref;
- for (i = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list, i, ref); i++)
+ for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list, i, ref); i++)
if (ref->use == IPA_REF_ALIAS)
{
struct varpool_node *alias = ipa_ref_referring_varpool_node (ref);
- do_assemble_alias (alias->symbol.decl,
- DECL_ASSEMBLER_NAME (node->symbol.decl));
+ do_assemble_alias (alias->decl,
+ DECL_ASSEMBLER_NAME (node->decl));
assemble_aliases (alias);
}
}
@@ -421,11 +420,11 @@ assemble_aliases (struct varpool_node *node)
bool
varpool_assemble_decl (struct varpool_node *node)
{
- tree decl = node->symbol.decl;
+ tree decl = node->decl;
/* Aliases are outout when their target is produced or by
output_weakrefs. */
- if (node->symbol.alias)
+ if (node->alias)
return false;
/* Constant pool is output from RTL land when the reference
@@ -449,12 +448,12 @@ varpool_assemble_decl (struct varpool_node *node)
&& TREE_CODE (decl) == VAR_DECL
&& !DECL_HAS_VALUE_EXPR_P (decl));
- if (!node->symbol.in_other_partition
+ if (!node->in_other_partition
&& !DECL_EXTERNAL (decl))
{
assemble_variable (decl, 0, 1, 0);
gcc_assert (TREE_ASM_WRITTEN (decl));
- node->symbol.definition = true;
+ node->definition = true;
assemble_aliases (node);
return true;
}
@@ -468,10 +467,10 @@ varpool_assemble_decl (struct varpool_node *node)
static void
enqueue_node (struct varpool_node *node, struct varpool_node **first)
{
- if (node->symbol.aux)
+ if (node->aux)
return;
gcc_checking_assert (*first);
- node->symbol.aux = *first;
+ node->aux = *first;
*first = node;
}
@@ -495,11 +494,11 @@ varpool_remove_unreferenced_decls (void)
fprintf (cgraph_dump_file, "Trivially needed variables:");
FOR_EACH_DEFINED_VARIABLE (node)
{
- if (node->symbol.analyzed
+ if (node->analyzed
&& (!varpool_can_remove_if_no_refs (node)
/* We just expanded all function bodies. See if any of
them needed the variable. */
- || DECL_RTL_SET_P (node->symbol.decl)))
+ || DECL_RTL_SET_P (node->decl)))
{
enqueue_node (node, &first);
if (cgraph_dump_file)
@@ -509,27 +508,27 @@ varpool_remove_unreferenced_decls (void)
while (first != (struct varpool_node *)(void *)1)
{
node = first;
- first = (struct varpool_node *)first->symbol.aux;
+ first = (struct varpool_node *)first->aux;
- if (node->symbol.same_comdat_group)
+ if (node->same_comdat_group)
{
- symtab_node next;
- for (next = node->symbol.same_comdat_group;
- next != (symtab_node)node;
- next = next->symbol.same_comdat_group)
+ symtab_node *next;
+ for (next = node->same_comdat_group;
+ next != node;
+ next = next->same_comdat_group)
{
varpool_node *vnext = dyn_cast <varpool_node> (next);
- if (vnext && vnext->symbol.analyzed)
+ if (vnext && vnext->analyzed)
enqueue_node (vnext, &first);
}
}
- for (i = 0; ipa_ref_list_reference_iterate (&node->symbol.ref_list, i, ref); i++)
+ for (i = 0; ipa_ref_list_reference_iterate (&node->ref_list, i, ref); i++)
{
varpool_node *vnode = dyn_cast <varpool_node> (ref->referred);
if (vnode
- && (!DECL_EXTERNAL (ref->referred->symbol.decl)
- || vnode->symbol.alias)
- && vnode->symbol.analyzed)
+ && (!DECL_EXTERNAL (ref->referred->decl)
+ || vnode->alias)
+ && vnode->analyzed)
enqueue_node (vnode, &first);
}
}
@@ -538,7 +537,7 @@ varpool_remove_unreferenced_decls (void)
for (node = varpool_first_defined_variable (); node; node = next)
{
next = varpool_next_defined_variable (node);
- if (!node->symbol.aux)
+ if (!node->aux)
{
if (cgraph_dump_file)
fprintf (cgraph_dump_file, " %s", varpool_node_asm_name (node));
@@ -556,14 +555,14 @@ varpool_remove_unreferenced_decls (void)
void
varpool_finalize_named_section_flags (struct varpool_node *node)
{
- if (!TREE_ASM_WRITTEN (node->symbol.decl)
- && !node->symbol.alias
- && !node->symbol.in_other_partition
- && !DECL_EXTERNAL (node->symbol.decl)
- && TREE_CODE (node->symbol.decl) == VAR_DECL
- && !DECL_HAS_VALUE_EXPR_P (node->symbol.decl)
- && DECL_SECTION_NAME (node->symbol.decl))
- get_variable_section (node->symbol.decl, false);
+ if (!TREE_ASM_WRITTEN (node->decl)
+ && !node->alias
+ && !node->in_other_partition
+ && !DECL_EXTERNAL (node->decl)
+ && TREE_CODE (node->decl) == VAR_DECL
+ && !DECL_HAS_VALUE_EXPR_P (node->decl)
+ && DECL_SECTION_NAME (node->decl))
+ get_variable_section (node->decl, false);
}
/* Output all variables enqueued to be assembled. */
@@ -608,7 +607,7 @@ add_new_static_var (tree type)
new_node = varpool_node_for_decl (new_decl);
varpool_finalize_decl (new_decl);
- return new_node->symbol.decl;
+ return new_node->decl;
}
/* Attempt to mark ALIAS as an alias to DECL. Return TRUE if successful.
@@ -622,11 +621,11 @@ varpool_create_variable_alias (tree alias, tree decl)
gcc_assert (TREE_CODE (decl) == VAR_DECL);
gcc_assert (TREE_CODE (alias) == VAR_DECL);
alias_node = varpool_node_for_decl (alias);
- alias_node->symbol.alias = true;
- alias_node->symbol.definition = true;
- alias_node->symbol.alias_target = decl;
+ alias_node->alias = true;
+ alias_node->definition = true;
+ alias_node->alias_target = decl;
if (lookup_attribute ("weakref", DECL_ATTRIBUTES (alias)) != NULL)
- alias_node->symbol.weakref = true;
+ alias_node->weakref = true;
return alias_node;
}
@@ -643,15 +642,15 @@ varpool_extra_name_alias (tree alias, tree decl)
return NULL;
#endif
alias_node = varpool_create_variable_alias (alias, decl);
- alias_node->symbol.cpp_implicit_alias = true;
+ alias_node->cpp_implicit_alias = true;
/* Extra name alias mechanizm creates aliases really late
via DECL_ASSEMBLER_NAME mechanizm.
This is unfortunate because they are not going through the
standard channels. Ensure they get output. */
if (cpp_implicit_aliases_done)
- symtab_resolve_alias ((symtab_node)alias_node,
- (symtab_node)varpool_node_for_decl (decl));
+ symtab_resolve_alias (alias_node,
+ varpool_node_for_decl (decl));
return alias_node;
}
@@ -670,7 +669,7 @@ varpool_for_node_and_aliases (struct varpool_node *node,
if (callback (node, data))
return true;
- for (i = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list, i, ref); i++)
+ for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list, i, ref); i++)
if (ref->use == IPA_REF_ALIAS)
{
struct varpool_node *alias = ipa_ref_referring_varpool_node (ref);
diff --git a/gcc/vec.c b/gcc/vec.c
index 979ecc81ba5..78252e0d088 100644
--- a/gcc/vec.c
+++ b/gcc/vec.c
@@ -183,13 +183,11 @@ vec_prefix::calculate_allocation (vec_prefix *pfx, unsigned reserve,
if (pfx)
{
- alloc = pfx->alloc_;
- num = pfx->num_;
+ alloc = pfx->m_alloc;
+ num = pfx->m_num;
}
else if (!reserve)
- /* If there's no vector, and we've not requested anything, then we
- will create a NULL vector. */
- return 0;
+ gcc_unreachable ();
/* We must have run out of room. */
gcc_assert (alloc - num < reserve);
@@ -217,49 +215,6 @@ vec_prefix::calculate_allocation (vec_prefix *pfx, unsigned reserve,
}
-/* Stack vectors are a little different. VEC_alloc turns into a call
- to vec<T, A>::stack_reserve and passes in space allocated via a
- call to alloca. We record that pointer so that we know that we
- shouldn't free it. If the vector is resized, we resize it on the
- heap. We record the pointers in a vector and search it in LIFO
- order--i.e., we look for the newest stack vectors first. We don't
- expect too many stack vectors at any one level, and searching from
- the end should normally be efficient even if they are used in a
- recursive function. */
-
-static vec<void *> stack_vecs;
-
-/* Add a stack vector to STACK_VECS. */
-
-void
-register_stack_vec (void *vec)
-{
- stack_vecs.safe_push (vec);
-}
-
-
-/* If VEC is registered in STACK_VECS, return its index.
- Otherwise, return -1. */
-
-int
-stack_vec_register_index (void *vec)
-{
- for (unsigned ix = stack_vecs.length (); ix > 0; --ix)
- if (stack_vecs[ix - 1] == vec)
- return static_cast<int> (ix - 1);
- return -1;
-}
-
-
-/* Remove vector at slot IX from the list of registered stack vectors. */
-
-void
-unregister_stack_vec (unsigned ix)
-{
- stack_vecs.unordered_remove (ix);
-}
-
-
/* Helper for qsort; sort descriptors by amount of memory consumed. */
static int
diff --git a/gcc/vec.h b/gcc/vec.h
index 09a1d0a4d86..b1ebda44f5e 100644
--- a/gcc/vec.h
+++ b/gcc/vec.h
@@ -101,8 +101,6 @@ along with GCC; see the file COPYING3. If not see
- Heap: allocation is done using malloc/free. This is the
default allocation strategy.
- - Stack: allocation is done using alloca.
-
- GC: allocation is done using ggc_alloc/ggc_free.
- GC atomic: same as GC with the exception that the elements
@@ -233,10 +231,10 @@ struct vec_prefix
friend struct va_gc;
friend struct va_gc_atomic;
friend struct va_heap;
- friend struct va_stack;
- unsigned alloc_;
- unsigned num_;
+ unsigned m_alloc : 31;
+ unsigned m_has_auto_buf : 1;
+ unsigned m_num;
};
template<typename, typename, typename> struct vec;
@@ -255,8 +253,7 @@ struct vl_ptr { };
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.
- va_stack - Allocation uses alloca. */
+ do not need to be marked during collection. */
/* Allocator type for heap vectors. */
struct va_heap
@@ -285,15 +282,11 @@ va_heap::reserve (vec<T, va_heap, vl_embed> *&v, unsigned reserve, bool exact
MEM_STAT_DECL)
{
unsigned alloc
- = vec_prefix::calculate_allocation (v ? &v->vecpfx_ : 0, reserve, exact);
- if (!alloc)
- {
- release (v);
- return;
- }
+ = vec_prefix::calculate_allocation (v ? &v->m_vecpfx : 0, reserve, exact);
+ gcc_assert (alloc);
if (GATHER_STATISTICS && v)
- v->vecpfx_.release_overhead ();
+ v->m_vecpfx.release_overhead ();
size_t size = vec<T, va_heap, vl_embed>::embedded_size (alloc);
unsigned nelem = v ? v->length () : 0;
@@ -301,7 +294,7 @@ va_heap::reserve (vec<T, va_heap, vl_embed> *&v, unsigned reserve, bool exact
v->embedded_init (alloc, nelem);
if (GATHER_STATISTICS)
- v->vecpfx_.register_overhead (size FINAL_PASS_MEM_STAT);
+ v->m_vecpfx.register_overhead (size FINAL_PASS_MEM_STAT);
}
@@ -315,7 +308,7 @@ va_heap::release (vec<T, va_heap, vl_embed> *&v)
return;
if (GATHER_STATISTICS)
- v->vecpfx_.release_overhead ();
+ v->m_vecpfx.release_overhead ();
::free (v);
v = NULL;
}
@@ -364,7 +357,7 @@ va_gc::reserve (vec<T, A, vl_embed> *&v, unsigned reserve, bool exact
MEM_STAT_DECL)
{
unsigned alloc
- = vec_prefix::calculate_allocation (v ? &v->vecpfx_ : 0, reserve, exact);
+ = vec_prefix::calculate_allocation (v ? &v->m_vecpfx : 0, reserve, exact);
if (!alloc)
{
::ggc_free (v);
@@ -401,107 +394,6 @@ struct va_gc_atomic : va_gc
};
-/* Allocator type for stack vectors. */
-struct va_stack
-{
- /* Use vl_ptr as the default layout for stack vectors. */
- typedef vl_ptr default_layout;
-
- template<typename T>
- static void alloc (vec<T, va_stack, vl_ptr>&, unsigned,
- vec<T, va_stack, vl_embed> *);
-
- template <typename T>
- static void reserve (vec<T, va_stack, vl_embed> *&, unsigned, bool
- CXX_MEM_STAT_INFO);
-
- template <typename T>
- static void release (vec<T, va_stack, vl_embed> *&);
-};
-
-/* Helper functions to keep track of vectors allocated on the stack. */
-void register_stack_vec (void *);
-int stack_vec_register_index (void *);
-void unregister_stack_vec (unsigned);
-
-/* Allocate a vector V which uses alloca for the initial allocation.
- SPACE is space allocated using alloca. NELEMS is the number of
- entries allocated. */
-
-template<typename T>
-void
-va_stack::alloc (vec<T, va_stack, vl_ptr> &v, unsigned nelems,
- vec<T, va_stack, vl_embed> *space)
-{
- v.vec_ = space;
- register_stack_vec (static_cast<void *> (v.vec_));
- v.vec_->embedded_init (nelems, 0);
-}
-
-
-/* Reserve NELEMS slots for a vector initially allocated on the stack.
- When this happens, we switch back to heap allocation. We remove
- the vector from stack_vecs, if it is there, since we no longer need
- to avoid freeing it. If EXACT is true, grow exactly, otherwise
- grow exponentially. */
-
-template<typename T>
-void
-va_stack::reserve (vec<T, va_stack, vl_embed> *&v, unsigned nelems, bool exact
- MEM_STAT_DECL)
-{
- int ix = stack_vec_register_index (static_cast<void *> (v));
- if (ix >= 0)
- unregister_stack_vec (ix);
- else
- {
- /* V is already on the heap. */
- va_heap::reserve (reinterpret_cast<vec<T, va_heap, vl_embed> *&> (v),
- nelems, exact PASS_MEM_STAT);
- return;
- }
-
- /* Move VEC_ to the heap. */
- nelems += v->vecpfx_.num_;
- vec<T, va_stack, vl_embed> *oldvec = v;
- v = NULL;
- va_heap::reserve (reinterpret_cast<vec<T, va_heap, vl_embed> *&>(v), nelems,
- exact PASS_MEM_STAT);
- if (v && oldvec)
- {
- v->vecpfx_.num_ = oldvec->length ();
- memcpy (v->vecdata_,
- oldvec->vecdata_,
- oldvec->length () * sizeof (T));
- }
-}
-
-
-/* Free a vector allocated on the stack. Don't actually free it if we
- find it in the hash table. */
-
-template<typename T>
-void
-va_stack::release (vec<T, va_stack, vl_embed> *&v)
-{
- if (v == NULL)
- return;
-
- int ix = stack_vec_register_index (static_cast<void *> (v));
- if (ix >= 0)
- {
- unregister_stack_vec (ix);
- v = NULL;
- }
- else
- {
- /* The vector was not on the list of vectors allocated on the stack, so it
- must be allocated on the heap. */
- va_heap::release (reinterpret_cast<vec<T, va_heap, vl_embed> *&> (v));
- }
-}
-
-
/* Generic vector template. Default values for A and L indicate the
most commonly used strategies.
@@ -562,11 +454,11 @@ template<typename T, typename A>
struct GTY((user)) vec<T, A, vl_embed>
{
public:
- unsigned allocated (void) const { return vecpfx_.alloc_; }
- unsigned length (void) const { return vecpfx_.num_; }
- bool is_empty (void) const { return vecpfx_.num_ == 0; }
- T *address (void) { return vecdata_; }
- const T *address (void) const { return vecdata_; }
+ 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; }
const T &operator[] (unsigned) const;
T &operator[] (unsigned);
T &last (void);
@@ -597,12 +489,11 @@ public:
friend struct va_gc;
friend struct va_gc_atomic;
friend struct va_heap;
- friend struct va_stack;
/* FIXME - These fields should be private, but we need to cater to
compilers that have stricter notions of PODness for types. */
- vec_prefix vecpfx_;
- T vecdata_[1];
+ vec_prefix m_vecpfx;
+ T m_vecdata[1];
};
@@ -719,7 +610,7 @@ vec_safe_grow_cleared (vec<T, A, vl_embed> *&v, unsigned len CXX_MEM_STAT_INFO)
{
unsigned oldlen = vec_safe_length (v);
vec_safe_grow (v, len PASS_MEM_STAT);
- memset (&(v->address()[oldlen]), 0, sizeof (T) * (len - oldlen));
+ memset (&(v->address ()[oldlen]), 0, sizeof (T) * (len - oldlen));
}
@@ -816,16 +707,16 @@ template<typename T, typename A>
inline const T &
vec<T, A, vl_embed>::operator[] (unsigned ix) const
{
- gcc_checking_assert (ix < vecpfx_.num_);
- return vecdata_[ix];
+ 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 < vecpfx_.num_);
- return vecdata_[ix];
+ gcc_checking_assert (ix < m_vecpfx.m_num);
+ return m_vecdata[ix];
}
@@ -835,8 +726,8 @@ template<typename T, typename A>
inline T &
vec<T, A, vl_embed>::last (void)
{
- gcc_checking_assert (vecpfx_.num_ > 0);
- return (*this)[vecpfx_.num_ - 1];
+ gcc_checking_assert (m_vecpfx.m_num > 0);
+ return (*this)[m_vecpfx.m_num - 1];
}
@@ -850,7 +741,7 @@ template<typename T, typename A>
inline bool
vec<T, A, vl_embed>::space (unsigned nelems) const
{
- return vecpfx_.alloc_ - vecpfx_.num_ >= nelems;
+ return m_vecpfx.m_alloc - m_vecpfx.m_num >= nelems;
}
@@ -858,16 +749,16 @@ vec<T, A, vl_embed>::space (unsigned nelems) const
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++)
+ 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 < vecpfx_.num_)
+ if (ix < m_vecpfx.m_num)
{
- *ptr = vecdata_[ix];
+ *ptr = m_vecdata[ix];
return true;
}
else
@@ -882,7 +773,7 @@ vec<T, A, vl_embed>::iterate (unsigned ix, T *ptr) const
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++)
+ for (ix = 0; v->iterate (ix, &ptr); ix++)
continue;
This variant is for vectors of objects. */
@@ -891,9 +782,9 @@ template<typename T, typename A>
inline bool
vec<T, A, vl_embed>::iterate (unsigned ix, T **ptr) const
{
- if (ix < vecpfx_.num_)
+ if (ix < m_vecpfx.m_num)
{
- *ptr = CONST_CAST (T *, &vecdata_[ix]);
+ *ptr = CONST_CAST (T *, &m_vecdata[ix]);
return true;
}
else
@@ -916,7 +807,7 @@ vec<T, A, vl_embed>::copy (ALONE_MEM_STAT_DECL) const
{
vec_alloc (new_vec, len PASS_MEM_STAT);
new_vec->embedded_init (len, len);
- memcpy (new_vec->address(), vecdata_, sizeof (T) * len);
+ memcpy (new_vec->address (), m_vecdata, sizeof (T) * len);
}
return new_vec;
}
@@ -929,12 +820,12 @@ template<typename T, typename A>
inline void
vec<T, A, vl_embed>::splice (vec<T, A, vl_embed> &src)
{
- unsigned len = src.length();
+ unsigned len = src.length ();
if (len)
{
gcc_checking_assert (space (len));
- memcpy (address() + length(), src.address(), len * sizeof (T));
- vecpfx_.num_ += len;
+ memcpy (address () + length (), src.address (), len * sizeof (T));
+ m_vecpfx.m_num += len;
}
}
@@ -956,7 +847,7 @@ inline T *
vec<T, A, vl_embed>::quick_push (const T &obj)
{
gcc_checking_assert (space (1));
- T *slot = &vecdata_[vecpfx_.num_++];
+ T *slot = &m_vecdata[m_vecpfx.m_num++];
*slot = obj;
return slot;
}
@@ -969,7 +860,7 @@ inline T &
vec<T, A, vl_embed>::pop (void)
{
gcc_checking_assert (length () > 0);
- return vecdata_[--vecpfx_.num_];
+ return m_vecdata[--m_vecpfx.m_num];
}
@@ -981,7 +872,7 @@ inline void
vec<T, A, vl_embed>::truncate (unsigned size)
{
gcc_checking_assert (length () >= size);
- vecpfx_.num_ = size;
+ m_vecpfx.m_num = size;
}
@@ -994,8 +885,8 @@ vec<T, A, vl_embed>::quick_insert (unsigned ix, const T &obj)
{
gcc_checking_assert (length () < allocated ());
gcc_checking_assert (ix <= length ());
- T *slot = &vecdata_[ix];
- memmove (slot + 1, slot, (vecpfx_.num_++ - ix) * sizeof (T));
+ T *slot = &m_vecdata[ix];
+ memmove (slot + 1, slot, (m_vecpfx.m_num++ - ix) * sizeof (T));
*slot = obj;
}
@@ -1008,9 +899,9 @@ template<typename T, typename A>
inline void
vec<T, A, vl_embed>::ordered_remove (unsigned ix)
{
- gcc_checking_assert (ix < length());
- T *slot = &vecdata_[ix];
- memmove (slot, slot + 1, (--vecpfx_.num_ - ix) * sizeof (T));
+ gcc_checking_assert (ix < length ());
+ T *slot = &m_vecdata[ix];
+ memmove (slot, slot + 1, (--m_vecpfx.m_num - ix) * sizeof (T));
}
@@ -1021,8 +912,8 @@ template<typename T, typename A>
inline void
vec<T, A, vl_embed>::unordered_remove (unsigned ix)
{
- gcc_checking_assert (ix < length());
- vecdata_[ix] = vecdata_[--vecpfx_.num_];
+ gcc_checking_assert (ix < length ());
+ m_vecdata[ix] = m_vecdata[--m_vecpfx.m_num];
}
@@ -1033,10 +924,10 @@ 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 = &vecdata_[ix];
- vecpfx_.num_ -= len;
- memmove (slot, slot + len, (vecpfx_.num_ - ix) * sizeof (T));
+ 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));
}
@@ -1047,7 +938,7 @@ template<typename T, typename A>
inline void
vec<T, A, vl_embed>::qsort (int (*cmp) (const void *, const void *))
{
- ::qsort (address(), length(), sizeof (T), cmp);
+ ::qsort (address (), length (), sizeof (T), cmp);
}
@@ -1091,7 +982,7 @@ vec<T, A, vl_embed>::lower_bound (T obj, bool (*lessthan)(const T &, const T &))
final member):
size_t vec<T, A, vl_embed>::embedded_size (unsigned alloc);
- void v->embedded_init(unsigned alloc, unsigned num);
+ void v->embedded_init (unsigned alloc, unsigned num);
These allow the caller to perform the memory allocation. */
@@ -1100,7 +991,7 @@ inline size_t
vec<T, A, vl_embed>::embedded_size (unsigned alloc)
{
typedef vec<T, A, vl_embed> vec_embedded;
- return offsetof (vec_embedded, vecdata_) + alloc * sizeof (T);
+ return offsetof (vec_embedded, m_vecdata) + alloc * sizeof (T);
}
@@ -1111,8 +1002,9 @@ template<typename T, typename A>
inline void
vec<T, A, vl_embed>::embedded_init (unsigned alloc, unsigned num)
{
- vecpfx_.alloc_ = alloc;
- vecpfx_.num_ = num;
+ m_vecpfx.m_alloc = alloc;
+ m_vecpfx.m_has_auto_buf = 0;
+ m_vecpfx.m_num = num;
}
@@ -1123,8 +1015,8 @@ template<typename T, typename A>
inline void
vec<T, A, vl_embed>::quick_grow (unsigned len)
{
- gcc_checking_assert (length () <= len && len <= vecpfx_.alloc_);
- vecpfx_.num_ = len;
+ gcc_checking_assert (length () <= len && len <= m_vecpfx.m_alloc);
+ m_vecpfx.m_num = len;
}
@@ -1137,7 +1029,7 @@ vec<T, A, vl_embed>::quick_grow_cleared (unsigned len)
{
unsigned oldlen = length ();
quick_grow (len);
- memset (&(address()[oldlen]), 0, sizeof (T) * (len - oldlen));
+ memset (&(address ()[oldlen]), 0, sizeof (T) * (len - oldlen));
}
@@ -1218,8 +1110,8 @@ gt_pch_nx (vec<T, A, vl_embed> *v, gt_pointer_operator op, void *cookie)
As long as we use C++03, we cannot have constructors nor
destructors in classes that are stored in unions. */
-template<typename T, typename A>
-struct vec<T, A, vl_ptr>
+template<typename T>
+struct vec<T, va_heap, vl_ptr>
{
public:
/* Memory allocation and deallocation for the embedded vector.
@@ -1229,37 +1121,37 @@ public:
/* Vector operations. */
bool exists (void) const
- { return vec_ != NULL; }
+ { return m_vec != NULL; }
bool is_empty (void) const
- { return vec_ ? vec_->is_empty() : true; }
+ { return m_vec ? m_vec->is_empty () : true; }
unsigned length (void) const
- { return vec_ ? vec_->length() : 0; }
+ { return m_vec ? m_vec->length () : 0; }
T *address (void)
- { return vec_ ? vec_->vecdata_ : NULL; }
+ { return m_vec ? m_vec->m_vecdata : NULL; }
const T *address (void) const
- { return vec_ ? vec_->vecdata_ : NULL; }
+ { return m_vec ? m_vec->m_vecdata : NULL; }
const T &operator[] (unsigned ix) const
- { return (*vec_)[ix]; }
+ { return (*m_vec)[ix]; }
bool operator!=(const vec &other) const
{ return !(*this == other); }
bool operator==(const vec &other) const
- { return address() == other.address(); }
+ { return address () == other.address (); }
T &operator[] (unsigned ix)
- { return (*vec_)[ix]; }
+ { return (*m_vec)[ix]; }
T &last (void)
- { return vec_->last(); }
+ { return m_vec->last (); }
bool space (int nelems) const
- { return vec_ ? vec_->space (nelems) : nelems == 0; }
+ { return m_vec ? m_vec->space (nelems) : nelems == 0; }
bool iterate (unsigned ix, T *p) const;
bool iterate (unsigned ix, T **p) const;
@@ -1284,23 +1176,39 @@ public:
void qsort (int (*) (const void *, const void *));
unsigned lower_bound (T, bool (*)(const T &, const T &)) const;
- template<typename T1>
- friend void va_stack::alloc(vec<T1, va_stack, vl_ptr>&, unsigned,
- vec<T1, va_stack, vl_embed> *);
+ 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, A, vl_embed> *vec_;
+ vec<T, va_heap, vl_embed> *m_vec;
};
-/* Empty specialization for GC allocation. This will prevent GC
- vectors from using the vl_ptr layout. FIXME: This is needed to
- circumvent limitations in the GTY machinery. */
-
-template<typename T>
-struct vec<T, va_gc, vl_ptr>
+/* stack_vec is a subclass of vec containing N elements of internal storage.
+ You probably only want to allocate this on the stack because if the array
+ ends up being larger or much smaller than N it will be wasting space. */
+template<typename T, size_t N>
+class stack_vec : public vec<T, va_heap>
{
+public:
+ stack_vec ()
+ {
+ m_header.m_alloc = N;
+ m_header.m_has_auto_buf = 1;
+ m_header.m_num = 0;
+ this->m_vec = reinterpret_cast<vec<T, va_heap, vl_embed> *> (&m_header);
+ }
+
+ ~stack_vec ()
+ {
+ this->release ();
+ }
+
+private:
+ friend class vec<T, va_heap, vl_ptr>;
+
+ vec_prefix m_header;
+ T m_data[N];
};
@@ -1343,58 +1251,19 @@ vec_free (vec<T> *&v)
}
-/* Allocate a new stack vector with space for exactly NELEMS objects.
- If NELEMS is zero, NO vector is created.
-
- For the stack allocator, no memory is really allocated. The vector
- is initialized to be at address SPACE and contain NELEMS slots.
- Memory allocation actually occurs in the expansion of VEC_alloc.
-
- Usage notes:
-
- * This does not allocate an instance of vec<T, A>. It allocates the
- actual vector of elements (i.e., vec<T, A, vl_embed>) inside a
- vec<T, A> instance.
-
- * This allocator must always be a macro:
-
- We support a vector which starts out with space on the stack and
- switches to heap space when forced to reallocate. This works a
- little differently. In the case of stack vectors, vec_alloc will
- expand to a call to vec_alloc_1 that calls XALLOCAVAR to request
- the initial allocation. This uses alloca to get the initial
- space. Since alloca can not be usefully called in an inline
- function, vec_alloc must always be a macro.
-
- Important limitations of stack vectors:
-
- - Only the initial allocation will be made using alloca, so pass
- a reasonable estimate that doesn't use too much stack space;
- don't pass zero.
-
- - Don't return a stack-allocated vector from the function which
- allocated it. */
-
-#define vec_stack_alloc(T,V,N) \
- do { \
- typedef vec<T, va_stack, vl_embed> stackv; \
- va_stack::alloc (V, N, XALLOCAVAR (stackv, stackv::embedded_size (N)));\
- } while (0)
-
-
/* 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++)
+ for (ix = 0; v.iterate (ix, &ptr); ix++)
continue; */
-template<typename T, typename A>
+template<typename T>
inline bool
-vec<T, A, vl_ptr>::iterate (unsigned ix, T *ptr) const
+vec<T, va_heap, vl_ptr>::iterate (unsigned ix, T *ptr) const
{
- if (vec_)
- return vec_->iterate (ix, ptr);
+ if (m_vec)
+ return m_vec->iterate (ix, ptr);
else
{
*ptr = 0;
@@ -1407,17 +1276,17 @@ vec<T, A, vl_ptr>::iterate (unsigned ix, T *ptr) const
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++)
+ for (ix = 0; v->iterate (ix, &ptr); ix++)
continue;
This variant is for vectors of objects. */
-template<typename T, typename A>
+template<typename T>
inline bool
-vec<T, A, vl_ptr>::iterate (unsigned ix, T **ptr) const
+vec<T, va_heap, vl_ptr>::iterate (unsigned ix, T **ptr) const
{
- if (vec_)
- return vec_->iterate (ix, ptr);
+ if (m_vec)
+ return m_vec->iterate (ix, ptr);
else
{
*ptr = 0;
@@ -1451,13 +1320,13 @@ vec<T, A, vl_ptr>::iterate (unsigned ix, T **ptr) const
/* Return a copy of this vector. */
-template<typename T, typename A>
-inline vec<T, A, vl_ptr>
-vec<T, A, vl_ptr>::copy (ALONE_MEM_STAT_DECL) const
+template<typename T>
+inline vec<T, va_heap, vl_ptr>
+vec<T, va_heap, vl_ptr>::copy (ALONE_MEM_STAT_DECL) const
{
- vec<T, A, vl_ptr> new_vec = vNULL;
+ vec<T, va_heap, vl_ptr> new_vec = vNULL;
if (length ())
- new_vec.vec_ = vec_->copy ();
+ new_vec.m_vec = m_vec->copy ();
return new_vec;
}
@@ -1471,14 +1340,34 @@ vec<T, A, vl_ptr>::copy (ALONE_MEM_STAT_DECL) const
Note that this can cause the embedded vector to be reallocated.
Returns true iff reallocation actually occurred. */
-template<typename T, typename A>
+template<typename T>
inline bool
-vec<T, A, vl_ptr>::reserve (unsigned nelems, bool exact MEM_STAT_DECL)
-{
- bool extend = nelems ? !space (nelems) : false;
- if (extend)
- A::reserve (vec_, nelems, exact PASS_MEM_STAT);
- return extend;
+vec<T, va_heap, vl_ptr>::reserve (unsigned nelems, bool exact MEM_STAT_DECL)
+{
+ if (!nelems || 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)
+ {
+ memcpy (m_vec->address (), oldvec->address (), sizeof (T) * oldsize);
+ m_vec->m_vecpfx.m_num = oldsize;
+ }
+
+ return true;
}
@@ -1487,9 +1376,9 @@ vec<T, A, vl_ptr>::reserve (unsigned nelems, bool exact MEM_STAT_DECL)
embedded vector to be reallocated. Returns true iff reallocation
actually occurred. */
-template<typename T, typename A>
+template<typename T>
inline bool
-vec<T, A, vl_ptr>::reserve_exact (unsigned nelems MEM_STAT_DECL)
+vec<T, va_heap, vl_ptr>::reserve_exact (unsigned nelems MEM_STAT_DECL)
{
return reserve (nelems, true PASS_MEM_STAT);
}
@@ -1500,11 +1389,11 @@ vec<T, A, vl_ptr>::reserve_exact (unsigned nelems MEM_STAT_DECL)
unconditionally allocated from scratch. The old one, if it
existed, is lost. */
-template<typename T, typename A>
+template<typename T>
inline void
-vec<T, A, vl_ptr>::create (unsigned nelems MEM_STAT_DECL)
+vec<T, va_heap, vl_ptr>::create (unsigned nelems MEM_STAT_DECL)
{
- vec_ = NULL;
+ m_vec = NULL;
if (nelems > 0)
reserve_exact (nelems PASS_MEM_STAT);
}
@@ -1512,26 +1401,33 @@ vec<T, A, vl_ptr>::create (unsigned nelems MEM_STAT_DECL)
/* Free the memory occupied by the embedded vector. */
-template<typename T, typename A>
+template<typename T>
inline void
-vec<T, A, vl_ptr>::release (void)
+vec<T, va_heap, vl_ptr>::release (void)
{
- if (vec_)
- A::release (vec_);
-}
+ if (!m_vec)
+ return;
+ if (using_auto_storage ())
+ {
+ static_cast<stack_vec<T, 1> *> (this)->m_header.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, typename A>
+template<typename T>
inline void
-vec<T, A, vl_ptr>::splice (vec<T, A, vl_ptr> &src)
+vec<T, va_heap, vl_ptr>::splice (vec<T, va_heap, vl_ptr> &src)
{
- if (src.vec_)
- vec_->splice (*(src.vec_));
+ if (src.m_vec)
+ m_vec->splice (*(src.m_vec));
}
@@ -1540,13 +1436,14 @@ vec<T, A, vl_ptr>::splice (vec<T, A, vl_ptr> &src)
If there is not enough headroom in this vector, it will be reallocated
as needed. */
-template<typename T, typename A>
+template<typename T>
inline void
-vec<T, A, vl_ptr>::safe_splice (vec<T, A, vl_ptr> &src MEM_STAT_DECL)
+vec<T, va_heap, vl_ptr>::safe_splice (vec<T, va_heap, vl_ptr> &src
+ MEM_STAT_DECL)
{
- if (src.length())
+ if (src.length ())
{
- reserve_exact (src.length());
+ reserve_exact (src.length ());
splice (src);
}
}
@@ -1556,11 +1453,11 @@ vec<T, A, vl_ptr>::safe_splice (vec<T, A, vl_ptr> &src MEM_STAT_DECL)
sufficient space in the vector. Return a pointer to the slot
where OBJ was inserted. */
-template<typename T, typename A>
+template<typename T>
inline T *
-vec<T, A, vl_ptr>::quick_push (const T &obj)
+vec<T, va_heap, vl_ptr>::quick_push (const T &obj)
{
- return vec_->quick_push (obj);
+ return m_vec->quick_push (obj);
}
@@ -1568,9 +1465,9 @@ vec<T, A, vl_ptr>::quick_push (const T &obj)
the embedded vector, if needed. Return a pointer to the slot where
OBJ was inserted. */
-template<typename T, typename A>
+template<typename T>
inline T *
-vec<T, A, vl_ptr>::safe_push (const T &obj MEM_STAT_DECL)
+vec<T, va_heap, vl_ptr>::safe_push (const T &obj MEM_STAT_DECL)
{
reserve (1, false PASS_MEM_STAT);
return quick_push (obj);
@@ -1579,23 +1476,23 @@ vec<T, A, vl_ptr>::safe_push (const T &obj MEM_STAT_DECL)
/* Pop and return the last element off the end of the vector. */
-template<typename T, typename A>
+template<typename T>
inline T &
-vec<T, A, vl_ptr>::pop (void)
+vec<T, va_heap, vl_ptr>::pop (void)
{
- return vec_->pop ();
+ 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, typename A>
+template<typename T>
inline void
-vec<T, A, vl_ptr>::truncate (unsigned size)
+vec<T, va_heap, vl_ptr>::truncate (unsigned size)
{
- if (vec_)
- vec_->truncate (size);
+ if (m_vec)
+ m_vec->truncate (size);
else
gcc_checking_assert (size == 0);
}
@@ -1605,14 +1502,14 @@ vec<T, A, vl_ptr>::truncate (unsigned size)
longer than the current length. The new elements are
uninitialized. Reallocate the internal vector, if needed. */
-template<typename T, typename A>
+template<typename T>
inline void
-vec<T, A, vl_ptr>::safe_grow (unsigned len MEM_STAT_DECL)
+vec<T, va_heap, vl_ptr>::safe_grow (unsigned len MEM_STAT_DECL)
{
unsigned oldlen = length ();
gcc_checking_assert (oldlen <= len);
reserve_exact (len - oldlen PASS_MEM_STAT);
- vec_->quick_grow (len);
+ m_vec->quick_grow (len);
}
@@ -1620,25 +1517,25 @@ vec<T, A, vl_ptr>::safe_grow (unsigned len MEM_STAT_DECL)
long or longer than the current length. The new elements are
initialized to zero. Reallocate the internal vector, if needed. */
-template<typename T, typename A>
+template<typename T>
inline void
-vec<T, A, vl_ptr>::safe_grow_cleared (unsigned len MEM_STAT_DECL)
+vec<T, va_heap, vl_ptr>::safe_grow_cleared (unsigned len MEM_STAT_DECL)
{
unsigned oldlen = length ();
safe_grow (len PASS_MEM_STAT);
- memset (&(address()[oldlen]), 0, sizeof (T) * (len - oldlen));
+ memset (&(address ()[oldlen]), 0, sizeof (T) * (len - oldlen));
}
/* 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, typename A>
+template<typename T>
inline void
-vec<T, A, vl_ptr>::quick_grow (unsigned len)
+vec<T, va_heap, vl_ptr>::quick_grow (unsigned len)
{
- gcc_checking_assert (vec_);
- vec_->quick_grow (len);
+ gcc_checking_assert (m_vec);
+ m_vec->quick_grow (len);
}
@@ -1646,32 +1543,32 @@ vec<T, A, vl_ptr>::quick_grow (unsigned len)
internal vector. If the vector cannot be extended, a runtime
assertion will be triggered. */
-template<typename T, typename A>
+template<typename T>
inline void
-vec<T, A, vl_ptr>::quick_grow_cleared (unsigned len)
+vec<T, va_heap, vl_ptr>::quick_grow_cleared (unsigned len)
{
- gcc_checking_assert (vec_);
- vec_->quick_grow_cleared (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, typename A>
+template<typename T>
inline void
-vec<T, A, vl_ptr>::quick_insert (unsigned ix, const T &obj)
+vec<T, va_heap, vl_ptr>::quick_insert (unsigned ix, const T &obj)
{
- vec_->quick_insert (ix, 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, typename A>
+template<typename T>
inline void
-vec<T, A, vl_ptr>::safe_insert (unsigned ix, const T &obj MEM_STAT_DECL)
+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);
@@ -1682,45 +1579,45 @@ vec<T, A, vl_ptr>::safe_insert (unsigned ix, const T &obj MEM_STAT_DECL)
remaining elements is preserved. This is an O(N) operation due to
a memmove. */
-template<typename T, typename A>
+template<typename T>
inline void
-vec<T, A, vl_ptr>::ordered_remove (unsigned ix)
+vec<T, va_heap, vl_ptr>::ordered_remove (unsigned ix)
{
- vec_->ordered_remove (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, typename A>
+template<typename T>
inline void
-vec<T, A, vl_ptr>::unordered_remove (unsigned ix)
+vec<T, va_heap, vl_ptr>::unordered_remove (unsigned ix)
{
- vec_->unordered_remove (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, typename A>
+template<typename T>
inline void
-vec<T, A, vl_ptr>::block_remove (unsigned ix, unsigned len)
+vec<T, va_heap, vl_ptr>::block_remove (unsigned ix, unsigned len)
{
- vec_->block_remove (ix, 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, typename A>
+template<typename T>
inline void
-vec<T, A, vl_ptr>::qsort (int (*cmp) (const void *, const void *))
+vec<T, va_heap, vl_ptr>::qsort (int (*cmp) (const void *, const void *))
{
- if (vec_)
- vec_->qsort (cmp);
+ if (m_vec)
+ m_vec->qsort (cmp);
}
@@ -1729,16 +1626,29 @@ vec<T, A, vl_ptr>::qsort (int (*cmp) (const void *, const void *))
function that returns true if the first argument is strictly less
than the second. */
-template<typename T, typename A>
+template<typename T>
inline unsigned
-vec<T, A, vl_ptr>::lower_bound (T obj, bool (*lessthan)(const T &, const T &))
+vec<T, va_heap, vl_ptr>::lower_bound (T obj,
+ bool (*lessthan)(const T &, const T &))
const
{
- return vec_ ? vec_->lower_bound (obj, lessthan) : 0;
+ return m_vec ? m_vec->lower_bound (obj, lessthan) : 0;
+}
+
+template<typename T>
+inline bool
+vec<T, va_heap, vl_ptr>::using_auto_storage () const
+{
+ if (!m_vec->m_vecpfx.m_has_auto_buf)
+ return false;
+
+ const vec_prefix *auto_header
+ = &static_cast<const stack_vec<T, 1> *> (this)->m_header;
+ return reinterpret_cast<vec_prefix *> (m_vec) == auto_header;
}
#if (GCC_VERSION >= 3000)
-# pragma GCC poison vec_ vecpfx_ vecdata_
+# pragma GCC poison m_vec m_vecpfx m_vecdata
#endif
#endif // GCC_VEC_H
diff --git a/gcc/vmsdbgout.c b/gcc/vmsdbgout.c
index 9f05c1cd32b..9f308a6fdf2 100644
--- a/gcc/vmsdbgout.c
+++ b/gcc/vmsdbgout.c
@@ -221,9 +221,9 @@ const struct gcc_debug_hooks vmsdbg_debug_hooks
#ifndef UNALIGNED_OFFSET_ASM_OP
#define UNALIGNED_OFFSET_ASM_OP(OFFSET) \
- (NUMBYTES(OFFSET) == 4 \
+ (NUMBYTES (OFFSET) == 4 \
? VMS_UNALIGNED_LONG_ASM_OP \
- : (NUMBYTES(OFFSET) == 2 ? VMS_UNALIGNED_SHORT_ASM_OP : VMS_ASM_BYTE_OP))
+ : (NUMBYTES (OFFSET) == 2 ? VMS_UNALIGNED_SHORT_ASM_OP : VMS_ASM_BYTE_OP))
#endif
/* Definitions of defaults for formats and names of various special
@@ -329,7 +329,7 @@ static char text_end_label[MAX_ARTIFICIAL_LABEL_BYTES];
#ifndef ASM_OUTPUT_DEBUG_DATA
#define ASM_OUTPUT_DEBUG_DATA(FILE,VALUE) \
- fprintf ((FILE), "\t%s\t%#lx", UNALIGNED_OFFSET_ASM_OP(VALUE), VALUE)
+ fprintf ((FILE), "\t%s\t%#lx", UNALIGNED_OFFSET_ASM_OP (VALUE), VALUE)
#endif
#ifndef ASM_OUTPUT_DEBUG_ADDR_DATA
@@ -351,7 +351,7 @@ static char text_end_label[MAX_ARTIFICIAL_LABEL_BYTES];
#define ASM_OUTPUT_DEBUG_STRING(FILE,P) \
do \
{ \
- register int slen = strlen(P); \
+ register int slen = strlen (P); \
register const char *p = (P); \
register int i; \
fprintf (FILE, "\t.ascii \""); \
diff --git a/gcc/vtable-verify.c b/gcc/vtable-verify.c
index 1b5cc0c6e98..fb26978d273 100644
--- a/gcc/vtable-verify.c
+++ b/gcc/vtable-verify.c
@@ -138,7 +138,11 @@ along with GCC; see the file COPYING3. If not see
#include "coretypes.h"
#include "tree.h"
#include "basic-block.h"
-#include "tree-ssa.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+#include "tree-ssanames.h"
#include "tree-pass.h"
#include "cfgloop.h"
@@ -173,7 +177,7 @@ vtbl_map_node_registration_find (struct vtbl_map_node *node,
struct vtable_registration key;
struct vtable_registration **slot;
- gcc_assert (node && node->registered.is_created());
+ gcc_assert (node && node->registered.is_created ());
key.vtable_decl = vtable_decl;
slot = (struct vtable_registration **) node->registered.find_slot (&key,
@@ -182,7 +186,7 @@ vtbl_map_node_registration_find (struct vtbl_map_node *node,
if (slot && (*slot))
{
unsigned i;
- for (i = 0; i < ((*slot)->offsets).length(); ++i)
+ for (i = 0; i < ((*slot)->offsets).length (); ++i)
if ((*slot)->offsets[i] == offset)
return true;
}
@@ -203,7 +207,7 @@ vtbl_map_node_registration_insert (struct vtbl_map_node *node,
struct vtable_registration **slot;
bool inserted_something = false;
- if (!node || !node->registered.is_created())
+ if (!node || !node->registered.is_created ())
return false;
key.vtable_decl = vtable_decl;
@@ -227,7 +231,7 @@ vtbl_map_node_registration_insert (struct vtbl_map_node *node,
contains the offset. If not, we need to add the offset. */
unsigned i;
bool found = false;
- for (i = 0; i < ((*slot)->offsets).length() && !found; ++i)
+ for (i = 0; i < ((*slot)->offsets).length () && !found; ++i)
if ((*slot)->offsets[i] == offset)
found = true;
@@ -319,7 +323,7 @@ vtbl_map_get_node (tree class_type)
tree class_name;
unsigned int type_quals;
- if (!vtbl_map_hash.is_created())
+ if (!vtbl_map_hash.is_created ())
return NULL;
gcc_assert (TREE_CODE (class_type) == RECORD_TYPE);
@@ -356,7 +360,7 @@ find_or_create_vtbl_map_node (tree base_class_type)
tree class_type_decl;
unsigned int type_quals;
- if (!vtbl_map_hash.is_created())
+ if (!vtbl_map_hash.is_created ())
vtbl_map_hash.create (10);
/* Find the TYPE_DECL for the class. */
@@ -772,8 +776,8 @@ const pass_data pass_data_vtable_verify =
class pass_vtable_verify : public gimple_opt_pass
{
public:
- pass_vtable_verify(gcc::context *ctxt)
- : gimple_opt_pass(pass_data_vtable_verify, ctxt)
+ pass_vtable_verify (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_vtable_verify, ctxt)
{}
/* opt_pass methods: */
diff --git a/gcc/web.c b/gcc/web.c
index 6c3ab952188..c64e0bd7bd1 100644
--- a/gcc/web.c
+++ b/gcc/web.c
@@ -378,7 +378,7 @@ web_main (void)
}
/* Record the number of uses and defs at the beginning of the optimization. */
- def_entry = XCNEWVEC (struct web_entry, DF_DEFS_TABLE_SIZE());
+ def_entry = XCNEWVEC (struct web_entry, DF_DEFS_TABLE_SIZE ());
used = XCNEWVEC (unsigned, max);
use_entry = XCNEWVEC (struct web_entry, uses_num);
@@ -473,8 +473,8 @@ const pass_data pass_data_web =
class pass_web : public rtl_opt_pass
{
public:
- pass_web(gcc::context *ctxt)
- : rtl_opt_pass(pass_data_web, ctxt)
+ pass_web (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_web, ctxt)
{}
/* opt_pass methods: */
diff --git a/include/ChangeLog b/include/ChangeLog
index e41915461d6..a43d36758d6 100644
--- a/include/ChangeLog
+++ b/include/ChangeLog
@@ -1,3 +1,17 @@
+2013-10-29 Marc Glisse <marc.glisse@inria.fr>
+
+ PR tree-optimization/58689
+ * ansidecl.h (ATTRIBUTE_RETURNS_NONNULL): New macro.
+ * libiberty.h (basename, lbasename, dos_lbasename, unix_lbasename,
+ concat_copy): Mark with attributes nonnull(1) and returns_nonnull.
+ (concat, reconcat, concat_copy2, choose_temp_base, xstrerror,
+ xmalloc, xrealloc, xcalloc, xstrdup, xstrndup, xmemdup, pex_init):
+ Mark with attribute returns_nonnull.
+
+2013-10-22 Sterling Augustine <saugustine@google.com>
+
+ * gdb/gdb-index.h: Merge from gdb tree.
+
2013-08-20 Alan Modra <amodra@gmail.com>
* floatformat.h (floatformat_ibm_long_double): Delete.
@@ -47,8 +61,8 @@
* demangle.h (enum demangle_component_type): Add
DEMANGLE_COMPONENT_TAGGED_NAME.
-2012-10-29 Sterling Augustine <saugustine@google.com>
- Cary Coutant <ccoutant@google.com>
+2012-10-29 Sterling Augustine <saugustine@google.com>
+ Cary Coutant <ccoutant@google.com>
* dwarf2.h (dwarf_location_list_entry_type): New enum with fields
DW_LLE_GNU_end_of_list_entry, DW_LLE_GNU_base_address_selection_entry,
@@ -315,7 +329,7 @@
Sync LD plugin patch series (part 1/6) with src/include/.
* plugin-api.h (LDPT_GNU_LD_VERSION): New ld_plugin_tag enum member.
-2010-10-06 Andi Kleen <ak@linux.intel.com>
+2010-10-06 Andi Kleen <ak@linux.intel.com>
* libiberty.h (setproctitle): Add prototype.
diff --git a/include/ansidecl.h b/include/ansidecl.h
index 40f4a5fea42..5cd03a7d760 100644
--- a/include/ansidecl.h
+++ b/include/ansidecl.h
@@ -311,6 +311,15 @@ So instead we use the macro below and test it against specific values. */
# endif /* GNUC >= 3.3 */
#endif /* ATTRIBUTE_NONNULL */
+/* Attribute `returns_nonnull' was valid as of gcc 4.9. */
+#ifndef ATTRIBUTE_RETURNS_NONNULL
+# if (GCC_VERSION >= 4009)
+# define ATTRIBUTE_RETURNS_NONNULL __attribute__ ((__returns_nonnull__))
+# else
+# define ATTRIBUTE_RETURNS_NONNULL
+# endif /* GNUC >= 4.9 */
+#endif /* ATTRIBUTE_RETURNS_NONNULL */
+
/* Attribute `pure' was valid as of gcc 3.0. */
#ifndef ATTRIBUTE_PURE
# if (GCC_VERSION >= 3000)
diff --git a/include/gdb/gdb-index.h b/include/gdb/gdb-index.h
new file mode 100644
index 00000000000..b43c68f9e3b
--- /dev/null
+++ b/include/gdb/gdb-index.h
@@ -0,0 +1,99 @@
+/* Public attributes of the .gdb_index section.
+ Copyright 2012 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ 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 of the License, 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, see <http://www.gnu.org/licenses/>. */
+
+/* This file contains values for understanding the .gdb_index section
+ needed by more than just GDB, e.g. readelf. */
+
+#ifndef GDB_INDEX_H
+#define GDB_INDEX_H
+
+/* Each symbol in .gdb_index refers to a set of CUs that defines the symbol.
+ Each CU is represented by a 32 bit number that is the index of the CU in
+ the CU table, plus some attributes of the use of the symbol in that CU.
+
+ The values are defined such that if all the bits are zero, then no
+ special meaning is assigned to any of them. This is done to preserve
+ compatibility with older indices. The way this is done is to specify
+ that if the GDB_INDEX_SYMBOL_KIND value is zero then all other attribute
+ bits must be zero.
+
+ 0-23 CU index
+ 24-27 reserved
+ 28-30 symbol kind
+ 31 0 == global, 1 == static
+
+ Bits 24-27 are reserved because it's easier to relax restrictions than
+ it is to impose them after the fact. At present 24 bits to represent
+ the CU index is plenty. If we need more bits for the CU index or for
+ attributes then we have them. */
+
+/* Whether the symbol is in GLOBAL_BLOCK (== 0) or STATIC_BLOCK (== 1). */
+#define GDB_INDEX_SYMBOL_STATIC_SHIFT 31
+#define GDB_INDEX_SYMBOL_STATIC_MASK 1
+#define GDB_INDEX_SYMBOL_STATIC_VALUE(cu_index) \
+ (((cu_index) >> GDB_INDEX_SYMBOL_STATIC_SHIFT) & GDB_INDEX_SYMBOL_STATIC_MASK)
+#define GDB_INDEX_SYMBOL_STATIC_SET_VALUE(cu_index, value) \
+ do { \
+ (cu_index) |= (((value) & GDB_INDEX_SYMBOL_STATIC_MASK) \
+ << GDB_INDEX_SYMBOL_STATIC_SHIFT); \
+ } while (0)
+
+/* The kind of the symbol.
+ We don't use GDB's internal values as these numbers are published
+ so that other tools can build and read .gdb_index. */
+
+typedef enum {
+ /* Special value to indicate no attributes are present. */
+ GDB_INDEX_SYMBOL_KIND_NONE = 0,
+ GDB_INDEX_SYMBOL_KIND_TYPE = 1,
+ GDB_INDEX_SYMBOL_KIND_VARIABLE = 2,
+ GDB_INDEX_SYMBOL_KIND_FUNCTION = 3,
+ GDB_INDEX_SYMBOL_KIND_OTHER = 4,
+ /* We currently allocate 3 bits to record the symbol kind.
+ Give the unused bits a value so gdb will print them sensibly. */
+ GDB_INDEX_SYMBOL_KIND_UNUSED5 = 5,
+ GDB_INDEX_SYMBOL_KIND_UNUSED6 = 6,
+ GDB_INDEX_SYMBOL_KIND_UNUSED7 = 7
+} gdb_index_symbol_kind;
+
+#define GDB_INDEX_SYMBOL_KIND_SHIFT 28
+#define GDB_INDEX_SYMBOL_KIND_MASK 7
+#define GDB_INDEX_SYMBOL_KIND_VALUE(cu_index) \
+ ((gdb_index_symbol_kind) (((cu_index) >> GDB_INDEX_SYMBOL_KIND_SHIFT) \
+ & GDB_INDEX_SYMBOL_KIND_MASK))
+#define GDB_INDEX_SYMBOL_KIND_SET_VALUE(cu_index, value) \
+ do { \
+ (cu_index) |= (((value) & GDB_INDEX_SYMBOL_KIND_MASK) \
+ << GDB_INDEX_SYMBOL_KIND_SHIFT); \
+ } while (0)
+
+#define GDB_INDEX_RESERVED_SHIFT 24
+#define GDB_INDEX_RESERVED_MASK 15
+#define GDB_INDEX_RESERVED_VALUE(cu_index) \
+ (((cu_index) >> GDB_INDEX_RESERVED_SHIFT) & GDB_INDEX_RESERVED_MASK)
+
+/* CU index. */
+#define GDB_INDEX_CU_BITSIZE 24
+#define GDB_INDEX_CU_MASK ((1 << GDB_INDEX_CU_BITSIZE) - 1)
+#define GDB_INDEX_CU_VALUE(cu_index) ((cu_index) & GDB_INDEX_CU_MASK)
+#define GDB_INDEX_CU_SET_VALUE(cu_index, value) \
+ do { \
+ (cu_index) |= (value) & GDB_INDEX_CU_MASK; \
+ } while (0)
+
+#endif /* GDB_INDEX_H */
diff --git a/include/libiberty.h b/include/libiberty.h
index cacde800ea3..f2cf573d1b6 100644
--- a/include/libiberty.h
+++ b/include/libiberty.h
@@ -107,7 +107,7 @@ extern int countargv (char**);
is 1, we found it so don't provide any declaration at all. */
#if !HAVE_DECL_BASENAME
#if defined (__GNU_LIBRARY__ ) || defined (__linux__) || defined (__FreeBSD__) || defined (__OpenBSD__) || defined(__NetBSD__) || defined (__CYGWIN__) || defined (__CYGWIN32__) || defined (__MINGW32__) || defined (HAVE_DECL_BASENAME)
-extern char *basename (const char *);
+extern char *basename (const char *) ATTRIBUTE_RETURNS_NONNULL ATTRIBUTE_NONNULL(1);
#else
/* Do not allow basename to be used if there is no prototype seen. We
either need to use the above prototype or have one from
@@ -118,18 +118,18 @@ extern char *basename (const char *);
/* A well-defined basename () that is always compiled in. */
-extern const char *lbasename (const char *);
+extern const char *lbasename (const char *) ATTRIBUTE_RETURNS_NONNULL ATTRIBUTE_NONNULL(1);
/* Same, but assumes DOS semantics (drive name, backslash is also a
dir separator) regardless of host. */
-extern const char *dos_lbasename (const char *);
+extern const char *dos_lbasename (const char *) ATTRIBUTE_RETURNS_NONNULL ATTRIBUTE_NONNULL(1);
/* Same, but assumes Unix semantics (absolute paths always start with
a slash, only forward slash is accepted as dir separator)
regardless of host. */
-extern const char *unix_lbasename (const char *);
+extern const char *unix_lbasename (const char *) ATTRIBUTE_RETURNS_NONNULL ATTRIBUTE_NONNULL(1);
/* A well-defined realpath () that is always compiled in. */
@@ -139,7 +139,7 @@ extern char *lrealpath (const char *);
the last argument of this function, to terminate the list of
strings. Allocates memory using xmalloc. */
-extern char *concat (const char *, ...) ATTRIBUTE_MALLOC ATTRIBUTE_SENTINEL;
+extern char *concat (const char *, ...) ATTRIBUTE_MALLOC ATTRIBUTE_RETURNS_NONNULL ATTRIBUTE_SENTINEL;
/* Concatenate an arbitrary number of strings. You must pass NULL as
the last argument of this function, to terminate the list of
@@ -148,7 +148,7 @@ extern char *concat (const char *, ...) ATTRIBUTE_MALLOC ATTRIBUTE_SENTINEL;
pointer to be freed after the new string is created, similar to the
way xrealloc works. */
-extern char *reconcat (char *, const char *, ...) ATTRIBUTE_MALLOC ATTRIBUTE_SENTINEL;
+extern char *reconcat (char *, const char *, ...) ATTRIBUTE_MALLOC ATTRIBUTE_RETURNS_NONNULL ATTRIBUTE_SENTINEL;
/* Determine the length of concatenating an arbitrary number of
strings. You must pass NULL as the last argument of this function,
@@ -161,14 +161,14 @@ extern unsigned long concat_length (const char *, ...) ATTRIBUTE_SENTINEL;
to terminate the list of strings. The supplied memory is assumed
to be large enough. */
-extern char *concat_copy (char *, const char *, ...) ATTRIBUTE_SENTINEL;
+extern char *concat_copy (char *, const char *, ...) ATTRIBUTE_RETURNS_NONNULL ATTRIBUTE_NONNULL(1) ATTRIBUTE_SENTINEL;
/* Concatenate an arbitrary number of strings into a GLOBAL area of
memory. You must pass NULL as the last argument of this function,
to terminate the list of strings. The supplied memory is assumed
to be large enough. */
-extern char *concat_copy2 (const char *, ...) ATTRIBUTE_SENTINEL;
+extern char *concat_copy2 (const char *, ...) ATTRIBUTE_RETURNS_NONNULL ATTRIBUTE_SENTINEL;
/* This is the global area used by concat_copy2. */
@@ -226,7 +226,7 @@ extern char *make_relative_prefix_ignore_links (const char *, const char *,
/* Choose a temporary directory to use for scratch files. */
-extern char *choose_temp_base (void) ATTRIBUTE_MALLOC;
+extern char *choose_temp_base (void) ATTRIBUTE_MALLOC ATTRIBUTE_RETURNS_NONNULL;
/* Return a temporary file name or NULL if unable to create one. */
@@ -256,7 +256,7 @@ extern int strtoerrno (const char *);
/* ANSI's strerror(), but more robust. */
-extern char *xstrerror (int);
+extern char *xstrerror (int) ATTRIBUTE_RETURNS_NONNULL;
/* Return the maximum signal number for which strsignal will return a
string. */
@@ -298,30 +298,30 @@ extern void xmalloc_failed (size_t) ATTRIBUTE_NORETURN;
message to stderr (using the name set by xmalloc_set_program_name,
if any) and then call xexit. */
-extern void *xmalloc (size_t) ATTRIBUTE_MALLOC;
+extern void *xmalloc (size_t) ATTRIBUTE_MALLOC ATTRIBUTE_RETURNS_NONNULL;
/* Reallocate memory without fail. This works like xmalloc. Note,
realloc type functions are not suitable for attribute malloc since
they may return the same address across multiple calls. */
-extern void *xrealloc (void *, size_t);
+extern void *xrealloc (void *, size_t) ATTRIBUTE_RETURNS_NONNULL;
/* Allocate memory without fail and set it to zero. This works like
xmalloc. */
-extern void *xcalloc (size_t, size_t) ATTRIBUTE_MALLOC;
+extern void *xcalloc (size_t, size_t) ATTRIBUTE_MALLOC ATTRIBUTE_RETURNS_NONNULL;
/* Copy a string into a memory buffer without fail. */
-extern char *xstrdup (const char *) ATTRIBUTE_MALLOC;
+extern char *xstrdup (const char *) ATTRIBUTE_MALLOC ATTRIBUTE_RETURNS_NONNULL;
/* Copy at most N characters from string into a buffer without fail. */
-extern char *xstrndup (const char *, size_t) ATTRIBUTE_MALLOC;
+extern char *xstrndup (const char *, size_t) ATTRIBUTE_MALLOC ATTRIBUTE_RETURNS_NONNULL;
/* Copy an existing memory buffer to a new memory buffer without fail. */
-extern void *xmemdup (const void *, size_t, size_t) ATTRIBUTE_MALLOC;
+extern void *xmemdup (const void *, size_t, size_t) ATTRIBUTE_MALLOC ATTRIBUTE_RETURNS_NONNULL;
/* Physical memory routines. Return values are in BYTES. */
extern double physmem_total (void);
@@ -399,7 +399,7 @@ extern void hex_init (void);
Returns NULL on error. */
extern struct pex_obj *pex_init (int flags, const char *pname,
- const char *tempbase);
+ const char *tempbase) ATTRIBUTE_RETURNS_NONNULL;
/* Flags for pex_run. These are bits to be or'ed together. */
diff --git a/libatomic/ChangeLog b/libatomic/ChangeLog
index 794aa7262a3..06aff7feb35 100644
--- a/libatomic/ChangeLog
+++ b/libatomic/ChangeLog
@@ -1,3 +1,26 @@
+2013-11-10 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/x86/fenv.c: New file.
+
+2013-11-07 Joseph Myers <joseph@codesourcery.com>
+
+ * fenv.c: New file.
+ * libatomic.map (LIBATOMIC_1.1): New symbol version. Include
+ __atomic_feraiseexcept.
+ * configure.ac (libtool_VERSION): Change to 2:0:1.
+ (fenv.h): Test for header.
+ * Makefile.am (libatomic_la_SOURCES): Add fenv.c.
+ * Makefile.in, auto-config.h.in, configure: Regenerate.
+
+2013-10-17 Michael Hudson-Doyle <michael.hudson@linaro.org>
+
+ * libatomic/configure.tgt (aarch64*): Remove code preventing
+ build.
+
+2013-09-20 Alan Modra <amodra@gmail.com>
+
+ * configure: Regenerate.
+
2013-01-14 Richard Sandiford <rdsandiford@googlemail.com>
Update copyright years.
diff --git a/libatomic/Makefile.am b/libatomic/Makefile.am
index a98ee6437ce..537b24a7149 100644
--- a/libatomic/Makefile.am
+++ b/libatomic/Makefile.am
@@ -67,7 +67,8 @@ endif
libatomic_version_info = -version-info $(libtool_VERSION)
libatomic_la_LDFLAGS = $(libatomic_version_info) $(libatomic_version_script)
-libatomic_la_SOURCES = gload.c gstore.c gcas.c gexch.c glfree.c lock.c init.c
+libatomic_la_SOURCES = gload.c gstore.c gcas.c gexch.c glfree.c lock.c init.c \
+ fenv.c
SIZEOBJS = load store cas exch fadd fsub fand fior fxor fnand tas
SIZES = @SIZES@
diff --git a/libatomic/Makefile.in b/libatomic/Makefile.in
index 8efa07d0bdd..e759e60f80e 100644
--- a/libatomic/Makefile.in
+++ b/libatomic/Makefile.in
@@ -113,14 +113,14 @@ am__uninstall_files_from_dir = { \
am__installdirs = "$(DESTDIR)$(toolexeclibdir)"
LTLIBRARIES = $(noinst_LTLIBRARIES) $(toolexeclib_LTLIBRARIES)
am_libatomic_la_OBJECTS = gload.lo gstore.lo gcas.lo gexch.lo \
- glfree.lo lock.lo init.lo
+ glfree.lo lock.lo init.lo fenv.lo
libatomic_la_OBJECTS = $(am_libatomic_la_OBJECTS)
libatomic_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(libatomic_la_LDFLAGS) $(LDFLAGS) -o $@
libatomic_convenience_la_DEPENDENCIES = $(libatomic_la_LIBADD)
am__objects_1 = gload.lo gstore.lo gcas.lo gexch.lo glfree.lo lock.lo \
- init.lo
+ init.lo fenv.lo
am_libatomic_convenience_la_OBJECTS = $(am__objects_1)
libatomic_convenience_la_OBJECTS = \
$(am_libatomic_convenience_la_OBJECTS)
@@ -314,7 +314,9 @@ noinst_LTLIBRARIES = libatomic_convenience.la
@LIBAT_BUILD_VERSIONED_SHLIB_SUN_TRUE@@LIBAT_BUILD_VERSIONED_SHLIB_TRUE@libatomic_version_dep = libatomic.map-sun
libatomic_version_info = -version-info $(libtool_VERSION)
libatomic_la_LDFLAGS = $(libatomic_version_info) $(libatomic_version_script)
-libatomic_la_SOURCES = gload.c gstore.c gcas.c gexch.c glfree.c lock.c init.c
+libatomic_la_SOURCES = gload.c gstore.c gcas.c gexch.c glfree.c lock.c init.c \
+ fenv.c
+
SIZEOBJS = load store cas exch fadd fsub fand fior fxor fnand tas
EXTRA_libatomic_la_SOURCES = $(addsuffix _n.c,$(SIZEOBJS))
libatomic_la_DEPENDENCIES = $(libatomic_la_LIBADD) $(libatomic_version_dep)
@@ -452,6 +454,7 @@ mostlyclean-compile:
distclean-compile:
-rm -f *.tab.c
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fenv.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gcas.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gexch.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/glfree.Plo@am__quote@
diff --git a/libatomic/auto-config.h.in b/libatomic/auto-config.h.in
index ab080e7d6e4..83e54e2db3b 100644
--- a/libatomic/auto-config.h.in
+++ b/libatomic/auto-config.h.in
@@ -105,6 +105,9 @@
/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
+/* Define to 1 if you have the <fenv.h> header file. */
+#undef HAVE_FENV_H
+
/* Define to 1 if the target supports __attribute__((ifunc(...))). */
#undef HAVE_IFUNC
diff --git a/libatomic/config/x86/fenv.c b/libatomic/config/x86/fenv.c
new file mode 100644
index 00000000000..154983e5f45
--- /dev/null
+++ b/libatomic/config/x86/fenv.c
@@ -0,0 +1,116 @@
+/* Copyright (C) 2013 Free Software Foundation, Inc.
+
+ This file is part of the GNU Atomic Library (libatomic).
+
+ Libatomic is free software; you can redistribute 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.
+
+ Libatomic is distributed in the hope that it will be useful, but WITHOUT 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/>. */
+
+#include "libatomic_i.h"
+
+#define FE_INVALID 0x01
+#define FE_DENORM 0x02
+#define FE_DIVBYZERO 0x04
+#define FE_OVERFLOW 0x08
+#define FE_UNDERFLOW 0x10
+#define FE_INEXACT 0x20
+
+struct fenv
+{
+ unsigned short int __control_word;
+ unsigned short int __unused1;
+ unsigned short int __status_word;
+ unsigned short int __unused2;
+ unsigned short int __tags;
+ unsigned short int __unused3;
+ unsigned int __eip;
+ unsigned short int __cs_selector;
+ unsigned int __opcode:11;
+ unsigned int __unused4:5;
+ unsigned int __data_offset;
+ unsigned short int __data_selector;
+ unsigned short int __unused5;
+};
+
+/* Raise the supported floating-point exceptions from EXCEPTS. Other
+ bits in EXCEPTS are ignored. */
+
+void
+__atomic_feraiseexcept (int excepts)
+{
+ if (excepts & FE_INVALID)
+ {
+ float f = 0.0f;
+#ifdef __x86_64__
+ volatile float r __attribute__ ((unused));
+ asm volatile ("%vdivss\t{%0, %d0|%d0, %0}" : "+x" (f));
+ r = f; /* Needed to trigger exception. */
+#else
+ asm volatile ("fdiv\t{%y0, %0|%0, %y0}" : "+t" (f));
+ /* No need for fwait, exception is triggered by emitted fstp. */
+#endif
+ }
+ if (excepts & FE_DENORM)
+ {
+ struct fenv temp;
+ asm volatile ("fnstenv\t%0" : "=m" (temp));
+ temp.__status_word |= FE_DENORM;
+ asm volatile ("fldenv\t%0" : : "m" (temp));
+ asm volatile ("fwait");
+ }
+ if (excepts & FE_DIVBYZERO)
+ {
+ float f = 1.0f, g = 0.0f;
+#ifdef __x86_64__
+ volatile float r __attribute__ ((unused));
+ asm volatile ("%vdivss\t{%1, %d0|%d0, %1}" : "+x" (f) : "xm" (g));
+ r = f; /* Needed to trigger exception. */
+#else
+ asm volatile ("fdivs\t%1" : "+t" (f) : "m" (g));
+ /* No need for fwait, exception is triggered by emitted fstp. */
+#endif
+ }
+ if (excepts & FE_OVERFLOW)
+ {
+ struct fenv temp;
+ asm volatile ("fnstenv\t%0" : "=m" (temp));
+ temp.__status_word |= FE_OVERFLOW;
+ asm volatile ("fldenv\t%0" : : "m" (temp));
+ asm volatile ("fwait");
+ }
+ if (excepts & FE_UNDERFLOW)
+ {
+ struct fenv temp;
+ asm volatile ("fnstenv\t%0" : "=m" (temp));
+ temp.__status_word |= FE_UNDERFLOW;
+ asm volatile ("fldenv\t%0" : : "m" (temp));
+ asm volatile ("fwait");
+ }
+ if (excepts & FE_INEXACT)
+ {
+ float f = 1.0f, g = 3.0f;
+#ifdef __x86_64__
+ volatile float r __attribute__ ((unused));
+ asm volatile ("%vdivss\t{%1, %d0|%d0, %1}" : "+x" (f) : "xm" (g));
+ r = f; /* Needed to trigger exception. */
+#else
+ asm volatile ("fdivs\t%1" : "+t" (f) : "m" (g));
+ /* No need for fwait, exception is triggered by emitted fstp. */
+#endif
+ }
+}
diff --git a/libatomic/configure b/libatomic/configure
index a2562b4c9ea..d707b096c2e 100755
--- a/libatomic/configure
+++ b/libatomic/configure
@@ -655,7 +655,6 @@ CCAS
am__fastdepCC_FALSE
am__fastdepCC_TRUE
CCDEPMODE
-am__nodep
AMDEPBACKSLASH
AMDEP_FALSE
AMDEP_TRUE
@@ -2001,6 +2000,93 @@ rm -f conftest.val
return $ac_retval
} # ac_fn_c_compute_int
+
+# ac_fn_c_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_c_check_header_mongrel ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; 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_c_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_c_try_cpp "$LINENO"; then :
+ ac_header_preproc=yes
+else
+ ac_header_preproc=no
+fi
+rm -f conftest.err 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_c_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 { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; 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; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+
+} # ac_fn_c_check_header_mongrel
cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
@@ -3045,11 +3131,11 @@ MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
# We need awk for the "check" target. The system "awk" is bad on
# some platforms.
-# Always define AMTAR for backward compatibility. Yes, it's still used
-# in the wild :-( We should find a proper way to deprecate it ...
-AMTAR='$${TAR-tar}'
+# Always define AMTAR for backward compatibility.
+
+AMTAR=${AMTAR-"${am_missing_run}tar"}
-am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'
+am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'
@@ -3947,7 +4033,6 @@ fi
if test "x$enable_dependency_tracking" != xno; then
am_depcomp="$ac_aux_dir/depcomp"
AMDEPBACKSLASH='\'
- am__nodep='_no'
fi
if test "x$enable_dependency_tracking" != xno; then
AMDEP_TRUE=
@@ -3972,7 +4057,6 @@ else
# 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'.
- rm -rf conftest.dir
mkdir conftest.dir
# Copy depcomp to subdir because otherwise we won't find it if we're
# using a relative directory.
@@ -4032,7 +4116,7 @@ else
break
fi
;;
- msvc7 | msvc7msys | msvisualcpp | msvcmsys)
+ msvisualcpp | msvcmsys)
# This compiler won't grok `-c -o', but also, the minuso test has
# not run yet. These depmodes are late enough in the game, and
# so weak that their functioning should not be impacted.
@@ -4107,7 +4191,6 @@ else
# 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'.
- rm -rf conftest.dir
mkdir conftest.dir
# Copy depcomp to subdir because otherwise we won't find it if we're
# using a relative directory.
@@ -4165,7 +4248,7 @@ else
break
fi
;;
- msvc7 | msvc7msys | msvisualcpp | msvcmsys)
+ msvisualcpp | msvcmsys)
# This compiler won't grok `-c -o', but also, the minuso test has
# not run yet. These depmodes are late enough in the game, and
# so weak that their functioning should not be impacted.
@@ -6509,7 +6592,7 @@ ia64-*-hpux*)
rm -rf conftest*
;;
-x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \
+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
@@ -6534,7 +6617,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
;;
esac
;;
- ppc64-*linux*|powerpc64-*linux*)
+ powerpc64le-*linux*)
+ LD="${LD-ld} -m elf32lppclinux"
+ ;;
+ powerpc64-*linux*)
LD="${LD-ld} -m elf32ppclinux"
;;
s390x-*linux*)
@@ -6553,7 +6639,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
x86_64-*linux*)
LD="${LD-ld} -m elf_x86_64"
;;
- ppc*-*linux*|powerpc*-*linux*)
+ powerpcle-*linux*)
+ LD="${LD-ld} -m elf64lppc"
+ ;;
+ powerpc-*linux*)
LD="${LD-ld} -m elf64ppc"
;;
s390*-*linux*|s390*-*tpf*)
@@ -11017,7 +11106,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11020 "configure"
+#line 11109 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -11123,7 +11212,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11126 "configure"
+#line 11215 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -11387,7 +11476,7 @@ fi
# For libtool versioning info, format is CURRENT:REVISION:AGE
-libtool_VERSION=1:0:0
+libtool_VERSION=2:0:1
# Get target configury.
@@ -11951,6 +12040,18 @@ ac_config_commands="$ac_config_commands gstdint.h"
+for ac_header in fenv.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "fenv.h" "ac_cv_header_fenv_h" "$ac_includes_default"
+if test "x$ac_cv_header_fenv_h" = x""yes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_FENV_H 1
+_ACEOF
+
+fi
+
+done
+
# Check for common type sizes
diff --git a/libatomic/configure.ac b/libatomic/configure.ac
index 0dc4a9809ec..fd2d35bf04f 100644
--- a/libatomic/configure.ac
+++ b/libatomic/configure.ac
@@ -148,7 +148,7 @@ AC_SUBST(enable_static)
AM_MAINTAINER_MODE
# For libtool versioning info, format is CURRENT:REVISION:AGE
-libtool_VERSION=1:0:0
+libtool_VERSION=2:0:1
AC_SUBST(libtool_VERSION)
# Get target configury.
@@ -165,6 +165,7 @@ CFLAGS="$save_CFLAGS -fno-sync-libcalls $XCFLAGS"
AC_STDC_HEADERS
ACX_HEADER_STRING
GCC_HEADER_STDINT(gstdint.h)
+AC_CHECK_HEADERS([fenv.h])
# Check for common type sizes
LIBAT_FORALL_MODES([LIBAT_HAVE_INT_MODE])
diff --git a/libatomic/configure.tgt b/libatomic/configure.tgt
index b9e5d6ce015..7eaab38d97c 100644
--- a/libatomic/configure.tgt
+++ b/libatomic/configure.tgt
@@ -95,11 +95,6 @@ fi
# Other system configury
case "${target}" in
- aarch64*)
- # This is currently not supported in AArch64.
- UNSUPPORTED=1
- ;;
-
arm*-*-linux*)
# OS support for atomic primitives.
config_path="${config_path} linux/arm posix"
diff --git a/libatomic/fenv.c b/libatomic/fenv.c
new file mode 100644
index 00000000000..752cf3b378d
--- /dev/null
+++ b/libatomic/fenv.c
@@ -0,0 +1,72 @@
+/* Copyright (C) 2012-2013 Free Software Foundation, Inc.
+
+ This file is part of the GNU Atomic Library (libatomic).
+
+ Libatomic is free software; you can redistribute 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.
+
+ Libatomic is distributed in the hope that it will be useful, but WITHOUT 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/>. */
+
+#include "libatomic_i.h"
+
+#ifdef HAVE_FENV_H
+# include <fenv.h>
+#endif
+
+/* Raise the supported floating-point exceptions from EXCEPTS. Other
+ bits in EXCEPTS are ignored. */
+
+void
+__atomic_feraiseexcept (int excepts __attribute__ ((unused)))
+{
+ volatile float r __attribute__ ((unused));
+#ifdef FE_INVALID
+ if (excepts & FE_INVALID)
+ {
+ volatile float zero = 0.0f;
+ r = zero / zero;
+ }
+#endif
+#ifdef FE_DIVBYZERO
+ if (excepts & FE_DIVBYZERO)
+ {
+ volatile float zero = 0.0f;
+ r = 1.0f / zero;
+ }
+#endif
+#ifdef FE_OVERFLOW
+ if (excepts & FE_OVERFLOW)
+ {
+ volatile float max = __FLT_MAX__;
+ r = max * max;
+ }
+#endif
+#ifdef FE_UNDERFLOW
+ if (excepts & FE_UNDERFLOW)
+ {
+ volatile float min = __FLT_MIN__;
+ r = min * min;
+ }
+#endif
+#ifdef FE_INEXACT
+ if (excepts & FE_INEXACT)
+ {
+ volatile float three = 3.0f;
+ r = 1.0f / three;
+ }
+#endif
+}
diff --git a/libatomic/libatomic.map b/libatomic/libatomic.map
index bcf077370a9..8fd2bafd80c 100644
--- a/libatomic/libatomic.map
+++ b/libatomic/libatomic.map
@@ -95,3 +95,7 @@ LIBATOMIC_1.0 {
local:
*;
};
+LIBATOMIC_1.1 {
+ global:
+ __atomic_feraiseexcept;
+} LIBATOMIC_1.0;
diff --git a/libbacktrace/ChangeLog b/libbacktrace/ChangeLog
index d6f7205f1d1..86536a16adb 100644
--- a/libbacktrace/ChangeLog
+++ b/libbacktrace/ChangeLog
@@ -1,3 +1,18 @@
+2013-10-17 Ian Lance Taylor <iant@google.com>
+
+ * elf.c (elf_add): Don't get the wrong offsets if a debug section
+ is missing.
+
+2013-10-15 David Malcolm <dmalcolm@redhat.com>
+
+ * configure.ac: Add --enable-host-shared, setting up
+ pre-existing PIC_FLAG variable within Makefile.am et al.
+ * configure: Regenerate.
+
+2013-09-20 Alan Modra <amodra@gmail.com>
+
+ * configure: Regenerate.
+
2013-07-23 Alexander Monakov <amonakov@ispras.ru>
* elf.c (elf_syminfo): Loop over the elf_syminfo_data chain.
diff --git a/libbacktrace/configure b/libbacktrace/configure
index 4e9d5933a4a..15bdaff6a6c 100755
--- a/libbacktrace/configure
+++ b/libbacktrace/configure
@@ -731,6 +731,7 @@ with_gnu_ld
enable_libtool_lock
enable_multilib
with_system_libunwind
+enable_host_shared
'
ac_precious_vars='build_alias
host_alias
@@ -1369,6 +1370,7 @@ Optional Features:
optimize for fast installation [default=yes]
--disable-libtool-lock avoid locking (might break parallel builds)
--enable-multilib build many library versions (default)
+ --enable-host-shared build host code as shared libraries
Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
@@ -6842,7 +6844,7 @@ ia64-*-hpux*)
rm -rf conftest*
;;
-x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \
+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
@@ -6867,7 +6869,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
;;
esac
;;
- ppc64-*linux*|powerpc64-*linux*)
+ powerpc64le-*linux*)
+ LD="${LD-ld} -m elf32lppclinux"
+ ;;
+ powerpc64-*linux*)
LD="${LD-ld} -m elf32ppclinux"
;;
s390x-*linux*)
@@ -6886,7 +6891,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
x86_64-*linux*)
LD="${LD-ld} -m elf_x86_64"
;;
- ppc*-*linux*|powerpc*-*linux*)
+ powerpcle-*linux*)
+ LD="${LD-ld} -m elf64lppc"
+ ;;
+ powerpc-*linux*)
LD="${LD-ld} -m elf64ppc"
;;
s390*-*linux*|s390*-*tpf*)
@@ -11081,7 +11089,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11084 "configure"
+#line 11092 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -11187,7 +11195,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11190 "configure"
+#line 11198 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -11690,6 +11698,12 @@ PIC_FLAG=
if test -n "${with_target_subdir}"; then
PIC_FLAG=-fPIC
fi
+# Similarly, use -fPIC with --enable-host-shared:
+# Check whether --enable-host-shared was given.
+if test "${enable_host_shared+set}" = set; then :
+ enableval=$enable_host_shared; PIC_FLAG=-fPIC
+fi
+
# Test for __sync support.
diff --git a/libbacktrace/configure.ac b/libbacktrace/configure.ac
index 28b2a1cd5c7..48c86203837 100644
--- a/libbacktrace/configure.ac
+++ b/libbacktrace/configure.ac
@@ -165,6 +165,11 @@ PIC_FLAG=
if test -n "${with_target_subdir}"; then
PIC_FLAG=-fPIC
fi
+# Similarly, use -fPIC with --enable-host-shared:
+AC_ARG_ENABLE(host-shared,
+[AS_HELP_STRING([--enable-host-shared],
+ [build host code as shared libraries])],
+[PIC_FLAG=-fPIC], [])
AC_SUBST(PIC_FLAG)
# Test for __sync support.
diff --git a/libbacktrace/elf.c b/libbacktrace/elf.c
index c1dbc5492e0..2161ad2a258 100644
--- a/libbacktrace/elf.c
+++ b/libbacktrace/elf.c
@@ -759,6 +759,8 @@ elf_add (struct backtrace_state *state, int descriptor, uintptr_t base_address,
{
off_t end;
+ if (sections[i].size == 0)
+ continue;
if (min_offset == 0 || sections[i].offset < min_offset)
min_offset = sections[i].offset;
end = sections[i].offset + sections[i].size;
@@ -785,8 +787,13 @@ elf_add (struct backtrace_state *state, int descriptor, uintptr_t base_address,
descriptor = -1;
for (i = 0; i < (int) DEBUG_MAX; ++i)
- sections[i].data = ((const unsigned char *) debug_view.data
- + (sections[i].offset - min_offset));
+ {
+ if (sections[i].size == 0)
+ sections[i].data = NULL;
+ else
+ sections[i].data = ((const unsigned char *) debug_view.data
+ + (sections[i].offset - min_offset));
+ }
if (!backtrace_dwarf_add (state, base_address,
sections[DEBUG_INFO].data,
diff --git a/libcilkrts/ChangeLog b/libcilkrts/ChangeLog
new file mode 100644
index 00000000000..7f94aefb65f
--- /dev/null
+++ b/libcilkrts/ChangeLog
@@ -0,0 +1,155 @@
+2013-11-08 Balaji V. Iyer <balaji.v.iyer@intel.com>
+
+ PR c/59039
+ * runtime/cilk_fiber-unix.cpp: Fixed a crash in run() function
+ when optimization is turned on.
+
+2013-11-04 Balaji V. Iyer <balaji.v.iyer@intel.com>
+
+ PR bootstrap/58951
+ * Makefile.am (AM_LDFLAGS): Removed -ldl flag.
+ * Makefile.in: Regenerate.
+
+2013-11-04 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * runtime/os-unix.c [__sun__ && __svr4__]: Include <sched.h>.
+ (__cilkrts_hardware_cpu_count) [__sun__ && __svr4__]: Use sysconf.
+ (__cilkrts_yield) [__sun__ && __svr4__]: Use sched_yield.
+
+2013-10-31 Balaji V. Iyer <balaji.v.iyer@intel.com>
+
+ PR other/58925
+ * configure.ac: Added target_alias and GCC_LIBSTDCXX_RAW_CXX_FLAGS
+ fields.
+ * configure: Regenerated.
+ * aclocal.m4: Likewise.
+ * Makefile.in: Likewise.
+ * Makefile.am: Added gcc_version field.
+
+2013-10-30 Balaji V. Iyer <balaji.v.iyer@intel.com>
+
+ * configure.ac: Changed a case statement to include i386.
+ * configure: Regenerated.
+
+2013-10-30 Balaji V. Iyer <balaji.v.iyer@intel.com>
+
+ PR bootstrap/58918
+ * configure: Reconfigured.
+ * configure.ac: Add AC_FUNC_ALLOCA.
+ * runtime/sysdep-unix.c: Added check for alloca.h before
+ including it.
+ * config/x86/cilk-abi-vla.c: Likewise.
+ * runtime/cilk_fiber-unix.cpp: Likewise.
+
+2013-10-29 Tobias Burnus <burnus@net-b.de>
+
+ * configure.ac: Add AM_MAINTAINER_MODE.
+ * aclocal.m4: Regenerate.
+ * configure.ac: Regenerate.
+ * Makefile.in: Regenerate.
+
+2013-10-23 Balaji V. Iyer <balaji.v.iyer@intel.com>
+
+ * libcilkrts/Makefile.am: New file. Libcilkrts version 3902.
+ * libcilkrts/Makefile.in: Likewise
+ * libcilkrts/README: Likewise
+ * libcilkrts/aclocal.m4: Likewise
+ * libcilkrts/configure: Likewise
+ * libcilkrts/configure.ac: Likewise
+ * libcilkrts/include/cilk/cilk.h: Likewise
+ * libcilkrts/include/cilk/cilk_api.h: Likewise
+ * libcilkrts/include/cilk/cilk_api_linux.h: Likewise
+ * libcilkrts/include/cilk/cilk_stub.h: Likewise
+ * libcilkrts/include/cilk/cilk_undocumented.h: Likewise
+ * libcilkrts/include/cilk/common.h: Likewise
+ * libcilkrts/include/cilk/holder.h: Likewise
+ * libcilkrts/include/cilk/hyperobject_base.h: Likewise
+ * libcilkrts/include/cilk/metaprogramming.h: Likewise
+ * libcilkrts/include/cilk/reducer.h: Likewise
+ * libcilkrts/include/cilk/reducer_file.h: Likewise
+ * libcilkrts/include/cilk/reducer_list.h: Likewise
+ * libcilkrts/include/cilk/reducer_max.h: Likewise
+ * libcilkrts/include/cilk/reducer_min.h: Likewise
+ * libcilkrts/include/cilk/reducer_min_max.h: Likewise
+ * libcilkrts/include/cilk/reducer_opadd.h: Likewise
+ * libcilkrts/include/cilk/reducer_opand.h: Likewise
+ * libcilkrts/include/cilk/reducer_opmul.h: Likewise
+ * libcilkrts/include/cilk/reducer_opor.h: Likewise
+ * libcilkrts/include/cilk/reducer_opxor.h: Likewise
+ * libcilkrts/include/cilk/reducer_ostream.h: Likewise
+ * libcilkrts/include/cilk/reducer_string.h: Likewise
+ * libcilkrts/include/cilktools/cilkscreen.h: Likewise
+ * libcilkrts/include/cilktools/cilkview.h: Likewise
+ * libcilkrts/include/cilktools/fake_mutex.h: Likewise
+ * libcilkrts/include/cilktools/lock_guard.h: Likewise
+ * libcilkrts/include/internal/abi.h: Likewise
+ * libcilkrts/include/internal/cilk_fake.h: Likewise
+ * libcilkrts/include/internal/cilk_version.h: Likewise
+ * libcilkrts/include/internal/inspector-abi.h: Likewise
+ * libcilkrts/include/internal/metacall.h: Likewise
+ * libcilkrts/include/internal/rev.mk: Likewise
+ * libcilkrts/mk/cilk-version.mk: Likewise
+ * libcilkrts/mk/unix-common.mk: Likewise
+ * libcilkrts/runtime/acknowledgements.dox: Likewise
+ * libcilkrts/runtime/bug.cpp: Likewise
+ * libcilkrts/runtime/bug.h: Likewise
+ * libcilkrts/runtime/c_reducers.c: Likewise
+ * libcilkrts/runtime/cilk-abi-cilk-for.cpp: Likewise
+ * libcilkrts/runtime/cilk-abi-vla-internal.c: Likewise
+ * libcilkrts/runtime/cilk-abi-vla-internal.h: Likewise
+ * libcilkrts/runtime/cilk-abi-vla.c: Likewise
+ * libcilkrts/runtime/cilk-abi.c: Likewise
+ * libcilkrts/runtime/cilk-ittnotify.h: Likewise
+ * libcilkrts/runtime/cilk-tbb-interop.h: Likewise
+ * libcilkrts/runtime/cilk_api.c: Likewise
+ * libcilkrts/runtime/cilk_fiber-unix.cpp: Likewise
+ * libcilkrts/runtime/cilk_fiber-unix.h: Likewise
+ * libcilkrts/runtime/cilk_fiber.cpp: Likewise
+ * libcilkrts/runtime/cilk_fiber.h: Likewise
+ * libcilkrts/runtime/cilk_malloc.c: Likewise
+ * libcilkrts/runtime/cilk_malloc.h: Likewise
+ * libcilkrts/runtime/component.h: Likewise
+ * libcilkrts/runtime/doxygen-layout.xml: Likewise
+ * libcilkrts/runtime/doxygen.cfg: Likewise
+ * libcilkrts/runtime/except-gcc.cpp: Likewise
+ * libcilkrts/runtime/except-gcc.h: Likewise
+ * libcilkrts/runtime/except.h: Likewise
+ * libcilkrts/runtime/frame_malloc.c: Likewise
+ * libcilkrts/runtime/frame_malloc.h: Likewise
+ * libcilkrts/runtime/full_frame.c: Likewise
+ * libcilkrts/runtime/full_frame.h: Likewise
+ * libcilkrts/runtime/global_state.cpp: Likewise
+ * libcilkrts/runtime/global_state.h: Likewise
+ * libcilkrts/runtime/jmpbuf.c: Likewise
+ * libcilkrts/runtime/jmpbuf.h: Likewise
+ * libcilkrts/runtime/local_state.c: Likewise
+ * libcilkrts/runtime/local_state.h: Likewise
+ * libcilkrts/runtime/metacall_impl.c: Likewise
+ * libcilkrts/runtime/metacall_impl.h: Likewise
+ * libcilkrts/runtime/os-unix.c: Likewise
+ * libcilkrts/runtime/os.h: Likewise
+ * libcilkrts/runtime/os_mutex-unix.c: Likewise
+ * libcilkrts/runtime/os_mutex.h: Likewise
+ * libcilkrts/runtime/pedigrees.c: Likewise
+ * libcilkrts/runtime/pedigrees.h: Likewise
+ * libcilkrts/runtime/record-replay.cpp: Likewise
+ * libcilkrts/runtime/record-replay.h: Likewise
+ * libcilkrts/runtime/reducer_impl.cpp: Likewise
+ * libcilkrts/runtime/reducer_impl.h: Likewise
+ * libcilkrts/runtime/rts-common.h: Likewise
+ * libcilkrts/runtime/scheduler.c: Likewise
+ * libcilkrts/runtime/scheduler.h: Likewise
+ * libcilkrts/runtime/signal_node.c: Likewise
+ * libcilkrts/runtime/signal_node.h: Likewise
+ * libcilkrts/runtime/spin_mutex.c: Likewise
+ * libcilkrts/runtime/spin_mutex.h: Likewise
+ * libcilkrts/runtime/stacks.h: Likewise
+ * libcilkrts/runtime/stats.c: Likewise
+ * libcilkrts/runtime/stats.h: Likewise
+ * libcilkrts/runtime/symbol_test.c: Likewise
+ * libcilkrts/runtime/sysdep-unix.c: Likewise
+ * libcilkrts/runtime/sysdep.h: Likewise
+ * libcilkrts/runtime/unix_symbols.t: Likewise
+ * libcilkrts/runtime/worker_mutex.c: Likewise
+ * libcilkrts/runtime/worker_mutex.h: Likewise
+
diff --git a/libcilkrts/Makefile.am b/libcilkrts/Makefile.am
new file mode 100644
index 00000000000..1a8bafaa1f3
--- /dev/null
+++ b/libcilkrts/Makefile.am
@@ -0,0 +1,176 @@
+# @copyright
+# Copyright (C) 2011, 2013, Intel Corporation
+# All rights reserved.
+#
+# @copyright
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# @copyright
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+# WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+AUTOMAKE_OPTIONS = foreign
+
+# Use when building GCC
+ACLOCAL_AMFLAGS = -I .. -I ../config
+
+# Compiler and linker flags.
+GENERAL_FLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/runtime -I$(top_srcdir)/runtime/config/$(config_dir) -DIN_CILK_RUNTIME=1
+GENERAL_FLAGS += -D_Cilk_spawn="" -D_Cilk_sync="" -D_Cilk_for=for
+
+# Enable Intel Cilk Plus extension
+GENERAL_FLAGS += -fcilkplus
+
+AM_CFLAGS = $(GENERAL_FLAGS) -std=c99
+AM_CPPFLAGS = $(GENERAL_FLAGS)
+AM_LDFLAGS = -lpthread
+
+# May be used by toolexeclibdir.
+gcc_version := $(shell cat $(top_srcdir)/../gcc/BASE-VER)
+
+# Target list.
+toolexeclib_LTLIBRARIES = libcilkrts.la
+
+libcilkrts_la_SOURCES = \
+ runtime/config/$(config_dir)/cilk-abi-vla.c \
+ runtime/config/$(config_dir)/os-unix-sysdep.c \
+ runtime/bug.cpp \
+ runtime/cilk-abi.c \
+ runtime/cilk-abi-cilk-for.cpp \
+ runtime/cilk-abi-vla-internal.c \
+ runtime/cilk_api.c \
+ runtime/cilk_fiber.cpp \
+ runtime/cilk_fiber-unix.cpp \
+ runtime/cilk_malloc.c \
+ runtime/c_reducers.c \
+ runtime/except-gcc.cpp \
+ runtime/frame_malloc.c \
+ runtime/full_frame.c \
+ runtime/global_state.cpp \
+ runtime/jmpbuf.c \
+ runtime/local_state.c \
+ runtime/metacall_impl.c \
+ runtime/os_mutex-unix.c \
+ runtime/os-unix.c \
+ runtime/pedigrees.c \
+ runtime/record-replay.cpp \
+ runtime/reducer_impl.cpp \
+ runtime/scheduler.c \
+ runtime/signal_node.c \
+ runtime/spin_mutex.c \
+ runtime/stats.c \
+ runtime/symbol_test.c \
+ runtime/sysdep-unix.c \
+ runtime/worker_mutex.c
+
+
+# Load the $(REVISION) value.
+include include/internal/rev.mk
+
+#libcilkrts_la_LDFLAGS = -rpath '$(libdir)'
+libcilkrts_la_LDFLAGS = -version-info 5:0:0
+libcilkrts_la_LDFLAGS += -lpthread -ldl
+
+# If we're building on Linux, use the Linux version script
+if LINUX_LINKER_SCRIPT
+ libcilkrts_la_LDFLAGS += -Wl,--version-script,$(srcdir)/runtime/linux-symbols.ver
+endif
+
+# If we're building on MacOS, use the Mac versioning
+if MAC_LINKER_SCRIPT
+ libcilkrts_la_LDFLAGS += -Wl,-exported_symbols_list,$(srcdir)/runtime/mac-symbols.txt
+endif
+
+
+# Hack for Cygwin
+libcilkrts_la_LDFLAGS += -no-undefined
+
+# C/C++ header files for Cilk.
+cilkincludedir = $(includedir)/cilk
+cilkinclude_HEADERS = \
+ include/cilk/cilk_api.h \
+ include/cilk/cilk_api_linux.h \
+ include/cilk/cilk.h \
+ include/cilk/cilk_stub.h \
+ include/cilk/cilk_undocumented.h \
+ include/cilk/common.h \
+ include/cilk/holder.h \
+ include/cilk/hyperobject_base.h \
+ include/cilk/metaprogramming.h \
+ include/cilk/reducer_file.h \
+ include/cilk/reducer.h \
+ include/cilk/reducer_list.h \
+ include/cilk/reducer_max.h \
+ include/cilk/reducer_min.h \
+ include/cilk/reducer_min_max.h \
+ include/cilk/reducer_opadd.h \
+ include/cilk/reducer_opand.h \
+ include/cilk/reducer_opmul.h \
+ include/cilk/reducer_opor.h \
+ include/cilk/reducer_opxor.h \
+ include/cilk/reducer_ostream.h \
+ include/cilk/reducer_string.h
+
+
+# Work around what appears to be a GNU make bug handling MAKEFLAGS
+# values defined in terms of make variables, as is the case for CC and
+# friends when we are called from the top level Makefile.
+AM_MAKEFLAGS = \
+ "AR_FLAGS=$(AR_FLAGS)" \
+ "CC_FOR_BUILD=$(CC_FOR_BUILD)" \
+ "CFLAGS=$(CFLAGS)" \
+ "CXXFLAGS=$(CXXFLAGS)" \
+ "CFLAGS_FOR_BUILD=$(CFLAGS_FOR_BUILD)" \
+ "CFLAGS_FOR_TARGET=$(CFLAGS_FOR_TARGET)" \
+ "INSTALL=$(INSTALL)" \
+ "INSTALL_DATA=$(INSTALL_DATA)" \
+ "INSTALL_PROGRAM=$(INSTALL_PROGRAM)" \
+ "INSTALL_SCRIPT=$(INSTALL_SCRIPT)" \
+ "JC1FLAGS=$(JC1FLAGS)" \
+ "LDFLAGS=$(LDFLAGS)" \
+ "LIBCFLAGS=$(LIBCFLAGS)" \
+ "LIBCFLAGS_FOR_TARGET=$(LIBCFLAGS_FOR_TARGET)" \
+ "MAKE=$(MAKE)" \
+ "MAKEINFO=$(MAKEINFO) $(MAKEINFOFLAGS)" \
+ "PICFLAG=$(PICFLAG)" \
+ "PICFLAG_FOR_TARGET=$(PICFLAG_FOR_TARGET)" \
+ "SHELL=$(SHELL)" \
+ "RUNTESTFLAGS=$(RUNTESTFLAGS)" \
+ "exec_prefix=$(exec_prefix)" \
+ "infodir=$(infodir)" \
+ "libdir=$(libdir)" \
+ "prefix=$(prefix)" \
+ "includedir=$(includedir)" \
+ "AR=$(AR)" \
+ "AS=$(AS)" \
+ "LD=$(LD)" \
+ "LIBCFLAGS=$(LIBCFLAGS)" \
+ "NM=$(NM)" \
+ "PICFLAG=$(PICFLAG)" \
+ "RANLIB=$(RANLIB)" \
+ "DESTDIR=$(DESTDIR)"
+
+MAKEOVERRIDES=
+
diff --git a/libcilkrts/Makefile.in b/libcilkrts/Makefile.in
new file mode 100644
index 00000000000..a35eb7b63bc
--- /dev/null
+++ b/libcilkrts/Makefile.in
@@ -0,0 +1,1055 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in 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.
+
+@SET_MAKE@
+
+# @copyright
+# Copyright (C) 2011, 2013, Intel Corporation
+# All rights reserved.
+#
+# @copyright
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# @copyright
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+# WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+#########################################################################
+#
+# @copyright
+# Copyright (C) 2011-2013, Intel Corporation
+# All rights reserved.
+#
+# @copyright
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# @copyright
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+# WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+###########################################################################
+
+# DO NOT EDIT THIS FILE!
+#
+# It was automatically generated by cilkrts/include/internal/Makefile
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+DIST_COMMON = $(srcdir)/include/internal/rev.mk README ChangeLog \
+ $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+ $(top_srcdir)/configure $(am__configure_deps) \
+ $(srcdir)/../mkinstalldirs $(srcdir)/../depcomp \
+ $(cilkinclude_HEADERS)
+
+# If we're building on Linux, use the Linux version script
+@LINUX_LINKER_SCRIPT_TRUE@am__append_1 = -Wl,--version-script,$(srcdir)/runtime/linux-symbols.ver
+
+# If we're building on MacOS, use the Mac versioning
+@MAC_LINKER_SCRIPT_TRUE@am__append_2 = -Wl,-exported_symbols_list,$(srcdir)/runtime/mac-symbols.txt
+subdir = .
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \
+ $(top_srcdir)/../config/depstand.m4 \
+ $(top_srcdir)/../config/lead-dot.m4 \
+ $(top_srcdir)/../config/libstdc++-raw-cxx.m4 \
+ $(top_srcdir)/../config/multi.m4 \
+ $(top_srcdir)/../config/override.m4 \
+ $(top_srcdir)/../libtool.m4 $(top_srcdir)/../ltoptions.m4 \
+ $(top_srcdir)/../ltsugar.m4 $(top_srcdir)/../ltversion.m4 \
+ $(top_srcdir)/../lt~obsolete.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
+ configure.lineno config.status.lineno
+mkinstalldirs = $(SHELL) $(top_srcdir)/../mkinstalldirs
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(toolexeclibdir)" \
+ "$(DESTDIR)$(cilkincludedir)"
+LTLIBRARIES = $(toolexeclib_LTLIBRARIES)
+libcilkrts_la_LIBADD =
+am_libcilkrts_la_OBJECTS = cilk-abi-vla.lo os-unix-sysdep.lo bug.lo \
+ cilk-abi.lo cilk-abi-cilk-for.lo cilk-abi-vla-internal.lo \
+ cilk_api.lo cilk_fiber.lo cilk_fiber-unix.lo cilk_malloc.lo \
+ c_reducers.lo except-gcc.lo frame_malloc.lo full_frame.lo \
+ global_state.lo jmpbuf.lo local_state.lo metacall_impl.lo \
+ os_mutex-unix.lo os-unix.lo pedigrees.lo record-replay.lo \
+ reducer_impl.lo scheduler.lo signal_node.lo spin_mutex.lo \
+ stats.lo symbol_test.lo sysdep-unix.lo worker_mutex.lo
+libcilkrts_la_OBJECTS = $(am_libcilkrts_la_OBJECTS)
+libcilkrts_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+ $(CXXFLAGS) $(libcilkrts_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@
+depcomp = $(SHELL) $(top_srcdir)/../depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libcilkrts_la_SOURCES)
+MULTISRCTOP =
+MULTIBUILDTOP =
+MULTIDIRS =
+MULTISUBDIR =
+MULTIDO = true
+MULTICLEAN = true
+HEADERS = $(cilkinclude_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBSTDCXX_RAW_CXX_CXXFLAGS = @LIBSTDCXX_RAW_CXX_CXXFLAGS@
+LIBSTDCXX_RAW_CXX_LDFLAGS = @LIBSTDCXX_RAW_CXX_LDFLAGS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+config_dir = @config_dir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+multi_basedir = @multi_basedir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_noncanonical = @target_noncanonical@
+target_os = @target_os@
+target_vendor = @target_vendor@
+toolexecdir = @toolexecdir@
+toolexeclibdir = @toolexeclibdir@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AUTOMAKE_OPTIONS = foreign
+
+# Use when building GCC
+ACLOCAL_AMFLAGS = -I .. -I ../config
+
+# Compiler and linker flags.
+
+# Enable Intel Cilk Plus extension
+GENERAL_FLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/runtime \
+ -I$(top_srcdir)/runtime/config/$(config_dir) \
+ -DIN_CILK_RUNTIME=1 -D_Cilk_spawn="" -D_Cilk_sync="" \
+ -D_Cilk_for=for -fcilkplus
+AM_CFLAGS = $(GENERAL_FLAGS) -std=c99
+AM_CPPFLAGS = $(GENERAL_FLAGS)
+AM_LDFLAGS = -lpthread
+
+# May be used by toolexeclibdir.
+gcc_version := $(shell cat $(top_srcdir)/../gcc/BASE-VER)
+
+# Target list.
+toolexeclib_LTLIBRARIES = libcilkrts.la
+libcilkrts_la_SOURCES = \
+ runtime/config/$(config_dir)/cilk-abi-vla.c \
+ runtime/config/$(config_dir)/os-unix-sysdep.c \
+ runtime/bug.cpp \
+ runtime/cilk-abi.c \
+ runtime/cilk-abi-cilk-for.cpp \
+ runtime/cilk-abi-vla-internal.c \
+ runtime/cilk_api.c \
+ runtime/cilk_fiber.cpp \
+ runtime/cilk_fiber-unix.cpp \
+ runtime/cilk_malloc.c \
+ runtime/c_reducers.c \
+ runtime/except-gcc.cpp \
+ runtime/frame_malloc.c \
+ runtime/full_frame.c \
+ runtime/global_state.cpp \
+ runtime/jmpbuf.c \
+ runtime/local_state.c \
+ runtime/metacall_impl.c \
+ runtime/os_mutex-unix.c \
+ runtime/os-unix.c \
+ runtime/pedigrees.c \
+ runtime/record-replay.cpp \
+ runtime/reducer_impl.cpp \
+ runtime/scheduler.c \
+ runtime/signal_node.c \
+ runtime/spin_mutex.c \
+ runtime/stats.c \
+ runtime/symbol_test.c \
+ runtime/sysdep-unix.c \
+ runtime/worker_mutex.c
+
+CILK_REVISION = 3902
+
+# Load the $(REVISION) value.
+
+#libcilkrts_la_LDFLAGS = -rpath '$(libdir)'
+
+# Hack for Cygwin
+libcilkrts_la_LDFLAGS = -version-info 5:0:0 -lpthread -ldl \
+ $(am__append_1) $(am__append_2) -no-undefined
+
+# C/C++ header files for Cilk.
+cilkincludedir = $(includedir)/cilk
+cilkinclude_HEADERS = \
+ include/cilk/cilk_api.h \
+ include/cilk/cilk_api_linux.h \
+ include/cilk/cilk.h \
+ include/cilk/cilk_stub.h \
+ include/cilk/cilk_undocumented.h \
+ include/cilk/common.h \
+ include/cilk/holder.h \
+ include/cilk/hyperobject_base.h \
+ include/cilk/metaprogramming.h \
+ include/cilk/reducer_file.h \
+ include/cilk/reducer.h \
+ include/cilk/reducer_list.h \
+ include/cilk/reducer_max.h \
+ include/cilk/reducer_min.h \
+ include/cilk/reducer_min_max.h \
+ include/cilk/reducer_opadd.h \
+ include/cilk/reducer_opand.h \
+ include/cilk/reducer_opmul.h \
+ include/cilk/reducer_opor.h \
+ include/cilk/reducer_opxor.h \
+ include/cilk/reducer_ostream.h \
+ include/cilk/reducer_string.h
+
+
+# Work around what appears to be a GNU make bug handling MAKEFLAGS
+# values defined in terms of make variables, as is the case for CC and
+# friends when we are called from the top level Makefile.
+AM_MAKEFLAGS = \
+ "AR_FLAGS=$(AR_FLAGS)" \
+ "CC_FOR_BUILD=$(CC_FOR_BUILD)" \
+ "CFLAGS=$(CFLAGS)" \
+ "CXXFLAGS=$(CXXFLAGS)" \
+ "CFLAGS_FOR_BUILD=$(CFLAGS_FOR_BUILD)" \
+ "CFLAGS_FOR_TARGET=$(CFLAGS_FOR_TARGET)" \
+ "INSTALL=$(INSTALL)" \
+ "INSTALL_DATA=$(INSTALL_DATA)" \
+ "INSTALL_PROGRAM=$(INSTALL_PROGRAM)" \
+ "INSTALL_SCRIPT=$(INSTALL_SCRIPT)" \
+ "JC1FLAGS=$(JC1FLAGS)" \
+ "LDFLAGS=$(LDFLAGS)" \
+ "LIBCFLAGS=$(LIBCFLAGS)" \
+ "LIBCFLAGS_FOR_TARGET=$(LIBCFLAGS_FOR_TARGET)" \
+ "MAKE=$(MAKE)" \
+ "MAKEINFO=$(MAKEINFO) $(MAKEINFOFLAGS)" \
+ "PICFLAG=$(PICFLAG)" \
+ "PICFLAG_FOR_TARGET=$(PICFLAG_FOR_TARGET)" \
+ "SHELL=$(SHELL)" \
+ "RUNTESTFLAGS=$(RUNTESTFLAGS)" \
+ "exec_prefix=$(exec_prefix)" \
+ "infodir=$(infodir)" \
+ "libdir=$(libdir)" \
+ "prefix=$(prefix)" \
+ "includedir=$(includedir)" \
+ "AR=$(AR)" \
+ "AS=$(AS)" \
+ "LD=$(LD)" \
+ "LIBCFLAGS=$(LIBCFLAGS)" \
+ "NM=$(NM)" \
+ "PICFLAG=$(PICFLAG)" \
+ "RANLIB=$(RANLIB)" \
+ "DESTDIR=$(DESTDIR)"
+
+MAKEOVERRIDES =
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .cpp .lo .o .obj
+am--refresh:
+ @:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(srcdir)/include/internal/rev.mk $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \
+ $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ echo ' $(SHELL) ./config.status'; \
+ $(SHELL) ./config.status;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ $(SHELL) ./config.status --recheck
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ $(am__cd) $(srcdir) && $(AUTOCONF)
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
+$(am__aclocal_m4_deps):
+install-toolexeclibLTLIBRARIES: $(toolexeclib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(toolexeclibdir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibdir)"
+ @list='$(toolexeclib_LTLIBRARIES)'; test -n "$(toolexeclibdir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(toolexeclibdir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(toolexeclibdir)"; \
+ }
+
+uninstall-toolexeclibLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(toolexeclib_LTLIBRARIES)'; test -n "$(toolexeclibdir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(toolexeclibdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(toolexeclibdir)/$$f"; \
+ done
+
+clean-toolexeclibLTLIBRARIES:
+ -test -z "$(toolexeclib_LTLIBRARIES)" || rm -f $(toolexeclib_LTLIBRARIES)
+ @list='$(toolexeclib_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libcilkrts.la: $(libcilkrts_la_OBJECTS) $(libcilkrts_la_DEPENDENCIES)
+ $(libcilkrts_la_LINK) -rpath $(toolexeclibdir) $(libcilkrts_la_OBJECTS) $(libcilkrts_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bug.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/c_reducers.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cilk-abi-cilk-for.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cilk-abi-vla-internal.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cilk-abi-vla.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cilk-abi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cilk_api.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cilk_fiber-unix.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cilk_fiber.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cilk_malloc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/except-gcc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/frame_malloc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/full_frame.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/global_state.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/jmpbuf.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/local_state.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/metacall_impl.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/os-unix-sysdep.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/os-unix.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/os_mutex-unix.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pedigrees.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/record-replay.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/reducer_impl.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/scheduler.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/signal_node.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spin_mutex.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stats.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/symbol_test.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sysdep-unix.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/worker_mutex.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+cilk-abi-vla.lo: runtime/config/$(config_dir)/cilk-abi-vla.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cilk-abi-vla.lo -MD -MP -MF $(DEPDIR)/cilk-abi-vla.Tpo -c -o cilk-abi-vla.lo `test -f 'runtime/config/$(config_dir)/cilk-abi-vla.c' || echo '$(srcdir)/'`runtime/config/$(config_dir)/cilk-abi-vla.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/cilk-abi-vla.Tpo $(DEPDIR)/cilk-abi-vla.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/config/$(config_dir)/cilk-abi-vla.c' object='cilk-abi-vla.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cilk-abi-vla.lo `test -f 'runtime/config/$(config_dir)/cilk-abi-vla.c' || echo '$(srcdir)/'`runtime/config/$(config_dir)/cilk-abi-vla.c
+
+os-unix-sysdep.lo: runtime/config/$(config_dir)/os-unix-sysdep.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT os-unix-sysdep.lo -MD -MP -MF $(DEPDIR)/os-unix-sysdep.Tpo -c -o os-unix-sysdep.lo `test -f 'runtime/config/$(config_dir)/os-unix-sysdep.c' || echo '$(srcdir)/'`runtime/config/$(config_dir)/os-unix-sysdep.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/os-unix-sysdep.Tpo $(DEPDIR)/os-unix-sysdep.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/config/$(config_dir)/os-unix-sysdep.c' object='os-unix-sysdep.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o os-unix-sysdep.lo `test -f 'runtime/config/$(config_dir)/os-unix-sysdep.c' || echo '$(srcdir)/'`runtime/config/$(config_dir)/os-unix-sysdep.c
+
+cilk-abi.lo: runtime/cilk-abi.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cilk-abi.lo -MD -MP -MF $(DEPDIR)/cilk-abi.Tpo -c -o cilk-abi.lo `test -f 'runtime/cilk-abi.c' || echo '$(srcdir)/'`runtime/cilk-abi.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/cilk-abi.Tpo $(DEPDIR)/cilk-abi.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/cilk-abi.c' object='cilk-abi.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cilk-abi.lo `test -f 'runtime/cilk-abi.c' || echo '$(srcdir)/'`runtime/cilk-abi.c
+
+cilk-abi-vla-internal.lo: runtime/cilk-abi-vla-internal.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cilk-abi-vla-internal.lo -MD -MP -MF $(DEPDIR)/cilk-abi-vla-internal.Tpo -c -o cilk-abi-vla-internal.lo `test -f 'runtime/cilk-abi-vla-internal.c' || echo '$(srcdir)/'`runtime/cilk-abi-vla-internal.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/cilk-abi-vla-internal.Tpo $(DEPDIR)/cilk-abi-vla-internal.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/cilk-abi-vla-internal.c' object='cilk-abi-vla-internal.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cilk-abi-vla-internal.lo `test -f 'runtime/cilk-abi-vla-internal.c' || echo '$(srcdir)/'`runtime/cilk-abi-vla-internal.c
+
+cilk_api.lo: runtime/cilk_api.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cilk_api.lo -MD -MP -MF $(DEPDIR)/cilk_api.Tpo -c -o cilk_api.lo `test -f 'runtime/cilk_api.c' || echo '$(srcdir)/'`runtime/cilk_api.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/cilk_api.Tpo $(DEPDIR)/cilk_api.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/cilk_api.c' object='cilk_api.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cilk_api.lo `test -f 'runtime/cilk_api.c' || echo '$(srcdir)/'`runtime/cilk_api.c
+
+cilk_malloc.lo: runtime/cilk_malloc.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cilk_malloc.lo -MD -MP -MF $(DEPDIR)/cilk_malloc.Tpo -c -o cilk_malloc.lo `test -f 'runtime/cilk_malloc.c' || echo '$(srcdir)/'`runtime/cilk_malloc.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/cilk_malloc.Tpo $(DEPDIR)/cilk_malloc.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/cilk_malloc.c' object='cilk_malloc.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cilk_malloc.lo `test -f 'runtime/cilk_malloc.c' || echo '$(srcdir)/'`runtime/cilk_malloc.c
+
+c_reducers.lo: runtime/c_reducers.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT c_reducers.lo -MD -MP -MF $(DEPDIR)/c_reducers.Tpo -c -o c_reducers.lo `test -f 'runtime/c_reducers.c' || echo '$(srcdir)/'`runtime/c_reducers.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/c_reducers.Tpo $(DEPDIR)/c_reducers.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/c_reducers.c' object='c_reducers.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o c_reducers.lo `test -f 'runtime/c_reducers.c' || echo '$(srcdir)/'`runtime/c_reducers.c
+
+frame_malloc.lo: runtime/frame_malloc.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT frame_malloc.lo -MD -MP -MF $(DEPDIR)/frame_malloc.Tpo -c -o frame_malloc.lo `test -f 'runtime/frame_malloc.c' || echo '$(srcdir)/'`runtime/frame_malloc.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/frame_malloc.Tpo $(DEPDIR)/frame_malloc.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/frame_malloc.c' object='frame_malloc.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o frame_malloc.lo `test -f 'runtime/frame_malloc.c' || echo '$(srcdir)/'`runtime/frame_malloc.c
+
+full_frame.lo: runtime/full_frame.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT full_frame.lo -MD -MP -MF $(DEPDIR)/full_frame.Tpo -c -o full_frame.lo `test -f 'runtime/full_frame.c' || echo '$(srcdir)/'`runtime/full_frame.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/full_frame.Tpo $(DEPDIR)/full_frame.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/full_frame.c' object='full_frame.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o full_frame.lo `test -f 'runtime/full_frame.c' || echo '$(srcdir)/'`runtime/full_frame.c
+
+jmpbuf.lo: runtime/jmpbuf.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT jmpbuf.lo -MD -MP -MF $(DEPDIR)/jmpbuf.Tpo -c -o jmpbuf.lo `test -f 'runtime/jmpbuf.c' || echo '$(srcdir)/'`runtime/jmpbuf.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/jmpbuf.Tpo $(DEPDIR)/jmpbuf.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/jmpbuf.c' object='jmpbuf.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o jmpbuf.lo `test -f 'runtime/jmpbuf.c' || echo '$(srcdir)/'`runtime/jmpbuf.c
+
+local_state.lo: runtime/local_state.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT local_state.lo -MD -MP -MF $(DEPDIR)/local_state.Tpo -c -o local_state.lo `test -f 'runtime/local_state.c' || echo '$(srcdir)/'`runtime/local_state.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/local_state.Tpo $(DEPDIR)/local_state.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/local_state.c' object='local_state.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o local_state.lo `test -f 'runtime/local_state.c' || echo '$(srcdir)/'`runtime/local_state.c
+
+metacall_impl.lo: runtime/metacall_impl.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT metacall_impl.lo -MD -MP -MF $(DEPDIR)/metacall_impl.Tpo -c -o metacall_impl.lo `test -f 'runtime/metacall_impl.c' || echo '$(srcdir)/'`runtime/metacall_impl.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/metacall_impl.Tpo $(DEPDIR)/metacall_impl.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/metacall_impl.c' object='metacall_impl.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o metacall_impl.lo `test -f 'runtime/metacall_impl.c' || echo '$(srcdir)/'`runtime/metacall_impl.c
+
+os_mutex-unix.lo: runtime/os_mutex-unix.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT os_mutex-unix.lo -MD -MP -MF $(DEPDIR)/os_mutex-unix.Tpo -c -o os_mutex-unix.lo `test -f 'runtime/os_mutex-unix.c' || echo '$(srcdir)/'`runtime/os_mutex-unix.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/os_mutex-unix.Tpo $(DEPDIR)/os_mutex-unix.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/os_mutex-unix.c' object='os_mutex-unix.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o os_mutex-unix.lo `test -f 'runtime/os_mutex-unix.c' || echo '$(srcdir)/'`runtime/os_mutex-unix.c
+
+os-unix.lo: runtime/os-unix.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT os-unix.lo -MD -MP -MF $(DEPDIR)/os-unix.Tpo -c -o os-unix.lo `test -f 'runtime/os-unix.c' || echo '$(srcdir)/'`runtime/os-unix.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/os-unix.Tpo $(DEPDIR)/os-unix.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/os-unix.c' object='os-unix.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o os-unix.lo `test -f 'runtime/os-unix.c' || echo '$(srcdir)/'`runtime/os-unix.c
+
+pedigrees.lo: runtime/pedigrees.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pedigrees.lo -MD -MP -MF $(DEPDIR)/pedigrees.Tpo -c -o pedigrees.lo `test -f 'runtime/pedigrees.c' || echo '$(srcdir)/'`runtime/pedigrees.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pedigrees.Tpo $(DEPDIR)/pedigrees.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/pedigrees.c' object='pedigrees.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o pedigrees.lo `test -f 'runtime/pedigrees.c' || echo '$(srcdir)/'`runtime/pedigrees.c
+
+scheduler.lo: runtime/scheduler.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT scheduler.lo -MD -MP -MF $(DEPDIR)/scheduler.Tpo -c -o scheduler.lo `test -f 'runtime/scheduler.c' || echo '$(srcdir)/'`runtime/scheduler.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/scheduler.Tpo $(DEPDIR)/scheduler.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/scheduler.c' object='scheduler.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o scheduler.lo `test -f 'runtime/scheduler.c' || echo '$(srcdir)/'`runtime/scheduler.c
+
+signal_node.lo: runtime/signal_node.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT signal_node.lo -MD -MP -MF $(DEPDIR)/signal_node.Tpo -c -o signal_node.lo `test -f 'runtime/signal_node.c' || echo '$(srcdir)/'`runtime/signal_node.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/signal_node.Tpo $(DEPDIR)/signal_node.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/signal_node.c' object='signal_node.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o signal_node.lo `test -f 'runtime/signal_node.c' || echo '$(srcdir)/'`runtime/signal_node.c
+
+spin_mutex.lo: runtime/spin_mutex.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT spin_mutex.lo -MD -MP -MF $(DEPDIR)/spin_mutex.Tpo -c -o spin_mutex.lo `test -f 'runtime/spin_mutex.c' || echo '$(srcdir)/'`runtime/spin_mutex.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/spin_mutex.Tpo $(DEPDIR)/spin_mutex.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/spin_mutex.c' object='spin_mutex.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o spin_mutex.lo `test -f 'runtime/spin_mutex.c' || echo '$(srcdir)/'`runtime/spin_mutex.c
+
+stats.lo: runtime/stats.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT stats.lo -MD -MP -MF $(DEPDIR)/stats.Tpo -c -o stats.lo `test -f 'runtime/stats.c' || echo '$(srcdir)/'`runtime/stats.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/stats.Tpo $(DEPDIR)/stats.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/stats.c' object='stats.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o stats.lo `test -f 'runtime/stats.c' || echo '$(srcdir)/'`runtime/stats.c
+
+symbol_test.lo: runtime/symbol_test.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT symbol_test.lo -MD -MP -MF $(DEPDIR)/symbol_test.Tpo -c -o symbol_test.lo `test -f 'runtime/symbol_test.c' || echo '$(srcdir)/'`runtime/symbol_test.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/symbol_test.Tpo $(DEPDIR)/symbol_test.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/symbol_test.c' object='symbol_test.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o symbol_test.lo `test -f 'runtime/symbol_test.c' || echo '$(srcdir)/'`runtime/symbol_test.c
+
+sysdep-unix.lo: runtime/sysdep-unix.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sysdep-unix.lo -MD -MP -MF $(DEPDIR)/sysdep-unix.Tpo -c -o sysdep-unix.lo `test -f 'runtime/sysdep-unix.c' || echo '$(srcdir)/'`runtime/sysdep-unix.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/sysdep-unix.Tpo $(DEPDIR)/sysdep-unix.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/sysdep-unix.c' object='sysdep-unix.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sysdep-unix.lo `test -f 'runtime/sysdep-unix.c' || echo '$(srcdir)/'`runtime/sysdep-unix.c
+
+worker_mutex.lo: runtime/worker_mutex.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT worker_mutex.lo -MD -MP -MF $(DEPDIR)/worker_mutex.Tpo -c -o worker_mutex.lo `test -f 'runtime/worker_mutex.c' || echo '$(srcdir)/'`runtime/worker_mutex.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/worker_mutex.Tpo $(DEPDIR)/worker_mutex.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/worker_mutex.c' object='worker_mutex.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o worker_mutex.lo `test -f 'runtime/worker_mutex.c' || echo '$(srcdir)/'`runtime/worker_mutex.c
+
+.cpp.o:
+@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
+
+.cpp.obj:
+@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cpp.lo:
+@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $<
+
+bug.lo: runtime/bug.cpp
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT bug.lo -MD -MP -MF $(DEPDIR)/bug.Tpo -c -o bug.lo `test -f 'runtime/bug.cpp' || echo '$(srcdir)/'`runtime/bug.cpp
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/bug.Tpo $(DEPDIR)/bug.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='runtime/bug.cpp' object='bug.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o bug.lo `test -f 'runtime/bug.cpp' || echo '$(srcdir)/'`runtime/bug.cpp
+
+cilk-abi-cilk-for.lo: runtime/cilk-abi-cilk-for.cpp
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT cilk-abi-cilk-for.lo -MD -MP -MF $(DEPDIR)/cilk-abi-cilk-for.Tpo -c -o cilk-abi-cilk-for.lo `test -f 'runtime/cilk-abi-cilk-for.cpp' || echo '$(srcdir)/'`runtime/cilk-abi-cilk-for.cpp
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/cilk-abi-cilk-for.Tpo $(DEPDIR)/cilk-abi-cilk-for.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='runtime/cilk-abi-cilk-for.cpp' object='cilk-abi-cilk-for.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o cilk-abi-cilk-for.lo `test -f 'runtime/cilk-abi-cilk-for.cpp' || echo '$(srcdir)/'`runtime/cilk-abi-cilk-for.cpp
+
+cilk_fiber.lo: runtime/cilk_fiber.cpp
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT cilk_fiber.lo -MD -MP -MF $(DEPDIR)/cilk_fiber.Tpo -c -o cilk_fiber.lo `test -f 'runtime/cilk_fiber.cpp' || echo '$(srcdir)/'`runtime/cilk_fiber.cpp
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/cilk_fiber.Tpo $(DEPDIR)/cilk_fiber.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='runtime/cilk_fiber.cpp' object='cilk_fiber.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o cilk_fiber.lo `test -f 'runtime/cilk_fiber.cpp' || echo '$(srcdir)/'`runtime/cilk_fiber.cpp
+
+cilk_fiber-unix.lo: runtime/cilk_fiber-unix.cpp
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT cilk_fiber-unix.lo -MD -MP -MF $(DEPDIR)/cilk_fiber-unix.Tpo -c -o cilk_fiber-unix.lo `test -f 'runtime/cilk_fiber-unix.cpp' || echo '$(srcdir)/'`runtime/cilk_fiber-unix.cpp
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/cilk_fiber-unix.Tpo $(DEPDIR)/cilk_fiber-unix.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='runtime/cilk_fiber-unix.cpp' object='cilk_fiber-unix.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o cilk_fiber-unix.lo `test -f 'runtime/cilk_fiber-unix.cpp' || echo '$(srcdir)/'`runtime/cilk_fiber-unix.cpp
+
+except-gcc.lo: runtime/except-gcc.cpp
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT except-gcc.lo -MD -MP -MF $(DEPDIR)/except-gcc.Tpo -c -o except-gcc.lo `test -f 'runtime/except-gcc.cpp' || echo '$(srcdir)/'`runtime/except-gcc.cpp
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/except-gcc.Tpo $(DEPDIR)/except-gcc.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='runtime/except-gcc.cpp' object='except-gcc.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o except-gcc.lo `test -f 'runtime/except-gcc.cpp' || echo '$(srcdir)/'`runtime/except-gcc.cpp
+
+global_state.lo: runtime/global_state.cpp
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT global_state.lo -MD -MP -MF $(DEPDIR)/global_state.Tpo -c -o global_state.lo `test -f 'runtime/global_state.cpp' || echo '$(srcdir)/'`runtime/global_state.cpp
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/global_state.Tpo $(DEPDIR)/global_state.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='runtime/global_state.cpp' object='global_state.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o global_state.lo `test -f 'runtime/global_state.cpp' || echo '$(srcdir)/'`runtime/global_state.cpp
+
+record-replay.lo: runtime/record-replay.cpp
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT record-replay.lo -MD -MP -MF $(DEPDIR)/record-replay.Tpo -c -o record-replay.lo `test -f 'runtime/record-replay.cpp' || echo '$(srcdir)/'`runtime/record-replay.cpp
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/record-replay.Tpo $(DEPDIR)/record-replay.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='runtime/record-replay.cpp' object='record-replay.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o record-replay.lo `test -f 'runtime/record-replay.cpp' || echo '$(srcdir)/'`runtime/record-replay.cpp
+
+reducer_impl.lo: runtime/reducer_impl.cpp
+@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT reducer_impl.lo -MD -MP -MF $(DEPDIR)/reducer_impl.Tpo -c -o reducer_impl.lo `test -f 'runtime/reducer_impl.cpp' || echo '$(srcdir)/'`runtime/reducer_impl.cpp
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/reducer_impl.Tpo $(DEPDIR)/reducer_impl.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='runtime/reducer_impl.cpp' object='reducer_impl.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o reducer_impl.lo `test -f 'runtime/reducer_impl.cpp' || echo '$(srcdir)/'`runtime/reducer_impl.cpp
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+distclean-libtool:
+ -rm -f libtool config.lt
+
+# GNU Make needs to see an explicit $(MAKE) variable in the command it
+# runs to enable its job server during parallel builds. Hence the
+# comments below.
+all-multi:
+ $(MULTIDO) $(AM_MAKEFLAGS) DO=all multi-do # $(MAKE)
+install-multi:
+ $(MULTIDO) $(AM_MAKEFLAGS) DO=install multi-do # $(MAKE)
+
+mostlyclean-multi:
+ $(MULTICLEAN) $(AM_MAKEFLAGS) DO=mostlyclean multi-clean # $(MAKE)
+clean-multi:
+ $(MULTICLEAN) $(AM_MAKEFLAGS) DO=clean multi-clean # $(MAKE)
+distclean-multi:
+ $(MULTICLEAN) $(AM_MAKEFLAGS) DO=distclean multi-clean # $(MAKE)
+maintainer-clean-multi:
+ $(MULTICLEAN) $(AM_MAKEFLAGS) DO=maintainer-clean multi-clean # $(MAKE)
+install-cilkincludeHEADERS: $(cilkinclude_HEADERS)
+ @$(NORMAL_INSTALL)
+ test -z "$(cilkincludedir)" || $(MKDIR_P) "$(DESTDIR)$(cilkincludedir)"
+ @list='$(cilkinclude_HEADERS)'; test -n "$(cilkincludedir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(cilkincludedir)'"; \
+ $(INSTALL_HEADER) $$files "$(DESTDIR)$(cilkincludedir)" || exit $$?; \
+ done
+
+uninstall-cilkincludeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(cilkinclude_HEADERS)'; test -n "$(cilkincludedir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(cilkincludedir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(cilkincludedir)" && rm -f $$files
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) all-multi $(HEADERS)
+installdirs:
+ for dir in "$(DESTDIR)$(toolexeclibdir)" "$(DESTDIR)$(cilkincludedir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am clean-multi
+
+clean-am: clean-generic clean-libtool clean-toolexeclibLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am distclean-multi
+ -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-libtool distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-cilkincludeHEADERS
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-multi install-toolexeclibLTLIBRARIES
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am maintainer-clean-multi
+ -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+ -rm -rf $(top_srcdir)/autom4te.cache
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am mostlyclean-multi
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-cilkincludeHEADERS \
+ uninstall-toolexeclibLTLIBRARIES
+
+.MAKE: all-multi clean-multi distclean-multi install-am install-multi \
+ install-strip maintainer-clean-multi mostlyclean-multi
+
+.PHONY: CTAGS GTAGS all all-am all-multi am--refresh check check-am \
+ clean clean-generic clean-libtool clean-multi \
+ clean-toolexeclibLTLIBRARIES ctags distclean distclean-compile \
+ distclean-generic distclean-libtool distclean-multi \
+ distclean-tags dvi dvi-am html html-am info info-am install \
+ install-am install-cilkincludeHEADERS install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-multi install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ install-toolexeclibLTLIBRARIES installcheck installcheck-am \
+ installdirs maintainer-clean maintainer-clean-generic \
+ maintainer-clean-multi mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool mostlyclean-multi pdf \
+ pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-cilkincludeHEADERS uninstall-toolexeclibLTLIBRARIES
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/libcilkrts/README b/libcilkrts/README
new file mode 100644
index 00000000000..7c101150ece
--- /dev/null
+++ b/libcilkrts/README
@@ -0,0 +1,84 @@
+Intel(R) Cilk(TM) Plus runtime library
+
+Index:
+1. BUILDING
+2. USING
+3. DOXYGEN DOCUMENTATION
+4. QUESTIONS OR BUGS
+5. CONTRIBUTIONS
+
+#
+# 1. BUILDING:
+#
+
+To distribute applications that use the Intel Cilk Plus language
+extensions to non-development systems, you need to build the Intel
+Cilk Plus runtime library and distribute it with your application.
+
+To build the libcilkrts.so runtime library component, you need the
+autoconf and automake packages, which are available through your
+favorite package manager. You also need a C/C++ compiler that
+supports the Intel Cilk Plus language extensions, since the runtime
+uses Intel Cilk Plus features internally. Use either the Intel(R)
+C++ Compiler (icc command) v12.1 or later, or in GCC 4.9 or later
+(gcc command).
+
+Once you have the necessary prerequisites installed, you can use the
+following commands to create the library:
+
+% libtoolize
+% aclocal
+% automake --add-missing
+% autoconf
+% ./configure
+% make
+% make install
+
+This will produce the libcilkrts.so shared object. To install the
+library in a custom location, set the prefix while running the
+configure script:
+
+% ./configure --prefix=/your/path/to/lib
+
+#
+# 2. USING:
+#
+
+The Intel(R) C++ Compiler will automatically try to bring in the
+Intel Cilk Plus runtime in any program that uses the relevant
+features. GCC requires explicit linking of both the library and
+its dependencies (libpthread, libdl). For example:
+
+% gcc foo.c -lcilkrts -lpthread -ldl
+
+#
+# 3. DOXYGEN DOCUMENTATION:
+#
+
+The library source has Doxygen markup. Generate HTML documentation
+based on the markup by changing directory into runtime and running:
+
+% doxygen doxygen.cfg
+
+#
+# 4. QUESTIONS OR BUGS:
+#
+
+Issues with the Intel Cilk Plus runtime can be addressed in the Intel
+Cilk Plus forums:
+http://software.intel.com/en-us/forums/intel-cilk-plus/
+
+#
+# 5. CONTRIBUTIONS:
+#
+
+The Intel Cilk Plus runtime library is dual licensed. The upstream copy
+of the library is maintained via the BSD-licensed version available at:
+http://cilkplus.org/
+
+Changes to the Intel Cilk Plus runtime are welcome and should be
+contributed to the upstream version via http://cilkplus.org/.
+
+------------------------
+Intel and Cilk are trademarks of Intel Corporation in the U.S. and/or
+other countries.
diff --git a/libcilkrts/aclocal.m4 b/libcilkrts/aclocal.m4
new file mode 100644
index 00000000000..c24d0b60415
--- /dev/null
+++ b/libcilkrts/aclocal.m4
@@ -0,0 +1,981 @@
+# generated automatically by aclocal 1.11.1 -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2006, 2007, 2008, 2009 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_AUTOCONF_VERSION],
+ [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.64],,
+[m4_warning([this file was generated for autoconf 2.64.
+You have another version of autoconf. It may work, but is not guaranteed to.
+If you have problems, you may need to regenerate the build system entirely.
+To do so, use the procedure documented by the package, typically `autoreconf'.])])
+
+# Copyright (C) 2002, 2003, 2005, 2006, 2007, 2008 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.
+
+# AM_AUTOMAKE_VERSION(VERSION)
+# ----------------------------
+# Automake X.Y traces this macro to ensure aclocal.m4 has been
+# generated from the m4 files accompanying Automake X.Y.
+# (This private macro should not be called outside this file.)
+AC_DEFUN([AM_AUTOMAKE_VERSION],
+[am__api_version='1.11'
+dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
+dnl require some minimum version. Point them to the right macro.
+m4_if([$1], [1.11.1], [],
+ [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
+])
+
+# _AM_AUTOCONF_VERSION(VERSION)
+# -----------------------------
+# aclocal traces this macro to find the Autoconf version.
+# This is a private macro too. Using m4_define simplifies
+# the logic in aclocal, which can simply ignore this definition.
+m4_define([_AM_AUTOCONF_VERSION], [])
+
+# AM_SET_CURRENT_AUTOMAKE_VERSION
+# -------------------------------
+# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
+# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
+AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
+[AM_AUTOMAKE_VERSION([1.11.1])dnl
+m4_ifndef([AC_AUTOCONF_VERSION],
+ [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
+
+# AM_AUX_DIR_EXPAND -*- Autoconf -*-
+
+# Copyright (C) 2001, 2003, 2005 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.
+
+# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
+# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to
+# `$srcdir', `$srcdir/..', or `$srcdir/../..'.
+#
+# Of course, Automake must honor this variable whenever it calls a
+# tool from the auxiliary directory. The problem is that $srcdir (and
+# therefore $ac_aux_dir as well) can be either absolute or relative,
+# depending on how configure is run. This is pretty annoying, since
+# it makes $ac_aux_dir quite unusable in subdirectories: in the top
+# source directory, any form will work fine, but in subdirectories a
+# relative path needs to be adjusted first.
+#
+# $ac_aux_dir/missing
+# fails when called from a subdirectory if $ac_aux_dir is relative
+# $top_srcdir/$ac_aux_dir/missing
+# fails if $ac_aux_dir is absolute,
+# fails when called from a subdirectory in a VPATH build with
+# a relative $ac_aux_dir
+#
+# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
+# are both prefixed by $srcdir. In an in-source build this is usually
+# harmless because $srcdir is `.', but things will broke when you
+# start a VPATH build or use an absolute $srcdir.
+#
+# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
+# iff we strip the leading $srcdir from $ac_aux_dir. That would be:
+# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
+# and then we would define $MISSING as
+# MISSING="\${SHELL} $am_aux_dir/missing"
+# This will work as long as MISSING is not called from configure, because
+# unfortunately $(top_srcdir) has no meaning in configure.
+# However there are other variables, like CC, which are often used in
+# configure, and could therefore not use this "fixed" $ac_aux_dir.
+#
+# Another solution, used here, is to always expand $ac_aux_dir to an
+# absolute PATH. The drawback is that using absolute paths prevent a
+# configured tree to be moved without reconfiguration.
+
+AC_DEFUN([AM_AUX_DIR_EXPAND],
+[dnl Rely on autoconf to set up CDPATH properly.
+AC_PREREQ([2.50])dnl
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+])
+
+# AM_CONDITIONAL -*- Autoconf -*-
+
+# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006, 2008
+# 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.
+
+# serial 9
+
+# AM_CONDITIONAL(NAME, SHELL-CONDITION)
+# -------------------------------------
+# Define a conditional.
+AC_DEFUN([AM_CONDITIONAL],
+[AC_PREREQ(2.52)dnl
+ ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])],
+ [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
+AC_SUBST([$1_TRUE])dnl
+AC_SUBST([$1_FALSE])dnl
+_AM_SUBST_NOTMAKE([$1_TRUE])dnl
+_AM_SUBST_NOTMAKE([$1_FALSE])dnl
+m4_define([_AM_COND_VALUE_$1], [$2])dnl
+if $2; then
+ $1_TRUE=
+ $1_FALSE='#'
+else
+ $1_TRUE='#'
+ $1_FALSE=
+fi
+AC_CONFIG_COMMANDS_PRE(
+[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
+ AC_MSG_ERROR([[conditional "$1" was never defined.
+Usually this means the macro was only invoked conditionally.]])
+fi])])
+
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009
+# 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.
+
+# serial 10
+
+# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be
+# written in clear, in which case automake, when reading aclocal.m4,
+# will think it sees a *use*, and therefore will trigger all it's
+# C support machinery. Also note that it means that autoscan, seeing
+# CC etc. in the Makefile, will ask for an AC_PROG_CC use...
+
+
+# _AM_DEPENDENCIES(NAME)
+# ----------------------
+# See how the compiler implements dependency checking.
+# NAME is "CC", "CXX", "GCJ", or "OBJC".
+# We try a few techniques and use that to set a single cache variable.
+#
+# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was
+# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular
+# dependency, and given that the user is not expected to run this macro,
+# just rely on AC_PROG_CC.
+AC_DEFUN([_AM_DEPENDENCIES],
+[AC_REQUIRE([AM_SET_DEPDIR])dnl
+AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl
+AC_REQUIRE([AM_MAKE_INCLUDE])dnl
+AC_REQUIRE([AM_DEP_TRACK])dnl
+
+ifelse([$1], CC, [depcc="$CC" am_compiler_list=],
+ [$1], CXX, [depcc="$CXX" am_compiler_list=],
+ [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'],
+ [$1], UPC, [depcc="$UPC" am_compiler_list=],
+ [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'],
+ [depcc="$$1" am_compiler_list=])
+
+AC_CACHE_CHECK([dependency style of $depcc],
+ [am_cv_$1_dependencies_compiler_type],
+[if test -z "$AMDEP_TRUE" && 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_$1_dependencies_compiler_type=none
+ if test "$am_compiler_list" = ""; then
+ am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp`
+ fi
+ am__universal=false
+ m4_case([$1], [CC],
+ [case " $depcc " in #(
+ *\ -arch\ *\ -arch\ *) am__universal=true ;;
+ esac],
+ [CXX],
+ [case " $depcc " in #(
+ *\ -arch\ *\ -arch\ *) am__universal=true ;;
+ esac])
+
+ for depmode in $am_compiler_list; do
+ # 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 "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > 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. Also, some Intel
+ # versions had trouble with output in subdirs
+ am__obj=sub/conftest.${OBJEXT-o}
+ am__minus_obj="-o $am__obj"
+ case $depmode in
+ gcc)
+ # This depmode causes a compiler race in universal mode.
+ test "$am__universal" = false || continue
+ ;;
+ nosideeffect)
+ # after this tag, mechanisms are not by side-effect, so they'll
+ # only be used when explicitly requested
+ if test "x$enable_dependency_tracking" = xyes; then
+ continue
+ else
+ break
+ fi
+ ;;
+ msvisualcpp | msvcmsys)
+ # This compiler won't grok `-c -o', but also, the minuso test has
+ # not run yet. These depmodes are late enough in the game, and
+ # so weak that their functioning should not be impacted.
+ am__obj=conftest.${OBJEXT-o}
+ am__minus_obj=
+ ;;
+ none) break ;;
+ esac
+ if depmode=$depmode \
+ source=sub/conftest.c object=$am__obj \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+ >/dev/null 2>conftest.err &&
+ grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+ ${MAKE-make} -s -f confmf > /dev/null 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_$1_dependencies_compiler_type=$depmode
+ break
+ fi
+ fi
+ done
+
+ cd ..
+ rm -rf conftest.dir
+else
+ am_cv_$1_dependencies_compiler_type=none
+fi
+])
+AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type])
+AM_CONDITIONAL([am__fastdep$1], [
+ test "x$enable_dependency_tracking" != xno \
+ && test "$am_cv_$1_dependencies_compiler_type" = gcc3])
+])
+
+
+# AM_SET_DEPDIR
+# -------------
+# Choose a directory name for dependency files.
+# This macro is AC_REQUIREd in _AM_DEPENDENCIES
+AC_DEFUN([AM_SET_DEPDIR],
+[AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl
+])
+
+
+# AM_DEP_TRACK
+# ------------
+AC_DEFUN([AM_DEP_TRACK],
+[AC_ARG_ENABLE(dependency-tracking,
+[ --disable-dependency-tracking speeds up one-time build
+ --enable-dependency-tracking do not reject slow dependency extractors])
+if test "x$enable_dependency_tracking" != xno; then
+ am_depcomp="$ac_aux_dir/depcomp"
+ AMDEPBACKSLASH='\'
+fi
+AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
+AC_SUBST([AMDEPBACKSLASH])dnl
+_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl
+])
+
+# Generate code to set up dependency tracking. -*- Autoconf -*-
+
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008
+# 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.
+
+#serial 5
+
+# _AM_OUTPUT_DEPENDENCY_COMMANDS
+# ------------------------------
+AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
+[{
+ # Autoconf 2.62 quotes --file arguments for eval, but not when files
+ # are listed without --file. Let's play safe and only enable the eval
+ # if we detect the quoting.
+ case $CONFIG_FILES in
+ *\'*) eval set x "$CONFIG_FILES" ;;
+ *) set x $CONFIG_FILES ;;
+ esac
+ shift
+ for mf
+ do
+ # Strip MF so we end up with the name of the file.
+ mf=`echo "$mf" | sed -e 's/:.*$//'`
+ # Check whether this is an Automake generated Makefile or not.
+ # We used to match only the files named `Makefile.in', but
+ # some people rename them; so instead we look at the file content.
+ # Grep'ing the first line is not enough: some people post-process
+ # each Makefile.in and add a new line on top of each file to say so.
+ # Grep'ing the whole file is not good either: AIX grep has a line
+ # limit of 2048, but all sed's we know have understand at least 4000.
+ if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
+ dirpart=`AS_DIRNAME("$mf")`
+ else
+ continue
+ fi
+ # Extract the definition of DEPDIR, am__include, and am__quote
+ # from the Makefile without running `make'.
+ DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+ test -z "$DEPDIR" && continue
+ am__include=`sed -n 's/^am__include = //p' < "$mf"`
+ test -z "am__include" && continue
+ am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+ # When using ansi2knr, U may be empty or an underscore; expand it
+ U=`sed -n 's/^U = //p' < "$mf"`
+ # Find all dependency output files, they are included files with
+ # $(DEPDIR) in their names. We invoke sed twice because it is the
+ # simplest approach to changing $(DEPDIR) to its actual value in the
+ # expansion.
+ for file in `sed -n "
+ s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
+ # Make sure the directory exists.
+ test -f "$dirpart/$file" && continue
+ fdir=`AS_DIRNAME(["$file"])`
+ AS_MKDIR_P([$dirpart/$fdir])
+ # echo "creating $dirpart/$file"
+ echo '# dummy' > "$dirpart/$file"
+ done
+ done
+}
+])# _AM_OUTPUT_DEPENDENCY_COMMANDS
+
+
+# AM_OUTPUT_DEPENDENCY_COMMANDS
+# -----------------------------
+# This macro should only be invoked once -- use via AC_REQUIRE.
+#
+# This code is only required when automatic dependency tracking
+# is enabled. FIXME. This creates each `.P' file that we will
+# need in order to bootstrap the dependency handling code.
+AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
+[AC_CONFIG_COMMANDS([depfiles],
+ [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS],
+ [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"])
+])
+
+# Do all the work for Automake. -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2006, 2008, 2009 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.
+
+# serial 16
+
+# This macro actually does too much. Some checks are only needed if
+# your package does certain things. But this isn't really a big deal.
+
+# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
+# AM_INIT_AUTOMAKE([OPTIONS])
+# -----------------------------------------------
+# The call with PACKAGE and VERSION arguments is the old style
+# call (pre autoconf-2.50), which is being phased out. PACKAGE
+# and VERSION should now be passed to AC_INIT and removed from
+# the call to AM_INIT_AUTOMAKE.
+# We support both call styles for the transition. After
+# the next Automake release, Autoconf can make the AC_INIT
+# arguments mandatory, and then we can depend on a new Autoconf
+# release and drop the old call support.
+AC_DEFUN([AM_INIT_AUTOMAKE],
+[AC_PREREQ([2.62])dnl
+dnl Autoconf wants to disallow AM_ names. We explicitly allow
+dnl the ones we care about.
+m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
+AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
+AC_REQUIRE([AC_PROG_INSTALL])dnl
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+ # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+ # is not polluted with repeated "-I."
+ AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl
+ # test to see if srcdir already configured
+ if test -f $srcdir/config.status; then
+ AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
+ fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+ if (cygpath --version) >/dev/null 2>/dev/null; then
+ CYGPATH_W='cygpath -w'
+ else
+ CYGPATH_W=echo
+ fi
+fi
+AC_SUBST([CYGPATH_W])
+
+# Define the identity of the package.
+dnl Distinguish between old-style and new-style calls.
+m4_ifval([$2],
+[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
+ AC_SUBST([PACKAGE], [$1])dnl
+ AC_SUBST([VERSION], [$2])],
+[_AM_SET_OPTIONS([$1])dnl
+dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
+m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,,
+ [m4_fatal([AC_INIT should be called with package and version arguments])])dnl
+ AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
+ AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
+
+_AM_IF_OPTION([no-define],,
+[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
+ AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl
+
+# Some tools Automake needs.
+AC_REQUIRE([AM_SANITY_CHECK])dnl
+AC_REQUIRE([AC_ARG_PROGRAM])dnl
+AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version})
+AM_MISSING_PROG(AUTOCONF, autoconf)
+AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version})
+AM_MISSING_PROG(AUTOHEADER, autoheader)
+AM_MISSING_PROG(MAKEINFO, makeinfo)
+AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl
+AC_REQUIRE([AM_PROG_MKDIR_P])dnl
+# We need awk for the "check" target. The system "awk" is bad on
+# some platforms.
+AC_REQUIRE([AC_PROG_AWK])dnl
+AC_REQUIRE([AC_PROG_MAKE_SET])dnl
+AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
+ [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
+ [_AM_PROG_TAR([v7])])])
+_AM_IF_OPTION([no-dependencies],,
+[AC_PROVIDE_IFELSE([AC_PROG_CC],
+ [_AM_DEPENDENCIES(CC)],
+ [define([AC_PROG_CC],
+ defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_CXX],
+ [_AM_DEPENDENCIES(CXX)],
+ [define([AC_PROG_CXX],
+ defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_OBJC],
+ [_AM_DEPENDENCIES(OBJC)],
+ [define([AC_PROG_OBJC],
+ defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl
+])
+_AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl
+dnl The `parallel-tests' driver may need to know about EXEEXT, so add the
+dnl `am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This macro
+dnl is hooked onto _AC_COMPILER_EXEEXT early, see below.
+AC_CONFIG_COMMANDS_PRE(dnl
+[m4_provide_if([_AM_COMPILER_EXEEXT],
+ [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl
+])
+
+dnl Hook into `_AC_COMPILER_EXEEXT' early to learn its expansion. Do not
+dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further
+dnl mangled by Autoconf and run in a shell conditional statement.
+m4_define([_AC_COMPILER_EXEEXT],
+m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])])
+
+
+# When config.status generates a header, we must update the stamp-h file.
+# This file resides in the same directory as the config header
+# that is generated. The stamp files are numbered to have different names.
+
+# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
+# loop where config.status creates the headers, so we can generate
+# our stamp files there.
+AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
+[# Compute $1's index in $config_headers.
+_am_arg=$1
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+ case $_am_header in
+ $_am_arg | $_am_arg:* )
+ break ;;
+ * )
+ _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+ esac
+done
+echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
+
+# Copyright (C) 2001, 2003, 2005, 2008 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.
+
+# AM_PROG_INSTALL_SH
+# ------------------
+# Define $install_sh.
+AC_DEFUN([AM_PROG_INSTALL_SH],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+if test x"${install_sh}" != xset; then
+ case $am_aux_dir in
+ *\ * | *\ *)
+ install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
+ *)
+ install_sh="\${SHELL} $am_aux_dir/install-sh"
+ esac
+fi
+AC_SUBST(install_sh)])
+
+# Add --enable-maintainer-mode option to configure. -*- Autoconf -*-
+# From Jim Meyering
+
+# Copyright (C) 1996, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2008
+# 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.
+
+# serial 5
+
+# AM_MAINTAINER_MODE([DEFAULT-MODE])
+# ----------------------------------
+# Control maintainer-specific portions of Makefiles.
+# Default is to disable them, unless `enable' is passed literally.
+# For symmetry, `disable' may be passed as well. Anyway, the user
+# can override the default with the --enable/--disable switch.
+AC_DEFUN([AM_MAINTAINER_MODE],
+[m4_case(m4_default([$1], [disable]),
+ [enable], [m4_define([am_maintainer_other], [disable])],
+ [disable], [m4_define([am_maintainer_other], [enable])],
+ [m4_define([am_maintainer_other], [enable])
+ m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])])
+AC_MSG_CHECKING([whether to am_maintainer_other maintainer-specific portions of Makefiles])
+ dnl maintainer-mode's default is 'disable' unless 'enable' is passed
+ AC_ARG_ENABLE([maintainer-mode],
+[ --][am_maintainer_other][-maintainer-mode am_maintainer_other make rules and dependencies not useful
+ (and sometimes confusing) to the casual installer],
+ [USE_MAINTAINER_MODE=$enableval],
+ [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes]))
+ AC_MSG_RESULT([$USE_MAINTAINER_MODE])
+ AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes])
+ MAINT=$MAINTAINER_MODE_TRUE
+ AC_SUBST([MAINT])dnl
+]
+)
+
+AU_DEFUN([jm_MAINTAINER_MODE], [AM_MAINTAINER_MODE])
+
+# Check to see how 'make' treats includes. -*- Autoconf -*-
+
+# Copyright (C) 2001, 2002, 2003, 2005, 2009 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.
+
+# serial 4
+
+# AM_MAKE_INCLUDE()
+# -----------------
+# Check to see how make treats includes.
+AC_DEFUN([AM_MAKE_INCLUDE],
+[am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+ @echo this is the am__doit target
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+AC_MSG_CHECKING([for style of include used by $am_make])
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# Ignore all kinds of additional output from `make'.
+case `$am_make -s -f confmf 2> /dev/null` in #(
+*the\ am__doit\ target*)
+ am__include=include
+ am__quote=
+ _am_result=GNU
+ ;;
+esac
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+ echo '.include "confinc"' > confmf
+ case `$am_make -s -f confmf 2> /dev/null` in #(
+ *the\ am__doit\ target*)
+ am__include=.include
+ am__quote="\""
+ _am_result=BSD
+ ;;
+ esac
+fi
+AC_SUBST([am__include])
+AC_SUBST([am__quote])
+AC_MSG_RESULT([$_am_result])
+rm -f confinc confmf
+])
+
+# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
+
+# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005, 2008
+# 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.
+
+# serial 6
+
+# AM_MISSING_PROG(NAME, PROGRAM)
+# ------------------------------
+AC_DEFUN([AM_MISSING_PROG],
+[AC_REQUIRE([AM_MISSING_HAS_RUN])
+$1=${$1-"${am_missing_run}$2"}
+AC_SUBST($1)])
+
+
+# AM_MISSING_HAS_RUN
+# ------------------
+# Define MISSING if not defined so far and test if it supports --run.
+# If it does, set am_missing_run to use it, otherwise, to nothing.
+AC_DEFUN([AM_MISSING_HAS_RUN],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([missing])dnl
+if test x"${MISSING+set}" != xset; then
+ case $am_aux_dir in
+ *\ * | *\ *)
+ MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
+ *)
+ MISSING="\${SHELL} $am_aux_dir/missing" ;;
+ esac
+fi
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+ am_missing_run="$MISSING --run "
+else
+ am_missing_run=
+ AC_MSG_WARN([`missing' script is too old or missing])
+fi
+])
+
+# Copyright (C) 2003, 2004, 2005, 2006 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.
+
+# AM_PROG_MKDIR_P
+# ---------------
+# Check for `mkdir -p'.
+AC_DEFUN([AM_PROG_MKDIR_P],
+[AC_PREREQ([2.60])dnl
+AC_REQUIRE([AC_PROG_MKDIR_P])dnl
+dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P,
+dnl while keeping a definition of mkdir_p for backward compatibility.
+dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile.
+dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of
+dnl Makefile.ins that do not define MKDIR_P, so we do our own
+dnl adjustment using top_builddir (which is defined more often than
+dnl MKDIR_P).
+AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl
+case $mkdir_p in
+ [[\\/$]]* | ?:[[\\/]]*) ;;
+ */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;;
+esac
+])
+
+# Helper functions for option handling. -*- Autoconf -*-
+
+# Copyright (C) 2001, 2002, 2003, 2005, 2008 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.
+
+# serial 4
+
+# _AM_MANGLE_OPTION(NAME)
+# -----------------------
+AC_DEFUN([_AM_MANGLE_OPTION],
+[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
+
+# _AM_SET_OPTION(NAME)
+# ------------------------------
+# Set option NAME. Presently that only means defining a flag for this option.
+AC_DEFUN([_AM_SET_OPTION],
+[m4_define(_AM_MANGLE_OPTION([$1]), 1)])
+
+# _AM_SET_OPTIONS(OPTIONS)
+# ----------------------------------
+# OPTIONS is a space-separated list of Automake options.
+AC_DEFUN([_AM_SET_OPTIONS],
+[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
+
+# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
+# -------------------------------------------
+# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
+AC_DEFUN([_AM_IF_OPTION],
+[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
+
+# Check to make sure that the build environment is sane. -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005, 2008
+# 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.
+
+# serial 5
+
+# AM_SANITY_CHECK
+# ---------------
+AC_DEFUN([AM_SANITY_CHECK],
+[AC_MSG_CHECKING([whether build environment is sane])
+# Just in case
+sleep 1
+echo timestamp > conftest.file
+# Reject unsafe characters in $srcdir or the absolute working directory
+# name. Accept space and tab only in the latter.
+am_lf='
+'
+case `pwd` in
+ *[[\\\"\#\$\&\'\`$am_lf]]*)
+ AC_MSG_ERROR([unsafe absolute working directory name]);;
+esac
+case $srcdir in
+ *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*)
+ AC_MSG_ERROR([unsafe srcdir value: `$srcdir']);;
+esac
+
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments. Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+ set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
+ if test "$[*]" = "X"; then
+ # -L didn't work.
+ set X `ls -t "$srcdir/configure" conftest.file`
+ fi
+ rm -f conftest.file
+ if test "$[*]" != "X $srcdir/configure conftest.file" \
+ && test "$[*]" != "X conftest.file $srcdir/configure"; then
+
+ # If neither matched, then we have a broken ls. This can happen
+ # if, for instance, CONFIG_SHELL is bash and it inherits a
+ # broken ls alias from the environment. This has actually
+ # happened. Such a system could not be considered "sane".
+ AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken
+alias in your environment])
+ fi
+
+ test "$[2]" = conftest.file
+ )
+then
+ # Ok.
+ :
+else
+ AC_MSG_ERROR([newly created file is older than distributed files!
+Check your system clock])
+fi
+AC_MSG_RESULT(yes)])
+
+# Copyright (C) 2001, 2003, 2005 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.
+
+# AM_PROG_INSTALL_STRIP
+# ---------------------
+# One issue with vendor `install' (even GNU) is that you can't
+# specify the program used to strip binaries. This is especially
+# annoying in cross-compiling environments, where the build's strip
+# is unlikely to handle the host's binaries.
+# Fortunately install-sh will honor a STRIPPROG variable, so we
+# always use install-sh in `make install-strip', and initialize
+# STRIPPROG with the value of the STRIP variable (set by the user).
+AC_DEFUN([AM_PROG_INSTALL_STRIP],
+[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'. However `strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the `STRIP' environment variable to overrule this program.
+dnl Don't test for $cross_compiling = yes, because it might be `maybe'.
+if test "$cross_compiling" != no; then
+ AC_CHECK_TOOL([STRIP], [strip], :)
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+AC_SUBST([INSTALL_STRIP_PROGRAM])])
+
+# Copyright (C) 2006, 2008 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.
+
+# serial 2
+
+# _AM_SUBST_NOTMAKE(VARIABLE)
+# ---------------------------
+# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in.
+# This macro is traced by Automake.
+AC_DEFUN([_AM_SUBST_NOTMAKE])
+
+# AM_SUBST_NOTMAKE(VARIABLE)
+# ---------------------------
+# Public sister of _AM_SUBST_NOTMAKE.
+AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
+
+# Check how to create a tarball. -*- Autoconf -*-
+
+# Copyright (C) 2004, 2005 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.
+
+# serial 2
+
+# _AM_PROG_TAR(FORMAT)
+# --------------------
+# Check how to create a tarball in format FORMAT.
+# FORMAT should be one of `v7', `ustar', or `pax'.
+#
+# Substitute a variable $(am__tar) that is a command
+# writing to stdout a FORMAT-tarball containing the directory
+# $tardir.
+# tardir=directory && $(am__tar) > result.tar
+#
+# Substitute a variable $(am__untar) that extract such
+# a tarball read from stdin.
+# $(am__untar) < result.tar
+AC_DEFUN([_AM_PROG_TAR],
+[# Always define AMTAR for backward compatibility.
+AM_MISSING_PROG([AMTAR], [tar])
+m4_if([$1], [v7],
+ [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'],
+ [m4_case([$1], [ustar],, [pax],,
+ [m4_fatal([Unknown tar format])])
+AC_MSG_CHECKING([how to create a $1 tar archive])
+# Loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
+_am_tools=${am_cv_prog_tar_$1-$_am_tools}
+# Do not fold the above two line into one, because Tru64 sh and
+# Solaris sh will not grok spaces in the rhs of `-'.
+for _am_tool in $_am_tools
+do
+ case $_am_tool in
+ gnutar)
+ for _am_tar in tar gnutar gtar;
+ do
+ AM_RUN_LOG([$_am_tar --version]) && break
+ done
+ am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
+ am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
+ am__untar="$_am_tar -xf -"
+ ;;
+ plaintar)
+ # Must skip GNU tar: if it does not support --format= it doesn't create
+ # ustar tarball either.
+ (tar --version) >/dev/null 2>&1 && continue
+ am__tar='tar chf - "$$tardir"'
+ am__tar_='tar chf - "$tardir"'
+ am__untar='tar xf -'
+ ;;
+ pax)
+ am__tar='pax -L -x $1 -w "$$tardir"'
+ am__tar_='pax -L -x $1 -w "$tardir"'
+ am__untar='pax -r'
+ ;;
+ cpio)
+ am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
+ am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
+ am__untar='cpio -i -H $1 -d'
+ ;;
+ none)
+ am__tar=false
+ am__tar_=false
+ am__untar=false
+ ;;
+ esac
+
+ # If the value was cached, stop now. We just wanted to have am__tar
+ # and am__untar set.
+ test -n "${am_cv_prog_tar_$1}" && break
+
+ # tar/untar a dummy directory, and stop if the command works
+ rm -rf conftest.dir
+ mkdir conftest.dir
+ echo GrepMe > conftest.dir/file
+ AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
+ rm -rf conftest.dir
+ if test -s conftest.tar; then
+ AM_RUN_LOG([$am__untar <conftest.tar])
+ grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
+ fi
+done
+rm -rf conftest.dir
+
+AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
+AC_MSG_RESULT([$am_cv_prog_tar_$1])])
+AC_SUBST([am__tar])
+AC_SUBST([am__untar])
+]) # _AM_PROG_TAR
+
+m4_include([../config/acx.m4])
+m4_include([../config/depstand.m4])
+m4_include([../config/lead-dot.m4])
+m4_include([../config/libstdc++-raw-cxx.m4])
+m4_include([../config/multi.m4])
+m4_include([../config/override.m4])
+m4_include([../libtool.m4])
+m4_include([../ltoptions.m4])
+m4_include([../ltsugar.m4])
+m4_include([../ltversion.m4])
+m4_include([../lt~obsolete.m4])
diff --git a/libcilkrts/configure b/libcilkrts/configure
new file mode 100644
index 00000000000..41deb9fcc46
--- /dev/null
+++ b/libcilkrts/configure
@@ -0,0 +1,16907 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.64 for Cilk Runtime Library 2.0.
+#
+# Report bugs to <cilk@intel.com>.
+#
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 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.
+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
+
+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"
+ 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 :
+ # 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.
+ BASH_ENV=/dev/null
+ ENV=/dev/null
+ (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+ export CONFIG_SHELL
+ exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"}
+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 and cilk@intel.com
+$0: about your system, including any error possibly output
+$0: before this message. Then install a modern shell, or
+$0: manually run the script under such a shell if you do
+$0: 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_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 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=$?; test $as_status -eq 0 && as_status=1
+ if test "$3"; then
+ as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3
+ fi
+ $as_echo "$as_me: error: $1" >&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; }
+
+ # 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 -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -p'
+ fi
+else
+ as_ln_s='cp -p'
+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
+
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in #(
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
+
+# 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}
+
+
+exec 7<&0 </dev/null 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, 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='Cilk Runtime Library'
+PACKAGE_TARNAME='cilk-runtime-library'
+PACKAGE_VERSION='2.0'
+PACKAGE_STRING='Cilk Runtime Library 2.0'
+PACKAGE_BUGREPORT='cilk@intel.com'
+PACKAGE_URL=''
+
+# 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='am__EXEEXT_FALSE
+am__EXEEXT_TRUE
+LTLIBOBJS
+LIBOBJS
+toolexeclibdir
+toolexecdir
+CXXCPP
+OTOOL64
+OTOOL
+LIPO
+NMEDIT
+DSYMUTIL
+RANLIB
+AR
+OBJDUMP
+LN_S
+NM
+ac_ct_DUMPBIN
+DUMPBIN
+LD
+FGREP
+SED
+LIBTOOL
+MAC_LINKER_SCRIPT_FALSE
+MAC_LINKER_SCRIPT_TRUE
+LINUX_LINKER_SCRIPT_FALSE
+LINUX_LINKER_SCRIPT_TRUE
+config_dir
+EGREP
+GREP
+CPP
+ALLOCA
+multi_basedir
+am__fastdepCC_FALSE
+am__fastdepCC_TRUE
+CCDEPMODE
+ac_ct_CC
+CFLAGS
+CC
+am__fastdepCXX_FALSE
+am__fastdepCXX_TRUE
+CXXDEPMODE
+AMDEPBACKSLASH
+AMDEP_FALSE
+AMDEP_TRUE
+am__quote
+am__include
+DEPDIR
+OBJEXT
+EXEEXT
+ac_ct_CXX
+CPPFLAGS
+LDFLAGS
+CXXFLAGS
+CXX
+MAINT
+MAINTAINER_MODE_FALSE
+MAINTAINER_MODE_TRUE
+am__untar
+am__tar
+AMTAR
+am__leading_dot
+SET_MAKE
+AWK
+mkdir_p
+MKDIR_P
+INSTALL_STRIP_PROGRAM
+STRIP
+install_sh
+MAKEINFO
+AUTOHEADER
+AUTOMAKE
+AUTOCONF
+ACLOCAL
+VERSION
+PACKAGE
+CYGPATH_W
+am__isrc
+INSTALL_DATA
+INSTALL_SCRIPT
+INSTALL_PROGRAM
+LIBSTDCXX_RAW_CXX_LDFLAGS
+LIBSTDCXX_RAW_CXX_CXXFLAGS
+target_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=''
+ac_user_opts='
+enable_option_checking
+enable_maintainer_mode
+enable_dependency_tracking
+enable_multilib
+enable_version_specific_runtime_libs
+enable_shared
+enable_static
+with_pic
+enable_fast_install
+with_gnu_ld
+enable_libtool_lock
+'
+ ac_precious_vars='build_alias
+host_alias
+target_alias
+CXX
+CXXFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CCC
+CC
+CFLAGS
+CPP
+CXXCPP'
+
+
+# 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_TARNAME}'
+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=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
+ $as_echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+ If a cross compiler is detected then cross compile mode will be used." >&2
+ 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 Cilk Runtime Library 2.0 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/cilk-runtime-library]
+ --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
+ case $ac_init_help in
+ short | recursive ) echo "Configuration of Cilk Runtime Library 2.0:";;
+ esac
+ 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-maintainer-mode enable make rules and dependencies not useful
+ (and sometimes confusing) to the casual installer
+ --disable-dependency-tracking speeds up one-time build
+ --enable-dependency-tracking do not reject slow dependency extractors
+ --enable-multilib build many library versions (default)
+ --enable-version-specific-runtime-libs
+ Specify that runtime libraries should be installed
+ in a compi ler-specific directory
+ --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)
+
+Optional Packages:
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --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]
+
+Some influential environment variables:
+ CXX C++ compiler command
+ CXXFLAGS 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 C/C++/Objective C preprocessor flags, e.g. -I<include dir> if
+ you have headers in a nonstandard directory <include dir>
+ CC C compiler command
+ CFLAGS C compiler flags
+ CPP C preprocessor
+ CXXCPP C++ preprocessor
+
+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 <cilk@intel.com>.
+_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
+Cilk Runtime Library configure 2.0
+generated by GNU Autoconf 2.64
+
+Copyright (C) 2009 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_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; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+ return $ac_retval
+
+} # ac_fn_cxx_try_compile
+
+# 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; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+ return $ac_retval
+
+} # ac_fn_c_try_compile
+
+# 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 ||
+ $as_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; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+ return $ac_retval
+
+} # ac_fn_c_try_link
+
+# 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; } >/dev/null && {
+ 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; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+ return $ac_retval
+
+} # ac_fn_c_try_cpp
+
+# 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 { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; 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; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+
+} # ac_fn_c_check_func
+
+# ac_fn_c_try_run LINENO
+# ----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
+# that executables *can* be run.
+ac_fn_c_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; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+ return $ac_retval
+
+} # ac_fn_c_try_run
+
+# ac_fn_c_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_c_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 { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_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; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+
+} # ac_fn_c_check_header_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; } >/dev/null && {
+ 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; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+ return $ac_retval
+
+} # ac_fn_cxx_try_cpp
+
+# 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 ||
+ $as_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; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+ return $ac_retval
+
+} # ac_fn_cxx_try_link
+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 Cilk Runtime Library $as_me 2.0, which was
+generated by GNU Autoconf 2.64. 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
+
+ cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+ 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
+
+ cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+ 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
+ cat <<\_ASBOX
+## ------------------- ##
+## File substitutions. ##
+## ------------------- ##
+_ASBOX
+ 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
+ cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+ 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
+ ac_site_file1=$CONFIG_SITE
+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 -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"
+ 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.
+ if 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
+
+
+
+
+
+
+
+# Needed to define ${target}. Needs to be very early to avoid annoying
+# warning about calling AC_ARG_PROGRAM before AC_CANONICAL_SYSTEM
+ac_aux_dir=
+for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
+ for ac_t in install-sh install.sh shtool; do
+ if test -f "$ac_dir/$ac_t"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/$ac_t -c"
+ break 2
+ fi
+ done
+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 test "${ac_cv_build+set}" = set; 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 test "${ac_cv_host+set}" = set; 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 test "${ac_cv_target+set}" = set; 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}-
+
+target_alias=${target_alias-$host_alias}
+
+ 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
+
+ case ${target_alias} in
+ "") target_noncanonical=${host_noncanonical} ;;
+ *) target_noncanonical=${target_alias} ;;
+esac
+
+
+
+
+
+ LIBSTDCXX_RAW_CXX_CXXFLAGS="\
+ -I\$(top_builddir)/../libstdc++-v3/include \
+ -I\$(top_builddir)/../libstdc++-v3/include/\$(target_noncanonical) \
+ -I\$(top_srcdir)/../libstdc++-v3/libsupc++"
+ LIBSTDCXX_RAW_CXX_LDFLAGS="\
+ \$(top_builddir)/../libstdc++-v3/src/libstdc++.la"
+
+
+
+am__api_version='1.11'
+
+# 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
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+# Reject install programs that cannot install multiple files.
+{ $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 test "${ac_cv_path_install+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in #((
+ ./ | .// | /[cC]/* | \
+ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
+ /usr/ucb/* ) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
+ if test $ac_prog = install &&
+ grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ elif test $ac_prog = install &&
+ grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # program-specific install script used by HP pwplus--don't use.
+ :
+ else
+ rm -rf conftest.one conftest.two conftest.dir
+ echo one > conftest.one
+ echo two > conftest.two
+ mkdir conftest.dir
+ if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" &&
+ test -s conftest.one && test -s conftest.two &&
+ test -s conftest.dir/conftest.one &&
+ test -s conftest.dir/conftest.two
+ then
+ ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+ break 3
+ fi
+ fi
+ fi
+ done
+ done
+ ;;
+esac
+
+ done
+IFS=$as_save_IFS
+
+rm -rf conftest.one conftest.two conftest.dir
+
+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. Don't cache a
+ # value for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the value is a relative name.
+ 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_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5
+$as_echo_n "checking whether build environment is sane... " >&6; }
+# Just in case
+sleep 1
+echo timestamp > conftest.file
+# Reject unsafe characters in $srcdir or the absolute working directory
+# name. Accept space and tab only in the latter.
+am_lf='
+'
+case `pwd` in
+ *[\\\"\#\$\&\'\`$am_lf]*)
+ as_fn_error "unsafe absolute working directory name" "$LINENO" 5;;
+esac
+case $srcdir in
+ *[\\\"\#\$\&\'\`$am_lf\ \ ]*)
+ as_fn_error "unsafe srcdir value: \`$srcdir'" "$LINENO" 5;;
+esac
+
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments. Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+ set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
+ if test "$*" = "X"; then
+ # -L didn't work.
+ set X `ls -t "$srcdir/configure" conftest.file`
+ fi
+ rm -f conftest.file
+ if test "$*" != "X $srcdir/configure conftest.file" \
+ && test "$*" != "X conftest.file $srcdir/configure"; then
+
+ # If neither matched, then we have a broken ls. This can happen
+ # if, for instance, CONFIG_SHELL is bash and it inherits a
+ # broken ls alias from the environment. This has actually
+ # happened. Such a system could not be considered "sane".
+ as_fn_error "ls -t appears to fail. Make sure there is not a broken
+alias in your environment" "$LINENO" 5
+ fi
+
+ test "$2" = conftest.file
+ )
+then
+ # Ok.
+ :
+else
+ as_fn_error "newly created file is older than distributed files!
+Check your system clock" "$LINENO" 5
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+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"`
+
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+
+if test x"${MISSING+set}" != xset; then
+ case $am_aux_dir in
+ *\ * | *\ *)
+ MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
+ *)
+ MISSING="\${SHELL} $am_aux_dir/missing" ;;
+ esac
+fi
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+ am_missing_run="$MISSING --run "
+else
+ am_missing_run=
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`missing' script is too old or missing" >&5
+$as_echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;}
+fi
+
+if test x"${install_sh}" != xset; then
+ case $am_aux_dir in
+ *\ * | *\ *)
+ install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
+ *)
+ install_sh="\${SHELL} $am_aux_dir/install-sh"
+ esac
+fi
+
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'. However `strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the `STRIP' environment variable to overrule this program.
+if test "$cross_compiling" != no; then
+ 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 test "${ac_cv_prog_STRIP+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_ac_ct_STRIP+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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
+
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5
+$as_echo_n "checking for a thread-safe mkdir -p... " >&6; }
+if test -z "$MKDIR_P"; then
+ if test "${ac_cv_path_mkdir+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in mkdir gmkdir; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; } || continue
+ case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #(
+ 'mkdir (GNU coreutils) '* | \
+ 'mkdir (coreutils) '* | \
+ 'mkdir (fileutils) '4.1*)
+ ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext
+ break 3;;
+ esac
+ done
+ done
+ done
+IFS=$as_save_IFS
+
+fi
+
+ if test "${ac_cv_path_mkdir+set}" = set; then
+ MKDIR_P="$ac_cv_path_mkdir -p"
+ else
+ # As a last resort, use the slow shell script. Don't cache a
+ # value for MKDIR_P within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the value is a relative name.
+ test -d ./--version && rmdir ./--version
+ MKDIR_P="$ac_install_sh -d"
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5
+$as_echo "$MKDIR_P" >&6; }
+
+mkdir_p="$MKDIR_P"
+case $mkdir_p in
+ [\\/$]* | ?:[\\/]*) ;;
+ */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;;
+esac
+
+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 test "${ac_cv_prog_AWK+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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
+
+{ $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 { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; 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
+
+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
+
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+ # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+ # is not polluted with repeated "-I."
+ am__isrc=' -I$(srcdir)'
+ # test to see if srcdir already configured
+ if test -f $srcdir/config.status; then
+ as_fn_error "source directory already configured; run \"make distclean\" there first" "$LINENO" 5
+ fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+ if (cygpath --version) >/dev/null 2>/dev/null; then
+ CYGPATH_W='cygpath -w'
+ else
+ CYGPATH_W=echo
+ fi
+fi
+
+
+# Define the identity of the package.
+ PACKAGE='cilk-runtime-library'
+ VERSION='2.0'
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE "$PACKAGE"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define VERSION "$VERSION"
+_ACEOF
+
+# Some tools Automake needs.
+
+ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"}
+
+
+AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"}
+
+
+AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"}
+
+
+AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"}
+
+
+MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
+
+# We need awk for the "check" target. The system "awk" is bad on
+# some platforms.
+# Always define AMTAR for backward compatibility.
+
+AMTAR=${AMTAR-"${am_missing_run}tar"}
+
+am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'
+
+
+
+
+
+
+
+{ $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; USE_MAINTAINER_MODE=$enableval
+else
+ USE_MAINTAINER_MODE=no
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5
+$as_echo "$USE_MAINTAINER_MODE" >&6; }
+ if test $USE_MAINTAINER_MODE = yes; then
+ MAINTAINER_MODE_TRUE=
+ MAINTAINER_MODE_FALSE='#'
+else
+ MAINTAINER_MODE_TRUE='#'
+ MAINTAINER_MODE_FALSE=
+fi
+
+ MAINT=$MAINTAINER_MODE_TRUE
+
+
+
+# Build a DLL on Windows
+# AC_LIBTOOL_WIN32_DLL
+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 test "${ac_cv_prog_CXX+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_ac_ct_CXX+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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
+ rm -f conftest.er1 conftest.err
+ fi
+ $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 conftest.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 for C++ compiler default output file name" >&5
+$as_echo_n "checking for C++ compiler default output file name... " >&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
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+if test -z "$ac_file"; then :
+ $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_set_status 77
+as_fn_error "C++ compiler cannot create executables
+See \`config.log' for more details." "$LINENO" 5; }; }
+fi
+ac_exeext=$ac_cv_exeext
+
+# 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 the C++ compiler works" >&5
+$as_echo_n "checking whether the C++ compiler works... " >&6; }
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+ if { ac_try='./$ac_file'
+ { { 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: yes" >&5
+$as_echo "yes" >&6; }
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out conftest.out
+ac_clean_files=$ac_clean_files_save
+# 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; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+{ $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$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
+{ $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 test "${ac_cv_objext+set}" = set; 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 test "${ac_cv_cxx_compiler_gnu+set}" = set; 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 test "${ac_cv_prog_cxx_g+set}" = set; 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
+DEPDIR="${am__leading_dot}deps"
+
+ac_config_commands="$ac_config_commands depfiles"
+
+
+am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+ @echo this is the am__doit target
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5
+$as_echo_n "checking for style of include used by $am_make... " >&6; }
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# Ignore all kinds of additional output from `make'.
+case `$am_make -s -f confmf 2> /dev/null` in #(
+*the\ am__doit\ target*)
+ am__include=include
+ am__quote=
+ _am_result=GNU
+ ;;
+esac
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+ echo '.include "confinc"' > confmf
+ case `$am_make -s -f confmf 2> /dev/null` in #(
+ *the\ am__doit\ target*)
+ am__include=.include
+ am__quote="\""
+ _am_result=BSD
+ ;;
+ esac
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5
+$as_echo "$_am_result" >&6; }
+rm -f confinc confmf
+
+# Check whether --enable-dependency-tracking was given.
+if test "${enable_dependency_tracking+set}" = set; then :
+ enableval=$enable_dependency_tracking;
+fi
+
+if test "x$enable_dependency_tracking" != xno; then
+ am_depcomp="$ac_aux_dir/depcomp"
+ AMDEPBACKSLASH='\'
+fi
+ if test "x$enable_dependency_tracking" != xno; then
+ AMDEP_TRUE=
+ AMDEP_FALSE='#'
+else
+ AMDEP_TRUE='#'
+ AMDEP_FALSE=
+fi
+
+
+
+depcc="$CXX" am_compiler_list=
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
+$as_echo_n "checking dependency style of $depcc... " >&6; }
+if test "${am_cv_CXX_dependencies_compiler_type+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -z "$AMDEP_TRUE" && 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
+ am__universal=false
+ case " $depcc " in #(
+ *\ -arch\ *\ -arch\ *) am__universal=true ;;
+ esac
+
+ for depmode in $am_compiler_list; do
+ # 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 "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > 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. Also, some Intel
+ # versions had trouble with output in subdirs
+ am__obj=sub/conftest.${OBJEXT-o}
+ am__minus_obj="-o $am__obj"
+ case $depmode in
+ gcc)
+ # This depmode causes a compiler race in universal mode.
+ test "$am__universal" = false || continue
+ ;;
+ nosideeffect)
+ # after this tag, mechanisms are not by side-effect, so they'll
+ # only be used when explicitly requested
+ if test "x$enable_dependency_tracking" = xyes; then
+ continue
+ else
+ break
+ fi
+ ;;
+ msvisualcpp | msvcmsys)
+ # This compiler won't grok `-c -o', but also, the minuso test has
+ # not run yet. These depmodes are late enough in the game, and
+ # so weak that their functioning should not be impacted.
+ am__obj=conftest.${OBJEXT-o}
+ am__minus_obj=
+ ;;
+ none) break ;;
+ esac
+ if depmode=$depmode \
+ source=sub/conftest.c object=$am__obj \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+ >/dev/null 2>conftest.err &&
+ grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+ ${MAKE-make} -s -f confmf > /dev/null 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
+ break
+ fi
+ fi
+ 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; }
+CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type
+
+ if
+ test "x$enable_dependency_tracking" != xno \
+ && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then
+ am__fastdepCXX_TRUE=
+ am__fastdepCXX_FALSE='#'
+else
+ am__fastdepCXX_TRUE='#'
+ am__fastdepCXX_FALSE=
+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
+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 test "${ac_cv_prog_CC+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_ac_ct_CC+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_CC+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_CC+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_CC+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_ac_ct_CC+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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
+ rm -f conftest.er1 conftest.err
+ fi
+ $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 test "${ac_cv_c_compiler_gnu+set}" = set; 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 test "${ac_cv_prog_cc_g+set}" = set; 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 test "${ac_cv_prog_cc_c89+set}" = set; 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>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* 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
+
+depcc="$CC" am_compiler_list=
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
+$as_echo_n "checking dependency style of $depcc... " >&6; }
+if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -z "$AMDEP_TRUE" && 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_CC_dependencies_compiler_type=none
+ if test "$am_compiler_list" = ""; then
+ am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+ fi
+ am__universal=false
+ case " $depcc " in #(
+ *\ -arch\ *\ -arch\ *) am__universal=true ;;
+ esac
+
+ for depmode in $am_compiler_list; do
+ # 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 "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > 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. Also, some Intel
+ # versions had trouble with output in subdirs
+ am__obj=sub/conftest.${OBJEXT-o}
+ am__minus_obj="-o $am__obj"
+ case $depmode in
+ gcc)
+ # This depmode causes a compiler race in universal mode.
+ test "$am__universal" = false || continue
+ ;;
+ nosideeffect)
+ # after this tag, mechanisms are not by side-effect, so they'll
+ # only be used when explicitly requested
+ if test "x$enable_dependency_tracking" = xyes; then
+ continue
+ else
+ break
+ fi
+ ;;
+ msvisualcpp | msvcmsys)
+ # This compiler won't grok `-c -o', but also, the minuso test has
+ # not run yet. These depmodes are late enough in the game, and
+ # so weak that their functioning should not be impacted.
+ am__obj=conftest.${OBJEXT-o}
+ am__minus_obj=
+ ;;
+ none) break ;;
+ esac
+ if depmode=$depmode \
+ source=sub/conftest.c object=$am__obj \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+ >/dev/null 2>conftest.err &&
+ grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+ ${MAKE-make} -s -f confmf > /dev/null 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_CC_dependencies_compiler_type=$depmode
+ break
+ fi
+ fi
+ done
+
+ cd ..
+ rm -rf conftest.dir
+else
+ am_cv_CC_dependencies_compiler_type=none
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5
+$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; }
+CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
+
+ if
+ test "x$enable_dependency_tracking" != xno \
+ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then
+ am__fastdepCC_TRUE=
+ am__fastdepCC_FALSE='#'
+else
+ am__fastdepCC_TRUE='#'
+ am__fastdepCC_FALSE=
+fi
+
+
+# AC_PROG_LIBTOOL
+# AC_CONFIG_MACRO_DIR([..])
+ac_config_files="$ac_config_files Makefile"
+
+# Default to --enable-multilib
+# Check whether --enable-multilib was given.
+if test "${enable_multilib+set}" = set; then :
+ enableval=$enable_multilib; case "$enableval" in
+ yes) multilib=yes ;;
+ no) multilib=no ;;
+ *) as_fn_error "bad value $enableval for multilib option" "$LINENO" 5 ;;
+ esac
+else
+ multilib=yes
+fi
+
+
+# We may get other options which we leave undocumented:
+# --with-target-subdir, --with-multisrctop, --with-multisubdir
+# See config-ml.in if you want the gory details.
+
+if test "$srcdir" = "."; then
+ if test "$with_target_subdir" != "."; then
+ multi_basedir="$srcdir/$with_multisrctop../.."
+ else
+ multi_basedir="$srcdir/$with_multisrctop.."
+ fi
+else
+ multi_basedir="$srcdir/.."
+fi
+
+
+# Even if the default multilib is not a cross compilation,
+# it may be that some of the other multilibs are.
+if test $cross_compiling = no && test $multilib = yes \
+ && test "x${with_multisubdir}" != x ; then
+ cross_compiling=maybe
+fi
+
+ac_config_commands="$ac_config_commands default-1"
+
+
+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 test "${ac_cv_prog_CPP+set}" = set; 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.$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.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f 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.$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.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f 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=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 for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if test "${ac_cv_path_GREP+set}" = set; 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"
+ { test -f "$ac_path_GREP" && $as_test_x "$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 test "${ac_cv_path_EGREP+set}" = set; 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"
+ { test -f "$ac_path_EGREP" && $as_test_x "$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 test "${ac_cv_header_stdc+set}" = set; 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_c_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_c_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_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
+"
+eval as_val=\$$as_ac_Header
+ if test "x$as_val" = x""yes; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works
+# for constant arguments. Useless!
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working alloca.h" >&5
+$as_echo_n "checking for working alloca.h... " >&6; }
+if test "${ac_cv_working_alloca_h+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <alloca.h>
+int
+main ()
+{
+char *p = (char *) alloca (2 * sizeof (int));
+ if (p) return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_working_alloca_h=yes
+else
+ ac_cv_working_alloca_h=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: $ac_cv_working_alloca_h" >&5
+$as_echo "$ac_cv_working_alloca_h" >&6; }
+if test $ac_cv_working_alloca_h = yes; then
+
+$as_echo "#define HAVE_ALLOCA_H 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for alloca" >&5
+$as_echo_n "checking for alloca... " >&6; }
+if test "${ac_cv_func_alloca_works+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __GNUC__
+# define alloca __builtin_alloca
+#else
+# ifdef _MSC_VER
+# include <malloc.h>
+# define alloca _alloca
+# else
+# ifdef HAVE_ALLOCA_H
+# include <alloca.h>
+# else
+# ifdef _AIX
+ #pragma alloca
+# else
+# ifndef alloca /* predefined by HP cc +Olibcalls */
+char *alloca ();
+# endif
+# endif
+# endif
+# endif
+#endif
+
+int
+main ()
+{
+char *p = (char *) alloca (1);
+ if (p) return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_func_alloca_works=yes
+else
+ ac_cv_func_alloca_works=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: $ac_cv_func_alloca_works" >&5
+$as_echo "$ac_cv_func_alloca_works" >&6; }
+
+if test $ac_cv_func_alloca_works = yes; then
+
+$as_echo "#define HAVE_ALLOCA 1" >>confdefs.h
+
+else
+ # The SVR3 libPW and SVR4 libucb both contain incompatible functions
+# that cause trouble. Some versions do not even contain alloca or
+# contain a buggy version. If you still want to use their alloca,
+# use ar to extract alloca.o from them instead of compiling alloca.c.
+
+ALLOCA=\${LIBOBJDIR}alloca.$ac_objext
+
+$as_echo "#define C_ALLOCA 1" >>confdefs.h
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether \`alloca.c' needs Cray hooks" >&5
+$as_echo_n "checking whether \`alloca.c' needs Cray hooks... " >&6; }
+if test "${ac_cv_os_cray+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#if defined CRAY && ! defined CRAY2
+webecray
+#else
+wenotbecray
+#endif
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "webecray" >/dev/null 2>&1; then :
+ ac_cv_os_cray=yes
+else
+ ac_cv_os_cray=no
+fi
+rm -f conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_os_cray" >&5
+$as_echo "$ac_cv_os_cray" >&6; }
+if test $ac_cv_os_cray = yes; then
+ for ac_func in _getb67 GETB67 getb67; do
+ as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+eval as_val=\$$as_ac_var
+ if test "x$as_val" = x""yes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define CRAY_STACKSEG_END $ac_func
+_ACEOF
+
+ break
+fi
+
+ done
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking stack direction for C alloca" >&5
+$as_echo_n "checking stack direction for C alloca... " >&6; }
+if test "${ac_cv_c_stack_direction+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "$cross_compiling" = yes; then :
+ ac_cv_c_stack_direction=0
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+int
+find_stack_direction ()
+{
+ static char *addr = 0;
+ auto char dummy;
+ if (addr == 0)
+ {
+ addr = &dummy;
+ return find_stack_direction ();
+ }
+ else
+ return (&dummy > addr) ? 1 : -1;
+}
+
+int
+main ()
+{
+ return find_stack_direction () < 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+ ac_cv_c_stack_direction=1
+else
+ ac_cv_c_stack_direction=-1
+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_c_stack_direction" >&5
+$as_echo "$ac_cv_c_stack_direction" >&6; }
+cat >>confdefs.h <<_ACEOF
+#define STACK_DIRECTION $ac_cv_c_stack_direction
+_ACEOF
+
+
+fi
+
+
+# Get target configury.
+. ${srcdir}/configure.tgt
+if test -n "$UNSUPPORTED"; then
+ as_fn_error "Configuration ${target} is unsupported." "$LINENO" 5
+fi
+
+if test "${multilib}" = "yes"; then
+ multilib_arg="--enable-multilib"
+else
+ multilib_arg=
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for --enable-version-specific-runtime-libs" >&5
+$as_echo_n "checking for --enable-version-specific-runtime-libs... " >&6; }
+# 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; case "$enableval" in
+ yes) enable_version_specific_runtime_libs=yes ;;
+ no) enable_version_specific_runtime_libs=no ;;
+ *) as_fn_error "Unknown argument to enable/disable version-specific libs
+" "$LINENO" 5;;
+ esac
+else
+ enable_version_specific_runtime_libs=no
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_version_specific_runtime_libs" >&5
+$as_echo "$enable_version_specific_runtime_libs" >&6; }
+
+
+# Calculate toolexeclibdir
+# Also toolexecdir, though it's only used in toolexeclibdir
+case ${enable_version_specific_runtime_libs} in
+ yes)
+ # Need the gcc compiler version to know where to install libraries
+ # and header files if --enable-version-specific-runtime-libs option
+ # is selected.
+ toolexecdir='$(libdir)/gcc/$(target_alias)'
+ toolexeclibdir='$(toolexecdir)/$(gcc_version)$(MULTISUBDIR)'
+ ;;
+ no)
+ if test -n "$with_cross_host" &&
+ test x"$with_cross_host" != x"no"; then
+ # Install a library built with a cross compiler in tooldir, not libdir.
+ toolexecdir='$(exec_prefix)/$(target_alias)'
+ toolexeclibdir='$(toolexecdir)/lib'
+ else
+ toolexecdir='$(libdir)/gcc-lib/$(target_alias)'
+ toolexeclibdir='$(libdir)'
+ fi
+ multi_os_directory=`$CC -print-multi-os-directory`
+ case $multi_os_directory in
+ .) ;; # Avoid trailing /.
+ *) toolexeclibdir=$toolexeclibdir/$multi_os_directory ;;
+ esac
+ ;;
+esac
+
+# Set config_dir based on the target. config_dir specifies where to get
+# target-specific files. The generic implementation is incomplete, but
+# contains information on what's needed
+case "${target}" in
+
+ x86_64-*-*)
+ config_dir="x86"
+ ;;
+
+ i?86-*-*)
+ config_dir="x86"
+ ;;
+
+ *)
+ config_dir="generic"
+ ;;
+
+esac
+
+
+# We have linker scripts for appropriate operating systems
+linux_linker_script=no
+case "${host}" in
+ *-*-linux*)
+ linux_linker_script=yes
+ ;;
+esac
+ if test "$linux_linker_script" = "yes"; then
+ LINUX_LINKER_SCRIPT_TRUE=
+ LINUX_LINKER_SCRIPT_FALSE='#'
+else
+ LINUX_LINKER_SCRIPT_TRUE='#'
+ LINUX_LINKER_SCRIPT_FALSE=
+fi
+
+
+mac_linker_script=no
+case "${host}" in
+ *-*-apple*)
+ mac_linker_script=yes
+ ;;
+esac
+ if test "$mac_linker_script" = "yes"; then
+ MAC_LINKER_SCRIPT_TRUE=
+ MAC_LINKER_SCRIPT_FALSE='#'
+else
+ MAC_LINKER_SCRIPT_TRUE='#'
+ MAC_LINKER_SCRIPT_FALSE=
+fi
+
+
+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 test "${ac_cv_path_SED+set}" = set; 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"
+ { test -f "$ac_path_SED" && $as_test_x "$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 test "${ac_cv_path_FGREP+set}" = set; 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"
+ { test -f "$ac_path_FGREP" && $as_test_x "$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 test "${lt_cv_path_LD+set}" = set; 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 test "${lt_cv_prog_gnu_ld+set}" = set; 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 test "${lt_cv_path_NM+set}" = set; 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 test "${ac_cv_prog_DUMPBIN+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_ac_ct_DUMPBIN+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${lt_cv_nm_interface+set}" = set; 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 test "${lt_cv_sys_max_cmd_len+set}" = set; 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 test "${lt_cv_ld_reload_flag+set}" = set; 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 test "${ac_cv_prog_OBJDUMP+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_ac_ct_OBJDUMP+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${lt_cv_deplibs_check_method+set}" = set; 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)
+ 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 test "${ac_cv_prog_AR+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_ac_ct_AR+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_STRIP+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_ac_ct_STRIP+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_RANLIB+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${lt_cv_sys_global_symbol_pipe+set}" = set; 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 test "${lt_cv_cc_needs_belf+set}" = set; 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 test "${ac_cv_prog_DSYMUTIL+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_ac_ct_DSYMUTIL+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_NMEDIT+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_ac_ct_NMEDIT+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_LIPO+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_ac_ct_LIPO+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_OTOOL+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_ac_ct_OTOOL+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_OTOOL64+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_ac_ct_OTOOL64+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${lt_cv_apple_cc_single_mod+set}" = set; 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 test "${lt_cv_ld_exported_symbols_list+set}" = set; 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 test "${lt_cv_ld_force_load+set}" = set; 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; }
+ case $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 on
+ # if running on 10.5 or later, the deployment target defaults
+ # to the OS version, if on x86, and 10.4, the deployment
+ # target defaults to 10.4. Don't you love it?
+ case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
+ 10.0,*86*-darwin8*|10.0,*-darwin[91]*)
+ _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
+ 10.[012]*)
+ _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
+ 10.*)
+ _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
+ 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_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default
+"
+if test "x$ac_cv_header_dlfcn_h" = x""yes; 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 test "${lt_cv_objdir+set}" = set; 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 test "${lt_cv_path_MAGIC_CMD+set}" = set; 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 test "${lt_cv_path_MAGIC_CMD+set}" = set; 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 test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; 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 test "${lt_cv_prog_compiler_pic_works+set}" = set; 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 test "${lt_cv_prog_compiler_static_works+set}" = set; 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 test "${lt_cv_prog_compiler_c_o+set}" = set; 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 test "${lt_cv_prog_compiler_c_o+set}" = set; 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)
+ 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=
+ 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")) && (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 -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 -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 test "${lt_cv_prog_compiler__b+set}" = set; 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 test "${lt_cv_archive_cmds_need_lc+set}" = set; 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
+ ;;
+
+gnu*)
+ 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
+ hardcode_into_libs=yes
+ ;;
+
+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.
+linux* | k*bsd*-gnu | kopensolaris*-gnu)
+ 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 test "${lt_cv_shlibpath_overrides_runpath+set}" = set; 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 test "${ac_cv_lib_dl_dlopen+set}" = set; 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" = x""yes; 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" = x""yes; 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 test "${ac_cv_lib_dld_shl_load+set}" = set; 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" = x""yes; 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" = x""yes; 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 test "${ac_cv_lib_dl_dlopen+set}" = set; 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" = x""yes; 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 test "${ac_cv_lib_svld_dlopen+set}" = set; 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" = x""yes; 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 test "${ac_cv_lib_dld_dld_link+set}" = set; 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" = x""yes; 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 test "${lt_cv_dlopen_self+set}" = set; 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 11060 "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 test "${lt_cv_dlopen_self_static+set}" = set; 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 11166 "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=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
+
+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 test "${ac_cv_prog_CXXCPP+set}" = set; 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.$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.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f 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.$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.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f 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=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
+
+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 test "${lt_cv_path_LD+set}" = set; 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 test "${lt_cv_prog_gnu_ld+set}" = set; 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 -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_CXX='$CC -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 -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 -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 | $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 | $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 | $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 | $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 test "${lt_cv_prog_compiler_pic_works_CXX+set}" = set; 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 test "${lt_cv_prog_compiler_static_works_CXX+set}" = set; 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 test "${lt_cv_prog_compiler_c_o_CXX+set}" = set; 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 test "${lt_cv_prog_compiler_c_o_CXX+set}" = set; 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")) && (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 test "${lt_cv_archive_cmds_need_lc_CXX+set}" = set; 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
+ ;;
+
+gnu*)
+ 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
+ hardcode_into_libs=yes
+ ;;
+
+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.
+linux* | k*bsd*-gnu | kopensolaris*-gnu)
+ 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 test "${lt_cv_shlibpath_overrides_runpath+set}" = set; 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=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_commands="$ac_config_commands libtool"
+
+
+
+
+# Only expand once:
+
+
+
+
+
+# Must be last
+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
+ test "x$cache_file" != "x/dev/null" &&
+ { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+ cat confcache >$cache_file
+ 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}'
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+#
+# If the first sed substitution is executed (which looks for macros that
+# take arguments), then branch to the quote section. Otherwise,
+# look for a macro that doesn't take arguments.
+ac_script='
+:mline
+/\\$/{
+ N
+ s,\\\n,,
+ b mline
+}
+t clear
+:clear
+s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g
+t quote
+s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g
+t quote
+b any
+:quote
+s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g
+s/\[/\\&/g
+s/\]/\\&/g
+s/\$/$$/g
+H
+:any
+${
+ g
+ s/^\n//
+ s/\n/ /g
+ p
+}
+'
+DEFS=`sed -n "$ac_script" confdefs.h`
+
+
+ac_libobjs=
+ac_ltlibobjs=
+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
+
+
+ if test -n "$EXEEXT"; then
+ am__EXEEXT_TRUE=
+ am__EXEEXT_FALSE='#'
+else
+ am__EXEEXT_TRUE='#'
+ am__EXEEXT_FALSE=
+fi
+
+if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then
+ as_fn_error "conditional \"MAINTAINER_MODE\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then
+ as_fn_error "conditional \"AMDEP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then
+ as_fn_error "conditional \"am__fastdepCXX\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
+ as_fn_error "conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${LINUX_LINKER_SCRIPT_TRUE}" && test -z "${LINUX_LINKER_SCRIPT_FALSE}"; then
+ as_fn_error "conditional \"LINUX_LINKER_SCRIPT\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${MAC_LINKER_SCRIPT_TRUE}" && test -z "${MAC_LINKER_SCRIPT_FALSE}"; then
+ as_fn_error "conditional \"MAC_LINKER_SCRIPT\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+
+: ${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.
+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 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=$?; test $as_status -eq 0 && as_status=1
+ if test "$3"; then
+ as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3
+ fi
+ $as_echo "$as_me: error: $1" >&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 -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -p'
+ fi
+else
+ as_ln_s='cp -p'
+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
+
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in #(
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
+
+# 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 Cilk Runtime Library $as_me 2.0, which was
+generated by GNU Autoconf 2.64. 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
+
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+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
+ -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
+
+Configuration files:
+$config_files
+
+Configuration commands:
+$config_commands
+
+Report bugs to <cilk@intel.com>."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_version="\\
+Cilk Runtime Library config.status 2.0
+configured by $0, generated by GNU Autoconf 2.64,
+ with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright (C) 2009 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'
+INSTALL='$INSTALL'
+MKDIR_P='$MKDIR_P'
+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=$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 ;;
+ --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"` ;;
+ esac
+ as_fn_append CONFIG_FILES " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --he | --h | --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
+#
+AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"
+
+srcdir="$srcdir"
+host="$host"
+target="$target"
+with_multisubdir="$with_multisubdir"
+with_multisrctop="$with_multisrctop"
+with_target_subdir="$with_target_subdir"
+ac_configure_args="${multilib_arg} ${ac_configure_args}"
+multi_basedir="$multi_basedir"
+CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
+CC="$CC"
+CXX="$CXX"
+GFORTRAN="$GFORTRAN"
+GCJ="$GCJ"
+
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+sed_quote_subst='$sed_quote_subst'
+double_quote_subst='$double_quote_subst'
+delay_variable_subst='$delay_variable_subst'
+macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`'
+macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`'
+enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`'
+enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`'
+pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`'
+enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`'
+SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`'
+ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`'
+host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`'
+host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`'
+host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`'
+build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`'
+build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`'
+build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`'
+SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`'
+Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`'
+GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`'
+EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`'
+FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`'
+LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`'
+NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`'
+LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`'
+max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`'
+ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`'
+exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`'
+lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`'
+lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`'
+lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`'
+reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`'
+reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`'
+OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`'
+deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`'
+file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`'
+AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`'
+AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`'
+STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`'
+RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`'
+old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`'
+old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`'
+old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`'
+lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`'
+CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`'
+CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`'
+compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`'
+GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`'
+objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`'
+MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`'
+lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`'
+need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`'
+DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`'
+NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`'
+LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`'
+OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`'
+OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`'
+libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`'
+shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`'
+extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`'
+archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`'
+enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`'
+export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`'
+whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`'
+compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`'
+old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`'
+old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`'
+archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`'
+archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`'
+module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`'
+module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`'
+with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`'
+allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`'
+no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`'
+hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`'
+hardcode_libdir_flag_spec_ld='`$ECHO "$hardcode_libdir_flag_spec_ld" | $SED "$delay_single_quote_subst"`'
+hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`'
+hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`'
+hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`'
+hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`'
+hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`'
+hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`'
+inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`'
+link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`'
+fix_srcfile_path='`$ECHO "$fix_srcfile_path" | $SED "$delay_single_quote_subst"`'
+always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`'
+export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`'
+exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`'
+include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`'
+prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`'
+file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`'
+variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`'
+need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`'
+need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`'
+version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`'
+runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`'
+shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`'
+shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`'
+libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`'
+library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`'
+soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`'
+install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`'
+postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`'
+postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`'
+finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`'
+finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`'
+hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`'
+sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`'
+sys_lib_dlsearch_path_spec='`$ECHO "$sys_lib_dlsearch_path_spec" | $SED "$delay_single_quote_subst"`'
+hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`'
+enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`'
+enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`'
+enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`'
+old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`'
+striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`'
+compiler_lib_search_dirs='`$ECHO "$compiler_lib_search_dirs" | $SED "$delay_single_quote_subst"`'
+predep_objects='`$ECHO "$predep_objects" | $SED "$delay_single_quote_subst"`'
+postdep_objects='`$ECHO "$postdep_objects" | $SED "$delay_single_quote_subst"`'
+predeps='`$ECHO "$predeps" | $SED "$delay_single_quote_subst"`'
+postdeps='`$ECHO "$postdeps" | $SED "$delay_single_quote_subst"`'
+compiler_lib_search_path='`$ECHO "$compiler_lib_search_path" | $SED "$delay_single_quote_subst"`'
+LD_CXX='`$ECHO "$LD_CXX" | $SED "$delay_single_quote_subst"`'
+reload_flag_CXX='`$ECHO "$reload_flag_CXX" | $SED "$delay_single_quote_subst"`'
+reload_cmds_CXX='`$ECHO "$reload_cmds_CXX" | $SED "$delay_single_quote_subst"`'
+old_archive_cmds_CXX='`$ECHO "$old_archive_cmds_CXX" | $SED "$delay_single_quote_subst"`'
+compiler_CXX='`$ECHO "$compiler_CXX" | $SED "$delay_single_quote_subst"`'
+GCC_CXX='`$ECHO "$GCC_CXX" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_no_builtin_flag_CXX='`$ECHO "$lt_prog_compiler_no_builtin_flag_CXX" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_wl_CXX='`$ECHO "$lt_prog_compiler_wl_CXX" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_pic_CXX='`$ECHO "$lt_prog_compiler_pic_CXX" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_static_CXX='`$ECHO "$lt_prog_compiler_static_CXX" | $SED "$delay_single_quote_subst"`'
+lt_cv_prog_compiler_c_o_CXX='`$ECHO "$lt_cv_prog_compiler_c_o_CXX" | $SED "$delay_single_quote_subst"`'
+archive_cmds_need_lc_CXX='`$ECHO "$archive_cmds_need_lc_CXX" | $SED "$delay_single_quote_subst"`'
+enable_shared_with_static_runtimes_CXX='`$ECHO "$enable_shared_with_static_runtimes_CXX" | $SED "$delay_single_quote_subst"`'
+export_dynamic_flag_spec_CXX='`$ECHO "$export_dynamic_flag_spec_CXX" | $SED "$delay_single_quote_subst"`'
+whole_archive_flag_spec_CXX='`$ECHO "$whole_archive_flag_spec_CXX" | $SED "$delay_single_quote_subst"`'
+compiler_needs_object_CXX='`$ECHO "$compiler_needs_object_CXX" | $SED "$delay_single_quote_subst"`'
+old_archive_from_new_cmds_CXX='`$ECHO "$old_archive_from_new_cmds_CXX" | $SED "$delay_single_quote_subst"`'
+old_archive_from_expsyms_cmds_CXX='`$ECHO "$old_archive_from_expsyms_cmds_CXX" | $SED "$delay_single_quote_subst"`'
+archive_cmds_CXX='`$ECHO "$archive_cmds_CXX" | $SED "$delay_single_quote_subst"`'
+archive_expsym_cmds_CXX='`$ECHO "$archive_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`'
+module_cmds_CXX='`$ECHO "$module_cmds_CXX" | $SED "$delay_single_quote_subst"`'
+module_expsym_cmds_CXX='`$ECHO "$module_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`'
+with_gnu_ld_CXX='`$ECHO "$with_gnu_ld_CXX" | $SED "$delay_single_quote_subst"`'
+allow_undefined_flag_CXX='`$ECHO "$allow_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`'
+no_undefined_flag_CXX='`$ECHO "$no_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`'
+hardcode_libdir_flag_spec_CXX='`$ECHO "$hardcode_libdir_flag_spec_CXX" | $SED "$delay_single_quote_subst"`'
+hardcode_libdir_flag_spec_ld_CXX='`$ECHO "$hardcode_libdir_flag_spec_ld_CXX" | $SED "$delay_single_quote_subst"`'
+hardcode_libdir_separator_CXX='`$ECHO "$hardcode_libdir_separator_CXX" | $SED "$delay_single_quote_subst"`'
+hardcode_direct_CXX='`$ECHO "$hardcode_direct_CXX" | $SED "$delay_single_quote_subst"`'
+hardcode_direct_absolute_CXX='`$ECHO "$hardcode_direct_absolute_CXX" | $SED "$delay_single_quote_subst"`'
+hardcode_minus_L_CXX='`$ECHO "$hardcode_minus_L_CXX" | $SED "$delay_single_quote_subst"`'
+hardcode_shlibpath_var_CXX='`$ECHO "$hardcode_shlibpath_var_CXX" | $SED "$delay_single_quote_subst"`'
+hardcode_automatic_CXX='`$ECHO "$hardcode_automatic_CXX" | $SED "$delay_single_quote_subst"`'
+inherit_rpath_CXX='`$ECHO "$inherit_rpath_CXX" | $SED "$delay_single_quote_subst"`'
+link_all_deplibs_CXX='`$ECHO "$link_all_deplibs_CXX" | $SED "$delay_single_quote_subst"`'
+fix_srcfile_path_CXX='`$ECHO "$fix_srcfile_path_CXX" | $SED "$delay_single_quote_subst"`'
+always_export_symbols_CXX='`$ECHO "$always_export_symbols_CXX" | $SED "$delay_single_quote_subst"`'
+export_symbols_cmds_CXX='`$ECHO "$export_symbols_cmds_CXX" | $SED "$delay_single_quote_subst"`'
+exclude_expsyms_CXX='`$ECHO "$exclude_expsyms_CXX" | $SED "$delay_single_quote_subst"`'
+include_expsyms_CXX='`$ECHO "$include_expsyms_CXX" | $SED "$delay_single_quote_subst"`'
+prelink_cmds_CXX='`$ECHO "$prelink_cmds_CXX" | $SED "$delay_single_quote_subst"`'
+file_list_spec_CXX='`$ECHO "$file_list_spec_CXX" | $SED "$delay_single_quote_subst"`'
+hardcode_action_CXX='`$ECHO "$hardcode_action_CXX" | $SED "$delay_single_quote_subst"`'
+compiler_lib_search_dirs_CXX='`$ECHO "$compiler_lib_search_dirs_CXX" | $SED "$delay_single_quote_subst"`'
+predep_objects_CXX='`$ECHO "$predep_objects_CXX" | $SED "$delay_single_quote_subst"`'
+postdep_objects_CXX='`$ECHO "$postdep_objects_CXX" | $SED "$delay_single_quote_subst"`'
+predeps_CXX='`$ECHO "$predeps_CXX" | $SED "$delay_single_quote_subst"`'
+postdeps_CXX='`$ECHO "$postdeps_CXX" | $SED "$delay_single_quote_subst"`'
+compiler_lib_search_path_CXX='`$ECHO "$compiler_lib_search_path_CXX" | $SED "$delay_single_quote_subst"`'
+
+LTCC='$LTCC'
+LTCFLAGS='$LTCFLAGS'
+compiler='$compiler_DEFAULT'
+
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+ eval 'cat <<_LTECHO_EOF
+\$1
+_LTECHO_EOF'
+}
+
+# Quote evaled strings.
+for var in SHELL \
+ECHO \
+SED \
+GREP \
+EGREP \
+FGREP \
+LD \
+NM \
+LN_S \
+lt_SP2NL \
+lt_NL2SP \
+reload_flag \
+OBJDUMP \
+deplibs_check_method \
+file_magic_cmd \
+AR \
+AR_FLAGS \
+STRIP \
+RANLIB \
+CC \
+CFLAGS \
+compiler \
+lt_cv_sys_global_symbol_pipe \
+lt_cv_sys_global_symbol_to_cdecl \
+lt_cv_sys_global_symbol_to_c_name_address \
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \
+lt_prog_compiler_no_builtin_flag \
+lt_prog_compiler_wl \
+lt_prog_compiler_pic \
+lt_prog_compiler_static \
+lt_cv_prog_compiler_c_o \
+need_locks \
+DSYMUTIL \
+NMEDIT \
+LIPO \
+OTOOL \
+OTOOL64 \
+shrext_cmds \
+export_dynamic_flag_spec \
+whole_archive_flag_spec \
+compiler_needs_object \
+with_gnu_ld \
+allow_undefined_flag \
+no_undefined_flag \
+hardcode_libdir_flag_spec \
+hardcode_libdir_flag_spec_ld \
+hardcode_libdir_separator \
+fix_srcfile_path \
+exclude_expsyms \
+include_expsyms \
+file_list_spec \
+variables_saved_for_relink \
+libname_spec \
+library_names_spec \
+soname_spec \
+install_override_mode \
+finish_eval \
+old_striplib \
+striplib \
+compiler_lib_search_dirs \
+predep_objects \
+postdep_objects \
+predeps \
+postdeps \
+compiler_lib_search_path \
+LD_CXX \
+reload_flag_CXX \
+compiler_CXX \
+lt_prog_compiler_no_builtin_flag_CXX \
+lt_prog_compiler_wl_CXX \
+lt_prog_compiler_pic_CXX \
+lt_prog_compiler_static_CXX \
+lt_cv_prog_compiler_c_o_CXX \
+export_dynamic_flag_spec_CXX \
+whole_archive_flag_spec_CXX \
+compiler_needs_object_CXX \
+with_gnu_ld_CXX \
+allow_undefined_flag_CXX \
+no_undefined_flag_CXX \
+hardcode_libdir_flag_spec_CXX \
+hardcode_libdir_flag_spec_ld_CXX \
+hardcode_libdir_separator_CXX \
+fix_srcfile_path_CXX \
+exclude_expsyms_CXX \
+include_expsyms_CXX \
+file_list_spec_CXX \
+compiler_lib_search_dirs_CXX \
+predep_objects_CXX \
+postdep_objects_CXX \
+predeps_CXX \
+postdeps_CXX \
+compiler_lib_search_path_CXX; do
+ case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
+ *[\\\\\\\`\\"\\\$]*)
+ eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\""
+ ;;
+ *)
+ eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+ ;;
+ esac
+done
+
+# Double-quote double-evaled strings.
+for var in reload_cmds \
+old_postinstall_cmds \
+old_postuninstall_cmds \
+old_archive_cmds \
+extract_expsyms_cmds \
+old_archive_from_new_cmds \
+old_archive_from_expsyms_cmds \
+archive_cmds \
+archive_expsym_cmds \
+module_cmds \
+module_expsym_cmds \
+export_symbols_cmds \
+prelink_cmds \
+postinstall_cmds \
+postuninstall_cmds \
+finish_cmds \
+sys_lib_search_path_spec \
+sys_lib_dlsearch_path_spec \
+reload_cmds_CXX \
+old_archive_cmds_CXX \
+old_archive_from_new_cmds_CXX \
+old_archive_from_expsyms_cmds_CXX \
+archive_cmds_CXX \
+archive_expsym_cmds_CXX \
+module_cmds_CXX \
+module_expsym_cmds_CXX \
+export_symbols_cmds_CXX \
+prelink_cmds_CXX; do
+ case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
+ *[\\\\\\\`\\"\\\$]*)
+ eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\""
+ ;;
+ *)
+ eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+ ;;
+ esac
+done
+
+ac_aux_dir='$ac_aux_dir'
+xsi_shell='$xsi_shell'
+lt_shell_append='$lt_shell_append'
+
+# See if we are running on zsh, and set the options which allow our
+# commands through without removal of \ escapes INIT.
+if test -n "\${ZSH_VERSION+set}" ; then
+ setopt NO_GLOB_SUBST
+fi
+
+
+ PACKAGE='$PACKAGE'
+ VERSION='$VERSION'
+ TIMESTAMP='$TIMESTAMP'
+ RM='$RM'
+ ofile='$ofile'
+
+
+
+
+
+
+_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
+ "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
+ "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+ "default-1") CONFIG_COMMANDS="$CONFIG_COMMANDS default-1" ;;
+ "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;;
+
+ *) 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_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=
+ trap 'exit_status=$?
+ { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$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 -n "$tmp" && test -d "$tmp"
+} ||
+{
+ tmp=./conf$$-$RANDOM
+ (umask 077 && mkdir "$tmp")
+} || as_fn_error "cannot create a temporary directory in ." "$LINENO" 5
+
+# 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
+
+
+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 {' >"$tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+ 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 >>"\$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 >>"\$tmp/subs1.awk" <<_ACAWK &&
+ for (key in S) S_is_set[key] = 1
+ FS = ""
+
+}
+{
+ 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
+ }
+
+ print line
+}
+
+_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 < "$tmp/subs1.awk" > "$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 $(srcdir),
+# ${srcdir} and @srcdir@ 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[ ]*=/{
+s/:*\$(srcdir):*/:/
+s/:*\${srcdir}:*/:/
+s/:*@srcdir@:*/:/
+s/^\([^=]*=[ ]*\):*/\1/
+s/:*$//
+s/^[^=]*=[ ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+
+eval set X " :F $CONFIG_FILES :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="$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 "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 >"$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
+ #
+
+ case $INSTALL in
+ [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+ *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+ esac
+ ac_MKDIR_P=$MKDIR_P
+ case $MKDIR_P in
+ [\\/$]* | ?:[\\/]* ) ;;
+ */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;;
+ esac
+_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
+s&@INSTALL@&$ac_INSTALL&;t t
+s&@MKDIR_P@&$ac_MKDIR_P&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$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' "$tmp/out"`; test -n "$ac_out"; } &&
+ { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$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 "$tmp/stdin"
+ case $ac_file in
+ -) cat "$tmp/out" && rm -f "$tmp/out";;
+ *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";;
+ esac \
+ || as_fn_error "could not create $ac_file" "$LINENO" 5
+ ;;
+
+
+ :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
+ "depfiles":C) test x"$AMDEP_TRUE" != x"" || {
+ # Autoconf 2.62 quotes --file arguments for eval, but not when files
+ # are listed without --file. Let's play safe and only enable the eval
+ # if we detect the quoting.
+ case $CONFIG_FILES in
+ *\'*) eval set x "$CONFIG_FILES" ;;
+ *) set x $CONFIG_FILES ;;
+ esac
+ shift
+ for mf
+ do
+ # Strip MF so we end up with the name of the file.
+ mf=`echo "$mf" | sed -e 's/:.*$//'`
+ # Check whether this is an Automake generated Makefile or not.
+ # We used to match only the files named `Makefile.in', but
+ # some people rename them; so instead we look at the file content.
+ # Grep'ing the first line is not enough: some people post-process
+ # each Makefile.in and add a new line on top of each file to say so.
+ # Grep'ing the whole file is not good either: AIX grep has a line
+ # limit of 2048, but all sed's we know have understand at least 4000.
+ if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
+ dirpart=`$as_dirname -- "$mf" ||
+$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$mf" : 'X\(//\)[^/]' \| \
+ X"$mf" : 'X\(//\)$' \| \
+ X"$mf" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$mf" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ else
+ continue
+ fi
+ # Extract the definition of DEPDIR, am__include, and am__quote
+ # from the Makefile without running `make'.
+ DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+ test -z "$DEPDIR" && continue
+ am__include=`sed -n 's/^am__include = //p' < "$mf"`
+ test -z "am__include" && continue
+ am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+ # When using ansi2knr, U may be empty or an underscore; expand it
+ U=`sed -n 's/^U = //p' < "$mf"`
+ # Find all dependency output files, they are included files with
+ # $(DEPDIR) in their names. We invoke sed twice because it is the
+ # simplest approach to changing $(DEPDIR) to its actual value in the
+ # expansion.
+ for file in `sed -n "
+ s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
+ # Make sure the directory exists.
+ test -f "$dirpart/$file" && continue
+ fdir=`$as_dirname -- "$file" ||
+$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$file" : 'X\(//\)[^/]' \| \
+ X"$file" : 'X\(//\)$' \| \
+ X"$file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ as_dir=$dirpart/$fdir; as_fn_mkdir_p
+ # echo "creating $dirpart/$file"
+ echo '# dummy' > "$dirpart/$file"
+ done
+ done
+}
+ ;;
+ "default-1":C)
+# Only add multilib support code if we just rebuilt the top-level
+# Makefile.
+case " $CONFIG_FILES " in
+ *" Makefile "*)
+ ac_file=Makefile . ${multi_basedir}/config-ml.in
+ ;;
+esac ;;
+ "libtool":C)
+
+ # See if we are running on zsh, and set the options which allow our
+ # commands through without removal of \ escapes.
+ if test -n "${ZSH_VERSION+set}" ; then
+ setopt NO_GLOB_SUBST
+ fi
+
+ cfgfile="${ofile}T"
+ trap "$RM \"$cfgfile\"; exit 1" 1 2 15
+ $RM "$cfgfile"
+
+ cat <<_LT_EOF >> "$cfgfile"
+#! $SHELL
+
+# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
+# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+#
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
+# 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+# Written by Gordon Matzigkeit, 1996
+#
+# This file is part of GNU Libtool.
+#
+# GNU Libtool is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# As a special exception to the GNU General Public License,
+# if you distribute this file as part of a program or library that
+# is built using GNU Libtool, you may include this file under the
+# same distribution terms that you use for the rest of that program.
+#
+# GNU Libtool is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Libtool; see the file COPYING. If not, a copy
+# can be downloaded from http://www.gnu.org/licenses/gpl.html, or
+# obtained by writing to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+
+# The names of the tagged configurations supported by this script.
+available_tags="CXX "
+
+# ### BEGIN LIBTOOL CONFIG
+
+# Which release of libtool.m4 was used?
+macro_version=$macro_version
+macro_revision=$macro_revision
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# What type of objects to build.
+pic_mode=$pic_mode
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# An echo program that protects backslashes.
+ECHO=$lt_ECHO
+
+# The host system.
+host_alias=$host_alias
+host=$host
+host_os=$host_os
+
+# The build system.
+build_alias=$build_alias
+build=$build
+build_os=$build_os
+
+# A sed program that does not truncate output.
+SED=$lt_SED
+
+# Sed that helps us avoid accidentally triggering echo(1) options like -n.
+Xsed="\$SED -e 1s/^X//"
+
+# A grep program that handles long lines.
+GREP=$lt_GREP
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# A literal string matcher.
+FGREP=$lt_FGREP
+
+# A BSD- or MS-compatible name lister.
+NM=$lt_NM
+
+# Whether we need soft or hard links.
+LN_S=$lt_LN_S
+
+# What is the maximum length of a command?
+max_cmd_len=$max_cmd_len
+
+# Object file suffix (normally "o").
+objext=$ac_objext
+
+# Executable file suffix (normally "").
+exeext=$exeext
+
+# whether the shell understands "unset".
+lt_unset=$lt_unset
+
+# turn spaces into newlines.
+SP2NL=$lt_lt_SP2NL
+
+# turn newlines into spaces.
+NL2SP=$lt_lt_NL2SP
+
+# An object symbol dumper.
+OBJDUMP=$lt_OBJDUMP
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == "file_magic".
+file_magic_cmd=$lt_file_magic_cmd
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# A symbol stripping program.
+STRIP=$lt_STRIP
+
+# Commands used to install an old-style archive.
+RANLIB=$lt_RANLIB
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Whether to use a lock for old archive extraction.
+lock_old_archive_extraction=$lock_old_archive_extraction
+
+# A C compiler.
+LTCC=$lt_CC
+
+# LTCC compiler flags.
+LTCFLAGS=$lt_CFLAGS
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration.
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair.
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# Transform the output of nm in a C name address pair when lib prefix is needed.
+global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# Used to examine libraries when file_magic_cmd begins with "file".
+MAGIC_CMD=$MAGIC_CMD
+
+# Must we lock files when doing compilation?
+need_locks=$lt_need_locks
+
+# Tool to manipulate archived DWARF debug symbol files on Mac OS X.
+DSYMUTIL=$lt_DSYMUTIL
+
+# Tool to change global to local symbols on Mac OS X.
+NMEDIT=$lt_NMEDIT
+
+# Tool to manipulate fat objects and archives on Mac OS X.
+LIPO=$lt_LIPO
+
+# ldd/readelf like tool for Mach-O binaries on Mac OS X.
+OTOOL=$lt_OTOOL
+
+# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4.
+OTOOL64=$lt_OTOOL64
+
+# Old archive suffix (normally "a").
+libext=$libext
+
+# Shared library suffix (normally ".so").
+shrext_cmds=$lt_shrext_cmds
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at link time.
+variables_saved_for_relink=$lt_variables_saved_for_relink
+
+# Do we need the "lib" prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Library versioning type.
+version_type=$version_type
+
+# Shared library runtime path variable.
+runpath_var=$runpath_var
+
+# Shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names. First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Permission mode override for installation of shared libraries.
+install_override_mode=$lt_install_override_mode
+
+# Command to use after installation of a shared archive.
+postinstall_cmds=$lt_postinstall_cmds
+
+# Command to use after uninstallation of a shared archive.
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# As "finish_cmds", except a single script fragment to be evaled but
+# not shown.
+finish_eval=$lt_finish_eval
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Compile-time system search path for libraries.
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Run-time system search path for libraries.
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+
+# The linker used to build libraries.
+LD=$lt_LD
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# Commands used to build an old-style archive.
+old_archive_cmds=$lt_old_archive_cmds
+
+# A language specific compiler.
+CC=$lt_compiler
+
+# Is the compiler the GNU compiler?
+with_gcc=$GCC
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc
+
+# Whether or not to disallow shared libs when runtime libs are static.
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec
+
+# Whether the compiler copes with passing no objects directly.
+compiler_needs_object=$lt_compiler_needs_object
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds
+
+# Commands used to build a shared archive.
+archive_cmds=$lt_archive_cmds
+archive_expsym_cmds=$lt_archive_expsym_cmds
+
+# Commands used to build a loadable module if different from building
+# a shared archive.
+module_cmds=$lt_module_cmds
+module_expsym_cmds=$lt_module_expsym_cmds
+
+# Whether we are building with GNU ld or not.
+with_gnu_ld=$lt_with_gnu_ld
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag
+
+# Flag that enforces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec
+
+# If ld is used when linking, flag to hardcode \$libdir into a binary
+# during linking. This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld
+
+# Whether we need a single "-rpath" flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator
+
+# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes
+# DIR into the resulting binary.
+hardcode_direct=$hardcode_direct
+
+# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes
+# DIR into the resulting binary and the resulting library dependency is
+# "absolute",i.e impossible to change by setting \${shlibpath_var} if the
+# library is relocated.
+hardcode_direct_absolute=$hardcode_direct_absolute
+
+# Set to "yes" if using the -LDIR flag during linking hardcodes DIR
+# into the resulting binary.
+hardcode_minus_L=$hardcode_minus_L
+
+# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
+# into the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var
+
+# Set to "yes" if building a shared library automatically hardcodes DIR
+# into the library and all subsequent libraries and executables linked
+# against it.
+hardcode_automatic=$hardcode_automatic
+
+# Set to yes if linker adds runtime paths of dependent libraries
+# to runtime path list.
+inherit_rpath=$inherit_rpath
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path=$lt_fix_srcfile_path
+
+# Set to "yes" if exported symbols are required.
+always_export_symbols=$always_export_symbols
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms
+
+# Commands necessary for linking programs (against libraries) with templates.
+prelink_cmds=$lt_prelink_cmds
+
+# Specify filename containing input files.
+file_list_spec=$lt_file_list_spec
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action
+
+# The directories searched by this compiler when creating a shared library.
+compiler_lib_search_dirs=$lt_compiler_lib_search_dirs
+
+# Dependencies to place before and after the objects being linked to
+# create a shared library.
+predep_objects=$lt_predep_objects
+postdep_objects=$lt_postdep_objects
+predeps=$lt_predeps
+postdeps=$lt_postdeps
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path=$lt_compiler_lib_search_path
+
+# ### END LIBTOOL CONFIG
+
+_LT_EOF
+
+ case $host_os in
+ aix3*)
+ cat <<\_LT_EOF >> "$cfgfile"
+# 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
+_LT_EOF
+ ;;
+ esac
+
+
+ltmain="$ac_aux_dir/ltmain.sh"
+
+
+ # We use sed instead of cat because bash on DJGPP gets confused if
+ # if finds mixed CR/LF and LF-only lines. Since sed operates in
+ # text mode, it properly converts lines to CR/LF. This bash problem
+ # is reportedly fixed, but why not run on old versions too?
+ sed '/^# Generated shell functions inserted here/q' "$ltmain" >> "$cfgfile" \
+ || (rm -f "$cfgfile"; exit 1)
+
+ case $xsi_shell in
+ yes)
+ cat << \_LT_EOF >> "$cfgfile"
+
+# func_dirname file append nondir_replacement
+# Compute the dirname of FILE. If nonempty, add APPEND to the result,
+# otherwise set result to NONDIR_REPLACEMENT.
+func_dirname ()
+{
+ case ${1} in
+ */*) func_dirname_result="${1%/*}${2}" ;;
+ * ) func_dirname_result="${3}" ;;
+ esac
+}
+
+# func_basename file
+func_basename ()
+{
+ func_basename_result="${1##*/}"
+}
+
+# func_dirname_and_basename file append nondir_replacement
+# perform func_basename and func_dirname in a single function
+# call:
+# dirname: Compute the dirname of FILE. If nonempty,
+# add APPEND to the result, otherwise set result
+# to NONDIR_REPLACEMENT.
+# value returned in "$func_dirname_result"
+# basename: Compute filename of FILE.
+# value retuned in "$func_basename_result"
+# Implementation must be kept synchronized with func_dirname
+# and func_basename. For efficiency, we do not delegate to
+# those functions but instead duplicate the functionality here.
+func_dirname_and_basename ()
+{
+ case ${1} in
+ */*) func_dirname_result="${1%/*}${2}" ;;
+ * ) func_dirname_result="${3}" ;;
+ esac
+ func_basename_result="${1##*/}"
+}
+
+# func_stripname prefix suffix name
+# strip PREFIX and SUFFIX off of NAME.
+# PREFIX and SUFFIX must not contain globbing or regex special
+# characters, hashes, percent signs, but SUFFIX may contain a leading
+# dot (in which case that matches only a dot).
+func_stripname ()
+{
+ # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are
+ # positional parameters, so assign one to ordinary parameter first.
+ func_stripname_result=${3}
+ func_stripname_result=${func_stripname_result#"${1}"}
+ func_stripname_result=${func_stripname_result%"${2}"}
+}
+
+# func_opt_split
+func_opt_split ()
+{
+ func_opt_split_opt=${1%%=*}
+ func_opt_split_arg=${1#*=}
+}
+
+# func_lo2o object
+func_lo2o ()
+{
+ case ${1} in
+ *.lo) func_lo2o_result=${1%.lo}.${objext} ;;
+ *) func_lo2o_result=${1} ;;
+ esac
+}
+
+# func_xform libobj-or-source
+func_xform ()
+{
+ func_xform_result=${1%.*}.lo
+}
+
+# func_arith arithmetic-term...
+func_arith ()
+{
+ func_arith_result=$(( $* ))
+}
+
+# func_len string
+# STRING may not start with a hyphen.
+func_len ()
+{
+ func_len_result=${#1}
+}
+
+_LT_EOF
+ ;;
+ *) # Bourne compatible functions.
+ cat << \_LT_EOF >> "$cfgfile"
+
+# func_dirname file append nondir_replacement
+# Compute the dirname of FILE. If nonempty, add APPEND to the result,
+# otherwise set result to NONDIR_REPLACEMENT.
+func_dirname ()
+{
+ # Extract subdirectory from the argument.
+ func_dirname_result=`$ECHO "${1}" | $SED "$dirname"`
+ if test "X$func_dirname_result" = "X${1}"; then
+ func_dirname_result="${3}"
+ else
+ func_dirname_result="$func_dirname_result${2}"
+ fi
+}
+
+# func_basename file
+func_basename ()
+{
+ func_basename_result=`$ECHO "${1}" | $SED "$basename"`
+}
+
+
+# func_stripname prefix suffix name
+# strip PREFIX and SUFFIX off of NAME.
+# PREFIX and SUFFIX must not contain globbing or regex special
+# characters, hashes, percent signs, but SUFFIX may contain a leading
+# dot (in which case that matches only a dot).
+# func_strip_suffix prefix name
+func_stripname ()
+{
+ case ${2} in
+ .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;;
+ *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;;
+ esac
+}
+
+# sed scripts:
+my_sed_long_opt='1s/^\(-[^=]*\)=.*/\1/;q'
+my_sed_long_arg='1s/^-[^=]*=//'
+
+# func_opt_split
+func_opt_split ()
+{
+ func_opt_split_opt=`$ECHO "${1}" | $SED "$my_sed_long_opt"`
+ func_opt_split_arg=`$ECHO "${1}" | $SED "$my_sed_long_arg"`
+}
+
+# func_lo2o object
+func_lo2o ()
+{
+ func_lo2o_result=`$ECHO "${1}" | $SED "$lo2o"`
+}
+
+# func_xform libobj-or-source
+func_xform ()
+{
+ func_xform_result=`$ECHO "${1}" | $SED 's/\.[^.]*$/.lo/'`
+}
+
+# func_arith arithmetic-term...
+func_arith ()
+{
+ func_arith_result=`expr "$@"`
+}
+
+# func_len string
+# STRING may not start with a hyphen.
+func_len ()
+{
+ func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len`
+}
+
+_LT_EOF
+esac
+
+case $lt_shell_append in
+ yes)
+ cat << \_LT_EOF >> "$cfgfile"
+
+# func_append var value
+# Append VALUE to the end of shell variable VAR.
+func_append ()
+{
+ eval "$1+=\$2"
+}
+_LT_EOF
+ ;;
+ *)
+ cat << \_LT_EOF >> "$cfgfile"
+
+# func_append var value
+# Append VALUE to the end of shell variable VAR.
+func_append ()
+{
+ eval "$1=\$$1\$2"
+}
+
+_LT_EOF
+ ;;
+ esac
+
+
+ sed -n '/^# Generated shell functions inserted here/,$p' "$ltmain" >> "$cfgfile" \
+ || (rm -f "$cfgfile"; exit 1)
+
+ mv -f "$cfgfile" "$ofile" ||
+ (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
+ chmod +x "$ofile"
+
+
+ cat <<_LT_EOF >> "$ofile"
+
+# ### BEGIN LIBTOOL TAG CONFIG: CXX
+
+# The linker used to build libraries.
+LD=$lt_LD_CXX
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag_CXX
+reload_cmds=$lt_reload_cmds_CXX
+
+# Commands used to build an old-style archive.
+old_archive_cmds=$lt_old_archive_cmds_CXX
+
+# A language specific compiler.
+CC=$lt_compiler_CXX
+
+# Is the compiler the GNU compiler?
+with_gcc=$GCC_CXX
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl_CXX
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic_CXX
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static_CXX
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o_CXX
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc_CXX
+
+# Whether or not to disallow shared libs when runtime libs are static.
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_CXX
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_CXX
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec_CXX
+
+# Whether the compiler copes with passing no objects directly.
+compiler_needs_object=$lt_compiler_needs_object_CXX
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_CXX
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_CXX
+
+# Commands used to build a shared archive.
+archive_cmds=$lt_archive_cmds_CXX
+archive_expsym_cmds=$lt_archive_expsym_cmds_CXX
+
+# Commands used to build a loadable module if different from building
+# a shared archive.
+module_cmds=$lt_module_cmds_CXX
+module_expsym_cmds=$lt_module_expsym_cmds_CXX
+
+# Whether we are building with GNU ld or not.
+with_gnu_ld=$lt_with_gnu_ld_CXX
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag_CXX
+
+# Flag that enforces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag_CXX
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_CXX
+
+# If ld is used when linking, flag to hardcode \$libdir into a binary
+# during linking. This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_CXX
+
+# Whether we need a single "-rpath" flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator_CXX
+
+# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes
+# DIR into the resulting binary.
+hardcode_direct=$hardcode_direct_CXX
+
+# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes
+# DIR into the resulting binary and the resulting library dependency is
+# "absolute",i.e impossible to change by setting \${shlibpath_var} if the
+# library is relocated.
+hardcode_direct_absolute=$hardcode_direct_absolute_CXX
+
+# Set to "yes" if using the -LDIR flag during linking hardcodes DIR
+# into the resulting binary.
+hardcode_minus_L=$hardcode_minus_L_CXX
+
+# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
+# into the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var_CXX
+
+# Set to "yes" if building a shared library automatically hardcodes DIR
+# into the library and all subsequent libraries and executables linked
+# against it.
+hardcode_automatic=$hardcode_automatic_CXX
+
+# Set to yes if linker adds runtime paths of dependent libraries
+# to runtime path list.
+inherit_rpath=$inherit_rpath_CXX
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs_CXX
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path=$lt_fix_srcfile_path_CXX
+
+# Set to "yes" if exported symbols are required.
+always_export_symbols=$always_export_symbols_CXX
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds_CXX
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms_CXX
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms_CXX
+
+# Commands necessary for linking programs (against libraries) with templates.
+prelink_cmds=$lt_prelink_cmds_CXX
+
+# Specify filename containing input files.
+file_list_spec=$lt_file_list_spec_CXX
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action_CXX
+
+# The directories searched by this compiler when creating a shared library.
+compiler_lib_search_dirs=$lt_compiler_lib_search_dirs_CXX
+
+# Dependencies to place before and after the objects being linked to
+# create a shared library.
+predep_objects=$lt_predep_objects_CXX
+postdep_objects=$lt_postdep_objects_CXX
+predeps=$lt_predeps_CXX
+postdeps=$lt_postdeps_CXX
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path=$lt_compiler_lib_search_path_CXX
+
+# ### END LIBTOOL TAG CONFIG: CXX
+_LT_EOF
+
+ ;;
+
+ 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 $?
+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/libcilkrts/configure.ac b/libcilkrts/configure.ac
new file mode 100644
index 00000000000..4582d80c452
--- /dev/null
+++ b/libcilkrts/configure.ac
@@ -0,0 +1,154 @@
+# @copyright
+# Copyright (C) 2011-2013, Intel Corporation
+# All rights reserved.
+#
+# @copyright
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# @copyright
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+# WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+AC_INIT([Cilk Runtime Library], [2.0], [cilk@intel.com])
+AC_PREREQ([2.64])
+
+# Needed to define ${target}. Needs to be very early to avoid annoying
+# warning about calling AC_ARG_PROGRAM before AC_CANONICAL_SYSTEM
+AC_CANONICAL_SYSTEM
+target_alias=${target_alias-$host_alias}
+AC_SUBST(target_alias)
+GCC_LIBSTDCXX_RAW_CXX_FLAGS
+AM_INIT_AUTOMAKE(foreign no-dist)
+
+AM_MAINTAINER_MODE
+
+# Build a DLL on Windows
+# AC_LIBTOOL_WIN32_DLL
+AC_PROG_CXX
+AC_PROG_CC
+# AC_PROG_LIBTOOL
+# AC_CONFIG_MACRO_DIR([..])
+AC_CONFIG_FILES([Makefile])
+AM_ENABLE_MULTILIB(, ..)
+AC_FUNC_ALLOCA
+
+# Get target configury.
+. ${srcdir}/configure.tgt
+if test -n "$UNSUPPORTED"; then
+ AC_MSG_ERROR([Configuration ${target} is unsupported.])
+fi
+
+if test "${multilib}" = "yes"; then
+ multilib_arg="--enable-multilib"
+else
+ multilib_arg=
+fi
+
+AC_MSG_CHECKING([for --enable-version-specific-runtime-libs])
+AC_ARG_ENABLE([version-specific-runtime-libs],
+ AC_HELP_STRING([--enable-version-specific-runtime-libs],
+ [Specify that runtime libraries should be installed in a compi
+ler-specific directory]),
+ [case "$enableval" in
+ yes) enable_version_specific_runtime_libs=yes ;;
+ no) enable_version_specific_runtime_libs=no ;;
+ *) AC_MSG_ERROR([Unknown argument to enable/disable version-specific libs
+]);;
+ esac],
+ [enable_version_specific_runtime_libs=no])
+AC_MSG_RESULT($enable_version_specific_runtime_libs)
+
+
+# Calculate toolexeclibdir
+# Also toolexecdir, though it's only used in toolexeclibdir
+case ${enable_version_specific_runtime_libs} in
+ yes)
+ # Need the gcc compiler version to know where to install libraries
+ # and header files if --enable-version-specific-runtime-libs option
+ # is selected.
+ toolexecdir='$(libdir)/gcc/$(target_alias)'
+ toolexeclibdir='$(toolexecdir)/$(gcc_version)$(MULTISUBDIR)'
+ ;;
+ no)
+ if test -n "$with_cross_host" &&
+ test x"$with_cross_host" != x"no"; then
+ # Install a library built with a cross compiler in tooldir, not libdir.
+ toolexecdir='$(exec_prefix)/$(target_alias)'
+ toolexeclibdir='$(toolexecdir)/lib'
+ else
+ toolexecdir='$(libdir)/gcc-lib/$(target_alias)'
+ toolexeclibdir='$(libdir)'
+ fi
+ multi_os_directory=`$CC -print-multi-os-directory`
+ case $multi_os_directory in
+ .) ;; # Avoid trailing /.
+ *) toolexeclibdir=$toolexeclibdir/$multi_os_directory ;;
+ esac
+ ;;
+esac
+
+# Set config_dir based on the target. config_dir specifies where to get
+# target-specific files. The generic implementation is incomplete, but
+# contains information on what's needed
+case "${target}" in
+
+ x86_64-*-*)
+ config_dir="x86"
+ ;;
+
+ i?86-*-*)
+ config_dir="x86"
+ ;;
+
+ *)
+ config_dir="generic"
+ ;;
+
+esac
+AC_SUBST(config_dir)
+
+# We have linker scripts for appropriate operating systems
+linux_linker_script=no
+case "${host}" in
+ *-*-linux*)
+ linux_linker_script=yes
+ ;;
+esac
+AM_CONDITIONAL(LINUX_LINKER_SCRIPT, test "$linux_linker_script" = "yes")
+
+mac_linker_script=no
+case "${host}" in
+ *-*-apple*)
+ mac_linker_script=yes
+ ;;
+esac
+AM_CONDITIONAL(MAC_LINKER_SCRIPT, test "$mac_linker_script" = "yes")
+
+AM_PROG_LIBTOOL
+AC_SUBST(toolexecdir)
+AC_SUBST(toolexeclibdir)
+
+# Must be last
+AC_OUTPUT
diff --git a/libcilkrts/configure.tgt b/libcilkrts/configure.tgt
new file mode 100644
index 00000000000..f7663521cda
--- /dev/null
+++ b/libcilkrts/configure.tgt
@@ -0,0 +1,61 @@
+# @copyright
+# Copyright (C) 2011-2013, Intel Corporation
+# All rights reserved.
+#
+# @copyright
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# @copyright
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+# WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+# Disable Cilk Runtime library for non x86 architecture...for now.
+case "${target}" in
+ x86_64-*-*)
+ ;;
+ i?86-*-*)
+ ;;
+ *-*-*)
+ UNSUPPORTED=1
+ ;;
+esac
+
+# Disable libcilkrts on non POSIX hosted systems.
+if test x$enable_libcilkrts = x ; then
+ # Enable libcilkrts by default on hosted POSIX systems.
+ case "${target}" in
+ *-*-linux* | *-*-gnu* | *-*-k*bsd*-gnu | *-*-kopensolaris*-gnu)
+ ;;
+ *-*-netbsd* | *-*-freebsd* | *-*-openbsd* | *-*-dragonfly*)
+ ;;
+ *-*-solaris2* | *-*-hpux11*)
+ ;;
+ *-*-darwin* | *-*-aix*)
+ ;;
+ *)
+ UNSUPPORTED=1
+ ;;
+ esac
+fi
diff --git a/libcilkrts/include/cilk/cilk.h b/libcilkrts/include/cilk/cilk.h
new file mode 100644
index 00000000000..2d0de0d293e
--- /dev/null
+++ b/libcilkrts/include/cilk/cilk.h
@@ -0,0 +1,71 @@
+/* cilk.h -*-C++-*-
+ *
+ * @copyright
+ * Copyright (C) 2010-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file cilk.h
+ *
+ * @brief Provides convenient aliases for the Cilk language keywords.
+ *
+ * @details
+ * Since Cilk is a nonstandard extension to both C and C++, the Cilk
+ * language keywords all begin with “`_Cilk_`â€, which guarantees that they
+ * will not conflict with user-defined identifiers in properly written
+ * programs, so that “standard†C and C++ programs can safely be
+ * compiled a Cilk-enabled C or C++ compiler.
+ *
+ * However, this means that the keywords _look_ like something grafted on to
+ * the base language. Therefore, you can include this header:
+ *
+ * #include "cilk/cilk.h"
+ *
+ * and then write the Cilk keywords with a “`cilk_`†prefix instead of
+ * “`_Cilk_`â€.
+ *
+ * @ingroup language
+ */
+
+
+/** @defgroup language Language Keywords
+ * Definitions having to do with the Cilk language.
+ * @{
+ */
+
+#ifndef cilk_spawn
+# define cilk_spawn _Cilk_spawn ///< Spawn a task that can execute in parallel.
+# define cilk_sync _Cilk_sync ///< Wait for spawned tasks to complete.
+# define cilk_for _Cilk_for ///< Execute iterations of a for loop in parallel.
+#endif
+
+/// @}
diff --git a/libcilkrts/include/cilk/cilk_api.h b/libcilkrts/include/cilk/cilk_api.h
new file mode 100644
index 00000000000..a21687b7b32
--- /dev/null
+++ b/libcilkrts/include/cilk/cilk_api.h
@@ -0,0 +1,424 @@
+/* cilk_api.h
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file cilk_api.h
+ *
+ * @brief Defines the documented API exposed by the Cilk Plus for use
+ * by applications.
+ *
+ * @ingroup api
+ */
+
+#ifndef INCLUDED_CILK_API_H
+#define INCLUDED_CILK_API_H
+
+/** @defgroup api Runtime API
+ * API to allow user programs to interact with the Cilk runtime.
+ * @{
+ */
+
+#ifndef CILK_STUB /* Real (non-stub) definitions */
+
+#if ! defined(__cilk) && ! defined(USE_CILK_API)
+# ifdef _WIN32
+# error Cilk API is being used with non-Cilk compiler (or Cilk is disabled)
+# else
+# warning Cilk API is being used with non-Cilk compiler (or Cilk is disabled)
+# endif
+#endif
+
+#include <cilk/common.h>
+
+#ifdef __cplusplus
+# include <cstddef> /* Defines size_t */
+#else
+# include <stddef.h> /* Defines size_t */
+#endif
+
+#ifdef _WIN32
+# ifndef IN_CILK_RUNTIME
+/* Ensure the library is brought if any of these functions are being called. */
+# pragma comment(lib, "cilkrts")
+# endif
+
+# ifndef __cplusplus
+# include <wchar.h>
+# endif
+#endif /* _WIN32 */
+
+__CILKRTS_BEGIN_EXTERN_C
+
+/** Return values from __cilkrts_set_param() and __cilkrts_set_param_w()
+ */
+enum __cilkrts_set_param_status {
+ __CILKRTS_SET_PARAM_SUCCESS = 0, /**< Success - parameter set */
+ __CILKRTS_SET_PARAM_UNIMP = 1, /**< Unimplemented parameter */
+ __CILKRTS_SET_PARAM_XRANGE = 2, /**< Parameter value out of range */
+ __CILKRTS_SET_PARAM_INVALID = 3, /**< Invalid parameter value */
+ __CILKRTS_SET_PARAM_LATE = 4 /**< Too late to change parameter value */
+};
+
+/** Set user controllable runtime parameters
+ *
+ * Call this function to set runtime parameters that control the behavior
+ * of the Cilk scheduler.
+ *
+ * @param param A string specifying the parameter to be set. One of:
+ * - `"nworkers"`
+ * - `"force reduce"`
+ * @param value A string specifying the parameter value.
+ * @returns A value from the @ref __cilkrts_set_param_status
+ * enumeration indicating the result of the operation.
+ *
+ * @par The "nworkers" parameter
+ *
+ * This parameter specifies the number of worker threads to be created by the
+ * Cilk runtime. @a Value must be a string of digits to be parsed by
+ * `strtol()`.
+ *
+ * The number of worker threads is:
+ * 1. the value set with `__cilkrts_set_param("nworkers")`, if it is
+ * positive; otherwise,
+ * 2. the value of the CILK_NWORKERS environment variable, if it is
+ * defined; otherwise
+ * 3. the number of cores available, as reported by the operating system.
+ *
+ * @note
+ * Technically, Cilk distinguishes between the _user thread_ (the thread that
+ * the user code was executing on when the Cilk runtime started), and
+ * _worker threads_ (new threads created by the Cilk runtime to support
+ * Cilk parallelism). `nworkers` actually includes both the user thread and
+ * the worker threads; that is, it is one greater than the number of true
+ * “worker threadsâ€.
+ *
+ * @note
+ * Setting `nworkers = 1` produces serial behavior. Cilk spawns and syncs will
+ * be executed, but with only one worker, continuations will never be stolen,
+ * so all code will execute in serial.
+ *
+ * @warning
+ * The number of worker threads can only be set *before* the runtime has
+ * started. Attempting to set it when the runtime is running will have no
+ * effect, and will return an error code. You can call __cilkrts_end_cilk()
+ * to shut down the runtime to change the number of workers.
+ *
+ * @warning
+ * The default Cilk scheduler behavior is usually pretty good. The ability
+ * to override `nworkers` can be useful for experimentation, but it won’t
+ * usually be necessary for getting good performance.
+ *
+ * @par The "force reduce" parameter
+ *
+ * This parameter controls whether the runtime should allocate a new view
+ * for a reducer for every parallel strand that it is accessed on. (See
+ * @ref pagereducers.) @a Value must be `"1"` or `"true"` to enable the
+ * “force reduce†behavior, or `"0"` or `"false"` to disable it.
+ *
+ * “Force reduce†behavior will also be enabled if
+ * `__cilkrts_set_param("force reduce")` is not called, but the
+ * `CILK_FORCE_REDUCE` environment variable is defined.
+ *
+ * @warning
+ * When this option is enabled, `nworkers` should be set to `1`. Using “force
+ * reduce†with more than one worker may result in runtime errors.
+ *
+ * @warning
+ * Enabling this option can significantly reduce performance. It should
+ * _only_ be used as a debugging tool.
+ */
+CILK_API(int) __cilkrts_set_param(const char *param, const char *value);
+
+#ifdef _WIN32
+/**
+ * Set user controllable parameters using wide strings
+ *
+ * @note This variant of __cilkrts_set_param() is only available
+ * on Windows.
+ *
+ * @copydetails __cilkrts_set_param
+ */
+CILK_API(int) __cilkrts_set_param_w(const wchar_t *param, const wchar_t *value);
+#endif
+
+/** Shut down and deallocate all Cilk state. The runtime will abort the
+ * application if Cilk is still in use by this thread. Otherwise the runtime
+ * will wait for all other threads using Cilk to exit.
+ */
+CILK_API(void) __cilkrts_end_cilk(void);
+
+/** Initialize the Cilk data structures and start the runtime.
+ */
+CILK_API(void) __cilkrts_init(void);
+
+/** Return the runtime `nworkers` parameter. (See the discussion of `nworkers`
+ * in the documentation for __cilkrts_set_param().)
+ */
+CILK_API(int) __cilkrts_get_nworkers(void);
+
+/** Return the number of thread data structures.
+ *
+ * This function returns the number of data structures that has been allocated
+ * allocated by the runtime to hold information about user and worker threads.
+ *
+ * If you don’t already know what this is good for, then you probably don’t
+ * need it.
+ */
+CILK_API(int) __cilkrts_get_total_workers(void);
+
+/** What thread is the function running on?
+ *
+ * Return a small integer identifying the current thread. Each worker thread
+ * started by the Cilk runtime library has a unique worker number in the range
+ * `1 .. nworkers - 1`.
+ *
+ * All _user_ threads (threads started by the user, or by other libraries) are
+ * identified as worker number 0. Therefore, the worker number is not unique
+ * across multiple user threads.
+ */
+CILK_API(int) __cilkrts_get_worker_number(void);
+
+/** Test whether “force reduce†behavior is enabled.
+ *
+ * @return Non-zero if force-reduce mode is on, zero if it is off.
+ */
+CILK_API(int) __cilkrts_get_force_reduce(void);
+
+/** Interact with tools
+ */
+CILK_API(void)
+ __cilkrts_metacall(unsigned int tool, unsigned int code, void *data);
+
+#ifdef _WIN32
+/// Windows exception description record.
+typedef struct _EXCEPTION_RECORD _EXCEPTION_RECORD;
+
+/** Function signature for Windows exception notification callbacks.
+ */
+typedef void (*__cilkrts_pfn_seh_callback)(const _EXCEPTION_RECORD *exception);
+
+/** Specify a function to call when a non-C++ exception is caught.
+ *
+ * Cilk Plus parallelism plays nicely with C++ exception handling, but the
+ * Cilk Plus runtime has no way to unwind the stack across a strand boundary
+ * for Microsoft SEH (“Structured Exception Handlingâ€) exceptions. Therefore,
+ * when the runtime catches such an exception, it must abort the application.
+ *
+ * If an SEH callback has been set, the runtime will call it before aborting.
+ *
+ * @param pfn A pointer to a callback function to be called before the
+ * runtime aborts the program because of an SEH exception.
+ */
+CILK_API(int) __cilkrts_set_seh_callback(__cilkrts_pfn_seh_callback pfn);
+#endif /* _WIN32 */
+
+#if __CILKRTS_ABI_VERSION >= 1
+/* Pedigree API is available only for compilers that use ABI version >= 1. */
+
+
+/** @name Pedigrees
+ */
+//@{
+
+// @cond internal
+
+/** Support for __cilkrts_get_pedigree.
+ */
+CILK_API(__cilkrts_pedigree)
+__cilkrts_get_pedigree_internal(__cilkrts_worker *w);
+
+/** Support for __cilkrts_bump_worker_rank.
+ */
+CILK_API(int)
+__cilkrts_bump_worker_rank_internal(__cilkrts_worker* w);
+
+/// @endcond
+
+
+/** Get the current pedigree, in a linked list representation.
+ *
+ * This routine returns a copy of the last node in the pedigree list.
+ * For example, if the current pedigree (in order) is <1, 2, 3, 4>,
+ * then this method returns a node with rank == 4, and whose parent
+ * field points to the node with rank of 3. In summary, following the
+ * nodes in the chain visits the terms of the pedigree in reverse.
+ *
+ * The returned node is guaranteed to be valid only until the caller
+ * of this routine has returned.
+ */
+__CILKRTS_INLINE
+__cilkrts_pedigree __cilkrts_get_pedigree(void)
+{
+ return __cilkrts_get_pedigree_internal(__cilkrts_get_tls_worker());
+}
+
+/** Context used by __cilkrts_get_pedigree_info.
+ *
+ * @deprecated
+ * This data structure is only used by the deprecated
+ * __cilkrts_get_pedigree_info function.
+ *
+ * Callers should initialize the `data` array to NULL and set the `size`
+ * field to `sizeof(__cilkrts_pedigree_context_t)` before the first call
+ * to __cilkrts_get_pedigree_info(), and should not examine or modify it
+ * thereafter.
+ */
+typedef struct
+{
+ __STDNS size_t size; /**< Size of the struct in bytes */
+ void *data[3]; /**< Opaque context data */
+} __cilkrts_pedigree_context_t;
+
+/** Get pedigree information.
+ *
+ * @deprecated
+ * Use __cilkrts_get_pedigree() instead.
+ *
+ * This routine allows code to walk up the stack of Cilk frames to gather
+ * the pedigree.
+ *
+ * Initialize the pedigree walk by filling the pedigree context with NULLs
+ * and setting the size field to sizeof(__cilkrts_pedigree_context).
+ * Other than initialization to NULL to start the walk, user coder should
+ * consider the pedigree context data opaque and should not examine or
+ * modify it.
+ *
+ * @returns 0 - Success - birthrank is valid
+ * @returns >0 - End of pedigree walk
+ * @returns -1 - Failure - No worker bound to thread
+ * @returns -2 - Failure - Sanity check failed,
+ * @returns -3 - Failure - Invalid context size
+ * @returns -4 - Failure - Internal error - walked off end of chain of frames
+ */
+CILK_API(int)
+__cilkrts_get_pedigree_info(/* In/Out */ __cilkrts_pedigree_context_t *context,
+ /* Out */ uint64_t *sf_birthrank);
+
+/** Get the rank of the currently executing worker.
+ *
+ * @deprecated
+ * Use `__cilkrts_get_pedigree().rank` instead.
+ *
+ * @returns 0 - Success - *rank is valid
+ * @returns <0 - Failure - *rank is not changed
+ */
+CILK_EXPORT_AND_INLINE
+int __cilkrts_get_worker_rank(uint64_t *rank)
+{
+ *rank = __cilkrts_get_pedigree().rank;
+ return 0;
+}
+
+/** Increment the pedigree rank of the currently executing worker.
+ *
+ * @returns 0 - Success - rank was incremented
+ * @returns-1 - Failure
+ */
+CILK_EXPORT_AND_INLINE
+int __cilkrts_bump_worker_rank(void)
+{
+ return __cilkrts_bump_worker_rank_internal(__cilkrts_get_tls_worker());
+}
+
+/** Increment the pedigree rank for a cilk_for loop.
+ * Obsolete.
+ *
+ * @deprecated
+ * This function was provided to allow the user to manipulate the pedigree
+ * rank of a `cilk_for` loop. The compiler now generates code to do that
+ * manipulation automatically, so this function is now unnecessary. It may
+ * be called, but will have no effect.
+ */
+CILK_EXPORT_AND_INLINE
+int __cilkrts_bump_loop_rank(void)
+{
+ return 0;
+}
+
+//@}
+
+#endif /* __CILKRTS_ABI_VERSION >= 1 */
+
+__CILKRTS_END_EXTERN_C
+
+#else /* CILK_STUB */
+
+// Programs compiled with CILK_STUB are not linked with the Cilk runtime
+// library, so they should not have external references to runtime functions.
+// Therefore, the functions are replaced with stubs.
+
+#ifdef _WIN32
+#define __cilkrts_set_param_w(name,value) ((value), 0)
+#define __cilkrts_set_seh_callback(pfn) (0)
+#endif
+#define __cilkrts_set_param(name,value) ((value), 0)
+#define __cilkrts_end_cilk() ((void) 0)
+#define __cilkrts_init() ((void) 0)
+#define __cilkrts_get_nworkers() (1)
+#define __cilkrts_get_total_workers() (1)
+#define __cilkrts_get_worker_number() (0)
+#define __cilkrts_get_force_reduce() (0)
+#define __cilkrts_metacall(tool,code,data) ((tool), (code), (data), 0)
+
+#if __CILKRTS_ABI_VERSION >= 1
+/* Pedigree stubs */
+#define __cilkrts_get_pedigree_info(context, sf_birthrank) (-1)
+#define __cilkrts_get_worker_rank(rank) (*(rank) = 0)
+#define __cilkrts_bump_worker_rank() (-1)
+#define __cilkrts_bump_loop_rank() (-1)
+
+/*
+ * A stub method for __cilkrts_get_pedigree.
+ * Returns an empty __cilkrts_pedigree.
+ */
+__CILKRTS_INLINE
+__cilkrts_pedigree __cilkrts_get_pedigree_stub(void)
+{
+ __cilkrts_pedigree ans;
+ ans.rank = 0;
+ ans.parent = NULL;
+ return ans;
+}
+
+/* Renamed to an actual stub method. */
+#define __cilkrts_get_pedigree() __cilkrts_get_pedigree_stub()
+
+#endif /* __CILKRTS_ABI_VERSION >= 1 */
+
+#endif /* CILK_STUB */
+
+//@}
+
+#endif /* INCLUDED_CILK_API_H */
diff --git a/libcilkrts/include/cilk/cilk_api_linux.h b/libcilkrts/include/cilk/cilk_api_linux.h
new file mode 100644
index 00000000000..ed9e70635f6
--- /dev/null
+++ b/libcilkrts/include/cilk/cilk_api_linux.h
@@ -0,0 +1,38 @@
+/*
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/* THIS FILE IS DEPRECATED. USE cilk_api.h INSTEAD. */
+#include <cilk/cilk_api.h>
diff --git a/libcilkrts/include/cilk/cilk_stub.h b/libcilkrts/include/cilk/cilk_stub.h
new file mode 100644
index 00000000000..116e3ff5541
--- /dev/null
+++ b/libcilkrts/include/cilk/cilk_stub.h
@@ -0,0 +1,55 @@
+/* cilk_stub.h -*-C++-*-
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef INCLUDED_CILK_STUB_DOT_H
+#define INCLUDED_CILK_STUB_DOT_H
+
+/* Definitions for creating a serialization from a Cilk program.
+ * These definitions are suitable for use by a compiler that is not
+ * Cilk-enabled.
+ */
+
+/* Pretend we are a non-Cilk compiler */
+#undef __cilk
+#define CILK_STUB
+
+/* Replace Cilk keywords with serial equivalents */
+#define _Cilk_spawn
+#define _Cilk_sync
+#define _Cilk_for for
+
+#endif /* ! defined(INCLUDED_CILK_STUB_DOT_H) */
diff --git a/libcilkrts/include/cilk/cilk_undocumented.h b/libcilkrts/include/cilk/cilk_undocumented.h
new file mode 100644
index 00000000000..81cdd64bb89
--- /dev/null
+++ b/libcilkrts/include/cilk/cilk_undocumented.h
@@ -0,0 +1,131 @@
+/*
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ *
+ * cilk_undocumented.h
+ *
+ * This file defines exported functions that are not included in the standard
+ * documentation.
+ */
+
+#ifndef INCLUDED_CILK_UNDOCUMENTED_H
+#define INCLUDED_CILK_UNDOCUMENTED_H
+
+#include <cilk/common.h>
+
+#ifndef CILK_STUB
+
+__CILKRTS_BEGIN_EXTERN_C
+
+/*
+ * __cilkrts_synched
+ *
+ * Allows an application to determine if there are any outstanding children at
+ * this instant. This function will examine the current full frame to
+ * determine this. This function will return a valid result only when called
+ * within a spawn continuation, within the stack frame of the continuation
+ * itself.
+ */
+
+CILK_EXPORT __CILKRTS_NOTHROW
+int __cilkrts_synched(void);
+
+/*
+ * __cilkrts_cilkscreen_puts
+ *
+ * Allows an application to write a string to the Cilkscreen log.
+ * The standard error stream will be flushed after the write.
+ */
+
+CILK_EXPORT __CILKRTS_NOTHROW
+void __cilkrts_cilkscreen_puts(const char *);
+
+/*
+ * __cilkrts_get_sf
+ *
+ * A debugging aid that allows an application to get the __cilkrts_stack_frame
+ * for the current function. Only compiled into the DLL in debug builds.
+ */
+
+CILK_EXPORT __CILKRTS_NOTHROW
+void *__cilkrts_get_sf(void);
+
+/**
+ * Returns the size of stacks created by Cilk.
+ */
+CILK_EXPORT __CILKRTS_NOTHROW
+size_t __cilkrts_get_stack_size(void);
+
+/**
+ * Dumps runtime statistics to stderr.
+ * Undocumented API for debugging.
+ */
+CILK_EXPORT __CILKRTS_NOTHROW
+void __cilkrts_dump_stats(void);
+
+CILK_EXPORT __CILKRTS_NOTHROW
+int __cilkrts_irml_version(void);
+
+struct __cilk_tbb_unwatch_thunk;
+struct __cilk_tbb_stack_op_thunk;
+
+CILK_EXPORT __CILKRTS_NOTHROW
+int __cilkrts_watch_stack(struct __cilk_tbb_unwatch_thunk *u,
+ struct __cilk_tbb_stack_op_thunk o);
+
+#ifndef IN_CILK_RUNTIME
+#ifdef _WIN32
+/* Do not use CILK_API because __cilkrts_worker_stub must be __stdcall */
+CILK_EXPORT unsigned __CILKRTS_NOTHROW __stdcall
+__cilkrts_worker_stub(void *arg);
+#else
+/* Do not use CILK_API because __cilkrts_worker_stub have default visibility */
+CILK_EXPORT void* __CILKRTS_NOTHROW
+__cilkrts_worker_stub(void *arg);
+#endif /* _WIN32 */
+#endif /* IN_CILK_RUNTIME */
+
+__CILKRTS_END_EXTERN_C
+
+#else /* CILK_STUB */
+
+/* Stubs for the api functions */
+
+#define __cilkrts_get_stack_size() (0)
+#define __cilkrts_synched() (1)
+
+#endif /* CILK_STUB */
+
+#endif /* INCLUDED_CILK_UNDOCUMENTED_H */
diff --git a/libcilkrts/include/cilk/common.h b/libcilkrts/include/cilk/common.h
new file mode 100644
index 00000000000..8ec19afa922
--- /dev/null
+++ b/libcilkrts/include/cilk/common.h
@@ -0,0 +1,376 @@
+/** common.h
+ *
+ * @copyright
+ * Copyright (C) 2010-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file common.h
+ *
+ * @brief Defines common macros and structures used by the Intel Cilk Plus
+ * runtime.
+ *
+ * @ingroup common
+ */
+
+/** @defgroup common Common Definitions
+ * Macro, structure, and class definitions used elsewhere in the runtime.
+ * @{
+ */
+
+#ifndef INCLUDED_CILK_COMMON
+#define INCLUDED_CILK_COMMON
+
+#ifdef __cplusplus
+/** Namespace for all Cilk definitions that can be included in user code.
+ */
+namespace cilk {
+
+ /** Namespace for definitions that are primarily intended for use
+ * in other Cilk definitions.
+ */
+ namespace internal {}
+}
+#endif
+
+/** Cilk library version = 1.01
+ */
+#define CILK_LIBRARY_VERSION 102
+
+#ifdef __cplusplus
+# include <cassert>
+#else
+# include <assert.h>
+#endif
+
+/**
+ * Prefix standard library function and type names with __STDNS in order to
+ * get correct lookup in both C and C++.
+ */
+#ifdef __cplusplus
+# define __STDNS std::
+#else
+# define __STDNS
+#endif
+
+/**
+ * @def CILK_EXPORT
+ * Define export of runtime functions from shared library.
+ * Should be exported only from cilkrts*.dll/cilkrts*.so
+ * @def CILK_EXPORT_DATA
+ * Define export of runtime data from shared library.
+ */
+#ifdef _WIN32
+# ifdef IN_CILK_RUNTIME
+# define CILK_EXPORT __declspec(dllexport)
+# define CILK_EXPORT_DATA __declspec(dllexport)
+# else
+# define CILK_EXPORT __declspec(dllimport)
+# define CILK_EXPORT_DATA __declspec(dllimport)
+# endif /* IN_CILK_RUNTIME */
+#elif defined(__CYGWIN__) || defined(__APPLE__) || defined(_DARWIN_C_SOURCE)
+# define CILK_EXPORT /* nothing */
+# define CILK_EXPORT_DATA /* nothing */
+#else /* Unix/gcc */
+# ifdef IN_CILK_RUNTIME
+# define CILK_EXPORT __attribute__((visibility("protected")))
+# define CILK_EXPORT_DATA __attribute__((visibility("protected")))
+# else
+# define CILK_EXPORT /* nothing */
+# define CILK_EXPORT_DATA /* nothing */
+# endif /* IN_CILK_RUNTIME */
+#endif /* Unix/gcc */
+
+/**
+ * @def __CILKRTS_BEGIN_EXTERN_C
+ * Macro to denote the start of a section in which all names have "C" linkage.
+ * That is, none of the names are to be mangled.
+ * @see __CILKRTS_END_EXTERN_C
+ * @see __CILKRTS_EXTERN_C
+ *
+ * @def __CILKRTS_END_EXTERN_C
+ * Macro to denote the end of a section in which all names have "C" linkage.
+ * That is, none of the names are to be mangled.
+ * @see __CILKRTS_BEGIN_EXTERN_C
+ * @see __CILKRTS_EXTERN_C
+ *
+ * @def __CILKRTS_EXTERN_C
+ * Macro to prefix a single definition which has "C" linkage.
+ * That is, the defined name is not to be mangled.
+ * @see __CILKRTS_BEGIN_EXTERN_C
+ * @see __CILKRTS_END_EXTERN_C
+ */
+#ifdef __cplusplus
+# define __CILKRTS_BEGIN_EXTERN_C extern "C" {
+# define __CILKRTS_END_EXTERN_C }
+# define __CILKRTS_EXTERN_C extern "C"
+#else
+# define __CILKRTS_BEGIN_EXTERN_C
+# define __CILKRTS_END_EXTERN_C
+# define __CILKRTS_EXTERN_C
+#endif
+
+/**
+ * OS-independent macro to specify a function which is known to not throw
+ * an exception.
+ */
+#ifdef __cplusplus
+# ifdef _WIN32
+# define __CILKRTS_NOTHROW __declspec(nothrow)
+# else /* Unix/gcc */
+# define __CILKRTS_NOTHROW __attribute__((nothrow))
+# endif /* Unix/gcc */
+#else
+# define __CILKRTS_NOTHROW /* nothing */
+#endif /* __cplusplus */
+
+/** Cache alignment. (Good enough for most architectures.)
+ */
+#define __CILKRTS_CACHE_LINE__ 64
+
+/**
+ * Macro to specify alignment of a data member in a structure.
+ * Because of the way that gcc’s alignment attribute is defined, @a n must
+ * be a numeric literal, not just a compile-time constant expression.
+ */
+#ifdef _WIN32
+# define CILK_ALIGNAS(n) __declspec(align(n))
+#else /* Unix/gcc */
+# define CILK_ALIGNAS(n) __attribute__((__aligned__(n)))
+#endif
+
+/**
+ * Macro to specify cache-line alignment of a data member in a structure.
+ */
+#define __CILKRTS_CACHE_ALIGN CILK_ALIGNAS(__CILKRTS_CACHE_LINE__)
+
+/**
+ * Macro to specify a class as being at least as strictly aligned as some
+ * type on Windows. gcc does not provide a way of doing this, so on Unix,
+ * this just specifies the largest natural type alignment. Put the macro
+ * between the `class` keyword and the class name:
+ *
+ * class CILK_ALIGNAS_TYPE(foo) bar { ... };
+ */
+#ifdef _WIN32
+# define CILK_ALIGNAS_TYPE(t) __declspec(align(__alignof(t)))
+#else /* Unix/gcc */
+# define CILK_ALIGNAS_TYPE(t) __attribute__((__aligned__))
+#endif
+
+/**
+ * @def CILK_API(RET_TYPE)
+ * A function called explicitly by the programmer.
+ * @def CILK_ABI(RET_TYPE)
+ * A function called by compiler-generated code.
+ * @def CILK_ABI_THROWS(RET_TYPE)
+ * An ABI function that may throw an exception
+ *
+ * Even when these are the same definitions, they should be separate macros so
+ * that they can be easily found in the code.
+ */
+
+#ifdef _WIN32
+# define CILK_API(RET_TYPE) CILK_EXPORT RET_TYPE __CILKRTS_NOTHROW __cdecl
+# define CILK_ABI(RET_TYPE) CILK_EXPORT RET_TYPE __CILKRTS_NOTHROW __cdecl
+# define CILK_ABI_THROWS(RET_TYPE) CILK_EXPORT RET_TYPE __cdecl
+#else
+# define CILK_API(RET_TYPE) CILK_EXPORT RET_TYPE __CILKRTS_NOTHROW
+# define CILK_ABI(RET_TYPE) CILK_EXPORT RET_TYPE __CILKRTS_NOTHROW
+# define CILK_ABI_THROWS(RET_TYPE) CILK_EXPORT RET_TYPE
+#endif
+
+/**
+ * __CILKRTS_ASSERT should be defined for debugging only, otherwise it
+ * interferes with vectorization. Since NDEBUG is not reliable (it must be
+ * set by the user), we must use a platform-specific detection of debug mode.
+ */
+#if defined(_WIN32) && defined(_DEBUG)
+ /* Windows debug */
+# define __CILKRTS_ASSERT(e) assert(e)
+#elif (! defined(_WIN32)) && ! defined(__OPTIMIZE__)
+ /* Unix non-optimized */
+# define __CILKRTS_ASSERT(e) assert(e)
+#elif defined __cplusplus
+ /* C++ non-debug */
+# define __CILKRTS_ASSERT(e) static_cast<void>(0)
+#else
+ /* C non-debug */
+# define __CILKRTS_ASSERT(e) ((void) 0)
+#endif
+
+/**
+ * OS-independent macro to specify a function that should be inlined
+ */
+#ifdef __cpluspus
+ // C++
+# define __CILKRTS_INLINE inline
+#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+ // C99
+# define __CILKRTS_INLINE static inline
+#elif defined(_MSC_VER)
+ // C89 on Windows
+# define __CILKRTS_INLINE __inline
+#else
+ // C89 on GCC-compatible systems
+# define __CILKRTS_INLINE extern __inline__
+#endif
+
+/**
+ * Functions marked as CILK_EXPORT_AND_INLINE have both
+ * inline versions defined in the Cilk API, as well as
+ * non-inlined versions that are exported (for
+ * compatibility with previous versions that did not
+ * inline the functions).
+ */
+#ifdef COMPILING_CILK_API_FUNCTIONS
+# define CILK_EXPORT_AND_INLINE CILK_EXPORT
+#else
+# define CILK_EXPORT_AND_INLINE __CILKRTS_INLINE
+#endif
+
+/**
+ * Try to determine if compiler supports rvalue references.
+ */
+#if defined(__cplusplus) && !defined(__CILKRTS_RVALUE_REFERENCES)
+# if __cplusplus >= 201103L // C++11
+# define __CILKRTS_RVALUE_REFERENCES 1
+# elif defined(__GXX_EXPERIMENTAL_CXX0X__)
+# define __CILKRTS_RVALUE_REFERENCES 1
+# elif __cplusplus >= 199711L && __cplusplus < 201103L
+ // Compiler recognizes a language version prior to C++11
+# elif __INTEL_COMPILER == 1200 && defined(__STDC_HOSTED__)
+ // Intel compiler version 12.0
+ // __cplusplus has a non-standard definition. In the absence of a
+ // proper definition, look for the C++0x macro, __STDC_HOSTED__.
+# define __CILKRTS_RVALUE_REFERENCES 1
+# elif __INTEL_COMPILER > 1200 && defined(CHAR16T)
+ // Intel compiler version >= 12.1
+ // __cplusplus has a non-standard definition. In the absence of a
+ // proper definition, look for the Intel macro, CHAR16T
+# define __CILKRTS_RVALUE_REFERENCES 1
+# endif
+#endif
+
+/*
+ * Include stdint.h to define the standard integer types.
+ *
+ * Unfortunately Microsoft doesn't provide stdint.h until Visual Studio 2010,
+ * so use our own definitions until those are available
+ */
+
+#if ! defined(_MSC_VER) || (_MSC_VER >= 1600)
+# include <stdint.h>
+#else
+# ifndef __MS_STDINT_TYPES_DEFINED__
+# define __MS_STDINT_TYPES_DEFINED__
+ typedef signed char int8_t;
+ typedef short int16_t;
+ typedef int int32_t;
+ typedef __int64 int64_t;
+
+ typedef unsigned char uint8_t;
+ typedef unsigned short uint16_t;
+ typedef unsigned int uint32_t;
+ typedef unsigned __int64 uint64_t;
+# endif /* __MS_STDINT_TYPES_DEFINED__ */
+#endif /* ! defined(_MSC_VER) || (_MSC_VER >= 1600) */
+
+/**
+ * @brief Application Binary Interface version of the Cilk runtime library.
+ *
+ * The ABI version is determined by the compiler used. An object file
+ * compiled with a higher ABI version is not compatible with a library that is
+ * compiled with a lower ABI version. An object file compiled with a lower
+ * ABI version, however, can be used with a library compiled with a higher ABI
+ * version unless otherwise stated.
+ */
+#ifndef __CILKRTS_ABI_VERSION
+# ifdef IN_CILK_RUNTIME
+# define __CILKRTS_ABI_VERSION 1
+# elif __INTEL_COMPILER > 1200
+ // Intel compiler version >= 12.1
+# define __CILKRTS_ABI_VERSION 1
+# else
+ // Compiler does not support ABI version 1
+ // (Non-Intel compiler or Intel compiler prior to version 12.1).
+# define __CILKRTS_ABI_VERSION 0
+# endif
+#endif
+
+// These structs are exported because the inlining of
+// the internal version of API methods require a worker
+// structure as parameter.
+__CILKRTS_BEGIN_EXTERN_C
+ /// Worker struct, exported for inlined API methods
+ /// @ingroup api
+ struct __cilkrts_worker;
+
+ /// Worker struct, exported for inlined API methods
+ /// @ingroup api
+ typedef struct __cilkrts_worker __cilkrts_worker;
+
+ /// Worker struct pointer, exported for inlined API methods
+ /// @ingroup api
+ typedef struct __cilkrts_worker *__cilkrts_worker_ptr;
+
+
+ /// Fetch the worker out of TLS.
+ CILK_ABI(__cilkrts_worker_ptr) __cilkrts_get_tls_worker(void);
+
+ /// void *, defined to work around complaints from the compiler
+ /// about using __declspec(nothrow) after the "void *" return type
+ typedef void * __cilkrts_void_ptr;
+
+__CILKRTS_END_EXTERN_C
+
+
+#if __CILKRTS_ABI_VERSION >= 1
+// Pedigree API is available only for compilers that use ABI version >= 1.
+
+/** Pedigree information kept in the worker and stack frame.
+ * @ingroup api
+ */
+typedef struct __cilkrts_pedigree
+{
+ /** Rank at start of spawn helper. Saved rank for spawning functions */
+ uint64_t rank;
+
+ /** Link to next in chain */
+ const struct __cilkrts_pedigree *parent;
+} __cilkrts_pedigree;
+
+#endif // __CILKRTS_ABI_VERSION >= 1
+
+/// @}
+
+#endif /* INCLUDED_CILK_COMMON */
diff --git a/libcilkrts/include/cilk/holder.h b/libcilkrts/include/cilk/holder.h
new file mode 100644
index 00000000000..8620c052f53
--- /dev/null
+++ b/libcilkrts/include/cilk/holder.h
@@ -0,0 +1,1000 @@
+/*
+ * @copyright
+ * Copyright (C) 2011-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+ * holder.h
+ *
+ * Purpose: hyperobject to provide different views of an object to each
+ * parallel strand.
+ */
+
+#ifndef HOLDER_H_INCLUDED
+#define HOLDER_H_INCLUDED
+
+#include <cilk/reducer.h>
+#include <memory>
+#include <utility>
+
+#ifdef __cplusplus
+
+/* C++ Interface
+ *
+ * Classes: holder<Type>
+ *
+ * Description:
+ * ============
+ * This component provides a hyperobject that isolates a parallel uses of a
+ * common variable where it is not necessary to preserve changes from
+ * different parallel strands. In effect, a holder acts a bit like
+ * thread-local storage, but has qualities that work better with the
+ * fork-join structure of Cilk. In particular, a holder has the following
+ * qualities:
+ *
+ * - The view of a holder before the first spawn within a function is the same
+ * as the view after each sync (as in the case of a reducer).
+ * - The view of a holder within the first spawned child of a function (or the
+ * first child spawned after a sync) is the same as the view on entry to the
+ * function.
+ * - The view of a holder before entering a _Cilk_for loop is the same as the
+ * view during the first iteration of the loop and the view at the end of
+ * the loop.
+ * - The view of a holder in the continuation of a spawn or in an arbitrary
+ * iteration of a _Cilk_for loop is *non-deterministic*. It is generally
+ * recommended that the holder be explicitly put into a known state in these
+ * situations.
+ *
+ * A holder can be used as an alternative to parameter-passing. They are most
+ * useful for replacing non-local variables without massive refactoring. A
+ * holder takes advantage of the fact that, most of the time, a holder view
+ * does not change after a spawn or from one iteration of a parallel for loop
+ * to the next (i.e., stealing is the exception, not the rule). When the
+ * holder view is a large object that is expensive to construct, this
+ * optimization can save significant time versus creating a separate local
+ * object for each view. In addition, a holder using the "keep last" policy
+ * will have the same value after a sync as the serialization of the same
+ * program. The last quality will often allow the program to avoid
+ * recomputing a value.
+ *
+ * Usage Example:
+ * ==============
+ * Function 'compute()' is a complex function that computes a value using a
+ * memoized algorithm, storing intermediate results in a hash table. Compute
+ * calls several other functions, each of which calls several other functions,
+ * all of which share a global hash table. In all, there are over a dozen
+ * functions with a total of about 60 references to the hash table.
+ *..
+ * hash_table<int, X> memos;
+ *
+ * void h(const X& x); // Uses memos
+ *
+ * double compute(const X& x)
+ * {
+ * memos.clear();
+ * // ...
+ * memos[i] = x;
+ * ...
+ * g(i); // Uses memos
+ * // ...
+ * std::for_each(c.begin(), c.end(), h); // Call h for each element of c
+ * }
+ *
+ * int main()
+ * {
+ * const std::size_t ARRAY_SIZE = 1000000;
+ * extern X myArray[ARRAY_SIZE];
+ *
+ * for (std::size_t i = 0; i < ARRAY_SIZE; ++i)
+ * {
+ * compute(myArray[i]);
+ * }
+ * }
+ *..
+ * We would like to replace the 'for' loop in 'main' with a 'cilk_for'.
+ * Although the hash table is cleared on entry to each call to 'compute()',
+ * and although the values stored in the hash table are no longer used after
+ * 'compute()' returns, the use of the hash table as a global variable
+ * prevents 'compute()' from being called safely in parallel. One way to do
+ * this would be to make 'memos' a private variable within the cilk_for loop
+ * and pass it down to the actual computation, so that each loop iteration has
+ * its own private copy:
+ *..
+ * cilk_for (std::size_t i = 0; i < ARRAY_SIZE; ++i)
+ * {
+ * hash_table<int, X> memos;
+ * compute(myArray[i], memos);
+ * }
+ *..
+ * The problem with this approach is that it requires changing the signature
+ * of 'compute', 'h', 'g', and every one of the dozen or so functions that
+ * reference 'memos' as well as any function that calls those functions. This
+ * may break the abstraction of 'compute' and other functions, exposing an
+ * implementation detail that was not part of the interface. In addition, the
+ * function 'h' is called through a templated algorithm, 'for_each', which
+ * requires a fixed interface. Finally, there is constructor and destructor
+ * overhead for 'hash_table' each time through the loop.
+ *
+ * The alternative approach is to replace 'memos' with a holder. The holder
+ * would be available to all of the functions involved, but would not cause a
+ * race between parallel loop iterations. In order to make this work, each
+ * use of the 'memos' variable must be (mechanically) replaced by a use of the
+ * holder:
+ *..
+ * cilk::holder<hash_table<int, X> > memos_h;
+ *
+ * void h(const X& x); // Uses memos_h
+ *
+ * double compute(const X& x)
+ * {
+ * memos_h().clear(); // operator() used to "dereference" the holder
+ * // ...
+ * memos_h()[i] = x; // operator() used to "dereference" the holder
+ * ...
+ * g(i); // Uses memos_h
+ * // ...
+ * std::for_each(c.begin(), c.end(), h); // Call h for each element of c
+ * }
+ *..
+ * Note that each reference to the holder must be modified with an empty pair
+ * of parenthesis. This syntax is needed because there is no facility in C++
+ * for a "smart reference" that would allow 'memos_h' to be a perfect
+ * replacement for 'memos'. One way that a user can avoid this syntax change
+ * is to wrap the holder in a class that has the same inteface as
+ * 'hash_table' but redirects all calls to the holder:
+ *..
+ * template <typename K, typename V>
+ * class hash_table_holder
+ * {
+ * private:
+ * cilk::holder<hash_table<K, V> > m_holder;
+ * public:
+ * void clear() { m_holder().clear(); }
+ * V& operator[](const K& x) { return m_holder()[x]; }
+ * std::size_t size() const { return m_holder().size(); }
+ * // etc. ...
+ * };
+ *..
+ * Using the above wrapper, the original code can be left unchanged except for
+ * replacing 'hash_table' with 'hash_table_holder' and replacing 'for' with
+ * 'cilk_for':
+ *..
+ * hash_table_holder<int, X> memos;
+ *
+ * void h(const X& x); // Uses memos
+ *
+ * double compute(const X& x)
+ * {
+ * memos.clear(); // Calls hash_table_holder::clear().
+ * // ...
+ * }
+ *..
+ * The above changes have no benefit over the use of thread-local storage.
+ * What if one of the functions has a 'cilk_spawn', however?
+ *..
+ * void h(const X& x)
+ * {
+ * Y y = x.nested();
+ * double d, w;
+ * if (y)
+ * {
+ * w = cilk_spawn compute_width(y); // May use 'memos'
+ * d = compute_depth(y); // Does not use 'memos'
+ * cilk_sync;
+ * compute(y); // recursive call. Uses 'memos'.
+ * }
+ * }
+ *..
+ * In the above example, the view of the holder within 'compute_width' is the
+ * same as the view on entry to 'h'. More importantly, the view of the holder
+ * within the recursive call to 'compute' is the same as the view on entry to
+ * 'h', even if a different worker is executing the recursive call. Thus, the
+ * holder view within a Cilk program has useful qualities not found in
+ * thread-local storage.
+ */
+
+namespace cilk {
+
+ /**
+ * After a sync, the value stored in a holder matches the most recent
+ * value stored into the holder by one of the starnds entering the sync.
+ * The holder policy used to instantiate the holder determines which of
+ * the entering strands determines the final value of the holder. A policy
+ * of 'holder_keep_indeterminate' (the default) is the most efficient, and
+ * results in an indeterminate value depending on the runtime schedule
+ * (see below for more specifics). An indeterminate value after a sync is
+ * often acceptable, especially if the value of the holder is not reused
+ * after the sync. All of the remaining policies retain the value of the
+ * last strand that would be executed in the serialization of the program.
+ * They differ in the mechanism used to move the value from one view to
+ * another. A policy of 'holder_keep_last_copy' moves values by
+ * copy-assignment. A policy of 'holder_keep_last_swap' moves values by
+ * calling 'swap'. A policy of 'holder_keep_last_move' is available only
+ * for compilers that support C++0x rvalue references and moves values by
+ * move-assignment. A policy of 'holder_keep_last' attempts to choose the
+ * most efficient mechanism: member-function 'swap' if the view type
+ * supports it, otherwise move-assignment if supported, otherwise
+ * copy-assignment. (The swap member function for a class that provides
+ * one is almost always as fast or faster than move-assignment or
+ * copy-assignment.)
+ *
+ * The behavior of 'holder_keep_indeterminate', while indeterminate, is
+ * not random and can be used for advanced programming or debugging. With
+ * a policy of 'holder_keep_intermediate', values are never copied or
+ * moved between views. The value of the view after a sync is the same as
+ * the value set in the last spawned child before a steal occurs or the
+ * last value set in the continuation if no steal occurs. Using this
+ * knowledge, a programmer can use a holder to detect the earliest steal
+ * in a piece of code. An indeterminate holder is also useful for keeping
+ * cached data similar to the way some applications might use thread-local
+ * storage.
+ */
+ enum holder_policy {
+ holder_keep_indeterminate,
+ holder_keep_last,
+ holder_keep_last_copy,
+ holder_keep_last_swap,
+#ifdef __CILKRTS_RVALUE_REFERENCES
+ holder_keep_last_move
+#endif
+ };
+
+ namespace internal {
+
+ // Private special-case holder policy using the swap member-function
+ const holder_policy holder_keep_last_member_swap =
+ (holder_policy) (holder_keep_last_swap | 0x10);
+
+ /* The constant, 'has_member_swap<T>::value', will be 'true' if 'T'
+ * has a non-static member function with prototype 'void swap(T&)'.
+ * The mechanism used to detect 'swap' is the most portable among
+ * present-day compilers, but is not the most robust. Specifically,
+ * the prototype for 'swap' must exactly match 'void swap(T&)'.
+ * Near-matches like a 'swap' function that returns 'int' instead of
+ * 'void' will not be detected. Detection will also fail if 'T'
+ * inherits 'swap' from a base class.
+ */
+ template <typename T>
+ class has_member_swap
+ {
+ // This technique for detecting member functions was described by
+ // Rani Sharoni in comp.lang.c++.moderated:
+ // http://groups.google.com/group/comp.lang.c++.moderated/msg/2b06b2432fddfb60
+
+ // sizeof(notchar) is guaranteed larger than 1
+ struct notchar { char x[2]; };
+
+ // Instantiationg Q<U, &U::swap> will fail unless U contains a
+ // non-static member with prototype 'void swap(U&)'.
+ template <class U, void (U::*)(U&)> struct Q { };
+
+ // First 'test' is preferred overload if U::swap exists with the
+ // correct prototype. Second 'test' is preferred overload
+ // otherwise.
+ template <typename U> static char test(Q<U,&U::swap>*);
+ template <typename U> static notchar test(...);
+
+ public:
+ /// 'value' will be true if T has a non-static member function
+ /// with prototype 'void swap(T&)'.
+ static const bool value = (1 == sizeof(test<T>(0)));
+ };
+
+ template <typename T> const bool has_member_swap<T>::value;
+
+ /**
+ * @brief Utility class for exception safety.
+ *
+ * The constuctor for this class takes a pointer and an allocator and
+ * holds on to them. The destructor deallocates the pointed-to
+ * object, without calling its destructor, typically to recover memory
+ * in case an exception is thrown. The release member clears the
+ * pointer so that the deallocation is prevented, i.e., when the
+ * exception danger has passed. The behavior of this class is similar
+ * to auto_ptr and unique_ptr.
+ */
+ template <typename Type, typename Allocator = std::allocator<Type> >
+ class auto_deallocator
+ {
+ Allocator m_alloc;
+ Type* m_ptr;
+
+ // Non-copiable
+ auto_deallocator(const auto_deallocator&);
+ auto_deallocator& operator=(const auto_deallocator&);
+
+ public:
+ /// Constructor
+ explicit auto_deallocator(Type* p, const Allocator& a = Allocator())
+ : m_alloc(a), m_ptr(p) { }
+
+ /// Destructor - free allocated resources
+ ~auto_deallocator() { if (m_ptr) m_alloc.deallocate(m_ptr, 1); }
+
+ /// Remove reference to resource
+ void release() { m_ptr = 0; }
+ };
+
+ /**
+ * Pure-abstract base class to initialize holder views
+ */
+ template <typename Type, typename Allocator>
+ class init_base
+ {
+ public:
+ virtual ~init_base() { }
+ virtual init_base* clone_self(Allocator& a) const = 0;
+ virtual void delete_self(Allocator& a) = 0;
+ virtual void construct_view(Type* p, Allocator& a) const = 0;
+ };
+
+ /**
+ * Class to default-initialize a holder view
+ */
+ template <typename Type, typename Allocator>
+ class default_init : public init_base<Type, Allocator>
+ {
+ typedef init_base<Type, Allocator> base;
+
+ /// Private constructor (called from static make() function).
+ default_init() { }
+
+ // Non-copiable
+ default_init(const default_init&);
+ default_init& operator=(const default_init&);
+
+ public:
+ // Static factory function
+ static default_init* make(Allocator& a);
+
+ // Virtual function overrides
+ virtual ~default_init();
+ virtual base* clone_self(Allocator& a) const;
+ virtual void delete_self(Allocator& a);
+ virtual void construct_view(Type* p, Allocator& a) const;
+ };
+
+ template <typename Type, typename Allocator>
+ default_init<Type, Allocator>*
+ default_init<Type, Allocator>::make(Allocator&)
+ {
+ // Return a pointer to a singleton. All instances of this class
+ // are identical, so we need only one.
+ static default_init self;
+ return &self;
+ }
+
+ template <typename Type, typename Allocator>
+ default_init<Type, Allocator>::~default_init()
+ {
+ }
+
+ template <typename Type, typename Allocator>
+ init_base<Type, Allocator>*
+ default_init<Type, Allocator>::clone_self(Allocator& a) const
+ {
+ return make(a);
+ }
+
+ template <typename Type, typename Allocator>
+ void default_init<Type, Allocator>::delete_self(Allocator&)
+ {
+ // Since make() returned a shared singleton, there is nothing to
+ // delete here.
+ }
+
+ template <typename Type, typename Allocator>
+ void
+ default_init<Type, Allocator>::construct_view(Type* p,
+ Allocator&) const
+ {
+ ::new((void*) p) Type();
+ // TBD: In a C++0x library, this should be rewritten
+ // std::allocator_traits<Allocator>::construct(a, p);
+ }
+
+ /**
+ * Class to copy-construct a view from a stored exemplar.
+ */
+ template <typename Type, typename Allocator>
+ class exemplar_init : public init_base<Type, Allocator>
+ {
+ typedef init_base<Type, Allocator> base;
+
+ Type* m_exemplar;
+
+ // Private constructors (called from make() functions).
+ exemplar_init(const Type& val, Allocator& a);
+#ifdef __CILKRTS_RVALUE_REFERENCES
+ exemplar_init(Type&& val, Allocator& a);
+#endif
+
+ // Non-copyiable
+ exemplar_init(const exemplar_init&);
+ exemplar_init& operator=(const exemplar_init&);
+
+ public:
+ // Static factory functions
+ static exemplar_init* make(const Type& val,
+ Allocator& a = Allocator());
+#ifdef __CILKRTS_RVALUE_REFERENCES
+ static exemplar_init* make(Type&& val,
+ Allocator& a = Allocator());
+#endif
+
+ // Virtual function overrides
+ virtual ~exemplar_init();
+ virtual base* clone_self(Allocator& a) const;
+ virtual void delete_self(Allocator& a);
+ virtual void construct_view(Type* p, Allocator& a) const;
+ };
+
+ template <typename Type, typename Allocator>
+ exemplar_init<Type, Allocator>::exemplar_init(const Type& val,
+ Allocator& a)
+ {
+ m_exemplar = a.allocate(1);
+ auto_deallocator<Type, Allocator> guard(m_exemplar, a);
+ a.construct(m_exemplar, val);
+ guard.release();
+ }
+
+#ifdef __CILKRTS_RVALUE_REFERENCES
+ template <typename Type, typename Allocator>
+ exemplar_init<Type, Allocator>::exemplar_init(Type&& val,
+ Allocator& a)
+ {
+ m_exemplar = a.allocate(1);
+ auto_deallocator<Type, Allocator> guard(m_exemplar, a);
+ a.construct(m_exemplar, std::forward<Type>(val));
+ guard.release();
+ }
+#endif
+
+ template <typename Type, typename Allocator>
+ exemplar_init<Type, Allocator>*
+ exemplar_init<Type, Allocator>::make(const Type& val,
+ Allocator& a)
+ {
+ typedef typename Allocator::template rebind<exemplar_init>::other
+ self_alloc_t;
+ self_alloc_t alloc(a);
+
+ exemplar_init *self = alloc.allocate(1);
+ auto_deallocator<exemplar_init, self_alloc_t> guard(self, alloc);
+
+ // Don't use allocator to construct self. Allocator should be
+ // used only on elements of type 'Type'.
+ ::new((void*) self) exemplar_init(val, a);
+
+ guard.release();
+
+ return self;
+ }
+
+#ifdef __CILKRTS_RVALUE_REFERENCES
+ template <typename Type, typename Allocator>
+ exemplar_init<Type, Allocator>*
+ exemplar_init<Type, Allocator>::make(Type&& val,
+ Allocator& a)
+ {
+ typedef typename Allocator::template rebind<exemplar_init>::other
+ self_alloc_t;
+ self_alloc_t alloc(a);
+
+ exemplar_init *self = alloc.allocate(1);
+ auto_deallocator<exemplar_init, self_alloc_t> guard(self, alloc);
+
+ // Don't use allocator to construct self. Allocator should be
+ // used only on elements of type 'Type'.
+ ::new((void*) self) exemplar_init(std::forward<Type>(val), a);
+
+ guard.release();
+
+ return self;
+ }
+#endif
+
+ template <typename Type, typename Allocator>
+ exemplar_init<Type, Allocator>::~exemplar_init()
+ {
+ // Called only by delete_self, which deleted the exemplar using an
+ // allocator.
+ __CILKRTS_ASSERT(0 == m_exemplar);
+ }
+
+ template <typename Type, typename Allocator>
+ init_base<Type, Allocator>*
+ exemplar_init<Type, Allocator>::clone_self(Allocator& a) const
+ {
+ return make(*m_exemplar, a);
+ }
+
+ template <typename Type, typename Allocator>
+ void exemplar_init<Type, Allocator>::delete_self(Allocator& a)
+ {
+ typename Allocator::template rebind<exemplar_init>::other alloc(a);
+
+ a.destroy(m_exemplar);
+ a.deallocate(m_exemplar, 1);
+ m_exemplar = 0;
+
+ this->~exemplar_init();
+ alloc.deallocate(this, 1);
+ }
+
+ template <typename Type, typename Allocator>
+ void
+ exemplar_init<Type, Allocator>::construct_view(Type* p,
+ Allocator& a) const
+ {
+ a.construct(p, *m_exemplar);
+ // TBD: In a C++0x library, this should be rewritten
+ // std::allocator_traits<Allocator>::construct(a, p, *m_exemplar);
+ }
+
+ /**
+ * Class to construct a view using a stored functor. The functor,
+ * 'f', must be be invokable using the expression 'Type x = f()'.
+ */
+ template <typename Func, typename Allocator>
+ class functor_init :
+ public init_base<typename Allocator::value_type, Allocator>
+ {
+ typedef typename Allocator::value_type value_type;
+ typedef init_base<value_type, Allocator> base;
+ typedef typename Allocator::template rebind<Func>::other f_alloc;
+
+ Func *m_functor;
+
+ /// Private constructors (called from make() functions
+ functor_init(const Func& f, Allocator& a);
+#ifdef __CILKRTS_RVALUE_REFERENCES
+ functor_init(Func&& f, Allocator& a);
+#endif
+
+ // Non-copiable
+ functor_init(const functor_init&);
+ functor_init& operator=(const functor_init&);
+
+ public:
+ // Static factory functions
+ static functor_init* make(const Func& val,
+ Allocator& a = Allocator());
+#ifdef __CILKRTS_RVALUE_REFERENCES
+ static functor_init* make(Func&& val,
+ Allocator& a = Allocator());
+#endif
+
+ // Virtual function overrides
+ virtual ~functor_init();
+ virtual base* clone_self(Allocator& a) const;
+ virtual void delete_self(Allocator& a);
+ virtual void
+ construct_view(value_type* p, Allocator& a) const;
+ };
+
+ /// Specialization to strip off reference from 'Func&'.
+ template <typename Func, typename Allocator>
+ struct functor_init<Func&, Allocator>
+ : functor_init<Func, Allocator> { };
+
+ /// Specialization to strip off reference and cvq from 'const Func&'.
+ template <typename Func, typename Allocator>
+ struct functor_init<const Func&, Allocator>
+ : functor_init<Func, Allocator> { };
+
+ template <typename Func, typename Allocator>
+ functor_init<Func, Allocator>::functor_init(const Func& f,
+ Allocator& a)
+ {
+ f_alloc alloc(a);
+
+ m_functor = alloc.allocate(1);
+ auto_deallocator<Func, f_alloc> guard(m_functor, alloc);
+ alloc.construct(m_functor, f);
+ guard.release();
+ }
+
+#ifdef __CILKRTS_RVALUE_REFERENCES
+ template <typename Func, typename Allocator>
+ functor_init<Func, Allocator>::functor_init(Func&& f,
+ Allocator& a)
+ {
+ f_alloc alloc(a);
+
+ m_functor = alloc.allocate(1);
+ auto_deallocator<Func, f_alloc> guard(m_functor, alloc);
+ alloc.construct(m_functor, std::forward<Func>(f));
+ guard.release();
+ }
+#endif
+
+ template <typename Func, typename Allocator>
+ functor_init<Func, Allocator>*
+ functor_init<Func, Allocator>::make(const Func& f, Allocator& a)
+ {
+ typedef typename Allocator::template rebind<functor_init>::other
+ self_alloc_t;
+ self_alloc_t alloc(a);
+
+ functor_init *self = alloc.allocate(1);
+ auto_deallocator<functor_init, self_alloc_t> guard(self, alloc);
+
+ // Don't use allocator to construct self. Allocator should be
+ // used only on elements of type 'Func'.
+ ::new((void*) self) functor_init(f, a);
+
+ guard.release();
+
+ return self;
+ }
+
+#ifdef __CILKRTS_RVALUE_REFERENCES
+ template <typename Func, typename Allocator>
+ functor_init<Func, Allocator>*
+ functor_init<Func, Allocator>::make(Func&& f, Allocator& a)
+ {
+ typedef typename Allocator::template rebind<functor_init>::other
+ self_alloc_t;
+ self_alloc_t alloc(a);
+
+ functor_init *self = alloc.allocate(1);
+ auto_deallocator<functor_init, self_alloc_t> guard(self, alloc);
+
+ // Don't use allocator to construct self. Allocator should be
+ // used only on elements of type 'Func'.
+ ::new((void*) self) functor_init(std::forward<Func>(f), a);
+
+ guard.release();
+
+ return self;
+ }
+#endif
+
+ template <typename Func, typename Allocator>
+ functor_init<Func, Allocator>::~functor_init()
+ {
+ // Called only by delete_self, which deleted the functor using an
+ // allocator.
+ __CILKRTS_ASSERT(0 == m_functor);
+ }
+
+ template <typename Func, typename Allocator>
+ init_base<typename Allocator::value_type, Allocator>*
+ functor_init<Func, Allocator>::clone_self(Allocator& a) const
+ {
+ return make(*m_functor, a);
+ }
+
+ template <typename Func, typename Allocator>
+ inline
+ void functor_init<Func, Allocator>::delete_self(Allocator& a)
+ {
+ typename Allocator::template rebind<functor_init>::other alloc(a);
+ f_alloc fa(a);
+
+ fa.destroy(m_functor);
+ fa.deallocate(m_functor, 1);
+ m_functor = 0;
+
+ this->~functor_init();
+ alloc.deallocate(this, 1);
+ }
+
+ template <typename Func, typename Allocator>
+ void functor_init<Func, Allocator>::construct_view(value_type* p,
+ Allocator& a) const
+ {
+ a.construct(p, (*m_functor)());
+ // In C++0x, the above should be written
+ // std::allocator_traits<Allocator>::construct(a, p, m_functor());
+ }
+
+ /**
+ * Functor called to reduce a holder
+ */
+ template <typename Type, holder_policy Policy>
+ struct holder_reduce_functor;
+
+ /**
+ * Specialization to keep the left (first) value.
+ */
+ template <typename Type>
+ struct holder_reduce_functor<Type, holder_keep_indeterminate>
+ {
+ void operator()(Type* left, Type* right) const { }
+ };
+
+ /**
+ * Specialization to copy-assign from the right (last) value.
+ */
+ template <typename Type>
+ struct holder_reduce_functor<Type, holder_keep_last_copy>
+ {
+ void operator()(Type* left, Type* right) const {
+ *left = *right;
+ }
+ };
+
+ /*
+ * Specialization to keep the right (last) value via swap.
+ */
+ template <typename Type>
+ struct holder_reduce_functor<Type, holder_keep_last_swap>
+ {
+ void operator()(Type* left, Type* right) const {
+ using std::swap;
+ swap(*left, *right);
+ }
+ };
+
+#ifdef __CILKRTS_RVALUE_REFERENCES
+ /*
+ * Specialization to move-assign from the right (last) value.
+ */
+ template <typename Type>
+ struct holder_reduce_functor<Type, holder_keep_last_move>
+ {
+ void operator()(Type* left, Type* right) const {
+ *left = std::move(*right);
+ }
+ };
+#endif
+
+ /*
+ * Specialization to keep the right (last) value via the swap member
+ * function.
+ */
+ template <typename Type>
+ struct holder_reduce_functor<Type, holder_keep_last_member_swap>
+ {
+ void operator()(Type* left, Type* right) const {
+ left->swap(*right);
+ }
+ };
+
+ /*
+ * Specialization to keep the right (last) value by the most efficient
+ * means detectable.
+ */
+ template <typename Type>
+ struct holder_reduce_functor<Type, holder_keep_last> :
+ holder_reduce_functor<Type,
+ (holder_policy)
+ (has_member_swap<Type>::value ?
+ holder_keep_last_member_swap :
+#ifdef __CILKRTS_RVALUE_REFERENCES
+ holder_keep_last_move
+#else
+ holder_keep_last_copy
+#endif
+ )>
+ {
+ };
+ } // end namespace internal
+
+ /**
+ * Monoid for holders.
+ * Allocator type is required to be thread-safe.
+ */
+ template <typename Type,
+ holder_policy Policy = holder_keep_indeterminate,
+ typename Allocator = std::allocator<Type> >
+ class holder_monoid : public monoid_base<Type>
+ {
+ // Allocator is mutable because the copy of the monoid inside the
+ // reducer is const (to avoid races on the shared state). However,
+ // the allocator is required to be thread-safe, so it is ok (and
+ // necessary) to modify.
+ mutable Allocator m_allocator;
+ internal::init_base<Type, Allocator> *m_initializer;
+
+ public:
+ /// This constructor uses default-initialization for both the leftmost
+ /// view and each identity view.
+ holder_monoid(const Allocator& a = Allocator())
+ : m_allocator(a)
+ , m_initializer(
+ internal::default_init<Type, Allocator>::make(m_allocator))
+ { }
+
+ /// These constructors use 'val' as an exemplar to copy-construct both
+ /// the leftmost view and each identity view.
+ holder_monoid(const Type& val, const Allocator& a = Allocator())
+ : m_allocator(a)
+ , m_initializer(internal::exemplar_init<Type, Allocator>::make(
+ val, m_allocator)) { }
+ /// This constructor uses 'f' as a functor to construct both
+ /// the leftmost view and each identity view.
+ template <typename Func>
+ holder_monoid(const Func& f, const Allocator& a = Allocator())
+ : m_allocator(a)
+ , m_initializer(
+ internal::functor_init<Func, Allocator>::make(f,m_allocator))
+ { }
+
+ /// Copy constructor
+ holder_monoid(const holder_monoid& rhs)
+ : m_allocator(rhs.m_allocator)
+ , m_initializer(rhs.m_initializer->clone_self(m_allocator)) { }
+
+ /// "Extended" copy constructor with allocator
+ holder_monoid(const holder_monoid& rhs, const Allocator& a)
+ : m_allocator(a)
+ , m_initializer(rhs.m_initializer->clone_self(m_allocator)) { }
+
+#ifdef __CILKRTS_RVALUE_REFERENCES
+ /// Move constructor
+ holder_monoid(holder_monoid&& rhs)
+ : m_allocator(rhs.m_allocator)
+ , m_initializer(rhs.m_initializer) {
+ rhs.m_initializer =
+ internal::default_init<Type, Allocator>::make(m_allocator);
+ }
+
+ /// "Extended" move constructor with allocator
+ holder_monoid(holder_monoid&& rhs, const Allocator& a)
+ : m_allocator(a)
+ , m_initializer(0) {
+ if (a != rhs.m_allocator)
+ m_initializer = rhs.m_initializer->clone_self(a);
+ else {
+ m_initializer = rhs.m_initializer;
+ rhs.m_initializer =
+ internal::default_init<Type, Allocator>::make(m_allocator);
+ }
+ }
+#endif
+ /// Destructor
+ ~holder_monoid() { m_initializer->delete_self(m_allocator); }
+
+ holder_monoid& operator=(const holder_monoid& rhs) {
+ if (this == &rhs) return *this;
+ m_initializer->delete_self(m_allocator);
+ m_initializer = rhs.m_initializer->clone_self(m_allocator);
+ }
+
+#ifdef __CILKRTS_RVALUE_REFERENCES
+ holder_monoid& operator=(holder_monoid&& rhs) {
+ if (m_allocator != rhs.m_allocator)
+ // Delegate to copy-assignment on unequal allocators
+ return operator=(static_cast<const holder_monoid&>(rhs));
+ std::swap(m_initializer, rhs.m_initializer);
+ return *this;
+ }
+#endif
+
+ /// Constructs IDENTITY value into the uninitilized '*p'
+ void identity(Type* p) const
+ { m_initializer->construct_view(p, m_allocator); }
+
+ /// Calls the destructor on the object pointed-to by 'p'
+ void destroy(Type* p) const
+ { m_allocator.destroy(p); }
+
+ /// Return a pointer to size bytes of raw memory
+ void* allocate(std::size_t s) const {
+ __CILKRTS_ASSERT(sizeof(Type) == s);
+ return m_allocator.allocate(1);
+ }
+
+ /// Deallocate the raw memory at p
+ void deallocate(void* p) const {
+ m_allocator.deallocate(static_cast<Type*>(p), sizeof(Type));
+ }
+
+ void reduce(Type* left, Type* right) const {
+ internal::holder_reduce_functor<Type, Policy>()(left, right);
+ }
+
+ void swap(holder_monoid& other) {
+ __CILKRTS_ASSERT(m_allocator == other.m_allocator);
+ std::swap(m_initializer, other.m_initializer);
+ }
+
+ Allocator get_allocator() const {
+ return m_allocator;
+ }
+ };
+
+ // Namespace-scope swap
+ template <typename Type, holder_policy Policy, typename Allocator>
+ inline void swap(holder_monoid<Type, Policy, Allocator>& a,
+ holder_monoid<Type, Policy, Allocator>& b)
+ {
+ a.swap(b);
+ }
+
+ /**
+ * Hyperobject to provide different views of an object to each
+ * parallel strand.
+ */
+ template <typename Type,
+ holder_policy Policy = holder_keep_indeterminate,
+ typename Allocator = std::allocator<Type> >
+ class holder : public reducer<holder_monoid<Type, Policy, Allocator> >
+ {
+ typedef holder_monoid<Type, Policy, Allocator> monoid_type;
+ typedef reducer<monoid_type> imp;
+
+ // Return a value of Type constructed using the functor Func.
+ template <typename Func>
+ Type make_value(const Func& f) const {
+ struct obj {
+ union {
+ char buf[sizeof(Type)];
+ void* align1;
+ double align2;
+ };
+
+ obj(const Func& f) { f(static_cast<Type*>(buf)); }
+ ~obj() { static_cast<Type*>(buf)->~Type(); }
+
+ operator Type&() { return *static_cast<Type*>(buf); }
+ };
+
+ return obj(f);
+ }
+
+ public:
+ /// Default constructor uses default-initialization for both the
+ /// leftmost view and each identity view.
+ holder(const Allocator& alloc = Allocator())
+ : imp(monoid_type(alloc)) { }
+
+ /// Construct from an exemplar that is used to initialize both the
+ /// leftmost view and each identity view.
+ holder(const Type& v, const Allocator& alloc = Allocator())
+ // Alas, cannot use an rvalue reference for 'v' because it is used
+ // twice in the same expression for initializing imp.
+ : imp(monoid_type(v, alloc), v) { }
+
+ /// Construct from a functor that is used to initialize both the
+ /// leftmost view and each identity view. The functor, 'f', must be be
+ /// invokable using the expression 'Type x = f()'.
+ template <typename Func>
+ holder(const Func& f, const Allocator& alloc = Allocator())
+ // Alas, cannot use an rvalue for 'f' because it is used twice in
+ // the same expression for initializing imp.
+ : imp(monoid_type(f, alloc), make_value(f)) { }
+ };
+
+} // end namespace cilk
+
+#else /* C */
+# error Holders are currently available only for C++
+#endif /* __cplusplus */
+
+#endif /* HOLDER_H_INCLUDED */
diff --git a/libcilkrts/include/cilk/hyperobject_base.h b/libcilkrts/include/cilk/hyperobject_base.h
new file mode 100644
index 00000000000..484bf5f01ea
--- /dev/null
+++ b/libcilkrts/include/cilk/hyperobject_base.h
@@ -0,0 +1,172 @@
+/*
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef INCLUDED_CILK_HYPEROBJECT_BASE
+#define INCLUDED_CILK_HYPEROBJECT_BASE
+
+#ifdef __cplusplus
+# include <cstdlib>
+# include <cstddef>
+#else
+# include <stdlib.h>
+# include <stddef.h>
+#endif
+
+#include <cilk/common.h>
+
+#if defined _WIN32 || defined _WIN64
+# if !defined CILK_STUB && !defined IN_CILK_RUNTIME
+ /* bring in the Cilk library, which has definitions for some of these
+ * functions. */
+# pragma comment(lib, "cilkrts")
+# endif
+#endif
+
+/* The __CILKRTS_STRAND_PURE attribute tells the compiler that the value
+ * returned by 'func' for a given argument to 'func' will remain valid until
+ * the next strand boundary (spawn or sync) or until the next call to a
+ * function with the __CILKRTS_STRAND_STALE attribute using the same function
+ * argument.
+ */
+#if 0 && defined __cilk && (defined __GNUC__ && !defined _WIN32) && defined __cilkartsrev
+# define __CILKRTS_STRAND_PURE(func) \
+ func __attribute__((__cilk_hyper__("lookup")))
+# define __CILKRTS_STRAND_STALE(func) \
+ func __attribute__((__cilk_hyper__("flush")))
+#else
+# define __CILKRTS_STRAND_PURE(func) func
+# define __CILKRTS_STRAND_STALE(func) func
+#endif
+
+/*****************************************************************************
+ * C runtime interface to the hyperobject subsystem
+ *****************************************************************************/
+
+__CILKRTS_BEGIN_EXTERN_C
+
+/* Callback function signatures. The 'r' argument always points to the
+ * reducer itself and is commonly ignored. */
+typedef void (*cilk_c_reducer_reduce_fn_t)(void* r, void* lhs, void* rhs);
+typedef void (*cilk_c_reducer_identity_fn_t)(void* r, void* view);
+typedef void (*cilk_c_reducer_destroy_fn_t)(void* r, void* view);
+typedef void* (*cilk_c_reducer_allocate_fn_t)(void* r, __STDNS size_t bytes);
+typedef void (*cilk_c_reducer_deallocate_fn_t)(void* r, void* view);
+
+/** Representation of the monoid */
+typedef struct cilk_c_monoid {
+ cilk_c_reducer_reduce_fn_t reduce_fn;
+ cilk_c_reducer_identity_fn_t identity_fn;
+ cilk_c_reducer_destroy_fn_t destroy_fn;
+ cilk_c_reducer_allocate_fn_t allocate_fn;
+ cilk_c_reducer_deallocate_fn_t deallocate_fn;
+} cilk_c_monoid;
+
+/** Base of the hyperobject */
+typedef struct __cilkrts_hyperobject_base
+{
+ cilk_c_monoid __c_monoid;
+ unsigned long long __flags;
+ __STDNS ptrdiff_t __view_offset; /* offset (in bytes) to leftmost view */
+ __STDNS size_t __view_size; /* Size of each view */
+} __cilkrts_hyperobject_base;
+
+
+#ifndef CILK_STUB
+
+/* Library functions. */
+CILK_EXPORT
+ void __cilkrts_hyper_create(__cilkrts_hyperobject_base *key);
+CILK_EXPORT void __CILKRTS_STRAND_STALE(
+ __cilkrts_hyper_destroy(__cilkrts_hyperobject_base *key));
+CILK_EXPORT void* __CILKRTS_STRAND_PURE(
+ __cilkrts_hyper_lookup(__cilkrts_hyperobject_base *key));
+
+CILK_EXPORT
+ void* __cilkrts_hyperobject_alloc(void* ignore, __STDNS size_t bytes);
+CILK_EXPORT
+ void __cilkrts_hyperobject_dealloc(void* ignore, void* view);
+
+/* No-op destroy function */
+CILK_EXPORT
+ void __cilkrts_hyperobject_noop_destroy(void* ignore, void* ignore2);
+
+
+#else // CILK_STUB
+
+// Programs compiled with CILK_STUB are not linked with the Cilk runtime
+// library, so they should not have external references to cilkrts functions.
+// Furthermore, they don't need the hyperobject functionality, so the
+// functions can be stubbed.
+
+#define __cilkrts_hyperobject_create __cilkrts_hyperobject_create__stub
+__CILKRTS_INLINE
+ void __cilkrts_hyper_create(__cilkrts_hyperobject_base *key)
+ {}
+
+#define __cilkrts_hyperobject_destroy __cilkrts_hyperobject_destroy__stub
+__CILKRTS_INLINE
+ void __cilkrts_hyper_destroy(__cilkrts_hyperobject_base *key)
+ {}
+
+#define __cilkrts_hyperobject_lookup __cilkrts_hyperobject_lookup__stub
+__CILKRTS_INLINE
+ void* __cilkrts_hyper_lookup(__cilkrts_hyperobject_base *key)
+ { return (char*)(key) + key->__view_offset; }
+
+// Pointers to these functions are stored into monoids, so real functions
+// are needed.
+
+#define __cilkrts_hyperobject_alloc __cilkrts_hyperobject_alloc__stub
+__CILKRTS_INLINE
+ void* __cilkrts_hyperobject_alloc(void* ignore, __STDNS size_t bytes)
+ { assert(0); return __STDNS malloc(bytes); }
+
+#define __cilkrts_hyperobject_dealloc __cilkrts_hyperobject_dealloc__stub
+__CILKRTS_INLINE
+ void __cilkrts_hyperobject_dealloc(void* ignore, void* view)
+ { assert(0); __STDNS free(view); }
+
+#define __cilkrts_hyperobject_noop_destroy \
+ __cilkrts_hyperobject_noop_destroy__stub
+__CILKRTS_INLINE
+ void __cilkrts_hyperobject_noop_destroy(void* ignore, void* ignore2)
+ {}
+
+#endif
+
+__CILKRTS_END_EXTERN_C
+
+#endif /* INCLUDED_CILK_HYPEROBJECT_BASE */
diff --git a/libcilkrts/include/cilk/metaprogramming.h b/libcilkrts/include/cilk/metaprogramming.h
new file mode 100644
index 00000000000..5f6f29df87b
--- /dev/null
+++ b/libcilkrts/include/cilk/metaprogramming.h
@@ -0,0 +1,606 @@
+/* metaprogramming.h -*- C++ -*-
+ *
+ * @copyright
+ * Copyright (C) 2012-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file metaprogramming.h
+ *
+ * @brief Defines metaprogramming utility classes used in the Cilk library.
+ *
+ * @ingroup common
+ */
+
+#ifndef METAPROGRAMMING_H_INCLUDED
+#define METAPROGRAMMING_H_INCLUDED
+
+#ifdef __cplusplus
+
+#include <functional>
+#include <new>
+#include <cstdlib>
+#ifdef _WIN32
+#include <malloc.h>
+#endif
+#include <algorithm>
+
+namespace cilk {
+
+namespace internal {
+
+/** Test if a class is empty.
+ *
+ * If @a Class is an empty (and therefore necessarily stateless) class, then
+ * the “empty base-class optimization†guarantees that
+ * `sizeof(check_for_empty_class<Class>) == sizeof(char)`. Conversely, if
+ * `sizeof(check_for_empty_class<Class>) > sizeof(char)`, then @a Class is not
+ * empty, and we must discriminate distinct instances of @a Class.
+ *
+ * Typical usage:
+ *
+ * // General definition of A<B> for non-empty B:
+ * template <typename B, bool BIsEmpty = class_is_empty<B>::value> >
+ * class A { ... };
+ *
+ * // Specialized definition of A<B> for empty B:
+ * template <typename B>
+ * class A<B, true> { ... };
+ *
+ * @tparam Class The class to be tested for emptiness.
+ *
+ * @result The `value` member will be `true` if @a Class is empty,
+ * `false` otherwise.
+ *
+ * @ingroup common
+ */
+template <class Class>
+class class_is_empty {
+ class check_for_empty_class : public Class
+ {
+ char m_data;
+ public:
+ // Declared but not defined
+ check_for_empty_class();
+ check_for_empty_class(const check_for_empty_class&);
+ check_for_empty_class& operator=(const check_for_empty_class&);
+ ~check_for_empty_class();
+ };
+public:
+
+ /** Constant is true if and only if @a Class is empty.
+ */
+ static const bool value = (sizeof(check_for_empty_class) == sizeof(char));
+};
+
+
+/** Get the alignment of a type.
+ *
+ * For example:
+ *
+ * align_of<double>::value == 8
+ *
+ * @tparam Tp The type whose alignment is to be computed.
+ *
+ * @result The `value` member of an instantiation of this class template
+ * will hold the integral alignment requirement of @a Tp.
+ *
+ * @pre @a Tp shall be a complete type.
+ *
+ * @ingroup common
+ */
+template <typename Tp>
+struct align_of
+{
+private:
+ struct imp {
+ char m_padding;
+ Tp m_val;
+
+ // The following declarations exist to suppress compiler-generated
+ // definitions, in case @a Tp does not have a public default
+ // constructor, copy constructor, or destructor.
+ imp(const imp&); // Declared but not defined
+ ~imp(); // Declared but not defined
+ };
+
+public:
+ /// The integral alignment requirement of @a Tp.
+ static const std::size_t value = (sizeof(imp) - sizeof(Tp));
+};
+
+
+/** A class containing raw bytes with a specified alignment and size.
+ *
+ * An object of type `aligned_storage<S, A>` will have alignment `A` and
+ * size at least `S`. Its contents will be uninitialized bytes.
+ *
+ * @tparam Size The required minimum size of the resulting class.
+ * @tparam Alignment The required alignment of the resulting class.
+ *
+ * @pre @a Alignment shall be a power of 2 no greater then 64.
+ *
+ * @note This is implemented using the `CILK_ALIGNAS` macro, which uses
+ * the non-standard, implementation-specific features
+ * `__declspec(align(N))` on Windows, and
+ * `__attribute__((__aligned__(N)))` on Unix. The `gcc` implementation
+ * of `__attribute__((__aligned__(N)))` requires a numeric literal `N`
+ * (_not_ an arbitrary compile-time constant expression). Therefore,
+ * this class is implemented using specialization on the required
+ * alignment.
+ *
+ * @note The template class is specialized only for the supported
+ * alignments. An attempt to instantiate it for an unsupported
+ * alignment will result in a compilation error.
+ */
+template <std::size_t Size, std::size_t Alignment>
+struct aligned_storage;
+
+template<std::size_t Size> class aligned_storage<Size, 1>
+ { CILK_ALIGNAS( 1) char m_bytes[Size]; };
+template<std::size_t Size> class aligned_storage<Size, 2>
+ { CILK_ALIGNAS( 2) char m_bytes[Size]; };
+template<std::size_t Size> class aligned_storage<Size, 4>
+ { CILK_ALIGNAS( 4) char m_bytes[Size]; };
+template<std::size_t Size> class aligned_storage<Size, 8>
+ { CILK_ALIGNAS( 8) char m_bytes[Size]; };
+template<std::size_t Size> class aligned_storage<Size, 16>
+ { CILK_ALIGNAS(16) char m_bytes[Size]; };
+template<std::size_t Size> class aligned_storage<Size, 32>
+ { CILK_ALIGNAS(32) char m_bytes[Size]; };
+template<std::size_t Size> class aligned_storage<Size, 64>
+ { CILK_ALIGNAS(64) char m_bytes[Size]; };
+
+
+/** A buffer of uninitialized bytes with the same size and alignment as a
+ * specified type.
+ *
+ * The class `storage_for_object<Type>` will have the same size and alignment
+ * properties as `Type`, but it will contain only raw (uninitialized) bytes.
+ * This allows the definition of a data member which can contain a `Type`
+ * object which is initialized explicitly under program control, rather
+ * than implicitly as part of the initialization of the containing class.
+ * For example:
+ *
+ * class C {
+ * storage_for_object<MemberClass> _member;
+ * public:
+ * C() ... // Does NOT initialize _member
+ * void initialize(args)
+ * { new (_member.pointer()) MemberClass(args); }
+ * const MemberClass& member() const { return _member.object(); }
+ * MemberClass& member() { return _member.object(); }
+ *
+ * @tparam Type The type whose size and alignment are to be reflected
+ * by this class.
+ */
+template <typename Type>
+class storage_for_object :
+ aligned_storage< sizeof(Type), align_of<Type>::value >
+{
+public:
+ /// Return a typed reference to the buffer.
+ const Type& object() const { return *reinterpret_cast<Type*>(this); }
+ Type& object() { return *reinterpret_cast<Type*>(this); }
+};
+
+
+/** Get the functor class corresponding to a binary function type.
+ *
+ * The `binary_functor` template class class can be instantiated with a binary
+ * functor class or with a real binary function, and will yield an equivalent
+ * binary functor class class in either case.
+ *
+ * @tparam F A binary functor class, a binary function type, or a pointer to
+ * binary function type.
+ *
+ * @result `binary_functor<F>::%type` will be the same as @a F if @a F is
+ * a class. It will be a `std::pointer_to_binary_function` wrapper
+ * if @a F is a binary function or binary function pointer type.
+ * (It will _not_ necessarily be an `Adaptable Binary Function`
+ * class, since @a F might be a non-adaptable binary functor
+ * class.)
+ *
+ * @ingroup common
+ */
+template <typename F>
+struct binary_functor {
+ /// The binary functor class equivalent to @a F.
+ typedef F type;
+};
+
+/// @copydoc binary_functor
+/// Specialization for binary function.
+template <typename R, typename A, typename B>
+struct binary_functor<R(A,B)> {
+ /// The binary functor class equivalent to @a F.
+ typedef std::pointer_to_binary_function<A, B, R> type;
+};
+
+/// @copydoc binary_functor
+/// Specialization for pointer to binary function.
+template <typename R, typename A, typename B>
+struct binary_functor<R(*)(A,B)> {
+ /// The binary functor class equivalent to @a F.
+ typedef std::pointer_to_binary_function<A, B, R> type;
+};
+
+
+/** Indirect binary function class with specified types.
+ *
+ * `typed_indirect_binary_function<F>` is an `Adaptable Binary Function` class
+ * based on an existing binary functor class or binary function type @a F. If
+ * @a F is a stateless class, then this class will be empty, and its
+ * `operator()` will invoke @a F’s `operator()`. Otherwise, an object of this
+ * class will hold a pointer to an object of type @a F, and will refer its
+ * `operator()` calls to the pointed-to @a F object.
+ *
+ * That is, suppose that we have the declarations:
+ *
+ * F *p;
+ * typed_indirect_binary_function<F, int, int, bool> ibf(p);
+ *
+ * Then:
+ *
+ * - `ibf(x, y) == (*p)(x, y)`.
+ * - `ibf(x, y)` will not do a pointer dereference if `F` is an empty class.
+ *
+ * @note Just to repeat: if `F` is an empty class, then
+ * `typed_indirect_binary_function\<F\>' is also an empty class.
+ * This is critical for its use in the @ref min_max::view_base
+ * "min/max reducer view classes", where it allows the view to
+ * call a comparison functor in the monoid without actually
+ * having to allocate a pointer in the view class when the
+ * comparison class is empty.
+ *
+ * @note If you have an `Adaptable Binary Function` class or a binary
+ * function type, then you can use the
+ * @ref indirect_binary_function class, which derives the
+ * argument and result types parameter type instead of requiring
+ * you to specify them as template arguments.
+ *
+ * @tparam F A binary functor class, a binary function type, or a pointer to
+ * binary function type.
+ * @param A1 The first argument type.
+ * @param A2 The second argument type.
+ * @param R The result type.
+ *
+ * @see min_max::comparator_base
+ * @see indirect_binary_function
+ *
+ * @ingroup common
+ */
+template < typename F
+ , typename A1
+ , typename A2
+ , typename R
+ , typename Functor = typename binary_functor<F>::type
+ , bool FunctorIsEmpty = class_is_empty<Functor>::value
+ >
+class typed_indirect_binary_function : std::binary_function<A1, A2, R>
+{
+ const F* f;
+public:
+ /// Constructor captures a pointer to the wrapped function.
+ typed_indirect_binary_function(const F* f) : f(f) {}
+
+ /// Return the comparator pointer, or `NULL` if the comparator is stateless.
+ const F* pointer() const { return f; }
+
+ /// Apply the pointed-to functor to the arguments.
+ R operator()(const A1& a1, const A2& a2) const { return (*f)(a1, a2); }
+};
+
+
+/// @copydoc typed_indirect_binary_function
+/// Specialization for an empty functor class. (This is only possible if @a F
+/// itself is an empty class. If @a F is a function or pointer-to-function
+/// type, then the functor will contain a pointer.)
+template <typename F, typename A1, typename A2, typename R, typename Functor>
+class typed_indirect_binary_function<F, A1, A2, R, Functor, true> :
+ std::binary_function<A1, A2, R>
+{
+public:
+ /// Return `NULL` for the comparator pointer of a stateless comparator.
+ const F* pointer() const { return 0; }
+
+ /// Constructor discards the pointer to a stateless functor class.
+ typed_indirect_binary_function(const F* f) {}
+
+ /// Create an instance of the stateless functor class and apply it to the arguments.
+ R operator()(const A1& a1, const A2& a2) const { return F()(a1, a2); }
+};
+
+
+/** Indirect binary function class with inferred types.
+ *
+ * This is identical to @ref typed_indirect_binary_function, except that it
+ * derives the binary function argument and result types from the parameter
+ * type @a F instead of taking them as additional template parameters. If @a F
+ * is a class type, then it must be an `Adaptable Binary Function`.
+ *
+ * @see typed_indirect_binary_function
+ *
+ * @ingroup common
+ */
+template <typename F, typename Functor = typename binary_functor<F>::type>
+class indirect_binary_function :
+ typed_indirect_binary_function< F
+ , typename Functor::first_argument_type
+ , typename Functor::second_argument_type
+ , typename Functor::result_type
+ >
+{
+ typedef typed_indirect_binary_function< F
+ , typename Functor::first_argument_type
+ , typename Functor::second_argument_type
+ , typename Functor::result_type
+ >
+ base;
+public:
+ indirect_binary_function(const F* f) : base(f) {} ///< Constructor
+};
+
+
+/** Choose a type based on a boolean constant.
+ *
+ * This metafunction is identical to C++11’s condition metafunction.
+ * It needs to be here until we can reasonably assume that users will be
+ * compiling with C++11.
+ *
+ * @tparam Cond A boolean constant.
+ * @tparam IfTrue A type.
+ * @tparam IfFalse A type.
+ * @result The `type` member will be a typedef of @a IfTrue if @a Cond
+ * is true, and a typedef of @a IfFalse if @a Cond is false.
+ *
+ * @ingroup common
+ */
+template <bool Cond, typename IfTrue, typename IfFalse>
+struct condition
+{
+ typedef IfTrue type; ///< The type selected by the condition.
+};
+
+/// @copydoc condition
+/// Specialization for @a Cond == `false`.
+template <typename IfTrue, typename IfFalse>
+struct condition<false, IfTrue, IfFalse>
+{
+ typedef IfFalse type; ///< The type selected by the condition.
+};
+
+
+/** @def __CILKRTS_STATIC_ASSERT
+ *
+ * @brief Compile-time assertion.
+ *
+ * Causes a compilation error if a compile-time constant expression is false.
+ *
+ * @par Usage example.
+ * This assertion is used in reducer_min_max.h to avoid defining
+ * legacy reducer classes that would not be binary-compatible with the
+ * same classes compiled with earlier versions of the reducer library.
+ *
+ * __CILKRTS_STATIC_ASSERT(
+ * internal::class_is_empty< internal::binary_functor<Compare> >::value,
+ * "cilk::reducer_max<Value, Compare> only works with an empty Compare class");
+ *
+ * @note In a C++11 compiler, this is just the language predefined
+ * `static_assert` macro.
+ *
+ * @note In a non-C++11 compiler, the @a Msg string is not directly included
+ * in the compiler error message, but it may appear if the compiler
+ * prints the source line that the error occurred on.
+ *
+ * @param Cond The expression to test.
+ * @param Msg A string explaining the failure.
+ *
+ * @ingroup common
+ */
+#if defined(__INTEL_CXX11_MODE__) || defined(__GXX_EXPERIMENTAL_CXX0X__)
+# define __CILKRTS_STATIC_ASSERT(Cond, Msg) static_assert(Cond, Msg)
+#else
+# define __CILKRTS_STATIC_ASSERT(Cond, Msg) \
+ typedef int __CILKRTS_STATIC_ASSERT_DUMMY_TYPE \
+ [::cilk::internal::static_assert_failure<(Cond)>::Success]
+
+/// @cond internal
+ template <bool> struct static_assert_failure { };
+ template <> struct static_assert_failure<true> { enum { Success = 1 }; };
+
+# define __CILKRTS_STATIC_ASSERT_DUMMY_TYPE \
+ __CILKRTS_STATIC_ASSERT_DUMMY_TYPE1(__cilkrts_static_assert_, __LINE__)
+# define __CILKRTS_STATIC_ASSERT_DUMMY_TYPE1(a, b) \
+ __CILKRTS_STATIC_ASSERT_DUMMY_TYPE2(a, b)
+# define __CILKRTS_STATIC_ASSERT_DUMMY_TYPE2(a, b) a ## b
+/// @endcond
+
+#endif
+
+/// @cond internal
+
+/** @name Aligned heap management.
+ */
+//@{
+
+/** Implementation-specific aligned memory allocation function.
+ *
+ * @param size The minimum number of bytes to allocate.
+ * @param alignment The required alignment (must be a power of 2).
+ * @return The address of a block of memory of at least @a size
+ * bytes. The address will be a multiple of @a alignment.
+ * `NULL` if the allocation fails.
+ *
+ * @see deallocate_aligned()
+ */
+inline void* allocate_aligned(std::size_t size, std::size_t alignment)
+{
+#ifdef _WIN32
+ return _aligned_malloc(size, alignment);
+#else
+#if defined(ANDROID) || defined(__ANDROID__)
+ return memalign(std::max(alignment, sizeof(void*)), size);
+#else
+ void* ptr;
+ return (posix_memalign(&ptr, std::max(alignment, sizeof(void*)), size) == 0) ? ptr : 0;
+#endif
+#endif
+}
+
+/** Implementation-specific aligned memory deallocation function.
+ *
+ * @param ptr A pointer which was returned by a call to alloc_aligned().
+ */
+inline void deallocate_aligned(void* ptr)
+{
+#ifdef _WIN32
+ _aligned_free(ptr);
+#else
+ std::free(ptr);
+#endif
+}
+
+/** Class to allocate and guard an aligned pointer.
+ *
+ * A new_aligned_pointer object allocates aligned heap-allocated memory when
+ * it is created, and automatically deallocates it when it is destroyed
+ * unless its `ok()` function is called.
+ *
+ * @tparam T The type of the object to allocate on the heap. The allocated
+ * will have the size and alignment of an object of type T.
+ */
+template <typename T>
+class new_aligned_pointer {
+ void* m_ptr;
+public:
+ /// Constructor allocates the pointer.
+ new_aligned_pointer() :
+ m_ptr(allocate_aligned(sizeof(T), internal::align_of<T>::value)) {}
+ /// Destructor deallocates the pointer.
+ ~new_aligned_pointer() { if (m_ptr) deallocate_aligned(m_ptr); }
+ /// Get the pointer.
+ operator void*() { return m_ptr; }
+ /// Return the pointer and release the guard.
+ T* ok() {
+ T* ptr = static_cast<T*>(m_ptr);
+ m_ptr = 0;
+ return ptr;
+ }
+};
+
+//@}
+
+/// @endcond
+
+} // namespace internal
+
+//@{
+
+/** Allocate an aligned data structure on the heap.
+ *
+ * `cilk::aligned_new<T>([args])` is equivalent to `new T([args])`, except
+ * that it guarantees that the returned pointer will be at least as aligned
+ * as the alignment requirements of type `T`.
+ *
+ * @ingroup common
+ */
+template <typename T>
+T* aligned_new()
+{
+ internal::new_aligned_pointer<T> ptr;
+ new (ptr) T();
+ return ptr.ok();
+}
+
+template <typename T, typename T1>
+T* aligned_new(const T1& x1)
+{
+ internal::new_aligned_pointer<T> ptr;
+ new (ptr) T(x1);
+ return ptr.ok();
+}
+
+template <typename T, typename T1, typename T2>
+T* aligned_new(const T1& x1, const T2& x2)
+{
+ internal::new_aligned_pointer<T> ptr;
+ new (ptr) T(x1, x2);
+ return ptr.ok();
+}
+
+template <typename T, typename T1, typename T2, typename T3>
+T* aligned_new(const T1& x1, const T2& x2, const T3& x3)
+{
+ internal::new_aligned_pointer<T> ptr;
+ new (ptr) T(x1, x2, x3);
+ return ptr.ok();
+}
+
+template <typename T, typename T1, typename T2, typename T3, typename T4>
+T* aligned_new(const T1& x1, const T2& x2, const T3& x3, const T4& x4)
+{
+ internal::new_aligned_pointer<T> ptr;
+ new (ptr) T(x1, x2, x3, x4);
+ return ptr.ok();
+}
+
+template <typename T, typename T1, typename T2, typename T3, typename T4, typename T5>
+T* aligned_new(const T1& x1, const T2& x2, const T3& x3, const T4& x4, const T5& x5)
+{
+ internal::new_aligned_pointer<T> ptr;
+ new (ptr) T(x1, x2, x3, x4, x5);
+ return ptr.ok();
+}
+
+//@}
+
+
+/** Deallocate an aligned data structure on the heap.
+ *
+ * `cilk::aligned_delete(ptr)` is equivalent to `delete ptr`, except that it
+ * operates on a pointer that was allocated by aligned_new().
+ *
+ * @ingroup common
+ */
+template <typename T>
+void aligned_delete(const T* ptr)
+{
+ ptr->~T();
+ internal::deallocate_aligned((void*)ptr);
+}
+
+} // namespace cilk
+
+#endif // __cplusplus
+
+#endif // METAPROGRAMMING_H_INCLUDED
diff --git a/libcilkrts/include/cilk/reducer.h b/libcilkrts/include/cilk/reducer.h
new file mode 100644
index 00000000000..a22651e1e6f
--- /dev/null
+++ b/libcilkrts/include/cilk/reducer.h
@@ -0,0 +1,1900 @@
+/* reducer.h -*- C++ -*-
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file reducer.h
+ *
+ * @brief Defines foundation classes for creating Cilk reducers.
+ *
+ * @ingroup Reducers
+ *
+ * @see @ref pagereducers
+ *
+ * @defgroup Reducers Reducers
+ */
+
+#ifndef REDUCER_H_INCLUDED
+#define REDUCER_H_INCLUDED
+
+#include "cilk/hyperobject_base.h"
+#include "cilk/metaprogramming.h"
+
+#ifdef __cplusplus
+
+//===================== C++ interfaces ===================================
+
+#include <new>
+
+namespace cilk {
+
+/** Base class for defining monoids.
+ *
+ * The monoid_base class template is useful for creating classes that model
+ * the monoid concept. It provides the core type and memory management
+ * functionality. A subclass of monoid_base need only declare and implement
+ * the `identity` and `reduce` functions.
+ *
+ * The monoid_base class also manages the integration between the monoid, the
+ * reducer class that is based on it, and an optional view class which wraps
+ * value objects and restricts access to their operations.
+ *
+ * @tparam Value The value type for the monoid.
+ * @tparam View An optional view class that serves as a proxy for the value
+ * type.
+ *
+ * @see monoid_with_view
+ */
+template <typename Value, typename View = Value>
+class monoid_base
+{
+protected:
+
+ /** Class for provisionally constructed objects.
+ *
+ * The monoid_base::construct() functions manually construct both a monoid
+ * and a view. If one of these is constructed successfully, and the
+ * construction of the other (or some other initialization) fails, then
+ * the first one must be destroyed to avoid a memory leak. Because the
+ * construction is explicit, the destruction must be explicit, too.
+ *
+ * A provisional_guard object wraps a pointer to a newly constructed
+ * object. A call to its confirm() function confirms that the object is
+ * really going to be used. If the guard is destroyed without being
+ * confirmed, then the pointed-to object is destroyed (but not
+ * deallocated).
+ *
+ * Expected usage:
+ *
+ * provisional_guard<T1> x1_provisional( new (x1) T1() );
+ * … more initialization …
+ * x1_provisional.confirm();
+ *
+ * or
+ *
+ * provisional_guard<T1> x1_provisional( new (x1) T1() );
+ * x1_provisional.confirm_if( new (x2) T2() );
+ *
+ * If an exception is thrown in the “more initialization†code in the
+ * first example, or in the `T2` constructor in the second example, then
+ * `x1_provisional` will not be confirmed, so when its destructor is
+ * called during exception unwinding, the `T1` object that was constructed
+ * in `x1` will be destroyed.
+ *
+ * @see provisional()
+ *
+ * @tparam Type The type of the provisionally constructed object.
+ */
+ template <typename Type>
+ class provisional_guard {
+ Type* m_ptr;
+
+ public:
+
+ /** Constructor. Creates a guard for a provisionally constructed object.
+ *
+ * @param ptr A pointer to the provisionally constructed object.
+ */
+ provisional_guard(Type* ptr) : m_ptr(ptr) {}
+
+ /** Destructor. Destroy the object pointed to by the contained pointer
+ * if it has not been confirmed.
+ */
+ ~provisional_guard() { if (m_ptr) m_ptr->~Type(); }
+
+ /** Confirm the provisional construction. Do *not* delete the contained
+ * pointer when the guard is destroyed.
+ */
+ void confirm() { m_ptr = 0; }
+
+ /** Confirm provisional construction if argument is non-null. Note that
+ * if an exception is thrown during evaluation of the argument
+ * expression, then this function will not be called, and the
+ * provisional object will not be confirmed. This allows the usage:
+ *
+ * x1_provisional.confirm_if( new (x2) T2() );
+ *
+ * @param cond An arbitrary pointer. The provisional object will be
+ * confirmed if @a cond is not null.
+ *
+ * @returns The value of the @a cond argument.
+ */
+ template <typename Cond>
+ Cond* confirm_if(Cond* cond) { if (cond) m_ptr = 0; return cond; }
+ };
+
+
+ /** Create a provisional_guard object. This function allows simpler code
+ * when the only use of a provisional_guard is in a
+ * provisional_guard::confirm_if() call immediately following its
+ * creation. Instead of
+ *
+ * provisional_guard<T>guard( new (ptr_to_T) T() );
+ * guard.confirm_if( new (ptr_to_U) U() );
+ *
+ * you can just write
+ *
+ * provisional( new (ptr_to_T) T() ).confirm_if( new (ptr_to_U) U() );
+ *
+ * @tparam Type The type of the provisionally constructed object.
+ *
+ * @param ptr A pointer to a provisionally constructed object.
+ *
+ * @returns A @ref provisional_guard object that guards the
+ * provisionally constructed object pointed to by @a ptr.
+ */
+ template <typename Type>
+ static provisional_guard<Type> provisional(Type* ptr)
+ { return provisional_guard<Type>(ptr); }
+
+public:
+
+ /** Value type of the monoid.
+ */
+ typedef Value value_type;
+
+ /** View type of the monoid. Defaults to be the same as the value type.
+ * @see monoid_with_view
+ */
+ typedef View view_type;
+
+ enum {
+ /** Should reducers created with this monoid be aligned?
+ *
+ * @details
+ * “Aligned†means that the view is allocated at a cache-line aligned
+ * offset in the reducer, and the reducer must be cache-line aligned.
+ * “Unaligned†means that the reducer as a whole is just naturally
+ * aligned, but it contains a large enough block of uninitialized
+ * storage for a cache-line aligned view to be allocated in it at
+ * reducer construction time.
+ *
+ * Since the standard heap allocator (new reducer) does not allocate
+ * cache-line aligned storage, only unaligned reducers can be safely
+ * allocated on the heap.
+ *
+ * Default is false (unaligned) unless overridden in a subclass.
+ *
+ * @since 1.02
+ * (In Cilk library versions 1.0 and 1.01, the default was true.
+ * In Cilk library versions prior to 1.0, reducers were always aligned,
+ * and this data member did not exist.)
+ */
+ align_reducer = false
+ };
+
+ /** Destroy a view. Destroys (without deallocating) the @a View object
+ * pointed to by @a p.
+ *
+ * @param p The address of the @a View object to be destroyed.
+ */
+ void destroy(view_type* p) const { p->~view_type(); }
+
+ /** Allocate raw memory. Allocate @a s bytes of memory with no
+ * initialization.
+ *
+ * @param s The number of bytes of memory to allocate.
+ * @return An untyped pointer to the allocated memory.
+ */
+ void* allocate(size_t s) const { return operator new(s); }
+
+ /** Deallocate raw memory. Deallocates the memory pointed to by @a p
+ * without doing any destruction.
+ *
+ * @param p Pointer to the memory to be deallocated.
+ *
+ * @pre @a p points to a block of memory that was allocated by a
+ * call to allocate().
+ */
+ void deallocate(void* p) const { operator delete(p); }
+
+ /** Create the identity value. Constructs (without allocating) a @a View
+ * object representing the default value of the @a Value type.
+ *
+ * @param p A pointer to a block of raw memory large enough to hold a
+ * @a View object.
+ *
+ * @post The memory pointed to by @a p contains a @a View object that
+ * represents the default value of the @a View type.
+ *
+ * @deprecated This function constructs the @a View object with its default
+ * constructor, which will often, but not always, yield the
+ * appropriate identity value. Monoid classes should declare
+ * their identity function explicitly, rather than relying on
+ * this default definition.
+ */
+ void identity(View* p) const { new ((void*) p) View(); }
+
+
+ /** @name Construct the monoid and the view with arbitrary arguments.
+ *
+ * A @ref reducer object contains monoid and view data members, which are
+ * declared as raw storage (byte arrays), so that they are not implicitly
+ * constructed when the reducer is constructed. Instead, a reducer
+ * constructor calls one of the monoid class’s static construct()
+ * functions with the addresses of the monoid and the view, and the
+ * construct() function uses placement `new` to construct them.
+ *
+ * This allows the monoid to determine the order in which the monoid and
+ * view are constructed, and to make one of them dependent on the other.
+ *
+ * Any arguments to the reducer constructor are just passed on as
+ * additional arguments to the construct() function (after the monoid
+ * and view addresses).
+ *
+ * Any monoid whose needs are satisfied by the suite of construct()
+ * functions below, such as @ref monoid_with_view, can just inherit them
+ * from monoid_base. Other monoids will need to provide their own versions
+ * to override the monoid_base functions.
+ */
+ //@{
+
+ /** Default-construct the monoid, and pass zero to five const reference
+ * arguments to the view constructor.
+ */
+ //@{
+
+ template <typename Monoid>
+ static void construct(Monoid* monoid, View* view)
+ { provisional( new ((void*)monoid) Monoid() ).confirm_if(
+ (monoid->identity(view), view) ); }
+
+ template <typename Monoid, typename T1>
+ static void construct(Monoid* monoid, View* view, const T1& x1)
+ { provisional( new ((void*)monoid) Monoid() ).confirm_if(
+ new ((void*)view) View(x1) ); }
+
+ template <typename Monoid, typename T1, typename T2>
+ static void construct(Monoid* monoid, View* view,
+ const T1& x1, const T2& x2)
+ { provisional( new ((void*)monoid) Monoid() ).confirm_if(
+ new ((void*)view) View(x1, x2) ); }
+
+ template <typename Monoid, typename T1, typename T2, typename T3>
+ static void construct(Monoid* monoid, View* view,
+ const T1& x1, const T2& x2, const T3& x3)
+ { provisional( new ((void*)monoid) Monoid() ).confirm_if(
+ new ((void*)view) View(x1, x2, x3) ); }
+
+ template <typename Monoid, typename T1, typename T2, typename T3,
+ typename T4>
+ static void construct(Monoid* monoid, View* view,
+ const T1& x1, const T2& x2, const T3& x3,
+ const T4& x4)
+ { provisional( new ((void*)monoid) Monoid() ).confirm_if(
+ new ((void*)view) View(x1, x2, x3, x4) ); }
+
+ template <typename Monoid, typename T1, typename T2, typename T3,
+ typename T4, typename T5>
+ static void construct(Monoid* monoid, View* view,
+ const T1& x1, const T2& x2, const T3& x3,
+ const T4& x4, const T5& x5)
+ { provisional( new ((void*)monoid) Monoid() ).confirm_if(
+ new ((void*)view) View(x1, x2, x3, x4, x5) ); }
+
+ //@}
+
+ /** Default-construct the monoid, and pass one non-const reference argument
+ * to the view constructor.
+ */
+ //@{
+ template <typename Monoid, typename T1>
+ static void construct(Monoid* monoid, View* view, T1& x1)
+ { provisional( new ((void*)monoid) Monoid() ).confirm_if(
+ new ((void*)view) View(x1) ); }
+ //@}
+
+ /** Copy-construct the monoid, and pass zero to four const reference
+ * arguments to the view constructor.
+ */
+ //@{
+
+ template <typename Monoid>
+ static void construct(Monoid* monoid, View* view, const Monoid& m)
+ { provisional( new ((void*)monoid) Monoid(m) ).confirm_if(
+ new ((void*)view) View() ); }
+
+ template <typename Monoid, typename T1>
+ static void construct(Monoid* monoid, View* view, const Monoid& m,
+ const T1& x1)
+ { provisional( new ((void*)monoid) Monoid(m) ).confirm_if(
+ new ((void*)view) View(x1) ); }
+
+ template <typename Monoid, typename T1, typename T2>
+ static void construct(Monoid* monoid, View* view, const Monoid& m,
+ const T1& x1, const T2& x2)
+ { provisional( new ((void*)monoid) Monoid(m) ).confirm_if(
+ new ((void*)view) View(x1, x2) ); }
+
+ template <typename Monoid, typename T1, typename T2, typename T3>
+ static void construct(Monoid* monoid, View* view, const Monoid& m,
+ const T1& x1, const T2& x2, const T3& x3)
+ {
+ provisional( new ((void*)monoid) Monoid(m) ).confirm_if(
+ new ((void*)view) View(x1, x2, x3) );
+ }
+
+ template <typename Monoid, typename T1, typename T2, typename T3,
+ typename T4>
+ static void construct(Monoid* monoid, View* view, const Monoid& m,
+ const T1& x1, const T2& x2, const T3& x3,
+ const T4& x4)
+ {
+ provisional( new ((void*)monoid) Monoid(m) ).confirm_if(
+ new ((void*)view) View(x1, x2, x3, x4) );
+ }
+
+ //@}
+
+ //@}
+};
+
+
+/** Monoid class that gets its value type and identity and reduce operations
+ * from its view.
+ *
+ * A simple implementation of the monoid-view-reducer architecture would
+ * distribute knowledge about the type and operations for the reduction
+ * between the monoid and the view — the identity and reduction operations are
+ * specified in the monoid, the reduction operations are implemented in the
+ * view, and the value type is specified in both the monoid and the view.
+ * This is inelegant.
+ *
+ * monoid_with_view is a subclass of @ref monoid_base that gets its value type
+ * and its identity and reduction operations from its view class. No
+ * customization of the monoid_with_view class itself is needed beyond
+ * instantiating it with an appropriate view class. (Customized subclasses of
+ * monoid_with_view may be needed for other reasons, such as to keep some
+ * state for the reducer.) All of the Cilk predefined reducers use
+ * monoid_with_view or one of its subclasses.
+ *
+ * The view class `View` of a monoid_with_view must provide the following public definitions:
+ *
+ * Definition | Meaning
+ * ---------------------------------|--------
+ * `value_type` | a typedef of the value type for the reduction
+ * `View()` | a default constructor which constructs the identity value for the reduction
+ * `void reduce(const View* other)` | a member function which applies the reduction operation to the values of `this` view and the `other` view, leaving the result as the value of `this` view, and leaving the value of the `other` view undefined (but valid)
+ *
+ * @tparam View The view class for the monoid.
+ * @tparam Align If true, reducers instantiated on this monoid will be
+ * cache-aligned. By default, library reducers (unlike legacy
+ * library reducer _wrappers_) are aligned only as required by
+ * contents.
+ */
+template <class View, bool Align = false>
+class monoid_with_view : public monoid_base<typename View::value_type, View>
+{
+public:
+ /** Should reducers created with this monoid be aligned?
+ */
+ enum { align_reducer = Align };
+
+ /** Create the identity value.
+ *
+ * Implements the monoid `identity` operation by using the @a View class’s
+ * default constructor.
+ *
+ * @param p A pointer to a block of raw memory large enough to hold a
+ * @p View object.
+ */
+ void identity(View* p) const { new ((void*)p) View(); }
+
+ /** Reduce the values of two views.
+ *
+ * Implements the monoid `reduce` operation by calling the left view’s
+ * `%reduce()` function with the right view as an operand.
+ *
+ * @param left The left operand of the reduce operation.
+ * @param right The right operand of the reduce operation.
+ * @post The left view contains the result of the reduce
+ * operation, and the right view is undefined.
+ */
+ void reduce(View* left, View* right) const { left->reduce(right); }
+};
+
+
+/** Base class for simple views with (usually) scalar values.
+ *
+ * The scalar_view class is intended as a base class which provides about half
+ * of the required definitions for simple views. It defines the `value_type`
+ * required by a @ref monoid_with_view (but not the identity constructor and
+ * reduce operation, which are inherently specific to a particular kind of
+ * reduction). It also defines the value access functions which will be called
+ * by the corresponding @ref reducer functions. (It uses copy semantics for
+ * the view_move_in() and view_move_out() functions, which is appropriate
+ * for simple scalar types, but not necessarily for more complex types like
+ * STL containers.
+ *
+ * @tparam Type The type of value wrapped by the view.
+ */
+template <typename Type>
+class scalar_view
+{
+protected:
+ Type m_value; ///< The wrapped accumulator variable.
+
+public:
+ /** Value type definition required by @ref monoid_with_view.
+ */
+ typedef Type value_type;
+
+ /** Default constructor.
+ */
+ scalar_view() : m_value() {}
+
+ /** Value constructor.
+ */
+ scalar_view(const Type& v) : m_value(v) {}
+
+ /** @name Value functions required by the reducer class.
+ *
+ * Note that the move in/out functions use simple assignment semantics.
+ */
+ //@{
+
+ /** Set the value of the view.
+ */
+ void view_move_in(Type& v) { m_value = v; }
+
+ /** Get the value of the view.
+ */
+ void view_move_out(Type& v) { v = m_value; }
+
+ /** Set the value of the view.
+ */
+ void view_set_value(const Type& v) { m_value = v; }
+
+ /** Get the value of the view.
+ */
+ Type const& view_get_value() const { return m_value; }
+
+ /** Get a reference to the value contained in the view. For legacy
+ * reducer support only.
+ */
+ Type & view_get_reference() { return m_value; }
+
+ /** Get a reference to the value contained in the view. For legacy
+ * reducer support only.
+ */
+ Type const& view_get_reference() const { return m_value; }
+ //@}
+};
+
+
+/** Wrapper class for move-in construction.
+ *
+ * Some types allow their values to be _moved_ as an alternative to copying.
+ * Moving a value may be much faster than copying it, but may leave the value
+ * of the move’s source undefined. Consider the `swap` operation provided by
+ * many STL container classes:
+ *
+ * list<T> x, y;
+ * x = y; // Copy
+ * x.swap(y); // Move
+ *
+ * The assignment _copies_ the value of `y` into `x` in time linear in the
+ * size of `y`, leaving `y` unchanged. The `swap` _moves_ the value of `y`
+ * into `x` in constant time, but it also moves the value of `x` into `y`,
+ * potentially leaving `y` undefined.
+ *
+ * A move_in_wrapper simply wraps a pointer to an object. It is created by a
+ * call to cilk::move_in(). Passing a move_in_wrapper to a view constructor
+ * (actually, passing it to a reducer constructor, which passes it to the
+ * monoid `construct()` function, which passes it to the view constructor)
+ * allows, but does not require, the value pointed to by the wrapper to be
+ * moved into the view instead of copied.
+ *
+ * A view class exercises this option by defining a _move-in constructor_,
+ * i.e., a constructor with a move_in_wrapper parameter. The constructor calls
+ * the wrapper’s `value()` function to get a reference to its pointed-to
+ * value, and can then use that reference in a move operation.
+ *
+ * A move_in_wrapper also has an implicit conversion to its pointed-to value,
+ * so if a view class does not define a move-in constructor, its ordinary
+ * value constructor will be called with the wrapped value. For example, an
+ * @ref ReducersAdd "op_add" view does not have a move-in constructor, so
+ *
+ * int x;
+ * reducer< op_add<int> > xr(move_in(x));
+ *
+ * will simply call the `op_add_view(const int &)` constructor. But an
+ * @ref ReducersList "op_list_append" view does have a move-in constructor,
+ * so
+ *
+ * list<int> x;
+ * reducer< op_list_append<int> > xr(move_in(x));
+ *
+ * will call the `op_list_append_view(move_in_wrapper<int>)` constructor,
+ * which can `swap` the value of `x` into the view.
+ *
+ * @note Remember that passing the value of a variable to a reducer
+ * constructor using a move_in_wrapper leaves the variable undefined.
+ * You cannot assume that the constructor either will or will not copy
+ * or move the value.
+ *
+ * @tparam Type The type of the wrapped value.
+ *
+ * @see cilk::move_in()
+ */
+template <typename Type>
+class move_in_wrapper
+{
+ Type *m_pointer;
+public:
+
+ /** Constructor that captures the address of its argument. This is almost
+ * always called from the @ref move_in function.
+ */
+ explicit move_in_wrapper(Type& ref) : m_pointer(&ref) { }
+
+ /** Implicit conversion to the wrapped value. This allows a move_in_wrapper
+ * to be used where a value of the wrapped type is expected, in which case
+ * the wrapper is completely transparent.
+ */
+ operator Type&() const { return *m_pointer; }
+
+ /** Get a reference to the pointed-to value. This has the same effect as
+ * the implicit conversion, but makes the intent clearer in a move-in
+ * constructor.
+ */
+ Type& value() const { return *m_pointer; }
+};
+
+/** Function to create a move_in_wrapper for a value.
+ *
+ * @tparam Type The type of the argument, which will be the `type` of the
+ * created wrapper.
+ *
+ * @see move_in_wrapper
+ */
+template <typename Type>
+inline
+move_in_wrapper<Type> move_in(Type& ref)
+ { return move_in_wrapper<Type>(ref); }
+
+
+/** @copydoc move_in(Type&)
+ *
+ * @note Applying a function that is explicitly specified as modifying its
+ * argument to a const argument is obviously an irrational thing to
+ * do. This move_in() variant is just provided to allow calling a
+ * move-in constructor with a function return value, which the
+ * language treats as a const. Using it for any other purpose will
+ * probably end in tears.
+ */
+template <typename Type>
+inline
+move_in_wrapper<Type> move_in(const Type& ref)
+ { return move_in_wrapper<Type>(ref); }
+
+
+/** Wrapper class to allow implicit downcasts to reducer subclasses.
+ *
+ * The Cilk library contains a collection of reducer wrapper classes which
+ * were created before the `cilk::reducer<Monoid>` style was developed. For
+ * example, `cilk::reducer_opadd<Type>` provided essentially the same
+ * functionality that is now provided by
+ * `cilk::reducer< cilk::op_add<Type> >`. These legacy reducer classes are
+ * deprecated, but still supported, and they have been reimplemented as
+ * subclasses of the corresponding `cilk::reducer` classes. For example:
+ *
+ * template <class T>
+ * reducer_opadd<T> : public reducer< op_add<T> > { ... };
+ *
+ * This reimplementation allows transparent conversion between legacy and
+ * new reducers. That is, a `reducer<op_add>*` or `reducer<op_add>&` can be
+ * used anywhere that a `reducer_opadd*` or `reducer_opadd&` is expected,
+ * and vice versa.
+ *
+ * The conversion from the legacy reducer to the new reducer is just an
+ * up-cast, which is provided for free by C++. The conversion from the new
+ * reducer to the legacy reducer is a down-cast, though, which requires an
+ * explicit conversion member function in the `reducer` class. The challenge
+ * is to define a function in the reducer template class which will convert
+ * each cilk::reducer specialization to the corresponding legacy reducer,
+ * if there is one.
+ *
+ * The trick is in the legacy_reducer_downcast template class, which provides
+ * a mapping from `cilk::reducer` specializations to legacy reducer classes.
+ * `reducer<Monoid>` has a conversion function to convert itself to
+ * `legacy_reducer_downcast< reducer<Monoid> >::%type`. By default,
+ * `legacy_reducer_downcast<Reducer>::%type` is just a trivial subclass of
+ * `Reducer`, which is uninteresting, but a reducer with a legacy counterpart
+ * will have a specialization of `legacy_reducer_downcast` whose `type` is
+ * the corresponding legacy reducer. For example:
+ *
+ * template <typename Type>
+ * struct legacy_reducer_downcast< reducer< op_add<Type> > >
+ * {
+ * typedef reducer_opadd<Type> type;
+ * };
+ *
+ *
+ * @tparam Reducer The new-style reducer class whose corresponding legacy reducer class
+ * is `type`, if there is such a legacy reducer class.
+ */
+template <typename Reducer>
+struct legacy_reducer_downcast
+{
+ /** The related legacy reducer class.
+ *
+ * By default, this is just a trivial subclass of Reducer, but it can be
+ * overridden in the specialization of legacy_reducer_downcast for
+ * a reducer that has a corresponding legacy reducers.
+ */
+ struct type : Reducer { };
+};
+
+
+namespace internal {
+/// @cond internal
+
+template <typename Value, typename View>
+struct reducer_set_get
+{
+ static View theView; // Declared but not defined
+
+ // sizeof(notchar) is guaranteed larger than 1
+ struct notchar { char x[2]; };
+
+ // check_for_ref returns char if 'get_value' returns by value and notchar
+ // if 'get_value' returns by reference.
+ static char check_for_ref(Value, ...);
+ static notchar check_for_ref(Value&, int);
+
+ enum { GET_VALUE_BY_VALUE =
+ (1 == sizeof(check_for_ref(theView.view_get_value(), 0))) } ;
+
+ typedef typename condition<GET_VALUE_BY_VALUE,
+ Value, const Value&>::type get_value_type;
+
+ static void move_in(View& view, Value& v) { view.view_move_in(v); }
+ static void move_out(View& view, Value& v) { view.view_move_out(v); }
+
+ static void set_value(View& view, const Value& v)
+ { view.view_set_value(v); }
+
+ static get_value_type get_value(const View& view)
+ { return view.view_get_value(); }
+};
+
+template <typename Value>
+struct reducer_set_get<Value, Value>
+{
+ typedef const Value& get_value_type;
+
+ static void move_in(Value& view, Value& v) { view = v; }
+ static void move_out(Value& view, Value& v) { v = view; }
+
+ static void set_value(Value& view, const Value& v) { view = v; }
+
+ static get_value_type get_value(const Value& view) { return view; }
+};
+
+/// @endcond
+
+
+/** Base class defining the data layout that is common to all reducers.
+ */
+template <typename Monoid>
+class reducer_base {
+ typedef typename Monoid::view_type view_type;
+
+ // This makes the reducer a hyper-object. (Partially initialized in
+ // the derived reducer_content class.)
+ //
+ __cilkrts_hyperobject_base m_base;
+
+ // The monoid is allocated here as raw bytes, and is constructed explicitly
+ // by a call to the monoid_type::construct() function in the constructor of
+ // the `reducer` subclass.
+ //
+ storage_for_object<Monoid> m_monoid;
+
+ // Used for sanity checking at destruction.
+ //
+ void* m_initialThis;
+
+ // The leftmost view comes next. It is defined in the derived
+ // reducer_content class.
+
+ /** @name C-callable wrappers for the C++-coded monoid dispatch functions.
+ */
+ //@{
+
+ static void reduce_wrapper(void* r, void* lhs, void* rhs);
+ static void identity_wrapper(void* r, void* view);
+ static void destroy_wrapper(void* r, void* view);
+ static void* allocate_wrapper(void* r, __STDNS size_t bytes);
+ static void deallocate_wrapper(void* r, void* view);
+
+ //@}
+
+protected:
+
+ /** Constructor.
+ *
+ * @param leftmost The address of the leftmost view in the reducer.
+ */
+ reducer_base(char* leftmost)
+ {
+ static const cilk_c_monoid c_monoid_initializer = {
+ (cilk_c_reducer_reduce_fn_t) &reduce_wrapper,
+ (cilk_c_reducer_identity_fn_t) &identity_wrapper,
+ (cilk_c_reducer_destroy_fn_t) &destroy_wrapper,
+ (cilk_c_reducer_allocate_fn_t) &allocate_wrapper,
+ (cilk_c_reducer_deallocate_fn_t) &deallocate_wrapper
+ };
+
+ m_base.__c_monoid = c_monoid_initializer;
+ m_base.__flags = 0;
+ m_base.__view_offset = (char*)leftmost - (char*)this;
+ m_base.__view_size = sizeof(view_type);
+ m_initialThis = this;
+
+ __cilkrts_hyper_create(&m_base);
+ }
+
+ /** Destructor.
+ */
+ __CILKRTS_STRAND_STALE(~reducer_base())
+ {
+ // Make sure we haven't been memcopy'd or corrupted
+ __CILKRTS_ASSERT(
+ this == m_initialThis ||
+ // Allow for a layout bug that may put the initialThis field one
+ // word later in 1.0 reducers than in 0.9 and 1.1 reducers.
+ this == *(&m_initialThis + 1)
+ );
+ __cilkrts_hyper_destroy(&m_base);
+ }
+
+ /** Monoid data member.
+ *
+ * @return A pointer to the reducer’s monoid data member.
+ */
+ Monoid* monoid_ptr() { return &m_monoid.object(); }
+
+ /** Leftmost view data member.
+ *
+ * @return A pointer to the reducer’s leftmost view data member.
+ *
+ * @note This function returns the address of the *leftmost* view,
+ * which is unique for the lifetime of the reducer. It is
+ * intended to be used in constructors and destructors.
+ * Use the reducer::view() function to access the per-strand
+ * view instance.
+ */
+ view_type* leftmost_ptr()
+ {
+ char* view_addr = (char*)this + m_base.__view_offset;
+ return reinterpret_cast<view_type*>(view_addr);
+ }
+
+public:
+
+ /** @name Access the current view.
+ *
+ * These functions return a reference to the instance of the reducer’s
+ * view that was created for the current strand of a parallel computation
+ * (and create it if it doesn’t already exist). Note the difference from
+ * the (private) leftmost_ptr() function, which returns a pointer to the
+ * _leftmost_ view, which is the same in all strands.
+ */
+ //@{
+
+ /** Per-strand view instance.
+ *
+ * @return A reference to the per-strand view instance.
+ */
+ view_type& view()
+ {
+ return *static_cast<view_type *>(__cilkrts_hyper_lookup(&m_base));
+ }
+
+ /** @copydoc view()
+ */
+ const view_type& view() const
+ {
+ return const_cast<reducer_base*>(this)->view();
+ }
+
+ //@}
+
+ /** Initial view pointer field.
+ *
+ * @internal
+ *
+ * @return a reference to the m_initialThis field.
+ *
+ * @note This function is provided for “white-box†testing of the
+ * reducer layout code. There is never any reason for user code
+ * to call it.
+ */
+ const void* const & initial_this() const { return m_initialThis; }
+};
+
+template <typename Monoid>
+void reducer_base<Monoid>::reduce_wrapper(void* r, void* lhs, void* rhs)
+{
+ Monoid* monoid = static_cast<reducer_base*>(r)->monoid_ptr();
+ monoid->reduce(static_cast<view_type*>(lhs),
+ static_cast<view_type*>(rhs));
+}
+
+template <typename Monoid>
+void reducer_base<Monoid>::identity_wrapper(void* r, void* view)
+{
+ Monoid* monoid = static_cast<reducer_base*>(r)->monoid_ptr();
+ monoid->identity(static_cast<view_type*>(view));
+}
+
+template <typename Monoid>
+void reducer_base<Monoid>::destroy_wrapper(void* r, void* view)
+{
+ Monoid* monoid = static_cast<reducer_base*>(r)->monoid_ptr();
+ monoid->destroy(static_cast<view_type*>(view));
+}
+
+template <typename Monoid>
+void* reducer_base<Monoid>::allocate_wrapper(void* r, __STDNS size_t bytes)
+{
+ Monoid* monoid = static_cast<reducer_base*>(r)->monoid_ptr();
+ return monoid->allocate(bytes);
+}
+
+template <typename Monoid>
+void reducer_base<Monoid>::deallocate_wrapper(void* r, void* view)
+{
+ Monoid* monoid = static_cast<reducer_base*>(r)->monoid_ptr();
+ monoid->deallocate(static_cast<view_type*>(view));
+}
+
+
+/** Base class defining the data members of a reducer.
+ *
+ * @tparam Aligned The `m_view` data member, and therefore the entire
+ * structure, are cache-line aligned if this parameter
+ * is `true'.
+ */
+template <typename Monoid, bool Aligned = Monoid::align_reducer>
+class reducer_content;
+
+/** Base class defining the data members of an aligned reducer.
+ */
+template <typename Monoid>
+class reducer_content<Monoid, true> : public reducer_base<Monoid>
+{
+ typedef typename Monoid::view_type view_type;
+
+ // The leftmost view is defined as raw bytes. It will be constructed
+ // by the monoid `construct` function. It is cache-aligned, which
+ // will push it into a new cache line. Furthermore, its alignment causes
+ // the reducer as a whole to be cache-aligned, which makes the reducer
+ // size a multiple of a cache line. Since there is nothing in the reducer
+ // after the view, all this means that the leftmost view gets one or more
+ // cache lines all to itself, which prevents false sharing.
+ //
+ __CILKRTS_CACHE_ALIGN
+ char m_leftmost[sizeof(view_type)];
+
+ /** Test if the reducer is cache-line-aligned.
+ *
+ * Used in assertions.
+ */
+ bool reducer_is_cache_aligned() const
+ { return 0 == ((std::size_t) this & (__CILKRTS_CACHE_LINE__ - 1)); }
+
+protected:
+
+ /** Constructor.
+ */
+ reducer_content() : reducer_base<Monoid>((char*)&m_leftmost)
+ {
+#ifndef CILK_IGNORE_REDUCER_ALIGNMENT
+ assert(reducer_is_cache_aligned() &&
+ "Reducer should be cache aligned. Please see comments following this assertion for explanation and fixes.");
+#endif
+ /* "REDUCER SHOULD BE CACHE ALIGNED" ASSERTION.
+ *
+ * This Reducer class instantiation specifies cache-line alignment of the
+ * leftmost view field (and, implicitly, of the reducer itself). You got
+ * this assertion because a reducer with this class was allocated at a
+ * non-cache-aligned address, probably because it was allocated on the
+ * heap with `new`. This can be a problem for two reasons:
+ *
+ * 1. If the leftmost view is not on a cache line by itself, there might
+ * be a slowdown resulting from accesses to the same cache line from
+ * different threads.
+ *
+ * 2. The compiler thinks that reducer is cache-line aligned, but it
+ * really isn't. If the reducer is contained in a structure, then the
+ * compiler will believe that the containing structure, and other
+ * fields contained in it, are also more aligned than they really
+ * are. In particular, if the structure contains a numeric array that
+ * is used in a vectorizable loop, then the compiler might generate
+ * invalid vector instructions, resulting in a runtime error.
+ *
+ * The compiler will always allocate reducer variables, and structure
+ * variables containing reducers, with their required alignment.
+ * Reducers, and structures containing a reducer, which are allocated
+ * on the heap with `new` will _not_ be properly aligned.
+ *
+ * There are three ways that you can fix this assertion failure.
+ *
+ * A. Rewrite your code to use the new-style `reducer< op_XXX<Type> >`
+ * instead of the legacy `reducer_XXX<type>`. The new-style reducers
+ * are not declared to be cache-aligned, and will work properly if
+ * they are not cache-aligned.
+ *
+ * B. If you must allocate an old-style reducer or a structure containing
+ * a reducer on the heap, figure out how to align it correctly. The
+ * suggested fix is to use `cilk::aligned_new()` and
+ * `cilk::aligned_delete()` instead of `new` and `delete`, as follows:
+ *
+ * Type* ptr = cilk::aligned_new<Type>(constructor-arguments);
+ * cilk::aligned_delete(ptr);
+ *
+ * C. Define the macro CILK_IGNORE_REDUCER_ALIGNMENT, which will suppress
+ * the assertion check. Do this only if you are comfortable that
+ * problem (2) above will not occur.
+ */
+ }
+};
+
+/** Base class defining the data members of an unaligned reducer.
+ */
+template <typename Monoid>
+class reducer_content<Monoid, false> : public reducer_base<Monoid>
+{
+ typedef typename Monoid::view_type view_type; ///< The view type.
+
+ // Reserve space for the leftmost view. The view will be allocated at an
+ // aligned offset in this space at runtime, to guarantee that the view
+ // will get one or more cache lines all to itself, to prevent false
+ // sharing.
+ //
+ // The number of bytes to reserve is determined as follows:
+ // * Start with the view size.
+ // * Round up to a multiple of the cache line size, to get the total size
+ // of the cache lines that will be dedicated to the view.
+ // * Add (cache line size - 1) filler bytes to guarantee that the reserved
+ // area will contain a cache-aligned block of the required cache lines,
+ // no matter where the reserved area starts.
+ //
+ char m_leftmost[
+ // View size rounded up to multiple cache lines
+ ( (sizeof(view_type) + __CILKRTS_CACHE_LINE__ - 1)
+ & ~ (__CILKRTS_CACHE_LINE__ - 1)
+ )
+ // plus filler to allow alignment.
+ + __CILKRTS_CACHE_LINE__ - 1
+ ];
+
+protected:
+
+ /** Constructor. Find the first cache-aligned position in the reserved
+ * area, and pass it to the base constructor as the leftmost view
+ * address.
+ */
+ reducer_content() :
+ reducer_base<Monoid>(
+ (char*)( ((std::size_t)&m_leftmost + __CILKRTS_CACHE_LINE__ - 1)
+ & ~ (__CILKRTS_CACHE_LINE__ - 1) ) )
+ {}
+};
+
+
+} // namespace internal
+
+
+// The __cilkrts_hyperobject_ functions are defined differently depending on
+// whether a file is compiled with or without the CILK_STUB option. Therefore,
+// reducers compiled in the two modes should be link-time incompatible, so that
+// object files compiled with stubbed reducers won't be linked into an
+// unstubbed program, or vice versa. We achieve this by putting the reducer
+// class definition into the cilk::stub namespace in a stubbed compilation.
+
+#ifdef CILK_STUB
+namespace stub {
+#endif
+
+/** Reducer class.
+ *
+ * A reducer is instantiated on a Monoid. The Monoid provides the value
+ * type, associative reduce function, and identity for the reducer.
+ *
+ * @tparam Monoid The monoid class that the reducer is instantiated on. It must model
+ * the @ref reducers_monoid_concept "monoid concept".
+ *
+ * @see @ref pagereducers
+ */
+template <class Monoid>
+class reducer : public internal::reducer_content<Monoid>
+{
+ typedef internal::reducer_content<Monoid> base;
+ using base::monoid_ptr;
+ using base::leftmost_ptr;
+ public:
+ typedef Monoid monoid_type; ///< The monoid type.
+ typedef typename Monoid::value_type value_type; ///< The value type.
+ typedef typename Monoid::view_type view_type; ///< The view type.
+
+ private:
+ typedef internal::reducer_set_get<value_type, view_type> set_get;
+
+ reducer(const reducer&); ///< Disallow copying.
+ reducer& operator=(const reducer&); ///< Disallow assignment.
+
+ public:
+
+ /** @name Constructors
+ *
+ * All reducer constructors call the static `construct()` function of the monoid class to
+ * construct the reducer's monoid and leftmost view.
+ *
+ * The reducer constructor arguments are simply passed through to the construct() function.
+ * Thus, the constructor parameters accepted by a particular reducer class are determined
+ * by its monoid class.
+ */
+ //@{
+
+ /** 0 – 6 const reference parameters.
+ */
+ //@{
+
+ reducer()
+ {
+ monoid_type::construct(monoid_ptr(), leftmost_ptr());
+ }
+
+ template <typename T1>
+ reducer(const T1& x1)
+ {
+ monoid_type::construct(monoid_ptr(), leftmost_ptr(), x1);
+ }
+
+ template <typename T1, typename T2>
+ reducer(const T1& x1, const T2& x2)
+ {
+ monoid_type::construct(monoid_ptr(), leftmost_ptr(), x1, x2);
+ }
+
+ template <typename T1, typename T2, typename T3>
+ reducer(const T1& x1, const T2& x2, const T3& x3)
+ {
+ monoid_type::construct(monoid_ptr(), leftmost_ptr(), x1, x2, x3);
+ }
+
+ template <typename T1, typename T2, typename T3, typename T4>
+ reducer(const T1& x1, const T2& x2, const T3& x3, const T4& x4)
+ {
+ monoid_type::construct(monoid_ptr(), leftmost_ptr(), x1, x2, x3, x4);
+ }
+
+ template <typename T1, typename T2, typename T3, typename T4, typename T5>
+ reducer(const T1& x1, const T2& x2, const T3& x3, const T4& x4, const T5& x5)
+ {
+ monoid_type::construct(monoid_ptr(), leftmost_ptr(), x1, x2, x3, x4, x5);
+ }
+
+ template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
+ reducer(const T1& x1, const T2& x2, const T3& x3, const T4& x4, const T5& x5, const T6& x6)
+ {
+ monoid_type::construct(monoid_ptr(), leftmost_ptr(), x1, x2, x3, x4, x5, x6);
+ }
+
+ //@}
+
+ /** 1 non-const reference parameter.
+ */
+ //@{
+
+ template <typename T1>
+ reducer(T1& x1)
+ {
+ monoid_type::construct(monoid_ptr(), leftmost_ptr(), x1);
+ }
+
+ //@}
+
+ /** Destructor.
+ */
+ __CILKRTS_STRAND_STALE(~reducer())
+ {
+ leftmost_ptr()->~view_type();
+ monoid_ptr()->~monoid_type();
+ }
+
+ //@{
+ /** Get the monoid.
+ *
+ * @return A reference to the monoid object belonging to this reducer.
+ */
+ Monoid& monoid() { return *monoid_ptr(); }
+
+ const Monoid& monoid() const
+ { return const_cast<reducer*>(this)->monoid(); }
+ //@}
+
+ //@{
+ /** Access the current view.
+ *
+ * Return a reference to the instance of the reducer’s view that was
+ * created for the current strand of a parallel computation (and create
+ * it if it doesn’t already exist).
+ */
+ view_type& view() { return base::view(); }
+ const view_type& view() const { return base::view(); }
+ //@}
+
+
+ /** @name Dereference the reducer to get the view.
+ *
+ * “Dereferencing†a reducer yields the view for the current strand. The
+ * view, in turn, acts as a proxy for its contained value, exposing only
+ * those operations which are consistent with the reducer’s monoid. Thus,
+ * all modifications of the reducer’s accumulator variable are written as
+ *
+ * *reducer OP ...
+ *
+ * or
+ *
+ * reducer->func(...)
+ *
+ * (The permitted operations on a reducer’s accumulator are listed in the
+ * documentation for that particular kind of reducer.)
+ *
+ * @note `*r` is a synonym for `r.view()`. Recommended style is to use
+ * `*r` (or `r->`) in the common case where code is simply
+ * updating the accumulator variable wrapped in the view, and to
+ * use `r.view()` in the unusual case where it is desirable to
+ * call attention to the view itself.
+ */
+ //@{
+
+ //@{
+ /** Dereference operator.
+ *
+ * @return A reference to the per-strand view instance.
+ */
+ view_type& operator*() { return view(); }
+ view_type const& operator*() const { return view(); }
+ //@}
+
+ //@{
+ /** Pointer operator.
+ *
+ * @return A pointer to the per-strand view instance.
+ */
+ view_type* operator->() { return &view(); }
+ view_type const* operator->() const { return &view(); }
+ //@}
+
+ //@{
+ /** Deprecated view access.
+ *
+ * `r()` is a synonym for `*r` which was used with early versions of Cilk
+ * reducers. `*r` is now the preferred usage.
+ *
+ * @deprecated Use operator*() instead of operator()().
+ *
+ * @return A reference to the per-strand view instance.
+ */
+ view_type& operator()() { return view(); }
+ view_type const& operator()() const { return view(); }
+ //@}
+
+ //@}
+
+ /** @name Set and get the value.
+ *
+ * These functions are used to set an initial value for the reducer before
+ * starting the reduction, or to get the final value after the reduction
+ * is complete.
+ *
+ * @note These functions are completely different from the view
+ * operations that are made available via operator*() and
+ * operator->(), which are used to _modify_ the reducer’s value
+ * _during_ the reduction.
+ *
+ * @warning These functions _can_ be called at any time, and in
+ * general, they will refer to the value contained in the view
+ * for the current strand. However, using them other than to
+ * set the reduction’s initial value or get its final value
+ * will almost always result in undefined behavior.
+ */
+ //@{
+
+ /** Move a value into the reducer.
+ *
+ * This function is used to set the initial value of the reducer’s
+ * accumulator variable by either copying or _moving_ the value of @a obj
+ * into it. Moving a value can often be performed in constant time, even
+ * for large container objects, but has the side effect of leaving the
+ * value of @a obj undefined. (See the description of the
+ * @ref move_in_wrapper class for a discussion of moving values.)
+ *
+ * @par Usage
+ * A move_in() call to initialize a reducer is often paired with a
+ * move_out() call to get its final value:
+ *
+ * reducer<Type> xr;
+ * xr.move_in(x);
+ * … do the reduction …
+ * xr.move_out(x);
+ *
+ * @par Assumptions
+ * - You cannot assume either that this will function will copy its
+ * value or that it will move it.
+ * - You must assume that the value of @a obj will be undefined
+ * after the call to move_in().
+ * - You can assume that move_in() will be at least as efficient as
+ * set_value(), and you should therefore prefer move_in() unless
+ * you need the value of @a obj to be unchanged after the call.
+ * (But you should usually prefer the move-in constructor over a
+ * move_in() call — see the note below.)
+ *
+ * @note The behavior of a default constructor followed by move-in
+ * initialization:
+ *
+ * reducer<Type> xr;
+ * xr.move_in(x);
+ *
+ * @note is not necessarily the same as a move-in constructor:
+ *
+ * reducer<Type> xr(move_in(x));
+ *
+ * @note In particular, when @a Type is a container type with a
+ * non-empty allocator, the move-in constructor will create the
+ * accumulator variable with the same allocator as the input
+ * argument @a x, while the default constructor will create the
+ * accumulator variable with a default allocator. The mismatch of
+ * allocators in the latter case means that the input argument
+ * @a x may have to be copied in linear time instead of being
+ * moved in constant time.
+ *
+ * @note Best practice is to prefer the move-in constructor over the
+ * move-in function unless the move-in function is required for
+ * some specific reason.
+ *
+ * @warning Calling this function other than to set the initial value
+ * for a reduction will almost always result in undefined
+ * behavior.
+ *
+ * @param obj The object containing the value that will be moved into the
+ * reducer.
+ *
+ * @post The reducer contains the value that was initially in @a obj.
+ * @post The value of @a obj is undefined.
+ *
+ * @see set_value()
+ */
+ void move_in(value_type& obj) { set_get::move_in(view(), obj);}
+
+ /** Move the value out of the reducer.
+ *
+ * This function is used to retrieve the final value of the reducer’s
+ * accumulator variable by either copying or _moving_ the value of @a obj
+ * into it. Moving a value can often be performed in constant time, even
+ * for large container objects, but has the side effect of leaving the
+ * value of the reducer’s accumulator variable undefined. (See the
+ * description of the @ref move_in_wrapper class for a discussion of
+ * moving values.)
+ *
+ * @par Usage
+ * A move_in() call to initialize a reducer is often paired with a
+ * move_out() call to get its final value:
+ *
+ * reducer<Type> xr;
+ * xr.move_in(x);
+ * … do the reduction …
+ * xr.move_out(x);
+ *
+ * @par Assumptions
+ * - You cannot assume either that this will function will copy its
+ * value or that it will move it.
+ * - You must assume that the value of the reducer’s accumulator
+ * variable will be undefined after the call to move_out().
+ * - You can assume that move_out() will be at least as efficient as
+ * get_value(), and you should therefore prefer move_out() unless
+ * you need the accumulator variable to be preserved after the
+ * call.
+ *
+ * @warning Calling this function other than to retrieve the final
+ * value of a reduction will almost always result in undefined
+ * behavior.
+ *
+ * @param obj The object that the value of the reducer will be moved into.
+ *
+ * @post @a obj contains the value that was initially in the reducer.
+ * @post The value of the reducer is undefined.
+ *
+ * @see get_value()
+ */
+ void move_out(value_type& obj) { set_get::move_out(view(), obj); }
+
+ /** Set the value of the reducer.
+ *
+ * This function sets the initial value of the reducer’s accumulator
+ * variable to the value of @a obj.
+ *
+ * @note The behavior of a default constructor followed by
+ * initialization:
+ *
+ * reducer<Type> xr;
+ * xr.set_value(x);
+ *
+ * @note is not necessarily the same as a value constructor:
+ *
+ * reducer<Type> xr(x);
+ *
+ * @note In particular, when @a Type is a container type with a
+ * non-empty allocator, the value constructor will create the
+ * accumulator variable with the same allocator as the input
+ * argument @a x, while the default constructor will create the
+ * accumulator variable with a default allocator.
+ *
+ * @warning Calling this function other than to set the initial value
+ * for a reduction will almost always result in undefined
+ * behavior.
+ *
+ * @param obj The object containing the value that will be copied into
+ * the reducer.
+ *
+ * @post The reducer contains a copy of the value in @a obj.
+ *
+ * @see move_in()
+ */
+ void set_value(const value_type& obj) { set_get::set_value(view(), obj); }
+
+ /** Get the value of the reducer.
+ *
+ * This function gets the final value of the reducer’s accumulator
+ * variable.
+ *
+ * @warning Calling this function other than to retrieve the final
+ * value of a reduction will almost always result in undefined
+ * behavior.
+ *
+ * @return A reference to the value contained in the reducer.
+ *
+ * @see move_out()
+ */
+ typename set_get::get_value_type get_value() const
+ { return set_get::get_value(view()); }
+
+ //@}
+
+ /** Implicit downcast to legacy reducer wrapper, if any.
+ *
+ * @see legacy_reducer_downcast
+ */
+ operator typename legacy_reducer_downcast<reducer>::type& ()
+ {
+ typedef typename legacy_reducer_downcast<reducer>::type downcast_type;
+ return *reinterpret_cast<downcast_type*>(this);
+ }
+
+
+ /** Implicit downcast to legacy reducer wrapper, if any.
+ *
+ * @see legacy_reducer_downcast
+ */
+ operator const typename legacy_reducer_downcast<reducer>::type& () const
+ {
+ typedef typename legacy_reducer_downcast<reducer>::type downcast_type;
+ return *reinterpret_cast<const downcast_type*>(this);
+ }
+};
+
+#ifdef CILK_STUB
+} // namespace stub
+using stub::reducer;
+#endif
+
+} // end namespace cilk
+
+#endif /* __cplusplus */
+
+/** @page page_reducers_in_c Creating and Using Reducers in C
+ *
+ * @tableofcontents
+ *
+ * The Cilk runtime supports reducers written in C as well as in C++. The basic logic is the
+ * same, but the implementation details are very different. The C++ reducer implementation uses
+ * templates heavily to create very generic components. The C reducer implementation uses
+ * macros, which are a much blunter instrument. The most immediate consequence is that the
+ * monoid/view/reducer architecture is mostly implicit rather than explicit in C reducers.
+ *
+ * @section reducers_c_overview Overview of Using Reducers in C
+ *
+ * The basic usage pattern for C reducers is:
+ *
+ * 1. Create and initialize a reducer object.
+ * 2. Tell the Cilk runtime about the reducer.
+ * 3. Update the value contained in the reducer in a parallel computation.
+ * 4. Tell the Cilk runtime that you are done with the reducer.
+ * 5. Retrieve the value from the reducer.
+ *
+ * @subsection reducers_c_creation Creating and Initializing a C Reducer
+ *
+ * The basic pattern for creating and initializing a reducer object in C is
+ *
+ * CILK_C_DECLARE_REDUCER(value-type) reducer-name =
+ * CILK_C_INIT_REDUCER(value-type,
+ * reduce-function,
+ * identity-function,
+ * destroy-function,
+ * initial-value);
+ *
+ * This is simply an initialized definition of a variable named _reducer-name_. The
+ * @ref CILK_C_DECLARE_REDUCER macro expands to an anonymous `struct` declaration for a reducer
+ * object containing a view of type _value-type_, and the @ref CILK_C_INIT_REDUCER macro
+ * expands to a struct initializer.
+ *
+ * @subsection reducers_c_reduce_func Reduce Functions
+ *
+ * The reduce function for a reducer is called when a parallel execution strand terminates, to
+ * combine the values computed by the terminating strand and the strand to its left. It takes
+ * three arguments:
+ *
+ * - `void* reducer` — the address of the reducer.
+ * - `void* left` — the address of the value for the left strand.
+ * - `void* right` — the address of the value for the right (terminating) strand.
+ *
+ * It must apply the reducer’s reduction operation to the `left` and `right` values, leaving
+ * the result in the `left` value. The `right` value is undefined after the reduce function
+ * call.
+ *
+ * @subsection reducers_c_identity_func Identity Functions
+ *
+ * The identity function for a reducer is called when a parallel execution strand begins, to
+ * initialize its value to the reducer’s identity value. It takes two arguments:
+ *
+ * - `void* reducer` — the address of the reducer.
+ * - `void* v` — the address of a freshly allocated block of memory of size
+ * `sizeof(value-type)`.
+ *
+ * It must initialize the memory pointed to by `v` so that it contains the reducer’s identity
+ * value.
+ *
+ * @subsection reducers_c_destroy_func Destroy Functions
+ *
+ * The destroy function for a reducer is called when a parallel execution strand terminates, to
+ * do any necessary cleanup before its value is deallocated. It takes two arguments:
+ *
+ * - `void* reducer` — the address of the reducer.
+ * - `void* p` — the address of the value for the terminating strand.
+ *
+ * It must release any resources belonging to the value pointed to by `p`, to avoid a resource
+ * leak when the memory containing the value is deallocated.
+ *
+ * The runtime function `__cilkrts_hyperobject_noop_destroy` can be used for the destructor
+ * function if the reducer’s values do not need any cleanup.
+ *
+ * @subsection reducers_c_register Tell the Cilk Runtime About the Reducer
+ *
+ * Call the @ref CILK_C_REGISTER_REDUCER macro to register the reducer with the Cilk runtime:
+ *
+ * CILK_C_REGISTER_REDUCER(reducer-name);
+ *
+ * The runtime will manage reducer values for all registered reducers when parallel execution
+ * strands begin and end.
+ *
+ * @subsection reducers_c_update Update the Value Contained in the Reducer
+ *
+ * The @ref REDUCER_VIEW macro returns a reference to the reducer’s value for the current
+ * parallel strand:
+ *
+ * REDUCER_VIEW(reducer-name) = REDUCER_VIEW(reducer-name) OP x;
+ *
+ * C++ reducer views restrict access to the wrapped value so that it can only be modified in
+ * ways consistent with the reducer’s operation. No such protection is provided for C reducers.
+ * It is
+ * entirely the responsibility of the user to avoid modifying the value in any
+ * inappropriate way.
+ *
+ * @subsection c_reducers_unregister Tell the Cilk Runtime That You Are Done with the Reducer
+ *
+ * When the parallel computation is complete, call the @ref CILK_C_UNREGISTER_REDUCER macro to
+ * unregister the reducer with the Cilk runtime:
+ *
+ * CILK_C_UNREGISTER_REDUCER(reducer-name);
+ *
+ * The runtime will stop managing reducer values for the reducer.
+ *
+ * @subsection c_reducers_retrieve Retrieve the Value from the Reducer
+ *
+ * When the parallel computation is complete, use the @ref REDUCER_VIEW macro to retrieve the
+ * final value computed by the reducer.
+ *
+ * @subsection reducers_c_example_custom Example — Creating and Using a Custom C Reducer
+ *
+ * The `IntList` type represents a simple list of integers.
+ *
+ * struct _intListNode {
+ * int value;
+ * _intListNode* next;
+ * } IntListNode;
+ * typedef struct { IntListNode* head; IntListNode* tail; } IntList;
+ *
+ * // Initialize a list to be empty
+ * void IntList_init(IntList* list) { list->head = list->tail = 0; }
+ *
+ * // Append an integer to the list
+ * void IntList_append(IntList* list, int x)
+ * {
+ * IntListNode* node = (IntListNode*) malloc(sizeof(IntListNode));
+ * if (list->tail) list->tail->next = node; else list->head = node;
+ * list->tail = node;
+ * }
+ *
+ * // Append the right list to the left list, and leave the right list empty
+ * void IntList_concat(IntList* left, IntList* right)
+ * {
+ * if (left->head) {
+ * left->tail->next = right->head;
+ * if (right->tail) left->tail = right->tail;
+ * }
+ * else {
+ * *left = *right;
+ * }
+ * IntList_init(*right);
+ * }
+ *
+ * This code creates a reducer that supports creating an `IntList` by appending values to it.
+ *
+ * void identity_IntList(void* reducer, void* list)
+ * {
+ * IntList_init((IntList*)list);
+ * }
+ *
+ * void reduce_IntList(void* reducer, void* left, void* right)
+ * {
+ * IntList_concat((IntList*)left, (IntList*)right);
+ * }
+ *
+ * CILK_C_DECLARE_REDUCER(IntList) my_list_int_reducer =
+ * CILK_C_INIT_REDUCER(IntList,
+ * reduce_int_list,
+ * identity_int_list,
+ * __cilkrts_hyperobject_noop_destroy);
+ * // Initial value omitted //
+ * ListInt_init(&REDUCER_VIEW(my_int_list_reducer));
+ *
+ * CILK_C_REGISTER_REDUCER(my_int_list_reducer);
+ * cilk_for (int i = 0; i != n; ++i) {
+ * IntList_append(&REDUCER_VIEW(my_int_list_reducer), a[i]);
+ * }
+ * CILK_C_UNREGISTER_REDUCER(my_int_list_reducer);
+ *
+ * IntList result = REDUCER_VIEW(my_int_list_reducer);
+ *
+ * @section reducers_c_predefined Predefined C Reducers
+ *
+ * Some of the predefined reducer classes in the Cilk library come with a set of predefined
+ * macros to provide the same capabilities in C. In general, two macros are provided for each
+ * predefined reducer family:
+ *
+ * - `CILK_C_REDUCER_operation(reducer-name, type-name, initial-value)` — Declares a
+ * reducer object named _reducer-name_ with initial value _initial-value_ to perform
+ * a reduction using the _operation_ on values of the type specified by _type-name_.
+ * This is the equivalent of the general code described in @ref reducers_c_creation :
+ *
+ * CILK_C_DECLARE_REDUCER(type) reducer-name =
+ * CILK_C_INIT_REDUCER(type, ..., initial-value);
+ *
+ * where _type_ is the C type corresponding to _type_name_. See @ref reducers_c_type_names
+ * below for the _type-names_ that you can use.
+ *
+ * - `CILK_C_REDUCER_operation_TYPE(type-name)` — Expands to the `typedef` name for the type
+ * of the reducer object declared by
+ * `CILK_C_REDUCER_operation(reducer-name, type-name, initial-value)`.
+ *
+ * See @ref reducers_c_example_predefined.
+ *
+ * The predefined C reducers are:
+ *
+ * | Operation | Name | Documentation |
+ * |-------------------|---------------|-------------------------------|
+ * | addition | `OPADD` | @ref ReducersAdd |
+ * | bitwise and | `OPAND` | @ref ReducersAnd |
+ * | bitwise or | `OPOR` | @ref ReducersOr |
+ * | bitwise xor | `OPXOR` | @ref ReducersXor |
+ * | multiplication | `OPMUL` | @ref ReducersMul |
+ * | minimum | `MIN` | @ref ReducersMinMax |
+ * | minimum & index | `MIN_INDEX` | @ref ReducersMinMax |
+ * | maximum | `MIN` | @ref ReducersMinMax |
+ * | maximum & index | `MIN_INDEX` | @ref ReducersMinMax |
+ *
+ * @subsection reducers_c_type_names Numeric Type Names
+ *
+ * The type and function names created by the C reducer definition macros incorporate both the
+ * reducer kind (`opadd`, `opxor`, etc.) and the value type of the reducer (`int`, `double`,
+ * etc.). The value type is represented by a _numeric type name_ string. The types supported
+ * in C reducers, and their corresponding numeric type names, are given in the following table:
+ *
+ * | Type | Numeric Type Name |
+ * |-----------------------|-------------------------------|
+ * | `char` | `char` |
+ * | `unsigned char` | `uchar` |
+ * | `signed char` | `schar` |
+ * | `wchar_t` | `wchar_t` |
+ * | `short` | `short` |
+ * | `unsigned short` | `ushort` |
+ * | `int` | `int` |
+ * | `unsigned int` | `uint` |
+ * | `unsigned int` | `unsigned` (alternate name) |
+ * | `long` | `long` |
+ * | `unsigned long` | `ulong` |
+ * | `long long` | `longlong` |
+ * | `unsigned long long` | `ulonglong` |
+ * | `float` | `float` |
+ * | `double` | `double` |
+ * | `long double` | `longdouble` |
+ *
+ * @subsection reducers_c_example_predefined Example — Using a Predefined C Reducer
+ *
+ * To compute the sum of all the values in an array of `unsigned int`:
+ *
+ * CILK_C_REDUCER_OPADD(sum, uint, 0);
+ * CILK_C_REGISTER_REDUCER(sum);
+ * cilk_for(int i = 0; i != n; ++i) {
+ * REDUCER_VIEW(sum) += a[i];
+ * }
+ * CILK_C_UNREGISTER_REDUCER(sum);
+ * printf("The sum is %u\n", REDUCER_VIEW(sum));
+ */
+
+
+ /** @name C language reducer macros
+ *
+ * These macros are used to declare and work with reducers in C code.
+ *
+ * @see @ref page_reducers_in_c
+ */
+ //@{
+
+/// @cond internal
+
+/** @name Compound identifier macros.
+ *
+ * These macros are used to construct an identifier by concatenating two or three identifiers.
+ */
+//@{
+
+/** Expand to an identifier formed by concatenating two identifiers.
+ */
+#define __CILKRTS_MKIDENT(a,b) __CILKRTS_MKIDENT_IMP(a,b,)
+
+/** Expand to an identifier formed by concatenating three identifiers.
+ */
+#define __CILKRTS_MKIDENT3(a,b,c) __CILKRTS_MKIDENT_IMP(a,b,c)
+
+/** Helper macro to do the concatenation.
+ */
+#define __CILKRTS_MKIDENT_IMP(a,b,c) a ## b ## c
+
+//@}
+
+/** Compiler-specific keyword for the “type of†operator.
+ */
+#if defined(__GNUC__) && !defined(__INTEL_COMPILER)
+# define _Typeof __typeof__
+#endif
+
+/** @name Predefined reducer function declaration macros.
+ *
+ * These macros are used to create the function headers for the identity, reduction,
+ * and destructor functions for a builtin reducer family. The macro can be followed by
+ * a semicolon to create a declaration, or by a brace-enclosed body to create a definition.
+ */
+//@{
+
+/** Create an identity function header.
+ *
+ * @note The name of the function’s value pointer parameter will always be `v`.
+ *
+ * @param name The reducer family name.
+ * @param tn The type name.
+ */
+#define __CILKRTS_DECLARE_REDUCER_IDENTITY(name,tn) CILK_EXPORT \
+ void __CILKRTS_MKIDENT3(name,_identity_,tn)(void* key, void* v)
+
+/** Create a reduction function header.
+ *
+ * @param name The reducer family name.
+ * @param tn The type name.
+ * @param l The name to use for the function’s left value pointer parameter.
+ * @param r The name to use for the function’s right value pointer parameter.
+ */
+#define __CILKRTS_DECLARE_REDUCER_REDUCE(name,tn,l,r) CILK_EXPORT \
+ void __CILKRTS_MKIDENT3(name,_reduce_,tn)(void* key, void* l, void* r)
+
+/** Create a destructor function header.
+ *
+ * @param name The reducer family name.
+ * @param tn The type name.
+ * @param p The name to use for the function’s value pointer parameter.
+ */
+#define __CILKRTS_DECLARE_REDUCER_DESTROY(name,tn,p) CILK_EXPORT \
+ void __CILKRTS_MKIDENT3(name,_destroy_,tn)(void* key, void* p)
+
+//@}
+
+/// @endcond
+
+
+/***************************************************************************
+ * Real implementation
+ ***************************************************************************/
+
+/** Declaration of a C reducer structure type.
+ *
+ * This macro expands into an anonymous structure declaration for a C reducer structure
+ * which contains a @a Type value. For example:
+ *
+ * CILK_C_DECLARE_REDUCER(int) my_add_int_reducer =
+ * CILK_C_INIT_REDUCER(int, …);
+ *
+ * @param Type The type of the value contained in the reducer object.
+ *
+ * @see @ref reducers_c_creation
+ */
+#define CILK_C_DECLARE_REDUCER(Type) struct { \
+ __cilkrts_hyperobject_base __cilkrts_hyperbase; \
+ __CILKRTS_CACHE_ALIGN Type value; \
+ }
+
+/** Initializer for a C reducer structure.
+ *
+ * This macro expands into a brace-enclosed structure initializer for a C reducer structure
+ * that was declared with `CILK_C_DECLARE_REDUCER(Type)`. For example:
+ *
+ * CILK_C_DECLARE_REDUCER(int) my_add_int_reducer =
+ * CILK_C_INIT_REDUCER(int,
+ * add_int_reduce,
+ * add_int_identity,
+ * __cilkrts_hyperobject_noop_destroy,
+ * 0);
+ *
+ * @param Type The type of the value contained in the reducer object. Must be the same as
+ * the @a Type argument of the CILK_C_DECLARE_REDUCER macro call that created
+ * the reducer.
+ * @param Reduce The address of the @ref reducers_c_reduce_func "reduce function" for the
+ * reducer.
+ * @param Identity The address of the @ref reducers_c_identity_func "identity function" for
+ * the reducer.
+ * @param Destroy The address of the @ref reducers_c_destroy_func "destroy function" for the
+ * reducer.
+ * @param ... The initial value for the reducer. (A single expression if @a Type is a
+ * scalar type; a list of values if @a Type is a struct or array type.)
+ *
+ * @see @ref reducers_c_creation
+ */
+
+#define CILK_C_INIT_REDUCER(Type, Reduce, Identity, Destroy, ...) \
+ { { { Reduce \
+ , Identity \
+ , Destroy \
+ , __cilkrts_hyperobject_alloc \
+ , __cilkrts_hyperobject_dealloc \
+ } \
+ , 0 \
+ , __CILKRTS_CACHE_LINE__ \
+ , sizeof(Type) \
+ } \
+ , __VA_ARGS__ \
+ }
+
+/** Register a reducer with the Cilk runtime.
+ *
+ * The runtime will manage reducer values for all registered reducers when parallel execution
+ * strands begin and end. For example:
+ *
+ * CILK_C_REGISTER_REDUCER(my_add_int_reducer);
+ * cilk_for (int i = 0; i != n; ++i) {
+ * …
+ * }
+ *
+ * @param Expr The reducer to be registered.
+ *
+ * @see @ref page_reducers_in_c
+ */
+#define CILK_C_REGISTER_REDUCER(Expr) \
+ __cilkrts_hyper_create(&(Expr).__cilkrts_hyperbase)
+
+/** Unregister a reducer with the Cilk runtime.
+ *
+ * The runtime will stop managing reducer values for a reducer after it is unregistered. For
+ * example:
+ *
+ * cilk_for (int i = 0; i != n; ++i) {
+ * …
+ * }
+ * CILK_C_UNREGISTER_REDUCER(my_add_int_reducer);
+ *
+ * @param Expr The reducer to be unregistered.
+ *
+ * @see @ref page_reducers_in_c
+ */
+#define CILK_C_UNREGISTER_REDUCER(Expr) \
+ __cilkrts_hyper_destroy(&(Expr).__cilkrts_hyperbase)
+
+/** Get the current view for a reducer.
+ *
+ * The `REDUCER_VIEW(reducer-name)` returns a reference to the reducer’s value for the
+ * current parallel strand. This can be used to initialize thevalue of the reducer before it
+ * is used, to modify the value of the reducer on the current parallel strand, or to retrieve
+ * the final value of the reducer at the end of the parallel computation.
+ *
+ * REDUCER_VIEW(my_add_int_reducer) = REDUCER_VIEW(my_add_int_reducer) + x;
+ *
+ * @note C++ reducer views restrict access to the wrapped value so that it can only be
+ * modified in ways consistent with the reducer’s operation. No such protection is provided
+ * for C reducers. It is entirely the responsibility of the user to refrain from modifying the
+ * value in any inappropriate way.
+ *
+ * @param Expr The reducer whose value is to be returned.
+ *
+ * @see @ref page_reducers_in_c
+ */
+#define REDUCER_VIEW(Expr) (*(_Typeof((Expr).value)*) \
+ __cilkrts_hyper_lookup(&(Expr).__cilkrts_hyperbase))
+
+//@} C language reducer macros
+
+#endif // CILK_REDUCER_H_INCLUDED
diff --git a/libcilkrts/include/cilk/reducer_file.h b/libcilkrts/include/cilk/reducer_file.h
new file mode 100644
index 00000000000..75af994e9d4
--- /dev/null
+++ b/libcilkrts/include/cilk/reducer_file.h
@@ -0,0 +1,37 @@
+/*
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
diff --git a/libcilkrts/include/cilk/reducer_list.h b/libcilkrts/include/cilk/reducer_list.h
new file mode 100644
index 00000000000..fc0be1e03d3
--- /dev/null
+++ b/libcilkrts/include/cilk/reducer_list.h
@@ -0,0 +1,1127 @@
+/* reducer_list.h -*- C++ -*-
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file reducer_list.h
+ *
+ * @brief Defines classes for doing parallel list creation by appending or
+ * prepending.
+ *
+ * @ingroup ReducersList
+ *
+ * @see ReducersList
+ */
+
+#ifndef REDUCER_LIST_H_INCLUDED
+#define REDUCER_LIST_H_INCLUDED
+
+#include <cilk/reducer.h>
+#include <list>
+
+/** @defgroup ReducersList List Reducers
+ *
+ * List append and prepend reducers allow the creation of a standard list by
+ * concatenating a set of lists or values in parallel.
+ *
+ * @ingroup Reducers
+ *
+ * You should be familiar with @ref pagereducers "Cilk reducers", described in
+ * file `reducers.md`, and particularly with @ref reducers_using, before trying
+ * to use the information in this file.
+ *
+ * @section redlist_usage Usage Example
+ *
+ * // Create a list containing the labels of the nodes of a tree in
+ * // “inorder†(left subtree, root, right subtree).
+ *
+ * struct Tree { Tree* left; Tree* right; string label; ... };
+ *
+ * list<string> x;
+ * cilk::reducer< cilk::op_list_append<string> > xr(cilk::move_in(x));
+ * collect_labels(tree, xr);
+ * xr.move_out(x);
+ *
+ * void collect_labels(Tree* node,
+ * cilk::reducer< cilk::op_list_append<string> >& xr)
+ * {
+ * if (node) {
+ * cilk_spawn collect_labels(node->left, xr);
+ * xr->push_back(node->label);
+ * collect_labels(node->right, xr);
+ * cilk_sync;
+ * }
+ * }
+ *
+ * @section redlist_monoid The Monoid
+ *
+ * @subsection redlist_monoid_values Value Set
+ *
+ * The value set of a list reducer is the set of values of the class
+ * `std::list<Type, Allocator>`, which we refer to as “the reducer’s list
+ * typeâ€.
+ *
+ * @subsection redlist_monoid_operator Operator
+ *
+ * The operator of a list append reducer is defined as
+ *
+ * x CAT y == (every element of x, followed by every element of y)
+ *
+ * The operator of a list prepend reducer is defined as
+ *
+ * x RCAT y == (every element of y, followed by every element of x)
+ *
+ * @subsection redlist_monoid_identity Identity
+ *
+ * The identity value of a list reducer is the empty list, which is the value
+ * of the expression `std::list<Type, Allocator>([allocator])`.
+ *
+ * @section redlist_operations Operations
+ *
+ * In the operation descriptions below, the type name `List` refers to the
+ * reducer’s string type, `std::list<Type, Allocator>`.
+ *
+ * @subsection redlist_constructors Constructors
+ *
+ * Any argument list which is valid for a `std::list` constructor is valid for
+ * a list reducer constructor. The usual move-in constructor is also provided:
+ *
+ * reducer(move_in(List& variable))
+ *
+ * A list reducer with no constructor arguments, or with only an allocator
+ * argument, will initially contain the identity value, an empty list.
+ *
+ * @subsection redlist_get_set Set and Get
+ *
+ * r.set_value(const List& value)
+ * const List& = r.get_value() const
+ * r.move_in(List& variable)
+ * r.move_out(List& variable)
+ *
+ * @subsection redlist_view_ops View Operations
+ *
+ * The view of a list append reducer provides the following member functions:
+ *
+ * void push_back(const Type& element)
+ * void insert_back(List::size_type n, const Type& element)
+ * template <typename Iter> void insert_back(Iter first, Iter last)
+ * void splice_back(List& x)
+ * void splice_back(List& x, List::iterator i)
+ * void splice_back(List& x, List::iterator first, List::iterator last)
+ *
+ * The view of a list prepend reducer provides the following member functions:
+ *
+ * void push_front(const Type& element)
+ * void insert_front(List::size_type n, const Type& element)
+ * template <typename Iter> void insert_front(Iter first, Iter last)
+ * void splice_front(List& x)
+ * void splice_front(List& x, List::iterator i)
+ * void splice_front(List& x, List::iterator first, List::iterator last)
+ *
+ * The `push_back` and `push_front` functions are the same as the
+ * corresponding `std::list` functions. The `insert_back`, `splice_back`,
+ * `insert_front`, and `splice_front` functions are the same as the
+ * `std::list` `insert` and `splice` functions, with the first parameter
+ * fixed to the end or beginning of the list, respectively.
+ *
+ * @section redlist_performance Performance Considerations
+ *
+ * An efficient reducer requires that combining the values of two views (using
+ * the view `reduce()` function) be a constant-time operations. Two lists can
+ * be merged in constant time using the `splice()` function if they have the
+ * same allocator. Therefore, the lists for new views are created (by the view
+ * identity constructor) using the same allocator as the list that was created
+ * when the reducer was constructed.
+ *
+ * The performance of adding elements to a list reducer depends on the view
+ * operations that are used:
+ *
+ * * The `push` functions add a single element to the list, and therefore
+ * take constant time.
+ * * An `insert` function that inserts _N_ elements adds each of them
+ * individually, and therefore takes _O(N)_ time.
+ * * A `splice` function that inserts _N_ elements just adjusts a couple of
+ * pointers, and therefore takes constant time, _if the splice is from a
+ * list with the same allocator as the reducer_. Otherwise, it is
+ * equivalent to an `insert`, and takes _O(N)_ time.
+ *
+ * This means that for best performance, if you will be adding elements to a
+ * list reducer in batches, you should `splice` them from a list having the
+ * same allocator as the reducer.
+ *
+ * The reducer `move_in` and `move_out` functions do a constant-time `swap` if
+ * the variable has the same allocator as the reducer, and a linear-time copy
+ * otherwise.
+ *
+ * Note that the allocator of a list reducer is determined when the reducer is
+ * constructed. The following two examples may have very different behavior:
+ *
+ * list<Element, Allocator> a_list;
+ *
+ * reducer< list_append<Element, Allocator> reducer1(move_in(a_list));
+ * ... parallel computation ...
+ * reducer1.move_out(a_list);
+ *
+ * reducer< list_append<Element, Allocator> reducer2;
+ * reducer2.move_in(a_list);
+ * ... parallel computation ...
+ * reducer2.move_out(a_list);
+ *
+ * * `reducer1` will be constructed with the same allocator as `a_list`,
+ * because the list was was specified in the constructor. The `move_in`
+ * and`move_out` can therefore be done with a `swap` in constant time.
+ * * `reducer2` will be constructed with a _default_ allocator,
+ * “`Allocator()`â€, which may or may not be the same as the allocator of
+ * `a_list`. Therefore, the `move_in` and `move_out` may have to be done
+ * with a copy in _O(N)_ time.
+ *
+ * (All instances of an allocator type with no internal state (like
+ * `std::allocator`) are “the sameâ€. You only need to worry about the “same
+ * allocator†issue when you create list reducers with custom allocator types.)
+ *
+ * @section redlist_types Type and Operator Requirements
+ *
+ * `std::list<Type, Allocator>` must be a valid type.
+ */
+
+
+namespace cilk {
+
+namespace internal {
+
+/** @ingroup ReducersList */
+//@{
+
+/** Base class for list append and prepend view classes.
+ *
+ * @note This class provides the definitions that are required for a class
+ * that will be used as the parameter of a @ref list_monoid_base
+ * specialization.
+ *
+ * @tparam Type The list element type (not the list type).
+ * @tparam Allocator The list's allocator class.
+ *
+ * @see ReducersList
+ * @see list_monoid_base
+ */
+template <typename Type, typename Allocator>
+class list_view_base
+{
+protected:
+ /// The type of the contained list.
+ typedef std::list<Type, Allocator> list_type;
+
+ /// The list accumulator variable.
+ list_type m_value;
+
+public:
+
+ /** @name Monoid support.
+ */
+ //@{
+
+ /// Required by @ref monoid_with_view
+ typedef list_type value_type;
+
+ /// Required by @ref list_monoid_base
+ Allocator get_allocator() const
+ {
+ return m_value.get_allocator();
+ }
+
+ //@}
+
+
+ /** @name Constructors.
+ */
+ //@{
+
+ /// Standard list constructor.
+ explicit list_view_base(const Allocator& a = Allocator()) : m_value(a) {}
+ explicit list_view_base(
+ typename list_type::size_type n,
+ const Type& value = Type(),
+ const Allocator& a = Allocator() ) : m_value(n, value, a) {}
+ template <typename Iter>
+ list_view_base(Iter first, Iter last, const Allocator& a = Allocator()) :
+ m_value(first, last, a) {}
+ list_view_base(const list_type& list) : m_value(list) {}
+
+ /// Move-in constructor.
+ explicit list_view_base(move_in_wrapper<value_type> w)
+ : m_value(w.value().get_allocator())
+ {
+ m_value.swap(w.value());
+ }
+
+ //@}
+
+ /** @name Reducer support.
+ */
+ //@{
+
+ /// Required by reducer::move_in()
+ void view_move_in(value_type& v)
+ {
+ if (m_value.get_allocator() == v.get_allocator())
+ // Equal allocators. Do a (fast) swap.
+ m_value.swap(v);
+ else
+ // Unequal allocators. Do a (slow) copy.
+ m_value = v;
+ v.clear();
+ }
+
+ /// Required by reducer::move_out()
+ void view_move_out(value_type& v)
+ {
+ if (m_value.get_allocator() == v.get_allocator())
+ // Equal allocators. Do a (fast) swap.
+ m_value.swap(v);
+ else
+ // Unequal allocators. Do a (slow) copy.
+ v = m_value;
+ m_value.clear();
+ }
+
+ /// Required by reducer::set_value()
+ void view_set_value(const value_type& v) { m_value = v; }
+
+ /// Required by reducer::get_value()
+ value_type const& view_get_value() const { return m_value; }
+
+ // Required by legacy wrapper get_reference()
+ value_type & view_get_reference() { return m_value; }
+ value_type const& view_get_reference() const { return m_value; }
+
+ //@}
+};
+
+
+/** Base class for list append and prepend monoid classes.
+ *
+ * The key to efficient reducers is that the `identity` operation, which
+ * creates a new per-strand view, and the `reduce` operation, which combines
+ * two per-strand views, must be constant-time operations. Two lists can be
+ * concatenated in constant time only if they have the same allocator.
+ * Therefore, all the per-strand list accumulator variables must be created
+ * with the same allocator as the leftmost view list.
+ *
+ * This means that a list reduction monoid must have a copy of the allocator
+ * of the leftmost view’s list, so that it can use it in the `identity`
+ * operation. This, in turn, requires that list reduction monoids have a
+ * specialized `construct()` function, which constructs the leftmost view
+ * before the monoid, and then passes the leftmost view’s allocator to the
+ * monoid constructor.
+ *
+ * @tparam View The list append or prepend view class.
+ * @tparam Align If `false` (the default), reducers instantiated on this
+ * monoid will be naturally aligned (the Cilk library 1.0
+ * behavior). If `true`, reducers instantiated on this monoid
+ * will be cache-aligned for binary compatibility with
+ * reducers in Cilk library version 0.9.
+ *
+ * @see ReducersList
+ * @see list_view_base
+ */
+template <typename View, bool Align>
+class list_monoid_base : public monoid_with_view<View, Align>
+{
+ typedef typename View::value_type list_type;
+ typedef typename list_type::allocator_type allocator_type;
+ allocator_type m_allocator;
+
+ using monoid_base<list_type, View>::provisional;
+
+public:
+
+ /** Constructor.
+ *
+ * There is no default constructor for list monoids, because the allocator
+ * must always be specified.
+ *
+ * @param allocator The list allocator to be used when
+ * identity-constructing new views.
+ */
+ list_monoid_base(const allocator_type& allocator = allocator_type()) :
+ m_allocator(allocator) {}
+
+ /** Create an identity view.
+ *
+ * List view identity constructors take the list allocator as an argument.
+ *
+ * @param v The address of the uninitialized memory in which the view
+ * will be constructed.
+ */
+ void identity(View *v) const { ::new((void*) v) View(m_allocator); }
+
+ /** @name construct functions
+ *
+ * All `construct()` functions first construct the leftmost view, using
+ * the optional @a x1, @a x2, and @a x3 arguments that were passed in from
+ * the reducer constructor. They then call the view’s `get_allocator()`
+ * function to get the list allocator from its contained list, and pass it
+ * to the monoid constructor.
+ */
+ //@{
+
+ template <typename Monoid>
+ static void construct(Monoid* monoid, View* view)
+ { provisional( new ((void*)view) View() ).confirm_if(
+ new ((void*)monoid) Monoid(view->get_allocator()) ); }
+
+ template <typename Monoid, typename T1>
+ static void construct(Monoid* monoid, View* view, const T1& x1)
+ { provisional( new ((void*)view) View(x1) ).confirm_if(
+ new ((void*)monoid) Monoid(view->get_allocator()) ); }
+
+ template <typename Monoid, typename T1, typename T2>
+ static void construct(Monoid* monoid, View* view, const T1& x1, const T2& x2)
+ { provisional( new ((void*)view) View(x1, x2) ).confirm_if(
+ new ((void*)monoid) Monoid(view->get_allocator()) ); }
+
+ template <typename Monoid, typename T1, typename T2, typename T3>
+ static void construct(Monoid* monoid, View* view, const T1& x1, const T2& x2,
+ const T3& x3)
+ { provisional( new ((void*)view) View(x1, x2, x3) ).confirm_if(
+ new ((void*)monoid) Monoid(view->get_allocator()) ); }
+
+ //@}
+};
+
+//@}
+
+} // namespace internal
+
+
+/** @ingroup ReducersList */
+//@{
+
+/** The list append reducer view class.
+ *
+ * This is the view class for reducers created with
+ * `cilk::reducer< cilk::op_list_append<Type, Allocator> >`. It holds the
+ * accumulator variable for the reduction, and allows only append operations
+ * to be performed on it.
+ *
+ * @note The reducer “dereference†operation (`reducer::operator *()`)
+ * yields a reference to the view. Thus, for example, the view class’s
+ * `push_back` operation would be used in an expression like
+ * `r->push_back(a)`, where `r` is a list append reducer variable.
+ *
+ * @tparam Type The list element type (not the list type).
+ * @tparam Allocator The list allocator type.
+ *
+ * @see ReducersList
+ * @see op_list_append
+ */
+template <class Type,
+ class Allocator = typename std::list<Type>::allocator_type>
+class op_list_append_view : public internal::list_view_base<Type, Allocator>
+{
+ typedef internal::list_view_base<Type, Allocator> base;
+ typedef std::list<Type, Allocator> list_type;
+ typedef typename list_type::iterator iterator;
+
+ iterator end() { return this->m_value.end(); }
+
+public:
+
+ /** @name Constructors.
+ *
+ * All op_list_append_view constructors simply pass their arguments on to
+ * the @ref internal::list_view_base base class constructor.
+ *
+ * @ref internal::list_view_base supports all the std::list constructor
+ * forms, as well as the reducer move_in constructor form.
+ */
+ //@{
+
+ op_list_append_view() : base() {}
+
+ template <typename T1>
+ op_list_append_view(const T1& x1) : base(x1) {}
+
+ template <typename T1, typename T2>
+ op_list_append_view(const T1& x1, const T2& x2) : base(x1, x2) {}
+
+ template <typename T1, typename T2, typename T3>
+ op_list_append_view(const T1& x1, const T2& x2, const T3& x3) :
+ base(x1, x2, x3) {}
+
+ //@}
+
+ /** @name View modifier operations.
+ */
+ //@{
+
+ /** Add an element at the end of the list.
+ *
+ * This is equivalent to `list.push_back(element)`
+ */
+ void push_back(const Type& element)
+ { this->m_value.push_back(element); }
+
+ /** Insert elements at the end of the list.
+ *
+ * This is equivalent to `list.insert(list.end(), n, element)`
+ */
+ void insert_back(typename list_type::size_type n, const Type& element)
+ { this->m_value.insert(end(), n, element); }
+
+ /** Insert elements at the end of the list.
+ *
+ * This is equivalent to `list.insert(list.end(), first, last)`
+ */
+ template <typename Iter>
+ void insert_back(Iter first, Iter last)
+ { this->m_value.insert(end(), first, last); }
+
+ /** Splice elements at the end of the list.
+ *
+ * This is equivalent to `list.splice(list.end(), x)`
+ */
+ void splice_back(list_type& x) {
+ if (x.get_allocator() == this->m_value.get_allocator())
+ this->m_value.splice(end(), x);
+ else {
+ insert_back(x.begin(), x.end());
+ x.clear();
+ }
+ }
+
+ /** Splice elements at the end of the list.
+ *
+ * This is equivalent to `list.splice(list.end(), x, i)`
+ */
+ void splice_back(list_type& x, iterator i) {
+ if (x.get_allocator() == this->m_value.get_allocator())
+ this->m_value.splice(end(), x, i);
+ else {
+ push_back(*i);
+ x.erase(i);
+ }
+ }
+
+ /** Splice elements at the end of the list.
+ *
+ * This is equivalent to `list.splice(list.end(), x, first, last)`
+ */
+ void splice_back(list_type& x, iterator first, iterator last) {
+ if (x.get_allocator() == this->m_value.get_allocator())
+ this->m_value.splice(end(), x, first, last);
+ else {
+ insert_back(first, last);
+ x.erase(first, last);
+ }
+ }
+
+ //@}
+
+ /** Reduction operation.
+ *
+ * This function is invoked by the @ref op_list_append monoid to combine
+ * the views of two strands when the right strand merges with the left
+ * one. It appends the value contained in the right-strand view to the
+ * value contained in the left-strand view, and leaves the value in the
+ * right-strand view undefined.
+ *
+ * @param right A pointer to the right-strand view. (`this` points to
+ * the left-strand view.)
+ *
+ * @note Used only by the @ref op_list_append monoid to implement the
+ * monoid reduce operation.
+ */
+ void reduce(op_list_append_view* right)
+ {
+ __CILKRTS_ASSERT(
+ this->m_value.get_allocator() == right->m_value.get_allocator());
+ this->m_value.splice(end(), right->m_value);
+ }
+};
+
+
+/** The list prepend reducer view class.
+ *
+ * This is the view class for reducers created with
+ * `cilk::reducer< cilk::op_list_prepend<Type, Allocator> >`. It holds the
+ * accumulator variable for the reduction, and allows only prepend operations
+ * to be performed on it.
+ *
+ * @note The reducer “dereference†operation (`reducer::operator *()`)
+ * yields a reference to the view. Thus, for example, the view class’s
+ * `push_front` operation would be used in an expression like
+ * `r->push_front(a)`, where `r` is a list prepend reducer variable.
+ *
+ * @tparam Type The list element type (not the list type).
+ * @tparam Allocator The list allocator type.
+ *
+ * @see ReducersList
+ * @see op_list_prepend
+ */
+template <class Type,
+ class Allocator = typename std::list<Type>::allocator_type>
+class op_list_prepend_view : public internal::list_view_base<Type, Allocator>
+{
+ typedef internal::list_view_base<Type, Allocator> base;
+ typedef std::list<Type, Allocator> list_type;
+ typedef typename list_type::iterator iterator;
+
+ iterator begin() { return this->m_value.begin(); }
+
+public:
+
+ /** @name Constructors.
+ *
+ * All op_list_prepend_view constructors simply pass their arguments on to
+ * the @ref internal::list_view_base base class constructor.
+ *
+ * @ref internal::list_view_base supports all the std::list constructor
+ * forms, as well as the reducer move_in constructor form.
+ *
+ */
+ //@{
+
+ op_list_prepend_view() : base() {}
+
+ template <typename T1>
+ op_list_prepend_view(const T1& x1) : base(x1) {}
+
+ template <typename T1, typename T2>
+ op_list_prepend_view(const T1& x1, const T2& x2) : base(x1, x2) {}
+
+ template <typename T1, typename T2, typename T3>
+ op_list_prepend_view(const T1& x1, const T2& x2, const T3& x3) :
+ base(x1, x2, x3) {}
+
+ //@}
+
+ /** @name View modifier operations.
+ */
+ //@{
+
+ /** Add an element at the beginning of the list.
+ *
+ * This is equivalent to `list.push_front(element)`
+ */
+ void push_front(const Type& element)
+ { this->m_value.push_front(element); }
+
+ /** Insert elements at the beginning of the list.
+ *
+ * This is equivalent to `list.insert(list.begin(), n, element)`
+ */
+ void insert_front(typename list_type::size_type n, const Type& element)
+ { this->m_value.insert(begin(), n, element); }
+
+ /** Insert elements at the beginning of the list.
+ *
+ * This is equivalent to `list.insert(list.begin(), first, last)`
+ */
+ template <typename Iter>
+ void insert_front(Iter first, Iter last)
+ { this->m_value.insert(begin(), first, last); }
+
+ /** Splice elements at the beginning of the list.
+ *
+ * This is equivalent to `list.splice(list.begin(), x)`
+ */
+ void splice_front(list_type& x) {
+ if (x.get_allocator() == this->m_value.get_allocator())
+ this->m_value.splice(begin(), x);
+ else {
+ insert_front(x.begin(), x.begin());
+ x.clear();
+ }
+ }
+
+ /** Splice elements at the beginning of the list.
+ *
+ * This is equivalent to `list.splice(list.begin(), x, i)`
+ */
+ void splice_front(list_type& x, iterator i) {
+ if (x.get_allocator() == this->m_value.get_allocator())
+ this->m_value.splice(begin(), x, i);
+ else {
+ push_front(*i);
+ x.erase(i);
+ }
+ }
+
+ /** Splice elements at the beginning of the list.
+ *
+ * This is equivalent to `list.splice(list.begin(), x, first, last)`
+ */
+ void splice_front(list_type& x, iterator first, iterator last) {
+ if (x.get_allocator() == this->m_value.get_allocator())
+ this->m_value.splice(begin(), x, first, last);
+ else {
+ insert_front(first, last);
+ x.erase(first, last);
+ }
+ }
+
+ //@}
+
+ /** Reduction operation.
+ *
+ * This function is invoked by the @ref op_list_prepend monoid to combine
+ * the views of two strands when the right strand merges with the left
+ * one. It prepends the value contained in the right-strand view to the
+ * value contained in the left-strand view, and leaves the value in the
+ * right-strand view undefined.
+ *
+ * @param right A pointer to the right-strand view. (`this` points to
+ * the left-strand view.)
+ *
+ * @note Used only by the @ref op_list_prepend monoid to implement the
+ * monoid reduce operation.
+ */
+ /** Reduce operation.
+ *
+ * Required by @ref monoid_base.
+ */
+ void reduce(op_list_prepend_view* right)
+ {
+ __CILKRTS_ASSERT(
+ this->m_value.get_allocator() == right->m_value.get_allocator());
+ this->m_value.splice(begin(), right->m_value);
+ }
+};
+
+
+
+/** Monoid class for list append reductions. Instantiate the cilk::reducer
+ * template class with a op_list_append monoid to create a list append reducer
+ * class. For example, to create a list of strings:
+ *
+ * cilk::reducer< cilk::op_list_append<std::string> > r;
+ *
+ * @tparam Type The list element type (not the list type).
+ * @tparam Alloc The list allocator type.
+ * @tparam Align If `false` (the default), reducers instantiated on this
+ * monoid will be naturally aligned (the Cilk library 1.0
+ * behavior). If `true`, reducers instantiated on this monoid
+ * will be cache-aligned for binary compatibility with
+ * reducers in Cilk library version 0.9.
+ *
+ * @see ReducersList
+ * @see op_list_append_view
+ */
+template <typename Type,
+ typename Allocator = typename std::list<Type>::allocator_type,
+ bool Align = false>
+struct op_list_append :
+ public internal::list_monoid_base<op_list_append_view<Type, Allocator>, Align>
+{
+ /// Construct with default allocator.
+ op_list_append() {}
+ /// Construct with specified allocator.
+ op_list_append(const Allocator& alloc) :
+ internal::list_monoid_base<op_list_append_view<Type, Allocator>, Align>(alloc) {}
+};
+
+/** Monoid class for list prepend reductions. Instantiate the cilk::reducer
+ * template class with a op_list_prepend monoid to create a list prepend
+ * reducer class. For example, to create a list of strings:
+ *
+ * cilk::reducer< cilk::op_list_prepend<std::string> > r;
+ *
+ * @tparam Type The list element type (not the list type).
+ * @tparam Alloc The list allocator type.
+ * @tparam Align If `false` (the default), reducers instantiated on this
+ * monoid will be naturally aligned (the Cilk library 1.0
+ * behavior). If `true`, reducers instantiated on this monoid
+ * will be cache-aligned for binary compatibility with
+ * reducers in Cilk library version 0.9.
+ *
+ * @see ReducersList
+ * @see op_list_prepend_view
+ */
+template <typename Type,
+ typename Allocator = typename std::list<Type>::allocator_type,
+ bool Align = false>
+struct op_list_prepend :
+ public internal::list_monoid_base<op_list_prepend_view<Type, Allocator>, Align>
+{
+ /// Construct with default allocator.
+ op_list_prepend() {}
+ /// Construct with specified allocator.
+ op_list_prepend(const Allocator& alloc) :
+ internal::list_monoid_base<op_list_prepend_view<Type, Allocator>, Align>(alloc) {}
+};
+
+
+/** Deprecated list append reducer wrapper class.
+ *
+ * reducer_list_append is the same as
+ * @ref reducer<@ref op_list_append>, except that reducer_list_append is a
+ * proxy for the contained view, so that accumulator variable update
+ * operations can be applied directly to the reducer. For example, an element
+ * is appended to a `reducer<%op_list_append>` with `r->push_back(a)`, but an
+ * element can be appended to a `%reducer_list_append` with `r.push_back(a)`.
+ *
+ * @deprecated Users are strongly encouraged to use `reducer<monoid>`
+ * reducers rather than the old wrappers like reducer_list_append.
+ * The `reducer<monoid>` reducers show the reducer/monoid/view
+ * architecture more clearly, are more consistent in their
+ * implementation, and present a simpler model for new
+ * user-implemented reducers.
+ *
+ * @note Implicit conversions are provided between `%reducer_list_append`
+ * and `reducer<%op_list_append>`. This allows incremental code
+ * conversion: old code that used `%reducer_list_append` can pass a
+ * `%reducer_list_append` to a converted function that now expects a
+ * pointer or reference to a `reducer<%op_list_append>`, and vice
+ * versa.
+ *
+ * @tparam Type The value type of the list.
+ * @tparam Allocator The allocator type of the list.
+ *
+ * @see op_list_append
+ * @see reducer
+ * @see ReducersList
+ */
+template <class Type, class Allocator = std::allocator<Type> >
+class reducer_list_append :
+ public reducer<op_list_append<Type, Allocator, true> >
+{
+ typedef reducer<op_list_append<Type, Allocator, true> > base;
+ using base::view;
+public:
+
+ /// The reducer’s list type.
+ typedef typename base::value_type list_type;
+
+ /// The list’s element type.
+ typedef Type list_value_type;
+
+ /// The reducer’s primitive component type.
+ typedef Type basic_value_type;
+
+ /// The monoid type.
+ typedef typename base::monoid_type Monoid;
+
+ /** @name Constructors
+ */
+ //@{
+
+ /** Construct a reducer with an empty list.
+ */
+ reducer_list_append() {}
+
+ /** Construct a reducer with a specified initial list value.
+ */
+ reducer_list_append(const std::list<Type, Allocator> &initial_value) :
+ base(initial_value) {}
+
+ //@}
+
+
+ /** @name Forwarded functions
+ * @details Functions that update the contained accumulator variable are
+ * simply forwarded to the contained @ref op_and_view. */
+ //@{
+
+ /// @copydoc op_list_append_view::push_back(const Type&)
+ void push_back(const Type& element) { view().push_back(element); }
+
+ //@}
+
+ /** Allow mutable access to the list within the current view.
+ *
+ * @warning If this method is called before the parallel calculation is
+ * complete, the list returned by this method will be a partial
+ * result.
+ *
+ * @returns A mutable reference to the list within the current view.
+ */
+ list_type &get_reference() { return view().view_get_reference(); }
+
+ /** Allow read-only access to the list within the current view.
+ *
+ * @warning If this method is called before the parallel calculation is
+ * complete, the list returned by this method will be a partial
+ * result.
+ *
+ * @returns A const reference to the list within the current view.
+ */
+ list_type const &get_reference() const { return view().view_get_reference(); }
+
+ /// @name Dereference
+ //@{
+ /** Dereferencing a wrapper is a no-op. It simply returns the wrapper.
+ * Combined with the rule that a wrapper forwards view operations to the
+ * view, this means that view operations can be written the same way on
+ * reducers and wrappers, which is convenient for incrementally
+ * converting code using wrappers to code using reducers. That is:
+ *
+ * reducer< op_list_append<int> > r;
+ * r->push_back(a); // *r returns the view
+ * // push_back is a view member function
+ *
+ * reducer_list_append<int> w;
+ * w->push_back(a); // *w returns the wrapper
+ * // push_back is a wrapper member function that
+ * // calls the corresponding view function
+ */
+ //@{
+ reducer_list_append& operator*() { return *this; }
+ reducer_list_append const& operator*() const { return *this; }
+
+ reducer_list_append* operator->() { return this; }
+ reducer_list_append const* operator->() const { return this; }
+ //@}
+
+ /** @name Upcast
+ * @details In Cilk library 0.9, reducers were always cache-aligned. In
+ * library 1.0, reducer cache alignment is optional. By default, reducers
+ * are unaligned (i.e., just naturally aligned), but legacy wrappers
+ * inherit from cache-aligned reducers for binary compatibility.
+ *
+ * This means that a wrapper will automatically be upcast to its aligned
+ * reducer base class. The following conversion operators provide
+ * pseudo-upcasts to the corresponding unaligned reducer class.
+ */
+ //@{
+ operator reducer< op_list_append<Type, Allocator, false> >& ()
+ {
+ return *reinterpret_cast<
+ reducer< op_list_append<Type, Allocator, false> >*
+ >(this);
+ }
+ operator const reducer< op_list_append<Type, Allocator, false> >& () const
+ {
+ return *reinterpret_cast<
+ const reducer< op_list_append<Type, Allocator, false> >*
+ >(this);
+ }
+ //@}
+
+};
+
+
+/** Deprecated list prepend reducer wrapper class.
+ *
+ * reducer_list_prepend is the same as
+ * @ref reducer<@ref op_list_prepend>, except that reducer_list_prepend is a
+ * proxy for the contained view, so that accumulator variable update operations
+ * can be applied directly to the reducer. For example, an element is prepended
+ * to a `reducer<op_list_prepend>` with `r->push_back(a)`, but an element is
+ * prepended to a `reducer_list_prepend` with `r.push_back(a)`.
+ *
+ * @deprecated Users are strongly encouraged to use `reducer<monoid>`
+ * reducers rather than the old wrappers like reducer_list_prepend.
+ * The `reducer<monoid>` reducers show the reducer/monoid/view
+ * architecture more clearly, are more consistent in their
+ * implementation, and present a simpler model for new
+ * user-implemented reducers.
+ *
+ * @note Implicit conversions are provided between `%reducer_list_prepend`
+ * and `reducer<%op_list_prepend>`. This allows incremental code
+ * conversion: old code that used `%reducer_list_prepend` can pass a
+ * `%reducer_list_prepend` to a converted function that now expects a
+ * pointer or reference to a `reducer<%op_list_prepend>`, and vice
+ * versa.
+ *
+ * @tparam Type The value type of the list.
+ * @tparam Allocator The allocator type of the list.
+ *
+ * @see op_list_prepend
+ * @see reducer
+ * @see ReducersList
+ */
+template <class Type, class Allocator = std::allocator<Type> >
+class reducer_list_prepend :
+ public reducer<op_list_prepend<Type, Allocator, true> >
+{
+ typedef reducer<op_list_prepend<Type, Allocator, true> > base;
+ using base::view;
+public:
+
+ /** The reducer’s list type.
+ */
+ typedef typename base::value_type list_type;
+
+ /** The list’s element type.
+ */
+ typedef Type list_value_type;
+
+ /** The reducer’s primitive component type.
+ */
+ typedef Type basic_value_type;
+
+ /** The monoid type.
+ */
+ typedef typename base::monoid_type Monoid;
+
+ /** @name Constructors
+ */
+ //@{
+
+ /** Construct a reducer with an empty list.
+ */
+ reducer_list_prepend() {}
+
+ /** Construct a reducer with a specified initial list value.
+ */
+ reducer_list_prepend(const std::list<Type, Allocator> &initial_value) :
+ base(initial_value) {}
+
+ //@}
+
+ /** @name Forwarded functions
+ * @details Functions that update the contained accumulator variable are
+ * simply forwarded to the contained @ref op_and_view.
+ */
+ //@{
+
+ /// @copydoc op_list_prepend_view::push_front(const Type&)
+ void push_front(const Type& element) { view().push_front(element); }
+
+ //@}
+
+ /** Allow mutable access to the list within the current view.
+ *
+ * @warning If this method is called before the parallel calculation is
+ * complete, the list returned by this method will be a partial
+ * result.
+ *
+ * @returns A mutable reference to the list within the current view.
+ */
+ list_type &get_reference() { return view().view_get_reference(); }
+
+ /** Allow read-only access to the list within the current view.
+ *
+ * @warning If this method is called before the parallel calculation is
+ * complete, the list returned by this method will be a partial
+ * result.
+ *
+ * @returns A const reference to the list within the current view.
+ */
+ list_type const &get_reference() const { return view().view_get_reference(); }
+
+ /// @name Dereference
+ /** Dereferencing a wrapper is a no-op. It simply returns the wrapper.
+ * Combined with the rule that a wrapper forwards view operations to the
+ * view, this means that view operations can be written the same way on
+ * reducers and wrappers, which is convenient for incrementally
+ * converting code using wrappers to code using reducers. That is:
+ *
+ * reducer< op_list_prepend<int> > r;
+ * r->push_front(a); // *r returns the view
+ * // push_front is a view member function
+ *
+ * reducer_list_prepend<int> w;
+ * w->push_front(a); // *w returns the wrapper
+ * // push_front is a wrapper member function that
+ * // calls the corresponding view function
+ */
+ //@{
+ reducer_list_prepend& operator*() { return *this; }
+ reducer_list_prepend const& operator*() const { return *this; }
+
+ reducer_list_prepend* operator->() { return this; }
+ reducer_list_prepend const* operator->() const { return this; }
+ //@}
+
+ /** @name Upcast
+ * @details In Cilk library 0.9, reducers were always cache-aligned. In
+ * library 1.0, reducer cache alignment is optional. By default, reducers
+ * are unaligned (i.e., just naturally aligned), but legacy wrappers
+ * inherit from cache-aligned reducers for binary compatibility.
+ *
+ * This means that a wrapper will automatically be upcast to its aligned
+ * reducer base class. The following conversion operators provide
+ * pseudo-upcasts to the corresponding unaligned reducer class.
+ */
+ //@{
+ operator reducer< op_list_prepend<Type, Allocator, false> >& ()
+ {
+ return *reinterpret_cast<
+ reducer< op_list_prepend<Type, Allocator, false> >*
+ >(this);
+ }
+ operator const reducer< op_list_prepend<Type, Allocator, false> >& () const
+ {
+ return *reinterpret_cast<
+ const reducer< op_list_prepend<Type, Allocator, false> >*
+ >(this);
+ }
+ //@}
+
+};
+
+/// @cond internal
+
+/** Metafunction specialization for reducer conversion.
+ *
+ * This specialization of the @ref legacy_reducer_downcast template class
+ * defined in reducer.h causes the `reducer< op_list_append<Type, Allocator> >`
+ * class to have an `operator reducer_list_append<Type, Allocator>& ()`
+ * conversion operator that statically downcasts the `reducer<op_list_append>`
+ * to the corresponding `reducer_list_append` type. (The reverse conversion,
+ * from `reducer_list_append` to `reducer<op_list_append>`, is just an upcast,
+ * which is provided for free by the language.)
+ */
+template <class Type, class Allocator, bool Align>
+struct legacy_reducer_downcast<reducer<op_list_append<Type, Allocator, Align> > >
+{
+ typedef reducer_list_append<Type, Allocator> type;
+};
+
+/** Metafunction specialization for reducer conversion.
+ *
+ * This specialization of the @ref legacy_reducer_downcast template class
+ * defined in reducer.h causes the
+ * `reducer< op_list_prepend<Type, Allocator> >` class to have an
+ * `operator reducer_list_prepend<Type, Allocator>& ()` conversion operator
+ * that statically downcasts the `reducer<op_list_prepend>` to the
+ * corresponding `reducer_list_prepend` type. (The reverse conversion, from
+ * `reducer_list_prepend` to `reducer<op_list_prepend>`, is just an upcast,
+ * which is provided for free by the language.)
+ */
+template <class Type, class Allocator, bool Align>
+struct legacy_reducer_downcast<reducer<op_list_prepend<Type, Allocator, Align> > >
+{
+ typedef reducer_list_prepend<Type, Allocator> type;
+};
+
+/// @endcond
+
+//@}
+
+} // Close namespace cilk
+
+#endif // REDUCER_LIST_H_INCLUDED
diff --git a/libcilkrts/include/cilk/reducer_max.h b/libcilkrts/include/cilk/reducer_max.h
new file mode 100644
index 00000000000..3ba3a0bc8ac
--- /dev/null
+++ b/libcilkrts/include/cilk/reducer_max.h
@@ -0,0 +1,46 @@
+/* reducer_max.h -*- C++ -*-
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file reducer_max.h
+ *
+ * @brief Defines classes for doing parallel maximum reductions.
+ *
+ * @ingroup ReducersMinMax
+ *
+ * @see ReducersMinMax
+ */
+
+#include "reducer_min_max.h"
diff --git a/libcilkrts/include/cilk/reducer_min.h b/libcilkrts/include/cilk/reducer_min.h
new file mode 100644
index 00000000000..f5a3910850e
--- /dev/null
+++ b/libcilkrts/include/cilk/reducer_min.h
@@ -0,0 +1,46 @@
+/* reducer_min.h -*- C++ -*-
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file reducer_min.h
+ *
+ * @brief Defines classes for doing parallel minimum reductions.
+ *
+ * @ingroup ReducersMinMax
+ *
+ * @see ReducersMinMax
+ */
+
+#include "reducer_min_max.h"
diff --git a/libcilkrts/include/cilk/reducer_min_max.h b/libcilkrts/include/cilk/reducer_min_max.h
new file mode 100644
index 00000000000..55f068c34a3
--- /dev/null
+++ b/libcilkrts/include/cilk/reducer_min_max.h
@@ -0,0 +1,3606 @@
+/* reducer_min_max.h -*- C++ -*-
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file reducer_min_max.h
+ *
+ * @brief Defines classes for doing parallel minimum and maximum reductions.
+ *
+ * @ingroup ReducersMinMax
+ *
+ * @see ReducersMinMax
+ */
+
+#ifndef REDUCER_MIN_MAX_H_INCLUDED
+#define REDUCER_MIN_MAX_H_INCLUDED
+
+#include <cilk/reducer.h>
+
+#ifdef __cplusplus
+
+#include <algorithm>
+#include <limits>
+
+/** @defgroup ReducersMinMax Minimum and Maximum Reducers
+ *
+ * Minimum and maximum reducers allow the computation of the minimum or
+ * maximum of a set of values in parallel.
+ *
+ * @ingroup Reducers
+ *
+ * You should be familiar with @ref pagereducers "Cilk reducers", described in
+ * file `reducers.md`, and particularly with @ref reducers_using, before trying
+ * to use the information in this file.
+ *
+ * @section redminmax_usage Usage Examples
+ *
+ * cilk::reducer< cilk::op_max<int> > rm;
+ * cilk_for (int i = 0; i < ARRAY_SIZE; ++i)
+ * {
+ * rm->calc_max(a[i]); // or *rm = cilk::max_of(*max, a[i])
+ * }
+ * std::cout << "maximum value is " << rm.get_value() << std::endl;
+ *
+ * and
+ *
+ * cilk::reducer< cilk::op_min_index<int, double> > rmi;
+ * cilk_for (int i = 0; i < ARRAY_SIZE; ++i)
+ * {
+ * rmi->calc_min(i, a[i]) // or *rmi = cilk::min_of(*rmi, i, a[i]);
+ * }
+ * std::cout << "minimum value a[" << rmi.get_value().first << "] = "
+ * << rmi.get_value().second << std::endl;
+ *
+ * @section redminmax_monoid The Monoid
+ *
+ * @subsection redminmax_monoid_values Value Set
+ *
+ * The value set of a minimum or maximum reducer is the set of values of
+ * `Type`, possibly augmented with a special identity value which is greater
+ * than (less than) any value of `Type`.
+ *
+ * @subsection redminmax_monoid_operator Operator
+ *
+ * In the most common case, the operator of a minimum reducer is defined as
+ *
+ * x MIN y == (x < y) ? x : y
+ *
+ * Thus, `a1 MIN a2 MIN … an` is the first `ai` which is not greater than any
+ * other `ai`.
+ *
+ * The operator of a maximum reducer is defined as
+ *
+ * x MAX y == (x > y) ? x : y
+ *
+ * Thus, `a1 MAX a2 MAX … an` is the first `ai` which is not less than any
+ * other `ai`.
+ *
+ * @subsection redminmax_monoid_comparators Comparators
+ *
+ * Min/max reducers are not limited to finding the minimum or maximum value
+ * determined by the `<` or `>` operator. In fact, all min/max reducers use a
+ * _comparator_, which is either a function or an object of a function class
+ * that defines a [strict weak ordering]
+ * (http://en.wikipedia.org/wiki/Strict_weak_ordering#Strict_weak_orderings)
+ * on a set of values. (This is exactly the same as the requirement for the
+ * comparison predicate for STL associative containers and sorting
+ * algorithms.)
+ *
+ * Just as with STL algorithms and containers, the comparator type parameter
+ * for min/max reducers is optional. If it is omitted, it defaults to
+ * `std::less`, which gives the behavior described in the previous section.
+ * Using non-default comparators (anything other than `std::less`) with
+ * min/max reducers is just like using them with STL containers and
+ * algorithms.
+ *
+ * Taking comparator objects into account, the reduction operation `MIN` for a
+ * minimum reducer is defined as
+ *
+ * x MIN y == compare(x, y) ? x : y
+ *
+ * where `compare()` is the reducer’s comparator. Similarly, the reduction
+ * operation MAX for a maximum reducer is defined as
+ *
+ * x MAX y == compare(y, x) ? x : y
+ *
+ * (If `compare(x, y) == x < y`, then `compare(y, x) == x > y`.)
+ *
+ * @subsection redminmax_monoid_identity Identity
+ *
+ * The identity value of the reducer is the value which is greater than (less
+ * than) any other value in the value set of the reducer. This is the
+ * [“special identity valueâ€](#redminmax_monoid_values) if the reducer has
+ * one, or the largest (smallest) value in the value set otherwise.
+ *
+ * @section redminmax_index Value and Index Reducers
+ *
+ * Min/max reducers come in two families. The _value_ reducers, using `op_min`
+ * and `op_max` monoids, simply find the smallest or largest value from a set
+ * of values. The _index_ reducers, using `op_min_index` and `op_max_index`
+ * monoids, also record an index value associated with the first occurrence of
+ * the smallest or largest value.
+ *
+ * In the `%op_min_index` usage example [above](#redminmax_usage), the values
+ * are taken from an array, and the index of a value is the index of the array
+ * element it comes from. More generally, though, an index can be any sort of
+ * key which identifies a particular value in a collection of values. For
+ * example, if the values were taken from the nodes of a tree, then the
+ * “index†of a value might be a pointer to the node containing that value.
+ *
+ * A min/max index reducer is essentially the same as a min/max value reducer
+ * whose value type is an (index, value) pair, and whose comparator ignores
+ * the index part of the pair. (index, value) pairs are represented by
+ * `std::pair<Index, Type>` objects. This has the consequence that wherever
+ * the interface of a min/max value reducer has a `Type`, the interface of the
+ * corresponding min/max index reducer has a `std::pair<Index, Type>`. (There
+ * are convenience variants of the `reducer(Type)` constructor and the
+ * `calc_min()`, `calc_max()`, `%min_of()`, and `%max_of()` functions that
+ * take an index argument and a value argument instead of an index/value
+ * pair.)
+ *
+ * @section redminmax_operations Operations
+ *
+ * @subsection redminmax_constructors Constructors
+ *
+ * @subsubsection redminmax_constructors_value Min/Max Value Reducers
+ *
+ * reducer() // identity
+ * reducer(const Compare& compare) // identity
+ * reducer(const Type& value)
+ * reducer(move_in(Type& variable))
+ * reducer(const Type& value, const Compare& compare)
+ * reducer(move_in(Type& variable), const Compare& compare)
+ *
+ * @subsubsection redminmax_constructors_index Min/Max Index Reducers
+ *
+ * reducer() // identity
+ * reducer(const Compare& compare) // identity
+ * reducer(const std::pair<Index, Type>& pair)
+ * reducer(const Index& index, const Type& value)
+ * reducer(move_in(std::pair<Index, Type>& variable))
+ * reducer(const std::pair<Index, Type>& pair, const Compare& compare)
+ * reducer(const Index& index, const Type& value, const Compare& compare)
+ * reducer(move_in(std::pair<Index, Type>& variable), const Compare& compare)
+ *
+ * @subsection redminmax_get_set Set and Get
+ *
+ * r.set_value(const Type& value)
+ * Type = r.get_value() const
+ * r.move_in(Type& variable)
+ * r.move_out(Type& variable)
+ *
+ * Note that for an index reducer, the `Type` in these operations is actually a
+ * `std::pair<Index, Type>`. (See @ref redminmax_index.) There is _not_ a
+ * `set_value(value, index)` operation.
+ *
+ * @subsection redminmax_initial Initial Values and is_set()
+ *
+ * A minimum or maximum reducer without a specified initial value, before any
+ * MIN or MAX operation has been performed on it, represents the [identity
+ * value](#redminmax_monoid_identity) of its monoid. For value reducers with a
+ * numeric type and default comparator (`std::less`), this will be a well
+ * defined value. For example,
+ *
+ * reducer< op_max<unsigned> > r1;
+ * // r1.get_value() == 0
+ *
+ * reducer< op_min<float> > r2;
+ * // r2.get_value() == std::numeric_limits<float>::infinity
+ *
+ * In other cases, though (index reducers, non-numeric types, or non-default
+ * comparators), the actual identity value for the monoid may be unknown, or
+ * it may not even be a value of the reducer’s type. For example, there is no
+ * “largest string†to serve as the initial value for a
+ * `reducer< op_min<std::string> >`. In these cases, the result of calling
+ * `get_value()` is undefined.
+ *
+ * To avoid calling `get_value()` when its result is undefined, you can call
+ * the view’s `is_set()` function, which will return true if the reducer
+ * has a well-defined value — either because a MIN or MAX operation has been
+ * performed, or because it had a well-defined initial value:
+ *
+ * reducer< op_max<unsigned> > r1;
+ * // r1->is_set() == true
+ * // r1.get_value() == 0
+ *
+ * reducer< op_min<std::string> > r2;
+ * // r2->is_set() == false
+ * // r2.get_value() is undefined
+ * r2->calc_min("xyzzy");
+ * // r2->is_set() == true
+ * // r2.get_value() == "xyzzy"
+ *
+ * > Note: For an index reducer without a specified initial value, the
+ * > initial value of the index is the default value of the `Index` type.
+ *
+ * @subsection redminmax_view_ops View Operations
+ *
+ * The basic reduction operation is `x = x MIN a` for a minimum reducer, or
+ * `x = x MAX a` for a maximum reducer. The basic syntax for these operations
+ * uses the `calc_min()` and `calc_max()` member functions of the view class.
+ * An assignment syntax is also provided, using the %cilk::min_of() and
+ * %cilk::max_of() global functions:
+ *
+ * Class | Modifier | Assignment
+ * ---------------|---------------------|-----------
+ * `op_min` | `r->calc_min(x)` | `*r = min_of(*r, x)` or `*r = min_of(x, *r)`
+ * `op_max` | `r->calc_max(x)` | `*r = max_of(*r, x)` or `*r = max_of(x, *r)`
+ * `op_min_index` | `r->calc_min(i, x)` | `*r = min_of(*r, i, x)` or `*r = min_of(i, x, *r)`
+ * `op_max_index` | `r->calc_max(i, x)` | `*r = max_of(*r, i, x)` or `*r = max_of(i, x, *r)`
+ *
+ * Wherever an “`i`, `x`†argument pair is shown in the table above, a single
+ * pair argument may be passed instead. For example:
+ *
+ * Index index;
+ * Type value;
+ * std::pair<Index, Type> ind_val(index, value);
+ * // The following statements are all equivalent.
+ * r->calc_min(index, value);
+ * r->calc_min(ind_val);
+ * *r = min_of(*r, index, value);
+ * *r = min_of(*r, ind_val);
+ *
+ * The `calc_min()` and `calc_max()` member functions return a reference to
+ * the view, so they can be chained:
+ *
+ * r->calc_max(x).calc_max(y).calc_max(z);
+ *
+ * In a `%min_of()` or `%max_of()` assignment, the view on the left-hand side
+ * of the assignment must be the same as the view argument in the call.
+ * Otherwise, the behavior is undefined (but an assertion error will occur if
+ * the code is compiled with debugging enabled).
+ *
+ * *r = max_of(*r, x); // OK
+ * *r1 = max_of(*r2, y); // ERROR
+ *
+ * `%min_of()` and `%max_of()` calls can be nested:
+ *
+ * *r = max_of(max_of(max_of(*r, x), y), z);
+ * *r = min_of(i, a[i], min_of(j, a[j], min_of(k, a[k], *r)));
+ *
+ * @section redminmax_compatibility Compatibility Issues
+ *
+ * Most Cilk library reducers provide
+ * * Binary compatibility between `reducer_KIND` reducers compiled with Cilk
+ * library version 0.9 (distributed with Intel® C++ Composer XE version
+ * 13.0 and earlier) and the same reducers compiled with Cilk library
+ * version 1.0 and later.
+ * * Transparent casting between references to `reducer<op_KIND>` and
+ * `reducer_KIND`.
+ *
+ * This compatibility is not available in all cases for min/max reducers.
+ * There are two areas of incompatibility.
+ *
+ * @subsection redminmax_compatibility_stateful Non-empty Comparators
+ *
+ * There is no way to provide binary compatibility between the 0.9 and 1.0
+ * definitions of min/max reducers that use a non-empty comparator class or a
+ * comparator function. (Empty comparator classes like `std::less` are not a
+ * problem.)
+ *
+ * To avoid run-time surprises, the legacy `reducer_{min|max}[_index]` classes
+ * have been coded in the 1.0 library so that they will not even compile when
+ * instantiated with a non-empty comparator class.
+ *
+ * @subsection redminmax_compatibility_optimized Numeric Optimization
+ *
+ * Min/max reducers with a numeric value type and the default comparator can
+ * be implemented slightly more efficiently than other min/max reducers.
+ * However, the optimization is incompatible with the 0.9 library
+ * implementation of min/max reducers.
+ *
+ * The default min/max reducers implementation in the 1.0 library uses this
+ * numeric optimization. Code using legacy reducers compiled with the 1.0
+ * library can be safely used in the same program as code compiled with the
+ * 0.9 library, but classes compiled with the different Cilk libraries will be
+ * defined in different namespaces.
+ *
+ * The simplest solution is just to recompile the code that was compiled with
+ * the older version of Cilk. However, if this is impossible, you can define
+ * the `CILK_LIBRARY_0_9_REDUCER_MINMAX` macro (on the compiler command line,
+ * or in your source code before including `reducer_min_max.h`) when compiling
+ * with the new library. This will cause it to generate numeric reducers that
+ * will be less efficient, but will be fully compatible with previously
+ * compiled code. (Note that this macro has no effect on [the non-empty
+ * comparator incompatibility] (redminmax_compatibility_stateful).)
+ *
+ * @section redminmax_types Type Requirements
+ *
+ * `Type` and `Index` must be `Copy Constructible`, `Default Constructible`,
+ * and `Assignable`.
+ *
+ * `Compare` must be `Copy Constructible` if the reducer is constructed with a
+ * `compare` argument, and `Default Constructible` otherwise.
+ *
+ * The `Compare` function must induce a strict weak ordering on the elements
+ * of `Type`.
+ *
+ * @section redminmax_in_c Minimum and Maximum Reducers in C
+ *
+ * These macros can be used to do minimum and maximum reductions in C:
+ *
+ * Declaration | Type | Operation
+ * -----------------------------|-----------------------------------|----------
+ * @ref CILK_C_REDUCER_MIN |@ref CILK_C_REDUCER_MIN_TYPE |@ref CILK_C_REDUCER_MIN_CALC
+ * @ref CILK_C_REDUCER_MAX |@ref CILK_C_REDUCER_MAX_TYPE |@ref CILK_C_REDUCER_MAX_CALC
+ * @ref CILK_C_REDUCER_MIN_INDEX |@ref CILK_C_REDUCER_MIN_INDEX_TYPE |@ref CILK_C_REDUCER_MIN_INDEX_CALC
+ * @ref CILK_C_REDUCER_MAX_INDEX |@ref CILK_C_REDUCER_MAX_INDEX_TYPE |@ref CILK_C_REDUCER_MAX_INDEX_CALC
+ *
+ * For example:
+ *
+ * CILK_C_REDUCER_MIN(r, int, INT_MAX);
+ * CILK_C_REGISTER_REDUCER(r);
+ * cilk_for(int i = 0; i != n; ++i) {
+ * CILK_C_REDUCER_MIN_CALC(r, a[i]);
+ * }
+ * CILK_C_UNREGISTER_REDUCER(r);
+ * printf("The smallest value in a is %d\n", REDUCER_VIEW(r));
+ *
+ *
+ * CILK_C_REDUCER_MAX_INDEX(r, uint, 0);
+ * CILK_C_REGISTER_REDUCER(r);
+ * cilk_for(int i = 0; i != n; ++i) {
+ * CILK_C_REDUCER_MAX_INDEX_CALC(r, i, a[i]);
+ * }
+ * CILK_C_UNREGISTER_REDUCER(r);
+ * printf("The largest value in a is %u at %d\n",
+ * REDUCER_VIEW (r).value, REDUCER_VIEW(r).index);
+ *
+ * See @ref reducers_c_predefined.
+ */
+
+namespace cilk {
+
+/** @defgroup ReducersMinMaxBinComp Binary compatibility
+ *
+ * If the macro CILK_LIBRARY_0_9_REDUCER_MINMAX is defined, then we generate
+ * reducer code and data structures which are binary-compatible with code that
+ * was compiled with the old min/max wrapper definitions, so we want the
+ * mangled names of the legacy min/max reducer wrapper classes to be the
+ * same as the names produced by the old definitions.
+ *
+ * Conversely, if the macro is not defined, then we generate binary-
+ * incompatible code, so we want different mangled names, to make sure that
+ * the linker does not allow new and old compiled legacy wrappers to be passed
+ * to one another. (Global variables are a different, and probably insoluble,
+ * problem.)
+ *
+ * Similarly, min/max classes compiled with and without
+ * CILK_LIBRARY_0_9_REDUCER_MINMAX are binary-incompatible, and must get
+ * different mangled names.
+ *
+ * The trick is, when compiling in normal (non-compatibility) mode, wrap
+ * everything in an extra namespace, and then `use` it into the top-level cilk
+ * namespace. Then
+ *
+ * * Classes and functions compiled in normal mode will be in
+ * different namespaces from the same classes and functions compiled in
+ * compatibility mode.
+ * * The legacy wrapper classes and functions will be in the same namespace
+ * as the same classes and functions compiled with the0.9 library if and
+ * only if the are compiled in compatibility mode.
+ *
+ * @ingroup ReducersMinMax
+ */
+
+#ifndef CILK_LIBRARY_0_9_REDUCER_MINMAX
+/** Namespace to wrap min/max reducer definitions when not compiling in “binary
+ * compatibility†mode.
+ *
+ * By default, all of the min/max reducer definitions are defined in this
+ * namespace and then imported into namespace ::cilk, so that they do not
+ * clash with the legacy definitions with the same names. However, if the
+ * macro `CILK_LIBRARY_0_9_REDUCER_MINMAX` is defined, then the min/max
+ * definitions go directly into namespace ::cilk, so that, for example,
+ * cilk::reducer_max defined with the 1.0 library is equivalent (to the
+ * linker) to cilk::reducer_max defined with the 0.9 library.
+ *
+ * @ingroup ReducersMinMaxBinComp
+ * @ingroup ReducersMinMax
+ */
+namespace cilk_lib_1_0 {
+#endif
+
+/** Namespace containing internal implementation classes and functions for
+ * min/max reducers.
+ *
+ * @ingroup ReducersMinMax
+ */
+namespace min_max_internal {
+
+using ::cilk::internal::binary_functor;
+using ::cilk::internal::typed_indirect_binary_function;
+using ::cilk::internal::class_is_empty;
+
+/** @defgroup ReducersMinMaxIsSet The “is_set optimizationâ€
+ *
+ * The obvious definition of the identity value for a max or min reducer is as
+ * the smallest (or largest) value of the value type. However, for an
+ * arbitrary comparator and/or an arbitrary value type, the largest / smallest
+ * value may not be known. It may not even be defined — what is the largest
+ * string?
+ *
+ * Therefore, min/max reducers represent their value internally as a pair
+ * `(value, is_set)`. When `is_set` is true, the pair represents the known
+ * value `value`; when `is_set` is false, the pair represents the identity
+ * value.
+ *
+ * This is an effective solution, but the most common use of min/max reducers
+ * is probably with numeric types and the default definition of minimum or
+ * maximum (using `std::less`), in which case there are well-defined, knowable
+ * smallest and largest values. Testing `is_set` for every comparison is then
+ * unnecessary and wasteful.
+ *
+ * The “is_set optimization†just means generating code that doesn’t use
+ * `is_set` when it isn’t needed. It is implemented using two metaprogramming
+ * classes:
+ *
+ * - do_is_set_optimization tests whether the optimization is applicable.
+ * - identity_value gets the appropriate identity value for a type.
+ *
+ * The is_set optimization is the reason that min/max reducers compiled with
+ * Cilk library 1.0 are binary-incompatible with the same reducers compiled
+ * with library 0.9, and therefore the optimization is suppressed when
+ * compiling in
+ * ReducersMinMaxBinComp "binary compatibility mode".
+ *
+ * @ingroup ReducersMinMax
+ */
+
+/** Test whether the ReducersMinMaxIsSet "is_set optimization" is
+ * applicable.
+ *
+ * The @ref do_is_set_optimization class is used to test whether the is_set
+ * optimization should be applied for a particular reducer. It is instantiated
+ * with a value type and a comparator, and defines a boolean constant,
+ * `value`. Then `%do_is_set_optimization<Type, Comp>::%value` can be used as
+ * a boolean template parameter to control the specialization of another
+ * class.
+ *
+ * In ReducersMinMaxBinComp "binary compatibility mode", when the
+ * `CILK_LIBRARY_0_9_REDUCER_MINMAX` macro is defined, `value` will always
+ * be false.
+ *
+ * @tparam Type The value type for the reducer.
+ * @tparam Compare The comparator type for the reducer.
+ *
+ * @result The `value` data member will be `true` if @a Type is a numeric
+ * type, @a Compare is `std::less<Type>`, and
+ * `CILK_LIBRARY_0_9_REDUCER_MINMAX` is not defined.
+ *
+ * @see ReducersMinMaxIsSet
+ * @see @ref view_content
+ *
+ * @ingroup ReducersMinMaxIsSet
+ */
+template < typename Type,
+ typename Compare >
+struct do_is_set_optimization
+{
+ /// `True` if the is_set optimization should be applied to min/max reducers
+ /// with this value type and comparator; `false` otherwise.
+ static const bool value = false;
+};
+
+#ifndef CILK_LIBRARY_0_9_REDUCER_MINMAX
+/// @cond
+template <typename Type>
+struct do_is_set_optimization<Type, std::less<Type> >
+{
+ /// True in the special case where optimization is possible.
+ static const bool value = std::numeric_limits<Type>::is_specialized;
+};
+/// @endcond
+#endif
+
+
+/** Get the identity value when using the ReducersMinMaxIsSet
+ * "is_set optimization".
+ *
+ * This class defines a function which assigns the appropriate identity value
+ * to a variable when the is_set optimization is applicable.
+ *
+ * @tparam Type The value type for the reducer.
+ * @tparam Compare The comparator type for the reducer.
+ * @tparam ForMax `true` to get the identity value for a max reducer (i.e.,
+ * the smallest value of @a Type), `false` to get the identity
+ * value for a min reducer (i.e., the largest value of
+ * @a Type).
+ *
+ * @result If @a Type and @a Compare qualify for the is_set optimization, the
+ * `set_identity()' function will set its argument variable to the
+ * smallest or largest value of @a Type, depending on @a ForMax.
+ * Otherwise, `set_identity()` will be a no-op.
+ *
+ * @see ReducersMinMaxIsSet
+ *
+ * @ingroup ReducersMinMaxIsSet
+ * @see @ref view_content
+ */
+template < typename Type,
+ typename Compare,
+ bool ForMax,
+ bool = std::numeric_limits<Type>::is_specialized,
+ bool = std::numeric_limits<Type>::has_infinity >
+struct identity_value {
+ /// Assign the identity value to the reference parameter.
+ static void set_identity(Type&) {}
+};
+
+/// @cond
+template <typename Type>
+struct identity_value<Type, std::less<Type>, true, true, true> {
+ /// Floating max identity is negative infinity.
+ static void set_identity(Type& id)
+ { id = -std::numeric_limits<Type>::infinity(); }
+};
+
+template <typename Type>
+struct identity_value<Type, std::less<Type>, true, true, false> {
+ /// Integer max identity is minimum value of type.
+ static void set_identity(Type& id)
+ { id = std::numeric_limits<Type>::min(); }
+};
+
+template <typename Type>
+struct identity_value<Type, std::less<Type>, false, true, true> {
+ /// Floating min identity is positive infinity.
+ static void set_identity(Type& id)
+ { id = std::numeric_limits<Type>::infinity(); }
+};
+
+template <typename Type>
+struct identity_value<Type, std::less<Type>, false, true, false> {
+ /// Integer min identity is maximum value of type.
+ static void set_identity(Type& id)
+ { id = std::numeric_limits<Type>::max(); }
+};
+
+/// @endcond
+
+
+/** Adapter class to reverse the arguments of a predicate.
+ *
+ * Observe that:
+ *
+ * (x < y) == (y > x)
+ * max(x, y) == (x < y) ? y : x
+ * min(x, y) == (y < x) ? y : x == (x > y) ? y : x
+ *
+ * More generally, if `c` is a predicate defining a `Strict Weak Ordering`,
+ * and `c*(x, y) == c(y, x)`, then
+ *
+ * max(x, y, c) == c(x, y) ? y : x
+ * min(x, y, c) == c(y, x) ? y : x == c*(x, y) ? y : x == max(x, y, c*)
+ *
+ * For any predicate `C` with argument type `T`, the template class
+ * `%reverse_predicate<C, T>` defines a predicate which is identical to `C`,
+ * except that its arguments are reversed. Thus, for example, we could
+ * implement `%op_min_view<Type, Compare>` as
+ * `%op_max_view<Type, %reverse_predicate<Compare, Type> >`.
+ * (Actually, op_min_view and op_max_view are both implemented as subclasses
+ * of a common base class, view_base.)
+ *
+ * @note If `C` is an empty functor class, then `reverse_predicate(C)` will
+ * also be an empty functor class.
+ *
+ * @tparam Predicate The predicate whose arguments are to be reversed.
+ * @tparam Argument @a Predicate’s argument type.
+ *
+ * @ingroup ReducersMinMax
+ */
+template <typename Predicate,
+ typename Argument = typename Predicate::first_argument_type>
+class reverse_predicate : private binary_functor<Predicate>::type {
+ typedef typename binary_functor<Predicate>::type base;
+public:
+ /// Default constructor
+ reverse_predicate() : base() {}
+ /// Constructor with predicate object
+ reverse_predicate(const Predicate& p) : base(p) {}
+ /// The reversed predicate operation
+ bool operator()(const Argument& x, const Argument& y) const
+ { return base::operator()(y, x); }
+};
+
+
+/** Class to represent the comparator for a min/max view class.
+ *
+ * This class is intended to accomplish two objectives in the implementation
+ * of min/max views.
+ *
+ * 1. To minimize data bloat, when we have a reducer with a non-stateless
+ * comparator, we want to keep a single instance of the comparator object
+ * in the monoid, and just call it from the views.
+ * 2. In ReducersMinMaxBinComp "binary compatibility mode", views for
+ * reducers with a stateless comparator must have the same content as in
+ * Cilk library 0.9 — that is, they must contain only `value` and
+ * `is_set` data members.
+ *
+ * To achieve the first objective, we use the
+ * @ref internal::typed_indirect_binary_function class defined in
+ * metaprogramming.h to wrap a pointer to the actual comparator. If no
+ * pointer is needed because the actual comparator is stateless, the
+ * `typed_indirect_binary_function` class will be empty, too.
+ *
+ * To achieve the second objective, we make the
+ * `typed_indirect_binary_function` class a base class of the view rather than
+ * a data member, so the “empty base class†rule will ensure no that no
+ * additional space is allocated in the view unless it is needed.
+ *
+ * We could simply use typed_indirect_binary_function as the base class of the
+ * view, but this would mean writing comparisons as `(*this)(x, y)`, which is
+ * just weird. So, instead, we comparator_base as a subclass of
+ * typed_indirect_binary_function which provides function `compare()`
+ * as a synonym for `operator()`.
+ *
+ * @tparam Type The value type of the comparator class.
+ * @tparam Compare A predicate class.
+ *
+ * @see internal::typed_indirect_binary_function
+ *
+ * @ingroup ReducersMinMax
+ */
+template <typename Type, typename Compare>
+class comparator_base : private typed_indirect_binary_function<Compare, Type, Type, bool>
+{
+ typedef typed_indirect_binary_function<Compare, Type, Type, bool> base;
+protected:
+ comparator_base(const Compare* f) : base(f) {} ///< Constructor.
+
+ /// Comparison function.
+ bool compare(const Type& a, const Type& b) const
+ {
+ return base::operator()(a, b);
+ }
+
+ /// Get the comparator pointer.
+ const Compare* compare_pointer() const { return base::pointer(); }
+};
+
+
+/** @defgroup ReducersMinMaxViewContent Content classes for min/max views
+ *
+ * @ingroup ReducersMinMax
+ *
+ * Minimum and maximum reducer view classes inherit from a “view contentâ€
+ * class. The content class defines the actual data members for the view,
+ * and provides typedefs and member functions for accessing the data members
+ * as needed to support the view functionality.
+ *
+ * There are two content classes, which encapsulate the differences between
+ * simple min/max reducers and min/max with index reducers:
+ *
+ * - view_content
+ * - index_view_content
+ *
+ * @note An obvious, and arguably simpler, encapsulation strategy would be
+ * to just let the `Type` of a min/max view be an (index, value) pair
+ * structure for min_index and max_index reducers. Then all views
+ * would just have a `Type` data member and an `is_set` data member,
+ * and the comparator for min_index and max_index views could be
+ * customized to consider only the value component of the (index,
+ * value) `Type` pair. Unfortunately, this would break binary
+ * compatibility with reducer_max_index and reducer_min_index in
+ * Cilk library 0.9, because the memory layout of an (index, value)
+ * pair followed by a `bool` is different from the memory layout of an
+ * index data member followed by a value data member followed by a
+ * `bool` data member. The content class is designed to exactly
+ * replicate the layout of the views in library 0.9 reducers.
+ *
+ * A content class `C`, and its objects `c`, must define the following:
+ *
+ * Definition | Meaning
+ * ------------------------------------|--------
+ * `C::value_type` | A typedef for `Type` of the view. (A `std::pair<Index, Type>` for min_index and max_index views).
+ * `C::comp_value_type` | A typedef for the type of value compared by the view’s `compare()` function.
+ * `C()` | Constructs the content with the identity value.
+ * `C(const value_type&)` | Constructs the content with a specified value.
+ * `c.is_set()` | Returns true if the content has a known value.
+ * `c.value()` | Returns the content’s value.
+ * `c.set_value(const value_type&)` | Sets the content’s value. (The value becomes known.)
+ * `c.comp_value()` | Returns a const reference to the value or component of the value that is to be compared by the view’s comparator.
+ * `C::comp_value(const value_type&)` | Returns a const reference to a value or component of a value that is to be compared by the view’s comparator.
+ *
+ * @see view_base
+ */
+
+/** Content class for op_min_view and op_max_view.
+ *
+ * @tparam Type The value type of the op_min_view or op_max_view.
+ * @tparam Compare The comparator class specified for the op_min_view or
+ * op_max_view. (_Not_ the derived comparator class actually
+ * used by the view_base. For example, the view_content of an
+ * `op_min_view<int>` will have `Compare = std::less<int>`,
+ * but its comparator_base will have
+ * `Compare = reverse_predicate< std::less<int> >`.)
+ * @tparam ForMax `true` if this is the content class for an op_max_view,
+ * `false` if it is for an op_min_view.
+ *
+ * @note The general implementation of view_content uses an `is_set` data
+ * member. There is also a specialization which implements the
+ * ReducersMinMaxIsSet "is_set optimization". View classes that
+ * inherit from view_content do not need to know anything about the
+ * difference, though; the details are abstracted away in the
+ * view_content interface.
+ *
+ * @see ReducersMinMaxViewContent
+ *
+ * @ingroup ReducersMinMaxViewContent
+ * @ingroup ReducersMinMax
+ */
+template < typename Type
+ , typename Compare
+ , bool ForMax
+ , bool = do_is_set_optimization<Type, Compare>::value
+ >
+class view_content {
+ Type m_value;
+ bool m_is_set;
+public:
+ /// The value type of the view.
+ typedef Type value_type;
+
+ /// The type compared by the view’s `compare()` function (which is the same
+ /// as the value type for view_content).
+ typedef Type comp_value_type;
+
+ /// Construct with the identity value.
+ view_content() : m_value(), m_is_set(false) {}
+
+ /// Construct with a defined value.
+ view_content(const value_type& value) : m_value(value), m_is_set(true) {}
+
+ /// Get the value.
+ value_type value() const { return m_value; }
+
+ /// Set the value.
+ void set_value(const value_type& value)
+ {
+ m_value = value;
+ m_is_set = true;
+ }
+
+ /// Get the comparison value (which is the same as the value for
+ /// view_content).
+ const comp_value_type& comp_value() const { return m_value; }
+
+ /// Given an arbitrary value, get the corresponding comparison value (which
+ /// is the same as the value for view_content).
+ static const comp_value_type& comp_value(const value_type& value)
+ {
+ return value;
+ }
+
+ /// Get a const reference to value part of the value (which is the same as
+ /// the value for view_content).
+ const Type& get_reference() const { return m_value; }
+
+ /// Get a const reference to the index part of the value (which is
+ /// meaningless for non-index reducers, but required for view_base.
+ const Type& get_index_reference() const { return m_value; }
+
+ /// Test if the value is defined.
+ bool is_set() const { return m_is_set; }
+};
+
+/// @cond
+
+/* This is the specialization of the view_content class for cases where
+ * `AssumeIsSet` is true (i.e., where the is_set optimization is applicable).
+ */
+template < typename Type
+ , typename Compare
+ , bool ForMax
+ >
+class view_content<Type, Compare, ForMax, true> {
+ typedef identity_value<Type, Compare, ForMax> Identity;
+ Type m_value;
+public:
+ typedef Type value_type;
+ typedef Type comp_value_type;
+
+ /// Construct with identity value.
+ view_content() { Identity::set_identity(m_value); }
+
+ view_content(const value_type& value) : m_value(value) {}
+
+ value_type value() const { return m_value; }
+
+ void set_value(const value_type& value)
+ {
+ m_value = value;
+ }
+
+ const comp_value_type& comp_value() const { return m_value; }
+
+ static const comp_value_type& comp_value(const value_type& value)
+ {
+ return value;
+ }
+
+ const Type& get_reference() const { return m_value; }
+
+ const Type& get_index_reference() const { return m_value; }
+
+ /// Test if the value is defined.
+ bool is_set() const { return true; }
+};
+
+/// @endcond
+
+
+/** Content class for op_min_index_view and op_max_index_view.
+ *
+ * @tparam Index The index type of the op_min_index_view or
+ op_max_index_view.
+ * @tparam Type The value type of the op_min_view or op_max_view. (_Not_
+ * the value type of the view, which will be
+ * `std::pair<Index, Type>`.)
+ * @tparam Compare The comparator class specified for the op_min_index_view or
+ * op_max_index_view. (_Not_ the derived comparator class
+ * actually used by the view_base. For example, the
+ * index_view_content of an `op_min_index_view<int>` will have
+ * `Compare = std::less<int>`, but its comparator_base will
+ * have `Compare = reverse_predicate< std::less<int> >`.)
+ * @tparam ForMax `true` if this is the content class for an
+ * op_max_index_view, `false` if it is for an
+ * op_min_index_view.
+ *
+ * @see ReducersMinMaxViewContent
+ *
+ * @ingroup ReducersMinMaxViewContent
+ * @ingroup ReducersMinMax
+ */
+template < typename Index
+ , typename Type
+ , typename Compare
+ , bool ForMax
+ >
+class index_view_content {
+ typedef identity_value<Type, Compare, ForMax> Identity;
+
+ Index m_index;
+ Type m_value;
+ bool m_is_set;
+public:
+ /// The value type of the view (which is an <index, value> pair for
+ /// index_view_content).
+ typedef std::pair<Index, Type> value_type;
+
+ /// The type compared by the view’s `compare()` function (which is the data
+ /// value type for index_view_content).
+ typedef Type comp_value_type;
+
+ /// Construct with the identity value.
+ index_view_content() : m_index(), m_value(), m_is_set(false) {}
+
+ /// Construct with an index/value pair.
+ index_view_content(const value_type& value) :
+ m_index(value.first), m_value(value.second), m_is_set(true) {}
+
+ /// Construct with an index and a value.
+ index_view_content(const Index& index, const Type& value) :
+ m_index(index), m_value(value), m_is_set(true) {}
+
+ /// Construct with just an index.
+ index_view_content(const Index& index) :
+ m_index(index), m_value(), m_is_set(false) {}
+
+ /// Get the value.
+ value_type value() const { return value_type(m_index, m_value); }
+
+ /// Set value.
+ void set_value(const value_type& value)
+ {
+ m_index = value.first;
+ m_value = value.second;
+ m_is_set = true;
+ }
+
+ /// Get the comparison value (which is the value component of the
+ /// index/value pair for index_view_content).
+ const comp_value_type& comp_value() const { return m_value; }
+
+ /// Given an arbitrary value (i.e., index/value pair), get the
+ /// corresponding comparison value (which is the value component of the
+ /// index/value pair for index_view_content).
+ static const comp_value_type& comp_value(const value_type& value)
+ { return value.second; }
+
+ /// Get a const reference to value part of the value.
+ const Type& get_reference() const { return m_value; }
+
+ /// Get a const reference to the index part of the value.
+ const Index& get_index_reference() const { return m_index; }
+
+ /// Test if the value is defined.
+ bool is_set() const { return m_is_set; }
+};
+
+
+template <typename View> class rhs_proxy;
+
+/** Create an rhs_proxy.
+ */
+template <typename View>
+inline rhs_proxy<View>
+make_proxy(const typename View::value_type& value, const View& view);
+
+template <typename Content, typename Less, typename Compare> class view_base;
+
+
+/** Class to represent the right-hand side of
+ * `*reducer = {min|max}_of(*reducer, value)`.
+ *
+ * The only assignment operator for a min/max view class takes a rhs_proxy as
+ * its operand. This results in the syntactic restriction that the only
+ * expressions that can be assigned to a min/max view are ones which generate
+ * an rhs_proxy — that is, expressions of the form `max_of(view, value)` and
+ * `min_of(view, value)`.
+ *
+ * @warning
+ * The lhs and rhs views in such an assignment must be the same; otherwise,
+ * the behavior will be undefined. (I.e., `*r1 = min_of(*r1, x)` is legal;
+ * `*r1 = min_of(*r2, x)` is illegal.) This condition will be checked with a
+ * runtime assertion when compiled in debug mode.
+ *
+ * @tparam View The view class (op_{min|max}[_index]_view) that this proxy
+ * was created from.
+ *
+ * @see view_base
+ *
+ * @ingroup ReducersMinMax
+ */
+template <typename View>
+class rhs_proxy {
+ typedef typename View::less_type less_type;
+ typedef typename View::compare_type compare_type;
+ typedef typename View::value_type value_type;
+ typedef typename View::content_type content_type;
+ typedef typename content_type::comp_value_type comp_value_type;
+
+ friend class view_base<content_type, less_type, compare_type>;
+ friend rhs_proxy make_proxy<View>(
+ const typename View::value_type& value,
+ const View& view);
+
+ typed_indirect_binary_function<
+ compare_type, comp_value_type, comp_value_type, bool>
+ m_comp;
+ const View* m_view;
+ value_type m_value;
+
+ rhs_proxy& operator=(const rhs_proxy&); // Disable assignment operator
+ rhs_proxy(); // Disable default constructor
+
+ // Constructor (called from view_base::make_proxy).
+ rhs_proxy(const View* view,
+ const value_type& value,
+ const compare_type* compare) :
+ m_view(view), m_value(value), m_comp(compare) {}
+
+ // Check matching view, then return value (called from view_base::assign).
+ value_type value(const typename View::base* view) const
+ {
+ __CILKRTS_ASSERT(view == m_view);
+ return m_value;
+ }
+
+public:
+
+ /** Support max_of(max_of(view, value), value) and the like.
+ */
+ rhs_proxy calc(const value_type& x) const
+ {
+ return rhs_proxy(
+ m_view,
+ m_comp( content_type::comp_value(m_value),
+ content_type::comp_value(x)
+ ) ? x : m_value,
+ m_comp.pointer());
+ }
+};
+
+
+template <typename View>
+inline rhs_proxy<View>
+make_proxy(const typename View::value_type& value, const View& view)
+{
+ return rhs_proxy<View>(&view, value, view.compare_pointer());
+}
+
+//@}
+
+/** Base class for min and max view classes.
+ *
+ * This class accumulates the minimum or maximum of a set of values which have
+ * occurred as arguments to the `calc()` function, as determined by a
+ * comparator. The accumulated value will be the first `calc()` argument value
+ * `x` such that `compare(x, y)` is false for every `calc()` argument value
+ * `y`.
+ *
+ * If the comparator is `std::less`, then the accumulated value is the first
+ * argument value which is not less than any other argument value, i.e., the
+ * maximum. Similarly, if the comparator is `reverse_predicate<std::less>`,
+ * which is equivalent to `std::greater`, then the accumulated value is the
+ * first argument value which is not greater than any other argument value,
+ * i.e., the minimum.
+ *
+ * @note This class provides the definitions that are required for a class
+ * that will be used as the parameter of a
+ * min_max_internal::monoid_base specialization.
+ *
+ * @tparam Content A content class that provides the value types and data
+ * members for the view.
+ * @tparam Less A “less than†binary predicate that defines the min or
+ * max function.
+ * @tparam Compare A binary predicate to be used to compare the values.
+ * (The same as @a Less for max reducers; its reversal for
+ * min reducers.)
+ *
+ * @see ReducersMinMaxViewContent
+ * @see op_max_view
+ * @see op_min_view
+ * @see op_max_index_view
+ * @see op_min_index_view
+ * @see monoid_base
+ *
+ * @ingroup ReducersMinMax
+ */
+template <typename Content, typename Less, typename Compare>
+class view_base :
+ // comparator_base comes first to ensure that it will get empty base class
+ // treatment
+ private comparator_base<typename Content::comp_value_type, Compare>,
+ private Content
+{
+ typedef comparator_base<typename Content::comp_value_type, Compare> base;
+ using base::compare;
+ using Content::value;
+ using Content::set_value;
+ using Content::comp_value;
+ typedef Content content_type;
+
+ template <typename View> friend class rhs_proxy;
+ template <typename View>
+ friend rhs_proxy<View> make_proxy(const typename View::value_type& value, const View& view);
+
+public:
+
+ /** @name Monoid support.
+ */
+ //@{
+
+ /** Value type. Required by @ref monoid_with_view.
+ */
+ typedef typename Content::value_type value_type;
+
+ /** The type of the comparator specified by the user, that defines the
+ * ordering on @a Type. Required by min_max::monoid_base.
+ */
+ typedef Less less_type;
+
+ /** The type of the comparator actually used by the view. Required by
+ * min_max::monoid_base. (This is the same as the @ref less_type for a
+ * max reducer, or `reverse_predicate<less_type>` for a min reducer.)
+ */
+ typedef Compare compare_type;
+
+ /** Reduce operation. Required by @ref monoid_with_view.
+ */
+ void reduce(view_base* other)
+ {
+ if ( other->is_set() &&
+ ( !this->is_set() ||
+ compare(this->comp_value(), other->comp_value()) ) )
+ {
+ this->set_value(other->value());
+ }
+ }
+
+ //@}
+
+ /** Default constructor. Initializes to identity value.
+ */
+ explicit view_base(const compare_type* compare) :
+ base(compare), Content() {}
+
+ /** Value constructor.
+ */
+ template <typename T1>
+ view_base(const T1& x1, const compare_type* compare) :
+ base(compare), Content(x1) {}
+
+ /** Value constructor.
+ */
+ template <typename T1, typename T2>
+ view_base(const T1& x1, const T2& x2, const compare_type* compare) :
+ base(compare), Content(x1, x2) {}
+
+
+ /** Move-in constructor.
+ */
+ explicit view_base(move_in_wrapper<value_type> w, const compare_type* compare) :
+ base(compare), Content(w.value()) {}
+
+ /** @name Reducer support.
+ */
+ //@{
+
+ void view_move_in(value_type& v) { set_value(v); }
+ void view_move_out(value_type& v) { v = value(); }
+ void view_set_value(const value_type& v) { set_value(v); }
+ value_type view_get_value() const { return value(); }
+ // view_get_reference() NOT SUPPORTED
+
+ //@}
+
+ /** Is the value defined?
+ */
+ using Content::is_set;
+
+ /** Reference to contained value data member.
+ * @deprecated For legacy reducers only.
+ */
+ using Content::get_reference;
+
+ /** Reference to contained index data member.
+ * (Meaningless for non-index reducers.)
+ * @deprecated For legacy reducers only.
+ */
+ using Content::get_index_reference;
+
+protected:
+
+ /** Update the min/max value.
+ */
+ void calc(const value_type& x)
+ {
+ if (!is_set() || compare(comp_value(), comp_value(x))) set_value(x);
+ }
+
+ /** Assign the result of a `{min|max}_of(view, value)` expression to the
+ * view.
+ *
+ * @see rhs_proxy
+ */
+ template <typename View>
+ void assign(const rhs_proxy<View>& rhs)
+ {
+ calc(rhs.value(this));
+ }
+
+};
+
+
+/** Base class for min and max monoid classes.
+ *
+ * The unique characteristic of minimum and maximum reducers is that they
+ * incorporate a comparator functor that defines what “minimum†or “maximumâ€
+ * means. The monoid for a reducer contains the comparator that will be used
+ * for the reduction. If the comparator is a function or a class with state,
+ * then each view will have a pointer to the comparator.
+ *
+ * This means that the `construct()` functions first construct the monoid
+ * (possibly with an explicit comparator argument), and then construct the
+ * view with a pointer to the monoid’s comparator.
+ *
+ * @tparam View The view class.
+ * @tparam Align If true, reducers instantiated on this monoid will be
+ * aligned. By default, library reducers (unlike legacy
+ * library reducer _wrappers_) are unaligned.
+ *
+ * @see view_base
+ *
+ * @ingroup ReducersMinMax
+ */
+template <typename View, bool Align = false>
+class monoid_base : public monoid_with_view<View, Align>
+{
+ typedef typename View::compare_type compare_type;
+ typedef typename View::less_type less_type;
+ const compare_type m_compare;
+
+ const compare_type* compare_pointer() const { return &m_compare; }
+
+ using cilk::monoid_base<typename View::value_type, View>::provisional;
+
+public:
+
+ /** Default constructor uses default comparator.
+ */
+ monoid_base() : m_compare() {}
+
+ /** Constructor.
+ *
+ * @param compare The comparator to use.
+ */
+ monoid_base(const compare_type& compare) : m_compare(compare) {}
+
+ /** Create an identity view.
+ *
+ * List view identity constructors take the list allocator as an argument.
+ *
+ * @param v The address of the uninitialized memory in which the view
+ * will be constructed.
+ */
+ void identity(View *v) const { ::new((void*) v) View(compare_pointer()); }
+
+ /** @name construct functions
+ *
+ * Min/max monoid `construct()` functions optionally take one or two value
+ * arguments, a @ref move_in argument, and/or a comparator argument.
+ */
+ //@{
+
+ template <typename Monoid>
+ static void construct(Monoid* monoid, View* view)
+ { provisional( new ((void*)monoid) Monoid() ).confirm_if(
+ new ((void*)view) View(monoid->compare_pointer()) ); }
+
+ template <typename Monoid, typename T1>
+ static void construct(Monoid* monoid, View* view, const T1& x1)
+ { provisional( new ((void*)monoid) Monoid() ).confirm_if(
+ new ((void*)view) View(x1, monoid->compare_pointer()) ); }
+
+ template <typename Monoid, typename T1, typename T2>
+ static void construct(Monoid* monoid, View* view, const T1& x1, const T2& x2)
+ { provisional( new ((void*)monoid) Monoid() ).confirm_if(
+ new ((void*)view) View(x1, x2, monoid->compare_pointer()) ); }
+
+ template <typename Monoid>
+ static void construct(Monoid* monoid, View* view, const less_type& compare)
+ { provisional( new ((void*)monoid) Monoid(compare) ).confirm_if(
+ new ((void*)view) View(monoid->compare_pointer()) ); }
+
+ template <typename Monoid, typename T1>
+ static void construct(Monoid* monoid, View* view, const T1& x1, const less_type& compare)
+ { provisional( new ((void*)monoid) Monoid(compare) ).confirm_if(
+ new ((void*)view) View(x1, monoid->compare_pointer()) ); }
+
+ template <typename Monoid, typename T1, typename T2>
+ static void construct(Monoid* monoid, View* view, const T1& x1, const T2& x2, const less_type& compare)
+ { provisional( new ((void*)monoid) Monoid(compare) ).confirm_if(
+ new ((void*)view) View(x1, x2, monoid->compare_pointer()) ); }
+
+ //@}
+};
+
+} //namespace min_max_internal
+
+
+/** @defgroup ReducersMinMaxMaxValue Maximum reducers (value only)
+ *
+ * These reducers will find the largest value from a set of values.
+ *
+ * @ingroup ReducersMinMax
+ */
+//@{
+
+/** The maximum reducer view class.
+ *
+ * This is the view class for reducers created with
+ * `cilk::reducer< cilk::op_max<Type, Compare> >`. It accumulates the maximum,
+ * as determined by a comparator, of a set of values which have occurred as
+ * arguments to the `calc_max()` function. The accumulated value will be the
+ * first argument `x` such that `compare(x, y)` is false for every argument
+ * `y`.
+ *
+ * If the comparator is `std::less`, then the accumulated value is the first
+ * argument value which is not less than any other argument value, i.e., the
+ * maximum.
+ *
+ * @note The reducer “dereference†operation (`reducer::operator *()`)
+ * yields a reference to the view. Thus, for example, the view class’s
+ * `calc_max()` function would be used in an expression like
+ * `r->calc_max(a)` where `r` is an op_max reducer variable.
+ *
+ * @tparam Type The type of the values compared by the reducer. This will
+ * be the value type of a monoid_with_view that is
+ * instantiated with this view.
+ * @tparam Compare A `Strict Weak Ordering` whose argument type is @a Type. It
+ * defines the “less than†relation used to compute the
+ * maximum.
+ *
+ * @see ReducersMinMax
+ * @see op_max
+ */
+template <typename Type, typename Compare>
+class op_max_view : public min_max_internal::view_base<
+ min_max_internal::view_content<Type, Compare, true>,
+ Compare,
+ Compare>
+{
+ typedef min_max_internal::view_base<
+ min_max_internal::view_content<Type, Compare, true>,
+ Compare,
+ Compare> base;
+ using base::calc;
+ using base::assign;
+ friend class min_max_internal::rhs_proxy<op_max_view>;
+
+public:
+
+ /** @name Constructors.
+ *
+ * All op_max_view constructors simply pass their arguments on to the
+ * @ref view_base base class.
+ */
+ //@{
+
+ op_max_view() : base() {}
+
+ template <typename T1>
+ op_max_view(const T1& x1) : base(x1) {}
+
+ template <typename T1, typename T2>
+ op_max_view(const T1& x1, const T2& x2) : base(x1, x2) {}
+
+ //@}
+
+ /** @name View modifier operations.
+ */
+ //@{
+
+ /** Maximize with a value.
+ *
+ * If @a x is greater than the current value of the view (as defined by
+ * the reducer’s comparator), or if the view was created without an
+ * initial value and its value has never been updated (with `calc_max()`
+ * or `= max_of()`), then the value of the view is set to @a x.
+ *
+ * @param x The value to maximize the view’s value with.
+ *
+ * @return A reference to the view. (Allows chaining
+ * `view.comp_max(a).comp_max(b)…`.)
+ */
+ op_max_view& calc_max(const Type& x) { calc(x); return *this; }
+
+ /** Assign the result of a `max_of(view, value)` expression to the view.
+ *
+ * @param rhs An rhs_proxy value created by a `max_of(view, value)`
+ * expression.
+ *
+ * @return A reference to the view.
+ *
+ * @see min_max_internal::view_base::rhs_proxy
+ */
+ op_max_view& operator=(const min_max_internal::rhs_proxy<op_max_view>& rhs)
+ { assign(rhs); return *this; }
+
+ //@}
+};
+
+
+/** Compute the maximum of the value in an op_max_view and another value.
+ *
+ * The result of this computation can only be assigned back to the original
+ * view or used in another max_of() call. For example,
+ *
+ * *reducer = max_of(*reducer, x);
+ * *reducer = max_of(x, *reducer);
+ *
+ * @see min_max_internal::rhs_proxy
+ */
+template <typename Type, typename Compare>
+inline min_max_internal::rhs_proxy< op_max_view<Type, Compare> >
+max_of(const op_max_view<Type, Compare>& view, const Type& value)
+{
+ return min_max_internal::make_proxy(value, view);
+}
+
+/// @copydoc max_of(const op_max_view<Type, Compare>&, const Type&)
+template <typename Type, typename Compare>
+inline min_max_internal::rhs_proxy< op_max_view<Type, Compare> >
+max_of(const Type& value, const op_max_view<Type, Compare>& view)
+{
+ return min_max_internal::make_proxy(value, view);
+}
+
+/** Nested maximum computation.
+ *
+ * Compute the maximum of the result of a max_of() call and another value.
+ *
+ * The result of this computation can only be assigned back to the original
+ * view or wrapper, or used in another max_of() call. For example,
+ *
+ * *reducer = max_of(x, max_of(y, *reducer));
+ * wrapper = max_of(max_of(wrapper, x), y);
+ *
+ * @see min_max_internal::rhs_proxy
+ */
+template <typename Type, typename Compare>
+inline min_max_internal::rhs_proxy< op_max_view<Type, Compare> >
+max_of(const min_max_internal::rhs_proxy< op_max_view<Type, Compare> >& proxy,
+ const Type& value)
+{
+ return proxy.calc(value);
+}
+
+/// @copydoc max_of(const min_max_internal::rhs_proxy< op_max_view<Type, Compare> >&, const Type&)
+template <typename Type, typename Compare>
+inline min_max_internal::rhs_proxy< op_max_view<Type, Compare> >
+max_of(const Type& value,
+ const min_max_internal::rhs_proxy< op_max_view<Type, Compare> >& proxy)
+{
+ return proxy.calc(value);
+}
+
+
+/** Monoid class for maximum reductions. Instantiate the cilk::reducer template
+ * class with an op_max monoid to create a maximum reducer class. For example,
+ * to compute the maximum of a set of `int` values:
+ *
+ * cilk::reducer< cilk::op_max<int> > r;
+ *
+ * @see ReducersMinMax
+ * @see op_max_view
+ */
+template <typename Type, typename Compare=std::less<Type>, bool Align = false>
+class op_max :
+ public min_max_internal::monoid_base<op_max_view<Type, Compare>, Align>
+{
+ typedef min_max_internal::monoid_base<op_max_view<Type, Compare>, Align>
+ base;
+public:
+ /// Construct with default comparator.
+ op_max() {}
+ /// Construct with specified comparator.
+ op_max(const Compare& compare) : base(compare) {}
+};
+
+//@}
+
+
+/** @defgroup ReducersMinMaxMinValue Minimum reducers (value only)
+ *
+ * These reducers will find the smallest value from a set of values.
+ *
+ * @ingroup ReducersMinMax
+ */
+//@{
+
+/** The minimum reducer view class.
+ *
+ * This is the view class for reducers created with
+ * `cilk::reducer< cilk::op_min<Type, Compare> >`. It accumulates the minimum,
+ * as determined by a comparator, of a set of values which have occurred as
+ * arguments to the `calc_min()` function. The accumulated value will be the
+ * first argument `x` such that `compare(y, x)` is false for every argument
+ * `y`.
+ *
+ * If the comparator is `std::less`, then the accumulated value is the first
+ * argument value which no other argument value is less than, i.e., the
+ * minimum.
+ *
+ * @note The reducer “dereference†operation (`reducer::operator *()`)
+ * yields a reference to the view. Thus, for example, the view class’s
+ * `calc_min()` function would be used in an expression like
+ * `r->calc_min(a)` where `r` is an op_min reducer variable.
+ *
+ * @tparam Type The type of the values compared by the reducer. This will
+ * be the value type of a monoid_with_view that is
+ * instantiated with this view.
+ * @tparam Compare A `Strict Weak Ordering` whose argument type is @a Type. It
+ * defines the “less than†relation used to compute the
+ * minimum.
+ *
+ * @see ReducersMinMax
+ * @see op_min
+ */
+template <typename Type, typename Compare>
+class op_min_view : public min_max_internal::view_base<
+ min_max_internal::view_content<Type, Compare, false>,
+ Compare,
+ min_max_internal::reverse_predicate<Compare, Type> >
+{
+ typedef min_max_internal::view_base<
+ min_max_internal::view_content<Type, Compare, false>,
+ Compare,
+ min_max_internal::reverse_predicate<Compare, Type> > base;
+ using base::calc;
+ using base::assign;
+ friend class min_max_internal::rhs_proxy<op_min_view>;
+
+public:
+ /** @name Constructors.
+ *
+ * All op_min_view constructors simply pass their arguments on to the
+ * @ref view_base base class.
+ */
+ //@{
+
+ op_min_view() : base() {}
+
+ template <typename T1>
+ op_min_view(const T1& x1) : base(x1) {}
+
+ template <typename T1, typename T2>
+ op_min_view(const T1& x1, const T2& x2) : base(x1, x2) {}
+
+ //@}
+
+ /** @name View modifier operations.
+ */
+ //@{
+
+ /** Minimize with a value.
+ *
+ * If @a x is less than the current value of the view (as defined by the
+ * reducer’s comparator), or if the view was created without an initial
+ * value and its value has never been updated (with `calc_min()` or
+ * `= min_of()`), then the value of the view is set to @a x.
+ *
+ * @param x The value to minimize the view’s value with.
+ *
+ * @return A reference to the view. (Allows chaining
+ * `view.comp_min(a).comp_min(b)…`.)
+ */
+ op_min_view& calc_min(const Type& x) { calc(x); return *this; }
+
+ /** Assign the result of a `min_of(view, value)` expression to the view.
+ *
+ * @param rhs An rhs_proxy value created by a `min_of(view, value)`
+ * expression.
+ *
+ * @return A reference to the view.
+ *
+ * @see min_max_internal::view_base::rhs_proxy
+ */
+ op_min_view& operator=(const min_max_internal::rhs_proxy<op_min_view>& rhs)
+ { assign(rhs); return *this; }
+};
+
+
+/** Compute the minimum of the value in a view and another value.
+ *
+ * The result of this computation can only be assigned back to the original
+ * view or used in another min_of() call. For example,
+ *
+ * *reducer = min_of(*reducer, x);
+ * *reducer = min_of(x, *reducer);
+ *
+ * @see min_max_internal::view_base::rhs_proxy
+ */
+template <typename Type, typename Compare>
+inline min_max_internal::rhs_proxy< op_min_view<Type, Compare> >
+min_of(const op_min_view<Type, Compare>& view, const Type& value)
+{
+ return min_max_internal::make_proxy(value, view);
+}
+
+/// @copydoc min_of(const op_min_view<Type, Compare>&, const Type&)
+template <typename Type, typename Compare>
+inline min_max_internal::rhs_proxy< op_min_view<Type, Compare> >
+min_of(const Type& value, const op_min_view<Type, Compare>& view)
+{
+ return min_max_internal::make_proxy(value, view);
+}
+
+/** Nested minimum computation.
+ *
+ * Compute the minimum of the result of a min_of() call and another value.
+ *
+ * The result of this computation can only be assigned back to the original
+ * view or wrapper, or used in another min_of() call. For example,
+ *
+ * *reducer = min_of(x, min_of(y, *reducer));
+ * wrapper = min_of(min_of(wrapper, x), y);
+ *
+ * @see min_max_internal::rhs_proxy
+ */
+template <typename Type, typename Compare>
+inline min_max_internal::rhs_proxy< op_min_view<Type, Compare> >
+min_of(const min_max_internal::rhs_proxy< op_min_view<Type, Compare> >& proxy,
+ const Type& value)
+{
+ return proxy.calc(value);
+}
+
+/// @copydoc min_of(const min_max_internal::rhs_proxy< op_min_view<Type, Compare> >&, const Type&)
+template <typename Type, typename Compare>
+inline min_max_internal::rhs_proxy< op_min_view<Type, Compare> >
+min_of(const Type& value,
+ const min_max_internal::rhs_proxy< op_min_view<Type, Compare> >& proxy)
+{
+ return proxy.calc(value);
+}
+
+
+/** Monoid class for minimum reductions. Instantiate the cilk::reducer template
+ * class with an op_min monoid to create a minimum reducer class. For example,
+ * to compute the minimum of a set of `int` values:
+ *
+ * cilk::reducer< cilk::op_min<int> > r;
+ *
+ * @see ReducersMinMax
+ * @see op_min_view
+ */
+template <typename Type, typename Compare=std::less<Type>, bool Align = false>
+class op_min : public min_max_internal::monoid_base<op_min_view<Type, Compare>, Align> {
+ typedef min_max_internal::monoid_base<op_min_view<Type, Compare>, Align> base;
+public:
+ /// Construct with default comparator.
+ op_min() {}
+ /// Construct with specified comparator.
+ op_min(const Compare& compare) : base(compare) {}
+};
+
+//@}
+
+
+/** @defgroup ReducersMinMaxMaxIndex Maximum reducers (value and index)
+ *
+ * These reducers will find the largest value from a set of values, and its
+ * index in the set.
+ *
+ * @ingroup ReducersMinMax
+ */
+//@{
+
+/** The maximum index reducer view class.
+ *
+ * This is the view class for reducers created with
+ * `cilk::reducer< cilk::op_max_index<Index, Type, Compare> >`. It accumulates
+ * the maximum, as determined by a comparator, of a set of values which have
+ * occurred as arguments to the `calc_max()` function, and records the index
+ * of the maximum value. The accumulated value will be the first argument `x`
+ * such that `compare(x, y)` is false for every argument `y`.
+ *
+ * If the comparator is `std::less`, then the accumulated value is the first
+ * argument value which is not less than any other argument value, i.e., the
+ * maximum.
+ *
+ * @note The reducer “dereference†operation (`reducer::operator *()`)
+ * yields a reference to the view. Thus, for example, the view class’s
+ * `calc_max()` function would be used in an expression like
+ * `r->calc_max(i, a)`where `r` is an op_max_index reducer
+ * variable.
+ *
+ * @note The word “index†suggests an integer index into an array, but there
+ * is no restriction on the index type or how it should be used. In
+ * general, it may be convenient to use it for any kind of key that
+ * can be used to locate the maximum value in the collection that it
+ * came from — for example:
+ * - An index into an array.
+ * - A key into an STL map.
+ * - An iterator into any STL container.
+ *
+ * @note A max_index reducer is essentially a max reducer whose value type
+ * is a `std::pair<Index, Type>`. This fact is camouflaged in the view
+ * `calc_max` function, the global `max_of` functions, and the reducer
+ * value constructor, which can all take an index argument and a value
+ * argument as an alternative to a single `std::pair` argument.
+ * However, the reducer `set_value()`, `get_value()`, `move_in()`, and
+ * `move_out()` functions work only with pairs, not with individual
+ * value and/or index arguments.
+ *
+ * @tparam Index The type of the indices associated with the values.
+ * @tparam Type The type of the values compared by the reducer. This will
+ * be the value type of a monoid_with_view that is
+ * instantiated with this view.
+ * @tparam Compare Used to compare the values. It must be a binary predicate.
+ * If it is omitted, then the view computes the conventional
+ * arithmetic maximum.
+ *
+ * @see ReducersMinMax
+ * @see op_max_index
+ */
+template <typename Index, typename Type, typename Compare>
+class op_max_index_view : public min_max_internal::view_base<
+ min_max_internal::index_view_content<Index, Type, Compare, true>,
+ Compare,
+ Compare>
+{
+ typedef min_max_internal::view_base<
+ min_max_internal::index_view_content<Index, Type, Compare, true>,
+ Compare,
+ Compare> base;
+ using base::calc;
+ using base::assign;
+ typedef std::pair<Index, Type> pair_type;
+ friend class min_max_internal::rhs_proxy<op_max_index_view>;
+
+public:
+ /** @name Constructors.
+ *
+ * All op_max_index_view constructors simply pass their arguments on to the
+ * @ref view_base base class, except for the `(index, value [, compare])`
+ * constructors, which create a `std::pair` containing the index and value.
+ */
+ //@{
+
+ op_max_index_view() : base() {}
+
+ template <typename T1>
+ op_max_index_view(const T1& x1) : base(x1) {}
+
+ template <typename T1, typename T2>
+ op_max_index_view(const T1& x1, const T2& x2) : base(x1, x2) {}
+
+ template <typename T1, typename T2, typename T3>
+ op_max_index_view(const T1& x1, const T2& x2, const T3& x3) : base(x1, x2, x3) {}
+
+ op_max_index_view(const Index& i, const Type& v) : base(pair_type(i, v)) {}
+
+ op_max_index_view(const Index& i, const Type& v, const typename base::compare_type* c) :
+ base(pair_type(i, v), c) {}
+
+ //@}
+
+ /** Maximize with a value and index.
+ *
+ * If @a x is greater than the current value of the view (as defined by
+ * the reducer’s comparator), or if the view was created without an
+ * initial value and its value has never been updated (with `calc_max()`
+ * or `= max_of()`), then the value of the view is set to @a x, and the
+ * index is set to @a i..
+ *
+ * @param i The index of the value @a x.
+ * @param x The value to maximize the view’s value with.
+ *
+ * @return A reference to the view. (Allows
+ * `view.comp_max(i, a).comp_max(j, b)…`.)
+ */
+ op_max_index_view& calc_max(const Index& i, const Type& x)
+ { calc(pair_type(i, x)); return *this; }
+
+ /** Maximize with an index/value pair.
+ *
+ * If @a pair.second is greater than the current value of the view (as
+ * defined by the reducer’s comparator), or if the view was created
+ * without an initial value and its value has never been updated (with
+ * `calc_max()` or `= max_of()`), then the value of the view is set to
+ * @a pair.second, and the index is set to @a pair.first.
+ *
+ * @param pair A pair containing a value to maximize the view’s value
+ * with and its associated index.
+ *
+ * @return A reference to the view. (Allows
+ * `view.comp_max(p1).comp_max(p2)…`.)
+ */
+ op_max_index_view& calc_max(const pair_type& pair)
+ { calc(pair); return *this; }
+
+ /** Assign the result of a `max_of(view, index, value)` expression to the
+ * view.
+ *
+ * @param rhs An rhs_proxy value created by a `max_of(view, index, value)`
+ * expression.
+ *
+ * @return A reference to the view.
+ *
+ * @see min_max_internal::view_base::rhs_proxy
+ */
+ op_max_index_view& operator=(const min_max_internal::rhs_proxy<op_max_index_view>& rhs)
+ { assign(rhs); return *this; }
+};
+
+
+/** Compute the maximum of the value in a view and another value.
+ *
+ * The result of this computation can only be assigned back to the original
+ * view or used in another max_of() call. For example,
+ *
+ * *reducer = max_of(*reducer, i, x);
+ * *reducer = max_of(i, x, *reducer);
+ *
+ * @see min_max_internal::rhs_proxy
+ */
+template <typename Index, typename Type, typename Compare>
+inline min_max_internal::rhs_proxy< op_max_index_view<Index, Type, Compare> >
+max_of(const op_max_index_view<Index, Type, Compare>& view,
+ const Index& index, const Type& value)
+{
+ return min_max_internal::make_proxy(std::pair<Index, Type>(index, value), view);
+}
+
+/// @copydoc max_of(const op_max_index_view<Index, Type, Compare>&, const Index&, const Type&)
+template <typename Index, typename Type, typename Compare>
+inline min_max_internal::rhs_proxy< op_max_index_view<Index, Type, Compare> >
+max_of(const Index& index, const Type& value,
+ const op_max_index_view<Index, Type, Compare>& view)
+{
+ return min_max_internal::make_proxy(std::pair<Index, Type>(index, value), view);
+}
+
+/// @copydoc max_of(const op_max_index_view<Index, Type, Compare>&, const Index&, const Type&)
+template <typename Index, typename Type, typename Compare>
+inline min_max_internal::rhs_proxy< op_max_index_view<Index, Type, Compare> >
+max_of(const op_max_index_view<Index, Type, Compare>& view,
+ const std::pair<Index, Type>& pair)
+{
+ return min_max_internal::make_proxy(pair, view);
+}
+
+/// @copydoc max_of(const op_max_index_view<Index, Type, Compare>&, const Index&, const Type&)
+template <typename Index, typename Type, typename Compare>
+inline min_max_internal::rhs_proxy< op_max_index_view<Index, Type, Compare> >
+max_of(const std::pair<Index, Type>& pair,
+ const op_max_index_view<Index, Type, Compare>& view)
+{
+ return min_max_internal::make_proxy(pair, view);
+}
+
+/** Nested computation of the maximum of the value in a view and other values.
+ *
+ * Compute the maximum of the result of a max_of() call and another value.
+ *
+ * The result of this computation can only be assigned back to the original
+ * view or used in another max_of() call. For example,
+ *
+ * *reducer = max_of(x, max_of(y, *reducer));
+ * *reducer = max_of(max_of(*reducer, x), y);
+ *
+ * @see min_max_internal::rhs_proxy
+ */
+template <typename Index, typename Type, typename Compare>
+inline min_max_internal::rhs_proxy< op_max_index_view<Index, Type, Compare> >
+max_of(const min_max_internal::rhs_proxy< op_max_index_view<Index, Type, Compare> >& proxy,
+ const Index& index, const Type& value)
+{
+ return proxy.calc(std::pair<Index, Type>(index, value));
+}
+
+/// @copydoc max_of(const min_max_internal::rhs_proxy< op_max_index_view<Index, Type, Compare> >&, const Index&, const Type&)
+template <typename Index, typename Type, typename Compare>
+inline min_max_internal::rhs_proxy< op_max_index_view<Index, Type, Compare> >
+max_of(const Index& index, const Type& value,
+ const min_max_internal::rhs_proxy< op_max_index_view<Index, Type, Compare> >& proxy)
+{
+ return proxy.calc(std::pair<Index, Type>(index, value));
+}
+
+/// @copydoc max_of(const min_max_internal::rhs_proxy< op_max_index_view<Index, Type, Compare> >&, const Index&, const Type&)
+template <typename Index, typename Type, typename Compare>
+inline min_max_internal::rhs_proxy< op_max_index_view<Index, Type, Compare> >
+max_of(const min_max_internal::rhs_proxy< op_max_index_view<Index, Type, Compare> >& proxy,
+ const std::pair<Index, Type>& pair)
+{
+ return proxy.calc(pair);
+}
+
+/// @copydoc max_of(const min_max_internal::rhs_proxy< op_max_index_view<Index, Type, Compare> >&, const Index&, const Type&)
+template <typename Index, typename Type, typename Compare>
+inline min_max_internal::rhs_proxy< op_max_index_view<Index, Type, Compare> >
+max_of(const std::pair<Index, Type>& pair,
+ const min_max_internal::rhs_proxy< op_max_index_view<Index, Type, Compare> >& proxy)
+{
+ return proxy.calc(pair);
+}
+
+
+/** Monoid class for maximum reductions with index. Instantiate the
+ * cilk::reducer template class with an op_max_index monoid to create a
+ * max_index reducer class. For example, to compute the maximum of an array of
+ * `double` values and the array index of the max value:
+ *
+ * cilk::reducer< cilk::op_max_index<unsigned, double> > r;
+ *
+ * @see ReducersMinMax
+ * @see op_max_index_view
+ */
+template < typename Index
+ , typename Type
+ , typename Compare=std::less<Type>
+ , bool Align = false
+ >
+class op_max_index : public min_max_internal::monoid_base<op_max_index_view<Index, Type, Compare>, Align>
+{
+ typedef min_max_internal::monoid_base<
+ op_max_index_view<Index, Type, Compare>, Align> base;
+public:
+ /// Construct with default comparator.
+ op_max_index() {}
+ /// Construct with specified comparator.
+ op_max_index(const Compare& compare) : base(compare) {}
+};
+
+//@}
+
+
+
+/** @defgroup ReducersMinMaxMinIndex Minimum reducers (value and index)
+ *
+ * These reducers will find the smallest value from a set of values, and its
+ * index in the set.
+ *
+ * @ingroup ReducersMinMax
+ */
+//@{
+
+/** The minimum index reducer view class.
+ *
+ * This is the view class for reducers created with
+ * `cilk::reducer<cilk::op_min_index<Index, Type, Compare> >`. It accumulates
+ * the minimum, as determined by a comparator, of a set of values which have
+ * occurred as arguments to the `calc_min()` function, and records the index
+ * of the minimum value. The accumulated value will be the first argument `x`
+ * such that `compare(y, x)` is false for every argument `y`.
+ *
+ * If the comparator is `std::less`, then the accumulated value is the first
+ * argument value which no other argument value is less than, i.e., the
+ * minimum.
+ *
+ * @note The reducer “dereference†operation (`reducer::operator *()`)
+ * yields a reference to the view. Thus, for example, the view class’s
+ * `calc_min()` function would be
+ * used in an expression like `r->calc_min(i, a)`where `r` is an
+ * op_min_index reducer variable.
+ *
+ * @note The word “index†suggests an integer index into an array, but there
+ * is no restriction on the index type or how it should be used. In
+ * general, it may be convenient to use it for any kind of key that
+ * can be used to locate the minimum value in the collection that it
+ * came from — for example:
+ * - An index into an array.
+ * - A key into an STL map.
+ * - An iterator into any STL container.
+ *
+ * @note A min_index reducer is essentially a min reducer whose value type
+ * is a `std::pair<Index, Type>`. This fact is camouflaged in the view
+ * `calc_min` function, the global `min_of` functions, and the reducer
+ * value constructor, which can all take an index argument and a value
+ * argument as an alternative to a single `std::pair` argument.
+ * However, the reducer `set_value()`, `get_value()`, `move_in()`, and
+ * `move_out()` functions work only with pairs, not with individual
+ * value and/or index arguments.
+ *
+ * @tparam Index The type of the indices associated with the values.
+ * @tparam Type The type of the values compared by the reducer. This will
+ * be the value type of a monoid_with_view that is
+ * instantiated with this view.
+ * @tparam Compare Used to compare the values. It must be a binary predicate.
+ * If it is omitted, then the view computes the conventional
+ * arithmetic minimum.
+ *
+ * @see ReducersMinMax
+ * @see op_min_index
+ */
+template <typename Index, typename Type, typename Compare>
+class op_min_index_view : public min_max_internal::view_base<
+ min_max_internal::index_view_content<Index, Type, Compare, false>,
+ Compare,
+ min_max_internal::reverse_predicate<Compare, Type> >
+{
+ typedef min_max_internal::view_base<
+ min_max_internal::index_view_content<Index, Type, Compare, false>,
+ Compare,
+ min_max_internal::reverse_predicate<Compare, Type> > base;
+ using base::calc;
+ using base::assign;
+ typedef std::pair<Index, Type> pair_type;
+ friend class min_max_internal::rhs_proxy<op_min_index_view>;
+
+public:
+ /** @name Constructors.
+ *
+ * All op_min_index_view constructors simply pass their arguments on to the
+ * @ref view_base base class, except for the `(index, value [, compare])`
+ * constructors, which create a `std::pair` containing the index and value.
+ */
+ //@{
+
+ op_min_index_view() : base() {}
+
+ template <typename T1>
+ op_min_index_view(const T1& x1) : base(x1) {}
+
+ template <typename T1, typename T2>
+ op_min_index_view(const T1& x1, const T2& x2) : base(x1, x2) {}
+
+ template <typename T1, typename T2, typename T3>
+ op_min_index_view(const T1& x1, const T2& x2, const T3& x3) : base(x1, x2, x3) {}
+
+ op_min_index_view(const Index& i, const Type& v) : base(pair_type(i, v)) {}
+
+ op_min_index_view(const Index& i, const Type& v, const typename base::compare_type* c) :
+ base(pair_type(i, v), c) {}
+
+ //@}
+
+ /** Minimize with a value and index.
+ *
+ * If @a x is greater than the current value of the view (as defined by
+ * the reducer’s comparator), or if the view was created without an
+ * initial value and its value has never been updated (with `calc_min()`
+ * or `= min_of()`), then the value of the view is set to @a x, and the
+ * index is set to @a i..
+ *
+ * @param i The index of the value @a x.
+ * @param x The value to minimize the view’s value with.
+ *
+ * @return A reference to the view. (Allows
+ * `view.comp_min(i, a).comp_min(j, b)…`.)
+ */
+ op_min_index_view& calc_min(const Index& i, const Type& x)
+ { calc(pair_type(i, x)); return *this; }
+
+ /** Maximize with an index/value pair.
+ *
+ * If @a pair.second is less than the current value of the view (as
+ * defined by the reducer’s comparator), or if the view was created
+ * without an initial value and its value has never been updated (with
+ * `calc_min()` or `= min_of()`), then the value of the view is set to
+ * @a pair.second, and the index is set to @a pair.first.
+ *
+ * @param pair A pair containing a value to minimize the view’s value
+ * with and its associated index.
+ *
+ * @return A reference to the view. (Allows
+ * `view.comp_min(p1).comp_min(p2)…`.)
+ */
+ op_min_index_view& calc_min(const pair_type& pair)
+ { calc(pair); return *this; }
+
+ /** Assign the result of a `min_of(view, index, value)` expression to the
+ * view.
+ *
+ * @param rhs An rhs_proxy value created by a `min_of(view, index, value)`
+ * expression.
+ *
+ * @return A reference to the view.
+ *
+ * @see min_max_internal::view_base::rhs_proxy
+ */
+ op_min_index_view& operator=(const min_max_internal::rhs_proxy<op_min_index_view>& rhs)
+ { assign(rhs); return *this; }
+};
+
+
+/** Compute the minimum of the value in a view and another value.
+ *
+ * The result of this computation can only be assigned back to the original
+ * view or used in another min_of() call. For example,
+ *
+ * *reducer = min_of(*reducer, i, x);
+ * *reducer = min_of(i, x, *reducer);
+ *
+ * @see min_max_internal::min_min_view_base::rhs_proxy
+ */
+template <typename Index, typename Type, typename Compare>
+inline min_max_internal::rhs_proxy< op_min_index_view<Index, Type, Compare> >
+min_of(const op_min_index_view<Index, Type, Compare>& view,
+ const Index& index, const Type& value)
+{
+ return min_max_internal::make_proxy(std::pair<Index, Type>(index, value), view);
+}
+
+/// @copydoc min_of(const op_min_index_view<Index, Type, Compare>&, const Index&, const Type&)
+template <typename Index, typename Type, typename Compare>
+inline min_max_internal::rhs_proxy< op_min_index_view<Index, Type, Compare> >
+min_of(const Index& index, const Type& value,
+ const op_min_index_view<Index, Type, Compare>& view)
+{
+ return min_max_internal::make_proxy(std::pair<Index, Type>(index, value), view);
+}
+
+/// @copydoc min_of(const op_min_index_view<Index, Type, Compare>&, const Index&, const Type&)
+template <typename Index, typename Type, typename Compare>
+inline min_max_internal::rhs_proxy< op_min_index_view<Index, Type, Compare> >
+min_of(const op_min_index_view<Index, Type, Compare>& view,
+ const std::pair<Index, Type>& pair)
+{
+ return min_max_internal::make_proxy(pair, view);
+}
+
+/// @copydoc min_of(const op_min_index_view<Index, Type, Compare>&, const Index&, const Type&)
+template <typename Index, typename Type, typename Compare>
+inline min_max_internal::rhs_proxy< op_min_index_view<Index, Type, Compare> >
+min_of(const std::pair<Index, Type>& pair,
+ const op_min_index_view<Index, Type, Compare>& view)
+{
+ return min_max_internal::make_proxy(pair, view);
+}
+
+/** Nested computation of the minimum of the value in a view and other values.
+ *
+ * Compute the minimum of the result of a min_of() call and another value.
+ *
+ * The result of this computation can only be assigned back to the original
+ * view or used in another min_of() call. For example,
+ *
+ * *reducer = min_of(x, min_of(y, *reducer));
+ * *reducer = min_of(min_of(*reducer, x), y);
+ *
+ * @see min_max_internal::min_min_view_base::rhs_proxy
+ */
+template <typename Index, typename Type, typename Compare>
+inline min_max_internal::rhs_proxy< op_min_index_view<Index, Type, Compare> >
+min_of(const min_max_internal::rhs_proxy< op_min_index_view<Index, Type, Compare> >& proxy,
+ const Index& index, const Type& value)
+{
+ return proxy.calc(std::pair<Index, Type>(index, value));
+}
+
+/// @copydoc min_of(const min_max_internal::rhs_proxy< op_min_index_view<Index, Type, Compare> >&, const Index&, const Type&)
+template <typename Index, typename Type, typename Compare>
+inline min_max_internal::rhs_proxy< op_min_index_view<Index, Type, Compare> >
+min_of(const Index& index, const Type& value,
+ const min_max_internal::rhs_proxy< op_min_index_view<Index, Type, Compare> >& proxy)
+{
+ return proxy.calc(std::pair<Index, Type>(index, value));
+}
+
+/// @copydoc min_of(const min_max_internal::rhs_proxy< op_min_index_view<Index, Type, Compare> >&, const Index&, const Type&)
+template <typename Index, typename Type, typename Compare>
+inline min_max_internal::rhs_proxy< op_min_index_view<Index, Type, Compare> >
+min_of(const min_max_internal::rhs_proxy< op_min_index_view<Index, Type, Compare> >& proxy,
+ const std::pair<Index, Type>& pair)
+{
+ return proxy.calc(pair);
+}
+
+/// @copydoc min_of(const min_max_internal::rhs_proxy< op_min_index_view<Index, Type, Compare> >&, const Index&, const Type&)
+template <typename Index, typename Type, typename Compare>
+inline min_max_internal::rhs_proxy< op_min_index_view<Index, Type, Compare> >
+min_of(const std::pair<Index, Type>& pair,
+ const min_max_internal::rhs_proxy< op_min_index_view<Index, Type, Compare> >& proxy)
+{
+ return proxy.calc(pair);
+}
+
+
+/** Monoid class for minimum reductions with index. Instantiate the
+ * cilk::reducer template class with an op_min_index monoid to create a
+ * min_index reducer class. For example, to compute the minimum of an array of
+ * `double` values and the array index of the min value:
+ *
+ * cilk::reducer< cilk::op_min_index<unsigned, double> > r;
+ *
+ * @see ReducersMinMax
+ * @see op_min_index_view
+ */
+template < typename Index
+ , typename Type
+ , typename Compare=std::less<Type>
+ , bool Align = false
+ >
+class op_min_index : public min_max_internal::monoid_base<op_min_index_view<Index, Type, Compare>, Align>
+{
+ typedef min_max_internal::monoid_base<
+ op_min_index_view<Index, Type, Compare>, Align> base;
+public:
+ /// Construct with default comparator.
+ op_min_index() {}
+ /// Construct with specified comparator.
+ op_min_index(const Compare& compare) : base(compare) {}
+};
+
+//@}
+
+
+/** Deprecated maximum reducer wrapper class.
+ *
+ * reducer_max is the same as @ref reducer<@ref op_max>, except that
+ * reducer_max is a proxy for the contained view, so that accumulator
+ * variable update operations can be applied directly to the reducer. For
+ * example, a value is maximized with a `reducer<%op_max>` with
+ * `r->calc_max(a)`, but a value can be maximized with a `%reducer_max` with
+ * `r.calc_max(a)`.
+ *
+ *
+ * @deprecated Users are strongly encouraged to use `reducer<monoid>`
+ * reducers rather than the old wrappers like reducer_max.
+ * The `reducer<monoid>` reducers show the reducer/monoid/view
+ * architecture more clearly, are more consistent in their
+ * implementation, and present a simpler model for new
+ * user-implemented reducers.
+ *
+ * @note Implicit conversions are provided between `%reducer_max`
+ * and `reducer<%op_max>`. This allows incremental code
+ * conversion: old code that used `%reducer_max` can pass a
+ * `%reducer_max` to a converted function that now expects a
+ * pointer or reference to a `reducer<%op_max>`, and vice
+ * versa. **But see @ref redminmax_compatibility.**
+ *
+ * @tparam Type The value type of the reducer.
+ * @tparam Compare The “less than†comparator type for the reducer.
+ *
+ * @see op_max
+ * @see op_max_view
+ * @see reducer
+ * @see ReducersMinMax
+ * @ingroup ReducersMinMaxMaxValue
+ */
+template <typename Type, typename Compare=std::less<Type> >
+class reducer_max : public reducer< op_max<Type, Compare, true> >
+{
+ __CILKRTS_STATIC_ASSERT(
+ ::cilk::internal::class_is_empty<
+ typename ::cilk::internal::binary_functor<Compare>::type >::value,
+ "cilk::reducer_max<Type, Compare> only works with "
+ "an empty Compare class");
+ typedef reducer< op_max<Type, Compare, true> > base;
+public:
+
+ /// Type of data in a reducer_max.
+ typedef Type basic_value_type;
+
+ /// The view type for the reducer.
+ typedef typename base::view_type view_type;
+
+ /// The view type for the reducer.
+ typedef typename base::view_type View;
+
+ /// The monoid type for the reducer.
+ typedef typename base::monoid_type monoid_type;
+
+ /// The monoid type for the reducer.
+ typedef typename base::monoid_type Monoid;
+
+ /// The view’s rhs proxy type.
+ typedef min_max_internal::rhs_proxy<View> rhs_proxy;
+
+ using base::view;
+
+ /** @name Constructors
+ */
+ //@{
+
+ /// Construct the wrapper in its identity state (either `!is_set()`, or
+ /// `value() == identity value`).
+ reducer_max() : base() {}
+
+ /// Construct the wrapper with a specified initial value.
+ explicit reducer_max(const Type& initial_value) : base(initial_value) {}
+
+ /// Construct the wrapper in its identity state with a specified
+ /// comparator.
+ explicit reducer_max(const Compare& comp) : base(comp) {}
+
+ /// Construct the wrapper with a specified initial value and a specified
+ /// comparator.
+ reducer_max(const Type& initial_value, const Compare& comp)
+ : base(initial_value, comp) {}
+
+ //@}
+
+ /** @name Forwarded functions
+ * @details Functions that update the contained accumulator variable are
+ * simply forwarded to the contained @ref op_max_view. */
+ //@{
+
+ /// @copydoc cilk_lib_1_0::min_max_internal::view_content::is_set() const
+ bool is_set() const { return view().is_set(); }
+
+ /// @copydoc op_max_view::calc_max(const Type&)
+ reducer_max& calc_max(const Type& x)
+ { view().calc_max(x); return *this; }
+
+ /// @copydoc op_max_view::operator=(const min_max_internal::rhs_proxy<op_max_view>&)
+ reducer_max& operator=(const rhs_proxy& rhs)
+ { view() = rhs; return *this; }
+
+ //@}
+
+ /** Allow read-only access to the value within the current view.
+ *
+ * @returns A const reference to the value within the current view.
+ */
+ const Type& get_reference() const { return view().get_reference(); }
+
+ /// @name Dereference
+ /** Dereferencing a wrapper is a no-op. It simply returns the wrapper.
+ * Combined with the rule that a wrapper forwards view operations to the
+ * view, this means that view operations can be written the same way on
+ * reducers and wrappers, which is convenient for incrementally
+ * converting code using wrappers to code using reducers. That is:
+ *
+ * reducer< op_max<int> > r;
+ * r->calc_max(a); // *r returns the view
+ * // calc_max is a view member function
+ *
+ * reducer_max<int> w;
+ * w->calc_max(a); // *w returns the wrapper
+ * // calc_max is a wrapper member function that
+ * // calls the corresponding view function
+ */
+ //@{
+ reducer_max& operator*() { return *this; }
+ reducer_max const& operator*() const { return *this; }
+
+ reducer_max* operator->() { return this; }
+ reducer_max const* operator->() const { return this; }
+ //@}
+
+ /** @name Upcast
+ * @details In Cilk library 0.9, reducers were always cache-aligned. In
+ * library 1.0, reducer cache alignment is optional. By default, reducers
+ * are unaligned (i.e., just naturally aligned), but legacy wrappers
+ * inherit from cache-aligned reducers for binary compatibility.
+ *
+ * This means that a wrapper will automatically be upcast to its aligned
+ * reducer base class. The following conversion operators provide
+ * pseudo-upcasts to the corresponding unaligned reducer class.
+ */
+ //@{
+ operator reducer< op_max<Type, Compare, false> >& ()
+ {
+ return *reinterpret_cast< reducer< op_max<Type, Compare, false> >* >(this);
+ }
+
+ operator const reducer< op_max<Type, Compare, false> >& () const
+ {
+ return *reinterpret_cast< const reducer< op_max<Type, Compare, false> >* >(this);
+ }
+ //@}
+};
+
+
+/// @cond internal
+// The legacy definition of max_of(reducer_max, value) has different
+// behavior and a different return type than this definition. We add an
+// unused third argument to this version of the function to give it a different
+// signature, so that they won’t end up sharing a single object file entry.
+struct max_of_1_0_t {};
+const max_of_1_0_t max_of_1_0 = {};
+/// @endcond
+
+/** Compute the maximum of the value in a reducer_max and another value.
+ *
+ * @deprecated Because reducer_max is deprecated.
+ *
+ * The result of this computation can only be assigned back to the original
+ * reducer or used in another max_of() call. For example,
+ *
+ * reducer = max_of(reducer, x);
+ * reducer = max_of(x, reducer);
+ *
+ * @see min_max_internal::rhs_proxy
+ *
+ * @ingroup ReducersMinMaxMaxValue
+ */
+template <typename Type, typename Compare>
+inline min_max_internal::rhs_proxy< op_max_view<Type, Compare> >
+max_of(const reducer_max<Type, Compare>& r, const Type& value,
+ const max_of_1_0_t& = max_of_1_0)
+{
+ return min_max_internal::make_proxy(value, r.view());
+}
+
+/// @copydoc max_of(const reducer_max<Type, Compare>&, const Type&, const max_of_1_0_t&)
+/// @ingroup ReducersMinMaxMaxValue
+template <typename Type, typename Compare>
+inline min_max_internal::rhs_proxy< op_max_view<Type, Compare> >
+max_of(const Type& value, const reducer_max<Type, Compare>& r,
+ const max_of_1_0_t& = max_of_1_0)
+{
+ return min_max_internal::make_proxy(value, r.view());
+}
+
+
+/** Deprecated minimum reducer wrapper class.
+ *
+ * reducer_min is the same as @ref reducer<@ref op_min>, except that
+ * reducer_min is a proxy for the contained view, so that accumulator
+ * variable update operations can be applied directly to the reducer. For
+ * example, a value is minimized with a `reducer<%op_min>` with
+ * `r->calc_min(a)`, but a value can be minimized with a `%reducer_min` with
+ * `r.calc_min(a)`.
+ *
+ *
+ * @deprecated Users are strongly encouraged to use `reducer<monoid>`
+ * reducers rather than the old wrappers like reducer_min.
+ * The `reducer<monoid>` reducers show the reducer/monoid/view
+ * architecture more clearly, are more consistent in their
+ * implementation, and present a simpler model for new
+ * user-implemented reducers.
+ *
+ * @note Implicit conversions are provided between `%reducer_min`
+ * and `reducer<%op_min>`. This allows incremental code
+ * conversion: old code that used `%reducer_min` can pass a
+ * `%reducer_min` to a converted function that now expects a
+ * pointer or reference to a `reducer<%op_min>`, and vice
+ * versa. **But see @ref redminmax_compatibility.**
+ *
+ * @tparam Type The value type of the reducer.
+ * @tparam Compare The “less than†comparator type for the reducer.
+ *
+ * @see op_min
+ * @see op_min_view
+ * @see reducer
+ * @see ReducersMinMax
+ * @ingroup ReducersMinMaxMinValue
+ */
+template <typename Type, typename Compare=std::less<Type> >
+class reducer_min : public reducer< op_min<Type, Compare, true> >
+{
+ __CILKRTS_STATIC_ASSERT(
+ ::cilk::internal::class_is_empty<
+ typename ::cilk::internal::binary_functor<Compare>::type >::value,
+ "cilk::reducer_min<Type, Compare> only works with "
+ "an empty Compare class");
+ typedef reducer< op_min<Type, Compare, true> > base;
+public:
+
+ /// Type of data in a reducer_min.
+ typedef Type basic_value_type;
+
+ /// The view type for the reducer.
+ typedef typename base::view_type view_type;
+
+ /// The view type for the reducer.
+ typedef typename base::view_type View;
+
+ /// The monoid type for the reducer.
+ typedef typename base::monoid_type monoid_type;
+
+ /// The monoid type for the reducer.
+ typedef typename base::monoid_type Monoid;
+
+ /// The view’s rhs proxy type.
+ typedef min_max_internal::rhs_proxy<View> rhs_proxy;
+
+ using base::view;
+
+ /** @name Constructors
+ */
+ //@{
+
+ /// Construct the wrapper in its identity state (either `!is_set()`, or
+ /// `value() == identity value`).
+ reducer_min() : base() {}
+
+ /// Construct the wrapper with a specified initial value.
+ explicit reducer_min(const Type& initial_value) : base(initial_value) {}
+
+ /// Construct the wrapper in its identity state with a specified
+ /// comparator.
+ explicit reducer_min(const Compare& comp) : base(comp) {}
+
+ /// Construct the wrapper with a specified initial value and a specified
+ /// comparator.
+ reducer_min(const Type& initial_value, const Compare& comp)
+ : base(initial_value, comp) {}
+
+ //@}
+
+ /** @name Forwarded functions
+ * @details Functions that update the contained accumulator variable are
+ * simply forwarded to the contained @ref op_min_view. */
+ //@{
+
+ /// @copydoc cilk_lib_1_0::min_max_internal::view_content::is_set() const
+ bool is_set() const { return view().is_set(); }
+
+ /// @copydoc op_min_view::calc_min(const Type&)
+ reducer_min& calc_min(const Type& x)
+ { view().calc_min(x); return *this; }
+
+ /// @copydoc op_min_view::operator=(const min_max_internal::rhs_proxy<op_min_view>&)
+ reducer_min& operator=(const rhs_proxy& rhs)
+ { view() = rhs; return *this; }
+
+ //@}
+
+ /** Allow read-only access to the value within the current view.
+ *
+ * @returns A const reference to the value within the current view.
+ */
+ const Type& get_reference() const { return view().get_reference(); }
+
+ /// @name Dereference
+ /** Dereferencing a wrapper is a no-op. It simply returns the wrapper.
+ * Combined with the rule that a wrapper forwards view operations to the
+ * view, this means that view operations can be written the same way on
+ * reducers and wrappers, which is convenient for incrementally
+ * converting code using wrappers to code using reducers. That is:
+ *
+ * reducer< op_min<int> > r;
+ * r->calc_min(a); // *r returns the view
+ * // calc_min is a view member function
+ *
+ * reducer_min<int> w;
+ * w->calc_min(a); // *w returns the wrapper
+ * // calc_min is a wrapper member function that
+ * // calls the corresponding view function
+ */
+ //@{
+ reducer_min& operator*() { return *this; }
+ reducer_min const& operator*() const { return *this; }
+
+ reducer_min* operator->() { return this; }
+ reducer_min const* operator->() const { return this; }
+ //@}
+
+ /** @name Upcast
+ * @details In Cilk library 0.9, reducers were always cache-aligned. In
+ * library 1.0, reducer cache alignment is optional. By default, reducers
+ * are unaligned (i.e., just naturally aligned), but legacy wrappers
+ * inherit from cache-aligned reducers for binary compatibility.
+ *
+ * This means that a wrapper will automatically be upcast to its aligned
+ * reducer base class. The following conversion operators provide
+ * pseudo-upcasts to the corresponding unaligned reducer class.
+ */
+ //@{
+ operator reducer< op_min<Type, Compare, false> >& ()
+ {
+ return *reinterpret_cast< reducer< op_min<Type, Compare, false> >* >(this);
+ }
+
+ operator const reducer< op_min<Type, Compare, false> >& () const
+ {
+ return *reinterpret_cast< const reducer< op_min<Type, Compare, false> >* >(this);
+ }
+ //@}
+};
+
+
+/** Compute the minimum of a reducer and a value.
+ *
+ * @deprecated Because reducer_min is deprecated.
+ */
+//@{
+// The legacy definition of min_of(reducer_min, value) has different
+// behavior and a different return type than this definition. We add an
+// unused third argument to this version of the function to give it a different
+// signature, so that they won’t end up sharing a single object file entry.
+struct min_of_1_0_t {};
+const min_of_1_0_t min_of_1_0 = {};
+
+template <typename Type, typename Compare>
+inline min_max_internal::rhs_proxy< op_min_view<Type, Compare> >
+min_of(const reducer_min<Type, Compare>& r, const Type& value,
+ const min_of_1_0_t& = min_of_1_0)
+{
+ return min_max_internal::make_proxy(value, r.view());
+}
+
+template <typename Type, typename Compare>
+inline min_max_internal::rhs_proxy< op_min_view<Type, Compare> >
+min_of(const Type& value, const reducer_min<Type, Compare>& r,
+ const min_of_1_0_t& = min_of_1_0)
+{
+ return min_max_internal::make_proxy(value, r.view());
+}
+//@}
+
+
+/** Deprecated maximum with index reducer wrapper class.
+ *
+ * reducer_max_index is the same as @ref reducer<@ref op_max_index>, except
+ * that reducer_max_index is a proxy for the contained view, so that
+ * accumulator variable update operations can be applied directly to the
+ * reducer. For example, a value is maximized with a `reducer<%op_max_index>`
+ * with `r->calc_max(i, a)`, but a value can be maximized with a
+ * `%reducer_max` with `r.calc_max(i, aa)`.
+ *
+ *
+ * @deprecated Users are strongly encouraged to use `reducer<monoid>`
+ * reducers rather than the old wrappers like reducer_max.
+ * The `reducer<monoid>` reducers show the reducer/monoid/view
+ * architecture more clearly, are more consistent in their
+ * implementation, and present a simpler model for new
+ * user-implemented reducers.
+ *
+ * @note Implicit conversions are provided between `%reducer_max_index`
+ * and `reducer<%op_max_index>`. This allows incremental code
+ * conversion: old code that used `%reducer_max_index` can pass a
+ * `%reducer_max_index` to a converted function that now expects a
+ * pointer or reference to a `reducer<%op_max_index>`, and vice
+ * versa. **But see @ref redminmax_compatibility.**
+ *
+ * @tparam Index The index type of the reducer.
+ * @tparam Type The value type of the reducer.
+ * @tparam Compare The “less than†comparator type for the reducer.
+ *
+ * @see op_max_index
+ * @see op_max_index_view
+ * @see reducer
+ * @see ReducersMinMax
+ * @ingroup ReducersMinMaxMaxIndex
+ */
+template < typename Index
+ , typename Type
+ , typename Compare = std::less<Type>
+ >
+class reducer_max_index :
+ public reducer< op_max_index<Index, Type, Compare, true> >
+{
+ __CILKRTS_STATIC_ASSERT(
+ ::cilk::internal::class_is_empty<
+ typename ::cilk::internal::binary_functor<Compare>::type >::value,
+ "cilk::reducer_max_index<Type, Compare> only works with "
+ "an empty Compare class");
+ typedef reducer< op_max_index<Index, Type, Compare, true> > base;
+public:
+
+ /// Type of data in a reducer_max_index.
+ typedef Type basic_value_type;
+
+ /// The view type for the reducer.
+ typedef typename base::view_type view_type;
+
+ /// The view type for the reducer.
+ typedef typename base::view_type View;
+
+ /// The monoid type for the reducer.
+ typedef typename base::monoid_type monoid_type;
+
+ /// The monoid type for the reducer.
+ typedef typename base::monoid_type Monoid;
+
+ /// The view’s rhs proxy type.
+ typedef min_max_internal::rhs_proxy<View> rhs_proxy;
+
+ using base::view;
+
+ /** @name Constructors
+ */
+ //@{
+
+ /// Construct the wrapper in its identity state (`!is_set()`).
+ reducer_max_index() : base() {}
+
+ /// Construct with a specified initial index and value.
+ reducer_max_index(const Index& initial_index,
+ const Type& initial_value)
+ : base(initial_index, initial_value) {}
+
+ /// Construct the wrapper with a specified comparator.
+ explicit reducer_max_index(const Compare& comp) : base(comp) {}
+
+ /// Construct the wrapper with a specified initial index, value,
+ /// and comparator.
+ reducer_max_index(const Index& initial_index,
+ const Type& initial_value,
+ const Compare& comp)
+ : base(initial_index, initial_value, comp) {}
+
+ //@}
+
+ /** @name Set / Get
+ */
+ //@{
+
+ /// Set the index and value of this object.
+ void set_value(const Index& index, const Type& value)
+ { base::set_value(std::make_pair(index, value)); }
+
+ /// Return the maximum value.
+ const Type& get_value() const
+ { return view().get_reference(); }
+
+ /// Return the maximum index.
+ const Index& get_index() const
+ { return view().get_index_reference(); }
+
+ /// Return a const reference to value data member in the view.
+ const Type& get_reference() const
+ { return view().get_reference(); }
+
+ /// Return a const reference to index data member in the view.
+ const Index& get_index_reference() const
+ { return view().get_index_reference(); }
+
+ //@}
+
+ /** @name Forwarded functions
+ * @details Functions that update the contained accumulator variable are
+ * simply forwarded to the contained @ref op_max_view. */
+ //@{
+
+ /// @copydoc cilk_lib_1_0::min_max_internal::view_content::is_set() const
+ bool is_set() const { return view().is_set(); }
+
+ /// @copydoc op_max_index_view::calc_max(const Index&, const Type&)
+ reducer_max_index& calc_max(const Index& i, const Type& x)
+ { view().calc_max(i, x); return *this; }
+
+ /// @copydoc op_max_view::operator=(const min_max_internal::rhs_proxy<op_max_view>&)
+ reducer_max_index& operator=(const rhs_proxy& rhs)
+ { view() = rhs; return *this; }
+
+ //@}
+
+ /// @name Dereference
+ /** Dereferencing a wrapper is a no-op. It simply returns the wrapper.
+ * Combined with the rule that a wrapper forwards view operations to the
+ * view, this means that view operations can be written the same way on
+ * reducers and wrappers, which is convenient for incrementally
+ * converting code using wrappers to code using reducers. That is:
+ *
+ * reducer< op_max_index<int, int> > r;
+ * r->calc_max(i, a); // *r returns the view
+ * // calc_max is a view member function
+ *
+ * reducer_max_index<int, int> w;
+ * w->calc_max(i, a); // *w returns the wrapper
+ * // calc_max is a wrapper member function that
+ * // calls the corresponding view function
+ */
+ //@{
+ reducer_max_index& operator*() { return *this; }
+ reducer_max_index const& operator*() const { return *this; }
+
+ reducer_max_index* operator->() { return this; }
+ reducer_max_index const* operator->() const { return this; }
+ //@}
+
+ /** @name Upcast
+ * @details In Cilk library 0.9, reducers were always cache-aligned. In
+ * library 1.0, reducer cache alignment is optional. By default, reducers
+ * are unaligned (i.e., just naturally aligned), but legacy wrappers
+ * inherit from cache-aligned reducers for binary compatibility.
+ *
+ * This means that a wrapper will automatically be upcast to its aligned
+ * reducer base class. The following conversion operators provide
+ * pseudo-upcasts to the corresponding unaligned reducer class.
+ */
+ //@{
+ operator reducer< op_max_index<Index, Type, Compare, false> >& ()
+ {
+ return *reinterpret_cast< reducer< op_max_index<Index, Type, Compare, false> >* >(this);
+ }
+
+ operator const reducer< op_max_index<Index, Type, Compare, false> >& () const
+ {
+ return *reinterpret_cast< const reducer< op_max_index<Index, Type, Compare, false> >* >(this);
+ }
+ //@}
+
+};
+
+
+/** Deprecated minimum with index reducer wrapper class.
+ *
+ * reducer_min_index is the same as @ref reducer<@ref op_min_index>, except
+ * that reducer_min_index is a proxy for the contained view, so that
+ * accumulator variable update operations can be applied directly to the
+ * reducer. For example, a value is minimized with a `reducer<%op_min_index>`
+ * with `r->calc_min(i, a)`, but a value can be minimized with a
+ * `%reducer_min` with `r.calc_min(i, aa)`.
+ *
+ *
+ * @deprecated Users are strongly encouraged to use `reducer<monoid>`
+ * reducers rather than the old wrappers like reducer_min.
+ * The `reducer<monoid>` reducers show the reducer/monoid/view
+ * architecture more clearly, are more consistent in their
+ * implementation, and present a simpler model for new
+ * user-implemented reducers.
+ *
+ * @note Implicit conversions are provided between `%reducer_min_index`
+ * and `reducer<%op_min_index>`. This allows incremental code
+ * conversion: old code that used `%reducer_min_index` can pass a
+ * `%reducer_min_index` to a converted function that now expects a
+ * pointer or reference to a `reducer<%op_min_index>`, and vice
+ * versa. **But see @ref redminmax_compatibility.**
+ *
+ * @tparam Index The index type of the reducer.
+ * @tparam Type The value type of the reducer.
+ * @tparam Compare The “less than†comparator type for the reducer.
+ *
+ * @see op_min_index
+ * @see op_min_index_view
+ * @see reducer
+ * @see ReducersMinMax
+ * @ingroup ReducersMinMaxMinIndex
+ */
+template < typename Index
+ , typename Type
+ , typename Compare = std::less<Type>
+ >
+class reducer_min_index :
+ public reducer< op_min_index<Index, Type, Compare, true> >
+{
+ __CILKRTS_STATIC_ASSERT(
+ ::cilk::internal::class_is_empty<
+ typename ::cilk::internal::binary_functor<Compare>::type >::value,
+ "cilk::reducer_min_index<Type, Compare> only works with "
+ "an empty Compare class");
+ typedef reducer< op_min_index<Index, Type, Compare, true> > base;
+public:
+
+ /// Type of data in a reducer_min_index.
+ typedef Type basic_value_type;
+
+ /// The view type for the reducer.
+ typedef typename base::view_type view_type;
+
+ /// The view type for the reducer.
+ typedef typename base::view_type View;
+
+ /// The monoid type for the reducer.
+ typedef typename base::monoid_type monoid_type;
+
+ /// The monoid type for the reducer.
+ typedef typename base::monoid_type Monoid;
+
+ /// The view’s rhs proxy type.
+ typedef min_max_internal::rhs_proxy<View> rhs_proxy;
+
+ using base::view;
+
+ /** @name Constructors
+ */
+ //@{
+
+ /// Construct the wrapper in its identity state (`!is_set()`).
+ reducer_min_index() : base() {}
+
+ /// Construct with a specified initial index and value.
+ reducer_min_index(const Index& initial_index,
+ const Type& initial_value)
+ : base(initial_index, initial_value) {}
+
+ /// Construct the wrapper with a specified comparator.
+ explicit reducer_min_index(const Compare& comp) : base(comp) {}
+
+ /// Construct the wrapper with a specified initial index, value,
+ /// and comparator.
+ reducer_min_index(const Index& initial_index,
+ const Type& initial_value,
+ const Compare& comp)
+ : base(initial_index, initial_value, comp) {}
+
+ //@}
+
+ /** @name Set / Get
+ */
+ //@{
+
+ /// Set the index and value of this object.
+ void set_value(const Index& index, const Type& value)
+ { base::set_value(std::make_pair(index, value)); }
+
+ /// Return the minimum value.
+ const Type& get_value() const
+ { return view().get_reference(); }
+
+ /// Return the minimum index.
+ const Index& get_index() const
+ { return view().get_index_reference(); }
+
+ /// Return a const reference to value data member in the view.
+ const Type& get_reference() const
+ { return view().get_reference(); }
+
+ /// Return a const reference to index data member in the view.
+ const Index& get_index_reference() const
+ { return view().get_index_reference(); }
+
+ //@}
+
+ /** @name Forwarded functions
+ * @details Functions that update the contained accumulator variable are
+ * simply forwarded to the contained @ref op_min_view. */
+ //@{
+
+ /// @copydoc cilk_lib_1_0::min_max_internal::view_content::is_set() const
+ bool is_set() const { return view().is_set(); }
+
+ /// @copydoc op_min_index_view::calc_min(const Index&, const Type&)
+ reducer_min_index& calc_min(const Index& i, const Type& x)
+ { view().calc_min(i, x); return *this; }
+
+ /// @copydoc op_min_view::operator=(const min_max_internal::rhs_proxy<op_min_view>&)
+ reducer_min_index& operator=(const rhs_proxy& rhs)
+ { view() = rhs; return *this; }
+
+ //@}
+
+ /// @name Dereference
+ /** Dereferencing a wrapper is a no-op. It simply returns the wrapper.
+ * Combined with the rule that a wrapper forwards view operations to the
+ * view, this means that view operations can be written the same way on
+ * reducers and wrappers, which is convenient for incrementally
+ * converting code using wrappers to code using reducers. That is:
+ *
+ * reducer< op_min_index<int, int> > r;
+ * r->calc_min(i, a); // *r returns the view
+ * // calc_min is a view member function
+ *
+ * reducer_min_index<int, int> w;
+ * w->calc_min(i, a); // *w returns the wrapper
+ * // calc_min is a wrapper member function that
+ * // calls the corresponding view function
+ */
+ //@{
+ reducer_min_index& operator*() { return *this; }
+ reducer_min_index const& operator*() const { return *this; }
+
+ reducer_min_index* operator->() { return this; }
+ reducer_min_index const* operator->() const { return this; }
+ //@}
+
+ /** @name Upcast
+ * @details In Cilk library 0.9, reducers were always cache-aligned. In
+ * library 1.0, reducer cache alignment is optional. By default, reducers
+ * are unaligned (i.e., just naturally aligned), but legacy wrappers
+ * inherit from cache-aligned reducers for binary compatibility.
+ *
+ * This means that a wrapper will automatically be upcast to its aligned
+ * reducer base class. The following conversion operators provide
+ * pseudo-upcasts to the corresponding unaligned reducer class.
+ */
+ //@{
+ operator reducer< op_min_index<Index, Type, Compare, false> >& ()
+ {
+ return *reinterpret_cast< reducer< op_min_index<Index, Type, Compare, false> >* >(this);
+ }
+
+ operator const reducer< op_min_index<Index, Type, Compare, false> >& () const
+ {
+ return *reinterpret_cast< const reducer< op_min_index<Index, Type, Compare, false> >* >(this);
+ }
+ //@}
+
+};
+
+
+#ifndef CILK_LIBRARY_0_9_REDUCER_MINMAX
+} // namespace cilk_lib_1_0
+using namespace cilk_lib_1_0;
+#endif
+
+
+/// @cond internal
+/** Metafunction specialization for reducer conversion.
+ *
+ * These specializations of the @ref legacy_reducer_downcast template class
+ * defined in reducer.h causes each `reducer< op_xxxx<Type> >` classes to have
+ * an `operator reducer_xxxx<Type>& ()` conversion operator that statically
+ * downcasts the `reducer<op_xxxx>` to the corresponding `reducer_xxxx` type.
+ * (The reverse conversion, from `reducer_xxxx` to `reducer<op_xxxx>`, is just
+ * an upcast, which is provided for free by the language.)
+ */
+template <typename Type, typename Compare, bool Align>
+struct legacy_reducer_downcast< reducer< op_max<Type, Compare, Align> > >
+{
+ typedef reducer_max<Type> type;
+};
+
+template <typename Type, typename Compare, bool Align>
+struct legacy_reducer_downcast< reducer< op_min<Type, Compare, Align> > >
+{
+ typedef reducer_min<Type> type;
+};
+
+template <typename Index, typename Type, typename Compare, bool Align>
+struct legacy_reducer_downcast< reducer< op_max_index<Index, Type, Compare, Align> > >
+{
+ typedef reducer_max_index<Index, Type> type;
+};
+
+template <typename Index, typename Type, typename Compare, bool Align>
+struct legacy_reducer_downcast< reducer< op_min_index<Index, Type, Compare, Align> > >
+{
+ typedef reducer_min_index<Index, Type> type;
+};
+/// @endcond
+
+} // namespace cilk
+
+#endif // __cplusplus
+
+
+/** @name C language reducer macros
+ *
+ * These macros are used to declare and work with numeric minimum and maximum reducers in C
+ * code.
+ *
+ * @see @ref page_reducers_in_c
+ */
+ //@{
+
+
+#ifdef CILK_C_DEFINE_REDUCERS
+
+/* Integer min/max constants */
+#include <limits.h>
+
+/* Wchar_t min/max constants */
+#if defined(_MSC_VER) || defined(ANDROID)
+# include <wchar.h>
+#else
+# include <stdint.h>
+#endif
+
+/* Floating-point min/max constants */
+#include <math.h>
+#ifndef HUGE_VALF
+ static const unsigned int __huge_valf[] = {0x7f800000};
+# define HUGE_VALF (*((const float *)__huge_valf))
+#endif
+
+#ifndef HUGE_VALL
+ static const unsigned int __huge_vall[] = {0, 0, 0x00007f80, 0};
+# define HUGE_VALL (*((const long double *)__huge_vall))
+#endif
+
+#endif
+
+/** Max reducer type name.
+ *
+ * This macro expands into the identifier which is the name of the max reducer
+ * type for a specified numeric type.
+ *
+ * @param tn The @ref reducers_c_type_names "numeric type name" specifying the type of the
+ * reducer.
+ *
+ * @see @ref reducers_c_predefined
+ */
+#define CILK_C_REDUCER_MAX_TYPE(tn) \
+ __CILKRTS_MKIDENT(cilk_c_reducer_max_,tn)
+
+/** Declare a max reducer object.
+ *
+ * This macro expands into a declaration of a max reducer object for a specified numeric
+ * type. For example:
+ *
+ * CILK_C_REDUCER_MAX(my_reducer, double, -DBL_MAX);
+ *
+ * @param obj The variable name to be used for the declared reducer object.
+ * @param tn The @ref reducers_c_type_names "numeric type name" specifying the type of the
+ * reducer.
+ * @param v The initial value for the reducer. (A value which can be assigned to the
+ * numeric type represented by @a tn.)
+ *
+ * @see @ref reducers_c_predefined
+ */
+#define CILK_C_REDUCER_MAX(obj,tn,v) \
+ CILK_C_REDUCER_MAX_TYPE(tn) obj = \
+ CILK_C_INIT_REDUCER(_Typeof(obj.value), \
+ __CILKRTS_MKIDENT(cilk_c_reducer_max_reduce_,tn), \
+ __CILKRTS_MKIDENT(cilk_c_reducer_max_identity_,tn), \
+ __cilkrts_hyperobject_noop_destroy, v)
+
+/** Maximize with a value.
+ *
+ * `CILK_C_REDUCER_MAX_CALC(reducer, v)` sets the current view of the
+ * reducer to the max of its previous value and a specified new value.
+ * This is equivalent to
+ *
+ * REDUCER_VIEW(reducer) = max(REDUCER_VIEW(reducer), v)
+ *
+ * @param reducer The reducer whose contained value is to be updated.
+ * @param v The value that it is to be maximized with.
+ */
+#define CILK_C_REDUCER_MAX_CALC(reducer, v) do { \
+ _Typeof((reducer).value)* view = &(REDUCER_VIEW(reducer)); \
+ _Typeof(v) __value = (v); \
+ if (*view < __value) { \
+ *view = __value; \
+ } } while (0)
+
+/// @cond internal
+
+/** Declare the max reducer functions for a numeric type.
+ *
+ * This macro expands into external function declarations for functions which implement
+ * the reducer functionality for the max reducer type for a specified numeric type.
+ *
+ * @param t The value type of the reducer.
+ * @param tn The value “type name†identifier, used to construct the reducer type name,
+ * function names, etc.
+ */
+#define CILK_C_REDUCER_MAX_DECLARATION(t,tn,id) \
+ typedef CILK_C_DECLARE_REDUCER(t) CILK_C_REDUCER_MAX_TYPE(tn); \
+ __CILKRTS_DECLARE_REDUCER_REDUCE(cilk_c_reducer_max,tn,l,r); \
+ __CILKRTS_DECLARE_REDUCER_IDENTITY(cilk_c_reducer_max,tn);
+
+/** Define the max reducer functions for a numeric type.
+ *
+ * This macro expands into function definitions for functions which implement the
+ * reducer functionality for the max reducer type for a specified numeric type.
+ *
+ * @param t The value type of the reducer.
+ * @param tn The value “type name†identifier, used to construct the reducer type name,
+ * function names, etc.
+ */
+#define CILK_C_REDUCER_MAX_DEFINITION(t,tn,id) \
+ typedef CILK_C_DECLARE_REDUCER(t) CILK_C_REDUCER_MAX_TYPE(tn); \
+ __CILKRTS_DECLARE_REDUCER_REDUCE(cilk_c_reducer_max,tn,l,r) \
+ { if (*(t*)l < *(t*)r) *(t*)l = *(t*)r; } \
+ __CILKRTS_DECLARE_REDUCER_IDENTITY(cilk_c_reducer_max,tn) \
+ { *(t*)v = id; }
+
+//@{
+/** @def CILK_C_REDUCER_MAX_INSTANCE
+ * @brief Declare or define implementation functions for a reducer type.
+ *
+ * In the runtime source file c_reducers.c, the macro `CILK_C_DEFINE_REDUCERS` will be defined, and
+ * this macro will generate reducer implementation functions. Everywhere else, `CILK_C_DEFINE_REDUCERS`
+ * will be undefined, and this macro will expand into external declarations for the functions.
+ */
+#ifdef CILK_C_DEFINE_REDUCERS
+# define CILK_C_REDUCER_MAX_INSTANCE(t,tn,id) \
+ CILK_C_REDUCER_MAX_DEFINITION(t,tn,id)
+#else
+# define CILK_C_REDUCER_MAX_INSTANCE(t,tn,id) \
+ CILK_C_REDUCER_MAX_DECLARATION(t,tn,id)
+#endif
+//@}
+
+/* Declare or define an instance of the reducer type and its functions for each
+ * numeric type.
+ */
+__CILKRTS_BEGIN_EXTERN_C
+CILK_C_REDUCER_MAX_INSTANCE(char, char, CHAR_MIN)
+CILK_C_REDUCER_MAX_INSTANCE(unsigned char, uchar, 0)
+CILK_C_REDUCER_MAX_INSTANCE(signed char, schar, SCHAR_MIN)
+CILK_C_REDUCER_MAX_INSTANCE(wchar_t, wchar_t, WCHAR_MIN)
+CILK_C_REDUCER_MAX_INSTANCE(short, short, SHRT_MIN)
+CILK_C_REDUCER_MAX_INSTANCE(unsigned short, ushort, 0)
+CILK_C_REDUCER_MAX_INSTANCE(int, int, INT_MIN)
+CILK_C_REDUCER_MAX_INSTANCE(unsigned int, uint, 0)
+CILK_C_REDUCER_MAX_INSTANCE(unsigned int, unsigned, 0) // alternate name
+CILK_C_REDUCER_MAX_INSTANCE(long, long, LONG_MIN)
+CILK_C_REDUCER_MAX_INSTANCE(unsigned long, ulong, 0)
+CILK_C_REDUCER_MAX_INSTANCE(long long, longlong, LLONG_MIN)
+CILK_C_REDUCER_MAX_INSTANCE(unsigned long long, ulonglong, 0)
+CILK_C_REDUCER_MAX_INSTANCE(float, float, -HUGE_VALF)
+CILK_C_REDUCER_MAX_INSTANCE(double, double, -HUGE_VAL)
+CILK_C_REDUCER_MAX_INSTANCE(long double, longdouble, -HUGE_VALL)
+__CILKRTS_END_EXTERN_C
+
+/// @endcond
+
+/** Max_index reducer type name.
+ *
+ * This macro expands into the identifier which is the name of the max_index reducer
+ * type for a specified numeric type.
+ *
+ * @param tn The @ref reducers_c_type_names "numeric type name" specifying the type of the
+ * reducer.
+ *
+ * @see @ref reducers_c_predefined
+ */
+#define CILK_C_REDUCER_MAX_INDEX_TYPE(tn) \
+ __CILKRTS_MKIDENT(cilk_c_reducer_max_index_,tn)
+
+/** Declare an op_max_index reducer object.
+ *
+ * This macro expands into a declaration of a max_index reducer object for a specified
+ * numeric type. For example:
+ *
+ * CILK_C_REDUCER_MAX_INDEX(my_reducer, double, -DBL_MAX_INDEX);
+ *
+ * @param obj The variable name to be used for the declared reducer object.
+ * @param tn The @ref reducers_c_type_names "numeric type name" specifying the type of the
+ * reducer.
+ * @param v The initial value for the reducer. (A value which can be assigned to the
+ * numeric type represented by @a tn.)
+ *
+ * @see @ref reducers_c_predefined
+ */
+#define CILK_C_REDUCER_MAX_INDEX(obj,tn,v) \
+ CILK_C_REDUCER_MAX_INDEX_TYPE(tn) obj = \
+ CILK_C_INIT_REDUCER(_Typeof(obj.value), \
+ __CILKRTS_MKIDENT(cilk_c_reducer_max_index_reduce_,tn), \
+ __CILKRTS_MKIDENT(cilk_c_reducer_max_index_identity_,tn), \
+ __cilkrts_hyperobject_noop_destroy, {0, v})
+
+/** Maximize with a value.
+ *
+ * `CILK_C_REDUCER_MAX_INDEX_CALC(reducer, i, v)` sets the current view of the
+ * reducer to the max of its previous value and a specified new value.
+ * This is equivalent to
+ *
+ * REDUCER_VIEW(reducer) = max_index(REDUCER_VIEW(reducer), v)
+ *
+ * If the value of the reducer is changed to @a v, then the index of the reducer is
+ * changed to @a i.
+ *
+ * @param reducer The reducer whose contained value and index are to be updated.
+ * @param i The index associated with the new value.
+ * @param v The value that it is to be maximized with.
+ */
+#define CILK_C_REDUCER_MAX_INDEX_CALC(reducer, i, v) do { \
+ _Typeof((reducer).value)* view = &(REDUCER_VIEW(reducer)); \
+ _Typeof(v) __value = (v); \
+ if (view->value < __value) { \
+ view->index = (i); \
+ view->value = __value; \
+ } } while (0)
+
+/// @cond internal
+
+/** Declare the max_index view type.
+ *
+ * The view of a max_index reducer is a structure containing both the
+ * maximum value for the reducer and the index that was associated with
+ * that value in the sequence of input values.
+ */
+#define CILK_C_REDUCER_MAX_INDEX_VIEW(t,tn) \
+ typedef struct { \
+ __STDNS ptrdiff_t index; \
+ t value; \
+ } __CILKRTS_MKIDENT(cilk_c_reducer_max_index_view_,tn)
+
+/** Declare the max_index reducer functions for a numeric type.
+ *
+ * This macro expands into external function declarations for functions which implement
+ * the reducer functionality for the max_index reducer type for a specified numeric type.
+ *
+ * @param t The value type of the reducer.
+ * @param tn The value “type name†identifier, used to construct the reducer type name,
+ * function names, etc.
+ */
+#define CILK_C_REDUCER_MAX_INDEX_DECLARATION(t,tn,id) \
+ CILK_C_REDUCER_MAX_INDEX_VIEW(t,tn); \
+ typedef CILK_C_DECLARE_REDUCER( \
+ __CILKRTS_MKIDENT(cilk_c_reducer_max_index_view_,tn)) \
+ CILK_C_REDUCER_MAX_INDEX_TYPE(tn); \
+ __CILKRTS_DECLARE_REDUCER_REDUCE(cilk_c_reducer_max_index,tn,l,r); \
+ __CILKRTS_DECLARE_REDUCER_IDENTITY(cilk_c_reducer_max_index,tn);
+
+/** Define the max_index reducer functions for a numeric type.
+ *
+ * This macro expands into function definitions for functions which implement the
+ * reducer functionality for the max_index reducer type for a specified numeric type.
+ *
+ * @param t The value type of the reducer.
+ * @param tn The value “type name†identifier, used to construct the reducer type name,
+ * function names, etc.
+ */
+#define CILK_C_REDUCER_MAX_INDEX_DEFINITION(t,tn,id) \
+ CILK_C_REDUCER_MAX_INDEX_VIEW(t,tn); \
+ typedef CILK_C_DECLARE_REDUCER( \
+ __CILKRTS_MKIDENT(cilk_c_reducer_max_index_view_,tn)) \
+ CILK_C_REDUCER_MAX_INDEX_TYPE(tn); \
+ __CILKRTS_DECLARE_REDUCER_REDUCE(cilk_c_reducer_max_index,tn,l,r) \
+ { typedef __CILKRTS_MKIDENT(cilk_c_reducer_max_index_view_,tn) view_t; \
+ if (((view_t*)l)->value < ((view_t*)r)->value) \
+ *(view_t*)l = *(view_t*)r; } \
+ __CILKRTS_DECLARE_REDUCER_IDENTITY(cilk_c_reducer_max_index,tn) \
+ { typedef __CILKRTS_MKIDENT(cilk_c_reducer_max_index_view_,tn) view_t; \
+ ((view_t*)v)->index = 0; ((view_t*)v)->value = id; }
+
+//@{
+/** @def CILK_C_REDUCER_MAX_INDEX_INSTANCE
+ * @brief Declare or define implementation functions for a reducer type.
+ *
+ * In the runtime source file c_reducers.c, the macro `CILK_C_DEFINE_REDUCERS` will be defined, and
+ * this macro will generate reducer implementation functions. Everywhere else, `CILK_C_DEFINE_REDUCERS`
+ * will be undefined, and this macro will expand into external declarations for the functions.
+ */
+#ifdef CILK_C_DEFINE_REDUCERS
+# define CILK_C_REDUCER_MAX_INDEX_INSTANCE(t,tn,id) \
+ CILK_C_REDUCER_MAX_INDEX_DEFINITION(t,tn,id)
+#else
+# define CILK_C_REDUCER_MAX_INDEX_INSTANCE(t,tn,id) \
+ CILK_C_REDUCER_MAX_INDEX_DECLARATION(t,tn,id)
+#endif
+//@}
+
+/* Declare or define an instance of the reducer type and its functions for each
+ * numeric type.
+ */
+__CILKRTS_BEGIN_EXTERN_C
+CILK_C_REDUCER_MAX_INDEX_INSTANCE(char, char, CHAR_MIN)
+CILK_C_REDUCER_MAX_INDEX_INSTANCE(unsigned char, uchar, 0)
+CILK_C_REDUCER_MAX_INDEX_INSTANCE(signed char, schar, SCHAR_MIN)
+CILK_C_REDUCER_MAX_INDEX_INSTANCE(wchar_t, wchar_t, WCHAR_MIN)
+CILK_C_REDUCER_MAX_INDEX_INSTANCE(short, short, SHRT_MIN)
+CILK_C_REDUCER_MAX_INDEX_INSTANCE(unsigned short, ushort, 0)
+CILK_C_REDUCER_MAX_INDEX_INSTANCE(int, int, INT_MIN)
+CILK_C_REDUCER_MAX_INDEX_INSTANCE(unsigned int, uint, 0)
+CILK_C_REDUCER_MAX_INDEX_INSTANCE(unsigned int, unsigned, 0) // alternate name
+CILK_C_REDUCER_MAX_INDEX_INSTANCE(long, long, LONG_MIN)
+CILK_C_REDUCER_MAX_INDEX_INSTANCE(unsigned long, ulong, 0)
+CILK_C_REDUCER_MAX_INDEX_INSTANCE(long long, longlong, LLONG_MIN)
+CILK_C_REDUCER_MAX_INDEX_INSTANCE(unsigned long long, ulonglong, 0)
+CILK_C_REDUCER_MAX_INDEX_INSTANCE(float, float, -HUGE_VALF)
+CILK_C_REDUCER_MAX_INDEX_INSTANCE(double, double, -HUGE_VAL)
+CILK_C_REDUCER_MAX_INDEX_INSTANCE(long double, longdouble, -HUGE_VALL)
+__CILKRTS_END_EXTERN_C
+
+/// @endcond
+
+/** Min reducer type name.
+ *
+ * This macro expands into the identifier which is the name of the min reducer
+ * type for a specified numeric type.
+ *
+ * @param tn The @ref reducers_c_type_names "numeric type name" specifying the type of the
+ * reducer.
+ *
+ * @see @ref reducers_c_predefined
+ */
+#define CILK_C_REDUCER_MIN_TYPE(tn) \
+ __CILKRTS_MKIDENT(cilk_c_reducer_min_,tn)
+
+/** Declare a min reducer object.
+ *
+ * This macro expands into a declaration of a min reducer object for a specified numeric
+ * type. For example:
+ *
+ * CILK_C_REDUCER_MIN(my_reducer, double, DBL_MAX);
+ *
+ * @param obj The variable name to be used for the declared reducer object.
+ * @param tn The @ref reducers_c_type_names "numeric type name" specifying the type of the
+ * reducer.
+ * @param v The initial value for the reducer. (A value which can be assigned to the
+ * numeric type represented by @a tn.)
+ *
+ * @see @ref reducers_c_predefined
+ */
+#define CILK_C_REDUCER_MIN(obj,tn,v) \
+ CILK_C_REDUCER_MIN_TYPE(tn) obj = \
+ CILK_C_INIT_REDUCER(_Typeof(obj.value), \
+ __CILKRTS_MKIDENT(cilk_c_reducer_min_reduce_,tn), \
+ __CILKRTS_MKIDENT(cilk_c_reducer_min_identity_,tn), \
+ __cilkrts_hyperobject_noop_destroy, v)
+
+/** Minimize with a value.
+ *
+ * `CILK_C_REDUCER_MIN_CALC(reducer, v)` sets the current view of the
+ * reducer to the min of its previous value and a specified new value.
+ * This is equivalent to
+ *
+ * REDUCER_VIEW(reducer) = min(REDUCER_VIEW(reducer), v)
+ *
+ * @param reducer The reducer whose contained value is to be updated.
+ * @param v The value that it is to be minimized with.
+ */
+#define CILK_C_REDUCER_MIN_CALC(reducer, v) do { \
+ _Typeof((reducer).value)* view = &(REDUCER_VIEW(reducer)); \
+ _Typeof(v) __value = (v); \
+ if (*view > __value) { \
+ *view = __value; \
+ } } while (0)
+
+/// @cond internal
+
+/** Declare the min reducer functions for a numeric type.
+ *
+ * This macro expands into external function declarations for functions which implement
+ * the reducer functionality for the min reducer type for a specified numeric type.
+ *
+ * @param t The value type of the reducer.
+ * @param tn The value “type name†identifier, used to construct the reducer type name,
+ * function names, etc.
+ */
+#define CILK_C_REDUCER_MIN_DECLARATION(t,tn,id) \
+ typedef CILK_C_DECLARE_REDUCER(t) CILK_C_REDUCER_MIN_TYPE(tn); \
+ __CILKRTS_DECLARE_REDUCER_REDUCE(cilk_c_reducer_min,tn,l,r); \
+ __CILKRTS_DECLARE_REDUCER_IDENTITY(cilk_c_reducer_min,tn);
+
+/** Define the min reducer functions for a numeric type.
+ *
+ * This macro expands into function definitions for functions which implement the
+ * reducer functionality for the min reducer type for a specified numeric type.
+ *
+ * @param t The value type of the reducer.
+ * @param tn The value “type name†identifier, used to construct the reducer type name,
+ * function names, etc.
+ */
+#define CILK_C_REDUCER_MIN_DEFINITION(t,tn,id) \
+ typedef CILK_C_DECLARE_REDUCER(t) CILK_C_REDUCER_MIN_TYPE(tn); \
+ __CILKRTS_DECLARE_REDUCER_REDUCE(cilk_c_reducer_min,tn,l,r) \
+ { if (*(t*)l > *(t*)r) *(t*)l = *(t*)r; } \
+ __CILKRTS_DECLARE_REDUCER_IDENTITY(cilk_c_reducer_min,tn) \
+ { *(t*)v = id; }
+
+//@{
+/** @def CILK_C_REDUCER_MIN_INSTANCE
+ * @brief Declare or define implementation functions for a reducer type.
+ *
+ * In the runtime source file c_reducers.c, the macro `CILK_C_DEFINE_REDUCERS` will be defined, and
+ * this macro will generate reducer implementation functions. Everywhere else, `CILK_C_DEFINE_REDUCERS`
+ * will be undefined, and this macro will expand into external declarations for the functions.
+ */
+#ifdef CILK_C_DEFINE_REDUCERS
+# define CILK_C_REDUCER_MIN_INSTANCE(t,tn,id) \
+ CILK_C_REDUCER_MIN_DEFINITION(t,tn,id)
+#else
+# define CILK_C_REDUCER_MIN_INSTANCE(t,tn,id) \
+ CILK_C_REDUCER_MIN_DECLARATION(t,tn,id)
+#endif
+//@}
+
+/* Declare or define an instance of the reducer type and its functions for each
+ * numeric type.
+ */
+__CILKRTS_BEGIN_EXTERN_C
+CILK_C_REDUCER_MIN_INSTANCE(char, char, CHAR_MAX)
+CILK_C_REDUCER_MIN_INSTANCE(unsigned char, uchar, CHAR_MAX)
+CILK_C_REDUCER_MIN_INSTANCE(signed char, schar, SCHAR_MAX)
+CILK_C_REDUCER_MIN_INSTANCE(wchar_t, wchar_t, WCHAR_MAX)
+CILK_C_REDUCER_MIN_INSTANCE(short, short, SHRT_MAX)
+CILK_C_REDUCER_MIN_INSTANCE(unsigned short, ushort, USHRT_MAX)
+CILK_C_REDUCER_MIN_INSTANCE(int, int, INT_MAX)
+CILK_C_REDUCER_MIN_INSTANCE(unsigned int, uint, UINT_MAX)
+CILK_C_REDUCER_MIN_INSTANCE(unsigned int, unsigned, UINT_MAX) // alternate name
+CILK_C_REDUCER_MIN_INSTANCE(long, long, LONG_MAX)
+CILK_C_REDUCER_MIN_INSTANCE(unsigned long, ulong, ULONG_MAX)
+CILK_C_REDUCER_MIN_INSTANCE(long long, longlong, LLONG_MAX)
+CILK_C_REDUCER_MIN_INSTANCE(unsigned long long, ulonglong, ULLONG_MAX)
+CILK_C_REDUCER_MIN_INSTANCE(float, float, HUGE_VALF)
+CILK_C_REDUCER_MIN_INSTANCE(double, double, HUGE_VAL)
+CILK_C_REDUCER_MIN_INSTANCE(long double, longdouble, HUGE_VALL)
+__CILKRTS_END_EXTERN_C
+
+/// @endcond
+
+/** Min_index reducer type name.
+ *
+ * This macro expands into the identifier which is the name of the min_index reducer
+ * type for a specified numeric type.
+ *
+ * @param tn The @ref reducers_c_type_names "numeric type name" specifying the type of the
+ * reducer.
+ *
+ * @see @ref reducers_c_predefined
+ */
+#define CILK_C_REDUCER_MIN_INDEX_TYPE(tn) \
+ __CILKRTS_MKIDENT(cilk_c_reducer_min_index_,tn)
+
+/** Declare an op_min_index reducer object.
+ *
+ * This macro expands into a declaration of a min_index reducer object for a specified
+ * numeric type. For example:
+ *
+ * CILK_C_REDUCER_MIN_INDEX(my_reducer, double, -DBL_MIN_INDEX);
+ *
+ * @param obj The variable name to be used for the declared reducer object.
+ * @param tn The @ref reducers_c_type_names "numeric type name" specifying the type of the
+ * reducer.
+ * @param v The initial value for the reducer. (A value which can be assigned to the
+ * numeric type represented by @a tn.)
+ *
+ * @see @ref reducers_c_predefined
+ */
+#define CILK_C_REDUCER_MIN_INDEX(obj,tn,v) \
+ CILK_C_REDUCER_MIN_INDEX_TYPE(tn) obj = \
+ CILK_C_INIT_REDUCER(_Typeof(obj.value), \
+ __CILKRTS_MKIDENT(cilk_c_reducer_min_index_reduce_,tn), \
+ __CILKRTS_MKIDENT(cilk_c_reducer_min_index_identity_,tn), \
+ __cilkrts_hyperobject_noop_destroy, {0, v})
+
+/** Minimize with a value.
+ *
+ * `CILK_C_REDUCER_MIN_INDEX_CALC(reducer, i, v)` sets the current view of the
+ * reducer to the min of its previous value and a specified new value.
+ * This is equivalent to
+ *
+ * REDUCER_VIEW(reducer) = min_index(REDUCER_VIEW(reducer), v)
+ *
+ * If the value of the reducer is changed to @a v, then the index of the reducer is
+ * changed to @a i.
+ *
+ * @param reducer The reducer whose contained value and index are to be updated.
+ * @param i The index associated with the new value.
+ * @param v The value that it is to be minimized with.
+ */
+#define CILK_C_REDUCER_MIN_INDEX_CALC(reducer, i, v) do { \
+ _Typeof((reducer).value)* view = &(REDUCER_VIEW(reducer)); \
+ _Typeof(v) __value = (v); \
+ if (view->value > __value) { \
+ view->index = (i); \
+ view->value = __value; \
+ } } while (0)
+
+/// @cond internal
+
+/** Declare the min_index view type.
+ *
+ * The view of a min_index reducer is a structure containing both the
+ * minimum value for the reducer and the index that was associated with
+ * that value in the sequence of input values.
+ */
+#define CILK_C_REDUCER_MIN_INDEX_VIEW(t,tn) \
+ typedef struct { \
+ __STDNS ptrdiff_t index; \
+ t value; \
+ } __CILKRTS_MKIDENT(cilk_c_reducer_min_index_view_,tn)
+
+/** Declare the min_index reducer functions for a numeric type.
+ *
+ * This macro expands into external function declarations for functions which implement
+ * the reducer functionality for the min_index reducer type for a specified numeric type.
+ *
+ * @param t The value type of the reducer.
+ * @param tn The value “type name†identifier, used to construct the reducer type name,
+ * function names, etc.
+ */
+#define CILK_C_REDUCER_MIN_INDEX_DECLARATION(t,tn,id) \
+ CILK_C_REDUCER_MIN_INDEX_VIEW(t,tn); \
+ typedef CILK_C_DECLARE_REDUCER( \
+ __CILKRTS_MKIDENT(cilk_c_reducer_min_index_view_,tn)) \
+ CILK_C_REDUCER_MIN_INDEX_TYPE(tn); \
+ __CILKRTS_DECLARE_REDUCER_REDUCE(cilk_c_reducer_min_index,tn,l,r); \
+ __CILKRTS_DECLARE_REDUCER_IDENTITY(cilk_c_reducer_min_index,tn);
+
+/** Define the min_index reducer functions for a numeric type.
+ *
+ * This macro expands into function definitions for functions which implement the
+ * reducer functionality for the min_index reducer type for a specified numeric type.
+ *
+ * @param t The value type of the reducer.
+ * @param tn The value “type name†identifier, used to construct the reducer type name,
+ * function names, etc.
+ */
+#define CILK_C_REDUCER_MIN_INDEX_DEFINITION(t,tn,id) \
+ CILK_C_REDUCER_MIN_INDEX_VIEW(t,tn); \
+ typedef CILK_C_DECLARE_REDUCER( \
+ __CILKRTS_MKIDENT(cilk_c_reducer_min_index_view_,tn)) \
+ CILK_C_REDUCER_MIN_INDEX_TYPE(tn); \
+ __CILKRTS_DECLARE_REDUCER_REDUCE(cilk_c_reducer_min_index,tn,l,r) \
+ { typedef __CILKRTS_MKIDENT(cilk_c_reducer_min_index_view_,tn) view_t; \
+ if (((view_t*)l)->value > ((view_t*)r)->value) \
+ *(view_t*)l = *(view_t*)r; } \
+ __CILKRTS_DECLARE_REDUCER_IDENTITY(cilk_c_reducer_min_index,tn) \
+ { typedef __CILKRTS_MKIDENT(cilk_c_reducer_min_index_view_,tn) view_t; \
+ ((view_t*)v)->index = 0; ((view_t*)v)->value = id; }
+
+//@{
+/** @def CILK_C_REDUCER_MIN_INDEX_INSTANCE
+ * @brief Declare or define implementation functions for a reducer type.
+ *
+ * In the runtime source file c_reducers.c, the macro `CILK_C_DEFINE_REDUCERS` will be defined, and
+ * this macro will generate reducer implementation functions. Everywhere else, `CILK_C_DEFINE_REDUCERS`
+ * will be undefined, and this macro will expand into external declarations for the functions.
+ */
+#ifdef CILK_C_DEFINE_REDUCERS
+# define CILK_C_REDUCER_MIN_INDEX_INSTANCE(t,tn,id) \
+ CILK_C_REDUCER_MIN_INDEX_DEFINITION(t,tn,id)
+#else
+# define CILK_C_REDUCER_MIN_INDEX_INSTANCE(t,tn,id) \
+ CILK_C_REDUCER_MIN_INDEX_DECLARATION(t,tn,id)
+#endif
+//@}
+
+/* Declare or define an instance of the reducer type and its functions for each
+ * numeric type.
+ */
+__CILKRTS_BEGIN_EXTERN_C
+CILK_C_REDUCER_MIN_INDEX_INSTANCE(char, char, CHAR_MAX)
+CILK_C_REDUCER_MIN_INDEX_INSTANCE(unsigned char, uchar, CHAR_MAX)
+CILK_C_REDUCER_MIN_INDEX_INSTANCE(signed char, schar, SCHAR_MAX)
+CILK_C_REDUCER_MIN_INDEX_INSTANCE(wchar_t, wchar_t, WCHAR_MAX)
+CILK_C_REDUCER_MIN_INDEX_INSTANCE(short, short, SHRT_MAX)
+CILK_C_REDUCER_MIN_INDEX_INSTANCE(unsigned short, ushort, USHRT_MAX)
+CILK_C_REDUCER_MIN_INDEX_INSTANCE(int, int, INT_MAX)
+CILK_C_REDUCER_MIN_INDEX_INSTANCE(unsigned int, uint, UINT_MAX)
+CILK_C_REDUCER_MIN_INDEX_INSTANCE(unsigned int, unsigned, UINT_MAX) // alternate name
+CILK_C_REDUCER_MIN_INDEX_INSTANCE(long, long, LONG_MAX)
+CILK_C_REDUCER_MIN_INDEX_INSTANCE(unsigned long, ulong, ULONG_MAX)
+CILK_C_REDUCER_MIN_INDEX_INSTANCE(long long, longlong, LLONG_MAX)
+CILK_C_REDUCER_MIN_INDEX_INSTANCE(unsigned long long, ulonglong, ULLONG_MAX)
+CILK_C_REDUCER_MIN_INDEX_INSTANCE(float, float, HUGE_VALF)
+CILK_C_REDUCER_MIN_INDEX_INSTANCE(double, double, HUGE_VAL)
+CILK_C_REDUCER_MIN_INDEX_INSTANCE(long double, longdouble, HUGE_VALL)
+__CILKRTS_END_EXTERN_C
+
+/// @endcond
+
+//@}
+
+#endif // defined REDUCER_MAX_H_INCLUDED
diff --git a/libcilkrts/include/cilk/reducer_opadd.h b/libcilkrts/include/cilk/reducer_opadd.h
new file mode 100644
index 00000000000..4b7a83f845d
--- /dev/null
+++ b/libcilkrts/include/cilk/reducer_opadd.h
@@ -0,0 +1,690 @@
+/* reducer_opadd.h -*- C++ -*-
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file reducer_opadd.h
+ *
+ * @brief Defines classes for doing parallel addition reductions.
+ *
+ * @ingroup ReducersAdd
+ *
+ * @see ReducersAdd
+ */
+
+#ifndef REDUCER_OPADD_H_INCLUDED
+#define REDUCER_OPADD_H_INCLUDED
+
+#include <cilk/reducer.h>
+
+/** @defgroup ReducersAdd Addition Reducers
+ *
+ * Addition reducers allow the computation of the sum of a set of values in
+ * parallel.
+ *
+ * @ingroup Reducers
+ *
+ * You should be familiar with @ref pagereducers "Cilk reducers", described in
+ * file `reducers.md`, and particularly with @ref reducers_using, before trying
+ * to use the information in this file.
+ *
+ * @section redopadd_usage Usage Example
+ *
+ * cilk::reducer< cilk::op_add<int> > r;
+ * cilk_for (int i = 0; i != N; ++i) {
+ * *r += a[i];
+ * }
+ * return r.get_value();
+ *
+ * @section redopadd_monoid The Monoid
+ *
+ * @subsection redopadd_monoid_values Value Set
+ *
+ * The value set of an addition reducer is the set of values of `Type`, which
+ * is expected to be a builtin numeric type (or something like it, such as
+ * `std::complex`).
+ *
+ * @subsection redopadd_monoid_operator Operator
+ *
+ * The operator of an addition reducer is the addition operator, defined by
+ * the “`+`†binary operator on `Type`.
+ *
+ * @subsection redopadd_monoid_identity Identity
+ *
+ * The identity value of the reducer is the numeric value “`0`â€. This is
+ * expected to be the value of the default constructor `Type()`.
+ *
+ * @section redopadd_operations Operations
+ *
+ * @subsection redopadd_constructors Constructors
+ *
+ * reducer() // identity
+ * reducer(const Type& value)
+ * reducer(move_in(Type& variable))
+ *
+ * @subsection redopadd_get_set Set and Get
+ *
+ * r.set_value(const Type& value)
+ * const Type& = r.get_value() const
+ * r.move_in(Type& variable)
+ * r.move_out(Type& variable)
+ *
+ * @subsection redopadd_initial Initial Values
+ *
+ * If an addition reducer is constructed without an explicit initial value,
+ * then its initial value will be its identity value, as long as `Type`
+ * satisfies the requirements of @ref redopadd_types.
+ *
+ * @subsection redopadd_view_ops View Operations
+ *
+ * *r += a
+ * *r -= a
+ * ++*r
+ * --*r
+ * (*r)++
+ * (*r)--
+ * *r = *r + a
+ * *r = *r - a
+ * *r = *r ± a1 ± a2 … ± an
+ *
+ * The post-increment and post-decrement operations do not return a value. (If
+ * they did, they would expose the value contained in the view, which is
+ * non-deterministic in the middle of a reduction.)
+ *
+ * Note that subtraction operations are allowed on an addition reducer because
+ * subtraction is equivalent to addition with a negated operand. It is true
+ * that `(x - y) - z` is not equivalent to `x - (y - z)`, but
+ * `(x + (-y)) + (-z)` _is_ equivalent to `x + ((-y) + (-z))`.
+ *
+ * @section redopadd_floating_point Issues with Floating-Point Types
+ *
+ * Because of precision and round-off issues, floating-point addition is not
+ * really associative. For example, `(1e30 + -1e30) + 1 == 1`, but
+ * `1e30 + (-1e30 + 1) == 0`.
+ *
+ * In many cases, this won’t matter, but computations which have been
+ * carefully ordered to control round-off errors may not deal well with
+ * being reassociated. In general, you should be sure to understand the
+ * floating-point behavior of your program before doing any transformation
+ * that will reassociate its computations.
+ *
+ * @section redopadd_types Type and Operator Requirements
+ *
+ * `Type` must be `Copy Constructible`, `Default Constructible`, and
+ * `Assignable`.
+ *
+ * The operator “`+=`†must be defined on `Type`, with `x += a` having the
+ * same meaning as `x = x + a`. In addition, if the code uses the “`-=`â€,
+ * pre-increment, post-increment, pre-decrement, or post-decrement operators,
+ * then the corresponding operators must be defined on `Type`.
+ *
+ * The expression `Type()` must be a valid expression which yields the
+ * identity value (the value of `Type` whose numeric value is zero).
+ *
+ * @section redopadd_in_c Addition Reducers in C
+ *
+ * The @ref CILK_C_REDUCER_OPADD and @ref CILK_C_REDUCER_OPADD_TYPE macros can
+ * be used to do addition reductions in C. For example:
+ *
+ * CILK_C_REDUCER_OPADD(r, double, 0);
+ * CILK_C_REGISTER_REDUCER(r);
+ * cilk_for(int i = 0; i != n; ++i) {
+ * REDUCER_VIEW(r) += a[i];
+ * }
+ * CILK_C_UNREGISTER_REDUCER(r);
+ * printf("The sum of the elements of a is %f\n", REDUCER_VIEW(r));
+ *
+ * See @ref reducers_c_predefined.
+ */
+
+#ifdef __cplusplus
+
+namespace cilk {
+
+/** The addition reducer view class.
+ *
+ * This is the view class for reducers created with
+ * `cilk::reducer< cilk::op_add<Type> >`. It holds the accumulator variable
+ * for the reduction, and allows only addition and subtraction operations to
+ * be performed on it.
+ *
+ * @note The reducer “dereference†operation (`reducer::operator *()`)
+ * yields a reference to the view. Thus, for example, the view class’s
+ * `+=` operation would be used in an expression like `*r += a`, where
+ * `r` is an op_add reducer variable.
+ *
+ * @tparam Type The type of the contained accumulator variable. This will
+ * be the value type of a monoid_with_view that is
+ * instantiated with this view.
+ *
+ * @see ReducersAdd
+ * @see op_add
+ *
+ * @ingroup ReducersAdd
+ */
+template <typename Type>
+class op_add_view : public scalar_view<Type>
+{
+ typedef scalar_view<Type> base;
+
+public:
+ /** Class to represent the right-hand side of
+ * `*reducer = *reducer ± value`.
+ *
+ * The only assignment operator for the op_add_view class takes an
+ * rhs_proxy as its operand. This results in the syntactic restriction
+ * that the only expressions that can be assigned to an op_add_view are
+ * ones which generate an rhs_proxy — that is, expressions of the form
+ * `op_add_view ± value ... ± value`.
+ *
+ * @warning
+ * The lhs and rhs views in such an assignment must be the same;
+ * otherwise, the behavior will be undefined. (I.e., `v1 = v1 + x` is
+ * legal; `v1 = v2 + x` is illegal.) This condition will be checked with a
+ * runtime assertion when compiled in debug mode.
+ *
+ * @see op_add_view
+ */
+ class rhs_proxy {
+ friend class op_add_view;
+
+ const op_add_view* m_view;
+ Type m_value;
+
+ // Constructor is invoked only from op_add_view::operator+() and
+ // op_add_view::operator-().
+ //
+ rhs_proxy(const op_add_view* view, const Type& value) :
+ m_view(view), m_value(value) {}
+
+ rhs_proxy& operator=(const rhs_proxy&); // Disable assignment operator
+ rhs_proxy(); // Disable default constructor
+
+ public:
+ //@{
+ /** Add or subtract an additional rhs value. If `v` is an op_add_view
+ * and `a1` is a value, then the expression `v + a1` invokes the view’s
+ * `operator+()` to create an rhs_proxy for `(v, a1)`; then
+ * `v + a1 + a2` invokes the rhs_proxy’s `operator+()` to create a new
+ * rhs_proxy for `(v, a1+a2)`. This allows the right-hand side of an
+ * assignment to be not just `view ± value`, but
+ * `view ± value ± value ... ± value`. The effect is that
+ *
+ * v = v ± a1 ± a2 ... ± an;
+ *
+ * is evaluated as
+ *
+ * v = v ± (±a1 ± a2 ... ± an);
+ */
+ rhs_proxy& operator+(const Type& x) { m_value += x; return *this; }
+ rhs_proxy& operator-(const Type& x) { m_value -= x; return *this; }
+ //@}
+ };
+
+
+ /** Default/identity constructor. This constructor initializes the
+ * contained value to `Type()`, which is expected to be the identity value
+ * for addition on `Type`.
+ */
+ op_add_view() : base() {}
+
+ /** Construct with a specified initial value.
+ */
+ explicit op_add_view(const Type& v) : base(v) {}
+
+ /** Reduction operation.
+ *
+ * This function is invoked by the @ref op_add monoid to combine the views
+ * of two strands when the right strand merges with the left one. It adds
+ * the value contained in the right-strand view to the value contained in
+ * the left-strand view, and leaves the value in the right-strand view
+ * undefined.
+ *
+ * @param right A pointer to the right-strand view. (`this` points to
+ * the left-strand view.)
+ *
+ * @note Used only by the @ref op_add monoid to implement the monoid
+ * reduce operation.
+ */
+ void reduce(op_add_view* right) { this->m_value += right->m_value; }
+
+ /** @name Accumulator variable updates.
+ *
+ * These functions support the various syntaxes for incrementing or
+ * decrementing the accumulator variable contained in the view.
+ */
+ //@{
+
+ /** Increment the accumulator variable by @a x.
+ */
+ op_add_view& operator+=(const Type& x) { this->m_value += x; return *this; }
+
+ /** Decrement the accumulator variable by @a x.
+ */
+ op_add_view& operator-=(const Type& x) { this->m_value -= x; return *this; }
+
+ /** Pre-increment.
+ */
+ op_add_view& operator++() { ++this->m_value; return *this; }
+
+ /** Post-increment.
+ *
+ * @note Conventionally, post-increment operators return the old value
+ * of the incremented variable. However, reducer views do not
+ * expose their contained values, so `view++` does not have a
+ * return value.
+ */
+ void operator++(int) { this->m_value++; }
+
+ /** Pre-decrement.
+ */
+ op_add_view& operator--() { --this->m_value; return *this; }
+
+ /** Post-decrement.
+ *
+ * @note Conventionally, post-decrement operators return the old value
+ * of the decremented variable. However, reducer views do not
+ * expose their contained values, so `view--` does not have a
+ * return value.
+ */
+ void operator--(int) { this->m_value--; }
+
+ /** Create an object representing `*this + x`.
+ *
+ * @see rhs_proxy
+ */
+ rhs_proxy operator+(const Type& x) const { return rhs_proxy(this, x); }
+
+ /** Create an object representing `*this - x`.
+ *
+ * @see rhs_proxy
+ */
+ rhs_proxy operator-(const Type& x) const { return rhs_proxy(this, -x); }
+
+ /** Assign the result of a `view ± value` expression to the view. Note that
+ * this is the only assignment operator for this class.
+ *
+ * @see rhs_proxy
+ */
+ op_add_view& operator=(const rhs_proxy& rhs) {
+ __CILKRTS_ASSERT(this == rhs.m_view);
+ this->m_value += rhs.m_value;
+ return *this;
+ }
+
+ //@}
+};
+
+
+/** Monoid class for addition reductions. Instantiate the cilk::reducer
+ * template class with an op_add monoid to create an addition reducer class.
+ * For example, to compute
+ * the sum of a set of `int` values:
+ *
+ * cilk::reducer< cilk::op_add<int> > r;
+ *
+ * @tparam Type The reducer value type.
+ * @tparam Align If `false` (the default), reducers instantiated on this
+ * monoid will be naturally aligned (the Cilk library 1.0
+ * behavior). If `true`, reducers instantiated on this monoid
+ * will be cache-aligned for binary compatibility with
+ * reducers in Cilk library version 0.9.
+ *
+ * @see ReducersAdd
+ * @see op_add_view
+ *
+ * @ingroup ReducersAdd
+ */
+template <typename Type, bool Align = false>
+struct op_add : public monoid_with_view<op_add_view<Type>, Align> {};
+
+/** **Deprecated** addition reducer wrapper class.
+ *
+ * reducer_opadd is the same as @ref reducer<@ref op_add>, except that
+ * reducer_opadd is a proxy for the contained view, so that accumulator
+ * variable update operations can be applied directly to the reducer. For
+ * example, a value is added to a `reducer<%op_add>` with `*r += a`, but a
+ * value can be added to a `%reducer_opadd` with `r += a`.
+ *
+ * @deprecated Users are strongly encouraged to use `reducer<monoid>`
+ * reducers rather than the old wrappers like reducer_opadd.
+ * The `reducer<monoid>` reducers show the reducer/monoid/view
+ * architecture more clearly, are more consistent in their
+ * implementation, and present a simpler model for new
+ * user-implemented reducers.
+ *
+ * @note Implicit conversions are provided between `%reducer_opadd`
+ * and `reducer<%op_add>`. This allows incremental code
+ * conversion: old code that used `%reducer_opadd` can pass a
+ * `%reducer_opadd` to a converted function that now expects a
+ * pointer or reference to a `reducer<%op_add>`, and vice
+ * versa.
+ *
+ * @tparam Type The value type of the reducer.
+ *
+ * @see op_add
+ * @see reducer
+ * @see ReducersAdd
+ *
+ * @ingroup ReducersAdd
+ */
+template <typename Type>
+class reducer_opadd : public reducer< op_add<Type, true> >
+{
+ typedef reducer< op_add<Type, true> > base;
+ using base::view;
+
+ public:
+ /// The view type for the reducer.
+ typedef typename base::view_type view_type;
+
+ /// The view’s rhs proxy type.
+ typedef typename view_type::rhs_proxy rhs_proxy;
+
+ /// The view type for the reducer.
+ typedef view_type View;
+
+ /// The monoid type for the reducer.
+ typedef typename base::monoid_type Monoid;
+
+ /** @name Constructors
+ */
+ //@{
+
+ /** Default (identity) constructor.
+ *
+ * Constructs the wrapper with the default initial value of `Type()`.
+ */
+ reducer_opadd() {}
+
+ /** Value constructor.
+ *
+ * Constructs the wrapper with a specified initial value.
+ */
+ explicit reducer_opadd(const Type& initial_value) : base(initial_value) {}
+
+ //@}
+
+ /** @name Forwarded functions
+ * @details Functions that update the contained accumulator variable are
+ * simply forwarded to the contained @ref op_add_view. */
+ //@{
+
+ /// @copydoc op_add_view::operator+=(const Type&)
+ reducer_opadd& operator+=(const Type& x) { view() += x; return *this; }
+
+ /// @copydoc op_add_view::operator-=(const Type&)
+ reducer_opadd& operator-=(const Type& x) { view() -= x; return *this; }
+
+ /// @copydoc op_add_view::operator++()
+ reducer_opadd& operator++() { ++view(); return *this; }
+
+ /// @copydoc op_add_view::operator++(int)
+ void operator++(int) { view()++; }
+
+ /// @copydoc op_add_view::operator-\-()
+ reducer_opadd& operator--() { --view(); return *this; }
+
+ /// @copydoc op_add_view::operator-\-(int)
+ void operator--(int) { view()--; }
+
+ // The legacy definitions of reducer_opadd::operator+() and
+ // reducer_opadd::operator-() have different behavior and a different
+ // return type than this definition. The legacy version is defined as a
+ // member function, so this new version is defined as a free function to
+ // give it a different signature, so that they won’t end up sharing a
+ // single object file entry.
+
+ /// @copydoc op_add_view::operator+(const Type&) const
+ friend rhs_proxy operator+(const reducer_opadd& r, const Type& x)
+ {
+ return r.view() + x;
+ }
+ /// @copydoc op_add_view::operator-(const Type&) const
+ friend rhs_proxy operator-(const reducer_opadd& r, const Type& x)
+ {
+ return r.view() - x;
+ }
+ /// @copydoc op_add_view::operator=(const rhs_proxy&)
+ reducer_opadd& operator=(const rhs_proxy& temp)
+ {
+ view() = temp;
+ return *this;
+ }
+ //@}
+
+ /** @name Dereference
+ * @details Dereferencing a wrapper is a no-op. It simply returns the
+ * wrapper. Combined with the rule that the wrapper forwards view
+ * operations to its contained view, this means that view operations can
+ * be written the same way on reducers and wrappers, which is convenient
+ * for incrementally converting old code using wrappers to use reducers
+ * instead. That is:
+ *
+ * reducer< op_add<int> > r;
+ * *r += a; // *r returns the view
+ * // operator += is a view member function
+ *
+ * reducer_opadd<int> w;
+ * *w += a; // *w returns the wrapper
+ * // operator += is a wrapper member function that
+ * // calls the corresponding view function
+ */
+ //@{
+ reducer_opadd& operator*() { return *this; }
+ reducer_opadd const& operator*() const { return *this; }
+
+ reducer_opadd* operator->() { return this; }
+ reducer_opadd const* operator->() const { return this; }
+ //@}
+
+ /** @name Upcast
+ * @details In Cilk library 0.9, reducers were always cache-aligned. In
+ * library 1.0, reducer cache alignment is optional. By default, reducers
+ * are unaligned (i.e., just naturally aligned), but legacy wrappers
+ * inherit from cache-aligned reducers for binary compatibility.
+ *
+ * This means that a wrapper will automatically be upcast to its aligned
+ * reducer base class. The following conversion operators provide
+ * pseudo-upcasts to the corresponding unaligned reducer class.
+ */
+ //@{
+ operator reducer< op_add<Type, false> >& ()
+ {
+ return *reinterpret_cast< reducer< op_add<Type, false> >* >(this);
+ }
+ operator const reducer< op_add<Type, false> >& () const
+ {
+ return *reinterpret_cast< const reducer< op_add<Type, false> >* >(this);
+ }
+ //@}
+};
+
+/// @cond internal
+/** Metafunction specialization for reducer conversion.
+ *
+ * This specialization of the @ref legacy_reducer_downcast template class
+ * defined in reducer.h causes the `reducer< op_add<Type> >` class to have an
+ * `operator reducer_opadd<Type>& ()` conversion operator that statically
+ * downcasts the `reducer<op_add>` to the corresponding `reducer_opadd` type.
+ * (The reverse conversion, from `reducer_opadd` to `reducer<op_add>`, is just
+ * an upcast, which is provided for free by the language.)
+ *
+ * @ingroup ReducersAdd
+ */
+template <typename Type, bool Align>
+struct legacy_reducer_downcast<reducer<op_add<Type, Align> > >
+{
+ typedef reducer_opadd<Type> type;
+};
+/// @endcond
+
+} // namespace cilk
+
+#endif // __cplusplus
+
+
+/** @ingroup ReducersAdd
+ */
+//@{
+
+/** @name C Language Reducer Macros
+ *
+ * These macros are used to declare and work with numeric op_add reducers in
+ * C code.
+ *
+ * @see @ref page_reducers_in_c
+ */
+ //@{
+
+__CILKRTS_BEGIN_EXTERN_C
+
+/** Opadd reducer type name.
+ *
+ * This macro expands into the identifier which is the name of the op_add
+ * reducer type for a specified numeric type.
+ *
+ * @param tn The @ref reducers_c_type_names "numeric type name" specifying
+ * the type of the reducer.
+ *
+ * @see @ref reducers_c_predefined
+ * @see ReducersAdd
+ */
+#define CILK_C_REDUCER_OPADD_TYPE(tn) \
+ __CILKRTS_MKIDENT(cilk_c_reducer_opadd_,tn)
+
+/** Declare an op_add reducer object.
+ *
+ * This macro expands into a declaration of an op_add reducer object for a
+ * specified numeric type. For example:
+ *
+ * CILK_C_REDUCER_OPADD(my_reducer, double, 0.0);
+ *
+ * @param obj The variable name to be used for the declared reducer object.
+ * @param tn The @ref reducers_c_type_names "numeric type name" specifying
+ * the type of the reducer.
+ * @param v The initial value for the reducer. (A value which can be
+ * assigned to the numeric type represented by @a tn.)
+ *
+ * @see @ref reducers_c_predefined
+ * @see ReducersAdd
+ */
+#define CILK_C_REDUCER_OPADD(obj,tn,v) \
+ CILK_C_REDUCER_OPADD_TYPE(tn) obj = \
+ CILK_C_INIT_REDUCER(_Typeof(obj.value), \
+ __CILKRTS_MKIDENT(cilk_c_reducer_opadd_reduce_,tn), \
+ __CILKRTS_MKIDENT(cilk_c_reducer_opadd_identity_,tn), \
+ __cilkrts_hyperobject_noop_destroy, v)
+
+/// @cond internal
+
+/** Declare the op_add reducer functions for a numeric type.
+ *
+ * This macro expands into external function declarations for functions which
+ * implement the reducer functionality for the op_add reducer type for a
+ * specified numeric type.
+ *
+ * @param t The value type of the reducer.
+ * @param tn The value “type name†identifier, used to construct the reducer
+ * type name, function names, etc.
+ */
+#define CILK_C_REDUCER_OPADD_DECLARATION(t,tn) \
+ typedef CILK_C_DECLARE_REDUCER(t) CILK_C_REDUCER_OPADD_TYPE(tn); \
+ __CILKRTS_DECLARE_REDUCER_REDUCE(cilk_c_reducer_opadd,tn,l,r); \
+ __CILKRTS_DECLARE_REDUCER_IDENTITY(cilk_c_reducer_opadd,tn);
+
+/** Define the op_add reducer functions for a numeric type.
+ *
+ * This macro expands into function definitions for functions which implement
+ * the reducer functionality for the op_add reducer type for a specified
+ * numeric type.
+ *
+ * @param t The value type of the reducer.
+ * @param tn The value “type name†identifier, used to construct the reducer
+ * type name, function names, etc.
+ */
+#define CILK_C_REDUCER_OPADD_DEFINITION(t,tn) \
+ typedef CILK_C_DECLARE_REDUCER(t) CILK_C_REDUCER_OPADD_TYPE(tn); \
+ __CILKRTS_DECLARE_REDUCER_REDUCE(cilk_c_reducer_opadd,tn,l,r) \
+ { *(t*)l += *(t*)r; } \
+ __CILKRTS_DECLARE_REDUCER_IDENTITY(cilk_c_reducer_opadd,tn) \
+ { *(t*)v = 0; }
+
+//@{
+/** @def CILK_C_REDUCER_OPADD_INSTANCE
+ * @brief Declare or define implementation functions for a reducer type.
+ *
+ * In the runtime source file c_reducers.c, the macro `CILK_C_DEFINE_REDUCERS`
+ * will be defined, and this macro will generate reducer implementation
+ * functions. Everywhere else, `CILK_C_DEFINE_REDUCERS` will be undefined,
+ * and this macro will expand into external declarations for the functions.
+ */
+#ifdef CILK_C_DEFINE_REDUCERS
+# define CILK_C_REDUCER_OPADD_INSTANCE(t,tn) \
+ CILK_C_REDUCER_OPADD_DEFINITION(t,tn)
+#else
+# define CILK_C_REDUCER_OPADD_INSTANCE(t,tn) \
+ CILK_C_REDUCER_OPADD_DECLARATION(t,tn)
+#endif
+//@}
+
+/* Declare or define an instance of the reducer type and its functions for each
+ * numeric type.
+ */
+CILK_C_REDUCER_OPADD_INSTANCE(char, char)
+CILK_C_REDUCER_OPADD_INSTANCE(unsigned char, uchar)
+CILK_C_REDUCER_OPADD_INSTANCE(signed char, schar)
+CILK_C_REDUCER_OPADD_INSTANCE(wchar_t, wchar_t)
+CILK_C_REDUCER_OPADD_INSTANCE(short, short)
+CILK_C_REDUCER_OPADD_INSTANCE(unsigned short, ushort)
+CILK_C_REDUCER_OPADD_INSTANCE(int, int)
+CILK_C_REDUCER_OPADD_INSTANCE(unsigned int, uint)
+CILK_C_REDUCER_OPADD_INSTANCE(unsigned int, unsigned) /* alternate name */
+CILK_C_REDUCER_OPADD_INSTANCE(long, long)
+CILK_C_REDUCER_OPADD_INSTANCE(unsigned long, ulong)
+CILK_C_REDUCER_OPADD_INSTANCE(long long, longlong)
+CILK_C_REDUCER_OPADD_INSTANCE(unsigned long long, ulonglong)
+CILK_C_REDUCER_OPADD_INSTANCE(float, float)
+CILK_C_REDUCER_OPADD_INSTANCE(double, double)
+CILK_C_REDUCER_OPADD_INSTANCE(long double, longdouble)
+
+//@endcond
+
+__CILKRTS_END_EXTERN_C
+
+//@}
+
+//@}
+
+#endif /* REDUCER_OPADD_H_INCLUDED */
diff --git a/libcilkrts/include/cilk/reducer_opand.h b/libcilkrts/include/cilk/reducer_opand.h
new file mode 100644
index 00000000000..8a086c91818
--- /dev/null
+++ b/libcilkrts/include/cilk/reducer_opand.h
@@ -0,0 +1,604 @@
+/* reducer_opand.h -*- C++ -*-
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file reducer_opand.h
+ *
+ * @brief Defines classes for doing parallel bitwise and reductions.
+ *
+ * @ingroup ReducersAnd
+ *
+ * @see ReducersAnd
+ */
+
+#ifndef REDUCER_OPAND_H_INCLUDED
+#define REDUCER_OPAND_H_INCLUDED
+
+#include <cilk/reducer.h>
+
+/** @defgroup ReducersAnd Bitwise And Reducers
+ *
+ * Bitwise and reducers allow the computation of the bitwise and of a set of
+ * values in parallel.
+ *
+ * @ingroup Reducers
+ *
+ * You should be familiar with @ref pagereducers "Cilk reducers", described in
+ * file `reducers.md`, and particularly with @ref reducers_using, before trying
+ * to use the information in this file.
+ *
+ * @section redopand_usage Usage Example
+ *
+ * cilk::reducer< cilk::op_and<unsigned> > r;
+ * cilk_for (int i = 0; i != N; ++i) {
+ * *r &= a[i];
+ * }
+ * unsigned result;
+ * r.move_out(result);
+ *
+ * @section redopand_monoid The Monoid
+ *
+ * @subsection redopand_monoid_values Value Set
+ *
+ * The value set of a bitwise and reducer is the set of values of `Type`,
+ * which is expected to be a builtin integer type which has a representation
+ * as a sequence of bits (or something like it, such as `bool` or
+ * `std::bitset`).
+ *
+ * @subsection redopand_monoid_operator Operator
+ *
+ * The operator of a bitwise and reducer is the bitwise and operator, defined
+ * by the “`&`†binary operator on `Type`.
+ *
+ * @subsection redopand_monoid_identity Identity
+ *
+ * The identity value of the reducer is the value whose representation
+ * contains all 1-bits. This is expected to be the value of the expression
+ * `~Type()` (i.e., the bitwise negation operator applied to the default value
+ * of the value type).
+ *
+ * @section redopand_operations Operations
+ *
+ * @subsection redopand_constructors Constructors
+ *
+ * reducer() // identity
+ * reducer(const Type& value)
+ * reducer(move_in(Type& variable))
+ *
+ * @subsection redopand_get_set Set and Get
+ *
+ * r.set_value(const Type& value)
+ * const Type& = r.get_value() const
+ * r.move_in(Type& variable)
+ * r.move_out(Type& variable)
+ *
+ * @subsection redopand_initial Initial Values
+ *
+ * If a bitwise and reducer is constructed without an explicit initial value,
+ * then its initial value will be its identity value, as long as `Type`
+ * satisfies the requirements of @ref redopand_types.
+ *
+ * @subsection redopand_view_ops View Operations
+ *
+ * *r &= a
+ * *r = *r & a
+ * *r = *r & a1 & a2 … & an
+ *
+ * @section redopand_types Type and Operator Requirements
+ *
+ * `Type` must be `Copy Constructible`, `Default Constructible`, and
+ * `Assignable`.
+ *
+ * The operator “`&=`†must be defined on `Type`, with `x &= a` having the
+ * same meaning as `x = x & a`.
+ *
+ * The expression `~ Type()` must be a valid expression which yields the
+ * identity value (the value of `Type` whose representation consists of all
+ * 1-bits).
+ *
+ * @section redopand_in_c Bitwise And Reducers in C
+ *
+ * The @ref CILK_C_REDUCER_OPAND and @ref CILK_C_REDUCER_OPAND_TYPE macros can
+ * be used to do bitwise and reductions in C. For example:
+ *
+ * CILK_C_REDUCER_OPAND(r, uint, ~0);
+ * CILK_C_REGISTER_REDUCER(r);
+ * cilk_for(int i = 0; i != n; ++i) {
+ * REDUCER_VIEW(r) &= a[i];
+ * }
+ * CILK_C_UNREGISTER_REDUCER(r);
+ * printf("The bitwise AND of the elements of a is %x\n", REDUCER_VIEW(r));
+ *
+ * See @ref reducers_c_predefined.
+ */
+
+#ifdef __cplusplus
+
+namespace cilk {
+
+/** The bitwise and reducer view class.
+ *
+ * This is the view class for reducers created with
+ * `cilk::reducer< cilk::op_and<Type> >`. It holds the accumulator variable
+ * for the reduction, and allows only `and` operations to be performed on it.
+ *
+ * @note The reducer “dereference†operation (`reducer::operator *()`)
+ * yields a reference to the view. Thus, for example, the view class’s
+ * `&=` operation would be used in an expression like `*r &= a`, where
+ * `r` is an opmod reducer variable.
+ *
+ * @tparam Type The type of the contained accumulator variable. This will
+ * be the value type of a monoid_with_view that is
+ * instantiated with this view.
+ *
+ * @see ReducersAnd
+ * @see op_and
+ *
+ * @ingroup ReducersAnd
+ */
+template <typename Type>
+class op_and_view : public scalar_view<Type>
+{
+ typedef scalar_view<Type> base;
+
+public:
+ /** Class to represent the right-hand side of `*reducer = *reducer & value`.
+ *
+ * The only assignment operator for the op_and_view class takes an
+ * rhs_proxy as its operand. This results in the syntactic restriction
+ * that the only expressions that can be assigned to an op_and_view are
+ * ones which generate an rhs_proxy — that is, expressions of the form
+ * `op_and_view & value ... & value`.
+ *
+ * @warning
+ * The lhs and rhs views in such an assignment must be the same;
+ * otherwise, the behavior will be undefined. (I.e., `v1 = v1 & x` is
+ * legal; `v1 = v2 & x` is illegal.) This condition will be checked with
+ * a runtime assertion when compiled in debug mode.
+ *
+ * @see op_and_view
+ */
+ class rhs_proxy {
+ private:
+ friend class op_and_view;
+
+ const op_and_view* m_view;
+ Type m_value;
+
+ // Constructor is invoked only from op_and_view::operator&().
+ //
+ rhs_proxy(const op_and_view* view, const Type& value) : m_view(view), m_value(value) {}
+
+ rhs_proxy& operator=(const rhs_proxy&); // Disable assignment operator
+ rhs_proxy(); // Disable default constructor
+
+ public:
+ /** Bitwise and with an additional rhs value. If `v` is an op_and_view
+ * and `a1` is a value, then the expression `v & a1` invokes the
+ * view’s `operator&()` to create an rhs_proxy for `(v, a1)`; then
+ * `v & a1 & a2` invokes the rhs_proxy’s `operator&()` to create a new
+ * rhs_proxy for `(v, a1&a2)`. This allows the right-hand side of an
+ * assignment to be not just `view & value`, but
+ * `view & value & value ... & value`. The effect is that
+ *
+ * v = v & a1 & a2 ... & an;
+ *
+ * is evaluated as
+ *
+ * v = v & (a1 & a2 ... & an);
+ */
+ rhs_proxy& operator&(const Type& x) { m_value &= x; return *this; }
+ };
+
+
+ /** Default/identity constructor. This constructor initializes the
+ * contained value to `~ Type()`.
+ */
+ op_and_view() : base(~Type()) {}
+
+ /** Construct with a specified initial value.
+ */
+ explicit op_and_view(const Type& v) : base(v) {}
+
+
+ /** Reduction operation.
+ *
+ * This function is invoked by the @ref op_and monoid to combine the views
+ * of two strands when the right strand merges with the left one. It
+ * “ands†the value contained in the left-strand view with the value
+ * contained in the right-strand view, and leaves the value in the
+ * right-strand view undefined.
+ *
+ * @param right A pointer to the right-strand view. (`this` points to
+ * the left-strand view.)
+ *
+ * @note Used only by the @ref op_and monoid to implement the monoid
+ * reduce operation.
+ */
+ void reduce(op_and_view* right) { this->m_value &= right->m_value; }
+
+ /** @name Accumulator variable updates.
+ *
+ * These functions support the various syntaxes for “anding†the
+ * accumulator variable contained in the view with some value.
+ */
+ //@{
+
+ /** And the accumulator variable with @a x.
+ */
+ op_and_view& operator&=(const Type& x) { this->m_value &= x; return *this; }
+
+ /** Create an object representing `*this & x`.
+ *
+ * @see rhs_proxy
+ */
+ rhs_proxy operator&(const Type& x) const { return rhs_proxy(this, x); }
+
+ /** Assign the result of a `view & value` expression to the view. Note that
+ * this is the only assignment operator for this class.
+ *
+ * @see rhs_proxy
+ */
+ op_and_view& operator=(const rhs_proxy& rhs) {
+ __CILKRTS_ASSERT(this == rhs.m_view);
+ this->m_value &= rhs.m_value;
+ return *this;
+ }
+
+ //@}
+};
+
+/** Monoid class for bitwise and reductions. Instantiate the cilk::reducer
+ * template class with an op_and monoid to create a bitwise and reducer
+ * class. For example, to compute the bitwise and of a set of `unsigned long`
+ * values:
+ *
+ * cilk::reducer< cilk::op_and<unsigned long> > r;
+ *
+ * @tparam Type The reducer value type.
+ * @tparam Align If `false` (the default), reducers instantiated on this
+ * monoid will be naturally aligned (the Cilk library 1.0
+ * behavior). If `true`, reducers instantiated on this monoid
+ * will be cache-aligned for binary compatibility with
+ * reducers in Cilk library version 0.9.
+ *
+ * @see ReducersAnd
+ * @see op_and_view
+ *
+ * @ingroup ReducersAnd
+ */
+template <typename Type, bool Align = false>
+struct op_and : public monoid_with_view<op_and_view<Type>, Align> {};
+
+/** Deprecated bitwise and reducer class.
+ *
+ * reducer_opand is the same as @ref reducer<@ref op_and>, except that
+ * reducer_opand is a proxy for the contained view, so that accumulator
+ * variable update operations can be applied directly to the reducer. For
+ * example, a value is anded with a `reducer<%op_and>` with `*r &= a`, but a
+ * value can be anded with a `%reducer_opand` with `r &= a`.
+ *
+ * @deprecated Users are strongly encouraged to use `reducer<monoid>`
+ * reducers rather than the old wrappers like reducer_opand.
+ * The `reducer<monoid>` reducers show the reducer/monoid/view
+ * architecture more clearly, are more consistent in their
+ * implementation, and present a simpler model for new
+ * user-implemented reducers.
+ *
+ * @note Implicit conversions are provided between `%reducer_opand`
+ * and `reducer<%op_and>`. This allows incremental code
+ * conversion: old code that used `%reducer_opand` can pass a
+ * `%reducer_opand` to a converted function that now expects a
+ * pointer or reference to a `reducer<%op_and>`, and vice
+ * versa.
+ *
+ * @tparam Type The value type of the reducer.
+ *
+ * @see op_and
+ * @see reducer
+ * @see ReducersAnd
+ *
+ * @ingroup ReducersAnd
+ */
+template <typename Type>
+class reducer_opand : public reducer< op_and<Type, true> >
+{
+ typedef reducer< op_and<Type, true> > base;
+ using base::view;
+
+public:
+ /// The view type for the reducer.
+ typedef typename base::view_type view_type;
+
+ /// The view’s rhs proxy type.
+ typedef typename view_type::rhs_proxy rhs_proxy;
+
+ /// The view type for the reducer.
+ typedef view_type View;
+
+ /// The monoid type for the reducer.
+ typedef typename base::monoid_type Monoid;
+
+ /** @name Constructors
+ */
+ //@{
+
+ /** Default constructor.
+ *
+ * Constructs the wrapper with the default initial value of `Type()`
+ * (not the identity value).
+ */
+ reducer_opand() : base(Type()) {}
+
+ /** Value constructor.
+ *
+ * Constructs the wrapper with a specified initial value.
+ */
+ explicit reducer_opand(const Type& initial_value) : base(initial_value) {}
+
+ //@}
+
+ /** @name Forwarded functions
+ * @details Functions that update the contained accumulator variable are
+ * simply forwarded to the contained @ref op_and_view. */
+ //@{
+
+ /// @copydoc op_and_view::operator&=(const Type&)
+ reducer_opand& operator&=(const Type& x)
+ {
+ view() &= x;
+ return *this;
+ }
+
+ // The legacy definition of reducer_opand::operator&() has different
+ // behavior and a different return type than this definition. The legacy
+ // version is defined as a member function, so this new version is defined
+ // as a free function to give it a different signature, so that they won’t
+ // end up sharing a single object file entry.
+
+ /// @copydoc op_and_view::operator&(const Type&) const
+ friend rhs_proxy operator&(const reducer_opand& r, const Type& x)
+ {
+ return r.view() & x;
+ }
+
+ /// @copydoc op_and_view::operator=(const rhs_proxy&)
+ reducer_opand& operator=(const rhs_proxy& temp)
+ {
+ view() = temp;
+ return *this;
+ }
+ //@}
+
+ /** @name Dereference
+ * @details Dereferencing a wrapper is a no-op. It simply returns the
+ * wrapper. Combined with the rule that the wrapper forwards view
+ * operations to its contained view, this means that view operations can
+ * be written the same way on reducers and wrappers, which is convenient
+ * for incrementally converting old code using wrappers to use reducers
+ * instead. That is:
+ *
+ * reducer< op_and<int> > r;
+ * *r &= a; // *r returns the view
+ * // operator &= is a view member function
+ *
+ * reducer_opand<int> w;
+ * *w &= a; // *w returns the wrapper
+ * // operator &= is a wrapper member function that
+ * // calls the corresponding view function
+ */
+ //@{
+ reducer_opand& operator*() { return *this; }
+ reducer_opand const& operator*() const { return *this; }
+
+ reducer_opand* operator->() { return this; }
+ reducer_opand const* operator->() const { return this; }
+ //@}
+
+ /** @name Upcast
+ * @details In Cilk library 0.9, reducers were always cache-aligned. In
+ * library 1.0, reducer cache alignment is optional. By default, reducers
+ * are unaligned (i.e., just naturally aligned), but legacy wrappers
+ * inherit from cache-aligned reducers for binary compatibility.
+ *
+ * This means that a wrapper will automatically be upcast to its aligned
+ * reducer base class. The following conversion operators provide
+ * pseudo-upcasts to the corresponding unaligned reducer class.
+ */
+ //@{
+ operator reducer< op_and<Type, false> >& ()
+ {
+ return *reinterpret_cast< reducer< op_and<Type, false> >* >(this);
+ }
+ operator const reducer< op_and<Type, false> >& () const
+ {
+ return *reinterpret_cast< const reducer< op_and<Type, false> >* >(this);
+ }
+ //@}
+};
+
+/// @cond internal
+/** Metafunction specialization for reducer conversion.
+ *
+ * This specialization of the @ref legacy_reducer_downcast template class
+ * defined in reducer.h causes the `reducer< op_and<Type> >` class to have an
+ * `operator reducer_opand<Type>& ()` conversion operator that statically
+ * downcasts the `reducer<op_and>` to the corresponding `reducer_opand` type.
+ * (The reverse conversion, from `reducer_opand` to `reducer<op_and>`, is just
+ * an upcast, which is provided for free by the language.)
+ *
+ * @ingroup ReducersAnd
+ */
+template <typename Type, bool Align>
+struct legacy_reducer_downcast<reducer<op_and<Type, Align> > >
+{
+ typedef reducer_opand<Type> type;
+};
+/// @endcond
+
+} // namespace cilk
+
+#endif // __cplusplus
+
+
+/** @ingroup ReducersAdd
+ */
+//@{
+
+/** @name C language reducer macros
+ *
+ * These macros are used to declare and work with op_and reducers in C code.
+ *
+ * @see @ref page_reducers_in_c
+ */
+ //@{
+
+__CILKRTS_BEGIN_EXTERN_C
+
+/** Opand reducer type name.
+ *
+ * This macro expands into the identifier which is the name of the op_and
+ * reducer type for a specified numeric type.
+ *
+ * @param tn The @ref reducers_c_type_names "numeric type name" specifying
+ * the type of the reducer.
+ *
+ * @see @ref reducers_c_predefined
+ * @see ReducersAnd
+ */
+#define CILK_C_REDUCER_OPAND_TYPE(tn) \
+ __CILKRTS_MKIDENT(cilk_c_reducer_opand_,tn)
+
+/** Declare an op_and reducer object.
+ *
+ * This macro expands into a declaration of an op_and reducer object for a
+ * specified numeric type. For example:
+ *
+ * CILK_C_REDUCER_OPAND(my_reducer, ulong, ~0UL);
+ *
+ * @param obj The variable name to be used for the declared reducer object.
+ * @param tn The @ref reducers_c_type_names "numeric type name" specifying
+ * the type of the reducer.
+ * @param v The initial value for the reducer. (A value which can be
+ * assigned to the numeric type represented by @a tn.)
+ *
+ * @see @ref reducers_c_predefined
+ * @see ReducersAnd
+ */
+#define CILK_C_REDUCER_OPAND(obj,tn,v) \
+ CILK_C_REDUCER_OPAND_TYPE(tn) obj = \
+ CILK_C_INIT_REDUCER(_Typeof(obj.value), \
+ __CILKRTS_MKIDENT(cilk_c_reducer_opand_reduce_,tn), \
+ __CILKRTS_MKIDENT(cilk_c_reducer_opand_identity_,tn), \
+ __cilkrts_hyperobject_noop_destroy, v)
+
+/// @cond internal
+
+/** Declare the op_and reducer functions for a numeric type.
+ *
+ * This macro expands into external function declarations for functions which
+ * implement the reducer functionality for the op_and reducer type for a
+ * specified numeric type.
+ *
+ * @param t The value type of the reducer.
+ * @param tn The value “type name†identifier, used to construct the reducer
+ * type name, function names, etc.
+ */
+#define CILK_C_REDUCER_OPAND_DECLARATION(t,tn) \
+ typedef CILK_C_DECLARE_REDUCER(t) CILK_C_REDUCER_OPAND_TYPE(tn); \
+ __CILKRTS_DECLARE_REDUCER_REDUCE(cilk_c_reducer_opand,tn,l,r); \
+ __CILKRTS_DECLARE_REDUCER_IDENTITY(cilk_c_reducer_opand,tn);
+
+/** Define the op_and reducer functions for a numeric type.
+ *
+ * This macro expands into function definitions for functions which implement
+ * the reducer functionality for the op_and reducer type for a specified
+ * numeric type.
+ *
+ * @param t The value type of the reducer.
+ * @param tn The value “type name†identifier, used to construct the reducer
+ * type name, function names, etc.
+ */
+#define CILK_C_REDUCER_OPAND_DEFINITION(t,tn) \
+ typedef CILK_C_DECLARE_REDUCER(t) CILK_C_REDUCER_OPAND_TYPE(tn); \
+ __CILKRTS_DECLARE_REDUCER_REDUCE(cilk_c_reducer_opand,tn,l,r) \
+ { *(t*)l &= *(t*)r; } \
+ __CILKRTS_DECLARE_REDUCER_IDENTITY(cilk_c_reducer_opand,tn) \
+ { *(t*)v = ~((t)0); }
+
+//@{
+/** @def CILK_C_REDUCER_OPAND_INSTANCE
+ * @brief Declare or define implementation functions for a reducer type.
+ *
+ * In the runtime source file c_reducers.c, the macro `CILK_C_DEFINE_REDUCERS`
+ * will be defined, and this macro will generate reducer implementation
+ * functions. Everywhere else, `CILK_C_DEFINE_REDUCERS` will be undefined, and
+ * this macro will expand into external declarations for the functions.
+ */
+#ifdef CILK_C_DEFINE_REDUCERS
+# define CILK_C_REDUCER_OPAND_INSTANCE(t,tn) \
+ CILK_C_REDUCER_OPAND_DEFINITION(t,tn)
+#else
+# define CILK_C_REDUCER_OPAND_INSTANCE(t,tn) \
+ CILK_C_REDUCER_OPAND_DECLARATION(t,tn)
+#endif
+//@}
+
+/* Declare or define an instance of the reducer type and its functions for
+ * each numeric type.
+ */
+CILK_C_REDUCER_OPAND_INSTANCE(char, char)
+CILK_C_REDUCER_OPAND_INSTANCE(unsigned char, uchar)
+CILK_C_REDUCER_OPAND_INSTANCE(signed char, schar)
+CILK_C_REDUCER_OPAND_INSTANCE(wchar_t, wchar_t)
+CILK_C_REDUCER_OPAND_INSTANCE(short, short)
+CILK_C_REDUCER_OPAND_INSTANCE(unsigned short, ushort)
+CILK_C_REDUCER_OPAND_INSTANCE(int, int)
+CILK_C_REDUCER_OPAND_INSTANCE(unsigned int, uint)
+CILK_C_REDUCER_OPAND_INSTANCE(unsigned int, unsigned) /* alternate name */
+CILK_C_REDUCER_OPAND_INSTANCE(long, long)
+CILK_C_REDUCER_OPAND_INSTANCE(unsigned long, ulong)
+CILK_C_REDUCER_OPAND_INSTANCE(long long, longlong)
+CILK_C_REDUCER_OPAND_INSTANCE(unsigned long long, ulonglong)
+
+//@endcond
+
+__CILKRTS_END_EXTERN_C
+
+//@}
+
+//@}
+
+#endif /* REDUCER_OPAND_H_INCLUDED */
diff --git a/libcilkrts/include/cilk/reducer_opmul.h b/libcilkrts/include/cilk/reducer_opmul.h
new file mode 100644
index 00000000000..271529d787b
--- /dev/null
+++ b/libcilkrts/include/cilk/reducer_opmul.h
@@ -0,0 +1,442 @@
+/* reducer_opmul.h -*- C++ -*-
+ *
+ * @copyright
+ * Copyright (C) 2012-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file reducer_opmul.h
+ *
+ * @brief Defines classes for doing parallel multiplication reductions.
+ *
+ * @ingroup ReducersMul
+ *
+ * @see ReducersMul
+ */
+
+#ifndef REDUCER_OPMUL_H_INCLUDED
+#define REDUCER_OPMUL_H_INCLUDED
+
+#include <cilk/reducer.h>
+
+/** @defgroup ReducersMul Multiplication Reducers
+ *
+ * Multiplication reducers allow the computation of the product of a set of
+ * values in parallel.
+ *
+ * @ingroup Reducers
+ *
+ * You should be familiar with @ref pagereducers "Cilk reducers", described in
+ * file `reducers.md`, and particularly with @ref reducers_using, before trying
+ * to use the information in this file.
+ *
+ * @section redopmul_usage Usage Example
+ *
+ * cilk::reducer< cilk::op_mul<double> > r;
+ * cilk_for (int i = 0; i != N; ++i) {
+ * *r *= a[i];
+ * }
+ * double product;
+ * r.move_out(product);
+ *
+ * @section redopmul_monoid The Monoid
+ *
+ * @subsection redopmul_monoid_values Value Set
+ *
+ * The value set of a multiplication reducer is the set of values of `Type`,
+ * which is expected to be a builtin numeric type (or something like it, such
+ * as `std::complex`).
+ *
+ * @subsection redopmul_monoid_operator Operator
+ *
+ * The operator of a multiplication reducer is the multiplication operation,
+ * defined by the “`*`†binary operator on `Type`.
+ *
+ * @subsection redopmul_monoid_identity Identity
+ *
+ * The identity value of the reducer is the numeric value “`1`â€. This is
+ * expected to be the value of the expression `Type(1)`.
+ *
+ * @section redopmul_operations Operations
+ *
+ * @subsection redopmul_constructors Constructors
+ *
+ * reducer() // identity
+ * reducer(const Type& value)
+ * reducer(move_in(Type& variable))
+ *
+ * @subsection redopmul_get_set Set and Get
+ *
+ * r.set_value(const Type& value)
+ * const Type& = r.get_value() const
+ * r.move_in(Type& variable)
+ * r.move_out(Type& variable)
+ *
+ * @subsection redopmul_initial Initial Values
+ *
+ * If a multiplication reducer is constructed without an explicit initial
+ * value, then its initial value will be its identity value, as long as `Type`
+ * satisfies the requirements of @ref redopmul_types.
+ *
+ * @subsection redopmul_view_ops View Operations
+ *
+ * *r *= a
+ * *r = *r * a
+ * *r = *r * a1 * a2 … * an
+ *
+ * @section redopmul_floating_point Issues with Floating-Point Types
+ *
+ * Because of overflow and underflow issues, floating-point multiplication is
+ * not really associative. For example, `(1e200 * 1e-200) * 1e-200 == 1e-200`,
+ * but `1e200 * (1e-200 * 1e-200 == 0.
+ *
+ * In many cases, this won’t matter, but computations which have been
+ * carefully ordered to control overflow and underflow may not deal well with
+ * being reassociated. In general, you should be sure to understand the
+ * floating-point behavior of your program before doing any transformation
+ * that will reassociate its computations.
+ *
+ * @section redopmul_types Type and Operator Requirements
+ *
+ * `Type` must be `Copy Constructible`, `Default Constructible`, and
+ * `Assignable`.
+ *
+ * The operator “`*=`†must be defined on `Type`, with `x *= a` having the same
+ * meaning as `x = x * a`.
+ *
+ * The expression `Type(1)` must be a valid expression which yields the
+ * identity value (the value of `Type` whose numeric value is `1`).
+ *
+ * @section redopmul_in_c Multiplication Reducers in C
+ *
+ * The @ref CILK_C_REDUCER_OPMUL and @ref CILK_C_REDUCER_OPMUL_TYPE macros can
+ * be used to do multiplication reductions in C. For example:
+ *
+ * CILK_C_REDUCER_OPMUL(r, double, 1);
+ * CILK_C_REGISTER_REDUCER(r);
+ * cilk_for(int i = 0; i != n; ++i) {
+ * REDUCER_VIEW(r) *= a[i];
+ * }
+ * CILK_C_UNREGISTER_REDUCER(r);
+ * printf("The product of the elements of a is %f\n", REDUCER_VIEW(r));
+ *
+ * See @ref reducers_c_predefined.
+ */
+
+#ifdef __cplusplus
+
+namespace cilk {
+
+/** The multiplication reducer view class.
+ *
+ * This is the view class for reducers created with
+ * `cilk::reducer< cilk::op_mul<Type> >`. It holds the accumulator variable
+ * for the reduction, and allows only multiplication operations to be
+ * performed on it.
+ *
+ * @note The reducer “dereference†operation (`reducer::operator *()`)
+ * yields a reference to the view. Thus, for example, the view class’s
+ * `*=` operation would be used in an expression like `*r *= a`, where
+ * `r` is an op_mul reducer variable.
+ *
+ * @tparam Type The type of the contained accumulator variable. This will
+ * be the value type of a monoid_with_view that is
+ * instantiated with this view.
+ *
+ * @see ReducersMul
+ * @see op_mul
+ *
+ * @ingroup ReducersMul
+ */
+template <typename Type>
+class op_mul_view : public scalar_view<Type>
+{
+ typedef scalar_view<Type> base;
+
+public:
+ /** Class to represent the right-hand side of `*reducer = *reducer * value`.
+ *
+ * The only assignment operator for the op_mul_view class takes an
+ * rhs_proxy as its operand. This results in the syntactic restriction
+ * that the only expressions that can be assigned to an op_mul_view are
+ * ones which generate an rhs_proxy — that is, expressions of the form
+ * `op_mul_view * value ... * value`.
+ *
+ * @warning
+ * The lhs and rhs views in such an assignment must be the same;
+ * otherwise, the behavior will be undefined. (I.e., `v1 = v1 * x` is
+ * legal; `v1 = v2 * x` is illegal.) This condition will be checked with a
+ * runtime assertion when compiled in debug mode.
+ *
+ * @see op_mul_view
+ */
+ class rhs_proxy {
+ friend class op_mul_view;
+
+ const op_mul_view* m_view;
+ Type m_value;
+
+ // Constructor is invoked only from op_mul_view::operator*().
+ //
+ rhs_proxy(const op_mul_view* view, const Type& value) : m_view(view), m_value(value) {}
+
+ rhs_proxy& operator=(const rhs_proxy&); // Disable assignment operator
+ rhs_proxy(); // Disable default constructor
+
+ public:
+ /** Multiply by an additional rhs value. If `v` is an op_mul_view and
+ * `a1` is a value, then the expression `v * a1` invokes the view’s
+ * `operator*()` to create an rhs_proxy for `(v, a1)`; then
+ * `v * a1 * a2` invokes the rhs_proxy’s `operator*()` to create a
+ * new rhs_proxy for `(v, a1*a2)`. This allows the right-hand side of
+ * an assignment to be not just `view * value`, but
+ * `view * value * value ... * value`. The effect is that
+ *
+ * v = v * a1 * a2 ... * an;
+ *
+ * is evaluated as
+ *
+ * v = v * (a1 * a2 ... * an);
+ */
+ rhs_proxy& operator*(const Type& x) { m_value *= x; return *this; }
+ };
+
+
+ /** Default/identity constructor. This constructor initializes the
+ * contained value to `Type(1)`, which is expected to be the identity
+ * value for multiplication on `Type`.
+ */
+ op_mul_view() : base(Type(1)) {}
+
+ /** Construct with a specified initial value.
+ */
+ explicit op_mul_view(const Type& v) : base(v) {}
+
+ /** Reduction operation.
+ *
+ * This function is invoked by the @ref op_mul monoid to combine the views
+ * of two strands when the right strand merges with the left one. It
+ * multiplies the value contained in the left-strand view by the value
+ * contained in the right-strand view, and leaves the value in the
+ * right-strand view undefined.
+ *
+ * @param right A pointer to the right-strand view. (`this` points to
+ * the left-strand view.)
+ *
+ * @note Used only by the @ref op_mul monoid to implement the monoid
+ * reduce operation.
+ */
+ void reduce(op_mul_view* right) { this->m_value *= right->m_value; }
+
+ /** @name Accumulator variable updates.
+ *
+ * These functions support the various syntaxes for multiplying the
+ * accumulator variable contained in the view by some value.
+ */
+ //@{
+
+ /** Multiply the accumulator variable by @a x.
+ */
+ op_mul_view& operator*=(const Type& x) { this->m_value *= x; return *this; }
+
+ /** Create an object representing `*this * x`.
+ *
+ * @see rhs_proxy
+ */
+ rhs_proxy operator*(const Type& x) const { return rhs_proxy(this, x); }
+
+ /** Assign the result of a `view * value` expression to the view. Note that
+ * this is the only assignment operator for this class.
+ *
+ * @see rhs_proxy
+ */
+ op_mul_view& operator=(const rhs_proxy& rhs) {
+ __CILKRTS_ASSERT(this == rhs.m_view);
+ this->m_value *= rhs.m_value;
+ return *this;
+ }
+
+ //@}
+};
+
+/** Monoid class for multiplication reductions. Instantiate the cilk::reducer
+ * template class with an op_mul monoid to create a multiplication reducer
+ * class. For example, to compute the product of a set of `double` values:
+ *
+ * cilk::reducer< cilk::op_mul<double> > r;
+ *
+ * @see ReducersMul
+ * @see op_mul_view
+ *
+ * @ingroup ReducersMul
+ */
+template <typename Type>
+struct op_mul : public monoid_with_view< op_mul_view<Type> > {};
+
+} // namespace cilk
+
+#endif // __cplusplus
+
+
+/** @ingroup ReducersAdd
+ */
+//@{
+
+/** @name C language reducer macros
+ *
+ * These macros are used to declare and work with numeric op_mul reducers in
+ * C code.
+ *
+ * @see @ref page_reducers_in_c
+ */
+ //@{
+
+__CILKRTS_BEGIN_EXTERN_C
+
+/** Opmul reducer type name.
+ *
+ * This macro expands into the identifier which is the name of the op_mul
+ * reducer type for a specified numeric type.
+ *
+ * @param tn The @ref reducers_c_type_names "numeric type name" specifying
+ * the type of the reducer.
+ *
+ * @see @ref reducers_c_predefined
+ * @see ReducersMul
+ */
+#define CILK_C_REDUCER_OPMUL_TYPE(tn) \
+ __CILKRTS_MKIDENT(cilk_c_reducer_opmul_,tn)
+
+/** Declare an op_mul reducer object.
+ *
+ * This macro expands into a declaration of an op_mul reducer object for a
+ * specified numeric type. For example:
+ *
+ * CILK_C_REDUCER_OPMUL(my_reducer, double, 1.0);
+ *
+ * @param obj The variable name to be used for the declared reducer object.
+ * @param tn The @ref reducers_c_type_names "numeric type name" specifying
+ * the type of the reducer.
+ * @param v The initial value for the reducer. (A value which can be
+ * assigned to the numeric type represented by @a tn.)
+ *
+ * @see @ref reducers_c_predefined
+ * @see ReducersMul
+ */
+#define CILK_C_REDUCER_OPMUL(obj,tn,v) \
+ CILK_C_REDUCER_OPMUL_TYPE(tn) obj = \
+ CILK_C_INIT_REDUCER(_Typeof(obj.value), \
+ __CILKRTS_MKIDENT(cilk_c_reducer_opmul_reduce_,tn), \
+ __CILKRTS_MKIDENT(cilk_c_reducer_opmul_identity_,tn), \
+ __cilkrts_hyperobject_noop_destroy, v)
+
+/// @cond internal
+
+/** Declare the op_mul reducer functions for a numeric type.
+ *
+ * This macro expands into external function declarations for functions which
+ * implement the reducer functionality for the op_mul reducer type for a
+ * specified numeric type.
+ *
+ * @param t The value type of the reducer.
+ * @param tn The value “type name†identifier, used to construct the reducer
+ * type name, function names, etc.
+ */
+#define CILK_C_REDUCER_OPMUL_DECLARATION(t,tn) \
+ typedef CILK_C_DECLARE_REDUCER(t) CILK_C_REDUCER_OPMUL_TYPE(tn); \
+ __CILKRTS_DECLARE_REDUCER_REDUCE(cilk_c_reducer_opmul,tn,l,r); \
+ __CILKRTS_DECLARE_REDUCER_IDENTITY(cilk_c_reducer_opmul,tn);
+
+/** Define the op_mul reducer functions for a numeric type.
+ *
+ * This macro expands into function definitions for functions which implement
+ * the reducer functionality for the op_mul reducer type for a specified
+ * numeric type.
+ *
+ * @param t The value type of the reducer.
+ * @param tn The value “type name†identifier, used to construct the reducer
+ * type name, function names, etc.
+ */
+#define CILK_C_REDUCER_OPMUL_DEFINITION(t,tn) \
+ typedef CILK_C_DECLARE_REDUCER(t) CILK_C_REDUCER_OPMUL_TYPE(tn); \
+ __CILKRTS_DECLARE_REDUCER_REDUCE(cilk_c_reducer_opmul,tn,l,r) \
+ { *(t*)l *= *(t*)r; } \
+ __CILKRTS_DECLARE_REDUCER_IDENTITY(cilk_c_reducer_opmul,tn) \
+ { *(t*)v = 1; }
+
+//@{
+/** @def CILK_C_REDUCER_OPMUL_INSTANCE
+ * @brief Declare or define implementation functions for a reducer type.
+ *
+ * In the runtime source file c_reducers.c, the macro `CILK_C_DEFINE_REDUCERS`
+ * will be defined, and this macro will generate reducer implementation
+ * functions. Everywhere else, `CILK_C_DEFINE_REDUCERS` will be undefined, and
+ * this macro will expand into external declarations for the functions.
+ */
+#ifdef CILK_C_DEFINE_REDUCERS
+# define CILK_C_REDUCER_OPMUL_INSTANCE(t,tn) \
+ CILK_C_REDUCER_OPMUL_DEFINITION(t,tn)
+#else
+# define CILK_C_REDUCER_OPMUL_INSTANCE(t,tn) \
+ CILK_C_REDUCER_OPMUL_DECLARATION(t,tn)
+#endif
+//@}
+
+/* Declare or define an instance of the reducer type and its functions for each
+ * numeric type.
+ */
+CILK_C_REDUCER_OPMUL_INSTANCE(char, char)
+CILK_C_REDUCER_OPMUL_INSTANCE(unsigned char, uchar)
+CILK_C_REDUCER_OPMUL_INSTANCE(signed char, schar)
+CILK_C_REDUCER_OPMUL_INSTANCE(wchar_t, wchar_t)
+CILK_C_REDUCER_OPMUL_INSTANCE(short, short)
+CILK_C_REDUCER_OPMUL_INSTANCE(unsigned short, ushort)
+CILK_C_REDUCER_OPMUL_INSTANCE(int, int)
+CILK_C_REDUCER_OPMUL_INSTANCE(unsigned int, uint)
+CILK_C_REDUCER_OPMUL_INSTANCE(unsigned int, unsigned) /* alternate name */
+CILK_C_REDUCER_OPMUL_INSTANCE(long, long)
+CILK_C_REDUCER_OPMUL_INSTANCE(unsigned long, ulong)
+CILK_C_REDUCER_OPMUL_INSTANCE(long long, longlong)
+CILK_C_REDUCER_OPMUL_INSTANCE(unsigned long long, ulonglong)
+CILK_C_REDUCER_OPMUL_INSTANCE(float, float)
+CILK_C_REDUCER_OPMUL_INSTANCE(double, double)
+CILK_C_REDUCER_OPMUL_INSTANCE(long double, longdouble)
+
+//@endcond
+
+__CILKRTS_END_EXTERN_C
+
+//@}
+
+//@}
+
+#endif /* REDUCER_OPMUL_H_INCLUDED */
diff --git a/libcilkrts/include/cilk/reducer_opor.h b/libcilkrts/include/cilk/reducer_opor.h
new file mode 100644
index 00000000000..5c8e7bd972e
--- /dev/null
+++ b/libcilkrts/include/cilk/reducer_opor.h
@@ -0,0 +1,598 @@
+/* reducer_opor.h -*- C++ -*-
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file reducer_opor.h
+ *
+ * @brief Defines classes for doing parallel bitwise or reductions.
+ *
+ * @ingroup ReducersOr
+ *
+ * @see ReducersOr
+ */
+
+#ifndef REDUCER_OPOR_H_INCLUDED
+#define REDUCER_OPOR_H_INCLUDED
+
+#include <cilk/reducer.h>
+
+/** @defgroup ReducersOr Bitwise Or Reducers
+ *
+ * Bitwise and reducers allow the computation of the bitwise and of a set of
+ * values in parallel.
+ *
+ * @ingroup Reducers
+ *
+ * You should be familiar with @ref pagereducers "Cilk reducers", described in
+ * file `reducers.md`, and particularly with @ref reducers_using, before trying
+ * to use the information in this file.
+ *
+ * @section redopor_usage Usage Example
+ *
+ * cilk::reducer< cilk::op_or<unsigned> > r;
+ * cilk_for (int i = 0; i != N; ++i) {
+ * *r |= a[i];
+ * }
+ * unsigned result;
+ * r.move_out(result);
+ *
+ * @section redopor_monoid The Monoid
+ *
+ * @subsection redopor_monoid_values Value Set
+ *
+ * The value set of a bitwise or reducer is the set of values of `Type`, which
+ * is expected to be a builtin integer type which has a representation as a
+ * sequence of bits (or something like it, such as `bool` or `std::bitset`).
+ *
+ * @subsection redopor_monoid_operator Operator
+ *
+ * The operator of a bitwise or reducer is the bitwise or operator, defined by
+ * the “`|`†binary operator on `Type`.
+ *
+ * @subsection redopor_monoid_identity Identity
+ *
+ * The identity value of the reducer is the value whose representation
+ * contains all 0-bits. This is expected to be the value of the default
+ * constructor `Type()`.
+ *
+ * @section redopor_operations Operations
+ *
+ * @subsection redopor_constructors Constructors
+ *
+ * reducer() // identity
+ * reducer(const Type& value)
+ * reducer(move_in(Type& variable))
+ *
+ * @subsection redopor_get_set Set and Get
+ *
+ * r.set_value(const Type& value)
+ * const Type& = r.get_value() const
+ * r.move_in(Type& variable)
+ * r.move_out(Type& variable)
+ *
+ * @subsection redopor_initial Initial Values
+ *
+ * If a bitwise or reducer is constructed without an explicit initial value,
+ * then its initial value will be its identity value, as long as `Type`
+ * satisfies the requirements of @ref redopor_types.
+ *
+ * @subsection redopor_view_ops View Operations
+ *
+ * *r |= a
+ * *r = *r | a
+ * *r = *r | a1 | a2 … | an
+ *
+ * @section redopor_types Type and Operator Requirements
+ *
+ * `Type` must be `Copy Constructible`, `Default Constructible`, and
+ * `Assignable`.
+ *
+ * The operator “`|=`†must be defined on `Type`, with `x |= a` having the
+ * same meaning as `x = x | a`.
+ *
+ * The expression `Type()` must be a valid expression which yields the
+ * identity value (the value of `Type` whose representation consists of all
+ * 0-bits).
+ *
+ * @section redopor_in_c Bitwise Or Reducers in C
+ *
+ * The @ref CILK_C_REDUCER_OPOR and @ref CILK_C_REDUCER_OPOR_TYPE macros can
+ * be used to do bitwise or reductions in C. For example:
+ *
+ * CILK_C_REDUCER_OPOR(r, uint, 0);
+ * CILK_C_REGISTER_REDUCER(r);
+ * cilk_for(int i = 0; i != n; ++i) {
+ * REDUCER_VIEW(r) |= a[i];
+ * }
+ * CILK_C_UNREGISTER_REDUCER(r);
+ * printf("The bitwise OR of the elements of a is %x\n", REDUCER_VIEW(r));
+ *
+ * See @ref reducers_c_predefined.
+ */
+
+#ifdef __cplusplus
+
+namespace cilk {
+
+/** The bitwise or reducer view class.
+ *
+ * This is the view class for reducers created with
+ * `cilk::reducer< cilk::op_or<Type> >`. It holds the accumulator variable for
+ * the reduction, and allows only `or` operations to be performed on it.
+ *
+ * @note The reducer “dereference†operation (`reducer::operator *()`)
+ * yields a reference to the view. Thus, for example, the view class’s
+ * `|=` operation would be used in an expression like `*r |= a`, where
+ * `r` is an opmod reducer variable.
+ *
+ * @tparam Type The type of the contained accumulator variable. This will
+ * be the value type of a monoid_with_view that is
+ * instantiated with this view.
+ *
+ * @see ReducersOr
+ * @see op_or
+ *
+ * @ingroup ReducersOr
+ */
+template <typename Type>
+class op_or_view : public scalar_view<Type>
+{
+ typedef scalar_view<Type> base;
+
+public:
+ /** Class to represent the right-hand side of `*reducer = *reducer | value`.
+ *
+ * The only assignment operator for the op_or_view class takes an
+ * rhs_proxy as its operand. This results in the syntactic restriction
+ * that the only expressions that can be assigned to an op_or_view are
+ * ones which generate an rhs_proxy — that is, expressions of the form
+ * `op_or_view | value ... | value`.
+ *
+ * @warning
+ * The lhs and rhs views in such an assignment must be the same;
+ * otherwise, the behavior will be undefined. (I.e., `v1 = v1 | x` is
+ * legal; `v1 = v2 | x` is illegal.) This condition will be checked with
+ * a runtime assertion when compiled in debug mode.
+ *
+ * @see op_or_view
+ */
+ class rhs_proxy {
+ friend class op_or_view;
+
+ const op_or_view* m_view;
+ Type m_value;
+
+ // Constructor is invoked only from op_or_view::operator|().
+ //
+ rhs_proxy(const op_or_view* view, const Type& value) : m_view(view), m_value(value) {}
+
+ rhs_proxy& operator=(const rhs_proxy&); // Disable assignment operator
+ rhs_proxy(); // Disable default constructor
+
+ public:
+ /** Bitwise or with an additional rhs value. If `v` is an op_or_view
+ * and `a1` is a value, then the expression `v | a1` invokes the
+ * view’s `operator|()` to create an rhs_proxy for `(v, a1)`; then
+ * `v | a1 | a2` invokes the rhs_proxy’s `operator|()` to create a new
+ * rhs_proxy for `(v, a1|a2)`. This allows the right-hand side of an
+ * assignment to be not just `view | value`, but
+ ( `view | value | value ... | value`. The effect is that
+ *
+ * v = v | a1 | a2 ... | an;
+ *
+ * is evaluated as
+ *
+ * v = v | (a1 | a2 ... | an);
+ */
+ rhs_proxy& operator|(const Type& x) { m_value |= x; return *this; }
+ };
+
+
+ /** Default/identity constructor. This constructor initializes the
+ * contained value to `Type()`.
+ */
+ op_or_view() : base() {}
+
+ /** Construct with a specified initial value.
+ */
+ explicit op_or_view(const Type& v) : base(v) {}
+
+ /** Reduction operation.
+ *
+ * This function is invoked by the @ref op_or monoid to combine the views
+ * of two strands when the right strand merges with the left one. It
+ * “ors†the value contained in the left-strand view by the value
+ * contained in the right-strand view, and leaves the value in the
+ * right-strand view undefined.
+ *
+ * @param right A pointer to the right-strand view. (`this` points to
+ * the left-strand view.)
+ *
+ * @note Used only by the @ref op_or monoid to implement the monoid
+ * reduce operation.
+ */
+ void reduce(op_or_view* right) { this->m_value |= right->m_value; }
+
+ /** @name Accumulator variable updates.
+ *
+ * These functions support the various syntaxes for “oring†the
+ * accumulator variable contained in the view with some value.
+ */
+ //@{
+
+ /** Or the accumulator variable with @a x.
+ */
+ op_or_view& operator|=(const Type& x) { this->m_value |= x; return *this; }
+
+ /** Create an object representing `*this | x`.
+ *
+ * @see rhs_proxy
+ */
+ rhs_proxy operator|(const Type& x) const { return rhs_proxy(this, x); }
+
+ /** Assign the result of a `view | value` expression to the view. Note that
+ * this is the only assignment operator for this class.
+ *
+ * @see rhs_proxy
+ */
+ op_or_view& operator=(const rhs_proxy& rhs) {
+ __CILKRTS_ASSERT(this == rhs.m_view);
+ this->m_value |= rhs.m_value;
+ return *this;
+ }
+
+ //@}
+};
+
+/** Monoid class for bitwise or reductions. Instantiate the cilk::reducer
+ * template class with an op_or monoid to create a bitwise or reducer
+ * class. For example, to compute the bitwise or of a set of `unsigned long`
+ * values:
+ *
+ * cilk::reducer< cilk::op_or<unsigned long> > r;
+ *
+ * @tparam Type The reducer value type.
+ * @tparam Align If `false` (the default), reducers instantiated on this
+ * monoid will be naturally aligned (the Cilk library 1.0
+ * behavior). If `true`, reducers instantiated on this monoid
+ * will be cache-aligned for binary compatibility with
+ * reducers in Cilk library version 0.9.
+ *
+ * @see ReducersOr
+ * @see op_or_view
+ *
+ * @ingroup ReducersOr
+ */
+template <typename Type, bool Align = false>
+struct op_or : public monoid_with_view<op_or_view<Type>, Align> {};
+
+/** Deprecated bitwise or reducer class.
+ *
+ * reducer_opor is the same as @ref reducer<@ref op_or>, except that
+ * reducer_opor is a proxy for the contained view, so that accumulator
+ * variable update operations can be applied directly to the reducer. For
+ * example, a value is ored with a `reducer<%op_or>` with `*r |= a`, but a
+ * value can be ored with a `%reducer_opor` with `r |= a`.
+ *
+ * @deprecated Users are strongly encouraged to use `reducer<monoid>`
+ * reducers rather than the old wrappers like reducer_opor.
+ * The `reducer<monoid>` reducers show the reducer/monoid/view
+ * architecture more clearly, are more consistent in their
+ * implementation, and present a simpler model for new
+ * user-implemented reducers.
+ *
+ * @note Implicit conversions are provided between `%reducer_opor`
+ * and `reducer<%op_or>`. This allows incremental code
+ * conversion: old code that used `%reducer_opor` can pass a
+ * `%reducer_opor` to a converted function that now expects a
+ * pointer or reference to a `reducer<%op_or>`, and vice
+ * versa.
+ *
+ * @tparam Type The value type of the reducer.
+ *
+ * @see op_or
+ * @see reducer
+ * @see ReducersOr
+ *
+ * @ingroup ReducersOr
+ */
+template <typename Type>
+class reducer_opor : public reducer< op_or<Type, true> >
+{
+ typedef reducer< op_or<Type, true> > base;
+ using base::view;
+
+ public:
+ /// The view type for the reducer.
+ typedef typename base::view_type view_type;
+
+ /// The view’s rhs proxy type.
+ typedef typename view_type::rhs_proxy rhs_proxy;
+
+ /// The view type for the reducer.
+ typedef view_type View;
+
+ /// The monoid type for the reducer.
+ typedef typename base::monoid_type Monoid;
+
+ /** @name Constructors
+ */
+ //@{
+
+ /** Default (identity) constructor.
+ *
+ * Constructs the wrapper with the default initial value of `Type()`.
+ */
+ reducer_opor() {}
+
+ /** Value constructor.
+ *
+ * Constructs the wrapper with a specified initial value.
+ */
+ explicit reducer_opor(const Type& initial_value) : base(initial_value) {}
+
+ //@}
+
+ /** @name Forwarded functions
+ * @details Functions that update the contained accumulator variable are
+ * simply forwarded to the contained @ref op_and_view. */
+ //@{
+
+ /// @copydoc op_or_view::operator|=(const Type&)
+ reducer_opor& operator|=(const Type& x)
+ {
+ view() |= x; return *this;
+ }
+
+ // The legacy definition of reducer_opor::operator|() has different
+ // behavior and a different return type than this definition. The legacy
+ // version is defined as a member function, so this new version is defined
+ // as a free function to give it a different signature, so that they won’t
+ // end up sharing a single object file entry.
+
+ /// @copydoc op_or_view::operator|(const Type&) const
+ friend rhs_proxy operator|(const reducer_opor& r, const Type& x)
+ {
+ return r.view() | x;
+ }
+
+ /// @copydoc op_and_view::operator=(const rhs_proxy&)
+ reducer_opor& operator=(const rhs_proxy& temp)
+ {
+ view() = temp; return *this;
+ }
+ //@}
+
+ /** @name Dereference
+ * @details Dereferencing a wrapper is a no-op. It simply returns the
+ * wrapper. Combined with the rule that the wrapper forwards view
+ * operations to its contained view, this means that view operations can
+ * be written the same way on reducers and wrappers, which is convenient
+ * for incrementally converting old code using wrappers to use reducers
+ * instead. That is:
+ *
+ * reducer< op_and<int> > r;
+ * *r &= a; // *r returns the view
+ * // operator &= is a view member function
+ *
+ * reducer_opand<int> w;
+ * *w &= a; // *w returns the wrapper
+ * // operator &= is a wrapper member function that
+ * // calls the corresponding view function
+ */
+ //@{
+ reducer_opor& operator*() { return *this; }
+ reducer_opor const& operator*() const { return *this; }
+
+ reducer_opor* operator->() { return this; }
+ reducer_opor const* operator->() const { return this; }
+ //@}
+
+ /** @name Upcast
+ * @details In Cilk library 0.9, reducers were always cache-aligned. In
+ * library 1.0, reducer cache alignment is optional. By default, reducers
+ * are unaligned (i.e., just naturally aligned), but legacy wrappers
+ * inherit from cache-aligned reducers for binary compatibility.
+ *
+ * This means that a wrapper will automatically be upcast to its aligned
+ * reducer base class. The following conversion operators provide
+ * pseudo-upcasts to the corresponding unaligned reducer class.
+ */
+ //@{
+ operator reducer< op_or<Type, false> >& ()
+ {
+ return *reinterpret_cast< reducer< op_or<Type, false> >* >(this);
+ }
+ operator const reducer< op_or<Type, false> >& () const
+ {
+ return *reinterpret_cast< const reducer< op_or<Type, false> >* >(this);
+ }
+ //@}
+
+};
+
+/// @cond internal
+/** Metafunction specialization for reducer conversion.
+ *
+ * This specialization of the @ref legacy_reducer_downcast template class
+ * defined in reducer.h causes the `reducer< op_or<Type> >` class to have an
+ * `operator reducer_opor<Type>& ()` conversion operator that statically
+ * downcasts the `reducer<op_or>` to the corresponding `reducer_opor` type.
+ * (The reverse conversion, from `reducer_opor` to `reducer<op_or>`, is just
+ * an upcast, which is provided for free by the language.)
+ *
+ * @ingroup ReducersOr
+ */
+template <typename Type, bool Align>
+struct legacy_reducer_downcast<reducer<op_or<Type, Align> > >
+{
+ typedef reducer_opor<Type> type;
+};
+/// @endcond
+
+} // namespace cilk
+
+#endif /* __cplusplus */
+
+
+/** @ingroup ReducersOr
+ */
+//@{
+
+/** @name C language reducer macros
+ *
+ * These macros are used to declare and work with op_or reducers in C code.
+ *
+ * @see @ref page_reducers_in_c
+ */
+ //@{
+
+__CILKRTS_BEGIN_EXTERN_C
+
+/** Opor reducer type name.
+ *
+ * This macro expands into the identifier which is the name of the op_or
+ * reducer type for a specified numeric type.
+ *
+ * @param tn The @ref reducers_c_type_names "numeric type name" specifying
+ * the type of the reducer.
+ *
+ * @see @ref reducers_c_predefined
+ * @see ReducersOr
+ */
+#define CILK_C_REDUCER_OPOR_TYPE(tn) \
+ __CILKRTS_MKIDENT(cilk_c_reducer_opor_,tn)
+
+/** Declare an op_or reducer object.
+ *
+ * This macro expands into a declaration of an op_or reducer object for a
+ * specified numeric type. For example:
+ *
+ * CILK_C_REDUCER_OPOR(my_reducer, ulong, 0);
+ *
+ * @param obj The variable name to be used for the declared reducer object.
+ * @param tn The @ref reducers_c_type_names "numeric type name" specifying
+ * the type of the reducer.
+ * @param v The initial value for the reducer. (A value which can be
+ * assigned to the numeric type represented by @a tn.)
+ *
+ * @see @ref reducers_c_predefined
+ * @see ReducersOr
+ */
+#define CILK_C_REDUCER_OPOR(obj,tn,v) \
+ CILK_C_REDUCER_OPOR_TYPE(tn) obj = \
+ CILK_C_INIT_REDUCER(_Typeof(obj.value), \
+ __CILKRTS_MKIDENT(cilk_c_reducer_opor_reduce_,tn), \
+ __CILKRTS_MKIDENT(cilk_c_reducer_opor_identity_,tn), \
+ __cilkrts_hyperobject_noop_destroy, v)
+
+/// @cond internal
+
+/** Declare the op_or reducer functions for a numeric type.
+ *
+ * This macro expands into external function declarations for functions which
+ * implement the reducer functionality for the op_or reducer type for a
+ * specified numeric type.
+ *
+ * @param t The value type of the reducer.
+ * @param tn The value “type name†identifier, used to construct the reducer
+ * type name, function names, etc.
+ */
+#define CILK_C_REDUCER_OPOR_DECLARATION(t,tn) \
+ typedef CILK_C_DECLARE_REDUCER(t) CILK_C_REDUCER_OPOR_TYPE(tn); \
+ __CILKRTS_DECLARE_REDUCER_REDUCE(cilk_c_reducer_opor,tn,l,r); \
+ __CILKRTS_DECLARE_REDUCER_IDENTITY(cilk_c_reducer_opor,tn);
+
+/** Define the op_or reducer functions for a numeric type.
+ *
+ * This macro expands into function definitions for functions which implement
+ * the reducer functionality for the op_or reducer type for a specified
+ * numeric type.
+ *
+ * @param t The value type of the reducer.
+ * @param tn The value “type name†identifier, used to construct the reducer
+ * type name, function names, etc.
+ */
+#define CILK_C_REDUCER_OPOR_DEFINITION(t,tn) \
+ typedef CILK_C_DECLARE_REDUCER(t) CILK_C_REDUCER_OPOR_TYPE(tn); \
+ __CILKRTS_DECLARE_REDUCER_REDUCE(cilk_c_reducer_opor,tn,l,r) \
+ { *(t*)l |= *(t*)r; } \
+ __CILKRTS_DECLARE_REDUCER_IDENTITY(cilk_c_reducer_opor,tn) \
+ { *(t*)v = 0; }
+
+//@{
+/** @def CILK_C_REDUCER_OPOR_INSTANCE
+ * @brief Declare or define implementation functions for a reducer type.
+ *
+ * In the runtime source file c_reducers.c, the macro `CILK_C_DEFINE_REDUCERS`
+ * will be defined, and this macro will generate reducer implementation
+ * functions. Everywhere else, `CILK_C_DEFINE_REDUCERS` will be undefined, and
+ * this macro will expand into external declarations for the functions.
+ */
+#ifdef CILK_C_DEFINE_REDUCERS
+# define CILK_C_REDUCER_OPOR_INSTANCE(t,tn) \
+ CILK_C_REDUCER_OPOR_DEFINITION(t,tn)
+#else
+# define CILK_C_REDUCER_OPOR_INSTANCE(t,tn) \
+ CILK_C_REDUCER_OPOR_DECLARATION(t,tn)
+#endif
+//@}
+
+/* Declare or define an instance of the reducer type and its functions for each
+ * numeric type.
+ */
+CILK_C_REDUCER_OPOR_INSTANCE(char, char)
+CILK_C_REDUCER_OPOR_INSTANCE(unsigned char, uchar)
+CILK_C_REDUCER_OPOR_INSTANCE(signed char, schar)
+CILK_C_REDUCER_OPOR_INSTANCE(wchar_t, wchar_t)
+CILK_C_REDUCER_OPOR_INSTANCE(short, short)
+CILK_C_REDUCER_OPOR_INSTANCE(unsigned short, ushort)
+CILK_C_REDUCER_OPOR_INSTANCE(int, int)
+CILK_C_REDUCER_OPOR_INSTANCE(unsigned int, uint)
+CILK_C_REDUCER_OPOR_INSTANCE(unsigned int, unsigned) /* alternate name */
+CILK_C_REDUCER_OPOR_INSTANCE(long, long)
+CILK_C_REDUCER_OPOR_INSTANCE(unsigned long, ulong)
+CILK_C_REDUCER_OPOR_INSTANCE(long long, longlong)
+CILK_C_REDUCER_OPOR_INSTANCE(unsigned long long, ulonglong)
+
+//@endcond
+
+__CILKRTS_END_EXTERN_C
+
+//@}
+
+//@}
+
+#endif /* REDUCER_OPOR_H_INCLUDED */
diff --git a/libcilkrts/include/cilk/reducer_opxor.h b/libcilkrts/include/cilk/reducer_opxor.h
new file mode 100644
index 00000000000..fed49943ef6
--- /dev/null
+++ b/libcilkrts/include/cilk/reducer_opxor.h
@@ -0,0 +1,598 @@
+/* reducer_opxor.h -*- C++ -*-
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file reducer_opxor.h
+ *
+ * @brief Defines classes for doing parallel bitwise or reductions.
+ *
+ * @ingroup ReducersXor
+ *
+ * @see ReducersXor
+ */
+
+#ifndef REDUCER_OPXOR_H_INCLUDED
+#define REDUCER_OPXOR_H_INCLUDED
+
+#include <cilk/reducer.h>
+
+/** @defgroup ReducersXor Bitwise Xor Reducers
+ *
+ * Bitwise and reducers allow the computation of the bitwise and of a set of
+ * values in parallel.
+ *
+ * @ingroup Reducers
+ *
+ * You should be familiar with @ref pagereducers "Cilk reducers", described in
+ * file `reducers.md`, and particularly with @ref reducers_using, before trying
+ * to use the information in this file.
+ *
+ * @section redopxor_usage Usage Example
+ *
+ * cilk::reducer< cilk::op_xor<unsigned> > r;
+ * cilk_for (int i = 0; i != N; ++i) {
+ * *r ^= a[i];
+ * }
+ * unsigned result;
+ * r.move_out(result);
+ *
+ * @section redopxor_monoid The Monoid
+ *
+ * @subsection redopxor_monoid_values Value Set
+ *
+ * The value set of a bitwise xor reducer is the set of values of `Type`, which
+ * is expected to be a builtin integer type which has a representation as a
+ * sequence of bits (or something like it, such as `bool` or `std::bitset`).
+ *
+ * @subsection redopxor_monoid_operator Operator
+ *
+ * The operator of a bitwise xor reducer is the bitwise xor operator, defined
+ * by the “`^`†binary operator on `Type`.
+ *
+ * @subsection redopxor_monoid_identity Identity
+ *
+ * The identity value of the reducer is the value whose representation
+ * contains all 0-bits. This is expected to be the value of the default
+ * constructor `Type()`.
+ *
+ * @section redopxor_operations Operations
+ *
+ * @subsection redopxor_constructors Constructors
+ *
+ * reducer() // identity
+ * reducer(const Type& value)
+ * reducer(move_in(Type& variable))
+ *
+ * @subsection redopxor_get_set Set and Get
+ *
+ * r.set_value(const Type& value)
+ * const Type& = r.get_value() const
+ * r.move_in(Type& variable)
+ * r.move_out(Type& variable)
+ *
+ * @subsection redopxor_initial Initial Values
+ *
+ * If a bitwise xor reducer is constructed without an explicit initial value,
+ * then its initial value will be its identity value, as long as `Type`
+ * satisfies the requirements of @ref redopxor_types.
+ *
+ * @subsection redopxor_view_ops View Operations
+ *
+ * *r ^= a
+ * *r = *r ^ a
+ * *r = *r ^ a1 ^ a2 … ^ an
+ *
+ * @section redopxor_types Type and Operator Requirements
+ *
+ * `Type` must be `Copy Constructible`, `Default Constructible`, and
+ * `Assignable`.
+ *
+ * The operator “`^=`†must be defined on `Type`, with `x ^= a` having the
+ * same meaning as `x = x ^ a`.
+ *
+ * The expression `Type()` must be a valid expression which yields the
+ * identity value (the value of `Type` whose representation consists of all
+ * 0-bits).
+ *
+ * @section redopxor_in_c Bitwise Xor Reducers in C
+ *
+ * The @ref CILK_C_REDUCER_OPXOR and @ref CILK_C_REDUCER_OPXOR_TYPE macros can
+ * be used to do bitwise xor reductions in C. For example:
+ *
+ * CILK_C_REDUCER_OPXOR(r, uint, 0);
+ * CILK_C_REGISTER_REDUCER(r);
+ * cilk_for(int i = 0; i != n; ++i) {
+ * REDUCER_VIEW(r) ^= a[i];
+ * }
+ * CILK_C_UNREGISTER_REDUCER(r);
+ * printf("The bitwise XOR of the elements of a is %x\n", REDUCER_VIEW(r));
+ *
+ * See @ref reducers_c_predefined.
+ */
+
+#ifdef __cplusplus
+
+namespace cilk {
+
+/** The bitwise xor reducer view class.
+ *
+ * This is the view class for reducers created with
+ * `cilk::reducer< cilk::op_xor<Type> >`. It holds the accumulator variable
+ * for the reduction, and allows only `xor` operations to be performed on it.
+ *
+ * @note The reducer “dereference†operation (`reducer::operator *()`)
+ * yields a reference to the view. Thus, for example, the view class’s
+ * `^=` operation would be used in an expression like `*r ^= a`, where
+ * `r` is an opmod reducer variable.
+ *
+ * @tparam Type The type of the contained accumulator variable. This will
+ * be the value type of a monoid_with_view that is
+ * instantiated with this view.
+ *
+ * @see ReducersXor
+ * @see op_xor
+ *
+ * @ingroup ReducersXor
+ */
+template <typename Type>
+class op_xor_view : public scalar_view<Type>
+{
+ typedef scalar_view<Type> base;
+
+public:
+ /** Class to represent the right-hand side of `*reducer = *reducer ^ value`.
+ *
+ * The only assignment operator for the op_xor_view class takes an
+ * rhs_proxy as its operand. This results in the syntactic restriction
+ * that the only expressions that can be assigned to an op_xor_view are
+ * ones which generate an rhs_proxy — that is, expressions of the form
+ * `op_xor_view ^ value ... ^ value`.
+ *
+ * @warning
+ * The lhs and rhs views in such an assignment must be the same;
+ * otherwise, the behavior will be undefined. (I.e., `v1 = v1 ^ x` is
+ * legal; `v1 = v2 ^ x` is illegal.) This condition will be checked with
+ * a runtime assertion when compiled in debug mode.
+ *
+ * @see op_xor_view
+ */
+ class rhs_proxy {
+ friend class op_xor_view;
+
+ const op_xor_view* m_view;
+ Type m_value;
+
+ // Constructor is invoked only from op_xor_view::operator^().
+ //
+ rhs_proxy(const op_xor_view* view, const Type& value) : m_view(view), m_value(value) {}
+
+ rhs_proxy& operator=(const rhs_proxy&); // Disable assignment operator
+ rhs_proxy(); // Disable default constructor
+
+ public:
+ /** Bitwise xor with an additional rhs value. If `v` is an op_xor_view
+ * and `a1` is a value, then the expression `v ^ a1` invokes the
+ * view’s `operator^()` to create an rhs_proxy for `(v, a1)`; then
+ * `v ^ a1 ^ a2` invokes the rhs_proxy’s `operator^()` to create a new
+ * rhs_proxy for `(v, a1^a2)`. This allows the right-hand side of an
+ * assignment to be not just `view ^ value`, but
+ ( `view ^ value ^ value ... ^ value`. The effect is that
+ *
+ * v = v ^ a1 ^ a2 ... ^ an;
+ *
+ * is evaluated as
+ *
+ * v = v ^ (a1 ^ a2 ... ^ an);
+ */
+ rhs_proxy& operator^(const Type& x) { m_value ^= x; return *this; }
+ };
+
+
+ /** Default/identity constructor. This constructor initializes the
+ * contained value to `Type()`.
+ */
+ op_xor_view() : base() {}
+
+ /** Construct with a specified initial value.
+ */
+ explicit op_xor_view(const Type& v) : base(v) {}
+
+ /** Reduction operation.
+ *
+ * This function is invoked by the @ref op_xor monoid to combine the views
+ * of two strands when the right strand merges with the left one. It
+ * “xors†the value contained in the left-strand view by the value
+ * contained in the right-strand view, and leaves the value in the
+ * right-strand view undefined.
+ *
+ * @param right A pointer to the right-strand view. (`this` points to
+ * the left-strand view.)
+ *
+ * @note Used only by the @ref op_xor monoid to implement the monoid
+ * reduce operation.
+ */
+ void reduce(op_xor_view* right) { this->m_value ^= right->m_value; }
+
+ /** @name Accumulator variable updates.
+ *
+ * These functions support the various syntaxes for “xoring†the
+ * accumulator variable contained in the view with some value.
+ */
+ //@{
+
+ /** Xor the accumulator variable with @a x.
+ */
+ op_xor_view& operator^=(const Type& x) { this->m_value ^= x; return *this; }
+
+ /** Create an object representing `*this ^ x`.
+ *
+ * @see rhs_proxy
+ */
+ rhs_proxy operator^(const Type& x) const { return rhs_proxy(this, x); }
+
+ /** Assign the result of a `view ^ value` expression to the view. Note that
+ * this is the only assignment operator for this class.
+ *
+ * @see rhs_proxy
+ */
+ op_xor_view& operator=(const rhs_proxy& rhs) {
+ __CILKRTS_ASSERT(this == rhs.m_view);
+ this->m_value ^= rhs.m_value;
+ return *this;
+ }
+
+ //@}
+};
+
+/** Monoid class for bitwise xor reductions. Instantiate the cilk::reducer
+ * template class with an op_xor monoid to create a bitwise xor reducer
+ * class. For example, to compute the bitwise xor of a set of `unsigned long`
+ * values:
+ *
+ * cilk::reducer< cilk::op_xor<unsigned long> > r;
+ *
+ * @tparam Type The reducer value type.
+ * @tparam Align If `false` (the default), reducers instantiated on this
+ * monoid will be naturally aligned (the Cilk library 1.0
+ * behavior). If `true`, reducers instantiated on this monoid
+ * will be cache-aligned for binary compatibility with
+ * reducers in Cilk library version 0.9.
+ *
+ * @see ReducersXor
+ * @see op_xor_view
+ *
+ * @ingroup ReducersXor
+ */
+template <typename Type, bool Align = false>
+struct op_xor : public monoid_with_view<op_xor_view<Type>, Align> {};
+
+/** Deprecated bitwise xor reducer class.
+ *
+ * reducer_opxor is the same as @ref reducer<@ref op_xor>, except that
+ * reducer_opxor is a proxy for the contained view, so that accumulator
+ * variable update operations can be applied directly to the reducer. For
+ * example, a value is xored with a `reducer<%op_xor>` with `*r ^= a`, but a
+ * value can be xored with a `%reducer_opxor` with `r ^= a`.
+ *
+ * @deprecated Users are strongly encouraged to use `reducer<monoid>`
+ * reducers rather than the old wrappers like reducer_opand.
+ * The `reducer<monoid>` reducers show the reducer/monoid/view
+ * architecture more clearly, are more consistent in their
+ * implementation, and present a simpler model for new
+ * user-implemented reducers.
+ *
+ * @note Implicit conversions are provided between `%reducer_opxor`
+ * and `reducer<%op_xor>`. This allows incremental code
+ * conversion: old code that used `%reducer_opxor` can pass a
+ * `%reducer_opxor` to a converted function that now expects a
+ * pointer or reference to a `reducer<%op_xor>`, and vice
+ * versa.
+ *
+ * @tparam Type The value type of the reducer.
+ *
+ * @see op_xor
+ * @see reducer
+ * @see ReducersXor
+ *
+ * @ingroup ReducersXor
+ */
+template <typename Type>
+class reducer_opxor : public reducer< op_xor<Type, true> >
+{
+ typedef reducer< op_xor<Type, true> > base;
+ using base::view;
+
+ public:
+ /// The view type for the reducer.
+ typedef typename base::view_type view_type;
+
+ /// The view’s rhs proxy type.
+ typedef typename view_type::rhs_proxy rhs_proxy;
+
+ /// The view type for the reducer.
+ typedef view_type View;
+
+ /// The monoid type for the reducer.
+ typedef typename base::monoid_type Monoid;
+
+ /** @name Constructors
+ */
+ //@{
+
+ /** Default (identity) constructor.
+ *
+ * Constructs the wrapper with the default initial value of `Type()`.
+ */
+ reducer_opxor() {}
+
+ /** Value constructor.
+ *
+ * Constructs the wrapper with a specified initial value.
+ */
+ explicit reducer_opxor(const Type& initial_value) : base(initial_value) {}
+
+ //@}
+
+ /** @name Forwarded functions
+ * @details Functions that update the contained accumulator variable are
+ * simply forwarded to the contained @ref op_and_view. */
+ //@{
+
+ /// @copydoc op_xor_view::operator^=(const Type&)
+ reducer_opxor& operator^=(const Type& x)
+ {
+ view() ^= x; return *this;
+ }
+
+ // The legacy definition of reducer_opxor::operator^() has different
+ // behavior and a different return type than this definition. The legacy
+ // version is defined as a member function, so this new version is defined
+ // as a free function to give it a different signature, so that they won’t
+ // end up sharing a single object file entry.
+
+ /// @copydoc op_xor_view::operator^(const Type&) const
+ friend rhs_proxy operator^(const reducer_opxor& r, const Type& x)
+ {
+ return r.view() ^ x;
+ }
+
+ /// @copydoc op_and_view::operator=(const rhs_proxy&)
+ reducer_opxor& operator=(const rhs_proxy& temp)
+ {
+ view() = temp; return *this;
+ }
+ //@}
+
+ /** @name Dereference
+ * @details Dereferencing a wrapper is a no-op. It simply returns the
+ * wrapper. Combined with the rule that the wrapper forwards view
+ * operations to its contained view, this means that view operations can
+ * be written the same way on reducers and wrappers, which is convenient
+ * for incrementally converting old code using wrappers to use reducers
+ * instead. That is:
+ *
+ * reducer< op_and<int> > r;
+ * *r &= a; // *r returns the view
+ * // operator &= is a view member function
+ *
+ * reducer_opand<int> w;
+ * *w &= a; // *w returns the wrapper
+ * // operator &= is a wrapper member function that
+ * // calls the corresponding view function
+ */
+ //@{
+ reducer_opxor& operator*() { return *this; }
+ reducer_opxor const& operator*() const { return *this; }
+
+ reducer_opxor* operator->() { return this; }
+ reducer_opxor const* operator->() const { return this; }
+ //@}
+
+ /** @name Upcast
+ * @details In Cilk library 0.9, reducers were always cache-aligned. In
+ * library 1.0, reducer cache alignment is optional. By default, reducers
+ * are unaligned (i.e., just naturally aligned), but legacy wrappers
+ * inherit from cache-aligned reducers for binary compatibility.
+ *
+ * This means that a wrapper will automatically be upcast to its aligned
+ * reducer base class. The following conversion operators provide
+ * pseudo-upcasts to the corresponding unaligned reducer class.
+ */
+ //@{
+ operator reducer< op_xor<Type, false> >& ()
+ {
+ return *reinterpret_cast< reducer< op_xor<Type, false> >* >(this);
+ }
+ operator const reducer< op_xor<Type, false> >& () const
+ {
+ return *reinterpret_cast< const reducer< op_xor<Type, false> >* >(this);
+ }
+ //@}
+
+};
+
+/// @cond internal
+/** Metafunction specialization for reducer conversion.
+ *
+ * This specialization of the @ref legacy_reducer_downcast template class
+ * defined in reducer.h causes the `reducer< op_xor<Type> >` class to have an
+ * `operator reducer_opxor<Type>& ()` conversion operator that statically
+ * downcasts the `reducer<op_xor>` to the corresponding `reducer_opxor` type.
+ * (The reverse conversion, from `reducer_opxor` to `reducer<op_xor>`, is just
+ * an upcast, which is provided for free by the language.)
+ *
+ * @ingroup ReducersXor
+ */
+template <typename Type, bool Align>
+struct legacy_reducer_downcast<reducer<op_xor<Type, Align> > >
+{
+ typedef reducer_opxor<Type> type;
+};
+/// @endcond
+
+} // namespace cilk
+
+#endif /* __cplusplus */
+
+
+/** @ingroup ReducersXor
+ */
+//@{
+
+/** @name C language reducer macros
+ *
+ * These macros are used to declare and work with op_xor reducers in C code.
+ *
+ * @see @ref page_reducers_in_c
+ */
+ //@{
+
+__CILKRTS_BEGIN_EXTERN_C
+
+/** Opxor reducer type name.
+ *
+ * This macro expands into the identifier which is the name of the op_xor
+ * reducer type for a specified numeric type.
+ *
+ * @param tn The @ref reducers_c_type_names "numeric type name" specifying
+ * the type of the reducer.
+ *
+ * @see @ref reducers_c_predefined
+ * @see ReducersXor
+ */
+#define CILK_C_REDUCER_OPXOR_TYPE(tn) \
+ __CILKRTS_MKIDENT(cilk_c_reducer_opxor_,tn)
+
+/** Declare an op_xor reducer object.
+ *
+ * This macro expands into a declaration of an op_xor reducer object for a
+ * specified numeric type. For example:
+ *
+ * CILK_C_REDUCER_OPXOR(my_reducer, ulong, 0);
+ *
+ * @param obj The variable name to be used for the declared reducer object.
+ * @param tn The @ref reducers_c_type_names "numeric type name" specifying
+ * the type of the reducer.
+ * @param v The initial value for the reducer. (A value which can be
+ * assigned to the numeric type represented by @a tn.)
+ *
+ * @see @ref reducers_c_predefined
+ * @see ReducersXor
+ */
+#define CILK_C_REDUCER_OPXOR(obj,tn,v) \
+ CILK_C_REDUCER_OPXOR_TYPE(tn) obj = \
+ CILK_C_INIT_REDUCER(_Typeof(obj.value), \
+ __CILKRTS_MKIDENT(cilk_c_reducer_opxor_reduce_,tn), \
+ __CILKRTS_MKIDENT(cilk_c_reducer_opxor_identity_,tn), \
+ __cilkrts_hyperobject_noop_destroy, v)
+
+/// @cond internal
+
+/** Declare the op_xor reducer functions for a numeric type.
+ *
+ * This macro expands into external function declarations for functions which
+ * implement the reducer functionality for the op_xor reducer type for a
+ * specified numeric type.
+ *
+ * @param t The value type of the reducer.
+ * @param tn The value “type name†identifier, used to construct the reducer
+ * type name, function names, etc.
+ */
+#define CILK_C_REDUCER_OPXOR_DECLARATION(t,tn) \
+ typedef CILK_C_DECLARE_REDUCER(t) CILK_C_REDUCER_OPXOR_TYPE(tn); \
+ __CILKRTS_DECLARE_REDUCER_REDUCE(cilk_c_reducer_opxor,tn,l,r); \
+ __CILKRTS_DECLARE_REDUCER_IDENTITY(cilk_c_reducer_opxor,tn);
+
+/** Define the op_xor reducer functions for a numeric type.
+ *
+ * This macro expands into function definitions for functions which implement
+ * the reducer functionality for the op_xor reducer type for a specified
+ * numeric type.
+ *
+ * @param t The value type of the reducer.
+ * @param tn The value “type name†identifier, used to construct the reducer
+ * type name, function names, etc.
+ */
+#define CILK_C_REDUCER_OPXOR_DEFINITION(t,tn) \
+ typedef CILK_C_DECLARE_REDUCER(t) CILK_C_REDUCER_OPXOR_TYPE(tn); \
+ __CILKRTS_DECLARE_REDUCER_REDUCE(cilk_c_reducer_opxor,tn,l,r) \
+ { *(t*)l ^= *(t*)r; } \
+ __CILKRTS_DECLARE_REDUCER_IDENTITY(cilk_c_reducer_opxor,tn) \
+ { *(t*)v = 0; }
+
+//@{
+/** @def CILK_C_REDUCER_OPXOR_INSTANCE
+ * @brief Declare or define implementation functions for a reducer type.
+ *
+ * In the runtime source file c_reducers.c, the macro `CILK_C_DEFINE_REDUCERS`
+ * will be defined, and this macro will generate reducer implementation
+ * functions. Everywhere else, `CILK_C_DEFINE_REDUCERS` will be undefined, and
+ * this macro will expand into external declarations for the functions.
+ */
+#ifdef CILK_C_DEFINE_REDUCERS
+# define CILK_C_REDUCER_OPXOR_INSTANCE(t,tn) \
+ CILK_C_REDUCER_OPXOR_DEFINITION(t,tn)
+#else
+# define CILK_C_REDUCER_OPXOR_INSTANCE(t,tn) \
+ CILK_C_REDUCER_OPXOR_DECLARATION(t,tn)
+#endif
+//@}
+
+/* Declare or define an instance of the reducer type and its functions for each
+ * numeric type.
+ */
+CILK_C_REDUCER_OPXOR_INSTANCE(char, char)
+CILK_C_REDUCER_OPXOR_INSTANCE(unsigned char, uchar)
+CILK_C_REDUCER_OPXOR_INSTANCE(signed char, schar)
+CILK_C_REDUCER_OPXOR_INSTANCE(wchar_t, wchar_t)
+CILK_C_REDUCER_OPXOR_INSTANCE(short, short)
+CILK_C_REDUCER_OPXOR_INSTANCE(unsigned short, ushort)
+CILK_C_REDUCER_OPXOR_INSTANCE(int, int)
+CILK_C_REDUCER_OPXOR_INSTANCE(unsigned int, uint)
+CILK_C_REDUCER_OPXOR_INSTANCE(unsigned int, unsigned) /* alternate name */
+CILK_C_REDUCER_OPXOR_INSTANCE(long, long)
+CILK_C_REDUCER_OPXOR_INSTANCE(unsigned long, ulong)
+CILK_C_REDUCER_OPXOR_INSTANCE(long long, longlong)
+CILK_C_REDUCER_OPXOR_INSTANCE(unsigned long long, ulonglong)
+
+//@endcond
+
+__CILKRTS_END_EXTERN_C
+
+//@}
+
+//@}
+
+#endif /* REDUCER_OPXOR_H_INCLUDED */
diff --git a/libcilkrts/include/cilk/reducer_ostream.h b/libcilkrts/include/cilk/reducer_ostream.h
new file mode 100644
index 00000000000..d9addeee89f
--- /dev/null
+++ b/libcilkrts/include/cilk/reducer_ostream.h
@@ -0,0 +1,293 @@
+/*
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+ * reducer_ostream.h
+ *
+ * Purpose: Hyper-object to write to 'std::ostream's
+ *
+ * Classes: reducer_ostream
+ *
+ * Description:
+ * ============
+ * Output streams ('std::ostream's) are a convenient means of writing text to
+ * files, the user console, or sockets. In a serial program, text is written
+ * to an ostream in a specific, logical order. For example, computing while
+ * traversing a data structure and printing them to an 'ostream' will result
+ * in the values being printed in the order of traversal. In a parallel
+ * version of the same program, however, different parts of the data structure
+ * may be traversed in a different order, resulting in a non-deterministic
+ * ordering of the stream. Worse, multiple strands may write to the same
+ * stream simultaneously, resulting in a data race. Replacing the
+ * 'std::ostream' with a 'cilk::reducer_ostream' will solve both problems: Data
+ * will appeaer in the stream in the same order as it would for the serial
+ * program, and there will be no races (no locks) on the common stream.
+ *
+ * Usage Example:
+ * ==============
+ * Assume we wish to traverse an array of objects, performing an operation on
+ * each object and writing the result to a file. Without a reducer_ostream,
+ * we have a race on the 'output' file stream:
+ *..
+ * void compute(std::ostream& os, double x)
+ * {
+ * // Perform some significant computation and print the result:
+ * os << std::asin(x);
+ * }
+ *
+ * int test()
+ * {
+ * const std::size_t ARRAY_SIZE = 1000000;
+ * extern double myArray[ARRAY_SIZE];
+ *
+ * std::ofstream output("output.txt");
+ * cilk_for (std::size_t i = 0; i < ARRAY_SIZE; ++i)
+ * {
+ * compute(output, myArray[i]);
+ * }
+ *
+ * return 0;
+ * }
+ *..
+ * The race is solved by using a reducer_ostream to proxy the 'output' file:
+ *..
+ * void compute(cilk::reducer_ostream& os, double x)
+ * {
+ * // Perform some significant computation and print the result:
+ * *os << std::asin(x);
+ * }
+ *
+ * int test()
+ * {
+ * const std::size_t ARRAY_SIZE = 1000000;
+ * extern double myArray[ARRAY_SIZE];
+ *
+ * std::ofstream output("output.txt");
+ * cilk::reducer_ostream hyper_output(output);
+ * cilk_for (std::size_t i = 0; i < ARRAY_SIZE; ++i)
+ * {
+ * compute(hyper_output, myArray[i]);
+ * }
+ *
+ * return 0;
+ * }
+ *..
+ *
+ * Limitations:
+ * ============
+ * There are two possible values for the formatting flags immediately after a
+ * 'cilk_spawn' statement: they may either have the value that was set by the
+ * spawn function, or they may have default values. Because of
+ * non-determinism in the processor scheduling, there is no way to determine
+ * which it will be. Similarly, the formatting flags after a 'cilk_sync' may
+ * or may not have the same value as before the sync. Therefore, one must use
+ * a disciplined coding style to avoid formatting errors. There are two
+ * approaches to mitigating the problem: The first is to eliminate the
+ * difference between the two possible outcomes by ensuring that the spawned
+ * function always returns the flags to their initial state:
+ *..
+ * void compute(cilk::reducer_ostream& os, double x)
+ * {
+ * // Perform some significant computation and print the result:
+ * int saveprec = os.precision(5);
+ * os << std::asin(x);
+ * os.precision(saveprec);
+ * }
+ *..
+ * The second approach is to write your streaming operations such that they
+ * don't depend on the previous state of the formatting flags by setting any
+ * important flags before every block of output:
+ *..
+ * cilk_spawn compute(hyper_output, value);
+ *
+ * hyper_output->precision(2); // Don't depend on previous precision
+ * *hyper_output << f();
+ * *hyper_output << g();
+ *..
+ * Another concern is memory usage. A reducer_ostream will buffer as much text
+ * as necessary to ensure that the order of output matches that of the serial
+ * version of the program. If all spawn branches perform an equal amount of
+ * output, then one can expect that half of the output before a sync will be
+ * buffered in memory. This hyperobject is therefore not well suited for
+ * serializing very large quantities of text output.
+ */
+
+#ifndef REDUCER_OSTREAM_H_INCLUDED
+#define REDUCER_OSTREAM_H_INCLUDED
+
+#include <cilk/reducer.h>
+#include <iostream>
+#include <sstream>
+
+namespace cilk {
+
+/**
+ * @brief Class 'reducer_ostream' is the representation of a hyperobject for
+ * output text streaming.
+ */
+class reducer_ostream
+{
+public:
+ /// Internal representation of the per-strand view of the data for reducer_ostream
+ class View: public std::ostream
+ {
+ public:
+ /// Type of the std::stream reducer_ostream is based on
+ typedef std::ostream Base;
+
+ friend class reducer_ostream;
+
+ View():
+ std::ostream(0)
+ {
+ Base::rdbuf(&strbuf_);
+ };
+
+ private:
+ void use_ostream (const std::ostream &os)
+ {
+ Base::rdbuf(os.rdbuf());
+ Base::flags(os.flags()); // Copy formatting flags
+ Base::setstate(os.rdstate()); // Copy error state
+ }
+
+ private:
+ std::stringbuf strbuf_;
+ };
+
+public:
+ /// Definition of data view, operation, and identity for reducer_ostream
+ struct Monoid: monoid_base< View >
+ {
+ static void reduce (View *left, View *right);
+ };
+
+private:
+ // Hyperobject to serve up views
+ reducer<Monoid> imp_;
+
+ // Methods that provide the API for the reducer
+public:
+
+ // Construct an initial 'reducer_ostream' from an 'std::ostream'. The
+ // specified 'os' stream is used as the eventual destination for all
+ // text streamed to this hyperobject.
+ explicit reducer_ostream(const std::ostream &os);
+
+ // Return a modifiable reference to the underlying 'ostream' object.
+ std::ostream& get_reference();
+
+ /**
+ * Append data from some type to the reducer_ostream
+ *
+ * @param v Value to be appended to the reducer_ostream
+ */
+ template<typename T>
+ std::ostream &
+ operator<< (const T &v)
+ {
+ return imp_.view() << v;
+ }
+
+ /**
+ * Append data from a std::ostream to the reducer_ostream
+ *
+ * @param _Pfn std::ostream to copy from
+ */
+ std::ostream &
+ operator<< (std::ostream &(*_Pfn)(std::ostream &))
+ {
+ View &v = imp_.view();
+
+ return ((*_Pfn)(v));
+ }
+
+ reducer_ostream& operator*() { return *this; }
+ reducer_ostream const& operator*() const { return *this; }
+
+ reducer_ostream* operator->() { return this; }
+ reducer_ostream const* operator->() const { return this; }
+};
+
+
+// -------------------------------------------
+// class reducer_ostream::Monoid
+// -------------------------------------------
+
+/**
+ * Appends string from "right" reducer_basic_string onto the end of
+ * the "left". When done, the "right" reducer_basic_string is empty.
+ */
+void
+reducer_ostream::Monoid::reduce(View *left, View *right)
+{
+ left->operator<< (&right->strbuf_);
+}
+
+// --------------------------
+// class reducer_ostream
+// --------------------------
+
+/**
+ * Construct a reducer_ostream which will write to the specified std::ostream
+ *
+ * @param os std::ostream to write to
+ */
+inline
+reducer_ostream::reducer_ostream(const std::ostream &os) :
+ imp_()
+{
+ View &v = imp_.view();
+
+ v.use_ostream(os);
+}
+
+/**
+ * Get a reference to the std::ostream
+ */
+inline
+std::ostream &
+reducer_ostream::get_reference()
+{
+ View &v = imp_.view();
+
+ return v;
+}
+
+} // namespace cilk
+
+#endif // REDUCER_OSTREAM_H_INCLUDED
+
diff --git a/libcilkrts/include/cilk/reducer_string.h b/libcilkrts/include/cilk/reducer_string.h
new file mode 100644
index 00000000000..0d70dd8b30a
--- /dev/null
+++ b/libcilkrts/include/cilk/reducer_string.h
@@ -0,0 +1,729 @@
+/* reducer_string.h -*- C++ -*-
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file reducer_string.h
+ *
+ * @brief Defines classes for doing parallel string creation by appending.
+ *
+ * @ingroup ReducersString
+ *
+ * @see ReducersString
+ */
+
+#ifndef REDUCER_STRING_H_INCLUDED
+#define REDUCER_STRING_H_INCLUDED
+
+#include <cilk/reducer.h>
+#include <string>
+#include <list>
+
+/** @defgroup ReducersString String Reducers
+ *
+ * String reducers allow the creation of a string by concatenating a set of
+ * strings or characters in parallel.
+ *
+ * @ingroup Reducers
+ *
+ * You should be familiar with @ref pagereducers "Cilk reducers", described in
+ * file reducers.md, and particularly with @ref reducers_using, before trying
+ * to use the information in this file.
+ *
+ * @section redstring_usage Usage Example
+ *
+ * vector<Data> data;
+ * void expensive_string_computation(const Data& x, string& s);
+ * cilk::reducer<cilk::op_string> r;
+ * cilk_for (int i = 0; i != data.size(); ++i) {
+ * string temp;
+ * expensive_string_computation(data[i], temp);
+ * *r += temp;
+ * }
+ * string result;
+ * r.move_out(result);
+ *
+ * @section redstring_monoid The Monoid
+ *
+ * @subsection redstring_monoid_values Value Set
+ *
+ * The value set of a string reducer is the set of values of the class
+ * `std::basic_string<Char, Traits, Alloc>`, which we refer to as “the
+ * reducer’s string typeâ€.
+ *
+ * @subsection redstring_monoid_operator Operator
+ *
+ * The operator of a string reducer is the string concatenation operator,
+ * defined by the “`+`†binary operator on the reducer’s string type.
+ *
+ * @subsection redstring_monoid_identity Identity
+ *
+ * The identity value of a string reducer is the empty string, which is the
+ * value of the expression
+ * `std::basic_string<Char, Traits, Alloc>([allocator])`.
+ *
+ * @section redstring_operations Operations
+ *
+ * In the operation descriptions below, the type name `String` refers to the
+ * reducer’s string type, `std::basic_string<Char, Traits, Alloc>`.
+ *
+ * @subsection redstring_constructors Constructors
+ *
+ * Any argument list which is valid for a `std::basic_string` constructor is
+ * valid for a string reducer constructor. The usual move-in constructor is
+ * also provided:
+ *
+ * reducer(move_in(String& variable))
+ *
+ * @subsection redstring_get_set Set and Get
+ *
+ * r.set_value(const String& value)
+ * const String& = r.get_value() const
+ * r.move_in(String& variable)
+ * r.move_out(String& variable)
+ *
+ * @subsection redstring_initial Initial Values
+ *
+ * A string reducer with no constructor arguments, or with only an allocator
+ * argument, will initially contain the identity value, an empty string.
+ *
+ * @subsection redstring_view_ops View Operations
+ *
+ * *r += a
+ * r->append(a)
+ * r->append(a, b)
+ * r->push_back(a)
+ *
+ * These operations on string reducer views are the same as the corresponding
+ * operations on strings.
+ *
+ * @section redstring_performance Performance Considerations
+ *
+ * String reducers work by creating a string for each view, collecting those
+ * strings in a list, and then concatenating them into a single result string
+ * at the end of the computation. This last step takes place in serial code,
+ * and necessarily takes time proportional to the length of the result string.
+ * Thus, a parallel string reducer cannot actually speed up the time spent
+ * directly creating the string. This trivial example would probably be slower
+ * (because of reducer overhead) than the corresponding serial code:
+ *
+ * vector<string> a;
+ * reducer<op_string> r;
+ * cilk_for (int i = 0; i != a.length(); ++i) {
+ * *r += a[i];
+ * }
+ * string result;
+ * r.move_out(result);
+ *
+ * What a string reducer _can_ do is to allow the _remainder_ of the
+ * computation to be done in parallel, without having to worry about managing
+ * the string computation.
+ *
+ * The strings for new views are created (by the view identity constructor)
+ * using the same allocator as the string that was created when the reducer
+ * was constructed. Note that this allocator is determined when the reducer is
+ * constructed. The following two examples may have very different behavior:
+ *
+ * string<Char, Traits, Allocator> a_string;
+ *
+ * reducer< op_string<Char, Traits, Allocator> reducer1(move_in(a_string));
+ * ... parallel computation ...
+ * reducer1.move_out(a_string);
+ *
+ * reducer< op_string<Char, Traits, Allocator> reducer2;
+ * reducer2.move_in(a_string);
+ * ... parallel computation ...
+ * reducer2.move_out(a_string);
+ *
+ * * `reducer1` will be constructed with the same allocator as `a_string`,
+ * because the string was specified in the constructor. The `move_in`
+ * and `move_out` can therefore be done with a `swap` in constant time.
+ * * `reducer2` will be constructed with a _default_ allocator of type
+ * `Allocator`, which may not be the same as the allocator of `a_string`.
+ * Therefore, the `move_in` and `move_out` may have to be done with a copy
+ * in _O(N)_ time.
+ *
+ * (All instances of an allocator type with no internal state (like
+ * `std::allocator`) are “the sameâ€. You only need to worry about the “same
+ * allocator†issue when you create string reducers with custom allocator
+ * types.)
+ *
+ * @section redstring_types Type and Operator Requirements
+ *
+ * `std::basic_string<Char, Traits, Alloc>` must be a valid type.
+*/
+
+namespace cilk {
+
+/** @ingroup ReducersString */
+//@{
+
+/** The string append reducer view class.
+ *
+ * This is the view class for reducers created with
+ * `cilk::reducer< cilk::op_basic_string<Type, Traits, Allocator> >`. It holds
+ * the accumulator variable for the reduction, and allows only append
+ * operations to be performed on it.
+ *
+ * @note The reducer “dereference†operation (`reducer::operator *()`)
+ * yields a reference to the view. Thus, for example, the view class’s
+ * `append` operation would be used in an expression like
+ * `r->append(a)`, where `r` is a string append reducer variable.
+ *
+ * @tparam Char The string element type (not the string type).
+ * @tparam Traits The character traits type.
+ * @tparam Alloc The string allocator type.
+ *
+ * @see ReducersString
+ * @see op_basic_string
+ */
+template<typename Char, typename Traits, typename Alloc>
+class op_basic_string_view
+{
+ typedef std::basic_string<Char, Traits, Alloc> string_type;
+ typedef std::list<string_type> list_type;
+ typedef typename string_type::size_type size_type;
+
+ // The view's value is represented by a list of strings and a single
+ // string. The value is the concatenation of the strings in the list with
+ // the single string at the end. All string operations apply to the single
+ // string; reduce operations cause lists of partial strings from multiple
+ // strands to be combined.
+ //
+ mutable string_type m_string;
+ mutable list_type m_list;
+
+ // Before returning the value of the reducer, concatenate all the strings
+ // in the list with the single string.
+ //
+ void flatten() const
+ {
+ if (m_list.empty()) return;
+
+ typename list_type::iterator i;
+
+ size_type len = m_string.size();
+ for (i = m_list.begin(); i != m_list.end(); ++i)
+ len += i->size();
+
+ string_type result(get_allocator());
+ result.reserve(len);
+
+ for (i = m_list.begin(); i != m_list.end(); ++i)
+ result += *i;
+ m_list.clear();
+
+ result += m_string;
+ result.swap(m_string);
+ }
+
+public:
+
+ /** @name Monoid support.
+ */
+ //@{
+
+ /// Required by @ref monoid_with_view
+ typedef string_type value_type;
+
+ /// Required by @ref op_string
+ Alloc get_allocator() const
+ {
+ return m_string.get_allocator();
+ }
+
+ /** Reduction operation.
+ *
+ * This function is invoked by the @ref op_basic_string monoid to combine
+ * the views of two strands when the right strand merges with the left
+ * one. It appends the value contained in the right-strand view to the
+ * value contained in the left-strand view, and leaves the value in the
+ * right-strand view undefined.
+ *
+ * @param right A pointer to the right-strand view. (`this` points to
+ * the left-strand view.)
+ *
+ * @note Used only by the @ref op_basic_string monoid to implement the
+ * monoid reduce operation.
+ */
+ void reduce(op_basic_string_view* right)
+ {
+ if (!right->m_string.empty() || !right->m_list.empty()) {
+ // (list, string) + (right_list, right_string) =>
+ // (list + {string} + right_list, right_string)
+ if (!m_string.empty()) {
+ // simulate m_list.push_back(std::move(m_string))
+ m_list.push_back(string_type(get_allocator()));
+ m_list.back().swap(m_string);
+ }
+ m_list.splice(m_list.end(), right->m_list);
+ m_string.swap(right->m_string);
+ }
+ }
+
+ //@}
+
+ /** @name Pass constructor arguments through to the string constructor.
+ */
+ //@{
+
+ op_basic_string_view() : m_string() {}
+
+ template <typename T1>
+ op_basic_string_view(const T1& x1) : m_string(x1) {}
+
+ template <typename T1, typename T2>
+ op_basic_string_view(const T1& x1, const T2& x2) : m_string(x1, x2) {}
+
+ template <typename T1, typename T2, typename T3>
+ op_basic_string_view(const T1& x1, const T2& x2, const T3& x3) : m_string(x1, x2, x3) {}
+
+ template <typename T1, typename T2, typename T3, typename T4>
+ op_basic_string_view(const T1& x1, const T2& x2, const T3& x3, const T4& x4) :
+ m_string(x1, x2, x3, x4) {}
+
+ //@}
+
+ /** Move-in constructor.
+ */
+ explicit op_basic_string_view(move_in_wrapper<value_type> w)
+ : m_string(w.value().get_allocator())
+ {
+ m_string.swap(w.value());
+ }
+
+ /** @name @ref reducer support.
+ */
+ //@{
+
+ void view_move_in(string_type& s)
+ {
+ m_list.clear();
+ if (m_string.get_allocator() == s.get_allocator())
+ // Equal allocators. Do a (fast) swap.
+ m_string.swap(s);
+ else
+ // Unequal allocators. Do a (slow) copy.
+ m_string = s;
+ s.clear();
+ }
+
+ void view_move_out(string_type& s)
+ {
+ flatten();
+ if (m_string.get_allocator() == s.get_allocator())
+ // Equal allocators. Do a (fast) swap.
+ m_string.swap(s);
+ else
+ // Unequal allocators. Do a (slow) copy.
+ s = m_string;
+ m_string.clear();
+ }
+
+ void view_set_value(const string_type& s)
+ { m_list.clear(); m_string = s; }
+
+ string_type const& view_get_value() const
+ { flatten(); return m_string; }
+
+ string_type & view_get_reference()
+ { flatten(); return m_string; }
+
+ string_type const& view_get_reference() const
+ { flatten(); return m_string; }
+
+ //@}
+
+ /** @name View modifier operations.
+ *
+ * @details These simply wrap the corresponding operations on the underlying string.
+ */
+ //@{
+
+ template <typename T>
+ op_basic_string_view& operator +=(const T& x)
+ { m_string += x; return *this; }
+
+ template <typename T1>
+ op_basic_string_view& append(const T1& x1)
+ { m_string.append(x1); return *this; }
+
+ template <typename T1, typename T2>
+ op_basic_string_view& append(const T1& x1, const T2& x2)
+ { m_string.append(x1, x2); return *this; }
+
+ template <typename T1, typename T2, typename T3>
+ op_basic_string_view& append(const T1& x1, const T2& x2, const T3& x3)
+ { m_string.append(x1, x2, x3); return *this; }
+
+ void push_back(const Char x) { m_string.push_back(x); }
+
+ //@}
+};
+
+
+/** String append monoid class. Instantiate the cilk::reducer template class
+ * with an op_basic_string monoid to create a string append reducer class. For
+ * example, to concatenate a collection of standard strings:
+ *
+ * cilk::reducer< cilk::op_basic_string<char> > r;
+ *
+ * @tparam Char The string element type (not the string type).
+ * @tparam Traits The character traits type.
+ * @tparam Alloc The string allocator type.
+ * @tparam Align If `false` (the default), reducers instantiated on this
+ * monoid will be naturally aligned (the Cilk library 1.0
+ * behavior). If `true`, reducers instantiated on this monoid
+ * will be cache-aligned for binary compatibility with
+ * reducers in Cilk library version 0.9.
+ *
+ * @see ReducersString
+ * @see op_basic_string_view
+ * @see reducer_basic_string
+ * @see op_string
+ * @see op_wstring
+ */
+template<typename Char,
+ typename Traits = std::char_traits<Char>,
+ typename Alloc = std::allocator<Char>,
+ bool Align = false>
+class op_basic_string :
+ public monoid_with_view< op_basic_string_view<Char, Traits, Alloc>, Align >
+{
+ typedef monoid_with_view< op_basic_string_view<Char, Traits, Alloc>, Align >
+ base;
+ Alloc m_allocator;
+
+public:
+
+ /** View type of the monoid.
+ */
+ typedef typename base::view_type view_type;
+
+ /** Constructor.
+ *
+ * There is no default constructor for string monoids, because the
+ * allocator must always be specified.
+ *
+ * @param allocator The list allocator to be used when
+ * identity-constructing new views.
+ */
+ op_basic_string(const Alloc& allocator = Alloc()) : m_allocator(allocator)
+ {}
+
+ /** Create an identity view.
+ *
+ * String view identity constructors take the string allocator as an
+ * argument.
+ *
+ * @param v The address of the uninitialized memory in which the view
+ * will be constructed.
+ */
+ void identity(view_type *v) const { ::new((void*) v) view_type(m_allocator); }
+
+ /** @name Construct functions
+ *
+ * A string append reduction monoid must have a copy of the allocator of
+ * the leftmost view’s string, so that it can use it in the `identity`
+ * operation. This, in turn, requires that string reduction monoids have a
+ * specialized `construct()` function.
+ *
+ * All string reducer monoid `construct()` functions first construct the
+ * leftmost view, using the arguments that were passed in from the reducer
+ * constructor. They then call the view’s `get_allocator()` function to
+ * get the string allocator from the string in the leftmost view, and pass
+ * that to the monoid constructor.
+ */
+ //@{
+
+ static void construct(op_basic_string* monoid, view_type* view)
+ { provisional( new ((void*)view) view_type() ).confirm_if(
+ new ((void*)monoid) op_basic_string(view->get_allocator()) ); }
+
+ template <typename T1>
+ static void construct(op_basic_string* monoid, view_type* view, const T1& x1)
+ { provisional( new ((void*)view) view_type(x1) ).confirm_if(
+ new ((void*)monoid) op_basic_string(view->get_allocator()) ); }
+
+ template <typename T1, typename T2>
+ static void construct(op_basic_string* monoid, view_type* view, const T1& x1, const T2& x2)
+ { provisional( new ((void*)view) view_type(x1, x2) ).confirm_if(
+ new ((void*)monoid) op_basic_string(view->get_allocator()) ); }
+
+ template <typename T1, typename T2, typename T3>
+ static void construct(op_basic_string* monoid, view_type* view, const T1& x1, const T2& x2,
+ const T3& x3)
+ { provisional( new ((void*)view) view_type(x1, x2, x3) ).confirm_if(
+ new ((void*)monoid) op_basic_string(view->get_allocator()) ); }
+
+ template <typename T1, typename T2, typename T3, typename T4>
+ static void construct(op_basic_string* monoid, view_type* view, const T1& x1, const T2& x2,
+ const T3& x3, const T4& x4)
+ { provisional( new ((void*)view) view_type(x1, x2, x3, x4) ).confirm_if(
+ new ((void*)monoid) op_basic_string(view->get_allocator()) ); }
+
+ //@}
+};
+
+
+/** Convenience typedef for 8-bit strings
+ */
+typedef op_basic_string<char> op_string;
+
+/** Convenience typedef for 16-bit strings
+ */
+typedef op_basic_string<wchar_t> op_wstring;
+
+
+/** Deprecated string append reducer class.
+ *
+ * reducer_basic_string is the same as @ref reducer<@ref op_basic_string>,
+ * except that reducer_basic_string is a proxy for the contained view, so that
+ * accumulator variable update operations can be applied directly to the
+ * reducer. For example, a value is appended to a `reducer<%op_basic_string>`
+ * with `r->push_back(a)`, but a value can be appended to a `%reducer_opand`
+ * with `r.push_back(a)`.
+ *
+ * @deprecated Users are strongly encouraged to use `reducer<monoid>`
+ * reducers rather than the old wrappers like reducer_basic_string.
+ * The `reducer<monoid>` reducers show the reducer/monoid/view
+ * architecture more clearly, are more consistent in their
+ * implementation, and present a simpler model for new
+ * user-implemented reducers.
+ *
+ * @note Implicit conversions are provided between `%reducer_basic_string`
+ * and `reducer<%op_basic_string>`. This allows incremental code
+ * conversion: old code that used `%reducer_basic_string` can pass a
+ * `%reducer_basic_string` to a converted function that now expects a
+ * pointer or reference to a `reducer<%op_basic_string>`, and vice
+ * versa.
+ *
+ * @tparam Char The string element type (not the string type).
+ * @tparam Traits The character traits type.
+ * @tparam Alloc The string allocator type.
+ *
+ * @see op_basic_string
+ * @see reducer
+ * @see ReducersString
+ */
+template<typename Char,
+ typename Traits = std::char_traits<Char>,
+ typename Alloc = std::allocator<Char> >
+class reducer_basic_string :
+ public reducer< op_basic_string<Char, Traits, Alloc, true> >
+{
+ typedef reducer< op_basic_string<Char, Traits, Alloc, true> > base;
+ using base::view;
+public:
+
+ /// The reducer’s string type.
+ typedef typename base::value_type string_type;
+
+ /// The reducer’s primitive component type.
+ typedef Char basic_value_type;
+
+ /// The string size type.
+ typedef typename string_type::size_type size_type;
+
+ /// The view type for the reducer.
+ typedef typename base::view_type View;
+
+ /// The monoid type for the reducer.
+ typedef typename base::monoid_type Monoid;
+
+
+ /** @name Constructors
+ */
+ //@{
+
+ /** @name Forward constructor calls to the base class.
+ *
+ * All basic_string constructor forms are supported.
+ */
+ //@{
+ reducer_basic_string() {}
+
+ template <typename T1>
+ reducer_basic_string(const T1& x1) :
+ base(x1) {}
+
+ template <typename T1, typename T2>
+ reducer_basic_string(const T1& x1, const T2& x2) :
+ base(x1, x2) {}
+
+ template <typename T1, typename T2, typename T3>
+ reducer_basic_string(const T1& x1, const T2& x2, const T3& x3) :
+ base(x1, x2, x3) {}
+
+ template <typename T1, typename T2, typename T3, typename T4>
+ reducer_basic_string(const T1& x1, const T2& x2, const T3& x3, const T4& x4) :
+ base(x1, x2, x3, x4) {}
+ //@}
+
+ /** Allow mutable access to the string within the current view.
+ *
+ * @warning If this method is called before the parallel calculation is
+ * complete, the string returned by this method will be a
+ * partial result.
+ *
+ * @returns A mutable reference to the string within the current view.
+ */
+ string_type &get_reference()
+ { return view().view_get_reference(); }
+
+ /** Allow read-only access to the string within the current view.
+ *
+ * @warning If this method is called before the parallel calculation is
+ * complete, the string returned by this method will be a
+ * partial result.
+ *
+ * @returns A const reference to the string within the current view.
+ */
+ string_type const &get_reference() const
+ { return view().view_get_reference(); }
+
+ /** @name Append to the string.
+ *
+ * These operations are simply forwarded to the view.
+ */
+ //@{
+ void append(const Char *ptr)
+ { view().append(ptr); }
+ void append(const Char *ptr, size_type count)
+ { view().append(ptr, count); }
+ void append(const string_type &str, size_type offset, size_type count)
+ { view().append(str, offset, count); }
+ void append(const string_type &str)
+ { view().append(str); }
+ void append(size_type count, Char ch)
+ { view().append(count, ch); }
+
+ // Append to the string
+ reducer_basic_string<Char, Traits, Alloc> &operator+=(Char ch)
+ { view() += ch; return *this; }
+ reducer_basic_string<Char, Traits, Alloc> &operator+=(const Char *ptr)
+ { view() += ptr; return *this; }
+ reducer_basic_string<Char, Traits, Alloc> &operator+=(const string_type &right)
+ { view() += right; return *this; }
+ //@}
+
+ /** @name Dereference
+ * @details Dereferencing a wrapper is a no-op. It simply returns the
+ * wrapper. Combined with the rule that the wrapper forwards view
+ * operations to its contained view, this means that view operations can
+ * be written the same way on reducers and wrappers, which is convenient
+ * for incrementally converting old code using wrappers to use reducers
+ * instead. That is:
+ *
+ * reducer<op_string> r;
+ * r->push_back(a); // r-> returns the view
+ * // push_back() is a view member function
+ *
+ * reducer_string w;
+ * w->push_back(a); // *w returns the wrapper
+ * // push_back() is a wrapper member function
+ * // that calls the corresponding view function
+ */
+ //@{
+ reducer_basic_string& operator*() { return *this; }
+ reducer_basic_string const& operator*() const { return *this; }
+
+ reducer_basic_string* operator->() { return this; }
+ reducer_basic_string const* operator->() const { return this; }
+ //@}
+
+ /** @name Upcast
+ * @details In Cilk library 0.9, reducers were always cache-aligned. In
+ * library 1.0, reducer cache alignment is optional. By default, reducers
+ * are unaligned (i.e., just naturally aligned), but legacy wrappers
+ * inherit from cache-aligned reducers for binary compatibility.
+ *
+ * This means that a wrapper will automatically be upcast to its aligned
+ * reducer base class. The following conversion operators provide
+ * pseudo-upcasts to the corresponding unaligned reducer class.
+ */
+ //@{
+ operator reducer< op_basic_string<Char, Traits, Alloc, false> >& ()
+ {
+ return *reinterpret_cast< reducer<
+ op_basic_string<Char, Traits, Alloc, false> >*
+ >(this);
+ }
+ operator const reducer< op_basic_string<Char, Traits, Alloc, false> >& () const
+ {
+ return *reinterpret_cast< const reducer<
+ op_basic_string<Char, Traits, Alloc, false> >*
+ >(this);
+ }
+ //@}
+};
+
+
+/** Convenience typedef for 8-bit strings
+ */
+typedef reducer_basic_string<char> reducer_string;
+
+/** Convenience typedef for 16-bit strings
+ */
+typedef reducer_basic_string<wchar_t> reducer_wstring;
+
+/// @cond internal
+
+/// @cond internal
+/** Metafunction specialization for reducer conversion.
+ *
+ * This specialization of the @ref legacy_reducer_downcast template class
+ * defined in reducer.h causes the `reducer< op_basic_string<Char> >` class to
+ * have an `operator reducer_basic_string<Char>& ()` conversion operator that
+ * statically downcasts the `reducer<op_basic_string>` to the corresponding
+ * `reducer_basic_string` type. (The reverse conversion, from
+ * `reducer_basic_string` to `reducer<op_basic_string>`, is just an upcast,
+ * which is provided for free by the language.)
+ *
+ * @ingroup ReducersString
+ */
+template<typename Char, typename Traits, typename Alloc, bool Align>
+struct legacy_reducer_downcast<
+ reducer<op_basic_string<Char, Traits, Alloc, Align> > >
+{
+ typedef reducer_basic_string<Char, Traits, Alloc> type;
+};
+
+/// @endcond
+
+//@}
+
+} // namespace cilk
+
+#endif // REDUCER_STRING_H_INCLUDED
diff --git a/libcilkrts/include/cilktools/cilkscreen.h b/libcilkrts/include/cilktools/cilkscreen.h
new file mode 100644
index 00000000000..c6986ae7b08
--- /dev/null
+++ b/libcilkrts/include/cilktools/cilkscreen.h
@@ -0,0 +1,108 @@
+/* cilkscreen.h -*-C++-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2010-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ **************************************************************************/
+
+#ifndef INCLUDED_CILKSCREEN_H
+#define INCLUDED_CILKSCREEN_H
+
+#include <cilk/cilk_api.h>
+
+/*
+ * Cilkscreen "functions". These macros generate metadata in your application
+ * to notify Cilkscreen of program state changes
+ */
+
+#if ! defined(CILK_STUB) && defined(__INTEL_COMPILER)
+# define __cilkscreen_metacall(annotation,expr) \
+ __notify_zc_intrinsic((char *)annotation, expr)
+#else
+# define __cilkscreen_metacall(annotation,expr) ((void)annotation, (void)(expr))
+#endif
+
+/* Call once when a user thread enters a spawning function */
+#define __cilkscreen_enable_instrumentation() \
+ __cilkscreen_metacall("cilkscreen_enable_instrumentation", 0)
+
+/* Call once when a user thread exits a spawning function */
+#define __cilkscreen_disable_instrumentation() \
+ __cilkscreen_metacall("cilkscreen_disable_instrumentation", 0)
+
+/* Call to temporarily disable cilkscreen instrumentation */
+#define __cilkscreen_enable_checking() \
+ __cilkscreen_metacall("cilkscreen_enable_checking", 0)
+
+/* Call to re-enable temporarily-disabled cilkscreen instrumentation */
+#define __cilkscreen_disable_checking() \
+ __cilkscreen_metacall("cilkscreen_disable_checking", 0)
+
+/* Inform cilkscreen that memory from begin to end can be reused without
+ * causing races (e.g., for memory that comes from a memory allocator) */
+#define __cilkscreen_clean(begin, end) \
+ do { \
+ void *__data[2] = { (begin), (end) }; \
+ __cilkscreen_metacall("cilkscreen_clean", &__data); \
+ } while(0)
+
+/* Inform cilkscreen that a lock is being acquired.
+ * If the lock type is not a handle, then the caller should take its address
+ * and pass the pointer to the lock. Otherwise, the caller should pass the
+ * lock handle directly.
+ */
+#define __cilkscreen_acquire_lock(lock) \
+ __cilkscreen_metacall("cilkscreen_acquire_lock", (lock))
+
+#define __cilkscreen_release_lock(lock) \
+ __cilkscreen_metacall("cilkscreen_release_lock", (lock))
+
+/*
+ * Metacall data
+ *
+ * A metacall is a way to pass data to a function implemented by a tool.
+ * Metacalls are always instrumented when the tool is loaded.
+ */
+
+// Tool code for Cilkscreen
+#define METACALL_TOOL_CILKSCREEN 1
+
+// Metacall codes implemented by Cilkscreen
+#define CS_METACALL_PUTS 0 // Write string to the Cilkscreen log
+
+#define __cilkscreen_puts(text) \
+ __cilkrts_metacall(METACALL_TOOL_CILKSCREEN, CS_METACALL_PUTS, (void *)(const char *)text)
+
+#endif /* defined(INCLUDED_CILKSCREEN_H) */
diff --git a/libcilkrts/include/cilktools/cilkview.h b/libcilkrts/include/cilktools/cilkview.h
new file mode 100644
index 00000000000..eb7d9d8c0e4
--- /dev/null
+++ b/libcilkrts/include/cilktools/cilkview.h
@@ -0,0 +1,278 @@
+/* cilkview.h -*-C++-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2010-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ **************************************************************************/
+
+#ifndef INCLUDED_CILKVIEW_H
+#define INCLUDED_CILKVIEW_H
+
+#include <cilk/cilk_api.h>
+
+#ifdef _WIN32
+# ifndef _WINBASE_
+__CILKRTS_BEGIN_EXTERN_C
+unsigned long __stdcall GetTickCount();
+__CILKRTS_END_EXTERN_C
+# endif
+#endif // _WIN32
+
+#if defined __unix__ || defined __APPLE__ || defined __VXWORKS__
+# include <sys/time.h>
+#endif // defined __unix__ || defined __APPLE__
+
+/// @brief Return the system clock with millisecond resolution
+///
+/// This function returns a long integer representing the number of
+/// milliseconds since an arbitrary starting point, e.g., since the system was
+/// started or since the Unix Epoch. The result is meaningless by itself, but
+/// the difference between two sequential calls to __cilkview_getticks()
+/// represents the time interval that elapsed between them (in ms).
+static inline unsigned long long __cilkview_getticks()
+{
+#if __INTEL_COMPILER > 1200
+ // When inlined, prevent code motion around this call
+ __notify_zc_intrinsic((void*) "test_getticks_start", 0);
+#endif
+
+#ifdef _WIN32
+ // Return milliseconds elapsed since the system started
+ return GetTickCount();
+#elif defined(__unix__) || defined(__APPLE__) || defined __VXWORKS__
+ // Return milliseconds elapsed since the Unix Epoch
+ // (1-Jan-1970 00:00:00.000 UTC)
+ struct timeval t;
+ gettimeofday(&t, 0);
+ return t.tv_sec * 1000ULL + t.tv_usec / 1000;
+#else
+# error test_getticks() not implemented for this OS
+#endif
+
+#if __INTEL_COMPILER > 1200
+ // When inlined, prevent code motion around this call
+ __notify_zc_intrinsic((void*) "test_getticks_end", 0);
+#endif
+}
+
+typedef struct
+{
+ unsigned int size; // Size of structure in bytes
+ unsigned int status; // 1 = success, 0 = failure
+ unsigned long long time; // Time in milliseconds
+ unsigned long long work;
+ unsigned long long span;
+ unsigned long long burdened_span;
+ unsigned long long spawns;
+ unsigned long long syncs;
+ unsigned long long strands;
+ unsigned long long atomic_ins;
+ unsigned long long frames;
+} cilkview_data_t;
+
+typedef struct
+{
+ cilkview_data_t *start; // Values at start of interval
+ cilkview_data_t *end; // Values at end of interval
+ const char *label; // Name for this interval
+ unsigned int flags; // What to do - see flags below
+} cilkview_report_t;
+
+// What __cilkview_report should do. The flags can be ORed together
+enum
+{
+ CV_REPORT_WRITE_TO_LOG = 1, // Write parallelism report to the log (xml or text)
+ CV_REPORT_WRITE_TO_RESULTS = 2 // Write parallelism data to results file
+};
+
+#ifndef CILKVIEW_NO_REPORT
+static void __cilkview_do_report(cilkview_data_t *start,
+ cilkview_data_t *end,
+ const char *label,
+ unsigned int flags);
+#endif /* CILKVIEW_NO_REPORT */
+
+/*
+ * Metacall data
+ *
+ * A metacall is a way to pass data to a function implemented by a tool.
+ * Metacalls are always instrumented when the tool is loaded.
+ */
+
+// Tool code for Cilkview
+#define METACALL_TOOL_CILKVIEW 2
+
+// Metacall codes implemented by Cilkview
+enum
+{
+ CV_METACALL_PUTS,
+ CV_METACALL_QUERY,
+ CV_METACALL_START,
+ CV_METACALL_STOP,
+ CV_METACALL_RESET,
+ CV_METACALL_USE_DEFAULT_GRAIN,
+ CV_METACALL_CONNECTED,
+ CV_METACALL_SUSPEND,
+ CV_METACALL_RESUME,
+ CV_METACALL_REPORT
+};
+
+#if ! defined(CILK_STUB) && defined(__INTEL_COMPILER)
+# define __cilkview_metacall(code,data) \
+ __cilkrts_metacall(METACALL_TOOL_CILKVIEW, code, data)
+#else
+# define __cilkview_metacall(annotation,expr) (annotation, (void) (expr))
+#endif
+
+// Write arbitrary string to the log
+#define __cilkview_puts(arg) \
+ __cilkview_metacall(CV_METACALL_PUTS, arg)
+
+// Retrieve the Cilkview performance counters. The parameter must be a
+// cilkview_data_t
+#define __cilkview_query(d) \
+ do { \
+ d.size = sizeof(d); \
+ d.status = 0; \
+ __cilkview_metacall(CV_METACALL_QUERY, &d); \
+ if (0 == d.status) \
+ d.time = __cilkview_getticks(); \
+ } while (0)
+
+// Write report to log or results file. If end is NULL, Cilkview will
+// use the current values.
+#define __cilkview_report(start, end, label, flags) \
+ __cilkview_do_report(start, end, label, flags)
+
+// Control the workspan performance counters for the final report
+#define __cilkview_workspan_start() \
+ __cilkview_metacall(CV_METACALL_START, 0)
+#define __cilkview_workspan_stop() \
+ __cilkview_metacall(CV_METACALL_STOP, 0)
+#define __cilkview_workspan_reset() \
+ __cilkview_metacall(CV_METACALL_RESET, 0)
+#define __cilkview_workspan_suspend() \
+ __cilkview_metacall(CV_METACALL_SUSPEND, 0)
+#define __cilkview_workspan_resume() \
+ __cilkview_metacall(CV_METACALL_RESUME, 0)
+
+#define __cilkview_use_default_grain_size() \
+ __cilkview_metacall(CV_METACALL_USE_DEFAULT, 0)
+
+// Sets the int is_connected to 1 if Cilkview is active
+#define __cilkview_connected(is_connected) \
+ __cilkview_metacall(CV_METACALL_CONNECTED, &is_connected)
+
+
+#ifndef CILKVIEW_NO_REPORT
+
+// Stop Microsoft include files from complaining about getenv and fopen
+#define _CRT_SECURE_NO_WARNINGS
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#ifdef _WIN32
+#pragma warning(push)
+#pragma warning(disable: 1786) // Suppress warnings that getenv, fopen are deprecated
+#endif
+
+static void __cilkview_do_report(cilkview_data_t *start,
+ cilkview_data_t *end,
+ const char *label,
+ unsigned int flags)
+{
+ int under_cilkview = 0;
+ unsigned long long elapsed_ms;
+ int worker_count = 0;
+ char *nworkers;
+ char *outfile;
+ FILE *f;
+
+ // Check whether we're running under Cilkview
+ __cilkview_connected(under_cilkview);
+
+ // If we're running under Cilkview, let it do those things that need
+ // to be done
+ if (under_cilkview)
+ {
+ cilkview_report_t d = {start, end, label, flags};
+ __cilkview_metacall(CV_METACALL_REPORT, &d);
+ return;
+ }
+
+ // We're not running under Cilkview.
+ //
+ // If we weren't asked to write to the results file, we're done.
+ if (0 == (flags & CV_REPORT_WRITE_TO_RESULTS))
+ return;
+
+ // Calculate the elapse milliseconds
+ if (NULL == end)
+ elapsed_ms = __cilkview_getticks() - start->time;
+ else
+ elapsed_ms = end->time - start->time;
+
+ // Determine how many workers we're using for this trial run
+ nworkers = getenv("CILK_NWORKERS");
+ if (NULL != nworkers)
+ worker_count = atoi(nworkers);
+ if (0 == worker_count)
+ worker_count = 16;
+
+ // Open the output file and write the trial data to it
+ outfile = getenv("CILKVIEW_OUTFILE");
+ if (NULL == outfile)
+ outfile = (char *)"cilkview.out";
+
+ f = fopen(outfile, "a");
+ if (NULL == f)
+ fprintf(stderr, "__cilkview_do_report: unable to append to file %s\n", outfile);
+ else
+ {
+ fprintf(f, "%s trial %d %f\n", label,
+ worker_count,
+ ((float)elapsed_ms) / 1000.0f);
+ fclose(f);
+ }
+}
+#ifdef _WIN32
+#pragma warning(pop)
+#endif
+
+#endif // CILKVIEW_NO_REPORT
+
+
+#endif /* ! defined(INCLUDED_CILKVIEW_H) */
diff --git a/libcilkrts/include/cilktools/fake_mutex.h b/libcilkrts/include/cilktools/fake_mutex.h
new file mode 100644
index 00000000000..9ae0678112f
--- /dev/null
+++ b/libcilkrts/include/cilktools/fake_mutex.h
@@ -0,0 +1,92 @@
+/* fake_mutex.h -*-C++-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ **************************************************************************
+ *
+ * Cilkscreen fake mutexes are provided to indicate to the Cilkscreen race
+ * detector that a race should be ignored.
+ *
+ * NOTE: This class does not provide mutual exclusion. You should use the
+ * mutual exclusion constructs provided by TBB or your operating system to
+ * protect against real data races.
+ */
+
+#ifndef FAKE_MUTEX_H_INCLUDED
+#define FAKE_MUTEX_H_INCLUDED
+
+#include <cilktools/cilkscreen.h>
+
+namespace cilkscreen
+{
+ class fake_mutex
+ {
+ public:
+ fake_mutex() : locked(false)
+ {
+ }
+
+ ~fake_mutex()
+ {
+ __CILKRTS_ASSERT(! locked);
+ }
+
+ // Wait until mutex is available, then enter
+ void lock()
+ {
+ __cilkscreen_acquire_lock(&locked);
+ __CILKRTS_ASSERT(! locked);
+ locked = true;
+ }
+
+ // A fake mutex is always available
+ bool try_lock() { lock(); return true; }
+
+ // Releases the mutex
+ void unlock()
+ {
+ __CILKRTS_ASSERT(locked);
+ locked = false;
+ __cilkscreen_release_lock(&locked);
+ }
+
+ private:
+ bool locked;
+ };
+
+} // namespace cilk
+
+#endif // FAKE_MUTEX_H_INCLUDED
diff --git a/libcilkrts/include/cilktools/lock_guard.h b/libcilkrts/include/cilktools/lock_guard.h
new file mode 100644
index 00000000000..d513e2b9734
--- /dev/null
+++ b/libcilkrts/include/cilktools/lock_guard.h
@@ -0,0 +1,86 @@
+/* lock_guard.h -*-C++-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2011-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ **************************************************************************
+ *
+ * Lock guard patterned after the std::lock_guard class template proposed in
+ * the C++ 0x draft standard.
+ *
+ * An object of type lock_guard controls the ownership of a mutex object
+ * within a scope. A lock_guard object maintains ownership of a mutex object
+ * throughout the lock_guard object's lifetime. The behavior of a program is
+ * undefined if the mutex referenced by pm does not exist for the entire
+ * lifetime of the lock_guard object.
+ */
+
+#ifndef LOCK_GUARD_H_INCLUDED
+#define LOCK_GUARD_H_INCLUDED
+
+#include <cilk/cilk.h>
+
+namespace cilkscreen
+{
+ template <class Mutex>
+ class lock_guard
+ {
+ public:
+ typedef Mutex mutex_type;
+
+ explicit lock_guard(mutex_type &m) : pm(m)
+ {
+ pm.lock();
+ locked = true;
+ }
+
+ ~lock_guard()
+ {
+ locked = false;
+ pm.unlock();
+ }
+
+ private:
+ lock_guard(lock_guard const&);
+ lock_guard& operator=(lock_guard const&);
+
+ private:
+ // exposition only:
+ mutex_type &pm;
+ bool locked;
+ };
+}
+
+#endif // LOCK_GUARD_H_INCLUDED
diff --git a/libcilkrts/include/internal/abi.h b/libcilkrts/include/internal/abi.h
new file mode 100644
index 00000000000..f45b5bcb178
--- /dev/null
+++ b/libcilkrts/include/internal/abi.h
@@ -0,0 +1,639 @@
+/*
+ * abi.h
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************/
+
+/**
+ * @file abi.h
+ *
+ * @brief Defines the application binary interface between the compiler and
+ * the Intel Cilk Plus runtime.
+ */
+
+#ifndef CILK_INTERNAL_ABI_H
+#define CILK_INTERNAL_ABI_H
+
+
+#include <cilk/common.h>
+#include <stddef.h> // Needed to define size_t
+
+/**
+ * Jump buffers are OS and architecture dependent
+ */
+#if ! defined(_MSC_VER)
+/* Non-Windows - only need 5 registers for the jump buffer for both IA32 and Intel64 */
+typedef void *__CILK_JUMP_BUFFER[5];
+
+/** OS-specific implementation of setjmp */
+# define CILK_SETJMP(X) __builtin_setjmp(X)
+/** OS-specific implementation of longjmp */
+# define CILK_LONGJMP(X) __builtin_longjmp(X,1)
+#else
+/* Windows - things are a little more complicated */
+# if defined(_M_X64)
+/* Intel64 - Use an OS-defined jump buffer */
+# include <setjmp.h>
+typedef jmp_buf __CILK_JUMP_BUFFER;
+
+# define CILK_SETJMP(X) setjmp(X)
+# define CILK_LONGJMP(X) longjmp(X, 1)
+# elif defined(_M_IX86)
+/**
+ * Windows x86 - Use a simplified version of the Windows jump buffer for x86
+ * setjmp is provided by __cilkrts_setjmp which passes jump buffer in EAX and
+ * destination in EDX longjmp is provided by an internal routine which uses
+ * this structure
+ */
+typedef struct
+{
+ unsigned long Ebp;
+ unsigned long Ebx;
+ unsigned long Edi;
+ unsigned long Esi;
+ unsigned long Esp;
+ unsigned long Eip;
+ unsigned long Registration;
+ unsigned long TryLevel;
+} __CILK_JUMP_BUFFER;
+
+# else
+# error Unexpected architecture - Need to define __CILK_JUMP_BUFFER
+# endif /* _M_X64 */
+
+#endif /* defined(_MSC_VER) */
+
+/* struct tags */
+typedef struct __cilkrts_stack_frame __cilkrts_stack_frame; ///< struct tag for stack frame
+
+// Forwarded declarations
+typedef struct global_state_t global_state_t; ///< Forwarded declaration for global state
+typedef struct local_state local_state; ///< Forwarded declaration for local state
+typedef struct cilkred_map cilkred_map; ///< Forward declaration for reducer map
+
+/// Forwarded declaration for system-dependent worker state
+typedef struct __cilkrts_worker_sysdep_state
+ __cilkrts_worker_sysdep_state;
+
+/**
+ * The worker struct contains per-worker information that needs to be
+ * visible to the compiler, or rooted here.
+ *
+ * For 32-bit Windows we need to be aligning the structures on 4-byte
+ * boundaries to match where ICL is allocating the birthrank and rank
+ * in the __cilkrts_stack_frame. It's 4-byte aligned instead of 8-byte
+ * aligned. This is OK because the compiler is dealing with the 64-bit
+ * quantities as two 32-bit values. So change the packing to be on
+ * 4-byte boundaries.
+ *
+ * The fields of the worker struct can be classified as either local
+ * or shared.
+ *
+ * Local: This field is only accessed by the thread bound to this
+ * worker struct. Local fields can be freely accessed without
+ * acquiring locks.
+ *
+ * Shared: This field may be accessed by multiple worker threads.
+ * Accesses to shared fields usually requires locks, except in
+ * special situations where one can prove that locks are
+ * unnecessary.
+ *
+ * The fields of the worker struct can also be classified as
+ * "read-only" if the field does not change after it is initialized.
+ * Otherwise, the field is "read/write". Read-only fields do not
+ * require locks to access (ignoring the synchronization that might be
+ * needed for initialization if this can occur in parallel).
+ *
+ * Finally, we explicitly classify some fields as "synchronization"
+ * fields if they are used as part of a synchronization protocol in
+ * the runtime. These variables are generally shared and read/write.
+ * Mostly, this category includes lock variables and other variables
+ * that are involved in synchronization protocols (i.e., the THE
+ * protocol).
+ */
+#if defined(_MSC_VER) && defined(_M_IX86)
+#pragma pack(push, 4)
+#endif
+
+struct __cilkrts_worker {
+ /**
+ * T, H, and E pointers in the THE protocol See "The implementation of
+ * the Cilk-5 multithreaded language", PLDI 1998:
+ * http://portal.acm.org/citation.cfm?doid=277652.277725
+ *
+ * Synchronization fields. [shared read/write]
+ */
+ __cilkrts_stack_frame *volatile *volatile tail;
+ __cilkrts_stack_frame *volatile *volatile head; /**< @copydoc tail */
+ __cilkrts_stack_frame *volatile *volatile exc; /**< @copydoc tail */
+
+ /**
+ * Addition to the THE protocol to allow us to protect some set of
+ * entries in the tail queue from stealing. Normally, this is set
+ * beyond the end of the task queue, indicating that all entries are
+ * available for stealing. During exception handling, protected_tail
+ * may be set to the first entry in the task queue, indicating that
+ * stealing is not allowed.
+ *
+ * Synchronization field.
+ */
+ __cilkrts_stack_frame *volatile *volatile protected_tail;
+
+ /**
+ * Limit of the Lazy Task Queue, to detect queue overflow
+ * [local read-only]
+ */
+ __cilkrts_stack_frame *volatile *ltq_limit;
+
+ /**
+ * Worker id.
+ * [local read-only]
+ */
+ int32_t self;
+
+ /**
+ * Global state of the runtime system, opaque to the client.
+ * [local read-only]
+ */
+ global_state_t *g;
+
+ /**
+ * Additional per-worker state of the runtime system that we want
+ * to maintain hidden from the client.
+ * [shared read-only]
+ */
+ local_state *l;
+
+ /**
+ * Map from reducer names to reducer values.
+ * [local read/write]
+ */
+ cilkred_map *reducer_map;
+
+ /**
+ * A slot that points to the currently executing Cilk frame.
+ * [local read/write]
+ */
+ __cilkrts_stack_frame *current_stack_frame;
+
+ /**
+ * Reserved space for a pointer.
+ * Used to be __cilkrts_stack_frame *volatile *volatile saved_protected_tail;
+ */
+ void* reserved;
+
+ /**
+ * System-dependent part of the worker state
+ * [local read-only]
+ */
+ __cilkrts_worker_sysdep_state *sysdep;
+
+#if __CILKRTS_ABI_VERSION >= 1
+ /**
+ * Per-worker pedigree information used to support scheduling-independent
+ * pseudo-random numbers.
+ * [local read/write]
+ */
+ __cilkrts_pedigree pedigree;
+#endif /* __CILKRTS_ABI_VERSION >= 1 */
+};
+
+
+/**
+ * Every spawning function has a frame descriptor. A spawning function
+ * is a function that spawns or detaches. Only spawning functions
+ * are visible to the Cilk runtime.
+ */
+struct __cilkrts_stack_frame
+{
+ /**
+ * flags is an integer with values defined below. Client code
+ * initializes flags to CILK_FRAME_VERSION before the first Cilk
+ * operation.
+ *
+ * The low 24-bits of the 'flags' field are the flags, proper. The high
+ * 8-bits are the version number.
+ *
+ * IMPORTANT: bits in this word are set and read by the PARENT ONLY,
+ * not by a spawned child. In particular, the STOLEN and UNSYNCHED
+ * bits are set on a steal and are read before a sync. Since there
+ * is no synchronization (locking) on this word, any attempt to set
+ * or read these bits asynchronously in a child would result in a race.
+ */
+ uint32_t flags;
+
+ /** Not currently used. Not initialized by Intel compiler. */
+ int32_t size;
+
+ /**
+ * call_parent points to the __cilkrts_stack_frame of the closest
+ * ancestor spawning function, including spawn helpers, of this frame.
+ * It forms a linked list ending at the first stolen frame.
+ */
+ __cilkrts_stack_frame *call_parent;
+
+ /**
+ * The client copies the worker from TLS here when initializing
+ * the structure. The runtime ensures that the field always points
+ * to the __cilkrts_worker which currently "owns" the frame.
+ */
+ __cilkrts_worker *worker;
+
+ /**
+ * Unix: Pending exception after sync. The sync continuation
+ * must call __cilkrts_rethrow to handle the pending exception.
+ *
+ * Windows: the handler that _would_ have been registered if our
+ * handler were not there. We maintain this for unwinding purposes.
+ * Win32: the value of this field is only defined in spawn helper
+ * functions
+ *
+ * Win64: except_data must be filled in for all functions with a
+ * __cilkrts_stack_frame
+ */
+ void *except_data;
+
+ /**
+ * Before every spawn and nontrivial sync the client function
+ * saves its continuation here.
+ */
+ __CILK_JUMP_BUFFER ctx;
+
+#if __CILKRTS_ABI_VERSION >= 1
+ /**
+ * Architecture-specific floating point state. mxcsr and fpcsr should be
+ * set when CILK_SETJMP is called in client code. Note that the Win64
+ * jmpbuf for the Intel64 architecture already contains this information
+ * so there is no need to use these fields on that OS/architecture.
+ */
+ uint32_t mxcsr;
+ uint16_t fpcsr; /**< @copydoc mxcsr */
+
+
+ /**
+ * reserved is not used at this time. Client code should initialize it
+ * to 0 before the first Cilk operation
+ */
+ uint16_t reserved;
+
+ /**
+ * Pedigree information to support scheduling-independent pseudo-random
+ * numbers. There are two views of this information. The copy in a
+ * spawning function is used to stack the rank and communicate to the
+ * runtime on a steal or continuation. The copy in a spawn helper is
+ * immutable once the function is detached and is a node in the pedigree.
+ * The union is used to make clear which view we're using.
+ *
+ * In the detach sequence Client code should:
+ * - copy the worker pedigree into the spawn helper's pedigree
+ * - copy the worker pedigree into the call parent's pedigree
+ * - set the worker's rank to 0
+ * - set the worker's pedigree.next to the spawn helper's pedigree
+ */
+ union
+ {
+ __cilkrts_pedigree spawn_helper_pedigree; /* Used in spawn helpers */
+ __cilkrts_pedigree parent_pedigree; /* Used in spawning funcs */
+ };
+#endif /* __CILKRTS_ABI_VERSION >= 1 */
+};
+
+/*
+ * Restore previous structure packing for 32-bit Windows
+ */
+#if defined(_MSC_VER) && defined(_M_IX86)
+#pragma pack(pop)
+#endif
+
+/* Values of the flags bitfield */
+/** CILK_FRAME_STOLEN is set if the frame has ever been stolen. */
+#define CILK_FRAME_STOLEN 0x01
+
+/**
+ * CILK_FRAME_UNSYNCHED is set if the frame has been stolen and
+ * is has not yet executed _Cilk_sync. It is technically a misnomer in that a
+ * frame can have this flag set even if all children have returned.
+ */
+#define CILK_FRAME_UNSYNCHED 0x02
+
+/**
+ * Is this frame detached (spawned)? If so the runtime needs
+ * to undo-detach in the slow path epilogue.
+ */
+#define CILK_FRAME_DETACHED 0x04
+
+/**
+ * CILK_FRAME_EXCEPTION_PROBED is set if the frame has been probed in the
+ * exception handler first pass
+ */
+#define CILK_FRAME_EXCEPTION_PROBED 0x08
+
+/** Is this frame receiving an exception after sync? */
+#define CILK_FRAME_EXCEPTING 0x10
+
+/**
+ * Is the pedigree unsynched? That is, has a synch occurred that is not
+ * yet represented in the pedigree?
+ */
+#define CILK_FRAME_SF_PEDIGREE_UNSYNCHED 0x20
+
+/** Is this the last (oldest) Cilk frame? */
+#define CILK_FRAME_LAST 0x80
+
+/**
+ * Is this frame in the epilogue, or more generally after the last
+ * sync when it can no longer do any Cilk operations?
+ */
+#define CILK_FRAME_EXITING 0x0100
+
+/** Is this frame suspended? (used for debugging) */
+#define CILK_FRAME_SUSPENDED 0x8000
+
+/** Used by Windows exception handling to indicate that __cilkrts_leave_frame should do nothing */
+#define CILK_FRAME_UNWINDING 0x10000
+
+/*
+ * The low 24-bits of the 'flags' field are the flags, proper. The high 8-bits
+ * are the version number.
+ */
+
+/** ABI version left shifted to the high byte */
+#define CILK_FRAME_VERSION (__CILKRTS_ABI_VERSION << 24)
+
+/** Mask for the flags field to isolate the version bits */
+#define CILK_FRAME_VERSION_MASK 0xFF000000
+
+/** Mask for the flags field to isolate the flag bits */
+#define CILK_FRAME_FLAGS_MASK 0x00FFFFFF
+
+/** Convenience macro to provide access the version portion of the flags field */
+#define CILK_FRAME_VERSION_VALUE(_flags) (((_flags) & CILK_FRAME_VERSION_MASK) >> 24)
+
+/** Any undefined bits are reserved and must be zero ("MBZ" = "Must Be Zero") */
+#define CILK_FRAME_MBZ (~ (CILK_FRAME_STOLEN | \
+ CILK_FRAME_UNSYNCHED | \
+ CILK_FRAME_DETACHED | \
+ CILK_FRAME_EXCEPTION_PROBED | \
+ CILK_FRAME_EXCEPTING | \
+ CILK_FRAME_SF_PEDIGREE_UNSYNCHED | \
+ CILK_FRAME_LAST | \
+ CILK_FRAME_EXITING | \
+ CILK_FRAME_SUSPENDED | \
+ CILK_FRAME_UNWINDING | \
+ CILK_FRAME_VERSION_MASK))
+
+__CILKRTS_BEGIN_EXTERN_C
+
+/**
+ * Call __cilkrts_enter_frame to initialize an ABI 0 frame descriptor.
+ * Initialize the frame descriptor before spawn or detach. A function that
+ * conditionally does Cilk operations need not initialize the frame descriptor
+ * in a code path that never uses it.
+ *
+ * @param sf The __cilkrts_stack_frame that is to be initialized.
+ */
+CILK_ABI(void) __cilkrts_enter_frame(__cilkrts_stack_frame* sf);
+
+/**
+ * Call __cilkrts_enter_frame to initialize an ABI 1 frame descriptor.
+ * Initialize the frame descriptor before spawn or detach. A function that
+ * conditionally does Cilk operations need not initialize the frame descriptor
+ * in a code path that never uses it.
+ *
+ * @param sf The __cilkrts_stack_frame that is to be initialized.
+ */
+CILK_ABI(void) __cilkrts_enter_frame_1(__cilkrts_stack_frame* sf);
+
+/**
+ * __cilkrts_enter_frame_fast is the same as __cilkrts_enter_frame, except it
+ * assumes that the thread has already been bound to a worker.
+ *
+ * @param sf The __cilkrts_stack_frame that is to be initialized.
+ */
+CILK_ABI(void) __cilkrts_enter_frame_fast(__cilkrts_stack_frame *sf);
+
+/**
+ * __cilkrts_enter_frame_fast_1 is the same as __cilkrts_enter_frame_1,
+ * except it assumes that the thread has already been bound to a worker.
+ *
+ * @param sf The __cilkrts_stack_frame that is to be initialized.
+ */
+CILK_ABI(void) __cilkrts_enter_frame_fast_1(__cilkrts_stack_frame *sf);
+
+/**
+ * Call leave_frame before leaving a frame, after sync. This function
+ * returns except in a spawn wrapper where the parent has been stolen.
+ *
+ * @param sf The __cilkrts_stack_frame that is to be left.
+ */
+CILK_ABI(void) __cilkrts_leave_frame(__cilkrts_stack_frame *sf);
+
+/**
+ * Wait for any spawned children of this function to complete before
+ * continuing. This function will only return when the join counter
+ * has gone to 0. Other workers will re-enter the scheduling loop to
+ * attempt to steal additional work.
+ *
+ * @param sf The __cilkrts_stack_frame that is to be synched.
+ */
+CILK_ABI(void) __cilkrts_sync(__cilkrts_stack_frame *sf);
+
+/**
+ * Called when an exception is escaping a spawn * wrapper.
+ * The stack frame's except_data field is the C++ runtime
+ * exception object. If NULL (temporary workaround) the
+ * currently caught exception should be rethrown. If this
+ * function returns normal exit functions must be called;
+ * undo-detach will have been done.
+ *
+ * @param sf The __cilkrts_stack_frame for the function that
+ * is raising an exception.
+ */
+CILK_ABI_THROWS(void)
+ __cilkrts_return_exception(__cilkrts_stack_frame *sf);
+
+/**
+ * Called to re-raise an exception.
+ *
+ * @param sf The __cilkrts_stack_frame for the function that
+ * is raising an exception.
+ */
+CILK_ABI_THROWS(void) __cilkrts_rethrow(__cilkrts_stack_frame *sf);
+
+/**
+ * Called at the beginning of a spawning function to get the worker
+ * that this function is running on. This worker will be used to
+ * initialize the __cilkrts_stack_frame.
+ *
+ * @return The __cilkrts_worker that the function is running on.
+ * @return NULL if this thread is not yet bound to a worker.
+ */
+CILK_ABI(__cilkrts_worker_ptr) __cilkrts_get_tls_worker(void);
+
+/**
+ * Similar to __cilkrts_get_tls_worker, but assumes that TLS has been
+ * initialized.
+ *
+ * @return The __cilkrts_worker that the function is running on.
+ * @return NULL if this thread is not yet bound to a worker.
+ */
+CILK_ABI(__cilkrts_worker_ptr) __cilkrts_get_tls_worker_fast(void);
+
+/**
+ * Binds a thread to the runtime by associating a __cilkrts_worker with
+ * it. Called if __cilkrts_get_tls_worker returns NULL. This function will
+ * initialize the runtime the first time it is called.
+ *
+ * This function is versioned by the ABI version number. The runtime
+ * will export all previous versions. This prevents using an application
+ * built with a newer compiler against an old runtime.
+ *
+ * @return The __cilkrts_worker bound to the thread the function is running
+ * on.
+ */
+CILK_ABI(__cilkrts_worker_ptr) __cilkrts_bind_thread_1(void);
+
+typedef uint32_t cilk32_t; /**< 32-bit unsigned type for cilk_for loop indicies */
+
+typedef uint64_t cilk64_t; /**< 64-bit unsigned type for cilk_for loop indicies */
+
+/**
+ * Signature for the lambda function generated for the body of a cilk_for loop
+ * which uses 32-bit indicies
+ */
+typedef void (*__cilk_abi_f32_t)(void *data, cilk32_t low, cilk32_t high);
+
+/**
+ * Signature for the lambda function generated for the body of a cilk_for lop
+ * which uses 64-bit indicies
+ */
+typedef void (*__cilk_abi_f64_t)(void *data, cilk64_t low, cilk64_t high);
+
+/**
+ * @brief cilk_for implementation for 32-bit indexes.
+ *
+ * @param body The lambda function for the body of the cilk_for. The lambda
+ * function will be called to execute each grain of work.
+ * @param data Data passed by the compiler into the lambda function. Provides
+ * access to data outside the cilk_for body.
+ * @param count Number of steps in the loop.
+ * @param grain This parameter allows the compiler to pass a value from a
+ * \#pragam(grainsize) statement to allow the user to control the grainsize. If
+ * there isn't a \#pragma(grainsize) immediately preceeding cilk_for loop, Pass
+ * 0 to specify that the runtime should calculate the grainsize using its own
+ * hueristicts.
+ */
+CILK_ABI_THROWS(void) __cilkrts_cilk_for_32(__cilk_abi_f32_t body,
+ void *data,
+ cilk32_t count,
+ int grain);
+
+/**
+ * @brief cilk_for implementation for 64-bit indexes.
+ *
+ * @copydetails __cilkrts_cilk_for_32
+ */
+CILK_ABI_THROWS(void) __cilkrts_cilk_for_64(__cilk_abi_f64_t body,
+ void *data,
+ cilk64_t count,
+ int grain);
+
+/**
+ * @brief Allocate memory for variable length arrays. If the frame is
+ * sync'd, the memory will be allocated on the stack, otherwise it will
+ * be allocated from the heap.
+ *
+ * @param sf The __cilkrts_stack_frame for the function allocating the
+ * memory.
+ * @param size The number of bytes requested.
+ * @param distance_from_sp_to_alloca_area ?.
+ * @param align Alignment required. Always >= minimum stack alignment,
+ * >= ptr_size, and always a power of 2.
+ * @param needs_tag Non-zero if the pointer being returned needs to be
+ * tagged
+ *
+ * @return The address of the memory block allocated.
+ */
+
+CILK_ABI(__cilkrts_void_ptr)
+__cilkrts_stack_alloc(__cilkrts_stack_frame *sf,
+ size_t size,
+ size_t distance_from_sp_to_alloca_area,
+ uint32_t align,
+ uint32_t needs_tag);
+
+/**
+ * @brief Free memory allocated by _cilkrts_stack_alloc() for variable length
+ * arrays.
+ *
+ * @param sf The __cilkrts_stack_frame for the function allocating the
+ * memory.
+ * @param p Pointer to the memory block to be freed.
+ * @param size The number of bytes requested.
+ * @param distance_from_sp_to_alloca_area ?.
+ * @param align Alignment required. Always >= minimum stack alignment,
+ * >= ptr_size, and always a power of 2.
+ * @param know_from_stack Non-zero if the pointer is known to have been
+ * allocated on the stack and has no tag.
+ */
+CILK_ABI(void)
+__cilkrts_stack_free(__cilkrts_stack_frame *sf,
+ void *p,
+ size_t size,
+ size_t distance_from_sp_to_alloca_area,
+ uint32_t align,
+ uint32_t known_from_stack);
+
+/**
+ * @brief System-dependent code to save floating point control information
+ * to an ABI 1 or higher @c __cilkrts_stack_frame. If possible (and necessary)
+ * the code to save the floating point control information should be inlined.
+ *
+ * Note that this function does *not* save the current floating point
+ * registers. It saves the floating point control words that control
+ * precision and rounding and stuff like that.
+ *
+ * This function will be a noop for architectures that don't have warts
+ * like the floating point control words, or where the information is
+ * already being saved by the setjmp.
+ *
+ * @param sf @c __cilkrts_stack_frame for the frame we're saving the
+ * floating point control information in.
+ */
+CILK_ABI(void)
+__cilkrts_save_fp_ctrl_state(__cilkrts_stack_frame *sf);
+
+__CILKRTS_END_EXTERN_C
+#endif /* include guard */
diff --git a/libcilkrts/include/internal/cilk_fake.h b/libcilkrts/include/internal/cilk_fake.h
new file mode 100644
index 00000000000..2386dd6bffa
--- /dev/null
+++ b/libcilkrts/include/internal/cilk_fake.h
@@ -0,0 +1,477 @@
+/* cilk_fake.h -*-C++-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2011-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ **************************************************************************/
+
+/**
+ * @file cilk_fake.h
+ *
+ * @brief Macros to simulate a compiled Cilk program.
+ *
+ * Used carefully, these macros can be used to create a Cilk program with a
+ * non-Cilk compiler by manually inserting the code necessary for interacting
+ * with the Cilk runtime library. They are not intended to be pretty (you
+ * wouldn't want to write a whole program using these macros), but they are
+ * useful for experiments. They also work well as an illustration of what the
+ * compiler generates.
+ *
+ * Details of the mechanisms used in these macros are described in
+ * design-notes/CilkPlusABI.docx
+ *
+ * Example 1: fib in C++
+ * ---------------------
+ *
+ * #include <internal/cilk_fake.h>
+ *
+ * int fib(int n)
+ * {
+ * CILK_FAKE_PROLOG();
+ *
+ * if (n < 2)
+ * return n;
+ *
+ * int a, b;
+ * CILK_FAKE_SPAWN_R(a, fib(n - 1));
+ * b = fib(n - 2);
+ * CILK_FAKE_SYNC();
+ *
+ * return a + b;
+ * }
+ *
+ *
+ * Example 2: fib in C
+ * -------------------
+ *
+ * #include <internal/cilk_fake.h>
+ *
+ * int fib(int n);
+ *
+ * void fib_spawn_helper(__cilkrts_stack_frame* parent_sf, int* a, int n)
+ * {
+ * CILK_FAKE_SPAWN_HELPER_PROLOG(*parent_sf);
+ * *a = fib(n - 1);
+ * CILK_FAKE_SPAWN_HELPER_EPILOG();
+ * }
+ *
+ * int fib(int n)
+ * {
+ * CILK_FAKE_PROLOG();
+ *
+ * if (n < 2)
+ * return n;
+ *
+ * int a, b;
+ * CILK_FAKE_CALL_SPAWN_HELPER(fib_spawn_helper(&__cilk_sf, &a, n));
+ * b = fib(n - 2);
+ * CILK_FAKE_SYNC();
+ *
+ * CILK_FAKE_EPILOG();
+ * return a + b;
+ * }
+ */
+
+#ifndef INCLUDED_CILK_FAKE_DOT_H
+#define INCLUDED_CILK_FAKE_DOT_H
+
+// This header implements ABI version 1. If __CILKRTS_ABI_VERSION is already
+// defined but is less than 1, then the data structures in <internal/abi.h>
+// will not match the expectations of facilities in this header. Therefore,
+// for successful compilation, __CILKRTS_ABI_VERSION must either be not
+// defined, or defined to be 1 or greater.
+#ifndef __CILKRTS_ABI_VERSION
+ // ABI version was not specified. Set it to 1.
+# define __CILKRTS_ABI_VERSION 1
+#elif __CILKRTS_ABI_VERSION < 1
+ // ABI version was specified but was too old. Fail compilation.
+# error cilk_fake.h requirs an ABI version of 1 or greater
+#endif
+
+#include <internal/abi.h>
+
+// alloca is defined in malloc.h on Windows, alloca.h on Linux
+#ifndef _MSC_VER
+#include <alloca.h>
+#else
+#include <malloc.h>
+// Define offsetof
+#include <stddef.h>
+#endif
+
+// Allows use of a different version that the one defined in abi.h
+#define CILK_FAKE_VERSION_FLAG (__CILKRTS_ABI_VERSION << 24)
+
+/* Initialize frame. To be called when worker is known */
+__CILKRTS_INLINE void __cilk_fake_enter_frame_fast(__cilkrts_stack_frame *sf,
+ __cilkrts_worker *w)
+{
+ sf->call_parent = w->current_stack_frame;
+ sf->worker = w;
+ sf->flags = CILK_FAKE_VERSION_FLAG;
+ w->current_stack_frame = sf;
+}
+
+/* Initialize frame. To be called when worker is not known */
+__CILKRTS_INLINE void __cilk_fake_enter_frame(__cilkrts_stack_frame *sf)
+{
+ __cilkrts_worker* w = __cilkrts_get_tls_worker();
+ uint32_t last_flag = 0;
+ if (! w) {
+ w = __cilkrts_bind_thread_1();
+ last_flag = CILK_FRAME_LAST;
+ }
+ __cilk_fake_enter_frame_fast(sf, w);
+ sf->flags |= last_flag;
+}
+
+/* Initialize frame. To be called within the spawn helper */
+__CILKRTS_INLINE void __cilk_fake_helper_enter_frame(
+ __cilkrts_stack_frame *sf,
+ __cilkrts_stack_frame *parent_sf)
+{
+ sf->worker = 0;
+ sf->call_parent = parent_sf;
+}
+
+/* Called from the spawn helper to push the parent continuation on the task
+ * deque so that it can be stolen.
+ */
+__CILKRTS_INLINE void __cilk_fake_detach(__cilkrts_stack_frame *sf)
+{
+ /* Initialize spawn helper frame.
+ * call_parent was saved in __cilk_fake_helper_enter_frame */
+ __cilkrts_stack_frame *parent = sf->call_parent;
+ __cilkrts_worker *w = parent->worker;
+ __cilk_fake_enter_frame_fast(sf, w);
+
+ /* Append a node to the pedigree */
+ sf->spawn_helper_pedigree = w->pedigree;
+ parent->parent_pedigree = w->pedigree;
+ w->pedigree.rank = 0;
+ w->pedigree.parent = &sf->spawn_helper_pedigree;
+
+ /* Push parent onto the task deque */
+ __cilkrts_stack_frame *volatile *tail = w->tail;
+ *tail++ = sf->call_parent;
+ /* The stores must be separated by a store fence (noop on x86)
+ * or the second store is a release (st8.rel on Itanium) */
+ w->tail = tail;
+ sf->flags |= CILK_FRAME_DETACHED;
+}
+
+/* This variable is used in CILK_FAKE_FORCE_FRAME_PTR(), below */
+static int __cilk_fake_dummy = 8;
+
+/* The following macro is used to force the compiler into generating a frame
+ * pointer. We never change the value of __cilk_fake_dummy, so the alloca()
+ * is never called, but we need the 'if' statement and the __cilk_fake_dummy
+ * variable so that the compiler does not attempt to optimize it away.
+ */
+#define CILK_FAKE_FORCE_FRAME_PTR(sf) do { \
+ if (__builtin_expect(1 & __cilk_fake_dummy, 0)) \
+ (sf).worker = (__cilkrts_worker*) alloca(__cilk_fake_dummy); \
+} while (0)
+
+#ifndef CILK_FAKE_NO_SHRINKWRAP
+ /* "shrink-wrap" optimization enabled. Do not initialize frame on entry,
+ * except to clear worker pointer. Instead, defer initialization until
+ * the first spawn.
+ */
+# define CILK_FAKE_INITIAL_ENTER_FRAME(sf) ((void) ((sf).worker = 0))
+# define CILK_FAKE_DEFERRED_ENTER_FRAME(sf) do { \
+ if (! (sf).worker) __cilk_fake_enter_frame(&(sf)); \
+ } while (0)
+#else
+ /* "shrink-wrap" optimization disabled. Initialize frame immediately on
+ * entry. Do not initialize frame on spawn.
+ */
+# define CILK_FAKE_INITIAL_ENTER_FRAME(sf) \
+ __cilk_fake_enter_frame(&(sf))
+# define CILK_FAKE_DEFERRED_ENTER_FRAME(sf) ((void) &(sf))
+#endif
+
+/* Prologue of a spawning function. Declares and initializes the stack
+ * frame.
+ */
+#define CILK_FAKE_PROLOG() \
+ __cilk_fake_stack_frame __cilk_sf; \
+ CILK_FAKE_FORCE_FRAME_PTR(__cilk_sf); \
+ CILK_FAKE_INITIAL_ENTER_FRAME(__cilk_sf)
+
+/* Prologue of a spawning function where the current worker is already known.
+ * Declares and initializes the stack frame without looking up the worker from
+ * TLS.
+ */
+#define CILK_FAKE_PROLOG_FAST(w) \
+ __cilk_fake_stack_frame __cilk_sf; \
+ CILK_FAKE_FORCE_FRAME_PTR(__cilk_sf); \
+ __cilk_fake_enter_frame_fast(&__cilk_sf, (w))
+
+/* Simulate a cilk_sync */
+#define CILK_FAKE_SYNC() CILK_FAKE_SYNC_IMP(__cilk_sf)
+
+/* Epilog at the end of a spawning function. Does a sync and calls the
+ * runtime for leaving the frame.
+ */
+#ifdef __cplusplus
+ // Epilogue is run automatically by __cilk_fake_stack_frame destructor.
+# define CILK_FAKE_EPILOG() ((void) __cilk_sf)
+#else
+# define CILK_FAKE_EPILOG() CILK_FAKE_CLEANUP_FRAME(__cilk_sf)
+#endif // C
+
+/* Implementation of spawning function epilog. See CILK_FAKE_EPILOG macro and
+ * __cilk_fake_stack_frame destructor body.
+ */
+#define CILK_FAKE_CLEANUP_FRAME(sf) do { \
+ if (! (sf).worker) break; \
+ CILK_FAKE_SYNC_IMP(sf); \
+ CILK_FAKE_POP_FRAME(sf); \
+ if ((sf).flags != CILK_FAKE_VERSION_FLAG) \
+ __cilkrts_leave_frame(&(sf)); \
+} while (0)
+
+/* Implementation of CILK_FAKE_SYNC with sf argument */
+#define CILK_FAKE_SYNC_IMP(sf) do { \
+ if (__builtin_expect((sf).flags & CILK_FRAME_UNSYNCHED, 0)) { \
+ (sf).parent_pedigree = (sf).worker->pedigree; \
+ CILK_FAKE_SAVE_FP(sf); \
+ if (! CILK_SETJMP((sf).ctx)) \
+ __cilkrts_sync(&(sf)); \
+ } \
+ ++(sf).worker->pedigree.rank; \
+} while (0)
+
+/* Save the floating-point control registers.
+ * The definition of CILK_FAKE_SAVE_FP is compiler specific (and
+ * architecture specific on Windows)
+ */
+#ifdef _MSC_VER
+# define MXCSR_OFFSET offsetof(struct __cilkrts_stack_frame, mxcsr)
+# define FPCSR_OFFSET offsetof(struct __cilkrts_stack_frame, fpcsr)
+# if defined(_M_IX86)
+/* Windows x86 */
+# define CILK_FAKE_SAVE_FP(sf) do { \
+ __asm \
+ { \
+ mov eax, sf \
+ stmxcsr [eax+MXCSR_OFFSET] \
+ fnstcw [eax+FPCSR_OFFSET] \
+ } \
+ } while (0)
+# elif defined(_M_X64)
+/* Windows Intel64 - Not needed - saved by setjmp call */
+# define CILK_FAKE_SAVE_FP(sf) ((void) sf)
+# else
+# error "Unknown architecture"
+# endif /* Microsoft architecture specifics */
+#else
+/* Non-Windows */
+# define CILK_FAKE_SAVE_FP(sf) do { \
+ __asm__ ( "stmxcsr %0\n\t" \
+ "fnstcw %1" : : "m" ((sf).mxcsr), "m" ((sf).fpcsr)); \
+ } while (0)
+#endif
+
+/* Call the spawn helper as part of a fake spawn */
+#define CILK_FAKE_CALL_SPAWN_HELPER(helper) do { \
+ CILK_FAKE_DEFERRED_ENTER_FRAME(__cilk_sf); \
+ CILK_FAKE_SAVE_FP(__cilk_sf); \
+ if (__builtin_expect(! CILK_SETJMP(__cilk_sf.ctx), 1)) { \
+ helper; \
+ } \
+} while (0)
+
+/* Body of a spawn helper function. In addition to the worker and the
+ * expression to spawn, pass it any number of statements to be executed before
+ * detaching.
+ */
+#define CILK_FAKE_SPAWN_HELPER_BODY(parent_sf, expr, ...) \
+ CILK_FAKE_SPAWN_HELPER_PROLOG(parent_sf); \
+ __VA_ARGS__; \
+ __cilk_fake_detach(&__cilk_sf); \
+ expr; \
+ CILK_FAKE_SPAWN_HELPER_EPILOG()
+
+/* Prolog for a spawn helper function */
+#define CILK_FAKE_SPAWN_HELPER_PROLOG(parent_sf) \
+ __cilk_fake_spawn_helper_stack_frame __cilk_sf; \
+ __cilk_fake_helper_enter_frame(&__cilk_sf, &(parent_sf))
+
+/* Implementation of spawn helper epilog. See CILK_FAKE_SPAWN_HELPER_EPILOG
+ * and the __cilk_fake_spawn_helper_frame destructor.
+ */
+#define CILK_FAKE_SPAWN_HELPER_CLEANUP_FRAME(sf) do { \
+ if (! (sf).worker) break; \
+ CILK_FAKE_POP_FRAME(sf); \
+ __cilkrts_leave_frame(&(sf)); \
+} while (0)
+
+/* Epilog to execute at the end of a spawn helper */
+#ifdef __cplusplus
+ // Epilog handled by __cilk_fake_spawn_helper_stack_frame destructor
+# define CILK_FAKE_SPAWN_HELPER_EPILOG() ((void) __cilk_sf)
+#else
+# define CILK_FAKE_SPAWN_HELPER_EPILOG() \
+ CILK_FAKE_SPAWN_HELPER_CLEANUP_FRAME(__cilk_sf)
+#endif
+
+/* Pop the current frame off of the call chain */
+#define CILK_FAKE_POP_FRAME(sf) do { \
+ (sf).worker->current_stack_frame = (sf).call_parent; \
+ (sf).call_parent = 0; \
+} while (0)
+
+#ifdef _WIN32
+/* define macros for synching functions before allowing them to propagate. */
+# define CILK_FAKE_EXCEPT_BEGIN \
+ if (0 == CILK_SETJMP(__cilk_sf.except_ctx)) {
+
+# define CILK_FAKE_EXCEPT_END \
+ } else { \
+ assert((__cilk_sf.flags & (CILK_FRAME_UNSYNCHED|CILK_FRAME_EXCEPTING))\
+ == CILK_FRAME_EXCEPTING); \
+ __cilkrts_rethrow(&__cilk_sf); \
+ exit(0); \
+ }
+#else
+# define CILK_EXCEPT_BEGIN {
+# define CILK_EXCEPT_END }
+#endif
+
+#ifdef __cplusplus
+// The following definitions depend on C++ features.
+
+// Wrap a functor (probably a lambda), so that a call to it cannot be
+// inlined.
+template <typename F>
+class __cilk_fake_noinline_wrapper
+{
+ F&& m_fn;
+public:
+ __cilk_fake_noinline_wrapper(F&& fn) : m_fn(static_cast<F&&>(fn)) { }
+
+#ifdef _WIN32
+ __declspec(noinline) void operator()(__cilkrts_stack_frame *sf);
+#else
+ void operator()(__cilkrts_stack_frame *sf) __attribute__((noinline));
+#endif
+
+};
+
+template <typename F>
+void __cilk_fake_noinline_wrapper<F>::operator()(__cilkrts_stack_frame *sf)
+{
+ m_fn(sf);
+}
+
+template <typename F>
+inline
+__cilk_fake_noinline_wrapper<F> __cilk_fake_make_noinline_wrapper(F&& fn)
+{
+ return __cilk_fake_noinline_wrapper<F>(static_cast<F&&>(fn));
+}
+
+// Simulate "_Cilk_spawn expr", where expr must be a function call.
+//
+// Note: this macro does not correctly construct function arguments.
+// According to the ABI specification, function arguments should be evaluated
+// before the detach and destroyed after the detach. This macro both
+// evaluates and destroys them after the detach. This means that if any part
+// of the function argument expression depends on a value that is modified in
+// the continuation of the spawn, race will occur between the continuation and
+// the argument evaluation.
+//
+// To work around this problem, this macro accepts an arbitrary list of
+// declarations and statements (separated by semicolons) that are evaluated
+// before the detach. Thus, to simulate:
+//
+// _Cilk_spawn f(expr);
+//
+// one would write:
+//
+// CILK_FAKE_SPAWN(f(arg), auto arg = expr);
+//
+// Despite appearing in the reverse order, the 'arg' variable is created and
+// initialized before the detach and the call to f(arg) occurs after the
+// detach.
+#define CILK_FAKE_SPAWN(expr, ...) \
+ CILK_FAKE_CALL_SPAWN_HELPER( \
+ CILK_FAKE_SPAWN_HELPER(expr, __VA_ARGS__)(&__cilk_sf))
+
+// Simulate "ret = cilk_spawn expr". See CILK_FAKE_SPAWN for constraints.
+#define CILK_FAKE_SPAWN_R(ret, expr, ...) \
+ CILK_FAKE_SPAWN(((ret) = (expr)), __VA_ARGS__)
+
+// Create a spawn helper as a C++11 lambda function. In addition to the
+// expression to spawn, this macro takes a any number of statements to be
+// executed before detaching.
+#define CILK_FAKE_SPAWN_HELPER(expr, ...) \
+ __cilk_fake_make_noinline_wrapper([&](__cilkrts_stack_frame *parent_sf) { \
+ CILK_FAKE_SPAWN_HELPER_BODY(*parent_sf, expr, __VA_ARGS__); \
+ })
+
+// C++ version of a __cilkrts_stack_frame for a spawning function.
+// This struct is identical to __cilkrts_stack_frame except that the
+// destructor automatically does frame cleanup.
+struct __cilk_fake_stack_frame : __cilkrts_stack_frame
+{
+ // Extension of __cilkrts_stack_frame with constructor and destructor
+ __cilk_fake_stack_frame() { }
+ __forceinline ~__cilk_fake_stack_frame() {
+ CILK_FAKE_CLEANUP_FRAME(*this);
+ }
+};
+
+// C++ version of a __cilkrts_stack_frame for a spawn helper.
+// This struct is identical to __cilkrts_stack_frame except that the
+// destructor automatically does frame cleanup.
+struct __cilk_fake_spawn_helper_stack_frame : __cilkrts_stack_frame
+{
+ // Extension of __cilkrts_stack_frame with constructor and destructor
+ __cilk_fake_spawn_helper_stack_frame() { worker = 0; }
+ __forceinline ~__cilk_fake_spawn_helper_stack_frame() {
+ CILK_FAKE_SPAWN_HELPER_CLEANUP_FRAME(*this);
+ }
+};
+#else
+// For C, __cilk_fake_stack_frame and __cilk_fake_spawn_helper_stack_frame are
+// identical to __cilkrts_stack_frame. Frame cleanup must be performed
+// excplicitly (in CILK_FAKE_EPILOG and CILK_FAKE_SPAWN_HELPER_EPILOG)
+typedef __cilkrts_stack_frame __cilk_fake_stack_frame;
+typedef __cilkrts_stack_frame __cilk_fake_spawn_helper_stack_frame;
+#endif
+
+#endif // ! defined(INCLUDED_CILK_FAKE_DOT_H)
diff --git a/libcilkrts/include/internal/cilk_version.h b/libcilkrts/include/internal/cilk_version.h
new file mode 100644
index 00000000000..f628338f7d2
--- /dev/null
+++ b/libcilkrts/include/internal/cilk_version.h
@@ -0,0 +1,47 @@
+// cilk_version.h
+//
+// @copyright
+// Copyright (C) 2009-2013, Intel Corporation
+// All rights reserved.
+//
+// @copyright
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in
+// the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// @copyright
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+// WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+// DO NOT EDIT THIS FILE!
+//
+// It was automatically generated by cilkrts/include/internal/Makefile
+
+#define VERSION_MAJOR 2
+#define VERSION_MINOR 0
+#define VERSION_BUILD 3902
+#define VERSION_REV 0
+#define VERSION_STRING "2,0,3902,0"
+#define VERSION_HASH "b4e38f4f7e3e"
+#define VERSION_BRANCH "v14.0"
+#define TBB_REV_NUMBER ""
+#define VERSION_YEAR "2013"
diff --git a/libcilkrts/include/internal/metacall.h b/libcilkrts/include/internal/metacall.h
new file mode 100644
index 00000000000..886f49f9f83
--- /dev/null
+++ b/libcilkrts/include/internal/metacall.h
@@ -0,0 +1,99 @@
+// -*- C++ -*-
+
+/*
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ *
+ * metacall.h
+ *
+ * This is an internal header file defining part of the metacall
+ * interface used by Cilkscreen. It is not a stable API and is
+ * subject to change without notice.
+ */
+
+// Provides the enum of metacall kinds. This is used by Cilkscreen and the
+// runtime, and will probably be used by any future ptools.
+
+#pragma once
+
+///////////////////////////////////////////////////////////////////////////////
+
+enum
+{
+ // Notify Cilkscreen to stop/start instrumenting code
+ HYPER_DISABLE_INSTRUMENTATION = 0,
+ HYPER_ENABLE_INSTRUMENTATION = 1,
+
+ // Write 0 in *(char *)arg if the p-tool is sequential. The Cilk runtime
+ // system invokes this metacall to know whether to spawn worker threads.
+ HYPER_ZERO_IF_SEQUENTIAL_PTOOL = 2,
+
+ // Write 0 in *(char *)arg if the runtime must force reducers to
+ // call the reduce() method even if no actual stealing occurs.
+ HYPER_ZERO_IF_FORCE_REDUCE = 3,
+
+ // Inform cilkscreen about the current stack pointer.
+ HYPER_ESTABLISH_C_STACK = 4,
+
+ // Inform Cilkscreen about the current worker
+ HYPER_ESTABLISH_WORKER = 5,
+
+ // Tell tools to ignore a block of memory. Parameter is a 2 element
+ // array: void *block[2] = {_begin, _end}; _end is 1 beyond the end
+ // of the block to be ignored. Essentially, if p is a pointer to an
+ // array, _begin = &p[0], _end = &p[max]
+ HYPER_IGNORE_MEMORY_BLOCK = 6
+
+ // If you add metacalls here, remember to update BOTH workspan.cpp AND
+ // cilkscreen-common.cpp!
+};
+
+typedef struct
+{
+ unsigned int tool; // Specifies tool metacall is for
+ // (eg. system=0, cilkscreen=1, cilkview=2).
+ // All tools should understand system codes.
+ // Tools should ignore all other codes, except
+ // their own.
+
+ unsigned int code; // Tool-specific code specifies what to do and how to
+ // interpret data
+
+ void *data;
+} metacall_data_t;
+
+#define METACALL_TOOL_SYSTEM 0
+
+///////////////////////////////////////////////////////////////////////////////
diff --git a/libcilkrts/include/internal/rev.mk b/libcilkrts/include/internal/rev.mk
new file mode 100644
index 00000000000..f65ad6d57d0
--- /dev/null
+++ b/libcilkrts/include/internal/rev.mk
@@ -0,0 +1,41 @@
+#########################################################################
+#
+# @copyright
+# Copyright (C) 2011-2013, Intel Corporation
+# All rights reserved.
+#
+# @copyright
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# @copyright
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+# WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+###########################################################################
+
+# DO NOT EDIT THIS FILE!
+#
+# It was automatically generated by cilkrts/include/internal/Makefile
+
+CILK_REVISION = 3902
diff --git a/libcilkrts/mk/cilk-version.mk b/libcilkrts/mk/cilk-version.mk
new file mode 100644
index 00000000000..76f3f4ee38e
--- /dev/null
+++ b/libcilkrts/mk/cilk-version.mk
@@ -0,0 +1,61 @@
+#########################################################################
+#
+# @copyright
+# Copyright (C) 2009-2013, Intel Corporation
+# All rights reserved.
+#
+# @copyright
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# @copyright
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+# WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+###########################################################################
+# cilk-version.mk
+#
+# The one place we look up information from the code management system
+#
+# Note that the build number is *only* valid on the build machines
+
+ifeq ($(wildcard $(TOP)/../.hg),)
+ # If this is the open source release, there is no Mercurial repository,
+ # so set some reasonable defaults.
+ CILK_VERSION_MAJOR := 2
+ CILK_VERSION_MINOR := 0
+ CILK_VERSION_BUILD := 1
+ CILK_VERSION_REV := 0
+
+ CILK_VERSION_HASH := 000000000000
+ CILK_VERSION_BRANCH := oss
+else
+ CILK_VERSION_MAJOR := 2
+ CILK_VERSION_MINOR := 0
+ CILK_VERSION_BUILD := $(firstword $(subst +, ,$(shell hg id --num)))
+ CILK_VERSION_REV := 0
+
+ CILK_VERSION_HASH := $(firstword $(subst +, ,$(shell hg id --id)))
+ CILK_VERSION_BRANCH := $(shell hg id --branch)
+endif
+
diff --git a/libcilkrts/runtime/acknowledgements.dox b/libcilkrts/runtime/acknowledgements.dox
new file mode 100644
index 00000000000..79b5d876f33
--- /dev/null
+++ b/libcilkrts/runtime/acknowledgements.dox
@@ -0,0 +1,51 @@
+/* acknowledgements.dox
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ **************************************************************************/
+
+/*
+ * This file contains acknowledgements of community contributions to the
+ * Cilk Plus runtime.
+ */
+
+/**
+ * @mainpage
+ *
+ * @section Acknowledgements Acknowledgements
+ *
+ * Modifications to build the Cilk Plus runtime for VxWorks provided by
+ * Brian Kuhl of Wind River.
+ */
diff --git a/libcilkrts/runtime/bug.cpp b/libcilkrts/runtime/bug.cpp
new file mode 100644
index 00000000000..dbdf1fd3216
--- /dev/null
+++ b/libcilkrts/runtime/bug.cpp
@@ -0,0 +1,139 @@
+/* bug.cpp -*-C++-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ **************************************************************************/
+
+#include "bug.h"
+
+#include <exception>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#ifdef _WIN32
+# include "windows-clean.h"
+# include "internal/abi.h"
+# include "cilktools/cilkscreen.h"
+# include <crtdbg.h>
+#endif
+
+__CILKRTS_BEGIN_EXTERN_C
+
+COMMON_PORTABLE const char *const __cilkrts_assertion_failed =
+ "%s:%d: cilk assertion failed: %s\n";
+
+COMMON_PORTABLE void __cilkrts_bug(const char *fmt,...) cilk_nothrow
+{
+#if defined (_WIN32) && defined(_DEBUG)
+ _CRTIMP void __cdecl _wassert(__in_z const wchar_t * _Message,
+ __in_z const wchar_t *_File,
+ __in unsigned _Line);
+ char message[256];
+ wchar_t wmessage[256];
+ va_list l;
+ va_start(l, fmt);
+ _vsnprintf_s(message, 256, _TRUNCATE, fmt, l);
+ va_end(l);
+ _snwprintf_s(wmessage, 256, _TRUNCATE, _CRT_WIDE("%S"),
+ message); /* widen */
+
+ // Force asserts to go to stderr and the debugger. This isn't polite, but
+ // we're about to kill the app anyway and it will prevent our tests from
+ // hanging
+ _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE| _CRTDBG_MODE_DEBUG);
+ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
+
+ _wassert(wmessage, _CRT_WIDE(__FILE__), __LINE__);
+
+ // If there's a debugger attached, give it a chance to look at the failure
+ if (IsDebuggerPresent())
+ DebugBreak();
+
+ abort();
+/* __asm int 3 */
+#else
+ /* To reduce user confusion, write all user-generated output
+ before the system-generated error message. */
+ va_list l;
+ fflush(NULL);
+ va_start(l, fmt);
+ vfprintf(stderr, fmt, l);
+ va_end(l);
+ fflush(stderr);
+
+#ifndef _WIN32
+ abort();
+#endif
+
+#endif
+
+ exit(1);
+}
+
+COMMON_PORTABLE void cilkbug_assert_no_uncaught_exception(void)
+{
+ bool uncaught = std::uncaught_exception();
+ CILK_ASSERT(!uncaught);
+}
+
+COMMON_SYSDEP void abort_because_rts_is_corrupted(void)
+{
+ __cilkrts_bug("The Cilk Plus runtime system detected a corruption "
+ "in its data structures. This is most likely caused "
+ "by an application bug. Aborting execution.\n");
+}
+
+#ifdef WIN32
+COMMON_SYSDEP void __cilkrts_dbgprintf(const char *fmt,...)
+{
+ char message[2048];
+ va_list l;
+
+ // Cilkscreen shouldn't watch this
+ __cilkscreen_disable_checking();
+
+ va_start(l, fmt);
+ _vsnprintf_s(message, 2048, _TRUNCATE, fmt, l);
+ va_end(l);
+ OutputDebugStringA (message);
+
+ // Re-enable Cilkscreen
+ __cilkscreen_enable_checking();
+}
+#endif
+
+__CILKRTS_END_EXTERN_C
+
+/* End bug.cpp */
diff --git a/libcilkrts/runtime/bug.h b/libcilkrts/runtime/bug.h
new file mode 100644
index 00000000000..bb18913787d
--- /dev/null
+++ b/libcilkrts/runtime/bug.h
@@ -0,0 +1,141 @@
+/* bug.h -*-C++-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ **************************************************************************/
+
+/**
+ * @file bug.h
+ *
+ * @brief Support for reporting bugs and debugging.
+ */
+
+#ifndef INCLUDED_BUG_DOT_H
+#define INCLUDED_BUG_DOT_H
+
+#include "rts-common.h"
+#include <cilk/common.h>
+
+__CILKRTS_BEGIN_EXTERN_C
+
+/**
+ * Flush all output, write error message to stderr and abort the execution.
+ * On Windows the error is also written to the debugger.
+ *
+ * @param fmt printf-style format string. Any remaining parameters will be
+ * be interpreted based on the format string text.
+ */
+COMMON_PORTABLE NORETURN __cilkrts_bug(const char *fmt,...) cilk_nothrow;
+
+#ifndef CILK_ASSERT
+
+/** Standard text for failed assertion */
+COMMON_PORTABLE extern const char *const __cilkrts_assertion_failed;
+
+/**
+ * Macro to assert an invariant that must be true. If the statement evalutes
+ * to false, __cilkrts_bug will be called to report the failure and terminate
+ * the application.
+ */
+#define CILK_ASSERT(ex) \
+ (__builtin_expect((ex) != 0, 1) ? (void)0 : \
+ __cilkrts_bug(__cilkrts_assertion_failed, __FILE__, __LINE__, #ex))
+
+#define CILK_ASSERT_MSG(ex, msg) \
+ (__builtin_expect((ex) != 0, 1) ? (void)0 : \
+ __cilkrts_bug(__cilkrts_assertion_failed, __FILE__, __LINE__, \
+ #ex "\n " msg))
+#endif // CILK_ASSERT
+
+/**
+ * Assert that there is no uncaught exception.
+ *
+ * Not valid on Windows or Android.
+ *
+ * On Android, calling std::uncaught_exception with the stlport library causes
+ * a seg fault. Since we're not supporting exceptions there at this point,
+ * just don't do the check. It works with the GNU STL library, but that's
+ * GPL V3 licensed.
+ */
+COMMON_PORTABLE void cilkbug_assert_no_uncaught_exception(void);
+#if defined(_WIN32) || defined(ANDROID)
+# define CILKBUG_ASSERT_NO_UNCAUGHT_EXCEPTION()
+#else
+# define CILKBUG_ASSERT_NO_UNCAUGHT_EXCEPTION() \
+ cilkbug_assert_no_uncaught_exception()
+#endif
+
+
+/**
+ * Call __cilkrts_bug with a standard message that the runtime state is
+ * corrupted and the application is being terminated.
+ */
+COMMON_SYSDEP void abort_because_rts_is_corrupted(void);
+
+// Debugging aids
+#ifndef _DEBUG
+# define DBGPRINTF(_fmt, ...)
+#elif defined(_WIN32)
+
+/**
+ * Write debugging output. On windows this is written to the debugger.
+ *
+ * @param fmt printf-style format string. Any remaining parameters will be
+ * be interpreted based on the format string text.
+ */
+COMMON_SYSDEP void __cilkrts_dbgprintf(const char *fmt,...) cilk_nothrow;
+
+/**
+ * Macro to write debugging output which will be elided if this is not a
+ * debug build. The macro is currently always elided on non-Windows builds.
+ *
+ * @param _fmt printf-style format string. Any remaining parameters will be
+ * be interpreted based on the format string text.
+ */
+# define DBGPRINTF(_fmt, ...) __cilkrts_dbgprintf(_fmt, __VA_ARGS__)
+
+#else /* if _DEBUG && !_WIN32 */
+ /* Non-Windows debug logging. Someday we should make GetCurrentFiber()
+ * and GetWorkerFiber() do something.
+ */
+# include <stdio.h>
+ __CILKRTS_INLINE void* GetCurrentFiber() { return 0; }
+ __CILKRTS_INLINE void* GetWorkerFiber(__cilkrts_worker* w) { return 0; }
+# define DBGPRINTF(_fmt, ...) fprintf(stderr, _fmt, __VA_ARGS__)
+#endif // _DEBUG
+
+__CILKRTS_END_EXTERN_C
+
+#endif // ! defined(INCLUDED_BUG_DOT_H)
diff --git a/libcilkrts/runtime/c_reducers.c b/libcilkrts/runtime/c_reducers.c
new file mode 100644
index 00000000000..52615e93f43
--- /dev/null
+++ b/libcilkrts/runtime/c_reducers.c
@@ -0,0 +1,57 @@
+/* c_reducers.c -*-C-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2010-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ **************************************************************************/
+
+/* Implementation of C reducers */
+
+// Disable warning about integer conversions losing significant bits.
+// The code is correct as is.
+#ifdef __INTEL_COMPILER
+#pragma warning(disable:2259)
+#endif
+
+#define CILK_C_DEFINE_REDUCERS
+
+#include <cilk/reducer_opadd.h>
+#include <cilk/reducer_opand.h>
+#include <cilk/reducer_opmul.h>
+#include <cilk/reducer_opor.h>
+#include <cilk/reducer_opxor.h>
+#include <cilk/reducer_min_max.h>
+
+/* End reducer_opadd.c */
diff --git a/libcilkrts/runtime/cilk-abi-cilk-for.cpp b/libcilkrts/runtime/cilk-abi-cilk-for.cpp
new file mode 100644
index 00000000000..4fa6dcec82a
--- /dev/null
+++ b/libcilkrts/runtime/cilk-abi-cilk-for.cpp
@@ -0,0 +1,406 @@
+/* cilk-abi-cilk-for.cpp -*-C++-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2011, 2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ **************************************************************************/
+
+/* Implementation of cilk_for ABI.
+ *
+ * This file must be C++, not C, in order to handle C++ exceptions correctly
+ * from within the body of the cilk_for loop
+ */
+
+#include "internal/abi.h"
+#include "metacall_impl.h"
+#include "global_state.h"
+
+// Icky macros to determine if we're compiled with optimization. Based on
+// the declaration of __CILKRTS_ASSERT in common.h
+#if defined(_WIN32)
+# if defined (_DEBUG)
+# define CILKRTS_OPTIMIZED 0 // Assumes /MDd is always used with /Od
+# else
+# define CILKRTS_OPTIMIZED 1
+# endif // defined(_DEBUG)
+#else
+# if defined(__OPTIMIZE__)
+# define CILKRTS_OPTIMIZED 1
+# else
+# define CILKRTS_OPTIMIZED 0
+# endif
+#endif
+
+template <typename count_t>
+static inline int grainsize(int req, count_t count)
+{
+ // A positive requested grain size comes from the user. A very high grain
+ // size risks losing parallelism, but the user told us what they want for
+ // grainsize. Who are we to argue?
+ if (req > 0)
+ return req;
+
+ // At present, a negative requested grain size is treated the same way as
+ // a zero grain size, i.e., the runtime computes the actual grainsize
+ // using a hueristic. In the future, the compiler may give us additional
+ // information about the size of the cilk_for body by passing a negative
+ // grain size.
+
+ // Avoid generating a zero grainsize, even for empty loops.
+ if (count < 1)
+ return 1;
+
+ global_state_t* g = cilkg_get_global_state();
+ if (g->under_ptool)
+ {
+ // Grainsize = 1, when running under PIN, and when the grainsize has
+ // not explicitly been set by the user.
+ return 1;
+ }
+ else
+ {
+ // Divide loop count by 8 times the worker count and round up.
+ const int Px8 = g->P * 8;
+ count_t n = (count + Px8 - 1) / Px8;
+
+ // 2K should be enough to amortize the cost of the cilk_for. Any
+ // larger grainsize risks losing parallelism.
+ if (n > 2048)
+ return 2048;
+ return (int) n; // n <= 2048, so no loss of precision on cast to int
+ }
+}
+
+/*
+ * call_cilk_for_loop_body
+ *
+ * Centralizes the code to call the loop body. The compiler should be
+ * inlining this code
+ *
+ * low - Low loop index we're considering in this portion of the algorithm
+ * high - High loop index we're considering in this portion of the algorithm
+ * body - lambda function for the cilk_for loop body
+ * data - data used by the lambda function
+ * w - __cilkrts_worker we're currently executing on
+ * loop_root_pedigree - __cilkrts_pedigree node we generated for the root of
+ * the cilk_for loop to flatten out the internal nodes
+ */
+template <typename count_t, typename F>
+inline static
+void call_cilk_for_loop_body(count_t low, count_t high,
+ F body, void *data,
+ __cilkrts_worker *w,
+ __cilkrts_pedigree *loop_root_pedigree)
+{
+ // Cilkscreen should not report this call in a stack trace
+ NOTIFY_ZC_INTRINSIC((char *)"cilkscreen_hide_call", 0);
+
+ // The worker is only valid until the first spawn. Fetch the
+ // __cilkrts_stack_frame out of the worker, since it will be stable across
+ // steals. The sf pointer actually points to the *parent's*
+ // __cilkrts_stack_frame, since this function is a non-spawning function
+ // and therefore has no cilk stack frame of its own.
+ __cilkrts_stack_frame *sf = w->current_stack_frame;
+
+ // Save the pedigree node pointed to by the worker. We'll need to restore
+ // that when we exit since the spawn helpers in the cilk_for call tree
+ // will assume that it's valid
+ const __cilkrts_pedigree *saved_next_pedigree_node = w->pedigree.parent;
+
+ // Add the leaf pedigree node to the chain. The parent is the root node
+ // to flatten the tree regardless of the DAG branches in the cilk_for
+ // divide-and-conquer recursion.
+ //
+ // The rank is initialized to the low index. The user is
+ // expected to call __cilkrts_bump_loop_rank at the end of the cilk_for
+ // loop body.
+ __cilkrts_pedigree loop_leaf_pedigree;
+
+ loop_leaf_pedigree.rank = (uint64_t)low;
+ loop_leaf_pedigree.parent = loop_root_pedigree;
+
+ // The worker's pedigree always starts with a rank of 0
+ w->pedigree.rank = 0;
+ w->pedigree.parent = &loop_leaf_pedigree;
+
+ // Call the compiler generated cilk_for loop body lambda function
+ body(data, low, high);
+
+ // The loop body may have included spawns, so we must refetch the worker
+ // from the __cilkrts_stack_frame, which is stable regardless of which
+ // worker we're executing on.
+ w = sf->worker;
+
+ // Restore the pedigree chain. It must be valid because the spawn helpers
+ // generated by the cilk_for implementation will access it.
+ w->pedigree.parent = saved_next_pedigree_node;
+}
+
+/* capture_spawn_arg_stack_frame
+ *
+ * Efficiently get the address of the caller's __cilkrts_stack_frame. The
+ * preconditons are that 'w' is the worker at the time of the call and
+ * 'w->current_stack_frame' points to the __cilkrts_stack_frame within the
+ * spawn helper. This function should be called only within the argument list
+ * of a function that is being spawned because that is the only situation in
+ * which these preconditions hold. This function returns the worker
+ * (unchanged) after storing the captured stack frame pointer is stored in the
+ * sf argument.
+ *
+ * The purpose of this function is to get the caller's stack frame in a
+ * context where the caller's worker is known but its stack frame is not
+ * necessarily initialized. The "shrink wrap" optimization delays
+ * initializing the contents of a spawning function's '__cilkrts_stack_frame'
+ * as well as the 'current_stack_frame' pointer within the worker. By calling
+ * this function within a spawning function's argument list, we can ensure
+ * that these initializations have occured but that a detach (which would
+ * invalidate the worker pointer in the caller) has not yet occured. Once the
+ * '__cilkrts_stack_frame' has been retrieved in this way, it is stable for the
+ * remainder of the caller's execution, and becomes an efficient way to get
+ * the worker (much more efficient than calling '__cilkrts_get_tls_worker()'),
+ * even after a spawn or sync.
+ */
+inline __cilkrts_worker*
+capture_spawn_arg_stack_frame(__cilkrts_stack_frame* &sf, __cilkrts_worker* w)
+{
+ // Get current stack frame
+ sf = w->current_stack_frame;
+#ifdef __INTEL_COMPILER
+# if __INTEL_COMPILER <= 1300 && __INTEL_COMPILER_BUILD_DATE < 20130101
+ // In older compilers 'w->current_stack_frame' points to the
+ // spawn-helper's stack frame. In newer compiler's however, it points
+ // directly to the pointer's stack frame. (This change was made to avoid
+ // having the spawn helper in the frame list when evaluating function
+ // arguments, thus avoiding corruption when those arguments themselves
+ // contain cilk_spawns.)
+
+ // w->current_stack_frame is the spawn helper's stack frame.
+ // w->current_stack_frame->call_parent is the caller's stack frame.
+ sf = sf->call_parent;
+# endif
+#endif
+ return w;
+}
+
+/*
+ * cilk_for_recursive
+ *
+ * Templatized function to implement the recursive divide-and-conquer
+ * algorithm that's how we implement a cilk_for.
+ *
+ * low - Low loop index we're considering in this portion of the algorithm
+ * high - High loop index we're considering in this portion of the algorithm
+ * body - lambda function for the cilk_for loop body
+ * data - data used by the lambda function
+ * grain - grain size (0 if it should be computed)
+ * w - __cilkrts_worker we're currently executing on
+ * loop_root_pedigree - __cilkrts_pedigree node we generated for the root of
+ * the cilk_for loop to flatten out the internal nodes
+ */
+template <typename count_t, typename F>
+static
+void cilk_for_recursive(count_t low, count_t high,
+ F body, void *data, int grain,
+ __cilkrts_worker *w,
+ __cilkrts_pedigree *loop_root_pedigree)
+{
+tail_recurse:
+ // Cilkscreen should not report this call in a stack trace
+ // This needs to be done everytime the worker resumes
+ NOTIFY_ZC_INTRINSIC((char *)"cilkscreen_hide_call", 0);
+
+ count_t count = high - low;
+ // Invariant: count > 0, grain >= 1
+ if (count > grain)
+ {
+ // Invariant: count >= 2
+ count_t mid = low + count / 2;
+ // The worker is valid only until the first spawn and is expensive to
+ // retrieve (using '__cilkrts_get_tls_worker') after the spawn. The
+ // '__cilkrts_stack_frame' is more stable, but isn't initialized until
+ // the first spawn. Thus, we want to grab the address of the
+ // '__cilkrts_stack_frame' after it is initialized but before the
+ // spawn detaches. The only place we can do that is within the
+ // argument list of the spawned function, hence the call to
+ // capture_spawn_arg_stack_frame().
+ __cilkrts_stack_frame *sf;
+ _Cilk_spawn cilk_for_recursive(low, mid, body, data, grain,
+ capture_spawn_arg_stack_frame(sf, w),
+ loop_root_pedigree);
+ w = sf->worker;
+ low = mid;
+
+ goto tail_recurse;
+ }
+
+ // Call the cilk_for loop body lambda function passed in by the compiler to
+ // execute one grain
+ call_cilk_for_loop_body(low, high, body, data, w, loop_root_pedigree);
+}
+
+static void noop() { }
+
+/*
+ * cilk_for_root
+ *
+ * Templatized function to implement the top level of a cilk_for loop.
+ *
+ * body - lambda function for the cilk_for loop body
+ * data - data used by the lambda function
+ * count - trip count for loop
+ * grain - grain size (0 if it should be computed)
+ */
+template <typename count_t, typename F>
+static void cilk_for_root(F body, void *data, count_t count, int grain)
+{
+ // Cilkscreen should not report this call in a stack trace
+ NOTIFY_ZC_INTRINSIC((char *)"cilkscreen_hide_call", 0);
+
+ // Pedigree computation:
+ //
+ // If the last pedigree node on entry to the _Cilk_for has value X,
+ // then at the start of each iteration of the loop body, the value of
+ // the last pedigree node should be 0, the value of the second-to-last
+ // node should equal the loop counter, and the value of the
+ // third-to-last node should be X. On return from the _Cilk_for, the
+ // value of the last pedigree should be incremented to X+2. The
+ // pedigree within the loop is thus flattened, such that the depth of
+ // recursion does not affect the results either inside or outside of
+ // the loop. Note that the pedigree after the loop exists is the same
+ // as if a single spawn and sync were executed within this function.
+
+ // TBD: Since the shrink-wrap optimization was turned on in the compiler,
+ // it is not possible to get the current stack frame without actually
+ // forcing a call to bind-thread. This spurious spawn is a temporary
+ // stopgap until the correct intrinsics are added to give us total control
+ // over frame initialization.
+ _Cilk_spawn noop();
+
+ // Fetch the current worker. From that we can get the current stack frame
+ // which will be constant even if we're stolen
+ __cilkrts_worker *w = __cilkrts_get_tls_worker();
+ __cilkrts_stack_frame *sf = w->current_stack_frame;
+
+ // Decrement the rank by one to undo the pedigree change from the
+ // _Cilk_spawn
+ --w->pedigree.rank;
+
+ // Save the current worker pedigree into loop_root_pedigree, which will be
+ // the root node for our flattened pedigree.
+ __cilkrts_pedigree loop_root_pedigree = w->pedigree;
+
+ // Don't splice the loop_root node in yet. It will be done when we
+ // call the loop body lambda function
+// w->pedigree.rank = 0;
+// w->pedigree.next = &loop_root_pedigree;
+
+ /* Spawn is necessary at top-level to force runtime to start up.
+ * Runtime must be started in order to call the grainsize() function.
+ */
+ int gs = grainsize(grain, count);
+ cilk_for_recursive((count_t) 0, count, body, data, gs, w,
+ &loop_root_pedigree);
+
+ // Need to refetch the worker after calling a spawning function.
+ w = sf->worker;
+
+ // Restore the pedigree in the worker.
+ w->pedigree = loop_root_pedigree;
+
+ // Bump the worker pedigree.
+ ++w->pedigree.rank;
+
+ // Implicit sync will increment the pedigree leaf rank again, for a total
+ // of two increments. If the noop spawn above is removed, then we'll need
+ // to re-enable the following code:
+// // If this is an optimized build, then the compiler will have optimized
+// // out the increment of the worker's pedigree in the implied sync. We
+// // need to add one to make the pedigree_loop test work correctly.
+// #if CILKRTS_OPTIMIZED
+// ++sf->worker->pedigree.rank;
+// #endif
+}
+
+// Use extern "C" to suppress name mangling of __cilkrts_cilk_for_32 and
+// __cilkrts_cilk_for_64.
+extern "C" {
+
+/*
+ * __cilkrts_cilk_for_32
+ *
+ * Implementation of cilk_for for 32-bit trip counts (regardless of processor
+ * word size). Assumes that the range is 0 - count.
+ *
+ * body - lambda function for the cilk_for loop body
+ * data - data used by the lambda function
+ * count - trip count for loop
+ * grain - grain size (0 if it should be computed)
+ */
+
+CILK_ABI_THROWS_VOID __cilkrts_cilk_for_32(__cilk_abi_f32_t body, void *data,
+ cilk32_t count, int grain)
+{
+ // Cilkscreen should not report this call in a stack trace
+ NOTIFY_ZC_INTRINSIC((char *)"cilkscreen_hide_call", 0);
+
+ // Check for an empty range here as an optimization - don't need to do any
+ // __cilkrts_stack_frame initialization
+ if (count > 0)
+ cilk_for_root(body, data, count, grain);
+}
+
+/*
+ * __cilkrts_cilk_for_64
+ *
+ * Implementation of cilk_for for 64-bit trip counts (regardless of processor
+ * word size). Assumes that the range is 0 - count.
+ *
+ * body - lambda function for the cilk_for loop body
+ * data - data used by the lambda function
+ * count - trip count for loop
+ * grain - grain size (0 if it should be computed)
+ */
+CILK_ABI_THROWS_VOID __cilkrts_cilk_for_64(__cilk_abi_f64_t body, void *data,
+ cilk64_t count, int grain)
+{
+ // Check for an empty range here as an optimization - don't need to do any
+ // __cilkrts_stack_frame initialization
+ if (count > 0)
+ cilk_for_root(body, data, count, grain);
+}
+
+} // end extern "C"
+
+/* End cilk-abi-cilk-for.cpp */
diff --git a/libcilkrts/runtime/cilk-abi-vla-internal.c b/libcilkrts/runtime/cilk-abi-vla-internal.c
new file mode 100644
index 00000000000..6fb92677ad0
--- /dev/null
+++ b/libcilkrts/runtime/cilk-abi-vla-internal.c
@@ -0,0 +1,83 @@
+/* cilk-abi-vla-internal.c -*-C++-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ **************************************************************************/
+
+/*
+ * These functions are provided in their own compilation unit so I can debug
+ * them. cilk-abi-vla.c must always be compiled with optimization on so that
+ * inlining occurs.
+ */
+
+#include "internal/abi.h"
+#include "cilk-abi-vla-internal.h"
+#include "bug.h"
+#include "full_frame.h"
+#include "local_state.h"
+
+#include <stdlib.h>
+#include <stdint.h>
+
+#include "bug.h"
+
+void *vla_internal_heap_alloc(__cilkrts_stack_frame *sf,
+ size_t full_size,
+ uint32_t align)
+{
+ return malloc(full_size);
+}
+
+void vla_internal_heap_free(void *t, size_t size)
+{
+ free(t);
+}
+
+void vla_free_from_original_stack(__cilkrts_stack_frame *sf,
+ size_t full_size)
+{
+ // The __cilkrts_stack_frame must be initialized
+ CILK_ASSERT(sf->worker);
+
+#if 1
+ // Add full_size to ff->sync_sp so that when we return, the VLA will no
+ // longer be allocated on the stack
+ __cilkrts_adjust_stack(sf->worker->l->frame_ff, full_size);
+#else
+ // Inline __cilkrts_adjust_stack for Kevin
+ full_frame *ff = sf->worker->l->frame_ff;
+ ff->sync_sp = ff->sync_sp + full_size;
+#endif
+}
diff --git a/libcilkrts/runtime/cilk-abi-vla-internal.h b/libcilkrts/runtime/cilk-abi-vla-internal.h
new file mode 100644
index 00000000000..909f08fa471
--- /dev/null
+++ b/libcilkrts/runtime/cilk-abi-vla-internal.h
@@ -0,0 +1,90 @@
+/* cilk-abi-vla-internal.h -*-C++-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ **************************************************************************/
+
+/**
+ * @file cilk-abi-vla-internal.h
+ *
+ * @brief Allocation/deallocation function for use with Variable Length
+ * Arrays in spawning functions.
+ *
+ * These should be the only functions in the Cilk runtime allocating memory
+ * from the standard C runtime heap. This memory will be provided to user
+ * code for use in VLAs, when the memory cannot be allocated from the stack.
+ *
+ * While these functions are simply passthroughs to malloc and free at the
+ * moment, once we've got the basics of VLA allocations working we'll make
+ * them do fancier tricks.
+ */
+
+/**
+ * @brief Allocate memory from the heap for use by a Variable Length Array in
+ * a spawning function.
+ *
+ * @param sf The __cilkrts_stack_frame for the spawning function containing
+ * the VLA.
+ * @param full_size The number of bytes to be allocated, including any tags
+ * needed to identify this as allocated from the heap.
+ * @param align Any alignment necessary for the allocation.
+ */
+
+void *vla_internal_heap_alloc(__cilkrts_stack_frame *sf,
+ size_t full_size,
+ uint32_t align);
+
+/**
+ * @brief Deallocate memory from the heap used by a Variable Length Array in
+ * a spawning function.
+ *
+ * @param t The address of the memory block to be freed.
+ * @param size The size of the memory block to be freed.
+ */
+
+void vla_internal_heap_free(void *t,
+ size_t size);
+
+/**
+ * @brief Deallocate memory from the original stack. We'll do this by adding
+ * full_size to ff->sync_sp. So after the sync, the Variable Length Array
+ * will no longer be allocated on the stack.
+ *
+ * @param sf The __cilkrts_stack_frame for the spawning function that is
+ * deallocating a VLA.
+ * @param full_size The size of the VLA, including any alignment and tags.
+ */
+void vla_free_from_original_stack(__cilkrts_stack_frame *sf,
+ size_t full_size);
diff --git a/libcilkrts/runtime/cilk-abi.c b/libcilkrts/runtime/cilk-abi.c
new file mode 100644
index 00000000000..1da05239ebc
--- /dev/null
+++ b/libcilkrts/runtime/cilk-abi.c
@@ -0,0 +1,733 @@
+/* Cilk_abi.c -*-C++-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2010-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ **************************************************************************/
+
+/**
+ * @file cilk-abi.c
+ *
+ * @brief cilk-abi.c implements all of the entrypoints to the Intel Cilk
+ * Plus runtime.
+ */
+
+/*
+ * Define this macro so that compiliation of this file generates the
+ * non-inlined versions of certain functions in cilk_api.h.
+ */
+#include "internal/abi.h"
+#include "cilk/cilk_api.h"
+#include "cilk/cilk_undocumented.h"
+#include "cilktools/cilkscreen.h"
+
+#include "global_state.h"
+#include "os.h"
+#include "os_mutex.h"
+#include "bug.h"
+#include "local_state.h"
+#include "full_frame.h"
+#include "pedigrees.h"
+#include "scheduler.h"
+#include "sysdep.h"
+#include "except.h"
+#include "cilk_malloc.h"
+#include "record-replay.h"
+
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+
+#ifdef _MSC_VER
+/* Some versions of icc don't support limits.h on Linux if
+ gcc 4.3 or newer is installed. */
+#include <limits.h>
+
+/* Declare _ReturnAddress compiler intrinsic */
+void * _ReturnAddress(void);
+#pragma intrinsic(_ReturnAddress)
+
+#include "sysdep-win.h" // Needed for sysdep_init_module()
+#endif /* _WIN32 */
+
+#include "metacall_impl.h"
+#include "reducer_impl.h"
+#include "cilk-ittnotify.h"
+#include "cilk-tbb-interop.h"
+
+#define TBB_INTEROP_DATA_DELAYED_UNTIL_BIND (void *)-1
+
+/**
+ * __cilkrts_bind_thread is a versioned entrypoint. The runtime should be
+ * exporting copies of __cilkrts_bind_version for the current and all previous
+ * versions of the ABI.
+ *
+ * This macro should always be set to generate a version to match the current
+ * version; __CILKRTS_ABI_VERSION.
+ */
+#define BIND_THREAD_RTN __cilkrts_bind_thread_1
+
+static inline
+void enter_frame_internal(__cilkrts_stack_frame *sf, uint32_t version)
+{
+ __cilkrts_worker *w = __cilkrts_get_tls_worker();
+ if (w == 0) { /* slow path */
+ w = BIND_THREAD_RTN();
+
+ sf->flags = CILK_FRAME_LAST | (version << 24);
+ CILK_ASSERT((sf->flags & CILK_FRAME_FLAGS_MASK) == CILK_FRAME_LAST);
+ } else {
+ sf->flags = (version << 24);
+ CILK_ASSERT((sf->flags & CILK_FRAME_FLAGS_MASK) == 0);
+ }
+ sf->call_parent = w->current_stack_frame;
+ sf->worker = w;
+ w->current_stack_frame = sf;
+}
+
+CILK_ABI_VOID __cilkrts_enter_frame(__cilkrts_stack_frame *sf)
+{
+ enter_frame_internal(sf, 0);
+}
+
+CILK_ABI_VOID __cilkrts_enter_frame_1(__cilkrts_stack_frame *sf)
+{
+ enter_frame_internal(sf, 1);
+ sf->reserved = 0;
+}
+
+static inline
+void enter_frame_fast_internal(__cilkrts_stack_frame *sf, uint32_t version)
+{
+ __cilkrts_worker *w = __cilkrts_get_tls_worker_fast();
+ sf->flags = version << 24;
+ sf->call_parent = w->current_stack_frame;
+ sf->worker = w;
+ w->current_stack_frame = sf;
+}
+
+CILK_ABI_VOID __cilkrts_enter_frame_fast(__cilkrts_stack_frame *sf)
+{
+ enter_frame_fast_internal(sf, 0);
+}
+
+CILK_ABI_VOID __cilkrts_enter_frame_fast_1(__cilkrts_stack_frame *sf)
+{
+ enter_frame_fast_internal(sf, 1);
+ sf->reserved = 0;
+}
+
+/**
+ * A component of the THE protocol. __cilkrts_undo_detach checks whether
+ * this frame's parent has been stolen. If it hasn't, the frame can return
+ * normally. If the parent has been stolen, of if we suspect it might be,
+ * then __cilkrts_leave_frame() needs to call into the runtime.
+ *
+ * @note __cilkrts_undo_detach() is comparing the exception pointer against
+ * the tail pointer. The exception pointer is modified when another worker
+ * is considering whether it can steal a frame. The head pointer is updated
+ * to match when the worker lock is taken out and the thief is sure that
+ * it can complete the steal. If the steal cannot be completed, the thief
+ * will restore the exception pointer.
+ *
+ * @return true if undo-detach failed.
+ */
+static int __cilkrts_undo_detach(__cilkrts_stack_frame *sf)
+{
+ __cilkrts_worker *w = sf->worker;
+ __cilkrts_stack_frame *volatile *t = w->tail;
+
+/* DBGPRINTF("%d - __cilkrts_undo_detach - sf %p\n", w->self, sf); */
+
+ --t;
+ w->tail = t;
+ /* On x86 the __sync_fetch_and_<op> family includes a
+ full memory barrier. In theory the sequence in the
+ second branch of the #if should be faster, but on
+ most x86 it is not. */
+#if defined __i386__ || defined __x86_64__
+ __sync_fetch_and_and(&sf->flags, ~CILK_FRAME_DETACHED);
+#else
+ __cilkrts_fence(); /* membar #StoreLoad */
+ sf->flags &= ~CILK_FRAME_DETACHED;
+#endif
+
+ return __builtin_expect(t < w->exc, 0);
+}
+
+CILK_ABI_VOID __cilkrts_leave_frame(__cilkrts_stack_frame *sf)
+{
+ __cilkrts_worker *w = sf->worker;
+
+/* DBGPRINTF("%d-%p __cilkrts_leave_frame - sf %p, flags: %x\n", w->self, GetWorkerFiber(w), sf, sf->flags); */
+
+#ifdef _WIN32
+ /* if leave frame was called from our unwind handler, leave_frame should
+ proceed no further. */
+ if (sf->flags & CILK_FRAME_UNWINDING)
+ {
+/* DBGPRINTF("%d - __cilkrts_leave_frame - aborting due to UNWINDING flag\n", w->self); */
+
+ // If this is the frame of a spawn helper (indicated by the
+ // CILK_FRAME_DETACHED flag) we must update the pedigree. The pedigree
+ // points to nodes allocated on the stack. Failing to update it will
+ // result in a accvio/segfault if the pedigree is walked. This must happen
+ // for all spawn helper frames, even if we're processing an exception
+ if ((sf->flags & CILK_FRAME_DETACHED))
+ {
+ update_pedigree_on_leave_frame(w, sf);
+ }
+ return;
+ }
+#endif
+
+#if CILK_LIB_DEBUG
+ /* ensure the caller popped itself */
+ CILK_ASSERT(w->current_stack_frame != sf);
+#endif
+
+ /* The exiting function should have checked for zero flags,
+ so there is no check for flags == 0 here. */
+
+#if CILK_LIB_DEBUG
+ if (__builtin_expect(sf->flags & (CILK_FRAME_EXITING|CILK_FRAME_UNSYNCHED), 0))
+ __cilkrts_bug("W%u: function exiting with invalid flags %02x\n",
+ w->self, sf->flags);
+#endif
+
+ /* Must return normally if (1) the active function was called
+ and not spawned, or (2) the parent has never been stolen. */
+ if ((sf->flags & CILK_FRAME_DETACHED)) {
+/* DBGPRINTF("%d - __cilkrts_leave_frame - CILK_FRAME_DETACHED\n", w->self); */
+
+#ifndef _WIN32
+ if (__builtin_expect(sf->flags & CILK_FRAME_EXCEPTING, 0)) {
+// Pedigree will be updated in __cilkrts_leave_frame. We need the
+// pedigree before the update for record/replay
+// update_pedigree_on_leave_frame(w, sf);
+ __cilkrts_return_exception(sf);
+ /* If return_exception returns the caller is attached.
+ leave_frame is called from a cleanup (destructor)
+ for the frame object. The caller will reraise the
+ exception. */
+ return;
+ }
+#endif
+
+ // During replay, check whether w was the last worker to continue
+ replay_wait_for_steal_if_parent_was_stolen(w);
+
+ // Attempt to undo the detach
+ if (__builtin_expect(__cilkrts_undo_detach(sf), 0)) {
+ // The update of pedigree for leaving the frame occurs
+ // inside this call if it does not return.
+ __cilkrts_c_THE_exception_check(w, sf);
+ }
+
+ update_pedigree_on_leave_frame(w, sf);
+
+ /* This path is taken when undo-detach wins the race with stealing.
+ Otherwise this strand terminates and the caller will be resumed
+ via setjmp at sync. */
+ if (__builtin_expect(sf->flags & CILK_FRAME_FLAGS_MASK, 0))
+ __cilkrts_bug("W%u: frame won undo-detach race with flags %02x\n",
+ w->self, sf->flags);
+
+ return;
+ }
+
+#if CILK_LIB_DEBUG
+ sf->flags |= CILK_FRAME_EXITING;
+#endif
+
+ if (__builtin_expect(sf->flags & CILK_FRAME_LAST, 0))
+ __cilkrts_c_return_from_initial(w); /* does return */
+ else if (sf->flags & CILK_FRAME_STOLEN)
+ __cilkrts_return(w); /* does return */
+
+/* DBGPRINTF("%d-%p __cilkrts_leave_frame - returning, StackBase: %p\n", w->self, GetWorkerFiber(w)); */
+}
+
+/* Caller must have called setjmp. */
+CILK_ABI_VOID __cilkrts_sync(__cilkrts_stack_frame *sf)
+{
+ __cilkrts_worker *w = sf->worker;
+/* DBGPRINTF("%d-%p __cilkrts_sync - sf %p\n", w->self, GetWorkerFiber(w), sf); */
+ if (__builtin_expect(!(sf->flags & CILK_FRAME_UNSYNCHED), 0))
+ __cilkrts_bug("W%u: double sync %p\n", w->self, sf);
+#ifndef _WIN32
+ if (__builtin_expect(sf->flags & CILK_FRAME_EXCEPTING, 0)) {
+ __cilkrts_c_sync_except(w, sf);
+ }
+#endif
+
+ __cilkrts_c_sync(w, sf);
+}
+
+/*
+ * __cilkrts_get_sf
+ *
+ * Debugging aid to provide access to the current __cilkrts_stack_frame.
+ *
+ * Not documented!
+ */
+
+CILK_API_VOID_PTR
+__cilkrts_get_sf(void)
+{
+ __cilkrts_worker *w = __cilkrts_get_tls_worker();
+ if (0 == w)
+ return NULL;
+
+ return w->current_stack_frame;
+}
+
+/* Call with global lock held */
+static __cilkrts_worker *find_free_worker(global_state_t *g)
+{
+ __cilkrts_worker *w = 0;
+ int i;
+
+ // Scan the non-system workers looking for one which is free so we can
+ // use it.
+ for (i = g->P - 1; i < g->total_workers; ++i) {
+ w = g->workers[i];
+ CILK_ASSERT(WORKER_SYSTEM != w->l->type);
+ if (w->l->type == WORKER_FREE) {
+ w->l->type = WORKER_USER;
+ w->l->team = w;
+ return w;
+ }
+ }
+
+ // If we ran out of workers, create a new one. It doesn't actually belong
+ // to the Cilk global state so nobody will ever try to steal from it.
+ w = (__cilkrts_worker *)__cilkrts_malloc(sizeof(*w));
+ __cilkrts_cilkscreen_ignore_block(w, w+1);
+ make_worker(g, -1, w);
+ w->l->type = WORKER_USER;
+ w->l->team = w;
+ return w;
+}
+
+/*
+ * __cilkrts_bind_thread
+ *
+ * Exported function to bind a thread to the runtime.
+ *
+ * This function name should always have a trailing suffix for the latest ABI
+ * version. This means that code built with a new compiler will not load
+ * against an old copy of the runtime.
+ *
+ * Symbols for the function called by code compiled with old versions of the
+ * compiler are created in an OS-specific manner:
+ * - On Windows the old symbols are defined in the cilk-exports.def linker
+ * definitions file as aliases of BIND_THREAD_RTN
+ * - On Linux aliased symbols are created for BIND_THREAD_RTN in this file
+ * - On MacOS the alternate entrypoints are implemented and simply call
+ * BIND_THREAD_RTN.
+ */
+CILK_ABI_WORKER_PTR BIND_THREAD_RTN(void)
+{
+ __cilkrts_worker *w;
+ int start_cilkscreen = 0;
+#ifdef USE_ITTNOTIFY
+ static int unique_obj;
+#endif
+
+ // Cannot set this pointer until after __cilkrts_init_internal() call:
+ global_state_t* g;
+
+ ITT_SYNC_CREATE (&unique_obj, "Initialization");
+ ITT_SYNC_PREPARE(&unique_obj);
+ ITT_SYNC_ACQUIRED(&unique_obj);
+
+
+ /* 1: Initialize and start the Cilk runtime */
+ __cilkrts_init_internal(1);
+
+ /*
+ * 2: Choose a worker for this thread (fail if none left). The table of
+ * user workers is protected by the global OS mutex lock.
+ */
+ g = cilkg_get_global_state();
+ global_os_mutex_lock();
+ if (__builtin_expect(g->work_done, 0))
+ __cilkrts_bug("Attempt to enter Cilk while Cilk is shutting down");
+ w = find_free_worker(g);
+ CILK_ASSERT(w);
+
+ __cilkrts_set_tls_worker(w);
+ __cilkrts_cilkscreen_establish_worker(w);
+ {
+ full_frame *ff = __cilkrts_make_full_frame(w, 0);
+
+ ff->fiber_self = cilk_fiber_allocate_from_thread();
+ CILK_ASSERT(ff->fiber_self);
+
+ cilk_fiber_set_owner(ff->fiber_self, w);
+ cilk_fiber_tbb_interop_use_saved_stack_op_info(ff->fiber_self);
+
+ CILK_ASSERT(ff->join_counter == 0);
+ ff->join_counter = 1;
+ w->l->frame_ff = ff;
+ w->reducer_map = __cilkrts_make_reducer_map(w);
+ __cilkrts_set_leftmost_reducer_map(w->reducer_map, 1);
+ load_pedigree_leaf_into_user_worker(w);
+ }
+
+ // Make sure that the head and tail are reset, and saved_protected_tail
+ // allows all frames to be stolen.
+ //
+ // Note that we must NOT check w->exc, since workers that are trying to
+ // steal from it will be updating w->exc and we don't own the worker lock.
+ // It's not worth taking out the lock just for an assertion.
+ CILK_ASSERT(w->head == w->l->ltq);
+ CILK_ASSERT(w->tail == w->l->ltq);
+ CILK_ASSERT(w->protected_tail == w->ltq_limit);
+
+ // There may have been an old pending exception which was freed when the
+ // exception was caught outside of Cilk
+ w->l->pending_exception = NULL;
+
+ w->reserved = NULL;
+
+ // If we've already created a scheduling fiber for this worker, we'll just
+ // reuse it. If w->self < 0, it means that this is an ad-hoc user worker
+ // not known to the global state. Thus, we need to create a scheduling
+ // stack only if we don't already have one and w->self >= 0.
+ if (NULL == w->l->scheduling_fiber && w->self >= 0)
+ {
+ START_INTERVAL(w, INTERVAL_FIBER_ALLOCATE) {
+ // Create a scheduling fiber for this worker.
+ w->l->scheduling_fiber =
+ cilk_fiber_allocate_from_heap(CILK_SCHEDULING_STACK_SIZE);
+ cilk_fiber_reset_state(w->l->scheduling_fiber,
+ scheduler_fiber_proc_for_user_worker);
+ cilk_fiber_set_owner(w->l->scheduling_fiber, w);
+ } STOP_INTERVAL(w, INTERVAL_FIBER_ALLOCATE);
+ }
+
+ // If the scheduling fiber is NULL, we've either exceeded our quota for
+ // fibers or workers or we're out of memory, so we should lose parallelism
+ // by disallowing stealing.
+ if (NULL == w->l->scheduling_fiber)
+ __cilkrts_disallow_stealing(w, NULL);
+
+ start_cilkscreen = (0 == w->g->Q);
+
+ if (w->self != -1) {
+ // w->self != -1, means that w is a normal user worker and must be
+ // accounted for by the global state since other workers can steal from
+ // it.
+
+ // w->self == -1, means that w is an overflow worker and was created on
+ // demand. I.e., it does not need to be accounted for by the global
+ // state.
+
+ __cilkrts_enter_cilk(w->g);
+ }
+
+ global_os_mutex_unlock();
+
+ /* If there's only 1 worker, the counts will be started in
+ * __cilkrts_scheduler */
+ if (g->P > 1)
+ {
+ START_INTERVAL(w, INTERVAL_IN_SCHEDULER);
+ START_INTERVAL(w, INTERVAL_WORKING);
+ }
+
+ ITT_SYNC_RELEASING(&unique_obj);
+
+ /* Turn on Cilkscreen if this is the first worker. This needs to be done
+ * when we are NOT holding the os mutex. */
+ if (start_cilkscreen)
+ __cilkrts_cilkscreen_enable_instrumentation();
+
+ return w;
+}
+
+#ifndef _MSC_VER
+/*
+ * Define old version-specific symbols for binding threads (since they exist in
+ * all Cilk code). These aliases prohibit newly compiled code from loading an
+ * old version of the runtime. We can handle old code with a new runtime, but
+ * new code with an old runtime is verboten!
+ *
+ * For Windows, the aliased symbol is exported in cilk-exports.def.
+ */
+#if defined(_DARWIN_C_SOURCE) || defined(__APPLE__)
+/**
+ * Mac OS X: Unfortunately, Darwin doesn't allow aliasing, so we just make a
+ * call and hope the optimizer does the right thing.
+ */
+CILK_ABI_WORKER_PTR __cilkrts_bind_thread (void) {
+ return BIND_THREAD_RTN();
+}
+#else
+
+/**
+ * Macro to convert a parameter to a string. Used on Linux or BSD.
+ */
+#define STRINGIFY(x) #x
+
+/**
+ * Macro to generate an __attribute__ for an aliased name
+ */
+#define ALIASED_NAME(x) __attribute__ ((alias (STRINGIFY(x))))
+
+/**
+ * Linux or BSD: Use the alias attribute to make the labels for the versioned
+ * functions point to the same place in the code as the original. Using
+ * the two macros is annoying but required.
+ */
+
+CILK_ABI_WORKER_PTR __cilkrts_bind_thread(void)
+ ALIASED_NAME(BIND_THREAD_RTN);
+
+#endif // defined _DARWIN_C_SOURCE || defined __APPLE__
+#endif // !defined _MSC_VER
+
+CILK_API_SIZET
+__cilkrts_get_stack_size(void) {
+ return cilkg_get_stack_size();
+}
+
+// Method for debugging.
+CILK_API_VOID __cilkrts_dump_stats(void)
+{
+ // While the stats aren't protected by the global OS mutex, the table
+ // of workers is, so take out the global OS mutex while we're doing this
+ global_os_mutex_lock();
+ if (cilkg_is_published()) {
+ global_state_t *g = cilkg_get_global_state();
+ __cilkrts_dump_stats_to_stderr(g);
+ }
+ else {
+ __cilkrts_bug("Attempting to report Cilk stats before the runtime has started\n");
+ }
+ global_os_mutex_unlock();
+}
+
+#ifndef _WIN32
+CILK_ABI_THROWS_VOID __cilkrts_rethrow(__cilkrts_stack_frame *sf)
+{
+ __cilkrts_gcc_rethrow(sf);
+}
+#endif
+
+/*
+ * __cilkrts_unwatch_stack
+ *
+ * Callback for TBB to tell us they don't want to watch the stack anymore
+ */
+
+static __cilk_tbb_retcode __cilkrts_unwatch_stack(void *data)
+{
+ __cilk_tbb_stack_op_thunk o;
+
+ // If the cilk_fiber wasn't available fetch it now
+ if (TBB_INTEROP_DATA_DELAYED_UNTIL_BIND == data)
+ {
+ full_frame *ff;
+ __cilkrts_worker *w = __cilkrts_get_tls_worker();
+ if (NULL == w)
+ {
+ // Free any saved stack op information
+ cilk_fiber_tbb_interop_free_stack_op_info();
+
+ return 0; /* Success! */
+ }
+
+ __cilkrts_worker_lock(w);
+ ff = w->l->frame_ff;
+ __cilkrts_frame_lock(w,ff);
+ data = ff->fiber_self;
+ __cilkrts_frame_unlock(w,ff);
+ __cilkrts_worker_unlock(w);
+ }
+
+#if CILK_LIB_DEBUG /* Debug code */
+ /* Get current stack */
+ full_frame *ff;
+ __cilkrts_worker *w = __cilkrts_get_tls_worker();
+ __cilkrts_worker_lock(w);
+ ff = w->l->frame_ff;
+ __cilkrts_frame_lock(w,ff);
+ CILK_ASSERT (data == ff->fiber_self);
+ __cilkrts_frame_unlock(w,ff);
+ __cilkrts_worker_unlock(w);
+#endif
+
+ /* Clear the callback information */
+ o.data = NULL;
+ o.routine = NULL;
+ cilk_fiber_set_stack_op((cilk_fiber*)data, o);
+
+ // Note. Do *NOT* free any saved stack information here. If they want to
+ // free the saved stack op information, they'll do it when the thread is
+ // unbound
+
+ return 0; /* Success! */
+}
+
+/*
+ * __cilkrts_watch_stack
+ *
+ * Called by TBB, defined by Cilk.
+ *
+ * Requests that Cilk invoke the stack op routine when it orphans a stack.
+ * Cilk sets *u to a thunk that TBB should call when it is no longer interested
+ * in watching the stack.
+ */
+
+CILK_API_TBB_RETCODE
+__cilkrts_watch_stack(__cilk_tbb_unwatch_thunk *u,
+ __cilk_tbb_stack_op_thunk o)
+{
+ cilk_fiber* current_fiber;
+ __cilkrts_worker *w;
+
+#ifdef _MSC_VER
+ // This may be called by TBB *before* the OS has given us our
+ // initialization call. Make sure the module is initialized.
+ sysdep_init_module();
+#endif
+
+ // Fetch the __cilkrts_worker bound to this thread
+ w = __cilkrts_get_tls_worker();
+ if (NULL == w)
+ {
+ // Save data for later. We'll deal with it when/if this thread binds
+ // to the runtime
+ cilk_fiber_tbb_interop_save_stack_op_info(o);
+
+ u->routine = __cilkrts_unwatch_stack;
+ u->data = TBB_INTEROP_DATA_DELAYED_UNTIL_BIND;
+
+ return 0;
+ }
+
+ /* Get current stack */
+ __cilkrts_worker_lock(w);
+ current_fiber = w->l->frame_ff->fiber_self;
+ __cilkrts_worker_unlock(w);
+
+/* CILK_ASSERT( !sd->stack_op_data ); */
+/* CILK_ASSERT( !sd->stack_op_routine ); */
+
+ /* Give TBB our callback */
+ u->routine = __cilkrts_unwatch_stack;
+ u->data = current_fiber;
+ /* Save the callback information */
+ cilk_fiber_set_stack_op(current_fiber, o);
+
+ return 0; /* Success! */
+}
+
+
+// This function must be called only within a continuation, within the stack
+// frame of the continuation itself.
+CILK_API_INT __cilkrts_synched(void)
+{
+ __cilkrts_worker *w = __cilkrts_get_tls_worker();
+
+ // If we don't have a worker, then we're synched by definition :o)
+ if (NULL == w)
+ return 1;
+
+ // Check to see if we are in a stolen continuation. If not, then
+ // we are synched.
+ uint32_t flags = w->current_stack_frame->flags;
+ if (0 == (flags & CILK_FRAME_UNSYNCHED))
+ return 1;
+
+ // We are in a stolen continutation, but the join counter might have been
+ // decremented to one, making us synched again. Get the full frame so
+ // that we can check the join counter. ASSUME: frame_ff is stable (can be
+ // read without a lock) in a stolen continuation -- it can't be stolen
+ // while it's currently executing.
+ full_frame *ff = w->l->frame_ff;
+
+ // Make sure we have a full frame
+ // TBD: Don't think that we should ever not have a full frame here.
+ // CILK_ASSERT(NULL != ff); ?
+ if (NULL == ff)
+ return 1;
+
+ // We're synched if there are no outstanding children at this instant in
+ // time. Note that this is a known race, but it's ok since we're only
+ // reading. We can get false negatives, but not false positives. (I.e.,
+ // we can read a non-one join_counter just before it goes to one, but the
+ // join_counter cannot go from one to greater than one while we're
+ // reading.)
+ return 1 == ff->join_counter;
+}
+
+
+
+
+CILK_API_INT
+__cilkrts_bump_loop_rank_internal(__cilkrts_worker* w)
+{
+ // If we don't have a worker, then the runtime is not bound to this
+ // thread and there is no rank to increment
+ if (NULL == w)
+ return -1;
+
+ // We're at the start of the loop body. Advance the cilk_for loop
+ // body pedigree by following the parent link and updating its
+ // rank.
+
+ // Normally, we'd just write "w->pedigree.parent->rank++"
+ // But we need to cast away the "const".
+ ((__cilkrts_pedigree*) w->pedigree.parent)->rank++;
+
+ // Zero the worker's pedigree rank since this is the start of a new
+ // pedigree domain.
+ w->pedigree.rank = 0;
+
+ return 0;
+}
+
+CILK_ABI_VOID
+__cilkrts_save_fp_ctrl_state(__cilkrts_stack_frame *sf)
+{
+ // Pass call onto OS/architecture dependent function
+ sysdep_save_fp_ctrl_state(sf);
+}
+
+/* end cilk-abi.c */
diff --git a/libcilkrts/runtime/cilk-ittnotify.h b/libcilkrts/runtime/cilk-ittnotify.h
new file mode 100644
index 00000000000..ff995db6fbb
--- /dev/null
+++ b/libcilkrts/runtime/cilk-ittnotify.h
@@ -0,0 +1,100 @@
+/* cilk-ittnotify.h -*-C++-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ **************************************************************************/
+
+#ifndef INCLUDED_CILK_ITTNOTIFY_DOT_H
+#define INCLUDED_CILK_ITTNOTIFY_DOT_H
+
+#ifdef __INTEL_COMPILER
+#endif
+#include <stdio.h>
+
+// ITTNOTIFY does not support ARM at this time
+#ifdef __arm__
+#undef USE_ITTNOTIFY
+#endif
+
+#ifdef USE_ITTNOTIFY
+#include <ittnotify.h>
+
+#ifdef _WIN32
+# define ITT_SYNC_CREATE(_address, _description) \
+ __itt_sync_createA(_address, \
+ "Intel Cilk Plus " _description, \
+ "", \
+ __itt_attr_barrier)
+#else
+# define ITT_SYNC_CREATE(_address, _description) \
+ __itt_sync_create(_address, \
+ "Intel Cilk Plus " _description, \
+ "", \
+ __itt_attr_barrier)
+#endif
+
+#define ITT_SYNC_PREPARE(_address) __itt_sync_prepare(_address)
+#define ITT_SYNC_ACQUIRED(_address) __itt_sync_acquired(_address)
+#define ITT_SYNC_RELEASING(_address) __itt_sync_releasing(_address)
+#define ITT_SYNC_DESTROY(_address) __itt_sync_destroy(_address)
+// Note that we subtract 5 from the return address to find the CALL instruction
+// to __cilkrts_sync
+#if 1 // Disable renaming for now. Piersol isn't ready yet
+#define ITT_SYNC_SET_NAME_AND_PREPARE(_address, _sync_ret_address) __itt_sync_prepare(_address)
+#else
+#define ITT_SYNC_SET_NAME_AND_PREPARE(_address, _sync_ret_address) \
+ if (NULL != __itt_sync_prepare_ptr) { \
+ if (0 == _sync_ret_address) \
+ __itt_sync_renameA(_address, ""); \
+ else \
+ { \
+ char buf[128]; \
+ sprintf_s(buf, 128, "IP:0x%p", (DWORD_PTR)_sync_ret_address - 5); \
+ __itt_sync_renameA(_address, buf); \
+ _sync_ret_address = 0; \
+ } \
+ __itt_sync_prepare(_address); \
+ }
+#endif
+#else // USE_ITTNOTIFY not defined, compile out all calls
+#define ITT_SYNC_CREATE(_address, _description)
+#define ITT_SYNC_PREPARE(_address)
+#define ITT_SYNC_ACQUIRED(_address)
+#define ITT_SYNC_RELEASING(_addresss)
+#define ITT_SYNC_DESTROY(_address)
+#define ITT_SYNC_SET_NAME_AND_PREPARE(_sync_address, _wait_address)
+#endif
+
+#endif // ! defined(INCLUDED_CILK_ITTNOTIFY_DOT_H)
diff --git a/libcilkrts/runtime/cilk-tbb-interop.h b/libcilkrts/runtime/cilk-tbb-interop.h
new file mode 100644
index 00000000000..cc5cff4b57e
--- /dev/null
+++ b/libcilkrts/runtime/cilk-tbb-interop.h
@@ -0,0 +1,192 @@
+/* cilk-tbb-interop.h -*-C++-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ **************************************************************************/
+
+/**
+ * @file cilk-tbb-interop.h
+ *
+ * @brief Interface between TBB and Cilk to allow TBB to associate it's
+ * per-thread data with Cilk workers, and maintain the association as work
+ * moves between worker threads. This handles the case where TBB calls
+ * into a Cilk function which may later call back to a function making
+ * TBB calls.
+ *
+ * Each thunk structure has two pointers: \"routine\" and \"data\".
+ * The caller of the thunk invokes *routine, passing \"data\" as the void*
+ * parameter.
+ */
+
+#ifndef INCLUDED_CILK_TBB_INTEROP_DOT_H
+#define INCLUDED_CILK_TBB_INTEROP_DOT_H
+
+#include <cilk/common.h> // for CILK_EXPORT
+
+__CILKRTS_BEGIN_EXTERN_C
+
+/** A return code. 0 indicates success. */
+typedef int __cilk_tbb_retcode;
+
+/**
+ * Enumeration of reasons that Cilk will call the TBB stack operation
+ * function.
+ *
+ * When a non-empty stack is transfered between threads, the first thread must
+ * orphan it and the second thread must adopt it.
+ *
+ * An empty stack can be transfered similarly, or simply released by the first
+ * thread.
+ *
+ * Here is a summary of the actions as transitions on a state machine.
+@verbatim
+ watch ORPHAN
+ -->--> -->--
+ / \ / \
+ (freed empty stack) (TBB sees stack running on thread) (stack in limbo)
+ \ / \ /
+ --<-- --<--
+ RELEASE or ADOPT
+ unwatch
+@endverbatim
+ */
+typedef enum __cilk_tbb_stack_op {
+ /**
+ * Disconnecting stack from a thread.
+ *
+ * The thunk must be invoked on the thread disconnecting itself from the
+ * stack. Must \"happen before\" the stack is adopted elsewhere.
+ */
+ CILK_TBB_STACK_ORPHAN,
+
+ /**
+ * Reconnecting orphaned stack to a thread.
+ *
+ * The thunk must be invoked on the thread adopting the stack.
+ */
+ CILK_TBB_STACK_ADOPT,
+
+ /**
+ * Releasing stack.
+ *
+ * The thunk must be invoked on the thread doing the releasing, Must
+ * \"happen before\" the stack is used elsewhere.
+ */
+ CILK_TBB_STACK_RELEASE
+} __cilk_tbb_stack_op;
+
+/**
+ * Function that will be called by the Cilk runtime to inform TBB of a change
+ * in the stack associated with the current thread.
+ *
+ * It does not matter what stack the thunk runs on.
+ * The thread (not fiber) on which the thunk runs is important.
+ *
+ * @param op Enumerated value indicating what type of change is ocurring.
+ * @param data Context value provided by TBB in the __cilkrts_watch_stack
+ * call. This data is opaque to Cilk.
+ *
+ * @return 0 indicates success.
+ */
+typedef __cilk_tbb_retcode (*__cilk_tbb_pfn_stack_op)(enum __cilk_tbb_stack_op op,
+ void* data);
+
+/**
+ * Function that will be called by TBB to inform the Cilk runtime that TBB
+ * is no longer interested in watching the stack bound to the current thread.
+ *
+ * @param data Context value provided to TBB by the __cilkrts_watch_stack
+ * call. This data is opaque to TBB.
+ *
+ * @return 0 indicates success.
+ */
+typedef __cilk_tbb_retcode (*__cilk_tbb_pfn_unwatch_stacks)(void *data);
+
+/**
+ * Thunk invoked by Cilk to call back to TBB to tell it about a change in
+ * the stack bound to the current thread.
+ */
+typedef struct __cilk_tbb_stack_op_thunk {
+ /// Function in TBB the Cilk runtime should call when something
+ // "interesting" happens involving a stack
+ __cilk_tbb_pfn_stack_op routine;
+
+ /// TBB context data to pass with the call to the stack_op routine
+ void* data;
+} __cilk_tbb_stack_op_thunk;
+
+/**
+ * Thunk invoked by TBB when it is no longer interested in watching the stack
+ * bound to the current thread.
+ */
+typedef struct __cilk_tbb_unwatch_thunk {
+ /// Function in Cilk runtime to call when TBB no longer wants to watch
+ // stacks
+ __cilk_tbb_pfn_unwatch_stacks routine;
+
+ /// Cilk runtime context data to pass with the call to the unwatch_stacks
+ /// routine
+ void* data;
+} __cilk_tbb_unwatch_thunk;
+
+/**
+ * Requests that Cilk invoke __cilk_tbb_orphan_thunk when it orphans a stack.
+ * Cilk sets *u to a thunk that TBB should call when it is no longer
+ * interested in watching the stack.
+ *
+ * If the thread is not yet bound to the Cilk runtime, the Cilk runtime should
+ * save this data in thread-local storage until __cilkrts_bind_thread is called.
+ *
+ * Called by TBB, defined by Cilk. This function is exported from the Cilk
+ * runtime DLL/shared object. This declaration also appears in
+ * cilk/cilk_undocumented.h -- don't change one declaration without also
+ * changing the other.
+ *
+ * @param u __cilk_tbb_unwatch_thunk. This structure will be filled in by
+ * the Cilk runtime to allow TBB to register that it is no longer interested
+ * in watching the stack bound to the current thread.
+ * @param o __cilk_tbb_stack_op_thunk. This structure specifies the routine
+ * that the Cilk runtime should call when an "interesting" change in the stack
+ * associate with the current worker occurs.
+ *
+ * @return 0 indicates success.
+ */
+CILK_EXPORT
+__cilk_tbb_retcode __cilkrts_watch_stack(__cilk_tbb_unwatch_thunk* u,
+ __cilk_tbb_stack_op_thunk o);
+
+__CILKRTS_END_EXTERN_C
+
+#endif // ! defined(INCLUDED_CILK_TBB_INTEROP_DOT_H)
diff --git a/libcilkrts/runtime/cilk_api.c b/libcilkrts/runtime/cilk_api.c
new file mode 100644
index 00000000000..bbca984bc03
--- /dev/null
+++ b/libcilkrts/runtime/cilk_api.c
@@ -0,0 +1,255 @@
+/* cilk_api.c -*-C-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ **************************************************************************/
+
+/*
+ * Implementation of functions declared in cilk_api.h
+ */
+
+/*
+ * Define the COMPILING_CILK_ABI_FUNCTIONS macro, so that
+ * compilation of this file generates non-inlined definitions for the
+ * functions marked as CILK_EXPORT_AND_INLINE in cilk_api.h.
+ *
+ * We must deal with these functions differently because we need to
+ * continue to ship nonlined versions of these functions.
+ *
+ * CILK_EXPORT_AND_INLINE int __cilkrts_get_worker_rank(uint64_t *rank);
+ * CILK_EXPORT_AND_INLINE int __cilkrts_bump_worker_rank();
+ * CILK_EXPORT_AND_INLINE int __cilkrts_bump_loop_rank();
+ */
+#define COMPILING_CILK_API_FUNCTIONS
+
+#include <internal/abi.h>
+#include <cilk/cilk_api.h>
+
+#include "os.h"
+#include "os_mutex.h"
+#include "bug.h"
+#include "global_state.h"
+#include "local_state.h"
+#include "scheduler.h"
+#include "sysdep.h"
+
+CILK_API_VOID __cilkrts_init(void)
+{
+ // Initialize, but don't start, the cilk runtime.
+ __cilkrts_init_internal(0);
+}
+
+CILK_API_VOID __cilkrts_end_cilk(void)
+{
+ // Take out the global OS mutex while we do this to protect against
+ // another thread attempting to bind while we do this
+ global_os_mutex_lock();
+
+ if (cilkg_is_published()) {
+ global_state_t *g = cilkg_get_global_state();
+ if (g->Q || __cilkrts_get_tls_worker())
+ __cilkrts_bug("Attempt to shut down Cilk while Cilk is still "
+ "running");
+ __cilkrts_stop_workers(g);
+ __cilkrts_deinit_internal(g);
+ }
+
+ global_os_mutex_unlock();
+}
+
+CILK_API_INT
+__cilkrts_get_nworkers()
+{
+ return cilkg_get_nworkers();
+}
+
+CILK_API_INT
+__cilkrts_get_total_workers()
+{
+ return cilkg_get_total_workers();
+}
+
+CILK_API_INT __cilkrts_get_force_reduce(void)
+{
+ return cilkg_get_force_reduce();
+}
+
+CILK_API_INT __cilkrts_set_param(const char* param, const char* value)
+{
+ return cilkg_set_param(param, value);
+}
+
+#ifdef _WIN32
+CILK_API_INT __cilkrts_set_param_w(const wchar_t* param, const wchar_t* value)
+{
+ return cilkg_set_param_w(param, value);
+}
+#endif // _WIN32
+
+/* Return a small integer indicating which Cilk worker the function is
+ * currently running on. Each thread started by the Cilk runtime library
+ * (system worker) has a unique worker number in the range 1..P-1, where P is
+ * the valued returned by __cilkrts_get_nworkers(). All threads started by
+ * the user or by other libraries (user workers) share the worker number 0.
+ * Therefore, the worker number is not unique across multiple user threads.
+ *
+ * Implementor's note: The value returned from this function is different from
+ * the value, w->self, used in most debug messages.
+ */
+CILK_API_INT
+__cilkrts_get_worker_number(void)
+{
+ __cilkrts_worker *w = __cilkrts_get_tls_worker();
+
+ if (0 == w)
+ /* A non-worker always has a worker number of zero. */
+ return 0;
+ else if (WORKER_USER == w->l->type)
+ /* User worker was once a non-worker, so its number should still be
+ * zero. */
+ return 0;
+ else
+ /* w->self for a system worker is in range 0..(P-1); adjust to 1..P
+ * to avoid conflicting with the user thread's worker number. */
+ return w->self + 1;
+}
+
+/**
+ * Internal definition of the pedigree context. The size of the
+ * structure must match __cilkrts_pedigree_context_t defined in abi.i
+ */
+typedef struct pedigree_context_t
+{
+ /** Size of the structure, in bytes */
+ size_t size;
+
+ /** Next __cilkrts_pedigree to return */
+ const __cilkrts_pedigree *pedigree;
+
+ /** Unused. Left over from previous implementation */
+ void *unused1;
+
+ /** Unused. Left over from previous implementation */
+ void *unused2;
+
+ // // Debugging aid for pedigree-test:
+ // __cilkrts_stack_frame *expected_sf;
+} pedigree_context_t;
+
+/*
+ * __cilkrts_get_pedigree_info
+ *
+ * Fetch the birthrank for a stack frame. To initialize the walk, both sf_in
+ * and frame_in should be NULL. parent_sf_ptr and parent_frame_ptr provide
+ * context for the stackwalk and should be returned as sf_in and frame_in on
+ * the next call.
+ *
+ * Returns:
+ * 0 - Success - birthrank, parent_sf_out and parent_frame_out are valid
+ * >1 - Pedigree walk completed
+ * <1 - Failure - -1: No worker bound to thread, -2: Sanity check failed
+ */
+
+#define PEDIGREE_WALK_COMPLETE (__cilkrts_pedigree *)-1
+
+CILK_API_INT
+__cilkrts_get_pedigree_info(__cilkrts_pedigree_context_t *external_context,
+ uint64_t *sf_birthrank)
+{
+ pedigree_context_t *context = (pedigree_context_t *)external_context;
+
+ CILK_ASSERT(sizeof(__cilkrts_pedigree_context_t) ==
+ sizeof(pedigree_context_t));
+ if (context->size != sizeof(pedigree_context_t))
+ return -3; // Invalid size
+
+ // If the pointer to the last __cilkrts_pedigree is -1, we've
+ // finished the walk. We're still done.
+ if (PEDIGREE_WALK_COMPLETE == context->pedigree)
+ return 1;
+
+ // The passed in context value contains a pointer to the last
+ // __cilkrts_pedigree returned, or NULL if we're starting a
+ // new walk
+ if (NULL == context->pedigree)
+ {
+ __cilkrts_worker *w = __cilkrts_get_tls_worker();
+ __cilkrts_pedigree* pedigree_node;
+ if (NULL != w) {
+ pedigree_node = &w->pedigree;
+ }
+ else {
+ pedigree_node = __cilkrts_get_tls_pedigree_leaf(1);
+ }
+ context->pedigree = pedigree_node->parent;
+ }
+ else
+ context->pedigree = context->pedigree->parent;
+
+ // Note: If we want to omit the user root node,
+ // stop at context->pedigree->parent instead.
+ if (NULL == context->pedigree)
+ {
+ context->pedigree = PEDIGREE_WALK_COMPLETE;
+ return 1;
+ }
+
+ *sf_birthrank = context->pedigree->rank;
+ return 0;
+}
+
+CILK_API_PEDIGREE
+__cilkrts_get_pedigree_internal(__cilkrts_worker *w)
+{
+ if (NULL != w) {
+ return w->pedigree;
+ }
+ else {
+ const __cilkrts_pedigree *pedigree =
+ __cilkrts_get_tls_pedigree_leaf(1);
+ return *pedigree;
+ }
+}
+
+
+CILK_API_INT __cilkrts_bump_worker_rank_internal(__cilkrts_worker *w)
+{
+ __cilkrts_pedigree *pedigree;
+ pedigree = (w ? &w->pedigree : __cilkrts_get_tls_pedigree_leaf(1));
+ pedigree->rank++;
+ return 0;
+}
+
+/* End cilk_api.c */
diff --git a/libcilkrts/runtime/cilk_fiber-unix.cpp b/libcilkrts/runtime/cilk_fiber-unix.cpp
new file mode 100644
index 00000000000..b0ed53ad052
--- /dev/null
+++ b/libcilkrts/runtime/cilk_fiber-unix.cpp
@@ -0,0 +1,301 @@
+/* cilk_fiber-unix.cpp -*-C++-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2012-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ **************************************************************************/
+
+#include "cilk_fiber-unix.h"
+#include "cilk_malloc.h"
+#include "bug.h"
+#include "os.h"
+
+#include <cstdio>
+#include <cstdlib>
+
+#include <errno.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+// You'd think that getting a defintion for alloca would be easy. But you'd
+// be wrong. Here's a variant on what's recommended in the autoconf doc. I've
+// remove the Windows portion since this is Unix-specific code.
+#if defined HAVE_ALLOCA_H
+# include <alloca.h>
+#elif defined __GNUC__
+# define alloca __builtin_alloca
+#elif defined _AIX
+# define alloca __alloca
+#else
+# include <stddef.h>
+# ifdef __cplusplus
+extern "C"
+# endif
+void *alloca (size_t);
+#endif
+
+// MAP_ANON is deprecated on Linux, but seems to be required on Mac...
+#ifndef MAP_ANONYMOUS
+#define MAP_ANONYMOUS MAP_ANON
+#endif
+
+// Magic number for sanity checking fiber structure
+const unsigned magic_number = 0x5afef00d;
+
+int cilk_fiber_sysdep::s_page_size = getpagesize();
+
+cilk_fiber_sysdep::cilk_fiber_sysdep(std::size_t stack_size)
+ : cilk_fiber(stack_size)
+ , m_magic(magic_number)
+{
+ // Set m_stack and m_stack_base.
+ make_stack(stack_size);
+
+ // Get high-address of stack, with 32-bytes of spare space, and rounded
+ // down to the nearest 32-byte boundary.
+ const uintptr_t align_mask = 32 - 1;
+ m_stack_base -= ((std::size_t) m_stack_base) & align_mask;
+}
+
+cilk_fiber_sysdep::cilk_fiber_sysdep(from_thread_t)
+ : cilk_fiber()
+ , m_magic(magic_number)
+{
+ this->set_allocated_from_thread(true);
+
+ // Dummy stack data for thread-main fiber
+ m_stack = NULL;
+ m_stack_base = NULL;
+}
+
+void cilk_fiber_sysdep::convert_fiber_back_to_thread()
+{
+ // Does nothing on Linux.
+}
+
+cilk_fiber_sysdep::~cilk_fiber_sysdep()
+{
+ CILK_ASSERT(magic_number == m_magic);
+ if (!this->is_allocated_from_thread())
+ free_stack();
+}
+
+#if SUPPORT_GET_CURRENT_FIBER
+cilk_fiber_sysdep* cilk_fiber_sysdep::get_current_fiber_sysdep()
+{
+ return cilkos_get_tls_cilk_fiber();
+}
+#endif
+
+// Jump to resume other fiber. We may or may not come back.
+inline void cilk_fiber_sysdep::resume_other_sysdep(cilk_fiber_sysdep* other)
+{
+ if (other->is_resumable()) {
+ other->set_resumable(false);
+ // Resume by longjmp'ing to the place where we suspended.
+ CILK_LONGJMP(other->m_resume_jmpbuf);
+ }
+ else {
+ // Otherwise, we've never ran this fiber before. Start the
+ // proc method.
+ other->run();
+ }
+}
+
+void cilk_fiber_sysdep::suspend_self_and_resume_other_sysdep(cilk_fiber_sysdep* other)
+{
+#if SUPPORT_GET_CURRENT_FIBER
+ cilkos_set_tls_cilk_fiber(other);
+#endif
+ CILK_ASSERT(this->is_resumable());
+
+
+ // Jump to the other fiber. We expect to come back.
+ if (! CILK_SETJMP(m_resume_jmpbuf)) {
+ resume_other_sysdep(other);
+ }
+
+ // Return here when another fiber resumes me.
+ // If the fiber that switched to me wants to be deallocated, do it now.
+ do_post_switch_actions();
+}
+
+NORETURN cilk_fiber_sysdep::jump_to_resume_other_sysdep(cilk_fiber_sysdep* other)
+{
+#if SUPPORT_GET_CURRENT_FIBER
+ cilkos_set_tls_cilk_fiber(other);
+#endif
+ CILK_ASSERT(!this->is_resumable());
+
+ // Jump to the other fiber. But we are never coming back because
+ // this fiber is being reset.
+ resume_other_sysdep(other);
+
+ // We should never come back here...
+ __cilkrts_bug("Should not get here");
+}
+
+// GCC doesn't allow us to call __builtin_longjmp in the same function that
+// calls __builtin_setjmp, so create a new function to house the call to
+// __builtin_longjmp
+static void __attribute__((noinline))
+do_cilk_longjmp(__CILK_JUMP_BUFFER jmpbuf)
+{
+ CILK_LONGJMP(jmpbuf);
+}
+
+NORETURN cilk_fiber_sysdep::run()
+{
+ // Only fibers created from a pool have a proc method to run and execute.
+ CILK_ASSERT(m_start_proc);
+ CILK_ASSERT(!this->is_allocated_from_thread());
+ CILK_ASSERT(!this->is_resumable());
+
+ // TBD: This setjmp/longjmp pair simply changes the stack pointer.
+ // We could probably replace this code with some assembly.
+ if (! CILK_SETJMP(m_resume_jmpbuf))
+ {
+ // Calculate the size of the current stack frame (i.e., this
+ // run() function.
+ size_t frame_size = (size_t)JMPBUF_FP(m_resume_jmpbuf) - (size_t)JMPBUF_SP(m_resume_jmpbuf);
+
+ // Macs require 16-byte alignment. Do it always because it just
+ // doesn't matter
+ if (frame_size & (16-1))
+ frame_size += 16 - (frame_size & (16-1));
+
+ // Assert that we are getting a reasonable frame size out of
+ // it. If this run() function is using more than 4096 bytes
+ // of space for its local variables / any state that spills to
+ // registers, something is probably *very* wrong here...
+ //
+ // 4096 bytes just happens to be a number that seems "large
+ // enough" --- for an example GCC 32-bit compilation, the
+ // frame size was 48 bytes.
+ CILK_ASSERT(frame_size < 4096);
+
+ // Change stack pointer to fiber stack. Offset the
+ // calculation by the frame size, so that we've allocated
+ // enough extra space from the top of the stack we are
+ // switching to for any temporaries required for this run()
+ // function.
+ JMPBUF_SP(m_resume_jmpbuf) = m_stack_base - frame_size;
+
+ // GCC doesn't allow us to call __builtin_longjmp in the same function
+ // that calls __builtin_setjmp, so it's been moved into it's own
+ // function that cannot be inlined.
+ do_cilk_longjmp(m_resume_jmpbuf);
+ }
+
+ // Note: our resetting of the stack pointer is valid only if the
+ // compiler has not saved any temporaries onto the stack for this
+ // function before the longjmp that we still care about at this
+ // point.
+
+ // Verify that 1) 'this' is still valid and 2) '*this' has not been
+ // corrupted.
+ CILK_ASSERT(magic_number == m_magic);
+
+ // If the fiber that switched to me wants to be deallocated, do it now.
+ do_post_switch_actions();
+
+ // Now call the user proc on the new stack
+ m_start_proc(this);
+
+ // alloca() to force generation of frame pointer. The argument to alloca
+ // is contrived to prevent the compiler from optimizing it away. This
+ // code should never actually be executed.
+ int* dummy = (int*) alloca((sizeof(int) + (std::size_t) m_start_proc) & 0x1);
+ *dummy = 0xface;
+
+ // User proc should never return.
+ __cilkrts_bug("Should not get here");
+}
+
+void cilk_fiber_sysdep::make_stack(size_t stack_size)
+{
+ char* p;
+ // We've already validated that the stack size is page-aligned and
+ // is a reasonable value. No need to do any extra rounding here.
+ size_t rounded_stack_size = stack_size;
+
+ // Normally, we have already validated that the stack size is
+ // aligned to 4K. In the rare case that pages are huge though, we
+ // need to do some extra checks.
+ if (rounded_stack_size < 3 * (size_t)s_page_size) {
+ // If the specified stack size is too small, round up to 3
+ // pages. We need at least 2 extra for the guard pages.
+ rounded_stack_size = 3 * (size_t)s_page_size;
+ }
+ else {
+ // Otherwise, the stack size is large enough, but might not be
+ // a multiple of page size. Round up to nearest multiple of
+ // s_page_size, just to be safe.
+ size_t remainder = rounded_stack_size % s_page_size;
+ if (remainder) {
+ rounded_stack_size += s_page_size - remainder;
+ }
+ }
+
+ p = (char*)mmap(0, rounded_stack_size,
+ PROT_READ|PROT_WRITE,
+ MAP_PRIVATE|MAP_ANONYMOUS,
+ -1, 0);
+ if (MAP_FAILED == p) {
+ // For whatever reason (probably ran out of memory), mmap() failed.
+ // There is no stack to return, so the program loses parallelism.
+ m_stack = NULL;
+ m_stack_base = NULL;
+ return;
+ }
+
+ // mprotect guard pages.
+ mprotect(p + rounded_stack_size - s_page_size, s_page_size, PROT_NONE);
+ mprotect(p, s_page_size, PROT_NONE);
+
+ m_stack = p;
+ m_stack_base = p + rounded_stack_size - s_page_size;
+}
+
+
+void cilk_fiber_sysdep::free_stack()
+{
+ if (m_stack) {
+ size_t rounded_stack_size = m_stack_base - m_stack + s_page_size;
+ if (munmap(m_stack, rounded_stack_size) < 0)
+ __cilkrts_bug("Cilk: stack munmap failed error %d\n", errno);
+ }
+}
+
+/* End cilk_fiber-unix.cpp */
diff --git a/libcilkrts/runtime/cilk_fiber-unix.h b/libcilkrts/runtime/cilk_fiber-unix.h
new file mode 100644
index 00000000000..9f47d5b0437
--- /dev/null
+++ b/libcilkrts/runtime/cilk_fiber-unix.h
@@ -0,0 +1,149 @@
+/* cilk_fiber-unix.h -*-C++-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2012-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ **************************************************************************/
+
+#ifndef INCLUDED_CILK_FIBER_UNIX_DOT_H
+#define INCLUDED_CILK_FIBER_UNIX_DOT_H
+
+#ifndef __cplusplus
+# error cilk_fiber-unix.h is a C++-only header
+#endif
+
+#include "cilk_fiber.h"
+#include "jmpbuf.h"
+
+/**
+ * @file cilk_fiber-unix.h
+ *
+ * @brief Unix-specific implementation for cilk_fiber.
+ */
+
+/**
+ * @brief Unix-specific fiber class derived from portable fiber class
+ */
+struct cilk_fiber_sysdep : public cilk_fiber
+{
+ public:
+
+#if SUPPORT_GET_CURRENT_FIBER
+ /**
+ * @brief Gets the current fiber from TLS.
+ */
+ static cilk_fiber_sysdep* get_current_fiber_sysdep();
+#endif
+
+ /**
+ * @brief Construct the system-dependent portion of a fiber.
+ *
+ * @param stack_size The size of the stack for this fiber.
+ */
+ cilk_fiber_sysdep(std::size_t stack_size);
+
+ /**
+ * @brief Construct the system-dependent of a fiber created from a
+ * thread.
+ */
+ cilk_fiber_sysdep(from_thread_t);
+
+ /**
+ * @brief Destructor
+ */
+ ~cilk_fiber_sysdep();
+
+ /**
+ * @brief OS-specific calls to convert this fiber back to thread.
+ *
+ * Nothing to do for Linux.
+ */
+ void convert_fiber_back_to_thread();
+
+ /**
+ * @brief System-dependent function to suspend self and resume execution of "other".
+ *
+ * This fiber is suspended.
+ *
+ * @pre @c is_resumable() should be true.
+ *
+ * @param other Fiber to resume.
+ */
+ void suspend_self_and_resume_other_sysdep(cilk_fiber_sysdep* other);
+
+ /**
+ * @brief System-dependent function called to jump to @p other
+ * fiber.
+ *
+ * @pre @c is_resumable() should be false.
+ *
+ * @param other Fiber to resume.
+ */
+ NORETURN jump_to_resume_other_sysdep(cilk_fiber_sysdep* other);
+
+ /**
+ * @brief Runs the start_proc.
+ * @pre is_resumable() should be false.
+ * @pre is_allocated_from_thread() should be false.
+ * @pre m_start_proc must be valid.
+ */
+ NORETURN run();
+
+ /**
+ * @brief Returns the base of this fiber's stack.
+ */
+ inline char* get_stack_base_sysdep() { return m_stack_base; }
+
+ private:
+ char* m_stack_base; ///< The base of this fiber's stack.
+ char* m_stack; // Stack memory (low address)
+ __CILK_JUMP_BUFFER m_resume_jmpbuf; // Place to resume fiber
+ unsigned m_magic; // Magic number for checking
+
+ static int s_page_size; // Page size for
+ // stacks.
+
+ // Allocate memory for a stack. This method
+ // initializes m_stack and m_stack_base.
+ void make_stack(size_t stack_size);
+
+ // Deallocates memory for the stack.
+ void free_stack();
+
+ // Common helper method for implementation of resume_other_sysdep
+ // variants.
+ inline void resume_other_sysdep(cilk_fiber_sysdep* other);
+};
+
+#endif // ! defined(INCLUDED_CILK_FIBER_UNIX_DOT_H)
diff --git a/libcilkrts/runtime/cilk_fiber.cpp b/libcilkrts/runtime/cilk_fiber.cpp
new file mode 100644
index 00000000000..0c66f234d3b
--- /dev/null
+++ b/libcilkrts/runtime/cilk_fiber.cpp
@@ -0,0 +1,1078 @@
+/* cilk_fiber.cpp -*-C++-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2012-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ **************************************************************************/
+
+/* Implementations of non-platform-specific aspects of cilk_fiber, especially
+ * the cilk_fiber_pool interface.
+ */
+#include "cilk_fiber.h"
+#ifdef _WIN32
+# include "cilk_fiber-win.h"
+#else
+# include "cilk_fiber-unix.h"
+#endif
+#include "cilk_malloc.h"
+#include "bug.h"
+#include <new>
+
+#include <climits>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+#include "sysdep.h"
+
+
+extern "C" {
+
+inline int cilk_fiber_pool_sanity_check(cilk_fiber_pool *pool, const char* desc)
+{
+ int errors = 0;
+#if FIBER_DEBUG >= 1
+ if ((NULL != pool) && pool->total > 0) {
+
+ // Root pool should not allocate more fibers than alloc_max
+ errors += ((pool->parent == NULL) &&
+ (pool->total > pool->alloc_max));
+ errors += (pool->total > pool->high_water);
+
+ if (errors) {
+ fprintf(stderr, "ERROR at %s: pool=%p has max_size=%u, total=%d, high_water=%d\n",
+ desc,
+ pool, pool->max_size, pool->total, pool->high_water);
+ }
+ }
+#endif
+ return (errors == 0);
+}
+
+inline void increment_pool_total(cilk_fiber_pool* pool)
+{
+ ++pool->total;
+ if (pool->high_water < pool->total)
+ pool->high_water = pool->total;
+}
+
+inline void decrement_pool_total(cilk_fiber_pool* pool, int fibers_freed)
+{
+ pool->total -= fibers_freed;
+}
+
+
+/**
+ * @brief Free fibers from this pool until we have at most @c
+ * num_to_keep fibers remaining, and then put a fiber back.
+ *
+ * @pre We do not hold @c pool->lock
+ * @post After completion, we do not hold @c pool->lock
+ */
+static void cilk_fiber_pool_free_fibers_from_pool(cilk_fiber_pool* pool,
+ unsigned num_to_keep,
+ cilk_fiber* fiber_to_return)
+{
+ // Free our own fibers, until we fall below our desired threshold.
+ // Each iteration of this loop proceeds in the following stages:
+ // 1. Acquire the pool lock,
+ // 2. Grabs up to B fibers from the pool, stores them into a buffer.
+ // 3. Check if pool is empty enough. If yes, put the last fiber back,
+ // and remember that we should quit.
+ // 4. Release the pool lock, and actually free any buffered fibers.
+ // 5. Check if we are done and should exit the loop. Otherwise, try again.
+ //
+ const bool need_lock = pool->lock;
+ bool last_fiber_returned = false;
+
+ do {
+ const int B = 10; // Pull at most this many fibers from the
+ // parent for one lock acquisition. Make
+ // this value large enough to amortize
+ // against the cost of acquiring and
+ // releasing the lock.
+ int num_to_free = 0;
+ cilk_fiber* fibers_to_free[B];
+
+ // Stage 1: Grab the lock.
+ if (need_lock) {
+ spin_mutex_lock(pool->lock);
+ }
+
+ // Stage 2: Grab up to B fibers to free.
+ int fibers_freed = 0;
+ while ((pool->size > num_to_keep) && (num_to_free < B)) {
+ fibers_to_free[num_to_free++] = pool->fibers[--pool->size];
+ fibers_freed++;
+ }
+ decrement_pool_total(pool, fibers_freed);
+
+ // Stage 3. Pool is below threshold. Put extra fiber back.
+ if (pool->size <= num_to_keep) {
+ // Put the last fiber back into the pool.
+ if (fiber_to_return) {
+ CILK_ASSERT(pool->size < pool->max_size);
+ pool->fibers[pool->size] = fiber_to_return;
+ pool->size++;
+ }
+ last_fiber_returned = true;
+ }
+
+ // Stage 4: Release the lock, and actually free any fibers
+ // buffered.
+ if (need_lock) {
+ spin_mutex_unlock(pool->lock);
+ }
+
+ for (int i = 0; i < num_to_free; ++i) {
+ fibers_to_free[i]->deallocate_to_heap();
+ }
+
+ } while (!last_fiber_returned);
+}
+
+
+/******************************************************************
+ * TBD: We want to simplify / rework the logic for allocating and
+ * deallocating fibers, so that they are hopefully simpler and work
+ * more elegantly for more than two levels.
+ ******************************************************************/
+
+/**
+ * @brief Transfer fibers from @c pool to @c pool->parent.
+ *
+ * @pre Must hold @c pool->lock if it exists.
+ * @post After completion, some number of fibers
+ * have been moved from this pool to the parent.
+ * The lock @c pool->lock is still held.
+ *
+ * TBD: Do we wish to guarantee that the lock has never been
+ * released? It may depend on the implementation...
+ */
+static void cilk_fiber_pool_move_fibers_to_parent_pool(cilk_fiber_pool* pool,
+ unsigned num_to_keep)
+{
+ // ASSERT: We should hold the lock on pool (if it has one).
+ CILK_ASSERT(pool->parent);
+ cilk_fiber_pool* parent_pool = pool->parent;
+
+ // Move fibers from our pool to the parent until we either run out
+ // of space in the parent, or hit our threshold.
+ //
+ // This operation must be done while holding the parent lock.
+
+ // If the parent pool appears to be full, just return early.
+ if (parent_pool->size >= parent_pool->max_size)
+ return;
+
+ spin_mutex_lock(pool->parent->lock);
+ while ((parent_pool->size < parent_pool->max_size) &&
+ (pool->size > num_to_keep)) {
+ parent_pool->fibers[parent_pool->size++] =
+ pool->fibers[--pool->size];
+ }
+
+ // If the child pool has deallocated more than fibers to the heap
+ // than it has allocated, then transfer this "surplus" to the
+ // parent, so that the parent is free to allocate more from the
+ // heap.
+ //
+ // This transfer means that the total in the parent can
+ // temporarily go negative.
+ if (pool->total < 0) {
+ // Reduce parent total by the surplus we have in the local
+ // pool.
+ parent_pool->total += pool->total;
+ pool->total = 0;
+ }
+
+ spin_mutex_unlock(pool->parent->lock);
+}
+
+void cilk_fiber_pool_init(cilk_fiber_pool* pool,
+ cilk_fiber_pool* parent,
+ size_t stack_size,
+ unsigned buffer_size,
+ int alloc_max,
+ int is_shared)
+{
+#if FIBER_DEBUG >= 1
+ fprintf(stderr, "fiber_pool_init, pool=%p, parent=%p, alloc_max=%u\n",
+ pool, parent, alloc_max);
+#endif
+
+ pool->lock = (is_shared ? spin_mutex_create() : NULL);
+ pool->parent = parent;
+ pool->stack_size = stack_size;
+ pool->max_size = buffer_size;
+ pool->size = 0;
+ pool->total = 0;
+ pool->high_water = 0;
+ pool->alloc_max = alloc_max;
+ pool->fibers =
+ (cilk_fiber**) __cilkrts_malloc(buffer_size * sizeof(cilk_fiber*));
+ CILK_ASSERT(NULL != pool->fibers);
+
+#ifdef __MIC__
+#define PREALLOCATE_FIBERS
+#endif
+
+#ifdef PREALLOCATE_FIBERS
+ // Pre-allocate 1/4 of fibers in the pools ahead of time. This
+ // value is somewhat arbitrary. It was chosen to be less than the
+ // threshold (of about 3/4) of fibers to keep in the pool when
+ // transferring fibers to the parent.
+
+ int pre_allocate_count = buffer_size/4;
+ for (pool->size = 0; pool->size < pre_allocate_count; pool->size++) {
+ pool->fibers[pool->size] = cilk_fiber::allocate_from_heap(pool->stack_size);
+ }
+#endif
+}
+
+
+void cilk_fiber_pool_set_fiber_limit(cilk_fiber_pool* root_pool,
+ unsigned max_fibers_to_allocate)
+{
+ // Should only set limit on root pool, not children.
+ CILK_ASSERT(NULL == root_pool->parent);
+ root_pool->alloc_max = max_fibers_to_allocate;
+}
+
+void cilk_fiber_pool_destroy(cilk_fiber_pool* pool)
+{
+ CILK_ASSERT(cilk_fiber_pool_sanity_check(pool, "pool_destroy"));
+
+ // Lock my own pool, if I need to.
+ if (pool->lock) {
+ spin_mutex_lock(pool->lock);
+ }
+
+ // Give any remaining fibers to parent pool.
+ if (pool->parent) {
+ cilk_fiber_pool_move_fibers_to_parent_pool(pool, 0);
+ }
+
+ // Unlock pool.
+ if (pool->lock) {
+ spin_mutex_unlock(pool->lock);
+ }
+
+ // If I have any left in my pool, just free them myself.
+ // This method may acquire the pool lock.
+ cilk_fiber_pool_free_fibers_from_pool(pool, 0, NULL);
+
+ // Destroy the lock if there is one.
+ if (pool->lock) {
+ spin_mutex_destroy(pool->lock);
+ }
+ __cilkrts_free(pool->fibers);
+}
+
+
+cilk_fiber* cilk_fiber_allocate(cilk_fiber_pool* pool)
+{
+ CILK_ASSERT(cilk_fiber_pool_sanity_check(pool, "allocate"));
+ return cilk_fiber::allocate(pool);
+}
+
+cilk_fiber* cilk_fiber_allocate_from_heap(size_t stack_size)
+{
+ return cilk_fiber::allocate_from_heap(stack_size);
+}
+
+void cilk_fiber_reset_state(cilk_fiber* fiber, cilk_fiber_proc start_proc)
+{
+ fiber->reset_state(start_proc);
+}
+
+int cilk_fiber_remove_reference(cilk_fiber *fiber, cilk_fiber_pool *pool)
+{
+ return fiber->remove_reference(pool);
+}
+
+cilk_fiber* cilk_fiber_allocate_from_thread()
+{
+ return cilk_fiber::allocate_from_thread();
+}
+
+int cilk_fiber_deallocate_from_thread(cilk_fiber *fiber)
+{
+ return fiber->deallocate_from_thread();
+}
+
+int cilk_fiber_remove_reference_from_thread(cilk_fiber *fiber)
+{
+ return fiber->remove_reference_from_thread();
+}
+
+int cilk_fiber_is_allocated_from_thread(cilk_fiber *fiber)
+{
+ return fiber->is_allocated_from_thread();
+}
+
+#if SUPPORT_GET_CURRENT_FIBER
+cilk_fiber* cilk_fiber_get_current_fiber(void)
+{
+ return cilk_fiber::get_current_fiber();
+}
+#endif
+
+void cilk_fiber_suspend_self_and_resume_other(cilk_fiber* self,
+ cilk_fiber* other)
+{
+ self->suspend_self_and_resume_other(other);
+}
+
+
+void cilk_fiber::reset_state(cilk_fiber_proc start_proc)
+{
+ // Setup the fiber and return.
+ this->m_start_proc = start_proc;
+
+ CILK_ASSERT(!this->is_resumable());
+ CILK_ASSERT(NULL == this->m_pending_remove_ref);
+ CILK_ASSERT(NULL == this->m_pending_pool);
+}
+
+NORETURN
+cilk_fiber_remove_reference_from_self_and_resume_other(cilk_fiber* self,
+ cilk_fiber_pool* self_pool,
+ cilk_fiber* other)
+{
+#if FIBER_DEBUG >= 3
+ __cilkrts_worker* w = __cilkrts_get_tls_worker();
+ fprintf(stderr, "W=%d: cilk_fiber_deactivate_self_and_resume_other: self=%p, other=%p\n",
+ w->self,
+ self, other);
+#endif
+ CILK_ASSERT(cilk_fiber_pool_sanity_check(self_pool, "remove_reference_from_self_resume_other"));
+ self->remove_reference_from_self_and_resume_other(self_pool, other);
+
+ // We should never return here.
+}
+
+void cilk_fiber_set_post_switch_proc(cilk_fiber *self,
+ cilk_fiber_proc post_switch_proc)
+{
+ self->set_post_switch_proc(post_switch_proc);
+}
+
+void cilk_fiber_invoke_tbb_stack_op(cilk_fiber* fiber,
+ __cilk_tbb_stack_op op)
+{
+ fiber->invoke_tbb_stack_op(op);
+}
+
+cilk_fiber_data* cilk_fiber_get_data(cilk_fiber* fiber)
+{
+ return fiber->get_data();
+
+ /// TBD: Change this code to "return (cilk_fiber_data*)fiber;"
+ // plus a static assert, so that this function is
+ // more easily inlined by the compiler.
+}
+
+int cilk_fiber_is_resumable(cilk_fiber *fiber)
+{
+ return fiber->is_resumable();
+}
+
+char* cilk_fiber_get_stack_base(cilk_fiber *fiber)
+{
+ return fiber->get_stack_base();
+}
+
+
+#if defined(_WIN32) && 0 // Only works on Windows. Disable debugging for now.
+#define DBG_STACK_OPS(_fmt, ...) __cilkrts_dbgprintf(_fmt, __VA_ARGS__)
+#else
+#define DBG_STACK_OPS(_fmt, ...)
+#endif
+
+void cilk_fiber_set_stack_op(cilk_fiber *fiber,
+ __cilk_tbb_stack_op_thunk o)
+{
+ cilk_fiber_data *fdata = cilk_fiber_get_data(fiber);
+ DBG_STACK_OPS ("cilk_fiber_set_stack_op - cilk_fiber %p, routine: %p, data: %p\n",
+ fiber,
+ o.routine,
+ o.data);
+ fdata->stack_op_routine = o.routine;
+ fdata->stack_op_data = o.data;
+}
+
+#if 0 // Debugging function
+static
+const char *NameStackOp (enum __cilk_tbb_stack_op op)
+{
+ switch(op)
+ {
+ case CILK_TBB_STACK_ORPHAN: return "CILK_TBB_STACK_ORPHAN";
+ case CILK_TBB_STACK_ADOPT: return "CILK_TBB_STACK_ADOPT";
+ case CILK_TBB_STACK_RELEASE: return "CILK_TBB_STACK_RELEASE";
+ default: return "Unknown";
+ }
+}
+#endif
+
+/*
+ * Save TBB interop information for an unbound thread. It will get picked
+ * up when the thread is bound to the runtime.
+ */
+void cilk_fiber_tbb_interop_save_stack_op_info(__cilk_tbb_stack_op_thunk o)
+{
+ __cilk_tbb_stack_op_thunk *saved_thunk =
+ __cilkrts_get_tls_tbb_interop();
+
+ DBG_STACK_OPS("Calling save_stack_op; o.routine=%p, o.data=%p, saved_thunk=%p\n",
+ o.routine, o.data, saved_thunk);
+
+ // If there is not already space allocated, allocate some.
+ if (NULL == saved_thunk) {
+ saved_thunk = (__cilk_tbb_stack_op_thunk*)
+ __cilkrts_malloc(sizeof(__cilk_tbb_stack_op_thunk));
+ __cilkrts_set_tls_tbb_interop(saved_thunk);
+ }
+
+ *saved_thunk = o;
+
+ DBG_STACK_OPS ("Unbound Thread %04x: tbb_interop_save_stack_op_info - saved info\n",
+ cilkos_get_current_thread_id());
+}
+
+/*
+ * Save TBB interop information from the cilk_fiber. It will get picked
+ * up when the thread is bound to the runtime next time.
+ */
+void cilk_fiber_tbb_interop_save_info_from_stack(cilk_fiber *fiber)
+{
+ __cilk_tbb_stack_op_thunk *saved_thunk;
+ cilk_fiber_data* fdata;
+
+ if (NULL == fiber)
+ return;
+
+ fdata = cilk_fiber_get_data(fiber);
+ // If there is no TBB interop data, just return
+ if (NULL == fdata->stack_op_routine)
+ return;
+
+ saved_thunk = __cilkrts_get_tls_tbb_interop();
+
+ // If there is not already space allocated, allocate some.
+ if (NULL == saved_thunk) {
+ saved_thunk = (__cilk_tbb_stack_op_thunk*)
+ __cilkrts_malloc(sizeof(__cilk_tbb_stack_op_thunk));
+ __cilkrts_set_tls_tbb_interop(saved_thunk);
+ }
+
+ saved_thunk->routine = fdata->stack_op_routine;
+ saved_thunk->data = fdata->stack_op_data;
+}
+
+/*
+ * If there's TBB interop information that was saved before the thread was
+ * bound, apply it now
+ */
+void cilk_fiber_tbb_interop_use_saved_stack_op_info(cilk_fiber* fiber)
+{
+ __cilk_tbb_stack_op_thunk *saved_thunk =
+ __cilkrts_get_tls_tbb_interop();
+
+ CILK_ASSERT(fiber);
+ // If we haven't allocated a TBB interop index, we don't have any saved info
+ if (NULL == saved_thunk) {
+ DBG_STACK_OPS ("cilk_fiber %p: tbb_interop_use_saved_stack_op_info - no saved info\n",
+ fiber);
+ return;
+ }
+
+ DBG_STACK_OPS ("cilk_fiber %p: tbb_interop_use_saved_stack_op_info - using saved info\n",
+ fiber);
+
+ // Associate the saved info with the __cilkrts_stack
+ cilk_fiber_set_stack_op(fiber, *saved_thunk);
+
+ // Free the saved data. We'll save it again if needed when the code
+ // returns from the initial function
+ cilk_fiber_tbb_interop_free_stack_op_info();
+}
+
+/*
+ * Free saved TBB interop memory. Should only be called when the thread is
+ * not bound.
+ */
+void cilk_fiber_tbb_interop_free_stack_op_info(void)
+{
+ __cilk_tbb_stack_op_thunk *saved_thunk =
+ __cilkrts_get_tls_tbb_interop();
+
+ // If we haven't allocated a TBB interop index, we don't have any saved info
+ if (NULL == saved_thunk)
+ return;
+
+ DBG_STACK_OPS ("tbb_interop_free_stack_op_info - freeing saved info\n");
+
+ // Free the memory and wipe out the TLS value
+ __cilkrts_free(saved_thunk);
+ __cilkrts_set_tls_tbb_interop(NULL);
+}
+
+
+
+#if NEED_FIBER_REF_COUNTS
+int cilk_fiber_has_references(cilk_fiber *fiber)
+{
+ return (fiber->get_ref_count() > 0);
+}
+
+int cilk_fiber_get_ref_count(cilk_fiber *fiber)
+{
+ return fiber->get_ref_count();
+}
+
+void cilk_fiber_add_reference(cilk_fiber *fiber)
+{
+ fiber->inc_ref_count();
+}
+#endif // NEED_FIBER_REF_COUNTS
+
+
+} // End extern "C"
+
+
+cilk_fiber_sysdep* cilk_fiber::sysdep()
+{
+ return static_cast<cilk_fiber_sysdep*>(this);
+}
+
+
+cilk_fiber::cilk_fiber()
+ : m_start_proc(NULL)
+ , m_post_switch_proc(NULL)
+ , m_pending_remove_ref(NULL)
+ , m_pending_pool(NULL)
+ , m_flags(0)
+{
+ // Clear cilk_fiber_data base-class data members
+ std::memset((cilk_fiber_data*) this, 0, sizeof(cilk_fiber_data));
+
+ // cilk_fiber data members
+ init_ref_count(0);
+}
+
+cilk_fiber::cilk_fiber(std::size_t stack_size)
+{
+ *this = cilk_fiber(); // A delegating constructor would be nice here
+ this->stack_size = stack_size;
+}
+
+cilk_fiber::~cilk_fiber()
+{
+ // Empty destructor.
+}
+
+
+char* cilk_fiber::get_stack_base()
+{
+ return this->sysdep()->get_stack_base_sysdep();
+}
+
+cilk_fiber* cilk_fiber::allocate_from_heap(std::size_t stack_size)
+{
+ // Case 1: pool is NULL. create a new fiber from the heap
+ // No need for locks here.
+ cilk_fiber_sysdep* ret =
+ (cilk_fiber_sysdep*) __cilkrts_malloc(sizeof(cilk_fiber_sysdep));
+
+ // Error condition. If we failed to allocate a fiber from the
+ // heap, we are in trouble though...
+ if (!ret)
+ return NULL;
+
+ ::new(ret) cilk_fiber_sysdep(stack_size);
+
+ CILK_ASSERT(0 == ret->m_flags);
+ CILK_ASSERT(NULL == ret->m_pending_remove_ref);
+ CILK_ASSERT(NULL == ret->m_pending_pool);
+ ret->init_ref_count(1);
+ return ret;
+}
+
+
+#if USE_FIBER_TRY_ALLOCATE_FROM_POOL
+/**
+ * Helper method: try to allocate a fiber from this pool or its
+ * ancestors without going to the OS / heap.
+ *
+ * Returns allocated pool, or NULL if no pool is found.
+ *
+ * If pool contains a suitable fiber. Return it. Otherwise, try to
+ * recursively grab a fiber from the parent pool, if there is one.
+ *
+ * This method will not allocate a fiber from the heap.
+ *
+ * This method could be written either recursively or iteratively.
+ * It probably does not matter which one we do.
+ *
+ * @note This method is compiled, but may not be used unless the
+ * USE_FIBER_TRY_ALLOCATE_FROM_POOL switch is set.
+ */
+cilk_fiber* cilk_fiber::try_allocate_from_pool_recursive(cilk_fiber_pool* pool)
+{
+ cilk_fiber* ret = NULL;
+
+ if (pool->size > 0) {
+ // Try to get the lock.
+ if (pool->lock) {
+ // For some reason, it seems to be better to just block on the parent
+ // pool lock, instead of using a try-lock?
+#define USE_TRY_LOCK_IN_FAST_ALLOCATE 0
+#if USE_TRY_LOCK_IN_FAST_ALLOCATE
+ int got_lock = spin_mutex_trylock(pool->lock);
+ if (!got_lock) {
+ // If we fail, skip to the parent.
+ if (pool->parent) {
+ return try_allocate_from_pool_recursive(pool->parent);
+ }
+ }
+#else
+ spin_mutex_lock(pool->lock);
+#endif
+ }
+
+ // Check in the pool if we have the lock.
+ if (pool->size > 0) {
+ ret = pool->fibers[--pool->size];
+ }
+
+ // Release the lock once we are done updating pool fields.
+ if (pool->lock) {
+ spin_mutex_unlock(pool->lock);
+ }
+ }
+
+ if ((!ret) && (pool->parent)) {
+ return try_allocate_from_pool_recursive(pool->parent);
+ }
+
+ if (ret) {
+ // When we pull a fiber out of the pool, set its reference
+ // count before we return it.
+ ret->init_ref_count(1);
+ }
+ return ret;
+}
+#endif // USE_FIBER_TRY_ALLOCATE_FROM_POOL
+
+
+cilk_fiber* cilk_fiber::allocate(cilk_fiber_pool* pool)
+{
+ // Pool should not be NULL in this method. But I'm not going to
+ // actually assert it, because we are likely to seg fault anyway
+ // if it is.
+ // CILK_ASSERT(NULL != pool);
+
+ cilk_fiber *ret = NULL;
+
+#if USE_FIBER_TRY_ALLOCATE_FROM_POOL
+ // "Fast" path, which doesn't go to the heap or OS until checking
+ // the ancestors first.
+ ret = try_allocate_from_pool_recursive(pool);
+ if (ret)
+ return ret;
+#endif
+
+ // If we don't get anything from the "fast path", then go through
+ // a slower path to look for a fiber.
+ //
+ // 1. Lock the pool if it is shared.
+ // 2. Look in our local pool. If we find one, release the lock
+ // and quit searching.
+ // 3. Otherwise, check whether we can allocate from heap.
+ // 4. Release the lock if it was acquired.
+ // 5. Try to allocate from the heap, if step 3 said we could.
+ // If we find a fiber, then quit searching.
+ // 6. If none of these steps work, just recursively try again
+ // from the parent.
+
+ // 1. Lock the pool if it is shared.
+ if (pool->lock) {
+ spin_mutex_lock(pool->lock);
+ }
+
+ // 2. Look in local pool.
+ if (pool->size > 0) {
+ ret = pool->fibers[--pool->size];
+ if (ret) {
+ // If we found one, release the lock once we are
+ // done updating pool fields, and break out of the
+ // loop.
+ if (pool->lock) {
+ spin_mutex_unlock(pool->lock);
+ }
+
+ // When we pull a fiber out of the pool, set its reference
+ // count just in case.
+ ret->init_ref_count(1);
+ return ret;
+ }
+ }
+
+ // 3. Check whether we can allocate from the heap.
+ bool can_allocate_from_heap = false;
+ if (pool->total < pool->alloc_max) {
+ // Track that we are allocating a new fiber from the
+ // heap, originating from this pool.
+ // This increment may be undone if we happen to fail to
+ // allocate from the heap.
+ increment_pool_total(pool);
+ can_allocate_from_heap = true;
+ }
+
+ // 4. Unlock the pool, and then allocate from the heap.
+ if (pool->lock) {
+ spin_mutex_unlock(pool->lock);
+ }
+
+ // 5. Actually try to allocate from the heap / OS.
+ if (can_allocate_from_heap) {
+ ret = allocate_from_heap(pool->stack_size);
+ // If we got something from the heap, just return it.
+ if (ret) {
+ return ret;
+ }
+
+ // Otherwise, we failed in our attempt to allocate a
+ // fiber from the heap. Grab the lock and decrement
+ // the total again.
+ if (pool->lock) {
+ spin_mutex_lock(pool->lock);
+ }
+ decrement_pool_total(pool, 1);
+ if (pool->lock) {
+ spin_mutex_unlock(pool->lock);
+ }
+ }
+
+ // 6. If we get here, then searching this pool failed. Go search
+ // the parent instead if we have one.
+ if (pool->parent) {
+ return allocate(pool->parent);
+ }
+
+ return ret;
+}
+
+int cilk_fiber::remove_reference(cilk_fiber_pool* pool)
+{
+ int ref_count = this->dec_ref_count();
+ if (ref_count == 0) {
+ if (pool) {
+ deallocate_self(pool);
+ }
+ else {
+ deallocate_to_heap();
+ }
+ }
+ return ref_count;
+}
+
+cilk_fiber* cilk_fiber::allocate_from_thread()
+{
+ void* retmem = __cilkrts_malloc(sizeof(cilk_fiber_sysdep));
+ CILK_ASSERT(retmem);
+ cilk_fiber_sysdep* ret = ::new(retmem) cilk_fiber_sysdep(from_thread);
+
+ // A fiber allocated from a thread begins with a reference count
+ // of 2. The first is for being created, and the second is for
+ // being running.
+ //
+ // Suspending this fiber will decrement the count down to 1.
+ ret->init_ref_count(2);
+
+#if SUPPORT_GET_CURRENT_FIBER
+ // We're creating the main fiber for this thread. Set this fiber as the
+ // current fiber.
+ cilkos_set_tls_cilk_fiber(ret);
+#endif
+ return ret;
+}
+
+int cilk_fiber::deallocate_from_thread()
+{
+ CILK_ASSERT(this->is_allocated_from_thread());
+#if SUPPORT_GET_CURRENT_FIBER
+ CILK_ASSERT(this == cilkos_get_tls_cilk_fiber());
+ // Reverse of "allocate_from_thread".
+ cilkos_set_tls_cilk_fiber(NULL);
+#endif
+
+ this->assert_ref_count_at_least(2);
+
+ // Suspending the fiber should conceptually decrement the ref
+ // count by 1.
+ cilk_fiber_sysdep* self = this->sysdep();
+ self->convert_fiber_back_to_thread();
+
+ // Then, freeing the fiber itself decrements the ref count again.
+ int ref_count = this->sub_from_ref_count(2);
+ if (ref_count == 0) {
+ self->~cilk_fiber_sysdep();
+ __cilkrts_free(self);
+ }
+ return ref_count;
+}
+
+int cilk_fiber::remove_reference_from_thread()
+{
+ int ref_count = dec_ref_count();
+ if (ref_count == 0) {
+ cilk_fiber_sysdep* self = this->sysdep();
+ self->~cilk_fiber_sysdep();
+ __cilkrts_free(self);
+ }
+ return ref_count;
+}
+
+
+#if SUPPORT_GET_CURRENT_FIBER
+cilk_fiber* cilk_fiber::get_current_fiber()
+{
+ return cilk_fiber_sysdep::get_current_fiber_sysdep();
+}
+#endif
+
+void cilk_fiber::do_post_switch_actions()
+{
+ if (m_post_switch_proc)
+ {
+ cilk_fiber_proc proc = m_post_switch_proc;
+ m_post_switch_proc = NULL;
+ proc(this);
+ }
+
+ if (m_pending_remove_ref)
+ {
+ m_pending_remove_ref->remove_reference(m_pending_pool);
+
+ // Even if we don't free it,
+ m_pending_remove_ref = NULL;
+ m_pending_pool = NULL;
+ }
+}
+
+void cilk_fiber::suspend_self_and_resume_other(cilk_fiber* other)
+{
+#if FIBER_DEBUG >=1
+ fprintf(stderr, "suspend_self_and_resume_other: self =%p, other=%p [owner=%p, resume_sf=%p]\n",
+ this, other, other->owner, other->resume_sf);
+#endif
+
+ // Decrement my reference count (to suspend)
+ // Increment other's count (to resume)
+ // Suspended fiber should have a reference count of at least 1. (It is not in a pool).
+ this->dec_ref_count();
+ other->inc_ref_count();
+ this->assert_ref_count_at_least(1);
+
+ // Pass along my owner.
+ other->owner = this->owner;
+ this->owner = NULL;
+
+ // Change this fiber to resumable.
+ CILK_ASSERT(!this->is_resumable());
+ this->set_resumable(true);
+
+ // Normally, I'd assert other->is_resumable(). But this flag may
+ // be false the first time we try to "resume" a fiber.
+ cilk_fiber_sysdep* self = this->sysdep();
+ self->suspend_self_and_resume_other_sysdep(other->sysdep());
+
+ // HAVE RESUMED EXECUTION
+ // When we come back here, we should have at least two references:
+ // one for the fiber being allocated / out of a pool, and one for it being active.
+ this->assert_ref_count_at_least(2);
+}
+
+NORETURN
+cilk_fiber::remove_reference_from_self_and_resume_other(cilk_fiber_pool* self_pool,
+ cilk_fiber* other)
+{
+ // Decrement my reference count once (to suspend)
+ // Increment other's count (to resume)
+ // Suspended fiber should have a reference count of at least 1. (It is not in a pool).
+ this->dec_ref_count();
+ other->inc_ref_count();
+
+ // Set a pending remove reference for this fiber, once we have
+ // actually switched off.
+ other->m_pending_remove_ref = this;
+ other->m_pending_pool = self_pool;
+
+ // Pass along my owner.
+ other->owner = this->owner;
+ this->owner = NULL;
+
+ // Since we are deallocating self, this fiber does not become
+ // resumable.
+ CILK_ASSERT(!this->is_resumable());
+
+ cilk_fiber_sysdep* self = this->sysdep();
+ self->jump_to_resume_other_sysdep(other->sysdep());
+
+ __cilkrts_bug("Deallocating fiber. We should never come back here.");
+ std::abort();
+}
+
+
+void cilk_fiber::deallocate_to_heap()
+{
+ cilk_fiber_sysdep* self = this->sysdep();
+ self->~cilk_fiber_sysdep();
+ __cilkrts_free(self);
+}
+
+void cilk_fiber::deallocate_self(cilk_fiber_pool* pool)
+{
+ this->set_resumable(false);
+
+ CILK_ASSERT(NULL != pool);
+ CILK_ASSERT(!this->is_allocated_from_thread());
+ this->assert_ref_count_equals(0);
+
+ // Cases:
+ //
+ // 1. pool has space: Add to this pool.
+ // 2. pool is full: Give some fibers to parent, and then free
+ // enough to make space for the fiber we are deallocating.
+ // Then put the fiber back into the pool.
+
+ const bool need_lock = pool->lock;
+ // Grab the lock for the remaining cases.
+ if (need_lock) {
+ spin_mutex_lock(pool->lock);
+ }
+
+ // Case 1: this pool has space. Return the fiber.
+ if (pool->size < pool->max_size)
+ {
+ // Add this fiber to pool
+ pool->fibers[pool->size++] = this;
+ if (need_lock) {
+ spin_mutex_unlock(pool->lock);
+ }
+ return;
+ }
+
+ // Case 2: Pool is full.
+ //
+ // First free up some space by giving fibers to the parent.
+ if (pool->parent)
+ {
+ // Pool is full. Move all but "num_to_keep" fibers to parent,
+ // if we can.
+ unsigned num_to_keep = pool->max_size/2 + pool->max_size/4;
+ cilk_fiber_pool_move_fibers_to_parent_pool(pool, num_to_keep);
+ }
+
+ if (need_lock) {
+ spin_mutex_unlock(pool->lock);
+ }
+
+ // Now, free a fiber to make room for the one we need to put back,
+ // and then put this fiber back. This step may actually return
+ // fibers to the heap.
+ cilk_fiber_pool_free_fibers_from_pool(pool, pool->max_size -1, this);
+}
+
+
+// NOTE: Except for print-debug, this code is the same as in Windows.
+void cilk_fiber::invoke_tbb_stack_op(__cilk_tbb_stack_op op)
+{
+ cilk_fiber_data *fdata = this->get_data();
+
+ if (0 == fdata->stack_op_routine)
+ {
+ if (CILK_TBB_STACK_RELEASE != op)
+ DBG_STACK_OPS ("Wkr %p: invoke_tbb_stack_op - %s (%d) for cilk_fiber %p, fiber %p, thread id %04x - No stack op routine\n",
+ fdata->owner,
+ NameStackOp(op),
+ op,
+ fdata,
+ this,
+ cilkos_get_current_thread_id());
+ return;
+ }
+
+ // Call TBB to do it's thing
+ DBG_STACK_OPS ("Wkr %p: invoke_tbb_stack_op - op %s data %p for cilk_fiber %p, fiber %p, thread id %04x\n",
+ fdata->owner,
+ NameStackOp(op),
+ fdata->stack_op_data,
+ fdata,
+ this,
+ cilkos_get_current_thread_id());
+
+ (*fdata->stack_op_routine)(op, fdata->stack_op_data);
+ if (op == CILK_TBB_STACK_RELEASE)
+ {
+ fdata->stack_op_routine = 0;
+ fdata->stack_op_data = 0;
+ }
+}
+
+
+
+#if NEED_FIBER_REF_COUNTS
+
+void cilk_fiber::atomic_inc_ref_count()
+{
+ cilkos_atomic_add(&m_outstanding_references, 1);
+}
+
+long cilk_fiber::atomic_dec_ref_count()
+{
+ return cilkos_atomic_add(&m_outstanding_references, -1);
+}
+
+long cilk_fiber::atomic_sub_from_ref_count(long v)
+{
+ return cilkos_atomic_add(&m_outstanding_references, -v);
+}
+
+#endif // NEED_FIBER_REF_COUNTS
+
+/* End cilk_fibers.cpp */
diff --git a/libcilkrts/runtime/cilk_fiber.h b/libcilkrts/runtime/cilk_fiber.h
new file mode 100644
index 00000000000..2671f924681
--- /dev/null
+++ b/libcilkrts/runtime/cilk_fiber.h
@@ -0,0 +1,882 @@
+/* cilk_fiber.h -*-C++-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2012-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ **************************************************************************/
+
+/**
+ * @file cilk_fiber.h
+ *
+ * @brief Abstraction of a "fiber": A coprocess-like stack and auxiliary data
+ */
+
+#ifndef INCLUDED_CILK_FIBER_DOT_H
+#define INCLUDED_CILK_FIBER_DOT_H
+
+#include <cilk/common.h>
+#ifdef __cplusplus
+# include <cstddef>
+#else
+# include <stddef.h>
+#endif
+
+#include "bug.h"
+#include "cilk-tbb-interop.h"
+#include "spin_mutex.h"
+#include "internal/abi.h" // Define __cilkrts_stack_frame
+
+/**
+ * @brief Debugging level for Cilk fiber code.
+ *
+ * A value of 0 means no debugging.
+ * Higher values generate more debugging output.
+ */
+#define FIBER_DEBUG 0
+
+/**
+ * @brief Flag for validating reference counts.
+ *
+ * Set to 1 to assert that fiber reference counts are reasonable.
+ */
+#define FIBER_CHECK_REF_COUNTS 1
+
+/**
+ * @brief Flag to determine whether fibers support reference counting.
+ * We require reference counting only on Windows, for exception
+ * processing. Unix does not need reference counting.
+ */
+#if defined(_WIN32)
+# define NEED_FIBER_REF_COUNTS 1
+#endif
+
+/**
+ * @brief Flag to enable support for the
+ * cilk_fiber_get_current_fiber() method.
+ *
+ * I'd like this flag to be 0. However, the cilk_fiber test depends
+ * on being able to call this method.
+ */
+#if !defined(SUPPORT_GET_CURRENT_FIBER)
+# define SUPPORT_GET_CURRENT_FIBER 0
+#endif
+
+/**
+ * @brief Switch for enabling "fast path" check for fibers, which
+ * doesn't go to the heap or OS until checking the ancestors first.
+ *
+ * Doing this check seems to make the stress test in
+ * cilk_fiber_pool.t.cpp run faster. But it doesn't seem to make much
+ * difference in other benchmarks, so it is disabled by default.
+ */
+#define USE_FIBER_TRY_ALLOCATE_FROM_POOL 0
+
+
+__CILKRTS_BEGIN_EXTERN_C
+
+/// @brief Forward reference to fiber pool.
+typedef struct cilk_fiber_pool cilk_fiber_pool;
+
+/** @brief Opaque data structure representing a fiber */
+typedef struct cilk_fiber cilk_fiber;
+
+/** @brief Function pointer type for use as a fiber's "main" procedure */
+typedef void (*cilk_fiber_proc)(cilk_fiber*);
+
+/** @brief Data structure associated with each fiber. */
+typedef struct cilk_fiber_data
+{
+ __STDNS size_t stack_size; /**< Size of stack for fiber */
+ __cilkrts_worker* owner; /**< Worker using this fiber */
+ __cilkrts_stack_frame* resume_sf; /**< Stack frame to resume */
+ __cilk_tbb_pfn_stack_op stack_op_routine; /**< Cilk/TBB interop callback */
+ void* stack_op_data; /**< Data for Cilk/TBB callback */
+ void* client_data; /**< Data managed by client */
+
+#ifdef _WIN32
+ char *initial_sp; /**< Initalized in fiber_stub */
+# ifdef _WIN64
+ char *steal_frame_sp; /**< RSP for frame stealing work */
+ // Needed for exception handling so we can
+ // identify when about to unwind off stack
+# endif
+#endif
+
+} cilk_fiber_data;
+
+/** @brief Pool of cilk_fiber for fiber reuse
+ *
+ * Pools form a hierarchy, with each pool pointing to its parent. When the
+ * pool undeflows, it gets a fiber from its parent. When a pool overflows,
+ * it returns some fibers to its parent. If the root pool underflows, it
+ * allocates and initializes a new fiber from the heap but only if the total
+ * is less than max_size; otherwise, fiber creation fails.
+ */
+struct cilk_fiber_pool
+{
+ spin_mutex* lock; ///< Mutual exclusion for pool operations
+ __STDNS size_t stack_size; ///< Size of stacks for fibers in this pool.
+ cilk_fiber_pool* parent; ///< @brief Parent pool.
+ ///< If this pool is empty, get from parent
+
+ // Describes inactive fibers stored in the pool.
+ cilk_fiber** fibers; ///< Array of max_size fiber pointers
+ unsigned max_size; ///< Limit on number of fibers in pool
+ unsigned size; ///< Number of fibers currently in the pool
+
+ // Statistics on active fibers that were allocated from this pool,
+ // but no longer in the pool.
+ int total; ///< @brief Fibers allocated - fiber deallocated from pool
+ ///< total may be negative for non-root pools.
+ int high_water; ///< High water mark of total fibers
+ int alloc_max; ///< Limit on number of fibers allocated from the heap/OS
+};
+
+/** @brief Initializes a cilk_fiber_pool structure
+ *
+ * @param pool - The address of the pool that is to be initialized
+ * @param parent - The address of this pool's parent, or NULL for root pool
+ * @param stack_size - Size of stacks for fibers allocated from this pool.
+ * @param buffer_size - The maximum number of fibers that may be pooled.
+ * @param alloc_max - Limit on # of fibers this pool can allocate from the heap.
+ * @param is_shared - True if accessing this pool needs a lock, false otherwise.
+ */
+void cilk_fiber_pool_init(cilk_fiber_pool* pool,
+ cilk_fiber_pool* parent,
+ size_t stack_size,
+ unsigned buffer_size,
+ int alloc_max,
+ int is_shared);
+
+/** @brief Sets the maximum number of fibers to allocate from a root pool.
+ *
+ * @param root_pool - A root fiber pool
+ * @param max_fibers_to_allocate - The limit on # of fibers to allocate.
+ *
+ * Sets the maximum number of fibers that can be allocated from this
+ * pool and all its descendants. This pool must be a root pool.
+ */
+void cilk_fiber_pool_set_fiber_limit(cilk_fiber_pool* root_pool,
+ unsigned max_fibers_to_allocate);
+
+/** @brief De-initalizes a cilk_fiber_pool
+ *
+ * @param pool - The address of the pool that is to be destroyed
+ */
+void cilk_fiber_pool_destroy(cilk_fiber_pool* pool);
+
+/** @brief Allocates a new cilk_fiber.
+ *
+ * If the specified pool is empty, this method may choose to either
+ * allocate a fiber from the heap (if pool->total < pool->alloc_max),
+ * or retrieve a fiber from the parent pool.
+ *
+ * @note If a non-null fiber is returned, @c cilk_fiber_reset_state
+ * should be called on this fiber before using it.
+ *
+ * An allocated fiber begins with a reference count of 1.
+ * This method may lock @c pool or one of its ancestors.
+ *
+ * @pre pool should not be NULL.
+ *
+ * @param pool The fiber pool from which to retrieve a fiber.
+ * @return An allocated fiber, or NULL if failed to allocate.
+ */
+cilk_fiber* cilk_fiber_allocate(cilk_fiber_pool* pool);
+
+/** @brief Allocate and initialize a new cilk_fiber using memory from
+ * the heap and/or OS.
+ *
+ * The allocated fiber begins with a reference count of 1.
+ *
+ * @param stack_size The size (in bytes) to be allocated for the fiber's
+ * stack.
+ * @return An initialized fiber. This method should not return NULL
+ * unless some exceptional condition has occurred.
+ */
+cilk_fiber* cilk_fiber_allocate_from_heap(size_t stack_size);
+
+
+/** @brief Resets an fiber object just allocated from a pool with the
+ * specified proc.
+ *
+ * After this call, cilk_fiber_data object associated with this fiber
+ * is filled with zeros.
+ *
+ * This function can be called only on a fiber that has been allocated
+ * from a pool, but never used.
+ *
+ * @param fiber The fiber to reset and initialize.
+ * @param start_proc The function to run when switching to the fiber. If
+ * null, the fiber can be used with cilk_fiber_run_proc()
+ * but not with cilk_fiber_resume().
+ */
+void cilk_fiber_reset_state(cilk_fiber* fiber,
+ cilk_fiber_proc start_proc);
+
+/** @brief Remove a reference from this fiber, possibly deallocating it.
+ *
+ * This fiber is deallocated only when there are no other references
+ * to it. Deallocation happens either by returning the fiber to the
+ * specified pool, or returning it to the heap.
+ *
+ * A fiber that is currently executing should not remove the last
+ * reference to itself.
+ *
+ * When a fiber is deallocated, destructors are not called for the
+ * objects (if any) still on its stack. The fiber's stack and fiber
+ * data is returned to the stack pool but the client fiber data is not
+ * deallocated.
+ *
+ * If the pool overflows because of a deallocation, then some fibers
+ * will be returned to the parent pool. If the root pool overflows,
+ * then the fiber is returned to the heap.
+ *
+ * @param fiber The Cilk fiber to remove a reference to.
+ * @param pool The fiber pool to which the fiber should be returned. The
+ * caller is assumed to have exclusive access to the pool
+ * either because there is no contention for it or because
+ * its lock has been acquired. If pool is NULL, any
+ * deallocated fiber is destroyed and returned to the
+ * heap.
+ *
+ * @return Final reference count. If the count is 0, the fiber was
+ * returned to a pool or the heap.
+ */
+int cilk_fiber_remove_reference(cilk_fiber *fiber, cilk_fiber_pool *pool);
+
+/** @brief Allocates and intializes this thread's main fiber
+ *
+ * Each thread has an "implicit" main fiber that control's the
+ * thread's initial stack. This function makes this fiber visible to
+ * the client and allocates the Cilk-specific aspects of the implicit
+ * fiber. A call to this function must be paired with a call to
+ * cilk_fiber_deallocate_fiber_from_thread()
+ * or a memory leak (or worse) will result.
+ *
+ * A fiber allocated from a thread begins with a reference count of 2.
+ * One is for being allocated, and one is for being active.
+ * (A fiber created from a thread is automatically currently executing.)
+ * The matching calls above each decrement the reference count by 1.
+ *
+ * @return A fiber for the currently executing thread.
+ */
+cilk_fiber* cilk_fiber_allocate_from_thread(void);
+
+/** @brief Remove a fiber created from a thread,
+ * possibly deallocating it.
+ *
+ * Same as cilk_fiber_remove_reference, except that it works on fibers
+ * created via cilk_fiber_allocate_from_thread().
+ *
+ * Fibers created from a thread are never returned to a pool.
+ *
+ * @param fiber The Cilk fiber to remove a reference from.
+ * @return Final reference count. If the count is 0, the fiber was
+ * returned to the heap.
+ */
+int cilk_fiber_remove_reference_from_thread(cilk_fiber *fiber);
+
+/** @brief Deallocate a fiber created from a thread,
+ * possibly destroying it.
+ *
+ * This method decrements the reference count of the fiber by 2, and
+ * destroys the fiber struct if the reference count is 0.
+ *
+ * OS-specific cleanup for the fiber executes unconditionally with
+ * this method. The destruction of the actual object, however, does
+ * not occur unless the reference count is 0.
+ *
+ * @param fiber The cilk_fiber to deallocate from a thread.
+ * @return Final reference count. If the count is 0, the fiber was
+ * returned to the heap.
+ */
+int cilk_fiber_deallocate_from_thread(cilk_fiber *fiber);
+
+/** @brief Returns true if this fiber is allocated from a thread.
+ */
+int cilk_fiber_is_allocated_from_thread(cilk_fiber *fiber);
+
+
+/** @brief Suspend execution on current fiber resumes other fiber.
+ *
+ * Suspends the current fiber and transfers control to a new fiber. Execution
+ * on the new fiber resumes from the point at which fiber suspended itself to
+ * run a different fiber. If fiber was freshly allocated, then runs the
+ * start_proc function specified at allocation. This function returns when
+ * another fiber resumes the self fiber. Note that the state of the
+ * floating-point control register (i.e., the register that controls rounding
+ * mode, etc.) is valid but indeterminate on return -- different
+ * implementations will have different results.
+ *
+ * When the @c self fiber is resumed, execution proceeds as though
+ * this function call returns.
+ *
+ * This operation increments the reference count of @p other.
+ * This operation decrements the reference count of @p self.
+ *
+ * @param self Fiber to switch from. Must equal current fiber.
+ * @param other Fiber to switch to.
+ */
+void cilk_fiber_suspend_self_and_resume_other(cilk_fiber* self,
+ cilk_fiber* other);
+
+/** @brief Removes a reference from the currently executing fiber and
+ * resumes other fiber.
+ *
+ * Removes a reference from @p self and transfer control to @p other
+ * fiber. Execution on @p other resumes from the point at which @p
+ * other suspended itself to run a different fiber. If @p other fiber
+ * was freshly allocated, then runs the function specified at
+ * creation.
+ *
+ *
+ * This operation increments the reference count of @p other.
+ *
+ * This operation conceptually decrements the reference count of
+ * @p self twice, once to suspend it, and once to remove a reference to
+ * it. Then, if the count is 0, it is returned to the specified pool
+ * or destroyed.
+ *
+ * @pre @p self is the currently executing fiber.
+ *
+ * @param self Fiber to remove reference switch from.
+ * @param self_pool Pool to which the current fiber should be returned
+ * @param other Fiber to switch to.
+ */
+NORETURN
+cilk_fiber_remove_reference_from_self_and_resume_other(cilk_fiber* self,
+ cilk_fiber_pool* self_pool,
+ cilk_fiber* other);
+
+/** @brief Set the proc method to execute immediately after a switch
+ * to this fiber.
+ *
+ * The @c post_switch_proc method executes immediately after switching
+ * away form @p self fiber to some other fiber, but before @c self
+ * gets cleaned up.
+ *
+ * @note A fiber can have only one post_switch_proc method at a time.
+ * If this method is called multiple times before switching to the
+ * fiber, only the last proc method will execute.
+ *
+ * @param self Fiber.
+ * @param post_switch_proc Proc method to execute immediately after switching to this fiber.
+ */
+void cilk_fiber_set_post_switch_proc(cilk_fiber* self, cilk_fiber_proc post_switch_proc);
+
+/** @brief Invoke TBB stack op for this fiber.
+ *
+ * @param fiber Fiber to invoke stack op for.
+ * @param op The stack op to invoke
+ */
+void cilk_fiber_invoke_tbb_stack_op(cilk_fiber* fiber, __cilk_tbb_stack_op op);
+
+/** @brief Returns the fiber data associated with the specified fiber.
+ *
+ * The returned struct is owned by the fiber and is deallocated automatically
+ * when the fiber is destroyed. However, the client_data field is owned by
+ * the client and must be deallocated separately. When called for a
+ * newly-allocated fiber, the returned data is zero-filled.
+ *
+ * @param fiber The fiber for which data is being requested.
+ * @return The fiber data for the specified fiber
+ */
+cilk_fiber_data* cilk_fiber_get_data(cilk_fiber* fiber);
+
+/** @brief Retrieve the owner field from the fiber.
+ *
+ * This method is provided for convenience. One can also get the
+ * fiber data, and then get the owner field.
+ */
+__CILKRTS_INLINE
+__cilkrts_worker* cilk_fiber_get_owner(cilk_fiber* fiber)
+{
+ // TBD: We really want a static assert here, that this cast is
+ // doing the right thing.
+ cilk_fiber_data* fdata = (cilk_fiber_data*)fiber;
+ return fdata->owner;
+}
+
+/** @brief Sets the owner field of a fiber.
+ *
+ * This method is provided for convenience. One can also get the
+ * fiber data, and then get the owner field.
+ */
+__CILKRTS_INLINE
+void cilk_fiber_set_owner(cilk_fiber* fiber, __cilkrts_worker* owner)
+{
+ // TBD: We really want a static assert here, that this cast is
+ // doing the right thing.
+ cilk_fiber_data* fdata = (cilk_fiber_data*)fiber;
+ fdata->owner = owner;
+}
+
+/** @brief Returns true if this fiber is resumable.
+ *
+ * A fiber is considered resumable when it is not currently being
+ * executed.
+ *
+ * This function is used by Windows exception code.
+ * @param fiber The fiber to check.
+ * @return Nonzero value if fiber is resumable.
+ */
+int cilk_fiber_is_resumable(cilk_fiber* fiber);
+
+/**
+ * @brief Returns the base of this fiber's stack.
+ *
+ * On some platforms (e.g., Windows), the fiber must have started
+ * running before we can get this information.
+ *
+ * @param fiber The fiber to get the stack pointer from.
+ * @return The base of the stack, or NULL if this
+ * information is not available yet.
+ */
+char* cilk_fiber_get_stack_base(cilk_fiber* fiber);
+
+
+/****************************************************************************
+ * TBB interop functions
+ * **************************************************************************/
+/**
+ * @brief Set the TBB callback information for a stack
+ *
+ * @param fiber The fiber to set the TBB callback information for
+ * @param o The TBB callback thunk. Specifies the callback address and
+ * context value.
+ */
+void cilk_fiber_set_stack_op(cilk_fiber *fiber,
+ __cilk_tbb_stack_op_thunk o);
+
+/**
+ * @brief Save the TBB callback address and context value in
+ * thread-local storage.
+ *
+ * We'll use it later when the thread binds to a worker.
+ *
+ * @param o The TBB callback thunk which is to be saved.
+ */
+void cilk_fiber_tbb_interop_save_stack_op_info(__cilk_tbb_stack_op_thunk o);
+
+/**
+ * @brief Move TBB stack-op info from thread-local storage and store
+ * it into the fiber.
+ *
+ * Called when we bind a thread to the runtime. If there is any TBB
+ * interop information in thread-local storage, bind it to the stack
+ * now.
+ *
+ * @pre \c fiber should not be NULL.
+ * @param fiber The fiber that should take over the TBB interop information.
+ */
+void cilk_fiber_tbb_interop_use_saved_stack_op_info(cilk_fiber *fiber);
+
+/**
+ * @brief Free any TBB interop information saved in thread-local storage
+ */
+void cilk_fiber_tbb_interop_free_stack_op_info(void);
+
+/**
+ * @brief Migrate any TBB interop information from a cilk_fiber to
+ * thread-local storage.
+ *
+ * Returns immediately if no TBB interop information has been
+ * associated with the stack.
+ *
+ * @param fiber The cilk_fiber who's TBB interop information should be
+ * saved in thread-local storage.
+ */
+void cilk_fiber_tbb_interop_save_info_from_stack(cilk_fiber* fiber);
+
+
+#if SUPPORT_GET_CURRENT_FIBER
+/** @brief Returns the fiber associated with the currently executing thread
+ *
+ * @note This function is currently used only for testing the Cilk
+ * runtime.
+ *
+ * @return Fiber associated with the currently executing thread or NULL if no
+ * fiber was associated with this thread.
+ */
+cilk_fiber* cilk_fiber_get_current_fiber(void);
+#endif
+
+
+#if NEED_FIBER_REF_COUNTS
+/** @brief Returns true if this fiber has reference count > 0.
+ *
+ * @param fiber The fiber to check for references.
+ * @return Nonzero value if the fiber has references.
+ */
+int cilk_fiber_has_references(cilk_fiber *fiber);
+
+/** @brief Returns the value of the reference count.
+ *
+ * @param fiber The fiber to check for references.
+ * @return The value of the reference count of fiber.
+ */
+int cilk_fiber_get_ref_count(cilk_fiber *fiber);
+
+/** @brief Adds a reference to this fiber.
+ *
+ * Increments the reference count of a current fiber. Fibers with
+ * nonzero reference count will not be freed or returned to a fiber
+ * pool.
+ *
+ * @param fiber The fiber to add a reference to.
+ */
+void cilk_fiber_add_reference(cilk_fiber *fiber);
+
+#endif // NEED_FIBER_REF_COUNTS
+
+__CILKRTS_END_EXTERN_C
+
+#ifdef __cplusplus
+// Some C++ implementation details
+
+/// Opaque declaration of a cilk_fiber_sysdep object.
+struct cilk_fiber_sysdep;
+
+/**
+ * cilk_fiber is a base-class for system-dependent fiber implementations.
+ */
+struct cilk_fiber : protected cilk_fiber_data
+{
+ protected:
+ // This is a rare acceptable use of protected inheritence and protected
+ // variable access: when the base class and derived class collaborate
+ // tightly to comprise a single component.
+
+ /// For overloading constructor of cilk_fiber.
+ enum from_thread_t { from_thread = 1 };
+
+ // Boolean flags capturing the status of the fiber.
+ // Each one can be set independently.
+ // A default fiber is constructed with a flag value of 0.
+ static const int RESUMABLE = 0x01; ///< True if the fiber is in a suspended state and can be resumed.
+ static const int ALLOCATED_FROM_THREAD = 0x02; ///< True if fiber was allocated from a thread.
+
+ cilk_fiber_proc m_start_proc; ///< Function to run on start up/reset
+ cilk_fiber_proc m_post_switch_proc; ///< Function that executes when we first switch to a new fiber from a different one.
+
+ cilk_fiber* m_pending_remove_ref;///< Fiber to possibly delete on start up or resume
+ cilk_fiber_pool* m_pending_pool; ///< Pool where m_pending_remove_ref should go if it is deleted.
+ unsigned m_flags; ///< Captures the status of this fiber.
+
+#if NEED_FIBER_REF_COUNTS
+ volatile long m_outstanding_references; ///< Counts references to this fiber.
+#endif
+
+ /// Creates a fiber with NULL data.
+ cilk_fiber();
+
+ /**
+ * @brief Creates a fiber with user-specified arguments.
+ *
+ * @param stack_size Size of stack to use for this fiber.
+ */
+ cilk_fiber(std::size_t stack_size);
+
+ /// Empty destructor.
+ ~cilk_fiber();
+
+ /**
+ * @brief Performs any actions that happen after switching from
+ * one fiber to another.
+ *
+ * These actions are:
+ * 1. Execute m_post_switch_proc on a fiber.
+ * 2. Do any pending deallocations from the previous fiber.
+ */
+ void do_post_switch_actions();
+
+ /**
+ *@brief Helper method that converts a @c cilk_fiber object into a
+ * @c cilk_fiber_sysdep object.
+ *
+ * The @c cilk_fiber_sysdep object contains the system-dependent parts
+ * of the implementation of a @\c cilk_fiber.
+ *
+ * We could have @c cilk_fiber_sysdep inherit from @c cilk_fiber and
+ * then use virtual functions. But since a given platform only uses
+ * one definition of @c cilk_fiber_sysdep at a time, we statically
+ * cast between them.
+ */
+ inline cilk_fiber_sysdep* sysdep();
+
+ /**
+ * @brief Set resumable flag to specified state.
+ */
+ inline void set_resumable(bool state) {
+ m_flags = state ? (m_flags | RESUMABLE) : (m_flags & (~RESUMABLE));
+ }
+
+ /**
+ *@brief Set the allocated_from_thread flag.
+ */
+ inline void set_allocated_from_thread(bool state) {
+ m_flags = state ? (m_flags | ALLOCATED_FROM_THREAD) : (m_flags & (~ALLOCATED_FROM_THREAD));
+ }
+
+ public:
+
+ /**
+ * @brief Allocates and initializes a new cilk_fiber, either from
+ * the specified pool or from the heap.
+ *
+ * @pre pool should not be NULL.
+ */
+ static cilk_fiber* allocate(cilk_fiber_pool* pool);
+
+ /**
+ * @brief Allocates a fiber from the heap.
+ */
+ static cilk_fiber* allocate_from_heap(size_t stack_size);
+
+ /**
+ * @brief Return a fiber to the heap.
+ */
+ void deallocate_to_heap();
+
+ /**
+ * @brief Reset the state of a fiber just allocated from a pool.
+ */
+ void reset_state(cilk_fiber_proc start_proc);
+
+ /**
+ * @brief Remove a reference from this fiber, possibly
+ * deallocating it if the reference count becomes 0.
+ *
+ * @param pool The fiber pool to which this fiber should be returned.
+ * @return The final reference count.
+ */
+ int remove_reference(cilk_fiber_pool* pool);
+
+ /**
+ * @brief Deallocate the fiber by returning it to the pool.
+ * @pre This method should only be called if the reference count
+ * is 0.
+ *
+ * @param pool The fiber pool to return this fiber to. If NULL,
+ * fiber is returned to the heap.
+ */
+ void deallocate_self(cilk_fiber_pool *pool);
+
+ /** @brief Allocates and intializes this thread's main fiber. */
+ static cilk_fiber* allocate_from_thread();
+
+ /** @brief Deallocate a fiber created from a thread,
+ * possibly destroying it.
+ *
+ * This method decrements the reference count of this fiber by 2,
+ * and destroys the fiber if the reference count is 0.
+ *
+ * OS-specific cleanup for the fiber executes unconditionally with for
+ * this method. The destruction of the actual object, however, does
+ * not occur unless the reference count is 0.
+ *
+ * @return Final reference count. If the count is 0, the fiber was
+ * returned to the heap.
+ */
+ int deallocate_from_thread();
+
+ /** @brief Removes a reference from this fiber.
+ *
+ * This method deallocates this fiber if the reference count
+ * becomes 0.
+ *
+ * @pre This fiber must be allocated from a thread.
+ * @return The final reference count of this fiber.
+ */
+ int remove_reference_from_thread();
+
+#if SUPPORT_GET_CURRENT_FIBER
+ /** @brief Get the current fiber from TLS.
+ *
+ * @note This function is only used for testing the runtime.
+ */
+ static cilk_fiber* get_current_fiber();
+#endif
+
+ /** @brief Suspend execution on current fiber resumes other fiber.
+ *
+ * Control returns after resuming execution of the self fiber.
+ */
+ void suspend_self_and_resume_other(cilk_fiber* other);
+
+
+ /** @brief Removes a reference from the currently executing fiber
+ * and resumes other fiber.
+ *
+ * This fiber may be returned to a pool or deallocated.
+ */
+ NORETURN remove_reference_from_self_and_resume_other(cilk_fiber_pool* self_pool,
+ cilk_fiber* other);
+
+ /** @brief Set the proc method to execute immediately after a switch
+ * to this fiber.
+ *
+ * @param post_switch_proc Proc method to execute immediately
+ * after switching to this fiber.
+ */
+ inline void set_post_switch_proc(cilk_fiber_proc post_switch_proc) {
+ m_post_switch_proc = post_switch_proc;
+ }
+
+ /** @brief Returns true if this fiber is resumable.
+ *
+ * A fiber is considered resumable when it is not currently being
+ * executed.
+ */
+ inline bool is_resumable(void) {
+ return (m_flags & RESUMABLE);
+ }
+
+ /** @brief Returns true if fiber was allocated from a thread. */
+ inline bool is_allocated_from_thread(void) {
+ return (m_flags & ALLOCATED_FROM_THREAD);
+ }
+
+ /**
+ *@brief Get the address at the base of the stack for this fiber.
+ */
+ inline char* get_stack_base();
+
+ /** @brief Return the data for this fiber. */
+ cilk_fiber_data* get_data() { return this; }
+
+ /** @brief Return the data for this fiber. */
+ cilk_fiber_data const* get_data() const { return this; }
+
+
+#if NEED_FIBER_REF_COUNTS
+ /** @brief Verifies that this fiber's reference count equals v. */
+ inline void assert_ref_count_equals(long v) {
+ #if FIBER_CHECK_REF_COUNTS
+ CILK_ASSERT(m_outstanding_references >= v);
+ #endif
+ }
+
+ /** @brief Verifies that this fiber's reference count is at least v. */
+ inline void assert_ref_count_at_least(long v) {
+ #if FIBER_CHECK_REF_COUNTS
+ CILK_ASSERT(m_outstanding_references >= v);
+ #endif
+ }
+
+ /** @brief Get reference count. */
+ inline long get_ref_count() { return m_outstanding_references; }
+
+ /** @brief Initialize reference count.
+ * Operation is not atomic.
+ */
+ inline void init_ref_count(long v) { m_outstanding_references = v; }
+
+ // For Windows, updates to the fiber reference count need to be
+ // atomic, because exceptions can live on a stack that we are not
+ // currently executing on. Thus, we can update the reference
+ // count of a fiber we are not currently executing on.
+
+ /** @brief Increment reference count for this fiber [Windows]. */
+ inline void inc_ref_count() { atomic_inc_ref_count(); }
+
+ /** @brief Decrement reference count for this fiber [Windows]. */
+ inline long dec_ref_count() { return atomic_dec_ref_count(); }
+
+ /** @brief Subtract v from the reference count for this fiber [Windows]. */
+ inline long sub_from_ref_count(long v) { return atomic_sub_from_ref_count(v); }
+#else // NEED_FIBER_REF_COUNTS
+
+ // Without reference counting, we have placeholder methods.
+ inline void init_ref_count(long v) { }
+
+ inline void inc_ref_count() { }
+
+ // With no reference counting, dec_ref_count always return 0.
+ // Thus, anyone checking is always the "last" one.
+ inline long dec_ref_count() { return 0; }
+ inline long sub_from_ref_count(long v) { return 0; }
+
+ // The assert methods do nothing.
+ inline void assert_ref_count_equals(long v) { }
+ inline void assert_ref_count_at_least(long v) { }
+#endif
+
+ /**
+ * @brief Call TBB to tell it about an "interesting" event.
+ *
+ * @param op Value specifying the event to track.
+ */
+ void invoke_tbb_stack_op(__cilk_tbb_stack_op op);
+
+private:
+
+ /**
+ * @brief Helper method: try to allocate a fiber from this pool or
+ * its ancestors without going to the OS / heap.
+ *
+ * Returns allocated pool, or NULL if no pool is found.
+ *
+ * If pool contains a suitable fiber. Return it. Otherwise, try to
+ * recursively grab a fiber from the parent pool, if there is one.
+ *
+ * This method will not allocate a fiber from the heap.
+ */
+ static cilk_fiber* try_allocate_from_pool_recursive(cilk_fiber_pool* pool);
+
+
+#if NEED_FIBER_REF_COUNTS
+ /**
+ * @brief Atomic increment of reference count.
+ */
+ void atomic_inc_ref_count();
+
+ /**
+ * @brief Atomic decrement of reference count.
+ */
+ long atomic_dec_ref_count();
+
+ /**
+ * @brief Atomic subtract of v from reference count.
+ * @param v Value to subtract.
+ */
+ long atomic_sub_from_ref_count(long v);
+#endif // NEED_FIBER_REF_COUNTS
+
+};
+
+#endif // __cplusplus
+
+#endif // ! defined(INCLUDED_CILK_FIBER_DOT_H)
diff --git a/libcilkrts/runtime/cilk_malloc.c b/libcilkrts/runtime/cilk_malloc.c
new file mode 100644
index 00000000000..9d02c52d037
--- /dev/null
+++ b/libcilkrts/runtime/cilk_malloc.c
@@ -0,0 +1,84 @@
+/* cilk_malloc.c -*-C-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ **************************************************************************/
+
+#include "cilk_malloc.h"
+
+#include <stdlib.h>
+#if defined _WIN32 || defined _WIN64 || defined __linux__
+#include <malloc.h>
+#define HAS_MEMALIGN 1
+#endif
+#ifdef __VXWORKS__
+#define HAS_MEMALIGN 1
+#include <memLib.h>
+#endif
+
+#define PREFERRED_ALIGNMENT 64 /* try to keep runtime system data
+ structures within one cache line */
+
+void *__cilkrts_malloc(size_t size)
+{
+ /* TODO: check for out of memory */
+#ifdef _WIN32
+ return _aligned_malloc(size, PREFERRED_ALIGNMENT);
+#elif defined HAS_MEMALIGN
+ return memalign(PREFERRED_ALIGNMENT, size);
+#else
+ return malloc(size);
+#endif
+}
+
+void *__cilkrts_realloc(void *ptr, size_t size)
+{
+#ifdef _WIN32
+ return _aligned_realloc(ptr, size, PREFERRED_ALIGNMENT);
+#else
+ return realloc(ptr, size);
+#endif
+}
+
+void __cilkrts_free(void *ptr)
+{
+#ifdef _WIN32
+ _aligned_free(ptr);
+#else
+ free(ptr);
+#endif
+}
+
+/* End cilk_malloc.c */
diff --git a/libcilkrts/runtime/cilk_malloc.h b/libcilkrts/runtime/cilk_malloc.h
new file mode 100644
index 00000000000..fa0fa6d5c9d
--- /dev/null
+++ b/libcilkrts/runtime/cilk_malloc.h
@@ -0,0 +1,90 @@
+/* cilk_malloc.h -*-C++-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ **************************************************************************/
+
+/**
+ * @file cilk_malloc.h
+ *
+ * @brief Provides replacement memory allocation functions to allocate
+ * (and free) memory on cache line boundaries, if supported by the OS.
+ *
+ * If aligned memory functions are not provided by the OS, the calls just
+ * pass through to the standard memory allocation functions.
+ */
+
+#ifndef INCLUDED_CILK_MALLOC_DOT_H
+#define INCLUDED_CILK_MALLOC_DOT_H
+
+#include <cilk/common.h>
+#include <stddef.h>
+
+#include "rts-common.h"
+
+__CILKRTS_BEGIN_EXTERN_C
+
+/**
+ * malloc replacement function to allocate memory aligned on a cache line
+ * boundary if aligned memory allocations are supported by the OS.
+ *
+ * @param size Number of bytes to allocate.
+ *
+ * @return pointer to memory block allocated, or NULL if unsuccessful.
+ */
+COMMON_PORTABLE void *__cilkrts_malloc(size_t size);
+
+/**
+ * realloc replacement function to allocate memory aligned on a cache line
+ * boundary if aligned memory allocations are supported by the OS.
+ *
+ * @param ptr Block to be reallocated.
+ * @param size Number of bytes to allocate.
+ *
+ * @return pointer to memory block allocated, or NULL if unsuccessful.
+ */
+COMMON_PORTABLE void *__cilkrts_realloc(void *ptr, size_t size);
+
+/**
+ * free replacement function to deallocate memory aligned on a cache line
+ * boundary if aligned memory allocations are supported by the OS.
+ *
+ * @param ptr Block to be freed.
+ */
+COMMON_PORTABLE void __cilkrts_free(void *ptr);
+
+__CILKRTS_END_EXTERN_C
+
+#endif // ! defined(INCLUDED_CILK_MALLOC_DOT_H)
diff --git a/libcilkrts/runtime/component.h b/libcilkrts/runtime/component.h
new file mode 100644
index 00000000000..64ff3e5fc42
--- /dev/null
+++ b/libcilkrts/runtime/component.h
@@ -0,0 +1,52 @@
+/* component.h -*-C++-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ **************************************************************************/
+
+#ifndef INCLUDED_COMPONENT_DOT_H
+#define INCLUDED_COMPONENT_DOT_H
+
+#define COMPONENT_NAME "Intel® Cilk™ Plus Runtime"
+
+#define COMPONENT_INTERNAL_NAME COMPONENT_NAME
+
+#define COMPONENT_FILENAME "CILKRTS20"
+
+#define BuildVersionString(_major, _minor, _build, _rev) #_major "," #_minor "," #_build "," #_rev
+
+#define COMPONENT_VERSION_STRING BuildVersionString (VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD, VERSION_REVISION)
+
+#endif // ! defined(INCLUDED_COMPONENT_DOT_H)
diff --git a/libcilkrts/runtime/config/generic/cilk-abi-vla.c b/libcilkrts/runtime/config/generic/cilk-abi-vla.c
new file mode 100644
index 00000000000..98fefa101bd
--- /dev/null
+++ b/libcilkrts/runtime/config/generic/cilk-abi-vla.c
@@ -0,0 +1,107 @@
+/* cilk-abi-vla.cpp -*-C++-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ **************************************************************************/
+
+/*
+ * Implementation of Variable Length Array (VLA) ABI.
+ *
+ * The compiler calls these functions to allocate Variable Length Arrays
+ * at runtime. The compiler must guarantee that __cilkrts_stack_free() is
+ * called to cleanup any memory allocated by __cilkrts_stack_alloc().
+ *
+ * This generic implementation always allocates the memory from the heap.
+ * Optimally, the implementation should expand the frame of the calling
+ * function if possible, since that will be faster. See the x86 version
+ * for one possible implementation.
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#include "internal/abi.h"
+#include "cilk-abi-vla-internal.h"
+
+#define c_cilk_ptr_from_heap 0xc2f2f00d
+#define c_cilk_ptr_from_stack 0xc3f30d0f
+
+// Allocate space for a variable length array
+CILK_ABI(__cilkrts_void_ptr)
+__cilkrts_stack_alloc(
+ __cilkrts_stack_frame *sf,
+ size_t size,
+ size_t distance_from_sp_to_alloca_area,
+ uint32_t align, // align is always >= minimum stack alignment and
+ // >= ptr_size as well, and must be a power of 2.
+ uint32_t needs_tag // non-zero if the pointer being returned needs to
+ // be tagged
+)
+{
+ // full_size will be a multiple of align, and contains
+ // enough extra space to allocate a marker.
+ size_t full_size = (size + align - 1) & ~(align - 1);
+
+ // Allocate memory from the heap. The compiler is responsible
+ // for guaranteeing us a chance to free it before the function
+ // exits
+
+ return (void *)vla_internal_heap_alloc(sf, full_size, align);
+}
+
+// Free the space allocated for a variable length array.
+CILK_ABI(void)
+__cilkrts_stack_free(
+ __cilkrts_stack_frame *sf,
+ void *p,
+ size_t size,
+ size_t distance_from_sp_to_alloca_area,
+ uint32_t align, // same requirements as for align in allocation,
+ // and must match alignment that was passed when
+ // doing the allocation
+ uint32_t known_from_stack // non-zero if this is known to be allocated
+ // on the stack, and therefore has no tag
+)
+{
+ // full_size will be a multiple of align, and contains
+ // enough extra space to allocate a marker if one was needed.
+ size_t full_size = (size + align - 1) & ~(align - 1);
+
+ // Just free the allocated memory to the heap since we don't know
+ // how to expand/contract the calling frame
+ vla_internal_heap_free(t, full_size);
+}
diff --git a/libcilkrts/runtime/config/generic/os-fence.h b/libcilkrts/runtime/config/generic/os-fence.h
new file mode 100644
index 00000000000..841307a5296
--- /dev/null
+++ b/libcilkrts/runtime/config/generic/os-fence.h
@@ -0,0 +1,53 @@
+/* os.h -*-C++-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ **************************************************************************/
+
+/*
+ * void __cilkrts_fence(void)
+ *
+ * Executes an MFENCE instruction to serialize all load and store instructions
+ * that were issued prior the MFENCE instruction. This serializing operation
+ * guarantees that every load and store instruction that precedes the MFENCE
+ * instruction is globally visible before any load or store instruction that
+ * follows the MFENCE instruction. The MFENCE instruction is ordered with
+ * respect to all load and store instructions, other MFENCE instructions, any
+ * SFENCE and LFENCE instructions, and any serializing instructions (such as
+ * the CPUID instruction).
+ */
+
+COMMON_SYSDEP void __cilkrts_fence(void); ///< MFENCE instruction
+
diff --git a/libcilkrts/runtime/config/generic/os-unix-sysdep.c b/libcilkrts/runtime/config/generic/os-unix-sysdep.c
new file mode 100644
index 00000000000..fda7fc414bc
--- /dev/null
+++ b/libcilkrts/runtime/config/generic/os-unix-sysdep.c
@@ -0,0 +1,94 @@
+/* os-unix-sysdep.c -*-C-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *************************************************************************
+ *
+ * This file contains generic implementations of system-specific code for
+ * Unix-based systems
+ */
+
+#include "os.h"
+#include "sysdep.h"
+
+/*
+ * The cycle counter is used for debugging. This funciton is only called if
+ * CILK_PROFILE is defined when the runtime is built.
+ */
+COMMON_SYSDEP unsigned long long __cilkrts_getticks(void)
+{
+# warning "unimplemented cycle counter"
+ return 0;
+}
+
+/*
+ * A "short pause" - called from the Cilk runtime's spinloops.
+ */
+COMMON_SYSDEP void __cilkrts_short_pause(void)
+{
+# warning __cilkrts_short_pause empty
+}
+
+/*
+ * Interlocked exchange - used to implement the Cilk runtime's spinloops
+ */
+COMMON_SYSDEP int __cilkrts_xchg(volatile int *ptr, int x)
+{
+ x = __sync_lock_test_and_set(ptr, x);
+ return x;
+}
+
+
+/*
+ * Restore the floating point state that is stored in a stack frame at each
+ * spawn. This should be called each time a frame is resumed.
+ *
+ * Only valid for IA32 and Intel64 processors.
+ */
+void restore_x86_fp_state (__cilkrts_stack_frame *sf)
+{
+}
+
+
+/*
+ * Save the floating point state to the __cilkrts_stack_frame at each spawn.
+ *
+ * Architecture-specific - Should only be needed on IA32 and Intel64
+ * processors.
+ */
+void sysdep_save_fp_ctrl_state(__cilkrts_stack_frame *sf)
+{
+}
+
diff --git a/libcilkrts/runtime/config/x86/cilk-abi-vla.c b/libcilkrts/runtime/config/x86/cilk-abi-vla.c
new file mode 100644
index 00000000000..38c2630a1e6
--- /dev/null
+++ b/libcilkrts/runtime/config/x86/cilk-abi-vla.c
@@ -0,0 +1,441 @@
+/* cilk-abi-vla.cpp -*-C++-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ **************************************************************************/
+
+/*
+ * Implementation of Variable Length Array (VLA) ABI.
+ *
+ * __cilkrts_stack_alloc() and __cilkrts_stack_free must be compiled
+ * such that ebp/rbp is used for the stack frames. This is done by having
+ * each of them use alloca, which forces the special frame types needed on
+ * each of the ABIs. Additionally, for some forms of stack frame, special
+ * care must be taken because the alloca space may not be at the bottom of the
+ * stack frame of the caller. For Intel64 windows, and for some options
+ * with other ABIs, a preallocated parameter block may exist on the stack
+ * at a lower address than the alloca. If this is the case, the parameter
+ * distance_from_sp_to_alloca_area will be non-zero, and will indicate how
+ * much pre-allocated parameter space resides in the caller's stack frame
+ * between the alloca area, and the bottom of the stack when the call to
+ * the cilkrts is made. As such, when non-zero it also includes any space
+ * used for passing the cilkrts_stack_alloc or cilkrts_stack_free parameters.
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+// Getting a definition for alloca appears to be a pain in the butt. Here's
+// a variant on what's recommended in the autoconf doc
+#if defined _MSC_VER
+# include <malloc.h>
+# define alloca _alloca
+#elif defined HAVE_ALLOCA_H
+# include <alloca.h>
+#elif defined __GNUC__
+# define alloca __builtin_alloca
+#elif defined _AIX
+# define alloca __alloca
+#else
+# include <stddef.h>
+# ifdef __cplusplus
+extern "C"
+# endif
+void *alloca (size_t);
+#endif
+
+#ifdef _WIN32
+# define INLINE static __inline
+# pragma warning(disable:1025) // Don't whine about zero extending result of unary operation
+#else
+# define INLINE static inline
+#endif
+
+
+#include "internal/abi.h"
+#include "cilk-abi-vla-internal.h"
+
+#if defined(__x86_64) || defined(_M_X64)
+INLINE void setsp(void *val)
+{
+ __asm__("movq %0, %%rsp" : : "r"(val): "rsp");
+}
+INLINE char* getsp(void)
+{
+ void *res;
+
+ __asm__("movq %%rsp, %0" : "=r"(res): : "rsp");
+ return res;
+}
+INLINE char* getbp(void)
+{
+ void *res;
+
+ __asm__("movq %%rbp, %0" : "=r"(res): : "rbp");
+ return res;
+}
+INLINE void copy_frame_down_and_move_bp(
+ char *dst,
+ char *src,
+ size_t cpy_bytes,
+ char *new_ebp
+)
+{
+ // In this version, dst is guaranteed to be lower address than src,
+ // therefore copying upwards from src into dst is safe in case
+ // there is overlap. The number of bytes is also guaranteed to be
+ // a multiple of 8, and the copy is done in 64 bit word chunks for
+ // best efficiency.
+ __asm__(
+ "movq %0, %%rdi;"
+ "movq %1, %%rsi;"
+ "movq %2, %%rcx;"
+ "shrq $3, %%rcx;"
+ "rep movsq;"
+ "movq %3, %%rbp" :
+ :
+ "rm"(dst), "rm"(src), "rm"(cpy_bytes), "rm"(new_ebp) :
+ "rsi", "rdi", "rcx", "rbp", "memory");
+}
+INLINE void copy_frame_up_and_move_bp(
+ char *dst,
+ char *src,
+ size_t cpy_bytes,
+ char *new_ebp
+)
+{
+ // In this version, dst is guaranteed to be higher address than src,
+ // therefore copying downwards from src into dst is safe in case
+ // there is overlap. The number of bytes is also guaranteed to be
+ // a multiple of 8, and the copy is done in 64 bit word chunks for
+ // best efficiency.
+ dst += cpy_bytes - 8;
+ src += cpy_bytes - 8;
+ __asm__(
+ "movq %0, %%rdi;"
+ "movq %1, %%rsi;"
+ "movq %2, %%rcx;"
+ "shrq $3, %%rcx;"
+ "std; rep movsq; cld;"
+ "movl %3, %%rbp;" :
+ :
+ "rm"(dst), "rm"(src), "rm"(cpy_bytes), "rm"(new_ebp) :
+ "rsi", "rdi", "rcx", "rbp", "memory");
+}
+#else
+INLINE void setsp(void *val)
+{
+ __asm__("movl %0, %%esp" : : "r"(val): "esp");
+}
+INLINE char* getsp(void)
+{
+ void *res;
+
+ __asm__("movl %%esp, %0" : "=r"(res): : "esp");
+ return res;
+}
+INLINE char* getbp(void)
+{
+ void *res;
+
+ __asm__("movl %%ebp, %0" : "=r"(res): : "ebp");
+ return res;
+}
+INLINE void copy_frame_down_and_move_bp(
+ char *dst,
+ char *src,
+ size_t cpy_bytes,
+ char *new_ebp
+)
+{
+ // In this version, dst is guaranteed to be lower address than src,
+ // therefore copying upwards from src into dst is safe in case
+ // there is overlap. The number of bytes is also guaranteed to be
+ // a multiple of 4, and the copy is done in 32 bit word chunks for
+ // best efficiency.
+ __asm__(
+ "movl %0, %%edi;"
+ "movl %1, %%esi;"
+ "movl %2, %%ecx;"
+ "shrl $2, %%ecx;"
+ "rep movsd;"
+ "movl %3, %%ebp" :
+ :
+ "rm"(dst), "rm"(src), "rm"(cpy_bytes), "rm"(new_ebp) :
+ "esi", "edi", "ecx", "ebp", "memory");
+}
+INLINE void copy_frame_up_and_move_bp(
+ char *dst,
+ char *src,
+ size_t cpy_bytes,
+ char *new_ebp
+)
+{
+ // In this version, dst is guaranteed to be higher address than src,
+ // therefore copying downwards from src into dst is safe in case
+ // there is overlap. The number of bytes is also guaranteed to be
+ // a multiple of 4, and the copy is done in 32 bit word chunks for
+ // best efficiency.
+ dst += cpy_bytes - 4;
+ src += cpy_bytes - 4;
+ __asm__(
+ "movl %0, %%edi;"
+ "movl %1, %%esi;"
+ "movl %2, %%ecx;"
+ "shrl $2, %%ecx;"
+ "std; rep movsd; cld;"
+ "movl %3, %%ebp" :
+ // "=D"(dst), "=S"(src), "=C"(cpy_bytes) :
+ :
+ "rm"(dst), "rm"(src), "rm"(cpy_bytes), "rm"(new_ebp) :
+ "esi", "edi", "ecx", "ebp", "memory");
+}
+#endif
+
+
+#define c_cilk_ptr_from_heap 0xc2f2f00d
+#define c_cilk_ptr_from_stack 0xc3f30d0f
+
+CILK_ABI(__cilkrts_void_ptr)
+__cilkrts_stack_alloc(
+ __cilkrts_stack_frame *sf,
+ size_t size,
+ size_t distance_from_sp_to_alloca_area,
+ uint32_t align, // align is always >= minimum stack alignment and
+ // >= ptr_size as well, and must be a power of 2.
+ uint32_t needs_tag // non-zero if the pointer being returned needs to
+ // be tagged
+)
+{
+#ifdef __INTEL_COMPILER
+ // full_size will be a multiple of align, and contains
+ // enough extra space to allocate a marker.
+ size_t full_size = (size + align - 1) & ~(align - 1);
+
+ if (needs_tag) {
+ full_size += align;
+ }
+
+ char *t;
+ if (sf->worker != 0 &&
+ ((sf->flags & CILK_FRAME_UNSYNCHED) != 0)) {
+ t = vla_internal_heap_alloc(sf, full_size, align);
+ if (needs_tag) {
+ t += align;
+ ((uint32_t*)t)[-1] = c_cilk_ptr_from_heap;
+ }
+ return (void *)t;
+ }
+
+ // stack is still synced, allocate full_size from esp,
+ // and record in 32 bits immediately below the space
+ // allocated that this was space that this was
+ // allocated in the stack.
+ char *old_ebp = getbp();
+ char *old_esp = getsp();
+
+ // make top_ptr point to base of first parameter.
+ char *top_ptr = ((char *)(_AddressOfReturnAddress()) +
+ sizeof(char *));
+ size_t param_size = 0;
+
+#if defined(__x86_64)
+ // For Intel64 linux & MACH ABI, all the parameters were passed in
+ // register, so top of the stack frame above the return address
+ // is just the size of the return address plus
+ // distance_from_sp_to_alloca_area on the chance that the alloca
+ // area isn't at the very bottom of the calling functions stack.
+#elif defined(__MACH__)
+ // For ia32 MACH, parameter size is always a mutliple of 16
+ // bytes to keep the stack 16 byte aligned. So we need to round
+ // number of parameters up to multiple of 4.
+ param_size = 8 * sizeof(char *);
+#else
+ // For both windows Intel64 ABI, and the IA32 windows and
+ // linux ABIs, space is reserved on the stack for all these
+ // parameters. param_size is 5 * size of a stack slot.
+ param_size = 5 * sizeof(char *);
+#endif
+
+ // now make top_ptr point above the params, or if
+ // distance_from_sp_to_alloca_area is not zero, make
+ // it point above that area. When non-zero,
+ // distance_from_sp_to_alloca area is expected to contain
+ // the parameter space, so we only add one or the other,
+ // not both.
+ top_ptr += (distance_from_sp_to_alloca_area != 0) ?
+ distance_from_sp_to_alloca_area : param_size;
+
+ // t needs to end up at current value of top_ptr less full_size and less
+ // distance_from_sp_to_alloca_area and
+ // then rounded down to the alignment needed. Then we have to bump
+ // esp down by current frame_size, so that when all is done with respect
+ // to executing the return sequence, the final value of esp will be the
+ // same value as t.
+ t = (top_ptr - full_size) - distance_from_sp_to_alloca_area;
+ intptr_t temp = (intptr_t)t;
+ temp &= ~((intptr_t)(align - 1));
+ t = (char *)temp;
+
+ // ok, the value of t is set where we need it. Now set esp
+ // to the value of t less the current frame size.
+ // So now when we do regular return esp should be left such
+ // that it has moved down by full_size.
+ size_t cur_fm_size = (top_ptr - old_esp);
+ char *new_esp = t - cur_fm_size;
+ char *new_ebp = old_ebp - (old_esp - new_esp);
+
+ // extend the stack down by at least the difference between where
+ // I want it to be and where it currently is. This should take care
+ // of touching any pages necessary.
+ char *foo = alloca(old_esp - new_esp);
+ setsp(foo < new_esp ? foo : new_esp);
+
+ // Now set esp exactly where I want it.
+ // setsp(new_esp);
+
+ copy_frame_down_and_move_bp(new_esp, old_esp, cur_fm_size, new_ebp);
+
+ if (needs_tag) {
+ t += align;
+ ((uint32_t*)t)[-1] = c_cilk_ptr_from_stack;
+ }
+
+ return t;
+#else // Not __INTEL_COMPILER
+ // Not supported unless we can figure out how to get the size of the frame
+ return NULL;
+#endif
+}
+
+// This frees the space allocated for a variable length array.
+CILK_ABI(void)
+__cilkrts_stack_free(
+ __cilkrts_stack_frame *sf,
+ void *p,
+ size_t size,
+ size_t distance_from_sp_to_alloca_area,
+ uint32_t align, // same requirements as for align in allocation,
+ // and must match alignment that was passed when
+ // doing the allocation
+ uint32_t known_from_stack // non-zero if this is known to be allocated
+ // on the stack, and therefore has no tag
+)
+{
+#ifdef __INTEL_COMPILER
+ uint32_t *t = (uint32_t*)p;
+
+ // full_size will be a multiple of align, and contains
+ // enough extra space to allocate a marker if one was needed.
+ size_t full_size = (size + align - 1) & ~(align - 1);
+ if (known_from_stack == 0) {
+ // if the compiler hasn't told the run-time that this is
+ // known to be on the stack, then this pointer must have been
+ // tagged such that the run-time can tell.
+ assert(t[-1] == c_cilk_ptr_from_stack ||
+ t[-1] == c_cilk_ptr_from_heap);
+
+ known_from_stack = t[-1] == c_cilk_ptr_from_stack;
+ full_size += align; // accounts for extra space for marker
+ t = (uint32_t *)(((char *)t) - align);
+ }
+
+ if (known_from_stack) {
+ // alloca useage forces an ebp/rbp based stack frame even though
+ // 0 and unused.
+ char *foo = alloca(0);
+ if (sf->worker == 0 || (sf->flags & CILK_FRAME_UNSYNCHED) == 0) {
+ // p was allocated from current stack frame and we
+ // are synced on current stack frame. Return the
+ // amount of the stack that needs to be freed.
+ char *old_ebp = getbp();
+ char *old_esp = getsp();
+
+ // make top_ptr point to base of first parameter.
+ char *top_ptr = ((char *)(_AddressOfReturnAddress()) +
+ sizeof(char *));
+ size_t param_size = 0;
+
+#if defined(__x86_64)
+ // For Intel64 linux & MACH ABI, all the parameters were passed in
+ // register, so top of the stack frame above the return address
+ // is just the size of the return address plus
+ // distance_from_sp_to_alloca_area on the chance that the alloca
+ // area isn't at the very bottom of the calling functions stack.
+#elif defined(__MACH__)
+ // For ia32 MACH, parameter size is always a mutliple of 16
+ // bytes to keep the stack 16 byte aligned. So we need to round
+ // number of parameters up to multiple of 4.
+ param_size = 8 * sizeof(char *);
+#else
+ // For both windows Intel64 ABI, and the IA32 windows and
+ // linux ABIs, space is reserved on the stack for all these
+ // parameters. param_size is 5 * size of a stack slot.
+ param_size = 6 * sizeof(char *);
+#endif
+
+ // now make top_ptr point above the params, or if
+ // distance_from_sp_to_alloca_area is not zero, make
+ // it point above that area. When non-zero,
+ // distance_from_sp_to_alloca area is expected to contain
+ // the parameter space, so we only add one or the other,
+ // not both.
+ top_ptr += (distance_from_sp_to_alloca_area != 0) ?
+ distance_from_sp_to_alloca_area : param_size;
+
+ size_t cur_fm_size = (top_ptr - old_esp);
+ char *new_esp = old_esp + full_size;
+ char *new_ebp = old_ebp + full_size;
+
+ copy_frame_up_and_move_bp(new_esp, old_esp, cur_fm_size, new_ebp);
+ setsp(new_esp);
+ }
+ else {
+ // p was allocated on stack frame, but that is
+ // no longer the current stack frame. Need to adjust the
+ // saved esp that is somewhere in the cilk runtime so that
+ // on sync, esp will be cut back correctly.
+ vla_free_from_original_stack(sf, full_size);
+ }
+ }
+ else {
+ vla_internal_heap_free(t, full_size);
+ }
+#else // Not __INTEL_COMPILER
+ // Not supported unless we can figure out how to get the size of the frame
+#endif
+}
diff --git a/libcilkrts/runtime/config/x86/os-fence.h b/libcilkrts/runtime/config/x86/os-fence.h
new file mode 100644
index 00000000000..ec704e94ef2
--- /dev/null
+++ b/libcilkrts/runtime/config/x86/os-fence.h
@@ -0,0 +1,72 @@
+/* os.h -*-C++-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ **************************************************************************/
+
+/* gcc before 4.4 does not implement __sync_synchronize properly */
+#if (__ICC >= 1110 && !(__MIC__ || __MIC2__)) \
+ || (!defined __ICC && __GNUC__ * 10 + __GNUC_MINOR__ > 43)
+# define HAVE_SYNC_INTRINSICS 1
+#endif
+
+
+/*
+ * void __cilkrts_fence(void)
+ *
+ * Executes an MFENCE instruction to serialize all load and store instructions
+ * that were issued prior the MFENCE instruction. This serializing operation
+ * guarantees that every load and store instruction that precedes the MFENCE
+ * instruction is globally visible before any load or store instruction that
+ * follows the MFENCE instruction. The MFENCE instruction is ordered with
+ * respect to all load and store instructions, other MFENCE instructions, any
+ * SFENCE and LFENCE instructions, and any serializing instructions (such as
+ * the CPUID instruction).
+ */
+#ifdef HAVE_SYNC_INTRINSICS
+# define __cilkrts_fence() __sync_synchronize()
+#elif defined __ICC || defined __GNUC__
+ /* mfence is a strict subset of lock add but takes longer on many
+ * processors. */
+// # define __cilkrts_fence() __asm__ volatile ("mfence")
+ /* On MIC, fence seems to be completely unnecessary.
+ * Just for simplicity of 1st implementation, it defaults to x86 */
+# define __cilkrts_fence() __asm__ volatile ("lock addl $0,(%rsp)")
+// #elif defined _WIN32
+// # pragma intrinsic(_ReadWriteBarrier)
+// # define __cilkrts_fence() _ReadWriteBarrier()
+#else
+COMMON_SYSDEP void __cilkrts_fence(void); ///< MFENCE instruction
+#endif
diff --git a/libcilkrts/runtime/config/x86/os-unix-sysdep.c b/libcilkrts/runtime/config/x86/os-unix-sysdep.c
new file mode 100644
index 00000000000..881bc3f4283
--- /dev/null
+++ b/libcilkrts/runtime/config/x86/os-unix-sysdep.c
@@ -0,0 +1,123 @@
+/* os-unix-sysdep.c -*-C-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *************************************************************************
+ *
+ * This file contains system-specific code for Unix systems
+ */
+
+#include "os.h"
+#include "sysdep.h"
+#include <internal/abi.h>
+
+// On x86 processors (but not MIC processors), the compiler generated code to
+// save the FP state (rounding mode and the like) before calling setjmp. We
+// will need to restore that state when we resume.
+#ifndef __MIC__
+# if defined(__i386__) || defined(__x86_64)
+# define RESTORE_X86_FP_STATE
+# endif // defined(__i386__) || defined(__x86_64)
+#endif // __MIC__
+
+/* timer support */
+COMMON_SYSDEP unsigned long long __cilkrts_getticks(void)
+{
+#if defined __i386__ || defined __x86_64
+ unsigned a, d;
+ __asm__ volatile("rdtsc" : "=a" (a), "=d" (d));
+ return ((unsigned long long)a) | (((unsigned long long)d) << 32);
+#else
+# warning "unimplemented cycle counter"
+ return 0;
+#endif
+}
+
+COMMON_SYSDEP void __cilkrts_short_pause(void)
+{
+#if __ICC >= 1110
+# if __MIC__ || __MIC2__
+ _mm_delay_32(16); // stall for 16 cycles
+# else
+ _mm_pause();
+# endif
+#elif defined __i386__ || defined __x86_64
+ __asm__("pause");
+#else
+# warning __cilkrts_short_pause empty
+#endif
+}
+
+COMMON_SYSDEP int __cilkrts_xchg(volatile int *ptr, int x)
+{
+#if defined __i386__ || defined __x86_64
+ /* asm statement here works around icc bugs */
+ __asm__("xchgl %0,%a1" :"=r" (x) : "r" (ptr), "0" (x) :"memory");
+#else
+ x = __sync_lock_test_and_set(ptr, x);
+#endif
+ return x;
+}
+
+
+/*
+ * Restore the floating point state that is stored in a stack frame at each
+ * spawn. This should be called each time a frame is resumed.
+ *
+ * Only valid for IA32 and Intel64 processors.
+ */
+void restore_x86_fp_state (__cilkrts_stack_frame *sf) {
+#ifdef RESTORE_X86_FP_STATE
+ __asm__ ( "ldmxcsr %0\n\t"
+ "fnclex\n\t"
+ "fldcw %1"
+ :
+ : "m" (sf->mxcsr), "m" (sf->fpcsr));
+#endif
+}
+
+
+void sysdep_save_fp_ctrl_state(__cilkrts_stack_frame *sf)
+{
+// If we're not going to restore, don't bother saving it
+#ifdef RESTORE_X86_FP_STATE
+ if (CILK_FRAME_VERSION_VALUE(sf->flags) >= 1)
+ {
+ __asm__ ("stmxcsr %0" : "=m" (sf->mxcsr));
+ __asm__ ("fnstsw %0" : "=m" (sf->fpcsr));
+ }
+#endif
+}
+
diff --git a/libcilkrts/runtime/doxygen-layout.xml b/libcilkrts/runtime/doxygen-layout.xml
new file mode 100644
index 00000000000..fabe0ab3cd8
--- /dev/null
+++ b/libcilkrts/runtime/doxygen-layout.xml
@@ -0,0 +1,222 @@
+<doxygenlayout version="1.0">
+
+<!--
+# @copyright
+# Copyright (C) 2011-2013, Intel Corporation
+# All rights reserved.
+#
+# @copyright
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# @copyright
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+# WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+-->
+
+ <!-- Navigation index tabs for HTML output -->
+ <navindex>
+ <tab type="mainpage" visible="yes" title=""/>
+ <tab type="pages" visible="yes" title="" intro=""/>
+ <tab type="modules" visible="yes" title="" intro=""/>
+ <tab type="namespaces" visible="yes" title="">
+ <tab type="namespaces" visible="yes" title="" intro=""/>
+ <tab type="namespacemembers" visible="yes" title="" intro=""/>
+ </tab>
+ <tab type="classes" visible="yes" title="Classes, Structs and Unions">
+ <tab type="classes" visible="yes" title="Classes, Structs and Unions" intro=""/>
+ <tab type="classindex" visible="$ALPHABETICAL_INDEX" title=""/>
+ <tab type="hierarchy" visible="yes" title="" intro=""/>
+ <tab type="classmembers" visible="yes" title="" intro=""/>
+ </tab>
+ <tab type="files" visible="yes" title="">
+ <tab type="files" visible="yes" title="" intro=""/>
+ <tab type="globals" visible="yes" title="" intro=""/>
+ </tab>
+ <tab type="globals" visible="yes" title="Global Functions" intro=""/>
+ <tab type="dirs" visible="yes" title="" intro=""/>
+ <tab type="examples" visible="yes" title="" intro=""/>
+ </navindex>
+
+ <!-- Layout definition for a class page -->
+ <class>
+ <briefdescription visible="yes"/>
+ <includes visible="$SHOW_INCLUDE_FILES"/>
+ <inheritancegraph visible="$CLASS_GRAPH"/>
+ <collaborationgraph visible="$COLLABORATION_GRAPH"/>
+ <allmemberslink visible="yes"/>
+ <memberdecl>
+ <nestedclasses visible="yes" title=""/>
+ <publictypes title=""/>
+ <publicslots title=""/>
+ <signals title=""/>
+ <publicmethods title=""/>
+ <publicstaticmethods title=""/>
+ <publicattributes title=""/>
+ <publicstaticattributes title=""/>
+ <protectedtypes title=""/>
+ <protectedslots title=""/>
+ <protectedmethods title=""/>
+ <protectedstaticmethods title=""/>
+ <protectedattributes title=""/>
+ <protectedstaticattributes title=""/>
+ <packagetypes title=""/>
+ <packagemethods title=""/>
+ <packagestaticmethods title=""/>
+ <packageattributes title=""/>
+ <packagestaticattributes title=""/>
+ <properties title=""/>
+ <events title=""/>
+ <privatetypes title=""/>
+ <privateslots title=""/>
+ <privatemethods title=""/>
+ <privatestaticmethods title=""/>
+ <privateattributes title=""/>
+ <privatestaticattributes title=""/>
+ <friends title=""/>
+ <related title="" subtitle=""/>
+ <membergroups visible="yes"/>
+ </memberdecl>
+ <detaileddescription title=""/>
+ <memberdef>
+ <typedefs title=""/>
+ <enums title=""/>
+ <constructors title=""/>
+ <functions title=""/>
+ <related title=""/>
+ <variables title=""/>
+ <properties title=""/>
+ <events title=""/>
+ </memberdef>
+ <usedfiles visible="$SHOW_USED_FILES"/>
+ <authorsection visible="yes"/>
+ </class>
+
+ <!-- Layout definition for a namespace page -->
+ <namespace>
+ <briefdescription visible="yes"/>
+ <memberdecl>
+ <nestednamespaces visible="yes" title=""/>
+ <classes visible="yes" title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <functions title=""/>
+ <variables title=""/>
+ <membergroups visible="yes"/>
+ </memberdecl>
+ <detaileddescription title=""/>
+ <memberdef>
+ <typedefs title=""/>
+ <enums title=""/>
+ <functions title=""/>
+ <variables title=""/>
+ </memberdef>
+ <authorsection visible="yes"/>
+ </namespace>
+
+ <!-- Layout definition for a file page -->
+ <file>
+ <briefdescription visible="no"/>
+ <includegraph visible="$INCLUDE_GRAPH"/>
+ <includedbygraph visible="$INCLUDED_BY_GRAPH"/>
+ <detaileddescription title="Description"/>
+ <includes visible="no"/>
+ <sourcelink visible="yes"/>
+ <memberdecl>
+ <classes visible="yes" title="Structures and Classes"/>
+ <namespaces visible="yes" title=""/>
+ <defines title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <functions title=""/>
+ <variables title=""/>
+ <membergroups visible="yes"/>
+ </memberdecl>
+ <memberdef>
+ <defines title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <functions title=""/>
+ <variables title=""/>
+ </memberdef>
+ <authorsection/>
+ </file>
+
+ <!-- Layout definition for a group page -->
+ <group>
+ <briefdescription visible="yes"/>
+ <groupgraph visible="$GROUP_GRAPHS"/>
+ <memberdecl>
+ <classes visible="yes" title=""/>
+ <namespaces visible="yes" title=""/>
+ <dirs visible="yes" title=""/>
+ <nestedgroups visible="yes" title=""/>
+ <files visible="yes" title=""/>
+ <defines title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <enumvalues title=""/>
+ <functions title=""/>
+ <variables title=""/>
+ <signals title=""/>
+ <publicslots title=""/>
+ <protectedslots title=""/>
+ <privateslots title=""/>
+ <events title=""/>
+ <properties title=""/>
+ <friends title=""/>
+ <membergroups visible="yes"/>
+ </memberdecl>
+ <detaileddescription title=""/>
+ <memberdef>
+ <pagedocs/>
+ <inlineclasses title=""/>
+ <defines title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <enumvalues title=""/>
+ <functions title=""/>
+ <variables title=""/>
+ <signals title=""/>
+ <publicslots title=""/>
+ <protectedslots title=""/>
+ <privateslots title=""/>
+ <events title=""/>
+ <properties title=""/>
+ <friends title=""/>
+ </memberdef>
+ <authorsection visible="yes"/>
+ </group>
+
+ <!-- Layout definition for a directory page -->
+ <directory>
+ <briefdescription visible="yes"/>
+ <directorygraph visible="yes"/>
+ <memberdecl>
+ <dirs visible="yes"/>
+ <files visible="yes"/>
+ </memberdecl>
+ <detaileddescription title=""/>
+ </directory>
+</doxygenlayout>
diff --git a/libcilkrts/runtime/doxygen.cfg b/libcilkrts/runtime/doxygen.cfg
new file mode 100644
index 00000000000..684dcb51b51
--- /dev/null
+++ b/libcilkrts/runtime/doxygen.cfg
@@ -0,0 +1,1774 @@
+# Doxyfile 1.7.4
+
+# @copyright
+# Copyright (C) 2011-2013, Intel Corporation
+# All rights reserved.
+#
+# @copyright
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# @copyright
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+# WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME = "Intel Cilk Plus Runtime"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER =
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer
+# a quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF =
+
+# With the PROJECT_LOGO tag one can specify an logo or icon that is
+# included in the documentation. The maximum height of the logo should not
+# exceed 55 pixels and the maximum width should not exceed 200 pixels.
+# Doxygen will copy the logo to the output directory.
+
+PROJECT_LOGO =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY =
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
+# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
+# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian,
+# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak,
+# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful if your file system
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like regular Qt-style comments
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
+# interpret the first line (until the first dot) of a Qt-style
+# comment as the brief description. If set to NO, the comments
+# will behave just like regular Qt-style comments (thus requiring
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 8
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for
+# Java. For instance, namespaces will be presented as packages, qualified
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources only. Doxygen will then generate output that is more tailored for
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given extension.
+# Doxygen has a built-in mapping, but you can override or extend it using this
+# tag. The format is ext=language, where ext is a file extension, and language
+# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C,
+# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make
+# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C
+# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions
+# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen.
+
+EXTENSION_MAPPING =
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also makes the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
+# Doxygen will parse them like normal C++ but will assume all classes use public
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate getter
+# and setter methods for a property. Setting this option to YES (the default)
+# will make doxygen replace the get and set methods by a property in the
+# documentation. This will only work if the methods are indeed getting or
+# setting a simple type. If this is not the case, or you want to show the
+# methods anyway, you should set this option to NO.
+
+IDL_PROPERTY_SUPPORT = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and
+# unions are shown inside the group in which they are included (e.g. using
+# @ingroup) instead of on a separate page (for HTML and Man pages) or
+# section (for LaTeX and RTF).
+
+INLINE_GROUPED_CLASSES = NO
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
+# is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically
+# be useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
+# determine which symbols to keep in memory and which to flush to disk.
+# When the cache is full, less often used symbols will be written to disk.
+# For small to medium size projects (<1000 input files) the default value is
+# probably good enough. For larger projects a too small cache size can cause
+# doxygen to be busy swapping symbols to and from disk most of the time
+# causing a significant performance penalty.
+# If the system has enough physical memory increasing the cache will improve the
+# performance by keeping more symbols in memory. Note that the value works on
+# a logarithmic scale so increasing the size by one will roughly double the
+# memory usage. The cache size is given by this formula:
+# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols
+
+SYMBOL_CACHE_SIZE = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base
+# name of the file that contains the anonymous namespace. By default
+# anonymous namespaces are hidden.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = NO
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen
+# will list include files with double quotes in the documentation
+# rather than with sharp brackets.
+
+FORCE_LOCAL_INCLUDES = NO
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen
+# will sort the (brief and detailed) documentation of class members so that
+# constructors and destructors are listed first. If set to NO (the default)
+# the constructors will appear in the respective orders defined by
+# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS.
+# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO
+# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
+# hierarchy of group names into alphabetical order. If set to NO (the default)
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES = YES
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to
+# do proper type resolution of all parameters of a function it will reject a
+# match between the prototype and the implementation of a member function even
+# if there is only one candidate or it is obvious which candidate to choose
+# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen
+# will still accept a match between prototype and implementation in such cases.
+
+STRICT_PROTO_MATCHING = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or macro consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and macros in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES = NO
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
+# This will remove the Files entry from the Quick Index and from the
+# Folder Tree View (if specified). The default is YES.
+
+SHOW_FILES = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
+# Namespaces page.
+# This will remove the Namespaces entry from the Quick Index
+# and from the Folder Tree View (if specified). The default is YES.
+
+SHOW_NAMESPACES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. The create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option.
+# You can optionally specify a file name after the option, if omitted
+# DoxygenLayout.xml will be used as the name of the layout file.
+
+LAYOUT_FILE = doxygen-layout.xml
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# The WARN_NO_PARAMDOC option can be enabled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = ./ \
+ ../include/internal/abi.h \
+ ../include/cilk/cilk_api.h \
+ ../include/cilk/common.h \
+ ./readme.dox
+
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
+# also the default input encoding. Doxygen uses libiconv (or the iconv built
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
+# the list of possible encodings.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh
+# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py
+# *.f90 *.f *.for *.vhd *.vhdl
+
+FILE_PATTERNS =
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE = attributes.h \
+ cilk-ittnotify.h \
+ component.h \
+ rts-common.h \
+ windows-clean.h
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS = _UNWIND_INFO \
+ _UNWIND_CODE \
+ _DISPATCHER_CONTEXT \
+ __cilkrts_stack \
+ pending_exception_info
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output.
+# If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis.
+# Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match.
+# The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty or if
+# non of the patterns match the file name, INPUT_FILTER is applied.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any)
+# and it is also possible to disable source filtering for a specific pattern
+# using *.ext= (so without naming a filter). This option only has effect when
+# FILTER_SOURCE_FILES is enabled.
+
+FILTER_SOURCE_PATTERNS =
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code.
+# Otherwise they will link to the documentation.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = YES
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header. Note that when using a custom header you are responsible
+# for the proper inclusion of any scripts and style sheets that doxygen
+# needs, which is dependent on the configuration options used.
+# It is adviced to generate a default header using "doxygen -w html
+# header.html footer.html stylesheet.css YourConfigFile" and then modify
+# that header. Note that the header is subject to change so you typically
+# have to redo this when upgrading to a newer version of doxygen or when changing the value of configuration settings such as GENERATE_TREEVIEW!
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that
+# the files will be copied as-is; there are no commands or markers available.
+
+HTML_EXTRA_FILES =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output.
+# Doxygen will adjust the colors in the stylesheet and background images
+# according to this color. Hue is specified as an angle on a colorwheel,
+# see http://en.wikipedia.org/wiki/Hue for more information.
+# For instance the value 0 represents red, 60 is yellow, 120 is green,
+# 180 is cyan, 240 is blue, 300 purple, and 360 is red again.
+# The allowed range is 0 to 359.
+
+HTML_COLORSTYLE_HUE = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of
+# the colors in the HTML output. For a value of 0 the output will use
+# grayscales only. A value of 255 will produce the most vivid colors.
+
+HTML_COLORSTYLE_SAT = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to
+# the luminance component of the colors in the HTML output. Values below
+# 100 gradually make the output lighter, whereas values above 100 make
+# the output darker. The value divided by 100 is the actual gamma applied,
+# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2,
+# and 100 does not change the gamma.
+
+HTML_COLORSTYLE_GAMMA = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting
+# this to NO can help when comparing the output of multiple runs.
+
+HTML_TIMESTAMP = YES
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded. For this to work a browser that supports
+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+
+HTML_DYNAMIC_SECTIONS = NO
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files
+# will be generated that can be used as input for Apple's Xcode 3
+# integrated development environment, introduced with OSX 10.5 (Leopard).
+# To create a documentation set, doxygen will generate a Makefile in the
+# HTML output directory. Running make will produce the docset in that
+# directory and running "make install" will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
+# it at startup.
+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+
+GENERATE_DOCSET = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
+# feed. A documentation feed provides an umbrella under which multiple
+# documentation sets from a single provider (such as a company or product suite)
+# can be grouped.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
+# should uniquely identify the documentation set bundle. This should be a
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID = com.Intel.CilkPlusRuntime
+
+# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+
+DOCSET_PUBLISHER_ID = com.Intel.CilkPlusRuntime
+
+# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher.
+
+DOCSET_PUBLISHER_NAME = "Intel Corporation"
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
+# is used to encode HtmlHelp index (hhk), content (hhc) and project file
+# content.
+
+CHM_INDEX_ENCODING =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated
+# that can be used as input for Qt's qhelpgenerator to generate a
+# Qt Compressed Help (.qch) of the generated HTML documentation.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
+# be used to specify the file name of the resulting .qch file.
+# The path specified is relative to the HTML output folder.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#namespace
+
+QHP_NAMESPACE = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#virtual-folders
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to
+# add. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#custom-filters
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see
+# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">
+# Qt Help Project / Custom Filters</a>.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's
+# filter section matches.
+# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">
+# Qt Help Project / Filter Attributes</a>.
+
+QHP_SECT_FILTER_ATTRS =
+
+# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
+# be used to specify the location of Qt's qhelpgenerator.
+# If non-empty doxygen will try to run qhelpgenerator on the generated
+# .qhp file.
+
+QHG_LOCATION =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files
+# will be generated, which together with the HTML files, form an Eclipse help
+# plugin. To install this plugin and make it available under the help contents
+# menu in Eclipse, the contents of the directory containing the HTML and XML
+# files needs to be copied into the plugins directory of eclipse. The name of
+# the directory within the plugins directory should be the same as
+# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before
+# the help appears.
+
+GENERATE_ECLIPSEHELP = NO
+
+# A unique identifier for the eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have
+# this name.
+
+ECLIPSE_DOC_ID = org.doxygen.Project
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX = NO
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values
+# (range [0,1..20]) that doxygen will group on one line in the generated HTML
+# documentation. Note that a value of 0 will completely suppress the enum
+# values from appearing in the overview section.
+
+ENUM_VALUES_PER_LINE = 4
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information.
+# If the tag value is set to YES, a side panel will be generated
+# containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser).
+# Windows users are probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW = NO
+
+# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories,
+# and Class Hierarchy pages using a tree view instead of an ordered list.
+
+USE_INLINE_TREES = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open
+# links to external symbols imported via tag files in a separate window.
+
+EXT_LINKS_IN_WINDOW = NO
+
+# Use this tag to change the font size of Latex formulas included
+# as images in the HTML documentation. The default is 10. Note that
+# when you change the font size after a successful doxygen run you need
+# to manually remove any form_*.png images from the HTML output directory
+# to force them to be regenerated.
+
+FORMULA_FONTSIZE = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are
+# not supported properly for IE 6.0, but are supported on all modern browsers.
+# Note that when changing this option you need to delete any form_*.png files
+# in the HTML output before the changes have effect.
+
+FORMULA_TRANSPARENT = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax
+# (see http://www.mathjax.org) which uses client side Javascript for the
+# rendering instead of using prerendered bitmaps. Use this if you do not
+# have LaTeX installed or if you want to formulas look prettier in the HTML
+# output. When enabled you also need to install MathJax separately and
+# configure the path to it using the MATHJAX_RELPATH option.
+
+USE_MATHJAX = NO
+
+# When MathJax is enabled you need to specify the location relative to the
+# HTML output directory using the MATHJAX_RELPATH option. The destination
+# directory should contain the MathJax.js script. For instance, if the mathjax
+# directory is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the
+# mathjax.org site, so you can quickly see the result without installing
+# MathJax, but it is strongly recommended to install a local copy of MathJax
+# before deployment.
+
+MATHJAX_RELPATH = http://www.mathjax.org/mathjax
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box
+# for the HTML output. The underlying search engine uses javascript
+# and DHTML and should work on any modern browser. Note that when using
+# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets
+# (GENERATE_DOCSET) there is already a search function so this one should
+# typically be disabled. For large projects the javascript based search engine
+# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
+
+SEARCHENGINE = YES
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a PHP enabled web server instead of at the web client
+# using Javascript. Doxygen will generate the search PHP script and index
+# file to put on the web server. The advantage of the server
+# based approach is that it scales better to large projects and allows
+# full text search. The disadvantages are that it is more difficult to setup
+# and does not have live searching capabilities.
+
+SERVER_BASED_SEARCH = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+# Note that when enabling USE_PDFLATEX this option is only used for
+# generating bitmaps for formulas in the HTML output, but not in the
+# Makefile that is written to the output directory.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = a4
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for
+# the generated latex document. The footer should contain everything after
+# the last chapter. If it is left blank doxygen will generate a
+# standard footer. Notice: only use this tag if you know what you are doing!
+
+LATEX_FOOTER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = YES
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+# If LATEX_SOURCE_CODE is set to YES then doxygen will include
+# source code with syntax highlighting in the LaTeX output.
+# Note that which sources are shown also depends on other settings
+# such as SOURCE_BROWSER.
+
+LATEX_SOURCE_CODE = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader.
+# This is useful
+# if you want to understand what is going on.
+# On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = YES
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF = YES
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# pointed to by INCLUDE_PATH will be searched when a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED = _WIN32 \
+ COMMON_SYSDEP= \
+ COMMON_PORTABLE= \
+ NON_COMMON= \
+ __CILKRTS_BEGIN_EXTERN_C= \
+ __CILKRTS_END_EXTERN_C= \
+ CILK_API(t)=t \
+ CILK_ABI(t)=t \
+ CILK_ABI_THROWS(t)=t \
+ CALLBACK= \
+ __CILKRTS_INLINE=inline \
+ __CILKRTS_ABI_VERSION=1 \
+ __cplusplus \
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition that
+# overrules the definition found in the source code.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all references to function-like macros
+# that are alone on a line, have an all uppercase name, and do not end with a
+# semicolon, because these will confuse the parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+#
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+#
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option also works with HAVE_DOT disabled, but it is recommended to
+# install and use dot, since it yields more powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = NO
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is
+# allowed to run in parallel. When set to 0 (the default) doxygen will
+# base this on the number of processors available in the system. You can set it
+# explicitly to a value larger than 0 to get control over the balance
+# between CPU load and processing speed.
+
+DOT_NUM_THREADS = 0
+
+# By default doxygen will write a font called Helvetica to the output
+# directory and reference it in all dot files that doxygen generates.
+# When you want a differently looking font you can specify the font name
+# using DOT_FONTNAME. You need to make sure dot is able to find the font,
+# which can be done by putting it in a standard location or by setting the
+# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory
+# containing the font.
+
+DOT_FONTNAME = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
+# The default size is 10pt.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the output directory to look for the
+# FreeSans.ttf font (which doxygen will put there itself). If you specify a
+# different font using DOT_FONTNAME you can set the path where dot
+# can find it using this tag.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then
+# doxygen will generate a call dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable call graphs
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
+# doxygen will generate a caller dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable caller
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will generate a graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are svg, png, jpg, or gif.
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the
+# \mscfile command).
+
+MSCFILE_DIRS =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen if the
+# number of direct children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not
+# seem to support this out of the box. Warning: Depending on the platform used,
+# enabling this option may lead to badly anti-aliased labels on the edges of
+# a graph (i.e. they become hard to read).
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
diff --git a/libcilkrts/runtime/except-gcc.cpp b/libcilkrts/runtime/except-gcc.cpp
new file mode 100644
index 00000000000..bd08d1826b3
--- /dev/null
+++ b/libcilkrts/runtime/except-gcc.cpp
@@ -0,0 +1,597 @@
+/* except-gcc.cpp -*-C++-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ **************************************************************************/
+
+#include "except-gcc.h"
+#include "except.h"
+#include "sysdep.h"
+#include "bug.h"
+#include "local_state.h"
+#include "full_frame.h"
+#include "scheduler.h"
+#include "frame_malloc.h"
+#include "pedigrees.h"
+
+#include <stdint.h>
+#include <typeinfo>
+
+#define DEBUG_EXCEPTIONS 0
+
+struct pending_exception_info
+{
+ void make(__cxa_eh_globals *, _Unwind_Exception *, bool);
+ void destruct();
+ bool empty() const;
+ void check() const;
+ /* Active exception at time of suspend. */
+ _Unwind_Exception *active;
+ /* If true the most recently caught exception is to be rethrown
+ on resume. This handling is technically incorrect but allows
+ running without compiler support; the proper standards-compliant
+ method is to save the exception in the previous field. */
+ bool rethrow;
+ struct __cxa_eh_globals runtime_state;
+};
+
+void pending_exception_info::check() const
+{
+ if (active)
+ CILK_ASSERT((int)runtime_state.uncaughtExceptions > 0);
+}
+
+void pending_exception_info::make(__cxa_eh_globals *state_in,
+ _Unwind_Exception *exc_in, bool rethrow_in)
+{
+ active = exc_in;
+ rethrow = rethrow_in;
+ runtime_state = *state_in;
+ /* Read and clear C++ runtime state. */
+ state_in->caughtExceptions = 0;
+ state_in->uncaughtExceptions = 0;
+#if CILK_LIB_DEBUG
+ check();
+#endif
+}
+
+bool
+pending_exception_info::empty() const
+{
+ return !active && !rethrow && !runtime_state.caughtExceptions &&
+ !runtime_state.uncaughtExceptions;
+}
+
+#if DEBUG_EXCEPTIONS
+#include <stdio.h>
+static void
+decode_exceptions(char *out, size_t len, struct pending_exception_info *info)
+{
+ if (info->empty())
+ snprintf(out, len, "[empty]");
+ else if (info->rethrow)
+ snprintf(out, len, "[rethrow %p]",
+ info->runtime_state.caughtExceptions);
+ else
+ snprintf(out, len, "[throw %p]", (void *)info->active);
+}
+#endif
+
+static void
+save_exception_info(__cilkrts_worker *w,
+ __cxa_eh_globals *state,
+ _Unwind_Exception *exc,
+ bool rethrow,
+ const char *why)
+{
+ struct pending_exception_info *info =
+ (struct pending_exception_info *)__cilkrts_frame_malloc(w, sizeof (struct pending_exception_info));
+ CILK_ASSERT(info);
+ info->make(state, exc, rethrow);
+
+#if DEBUG_EXCEPTIONS
+ {
+ char buf[40];
+ decode_exceptions(buf, sizeof buf, info);
+ fprintf(stderr, "make exception info W%u %p %s (%s)\n",
+ w->self, info, buf, why);
+ }
+#endif
+
+ CILK_ASSERT(w->l->pending_exception == 0);
+ w->l->pending_exception = info;
+}
+
+#if DEBUG_EXCEPTIONS
+#include <stdio.h> /* DEBUG */
+
+static void decode_flags(int flags, char out[9])
+{
+ out[0] = (flags & CILK_FRAME_STOLEN) ? 'S' : '_';
+ out[1] = (flags & CILK_FRAME_UNSYNCHED) ? 'U' : '_';
+ out[2] = (flags & CILK_FRAME_DETACHED) ? 'D' : '_';
+ out[3] = (flags & CILK_FRAME_EXCEPTING) ? 'X' : '_';
+ out[4] = '\0';
+}
+#endif
+
+/* __cilkrts_save_except is called from the runtime epilogue
+ when a function is returning with an exception pending.
+
+ If the function has a parent to which it could return normally,
+ return and have the caller call _Unwind_Resume, the same as if
+ an exception filter had not matched.
+
+ Otherwise save the exception in the worker.
+
+ If this is a return from a ordinary call that must go through
+ the runtime, the assembly epilogue must have saved the call-saved
+ register state in the parent frame. */
+
+extern "C"
+CILK_ABI_THROWS_VOID
+__cilkrts_return_exception(__cilkrts_stack_frame *sf)
+{
+ __cilkrts_worker *w = sf->worker;
+ _Unwind_Exception *exc = (_Unwind_Exception *)sf->except_data;
+
+ CILK_ASSERT(sf->flags & CILK_FRAME_DETACHED);
+ sf->flags &= ~CILK_FRAME_DETACHED;
+
+ /*
+ * If we are in replay mode, and a steal occurred during the recording
+ * phase, stall till a steal actually occurs.
+ */
+ replay_wait_for_steal_if_parent_was_stolen(w);
+
+ /* If this is to be an abnormal return, save the active exception. */
+ if (!__cilkrts_pop_tail(w)) {
+ /* Write a record to the replay log for an attempt to return to a
+ stolen parent. This must be done before the exception handler
+ invokes __cilkrts_leave_frame which will bump the pedigree so
+ the replay_wait_for_steal_if_parent_was_stolen() above will match on
+ replay */
+ replay_record_orphaned(w);
+
+ /* Now that the record/replay stuff is done, update the pedigree */
+ update_pedigree_on_leave_frame(w, sf);
+
+ /* Inline pop_frame; this may not be needed. */
+ w->current_stack_frame = sf->call_parent;
+ sf->call_parent = 0;
+ __cxa_eh_globals *state = __cxa_get_globals();
+
+#if DEBUG_EXCEPTIONS
+ fflush(stdout);
+ char decoded[9];
+ decode_flags(sf->flags, decoded);
+ fprintf(stderr, "__cilkrts_save_except W%u sf %p/%s exc %p [%u %p] suspend\n",
+ w->self, sf, decoded, exc,
+ state->uncaughtExceptions,
+ state->caughtExceptions);
+#endif
+
+ /* Like __cilkrts_save_exception_state except for setting the
+ rethrow flag. */
+ save_exception_info(w, state, exc, exc == NULL, "save_except");
+ {
+ full_frame *ff = w->l->frame_ff;
+ CILK_ASSERT(NULL == ff->pending_exception);
+ ff->pending_exception = w->l->pending_exception;
+ w->l->pending_exception = NULL;
+ }
+ __cilkrts_exception_from_spawn(w, sf); /* does not return */
+ }
+ /* This code path is taken when the parent is attached. It is on
+ the same stack and part of the same full frame. The caller is
+ cleaning up the Cilk frame during unwind and will reraise the
+ exception */
+
+ /* Now that the record/replay stuff is done, update the pedigree */
+ update_pedigree_on_leave_frame(w, sf);
+
+#if DEBUG_EXCEPTIONS /* DEBUG ONLY */
+ {
+ __cxa_eh_globals *state = __cxa_get_globals();
+
+ fflush(stdout);
+ char decoded[9];
+ decode_flags(sf->flags, decoded);
+ fprintf(stderr, "__cilkrts_save_except W%d %p/%s %p->%p [%u %p] escape\n",
+ w->self, sf, decoded, exc,
+ exc ? to_cxx(exc)->nextException : 0,
+ state->uncaughtExceptions,
+ state->caughtExceptions);
+
+ /* XXX This is triggering in the user thread which gets an exception
+ from somewhere but does not get the corresponding runtime exception
+ state.
+ XXX There might be two or more uncaught exceptions. Test could be
+ (uncaught != 0) == (exc != 0). First, design tests to see if that
+ case is otherwise handled correctly. And what if there's an uncaught
+ exception that does not belong to this function? I.e. this is a return
+ from spawn in a destructor. */
+ if (exc)
+ CILK_ASSERT((int)state->uncaughtExceptions > 0);
+ /*CILK_ASSERT(state->uncaughtExceptions == (exc != 0));*/
+ }
+#endif
+
+ /* The parent is attached so this exception can be propagated normally. */
+ return;
+}
+
+/* Save the exception state into the full frame, which is exiting
+ or suspending. */
+extern "C"
+void __cilkrts_save_exception_state(__cilkrts_worker *w, full_frame *ff)
+{
+ save_exception_info(w, __cxa_get_globals(), 0, false, "undo-detach");
+ CILK_ASSERT(NULL == ff->pending_exception);
+ ff->pending_exception = w->l->pending_exception;
+ w->l->pending_exception = NULL;
+}
+
+/* __cilkrts_c_sync_except is like __cilkrts_c_sync except that it
+ saves exception state. __cilkrts_c_sync never returns here and
+ always reinstalls the saved exception state.
+
+ This function must be used because a parent of this function may
+ be propagating an uncaught exception. The uncaught exception
+ count must be saved by the child and passed back to the parent. */
+
+extern "C"
+NORETURN __cilkrts_c_sync_except (__cilkrts_worker *w, __cilkrts_stack_frame *sf)
+{
+ __cxa_eh_globals *state = __cxa_get_globals();
+ _Unwind_Exception *exc = (_Unwind_Exception *)sf->except_data;
+
+ CILK_ASSERT((sf->flags & (CILK_FRAME_UNSYNCHED|CILK_FRAME_EXCEPTING)) ==
+ (CILK_FRAME_UNSYNCHED|CILK_FRAME_EXCEPTING));
+ sf->flags &= ~CILK_FRAME_EXCEPTING;
+
+#if DEBUG_EXCEPTIONS
+ fflush(stdout);
+ char decoded[9];
+ decode_flags(sf->flags, decoded);
+ if (exc)
+ fprintf(stderr, "__cilkrts_sync_except W%u %p/%s %p->%p [%u %p]\n",
+ w->self, sf, decoded, exc,
+ to_cxx(exc)->nextException,
+ state->uncaughtExceptions,
+ state->caughtExceptions);
+ else
+ fprintf(stderr, "__cilkrts_sync_except W%d %p/%s none [%u %p]\n",
+ w->self, sf, decoded,
+ state->uncaughtExceptions,
+ state->caughtExceptions);
+#endif
+
+ /* Here the identity of an rethrown exception is always known.
+ If exc is NULL this call is only to preserve parent state. */
+ save_exception_info(w, state, exc, false, "sync_except");
+#if 0
+ {
+ full_frame *ff = w->l->frame_ff;
+ CILK_ASSERT(NULL == ff->pending_exception);
+ ff->pending_exception = w->l->pending_exception;
+ w->l->pending_exception = NULL;
+ }
+#endif
+ CILK_ASSERT(!std::uncaught_exception());
+ __cilkrts_c_sync(w, sf);
+}
+
+void
+pending_exception_info::destruct()
+{
+ if (active) {
+#if DEBUG_EXCEPTIONS
+ fprintf(stderr, "destroy exception info %p %p\n", this, active);
+#endif
+ _Unwind_DeleteException(active);
+ active = 0;
+ } else {
+#if DEBUG_EXCEPTIONS
+ fprintf(stderr, "destroy exception info %p\n", this);
+#endif
+ }
+ while (runtime_state.caughtExceptions) {
+ __cxa_exception *exc = runtime_state.caughtExceptions;
+ runtime_state.caughtExceptions = exc->nextException;
+#if DEBUG_EXCEPTIONS
+ fprintf(stderr, "destroy caught exception %p\n", this);
+#endif
+ _Unwind_DeleteException(&exc->unwindHeader);
+ }
+}
+
+/*
+ * __cilkrts_merge_pending_exceptions
+ *
+ * Merge the right exception record into the left. The left is logically
+ * earlier.
+ *
+ * The active exception of E is
+ * E->active if it is non-NULL (in which case E->rethrow is false)
+ * unresolved if E->active is NULL and E->rethrow is true
+ * nil if E->active is NULL and E->rethrow is false
+ *
+ * The merged active exception is left active exception if it is not
+ * nil, otherwise the right.
+ *
+ * On entry the left state is synched and can not have an unresolved
+ * exception. The merge may result in an unresolved exception.
+ *
+ * Due to scoping rules at most one of the caught exception lists is
+ * non-NULL.
+ */
+
+struct pending_exception_info *
+__cilkrts_merge_pending_exceptions (
+ __cilkrts_worker *w,
+ struct pending_exception_info *left,
+ struct pending_exception_info *right)
+{
+ /* If we've only got one exception, return it */
+
+ if (NULL == left) {
+#if DEBUG_EXCEPTIONS
+ if (right) {
+ char buf[40];
+ decode_exceptions(buf, sizeof buf, right);
+ fprintf(stderr, "__cilkrts merge W%u nil %p -> %p %s\n",
+ w->self, right, right, buf);
+ }
+#endif
+ return right;
+ }
+
+ if (NULL == right) {
+#if DEBUG_EXCEPTIONS
+ if (left) {
+ char buf[40];
+ decode_exceptions(buf, sizeof buf, left);
+ fprintf(stderr, "__cilkrts merge W%u %p nil -> %p %s\n",
+ w->self, left, left, buf);
+ }
+#endif
+ return left;
+ }
+
+#if CILK_LIB_DEBUG
+ /*volatile struct pending_exception_info left_in = *left, right_in = *right;*/
+ left->check();
+ right->check();
+#endif
+
+#if DEBUG_EXCEPTIONS
+ {
+ char buf1[40], buf2[40];
+ decode_exceptions(buf1, sizeof buf1, left);
+ decode_exceptions(buf2, sizeof buf2, right);
+ fprintf(stderr, "__cilkrts merge W%u %p %s %p %s\n",
+ w->self, left, buf1, right, buf2);
+ }
+#endif
+
+ /* It should not be possible for both left and right to
+ have accumulated catch blocks.
+
+ The left exception record may always have a catch
+ chain it kept when its parent was stolen.
+
+ If they are siblings, the right sibling should not
+ have accumulated any net catches. (Catch is lexically
+ scoped.)
+
+ If the right frame is a parent, it should not have entered
+ a catch block without syncing first. If it spawned in a
+ catch block, the child got its catch. */
+ __cxa_exception *caught = left->runtime_state.caughtExceptions;
+ if (caught)
+ CILK_ASSERT(!right->runtime_state.caughtExceptions);
+ else {
+ CILK_ASSERT(!left->rethrow);
+ left->rethrow = right->rethrow;
+ left->runtime_state.caughtExceptions = caught = right->runtime_state.caughtExceptions;
+ right->runtime_state.caughtExceptions = NULL;
+ }
+
+ /* Merge the uncaught exception and count of uncaught exceptions. */
+ const unsigned int right_uncaught = right->runtime_state.uncaughtExceptions;
+ if (!left->active){
+ left->active = right->active; /* could be NULL */
+ right->active = 0;
+ left->runtime_state.uncaughtExceptions += right_uncaught;
+ if (left->active)
+ /* assert is C++ exception */
+ /*CILK_ASSERT(__cxxabiv1::__is_gxx_exception_class(left->active->exception_class))*/;
+ } else {
+ /* Subtract 1 if the right exception is being destructed. */
+ left->runtime_state.uncaughtExceptions += right_uncaught - (right->active != 0);
+ }
+
+ right->destruct();
+ __cilkrts_frame_free(w, right, sizeof *right);
+
+ /* If there is no state left, return NULL. */
+ if (left->empty()) {
+ left->destruct();
+ __cilkrts_frame_free(w, left, sizeof *left);
+ left = NULL;
+ }
+
+#if CILK_LIB_DEBUG
+ if (left)
+ left->check();
+#endif
+
+ return left;
+}
+
+#if 0
+/* __cilkrts_c_resume_except is called from the assembly language
+ restart code when a resumed frame has a pending exception.
+
+ The handler count negation on rethrow was done when the throw was
+ resolved.
+
+ The assembly language runtime must make the throw unwind to
+ the sync, spawn, or other location where the exception should
+ be injected. (This should not happen after a spawn but nothing
+ here depends on there being no exception on steal.)
+
+ This function is unused in the Intel stack based system. */
+extern "C"
+void __cilkrts_c_resume_except (_Unwind_Exception *exc)
+{
+#if DEBUG_EXCEPTIONS
+ fprintf(stderr, "resume exception %p\n", exc);
+#endif
+ _Unwind_Reason_Code why = _Unwind_RaiseException(exc);
+ __cilkrts_bug ("Cilk runtime error: failed to reinstate suspended exception %p (%d)\n", exc, why);
+}
+#endif
+
+/* Restore the caught exception chain. This assumes no C++ exception
+ code will run before the frame is resumed. If there is no exception
+ to be resumed free the object. */
+
+extern "C"
+void __cilkrts_setup_for_execution_sysdep(__cilkrts_worker *w, full_frame *ff)
+{
+ // ASSERT: We own w->lock and ff->lock || P == 1
+
+ __cxa_eh_globals *state = __cxa_get_globals ();
+ struct pending_exception_info *info = w->l->pending_exception;
+
+ if (info == NULL)
+ return;
+
+ w->l->pending_exception = 0;
+
+#if DEBUG_EXCEPTIONS
+ _Unwind_Exception *exc = info->active;
+ if (exc) {
+ fflush(stdout);
+ fprintf(stderr, "__cilkrts_resume_except W%u %p->%p [%u %p]\n",
+ w->self, exc,
+ to_cxx(exc)->nextException,
+ info->runtime_state.uncaughtExceptions,
+ info->runtime_state.caughtExceptions);
+ /*CILK_ASSERT(info->runtime_state.uncaughtExceptions > 0);*/
+ }
+#endif
+
+ if (state->uncaughtExceptions || state->caughtExceptions)
+ __cilkrts_bug("W%u: resuming with non-empty prior exception state %u %p\n", state->uncaughtExceptions, state->caughtExceptions);
+
+ *state = info->runtime_state;
+ info->runtime_state.caughtExceptions = 0;
+ info->runtime_state.uncaughtExceptions = 0;
+
+ if (info->rethrow) {
+ info->rethrow = false;
+ /* Resuming function will rethrow. Runtime calls
+ std::terminate if there is no caught exception. */
+ ff->call_stack->flags |= CILK_FRAME_EXCEPTING;
+ }
+ if (info->active) {
+ ff->call_stack->flags |= CILK_FRAME_EXCEPTING;
+ ff->call_stack->except_data = info->active;
+ info->active = 0;
+ }
+
+ if (info->empty()) {
+ info->destruct();
+ __cilkrts_frame_free(w, info, sizeof *info);
+ w->l->pending_exception = NULL;
+ }
+
+#if CILK_LIB_DEBUG
+ if (ff->call_stack->except_data)
+ CILK_ASSERT(std::uncaught_exception());
+#endif
+}
+
+#if 0
+extern "C"
+struct pending_exception_info *__cilkrts_get_exception(__cilkrts_worker *w,
+ __cilkrts_stack_frame *sf)
+{
+ struct pending_exception_info *info = w->l->pending_exception;
+
+ if (info == NULL) {
+ sf->flags &= ~CILK_FRAME_EXCEPTING;
+ return 0;
+ }
+
+ w->l->pending_exception = NULL;
+
+ /* This exception goes into the frame. */
+
+ _Unwind_Exception *exc = info->active;
+ info->active = NULL;
+ info->destruct();
+ __cilkrts_frame_free(w, info, sizeof *info);
+ info = 0;
+ sf->flags |= CILK_FRAME_EXCEPTING;
+ sf->exception = exc;
+ return 0;
+}
+#endif
+
+extern "C"
+void __attribute__((nonnull)) __cilkrts_gcc_rethrow(__cilkrts_stack_frame *sf)
+{
+#ifdef __CYGWIN__
+ // Cygwin doesn't support exceptions, so _Unwind_Resume isn't available
+ // Which means we can't support exceptions either
+ __cilkrts_bug("The Cygwin implementation of the Intel Cilk Plus runtime doesn't support exceptions\n");
+#else
+ if (sf->except_data) {
+#if CILK_LIB_DEBUG
+ CILK_ASSERT(std::uncaught_exception());
+#endif
+ _Unwind_Resume ((_Unwind_Exception *)sf->except_data);
+ } else {
+ throw;
+ }
+#endif // __CYGWIN__
+}
+
+/* End except-gcc.cpp */
+
diff --git a/libcilkrts/runtime/except-gcc.h b/libcilkrts/runtime/except-gcc.h
new file mode 100644
index 00000000000..aa76adbc233
--- /dev/null
+++ b/libcilkrts/runtime/except-gcc.h
@@ -0,0 +1,146 @@
+/* except-gcc.h -*-C++-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ **************************************************************************/
+
+/**
+ * @file except-gcc.h
+ *
+ * @brief ABI for gcc exception handling.
+ *
+ * @par Origin
+ * The code below is generally copied from the Intel Itanium ABI (Intel
+ * download 245370).
+ */
+
+#ifndef INCLUDED_EXCEPT_GCC_DOT_H
+#define INCLUDED_EXCEPT_GCC_DOT_H
+
+#ifndef __cplusplus
+# error except-gcc.h should be used in C++ code only.
+#endif
+
+#include <cilk/common.h>
+#include <exception>
+#include <typeinfo>
+
+struct __cxa_exception;
+
+__CILKRTS_BEGIN_EXTERN_C
+
+/** Unwind reason code (Itanium ABI 6.1.2.1) */
+typedef enum _Unwind_Reason_Code {
+ _URC_NO_REASON = 0,
+ _URC_FOREIGN_EXCEPTION_CAUGHT = 1,
+ _URC_FATAL_PHASE2_ERROR = 2,
+ _URC_FATAL_PHASE1_ERROR = 3,
+ _URC_NORMAL_STOP = 4,
+ _URC_END_OF_STACK = 5,
+ _URC_HANDLER_FOUND = 6,
+ _URC_INSTALL_CONTEXT = 7,
+ _URC_CONTINUE_UNWIND = 8
+} _Unwind_Reason_Code;
+
+typedef struct _Unwind_Exception _Unwind_Exception;
+
+/** Exception cleanup function pointer (Itanium ABI 6.1.2.2) */
+typedef void (*_Unwind_Exception_Cleanup_Fn)(_Unwind_Reason_Code reason,
+ _Unwind_Exception *exc);
+
+/**
+ * @brief Exception undwinding information
+ *
+ * This is copied from the Intel Itanium ABI except that the
+ * private fields are declared unsigned long for binary
+ * compatibility with gcc/g++ on 32 bit machines.
+ */
+struct _Unwind_Exception
+{
+ uint64_t exception_class;
+ _Unwind_Exception_Cleanup_Fn exception_cleanup;
+ unsigned long private_1;
+ unsigned long private_2;
+};
+
+/** Throw or rethrow an exception */
+_Unwind_Reason_Code
+_Unwind_RaiseException(_Unwind_Exception *exception_object);
+
+/** Resume an exception other than by rethrowing it. */
+void _Unwind_Resume(_Unwind_Exception *exception_object);
+
+/** Delete an exception object */
+void _Unwind_DeleteException(_Unwind_Exception *exception_object);
+
+/**
+ * C++ exception ABI.
+ * The following declarations are from
+ *
+ * http://www.codesourcery.com/public/cxx-abi/abi-eh.html#cxx-abi
+ */
+
+struct __cxa_exception {
+ std::type_info * exceptionType;
+ void (*exceptionDestructor)(void *);
+ std::unexpected_handler unexpectedHandler;
+ std::terminate_handler terminateHandler;
+ __cxa_exception * nextException;
+
+ int handlerCount;
+ int handlerSwitchValue;
+ const char * actionRecord;
+ const char * languageSpecificData;
+ void * catchTemp;
+ void * adjustedPtr;
+
+ _Unwind_Exception unwindHeader;
+};
+
+static inline __cxa_exception *to_cxx(_Unwind_Exception *e)
+{
+ return ((__cxa_exception *)(e+1)) - 1;
+}
+
+typedef struct __cxa_eh_globals {
+ __cxa_exception *caughtExceptions;
+ unsigned int uncaughtExceptions;
+} __cxa_eh_globals;
+
+__cxa_eh_globals*__cxa_get_globals(void) throw();
+
+__CILKRTS_END_EXTERN_C
+
+#endif // ! defined(INCLUDED_EXCEPT_GCC_DOT_H)
diff --git a/libcilkrts/runtime/except.h b/libcilkrts/runtime/except.h
new file mode 100644
index 00000000000..58e2238c581
--- /dev/null
+++ b/libcilkrts/runtime/except.h
@@ -0,0 +1,123 @@
+/* except.h -*-C++-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ **************************************************************************/
+
+/**
+ * @file except.h
+ *
+ * @brief Common definitions for the various implementations of exception
+ * handling.
+ */
+
+#ifndef INCLUDED_EXCEPT_DOT_H
+#define INCLUDED_EXCEPT_DOT_H
+
+#include <cilk/common.h>
+#include <internal/abi.h>
+#include "full_frame.h"
+
+__CILKRTS_BEGIN_EXTERN_C
+
+/**
+ * OS-dependent information about an exception that's being moved between
+ * strands.
+ */
+typedef struct pending_exception_info pending_exception_info;
+
+/**
+ * Merge the right exception record into the left. The left is logically
+ * earlier.
+ *
+ * On entry the left state is synched and can not have an unresolved
+ * exception. The merge may result in an unresolved exception.
+ *
+ * If there is both a right and left exception, the right exception will
+ * be disposed of in preference to the left exception, destructing the
+ * exception object.
+ *
+ * @param w The worker that is preparing to resume execution.
+ * @param left_exception The exception that would have happened earlier
+ * if the code executed serially. Can be NULL if the left strand has not
+ * raised an exception.
+ * @param right_exception The exception that would have happened later
+ * if the code executed serially. Can be NULL if the right strand has not
+ * raised an exception.
+ *
+ * @return NULL if there both the right and left exception are NULL. This
+ * indicates that there are no pending exceptions.
+ * @return The pending exception that is to be raised to continue searching
+ * for a catch block to handle the exception.
+ */
+COMMON_SYSDEP
+struct pending_exception_info *__cilkrts_merge_pending_exceptions(
+ __cilkrts_worker *w,
+ pending_exception_info *left_exception,
+ pending_exception_info *right_exception);
+
+/**
+ * Move the exception information from the worker to the full_frame.
+ *
+ * @param w The worker which is suspending work on a full_frame.
+ * @param ff The full_frame which is being suspended.
+ */
+COMMON_SYSDEP
+void __cilkrts_save_exception_state(__cilkrts_worker *w,
+ full_frame *ff);
+
+/**
+ * Function to delete pending exception. This will delete the
+ * exception object and then free the stack/fiber.
+ *
+ * @param w The worker we're running on.
+ * @param pei The pending exception to be delete
+ * @param delete_object Unused. Should always be 1.
+ */
+void delete_exception_obj (__cilkrts_worker *w,
+ struct pending_exception_info *pei,
+ int delete_object);
+
+#ifndef _WIN32
+/* gcc-style exception handling */
+NON_COMMON NORETURN __cilkrts_c_sync_except(__cilkrts_worker *w,
+ __cilkrts_stack_frame *sf);
+NON_COMMON void __attribute__((nonnull))
+__cilkrts_gcc_rethrow(__cilkrts_stack_frame *sf);
+#endif
+
+__CILKRTS_END_EXTERN_C
+
+#endif // ! defined(INCLUDED_EXCEPT_DOT_H)
diff --git a/libcilkrts/runtime/frame_malloc.c b/libcilkrts/runtime/frame_malloc.c
new file mode 100644
index 00000000000..0b38bd209a9
--- /dev/null
+++ b/libcilkrts/runtime/frame_malloc.c
@@ -0,0 +1,462 @@
+/* frame_malloc.c -*-C-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ **************************************************************************/
+
+#include "frame_malloc.h"
+#include "bug.h"
+#include "local_state.h"
+#include "cilk_malloc.h"
+
+#ifndef __VXWORKS__
+#include <memory.h>
+#endif
+
+/* #define USE_MMAP 1 */
+#if USE_MMAP
+#define __USE_MISC 1
+#include <sys/mman.h>
+#include <errno.h>
+#endif
+
+// Define to fill the stack frame header with the fill character when pushing
+// it on a free list. Note that this should be #ifdef'd out when checked in!
+
+#ifdef _DEBUG
+#define HEADER_FILL_CHAR 0xbf
+#endif
+
+// HEADER_FILL_CHAR should not be defined when checked in, so put out a warning
+// message if this is a release build
+
+#if defined(NDEBUG) && defined (HEADER_FILL_CHAR)
+#pragma message ("Warning: HEADER_FILL_CHAR defined for a release build")
+#endif
+
+static void allocate_batch(__cilkrts_worker *w, int bucket, size_t size);
+
+#ifndef _WIN32
+
+const unsigned short __cilkrts_bucket_sizes[FRAME_MALLOC_NBUCKETS] =
+{
+ 64, 128, 256, 512, 1024, 2048
+};
+
+#define FRAME_MALLOC_BUCKET_TO_SIZE(bucket) __cilkrts_bucket_sizes[bucket]
+
+/* threshold above which we use slow malloc */
+#define FRAME_MALLOC_MAX_SIZE 2048
+
+#else // _WIN32
+
+/* Note that this must match the implementation of framesz_to_bucket in
+ * asmilator/layout.ml! */
+#define FRAME_MALLOC_BUCKET_TO_SIZE(bucket) ((size_t)(64 << (bucket)))
+
+/* threshold above which we use slow malloc */
+#define FRAME_MALLOC_MAX_SIZE \
+ FRAME_MALLOC_BUCKET_TO_SIZE(FRAME_MALLOC_NBUCKETS - 1)
+
+#endif // _WIN32
+
+/* utility procedures */
+static void push(struct free_list **b, struct free_list *p)
+{
+#ifdef HEADER_FILL_CHAR
+ memset (p, HEADER_FILL_CHAR, FRAME_MALLOC_BUCKET_TO_SIZE(0));
+#endif
+ /* cons! onto free list */
+ p->cdr = *b;
+ *b = p;
+}
+
+static struct free_list *pop(struct free_list **b)
+{
+ struct free_list *p = *b;
+ if (p)
+ *b = p->cdr;
+ return p;
+}
+
+/*************************************************************
+ global allocator:
+*************************************************************/
+/* request slightly less than 2^K from the OS, which after malloc
+ overhead and alignment should end up filling each VM page almost
+ completely. 128 is a guess of the total malloc overhead and cache
+ line alignment */
+#define FRAME_MALLOC_CHUNK (32 * 1024 - 128)
+
+/** Implements linked list of frames */
+struct pool_cons {
+ char *p; /**< This element of the list */
+ struct pool_cons *cdr; /**< Remainder of the list */
+};
+
+static void extend_global_pool(global_state_t *g)
+{
+ /* FIXME: memalign to a cache line? */
+ struct pool_cons *c = (struct pool_cons *)__cilkrts_malloc(sizeof(*c));
+ g->frame_malloc.pool_begin =
+ (char *)__cilkrts_malloc((size_t)FRAME_MALLOC_CHUNK);
+ g->frame_malloc.pool_end =
+ g->frame_malloc.pool_begin + FRAME_MALLOC_CHUNK;
+ g->frame_malloc.allocated_from_os += FRAME_MALLOC_CHUNK;
+ c->p = g->frame_malloc.pool_begin;
+ c->cdr = g->frame_malloc.pool_list;
+ g->frame_malloc.pool_list = c;
+}
+
+/* the size is already canonicalized at this point */
+static struct free_list *global_alloc(global_state_t *g, int bucket)
+{
+ struct free_list *mem;
+ size_t size;
+
+ CILK_ASSERT(bucket < FRAME_MALLOC_NBUCKETS);
+ size = FRAME_MALLOC_BUCKET_TO_SIZE(bucket);
+ g->frame_malloc.allocated_from_global_pool += size;
+
+ if (!(mem = pop(&g->frame_malloc.global_free_list[bucket]))) {
+
+ CILK_ASSERT(g->frame_malloc.pool_begin <= g->frame_malloc.pool_end);
+ if (g->frame_malloc.pool_begin + size > g->frame_malloc.pool_end) {
+ /* We waste the fragment of pool. */
+ g->frame_malloc.wasted +=
+ g->frame_malloc.pool_end - g->frame_malloc.pool_begin;
+ extend_global_pool(g);
+ }
+ mem = (struct free_list *)g->frame_malloc.pool_begin;
+ g->frame_malloc.pool_begin += size;
+ }
+
+ return mem;
+}
+
+static void global_free(global_state_t *g, void *mem, int bucket)
+{
+ size_t size;
+
+ CILK_ASSERT(bucket < FRAME_MALLOC_NBUCKETS);
+ size = FRAME_MALLOC_BUCKET_TO_SIZE(bucket);
+ g->frame_malloc.allocated_from_global_pool -= size;
+
+ push(&g->frame_malloc.global_free_list[bucket], mem);
+}
+
+void __cilkrts_frame_malloc_global_init(global_state_t *g)
+{
+ int i;
+
+ __cilkrts_mutex_init(&g->frame_malloc.lock);
+ g->frame_malloc.check_for_leaks = 1;
+ g->frame_malloc.pool_list = 0;
+ g->frame_malloc.pool_begin = 0;
+ g->frame_malloc.pool_end = 0;
+ g->frame_malloc.batch_size = 8000;
+ g->frame_malloc.potential_limit = 4 * g->frame_malloc.batch_size;
+ g->frame_malloc.allocated_from_os = 0;
+ g->frame_malloc.allocated_from_global_pool = 0;
+ g->frame_malloc.wasted = 0;
+ for (i = 0; i < FRAME_MALLOC_NBUCKETS; ++i)
+ g->frame_malloc.global_free_list[i] = 0;
+}
+
+// Counts how many bytes are in the global free list.
+static size_t count_memory_in_global_list(global_state_t *g)
+{
+
+ // Count the memory remaining in the global free list.
+ size_t size_remaining_in_global_list = 0;
+ int i;
+ for (i = 0; i < FRAME_MALLOC_NBUCKETS; ++i) {
+ struct free_list *p;
+ size_t size_in_bucket = 0;
+ p = g->frame_malloc.global_free_list[i];
+
+ while (p) {
+ size_in_bucket += FRAME_MALLOC_BUCKET_TO_SIZE(i);
+ p = p->cdr;
+ }
+ size_remaining_in_global_list += size_in_bucket;
+ }
+ return size_remaining_in_global_list;
+}
+
+
+void __cilkrts_frame_malloc_global_cleanup(global_state_t *g)
+{
+ struct pool_cons *c;
+
+ if (g->frame_malloc.check_for_leaks) {
+ size_t memory_in_global_list = count_memory_in_global_list(g);
+ // TBD: This check is weak. Short of memory corruption,
+ // I don't see how we have more memory in the free list
+ // than allocated from the os.
+ // Ideally, we should count the memory in the global free list
+ // and check that we have it all. But I believe the runtime
+ // itself also uses some memory, which is not being tracked.
+ if (memory_in_global_list > g->frame_malloc.allocated_from_os) {
+ __cilkrts_bug("\nError. The Cilk runtime data structures may have been corrupted.\n");
+ }
+ }
+
+ while ((c = g->frame_malloc.pool_list)) {
+ g->frame_malloc.pool_list = c->cdr;
+ __cilkrts_free(c->p);
+ __cilkrts_free(c);
+ }
+
+ __cilkrts_mutex_destroy(0, &g->frame_malloc.lock);
+
+ // Check that all the memory moved from the global pool into
+ // workers has been returned to the global pool.
+ if (g->frame_malloc.check_for_leaks
+ && (g->frame_malloc.allocated_from_global_pool != 0))
+ {
+ __cilkrts_bug("\n"
+ "---------------------------" "\n"
+ " MEMORY LEAK DETECTED!!! " "\n"
+ "---------------------------" "\n"
+ "\n"
+ );
+ }
+}
+
+/*************************************************************
+ per-worker allocator
+*************************************************************/
+/* allocate a batch of frames of size SIZE from the global pool and
+ store them in the worker's free list */
+static void allocate_batch(__cilkrts_worker *w, int bucket, size_t size)
+{
+ global_state_t *g = w->g;
+
+ __cilkrts_mutex_lock(w, &g->frame_malloc.lock); {
+#if USE_MMAP
+ char *p = mmap(0, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+ if (p == MAP_FAILED)
+ __cilkrts_bug("mmap failed %d", errno);
+ assert(size < 4096);
+ assert(p != MAP_FAILED);
+ mprotect(p, 4096, PROT_NONE);
+ mprotect(p + 8192, 4096, PROT_NONE);
+ w->l->bucket_potential[bucket] += size;
+ push(&w->l->free_list[bucket], (struct free_list *)(p + 8192 - size));
+#else
+ size_t bytes_allocated = 0;
+ do {
+ w->l->bucket_potential[bucket] += size;
+ bytes_allocated += size;
+ push(&w->l->free_list[bucket], global_alloc(g, bucket));
+ } while (bytes_allocated < g->frame_malloc.batch_size);
+#endif
+ } __cilkrts_mutex_unlock(w, &g->frame_malloc.lock);
+
+}
+
+static void gc_bucket(__cilkrts_worker *w, int bucket, size_t size)
+{
+ struct free_list *p, *q;
+ global_state_t *g = w->g;
+ size_t pot = w->l->bucket_potential[bucket];
+ size_t newpot;
+
+ /* Keep up to POT/2 elements in the free list. The cost of
+ counting up to POT/2 is amortized against POT. */
+ newpot = 0;
+ for (newpot = 0, p = w->l->free_list[bucket]; p && 2 * newpot < pot;
+ p = p->cdr, newpot += size)
+ ;
+ w->l->bucket_potential[bucket] = newpot;
+
+ if (p) {
+ /* free the rest of the list. The cost of grabbing the lock
+ is amortized against POT/2; the cost of traversing the rest
+ of the list is amortized against the free operation that
+ puts the element on the list. */
+ __cilkrts_mutex_lock(w, &g->frame_malloc.lock); {
+ while ((q = pop(&p->cdr)))
+#if USE_MMAP
+ munmap((char *)q + size - 8192, 12288);
+#else
+ global_free(g, q, bucket);
+#endif
+ } __cilkrts_mutex_unlock(w, &g->frame_malloc.lock);
+ }
+}
+
+// Free all the memory in this bucket for the specified worker,
+// returning it to the global pool's free list.
+static void move_bucket_to_global_free_list(__cilkrts_worker *w,
+ int bucket)
+{
+ struct free_list *p, *q;
+ global_state_t *g = w->g;
+ p = w->l->free_list[bucket];
+
+ if (p) {
+ __cilkrts_mutex_lock(w, &g->frame_malloc.lock); {
+ while ((q = pop(&p))) {
+#if USE_MMAP
+ size_t size = FRAME_MALLOC_BUCKET_TO_SIZE(bucket);
+ munmap((char *)q + size - 8192, 12288);
+#else
+ global_free(g, q, bucket);
+#endif
+ }
+ } __cilkrts_mutex_unlock(w, &g->frame_malloc.lock);
+ }
+
+ // I'm not sure this does anything useful now, since
+ // the worker is about to be destroyed. But why not?
+ w->l->bucket_potential[bucket] = 0;
+}
+
+static int bucket_of_size(size_t size)
+{
+ int i;
+
+ for (i = 0; i < FRAME_MALLOC_NBUCKETS; ++i)
+ if (size <= FRAME_MALLOC_BUCKET_TO_SIZE(i))
+ return i;
+
+ CILK_ASSERT(0 /* can't happen */);
+ return -1;
+}
+
+size_t __cilkrts_frame_malloc_roundup(size_t size)
+{
+ if (size > FRAME_MALLOC_MAX_SIZE) {
+ /* nothing, leave it alone */
+ } else {
+ int bucket = bucket_of_size(size);
+ size = FRAME_MALLOC_BUCKET_TO_SIZE(bucket);
+ }
+ return size;
+}
+
+size_t __cilkrts_size_of_bucket(int bucket)
+{
+ CILK_ASSERT(bucket >= 0 && bucket < FRAME_MALLOC_NBUCKETS);
+ return FRAME_MALLOC_BUCKET_TO_SIZE(bucket);
+}
+
+void *__cilkrts_frame_malloc(__cilkrts_worker *w, size_t size)
+{
+ int bucket;
+ void *mem;
+
+ /* if too large, or if no worker, fall back to __cilkrts_malloc() */
+ if (!w || size > FRAME_MALLOC_MAX_SIZE) {
+ NOTE_INTERVAL(w, INTERVAL_FRAME_ALLOC_LARGE);
+ return __cilkrts_malloc(size);
+ }
+
+ START_INTERVAL(w, INTERVAL_FRAME_ALLOC); {
+ bucket = bucket_of_size(size);
+ size = FRAME_MALLOC_BUCKET_TO_SIZE(bucket);
+
+ while (!(mem = pop(&w->l->free_list[bucket]))) {
+ /* get a batch of frames from the global pool */
+ START_INTERVAL(w, INTERVAL_FRAME_ALLOC_GLOBAL) {
+ allocate_batch(w, bucket, size);
+ } STOP_INTERVAL(w, INTERVAL_FRAME_ALLOC_GLOBAL);
+ }
+ } STOP_INTERVAL(w, INTERVAL_FRAME_ALLOC);
+
+ return mem;
+}
+
+void __cilkrts_frame_free(__cilkrts_worker *w, void *p0, size_t size)
+{
+ int bucket;
+ struct free_list *p = (struct free_list *)p0;
+
+ /* if too large, or if no worker, fall back to __cilkrts_free() */
+ if (!w || size > FRAME_MALLOC_MAX_SIZE) {
+ NOTE_INTERVAL(w, INTERVAL_FRAME_FREE_LARGE);
+ __cilkrts_free(p);
+ return;
+ }
+
+#if CILK_LIB_DEBUG
+ *(volatile long *)w;
+#endif
+
+ START_INTERVAL(w, INTERVAL_FRAME_FREE); {
+ bucket = bucket_of_size(size);
+ size = FRAME_MALLOC_BUCKET_TO_SIZE(bucket);
+ w->l->bucket_potential[bucket] += size;
+ push(&w->l->free_list[bucket], p);
+ if (w->l->bucket_potential[bucket] >
+ w->g->frame_malloc.potential_limit) {
+ START_INTERVAL(w, INTERVAL_FRAME_FREE_GLOBAL) {
+ gc_bucket(w, bucket, size);
+ } STOP_INTERVAL(w, INTERVAL_FRAME_FREE_GLOBAL);
+ }
+ } STOP_INTERVAL(w, INTERVAL_FRAME_FREE);
+}
+
+void __cilkrts_frame_malloc_per_worker_init(__cilkrts_worker *w)
+{
+ int i;
+ local_state *l = w->l;
+
+ for (i = 0; i < FRAME_MALLOC_NBUCKETS; ++i) {
+ l->free_list[i] = 0;
+ l->bucket_potential[i] = 0;
+ }
+}
+
+void __cilkrts_frame_malloc_per_worker_cleanup(__cilkrts_worker *w)
+{
+ int i;
+ // Move memory to the global pool. This operation
+ // ensures the memory does not become unreachable / leak
+ // when the worker is destroyed.
+ for (i = 0; i < FRAME_MALLOC_NBUCKETS; ++i) {
+ move_bucket_to_global_free_list(w, i);
+ }
+}
+
+/*
+ Local Variables: **
+ c-file-style:"bsd" **
+ c-basic-offset:4 **
+ indent-tabs-mode:nil **
+ End: **
+*/
diff --git a/libcilkrts/runtime/frame_malloc.h b/libcilkrts/runtime/frame_malloc.h
new file mode 100644
index 00000000000..d412fb620fe
--- /dev/null
+++ b/libcilkrts/runtime/frame_malloc.h
@@ -0,0 +1,205 @@
+/* frame_malloc.h -*-C++-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ **************************************************************************/
+
+/**
+ * @file frame_malloc.h
+ *
+ * @brief The frame allocation routines manage memory in a per-worker pool.
+ *
+ * The name "frame malloc" refers to an earlier implementation of Cilk which
+ * allocated frames from the heap using this allocator.
+ */
+
+#ifndef INCLUDED_FRAME_MALLOC_DOT_H
+#define INCLUDED_FRAME_MALLOC_DOT_H
+
+#include "worker_mutex.h"
+#include "rts-common.h"
+#include <internal/abi.h> // __cilkrts_worker
+
+#ifdef __cplusplus
+# include <cstddef>
+#else
+# include <stddef.h>
+#endif
+
+__CILKRTS_BEGIN_EXTERN_C
+
+/**
+ * Number of buckets. Gives us buckets to hold 64, 128, 256, 512, 1024
+ * and 2048 bytes
+ */
+#define FRAME_MALLOC_NBUCKETS 6
+
+/** Layout of frames when unallocated */
+struct free_list {
+ /** Pointer to next free frame */
+ struct free_list *cdr;
+};
+
+/** per-worker memory cache */
+struct __cilkrts_frame_cache
+{
+ /** Mutex to serialize access */
+ struct mutex lock;
+
+ /** Linked list of frames */
+ struct pool_cons *pool_list;
+
+ /** Low bound of memory in pool */
+ char *pool_begin;
+
+ /** High bound of memory in pool */
+ char *pool_end;
+
+ /** Global free-list buckets */
+ struct free_list *global_free_list[FRAME_MALLOC_NBUCKETS];
+
+ /**
+ * How many bytes to obtain at once from the global pool
+ * (approximately)
+ */
+ size_t batch_size;
+
+ /** Garbage-collect a bucket when its potential exceeds the limit */
+ size_t potential_limit;
+
+ /** If TRUE, check for memory leaks at the end of execution */
+ int check_for_leaks;
+
+ /** Bytes of memory allocated from the OS by the global cache */
+ size_t allocated_from_os;
+
+ /** Tracks memory allocated by a chunk that isn't a full bucket size */
+ size_t wasted;
+
+ /** Bytes of memory allocated from the global cache */
+ size_t allocated_from_global_pool;
+};
+
+/**
+ * Allocate memory from the per-worker pool. If the size is too large, or
+ * if we're given a NULL worker, the memory is allocated using
+ * __cilkrts_malloc().
+ *
+ * @param w The worker to allocate the memory from.
+ * @param size The number of bytes to allocate.
+ *
+ * @return pointer to allocated memory block.
+ */
+COMMON_PORTABLE
+void *__cilkrts_frame_malloc(__cilkrts_worker *w,
+ size_t size) cilk_nothrow;
+
+/**
+ * Return memory to the per-worker pool. If the size is too large, or
+ * if we're given a NULL worker, the memory is freed using
+ * __cilkrts_free().
+ *
+ * @param w The worker to allocate the memory from.
+ * @param p The memory block to be released.
+ * @param size The size of the block, in bytes.
+ */
+COMMON_PORTABLE
+void __cilkrts_frame_free(__cilkrts_worker *w,
+ void* p,
+ size_t size) cilk_nothrow;
+
+/**
+ * Destroy the global cache stored in the global state, freeing all memory
+ * to the global heap. Checks whether any memory has been allocated but
+ * not freed.
+ *
+ * @param g The global state.
+ */
+COMMON_PORTABLE
+void __cilkrts_frame_malloc_global_cleanup(global_state_t *g);
+
+/**
+ * Initialize a worker's memory cache. Initially it is empty.
+ *
+ * @param w The worker who's memory cache is to be initialized.
+ */
+COMMON_PORTABLE
+void __cilkrts_frame_malloc_per_worker_init(__cilkrts_worker *w);
+
+/**
+ * If check_for_leaks is set in the global state's memory cache, free any
+ * memory in the worker's memory cache.
+ *
+ * If check_for_leask is not set, nothing happens.
+ *
+ * @param w The worker who's memory cache is to be cleaned up.
+ */
+COMMON_PORTABLE
+void __cilkrts_frame_malloc_per_worker_cleanup(__cilkrts_worker *w);
+
+/**
+ * Round a number of bytes to the size of the smallest bucket that will
+ * hold it. If the size is bigger than the largest bucket, the value is
+ * unchanged.
+ *
+ * @param size Number of bytes to be rounded up to the nearest bucket size.
+ *
+ * @return The size of the smallest bucket that will hold the specified bytes.
+ */
+COMMON_PORTABLE
+size_t __cilkrts_frame_malloc_roundup(size_t size) cilk_nothrow;
+
+/**
+ * Return the number of bytes that can fit into a bucket.
+ *
+ * Preconditions:
+ * - The index must be in the range 0 - FRAME_MALLOC_NBUCKETS
+ *
+ * @param bucket Index of the bucket to be sized.
+ */
+COMMON_PORTABLE
+size_t __cilkrts_size_of_bucket(int bucket) cilk_nothrow;
+
+/**
+ * Initialize the global memory cache.
+ *
+ * @param g The global state.
+ */
+COMMON_PORTABLE
+void __cilkrts_frame_malloc_global_init(global_state_t *g);
+
+__CILKRTS_END_EXTERN_C
+
+#endif // ! defined(INCLUDED_FRAME_MALLOC_DOT_H)
diff --git a/libcilkrts/runtime/full_frame.c b/libcilkrts/runtime/full_frame.c
new file mode 100644
index 00000000000..9ccfd110d6b
--- /dev/null
+++ b/libcilkrts/runtime/full_frame.c
@@ -0,0 +1,181 @@
+/* full_frame.c -*-C++-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2010-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ **************************************************************************/
+
+#include "full_frame.h"
+#include "stats.h"
+#include "os.h"
+#include "bug.h"
+#include "jmpbuf.h"
+#include "frame_malloc.h"
+
+COMMON_PORTABLE
+full_frame *__cilkrts_make_full_frame(__cilkrts_worker *w,
+ __cilkrts_stack_frame *sf)
+{
+ full_frame *ff;
+
+ START_INTERVAL(w, INTERVAL_ALLOC_FULL_FRAME) {
+ ff = (full_frame *)__cilkrts_frame_malloc(w, sizeof(*ff));
+ __cilkrts_mutex_init(&ff->lock);
+
+ ff->full_frame_magic_0 = FULL_FRAME_MAGIC_0;
+ ff->join_counter = 0;
+ ff->parent = 0;
+ ff->rightmost_child = 0;
+ ff->left_sibling = ff->right_sibling = 0;
+ ff->call_stack = sf;
+ ff->is_call_child = 0;
+ ff->simulated_stolen = 0;
+ ff->children_reducer_map = ff->right_reducer_map = 0;
+ ff->pending_exception =
+ ff->child_pending_exception =
+ ff->right_pending_exception = NULL;
+
+ ff->sync_sp = 0;
+#ifdef _WIN32
+ ff->exception_sp = 0;
+ ff->trylevel = (unsigned long)-1;
+ ff->registration = 0;
+#endif
+ ff->frame_size = 0;
+ ff->fiber_self = 0;
+ ff->fiber_child = 0;
+
+ ff->sync_master = 0;
+
+ /*__cilkrts_init_full_frame_sysdep(w, ff);*/
+ ff->full_frame_magic_1 = FULL_FRAME_MAGIC_1;
+ } STOP_INTERVAL(w, INTERVAL_ALLOC_FULL_FRAME);
+ return ff;
+}
+
+COMMON_PORTABLE void __cilkrts_put_stack(full_frame *ff,
+ __cilkrts_stack_frame *sf)
+{
+ /* When suspending frame ff prior to stealing it, __cilkrts_put_stack is
+ * used to store the stack pointer for eventual sync. When suspending
+ * frame ff prior to a sync, __cilkrts_put_stack is called to re-establish
+ * the sync stack pointer, offsetting it by any change in the stack depth
+ * that occured between the spawn and the sync.
+ * Although it is not usually meaningful to add two pointers, the value of
+ * ff->sync_sp at the time of this call is really an integer, not a
+ * pointer.
+ */
+ ptrdiff_t sync_sp_i = (ptrdiff_t) ff->sync_sp;
+ char* sp = (char*) __cilkrts_get_sp(sf);
+
+ ff->sync_sp = sp + sync_sp_i;
+
+ DBGPRINTF("%d- __cilkrts_put_stack - adjust (+) sync "
+ "stack of full frame %p (+sp: %p) to %p\n",
+ __cilkrts_get_tls_worker()->self, ff, sp, ff->sync_sp);
+}
+
+COMMON_PORTABLE void __cilkrts_take_stack(full_frame *ff, void *sp)
+{
+ /* When resuming the parent after a steal, __cilkrts_take_stack is used to
+ * subtract the new stack pointer from the current stack pointer, storing
+ * the offset in ff->sync_sp. When resuming after a sync,
+ * __cilkrts_take_stack is used to subtract the new stack pointer from
+ * itself, leaving ff->sync_sp at zero (null). Although the pointers being
+ * subtracted are not part of the same contiguous chunk of memory, the
+ * flat memory model allows us to subtract them and get a useable offset.
+ */
+ ptrdiff_t sync_sp_i = ff->sync_sp - (char*) sp;
+
+ ff->sync_sp = (char *) sync_sp_i;
+
+ DBGPRINTF("%d- __cilkrts_take_stack - adjust (-) sync "
+ "stack of full frame %p to %p (-sp: %p)\n",
+ __cilkrts_get_tls_worker()->self, ff, ff->sync_sp, sp);
+}
+
+COMMON_PORTABLE void __cilkrts_adjust_stack(full_frame *ff, size_t size)
+{
+ /* When resuming the parent after a steal, __cilkrts_take_stack is used to
+ * subtract the new stack pointer from the current stack pointer, storing
+ * the offset in ff->sync_sp. When resuming after a sync,
+ * __cilkrts_take_stack is used to subtract the new stack pointer from
+ * itself, leaving ff->sync_sp at zero (null). Although the pointers being
+ * subtracted are not part of the same contiguous chunk of memory, the
+ * flat memory model allows us to subtract them and get a useable offset.
+ *
+ * __cilkrts_adjust_stack() is used to deallocate a Variable Length Array
+ * by adding it's size to ff->sync_sp.
+ */
+ ff->sync_sp = ff->sync_sp + size;
+
+ DBGPRINTF("%d- __cilkrts_adjust_stack - adjust (+) sync "
+ "stack of full frame %p to %p (+ size: 0x%x)\n",
+ __cilkrts_get_tls_worker()->self, ff, ff->sync_sp, size);
+}
+
+COMMON_PORTABLE
+void __cilkrts_destroy_full_frame(__cilkrts_worker *w, full_frame *ff)
+{
+ validate_full_frame(ff);
+ CILK_ASSERT(ff->children_reducer_map == 0);
+ CILK_ASSERT(ff->right_reducer_map == 0);
+ CILK_ASSERT(NULL == ff->pending_exception);
+ CILK_ASSERT(NULL == ff->child_pending_exception);
+ CILK_ASSERT(NULL == ff->right_pending_exception);
+ __cilkrts_mutex_destroy(w, &ff->lock);
+ __cilkrts_frame_free(w, ff, sizeof(*ff));
+}
+
+COMMON_PORTABLE void validate_full_frame(full_frame *ff)
+{
+ /* check the magic numbers, for debugging purposes */
+ if (ff->full_frame_magic_0 != FULL_FRAME_MAGIC_0 ||
+ ff->full_frame_magic_1 != FULL_FRAME_MAGIC_1)
+ abort_because_rts_is_corrupted();
+}
+
+void __cilkrts_frame_lock(__cilkrts_worker *w, full_frame *ff)
+{
+ validate_full_frame(ff);
+ __cilkrts_mutex_lock(w, &ff->lock);
+}
+
+void __cilkrts_frame_unlock(__cilkrts_worker *w, full_frame *ff)
+{
+ __cilkrts_mutex_unlock(w, &ff->lock);
+}
+
+/* End full_frame.c */
diff --git a/libcilkrts/runtime/full_frame.h b/libcilkrts/runtime/full_frame.h
new file mode 100644
index 00000000000..327a3337afe
--- /dev/null
+++ b/libcilkrts/runtime/full_frame.h
@@ -0,0 +1,493 @@
+/* full_frame.h -*-C++-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ **************************************************************************/
+
+#ifndef INCLUDED_FULL_FRAME_DOT_H
+#define INCLUDED_FULL_FRAME_DOT_H
+
+
+#include "rts-common.h"
+#include "worker_mutex.h"
+
+#include <cilk/common.h>
+#include <internal/abi.h>
+#include <stddef.h>
+#include "cilk_fiber.h"
+
+__CILKRTS_BEGIN_EXTERN_C
+
+/** Magic numbers for full_frame, used for debugging */
+typedef unsigned long long ff_magic_t;
+
+/* COMMON_SYSDEP */ struct pending_exception_info; /* opaque */
+
+/*************************************************************
+ Full frames
+*************************************************************/
+
+/**
+ * @file full_frame.h
+ * @brief A full frame includes additional information such as a join
+ * counter and parent frame.
+ * @defgroup FullFrames Full Frames
+ * A full frame includes additional information such as a join
+ * counter and parent frame.
+ * @{
+ */
+
+/**
+ * Convenience typedef so we don't have to specify "struct full_frame"
+ * all over the code. Putting it before the structure definition allows
+ * us to use the typedef within the structure itself
+ */
+typedef struct full_frame full_frame;
+
+/**
+ * @brief A full frame includes additional information such as a join
+ * counter and parent frame.
+ *
+ * The frame at the top of a worker's stack is promoted into a "full"
+ * frame, which carries additional information, such as join counter
+ * and parent frame. Full frames can be suspended at a sync, in which
+ * case they lie somewhere in memory and do not belong to any
+ * worker.
+ *
+ * Full frames are in contrast to the entries in the worker's deque which
+ * are only represented by a pointer to their __cilkrts_stack_frame.
+ *
+ * At any instant, we say that a full frame ff is either "suspended",
+ * or "owned" by some worker w.
+ *
+ * More precisely, we say that a worker w owns a frame ff under one of
+ * the following conditions:
+ *
+ * 1. Creation: Worker w has just created ff, but not yet linked ff
+ * into the tree of full frames. This situation can occur when a
+ * worker is unrolling a call stack to promote a
+ * __cilkrts_stack_frame to a full_frame.
+ * 2. Executing frame: We have w->l->frame_ff == ff, i.e,. ff is the
+ * currently executing frame for w.
+ * 3. Next frame: We have w->l->next_frame_ff == ff, i.e,. ff is the
+ * next frame that w is about to execute.
+ * 4. Resume execution: Worker w has popped ff from
+ * w->l->next_frame_ff, and is about to resume execution of ff.
+ * 5. Dying leaf: Worker w has finished executing a frame ff
+ * that is a leaf the tree of full frames, and is in the process
+ * of unlinking "ff" from the tree.
+ *
+ * Otherwise, the frame ff is suspended, and has no owner.
+ * Note that work-stealing changes the owner of a full frame from the
+ * victim to the thief.
+ *
+ * Using this notion of ownership, we classify the fields of a full
+ * frame into one of several categories:
+ *
+ * 1. Local:
+ * These fields are accessed only by the owner of the full frame.
+ * Because a frame can have only one owner at a time, these fields
+ * can be modified without any (additional) locking or
+ * synchronization, assuming the correct synchronization for
+ * changing the ownership of full frame (e.g., on a successful
+ * steal) is already in place.
+ *
+ * 2. Constant (i.e., read-only):
+ * This field is constant for the lifetime of the full frame.
+ * No locks are needed to access this field.
+ * Technically, a field could be read-only and local, but we assume
+ * it is shared.
+ *
+ * 3. Self-locked:
+ * To access this field in the frame ff, a worker should acquire
+ * the lock on ff.
+ * A self-locked field is conceptually "shared" between the worker
+ * that owns frame ff (which is a child) and the worker that
+ * owns the frame ff->parent (which is the parent of ff).
+ *
+ * 4. Parent-locked:
+ * To access this field in the frame ff, a worker should
+ * acquire the lock on ff->parent.
+ * A parent-locked field is conceptually "shared" between the worker
+ * that owns frame ff, and a worker that is either owns the
+ * parent frame (ff->parent) or owns a sibling frame of ff (i.e.,
+ * any child of ff->parent).
+ *
+ * 5. Synchronization
+ * A field used explicitly for synchronization (i.e., locks).
+ */
+
+/* COMMON_PORTABLE */
+struct full_frame
+{
+ /**
+ * Value to detect writes off the beginning of a full_frame.
+ */
+# define FULL_FRAME_MAGIC_0 ((ff_magic_t)0x361e710b9597d553ULL)
+
+ /**
+ * Field to detect writes off the beginning of a full_frame. Must be
+ * FULL_FRAME_MAGIC_0.
+ * [constant]
+ */
+ ff_magic_t full_frame_magic_0;
+
+ /**
+ * Used to serialize access to this full_frame
+ * [synchronization]
+ */
+ struct mutex lock;
+
+ /**
+ * Count of outstanding children running in parallel
+ * [self-locked]
+ */
+ int join_counter;
+
+ /**
+ * If TRUE: frame was called by the parent.
+ * If FALSE: frame was spawned by parent.
+ * [constant]
+ */
+ int is_call_child;
+
+ /**
+ * TRUE if this frame is the loot of a simulated steal.
+ *
+ * This situation never happens in normal execution. However,
+ * when running under cilkscreen, a worker may promote frames and
+ * then immediately suspend them, in order to simulate an
+ * execution on an infinite number of processors where all spawns
+ * are stolen. In this case, the frame is marked as the loot of a fake
+ * steal.
+ * [local]
+ */
+ int simulated_stolen;
+
+ /**
+ * Caller of this full_frame
+ * [constant]
+ */
+ full_frame *parent;
+
+ /**
+ * Doubly-linked list of children. The serial execution order is
+ * by definition from left to right. Because of how we do work
+ * stealing, the parent is always to the right of all its
+ * children.
+ *
+ * For a frame ff, we lock the ff->parent to follow the sibling
+ * links for ff.
+ *
+ * [parent-locked]
+ */
+ full_frame *left_sibling;
+
+ /**
+ * @copydoc left_sibling
+ */
+ full_frame *right_sibling;
+
+ /**
+ * Pointer to rightmost child
+ *
+ * [self-locked]
+ */
+ full_frame *rightmost_child;
+
+ /**
+ * Call stack associated with this frame.
+ * Set and reset in make_unrunnable and make_runnable
+ *
+ * [self-locked]
+ */
+ __cilkrts_stack_frame *call_stack;
+
+ /**
+ * Accumulated reducers of children
+ *
+ * [self-locked]
+ */
+ struct cilkred_map *children_reducer_map;
+
+ /**
+ * Accumulated reducers of right siblings that have already
+ * terminated
+ *
+ * [parent-locked]
+ */
+ struct cilkred_map *right_reducer_map;
+
+ /**
+ * Exception that needs to be pass to our parent
+ *
+ * [local]
+ *
+ * TBD: verify that the exception code satisfies this requirement.
+ */
+ struct pending_exception_info *pending_exception;
+
+ /**
+ * Exception from one of our children
+ *
+ * [self-locked]
+ */
+ struct pending_exception_info *child_pending_exception;
+
+ /**
+ * Exception from any right siblings
+ *
+ * [parent-locked]
+ */
+ struct pending_exception_info *right_pending_exception;
+
+ /**
+ * Stack pointer to restore on sync.
+ * [local]
+ */
+ char *sync_sp;
+
+#ifdef _WIN32
+ /**
+ * Stack pointer to restore on exception.
+ * [local]
+ */
+ char *exception_sp;
+
+ /**
+ * Exception trylevel at steal
+ * [local]
+ *
+ * TBD: this field is set but not read?
+ */
+ unsigned long trylevel;
+
+ /**
+ * Exception registration head pointer to restore on sync.
+ * [local]
+ */
+ unsigned long registration;
+#endif
+
+ /**
+ * Size of frame to match sync sp
+ * [local]
+ * TBD: obsolete field only used in debugging?
+ */
+ ptrdiff_t frame_size;
+
+ /**
+ * Allocated fibers that need to be freed. The fibers work
+ * like a reducer. The leftmost frame may have @c fiber_self
+ * null and owner non-null.
+ *
+ * [local]
+ * TBD: verify exception code satisfies this requirement.
+ */
+ cilk_fiber *fiber_self;
+
+ /**
+ * Allocated fibers that need to be freed. The fibers work
+ * like a reducer. The leftmost frame may have @c fiber_self
+ * null and owner non-null.
+ *
+ * [self-locked]
+ */
+ cilk_fiber *fiber_child;
+
+ /**
+ * If the sync_master is set, this function can only be sync'd by the team
+ * leader, who first entered Cilk. This is set by the first worker to steal
+ * from the user worker.
+ *
+ * [self-locked]
+ */
+ __cilkrts_worker *sync_master;
+
+ /**
+ * Value to detect writes off the end of a full_frame.
+ */
+# define FULL_FRAME_MAGIC_1 ((ff_magic_t)0x189986dcc7aee1caULL)
+
+ /**
+ * Field to detect writes off the end of a full_frame. Must be
+ * FULL_FRAME_MAGIC_1.
+ *
+ * [constant]
+ */
+ ff_magic_t full_frame_magic_1;
+};
+
+/* The functions __cilkrts_put_stack and __cilkrts_take_stack keep track of
+ * changes in the stack's depth between when the point at which a frame is
+ * stolen and when it is resumed at a sync. A stolen frame typically goes
+ * through the following phase changes:
+ *
+ * 1. Suspend frame while stealing it.
+ * 2. Resume stolen frame at begining of continuation
+ * 3. Suspend stolen frame at a sync
+ * 4. Resume frame (no longer marked stolen) after the sync
+ *
+ * When the frame is suspended (steps 1 and 3), __cilkrts_put_stack is called to
+ * establish the stack pointer for the sync. When the frame is resumed (steps
+ * 2 and 4), __cilkrts_take_stack is called to indicate the stack pointer
+ * (which may be on a different stack) at
+ * the point of resume. If the stack pointer changes between steps 2 and 3,
+ * e.g., as a result of pushing 4 bytes onto the stack,
+ * the offset is reflected in the value of ff->sync_sp after step 3 relative to
+ * its value after step 1 (e.g., the value of ff->sync_sp after step 3 would be
+ * 4 less than its value after step 1, for a down-growing stack).
+ *
+ * Imp detail: The actual call chains for each of these phase-change events is:
+ *
+ * 1. unroll_call_stack -> make_unrunnable -> __cilkrts_put_stack
+ * 2. do_work -> __cilkrts_resume -> __cilkrts_take_stack
+ * 3. do_sync -> disown -> make_runnable -> __cilkrts_put_stack
+ * 4. __cilkrts_resume -> __cilkrts_take_stack
+ *
+ * (The above is a changeable implementation detail. The resume, sequence, in
+ * particular, is more complex on some operating systems.)
+ */
+
+/**
+ * @brief Records the stack pointer within the @c sf stack frame as the
+ * current stack pointer at the point of suspending full frame @c ff.
+ *
+ * @pre @c ff->sync_sp must be either null or contain the result of a prior call to
+ * @c __cilkrts_take_stack().
+ * @pre If @c ff->sync_sp is not null, then @c SP(sf) must refer to the same stack as
+ * the @c sp argument to the prior call to @c __cilkrts_take_stack().
+ *
+
+ * @post If @c ff->sync_sp was null before the call, then @c
+ * ff->sync_sp will be set to @c SP(sf).
+ * @post Otherwise, @c ff->sync_sp will be restored to the value it had just prior
+ * to the last call to @c __cilkrts_take_stack(), except offset by any change
+ * in the stack pointer between the call to @c __cilkrts_take_stack() and
+ * this call to @c __cilkrts_put_stack().
+ *
+ * @param ff The full frame that is being suspended.
+ * @param sf The @c __cilkrts_stack_frame that is being suspended. The stack
+ * pointer will be taken from the jmpbuf contained within this
+ * @c __cilkrts_stack_frame.
+ */
+COMMON_PORTABLE void __cilkrts_put_stack(full_frame *ff,
+ __cilkrts_stack_frame *sf);
+
+/**
+ * @brief Records the stack pointer @c sp as the stack pointer at the point of
+ * resuming execution on full frame @c ff.
+ *
+ * The value of @c sp may be on a different stack than the original
+ * value recorded for the stack pointer using __cilkrts_put_stack().
+ *
+ * @pre @c ff->sync_sp must contain a value set by @c __cilkrts_put_stack().
+ *
+ * @post @c ff->sync_sp contains an *integer* value used to compute a change in the
+ * stack pointer upon the next call to @c __cilkrts_take_stack().
+ * @post If @c sp equals @c ff->sync_sp, then @c ff->sync_sp is set to null.
+ *
+ * @param ff The full frame that is being resumed.
+ * @param sp The stack pointer for the stack the function is being resumed on.
+ */
+COMMON_PORTABLE void __cilkrts_take_stack(full_frame *ff, void *sp);
+
+/*
+ * @brief Adjust the stack for to deallocate a Variable Length Array
+ *
+ * @param ff The full frame that is being adjusted.
+ * @param size The size of the array being deallocated from the stack
+ */
+COMMON_PORTABLE void __cilkrts_adjust_stack(full_frame *ff, size_t size);
+
+/**
+ * @brief Allocates and initailizes a full_frame.
+ *
+ * @param w The memory for the full_frame will be allocated out of the
+ * worker's pool.
+ * @param sf The @c __cilkrts_stack_frame which will be saved as the call_stack
+ * for this full_frame.
+ *
+ * @return The newly allocated and initialized full_frame.
+ */
+COMMON_PORTABLE
+full_frame *__cilkrts_make_full_frame(__cilkrts_worker *w,
+ __cilkrts_stack_frame *sf);
+
+/**
+ * @brief Deallocates a full_frame.
+ *
+ * @param w The memory for the full_frame will be returned to the worker's pool.
+ * @param ff The full_frame to be deallocated.
+ */
+COMMON_PORTABLE
+void __cilkrts_destroy_full_frame(__cilkrts_worker *w, full_frame *ff);
+
+/**
+ * @brief Performs sanity checks to check the integrity of a full_frame.
+ *
+ * @param ff The full_frame to be validated.
+ */
+COMMON_PORTABLE void validate_full_frame(full_frame *ff);
+
+/**
+ * @brief Locks the mutex contained in a full_frame.
+ *
+ * The full_frame is validated before the runtime attempts to lock it.
+ *
+ * @post @c ff->lock will be owned by @c w.
+ *
+ * @param w The worker that will own the full_frame. If the runtime is
+ * collecting stats, the intervals will be attributed to the worker.
+ * @param ff The full_frame containing the mutex to be locked.
+ */
+COMMON_PORTABLE void __cilkrts_frame_lock(__cilkrts_worker *w,
+ full_frame *ff);
+
+/**
+ * @brief Unlocks the mutex contained in a full_frame.
+ *
+ * @pre @c ff->lock must must be owned by @c w.
+ *
+ * @param w The worker that currently owns the full_frame.
+ * @param ff The full_frame containing the mutex to be unlocked.
+ */
+COMMON_PORTABLE void __cilkrts_frame_unlock(__cilkrts_worker *w,
+ full_frame *ff);
+/** @} */
+
+__CILKRTS_END_EXTERN_C
+
+#endif // ! defined(INCLUDED_FULL_FRAME_DOT_H)
diff --git a/libcilkrts/runtime/global_state.cpp b/libcilkrts/runtime/global_state.cpp
new file mode 100644
index 00000000000..02de54f43b1
--- /dev/null
+++ b/libcilkrts/runtime/global_state.cpp
@@ -0,0 +1,628 @@
+/* global_state.cpp -*-C++-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ **************************************************************************/
+
+#include "global_state.h"
+#include "os.h"
+#include "bug.h"
+#include "metacall_impl.h"
+#include "stats.h"
+#include "cilk/cilk_api.h"
+#include "cilk_malloc.h"
+#include "record-replay.h"
+
+#include <algorithm> // For max()
+#include <cstring>
+#include <cstdlib>
+#include <climits>
+#include <cerrno>
+
+#ifdef _WIN32
+# include <wchar.h>
+#endif
+
+// TBD: There is a race when multiple threads try to initialize the
+// user_settable_values??
+//
+// Set to true if the user settable values portion of the global state
+// singleton is initialized, even if the rest of the singleton is not
+// initialized.
+int cilkg_user_settable_values_initialized = false;
+
+namespace {
+
+// Single copy of the global state. Zero-filled until
+// cilkg_get_user_settable_values() is called and partially-zero-filled until
+// cilkg_init_global_state() is called. The first field is filled in with
+// the size of a void* for the debugger and must be valid before initialization
+global_state_t global_state_singleton =
+{
+ sizeof(void *), // addr_size
+};
+
+
+// Variables that need to export C-style names
+extern "C"
+{
+ // Pointer to the global state singleton.
+ global_state_t *cilkg_singleton_ptr = NULL;
+
+ // __cilkrts_global_state is exported and referenced by the debugger.
+ // The debugger expects it to be valid when the module loads.
+// CILK_EXPORT_DATA
+ global_state_t *__cilkrts_global_state = &global_state_singleton;
+}
+
+// Returns true if 'a' and 'b' are equal null-terminated strings
+inline bool strmatch(const char* a, const char* b)
+{
+ return 0 == std::strcmp(a, b);
+}
+
+// Returns the integer value represented by the null-terminated string at 's'.
+inline long to_long(const char* s)
+{
+ char *end;
+
+ errno = 0;
+ return std::strtol(s, &end, 0);
+}
+
+#ifdef _WIN32
+// Returns true if 'a' and 'b' are equal null-terminated wide-char strings
+inline bool strmatch(const wchar_t* a, const wchar_t* b)
+{
+ return 0 == wcscmp(a, b);
+}
+
+// Returns true if the multi-byte character string at 'a' represents the same
+// character sequence as the wide-character string at 'b'. The behavior is
+// undefined if 'a' contains more than 30 multi-byte characters.
+bool strmatch(const char* a, const wchar_t* b)
+{
+ // Convert 'a' to wide-characters, then compare.
+ wchar_t wa[31];
+ std::size_t count;
+ errno_t err = mbstowcs_s(&count, wa, a, 30);
+ CILK_ASSERT(0 == err);
+ if (err) return false;
+ return strmatch(wa, b);
+}
+
+// Returns true if the wide-character string at 'a' represents the same
+// character sequence as the multi-byte character string at 'b'. The behavior
+// id undefined if 'b' contains more than 30 multi-byte characters.
+inline
+bool strmatch(const wchar_t* a, const char* b)
+{
+ return strmatch(b, a);
+}
+
+
+// Returns the integer value represented by the null-terminated wide-char
+// string at 's'.
+inline long to_long(const wchar_t* s)
+{
+ wchar_t *end;
+
+ errno = 0;
+ return wcstol(s, &end, 0);
+}
+#endif
+
+// Check if Cilkscreen or other sequential ptool wants to force reducers.
+bool always_force_reduce()
+{
+ // Metacall *looks* like a no-op. volatile needed to keep compiler from
+ // optimizing away variable.
+ volatile char not_force_reduce = '\377';
+ __cilkrts_metacall(METACALL_TOOL_SYSTEM, HYPER_ZERO_IF_FORCE_REDUCE,
+ const_cast<char*>(&not_force_reduce));
+ return ! not_force_reduce;
+}
+
+// Stores the boolean value represented by the null-terminated string at 'val'
+// into the integer object at 'out'. Returns '__CILKRTS_SET_PARAM_SUCCESS' if
+// 'val' is "true", "false", "0" or "1" and '__CILKRTS_SET_PARAM_INVALID'
+// otherwise.
+template <typename INT_T, typename CHAR_T>
+int store_bool(INT_T *out, const CHAR_T *val)
+{
+ static const char* const s_zero = "0";
+ static const char* const s_one = "1";
+ static const char* const s_true = "true";
+ static const char* const s_false = "false";
+
+ if (val == 0)
+ return __CILKRTS_SET_PARAM_INVALID;
+
+ if (strmatch(s_false, val) || strmatch(s_zero, val)) {
+ *out = 0;
+ return __CILKRTS_SET_PARAM_SUCCESS;
+ }
+
+ if (strmatch(s_true, val) || strmatch(s_one, val)) {
+ *out = 1;
+ return __CILKRTS_SET_PARAM_SUCCESS;
+ }
+
+ return __CILKRTS_SET_PARAM_INVALID;
+}
+
+// Stores the integer value represented by the null-terminated string at 'val'
+// into the integer object at 'out', restricting the result to the range 'min'
+// to 'max', inclusive. Returns '__CILKRTS_SET_PARAM_SUCCESS' if the conversion
+// succeeds and is in range, '__CILKRTS_SET_PARAM_XRANGE' if the conversion
+// succeeds but is out of range, and '__CILKRTS_SET_PARAM_INVALID' otherwise. In
+// the case of any error, '*out' is unchanged.
+template <typename INT_T, typename CHAR_T>
+int store_int(INT_T *out, const CHAR_T *val, INT_T min, INT_T max)
+{
+ errno = 0;
+ long val_as_long = to_long(val);
+ if (val_as_long == 0 && errno != 0)
+ return __CILKRTS_SET_PARAM_INVALID;
+ if (val_as_long < min || val_as_long == LONG_MIN)
+ return __CILKRTS_SET_PARAM_XRANGE;
+ else if (val_as_long > max || val_as_long == LONG_MAX)
+ return __CILKRTS_SET_PARAM_XRANGE;
+
+ *out = val_as_long;
+ return __CILKRTS_SET_PARAM_SUCCESS;
+}
+
+// Implementaton of cilkg_set_param templatized on character type.
+// Windows will instantiate with both char and wchar_t.
+// Note that g must have its user settable values set, but need not be fully
+// initialized.
+template <class CHAR_T>
+int set_param_imp(global_state_t* g, const CHAR_T* param, const CHAR_T* value)
+{
+ static const char* const s_force_reduce = "force reduce";
+ static const char* const s_nworkers = "nworkers";
+ static const char* const s_max_user_workers = "max user workers";
+ static const char* const s_local_stacks = "local stacks";
+ static const char* const s_shared_stacks = "shared stacks";
+ static const char* const s_nstacks = "nstacks";
+ static const char* const s_stack_size = "stack size";
+
+ // We must have a parameter and a value
+ if (0 == param)
+ return __CILKRTS_SET_PARAM_INVALID;
+ if (0 == value)
+ return __CILKRTS_SET_PARAM_INVALID;
+
+ if (strmatch(param, s_force_reduce))
+ {
+ // Sets whether we force a reduce operation at every sync. Useful for
+ // debugging reducers. Off by default. Overridden by Cilkscreen
+ //
+ // Documented in cilk_api_<os>.h
+ if (always_force_reduce())
+ // Force reduce is set by cilkscreen. User cannot change it.
+ return __CILKRTS_SET_PARAM_LATE;
+
+ return store_bool(&g->force_reduce, value);
+ }
+ else if (strmatch(param, s_nworkers))
+ {
+ // Set the total number of workers. Overrides count of cores we get
+ // from the OS and the setting of the CILK_NWORKERS environment
+ // variable. Setting to 0 indicates that the default worker count
+ // should be used.
+ //
+ // Documented in cilk_api_<os>.h
+ if (cilkg_singleton_ptr)
+ return __CILKRTS_SET_PARAM_LATE;
+
+ // Fetch the number of cores. There must be at last 1, since we're
+ // executing on *something*, aren't we!?
+ int hardware_cpu_count = __cilkrts_hardware_cpu_count();
+ CILK_ASSERT(hardware_cpu_count > 0);
+
+ int max_cpu_count = 16 * hardware_cpu_count;
+ if (__cilkrts_running_under_sequential_ptool())
+ {
+ hardware_cpu_count = 1;
+ max_cpu_count = 1;
+ }
+ // Allow a value of 0, which means "set to hardware thread count".
+ int ret = store_int(&g->P, value, 0, max_cpu_count);
+ if (0 == g->P)
+ g->P = hardware_cpu_count;
+ return ret;
+ }
+ else if (strmatch(param, s_max_user_workers))
+ {
+ // ** UNDOCUMENTED **
+ //
+ // Sets the number of slots allocated for user worker threads
+ int hardware_cpu_count = __cilkrts_hardware_cpu_count();
+ CILK_ASSERT (hardware_cpu_count > 0);
+
+ return store_int(&g->max_user_workers, value, 1,
+ 16 * hardware_cpu_count);
+ }
+ else if (strmatch(param, s_local_stacks))
+ {
+ // ** UNDOCUMENTED **
+ //
+ // Number of stacks we'll hold in the per-worker stack cache. Maximum
+ // value is 42. See __cilkrts_make_global_state for details.
+ return store_int(&g->fiber_pool_size, value, 0, 42);
+ }
+ else if (strmatch(param, s_shared_stacks))
+ {
+ // ** UNDOCUMENTED **
+ //
+ // Maximum number of stacks we'll hold in the global stack
+ // cache. Maximum value is 42. See __cilkrts_make_global_state for
+ // details.
+ return store_int(&g->global_fiber_pool_size, value, 0, 42);
+ }
+ else if (strmatch(param, s_nstacks))
+ {
+ // Sets the maximum number of stacks permitted at one time. If the
+ // runtime reaches this maximum, it will cease to allocate stacks and
+ // the app will lose parallelism. 0 means unlimited. Default is
+ // unlimited. Minimum is twice the number of worker threads, though
+ // that cannot be tested at this time.
+ //
+ // Undocumented at this time, though there are plans to expose it.
+ // The current implentation is for Linux debugging only and is not
+ // robust enough for users.
+ if (cilkg_singleton_ptr)
+ return __CILKRTS_SET_PARAM_LATE;
+ return store_int<unsigned>(&g->max_stacks, value, 0, INT_MAX);
+ }
+ else if (strmatch(param, s_stack_size))
+ {
+ // ** UNDOCUMENTED **
+ //
+ // Sets the size (in bytes) of the stacks that Cilk creates.
+ // Can only be set before the runtime starts.
+ if (cilkg_singleton_ptr)
+ return __CILKRTS_SET_PARAM_LATE;
+
+ // Maximum value that can be parsed is MAX_INT (32-bit).
+ int ret = store_int<size_t>(&g->stack_size, value, 0, INT_MAX);
+
+ // Process the value the user set (or 0 if the user didn't set
+ // anything) into something nice for the current OS. This
+ // processing is done immediately and stored into
+ // g->stack_size so that a call to get stack size will return
+ // the value that the runtime will actually use.
+ g->stack_size = cilkos_validate_stack_size(g->stack_size);
+ return ret;
+ }
+
+
+ // If got here, then didn't match any of the strings
+ return __CILKRTS_SET_PARAM_UNIMP;
+}
+
+inline
+int calc_max_user_workers(global_state_t *g)
+{
+ // If it's been set by the user, give back what we got
+ if (g->max_user_workers > 0)
+ return g->max_user_workers;
+
+ // Calculate it
+ return std::max(3, g->P * 2);
+}
+
+} // end unnamed namespace
+
+__CILKRTS_BEGIN_EXTERN_C
+
+/**
+ * @brief Returns the global state object. If called for the first time,
+ * initializes the user-settable values in the global state, but does not
+ * initialize the rest of the structure.
+ */
+global_state_t* cilkg_get_user_settable_values()
+{
+ // Environment variable value. More than big enough for a 64-bit signed
+ // integer.
+ char envstr[24];
+
+ // Abbreviating &global_state_singleton as g is not only shorter, it also
+ // facilitates grepping for the string "g->", which appears ubiquitously
+ // in the runtime code.
+ global_state_t* g = &global_state_singleton;
+
+ // TBD: We need synchronization around this loop to prevent
+ // multiple threads from initializing this data.
+ if (! cilkg_user_settable_values_initialized)
+ {
+ size_t len;
+
+ // Preserve stealing disabled since it may have been set by the
+ // debugger
+ int stealing_disabled = g->stealing_disabled;
+
+ // All fields will be zero until set. In particular
+ std::memset(g, 0, sizeof(global_state_t));
+
+ // Fetch the number of cores. There must be at last 1, since we're
+ // executing on *something*, aren't we!?
+ int hardware_cpu_count = __cilkrts_hardware_cpu_count();
+ CILK_ASSERT(hardware_cpu_count > 0);
+
+ bool under_ptool = __cilkrts_running_under_sequential_ptool();
+ if (under_ptool)
+ hardware_cpu_count = 1;
+
+ g->stealing_disabled = stealing_disabled;
+ g->under_ptool = under_ptool;
+ g->force_reduce = 0; // Default Off
+ g->P = hardware_cpu_count; // Defaults to hardware CPU count
+ g->max_user_workers = 0; // 0 unless set by user
+ g->fiber_pool_size = 7; // Arbitrary default
+
+ g->global_fiber_pool_size = 3 * 3* g->P; // Arbitrary default
+ // 3*P was the default size of the worker array (including
+ // space for extra user workers). This parameter was chosen
+ // to match previous versions of the runtime.
+
+ if (4 == sizeof(void *))
+ g->max_stacks = 1200; // Only 1GB on 32-bit machines
+ else
+ g->max_stacks = 2400; // 2GB on 64-bit machines
+
+ // If we have 2400 1MB stacks, that is 2 gb. If we reach this
+ // limit on a single-socket machine, we may have other
+ // problems. Is 2400 too small for large multicore machines?
+
+ // TBD(jsukha, 11/27/2012): I set this limit on stacks to be a
+ // value independent of P. When running on a Xeon Phi with
+ // small values of P, I recall seeing a few microbenchmarks
+ // (e.g., fib) where a limit of 10*P seemed to be
+ // unnecessarily slowing things down.
+ //
+ // That being said, the code has changed sufficiently that
+ // this observation may no longer be true.
+ //
+ // Note: in general, the worst-case number of stacks required
+ // for a Cilk computation with spawn depth "d" on P workers is
+ // O(Pd). Code with unbalanced recursion may run into issues
+ // with this stack usage.
+
+ g->max_steal_failures = 128; // TBD: depend on max_workers?
+ g->stack_size = 0; // 0 unless set by the user
+
+ // Assume no record or replay log for now
+ g->record_replay_file_name = NULL;
+ g->record_or_replay = RECORD_REPLAY_NONE; // set by user
+
+ if (always_force_reduce())
+ g->force_reduce = true;
+ else if (cilkos_getenv(envstr, sizeof(envstr), "CILK_FORCE_REDUCE"))
+ store_bool(&g->force_reduce, envstr);
+
+ if (under_ptool)
+ g->P = 1; // Ignore environment variable if under cilkscreen
+ else if (cilkos_getenv(envstr, sizeof(envstr), "CILK_NWORKERS"))
+ // Set P to environment variable, but limit to no less than 1
+ // and no more than 16 times the number of hardware threads.
+ store_int(&g->P, envstr, 1, 16 * hardware_cpu_count);
+
+ if (cilkos_getenv(envstr, sizeof(envstr), "CILK_MAX_USER_WORKERS"))
+ // Set max_user_workers to environment variable, but limit to no
+ // less than 1 and no more 16 times the number of hardware
+ // threads. If not specified, defaults (somewhat arbitrarily) to
+ // the larger of 3 and twice the number of hardware threads.
+ store_int(&g->max_user_workers, envstr, 1, 16*hardware_cpu_count);
+
+ if (cilkos_getenv(envstr, sizeof(envstr), "CILK_STEAL_FAILURES"))
+ // Set the number of times a worker should fail to steal before
+ // it looks to see whether it should suspend itself.
+ store_int<unsigned>(&g->max_steal_failures, envstr, 1, INT_MAX);
+
+ // Compute the total number of workers to allocate. Subtract one from
+ // nworkers and user workers so that the first user worker isn't
+ // factored in twice.
+ //
+ // total_workers must be computed now to support __cilkrts_get_total_workers
+ g->total_workers = g->P + calc_max_user_workers(g) - 1;
+
+#ifdef CILK_RECORD_REPLAY
+ // RecordReplay: See if we've been asked to replay a log
+ len = cilkos_getenv(envstr, 0, "CILK_REPLAY_LOG");
+ if (len > 0)
+ {
+ len += 1; // Allow for trailing NUL
+ g->record_or_replay = REPLAY_LOG;
+ g->record_replay_file_name = (char *)__cilkrts_malloc(len);
+ cilkos_getenv(g->record_replay_file_name, len, "CILK_REPLAY_LOG");
+ }
+
+ // RecordReplay: See if we've been asked to record a log
+ len = cilkos_getenv(envstr, 0, "CILK_RECORD_LOG");
+ if (len > 0)
+ {
+ if (RECORD_REPLAY_NONE != g->record_or_replay)
+ cilkos_warning("CILK_RECORD_LOG ignored since CILK_REPLAY_LOG is defined.\n");
+ else
+ {
+ len += 1; // Allow for trailing NUL
+ g->record_or_replay = RECORD_LOG;
+ g->record_replay_file_name = (char *)__cilkrts_malloc(len);
+ cilkos_getenv(g->record_replay_file_name, len, "CILK_RECORD_LOG");
+ }
+ }
+#endif
+
+ cilkg_user_settable_values_initialized = true;
+ }
+
+ return g;
+}
+
+int cilkg_calc_total_workers()
+{
+ global_state_t* g = cilkg_get_user_settable_values();
+
+ // Compute the total number of workers to allocate. Subtract one from
+ // nworkers and user workers so that the first user worker isn't
+ // factored in twice.
+ return g->P + calc_max_user_workers(g) - 1;
+}
+
+// Should be called while holding the global lock.
+global_state_t* cilkg_init_global_state()
+{
+ if (cilkg_singleton_ptr)
+ return cilkg_singleton_ptr;
+
+ // Get partially-initialized global state.
+ global_state_t* g = cilkg_get_user_settable_values();
+
+ if (g->max_stacks > 0) {
+
+ // nstacks is currently honored on non-Windows systems only.
+
+ // Set an upper bound on the number of stacks that are allocated. If
+ // nstacks is set, each worker gets up to one stack in its cache so that
+ // no one worker can hog all of the free stacks and keep work from being
+ // stolen by the other workers.
+
+ // nstacks corresponds to the number of stacks that will be allocated by
+ // the runtime apart from the initial stack created for each thread by
+ // the system. Therefore, if a user asks for n stacks, and there are
+ // p workers created, the total number of stacks is actually n + p.
+
+ // This feature is primarily for MIC which has flat memory
+ // instead of virtual addresses and tends to run out really quickly.
+ // It is not implemented for Windows and it's non-intuitive
+ // interaction with the local stack cache is specifically to help out
+ // MIC.
+
+ // About max_stacks / P stacks, except we require at least 1
+ // per pool.
+ if (((int)g->max_stacks / g->P) < g->fiber_pool_size)
+ g->fiber_pool_size = g->max_stacks / g->P;
+
+ if (g->fiber_pool_size <= 0) {
+ g->fiber_pool_size = 1;
+ }
+
+ if ((int)g->max_stacks < g->P)
+ g->max_stacks = g->P;
+
+ g->global_fiber_pool_size = g->P * (g->fiber_pool_size+1);
+ }
+
+ // Number of bytes/address - validation for debugger integration
+ g->addr_size = sizeof(void *);
+
+ __cilkrts_init_stats(&g->stats);
+
+ __cilkrts_frame_malloc_global_init(g);
+
+ g->Q = 0;
+ g->total_workers = cilkg_calc_total_workers();
+ g->system_workers = g->P - 1; // system_workers is here for the debugger.
+ g->work_done = 0;
+ g->workers_running = 0;
+ g->ltqsize = 1024; /* FIXME */
+
+ g->stack_size = cilkos_validate_stack_size(g->stack_size);
+ g->failure_to_allocate_stack = 0;
+
+
+ return g;
+}
+
+void cilkg_publish_global_state(global_state_t* g)
+{
+
+ // TBD: which one of these needs to be executed first? I say
+ // cilkg_singleton_ptr needs to be set last, with a mfence in
+ // between, since it is the flag that cilkg_is_published_is
+ // checking for.
+ __cilkrts_global_state = g;
+ __cilkrts_fence();
+ cilkg_singleton_ptr = g;
+}
+
+void cilkg_deinit_global_state()
+{
+ cilkg_singleton_ptr = NULL;
+ __cilkrts_global_state = NULL;
+}
+
+int cilkg_is_published(void)
+{
+ return NULL != cilkg_singleton_ptr;
+}
+
+int cilkg_set_param(const char* param, const char* value)
+{
+ return set_param_imp(cilkg_get_user_settable_values(), param, value);
+}
+
+#ifdef _WIN32
+int cilkg_set_param_w(const wchar_t* param, const wchar_t* value)
+{
+ return set_param_imp(cilkg_get_user_settable_values(), param, value);
+}
+#endif
+
+extern "C++" {
+ // C++ scheduler function (that may throw exceptions)
+ typedef void cpp_scheduler_t(__cilkrts_worker *w);
+}
+
+void __cilkrts_run_scheduler_with_exceptions(__cilkrts_worker *w)
+{
+ global_state_t* g = cilkg_get_global_state();
+ CILK_ASSERT(g->scheduler);
+
+ cpp_scheduler_t* scheduler = (cpp_scheduler_t*) g->scheduler;
+
+ try {
+ scheduler(w);
+ } catch (...) {
+ __cilkrts_bug("Exception escaped Cilk context");
+ }
+}
+
+__CILKRTS_END_EXTERN_C
+
+/* End global_state.cpp */
diff --git a/libcilkrts/runtime/global_state.h b/libcilkrts/runtime/global_state.h
new file mode 100644
index 00000000000..ef455e479d5
--- /dev/null
+++ b/libcilkrts/runtime/global_state.h
@@ -0,0 +1,417 @@
+/* global_state.h -*-C++-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ **************************************************************************/
+
+/**
+ * @file global_state.h
+ *
+ * @brief The global_state_t structure contains most of the global context
+ * maintained by the Intel Cilk runtime.
+ */
+
+#ifndef INCLUDED_GLOBAL_STATE_DOT_H
+#define INCLUDED_GLOBAL_STATE_DOT_H
+
+#include <cilk/common.h>
+
+#include "frame_malloc.h"
+#include "stats.h"
+#include "bug.h"
+#include "cilk_fiber.h"
+
+__CILKRTS_BEGIN_EXTERN_C
+
+/**
+ * Non-null place-holder for a stack handle that has no meaningful value.
+ */
+#define PLACEHOLDER_FIBER ((cilk_fiber *) -2)
+
+/**
+ * States for record_or_replay
+ */
+enum record_replay_t {
+ RECORD_REPLAY_NONE,
+ RECORD_LOG,
+ REPLAY_LOG
+};
+
+/**
+ * @brief The global state is a structure that is shared by all workers in
+ * Cilk.
+ *
+ * Make the structure ready for use by calling
+ * cilkg_init_global_state() and then cilkg_publish_global_state().
+ *
+ * The same global lock should be held while both of these methods are
+ * called. These methods are split because it is useful to execute
+ * other runtime initialization code in between.
+ *
+ * After cilkg_publish_global_state() has completed, Cilk runtime
+ * methods may call cilkg_get_global_state() to look at the published
+ * value without holding the global lock.
+ *
+ * Finally, clean up the global state by calling
+ * cilkg_deinit_global_state(). This method should be called only
+ * after all calls to cilkg_get_global_state() have completed, and
+ * while holding the global lock.
+ *
+ * Before initialization and after deinitialization, the fields in the
+ * global state have unspecified values, except for a few special
+ * fields labeled "USER SETTING", which can be read and written before
+ * initialization and after deinitialization.
+ */
+
+struct global_state_t { /* COMMON_PORTABLE */
+
+ /* Fields described as "(fixed)" should not be changed after
+ * initialization.
+ */
+
+ /*************************************************************************
+ * Note that debugger integration must reach into the
+ * global state! The debugger integration is depending on the
+ * offsets of the addr_size, system_workers, total_workers,
+ * stealing_disabled, sysdep, and workers. If these offsets change, the
+ * debugger integration library will need to be changed to match!!!
+ *************************************************************************/
+
+ int addr_size; ///< Number of bytes for an address, used by debugger (fixed)
+
+ int system_workers; ///< Number of system workers (fixed)
+
+ /**
+ * @brief USER SETTING: Maximum number of user workers that can be
+ * bound to cilk workers.
+ *
+ * 0 unless set by user. Call cilkg_calc_max_user_workers to get
+ * the value.
+ */
+ int max_user_workers;
+
+ int total_workers; ///< Total number of worker threads allocated (fixed)
+
+ int workers_running; ///< True when system workers have beens started */
+
+ /// Set by debugger to disable stealing (fixed)
+ int stealing_disabled;
+
+ /// System-dependent part of the global state
+ struct global_sysdep_state *sysdep;
+
+ /// Array of worker structures.
+ __cilkrts_worker **workers;
+
+ /******* END OF DEBUGGER-INTEGRATION FIELDS ***************/
+
+ /// Number of frames in each worker's lazy task queue
+ __STDNS size_t ltqsize;
+
+ /**
+ * @brief USER SETTING: Force all possible reductions.
+ *
+ * TRUE if running a p-tool that requires reducers to call the reduce()
+ * method even if no actual stealing occurs.
+ *
+ * When set to TRUE, runtime will simulate steals, forcing calls to the
+ * the reduce() methods of reducers.
+ *
+ */
+ int force_reduce;
+
+ /// USER SETTING: Per-worker fiber pool size
+ int fiber_pool_size;
+
+ /// USER SETTING: Global fiber pool size
+ int global_fiber_pool_size;
+
+ /**
+ * @brief TRUE when workers should exit scheduling loop so we can
+ * shut down the runtime and free the global state.
+ *
+ * @note @c work_done will be checked *FREQUENTLY* in the scheduling loop
+ * by idle workers. We need to ensure that it's not in a cache line which
+ * may be invalidated by other cores. The surrounding fields are either
+ * constant after initialization or not used until shutdown (stats) so we
+ * should be OK.
+ */
+ volatile int work_done;
+
+ int under_ptool; ///< True when running under a serial PIN tool
+
+ statistics stats; ///< Statistics on use of runtime
+
+ /**
+ * @brief USER SETTING: Maximum number of stacks the runtime will
+ * allocate (apart from those created by the OS when worker
+ * threads are created).
+ *
+ * If max_stacks == 0,there is no pre-defined maximum.
+ */
+ unsigned max_stacks;
+
+ /// Size of each stack
+ size_t stack_size;
+
+ /// Global cache for per-worker memory
+ struct __cilkrts_frame_cache frame_malloc;
+
+ /// Global fiber pool
+ cilk_fiber_pool fiber_pool;
+
+
+ /**
+ * @brief Track whether the runtime has failed to allocate a
+ * stack.
+ *
+ * Setting this flag prevents multiple warnings from being
+ * issued.
+ */
+ int failure_to_allocate_stack;
+
+ /**
+ * @brief USER SETTING: indicate record or replay log.
+ * Set to NULL if not used in this run.
+ */
+ char *record_replay_file_name;
+
+ /**
+ * @brief Record/replay state.
+ * Valid states are:
+ * RECORD_REPLAY_NONE - Not recording or replaying a log
+ * RECORD_LOG - Recording a log for replay later
+ * REPLAY_LOG - Replay a log recorded earlier
+ */
+ enum record_replay_t record_or_replay;
+
+ /**
+ * @brief Buffer to force max_steal_failures to appear on a
+ * different cache line from the previous member variables.
+ *
+ * This padding is needed because max_steal_failures is read
+ * constantly and other modified values in the global state will
+ * cause thrashing.
+ */
+ char cache_buf[64];
+
+ /**
+ * @brief Maximum number of times a thread should fail to steal
+ * before checking if Cilk is shutting down.
+ */
+ unsigned int max_steal_failures;
+
+ /// Pointer to scheduler entry point
+ void (*scheduler)(__cilkrts_worker *w);
+
+ /**
+ * @brief Buffer to force P and Q to appear on a different cache
+ * line from the previous member variables.
+ */
+ char cache_buf_2[64];
+
+ int P; ///< USER SETTING: number of system workers + 1 (fixed)
+ int Q; ///< Number of user threads currently bound to workers
+};
+
+/**
+ * @brief Initialize the global state object. This method must both
+ * complete before referencing any fields in the global state, except
+ * those specified as "user-settable values".
+ */
+global_state_t* cilkg_init_global_state();
+
+/**
+ * @brief Publish the global state object, so that
+ * cilkg_is_published can return true.
+ *
+ * @param g - the global state created by cilkg_init_global_state() to
+ * publish.
+ *
+ * After the global state object has been published, a thread should
+ * not modify this state unless it has exclusive access (i.e., holds
+ * the global lock).
+ */
+void cilkg_publish_global_state(global_state_t* g);
+
+/**
+ * @brief Return true if the global state has been fully initialized
+ * and published, and has not been deinitialized.
+ */
+int cilkg_is_published(void);
+
+/**
+ * @brief De-initializes the global state object. Must be called to free
+ * resources when the global state is no longer needed.
+ */
+void cilkg_deinit_global_state(void);
+
+/**
+ * @brief Returns the global state object. Result is valid only if the
+ * global state has been published (see cilkg_publish_global_state()).
+ */
+static inline
+global_state_t* cilkg_get_global_state(void)
+{
+ // "private" extern declaration:
+ extern global_state_t *cilkg_singleton_ptr;
+
+ __CILKRTS_ASSERT(cilkg_singleton_ptr); // Debug only
+ return cilkg_singleton_ptr;
+}
+
+
+/**
+ * @brief Implementation of __cilkrts_set_params.
+ *
+ * Set user controllable parameters
+ * @param param - string specifying parameter to be set
+ * @param value - string specifying new value
+ * @returns One of: CILKG_SET_PARAM_SUCCESS ( = 0),
+ * CILKG_SET_PARAM_UNIMP, CILKG_SET_PARAM_XRANGE,
+ * CILKG_SET_PARAM_INVALID, or CILKG_SET_PARAM_LATE.
+ *
+ * @attention The wide character version __cilkrts_set_param_w() is available
+ * only on Windows.
+ *
+ * Allowable parameter names:
+ *
+ * - "nworkers" - number of processors that should run Cilk code.
+ * The value is a string of digits to be parsed by strtol.
+ *
+ * - "force reduce" - test reducer callbacks by allocating new views
+ * for every spawn within which a reducer is accessed. This can
+ * significantly reduce performance. The value is "1" or "true"
+ * to enable, "0" or "false" to disable.
+ * @warning Enabling "force reduce" when running with more than a single
+ * worker is currently broken.
+ *
+ * - "max user workers" - (Not publicly documented) Sets the number of slots
+ * allocated for user worker threads
+ *
+ * - "local stacks" - (Not publicly documented) Number of stacks we'll hold in
+ * the per-worker stack cache. Range 1 .. 42. See
+ * cilkg_init_global_state for details.
+ *
+ * - "shared stacks" - (Not publicly documented) Maximum number of stacks
+ * we'll hold in the global stack cache. Maximum value is 42. See
+ * __cilkrts_make_global_state for details
+ *
+ * - "nstacks" - (Not publicly documented at this time, though it may be
+ * exposed in the future) Sets the maximum number of stacks permitted at one
+ * time. If the runtime reaches this maximum, it will cease to allocate
+ * stacks and the app will lose parallelism. 0 means unlimited. Default is
+ * unlimited. Minimum is twice the number of worker threads, though that
+ * cannot be tested at this time.
+ */
+int cilkg_set_param(const char* param, const char* value);
+#ifdef _WIN32
+/**
+ * @brief Implementation of __cilkrts_set_params for Unicode characters on
+ * Windows. See the documentation on @ref cilkg_set_param for more details.
+ *
+ * Set user controllable parameters
+ * @param param - string specifying parameter to be set
+ * @param value - string specifying new value
+ * @returns One of: CILKG_SET_PARAM_SUCCESS ( = 0),
+ * CILKG_SET_PARAM_UNIMP, CILKG_SET_PARAM_XRANGE,
+ * CILKG_SET_PARAM_INVALID, or CILKG_SET_PARAM_LATE.
+ */
+int cilkg_set_param_w(const wchar_t* param, const wchar_t* value);
+#endif
+
+/**
+ * @brief implementation of __cilkrts_get_nworkers()
+ */
+static inline
+int cilkg_get_nworkers(void)
+{
+ // "private" extern declaration
+ extern global_state_t* cilkg_get_user_settable_values(void);
+ return cilkg_get_user_settable_values()->P;
+}
+
+/**
+ * @brief implementation of __cilkrts_get_total_workers()
+ */
+static inline
+int cilkg_get_total_workers(void)
+{
+ // "private" extern declaration
+ extern int cilkg_calc_total_workers(void);
+
+ // This number can fluctate until initialization so we
+ // compute it from scratch
+ return cilkg_calc_total_workers();
+}
+
+/**
+ * @brief implementation of __cilkrts_get_force_reduce()
+ */
+static inline
+int cilkg_get_force_reduce(void)
+{
+ // "private" extern declaration
+ extern global_state_t* cilkg_get_user_settable_values(void);
+ return cilkg_get_user_settable_values()->force_reduce;
+}
+
+/**
+ * @brief implementation of __cilkrts_get_stack_size()
+ */
+static inline
+size_t cilkg_get_stack_size(void)
+{
+ // "private" extern declaration
+ extern global_state_t* cilkg_get_user_settable_values(void);
+ return cilkg_get_user_settable_values()->stack_size;
+}
+
+/**
+ * @brief Run the scheduler function stored in the global_state
+ *
+ * Look up the scheduler function in global_state and run it. Report a fatal
+ * error if an exception escapes the scheduler function.
+ *
+ * @param w - Worker structure to associate with the current thread.
+ *
+ * @attention The scheduler field of the global state must be set before this
+ * function is called.
+ */
+void __cilkrts_run_scheduler_with_exceptions(__cilkrts_worker *w);
+
+__CILKRTS_END_EXTERN_C
+
+#endif // ! defined(INCLUDED_GLOBAL_STATE_DOT_H)
diff --git a/libcilkrts/runtime/jmpbuf.c b/libcilkrts/runtime/jmpbuf.c
new file mode 100644
index 00000000000..39b51a593ce
--- /dev/null
+++ b/libcilkrts/runtime/jmpbuf.c
@@ -0,0 +1,48 @@
+/* jmpbuf.c -*-C-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ **************************************************************************/
+
+#include "jmpbuf.h"
+
+/*
+ * C99 requires that every inline function with external linkage have
+ * one extern declaration in the program.
+ */
+extern char *__cilkrts_get_sp(__cilkrts_stack_frame *sf);
+extern ptrdiff_t __cilkrts_get_frame_size(__cilkrts_stack_frame *sf);
+
+/* End jmpbuf.c */
diff --git a/libcilkrts/runtime/jmpbuf.h b/libcilkrts/runtime/jmpbuf.h
new file mode 100644
index 00000000000..60573f3a5fa
--- /dev/null
+++ b/libcilkrts/runtime/jmpbuf.h
@@ -0,0 +1,136 @@
+/* jmpbuf.h -*-C++-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ **************************************************************************/
+
+/**
+ * @file jmpbuf.h
+ *
+ * @brief Macros and functions to access the _JUMP_BUFFER initialized by a
+ * call to CILK_SETJMP before a cilk_spawn or cilk_sync. The definition of
+ * CILK_SETJMP and CILK_LONGJMP are OS dependent and in abi.h
+ *
+ */
+
+#ifndef INCLUDED_JMPBUF_DOT_H
+#define INCLUDED_JMPBUF_DOT_H
+
+#include <cilk/common.h>
+#include <internal/abi.h>
+#include <stddef.h>
+#include <setjmp.h>
+
+#if 0 /* defined CILK_USE_C_SETJMP && defined JB_RSP */
+# define JMPBUF_SP(ctx) (ctx)[0].__jmpbuf[JB_RSP]
+# define JMPBUF_FP(ctx) (ctx)[0].__jmpbuf[JB_RBP]
+# define JMPBUF_PC(ctx) (ctx)[0].__jmpbuf[JB_PC]
+#elif 0 /* defined CILK_USE_C_SETJMP && defined JB_SP */
+# define JMPBUF_SP(ctx) (ctx)[0].__jmpbuf[JB_SP]
+# define JMPBUF_FP(ctx) (ctx)[0].__jmpbuf[JB_BP]
+# define JMPBUF_PC(ctx) (ctx)[0].__jmpbuf[JB_PC]
+#elif defined _WIN64
+# define JMPBUF_SP(ctx) ((_JUMP_BUFFER*)(&(ctx)))->Rsp
+# define JMPBUF_FP(ctx) ((_JUMP_BUFFER*)(&(ctx)))->Rbp
+# define JMPBUF_PC(ctx) ((_JUMP_BUFFER*)(&(ctx)))->Rip
+#elif defined _WIN32
+ /** Fetch stack pointer from a __cilkrts_stack_frame */
+# define JMPBUF_SP(ctx) (ctx).Esp
+ /** Fetch frame pointer from a __cilkrts_stack_frame */
+# define JMPBUF_FP(ctx) (ctx).Ebp
+ /** Fetch program counter from a __cilkrts_stack_frame */
+# define JMPBUF_PC(ctx) (ctx).Eip
+#else /* defined __GNUC__ || defined __ICC */
+ /* word 0 is frame address
+ * word 1 is resume address
+ * word 2 is stack address */
+# define JMPBUF_FP(ctx) (ctx)[0]
+# define JMPBUF_PC(ctx) (ctx)[1]
+# define JMPBUF_SP(ctx) (ctx)[2]
+#endif
+
+/**
+ * @brief Get frame pointer from jump buffer in__cilkrts_stack_frame.
+ */
+#define FP(SF) JMPBUF_FP((SF)->ctx)
+
+/**
+ * @brief Get program counter from jump buffer in__cilkrts_stack_frame.
+ */
+#define PC(SF) JMPBUF_PC((SF)->ctx)
+
+/**
+ * @brief Get stack pointer from jump buffer in__cilkrts_stack_frame.
+ */
+#define SP(SF) JMPBUF_SP((SF)->ctx)
+
+
+__CILKRTS_BEGIN_EXTERN_C
+
+/**
+ * Fetch the stack pointer from a __cilkrts_stack_frame. The jmpbuf was
+ * initialized before a cilk_spawn or cilk_sync.
+ *
+ * @param sf __cilkrts_stack_frame containing the jmpbuf.
+ *
+ * @return the stack pointer from the ctx.
+ */
+inline char *__cilkrts_get_sp(__cilkrts_stack_frame *sf)
+{
+ return (char *)SP(sf);
+}
+
+/**
+ * Calculate the frame size from __cilkrts_stack_frame. The jmpbuf was
+ * initialized before a cilk_spawn or cilk_sync.
+ *
+ * @warning Returning an arbitrary value on Windows!
+ *
+ * @param sf __cilkrts_stack_frame containing the jmpbuf.
+ *
+ * @return the stack pointer from the ctx.
+ */
+inline ptrdiff_t __cilkrts_get_frame_size(__cilkrts_stack_frame *sf)
+{
+#ifdef _WIN32
+ if (0 == SP(sf))
+ return 256; // Arbitrary!
+#endif
+ return (ptrdiff_t)FP(sf) - (ptrdiff_t)SP(sf);
+}
+
+__CILKRTS_END_EXTERN_C
+
+#endif // ! defined(INCLUDED_JMPBUF_DOT_H)
diff --git a/libcilkrts/runtime/linux-symbols.ver b/libcilkrts/runtime/linux-symbols.ver
new file mode 100644
index 00000000000..aeb4a5fb13d
--- /dev/null
+++ b/libcilkrts/runtime/linux-symbols.ver
@@ -0,0 +1,369 @@
+/*
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ **************************************************************************/
+
+CILKABI0
+{
+ global:
+ __cilkrts_bind_thread;
+ __cilkrts_cilk_for_32;
+ __cilkrts_cilk_for_64;
+ __cilkrts_debugger_notification;
+ __cilkrts_dump_stats;
+ __cilkrts_end_cilk;
+ __cilkrts_enter_frame;
+ __cilkrts_enter_frame_fast;
+ __cilkrts_get_force_reduce;
+ __cilkrts_get_nworkers;
+ __cilkrts_get_tls_worker;
+ __cilkrts_get_tls_worker_fast;
+ __cilkrts_get_total_workers;
+ __cilkrts_get_worker_number;
+ __cilkrts_global_state;
+ __cilkrts_hyper_create;
+ __cilkrts_hyper_destroy;
+ __cilkrts_hyper_lookup;
+ __cilkrts_hyperobject_alloc;
+ __cilkrts_hyperobject_dealloc;
+ __cilkrts_hyperobject_noop_destroy;
+ __cilkrts_init;
+ __cilkrts_irml_version;
+ __cilkrts_leave_frame;
+ __cilkrts_metacall;
+ __cilkrts_rethrow;
+ __cilkrts_return_exception;
+ __cilkrts_set_param;
+ __cilkrts_sync;
+ __cilkrts_synched;
+ __cilkrts_worker_stub;
+ local: *;
+};
+
+CILKABI1
+{
+ global:
+ __cilkrts_bind_thread_1;
+ __cilkrts_bump_loop_rank;
+ __cilkrts_bump_loop_rank_internal;
+ __cilkrts_bump_worker_rank;
+ __cilkrts_bump_worker_rank_internal;
+ __cilkrts_enter_frame_1;
+ __cilkrts_enter_frame_fast_1;
+ __cilkrts_get_pedigree_info;
+ __cilkrts_get_pedigree_internal;
+ __cilkrts_get_sf;
+ __cilkrts_get_stack_size;
+ __cilkrts_get_worker_rank;
+ __cilkrts_save_fp_ctrl_state;
+ __cilkrts_stack_alloc;
+ __cilkrts_stack_free;
+ __cilkrts_watch_stack;
+} CILKABI0;
+
+CILKLIB1.02
+{
+ global:
+ cilk_c_reducer_max_identity_char;
+ cilk_c_reducer_max_identity_double;
+ cilk_c_reducer_max_identity_float;
+ cilk_c_reducer_max_identity_int;
+ cilk_c_reducer_max_identity_long;
+ cilk_c_reducer_max_identity_longdouble;
+ cilk_c_reducer_max_identity_longlong;
+ cilk_c_reducer_max_identity_schar;
+ cilk_c_reducer_max_identity_short;
+ cilk_c_reducer_max_identity_uchar;
+ cilk_c_reducer_max_identity_uint;
+ cilk_c_reducer_max_identity_ulong;
+ cilk_c_reducer_max_identity_ulonglong;
+ cilk_c_reducer_max_identity_unsigned;
+ cilk_c_reducer_max_identity_ushort;
+ cilk_c_reducer_max_identity_wchar_t;
+ cilk_c_reducer_max_index_identity_char;
+ cilk_c_reducer_max_index_identity_double;
+ cilk_c_reducer_max_index_identity_float;
+ cilk_c_reducer_max_index_identity_int;
+ cilk_c_reducer_max_index_identity_long;
+ cilk_c_reducer_max_index_identity_longdouble;
+ cilk_c_reducer_max_index_identity_longlong;
+ cilk_c_reducer_max_index_identity_schar;
+ cilk_c_reducer_max_index_identity_short;
+ cilk_c_reducer_max_index_identity_uchar;
+ cilk_c_reducer_max_index_identity_uint;
+ cilk_c_reducer_max_index_identity_ulong;
+ cilk_c_reducer_max_index_identity_ulonglong;
+ cilk_c_reducer_max_index_identity_unsigned;
+ cilk_c_reducer_max_index_identity_ushort;
+ cilk_c_reducer_max_index_identity_wchar_t;
+ cilk_c_reducer_max_index_reduce_char;
+ cilk_c_reducer_max_index_reduce_double;
+ cilk_c_reducer_max_index_reduce_float;
+ cilk_c_reducer_max_index_reduce_int;
+ cilk_c_reducer_max_index_reduce_long;
+ cilk_c_reducer_max_index_reduce_longdouble;
+ cilk_c_reducer_max_index_reduce_longlong;
+ cilk_c_reducer_max_index_reduce_schar;
+ cilk_c_reducer_max_index_reduce_short;
+ cilk_c_reducer_max_index_reduce_uchar;
+ cilk_c_reducer_max_index_reduce_uint;
+ cilk_c_reducer_max_index_reduce_ulong;
+ cilk_c_reducer_max_index_reduce_ulonglong;
+ cilk_c_reducer_max_index_reduce_unsigned;
+ cilk_c_reducer_max_index_reduce_ushort;
+ cilk_c_reducer_max_index_reduce_wchar_t;
+ cilk_c_reducer_max_reduce_char;
+ cilk_c_reducer_max_reduce_double;
+ cilk_c_reducer_max_reduce_float;
+ cilk_c_reducer_max_reduce_int;
+ cilk_c_reducer_max_reduce_long;
+ cilk_c_reducer_max_reduce_longdouble;
+ cilk_c_reducer_max_reduce_longlong;
+ cilk_c_reducer_max_reduce_schar;
+ cilk_c_reducer_max_reduce_short;
+ cilk_c_reducer_max_reduce_uchar;
+ cilk_c_reducer_max_reduce_uint;
+ cilk_c_reducer_max_reduce_ulong;
+ cilk_c_reducer_max_reduce_ulonglong;
+ cilk_c_reducer_max_reduce_unsigned;
+ cilk_c_reducer_max_reduce_ushort;
+ cilk_c_reducer_max_reduce_wchar_t;
+ cilk_c_reducer_min_identity_char;
+ cilk_c_reducer_min_identity_double;
+ cilk_c_reducer_min_identity_float;
+ cilk_c_reducer_min_identity_int;
+ cilk_c_reducer_min_identity_long;
+ cilk_c_reducer_min_identity_longdouble;
+ cilk_c_reducer_min_identity_longlong;
+ cilk_c_reducer_min_identity_schar;
+ cilk_c_reducer_min_identity_short;
+ cilk_c_reducer_min_identity_uchar;
+ cilk_c_reducer_min_identity_uint;
+ cilk_c_reducer_min_identity_ulong;
+ cilk_c_reducer_min_identity_ulonglong;
+ cilk_c_reducer_min_identity_unsigned;
+ cilk_c_reducer_min_identity_ushort;
+ cilk_c_reducer_min_identity_wchar_t;
+ cilk_c_reducer_min_index_identity_char;
+ cilk_c_reducer_min_index_identity_double;
+ cilk_c_reducer_min_index_identity_float;
+ cilk_c_reducer_min_index_identity_int;
+ cilk_c_reducer_min_index_identity_long;
+ cilk_c_reducer_min_index_identity_longdouble;
+ cilk_c_reducer_min_index_identity_longlong;
+ cilk_c_reducer_min_index_identity_schar;
+ cilk_c_reducer_min_index_identity_short;
+ cilk_c_reducer_min_index_identity_uchar;
+ cilk_c_reducer_min_index_identity_uint;
+ cilk_c_reducer_min_index_identity_ulong;
+ cilk_c_reducer_min_index_identity_ulonglong;
+ cilk_c_reducer_min_index_identity_unsigned;
+ cilk_c_reducer_min_index_identity_ushort;
+ cilk_c_reducer_min_index_identity_wchar_t;
+ cilk_c_reducer_min_index_reduce_char;
+ cilk_c_reducer_min_index_reduce_double;
+ cilk_c_reducer_min_index_reduce_float;
+ cilk_c_reducer_min_index_reduce_int;
+ cilk_c_reducer_min_index_reduce_long;
+ cilk_c_reducer_min_index_reduce_longdouble;
+ cilk_c_reducer_min_index_reduce_longlong;
+ cilk_c_reducer_min_index_reduce_schar;
+ cilk_c_reducer_min_index_reduce_short;
+ cilk_c_reducer_min_index_reduce_uchar;
+ cilk_c_reducer_min_index_reduce_uint;
+ cilk_c_reducer_min_index_reduce_ulong;
+ cilk_c_reducer_min_index_reduce_ulonglong;
+ cilk_c_reducer_min_index_reduce_unsigned;
+ cilk_c_reducer_min_index_reduce_ushort;
+ cilk_c_reducer_min_index_reduce_wchar_t;
+ cilk_c_reducer_min_reduce_char;
+ cilk_c_reducer_min_reduce_double;
+ cilk_c_reducer_min_reduce_float;
+ cilk_c_reducer_min_reduce_int;
+ cilk_c_reducer_min_reduce_long;
+ cilk_c_reducer_min_reduce_longdouble;
+ cilk_c_reducer_min_reduce_longlong;
+ cilk_c_reducer_min_reduce_schar;
+ cilk_c_reducer_min_reduce_short;
+ cilk_c_reducer_min_reduce_uchar;
+ cilk_c_reducer_min_reduce_uint;
+ cilk_c_reducer_min_reduce_ulong;
+ cilk_c_reducer_min_reduce_ulonglong;
+ cilk_c_reducer_min_reduce_unsigned;
+ cilk_c_reducer_min_reduce_ushort;
+ cilk_c_reducer_min_reduce_wchar_t;
+ cilk_c_reducer_opadd_identity_char;
+ cilk_c_reducer_opadd_identity_double;
+ cilk_c_reducer_opadd_identity_float;
+ cilk_c_reducer_opadd_identity_int;
+ cilk_c_reducer_opadd_identity_long;
+ cilk_c_reducer_opadd_identity_longdouble;
+ cilk_c_reducer_opadd_identity_longlong;
+ cilk_c_reducer_opadd_identity_schar;
+ cilk_c_reducer_opadd_identity_short;
+ cilk_c_reducer_opadd_identity_uchar;
+ cilk_c_reducer_opadd_identity_uint;
+ cilk_c_reducer_opadd_identity_ulong;
+ cilk_c_reducer_opadd_identity_ulonglong;
+ cilk_c_reducer_opadd_identity_unsigned;
+ cilk_c_reducer_opadd_identity_ushort;
+ cilk_c_reducer_opadd_identity_wchar_t;
+ cilk_c_reducer_opadd_reduce_char;
+ cilk_c_reducer_opadd_reduce_double;
+ cilk_c_reducer_opadd_reduce_float;
+ cilk_c_reducer_opadd_reduce_int;
+ cilk_c_reducer_opadd_reduce_long;
+ cilk_c_reducer_opadd_reduce_longdouble;
+ cilk_c_reducer_opadd_reduce_longlong;
+ cilk_c_reducer_opadd_reduce_schar;
+ cilk_c_reducer_opadd_reduce_short;
+ cilk_c_reducer_opadd_reduce_uchar;
+ cilk_c_reducer_opadd_reduce_uint;
+ cilk_c_reducer_opadd_reduce_ulong;
+ cilk_c_reducer_opadd_reduce_ulonglong;
+ cilk_c_reducer_opadd_reduce_unsigned;
+ cilk_c_reducer_opadd_reduce_ushort;
+ cilk_c_reducer_opadd_reduce_wchar_t;
+ cilk_c_reducer_opand_identity_char;
+ cilk_c_reducer_opand_identity_int;
+ cilk_c_reducer_opand_identity_long;
+ cilk_c_reducer_opand_identity_longlong;
+ cilk_c_reducer_opand_identity_schar;
+ cilk_c_reducer_opand_identity_short;
+ cilk_c_reducer_opand_identity_uchar;
+ cilk_c_reducer_opand_identity_uint;
+ cilk_c_reducer_opand_identity_ulong;
+ cilk_c_reducer_opand_identity_ulonglong;
+ cilk_c_reducer_opand_identity_unsigned;
+ cilk_c_reducer_opand_identity_ushort;
+ cilk_c_reducer_opand_identity_wchar_t;
+ cilk_c_reducer_opand_reduce_char;
+ cilk_c_reducer_opand_reduce_int;
+ cilk_c_reducer_opand_reduce_long;
+ cilk_c_reducer_opand_reduce_longlong;
+ cilk_c_reducer_opand_reduce_schar;
+ cilk_c_reducer_opand_reduce_short;
+ cilk_c_reducer_opand_reduce_uchar;
+ cilk_c_reducer_opand_reduce_uint;
+ cilk_c_reducer_opand_reduce_ulong;
+ cilk_c_reducer_opand_reduce_ulonglong;
+ cilk_c_reducer_opand_reduce_unsigned;
+ cilk_c_reducer_opand_reduce_ushort;
+ cilk_c_reducer_opand_reduce_wchar_t;
+ cilk_c_reducer_opmul_identity_char;
+ cilk_c_reducer_opmul_identity_double;
+ cilk_c_reducer_opmul_identity_float;
+ cilk_c_reducer_opmul_identity_int;
+ cilk_c_reducer_opmul_identity_long;
+ cilk_c_reducer_opmul_identity_longdouble;
+ cilk_c_reducer_opmul_identity_longlong;
+ cilk_c_reducer_opmul_identity_schar;
+ cilk_c_reducer_opmul_identity_short;
+ cilk_c_reducer_opmul_identity_uchar;
+ cilk_c_reducer_opmul_identity_uint;
+ cilk_c_reducer_opmul_identity_ulong;
+ cilk_c_reducer_opmul_identity_ulonglong;
+ cilk_c_reducer_opmul_identity_unsigned;
+ cilk_c_reducer_opmul_identity_ushort;
+ cilk_c_reducer_opmul_identity_wchar_t;
+ cilk_c_reducer_opmul_reduce_char;
+ cilk_c_reducer_opmul_reduce_double;
+ cilk_c_reducer_opmul_reduce_float;
+ cilk_c_reducer_opmul_reduce_int;
+ cilk_c_reducer_opmul_reduce_long;
+ cilk_c_reducer_opmul_reduce_longdouble;
+ cilk_c_reducer_opmul_reduce_longlong;
+ cilk_c_reducer_opmul_reduce_schar;
+ cilk_c_reducer_opmul_reduce_short;
+ cilk_c_reducer_opmul_reduce_uchar;
+ cilk_c_reducer_opmul_reduce_uint;
+ cilk_c_reducer_opmul_reduce_ulong;
+ cilk_c_reducer_opmul_reduce_ulonglong;
+ cilk_c_reducer_opmul_reduce_unsigned;
+ cilk_c_reducer_opmul_reduce_ushort;
+ cilk_c_reducer_opmul_reduce_wchar_t;
+ cilk_c_reducer_opor_identity_char;
+ cilk_c_reducer_opor_identity_int;
+ cilk_c_reducer_opor_identity_long;
+ cilk_c_reducer_opor_identity_longlong;
+ cilk_c_reducer_opor_identity_schar;
+ cilk_c_reducer_opor_identity_short;
+ cilk_c_reducer_opor_identity_uchar;
+ cilk_c_reducer_opor_identity_uint;
+ cilk_c_reducer_opor_identity_ulong;
+ cilk_c_reducer_opor_identity_ulonglong;
+ cilk_c_reducer_opor_identity_unsigned;
+ cilk_c_reducer_opor_identity_ushort;
+ cilk_c_reducer_opor_identity_wchar_t;
+ cilk_c_reducer_opor_reduce_char;
+ cilk_c_reducer_opor_reduce_int;
+ cilk_c_reducer_opor_reduce_long;
+ cilk_c_reducer_opor_reduce_longlong;
+ cilk_c_reducer_opor_reduce_schar;
+ cilk_c_reducer_opor_reduce_short;
+ cilk_c_reducer_opor_reduce_uchar;
+ cilk_c_reducer_opor_reduce_uint;
+ cilk_c_reducer_opor_reduce_ulong;
+ cilk_c_reducer_opor_reduce_ulonglong;
+ cilk_c_reducer_opor_reduce_unsigned;
+ cilk_c_reducer_opor_reduce_ushort;
+ cilk_c_reducer_opor_reduce_wchar_t;
+ cilk_c_reducer_opxor_identity_char;
+ cilk_c_reducer_opxor_identity_int;
+ cilk_c_reducer_opxor_identity_long;
+ cilk_c_reducer_opxor_identity_longlong;
+ cilk_c_reducer_opxor_identity_schar;
+ cilk_c_reducer_opxor_identity_short;
+ cilk_c_reducer_opxor_identity_uchar;
+ cilk_c_reducer_opxor_identity_uint;
+ cilk_c_reducer_opxor_identity_ulong;
+ cilk_c_reducer_opxor_identity_ulonglong;
+ cilk_c_reducer_opxor_identity_unsigned;
+ cilk_c_reducer_opxor_identity_ushort;
+ cilk_c_reducer_opxor_identity_wchar_t;
+ cilk_c_reducer_opxor_reduce_char;
+ cilk_c_reducer_opxor_reduce_int;
+ cilk_c_reducer_opxor_reduce_long;
+ cilk_c_reducer_opxor_reduce_longlong;
+ cilk_c_reducer_opxor_reduce_schar;
+ cilk_c_reducer_opxor_reduce_short;
+ cilk_c_reducer_opxor_reduce_uchar;
+ cilk_c_reducer_opxor_reduce_uint;
+ cilk_c_reducer_opxor_reduce_ulong;
+ cilk_c_reducer_opxor_reduce_ulonglong;
+ cilk_c_reducer_opxor_reduce_unsigned;
+ cilk_c_reducer_opxor_reduce_ushort;
+ cilk_c_reducer_opxor_reduce_wchar_t;
+};
diff --git a/libcilkrts/runtime/local_state.c b/libcilkrts/runtime/local_state.c
new file mode 100644
index 00000000000..14ac8271936
--- /dev/null
+++ b/libcilkrts/runtime/local_state.c
@@ -0,0 +1,68 @@
+/* local_state.c -*-C++-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2010-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ **************************************************************************/
+
+#include "local_state.h"
+#include "bug.h"
+#include "full_frame.h"
+
+void run_scheduling_stack_fcn(__cilkrts_worker *w)
+{
+ scheduling_stack_fcn_t fcn = w->l->post_suspend;
+ full_frame *ff2 = w->l->frame_ff;
+ __cilkrts_stack_frame *sf2 = w->l->suspended_stack;
+
+ w->l->post_suspend = 0;
+ w->l->suspended_stack = 0;
+
+ // Conceptually, after clearing w->l->frame_ff,
+ // w no longer owns the full frame ff.
+ // The next time another (possibly different) worker takes
+ // ownership of ff will be at a provably_good_steal on ff.
+ w->l->frame_ff = NULL;
+
+ CILK_ASSERT(fcn);
+ CILK_ASSERT(ff2);
+ fcn(w, ff2, sf2);
+
+ // After we run the scheduling stack function, we shouldn't
+ // (still) not have a full frame.
+ CILK_ASSERT(NULL == w->l->frame_ff);
+}
+
+/* End local_state.c */
diff --git a/libcilkrts/runtime/local_state.h b/libcilkrts/runtime/local_state.h
new file mode 100644
index 00000000000..03f39897f51
--- /dev/null
+++ b/libcilkrts/runtime/local_state.h
@@ -0,0 +1,424 @@
+/* local_state.h -*-C++-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ **************************************************************************/
+
+/**
+ * @file local_state.h
+ *
+ * @brief The local_state structure contains additional OS-independent
+ * information that's associated with a worker, but doesn't need to be visible
+ * to the code generated by the compiler.
+ */
+
+#ifndef INCLUDED_LOCAL_STATE_DOT_H
+#define INCLUDED_LOCAL_STATE_DOT_H
+
+#include <internal/abi.h>
+#include "worker_mutex.h"
+#include "global_state.h"
+#include "record-replay.h"
+#include "signal_node.h"
+
+#include <setjmp.h>
+#include <stddef.h>
+#include <stdio.h>
+
+
+#ifndef _WIN32
+# include <pthread.h>
+#endif
+
+__CILKRTS_BEGIN_EXTERN_C
+
+/* Opaque types. */
+
+struct full_frame;
+struct free_list;
+struct pending_exception_info;
+/// Opaque type for replay entry.
+typedef struct replay_entry_t replay_entry_t;
+
+/**
+ * @brief Magic numbers for local_state, used for debugging
+ */
+typedef unsigned long long ls_magic_t;
+
+/**
+ * @brief Scheduling stack function: A function that is decided on the program stack,
+ * but that must be executed on the scheduling stack.
+ */
+typedef void (*scheduling_stack_fcn_t) (__cilkrts_worker *w,
+ struct full_frame *ff,
+ __cilkrts_stack_frame *sf);
+
+/**
+ * @brief Type of this worker.
+ **/
+typedef enum cilk_worker_type
+{
+ WORKER_FREE, ///< Unused worker - available to be bound to user threads
+ WORKER_SYSTEM, ///< Worker created by runtime - able to steal from any worker
+ WORKER_USER ///< User thread - able to steal only from team members
+} cilk_worker_type;
+
+
+/**
+ * @brief The local_state structure contains additional OS-independent
+ * information that's associated with a worker, but doesn't need to be
+ * visible to the compiler.
+ *
+ * No compiler-generated code should need to know the layout of this
+ * structure.
+ *
+ * The fields of this struct can be classified as either local or
+ * shared.
+ *
+ * Local: This field is only accessed by the thread bound to this
+ * worker struct. Local fields can be freely accessed without
+ * acquiring locks.
+ *
+ * Shared: This field may be accessed by multiple worker threads.
+ * Accesses to shared fields usually requires locks, except in
+ * special situations where one can prove that locks are
+ * unnecessary.
+ *
+ * The fields of this can also be classified as "read-only" if the
+ * field does not change after it is initialized. Otherwise, the
+ * field is "read/write". Read-only fields do not require locks to
+ * access (ignoring the synchronization that might be needed for
+ * initialization if this can occur in parallel).
+ *
+ * Finally, we explicitly classify some fields as "synchronization"
+ * fields if they are used as part of a synchronization protocol in
+ * the runtime. These variables are generally shared and read/write.
+ * Mostly, this category includes lock variables and other variables
+ * that are involved in synchronization protocols (i.e., the THE
+ * protocol).
+ */
+struct local_state /* COMMON_PORTABLE */
+{
+ /** This value should be in the first field in any local_state */
+# define WORKER_MAGIC_0 ((ls_magic_t)0xe0831a4a940c60b8ULL)
+
+ /**
+ * Should be WORKER_MAGIC_0 or the local_state has been corrupted
+ * This magic field is shared because it is read on lock acquisitions.
+ *
+ * [shared read-only]
+ */
+ ls_magic_t worker_magic_0;
+
+ /**
+ * Mutex used to serialize access to the local_state
+ * Synchronization field. [shared read/write]
+ */
+ struct mutex lock;
+
+ /**
+ * Flag that indicates that the worker is interested in grabbing
+ * LOCK, and thus thieves should leave the worker alone.
+ * Written only by self, may be read by others.
+ *
+ * Synchronization field. [shared read/write]
+ */
+ int do_not_steal;
+
+ /**
+ * Lock that all thieves grab in order to compete for the right
+ * to disturb this worker.
+ *
+ * Synchronization field. [shared read/write]
+ */
+ struct mutex steal_lock;
+
+ /**
+ * Full frame that the worker is working on.
+ *
+ * While a worker w is executing, a thief may change
+ * w->l->frame_ff (on a successful steal) after acquiring w's
+ * lock.
+ *
+ * Unlocked accesses to w->l->frame_ff are safe (by w itself) when
+ * w's deque is empty, or when stealing from w has been disabled.
+ *
+ * [shared read/write]
+ */
+ struct full_frame *frame_ff;
+
+ /**
+ * Full frame that the worker will be working on next
+ *
+ * This field is normally local for a worker w. Another worker v
+ * may modify w->l->next_frame_ff, however, in the special case
+ * when v is returning a frame to a user thread w since w is the
+ * team leader.
+ *
+ * [shared read/write]
+ */
+ struct full_frame *next_frame_ff;
+
+ /**
+ * This is set iff this is a WORKER_USER and there has been a steal. It
+ * points to the first frame that was stolen since the team was last fully
+ * sync'd. Only this worker may continue past a sync in this function.
+ *
+ * This field is set by a thief for a victim that is a user
+ * thread, while holding the victim's lock.
+ * It can be cleared without a lock by the worker that will
+ * continue exuecting past the sync.
+ *
+ * [shared read/write]
+ */
+ struct full_frame *last_full_frame;
+
+ /**
+ * Team on which this worker is a participant. When a user worker enters,
+ * its team is its own worker struct and it can never change teams. When a
+ * system worker steals, it adopts the team of its victim.
+ *
+ * When a system worker w steals, it reads victim->l->team and
+ * joins this team. w->l->team is constant until the next time w
+ * returns control to the runtime.
+ * We must acquire the worker lock to change w->l->team.
+ *
+ * @note This field is 64-byte aligned because it is the first in
+ * the group of shared read-only fields. We want this group to
+ * fall on a different cache line from the previous group, which
+ * is shared read-write.
+ *
+ * [shared read-only]
+ */
+ __attribute__((aligned(64)))
+ __cilkrts_worker *team;
+
+ /**
+ * Type of this worker
+ *
+ * This field changes only when a worker binds or unbinds.
+ * Otherwise, the field is read-only while the worker is bound.
+ *
+ * [shared read-only]
+ */
+ cilk_worker_type type;
+
+ /**
+ * Lazy task queue of this worker - an array of pointers to stack frames.
+ *
+ * Read-only because deques are a fixed size in the current
+ * implementation.
+ *
+ * @note This field is 64-byte aligned because it is the first in
+ * the group of local fields. We want this group to fall on a
+ * different cache line from the previous group, which is shared
+ * read-only.
+ *
+ * [local read-only]
+ */
+ __attribute__((aligned(64)))
+ __cilkrts_stack_frame **ltq;
+
+ /**
+ * Pool of fibers waiting to be reused.
+ * [local read/write]
+ */
+ cilk_fiber_pool fiber_pool;
+
+ /**
+ * The fiber for the scheduling stacks.
+ * [local read/write]
+ */
+ cilk_fiber* scheduling_fiber;
+
+ /**
+ * Saved pointer to the leaf node in thread-local storage, when a
+ * user thread is imported. This pointer gets set to a
+ * meaningful value when binding a user thread, and cleared on
+ * unbind.
+ *
+ * [local read/write]
+ */
+ __cilkrts_pedigree* original_pedigree_leaf;
+
+ /**
+ * State of the random number generator
+ *
+ * [local read/write]
+ */
+ unsigned rand_seed;
+
+ /**
+ * Function to execute after transferring onto the scheduling stack.
+ *
+ * [local read/write]
+ */
+ scheduling_stack_fcn_t post_suspend;
+
+ /**
+ * __cilkrts_stack_frame we suspended when we transferred onto the
+ * scheduling stack.
+ *
+ * [local read/write]
+ */
+ __cilkrts_stack_frame *suspended_stack;
+
+ /**
+ * cilk_fiber that should be freed after returning from a
+ * spawn with a stolen parent or after stalling at a sync.
+
+ * We calculate the stack to free when executing a reduction on
+ * the user stack, but we can not actually release the stack
+ * until control longjmps onto a runtime scheduling stack.
+ *
+ * This field is used to pass information to the runtime across
+ * the longjmp onto the scheduling stack.
+ *
+ * [local read/write]
+ */
+ cilk_fiber* fiber_to_free;
+
+ /**
+ * Saved exception object for an exception that is being passed to
+ * our parent
+ *
+ * [local read/write]
+ */
+ struct pending_exception_info *pending_exception;
+
+ /**
+ * Buckets for the memory allocator
+ *
+ * [local read/write]
+ */
+ struct free_list *free_list[FRAME_MALLOC_NBUCKETS];
+
+ /**
+ * Potential function for the memory allocator
+ *
+ * [local read/write]
+ */
+ size_t bucket_potential[FRAME_MALLOC_NBUCKETS];
+
+ /**
+ * Support for statistics
+ *
+ * Useful only when CILK_PROFIlE is compiled in.
+ * [local read/write]
+ */
+ statistics* stats;
+
+ /**
+ * Count indicates number of failures since last successful steal. This is
+ * used by the scheduler to reduce contention on shared flags.
+ *
+ * [local read/write]
+ */
+ unsigned int steal_failure_count;
+
+ /**
+ * 1 if work was stolen from another worker. When true, this will flag
+ * setup_for_execution_pedigree to increment the pedigree when we resume
+ * execution to match the increment that would have been done on a return
+ * from a spawn helper.
+ *
+ * [local read/write]
+ */
+ int work_stolen;
+
+ /**
+ * File pointer for record or replay
+ * Does FILE * work on Windows?
+ * During record, the file will be opened in write-only mode.
+ * During replay, the file will be opened in read-only mode.
+ *
+ * [local read/write]
+ */
+ FILE *record_replay_fptr;
+
+ /**
+ * Root of array of replay entries - NULL if we're not replaying a log
+ *
+ * [local read/write]
+ */
+ replay_entry_t *replay_list_root;
+
+ /**
+ * Current replay entry - NULL if we're not replaying a log
+ *
+ * [local read/write]
+ */
+ replay_entry_t *replay_list_entry;
+
+ /**
+ * Separate the signal_node from other things in the local_state by the
+ * sizeof a cache line for performance reasons.
+ *
+ * unused
+ */
+ char buf[64];
+
+ /**
+ * Signal object for waking/sleeping the worker. This should be a pointer
+ * to avoid the possibility of caching problems.
+ *
+ * [shared read-only]
+ */
+ signal_node_t *signal_node;
+
+ /** This value should be in the last field in any local_state */
+# define WORKER_MAGIC_1 ((ls_magic_t)0x16164afb0ea0dff9ULL)
+
+ /**
+ * Should be WORKER_MAGIC_1 or the local_state has been corrupted
+ * This magic field is shared because it is read on lock acquisitions.
+ * [shared read-only]
+ */
+ ls_magic_t worker_magic_1;
+};
+
+/**
+ * Perform cleanup according to the function set before the longjmp().
+ *
+ * Call this after longjmp() has completed and the worker is back on a
+ * scheduling stack.
+ *
+ * @param w __cilkrts_worker currently executing.
+ */
+void run_scheduling_stack_fcn(__cilkrts_worker *w);
+
+__CILKRTS_END_EXTERN_C
+
+#endif // ! defined(INCLUDED_LOCAL_STATE_DOT_H)
diff --git a/libcilkrts/runtime/mac-symbols.txt b/libcilkrts/runtime/mac-symbols.txt
new file mode 100644
index 00000000000..38d83a8675d
--- /dev/null
+++ b/libcilkrts/runtime/mac-symbols.txt
@@ -0,0 +1,318 @@
+# Exported symbol list:
+___cilkrts_bind_thread
+___cilkrts_bind_thread_1
+___cilkrts_bump_loop_rank
+___cilkrts_bump_loop_rank_internal
+___cilkrts_bump_worker_rank
+___cilkrts_bump_worker_rank_internal
+___cilkrts_cilk_for_32
+___cilkrts_cilk_for_64
+___cilkrts_debugger_notification
+___cilkrts_dump_stats
+___cilkrts_end_cilk
+___cilkrts_enter_frame
+___cilkrts_enter_frame_1
+___cilkrts_enter_frame_fast
+___cilkrts_enter_frame_fast_1
+___cilkrts_get_force_reduce
+___cilkrts_get_nworkers
+___cilkrts_get_pedigree_info
+___cilkrts_get_pedigree_internal
+___cilkrts_get_sf
+___cilkrts_get_stack_size
+___cilkrts_get_tls_worker
+___cilkrts_get_tls_worker_fast
+___cilkrts_get_total_workers
+___cilkrts_get_worker_number
+___cilkrts_get_worker_rank
+___cilkrts_global_state
+___cilkrts_hyper_create
+___cilkrts_hyper_destroy
+___cilkrts_hyper_lookup
+___cilkrts_hyperobject_alloc
+___cilkrts_hyperobject_dealloc
+___cilkrts_hyperobject_noop_destroy
+___cilkrts_init
+___cilkrts_irml_version
+___cilkrts_leave_frame
+___cilkrts_metacall
+___cilkrts_rethrow
+___cilkrts_return_exception
+___cilkrts_save_fp_ctrl_state
+___cilkrts_set_param
+___cilkrts_stack_alloc
+___cilkrts_stack_free
+___cilkrts_sync
+___cilkrts_synched
+___cilkrts_watch_stack
+___cilkrts_worker_stub
+_cilk_c_reducer_max_identity_char
+_cilk_c_reducer_max_identity_double
+_cilk_c_reducer_max_identity_float
+_cilk_c_reducer_max_identity_int
+_cilk_c_reducer_max_identity_long
+_cilk_c_reducer_max_identity_longdouble
+_cilk_c_reducer_max_identity_longlong
+_cilk_c_reducer_max_identity_schar
+_cilk_c_reducer_max_identity_short
+_cilk_c_reducer_max_identity_uchar
+_cilk_c_reducer_max_identity_uint
+_cilk_c_reducer_max_identity_ulong
+_cilk_c_reducer_max_identity_ulonglong
+_cilk_c_reducer_max_identity_unsigned
+_cilk_c_reducer_max_identity_ushort
+_cilk_c_reducer_max_identity_wchar_t
+_cilk_c_reducer_max_index_identity_char
+_cilk_c_reducer_max_index_identity_double
+_cilk_c_reducer_max_index_identity_float
+_cilk_c_reducer_max_index_identity_int
+_cilk_c_reducer_max_index_identity_long
+_cilk_c_reducer_max_index_identity_longdouble
+_cilk_c_reducer_max_index_identity_longlong
+_cilk_c_reducer_max_index_identity_schar
+_cilk_c_reducer_max_index_identity_short
+_cilk_c_reducer_max_index_identity_uchar
+_cilk_c_reducer_max_index_identity_uint
+_cilk_c_reducer_max_index_identity_ulong
+_cilk_c_reducer_max_index_identity_ulonglong
+_cilk_c_reducer_max_index_identity_unsigned
+_cilk_c_reducer_max_index_identity_ushort
+_cilk_c_reducer_max_index_identity_wchar_t
+_cilk_c_reducer_max_index_reduce_char
+_cilk_c_reducer_max_index_reduce_double
+_cilk_c_reducer_max_index_reduce_float
+_cilk_c_reducer_max_index_reduce_int
+_cilk_c_reducer_max_index_reduce_long
+_cilk_c_reducer_max_index_reduce_longdouble
+_cilk_c_reducer_max_index_reduce_longlong
+_cilk_c_reducer_max_index_reduce_schar
+_cilk_c_reducer_max_index_reduce_short
+_cilk_c_reducer_max_index_reduce_uchar
+_cilk_c_reducer_max_index_reduce_uint
+_cilk_c_reducer_max_index_reduce_ulong
+_cilk_c_reducer_max_index_reduce_ulonglong
+_cilk_c_reducer_max_index_reduce_unsigned
+_cilk_c_reducer_max_index_reduce_ushort
+_cilk_c_reducer_max_index_reduce_wchar_t
+_cilk_c_reducer_max_reduce_char
+_cilk_c_reducer_max_reduce_double
+_cilk_c_reducer_max_reduce_float
+_cilk_c_reducer_max_reduce_int
+_cilk_c_reducer_max_reduce_long
+_cilk_c_reducer_max_reduce_longdouble
+_cilk_c_reducer_max_reduce_longlong
+_cilk_c_reducer_max_reduce_schar
+_cilk_c_reducer_max_reduce_short
+_cilk_c_reducer_max_reduce_uchar
+_cilk_c_reducer_max_reduce_uint
+_cilk_c_reducer_max_reduce_ulong
+_cilk_c_reducer_max_reduce_ulonglong
+_cilk_c_reducer_max_reduce_unsigned
+_cilk_c_reducer_max_reduce_ushort
+_cilk_c_reducer_max_reduce_wchar_t
+_cilk_c_reducer_min_identity_char
+_cilk_c_reducer_min_identity_double
+_cilk_c_reducer_min_identity_float
+_cilk_c_reducer_min_identity_int
+_cilk_c_reducer_min_identity_long
+_cilk_c_reducer_min_identity_longdouble
+_cilk_c_reducer_min_identity_longlong
+_cilk_c_reducer_min_identity_schar
+_cilk_c_reducer_min_identity_short
+_cilk_c_reducer_min_identity_uchar
+_cilk_c_reducer_min_identity_uint
+_cilk_c_reducer_min_identity_ulong
+_cilk_c_reducer_min_identity_ulonglong
+_cilk_c_reducer_min_identity_unsigned
+_cilk_c_reducer_min_identity_ushort
+_cilk_c_reducer_min_identity_wchar_t
+_cilk_c_reducer_min_index_identity_char
+_cilk_c_reducer_min_index_identity_double
+_cilk_c_reducer_min_index_identity_float
+_cilk_c_reducer_min_index_identity_int
+_cilk_c_reducer_min_index_identity_long
+_cilk_c_reducer_min_index_identity_longdouble
+_cilk_c_reducer_min_index_identity_longlong
+_cilk_c_reducer_min_index_identity_schar
+_cilk_c_reducer_min_index_identity_short
+_cilk_c_reducer_min_index_identity_uchar
+_cilk_c_reducer_min_index_identity_uint
+_cilk_c_reducer_min_index_identity_ulong
+_cilk_c_reducer_min_index_identity_ulonglong
+_cilk_c_reducer_min_index_identity_unsigned
+_cilk_c_reducer_min_index_identity_ushort
+_cilk_c_reducer_min_index_identity_wchar_t
+_cilk_c_reducer_min_index_reduce_char
+_cilk_c_reducer_min_index_reduce_double
+_cilk_c_reducer_min_index_reduce_float
+_cilk_c_reducer_min_index_reduce_int
+_cilk_c_reducer_min_index_reduce_long
+_cilk_c_reducer_min_index_reduce_longdouble
+_cilk_c_reducer_min_index_reduce_longlong
+_cilk_c_reducer_min_index_reduce_schar
+_cilk_c_reducer_min_index_reduce_short
+_cilk_c_reducer_min_index_reduce_uchar
+_cilk_c_reducer_min_index_reduce_uint
+_cilk_c_reducer_min_index_reduce_ulong
+_cilk_c_reducer_min_index_reduce_ulonglong
+_cilk_c_reducer_min_index_reduce_unsigned
+_cilk_c_reducer_min_index_reduce_ushort
+_cilk_c_reducer_min_index_reduce_wchar_t
+_cilk_c_reducer_min_reduce_char
+_cilk_c_reducer_min_reduce_double
+_cilk_c_reducer_min_reduce_float
+_cilk_c_reducer_min_reduce_int
+_cilk_c_reducer_min_reduce_long
+_cilk_c_reducer_min_reduce_longdouble
+_cilk_c_reducer_min_reduce_longlong
+_cilk_c_reducer_min_reduce_schar
+_cilk_c_reducer_min_reduce_short
+_cilk_c_reducer_min_reduce_uchar
+_cilk_c_reducer_min_reduce_uint
+_cilk_c_reducer_min_reduce_ulong
+_cilk_c_reducer_min_reduce_ulonglong
+_cilk_c_reducer_min_reduce_unsigned
+_cilk_c_reducer_min_reduce_ushort
+_cilk_c_reducer_min_reduce_wchar_t
+_cilk_c_reducer_opadd_identity_char
+_cilk_c_reducer_opadd_identity_double
+_cilk_c_reducer_opadd_identity_float
+_cilk_c_reducer_opadd_identity_int
+_cilk_c_reducer_opadd_identity_long
+_cilk_c_reducer_opadd_identity_longdouble
+_cilk_c_reducer_opadd_identity_longlong
+_cilk_c_reducer_opadd_identity_schar
+_cilk_c_reducer_opadd_identity_short
+_cilk_c_reducer_opadd_identity_uchar
+_cilk_c_reducer_opadd_identity_uint
+_cilk_c_reducer_opadd_identity_ulong
+_cilk_c_reducer_opadd_identity_ulonglong
+_cilk_c_reducer_opadd_identity_unsigned
+_cilk_c_reducer_opadd_identity_ushort
+_cilk_c_reducer_opadd_identity_wchar_t
+_cilk_c_reducer_opadd_reduce_char
+_cilk_c_reducer_opadd_reduce_double
+_cilk_c_reducer_opadd_reduce_float
+_cilk_c_reducer_opadd_reduce_int
+_cilk_c_reducer_opadd_reduce_long
+_cilk_c_reducer_opadd_reduce_longdouble
+_cilk_c_reducer_opadd_reduce_longlong
+_cilk_c_reducer_opadd_reduce_schar
+_cilk_c_reducer_opadd_reduce_short
+_cilk_c_reducer_opadd_reduce_uchar
+_cilk_c_reducer_opadd_reduce_uint
+_cilk_c_reducer_opadd_reduce_ulong
+_cilk_c_reducer_opadd_reduce_ulonglong
+_cilk_c_reducer_opadd_reduce_unsigned
+_cilk_c_reducer_opadd_reduce_ushort
+_cilk_c_reducer_opadd_reduce_wchar_t
+_cilk_c_reducer_opand_identity_char
+_cilk_c_reducer_opand_identity_int
+_cilk_c_reducer_opand_identity_long
+_cilk_c_reducer_opand_identity_longlong
+_cilk_c_reducer_opand_identity_schar
+_cilk_c_reducer_opand_identity_short
+_cilk_c_reducer_opand_identity_uchar
+_cilk_c_reducer_opand_identity_uint
+_cilk_c_reducer_opand_identity_ulong
+_cilk_c_reducer_opand_identity_ulonglong
+_cilk_c_reducer_opand_identity_unsigned
+_cilk_c_reducer_opand_identity_ushort
+_cilk_c_reducer_opand_identity_wchar_t
+_cilk_c_reducer_opand_reduce_char
+_cilk_c_reducer_opand_reduce_int
+_cilk_c_reducer_opand_reduce_long
+_cilk_c_reducer_opand_reduce_longlong
+_cilk_c_reducer_opand_reduce_schar
+_cilk_c_reducer_opand_reduce_short
+_cilk_c_reducer_opand_reduce_uchar
+_cilk_c_reducer_opand_reduce_uint
+_cilk_c_reducer_opand_reduce_ulong
+_cilk_c_reducer_opand_reduce_ulonglong
+_cilk_c_reducer_opand_reduce_unsigned
+_cilk_c_reducer_opand_reduce_ushort
+_cilk_c_reducer_opand_reduce_wchar_t
+_cilk_c_reducer_opmul_identity_char
+_cilk_c_reducer_opmul_identity_double
+_cilk_c_reducer_opmul_identity_float
+_cilk_c_reducer_opmul_identity_int
+_cilk_c_reducer_opmul_identity_long
+_cilk_c_reducer_opmul_identity_longdouble
+_cilk_c_reducer_opmul_identity_longlong
+_cilk_c_reducer_opmul_identity_schar
+_cilk_c_reducer_opmul_identity_short
+_cilk_c_reducer_opmul_identity_uchar
+_cilk_c_reducer_opmul_identity_uint
+_cilk_c_reducer_opmul_identity_ulong
+_cilk_c_reducer_opmul_identity_ulonglong
+_cilk_c_reducer_opmul_identity_unsigned
+_cilk_c_reducer_opmul_identity_ushort
+_cilk_c_reducer_opmul_identity_wchar_t
+_cilk_c_reducer_opmul_reduce_char
+_cilk_c_reducer_opmul_reduce_double
+_cilk_c_reducer_opmul_reduce_float
+_cilk_c_reducer_opmul_reduce_int
+_cilk_c_reducer_opmul_reduce_long
+_cilk_c_reducer_opmul_reduce_longdouble
+_cilk_c_reducer_opmul_reduce_longlong
+_cilk_c_reducer_opmul_reduce_schar
+_cilk_c_reducer_opmul_reduce_short
+_cilk_c_reducer_opmul_reduce_uchar
+_cilk_c_reducer_opmul_reduce_uint
+_cilk_c_reducer_opmul_reduce_ulong
+_cilk_c_reducer_opmul_reduce_ulonglong
+_cilk_c_reducer_opmul_reduce_unsigned
+_cilk_c_reducer_opmul_reduce_ushort
+_cilk_c_reducer_opmul_reduce_wchar_t
+_cilk_c_reducer_opor_identity_char
+_cilk_c_reducer_opor_identity_int
+_cilk_c_reducer_opor_identity_long
+_cilk_c_reducer_opor_identity_longlong
+_cilk_c_reducer_opor_identity_schar
+_cilk_c_reducer_opor_identity_short
+_cilk_c_reducer_opor_identity_uchar
+_cilk_c_reducer_opor_identity_uint
+_cilk_c_reducer_opor_identity_ulong
+_cilk_c_reducer_opor_identity_ulonglong
+_cilk_c_reducer_opor_identity_unsigned
+_cilk_c_reducer_opor_identity_ushort
+_cilk_c_reducer_opor_identity_wchar_t
+_cilk_c_reducer_opor_reduce_char
+_cilk_c_reducer_opor_reduce_int
+_cilk_c_reducer_opor_reduce_long
+_cilk_c_reducer_opor_reduce_longlong
+_cilk_c_reducer_opor_reduce_schar
+_cilk_c_reducer_opor_reduce_short
+_cilk_c_reducer_opor_reduce_uchar
+_cilk_c_reducer_opor_reduce_uint
+_cilk_c_reducer_opor_reduce_ulong
+_cilk_c_reducer_opor_reduce_ulonglong
+_cilk_c_reducer_opor_reduce_unsigned
+_cilk_c_reducer_opor_reduce_ushort
+_cilk_c_reducer_opor_reduce_wchar_t
+_cilk_c_reducer_opxor_identity_char
+_cilk_c_reducer_opxor_identity_int
+_cilk_c_reducer_opxor_identity_long
+_cilk_c_reducer_opxor_identity_longlong
+_cilk_c_reducer_opxor_identity_schar
+_cilk_c_reducer_opxor_identity_short
+_cilk_c_reducer_opxor_identity_uchar
+_cilk_c_reducer_opxor_identity_uint
+_cilk_c_reducer_opxor_identity_ulong
+_cilk_c_reducer_opxor_identity_ulonglong
+_cilk_c_reducer_opxor_identity_unsigned
+_cilk_c_reducer_opxor_identity_ushort
+_cilk_c_reducer_opxor_identity_wchar_t
+_cilk_c_reducer_opxor_reduce_char
+_cilk_c_reducer_opxor_reduce_int
+_cilk_c_reducer_opxor_reduce_long
+_cilk_c_reducer_opxor_reduce_longlong
+_cilk_c_reducer_opxor_reduce_schar
+_cilk_c_reducer_opxor_reduce_short
+_cilk_c_reducer_opxor_reduce_uchar
+_cilk_c_reducer_opxor_reduce_uint
+_cilk_c_reducer_opxor_reduce_ulong
+_cilk_c_reducer_opxor_reduce_ulonglong
+_cilk_c_reducer_opxor_reduce_unsigned
+_cilk_c_reducer_opxor_reduce_ushort
+_cilk_c_reducer_opxor_reduce_wchar_t
diff --git a/libcilkrts/runtime/metacall_impl.c b/libcilkrts/runtime/metacall_impl.c
new file mode 100644
index 00000000000..ce1c51a202b
--- /dev/null
+++ b/libcilkrts/runtime/metacall_impl.c
@@ -0,0 +1,167 @@
+/* metacall_impl.c -*-C-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ **************************************************************************/
+
+#include "metacall_impl.h"
+
+NOINLINE
+CILK_API_VOID
+__cilkrts_metacall(unsigned int tool, unsigned int code, void *data)
+{
+#ifdef ENABLE_NOTIFY_ZC_INTRINSIC
+ // The metacall type, code and data are packed together into a single
+ // struct which will be interpreted by the tool. This function is the
+ // one and only use of a "cilkscreen_metacall" annotation
+ metacall_data_t d = { tool, code, data };
+
+ // Note that Inspector uses probe mode, and is implementing the metacall
+ // interface to force the runtime to run with a single worker. So
+ // __cilkrts_metacall must use __notify_intrinsic instead of
+ // __notify_zc_intrinsic
+ __notify_intrinsic("cilkscreen_metacall", &d);
+#endif // ENABLE_NOTIFY_ZC_INTRINSIC
+}
+
+int __cilkrts_running_under_sequential_ptool(void)
+{
+ static int running_under_sequential_ptool = -1;
+ volatile char c = ~0;
+
+ // If we haven't been called before, see if we're running under Cilkscreen
+ // or Cilkview
+ if (-1 == running_under_sequential_ptool)
+ {
+ // metacall #2 writes 0 in C if we are running under
+ // a p-tools that requires serial execution, and is a
+ // no-op otherwise
+ //
+ // Note that removing the volatile is required to prevent the compiler
+ // from assuming that the value has not changed
+ __cilkrts_metacall(METACALL_TOOL_SYSTEM,
+ HYPER_ZERO_IF_SEQUENTIAL_PTOOL, (void *)&c);
+
+ running_under_sequential_ptool = (0 == c);
+ }
+
+ return running_under_sequential_ptool;
+}
+
+/*
+ * __cilkrts_cilkscreen_establish_c_stack
+ *
+ * Notify Cilkscreen of the extent of the stack
+ */
+
+void __cilkrts_cilkscreen_establish_c_stack(char *begin, char *end)
+{
+ char *limits[2] = {begin, end};
+
+ __cilkrts_metacall(METACALL_TOOL_SYSTEM, HYPER_ESTABLISH_C_STACK, limits);
+}
+
+#ifdef WORKSPAN // Workspan stuff - remove when we're sure what we can drop
+
+void __cilkview_workspan_start(void) {
+ __cilkrts_metacall(HYPER_WORKSPAN_START, 0);
+}
+
+void __cilkview_workspan_stop(void) {
+ __cilkrts_metacall(HYPER_WORKSPAN_STOP, 0);
+}
+
+void __cilkview_workspan_dump(const char *str) {
+ __cilkrts_metacall(HYPER_WORKSPAN_DUMP, (void*)str);
+}
+
+
+void __cilkview_workspan_reset(void) {
+ __cilkrts_metacall(HYPER_WORKSPAN_RESET, 0);
+}
+
+
+void __cilkview_use_default_grain(void) {
+ __cilkrts_metacall(HYPER_USE_DEFAULT_GRAIN, 0);
+}
+
+void __cilkview_get_workspan_data(unsigned long long *values, int size)
+{
+ void *data[2];
+
+ /* reset counters to zero in case we are not running under
+ a p-tool */
+
+ values[0] = 0;
+
+ data[0] = (void*) values;
+ data[1] = (void*) &size;
+ __cilkrts_metacall(HYPER_WORKSPAN_QUERY, &data);
+}
+
+void __cilkview_workspan_connected (int *flag) {
+ *flag = 0;
+ __cilkrts_metacall(HYPER_WORKSPAN_CONNECTED, (void *)flag);
+}
+
+void __cilkview_workspan_suspend() {
+ __cilkrts_metacall(HYPER_WORKSPAN_SUSPEND, 0);
+}
+
+void __cilkview_workspan_resume() {
+ __cilkrts_metacall(HYPER_WORKSPAN_RESUME, 0);
+}
+
+/* depreciated interfaces */
+void __cilkometer_workspan_start(void) {
+ __cilkrts_metacall(HYPER_WORKSPAN_START, 0);
+}
+
+void __cilkometer_workspan_stop(void) {
+ __cilkrts_metacall(HYPER_WORKSPAN_STOP, 0);
+}
+
+void __cilkometer_workspan_dump(const char *str) {
+ __cilkrts_metacall(HYPER_WORKSPAN_DUMP, (void*)str);
+}
+
+
+void __cilkometer_workspan_reset(void) {
+ __cilkrts_metacall(HYPER_WORKSPAN_RESET, 0);
+}
+
+#endif // WORKSPAN
+
+/* End metacall_impl.c */
diff --git a/libcilkrts/runtime/metacall_impl.h b/libcilkrts/runtime/metacall_impl.h
new file mode 100644
index 00000000000..90cc7f95168
--- /dev/null
+++ b/libcilkrts/runtime/metacall_impl.h
@@ -0,0 +1,123 @@
+/* metacall_impl.h -*-C++-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2010-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ **************************************************************************/
+
+/**
+ * @file metacall_impl.h
+ *
+ * @brief Meta-function calls to be used within the Cilk runtime system.
+ *
+ * These differ from the macros in cilkscreen.h and cilkview.h because they go
+ * through the __cilkrts_metacall interface, which ensures that the operation
+ * is performed even when instrumentation is disabled.
+ */
+
+#ifndef INCLUDED_CILKRTS_METACALL_H
+#define INCLUDED_CILKRTS_METACALL_H
+
+#include "rts-common.h"
+#include <internal/metacall.h>
+#include <cilk/common.h>
+
+__CILKRTS_BEGIN_EXTERN_C
+
+/**
+ * This function is effectively an unconditional call from the runtime into
+ * a tool. It is used for operations that must be performed by the tool,
+ * even when the tool is not instrumenting. For example, Cilkscreen always
+ * recognizes the address of this function and performs the action specified
+ * in the contained metadata.
+ *
+ * Note that this function MUST NOT BE INLINED within the runtime. This must
+ * be the ONLY instance of the cilkscreen_metacall metadata.
+ */
+CILK_API_VOID
+__cilkrts_metacall(unsigned int tool, unsigned int code, void *data);
+
+/**
+ * Return non-zero if running under Cilkscreen or Cilkview
+ */
+COMMON_PORTABLE
+int __cilkrts_running_under_sequential_ptool(void);
+
+/**
+ * Disable Cilkscreen implementation
+ */
+#define __cilkrts_cilkscreen_disable_instrumentation() \
+ __cilkrts_metacall(METACALL_TOOL_SYSTEM, HYPER_DISABLE_INSTRUMENTATION, 0)
+
+/**
+ * Enable Cilkscreen implementation
+ */
+#define __cilkrts_cilkscreen_enable_instrumentation() \
+ __cilkrts_metacall(METACALL_TOOL_SYSTEM, HYPER_ENABLE_INSTRUMENTATION, 0)
+
+/**
+ * Set the worker on entering runtime.
+ *
+ * @attention Deprecated in favor of __cilkrts_cilkscreen_ignore_block. The
+ * begin/enter pairs in the current metadata mean Cilkscreen no longer has to
+ * have improper knowledge of the __cilkrts_worker or __cilkrts_stack_frame
+ * structures.
+ */
+#define __cilkrts_cilkscreen_establish_worker(w) \
+ __cilkrts_metacall(METACALL_TOOL_SYSTEM, HYPER_ESTABLISH_WORKER, w)
+
+/**
+ * Notify Cilkscreen of the extent of the stack.
+ *
+ * @param[in] begin Start (low address) of stack
+ * @param[in] end One past high address of stack
+ */
+void __cilkrts_cilkscreen_establish_c_stack(char *begin, char *end);
+
+/**
+ * Tell tools to ignore a block of memory - currently the global state and
+ * memory allocated for workers.
+ */
+#define __cilkrts_cilkscreen_ignore_block(_begin, _end) \
+{ \
+ void *block[2] = {_begin, _end}; \
+ __cilkrts_metacall(METACALL_TOOL_SYSTEM, \
+ HYPER_IGNORE_MEMORY_BLOCK, \
+ block); \
+}
+
+__CILKRTS_END_EXTERN_C
+
+#endif /* ! defined(INCLUDED_CILKRTS_METACALL_H) */
diff --git a/libcilkrts/runtime/os-unix.c b/libcilkrts/runtime/os-unix.c
new file mode 100644
index 00000000000..dbca21f6f3c
--- /dev/null
+++ b/libcilkrts/runtime/os-unix.c
@@ -0,0 +1,511 @@
+/* os-unix.c -*-C-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ **************************************************************************/
+
+#ifdef __linux__
+ // define _GNU_SOURCE before *any* #include.
+ // Even <stdint.h> will break later #includes if this macro is not
+ // already defined when it is #included.
+# define _GNU_SOURCE
+#endif
+
+#include "os.h"
+#include "bug.h"
+#include "cilk_malloc.h"
+#include <internal/abi.h>
+
+#if defined __linux__
+# include <sys/sysinfo.h>
+# include <sys/syscall.h>
+#elif defined __APPLE__
+# include <sys/sysctl.h>
+ // Uses sysconf(_SC_NPROCESSORS_ONLN) in verbose output
+#elif defined __FreeBSD__
+// No additional include files
+#elif defined __CYGWIN__
+// Cygwin on Windows - no additional include files
+#elif defined __VXWORKS__
+# include <vxWorks.h>
+# include <vxCpuLib.h>
+# include <taskLib.h>
+// Solaris
+#elif defined __sun__ && defined __svr4__
+# include <sched.h>
+#else
+# error "Unsupported OS"
+#endif
+
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <sys/types.h>
+
+
+
+// /* Thread-local storage */
+// #ifdef _WIN32
+// typedef unsigned cilkos_tls_key_t;
+// #else
+// typedef pthread_key_t cilkos_tls_key_t;
+// #endif
+// cilkos_tls_key_t cilkos_allocate_tls_key();
+// void cilkos_set_tls_pointer(cilkos_tls_key_t key, void* ptr);
+// void* cilkos_get_tls_pointer(cilkos_tls_key_t key);
+
+#if !defined CILK_WORKER_TLS
+static int cilk_keys_defined;
+static pthread_key_t worker_key, pedigree_leaf_key, tbb_interop_key;
+
+#if SUPPORT_GET_CURRENT_FIBER > 0
+static pthread_key_t fiber_key;
+#endif
+
+static void *serial_worker;
+
+
+// This destructor is called when a pthread dies to deallocate the
+// pedigree node.
+static void __cilkrts_pedigree_leaf_destructor(void* pedigree_tls_ptr)
+{
+ __cilkrts_pedigree* pedigree_tls
+ = (__cilkrts_pedigree*)pedigree_tls_ptr;
+ if (pedigree_tls) {
+ // Assert that we have either one or two nodes
+ // left in the pedigree chain.
+ // If we have more, then something is going wrong...
+ CILK_ASSERT(!pedigree_tls->parent || !pedigree_tls->parent->parent);
+ __cilkrts_free(pedigree_tls);
+ }
+}
+
+void __cilkrts_init_tls_variables(void)
+{
+ int status;
+ /* This will be called once in serial execution before any
+ Cilk parallelism so we do not need to worry about races
+ on cilk_keys_defined. */
+ if (cilk_keys_defined)
+ return;
+ status = pthread_key_create(&worker_key, NULL);
+ CILK_ASSERT (status == 0);
+ status = pthread_key_create(&pedigree_leaf_key,
+ __cilkrts_pedigree_leaf_destructor);
+ CILK_ASSERT (status == 0);
+ status = pthread_key_create(&tbb_interop_key, NULL);
+ CILK_ASSERT (status == 0);
+
+#if SUPPORT_GET_CURRENT_FIBER > 0
+ status = pthread_key_create(&fiber_key, NULL);
+ CILK_ASSERT (status == 0);
+#endif
+ cilk_keys_defined = 1;
+ return;
+}
+
+COMMON_SYSDEP
+void* cilkos_get_current_thread_id(void)
+{
+ return (void*)pthread_self();
+}
+
+
+CILK_ABI_WORKER_PTR __cilkrts_get_tls_worker()
+{
+ if (__builtin_expect(cilk_keys_defined, 1))
+ return (__cilkrts_worker *)pthread_getspecific(worker_key);
+ else
+ return serial_worker;
+
+}
+
+CILK_ABI_WORKER_PTR __cilkrts_get_tls_worker_fast()
+{
+ return (__cilkrts_worker *)pthread_getspecific(worker_key);
+}
+
+COMMON_SYSDEP
+__cilk_tbb_stack_op_thunk *__cilkrts_get_tls_tbb_interop(void)
+{
+ if (__builtin_expect(cilk_keys_defined, 1))
+ return (__cilk_tbb_stack_op_thunk *)
+ pthread_getspecific(tbb_interop_key);
+ else
+ return 0;
+}
+
+// This counter should be updated atomically.
+static int __cilkrts_global_pedigree_tls_counter = -1;
+
+COMMON_SYSDEP
+__cilkrts_pedigree *__cilkrts_get_tls_pedigree_leaf(int create_new)
+{
+ __cilkrts_pedigree *pedigree_tls;
+ if (__builtin_expect(cilk_keys_defined, 1)) {
+ pedigree_tls =
+ (struct __cilkrts_pedigree *)pthread_getspecific(pedigree_leaf_key);
+ }
+ else {
+ return 0;
+ }
+
+ if (!pedigree_tls && create_new) {
+ // This call creates two nodes, X and Y.
+ // X == pedigree_tls[0] is the leaf node, which gets copied
+ // in and out of a user worker w when w binds and unbinds.
+ // Y == pedigree_tls[1] is the root node,
+ // which is a constant node that represents the user worker
+ // thread w.
+ pedigree_tls = (__cilkrts_pedigree*)
+ __cilkrts_malloc(2 * sizeof(__cilkrts_pedigree));
+
+ // This call sets the TLS pointer to the new node.
+ __cilkrts_set_tls_pedigree_leaf(pedigree_tls);
+
+ pedigree_tls[0].rank = 0;
+ pedigree_tls[0].parent = &pedigree_tls[1];
+
+ // Create Y, whose rank begins as the global counter value.
+ pedigree_tls[1].rank =
+ __sync_add_and_fetch(&__cilkrts_global_pedigree_tls_counter, 1);
+
+ pedigree_tls[1].parent = NULL;
+ CILK_ASSERT(pedigree_tls[1].rank != -1);
+ }
+ return pedigree_tls;
+}
+
+#if SUPPORT_GET_CURRENT_FIBER > 0
+COMMON_SYSDEP
+cilk_fiber_sysdep* cilkos_get_tls_cilk_fiber(void)
+{
+ if (__builtin_expect(cilk_keys_defined, 1))
+ return (cilk_fiber_sysdep *)pthread_getspecific(fiber_key);
+ else
+ return NULL;
+}
+#endif
+
+COMMON_SYSDEP
+void __cilkrts_set_tls_worker(__cilkrts_worker *w)
+{
+ if (__builtin_expect(cilk_keys_defined, 1)) {
+ int status;
+ status = pthread_setspecific(worker_key, w);
+ CILK_ASSERT (status == 0);
+ return;
+ }
+ else
+ {
+ serial_worker = w;
+ }
+}
+
+COMMON_SYSDEP
+void __cilkrts_set_tls_tbb_interop(__cilk_tbb_stack_op_thunk *t)
+{
+ if (__builtin_expect(cilk_keys_defined, 1)) {
+ int status;
+ status = pthread_setspecific(tbb_interop_key, t);
+ CILK_ASSERT (status == 0);
+ return;
+ }
+ abort();
+}
+
+COMMON_SYSDEP
+void __cilkrts_set_tls_pedigree_leaf(__cilkrts_pedigree* pedigree_leaf)
+{
+ if (__builtin_expect(cilk_keys_defined, 1)) {
+ int status;
+ status = pthread_setspecific(pedigree_leaf_key, pedigree_leaf);
+ CILK_ASSERT (status == 0);
+ return;
+ }
+ abort();
+}
+
+#if SUPPORT_GET_CURRENT_FIBER > 0
+COMMON_SYSDEP
+void cilkos_set_tls_cilk_fiber(cilk_fiber_sysdep* fiber)
+{
+ if (__builtin_expect(cilk_keys_defined, 1)) {
+ int status;
+ status = pthread_setspecific(fiber_key, fiber);
+ CILK_ASSERT (status == 0);
+ return;
+ }
+ abort();
+}
+#endif
+
+#else
+void __cilkrts_init_tls_variables(void)
+{
+}
+#endif
+
+#if defined (__linux__) && ! defined(ANDROID)
+/*
+ * Get the thread id, rather than the pid. In the case of MIC offload, it's
+ * possible that we have multiple threads entering Cilk, and each has a
+ * different affinity.
+ */
+static pid_t linux_gettid(void)
+{
+ return syscall(SYS_gettid);
+}
+
+/*
+ * On Linux we look at the thread affinity mask and restrict ourself to one
+ * thread for each of the hardware contexts to which we are bound.
+ * Therefore if user does
+ * % taskset 0-1 cilkProgram
+ * # restrict execution to hardware contexts zero and one
+ * the Cilk program will only use two threads even if it is running on a
+ * machine that has 32 hardware contexts.
+ * This is the right thing to do, because the threads are restricted to two
+ * hardware contexts by the affinity mask set by taskset, and if we were to
+ * create extra threads they would simply oversubscribe the hardware resources
+ * we can use.
+ * This is particularly important on MIC in offload mode, where the affinity
+ * mask is set by the offload library to force the offload code away from
+ * cores that have offload support threads running on them.
+ */
+static int linux_get_affinity_count (int tid)
+{
+ cpu_set_t process_mask;
+
+ // Extract the thread affinity mask
+ int err = sched_getaffinity (tid, sizeof(process_mask),&process_mask);
+
+ if (0 != err)
+ {
+ return 0;
+ }
+
+ // We have extracted the mask OK, so now we can count the number of threads
+ // in it. This is linear in the maximum number of CPUs available, We
+ // could do a logarithmic version, if we assume the format of the mask,
+ // but it's not really worth it. We only call this at thread startup
+ // anyway.
+ int available_procs = 0;
+ int i;
+ for (i = 0; i < CPU_SETSIZE; i++)
+ {
+ if (CPU_ISSET(i, &process_mask))
+ {
+ available_procs++;
+ }
+ }
+
+ return available_procs;
+}
+#endif
+
+/*
+ * __cilkrts_hardware_cpu_count
+ *
+ * Returns the number of available CPUs on this hardware. This is architecture-
+ * specific.
+ */
+
+COMMON_SYSDEP int __cilkrts_hardware_cpu_count(void)
+{
+#if defined ANDROID || (defined(__sun__) && defined(__svr4__))
+ return sysconf (_SC_NPROCESSORS_ONLN);
+#elif defined __MIC__
+ /// HACK: Usually, the 3rd and 4th hyperthreads are not beneficial
+ /// on KNC. Also, ignore the last core.
+ int P = sysconf (_SC_NPROCESSORS_ONLN);
+ return P/2 - 2;
+#elif defined __linux__
+ int affinity_count = linux_get_affinity_count(linux_gettid());
+
+ return (0 != affinity_count) ? affinity_count : sysconf (_SC_NPROCESSORS_ONLN);
+#elif defined __APPLE__
+ int count = 0;
+ int cmd[2] = { CTL_HW, HW_NCPU };
+ size_t len = sizeof count;
+ int status = sysctl(cmd, 2, &count, &len, 0, 0);
+ assert(status >= 0);
+ assert((unsigned)count == count);
+
+ return count;
+#elif defined __FreeBSD__ || defined __CYGWIN__
+ int ncores = sysconf(_SC_NPROCESSORS_ONLN);
+
+ return ncores;
+ // Just get the number of processors
+// return sysconf(_SC_NPROCESSORS_ONLN);
+#elif defined __VXWORKS__
+ return __builtin_popcount( vxCpuEnabledGet() );
+#else
+#error "Unknown architecture"
+#endif
+}
+
+COMMON_SYSDEP void __cilkrts_sleep(void)
+{
+#ifdef __VXWORKS__
+ taskDelay(1);
+#else
+ usleep(1);
+#endif
+}
+
+COMMON_SYSDEP void __cilkrts_yield(void)
+{
+#if __APPLE__ || __FreeBSD__ || __VXWORKS__
+ // On MacOS, call sched_yield to yield quantum. I'm not sure why we
+ // don't do this on Linux also.
+ sched_yield();
+#elif defined(__MIC__)
+ // On MIC, pthread_yield() really trashes things. Arch's measurements
+ // showed that calling _mm_delay_32() (or doing nothing) was a better
+ // option. Delaying 1024 clock cycles is a reasonable compromise between
+ // giving up the processor and latency starting up when work becomes
+ // available
+ _mm_delay_32(1024);
+#elif defined(ANDROID) || (defined(__sun__) && defined(__svr4__))
+ // On Android and Solaris, call sched_yield to yield quantum. I'm not
+ // sure why we don't do this on Linux also.
+ sched_yield();
+#else
+ // On Linux, call pthread_yield (which in turn will call sched_yield)
+ // to yield quantum.
+ pthread_yield();
+#endif
+}
+
+COMMON_SYSDEP __STDNS size_t cilkos_getenv(char* value, __STDNS size_t vallen,
+ const char* varname)
+{
+ CILK_ASSERT(value);
+ CILK_ASSERT(varname);
+
+ const char* envstr = getenv(varname);
+ if (envstr)
+ {
+ size_t len = strlen(envstr);
+ if (len > vallen - 1)
+ return len + 1;
+
+ strcpy(value, envstr);
+ return len;
+ }
+ else
+ {
+ value[0] = '\0';
+ return 0;
+ }
+}
+
+/*
+ * Unrecoverable error: Print an error message and abort execution.
+ */
+COMMON_SYSDEP void cilkos_error(const char *fmt, ...)
+{
+ va_list l;
+ fflush(NULL);
+ fprintf(stderr, "Cilk error: ");
+ va_start(l, fmt);
+ vfprintf(stderr, fmt, l);
+ va_end(l);
+ fprintf(stderr, "Exiting.\n");
+ fflush(stderr);
+
+ abort();
+}
+
+/*
+ * Print a warning message and return.
+ */
+COMMON_SYSDEP void cilkos_warning(const char *fmt, ...)
+{
+ va_list l;
+ fflush(NULL);
+ fprintf(stderr, "Cilk warning: ");
+ va_start(l, fmt);
+ vfprintf(stderr, fmt, l);
+ va_end(l);
+ fflush(stderr);
+}
+
+static void __attribute__((constructor)) init_once()
+{
+ /*__cilkrts_debugger_notification_internal(CILK_DB_RUNTIME_LOADED);*/
+ __cilkrts_init_tls_variables();
+}
+
+
+#define PAGE 4096
+#define CILK_MIN_STACK_SIZE (4*PAGE)
+// Default size for the stacks that we create in Cilk for Unix.
+#define CILK_DEFAULT_STACK_SIZE 0x100000
+
+/*
+ * Convert the user's specified stack size into a "reasonable" value
+ * for this OS.
+ */
+size_t cilkos_validate_stack_size(size_t specified_stack_size) {
+ // Convert any negative value to the default.
+ if (specified_stack_size == 0) {
+ CILK_ASSERT((CILK_DEFAULT_STACK_SIZE % PAGE) == 0);
+ return CILK_DEFAULT_STACK_SIZE;
+ }
+ // Round values in between 0 and CILK_MIN_STACK_SIZE up to
+ // CILK_MIN_STACK_SIZE.
+ if (specified_stack_size <= CILK_MIN_STACK_SIZE) {
+ return CILK_MIN_STACK_SIZE;
+ }
+ if ((specified_stack_size % PAGE) > 0) {
+ // Round the user's stack size value up to nearest page boundary.
+ return (PAGE * (1 + specified_stack_size / PAGE));
+ }
+ return specified_stack_size;
+}
+
+long cilkos_atomic_add(volatile long* p, long x)
+{
+ return __sync_add_and_fetch(p, x);
+}
+
+/* End os-unix.c */
diff --git a/libcilkrts/runtime/os.h b/libcilkrts/runtime/os.h
new file mode 100644
index 00000000000..8066f0313c2
--- /dev/null
+++ b/libcilkrts/runtime/os.h
@@ -0,0 +1,236 @@
+/* os.h -*-C++-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ **************************************************************************/
+
+/**
+ * @file os.h
+ *
+ * @brief Low-level operating-system dependent facilities, not dependent on
+ * any Cilk facilities.
+ */
+
+#ifndef INCLUDED_OS_DOT_H
+#define INCLUDED_OS_DOT_H
+
+#include "rts-common.h"
+#include "cilk/common.h"
+#include "cilk-tbb-interop.h"
+
+#ifdef __cplusplus
+# include <cstddef>
+#else
+# include <stddef.h>
+#endif
+
+__CILKRTS_BEGIN_EXTERN_C
+
+
+// /* Thread-local storage */
+// #ifdef _WIN32
+// typedef unsigned cilkos_tls_key_t;
+// #else
+// typedef pthread_key_t cilkos_tls_key_t;
+// #endif
+// cilkos_tls_key_t cilkos_allocate_tls_key();
+// void cilkos_set_tls_pointer(cilkos_tls_key_t key, void* ptr);
+// void* cilkos_get_tls_pointer(cilkos_tls_key_t key);
+
+/* The RTS assumes that some thread-local state exists that stores the
+ worker and reducer map currently associated with a thread. These routines
+ manipulate this state. */
+
+/** @brief Thread-local state for cilk fibers. */
+typedef struct cilk_fiber_sysdep cilk_fiber_sysdep;
+
+/** @brief Initialize all TLS variables for Cilk. */
+COMMON_SYSDEP void __cilkrts_init_tls_variables(void);
+
+/** @brief Set worker struct in TLS. */
+COMMON_SYSDEP
+void __cilkrts_set_tls_worker(__cilkrts_worker *w) cilk_nothrow;
+
+/** @brief Get stack_op for TBB-interop structures from TLS. */
+COMMON_SYSDEP
+__cilk_tbb_stack_op_thunk *__cilkrts_get_tls_tbb_interop(void);
+
+/** @brief Set stack_op for TBB-interop structures in TLS. */
+COMMON_SYSDEP
+void __cilkrts_set_tls_tbb_interop(__cilk_tbb_stack_op_thunk *t);
+
+/**
+ * @brief Get the pointer to the pedigree leaf node from TLS.
+ *
+ * Function to get a pointer to the thread's pedigree leaf node. This
+ * pointer can be NULL.
+ */
+COMMON_SYSDEP
+__cilkrts_pedigree * __cilkrts_get_tls_pedigree_leaf(int create_new);
+
+/**
+ * @brief Sets the pointer to the pedigree leaf node in TLS.
+ *
+ * If the previous pointer value was not NULL, it is the caller's
+ * responsibility to ensure that previous pointer value is saved and
+ * freed.
+ *
+ * @param pedigree_leaf The leaf node to store into TLS.
+ */
+COMMON_SYSDEP
+void __cilkrts_set_tls_pedigree_leaf(__cilkrts_pedigree* pedigree_leaf);
+
+
+#if SUPPORT_GET_CURRENT_FIBER > 0
+/**
+ * @brief Get the cilk_fiber from TLS.
+ */
+COMMON_SYSDEP
+cilk_fiber_sysdep* cilkos_get_tls_cilk_fiber(void);
+
+/**
+ * @brief Set the cilk_fiber in TLS.
+ *
+ * @param fiber The fiber to store into TLS.
+ */
+COMMON_SYSDEP
+void cilkos_set_tls_cilk_fiber(cilk_fiber_sysdep* fiber);
+#endif
+
+/**
+ * @brief Function for returning the current thread id.
+ * @warning This function is useful for debugging purposes only.
+ */
+COMMON_SYSDEP
+void* cilkos_get_current_thread_id(void);
+
+/** @brief Return number of CPUs supported by this hardware, using whatever definition
+ of CPU is considered appropriate. */
+COMMON_SYSDEP int __cilkrts_hardware_cpu_count(void);
+
+/** @brief Get current value of timer */
+COMMON_SYSDEP unsigned long long __cilkrts_getticks(void);
+
+/* Machine instructions */
+
+/// Stall execution for a few cycles.
+COMMON_SYSDEP void __cilkrts_short_pause(void);
+/// Wrapper for xchg instruction
+COMMON_SYSDEP int __cilkrts_xchg(volatile int *ptr, int x);
+
+// Defines __cilkrts_fence - A macro for x86, a function call for other
+// architectures
+#include "os-fence.h"
+
+COMMON_SYSDEP void __cilkrts_sleep(void); ///< Sleep briefly
+COMMON_SYSDEP void __cilkrts_yield(void); ///< Yield quantum
+
+/**
+ * @brief Gets environment variable 'varname' and copy its value into 'value'.
+ *
+ * If the entire value, including the null terminator fits into 'vallen'
+ * bytes, then returns the length of the value excluding the null. Otherwise,
+ * leaves the contents of 'value' undefined and returns the number of
+ * characters needed to store the environment variable's value, *including*
+ * the null terminator.
+ *
+ * @param value Buffer to store value.
+ * @param vallen Length of value buffer
+ * @param varname Name of the environment variable.
+ * @return Length of value buffer (excluding the null).
+ */
+COMMON_SYSDEP __STDNS size_t cilkos_getenv(char* value, __STDNS size_t vallen,
+ const char* varname);
+
+/**
+ * @brief Unrecoverable error: Print an error message and abort execution.
+ */
+COMMON_SYSDEP void cilkos_error(const char *fmt, ...);
+
+/**
+ * @brief Print a warning message and return.
+ */
+COMMON_SYSDEP void cilkos_warning(const char *fmt, ...);
+
+/**
+ * @brief Convert the user's specified stack size into a "reasonable"
+ * value for the current OS.
+ *
+ * @param specified_stack_size User-specified stack size.
+ * @return New stack size value, modified for the OS.
+ */
+COMMON_SYSDEP size_t cilkos_validate_stack_size(size_t specified_stack_size);
+
+/**
+ * @brief Atomic addition: computes *p += x.
+ *
+ * @param p Pointer to value to update
+ * @param x Value of x.
+ */
+COMMON_SYSDEP long cilkos_atomic_add(volatile long* p, long x);
+
+#ifdef _WIN32
+
+/**
+ * @brief Windows-only low-level functions for processor groups.
+ */
+typedef struct _GROUP_AFFINITY GROUP_AFFINITY;
+
+/**
+ * @brief Probe the executing OS to see if it supports processor
+ * groups. These functions are expected to be available in Windows 7
+ * or later.
+ */
+void win_init_processor_groups(void);
+
+unsigned long win_get_active_processor_count(unsigned short GroupNumber);
+unsigned short win_get_active_processor_group_count(void);
+int win_set_thread_group_affinity(/*HANDLE*/ void* hThread,
+ const GROUP_AFFINITY *GroupAffinity,
+ GROUP_AFFINITY* PreviousGroupAffinity);
+
+/**
+ * @brief Cleans up any state allocated in TLS.
+ *
+ * Only defined for Windows because Linux calls destructors for each
+ * thread-local variable.
+ */
+void __cilkrts_per_thread_tls_cleanup(void);
+
+#endif // _WIN32
+
+__CILKRTS_END_EXTERN_C
+
+#endif // ! defined(INCLUDED_OS_DOT_H)
diff --git a/libcilkrts/runtime/os_mutex-unix.c b/libcilkrts/runtime/os_mutex-unix.c
new file mode 100644
index 00000000000..af398cdd089
--- /dev/null
+++ b/libcilkrts/runtime/os_mutex-unix.c
@@ -0,0 +1,193 @@
+/* os_mutex-unix.c -*-C-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ **************************************************************************/
+
+#include "os_mutex.h"
+#include "bug.h"
+
+#include <stdlib.h>
+#include <errno.h>
+#include <pthread.h>
+
+// contains notification macros for VTune.
+#include "cilk-ittnotify.h"
+
+/*
+ * OS Mutex functions.
+ *
+ * Not to be confused with the spinlock mutexes implemented in cilk_mutex.c
+ */
+
+struct os_mutex {
+ pthread_mutex_t mutex; ///< On Linux, os_mutex is implemented with a pthreads mutex
+};
+
+// Unix implementation of the global OS mutex. This will be created by the
+// first call to global_os_mutex_lock() and *NEVER* destroyed. On gcc-based
+// systems there's no way to guarantee the ordering of constructors and
+// destructors, so we can't be guaranteed that our destructor for a static
+// object will be called *after* any static destructors that may use Cilk
+// in the user's application
+static struct os_mutex *global_os_mutex = NULL;
+
+/* Sometimes during shared library load malloc doesn't work.
+ To handle that case, preallocate space for one mutex. */
+static struct os_mutex static_mutex;
+static int static_mutex_used;
+
+struct os_mutex *__cilkrts_os_mutex_create(void)
+{
+ int status;
+ struct os_mutex *mutex = (struct os_mutex *)malloc(sizeof(struct os_mutex));
+ pthread_mutexattr_t attr;
+
+ ITT_SYNC_CREATE(mutex, "OS Mutex");
+
+ if (!mutex) {
+ if (static_mutex_used) {
+ __cilkrts_bug("Cilk RTS library initialization failed");
+ } else {
+ static_mutex_used = 1;
+ mutex = &static_mutex;
+ }
+ }
+
+ status = pthread_mutexattr_init(&attr);
+ CILK_ASSERT (status == 0);
+#if defined DEBUG || CILK_LIB_DEBUG
+#ifdef PTHREAD_MUTEX_ERRORCHECK
+ status = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
+#else
+ status = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK_NP);
+#endif
+ CILK_ASSERT (status == 0);
+#endif
+ status = pthread_mutex_init (&mutex->mutex, &attr);
+ CILK_ASSERT (status == 0);
+ pthread_mutexattr_destroy(&attr);
+
+ return mutex;
+}
+
+void __cilkrts_os_mutex_lock(struct os_mutex *p)
+{
+ int status;
+ status = pthread_mutex_lock (&p->mutex);
+ ITT_SYNC_ACQUIRED(p);
+ if (__builtin_expect(status, 0) == 0)
+ return;
+ if (status == EDEADLK)
+ __cilkrts_bug("Cilk runtime error: deadlock acquiring mutex %p\n",
+ p);
+ else
+ __cilkrts_bug("Cilk runtime error %d acquiring mutex %p\n",
+ status, p);
+}
+
+int __cilkrts_os_mutex_trylock(struct os_mutex *p)
+{
+ int status;
+ status = pthread_mutex_trylock (&p->mutex);
+ return (status == 0);
+}
+
+void __cilkrts_os_mutex_unlock(struct os_mutex *p)
+{
+ int status;
+ ITT_SYNC_RELEASING(p);
+ status = pthread_mutex_unlock (&p->mutex);
+ CILK_ASSERT(status == 0);
+}
+
+void __cilkrts_os_mutex_destroy(struct os_mutex *p)
+{
+ pthread_mutex_destroy (&p->mutex);
+ if (p == &static_mutex) {
+ static_mutex_used = 0;
+ } else {
+ free(p);
+ }
+}
+
+/*
+ * create_global_os_mutex
+ *
+ * Function used with pthread_once to initialize the global OS mutex. Since
+ * pthread_once requires a function which takes no parameters and has no
+ * return value, the global OS mutex will be stored in the static (global
+ * to the compilation unit) variable "global_os_mutex."
+ *
+ *
+ * global_os_mutex will never be destroyed.
+ */
+static void create_global_os_mutex(void)
+{
+ CILK_ASSERT(NULL == global_os_mutex);
+ global_os_mutex = __cilkrts_os_mutex_create();
+}
+
+void global_os_mutex_lock(void)
+{
+ // pthread_once_t used with pthread_once to guarantee that
+ // create_global_os_mutex() is only called once
+ static pthread_once_t global_os_mutex_is_initialized = PTHREAD_ONCE_INIT;
+
+ // Execute create_global_os_mutex once in a thread-safe manner
+ // Note that create_global_os_mutex returns the mutex in the static
+ // (global to the module) variable "global_os_mutex"
+ pthread_once(&global_os_mutex_is_initialized,
+ create_global_os_mutex);
+
+ // We'd better have allocated a global_os_mutex
+ CILK_ASSERT(NULL != global_os_mutex);
+
+ // Acquire the global OS mutex
+ __cilkrts_os_mutex_lock(global_os_mutex);
+}
+
+void global_os_mutex_unlock(void)
+{
+ // We'd better have allocated a global_os_mutex. This means you should
+ // have called global_os_mutex_lock() before calling
+ // global_os_mutex_unlock(), but this is the only check for it.
+ CILK_ASSERT(NULL != global_os_mutex);
+
+ // Release the global OS mutex
+ __cilkrts_os_mutex_unlock(global_os_mutex);
+}
+
+/* End os_mutex-unix.c */
diff --git a/libcilkrts/runtime/os_mutex.h b/libcilkrts/runtime/os_mutex.h
new file mode 100644
index 00000000000..71d9eb14e51
--- /dev/null
+++ b/libcilkrts/runtime/os_mutex.h
@@ -0,0 +1,135 @@
+/* os_mutex.h -*-C++-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ **************************************************************************/
+
+/**
+ * @file os_mutex.h
+ *
+ * @brief Portable interface to operating-system mutexes.
+ *
+ * Do not confuse os_mutex with Cilk runtime-specific spinlock mutexes.
+ */
+
+#ifndef INCLUDED_OS_MUTEX_DOT_H
+#define INCLUDED_OS_MUTEX_DOT_H
+
+#include <cilk/common.h>
+#include "rts-common.h"
+
+__CILKRTS_BEGIN_EXTERN_C
+
+/// Opaque type
+typedef struct os_mutex os_mutex;
+
+/**
+ * Allocate and initialize an os_mutex
+ *
+ * @return A pointer to the initialized os_mutex
+ */
+COMMON_SYSDEP os_mutex* __cilkrts_os_mutex_create(void);
+
+/**
+ * Acquire the os_mutex for exclusive use
+ *
+ * @param m The os_mutex that is to be acquired.
+ */
+COMMON_SYSDEP void __cilkrts_os_mutex_lock(os_mutex *m);
+
+/**
+ * Try to acquire the os_mutex.
+ *
+ * @param m The os_mutex to try to acquire
+ * @return 0 if the lock acquire failed
+ * @return nonzero if the lock was acquired
+ */
+COMMON_SYSDEP int __cilkrts_os_mutex_trylock(os_mutex *m);
+
+/**
+ * Release the os_mutex
+ *
+ * @param m The os_mutex that is to be released.
+ */
+COMMON_SYSDEP void __cilkrts_os_mutex_unlock(os_mutex *m);
+
+/**
+ * Release any resources and deallocate the os_mutex.
+ *
+ * @param m The os_mutex that is to be deallocated.
+ */
+COMMON_SYSDEP void __cilkrts_os_mutex_destroy(os_mutex *m);
+
+/**
+ * Acquire the global os_mutex for exclusive use. The global os_mutex
+ * will be initialized the first time this function is called in a
+ * thread-safe manner.
+ */
+COMMON_SYSDEP void global_os_mutex_lock();
+
+/**
+ * Release the global os_mutex. global_os_mutex_lock() must have been
+ * called first.
+ */
+COMMON_SYSDEP void global_os_mutex_unlock();
+
+
+#ifdef _MSC_VER
+
+/**
+ * @brief Create the global OS mutex - Windows only.
+ *
+ * On Windows we use DllMain() to create the global OS mutex when cilkrts20.dll
+ * is loaded. As opposed to Linux/MacOS where we use pthread_once to implement
+ * a singleton since there are no guarantees about constructor or destructor
+ * ordering between shared objects.
+ */
+NON_COMMON void global_os_mutex_create();
+
+/**
+ * @brief Destroy the global OS mutex - Windows only
+ *
+ * On Windows we use DllMain() to destroy the global OS mutex when
+ * cilkrts20.dll is unloaded. As opposed to Linux/MacOS where we cannot
+ * know when it's safe to destroy the global OS mutex since there are no
+ * guarantees about constructor or destructor ordering.
+ */
+NON_COMMON void global_os_mutex_destroy();
+
+#endif // _MSC_VER
+
+__CILKRTS_END_EXTERN_C
+
+#endif // ! defined(INCLUDED_OS_MUTEX_DOT_H)
diff --git a/libcilkrts/runtime/pedigrees.c b/libcilkrts/runtime/pedigrees.c
new file mode 100644
index 00000000000..dee4d9cb411
--- /dev/null
+++ b/libcilkrts/runtime/pedigrees.c
@@ -0,0 +1,112 @@
+/* pedigrees.c -*-C-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2007-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ **************************************************************************/
+
+#include "pedigrees.h"
+#include "local_state.h"
+
+/*************************************************************
+ Pedigree API code.
+*************************************************************/
+
+/*
+ * C99 requires that every inline function with external linkage have one
+ * extern declaration in the program (with the inline definition in scope).
+ */
+COMMON_PORTABLE
+extern void update_pedigree_on_leave_frame(__cilkrts_worker *w,
+ __cilkrts_stack_frame *sf);
+
+void __cilkrts_set_pedigree_leaf(__cilkrts_pedigree *leaf)
+{
+ __cilkrts_set_tls_pedigree_leaf(leaf);
+}
+
+void load_pedigree_leaf_into_user_worker(__cilkrts_worker *w)
+{
+ __cilkrts_pedigree *pedigree_leaf;
+ CILK_ASSERT(w->l->type == WORKER_USER);
+ pedigree_leaf = __cilkrts_get_tls_pedigree_leaf(1);
+ w->pedigree = *pedigree_leaf;
+
+ // Save a pointer to the old leaf.
+ // We'll need to restore it later.
+ CILK_ASSERT(w->l->original_pedigree_leaf == NULL);
+ w->l->original_pedigree_leaf = pedigree_leaf;
+
+ __cilkrts_set_tls_pedigree_leaf(&w->pedigree);
+
+ // Check that this new pedigree root has at least two values.
+ CILK_ASSERT(w->pedigree.parent);
+ CILK_ASSERT(w->pedigree.parent->parent == NULL);
+}
+
+void save_pedigree_leaf_from_user_worker(__cilkrts_worker *w)
+{
+ CILK_ASSERT(w->l->type == WORKER_USER);
+
+ // Existing leaf in tls should be for the current worker.
+ // This assert is expensive to check though.
+ // CILK_ASSERT(&w->pedigree == __cilkrts_get_tls_pedigree_leaf(0));
+ CILK_ASSERT(w->l->original_pedigree_leaf);
+
+ // w should finish with a pedigree node that points to
+ // the same root that we just looked up.
+
+ // TODO: This assert should be valid.
+ // But we are removing it now to make exceptions (without pedigrees) work.
+ // Currently, reading the pedigree after an exception is caught
+ // fails because the pedigree chain not restored correctly.
+ // CILK_ASSERT(w->l->original_pedigree_leaf->next == w->pedigree.parent);
+ w->l->original_pedigree_leaf->rank = w->pedigree.rank;
+
+ // Save that leaf pointer back into tls.
+ __cilkrts_set_tls_pedigree_leaf(w->l->original_pedigree_leaf);
+ // Null out worker's leaf for paranoia.
+ w->l->original_pedigree_leaf = NULL;
+}
+
+
+
+/*
+ Local Variables: **
+ c-file-style:"bsd" **
+ c-basic-offset:4 **
+ indent-tabs-mode:nil **
+ End: **
+*/
diff --git a/libcilkrts/runtime/pedigrees.h b/libcilkrts/runtime/pedigrees.h
new file mode 100644
index 00000000000..3f6ebb977f9
--- /dev/null
+++ b/libcilkrts/runtime/pedigrees.h
@@ -0,0 +1,130 @@
+/* pedigrees.h -*-C++-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ **************************************************************************/
+
+#ifndef INCLUDED_PEDIGREES_DOT_H
+#define INCLUDED_PEDIGREES_DOT_H
+
+
+#include <cilk/common.h>
+#include <internal/abi.h>
+
+#include "rts-common.h"
+#include "global_state.h"
+#include "os.h"
+
+__CILKRTS_BEGIN_EXTERN_C
+
+/**
+ * @file pedigrees.h
+ *
+ * @brief pedigrees.h declares common routines related to pedigrees
+ * and the pedigree API.
+ */
+
+
+/**
+ * @brief Sets the leaf pedigree node for the current user thread.
+ *
+ * A typical implementation stores this pedigree node in thread-local
+ * storage.
+ *
+ * Preconditions:
+ * - Current thread should be a user thread.
+ *
+ * @param leaf The pedigree node to store as a leaf.
+ */
+COMMON_PORTABLE
+void __cilkrts_set_pedigree_leaf(__cilkrts_pedigree* leaf);
+
+
+/**
+ * Load the pedigree leaf node from thread-local storage into the
+ * current user worker. This method should execute as a part of
+ * binding the user thread to a worker.
+ *
+ * Preconditions:
+ *
+ * - w should be the worker for the current thread
+ * - w should be a user thread.
+ */
+COMMON_PORTABLE
+void load_pedigree_leaf_into_user_worker(__cilkrts_worker *w);
+
+/**
+ * Save the pedigree leaf node from the worker into thread-local
+ * storage. This method should execute as part of unbinding a user
+ * thread from a worker.
+ *
+ * Preconditions:
+ *
+ * - w should be the worker for the current thread
+ * - w should be a user thread.
+ */
+COMMON_PORTABLE
+void save_pedigree_leaf_from_user_worker(__cilkrts_worker *w);
+
+
+
+/**
+ * Update pedigree for a worker when leaving a frame.
+ *
+ * If this is the frame of a spawn helper (indicated by the
+ * CILK_FRAME_DETACHED flag) we must update the pedigree. The
+ * pedigree points to nodes allocated on the stack. Failing to
+ * update it will result in a accvio/segfault if the pedigree is
+ * walked. This must happen for all spawn helper frames, even if
+ * we're processing an exception.
+ */
+COMMON_PORTABLE
+inline void update_pedigree_on_leave_frame(__cilkrts_worker *w,
+ __cilkrts_stack_frame *sf)
+{
+ // Update the worker's pedigree information if this is an ABI 1 or later
+ // frame
+ if (CILK_FRAME_VERSION_VALUE(sf->flags) >= 1)
+ {
+ w->pedigree.rank = sf->spawn_helper_pedigree.rank + 1;
+ w->pedigree.parent = sf->spawn_helper_pedigree.parent;
+ }
+}
+
+
+
+__CILKRTS_END_EXTERN_C
+
+#endif // ! defined(INCLUDED_PEDIGREES_DOT_H)
diff --git a/libcilkrts/runtime/record-replay.cpp b/libcilkrts/runtime/record-replay.cpp
new file mode 100644
index 00000000000..bc5a79f2411
--- /dev/null
+++ b/libcilkrts/runtime/record-replay.cpp
@@ -0,0 +1,770 @@
+/* record-replay.cpp -*-C++-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2012-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ **************************************************************************/
+
+/*
+ * Implementation of the record/replay functionality for Cilk Plus
+ */
+
+#include <cstring>
+#include <vector>
+#include <stdlib.h>
+
+// clang is really strict about printf formats, so use the annoying integer
+// printf macros. Unfortunately they're not avaiable on Windows
+#ifdef _WIN32
+#define PRIu64 "llu"
+#else
+#define __STDC_FORMAT_MACROS 1
+#include <inttypes.h>
+#endif
+
+#include "record-replay.h"
+#include "bug.h"
+#include "internal/abi.h"
+#include "local_state.h"
+#include "full_frame.h"
+#include "global_state.h"
+#include "cilk_malloc.h"
+#include "os.h" // for cilkos_error()
+
+#if RECORD_ON_REPLAY
+#pragma message ("*** Record on Replay is enabled!")
+#endif
+
+// Defined to write sequence number to the logs. Note that you cannot
+// diff logs with sequence numbers because the numbers may increment in
+// different orders.
+//#define INCLUDE_SEQUENCE_NUMBER 1
+
+const int PED_VERSION = 1; // Log recording version
+
+// Log types
+enum ped_type_t
+{
+ ped_type_unknown,
+ ped_type_steal,
+ ped_type_sync,
+ ped_type_orphaned,
+ ped_type_last // Flags end of the list
+};
+
+// Log type strings
+#define PED_TYPE_STR_STEAL "Steal"
+#define PED_TYPE_STR_SYNC "Sync"
+#define PED_TYPE_STR_WORKERS "Workers"
+#define PED_TYPE_STR_ORPHANED "Orphaned"
+
+#define PED_TYPE_SIZE 16 // Buffer size for the type of pedigree. Must
+ // hold largest pedigree record type string.
+#define PEDIGREE_BUFF_SIZE 512 // Buffer size for the string representation
+ // of a pedigree.
+
+/**
+ * Data we store for a replay log entry
+ */
+typedef struct replay_entry_t
+{
+ uint64_t *m_reverse_pedigree; /**< Reverse pedigree for replay log entry */
+ ped_type_t m_type; /**< Type of replay log entry */
+ int16_t m_pedigree_len; /**< Number of terms in reverse pedigree */
+ int16_t m_value; /**< Victim for STEALs, 0 if matching steal found for ORPHANs */
+
+ /**
+ * Load data read from the log into the entry
+ */
+ bool load(const char *type, const char *pedigee_str, int32_t value1, int32_t value2)
+ {
+ // Convert the type into an enum
+ if (0 == strcmp(type, PED_TYPE_STR_STEAL))
+ {
+ m_type = ped_type_steal;
+ m_value = (int16_t)value1; // Victim
+ }
+ else
+ {
+ m_value = -1; // Victim not valid
+ if (0 == strcmp(type, PED_TYPE_STR_SYNC))
+ m_type = ped_type_sync;
+ else if (0 == strcmp(type, PED_TYPE_STR_ORPHANED))
+ m_type = ped_type_orphaned;
+ else
+ {
+ m_type = ped_type_unknown;
+ return false;
+ }
+ }
+
+ // Parse the pedigree
+ m_pedigree_len = 0;
+
+ const char *p = pedigee_str;
+ char *end;
+
+ uint64_t temp_pedigree[PEDIGREE_BUFF_SIZE/2];
+
+ while(1)
+ {
+ temp_pedigree[m_pedigree_len++] = (uint64_t)strtol(p, &end, 10);
+ if ('\0' == *end)
+ break;
+ p = end + 1;
+ }
+
+ // Allocate memory to hold the pedigree.
+ // Copy the pedigree in reverse order since that's the order we'll
+ // traverse it
+ m_reverse_pedigree =
+ (uint64_t *)__cilkrts_malloc(sizeof(int64_t) * m_pedigree_len);
+ for (int n = 0; n < m_pedigree_len; n++)
+ m_reverse_pedigree[n] = temp_pedigree[(m_pedigree_len - 1) - n];
+
+ return true;
+ }
+
+ /**
+ * Match this entry against the data supplied. This includes walking the
+ * pedigree from the specified node.
+ */
+ bool match (ped_type_t type, const __cilkrts_pedigree *node, int victim = -1)
+ {
+ int i = 0;
+
+ // If the type isn't what they're seeking, we don't have a match
+ if (type != m_type)
+ return false;
+
+ // If we're looking for a STEAL, then the victim must match
+ if ((type == ped_type_steal) && (victim != m_value))
+ return false;
+
+ // Compare the current pedigree against what was recorded
+ while ((NULL != node) && (i < m_pedigree_len))
+ {
+ // If we've got a pedigree rank difference, then we don't have
+ // a match
+ if (node->rank != m_reverse_pedigree[i])
+ return false;
+ node = node->parent;
+ i++;
+ }
+
+ // Make sure we exhausted both the pedigree chain and the recorded
+ // pedigree
+ return ((NULL == node) && (i == m_pedigree_len));
+ }
+
+ /**
+ * Advance to the next entry, skipping any ORPHANED records we didn't see
+ * a matching STEAL for
+ */
+ replay_entry_t *next_entry()
+ {
+ replay_entry_t *entry = this;
+
+ // You can't go beyond the end
+ if (ped_type_last == entry->m_type)
+ return entry;
+
+ // Advance to the next entry
+ entry++;
+
+ // Skip any ORPHANED records that don't have a matching steal. We
+ // initialized the value field to -1 for ORPHANED. After loading all
+ // the log data, we iterated through all the STEAL records setting the
+ // matching ORPHANED record's value field to 0. So if an ORPHANED
+ // record's value field is still -1, it doesn't have a matching STEAL
+ // record, and I don't know why we chose not to return from the
+ // spawned function.
+ while ((ped_type_orphaned == entry->m_type) && (-1 == entry->m_value))
+ {
+ entry++;
+ }
+
+ return entry;
+ }
+
+ /**
+ * Release any allocated resources
+ */
+ void unload()
+ {
+ __cilkrts_free(m_reverse_pedigree);
+ m_reverse_pedigree = NULL;
+ }
+
+} replay_entry_t;
+
+__CILKRTS_BEGIN_EXTERN_C
+
+/**
+ * Walk the pedigree and generate a string representation with underscores
+ * between terms. Currently does a recursive walk to generate a forward
+ * pedigree.
+ *
+ * @param p The buffer that is to be filled. Assumed to be PEDIGREE_BUFF_SIZE
+ * characters long
+ * @param pnode The initial pedigree term to be written.
+ *
+ * @return A pointer into the pedigree string buffer after a term has been
+ * written.
+ */
+static
+char * walk_pedigree_nodes(char *p, const __cilkrts_pedigree *pnode)
+{
+ CILK_ASSERT(pnode);
+ if (pnode->parent)
+ {
+ p = walk_pedigree_nodes(p, pnode->parent);
+ p += sprintf(p, "_");
+ }
+
+ return p + sprintf(p, "%" PRIu64, pnode->rank);
+}
+
+/**
+ * Write a record to a replay log file.
+ *
+ * @param w The worker we're writing the pedigree for.
+ * @param type The type of the pedigree record, as a string
+ * @param initial_node The initial pedigree node to be written, or NULL if
+ * there is no pedigree for this record type.
+ * @param i1 First integer value to be written to the record.
+ * @param i2 Second integer value to be written to the record. Only applies
+ * to STEAL records. Defaults to -1 (unused). The second value is always
+ * written to make parsing easier.
+ */
+static
+void write_to_replay_log (__cilkrts_worker *w, const char *type,
+ const __cilkrts_pedigree *initial_node,
+ int i1 = -1, int i2 = -1)
+{
+ char pedigree[PEDIGREE_BUFF_SIZE];
+
+ // If we don't have an initial pedigree node, just use "0" to fill the slot
+ if (NULL == initial_node)
+ strcpy(pedigree, "0");
+ else
+ walk_pedigree_nodes(pedigree, initial_node);
+
+#ifndef INCLUDE_SEQUENCE_NUMBER
+ // Simply write the record
+ fprintf(w->l->record_replay_fptr, "%s %s %d %d\n",
+ type, pedigree, i1, i2);
+#else
+ // Write the record with a sequence number. The sequence number should
+ // always be the last term, and ignored on read
+
+ static long volatile seq_num = 0;
+ long write_num;
+
+ // Atomic increment functions are compiler/OS-specific
+#ifdef _WIN32
+ write_num = _InterlockedIncrement(&seq_num);
+#else /* GCC */
+ write_num = __sync_add_and_fetch(&seq_num, 1);
+#endif // _WIN32
+
+ fprintf(w->l->record_replay_fptr, "%s %s %d %d %ld\n",
+ type, pedigree, i1, i2, write_num);
+#endif // INCLUDE_SEQUENCE_NUMBER
+
+ fflush(w->l->record_replay_fptr);
+}
+
+/**
+ * Record data for a successful steal.
+ *
+ * The pedigree for a STEAL record is the pedigree of the stolen frame.
+ *
+ * @note It's assumed that replay_record_steal() has already checked that we're
+ * recording a log and that the record/replay functionality has not been
+ * compiled out.
+ *
+ * @param w The worker stealing a frame.
+ * @param victim_id The ID of the worker which had it's frame stolen.
+ */
+void replay_record_steal_internal(__cilkrts_worker *w, int32_t victim_id)
+{
+ // Follow the pedigree chain using worker's stack frame
+ CILK_ASSERT(w->l->next_frame_ff);
+ CILK_ASSERT(w->l->next_frame_ff->call_stack);
+
+ // Record steal: STEAL pedigree victim_id thief_id
+ write_to_replay_log (w, PED_TYPE_STR_STEAL,
+ &(w->l->next_frame_ff->call_stack->parent_pedigree),
+ victim_id);
+}
+
+/**
+ * Record data for the worker that continues from a sync
+ *
+ * The pedigree for a SYNC record is the pedigree at the sync.
+ *
+ * @note It's assumed that replay_record_sync() has already checked that we're
+ * recording a log and that the record/replay functionality has not been
+ * compiled out.
+ *
+ * @param w The worker continuing from a sync.
+ */
+void replay_record_sync_internal(__cilkrts_worker *w)
+{
+ // Record sync: SYNC pedigree last_worker_id
+ write_to_replay_log (w, PED_TYPE_STR_SYNC, &w->pedigree);
+}
+
+/**
+ * Record the pedigree of an attempt to return to a stolen parent
+ *
+ * The pedigree for an ORPHANED record is the pedigree of our parent
+ *
+ * @note It's assumed that replay_record_orphaned() has already checked that
+ * we're recording a log and that the record/replay functionality has not
+ * been compiled out.
+ *
+ * @param w The worker continuing noting that it has been orphaned.
+ */
+void replay_record_orphaned_internal(__cilkrts_worker *w)
+{
+ // Record steal: ORPHANED pedigree self
+ write_to_replay_log (w, PED_TYPE_STR_ORPHANED, w->pedigree.parent);
+}
+
+/**
+ * Attempt to match a SYNC record. We have a match when this worker was
+ * recorded returning from the current call to __cilkrts_sync() with the
+ * same pedigree and this was the worker that continued from the sync, since
+ * it was the last to sync.
+ *
+ * If we find a match, the caller is expected to stall it is the last worker
+ * to reach a sync so it will be the worker to continue from the sync.
+ *
+ * @note It's assumed that replay_match_sync_pedigree() has already returned
+ * if we're not replaying a log, or if record/replay functionality has
+ * been compiled out.
+ *
+ * @param w The worker we're checking to see if we've got a match
+ */
+int replay_match_sync_pedigree_internal(__cilkrts_worker *w)
+{
+ // Return true if we have a match
+ if (w->l->replay_list_entry->match(ped_type_sync, &w->pedigree))
+ return 1;
+ else
+ return 0;
+}
+
+/**
+ * Advance to the next log entry from a SYNC record. Consume the current
+ * SYNC record on this worker and advance to the next one.
+ *
+ * @note It's assumed that replay_advance_from_sync() has already returned if
+ * we're not replaying a log, or if record/replay functionality has been
+ * compiled out.
+ *
+ * @param w The worker whose replay log we're advancing.
+ */
+void replay_advance_from_sync_internal (__cilkrts_worker *w)
+{
+ // The current replay entry must be a SYNC
+ CILK_ASSERT(ped_type_sync == w->l->replay_list_entry->m_type);
+
+ // Advance to the next entry
+ w->l->replay_list_entry = w->l->replay_list_entry->next_entry();
+}
+
+/**
+ * Called from random_steal() to override the ID of the randomly chosen victim
+ * worker which this worker will attempt to steal from. Returns the worker id
+ * of the next victim this worker was recorded stealing from, or -1 if the
+ * next record in the log is not a STEAL.
+ *
+ * @note This call does NOT attempt to match the pedigree. That will be done
+ * by replay_match_victim_pedigree() after random_steal() has locked the victim
+ * worker.
+ *
+ * @param w The __cilkrts_worker we're executing on. The worker's replay log
+ * is checked for a STEAL record. If we've got one, the stolen worker ID is
+ * returned.
+ *
+ * @return -1 if the next record is not a STEAL
+ * @return recorded stolen worker ID if we've got a matching STEAL record
+ */
+int replay_get_next_recorded_victim_internal(__cilkrts_worker *w)
+{
+ // If the next record isn't a STEAL, abort the attempt to steal work
+ if (ped_type_steal != w->l->replay_list_entry->m_type)
+ return -1;
+
+ // Return the victim's worker ID from the STEAL record. We'll check
+ // the pedigree after random_steal has locked the victim worker.
+ return w->l->replay_list_entry->m_value;
+}
+
+/**
+ * Called from random_steal() to determine if we have a STEAL record that
+ * matches the pedigree at the head of the victim worker. If we do have a
+ * match, the STEAL record is consumed.
+ *
+ * @note It's assumed that replay_match_victim_pedigree() has already returned if
+ * we're not replaying a log, or if record/replay functionality has been
+ * compiled out.
+ *
+ * @return 1 if we have a match
+ * @return 0 if the current replay record isn't a STEAL record, or the victim
+ * isn't correct, or the pedigree doesn't match.
+ */
+int replay_match_victim_pedigree_internal(__cilkrts_worker *w, __cilkrts_worker *victim)
+{
+ // If we don't have a match, return 0
+ if (! w->l->replay_list_entry->match(ped_type_steal,
+ &((*victim->head)->parent_pedigree),
+ victim->self))
+ return 0;
+
+ // Consume this entry
+ w->l->replay_list_entry = w->l->replay_list_entry->next_entry();
+
+ // Return success
+ return 1;
+}
+
+/**
+ * If the frame we're about to return to was recorded as being stolen,
+ * stall until it is.
+ *
+ * @note It's assumed that replay_wait_for_steal_if_parent_was_stolen() has
+ * already returned if we're not replaying a log, or if record/replay
+ * functionality has been compiled out.
+ *
+ * @param w The worker we're executing on.
+ */
+void replay_wait_for_steal_if_parent_was_stolen_internal(__cilkrts_worker *w)
+{
+ // If our parent wasn't recorded orphanen, return now
+ if (! w->l->replay_list_entry->match (ped_type_orphaned,
+ w->pedigree.parent))
+ return;
+
+ // Stall until our parent is stolen. Note that we're comparing head
+ // and tail, not head and exc. The steal is not completed until tail
+ // is modified.
+ while (!((w->tail - 1) < w->head))
+ __cilkrts_sleep();
+
+ // Consume the entry
+ w->l->replay_list_entry = w->l->replay_list_entry->next_entry();
+}
+
+/**
+ * Allocate memory for the list of logged events.
+ *
+ * This function will read through the file and count the number of records
+ * so it can estimate how big a buffer to allocate for the array or replay
+ * entries. It will then rewind the file to the beginning so it can be
+ * loaded into memory.
+ *
+ * @param w The worker we're loading the file for.
+ * @param f The file of replay data we're scanning.
+ */
+static
+void allocate_replay_list(__cilkrts_worker *w, FILE *f)
+{
+ // Count the number of entries - yeah, it's a hack, but it lets me
+ // allocate the space all at once instead of in chunks
+ char buf[1024];
+ int entries = 1; // Include "LAST" node
+
+ while (! feof(f))
+ {
+ if (fgets(buf, 1024, f))
+ {
+ // Skip the Workers record - should only be in file for Worker 0
+ if (0 != strncmp(PED_TYPE_STR_WORKERS, buf, sizeof(PED_TYPE_STR_WORKERS)-1))
+ entries++;
+ }
+ }
+
+ w->l->replay_list_root =
+ (replay_entry_t *)__cilkrts_malloc(entries * sizeof(replay_entry_t));
+ w->l->replay_list_root[entries - 1].m_type = ped_type_last;
+
+ // Reset the file to the beginning
+ rewind(f);
+}
+
+/**
+ * Load the replay log for a worker into memory.
+ *
+ * @param w The worker we're loading the replay for.
+ */
+static
+void load_recorded_log(__cilkrts_worker *w)
+{
+ char ped_type[PED_TYPE_SIZE];
+ char ped_str[PEDIGREE_BUFF_SIZE];
+ int32_t i1 = -1, i2 = -1;
+ int fret;
+ char local_replay_file_name[512];
+ FILE *f;
+
+ // Open the log for reading
+ sprintf(local_replay_file_name, "%s%d.cilklog", w->g->record_replay_file_name, w->self);
+ f = fopen(local_replay_file_name, "r");
+
+ // Make sure we found a log!
+ CILK_ASSERT (NULL != f);
+
+ // Initialize the replay_list
+ allocate_replay_list(w, f);
+ replay_entry_t *entry = w->l->replay_list_root;
+
+ // Read the data out and add it to our tables
+ while (! feof(f))
+ {
+#ifndef INCLUDE_SEQUENCE_NUMBER
+ fret = fscanf(f, "%s %s %d %d\n", ped_type, ped_str, &i1, &i2);
+ if(EOF == fret)
+ break;
+
+ // We must have read 4 fields
+ CILK_ASSERT(4 == fret);
+#else
+ int32_t write_num;
+ fret = fscanf(f, "%s %s %d %d %d\n", ped_type, ped_str,
+ &i1, &i2, &write_num);
+ if(EOF == fret)
+ break;
+
+ // We must have read 5 fields
+ CILK_ASSERT(5 == fret);
+#endif // INCLUDE_SEQUENCE_NUMBER
+
+ // Load the data into the entry
+ if (0 == strcmp(ped_type, PED_TYPE_STR_WORKERS))
+ {
+ // Verify we're replaying with the same number of workers we recorded with
+ if (i1 != w->g->P)
+ {
+ // Fatal error - does not return
+ cilkos_error("Cannot continue replay: number of workers(%d) doesn't match "
+ "that from the recording(%d).\n", w->g->P, i1);
+ }
+
+ // Verify that we understand this version of the pedigree file
+ if (PED_VERSION != i2)
+ {
+ // Fatal error - does not return
+ cilkos_error("Pedigree file version %d doesn't match current "
+ "version %d - cannot continue.\n",
+ i2, PED_VERSION);
+ }
+ }
+ else
+ {
+ entry->load(ped_type, ped_str, i1, i2);
+ entry++;
+ }
+ }
+
+ // Make sure we've filled the allocated memory. We initialized the last
+ // entry in
+ CILK_ASSERT(ped_type_last == entry->m_type);
+ w->l->replay_list_entry = w->l->replay_list_root;
+
+ // Close the log and return
+ fclose(f);
+}
+
+/**
+ * Scan a recorded log to match STEALs againsted ORPHANED records.
+ *
+ * @param g Cilk Runtime global state. Passed to access the worker array so
+ * we can scan a worker's ORPHANED entries for one that matches a STEAL entry.
+ * @param entry The root of a replay_list for a worker.
+ */
+static
+void scan_for_matching_steals(global_state_t *g, replay_entry_t *entry)
+{
+ // Iterate over all of the entries
+ while (ped_type_last != entry->m_type)
+ {
+ // Look for STEALs. That will tell us which worker the frame was
+ // stolen from
+ if (ped_type_steal == entry->m_type)
+ {
+ bool found = false;
+
+ // Validate the worker ID and make sure we've got a list
+ CILK_ASSERT((entry->m_value >= 0) && (entry->m_value < g->total_workers));
+ replay_entry_t *victim_entry = g->workers[entry->m_value]->l->replay_list_root;
+ CILK_ASSERT(NULL != victim_entry);
+
+ // Scan the victim's list for the matching ORPHANED record
+ while ((ped_type_last != victim_entry->m_type) && ! found)
+ {
+ if (ped_type_orphaned == victim_entry->m_type)
+ {
+ if (entry->m_pedigree_len == victim_entry->m_pedigree_len)
+ {
+ if (0 == memcmp(entry->m_reverse_pedigree,
+ victim_entry->m_reverse_pedigree,
+ entry->m_pedigree_len * sizeof(int64_t)))
+ {
+ // Note that this ORPHANED record has a matching steal
+ victim_entry->m_value = 0;
+ found = true;
+ }
+ }
+ }
+ victim_entry++;
+ }
+ }
+ entry++;
+ }
+}
+
+
+/*
+ * Initialize per-worker data for record or replay - See record-replay.h
+ * for full routine header.
+ */
+void replay_init_workers(global_state_t *g)
+{
+ int i;
+ char worker_file_name[512];
+
+ // If we're not recording or replaying a log, we're done. All of the
+ // fields in the global_state_t or local_state_t are already initialized
+ // to default values.
+ if (RECORD_REPLAY_NONE == g->record_or_replay)
+ return;
+
+ // If we're replaying a log, read each worker's log and construct the
+ // in-memory log
+ if (REPLAY_LOG == g->record_or_replay)
+ {
+ // Read all of the data
+ for (i = 0; i < g->total_workers; ++i)
+ {
+ // This function will also initialize and fill the worker's
+ // replay list
+ load_recorded_log(g->workers[i]);
+ }
+
+ // Scan for orphans with no matching steal. Mark them so they'll be
+ // skipped as we advance through the log.
+ for (i = 0; i < g->total_workers; ++i)
+ {
+ scan_for_matching_steals(g, g->workers[i]->l->replay_list_root);
+ }
+
+ // If we're recording the logs while replaying, create the log files.
+ // This will only be used for debugging. Create the logs in the
+ // current directory. It should be as good a place as any...
+#if RECORD_ON_REPLAY
+ for(i = 0; i < g->total_workers; ++i)
+ {
+ __cilkrts_worker *w = g->workers[i];
+ sprintf(worker_file_name, "replay_log_%d.cilklog", w->self);
+ w->l->record_replay_fptr = fopen(worker_file_name, "w+");
+ CILK_ASSERT(NULL != w->l->record_replay_fptr);
+ }
+
+ // Record the number of workers, file version in Worker 0's file
+ write_to_replay_log (g->workers[0], PED_TYPE_STR_WORKERS, NULL, g->P, PED_VERSION);
+#endif // RECORD_ON_REPLAY
+ }
+
+ // If we're recording, create the log files
+ if (RECORD_LOG == g->record_or_replay)
+ {
+ for(i = 0; i < g->total_workers; ++i)
+ {
+ __cilkrts_worker *w = g->workers[i];
+ sprintf(worker_file_name, "%s%d.cilklog",
+ g->record_replay_file_name,
+ w->self);
+ w->l->record_replay_fptr = fopen(worker_file_name, "w+");
+ CILK_ASSERT(NULL != w->l->record_replay_fptr);
+ }
+
+ // Record the number of workers, file version in Worker 0's file
+ write_to_replay_log (g->workers[0], PED_TYPE_STR_WORKERS, NULL, g->P, PED_VERSION);
+ }
+}
+
+/*
+ * Do any necessary cleanup for the logs - See record-replay.h for full
+ * routine header.
+ */
+void replay_term(global_state_t *g)
+{
+ // Free memory for the record/replay log file name, if we've got one
+ if (g->record_replay_file_name)
+ __cilkrts_free(g->record_replay_file_name);
+
+ // Per-worker cleanup
+ for(int i = 0; i < g->total_workers; ++i)
+ {
+ __cilkrts_worker *w = g->workers[i];
+
+ // Close the log files, if we've opened them
+ if(w->l->record_replay_fptr)
+ fclose(w->l->record_replay_fptr);
+
+ if (w->l->replay_list_root)
+ {
+ // We should have consumed the entire list
+ CILK_ASSERT(ped_type_last == w->l->replay_list_entry->m_type);
+
+ replay_entry_t *entry = w->l->replay_list_root;
+ while (ped_type_last != entry->m_type)
+ {
+ // Free the pedigree memory for each entry
+ entry->unload();
+ entry++;
+ }
+ __cilkrts_free(w->l->replay_list_root);
+ w->l->replay_list_root = NULL;
+ w->l->replay_list_entry = NULL;
+ }
+ }
+}
+
+__CILKRTS_END_EXTERN_C
diff --git a/libcilkrts/runtime/record-replay.h b/libcilkrts/runtime/record-replay.h
new file mode 100644
index 00000000000..c1c5a68f579
--- /dev/null
+++ b/libcilkrts/runtime/record-replay.h
@@ -0,0 +1,432 @@
+/* record_replay.h -*-C++-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2012-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ **************************************************************************/
+
+/**
+ * @file record-replay.h
+ *
+ * @brief record-replay.h and .cpp encapsulate most of the functionality to
+ * record and play back a Cilk Plus application.
+ *
+ * Recording is directed by the setting of the CILK_RECORD_LOG environment
+ * variable. If it's defined, the value specifies the root we'll use to
+ * generate files for each worker using the following format string:
+ * "%s%d.cilklog", where the integer is the value of w->self.
+ *
+ * Replay is directed by the setting of the CILK_REPLAY_LOG environment
+ * variable, interpreted the same way as CILK_RECORD_LOG. If both
+ * CILK_RECORD_LOG and CILK_REPLAY_LOG are defined, a warning will be given
+ * and the attempt to record a log will be ignored.
+ *
+ * Recording is relatively straightforward. We write all information about a
+ * worker to a per-worker file.
+ *
+ * Each pedigree record consists of the following fields. All fields must be
+ * present in every record to make parsing easy.
+ * - Type - A string identifying the pedigree record. See the PED_TYPE_STR_
+ * macros for the currently defined values.
+ * - Pedigree - A string of pedigree values, with underscores between
+ * adjacent values.
+ * - i1 - Record type-specific value. -1 if not used.
+ * - i2 - Record type-specific value. -1 if not used.
+ *
+ * WORKERS record - only written to the file for worker 0. Note that this is
+ * the first worker in the workers array. Worker 0 is the first system worker,
+ * *NOT* a user worker.
+ * - Type: "Workers"
+ * - Pedigree: Always "0" - ignored
+ * - i1: Number of workers (g->P) when we recorded the log. A mismatch when
+ * we attempt to replay the log will result in aborting the execution.
+ * - i2: Log version number - Specified by PED_VERSION in record-replay.cpp
+ *
+ * STEAL record - written after a successful steal.
+ * - Type: "Steal"
+ * - Pedigree: Pedigree of stolen frame
+ * - i1: Worker the frame was stolen from
+ * - i2: -1
+ *
+ * SYNC record - written after a worker continues from a sync.
+ * - Type: "Sync"
+ * - Pedigree: Pedigree of sync. Note that this is the pedigree *before*
+ * the pedigree in incremented in setup_for_execution_pedigree().
+ * - i1: -1
+ * - i2: -1
+ *
+ * ORPHANED record - saved on a return to a stolen parent.
+ * - Type: "Orphaned"
+ * - Pedigree: Pedigree of the parent frame *before* the pedigree is
+ * incremented by the return
+ * - i1: -1
+ * - i2: -1
+ *
+ * On replay, the data is loaded into a per-worker array, and the data is
+ * consumed in order as needed.
+ */
+
+#ifndef INCLUDED_RECORD_REPLAY_DOT_H
+#define INCLUDED_RECORD_REPLAY_DOT_H
+
+#include "cilk/common.h"
+#include "global_state.h"
+
+/**
+ * Define CILK_RECORD_REPLAY to enable record/replay functionality. If
+ * CILK_RECORD_REPLAY is not defined, all of the record/replay functions in
+ * record-replay.h will be stubbed out. Since they're declared as inline,
+ * functions, the resulting build should have no performance impact due to
+ * the implementation or record/replay.
+ */
+ #define CILK_RECORD_REPLAY 1
+
+/**
+ * Define RECORD_ON_REPLAY=1 to write logs when we're replaying a log. This
+ * should only be needed when debugging the replay functionality. This should
+ * always be defined as 0 when record-replay.h is checked in.
+ */
+#define RECORD_ON_REPLAY 0
+
+__CILKRTS_BEGIN_EXTERN_C
+
+#ifdef CILK_RECORD_REPLAY
+// Declarations of internal record/replay functions. The inlined versions
+// further down do some preliminary testing (like if we're not recording or
+// replaying) and will stub out the functionality if we've compiled out the
+// record/replay feature
+int replay_match_sync_pedigree_internal(__cilkrts_worker *w);
+void replay_wait_for_steal_if_parent_was_stolen_internal(__cilkrts_worker *w);
+void replay_record_steal_internal(__cilkrts_worker *w, int32_t victim_id);
+void replay_record_sync_internal(__cilkrts_worker *w);
+void replay_record_orphaned_internal(__cilkrts_worker *w);
+int replay_match_victim_pedigree_internal(__cilkrts_worker *w, __cilkrts_worker *victim);
+void replay_advance_from_sync_internal (__cilkrts_worker *w);
+int replay_get_next_recorded_victim_internal(__cilkrts_worker *w);
+#endif // CILK_RECORD_REPLAY
+
+// Publically defined record/replay API
+
+/**
+ * If we're replaying a log, wait for our parent to be stolen if it was when
+ * the log was recorded. If record/replay is compiled out, this is a noop.
+ *
+ * @param w The __cilkrts_worker we're executing on. The worker's replay
+ * list will be checked for a ORPHANED record with a matching pedigree. If
+ * there is a match, the ORPHANED record will be consumed.
+ */
+#ifdef CILK_RECORD_REPLAY
+__CILKRTS_INLINE
+void replay_wait_for_steal_if_parent_was_stolen(__cilkrts_worker *w)
+{
+ // Only check if we're replaying a log
+ if (REPLAY_LOG == w->g->record_or_replay)
+ replay_wait_for_steal_if_parent_was_stolen_internal(w);
+}
+#else
+__CILKRTS_INLINE
+void replay_wait_for_steal_if_parent_was_stolen(__cilkrts_worker *w)
+{
+ // If record/replay is disabled, we never wait
+}
+#endif // CILK_RECORD_REPLAY
+
+/**
+ * Called from random_steal() to override the ID of the randomly chosen victim
+ * worker which this worker will attempt to steal from. Returns the worker id
+ * of the next victim this worker was recorded stealing from, or -1 if the
+ * next record in the log is not a STEAL.
+ *
+ * @note This call does NOT attempt to match the pedigree. That will be done
+ * by replay_match_victim_pedigree() after random_steal() has locked the victim
+ * worker.
+ *
+ * @param w The __cilkrts_worker we're executing on. The worker's replay log
+ * is checked for a STEAL record. If we've got one, the stolen worker ID is
+ * returned.
+ * @param id The randomly chosen victim worker ID. If we're not replaying a
+ * log, or if record/replay has been compiled out, this is the value that
+ * will be returned.
+ *
+ * @return id if we're not replaying a log
+ * @return -1 if the next record is not a STEAL
+ * @return recorded stolen worker ID if we've got a matching STEAL record
+ */
+#ifdef CILK_RECORD_REPLAY
+__CILKRTS_INLINE
+int replay_get_next_recorded_victim(__cilkrts_worker *w, int id)
+{
+ // Only check if we're replaying a log
+ if (REPLAY_LOG == w->g->record_or_replay)
+ return replay_get_next_recorded_victim_internal(w);
+ else
+ return id;
+}
+#else
+__CILKRTS_INLINE
+int replay_get_next_recorded_victim(__cilkrts_worker *w, int id)
+{
+ // Record/replay is disabled. Always return the original worker id
+ return id;
+}
+#endif // CILK_RECORD_REPLAY
+
+/**
+ * Initialize per-worker data for record/replay. A noop if record/replay
+ * is disabled, or if we're not recording or replaying anything.
+ *
+ * If we're recording a log, this will ready us to create the per-worker
+ * logs.
+ *
+ * If we're replaying a log, this will read the logs into the per-worker
+ * structures.
+ *
+ * @param g Cilk runtime global state
+ */
+void replay_init_workers(global_state_t *g);
+
+/**
+ * Record a record on a successful steal. A noop if record/replay is
+ * diabled, or if we're not recording anything
+ *
+ * @param w The __cilkrts_worker we're executing on. The pedigree of
+ * the stolen frame will be walked to generate the STEAL record.
+ *
+ * @param victim_id The worker ID of the worker w stole from.
+ */
+#ifdef CILK_RECORD_REPLAY
+__CILKRTS_INLINE
+void replay_record_steal(__cilkrts_worker *w, int32_t victim_id)
+{
+#if RECORD_ON_REPLAY
+ // If we're recording on replay, write the record if we're recording or
+ // replaying
+ if (RECORD_REPLAY_NONE == w->g->record_or_replay)
+ return;
+#else
+ // Only write the record if we're recording
+ if (RECORD_LOG != w->g->record_or_replay)
+ return;
+#endif
+
+ replay_record_steal_internal(w, victim_id);
+}
+#else
+__CILKRTS_INLINE
+void replay_record_steal(__cilkrts_worker *w, int32_t victim_id)
+{
+}
+#endif // CILK_RECORD_REPLAY
+
+/**
+ * Record a record when continuing after a sync. A noop if record/replay is
+ * diabled, or if we're not recording anything, or if the sync was abandoned,
+ * meaning this isn't the worker that continues from the sync.
+ *
+ * @param w The __cilkrts_worker for we're executing on. The pedigree of
+ * the sync-ing frame will be walked to generate the SYNC record.
+ *
+ * @param continuing True if this worker will be continuing from the
+ * cilk_sync. A SYNC record will only be generated if continuing is true.
+ */
+#ifdef CILK_RECORD_REPLAY
+__CILKRTS_INLINE
+void replay_record_sync(__cilkrts_worker *w, int continuing)
+{
+ // If this was not the last worker to the syn, return
+ if (! continuing)
+ return;
+
+#if RECORD_ON_REPLAY
+ // If we're recording on replay, write the record if we're recording or
+ // replaying
+ if (RECORD_REPLAY_NONE == w->g->record_or_replay)
+ return;
+#else
+ // Only write the record if we're recording
+ if (RECORD_LOG != w->g->record_or_replay)
+ return;
+#endif
+
+ replay_record_sync_internal(w);
+}
+#else
+__CILKRTS_INLINE
+void replay_record_sync(__cilkrts_worker *w, int abandoned)
+{
+}
+#endif // CILK_RECORD_REPLAY
+
+/**
+ * Record a record on a return to a stolen parent. A noop if record/replay is
+ * diabled, or if we're not recording anything.
+ *
+ * @param w The __cilkrts_worker for we're executing on. The pedigree of the
+ * frame that has discovered that its parent has been stolken will be walked
+ * to generate the ORPHANED record.
+ */
+#ifdef CILK_RECORD_REPLAY
+__CILKRTS_INLINE
+void replay_record_orphaned(__cilkrts_worker *w)
+{
+#if RECORD_ON_REPLAY
+ // If we're recording on replay, write the record if we're recording or
+ // replaying
+ if (RECORD_REPLAY_NONE == w->g->record_or_replay)
+ return;
+#else
+ // Only write the record if we're recording
+ if (RECORD_LOG != w->g->record_or_replay)
+ return;
+#endif
+
+ replay_record_orphaned_internal(w);
+}
+#else
+__CILKRTS_INLINE
+void replay_record_orphaned(__cilkrts_worker *w)
+{
+}
+#endif // CILK_RECORD_REPLAY
+
+/**
+ * Test whether the frame at the head of the victim matches the pedigree of
+ * the frame that was recorded being stolen. Called in random steal to verify
+ * that we're about to steal the correct frame.
+ *
+ * @param w The __cilkrts_worker for we're executing on. The current worker
+ * is needed to find the replay entry to be checked.
+ *
+ * @param victim The __cilkrts_worker for we're proposing to steal a frame
+ * from. The victim's head entry is
+ * is needed to find the replay entry to be checked.
+ *
+ * @return 0 if we're replaying a log and the victim's pedigree does NOT match
+ * the next frame the worker is expected to steal.
+ *
+ * @return 1 in all other cases to indicate that the steal attempt should
+ * continue
+ */
+#ifdef CILK_RECORD_REPLAY
+__CILKRTS_INLINE
+int replay_match_victim_pedigree(__cilkrts_worker *w, __cilkrts_worker *victim)
+{
+ // We're not replaying a log. The victim is always acceptable
+ if (REPLAY_LOG != w->g->record_or_replay)
+ return 1;
+
+ // Return 1 if the victim's pedigree matches the frame the worker stole
+ // when we recorded the log
+ return replay_match_victim_pedigree_internal(w, victim);
+}
+#else
+__CILKRTS_INLINE
+int replay_match_victim_pedigree(__cilkrts_worker *w, __cilkrts_worker *victim)
+{
+ // Record/replay is disabled. The victim is always acceptable
+ return 1;
+}
+#endif // CILK_RECORD_REPLAY
+
+/**
+ * Test whether the current replay entry is a sync record matching the
+ * worker's pedigree.
+ *
+ * @param w The __cilkrts_worker for we're executing on.
+ *
+ * @return 1 if the current replay entry matches the current pedigree.
+ * @return 0 if there's no match, or if we're not replaying a log.
+ */
+#ifdef CILK_RECORD_REPLAY
+__CILKRTS_INLINE
+int replay_match_sync_pedigree(__cilkrts_worker *w)
+{
+ // If we're not replaying, assume no match
+ if (REPLAY_LOG != w->g->record_or_replay)
+ return 0;
+
+ return replay_match_sync_pedigree_internal(w);
+}
+#else
+__CILKRTS_INLINE
+int replay_match_sync_pedigree(__cilkrts_worker *w)
+{
+ // Record/replay is disabled. Assume no match
+ return 0;
+}
+#endif
+
+/**
+ * Marks a sync record seen, advancing to the next record in the replay list.
+ *
+ * This function will only advance to the next record if:
+ * - Record/replay hasn't been compiled out AND
+ * - We're replaying a log AND
+ * - A match was found AND
+ * - The sync is not being abandoned
+ *
+ * @param w The __cilkrts_worker for we're executing on.
+ * @param match_found The value returned by replay_match_sync_pedigree(). If
+ * match_found is false, nothing is done.
+ * @param continuing Flag indicating whether this worker will continue from
+ * the sync (it's the last worker to the sync) or if it will abandon the work
+ * and go to the scheduling loop to look for more work it can steal.
+ */
+#ifdef CILK_RECORD_REPLAY
+__CILKRTS_INLINE
+void replay_advance_from_sync(__cilkrts_worker *w, int match_found, int continuing)
+{
+ // If we're replaying a log, and the current sync wasn't abandoned, and we
+ // found a match in the log, mark the sync record seen.
+ if ((REPLAY_LOG == w->g->record_or_replay) && match_found && continuing)
+ replay_advance_from_sync_internal(w);
+}
+#else
+__CILKRTS_INLINE
+void replay_advance_from_sync(__cilkrts_worker *w, int match_found, int continuing)
+{
+}
+#endif
+
+/**
+ * Release any resources used to read or write a replay log.
+ *
+ * @param g Cilk runtime global state
+ */
+void replay_term(global_state_t *g);
+
+__CILKRTS_END_EXTERN_C
+
+#endif // ! defined(INCLUDED_RECORD_REPLAY_DOT_H)
diff --git a/libcilkrts/runtime/reducer_impl.cpp b/libcilkrts/runtime/reducer_impl.cpp
new file mode 100644
index 00000000000..f20b9bc4592
--- /dev/null
+++ b/libcilkrts/runtime/reducer_impl.cpp
@@ -0,0 +1,1012 @@
+/* reducer_impl.cpp -*-C++-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Patents Pending, Intel Corporation.
+ **************************************************************************/
+
+/**
+ * Support for reducers
+ */
+
+// ICL: Don't complain about conversion from pointer to same-sized integral type
+// in hashfun. That's why we're using size_t
+#ifdef _WIN32
+# pragma warning(disable: 1684)
+#endif
+
+#include "reducer_impl.h"
+#include "scheduler.h"
+#include "bug.h"
+#include "os.h"
+#include "global_state.h"
+#include "frame_malloc.h"
+
+#include "cilk/hyperobject_base.h"
+#include "cilktools/cilkscreen.h"
+#include "internal/abi.h"
+
+#if REDPAR_DEBUG > 0
+#include <stdio.h>
+#include <stdlib.h>
+#endif
+
+
+#define DBG if(0) // if(1) enables some internal checks
+
+// Check that w is the currently executing worker. This method is a
+// no-op unless the debug level is set high enough.
+static inline void verify_current_wkr(__cilkrts_worker *w)
+{
+#if REDPAR_DEBUG >= 5
+ __cilkrts_worker* tmp = __cilkrts_get_tls_worker();
+ if (w != tmp) {
+ fprintf(stderr, "W=%d, actual=%d... missing a refresh....\n",
+ w->self,
+ tmp->self);
+ }
+ CILK_ASSERT(w == tmp); // __cilkrts_get_tls_worker());
+#endif
+}
+
+// Suppress clang warning that the expression result is unused
+#if defined(__clang__) && (! defined(__INTEL_COMPILER))
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wunused-value"
+#endif // __clang__
+
+/// Helper class to disable and re-enable Cilkscreen
+struct DisableCilkscreen
+{
+ DisableCilkscreen () { __cilkscreen_disable_checking(); }
+ ~DisableCilkscreen () { __cilkscreen_enable_checking(); }
+};
+
+/// Helper class to enable and re-disable Cilkscreen
+struct EnableCilkscreen
+{
+ EnableCilkscreen () { __cilkscreen_enable_checking(); }
+ ~EnableCilkscreen () { __cilkscreen_disable_checking(); }
+};
+
+#if defined(__clang__) && (! defined(__INTEL_COMPILER))
+# pragma clang diagnostic pop
+#endif // __clang__
+
+/**
+ * @brief Element for a hyperobject
+ */
+struct elem {
+ void *key; ///< Shared key for this hyperobject
+ __cilkrts_hyperobject_base *hb; ///< Base of the hyperobject.
+ void *view; ///< Strand-private view of this hyperobject
+ /// Destroy and deallocate the view object for this element and set view to
+ /// null.
+ void destroy();
+
+ /// Returns true if this element contains a leftmost view.
+ bool is_leftmost() const;
+};
+
+/** Bucket containing at most NMAX elements */
+struct bucket {
+ /// Size of the array of elements for this bucket
+ size_t nmax;
+
+ /**
+ * We use the ``struct hack'' to allocate an array of variable
+ * dimension at the end of the struct. However, we allocate a
+ * total of NMAX+1 elements instead of NMAX. The last one always
+ * has key == 0, which we use as a termination criterion
+ */
+ elem el[1];
+};
+
+/**
+ * Class that implements the map for reducers so we can find the
+ * view for a strand.
+ */
+struct cilkred_map {
+ /** Handy pointer to the global state */
+ global_state_t *g;
+
+ /** Number of elements in table */
+ size_t nelem;
+
+ /** Number of buckets */
+ size_t nbuckets;
+
+ /** Array of pointers to buckets */
+ bucket **buckets;
+
+ /** Set true if merging (for debugging purposes) */
+ bool merging;
+
+ /** Set true for leftmost reducer map */
+ bool is_leftmost;
+
+ /** @brief Return element mapped to 'key' or null if not found. */
+ elem *lookup(void *key);
+
+ /**
+ * @brief Insert key/value element into hash map without rehashing.
+ * Does not check for duplicate key.
+ */
+ elem *insert_no_rehash(__cilkrts_worker *w,
+ void *key,
+ __cilkrts_hyperobject_base *hb,
+ void *value);
+
+ /**
+ * @brief Insert key/value element into hash map, rehashing if necessary.
+ * Does not check for duplicate key.
+ */
+ inline elem *rehash_and_insert(__cilkrts_worker *w,
+ void *key,
+ __cilkrts_hyperobject_base *hb,
+ void *value);
+
+ /** @brief Grow bucket by one element, reallocating bucket if necessary */
+ static elem *grow(__cilkrts_worker *w, bucket **bp);
+
+ /** @brief Rehash a worker's reducer map */
+ void rehash(__cilkrts_worker *);
+
+ /**
+ * @brief Returns true if a rehash is needed due to the number of elements that
+ * have been inserted.
+ */
+ inline bool need_rehash_p() const;
+
+ /** @brief Allocate and initialize the buckets */
+ void make_buckets(__cilkrts_worker *w, size_t nbuckets);
+
+ /**
+ * Specify behavior when the same key is present in both maps passed
+ * into merge().
+ */
+ enum merge_kind
+ {
+ MERGE_UNORDERED, ///< Assertion fails
+ MERGE_INTO_LEFT, ///< Merges the argument from the right into the left
+ MERGE_INTO_RIGHT ///< Merges the argument from the left into the right
+ };
+
+ /**
+ * @brief Merge another reducer map into this one, destroying the other map in
+ * the process.
+ */
+ __cilkrts_worker* merge(__cilkrts_worker *current_wkr,
+ cilkred_map *other_map,
+ enum merge_kind kind);
+
+ /** @brief check consistency of a reducer map */
+ void check(bool allow_null_view);
+
+ /** @brief Test whether the cilkred_map is empty */
+ bool is_empty() { return nelem == 0; }
+};
+
+static inline struct cilkred_map* install_new_reducer_map(__cilkrts_worker *w) {
+ cilkred_map *h;
+ h = __cilkrts_make_reducer_map(w);
+ w->reducer_map = h;
+ return h;
+}
+
+static size_t sizeof_bucket(size_t nmax)
+{
+ bucket *b = 0;
+ return (sizeof(*b) + nmax * sizeof(b->el[0]));
+}
+
+static bucket *alloc_bucket(__cilkrts_worker *w, size_t nmax)
+{
+ bucket *b = (bucket *)
+ __cilkrts_frame_malloc(w, sizeof_bucket(nmax));
+ b->nmax = nmax;
+ return b;
+}
+
+static void free_bucket(__cilkrts_worker *w, bucket **bp)
+{
+ bucket *b = *bp;
+ if (b) {
+ __cilkrts_frame_free(w, b, sizeof_bucket(b->nmax));
+ *bp = 0;
+ }
+}
+
+/* round up nmax to fill a memory allocator block completely */
+static size_t roundup(size_t nmax)
+{
+ size_t sz = sizeof_bucket(nmax);
+
+ /* round up size to a full malloc block */
+ sz = __cilkrts_frame_malloc_roundup(sz);
+
+ /* invert sizeof_bucket() */
+ nmax = ((sz - sizeof(bucket)) / sizeof(elem));
+
+ return nmax;
+}
+
+static bool is_power_of_2(size_t n)
+{
+ return (n & (n - 1)) == 0;
+}
+
+void cilkred_map::make_buckets(__cilkrts_worker *w,
+ size_t new_nbuckets)
+{
+ nbuckets = new_nbuckets;
+
+ CILK_ASSERT(is_power_of_2(nbuckets));
+#if defined __GNUC__ && defined __ICC
+ /* bug workaround -- suppress calls to _intel_fast_memset */
+ bucket *volatile*new_buckets = (bucket *volatile*)
+#else
+ bucket **new_buckets = (bucket **)
+#endif
+ __cilkrts_frame_malloc(w, nbuckets * sizeof(*(buckets)));
+
+#if REDPAR_DEBUG >= 1
+ fprintf(stderr, "W=%d, desc=make_buckets, new_buckets=%p, new_nbuckets=%zd\n",
+ w->self, new_buckets, new_nbuckets);
+#endif
+
+ for (size_t i = 0; i < new_nbuckets; ++i)
+ new_buckets[i] = 0;
+#if defined __GNUC__ && defined __ICC
+ buckets = (bucket **)new_buckets;
+#else
+ buckets = new_buckets;
+#endif
+ nelem = 0;
+}
+
+static void free_buckets(__cilkrts_worker *w,
+ bucket **buckets,
+ size_t nbuckets)
+{
+ size_t i;
+
+#if REDPAR_DEBUG >= 1
+ verify_current_wkr(w);
+ fprintf(stderr, "W=%d, desc=free_buckets, buckets=%p, size=%zd\n",
+ w->self, buckets,
+ nbuckets * sizeof(*buckets));
+#endif
+
+ for (i = 0; i < nbuckets; ++i)
+ free_bucket(w, buckets + i);
+
+ __cilkrts_frame_free(w, buckets, nbuckets * sizeof(*buckets));
+}
+
+static size_t minsz(size_t nelem)
+{
+ return 1U + nelem + nelem / 8U;
+}
+
+static size_t nextsz(size_t nelem)
+{
+ return 2 * nelem;
+}
+
+bool cilkred_map::need_rehash_p() const
+{
+ return minsz(nelem) > nbuckets;
+}
+
+static inline size_t hashfun(const cilkred_map *h, void *key)
+{
+ size_t k = (size_t) key;
+
+ k ^= k >> 21;
+ k ^= k >> 8;
+ k ^= k >> 3;
+
+ return k & (h->nbuckets - 1);
+}
+
+// Given a __cilkrts_hyperobject_base, return the key to that hyperobject in
+// the reducer map.
+static inline void* get_hyperobject_key(__cilkrts_hyperobject_base *hb)
+{
+ // The current implementation uses the address of the lefmost view as the
+ // key.
+ return reinterpret_cast<char*>(hb) + hb->__view_offset;
+}
+
+// Given a hyperobject key, return a pointer to the leftmost object. In the
+// current implementation, the address of the leftmost object IS the key, so
+// this function is an effective noop.
+static inline void* get_leftmost_view(void *key)
+{
+ return key;
+}
+
+/* debugging support: check consistency of a reducer map */
+void cilkred_map::check(bool allow_null_view)
+{
+ size_t count = 0;
+
+ CILK_ASSERT(buckets);
+ for (size_t i = 0; i < nbuckets; ++i) {
+ bucket *b = buckets[i];
+ if (b)
+ for (elem *el = b->el; el->key; ++el) {
+ CILK_ASSERT(allow_null_view || el->view);
+ ++count;
+ }
+ }
+ CILK_ASSERT(nelem == count);
+ /*global_reducer_map::check();*/
+}
+
+/* grow bucket by one element, reallocating bucket if necessary */
+elem *cilkred_map::grow(__cilkrts_worker *w,
+ bucket **bp)
+{
+ size_t i, nmax, nnmax;
+ bucket *b, *nb;
+
+ b = *bp;
+ if (b) {
+ nmax = b->nmax;
+ /* find empty element if any */
+ for (i = 0; i < nmax; ++i)
+ if (b->el[i].key == 0)
+ return &(b->el[i]);
+ /* do not use the last one even if empty */
+ } else {
+ nmax = 0;
+ }
+
+ verify_current_wkr(w);
+ /* allocate a new bucket */
+ nnmax = roundup(2 * nmax);
+ nb = alloc_bucket(w, nnmax);
+
+
+ /* copy old bucket into new */
+ for (i = 0; i < nmax; ++i)
+ nb->el[i] = b->el[i];
+
+ free_bucket(w, bp); *bp = nb;
+
+ /* zero out extra elements */
+ for (; i < nnmax; ++i)
+ nb->el[i].key = 0;
+
+ /* zero out the last one */
+ nb->el[i].key = 0;
+
+ return &(nb->el[nmax]);
+}
+
+elem *cilkred_map::insert_no_rehash(__cilkrts_worker *w,
+ void *key,
+ __cilkrts_hyperobject_base *hb,
+ void *view)
+{
+
+#if REDPAR_DEBUG >= 2
+ fprintf(stderr, "[W=%d, desc=insert_no_rehash, this_map=%p]\n",
+ w->self, this);
+ verify_current_wkr(w);
+#endif
+
+ CILK_ASSERT((w == 0 && g == 0) || w->g == g);
+ CILK_ASSERT(key != 0);
+ CILK_ASSERT(view != 0);
+
+ elem *el = grow(w, &(buckets[hashfun(this, key)]));
+
+#if REDPAR_DEBUG >= 3
+ fprintf(stderr, "[W=%d, this=%p, inserting key=%p, view=%p, el = %p]\n",
+ w->self, this, key, view, el);
+#endif
+
+ el->key = key;
+ el->hb = hb;
+ el->view = view;
+ ++nelem;
+
+ return el;
+}
+
+void cilkred_map::rehash(__cilkrts_worker *w)
+{
+#if REDPAR_DEBUG >= 1
+ fprintf(stderr, "[W=%d, desc=rehash, this_map=%p, g=%p, w->g=%p]\n",
+ w->self, this, g, w->g);
+ verify_current_wkr(w);
+#endif
+ CILK_ASSERT((w == 0 && g == 0) || w->g == g);
+
+ size_t onbuckets = nbuckets;
+ size_t onelem = nelem;
+ bucket **obuckets = buckets;
+ size_t i;
+ bucket *b;
+
+ make_buckets(w, nextsz(nbuckets));
+
+ for (i = 0; i < onbuckets; ++i) {
+ b = obuckets[i];
+ if (b) {
+ elem *oel;
+ for (oel = b->el; oel->key; ++oel)
+ insert_no_rehash(w, oel->key, oel->hb, oel->view);
+ }
+ }
+
+ CILK_ASSERT(nelem == onelem);
+
+ free_buckets(w, obuckets, onbuckets);
+}
+
+elem *cilkred_map::rehash_and_insert(__cilkrts_worker *w,
+ void *key,
+ __cilkrts_hyperobject_base *hb,
+ void *view)
+{
+
+#if REDPAR_DEBUG >= 1
+ fprintf(stderr, "W=%d, this_map =%p, inserting key=%p, view=%p\n",
+ w->self, this, key, view);
+ verify_current_wkr(w);
+#endif
+
+ if (need_rehash_p())
+ rehash(w);
+
+ return insert_no_rehash(w, key, hb, view);
+}
+
+
+elem *cilkred_map::lookup(void *key)
+{
+ bucket *b = buckets[hashfun(this, key)];
+
+ if (b) {
+ elem *el;
+ for (el = b->el; el->key; ++el) {
+ if (el->key == key) {
+ CILK_ASSERT(el->view);
+ return el;
+ }
+ }
+ }
+
+ return 0;
+}
+
+void elem::destroy()
+{
+ if (! is_leftmost()) {
+
+ // Call destroy_fn and deallocate_fn on the view, but not if it's the
+ // leftmost view.
+ cilk_c_monoid *monoid = &(hb->__c_monoid);
+ cilk_c_reducer_destroy_fn_t destroy_fn = monoid->destroy_fn;
+ cilk_c_reducer_deallocate_fn_t deallocate_fn = monoid->deallocate_fn;
+
+ destroy_fn((void*)hb, view);
+ deallocate_fn((void*)hb, view);
+ }
+
+ view = 0;
+}
+
+inline
+bool elem::is_leftmost() const
+{
+ // implementation uses the address of the leftmost view as the key, so if
+ // key == view, then this element refers to the leftmost view.
+ return key == view;
+}
+
+/* remove the reducer from the current reducer map. If the reducer
+ exists in maps other than the current one, the behavior is
+ undefined. */
+extern "C"
+CILK_EXPORT void __CILKRTS_STRAND_STALE(
+ __cilkrts_hyper_destroy(__cilkrts_hyperobject_base *hb))
+{
+ // Disable Cilkscreen for the duration of this call. The destructor for
+ // this class will re-enable Cilkscreen when the method returns. This
+ // will prevent Cilkscreen from reporting apparent races in reducers
+ DisableCilkscreen x;
+
+ __cilkrts_worker* w = __cilkrts_get_tls_worker();
+ if (! w) {
+ // If no worker, then Cilk is not running and there is no reducer
+ // map. Do nothing. The reducer's destructor will take care of
+ // destroying the leftmost view.
+ return;
+ }
+
+const char *UNSYNCED_REDUCER_MSG =
+ "Destroying a reducer while it is visible to unsynced child tasks, or\n"
+ "calling CILK_C_UNREGISTER_REDUCER() on an unregistered reducer.\n"
+ "Did you forget a _Cilk_sync or CILK_C_REGISTER_REDUCER()?";
+
+ cilkred_map* h = w->reducer_map;
+ if (NULL == h)
+ cilkos_error(UNSYNCED_REDUCER_MSG); // Does not return
+
+ if (h->merging) {
+ verify_current_wkr(w);
+ __cilkrts_bug("User error: hyperobject used by another hyperobject");
+ }
+
+ void* key = get_hyperobject_key(hb);
+ elem *el = h->lookup(key);
+
+ // Verify that the reducer is being destroyed from the leftmost strand for
+ // which the reducer is defined.
+ if (! (el && el->is_leftmost()))
+ cilkos_error(UNSYNCED_REDUCER_MSG);
+
+#if REDPAR_DEBUG >= 3
+ fprintf(stderr, "[W=%d, key=%p, lookup in map %p, found el=%p, about to destroy]\n",
+ w->self, key, h, el);
+#endif
+
+ // Remove the element from the hash bucket. Do not bother shrinking
+ // the bucket. Note that the destroy() function does not actually
+ // call the destructor for the leftmost view.
+ el->destroy();
+ do {
+ el[0] = el[1];
+ ++el;
+ } while (el->key);
+ --h->nelem;
+
+#if REDPAR_DEBUG >= 2
+ fprintf(stderr, "[W=%d, desc=hyper_destroy_finish, key=%p, w->reducer_map=%p]\n",
+ w->self, key, w->reducer_map);
+#endif
+}
+
+extern "C"
+CILK_EXPORT
+void __cilkrts_hyper_create(__cilkrts_hyperobject_base *hb)
+{
+ // This function registers the specified hyperobject in the current
+ // reducer map and registers the initial value of the hyperobject as the
+ // leftmost view of the reducer.
+ __cilkrts_worker *w = __cilkrts_get_tls_worker();
+ if (! w) {
+ // If there is no worker, then there is nothing to do: The iniitial
+ // value will automatically be used as the left-most view when we
+ // enter Cilk.
+ return;
+ }
+
+ // Disable Cilkscreen for the duration of this call. The destructor for
+ // this class will re-enable Cilkscreen when the method returns. This
+ // will prevent Cilkscreen from reporting apparent races in reducers
+ DisableCilkscreen x;
+
+ void* key = get_hyperobject_key(hb);
+ void* view = get_leftmost_view(key);
+ cilkred_map *h = w->reducer_map;
+
+ if (__builtin_expect(!h, 0)) {
+ h = install_new_reducer_map(w);
+#if REDPAR_DEBUG >= 2
+ fprintf(stderr, "[W=%d, hb=%p, hyper_create, isntalled new map %p, view=%p]\n",
+ w->self, hb, h, view);
+#endif
+ }
+
+ /* Must not exist. */
+ CILK_ASSERT(h->lookup(key) == NULL);
+
+#if REDPAR_DEBUG >= 3
+ verify_current_wkr(w);
+ fprintf(stderr, "[W=%d, hb=%p, lookup in map %p of view %p, should be null]\n",
+ w->self, hb, h, view);
+ fprintf(stderr, "W=%d, h=%p, inserting key %p, view%p\n",
+ w->self,
+ h,
+ &(hb->__c_monoid),
+ view);
+#endif
+
+ if (h->merging)
+ __cilkrts_bug("User error: hyperobject used by another hyperobject");
+
+ CILK_ASSERT(w->reducer_map == h);
+ // The address of the leftmost value is the same as the key for lookup.
+ (void) h->rehash_and_insert(w, view, hb, view);
+}
+
+extern "C"
+CILK_EXPORT void* __CILKRTS_STRAND_PURE(
+ __cilkrts_hyper_lookup(__cilkrts_hyperobject_base *hb))
+{
+ __cilkrts_worker* w = __cilkrts_get_tls_worker_fast();
+ void* key = get_hyperobject_key(hb);
+ if (! w)
+ return get_leftmost_view(key);
+
+ // Disable Cilkscreen for the duration of this call. This will
+ // prevent Cilkscreen from reporting apparent races in reducers
+ DisableCilkscreen dguard;
+
+ if (__builtin_expect(w->g->force_reduce, 0))
+ __cilkrts_promote_own_deque(w);
+ cilkred_map* h = w->reducer_map;
+
+ if (__builtin_expect(!h, 0)) {
+ h = install_new_reducer_map(w);
+ }
+
+ if (h->merging)
+ __cilkrts_bug("User error: hyperobject used by another hyperobject");
+ elem* el = h->lookup(key);
+ if (! el) {
+ /* lookup failed; insert a new default element */
+ void *rep;
+
+ {
+ /* re-enable cilkscreen while calling the constructor */
+ EnableCilkscreen eguard;
+ if (h->is_leftmost)
+ {
+ // This special case is called only if the reducer was not
+ // registered using __cilkrts_hyper_create, e.g., if this is a
+ // C reducer in global scope or if there is no bound worker.
+ rep = get_leftmost_view(key);
+ }
+ else
+ {
+ rep = hb->__c_monoid.allocate_fn((void*)hb,
+ hb->__view_size);
+ // TBD: Handle exception on identity function
+ hb->__c_monoid.identity_fn((void*)hb, rep);
+ }
+ }
+
+#if REDPAR_DEBUG >= 3
+ fprintf(stderr, "W=%d, h=%p, inserting key %p, view%p\n",
+ w->self,
+ h,
+ &(hb->__c_monoid),
+ rep);
+ CILK_ASSERT(w->reducer_map == h);
+#endif
+ el = h->rehash_and_insert(w, key, hb, rep);
+ }
+
+ return el->view;
+}
+
+extern "C" CILK_EXPORT
+void* __cilkrts_hyperobject_alloc(void* ignore, std::size_t bytes)
+{
+ return std::malloc(bytes);
+}
+
+extern "C" CILK_EXPORT
+void __cilkrts_hyperobject_dealloc(void* ignore, void* view)
+{
+ std::free(view);
+}
+
+/* No-op destroy function */
+extern "C" CILK_EXPORT
+void __cilkrts_hyperobject_noop_destroy(void* ignore, void* ignore2)
+{
+}
+
+cilkred_map *__cilkrts_make_reducer_map(__cilkrts_worker *w)
+{
+ CILK_ASSERT(w);
+
+ cilkred_map *h;
+ size_t nbuckets = 1; /* default value */
+
+ h = (cilkred_map *)__cilkrts_frame_malloc(w, sizeof(*h));
+#if REDPAR_DEBUG >= 1
+ fprintf(stderr, "[W=%d, desc=make_reducer_frame_malloc_reducer_map, h=%p]\n",
+ w->self, h);
+#endif
+
+ h->g = w ? w->g : 0;
+ h->make_buckets(w, nbuckets);
+ h->merging = false;
+ h->is_leftmost = false;
+
+ return h;
+}
+
+/* Destroy a reducer map. The map must have been allocated
+ from the worker's global context and should have been
+ allocated from the same worker. */
+void __cilkrts_destroy_reducer_map(__cilkrts_worker *w, cilkred_map *h)
+{
+ CILK_ASSERT((w == 0 && h->g == 0) || w->g == h->g);
+ verify_current_wkr(w);
+
+ /* the reducer map is allowed to contain el->view == NULL here (and
+ only here). We set el->view == NULL only when we know that the
+ map will be destroyed immediately afterwards. */
+ DBG h->check(/*allow_null_view=*/true);
+
+ bucket *b;
+ size_t i;
+
+ for (i = 0; i < h->nbuckets; ++i) {
+ b = h->buckets[i];
+ if (b) {
+ elem *el;
+ for (el = b->el; el->key; ++el) {
+ if (el->view)
+ el->destroy();
+ }
+ }
+ }
+
+ free_buckets(w, h->buckets, h->nbuckets);
+
+#if REDPAR_DEBUG >= 1
+ fprintf(stderr, "W=%d, destroy_red_map, freeing map h=%p, size=%zd\n",
+ w->self, h, sizeof(*h));
+#endif
+
+ __cilkrts_frame_free(w, h, sizeof(*h));
+}
+
+/* Set the specified reducer map as the leftmost map if is_leftmost is true,
+ otherwise, set it to not be the leftmost map. */
+void __cilkrts_set_leftmost_reducer_map(cilkred_map *h, int is_leftmost)
+{
+ h->is_leftmost = is_leftmost;
+}
+
+
+__cilkrts_worker* cilkred_map::merge(__cilkrts_worker *w,
+ cilkred_map *other_map,
+ enum merge_kind kind)
+{
+ // Disable Cilkscreen while the we merge the maps. The destructor for
+ // the guard class will re-enable Cilkscreen when it goes out of scope.
+ // This will prevent Cilkscreen from reporting apparent races in between
+ // the reduce function and the reducer operations. The Cilk runtime
+ // guarantees that a pair of reducer maps will only be merged when no
+ // other strand will access them.
+ DisableCilkscreen guard;
+
+#if REDPAR_DEBUG >= 2
+ fprintf(stderr, "[W=%d, desc=merge, this_map=%p, other_map=%p]\n",
+ w->self,
+ this, other_map);
+#endif
+ // Remember the current stack frame.
+ __cilkrts_stack_frame *current_sf = w->current_stack_frame;
+ merging = true;
+ other_map->merging = true;
+
+ // Merging to the leftmost view is a special case because every leftmost
+ // element must be initialized before the merge.
+ CILK_ASSERT(!other_map->is_leftmost /* || kind == MERGE_UNORDERED */);
+ bool merge_to_leftmost = (this->is_leftmost
+ /* && !other_map->is_leftmost */);
+
+ DBG check(/*allow_null_view=*/false);
+ DBG other_map->check(/*allow_null_view=*/false);
+
+ for (size_t i = 0; i < other_map->nbuckets; ++i) {
+ bucket *b = other_map->buckets[i];
+ if (b) {
+ for (elem *other_el = b->el; other_el->key; ++other_el) {
+ /* Steal the value from the other map, which will be
+ destroyed at the end of this operation. */
+ void *other_view = other_el->view;
+ CILK_ASSERT(other_view);
+
+ void *key = other_el->key;
+ __cilkrts_hyperobject_base *hb = other_el->hb;
+ elem *this_el = lookup(key);
+
+ if (this_el == 0 && merge_to_leftmost) {
+ /* Initialize leftmost view before merging. */
+ void* leftmost = get_leftmost_view(key);
+ // leftmost == other_view can be true if the initial view
+ // was created in other than the leftmost strand of the
+ // spawn tree, but then made visible to subsequent strands
+ // (E.g., the reducer was allocated on the heap and the
+ // pointer was returned to the caller.) In such cases,
+ // parallel semantics says that syncing with earlier
+ // strands will always result in 'this_el' being null,
+ // thus propagating the initial view up the spawn tree
+ // until it reaches the leftmost strand. When synching
+ // with the leftmost strand, leftmost == other_view will be
+ // true and we must avoid reducing the initial view with
+ // itself.
+ if (leftmost != other_view)
+ this_el = rehash_and_insert(w, key, hb, leftmost);
+ }
+
+ if (this_el == 0) {
+ /* move object from other map into this one */
+ rehash_and_insert(w, key, hb, other_view);
+ other_el->view = 0;
+ continue; /* No element-level merge necessary */
+ }
+
+ /* The same key is present in both maps with values
+ A and B. Three choices: fail, A OP B, B OP A. */
+ switch (kind)
+ {
+ case MERGE_UNORDERED:
+ __cilkrts_bug("TLS Reducer race");
+ break;
+ case MERGE_INTO_RIGHT:
+ /* Swap elements in order to preserve object
+ identity */
+ other_el->view = this_el->view;
+ this_el->view = other_view;
+ /* FALL THROUGH */
+ case MERGE_INTO_LEFT: {
+ /* Stealing should be disabled during reduce
+ (even if force-reduce is enabled). */
+
+#if DISABLE_PARALLEL_REDUCERS
+ __cilkrts_stack_frame * volatile *saved_protected_tail;
+ saved_protected_tail = __cilkrts_disallow_stealing(w, NULL);
+#endif
+
+ {
+ CILK_ASSERT(current_sf->worker == w);
+ CILK_ASSERT(w->current_stack_frame == current_sf);
+
+ /* TBD: if reduce throws an exception we need to stop it
+ here. */
+ hb->__c_monoid.reduce_fn((void*)hb,
+ this_el->view,
+ other_el->view);
+ w = current_sf->worker;
+
+#if REDPAR_DEBUG >= 2
+ verify_current_wkr(w);
+ CILK_ASSERT(w->current_stack_frame == current_sf);
+#endif
+ }
+
+#if DISABLE_PARALLEL_REDUCERS
+ /* Restore stealing */
+ __cilkrts_restore_stealing(w, saved_protected_tail);
+#endif
+
+ } break;
+ }
+ }
+ }
+ }
+ this->is_leftmost = this->is_leftmost || other_map->is_leftmost;
+ merging = false;
+ other_map->merging = false;
+ verify_current_wkr(w);
+ __cilkrts_destroy_reducer_map(w, other_map);
+ return w;
+}
+
+
+/**
+ * Print routine for debugging the merging of reducer maps.
+ * A no-op unless REDPAR_DEBUG set high enough.
+ */
+static inline
+void debug_map_merge(__cilkrts_worker *w,
+ cilkred_map *left_map,
+ cilkred_map *right_map,
+ __cilkrts_worker **final_wkr)
+{
+#if REDPAR_DEBUG >= 2
+ fprintf(stderr, "[W=%d, desc=finish_merge, left_map=%p, right_map=%p, w->reducer_map=%p, right_ans=%p, final_wkr=%d]\n",
+ w->self, left_map, right_map, w->reducer_map, right_map, (*final_wkr)->self);
+#endif
+}
+
+
+/**
+ * merge RIGHT into LEFT;
+ * return whichever map allows for faster merge, and destroy the other one.
+ *
+ * *w_ptr should be the currently executing worker.
+ * *w_ptr may change during execution if the reduction is parallel.
+ */
+cilkred_map*
+merge_reducer_maps(__cilkrts_worker **w_ptr,
+ cilkred_map *left_map,
+ cilkred_map *right_map)
+{
+ __cilkrts_worker *w = *w_ptr;
+ if (!left_map) {
+ debug_map_merge(w, left_map, right_map, w_ptr);
+ return right_map;
+ }
+
+ if (!right_map) {
+ debug_map_merge(w, left_map, right_map, w_ptr);
+ return left_map;
+ }
+
+ /* Special case, if left_map is leftmost, then always merge into it.
+ For C reducers this forces lazy creation of the leftmost views. */
+ if (left_map->is_leftmost || left_map->nelem > right_map->nelem) {
+ *w_ptr = left_map->merge(w, right_map, cilkred_map::MERGE_INTO_LEFT);
+ debug_map_merge(*w_ptr, left_map, right_map, w_ptr);
+ return left_map;
+ } else {
+ *w_ptr = right_map->merge(w, left_map, cilkred_map::MERGE_INTO_RIGHT);
+ debug_map_merge(*w_ptr, left_map, right_map, w_ptr);
+ return right_map;
+ }
+}
+
+/**
+ * Merges RIGHT into LEFT, and then repeatedly calls
+ * merge_reducer_maps_helper() until (*w_ptr)->reducer_map is NULL.
+ *
+ * *w_ptr may change as reductions execute.
+ */
+cilkred_map*
+repeated_merge_reducer_maps(__cilkrts_worker **w_ptr,
+ cilkred_map *left_map,
+ cilkred_map *right_map)
+{
+ // Note: if right_map == NULL but w->reducer_map != NULL, then
+ // this loop will reduce w->reducer_map into left_map.
+ do {
+ left_map = merge_reducer_maps(w_ptr, left_map, right_map);
+ verify_current_wkr(*w_ptr);
+
+ // Pull any newly created reducer map and loop around again.
+ right_map = (*w_ptr)->reducer_map;
+ (*w_ptr)->reducer_map = NULL;
+ } while (right_map);
+ return left_map;
+}
+
+/* End reducer_impl.cpp */
diff --git a/libcilkrts/runtime/reducer_impl.h b/libcilkrts/runtime/reducer_impl.h
new file mode 100644
index 00000000000..3425967ad8d
--- /dev/null
+++ b/libcilkrts/runtime/reducer_impl.h
@@ -0,0 +1,128 @@
+/* reducer_impl.h -*-C++-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ **************************************************************************/
+
+/**
+ * @file reducer_impl.h
+ *
+ * @brief Functions to implement reducers in the runtime.
+ */
+
+#ifndef INCLUDED_REDUCER_IMPL_DOT_H
+#define INCLUDED_REDUCER_IMPL_DOT_H
+
+#include <cilk/common.h>
+#include <internal/abi.h>
+#include "rts-common.h"
+
+__CILKRTS_BEGIN_EXTERN_C
+
+/**
+ * Construct an empty reducer map from the memory pool associated with the
+ * given worker. This reducer map must be destroyed before the worker's
+ * associated global context is destroyed.
+ *
+ * @param w __cilkrts_worker the cilkred_map is being created for.
+ *
+ * @return Pointer to the initialized cilkred_map.
+ */
+COMMON_SYSDEP
+cilkred_map *__cilkrts_make_reducer_map(__cilkrts_worker *w);
+
+/**
+ * Destroy a reducer map. The map must have been allocated from the worker's
+ * global context and should have been allocated from the same worker.
+ *
+ * @param w __cilkrts_worker the cilkred_map was created for.
+ * @param h The cilkred_map to be deallocated.
+ */
+COMMON_SYSDEP
+void __cilkrts_destroy_reducer_map(__cilkrts_worker *w,
+ cilkred_map *h);
+
+/**
+ * Set the specified reducer map as the leftmost map if is_leftmost is true,
+ * otherwise, set it to not be the leftmost map.
+ *
+ * @param h The cilkred_map to be modified.
+ * @param is_leftmost true if the reducer map is leftmost.
+ */
+COMMON_SYSDEP
+void __cilkrts_set_leftmost_reducer_map(cilkred_map *h,
+ int is_leftmost);
+
+/**
+ * Merge reducer map RIGHT_MAP into LEFT_MAP and return the result of the
+ * merge. Both maps must be allocated from the global context associated
+ * with the specified worker. The returned reducer map must be destroyed
+ * before the worker's associated global context is destroyed.
+ *
+ * If two cilkred_maps are specified, one will be destroyed and the other
+ * one will be returned as the merged cilkred_map.
+ *
+ * When reducers can contain nested parallelism, execution can return
+ * on a different worker than when it started (but still using the
+ * same stack).
+ *
+ * Upon return, *w_ptr stores the pointer to the worker that execution
+ * returns on.
+ *
+ * @param w_ptr Pointer to the currently executing worker.
+ * @param left_map The left cilkred_map.
+ * @param right_map The right cilkred_map.
+ *
+ * @return pointer to merged cilkred_map.
+ */
+extern
+cilkred_map *merge_reducer_maps(__cilkrts_worker **w_ptr,
+ cilkred_map *left_map,
+ cilkred_map *right_map);
+
+/**
+ * Similar to merge_reducer_maps(), except that after merging
+ * RIGHT_MAP into LEFT_MAP, it repeatedly merges (*w_ptr)->reducer_map
+ * into LEFT_MAP. This procedure ensures that any new reducers
+ * created by the reductions themselves also get merged into LEFT_MAP.
+ */
+extern
+cilkred_map *repeated_merge_reducer_maps(__cilkrts_worker **w_ptr,
+ cilkred_map *left_map,
+ cilkred_map *right_map);
+
+__CILKRTS_END_EXTERN_C
+
+#endif // ! defined(INCLUDED_REDUCER_IMPL_DOT_H)
diff --git a/libcilkrts/runtime/rts-common.h b/libcilkrts/runtime/rts-common.h
new file mode 100644
index 00000000000..4ffde7ccb1e
--- /dev/null
+++ b/libcilkrts/runtime/rts-common.h
@@ -0,0 +1,132 @@
+/* rts-common.h -*-C++-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ **************************************************************************/
+
+#ifndef INCLUDED_RTS_COMMON_DOT_H
+#define INCLUDED_RTS_COMMON_DOT_H
+
+/* Abbreviations API functions returning different types. By using these
+ * abbreviations instead of using CILK_API(ret) directly, etags and other
+ * tools can more easily recognize function signatures.
+ */
+#define CILK_API_VOID CILK_API(void)
+#define CILK_API_VOID_PTR CILK_API(void*)
+#define CILK_API_INT CILK_API(int)
+#define CILK_API_SIZET CILK_API(size_t)
+#define CILK_API_TBB_RETCODE CILK_API(__cilk_tbb_retcode)
+#define CILK_API_PEDIGREE CILK_API(__cilkrts_pedigree)
+
+/* Abbreviations ABI functions returning different types. By using these
+ * abbreviations instead of using CILK_ABI(ret) directly, etags and other
+ * tools can more easily recognize function signatures.
+ */
+#define CILK_ABI_VOID CILK_ABI(void)
+#define CILK_ABI_WORKER_PTR CILK_ABI(__cilkrts_worker_ptr)
+#define CILK_ABI_THROWS_VOID CILK_ABI_THROWS(void)
+
+/* documentation aid to identify portable vs. nonportable
+ parts of the runtime. See README for definitions. */
+#define COMMON_PORTABLE
+#define COMMON_SYSDEP
+#define NON_COMMON
+
+#if !(defined __GNUC__ || defined __ICC)
+# define __builtin_expect(a_, b_) a_
+#endif
+
+#ifdef __cplusplus
+# define cilk_nothrow throw()
+#else
+# define cilk_nothrow /*empty in C*/
+#endif
+
+#ifdef __GNUC__
+# define NORETURN void __attribute__((noreturn))
+#else
+# define NORETURN void __declspec(noreturn)
+#endif
+
+#ifdef __GNUC__
+# define NOINLINE __attribute__((noinline))
+#else
+# define NOINLINE __declspec(noinline)
+#endif
+
+#ifndef __GNUC__
+# define __attribute__(X)
+#endif
+
+/* Microsoft CL accepts "inline" for C++, but not for C. It accepts
+ * __inline for both. Intel ICL accepts inline for C of /Qstd=c99
+ * is set. The Cilk runtime is assumed to be compiled with /Qstd=c99
+ */
+#if defined(_MSC_VER) && ! defined(__INTEL_COMPILER)
+# error define inline
+# define inline __inline
+#endif
+
+/* Compilers that build the Cilk runtime are assumed to know about zero-cost
+ * intrinsics (__notify_intrinsic()). For those that don't, #undef the
+ * following definition:
+ */
+//#define ENABLE_NOTIFY_ZC_INTRINSIC 1
+
+#if defined(__INTEL_COMPILER)
+/* The notify intrinsic was introduced in ICC 12.0. */
+# if __INTEL_COMPILER <= 1200
+# undef ENABLE_NOTIFY_ZC_INTRINSIC
+# endif
+#elif defined(__VXWORKS__)
+# undef ENABLE_NOTIFY_ZC_INTRINSIC
+#elif defined(__clang__)
+# if !defined(__has_extension) || !__has_extension(notify_zc_intrinsic)
+# undef ENABLE_NOTIFY_ZC_INTRINSIC
+# endif
+#elif defined(__arm__)
+// __notify_zc_intrinsic not yet supported by gcc for ARM
+# undef ENABLE_NOTIFY_ZC_INTRINSIC
+#endif
+
+// If ENABLE_NOTIFY_ZC_INTRINSIC is defined, use __notify_zc_intrisic
+#ifdef ENABLE_NOTIFY_ZC_INTRINSIC
+# define NOTIFY_ZC_INTRINSIC(annotation, data) \
+ __notify_zc_intrinsic(annotation, data)
+#else
+# define NOTIFY_ZC_INTRINSIC(annotation, data)
+#endif
+
+#endif // ! defined(INCLUDED_RTS_COMMON_DOT_H)
diff --git a/libcilkrts/runtime/scheduler.c b/libcilkrts/runtime/scheduler.c
new file mode 100644
index 00000000000..bab6430d9db
--- /dev/null
+++ b/libcilkrts/runtime/scheduler.c
@@ -0,0 +1,3940 @@
+/* scheduler.c -*-C-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2007-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ **************************************************************************/
+
+/*
+ * Cilk scheduler
+ */
+
+#include "scheduler.h"
+#include "bug.h"
+#include "os.h"
+#include "os_mutex.h"
+#include "local_state.h"
+#include "signal_node.h"
+#include "full_frame.h"
+#include "sysdep.h"
+#include "except.h"
+#include "cilk_malloc.h"
+#include "pedigrees.h"
+#include "record-replay.h"
+
+#include <limits.h>
+#include <string.h> /* memcpy */
+#include <stdio.h> // sprintf
+#include <stdlib.h> // malloc, free, abort
+
+#ifdef _WIN32
+# pragma warning(disable:1786) // disable warning: sprintf is deprecated
+# include "sysdep-win.h"
+# include "except-win32.h"
+#endif // _WIN32
+
+// ICL: Don't complain about conversion from pointer to same-sized integral
+// type in __cilkrts_put_stack. That's why we're using ptrdiff_t
+#ifdef _WIN32
+# pragma warning(disable: 1684)
+#endif
+
+#include "cilk/cilk_api.h"
+#include "frame_malloc.h"
+#include "metacall_impl.h"
+#include "reducer_impl.h"
+#include "cilk-tbb-interop.h"
+#include "cilk-ittnotify.h"
+#include "stats.h"
+
+// ICL: Don't complain about loss of precision in myrand
+// I tried restoring the warning after the function, but it didn't
+// suppress it
+#ifdef _WIN32
+# pragma warning(disable: 2259)
+#endif
+
+#ifndef _WIN32
+# include <unistd.h>
+#endif
+
+#ifdef __VXWORKS__
+// redeclare longjmp() with noreturn to stop warnings
+extern __attribute__((noreturn))
+ void longjmp(jmp_buf, int);
+#endif
+
+//#define DEBUG_LOCKS 1
+#ifdef DEBUG_LOCKS
+// The currently executing worker must own this worker's lock
+# define ASSERT_WORKER_LOCK_OWNED(w) \
+ { \
+ __cilkrts_worker *tls_worker = __cilkrts_get_tls_worker(); \
+ CILK_ASSERT((w)->l->lock.owner == tls_worker); \
+ }
+#else
+# define ASSERT_WORKER_LOCK_OWNED(w)
+#endif // DEBUG_LOCKS
+
+// Options for the scheduler.
+enum schedule_t { SCHEDULE_RUN,
+ SCHEDULE_WAIT,
+ SCHEDULE_EXIT };
+
+// Return values for provably_good_steal()
+enum provably_good_steal_t
+{
+ ABANDON_EXECUTION, // Not the last child to the sync - attempt to steal work
+ CONTINUE_EXECUTION, // Last child to the sync - continue executing on this worker
+ WAIT_FOR_CONTINUE // The replay log indicates that this was the worker
+ // which continued. Loop until we are the last worker
+ // to the sync.
+};
+
+
+// Verify that "w" is the worker we are currently executing on.
+// Because this check is expensive, this method is usually a no-op.
+static inline void verify_current_wkr(__cilkrts_worker *w)
+{
+#if ((REDPAR_DEBUG >= 3) || (FIBER_DEBUG >= 1))
+ // Lookup the worker from TLS and compare to w.
+ __cilkrts_worker* tmp = __cilkrts_get_tls_worker();
+ if (w != tmp) {
+ fprintf(stderr, "Error. W=%d, actual worker =%d...\n",
+ w->self,
+ tmp->self);
+ }
+ CILK_ASSERT(w == tmp);
+#endif
+}
+
+static enum schedule_t worker_runnable(__cilkrts_worker *w);
+
+// Scheduling-fiber functions:
+static void do_return_from_spawn (__cilkrts_worker *w,
+ full_frame *ff,
+ __cilkrts_stack_frame *sf);
+static void do_sync (__cilkrts_worker *w,
+ full_frame *ff,
+ __cilkrts_stack_frame *sf);
+
+// max is defined on Windows and VxWorks
+#if (! defined(_WIN32)) && (! defined(__VXWORKS__))
+ // TBD: definition of max() for Linux.
+# define max(a, b) ((a) < (b) ? (b) : (a))
+#endif
+
+void __cilkrts_dump_stats_to_stderr(global_state_t *g)
+{
+#ifdef CILK_PROFILE
+ int i;
+ for (i = 0; i < g->total_workers; ++i) {
+ // Print out statistics for each worker. We collected them,
+ // so why not print them out?
+ fprintf(stderr, "Stats for worker %d\n", i);
+ dump_stats_to_file(stderr, g->workers[i]->l->stats);
+ __cilkrts_accum_stats(&g->stats, g->workers[i]->l->stats);
+ }
+
+ // Also print out aggregate statistics.
+ dump_stats_to_file(stderr, &g->stats);
+#endif
+ fprintf(stderr,
+ "CILK PLUS Thread Info: P=%d, Q=%d\n",
+ g->P,
+ g->Q);
+ fprintf(stderr,
+ "CILK PLUS RUNTIME MEMORY USAGE: %lld bytes",
+ (long long)g->frame_malloc.allocated_from_os);
+#ifdef CILK_PROFILE
+ if (g->stats.stack_hwm)
+ fprintf(stderr, ", %ld stacks", g->stats.stack_hwm);
+#endif
+ fputc('\n', stderr);
+}
+
+static void validate_worker(__cilkrts_worker *w)
+{
+ /* check the magic numbers, for debugging purposes */
+ if (w->l->worker_magic_0 != WORKER_MAGIC_0 ||
+ w->l->worker_magic_1 != WORKER_MAGIC_1)
+ abort_because_rts_is_corrupted();
+}
+
+static void double_link(full_frame *left_ff, full_frame *right_ff)
+{
+ if (left_ff)
+ left_ff->right_sibling = right_ff;
+ if (right_ff)
+ right_ff->left_sibling = left_ff;
+}
+
+/* add CHILD to the right of all children of PARENT */
+static void push_child(full_frame *parent_ff, full_frame *child_ff)
+{
+ double_link(parent_ff->rightmost_child, child_ff);
+ double_link(child_ff, 0);
+ parent_ff->rightmost_child = child_ff;
+}
+
+/* unlink CHILD from the list of all children of PARENT */
+static void unlink_child(full_frame *parent_ff, full_frame *child_ff)
+{
+ double_link(child_ff->left_sibling, child_ff->right_sibling);
+
+ if (!child_ff->right_sibling) {
+ /* this is the rightmost child -- update parent link */
+ CILK_ASSERT(parent_ff->rightmost_child == child_ff);
+ parent_ff->rightmost_child = child_ff->left_sibling;
+ }
+ child_ff->left_sibling = child_ff->right_sibling = 0; /* paranoia */
+}
+
+static void incjoin(full_frame *ff)
+{
+ ++ff->join_counter;
+}
+
+static int decjoin(full_frame *ff)
+{
+ CILK_ASSERT(ff->join_counter > 0);
+ return (--ff->join_counter);
+}
+
+static int simulate_decjoin(full_frame *ff)
+{
+ CILK_ASSERT(ff->join_counter > 0);
+ return (ff->join_counter - 1);
+}
+
+/*
+ * Pseudo-random generator defined by the congruence S' = 69070 * S
+ * mod (2^32 - 5). Marsaglia (CACM July 1993) says on page 107 that
+ * this is a ``good one''. There you go.
+ *
+ * The literature makes a big fuss about avoiding the division, but
+ * for us it is not worth the hassle.
+ */
+static const unsigned RNGMOD = ((1ULL << 32) - 5);
+static const unsigned RNGMUL = 69070U;
+
+static unsigned myrand(__cilkrts_worker *w)
+{
+ unsigned state = w->l->rand_seed;
+ state = (unsigned)((RNGMUL * (unsigned long long)state) % RNGMOD);
+ w->l->rand_seed = state;
+ return state;
+}
+
+static void mysrand(__cilkrts_worker *w, unsigned seed)
+{
+ seed %= RNGMOD;
+ seed += (seed == 0); /* 0 does not belong to the multiplicative
+ group. Use 1 instead */
+ w->l->rand_seed = seed;
+}
+
+/* W grabs its own lock */
+void __cilkrts_worker_lock(__cilkrts_worker *w)
+{
+ validate_worker(w);
+ CILK_ASSERT(w->l->do_not_steal == 0);
+
+ /* tell thieves to stay out of the way */
+ w->l->do_not_steal = 1;
+ __cilkrts_fence(); /* probably redundant */
+
+ __cilkrts_mutex_lock(w, &w->l->lock);
+}
+
+void __cilkrts_worker_unlock(__cilkrts_worker *w)
+{
+ __cilkrts_mutex_unlock(w, &w->l->lock);
+ CILK_ASSERT(w->l->do_not_steal == 1);
+ /* The fence is probably redundant. Use a release
+ operation when supported (gcc and compatibile);
+ that is faster on x86 which serializes normal stores. */
+#if defined __GNUC__ && (__GNUC__ * 10 + __GNUC_MINOR__ > 43 || __ICC >= 1110)
+ __sync_lock_release(&w->l->do_not_steal);
+#else
+ w->l->do_not_steal = 0;
+ __cilkrts_fence(); /* store-store barrier, redundant on x86 */
+#endif
+}
+
+/* try to acquire the lock of some *other* worker */
+static int worker_trylock_other(__cilkrts_worker *w,
+ __cilkrts_worker *other)
+{
+ int status = 0;
+
+ validate_worker(other);
+
+ /* This protocol guarantees that, after setting the DO_NOT_STEAL
+ flag, worker W can enter its critical section after waiting for
+ the thief currently in the critical section (if any) and at
+ most one other thief.
+
+ This requirement is overly paranoid, but it should protect us
+ against future nonsense from OS implementors.
+ */
+
+ /* compete for the right to disturb OTHER */
+ if (__cilkrts_mutex_trylock(w, &other->l->steal_lock)) {
+ if (other->l->do_not_steal) {
+ /* leave it alone */
+ } else {
+ status = __cilkrts_mutex_trylock(w, &other->l->lock);
+ }
+ __cilkrts_mutex_unlock(w, &other->l->steal_lock);
+ }
+
+
+ return status;
+}
+
+static void worker_unlock_other(__cilkrts_worker *w,
+ __cilkrts_worker *other)
+{
+ __cilkrts_mutex_unlock(w, &other->l->lock);
+}
+
+
+/* Lock macro Usage:
+ BEGIN_WITH_WORKER_LOCK(w) {
+ statement;
+ statement;
+ BEGIN_WITH_FRAME_LOCK(w, ff) {
+ statement;
+ statement;
+ } END_WITH_FRAME_LOCK(w, ff);
+ } END_WITH_WORKER_LOCK(w);
+ */
+#define BEGIN_WITH_WORKER_LOCK(w) __cilkrts_worker_lock(w); do
+#define END_WITH_WORKER_LOCK(w) while (__cilkrts_worker_unlock(w), 0)
+
+// TBD(jsukha): These are worker lock acquistions on
+// a worker whose deque is empty. My conjecture is that we
+// do not need to hold the worker lock at these points.
+// I have left them in for now, however.
+//
+// #define REMOVE_POSSIBLY_OPTIONAL_LOCKS
+#ifdef REMOVE_POSSIBLY_OPTIONAL_LOCKS
+ #define BEGIN_WITH_WORKER_LOCK_OPTIONAL(w) do
+ #define END_WITH_WORKER_LOCK_OPTIONAL(w) while (0)
+#else
+ #define BEGIN_WITH_WORKER_LOCK_OPTIONAL(w) __cilkrts_worker_lock(w); do
+ #define END_WITH_WORKER_LOCK_OPTIONAL(w) while (__cilkrts_worker_unlock(w), 0)
+#endif
+
+
+#define BEGIN_WITH_FRAME_LOCK(w, ff) \
+ do { full_frame *_locked_ff = ff; __cilkrts_frame_lock(w, _locked_ff); do
+
+#define END_WITH_FRAME_LOCK(w, ff) \
+ while (__cilkrts_frame_unlock(w, _locked_ff), 0); } while (0)
+
+/* W becomes the owner of F and F can be stolen from W */
+static void make_runnable(__cilkrts_worker *w, full_frame *ff)
+{
+ w->l->frame_ff = ff;
+
+ /* CALL_STACK is invalid (the information is stored implicitly in W) */
+ ff->call_stack = 0;
+}
+
+/*
+ * The worker parameter is unused, except for print-debugging purposes.
+ */
+static void make_unrunnable(__cilkrts_worker *w,
+ full_frame *ff,
+ __cilkrts_stack_frame *sf,
+ int is_loot,
+ const char *why)
+{
+ /* CALL_STACK becomes valid again */
+ ff->call_stack = sf;
+
+ if (sf) {
+#if CILK_LIB_DEBUG
+ if (__builtin_expect(sf->flags & CILK_FRAME_EXITING, 0))
+ __cilkrts_bug("W%d suspending exiting frame %p/%p\n", w->self, ff, sf);
+#endif
+ sf->flags |= CILK_FRAME_STOLEN | CILK_FRAME_SUSPENDED;
+ sf->worker = 0;
+
+ if (is_loot)
+ __cilkrts_put_stack(ff, sf);
+
+ /* perform any system-dependent action, such as saving the
+ state of the stack */
+ __cilkrts_make_unrunnable_sysdep(w, ff, sf, is_loot, why);
+ }
+}
+
+
+/* Push the next full frame to be made active in this worker and increment its
+ * join counter. __cilkrts_push_next_frame and pop_next_frame work on a
+ * one-element queue. This queue is used to communicate across the runtime
+ * from the code that wants to activate a frame to the code that can actually
+ * begin execution on that frame. They are asymetrical in that push
+ * increments the join counter but pop does not decrement it. Rather, a
+ * single push/pop combination makes a frame active and increments its join
+ * counter once. */
+void __cilkrts_push_next_frame(__cilkrts_worker *w, full_frame *ff)
+{
+ CILK_ASSERT(ff);
+ CILK_ASSERT(!w->l->next_frame_ff);
+ incjoin(ff);
+ w->l->next_frame_ff = ff;
+}
+
+/* Get the next full-frame to be made active in this worker. The join count
+ * of the full frame will have been incremented by the corresponding push
+ * event. See __cilkrts_push_next_frame, above.
+ */
+static full_frame *pop_next_frame(__cilkrts_worker *w)
+{
+ full_frame *ff;
+ ff = w->l->next_frame_ff;
+ // Remove the frame from the next_frame field.
+ //
+ // If this is a user worker, then there is a chance that another worker
+ // from our team could push work into our next_frame (if it is the last
+ // worker doing work for this team). The other worker's setting of the
+ // next_frame could race with our setting of next_frame to NULL. This is
+ // the only possible race condition on next_frame. However, if next_frame
+ // has a non-NULL value, then it means the team still has work to do, and
+ // there is no chance of another team member populating next_frame. Thus,
+ // it is safe to set next_frame to NULL, if it was populated. There is no
+ // need for an atomic op.
+ if (NULL != ff) {
+ w->l->next_frame_ff = NULL;
+ }
+ return ff;
+}
+
+/*
+ * Identify the single worker that is allowed to cross a sync in this frame. A
+ * thief should call this function when it is the first to steal work from a
+ * user worker. "First to steal work" may mean that there has been parallelism
+ * in the user worker before, but the whole team sync'd, and this is the first
+ * steal after that.
+ *
+ * This should happen while holding the worker and frame lock.
+ */
+static void set_sync_master(__cilkrts_worker *w, full_frame *ff)
+{
+ w->l->last_full_frame = ff;
+ ff->sync_master = w;
+}
+
+/*
+ * The sync that ends all parallelism for a particular user worker is about to
+ * be crossed. Decouple the worker and frame.
+ *
+ * No locks need to be held since the user worker isn't doing anything, and none
+ * of the system workers can steal from it. But unset_sync_master() should be
+ * called before the user worker knows about this work (i.e., before it is
+ * inserted into the w->l->next_frame_ff is set).
+ */
+static void unset_sync_master(__cilkrts_worker *w, full_frame *ff)
+{
+ CILK_ASSERT(WORKER_USER == w->l->type);
+ CILK_ASSERT(ff->sync_master == w);
+ ff->sync_master = NULL;
+ w->l->last_full_frame = NULL;
+}
+
+/********************************************************************
+ * THE protocol:
+ ********************************************************************/
+/*
+ * This is a protocol for work stealing that minimizes the overhead on
+ * the victim.
+ *
+ * The protocol uses three shared pointers into the worker's deque:
+ * - T - the "tail"
+ * - H - the "head"
+ * - E - the "exception" NB: In this case, "exception" has nothing to do
+ * with C++ throw-catch exceptions -- it refers only to a non-normal return,
+ * i.e., a steal or similar scheduling exception.
+ *
+ * with H <= E, H <= T.
+ *
+ * Stack frames SF, where H <= E < T, are available for stealing.
+ *
+ * The worker operates on the T end of the stack. The frame being
+ * worked on is not on the stack. To make a continuation available for
+ * stealing the worker pushes a from onto the stack: stores *T++ = SF.
+ * To return, it pops the frame off the stack: obtains SF = *--T.
+ *
+ * After decrementing T, the condition E > T signals to the victim that
+ * it should invoke the runtime system's "THE" exception handler. The
+ * pointer E can become INFINITY, in which case the victim must invoke
+ * the THE exception handler as soon as possible.
+ *
+ * See "The implementation of the Cilk-5 multithreaded language", PLDI 1998,
+ * http://portal.acm.org/citation.cfm?doid=277652.277725, for more information
+ * on the THE protocol.
+ */
+
+/* the infinity value of E */
+#define EXC_INFINITY ((__cilkrts_stack_frame **) (-1))
+
+static void increment_E(__cilkrts_worker *victim)
+{
+ __cilkrts_stack_frame *volatile *tmp;
+
+ // The currently executing worker must own the worker lock to touch
+ // victim->exc
+ ASSERT_WORKER_LOCK_OWNED(victim);
+
+ tmp = victim->exc;
+ if (tmp != EXC_INFINITY) {
+ /* On most x86 this pair of operations would be slightly faster
+ as an atomic exchange due to the implicit memory barrier in
+ an atomic instruction. */
+ victim->exc = tmp + 1;
+ __cilkrts_fence();
+ }
+}
+
+static void decrement_E(__cilkrts_worker *victim)
+{
+ __cilkrts_stack_frame *volatile *tmp;
+
+ // The currently executing worker must own the worker lock to touch
+ // victim->exc
+ ASSERT_WORKER_LOCK_OWNED(victim);
+
+ tmp = victim->exc;
+ if (tmp != EXC_INFINITY) {
+ /* On most x86 this pair of operations would be slightly faster
+ as an atomic exchange due to the implicit memory barrier in
+ an atomic instruction. */
+ victim->exc = tmp - 1;
+ __cilkrts_fence(); /* memory fence not really necessary */
+ }
+}
+
+#if 0
+/* for now unused, will be necessary if we implement abort */
+static void signal_THE_exception(__cilkrts_worker *wparent)
+{
+ wparent->exc = EXC_INFINITY;
+ __cilkrts_fence();
+}
+#endif
+
+static void reset_THE_exception(__cilkrts_worker *w)
+{
+ // The currently executing worker must own the worker lock to touch
+ // w->exc
+ ASSERT_WORKER_LOCK_OWNED(w);
+
+ w->exc = w->head;
+ __cilkrts_fence();
+}
+
+/* conditions under which victim->head can be stolen: */
+static int can_steal_from(__cilkrts_worker *victim)
+{
+ return ((victim->head < victim->tail) &&
+ (victim->head < victim->protected_tail));
+}
+
+/* Return TRUE if the frame can be stolen, false otherwise */
+static int dekker_protocol(__cilkrts_worker *victim)
+{
+ // increment_E and decrement_E are going to touch victim->exc. The
+ // currently executing worker must own victim's lock before they can
+ // modify it
+ ASSERT_WORKER_LOCK_OWNED(victim);
+
+ /* ASSERT(E >= H); */
+
+ increment_E(victim);
+
+ /* ASSERT(E >= H + 1); */
+ if (can_steal_from(victim)) {
+ /* success, we can steal victim->head and set H <- H + 1
+ in detach() */
+ return 1;
+ } else {
+ /* failure, restore previous state */
+ decrement_E(victim);
+ return 0;
+ }
+}
+
+
+/* Link PARENT and CHILD in the spawn tree */
+static full_frame *make_child(__cilkrts_worker *w,
+ full_frame *parent_ff,
+ __cilkrts_stack_frame *child_sf,
+ cilk_fiber *fiber)
+{
+ full_frame *child_ff = __cilkrts_make_full_frame(w, child_sf);
+
+ child_ff->parent = parent_ff;
+ push_child(parent_ff, child_ff);
+
+ //DBGPRINTF("%d- make_child - child_frame: %p, parent_frame: %p, child_sf: %p\n"
+ // " parent - parent: %p, left_sibling: %p, right_sibling: %p, rightmost_child: %p\n"
+ // " child - parent: %p, left_sibling: %p, right_sibling: %p, rightmost_child: %p\n",
+ // w->self, child, parent, child_sf,
+ // parent->parent, parent->left_sibling, parent->right_sibling, parent->rightmost_child,
+ // child->parent, child->left_sibling, child->right_sibling, child->rightmost_child);
+ CILK_ASSERT(parent_ff->call_stack);
+ child_ff->is_call_child = (fiber == NULL);
+
+ /* PLACEHOLDER_FIBER is used as non-null marker indicating that
+ child should be treated as a spawn child even though we have not
+ yet assigned a real fiber to its parent. */
+ if (fiber == PLACEHOLDER_FIBER)
+ fiber = NULL; /* Parent actually gets a null fiber, for now */
+
+ /* perform any system-dependent actions, such as capturing
+ parameter passing information */
+ /*__cilkrts_make_child_sysdep(child, parent);*/
+
+ /* Child gets reducer map and stack of parent.
+ Parent gets a new map and new stack. */
+ child_ff->fiber_self = parent_ff->fiber_self;
+ child_ff->sync_master = NULL;
+
+ if (child_ff->is_call_child) {
+ /* Cause segfault on any attempted access. The parent gets
+ the child map and stack when the child completes. */
+ parent_ff->fiber_self = 0;
+ } else {
+ parent_ff->fiber_self = fiber;
+ }
+
+ incjoin(parent_ff);
+ return child_ff;
+}
+
+static inline __cilkrts_stack_frame *__cilkrts_advance_frame(__cilkrts_stack_frame *sf)
+{
+ __cilkrts_stack_frame *p = sf->call_parent;
+ sf->call_parent = 0;
+ return p;
+}
+
+/* w should be the currently executing worker.
+ * loot_sf is the youngest stack frame in the call stack being
+ * unrolled (i.e., the most deeply nested stack frame.)
+ *
+ * When this method is called for a steal, loot_sf should be on a
+ * victim worker which is different from w.
+ * For CILK_FORCE_REDUCE, the victim worker will equal w.
+ *
+ * Before execution, the __cilkrts_stack_frame's have pointers from
+ * older to younger, i.e., a __cilkrts_stack_frame points to parent.
+ *
+ * This method creates a full frame for each __cilkrts_stack_frame in
+ * the call stack, with each full frame also pointing to its parent.
+ *
+ * The method returns the full frame created for loot_sf, i.e., the
+ * youngest full frame.
+ */
+static full_frame *unroll_call_stack(__cilkrts_worker *w,
+ full_frame *ff,
+ __cilkrts_stack_frame *const loot_sf)
+{
+ __cilkrts_stack_frame *sf = loot_sf;
+ __cilkrts_stack_frame *rev_sf = 0;
+ __cilkrts_stack_frame *t_sf;
+
+ CILK_ASSERT(sf);
+ /*CILK_ASSERT(sf->call_parent != sf);*/
+
+ /* The leafmost frame is unsynched. */
+ if (sf->worker != w)
+ sf->flags |= CILK_FRAME_UNSYNCHED;
+
+ /* Reverse the call stack to make a linked list ordered from parent
+ to child. sf->call_parent points to the child of SF instead of
+ the parent. */
+ do {
+ t_sf = (sf->flags & (CILK_FRAME_DETACHED|CILK_FRAME_STOLEN|CILK_FRAME_LAST))? 0 : sf->call_parent;
+ sf->call_parent = rev_sf;
+ rev_sf = sf;
+ sf = t_sf;
+ } while (sf);
+ sf = rev_sf;
+
+ /* Promote each stack frame to a full frame in order from parent
+ to child, following the reversed list we just built. */
+ make_unrunnable(w, ff, sf, sf == loot_sf, "steal 1");
+ /* T is the *child* of SF, because we have reversed the list */
+ for (t_sf = __cilkrts_advance_frame(sf); t_sf;
+ sf = t_sf, t_sf = __cilkrts_advance_frame(sf)) {
+ ff = make_child(w, ff, t_sf, NULL);
+ make_unrunnable(w, ff, t_sf, t_sf == loot_sf, "steal 2");
+ }
+
+ /* XXX What if the leafmost frame does not contain a sync
+ and this steal is from promote own deque? */
+ /*sf->flags |= CILK_FRAME_UNSYNCHED;*/
+
+ CILK_ASSERT(!sf->call_parent);
+ return ff;
+}
+
+/* detach the top of the deque frame from the VICTIM and install a new
+ CHILD frame in its place */
+static void detach_for_steal(__cilkrts_worker *w,
+ __cilkrts_worker *victim,
+ cilk_fiber* fiber)
+{
+ /* ASSERT: we own victim->lock */
+
+ full_frame *parent_ff, *child_ff, *loot_ff;
+ __cilkrts_stack_frame *volatile *h;
+ __cilkrts_stack_frame *sf;
+
+ w->l->team = victim->l->team;
+
+ CILK_ASSERT(w->l->frame_ff == 0 || w == victim);
+
+ h = victim->head;
+
+ CILK_ASSERT(*h);
+
+ victim->head = h + 1;
+
+ parent_ff = victim->l->frame_ff;
+ BEGIN_WITH_FRAME_LOCK(w, parent_ff) {
+ /* parent no longer referenced by victim */
+ decjoin(parent_ff);
+
+ /* obtain the victim call stack */
+ sf = *h;
+
+ /* perform system-dependent normalizations */
+ /*__cilkrts_normalize_call_stack_on_steal(sf);*/
+
+ /* unroll PARENT_FF with call stack SF, adopt the youngest
+ frame LOOT. If loot_ff == parent_ff, then we hold loot_ff->lock,
+ otherwise, loot_ff is newly created and we can modify it without
+ holding its lock. */
+ loot_ff = unroll_call_stack(w, parent_ff, sf);
+
+ #if REDPAR_DEBUG >= 3
+ fprintf(stderr, "[W=%d, victim=%d, desc=detach, parent_ff=%p, loot=%p]\n",
+ w->self, victim->self,
+ parent_ff, loot_ff);
+ #endif
+
+ if (WORKER_USER == victim->l->type &&
+ NULL == victim->l->last_full_frame) {
+ // Mark this looted frame as special: only the original user worker
+ // may cross the sync.
+ //
+ // This call is a shared access to
+ // victim->l->last_full_frame.
+ set_sync_master(victim, loot_ff);
+ }
+
+ /* LOOT is the next frame that the thief W is supposed to
+ run, unless the thief is stealing from itself, in which
+ case the thief W == VICTIM executes CHILD and nobody
+ executes LOOT. */
+ if (w == victim) {
+ /* Pretend that frame has been stolen */
+ loot_ff->call_stack->flags |= CILK_FRAME_UNSYNCHED;
+ loot_ff->simulated_stolen = 1;
+ }
+ else
+ __cilkrts_push_next_frame(w, loot_ff);
+
+ // After this "push_next_frame" call, w now owns loot_ff.
+ child_ff = make_child(w, loot_ff, 0, fiber);
+
+ BEGIN_WITH_FRAME_LOCK(w, child_ff) {
+ /* install child in the victim's work queue, taking
+ the parent_ff's place */
+ /* child is referenced by victim */
+ incjoin(child_ff);
+
+ // With this call, w is bestowing ownership of the newly
+ // created frame child_ff to the victim, and victim is
+ // giving up ownership of parent_ff.
+ //
+ // Worker w will either take ownership of parent_ff
+ // if parent_ff == loot_ff, or parent_ff will be
+ // suspended.
+ //
+ // Note that this call changes the victim->frame_ff
+ // while the victim may be executing.
+ make_runnable(victim, child_ff);
+ } END_WITH_FRAME_LOCK(w, child_ff);
+ } END_WITH_FRAME_LOCK(w, parent_ff);
+}
+
+/**
+ * @brief cilk_fiber_proc that resumes user code after a successful
+ * random steal.
+
+ * This function longjmps back into the user code whose state is
+ * stored in cilk_fiber_get_data(fiber)->resume_sf. The stack pointer
+ * is adjusted so that the code resumes on the specified fiber stack
+ * instead of its original stack.
+ *
+ * This method gets executed only on a fiber freshly allocated from a
+ * pool.
+ *
+ * @param fiber The fiber being used to resume user code.
+ * @param arg Unused.
+ */
+static
+void fiber_proc_to_resume_user_code_for_random_steal(cilk_fiber *fiber)
+{
+ cilk_fiber_data *data = cilk_fiber_get_data(fiber);
+ __cilkrts_stack_frame* sf = data->resume_sf;
+ full_frame *ff;
+
+ CILK_ASSERT(sf);
+
+ // When we pull the resume_sf out of the fiber to resume it, clear
+ // the old value.
+ data->resume_sf = NULL;
+ CILK_ASSERT(sf->worker == data->owner);
+ ff = sf->worker->l->frame_ff;
+
+ // For Win32, we need to overwrite the default exception handler
+ // in this function, so that when the OS exception handling code
+ // walks off the top of the current Cilk stack, it reaches our stub
+ // handler.
+
+ // Also, this function needs to be wrapped into a try-catch block
+ // so the compiler generates the appropriate exception information
+ // in this frame.
+
+ // TBD: IS THIS HANDLER IN THE WRONG PLACE? Can we longjmp out of
+ // this function (and does it matter?)
+#if defined(_WIN32) && !defined(_WIN64)
+ install_exception_stub_handler();
+ __try
+#endif
+ {
+ char* new_sp = sysdep_reset_jump_buffers_for_resume(fiber, ff, sf);
+
+ // Notify the Intel tools that we're stealing code
+ ITT_SYNC_ACQUIRED(sf->worker);
+ NOTIFY_ZC_INTRINSIC("cilk_continue", sf);
+
+ // TBD: We'd like to move TBB-interop methods into the fiber
+ // eventually.
+ cilk_fiber_invoke_tbb_stack_op(fiber, CILK_TBB_STACK_ADOPT);
+
+ sf->flags &= ~CILK_FRAME_SUSPENDED;
+
+ // longjmp to user code. Don't process exceptions here,
+ // because we are resuming a stolen frame.
+ sysdep_longjmp_to_sf(new_sp, sf, NULL);
+ /*NOTREACHED*/
+ // Intel's C compiler respects the preceding lint pragma
+ }
+#if defined(_WIN32) && !defined(_WIN64)
+ __except (CILK_ASSERT(!"should not execute the the stub filter"),
+ EXCEPTION_EXECUTE_HANDLER)
+ {
+ // If we are here, that means something very wrong
+ // has happened in our exception processing...
+ CILK_ASSERT(! "should not be here!");
+ }
+#endif
+}
+
+static void random_steal(__cilkrts_worker *w)
+{
+ __cilkrts_worker *victim = NULL;
+ cilk_fiber *fiber = NULL;
+ int n;
+ int success = 0;
+ int32_t victim_id;
+
+ // Nothing's been stolen yet. When true, this will flag
+ // setup_for_execution_pedigree to increment the pedigree
+ w->l->work_stolen = 0;
+
+ /* If the user has disabled stealing (using the debugger) we fail */
+ if (__builtin_expect(w->g->stealing_disabled, 0))
+ return;
+
+ CILK_ASSERT(w->l->type == WORKER_SYSTEM || w->l->team == w);
+
+ /* If there is only one processor work can still be stolen.
+ There must be only one worker to prevent stealing. */
+ CILK_ASSERT(w->g->total_workers > 1);
+
+ /* pick random *other* victim */
+ n = myrand(w) % (w->g->total_workers - 1);
+ if (n >= w->self)
+ ++n;
+
+ // If we're replaying a log, override the victim. -1 indicates that
+ // we've exhausted the list of things this worker stole when we recorded
+ // the log so just return. If we're not replaying a log,
+ // replay_get_next_recorded_victim() just returns the victim ID passed in.
+ n = replay_get_next_recorded_victim(w, n);
+ if (-1 == n)
+ return;
+
+ victim = w->g->workers[n];
+
+ START_INTERVAL(w, INTERVAL_FIBER_ALLOCATE) {
+ /* Verify that we can get a stack. If not, no need to continue. */
+ fiber = cilk_fiber_allocate(&w->l->fiber_pool);
+ } STOP_INTERVAL(w, INTERVAL_FIBER_ALLOCATE);
+
+
+ if (NULL == fiber) {
+#if FIBER_DEBUG >= 2
+ fprintf(stderr, "w=%d: failed steal because we could not get a fiber\n",
+ w->self);
+#endif
+ return;
+ }
+
+ /* do not steal from self */
+ CILK_ASSERT (victim != w);
+
+ /* Execute a quick check before engaging in the THE protocol.
+ Avoid grabbing locks if there is nothing to steal. */
+ if (!can_steal_from(victim)) {
+ NOTE_INTERVAL(w, INTERVAL_STEAL_FAIL_EMPTYQ);
+ START_INTERVAL(w, INTERVAL_FIBER_DEALLOCATE) {
+ int ref_count = cilk_fiber_remove_reference(fiber, &w->l->fiber_pool);
+ // Fibers we use when trying to steal should not be active,
+ // and thus should not have any other references.
+ CILK_ASSERT(0 == ref_count);
+ } STOP_INTERVAL(w, INTERVAL_FIBER_DEALLOCATE);
+ return;
+ }
+
+ /* Attempt to steal work from the victim */
+ if (worker_trylock_other(w, victim)) {
+ if (w->l->type == WORKER_USER && victim->l->team != w) {
+
+ // Fail to steal if this is a user worker and the victim is not
+ // on this team. If a user worker were allowed to steal work
+ // descended from another user worker, the former might not be
+ // done with its work by the time it was needed to resume and
+ // unbind. Therefore, user workers are not permitted to change
+ // teams.
+
+ // There is no race on the victim's team because the victim cannot
+ // change its team until it runs out of work to do, at which point
+ // it will try to take out its own lock, and this worker already
+ // holds it.
+ NOTE_INTERVAL(w, INTERVAL_STEAL_FAIL_USER_WORKER);
+
+ } else if (victim->l->frame_ff) {
+ // A successful steal will change victim->frame_ff, even
+ // though the victim may be executing. Thus, the lock on
+ // the victim's deque is also protecting victim->frame_ff.
+ if (dekker_protocol(victim)) {
+ int proceed_with_steal = 1; // optimistic
+
+ // If we're replaying a log, verify that this the correct frame
+ // to steal from the victim
+ if (! replay_match_victim_pedigree(w, victim))
+ {
+ // Abort the steal attempt. decrement_E(victim) to
+ // counter the increment_E(victim) done by the
+ // dekker protocol
+ decrement_E(victim);
+ proceed_with_steal = 0;
+ }
+
+ if (proceed_with_steal)
+ {
+ START_INTERVAL(w, INTERVAL_STEAL_SUCCESS) {
+ success = 1;
+ detach_for_steal(w, victim, fiber);
+ victim_id = victim->self;
+
+ #if REDPAR_DEBUG >= 1
+ fprintf(stderr, "Wkr %d stole from victim %d, fiber = %p\n",
+ w->self, victim->self, fiber);
+ #endif
+
+ // The use of victim->self contradicts our
+ // classification of the "self" field as
+ // local. But since this code is only for
+ // debugging, it is ok.
+ DBGPRINTF ("%d-%p: Stealing work from worker %d\n"
+ " sf: %p, call parent: %p\n",
+ w->self, GetCurrentFiber(), victim->self,
+ w->l->next_frame_ff->call_stack,
+ w->l->next_frame_ff->call_stack->call_parent);
+ } STOP_INTERVAL(w, INTERVAL_STEAL_SUCCESS);
+ } // end if(proceed_with_steal)
+ } else {
+ NOTE_INTERVAL(w, INTERVAL_STEAL_FAIL_DEKKER);
+ }
+ } else {
+ NOTE_INTERVAL(w, INTERVAL_STEAL_FAIL_EMPTYQ);
+ }
+ worker_unlock_other(w, victim);
+ } else {
+ NOTE_INTERVAL(w, INTERVAL_STEAL_FAIL_LOCK);
+ }
+
+ // Record whether work was stolen. When true, this will flag
+ // setup_for_execution_pedigree to increment the pedigree
+ w->l->work_stolen = success;
+
+ if (0 == success) {
+ // failed to steal work. Return the fiber to the pool.
+ START_INTERVAL(w, INTERVAL_FIBER_DEALLOCATE) {
+ int ref_count = cilk_fiber_remove_reference(fiber, &w->l->fiber_pool);
+ // Fibers we use when trying to steal should not be active,
+ // and thus should not have any other references.
+ CILK_ASSERT(0 == ref_count);
+ } STOP_INTERVAL(w, INTERVAL_FIBER_DEALLOCATE);
+ }
+ else
+ {
+ // Since our steal was successful, finish initialization of
+ // the fiber.
+ cilk_fiber_reset_state(fiber,
+ fiber_proc_to_resume_user_code_for_random_steal);
+ // Record the pedigree of the frame that w has stolen.
+ // record only if CILK_RECORD_LOG is set
+ replay_record_steal(w, victim_id);
+ }
+}
+
+
+
+/**
+ * At a provably good steal, we need to transfer the child reducer map
+ * from ff->children_reducer_map into v->reducer_map, where v is the
+ * worker that resumes execution of ff.
+ *
+ * Normally, we have v == w, where w is the currently executing
+ * worker. In the case where we are resuming a team leader on a user
+ * worker, however, v might differ from w.
+
+ * Thus, this, operation is a no-op, since we can't really move
+ * ff->children_reducer_map into w here.
+ *
+ * Instead, this work is done in setup_for_execution_reducers().
+ */
+static inline void provably_good_steal_reducers(__cilkrts_worker *w,
+ full_frame *ff)
+{
+ // No-op.
+}
+
+/* at a provably good steal, incorporate the accumulated exceptions of
+ children into the parent's exception */
+static void provably_good_steal_exceptions(__cilkrts_worker *w,
+ full_frame *ff)
+{
+ // ASSERT: we own ff->lock
+ ff->pending_exception =
+ __cilkrts_merge_pending_exceptions(w,
+ ff->child_pending_exception,
+ ff->pending_exception);
+ ff->child_pending_exception = NULL;
+}
+
+/* At sync discard the frame's old stack and take the leftmost child's. */
+static void provably_good_steal_stacks(__cilkrts_worker *w, full_frame *ff)
+{
+ CILK_ASSERT(NULL == ff->fiber_self);
+ ff->fiber_self = ff->fiber_child;
+ ff->fiber_child = NULL;
+}
+
+static void __cilkrts_mark_synched(full_frame *ff)
+{
+ ff->call_stack->flags &= ~CILK_FRAME_UNSYNCHED;
+ ff->simulated_stolen = 0;
+}
+
+static
+enum provably_good_steal_t provably_good_steal(__cilkrts_worker *w,
+ full_frame *ff)
+{
+ // ASSERT: we hold w->lock and ff->lock
+
+ enum provably_good_steal_t result = ABANDON_EXECUTION;
+
+ // If the current replay entry is a sync record matching the worker's
+ // pedigree, AND this isn't the last child to the sync, return
+ // WAIT_FOR_CONTINUE to indicate that the caller should loop until
+ // we find the right frame to steal and CONTINUE_EXECUTION is returned.
+ int match_found = replay_match_sync_pedigree(w);
+ if (match_found && (0 != simulate_decjoin(ff)))
+ return WAIT_FOR_CONTINUE;
+
+ START_INTERVAL(w, INTERVAL_PROVABLY_GOOD_STEAL) {
+ if (decjoin(ff) == 0) {
+ provably_good_steal_reducers(w, ff);
+ provably_good_steal_exceptions(w, ff);
+ provably_good_steal_stacks(w, ff);
+ __cilkrts_mark_synched(ff);
+
+ // If the original owner wants this frame back (to resume
+ // it on its original thread) pass it back now.
+ if (NULL != ff->sync_master) {
+ // The frame wants to go back and be executed by the original
+ // user thread. We can throw caution to the wind and push the
+ // frame straight onto its queue because the only way we have
+ // gotten to this point of being able to continue execution of
+ // the frame is if the original user worker is spinning without
+ // work.
+
+ unset_sync_master(w->l->team, ff);
+ __cilkrts_push_next_frame(w->l->team, ff);
+
+ // If this is the team leader we're not abandoning the work
+ if (w == w->l->team)
+ result = CONTINUE_EXECUTION;
+ } else {
+ __cilkrts_push_next_frame(w, ff);
+ result = CONTINUE_EXECUTION; // Continue working on this thread
+ }
+
+ // The __cilkrts_push_next_frame() call changes ownership
+ // of ff to the specified worker.
+ }
+ } STOP_INTERVAL(w, INTERVAL_PROVABLY_GOOD_STEAL);
+
+ // Only write a SYNC record if:
+ // - We're recording a log *AND*
+ // - We're the worker continuing from this sync
+ replay_record_sync(w, result == CONTINUE_EXECUTION);
+
+ // If we're replaying a log, and matched a sync from the log, mark the
+ // sync record seen if the sync isn't going to be abandoned.
+ replay_advance_from_sync (w, match_found, result == CONTINUE_EXECUTION);
+
+ return result;
+}
+
+static void unconditional_steal(__cilkrts_worker *w,
+ full_frame *ff)
+{
+ // ASSERT: we hold ff->lock
+
+ START_INTERVAL(w, INTERVAL_UNCONDITIONAL_STEAL) {
+ decjoin(ff);
+ __cilkrts_push_next_frame(w, ff);
+ } STOP_INTERVAL(w, INTERVAL_UNCONDITIONAL_STEAL);
+}
+
+
+/* CHILD is about to die. Give its exceptions to a sibling or to the
+ parent. */
+static inline void splice_exceptions_for_call(__cilkrts_worker *w,
+ full_frame *parent_ff,
+ full_frame *child_ff)
+{
+ // ASSERT: We own parent_ff->lock
+ CILK_ASSERT(child_ff->is_call_child);
+ CILK_ASSERT(NULL == child_ff->right_pending_exception);
+ CILK_ASSERT(NULL == parent_ff->pending_exception);
+
+ parent_ff->pending_exception = child_ff->pending_exception;
+ child_ff->pending_exception = NULL;
+}
+
+/**
+ * Merge exceptions for a dying child.
+ *
+ * @param w The currently executing worker.
+ * @param ff The child frame that is dying.
+ * @param left_exception_ptr Pointer to the exception that is to our left.
+ */
+static inline
+void splice_exceptions_for_spawn(__cilkrts_worker *w,
+ full_frame *ff,
+ struct pending_exception_info **left_exception_ptr)
+{
+ // ASSERT: parent_ff == child_ff->parent.
+ // ASSERT: We own parent_ff->lock
+
+ // Merge current exception into the slot where the left
+ // exception should go.
+ *left_exception_ptr =
+ __cilkrts_merge_pending_exceptions(w,
+ *left_exception_ptr,
+ ff->pending_exception);
+ ff->pending_exception = NULL;
+
+
+ // Merge right exception into the slot where the left exception
+ // should go.
+ *left_exception_ptr =
+ __cilkrts_merge_pending_exceptions(w,
+ *left_exception_ptr,
+ ff->right_pending_exception);
+ ff->right_pending_exception = NULL;
+}
+
+
+static inline void splice_stacks_for_call(__cilkrts_worker *w,
+ full_frame *parent_ff,
+ full_frame *child_ff)
+{
+#if CILK_LIB_DEBUG
+ if (parent_ff->call_stack)
+ CILK_ASSERT(!(parent_ff->call_stack->flags & CILK_FRAME_MBZ));
+#endif
+
+ /* A synched frame does not have accumulated child reducers. */
+ CILK_ASSERT(!child_ff->fiber_child);
+ CILK_ASSERT(child_ff->is_call_child);
+
+ /* An attached parent has no self fiber. It may have
+ accumulated child fibers or child owners, which should be
+ ignored until sync. */
+ CILK_ASSERT(!parent_ff->fiber_self);
+ parent_ff->fiber_self = child_ff->fiber_self;
+ child_ff->fiber_self = NULL;
+}
+
+static void finalize_child_for_call(__cilkrts_worker *w,
+ full_frame *parent_ff,
+ full_frame *child_ff)
+{
+ // ASSERT: we hold w->lock and parent_ff->lock
+
+ START_INTERVAL(w, INTERVAL_FINALIZE_CHILD) {
+ CILK_ASSERT(child_ff->is_call_child);
+ CILK_ASSERT(child_ff->join_counter == 0);
+ CILK_ASSERT(!child_ff->rightmost_child);
+ CILK_ASSERT(child_ff == parent_ff->rightmost_child);
+
+ // CHILD is about to die.
+ // Splicing out reducers is a no-op for a call since
+ // w->reducer_map should already store the correct
+ // reducer map.
+
+ // ASSERT there are no maps left to reduce.
+ CILK_ASSERT(NULL == child_ff->children_reducer_map);
+ CILK_ASSERT(NULL == child_ff->right_reducer_map);
+
+ splice_exceptions_for_call(w, parent_ff, child_ff);
+
+ splice_stacks_for_call(w, parent_ff, child_ff);
+
+ /* remove CHILD from list of children of PARENT */
+ unlink_child(parent_ff, child_ff);
+
+ /* continue with the parent. */
+ unconditional_steal(w, parent_ff);
+ __cilkrts_destroy_full_frame(w, child_ff);
+ } STOP_INTERVAL(w, INTERVAL_FINALIZE_CHILD);
+}
+
+
+/**
+ * The invariant on ff->children_reducer_map is that when ff is
+ * synched and when we are about to resume execution of ff, at least
+ * one of ff->children_reducer_map and w->reducer_map must be NULL.
+ *
+ * Consider the two possibilities before resuming execution of ff:
+ *
+ * 1. Suppose ff is synched and suspended. Then either
+ *
+ * (a) ff->children_reducer_map stores the reducer map that w
+ * should use, where w is the worker resuming execution of ff,
+ * OR
+ * (b) w already has a user map, and ff->children_reducer_map is NULL.
+ *
+ * Case (a) happens when we are resuming execution of ff as a
+ * provably good steal. In this case, w->reducer_map should be
+ * NULL and ff->children_reducer_map is valid. To resume
+ * execution of ff on w, set w->reducer_map to
+ * ff->children_reducer_map.
+ *
+ * Case (b) occurs when we resume execution of ff because ff is a
+ * called child. Then, ff->children_reducer_map should be NULL,
+ * and w should already have a valid reducer map when resuming
+ * execution of ff. We resume execution of ff without changing
+ * w->reducer_map.
+ *
+ * 2. Suppose frame ff is not synched (i.e., it is active and might have
+ * active children). Then ff->children_reducer_map is the slot for
+ * storing the reducer map from ff's leftmost child, as in the reducer
+ * protocol. The runtime may resume execution of ff while it is not
+ * synched only because of a steal.
+ * In this case, while we are resuming ff, ff->children_reducer_map
+ * may be non-NULL (because one of ff's children has completed).
+ * We resume execution of ff without changing w->reducer_map.
+ */
+static void setup_for_execution_reducers(__cilkrts_worker *w,
+ full_frame *ff)
+{
+ // We only need to move ff->children_reducer_map into
+ // w->reducer_map in case 1(a).
+ //
+ // First check whether ff is synched.
+ __cilkrts_stack_frame *sf = ff->call_stack;
+ if (!(sf->flags & CILK_FRAME_UNSYNCHED)) {
+ // In this case, ff is synched. (Case 1).
+ CILK_ASSERT(!ff->rightmost_child);
+
+ // Test whether we are in case 1(a) and have
+ // something to do. Note that if both
+ // ff->children_reducer_map and w->reducer_map are NULL, we
+ // can't distinguish between cases 1(a) and 1(b) here.
+ if (ff->children_reducer_map) {
+ // We are in Case 1(a).
+ CILK_ASSERT(!w->reducer_map);
+ w->reducer_map = ff->children_reducer_map;
+ ff->children_reducer_map = NULL;
+ }
+ }
+}
+
+static void setup_for_execution_exceptions(__cilkrts_worker *w,
+ full_frame *ff)
+{
+ CILK_ASSERT(NULL == w->l->pending_exception);
+ w->l->pending_exception = ff->pending_exception;
+ ff->pending_exception = NULL;
+}
+
+#if 0 /* unused */
+static void setup_for_execution_stack(__cilkrts_worker *w,
+ full_frame *ff)
+{
+}
+#endif
+
+/*
+ * setup_for_execution_pedigree
+ *
+ * Copies the pedigree information from the frame we're resuming to the
+ * worker. Increments the pedigree if this is work that has been stolen
+ * to match the increment on a return from a spawn helper.
+ */
+static void setup_for_execution_pedigree(__cilkrts_worker *w)
+{
+ int pedigree_unsynched;
+ __cilkrts_stack_frame *sf = w->current_stack_frame;
+
+ CILK_ASSERT(NULL != sf);
+
+ // If this isn't an ABI 1 or later frame, there's no pedigree information
+ if (0 == CILK_FRAME_VERSION_VALUE(sf->flags))
+ return;
+
+ // Note whether the pedigree is unsynched and clear the flag before
+ // we forget
+ pedigree_unsynched = sf->flags & CILK_FRAME_SF_PEDIGREE_UNSYNCHED;
+ sf->flags &= ~CILK_FRAME_SF_PEDIGREE_UNSYNCHED;
+
+ // If we're just marshalling onto this worker, do not increment
+ // the rank since that wouldn't happen in a sequential execution
+ if (w->l->work_stolen || pedigree_unsynched)
+ {
+ if (w->l->work_stolen)
+ w->pedigree.rank = sf->parent_pedigree.rank + 1;
+ else
+ w->pedigree.rank = sf->parent_pedigree.rank;
+ }
+
+ w->pedigree.parent = sf->parent_pedigree.parent;
+ w->l->work_stolen = 0;
+}
+
+static void setup_for_execution(__cilkrts_worker *w,
+ full_frame *ff,
+ int is_return_from_call)
+{
+ // ASSERT: We own w->lock and ff->lock || P == 1
+
+ setup_for_execution_reducers(w, ff);
+ setup_for_execution_exceptions(w, ff);
+ /*setup_for_execution_stack(w, ff);*/
+
+ ff->call_stack->worker = w;
+ w->current_stack_frame = ff->call_stack;
+
+ // If this is a return from a call, leave the pedigree alone
+ if (! is_return_from_call)
+ setup_for_execution_pedigree(w);
+
+ __cilkrts_setup_for_execution_sysdep(w, ff);
+
+ w->head = w->tail = w->l->ltq;
+ reset_THE_exception(w);
+
+ make_runnable(w, ff);
+}
+
+
+/*
+ * Called by the scheduling fiber, right before
+ * resuming a sf/ff for user code.
+ *
+ * This method associates the specified sf with the worker.
+ *
+ * It also asserts that w, ff, and sf all have the expected properties
+ * for resuming user code.
+ */
+void scheduling_fiber_prepare_to_resume_user_code(__cilkrts_worker *w,
+ full_frame *ff,
+ __cilkrts_stack_frame *sf)
+{
+ w->current_stack_frame = sf;
+ sf->worker = w;
+
+ // Lots of debugging checks on the state of the fiber we might be
+ // resuming.
+#if FIBER_DEBUG >= 1
+# if FIBER_DEBUG >= 3
+ {
+ fprintf(stderr, "w=%d: ff=%p, sf=%p. about to resume user code\n",
+ w->self, ff, sf);
+ }
+# endif
+
+ const int flags = sf->flags;
+ CILK_ASSERT(flags & CILK_FRAME_SUSPENDED);
+ CILK_ASSERT(!sf->call_parent);
+ CILK_ASSERT(w->head == w->tail);
+
+ /* A frame can not be resumed unless it was suspended. */
+ CILK_ASSERT(ff->sync_sp != NULL);
+
+ /* The leftmost frame has no allocated stack */
+ if (ff->simulated_stolen)
+ CILK_ASSERT(flags & CILK_FRAME_UNSYNCHED);
+ else if (flags & CILK_FRAME_UNSYNCHED)
+ /* XXX By coincidence sync_sp could be null. */
+ CILK_ASSERT(ff->fiber_self != NULL);
+ else
+ /* XXX This frame could be resumed unsynched on the leftmost stack */
+ CILK_ASSERT((ff->sync_master == 0 || ff->sync_master == w));
+ CILK_ASSERT(w->l->frame_ff == ff);
+#endif
+}
+
+
+/**
+ * This method is the first method that should execute after we've
+ * switched to a scheduling fiber from user code.
+ *
+ * @param fiber The scheduling fiber for the current worker.
+ * @param wptr The current worker.
+ */
+static void enter_runtime_transition_proc(cilk_fiber *fiber)
+{
+ // We can execute this method for one of three reasons:
+ // 1. Undo-detach finds parent stolen.
+ // 2. Sync suspends frame.
+ // 3. Return from Cilk entry point.
+ //
+ //
+ // In cases 1 and 2, the frame may be truly suspended or
+ // may be immediately executed by this worker after provably_good_steal.
+ //
+ //
+ // There is a fourth case, which can, but does not need to execute
+ // this function:
+ // 4. Starting up the scheduling loop on a user or
+ // system worker. In this case, we won't have
+ // a scheduling stack function to run.
+ __cilkrts_worker* w = cilk_fiber_get_owner(fiber);
+ if (w->l->post_suspend) {
+ // Run the continuation function passed to longjmp_into_runtime
+ run_scheduling_stack_fcn(w);
+
+ // After we have jumped into the runtime and run the
+ // scheduling function, any reducer map the worker had before entering the runtime
+ // should have already been saved into the appropriate full
+ // frame.
+ CILK_ASSERT(NULL == w->reducer_map);
+
+ // There shouldn't be any uncaught exceptions.
+ //
+ // In Windows, the OS catches any exceptions not caught by the
+ // user code. Thus, we are omitting the check on Windows.
+ //
+ // On Android, calling std::uncaught_exception with the stlport
+ // library causes a seg fault. Since we're not supporting
+ // exceptions there at this point, just don't do the check
+ //
+ // TBD: Is this check also safe to do on Windows?
+ CILKBUG_ASSERT_NO_UNCAUGHT_EXCEPTION();
+ }
+}
+
+
+/**
+ * Method called to jump back to executing user code.
+ *
+ * A normal return from the runtime back to resuming user code calls
+ * this method. A computation executed using force_reduce also calls
+ * this method to return to user code.
+ *
+ * This function should not contain any code that depends on a fiber.
+ * In a force-reduce case, the user worker may not have a fiber. In
+ * the force-reduce case, we call this method directly instead of
+ * calling @c user_code_resume_after_switch_into_runtime.
+ */
+static inline NORETURN
+cilkrts_resume(__cilkrts_stack_frame *sf, full_frame *ff)
+{
+ // Save the sync stack pointer, and do the bookkeeping
+ char* sync_sp = ff->sync_sp;
+ __cilkrts_take_stack(ff, sync_sp); // leaves ff->sync_sp null
+
+ sf->flags &= ~CILK_FRAME_SUSPENDED;
+ // Actually longjmp to the user code.
+ // We may have exceptions to deal with, since we are resuming
+ // a previous-suspended frame.
+ sysdep_longjmp_to_sf(sync_sp, sf, ff);
+}
+
+
+/**
+ * Called by the user-code fiber right before resuming a full frame
+ * (sf/ff).
+ *
+ * This method pulls sf/ff out of the worker, and then calls
+ * cilkrts_resume to jump to user code.
+ */
+static NORETURN
+user_code_resume_after_switch_into_runtime(cilk_fiber *fiber)
+{
+ __cilkrts_worker *w = cilk_fiber_get_owner(fiber);
+ __cilkrts_stack_frame *sf;
+ full_frame *ff;
+ sf = w->current_stack_frame;
+ ff = sf->worker->l->frame_ff;
+
+#if FIBER_DEBUG >= 1
+ CILK_ASSERT(ff->fiber_self == fiber);
+ cilk_fiber_data *fdata = cilk_fiber_get_data(fiber);
+ DBGPRINTF ("%d-%p: resume_after_switch_into_runtime, fiber=%p\n",
+ w->self, w, fiber);
+ CILK_ASSERT(sf == fdata->resume_sf);
+#endif
+
+ // Notify the Intel tools that we're stealing code
+ ITT_SYNC_ACQUIRED(sf->worker);
+ NOTIFY_ZC_INTRINSIC("cilk_continue", sf);
+ cilk_fiber_invoke_tbb_stack_op(fiber, CILK_TBB_STACK_ADOPT);
+
+ // Actually jump to user code.
+ cilkrts_resume(sf, ff);
+ }
+
+
+/* The current stack is about to either be suspended or destroyed. This
+ * function will switch to the stack on which the scheduler is suspended and
+ * resume running the scheduler within function do_work(). Upon waking up,
+ * the scheduler will run the 'cont' function, using the supplied worker and
+ * frame.
+ */
+static NORETURN
+longjmp_into_runtime(__cilkrts_worker *w,
+ scheduling_stack_fcn_t fcn,
+ __cilkrts_stack_frame *sf)
+{
+ full_frame *ff, *ff2;
+
+ CILK_ASSERT(!w->l->post_suspend);
+ ff = w->l->frame_ff;
+
+ // If we've got only one worker, stealing shouldn't be possible.
+ // Assume that this is a steal or return from spawn in a force-reduce case.
+ // We don't have a scheduling stack to switch to, so call the continuation
+ // function directly.
+ if (1 == w->g->P) {
+ fcn(w, ff, sf);
+
+ /* The call to function c() will have pushed ff as the next frame. If
+ * this were a normal (non-forced-reduce) execution, there would have
+ * been a pop_next_frame call in a separate part of the runtime. We
+ * must call pop_next_frame here to complete the push/pop cycle. */
+ ff2 = pop_next_frame(w);
+
+ setup_for_execution(w, ff2, 0);
+ scheduling_fiber_prepare_to_resume_user_code(w, ff2, w->current_stack_frame);
+ cilkrts_resume(w->current_stack_frame, ff2);
+
+// Suppress clang warning that the expression result is unused
+#if defined(__clang__) && (! defined(__INTEL_COMPILER))
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wunused-value"
+#endif // __clang__
+ /* no return */
+ CILK_ASSERT(((void)"returned from __cilkrts_resume", 0));
+#if defined(__clang__) && (! defined(__INTEL_COMPILER))
+# pragma clang diagnostic pop
+#endif // __clang__
+ }
+
+ w->l->post_suspend = fcn;
+ w->l->suspended_stack = sf;
+
+ ITT_SYNC_RELEASING(w);
+ ITT_SYNC_PREPARE(w);
+
+#if FIBER_DEBUG >= 2
+ fprintf(stderr, "ThreadId=%p, W=%d: about to switch into runtime... w->l->frame_ff = %p, sf=%p\n",
+ cilkos_get_current_thread_id(),
+ w->self, w->l->frame_ff,
+ sf);
+#endif
+
+ // Current fiber is either the (1) one we are about to free,
+ // or (2) it has been passed up to the parent.
+ cilk_fiber *current_fiber = ( w->l->fiber_to_free ?
+ w->l->fiber_to_free :
+ w->l->frame_ff->parent->fiber_child );
+ cilk_fiber_data* fdata = cilk_fiber_get_data(current_fiber);
+ CILK_ASSERT(NULL == w->l->frame_ff->fiber_self);
+
+ // Clear the sf in the current fiber for cleanliness, to prevent
+ // us from accidentally resuming a bad sf.
+ // Technically, resume_sf gets overwritten for a fiber when
+ // we are about to resume it anyway.
+ fdata->resume_sf = NULL;
+ CILK_ASSERT(fdata->owner == w);
+
+ // Set the function to execute immediately after switching to the
+ // scheduling fiber, but before freeing any fibers.
+ cilk_fiber_set_post_switch_proc(w->l->scheduling_fiber,
+ enter_runtime_transition_proc);
+ cilk_fiber_invoke_tbb_stack_op(current_fiber, CILK_TBB_STACK_ORPHAN);
+
+ if (w->l->fiber_to_free) {
+ // Case 1: we are freeing this fiber. We never
+ // resume this fiber again after jumping into the runtime.
+ w->l->fiber_to_free = NULL;
+
+ // Extra check. Normally, the fiber we are about to switch to
+ // should have a NULL owner.
+ CILK_ASSERT(NULL == cilk_fiber_get_data(w->l->scheduling_fiber)->owner);
+#if FIBER_DEBUG >= 4
+ fprintf(stderr, "ThreadId=%p, W=%d: about to switch into runtime.. current_fiber = %p, deallcoate, switch to fiber %p\n",
+ cilkos_get_current_thread_id(),
+ w->self,
+ current_fiber, w->l->scheduling_fiber);
+#endif
+ cilk_fiber_invoke_tbb_stack_op(current_fiber, CILK_TBB_STACK_RELEASE);
+ NOTE_INTERVAL(w, INTERVAL_DEALLOCATE_RESUME_OTHER);
+ cilk_fiber_remove_reference_from_self_and_resume_other(current_fiber,
+ &w->l->fiber_pool,
+ w->l->scheduling_fiber);
+ // We should never come back here!
+ CILK_ASSERT(0);
+ }
+ else {
+ // Case 2: We are passing the fiber to our parent because we
+ // are leftmost. We should come back later to
+ // resume execution of user code.
+ //
+ // If we are not freeing a fiber, there we must be
+ // returning from a spawn or processing an exception. The
+ // "sync" path always frees a fiber.
+ //
+ // We must be the leftmost child, and by left holder logic, we
+ // have already moved the current fiber into our parent full
+ // frame.
+#if FIBER_DEBUG >= 2
+ fprintf(stderr, "ThreadId=%p, W=%d: about to suspend self into runtime.. current_fiber = %p, deallcoate, switch to fiber %p\n",
+ cilkos_get_current_thread_id(),
+ w->self,
+ current_fiber, w->l->scheduling_fiber);
+#endif
+
+ NOTE_INTERVAL(w, INTERVAL_SUSPEND_RESUME_OTHER);
+
+ cilk_fiber_suspend_self_and_resume_other(current_fiber,
+ w->l->scheduling_fiber);
+ // Resuming this fiber returns control back to
+ // this function because our implementation uses OS fibers.
+ //
+ // On Unix, we could have the choice of passing the
+ // user_code_resume_after_switch_into_runtime as an extra "resume_proc"
+ // that resumes execution of user code instead of the
+ // jumping back here, and then jumping back to user code.
+#if FIBER_DEBUG >= 2
+ CILK_ASSERT(fdata->owner == __cilkrts_get_tls_worker());
+#endif
+ user_code_resume_after_switch_into_runtime(current_fiber);
+ }
+}
+
+/*
+ * Send a message to the children of the specified worker: run or wait.
+ */
+static void notify_children(__cilkrts_worker *w, unsigned int msg)
+{
+ int child_num;
+ __cilkrts_worker *child;
+ int num_sys_workers = w->g->P - 1;
+
+ // If worker is "n", then its children are 2n + 1, and 2n + 2.
+ child_num = (w->self << 1) + 1;
+ if (child_num < num_sys_workers) {
+ child = w->g->workers[child_num];
+ CILK_ASSERT(child->l->signal_node);
+ signal_node_msg(child->l->signal_node, msg);
+ child_num++;
+ if (child_num < num_sys_workers) {
+ child = w->g->workers[child_num];
+ CILK_ASSERT(child->l->signal_node);
+ signal_node_msg(child->l->signal_node, msg);
+ }
+ }
+}
+
+/*
+ * Notify this worker's children that they need to wait.
+ */
+static void notify_children_wait(__cilkrts_worker *w)
+{
+ notify_children(w, 0);
+}
+
+/*
+ * Notify this worker's children to run and start trying to steal.
+ */
+static void notify_children_run(__cilkrts_worker *w)
+{
+ notify_children(w, 1);
+}
+
+/**
+ * A single "check" to find work, either on our queue or through a
+ * steal attempt. This method checks our local queue once, and
+ * performs one steal attempt.
+ */
+static full_frame* check_for_work(__cilkrts_worker *w)
+{
+ full_frame *ff = NULL;
+ ff = pop_next_frame(w);
+ // If there is no work on the queue, try to steal some.
+ if (NULL == ff) {
+ START_INTERVAL(w, INTERVAL_STEALING) {
+ if (w->l->type != WORKER_USER && w->l->team != NULL) {
+ // At this point, the worker knows for certain that it has run
+ // out of work. Therefore, it loses its team affiliation. User
+ // workers never change teams, of course.
+ __cilkrts_worker_lock(w);
+ w->l->team = NULL;
+ __cilkrts_worker_unlock(w);
+ }
+
+ // If we are about to do a random steal, we should have no
+ // full frame...
+ CILK_ASSERT(NULL == w->l->frame_ff);
+ random_steal(w);
+ } STOP_INTERVAL(w, INTERVAL_STEALING);
+
+ // If the steal was successful, then the worker has populated its next
+ // frame with the work to resume.
+ ff = pop_next_frame(w);
+ if (NULL == ff) {
+ // Punish the worker for failing to steal.
+ // No quantum for you!
+ __cilkrts_yield();
+ w->l->steal_failure_count++;
+ } else {
+ // Reset steal_failure_count since there is obviously still work to
+ // be done.
+ w->l->steal_failure_count = 0;
+ }
+ }
+ return ff;
+}
+
+/**
+ * Keep stealing or looking on our queue.
+ *
+ * Returns either when a full frame is found, or NULL if the
+ * computation is done.
+ */
+static full_frame* search_until_work_found_or_done(__cilkrts_worker *w)
+{
+ full_frame *ff = NULL;
+ // Find a full frame to execute (either through random stealing,
+ // or because we pull it off w's 1-element queue).
+ while (!ff) {
+ // Check worker state to figure out our next action.
+ switch (worker_runnable(w))
+ {
+ case SCHEDULE_RUN: // One attempt at checking for work.
+ ff = check_for_work(w);
+ break;
+ case SCHEDULE_WAIT: // go into wait-mode.
+ CILK_ASSERT(WORKER_SYSTEM == w->l->type);
+ // If we are about to wait, then we better not have
+ // a frame that we should execute...
+ CILK_ASSERT(NULL == w->l->next_frame_ff);
+ notify_children_wait(w);
+ signal_node_wait(w->l->signal_node);
+ // ...
+ // Runtime is waking up.
+ notify_children_run(w);
+ w->l->steal_failure_count = 0;
+ break;
+ case SCHEDULE_EXIT: // exit the scheduler.
+ CILK_ASSERT(WORKER_USER != w->l->type);
+ return NULL;
+ default:
+ CILK_ASSERT(0);
+ abort();
+ }
+ }
+ return ff;
+}
+
+/**
+ * The proc method for a scheduling fiber on a user worker.
+ *
+ * When a user worker jumps into the runtime, it jumps into this
+ * method by either starting it if the scheduling fiber has never run
+ * before, or resuming the fiber if it was previously suspended.
+ */
+COMMON_PORTABLE
+void scheduler_fiber_proc_for_user_worker(cilk_fiber *fiber)
+{
+ __cilkrts_worker* w = cilk_fiber_get_owner(fiber);
+ CILK_ASSERT(w);
+
+ // This must be a user worker
+ CILK_ASSERT(WORKER_USER == w->l->type);
+
+ // If we aren't the current worker, then something is very wrong
+ // here..
+ verify_current_wkr(w);
+
+ __cilkrts_run_scheduler_with_exceptions(w);
+}
+
+
+/**
+ * The body of the runtime scheduling loop. This function executes in
+ * 4 stages:
+ *
+ * 1. Transitions from the user code into the runtime by
+ * executing any scheduling-stack functions.
+ * 2. Looks for a full frame enqueued from a successful provably
+ * good steal.
+ * 3. If no full frame is found in step 2, steal until
+ * a frame is found or we are done. If we are done, finish
+ * the scheduling loop.
+ * 4. When a frame is found, setup to resume user code.
+ * In particular, suspend the current fiber and resume the
+ * user fiber to execute the frame.
+ *
+ * Returns a fiber object that we should switch to after completing
+ * the body of the loop, or NULL if we should continue executing on
+ * this fiber.
+ *
+ * @pre @c current_fiber should equal @c wptr->l->scheduling_fiber
+ *
+ * @param current_fiber The currently executing (scheduling_ fiber
+ * @param wptr The currently executing worker.
+ * @param return The next fiber we should switch to.
+ */
+static cilk_fiber* worker_scheduling_loop_body(cilk_fiber* current_fiber,
+ void* wptr)
+{
+ __cilkrts_worker *w = (__cilkrts_worker*) wptr;
+ CILK_ASSERT(current_fiber == w->l->scheduling_fiber);
+
+ // Stage 1: Transition from executing user code to the runtime code.
+ // We don't need to do this call here any more, because
+ // every switch to the scheduling fiber should make this call
+ // using a post_switch_proc on the fiber.
+ //
+ // enter_runtime_transition_proc(w->l->scheduling_fiber, wptr);
+
+ // After Stage 1 is complete, w should no longer have
+ // an associated full frame.
+ CILK_ASSERT(NULL == w->l->frame_ff);
+
+ // Stage 2. First do a quick check of our 1-element queue.
+ full_frame *ff = pop_next_frame(w);
+
+ if (!ff) {
+ // Stage 3. We didn't find anything from our 1-element
+ // queue. Now go through the steal loop to find work.
+ ff = search_until_work_found_or_done(w);
+ if (!ff) {
+ CILK_ASSERT(w->g->work_done);
+ return NULL;
+ }
+ }
+
+ // Stage 4. Now that we have found a full frame to work on,
+ // actually execute it.
+ __cilkrts_stack_frame *sf;
+
+ // There shouldn't be any uncaught exceptions.
+ //
+ // In Windows, the OS catches any exceptions not caught by the
+ // user code. Thus, we are omitting the check on Windows.
+ //
+ // On Android, calling std::uncaught_exception with the stlport
+ // library causes a seg fault. Since we're not supporting
+ // exceptions there at this point, just don't do the check
+ CILKBUG_ASSERT_NO_UNCAUGHT_EXCEPTION();
+
+ BEGIN_WITH_WORKER_LOCK(w) {
+ CILK_ASSERT(!w->l->frame_ff);
+ BEGIN_WITH_FRAME_LOCK(w, ff) {
+ sf = ff->call_stack;
+ CILK_ASSERT(sf && !sf->call_parent);
+ setup_for_execution(w, ff, 0);
+ } END_WITH_FRAME_LOCK(w, ff);
+ } END_WITH_WORKER_LOCK(w);
+
+ /* run it */
+ //
+ // Prepare to run the full frame. To do so, we need to:
+ // (a) Execute some code on this fiber (the scheduling
+ // fiber) to set up data structures, and
+ // (b) Suspend the scheduling fiber, and resume the
+ // user-code fiber.
+
+ // Part (a). Set up data structures.
+ scheduling_fiber_prepare_to_resume_user_code(w, ff, sf);
+
+ cilk_fiber *other = w->l->frame_ff->fiber_self;
+ cilk_fiber_data* other_data = cilk_fiber_get_data(other);
+ cilk_fiber_data* current_fiber_data = cilk_fiber_get_data(current_fiber);
+
+ // I believe two cases are possible here, both of which
+ // should have other_data->resume_sf as NULL.
+ //
+ // 1. Resuming a fiber that was previously executing
+ // user code (i.e., a provably-good-steal).
+ // In this case, resume_sf should have been
+ // set to NULL when it was suspended.
+ //
+ // 2. Resuming code on a steal. In this case, since we
+ // grabbed a new fiber, resume_sf should be NULL.
+ CILK_ASSERT(NULL == other_data->resume_sf);
+
+#if FIBER_DEBUG >= 2
+ fprintf(stderr, "W=%d: other fiber=%p, setting resume_sf to %p\n",
+ w->self, other, other_data->resume_sf);
+#endif
+ // Update our own fiber's data.
+ current_fiber_data->resume_sf = NULL;
+ // The scheduling fiber should have the right owner from before.
+ CILK_ASSERT(current_fiber_data->owner == w);
+ other_data->resume_sf = sf;
+
+
+#if FIBER_DEBUG >= 3
+ fprintf(stderr, "ThreadId=%p (about to suspend self resume other), W=%d: current_fiber=%p, other=%p, current_fiber->resume_sf = %p, other->resume_sf = %p\n",
+ cilkos_get_current_thread_id(),
+ w->self,
+ current_fiber, other,
+ current_fiber_data->resume_sf,
+ other_data->resume_sf);
+#endif
+ return other;
+}
+
+
+/**
+ * This function is executed once by each worker, to initialize its
+ * scheduling loop.
+ */
+static void worker_scheduler_init_function(__cilkrts_worker *w)
+{
+ // First, execute the startup tasks that must happen for all
+ // worker types.
+ ITT_SYNC_PREPARE(w);
+ /* Notify tools about the new worker. Inspector needs this, but we
+ don't want to confuse Cilkscreen with system threads. User threads
+ do this notification in bind_thread */
+ if (! w->g->under_ptool)
+ __cilkrts_cilkscreen_establish_worker(w);
+
+ // Seed the initial random number generator.
+ // If we forget to do this, then the worker always steals from 0.
+ // Programs will still execute correctly, but
+ // you may see a subtle performance bug...
+ mysrand(w, (w->self + 1));
+
+ // The startup work varies, depending on the worker type.
+ switch (w->l->type) {
+ case WORKER_USER:
+ // Stop working once we've entered the scheduler.
+ // For user workers, INTERVAL_IN_SCHEDULER counts the time
+ // since we called bind_thread.
+ break;
+
+ case WORKER_SYSTEM:
+ // If a system worker is starting, we must also be starting
+ // the runtime.
+
+ // Runtime begins in a wait-state and is woken up by the first user
+ // worker when the runtime is ready.
+ signal_node_wait(w->l->signal_node);
+ // ...
+ // Runtime is waking up.
+ notify_children_run(w);
+ w->l->steal_failure_count = 0;
+
+ // For system threads, count all the time this thread is
+ // alive in the scheduling loop.
+ START_INTERVAL(w, INTERVAL_IN_SCHEDULER);
+ START_INTERVAL(w, INTERVAL_WORKING);
+ break;
+ default:
+ __cilkrts_bug("Unknown worker %p of type %d entering scheduling loop\n",
+ w, w->l->type);
+ }
+}
+
+/**
+ * This function is executed once by each worker, to finish its
+ * scheduling loop.
+ *
+ * @note Currently, only system workers finish their loops. User
+ * workers will jump away to user code without exiting their
+ * scheduling loop.
+ */
+static void worker_scheduler_terminate_function(__cilkrts_worker *w)
+{
+ // A user worker should never finish by falling through the
+ // scheduling loop.
+ CILK_ASSERT(WORKER_USER != w->l->type);
+ STOP_INTERVAL(w, INTERVAL_IN_RUNTIME);
+ STOP_INTERVAL(w, INTERVAL_IN_SCHEDULER);
+}
+
+/**
+ * The main scheduler function executed by a worker's scheduling
+ * fiber.
+ *
+ * This method is started by either a new system worker, or a user
+ * worker that has stalled and just been imported into the runtime.
+ */
+static void worker_scheduler_function(__cilkrts_worker *w)
+{
+ worker_scheduler_init_function(w);
+
+ // The main scheduling loop body.
+
+ while (!w->g->work_done) {
+ // Set intervals. Now we are in the runtime instead of working.
+ START_INTERVAL(w, INTERVAL_IN_RUNTIME);
+ STOP_INTERVAL(w, INTERVAL_WORKING);
+
+ // Execute the "body" of the scheduling loop, and figure
+ // out the fiber to jump to next.
+ cilk_fiber* fiber_to_resume
+ = worker_scheduling_loop_body(w->l->scheduling_fiber, w);
+
+ if (fiber_to_resume) {
+ // Suspend the current fiber and resume next one.
+ NOTE_INTERVAL(w, INTERVAL_SUSPEND_RESUME_OTHER);
+ STOP_INTERVAL(w, INTERVAL_IN_RUNTIME);
+ START_INTERVAL(w, INTERVAL_WORKING);
+ cilk_fiber_suspend_self_and_resume_other(w->l->scheduling_fiber,
+ fiber_to_resume);
+
+ // Return here only when this (scheduling) fiber is
+ // resumed (i.e., this worker wants to reenter the runtime).
+ }
+ }
+
+ // Finish the scheduling loop.
+ worker_scheduler_terminate_function(w);
+}
+
+
+/*************************************************************
+ Forward declarations for reduction protocol.
+*************************************************************/
+
+static __cilkrts_worker*
+execute_reductions_for_sync(__cilkrts_worker *w,
+ full_frame *ff,
+ __cilkrts_stack_frame *sf_at_sync);
+
+static __cilkrts_worker*
+execute_reductions_for_spawn_return(__cilkrts_worker *w,
+ full_frame *ff,
+ __cilkrts_stack_frame *returning_sf);
+
+
+
+/*************************************************************
+ Scheduler functions that are callable by client code
+*************************************************************/
+static full_frame *disown(__cilkrts_worker *w,
+ full_frame *ff,
+ __cilkrts_stack_frame *sf,
+ const char *why)
+{
+ CILK_ASSERT(ff);
+ make_unrunnable(w, ff, sf, sf != 0, why);
+ w->l->frame_ff = 0;
+ return ff->parent;
+}
+
+/**
+ * Called when ff is returning from a spawn, and we need to execute a
+ * reduction.
+ *
+ * @param w The currently executing worker.
+ * @param ff The full frame for w.
+ * @param returning_sf The stack frame for the spawn helper that is returning.
+ *
+ * Normally, by the time we gain control in the runtime, the worker
+ * has already popped off the __cilkrts_stack_frame "returning_sf"
+ * from its call chain.
+ *
+ * When we have only serial reductions, w->current_stack_frame is not
+ * needed any more, because w is about to enter the runtime scheduling
+ * loop anyway. Similarly, the frame "ff" is slated to be destroyed
+ * after the runtime finishes the return from spawn and splices ff out
+ * of the tree of full frames.
+ *
+ * To execute a parallel reduction, however, we still want
+ * w->current_stack_frame == returning_sf, and we are going to use the
+ * frame ff for a little bit longer.
+ *
+ * This method:
+ *
+ * 1. Puts returning_sf back as w's current stack frame.
+ * 2. Makes "ff" runnable again on w.
+ */
+static inline
+void restore_frame_for_spawn_return_reduction(__cilkrts_worker *w,
+ full_frame *ff,
+ __cilkrts_stack_frame *returning_sf) {
+#if REDPAR_DEBUG >= 2
+ CILK_ASSERT(returning_sf);
+ CILK_ASSERT(returning_sf->worker == w);
+#endif
+ // Change w's current stack frame back to "returning_sf".
+ //
+ // Intuitively, w->current_stack_frame should be
+ // returning_sf->call_parent at this point.
+ //
+ // We can not assert this, however, because the pop of
+ // returning_sf from the call chain has already cleared
+ // returning_sf->call_parent. We don't want to restore the call
+ // parent of returning_sf, because its parent has been stolen, and
+ // the runtime assumes that steals break this link.
+
+ // We cannot assert call_parent is NULL either, since that's not true for
+ // Win64 exception handling
+// CILK_ASSERT(returning_sf->call_parent == NULL);
+ w->current_stack_frame = returning_sf;
+
+ // Make the full frame "ff" runnable again, in preparation for
+ // executing the reduction.
+ make_runnable(w, ff);
+}
+
+
+NORETURN __cilkrts_c_sync(__cilkrts_worker *w,
+ __cilkrts_stack_frame *sf_at_sync)
+{
+ full_frame *ff;
+
+ // Claim: This read of w->l->frame_ff can occur without
+ // holding the worker lock because when w has reached a sync
+ // and entered the runtime (because it stalls), w's deque is empty
+ // and no one else can steal and change w->l->frame_ff.
+
+ ff = w->l->frame_ff;
+#ifdef _WIN32
+ __cilkrts_save_exception_state(w, ff);
+#else
+ // Move any pending exceptions into the full frame
+ CILK_ASSERT(NULL == ff->pending_exception);
+ ff->pending_exception = w->l->pending_exception;
+ w->l->pending_exception = NULL;
+#endif
+
+ w = execute_reductions_for_sync(w, ff, sf_at_sync);
+
+#if FIBER_DEBUG >= 3
+ fprintf(stderr, "ThreadId=%p, w->self = %d. about to longjmp_into_runtim[c_sync] with ff=%p\n",
+ cilkos_get_current_thread_id(), w->self, ff);
+#endif
+
+ longjmp_into_runtime(w, do_sync, sf_at_sync);
+}
+
+static void do_sync(__cilkrts_worker *w, full_frame *ff,
+ __cilkrts_stack_frame *sf)
+{
+ //int abandoned = 1;
+ enum provably_good_steal_t steal_result = ABANDON_EXECUTION;
+
+ START_INTERVAL(w, INTERVAL_SYNC_CHECK) {
+ BEGIN_WITH_WORKER_LOCK_OPTIONAL(w) {
+
+ CILK_ASSERT(ff);
+ BEGIN_WITH_FRAME_LOCK(w, ff) {
+ CILK_ASSERT(sf->call_parent == 0);
+ CILK_ASSERT(sf->flags & CILK_FRAME_UNSYNCHED);
+
+ // Before switching into the scheduling fiber, we should have
+ // already taken care of deallocating the current
+ // fiber.
+ CILK_ASSERT(NULL == ff->fiber_self);
+
+ // Update the frame's pedigree information if this is an ABI 1
+ // or later frame
+ if (CILK_FRAME_VERSION_VALUE(sf->flags) >= 1)
+ {
+ sf->parent_pedigree.rank = w->pedigree.rank;
+ sf->parent_pedigree.parent = w->pedigree.parent;
+
+ // Note that the pedigree rank needs to be updated
+ // when setup_for_execution_pedigree runs
+ sf->flags |= CILK_FRAME_SF_PEDIGREE_UNSYNCHED;
+ }
+
+ /* the decjoin() occurs in provably_good_steal() */
+ steal_result = provably_good_steal(w, ff);
+
+ } END_WITH_FRAME_LOCK(w, ff);
+ // set w->l->frame_ff = NULL after checking abandoned
+ if (WAIT_FOR_CONTINUE != steal_result) {
+ w->l->frame_ff = NULL;
+ }
+ } END_WITH_WORKER_LOCK_OPTIONAL(w);
+ } STOP_INTERVAL(w, INTERVAL_SYNC_CHECK);
+
+ // Now, if we are in a replay situation and provably_good_steal() returned
+ // WAIT_FOR_CONTINUE, we should sleep, reacquire locks, call
+ // provably_good_steal(), and release locks until we get a value other
+ // than WAIT_FOR_CONTINUE from the function.
+#ifdef CILK_RECORD_REPLAY
+ // We don't have to explicitly check for REPLAY_LOG below because
+ // steal_result can only be set to WAIT_FOR_CONTINUE during replay
+ while(WAIT_FOR_CONTINUE == steal_result)
+ {
+ __cilkrts_sleep();
+ BEGIN_WITH_WORKER_LOCK_OPTIONAL(w)
+ {
+ ff = w->l->frame_ff;
+ BEGIN_WITH_FRAME_LOCK(w, ff)
+ {
+ steal_result = provably_good_steal(w, ff);
+ } END_WITH_FRAME_LOCK(w, ff);
+ if (WAIT_FOR_CONTINUE != steal_result)
+ w->l->frame_ff = NULL;
+ } END_WITH_WORKER_LOCK_OPTIONAL(w);
+ }
+#endif // CILK_RECORD_REPLAY
+
+#ifdef ENABLE_NOTIFY_ZC_INTRINSIC
+ // If we can't make any further progress on this thread, tell Inspector
+ // that we're abandoning the work and will go find something else to do.
+ if (ABANDON_EXECUTION == steal_result)
+ {
+ NOTIFY_ZC_INTRINSIC("cilk_sync_abandon", 0);
+ }
+#endif // defined ENABLE_NOTIFY_ZC_INTRINSIC
+
+ return; /* back to scheduler loop */
+}
+
+/* worker W completely promotes its own deque, simulating the case
+ where the whole deque is stolen. We use this mechanism to force
+ the allocation of new storage for reducers for race-detection
+ purposes. */
+void __cilkrts_promote_own_deque(__cilkrts_worker *w)
+{
+ // Remember the fiber we start this method on.
+ CILK_ASSERT(w->l->frame_ff);
+ cilk_fiber* starting_fiber = w->l->frame_ff->fiber_self;
+
+ BEGIN_WITH_WORKER_LOCK(w) {
+ while (dekker_protocol(w)) {
+ /* PLACEHOLDER_FIBER is used as non-null marker to tell detach()
+ and make_child() that this frame should be treated as a spawn
+ parent, even though we have not assigned it a stack. */
+ detach_for_steal(w, w, PLACEHOLDER_FIBER);
+ }
+ } END_WITH_WORKER_LOCK(w);
+
+
+ // TBD: The management of full frames and fibers is a bit
+ // sketchy here. We are promoting stack frames into full frames,
+ // and pretending they are stolen away, but no other worker is
+ // actually working on them. Some runtime invariants
+ // may be broken here.
+ //
+ // Technically, if we are simulating a steal from w
+ // w should get a new full frame, but
+ // keep the same fiber. A real thief would be taking the
+ // loot frame away, get a new fiber, and starting executing the
+ // loot frame.
+ //
+ // What should a fake thief do? Where does the frame go?
+
+ // In any case, we should be finishing the promotion process with
+ // the same fiber with.
+ CILK_ASSERT(w->l->frame_ff);
+ CILK_ASSERT(w->l->frame_ff->fiber_self == starting_fiber);
+}
+
+
+
+/* the client code calls this function after a spawn when the dekker
+ protocol fails. The function may either return or longjmp
+ into the rts
+
+ This function takes in a "returning_sf" argument which corresponds
+ to the __cilkrts_stack_frame that we are finishing (i.e., the
+ argument to __cilkrts_leave_frame).
+ */
+void __cilkrts_c_THE_exception_check(__cilkrts_worker *w,
+ __cilkrts_stack_frame *returning_sf)
+{
+ full_frame *ff;
+ int stolen_p;
+ __cilkrts_stack_frame *saved_sf = NULL;
+
+ START_INTERVAL(w, INTERVAL_THE_EXCEPTION_CHECK);
+
+ BEGIN_WITH_WORKER_LOCK(w) {
+ ff = w->l->frame_ff;
+ CILK_ASSERT(ff);
+ /* This code is called only upon a normal return and never
+ upon an exceptional return. Assert that this is the
+ case. */
+ CILK_ASSERT(!w->l->pending_exception);
+
+ reset_THE_exception(w);
+ stolen_p = !(w->head < (w->tail + 1)); /* +1 because tail was
+ speculatively
+ decremented by the
+ compiled code */
+
+ if (stolen_p) {
+ /* XXX This will be charged to THE for accounting purposes */
+ __cilkrts_save_exception_state(w, ff);
+
+ // Save the value of the current stack frame.
+ saved_sf = w->current_stack_frame;
+
+ // Reverse the decrement from undo_detach.
+ // This update effectively resets the deque to be
+ // empty (i.e., changes w->tail back to equal w->head).
+ // We need to reset the deque to execute parallel
+ // reductions. When we have only serial reductions, it
+ // does not matter, since serial reductions do not
+ // change the deque.
+ w->tail++;
+#if REDPAR_DEBUG > 1
+ // ASSERT our deque is empty.
+ CILK_ASSERT(w->head == w->tail);
+#endif
+ }
+ } END_WITH_WORKER_LOCK(w);
+
+ STOP_INTERVAL(w, INTERVAL_THE_EXCEPTION_CHECK);
+
+ if (stolen_p)
+ {
+ w = execute_reductions_for_spawn_return(w, ff, returning_sf);
+
+ // "Mr. Policeman? My parent always told me that if I was in trouble
+ // I should ask a nice policeman for help. I can't find my parent
+ // anywhere..."
+ //
+ // Write a record to the replay log for an attempt to return to a stolen parent
+ replay_record_orphaned(w);
+
+ // Update the pedigree only after we've finished the
+ // reductions.
+ update_pedigree_on_leave_frame(w, returning_sf);
+
+ // Notify Inspector that the parent has been stolen and we're
+ // going to abandon this work and go do something else. This
+ // will match the cilk_leave_begin in the compiled code
+ NOTIFY_ZC_INTRINSIC("cilk_leave_stolen", saved_sf);
+
+ DBGPRINTF ("%d: longjmp_into_runtime from __cilkrts_c_THE_exception_check\n", w->self);
+ longjmp_into_runtime(w, do_return_from_spawn, 0);
+ DBGPRINTF ("%d: returned from longjmp_into_runtime from __cilkrts_c_THE_exception_check?!\n", w->self);
+ }
+ else
+ {
+ NOTE_INTERVAL(w, INTERVAL_THE_EXCEPTION_CHECK_USELESS);
+ return;
+ }
+}
+
+/* Return an exception to a stolen parent. */
+NORETURN __cilkrts_exception_from_spawn(__cilkrts_worker *w,
+ __cilkrts_stack_frame *returning_sf)
+{
+ full_frame *ff = w->l->frame_ff;
+ // This is almost the same as THE_exception_check, except
+ // the detach didn't happen, we don't need to undo the tail
+ // update.
+ CILK_ASSERT(w->head == w->tail);
+ w = execute_reductions_for_spawn_return(w, ff, returning_sf);
+
+ longjmp_into_runtime(w, do_return_from_spawn, 0);
+ CILK_ASSERT(0);
+}
+
+static void do_return_from_spawn(__cilkrts_worker *w,
+ full_frame *ff,
+ __cilkrts_stack_frame *sf)
+{
+ full_frame *parent_ff;
+ enum provably_good_steal_t steal_result = ABANDON_EXECUTION;
+
+ BEGIN_WITH_WORKER_LOCK_OPTIONAL(w) {
+ CILK_ASSERT(ff);
+ CILK_ASSERT(!ff->is_call_child);
+ CILK_ASSERT(sf == NULL);
+ parent_ff = ff->parent;
+
+ BEGIN_WITH_FRAME_LOCK(w, ff) {
+ decjoin(ff);
+ } END_WITH_FRAME_LOCK(w, ff);
+
+ BEGIN_WITH_FRAME_LOCK(w, parent_ff) {
+ if (parent_ff->simulated_stolen)
+ unconditional_steal(w, parent_ff);
+ else
+ steal_result = provably_good_steal(w, parent_ff);
+ } END_WITH_FRAME_LOCK(w, parent_ff);
+
+ } END_WITH_WORKER_LOCK_OPTIONAL(w);
+
+ // Loop here in replay mode
+#ifdef CILK_RECORD_REPLAY
+ // We don't have to explicitly check for REPLAY_LOG below because
+ // steal_result can only get set to WAIT_FOR_CONTINUE during replay.
+ // We also don't have to worry about the simulated_stolen flag
+ // because steal_result can only be set to WAIT_FOR_CONTINUE by
+ // provably_good_steal().
+ while(WAIT_FOR_CONTINUE == steal_result)
+ {
+ __cilkrts_sleep();
+ BEGIN_WITH_WORKER_LOCK_OPTIONAL(w)
+ {
+ BEGIN_WITH_FRAME_LOCK(w, parent_ff)
+ {
+ steal_result = provably_good_steal(w, parent_ff);
+ } END_WITH_FRAME_LOCK(w, parent_ff);
+ } END_WITH_WORKER_LOCK_OPTIONAL(w);
+ }
+#endif // CILK_RECORD_REPLAY
+
+ // Cleanup the child frame.
+ __cilkrts_destroy_full_frame(w, ff);
+ return;
+}
+
+#ifdef _WIN32
+/* migrate an exception across fibers. Call this function when an exception has
+ * been thrown and has to traverse across a steal. The exception has already
+ * been wrapped up, so all that remains is to longjmp() into the continuation,
+ * sync, and re-raise it.
+ */
+void __cilkrts_migrate_exception(__cilkrts_stack_frame *sf) {
+
+ __cilkrts_worker *w = sf->worker;
+ full_frame *ff;
+
+ BEGIN_WITH_WORKER_LOCK(w) {
+ ff = w->l->frame_ff;
+ reset_THE_exception(w);
+ /* there is no need to check for a steal because we wouldn't be here if
+ there weren't a steal. */
+ __cilkrts_save_exception_state(w, ff);
+
+ CILK_ASSERT(w->head == w->tail);
+ } END_WITH_WORKER_LOCK(w);
+
+ {
+ // TBD(jsukha): This function emulates the
+ // the "do_return_from_spawn" path.
+ w = execute_reductions_for_spawn_return(w, ff, sf);
+ }
+
+ longjmp_into_runtime(w, do_return_from_spawn, 0); /* does not return. */
+ CILK_ASSERT(! "Shouldn't be here...");
+}
+#endif
+
+
+/* Pop a call stack from TAIL. Return the call stack, or NULL if the
+ queue is empty */
+__cilkrts_stack_frame *__cilkrts_pop_tail(__cilkrts_worker *w)
+{
+ __cilkrts_stack_frame *sf;
+ BEGIN_WITH_WORKER_LOCK(w) {
+ __cilkrts_stack_frame *volatile *tail = w->tail;
+ if (w->head < tail) {
+ --tail;
+ sf = *tail;
+ w->tail = tail;
+ } else {
+ sf = 0;
+ }
+ } END_WITH_WORKER_LOCK(w);
+ return sf;
+}
+
+#ifdef CILK_RECORD_REPLAY
+__cilkrts_stack_frame *simulate_pop_tail(__cilkrts_worker *w)
+{
+ __cilkrts_stack_frame *sf;
+ BEGIN_WITH_WORKER_LOCK(w) {
+ if (w->head < w->tail) {
+ sf = *(w->tail-1);
+ } else {
+ sf = 0;
+ }
+ } END_WITH_WORKER_LOCK(w);
+ return sf;
+}
+#endif
+
+
+/* Return from a call, not a spawn. */
+void __cilkrts_return(__cilkrts_worker *w)
+{
+ full_frame *ff, *parent_ff;
+ START_INTERVAL(w, INTERVAL_RETURNING);
+
+ BEGIN_WITH_WORKER_LOCK_OPTIONAL(w) {
+ ff = w->l->frame_ff;
+ CILK_ASSERT(ff);
+ CILK_ASSERT(ff->join_counter == 1);
+ /* This path is not used to return from spawn. */
+ CILK_ASSERT(ff->is_call_child);
+
+ BEGIN_WITH_FRAME_LOCK(w, ff) {
+ // After this call, w->l->frame_ff != ff.
+ // Technically, w will "own" ff until ff is freed,
+ // however, because ff is a dying leaf full frame.
+ parent_ff = disown(w, ff, 0, "return");
+ decjoin(ff);
+
+#ifdef _WIN32
+ __cilkrts_save_exception_state(w, ff);
+#else
+ // Move the pending exceptions into the full frame
+ // This should always be NULL if this isn't a
+ // return with an exception
+ CILK_ASSERT(NULL == ff->pending_exception);
+ ff->pending_exception = w->l->pending_exception;
+ w->l->pending_exception = NULL;
+#endif // _WIN32
+
+ } END_WITH_FRAME_LOCK(w, ff);
+
+ __cilkrts_fence(); /* redundant */
+
+ CILK_ASSERT(parent_ff);
+
+ BEGIN_WITH_FRAME_LOCK(w, parent_ff) {
+ finalize_child_for_call(w, parent_ff, ff);
+ } END_WITH_FRAME_LOCK(w, parent_ff);
+
+ ff = pop_next_frame(w);
+ /* ff will be non-null except when the parent frame is owned
+ by another worker.
+ CILK_ASSERT(ff)
+ */
+ CILK_ASSERT(!w->l->frame_ff);
+ if (ff) {
+ BEGIN_WITH_FRAME_LOCK(w, ff) {
+ __cilkrts_stack_frame *sf = ff->call_stack;
+ CILK_ASSERT(sf && !sf->call_parent);
+ setup_for_execution(w, ff, 1);
+ } END_WITH_FRAME_LOCK(w, ff);
+ }
+ } END_WITH_WORKER_LOCK_OPTIONAL(w);
+
+ STOP_INTERVAL(w, INTERVAL_RETURNING);
+}
+
+static void __cilkrts_unbind_thread()
+{
+ int stop_cilkscreen = 0;
+ global_state_t *g;
+
+ // Take out the global OS mutex to protect accesses to the table of workers
+ global_os_mutex_lock();
+
+ if (cilkg_is_published()) {
+ __cilkrts_worker *w = __cilkrts_get_tls_worker();
+ if (w) {
+ g = w->g;
+
+ // If there's only 1 worker, the counts will be stopped in
+ // __cilkrts_scheduler
+ if (g->P > 1)
+ {
+ STOP_INTERVAL(w, INTERVAL_WORKING);
+ STOP_INTERVAL(w, INTERVAL_IN_SCHEDULER);
+ }
+
+ __cilkrts_set_tls_worker(0);
+
+ if (w->self == -1) {
+ // This worker is an overflow worker. I.e., it was created on-
+ // demand when the global pool ran out of workers.
+ destroy_worker(w);
+ __cilkrts_free(w);
+ } else {
+ // This is a normal user worker and needs to be counted by the
+ // global state for the purposes of throttling system workers.
+ w->l->type = WORKER_FREE;
+ __cilkrts_leave_cilk(g);
+ }
+
+ stop_cilkscreen = (0 == g->Q);
+ }
+ }
+ global_os_mutex_unlock();
+
+ /* Turn off Cilkscreen. This needs to be done when we are NOT holding the
+ * os mutex. */
+ if (stop_cilkscreen)
+ __cilkrts_cilkscreen_disable_instrumentation();
+}
+
+/* special return from the initial frame */
+
+void __cilkrts_c_return_from_initial(__cilkrts_worker *w)
+{
+ struct cilkred_map *rm;
+
+ /* This is only called on a user thread worker. */
+ CILK_ASSERT(w->l->type == WORKER_USER);
+
+ #if REDPAR_DEBUG >= 3
+ fprintf(stderr, "[W=%d, desc=cilkrts_c_return_from_initial, ff=%p]\n",
+ w->self, w->l->frame_ff);
+ #endif
+
+ BEGIN_WITH_WORKER_LOCK_OPTIONAL(w) {
+ full_frame *ff = w->l->frame_ff;
+ CILK_ASSERT(ff);
+ CILK_ASSERT(ff->join_counter == 1);
+ w->l->frame_ff = 0;
+
+ CILK_ASSERT(ff->fiber_self);
+ // Save any TBB interop data for the next time this thread enters Cilk
+ cilk_fiber_tbb_interop_save_info_from_stack(ff->fiber_self);
+
+ // Deallocate cilk_fiber that mapped to the user stack. The stack
+ // itself does not get deallocated (of course) but our data
+ // structure becomes divorced from it.
+
+#if FIBER_DEBUG >= 1
+ fprintf(stderr, "ThreadId=%p: w=%d: We are about to deallocate ff->fiber_self = %p here. w->l->scheduling_fiber = %p. w->l->type = %d\n",
+ cilkos_get_current_thread_id(),
+ w->self,
+ ff->fiber_self,
+ w->l->scheduling_fiber,
+ w->l->type);
+#endif
+ // The fiber in ff is a user-code fiber. The fiber in
+ // w->l->scheduling_fiber is a scheduling fiber. These fibers should
+ // never be equal. When a user worker returns (and will unbind), we
+ // should destroy only the fiber in ff. The scheduling fiber will be
+ // re-used.
+
+ CILK_ASSERT(ff->fiber_self != w->l->scheduling_fiber);
+
+ START_INTERVAL(w, INTERVAL_FIBER_DEALLOCATE) {
+ // This fiber might not be deallocated here if there
+ // is a pending exception on Windows that refers
+ // to this fiber.
+ //
+ // First "suspend" the fiber, and then try to delete it.
+ cilk_fiber_deallocate_from_thread(ff->fiber_self);
+ } STOP_INTERVAL(w, INTERVAL_FIBER_DEALLOCATE);
+ ff->fiber_self = NULL;
+
+ /* Save reducer map into global_state object */
+ rm = w->reducer_map;
+ w->reducer_map = NULL;
+
+#if REDPAR_DEBUG >= 3
+ fprintf(stderr, "W=%d, reducer_map_to_delete=%p, was in ff=%p\n",
+ w->self,
+ rm,
+ ff);
+#endif
+ __cilkrts_destroy_full_frame(w, ff);
+
+
+ /* Work is never done. w->g->work_done = 1; __cilkrts_fence(); */
+ } END_WITH_WORKER_LOCK_OPTIONAL(w);
+
+
+ save_pedigree_leaf_from_user_worker(w);
+
+ // Workers can have NULL reducer maps now.
+ if (rm) {
+ __cilkrts_destroy_reducer_map(w, rm);
+ }
+
+
+#if FIBER_DEBUG >= 1
+ __cilkrts_worker* tmp = w;
+ int tmp_id = w->self;
+ fprintf(stderr, "w=%d: We are about unbind thread (w= %p)\n",
+ w->self,
+ w);
+#endif
+
+ w = NULL;
+
+ __cilkrts_unbind_thread();
+
+#if FIBER_DEBUG >= 1
+
+ fprintf(stderr, "w=%p, %d: Finished unbind\n",
+ tmp, tmp_id);
+#endif
+
+ /* Other workers will stop trying to steal if this was the last worker. */
+
+ return;
+}
+
+
+/*
+ * __cilkrts_restore_stealing
+ *
+ * Restore the protected_tail to a previous state, possibly allowing frames
+ * to be stolen. The dekker_protocol has been extended to steal only if
+ * head+1 is < protected_tail.
+ */
+
+void __cilkrts_restore_stealing(
+ __cilkrts_worker *w,
+ __cilkrts_stack_frame *volatile *saved_protected_tail)
+{
+ /* On most x86 this pair of operations would be slightly faster
+ as an atomic exchange due to the implicit memory barrier in
+ an atomic instruction. */
+ w->protected_tail = saved_protected_tail;
+ __cilkrts_fence();
+}
+
+/*
+ * __cilkrts_disallow_stealing
+ *
+ * Move the protected_tail to NEW_PROTECTED_TAIL, preventing any
+ * frames from being stolen. If NEW_PROTECTED_TAIL is NULL, prevent
+ * stealing from the whole queue. The dekker_protocol has been
+ * extended to only steal if head+1 is also < protected_tail.
+ */
+
+__cilkrts_stack_frame *volatile *__cilkrts_disallow_stealing(
+ __cilkrts_worker *w,
+ __cilkrts_stack_frame *volatile *new_protected_tail)
+{
+ __cilkrts_stack_frame *volatile *saved_protected_tail = w->protected_tail;
+
+ if (!new_protected_tail)
+ new_protected_tail = w->l->ltq;
+
+ if (w->protected_tail > new_protected_tail) {
+ w->protected_tail = new_protected_tail;
+ /* Issue a store-store barrier. The update to protected_tail
+ here must precede the update to tail in the next spawn.
+ On x86 this is probably not needed. */
+#if defined __GNUC__ && __ICC >= 1200 && !(__MIC__ ||__MIC2__)
+ _mm_sfence();
+#else
+ __cilkrts_fence();
+#endif
+ }
+
+ return saved_protected_tail;
+}
+
+/*************************************************************
+ Initialization and startup
+*************************************************************/
+
+__cilkrts_worker *make_worker(global_state_t *g,
+ int self, __cilkrts_worker *w)
+{
+ w->self = self;
+ w->g = g;
+
+ w->pedigree.rank = 0; // Initial rank is 0
+ w->pedigree.parent = NULL;
+
+ w->l = (local_state *)__cilkrts_malloc(sizeof(*w->l));
+
+ __cilkrts_frame_malloc_per_worker_init(w);
+
+ w->reducer_map = NULL;
+ w->current_stack_frame = NULL;
+ w->reserved = NULL;
+
+ w->l->worker_magic_0 = WORKER_MAGIC_0;
+ w->l->team = NULL;
+ w->l->type = WORKER_FREE;
+
+ __cilkrts_mutex_init(&w->l->lock);
+ __cilkrts_mutex_init(&w->l->steal_lock);
+ w->l->do_not_steal = 0;
+ w->l->frame_ff = 0;
+ w->l->next_frame_ff = 0;
+ w->l->last_full_frame = NULL;
+
+ w->l->ltq = (__cilkrts_stack_frame **)
+ __cilkrts_malloc(g->ltqsize * sizeof(*w->l->ltq));
+ w->ltq_limit = w->l->ltq + g->ltqsize;
+ w->head = w->tail = w->l->ltq;
+
+ cilk_fiber_pool_init(&w->l->fiber_pool,
+ &g->fiber_pool,
+ g->stack_size,
+ g->fiber_pool_size,
+ 0, // alloc_max is 0. We don't allocate from the heap directly without checking the parent pool.
+ 0);
+#if FIBER_DEBUG >= 2
+ fprintf(stderr, "ThreadId=%p: Making w=%d (%p), pool = %p\n",
+ cilkos_get_current_thread_id(),
+ w->self, w,
+ &w->l->fiber_pool);
+#endif
+ w->l->scheduling_fiber = NULL;
+ w->l->original_pedigree_leaf = NULL;
+ w->l->rand_seed = 0; /* the scheduler will overwrite this field */
+
+ w->l->post_suspend = 0;
+ w->l->suspended_stack = 0;
+ w->l->fiber_to_free = NULL;
+ w->l->pending_exception = NULL;
+
+#if CILK_PROFILE
+ w->l->stats = __cilkrts_malloc(sizeof(statistics));
+ __cilkrts_init_stats(w->l->stats);
+#else
+ w->l->stats = NULL;
+#endif
+ w->l->steal_failure_count = 0;
+
+ w->l->work_stolen = 0;
+
+ // Initialize record/replay assuming we're doing neither
+ w->l->record_replay_fptr = NULL;
+ w->l->replay_list_root = NULL;
+ w->l->replay_list_entry = NULL;
+ w->l->signal_node = NULL;
+ // Nothing's been stolen yet
+ w->l->worker_magic_1 = WORKER_MAGIC_1;
+
+ /*w->parallelism_disabled = 0;*/
+
+ // Allow stealing all frames. Sets w->saved_protected_tail
+ __cilkrts_restore_stealing(w, w->ltq_limit);
+
+ __cilkrts_init_worker_sysdep(w);
+
+ reset_THE_exception(w);
+
+ return w;
+}
+
+void destroy_worker(__cilkrts_worker *w)
+{
+ CILK_ASSERT (NULL == w->l->pending_exception);
+
+ // Deallocate the scheduling fiber
+ if (NULL != w->l->scheduling_fiber)
+ {
+ // The scheduling fiber is the main fiber for system workers and must
+ // be deallocated by the thread that created it. Thus, we can
+ // deallocate only free workers' (formerly user workers) scheduling
+ // fibers here.
+ CILK_ASSERT(WORKER_FREE == w->l->type);
+
+#if FIBER_DEBUG >=1
+ fprintf(stderr, "ThreadId=%p, w=%p, %d, deallocating scheduling fiber = %p, \n",
+ cilkos_get_current_thread_id(),
+ w,
+ w->self,
+ w->l->scheduling_fiber);
+#endif
+ int ref_count = cilk_fiber_remove_reference(w->l->scheduling_fiber, NULL);
+ // Scheduling fiber should never have extra references because of exceptions.
+ CILK_ASSERT(0 == ref_count);
+ w->l->scheduling_fiber = NULL;
+ }
+
+#if CILK_PROFILE
+ if (w->l->stats) {
+ __cilkrts_free(w->l->stats);
+ }
+#else
+ CILK_ASSERT(NULL == w->l->stats);
+#endif
+
+ /* Free any cached fibers. */
+ cilk_fiber_pool_destroy(&w->l->fiber_pool);
+
+ __cilkrts_destroy_worker_sysdep(w);
+
+ if (w->l->signal_node) {
+ CILK_ASSERT(WORKER_SYSTEM == w->l->type);
+ signal_node_destroy(w->l->signal_node);
+ }
+
+ __cilkrts_free(w->l->ltq);
+ __cilkrts_mutex_destroy(0, &w->l->lock);
+ __cilkrts_mutex_destroy(0, &w->l->steal_lock);
+ __cilkrts_frame_malloc_per_worker_cleanup(w);
+
+ __cilkrts_free(w->l);
+
+ // The caller is responsible for freeing the worker memory
+}
+
+/*
+ * Make a worker into a system worker.
+ */
+static void make_worker_system(__cilkrts_worker *w) {
+ CILK_ASSERT(WORKER_FREE == w->l->type);
+ w->l->type = WORKER_SYSTEM;
+ w->l->signal_node = signal_node_create();
+}
+
+void __cilkrts_deinit_internal(global_state_t *g)
+{
+ int i;
+ __cilkrts_worker *w;
+
+ // If there's no global state then we're done
+ if (NULL == g)
+ return;
+
+#ifdef CILK_PROFILE
+ __cilkrts_dump_stats_to_stderr(g);
+#endif
+
+ w = g->workers[0];
+ if (w->l->frame_ff) {
+ __cilkrts_destroy_full_frame(w, w->l->frame_ff);
+ w->l->frame_ff = 0;
+ }
+
+ // Release any resources used for record/replay
+ replay_term(g);
+
+ // Destroy any system dependent global state
+ __cilkrts_destroy_global_sysdep(g);
+
+ for (i = 0; i < g->total_workers; ++i)
+ destroy_worker(g->workers[i]);
+
+ // Free memory for all worker blocks which were allocated contiguously
+ __cilkrts_free(g->workers[0]);
+
+ __cilkrts_free(g->workers);
+
+ cilk_fiber_pool_destroy(&g->fiber_pool);
+ __cilkrts_frame_malloc_global_cleanup(g);
+
+ cilkg_deinit_global_state();
+}
+
+/*
+ * Wake the runtime by notifying the system workers that they can steal. The
+ * first user worker into the runtime should call this.
+ */
+static void wake_runtime(global_state_t *g)
+{
+ __cilkrts_worker *root;
+ if (g->P > 1) {
+ // Send a message to the root node. The message will propagate.
+ root = g->workers[0];
+ CILK_ASSERT(root->l->signal_node);
+ signal_node_msg(root->l->signal_node, 1);
+ }
+}
+
+/*
+ * Put the runtime to sleep. The last user worker out of the runtime should
+ * call this. Like Dad always said, turn out the lights when nobody's in the
+ * room.
+ */
+static void sleep_runtime(global_state_t *g)
+{
+ __cilkrts_worker *root;
+ if (g->P > 1) {
+ // Send a message to the root node. The message will propagate.
+ root = g->workers[0];
+ CILK_ASSERT(root->l->signal_node);
+ signal_node_msg(root->l->signal_node, 0);
+ }
+}
+
+/* Called when a user thread joins Cilk.
+ Global lock must be held. */
+void __cilkrts_enter_cilk(global_state_t *g)
+{
+ if (g->Q++ == 0) {
+ // If this is the first user thread to enter Cilk wake
+ // up all the workers.
+ wake_runtime(g);
+ }
+}
+
+/* Called when a user thread leaves Cilk.
+ Global lock must be held. */
+void __cilkrts_leave_cilk(global_state_t *g)
+{
+ if (--g->Q == 0) {
+ // Put the runtime to sleep.
+ sleep_runtime(g);
+ }
+}
+
+/*
+ * worker_runnable
+ *
+ * Return true if the worker should continue to try to steal. False, otherwise.
+ */
+
+NOINLINE
+static enum schedule_t worker_runnable(__cilkrts_worker *w)
+{
+ global_state_t *g = w->g;
+
+ /* If this worker has something to do, do it.
+ Otherwise the work would be lost. */
+ if (w->l->next_frame_ff)
+ return SCHEDULE_RUN;
+
+ // If Cilk has explicitly (by the user) been told to exit (i.e., by
+ // __cilkrts_end_cilk() -> __cilkrts_stop_workers(g)), then return 0.
+ if (g->work_done)
+ return SCHEDULE_EXIT;
+
+ if (0 == w->self) {
+ // This worker is the root node and is the only one that may query the
+ // global state to see if there are still any user workers in Cilk.
+ if (w->l->steal_failure_count > g->max_steal_failures) {
+ if (signal_node_should_wait(w->l->signal_node)) {
+ return SCHEDULE_WAIT;
+ } else {
+ // Reset the steal_failure_count since we have verified that
+ // user workers are still in Cilk.
+ w->l->steal_failure_count = 0;
+ }
+ }
+ } else if (WORKER_SYSTEM == w->l->type &&
+ signal_node_should_wait(w->l->signal_node)) {
+ // This worker has been notified by its parent that it should stop
+ // trying to steal.
+ return SCHEDULE_WAIT;
+ }
+
+ return SCHEDULE_RUN;
+}
+
+
+
+// Initialize the worker structs, but don't start the workers themselves.
+static void init_workers(global_state_t *g)
+{
+ int total_workers = g->total_workers;
+ int i;
+ struct CILK_ALIGNAS(256) buffered_worker {
+ __cilkrts_worker w;
+ char buf[64];
+ } *workers_memory;
+
+ /* not needed if only one worker */
+ cilk_fiber_pool_init(&g->fiber_pool,
+ NULL,
+ g->stack_size,
+ g->global_fiber_pool_size, // buffer_size
+ g->max_stacks, // maximum # to allocate
+ 1);
+
+ cilk_fiber_pool_set_fiber_limit(&g->fiber_pool,
+ (g->max_stacks ? g->max_stacks : INT_MAX));
+
+ g->workers = (__cilkrts_worker **)
+ __cilkrts_malloc(total_workers * sizeof(*g->workers));
+
+ // Allocate 1 block of memory for workers to make life easier for tools
+ // like Inspector which run multithreaded and need to know the memory
+ // range for all the workers that will be accessed in a user's program
+ workers_memory = (struct buffered_worker*)
+ __cilkrts_malloc(sizeof(*workers_memory) * total_workers);
+
+ // Notify any tools that care (Cilkscreen and Inspector) that they should
+ // ignore memory allocated for the workers
+ __cilkrts_cilkscreen_ignore_block(&workers_memory[0],
+ &workers_memory[total_workers]);
+
+ // Initialize worker structs, including unused worker slots.
+ for (i = 0; i < total_workers; ++i) {
+ g->workers[i] = make_worker(g, i, &workers_memory[i].w);
+ }
+
+ // Set the workers in the first P - 1 slots to be system workers.
+ // Remaining worker structs already have type == 0.
+ for (i = 0; i < g->system_workers; ++i) {
+ make_worker_system(g->workers[i]);
+ }
+}
+
+void __cilkrts_init_internal(int start)
+{
+ global_state_t *g = NULL;
+
+ if (cilkg_is_published()) {
+ g = cilkg_init_global_state();
+ }
+ else {
+
+ // We think the state has not been published yet.
+ // Grab the lock and try to initialize/publish.
+ global_os_mutex_lock();
+
+ if (cilkg_is_published()) {
+ // Some other thread must have snuck in and published.
+ g = cilkg_init_global_state();
+ }
+ else {
+ // Initialize and retrieve global state
+ g = cilkg_init_global_state();
+
+ // Set the scheduler pointer
+ g->scheduler = worker_scheduler_function;
+
+ // If we're running under a sequential P-Tool (Cilkscreen or
+ // Cilkview) then there's only one worker and we need to tell
+ // the tool about the extent of the stack
+ if (g->under_ptool)
+ __cilkrts_establish_c_stack();
+ init_workers(g);
+
+ // Initialize per-work record/replay logging
+ replay_init_workers(g);
+
+ // Initialize any system dependent global state
+ __cilkrts_init_global_sysdep(g);
+
+
+ cilkg_publish_global_state(g);
+ }
+
+ global_os_mutex_unlock();
+ }
+
+ CILK_ASSERT(g);
+
+ if (start && !g->workers_running)
+ {
+ // Acquire the global OS mutex while we're starting the workers
+ global_os_mutex_lock();
+ if (!g->workers_running)
+ // Start P - 1 system workers since P includes the first user
+ // worker.
+ __cilkrts_start_workers(g, g->P - 1);
+ global_os_mutex_unlock();
+ }
+}
+
+
+/************************************************************************
+ Methods for reducer protocol.
+
+ Reductions occur in two places:
+ A. A full frame "ff" is returning from a spawn with a stolen parent.
+ B. A full frame "ff" is stalling at a sync.
+
+ To support parallel reductions, reduction functions need to be
+ executed while control is on a user stack, before jumping into the
+ runtime. These reductions can not occur while holding a worker or
+ frame lock.
+
+ Before a worker w executes a reduction in either Case A or B, w's
+ deque is empty.
+
+ Since parallel reductions push work onto the deque, we must do extra
+ work to set up runtime data structures properly before reductions
+ begin to allow stealing. ( Normally, when we have only serial
+ reductions, once a worker w starts a reduction, its deque remains
+ empty until w either steals another frame or resumes a suspended
+ frame. Thus, we don't care about the state of the deque, since w
+ will reset its deque when setting up execution of a frame. )
+
+ To allow for parallel reductions, we coerce the runtime data
+ structures so that, from their perspective, it looks as though we
+ have spliced in an "execute_reductions()" function. Consider the
+ two cases for reductions:
+
+ Case A: Return from a spawn with a stolen parent.
+ Consider a spawned function g is returning on a worker w.
+ Assume:
+ - g was spawned from a parent function f.
+ - ff is the full frame for g's spawn helper
+ - sf be the __cilkrts_stack_frame for g's spawn helper.
+
+ We are conceptually splicing "execute_reductions()" so that it
+ occurs immediately before the spawn helper of g returns to f.
+
+ We do so by creating two different world views --- one for the
+ runtime data structures, and one for the actual control flow.
+
+ - Before reductions begin, the runtime data structures should
+ look as though the spawn helper of g is calling
+ "execute_reductions()", in terms of both the user stack and
+ worker deque. More precisely, w should satisfy the
+ following properties:
+
+ (a) w has ff as its full frame,
+ (b) w has sf as its __cilkrts_stack_frame, and
+ (c) w has an empty deque.
+
+ If the runtime satisfies these properties, then if w
+ encounters a spawn in a parallel reduction, it can push onto
+ a valid deque. Also, when a steal from w occurs, it will
+ build the correct tree of full frames when w is stolen from.
+
+ - In actual control flow, however, once the
+ "execute_reductions()" function returns, it is actually
+ returning to runtime code instead of g's spawn helper.
+
+ At the point a worker w began executing reductions, the
+ control flow / compiled code had already finished g's spawn
+ helper, and w was about to enter the runtime. With parallel
+ reductions, some worker v (which might be different from w)
+ is the one returning to the runtime.
+
+
+ The reduction logic consists of 4 steps:
+
+ A1. Restore runtime data structures to make it look as though
+ the spawn helper of g() is still the currently executing
+ frame for w.
+
+ A2. Execute reductions on the user stack. Reductions also
+ includes the logic for exceptions and stacks. Note that
+ reductions start on w, but may finish on a different
+ worker if there is parallelism in the reduce.
+
+ A3. Splice out ff from the tree of full frames.
+
+ A4. Jump into the runtime/scheduling stack and execute
+ "do_return_from_spawn". This method
+
+ (a) Frees the user stack we were just on if it is no longer needed.
+ (b) Decrement the join counter on ff->parent, and tries to do a
+ provably good steal.
+ (c) Clean up the full frame ff.
+
+
+ Case B: Stalling at a sync.
+
+ Consider a function g(), with full frame ff and
+ __cilkrts_stack_frame sf. Suppose g() stalls at a sync, and we
+ are executing reductions.
+
+ Conceptually, we are splicing in an "execute_reductions()"
+ function into g() as the last action that g() takes immediately
+ before it executes the cilk_sync.
+
+ The reduction logic for this case is similar to Case A.
+
+ B1. Restore the runtime data structures.
+
+ The main difference from Case A is that ff/sf is still a
+ frame that needs to be executed later (since it is stalling
+ at a cilk_sync). Thus, we also need to save the current
+ stack information into "ff" so that we can correctly resume
+ execution of "ff" after the sync.
+
+ B2. Execute reductions on the user stack.
+
+ B3. No frame to splice out of the tree.
+
+ B4. Jump into the runtime/scheduling stack and execute "do_sync".
+ This method:
+ (a) Frees the user stack we were just on if it is no longer needed.
+ (b) Tries to execute a provably good steal.
+
+ Finally, for the reducer protocol, we consider two reduction paths,
+ namely a "fast" and "slow" path. On a fast path, only trivial
+ merges of reducer maps happen (i.e., one or both of the maps are
+ NULL). Otherwise, on the slow path, a reduction actually needs to
+ happen.
+
+*****************************************************************/
+
+/**
+ * @brief Locations to store the result of a reduction.
+ *
+ * Struct storing pointers to the fields in our "left" sibling that we
+ * should update when splicing out a full frame or stalling at a sync.
+ */
+typedef struct {
+ /** A pointer to the location of our left reducer map. */
+ struct cilkred_map **map_ptr;
+
+ /** A pointer to the location of our left exception. */
+ struct pending_exception_info **exception_ptr;
+} splice_left_ptrs;
+
+/**
+ * For a full frame returning from a spawn, calculate the pointers to
+ * the maps and exceptions to my left.
+ *
+ * @param w The currently executing worker.
+ * @param ff Full frame that is dying
+ * @return Pointers to our "left" for reducers and exceptions.
+ */
+static inline
+splice_left_ptrs compute_left_ptrs_for_spawn_return(__cilkrts_worker *w,
+ full_frame *ff)
+{
+ // ASSERT: we hold the lock on ff->parent
+
+ splice_left_ptrs left_ptrs;
+ if (ff->left_sibling) {
+ left_ptrs.map_ptr = &ff->left_sibling->right_reducer_map;
+ left_ptrs.exception_ptr = &ff->left_sibling->right_pending_exception;
+ }
+ else {
+ full_frame *parent_ff = ff->parent;
+ left_ptrs.map_ptr = &parent_ff->children_reducer_map;
+ left_ptrs.exception_ptr = &parent_ff->child_pending_exception;
+ }
+ return left_ptrs;
+}
+
+/**
+ * For a full frame at a sync, calculate the pointers to the maps and
+ * exceptions to my left.
+ *
+ * @param w The currently executing worker.
+ * @param ff Full frame that is stalling at a sync.
+ * @return Pointers to our "left" for reducers and exceptions.
+ */
+static inline
+splice_left_ptrs compute_left_ptrs_for_sync(__cilkrts_worker *w,
+ full_frame *ff)
+{
+ // ASSERT: we hold the lock on ff
+ splice_left_ptrs left_ptrs;
+
+ // Figure out which map to the left we should merge into.
+ if (ff->rightmost_child) {
+ CILK_ASSERT(ff->rightmost_child->parent == ff);
+ left_ptrs.map_ptr = &(ff->rightmost_child->right_reducer_map);
+ left_ptrs.exception_ptr = &(ff->rightmost_child->right_pending_exception);
+ }
+ else {
+ // We have no children. Then, we should be the last
+ // worker at the sync... "left" is our child map.
+ left_ptrs.map_ptr = &(ff->children_reducer_map);
+ left_ptrs.exception_ptr = &(ff->child_pending_exception);
+ }
+ return left_ptrs;
+}
+
+/**
+ * After we have completed all reductions on a spawn return, call this
+ * method to finish up before jumping into the runtime.
+ *
+ * 1. Perform the "reduction" on stacks, i.e., execute the left
+ * holder logic to pass the leftmost stack up.
+ *
+ * w->l->fiber_to_free holds any stack that needs to be freed
+ * when control switches into the runtime fiber.
+ *
+ * 2. Unlink and remove child_ff from the tree of full frames.
+ *
+ * @param w The currently executing worker.
+ * @param parent_ff The parent of child_ff.
+ * @param child_ff The full frame returning from a spawn.
+ */
+static inline
+void finish_spawn_return_on_user_stack(__cilkrts_worker *w,
+ full_frame *parent_ff,
+ full_frame *child_ff)
+{
+ CILK_ASSERT(w->l->fiber_to_free == NULL);
+
+ // Execute left-holder logic for stacks.
+ if (child_ff->left_sibling || parent_ff->fiber_child) {
+ // Case where we are not the leftmost stack.
+ CILK_ASSERT(parent_ff->fiber_child != child_ff->fiber_self);
+
+ // Remember any fiber we need to free in the worker.
+ // After we jump into the runtime, we will actually do the
+ // free.
+ w->l->fiber_to_free = child_ff->fiber_self;
+ }
+ else {
+ // We are leftmost, pass stack/fiber up to parent.
+ // Thus, no stack/fiber to free.
+ parent_ff->fiber_child = child_ff->fiber_self;
+ w->l->fiber_to_free = NULL;
+ }
+
+ child_ff->fiber_self = NULL;
+
+ unlink_child(parent_ff, child_ff);
+}
+
+
+/**
+ * Executes any fast reductions necessary to splice ff out of the tree
+ * of full frames.
+ *
+ * This "fast" path performs only trivial merges of reducer maps,
+ * i.e,. when one of them is NULL.
+ * (See slow_path_reductions_for_spawn_return() for slow path.)
+ *
+ * Returns: 1 if we finished all reductions.
+ * Returns: 0 if there are still reductions to execute, and
+ * we should execute the slow path.
+ *
+ * This method assumes w holds the frame lock on parent_ff.
+ * After this method completes:
+ * 1. We have spliced ff out of the tree of full frames.
+ * 2. The reducer maps of child_ff have been deposited
+ * "left" according to the reducer protocol.
+ * 3. w->l->stack_to_free stores the stack
+ * that needs to be freed once we jump into the runtime.
+ *
+ * We have not, however, decremented the join counter on ff->parent.
+ * This prevents any other workers from resuming execution of the parent.
+ *
+ * @param w The currently executing worker.
+ * @param ff The full frame returning from a spawn.
+ * @return NULL if we finished all reductions.
+ * @return The address where the left map is stored (which should be passed to
+ * slow_path_reductions_for_spawn_return()) if there are
+ * still reductions to execute.
+ */
+struct cilkred_map**
+fast_path_reductions_for_spawn_return(__cilkrts_worker *w,
+ full_frame *ff)
+{
+ // ASSERT: we hold ff->parent->lock.
+ splice_left_ptrs left_ptrs;
+
+ CILK_ASSERT(NULL == w->l->pending_exception);
+
+ // Figure out the pointers to the left where I want
+ // to put reducers and exceptions.
+ left_ptrs = compute_left_ptrs_for_spawn_return(w, ff);
+
+ // Go ahead and merge exceptions while holding the lock.
+ splice_exceptions_for_spawn(w, ff, left_ptrs.exception_ptr);
+
+ // Now check if we have any reductions to perform.
+ //
+ // Consider all the cases of left, middle and right maps.
+ // 0. (-, -, -) : finish and return 1
+ // 1. (L, -, -) : finish and return 1
+ // 2. (-, M, -) : slide over to left, finish, and return 1.
+ // 3. (L, M, -) : return 0
+ // 4. (-, -, R) : slide over to left, finish, and return 1.
+ // 5. (L, -, R) : return 0
+ // 6. (-, M, R) : return 0
+ // 7. (L, M, R) : return 0
+ //
+ // In terms of code:
+ // L == *left_ptrs.map_ptr
+ // M == w->reducer_map
+ // R == f->right_reducer_map.
+ //
+ // The goal of the code below is to execute the fast path with
+ // as few branches and writes as possible.
+
+ int case_value = (*(left_ptrs.map_ptr) != NULL);
+ case_value += ((w->reducer_map != NULL) << 1);
+ case_value += ((ff->right_reducer_map != NULL) << 2);
+
+ // Fastest path is case_value == 0 or 1.
+ if (case_value >=2) {
+ switch (case_value) {
+ case 2:
+ *(left_ptrs.map_ptr) = w->reducer_map;
+ w->reducer_map = NULL;
+ return NULL;
+ break;
+ case 4:
+ *(left_ptrs.map_ptr) = ff->right_reducer_map;
+ ff->right_reducer_map = NULL;
+ return NULL;
+ default:
+ // If we have to execute the slow path, then
+ // return the pointer to the place to deposit the left
+ // map.
+ return left_ptrs.map_ptr;
+ }
+ }
+
+ // Do nothing
+ return NULL;
+}
+
+
+/**
+ * Executes any reductions necessary to splice "ff" frame out of
+ * the steal tree.
+ *
+ * This method executes the "slow" path for reductions on a spawn
+ * return, i.e., there are non-NULL maps that need to be merged
+ * together.
+ *
+ * This method should execute only if
+ * fast_path_reductions_for_spawn_return() returns a non-NULL
+ * left_map_ptr.
+ *
+ * Upon entry, left_map_ptr should be the location of the left map
+ * at the start of the reduction, as calculated by
+ * fast_path_reductions_for_spawn_return().
+ *
+ * After this method completes:
+ * 1. We have spliced ff out of the tree of full frames.
+ * 2. The reducer maps of child_ff have been deposited
+ * "left" according to the reducer protocol.
+ * 3. w->l->stack_to_free stores the stack
+ * that needs to be freed once we jump into the runtime.
+ * We have not, however, decremented the join counter on ff->parent,
+ * so no one can resume execution of the parent yet.
+ *
+ * WARNING:
+ * This method assumes the lock on ff->parent is held upon entry, and
+ * Upon exit, the worker that returns still holds a lock on ff->parent
+ * This method can, however, release and reacquire the lock on ff->parent.
+ *
+ * @param w The currently executing worker.
+ * @param ff The full frame returning from a spawn.
+ * @param left_map_ptr Pointer to our initial left map.
+ * @return The worker that this method returns on.
+ */
+static __cilkrts_worker*
+slow_path_reductions_for_spawn_return(__cilkrts_worker *w,
+ full_frame *ff,
+ struct cilkred_map **left_map_ptr)
+{
+
+ // CILK_ASSERT: w is holding frame lock on parent_ff.
+#if REDPAR_DEBUG > 0
+ CILK_ASSERT(!ff->rightmost_child);
+ CILK_ASSERT(!ff->is_call_child);
+#endif
+
+ // Loop invariant:
+ // When beginning this loop, we should
+ // 1. Be holding the lock on ff->parent.
+ // 2. left_map_ptr should be the address of the pointer to the left map.
+ // 3. All maps should be slid over left by one, if possible.
+ // 4. All exceptions should be merged so far.
+ while (1) {
+
+ // Slide middle map left if possible.
+ if (!(*left_map_ptr)) {
+ *left_map_ptr = w->reducer_map;
+ w->reducer_map = NULL;
+ }
+ // Slide right map to middle if possible.
+ if (!w->reducer_map) {
+ w->reducer_map = ff->right_reducer_map;
+ ff->right_reducer_map = NULL;
+ }
+
+ // Since we slid everything left by one,
+ // we are finished if there is no middle map.
+ if (!w->reducer_map) {
+ verify_current_wkr(w);
+ return w;
+ }
+ else {
+ struct cilkred_map* left_map;
+ struct cilkred_map* middle_map;
+ struct cilkred_map* right_map;
+
+ // Take all the maps from their respective locations.
+ // We can't leave them in place and execute a reduction because these fields
+ // might change once we release the lock.
+ left_map = *left_map_ptr;
+ *left_map_ptr = NULL;
+ middle_map = w->reducer_map;
+ w->reducer_map = NULL;
+ right_map = ff->right_reducer_map;
+ ff->right_reducer_map = NULL;
+
+ // WARNING!!! Lock release here.
+ // We have reductions to execute (and we can't hold locks).
+ __cilkrts_frame_unlock(w, ff->parent);
+
+ // Merge all reducers into the left map.
+ left_map = repeated_merge_reducer_maps(&w,
+ left_map,
+ middle_map);
+ verify_current_wkr(w);
+ left_map = repeated_merge_reducer_maps(&w,
+ left_map,
+ right_map);
+ verify_current_wkr(w);
+ CILK_ASSERT(NULL == w->reducer_map);
+ // Put the final answer back into w->reducer_map.
+ w->reducer_map = left_map;
+
+ // Save any exceptions generated because of the reduction
+ // process from the returning worker. These get merged
+ // the next time around the loop.
+ CILK_ASSERT(NULL == ff->pending_exception);
+ ff->pending_exception = w->l->pending_exception;
+ w->l->pending_exception = NULL;
+
+ // Lock ff->parent for the next loop around.
+ __cilkrts_frame_lock(w, ff->parent);
+
+ // Once we have the lock again, recompute who is to our
+ // left.
+ splice_left_ptrs left_ptrs;
+ left_ptrs = compute_left_ptrs_for_spawn_return(w, ff);
+
+ // Update the pointer for the left map.
+ left_map_ptr = left_ptrs.map_ptr;
+ // Splice the exceptions for spawn.
+ splice_exceptions_for_spawn(w, ff, left_ptrs.exception_ptr);
+ }
+ }
+ // We should never break out of this loop.
+
+ CILK_ASSERT(0);
+ return NULL;
+}
+
+
+
+/**
+ * Execute reductions when returning from a spawn whose parent has
+ * been stolen.
+ *
+ * Execution may start on w, but may finish on a different worker.
+ * This method acquires/releases the lock on ff->parent.
+ *
+ * @param w The currently executing worker.
+ * @param ff The full frame of the spawned function that is returning.
+ * @param returning_sf The __cilkrts_stack_frame for this returning function.
+ * @return The worker returning from this method.
+ */
+static __cilkrts_worker*
+execute_reductions_for_spawn_return(__cilkrts_worker *w,
+ full_frame *ff,
+ __cilkrts_stack_frame *returning_sf)
+{
+ // Step A1 from reducer protocol described above.
+ //
+ // Coerce the runtime into thinking that
+ // ff/returning_sf are still on the bottom of
+ // w's deque.
+ restore_frame_for_spawn_return_reduction(w, ff, returning_sf);
+
+ // Step A2 and A3: Execute reductions on user stack.
+ BEGIN_WITH_FRAME_LOCK(w, ff->parent) {
+ struct cilkred_map **left_map_ptr;
+ left_map_ptr = fast_path_reductions_for_spawn_return(w, ff);
+
+ // Pointer will be non-NULL if there are
+ // still reductions to execute.
+ if (left_map_ptr) {
+ // WARNING: This method call may release the lock
+ // on ff->parent and re-acquire it (possibly on a
+ // different worker).
+ // We can't hold locks while actually executing
+ // reduce functions.
+ w = slow_path_reductions_for_spawn_return(w,
+ ff,
+ left_map_ptr);
+ verify_current_wkr(w);
+ }
+
+ finish_spawn_return_on_user_stack(w, ff->parent, ff);
+ // WARNING: the use of this lock macro is deceptive.
+ // The worker may have changed here.
+ } END_WITH_FRAME_LOCK(w, ff->parent);
+ return w;
+}
+
+
+
+/**
+ * Execute fast "reductions" when ff stalls at a sync.
+ *
+ * @param w The currently executing worker.
+ * @param ff The full frame stalling at a sync.
+ * @return 1 if we are finished with all reductions after calling this method.
+ * @return 0 if we still need to execute the slow path reductions.
+ */
+static inline
+int fast_path_reductions_for_sync(__cilkrts_worker *w,
+ full_frame *ff) {
+ // Return 0 if there is some reduction that needs to happen.
+ return !(w->reducer_map || ff->pending_exception);
+}
+
+/**
+ * Executes slow reductions when ff stalls at a sync.
+ * This method should execute only if
+ * fast_path_reductions_for_sync(w, ff) returned 0.
+ *
+ * After this method completes:
+ * 1. ff's current reducer map has been deposited into
+ * right_reducer_map of ff's rightmost child, or
+ * ff->children_reducer_map if ff has no children.
+ * 2. Similarly for ff's current exception.
+ * 3. Nothing to calculate for stacks --- if we are stalling
+ * we will always free a stack.
+ *
+ * This method may repeatedly acquire/release the lock on ff.
+ *
+ * @param w The currently executing worker.
+ * @param ff The full frame stalling at a sync.
+ * @return The worker returning from this method.
+ */
+static __cilkrts_worker*
+slow_path_reductions_for_sync(__cilkrts_worker *w,
+ full_frame *ff)
+{
+ struct cilkred_map *left_map;
+ struct cilkred_map *middle_map;
+
+#if (REDPAR_DEBUG > 0)
+ CILK_ASSERT(ff);
+ CILK_ASSERT(w->head == w->tail);
+#endif
+
+ middle_map = w->reducer_map;
+ w->reducer_map = NULL;
+
+ // Loop invariant: middle_map should be valid (the current map to reduce).
+ // left_map is junk.
+ // w->reducer_map == NULL.
+ while (1) {
+ BEGIN_WITH_FRAME_LOCK(w, ff) {
+ splice_left_ptrs left_ptrs = compute_left_ptrs_for_sync(w, ff);
+
+ // Grab the "left" map and store pointers to those locations.
+ left_map = *(left_ptrs.map_ptr);
+ *(left_ptrs.map_ptr) = NULL;
+
+ // Slide the maps in our struct left as far as possible.
+ if (!left_map) {
+ left_map = middle_map;
+ middle_map = NULL;
+ }
+
+ *(left_ptrs.exception_ptr) =
+ __cilkrts_merge_pending_exceptions(w,
+ *left_ptrs.exception_ptr,
+ ff->pending_exception);
+ ff->pending_exception = NULL;
+
+ // If there is no middle map, then we are done.
+ // Deposit left and return.
+ if (!middle_map) {
+ *(left_ptrs).map_ptr = left_map;
+ #if (REDPAR_DEBUG > 0)
+ CILK_ASSERT(NULL == w->reducer_map);
+ #endif
+ // Sanity check upon leaving the loop.
+ verify_current_wkr(w);
+ // Make sure to unlock before we return!
+ __cilkrts_frame_unlock(w, ff);
+ return w;
+ }
+ } END_WITH_FRAME_LOCK(w, ff);
+
+ // If we get here, we have a nontrivial reduction to execute.
+ middle_map = repeated_merge_reducer_maps(&w,
+ left_map,
+ middle_map);
+ verify_current_wkr(w);
+
+ // Save any exceptions generated because of the reduction
+ // process. These get merged the next time around the
+ // loop.
+ CILK_ASSERT(NULL == ff->pending_exception);
+ ff->pending_exception = w->l->pending_exception;
+ w->l->pending_exception = NULL;
+ }
+
+ // We should never break out of the loop above.
+ CILK_ASSERT(0);
+ return NULL;
+}
+
+
+/**
+ * Execute reductions when ff stalls at a sync.
+ *
+ * Execution starts on w, but may finish on a different worker.
+ * This method may acquire/release the lock on ff.
+ *
+ * @param w The currently executing worker.
+ * @param ff The full frame of the spawned function at the sync
+ * @param sf_at_sync The __cilkrts_stack_frame stalling at a sync
+ * @return The worker returning from this method.
+ */
+static __cilkrts_worker*
+execute_reductions_for_sync(__cilkrts_worker *w,
+ full_frame *ff,
+ __cilkrts_stack_frame *sf_at_sync)
+{
+ int finished_reductions;
+ // Step B1 from reducer protocol above:
+ // Restore runtime invariants.
+ //
+ // The following code for this step is almost equivalent to
+ // the following sequence:
+ // 1. disown(w, ff, sf_at_sync, "sync") (which itself
+ // calls make_unrunnable(w, ff, sf_at_sync))
+ // 2. make_runnable(w, ff, sf_at_sync).
+ //
+ // The "disown" will mark the frame "sf_at_sync"
+ // as stolen and suspended, and save its place on the stack,
+ // so it can be resumed after the sync.
+ //
+ // The difference is, that we don't want the disown to
+ // break the following connections yet, since we are
+ // about to immediately make sf/ff runnable again anyway.
+ // sf_at_sync->worker == w
+ // w->l->frame_ff == ff.
+ //
+ // These connections are needed for parallel reductions, since
+ // we will use sf / ff as the stack frame / full frame for
+ // executing any potential reductions.
+ //
+ // TBD: Can we refactor the disown / make_unrunnable code
+ // to avoid the code duplication here?
+
+ ff->call_stack = NULL;
+
+ // Normally, "make_unrunnable" would add CILK_FRAME_STOLEN and
+ // CILK_FRAME_SUSPENDED to sf_at_sync->flags and save the state of
+ // the stack so that a worker can resume the frame in the correct
+ // place.
+ //
+ // But on this path, CILK_FRAME_STOLEN should already be set.
+ // Also, we technically don't want to suspend the frame until
+ // the reduction finishes.
+ // We do, however, need to save the stack before
+ // we start any reductions, since the reductions might push more
+ // data onto the stack.
+ CILK_ASSERT(sf_at_sync->flags | CILK_FRAME_STOLEN);
+
+ __cilkrts_put_stack(ff, sf_at_sync);
+ __cilkrts_make_unrunnable_sysdep(w, ff, sf_at_sync, 1,
+ "execute_reductions_for_sync");
+ CILK_ASSERT(w->l->frame_ff == ff);
+
+ // Step B2: Execute reductions on user stack.
+ // Check if we have any "real" reductions to do.
+ finished_reductions = fast_path_reductions_for_sync(w, ff);
+
+ if (!finished_reductions) {
+ // Still have some real reductions to execute.
+ // Run them here.
+
+ // This method may acquire/release the lock on ff.
+ w = slow_path_reductions_for_sync(w, ff);
+
+ // The previous call may return on a different worker.
+ // than what we started on.
+ verify_current_wkr(w);
+ }
+
+#if REDPAR_DEBUG >= 0
+ CILK_ASSERT(w->l->frame_ff == ff);
+ CILK_ASSERT(ff->call_stack == NULL);
+#endif
+
+ // Now we suspend the frame ff (since we've
+ // finished the reductions). Roughly, we've split apart the
+ // "make_unrunnable" call here --- we've already saved the
+ // stack info earlier before the reductions execute.
+ // All that remains is to restore the call stack back into the
+ // full frame, and mark the frame as suspended.
+ ff->call_stack = sf_at_sync;
+ sf_at_sync->flags |= CILK_FRAME_SUSPENDED;
+
+ // At a nontrivial sync, we should always free the current fiber,
+ // because it can not be leftmost.
+ w->l->fiber_to_free = ff->fiber_self;
+ ff->fiber_self = NULL;
+ return w;
+}
+
+
+/*
+ Local Variables: **
+ c-file-style:"bsd" **
+ c-basic-offset:4 **
+ indent-tabs-mode:nil **
+ End: **
+*/
diff --git a/libcilkrts/runtime/scheduler.h b/libcilkrts/runtime/scheduler.h
new file mode 100644
index 00000000000..543adaf68e0
--- /dev/null
+++ b/libcilkrts/runtime/scheduler.h
@@ -0,0 +1,421 @@
+/* scheduler.h -*-C++-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ **************************************************************************/
+
+/**
+ * @file scheduler.h
+ *
+ * @brief scheduler.h declares routines for the Intel Cilk Plus scheduler,
+ * making it the heart of the Intel Cilk Plus implementation.
+ */
+
+#ifndef INCLUDED_SCHEDULER_DOT_H
+#define INCLUDED_SCHEDULER_DOT_H
+
+#include <cilk/common.h>
+#include <internal/abi.h>
+
+#include "rts-common.h"
+#include "full_frame.h"
+#include "reducer_impl.h"
+#include "global_state.h"
+
+#ifdef CILK_RECORD_REPLAY
+#include "record-replay.h"
+#endif
+
+__CILKRTS_BEGIN_EXTERN_C
+
+
+/**
+ * @brief Flag to disable parallel reductions.
+ *
+ * Set to 0 to allow parallel reductions.
+ */
+#define DISABLE_PARALLEL_REDUCERS 0
+
+/**
+ * @brief Debugging level for parallel reductions.
+ *
+ * Print debugging messages and assertions for parallel reducers. 0 is
+ * no debugging. A higher value generates more output.
+ */
+#define REDPAR_DEBUG 0
+
+/**
+ * @brief Lock the worker mutex to allow exclusive access to the
+ * values in the @c __cilkrts_worker and local_state structures.
+ *
+ * @pre @c w->l->do_not_steal must not be set. Essentially this
+ * condition asserts that the worker is not locked recursively.
+ *
+ * @param w The worker to lock.
+ */
+COMMON_PORTABLE
+void __cilkrts_worker_lock(__cilkrts_worker *w);
+
+/**
+ * @brief Unlock the worker mutex.
+ *
+ * @pre @c w->l->do_not_steal must be set. Essentially this condition
+ * asserts that the worker has been previously locked.
+ *
+ * @param w The worker to unlock.
+ */
+COMMON_PORTABLE
+void __cilkrts_worker_unlock(__cilkrts_worker *w);
+
+/**
+ * @brief Push the next full frame to be made active in this worker
+ * and increment its join counter.
+ *
+ * __cilkrts_push_next_frame and pop_next_frame work on a one-element queue.
+ * This queue is used to communicate across the runtime from the code that
+ * wants to activate a frame to the code that can actually begin execution
+ * on that frame. They are asymetrical in that push increments the join
+ * counter but pop does not decrement it. Rather, a single push/pop
+ * combination makes a frame active and increments its join counter once.
+ *
+ * @note A system worker may chose to push work onto a user worker if
+ * the work is the continuation from a sync which only the user worker
+ * may complete.
+ *
+ * @param w The worker which the frame is to be pushed onto.
+ * @param ff The full_frame which is to be continued by the worker.
+ */
+COMMON_PORTABLE
+void __cilkrts_push_next_frame(__cilkrts_worker *w,
+ full_frame *ff);
+
+/**
+ * @brief Sync on this worker.
+ *
+ * If this worker is the last to reach the sync, execution may resume
+ * on this worker after the sync.
+ *
+ * If this worker is not the last spawned child to reach the sync,
+ * then execution is suspended and the worker will re-enter the
+ * scheduling loop, looking for work it can steal.
+ *
+ * This function will jump into the runtime to switch to the scheduling
+ * stack to implement most of its logic.
+ *
+ * @param w The worker which is executing the sync.
+ * @param sf The __cilkrts_stack_frame containing the sync.
+ */
+COMMON_PORTABLE
+NORETURN __cilkrts_c_sync(__cilkrts_worker *w,
+ __cilkrts_stack_frame *sf);
+
+/**
+ * @brief Worker @c w completely promotes its own deque, simulating the case
+ * where the whole deque is stolen.
+ *
+ * We use this mechanism to force the allocation of new storage for
+ * reducers for race-detection purposes.
+ *
+ * This method is called from the reducer lookup logic when
+ * @c g->force_reduce is set.
+ *
+ * @warning Use of "force_reduce" is known to have bugs when run with
+ * more than 1 worker.
+ *
+ * @param w The worker which is to have all entries in its deque
+ * promoted to full frames.
+ */
+COMMON_PORTABLE
+void __cilkrts_promote_own_deque(__cilkrts_worker *w);
+
+/**
+ * Called when a spawned function attempts to return and
+ * __cilkrts_undo_detach() fails. This can happen for two reasons:
+ *
+ * @li If another worker is considering stealing our parent, it bumps the
+ * exception pointer while it did so, which will cause __cilkrts_undo_detach()
+ * to fail. If the other worker didn't complete the steal of our parent, we
+ * still may be able to return to it, either because the steal attempt failed,
+ * or we won the race for the tail pointer.
+ *
+ * @li If the function's parent has been stolen then we cannot return. Instead
+ * we'll longjmp into the runtime to switch onto the scheduling stack to
+ * execute do_return_from_spawn() and determine what to do. Either this
+ * worker is the last one to the sync, in which case we need to jump to the
+ * sync, or this worker is not the last one to the sync, in which case we'll
+ * abandon this work and jump to the scheduling loop to search for more work
+ * we can steal.
+ *
+ * @param w The worker which attempting to return from a spawn to
+ * a stolen parent.
+ * @param returning_sf The stack frame which is returning.
+ */
+COMMON_PORTABLE
+void __cilkrts_c_THE_exception_check(__cilkrts_worker *w,
+ __cilkrts_stack_frame *returning_sf);
+
+/**
+ * @brief Return an exception to an stolen parent.
+ *
+ * Used by the gcc implementation of exceptions to return an exception
+ * to a stolen parent
+ *
+ * @param w The worker which attempting to return from a spawn with an
+ * exception to a stolen parent.
+ * @param returning_sf The stack frame which is returning.
+ */
+COMMON_PORTABLE
+NORETURN __cilkrts_exception_from_spawn(__cilkrts_worker *w,
+ __cilkrts_stack_frame *returning_sf);
+
+/**
+ * @brief Used by the Windows implementations of exceptions to migrate an exception
+ * across fibers.
+ *
+ * Call this function when an exception has been thrown and has to
+ * traverse across a steal. The exception has already been wrapped
+ * up, so all that remains is to longjmp() into the continuation,
+ * sync, and re-raise it.
+ *
+ * @param sf The __cilkrts_stack_frame for the frame that is attempting to
+ * return an exception to a stolen parent.
+ */
+void __cilkrts_migrate_exception (__cilkrts_stack_frame *sf);
+
+/**
+ * @brief Return from a call, not a spawn, where this frame has ever
+ * been stolen.
+ *
+ * @param w The worker that is returning from a frame which was ever stolen.
+ */
+COMMON_PORTABLE
+void __cilkrts_return(__cilkrts_worker *w);
+
+/**
+ * @brief Special return from the initial frame.
+ *
+ * This method will be called from @c __cilkrts_leave_frame if
+ * @c CILK_FRAME_LAST is set.
+ *
+ * This function will do the things necessary to cleanup, and unbind the
+ * thread from the Intel Cilk Plus runtime. If this is the last user
+ * worker unbinding from the runtime, all system worker threads will be
+ * suspended.
+ *
+ * @pre @c w must be the currently executing worker, and must be a user
+ * worker.
+ *
+ * @param w The worker that's returning from the initial frame.
+ */
+COMMON_PORTABLE
+void __cilkrts_c_return_from_initial(__cilkrts_worker *w);
+
+/**
+ * @brief Used by exception handling code to pop an entry from the
+ * worker's deque.
+ *
+ * @param w Worker to pop the entry from
+ *
+ * @return __cilkrts_stack_frame of parent call
+ * @return NULL if the deque is empty
+ */
+COMMON_PORTABLE
+__cilkrts_stack_frame *__cilkrts_pop_tail(__cilkrts_worker *w);
+
+/**
+ * @brief Modifies the worker's protected_tail to prevent frames from
+ * being stolen.
+ *
+ * The Dekker protocol has been extended to only steal if head+1 is also
+ * less than protected_tail.
+ *
+ * @param w The worker to be modified.
+ * @param new_protected_tail The new setting for protected_tail, or NULL if the
+ * entire deque is to be protected
+ *
+ * @return Previous value of protected tail.
+ */
+COMMON_PORTABLE
+__cilkrts_stack_frame *volatile *__cilkrts_disallow_stealing(
+ __cilkrts_worker *w,
+ __cilkrts_stack_frame *volatile *new_protected_tail);
+
+/**
+ * @brief Restores the protected tail to a previous state, possibly
+ * allowing frames to be stolen.
+ *
+ * @param w The worker to be modified.
+ * @param saved_protected_tail A previous setting for protected_tail that is
+ * to be restored
+ */
+COMMON_PORTABLE
+void __cilkrts_restore_stealing(
+ __cilkrts_worker *w,
+ __cilkrts_stack_frame *volatile *saved_protected_tail);
+
+/**
+ * @brief Initialize a @c __cilkrts_worker.
+ *
+ * @note The memory for the worker must have been allocated outside
+ * this call.
+ *
+ * @param g The global_state_t.
+ * @param self The index into the global_state's array of workers for this
+ * worker, or -1 if this worker was allocated from the heap and cannot be
+ * stolen from.
+ * @param w The worker to be initialized.
+ *
+ * @return The initialized __cilkrts_worker.
+ */
+COMMON_PORTABLE
+__cilkrts_worker *make_worker(global_state_t *g,
+ int self,
+ __cilkrts_worker *w);
+
+/**
+ * @brief Free up any resources allocated for a worker.
+ *
+ * @note The memory for the @c __cilkrts_worker itself must be
+ * deallocated outside this call.
+ *
+ * @param w The worker to be destroyed.
+ */
+COMMON_PORTABLE
+void destroy_worker (__cilkrts_worker *w);
+
+/**
+ * @brief Initialize the runtime.
+ *
+ * If necessary, allocates and initializes the global state. If
+ * necessary, unsuspends the system workers.
+ *
+ * @param start Specifies whether the workers are to be unsuspended if
+ * they are suspended. Allows __cilkrts_init() to start up the runtime without
+ * releasing the system threads.
+ */
+COMMON_PORTABLE
+void __cilkrts_init_internal(int start);
+
+/**
+ * @brief Part of the sequence to shutdown the runtime.
+ *
+ * Specifically, this call frees the @c global_state_t for the runtime.
+ *
+ * @param g The global_state_t.
+ */
+COMMON_PORTABLE
+void __cilkrts_deinit_internal(global_state_t *g);
+
+/**
+ * Obsolete. We no longer need to import or export reducer maps.
+ */
+COMMON_PORTABLE
+cilkred_map *__cilkrts_xchg_reducer(
+ __cilkrts_worker *w, cilkred_map *newmap) cilk_nothrow;
+
+/**
+ * @brief Called when a user thread is bound to the runtime.
+ *
+ * If this action increments the count of bound user threads from 0 to
+ * 1, the system worker threads are unsuspended.
+ *
+ * If this action increments the count of bound user threads from 0 to
+ * 1, the system worker threads are unsuspended.
+ *
+ * @pre Global lock must be held.
+ * @param g The runtime global state.
+ */
+COMMON_PORTABLE
+void __cilkrts_enter_cilk(global_state_t *g);
+
+/**
+ * @brief Called when a user thread is unbound from the runtime.
+ *
+ * If this action decrements the count of bound user threads to 0, the
+ * system worker threads are suspended.
+ *
+ *
+ * @pre Global lock must be held.
+ *
+ * @param g The runtime global state.
+ */
+COMMON_PORTABLE
+void __cilkrts_leave_cilk(global_state_t *g);
+
+
+/**
+ * @brief cilk_fiber_proc that runs the main scheduler loop on a
+ * user worker.
+ *
+ * @pre fiber's owner field should be set to the correct __cilkrts_worker
+ * @pre fiber must be a user worker.
+ *
+ * @param fiber The scheduling fiber object.
+ */
+void scheduler_fiber_proc_for_user_worker(cilk_fiber *fiber);
+
+
+/**
+ * @brief Prints out Cilk runtime statistics.
+ *
+ * @param g The runtime global state.
+ *
+ * This method is useful only for debugging purposes. No guarantees
+ * are made as to the validity of this data. :)
+ */
+COMMON_PORTABLE
+void __cilkrts_dump_stats_to_stderr(global_state_t *g);
+
+#ifdef CILK_RECORD_REPLAY
+COMMON_PORTABLE
+char * walk_pedigree_nodes(char *p, const __cilkrts_pedigree *pnode);
+
+/**
+ * @brief Used by exception handling code to simulate the popping of
+ * an entry from the worker's deque.
+ *
+ * @param w Worker whose deque we want to check
+ *
+ * @return @c __cilkrts_stack_frame of parent call
+ * @return NULL if the deque is empty
+ */
+COMMON_PORTABLE
+__cilkrts_stack_frame *simulate_pop_tail(__cilkrts_worker *w);
+
+#endif
+
+__CILKRTS_END_EXTERN_C
+
+#endif // ! defined(INCLUDED_SCHEDULER_DOT_H)
diff --git a/libcilkrts/runtime/signal_node.c b/libcilkrts/runtime/signal_node.c
new file mode 100644
index 00000000000..92c404b482c
--- /dev/null
+++ b/libcilkrts/runtime/signal_node.c
@@ -0,0 +1,241 @@
+/* signal_node.c -*-C-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2011-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ **************************************************************************/
+
+#include "signal_node.h"
+#include <stdlib.h>
+
+/* Define cilk_semaphore_t for all of the respective systems. */
+#if defined __APPLE__
+# include <mach/mach_init.h>
+# include <mach/semaphore.h>
+# include <mach/task.h>
+ typedef semaphore_t cilk_semaphore_t;
+#elif defined _WIN32
+# include "windows-clean.h"
+ typedef HANDLE cilk_semaphore_t;
+#else // Linux/MIC
+# include <errno.h>
+# include <semaphore.h>
+# include <stdio.h>
+ typedef sem_t cilk_semaphore_t;
+#endif // Linux/MIC
+
+#include "bug.h"
+#include "cilk_malloc.h"
+#include "signal_node.h"
+
+/**
+ * Interface within the tree to notify workers to wait without consuming cycles
+ * to expend cycles trying to steal.
+ *
+ * cilk_semaphore_t is implemented as an auto-reset event on Windows, and
+ * as a semaphore_t on Linux and MacOS.
+ */
+struct signal_node_t
+{
+ /** 0 if the worker should wait, 1 if it should be running. */
+ volatile unsigned int run;
+
+ /** OS-specific semaphore on which the worker can wait. */
+ cilk_semaphore_t sem;
+};
+
+/******************************************************************************/
+/* Semaphore-abstraction functions */
+/******************************************************************************/
+
+/*
+ * All of these functions are simple wrappers for the system-specific semaphore
+ * functions. This keeps the rest of the code reasonably clean and readable.
+ */
+
+#if defined __APPLE__
+static void initialize_cilk_semaphore (cilk_semaphore_t *sem)
+{
+ kern_return_t kstatus
+ = semaphore_create(mach_task_self(), sem, SYNC_POLICY_FIFO, 0);
+ assert(kstatus == KERN_SUCCESS);
+}
+static void deinitialize_cilk_semaphore (cilk_semaphore_t *sem)
+{
+ kern_return_t kstatus = semaphore_destroy(mach_task_self(), *sem);
+ assert(kstatus == KERN_SUCCESS);
+}
+static void wait_on_cilk_semaphore (cilk_semaphore_t *sem)
+{
+ kern_return_t kstatus = semaphore_wait(*sem);
+ assert(kstatus == KERN_SUCCESS);
+}
+static void signal_cilk_semaphore (cilk_semaphore_t *sem)
+{
+ kern_return_t kstatus = semaphore_signal(*sem);
+ assert(kstatus == KERN_SUCCESS);
+}
+#elif defined _WIN32
+// Note: Windows only provides counting semaphores, and we don't really
+// care about the count. So this is implemented using an auto-reset
+// event which will automatically reset after the WaitForSingleObject
+// call
+static void initialize_cilk_semaphore (cilk_semaphore_t *sem)
+{
+ // Create an auto-reset event
+ *sem = CreateEvent(NULL, // Security attributes
+ FALSE, // Manual reset
+ FALSE, // Initial state (initially reset)
+ NULL); // Name (anonymous)
+ CILK_ASSERT (NULL != *sem);
+}
+
+static void deinitialize_cilk_semaphore (cilk_semaphore_t *sem)
+{
+ BOOL result = CloseHandle(*sem);
+ CILK_ASSERT (0 != result);
+}
+
+static void wait_on_cilk_semaphore (cilk_semaphore_t *sem)
+{
+ // WaitForSingleObject will reset the event
+ DWORD result = WaitForSingleObject (*sem, INFINITE);
+ CILK_ASSERT (WAIT_OBJECT_0 == result);
+}
+static void signal_cilk_semaphore (cilk_semaphore_t *sem)
+{
+ BOOL result = SetEvent (*sem);
+ CILK_ASSERT (0 != result);
+}
+#else // Linux/MIC
+static void initialize_cilk_semaphore (cilk_semaphore_t *sem)
+{
+ int status = sem_init(sem, 0, 0);
+ assert(0 == status);
+}
+static void deinitialize_cilk_semaphore (cilk_semaphore_t *sem)
+{
+ int status = sem_destroy(sem);
+ assert(0 == status);
+}
+static void wait_on_cilk_semaphore (cilk_semaphore_t *sem)
+{
+ int status;
+
+ do {
+ status = sem_wait(sem);
+ } while (status != 0 && errno == EINTR);
+
+ if (status != 0) {
+ perror("sem_wait");
+ abort();
+ }
+}
+static void signal_cilk_semaphore (cilk_semaphore_t *sem)
+{
+ sem_post(sem);
+}
+#endif // Linux/MIC
+
+/******************************************************************************/
+/* Runtime interface functions */
+/******************************************************************************/
+
+/*
+ * Return a newly malloc'd and initialized signal_node_t.
+ */
+COMMON_SYSDEP
+signal_node_t *signal_node_create(void)
+{
+ signal_node_t *node;
+
+ node = ( signal_node_t*)
+ __cilkrts_malloc(sizeof( signal_node_t));
+ node->run = 0;
+ initialize_cilk_semaphore(&node->sem);
+
+ return node;
+}
+
+/*
+ * Clean and free a signal_node_t.
+ */
+void signal_node_destroy(signal_node_t *node)
+{
+ CILK_ASSERT(node);
+ deinitialize_cilk_semaphore(&node->sem);
+ __cilkrts_free(node);
+}
+
+/*
+ * Return 1 if the node thinks the worker should go to sleep, 0 otherwise.
+ */
+unsigned int signal_node_should_wait(signal_node_t *node)
+{
+ CILK_ASSERT(node);
+ return !node->run;
+}
+
+/*
+ * Send a message to the node that the worker will eventually read.
+ */
+void signal_node_msg(signal_node_t *node, unsigned int msg)
+{
+ CILK_ASSERT(node);
+ switch (msg) {
+ case 0: // worker should go to sleep.
+ node->run = msg;
+ break;
+ case 1: // worker should be awake.
+ node->run = msg;
+ signal_cilk_semaphore(&node->sem);
+ break;
+ default: // error.
+ CILK_ASSERT(0 == "Bad signal_node_t message.");
+ }
+}
+
+/*
+ * The current worker will wait on the semaphore.
+ */
+void signal_node_wait(signal_node_t *node)
+{
+ CILK_ASSERT(node);
+ while (signal_node_should_wait(node)) {
+ // The loop is here to consume extra semaphore signals that might have
+ // accumulated. No point in passing on the accumulation.
+ wait_on_cilk_semaphore(&node->sem);
+ }
+}
diff --git a/libcilkrts/runtime/signal_node.h b/libcilkrts/runtime/signal_node.h
new file mode 100644
index 00000000000..0a1fe200201
--- /dev/null
+++ b/libcilkrts/runtime/signal_node.h
@@ -0,0 +1,109 @@
+/* signal_node.h -*-C++-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ **************************************************************************/
+
+/**
+ * @file signal_node.h
+ *
+ * @brief Signal nodes allow coordinated waking and sleeping of the runtime
+ * without hammering on a single location in memory.
+ *
+ * The workers are logically arranged in a binary tree and propagate messages
+ * leaf-ward. User workers notify the root about waking and sleeping, so only
+ * that one node need share a cache line with a user worker.
+ */
+
+#ifndef INCLUDED_SIGNAL_NODE_DOT_H
+#define INCLUDED_SIGNAL_NODE_DOT_H
+
+#include "rts-common.h"
+#include <cilk/common.h>
+
+__CILKRTS_BEGIN_EXTERN_C
+
+/** Opaque type. */
+typedef struct signal_node_t signal_node_t;
+
+/**
+ * Allocate and initialize a signal_node_t
+ *
+ * @return The initialized signal_node_t
+ */
+COMMON_SYSDEP
+signal_node_t *signal_node_create(void);
+
+/**
+ * Free any resources and deallocate a signal_node_t
+ *
+ * @param node The node to be deallocated.
+ */
+COMMON_SYSDEP void signal_node_destroy(signal_node_t *node);
+
+/**
+ * Test whether the node thinks the worker should go to sleep
+ *
+ * @param node The node to be tested.
+ *
+ * @return 1 If the worker should go to sleep
+ * @return 0 If the worker should not go to sleep
+ */
+COMMON_SYSDEP
+unsigned int signal_node_should_wait(signal_node_t *node);
+
+/**
+ * Specify whether the worker should go to sleep
+ *
+ * @param node The node to be set.
+ * @param msg The value to be set. Valid values are:
+ * - 0 - the worker should go to sleep
+ * - 1 - the worker should stay active
+ */
+COMMON_SYSDEP
+void signal_node_msg(signal_node_t *node, unsigned int msg);
+
+
+/**
+ * Wait for the node to be set
+ *
+ * @param node The node to wait on
+ */
+COMMON_SYSDEP
+void signal_node_wait(signal_node_t *node);
+
+__CILKRTS_END_EXTERN_C
+
+#endif // ! defined(INCLUDED_SIGNAL_NODE_DOT_H)
diff --git a/libcilkrts/runtime/spin_mutex.c b/libcilkrts/runtime/spin_mutex.c
new file mode 100644
index 00000000000..03908f26322
--- /dev/null
+++ b/libcilkrts/runtime/spin_mutex.c
@@ -0,0 +1,109 @@
+/* spin_mutex.c -*-C-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ **************************************************************************/
+
+#include "spin_mutex.h"
+#include "bug.h"
+#include "os.h"
+#include "stats.h"
+
+// TBD (11/30/12): We should be doing a conditional test-xchg instead
+// of an unconditional xchg operation for the spin mutex.
+
+/* m->lock == 1 means that mutex M is locked */
+#define TRY_ACQUIRE(m) (__cilkrts_xchg(&(m)->lock, 1) == 0)
+
+/* ICC 11.1+ understands release semantics and generates an
+ ordinary store with a software memory barrier. */
+#if __ICC >= 1110
+#define RELEASE(m) __sync_lock_release(&(m)->lock)
+#else
+#define RELEASE(m) __cilkrts_xchg(&(m)->lock, 0)
+#endif
+
+
+spin_mutex* spin_mutex_create()
+{
+ spin_mutex* mutex = (spin_mutex*)__cilkrts_malloc(sizeof(spin_mutex));
+ spin_mutex_init(mutex);
+ return mutex;
+}
+
+void spin_mutex_init(struct spin_mutex *m)
+{
+ // Use a simple assignment so Inspector doesn't bug us about the
+ // interlocked exchange doing a read of an uninitialized variable.
+ // By definition there can't be a race when we're initializing the
+ // lock...
+ m->lock = 0;
+}
+
+void spin_mutex_lock(struct spin_mutex *m)
+{
+ int count;
+ const int maxspin = 1000; /* SWAG */
+ if (!TRY_ACQUIRE(m)) {
+ count = 0;
+ do {
+ do {
+ __cilkrts_short_pause();
+ if (++count >= maxspin) {
+ /* let the OS reschedule every once in a while */
+ __cilkrts_yield();
+ count = 0;
+ }
+ } while (m->lock != 0);
+ } while (!TRY_ACQUIRE(m));
+ }
+}
+
+int spin_mutex_trylock(struct spin_mutex *m)
+{
+ return TRY_ACQUIRE(m);
+}
+
+void spin_mutex_unlock(struct spin_mutex *m)
+{
+ RELEASE(m);
+}
+
+void spin_mutex_destroy(struct spin_mutex *m)
+{
+ __cilkrts_free(m);
+}
+
+/* End spin_mutex.c */
diff --git a/libcilkrts/runtime/spin_mutex.h b/libcilkrts/runtime/spin_mutex.h
new file mode 100644
index 00000000000..b0045ab9313
--- /dev/null
+++ b/libcilkrts/runtime/spin_mutex.h
@@ -0,0 +1,129 @@
+/* spin_mutex.h -*-C++-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ **************************************************************************/
+
+/**
+ * @file spin_mutex.h
+ *
+ * @brief Support for Cilk runtime mutexes.
+ *
+ * Cilk runtime mutexes are implemented as simple spin loops.
+ *
+ * This file is similar to a worker_mutex, except it does not have an
+ * owner field.
+ *
+ * TBD: This class, worker_mutex, and os_mutex overlap quite a bit in
+ * functionality. Can we unify these mutexes somehow?
+ */
+#ifndef INCLUDED_SPIN_MUTEX_DOT_H
+#define INCLUDED_SPIN_MUTEX_DOT_H
+
+#include <cilk/common.h>
+#include "rts-common.h"
+#include "cilk_malloc.h"
+
+__CILKRTS_BEGIN_EXTERN_C
+
+/**
+ * Mutexes are treated as an abstract data type within the Cilk
+ * runtime system. They are implemented as simple spin loops.
+ */
+typedef struct spin_mutex {
+ /** Mutex spin loop variable. 0 if unowned, 1 if owned. */
+ volatile int lock;
+
+ /** Padding so the mutex takes up a cache line. */
+ char pad[64/sizeof(int) - 1];
+} spin_mutex;
+
+
+/**
+ * @brief Create a new Cilk spin_mutex.
+ *
+ * @return Returns an initialized spin mutex.
+ */
+COMMON_PORTABLE
+spin_mutex* spin_mutex_create();
+
+/**
+ * @brief Initialize a Cilk spin_mutex.
+ *
+ * @param m Spin_Mutex to be initialized.
+ */
+COMMON_PORTABLE
+void spin_mutex_init(spin_mutex *m);
+
+/**
+ * @brief Acquire a Cilk spin_mutex.
+ *
+ * If statistics are being gathered, the time spent
+ * acquiring the spin_mutex will be attributed to the specified worker.
+ *
+ * @param m Spin_Mutex to be initialized.
+ */
+COMMON_PORTABLE
+void spin_mutex_lock(struct spin_mutex *m);
+/**
+ * @brief Attempt to lock a Cilk spin_mutex and fail if it isn't available.
+ *
+ * @param m Spin_Mutex to be acquired.
+ *
+ * @return 1 if the spin_mutex was acquired.
+ * @return 0 if the spin_mutex was not acquired.
+ */
+COMMON_PORTABLE
+int spin_mutex_trylock(struct spin_mutex *m);
+
+/**
+ * @brief Release a Cilk spin_mutex.
+ *
+ * @param m Spin_Mutex to be released.
+ */
+COMMON_PORTABLE
+void spin_mutex_unlock(struct spin_mutex *m);
+
+/**
+ * @brief Deallocate a Cilk spin_mutex. Currently does nothing.
+ *
+ * @param m Spin_Mutex to be deallocated.
+ */
+COMMON_PORTABLE
+void spin_mutex_destroy(struct spin_mutex *m);
+
+__CILKRTS_END_EXTERN_C
+
+#endif // ! defined(INCLUDED_SPIN_MUTEX_DOT_H)
diff --git a/libcilkrts/runtime/stats.c b/libcilkrts/runtime/stats.c
new file mode 100644
index 00000000000..3a420745039
--- /dev/null
+++ b/libcilkrts/runtime/stats.c
@@ -0,0 +1,172 @@
+/* stats.c -*-C-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ **************************************************************************/
+
+#include "stats.h"
+#include "bug.h"
+#include "os.h"
+#include "local_state.h"
+
+#include <stdio.h>
+
+#define INVALID_START (0ULL - 1ULL)
+
+#ifdef CILK_PROFILE
+/* MSVC does not support designated initializers, grrrr... */
+static const char *names[] = {
+ /*[INTERVAL_IN_SCHEDULER]*/ "in scheduler",
+ /*[INTERVAL_WORKING]*/ " of which: working",
+ /*[INTERVAL_IN_RUNTIME]*/ " of which: in runtime",
+ /*[INTERVAL_STEALING]*/ " of which: stealing",
+ /*[INTERVAL_STEAL_SUCCESS]*/ "steal success: detach",
+ /*[INTERVAL_STEAL_FAIL_EMPTYQ]*/ "steal fail: empty queue",
+ /*[INTERVAL_STEAL_FAIL_LOCK]*/ "steal fail: victim locked",
+ /*[INTERVAL_STEAL_FAIL_USER_WORKER]*/ "steal fail: user worker",
+ /*[INTERVAL_STEAL_FAIL_DEKKER]*/ "steal fail: dekker",
+ /*[INTERVAL_SYNC_CHECK]*/ "sync check",
+ /*[INTERVAL_THE_EXCEPTION_CHECK]*/ "THE exception check",
+ /*[INTERVAL_THE_EXCEPTION_CHECK_USELESS]*/ " of which: useless",
+ /*[INTERVAL_RETURNING]*/ "returning",
+ /*[INTERVAL_FINALIZE_CHILD]*/ "finalize child",
+ /*[INTERVAL_PROVABLY_GOOD_STEAL]*/ "provably good steal",
+ /*[INTERVAL_UNCONDITIONAL_STEAL]*/ "unconditional steal",
+ /*[INTERVAL_ALLOC_FULL_FRAME]*/ "alloc full frame",
+ /*[INTERVAL_FRAME_ALLOC_LARGE]*/ "large frame alloc",
+ /*[INTERVAL_FRAME_ALLOC]*/ "small frame alloc",
+ /*[INTERVAL_FRAME_ALLOC_GLOBAL]*/ " of which: to global pool",
+ /*[INTERVAL_FRAME_FREE_LARGE]*/ "large frame free",
+ /*[INTERVAL_FRAME_FREE]*/ "small frame free",
+ /*[INTERVAL_FRAME_FREE_GLOBAL]*/ " of which: to global pool",
+ /*[INTERVAL_MUTEX_LOCK]*/ "mutex lock",
+ /*[INTERVAL_MUTEX_LOCK_SPINNING]*/ " spinning",
+ /*[INTERVAL_MUTEX_LOCK_YIELDING]*/ " yielding",
+ /*[INTERVAL_MUTEX_TRYLOCK]*/ "mutex trylock",
+ /*[INTERVAL_FIBER_ALLOCATE]*/ "fiber_allocate",
+ /*[INTERVAL_FIBER_DEALLOCATE]*/ "fiber_deallocate",
+ /*[INTERVAL_FIBER_ALLOCATE_FROM_THREAD]*/ "fiber_allocate_from_thread",
+ /*[INTERVAL_FIBER_DEALLOCATE_FROM_THREAD]*/ "fiber_deallocate (thread)",
+ /*[INTERVAL_SUSPEND_RESUME_OTHER]*/ "fiber suspend self + resume",
+ /*[INTERVAL_DEALLOCATE_RESUME_OTHER]*/ "fiber deallocate self + resume",
+};
+#endif
+
+void __cilkrts_init_stats(statistics *s)
+{
+ int i;
+ for (i = 0; i < INTERVAL_N; ++i) {
+ s->start[i] = INVALID_START;
+ s->accum[i] = 0;
+ s->count[i] = 0;
+ }
+
+ s->stack_hwm = 0;
+}
+
+#ifdef CILK_PROFILE
+void __cilkrts_accum_stats(statistics *to, statistics *from)
+{
+ int i;
+
+ for (i = 0; i < INTERVAL_N; ++i) {
+ to->accum[i] += from->accum[i];
+ to->count[i] += from->count[i];
+ from->accum[i] = 0;
+ from->count[i] = 0;
+ }
+
+ if (from->stack_hwm > to->stack_hwm)
+ to->stack_hwm = from->stack_hwm;
+ from->stack_hwm = 0;
+}
+
+void __cilkrts_note_interval(__cilkrts_worker *w, enum interval i)
+{
+ if (w) {
+ statistics *s = w->l->stats;
+ CILK_ASSERT(s->start[i] == INVALID_START);
+ s->count[i]++;
+ }
+}
+
+void __cilkrts_start_interval(__cilkrts_worker *w, enum interval i)
+{
+ if (w) {
+ statistics *s = w->l->stats;
+ CILK_ASSERT(s->start[i] == INVALID_START);
+ s->start[i] = __cilkrts_getticks();
+ s->count[i]++;
+ }
+}
+
+void __cilkrts_stop_interval(__cilkrts_worker *w, enum interval i)
+{
+ if (w) {
+ statistics *s = w->l->stats;
+ CILK_ASSERT(s->start[i] != INVALID_START);
+ s->accum[i] += __cilkrts_getticks() - s->start[i];
+ s->start[i] = INVALID_START;
+ }
+}
+
+void dump_stats_to_file(FILE *stat_file, statistics *s)
+{
+ int i;
+ fprintf(stat_file, "\nCILK PLUS RUNTIME SYSTEM STATISTICS:\n\n");
+
+ fprintf(stat_file,
+ " %-32s: %15s %10s %12s %10s\n",
+ "event",
+ "count",
+ "ticks",
+ "ticks/count",
+ "%total"
+ );
+ for (i = 0; i < INTERVAL_N; ++i) {
+ fprintf(stat_file, " %-32s: %15llu", names[i], s->count[i]);
+ if (s->accum[i]) {
+ fprintf(stat_file, " %10.3g %12.3g %10.2f",
+ (double)s->accum[i],
+ (double)s->accum[i] / (double)s->count[i],
+ 100.0 * (double)s->accum[i] /
+ (double)s->accum[INTERVAL_IN_SCHEDULER]);
+ }
+ fprintf(stat_file, "\n");
+ }
+}
+#endif // CILK_PROFILE
+
+/* End stats.c */
diff --git a/libcilkrts/runtime/stats.h b/libcilkrts/runtime/stats.h
new file mode 100644
index 00000000000..aaa99274765
--- /dev/null
+++ b/libcilkrts/runtime/stats.h
@@ -0,0 +1,208 @@
+/* stats.h -*-C++-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ **************************************************************************/
+
+/**
+ * @file stats.h
+ *
+ * @brief Support for gathering and reporting statistics on Cilk applications.
+ *
+ * Note that stats are normally NOT compiled in because it increases the
+ * overhead of stealing. To compile in profiling support, define CILK_PROFILE.
+ */
+
+#ifndef INCLUDED_STATS_DOT_H
+#define INCLUDED_STATS_DOT_H
+
+/* #define CILK_PROFILE 1 */
+// @note The CILK_PROFILE flag and intervals is known to be broken
+// in at least programs with Windows exceptions.
+// Enable this flag at your own peril. :)
+
+#include <cilk/common.h>
+#include "rts-common.h"
+#include "internal/abi.h"
+
+#ifdef CILK_PROFILE
+#include <stdio.h> // Define FILE *
+#endif
+
+__CILKRTS_BEGIN_EXTERN_C
+
+/** @brief Events that we measure. */
+enum interval
+{
+ INTERVAL_IN_SCHEDULER, ///< Time threads spend "bound" to Cilk
+ INTERVAL_WORKING, ///< Time spent working
+ INTERVAL_IN_RUNTIME, ///< Time spent executing runtime scheduling loop
+ INTERVAL_STEALING, ///< Time spent stealing work
+ INTERVAL_STEAL_SUCCESS, ///< Time to do a successful steal
+ INTERVAL_STEAL_FAIL_EMPTYQ, ///< Count of steal failures due to lack of stealable work
+ INTERVAL_STEAL_FAIL_LOCK, ///< Count of steal failures due to failure to lock worker
+ INTERVAL_STEAL_FAIL_USER_WORKER, ///< Count of steal failures by user workers which attempt to steal from another team
+ INTERVAL_STEAL_FAIL_DEKKER, ///< Count of steal failures due to Dekker protocol failure
+ INTERVAL_SYNC_CHECK, ///< Time spent processing syncs
+ INTERVAL_THE_EXCEPTION_CHECK, ///< Time spent performing THE exception checks
+ INTERVAL_THE_EXCEPTION_CHECK_USELESS, ///< Count of useless THE exception checks
+ INTERVAL_RETURNING, ///< Time spent returning from calls
+ INTERVAL_FINALIZE_CHILD, ///< Time spent in finalize_child
+ INTERVAL_PROVABLY_GOOD_STEAL, ///< Time spent in provably_good_steal
+ INTERVAL_UNCONDITIONAL_STEAL, ///< Time spent in unconditional_steal
+ INTERVAL_ALLOC_FULL_FRAME, ///< Time spent in __cilkrts_make_full_frame
+ INTERVAL_FRAME_ALLOC_LARGE, ///< Count of calls to __cilkrts_frame_malloc for buffers bigger than FRAME_MALLOC_MAX_SIZE or with a NULL worker
+ INTERVAL_FRAME_ALLOC, ///< Time spent allocating memory from worker buckets
+ INTERVAL_FRAME_ALLOC_GLOBAL, ///< Time spent calling memory allocator when buckets are empty
+ INTERVAL_FRAME_FREE_LARGE, ///< Count of calls to __cilkrts_frame_malloc for buffers bigger than FRAME_MALLOC_MAX_SIZE or with a NULL worker
+ INTERVAL_FRAME_FREE, ///< Time spent freeing memory to worker buckets
+ INTERVAL_FRAME_FREE_GLOBAL, ///< Time spent calling memory deallocator when buckets are full
+ INTERVAL_MUTEX_LOCK, ///< Count of calls to __cilkrts_mutex_lock for a worker
+ INTERVAL_MUTEX_LOCK_SPINNING, ///< Time spent spinning in __cilkrts_mutex_lock for a worker
+ INTERVAL_MUTEX_LOCK_YIELDING, ///< Time spent yielding in __cilkrts_mutex_lock for a worker
+ INTERVAL_MUTEX_TRYLOCK, ///< Count of calls to __cilkrts_mutex_trylock
+ INTERVAL_FIBER_ALLOCATE, ///< Time spent calling cilk_fiber_allocate
+ INTERVAL_FIBER_DEALLOCATE, ///< Time spent calling cilk_fiber_deallocate (not from thread)
+ INTERVAL_FIBER_ALLOCATE_FROM_THREAD, ///< Time spent calling cilk_fiber_allocate_from_thread
+ INTERVAL_FIBER_DEALLOCATE_FROM_THREAD, ///< Time spent calling cilk_fiber_deallocate (from thread)
+ INTERVAL_SUSPEND_RESUME_OTHER, ///< Count of fiber suspend_self_and_resume_other
+ INTERVAL_DEALLOCATE_RESUME_OTHER, ///< Count of fiber deallocate_self_and_resume_other
+ INTERVAL_N ///< Number of intervals, must be last
+};
+
+/**
+ * @brief Struct that collects of all runtime statistics.
+ *
+ * There is an instance of this structure in each worker's
+ * local_state, as well as one in the @c global_state_t which will be
+ * used to accumulate the per-worker stats.
+ */
+typedef struct statistics
+{
+ /** Number of times each interval is entered */
+ unsigned long long count[INTERVAL_N];
+
+ /**
+ * Time when the system entered each interval, in system-dependent
+ * "ticks"
+ */
+ unsigned long long start[INTERVAL_N];
+
+ /** Total time spent in each interval, in system-dependent "ticks" */
+ unsigned long long accum[INTERVAL_N];
+
+ /**
+ * Largest global number of stacks seen by this worker.
+ * The true maximum at end of execution is the max of the
+ * worker maxima.
+ */
+ long stack_hwm;
+} statistics;
+
+/**
+ * Initializes a statistics structure
+ *
+ * @param s The statistics structure to be initialized.
+ */
+COMMON_PORTABLE void __cilkrts_init_stats(statistics *s);
+
+/**
+ * @brief Sums statistics from worker to the global struct
+ *
+ * @param to The statistics structure that will accumulate the information.
+ * This structure is usually @c g->stats.
+ * @param from The statistics structure that will be accumulated.
+ * This structure is usually statistics kept per worker.
+ */
+COMMON_PORTABLE
+void __cilkrts_accum_stats(statistics *to, statistics *from);
+
+/**
+ * @brief Mark the start of an interval by saving the current tick count.
+ *
+ * @pre Start time == INVALID_START
+ *
+ * @param w The worker we're accumulating stats for.
+ * @param i The interval we're accumulating stats for.
+ */
+COMMON_PORTABLE
+void __cilkrts_start_interval(__cilkrts_worker *w, enum interval i);
+
+/**
+ * @brief Mark the end of an interval by adding the ticks since the
+ * start to the accumulated time.
+ *
+ * @pre Start time != INVALID_START
+ *
+ * @param w The worker we're accumulating stats for.
+ * @param i The interval we're accumulating stats for.
+ */
+COMMON_PORTABLE
+void __cilkrts_stop_interval(__cilkrts_worker *w, enum interval i);
+
+/**
+ * @brief Start and stop interval I, charging zero time against it
+ *
+ * Precondition:
+ * - Start time == INVALID_START
+ *
+ * @param w The worker we're accumulating stats for.
+ * @param i The interval we're accumulating stats for.
+ */
+COMMON_PORTABLE
+void __cilkrts_note_interval(__cilkrts_worker *w, enum interval i);
+
+#ifdef CILK_PROFILE
+COMMON_PORTABLE
+void dump_stats_to_file(FILE *stat_file, statistics *s);
+#endif
+
+
+#ifdef CILK_PROFILE
+# define START_INTERVAL(w, i) __cilkrts_start_interval(w, i);
+# define STOP_INTERVAL(w, i) __cilkrts_stop_interval(w, i);
+# define NOTE_INTERVAL(w, i) __cilkrts_note_interval(w, i);
+#else
+/** Start an interval. No effect unless CILK_PROFILE is defined. */
+# define START_INTERVAL(w, i)
+/** End an interval. No effect unless CILK_PROFILE is defined. */
+# define STOP_INTERVAL(w, i)
+/** Increment a counter. No effect unless CILK_PROFILE is defined. */
+# define NOTE_INTERVAL(w, i)
+#endif
+
+__CILKRTS_END_EXTERN_C
+
+#endif // ! defined(INCLUDED_STATS_DOT_H)
diff --git a/libcilkrts/runtime/symbol_test.c b/libcilkrts/runtime/symbol_test.c
new file mode 100644
index 00000000000..1113ecd44cd
--- /dev/null
+++ b/libcilkrts/runtime/symbol_test.c
@@ -0,0 +1,62 @@
+/* symbol_test.c -*-C-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ **************************************************************************/
+
+/* simple program to verify that there are no undefined symbols in the runtime.
+ * If the runtime uses any symbols that are not defined, compiling this program
+ * will cause a linker error.
+ */
+
+extern void* __cilkrts_global_state;
+void *volatile p;
+
+void foo () { }
+int main ()
+{
+ int i;
+ long long j;
+
+ _Cilk_spawn foo();
+ _Cilk_for (i = 0; i < 2; ++i)
+ foo();
+ _Cilk_for (j = 0; j < 2; ++j)
+ foo();
+ p = __cilkrts_global_state;
+ return 0;
+}
+
+/* End symbol_test.c */
diff --git a/libcilkrts/runtime/sysdep-unix.c b/libcilkrts/runtime/sysdep-unix.c
new file mode 100644
index 00000000000..1f82b6288a1
--- /dev/null
+++ b/libcilkrts/runtime/sysdep-unix.c
@@ -0,0 +1,807 @@
+/*
+ * sysdep-unix.c
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2010-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ **************************************************************************
+ */
+
+#ifdef __linux__
+ // define _GNU_SOURCE before *any* #include.
+ // Even <stdint.h> will break later #includes if this macro is not
+ // already defined when it is #included.
+# define _GNU_SOURCE
+#endif
+
+#include "sysdep.h"
+#include "os.h"
+#include "bug.h"
+#include "local_state.h"
+#include "signal_node.h"
+#include "full_frame.h"
+#include "jmpbuf.h"
+#include "cilk_malloc.h"
+#include "reducer_impl.h"
+#include "metacall_impl.h"
+
+
+// On x86 processors (but not MIC processors), the compiler generated code to
+// save the FP state (rounding mode and the like) before calling setjmp. We
+// will need to restore that state when we resume.
+#ifndef __MIC__
+# if defined(__i386__) || defined(__x86_64)
+# define RESTORE_X86_FP_STATE
+# endif // defined(__i386__) || defined(__x86_64)
+#endif // __MIC__
+
+// contains notification macros for VTune.
+#include "cilk-ittnotify.h"
+
+#include <stddef.h>
+
+#ifdef __CYGWIN__
+// On Cygwin, string.h doesnt declare strcasecmp if __STRICT_ANSI__ is defined
+# undef __STRICT_ANSI__
+#endif
+
+#include <string.h>
+#include <pthread.h>
+#include <unistd.h>
+
+#if defined HAVE_ALLOCA_H
+# include <alloca.h>
+#elif defined __GNUC__
+# define alloca __builtin_alloca
+#elif defined _AIX
+# define alloca __alloca
+#else
+# include <stddef.h>
+# ifdef __cplusplus
+extern "C"
+# endif
+void *alloca (size_t);
+#endif
+
+#ifdef __APPLE__
+//# include <scheduler.h> // Angle brackets include Apple's scheduler.h, not ours.
+#endif
+
+#ifdef __linux__
+# include <sys/resource.h>
+# include <sys/sysinfo.h>
+#endif
+
+#ifdef __FreeBSD__
+# include <sys/resource.h>
+// BSD does not define MAP_ANONYMOUS, but *does* define MAP_ANON. Aren't standards great!
+# define MAP_ANONYMOUS MAP_ANON
+#endif
+
+#ifdef __VXWORKS__
+# include <vxWorks.h>
+# include <vxCpuLib.h>
+#endif
+
+struct global_sysdep_state
+{
+ pthread_t *threads; ///< Array of pthreads for system workers
+ size_t pthread_t_size; ///< for cilk_db
+};
+
+static void internal_enforce_global_visibility();
+
+
+COMMON_SYSDEP
+void __cilkrts_init_worker_sysdep(struct __cilkrts_worker *w)
+{
+ ITT_SYNC_CREATE(w, "Scheduler");
+}
+
+COMMON_SYSDEP
+void __cilkrts_destroy_worker_sysdep(struct __cilkrts_worker *w)
+{
+}
+
+COMMON_SYSDEP
+void __cilkrts_init_global_sysdep(global_state_t *g)
+{
+ internal_enforce_global_visibility();
+
+ __cilkrts_init_tls_variables();
+
+ CILK_ASSERT(g->total_workers >= g->P - 1);
+ g->sysdep = __cilkrts_malloc(sizeof (struct global_sysdep_state));
+ CILK_ASSERT(g->sysdep);
+ g->sysdep->pthread_t_size = sizeof (pthread_t);
+
+ // TBD: Should this value be g->total_workers, or g->P?
+ // Need to check what we are using this field for.
+ g->sysdep->threads = __cilkrts_malloc(sizeof(pthread_t) * g->total_workers);
+ CILK_ASSERT(g->sysdep->threads);
+
+ return;
+}
+
+COMMON_SYSDEP
+void __cilkrts_destroy_global_sysdep(global_state_t *g)
+{
+ if (g->sysdep->threads)
+ __cilkrts_free(g->sysdep->threads);
+ __cilkrts_free(g->sysdep);
+}
+
+/*************************************************************
+ Creation of worker threads:
+*************************************************************/
+
+static void internal_run_scheduler_with_exceptions(__cilkrts_worker *w)
+{
+ /* We assume the stack grows down. */
+ char var;
+ __cilkrts_cilkscreen_establish_c_stack(&var - 1000000, &var);
+
+ __cilkrts_run_scheduler_with_exceptions(w);
+}
+
+
+
+/*
+ * scheduler_thread_proc_for_system_worker
+ *
+ * Thread start function called when we start a new worker.
+ *
+ */
+NON_COMMON void* scheduler_thread_proc_for_system_worker(void *arg)
+{
+ /*int status;*/
+ __cilkrts_worker *w = (__cilkrts_worker *)arg;
+
+#ifdef __INTEL_COMPILER
+#ifdef USE_ITTNOTIFY
+ // Name the threads for Advisor. They don't want a worker number.
+ __itt_thread_set_name("Cilk Worker");
+#endif // defined USE_ITTNOTIFY
+#endif // defined __INTEL_COMPILER
+
+ /* Worker startup is serialized
+ status = pthread_mutex_lock(&__cilkrts_global_mutex);
+ CILK_ASSERT(status == 0);*/
+ CILK_ASSERT(w->l->type == WORKER_SYSTEM);
+ /*status = pthread_mutex_unlock(&__cilkrts_global_mutex);
+ CILK_ASSERT(status == 0);*/
+
+ __cilkrts_set_tls_worker(w);
+
+ // Create a cilk fiber for this worker on this thread.
+ START_INTERVAL(w, INTERVAL_FIBER_ALLOCATE_FROM_THREAD) {
+ w->l->scheduling_fiber = cilk_fiber_allocate_from_thread();
+ cilk_fiber_set_owner(w->l->scheduling_fiber, w);
+ } STOP_INTERVAL(w, INTERVAL_FIBER_ALLOCATE_FROM_THREAD);
+
+ internal_run_scheduler_with_exceptions(w);
+
+ START_INTERVAL(w, INTERVAL_FIBER_DEALLOCATE_FROM_THREAD) {
+ // Deallocate the scheduling fiber. This operation reverses the
+ // effect cilk_fiber_allocate_from_thread() and must be done in this
+ // thread before it exits.
+ int ref_count = cilk_fiber_deallocate_from_thread(w->l->scheduling_fiber);
+ // Scheduling fibers should never have extra references to them.
+ // We only get extra references into fibers because of Windows
+ // exceptions.
+ CILK_ASSERT(0 == ref_count);
+ w->l->scheduling_fiber = NULL;
+ } STOP_INTERVAL(w, INTERVAL_FIBER_DEALLOCATE_FROM_THREAD);
+
+ return 0;
+}
+
+
+/*
+ * __cilkrts_user_worker_scheduling_stub
+ *
+ * Routine for the scheduling fiber created for an imported user
+ * worker thread. This method is analogous to
+ * scheduler_thread_proc_for_system_worker.
+ *
+ */
+void __cilkrts_user_worker_scheduling_stub(cilk_fiber* fiber, void* null_arg)
+{
+ __cilkrts_worker *w = __cilkrts_get_tls_worker();
+
+ // Sanity check.
+ CILK_ASSERT(WORKER_USER == w->l->type);
+
+ // Enter the scheduling loop on the user worker.
+ // This function will never return.
+ __cilkrts_run_scheduler_with_exceptions(w);
+
+ // A WORKER_USER, at some point, will resume on the original stack and leave
+ // Cilk. Under no circumstances do we ever exit off of the bottom of this
+ // stack.
+ CILK_ASSERT(0);
+}
+
+/**
+ * We are exporting a function with this name to Inspector?
+ * What a confusing name...
+ *
+ * This function is exported so Piersol's stack trace displays
+ * reasonable information.
+ */
+void* __cilkrts_worker_stub(void* arg)
+{
+ return scheduler_thread_proc_for_system_worker(arg);
+}
+
+
+
+// /* Return the lesser of the argument and the operating system
+// limit on the number of workers (threads) that may or ought
+// to be created. */
+// int sysdep_thread_limit(int n, int physical_cpus)
+// {
+// /* On Linux thread creation fails somewhere short of the
+// number of available processes. */
+// struct rlimit lim;
+
+// if (n > 256 + 2 * physical_cpus)
+// n = 256 + 2 * physical_cpus;
+
+// if (getrlimit(RLIMIT_NPROC, &lim) == 0 && lim.rlim_cur != RLIM_INFINITY)
+// {
+// /* If the limit reads 0 or absurdly small, ignore it. */
+// unsigned int maxproc = (lim.rlim_cur * 3 + 3) / 4;
+// if (maxproc > 8 + 2 * physical_cpus && maxproc < n)
+// n = maxproc;
+// }
+// return n;
+// }
+
+
+
+static void write_version_file (global_state_t *, int);
+
+/* Create n worker threads from base..top-1
+ */
+static void create_threads(global_state_t *g, int base, int top)
+{
+ // TBD(11/30/12): We want to insert code providing the option of
+ // pinning system workers to cores.
+ for (int i = base; i < top; i++) {
+ int status = pthread_create(&g->sysdep->threads[i],
+ NULL,
+ scheduler_thread_proc_for_system_worker,
+ g->workers[i]);
+ if (status != 0)
+ __cilkrts_bug("Cilk runtime error: thread creation (%d) failed: %d\n", i, status);
+ }
+}
+
+#if PARALLEL_THREAD_CREATE
+static int volatile threads_created = 0;
+
+// Create approximately half of the worker threads, and then become a worker
+// ourselves.
+static void * create_threads_and_work (void * arg)
+{
+ global_state_t *g = ((__cilkrts_worker *)arg)->g;
+
+ create_threads(g, g->P/2, g->P-1);
+ // Let the initial thread know that we're done.
+ threads_created = 1;
+
+ // Ideally this turns into a tail call that wipes out this stack frame.
+ return scheduler_thread_proc_for_system_worker(arg);
+}
+#endif
+void __cilkrts_start_workers(global_state_t *g, int n)
+{
+ g->workers_running = 1;
+ g->work_done = 0;
+
+ if (!g->sysdep->threads)
+ return;
+
+ // Do we actually have any threads to create?
+ if (n > 0)
+ {
+#if PARALLEL_THREAD_CREATE
+ int status;
+ // We create (a rounded up) half of the threads, thread one creates the rest
+ int half_threads = (n+1)/2;
+
+ // Create the first thread passing a different thread function, so that it creates threads itself
+ status = pthread_create(&g->sysdep->threads[0], NULL, create_threads_and_work, g->workers[0]);
+
+ if (status != 0)
+ __cilkrts_bug("Cilk runtime error: thread creation (0) failed: %d\n", status);
+
+ // Then the rest of the ones we have to create
+ create_threads(g, 1, half_threads);
+
+ // Now wait for the first created thread to tell us it's created all of its threads.
+ // We could maybe drop this a bit lower and overlap with write_version_file.
+ while (!threads_created)
+ __cilkrts_yield();
+#else
+ // Simply create all the threads linearly here.
+ create_threads(g, 0, n);
+#endif
+ }
+ // write the version information to a file if the environment is configured
+ // for it (the function makes the check).
+ write_version_file(g, n);
+
+
+ return;
+}
+
+void __cilkrts_stop_workers(global_state_t *g)
+{
+ int i;
+
+ // Tell the workers to give up
+
+ g->work_done = 1;
+
+ if (g->workers_running == 0)
+ return;
+
+ if (!g->sysdep->threads)
+ return;
+
+ /* Make them all runnable. */
+ if (g->P > 1) {
+ CILK_ASSERT(g->workers[0]->l->signal_node);
+ signal_node_msg(g->workers[0]->l->signal_node, 1);
+ }
+
+ for (i = 0; i < g->P - 1; ++i) {
+ int sc_status;
+ void *th_status;
+
+ sc_status = pthread_join(g->sysdep->threads[i], &th_status);
+ if (sc_status != 0)
+ __cilkrts_bug("Cilk runtime error: thread join (%d) failed: %d\n", i, sc_status);
+ }
+
+ g->workers_running = 0;
+
+
+ return;
+}
+
+
+/*
+ * @brief Returns the stack address for resuming execution of sf.
+ *
+ * This method takes in the top of the stack to use, and then returns
+ * a properly aligned address for resuming execution of sf.
+ *
+ * @param sf - The stack frame we want to resume executing.
+ * @param stack_base - The top of the stack we want to execute sf on.
+ *
+ */
+static char* get_sp_for_executing_sf(char* stack_base,
+ full_frame *ff,
+ __cilkrts_stack_frame *sf)
+{
+// The original calculation that had been done to correct the stack
+// pointer when resuming execution.
+//
+// But this code was never getting called in the eng branch anyway...
+//
+// TBD(11/30/12): This logic needs to be revisited to make sure that
+// we are doing the proper calculation in reserving space for outgoing
+// arguments on all platforms and architectures.
+#if 0
+ /* Preserve outgoing argument space and stack alignment on steal.
+ Outgoing argument space is bounded by the difference between
+ stack and frame pointers. Some user code is known to rely on
+ 16 byte alignment. Maintain 32 byte alignment for future
+ compatibility. */
+#define SMASK 31 /* 32 byte alignment */
+ if (sf) {
+ char *fp = FP(sf), *sp = SP(sf);
+ int fp_align = (int)(size_t)fp & SMASK;
+ ptrdiff_t space = fp - sp;
+
+ fprintf(stderr, "Here: fp = %p, sp = %p\n", fp, sp);
+ char *top_aligned = (char *)((((size_t)stack_base - SMASK) & ~(size_t)SMASK) | fp_align);
+ /* Don't allocate an unreasonable amount of stack space. */
+
+ fprintf(stderr, "Here: stack_base = %p, top_aligned=%p, space=%ld\n",
+ stack_base, top_aligned, space);
+ if (space < 32)
+ space = 32 + (space & SMASK);
+ else if (space > 40 * 1024)
+ space = 40 * 1024 + (space & SMASK);
+
+ return top_aligned - space;
+ }
+#endif
+
+#define PERFORM_FRAME_SIZE_CALCULATION 0
+
+ char* new_stack_base = stack_base - 256;
+
+#if PERFORM_FRAME_SIZE_CALCULATION
+ // If there is a frame size saved, then use that as the
+ // correction instead of 256.
+ if (ff->frame_size > 0) {
+ if (ff->frame_size < 40*1024) {
+ new_stack_base = stack_base - ff->frame_size;
+ }
+ else {
+ // If for some reason, our frame size calculation is giving us
+ // a number which is bigger than about 10 pages, then
+ // there is likely something wrong here? Don't allocate
+ // an unreasonable amount of space.
+ new_stack_base = stack_base - 40*1024;
+ }
+ }
+#endif
+
+ // Whatever correction we choose, align the final stack top.
+ // This alignment seems to be necessary in particular on 32-bit
+ // Linux, and possibly Mac. (Is 32-byte alignment is sufficient?)
+ /* 256-byte alignment. Why not? */
+ const uintptr_t align_mask = ~(256 -1);
+ new_stack_base = (char*)((size_t)new_stack_base & align_mask);
+ return new_stack_base;
+}
+
+char* sysdep_reset_jump_buffers_for_resume(cilk_fiber* fiber,
+ full_frame *ff,
+ __cilkrts_stack_frame *sf)
+{
+#if FIBER_DEBUG >= 4
+ fprintf(stderr, "ThreadId=%p (fiber_proc_to_resume), Fiber %p. sf = %p. ff=%p, ff->sync_sp=%p\n",
+ cilkos_get_current_thread_id(),
+ fiber,
+ sf,
+ ff, ff->sync_sp);
+#endif
+
+ CILK_ASSERT(fiber);
+ void* sp = (void*)get_sp_for_executing_sf(cilk_fiber_get_stack_base(fiber), ff, sf);
+ SP(sf) = sp;
+
+ /* Debugging: make sure stack is accessible. */
+ ((volatile char *)sp)[-1];
+
+ // Adjust the saved_sp to account for the SP we're about to run. This will
+ // allow us to track fluctations in the stack
+#if FIBER_DEBUG >= 4
+ fprintf(stderr, "ThreadId=%p, about to take stack ff=%p, sp=%p, sync_sp=%p\n",
+ cilkos_get_current_thread_id(),
+ ff,
+ sp,
+ ff->sync_sp);
+#endif
+ __cilkrts_take_stack(ff, sp);
+ return sp;
+}
+
+
+NORETURN sysdep_longjmp_to_sf(char* new_sp,
+ __cilkrts_stack_frame *sf,
+ full_frame *ff_for_exceptions /* UNUSED on Unix */)
+{
+#if FIBER_DEBUG >= 3
+ fprintf(stderr,
+ "ThreadId=%p. resume user code, sf=%p, new_sp = %p, original SP(sf) = %p, FP(sf) = %p\n",
+ cilkos_get_current_thread_id(), sf, new_sp, SP(sf), FP(sf));
+#endif
+
+ // Set the stack pointer.
+ SP(sf) = new_sp;
+
+#ifdef RESTORE_X86_FP_STATE
+ if (CILK_FRAME_VERSION_VALUE(sf->flags) >= 1) {
+ // Restore the floating point state that was set in this frame at the
+ // last spawn.
+ //
+ // This feature is only available in ABI 1 or later frames, and only
+ // needed on IA64 or Intel64 processors.
+ restore_x86_fp_state(sf);
+ }
+#endif
+
+ CILK_LONGJMP(sf->ctx);
+}
+
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <errno.h>
+
+
+void __cilkrts_make_unrunnable_sysdep(__cilkrts_worker *w,
+ full_frame *ff,
+ __cilkrts_stack_frame *sf,
+ int is_loot,
+ const char *why)
+{
+ (void)w; /* unused */
+ sf->except_data = 0;
+
+ if (is_loot)
+ {
+ if (ff->frame_size == 0)
+ ff->frame_size = __cilkrts_get_frame_size(sf);
+
+ // Null loot's sp for debugging purposes (so we'll know it's not valid)
+ SP(sf) = 0;
+ }
+}
+
+/*
+ * __cilkrts_sysdep_is_worker_thread_id
+ *
+ * Returns true if the thread ID specified matches the thread ID we saved
+ * for a worker.
+ */
+
+int __cilkrts_sysdep_is_worker_thread_id(global_state_t *g,
+ int i,
+ void *thread_id)
+{
+#if defined( __linux__) || defined(__VXWORKS__)
+ pthread_t tid = *(pthread_t *)thread_id;
+ if (i < 0 || i > g->total_workers)
+ return 0;
+ return g->sysdep->threads[i] == tid;
+#else
+ // Needs to be implemented
+ return 0;
+#endif
+}
+
+
+
+
+/*************************************************************
+ Version information:
+*************************************************************/
+
+#include <dlfcn.h>
+#include "internal/cilk_version.h"
+#include <stdio.h>
+#include <sys/utsname.h>
+
+#ifdef __VXWORKS__
+#include <version.h>
+# endif
+
+/* (Non-static) dummy function is used by get_runtime_path() to find the path
+ * to the .so containing the Cilk runtime.
+ */
+void dummy_function() { }
+
+/* return a string with the path to the Cilk runtime, or "unknown" if the path
+ * cannot be determined.
+ */
+static const char *get_runtime_path ()
+{
+#ifdef __CYGWIN__
+ // Cygwin doesn't support dladdr, which sucks
+ return "unknown";
+#else
+ Dl_info info;
+ if (0 == dladdr(dummy_function, &info)) return "unknown";
+ return info.dli_fname;
+#endif
+}
+
+/* if the environment variable, CILK_VERSION, is defined, writes the version
+ * information to the specified file.
+ * g is the global state that was just created, and n is the number of workers
+ * that were made (or requested from RML) for it.
+ */
+static void write_version_file (global_state_t *g, int n)
+{
+ const char *env; // environment variable.
+ char buf[256]; // print buffer.
+ time_t t;
+ FILE *fp;
+ struct utsname sys_info;
+ int err; // error code from system calls.
+
+ // if CILK_VERSION is not set, or if the file cannot be opened, fail
+ // silently. Otherwise open the file for writing (or use stderr or stdout
+ // if the user specifies).
+ if (NULL == (env = getenv("CILK_VERSION"))) return;
+ if (0 == strcasecmp(env, "stderr")) fp = stderr;
+ else if (0 == strcasecmp(env, "stdout")) fp = stdout;
+ else if (NULL == (fp = fopen(env, "w"))) return;
+
+ // get a string for the current time. E.g.,
+ // Cilk runtime initialized: Thu Jun 10 13:28:00 2010
+ t = time(NULL);
+ strftime(buf, 256, "%a %b %d %H:%M:%S %Y", localtime(&t));
+ fprintf(fp, "Cilk runtime initialized: %s\n", buf);
+
+ // Print runtime info. E.g.,
+ // Cilk runtime information
+ // ========================
+ // Cilk version: 2.0.0 Build 9184
+ // Built by willtor on host willtor-desktop
+ // Compilation date: Thu Jun 10 13:27:42 2010
+ // Compiled with ICC V99.9.9, ICC build date: 20100610
+
+ fprintf(fp, "\nCilk runtime information\n");
+ fprintf(fp, "========================\n");
+ fprintf(fp, "Cilk version: %d.%d.%d Build %d\n",
+ VERSION_MAJOR,
+ VERSION_MINOR,
+ VERSION_REV,
+ VERSION_BUILD);
+#ifdef __VXWORKS__
+ char * vxWorksVer = VXWORKS_VERSION;
+ fprintf(fp, "Cross compiled for %s\n",vxWorksVer);
+ // user and host not avalible if VxWorks cross compiled on windows build host
+#else
+
+ // User and host are not available for GCC builds
+#ifdef BUILD_USER
+ fprintf(fp, "Built by "BUILD_USER" on host "BUILD_HOST"\n");
+#endif // BUILD_USER
+#endif // __VXWORKS__
+
+ // GCC has requested that this be removed for GCC builds
+#ifdef BUILD_USER
+ fprintf(fp, "Compilation date: "__DATE__" "__TIME__"\n");
+#endif // BUILD_USER
+
+#ifdef __INTEL_COMPILER
+ // Compiled by the Intel C/C++ compiler.
+ fprintf(fp, "Compiled with ICC V%d.%d.%d, ICC build date: %d\n",
+ __INTEL_COMPILER / 100,
+ (__INTEL_COMPILER / 10) % 10,
+ __INTEL_COMPILER % 10,
+ __INTEL_COMPILER_BUILD_DATE);
+#else
+ // Compiled by GCC.
+ fprintf(fp, "Compiled with GCC V%d.%d.%d\n",
+ __GNUC__,
+ __GNUC_MINOR__,
+ __GNUC_PATCHLEVEL__);
+#endif // defined __INTEL_COMPILER
+
+ // Print system info. E.g.,
+ // System information
+ // ==================
+ // Cilk runtime path: /opt/icc/64/lib/libcilkrts.so.5
+ // System OS: Linux, release 2.6.28-19-generic
+ // System architecture: x86_64
+
+ err = uname(&sys_info);
+ fprintf(fp, "\nSystem information\n");
+ fprintf(fp, "==================\n");
+ fprintf(fp, "Cilk runtime path: %s\n", get_runtime_path());
+ fprintf(fp, "System OS: %s, release %s\n",
+ err < 0 ? "unknown" : sys_info.sysname,
+ err < 0 ? "?" : sys_info.release);
+ fprintf(fp, "System architecture: %s\n",
+ err < 0 ? "unknown" : sys_info.machine);
+
+ // Print thread info. E.g.,
+ // Thread information
+ // ==================
+ // System cores: 8
+ // Cilk workers requested: 8
+ // Thread creator: Private
+
+ fprintf(fp, "\nThread information\n");
+ fprintf(fp, "==================\n");
+#ifdef __VXWORKS__
+ fprintf(fp, "System cores: %d\n", (int)__builtin_popcount(vxCpuEnabledGet()));
+#else
+ fprintf(fp, "System cores: %d\n", (int)sysconf(_SC_NPROCESSORS_ONLN));
+#endif
+ fprintf(fp, "Cilk workers requested: %d\n", n);
+#if (PARALLEL_THREAD_CREATE)
+ fprintf(fp, "Thread creator: Private (parallel)\n");
+#else
+ fprintf(fp, "Thread creator: Private\n");
+#endif
+
+ if (fp != stderr && fp != stdout) fclose(fp);
+ else fflush(fp); // flush the handle buffer if it is stdout or stderr.
+}
+
+
+/*
+ * __cilkrts_establish_c_stack
+ *
+ * Tell Cilkscreen about the user stack bounds.
+ *
+ * Note that the Cilk V1 runtime only included the portion of the stack from
+ * the entry into Cilk, down. We don't appear to be able to find that, but
+ * I think this will be sufficient.
+ */
+
+void __cilkrts_establish_c_stack(void)
+{
+ /* FIXME: Not implemented. */
+
+ /* TBD: Do we need this */
+ /*
+ void __cilkrts_cilkscreen_establish_c_stack(char *begin, char *end);
+
+ size_t r;
+ MEMORY_BASIC_INFORMATION mbi;
+
+ r = VirtualQuery (&mbi,
+ &mbi,
+ sizeof(mbi));
+
+ __cilkrts_cilkscreen_establish_c_stack((char *)mbi.BaseAddress,
+ (char *)mbi.BaseAddress + mbi.RegionSize);
+ */
+}
+
+
+/*
+ * internal_enforce_global_visibility
+ *
+ * Ensure global visibility of public symbols, for proper Cilk-TBB interop.
+ *
+ * If Cilk runtime is loaded dynamically, its symbols might remain unavailable
+ * for global search with dladdr; that might prevent TBB from finding Cilk
+ * in the process address space and initiating the interop protocol.
+ * The workaround is for the library to open itself with RTLD_GLOBAL flag.
+ */
+
+static __attribute__((noinline))
+void internal_enforce_global_visibility()
+{
+ void* handle = dlopen( get_runtime_path(), RTLD_GLOBAL|RTLD_LAZY );
+
+ /* For proper reference counting, close the handle immediately. */
+ if( handle) dlclose(handle);
+}
+
+/*
+ Local Variables: **
+ c-file-style:"bsd" **
+ c-basic-offset:4 **
+ indent-tabs-mode:nil **
+ End: **
+*/
diff --git a/libcilkrts/runtime/sysdep.h b/libcilkrts/runtime/sysdep.h
new file mode 100644
index 00000000000..ea939acc124
--- /dev/null
+++ b/libcilkrts/runtime/sysdep.h
@@ -0,0 +1,285 @@
+/* sysdep.h -*-C++-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ **************************************************************************/
+
+/**
+ * @file sysdep.h
+ *
+ * @brief Common system-dependent functions
+ */
+
+#ifndef INCLUDED_SYSDEP_DOT_H
+#define INCLUDED_SYSDEP_DOT_H
+
+#include <cilk/common.h>
+#include <internal/abi.h>
+
+#include "global_state.h"
+#include "full_frame.h"
+#include "os.h"
+#include "os_mutex.h"
+
+/**
+ * @brief Default page size for Cilk stacks.
+ *
+ * All Cilk stacks should have size that is a multiple of this value.
+ */
+#define PAGE 4096
+
+/**
+ * @brief Size of a scheduling stack.
+ *
+ * A scheduling stack is used to by system workers to execute runtime
+ * code. Since this stack is only executing runtime functions, we
+ * don't need it to be a full size stack.
+ *
+ * The number "18" should be small since the runtime doesn't require a
+ * large stack, but large enough to call "printf" for debugging.
+ */
+#define CILK_SCHEDULING_STACK_SIZE (18*PAGE)
+
+__CILKRTS_BEGIN_EXTERN_C
+
+
+/**
+ * Code to initialize the system-dependent portion of the global_state_t
+ *
+ * @param g Pointer to the global state.
+ */
+COMMON_SYSDEP
+void __cilkrts_init_global_sysdep(global_state_t *g);
+
+/**
+ * Code to clean up the system-dependent portion of the global_state_t
+ *
+ * @param g Pointer to the global state.
+ */
+COMMON_SYSDEP
+void __cilkrts_destroy_global_sysdep(global_state_t *g);
+
+/**
+ * Passes stack range to Cilkscreen. This functionality should be moved
+ * into Cilkscreen.
+ */
+COMMON_SYSDEP
+void __cilkrts_establish_c_stack(void);
+
+
+/**
+ * Save system dependent information in the full_frame and
+ * __cilkrts_stack_frame. Part of promoting a
+ * __cilkrts_stack_frame to a full_frame.
+ *
+ * @param w The worker the frame was running on. Not used.
+ * @param ff The full frame that is being created for the
+ * __cilkrts_stack_frame.
+ * @param sf The __cilkrts_stack_frame that's being promoted
+ * to a full frame.
+ * @param state_valid ?
+ * @param why A description of why make_unrunnable was called.
+ * Used for debugging.
+ */
+COMMON_SYSDEP
+void __cilkrts_make_unrunnable_sysdep(__cilkrts_worker *w,
+ full_frame *ff,
+ __cilkrts_stack_frame *sf,
+ int state_valid,
+ const char *why);
+
+
+/**
+ * OS-specific code to spawn worker threads.
+ *
+ * @param g The global state.
+ * @param n Number of worker threads to start.
+ */
+COMMON_SYSDEP
+void __cilkrts_start_workers(global_state_t *g, int n);
+
+/**
+ * @brief OS-specific code to stop worker threads.
+ *
+ * @param g The global state.
+ */
+COMMON_SYSDEP
+void __cilkrts_stop_workers(global_state_t *g);
+
+/**
+ * @brief Imports a user thread the first time it returns to a stolen parent.
+ *
+ * The thread has been bound to a worker, but additional steps need to
+ * be taken to start running a scheduling loop.
+ *
+ * @param w The worker bound to the thread.
+ */
+COMMON_SYSDEP
+void __cilkrts_sysdep_import_user_thread(__cilkrts_worker *w);
+
+/**
+ * @brief Function to be run for each of the system worker threads.
+ *
+ * This declaration also appears in cilk/cilk_undocumented.h -- don't
+ * change one declaration without also changing the other.
+ *
+ * @param arg The context value passed to the thread creation routine for
+ * the OS we're running on.
+ *
+ * @returns OS dependent.
+ */
+#ifdef _WIN32
+/* Do not use CILK_API because __cilkrts_worker_stub must be __stdcall */
+CILK_EXPORT unsigned __CILKRTS_NOTHROW __stdcall
+__cilkrts_worker_stub(void *arg);
+#else
+/* Do not use CILK_API because __cilkrts_worker_stub have default visibility */
+__attribute__((visibility("default")))
+void* __CILKRTS_NOTHROW __cilkrts_worker_stub(void *arg);
+#endif
+
+/**
+ * Initialize any OS-depenendent portions of a newly created
+ * __cilkrts_worker.
+ *
+ * Exported for Piersol. Without the export, Piersol doesn't display
+ * useful information in the stack trace. This declaration also appears in
+ * cilk/cilk_undocumented.h -- do not modify one without modifying the other.
+ *
+ * @param w The worker being initialized.
+ */
+COMMON_SYSDEP
+CILK_EXPORT
+void __cilkrts_init_worker_sysdep(__cilkrts_worker *w);
+
+/**
+ * Deallocate any OS-depenendent portions of a __cilkrts_worker.
+ *
+ * @param w The worker being deallocaed.
+ */
+COMMON_SYSDEP
+void __cilkrts_destroy_worker_sysdep(__cilkrts_worker *w);
+
+/**
+ * Called to do any OS-dependent setup before starting execution on a
+ * frame. Mostly deals with exception handling data.
+ *
+ * @param w The worker the frame will run on.
+ * @param ff The full_frame that is about to be resumed.
+ */
+COMMON_SYSDEP
+void __cilkrts_setup_for_execution_sysdep(__cilkrts_worker *w,
+ full_frame *ff);
+
+/**
+ * @brief OS-specific implementaton of resetting fiber and frame state
+ * to resume exeuction.
+ *
+ * This method:
+ * 1. Calculates the value of stack pointer where we should resume
+ * execution of "sf". This calculation uses info stored in the
+ * fiber, and takes into account alignment and frame size.
+ * 2. Updates sf and ff to match the calculated stack pointer.
+ *
+ * On Unix, the stack pointer calculation looks up the base of the
+ * stack from the fiber.
+ *
+ * On Windows, this calculation is calls "alloca" to find a stack
+ * pointer on the currently executing stack. Thus, the Windows code
+ * assumes @c fiber is the currently executing fiber.
+ *
+ * @param fiber fiber to resume execution on.
+ * @param ff full_frame for the frame we're resuming.
+ * @param sf __cilkrts_stack_frame that we should resume
+ * @return The calculated stack pointer.
+ */
+COMMON_SYSDEP
+char* sysdep_reset_jump_buffers_for_resume(cilk_fiber* fiber,
+ full_frame *ff,
+ __cilkrts_stack_frame *sf);
+
+/**
+ * @brief System-dependent longjmp to user code for resuming execution
+ * of a @c __cilkrts_stack_frame.
+ *
+ * This method:
+ * - Changes the stack pointer in @c sf to @c new_sp.
+ * - If @c ff_for_exceptions is not NULL, changes fields in @c sf and
+ * @c ff_for_exceptions for exception processing.
+ * - Restores any floating point state
+ * - Finishes with a longjmp to user code, never to return.
+ *
+ * @param new_sp stack pointer where we should resume execution
+ * @param sf @c __cilkrts_stack_frame for the frame we're resuming.
+ * @param ff_for_exceptions full_frame to safe exception info into, if necessary
+ */
+COMMON_SYSDEP
+NORETURN
+sysdep_longjmp_to_sf(char* new_sp,
+ __cilkrts_stack_frame *sf,
+ full_frame *ff_for_exceptions);
+
+/**
+ * @brief System-dependent code to save floating point control information
+ * to a @c __cilkrts_stack_frame. This function will be called by compilers
+ * that cannot inline the code.
+ *
+ * Note that this function does *not* save the current floating point
+ * registers. It saves the floating point control words that control
+ * precision and rounding and stuff like that.
+ *
+ * This function will be a noop for architectures that don't have warts
+ * like the floating point control words, or where the information is
+ * already being saved by the setjmp.
+ *
+ * @param sf @c __cilkrts_stack_frame for the frame we're
+ * saving the floating point control information in.
+ */
+COMMON_SYSDEP
+void
+sysdep_save_fp_ctrl_state(__cilkrts_stack_frame *sf);
+
+
+/**
+ * @brief restore x86 floating point state
+ *
+ * Only used for x86 and Intel64 processors
+ */
+COMMON_SYSDEP
+void restore_x86_fp_state(__cilkrts_stack_frame *sf);
+
+__CILKRTS_END_EXTERN_C
+
+#endif // ! defined(INCLUDED_SYSDEP_DOT_H)
diff --git a/libcilkrts/runtime/worker_mutex.c b/libcilkrts/runtime/worker_mutex.c
new file mode 100644
index 00000000000..380d6255a0c
--- /dev/null
+++ b/libcilkrts/runtime/worker_mutex.c
@@ -0,0 +1,121 @@
+/* worker_mutex.c -*-C-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ **************************************************************************/
+
+#include "worker_mutex.h"
+#include "bug.h"
+#include "os.h"
+#include "stats.h"
+
+/* m->lock == 1 means that mutex M is locked */
+#define TRY_ACQUIRE(m) (__cilkrts_xchg(&(m)->lock, 1) == 0)
+
+/* ICC 11.1+ understands release semantics and generates an
+ ordinary store with a software memory barrier. */
+#if __ICC >= 1110
+#define RELEASE(m) __sync_lock_release(&(m)->lock)
+#else
+#define RELEASE(m) __cilkrts_xchg(&(m)->lock, 0)
+#endif
+
+void __cilkrts_mutex_init(struct mutex *m)
+{
+ m->owner = 0;
+
+ // Use a simple assignment so Inspector doesn't bug us about the
+ // interlocked exchange doing a read of an uninitialized variable.
+ // By definition there can't be a race when we're initializing the
+ // lock...
+ m->lock = 0;
+}
+
+void __cilkrts_mutex_lock(__cilkrts_worker *w, struct mutex *m)
+{
+ int count;
+ const int maxspin = 1000; /* SWAG */
+
+ NOTE_INTERVAL(w, INTERVAL_MUTEX_LOCK);
+ if (!TRY_ACQUIRE(m)) {
+ START_INTERVAL(w, INTERVAL_MUTEX_LOCK_SPINNING);
+ count = 0;
+ do {
+ do {
+ __cilkrts_short_pause();
+ if (++count >= maxspin) {
+ STOP_INTERVAL(w, INTERVAL_MUTEX_LOCK_SPINNING);
+ START_INTERVAL(w, INTERVAL_MUTEX_LOCK_YIELDING);
+ /* let the OS reschedule every once in a while */
+ __cilkrts_yield();
+ STOP_INTERVAL(w, INTERVAL_MUTEX_LOCK_YIELDING);
+ START_INTERVAL(w, INTERVAL_MUTEX_LOCK_SPINNING);
+ count = 0;
+ }
+ } while (m->lock != 0);
+ } while (!TRY_ACQUIRE(m));
+ STOP_INTERVAL(w, INTERVAL_MUTEX_LOCK_SPINNING);
+ }
+
+ CILK_ASSERT(m->owner == 0);
+ m->owner = w;
+}
+
+int __cilkrts_mutex_trylock(__cilkrts_worker *w, struct mutex *m)
+{
+ NOTE_INTERVAL(w, INTERVAL_MUTEX_TRYLOCK);
+ if (TRY_ACQUIRE(m)) {
+ CILK_ASSERT(m->owner == 0);
+ m->owner = w;
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+void __cilkrts_mutex_unlock(__cilkrts_worker *w, struct mutex *m)
+{
+ CILK_ASSERT(m->owner == w);
+ m->owner = 0;
+ RELEASE(m);
+}
+
+void __cilkrts_mutex_destroy(__cilkrts_worker *w, struct mutex *m)
+{
+ (void)w; /* unused */
+ (void)m; /* unused */
+}
+
+/* End worker_mutex.c */
diff --git a/libcilkrts/runtime/worker_mutex.h b/libcilkrts/runtime/worker_mutex.h
new file mode 100644
index 00000000000..c2c68247e0b
--- /dev/null
+++ b/libcilkrts/runtime/worker_mutex.h
@@ -0,0 +1,131 @@
+/* worker_mutex.h -*-C++-*-
+ *
+ *************************************************************************
+ *
+ * @copyright
+ * Copyright (C) 2009-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * @copyright
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * @copyright
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ **************************************************************************/
+
+/**
+ * @file worker_mutex.h
+ *
+ * @brief Support for Cilk runtime mutexes.
+ *
+ * Cilk runtime mutexes are implemented as simple spin loops.
+ */
+
+#ifndef INCLUDED_WORKER_MUTEX_DOT_H
+#define INCLUDED_WORKER_MUTEX_DOT_H
+
+#include <cilk/common.h>
+#include "rts-common.h"
+
+__CILKRTS_BEGIN_EXTERN_C
+
+/**
+ * Mutexes are treated as an abstract data type within the Cilk
+ * runtime system. They are implemented as simple spin loops and
+ * owned by a __cilkrts_worker.
+ */
+typedef struct mutex {
+ /** Mutex spin loop variable. 0 if unowned, 1 if owned. */
+ volatile int lock;
+
+ /** Worker that owns the mutex. Must be 0 if mutex is unowned. */
+ __cilkrts_worker *owner;
+} mutex;
+
+/**
+ * @brief Initialize a Cilk mutex.
+ *
+ * @param m Mutex to be initialized.
+ */
+COMMON_PORTABLE
+void __cilkrts_mutex_init(struct mutex *m);
+
+/**
+ * @brief Acquire a Cilk mutex.
+ *
+ * If statistics are being gathered, the time spent
+ * acquiring the mutex will be attributed to the specified worker.
+ *
+ * @param w Worker that will become the owner of this mutex.
+ * @param m Mutex to be initialized.
+ */
+COMMON_PORTABLE
+void __cilkrts_mutex_lock(__cilkrts_worker *w,
+ struct mutex *m);
+/**
+ * @brief Attempt to lock a Cilk mutex and fail if it isn't available.
+ *
+ * If statistics are being gathered, the time spent acquiring the
+ * mutex will be attributed to the specified worker.
+ *
+ * @param w Worker that will become the owner of this mutex.
+ * @param m Mutex to be acquired.
+ *
+ * @return 1 if the mutex was acquired.
+ * @return 0 if the mutex was not acquired.
+ */
+COMMON_PORTABLE
+int __cilkrts_mutex_trylock(__cilkrts_worker *w,
+ struct mutex *m);
+
+/**
+ * @brief Release a Cilk mutex.
+ *
+ * If statistics are being gathered, the time spent
+ * acquiring the mutex will be attributed to the specified worker.
+ *
+ * @pre The mutex must be owned by the worker.
+ *
+ * @param w Worker that owns this mutex.
+ * @param m Mutex to be released.
+ */
+COMMON_PORTABLE
+void __cilkrts_mutex_unlock(__cilkrts_worker *w,
+ struct mutex *m);
+
+/**
+ * @brief Deallocate a Cilk mutex. Currently does nothing.
+ *
+ * @param w Unused.
+ * @param m Mutex to be deallocated.
+ */
+COMMON_PORTABLE
+void __cilkrts_mutex_destroy(__cilkrts_worker *w,
+ struct mutex *m);
+
+__CILKRTS_END_EXTERN_C
+
+#endif // ! defined(INCLUDED_WORKER_MUTEX_DOT_H)
diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog
index 862333e1422..64de79b287c 100644
--- a/libcpp/ChangeLog
+++ b/libcpp/ChangeLog
@@ -1,3 +1,38 @@
+2013-11-06 Tobias Burnus <burnus@net-b.de>
+
+ * macro.c (_cpp_builtin_macro_text): Correct
+ wording of two warnings.
+
+2013-11-05 Tobias Burnus <burnus@net-b.de>
+
+ * include/cpplib.h (CPP_W_DATE_TIME): Added.
+ (cpp_options): Add warn_date_time.
+ * init.c (cpp_create_reader): Init it.
+ * macro.c (_cpp_builtin_macro_text): Warn when
+ __DATE__/__TIME__/__TIMESTAMP__ is used.
+
+2013-10-31 Edward Smith-Rowland <3dw4rd@verizon.net>
+
+ Implement C++14 digit separators.
+ * include/cpplib.h (cpp_options): Add digit_separators flag.
+ * internal.h (DIGIT_SEP(c)): New macro.
+ * expr.c (cpp_classify_number): Check improper placement of digit sep;
+ (cpp_interpret_integer): Skip over digit separators.
+ * init.c (lang_flags): Add digit_separators flag; (lang_defaults): Add
+ digit separator flags per language; (cpp_set_lang): Set
+ digit_separators
+ * lex.c (lex_number): Add digits separator to allowable characters for
+ C++14.
+
+2013-10-15 David Malcolm <dmalcolm@redhat.com>
+
+ * Makefile.in (PICFLAG): New.
+ (ALL_CFLAGS): Add PICFLAG.
+ (ALL_CXXFLAGS): Likewise.
+ * configure.ac: Add --enable-host-shared, setting up new
+ PICFLAG variable.
+ * configure: Regenerate.
+
2013-08-07 Richard Earnshaw <rearnsha@arm.com>
* configure.ac: Set need_64bit_hwint for all arm targets.
diff --git a/libcpp/Makefile.in b/libcpp/Makefile.in
index 2353c9c043b..30bf8963cd8 100644
--- a/libcpp/Makefile.in
+++ b/libcpp/Makefile.in
@@ -57,6 +57,7 @@ CCDEPMODE = @CCDEPMODE@
CXXDEPMODE = @CXXDEPMODE@
DEPDIR = @DEPDIR@
NOEXCEPTION_FLAGS = @noexception_flags@
+PICFLAG = @PICFLAG@
datarootdir = @datarootdir@
datadir = @datadir@
@@ -72,9 +73,9 @@ depcomp = $(SHELL) $(srcdir)/../depcomp
INCLUDES = -I$(srcdir) -I. -I$(srcdir)/../include @INCINTL@ \
-I$(srcdir)/include
-ALL_CFLAGS = $(CFLAGS) $(WARN_CFLAGS) $(INCLUDES) $(CPPFLAGS)
+ALL_CFLAGS = $(CFLAGS) $(WARN_CFLAGS) $(INCLUDES) $(CPPFLAGS) $(PICFLAG)
ALL_CXXFLAGS = $(CXXFLAGS) $(WARN_CXXFLAGS) $(NOEXCEPTION_FLAGS) $(INCLUDES) \
- $(CPPFLAGS)
+ $(CPPFLAGS) $(PICFLAG)
# The name of the compiler to use.
COMPILER = $(CXX)
diff --git a/libcpp/aclocal.m4 b/libcpp/aclocal.m4
index db1ceaa1495..5a1ed754867 100644
--- a/libcpp/aclocal.m4
+++ b/libcpp/aclocal.m4
@@ -1,4 +1,4 @@
-# generated automatically by aclocal 1.13.3 -*- Autoconf -*-
+# generated automatically by aclocal 1.14 -*- Autoconf -*-
# Copyright (C) 1996-2013 Free Software Foundation, Inc.
diff --git a/libcpp/configure b/libcpp/configure
index 60ce2e569dd..782a7105ac3 100755
--- a/libcpp/configure
+++ b/libcpp/configure
@@ -592,6 +592,7 @@ ac_includes_default="\
#endif"
ac_subst_vars='LTLIBOBJS
+PICFLAG
MAINT
USED_CATALOGS
PACKAGE
@@ -701,6 +702,7 @@ with_libiconv_prefix
enable_maintainer_mode
enable_checking
enable_canonical_system_headers
+enable_host_shared
'
ac_precious_vars='build_alias
host_alias
@@ -1340,6 +1342,7 @@ Optional Features:
other strings
--enable-canonical-system-headers
enable or disable system headers canonicalization
+ --enable-host-shared build host code as shared libraries
Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
@@ -7204,6 +7207,16 @@ fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
esac
+# 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
+
+
+
# Output.
ac_config_headers="$ac_config_headers config.h:config.in"
diff --git a/libcpp/configure.ac b/libcpp/configure.ac
index 799301f0722..a70603c95a6 100644
--- a/libcpp/configure.ac
+++ b/libcpp/configure.ac
@@ -220,6 +220,13 @@ case $target in
[Define to 1 if you can assemble SSE4 insns.])])
esac
+# 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(PICFLAG)
+
# Output.
AC_CONFIG_HEADERS(config.h:config.in, [echo timestamp > stamp-h1])
diff --git a/libcpp/expr.c b/libcpp/expr.c
index 0eb6c13c2f0..c0098073ab8 100644
--- a/libcpp/expr.c
+++ b/libcpp/expr.c
@@ -394,6 +394,7 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
unsigned int max_digit, result, radix;
enum {NOT_FLOAT = 0, AFTER_POINT, AFTER_EXPON} float_flag;
bool seen_digit;
+ bool seen_digit_sep;
if (ud_suffix)
*ud_suffix = NULL;
@@ -408,6 +409,7 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
max_digit = 0;
radix = 10;
seen_digit = false;
+ seen_digit_sep = false;
/* First, interpret the radix. */
if (*str == '0')
@@ -416,16 +418,27 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
str++;
/* Require at least one hex digit to classify it as hex. */
- if ((*str == 'x' || *str == 'X')
- && (str[1] == '.' || ISXDIGIT (str[1])))
+ if (*str == 'x' || *str == 'X')
{
- radix = 16;
- str++;
+ if (str[1] == '.' || ISXDIGIT (str[1]))
+ {
+ radix = 16;
+ str++;
+ }
+ else if (DIGIT_SEP (str[1]))
+ SYNTAX_ERROR_AT (virtual_location,
+ "digit separator after base indicator");
}
- else if ((*str == 'b' || *str == 'B') && (str[1] == '0' || str[1] == '1'))
+ else if (*str == 'b' || *str == 'B')
{
- radix = 2;
- str++;
+ if (str[1] == '0' || str[1] == '1')
+ {
+ radix = 2;
+ str++;
+ }
+ else if (DIGIT_SEP (str[1]))
+ SYNTAX_ERROR_AT (virtual_location,
+ "digit separator after base indicator");
}
}
@@ -436,13 +449,24 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
if (ISDIGIT (c) || (ISXDIGIT (c) && radix == 16))
{
+ seen_digit_sep = false;
seen_digit = true;
c = hex_value (c);
if (c > max_digit)
max_digit = c;
}
+ else if (DIGIT_SEP (c))
+ {
+ if (seen_digit_sep)
+ SYNTAX_ERROR_AT (virtual_location, "adjacent digit separators");
+ seen_digit_sep = true;
+ }
else if (c == '.')
{
+ if (seen_digit_sep || DIGIT_SEP (*str))
+ SYNTAX_ERROR_AT (virtual_location,
+ "digit separator adjacent to decimal point");
+ seen_digit_sep = false;
if (float_flag == NOT_FLOAT)
float_flag = AFTER_POINT;
else
@@ -452,6 +476,9 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
else if ((radix <= 10 && (c == 'e' || c == 'E'))
|| (radix == 16 && (c == 'p' || c == 'P')))
{
+ if (seen_digit_sep || DIGIT_SEP (*str))
+ SYNTAX_ERROR_AT (virtual_location,
+ "digit separator adjacent to exponent");
float_flag = AFTER_EXPON;
break;
}
@@ -463,6 +490,10 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
}
}
+ if (seen_digit_sep && float_flag != AFTER_EXPON)
+ SYNTAX_ERROR_AT (virtual_location,
+ "digit separator outside digit sequence");
+
/* The suffix may be for decimal fixed-point constants without exponent. */
if (radix != 16 && float_flag == NOT_FLOAT)
{
@@ -520,16 +551,28 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
/* Exponent is decimal, even if string is a hex float. */
if (!ISDIGIT (*str))
- SYNTAX_ERROR_AT (virtual_location, "exponent has no digits");
-
+ {
+ if (DIGIT_SEP (*str))
+ SYNTAX_ERROR_AT (virtual_location,
+ "digit separator adjacent to exponent");
+ else
+ SYNTAX_ERROR_AT (virtual_location, "exponent has no digits");
+ }
do
- str++;
- while (ISDIGIT (*str));
+ {
+ seen_digit_sep = DIGIT_SEP (*str);
+ str++;
+ }
+ while (ISDIGIT (*str) || DIGIT_SEP (*str));
}
else if (radix == 16)
SYNTAX_ERROR_AT (virtual_location,
"hexadecimal floating constants require an exponent");
+ if (seen_digit_sep)
+ SYNTAX_ERROR_AT (virtual_location,
+ "digit separator outside digit sequence");
+
result = interpret_float_suffix (pfile, str, limit - str);
if (result == 0)
{
@@ -723,6 +766,8 @@ cpp_interpret_integer (cpp_reader *pfile, const cpp_token *token,
if (ISDIGIT (c) || (base == 16 && ISXDIGIT (c)))
c = hex_value (c);
+ else if (DIGIT_SEP (c))
+ continue;
else
break;
diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h
index 6c4225c8be7..02927d4c6cb 100644
--- a/libcpp/include/cpplib.h
+++ b/libcpp/include/cpplib.h
@@ -337,6 +337,9 @@ struct cpp_options
/* Nonzero means warn if slash-star appears in a comment. */
unsigned char warn_comments;
+ /* Nonzero means to warn about __DATA__, __TIME__ and __TIMESTAMP__ usage. */
+ unsigned char warn_date_time;
+
/* Nonzero means warn if a user-supplied include directory does not
exist. */
unsigned char warn_missing_include_dirs;
@@ -437,6 +440,9 @@ struct cpp_options
/* Nonzero for C++ 2014 Standard binary constants. */
unsigned char binary_constants;
+ /* Nonzero for C++ 2014 Standard digit separators. */
+ unsigned char digit_separators;
+
/* Holds the name of the target (execution) character set. */
const char *narrow_charset;
@@ -922,7 +928,8 @@ enum {
CPP_W_NORMALIZE,
CPP_W_INVALID_PCH,
CPP_W_WARNING_DIRECTIVE,
- CPP_W_LITERAL_SUFFIX
+ CPP_W_LITERAL_SUFFIX,
+ CPP_W_DATE_TIME
};
/* Output a diagnostic of some kind. */
diff --git a/libcpp/init.c b/libcpp/init.c
index 97510003dd8..67444301590 100644
--- a/libcpp/init.c
+++ b/libcpp/init.c
@@ -84,24 +84,25 @@ struct lang_flags
char rliterals;
char user_literals;
char binary_constants;
+ char digit_separators;
};
static const struct lang_flags lang_defaults[] =
-{ /* c99 c++ xnum xid std // digr ulit rlit udlit bin_cst */
- /* GNUC89 */ { 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0 },
- /* GNUC99 */ { 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0 },
- /* GNUC11 */ { 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0 },
- /* STDC89 */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
- /* STDC94 */ { 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0 },
- /* STDC99 */ { 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0 },
- /* STDC11 */ { 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0 },
- /* GNUCXX */ { 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0 },
- /* CXX98 */ { 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0 },
- /* GNUCXX11 */ { 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0 },
- /* CXX11 */ { 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0 },
- /* GNUCXX1Y */ { 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1 },
- /* CXX1Y */ { 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1 },
- /* ASM */ { 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0 }
+{ /* c99 c++ xnum xid std // digr ulit rlit udlit bin_cst dig_sep */
+ /* GNUC89 */ { 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0 },
+ /* GNUC99 */ { 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0 },
+ /* GNUC11 */ { 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0 },
+ /* STDC89 */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
+ /* STDC94 */ { 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0 },
+ /* STDC99 */ { 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0 },
+ /* STDC11 */ { 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0 },
+ /* GNUCXX */ { 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0 },
+ /* CXX98 */ { 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0 },
+ /* GNUCXX11 */ { 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0 },
+ /* CXX11 */ { 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0 },
+ /* GNUCXX1Y */ { 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1 },
+ /* CXX1Y */ { 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1 },
+ /* ASM */ { 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0 }
/* xid should be 1 for GNUC99, STDC99, GNUCXX, CXX98, GNUCXX11, CXX11,
GNUCXX1Y, and CXX1Y when no longer experimental (when all uses of
identifiers in the compiler have been audited for correct handling
@@ -128,6 +129,7 @@ cpp_set_lang (cpp_reader *pfile, enum c_lang lang)
CPP_OPTION (pfile, rliterals) = l->rliterals;
CPP_OPTION (pfile, user_literals) = l->user_literals;
CPP_OPTION (pfile, binary_constants) = l->binary_constants;
+ CPP_OPTION (pfile, digit_separators) = l->digit_separators;
}
/* Initialize library global state. */
@@ -191,6 +193,7 @@ cpp_create_reader (enum c_lang lang, cpp_hash_table *table,
CPP_OPTION (pfile, canonical_system_headers)
= ENABLE_CANONICAL_SYSTEM_HEADERS;
CPP_OPTION (pfile, ext_numeric_literals) = 1;
+ CPP_OPTION (pfile, warn_date_time) = 0;
/* Default CPP arithmetic to something sensible for the host for the
benefit of dumb users like fix-header. */
diff --git a/libcpp/internal.h b/libcpp/internal.h
index 1226dbd982b..6de44ed3556 100644
--- a/libcpp/internal.h
+++ b/libcpp/internal.h
@@ -59,6 +59,8 @@ struct cset_converter
|| (((prevc) == 'p' || (prevc) == 'P') \
&& CPP_OPTION (pfile, extended_numbers))))
+#define DIGIT_SEP(c) ((c) == '\'' && CPP_OPTION (pfile, digit_separators))
+
#define CPP_OPTION(PFILE, OPTION) ((PFILE)->opts.OPTION)
#define CPP_BUFFER(PFILE) ((PFILE)->buffer)
#define CPP_BUF_COLUMN(BUF, CUR) ((CUR) - (BUF)->line_base)
diff --git a/libcpp/lex.c b/libcpp/lex.c
index ed794d5b004..95995edca33 100644
--- a/libcpp/lex.c
+++ b/libcpp/lex.c
@@ -1274,7 +1274,8 @@ lex_number (cpp_reader *pfile, cpp_string *number,
cur = pfile->buffer->cur;
/* N.B. ISIDNUM does not include $. */
- while (ISIDNUM (*cur) || *cur == '.' || VALID_SIGN (*cur, cur[-1]))
+ while (ISIDNUM (*cur) || *cur == '.' || DIGIT_SEP (*cur)
+ || VALID_SIGN (*cur, cur[-1]))
{
cur++;
NORMALIZE_STATE_UPDATE_IDNUM (nst);
diff --git a/libcpp/macro.c b/libcpp/macro.c
index 6d46027e4ea..e359d158c03 100644
--- a/libcpp/macro.c
+++ b/libcpp/macro.c
@@ -232,6 +232,10 @@ _cpp_builtin_macro_text (cpp_reader *pfile, cpp_hashnode *node)
case BT_TIMESTAMP:
{
+ if (CPP_OPTION (pfile, warn_date_time))
+ cpp_warning (pfile, CPP_W_DATE_TIME, "macro \"%s\" might prevent "
+ "reproducible builds", NODE_NAME (node));
+
cpp_buffer *pbuffer = cpp_get_buffer (pfile);
if (pbuffer->timestamp == NULL)
{
@@ -325,6 +329,9 @@ _cpp_builtin_macro_text (cpp_reader *pfile, cpp_hashnode *node)
case BT_DATE:
case BT_TIME:
+ if (CPP_OPTION (pfile, warn_date_time))
+ cpp_warning (pfile, CPP_W_DATE_TIME, "macro \"%s\" might prevent "
+ "reproducible builds", NODE_NAME (node));
if (pfile->date == NULL)
{
/* Allocate __DATE__ and __TIME__ strings from permanent
diff --git a/libcpp/po/ChangeLog b/libcpp/po/ChangeLog
index 06d86565f3e..3870de500c8 100644
--- a/libcpp/po/ChangeLog
+++ b/libcpp/po/ChangeLog
@@ -1,3 +1,11 @@
+2013-11-01 Joseph Myers <joseph@codesourcery.com>
+
+ * tr.po: Update.
+
+2013-10-03 Joseph Myers <joseph@codesourcery.com>
+
+ * sr.po: Update.
+
2013-03-30 Joseph Myers <joseph@codesourcery.com>
* vi.po: Update.
diff --git a/libcpp/po/sr.po b/libcpp/po/sr.po
index c9416c4af76..ef7dbc3e695 100644
--- a/libcpp/po/sr.po
+++ b/libcpp/po/sr.po
@@ -1,13 +1,13 @@
# Serbian translation of cpplib.
# Copyright (C) 2012 Free Software Foundation, Inc.
# This file is distributed under the same license as the gcc package.
-# МироÑлав Ðиколић <miroslavnikolic@rocketmail.com>, 2012.
+# МироÑлав Ðиколић <miroslavnikolic@rocketmail.com>, 2012, 2013.
msgid ""
msgstr ""
-"Project-Id-Version: cpplib-4.7.0\n"
+"Project-Id-Version: cpplib-4.8.0\n"
"Report-Msgid-Bugs-To: http://gcc.gnu.org/bugs.html\n"
-"POT-Creation-Date: 2013-02-24 01:05+0000\n"
-"PO-Revision-Date: 2012-06-13 11:32+0200\n"
+"POT-Creation-Date: 2013-03-15 17:42+0000\n"
+"PO-Revision-Date: 2013-10-03 08:53+0200\n"
"Last-Translator: МироÑлав Ðиколић <miroslavnikolic@rocketmail.com>\n"
"Language-Team: Serbian <gnu@prevod.org>\n"
"Language: sr\n"
@@ -340,14 +340,13 @@ msgid "current file is older than %s"
msgstr "текућа датотека је Ñтарија од %s"
#: directives.c:1653
-#, fuzzy, c-format
-#| msgid "invalid #pragma GCC poison directive"
+#, c-format
msgid "invalid \"#pragma GCC %s\" directive"
-msgstr "неиÑправна „#pragma GCC poison“ директива"
+msgstr "неиÑправна директива „#pragma GCC %s“"
#: directives.c:1847
msgid "_Pragma takes a parenthesized string literal"
-msgstr "_Прагма узима ÑловноÑÑ‚ ниÑке затворену заградом"
+msgstr "_Прагма узима ÑловноÑÑ‚ ниÑке затворене заградом"
#: directives.c:1968
msgid "#else without #if"
@@ -398,7 +397,7 @@ msgstr "предикат мора бити одредник"
msgid "\"%s\" re-asserted"
msgstr "„%s“ је поново утврђен"
-#: directives.c:2566
+#: directives.c:2567
#, c-format
msgid "unterminated #%s"
msgstr "неокончано #%s"
@@ -570,39 +569,39 @@ msgstr "оператор зареза у операнду „#if“"
msgid "division by zero in #if"
msgstr "дељење нулом у „#if“"
-#: files.c:504
+#: files.c:505
msgid "NULL directory in find_file"
msgstr "ÐИШТÐÐ’ÐРдиректоријум у пронађи_датотеку"
-#: files.c:542
+#: files.c:553
msgid "one or more PCH files were found, but they were invalid"
msgstr "једна или више ПЦХ датотека је пронађено, али Ñу неиÑправне"
-#: files.c:545
+#: files.c:556
msgid "use -Winvalid-pch for more information"
msgstr "кориÑтите „-Winvalid-pch“ за више података"
-#: files.c:643
+#: files.c:660
#, c-format
msgid "%s is a block device"
msgstr "%s је блок уређај"
-#: files.c:660
+#: files.c:677
#, c-format
msgid "%s is too large"
msgstr "%s је превелико"
-#: files.c:700
+#: files.c:717
#, c-format
msgid "%s is shorter than expected"
msgstr "%s је краће од очекиваног"
-#: files.c:935
+#: files.c:953
#, c-format
msgid "no include path in which to search for %s"
msgstr "нема путање укључивања у којој потражити „%s“"
-#: files.c:1363
+#: files.c:1381
msgid "Multiple include guards may be useful for:\n"
msgstr "Више чувара укључивања може бити кориÑно за:\n"
@@ -710,7 +709,7 @@ msgstr "неокончана Ñирова ниÑка"
#: lex.c:1573 lex.c:1706
msgid "invalid suffix on literal; C++11 requires a space between literal and identifier"
-msgstr ""
+msgstr "неиÑправан ÑÑƒÑ„Ð¸ÐºÑ Ñƒ ÑловноÑти; Ц++11 захтева размак између ÑловноÑти и одредника"
#: lex.c:1684
msgid "null character(s) preserved in literal"
@@ -863,36 +862,36 @@ msgstr "макро аргумент „%s“ ће бити ниÑкован у Ñ
msgid "invalid hash type %d in cpp_macro_definition"
msgstr "неиÑправна врÑта хеша %d у цпп_макро_одредници"
-#: pch.c:87 pch.c:335 pch.c:347 pch.c:365 pch.c:371 pch.c:380 pch.c:387
+#: pch.c:87 pch.c:345 pch.c:359 pch.c:377 pch.c:383 pch.c:392 pch.c:399
msgid "while writing precompiled header"
msgstr "за време упиÑивања претходно преведеног заглавља"
-#: pch.c:607
+#: pch.c:619
#, c-format
msgid "%s: not used because `%.*s' is poisoned"
msgstr "%s: није употребљено зато што је „%.*s“ отровано"
-#: pch.c:629
+#: pch.c:641
#, c-format
msgid "%s: not used because `%.*s' not defined"
msgstr "%s: није употребљено зато што „%.*s“ није одређено"
-#: pch.c:641
+#: pch.c:653
#, c-format
msgid "%s: not used because `%.*s' defined as `%s' not `%.*s'"
msgstr "%s: није употребљено зато што „%.*s“ одређено као „%s“ није „%.*s“"
-#: pch.c:682
+#: pch.c:694
#, c-format
msgid "%s: not used because `%s' is defined"
msgstr "%s: није употребљено зато што је „%s“ одређено"
-#: pch.c:702
+#: pch.c:714
#, c-format
msgid "%s: not used because `__COUNTER__' is invalid"
msgstr "%s: није употребљено зато што „__COUNTER__“ није иÑправно"
-#: pch.c:711 pch.c:886
+#: pch.c:723 pch.c:898
msgid "while reading precompiled header"
msgstr "за време читања претходно преведеног заглавља"
@@ -904,42 +903,3 @@ msgstr "откривено је дубачење за време ширења м
#: traditional.c:968
msgid "syntax error in macro parameter list"
msgstr "Ñадржајна грешка у ÑпиÑку параметара макроа"
-
-#~ msgid "too many decimal points in number"
-#~ msgstr "превише децималних тачака у броју"
-
-#~ msgid "invalid digit \"%c\" in binary constant"
-#~ msgstr "неиÑправна цифра „%c“ у бинарној конÑтанти"
-
-#~ msgid "invalid digit \"%c\" in octal constant"
-#~ msgstr "неиÑправна цифра „%c“ у окталној конÑтанти"
-
-#~ msgid "no digits in hexadecimal floating constant"
-#~ msgstr "нема цифара у хекÑадецималној покретној конÑтанти"
-
-#~ msgid "exponent has no digits"
-#~ msgstr "изложилац нема цифру"
-
-#~ msgid "hexadecimal floating constants require an exponent"
-#~ msgstr "хекÑадецималне покретне конÑтанте захтевају изложилац"
-
-#~ msgid "missing binary operator before token \"%s\""
-#~ msgstr "недоÑтаје бинарни оператор пре Ñимбола „%s“"
-
-#~ msgid "token \"%s\" is not valid in preprocessor expressions"
-#~ msgstr "Ñимбол „%s“ није иÑправан у изразима претпроцеÑора"
-
-#~ msgid "missing expression between '(' and ')'"
-#~ msgstr "недоÑтаје израз између ( и )"
-
-#~ msgid "%s with no expression"
-#~ msgstr "%s без израза"
-
-#~ msgid "operator '%s' has no right operand"
-#~ msgstr "оператор „%s“ нема деÑни операнд"
-
-#~ msgid "operator '%s' has no left operand"
-#~ msgstr "оператор „%s“ нема леви операнд"
-
-#~ msgid " ':' without preceding '?'"
-#~ msgstr " „:“ без предводећег „?“"
diff --git a/libcpp/po/tr.po b/libcpp/po/tr.po
index a25bc8ff75d..7e63bd1d9f9 100644
--- a/libcpp/po/tr.po
+++ b/libcpp/po/tr.po
@@ -1,20 +1,22 @@
# Turkish translations for cpplib messages.
# Copyright (C) 2007 Free Software Foundation, Inc.
+# This file is distributed under the same license as the gcc package.
#
# Nilgün Belma Bugüner <nilgun@buguner.name.tr>, 2001, ..., 2007.
+# Volkan Gezer <vlkngzr@gmail.com>, 2013.
msgid ""
msgstr ""
-"Project-Id-Version: cpplib 4.2.0\n"
+"Project-Id-Version: cpplib 4.8.0\n"
"Report-Msgid-Bugs-To: http://gcc.gnu.org/bugs.html\n"
-"POT-Creation-Date: 2013-02-24 01:05+0000\n"
-"PO-Revision-Date: 2007-05-23 01:17+0300\n"
-"Last-Translator: Nilgün Belma Bugüner <nilgun@buguner.name.tr>\n"
+"POT-Creation-Date: 2013-03-15 17:42+0000\n"
+"PO-Revision-Date: 2013-11-01 22:29+0100\n"
+"Last-Translator: Volkan Gezer <vlkngzr@gmail.com>\n"
"Language-Team: Turkish <gnu-tr-u12a@lists.sourceforge.net>\n"
"Language: tr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Generator: KBabel 1.11.4\n"
+"X-Generator: Lokalize 1.5\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: charset.c:673
@@ -121,10 +123,9 @@ msgid "non-ISO-standard escape sequence, '\\%c'"
msgstr "ISO standardı olmayan önceleme dizgesi, '\\%c'"
#: charset.c:1320
-#, fuzzy, c-format
-#| msgid "unknown escape sequence '\\%c'"
+#, c-format
msgid "unknown escape sequence: '\\%c'"
-msgstr "bilinmeyen önceleme dizgesi '\\%c'"
+msgstr "bilinmeyen kaçış dizgesi: '\\%c'"
#: charset.c:1328
#, c-format
@@ -163,10 +164,9 @@ msgid "#%s is a GCC extension"
msgstr "#%s bir GCC uzantısıdır"
#: directives.c:362
-#, fuzzy, c-format
-#| msgid "#%s is a GCC extension"
+#, c-format
msgid "#%s is a deprecated GCC extension"
-msgstr "#%s bir GCC uzantısıdır"
+msgstr "#%s eskimiş bir GCC uzantısıdır"
#: directives.c:375
msgid "suggest not using #elif in traditional C"
@@ -247,7 +247,7 @@ msgstr "satır yönergesinde geçersiz \"%s\" seçeneği"
#: directives.c:909
msgid "unexpected end of file after #line"
-msgstr ""
+msgstr "#line satırından sonra beklenmeyen dosya sonu"
#: directives.c:912
#, c-format
@@ -271,7 +271,7 @@ msgstr "#'dan sonraki \"%s\" bir pozitif tamsayı değil"
#: directives.c:1068 directives.c:1070 directives.c:1072 directives.c:1658
#, c-format
msgid "%s"
-msgstr ""
+msgstr "%s"
#: directives.c:1096
#, c-format
@@ -312,16 +312,12 @@ msgid "#pragma once in main file"
msgstr "main dosyasında '#pragma once'"
#: directives.c:1462
-#, fuzzy
-#| msgid "invalid #pragma GCC poison directive"
msgid "invalid #pragma push_macro directive"
-msgstr "geçersiz #pragma GCC poison yönergesi"
+msgstr "geçersiz #pragma güdümlü_makro yönergesi"
#: directives.c:1517
-#, fuzzy
-#| msgid "invalid #pragma GCC poison directive"
msgid "invalid #pragma pop_macro directive"
-msgstr "geçersiz #pragma GCC poison yönergesi"
+msgstr "geçersiz #pragma güdümlü_makro yönergesi"
#: directives.c:1572
msgid "invalid #pragma GCC poison directive"
@@ -347,10 +343,9 @@ msgid "current file is older than %s"
msgstr "mevcut dosya %s den daha eski"
#: directives.c:1653
-#, fuzzy, c-format
-#| msgid "invalid #pragma GCC poison directive"
+#, c-format
msgid "invalid \"#pragma GCC %s\" directive"
-msgstr "geçersiz #pragma GCC poison yönergesi"
+msgstr "geçersiz \"#pragma GCC %s\" yönergesi"
#: directives.c:1847
msgid "_Pragma takes a parenthesized string literal"
@@ -405,7 +400,7 @@ msgstr "dayanak bir tanımlayıcı olmalı"
msgid "\"%s\" re-asserted"
msgstr "\"%s\" tekrar olumlanmış"
-#: directives.c:2566
+#: directives.c:2567
#, c-format
msgid "unterminated #%s"
msgstr "sonlandırılmamış #%s"
@@ -424,16 +419,12 @@ msgid "%s: %s"
msgstr "%s: %s"
#: expr.c:479 expr.c:577
-#, fuzzy
-#| msgid "imaginary constants are a GCC extension"
msgid "fixed-point constants are a GCC extension"
-msgstr "sanal sabitler bir GCC geniÅŸletmesidir"
+msgstr "sabit noktalı sabitler bir GCC uzantısıdır"
#: expr.c:504
-#, fuzzy
-#| msgid "invalid suffix \"%.*s\" on floating constant"
msgid "invalid prefix \"0b\" for floating constant"
-msgstr "gerçel sabitin \"%.*s\" soneki geçersiz"
+msgstr "kayan nokta için geçerisz \"0b\" öntakısı"
#: expr.c:514
msgid "use of C99 hexadecimal floating constant"
@@ -450,10 +441,8 @@ msgid "traditional C rejects the \"%.*s\" suffix"
msgstr "geleneksel C \"%.*s\" sonekini kullanmaz"
#: expr.c:564
-#, fuzzy
-#| msgid "imaginary constants are a GCC extension"
msgid "suffix for double constant is a GCC extension"
-msgstr "sanal sabitler bir GCC geniÅŸletmesidir"
+msgstr "çift sabit için öntakı bir GCC uzantısıdır"
#: expr.c:570
#, c-format
@@ -461,10 +450,8 @@ msgid "invalid suffix \"%.*s\" with hexadecimal floating constant"
msgstr "onaltılık kayan sabitli \"%.*s\" soneki geçersiz"
#: expr.c:581
-#, fuzzy
-#| msgid "imaginary constants are a GCC extension"
msgid "decimal float constants are a GCC extension"
-msgstr "sanal sabitler bir GCC geniÅŸletmesidir"
+msgstr "onluk kayan sabitler bir GCC uzantısıdır"
#: expr.c:599
#, c-format
@@ -472,10 +459,8 @@ msgid "invalid suffix \"%.*s\" on integer constant"
msgstr "tamsayı sabitte sonek \"%.*s\" soneki geçersiz"
#: expr.c:624
-#, fuzzy
-#| msgid "use of C99 long long integer constant"
msgid "use of C++0x long long integer constant"
-msgstr "ISO C99 long long tamsayı sabitleri yasaklar"
+msgstr "ISO C++0x long long tamsayı sabitlerinin kullanımı"
#: expr.c:625
msgid "use of C99 long long integer constant"
@@ -486,10 +471,8 @@ msgid "imaginary constants are a GCC extension"
msgstr "sanal sabitler bir GCC geniÅŸletmesidir"
#: expr.c:644
-#, fuzzy
-#| msgid "imaginary constants are a GCC extension"
msgid "binary constants are a GCC extension"
-msgstr "sanal sabitler bir GCC geniÅŸletmesidir"
+msgstr "ikili sabitler bir GCC uzantısıdır"
#: expr.c:737
msgid "integer constant is too large for its type"
@@ -517,10 +500,8 @@ msgid "this use of \"defined\" may not be portable"
msgstr "\"defined\" bu kullanımıyla uyarlanabilir olmayabilir"
#: expr.c:948
-#, fuzzy
-#| msgid "integer overflow in preprocessor expression"
msgid "user-defined literal in preprocessor expression"
-msgstr "önişlemci ifadesinde tamsayı taşması"
+msgstr "önişleyici ifadesinde kullanıcı tanımlı bağımlı"
#: expr.c:953
msgid "floating constant in preprocessor expression"
@@ -536,20 +517,17 @@ msgid "\"%s\" is not defined"
msgstr "\"%s\" tanımlı değil"
#: expr.c:1020
-#, fuzzy
-#| msgid "#%s is a GCC extension"
msgid "assertions are a GCC extension"
-msgstr "#%s bir GCC uzantısıdır"
+msgstr "belirteçler bir GCC uzantısıdır"
#: expr.c:1023
msgid "assertions are a deprecated extension"
-msgstr ""
+msgstr "belirteçler artık kullanılmayan bir ifadedir"
#: expr.c:1268
-#, fuzzy, c-format
-#| msgid "unbalanced stack in #if"
+#, c-format
msgid "unbalanced stack in %s"
-msgstr "#if ifadesinde karşılıksız yığın"
+msgstr "%s içinde dengelenmemiş yığın"
#: expr.c:1288
#, c-format
@@ -594,39 +572,39 @@ msgstr "#if'in teriminde virgül"
msgid "division by zero in #if"
msgstr "#if içinde sıfırla bölme"
-#: files.c:504
+#: files.c:505
msgid "NULL directory in find_file"
msgstr "find_file içinde boş dizin"
-#: files.c:542
+#: files.c:553
msgid "one or more PCH files were found, but they were invalid"
msgstr "bir veya daha fazla PCH dosyası bulundu ama bunlar geçersiz"
-#: files.c:545
+#: files.c:556
msgid "use -Winvalid-pch for more information"
msgstr "daha fazla bilgi almak için -Winvalid-pch kullanın"
-#: files.c:643
+#: files.c:660
#, c-format
msgid "%s is a block device"
msgstr "%s bir blok aygıtıdır"
-#: files.c:660
+#: files.c:677
#, c-format
msgid "%s is too large"
msgstr "%s çok büyük"
-#: files.c:700
+#: files.c:717
#, c-format
msgid "%s is shorter than expected"
msgstr "%s beklenenden daha kısa"
-#: files.c:935
+#: files.c:953
#, c-format
msgid "no include path in which to search for %s"
msgstr "%s için aranacaklar içinde başlık dosyaları yolu yok"
-#: files.c:1363
+#: files.c:1381
msgid "Multiple include guards may be useful for:\n"
msgstr "Çoklu include önlemleri aşağıdakiler için kullanışlı olabilir:\n"
@@ -717,27 +695,24 @@ msgstr "__VA_ARGS__ sadece argümanlarının sayısı değişebilen bir C99 mak
#: lex.c:1178 lex.c:1255
#, c-format
msgid "identifier \"%s\" is a special operator name in C++"
-msgstr ""
+msgstr "\"%s\" belirteci, C++'da özel bir işleç adıdır"
#: lex.c:1399
msgid "raw string delimiter longer than 16 characters"
-msgstr ""
+msgstr "ham dizge ayracı 16 karakterden uzun"
#: lex.c:1402
-#, fuzzy, c-format
-#| msgid "universal character %.*s is not valid in an identifier"
+#, c-format
msgid "invalid character '%c' in raw string delimiter"
-msgstr "evrensel karakter %.*s bir belirteç içinde geçerli değil"
+msgstr "ham dizge ayracında geçersiz karakter '%c'"
#: lex.c:1525 lex.c:1547
-#, fuzzy
-#| msgid "unterminated #%s"
msgid "unterminated raw string"
-msgstr "sonlandırılmamış #%s"
+msgstr "bitirilmemiÅŸ ham dizge"
#: lex.c:1573 lex.c:1706
msgid "invalid suffix on literal; C++11 requires a space between literal and identifier"
-msgstr ""
+msgstr "geçersiz ifade soneki; C++11 ifade ve tanımlayıcı arasında bir boşluk gerektirir"
#: lex.c:1684
msgid "null character(s) preserved in literal"
@@ -785,7 +760,7 @@ msgstr "tarih ve saat saptanamadı"
#: macro.c:377
msgid "__COUNTER__ expanded inside directive with -fdirectives-only"
-msgstr ""
+msgstr "__COUNTER__ -fdirectives-only ile talimat içerisinde genişletildi"
#: macro.c:535
msgid "invalid string literal, ignoring final '\\'"
@@ -823,7 +798,7 @@ msgstr "işlev benzeri makro \"%s\" geleneksel C'de argümanlarla kullanılmalı
#: macro.c:1746
#, c-format
msgid "invoking macro %s argument %d: empty macro arguments are undefined in ISO C90 and ISO C++98"
-msgstr ""
+msgstr "%s makrosu %d argümanı uygulanıyor: ISO C90 ve ISO C++98 içerisinde boş makro argümanları tanımsızdır"
#: macro.c:2708
#, c-format
@@ -890,38 +865,36 @@ msgstr "makro argümanı \"%s\" geleneksel C'de dizgelenmiş olmalıydı"
msgid "invalid hash type %d in cpp_macro_definition"
msgstr "cpp_macro_definition içindeki isimli yapı türü %d geçersiz"
-#: pch.c:87 pch.c:335 pch.c:347 pch.c:365 pch.c:371 pch.c:380 pch.c:387
+#: pch.c:87 pch.c:345 pch.c:359 pch.c:377 pch.c:383 pch.c:392 pch.c:399
msgid "while writing precompiled header"
msgstr "önderlemeli başlık yazılırken"
-#: pch.c:607
-#, fuzzy, c-format
-#| msgid "%s: not used because `%s' is defined"
+#: pch.c:619
+#, c-format
msgid "%s: not used because `%.*s' is poisoned"
-msgstr "%s: `%s' tanımlı olduğundan kullanılmadı"
+msgstr "%s: `%.*s' zehirli olduğu için kullanılmadı"
-#: pch.c:629
+#: pch.c:641
#, c-format
msgid "%s: not used because `%.*s' not defined"
msgstr "%s: `%.*s' tanımlı olmadığından kullanılmadı"
-#: pch.c:641
+#: pch.c:653
#, c-format
msgid "%s: not used because `%.*s' defined as `%s' not `%.*s'"
msgstr "%s: `%.*s' kullanılmadı çünkü `%s' olarak tanımlı, `%.*s' değil"
-#: pch.c:682
+#: pch.c:694
#, c-format
msgid "%s: not used because `%s' is defined"
msgstr "%s: `%s' tanımlı olduğundan kullanılmadı"
-#: pch.c:702
-#, fuzzy, c-format
-#| msgid "%s: not used because `%s' is defined"
+#: pch.c:714
+#, c-format
msgid "%s: not used because `__COUNTER__' is invalid"
-msgstr "%s: `%s' tanımlı olduğundan kullanılmadı"
+msgstr "%s: `__COUNTER__' geçersiz olduğundan kullanılmadı"
-#: pch.c:711 pch.c:886
+#: pch.c:723 pch.c:898
msgid "while reading precompiled header"
msgstr "önderlemeli başlık okunurken"
diff --git a/libdecnumber/ChangeLog b/libdecnumber/ChangeLog
index fb88bcc5c28..52b517854a2 100644
--- a/libdecnumber/ChangeLog
+++ b/libdecnumber/ChangeLog
@@ -1,3 +1,11 @@
+2013-10-15 David Malcolm <dmalcolm@redhat.com>
+
+ * Makefile.in (PICFLAG): New.
+ (ALL_CFLAGS): Add PICFLAG.
+ * configure.ac: Add --enable-host-shared, setting up new
+ PICFLAG variable.
+ * configure: Regenerate.
+
2013-07-09 Simon Baldwin <simonb@google.com>
* configure.ac: Add AC_CONFIG_AUX_DIR.
diff --git a/libdecnumber/Makefile.in b/libdecnumber/Makefile.in
index e67ff272f72..b6f3842b0d2 100644
--- a/libdecnumber/Makefile.in
+++ b/libdecnumber/Makefile.in
@@ -40,6 +40,7 @@ INSTALL_PROGRAM = @INSTALL_PROGRAM@
LDFLAGS = @LDFLAGS@
LIBICONV = @LIBICONV@
PACKAGE = @PACKAGE@
+PICFLAG = @PICFLAG@
RANLIB = @RANLIB@
SHELL = @SHELL@
objext = @OBJEXT@
@@ -57,7 +58,7 @@ enable_decimal_float= @enable_decimal_float@
INCLUDES = -I$(srcdir) -I.
-ALL_CFLAGS = $(CFLAGS) $(WARN_CFLAGS) $(INCLUDES) $(CPPFLAGS)
+ALL_CFLAGS = $(CFLAGS) $(WARN_CFLAGS) $(INCLUDES) $(CPPFLAGS) $(PICFLAG)
bid_OBJS = bid2dpd_dpd2bid.$(objext) host-ieee32.$(objext) \
host-ieee64.$(objext) host-ieee128.$(objext)
diff --git a/libdecnumber/aclocal.m4 b/libdecnumber/aclocal.m4
index e30869c5b9a..766af164a6a 100644
--- a/libdecnumber/aclocal.m4
+++ b/libdecnumber/aclocal.m4
@@ -1,4 +1,4 @@
-# generated automatically by aclocal 1.13.3 -*- Autoconf -*-
+# generated automatically by aclocal 1.14 -*- Autoconf -*-
# Copyright (C) 1996-2013 Free Software Foundation, Inc.
diff --git a/libdecnumber/configure b/libdecnumber/configure
index 4a1896e1b97..2720f46ff7f 100755
--- a/libdecnumber/configure
+++ b/libdecnumber/configure
@@ -593,6 +593,7 @@ ac_includes_default="\
ac_subst_vars='LTLIBOBJS
LIBOBJS
+PICFLAG
ADDITIONAL_OBJS
enable_decimal_float
target_os
@@ -670,6 +671,7 @@ enable_option_checking
enable_werror_always
enable_maintainer_mode
enable_decimal_float
+enable_host_shared
'
ac_precious_vars='build_alias
host_alias
@@ -1301,6 +1303,7 @@ Optional Features:
enable decimal float extension to C. Selecting 'bid'
or 'dpd' choses which decimal floating point format
to use
+ --enable-host-shared build host code as shared libraries
Some influential environment variables:
CC C compiler command
@@ -4889,6 +4892,16 @@ $as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h
esac
+# 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
+
+
+
# Output.
ac_config_headers="$ac_config_headers config.h:config.in"
diff --git a/libdecnumber/configure.ac b/libdecnumber/configure.ac
index 6cfc8033eae..dd0499c43f6 100644
--- a/libdecnumber/configure.ac
+++ b/libdecnumber/configure.ac
@@ -95,6 +95,13 @@ AC_SUBST(ADDITIONAL_OBJS)
AC_C_BIGENDIAN
+# 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(PICFLAG)
+
# Output.
AC_CONFIG_HEADERS(config.h:config.in, [echo timestamp > stamp-h1])
diff --git a/libffi/ChangeLog b/libffi/ChangeLog
index 77a949d13e5..6846f51cd03 100644
--- a/libffi/ChangeLog
+++ b/libffi/ChangeLog
@@ -1,3 +1,7 @@
+2013-09-20 Alan Modra <amodra@gmail.com>
+
+ * configure: Regenerate.
+
2013-06-25 Alan Modra <amodra@gmail.com>
* src/powerpc/ffi.c (ffi_prep_args_SYSV): Move var declaration
diff --git a/libffi/configure b/libffi/configure
index ce6c8adced7..cb959174d00 100755
--- a/libffi/configure
+++ b/libffi/configure
@@ -6392,7 +6392,7 @@ ia64-*-hpux*)
rm -rf conftest*
;;
-x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \
+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
@@ -6417,7 +6417,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
;;
esac
;;
- ppc64-*linux*|powerpc64-*linux*)
+ powerpc64le-*linux*)
+ LD="${LD-ld} -m elf32lppclinux"
+ ;;
+ powerpc64-*linux*)
LD="${LD-ld} -m elf32ppclinux"
;;
s390x-*linux*)
@@ -6436,7 +6439,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
x86_64-*linux*)
LD="${LD-ld} -m elf_x86_64"
;;
- ppc*-*linux*|powerpc*-*linux*)
+ powerpcle-*linux*)
+ LD="${LD-ld} -m elf64lppc"
+ ;;
+ powerpc-*linux*)
LD="${LD-ld} -m elf64ppc"
;;
s390*-*linux*|s390*-*tpf*)
@@ -10900,7 +10906,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 10903 "configure"
+#line 10909 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -11006,7 +11012,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11009 "configure"
+#line 11015 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog
index 5f503617658..81556a300e9 100644
--- a/libgcc/ChangeLog
+++ b/libgcc/ChangeLog
@@ -1,3 +1,246 @@
+2013-11-11 Eric Botcazou <ebotcazou@adacore.com>
+
+ * config.host (arm-wrs-vxworks): Replace arm/t-vxworks with arm/t-elf
+ in tmake_file.
+ * config/arm/t-vxworks: Delete.
+
+2013-11-10 Kai Tietz <ktietz@redhat.com>
+
+ * config/i386/cygming-crtbegin.c (__gcc_register_frame):
+ Increment load-count on use of LIBGCC_SONAME DLL.
+ (hmod_libgcc): New static variable to hold handle of
+ LIBGCC_SONAME DLL.
+ (__gcc_deregister_frame): Decrement load-count of
+ LIBGCC_SONAME DLL.
+
+2013-11-08 Bernhard Reutner-Fischer <aldot@gcc.gnu.org>
+
+ * configure.ac (libgcc_cv_dfp): Extend check to probe fenv.h
+ availability.
+ * configure: Regenerate
+
+2013-11-07 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/sfp-exceptions.c (__sfp_handle_exceptions): Handle
+ FP_EX_DENORM. Store result to volatile location after SSE division
+ to close interrupt window. Remove unneeded fwait after x87
+ division since interrupt window will be closed by emitted fstp.
+ Rewrite FP_EX_INEXACT handling.
+
+2013-11-06 Joseph Myers <joseph@codesourcery.com>
+
+ * soft-fp/README: Update.
+ * soft-fp/adddf3.c: Update from glibc.
+ * soft-fp/addsf3.c: Likewise.
+ * soft-fp/addtf3.c: Likewise.
+ * soft-fp/divdf3.c: Likewise.
+ * soft-fp/divsf3.c: Likewise.
+ * soft-fp/divtf3.c: Likewise.
+ * soft-fp/double.h: Likewise.
+ * soft-fp/eqdf2.c: Likewise.
+ * soft-fp/eqsf2.c: Likewise.
+ * soft-fp/eqtf2.c: Likewise.
+ * soft-fp/extenddftf2.c: Likewise.
+ * soft-fp/extended.h: Likewise.
+ * soft-fp/extendsfdf2.c: Likewise.
+ * soft-fp/extendsftf2.c: Likewise.
+ * soft-fp/extendxftf2.c: Likewise.
+ * soft-fp/fixdfdi.c: Likewise.
+ * soft-fp/fixdfsi.c: Likewise.
+ * soft-fp/fixdfti.c: Likewise.
+ * soft-fp/fixsfdi.c: Likewise.
+ * soft-fp/fixsfsi.c: Likewise.
+ * soft-fp/fixsfti.c: Likewise.
+ * soft-fp/fixtfdi.c: Likewise.
+ * soft-fp/fixtfsi.c: Likewise.
+ * soft-fp/fixtfti.c: Likewise.
+ * soft-fp/fixunsdfdi.c: Likewise.
+ * soft-fp/fixunsdfsi.c: Likewise.
+ * soft-fp/fixunsdfti.c: Likewise.
+ * soft-fp/fixunssfdi.c: Likewise.
+ * soft-fp/fixunssfsi.c: Likewise.
+ * soft-fp/fixunssfti.c: Likewise.
+ * soft-fp/fixunstfdi.c: Likewise.
+ * soft-fp/fixunstfsi.c: Likewise.
+ * soft-fp/fixunstfti.c: Likewise.
+ * soft-fp/floatdidf.c: Likewise.
+ * soft-fp/floatdisf.c: Likewise.
+ * soft-fp/floatditf.c: Likewise.
+ * soft-fp/floatsidf.c: Likewise.
+ * soft-fp/floatsisf.c: Likewise.
+ * soft-fp/floatsitf.c: Likewise.
+ * soft-fp/floattidf.c: Likewise.
+ * soft-fp/floattisf.c: Likewise.
+ * soft-fp/floattitf.c: Likewise.
+ * soft-fp/floatundidf.c: Likewise.
+ * soft-fp/floatundisf.c: Likewise.
+ * soft-fp/floatunditf.c: Likewise.
+ * soft-fp/floatunsidf.c: Likewise.
+ * soft-fp/floatunsisf.c: Likewise.
+ * soft-fp/floatunsitf.c: Likewise.
+ * soft-fp/floatuntidf.c: Likewise.
+ * soft-fp/floatuntisf.c: Likewise.
+ * soft-fp/floatuntitf.c: Likewise.
+ * soft-fp/gedf2.c: Likewise.
+ * soft-fp/gesf2.c: Likewise.
+ * soft-fp/getf2.c: Likewise.
+ * soft-fp/ledf2.c: Likewise.
+ * soft-fp/lesf2.c: Likewise.
+ * soft-fp/letf2.c: Likewise.
+ * soft-fp/muldf3.c: Likewise.
+ * soft-fp/mulsf3.c: Likewise.
+ * soft-fp/multf3.c: Likewise.
+ * soft-fp/negdf2.c: Likewise.
+ * soft-fp/negsf2.c: Likewise.
+ * soft-fp/negtf2.c: Likewise.
+ * soft-fp/op-1.h: Likewise.
+ * soft-fp/op-2.h: Likewise.
+ * soft-fp/op-4.h: Likewise.
+ * soft-fp/op-8.h: Likewise.
+ * soft-fp/op-common.h: Likewise.
+ * soft-fp/quad.h: Likewise.
+ * soft-fp/single.h: Likewise.
+ * soft-fp/soft-fp.h: Likewise.
+ * soft-fp/subdf3.c: Likewise.
+ * soft-fp/subsf3.c: Likewise.
+ * soft-fp/subtf3.c: Likewise.
+ * soft-fp/truncdfsf2.c: Likewise.
+ * soft-fp/trunctfdf2.c: Likewise.
+ * soft-fp/trunctfsf2.c: Likewise.
+ * soft-fp/trunctfxf2.c: Likewise.
+ * soft-fp/unorddf2.c: Likewise.
+ * soft-fp/unordsf2.c: Likewise.
+ * soft-fp/unordtf2.c: Likewise.
+
+2013-11-05 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/32/sfp-machine.h (_FP_MUL_MEAT_S): Define.
+ (_FP_MUL_MEAT_D): Ditto.
+ (_FP_DIV_MEAT_S): Ditto.
+ (_FP_DIV_MEAT_D): Ditto.
+ * config.host (i[34567]86-*-rtems*): Remove i386/t-softfp, add
+ t-softfp-sfdf and t-softfp to tmake_file.
+
+2013-11-03 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/crtfastmath.c: Compile only for !_SOFT_FLOAT.
+ * config/i386/crtprec.c: Ditto.
+
+2013-10-31 Chung-Ju Wu <jasonwucj@gmail.com>
+ Shiva Chen <shiva0217@gmail.com>
+
+ * config.host (nds32*-elf*): Add nds32 target.
+ * config/nds32 : New directory and files.
+
+2013-10-16 Hans-Peter Nilsson <hp@axis.com>
+
+ For CRIS ports, switch to soft-fp. Improve arit.c and longlong.h.
+ * config.host (cpu_type) <Setting default>: Add entry for
+ crisv32-*-*.
+ (tmake_file) <crisv32-*-elf, cris-*-elf, cris-*-linux*>
+ <crisv32-*-linux*>: Adjust.
+ * longlong.h: Wrap the whole CRIS section in a single
+ defined(__CRIS__) conditional. Add comment about add_ssaaaa
+ and sub_ddmmss.
+ (COUNT_LEADING_ZEROS_0): Define when count_leading_zeros is
+ defined.
+ [__CRIS__] (__umulsidi3): Define.
+ [__CRIS__] (umul_ppmm): Define in terms of __umulsidi3.
+ * config/cris/sfp-machine.h: New file.
+ * config/cris/umulsidi3.S: New file.
+ * config/cris/t-elfmulti (LIB2ADD_ST): Add umulsidi3.S.
+ * config/cris/arit.c (SIGNMULT): New macro.
+ (__Div, __Mod): Use SIGNMULT instead of naked multiplication.
+ * config/cris/mulsi3.S: Tweak to avoid redundant register-copying;
+ saving 3 out of originally 33 cycles from the fastest
+ path, 3 out of 54 from the medium path and one from the longest
+ path. Improve comments.
+
+2013-10-15 Richard Sandiford <rdsandiford@googlemail.com>
+
+ * sync.c: Remove static aliases and define each function directly
+ under its real name.
+
+2013-10-02 John David Anglin <danglin@gcc.gnu.org>
+
+ * config.host (hppa*64*-*-linux*): Define extra_parts.
+ (hppa*-*-linux*): Likewise.
+
+2013-10-02 Joern Rennecke <joern.rennecke@embecosm.com>
+
+ * config/arc/crtgend.S: Add 2013 to Copyright years.
+ * config/arc/gmon/atomic.h: Likewise.
+ * config/arc/gmon/auxreg.h: Likewise.
+ * config/arc/gmon/sys/gmon_out.h: Likewise.
+ * config/arc/gmon/sys/gmon.h: Likewise.
+ * config/arc/gmon/prof-freq.c: Likewise.
+ * config/arc/gmon/mcount.c: Likewise.
+ * config/arc/gmon/prof-freq-stub.S: Likewise.
+ * config/arc/gmon/gmon.c: Likewise.
+ * config/arc/gmon/machine-gmon.h: Likewise.
+ * config/arc/gmon/profil.S: Likewise.
+ * config/arc/gmon/dcache_linesz.S: Likewise.
+ * config/arc/crtg.S: Likewise.
+ * config/arc/ieee-754/arc600-mul64/divsf3.S: Likewise.
+ * config/arc/ieee-754/arc600-mul64/divdf3.S: Likewise.
+ * config/arc/ieee-754/adddf3.S: Likewise.
+ * config/arc/ieee-754/truncdfsf2.S: Likewise.
+ * config/arc/ieee-754/fixsfsi.S: Likewise.
+ * config/arc/ieee-754/gtsf2.S: Likewise.
+ * config/arc/ieee-754/floatsisf.S: Likewise.
+ * config/arc/ieee-754/arc600-dsp/divsf3.S: Likewise.
+ * config/arc/ieee-754/arc600-dsp/divdf3.S: Likewise.
+ * config/arc/ieee-754/arc600-dsp/mulsf3.S: Likewise.
+ * config/arc/ieee-754/fixdfsi.S: Likewise.
+ * config/arc/ieee-754/addsf3.S: Likewise.
+ * config/arc/ieee-754/gesf2.S: Likewise.
+ * config/arc/ieee-754/floatsidf.S: Likewise.
+ * config/arc/ieee-754/extendsfdf2.S: Likewise.
+ * config/arc/ieee-754/divtab-arc-df.c: Likewise.
+ * config/arc/ieee-754/gtdf2.S: Likewise.
+ * config/arc/ieee-754/fixunsdfsi.S: Likewise.
+ * config/arc/ieee-754/uneqdf2.S: Likewise.
+ * config/arc/ieee-754/divsf3-stdmul.S: Likewise.
+ * config/arc/ieee-754/uneqsf2.S: Likewise.
+ * config/arc/ieee-754/arc-ieee-754.h: Likewise.
+ * config/arc/ieee-754/divtab-arc-sf.c: Likewise.
+ * config/arc/ieee-754/eqdf2.S: Likewise.
+ * config/arc/ieee-754/ordsf2.S: Likewise.
+ * config/arc/ieee-754/divsf3.S: Likewise.
+ * config/arc/ieee-754/divdf3.S: Likewise.
+ * config/arc/ieee-754/floatunsidf.S: Likewise.
+ * config/arc/ieee-754/orddf2.S: Likewise.
+ * config/arc/ieee-754/eqsf2.S: Likewise.
+ * config/arc/ieee-754/gedf2.S: Likewise.
+ * config/arc/crtn.S: Likewise.
+ * config/arc/crti.S: Likewise.
+ * config/arc/t-arc700-uClibc: Likewise.
+ * config/arc/asm.h: Likewise.
+ * config/arc/libgcc-excl.ver: Likewise.
+ * config/arc/t-arc-newlib: Likewise.
+ * config/arc/divtab-arc700.c: Likewise.
+ * config/arc/initfini.c: Likewise.
+ * config/arc/fp-hack.h: Likewise.
+
+2013-10-01 Joern Rennecke <joern.rennecke@embecosm.com>
+ Diego Novillo <dnovillo@google.com>
+
+ * config/arc/gmon/mcount.c (_MCOUNT_DECL): Comment typo fix.
+ * config/arc/ieee-754/arc600-dsp/muldf3.S (.Linf_denorm): Likewise.
+ * config/arc/ieee-754/arc600-mul64/muldf3.S (.Linf_denorm): Likewise.
+ * config/arc/ieee-754/muldf3.S (.Linf_denorm): Likewise.
+
+2013-10-01 Joern Rennecke <joern.rennecke@embecosm.com>
+ Brendan Kehoe <brendan@zen.org>
+ Simon Cook <simon.cook@embecosm.com>
+
+ * config.host (arc*-*-elf*, arc*-*-linux-uclibc*): New configurations.
+ * config/arc: New directory.
+ * longlong.h [__arc__] (umul_ppmm): Remove.
+ [__arc__] (__umulsidi3): Define.
+ [__arc__ && __ARC_NORM__] (count_leading_zeroes): Define.
+ [__arc__ && __ARC_NORM__] (COUNT_LEADING_ZEROS_0): Likewise.
+
2013-09-17 Jacek Caban <jacek@codeweavers.com>
* config/i386/gthr-win32.c: CreateSemaphoreW instead of
@@ -39,8 +282,8 @@
(__gcov_indirect_call_counters): Likewise.
2013-08-16 Maciej W. Rozycki <macro@codesourcery.com>
- Catherine Moore <clm@codesourcery.com>
- Richard Sandiford <rdsandiford@googlemail.com>
+ Catherine Moore <clm@codesourcery.com>
+ Richard Sandiford <rdsandiford@googlemail.com>
* config/mips/mips16.S (CE_STARTFN, CE_ENDFN): New macros.
(RET_FUNCTION): Use them in place of STARTFN and ENDFN.
@@ -370,7 +613,7 @@
* config/sh/lib1funcs.S (udivsi3_i4i, sdivsi3_i4i): Add __SH2A__ to
inclusion list.
-2013-03-04 Edgar E. Iglesias <edgar.iglesias@gmail.com>
+2013-03-04 Edgar E. Iglesias <edgar.iglesias@gmail.com>
* config/microblaze/crti.S: Setup stack protection at entry
@@ -481,7 +724,7 @@
_divQQ, _divHQ, _divHA, _divSA,
_divUQQ, _divUHQ, _divUHA, _divUSA.
-2013-01-26 David Holsgrove <david.holsgrove@xilinx.com>
+2013-01-26 David Holsgrove <david.holsgrove@xilinx.com>
* config.host(microblaze*-linux*): tmake_file: Remove
t-slibgcc-nolc-override, add t-slibgcc-libgcc.
@@ -489,7 +732,7 @@
to exclude functions from being built with libgcc.c and use
the microblaze assembly.
-2013-01-26 Edgar E. Iglesias <edgar.iglesias@gmail.com>
+2013-01-26 Edgar E. Iglesias <edgar.iglesias@gmail.com>
* config.host (microblaze*-*-*): Rename microblaze*-*-elf, update
extra_parts.
diff --git a/libgcc/Makefile.in b/libgcc/Makefile.in
index 354fb72d984..0d91cfc2d91 100644
--- a/libgcc/Makefile.in
+++ b/libgcc/Makefile.in
@@ -858,7 +858,7 @@ LIBGCOV = _gcov _gcov_merge_add _gcov_merge_single _gcov_merge_delta \
_gcov_execv _gcov_execvp _gcov_execve _gcov_reset _gcov_dump \
_gcov_interval_profiler _gcov_pow2_profiler _gcov_one_value_profiler \
_gcov_indirect_call_profiler _gcov_average_profiler _gcov_ior_profiler \
- _gcov_merge_ior _gcov_indirect_call_profiler_v2
+ _gcov_merge_ior _gcov_time_profiler _gcov_indirect_call_profiler_v2 _gcov_merge_time_profile
libgcov-objects = $(patsubst %,%$(objext),$(LIBGCOV))
diff --git a/libgcc/config.host b/libgcc/config.host
index 1fa3a654131..8feb8f2bd04 100644
--- a/libgcc/config.host
+++ b/libgcc/config.host
@@ -91,6 +91,9 @@ alpha*-*-*)
am33_2.0-*-linux*)
cpu_type=mn10300
;;
+arc*-*-*)
+ cpu_type=arc
+ ;;
arm*-*-*)
cpu_type=arm
;;
@@ -102,6 +105,9 @@ bfin*-*)
;;
cr16-*-*)
;;
+crisv32-*-*)
+ cpu_type=cris
+ ;;
fido-*-*)
cpu_type=m68k
;;
@@ -137,6 +143,9 @@ mips*-*-*)
cpu_type=mips
tmake_file=mips/t-mips
;;
+nds32*-*)
+ cpu_type=nds32
+ ;;
powerpc*-*-*)
cpu_type=rs6000
;;
@@ -315,8 +324,16 @@ alpha*-dec-*vms*)
extra_parts="$extra_parts vms-dwarf2.o vms-dwarf2eh.o"
md_unwind_header=alpha/vms-unwind.h
;;
+arc*-*-elf*)
+ tmake_file="arc/t-arc-newlib arc/t-arc"
+ extra_parts="crti.o crtn.o crtend.o crtbegin.o crtendS.o crtbeginS.o libgmon.a crtg.o crtgend.o"
+ ;;
+arc*-*-linux-uclibc*)
+ tmake_file="${tmake_file} t-slibgcc-libgcc t-slibgcc-nolc-override arc/t-arc700-uClibc arc/t-arc"
+ extra_parts="crti.o crtn.o crtend.o crtbegin.o crtendS.o crtbeginS.o libgmon.a crtg.o crtgend.o"
+ ;;
arm-wrs-vxworks)
- tmake_file="$tmake_file arm/t-arm arm/t-vxworks t-softfp-sfdf t-softfp-excl arm/t-softfp t-softfp"
+ tmake_file="$tmake_file arm/t-arm arm/t-elf t-softfp-sfdf t-softfp-excl arm/t-softfp t-softfp"
extra_parts="$extra_parts crti.o crtn.o"
;;
arm*-*-netbsdelf*)
@@ -397,13 +414,13 @@ cr16-*-elf)
extra_parts="$extra_parts crti.o crtn.o crtlibid.o"
;;
crisv32-*-elf)
- tmake_file="$tmake_file cris/t-cris t-fdpbit"
+ tmake_file="$tmake_file cris/t-cris t-softfp-sfdf t-softfp"
;;
cris-*-elf)
- tmake_file="$tmake_file cris/t-cris t-fdpbit cris/t-elfmulti"
+ tmake_file="$tmake_file cris/t-cris t-softfp-sfdf t-softfp cris/t-elfmulti"
;;
cris-*-linux* | crisv32-*-linux*)
- tmake_file="$tmake_file cris/t-cris t-fdpbit cris/t-linux"
+ tmake_file="$tmake_file cris/t-cris t-softfp-sfdf t-softfp cris/t-linux"
;;
epiphany-*-elf*)
tmake_file="epiphany/t-epiphany t-fdpbit epiphany/t-custom-eqsf"
@@ -435,6 +452,7 @@ h8300-*-elf*)
;;
hppa*64*-*-linux*)
tmake_file="$tmake_file pa/t-linux pa/t-linux64"
+ extra_parts="crtbegin.o crtbeginS.o crtbeginT.o crtend.o crtendS.o"
;;
hppa*-*-linux*)
tmake_file="$tmake_file pa/t-linux t-slibgcc-libgcc"
@@ -444,6 +462,7 @@ hppa*-*-linux*)
else
tmake_file="$tmake_file pa/t-slibgcc-dwarf-ver"
fi
+ extra_parts="crtbegin.o crtbeginS.o crtbeginT.o crtend.o crtendS.o"
md_unwind_header=pa/linux-unwind.h
;;
hppa[12]*-*-hpux10*)
@@ -545,7 +564,7 @@ i[34567]86-*-nto-qnx*)
extra_parts=crtbegin.o
;;
i[34567]86-*-rtems*)
- tmake_file="$tmake_file i386/t-softfp i386/t-crtstuff"
+ tmake_file="$tmake_file i386/t-crtstuff t-softfp-sfdf t-softfp"
extra_parts="$extra_parts crti.o crtn.o"
;;
i[34567]86-*-solaris2* | x86_64-*-solaris2.1[0-9]*)
@@ -834,6 +853,29 @@ moxie-*-rtems*)
msp430*-*-elf)
tmake_file="$tm_file t-crtstuff t-fdpbit msp430/t-msp430"
;;
+nds32*-elf*)
+ # Basic makefile fragment and extra_parts for crt stuff.
+ # We also append c-isr library implementation.
+ tmake_file="${tmake_file} nds32/t-nds32 nds32/t-nds32-isr"
+ extra_parts="crtbegin1.o crtend1.o libnds32_isr.a"
+ # Append library definition makefile fragment according to --with-nds32-lib=X setting.
+ case "${with_nds32_lib}" in
+ "" | newlib)
+ # Append library definition makefile fragment t-nds32-newlib.
+ # Append 'soft-fp' software floating point make rule fragment provided by gcc.
+ tmake_file="${tmake_file} nds32/t-nds32-newlib t-softfp-sfdf t-softfp"
+ ;;
+ mculib)
+ # Append library definition makefile fragment t-nds32-mculib.
+ # The software floating point library is included in mculib.
+ tmake_file="${tmake_file} nds32/t-nds32-mculib"
+ ;;
+ *)
+ echo "Cannot accept --with-nds32-lib=$with_nds32_lib, available values are: newlib mculib" 1>&2
+ exit 1
+ ;;
+ esac
+ ;;
pdp11-*-*)
tmake_file="pdp11/t-pdp11 t-fdpbit"
;;
diff --git a/libgcc/config/arc/asm.h b/libgcc/config/arc/asm.h
new file mode 100644
index 00000000000..56356a4000c
--- /dev/null
+++ b/libgcc/config/arc/asm.h
@@ -0,0 +1,30 @@
+/* Assembler macros for the Synopsys DesignWare ARC CPU.
+
+ Copyright (C) 1994, 1995, 1997, 2004, 2007-2013
+ Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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 FUNC(X) .type X,@function
+#define ENDFUNC(X) .size X, .-X
diff --git a/libgcc/config/arc/crtg.S b/libgcc/config/arc/crtg.S
new file mode 100644
index 00000000000..6014f045881
--- /dev/null
+++ b/libgcc/config/arc/crtg.S
@@ -0,0 +1,52 @@
+/* Code to start and stop profiling for the Synopsys DesignWare ARC CPU.
+
+ Copyright (C) 1994, 1995, 1997, 2004, 2007-2013
+ Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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/>. */
+
+ .section .init
+ .global _init
+ .global _fini
+ .global __monstartup
+ mov_s r0,_init
+ mov_s r1,_fini
+ jl __monstartup
+
+ .section .__arc_profile_desc, "a"
+ .global __arc_profile_desc_secstart
+ .balign 4
+__arc_profile_desc_secstart:
+ .section .__arc_profile_forward, "a"
+ .global __arc_profile_forward_secstart
+ .balign 4
+__arc_profile_forward_secstart:
+ .section .__arc_profile_counters, "aw"
+ .global __arc_profile_counters_secstart
+ .balign 4
+__arc_profile_counters_secstart:
+
+ .section .fini
+ .global _mcleanup
+ jl _mcleanup
diff --git a/libgcc/config/arc/crtgend.S b/libgcc/config/arc/crtgend.S
new file mode 100644
index 00000000000..5db637a0c08
--- /dev/null
+++ b/libgcc/config/arc/crtgend.S
@@ -0,0 +1,34 @@
+/* Code to start and stop profiling for the Synopsys DesignWare ARC CPU.
+
+ Copyright (C) 1994, 1995, 1997, 2004, 2007-2013
+ Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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/>. */
+
+ .section .__arc_profile_desc, "a"
+ .global __arc_profile_desc_secend
+__arc_profile_desc_secend:
+ .section .__arc_profile_forward, "a"
+ .global __arc_profile_forward_secend
+__arc_profile_forward_secend:
diff --git a/libgcc/config/arc/crti.S b/libgcc/config/arc/crti.S
new file mode 100644
index 00000000000..1f3dfe14734
--- /dev/null
+++ b/libgcc/config/arc/crti.S
@@ -0,0 +1,42 @@
+/* .fini/.init stack frame setup for the Synopsys DesignWare ARC CPU.
+
+ Copyright (C) 1994, 1995, 1997, 2004, 2007-2013
+ Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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 contains the stack frame setup for contents of the .fini and
+# .init sections.
+
+ .section .init
+ .global _init
+ .word 0
+_init:
+ push_s blink
+
+ .section .fini
+ .global _fini
+ .word 0
+_fini:
+ push_s blink
diff --git a/libgcc/config/arc/crtn.S b/libgcc/config/arc/crtn.S
new file mode 100644
index 00000000000..1962d3c27cd
--- /dev/null
+++ b/libgcc/config/arc/crtn.S
@@ -0,0 +1,39 @@
+/* Ensure .fini/.init return for the Synopsys DesignWare ARC CPU.
+
+ Copyright (C) 1994, 1995, 1997, 2004, 2007-2013
+ Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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 just makes sure that the .fini and .init sections do in
+# fact return. This file is the last thing linked into any executable.
+
+ .section .init
+ pop_s blink
+ j_s [blink]
+
+
+ .section .fini
+ pop_s blink
+ j_s [blink]
diff --git a/libgcc/config/arc/divtab-arc700.c b/libgcc/config/arc/divtab-arc700.c
new file mode 100644
index 00000000000..dba0b4e3928
--- /dev/null
+++ b/libgcc/config/arc/divtab-arc700.c
@@ -0,0 +1,70 @@
+/* Copyright (C) 2004, 2006, 2007-2013 Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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.
+
+In addition to the permissions in the GNU General Public License, the
+Free Software Foundation gives you unlimited permission to link the
+compiled version of this file into combinations with other programs,
+and to distribute those combinations without any restriction coming
+from the use of this file. (The General Public License restrictions
+do apply in other respects; for example, they cover modification of
+the file, and distribution when not linked into a combine
+executable.)
+
+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.
+
+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/>. */
+
+/* Calculate division table for ARC700 integer division
+ Contributed by Joern Rennecke
+ joern.rennecke@arc.com */
+
+#include <stdio.h>
+#include <math.h>
+
+int
+main ()
+{
+ int i, j;
+ unsigned x;
+ double q, r, err, max_err = -1;
+
+ puts("/* This table has been generated by divtab-arc700.c. */");
+ puts("\
+/* 1/512 .. 1/256, normalized. There is a leading 1 in bit 31.\n\
+ For powers of two, we list unnormalized numbers instead. The values\n\
+ for powers of 2 are loaded, but not used. The value for 1 is actually\n\
+ the first instruction after .Lmuldiv. */\n\
+ .balign 4");
+ puts (".Ldivtab:\n");
+ for (i = 256; i >= 2; --i)
+ {
+ j = i < 0 ? -i : i;
+ if (j & (j-1))
+ while (j < 128)
+ j += j;
+ else
+ /* Power of two. */
+ j *= 128;
+ q = 4.*(1<<30)*128/j;
+ r = ceil (q);
+ printf ("\t.long\t0x%X\n", (unsigned) r);
+ err = r - q;
+ if (err > max_err)
+ max_err = err;
+ }
+#if 0
+ printf ("\t/* maximum error: %f */\n", max_err);
+#endif
+ exit (0);
+}
diff --git a/libgcc/config/arc/dp-hack.h b/libgcc/config/arc/dp-hack.h
new file mode 100644
index 00000000000..fcbd89cf9d7
--- /dev/null
+++ b/libgcc/config/arc/dp-hack.h
@@ -0,0 +1,101 @@
+/* Copyright (C) 2007-2013 Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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 selects the double-precision parts of fp-bit.c that are
+ still needed for some ARC hardware variants; it also renames functions
+ that duplicate asm-coded functionality so that their results can be
+ used to compare with the optimized versions for debugging. */
+
+#define FINE_GRAINED_LIBRARIES
+#define ARC_DP_DEBUG 1
+#if !defined (__ARC_NORM__) || ARC_DP_DEBUG
+#define L_pack_df
+#define L_unpack_df
+#define L_make_df
+#define L_thenan_df
+#define L_sf_to_df
+#endif
+#ifndef __ARC_NORM__
+#define L_addsub_df
+#elif ARC_DP_DEBUG
+#define L_addsub_df
+#define __adddf3 __adddf3_c
+#define __subdf3 __subdf3_c
+#endif
+#ifndef __ARC_NORM__
+#define L_mul_df
+#define L_div_df
+#elif (!defined (__ARC700__) && !defined (__ARC_MUL64__) \
+ && !defined(__ARC_MUL32BY16__))
+#define L_mul_df
+#define L_div_df
+#undef QUIET_NAN
+#define QUIET_NAN 0xfffffffffffffLL
+#elif ARC_DP_DEBUG
+#define L_mul_df
+#define __muldf3 __muldf3_c
+#define L_div_df
+#define __divdf3 __divdf3_c
+#endif
+#ifndef __ARC_NORM__
+#define L_df_to_sf
+#define L_si_to_df
+#define L_df_to_si
+#define L_tf_to_usi /* need to defined this instead of df_to_usi */
+#define L_usi_to_df
+#elif ARC_DP_DEBUG
+#define L_df_to_sf
+#define __truncdfsf2 __truncdfsf2_c
+#define L_si_to_df
+#define __floatsidf __floatsidf_c
+#define L_df_to_si
+#define __fixdfsi __fixdfsi_c
+#define L_tf_to_usi
+#define __fixunsdfsi __fixunsdfsi_c
+#define L_usi_to_df
+#define __floatunsidf __floatunsidf_c
+#endif
+#ifndef __ARC_NORM__
+#define L_fpcmp_parts_df
+#define L_compare_df
+#define L_eq_df
+#define L_ne_df
+#define L_gt_df
+#define L_ge_df
+#define L_lt_df
+#define L_le_df
+#define L_unord_df
+#define L_negate_df
+#elif ARC_DP_DEBUG
+#define L_fpcmp_parts_df
+#define L_eq_df
+#define __eqdf2 __eqdf2_c
+#define L_gt_df
+#define __gtdf2 __gtdf2_c
+#define L_ge_df
+#define __gedf2 __gedf2_c
+#define L_unord_df
+#define __unorddf2 __unorddf2_c
+#endif
diff --git a/libgcc/config/arc/fp-hack.h b/libgcc/config/arc/fp-hack.h
new file mode 100644
index 00000000000..7b1298ac1c8
--- /dev/null
+++ b/libgcc/config/arc/fp-hack.h
@@ -0,0 +1,85 @@
+/* Copyright (C) 2007-2013 Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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 selects the single-precision parts of fp-bit.c that are
+ still needed for some ARC hardware variants; it also renames functions
+ that duplicate asm-coded functionality so that their results can be
+ used to compare with the optimized versions for debugging. */
+
+#define ARC_FP_DEBUG 1
+#define FINE_GRAINED_LIBRARIES
+#if !defined (__ARC_NORM__) || ARC_FP_DEBUG
+#define L_pack_sf
+#define L_unpack_sf
+#define L_make_sf
+#define L_thenan_sf
+#endif
+#ifndef __ARC_NORM__
+#define L_addsub_sf
+#define L_mul_sf
+#define L_div_sf
+#define L_sf_to_df
+#define L_si_to_sf
+#define L_sf_to_si
+#define L_usi_to_sf
+#elif ARC_FP_DEBUG
+#define L_addsub_sf
+#define __addsf3 __addsf3_c
+#define __subsf3 __subsf3_c
+#define L_mul_sf
+#define __mulsf3 __mulsf3_c
+#define L_div_sf
+#define __divsf3 __divsf3_c
+#define L_sf_to_df
+#define __extendsfdf2 __extendsfdf2_c
+#define L_si_to_sf
+#define __floatsisf __floatsisf_c
+#define L_sf_to_si
+#define __fixsfsi __fixsfsi_c
+#define L_usi_to_sf
+#define __floatunsisf __floatunsisf_c
+#endif
+#ifndef __ARC_NORM__
+#define L_fpcmp_parts_sf
+#define L_compare_sf
+#define L_eq_sf
+#define L_ne_sf
+#define L_gt_sf
+#define L_ge_sf
+#define L_lt_sf
+#define L_le_sf
+#define L_unord_sf
+#define L_negate_sf
+#elif ARC_FP_DEBUG
+#define L_fpcmp_parts_sf
+#define L_eq_sf
+#define __eqsf2 __eqsf2_c
+#define L_gt_sf
+#define __gtsf2 __gtsf2_c
+#define L_ge_sf
+#define __gesf2 __gesf2_c
+#define L_unord_sf
+#define __unordsf2 __unordsf2_c
+#endif
diff --git a/libgcc/config/arc/gmon/atomic.h b/libgcc/config/arc/gmon/atomic.h
new file mode 100644
index 00000000000..857b85cefb3
--- /dev/null
+++ b/libgcc/config/arc/gmon/atomic.h
@@ -0,0 +1,26 @@
+/* Copyright (C) 2007-2013 Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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/>. */
+
+/* File deliberately left blank. */
diff --git a/libgcc/config/arc/gmon/auxreg.h b/libgcc/config/arc/gmon/auxreg.h
new file mode 100644
index 00000000000..10efa169eed
--- /dev/null
+++ b/libgcc/config/arc/gmon/auxreg.h
@@ -0,0 +1,35 @@
+/* Copyright (C) 2007-2013 Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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 LP_START 0x02
+#define LP_END 0x03
+#define IDENTITY 0x04
+#define STATUS32 0x0a
+#define COUNT0 0x21 /* Timer 0 count */
+#define CONTROL0 0x22 /* Timer 0 control */
+#define LIMIT0 0x23 /* Timer 0 limit */
+#define INT_VECTOR_BASE 0x25
+#define D_CACHE_BUILD 0x72
+#define DC_FLDL 0x4c
diff --git a/libgcc/config/arc/gmon/dcache_linesz.S b/libgcc/config/arc/gmon/dcache_linesz.S
new file mode 100644
index 00000000000..402a8331943
--- /dev/null
+++ b/libgcc/config/arc/gmon/dcache_linesz.S
@@ -0,0 +1,55 @@
+/* This file contains code to do profiling.
+
+ Copyright (C) 2007-2013 Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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/>. */
+
+#include "../asm.h"
+#include "auxreg.h"
+/* This file contains code to do profiling. */
+ .weak __profile_timer_cycles
+ .global __profile_timer_cycles
+ .set __profile_timer_cycles, 200
+ .text
+ ; For Arctangent-A5, if no data cache is present, a read of the
+ ; cache build register returns the ID register. For ARC600 and
+ ; later, the version field will be zero.
+ .global __dcache_linesz
+ .balign 4
+__dcache_linesz:
+ lr r12,[D_CACHE_BUILD]
+ extb_s r0,r12
+ breq_s r0,0,.Lsz_nocache
+ brge r0,0x20,.Lsz_havecache
+ lr r0,[IDENTITY]
+ breq r12,r0,.Lsz_nocache
+.Lsz_havecache:
+ lsr_s r12,r12,16
+ mov_s r0,16
+ bmsk_s r12,r12,3
+ asl_s r0,r0,r12
+ j_s [blink]
+.Lsz_nocache:
+ mov_s r0,1
+ j_s [blink]
diff --git a/libgcc/config/arc/gmon/gmon.c b/libgcc/config/arc/gmon/gmon.c
new file mode 100644
index 00000000000..098351f1664
--- /dev/null
+++ b/libgcc/config/arc/gmon/gmon.c
@@ -0,0 +1,450 @@
+/*-
+ * Copyright (c) 1983, 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (C) 2007-2013 Free Software Foundation, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#if 0
+#include <sys/param.h>
+#include <sys/time.h>
+#endif
+#include <sys/gmon.h>
+#include <sys/gmon_out.h>
+
+#include <stddef.h>
+#include <errno.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#if 0
+#include <libc-internal.h>
+#include <not-cancel.h>
+
+#ifdef USE_IN_LIBIO
+# include <wchar.h>
+#endif
+#endif
+#define internal_function
+#define weak_alias(fun,aliasid) extern __typeof(fun) aliasid __attribute__ ((weak, alias (#fun)));
+#define __libc_enable_secure 0
+
+/* Head of basic-block list or NULL. */
+struct __bb *__bb_head attribute_hidden;
+
+struct gmonparam _gmonparam attribute_hidden = { GMON_PROF_OFF };
+
+/*
+ * See profil(2) where this is described:
+ */
+static int s_scale;
+#define SCALE_1_TO_1 0x10000L
+
+#define ERR(s) write (STDERR_FILENO, s, sizeof (s) - 1)
+
+void moncontrol (int mode);
+void __moncontrol (int mode);
+static void write_hist (int fd) internal_function;
+static void write_call_graph (int fd) internal_function;
+static void write_bb_counts (int fd) internal_function;
+
+/*
+ * Control profiling
+ * profiling is what mcount checks to see if
+ * all the data structures are ready.
+ */
+void
+__moncontrol (int mode)
+{
+ struct gmonparam *p = &_gmonparam;
+
+ /* Don't change the state if we ran into an error. */
+ if (p->state == GMON_PROF_ERROR)
+ return;
+
+ if (mode)
+ {
+ /* start */
+ __profil((void *) p->kcount, p->kcountsize, p->lowpc, s_scale);
+ p->state = GMON_PROF_ON;
+ }
+ else
+ {
+ /* stop */
+ __profil(NULL, 0, 0, 0);
+ p->state = GMON_PROF_OFF;
+ }
+}
+weak_alias (__moncontrol, moncontrol)
+
+
+void
+__monstartup (u_long lowpc, u_long highpc)
+{
+ register int o;
+ char *cp;
+ struct gmonparam *p = &_gmonparam;
+ int linesz;
+
+ /*
+ * round lowpc and highpc to multiples of the density we're using
+ * so the rest of the scaling (here and in gprof) stays in ints.
+ */
+ p->lowpc = ROUNDDOWN(lowpc, HISTFRACTION * sizeof(HISTCOUNTER));
+ if (sizeof *p->froms % sizeof(HISTCOUNTER) != 0)
+ {
+ p->highpc = ROUNDUP(highpc, HISTFRACTION * sizeof(HISTCOUNTER));
+ p->textsize = p->highpc - p->lowpc;
+ p->kcountsize = ROUNDUP((p->textsize + HISTFRACTION - 1) / HISTFRACTION,
+ sizeof (*p->froms));
+ }
+ else
+ {
+ /* Avoid odd scales by rounding up highpc to get kcountsize rounded. */
+ p->textsize = ROUNDUP (highpc - p->lowpc,
+ HISTFRACTION * sizeof (*p->froms));
+ p->highpc = p->lowpc + p->textsize;
+ p->kcountsize = p->textsize / HISTFRACTION;
+ }
+ p->hashfraction = HASHFRACTION;
+ p->log_hashfraction = -1;
+ /* The following test must be kept in sync with the corresponding
+ test in mcount.c. */
+ if ((HASHFRACTION & (HASHFRACTION - 1)) == 0) {
+ /* if HASHFRACTION is a power of two, mcount can use shifting
+ instead of integer division. Precompute shift amount. */
+ p->log_hashfraction = ffs(p->hashfraction * sizeof(*p->froms)) - 1;
+ }
+ p->tolimit = p->textsize * ARCDENSITY / 100;
+ if (p->tolimit < MINARCS)
+ p->tolimit = MINARCS;
+ else if (p->tolimit > MAXARCS)
+ p->tolimit = MAXARCS;
+ p->tossize = p->tolimit * sizeof(struct tostruct);
+
+ /* p->kcount must not share cache lines with the adjacent data, because
+ we use uncached accesses while profiling. */
+ linesz = __dcache_linesz ();
+ cp = calloc (ROUNDUP (p->kcountsize, linesz) + p->tossize
+ + (linesz - 1), 1);
+ if (! cp)
+ {
+ ERR("monstartup: out of memory\n");
+ p->tos = NULL;
+ p->state = GMON_PROF_ERROR;
+ /* In case we loose the error state due to a race,
+ prevent invalid writes also by clearing tolimit. */
+ p->tolimit = 0;
+ return;
+ }
+ p->tos = (struct tostruct *)cp;
+ cp += p->tossize;
+ cp = (char *) ROUNDUP ((ptrdiff_t) cp, linesz);
+ p->kcount = (HISTCOUNTER *)cp;
+ cp += ROUNDUP (p->kcountsize, linesz);
+
+ p->tos[0].link = 0;
+
+ o = p->highpc - p->lowpc;
+ if (p->kcountsize < (u_long) o)
+ {
+#ifndef hp300
+ s_scale = ((float)p->kcountsize / o ) * SCALE_1_TO_1;
+#else
+ /* avoid floating point operations */
+ int quot = o / p->kcountsize;
+
+ if (quot >= 0x10000)
+ s_scale = 1;
+ else if (quot >= 0x100)
+ s_scale = 0x10000 / quot;
+ else if (o >= 0x800000)
+ s_scale = 0x1000000 / (o / (p->kcountsize >> 8));
+ else
+ s_scale = 0x1000000 / ((o << 8) / p->kcountsize);
+#endif
+ } else
+ s_scale = SCALE_1_TO_1;
+
+ __moncontrol(1);
+}
+weak_alias (__monstartup, monstartup)
+
+
+static void
+internal_function
+write_hist (int fd)
+{
+ u_char tag = GMON_TAG_TIME_HIST;
+ struct arc_gmon_hist_hdr thdr __attribute__ ((aligned (__alignof__ (char *))));
+ int r;
+
+ if (_gmonparam.kcountsize > 0)
+ {
+ *(char **) thdr.low_pc = (char *) _gmonparam.lowpc;
+ *(char **) thdr.high_pc = (char *) _gmonparam.highpc;
+ *(int32_t *) thdr.hist_size = (_gmonparam.kcountsize
+ / sizeof (HISTCOUNTER));
+ *(int32_t *) thdr.prof_rate = __profile_frequency ();
+ strncpy (thdr.dimen, "seconds", sizeof (thdr.dimen));
+ thdr.dimen_abbrev = 's';
+
+ r = write (fd, &tag, sizeof tag);
+ if (r != sizeof tag)
+ return;
+ r = write (fd, &thdr, sizeof thdr);
+ if (r != sizeof thdr)
+ return;
+ r = write (fd,_gmonparam.kcount, _gmonparam.kcountsize);
+ if ((unsigned) r != _gmonparam.kcountsize)
+ return;
+ }
+}
+
+
+static void
+internal_function
+write_call_graph (int fd)
+{
+#define NARCS_PER_WRITE 64
+#define BYTES_PER_ARC (1 + sizeof (struct gmon_cg_arc_record))
+#define BYTES_PER_WRITE (BYTES_PER_ARC * NARCS_PER_WRITE)
+ ARCINDEX to_index;
+ u_long frompc, selfpc, count;
+ char buffer[BYTES_PER_WRITE], *p;
+ u_long *prof_desc = __arc_profile_desc_secstart;
+ u_long *prof_count = __arc_profile_counters_secstart;
+ u_long *prof_desc_end = __arc_profile_desc_secend;
+ u_long *prof_forward = __arc_profile_forward_secstart;
+
+ for (p = buffer; p < buffer + BYTES_PER_WRITE; p += BYTES_PER_ARC)
+ *p = GMON_TAG_CG_ARC;
+ p = buffer;
+ frompc = *prof_desc++ & -2;
+ while (prof_desc < prof_desc_end)
+ {
+ selfpc = *prof_desc++;
+ if (selfpc & 1)
+ {
+ frompc = selfpc & -2;
+ selfpc = *prof_desc++;
+ }
+ count = *prof_count++;
+ if (selfpc)
+ {
+ struct arc
+ {
+ char *frompc;
+ char *selfpc;
+ int32_t count;
+ }
+ arc;
+
+ if (!count)
+ continue;
+ arc.frompc = (char *) frompc;
+ arc.selfpc = (char *) selfpc;
+ arc.count = count;
+ memcpy (p + 1, &arc, sizeof arc);
+ p += 1 + sizeof arc;
+
+ if (p == buffer + BYTES_PER_WRITE)
+ {
+ write (fd, buffer, BYTES_PER_WRITE);
+ p = buffer;
+ }
+ }
+ else
+ {
+ for (to_index = count;
+ to_index != 0;
+ to_index = _gmonparam.tos[to_index].link)
+ {
+ struct arc
+ {
+ char *frompc;
+ char *selfpc;
+ int32_t count;
+ }
+ arc;
+
+ arc.frompc = (char *) frompc;
+ arc.selfpc = (char *) _gmonparam.tos[to_index].selfpc;
+ arc.count = _gmonparam.tos[to_index].count;
+ memcpy (p + 1, &arc, sizeof arc);
+ p += 1 + sizeof arc;
+
+ if (p == buffer + BYTES_PER_WRITE)
+ {
+ write (fd, buffer, BYTES_PER_WRITE);
+ p = buffer;
+ }
+ }
+ }
+ }
+ while (prof_forward < __arc_profile_forward_secend)
+ {
+ /* ??? The 'call count' is actually supposed to be a fixed point
+ factor, with 16 bits each before and after the point.
+ It would be much nicer if we figured out the actual number
+ of calls to the caller, and multiplied that with the fixed point
+ factor to arrive at the estimated calls for the callee. */
+ memcpy (p + 1, prof_forward, 3 * sizeof *prof_forward);
+ prof_forward += 3;
+ p += 1 + 3 * sizeof *prof_forward;
+ if (p == buffer + BYTES_PER_WRITE)
+ {
+ write (fd, buffer, BYTES_PER_WRITE);
+ p = buffer;
+ }
+ }
+ if (p != buffer)
+ write (fd, buffer, p - buffer);
+}
+
+
+static void
+internal_function
+write_bb_counts (int fd)
+{
+ struct __bb *grp;
+ u_char tag = GMON_TAG_BB_COUNT;
+ size_t ncounts;
+ size_t i;
+
+ struct { unsigned long address; long count; } bbbody[8];
+ size_t nfilled;
+
+ /* Write each group of basic-block info (all basic-blocks in a
+ compilation unit form a single group). */
+
+ for (grp = __bb_head; grp; grp = grp->next)
+ {
+ ncounts = grp->ncounts;
+ write (fd, &tag, 1);
+ write (fd, &ncounts, sizeof ncounts);
+ for (nfilled = i = 0; i < ncounts; ++i)
+ {
+ if (nfilled == sizeof (bbbody) / sizeof (bbbody[0]))
+ {
+ write (fd, bbbody, sizeof bbbody);
+ nfilled = 0;
+ }
+
+ bbbody[nfilled].address = grp->addresses[i];
+ bbbody[nfilled++].count = grp->counts[i];
+ }
+ if (nfilled > 0)
+ write (fd, bbbody, nfilled * sizeof bbbody[0]);
+ }
+}
+
+
+static void
+write_gmon (void)
+{
+ struct gmon_hdr ghdr __attribute__ ((aligned (__alignof__ (int))));
+ int fd = -1;
+ char *env;
+
+#ifndef O_NOFOLLOW
+# define O_NOFOLLOW 0
+#endif
+
+ env = getenv ("GMON_OUT_PREFIX");
+ if (env != NULL && !__libc_enable_secure)
+ {
+ size_t len = strlen (env);
+ char buf[len + 20];
+ snprintf (buf, sizeof (buf), "%s.%u", env, getpid ());
+ fd = open (buf, O_CREAT|O_TRUNC|O_WRONLY|O_NOFOLLOW, 0666);
+ }
+
+ if (fd == -1)
+ {
+ fd = open ("gmon.out", O_CREAT|O_TRUNC|O_WRONLY|O_NOFOLLOW,
+ 0666);
+ if (fd < 0)
+ {
+ perror ("_mcleanup: gmon.out");
+ return;
+ }
+ }
+
+ /* write gmon.out header: */
+ memset (&ghdr, '\0', sizeof (struct gmon_hdr));
+ memcpy (&ghdr.cookie[0], GMON_MAGIC, sizeof (ghdr.cookie));
+ *(int32_t *) ghdr.version = GMON_VERSION;
+ write (fd, &ghdr, sizeof (struct gmon_hdr));
+
+ /* write PC histogram: */
+ write_hist (fd);
+
+ /* write call-graph: */
+ write_call_graph (fd);
+
+ /* write basic-block execution counts: */
+ write_bb_counts (fd);
+
+ close (fd);
+}
+
+
+void
+__write_profiling (void)
+{
+ int save = _gmonparam.state;
+ _gmonparam.state = GMON_PROF_OFF;
+ if (save == GMON_PROF_ON)
+ write_gmon ();
+ _gmonparam.state = save;
+}
+#ifndef SHARED
+/* This symbol isn't used anywhere in the DSO and it is not exported.
+ This would normally mean it should be removed to get the same API
+ in static libraries. But since profiling is special in static libs
+ anyway we keep it. But not when building the DSO since some
+ quality assurance tests will otherwise trigger. */
+weak_alias (__write_profiling, write_profiling)
+#endif
+
+
+void
+_mcleanup (void)
+{
+ __moncontrol (0);
+
+ if (_gmonparam.state != GMON_PROF_ERROR)
+ write_gmon ();
+
+ /* free the memory. */
+ if (_gmonparam.tos != NULL)
+ free (_gmonparam.tos);
+}
diff --git a/libgcc/config/arc/gmon/machine-gmon.h b/libgcc/config/arc/gmon/machine-gmon.h
new file mode 100644
index 00000000000..25ad0dd2882
--- /dev/null
+++ b/libgcc/config/arc/gmon/machine-gmon.h
@@ -0,0 +1,65 @@
+/* Copyright (C) 2007-2013 Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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 MACHINE_GMON_H
+#define MACHINE_GMON_H
+
+/* We can't fake out own <sys/types.h> header because the newlib / uclibc
+ headers in GCC_FOR_TARGET take precedence. */
+
+#define __BEGIN_DECLS
+#define __END_DECLS
+
+#define __THROW
+
+extern int __dcache_linesz (void);
+
+#define _MCOUNT_DECL(countp, selfpc) \
+ static inline void _mcount_internal (void *countp, u_long selfpc)
+
+extern void _mcount (void);
+extern void _mcount_call (void);
+
+/* N.B.: the calling point might be a sibcall, thus blink does not necessarily
+ hold the caller's address. r8 doesn't hold the caller's address, either,
+ but rather a pointer to the counter data structure associated with the
+ caller.
+ This function must be compiled with optimization turned on in order to
+ enable a sibcall for the final call to selfpc; this is important when trying
+ to profile a program with deep tail-recursion that would get a stack
+ overflow otherwise. */
+#define MCOUNT \
+void \
+_mcount_call (void) \
+{ \
+ register void *countp __asm("r8"); \
+ register u_long selfpc __asm("r9"); \
+ _mcount_internal (countp, selfpc); \
+ ((void (*)(void)) selfpc) (); \
+}
+
+extern int __profil (u_short *,size_t, size_t, u_int);
+
+#endif /* MACHINE_GMON_H */
diff --git a/libgcc/config/arc/gmon/mcount.c b/libgcc/config/arc/gmon/mcount.c
new file mode 100644
index 00000000000..c99dcd7bd7e
--- /dev/null
+++ b/libgcc/config/arc/gmon/mcount.c
@@ -0,0 +1,206 @@
+/*-
+ * Copyright (c) 1983, 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Copyright (C) 2007-2013 Free Software Foundation, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if !defined(lint) && !defined(KERNEL) && defined(LIBC_SCCS)
+static char sccsid[] = "@(#)mcount.c 8.1 (Berkeley) 6/4/93";
+#endif
+
+#if 0
+#include <unistd.h>
+#include <sys/param.h>
+#endif
+#include <sys/gmon.h>
+
+/* This file provides the machine-dependent definitions of the _MCOUNT_DECL
+ and MCOUNT macros. */
+#include <machine-gmon.h>
+
+#include <atomic.h>
+
+/*
+ * mcount is called on entry to each function compiled with the profiling
+ * switch set. _mcount(), which is declared in a machine-dependent way
+ * with _MCOUNT_DECL, does the actual work and is either inlined into a
+ * C routine or called by an assembly stub. In any case, this magic is
+ * taken care of by the MCOUNT definition in <machine/profile.h>.
+ *
+ * _mcount updates data structures that represent traversals of the
+ * program's call graph edges. frompc and selfpc are the return
+ * address and function address that represents the given call graph edge.
+ *
+ * Note: the original BSD code used the same variable (frompcindex) for
+ * both frompcindex and frompc. Any reasonable, modern compiler will
+ * perform this optimization.
+ */
+_MCOUNT_DECL(count_ptr, selfpc) /* _mcount; may be static, inline, etc */
+{
+ register ARCINDEX *frompcindex;
+ register struct tostruct *top, *prevtop;
+ register struct gmonparam *p;
+ register ARCINDEX toindex;
+
+ /* Check for nested function trampoline. */
+ if (selfpc & 2)
+ selfpc = *(u_long *) (selfpc + 10);
+
+ p = &_gmonparam;
+ /*
+ * check that we are profiling
+ * and that we aren't recursively invoked.
+ */
+#if 0
+ if (catomic_compare_and_exchange_bool_acq (&p->state, GMON_PROF_BUSY,
+ GMON_PROF_ON))
+ return;
+#elif defined (__ARC700__)
+/* ??? This could temporarily lose the ERROR / OFF condition in a race,
+ but doing an actual compare_and_exchange would be too costly. It would
+ be better if we had a semaphore independent of the 'sticky' state, but
+ then we could run into ABI compatibility problems with the size of struct
+ gmonparam. */
+ {
+ u_long old_state;
+
+ __asm ("ex %0,%1": "=r" (old_state), "+m" (p->state)
+ : "0" (GMON_PROF_BUSY));
+ if (old_state != GMON_PROF_ON)
+ {
+ switch (old_state)
+ {
+ case GMON_PROF_OFF:
+ __asm ("ex %0,%1": "+r" (old_state), "+m" (p->state));
+ if (old_state == GMON_PROF_BUSY
+ /* Switching off while we say we are busy while profiling
+ was actually already switched off is all right. */
+ || old_state == GMON_PROF_OFF)
+ break;
+ /* It is not clear if we should allow switching on
+ profiling at this point, and how to handle further races.
+ For now, record an error in this case. */
+ /* Fall through. */
+ default: /* We expect here only GMON_PROF_ERROR. */
+ p->state = GMON_PROF_ERROR;
+ break;
+ case GMON_PROF_BUSY: break;
+ }
+ return;
+ }
+ }
+#else /* ??? No semaphore primitives available. */
+ if (p->state != GMON_PROF_ON)
+ return;
+ p->state = GMON_PROF_BUSY;
+#endif
+
+ frompcindex = count_ptr;
+ toindex = *frompcindex;
+ if (toindex == 0) {
+ /*
+ * first time traversing this arc
+ */
+ toindex = ++p->tos[0].link;
+ if (toindex >= (ARCINDEX) p->tolimit)
+ /* halt further profiling */
+ goto overflow;
+
+ *frompcindex = toindex;
+ top = &p->tos[toindex];
+ top->selfpc = selfpc;
+ top->count = 1;
+ top->link = 0;
+ goto done;
+ }
+ top = &p->tos[toindex];
+ if (top->selfpc == selfpc) {
+ /*
+ * arc at front of chain; usual case.
+ */
+ top->count++;
+ goto done;
+ }
+ /*
+ * have to go looking down chain for it.
+ * top points to what we are looking at,
+ * prevtop points to previous top.
+ * we know it is not at the head of the chain.
+ */
+ for (; /* goto done */; ) {
+ if (top->link == 0) {
+ /*
+ * top is end of the chain and none of the chain
+ * had top->selfpc == selfpc.
+ * so we allocate a new tostruct
+ * and link it to the head of the chain.
+ */
+ toindex = ++p->tos[0].link;
+ if (toindex >= (ARCINDEX) p->tolimit)
+ goto overflow;
+
+ top = &p->tos[toindex];
+ top->selfpc = selfpc;
+ top->count = 1;
+ top->link = *frompcindex;
+ *frompcindex = toindex;
+ goto done;
+ }
+ /*
+ * otherwise, check the next arc on the chain.
+ */
+ prevtop = top;
+ top = &p->tos[top->link];
+ if (top->selfpc == selfpc) {
+ /*
+ * there it is.
+ * increment its count
+ * move it to the head of the chain.
+ */
+ top->count++;
+ toindex = prevtop->link;
+ prevtop->link = top->link;
+ top->link = *frompcindex;
+ *frompcindex = toindex;
+ goto done;
+ }
+
+ }
+done:
+ p->state = GMON_PROF_ON;
+ return;
+overflow:
+ p->state = GMON_PROF_ERROR;
+ return;
+}
+
+/*
+ * Actual definition of mcount function. Defined in <machine/profile.h>,
+ * which is included by <sys/gmon.h>.
+ */
+MCOUNT
diff --git a/libgcc/config/arc/gmon/prof-freq-stub.S b/libgcc/config/arc/gmon/prof-freq-stub.S
new file mode 100644
index 00000000000..dc9ec681b36
--- /dev/null
+++ b/libgcc/config/arc/gmon/prof-freq-stub.S
@@ -0,0 +1,40 @@
+/* This file contains code to do profiling.
+
+ Copyright (C) 2007-2013 Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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/>. */
+
+#include "../asm.h"
+/* This file contains code to do profiling. */
+ .weak __profile_frequency_value
+ .global __profile_frequency_value
+ .set __profile_frequency_value, 1000
+ .text
+ .balign 4
+ .global __profile_frequency
+ FUNC(__profile_frequency)
+__profile_frequency:
+ mov_s r0,__profile_frequency_value
+ j_s [blink]
+ ENDFUNC(__profile_frequency)
diff --git a/libgcc/config/arc/gmon/prof-freq.c b/libgcc/config/arc/gmon/prof-freq.c
new file mode 100644
index 00000000000..39395b1acd3
--- /dev/null
+++ b/libgcc/config/arc/gmon/prof-freq.c
@@ -0,0 +1,60 @@
+/* Return frequency of ticks reported by profil. Generic version. */
+/*-
+ * Copyright (c) 1983, 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Copyright (C) 2007-2013 Free Software Foundation, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+#include <sys/types.h>
+#include <sys/time.h>
+#if 0
+#include <libc-internal.h>
+#else
+#include "sys/gmon.h"
+#endif
+
+int
+__profile_frequency (void)
+{
+ /*
+ * Discover the tick frequency of the machine if something goes wrong,
+ * we return 0, an impossible hertz.
+ */
+ struct itimerval tim;
+
+ tim.it_interval.tv_sec = 0;
+ tim.it_interval.tv_usec = 1;
+ tim.it_value.tv_sec = 0;
+ tim.it_value.tv_usec = 0;
+ setitimer(ITIMER_REAL, &tim, 0);
+ setitimer(ITIMER_REAL, 0, &tim);
+ if (tim.it_interval.tv_usec < 2)
+ return 0;
+ return (1000000 / tim.it_interval.tv_usec);
+}
diff --git a/libgcc/config/arc/gmon/profil.S b/libgcc/config/arc/gmon/profil.S
new file mode 100644
index 00000000000..3835fe37944
--- /dev/null
+++ b/libgcc/config/arc/gmon/profil.S
@@ -0,0 +1,153 @@
+/* This file contains code to do profiling.
+
+ Copyright (C) 2007-2013 Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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/>. */
+
+#include "../asm.h"
+#include "auxreg.h"
+/* This file contains code to do profiling. */
+ .weak __profile_timer_cycles
+ .global __profile_timer_cycles
+ .set __profile_timer_cycles, 200
+
+ .section .bss
+ .global __profil_offset
+ .align 4
+ .type __profil_offset, @object
+ .size __profil_offset, 4
+__profil_offset:
+ .zero 4
+
+ .text
+ .global __dcache_linesz
+ .global __profil
+ FUNC(__profil)
+.Lstop_profiling:
+ sr r0,[CONTROL0]
+ j_s [blink]
+ .balign 4
+__profil:
+.Lprofil:
+ breq_s r0,0,.Lstop_profiling
+ ; r0: buf r1: bufsiz r2: offset r3: scale
+ bxor.f r3,r3,15; scale must be 0x8000, i.e. 1/2; generate 0.
+ push_s blink
+ lsr_s r2,r2,1
+ mov_s r8,r0
+ flag.ne 1 ; halt if wrong scale
+ sub_s r0,r0,r2
+ st r0,[__profil_offset]
+ bl __dcache_linesz
+ pop_s blink
+ bbit1.d r0,0,nocache
+ mov_s r0,r8
+#ifdef __ARC700__
+ add_s r1,r1,31
+ lsr.f lp_count,r1,5
+ lpne 2f
+ sr r0,[DC_FLDL]
+ add_s r0,r0,32
+#else /* !__ARC700__ */
+# FIX ME: set up loop according to cache line size
+ lr r12,[D_CACHE_BUILD]
+ sub_s r0,r0,16
+ sub_s r1,r1,1
+ lsr_s r12,r12,16
+ asr_s r1,r1,4
+ bmsk_s r12,r12,3
+ asr_s r1,r1,r12
+ add.f lp_count,r1,1
+ mov_s r1,16
+ asl_s r1,r1,r12
+ lpne 2f
+ add r0,r0,r1
+ sr r0,[DC_FLDL]
+#endif /* __ARC700__ */
+2: b_s .Lcounters_cleared
+nocache:
+.Lcounters_cleared:
+ lr r1,[INT_VECTOR_BASE] ; disable timer0 interrupts
+ sr r3,[CONTROL0]
+ sr r3,[COUNT0]
+0: ld_s r0,[pcl,1f-0b+((0b-.Lprofil) & 2)] ; 1f@GOTOFF
+0: ld_s r12,[pcl,1f+4-0b+((0b-.Lprofil) & 2)] ; 1f@GOTOFF + 4
+ st_s r0,[r1,24]; timer0 uses vector3
+ st_s r12,[r1,24+4]; timer0 uses vector3
+ ;sr 10000,[LIMIT0]
+ sr __profile_timer_cycles,[LIMIT0]
+ mov_s r12,3 ; enable timer interrupts; count only when not halted.
+ sr r12,[CONTROL0]
+ lr r12,[STATUS32]
+ bset_s r12,r12,1 ; allow level 1 interrupts
+ flag r12
+ mov_s r0,0
+ j_s [blink]
+ .balign 4
+1: j __profil_irq
+ ENDFUNC(__profil)
+
+ FUNC(__profil_irq)
+ .balign 4 ; make final jump unaligned to avoid delay penalty
+ .balign 32,0,12 ; make sure the code spans no more that two cache lines
+ nop_s
+__profil_irq:
+ push_s r0
+ ld r0,[__profil_offset]
+ push_s r1
+ lsr r1,ilink1,2
+ push_s r2
+ ldw.as.di r2,[r0,r1]
+ add1 r0,r0,r1
+ ld_s r1,[sp,4]
+ add_s r2,r2,1
+ bbit1 r2,16,nostore
+ stw.di r2,[r0]
+nostore:ld.ab r2,[sp,8]
+ pop_s r0
+ j.f [ilink1]
+ ENDFUNC(__profil_irq)
+
+; could save one cycle if the counters were allocated at link time and
+; the contents of __profil_offset were pre-computed at link time, like this:
+#if 0
+; __profil_offset needs to be PROVIDEd as __profile_base-text/4
+ .global __profil_offset
+ .balign 4
+__profil_irq:
+ push_s r0
+ lsr r0,ilink1,2
+ add1 r0,__profil_offset,r0
+ push_s r1
+ ldw.di r1,[r0]
+
+
+ add_s r1,r1,1
+ bbit1 r1,16,nostore
+ stw.di r1,[r0]
+nostore:pop_s r1
+ pop_s r0
+ j [ilink1]
+#endif /* 0 */
diff --git a/libgcc/config/arc/gmon/sys/gmon.h b/libgcc/config/arc/gmon/sys/gmon.h
new file mode 100644
index 00000000000..03171136281
--- /dev/null
+++ b/libgcc/config/arc/gmon/sys/gmon.h
@@ -0,0 +1,217 @@
+/*-
+ * Copyright (c) 1982, 1986, 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (C) 2007-2013 Free Software Foundation, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)gmon.h 8.2 (Berkeley) 1/4/94
+ */
+
+#ifndef _SYS_GMON_H
+#define _SYS_GMON_H 1
+
+#if 0
+#include <features.h>
+#include <sys/types.h>
+#else
+#include <sys/types.h>
+#include "machine-gmon.h"
+#define attribute_hidden __attribute__ ((visibility("hidden")))
+#endif
+
+#include <stdint.h>
+
+/*
+ * See gmon_out.h for gmon.out format.
+ */
+
+/* structure emitted by "gcc -a". This must match struct bb in
+ gcc/libgcc2.c. It is OK for gcc to declare a longer structure as
+ long as the members below are present. */
+struct __bb
+{
+ long zero_word;
+ const char *filename;
+ long *counts;
+ long ncounts;
+ struct __bb *next;
+ const unsigned long *addresses;
+};
+
+extern struct __bb *__bb_head;
+
+/*
+ * histogram counters are unsigned shorts (according to the kernel).
+ */
+#define HISTCOUNTER unsigned short
+
+/*
+ * fraction of text space to allocate for histogram counters here, 1/2
+ */
+#define HISTFRACTION 2
+
+/*
+ * Fraction of text space to allocate for from hash buckets.
+ * The value of HASHFRACTION is based on the minimum number of bytes
+ * of separation between two subroutine call points in the object code.
+ * Given MIN_SUBR_SEPARATION bytes of separation the value of
+ * HASHFRACTION is calculated as:
+ *
+ * HASHFRACTION = MIN_SUBR_SEPARATION / (2 * sizeof(short) - 1);
+ *
+ * For example, on the VAX, the shortest two call sequence is:
+ *
+ * calls $0,(r0)
+ * calls $0,(r0)
+ *
+ * which is separated by only three bytes, thus HASHFRACTION is
+ * calculated as:
+ *
+ * HASHFRACTION = 3 / (2 * 2 - 1) = 1
+ *
+ * Note that the division above rounds down, thus if MIN_SUBR_FRACTION
+ * is less than three, this algorithm will not work!
+ *
+ * In practice, however, call instructions are rarely at a minimal
+ * distance. Hence, we will define HASHFRACTION to be 2 across all
+ * architectures. This saves a reasonable amount of space for
+ * profiling data structures without (in practice) sacrificing
+ * any granularity.
+ */
+#define HASHFRACTION 2
+
+/*
+ * Percent of text space to allocate for tostructs.
+ * This is a heuristic; we will fail with a warning when profiling programs
+ * with a very large number of very small functions, but that's
+ * normally OK.
+ * 2 is probably still a good value for normal programs.
+ * Profiling a test case with 64000 small functions will work if
+ * you raise this value to 3 and link statically (which bloats the
+ * text size, thus raising the number of arcs expected by the heuristic).
+ */
+#define ARCDENSITY 3
+
+/*
+ * Always allocate at least this many tostructs. This
+ * hides the inadequacy of the ARCDENSITY heuristic, at least
+ * for small programs.
+ */
+#define MINARCS 50
+
+/*
+ * The type used to represent indices into gmonparam.tos[].
+ */
+#define ARCINDEX u_long
+
+/*
+ * Maximum number of arcs we want to allow.
+ * Used to be max representable value of ARCINDEX minus 2, but now
+ * that ARCINDEX is a long, that's too large; we don't really want
+ * to allow a 48 gigabyte table.
+ * The old value of 1<<16 wasn't high enough in practice for large C++
+ * programs; will 1<<20 be adequate for long? FIXME
+ */
+#define MAXARCS (1 << 20)
+
+struct tostruct {
+ u_long selfpc;
+ long count;
+ ARCINDEX link;
+};
+
+/*
+ * a raw arc, with pointers to the calling site and
+ * the called site and a count.
+ */
+struct rawarc {
+ u_long raw_frompc;
+ u_long raw_selfpc;
+ long raw_count;
+};
+
+/*
+ * general rounding functions.
+ */
+#define ROUNDDOWN(x,y) (((x)/(y))*(y))
+#define ROUNDUP(x,y) ((((x)+(y)-1)/(y))*(y))
+
+/*
+ * The profiling data structures are housed in this structure.
+ */
+struct gmonparam {
+ long int state;
+ u_short *kcount;
+ u_long kcountsize;
+ ARCINDEX *froms;
+ u_long fromssize;
+ struct tostruct *tos;
+ u_long tossize;
+ long tolimit;
+ u_long lowpc;
+ u_long highpc;
+ u_long textsize;
+ u_long hashfraction;
+ long log_hashfraction;
+};
+extern struct gmonparam _gmonparam;
+
+/*
+ * Possible states of profiling.
+ */
+#define GMON_PROF_ON 0
+#define GMON_PROF_BUSY 1
+#define GMON_PROF_ERROR 2
+#define GMON_PROF_OFF 3
+
+/*
+ * Sysctl definitions for extracting profiling information from the kernel.
+ */
+#define GPROF_STATE 0 /* int: profiling enabling variable */
+#define GPROF_COUNT 1 /* struct: profile tick count buffer */
+#define GPROF_FROMS 2 /* struct: from location hash bucket */
+#define GPROF_TOS 3 /* struct: destination/count structure */
+#define GPROF_GMONPARAM 4 /* struct: profiling parameters (see above) */
+
+__BEGIN_DECLS
+
+/* Set up data structures and start profiling. */
+extern void __monstartup (u_long __lowpc, u_long __highpc) __THROW;
+extern void monstartup (u_long __lowpc, u_long __highpc) __THROW;
+
+/* Clean up profiling and write out gmon.out. */
+extern void _mcleanup (void) __THROW;
+
+extern void __write_profiling (void);
+extern int attribute_hidden __profile_frequency (void);
+
+extern u_long __arc_profile_desc_secstart[], __arc_profile_desc_secend[];
+extern u_long __arc_profile_forward_secstart[], __arc_profile_forward_secend[];
+extern u_long __arc_profile_counters_secstart[];
+
+__END_DECLS
+
+#endif /* sys/gmon.h */
diff --git a/libgcc/config/arc/gmon/sys/gmon_out.h b/libgcc/config/arc/gmon/sys/gmon_out.h
new file mode 100644
index 00000000000..ae38145b145
--- /dev/null
+++ b/libgcc/config/arc/gmon/sys/gmon_out.h
@@ -0,0 +1,55 @@
+/* Copyright (C) 2007-2013 Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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 GMON_TAG_TIME_HIST 0
+#define GMON_TAG_CG_ARC 1
+#define GMON_TAG_BB_COUNT 2
+
+#define GMON_MAGIC "gmon"
+#define GMON_VERSION 1
+
+struct arc_gmon_hist_hdr
+{
+ char low_pc[4];
+ char high_pc[4];
+ char hist_size[4];
+ char prof_rate[4];
+ char dimen[15];
+ char dimen_abbrev;
+};
+
+struct gmon_cg_arc_record
+{
+ char afrompc[4];
+ char selfpc[4];
+ char count[4];
+};
+
+struct gmon_hdr
+{
+ char cookie[4];
+ char version[4];
+ char c[12];
+};
diff --git a/libgcc/config/arc/ieee-754/adddf3.S b/libgcc/config/arc/ieee-754/adddf3.S
new file mode 100644
index 00000000000..d0a3b43359e
--- /dev/null
+++ b/libgcc/config/arc/ieee-754/adddf3.S
@@ -0,0 +1,524 @@
+/* Copyright (C) 2008-2013 Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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/>. */
+
+#include "arc-ieee-754.h"
+#if 0 /* DEBUG */
+ .global __adddf3
+ .balign 4
+__adddf3:
+ push_s blink
+ push_s r2
+ push_s r3
+ push_s r0
+ bl.d __adddf3_c
+ push_s r1
+ ld_s r2,[sp,12]
+ ld_s r3,[sp,8]
+ st_s r0,[sp,12]
+ st_s r1,[sp,8]
+ pop_s r1
+ bl.d __adddf3_asm
+ pop_s r0
+ pop_s r3
+ pop_s r2
+ pop_s blink
+ cmp r0,r2
+ cmp.eq r1,r3
+ jeq_s [blink]
+ bl abort
+ .global __subdf3
+ .balign 4
+__subdf3:
+ push_s blink
+ push_s r2
+ push_s r3
+ push_s r0
+ bl.d __subdf3_c
+ push_s r1
+ ld_s r2,[sp,12]
+ ld_s r3,[sp,8]
+ st_s r0,[sp,12]
+ st_s r1,[sp,8]
+ pop_s r1
+ bl.d __subdf3_asm
+ pop_s r0
+ pop_s r3
+ pop_s r2
+ pop_s blink
+ cmp r0,r2
+ cmp.eq r1,r3
+ jeq_s [blink]
+ bl abort
+#define __adddf3 __adddf3_asm
+#define __subdf3 __subdf3_asm
+#endif /* DEBUG */
+/* N.B. This is optimized for ARC700.
+ ARC600 has very different scheduling / instruction selection criteria. */
+
+/* inputs: DBL0, DBL1 (r0-r3)
+ output: DBL0 (r0, r1)
+ clobber: r2-r10, r12, flags
+ All NaN highword bits must be 1. NaN low word is random. */
+
+ .balign 4
+ .global __adddf3
+ .global __subdf3
+ .long 0x7ff00000 ; exponent mask
+ FUNC(__adddf3)
+ FUNC(__subdf3)
+__subdf3:
+ bxor_l DBL1H,DBL1H,31
+__adddf3:
+ ld r9,[pcl,-8]
+ bmsk r4,DBL0H,30
+ xor r10,DBL0H,DBL1H
+ and r6,DBL1H,r9
+ sub.f r12,r4,r6
+ asr_s r12,r12,20
+ blo .Ldbl1_gt
+ brhs r4,r9,.Linf_nan
+ brhs r12,32,.Large_shift
+ brne r12,0,.Lsmall_shift
+ brge r10,0,.Ladd_same_exp ; r12 == 0
+
+/* After subtracting, we need to normalize; when shifting to place the
+ leading 1 into position for the implicit 1 and adding that to DBL0H,
+ we increment the exponent. Thus, we have to subtract one more than
+ the shift count from the exponent beforehand. Iff the exponent drops thus
+ below zero (before adding in the fraction with the leading one), we have
+ generated a denormal number. Denormal handling is basicallly reducing the
+ shift count so that we produce a zero exponent instead; however, this way
+ the shift count can become zero (if we started out with exponent 1).
+ Therefore, a simple min operation is not good enough, since we don't
+ want to handle a zero normalizing shift in the main path.
+ On the plus side, we don't need to check for denorm input, the result
+ of subtracing these looks just the same as denormals generated during
+ subtraction. */
+ bmsk r7,DBL1H,30
+ cmp r4,r7
+ cmp.eq DBL0L,DBL1L
+ blo .L_rsub_same_exp
+ sub.f DBL0L,DBL0L,DBL1L
+ bmsk r12,DBL0H,19
+ bic DBL1H,DBL0H,r12
+ sbc.f r4,r4,r7
+ beq_l .Large_cancel
+ norm DBL1L,r4
+ b.d .Lsub_done_same_exp
+ sub r12,DBL1L,9
+
+ .balign 4
+.Linf_nan:
+ ; If both inputs are inf, but with different signs, the result is NaN.
+ asr r12,r10,31
+ or_s DBL1H,DBL1H,r12
+ j_s.d [blink]
+ or.eq DBL0H,DBL0H,DBL1H
+
+ .balign 4
+.L_rsub_same_exp:
+ rsub.f DBL0L,DBL0L,DBL1L
+ bmsk r12,DBL1H,19
+ bic_s DBL1H,DBL1H,r12
+ sbc.f r4,r7,r4
+ beq_l .Large_cancel
+ norm DBL1L,r4
+
+ sub r12,DBL1L,9
+.Lsub_done_same_exp:
+ asl_s r12,r12,20
+ sub_s DBL1L,DBL1L,10
+ sub DBL0H,DBL1H,r12
+ xor.f 0,DBL0H,DBL1H
+ bmi .Ldenorm
+.Lpast_denorm:
+ neg_s r12,DBL1L
+ lsr r7,DBL0L,r12
+ asl r12,r4,DBL1L
+ asl_s DBL0L,DBL0L,DBL1L
+ add_s r12,r12,r7
+ j_s.d [blink]
+ add_l DBL0H,DBL0H,r12
+ .balign 4
+.Ladd_same_exp:
+ /* This is a special case because we can't test for need to shift
+ down by checking if bit 20 of DBL0H changes. OTOH, here we know
+ that we always need to shift down. */
+ ; The implicit 1 of DBL0 is not shifted together with the
+ ; fraction, thus effectively doubled, compensating for not setting
+ ; implicit1 for DBL1
+ add_s r12,DBL0L,DBL1L
+ lsr.f 0,r12,2 ; round to even
+ breq r6,0,.Ldenorm_add
+ adc.f DBL0L,DBL0L,DBL1L
+ sub r7,DBL1H,DBL0H
+ sub1 r7,r7,r9 ; boost exponent by 2/2
+ rrc DBL0L,DBL0L
+ asr.f r7,r7 ; DBL1.fraction/2 - DBL0.fraction/2 ; exp++
+ add.cs.f DBL0L,DBL0L,0x80000000
+ add_l DBL0H,DBL0H,r7 ; DBL0.implicit1 not shifted for DBL1.implicit1
+ add.cs DBL0H,DBL0H,1
+ bic.f 0,r9,DBL0H ; check for overflow -> infinity.
+ jne_l [blink]
+ and DBL0H,DBL0H,0xfff00000
+ j_s.d [blink]
+ mov_s DBL0L,0
+ .balign 4
+.Large_shift:
+ brhs r12,55,.Lret_dbl0
+ bmsk_s DBL1H,DBL1H,19
+ brne r6,0,.Lno_denorm_large_shift
+ brhi.d r12,33,.Lfixed_denorm_large_shift
+ sub_s r12,r12,1
+ breq r12,31, .Lfixed_denorm_small_shift
+.Lshift32:
+ mov_s r12,DBL1L
+ mov_s DBL1L,DBL1H
+ brlt.d r10,0,.Lsub
+ mov_s DBL1H,0
+ b_s .Ladd
+.Ldenorm_add:
+ cmp_s r12,DBL1L
+ mov_s DBL0L,r12
+ j_s.d [blink]
+ adc DBL0H,r4,DBL1H
+
+.Lret_dbl0:
+ j_s [blink]
+ .balign 4
+.Lsmall_shift:
+ breq.d r6,0,.Ldenorm_small_shift
+ bmsk_s DBL1H,DBL1H,19
+ bset_s DBL1H,DBL1H,20
+.Lfixed_denorm_small_shift:
+ neg r8,r12
+ asl r4,DBL1H,r8
+ lsr_l DBL1H,DBL1H,r12
+ lsr r5,DBL1L,r12
+ asl r12,DBL1L,r8
+ brge.d r10,0,.Ladd
+ or DBL1L,r4,r5
+/* subtract, abs(DBL0) > abs(DBL1) */
+/* DBL0H, DBL0L: original values
+ DBL1H, DBL1L: fraction with explicit leading 1, shifted into place
+ r4: orig. DBL0H & 0x7fffffff
+ r6: orig. DBL1H & 0x7ff00000
+ r9: 0x7ff00000
+ r10: orig. DBL0H ^ DBL1H
+ r12: guard bits */
+ .balign 4
+.Lsub:
+ neg.f r12,r12
+ mov_s r7,DBL1H
+ bmsk r5,DBL0H,19
+ sbc.f DBL0L,DBL0L,DBL1L
+ bic DBL1H,DBL0H,r5
+ bset r5,r5,20
+ sbc.f r4,r5,r7
+ beq_l .Large_cancel_sub
+ norm DBL1L,r4
+ bmsk r6,DBL1H,30
+.Lsub_done:
+ sub_s DBL1L,DBL1L,9
+ breq DBL1L,1,.Lsub_done_noshift
+ asl r5,DBL1L,20
+ sub_s DBL1L,DBL1L,1
+ brlo r6,r5,.Ldenorm_sub
+ sub DBL0H,DBL1H,r5
+.Lpast_denorm_sub:
+ neg_s DBL1H,DBL1L
+ lsr r6,r12,DBL1H
+ asl_s r12,r12,DBL1L
+ and r8,r6,1
+ add1.f 0,r8,r12
+ add.ne.f r12,r12,r12
+ asl r8,DBL0L,DBL1L
+ lsr r12,DBL0L,DBL1H
+ adc.f DBL0L,r8,r6
+ asl r5,r4,DBL1L
+ add_s DBL0H,DBL0H,r12
+ j_s.d [blink]
+ adc DBL0H,DBL0H,r5
+
+ .balign 4
+.Lno_denorm_large_shift:
+ breq.d r12,32,.Lshift32
+ bset_l DBL1H,DBL1H,20
+.Lfixed_denorm_large_shift:
+ neg r8,r12
+ asl r4,DBL1H,r8
+ lsr r5,DBL1L,r12
+ asl.f 0,DBL1L,r8
+ lsr DBL1L,DBL1H,r12
+ or r12,r4,r5
+ tst.eq r12,1
+ or.ne r12,r12,2
+ brlt.d r10,0,.Lsub
+ mov_s DBL1H,0
+ b_l .Ladd
+
+ ; If a denorm is produced without shifting, we have an exact result -
+ ; no need for rounding.
+ .balign 4
+.Ldenorm_sub:
+ lsr DBL1L,r6,20
+ xor DBL0H,r6,DBL1H
+ brne.d DBL1L,1,.Lpast_denorm_sub
+ sub_s DBL1L,DBL1L,1
+.Lsub_done_noshift:
+ add.f 0,r12,r12
+ btst.eq DBL0L,0
+ cmp.eq r12,r12
+ add.cs.f DBL0L,DBL0L,1
+ bclr r4,r4,20
+ j_s.d [blink]
+ adc DBL0H,DBL1H,r4
+
+ .balign 4
+.Ldenorm_small_shift:
+ brne.d r12,1,.Lfixed_denorm_small_shift
+ sub_l r12,r12,1
+ brlt r10,0,.Lsub
+.Ladd: ; bit 20 of DBL1H is clear and bit 0 of r12 does not matter
+ add.f DBL0L,DBL0L,DBL1L
+ add_s DBL1H,DBL1H,DBL0H
+ add.cs DBL1H,DBL1H,1
+ xor_l DBL0H,DBL0H,DBL1H
+ bbit0 DBL0H,20,.Lno_shiftdown
+ lsr.f DBL0H,DBL1H
+ and r4,DBL0L,2
+ bmsk DBL0H,DBL0H,18
+ sbc DBL0H,DBL1H,DBL0H
+ rrc.f DBL0L,DBL0L
+ or.f r12,r12,r4
+ cmp.eq r12,r12
+ add.cs.f DBL0L,DBL0L,1
+ bic.f 0,r9,DBL0H ; check for generating infinity with possible ...
+ jne.d [blink] ; ... non-zero fraction
+ add.cs DBL0H,DBL0H,1
+ mov_s DBL0L,0
+ bmsk DBL1H,DBL0H,19
+ j_s.d [blink]
+ bic_s DBL0H,DBL0H,DBL1H
+.Lno_shiftdown:
+ mov_s DBL0H,DBL1H
+ add.f 0,r12,r12
+ btst.eq DBL0L,0
+ cmp.eq r12,r12
+ add.cs.f DBL0L,DBL0L,1
+ j_s.d [blink]
+ add.cs DBL0H,DBL0H,1
+ .balign 4
+.Ldenorm:
+ bmsk DBL0H,DBL1H,30
+ lsr r12,DBL0H,20
+ xor_s DBL0H,DBL0H,DBL1H
+ sub_l DBL1L,r12,1
+ bgt .Lpast_denorm
+ j_s.d [blink]
+ add_l DBL0H,DBL0H,r4
+
+ .balign 4
+.Large_cancel:
+ ;DBL0L: mantissa DBL1H: sign & exponent
+ norm.f DBL1L,DBL0L
+ bmsk DBL0H,DBL1H,30
+ add_s DBL1L,DBL1L,22
+ mov.mi DBL1L,21
+ add_s r12,DBL1L,1
+ asl_s r12,r12,20
+ beq_s .Lret0
+ brhs.d DBL0H,r12,.Lpast_denorm_large_cancel
+ sub DBL0H,DBL1H,r12
+ bmsk DBL0H,DBL1H,30
+ lsr r12,DBL0H,20
+ xor_s DBL0H,DBL0H,DBL1H
+ sub.f DBL1L,r12,1
+ jle [blink]
+.Lpast_denorm_large_cancel:
+ rsub.f r7,DBL1L,32
+ lsr r7,DBL0L,r7
+ asl_s DBL0L,DBL0L,DBL1L
+ mov.ls r7,DBL0L
+ add_s DBL0H,DBL0H,r7
+ j_s.d [blink]
+ mov.ls DBL0L,0
+.Lret0:
+ j_s.d [blink]
+ mov_l DBL0H,0
+
+/* r4:DBL0L:r12 : unnormalized result fraction
+ DBL1H: result sign and exponent */
+/* When seeing large cancellation, only the topmost guard bit might be set. */
+ .balign 4
+.Large_cancel_sub:
+ norm.f DBL1L,DBL0L
+ bpnz.d 0f
+ bmsk DBL0H,DBL1H,30
+ mov r5,22<<20
+ bne.d 1f
+ mov_s DBL1L,21
+ bset r5,r5,5+20
+ add_s DBL1L,DBL1L,32
+ brne r12,0,1f
+ j_s.d [blink]
+ mov_l DBL0H,0
+ .balign 4
+0: add r5,DBL1L,23
+ asl r5,r5,20
+ add_s DBL1L,DBL1L,22
+1: brlo DBL0H,r5,.Ldenorm_large_cancel_sub
+ sub DBL0H,DBL1H,r5
+.Lpast_denorm_large_cancel_sub:
+ rsub.f r7,DBL1L,32
+ lsr r12,r12,r7
+ lsr r7,DBL0L,r7
+ asl_s DBL0L,DBL0L,DBL1L
+ add.ge DBL0H,DBL0H,r7
+ add_s DBL0L,DBL0L,r12
+ add.lt DBL0H,DBL0H,DBL0L
+ mov.eq DBL0L,r12
+ j_s.d [blink]
+ mov.lt DBL0L,0
+ .balign 4
+.Ldenorm_large_cancel_sub:
+ lsr r5,DBL0H,20
+ xor_s DBL0H,DBL0H,DBL1H
+ brgt.d r5,1,.Lpast_denorm_large_cancel_sub
+ sub DBL1L,r5,1
+ j_l [blink] ; denorm, no shift -> no rounding needed.
+
+/* r4: DBL0H & 0x7fffffff
+ r6: DBL1H & 0x7ff00000
+ r9: 0x7ff00000
+ r10: sign difference
+ r12: shift count (negative) */
+ .balign 4
+.Ldbl1_gt:
+ brhs r6,r9,.Lret_dbl1 ; inf or NaN
+ neg r8,r12
+ brhs r8,32,.Large_shift_dbl0
+.Lsmall_shift_dbl0:
+ breq.d r6,0,.Ldenorm_small_shift_dbl0
+ bmsk_s DBL0H,DBL0H,19
+ bset_s DBL0H,DBL0H,20
+.Lfixed_denorm_small_shift_dbl0:
+ asl r4,DBL0H,r12
+ lsr DBL0H,DBL0H,r8
+ lsr r5,DBL0L,r8
+ asl r12,DBL0L,r12
+ brge.d r10,0,.Ladd_dbl1_gt
+ or DBL0L,r4,r5
+/* subtract, abs(DBL0) < abs(DBL1) */
+/* DBL0H, DBL0L: fraction with explicit leading 1, shifted into place
+ DBL1H, DBL1L: original values
+ r6: orig. DBL1H & 0x7ff00000
+ r9: 0x7ff00000
+ r12: guard bits */
+ .balign 4
+.Lrsub:
+ neg.f r12,r12
+ bmsk r7,DBL1H,19
+ mov_s r5,DBL0H
+ sbc.f DBL0L,DBL1L,DBL0L
+ bic DBL1H,DBL1H,r7
+ bset r7,r7,20
+ sbc.f r4,r7,r5
+ beq_l .Large_cancel_sub
+ norm DBL1L,r4
+ b_l .Lsub_done ; note: r6 is already set up.
+
+.Lret_dbl1:
+ mov_s DBL0H,DBL1H
+ j_s.d [blink]
+ mov_l DBL0L,DBL1L
+ .balign 4
+.Ldenorm_small_shift_dbl0:
+ sub.f r8,r8,1
+ bne.d .Lfixed_denorm_small_shift_dbl0
+ add_s r12,r12,1
+ brlt r10,0,.Lrsub
+.Ladd_dbl1_gt: ; bit 20 of DBL0H is clear and bit 0 of r12 does not matter
+ add.f DBL0L,DBL0L,DBL1L
+ add_s DBL0H,DBL0H,DBL1H
+ add.cs DBL0H,DBL0H,1
+ xor DBL1H,DBL0H,DBL1H
+ bbit0 DBL1H,20,.Lno_shiftdown_dbl1_gt
+ lsr.f DBL1H,DBL0H
+ and r4,DBL0L,2
+ bmsk DBL1H,DBL1H,18
+ sbc DBL0H,DBL0H,DBL1H
+ rrc.f DBL0L,DBL0L
+ or.f r12,r12,r4
+ cmp.eq r12,r12
+ add.cs.f DBL0L,DBL0L,1
+ bic.f 0,r9,DBL0H ; check for generating infinity with possible ...
+ jne.d [blink] ; ... non-zero fraction
+ add.cs DBL0H,DBL0H,1
+ mov_s DBL0L,0
+ bmsk DBL1H,DBL0H,19
+ j_s.d [blink]
+ bic_s DBL0H,DBL0H,DBL1H
+.Lno_shiftdown_dbl1_gt:
+ add.f 0,r12,r12
+ btst.eq DBL0L,0
+ cmp.eq r12,r12
+ add.cs.f DBL0L,DBL0L,1
+ j_s.d [blink]
+ add.cs DBL0H,DBL0H,1
+
+ .balign 4
+.Large_shift_dbl0:
+ brhs r8,55,.Lret_dbl1
+ bmsk_s DBL0H,DBL0H,19
+ brne r6,0,.Lno_denorm_large_shift_dbl0
+ add_s r12,r12,1
+ brne.d r8,33,.Lfixed_denorm_large_shift_dbl0
+ sub r8,r8,1
+ bset_s DBL0H,DBL0H,20
+.Lshift32_dbl0:
+ mov_s r12,DBL0L
+ mov_s DBL0L,DBL0H
+ brlt.d r10,0,.Lrsub
+ mov_s DBL0H,0
+ b_s .Ladd_dbl1_gt
+
+ .balign 4
+.Lno_denorm_large_shift_dbl0:
+ breq.d r8,32,.Lshift32_dbl0
+ bset_l DBL0H,DBL0H,20
+.Lfixed_denorm_large_shift_dbl0:
+ asl r4,DBL0H,r12
+ lsr r5,DBL0L,r8
+ asl.f 0,DBL0L,r12
+ lsr DBL0L,DBL0H,r8
+ or r12,r4,r5
+ tst.eq r12,1
+ or.ne r12,r12,2
+ brlt.d r10,0,.Lrsub
+ mov_s DBL0H,0
+ b_l .Ladd_dbl1_gt
+ ENDFUNC(__adddf3)
+ ENDFUNC(__subdf3)
diff --git a/libgcc/config/arc/ieee-754/addsf3.S b/libgcc/config/arc/ieee-754/addsf3.S
new file mode 100644
index 00000000000..996a9732be1
--- /dev/null
+++ b/libgcc/config/arc/ieee-754/addsf3.S
@@ -0,0 +1,344 @@
+/* Copyright (C) 2008-2013 Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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/>. */
+
+#include "arc-ieee-754.h"
+#if 0 /* DEBUG */
+ .global __addsf3
+ FUNC(__addsf3)
+ .balign 4
+__addsf3:
+ push_s blink
+ push_s r1
+ bl.d __addsf3_c
+ push_s r0
+ ld_s r1,[sp,4]
+ st_s r0,[sp,4]
+ bl.d __addsf3_asm
+ pop_s r0
+ pop_s r1
+ pop_s blink
+ cmp r0,r1
+ jeq_s [blink]
+ bl abort
+ ENDFUNC(__addsf3)
+ .global __subsf3
+ FUNC(__subsf3)
+ .balign 4
+__subsf3:
+ push_s blink
+ push_s r1
+ bl.d __subsf3_c
+ push_s r0
+ ld_s r1,[sp,4]
+ st_s r0,[sp,4]
+ bl.d __subsf3_asm
+ pop_s r0
+ pop_s r1
+ pop_s blink
+ cmp r0,r1
+ jeq_s [blink]
+ bl abort
+ ENDFUNC(__subsf3)
+#define __addsf3 __addsf3_asm
+#define __subsf3 __subsf3_asm
+#endif /* DEBUG */
+/* N.B. This is optimized for ARC700.
+ ARC600 has very different scheduling / instruction selection criteria. */
+
+/* inputs: r0, r1
+ output: r0
+ clobber: r1-r10, r12, flags */
+
+ .balign 4
+ .global __addsf3
+ .global __subsf3
+ FUNC(__addsf3)
+ FUNC(__subsf3)
+ .long 0x7f800000 ; exponent mask
+__subsf3:
+ bxor_l r1,r1,31
+__addsf3:
+ ld r9,[pcl,-8]
+ bmsk r4,r0,30
+ xor r10,r0,r1
+ and r6,r1,r9
+ sub.f r12,r4,r6
+ asr_s r12,r12,23
+ blo .Ldbl1_gt
+ brhs r4,r9,.Linf_nan
+ brne r12,0,.Lsmall_shift
+ brge r10,0,.Ladd_same_exp ; r12 == 0
+/* After subtracting, we need to normalize; when shifting to place the
+ leading 1 into position for the implicit 1 and adding that to DBL0,
+ we increment the exponent. Thus, we have to subtract one more than
+ the shift count from the exponent beforehand. Iff the exponent drops thus
+ below zero (before adding in the fraction with the leading one), we have
+ generated a denormal number. Denormal handling is basicallly reducing the
+ shift count so that we produce a zero exponent instead; FWIW, this way
+ the shift count can become zero (if we started out with exponent 1).
+ On the plus side, we don't need to check for denorm input, the result
+ of subtracing these looks just the same as denormals generated during
+ subtraction. */
+ bmsk r7,r1,30
+ breq r4,r7,.Lret0
+ sub.f r5,r4,r7
+ lsr r12,r4,23
+ neg.cs r5,r5
+ norm r3,r5
+ bmsk r2,r0,22
+ sub_s r3,r3,6
+ min r12,r12,r3
+ bic r1,r0,r2
+ sub_s r3,r12,1
+ asl_s r12,r12,23
+ asl r2,r5,r3
+ sub_s r1,r1,r12
+ add_s r0,r1,r2
+ j_s.d [blink]
+ bxor.cs r0,r0,31
+ .balign 4
+.Linf_nan:
+ ; If both inputs are inf, but with different signs, the result is NaN.
+ asr r12,r10,31
+ or_s r1,r1,r12
+ j_s.d [blink]
+ or.eq r0,r0,r1
+ .balign 4
+.Ladd_same_exp:
+ /* This is a special case because we can't test for need to shift
+ down by checking if bit 23 of DBL0 changes. OTOH, here we know
+ that we always need to shift down. */
+ ; adding the two floating point numbers together makes the sign
+ ; cancel out and apear as carry; the exponent is doubled, and the
+ ; fraction also in need of shifting left by one. The two implicit
+ ; ones of the sources make an implicit 1 of the result, again
+ ; non-existent in a place shifted by one.
+ add.f r0,r0,r1
+ btst_s r0,1
+ breq r6,0,.Ldenorm_add
+ add.ne r0,r0,1 ; round to even.
+ rrc r0,r0
+ bmsk r1,r9,23
+ add r0,r0,r1 ; increment exponent
+ bic.f 0,r9,r0; check for overflow -> infinity.
+ jne_l [blink]
+ mov_s r0,r9
+ j_s.d [blink]
+ bset.cs r0,r0,31
+
+.Ldenorm_add:
+ j_s.d [blink]
+ add r0,r4,r1
+
+.Lret_dbl0:
+ j_s [blink]
+
+ .balign 4
+.Lsmall_shift:
+ brhi r12,25,.Lret_dbl0
+ breq.d r6,0,.Ldenorm_small_shift
+ bmsk_s r1,r1,22
+ bset_s r1,r1,23
+.Lfixed_denorm_small_shift:
+ neg r8,r12
+ asl r5,r1,r8
+ brge.d r10,0,.Ladd
+ lsr_l r1,r1,r12
+/* subtract, abs(DBL0) > abs(DBL1) */
+/* DBL0: original values
+ DBL1: fraction with explicit leading 1, shifted into place
+ r4: orig. DBL0 & 0x7fffffff
+ r6: orig. DBL1 & 0x7f800000
+ r9: 0x7f800000
+ r10: orig. DBL0H ^ DBL1H
+ r5 : guard bits */
+ .balign 4
+.Lsub:
+ neg.f r12,r5
+ bmsk r3,r0,22
+ bset r5,r3,23
+ sbc.f r4,r5,r1
+ beq.d .Large_cancel_sub
+ bic r7,r0,r3
+ norm r3,r4
+ bmsk r6,r7,30
+.Lsub_done:
+ sub_s r3,r3,6
+ breq r3,1,.Lsub_done_noshift
+ asl r5,r3,23
+ sub_l r3,r3,1
+ brlo r6,r5,.Ldenorm_sub
+ sub r0,r7,r5
+ neg_s r1,r3
+ lsr.f r2,r12,r1
+ asl_s r12,r12,r3
+ btst_s r2,0
+ bmsk.eq.f r12,r12,30
+ asl r5,r4,r3
+ add_s r0,r0,r2
+ adc.ne r0,r0,0
+ j_s.d [blink]
+ add_l r0,r0,r5
+
+.Lret0:
+ j_s.d [blink]
+ mov_l r0,0
+
+ .balign 4
+.Ldenorm_small_shift:
+ brne.d r12,1,.Lfixed_denorm_small_shift
+ sub_s r12,r12,1
+ brlt.d r10,0,.Lsub
+ mov_s r5,r12 ; zero r5, and align following code
+.Ladd: ; Both bit 23 of DBL1 and bit 0 of r5 are clear.
+ bmsk r2,r0,22
+ add_s r2,r2,r1
+ bbit0.d r2,23,.Lno_shiftdown
+ add_s r0,r0,r1
+ bic.f 0,r9,r0; check for overflow -> infinity; eq : infinity
+ bmsk r1,r2,22
+ lsr.ne.f r2,r2,2; cc: even ; hi: might round down
+ lsr.ne r1,r1,1
+ rcmp.hi r5,1; hi : round down
+ bclr.hi r0,r0,0
+ j_l.d [blink]
+ sub_s r0,r0,r1
+
+/* r4: DBL0H & 0x7fffffff
+ r6: DBL1H & 0x7f800000
+ r9: 0x7f800000
+ r10: sign difference
+ r12: shift count (negative) */
+ .balign 4
+.Ldbl1_gt:
+ brhs r6,r9,.Lret_dbl1 ; inf or NaN
+ neg r8,r12
+ brhi r8,25,.Lret_dbl1
+.Lsmall_shift_dbl0:
+ breq.d r6,0,.Ldenorm_small_shift_dbl0
+ bmsk_s r0,r0,22
+ bset_s r0,r0,23
+.Lfixed_denorm_small_shift_dbl0:
+ asl r5,r0,r12
+ brge.d r10,0,.Ladd_dbl1_gt
+ lsr r0,r0,r8
+/* subtract, abs(DBL0) < abs(DBL1) */
+/* DBL0: fraction with explicit leading 1, shifted into place
+ DBL1: original value
+ r6: orig. DBL1 & 0x7f800000
+ r9: 0x7f800000
+ r5: guard bits */
+ .balign 4
+.Lrsub:
+ neg.f r12,r5
+ bmsk r5,r1,22
+ bic r7,r1,r5
+ bset r5,r5,23
+ sbc.f r4,r5,r0
+ bne.d .Lsub_done ; note: r6 is already set up.
+ norm r3,r4
+ /* Fall through */
+
+/* r4:r12 : unnormalized result fraction
+ r7: result sign and exponent */
+/* When seeing large cancellation, only the topmost guard bit might be set. */
+ .balign 4
+.Large_cancel_sub:
+ breq_s r12,0,.Lret0
+ sub r0,r7,24<<23
+ xor.f 0,r0,r7 ; test if exponent is negative
+ tst.pl r9,r0 ; test if exponent is zero
+ jpnz [blink] ; return if non-denormal result
+ bmsk r6,r7,30
+ lsr r3,r6,23
+ xor r0,r6,r7
+ sub_s r3,r3,24-22
+ j_s.d [blink]
+ bset r0,r0,r3
+
+ ; If a denorm is produced, we have an exact result -
+ ; no need for rounding.
+ .balign 4
+.Ldenorm_sub:
+ sub r3,r6,1
+ lsr.f r3,r3,23
+ xor r0,r6,r7
+ neg_s r1,r3
+ asl.ne r4,r4,r3
+ lsr_s r12,r12,r1
+ add_s r0,r0,r4
+ j_s.d [blink]
+ add.ne r0,r0,r12
+
+ .balign 4
+.Lsub_done_noshift:
+ add.f 0,r12,r12
+ btst.eq r4,0
+ bclr r4,r4,23
+ add r0,r7,r4
+ j_s.d [blink]
+ adc.ne r0,r0,0
+
+ .balign 4
+.Lno_shiftdown:
+ add.f 0,r5,r5
+ btst.eq r0,0
+ cmp.eq r5,r5
+ j_s.d [blink]
+ add.cs r0,r0,1
+
+.Lret_dbl1:
+ j_s.d [blink]
+ mov_l r0,r1
+ .balign 4
+.Ldenorm_small_shift_dbl0:
+ sub.f r8,r8,1
+ bne.d .Lfixed_denorm_small_shift_dbl0
+ add_s r12,r12,1
+ brlt.d r10,0,.Lrsub
+ mov r5,0
+.Ladd_dbl1_gt: ; both bit 23 of DBL0 and bit 0 of r5 are clear.
+ bmsk r2,r1,22
+ add_s r2,r2,r0
+ bbit0.d r2,23,.Lno_shiftdown_dbl1_gt
+ add_s r0,r1,r0
+ bic.f 0,r9,r0; check for overflow -> infinity; eq : infinity
+ bmsk r1,r2,22
+ lsr.ne.f r2,r2,2; cc: even ; hi: might round down
+ lsr.ne r1,r1,1
+ rcmp.hi r5,1; hi : round down
+ bclr.hi r0,r0,0
+ j_l.d [blink]
+ sub_s r0,r0,r1
+
+ .balign 4
+.Lno_shiftdown_dbl1_gt:
+ add.f 0,r5,r5
+ btst.eq r0,0
+ cmp.eq r5,r5
+ j_s.d [blink]
+ add.cs r0,r0,1
+ ENDFUNC(__addsf3)
+ ENDFUNC(__subsf3)
diff --git a/libgcc/config/arc/ieee-754/arc-ieee-754.h b/libgcc/config/arc/ieee-754/arc-ieee-754.h
new file mode 100644
index 00000000000..22fcb81bfa2
--- /dev/null
+++ b/libgcc/config/arc/ieee-754/arc-ieee-754.h
@@ -0,0 +1,56 @@
+/* Copyright (C) 2008-2013 Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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/>. */
+
+#ifdef __LITTLE_ENDIAN__
+#define DBL0L r0
+#define DBL0H r1
+#define DBL1L r2
+#define DBL1H r3
+#else
+#define DBL0L r1
+#define DBL0H r0
+#define DBL1L r3
+#define DBL1H r2
+#endif
+#define add_l add
+#define asr_l asr
+#define j_l j
+#define jne_l jne
+#define jeq_l jeq
+#define or_l or
+#define mov_l mov
+#define b_l b
+#define beq_l beq
+#define bne_l bne
+#define brne_l brne
+#define bset_l bset
+#define sub_l sub
+#define sub1_l sub1
+#define lsr_l lsr
+#define xor_l xor
+#define bic_l bic
+#define bmsk_l bmsk
+#define bxor_l bxor
+#define bcs_s blo_s
diff --git a/libgcc/config/arc/ieee-754/arc600-dsp/divdf3.S b/libgcc/config/arc/ieee-754/arc600-dsp/divdf3.S
new file mode 100644
index 00000000000..e54d31d87d1
--- /dev/null
+++ b/libgcc/config/arc/ieee-754/arc600-dsp/divdf3.S
@@ -0,0 +1,421 @@
+/* Copyright (C) 2008-2013 Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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/>. */
+
+/*
+ to calculate a := b/x as b*y, with y := 1/x:
+ - x is in the range [1..2)
+ - calculate 15..18 bit inverse y0 using a table of approximating polynoms.
+ Precision is higher for polynoms used to evaluate input with larger
+ value.
+ - Do one newton-raphson iteration step to double the precision,
+ then multiply this with the divisor
+ -> more time to decide if dividend is subnormal
+ - the worst error propagation is on the side of the value range
+ with the least initial defect, thus giving us about 30 bits precision.
+ The truncation error for the either is less than 1 + x/2 ulp.
+ A 31 bit inverse can be simply calculated by using x with implicit 1
+ and chaining the multiplies. For a 32 bit inverse, we multiply y0^2
+ with the bare fraction part of x, then add in y0^2 for the implicit
+ 1 of x.
+ - If calculating a 31 bit inverse, the systematic error is less than
+ -1 ulp; likewise, for 32 bit, it is less than -2 ulp.
+ - If we calculate our seed with a 32 bit fraction, we can archive a
+ tentative result strictly better than -2 / +2.5 (1) ulp/128, i.e. we
+ only need to take the step to calculate the 2nd stage rest and
+ rounding adjust 1/32th of the time. However, if we use a 20 bit
+ fraction for the seed, the negative error can exceed -2 ulp/128, (2)
+ thus for a simple add / tst check, we need to do the 2nd stage
+ rest calculation/ rounding adjust 1/16th of the time.
+ (1): The inexactness of the 32 bit inverse contributes an error in the
+ range of (-1 .. +(1+x/2) ) ulp/128. Leaving out the low word of the
+ rest contributes an error < +1/x ulp/128 . In the interval [1,2),
+ x/2 + 1/x <= 1.5 .
+ (2): Unless proven otherwise. I have not actually looked for an
+ example where -2 ulp/128 is exceeded, and my calculations indicate
+ that the excess, if existent, is less than -1/512 ulp.
+ ??? The algorithm is still based on the ARC700 optimized code.
+ Maybe we could make better use of 32x16 bit multiply, or 64 bit multiply
+ results.
+ */
+#include "../arc-ieee-754.h"
+#define mlo acc2
+#define mhi acc1
+#define mul64(b,c) mullw 0,b,c` machlw 0,b,c
+#define mulu64(b,c) mululw 0,b,c` machulw 0,b,c
+
+/* N.B. fp-bit.c does double rounding on denormal numbers. */
+#if 0 /* DEBUG */
+ .global __divdf3
+ FUNC(__divdf3)
+ .balign 4
+__divdf3:
+ push_s blink
+ push_s r2
+ push_s r3
+ push_s r0
+ bl.d __divdf3_c
+ push_s r1
+ ld_s r2,[sp,12]
+ ld_s r3,[sp,8]
+ st_s r0,[sp,12]
+ st_s r1,[sp,8]
+ pop_s r1
+ bl.d __divdf3_asm
+ pop_s r0
+ pop_s r3
+ pop_s r2
+ pop_s blink
+ cmp r0,r2
+ cmp.eq r1,r3
+ jeq_s [blink]
+ and r12,DBL0H,DBL1H
+ bic.f 0,0x7ff80000,r12 ; both NaN -> OK
+ jeq_s [blink]
+ bl abort
+ ENDFUNC(__divdf3)
+#define __divdf3 __divdf3_asm
+#endif /* DEBUG */
+
+ FUNC(__divdf3)
+ .balign 4
+.L7ff00000:
+ .long 0x7ff00000
+.Ldivtab:
+ .long 0xfc0fffe1
+ .long 0xf46ffdfb
+ .long 0xed1ffa54
+ .long 0xe61ff515
+ .long 0xdf7fee75
+ .long 0xd91fe680
+ .long 0xd2ffdd52
+ .long 0xcd1fd30c
+ .long 0xc77fc7cd
+ .long 0xc21fbbb6
+ .long 0xbcefaec0
+ .long 0xb7efa100
+ .long 0xb32f92bf
+ .long 0xae8f83b7
+ .long 0xaa2f7467
+ .long 0xa5ef6479
+ .long 0xa1cf53fa
+ .long 0x9ddf433e
+ .long 0x9a0f3216
+ .long 0x965f2091
+ .long 0x92df0f11
+ .long 0x8f6efd05
+ .long 0x8c1eeacc
+ .long 0x88eed876
+ .long 0x85dec615
+ .long 0x82eeb3b9
+ .long 0x800ea10b
+ .long 0x7d3e8e0f
+ .long 0x7a8e7b3f
+ .long 0x77ee6836
+ .long 0x756e5576
+ .long 0x72fe4293
+ .long 0x709e2f93
+ .long 0x6e4e1c7f
+ .long 0x6c0e095e
+ .long 0x69edf6c5
+ .long 0x67cde3a5
+ .long 0x65cdd125
+ .long 0x63cdbe25
+ .long 0x61ddab3f
+ .long 0x600d991f
+ .long 0x5e3d868c
+ .long 0x5c6d7384
+ .long 0x5abd615f
+ .long 0x590d4ecd
+ .long 0x576d3c83
+ .long 0x55dd2a89
+ .long 0x545d18e9
+ .long 0x52dd06e9
+ .long 0x516cf54e
+ .long 0x4ffce356
+ .long 0x4e9cd1ce
+ .long 0x4d3cbfec
+ .long 0x4becae86
+ .long 0x4aac9da4
+ .long 0x496c8c73
+ .long 0x483c7bd3
+ .long 0x470c6ae8
+ .long 0x45dc59af
+ .long 0x44bc4915
+ .long 0x43ac3924
+ .long 0x428c27fb
+ .long 0x418c187a
+ .long 0x407c07bd
+
+__divdf3_support: /* This label makes debugger output saner. */
+ .balign 4
+.Ldenorm_dbl1:
+ brge r6, \
+ 0x43500000,.Linf_NaN ; large number / denorm -> Inf
+ bmsk.f r12,DBL1H,19
+ mov.eq r12,DBL1L
+ mov.eq DBL1L,0
+ sub.eq r7,r7,32
+ norm.f r11,r12 ; flag for x/0 -> Inf check
+ beq_s .Linf_NaN
+ mov.mi r11,0
+ add.pl r11,r11,1
+ add_s r12,r12,r12
+ asl r8,r12,r11
+ rsub r12,r11,31
+ lsr r12,DBL1L,r12
+ tst_s DBL1H,DBL1H
+ or r8,r8,r12
+ lsr r4,r8,26
+ lsr DBL1H,r8,12
+ ld.as r4,[r10,r4]
+ bxor.mi DBL1H,DBL1H,31
+ sub r11,r11,11
+ asl DBL1L,DBL1L,r11
+ sub r11,r11,1
+ mulu64 (r4,r8)
+ sub r7,r7,r11
+ b.d .Lpast_denorm_dbl1
+ asl r7,r7,20
+
+.Linf_NaN:
+ tst_s DBL0L,DBL0L ; 0/0 -> NaN
+ xor_s DBL1H,DBL1H,DBL0H
+ bclr.eq.f DBL0H,DBL0H,31
+ bmsk DBL0H,DBL1H,30
+ xor_s DBL0H,DBL0H,DBL1H
+ sub.eq DBL0H,DBL0H,1
+ mov_s DBL0L,0
+ j_s.d [blink]
+ or DBL0H,DBL0H,r9
+ .balign 4
+.Lret0_2:
+ xor_s DBL1H,DBL1H,DBL0H
+ mov_s DBL0L,0
+ bmsk DBL0H,DBL1H,30
+ j_s.d [blink]
+ xor_s DBL0H,DBL0H,DBL1H
+ .balign 4
+ .global __divdf3
+/* N.B. the spacing between divtab and the sub3 to get its address must
+ be a multiple of 8. */
+__divdf3:
+ asl r8,DBL1H,12
+ lsr r4,r8,26
+ sub3 r10,pcl,51;(.-.Ldivtab) >> 3
+ ld.as r9,[pcl,-104]; [pcl,(-((.-.L7ff00000) >> 2))] ; 0x7ff00000
+ ld.as r4,[r10,r4]
+ lsr r12,DBL1L,20
+ and.f r7,DBL1H,r9
+ or r8,r8,r12
+ mulu64 (r4,r8)
+ beq.d .Ldenorm_dbl1
+.Lpast_denorm_dbl1:
+ and.f r6,DBL0H,r9
+ breq.d r7,r9,.Linf_nan_dbl1
+ asl r4,r4,12
+ sub r4,r4,mhi
+ mululw 0,r4,r4
+ machulw r5,r4,r4
+ bne.d .Lnormal_dbl0
+ lsr r8,r8,1
+
+ .balign 4
+.Ldenorm_dbl0:
+ bmsk.f r12,DBL0H,19
+ ; wb stall
+ mov.eq r12,DBL0L
+ sub.eq r6,r6,32
+ norm.f r11,r12 ; flag for 0/x -> 0 check
+ brge r7, \
+ 0x43500000, .Lret0_2 ; denorm/large number -> 0
+ beq_s .Lret0_2
+ mov.mi r11,0
+ add.pl r11,r11,1
+ asl r12,r12,r11
+ sub r6,r6,r11
+ add.f 0,r6,31
+ lsr r10,DBL0L,r6
+ mov.mi r10,0
+ add r6,r6,11+32
+ neg.f r11,r6
+ asl DBL0L,DBL0L,r11
+ mov.pl DBL0L,0
+ sub r6,r6,32-1
+ b.d .Lpast_denorm_dbl0
+ asl r6,r6,20
+
+ .balign 4
+.Linf_nan_dbl1: ; 0/Inf -> NaN Inf/Inf -> NaN x/Inf-> 0 x/NaN -> NaN
+ or.f 0,r6,DBL0L
+ cmp.ne r6,r9
+ not_s DBL0L,DBL1H
+ sub_s.ne DBL0L,DBL0L,DBL0L
+ tst_s DBL0H,DBL0H
+ add_s DBL0H,DBL1H,DBL0L
+ j_s.d [blink]
+ bxor.mi DBL0H,DBL0H,31
+
+ .balign 4
+.Lnormal_dbl0:
+ breq.d r6,r9,.Linf_nan_dbl0
+ asl r12,DBL0H,11
+ lsr r10,DBL0L,21
+.Lpast_denorm_dbl0:
+ bset r8,r8,31
+ mulu64 (r5,r8)
+ add_s r12,r12,r10
+ bset r5,r12,31
+ cmp r5,r8
+ cmp.eq DBL0L,DBL1L
+ lsr.cc r5,r5,1
+ sub r4,r4,mhi ; u1.31 inverse, about 30 bit
+ mululw 0,r5,r4
+ machulw r11,r5,r4 ; result fraction highpart
+ lsr r8,r8,2 ; u3.29
+ add r5,r6, /* wait for immediate */ \
+ 0x3fe00000
+ mulu64 (r11,r8) ; u-28.31
+ asl_s DBL1L,DBL1L,9 ; u-29.23:9
+ sbc r6,r5,r7
+ mov r12,mlo ; u-28.31
+ mulu64 (r11,DBL1L) ; mhi: u-28.23:9
+ add.cs DBL0L,DBL0L,DBL0L
+ asl_s DBL0L,DBL0L,6 ; u-26.25:7
+ asl r10,r11,23
+ sub_l DBL0L,DBL0L,r12
+ lsr r7,r11,9
+ sub r5,DBL0L,mhi ; rest msw ; u-26.31:0
+ mul64 (r5,r4) ; mhi: result fraction lowpart
+ xor.f 0,DBL0H,DBL1H
+ and DBL0H,r6,r9
+ add_s DBL0H,DBL0H,r7
+ bclr r12,r9,20 ; 0x7fe00000
+ brhs.d r6,r12,.Linf_denorm
+ bxor.mi DBL0H,DBL0H,31
+ add.f r12,mhi,0x11
+ asr r9,r12,5
+ sub.mi DBL0H,DBL0H,1
+ add.f DBL0L,r9,r10
+ tst r12,0x1c
+ jne.d [blink]
+ add.cs DBL0H,DBL0H,1
+ /* work out exact rounding if we fall through here. */
+ /* We know that the exact result cannot be represented in double
+ precision. Find the mid-point between the two nearest
+ representable values, multiply with the divisor, and check if
+ the result is larger than the dividend. Since we want to know
+ only the sign bit, it is sufficient to calculate only the
+ highpart of the lower 64 bits. */
+ mulu64 (r11,DBL1L) ; rest before considering r12 in r5 : -mlo
+ sub.f DBL0L,DBL0L,1
+ asl r12,r9,2 ; u-22.30:2
+ sub.cs DBL0H,DBL0H,1
+ sub.f r12,r12,2
+ mov r10,mlo ; rest before considering r12 in r5 : -r10
+ mululw 0,r12,DBL1L
+ machulw r7,r12,DBL1L ; mhi: u-51.32
+ asl r5,r5,25 ; s-51.7:25
+ lsr r10,r10,7 ; u-51.30:2
+ mulu64 (r12,r8) ; mlo: u-51.31:1
+ sub r5,r5,r10
+ add.mi r5,r5,DBL1L ; signed multiply adjust for r12*DBL1L
+ bset r7,r7,0 ; make sure that the result is not zero, and that
+ sub r5,r5,r7 ; a highpart zero appears negative
+ sub.f r5,r5,mlo ; rest msw
+ add.pl.f DBL0L,DBL0L,1
+ j_s.d [blink]
+ add.eq DBL0H,DBL0H,1
+
+.Linf_nan_dbl0:
+ tst_s DBL1H,DBL1H
+ j_s.d [blink]
+ bxor.mi DBL0H,DBL0H,31
+ .balign 4
+.Linf_denorm:
+ lsr r12,r6,28
+ brlo.d r12,0xc,.Linf
+.Ldenorm:
+ asr r6,r6,20
+ neg r9,r6
+ mov_s DBL0H,0
+ brhs.d r9,54,.Lret0
+ bxor.mi DBL0H,DBL0H,31
+ add r12,mhi,1
+ and r12,r12,-4
+ rsub r7,r6,5
+ asr r10,r12,28
+ bmsk r4,r12,27
+ min r7,r7,31
+ asr DBL0L,r4,r7
+ add DBL1H,r11,r10
+ abs.f r10,r4
+ sub.mi r10,r10,1
+ add.f r7,r6,32-5
+ asl r4,r4,r7
+ mov.mi r4,r10
+ add.f r10,r6,23
+ rsub r7,r6,9
+ lsr r7,DBL1H,r7
+ asl r10,DBL1H,r10
+ or.pnz DBL0H,DBL0H,r7
+ or.mi r4,r4,r10
+ mov.mi r10,r7
+ add.f DBL0L,r10,DBL0L
+ add.cs.f DBL0H,DBL0H,1 ; carry clear after this point
+ bxor.f 0,r4,31
+ add.pnz.f DBL0L,DBL0L,1
+ add.cs.f DBL0H,DBL0H,1
+ jne_s [blink]
+ /* Calculation so far was not conclusive; calculate further rest. */
+ mulu64 (r11,DBL1L) ; rest before considering r12 in r5 : -mlo
+ asr.f r12,r12,3
+ asl r5,r5,25 ; s-51.7:25
+ mov r11,mlo ; rest before considering r12 in r5 : -r11
+ mulu64 (r12,r8) ; u-51.31:1
+ and r9,DBL0L,1 ; tie-breaker: round to even
+ lsr r11,r11,7 ; u-51.30:2
+ mov DBL1H,mlo ; u-51.31:1
+ mulu64 (r12,DBL1L) ; u-51.62:2
+ sub.mi r11,r11,DBL1L ; signed multiply adjust for r12*DBL1L
+ add_s DBL1H,DBL1H,r11
+ sub DBL1H,DBL1H,r5 ; -rest msw
+ add_s DBL1H,DBL1H,mhi ; -rest msw
+ add.f 0,DBL1H,DBL1H ; can't ror.f by 32 :-(
+ tst_s DBL1H,DBL1H
+ cmp.eq mlo,r9
+ add.cs.f DBL0L,DBL0L,1
+ j_s.d [blink]
+ add.cs DBL0H,DBL0H,1
+
+.Lret0:
+ /* return +- 0 */
+ j_s.d [blink]
+ mov_s DBL0L,0
+.Linf:
+ mov_s DBL0H,r9
+ mov_s DBL0L,0
+ j_s.d [blink]
+ bxor.mi DBL0H,DBL0H,31
+ ENDFUNC(__divdf3)
diff --git a/libgcc/config/arc/ieee-754/arc600-dsp/divsf3.S b/libgcc/config/arc/ieee-754/arc600-dsp/divsf3.S
new file mode 100644
index 00000000000..da25c711376
--- /dev/null
+++ b/libgcc/config/arc/ieee-754/arc600-dsp/divsf3.S
@@ -0,0 +1,274 @@
+/* Copyright (C) 2008-2013 Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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/>. */
+
+/*
+ - calculate 15..18 bit inverse using a table of approximating polynoms.
+ precision is higher for polynoms used to evaluate input with larger
+ value.
+ - do one newton-raphson iteration step to double the precision,
+ then multiply this with the divisor
+ -> more time to decide if dividend is subnormal
+ - the worst error propagation is on the side of the value range
+ with the least initial defect, thus giving us about 30 bits precision.
+ */
+#include "../arc-ieee-754.h"
+#define mlo acc2
+#define mhi acc1
+#define mul64(b,c) mullw 0,b,c` machlw 0,b,c
+#define mulu64(b,c) mululw 0,b,c` machulw 0,b,c
+
+#if 0 /* DEBUG */
+ .global __divsf3
+ FUNC(__divsf3)
+ .balign 4
+__divsf3:
+ push_s blink
+ push_s r1
+ bl.d __divsf3_c
+ push_s r0
+ ld_s r1,[sp,4]
+ st_s r0,[sp,4]
+ bl.d __divsf3_asm
+ pop_s r0
+ pop_s r1
+ pop_s blink
+ cmp r0,r1
+#if 1
+ bne abort
+ jeq_s [blink]
+ b abort
+#else
+ bne abort
+ j_s [blink]
+#endif
+ ENDFUNC(__divsf3)
+#define __divsf3 __divsf3_asm
+#endif /* DEBUG */
+
+ FUNC(__divsf3)
+ .balign 4
+.Ldivtab:
+ .long 0xfc0ffff0
+ .long 0xf46ffefd
+ .long 0xed1ffd2a
+ .long 0xe627fa8e
+ .long 0xdf7ff73b
+ .long 0xd917f33b
+ .long 0xd2f7eea3
+ .long 0xcd1fe986
+ .long 0xc77fe3e7
+ .long 0xc21fdddb
+ .long 0xbcefd760
+ .long 0xb7f7d08c
+ .long 0xb32fc960
+ .long 0xae97c1ea
+ .long 0xaa27ba26
+ .long 0xa5e7b22e
+ .long 0xa1cfa9fe
+ .long 0x9ddfa1a0
+ .long 0x9a0f990c
+ .long 0x9667905d
+ .long 0x92df878a
+ .long 0x8f6f7e84
+ .long 0x8c27757e
+ .long 0x88f76c54
+ .long 0x85df630c
+ .long 0x82e759c5
+ .long 0x8007506d
+ .long 0x7d3f470a
+ .long 0x7a8f3da2
+ .long 0x77ef341e
+ .long 0x756f2abe
+ .long 0x72f7212d
+ .long 0x709717ad
+ .long 0x6e4f0e44
+ .long 0x6c1704d6
+ .long 0x69e6fb44
+ .long 0x67cef1d7
+ .long 0x65c6e872
+ .long 0x63cedf18
+ .long 0x61e6d5cd
+ .long 0x6006cc6d
+ .long 0x5e36c323
+ .long 0x5c76b9f3
+ .long 0x5abeb0b7
+ .long 0x5916a79b
+ .long 0x57769e77
+ .long 0x55de954d
+ .long 0x54568c4e
+ .long 0x52d6834d
+ .long 0x51667a7f
+ .long 0x4ffe71b5
+ .long 0x4e9e68f1
+ .long 0x4d466035
+ .long 0x4bf65784
+ .long 0x4aae4ede
+ .long 0x496e4646
+ .long 0x48363dbd
+ .long 0x47063547
+ .long 0x45de2ce5
+ .long 0x44be2498
+ .long 0x43a61c64
+ .long 0x4296144a
+ .long 0x41860c0e
+ .long 0x407e03ee
+.L7f800000:
+ .long 0x7f800000
+ .balign 4
+ .global __divsf3_support
+__divsf3_support:
+.Linf_NaN:
+ bclr.f 0,r0,31 ; 0/0 -> NaN
+ xor_s r0,r0,r1
+ bmsk r1,r0,30
+ bic_s r0,r0,r1
+ sub.eq r0,r0,1
+ j_s.d [blink]
+ or r0,r0,r9
+.Lret0:
+ xor_s r0,r0,r1
+ bmsk r1,r0,30
+ j_s.d [blink]
+ bic_s r0,r0,r1
+/* N.B. the spacing between divtab and the sub3 to get its address must
+ be a multiple of 8. */
+__divsf3:
+ ld.as r9,[pcl,-9]; [pcl,(-((.-.L7f800000) >> 2))] ; 0x7f800000
+ sub3 r3,pcl,37;(.-.Ldivtab) >> 3
+ lsr r2,r1,17
+ and.f r11,r1,r9
+ bmsk r5,r2,5
+ beq.d .Ldenorm_fp1
+ asl r6,r1,8
+ and.f r2,r0,r9
+ ld.as r5,[r3,r5]
+ asl r4,r1,9
+ bset r6,r6,31
+ breq.d r11,r9,.Linf_nan_fp1
+.Lpast_denorm_fp1:
+ mululw 0,r5,r4
+ machulw r8,r5,r4
+ breq.d r2,r9,.Linf_nan_fp0
+ asl r5,r5,13
+ sub r7,r5,r8
+ mululw 0,r7,r6
+ machulw r8,r7,r6
+ beq.d .Ldenorm_fp0
+ asl r12,r0,8
+ mulu64 (r8,r7)
+ bset r3,r12,31
+.Lpast_denorm_fp0:
+ cmp_s r3,r6
+ lsr.cc r3,r3,1
+ add_s r2,r2, /* wait for immediate */ \
+ 0x3f000000
+ sub r7,r7,mhi ; u1.31 inverse, about 30 bit
+ mulu64 (r3,r7)
+ sbc r2,r2,r11
+ xor.f 0,r0,r1
+ and r0,r2,r9
+ bclr r3,r9,23 ; 0x7f000000
+ brhs.d r2,r3,.Linf_denorm
+ bxor.mi r0,r0,31
+.Lpast_denorm:
+ add r3,mhi,0x22 ; round to nearest or higher
+ tst r3,0x3c ; check if rounding was unsafe
+ lsr r3,r3,6
+ jne.d [blink] ; return if rounding was safe.
+ add_s r0,r0,r3
+ /* work out exact rounding if we fall through here. */
+ /* We know that the exact result cannot be represented in single
+ precision. Find the mid-point between the two nearest
+ representable values, multiply with the divisor, and check if
+ the result is larger than the dividend. */
+ add_s r3,r3,r3
+ sub_s r3,r3,1
+ mulu64 (r3,r6)
+ asr.f 0,r0,1 ; for round-to-even in case this is a denorm
+ rsub r2,r9,25
+ asl_s r12,r12,r2
+ sub.f 0,r12,mlo
+ j_s.d [blink]
+ sub.mi r0,r0,1
+.Linf_nan_fp1:
+ lsr_s r0,r0,31
+ bmsk.f 0,r1,22
+ asl_s r0,r0,31
+ bne_s 0f ; inf/inf -> nan
+ brne r2,r9,.Lsigned0 ; x/inf -> 0, but x/nan -> nan
+0: j_s.d [blink]
+ mov r0,-1
+.Lsigned0:
+.Linf_nan_fp0:
+ tst_s r1,r1
+ j_s.d [blink]
+ bxor.mi r0,r0,31
+ .balign 4
+ .global __divsf3
+/* For denormal results, it is possible that an exact result needs
+ rounding, and thus the round-to-even rule has to come into play. */
+.Linf_denorm:
+ brlo r2,0xc0000000,.Linf
+.Ldenorm:
+ asr_s r2,r2,23
+ bic r0,r0,r9
+ neg r9,r2
+ brlo.d r9,25,.Lpast_denorm
+ lsr r3,mlo,r9
+ /* Fall through: return +- 0 */
+ j_s [blink]
+.Linf:
+ j_s.d [blink]
+ or r0,r0,r9
+ .balign 4
+.Ldenorm_fp1:
+ norm.f r12,r6 ; flag for x/0 -> Inf check
+ add r6,r6,r6
+ rsub r5,r12,16
+ ror r5,r1,r5
+ bmsk r5,r5,5
+ bic.ne.f 0, \
+ 0x60000000,r0 ; large number / denorm -> Inf
+ ld.as r5,[r3,r5]
+ asl r6,r6,r12
+ beq.d .Linf_NaN
+ and.f r2,r0,r9
+ add r4,r6,r6
+ asl_s r12,r12,23
+ bne.d .Lpast_denorm_fp1
+ add_s r2,r2,r12
+.Ldenorm_fp0:
+ mulu64 (r8,r7)
+ bclr r12,r12,31
+ norm.f r3,r12 ; flag for 0/x -> 0 check
+ bic.ne.f 0,0x60000000,r1 ; denorm/large number -> 0
+ beq_s .Lret0
+ asl_s r12,r12,r3
+ asl_s r3,r3,23
+ add_s r12,r12,r12
+ add r11,r11,r3
+ b.d .Lpast_denorm_fp0
+ mov_s r3,r12
+ ENDFUNC(__divsf3)
diff --git a/libgcc/config/arc/ieee-754/arc600-dsp/muldf3.S b/libgcc/config/arc/ieee-754/arc600-dsp/muldf3.S
new file mode 100644
index 00000000000..88c541bf700
--- /dev/null
+++ b/libgcc/config/arc/ieee-754/arc600-dsp/muldf3.S
@@ -0,0 +1,231 @@
+/* Copyright (C) 2008-2013 Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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/>. */
+
+#include "../arc-ieee-754.h"
+
+#if 0 /* DEBUG */
+ .global __muldf3
+ .balign 4
+__muldf3:
+ push_s blink
+ push_s r2
+ push_s r3
+ push_s r0
+ bl.d __muldf3_c
+ push_s r1
+ ld_s r2,[sp,12]
+ ld_s r3,[sp,8]
+ st_s r0,[sp,12]
+ st_s r1,[sp,8]
+ pop_s r1
+ bl.d __muldf3_asm
+ pop_s r0
+ pop_s r3
+ pop_s r2
+ pop_s blink
+ cmp r0,r2
+ cmp.eq r1,r3
+ jeq_s [blink]
+ b abort
+#define __muldf3 __muldf3_asm
+#endif /* DEBUG */
+
+__muldf3_support: /* This label makes debugger output saner. */
+ .balign 4
+ FUNC(__muldf3)
+.Ldenorm_2:
+ breq.d DBL1L,0,.Lret0_2 ; 0 input -> 0 output
+ norm.f r12,DBL1L
+ mov.mi r12,21
+ add.pl r12,r12,22
+ neg r11,r12
+ asl_s r12,r12,20
+ lsr.f DBL1H,DBL1L,r11
+ ror DBL1L,DBL1L,r11
+ sub_s DBL0H,DBL0H,r12
+ mov.eq DBL1H,DBL1L
+ sub_l DBL1L,DBL1L,DBL1H
+ /* Fall through. */
+ .global __muldf3
+ .balign 4
+__muldf3:
+ mululw 0,DBL0L,DBL1L
+ machulw r4,DBL0L,DBL1L
+ ld.as r9,[pcl,0x67] ; ((.L7ff00000-.+2)/4)]
+ bmsk r6,DBL0H,19
+ bset r6,r6,20
+ mov r8,acc2
+ mululw 0,r4,1
+ and r11,DBL0H,r9
+ breq.d r11,0,.Ldenorm_dbl0
+ and r12,DBL1H,r9
+ breq.d r12,0,.Ldenorm_dbl1
+ maclw 0,r6,DBL1L
+ machulw 0,r6,DBL1L
+ breq.d r11,r9,.Linf_nan
+ bmsk r10,DBL1H,19
+ breq.d r12,r9,.Linf_nan
+ bset r10,r10,20
+ maclw 0,r10,DBL0L
+ machulw r5,r10,DBL0L
+ add_s r12,r12,r11 ; add exponents
+ mov r4,acc2
+ mululw 0,r5,1
+ maclw 0,r6,r10
+ machulw r7,r6,r10 ; fraction product in r7:acc2:r4:r8
+ tst r8,r8
+ bclr r8,r9,30 ; 0x3ff00000
+ bset.ne r4,r4,0 ; put least significant word into sticky bit
+ bclr r6,r9,20 ; 0x7fe00000
+ lsr.f r10,r7,9
+ rsub.eq r8,r8,r9 ; 0x40000000
+ sub r12,r12,r8 ; subtract bias + implicit 1
+ brhs.d r12,r6,.Linf_denorm
+ rsub r10,r10,12
+.Lshift_frac:
+ neg r8,r10
+ asl r6,r4,r10
+ lsr DBL0L,r4,r8
+ add.f 0,r6,r6
+ btst.eq DBL0L,0
+ cmp.eq r4,r4 ; round to nearest / round to even
+ asl r4,acc2,r10
+ lsr r5,acc2,r8
+ adc.f DBL0L,DBL0L,r4
+ xor.f 0,DBL0H,DBL1H
+ asl r7,r7,r10
+ add_s r12,r12,r5
+ adc DBL0H,r12,r7
+ j_s.d [blink]
+ bset.mi DBL0H,DBL0H,31
+
+/* N.B. This is optimized for ARC700.
+ ARC600 has very different scheduling / instruction selection criteria. */
+
+/* If one number is denormal, subtract some from the exponent of the other
+ one (if the other exponent is too small, return 0), and normalize the
+ denormal. Then re-run the computation. */
+.Lret0_2:
+ lsr_s DBL0H,DBL0H,31
+ asl_s DBL0H,DBL0H,31
+ j_s.d [blink]
+ mov_s DBL0L,0
+ .balign 4
+.Ldenorm_dbl0:
+ mov_s r12,DBL0L
+ mov_s DBL0L,DBL1L
+ mov_s DBL1L,r12
+ mov_s r12,DBL0H
+ mov_s DBL0H,DBL1H
+ mov_s DBL1H,r12
+ and r11,DBL0H,r9
+.Ldenorm_dbl1:
+ brhs r11,r9,.Linf_nan
+ brhs 0x3ca00001,r11,.Lret0
+ sub_s DBL0H,DBL0H,DBL1H
+ bmsk.f DBL1H,DBL1H,30
+ add_s DBL0H,DBL0H,DBL1H
+ beq.d .Ldenorm_2
+ norm r12,DBL1H
+ sub_s r12,r12,10
+ asl r5,r12,20
+ asl_s DBL1H,DBL1H,r12
+ sub DBL0H,DBL0H,r5
+ neg r5,r12
+ lsr r6,DBL1L,r5
+ asl_s DBL1L,DBL1L,r12
+ b.d __muldf3
+ add_s DBL1H,DBL1H,r6
+
+.Lret0: xor_s DBL0H,DBL0H,DBL1H
+ bclr DBL1H,DBL0H,31
+ xor_s DBL0H,DBL0H,DBL1H
+ j_s.d [blink]
+ mov_s DBL0L,0
+
+ .balign 4
+.Linf_nan:
+ bclr r12,DBL1H,31
+ xor_s DBL1H,DBL1H,DBL0H
+ bclr_s DBL0H,DBL0H,31
+ max r8,DBL0H,r12 ; either NaN -> NaN ; otherwise inf
+ or.f 0,DBL0H,DBL0L
+ mov_s DBL0L,0
+ or.ne.f DBL1L,DBL1L,r12
+ not_s DBL0H,DBL0L ; inf * 0 -> NaN
+ mov.ne DBL0H,r8
+ tst_s DBL1H,DBL1H
+ j_s.d [blink]
+ bset.mi DBL0H,DBL0H,31
+
+/* We have checked for infinity / NaN input before, and transformed
+ denormalized inputs into normalized inputs. Thus, the worst case
+ exponent overflows are:
+ 1 + 1 - 0x400 == 0xc02 : maximum underflow
+ 0x7fe + 0x7fe - 0x3ff == 0xbfd ; maximum overflow
+ N.B. 0x7e and 0x7f are also values for overflow.
+
+ If (r12 <= -54), we have an underflow to zero. */
+ .balign 4
+.Linf_denorm:
+ lsr r6,r12,28
+ brlo.d r6,0xc,.Linf
+ asr r6,r12,20
+ add.f r10,r10,r6
+ brgt.d r10,0,.Lshift_frac
+ mov_s r12,0
+ beq.d .Lround_frac
+ add r10,r10,32
+.Lshift32_frac:
+ tst r4,r4
+ mov r4,acc2
+ bset.ne r4,r4,1
+ mululw 0,r7,1
+ brge.d r10,1,.Lshift_frac
+ mov r7,0
+ breq.d r10,0,.Lround_frac
+ add r10,r10,32
+ brgt r10,21,.Lshift32_frac
+ b_s .Lret0
+
+.Lround_frac:
+ add.f 0,r4,r4
+ btst.eq acc2,0
+ mov_s DBL0L,acc2
+ mov_s DBL0H,r7
+ adc.eq.f DBL0L,DBL0L,0
+ j_s.d [blink]
+ adc.eq DBL0H,DBL0H,0
+
+.Linf: mov_s DBL0L,0
+ xor.f DBL1H,DBL1H,DBL0H
+ mov_s DBL0H,r9
+ j_s.d [blink]
+ bset.mi DBL0H,DBL0H,31
+ ENDFUNC(__muldf3)
+
+ .balign 4
+.L7ff00000:
+ .long 0x7ff00000
diff --git a/libgcc/config/arc/ieee-754/arc600-dsp/mulsf3.S b/libgcc/config/arc/ieee-754/arc600-dsp/mulsf3.S
new file mode 100644
index 00000000000..b58146f0271
--- /dev/null
+++ b/libgcc/config/arc/ieee-754/arc600-dsp/mulsf3.S
@@ -0,0 +1,176 @@
+/* Copyright (C) 2008-2013 Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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/>. */
+
+#include "../arc-ieee-754.h"
+
+#if 0 /* DEBUG */
+ .global __mulsf3
+ FUNC(__mulsf3)
+ .balign 4
+__mulsf3:
+ push_s blink
+ push_s r1
+ bl.d __mulsf3_c
+ push_s r0
+ ld_s r1,[sp,4]
+ st_s r0,[sp,4]
+ bl.d __mulsf3_asm
+ pop_s r0
+ pop_s r1
+ pop_s blink
+ cmp r0,r1
+ jeq_s [blink]
+ and r12,r0,r1
+ bic.f 0,0x7f800000,r12
+ bne 0f
+ bmsk.f 0,r0,22
+ bmsk.ne.f r1,r1,22
+ jne_s [blink] ; both NaN -> OK
+0: bl abort
+ ENDFUNC(__mulsf3)
+#define __mulsf3 __mulsf3_asm
+#endif /* DEBUG */
+
+ .balign 4
+ .global __mulsf3
+ FUNC(__mulsf3)
+__mulsf3:
+ ld.as r9,[pcl,80]; [pcl,((.L7f800000-.+2)/4)]
+ bmsk r4,r1,22
+ bset r2,r0,23
+ asl_s r2,r2,8
+ bset r3,r4,23
+ and r11,r0,r9
+ breq.d r11,0,.Ldenorm_dbl0
+ and r12,r1,r9
+ breq.d r12,0,.Ldenorm_dbl1
+ xor_s r0,r0,r1
+ mululw 0,r2,r3
+ machulw r6,r2,r3
+ breq.d r11,r9,.Linf_nan_dbl0
+ ld.as r4,[pcl,69]; [pcl,((.L7fffffff-.+2)/4)]
+ breq.d r12,r9,.Linf_nan_dbl1
+.Lpast_denorm:
+ asl.f 0,r6,8
+ mov r7,acc2
+ add.pl r6,r6,r6
+ bclr.pl r6,r6,23
+ add.pl.f r7,r7,r7
+ add.cs r6,r6,1
+ lsr.f 0,r6,1
+ add_s r12,r12,r11
+ adc.f 0,r7,r4
+ add_s r12,r12, \
+ -0x3f800000
+ adc.f r8,r6,r12
+ tst.pl r8,r9
+ bic r0,r0,r4
+ min r3,r8,r9
+ jpnz.d [blink]
+ add.pnz r0,r0,r3
+; infinity or denormal number
+ add.ne.f r3,r3,r3
+ asr_s r3,r3,23+1
+ bset r6,r6,23
+ bpnz.d .Linfinity
+ sub_s r3,r3,1
+ neg_s r2,r3
+ brhi.d r2,24,.Lret_r0 ; right shift shift > 24 -> return +-0
+ lsr r2,r6,r2
+ asl r9,r6,r3
+ lsr.f 0,r2,1
+ tst r7,r7
+ add_s r0,r0,r2
+ bset.ne r9,r9,0
+ adc.f 0,r9,r4
+ j_s.d [blink]
+ add.cs r0,r0,1
+.Linfinity:
+ j_s.d [blink]
+ add_s r0,r0,r9
+
+.Lret_r0: j_s [blink]
+
+ .balign 4
+.Ldenorm_dbl0:
+ bclr_s r2,r2,31
+ norm.f r4,r2
+ add_s r2,r2,r2
+ asl r2,r2,r4
+ breq.d r12,r9,.Ldenorm_dbl0_inf_nan_dbl1
+ asl r4,r4,23
+ mululw 0,r2,r3
+ machulw r6,r2,r3
+ sub.ne.f r12,r12,r4
+ ld.as r4,[pcl,28]; [pcl,((.L7fffffff-.+2)/4)]
+ bhi.d .Lpast_denorm
+ xor_s r0,r0,r1
+ bmsk r1,r0,30
+ j_s.d [blink]
+ bic_s r0,r0,r1
+
+ .balign 4
+.Ldenorm_dbl0_inf_nan_dbl1:
+ bmsk.f 0,r0,30
+ mov.eq r1,-1
+.Linf_nan_dbl1:
+ xor_s r1,r1,r0
+.Linf_nan_dbl0:
+ bclr_s r1,r1,31
+ j_s.d [blink]
+ xor_s r0,r0,r1
+
+ .balign 4
+.Ldenorm_dbl1:
+ breq.d r11,r9,.Linf_nan_dbl0_2
+ norm.f r3,r4
+ sub_s r3,r3,7
+ asl r4,r4,r3
+ mululw 0,r2,r4
+ machulw r6,r2,r4
+ sub_s r3,r3,1
+ asl_s r3,r3,23
+ sub.ne.f r11,r11,r3
+ ld.as r4,[pcl,11]; [pcl,((.L7fffffff-.+2)/4)]
+ bhi.d .Lpast_denorm
+ bmsk r8,r0,30
+ j_s.d [blink]
+ bic r0,r0,r8
+
+ .balign 4
+.Linf_nan_dbl0_2:
+ bclr_s r1,r1,31
+ xor_s r0,r0,r1
+ sub.eq r1,r1,1 ; inf/nan * 0 -> nan
+ bic.f 0,r9,r1
+ j_s.d [blink]
+ or.eq r0,r0,r1 ; r1 nan -> result nan
+
+ .balign 4
+.L7f800000:
+ .long 0x7f800000
+.L7fffffff:
+ .long 0x7fffffff
+ ENDFUNC(__mulsf3)
diff --git a/libgcc/config/arc/ieee-754/arc600-mul64/divdf3.S b/libgcc/config/arc/ieee-754/arc600-mul64/divdf3.S
new file mode 100644
index 00000000000..0584b53f77b
--- /dev/null
+++ b/libgcc/config/arc/ieee-754/arc600-mul64/divdf3.S
@@ -0,0 +1,410 @@
+/* Copyright (C) 2008-2013 Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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/>. */
+
+/*
+ to calculate a := b/x as b*y, with y := 1/x:
+ - x is in the range [1..2)
+ - calculate 15..18 bit inverse y0 using a table of approximating polynoms.
+ Precision is higher for polynoms used to evaluate input with larger
+ value.
+ - Do one newton-raphson iteration step to double the precision,
+ then multiply this with the divisor
+ -> more time to decide if dividend is subnormal
+ - the worst error propagation is on the side of the value range
+ with the least initial defect, thus giving us about 30 bits precision.
+ The truncation error for the either is less than 1 + x/2 ulp.
+ A 31 bit inverse can be simply calculated by using x with implicit 1
+ and chaining the multiplies. For a 32 bit inverse, we multiply y0^2
+ with the bare fraction part of x, then add in y0^2 for the implicit
+ 1 of x.
+ - If calculating a 31 bit inverse, the systematic error is less than
+ -1 ulp; likewise, for 32 bit, it is less than -2 ulp.
+ - If we calculate our seed with a 32 bit fraction, we can archive a
+ tentative result strictly better than -2 / +2.5 (1) ulp/128, i.e. we
+ only need to take the step to calculate the 2nd stage rest and
+ rounding adjust 1/32th of the time. However, if we use a 20 bit
+ fraction for the seed, the negative error can exceed -2 ulp/128, (2)
+ thus for a simple add / tst check, we need to do the 2nd stage
+ rest calculation/ rounding adjust 1/16th of the time.
+ (1): The inexactness of the 32 bit inverse contributes an error in the
+ range of (-1 .. +(1+x/2) ) ulp/128. Leaving out the low word of the
+ rest contributes an error < +1/x ulp/128 . In the interval [1,2),
+ x/2 + 1/x <= 1.5 .
+ (2): Unless proven otherwise. I have not actually looked for an
+ example where -2 ulp/128 is exceeded, and my calculations indicate
+ that the excess, if existent, is less than -1/512 ulp.
+ ??? The algorithm is still based on the ARC700 optimized code.
+ Maybe we could make better use of 64 bit multiply results and/or mmed .
+ */
+#include "../arc-ieee-754.h"
+
+/* N.B. fp-bit.c does double rounding on denormal numbers. */
+#if 0 /* DEBUG */
+ .global __divdf3
+ FUNC(__divdf3)
+ .balign 4
+__divdf3:
+ push_s blink
+ push_s r2
+ push_s r3
+ push_s r0
+ bl.d __divdf3_c
+ push_s r1
+ ld_s r2,[sp,12]
+ ld_s r3,[sp,8]
+ st_s r0,[sp,12]
+ st_s r1,[sp,8]
+ pop_s r1
+ bl.d __divdf3_asm
+ pop_s r0
+ pop_s r3
+ pop_s r2
+ pop_s blink
+ cmp r0,r2
+ cmp.eq r1,r3
+ jeq_s [blink]
+ and r12,DBL0H,DBL1H
+ bic.f 0,0x7ff80000,r12 ; both NaN -> OK
+ jeq_s [blink]
+ bl abort
+ ENDFUNC(__divdf3)
+#define __divdf3 __divdf3_asm
+#endif /* DEBUG */
+
+ FUNC(__divdf3)
+ .balign 4
+.L7ff00000:
+ .long 0x7ff00000
+.Ldivtab:
+ .long 0xfc0fffe1
+ .long 0xf46ffdfb
+ .long 0xed1ffa54
+ .long 0xe61ff515
+ .long 0xdf7fee75
+ .long 0xd91fe680
+ .long 0xd2ffdd52
+ .long 0xcd1fd30c
+ .long 0xc77fc7cd
+ .long 0xc21fbbb6
+ .long 0xbcefaec0
+ .long 0xb7efa100
+ .long 0xb32f92bf
+ .long 0xae8f83b7
+ .long 0xaa2f7467
+ .long 0xa5ef6479
+ .long 0xa1cf53fa
+ .long 0x9ddf433e
+ .long 0x9a0f3216
+ .long 0x965f2091
+ .long 0x92df0f11
+ .long 0x8f6efd05
+ .long 0x8c1eeacc
+ .long 0x88eed876
+ .long 0x85dec615
+ .long 0x82eeb3b9
+ .long 0x800ea10b
+ .long 0x7d3e8e0f
+ .long 0x7a8e7b3f
+ .long 0x77ee6836
+ .long 0x756e5576
+ .long 0x72fe4293
+ .long 0x709e2f93
+ .long 0x6e4e1c7f
+ .long 0x6c0e095e
+ .long 0x69edf6c5
+ .long 0x67cde3a5
+ .long 0x65cdd125
+ .long 0x63cdbe25
+ .long 0x61ddab3f
+ .long 0x600d991f
+ .long 0x5e3d868c
+ .long 0x5c6d7384
+ .long 0x5abd615f
+ .long 0x590d4ecd
+ .long 0x576d3c83
+ .long 0x55dd2a89
+ .long 0x545d18e9
+ .long 0x52dd06e9
+ .long 0x516cf54e
+ .long 0x4ffce356
+ .long 0x4e9cd1ce
+ .long 0x4d3cbfec
+ .long 0x4becae86
+ .long 0x4aac9da4
+ .long 0x496c8c73
+ .long 0x483c7bd3
+ .long 0x470c6ae8
+ .long 0x45dc59af
+ .long 0x44bc4915
+ .long 0x43ac3924
+ .long 0x428c27fb
+ .long 0x418c187a
+ .long 0x407c07bd
+
+__divdf3_support: /* This label makes debugger output saner. */
+ .balign 4
+.Ldenorm_dbl1:
+ brge r6, \
+ 0x43500000,.Linf_NaN ; large number / denorm -> Inf
+ bmsk.f r12,DBL1H,19
+ mov.eq r12,DBL1L
+ mov.eq DBL1L,0
+ sub.eq r7,r7,32
+ norm.f r11,r12 ; flag for x/0 -> Inf check
+ beq_s .Linf_NaN
+ mov.mi r11,0
+ add.pl r11,r11,1
+ add_s r12,r12,r12
+ asl r8,r12,r11
+ rsub r12,r11,31
+ lsr r12,DBL1L,r12
+ tst_s DBL1H,DBL1H
+ or r8,r8,r12
+ lsr r4,r8,26
+ lsr DBL1H,r8,12
+ ld.as r4,[r10,r4]
+ bxor.mi DBL1H,DBL1H,31
+ sub r11,r11,11
+ asl DBL1L,DBL1L,r11
+ sub r11,r11,1
+ mulu64 r4,r8
+ sub r7,r7,r11
+ b.d .Lpast_denorm_dbl1
+ asl r7,r7,20
+
+ .balign 4
+.Ldenorm_dbl0:
+ bmsk.f r12,DBL0H,19
+ ; wb stall
+ mov.eq r12,DBL0L
+ sub.eq r6,r6,32
+ norm.f r11,r12 ; flag for 0/x -> 0 check
+ brge r7, \
+ 0x43500000, .Lret0_2 ; denorm/large number -> 0
+ beq_s .Lret0_2
+ mov.mi r11,0
+ add.pl r11,r11,1
+ asl r12,r12,r11
+ sub r6,r6,r11
+ add.f 0,r6,31
+ lsr r10,DBL0L,r6
+ mov.mi r10,0
+ add r6,r6,11+32
+ neg.f r11,r6
+ asl DBL0L,DBL0L,r11
+ mov.pl DBL0L,0
+ sub r6,r6,32-1
+ b.d .Lpast_denorm_dbl0
+ asl r6,r6,20
+
+.Linf_NaN:
+ tst_s DBL0L,DBL0L ; 0/0 -> NaN
+ xor_s DBL1H,DBL1H,DBL0H
+ bclr.eq.f DBL0H,DBL0H,31
+ bmsk DBL0H,DBL1H,30
+ xor_s DBL0H,DBL0H,DBL1H
+ sub.eq DBL0H,DBL0H,1
+ mov_s DBL0L,0
+ j_s.d [blink]
+ or DBL0H,DBL0H,r9
+ .balign 4
+.Lret0_2:
+ xor_s DBL1H,DBL1H,DBL0H
+ mov_s DBL0L,0
+ bmsk DBL0H,DBL1H,30
+ j_s.d [blink]
+ xor_s DBL0H,DBL0H,DBL1H
+ .balign 4
+ .global __divdf3
+/* N.B. the spacing between divtab and the sub3 to get its address must
+ be a multiple of 8. */
+__divdf3:
+ asl r8,DBL1H,12
+ lsr r4,r8,26
+ sub3 r10,pcl,61; (.-.Ldivtab) >> 3
+ ld.as r9,[pcl,-124]; [pcl,(-((.-.L7ff00000) >> 2))] ; 0x7ff00000
+ ld.as r4,[r10,r4]
+ lsr r12,DBL1L,20
+ and.f r7,DBL1H,r9
+ or r8,r8,r12
+ mulu64 r4,r8
+ beq.d .Ldenorm_dbl1
+.Lpast_denorm_dbl1:
+ and.f r6,DBL0H,r9
+ breq.d r7,r9,.Linf_nan_dbl1
+ asl r4,r4,12
+ sub r4,r4,mhi
+ mulu64 r4,r4
+ beq.d .Ldenorm_dbl0
+ lsr r8,r8,1
+ breq.d r6,r9,.Linf_nan_dbl0
+ asl r12,DBL0H,11
+ lsr r10,DBL0L,21
+.Lpast_denorm_dbl0:
+ bset r8,r8,31
+ mulu64 mhi,r8
+ add_s r12,r12,r10
+ bset r5,r12,31
+ cmp r5,r8
+ cmp.eq DBL0L,DBL1L
+ lsr.cc r5,r5,1
+ sub r4,r4,mhi ; u1.31 inverse, about 30 bit
+ mulu64 r5,r4 ; result fraction highpart
+ lsr r8,r8,2 ; u3.29
+ add r5,r6, /* wait for immediate */ \
+ 0x3fe00000
+ mov r11,mhi ; result fraction highpart
+ mulu64 r11,r8 ; u-28.31
+ asl_s DBL1L,DBL1L,9 ; u-29.23:9
+ sbc r6,r5,r7
+ mov r12,mlo ; u-28.31
+ mulu64 r11,DBL1L ; mhi: u-28.23:9
+ add.cs DBL0L,DBL0L,DBL0L
+ asl_s DBL0L,DBL0L,6 ; u-26.25:7
+ asl r10,r11,23
+ sub_l DBL0L,DBL0L,r12
+ lsr r7,r11,9
+ sub r5,DBL0L,mhi ; rest msw ; u-26.31:0
+ mul64 r5,r4 ; mhi: result fraction lowpart
+ xor.f 0,DBL0H,DBL1H
+ and DBL0H,r6,r9
+ add_s DBL0H,DBL0H,r7
+ bclr r12,r9,20 ; 0x7fe00000
+ brhs.d r6,r12,.Linf_denorm
+ bxor.mi DBL0H,DBL0H,31
+ add.f r12,mhi,0x11
+ asr r9,r12,5
+ sub.mi DBL0H,DBL0H,1
+ add.f DBL0L,r9,r10
+ tst r12,0x1c
+ jne.d [blink]
+ add.cs DBL0H,DBL0H,1
+ /* work out exact rounding if we fall through here. */
+ /* We know that the exact result cannot be represented in double
+ precision. Find the mid-point between the two nearest
+ representable values, multiply with the divisor, and check if
+ the result is larger than the dividend. Since we want to know
+ only the sign bit, it is sufficient to calculate only the
+ highpart of the lower 64 bits. */
+ mulu64 r11,DBL1L ; rest before considering r12 in r5 : -mlo
+ sub.f DBL0L,DBL0L,1
+ asl r12,r9,2 ; u-22.30:2
+ sub.cs DBL0H,DBL0H,1
+ sub.f r12,r12,2
+ mov r10,mlo ; rest before considering r12 in r5 : -r10
+ mulu64 r12,DBL1L ; mhi: u-51.32
+ asl r5,r5,25 ; s-51.7:25
+ lsr r10,r10,7 ; u-51.30:2
+ mov r7,mhi ; u-51.32
+ mulu64 r12,r8 ; mlo: u-51.31:1
+ sub r5,r5,r10
+ add.mi r5,r5,DBL1L ; signed multiply adjust for r12*DBL1L
+ bset r7,r7,0 ; make sure that the result is not zero, and that
+ sub r5,r5,r7 ; a highpart zero appears negative
+ sub.f r5,r5,mlo ; rest msw
+ add.pl.f DBL0L,DBL0L,1
+ j_s.d [blink]
+ add.eq DBL0H,DBL0H,1
+
+.Linf_nan_dbl1: ; 0/Inf -> NaN Inf/Inf -> NaN x/Inf-> 0 x/NaN -> NaN
+ or.f 0,r6,DBL0L
+ cmp.ne r6,r9
+ not_s DBL0L,DBL1H
+ sub_s.ne DBL0L,DBL0L,DBL0L
+ tst_s DBL0H,DBL0H
+ add_s DBL0H,DBL1H,DBL0L
+ j_s.d [blink]
+ bxor.mi DBL0H,DBL0H,31
+.Linf_nan_dbl0:
+ tst_s DBL1H,DBL1H
+ j_s.d [blink]
+ bxor.mi DBL0H,DBL0H,31
+ .balign 4
+.Linf_denorm:
+ lsr r12,r6,28
+ brlo.d r12,0xc,.Linf
+.Ldenorm:
+ asr r6,r6,20
+ neg r9,r6
+ mov_s DBL0H,0
+ brhs.d r9,54,.Lret0
+ bxor.mi DBL0H,DBL0H,31
+ add r12,mhi,1
+ and r12,r12,-4
+ rsub r7,r6,5
+ asr r10,r12,28
+ bmsk r4,r12,27
+ min r7,r7,31
+ asr DBL0L,r4,r7
+ add DBL1H,r11,r10
+ abs.f r10,r4
+ sub.mi r10,r10,1
+ add.f r7,r6,32-5
+ asl r4,r4,r7
+ mov.mi r4,r10
+ add.f r10,r6,23
+ rsub r7,r6,9
+ lsr r7,DBL1H,r7
+ asl r10,DBL1H,r10
+ or.pnz DBL0H,DBL0H,r7
+ or.mi r4,r4,r10
+ mov.mi r10,r7
+ add.f DBL0L,r10,DBL0L
+ add.cs.f DBL0H,DBL0H,1 ; carry clear after this point
+ bxor.f 0,r4,31
+ add.pnz.f DBL0L,DBL0L,1
+ add.cs.f DBL0H,DBL0H,1
+ jne_s [blink]
+ /* Calculation so far was not conclusive; calculate further rest. */
+ mulu64 r11,DBL1L ; rest before considering r12 in r5 : -mlo
+ asr.f r12,r12,3
+ asl r5,r5,25 ; s-51.7:25
+ mov r11,mlo ; rest before considering r12 in r5 : -r11
+ mulu64 r12,r8 ; u-51.31:1
+ and r9,DBL0L,1 ; tie-breaker: round to even
+ lsr r11,r11,7 ; u-51.30:2
+ mov DBL1H,mlo ; u-51.31:1
+ mulu64 r12,DBL1L ; u-51.62:2
+ sub.mi r11,r11,DBL1L ; signed multiply adjust for r12*DBL1L
+ add_s DBL1H,DBL1H,r11
+ sub DBL1H,DBL1H,r5 ; -rest msw
+ add_s DBL1H,DBL1H,mhi ; -rest msw
+ add.f 0,DBL1H,DBL1H ; can't ror.f by 32 :-(
+ tst_s DBL1H,DBL1H
+ cmp.eq mlo,r9
+ add.cs.f DBL0L,DBL0L,1
+ j_s.d [blink]
+ add.cs DBL0H,DBL0H,1
+
+.Lret0:
+ /* return +- 0 */
+ j_s.d [blink]
+ mov_s DBL0L,0
+.Linf:
+ mov_s DBL0H,r9
+ mov_s DBL0L,0
+ j_s.d [blink]
+ bxor.mi DBL0H,DBL0H,31
+ ENDFUNC(__divdf3)
diff --git a/libgcc/config/arc/ieee-754/arc600-mul64/divsf3.S b/libgcc/config/arc/ieee-754/arc600-mul64/divsf3.S
new file mode 100644
index 00000000000..a9934f0ad94
--- /dev/null
+++ b/libgcc/config/arc/ieee-754/arc600-mul64/divsf3.S
@@ -0,0 +1,274 @@
+/* Copyright (C) 2008-2013 Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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/>. */
+
+/*
+ - calculate 15..18 bit inverse using a table of approximating polynoms.
+ precision is higher for polynoms used to evaluate input with larger
+ value.
+ - do one newton-raphson iteration step to double the precision,
+ then multiply this with the divisor
+ -> more time to decide if dividend is subnormal
+ - the worst error propagation is on the side of the value range
+ with the least initial defect, thus giving us about 30 bits precision.
+ */
+#include "../arc-ieee-754.h"
+
+#if 0 /* DEBUG */
+ .global __divsf3
+ FUNC(__divsf3)
+ .balign 4
+__divsf3:
+ push_s blink
+ push_s r1
+ bl.d __divsf3_c
+ push_s r0
+ ld_s r1,[sp,4]
+ st_s r0,[sp,4]
+ bl.d __divsf3_asm
+ pop_s r0
+ pop_s r1
+ pop_s blink
+ cmp r0,r1
+#if 1
+ bne abort
+ jeq_s [blink]
+ b abort
+#else
+ bne abort
+ j_s [blink]
+#endif
+ ENDFUNC(__divsf3)
+#define __divsf3 __divsf3_asm
+#endif /* DEBUG */
+
+ FUNC(__divsf3)
+ .balign 4
+.Ldivtab:
+ .long 0xfc0ffff0
+ .long 0xf46ffefd
+ .long 0xed1ffd2a
+ .long 0xe627fa8e
+ .long 0xdf7ff73b
+ .long 0xd917f33b
+ .long 0xd2f7eea3
+ .long 0xcd1fe986
+ .long 0xc77fe3e7
+ .long 0xc21fdddb
+ .long 0xbcefd760
+ .long 0xb7f7d08c
+ .long 0xb32fc960
+ .long 0xae97c1ea
+ .long 0xaa27ba26
+ .long 0xa5e7b22e
+ .long 0xa1cfa9fe
+ .long 0x9ddfa1a0
+ .long 0x9a0f990c
+ .long 0x9667905d
+ .long 0x92df878a
+ .long 0x8f6f7e84
+ .long 0x8c27757e
+ .long 0x88f76c54
+ .long 0x85df630c
+ .long 0x82e759c5
+ .long 0x8007506d
+ .long 0x7d3f470a
+ .long 0x7a8f3da2
+ .long 0x77ef341e
+ .long 0x756f2abe
+ .long 0x72f7212d
+ .long 0x709717ad
+ .long 0x6e4f0e44
+ .long 0x6c1704d6
+ .long 0x69e6fb44
+ .long 0x67cef1d7
+ .long 0x65c6e872
+ .long 0x63cedf18
+ .long 0x61e6d5cd
+ .long 0x6006cc6d
+ .long 0x5e36c323
+ .long 0x5c76b9f3
+ .long 0x5abeb0b7
+ .long 0x5916a79b
+ .long 0x57769e77
+ .long 0x55de954d
+ .long 0x54568c4e
+ .long 0x52d6834d
+ .long 0x51667a7f
+ .long 0x4ffe71b5
+ .long 0x4e9e68f1
+ .long 0x4d466035
+ .long 0x4bf65784
+ .long 0x4aae4ede
+ .long 0x496e4646
+ .long 0x48363dbd
+ .long 0x47063547
+ .long 0x45de2ce5
+ .long 0x44be2498
+ .long 0x43a61c64
+ .long 0x4296144a
+ .long 0x41860c0e
+ .long 0x407e03ee
+.L7f800000:
+ .long 0x7f800000
+ .balign 4
+ .global __divsf3_support
+__divsf3_support:
+.Linf_NaN:
+ bclr.f 0,r0,31 ; 0/0 -> NaN
+ xor_s r0,r0,r1
+ bmsk r1,r0,30
+ bic_s r0,r0,r1
+ sub.eq r0,r0,1
+ j_s.d [blink]
+ or r0,r0,r9
+.Lret0:
+ xor_s r0,r0,r1
+ bmsk r1,r0,30
+ j_s.d [blink]
+ bic_s r0,r0,r1
+/* N.B. the spacing between divtab and the sub3 to get its address must
+ be a multiple of 8. */
+__divsf3:
+ lsr r2,r1,17
+ sub3 r3,pcl,37 ; (.-.Ldivtab) >> 3
+ bmsk_s r2,r2,5
+ ld.as r5,[r3,r2]
+ asl r4,r1,9
+ ld.as r9,[pcl,-13]; [pcl,(-((.-.L7f800000) >> 2))] ; 0x7f800000
+ mulu64 r5,r4
+ and.f r11,r1,r9
+ asl r6,r1,8
+ bset r6,r6,31
+ beq.d .Ldenorm_fp1
+ asl r5,r5,13
+ breq.d r11,r9,.Linf_nan_fp1
+ and.f r2,r0,r9
+ sub r7,r5,mhi
+ mulu64 r7,r6
+ beq.d .Ldenorm_fp0
+ asl r12,r0,8
+ breq.d r2,r9,.Linf_nan_fp0
+ mulu64 mhi,r7
+.Lpast_denorm_fp1:
+ bset r3,r12,31
+.Lpast_denorm_fp0:
+ cmp_s r3,r6
+ lsr.cc r3,r3,1
+ add_s r2,r2, /* wait for immediate */ \
+ 0x3f000000
+ sub r7,r7,mhi ; u1.31 inverse, about 30 bit
+ mulu64 r3,r7
+ sbc r2,r2,r11
+ xor.f 0,r0,r1
+ and r0,r2,r9
+ bclr r3,r9,23 ; 0x7f000000
+ brhs.d r2,r3,.Linf_denorm
+ bxor.mi r0,r0,31
+.Lpast_denorm:
+ add r3,mhi,0x22 ; round to nearest or higher
+ tst r3,0x3c ; check if rounding was unsafe
+ lsr r3,r3,6
+ jne.d [blink] ; return if rounding was safe.
+ add_s r0,r0,r3
+ /* work out exact rounding if we fall through here. */
+ /* We know that the exact result cannot be represented in single
+ precision. Find the mid-point between the two nearest
+ representable values, multiply with the divisor, and check if
+ the result is larger than the dividend. */
+ add_s r3,r3,r3
+ sub_s r3,r3,1
+ mulu64 r3,r6
+ asr.f 0,r0,1 ; for round-to-even in case this is a denorm
+ rsub r2,r9,25
+ asl_s r12,r12,r2
+ sub.f 0,r12,mlo
+ j_s.d [blink]
+ sub.mi r0,r0,1
+.Linf_nan_fp1:
+ lsr_s r0,r0,31
+ bmsk.f 0,r1,22
+ asl_s r0,r0,31
+ bne_s 0f ; inf/inf -> nan
+ brne r2,r9,.Lsigned0 ; x/inf -> 0, but x/nan -> nan
+0: j_s.d [blink]
+ mov r0,-1
+.Lsigned0:
+.Linf_nan_fp0:
+ tst_s r1,r1
+ j_s.d [blink]
+ bxor.mi r0,r0,31
+ .balign 4
+ .global __divsf3
+/* For denormal results, it is possible that an exact result needs
+ rounding, and thus the round-to-even rule has to come into play. */
+.Linf_denorm:
+ brlo r2,0xc0000000,.Linf
+.Ldenorm:
+ asr_s r2,r2,23
+ bic r0,r0,r9
+ neg r9,r2
+ brlo.d r9,25,.Lpast_denorm
+ lsr r3,mlo,r9
+ /* Fall through: return +- 0 */
+ j_s [blink]
+.Linf:
+ j_s.d [blink]
+ or r0,r0,r9
+ .balign 4
+.Ldenorm_fp1:
+ bclr r6,r6,31
+ norm.f r12,r6 ; flag for x/0 -> Inf check
+ add r6,r6,r6
+ rsub r5,r12,16
+ ror r5,r1,r5
+ asl r6,r6,r12
+ bmsk r5,r5,5
+ ld.as r5,[r3,r5]
+ add r4,r6,r6
+ ; load latency
+ mulu64 r5,r4
+ bic.ne.f 0, \
+ 0x60000000,r0 ; large number / denorm -> Inf
+ asl r5,r5,13
+ sub r7,r5,mhi
+ beq.d .Linf_NaN
+ mulu64 r7,r6
+ asl_s r12,r12,23
+ and.f r2,r0,r9
+ add_s r2,r2,r12
+ asl r12,r0,8
+ bne.d .Lpast_denorm_fp1
+.Ldenorm_fp0: mulu64 mhi,r7
+ bclr r12,r12,31
+ norm.f r3,r12 ; flag for 0/x -> 0 check
+ bic.ne.f 0,0x60000000,r1 ; denorm/large number -> 0
+ beq_s .Lret0
+ asl_s r12,r12,r3
+ asl_s r3,r3,23
+ add_s r12,r12,r12
+ add r11,r11,r3
+ b.d .Lpast_denorm_fp0
+ mov_s r3,r12
+ ENDFUNC(__divsf3)
diff --git a/libgcc/config/arc/ieee-754/arc600-mul64/muldf3.S b/libgcc/config/arc/ieee-754/arc600-mul64/muldf3.S
new file mode 100644
index 00000000000..1e18999e49a
--- /dev/null
+++ b/libgcc/config/arc/ieee-754/arc600-mul64/muldf3.S
@@ -0,0 +1,234 @@
+/* Copyright (C) 2008-2013 Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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/>. */
+
+#include "../arc-ieee-754.h"
+
+#if 0 /* DEBUG */
+ .global __muldf3
+ .balign 4
+__muldf3:
+ push_s blink
+ push_s r2
+ push_s r3
+ push_s r0
+ bl.d __muldf3_c
+ push_s r1
+ ld_s r2,[sp,12]
+ ld_s r3,[sp,8]
+ st_s r0,[sp,12]
+ st_s r1,[sp,8]
+ pop_s r1
+ bl.d __muldf3_asm
+ pop_s r0
+ pop_s r3
+ pop_s r2
+ pop_s blink
+ cmp r0,r2
+ cmp.eq r1,r3
+ jeq_s [blink]
+ and r12,DBL0H,DBL1H
+ bic.f 0,0x7ff80000,r12 ; both NaN -> OK
+ jeq_s [blink]
+ b abort
+#define __muldf3 __muldf3_asm
+#endif /* DEBUG */
+
+__muldf3_support: /* This label makes debugger output saner. */
+ .balign 4
+ FUNC(__muldf3)
+.Ldenorm_2:
+ breq.d DBL1L,0,.Lret0_2 ; 0 input -> 0 output
+ norm.f r12,DBL1L
+ mov.mi r12,21
+ add.pl r12,r12,22
+ neg r11,r12
+ asl_s r12,r12,20
+ lsr.f DBL1H,DBL1L,r11
+ ror DBL1L,DBL1L,r11
+ sub_s DBL0H,DBL0H,r12
+ mov.eq DBL1H,DBL1L
+ sub_l DBL1L,DBL1L,DBL1H
+ /* Fall through. */
+ .global __muldf3
+ .balign 4
+__muldf3:
+ mulu64 DBL0L,DBL1L
+ ld.as r9,[pcl,0x68] ; ((.L7ff00000-.+2)/4)]
+ bmsk r6,DBL0H,19
+ bset r6,r6,20
+ and r11,DBL0H,r9
+ breq.d r11,0,.Ldenorm_dbl0
+ and r12,DBL1H,r9
+ breq.d r12,0,.Ldenorm_dbl1
+ mov r8,mlo
+ mov r4,mhi
+ mulu64 r6,DBL1L
+ breq.d r11,r9,.Linf_nan
+ bmsk r10,DBL1H,19
+ breq.d r12,r9,.Linf_nan
+ bset r10,r10,20
+ add.f r4,r4,mlo
+ adc r5,mhi,0
+ mulu64 r10,DBL0L
+ add_s r12,r12,r11 ; add exponents
+ add.f r4,r4,mlo
+ adc r5,r5,mhi
+ mulu64 r6,r10
+ tst r8,r8
+ bclr r8,r9,30 ; 0x3ff00000
+ bset.ne r4,r4,0 ; put least significant word into sticky bit
+ bclr r6,r9,20 ; 0x7fe00000
+ add.f r5,r5,mlo
+ adc r7,mhi,0 ; fraction product in r7:r5:r4
+ lsr.f r10,r7,9
+ rsub.eq r8,r8,r9 ; 0x40000000
+ sub r12,r12,r8 ; subtract bias + implicit 1
+ brhs.d r12,r6,.Linf_denorm
+ rsub r10,r10,12
+.Lshift_frac:
+ neg r8,r10
+ asl r6,r4,r10
+ lsr DBL0L,r4,r8
+ add.f 0,r6,r6
+ btst.eq DBL0L,0
+ cmp.eq r4,r4 ; round to nearest / round to even
+ asl r4,r5,r10
+ lsr r5,r5,r8
+ adc.f DBL0L,DBL0L,r4
+ xor.f 0,DBL0H,DBL1H
+ asl r7,r7,r10
+ add_s r12,r12,r5
+ adc DBL0H,r12,r7
+ j_s.d [blink]
+ bset.mi DBL0H,DBL0H,31
+
+/* N.B. This is optimized for ARC700.
+ ARC600 has very different scheduling / instruction selection criteria. */
+
+/* If one number is denormal, subtract some from the exponent of the other
+ one (if the other exponent is too small, return 0), and normalize the
+ denormal. Then re-run the computation. */
+.Lret0_2:
+ lsr_s DBL0H,DBL0H,31
+ asl_s DBL0H,DBL0H,31
+ j_s.d [blink]
+ mov_s DBL0L,0
+ .balign 4
+.Ldenorm_dbl0:
+ mov_s r12,DBL0L
+ mov_s DBL0L,DBL1L
+ mov_s DBL1L,r12
+ mov_s r12,DBL0H
+ mov_s DBL0H,DBL1H
+ mov_s DBL1H,r12
+ and r11,DBL0H,r9
+.Ldenorm_dbl1:
+ brhs r11,r9,.Linf_nan
+ brhs 0x3ca00001,r11,.Lret0
+ sub_s DBL0H,DBL0H,DBL1H
+ bmsk.f DBL1H,DBL1H,30
+ add_s DBL0H,DBL0H,DBL1H
+ beq.d .Ldenorm_2
+ norm r12,DBL1H
+ sub_s r12,r12,10
+ asl r5,r12,20
+ asl_s DBL1H,DBL1H,r12
+ sub DBL0H,DBL0H,r5
+ neg r5,r12
+ lsr r6,DBL1L,r5
+ asl_s DBL1L,DBL1L,r12
+ b.d __muldf3
+ add_s DBL1H,DBL1H,r6
+
+.Lret0: xor_s DBL0H,DBL0H,DBL1H
+ bclr DBL1H,DBL0H,31
+ xor_s DBL0H,DBL0H,DBL1H
+ j_s.d [blink]
+ mov_s DBL0L,0
+
+ .balign 4
+.Linf_nan:
+ bclr r12,DBL1H,31
+ xor_s DBL1H,DBL1H,DBL0H
+ bclr_s DBL0H,DBL0H,31
+ max r8,DBL0H,r12 ; either NaN -> NaN ; otherwise inf
+ or.f 0,DBL0H,DBL0L
+ mov_s DBL0L,0
+ or.ne.f DBL1L,DBL1L,r12
+ not_s DBL0H,DBL0L ; inf * 0 -> NaN
+ mov.ne DBL0H,r8
+ tst_s DBL1H,DBL1H
+ j_s.d [blink]
+ bset.mi DBL0H,DBL0H,31
+
+/* We have checked for infinity / NaN input before, and transformed
+ denormalized inputs into normalized inputs. Thus, the worst case
+ exponent overflows are:
+ 1 + 1 - 0x400 == 0xc02 : maximum underflow
+ 0x7fe + 0x7fe - 0x3ff == 0xbfd ; maximum overflow
+ N.B. 0x7e and 0x7f are also values for overflow.
+
+ If (r12 <= -54), we have an underflow to zero. */
+ .balign 4
+.Linf_denorm:
+ lsr r6,r12,28
+ brlo.d r6,0xc,.Linf
+ asr r6,r12,20
+ add.f r10,r10,r6
+ brgt.d r10,0,.Lshift_frac
+ mov_s r12,0
+ beq.d .Lround_frac
+ add r10,r10,32
+.Lshift32_frac:
+ tst r4,r4
+ mov r4,r5
+ bset.ne r4,r4,1
+ mov r5,r7
+ brge.d r10,1,.Lshift_frac
+ mov r7,0
+ breq.d r10,0,.Lround_frac
+ add r10,r10,32
+ brgt r10,21,.Lshift32_frac
+ b_s .Lret0
+
+.Lround_frac:
+ add.f 0,r4,r4
+ btst.eq r5,0
+ mov_s DBL0L,r5
+ mov_s DBL0H,r7
+ adc.eq.f DBL0L,DBL0L,0
+ j_s.d [blink]
+ adc.eq DBL0H,DBL0H,0
+
+.Linf: mov_s DBL0L,0
+ xor.f DBL1H,DBL1H,DBL0H
+ mov_s DBL0H,r9
+ j_s.d [blink]
+ bset.mi DBL0H,DBL0H,31
+ ENDFUNC(__muldf3)
+
+ .balign 4
+.L7ff00000:
+ .long 0x7ff00000
diff --git a/libgcc/config/arc/ieee-754/arc600-mul64/mulsf3.S b/libgcc/config/arc/ieee-754/arc600-mul64/mulsf3.S
new file mode 100644
index 00000000000..619662491b2
--- /dev/null
+++ b/libgcc/config/arc/ieee-754/arc600-mul64/mulsf3.S
@@ -0,0 +1,180 @@
+/* Copyright (C) 2008-2013 Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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/>. */
+
+#include "../arc-ieee-754.h"
+
+#if 0 /* DEBUG */
+ .global __mulsf3
+ FUNC(__mulsf3)
+ .balign 4
+__mulsf3:
+ push_s blink
+ push_s r1
+ bl.d __mulsf3_c
+ push_s r0
+ ld_s r1,[sp,4]
+ st_s r0,[sp,4]
+ bl.d __mulsf3_asm
+ pop_s r0
+ pop_s r1
+ pop_s blink
+ cmp r0,r1
+ jeq_s [blink]
+ and r12,r0,r1
+ bic.f 0,0x7f800000,r12
+ bne 0f
+ bmsk.f 0,r0,22
+ bmsk.ne.f r1,r1,22
+ jne_s [blink] ; both NaN -> OK
+0: bl abort
+ ENDFUNC(__mulsf3)
+#define __mulsf3 __mulsf3_asm
+#endif /* DEBUG */
+
+ .balign 4
+ .global __mulsf3
+ FUNC(__mulsf3)
+__mulsf3:
+ ld.as r9,[pcl,80]; [pcl,((.L7f800000-.+2)/4)]
+ bmsk r4,r1,22
+ bset r2,r0,23
+ asl_s r2,r2,8
+ bset r3,r4,23
+ mulu64 r2,r3
+ and r11,r0,r9
+ breq.d r11,0,.Ldenorm_dbl0
+ and r12,r1,r9
+ breq.d r12,0,.Ldenorm_dbl1
+ xor_s r0,r0,r1
+ breq.d r11,r9,.Linf_nan_dbl0
+ ld.as r4,[pcl,70]; [pcl,((.L7fffffff-.+2)/4)]
+ breq.d r12,r9,.Linf_nan_dbl1
+.Lpast_denorm:
+ asl.f 0,mhi,8
+ mov r6,mhi
+ mov r7,mlo
+ add.pl r6,r6,r6
+ bclr.pl r6,r6,23
+ add.pl.f r7,r7,r7
+ add.cs r6,r6,1
+ lsr.f 0,r6,1
+ add_s r12,r12,r11
+ adc.f 0,r7,r4
+ add_s r12,r12, \
+ -0x3f800000
+ adc.f r8,r6,r12
+ tst.pl r8,r9
+ bic r0,r0,r4
+ min r3,r8,r9
+ jpnz.d [blink]
+ add.pnz r0,r0,r3
+; infinity or denormal number
+ add.ne.f r3,r3,r3
+ asr_s r3,r3,23+1
+ bset r6,r6,23
+ bpnz.d .Linfinity
+ sub_s r3,r3,1
+ neg_s r2,r3
+ brhi.d r2,24,.Lret_r0 ; right shift shift > 24 -> return +-0
+ lsr r2,r6,r2
+ asl r9,r6,r3
+ lsr.f 0,r2,1
+ tst r7,r7
+ add_s r0,r0,r2
+ bset.ne r9,r9,0
+ adc.f 0,r9,r4
+ j_s.d [blink]
+ add.cs r0,r0,1
+.Linfinity:
+ j_s.d [blink]
+ add_s r0,r0,r9
+
+.Lret_r0: j_s [blink]
+
+ .balign 4
+.Ldenorm_dbl0:
+ bclr_s r2,r2,31
+ norm.f r4,r2
+ add_s r2,r2,r2
+ asl r2,r2,r4
+ mulu64 r2,r3
+ breq.d r12,r9,.Ldenorm_dbl0_inf_nan_dbl1
+ asl r4,r4,23
+ sub.ne.f r12,r12,r4
+ ld.as r4,[pcl,29]; [pcl,((.L7fffffff-.+2)/4)]
+ bhi.d .Lpast_denorm
+ xor_s r0,r0,r1
+ bmsk r1,r0,30
+ j_s.d [blink]
+ bic_s r0,r0,r1
+
+ .balign 4
+.Ldenorm_dbl0_inf_nan_dbl1:
+ bmsk.f 0,r0,30
+ beq_s .Lretnan
+ xor_s r0,r0,r1
+.Linf_nan_dbl1:
+ xor_s r1,r1,r0
+.Linf_nan_dbl0:
+ bclr_s r1,r1,31
+ cmp_s r1,r9
+ jls.d [blink]
+ xor_s r0,r0,r1
+; r1 NaN -> result NaN
+.Lretnan:
+ j_s.d [blink]
+ mov r0,-1
+
+ .balign 4
+.Ldenorm_dbl1:
+ breq.d r11,r9,.Linf_nan_dbl0_2
+ norm.f r3,r4
+ sub_s r3,r3,7
+ asl r4,r4,r3
+ mulu64 r2,r4
+ sub_s r3,r3,1
+ asl_s r3,r3,23
+ sub.ne.f r11,r11,r3
+ ld.as r4,[pcl,11]; [pcl,((.L7fffffff-.+2)/4)]
+ bhi.d .Lpast_denorm
+ bmsk r8,r0,30
+ j_s.d [blink]
+ bic r0,r0,r8
+
+ .balign 4
+.Linf_nan_dbl0_2:
+ bclr_s r1,r1,31
+ xor_s r0,r0,r1
+ sub.eq r1,r1,1 ; inf/nan * 0 -> nan
+ bic.f 0,r9,r1
+ j_s.d [blink]
+ or.eq r0,r0,r1 ; r1 nan -> result nan
+
+ .balign 4
+.L7f800000:
+ .long 0x7f800000
+.L7fffffff:
+ .long 0x7fffffff
+ ENDFUNC(__mulsf3)
diff --git a/libgcc/config/arc/ieee-754/arc600/divsf3.S b/libgcc/config/arc/ieee-754/arc600/divsf3.S
new file mode 100644
index 00000000000..7fcbadbe086
--- /dev/null
+++ b/libgcc/config/arc/ieee-754/arc600/divsf3.S
@@ -0,0 +1,227 @@
+/* Copyright (C) 2008-2013 Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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/>. */
+
+#include "../arc-ieee-754.h"
+
+#if 0 /* DEBUG */
+ .global __divsf3
+ FUNC(__divsf3)
+ .balign 4
+__divsf3:
+ push_s blink
+ push_s r1
+ bl.d __divsf3_c
+ push_s r0
+ ld_s r1,[sp,4]
+ st_s r0,[sp,4]
+ bl.d __divsf3_asm
+ pop_s r0
+ pop_s r1
+ pop_s blink
+ cmp r0,r1
+ jeq_s [blink]
+ and r12,r0,r1
+ bic.f 0,0x7f800000,r12 ; both NaN -> OK
+ jeq_s [blink]
+ bl abort
+ ENDFUNC(__divsf3)
+#define __divsf3 __divsf3_asm
+#endif /* DEBUG */
+
+ .balign 4
+__divdf3_support: /* This label makes debugger output saner. */
+ FUNC(__divsf3)
+.Ldenorm_fp0:
+ norm.f r12,r2 ; flag for 0/x -> 0 check
+ bic.ne.f 0,0x60000000,r1 ; denorm/large number -> 0
+ beq_s .Lret0_NaN
+ tst r1,r9
+ add_s r2,r2,r2
+ sub_s r12,r12,8
+ asl_s r2,r2,r12
+ asl_l r12,r12,23
+ bne.d .Lpast_denorm_fp0
+ add r5,r5,r12
+/* r0 is subnormal, r1 is subnormal or 0. */
+
+ .balign 4
+.Ldenorm_fp1:
+ norm.f r12,r3 ; flag for x/0 -> Inf check
+ bic.ne.f 0,0x60000000,r0 ; large number/denorm -> Inf
+ beq_s .Linf
+ add_s r3,r3,r3
+ sub_s r12,r12,8
+ asl_s r3,r3,r12
+ asl_s r12,r12,23
+ b.d .Lpast_denorm_fp1
+ add r4,r4,r12
+
+.Lret0_NaN:
+ bclr.f 0,r1,31 ; 0/0 -> NaN
+ bic r0,r10,r9
+ j_s.d [blink]
+ sub.eq r0,r0,1
+
+ .balign 4
+.Linf_nan_fp0:
+ bic.f 0,r9,r1 ; fp1 Inf -> result NaN
+ bic r1,r5,r9 ; fp1 sign
+ sub.eq r1,r1,1
+ j_s.d [blink]
+ xor_s r0,r0,r1
+.Linf_nan_fp1:
+ bic r0,r4,r9 ; fp0 sign
+ bmsk.f 0,r1,22 ; x/inf -> 0, x/nan -> nan
+ xor.eq r1,r1,r9
+ j_s.d [blink]
+ xor_s r0,r0,r1
+
+ .global __divsf3
+ .balign 4
+ .long 0x7f800000 ; exponent mask
+__divsf3:
+ ld r9,[pcl,-4]
+ bmsk r2,r0,22
+ xor r4,r0,r2
+ bmsk r3,r1,22
+ xor r5,r1,r3
+ and r11,r0,r9
+ breq.d r11,0,.Ldenorm_fp0
+ xor r10,r4,r5
+ breq r11,r9,.Linf_nan_fp0
+ bset_s r2,r2,23
+ and r11,r1,r9
+ breq r11,0,.Ldenorm_fp1
+ breq r11,r9,.Linf_nan_fp1
+.Lpast_denorm_fp0:
+ bset_s r3,r3,23
+.Lpast_denorm_fp1:
+ cmp r2,r3
+ asl_s r2,r2,6+1
+ asl_s r3,r3,7
+ add.lo r2,r2,r2
+ bclr r8,r9,30 ; exponent bias
+ bclr.lo r8,r8,23 ; reduce exp by one if fraction is shifted
+ sub r4,r4,r5
+ add r4,r4,r8
+ xor.f 0,r10,r4
+ bmi .Linf_denorm
+ and.f r12,r4,r9
+ beq .Ldenorm
+ sub_s r2,r2,r3 ; discard implicit 1
+ rsub r3,r3,1 ; prime r3 for two-insn divide-step use
+.Ldiv_23bit:
+ .rep 6
+ add1.f r2,r3,r2
+ sub.cc r2,r2,r3
+ .endr
+ breq r12,r9,.Linf
+ bmsk r0,r2,6
+ xor_s r2,r2,r0
+.Ldiv_17bit:
+ .rep 7
+ add1.f r2,r3,r2
+ sub.cc r2,r2,r3
+ .endr
+ asl_s r0,r0,7
+ bmsk r1,r2,6
+ xor_s r2,r2,r1
+ or_s r0,r0,r1
+.Ldiv_10bit:
+ .rep 7
+ add1.f r2,r3,r2
+ sub.cc r2,r2,r3
+ .endr
+ asl_s r0,r0,7
+ bmsk r1,r2,6
+ xor_s r2,r2,r1
+ or_s r0,r0,r1
+.Ldiv_3bit:
+ .rep 3
+ add1.f r2,r3,r2
+ sub.cc r2,r2,r3
+ .endr
+ asl_s r0,r0,3
+.Ldiv_0bit:
+ add1.f r1,r3,r2
+ sub.cc r1,r1,r3
+ bmsk_s r2,r2,2
+ tst r1,-0x7e ; 0xffffff82, test for rest or odd
+ bmsk_s r1,r1,0
+ add_s r0,r0,r2 ; assemble fraction
+ add_s r0,r0,r4 ; add in sign & exponent
+ j_s.d [blink]
+ add.ne r0,r0,r1 ; round to nearest / even
+
+ .balign 4
+.Linf:
+ j_s.d [blink]
+ or r0,r10,r9
+
+.Lret_r4:
+ j_s.d [blink]
+ mov_s r0,r4
+ .balign 4
+.Linf_denorm:
+ add.f r12,r4,r4
+ asr_l r12,r12,24
+ bpl .Linf
+ max r12,r12,-24
+.Ldenorm:
+ rsub r3,r3,1
+ add r1,pcl,68; .Ldenorm_tab-.
+ ldw.as r12,[r1,r12]
+ mov_s r0,0
+ lsr_s r2,r2
+ sub_s r1,r1,r12
+ j_s.d [r1]
+ bic r4,r10,r9
+ .short .Ldenorm_tab-.Lret_r4
+ .short .Ldenorm_tab-.Ldiv_0bit
+ .short .Ldenorm_tab-.Ldiv_3bit-2*8
+ .short .Ldenorm_tab-.Ldiv_3bit-1*8
+ .short .Ldenorm_tab-.Ldiv_3bit
+ .short .Ldenorm_tab-.Ldiv_10bit-6*8
+ .short .Ldenorm_tab-.Ldiv_10bit-5*8
+ .short .Ldenorm_tab-.Ldiv_10bit-3*8
+ .short .Ldenorm_tab-.Ldiv_10bit-3*8
+ .short .Ldenorm_tab-.Ldiv_10bit-2*8
+ .short .Ldenorm_tab-.Ldiv_10bit-1*8
+ .short .Ldenorm_tab-.Ldiv_10bit
+ .short .Ldenorm_tab-.Ldiv_17bit-6*8
+ .short .Ldenorm_tab-.Ldiv_17bit-5*8
+ .short .Ldenorm_tab-.Ldiv_17bit-4*8
+ .short .Ldenorm_tab-.Ldiv_17bit-3*8
+ .short .Ldenorm_tab-.Ldiv_17bit-2*8
+ .short .Ldenorm_tab-.Ldiv_17bit-1*8
+ .short .Ldenorm_tab-.Ldiv_17bit
+ .short .Ldenorm_tab-.Ldiv_23bit-5*8
+ .short .Ldenorm_tab-.Ldiv_23bit-4*8
+ .short .Ldenorm_tab-.Ldiv_23bit-3*8
+ .short .Ldenorm_tab-.Ldiv_23bit-2*8
+ .short .Ldenorm_tab-.Ldiv_23bit-1*8
+.Ldenorm_tab:
+ .short .Ldenorm_tab-.Ldiv_23bit
+ ENDFUNC(__divsf3)
diff --git a/libgcc/config/arc/ieee-754/arc600/mulsf3.S b/libgcc/config/arc/ieee-754/arc600/mulsf3.S
new file mode 100644
index 00000000000..e3f0a3c12b6
--- /dev/null
+++ b/libgcc/config/arc/ieee-754/arc600/mulsf3.S
@@ -0,0 +1,179 @@
+/* Copyright (C) 2008-2013 Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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/>. */
+
+#include "../arc-ieee-754.h"
+
+#if 0 /* DEBUG */
+ .global __mulsf3
+ FUNC(__mulsf3)
+ .balign 4
+__mulsf3:
+ push_s blink
+ push_s r1
+ bl.d __mulsf3_c
+ push_s r0
+ ld_s r1,[sp,4]
+ st_s r0,[sp,4]
+ bl.d __mulsf3_asm
+ pop_s r0
+ pop_s r1
+ pop_s blink
+ cmp r0,r1
+ jeq_s [blink]
+ and r12,r0,r1
+ bic.f 0,0x7f800000,r12
+ bne 0f
+ bmsk.f 0,r0,22
+ bmsk.ne.f r1,r1,22
+ jne_s [blink] ; both NaN -> OK
+0: bl abort
+ ENDFUNC(__mulsf3)
+#define __mulsf3 __mulsf3_asm
+#endif /* DEBUG */
+
+ .balign 4
+ .global __mulsf3
+ FUNC(__mulsf3)
+__mulsf3:
+ ld.as r9,[pcl,76]; [pcl,((.L7f800000-.+2)/4)]
+ bmsk r4,r1,22
+ bset r3,r4,23
+ bmsk r2,r0,22
+ and r11,r0,r9
+ breq.d r11,0,.Ldenorm_dbl0
+ and r12,r1,r9
+ xor_s r0,r0,r1
+ breq.d r11,r9,.Linf_nan_dbl0
+ bset_s r2,r2,23
+ breq r12,0,.Ldenorm_dbl1
+ breq r12,r9,.Linf_nan_dbl1
+.Lpast_denorm:
+ mov r6,0
+ lsr.f r7,r2
+; We could so this a bit faster here with a 32 bit shift register and
+; inserting the r2 factor / retrieving the low result a byte at a time,
+; but that'd increase code size.
+ mov lp_count,24
+ .balign 4
+ lp 0f
+ add.cs r6,r6,r3
+ lsr.f r6,r6
+ rrc.f r7,r7
+0:
+ ld.as r4,[pcl,59]; [pcl,((.L7fffffff-.+2)/4)]
+ asl.f 0,r6,8
+ add.pl r6,r6,r6
+ bclr.pl r6,r6,23
+ add.pl.f r7,r7,r7
+ add.cs r6,r6,1
+ lsr.f 0,r6,1
+ add_s r12,r12,r11
+ adc.f 0,r7,r4
+ add_s r12,r12, \
+ -0x3f800000
+ adc.f r8,r6,r12
+ tst.pl r8,r9
+ bic r0,r0,r4
+ min r3,r8,r9
+ jpnz.d [blink]
+ add.pnz r0,r0,r3
+; infinity or denormal number
+ add.ne.f r3,r3,r3
+ asr_s r3,r3,23+1
+ bset r6,r6,23
+ bpnz.d .Linfinity
+ sub_s r3,r3,1
+ neg_s r2,r3
+ brhi.d r2,24,.Lret_r0 ; right shift shift > 24 -> return +-0
+ lsr r2,r6,r2
+ asl r9,r6,r3
+ lsr.f 0,r2,1
+ tst r7,r7
+ add_s r0,r0,r2
+ bset.ne r9,r9,0
+ adc.f 0,r9,r4
+ j_s.d [blink]
+ add.cs r0,r0,1
+.Linfinity:
+ j_s.d [blink]
+ add_s r0,r0,r9
+
+.Lret_r0: j_s [blink]
+
+ .balign 4
+.Ldenorm_dbl0:
+ asl_s r2,r2,8
+ norm.f r4,r2
+ lsr_s r2,r2,7
+ asl r2,r2,r4
+ breq.d r12,r9,.Ldenorm_dbl0_inf_nan_dbl1
+ asl r4,r4,23
+ sub.ne.f r12,r12,r4
+ bhi.d .Lpast_denorm
+ xor_s r0,r0,r1
+ bmsk r1,r0,30
+ j_s.d [blink]
+ bic_s r0,r0,r1
+
+ .balign 4
+.Ldenorm_dbl0_inf_nan_dbl1:
+ bmsk.f 0,r0,30
+ beq_s .Lretnan
+ xor_s r0,r0,r1
+.Linf_nan_dbl1:
+ xor_s r1,r1,r0
+ bclr_s r1,r1,31
+ j_s.d [blink]
+ xor_s r0,r0,r1
+.Linf_nan_dbl0:
+ sub_s r2,r1,1 ; inf/nan * 0 -> nan; inf * nan -> nan (use |r2| >= inf)
+ bic.f 0,r9,r2
+ xor_s r0,r0,r1
+ bclr_s r1,r1,31
+ xor_s r0,r0,r1
+ jne_s [blink]
+.Lretnan:
+ j_s.d [blink]
+ mov r0,-1
+ .balign 4
+.Ldenorm_dbl1:
+ norm.f r3,r4
+ sub_s r3,r3,7
+ asl r4,r4,r3
+ sub_s r3,r3,1
+ asl_s r3,r3,23
+ sub.ne.f r11,r11,r3
+ bhi.d .Lpast_denorm
+ mov_s r3,r4
+ bmsk r3,r0,30
+ j_s.d [blink]
+ bic_s r0,r0,r3
+
+ .balign 4
+.L7f800000:
+ .long 0x7f800000
+.L7fffffff:
+ .long 0x7fffffff
+ ENDFUNC(__mulsf3)
diff --git a/libgcc/config/arc/ieee-754/divdf3.S b/libgcc/config/arc/ieee-754/divdf3.S
new file mode 100644
index 00000000000..783cee352b3
--- /dev/null
+++ b/libgcc/config/arc/ieee-754/divdf3.S
@@ -0,0 +1,416 @@
+/* Copyright (C) 2008-2013 Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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/>. */
+
+/*
+ to calculate a := b/x as b*y, with y := 1/x:
+ - x is in the range [1..2)
+ - calculate 15..18 bit inverse y0 using a table of approximating polynoms.
+ Precision is higher for polynoms used to evaluate input with larger
+ value.
+ - Do one newton-raphson iteration step to double the precision,
+ then multiply this with the divisor
+ -> more time to decide if dividend is subnormal
+ - the worst error propagation is on the side of the value range
+ with the least initial defect, thus giving us about 30 bits precision.
+ The truncation error for the either is less than 1 + x/2 ulp.
+ A 31 bit inverse can be simply calculated by using x with implicit 1
+ and chaining the multiplies. For a 32 bit inverse, we multiply y0^2
+ with the bare fraction part of x, then add in y0^2 for the implicit
+ 1 of x.
+ - If calculating a 31 bit inverse, the systematic error is less than
+ -1 ulp; likewise, for 32 bit, it is less than -2 ulp.
+ - If we calculate our seed with a 32 bit fraction, we can archive a
+ tentative result strictly better than -2 / +2.5 (1) ulp/128, i.e. we
+ only need to take the step to calculate the 2nd stage rest and
+ rounding adjust 1/32th of the time. However, if we use a 20 bit
+ fraction for the seed, the negative error can exceed -2 ulp/128, (2)
+ thus for a simple add / tst check, we need to do the 2nd stage
+ rest calculation/ rounding adjust 1/16th of the time.
+ (1): The inexactness of the 32 bit inverse contributes an error in the
+ range of (-1 .. +(1+x/2) ) ulp/128. Leaving out the low word of the
+ rest contributes an error < +1/x ulp/128 . In the interval [1,2),
+ x/2 + 1/x <= 1.5 .
+ (2): Unless proven otherwise. I have not actually looked for an
+ example where -2 ulp/128 is exceeded, and my calculations indicate
+ that the excess, if existent, is less than -1/512 ulp.
+ */
+#include "arc-ieee-754.h"
+
+/* N.B. fp-bit.c does double rounding on denormal numbers. */
+#if 0 /* DEBUG */
+ .global __divdf3
+ FUNC(__divdf3)
+ .balign 4
+__divdf3:
+ push_s blink
+ push_s r2
+ push_s r3
+ push_s r0
+ bl.d __divdf3_c
+ push_s r1
+ ld_s r2,[sp,12]
+ ld_s r3,[sp,8]
+ st_s r0,[sp,12]
+ st_s r1,[sp,8]
+ pop_s r1
+ bl.d __divdf3_asm
+ pop_s r0
+ pop_s r3
+ pop_s r2
+ pop_s blink
+ cmp r0,r2
+ cmp.eq r1,r3
+ jeq_s [blink]
+ and r12,DBL0H,DBL1H
+ bic.f 0,0x7ff80000,r12 ; both NaN -> OK
+ jeq_s [blink]
+ bl abort
+ ENDFUNC(__divdf3)
+#define __divdf3 __divdf3_asm
+#endif /* DEBUG */
+
+ FUNC(__divdf3)
+__divdf3_support: /* This label makes debugger output saner. */
+ .balign 4
+.Ldenorm_dbl1:
+ brge r6, \
+ 0x43500000,.Linf_NaN ; large number / denorm -> Inf
+ bmsk.f r12,DBL1H,19
+ mov.eq r12,DBL1L
+ mov.eq DBL1L,0
+ sub.eq r7,r7,32
+ norm.f r11,r12 ; flag for x/0 -> Inf check
+ beq_s .Linf_NaN
+ mov.mi r11,0
+ add.pl r11,r11,1
+ add_s r12,r12,r12
+ asl r8,r12,r11
+ rsub r12,r11,31
+ lsr r12,DBL1L,r12
+ tst_s DBL1H,DBL1H
+ or r8,r8,r12
+ lsr r4,r8,26
+ lsr DBL1H,r8,12
+ ld.as r4,[r10,r4]
+ bxor.mi DBL1H,DBL1H,31
+ sub r11,r11,11
+ asl DBL1L,DBL1L,r11
+ sub r11,r11,1
+ mpyhu r5,r4,r8
+ sub r7,r7,r11
+ asl r4,r4,12
+ b.d .Lpast_denorm_dbl1
+ asl r7,r7,20
+ ; wb stall
+
+ .balign 4
+.Ldenorm_dbl0:
+ bmsk.f r12,DBL0H,19
+ ; wb stall
+ mov.eq r12,DBL0L
+ sub.eq r6,r6,32
+ norm.f r11,r12 ; flag for 0/x -> 0 check
+ brge r7, \
+ 0x43500000, .Lret0_NaN ; denorm/large number -> 0
+ beq_s .Lret0_NaN
+ mov.mi r11,0
+ add.pl r11,r11,1
+ asl r12,r12,r11
+ sub r6,r6,r11
+ add.f 0,r6,31
+ lsr r10,DBL0L,r6
+ mov.mi r10,0
+ add r6,r6,11+32
+ neg.f r11,r6
+ asl DBL0L,DBL0L,r11
+ mov.pl DBL0L,0
+ sub r6,r6,32-1
+ b.d .Lpast_denorm_dbl0
+ asl r6,r6,20
+
+.Linf_NaN:
+ tst_s DBL0L,DBL0L ; 0/0 -> NaN
+ xor_s DBL1H,DBL1H,DBL0H
+ bclr.eq.f DBL0H,DBL0H,31
+ bmsk DBL0H,DBL1H,30
+ xor_s DBL0H,DBL0H,DBL1H
+ sub.eq DBL0H,DBL0H,1
+ mov_s DBL0L,0
+ j_s.d [blink]
+ or DBL0H,DBL0H,r9
+ .balign 4
+.Lret0_NaN:
+ xor_s DBL1H,DBL1H,DBL0H
+ cmp_s r12,r9
+ mov_s DBL0L,0
+ bmsk DBL0H,DBL1H,30
+ xor_s DBL0H,DBL0H,DBL1H
+ j_s.d [blink]
+ sub.hi DBL0H,DBL0H,1
+.Linf_nan_dbl1: ; Inf/Inf -> NaN x/Inf-> 0 x/NaN -> NaN
+ not_s DBL0L,DBL1H
+ cmp r6,r9
+ sub_s.ne DBL0L,DBL0L,DBL0L
+ tst_s DBL0H,DBL0H
+ add_s DBL0H,DBL1H,DBL0L
+ j_s.d [blink]
+ bxor.mi DBL0H,DBL0H,31
+.Linf_nan_dbl0:
+ tst_s DBL1H,DBL1H
+ j_s.d [blink]
+ bxor.mi DBL0H,DBL0H,31
+ .balign 4
+ .global __divdf3
+/* N.B. the spacing between divtab and the add3 to get its address must
+ be a multiple of 8. */
+__divdf3:
+ asl r8,DBL1H,12
+ lsr r12,DBL1L,20
+ lsr r4,r8,26
+ add3 r10,pcl,59 ; (.Ldivtab-.) >> 3
+ ld.as r4,[r10,r4]
+ ld.as r9,[pcl,180]; [pcl,(-((.-.L7ff00000) >> 2))] ; 0x7ff00000
+ or r8,r8,r12
+ mpyhu r5,r4,r8
+ and.f r7,DBL1H,r9
+ asl r4,r4,12 ; having the asl here is a concession to the XMAC pipeline.
+ beq.d .Ldenorm_dbl1
+ and r6,DBL0H,r9
+.Lpast_denorm_dbl1: ; wb stall
+ sub r4,r4,r5
+ mpyhu r5,r4,r4
+ breq.d r6,0,.Ldenorm_dbl0
+ lsr r8,r8,1
+ asl r12,DBL0H,11
+ lsr r10,DBL0L,21
+.Lpast_denorm_dbl0: ; wb stall
+ bset r8,r8,31
+ mpyhu r11,r5,r8
+ add_s r12,r12,r10
+ bset r5,r12,31
+ cmp r5,r8
+ cmp.eq DBL0L,DBL1L
+ ; wb stall
+ lsr.cc r5,r5,1
+ sub r4,r4,r11 ; u1.31 inverse, about 30 bit
+ mpyhu r11,r5,r4 ; result fraction highpart
+ breq r7,r9,.Linf_nan_dbl1
+ lsr r8,r8,2 ; u3.29
+ add r5,r6, /* wait for immediate / XMAC wb stall */ \
+ 0x3fe00000
+ ; wb stall (not for XMAC)
+ breq r6,r9,.Linf_nan_dbl0
+ mpyu r12,r11,r8 ; u-28.31
+ asl_s DBL1L,DBL1L,9 ; u-29.23:9
+ sbc r6,r5,r7
+ ; resource conflict (not for XMAC)
+ mpyhu r5,r11,DBL1L ; u-28.23:9
+ add.cs DBL0L,DBL0L,DBL0L
+ asl_s DBL0L,DBL0L,6 ; u-26.25:7
+ asl r10,r11,23
+ sub_l DBL0L,DBL0L,r12
+ ; wb stall (before 'and' for XMAC)
+ lsr r7,r11,9
+ sub r5,DBL0L,r5 ; rest msw ; u-26.31:0
+ mpyh r12,r5,r4 ; result fraction lowpart
+ xor.f 0,DBL0H,DBL1H
+ and DBL0H,r6,r9
+ add_s DBL0H,DBL0H,r7 ; (XMAC wb stall)
+ bxor.mi DBL0H,DBL0H,31
+ brhs r6, /* wb stall / wait for immediate */ \
+ 0x7fe00000,.Linf_denorm
+ add.f r12,r12,0x11
+ asr r9,r12,5
+ sub.mi DBL0H,DBL0H,1
+ add.f DBL0L,r9,r10
+ tst r12,0x1c
+ jne.d [blink]
+ add.cs DBL0H,DBL0H,1
+ /* work out exact rounding if we fall through here. */
+ /* We know that the exact result cannot be represented in double
+ precision. Find the mid-point between the two nearest
+ representable values, multiply with the divisor, and check if
+ the result is larger than the dividend. Since we want to know
+ only the sign bit, it is sufficient to calculate only the
+ highpart of the lower 64 bits. */
+ sub.f DBL0L,DBL0L,1
+ asl r12,r9,2 ; u-22.30:2
+ mpyu r10,r11,DBL1L ; rest before considering r12 in r5 : -r10
+ sub.cs DBL0H,DBL0H,1
+ sub.f r12,r12,2
+ ; resource conflict (not for XMAC)
+ mpyhu r7,r12,DBL1L ; u-51.32
+ asl r5,r5,25 ; s-51.7:25
+ lsr r10,r10,7 ; u-51.30:2
+ ; resource conflict (not for XMAC)
+ ; resource conflict (not for XMAC)
+ mpyu r9,r12,r8 ; u-51.31:1
+ sub r5,r5,r10
+ add.mi r5,r5,DBL1L ; signed multiply adjust for r12*DBL1L
+ bset r7,r7,0 ; make sure that the result is not zero, and that
+ ; wb stall (one earlier for XMAC)
+ sub r5,r5,r7 ; a highpart zero appears negative
+ sub.f r5,r5,r9 ; rest msw
+ add.pl.f DBL0L,DBL0L,1
+ j_s.d [blink]
+ add.eq DBL0H,DBL0H,1
+
+ .balign 4
+.Linf_denorm:
+ brlo r6,0xc0000000,.Linf
+.Ldenorm:
+ asr r6,r6,20
+ neg r9,r6
+ mov_s DBL0H,0
+ brhs.d r9,54,.Lret0
+ bxor.mi DBL0H,DBL0H,31
+ add_l r12,r12,1
+ and r12,r12,-4
+ rsub r7,r6,5
+ asr r10,r12,28
+ bmsk r4,r12,27
+ asrs DBL0L,r4,r7
+ add DBL1H,r11,r10
+ add.f r7,r6,32-5
+ abss r10,r4
+ asl r4,r4,r7
+ mov.mi r4,r10
+ add.f r10,r6,23
+ rsub r7,r6,9
+ lsr r7,DBL1H,r7
+ asl r10,DBL1H,r10
+ or.pnz DBL0H,DBL0H,r7
+ or.mi r4,r4,r10
+ mov.mi r10,r7
+ add.f DBL0L,r10,DBL0L
+ add.cs.f DBL0H,DBL0H,1 ; carry clear after this point
+ bxor.f 0,r4,31
+ add.pnz.f DBL0L,DBL0L,1
+ add.cs.f DBL0H,DBL0H,1
+ jne_l [blink]
+ /* Calculation so far was not conclusive; calculate further rest. */
+ mpyu r11,r11,DBL1L ; rest before considering r12 in r5 : -r11
+ asr.f r12,r12,3
+ asl r5,r5,25 ; s-51.7:25
+ ; resource conflict (not for XMAC)
+ mpyu DBL1H,r12,r8 ; u-51.31:1
+ and r9,DBL0L,1 ; tie-breaker: round to even
+ lsr r11,r11,7 ; u-51.30:2
+ ; resource conflict (not for XMAC)
+ mpyhu r8,r12,DBL1L ; u-51.32
+ sub.mi r11,r11,DBL1L ; signed multiply adjust for r12*DBL1L
+ add_s DBL1H,DBL1H,r11
+ ; resource conflict (not for XMAC)
+ ; resource conflict (not for XMAC)
+ mpyu r12,r12,DBL1L ; u-83.30:2
+ sub DBL1H,DBL1H,r5 ; -rest msw
+ add_s DBL1H,DBL1H,r8 ; -rest msw
+ add.f 0,DBL1H,DBL1H ; can't ror.f by 32 :-(
+ ; wb stall (XMAC: Before add.f)
+ tst_s DBL1H,DBL1H
+ cmp.eq r12,r9
+ add.cs.f DBL0L,DBL0L,1
+ j_s.d [blink]
+ add.cs DBL0H,DBL0H,1
+
+.Lret0:
+ /* return +- 0 */
+ j_s.d [blink]
+ mov_s DBL0L,0
+.Linf:
+ mov_s DBL0H,r9
+ mov_s DBL0L,0
+ j_s.d [blink]
+ bxor.mi DBL0H,DBL0H,31
+
+ .balign 4
+.Ldivtab:
+ .long 0xfc0fffe1
+ .long 0xf46ffdfb
+ .long 0xed1ffa54
+ .long 0xe61ff515
+ .long 0xdf7fee75
+ .long 0xd91fe680
+ .long 0xd2ffdd52
+ .long 0xcd1fd30c
+ .long 0xc77fc7cd
+ .long 0xc21fbbb6
+ .long 0xbcefaec0
+ .long 0xb7efa100
+ .long 0xb32f92bf
+ .long 0xae8f83b7
+ .long 0xaa2f7467
+ .long 0xa5ef6479
+ .long 0xa1cf53fa
+ .long 0x9ddf433e
+ .long 0x9a0f3216
+ .long 0x965f2091
+ .long 0x92df0f11
+ .long 0x8f6efd05
+ .long 0x8c1eeacc
+ .long 0x88eed876
+ .long 0x85dec615
+ .long 0x82eeb3b9
+ .long 0x800ea10b
+ .long 0x7d3e8e0f
+ .long 0x7a8e7b3f
+ .long 0x77ee6836
+ .long 0x756e5576
+ .long 0x72fe4293
+ .long 0x709e2f93
+ .long 0x6e4e1c7f
+ .long 0x6c0e095e
+ .long 0x69edf6c5
+ .long 0x67cde3a5
+ .long 0x65cdd125
+ .long 0x63cdbe25
+ .long 0x61ddab3f
+ .long 0x600d991f
+ .long 0x5e3d868c
+ .long 0x5c6d7384
+ .long 0x5abd615f
+ .long 0x590d4ecd
+ .long 0x576d3c83
+ .long 0x55dd2a89
+ .long 0x545d18e9
+ .long 0x52dd06e9
+ .long 0x516cf54e
+ .long 0x4ffce356
+ .long 0x4e9cd1ce
+ .long 0x4d3cbfec
+ .long 0x4becae86
+ .long 0x4aac9da4
+ .long 0x496c8c73
+ .long 0x483c7bd3
+ .long 0x470c6ae8
+ .long 0x45dc59af
+ .long 0x44bc4915
+ .long 0x43ac3924
+ .long 0x428c27fb
+ .long 0x418c187a
+ .long 0x407c07bd
+.L7ff00000:
+ .long 0x7ff00000
+ ENDFUNC(__divdf3)
diff --git a/libgcc/config/arc/ieee-754/divsf3-stdmul.S b/libgcc/config/arc/ieee-754/divsf3-stdmul.S
new file mode 100644
index 00000000000..b20f6c3889d
--- /dev/null
+++ b/libgcc/config/arc/ieee-754/divsf3-stdmul.S
@@ -0,0 +1,281 @@
+/* Copyright (C) 2008-2013 Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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/>. */
+
+/*
+ - calculate 15..18 bit inverse using a table of approximating polynoms.
+ precision is higher for polynoms used to evaluate input with larger
+ value.
+ - do one newton-raphson iteration step to double the precision,
+ then multiply this with the divisor
+ -> more time to decide if dividend is subnormal
+ - the worst error propagation is on the side of the value range
+ with the least initial defect, thus giving us about 30 bits precision.
+ */
+#include "arc-ieee-754.h"
+
+#if 0 /* DEBUG */
+ .global __divsf3
+ FUNC(__divsf3)
+ .balign 4
+__divsf3:
+ push_s blink
+ push_s r1
+ bl.d __divsf3_c
+ push_s r0
+ ld_s r1,[sp,4]
+ st_s r0,[sp,4]
+ bl.d __divsf3_asm
+ pop_s r0
+ pop_s r1
+ pop_s blink
+ cmp r0,r1
+#if 1
+ bne abort
+ jeq_s [blink]
+ b abort
+#else
+ bne abort
+ j_s [blink]
+#endif
+ ENDFUNC(__divsf3)
+#define __divsf3 __divsf3_asm
+#endif /* DEBUG */
+
+ FUNC(__divsf3)
+ .balign 4
+.L7f800000:
+ .long 0x7f800000
+.Ldivtab:
+ .long 0xfc0ffff0
+ .long 0xf46ffefd
+ .long 0xed1ffd2a
+ .long 0xe627fa8e
+ .long 0xdf7ff73b
+ .long 0xd917f33b
+ .long 0xd2f7eea3
+ .long 0xcd1fe986
+ .long 0xc77fe3e7
+ .long 0xc21fdddb
+ .long 0xbcefd760
+ .long 0xb7f7d08c
+ .long 0xb32fc960
+ .long 0xae97c1ea
+ .long 0xaa27ba26
+ .long 0xa5e7b22e
+ .long 0xa1cfa9fe
+ .long 0x9ddfa1a0
+ .long 0x9a0f990c
+ .long 0x9667905d
+ .long 0x92df878a
+ .long 0x8f6f7e84
+ .long 0x8c27757e
+ .long 0x88f76c54
+ .long 0x85df630c
+ .long 0x82e759c5
+ .long 0x8007506d
+ .long 0x7d3f470a
+ .long 0x7a8f3da2
+ .long 0x77ef341e
+ .long 0x756f2abe
+ .long 0x72f7212d
+ .long 0x709717ad
+ .long 0x6e4f0e44
+ .long 0x6c1704d6
+ .long 0x69e6fb44
+ .long 0x67cef1d7
+ .long 0x65c6e872
+ .long 0x63cedf18
+ .long 0x61e6d5cd
+ .long 0x6006cc6d
+ .long 0x5e36c323
+ .long 0x5c76b9f3
+ .long 0x5abeb0b7
+ .long 0x5916a79b
+ .long 0x57769e77
+ .long 0x55de954d
+ .long 0x54568c4e
+ .long 0x52d6834d
+ .long 0x51667a7f
+ .long 0x4ffe71b5
+ .long 0x4e9e68f1
+ .long 0x4d466035
+ .long 0x4bf65784
+ .long 0x4aae4ede
+ .long 0x496e4646
+ .long 0x48363dbd
+ .long 0x47063547
+ .long 0x45de2ce5
+ .long 0x44be2498
+ .long 0x43a61c64
+ .long 0x4296144a
+ .long 0x41860c0e
+ .long 0x407e03ee
+__divsf3_support: /* This label makes debugger output saner. */
+.Ldenorm_fp1:
+ bclr r6,r6,31
+ norm.f r12,r6 ; flag for x/0 -> Inf check
+ add r6,r6,r6
+ rsub r5,r12,16
+ ror r5,r1,r5
+ asl r6,r6,r12
+ bmsk r5,r5,5
+ ld.as r5,[r3,r5]
+ add r4,r6,r6
+ ; load latency
+ mpyhu r7,r5,r4
+ bic.ne.f 0, \
+ 0x60000000,r0 ; large number / denorm -> Inf
+ beq_s .Linf_NaN
+ asl r5,r5,13
+ ; wb stall
+ ; slow track
+ sub r7,r5,r7
+ mpyhu r8,r7,r6
+ asl_s r12,r12,23
+ and.f r2,r0,r9
+ add r2,r2,r12
+ asl r12,r0,8
+ ; wb stall
+ bne.d .Lpast_denorm_fp1
+.Ldenorm_fp0:
+ mpyhu r8,r8,r7
+ bclr r12,r12,31
+ norm.f r3,r12 ; flag for 0/x -> 0 check
+ bic.ne.f 0,0x60000000,r1 ; denorm/large number -> 0
+ beq_s .Lret0
+ asl_s r12,r12,r3
+ asl_s r3,r3,23
+ add_s r12,r12,r12
+ add r11,r11,r3
+ b.d .Lpast_denorm_fp0
+ mov_s r3,r12
+ .balign 4
+.Linf_NaN:
+ bclr.f 0,r0,31 ; 0/0 -> NaN
+ xor_s r0,r0,r1
+ bmsk r1,r0,30
+ bic_s r0,r0,r1
+ sub.eq r0,r0,1
+ j_s.d [blink]
+ or r0,r0,r9
+.Lret0:
+ xor_s r0,r0,r1
+ bmsk r1,r0,30
+ j_s.d [blink]
+ bic_s r0,r0,r1
+.Linf_nan_fp1:
+ lsr_s r0,r0,31
+ bmsk.f 0,r1,22
+ asl_s r0,r0,31
+ bne_s 0f ; inf/inf -> nan
+ brne r2,r9,.Lsigned0 ; x/inf -> 0, but x/nan -> nan
+0: j_s.d [blink]
+ mov r0,-1
+.Lsigned0:
+.Linf_nan_fp0:
+ tst_s r1,r1
+ j_s.d [blink]
+ bxor.mi r0,r0,31
+ .balign 4
+ .global __divsf3
+/* N.B. the spacing between divtab and the sub3 to get its address must
+ be a multiple of 8. */
+__divsf3:
+ lsr r2,r1,17
+ sub3 r3,pcl,55;(.-.Ldivtab) >> 3
+ bmsk_s r2,r2,5
+ ld.as r5,[r3,r2]
+ asl r4,r1,9
+ ld.as r9,[pcl,-114]; [pcl,(-((.-.L7f800000) >> 2))] ; 0x7f800000
+ mpyhu r7,r5,r4
+ asl r6,r1,8
+ and.f r11,r1,r9
+ bset r6,r6,31
+ asl r5,r5,13
+ ; wb stall
+ beq .Ldenorm_fp1
+ sub r7,r5,r7
+ mpyhu r8,r7,r6
+ breq.d r11,r9,.Linf_nan_fp1
+ and.f r2,r0,r9
+ beq.d .Ldenorm_fp0
+ asl r12,r0,8
+ ; wb stall
+ breq r2,r9,.Linf_nan_fp0
+ mpyhu r8,r8,r7
+.Lpast_denorm_fp1:
+ bset r3,r12,31
+.Lpast_denorm_fp0:
+ cmp_s r3,r6
+ lsr.cc r3,r3,1
+ add_s r2,r2, /* wait for immediate */ \
+ /* wb stall */ \
+ 0x3f000000
+ sub r7,r7,r8 ; u1.31 inverse, about 30 bit
+ mpyhu r3,r3,r7
+ sbc r2,r2,r11
+ xor.f 0,r0,r1
+ and r0,r2,r9
+ bxor.mi r0,r0,31
+ brhs r2, /* wb stall / wait for immediate */ \
+ 0x7f000000,.Linf_denorm
+.Lpast_denorm:
+ add_s r3,r3,0x22 ; round to nearest or higher
+ tst r3,0x3c ; check if rounding was unsafe
+ lsr r3,r3,6
+ jne.d [blink] ; return if rounding was safe.
+ add_s r0,r0,r3
+ /* work out exact rounding if we fall through here. */
+ /* We know that the exact result cannot be represented in single
+ precision. Find the mid-point between the two nearest
+ representable values, multiply with the divisor, and check if
+ the result is larger than the dividend. */
+ add_s r3,r3,r3
+ sub_s r3,r3,1
+ mpyu r3,r3,r6
+ asr.f 0,r0,1 ; for round-to-even in case this is a denorm
+ rsub r2,r9,25
+ asl_s r12,r12,r2
+ ; wb stall
+ ; slow track
+ sub.f 0,r12,r3
+ j_s.d [blink]
+ sub.mi r0,r0,1
+/* For denormal results, it is possible that an exact result needs
+ rounding, and thus the round-to-even rule has to come into play. */
+.Linf_denorm:
+ brlo r2,0xc0000000,.Linf
+.Ldenorm:
+ asr_s r2,r2,23
+ bic r0,r0,r9
+ neg r9,r2
+ brlo.d r9,25,.Lpast_denorm
+ lsr r3,r3,r9
+ /* Fall through: return +- 0 */
+ j_s [blink]
+.Linf:
+ j_s.d [blink]
+ or r0,r0,r9
+ ENDFUNC(__divsf3)
diff --git a/libgcc/config/arc/ieee-754/divsf3.S b/libgcc/config/arc/ieee-754/divsf3.S
new file mode 100644
index 00000000000..d7cc2ee938d
--- /dev/null
+++ b/libgcc/config/arc/ieee-754/divsf3.S
@@ -0,0 +1,221 @@
+/* Copyright (C) 2008-2013 Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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/>. */
+
+#include "arc-ieee-754.h"
+
+#if 0 /* DEBUG */
+ .global __divsf3
+ FUNC(__divsf3)
+ .balign 4
+__divsf3:
+ push_s blink
+ push_s r1
+ bl.d __divsf3_c
+ push_s r0
+ ld_s r1,[sp,4]
+ st_s r0,[sp,4]
+ bl.d __divsf3_asm
+ pop_s r0
+ pop_s r1
+ pop_s blink
+ cmp r0,r1
+#if 1
+ bne abort
+ jeq_s [blink]
+ b abort
+#else
+ bne abort
+ j_s [blink]
+#endif
+ ENDFUNC(__divsf3)
+#define __divsf3 __divsf3_asm
+#endif /* DEBUG */
+
+ .balign 4
+__divdf3_support: /* This label makes debugger output saner. */
+ FUNC(__divsf3)
+.Ldenorm_fp0:
+ norm.f r12,r2 ; flag for 0/x -> 0 check
+ bic.ne.f 0,0x60000000,r1 ; denorm/large number -> 0
+ beq_s .Lret0_NaN
+ tst r1,r9
+ add_s r2,r2,r2
+ sub_s r12,r12,8
+ asl_s r2,r2,r12
+ asl_l r12,r12,23
+ bne.d .Lpast_denorm_fp0
+ add r5,r5,r12
+/* r0 is subnormal, r1 is subnormal or 0. */
+
+ .balign 4
+.Ldenorm_fp1:
+ norm.f r12,r3 ; flag for x/0 -> Inf check
+ bic.ne.f 0,0x60000000,r0 ; large number/denorm -> Inf
+ beq_s .Linf
+ add_s r3,r3,r3
+ sub_s r12,r12,8
+ asl_s r3,r3,r12
+ asl_s r12,r12,23
+ b.d .Lpast_denorm_fp1
+ add r4,r4,r12
+
+.Lret0_NaN:
+ bclr.f 0,r1,31 ; 0/0 -> NaN
+ bic r0,r10,r9
+ j_s.d [blink]
+ sub.eq r0,r0,1
+
+ .global __divsf3
+ .balign 4
+ .long 0x7f800000 ; exponent mask
+__divsf3:
+ ld r9,[pcl,-4]
+ bmsk r2,r0,22
+ xor r4,r0,r2
+ bmsk r3,r1,22
+ xor r5,r1,r3
+ and r11,r0,r9
+ breq.d r11,0,.Ldenorm_fp0
+ xor r10,r4,r5
+ breq r11,r9,.Linf_nan_fp0
+ bset_s r2,r2,23
+ and r11,r1,r9
+ breq r11,0,.Ldenorm_fp1
+ breq r11,r9,.Linf_nan_fp1
+.Lpast_denorm_fp0:
+ bset_s r3,r3,23
+.Lpast_denorm_fp1:
+ cmp r2,r3
+ asl_s r2,r2,6+1
+ asl_s r3,r3,7
+ add.lo r2,r2,r2
+ bclr r8,r9,30 ; exponent bias
+ bclr.lo r8,r8,23 ; reduce exp by one if fraction is shifted
+ sub r4,r4,r5
+ add r4,r4,r8
+ xor.f 0,r10,r4
+ bmi .Linf_denorm
+ and r12,r4,r9
+ breq r12,0,.Ldenorm
+ sub_s r2,r2,r3 ; discard implicit 1
+.Ldiv_23bit:
+ .rep 6
+ divaw r2,r2,r3
+ .endr
+ breq r12,r9,.Linf
+ bmsk r0,r2,6
+ xor_s r2,r2,r0
+.Ldiv_17bit:
+ .rep 7
+ divaw r2,r2,r3
+ .endr
+ asl_s r0,r0,7
+ bmsk r1,r2,6
+ xor_s r2,r2,r1
+ or_s r0,r0,r1
+.Ldiv_10bit:
+ .rep 7
+ divaw r2,r2,r3
+ .endr
+ asl_s r0,r0,7
+ bmsk r1,r2,6
+ xor_s r2,r2,r1
+ or_s r0,r0,r1
+.Ldiv_3bit:
+ .rep 3
+ divaw r2,r2,r3
+ .endr
+ asl_s r0,r0,3
+.Ldiv_0bit:
+ divaw r1,r2,r3
+ bmsk_s r2,r2,2
+ tst r1,-0x7e ; 0xffffff82, test for rest or odd
+ bmsk_s r1,r1,0
+ add_s r0,r0,r2 ; assemble fraction
+ add_s r0,r0,r4 ; add in sign & exponent
+ j_s.d [blink]
+ add.ne r0,r0,r1 ; round to nearest / even
+
+ .balign 4
+.Linf_nan_fp0:
+ bic.f 0,r9,r1 ; fp1 Inf -> result NaN
+ bic r1,r5,r9 ; fp1 sign
+ sub.eq r1,r1,1
+ j_s.d [blink]
+ xor_s r0,r0,r1
+.Linf_nan_fp1:
+ bic r0,r4,r9 ; fp0 sign
+ bmsk.f 0,r1,22 ; x/inf -> 0, x/nan -> nan
+ xor.eq r1,r1,r9
+ j_s.d [blink]
+ xor_s r0,r0,r1
+.Linf:
+ j_s.d [blink]
+ or r0,r10,r9
+
+.Lret_r4:
+ j_s.d [blink]
+ mov_s r0,r4
+ .balign 4
+.Linf_denorm:
+ add.f r12,r4,r4
+ asr_l r12,r12,24
+ bpl .Linf
+ max r12,r12,-24
+.Ldenorm:
+ add r1,pcl,42; .Ldenorm_tab-.
+ ldb_s r12,[r12,r1]
+ mov_s r0,0
+ lsr_s r2,r2
+ sub_s r1,r1,r12
+ j_s.d [r1]
+ bic r4,r10,r9
+ .byte .Ldenorm_tab-.Lret_r4
+ .byte .Ldenorm_tab-.Ldiv_0bit
+ .byte .Ldenorm_tab-.Ldiv_3bit-8
+ .byte .Ldenorm_tab-.Ldiv_3bit-4
+ .byte .Ldenorm_tab-.Ldiv_3bit
+ .byte .Ldenorm_tab-.Ldiv_10bit-24
+ .byte .Ldenorm_tab-.Ldiv_10bit-20
+ .byte .Ldenorm_tab-.Ldiv_10bit-16
+ .byte .Ldenorm_tab-.Ldiv_10bit-12
+ .byte .Ldenorm_tab-.Ldiv_10bit-8
+ .byte .Ldenorm_tab-.Ldiv_10bit-4
+ .byte .Ldenorm_tab-.Ldiv_10bit
+ .byte .Ldenorm_tab-.Ldiv_17bit-24
+ .byte .Ldenorm_tab-.Ldiv_17bit-20
+ .byte .Ldenorm_tab-.Ldiv_17bit-16
+ .byte .Ldenorm_tab-.Ldiv_17bit-12
+ .byte .Ldenorm_tab-.Ldiv_17bit-8
+ .byte .Ldenorm_tab-.Ldiv_17bit-4
+ .byte .Ldenorm_tab-.Ldiv_17bit
+ .byte .Ldenorm_tab-.Ldiv_23bit-20
+ .byte .Ldenorm_tab-.Ldiv_23bit-16
+ .byte .Ldenorm_tab-.Ldiv_23bit-12
+ .byte .Ldenorm_tab-.Ldiv_23bit-8
+ .byte .Ldenorm_tab-.Ldiv_23bit-4
+.Ldenorm_tab:
+ .byte .Ldenorm_tab-.Ldiv_23bit
+ ENDFUNC(__divsf3)
diff --git a/libgcc/config/arc/ieee-754/divtab-arc-df.c b/libgcc/config/arc/ieee-754/divtab-arc-df.c
new file mode 100644
index 00000000000..b1574b9dc32
--- /dev/null
+++ b/libgcc/config/arc/ieee-754/divtab-arc-df.c
@@ -0,0 +1,161 @@
+/* Copyright (C) 2008-2013 Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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/>. */
+
+/* We use a polynom similar to a Tchebycheff polynom to get an initial
+ seed, and then use a newton-raphson iteration step to get an
+ approximate result
+ If this result can't be rounded to the exact result with confidence, we
+ round to the value between the two closest representable values, and
+ test if the correctly rounded value is above or below this value.
+
+ Because of the Newton-raphson iteration step, an error in the seed at X
+ is amplified by X. Therefore, we don't want a Tchebycheff polynom
+ or a polynom that is close to optimal according to the maximum norm
+ on the errro of the seed value; we want one that is close to optimal
+ according to the maximum norm on the error of the result, i.e. we
+ want the maxima of the polynom to increase linearily.
+ Given an interval [X0,X2) over which to approximate,
+ with X1 := (X0+X2)/2, D := X1-X0, F := 1/D, and S := D/X1 we have,
+ like for Tchebycheff polynoms:
+ P(0) := 1
+ but then we have:
+ P(1) := X + S*D
+ P(2) := 2 * X^2 + S*D * X - D^2
+ Then again:
+ P(n+1) := 2 * X * P(n) - D^2 * P (n-1)
+ */
+
+static long double merr = 42.;
+
+double
+err (long double a0, long double a1, long double x)
+{
+ long double y0 = a0 + (x-1)*a1;
+
+ long double approx = 2. * y0 - y0 * x * y0;
+ long double true = 1./x;
+ long double err = approx - true;
+
+ if (err <= -1./65536./16384.)
+ printf ("ERROR EXCEEDS 1 ULP %.15f %.15f %.15f\n",
+ (double)x, (double)approx, (double)true);
+ if (merr > err)
+ merr = err;
+ return err;
+}
+
+int
+main (void)
+{
+ long double T[5]; /* Taylor polynom */
+ long double P[5][5];
+ int i, j;
+ long double X0, X1, X2, S;
+ long double inc = 1./64;
+ long double D = inc*0.5;
+ long i0, i1, i2, io;
+
+ memset (P, 0, sizeof (P));
+ P[0][0] = 1.;
+ for (i = 1; i < 5; i++)
+ P[i][i] = 1 << i-1;
+ P[2][0] = -D*D;
+ for (X0 = 1.; X0 < 2.; X0 += inc)
+ {
+ X1 = X0 + inc * 0.5;
+ X2 = X0 + inc;
+ S = D / X1;
+ T[0] = 1./X1;
+ for (i = 1; i < 5; i++)
+ T[i] = T[i-1] * -T[0];
+#if 0
+ printf ("T %1.8f %f %f %f %f\n", (double)T[0], (double)T[1], (double)T[2],
+(double)T[3], (double)T[4]);
+#endif
+ P[1][0] = S*D;
+ P[2][1] = S*D;
+ for (i = 3; i < 5; i++)
+ {
+ P[i][0] = -D*D*P[i-2][0];
+ for (j = 1; j < i; j++)
+ P[i][j] = 2*P[i-1][j-1]-D*D*P[i-2][j];
+ }
+#if 0
+ printf ("P3 %1.8f %f %f %f %f\n", (double)P[3][0], (double)P[3][1], (double)P[3][2],
+(double)P[3][3], (double)P[3][4]);
+ printf ("P4 %1.8f %f %f %f %f\n", (double)P[4][0], (double)P[4][1], (double)P[4][2],
+(double)P[4][3], (double)P[4][4]);
+#endif
+ for (i = 4; i > 1; i--)
+ {
+ long double a = T[i]/P[i][i];
+
+ for (j = 0; j < i; j++)
+ T[j] -= a * P[i][j];
+ }
+#if 0
+ printf ("A %1.8f %f %f\n", (double)T[0], (double)T[1], (double)T[2]);
+#endif
+#if 0
+ i2 = T[2]*1024;
+ long double a = (T[2]-i/1024.)/P[2][2];
+ for (j = 0; j < 2; j++)
+ T[j] -= a * P[2][j];
+#else
+ i2 = 0;
+#endif
+ long double T0, Ti1;
+ for (i = 0, i0 = 0; i < 4; i++)
+ {
+
+ i1 = T[1]*4096. + i0 / (long double)(1 << 20) - 0.5;
+ i1 = - (-i1 & 0x0fff);
+ Ti1 = ((unsigned)(-i1 << 20) | i0) /-(long double)(1LL<<32LL);
+ T0 = T[0] - (T[1]-Ti1)/P[1][1] * P[1][0] - (X1 - 1) * Ti1;
+ i0 = T0 * 1024 * 1024 + 0.5;
+ i0 &= 0xfffff;
+ }
+#if 0
+ printf ("A %1.8f %f %f\n", (double)T[0], (double)T[1], (double)T[2]);
+#endif
+ io = (unsigned)(-i1 << 20) | i0;
+ long double A1 = (unsigned)io/-65536./65536.;
+ long double A0 = (unsigned)(io << 12)/65536./65536.;
+ long double Xm0 = 1./sqrt (-A1);
+ long double Xm1 = 0.5+0.5*-A0/A1;
+#if 0
+ printf ("%f %f %f %f\n", (double)A0, (double)A1, (double) Ti1, (double)X0);
+ printf ("%.12f %.12f %.12f\n",
+ err (A0, A1, X0), err (A0, A1, X1), err (A0, A1, X2));
+ printf ("%.12f %.12f\n", (double)Xm0, (double)Xm1);
+ printf ("%.12f %.12f\n", err (A0, A1, Xm0), err (A0, A1, Xm1));
+#endif
+ printf ("\t.long 0x%x\n", io);
+ }
+#if 0
+ printf ("maximum error: %.15f %x %f\n", (double)merr, (unsigned)(long long)(-merr * 65536 * 65536), (double)log(-merr)/log(2));
+#endif
+ return 0;
+}
diff --git a/libgcc/config/arc/ieee-754/divtab-arc-sf.c b/libgcc/config/arc/ieee-754/divtab-arc-sf.c
new file mode 100644
index 00000000000..d76e4996d21
--- /dev/null
+++ b/libgcc/config/arc/ieee-754/divtab-arc-sf.c
@@ -0,0 +1,127 @@
+/* Copyright (C) 2008-2013 Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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/>. */
+
+/* We use a polynom similar to a Tchebycheff polynom to get an initial
+ seed, and then use a newton-raphson iteration step to get an
+ approximate result
+ If this result can't be rounded to the exact result with confidence, we
+ round to the value between the two closest representable values, and
+ test if the correctly rounded value is above or below this value.
+
+ Because of the Newton-raphson iteration step, an error in the seed at X
+ is amplified by X. Therefore, we don't want a Tchebycheff polynom
+ or a polynom that is close to optimal according to the maximum norm
+ on the errro of the seed value; we want one that is close to optimal
+ according to the maximum norm on the error of the result, i.e. we
+ want the maxima of the polynom to increase linearily.
+ Given an interval [X0,X2) over which to approximate,
+ with X1 := (X0+X2)/2, D := X1-X0, F := 1/D, and S := D/X1 we have,
+ like for Tchebycheff polynoms:
+ P(0) := 1
+ but then we have:
+ P(1) := X + S*D
+ P(2) := 2 * X^2 + S*D * X - D^2
+ Then again:
+ P(n+1) := 2 * X * P(n) - D^2 * P (n-1)
+ */
+
+int
+main (void)
+{
+ long double T[5]; /* Taylor polynom */
+ long double P[5][5];
+ int i, j;
+ long double X0, X1, X2, S;
+ long double inc = 1./64;
+ long double D = inc*0.5;
+ long i0, i1, i2;
+
+ memset (P, 0, sizeof (P));
+ P[0][0] = 1.;
+ for (i = 1; i < 5; i++)
+ P[i][i] = 1 << i-1;
+ P[2][0] = -D*D;
+ for (X0 = 1.; X0 < 2.; X0 += inc)
+ {
+ X1 = X0 + inc * 0.5;
+ X2 = X1 + inc;
+ S = D / X1;
+ T[0] = 1./X1;
+ for (i = 1; i < 5; i++)
+ T[i] = T[i-1] * -T[0];
+#if 0
+ printf ("T %1.8f %f %f %f %f\n", (double)T[0], (double)T[1], (double)T[2],
+(double)T[3], (double)T[4]);
+#endif
+ P[1][0] = S*D;
+ P[2][1] = S*D;
+ for (i = 3; i < 5; i++)
+ {
+ P[i][0] = -D*D*P[i-2][0];
+ for (j = 1; j < i; j++)
+ P[i][j] = 2*P[i-1][j-1]-D*D*P[i-2][j];
+ }
+#if 0
+ printf ("P3 %1.8f %f %f %f %f\n", (double)P[3][0], (double)P[3][1], (double)P[3][2],
+(double)P[3][3], (double)P[3][4]);
+ printf ("P4 %1.8f %f %f %f %f\n", (double)P[4][0], (double)P[4][1], (double)P[4][2],
+(double)P[4][3], (double)P[4][4]);
+#endif
+ for (i = 4; i > 1; i--)
+ {
+ long double a = T[i]/P[i][i];
+
+ for (j = 0; j < i; j++)
+ T[j] -= a * P[i][j];
+ }
+#if 0
+ printf ("A %1.8f %f %f\n", (double)T[0], (double)T[1], (double)T[2]);
+#endif
+#if 0
+ i2 = T[2]*512;
+ long double a = (T[2]-i/512.)/P[2][2];
+ for (j = 0; j < 2; j++)
+ T[j] -= a * P[2][j];
+#else
+ i2 = 0;
+#endif
+ for (i = 0, i0 = 0; i < 4; i++)
+ {
+ long double T0, Ti1;
+
+ i1 = T[1]*8192. + i0 / (long double)(1 << 19) - 0.5;
+ i1 = - (-i1 & 0x1fff);
+ Ti1 = ((unsigned)(-i1 << 19) | i0) /-(long double)(1LL<<32LL);
+ T0 = T[0] - (T[1]-Ti1)/P[1][1] * P[1][0] - (X1 - 1) * Ti1;
+ i0 = T0 * 512 * 1024 + 0.5;
+ i0 &= 0x7ffff;
+ }
+#if 0
+ printf ("A %1.8f %f %f\n", (double)T[0], (double)T[1], (double)T[2]);
+#endif
+ printf ("\t.long 0x%x\n", (-i1 << 19) | i0);
+ }
+ return 0;
+}
diff --git a/libgcc/config/arc/ieee-754/eqdf2.S b/libgcc/config/arc/ieee-754/eqdf2.S
new file mode 100644
index 00000000000..26f09682494
--- /dev/null
+++ b/libgcc/config/arc/ieee-754/eqdf2.S
@@ -0,0 +1,76 @@
+/* Copyright (C) 2008-2013 Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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/>. */
+
+#include "arc-ieee-754.h"
+/* inputs: DBL0, DBL1
+ output: z flag
+ clobber: r12, flags
+ For NaNs, bit 19.. bit 30 of the high word must be set. */
+#if 0 /* DEBUG */
+ .global __eqdf2
+ .balign 4
+ FUNC(__eqdf2)
+__eqdf2:
+ st.a r11,[sp,-4]` push_s blink` st.a r10,[sp,-4]` st.a r9,[sp,-4]
+ st.a r8,[sp,-4]` st.a r7,[sp,-4]` st.a r6,[sp,-4]` st.a r5,[sp,-4]
+ st.a r4,[sp,-4]` push_s r3` push_s r2` push_s r1`
+ bl.d __eqdf2_c` push_s r0
+ mov r11,r0` pop_s r0` pop_s r1` pop_s r2` pop_s r3
+ ld.ab r4,[sp,4]` ld.ab r5,[sp,4]` ld.ab r6,[sp,4]`
+ ld.ab r7,[sp,4]` ld.ab r8,[sp,4]` ld.ab r9,[sp,4]
+ bl.d __eqdf2_asm` ld.ab r10,[sp,4]
+ pop_s blink
+ breq.d r11,0,0f
+ ld.ab r11,[sp,4]
+ jne_s [blink]
+ bl abort
+0: jeq_s [blink]
+ bl abort
+ ENDFUNC(__eqdf2)
+#define __eqdf2 __eqdf2_asm
+#endif /* DEBUG */
+ .global __eqdf2
+ .balign 4
+ HIDDEN_FUNC(__eqdf2)
+ /* Good performance as long as the difference in high word is
+ well predictable (as seen from the branch predictor). */
+__eqdf2:
+ brne.d DBL0H,DBL1H,.Lhighdiff
+ bmsk r12,DBL0H,20
+#ifdef DPFP_COMPAT
+ or.f 0,DBL0L,DBL1L
+ bset.ne r12,r12,21
+#endif /* DPFP_COMPAT */
+ add1.f r12,r12,DBL0H /* set c iff NaN; also, clear z if NaN. */
+ j_s.d [blink]
+ cmp.cc DBL0L,DBL1L
+ .balign 4
+.Lhighdiff:
+ or r12,DBL0H,DBL1H
+ or.f 0,DBL0L,DBL1L
+ j_s.d [blink]
+ bmsk.eq.f r12,r12,30
+ ENDFUNC(__eqdf2)
+/* ??? could we do better by speeding up some 'common' case of inequality? */
diff --git a/libgcc/config/arc/ieee-754/eqsf2.S b/libgcc/config/arc/ieee-754/eqsf2.S
new file mode 100644
index 00000000000..4390982bc83
--- /dev/null
+++ b/libgcc/config/arc/ieee-754/eqsf2.S
@@ -0,0 +1,69 @@
+/* Copyright (C) 2008-2013 Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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/>. */
+
+#include "arc-ieee-754.h"
+/* inputs: r0, r1
+ output: z flag
+ clobber: r12, flags
+ For NaNs, bit 22 .. bit 30 must be set. */
+#if 0 /* DEBUG */
+ .global __eqsf2
+ .balign 4
+ FUNC(__eqsf2)
+__eqsf2:
+ st.a r11,[sp,-4]` push_s blink` st.a r10,[sp,-4]` st.a r9,[sp,-4]
+ st.a r8,[sp,-4]` st.a r7,[sp,-4]` st.a r6,[sp,-4]` st.a r5,[sp,-4]
+ st.a r4,[sp,-4]` push_s r3` push_s r2` push_s r1`
+ bl.d __eqsf2_c` push_s r0
+ mov r11,r0` pop_s r0` pop_s r1` pop_s r2` pop_s r3
+ ld.ab r4,[sp,4]` ld.ab r5,[sp,4]` ld.ab r6,[sp,4]`
+ ld.ab r7,[sp,4]` ld.ab r8,[sp,4]` ld.ab r9,[sp,4]
+ bl.d __eqsf2_asm` ld.ab r10,[sp,4]
+ pop_s blink
+ breq.d r11,0,0f
+ ld.ab r11,[sp,4]
+ jne_s [blink]
+ bl abort
+0: jeq_s [blink]
+ bl abort
+ ENDFUNC(__eqsf2)
+#define __eqsf2 __eqsf2_asm
+#endif /* DEBUG */
+ /* Good performance as long as the binary difference is
+ well predictable (as seen from the branch predictor). */
+ .global __eqsf2
+ .balign 4
+ HIDDEN_FUNC(__eqsf2)
+__eqsf2:
+ breq r0, r1,.Lno_bdiff
+ or r12,r0,r1
+ j_s.d [blink]
+ bmsk.f 0,r12,30
+.Lno_bdiff:
+ bmsk r12,r0,23
+ add1.f r12,r12,r0 /* set c iff NaN; also, clear z if NaN. */
+ j_s.d [blink]
+ cmp.cc r0,r1
+ ENDFUNC(__eqsf2)
diff --git a/libgcc/config/arc/ieee-754/extendsfdf2.S b/libgcc/config/arc/ieee-754/extendsfdf2.S
new file mode 100644
index 00000000000..12e29449a96
--- /dev/null
+++ b/libgcc/config/arc/ieee-754/extendsfdf2.S
@@ -0,0 +1,122 @@
+/* Copyright (C) 2006, 2008-2013 Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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/>. */
+
+#include "arc-ieee-754.h"
+
+#if 0 /* DEBUG */
+ .global __extendsfdf2
+ .balign 4
+ FUNC(__extendsfdf2)
+__extendsfdf2:
+ push_s blink
+ bl.d __extendsfdf2_c
+ push_s r0
+ ld_s r2,[sp]
+ st_s r1,[sp]
+ push_s r0
+ bl.d __extendsfdf2_asm
+ mov_s r0,r2
+ pop_s r2
+ pop_s r3
+ pop_s blink
+ cmp r0,r2
+ cmp.eq r1,r3
+ jeq_s [blink]
+ bl abort
+ ENDFUNC(__extendsfdf2)
+#define __extendsfdf2 __extendsfdf2_asm
+#endif /* DEBUG */
+#if 0 /* ARC600 */
+__extendsfdf2:
+ lsr r2,r0,23
+ tst r2,0xff
+ bic.ne.f r2,0xff
+ beq_s .Linf_nan_denorm_0
+..
+.Linf_nan_denorm:
+ bbit1 r0,30,.Linf_nan
+#endif
+ .global __extendsfdf2
+ .balign 4
+ FUNC(__extendsfdf2)
+__extendsfdf2:
+ add.f r1,r0,r0
+ norm r3,r1
+#ifdef __LITTLE_ENDIAN__
+ lsr_s DBL0H,r1,4
+ brhs r3,7,.Linf_nan_denorm_0
+ asl_s DBL0L,r0,29
+ add_s DBL0H,DBL0H, \
+ 0x38000000
+#else
+ lsr r2,r1,4
+ brhs r3,7,.Linf_nan_denorm_0
+ asl_s DBL0L,r1,28
+ add DBL0H,r2, \
+ 0x38000000
+#endif
+ j_s.d [blink]
+ bxor.cs DBL0H,DBL0H,31
+ .balign 4
+.Linf_nan_denorm_0:
+#ifdef __LITTLE_ENDIAN__
+ mov_s DBL0H,r0
+ jeq.d [blink]
+ mov.eq DBL0L,0
+#else
+ jeq_s [blink]
+#endif
+ bmi .Linf_nan
+ asl_s r0,r0,r3
+ rsub r3,r3,0x380+6
+#ifdef __LITTLE_ENDIAN__
+ asl_s r3,r3,20
+ lsr DBL0H,r0,9
+ asl_s DBL0L,r0,23
+ add_s DBL0H,DBL0H,r3
+ j_s.d [blink]
+ bxor.cs DBL0H,DBL0H,31
+#else
+ asl DBL0L,r0,23
+ lsr_s DBL0H,r0,9
+ asl_s r3,r3,20
+ bxor.cs DBL0H,DBL0H,31
+ j_s.d [blink]
+ add_l DBL0H,DBL0H,r3
+#endif
+.Linf_nan:
+#ifdef __LITTLE_ENDIAN__
+ lsr DBL0H,r0,3
+
+ or_s DBL0H,DBL0H,r0
+ j_s.d [blink]
+ mov_l DBL0L,0
+#else
+ lsr r3,r0,3
+ mov_s DBL0L,0
+ j_s.d [blink]
+ or_l DBL0H,r0,r3
+#endif
+ ENDFUNC(__extendsfdf2)
diff --git a/libgcc/config/arc/ieee-754/fixdfsi.S b/libgcc/config/arc/ieee-754/fixdfsi.S
new file mode 100644
index 00000000000..f35d0b6eb06
--- /dev/null
+++ b/libgcc/config/arc/ieee-754/fixdfsi.S
@@ -0,0 +1,85 @@
+/* Copyright (C) 2008-2013 Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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/>. */
+
+#include "arc-ieee-754.h"
+
+#if 0 /* DEBUG */
+ FUNC(__fixdfsi)
+ .global __fixdfsi
+ .balign 4
+__fixdfsi:
+ push_s blink
+ push_s r0
+ bl.d __fixdfsi_c
+ push_s r1
+ mov_s r2,r0
+ pop_s r1
+ ld r0,[sp]
+ bl.d __fixdfsi_asm
+ st r2,[sp]
+ pop_s r1
+ pop_s blink
+ cmp r0,r1
+ jeq_s [blink]
+ bl abort
+ ENDFUNC(__fixdfsi)
+#define __fixdfsi __fixdfsi_asm
+#endif /* DEBUG */
+
+/* If the fraction has to be shifted left by a positive non-zero amount,
+ we have to combine bits from DBL0L and DBL0H. If we shift right,
+ or shift by zero, we only want to have the bits from DBL0H in r0. */
+
+ .global __fixdfsi
+ FUNC(__fixdfsi)
+ .balign 4
+__fixdfsi:
+ bbit0 DBL0H,30,.Lret0or1
+ asr r2,DBL0H,20
+ bmsk_s DBL0H,DBL0H,19
+ sub_s r2,r2,19; 0x3ff+20-0x400
+ neg_s r3,r2
+ asr.f 0,r3,11
+ bset_s DBL0H,DBL0H,20
+#ifdef __LITTLE_ENDIAN__
+ mov.cs DBL0L,DBL0H
+ asl DBL0H,DBL0H,r2
+#else
+ asl.cc DBL0H,DBL0H,r2
+ lsr.cs DBL0H,DBL0H,r3
+#endif
+ lsr_s DBL0L,DBL0L,r3
+
+ add.cc r0,r0,r1
+ j_s.d [blink]
+ neg.pl r0,r0
+.Lret0or1:
+ add.f r0,DBL0H,0x100000
+ lsr_s r0,r0,30
+
+ bmsk_s r0,r0,0
+ j_s.d [blink]
+ neg.mi r0,r0
+ ENDFUNC(__fixdfsi)
diff --git a/libgcc/config/arc/ieee-754/fixsfsi.S b/libgcc/config/arc/ieee-754/fixsfsi.S
new file mode 100644
index 00000000000..045b99f1982
--- /dev/null
+++ b/libgcc/config/arc/ieee-754/fixsfsi.S
@@ -0,0 +1,71 @@
+/* Copyright (C) 2008-2013 Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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/>. */
+
+#include "arc-ieee-754.h"
+
+#if 0 /* DEBUG */
+ .global __fixsfsi
+ FUNC(__fixsfsi)
+ .balign 4
+__fixsfsi:
+ push_s blink
+ bl.d __fixsfsi_c
+ push_s r0
+ ld_s r1,[sp]
+ st_s r0,[sp]
+ bl.d __fixsfsi_asm
+ mov_s r0,r1
+ pop_s r1
+ pop_s blink
+ cmp r0,r1
+ jeq_s [blink]
+ bl abort
+ ENDFUNC(__fixsfsi)
+#define __fixsfsi __fixsfsi_asm
+#endif /* DEBUG */
+
+ .global __fixsfsi
+ FUNC(__fixsfsi)
+ .balign 4
+__fixsfsi:
+ bbit0 r0,30,.Lret0or1
+ lsr r2,r0,23
+ bmsk_s r0,r0,22
+ bset_s r0,r0,23
+ sub_s r2,r2,22;0x7f+23-0x80
+ asl.f 0,r2,24
+ neg r3,r2
+ asl.mi r0,r0,r2
+ lsr.pl r0,r0,r3
+ j_s.d [blink]
+ neg.cs r0,r0
+.Lret0or1:
+ add.f r0,r0,0x800000
+ lsr_s r0,r0,30
+
+ bmsk_s r0,r0,0
+ j_s.d [blink]
+ neg.mi r0,r0
+ ENDFUNC(__fixsfsi)
diff --git a/libgcc/config/arc/ieee-754/fixunsdfsi.S b/libgcc/config/arc/ieee-754/fixunsdfsi.S
new file mode 100644
index 00000000000..54116a5b94d
--- /dev/null
+++ b/libgcc/config/arc/ieee-754/fixunsdfsi.S
@@ -0,0 +1,80 @@
+/* Copyright (C) 2008-2013 Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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/>. */
+
+#include "arc-ieee-754.h"
+
+#if 0 /* DEBUG */
+ FUNC(__fixunsdfsi)
+ .global __fixunsdfsi
+ .balign 4
+__fixunsdfsi:
+ push_s blink
+ push_s r0
+ bl.d __fixunsdfsi_c
+ push_s r1
+ mov_s r2,r0
+ pop_s r1
+ ld r0,[sp]
+ bl.d __fixunsdfsi_asm
+ st r2,[sp]
+ pop_s r1
+ pop_s blink
+ cmp r0,r1
+ jeq_s [blink]
+ bl abort
+ ENDFUNC(__fixunsdfsi)
+#define __fixunsdfsi __fixunsdfsi_asm
+#endif /* DEBUG */
+
+ .global __fixunsdfsi
+ FUNC(__fixunsdfsi)
+ .balign 4
+__fixunsdfsi:
+ bbit0 DBL0H,30,.Lret0or1
+ lsr r2,DBL0H,20
+ bmsk_s DBL0H,DBL0H,19
+ sub_s r2,r2,19; 0x3ff+20-0x400
+ neg_s r3,r2
+ btst_s r3,10
+ bset_s DBL0H,DBL0H,20
+#ifdef __LITTLE_ENDIAN__
+ mov.ne DBL0L,DBL0H
+ asl DBL0H,DBL0H,r2
+#else
+ asl.eq DBL0H,DBL0H,r2
+ lsr.ne DBL0H,DBL0H,r3
+#endif
+ lsr DBL0L,DBL0L,r3
+ j_s.d [blink]
+ add.eq r0,r0,r1
+.Lret0:
+ j_s.d [blink]
+ mov_l r0,0
+.Lret0or1:
+ add_s DBL0H,DBL0H,0x100000
+ lsr_s DBL0H,DBL0H,30
+ j_s.d [blink]
+ bmsk_l r0,DBL0H,0
+ ENDFUNC(__fixunsdfsi)
diff --git a/libgcc/config/arc/ieee-754/floatsidf.S b/libgcc/config/arc/ieee-754/floatsidf.S
new file mode 100644
index 00000000000..f7aa0324366
--- /dev/null
+++ b/libgcc/config/arc/ieee-754/floatsidf.S
@@ -0,0 +1,77 @@
+/* Copyright (C) 2008-2013 Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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/>. */
+
+#include "arc-ieee-754.h"
+
+#if 0 /* DEBUG */
+ .global __floatsidf
+ .balign 4
+ FUNC(__floatsidf)
+__floatsidf:
+ push_s blink
+ bl.d __floatsidf_c
+ push_s r0
+ ld_s r2,[sp]
+ st_s r1,[sp]
+ push_s r0
+ bl.d __floatsidf_asm
+ mov_s r0,r2
+ pop_s r2
+ pop_s r3
+ pop_s blink
+ cmp r0,r2
+ cmp.eq r1,r3
+ jeq_s [blink]
+ bl abort
+ ENDFUNC(__floatsidf)
+#define __floatsidf __floatsidf_asm
+#endif /* DEBUG */
+
+ .global __floatsidf
+ .balign 4
+ FUNC(__floatsidf)
+__floatsidf:
+ abs.f r1,r0
+ jeq_s [blink]
+ lsr r2,r1
+ mov r12,-0x41d ; -(0x3ff+31-1)
+ norm r2,r2
+ bclr.cs r12,r12,11
+ rsub.f r3,r2,11
+ add_s r12,r2,r12
+ add_s r2,r2,21
+#ifdef __LITTLE_ENDIAN__
+ asl DBL0L,r1,r2
+ lsr_s DBL0H,r1,r3
+#else
+ lsr DBL0H,r1,r3
+ asl_s DBL0L,r1,r2
+#endif
+ asl_s r12,r12,20
+ mov.lo DBL0H,DBL0L
+ sub_s DBL0H,DBL0H,r12
+ j_s.d [blink]
+ mov.ls DBL0L,0
+ ENDFUNC(__floatsidf)
diff --git a/libgcc/config/arc/ieee-754/floatsisf.S b/libgcc/config/arc/ieee-754/floatsisf.S
new file mode 100644
index 00000000000..d5838b00d95
--- /dev/null
+++ b/libgcc/config/arc/ieee-754/floatsisf.S
@@ -0,0 +1,99 @@
+/* Copyright (C) 2008-2013 Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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/>. */
+
+#include "arc-ieee-754.h"
+
+#if 0 /* DEBUG */
+ .global __floatsisf
+ FUNC(__floatsisf)
+ .balign 4
+__floatsisf:
+ push_s blink
+ bl.d __floatsisf_c
+ push_s r0
+ ld_s r1,[sp]
+ st_s r0,[sp]
+ bl.d __floatsisf_asm
+ mov_s r0,r1
+ pop_s r1
+ pop_s blink
+ cmp r0,r1
+ jeq_s [blink]
+ bl abort
+ ENDFUNC(__floatsisf)
+ .global __floatunsisf
+ FUNC(__floatunsisf)
+ .balign 4
+__floatunsisf:
+ push_s blink
+ bl.d __floatunsisf_c
+ push_s r0
+ ld_s r1,[sp]
+ st_s r0,[sp]
+ bl.d __floatunsisf_asm
+ mov_s r0,r1
+ pop_s r1
+ pop_s blink
+ cmp r0,r1
+ jeq_s [blink]
+ bl abort
+ ENDFUNC(__floatunsisf)
+#define __floatsisf __floatsisf_asm
+#define __floatunsisf __floatunsisf_asm
+#endif /* DEBUG */
+
+ .global __floatunsisf
+ .global __floatsisf
+ FUNC(__floatsisf)
+ FUNC(__floatunsisf)
+ .balign 4
+__floatunsisf:
+ lsr_s r2,r0
+ mov_l r12,0x9d ; 0x7f + 31 - 1
+ norm r2,r2
+ brne_l r0,0,0f
+ j_s [blink]
+ .balign 4
+__floatsisf:
+ abs.f r0,r0
+ jeq_s [blink]
+ lsr_s r2,r0
+ mov_s r12,0x9d ; 0x7f + 31 - 1
+ norm r2,r2
+ bset.cs r12,r12,8
+0: rsub.f r3,r2,8
+ bmsk r1,r0,r3
+ ror r1,r1,r3
+ lsr.pl r0,r0,r3
+ neg_s r3,r3
+ asl.mi r0,r0,r3
+ sub_s r12,r12,r2
+ asl_s r12,r12,23
+ bxor.pl.f r1,r1,31
+ add_s r0,r0,r12
+ j_s.d [blink]
+ add.pnz r0,r0,1
+ ENDFUNC(__floatunsisf)
+ ENDFUNC(__floatsisf)
diff --git a/libgcc/config/arc/ieee-754/floatunsidf.S b/libgcc/config/arc/ieee-754/floatunsidf.S
new file mode 100644
index 00000000000..c04b2461c3b
--- /dev/null
+++ b/libgcc/config/arc/ieee-754/floatunsidf.S
@@ -0,0 +1,75 @@
+/* Copyright (C) 2008-2013 Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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/>. */
+
+#include "arc-ieee-754.h"
+
+#if 0 /* DEBUG */
+ .global __floatunsidf
+ .balign 4
+ FUNC(__floatunsidf)
+__floatunsidf:
+ push_s blink
+ bl.d __floatunsidf_c
+ push_s r0
+ ld_s r2,[sp]
+ st_s r1,[sp]
+ push_s r0
+ bl.d __floatunsidf_asm
+ mov_s r0,r2
+ pop_s r2
+ pop_s r3
+ pop_s blink
+ cmp r0,r2
+ cmp.eq r1,r3
+ jeq_s [blink]
+ bl abort
+ ENDFUNC(__floatunsidf)
+#define __floatunsidf __floatunsidf_asm
+#endif /* DEBUG */
+
+ .global __floatunsidf
+ .balign 4
+ FUNC(__floatunsidf)
+__floatunsidf:
+ lsr_s r1,r0
+ breq_s r0,0,.Lret0
+ norm r2,r1
+ mov r12,-0x41d ; -(0x3ff+31-1)
+ rsub.f r3,r2,11
+ add_s r12,r2,r12
+ add_s r2,r2,21
+#ifdef __LITTLE_ENDIAN__
+ lsr DBL0H,r0,r3
+ asl_s DBL0L,r0,r2
+#else
+ asl DBL0L,r0,r2
+ lsr_s DBL0H,r0,r3
+#endif
+ asl_s r12,r12,20
+ mov.lo DBL0H,DBL0L
+ sub_s DBL0H,DBL0H,r12
+.Lret0: j_s.d [blink]
+ mov.ls DBL0L,0
+ ENDFUNC(__floatunsidf)
diff --git a/libgcc/config/arc/ieee-754/gedf2.S b/libgcc/config/arc/ieee-754/gedf2.S
new file mode 100644
index 00000000000..e0ea266104b
--- /dev/null
+++ b/libgcc/config/arc/ieee-754/gedf2.S
@@ -0,0 +1,86 @@
+/* Copyright (C) 2008-2013 Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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/>. */
+
+#include "arc-ieee-754.h"
+/* inputs: DBL0, DBL1
+ output: c flags to be used for 'hs' condition
+ clobber: r12, flags */
+/* For NaNs, bit 19.. bit 30 of the high word must be set. */
+#if 0 /* DEBUG */
+ .global __gedf2
+ .balign 4
+ FUNC(__gedf2)
+__gedf2:
+ st.a r11,[sp,-4]` push_s blink` st.a r10,[sp,-4]` st.a r9,[sp,-4]
+ st.a r8,[sp,-4]` st.a r7,[sp,-4]` st.a r6,[sp,-4]` st.a r5,[sp,-4]
+ st.a r4,[sp,-4]` push_s r3` push_s r2` push_s r1`
+ bl.d __gedf2_c` push_s r0
+ mov r11,r0` pop_s r0` pop_s r1` pop_s r2` pop_s r3
+ ld.ab r4,[sp,4]` ld.ab r5,[sp,4]` ld.ab r6,[sp,4]`
+ ld.ab r7,[sp,4]` ld.ab r8,[sp,4]` ld.ab r9,[sp,4]
+ bl.d __gedf2_asm` ld.ab r10,[sp,4]
+ pop_s blink
+ brge.d r11,0,0f
+ ld.ab r11,[sp,4]
+ jlo [blink]
+ bl abort
+0: jhs [blink]
+ bl abort
+ ENDFUNC(__gedf2)
+#define __gedf2 __gedf2_asm
+#endif /* DEBUG */
+ .global __gedf2
+ .balign 4
+ HIDDEN_FUNC(__gedf2)
+__gedf2:
+ or.f r12,DBL0H,DBL1H
+ bmi.d .Lneg
+ bmsk_s r12,r12,20
+ add1.f 0,r12,DBL0H ; clear z; set c iff NaN
+ add1.cc.f r12,r12,DBL1H ; clear z; set c iff NaN
+ bbit1 DBL0H,31,.Lneg
+ cmp.cc DBL0H,DBL1H
+ j_s.d [blink]
+ cmp.eq DBL0L,DBL1L
+ .balign 4
+.Lneg: breq.d DBL1H,0,.L0
+ add1.f 0,r12,DBL0H
+ add1.cc.f r12,r12,DBL1H
+ cmp.cc DBL1H,DBL0H
+ j_s.d [blink]
+ cmp.eq DBL1L,DBL0L
+ .balign 4
+.L0:
+ bxor.f 0,DBL0H,31 ; check for high word of -0.
+ beq_s .Lcheck_0
+ cmp.cc DBL1H,DBL0H
+ j_s.d [blink]
+ cmp.eq DBL1L,DBL0L
+.Lcheck_0:
+ ; high words suggest DBL0 may be -0, DBL1 +0; check low words.
+ cmp_s DBL1H,DBL0L
+ j_s.d [blink]
+ cmp.cc DBL1H,DBL1L
+ ENDFUNC(__gedf2)
diff --git a/libgcc/config/arc/ieee-754/gesf2.S b/libgcc/config/arc/ieee-754/gesf2.S
new file mode 100644
index 00000000000..857db58a237
--- /dev/null
+++ b/libgcc/config/arc/ieee-754/gesf2.S
@@ -0,0 +1,75 @@
+/* Copyright (C) 2008-2013 Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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/>. */
+
+#include "arc-ieee-754.h"
+/* inputs: r0, r1
+ output: c flag to be used for 'hs' condition
+ clobber: r12,flags */
+/* For NaNs, bit 22.. bit 30 must be set. */
+#if 0 /* DEBUG */
+ .global __gesf2
+ .balign 4
+ FUNC(__gesf2)
+__gesf2:
+ st.a r11,[sp,-4]` push_s blink` st.a r10,[sp,-4]` st.a r9,[sp,-4]
+ st.a r8,[sp,-4]` st.a r7,[sp,-4]` st.a r6,[sp,-4]` st.a r5,[sp,-4]
+ st.a r4,[sp,-4]` push_s r3` push_s r2` push_s r1`
+ bl.d __gesf2_c` push_s r0
+ mov r11,r0` pop_s r0` pop_s r1` pop_s r2` pop_s r3
+ ld.ab r4,[sp,4]` ld.ab r5,[sp,4]` ld.ab r6,[sp,4]`
+ ld.ab r7,[sp,4]` ld.ab r8,[sp,4]` ld.ab r9,[sp,4]
+ bl.d __gesf2_asm` ld.ab r10,[sp,4]
+ pop_s blink
+ brge.d r11,0,0f
+ ld.ab r11,[sp,4]
+ jlo [blink]
+ bl abort
+0: jhs [blink]
+ bl abort
+ ENDFUNC(__gesf2)
+#define __gesf2 __gesf2_asm
+#endif /* DEBUG */
+ .global __gesf2
+ .balign 4
+ HIDDEN_FUNC(__gesf2)
+__gesf2:
+ or.f r12,r0,r1
+ bmi.d .Lneg
+ bmsk_s r12,r12,23
+ add1.f 0,r12,r0 ; check for NaN
+ add1.cc.f r12,r12,r1
+ j_s.d [blink]
+ cmp.cc r0,r1
+ .balign 4
+.Lneg: breq.d r1,0,.L0
+ add1.f 0,r12,r0 ; check for NaN
+ add1.cc.f r12,r12,r1
+ j_s.d [blink]
+ cmp.cc r1,r0
+ .balign 4
+.L0: bxor.f 0,r0,31 ; check for -0
+ j_s.d [blink]
+ cmp.hi r1,r0
+ ENDFUNC(__gesf2)
diff --git a/libgcc/config/arc/ieee-754/gtdf2.S b/libgcc/config/arc/ieee-754/gtdf2.S
new file mode 100644
index 00000000000..b0abb95b84f
--- /dev/null
+++ b/libgcc/config/arc/ieee-754/gtdf2.S
@@ -0,0 +1,86 @@
+/* Copyright (C) 2008-2013 Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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/>. */
+
+#include "arc-ieee-754.h"
+/* inputs: DBL0, DBL1
+ output: c,z flags to be used for 'hi' condition
+ clobber: r12, flags */
+/* For NaNs, bit 19.. bit 30 of the high word must be set. */
+#if 0 /* DEBUG */
+ .global __gtdf2
+ .balign 4
+ FUNC(__gtdf2)
+__gtdf2:
+ st.a r11,[sp,-4]` push_s blink` st.a r10,[sp,-4]` st.a r9,[sp,-4]
+ st.a r8,[sp,-4]` st.a r7,[sp,-4]` st.a r6,[sp,-4]` st.a r5,[sp,-4]
+ st.a r4,[sp,-4]` push_s r3` push_s r2` push_s r1`
+ bl.d __gtdf2_c` push_s r0
+ mov r11,r0` pop_s r0` pop_s r1` pop_s r2` pop_s r3
+ ld.ab r4,[sp,4]` ld.ab r5,[sp,4]` ld.ab r6,[sp,4]`
+ ld.ab r7,[sp,4]` ld.ab r8,[sp,4]` ld.ab r9,[sp,4]
+ bl.d __gtdf2_asm` ld.ab r10,[sp,4]
+ pop_s blink
+ brgt.d r11,0,0f
+ ld.ab r11,[sp,4]
+ jls [blink]
+ bl abort
+0: jhi [blink]
+ bl abort
+ ENDFUNC(__gtdf2)
+#define __gtdf2 __gtdf2_asm
+#endif /* DEBUG */
+ .global __gtdf2
+ .balign 4
+ HIDDEN_FUNC(__gtdf2)
+__gtdf2:
+ or.f r12,DBL0H,DBL1H
+ bmi.d .Lneg
+ bmsk_s r12,r12,20
+ add1.f 0,r12,DBL0H ; clear z; set c iff NaN
+ add1.cc.f r12,r12,DBL1H ; clear z; set c iff NaN
+ ; don't care: z may or may not be cleared if there is no NaN event
+ cmp.cc DBL0H,DBL1H
+ j_s.d [blink]
+ cmp.eq DBL0L,DBL1L
+ .balign 4
+.Lneg: breq.d DBL0H,0,.L0
+ add1.f 0,r12,DBL1H
+ add1.cc.f r12,r12,DBL0H
+ cmp.cc DBL1H,DBL0H
+ j_s.d [blink]
+ cmp.eq DBL1L,DBL0L
+ .balign 4
+.L0:
+ bxor.f 0,DBL1H,31
+ beq_s .Lcheck_0
+ cmp.cc DBL1H,DBL0H
+ j_s.d [blink]
+ cmp.eq DBL1L,DBL0L
+ .balign 4
+.Lcheck_0:
+ ; high words suggest DBL0 may be +0, DBL1 -0; check low words.
+ j_s.d [blink]
+ or.f 0,DBL0L,DBL1L
+ ENDFUNC(__gtdf2)
diff --git a/libgcc/config/arc/ieee-754/gtsf2.S b/libgcc/config/arc/ieee-754/gtsf2.S
new file mode 100644
index 00000000000..b417fec8425
--- /dev/null
+++ b/libgcc/config/arc/ieee-754/gtsf2.S
@@ -0,0 +1,75 @@
+/* Copyright (C) 2008-2013 Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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/>. */
+
+#include "arc-ieee-754.h"
+/* inputs: r0, r1
+ output: c, z flags to be used for 'hi' condition
+ clobber: r12,flags */
+/* For NaNs, bit 22.. bit 30 must be set. */
+#if 0 /* DEBUG */
+ .global __gtsf2
+ .balign 4
+ FUNC(__gtsf2)
+__gtsf2:
+ st.a r11,[sp,-4]` push_s blink` st.a r10,[sp,-4]` st.a r9,[sp,-4]
+ st.a r8,[sp,-4]` st.a r7,[sp,-4]` st.a r6,[sp,-4]` st.a r5,[sp,-4]
+ st.a r4,[sp,-4]` push_s r3` push_s r2` push_s r1`
+ bl.d __gtsf2_c` push_s r0
+ mov r11,r0` pop_s r0` pop_s r1` pop_s r2` pop_s r3
+ ld.ab r4,[sp,4]` ld.ab r5,[sp,4]` ld.ab r6,[sp,4]`
+ ld.ab r7,[sp,4]` ld.ab r8,[sp,4]` ld.ab r9,[sp,4]
+ bl.d __gtsf2_asm` ld.ab r10,[sp,4]
+ pop_s blink
+ brgt.d r11,0,0f
+ ld.ab r11,[sp,4]
+ jls [blink]
+ bl abort
+0: jhi [blink]
+ bl abort
+ ENDFUNC(__gtsf2)
+#define __gtsf2 __gtsf2_asm
+#endif /* DEBUG */
+ .global __gtsf2
+ .balign 4
+ HIDDEN_FUNC(__gtsf2)
+__gtsf2:
+ or.f r12,r0,r1
+ bmi.d .Lneg
+ bmsk_s r12,r12,23
+ add1.f 0,r12,r0 ; check for NaN
+ add1.cc.f r12,r12,r1
+ j_s.d [blink]
+ cmp.cc r0,r1
+ .balign 4
+.Lneg: breq.d r0,0,.L0
+ add1.f 0,r12,r0 ; check for NaN
+ add1.cc.f r12,r12,r1
+ j_s.d [blink]
+ cmp.cc r1,r0
+ .balign 4
+.L0: bxor.f 0,r1,31 ; check for -0
+ j_s.d [blink]
+ cmp.hi r1,r0
+ ENDFUNC(__gtsf2)
diff --git a/libgcc/config/arc/ieee-754/muldf3.S b/libgcc/config/arc/ieee-754/muldf3.S
new file mode 100644
index 00000000000..59c2b07212b
--- /dev/null
+++ b/libgcc/config/arc/ieee-754/muldf3.S
@@ -0,0 +1,235 @@
+/* Copyright (C) 2008-2013 Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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/>. */
+
+/* XMAC schedule: directly back-to-back multiplies stall; the third
+ instruction after a multiply stalls unless it is also a multiply. */
+#include "arc-ieee-754.h"
+
+#if 0 /* DEBUG */
+ .global __muldf3
+ .balign 4
+__muldf3:
+ push_s blink
+ push_s r2
+ push_s r3
+ push_s r0
+ bl.d __muldf3_c
+ push_s r1
+ ld_s r2,[sp,12]
+ ld_s r3,[sp,8]
+ st_s r0,[sp,12]
+ st_s r1,[sp,8]
+ pop_s r1
+ bl.d __muldf3_asm
+ pop_s r0
+ pop_s r3
+ pop_s r2
+ pop_s blink
+ cmp r0,r2
+ cmp.eq r1,r3
+ jeq_s [blink]
+ b abort
+#define __muldf3 __muldf3_asm
+#endif /* DEBUG */
+/* N.B. This is optimized for ARC700.
+ ARC600 has very different scheduling / instruction selection criteria. */
+/* For the standard multiplier, instead of mpyu rx,DBL0L,DBL1L; tst rx,rx ,
+ we can do:
+ sub rx,DBL0L,1; bic rx,DBL0L,rx; lsr rx,rx; norm rx,rx; asl.f 0,DBL1L,rx */
+
+__muldf3_support: /* This label makes debugger output saner. */
+/* If one number is denormal, subtract some from the exponent of the other
+ one (if the other exponent is too small, return 0), and normalize the
+ denormal. Then re-run the computation. */
+ .balign 4
+ FUNC(__muldf3)
+.Ldenorm_dbl0:
+ mov_s r12,DBL0L
+ mov_s DBL0L,DBL1L
+ mov_s DBL1L,r12
+ mov_s r12,DBL0H
+ mov_s DBL0H,DBL1H
+ mov_s DBL1H,r12
+ and r11,DBL0H,r9
+.Ldenorm_dbl1:
+ brhs r11,r9,.Linf_nan
+ brhs 0x3ca00001,r11,.Lret0
+ sub_s DBL0H,DBL0H,DBL1H
+ bmsk_s DBL1H,DBL1H,30
+ add_s DBL0H,DBL0H,DBL1H
+ breq_s DBL1H,0,.Ldenorm_2
+ norm r12,DBL1H
+
+ sub_s r12,r12,10
+ asl r5,r12,20
+ asl_s DBL1H,DBL1H,r12
+ sub DBL0H,DBL0H,r5
+ neg r5,r12
+ lsr r6,DBL1L,r5
+ asl_s DBL1L,DBL1L,r12
+ b.d __muldf3
+ add_s DBL1H,DBL1H,r6
+
+ .balign 4
+.Linf_nan:
+ bclr r12,DBL1H,31
+ xor_s DBL1H,DBL1H,DBL0H
+ bclr_s DBL0H,DBL0H,31
+ max r8,DBL0H,r12 ; either NaN -> NaN ; otherwise inf
+ or.f 0,DBL0H,DBL0L
+ mov_s DBL0L,0
+ or.ne.f DBL1L,DBL1L,r12
+ not_s DBL0H,DBL0L ; inf * 0 -> NaN
+ mov.ne DBL0H,r8
+ tst_s DBL1H,DBL1H
+ j_s.d [blink]
+ bset.mi DBL0H,DBL0H,31
+
+.Lret0: xor_s DBL0H,DBL0H,DBL1H
+ bclr DBL1H,DBL0H,31
+ xor_s DBL0H,DBL0H,DBL1H
+ j_s.d [blink]
+ mov_l DBL0L,0
+
+ .balign 4
+.Ldenorm_2:
+ breq_s DBL1L,0,.Lret0 ; 0 input -> 0 output
+ norm.f r12,DBL1L
+
+ mov.mi r12,21
+ add.pl r12,r12,22
+ neg r11,r12
+ asl_s r12,r12,20
+ lsr.f DBL1H,DBL1L,r11
+ ror DBL1L,DBL1L,r11
+ sub_s DBL0H,DBL0H,r12
+ mov.eq DBL1H,DBL1L
+ sub_s DBL1L,DBL1L,DBL1H
+ /* Fall through. */
+ .global __muldf3
+ .balign 4
+__muldf3:
+ ld.as r9,[pcl,0x4b] ; ((.L7ff00000-.+2)/4)]
+ mpyhu r4,DBL0L,DBL1L
+ bmsk r6,DBL0H,19
+ bset r6,r6,20
+ mpyu r7,r6,DBL1L
+ and r11,DBL0H,r9
+ breq r11,0,.Ldenorm_dbl0
+ mpyhu r8,r6,DBL1L
+ bmsk r10,DBL1H,19
+ bset r10,r10,20
+ mpyhu r5,r10,DBL0L
+ add.f r4,r4,r7
+ and r12,DBL1H,r9
+ mpyhu r7,r6,r10
+ breq r12,0,.Ldenorm_dbl1
+ adc.f r5,r5,r8
+ mpyu r8,r10,DBL0L
+ breq r11,r9,.Linf_nan
+ breq r12,r9,.Linf_nan
+ mpyu r6,r6,r10
+ add.cs r7,r7,1
+ add.f r4,r4,r8
+ mpyu r10,DBL1L,DBL0L
+ bclr r8,r9,30 ; 0x3ff00000
+ adc.f r5,r5,r6
+ ; XMAC write-back stall / std. mult stall is one cycle later
+ bclr r6,r9,20 ; 0x7fe00000
+ add.cs r7,r7,1 ; fraction product in r7:r5:r4
+ tst r10,r10
+ bset.ne r4,r4,0 ; put least significant word into sticky bit
+ lsr.f r10,r7,9
+ add_l r12,r12,r11 ; add exponents
+ rsub.eq r8,r8,r9 ; 0x40000000
+ sub r12,r12,r8 ; subtract bias + implicit 1
+ brhs.d r12,r6,.Linf_denorm
+ rsub r10,r10,12
+.Lshift_frac:
+ neg r8,r10
+ asl r6,r4,r10
+ lsr DBL0L,r4,r8
+ add.f 0,r6,r6
+ btst.eq DBL0L,0
+ cmp.eq r4,r4 ; round to nearest / round to even
+ asl r4,r5,r10
+ lsr r5,r5,r8
+ adc.f DBL0L,DBL0L,r4
+ xor.f 0,DBL0H,DBL1H
+ asl r7,r7,r10
+ add_s r12,r12,r5
+ adc DBL0H,r12,r7
+ j_s.d [blink]
+ bset.mi DBL0H,DBL0H,31
+
+/* We have checked for infinity / NaN input before, and transformed
+ denormalized inputs into normalized inputs. Thus, the worst case
+ exponent overflows are:
+ 1 + 1 - 0x400 == 0xc02 : maximum underflow
+ 0x7fe + 0x7fe - 0x3ff == 0xbfd ; maximum overflow
+ N.B. 0x7e and 0x7f are also values for overflow.
+
+ If (r12 <= -54), we have an underflow to zero. */
+ .balign 4
+.Linf_denorm:
+ brlo r12,0xc0000000,.Linf
+ asr r6,r12,20
+ mov_s r12,0
+ add.f r10,r10,r6
+ brgt r10,0,.Lshift_frac
+ beq_s .Lround_frac
+ add.f r10,r10,32
+.Lshift32_frac:
+ tst r4,r4
+ mov r4,r5
+ bset.ne r4,r4,1
+ mov r5,r7
+ mov r7,0
+ brge r10,1,.Lshift_frac
+ breq r10,0,.Lround_frac
+ add.f r10,r10,32
+ brgt r10,21,.Lshift32_frac
+ b_s .Lret0
+
+.Lround_frac:
+ add.f 0,r4,r4
+ btst.eq r5,0
+ mov_s DBL0L,r5
+ mov_s DBL0H,r7
+ adc.eq.f DBL0L,DBL0L,0
+ j_s.d [blink]
+
+ adc.eq DBL0H,DBL0H,0
+
+.Linf: xor.f DBL1H,DBL1H,DBL0H
+ mov_s DBL0L,0
+ mov_s DBL0H,r9
+ j_s.d [blink]
+ bset.mi DBL0H,DBL0H,31
+ ENDFUNC(__muldf3)
+
+ .balign 4
+.L7ff00000:
+ .long 0x7ff00000
diff --git a/libgcc/config/arc/ieee-754/mulsf3.S b/libgcc/config/arc/ieee-754/mulsf3.S
new file mode 100644
index 00000000000..c931c3c947e
--- /dev/null
+++ b/libgcc/config/arc/ieee-754/mulsf3.S
@@ -0,0 +1,180 @@
+/* Copyright (C) 2008-2013 Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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/>. */
+
+/* XMAC schedule: directly back-to-back multiplies stall; the third
+ instruction after a multiply stalls unless it is also a multiply. */
+#include "arc-ieee-754.h"
+
+#if 0 /* DEBUG */
+ .global __mulsf3
+ FUNC(__mulsf3)
+ .balign 4
+__mulsf3:
+ push_s blink
+ push_s r1
+ bl.d __mulsf3_c
+ push_s r0
+ ld_s r1,[sp,4]
+ st_s r0,[sp,4]
+ bl.d __mulsf3_asm
+ pop_s r0
+ pop_s r1
+ pop_s blink
+ cmp r0,r1
+ jeq_s [blink]
+ and r12,r0,r1
+ bic.f 0,0x7f800000,r12
+ bne 0f
+ bmsk.f 0,r0,22
+ bmsk.ne.f r1,r1,22
+ jne_s [blink] ; both NaN -> OK
+0: bl abort
+ ENDFUNC(__mulsf3)
+#define __mulsf3 __mulsf3_asm
+#endif /* DEBUG */
+
+ .balign 4
+ .global __mulsf3
+ FUNC(__mulsf3)
+__mulsf3:
+ ld.as r9,[pcl,79]; [pcl,((.L7f800000-.+2)/4)]
+ bmsk r4,r1,22
+ bset r2,r0,23
+ asl_s r2,r2,8
+ bset r3,r4,23
+ mpyhu r6,r2,r3
+ and r11,r0,r9
+ breq r11,0,.Ldenorm_dbl0
+ mpyu r7,r2,r3
+ breq r11,r9,.Linf_nan_dbl0
+ and r12,r1,r9
+ asl.f 0,r6,8
+ breq r12,0,.Ldenorm_dbl1
+.Lpast_denorm:
+ xor_s r0,r0,r1
+.Lpast_denorm_dbl1:
+ add.pl r6,r6,r6
+ bclr.pl r6,r6,23
+ add.pl.f r7,r7,r7
+ ld.as r4,[pcl,64]; [pcl,((.L7fffffff-.+2)/4)]
+ add.cs r6,r6,1
+ lsr.f 0,r6,1
+ breq r12,r9,.Linf_nan_dbl1
+ add_s r12,r12,r11
+ adc.f 0,r7,r4
+ add_s r12,r12, \
+ -0x3f800000
+ adc.f r8,r6,r12
+ bic r0,r0,r4
+ tst.pl r8,r9
+ min r3,r8,r9
+ jpnz.d [blink]
+ add.pnz r0,r0,r3
+; infinity or denormal number
+ add.ne.f r3,r3,r3
+ bpnz .Linfinity
+ asr_s r3,r3,23+1
+ bset r6,r6,23
+ sub_s r3,r3,1
+ neg_s r2,r3
+ brhi r2,24,.Lret_r0 ; right shift shift > 24 -> return +-0
+ lsr r2,r6,r2
+ asl r9,r6,r3
+ lsr.f 0,r2,1
+ tst r7,r7
+ add_s r0,r0,r2
+ bset.ne r9,r9,0
+ adc.f 0,r9,r4
+ j_s.d [blink]
+ add.cs r0,r0,1
+.Linfinity:
+ j_s.d [blink]
+ add_s r0,r0,r9
+
+.Lret_r0: j_s [blink]
+
+ .balign 4
+.Linf_nan_dbl0:
+ sub_s r2,r1,1 ; inf/nan * 0 -> nan; inf * nan -> nan (use |r2| >= inf)
+ bic.f 0,r9,r2
+ xor_s r0,r0,r1
+ bclr_s r1,r1,31
+ xor_s r0,r0,r1
+ jne_s [blink]
+.Lretnan:
+ j_s.d [blink]
+ mov r0,-1
+.Ldenorm_dbl0_inf_nan_dbl1:
+ bmsk.f 0,r0,30
+ beq_s .Lretnan
+ xor_s r0,r0,r1
+.Linf_nan_dbl1:
+ xor_s r1,r1,r0
+ bclr_s r1,r1,31
+ j_s.d [blink]
+ xor_s r0,r0,r1
+
+ .balign 4
+.Ldenorm_dbl0:
+ bclr_s r2,r2,31
+ norm.f r4,r2
+ and r12,r1,r9
+ add_s r2,r2,r2
+ asl r2,r2,r4
+ asl r4,r4,23
+ mpyhu r6,r2,r3
+ breq r12,r9,.Ldenorm_dbl0_inf_nan_dbl1
+ sub.ne.f r12,r12,r4
+ mpyu r7,r2,r3
+ bhi.d .Lpast_denorm
+ asl.f 0,r6,8
+ xor_s r0,r0,r1
+ bmsk r1,r0,30
+ j_s.d [blink]
+ bic_l r0,r0,r1
+
+ .balign 4
+.Ldenorm_dbl1:
+ norm.f r3,r4
+ xor_s r0,r0,r1
+ sub_s r3,r3,7
+ asl r4,r4,r3
+ sub_s r3,r3,1
+ asl_s r3,r3,23
+ mpyhu r6,r2,r4
+ sub.ne.f r11,r11,r3
+ bmsk r8,r0,30
+ mpyu r7,r2,r4
+ bhi.d .Lpast_denorm_dbl1
+ asl.f 0,r6,8
+ j_s.d [blink]
+ bic r0,r0,r8
+
+ .balign 4
+.L7f800000:
+ .long 0x7f800000
+.L7fffffff:
+ .long 0x7fffffff
+ ENDFUNC(__mulsf3)
diff --git a/libgcc/config/arc/ieee-754/orddf2.S b/libgcc/config/arc/ieee-754/orddf2.S
new file mode 100644
index 00000000000..ac2793f6234
--- /dev/null
+++ b/libgcc/config/arc/ieee-754/orddf2.S
@@ -0,0 +1,63 @@
+/* Copyright (C) 2008-2013 Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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/>. */
+
+#include "arc-ieee-754.h"
+/* inputs: r0, r1
+ output: c flag
+ clobber: r12, flags
+ For NaNs, bit 19 .. bit 30 must be set. */
+#if 0 /* DEBUG */
+ .global __orddf2
+ .balign 4
+ FUNC(__orddf2)
+__orddf2:
+ st.a r11,[sp,-4]` push_s blink` st.a r10,[sp,-4]` st.a r9,[sp,-4]
+ st.a r8,[sp,-4]` st.a r7,[sp,-4]` st.a r6,[sp,-4]` st.a r5,[sp,-4]
+ st.a r4,[sp,-4]` push_s r3` push_s r2` push_s r1`
+ bl.d __unorddf2_c` push_s r0
+ mov r11,r0` pop_s r0` pop_s r1` pop_s r2` pop_s r3
+ ld.ab r4,[sp,4]` ld.ab r5,[sp,4]` ld.ab r6,[sp,4]`
+ ld.ab r7,[sp,4]` ld.ab r8,[sp,4]` ld.ab r9,[sp,4]
+ bl.d __orddf2_asm` ld.ab r10,[sp,4]
+ pop_s blink
+ brne.d r11,0,0f
+ ld.ab r11,[sp,4]
+ jcc [blink]
+ bl abort
+0: jcs [blink]
+ bl abort
+ ENDFUNC(__orddf2)
+#define __orddf2 __orddf2_asm
+#endif /* DEBUG */
+ .global __orddf2
+ .balign 4
+ HIDDEN_FUNC(__orddf2)
+__orddf2:
+ bmsk r12,DBL0H,20
+ add1.f r12,r12,DBL0H /* clear z; set c if NaN. */
+ bmsk r12,DBL1H,20
+ j_s.d [blink]
+ add1.cc.f r12,r12,DBL1H /* clear z; set c if NaN. */
+ ENDFUNC(__orddf2)
diff --git a/libgcc/config/arc/ieee-754/ordsf2.S b/libgcc/config/arc/ieee-754/ordsf2.S
new file mode 100644
index 00000000000..8f1495156b6
--- /dev/null
+++ b/libgcc/config/arc/ieee-754/ordsf2.S
@@ -0,0 +1,63 @@
+/* Copyright (C) 2008-2013 Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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/>. */
+
+#include "arc-ieee-754.h"
+/* inputs: r0, r1
+ output: c flag
+ clobber: r12, flags
+ For NaNs, bit 22 .. bit 30 must be set. */
+#if 0 /* DEBUG */
+ .global __ordsf2
+ .balign 4
+ FUNC(__ordsf2)
+__ordsf2:
+ st.a r11,[sp,-4]` push_s blink` st.a r10,[sp,-4]` st.a r9,[sp,-4]
+ st.a r8,[sp,-4]` st.a r7,[sp,-4]` st.a r6,[sp,-4]` st.a r5,[sp,-4]
+ st.a r4,[sp,-4]` push_s r3` push_s r2` push_s r1`
+ bl.d __unordsf2_c` push_s r0
+ mov r11,r0` pop_s r0` pop_s r1` pop_s r2` pop_s r3
+ ld.ab r4,[sp,4]` ld.ab r5,[sp,4]` ld.ab r6,[sp,4]`
+ ld.ab r7,[sp,4]` ld.ab r8,[sp,4]` ld.ab r9,[sp,4]
+ bl.d __ordsf2_asm` ld.ab r10,[sp,4]
+ pop_s blink
+ brne.d r11,0,0f
+ ld.ab r11,[sp,4]
+ jcc [blink]
+ bl abort
+0: jcs [blink]
+ bl abort
+ ENDFUNC(__ordsf2)
+#define __ordsf2 __ordsf2_asm
+#endif /* DEBUG */
+ .global __ordsf2
+ .balign 4
+ HIDDEN_FUNC(__ordsf2)
+__ordsf2:
+ bmsk r12,r0,23
+ add1.f r12,r12,r0 /* clear z; set c if NaN. */
+ bmsk r12,r1,23
+ j_s.d [blink]
+ add1.cc.f r12,r12,r1 /* clear z; set c if NaN. */
+ ENDFUNC(__ordsf2)
diff --git a/libgcc/config/arc/ieee-754/truncdfsf2.S b/libgcc/config/arc/ieee-754/truncdfsf2.S
new file mode 100644
index 00000000000..aafdf09445a
--- /dev/null
+++ b/libgcc/config/arc/ieee-754/truncdfsf2.S
@@ -0,0 +1,134 @@
+/* Copyright (C) 2006, 2008-2013 Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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/>. */
+
+#include "arc-ieee-754.h"
+
+#if 0 /* DEBUG */
+ FUNC(__truncdfsf2)
+ .global __truncdfsf2
+ .balign 4
+__truncdfsf2:
+ push_s blink
+ push_s r0
+ bl.d __truncdfsf2_c
+ push_s r1
+ mov_s r2,r0
+ pop_s r1
+ ld r0,[sp]
+ bl.d __truncdfsf2_asm
+ st r2,[sp]
+ pop_s r1
+ pop_s blink
+ cmp r0,r1
+ jeq_s [blink]
+ and r12,r0,r1
+ bic.f 0,0x7f800000,r12
+ bne 0f
+ bmsk.f 0,r0,22
+ bmsk.ne.f r1,r1,22
+ jne_s [blink] ; both NaN -> OK
+0: bl abort
+ ENDFUNC(__truncdfsf2)
+#define __truncdfsf2 __truncdfsf2_asm
+#endif /* DEBUG */
+
+ .global __truncdfsf2
+ .balign 4
+ FUNC(__truncdfsf2)
+__truncdfsf2:
+ lsr r2,DBL0H,20
+ asl_s DBL0H,DBL0H,12
+ sub r12,r2,0x380
+ bclr.f r3,r12,11
+ brhs r3,0xff,.Lill_exp
+ beq_l .Ldenorm0
+ asl_s r12,r12,23
+ tst DBL0L, \
+ 0x2fffffff /* Check if msb guard bit wants rounding up. */
+ lsr_s DBL0L,DBL0L,28
+ lsr_s DBL0H,DBL0H,8
+ add.ne DBL0L,DBL0L,1
+ add_s DBL0H,DBL0H,DBL0L
+ lsr_s DBL0H,DBL0H
+ btst_s r2,11
+ add_s r0,DBL0H,r12
+ j_s.d [blink]
+ bxor.ne r0,r0,31
+ .balign 4
+.Lill_exp:
+ bbit1 r2,10,.Linf_nan
+ bmsk_s r12,r12,9
+ rsub.f r12,r12,8+0x400-32 ; Go from 9 to 1 guard bit in MSW. */
+ bhs_s .Lzero
+ lsr r3,DBL0L,21
+ rrc DBL0H,DBL0H ; insert leading 1
+ asl.f 0,DBL0L,8 ; check lower 24 guard bits
+ add_s r3,DBL0H,r3
+ add.pnz r3,r3,1 ; assemble fraction with compressed guard bits.
+ lsr r0,r3,r12
+ neg_s r12,r12
+ btst_s r0,1
+ asl.eq.f r3,r3,r12
+ add.ne r0,r0,1
+ btst_s r2,11
+ lsr_s r0,r0
+ j_s.d [blink]
+ bxor.ne r0,r0,31
+.Lzero:
+ lsr_s r2,r2,11
+ j_s.d [blink]
+ asl r0,r2,31
+.Ldenorm0:
+ asl_s r12,r12,20
+ tst DBL0L, \
+ 0x5fffffff /* Check if msb guard bit wants rounding up. */
+ lsr_s DBL0L,DBL0L,29
+ lsr_s DBL0H,DBL0H,9
+ add.ne DBL0L,DBL0L,1
+ bset_s DBL0H,DBL0H,23
+ add_s DBL0H,DBL0H,DBL0L
+ lsr_s DBL0H,DBL0H
+ j_s.d [blink]
+ add_l r0,DBL0H,r12
+
+/* We would generally say that NaNs must have a non-zero high fraction part,
+ but to allow hardware double precision floating point to interoperate
+ with single precision software floating point, we make an exception here.
+ The cost is to replace a tst_s DBL0H with an or.f DBL0L,DBL0L,DBL0H .
+ As we start out unaligned, and there is an odd number of other short insns,
+ we have a choice of letting this cost us a misalign penalty or
+ 4 more bytes (if we align the code). We choose the former here because
+ infinity / NaN is not expected to be prevalent in time-critical code. */
+.Linf_nan:
+ or.f DBL0L,DBL0L,DBL0H
+ mov_s r0,1
+ add.ne r2,r2,1
+ tst r2,0x7ff
+ asl.ne r0,r0,23
+ btst_s r12,11
+ neg r0,r0
+ j_s.d [blink]
+ bxor.eq r0,r0,31
+ ENDFUNC(__truncdfsf2)
diff --git a/libgcc/config/arc/ieee-754/uneqdf2.S b/libgcc/config/arc/ieee-754/uneqdf2.S
new file mode 100644
index 00000000000..b3d16d0c0a1
--- /dev/null
+++ b/libgcc/config/arc/ieee-754/uneqdf2.S
@@ -0,0 +1,73 @@
+/* Copyright (C) 2008-2013 Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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/>. */
+
+#include "arc-ieee-754.h"
+/* inputs: DBL0, DBL1
+ output: z flag
+ clobber: r12, flags
+ For NaNs, bit 19.. bit 30 of the high word must be set. */
+#if 0 /* DEBUG */
+ .global __uneqdf2
+ .balign 4
+ FUNC(__uneqdf2)
+__uneqdf2:
+ st.a r11,[sp,-4]` push_s blink` st.a r10,[sp,-4]` st.a r9,[sp,-4]
+ st.a r8,[sp,-4]` st.a r7,[sp,-4]` st.a r6,[sp,-4]` st.a r5,[sp,-4]
+ st.a r4,[sp,-4]` push_s r3` push_s r2` push_s r1`
+ bl.d __eqdf2_c` push_s r0
+ push_s r0` ld_s r0, [sp,4]` ld_s r1, [sp,8]` ld_s r2,[sp,12]
+ bl.d __unorddf2_c` ld_s r3,[sp,16]
+ ld.ab r11,[sp,4]` tst r0,r0` mov.ne r11,0
+ pop_s r0` pop_s r1` pop_s r2` pop_s r3
+ ld.ab r4,[sp,4]` ld.ab r5,[sp,4]` ld.ab r6,[sp,4]`
+ ld.ab r7,[sp,4]` ld.ab r8,[sp,4]` ld.ab r9,[sp,4]
+ bl.d __uneqdf2_asm` ld.ab r10,[sp,4]
+ pop_s blink
+ breq.d r11,0,0f
+ ld.ab r11,[sp,4]
+ jne_s [blink]
+ bl abort
+0: jeq_s [blink]
+ bl abort
+ ENDFUNC(__uneqdf2)
+#define __uneqdf2 __uneqdf2_asm
+#endif /* DEBUG */
+ .global __uneqdf2
+ .balign 4
+ HIDDEN_FUNC(__uneqdf2)
+__uneqdf2:
+ cmp_s DBL0H,DBL1H
+ cmp.eq DBL0L,DBL1L
+ jeq_s [blink]
+ or r12,DBL0H,DBL1H
+ or.f 0,DBL0L,DBL1L
+ bclr.eq.f r12,r12,31
+ jeq_s [blink]
+ mov_s r12, \
+ 0x7ff80000
+ bic.f 0,r12,DBL0H
+ j_s.d [blink]
+ bic.ne.f r12,r12,DBL1H
+ ENDFUNC(__uneqdf2)
diff --git a/libgcc/config/arc/ieee-754/uneqsf2.S b/libgcc/config/arc/ieee-754/uneqsf2.S
new file mode 100644
index 00000000000..152c112dc4e
--- /dev/null
+++ b/libgcc/config/arc/ieee-754/uneqsf2.S
@@ -0,0 +1,69 @@
+/* Copyright (C) 2008-2013 Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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/>. */
+
+#include "arc-ieee-754.h"
+/* inputs: r0, r1
+ output: z flag
+ clobber: r12, flags
+ For NaNs, bit 22 .. bit 30 must be set. */
+#if 0 /* DEBUG */
+ .global __uneqsf2
+ .balign 4
+ FUNC(__uneqsf2)
+__uneqsf2:
+ st.a r11,[sp,-4]` push_s blink` st.a r10,[sp,-4]` st.a r9,[sp,-4]
+ st.a r8,[sp,-4]` st.a r7,[sp,-4]` st.a r6,[sp,-4]` st.a r5,[sp,-4]
+ st.a r4,[sp,-4]` push_s r3` push_s r2` push_s r1`
+ bl.d __eqsf2_c` push_s r0
+ push_s r0` ld_s r0, [sp,4]
+ bl.d __unordsf2_c` ld_s r1,[sp,8]
+ ld.ab r11,[sp,4]` tst r0,r0` mov.ne r11,0
+ pop_s r0` pop_s r1` pop_s r2` pop_s r3
+ ld.ab r4,[sp,4]` ld.ab r5,[sp,4]` ld.ab r6,[sp,4]`
+ ld.ab r7,[sp,4]` ld.ab r8,[sp,4]` ld.ab r9,[sp,4]
+ bl.d __uneqsf2_asm` ld.ab r10,[sp,4]
+ pop_s blink
+ breq.d r11,0,0f
+ ld.ab r11,[sp,4]
+ jne_s [blink]
+ bl abort
+0: jeq_s [blink]
+ bl abort
+ ENDFUNC(__uneqsf2)
+#define __uneqsf2 __uneqsf2_asm
+#endif /* DEBUG */
+ .global __uneqsf2
+ .balign 4
+ HIDDEN_FUNC(__uneqsf2)
+__uneqsf2:
+ mov_s r12, \
+ 0x7fc00000
+ bic.f 0,r12,r0
+ bic.ne.f r12,r12,r1
+ or r12,r0,r1
+ bmsk.ne.f r12,r12,30
+ j_s.d [blink]
+ cmp.ne r0,r1
+ ENDFUNC(__uneqsf2)
diff --git a/libgcc/config/arc/initfini.c b/libgcc/config/arc/initfini.c
new file mode 100644
index 00000000000..46bd8b0f9f4
--- /dev/null
+++ b/libgcc/config/arc/initfini.c
@@ -0,0 +1,157 @@
+/* .init/.fini section handling + C++ global constructor/destructor handling.
+ This file is based on crtstuff.c, sol2-crti.asm, sol2-crtn.asm.
+
+ Copyright (C) 1995, 1997, 1998, 2007-2013 Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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/>. */
+
+/* Declare a pointer to void function type. */
+typedef void (*func_ptr) (void);
+
+#ifdef CRT_INIT
+
+/* NOTE: In order to be able to support SVR4 shared libraries, we arrange
+ to have one set of symbols { __CTOR_LIST__, __DTOR_LIST__, __CTOR_END__,
+ __DTOR_END__ } per root executable and also one set of these symbols
+ per shared library. So in any given whole process image, we may have
+ multiple definitions of each of these symbols. In order to prevent
+ these definitions from conflicting with one another, and in order to
+ ensure that the proper lists are used for the initialization/finalization
+ of each individual shared library (respectively), we give these symbols
+ only internal (i.e. `static') linkage, and we also make it a point to
+ refer to only the __CTOR_END__ symbol in crtfini.o and the __DTOR_LIST__
+ symbol in crtinit.o, where they are defined. */
+
+static func_ptr __CTOR_LIST__[1] __attribute__ ((section (".ctors")))
+ = { (func_ptr) (-1) };
+
+static func_ptr __DTOR_LIST__[1] __attribute__ ((section (".dtors")))
+ = { (func_ptr) (-1) };
+
+/* Run all the global destructors on exit from the program. */
+
+/* Some systems place the number of pointers in the first word of the
+ table. On SVR4 however, that word is -1. In all cases, the table is
+ null-terminated. On SVR4, we start from the beginning of the list and
+ invoke each per-compilation-unit destructor routine in order
+ until we find that null.
+
+ Note that this function MUST be static. There will be one of these
+ functions in each root executable and one in each shared library, but
+ although they all have the same code, each one is unique in that it
+ refers to one particular associated `__DTOR_LIST__' which belongs to the
+ same particular root executable or shared library file. */
+
+static void __do_global_dtors (void)
+asm ("__do_global_dtors") __attribute__ ((section (".text")));
+
+static void
+__do_global_dtors (void)
+{
+ func_ptr *p;
+ for (p = __DTOR_LIST__ + 1; *p; p++)
+ (*p) ();
+}
+
+/* .init section start.
+ This must appear at the start of the .init section. */
+
+asm ("\n\
+ .section .init\n\
+ .global init\n\
+ .word 0\n\
+init:\n\
+ st blink,[sp,4]\n\
+ st fp,[sp]\n\
+ mov fp,sp\n\
+ sub sp,sp,16\n\
+");
+
+/* .fini section start.
+ This must appear at the start of the .init section. */
+
+asm ("\n\
+ .section .fini\n\
+ .global fini\n\
+ .word 0\n\
+fini:\n\
+ st blink,[sp,4]\n\
+ st fp,[sp]\n\
+ mov fp,sp\n\
+ sub sp,sp,16\n\
+ bl.nd __do_global_dtors\n\
+");
+
+#endif /* CRT_INIT */
+
+#ifdef CRT_FINI
+
+/* Put a word containing zero at the end of each of our two lists of function
+ addresses. Note that the words defined here go into the .ctors and .dtors
+ sections of the crtend.o file, and since that file is always linked in
+ last, these words naturally end up at the very ends of the two lists
+ contained in these two sections. */
+
+static func_ptr __CTOR_END__[1] __attribute__ ((section (".ctors")))
+ = { (func_ptr) 0 };
+
+static func_ptr __DTOR_END__[1] __attribute__ ((section (".dtors")))
+ = { (func_ptr) 0 };
+
+/* Run all global constructors for the program.
+ Note that they are run in reverse order. */
+
+static void __do_global_ctors (void)
+asm ("__do_global_ctors") __attribute__ ((section (".text")));
+
+static void
+__do_global_ctors (void)
+{
+ func_ptr *p;
+ for (p = __CTOR_END__ - 1; *p != (func_ptr) -1; p--)
+ (*p) ();
+}
+
+/* .init section end.
+ This must live at the end of the .init section. */
+
+asm ("\n\
+ .section .init\n\
+ bl.nd __do_global_ctors\n\
+ ld blink,[fp,4]\n\
+ j.d blink\n\
+ ld.a fp,[sp,16]\n\
+");
+
+/* .fini section end.
+ This must live at the end of the .fini section. */
+
+asm ("\n\
+ .section .fini\n\
+ ld blink,[fp,4]\n\
+ j.d blink\n\
+ ld.a fp,[sp,16]\n\
+");
+
+#endif /* CRT_FINI */
diff --git a/libgcc/config/arc/lib1funcs.S b/libgcc/config/arc/lib1funcs.S
new file mode 100644
index 00000000000..d434ccb4edd
--- /dev/null
+++ b/libgcc/config/arc/lib1funcs.S
@@ -0,0 +1,1418 @@
+; libgcc1 routines for Synopsys DesignWare ARC cpu.
+
+/* Copyright (C) 1995, 1997, 2007-2013 Free Software Foundation, Inc.
+ Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+ on behalf of Synopsys 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/>. */
+
+/* As a special exception, if you link this library with other files,
+ some of which are compiled with GCC, to produce an executable,
+ this library does not by itself cause the resulting executable
+ to be covered by the GNU General Public License.
+ This exception does not however invalidate any other reasons why
+ the executable file might be covered by the GNU General Public License. */
+
+
+ /* ANSI concatenation macros. */
+
+ #define CONCAT1(a, b) CONCAT2(a, b)
+ #define CONCAT2(a, b) a ## b
+
+ /* Use the right prefix for global labels. */
+
+ #define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
+
+#ifndef WORKING_ASSEMBLER
+#define abs_l abs
+#define asl_l asl
+#define mov_l mov
+#endif
+
+#define FUNC(X) .type SYM(X),@function
+#define HIDDEN_FUNC(X) FUNC(X)` .hidden X
+#define ENDFUNC0(X) .Lfe_##X: .size X,.Lfe_##X-X
+#define ENDFUNC(X) ENDFUNC0(X)
+
+
+
+#ifdef L_mulsi3
+ .section .text
+ .align 4
+
+ .global SYM(__mulsi3)
+SYM(__mulsi3):
+
+/* This the simple version.
+
+ while (a)
+ {
+ if (a & 1)
+ r += b;
+ a >>= 1;
+ b <<= 1;
+ }
+*/
+
+#if defined (__ARC_MUL64__)
+ FUNC(__mulsi3)
+ mulu64 r0,r1
+ j_s.d [blink]
+ mov_s r0,mlo
+ ENDFUNC(__mulsi3)
+#elif defined (__ARC700__)
+ HIDDEN_FUNC(__mulsi3)
+ mpyu r0,r0,r1
+ nop_s
+ j_s [blink]
+ ENDFUNC(__mulsi3)
+#elif defined (__ARC_NORM__)
+ FUNC(__mulsi3)
+ norm.f r2,r0
+ rsub lp_count,r2,31
+ mov.mi lp_count,32
+ mov_s r2,r0
+ mov_s r0,0
+ lpnz @.Lend ; loop is aligned
+ lsr.f r2,r2
+ add.cs r0,r0,r1
+ add_s r1,r1,r1
+.Lend: j_s [blink]
+ ENDFUNC(__mulsi3)
+#elif !defined (__OPTIMIZE_SIZE__) && !defined(__ARC601__)
+ /* Up to 3.5 times faster than the simpler code below, but larger. */
+ FUNC(__mulsi3)
+ ror.f r2,r0,4
+ mov_s r0,0
+ add3.mi r0,r0,r1
+ asl.f r2,r2,2
+ add2.cs r0,r0,r1
+ jeq_s [blink]
+.Loop:
+ add1.mi r0,r0,r1
+ asl.f r2,r2,2
+ add.cs r0,r0,r1
+ asl_s r1,r1,4
+ ror.f r2,r2,8
+ add3.mi r0,r0,r1
+ asl.f r2,r2,2
+ bne.d .Loop
+ add2.cs r0,r0,r1
+ j_s [blink]
+ ENDFUNC(__mulsi3)
+#elif !defined (__OPTIMIZE_SIZE__) /* __ARC601__ */
+ FUNC(__mulsi3)
+ lsr.f r2,r0
+ mov_s r0,0
+ mov_s r3,0
+ add.cs r0,r0,r1
+.Loop:
+ lsr.f r2,r2
+ add1.cs r0,r0,r1
+ lsr.f r2,r2
+ add2.cs r0,r0,r1
+ lsr.f r2,r2
+ add3.cs r0,r0,r1
+ bne.d .Loop
+ add3 r1,r3,r1
+ j_s [blink]
+ ENDFUNC(__mulsi3)
+#else
+/********************************************************/
+ FUNC(__mulsi3)
+ mov_s r2,0 ; Accumulate result here.
+.Lloop:
+ bbit0 r0,0,@.Ly
+ add_s r2,r2,r1 ; r += b
+.Ly:
+ lsr_s r0,r0 ; a >>= 1
+ asl_s r1,r1 ; b <<= 1
+ brne_s r0,0,@.Lloop
+.Ldone:
+ j_s.d [blink]
+ mov_s r0,r2
+ ENDFUNC(__mulsi3)
+/********************************************************/
+#endif
+
+#endif /* L_mulsi3 */
+
+#ifdef L_umulsidi3
+ .section .text
+ .align 4
+
+ .global SYM(__umulsidi3)
+SYM(__umulsidi3):
+ HIDDEN_FUNC(__umulsidi3)
+/* We need ARC700 /ARC_MUL64 definitions of __umulsidi3 / __umulsi3_highpart
+ in case some code has been compiled without multiply support enabled,
+ but linked with the multiply-support enabled libraries.
+ For ARC601 (i.e. without a barrel shifter), we also use umuldisi3 as our
+ umulsi3_highpart implementation; the use of the latter label doesn't
+ actually benefit ARC601 platforms, but is useful when ARC601 code is linked
+ against other libraries. */
+#if defined (__ARC700__) || defined (__ARC_MUL64__) || defined (__ARC601__)
+ .global SYM(__umulsi3_highpart)
+SYM(__umulsi3_highpart):
+ HIDDEN_FUNC(__umulsi3_highpart)
+#endif
+
+/* This the simple version.
+
+ while (a)
+ {
+ if (a & 1)
+ r += b;
+ a >>= 1;
+ b <<= 1;
+ }
+*/
+#include "ieee-754/arc-ieee-754.h"
+
+#ifdef __ARC700__
+ mov_s r12,DBL0L
+ mpyu DBL0L,r12,DBL0H
+ j_s.d [blink]
+ mpyhu DBL0H,r12,DBL0H
+#elif defined (__ARC_MUL64__)
+/* Likewise for __ARC_MUL64__ */
+ mulu64 r0,r1
+ mov_s DBL0L,mlo
+ j_s.d [blink]
+ mov_s DBL0H,mhi
+#else /* !__ARC700__ && !__ARC_MUL64__ */
+/* Although it might look tempting to extend this to handle muldi3,
+ using mulsi3 twice with 2.25 cycles per 32 bit add is faster
+ than one loop with 3 or four cycles per 32 bit add. */
+ asl.f r12,0 ; Top part of b.
+ mov_s r2,0 ; Accumulate result here.
+ bbit1.d r0,0,@.Ladd
+ mov_s r3,0
+.Llooptst:
+ rlc r12,r12
+ breq r0,0,@.Ldone ; while (a)
+.Lloop:
+ asl.f r1,r1 ; b <<= 1
+ bbit0.d r0,1,@.Llooptst
+ lsr r0,r0 ; a >>= 1
+ rlc r12,r12
+.Ladd:
+ add.f r3,r3,r1 ; r += b
+ brne.d r0,0,@.Lloop ; while (a);
+ adc r2,r2,r12
+.Ldone:
+ mov_s DBL0L,r3
+ j_s.d [blink]
+ mov DBL0H,r2
+#endif /* !__ARC700__*/
+ ENDFUNC(__umulsidi3)
+#if defined (__ARC700__) || defined (__ARC_MUL64__) || defined (__ARC601__)
+ ENDFUNC(__umulsi3_highpart)
+#endif
+#endif /* L_umulsidi3 */
+
+#ifdef L_umulsi3_highpart
+#include "ieee-754/arc-ieee-754.h"
+/* For use without a barrel shifter, and for ARC700 / ARC_MUL64, the
+ mulsidi3 algorithms above look better, so for these, there is an
+ extra label up there. */
+#if !defined (__ARC700__) && !defined (__ARC_MUL64__) && !defined (__ARC601__)
+ .global SYM(__umulsi3_highpart)
+SYM(__umulsi3_highpart):
+ HIDDEN_FUNC(__umulsi3_highpart)
+ mov_s r2,0
+ mov_s r3,32
+.Loop:
+ lsr.f r0,r0
+ add.cs.f r2,r2,r1
+ sub_s r3,r3,1
+ brne.d r0,0,.Loop
+ rrc r2,r2
+ j_s.d [blink]
+/* Make the result register peephole-compatible with mulsidi3. */
+ lsr DBL0H,r2,r3
+ ENDFUNC(__umulsi3_highpart)
+#endif /* !__ARC700__ && !__ARC601__ */
+#endif /* L_umulsi3_highpart */
+
+#ifdef L_divmod_tools
+
+; Utilities used by all routines.
+
+ .section .text
+
+/*
+unsigned long
+udivmodsi4(int modwanted, unsigned long num, unsigned long den)
+{
+ unsigned long bit = 1;
+ unsigned long res = 0;
+
+ while (den < num && bit && !(den & (1L<<31)))
+ {
+ den <<=1;
+ bit <<=1;
+ }
+ while (bit)
+ {
+ if (num >= den)
+ {
+ num -= den;
+ res |= bit;
+ }
+ bit >>=1;
+ den >>=1;
+ }
+ if (modwanted) return num;
+ return res;
+}
+*/
+
+; inputs: r0 = numerator, r1 = denominator
+; outputs: r0 = quotient, r1 = remainder, r2/r3 trashed
+
+ .balign 4
+ .global SYM(__udivmodsi4)
+ FUNC(__udivmodsi4)
+SYM(__udivmodsi4):
+
+#if defined (__ARC700__)
+/* Normalize divisor and divident, and then use the appropriate number of
+ divaw (the number of result bits, or one more) to produce the result.
+ There are some special conditions that need to be tested:
+ - We can only directly normalize unsigned numbers that fit in 31 bit. For
+ the divisor, we test early on that it is not 'negative'.
+ - divaw can't corrrectly process a divident that is larger than the divisor.
+ We handle this be checking that the divident prior to normalization is
+ not larger than the normalized divisor. As we then already know then
+ that the divisor fits 31 bit, this check also makes sure that the
+ divident fits.
+ - ordinary normalization of the divident could make it larger than the
+ normalized divisor, which again would be unsuitable for divaw.
+ Thus, we want to shift left the divident by one less, except that we
+ want to leave it alone if it is already 31 bit. To this end, we
+ double the input to norm with adds.
+ - If the divident has less bits than the divisor, that would leave us
+ with a negative number of divaw to execute. Although we could use a
+ conditional loop to avoid excess divaw, and then the quotient could
+ be extracted correctly as there'd be more than enough zero bits, the
+ remainder would be shifted left too far, requiring a conditional shift
+ right. The cost of that shift and the possible mispredict on the
+ conditional loop cost as much as putting in an early check for a zero
+ result. */
+ bmsk r3,r0,29
+ brne.d r3,r0,.Large_dividend
+ norm.f r2,r1
+ brlo r0,r1,.Lret0
+ norm r3,r0
+ asl_s r1,r1,r2
+ sub_s r3,r3,1
+ asl_l r0,r0,r3 ; not short to keep loop aligned
+ sub lp_count,r2,r3
+ lp .Ldiv_end
+ divaw r0,r0,r1
+.Ldiv_end:sub_s r3,r2,1
+ lsr r1,r0,r2
+ j_s.d [blink]
+ bmsk r0,r0,r3
+
+ .balign 4
+.Large_dividend:
+ bmi .Ltrivial
+ asl_s r1,r1,r2
+ mov_s r3,0
+ sub1.f r4,r0,r1
+ mov.lo r4,r0
+ mov.hs r3,2
+ cmp r4,r1
+ sub.hs r4,r4,r1
+ add.hs r3,r3,1
+ mov.f lp_count,r2
+ lpne .Ldiv_end2
+ divaw r4,r4,r1
+.Ldiv_end2:asl r0,r3,r2
+ lsr r1,r4,r2
+ sub_s r2,r2,1
+ bmsk r4,r4,r2
+ j_s.d [blink]
+ or.ne r0,r0,r4
+
+.Lret0:
+ mov_s r1,r0
+ j_s.d [blink]
+ mov_l r0,0
+ .balign 4
+.Ltrivial:
+ sub.f r1,r0,r1
+ mov.c r1,r0
+ mov_s r0,1
+ j_s.d [blink]
+ mov.c r0,0
+#elif !defined (__OPTIMIZE_SIZE__)
+#ifdef __ARC_NORM__
+ lsr_s r2,r0
+ brhs.d r1,r2,.Lret0_3
+ norm r2,r2
+ norm r3,r1
+ sub_s r3,r3,r2
+ asl_s r1,r1,r3
+ sub1.f 0,r0,r1
+ lsr.cs r1,r1,1
+ sbc r2,r3,0
+ sub1 r0,r0,r1
+ cmp_s r0,r1
+ mov.f lp_count,r2
+#else /* ! __ARC_NORM__ */
+ lsr_s r2,r0
+ brhs.d r1,r2,.Lret0_3
+ mov lp_count,32
+.Lloop1:
+ asl_s r1,r1 ; den <<= 1
+ brls.d r1,r2,@.Lloop1
+ sub lp_count,lp_count,1
+ sub_s r0,r0,r1
+ lsr_s r1,r1
+ cmp_s r0,r1
+ xor.f r2,lp_count,31
+ mov_s lp_count,r2
+#endif /* !__ARC_NORM__ */
+ sub.cc r0,r0,r1
+ mov_s r3,3
+ sbc r3,r3,0
+#ifndef __ARC601__
+ asl_s r3,r3,r2
+ rsub r1,r1,1
+ lpne @.Lloop2_end
+ add1.f r0,r1,r0
+ sub.cc r0,r0,r1
+.Lloop2_end:
+ lsr r1,r0,r2
+#else
+ rsub r1,r1,1
+ lpne @.Lloop2_end
+ asl_s r3,r3
+ add1.f r0,r1,r0
+ sub.cc r0,r0,r1
+.Lloop2_end:
+ lsr_s r1,r0
+ lsr.f lp_count,r2
+ mov.cc r1,r0
+ lpnz 1f
+ lsr_s r1,r1
+ lsr_s r1,r1
+1:
+#endif
+ bmsk r0,r0,r2
+ bclr r0,r0,r2
+ j_s.d [blink]
+ or_s r0,r0,r3
+.Lret0_3:
+#if 0 /* Slightly shorter, but slower. */
+ lp .Loop3_end
+ brhi.d r1,r0,.Loop3_end
+ sub_s r0,r0,r1
+.Loop3_end
+ add_s r1,r1,r0
+ j_s.d [blink]
+ rsub r0,lp_count,32-1
+#else
+ mov_s r4,r1
+ sub.f r1,r0,r1
+ sbc r0,r0,r0
+ sub.cc.f r1,r1,r4
+ sbc r0,r0,0
+ sub.cc.f r1,r1,r4
+ sbc r0,r0,-3
+ j_s.d [blink]
+ add.cs r1,r1,r4
+#endif
+#else /* Arctangent-A5 */
+ breq_s r1,0,@.Ldivmodend
+ mov_s r2,1 ; bit = 1
+ mov_s r3,0 ; res = 0
+.Lloop1:
+ brhs r1,r0,@.Lloop2
+ bbit1 r1,31,@.Lloop2
+ asl_s r1,r1 ; den <<= 1
+ b.d @.Lloop1
+ asl_s r2,r2 ; bit <<= 1
+.Lloop2:
+ brlo r0,r1,@.Lshiftdown
+ sub_s r0,r0,r1 ; num -= den
+ or_s r3,r3,r2 ; res |= bit
+.Lshiftdown:
+ lsr_s r2,r2 ; bit >>= 1
+ lsr_s r1,r1 ; den >>= 1
+ brne_s r2,0,@.Lloop2
+.Ldivmodend:
+ mov_s r1,r0 ; r1 = mod
+ j.d [blink]
+ mov_s r0,r3 ; r0 = res
+/******************************************************/
+#endif
+ ENDFUNC(__udivmodsi4)
+
+#endif
+
+#ifdef L_udivsi3
+ .section .text
+ .align 4
+
+ .global SYM(__udivsi3)
+ FUNC(__udivsi3)
+SYM(__udivsi3):
+ b @SYM(__udivmodsi4)
+ ENDFUNC(__udivsi3)
+#if 0 /* interferes with linux loader */
+ .section .__arc_profile_forward, "a"
+ .long SYM(__udivsi3)
+ .long SYM(__udivmodsi4)
+ .long 65536
+#endif
+
+#endif /* L_udivsi3 */
+
+#ifdef L_divsi3
+ .section .text
+ .align 4
+
+ .global SYM(__divsi3)
+ FUNC(__divsi3)
+
+#ifndef __ARC700__
+SYM(__divsi3):
+ /* A5 / ARC60? */
+ mov r7,blink
+ xor r6,r0,r1
+ abs_s r0,r0
+ bl.d @SYM(__udivmodsi4)
+ abs_s r1,r1
+ tst r6,r6
+ j.d [r7]
+ neg.mi r0,r0
+#else /* !ifndef __ARC700__ */
+ ;; We can use the abs, norm, divaw and mpy instructions for ARC700
+#define MULDIV
+#ifdef MULDIV
+/* This table has been generated by divtab-arc700.c. */
+/* 1/512 .. 1/256, normalized. There is a leading 1 in bit 31.
+ For powers of two, we list unnormalized numbers instead. The values
+ for powers of 2 are loaded, but not used. The value for 1 is actually
+ the first instruction after .Lmuldiv. */
+ .balign 4
+.Ldivtab:
+
+ .long 0x1000000
+ .long 0x80808081
+ .long 0x81020409
+ .long 0x81848DA9
+ .long 0x82082083
+ .long 0x828CBFBF
+ .long 0x83126E98
+ .long 0x83993053
+ .long 0x84210843
+ .long 0x84A9F9C9
+ .long 0x85340854
+ .long 0x85BF3762
+ .long 0x864B8A7E
+ .long 0x86D90545
+ .long 0x8767AB60
+ .long 0x87F78088
+ .long 0x88888889
+ .long 0x891AC73B
+ .long 0x89AE408A
+ .long 0x8A42F871
+ .long 0x8AD8F2FC
+ .long 0x8B70344B
+ .long 0x8C08C08D
+ .long 0x8CA29C05
+ .long 0x8D3DCB09
+ .long 0x8DDA5203
+ .long 0x8E78356E
+ .long 0x8F1779DA
+ .long 0x8FB823EF
+ .long 0x905A3864
+ .long 0x90FDBC0A
+ .long 0x91A2B3C5
+ .long 0x92492493
+ .long 0x92F11385
+ .long 0x939A85C5
+ .long 0x94458095
+ .long 0x94F20950
+ .long 0x95A02569
+ .long 0x964FDA6D
+ .long 0x97012E03
+ .long 0x97B425EE
+ .long 0x9868C80A
+ .long 0x991F1A52
+ .long 0x99D722DB
+ .long 0x9A90E7DA
+ .long 0x9B4C6F9F
+ .long 0x9C09C09D
+ .long 0x9CC8E161
+ .long 0x9D89D89E
+ .long 0x9E4CAD24
+ .long 0x9F1165E8
+ .long 0x9FD809FE
+ .long 0xA0A0A0A1
+ .long 0xA16B312F
+ .long 0xA237C32C
+ .long 0xA3065E40
+ .long 0xA3D70A3E
+ .long 0xA4A9CF1E
+ .long 0xA57EB503
+ .long 0xA655C43A
+ .long 0xA72F053A
+ .long 0xA80A80A9
+ .long 0xA8E83F58
+ .long 0xA9C84A48
+ .long 0xAAAAAAAB
+ .long 0xAB8F69E3
+ .long 0xAC769185
+ .long 0xAD602B59
+ .long 0xAE4C415D
+ .long 0xAF3ADDC7
+ .long 0xB02C0B03
+ .long 0xB11FD3B9
+ .long 0xB21642C9
+ .long 0xB30F6353
+ .long 0xB40B40B5
+ .long 0xB509E68B
+ .long 0xB60B60B7
+ .long 0xB70FBB5B
+ .long 0xB81702E1
+ .long 0xB92143FB
+ .long 0xBA2E8BA3
+ .long 0xBB3EE722
+ .long 0xBC52640C
+ .long 0xBD691048
+ .long 0xBE82FA0C
+ .long 0xBFA02FE9
+ .long 0xC0C0C0C1
+ .long 0xC1E4BBD6
+ .long 0xC30C30C4
+ .long 0xC4372F86
+ .long 0xC565C87C
+ .long 0xC6980C6A
+ .long 0xC7CE0C7D
+ .long 0xC907DA4F
+ .long 0xCA4587E7
+ .long 0xCB8727C1
+ .long 0xCCCCCCCD
+ .long 0xCE168A78
+ .long 0xCF6474A9
+ .long 0xD0B69FCC
+ .long 0xD20D20D3
+ .long 0xD3680D37
+ .long 0xD4C77B04
+ .long 0xD62B80D7
+ .long 0xD79435E6
+ .long 0xD901B204
+ .long 0xDA740DA8
+ .long 0xDBEB61EF
+ .long 0xDD67C8A7
+ .long 0xDEE95C4D
+ .long 0xE070381D
+ .long 0xE1FC780F
+ .long 0xE38E38E4
+ .long 0xE525982B
+ .long 0xE6C2B449
+ .long 0xE865AC7C
+ .long 0xEA0EA0EB
+ .long 0xEBBDB2A6
+ .long 0xED7303B6
+ .long 0xEF2EB720
+ .long 0xF0F0F0F1
+ .long 0xF2B9D649
+ .long 0xF4898D60
+ .long 0xF6603D99
+ .long 0xF83E0F84
+ .long 0xFA232CF3
+ .long 0xFC0FC0FD
+ .long 0xFE03F810
+ .long 0x2000000
+ .long 0x81020409
+ .long 0x82082083
+ .long 0x83126E98
+ .long 0x84210843
+ .long 0x85340854
+ .long 0x864B8A7E
+ .long 0x8767AB60
+ .long 0x88888889
+ .long 0x89AE408A
+ .long 0x8AD8F2FC
+ .long 0x8C08C08D
+ .long 0x8D3DCB09
+ .long 0x8E78356E
+ .long 0x8FB823EF
+ .long 0x90FDBC0A
+ .long 0x92492493
+ .long 0x939A85C5
+ .long 0x94F20950
+ .long 0x964FDA6D
+ .long 0x97B425EE
+ .long 0x991F1A52
+ .long 0x9A90E7DA
+ .long 0x9C09C09D
+ .long 0x9D89D89E
+ .long 0x9F1165E8
+ .long 0xA0A0A0A1
+ .long 0xA237C32C
+ .long 0xA3D70A3E
+ .long 0xA57EB503
+ .long 0xA72F053A
+ .long 0xA8E83F58
+ .long 0xAAAAAAAB
+ .long 0xAC769185
+ .long 0xAE4C415D
+ .long 0xB02C0B03
+ .long 0xB21642C9
+ .long 0xB40B40B5
+ .long 0xB60B60B7
+ .long 0xB81702E1
+ .long 0xBA2E8BA3
+ .long 0xBC52640C
+ .long 0xBE82FA0C
+ .long 0xC0C0C0C1
+ .long 0xC30C30C4
+ .long 0xC565C87C
+ .long 0xC7CE0C7D
+ .long 0xCA4587E7
+ .long 0xCCCCCCCD
+ .long 0xCF6474A9
+ .long 0xD20D20D3
+ .long 0xD4C77B04
+ .long 0xD79435E6
+ .long 0xDA740DA8
+ .long 0xDD67C8A7
+ .long 0xE070381D
+ .long 0xE38E38E4
+ .long 0xE6C2B449
+ .long 0xEA0EA0EB
+ .long 0xED7303B6
+ .long 0xF0F0F0F1
+ .long 0xF4898D60
+ .long 0xF83E0F84
+ .long 0xFC0FC0FD
+ .long 0x4000000
+ .long 0x82082083
+ .long 0x84210843
+ .long 0x864B8A7E
+ .long 0x88888889
+ .long 0x8AD8F2FC
+ .long 0x8D3DCB09
+ .long 0x8FB823EF
+ .long 0x92492493
+ .long 0x94F20950
+ .long 0x97B425EE
+ .long 0x9A90E7DA
+ .long 0x9D89D89E
+ .long 0xA0A0A0A1
+ .long 0xA3D70A3E
+ .long 0xA72F053A
+ .long 0xAAAAAAAB
+ .long 0xAE4C415D
+ .long 0xB21642C9
+ .long 0xB60B60B7
+ .long 0xBA2E8BA3
+ .long 0xBE82FA0C
+ .long 0xC30C30C4
+ .long 0xC7CE0C7D
+ .long 0xCCCCCCCD
+ .long 0xD20D20D3
+ .long 0xD79435E6
+ .long 0xDD67C8A7
+ .long 0xE38E38E4
+ .long 0xEA0EA0EB
+ .long 0xF0F0F0F1
+ .long 0xF83E0F84
+ .long 0x8000000
+ .long 0x84210843
+ .long 0x88888889
+ .long 0x8D3DCB09
+ .long 0x92492493
+ .long 0x97B425EE
+ .long 0x9D89D89E
+ .long 0xA3D70A3E
+ .long 0xAAAAAAAB
+ .long 0xB21642C9
+ .long 0xBA2E8BA3
+ .long 0xC30C30C4
+ .long 0xCCCCCCCD
+ .long 0xD79435E6
+ .long 0xE38E38E4
+ .long 0xF0F0F0F1
+ .long 0x10000000
+ .long 0x88888889
+ .long 0x92492493
+ .long 0x9D89D89E
+ .long 0xAAAAAAAB
+ .long 0xBA2E8BA3
+ .long 0xCCCCCCCD
+ .long 0xE38E38E4
+ .long 0x20000000
+ .long 0x92492493
+ .long 0xAAAAAAAB
+ .long 0xCCCCCCCD
+ .long 0x40000000
+ .long 0xAAAAAAAB
+ .long 0x80000000
+__muldiv:
+ neg r4,r2
+ ld.as r5,[pcl,r4]
+ abs_s r12,r0
+ bic.f 0,r2,r4
+ mpyhu.ne r12,r12,r5
+ norm r3,r2
+ xor.f 0,r0,r1
+ ; write port allocation stall
+ rsub r3,r3,30
+ lsr r0,r12,r3
+ j_s.d [blink]
+ neg.mi r0,r0
+
+ .balign 4
+SYM(__divsi3):
+ norm r3,r1
+ abs_s r2,r1
+ brhs r3,23,__muldiv
+ norm r4,r0
+ abs_l r12,r0
+ brhs r4,r3,.Lonebit
+ asl_s r2,r2,r3
+ asl r12,r12,r4
+ sub lp_count,r3,r4
+ sub.f r12,r12,r2
+ brge.d r12,r2,.Lsbit
+ sub r4,r3,r4
+ add.lo r12,r12,r2
+ lp .Ldivend
+.Ldivstart:divaw r12,r12,r2
+.Ldivend:xor_s r1,r1,r0
+ sub r0,r4,1
+ bmsk r0,r12,r0
+ bset.hs r0,r0,r4
+ tst_s r1,r1
+ j_s.d [blink]
+ neg.mi r0,r0
+.Lonebit:
+ xor_s r1,r1,r0
+ asr_s r1,r1,31
+ sub1.f 0,r12,r2 ; special case: -2**(n+1) / 2**n
+ or r0,r1,1
+ add.eq r0,r0,r0
+ cmp_s r12,r2
+ j_s.d [blink]
+ mov.lo r0,0
+.Lsbit:
+ ; Need to handle special cases involving negative powers of two:
+ ; r12,r2 are normalized dividend / divisor;
+ ; divide anything by 0x80000000, or divide 0x80000000 by 0x40000000
+ add_s r12,r12,r2
+ xor_s r1,r1,r0
+ rsub r4,r4,-1
+ ror r0,r12,r4
+ tst_s r2,r2
+ bmsk r0,r0,r3
+ add.pl r0,r0,r0
+ tst_s r1,r1
+ j_s.d [blink]
+ neg.mi r0,r0
+#else /* !MULDIV */
+/* This version requires that divaw works with a divisor of 0x80000000U */
+ abs_s r2,r1
+ norm r4,r0
+ neg_s r3,r2
+ norm r3,r3
+ abs_s r12,r0
+ brhs r4,r3,.Lonebit
+ asl_s r2,r2,r3
+ asl r12,r12,r4
+ sub lp_count,r3,r4
+ cmp_s r12,r2
+ sub.hs r12,r12,r2
+ lp .Ldivend
+.Ldivstart:divaw r12,r12,r2
+.Ldivend:xor_s r1,r1,r0
+ sub_s r0,r3,1
+ bmsk r0,r12,r0
+ bset.hs r0,r0,r3
+ tst_s r1,r1
+ j_s.d [blink]
+ negmi r0,r0
+.Lonebit:
+ xor_s r1,r1,r0
+ asr_s r1,r1,31
+ cmp_s r12,r2
+ mov_s r0,0
+ j_s.d [blink]
+ orhs r0,r1,1
+#endif /* MULDIV */
+
+#endif /* ifndef __ARC700__ */
+ ENDFUNC(__divsi3)
+
+
+#endif /* L_divsi3 */
+
+#ifdef L_umodsi3
+ .section .text
+ .align 4
+
+ .global SYM(__umodsi3)
+ FUNC(__umodsi3)
+SYM(__umodsi3):
+ mov r7,blink
+ bl.nd @SYM(__udivmodsi4)
+ j.d [r7]
+ mov r0,r1
+ ENDFUNC(__umodsi3)
+#if 0 /* interferes with linux loader */
+ .section .__arc_profile_forward, "a"
+ .long SYM(__umodsi3)
+ .long SYM(__udivmodsi4)
+ .long 65536
+#endif
+
+#endif /* L_umodsi3 */
+
+#ifdef L_modsi3
+ .section .text
+ .align 4
+
+ .global SYM (__modsi3)
+ FUNC(__modsi3)
+SYM(__modsi3):
+#ifndef __ARC700__
+ /* A5 / ARC60? */
+ mov_s r12,blink
+ mov_s r6,r0
+ abs_s r0,r0
+ bl.d @SYM(__udivmodsi4)
+ abs_s r1,r1
+ tst r6,r6
+ neg_s r0,r1
+ j_s.d [r12]
+ mov.pl r0,r1
+#else /* __ARC700__ */
+ abs_s r2,r1
+ norm.f r4,r0
+ neg r5,r2
+ norm r3,r5
+ abs_l r12,r0
+ brhs r4,r3,.Lonebit
+ asl_s r2,r2,r3
+ asl r12,r12,r4
+ sub lp_count,r3,r4
+ cmp_s r12,r2
+ sub.hs r12,r12,r2
+ tst_s r0,r0
+ lp .Ldivend
+.Ldivstart:divaw r12,r12,r2
+.Ldivend:
+ lsr r0,r12,r3
+ j_s.d [blink]
+ neg.mi r0,r0
+ .balign 4
+.Lonebit:neg.pl r5,r5
+ cmp_s r12,r2
+ j_s.d [blink]
+ sub.hs r0,r0,r5
+#endif /* __ARC700__ */
+ ENDFUNC(__modsi3)
+
+#endif /* L_modsi3 */
+
+#ifdef L_clzsi2
+ .section .text
+ .align 4
+ .global SYM (__clzsi2)
+SYM(__clzsi2):
+#ifdef __ARC_NORM__
+ HIDDEN_FUNC(__clzsi2)
+ norm.f r0,r0
+ mov.n r0,0
+ j_s.d [blink]
+ add.pl r0,r0,1
+ ENDFUNC(__clzsi2)
+#elif defined (__ARC601__)
+ FUNC(__clzsi2)
+ mov lp_count,10
+ mov_l r1,0
+ bset r2,r1,29
+ lp .Loop_end
+ brhs r0,r2,.Loop_end
+ add3 r0,r1,r0
+.Loop_end:
+ asl.f 0,r0
+ sub2 r0,lp_count,lp_count
+ sub.cs.f r0,r0,1
+ add r0,r0,31
+ j_s.d [blink]
+ add.pl r0,r0,1
+ ENDFUNC(__clzsi2)
+#else
+ FUNC(__clzsi2)
+ asl.f 0,r0,2
+ mov r1,-1
+.Lcheck:
+ bbit1.d r0,31,.Ldone
+ asl.pl r0,r0,3
+ bcs.d .Ldone_1
+ add_s r1,r1,3
+ bpnz.d .Lcheck
+ asl.f 0,r0,2
+ mov_s r0,32
+ j_s.d [blink]
+ mov.ne r0,r1
+.Ldone:
+ j_s.d [blink]
+ add_s r0,r1,1
+.Ldone_1:
+ j_s.d [blink]
+ sub_s r0,r1,1
+ ENDFUNC(__clzsi2)
+#endif
+#endif /* L_clzsi2 */
+ .section .text
+
+
+;;; MILLICODE THUNK LIB ;***************
+
+;;; .macro push_regs from, to, offset
+;;; st_s "\from", [sp, \offset]
+;;; .if \to-\from
+;;; push_regs "(\from+1)", \to, "(\offset+4)"
+;;; .endif
+;;; .endm
+;;; push_regs 13, 18, 0
+;;;
+
+;;;; .macro sum from, to, three
+;;;; .long \from
+;;;; .long \three
+;;;; .local regno
+;;;; .set regno, \from+1
+;;;; .set shift, 32
+;;;; .set shift, shift - 1
+;;;; # st_s %shift @3 lsl #shift
+;;;; .if \to-\from
+;;;; sum "(\from+1)", \to, "(\three)"
+;;;; .endif
+;;;; .endm
+;;;;
+;;;; SUM 0,5, 9
+;;;;
+; .altmacro
+;; .macro push_regs from=0, to=3, offset
+;; st_s r\from, [sp, \offset]
+;; .if \to-\from
+;; push_regs "\from+1 ",\to,"(\offset+4)"
+;; .endif
+;; .endm
+;;
+;; .macro expand_to_push from=13, to
+;; ; .section .text
+;; ; .align 4
+;; ; .global st_
+;; ; .type foo,
+;; st_13_to_25:
+;; ; push_regs \from, \to, 0
+;; push_regs 0,3 ;
+;; .endm
+;;
+;; expand_to_push 13,18
+;;
+;#endif
+
+#ifdef L_millicodethunk_st
+ .section .text
+ .align 4
+ .global SYM(__st_r13_to_r15)
+ .global SYM(__st_r13_to_r16)
+ .global SYM(__st_r13_to_r17)
+ .global SYM(__st_r13_to_r18)
+ .global SYM(__st_r13_to_r19)
+ .global SYM(__st_r13_to_r20)
+ .global SYM(__st_r13_to_r21)
+ .global SYM(__st_r13_to_r22)
+ .global SYM(__st_r13_to_r23)
+ .global SYM(__st_r13_to_r24)
+ .global SYM(__st_r13_to_r25)
+ HIDDEN_FUNC(__st_r13_to_r15)
+ HIDDEN_FUNC(__st_r13_to_r16)
+ HIDDEN_FUNC(__st_r13_to_r17)
+ HIDDEN_FUNC(__st_r13_to_r18)
+ HIDDEN_FUNC(__st_r13_to_r19)
+ HIDDEN_FUNC(__st_r13_to_r20)
+ HIDDEN_FUNC(__st_r13_to_r21)
+ HIDDEN_FUNC(__st_r13_to_r22)
+ HIDDEN_FUNC(__st_r13_to_r23)
+ HIDDEN_FUNC(__st_r13_to_r24)
+ HIDDEN_FUNC(__st_r13_to_r25)
+ .align 4
+SYM(__st_r13_to_r25):
+ st r25, [sp,48]
+SYM(__st_r13_to_r24):
+ st r24, [sp,44]
+SYM(__st_r13_to_r23):
+ st r23, [sp,40]
+SYM(__st_r13_to_r22):
+ st r22, [sp,36]
+SYM(__st_r13_to_r21):
+ st r21, [sp,32]
+SYM(__st_r13_to_r20):
+ st r20, [sp,28]
+SYM(__st_r13_to_r19):
+ st r19, [sp,24]
+SYM(__st_r13_to_r18):
+ st r18, [sp,20]
+SYM(__st_r13_to_r17):
+ st r17, [sp,16]
+SYM(__st_r13_to_r16):
+ st r16, [sp,12]
+SYM(__st_r13_to_r15):
+#ifdef __ARC700__
+ st r15, [sp,8] ; minimum function size to avoid stall: 6 bytes.
+#else
+ st_s r15, [sp,8]
+#endif
+ st_s r14, [sp,4]
+ j_s.d [%blink]
+ st_s r13, [sp,0]
+ ENDFUNC(__st_r13_to_r15)
+ ENDFUNC(__st_r13_to_r16)
+ ENDFUNC(__st_r13_to_r17)
+ ENDFUNC(__st_r13_to_r18)
+ ENDFUNC(__st_r13_to_r19)
+ ENDFUNC(__st_r13_to_r20)
+ ENDFUNC(__st_r13_to_r21)
+ ENDFUNC(__st_r13_to_r22)
+ ENDFUNC(__st_r13_to_r23)
+ ENDFUNC(__st_r13_to_r24)
+ ENDFUNC(__st_r13_to_r25)
+#endif /* L_millicodethunk_st */
+
+
+#ifdef L_millicodethunk_ld
+ .section .text
+ .align 4
+; ==================================
+; the loads
+
+ .global SYM(__ld_r13_to_r15)
+ .global SYM(__ld_r13_to_r16)
+ .global SYM(__ld_r13_to_r17)
+ .global SYM(__ld_r13_to_r18)
+ .global SYM(__ld_r13_to_r19)
+ .global SYM(__ld_r13_to_r20)
+ .global SYM(__ld_r13_to_r21)
+ .global SYM(__ld_r13_to_r22)
+ .global SYM(__ld_r13_to_r23)
+ .global SYM(__ld_r13_to_r24)
+ .global SYM(__ld_r13_to_r25)
+ HIDDEN_FUNC(__ld_r13_to_r15)
+ HIDDEN_FUNC(__ld_r13_to_r16)
+ HIDDEN_FUNC(__ld_r13_to_r17)
+ HIDDEN_FUNC(__ld_r13_to_r18)
+ HIDDEN_FUNC(__ld_r13_to_r19)
+ HIDDEN_FUNC(__ld_r13_to_r20)
+ HIDDEN_FUNC(__ld_r13_to_r21)
+ HIDDEN_FUNC(__ld_r13_to_r22)
+ HIDDEN_FUNC(__ld_r13_to_r23)
+ HIDDEN_FUNC(__ld_r13_to_r24)
+ HIDDEN_FUNC(__ld_r13_to_r25)
+SYM(__ld_r13_to_r25):
+ ld r25, [sp,48]
+SYM(__ld_r13_to_r24):
+ ld r24, [sp,44]
+SYM(__ld_r13_to_r23):
+ ld r23, [sp,40]
+SYM(__ld_r13_to_r22):
+ ld r22, [sp,36]
+SYM(__ld_r13_to_r21):
+ ld r21, [sp,32]
+SYM(__ld_r13_to_r20):
+ ld r20, [sp,28]
+SYM(__ld_r13_to_r19):
+ ld r19, [sp,24]
+SYM(__ld_r13_to_r18):
+ ld r18, [sp,20]
+SYM(__ld_r13_to_r17):
+ ld r17, [sp,16]
+SYM(__ld_r13_to_r16):
+ ld r16, [sp,12]
+SYM(__ld_r13_to_r15):
+#ifdef __ARC700__
+ ld r15, [sp,8] ; minimum function size to avoid stall: 6 bytes.
+#else
+ ld_s r15, [sp,8]
+#endif
+ ld_s r14, [sp,4]
+ j_s.d [%blink]
+ ld_s r13, [sp,0]
+ ENDFUNC(__ld_r13_to_r15)
+ ENDFUNC(__ld_r13_to_r16)
+ ENDFUNC(__ld_r13_to_r17)
+ ENDFUNC(__ld_r13_to_r18)
+ ENDFUNC(__ld_r13_to_r19)
+ ENDFUNC(__ld_r13_to_r20)
+ ENDFUNC(__ld_r13_to_r21)
+ ENDFUNC(__ld_r13_to_r22)
+ ENDFUNC(__ld_r13_to_r23)
+ ENDFUNC(__ld_r13_to_r24)
+ ENDFUNC(__ld_r13_to_r25)
+
+#endif /* L_millicodethunk_ld */
+#ifdef L_millicodethunk_ret
+ .global SYM(__ld_r13_to_r14_ret)
+ .global SYM(__ld_r13_to_r15_ret)
+ .global SYM(__ld_r13_to_r16_ret)
+ .global SYM(__ld_r13_to_r17_ret)
+ .global SYM(__ld_r13_to_r18_ret)
+ .global SYM(__ld_r13_to_r19_ret)
+ .global SYM(__ld_r13_to_r20_ret)
+ .global SYM(__ld_r13_to_r21_ret)
+ .global SYM(__ld_r13_to_r22_ret)
+ .global SYM(__ld_r13_to_r23_ret)
+ .global SYM(__ld_r13_to_r24_ret)
+ .global SYM(__ld_r13_to_r25_ret)
+ HIDDEN_FUNC(__ld_r13_to_r14_ret)
+ HIDDEN_FUNC(__ld_r13_to_r15_ret)
+ HIDDEN_FUNC(__ld_r13_to_r16_ret)
+ HIDDEN_FUNC(__ld_r13_to_r17_ret)
+ HIDDEN_FUNC(__ld_r13_to_r18_ret)
+ HIDDEN_FUNC(__ld_r13_to_r19_ret)
+ HIDDEN_FUNC(__ld_r13_to_r20_ret)
+ HIDDEN_FUNC(__ld_r13_to_r21_ret)
+ HIDDEN_FUNC(__ld_r13_to_r22_ret)
+ HIDDEN_FUNC(__ld_r13_to_r23_ret)
+ HIDDEN_FUNC(__ld_r13_to_r24_ret)
+ HIDDEN_FUNC(__ld_r13_to_r25_ret)
+ .section .text
+ .align 4
+SYM(__ld_r13_to_r25_ret):
+ ld r25, [sp,48]
+SYM(__ld_r13_to_r24_ret):
+ ld r24, [sp,44]
+SYM(__ld_r13_to_r23_ret):
+ ld r23, [sp,40]
+SYM(__ld_r13_to_r22_ret):
+ ld r22, [sp,36]
+SYM(__ld_r13_to_r21_ret):
+ ld r21, [sp,32]
+SYM(__ld_r13_to_r20_ret):
+ ld r20, [sp,28]
+SYM(__ld_r13_to_r19_ret):
+ ld r19, [sp,24]
+SYM(__ld_r13_to_r18_ret):
+ ld r18, [sp,20]
+SYM(__ld_r13_to_r17_ret):
+ ld r17, [sp,16]
+SYM(__ld_r13_to_r16_ret):
+ ld r16, [sp,12]
+SYM(__ld_r13_to_r15_ret):
+ ld r15, [sp,8]
+SYM(__ld_r13_to_r14_ret):
+ ld blink,[sp,r12]
+ ld_s r14, [sp,4]
+ ld.ab r13, [sp,r12]
+ j_s.d [%blink]
+ add_s sp,sp,4
+ ENDFUNC(__ld_r13_to_r14_ret)
+ ENDFUNC(__ld_r13_to_r15_ret)
+ ENDFUNC(__ld_r13_to_r16_ret)
+ ENDFUNC(__ld_r13_to_r17_ret)
+ ENDFUNC(__ld_r13_to_r18_ret)
+ ENDFUNC(__ld_r13_to_r19_ret)
+ ENDFUNC(__ld_r13_to_r20_ret)
+ ENDFUNC(__ld_r13_to_r21_ret)
+ ENDFUNC(__ld_r13_to_r22_ret)
+ ENDFUNC(__ld_r13_to_r23_ret)
+ ENDFUNC(__ld_r13_to_r24_ret)
+ ENDFUNC(__ld_r13_to_r25_ret)
+
+#endif /* L_millicodethunk_ret */
+
+#ifdef L_adddf3
+#ifdef __ARC_NORM__
+#include "ieee-754/adddf3.S"
+#endif
+#endif
+
+#ifdef L_muldf3
+#ifdef __ARC700__
+#include "ieee-754/muldf3.S"
+#elif defined (__ARC_NORM__) && defined(__ARC_MUL64__)
+#include "ieee-754/arc600-mul64/muldf3.S"
+#elif defined (__ARC_NORM__) && defined(__ARC_MUL32BY16__)
+#include "ieee-754/arc600-dsp/muldf3.S"
+#endif
+#endif
+
+#ifdef L_addsf3
+#ifdef __ARC_NORM__
+#include "ieee-754/addsf3.S"
+#endif
+#endif
+
+#ifdef L_mulsf3
+#ifdef __ARC700__
+#include "ieee-754/mulsf3.S"
+#elif defined (__ARC_NORM__) && defined(__ARC_MUL64__)
+#include "ieee-754/arc600-mul64/mulsf3.S"
+#elif defined (__ARC_NORM__) && defined(__ARC_MUL32BY16__)
+#include "ieee-754/arc600-dsp/mulsf3.S"
+#elif defined (__ARC_NORM__)
+#include "ieee-754/arc600/mulsf3.S"
+#endif
+#endif
+
+#ifdef L_divdf3
+#ifdef __ARC700__
+#include "ieee-754/divdf3.S"
+#elif defined (__ARC_NORM__) && defined(__ARC_MUL64__)
+#include "ieee-754/arc600-mul64/divdf3.S"
+#elif defined (__ARC_NORM__) && defined(__ARC_MUL32BY16__)
+#include "ieee-754/arc600-dsp/divdf3.S"
+#endif
+#endif
+
+#ifdef L_divsf3
+#ifdef __ARC700__
+#include "ieee-754/divsf3-stdmul.S"
+#elif defined (__ARC_NORM__) && defined(__ARC_MUL64__)
+#include "ieee-754/arc600-mul64/divsf3.S"
+#elif defined (__ARC_NORM__) && defined(__ARC_MUL32BY16__)
+#include "ieee-754/arc600-dsp/divsf3.S"
+#elif defined (__ARC_NORM__)
+#include "ieee-754/arc600/divsf3.S"
+#endif
+#endif
+
+#ifdef L_extendsfdf2
+#ifdef __ARC_NORM__
+#include "ieee-754/extendsfdf2.S"
+#endif
+#endif
+
+#ifdef L_truncdfsf2
+#ifdef __ARC_NORM__
+#include "ieee-754/truncdfsf2.S"
+#endif
+#endif
+
+#ifdef L_floatsidf
+#ifdef __ARC_NORM__
+#include "ieee-754/floatsidf.S"
+#endif
+#endif
+
+#ifdef L_floatsisf
+#ifdef __ARC_NORM__
+#include "ieee-754/floatsisf.S"
+#endif
+#endif
+
+#ifdef L_floatunsidf
+#ifdef __ARC_NORM__
+#include "ieee-754/floatunsidf.S"
+#endif
+#endif
+
+#ifdef L_fixdfsi
+#ifdef __ARC_NORM__
+#include "ieee-754/fixdfsi.S"
+#endif
+#endif
+
+#ifdef L_fixsfsi
+#ifdef __ARC_NORM__
+#include "ieee-754/fixsfsi.S"
+#endif
+#endif
+
+#ifdef L_fixunsdfsi
+#ifdef __ARC_NORM__
+#include "ieee-754/fixunsdfsi.S"
+#endif
+#endif
+
+#ifdef L_eqdf2
+#ifdef __ARC_NORM__
+#include "ieee-754/eqdf2.S"
+#endif
+#endif
+
+#ifdef L_eqsf2
+#ifdef __ARC_NORM__
+#include "ieee-754/eqsf2.S"
+#endif
+#endif
+
+#ifdef L_gtdf2
+#ifdef __ARC_NORM__
+#include "ieee-754/gtdf2.S"
+#endif
+#endif
+
+#ifdef L_gtsf2
+#ifdef __ARC_NORM__
+#include "ieee-754/gtsf2.S"
+#endif
+#endif
+
+#ifdef L_gedf2
+#ifdef __ARC_NORM__
+#include "ieee-754/gedf2.S"
+#endif
+#endif
+
+#ifdef L_gesf2
+#ifdef __ARC_NORM__
+#include "ieee-754/gesf2.S"
+#endif
+#endif
+
+#ifdef L_uneqdf2
+#ifdef __ARC_NORM__
+#include "ieee-754/uneqdf2.S"
+#endif
+#endif
+
+#ifdef L_uneqsf2
+#ifdef __ARC_NORM__
+#include "ieee-754/uneqsf2.S"
+#endif
+#endif
+
+#ifdef L_orddf2
+#ifdef __ARC_NORM__
+#include "ieee-754/orddf2.S"
+#endif
+#endif
+
+#ifdef L_ordsf2
+#ifdef __ARC_NORM__
+#include "ieee-754/ordsf2.S"
+#endif
+#endif
diff --git a/libgcc/config/arc/libgcc-excl.ver b/libgcc/config/arc/libgcc-excl.ver
new file mode 100644
index 00000000000..57c96e1e765
--- /dev/null
+++ b/libgcc/config/arc/libgcc-excl.ver
@@ -0,0 +1,43 @@
+# Exclude libgcc.so symbols for the Synopsys DesignWare ARC CPU.
+
+# Copyright (C) 2007-2013 Free Software Foundation, Inc.
+# Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+# on behalf of Synopsys 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/>. */
+
+# Exclude various symbols which should not be visible in libgcc.so for ARC.
+# Floating point comparisons use a special lightweight ABI which is not
+# compatible with calls via a plt. Moreover, the code is so compact that
+# it is better to include a separate copy in each dso.
+%exclude {
+ __eqsf2
+ __eqdf2
+ __gtsf2
+ __gtdf2
+ __gesf2
+ __gedf2
+ __uneqsf2
+ __uneqdf2
+ __ordsf2
+ __orddf2
+}
diff --git a/libgcc/config/arc/t-arc b/libgcc/config/arc/t-arc
new file mode 100644
index 00000000000..6edf10ee3ec
--- /dev/null
+++ b/libgcc/config/arc/t-arc
@@ -0,0 +1,100 @@
+# GCC Makefile fragment for Synopsys DesignWare ARC
+
+# Copyright (C) 2007-2013 Free Software Foundation, Inc.
+# Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+# on behalf of Synopsys 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/>.
+
+CROSS_LIBGCC1 = libgcc1-asm.a
+LIB1ASMSRC = arc/lib1funcs.S
+LIB1ASMFUNCS = _mulsi3 _umulsidi3 _umulsi3_highpart \
+ _udivsi3 _divsi3 _umodsi3 _modsi3 \
+ _divmod_tools _clzsi2 \
+ _millicodethunk_st _millicodethunk_ld _millicodethunk_ret \
+ _adddf3 _muldf3 _addsf3 _mulsf3 _divsf3 _divdf3 _truncdfsf2 _extendsfdf2 \
+ _eqdf2 _eqsf2 _gedf2 _gesf2 _gtdf2 _gtsf2 _uneqdf2 _uneqsf2 _ordsf2 _orddf2 \
+ _fixdfsi _fixsfsi _floatsidf _floatsisf _fixunsdfsi _floatunsidf
+
+#LIBGCC2_CFLAGS = -g1 -O2 $(LIBGCC2_INCLUDES) $(GCC_CFLAGS)
+
+# For floating-point emulation, we mostly use hand-coded assembly.
+# We use fp-bit.c for debugging purposes, and some parts of it
+# as a fallback for hardware configurations for which the hand-coded
+# assembly support is incomplete, i.e., where there is no NORM and/or no
+# supported multiply instruction. Using floating point on such a
+# configuration is generally inadvisable, but we got to provide support
+# somehow so that we can run the testsuites.
+# fp-hack.h / dp-hack.h take care of slecting the parts that are needed,
+# and (for debugging) of renaming functions so that they can be
+# used in an asm wrapper.
+
+LIB2ADD = fp-bit.c dp-bit.c
+
+dp-bit.c: $(srcdir)/fp-bit.c
+ echo '#ifndef __big_endian__' > dp-bit.c
+ echo '#define FLOAT_BIT_ORDER_MISMATCH' >> dp-bit.c
+ echo '#endif' >> dp-bit.c
+ echo '#include "fp-bit.h"' >> dp-bit.c
+ echo '#include "config/arc/dp-hack.h"' >> dp-bit.c
+ grep -v 'include.*fp-bit.h' $(srcdir)/fp-bit.c >> dp-bit.c
+
+fp-bit.c: $(srcdir)/fp-bit.c
+ echo '#define FLOAT' > fp-bit.c
+ echo '#ifndef __big_endian__' >> fp-bit.c
+ echo '#define FLOAT_BIT_ORDER_MISMATCH' >> fp-bit.c
+ echo '#endif' >> fp-bit.c
+ echo '#include "config/arc/fp-hack.h"' >> fp-bit.c
+ cat $(srcdir)/fp-bit.c >> fp-bit.c
+
+# .init/.fini section routines
+
+crtg.o: $(srcdir)/config/arc/crtg.S
+ $(crt_compile) -c -x assembler-with-cpp $<
+
+crtgend.o: $(srcdir)/config/arc/crtgend.S
+ $(crt_compile) -c -x assembler-with-cpp $<
+
+mcount.o: $(srcdir)/config/arc/gmon/mcount.c
+ $(gcc_compile) -isystem $(srcdir)/config/arc/gmon -c $< \
+ -fcall-saved-r0 -fcall-saved-r1 -fcall-saved-r2 -fcall-saved-r3 \
+ -fcall-saved-r4 -fcall-saved-r5 -fcall-saved-r6 -fcall-saved-r7 \
+ -fomit-frame-pointer
+
+gmon.o: $(srcdir)/config/arc/gmon/gmon.c
+ $(gcc_compile) -isystem $(srcdir)/config/arc/gmon -mno-sdata -c $< \
+ -fno-strict-aliasing \
+ -Wno-extra # suppress inane warning about missing initializer.
+ # Adding initializers for the remaining elements of gmonparam would
+ # make the code more brittle.
+
+prof-freq-stub.o: $(srcdir)/config/arc/gmon/prof-freq-stub.S
+ $(gcc_compile) -isystem $(srcdir)/config/arc/gmon -c $<
+
+prof-freq.o: $(srcdir)/config/arc/gmon/prof-freq.c
+ $(gcc_compile) -isystem $(srcdir)/config/arc/gmon -c $<
+
+dcache_linesz.o: $(srcdir)/config/arc/gmon/dcache_linesz.S
+ $(gcc_compile) -isystem $(srcdir)/config/arc/gmon -c $<
+
+profil.o: $(srcdir)/config/arc/gmon/profil.S
+ $(gcc_compile) -isystem $(srcdir)/config/arc/gmon -c $<
+
+profil-uclibc.o: $(srcdir)/config/arc/gmon/profil-uclibc.c
+ $(gcc_compile) -isystem $(srcdir)/config/arc/gmon -c $<
+
+libgmon.a: mcount.o gmon.o dcache_linesz.o $(PROFILE_OSDEP)
+ $(AR_CREATE_FOR_TARGET) $@ $^
diff --git a/libgcc/config/arc/t-arc-newlib b/libgcc/config/arc/t-arc-newlib
new file mode 100644
index 00000000000..c9b994657a6
--- /dev/null
+++ b/libgcc/config/arc/t-arc-newlib
@@ -0,0 +1,22 @@
+# GCC Makefile fragment for the Synopsys DesignWare ARC CPU with newlib.
+
+# Copyright (C) 2007-2013 Free Software Foundation, Inc.
+# Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+# on behalf of Synopsys 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/>.
+
+PROFILE_OSDEP = prof-freq-stub.o profil.o
diff --git a/libgcc/config/arc/t-arc700-uClibc b/libgcc/config/arc/t-arc700-uClibc
new file mode 100644
index 00000000000..ebaba498e96
--- /dev/null
+++ b/libgcc/config/arc/t-arc700-uClibc
@@ -0,0 +1,40 @@
+# GCC Makefile fragment for the Synopsys DesignWare ARC700 CPU with uClibc.
+
+# Copyright (C) 2007-2013 Free Software Foundation, Inc.
+# Contributor: Joern Rennecke <joern.rennecke@embecosm.com>
+# on behalf of Synopsys 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/>. */
+
+CRTSTUFF_T_CFLAGS += -mno-sdata
+
+# Compile crtbeginS.o and crtendS.o with pic.
+CRTSTUFF_T_CFLAGS_S = $(CRTSTUFF_T_CFLAGS) -mA7 -fPIC
+
+# Compile libgcc2.a with pic.
+TARGET_LIBGCC2_CFLAGS = -mA7 -fPIC
+
+PROFILE_OSDEP = prof-freq.o
+
+# Override t-slibgcc-elf-ver to hide some lib1func
+# routines which should not be called via PLT.
+SHLIB_MAPFILES = libgcc-std.ver $(srcdir)/config/arc/libgcc-excl.ver
diff --git a/libgcc/config/arm/t-vxworks b/libgcc/config/arm/t-vxworks
deleted file mode 100644
index 9db1f1602bc..00000000000
--- a/libgcc/config/arm/t-vxworks
+++ /dev/null
@@ -1 +0,0 @@
-LIB1ASMFUNCS += _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls _bb_init_func _call_via_rX _interwork_call_via_rX _clzsi2 _clzdi2 _ctzsi2
diff --git a/libgcc/config/cris/arit.c b/libgcc/config/cris/arit.c
index b64d7c95245..00ffa07a5a0 100644
--- a/libgcc/config/cris/arit.c
+++ b/libgcc/config/cris/arit.c
@@ -38,6 +38,14 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define LZ(v) __builtin_clz (v)
#endif
+/* In (at least) the 4.7 series, GCC doesn't automatically choose the
+ most optimal strategy, possibly related to insufficient modelling of
+ delay-slot costs. */
+#if defined (__CRIS_arch_version) && __CRIS_arch_version >= 10
+#define SIGNMULT(s, a) ((s) * (a)) /* Cheap multiplication, better than branch. */
+#else
+#define SIGNMULT(s, a) ((s) < 0 ? -(a) : (a)) /* Branches are still better. */
+#endif
#if defined (L_udivsi3) || defined (L_divsi3) || defined (L_umodsi3) \
|| defined (L_modsi3)
@@ -198,6 +206,7 @@ __Div (long a, long b)
{
long extra = 0;
long sign = (b < 0) ? -1 : 1;
+ long res;
/* We need to handle a == -2147483648 as expected and must while
doing that avoid producing a sequence like "abs (a) < 0" as GCC
@@ -213,15 +222,14 @@ __Div (long a, long b)
if ((a & 0x7fffffff) == 0)
{
/* We're at 0x80000000. Tread carefully. */
- a -= b * sign;
+ a -= SIGNMULT (sign, b);
extra = sign;
}
a = -a;
}
- /* We knowingly penalize pre-v10 models by multiplication with the
- sign. */
- return sign * do_31div (a, __builtin_labs (b)).quot + extra;
+ res = do_31div (a, __builtin_labs (b)).quot;
+ return SIGNMULT (sign, res) + extra;
}
#endif /* L_divsi3 */
@@ -273,6 +281,7 @@ long
__Mod (long a, long b)
{
long sign = 1;
+ long res;
/* We need to handle a == -2147483648 as expected and must while
doing that avoid producing a sequence like "abs (a) < 0" as GCC
@@ -290,7 +299,8 @@ __Mod (long a, long b)
a = -a;
}
- return sign * do_31div (a, __builtin_labs (b)).rem;
+ res = do_31div (a, __builtin_labs (b)).rem;
+ return SIGNMULT (sign, res);
}
#endif /* L_modsi3 */
#endif /* L_udivsi3 || L_divsi3 || L_umodsi3 || L_modsi3 */
diff --git a/libgcc/config/cris/mulsi3.S b/libgcc/config/cris/mulsi3.S
index 8ff76e51e58..734e162b4cb 100644
--- a/libgcc/config/cris/mulsi3.S
+++ b/libgcc/config/cris/mulsi3.S
@@ -113,16 +113,22 @@ ___Mul:
ret
nop
#else
- move.d $r10,$r12
+;; See if we can avoid multiplying some of the parts, knowing
+;; they're zero.
+
move.d $r11,$r9
- bound.d $r12,$r9
+ bound.d $r10,$r9
cmpu.w 65535,$r9
bls L(L3)
- move.d $r12,$r13
+ move.d $r10,$r12
- movu.w $r11,$r9
+;; Nope, have to do all the parts of a 32-bit multiplication.
+;; See head comment in optabs.c:expand_doubleword_mult.
+
+ move.d $r10,$r13
+ movu.w $r11,$r9 ; ab*cd = (a*d + b*c)<<16 + b*d
lslq 16,$r13
- mstep $r9,$r13
+ mstep $r9,$r13 ; d*b
mstep $r9,$r13
mstep $r9,$r13
mstep $r9,$r13
@@ -140,7 +146,7 @@ ___Mul:
mstep $r9,$r13
clear.w $r10
test.d $r10
- mstep $r9,$r10
+ mstep $r9,$r10 ; d*a
mstep $r9,$r10
mstep $r9,$r10
mstep $r9,$r10
@@ -157,10 +163,9 @@ ___Mul:
mstep $r9,$r10
mstep $r9,$r10
movu.w $r12,$r12
- move.d $r11,$r9
- clear.w $r9
- test.d $r9
- mstep $r12,$r9
+ clear.w $r11
+ move.d $r11,$r9 ; Doubles as a "test.d" preparing for the mstep.
+ mstep $r12,$r9 ; b*c
mstep $r12,$r9
mstep $r12,$r9
mstep $r12,$r9
@@ -182,17 +187,24 @@ ___Mul:
add.d $r13,$r10
L(L3):
- move.d $r9,$r10
+;; Form the maximum in $r10, by knowing the minimum, $r9.
+;; (We don't know which one of $r10 or $r11 it is.)
+;; Check if the largest operand is still just 16 bits.
+
+ xor $r9,$r10
xor $r11,$r10
- xor $r12,$r10
cmpu.w 65535,$r10
bls L(L5)
movu.w $r9,$r13
- movu.w $r13,$r13
+;; We have ab*cd = (a*c)<<32 + (a*d + b*c)<<16 + b*d, but c==0
+;; so we only need (a*d)<<16 + b*d with d = $r13, ab = $r10.
+;; We drop the upper part of (a*d)<<16 as we're only doing a
+;; 32-bit-result multiplication.
+
move.d $r10,$r9
lslq 16,$r9
- mstep $r13,$r9
+ mstep $r13,$r9 ; b*d
mstep $r13,$r9
mstep $r13,$r9
mstep $r13,$r9
@@ -210,7 +222,7 @@ L(L3):
mstep $r13,$r9
clear.w $r10
test.d $r10
- mstep $r13,$r10
+ mstep $r13,$r10 ; a*d
mstep $r13,$r10
mstep $r13,$r10
mstep $r13,$r10
@@ -231,25 +243,27 @@ L(L3):
add.d $r9,$r10
L(L5):
- movu.w $r9,$r9
+;; We have ab*cd = (a*c)<<32 + (a*d + b*c)<<16 + b*d, but a and c==0
+;; so b*d (with b=$r13, a=$r10) it is.
+
lslq 16,$r10
- mstep $r9,$r10
- mstep $r9,$r10
- mstep $r9,$r10
- mstep $r9,$r10
- mstep $r9,$r10
- mstep $r9,$r10
- mstep $r9,$r10
- mstep $r9,$r10
- mstep $r9,$r10
- mstep $r9,$r10
- mstep $r9,$r10
- mstep $r9,$r10
- mstep $r9,$r10
- mstep $r9,$r10
- mstep $r9,$r10
+ mstep $r13,$r10
+ mstep $r13,$r10
+ mstep $r13,$r10
+ mstep $r13,$r10
+ mstep $r13,$r10
+ mstep $r13,$r10
+ mstep $r13,$r10
+ mstep $r13,$r10
+ mstep $r13,$r10
+ mstep $r13,$r10
+ mstep $r13,$r10
+ mstep $r13,$r10
+ mstep $r13,$r10
+ mstep $r13,$r10
+ mstep $r13,$r10
ret
- mstep $r9,$r10
+ mstep $r13,$r10
#endif
L(Lfe1):
.size ___Mul,L(Lfe1)-___Mul
diff --git a/libgcc/config/cris/sfp-machine.h b/libgcc/config/cris/sfp-machine.h
new file mode 100644
index 00000000000..484693ea60a
--- /dev/null
+++ b/libgcc/config/cris/sfp-machine.h
@@ -0,0 +1,78 @@
+/* Soft-FP definitions for CRIS.
+ Copyright (C) 2013 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 _FP_W_TYPE_SIZE 32
+#define _FP_W_TYPE unsigned long
+#define _FP_WS_TYPE signed long
+#define _FP_I_TYPE long
+
+/* The type of the result of a floating point comparison. This must
+ match `__libgcc_cmp_return__' in GCC for the target. */
+typedef int __gcc_CMPtype __attribute__ ((mode (__libgcc_cmp_return__)));
+#define CMPtype __gcc_CMPtype
+
+/* FIXME: none of the *MEAT* macros have actually been benchmarked to be
+ better than any other choice for any CRIS variant. */
+
+#define _FP_MUL_MEAT_S(R,X,Y) \
+ _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_S,R,X,Y,umul_ppmm)
+#define _FP_MUL_MEAT_D(R,X,Y) \
+ _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm)
+
+#define _FP_DIV_MEAT_S(R,X,Y) _FP_DIV_MEAT_1_loop(S,R,X,Y)
+#define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_2_udiv(D,R,X,Y)
+
+#define _FP_NANFRAC_S ((_FP_QNANBIT_S << 1) - 1)
+#define _FP_NANFRAC_D ((_FP_QNANBIT_D << 1) - 1), -1
+#define _FP_NANSIGN_S 0
+#define _FP_NANSIGN_D 0
+#define _FP_QNANNEGATEDP 0
+#define _FP_KEEPNANFRACP 1
+
+/* Someone please check this. */
+#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \
+ do { \
+ if ((_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs) \
+ && !(_FP_FRAC_HIGH_RAW_##fs(Y) & _FP_QNANBIT_##fs)) \
+ { \
+ R##_s = Y##_s; \
+ _FP_FRAC_COPY_##wc(R,Y); \
+ } \
+ else \
+ { \
+ R##_s = X##_s; \
+ _FP_FRAC_COPY_##wc(R,X); \
+ } \
+ R##_c = FP_CLS_NAN; \
+ } while (0)
+
+#define __LITTLE_ENDIAN 1234
+#define __BIG_ENDIAN 4321
+
+# define __BYTE_ORDER __LITTLE_ENDIAN
+
+/* Define ALIASNAME as a strong alias for NAME. */
+# define strong_alias(name, aliasname) _strong_alias(name, aliasname)
+# define _strong_alias(name, aliasname) \
+ extern __typeof (name) aliasname __attribute__ ((alias (#name)));
diff --git a/libgcc/config/cris/t-elfmulti b/libgcc/config/cris/t-elfmulti
index b180521039e..308ef5105a9 100644
--- a/libgcc/config/cris/t-elfmulti
+++ b/libgcc/config/cris/t-elfmulti
@@ -1,3 +1,3 @@
-LIB2ADD_ST = $(srcdir)/config/cris/mulsi3.S
+LIB2ADD_ST = $(srcdir)/config/cris/mulsi3.S $(srcdir)/config/cris/umulsidi3.S
CRTSTUFF_T_CFLAGS = -moverride-best-lib-options
diff --git a/libgcc/config/cris/umulsidi3.S b/libgcc/config/cris/umulsidi3.S
new file mode 100644
index 00000000000..eba98a12228
--- /dev/null
+++ b/libgcc/config/cris/umulsidi3.S
@@ -0,0 +1,289 @@
+;; Copyright (C) 2001, 2004, 2013 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 code is derived from mulsi3.S, observing that the mstep*16-based
+;; multiplications there, from which it is formed, are actually
+;; zero-extending; in gcc-speak "umulhisi3". The difference to *this*
+;; function is just a missing top mstep*16 sequence and shifts and 64-bit
+;; additions for the high part. Compared to an implementation based on
+;; calling __Mul four times (see default implementation of umul_ppmm in
+;; longlong.h), this will complete in a time between a fourth and a third
+;; of that, assuming the value-based optimizations don't strike. If they
+;; all strike there (very often) but none here, we still win, though by a
+;; lesser margin, due to lesser total overhead.
+
+#define L(x) .x
+#define CONCAT1(a, b) CONCAT2(a, b)
+#define CONCAT2(a, b) a ## b
+
+#ifdef __USER_LABEL_PREFIX__
+# define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
+#else
+# define SYM(x) x
+#endif
+
+ .global SYM(__umulsidi3)
+ .type SYM(__umulsidi3),@function
+SYM(__umulsidi3):
+#if defined (__CRIS_arch_version) && __CRIS_arch_version >= 10
+;; Can't have the mulu.d last on a cache-line, due to a hardware bug. See
+;; the documentation for -mmul-bug-workaround.
+;; Not worthwhile to conditionalize here.
+ .p2alignw 2,0x050f
+ mulu.d $r11,$r10
+ ret
+ move $mof,$r11
+#else
+ move.d $r11,$r9
+ bound.d $r10,$r9
+ cmpu.w 65535,$r9
+ bls L(L3)
+ move.d $r10,$r12
+
+ move.d $r10,$r13
+ movu.w $r11,$r9 ; ab*cd = (a*c)<<32 (a*d + b*c)<<16 + b*d
+
+;; We're called for floating point numbers very often with the "low" 16
+;; bits zero, so it's worthwhile to optimize for that.
+
+ beq L(L6) ; d == 0?
+ lslq 16,$r13
+
+ beq L(L7) ; b == 0?
+ clear.w $r10
+
+ mstep $r9,$r13 ; d*b
+ mstep $r9,$r13
+ mstep $r9,$r13
+ mstep $r9,$r13
+ mstep $r9,$r13
+ mstep $r9,$r13
+ mstep $r9,$r13
+ mstep $r9,$r13
+ mstep $r9,$r13
+ mstep $r9,$r13
+ mstep $r9,$r13
+ mstep $r9,$r13
+ mstep $r9,$r13
+ mstep $r9,$r13
+ mstep $r9,$r13
+ mstep $r9,$r13
+
+L(L7):
+ test.d $r10
+ mstep $r9,$r10 ; d*a
+ mstep $r9,$r10
+ mstep $r9,$r10
+ mstep $r9,$r10
+ mstep $r9,$r10
+ mstep $r9,$r10
+ mstep $r9,$r10
+ mstep $r9,$r10
+ mstep $r9,$r10
+ mstep $r9,$r10
+ mstep $r9,$r10
+ mstep $r9,$r10
+ mstep $r9,$r10
+ mstep $r9,$r10
+ mstep $r9,$r10
+ mstep $r9,$r10
+
+;; d*a in $r10, d*b in $r13, ab in $r12 and cd in $r11
+;; $r9 = d, need to do b*c and a*c; we can drop d.
+;; so $r9 is up for use and we can shift down $r11 as the mstep
+;; source for the next mstep-part.
+
+L(L8):
+ lsrq 16,$r11
+ move.d $r12,$r9
+ lslq 16,$r9
+ beq L(L9) ; b == 0?
+ mstep $r11,$r9
+
+ mstep $r11,$r9 ; b*c
+ mstep $r11,$r9
+ mstep $r11,$r9
+ mstep $r11,$r9
+ mstep $r11,$r9
+ mstep $r11,$r9
+ mstep $r11,$r9
+ mstep $r11,$r9
+ mstep $r11,$r9
+ mstep $r11,$r9
+ mstep $r11,$r9
+ mstep $r11,$r9
+ mstep $r11,$r9
+ mstep $r11,$r9
+ mstep $r11,$r9
+L(L9):
+
+;; d*a in $r10, d*b in $r13, c*b in $r9, ab in $r12 and c in $r11,
+;; need to do a*c. We want that to end up in $r11, so we shift up $r11 to
+;; now use as the destination operand. We'd need a test insn to update N
+;; to do it the other way round.
+
+ lsrq 16,$r12
+ lslq 16,$r11
+ mstep $r12,$r11
+ mstep $r12,$r11
+ mstep $r12,$r11
+ mstep $r12,$r11
+ mstep $r12,$r11
+ mstep $r12,$r11
+ mstep $r12,$r11
+ mstep $r12,$r11
+ mstep $r12,$r11
+ mstep $r12,$r11
+ mstep $r12,$r11
+ mstep $r12,$r11
+ mstep $r12,$r11
+ mstep $r12,$r11
+ mstep $r12,$r11
+ mstep $r12,$r11
+
+;; d*a in $r10, d*b in $r13, c*b in $r9, a*c in $r11 ($r12 free).
+;; Need (a*d + b*c)<<16 + b*d into $r10 and
+;; a*c + (a*d + b*c)>>16 plus carry from the additions into $r11.
+
+ add.d $r9,$r10 ; (a*d + b*c) - may produce a carry.
+ scs $r12 ; The carry corresponds to bit 16 of $r11.
+ lslq 16,$r12
+ add.d $r12,$r11 ; $r11 = a*c + carry from (a*d + b*c).
+
+#if defined (__CRIS_arch_version) && __CRIS_arch_version >= 8
+ swapw $r10
+ addu.w $r10,$r11 ; $r11 = a*c + (a*d + b*c) >> 16 including carry.
+ clear.w $r10 ; $r10 = (a*d + b*c) << 16
+#else
+ move.d $r10,$r9
+ lsrq 16,$r9
+ add.d $r9,$r11 ; $r11 = a*c + (a*d + b*c) >> 16 including carry.
+ lslq 16,$r10 ; $r10 = (a*d + b*c) << 16
+#endif
+ add.d $r13,$r10 ; $r10 = (a*d + b*c) << 16 + b*d - may produce a carry.
+ scs $r9
+ ret
+ add.d $r9,$r11 ; Last carry added to the high-order 32 bits.
+
+L(L6):
+ clear.d $r13
+ ba L(L8)
+ clear.d $r10
+
+L(L11):
+ clear.d $r10
+ ret
+ clear.d $r11
+
+L(L3):
+;; Form the maximum in $r10, by knowing the minimum, $r9.
+;; (We don't know which one of $r10 or $r11 it is.)
+;; Check if the largest operand is still just 16 bits.
+
+ xor $r9,$r10
+ xor $r11,$r10
+ cmpu.w 65535,$r10
+ bls L(L5)
+ movu.w $r9,$r13
+
+;; We have ab*cd = (a*c)<<32 + (a*d + b*c)<<16 + b*d, but c==0
+;; so we only need (a*d)<<16 + b*d with d = $r13, ab = $r10.
+;; Remember that the upper part of (a*d)<<16 goes into the lower part
+;; of $r11 and there may be a carry from adding the low 32 parts.
+ beq L(L11) ; d == 0?
+ move.d $r10,$r9
+
+ lslq 16,$r9
+ beq L(L10) ; b == 0?
+ clear.w $r10
+
+ mstep $r13,$r9 ; b*d
+ mstep $r13,$r9
+ mstep $r13,$r9
+ mstep $r13,$r9
+ mstep $r13,$r9
+ mstep $r13,$r9
+ mstep $r13,$r9
+ mstep $r13,$r9
+ mstep $r13,$r9
+ mstep $r13,$r9
+ mstep $r13,$r9
+ mstep $r13,$r9
+ mstep $r13,$r9
+ mstep $r13,$r9
+ mstep $r13,$r9
+ mstep $r13,$r9
+L(L10):
+ test.d $r10
+ mstep $r13,$r10 ; a*d
+ mstep $r13,$r10
+ mstep $r13,$r10
+ mstep $r13,$r10
+ mstep $r13,$r10
+ mstep $r13,$r10
+ mstep $r13,$r10
+ mstep $r13,$r10
+ mstep $r13,$r10
+ mstep $r13,$r10
+ mstep $r13,$r10
+ mstep $r13,$r10
+ mstep $r13,$r10
+ mstep $r13,$r10
+ mstep $r13,$r10
+ mstep $r13,$r10
+ move.d $r10,$r11
+ lsrq 16,$r11
+ lslq 16,$r10
+ add.d $r9,$r10
+ scs $r12
+ ret
+ add.d $r12,$r11
+
+L(L5):
+;; We have ab*cd = (a*c)<<32 + (a*d + b*c)<<16 + b*d, but a and c==0
+;; so b*d (with min=b=$r13, max=d=$r10) it is. As it won't overflow the
+;; 32-bit part, just set $r11 to 0.
+
+ lslq 16,$r10
+ clear.d $r11
+
+ mstep $r13,$r10
+ mstep $r13,$r10
+ mstep $r13,$r10
+ mstep $r13,$r10
+ mstep $r13,$r10
+ mstep $r13,$r10
+ mstep $r13,$r10
+ mstep $r13,$r10
+ mstep $r13,$r10
+ mstep $r13,$r10
+ mstep $r13,$r10
+ mstep $r13,$r10
+ mstep $r13,$r10
+ mstep $r13,$r10
+ mstep $r13,$r10
+ ret
+ mstep $r13,$r10
+#endif
+L(Lfe1):
+ .size SYM(__umulsidi3),L(Lfe1)-SYM(__umulsidi3)
diff --git a/libgcc/config/i386/32/sfp-machine.h b/libgcc/config/i386/32/sfp-machine.h
index 143296d69ff..b9eb16633eb 100644
--- a/libgcc/config/i386/32/sfp-machine.h
+++ b/libgcc/config/i386/32/sfp-machine.h
@@ -65,9 +65,15 @@
"g" ((USItype) (y0)))
+#define _FP_MUL_MEAT_S(R,X,Y) \
+ _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_S,R,X,Y,umul_ppmm)
+#define _FP_MUL_MEAT_D(R,X,Y) \
+ _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm)
#define _FP_MUL_MEAT_Q(R,X,Y) \
_FP_MUL_MEAT_4_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm)
+#define _FP_DIV_MEAT_S(R,X,Y) _FP_DIV_MEAT_1_loop(S,R,X,Y)
+#define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_2_udiv(D,R,X,Y)
#define _FP_DIV_MEAT_Q(R,X,Y) _FP_DIV_MEAT_4_udiv(Q,R,X,Y)
#define _FP_NANFRAC_S _FP_QNANBIT_S
diff --git a/libgcc/config/i386/crtfastmath.c b/libgcc/config/i386/crtfastmath.c
index 991f531fe7d..5a267c3b1a5 100644
--- a/libgcc/config/i386/crtfastmath.c
+++ b/libgcc/config/i386/crtfastmath.c
@@ -21,6 +21,7 @@
* <http://www.gnu.org/licenses/>.
*/
+#ifndef _SOFT_FLOAT
#define MXCSR_DAZ (1 << 6) /* Enable denormals are zero mode */
#define MXCSR_FTZ (1 << 15) /* Enable flush to zero mode */
@@ -134,3 +135,4 @@ set_fast_math (void)
__builtin_ia32_ldmxcsr (mxcsr);
#endif
}
+#endif
diff --git a/libgcc/config/i386/crtprec.c b/libgcc/config/i386/crtprec.c
index f0c1fbe7228..f8f9962b13b 100644
--- a/libgcc/config/i386/crtprec.c
+++ b/libgcc/config/i386/crtprec.c
@@ -21,6 +21,7 @@
* <http://www.gnu.org/licenses/>.
*/
+#ifndef _SOFT_FLOAT
#if __PREC == 32
#define X87CW (0 << 8) /* Single precision (24 bits) */
#elif __PREC == 64
@@ -45,3 +46,4 @@ set_precision (void)
asm volatile ("fldcw\t%0" : : "m" (cwd));
}
+#endif
diff --git a/libgcc/config/i386/cygming-crtbegin.c b/libgcc/config/i386/cygming-crtbegin.c
index c34178787c8..53909d2dc14 100644
--- a/libgcc/config/i386/cygming-crtbegin.c
+++ b/libgcc/config/i386/cygming-crtbegin.c
@@ -91,6 +91,9 @@ static EH_FRAME_SECTION_CONST char __EH_FRAME_BEGIN__[]
= { };
static struct object obj;
+
+/* Handle of libgcc's DLL reference. */
+HANDLE hmod_libgcc;
#endif
#if TARGET_USE_JCR_SECTION
@@ -115,9 +118,14 @@ __gcc_register_frame (void)
void (*register_frame_fn) (const void *, struct object *);
HANDLE h = GetModuleHandle (LIBGCC_SONAME);
+
if (h)
- register_frame_fn = (void (*) (const void *, struct object *))
- GetProcAddress (h, "__register_frame_info");
+ {
+ /* Increasing the load-count of LIBGCC_SONAME DLL. */
+ hmod_libgcc = LoadLibrary (LIBGCC_SONAME);
+ register_frame_fn = (void (*) (const void *, struct object *))
+ GetProcAddress (h, "__register_frame_info");
+ }
else
register_frame_fn = __register_frame_info;
if (register_frame_fn)
@@ -154,5 +162,7 @@ __gcc_deregister_frame (void)
deregister_frame_fn = __deregister_frame_info;
if (deregister_frame_fn)
deregister_frame_fn (__EH_FRAME_BEGIN__);
+ if (hmod_libgcc)
+ FreeLibrary (hmod_libgcc);
#endif
}
diff --git a/libgcc/config/i386/sfp-exceptions.c b/libgcc/config/i386/sfp-exceptions.c
index fbaaab22f50..3504c4aedd1 100644
--- a/libgcc/config/i386/sfp-exceptions.c
+++ b/libgcc/config/i386/sfp-exceptions.c
@@ -48,20 +48,32 @@ __sfp_handle_exceptions (int _fex)
{
float f = 0.0f;
#ifdef __x86_64__
+ volatile float r __attribute__ ((unused));
asm volatile ("%vdivss\t{%0, %d0|%d0, %0}" : "+x" (f));
+ r = f; /* Needed to trigger exception. */
#else
asm volatile ("fdiv\t{%y0, %0|%0, %y0}" : "+t" (f));
- asm volatile ("fwait");
+ /* No need for fwait, exception is triggered by emitted fstp. */
#endif
}
+ if (_fex & FP_EX_DENORM)
+ {
+ struct fenv temp;
+ asm volatile ("fnstenv\t%0" : "=m" (temp));
+ temp.__status_word |= FP_EX_DENORM;
+ asm volatile ("fldenv\t%0" : : "m" (temp));
+ asm volatile ("fwait");
+ }
if (_fex & FP_EX_DIVZERO)
{
float f = 1.0f, g = 0.0f;
#ifdef __x86_64__
+ volatile float r __attribute__ ((unused));
asm volatile ("%vdivss\t{%1, %d0|%d0, %1}" : "+x" (f) : "xm" (g));
+ r = f; /* Needed to trigger exception. */
#else
asm volatile ("fdivs\t%1" : "+t" (f) : "m" (g));
- asm volatile ("fwait");
+ /* No need for fwait, exception is triggered by emitted fstp. */
#endif
}
if (_fex & FP_EX_OVERFLOW)
@@ -82,11 +94,15 @@ __sfp_handle_exceptions (int _fex)
}
if (_fex & FP_EX_INEXACT)
{
- struct fenv temp;
- asm volatile ("fnstenv\t%0" : "=m" (temp));
- temp.__status_word |= FP_EX_INEXACT;
- asm volatile ("fldenv\t%0" : : "m" (temp));
- asm volatile ("fwait");
+ float f = 1.0f, g = 3.0f;
+#ifdef __x86_64__
+ volatile float r __attribute__ ((unused));
+ asm volatile ("%vdivss\t{%1, %d0|%d0, %1}" : "+x" (f) : "xm" (g));
+ r = f; /* Needed to trigger exception. */
+#else
+ asm volatile ("fdivs\t%1" : "+t" (f) : "m" (g));
+ /* No need for fwait, exception is triggered by emitted fstp. */
+#endif
}
};
#endif
diff --git a/libgcc/config/nds32/crtzero.S b/libgcc/config/nds32/crtzero.S
new file mode 100644
index 00000000000..65098698dba
--- /dev/null
+++ b/libgcc/config/nds32/crtzero.S
@@ -0,0 +1,103 @@
+/* The startup code sample of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+!!==============================================================================
+!!
+!! crtzero.S
+!!
+!! This is JUST A SAMPLE of nds32 startup code !!
+!! You can refer this content and implement
+!! the actual one in newlib/mculib.
+!!
+!!==============================================================================
+
+!!------------------------------------------------------------------------------
+!! Jump to start up code
+!!------------------------------------------------------------------------------
+ .section .nds32_init, "ax"
+ j _start
+
+!!------------------------------------------------------------------------------
+!! Startup code implementation
+!!------------------------------------------------------------------------------
+ .section .text
+ .global _start
+ .weak _SDA_BASE_
+ .weak _FP_BASE_
+ .align 2
+ .func _start
+ .type _start, @function
+_start:
+.L_fp_gp_lp_init:
+ la $fp, _FP_BASE_ ! init $fp
+ la $gp, _SDA_BASE_ ! init $gp for small data access
+ movi $lp, 0 ! init $lp
+
+.L_stack_init:
+ la $sp, _stack ! init $sp
+ movi $r0, -8 ! align $sp to 8-byte (use 0xfffffff8)
+ and $sp, $sp, $r0 ! align $sp to 8-byte (filter out lower 3-bit)
+
+.L_bss_init:
+ ! clear BSS, this process can be 4 time faster if data is 4 byte aligned
+ ! if so, use swi.p instead of sbi.p
+ ! the related stuff are defined in linker script
+ la $r0, _edata ! get the starting addr of bss
+ la $r2, _end ! get ending addr of bss
+ beq $r0, $r2, .L_call_main ! if no bss just do nothing
+ movi $r1, 0 ! should be cleared to 0
+.L_clear_bss:
+ sbi.p $r1, [$r0], 1 ! Set 0 to bss
+ bne $r0, $r2, .L_clear_bss ! Still bytes left to set
+
+!.L_stack_heap_check:
+! la $r0, _end ! init heap_end
+! s.w $r0, heap_end ! save it
+
+
+!.L_init_argc_argv:
+! ! argc/argv initialization if necessary; default implementation is in crt1.o
+! la $r9, _arg_init ! load address of _arg_init?
+! beqz $r9, .L4 ! has _arg_init? no, go check main()
+! addi $sp, $sp, -512 ! allocate space for command line + arguments
+! move $r6, $sp ! r6 = buffer addr of cmd line
+! move $r0, $r6 ! r0 = buffer addr of cmd line
+! syscall 6002 ! get cmd line
+! move $r0, $r6 ! r0 = buffer addr of cmd line
+! addi $r1, $r6, 256 ! r1 = argv
+! jral $r9 ! init argc/argv
+! addi $r1, $r6, 256 ! r1 = argv
+
+.L_call_main:
+ ! call main() if main() is provided
+ la $r15, main ! load address of main
+ jral $r15 ! call main
+
+.L_terminate_program:
+ syscall 0x1 ! use syscall 0x1 to terminate program
+ .size _start, .-_start
+ .end
+
+!! ------------------------------------------------------------------------
diff --git a/libgcc/config/nds32/initfini.c b/libgcc/config/nds32/initfini.c
new file mode 100644
index 00000000000..7235148c5e3
--- /dev/null
+++ b/libgcc/config/nds32/initfini.c
@@ -0,0 +1,159 @@
+/* .init/.fini section handling + C++ global constructor/destructor
+ handling of Andes NDS32 cpu for GNU compiler.
+ This file is based on crtstuff.c, sol2-crti.asm, sol2-crtn.asm.
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+/* Declare a pointer to void function type. */
+typedef void (*func_ptr) (void);
+
+#ifdef CRT_BEGIN
+
+/* NOTE: In order to be able to support SVR4 shared libraries, we arrange
+ to have one set of symbols { __CTOR_LIST__, __DTOR_LIST__, __CTOR_END__,
+ __DTOR_END__ } per root executable and also one set of these symbols
+ per shared library. So in any given whole process image, we may have
+ multiple definitions of each of these symbols. In order to prevent
+ these definitions from conflicting with one another, and in order to
+ ensure that the proper lists are used for the initialization/finalization
+ of each individual shared library (respectively), we give these symbols
+ only internal (i.e. `static') linkage, and we also make it a point to
+ refer to only the __CTOR_END__ symbol in crtfini.o and the __DTOR_LIST__
+ symbol in crtinit.o, where they are defined. */
+
+static func_ptr __CTOR_LIST__[1] __attribute__ ((section (".ctors")))
+ = { (func_ptr) (-1) };
+
+static func_ptr __DTOR_LIST__[1] __attribute__ ((section (".dtors")))
+ = { (func_ptr) (-1) };
+
+/* Run all the global destructors on exit from the program. */
+
+/* Some systems place the number of pointers in the first word of the
+ table. On SVR4 however, that word is -1. In all cases, the table is
+ null-terminated. On SVR4, we start from the beginning of the list and
+ invoke each per-compilation-unit destructor routine in order
+ until we find that null.
+
+ Note that this function MUST be static. There will be one of these
+ functions in each root executable and one in each shared library, but
+ although they all have the same code, each one is unique in that it
+ refers to one particular associated `__DTOR_LIST__' which belongs to the
+ same particular root executable or shared library file. */
+
+static void __do_global_dtors (void)
+asm ("__do_global_dtors") __attribute__ ((section (".text")));
+
+static void
+__do_global_dtors (void)
+{
+ func_ptr *p;
+ for (p = __DTOR_LIST__ + 1; *p; p++)
+ (*p) ();
+}
+
+/* .init section start.
+ This must appear at the start of the .init section. */
+
+asm ("\n\
+ .section .init\n\
+ .global _init\n\
+ .type _init, @function\n\
+_init:\n\
+ ! 1. store $fp\n\
+ ! 2. adjust $fp by $sp\n\
+ ! 3. adjust $sp\n\
+");
+
+/* .fini section start.
+ This must appear at the start of the .fini section. */
+
+asm ("\n\
+ .section .fini\n\
+ .global _fini\n\
+ .type _fini, @function\n\
+_fini:\n\
+ ! 1. store $fp\n\
+ ! 2. adjust $fp by $sp\n\
+ ! 3. adjust $sp\n\
+ ! 4. call __do_global_dtors\n\
+ j __do_global_dtors\n\
+");
+
+#endif /* CRT_BEGIN */
+
+#ifdef CRT_END
+
+/* Define __dso_handle which would be needed for C++ library.
+ Since our elf-toolchain only builds programs with static link,
+ we can directly define 'void *__dso_handle = 0'. */
+void *__dso_handle = 0;
+
+/* Put a word containing zero at the end of each of our two lists of function
+ addresses. Note that the words defined here go into the .ctors and .dtors
+ sections of the crtend.o file, and since that file is always linked in
+ last, these words naturally end up at the very ends of the two lists
+ contained in these two sections. */
+
+static func_ptr __CTOR_END__[1] __attribute__ ((section (".ctors")))
+ = { (func_ptr) 0 };
+
+static func_ptr __DTOR_END__[1] __attribute__ ((section (".dtors")))
+ = { (func_ptr) 0 };
+
+/* Run all global constructors for the program.
+ Note that they are run in reverse order. */
+
+static void __do_global_ctors (void)
+asm ("__do_global_ctors") __attribute__ ((section (".text")));
+
+static void
+__do_global_ctors (void)
+{
+ func_ptr *p;
+ for (p = __CTOR_END__ - 1; *p != (func_ptr) -1; p--)
+ (*p) ();
+}
+
+/* .init section end.
+ This must live at the end of the .init section. */
+
+asm ("\n\
+ .section .init\n\
+ ! 1. call __do_global_ctors\n\
+ ! 2. adjust back $sp\n\
+ ! 3. restore $fp\n\
+ j __do_global_ctors\n\
+");
+
+/* .fini section end.
+ This must live at the end of the .fini section. */
+
+asm ("\n\
+ .section .fini\n\
+ ! 1. adjust back $sp\n\
+ ! 2. restore $fp\n\
+");
+
+#endif /* CRT_END */
diff --git a/libgcc/config/nds32/isr-library/adj_intr_lvl.inc b/libgcc/config/nds32/isr-library/adj_intr_lvl.inc
new file mode 100644
index 00000000000..6c0c8aaebad
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/adj_intr_lvl.inc
@@ -0,0 +1,38 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+.macro ADJ_INTR_LVL
+#if defined(NDS32_NESTED) /* Nested handler. */
+ mfsr $r3, $PSW
+ addi $r3, $r3, #-0x1
+ mtsr $r3, $PSW
+#elif defined(NDS32_NESTED_READY) /* Nested ready handler. */
+ /* Save ipc and ipsw and lower INT level. */
+ mfsr $r3, $PSW
+ addi $r3, $r3, #-0x2
+ mtsr $r3, $PSW
+#else /* Not nested handler. */
+#endif
+.endm
diff --git a/libgcc/config/nds32/isr-library/excp_isr.S b/libgcc/config/nds32/isr-library/excp_isr.S
new file mode 100644
index 00000000000..a68a8ec3313
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/excp_isr.S
@@ -0,0 +1,132 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+#include "save_mac_regs.inc"
+#include "save_fpu_regs.inc"
+#include "save_fpu_regs_00.inc"
+#include "save_fpu_regs_01.inc"
+#include "save_fpu_regs_02.inc"
+#include "save_fpu_regs_03.inc"
+#include "save_all.inc"
+#include "save_partial.inc"
+#include "adj_intr_lvl.inc"
+#include "restore_mac_regs.inc"
+#include "restore_fpu_regs_00.inc"
+#include "restore_fpu_regs_01.inc"
+#include "restore_fpu_regs_02.inc"
+#include "restore_fpu_regs_03.inc"
+#include "restore_fpu_regs.inc"
+#include "restore_all.inc"
+#include "restore_partial.inc"
+ .section .nds32_isr, "ax" /* Put it in the section of 1st level handler. */
+ .align 1
+/*
+ First Level Handlers
+ 1. First Level Handlers are invokded in vector section via jump instruction
+ with specific names for different configurations.
+ 2. Naming Format: _nds32_e_SR_NT for exception handlers.
+ _nds32_i_SR_NT for interrupt handlers.
+ 2.1 All upper case letters are replaced with specific lower case letters encodings.
+ 2.2 SR: Saved Registers
+ sa: Save All regs (context)
+ ps: Partial Save (all caller-saved regs)
+ 2.3 NT: Nested Type
+ ns: nested
+ nn: not nested
+ nr: nested ready
+*/
+
+/*
+ This is original 16-byte vector size version.
+*/
+#ifdef NDS32_SAVE_ALL_REGS
+#if defined(NDS32_NESTED)
+ .globl _nds32_e_sa_ns
+ .type _nds32_e_sa_ns, @function
+_nds32_e_sa_ns:
+#elif defined(NDS32_NESTED_READY)
+ .globl _nds32_e_sa_nr
+ .type _nds32_e_sa_nr, @function
+_nds32_e_sa_nr:
+#else /* Not nested handler. */
+ .globl _nds32_e_sa_nn
+ .type _nds32_e_sa_nn, @function
+_nds32_e_sa_nn:
+#endif /* endif for Nest Type */
+#else /* not NDS32_SAVE_ALL_REGS */
+#if defined(NDS32_NESTED)
+ .globl _nds32_e_ps_ns
+ .type _nds32_e_ps_ns, @function
+_nds32_e_ps_ns:
+#elif defined(NDS32_NESTED_READY)
+ .globl _nds32_e_ps_nr
+ .type _nds32_e_ps_nr, @function
+_nds32_e_ps_nr:
+#else /* Not nested handler. */
+ .globl _nds32_e_ps_nn
+ .type _nds32_e_ps_nn, @function
+_nds32_e_ps_nn:
+#endif /* endif for Nest Type */
+#endif /* not NDS32_SAVE_ALL_REGS */
+
+/*
+ This is 16-byte vector size version.
+ The vector id was restored into $r0 in vector by compiler.
+*/
+#ifdef NDS32_SAVE_ALL_REGS
+ SAVE_ALL
+#else
+ SAVE_PARTIAL
+#endif
+ /* Prepare to call 2nd level handler. */
+ la $r2, _nds32_jmptbl_00
+ lw $r2, [$r2 + $r0 << #2]
+ ADJ_INTR_LVL /* Adjust INTR level. $r3 is clobbered. */
+ jral $r2
+ /* Restore used registers. */
+#ifdef NDS32_SAVE_ALL_REGS
+ RESTORE_ALL
+#else
+ RESTORE_PARTIAL
+#endif
+ iret
+
+#ifdef NDS32_SAVE_ALL_REGS
+#if defined(NDS32_NESTED)
+ .size _nds32_e_sa_ns, .-_nds32_e_sa_ns
+#elif defined(NDS32_NESTED_READY)
+ .size _nds32_e_sa_nr, .-_nds32_e_sa_nr
+#else /* Not nested handler. */
+ .size _nds32_e_sa_nn, .-_nds32_e_sa_nn
+#endif /* endif for Nest Type */
+#else /* not NDS32_SAVE_ALL_REGS */
+#if defined(NDS32_NESTED)
+ .size _nds32_e_ps_ns, .-_nds32_e_ps_ns
+#elif defined(NDS32_NESTED_READY)
+ .size _nds32_e_ps_nr, .-_nds32_e_ps_nr
+#else /* Not nested handler. */
+ .size _nds32_e_ps_nn, .-_nds32_e_ps_nn
+#endif /* endif for Nest Type */
+#endif /* not NDS32_SAVE_ALL_REGS */
diff --git a/libgcc/config/nds32/isr-library/excp_isr_4b.S b/libgcc/config/nds32/isr-library/excp_isr_4b.S
new file mode 100644
index 00000000000..e37c2f62dd2
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/excp_isr_4b.S
@@ -0,0 +1,133 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+#include "save_mac_regs.inc"
+#include "save_fpu_regs.inc"
+#include "save_fpu_regs_00.inc"
+#include "save_fpu_regs_01.inc"
+#include "save_fpu_regs_02.inc"
+#include "save_fpu_regs_03.inc"
+#include "save_all.inc"
+#include "save_partial.inc"
+#include "adj_intr_lvl.inc"
+#include "restore_mac_regs.inc"
+#include "restore_fpu_regs_00.inc"
+#include "restore_fpu_regs_01.inc"
+#include "restore_fpu_regs_02.inc"
+#include "restore_fpu_regs_03.inc"
+#include "restore_fpu_regs.inc"
+#include "restore_all.inc"
+#include "restore_partial.inc"
+ .section .nds32_isr, "ax" /* Put it in the section of 1st level handler. */
+ .align 1
+/*
+ First Level Handlers
+ 1. First Level Handlers are invokded in vector section via jump instruction
+ with specific names for different configurations.
+ 2. Naming Format: _nds32_e_SR_NT for exception handlers.
+ _nds32_i_SR_NT for interrupt handlers.
+ 2.1 All upper case letters are replaced with specific lower case letters encodings.
+ 2.2 SR: Saved Registers
+ sa: Save All regs (context)
+ ps: Partial Save (all caller-saved regs)
+ 2.3 NT: Nested Type
+ ns: nested
+ nn: not nested
+ nr: nested ready
+*/
+
+/*
+ This is 4-byte vector size version.
+ The "_4b" postfix was added for 4-byte version symbol.
+*/
+#ifdef NDS32_SAVE_ALL_REGS
+#if defined(NDS32_NESTED)
+ .globl _nds32_e_sa_ns_4b
+ .type _nds32_e_sa_ns_4b, @function
+_nds32_e_sa_ns_4b:
+#elif defined(NDS32_NESTED_READY)
+ .globl _nds32_e_sa_nr_4b
+ .type _nds32_e_sa_nr_4b, @function
+_nds32_e_sa_nr_4b:
+#else /* Not nested handler. */
+ .globl _nds32_e_sa_nn_4b
+ .type _nds32_e_sa_nn_4b, @function
+_nds32_e_sa_nn_4b:
+#endif /* endif for Nest Type */
+#else /* not NDS32_SAVE_ALL_REGS */
+#if defined(NDS32_NESTED)
+ .globl _nds32_e_ps_ns_4b
+ .type _nds32_e_ps_ns_4b, @function
+_nds32_e_ps_ns_4b:
+#elif defined(NDS32_NESTED_READY)
+ .globl _nds32_e_ps_nr_4b
+ .type _nds32_e_ps_nr_4b, @function
+_nds32_e_ps_nr_4b:
+#else /* Not nested handler. */
+ .globl _nds32_e_ps_nn_4b
+ .type _nds32_e_ps_nn_4b, @function
+_nds32_e_ps_nn_4b:
+#endif /* endif for Nest Type */
+#endif /* not NDS32_SAVE_ALL_REGS */
+
+/*
+ This is 4-byte vector size version.
+ The vector id was restored into $lp in vector by compiler.
+*/
+#ifdef NDS32_SAVE_ALL_REGS
+ SAVE_ALL_4B
+#else
+ SAVE_PARTIAL_4B
+#endif
+ /* Prepare to call 2nd level handler. */
+ la $r2, _nds32_jmptbl_00
+ lw $r2, [$r2 + $r0 << #2]
+ ADJ_INTR_LVL /* Adjust INTR level. $r3 is clobbered. */
+ jral $r2
+ /* Restore used registers. */
+#ifdef NDS32_SAVE_ALL_REGS
+ RESTORE_ALL
+#else
+ RESTORE_PARTIAL
+#endif
+ iret
+
+#ifdef NDS32_SAVE_ALL_REGS
+#if defined(NDS32_NESTED)
+ .size _nds32_e_sa_ns_4b, .-_nds32_e_sa_ns_4b
+#elif defined(NDS32_NESTED_READY)
+ .size _nds32_e_sa_nr_4b, .-_nds32_e_sa_nr_4b
+#else /* Not nested handler. */
+ .size _nds32_e_sa_nn_4b, .-_nds32_e_sa_nn_4b
+#endif /* endif for Nest Type */
+#else /* not NDS32_SAVE_ALL_REGS */
+#if defined(NDS32_NESTED)
+ .size _nds32_e_ps_ns_4b, .-_nds32_e_ps_ns_4b
+#elif defined(NDS32_NESTED_READY)
+ .size _nds32_e_ps_nr_4b, .-_nds32_e_ps_nr_4b
+#else /* Not nested handler. */
+ .size _nds32_e_ps_nn_4b, .-_nds32_e_ps_nn_4b
+#endif /* endif for Nest Type */
+#endif /* not NDS32_SAVE_ALL_REGS */
diff --git a/libgcc/config/nds32/isr-library/intr_isr.S b/libgcc/config/nds32/isr-library/intr_isr.S
new file mode 100644
index 00000000000..4d9537474b9
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/intr_isr.S
@@ -0,0 +1,132 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+#include "save_mac_regs.inc"
+#include "save_fpu_regs.inc"
+#include "save_fpu_regs_00.inc"
+#include "save_fpu_regs_01.inc"
+#include "save_fpu_regs_02.inc"
+#include "save_fpu_regs_03.inc"
+#include "save_all.inc"
+#include "save_partial.inc"
+#include "adj_intr_lvl.inc"
+#include "restore_mac_regs.inc"
+#include "restore_fpu_regs_00.inc"
+#include "restore_fpu_regs_01.inc"
+#include "restore_fpu_regs_02.inc"
+#include "restore_fpu_regs_03.inc"
+#include "restore_fpu_regs.inc"
+#include "restore_all.inc"
+#include "restore_partial.inc"
+ .section .nds32_isr, "ax" /* Put it in the section of 1st level handler. */
+ .align 1
+/*
+ First Level Handlers
+ 1. First Level Handlers are invokded in vector section via jump instruction
+ with specific names for different configurations.
+ 2. Naming Format: _nds32_e_SR_NT for exception handlers.
+ _nds32_i_SR_NT for interrupt handlers.
+ 2.1 All upper case letters are replaced with specific lower case letters encodings.
+ 2.2 SR: Saved Registers
+ sa: Save All regs (context)
+ ps: Partial Save (all caller-saved regs)
+ 2.3 NT: Nested Type
+ ns: nested
+ nn: not nested
+ nr: nested ready
+*/
+
+/*
+ This is original 16-byte vector size version.
+*/
+#ifdef NDS32_SAVE_ALL_REGS
+#if defined(NDS32_NESTED)
+ .globl _nds32_i_sa_ns
+ .type _nds32_i_sa_ns, @function
+_nds32_i_sa_ns:
+#elif defined(NDS32_NESTED_READY)
+ .globl _nds32_i_sa_nr
+ .type _nds32_i_sa_nr, @function
+_nds32_i_sa_nr:
+#else /* Not nested handler. */
+ .globl _nds32_i_sa_nn
+ .type _nds32_i_sa_nn, @function
+_nds32_i_sa_nn:
+#endif /* endif for Nest Type */
+#else /* not NDS32_SAVE_ALL_REGS */
+#if defined(NDS32_NESTED)
+ .globl _nds32_i_ps_ns
+ .type _nds32_i_ps_ns, @function
+_nds32_i_ps_ns:
+#elif defined(NDS32_NESTED_READY)
+ .globl _nds32_i_ps_nr
+ .type _nds32_i_ps_nr, @function
+_nds32_i_ps_nr:
+#else /* Not nested handler. */
+ .globl _nds32_i_ps_nn
+ .type _nds32_i_ps_nn, @function
+_nds32_i_ps_nn:
+#endif /* endif for Nest Type */
+#endif /* not NDS32_SAVE_ALL_REGS */
+
+/*
+ This is 16-byte vector size version.
+ The vector id was restored into $r0 in vector by compiler.
+*/
+#ifdef NDS32_SAVE_ALL_REGS
+ SAVE_ALL
+#else
+ SAVE_PARTIAL
+#endif
+ /* Prepare to call 2nd level handler. */
+ la $r2, _nds32_jmptbl_09 /* For zero-based vcetor id. */
+ lw $r2, [$r2 + $r0 << #2]
+ ADJ_INTR_LVL /* Adjust INTR level. $r3 is clobbered. */
+ jral $r2
+ /* Restore used registers. */
+#ifdef NDS32_SAVE_ALL_REGS
+ RESTORE_ALL
+#else
+ RESTORE_PARTIAL
+#endif
+ iret
+
+#ifdef NDS32_SAVE_ALL_REGS
+#if defined(NDS32_NESTED)
+ .size _nds32_i_sa_ns, .-_nds32_i_sa_ns
+#elif defined(NDS32_NESTED_READY)
+ .size _nds32_i_sa_nr, .-_nds32_i_sa_nr
+#else /* Not nested handler. */
+ .size _nds32_i_sa_nn, .-_nds32_i_sa_nn
+#endif /* endif for Nest Type */
+#else /* not NDS32_SAVE_ALL_REGS */
+#if defined(NDS32_NESTED)
+ .size _nds32_i_ps_ns, .-_nds32_i_ps_ns
+#elif defined(NDS32_NESTED_READY)
+ .size _nds32_i_ps_nr, .-_nds32_i_ps_nr
+#else /* Not nested handler. */
+ .size _nds32_i_ps_nn, .-_nds32_i_ps_nn
+#endif /* endif for Nest Type */
+#endif /* not NDS32_SAVE_ALL_REGS */
diff --git a/libgcc/config/nds32/isr-library/intr_isr_4b.S b/libgcc/config/nds32/isr-library/intr_isr_4b.S
new file mode 100644
index 00000000000..21e60e72ed7
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/intr_isr_4b.S
@@ -0,0 +1,134 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+#include "save_mac_regs.inc"
+#include "save_fpu_regs.inc"
+#include "save_fpu_regs_00.inc"
+#include "save_fpu_regs_01.inc"
+#include "save_fpu_regs_02.inc"
+#include "save_fpu_regs_03.inc"
+#include "save_all.inc"
+#include "save_partial.inc"
+#include "adj_intr_lvl.inc"
+#include "restore_mac_regs.inc"
+#include "restore_fpu_regs_00.inc"
+#include "restore_fpu_regs_01.inc"
+#include "restore_fpu_regs_02.inc"
+#include "restore_fpu_regs_03.inc"
+#include "restore_fpu_regs.inc"
+#include "restore_all.inc"
+#include "restore_partial.inc"
+ .section .nds32_isr, "ax" /* Put it in the section of 1st level handler. */
+ .align 1
+/*
+ First Level Handlers
+ 1. First Level Handlers are invokded in vector section via jump instruction
+ with specific names for different configurations.
+ 2. Naming Format: _nds32_e_SR_NT for exception handlers.
+ _nds32_i_SR_NT for interrupt handlers.
+ 2.1 All upper case letters are replaced with specific lower case letters encodings.
+ 2.2 SR: Saved Registers
+ sa: Save All regs (context)
+ ps: Partial Save (all caller-saved regs)
+ 2.3 NT: Nested Type
+ ns: nested
+ nn: not nested
+ nr: nested ready
+*/
+
+/*
+ This is 4-byte vector size version.
+ The "_4b" postfix was added for 4-byte version symbol.
+*/
+#ifdef NDS32_SAVE_ALL_REGS
+#if defined(NDS32_NESTED)
+ .globl _nds32_i_sa_ns_4b
+ .type _nds32_i_sa_ns_4b, @function
+_nds32_i_sa_ns_4b:
+#elif defined(NDS32_NESTED_READY)
+ .globl _nds32_i_sa_nr_4b
+ .type _nds32_i_sa_nr_4b, @function
+_nds32_i_sa_nr_4b:
+#else /* Not nested handler. */
+ .globl _nds32_i_sa_nn_4b
+ .type _nds32_i_sa_nn_4b, @function
+_nds32_i_sa_nn_4b:
+#endif /* endif for Nest Type */
+#else /* not NDS32_SAVE_ALL_REGS */
+#if defined(NDS32_NESTED)
+ .globl _nds32_i_ps_ns_4b
+ .type _nds32_i_ps_ns_4b, @function
+_nds32_i_ps_ns_4b:
+#elif defined(NDS32_NESTED_READY)
+ .globl _nds32_i_ps_nr_4b
+ .type _nds32_i_ps_nr_4b, @function
+_nds32_i_ps_nr_4b:
+#else /* Not nested handler. */
+ .globl _nds32_i_ps_nn_4b
+ .type _nds32_i_ps_nn_4b, @function
+_nds32_i_ps_nn_4b:
+#endif /* endif for Nest Type */
+#endif /* not NDS32_SAVE_ALL_REGS */
+
+/*
+ This is 4-byte vector size version.
+ The vector id was restored into $lp in vector by compiler.
+*/
+#ifdef NDS32_SAVE_ALL_REGS
+ SAVE_ALL_4B
+#else
+ SAVE_PARTIAL_4B
+#endif
+ /* Prepare to call 2nd level handler. */
+ la $r2, _nds32_jmptbl_00
+ lw $r2, [$r2 + $r0 << #2]
+ addi $r0, $r0, #-9 /* Make interrput vector id zero-based. */
+ ADJ_INTR_LVL /* Adjust INTR level. $r3 is clobbered. */
+ jral $r2
+ /* Restore used registers. */
+#ifdef NDS32_SAVE_ALL_REGS
+ RESTORE_ALL
+#else
+ RESTORE_PARTIAL
+#endif
+ iret
+
+#ifdef NDS32_SAVE_ALL_REGS
+#if defined(NDS32_NESTED)
+ .size _nds32_i_sa_ns_4b, .-_nds32_i_sa_ns_4b
+#elif defined(NDS32_NESTED_READY)
+ .size _nds32_i_sa_nr_4b, .-_nds32_i_sa_nr_4b
+#else /* Not nested handler. */
+ .size _nds32_i_sa_nn_4b, .-_nds32_i_sa_nn_4b
+#endif /* endif for Nest Type */
+#else /* not NDS32_SAVE_ALL_REGS */
+#if defined(NDS32_NESTED)
+ .size _nds32_i_ps_ns_4b, .-_nds32_i_ps_ns_4b
+#elif defined(NDS32_NESTED_READY)
+ .size _nds32_i_ps_nr_4b, .-_nds32_i_ps_nr_4b
+#else /* Not nested handler. */
+ .size _nds32_i_ps_nn_4b, .-_nds32_i_ps_nn_4b
+#endif /* endif for Nest Type */
+#endif /* not NDS32_SAVE_ALL_REGS */
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid00.S b/libgcc/config/nds32/isr-library/jmptbl_vid00.S
new file mode 100644
index 00000000000..f0ed85a8275
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid00.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.00, "a"
+ .align 2
+ .weak _nds32_jmptbl_00
+ .type _nds32_jmptbl_00, @object
+_nds32_jmptbl_00:
+ .word 0
+ .size _nds32_jmptbl_00, .-_nds32_jmptbl_00
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid01.S b/libgcc/config/nds32/isr-library/jmptbl_vid01.S
new file mode 100644
index 00000000000..4c6b9c1d73d
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid01.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.01, "a"
+ .align 2
+ .weak _nds32_jmptbl_01
+ .type _nds32_jmptbl_01, @object
+_nds32_jmptbl_01:
+ .word 0
+ .size _nds32_jmptbl_01, .-_nds32_jmptbl_01
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid02.S b/libgcc/config/nds32/isr-library/jmptbl_vid02.S
new file mode 100644
index 00000000000..83ba980ad36
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid02.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.02, "a"
+ .align 2
+ .weak _nds32_jmptbl_02
+ .type _nds32_jmptbl_02, @object
+_nds32_jmptbl_02:
+ .word 0
+ .size _nds32_jmptbl_02, .-_nds32_jmptbl_02
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid03.S b/libgcc/config/nds32/isr-library/jmptbl_vid03.S
new file mode 100644
index 00000000000..47f11a4b86a
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid03.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.03, "a"
+ .align 2
+ .weak _nds32_jmptbl_03
+ .type _nds32_jmptbl_03, @object
+_nds32_jmptbl_03:
+ .word 0
+ .size _nds32_jmptbl_03, .-_nds32_jmptbl_03
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid04.S b/libgcc/config/nds32/isr-library/jmptbl_vid04.S
new file mode 100644
index 00000000000..e3e7fb8c1da
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid04.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.04, "a"
+ .align 2
+ .weak _nds32_jmptbl_04
+ .type _nds32_jmptbl_04, @object
+_nds32_jmptbl_04:
+ .word 0
+ .size _nds32_jmptbl_04, .-_nds32_jmptbl_04
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid05.S b/libgcc/config/nds32/isr-library/jmptbl_vid05.S
new file mode 100644
index 00000000000..32fa7eafd7b
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid05.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.05, "a"
+ .align 2
+ .weak _nds32_jmptbl_05
+ .type _nds32_jmptbl_05, @object
+_nds32_jmptbl_05:
+ .word 0
+ .size _nds32_jmptbl_05, .-_nds32_jmptbl_05
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid06.S b/libgcc/config/nds32/isr-library/jmptbl_vid06.S
new file mode 100644
index 00000000000..df2d83acaa3
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid06.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.06, "a"
+ .align 2
+ .weak _nds32_jmptbl_06
+ .type _nds32_jmptbl_06, @object
+_nds32_jmptbl_06:
+ .word 0
+ .size _nds32_jmptbl_06, .-_nds32_jmptbl_06
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid07.S b/libgcc/config/nds32/isr-library/jmptbl_vid07.S
new file mode 100644
index 00000000000..0070f7f5ae8
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid07.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.07, "a"
+ .align 2
+ .weak _nds32_jmptbl_07
+ .type _nds32_jmptbl_07, @object
+_nds32_jmptbl_07:
+ .word 0
+ .size _nds32_jmptbl_07, .-_nds32_jmptbl_07
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid08.S b/libgcc/config/nds32/isr-library/jmptbl_vid08.S
new file mode 100644
index 00000000000..0b19e60b9df
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid08.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.08, "a"
+ .align 2
+ .weak _nds32_jmptbl_08
+ .type _nds32_jmptbl_08, @object
+_nds32_jmptbl_08:
+ .word 0
+ .size _nds32_jmptbl_08, .-_nds32_jmptbl_08
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid09.S b/libgcc/config/nds32/isr-library/jmptbl_vid09.S
new file mode 100644
index 00000000000..b0e216b7520
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid09.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.09, "a"
+ .align 2
+ .weak _nds32_jmptbl_09
+ .type _nds32_jmptbl_09, @object
+_nds32_jmptbl_09:
+ .word 0
+ .size _nds32_jmptbl_09, .-_nds32_jmptbl_09
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid10.S b/libgcc/config/nds32/isr-library/jmptbl_vid10.S
new file mode 100644
index 00000000000..bd378ed5f7a
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid10.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.10, "a"
+ .align 2
+ .weak _nds32_jmptbl_10
+ .type _nds32_jmptbl_10, @object
+_nds32_jmptbl_10:
+ .word 0
+ .size _nds32_jmptbl_10, .-_nds32_jmptbl_10
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid11.S b/libgcc/config/nds32/isr-library/jmptbl_vid11.S
new file mode 100644
index 00000000000..9648ef347f0
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid11.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.11, "a"
+ .align 2
+ .weak _nds32_jmptbl_11
+ .type _nds32_jmptbl_11, @object
+_nds32_jmptbl_11:
+ .word 0
+ .size _nds32_jmptbl_11, .-_nds32_jmptbl_11
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid12.S b/libgcc/config/nds32/isr-library/jmptbl_vid12.S
new file mode 100644
index 00000000000..0ab14e2249c
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid12.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.12, "a"
+ .align 2
+ .weak _nds32_jmptbl_12
+ .type _nds32_jmptbl_12, @object
+_nds32_jmptbl_12:
+ .word 0
+ .size _nds32_jmptbl_12, .-_nds32_jmptbl_12
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid13.S b/libgcc/config/nds32/isr-library/jmptbl_vid13.S
new file mode 100644
index 00000000000..31664689df4
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid13.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.13, "a"
+ .align 2
+ .weak _nds32_jmptbl_13
+ .type _nds32_jmptbl_13, @object
+_nds32_jmptbl_13:
+ .word 0
+ .size _nds32_jmptbl_13, .-_nds32_jmptbl_13
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid14.S b/libgcc/config/nds32/isr-library/jmptbl_vid14.S
new file mode 100644
index 00000000000..cb8d129d81f
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid14.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.14, "a"
+ .align 2
+ .weak _nds32_jmptbl_14
+ .type _nds32_jmptbl_14, @object
+_nds32_jmptbl_14:
+ .word 0
+ .size _nds32_jmptbl_14, .-_nds32_jmptbl_14
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid15.S b/libgcc/config/nds32/isr-library/jmptbl_vid15.S
new file mode 100644
index 00000000000..bac9bc98407
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid15.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.15, "a"
+ .align 2
+ .weak _nds32_jmptbl_15
+ .type _nds32_jmptbl_15, @object
+_nds32_jmptbl_15:
+ .word 0
+ .size _nds32_jmptbl_15, .-_nds32_jmptbl_15
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid16.S b/libgcc/config/nds32/isr-library/jmptbl_vid16.S
new file mode 100644
index 00000000000..9066f81cfde
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid16.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.16, "a"
+ .align 2
+ .weak _nds32_jmptbl_16
+ .type _nds32_jmptbl_16, @object
+_nds32_jmptbl_16:
+ .word 0
+ .size _nds32_jmptbl_16, .-_nds32_jmptbl_16
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid17.S b/libgcc/config/nds32/isr-library/jmptbl_vid17.S
new file mode 100644
index 00000000000..60a8ba9ac4d
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid17.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.17, "a"
+ .align 2
+ .weak _nds32_jmptbl_17
+ .type _nds32_jmptbl_17, @object
+_nds32_jmptbl_17:
+ .word 0
+ .size _nds32_jmptbl_17, .-_nds32_jmptbl_17
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid18.S b/libgcc/config/nds32/isr-library/jmptbl_vid18.S
new file mode 100644
index 00000000000..a926fecc0b6
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid18.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.18, "a"
+ .align 2
+ .weak _nds32_jmptbl_18
+ .type _nds32_jmptbl_18, @object
+_nds32_jmptbl_18:
+ .word 0
+ .size _nds32_jmptbl_18, .-_nds32_jmptbl_18
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid19.S b/libgcc/config/nds32/isr-library/jmptbl_vid19.S
new file mode 100644
index 00000000000..064ace009bb
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid19.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.19, "a"
+ .align 2
+ .weak _nds32_jmptbl_19
+ .type _nds32_jmptbl_19, @object
+_nds32_jmptbl_19:
+ .word 0
+ .size _nds32_jmptbl_19, .-_nds32_jmptbl_19
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid20.S b/libgcc/config/nds32/isr-library/jmptbl_vid20.S
new file mode 100644
index 00000000000..e75bc71fbb6
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid20.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.20, "a"
+ .align 2
+ .weak _nds32_jmptbl_20
+ .type _nds32_jmptbl_20, @object
+_nds32_jmptbl_20:
+ .word 0
+ .size _nds32_jmptbl_20, .-_nds32_jmptbl_20
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid21.S b/libgcc/config/nds32/isr-library/jmptbl_vid21.S
new file mode 100644
index 00000000000..0c3d2b871c7
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid21.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.21, "a"
+ .align 2
+ .weak _nds32_jmptbl_21
+ .type _nds32_jmptbl_21, @object
+_nds32_jmptbl_21:
+ .word 0
+ .size _nds32_jmptbl_21, .-_nds32_jmptbl_21
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid22.S b/libgcc/config/nds32/isr-library/jmptbl_vid22.S
new file mode 100644
index 00000000000..415bf9f75e8
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid22.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.22, "a"
+ .align 2
+ .weak _nds32_jmptbl_22
+ .type _nds32_jmptbl_22, @object
+_nds32_jmptbl_22:
+ .word 0
+ .size _nds32_jmptbl_22, .-_nds32_jmptbl_22
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid23.S b/libgcc/config/nds32/isr-library/jmptbl_vid23.S
new file mode 100644
index 00000000000..1efe31099c2
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid23.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.23, "a"
+ .align 2
+ .weak _nds32_jmptbl_23
+ .type _nds32_jmptbl_23, @object
+_nds32_jmptbl_23:
+ .word 0
+ .size _nds32_jmptbl_23, .-_nds32_jmptbl_23
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid24.S b/libgcc/config/nds32/isr-library/jmptbl_vid24.S
new file mode 100644
index 00000000000..bb27eaa0812
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid24.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.24, "a"
+ .align 2
+ .weak _nds32_jmptbl_24
+ .type _nds32_jmptbl_24, @object
+_nds32_jmptbl_24:
+ .word 0
+ .size _nds32_jmptbl_24, .-_nds32_jmptbl_24
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid25.S b/libgcc/config/nds32/isr-library/jmptbl_vid25.S
new file mode 100644
index 00000000000..ca64f8c8bad
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid25.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.25, "a"
+ .align 2
+ .weak _nds32_jmptbl_25
+ .type _nds32_jmptbl_25, @object
+_nds32_jmptbl_25:
+ .word 0
+ .size _nds32_jmptbl_25, .-_nds32_jmptbl_25
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid26.S b/libgcc/config/nds32/isr-library/jmptbl_vid26.S
new file mode 100644
index 00000000000..95feab094fd
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid26.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.26, "a"
+ .align 2
+ .weak _nds32_jmptbl_26
+ .type _nds32_jmptbl_26, @object
+_nds32_jmptbl_26:
+ .word 0
+ .size _nds32_jmptbl_26, .-_nds32_jmptbl_26
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid27.S b/libgcc/config/nds32/isr-library/jmptbl_vid27.S
new file mode 100644
index 00000000000..2bb9eabe6a4
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid27.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.27, "a"
+ .align 2
+ .weak _nds32_jmptbl_27
+ .type _nds32_jmptbl_27, @object
+_nds32_jmptbl_27:
+ .word 0
+ .size _nds32_jmptbl_27, .-_nds32_jmptbl_27
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid28.S b/libgcc/config/nds32/isr-library/jmptbl_vid28.S
new file mode 100644
index 00000000000..57772ba494d
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid28.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.28, "a"
+ .align 2
+ .weak _nds32_jmptbl_28
+ .type _nds32_jmptbl_28, @object
+_nds32_jmptbl_28:
+ .word 0
+ .size _nds32_jmptbl_28, .-_nds32_jmptbl_28
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid29.S b/libgcc/config/nds32/isr-library/jmptbl_vid29.S
new file mode 100644
index 00000000000..c69d7398eb1
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid29.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.29, "a"
+ .align 2
+ .weak _nds32_jmptbl_29
+ .type _nds32_jmptbl_29, @object
+_nds32_jmptbl_29:
+ .word 0
+ .size _nds32_jmptbl_29, .-_nds32_jmptbl_29
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid30.S b/libgcc/config/nds32/isr-library/jmptbl_vid30.S
new file mode 100644
index 00000000000..f739c5821d7
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid30.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.30, "a"
+ .align 2
+ .weak _nds32_jmptbl_30
+ .type _nds32_jmptbl_30, @object
+_nds32_jmptbl_30:
+ .word 0
+ .size _nds32_jmptbl_30, .-_nds32_jmptbl_30
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid31.S b/libgcc/config/nds32/isr-library/jmptbl_vid31.S
new file mode 100644
index 00000000000..4997f4e9cc8
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid31.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.31, "a"
+ .align 2
+ .weak _nds32_jmptbl_31
+ .type _nds32_jmptbl_31, @object
+_nds32_jmptbl_31:
+ .word 0
+ .size _nds32_jmptbl_31, .-_nds32_jmptbl_31
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid32.S b/libgcc/config/nds32/isr-library/jmptbl_vid32.S
new file mode 100644
index 00000000000..1cde3fab097
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid32.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.32, "a"
+ .align 2
+ .weak _nds32_jmptbl_32
+ .type _nds32_jmptbl_32, @object
+_nds32_jmptbl_32:
+ .word 0
+ .size _nds32_jmptbl_32, .-_nds32_jmptbl_32
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid33.S b/libgcc/config/nds32/isr-library/jmptbl_vid33.S
new file mode 100644
index 00000000000..84edda36751
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid33.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.33, "a"
+ .align 2
+ .weak _nds32_jmptbl_33
+ .type _nds32_jmptbl_33, @object
+_nds32_jmptbl_33:
+ .word 0
+ .size _nds32_jmptbl_33, .-_nds32_jmptbl_33
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid34.S b/libgcc/config/nds32/isr-library/jmptbl_vid34.S
new file mode 100644
index 00000000000..82dc9f1dc24
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid34.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.34, "a"
+ .align 2
+ .weak _nds32_jmptbl_34
+ .type _nds32_jmptbl_34, @object
+_nds32_jmptbl_34:
+ .word 0
+ .size _nds32_jmptbl_34, .-_nds32_jmptbl_34
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid35.S b/libgcc/config/nds32/isr-library/jmptbl_vid35.S
new file mode 100644
index 00000000000..c99fc6cd996
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid35.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.35, "a"
+ .align 2
+ .weak _nds32_jmptbl_35
+ .type _nds32_jmptbl_35, @object
+_nds32_jmptbl_35:
+ .word 0
+ .size _nds32_jmptbl_35, .-_nds32_jmptbl_35
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid36.S b/libgcc/config/nds32/isr-library/jmptbl_vid36.S
new file mode 100644
index 00000000000..9154d713c40
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid36.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.36, "a"
+ .align 2
+ .weak _nds32_jmptbl_36
+ .type _nds32_jmptbl_36, @object
+_nds32_jmptbl_36:
+ .word 0
+ .size _nds32_jmptbl_36, .-_nds32_jmptbl_36
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid37.S b/libgcc/config/nds32/isr-library/jmptbl_vid37.S
new file mode 100644
index 00000000000..1f3acfd2c49
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid37.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.37, "a"
+ .align 2
+ .weak _nds32_jmptbl_37
+ .type _nds32_jmptbl_37, @object
+_nds32_jmptbl_37:
+ .word 0
+ .size _nds32_jmptbl_37, .-_nds32_jmptbl_37
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid38.S b/libgcc/config/nds32/isr-library/jmptbl_vid38.S
new file mode 100644
index 00000000000..0ff99b02235
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid38.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.38, "a"
+ .align 2
+ .weak _nds32_jmptbl_38
+ .type _nds32_jmptbl_38, @object
+_nds32_jmptbl_38:
+ .word 0
+ .size _nds32_jmptbl_38, .-_nds32_jmptbl_38
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid39.S b/libgcc/config/nds32/isr-library/jmptbl_vid39.S
new file mode 100644
index 00000000000..3fe74367c46
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid39.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.39, "a"
+ .align 2
+ .weak _nds32_jmptbl_39
+ .type _nds32_jmptbl_39, @object
+_nds32_jmptbl_39:
+ .word 0
+ .size _nds32_jmptbl_39, .-_nds32_jmptbl_39
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid40.S b/libgcc/config/nds32/isr-library/jmptbl_vid40.S
new file mode 100644
index 00000000000..fcd05dc627d
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid40.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.40, "a"
+ .align 2
+ .weak _nds32_jmptbl_40
+ .type _nds32_jmptbl_40, @object
+_nds32_jmptbl_40:
+ .word 0
+ .size _nds32_jmptbl_40, .-_nds32_jmptbl_40
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid41.S b/libgcc/config/nds32/isr-library/jmptbl_vid41.S
new file mode 100644
index 00000000000..0ec546a7f5b
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid41.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.41, "a"
+ .align 2
+ .weak _nds32_jmptbl_41
+ .type _nds32_jmptbl_41, @object
+_nds32_jmptbl_41:
+ .word 0
+ .size _nds32_jmptbl_41, .-_nds32_jmptbl_41
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid42.S b/libgcc/config/nds32/isr-library/jmptbl_vid42.S
new file mode 100644
index 00000000000..761ef769089
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid42.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.42, "a"
+ .align 2
+ .weak _nds32_jmptbl_42
+ .type _nds32_jmptbl_42, @object
+_nds32_jmptbl_42:
+ .word 0
+ .size _nds32_jmptbl_42, .-_nds32_jmptbl_42
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid43.S b/libgcc/config/nds32/isr-library/jmptbl_vid43.S
new file mode 100644
index 00000000000..0b2fc0eeedd
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid43.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.43, "a"
+ .align 2
+ .weak _nds32_jmptbl_43
+ .type _nds32_jmptbl_43, @object
+_nds32_jmptbl_43:
+ .word 0
+ .size _nds32_jmptbl_43, .-_nds32_jmptbl_43
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid44.S b/libgcc/config/nds32/isr-library/jmptbl_vid44.S
new file mode 100644
index 00000000000..0fc7e7e1662
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid44.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.44, "a"
+ .align 2
+ .weak _nds32_jmptbl_44
+ .type _nds32_jmptbl_44, @object
+_nds32_jmptbl_44:
+ .word 0
+ .size _nds32_jmptbl_44, .-_nds32_jmptbl_44
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid45.S b/libgcc/config/nds32/isr-library/jmptbl_vid45.S
new file mode 100644
index 00000000000..725d14483bf
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid45.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.45, "a"
+ .align 2
+ .weak _nds32_jmptbl_45
+ .type _nds32_jmptbl_45, @object
+_nds32_jmptbl_45:
+ .word 0
+ .size _nds32_jmptbl_45, .-_nds32_jmptbl_45
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid46.S b/libgcc/config/nds32/isr-library/jmptbl_vid46.S
new file mode 100644
index 00000000000..6b4253ada9d
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid46.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.46, "a"
+ .align 2
+ .weak _nds32_jmptbl_46
+ .type _nds32_jmptbl_46, @object
+_nds32_jmptbl_46:
+ .word 0
+ .size _nds32_jmptbl_46, .-_nds32_jmptbl_46
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid47.S b/libgcc/config/nds32/isr-library/jmptbl_vid47.S
new file mode 100644
index 00000000000..460e8509bcc
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid47.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.47, "a"
+ .align 2
+ .weak _nds32_jmptbl_47
+ .type _nds32_jmptbl_47, @object
+_nds32_jmptbl_47:
+ .word 0
+ .size _nds32_jmptbl_47, .-_nds32_jmptbl_47
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid48.S b/libgcc/config/nds32/isr-library/jmptbl_vid48.S
new file mode 100644
index 00000000000..d481e50e290
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid48.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.48, "a"
+ .align 2
+ .weak _nds32_jmptbl_48
+ .type _nds32_jmptbl_48, @object
+_nds32_jmptbl_48:
+ .word 0
+ .size _nds32_jmptbl_48, .-_nds32_jmptbl_48
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid49.S b/libgcc/config/nds32/isr-library/jmptbl_vid49.S
new file mode 100644
index 00000000000..4cea0b7e434
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid49.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.49, "a"
+ .align 2
+ .weak _nds32_jmptbl_49
+ .type _nds32_jmptbl_49, @object
+_nds32_jmptbl_49:
+ .word 0
+ .size _nds32_jmptbl_49, .-_nds32_jmptbl_49
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid50.S b/libgcc/config/nds32/isr-library/jmptbl_vid50.S
new file mode 100644
index 00000000000..dd15a384570
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid50.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.50, "a"
+ .align 2
+ .weak _nds32_jmptbl_50
+ .type _nds32_jmptbl_50, @object
+_nds32_jmptbl_50:
+ .word 0
+ .size _nds32_jmptbl_50, .-_nds32_jmptbl_50
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid51.S b/libgcc/config/nds32/isr-library/jmptbl_vid51.S
new file mode 100644
index 00000000000..02cf8dfb2f5
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid51.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.51, "a"
+ .align 2
+ .weak _nds32_jmptbl_51
+ .type _nds32_jmptbl_51, @object
+_nds32_jmptbl_51:
+ .word 0
+ .size _nds32_jmptbl_51, .-_nds32_jmptbl_51
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid52.S b/libgcc/config/nds32/isr-library/jmptbl_vid52.S
new file mode 100644
index 00000000000..5bc784611dd
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid52.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.52, "a"
+ .align 2
+ .weak _nds32_jmptbl_52
+ .type _nds32_jmptbl_52, @object
+_nds32_jmptbl_52:
+ .word 0
+ .size _nds32_jmptbl_52, .-_nds32_jmptbl_52
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid53.S b/libgcc/config/nds32/isr-library/jmptbl_vid53.S
new file mode 100644
index 00000000000..94f0dabcb44
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid53.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.53, "a"
+ .align 2
+ .weak _nds32_jmptbl_53
+ .type _nds32_jmptbl_53, @object
+_nds32_jmptbl_53:
+ .word 0
+ .size _nds32_jmptbl_53, .-_nds32_jmptbl_53
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid54.S b/libgcc/config/nds32/isr-library/jmptbl_vid54.S
new file mode 100644
index 00000000000..f13d6895bed
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid54.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.54, "a"
+ .align 2
+ .weak _nds32_jmptbl_54
+ .type _nds32_jmptbl_54, @object
+_nds32_jmptbl_54:
+ .word 0
+ .size _nds32_jmptbl_54, .-_nds32_jmptbl_54
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid55.S b/libgcc/config/nds32/isr-library/jmptbl_vid55.S
new file mode 100644
index 00000000000..521af640669
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid55.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.55, "a"
+ .align 2
+ .weak _nds32_jmptbl_55
+ .type _nds32_jmptbl_55, @object
+_nds32_jmptbl_55:
+ .word 0
+ .size _nds32_jmptbl_55, .-_nds32_jmptbl_55
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid56.S b/libgcc/config/nds32/isr-library/jmptbl_vid56.S
new file mode 100644
index 00000000000..2c01ed2c341
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid56.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.56, "a"
+ .align 2
+ .weak _nds32_jmptbl_56
+ .type _nds32_jmptbl_56, @object
+_nds32_jmptbl_56:
+ .word 0
+ .size _nds32_jmptbl_56, .-_nds32_jmptbl_56
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid57.S b/libgcc/config/nds32/isr-library/jmptbl_vid57.S
new file mode 100644
index 00000000000..58d4c1d72b0
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid57.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.57, "a"
+ .align 2
+ .weak _nds32_jmptbl_57
+ .type _nds32_jmptbl_57, @object
+_nds32_jmptbl_57:
+ .word 0
+ .size _nds32_jmptbl_57, .-_nds32_jmptbl_57
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid58.S b/libgcc/config/nds32/isr-library/jmptbl_vid58.S
new file mode 100644
index 00000000000..ceb7711c3cf
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid58.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.58, "a"
+ .align 2
+ .weak _nds32_jmptbl_58
+ .type _nds32_jmptbl_58, @object
+_nds32_jmptbl_58:
+ .word 0
+ .size _nds32_jmptbl_58, .-_nds32_jmptbl_58
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid59.S b/libgcc/config/nds32/isr-library/jmptbl_vid59.S
new file mode 100644
index 00000000000..527a1f52be6
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid59.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.59, "a"
+ .align 2
+ .weak _nds32_jmptbl_59
+ .type _nds32_jmptbl_59, @object
+_nds32_jmptbl_59:
+ .word 0
+ .size _nds32_jmptbl_59, .-_nds32_jmptbl_59
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid60.S b/libgcc/config/nds32/isr-library/jmptbl_vid60.S
new file mode 100644
index 00000000000..eedd8b88807
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid60.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.60, "a"
+ .align 2
+ .weak _nds32_jmptbl_60
+ .type _nds32_jmptbl_60, @object
+_nds32_jmptbl_60:
+ .word 0
+ .size _nds32_jmptbl_60, .-_nds32_jmptbl_60
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid61.S b/libgcc/config/nds32/isr-library/jmptbl_vid61.S
new file mode 100644
index 00000000000..e9813128491
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid61.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.61, "a"
+ .align 2
+ .weak _nds32_jmptbl_61
+ .type _nds32_jmptbl_61, @object
+_nds32_jmptbl_61:
+ .word 0
+ .size _nds32_jmptbl_61, .-_nds32_jmptbl_61
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid62.S b/libgcc/config/nds32/isr-library/jmptbl_vid62.S
new file mode 100644
index 00000000000..ef66f2b7e07
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid62.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.62, "a"
+ .align 2
+ .weak _nds32_jmptbl_62
+ .type _nds32_jmptbl_62, @object
+_nds32_jmptbl_62:
+ .word 0
+ .size _nds32_jmptbl_62, .-_nds32_jmptbl_62
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid63.S b/libgcc/config/nds32/isr-library/jmptbl_vid63.S
new file mode 100644
index 00000000000..95e38ba5eb1
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid63.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.63, "a"
+ .align 2
+ .weak _nds32_jmptbl_63
+ .type _nds32_jmptbl_63, @object
+_nds32_jmptbl_63:
+ .word 0
+ .size _nds32_jmptbl_63, .-_nds32_jmptbl_63
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid64.S b/libgcc/config/nds32/isr-library/jmptbl_vid64.S
new file mode 100644
index 00000000000..f27b6df9439
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid64.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.64, "a"
+ .align 2
+ .weak _nds32_jmptbl_64
+ .type _nds32_jmptbl_64, @object
+_nds32_jmptbl_64:
+ .word 0
+ .size _nds32_jmptbl_64, .-_nds32_jmptbl_64
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid65.S b/libgcc/config/nds32/isr-library/jmptbl_vid65.S
new file mode 100644
index 00000000000..69d83c67467
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid65.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.65, "a"
+ .align 2
+ .weak _nds32_jmptbl_65
+ .type _nds32_jmptbl_65, @object
+_nds32_jmptbl_65:
+ .word 0
+ .size _nds32_jmptbl_65, .-_nds32_jmptbl_65
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid66.S b/libgcc/config/nds32/isr-library/jmptbl_vid66.S
new file mode 100644
index 00000000000..3474d05a5d9
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid66.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.66, "a"
+ .align 2
+ .weak _nds32_jmptbl_66
+ .type _nds32_jmptbl_66, @object
+_nds32_jmptbl_66:
+ .word 0
+ .size _nds32_jmptbl_66, .-_nds32_jmptbl_66
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid67.S b/libgcc/config/nds32/isr-library/jmptbl_vid67.S
new file mode 100644
index 00000000000..8bbb5163f69
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid67.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.67, "a"
+ .align 2
+ .weak _nds32_jmptbl_67
+ .type _nds32_jmptbl_67, @object
+_nds32_jmptbl_67:
+ .word 0
+ .size _nds32_jmptbl_67, .-_nds32_jmptbl_67
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid68.S b/libgcc/config/nds32/isr-library/jmptbl_vid68.S
new file mode 100644
index 00000000000..fc875055818
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid68.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.68, "a"
+ .align 2
+ .weak _nds32_jmptbl_68
+ .type _nds32_jmptbl_68, @object
+_nds32_jmptbl_68:
+ .word 0
+ .size _nds32_jmptbl_68, .-_nds32_jmptbl_68
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid69.S b/libgcc/config/nds32/isr-library/jmptbl_vid69.S
new file mode 100644
index 00000000000..78847706f51
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid69.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.69, "a"
+ .align 2
+ .weak _nds32_jmptbl_69
+ .type _nds32_jmptbl_69, @object
+_nds32_jmptbl_69:
+ .word 0
+ .size _nds32_jmptbl_69, .-_nds32_jmptbl_69
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid70.S b/libgcc/config/nds32/isr-library/jmptbl_vid70.S
new file mode 100644
index 00000000000..0f41e21d4db
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid70.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.70, "a"
+ .align 2
+ .weak _nds32_jmptbl_70
+ .type _nds32_jmptbl_70, @object
+_nds32_jmptbl_70:
+ .word 0
+ .size _nds32_jmptbl_70, .-_nds32_jmptbl_70
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid71.S b/libgcc/config/nds32/isr-library/jmptbl_vid71.S
new file mode 100644
index 00000000000..5aab1252e1b
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid71.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.71, "a"
+ .align 2
+ .weak _nds32_jmptbl_71
+ .type _nds32_jmptbl_71, @object
+_nds32_jmptbl_71:
+ .word 0
+ .size _nds32_jmptbl_71, .-_nds32_jmptbl_71
diff --git a/libgcc/config/nds32/isr-library/jmptbl_vid72.S b/libgcc/config/nds32/isr-library/jmptbl_vid72.S
new file mode 100644
index 00000000000..6d40bfffb75
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/jmptbl_vid72.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_jmptbl.72, "a"
+ .align 2
+ .weak _nds32_jmptbl_72
+ .type _nds32_jmptbl_72, @object
+_nds32_jmptbl_72:
+ .word 0
+ .size _nds32_jmptbl_72, .-_nds32_jmptbl_72
diff --git a/libgcc/config/nds32/isr-library/nmih.S b/libgcc/config/nds32/isr-library/nmih.S
new file mode 100644
index 00000000000..083ec98023c
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/nmih.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_nmih, "a"
+ .align 2
+ .weak _nds32_nmih
+ .type _nds32_nmih, @object
+_nds32_nmih:
+ .word 0
+ .size _nds32_nmih, .-_nds32_nmih
diff --git a/libgcc/config/nds32/isr-library/reset.S b/libgcc/config/nds32/isr-library/reset.S
new file mode 100644
index 00000000000..3f539de48ea
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/reset.S
@@ -0,0 +1,130 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_isr, "ax" /* Put it in the section of 1st level handler. */
+ .align 1
+ .weak _SDA_BASE_ /* For reset handler only. */
+ .weak _FP_BASE_ /* For reset handler only. */
+ .weak _nds32_init_mem /* User defined memory initialization function. */
+ .globl _start
+ .globl _nds32_reset
+ .type _nds32_reset, @function
+_nds32_reset:
+_start:
+#ifdef NDS32_EXT_EX9
+ .no_ex9_begin
+#endif
+ /* Handle NMI and warm boot if any of them exists. */
+ beqz $sp, 1f /* Reset, NMI or warm boot? */
+ /* Either NMI or warm boot; save all regs. */
+
+ /* Preserve registers for context-switching. */
+#ifdef __NDS32_REDUCED_REGS__
+ /* For 16-reg mode. */
+ smw.adm $r0, [$sp], $r10, #0x0
+ smw.adm $r15, [$sp], $r15, #0xf
+#else
+ /* For 32-reg mode. */
+ smw.adm $r0, [$sp], $r27, #0xf
+#endif
+#ifdef NDS32_EXT_IFC
+ mfusr $r1, $IFC_LP
+ smw.adm $r1, [$sp], $r2, #0x0 /* Save extra $r2 to keep
+ stack 8-byte alignment. */
+#endif
+
+ la $gp, _SDA_BASE_ /* Init GP for small data access. */
+ move $r0, $sp /* Init parameter. */
+ mfsr $r1, $ITYPE /* Check ITYPE for NMI or warm boot. */
+ andi $r1, $r1, #0xf
+ addi $r1, $r1, #-1
+ beqz $r1, 2f /* Warm boot if true. */
+ l.w $r15, _nds32_nmih /* Load NMI handler. */
+ j 3f
+2:
+ l.w $r15, _nds32_wrh /* Load warm boot handler. */
+3:
+ beqz $r15, 1f /* If no handler, do cold boot. */
+ jral $r15 /* Call handler. */
+ bnez $r0, 1f /* If fail to resume, do cold boot. */
+
+ /* Restore registers for context-switching. */
+#ifdef NDS32_EXT_IFC
+ lmw.bim $r1, [$sp], $r2, #0x0 /* Restore extra $r2 to keep
+ stack 8-byte alignment. */
+ mtusr $r1, $IFC_LP
+#endif
+#ifdef __NDS32_REDUCED_REGS__
+ /* For 16-reg mode. */
+ lmw.bim $r15, [$sp], $r15, #0xf
+ lmw.bim $r0, [$sp], $r10, #0x0
+#else
+ /* For 32-reg mode. */
+ lmw.bim $r0, [$sp], $r27, #0xf
+#endif
+ iret /* Resume operation. */
+
+
+1: /* Cold boot. */
+ /* Set IVB.ESZ = 1 (vector table entry size = 16 bytes) */
+ mfsr $r0, $IVB
+ li $r1, #0xffff3fff
+ and $r0, $r0, $r1
+ ori $r0, $r0, #0x4000
+ mtsr $r0, $IVB
+ dsb
+
+ la $gp, _SDA_BASE_ /* Init $gp. */
+ la $fp, _FP_BASE_ /* Init $fp. */
+ la $sp, _stack /* Init $sp. */
+#ifdef NDS32_EXT_EX9
+/*
+ * Initialize the table base of EX9 instruction
+ * ex9 generation needs to disable before the ITB is set
+ */
+ mfsr $r0, $MSC_CFG /* Check if HW support of EX9. */
+ srli $r0, $r0, 24
+ andi $r0, $r0, 0x1
+ beqz $r0, 4f /* Zero means HW does not support EX9. */
+ la $r0, _ITB_BASE_ /* Init $ITB. */
+ mtusr $r0, $ITB
+ .no_ex9_end
+4:
+#endif
+ la $r15, _nds32_init_mem /* Call DRAM init. _nds32_init_mem
+ may written by C language. */
+ beqz $r15, 6f
+ jral $r15
+6:
+ l.w $r15, _nds32_jmptbl_00 /* Load reset handler. */
+ jral $r15
+/* Reset handler() should never return in a RTOS or non-OS system.
+ In case it does return, an exception will be generated.
+ This exception will be caught either by default break handler or by EDM.
+ Default break handle may just do an infinite loop.
+ EDM will notify GDB and GDB will regain control when the ID is 0x7fff. */
+5:
+ break #0x7fff
+ .size _nds32_reset, .-_nds32_reset
diff --git a/libgcc/config/nds32/isr-library/reset_4b.S b/libgcc/config/nds32/isr-library/reset_4b.S
new file mode 100644
index 00000000000..23b821a1aaf
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/reset_4b.S
@@ -0,0 +1,131 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_isr, "ax" /* Put it in the section of 1st level handler. */
+ .align 1
+ .weak _SDA_BASE_ /* For reset handler only. */
+ .weak _FP_BASE_ /* For reset handler only. */
+ .weak _nds32_init_mem /* User defined memory initialization function. */
+ .globl _start
+ .globl _nds32_reset_4b
+ .type _nds32_reset_4b, @function
+_nds32_reset_4b:
+_start:
+#ifdef NDS32_EXT_EX9
+ .no_ex9_begin
+#endif
+ /* Handle NMI and warm boot if any of them exists. */
+ beqz $sp, 1f /* Reset, NMI or warm boot? */
+ /* Either NMI or warm boot; save all regs. */
+
+ /* Preserve registers for context-switching. */
+#ifdef __NDS32_REDUCED_REGS__
+ /* For 16-reg mode. */
+ smw.adm $r0, [$sp], $r10, #0x0
+ smw.adm $r15, [$sp], $r15, #0xf
+#else
+ /* For 32-reg mode. */
+ smw.adm $r0, [$sp], $r27, #0xf
+#endif
+#ifdef NDS32_EXT_IFC
+ mfusr $r1, $IFC_LP
+ smw.adm $r1, [$sp], $r2, #0x0 /* Save extra $r2 to keep
+ stack 8-byte alignment. */
+#endif
+
+ la $gp, _SDA_BASE_ /* Init GP for small data access. */
+ move $r0, $sp /* Init parameter. */
+ mfsr $r1, $ITYPE /* Check ITYPE for NMI or warm boot. */
+ andi $r1, $r1, #0xf
+ addi $r1, $r1, #-1
+ beqz $r1, 2f /* Warm boot if true. */
+ l.w $r15, _nds32_nmih /* Load NMI handler. */
+ j 3f
+2:
+ l.w $r15, _nds32_wrh /* Load warm boot handler. */
+3:
+ beqz $r15, 1f /* If no handler, do cold boot. */
+ jral $r15 /* Call handler. */
+ bnez $r0, 1f /* If fail to resume, do cold boot. */
+
+ /* Restore registers for context-switching. */
+#ifdef NDS32_EXT_IFC
+ lmw.bim $r1, [$sp], $r2, #0x0 /* Restore extra $r2 to keep
+ stack 8-byte alignment. */
+ mtusr $r1, $IFC_LP
+#endif
+#ifdef __NDS32_REDUCED_REGS__
+ /* For 16-reg mode. */
+ lmw.bim $r15, [$sp], $r15, #0xf
+ lmw.bim $r0, [$sp], $r10, #0x0
+#else
+ /* For 32-reg mode. */
+ lmw.bim $r0, [$sp], $r27, #0xf
+#endif
+ iret /* Resume operation. */
+
+
+1: /* Cold boot. */
+ /* With vector ID feature, set default vector size to 4B. */
+ /* Set IVB.ESZ = 0 (vector table entry size = 4 bytes) */
+ mfsr $r0, $IVB
+ li $r1, #0xc000
+ or $r0, $r0, $r1
+ xor $r0, $r0, $r1
+ mtsr $r0, $IVB
+ dsb
+
+ la $gp, _SDA_BASE_ /* Init $gp. */
+ la $fp, _FP_BASE_ /* Init $fp. */
+ la $sp, _stack /* Init $sp. */
+#ifdef NDS32_EXT_EX9
+/*
+ * Initialize the table base of EX9 instruction
+ * ex9 generation needs to disable before the ITB is set
+ */
+ mfsr $r0, $MSC_CFG /* Check if HW support of EX9. */
+ srli $r0, $r0, 24
+ andi $r0, $r0, 0x1
+ beqz $r0, 4f /* Zero means HW does not support EX9. */
+ la $r0, _ITB_BASE_ /* Init $ITB. */
+ mtusr $r0, $ITB
+ .no_ex9_end
+4:
+#endif
+ la $r15, _nds32_init_mem /* Call DRAM init. _nds32_init_mem
+ may written by C language. */
+ beqz $r15, 6f
+ jral $r15
+6:
+ l.w $r15, _nds32_jmptbl_00 /* Load reset handler. */
+ jral $r15
+/* Reset handler() should never return in a RTOS or non-OS system.
+ In case it does return, an exception will be generated.
+ This exception will be caught either by default break handler or by EDM.
+ Default break handle may just do an infinite loop.
+ EDM will notify GDB and GDB will regain control when the ID is 0x7fff. */
+5:
+ break #0x7fff
+ .size _nds32_reset_4b, .-_nds32_reset_4b
diff --git a/libgcc/config/nds32/isr-library/restore_all.inc b/libgcc/config/nds32/isr-library/restore_all.inc
new file mode 100644
index 00000000000..a0799540358
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/restore_all.inc
@@ -0,0 +1,45 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+.macro RESTORE_ALL
+ setgie.d
+ dsb
+ lmw.bim $r1, [$sp], $r2, #0x0 /* Restore IPC, IPSW. */
+ mtsr $r1, $IPC
+ mtsr $r2, $IPSW
+ RESTORE_FPU_REGS
+ RESTORE_MAC_REGS
+#ifdef NDS32_EXT_IFC
+ lmw.bim $r1, [$sp], $r2, #0x0 /* Restore extra $r2 to keep
+ stack 8-byte alignment. */
+ mtusr $r1, $IFC_LP
+#endif
+#ifdef __NDS32_REDUCED_REGS__
+ lmw.bim $r0, [$sp], $r10, #0x0 /* Restore all regs. */
+ lmw.bim $r15, [$sp], $r15, #0xf
+#else /* not __NDS32_REDUCED_REGS__ */
+ lmw.bim $r0, [$sp], $r27, #0xf /* Restore all regs. */
+#endif
+.endm
diff --git a/libgcc/config/nds32/isr-library/restore_fpu_regs.inc b/libgcc/config/nds32/isr-library/restore_fpu_regs.inc
new file mode 100644
index 00000000000..23a86c424a9
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/restore_fpu_regs.inc
@@ -0,0 +1,36 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+.macro RESTORE_FPU_REGS
+#if defined(NDS32_EXT_FPU_CONFIG_0)
+ RESTORE_FPU_REGS_00
+#elif defined(NDS32_EXT_FPU_CONFIG_1)
+ RESTORE_FPU_REGS_01
+#elif defined(NDS32_EXT_FPU_CONFIG_2)
+ RESTORE_FPU_REGS_02
+#elif defined(NDS32_EXT_FPU_CONFIG_3)
+ RESTORE_FPU_REGS_03
+#endif
+.endm
diff --git a/libgcc/config/nds32/isr-library/restore_fpu_regs_00.inc b/libgcc/config/nds32/isr-library/restore_fpu_regs_00.inc
new file mode 100644
index 00000000000..a90a368fecf
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/restore_fpu_regs_00.inc
@@ -0,0 +1,31 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+.macro RESTORE_FPU_REGS_00
+ fldi.bi $fd0, [$sp], #8
+ fldi.bi $fd1, [$sp], #8
+ fldi.bi $fd2, [$sp], #8
+ fldi.bi $fd3, [$sp], #8
+.endm
diff --git a/libgcc/config/nds32/isr-library/restore_fpu_regs_01.inc b/libgcc/config/nds32/isr-library/restore_fpu_regs_01.inc
new file mode 100644
index 00000000000..615e4530924
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/restore_fpu_regs_01.inc
@@ -0,0 +1,35 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+.macro RESTORE_FPU_REGS_01
+ fldi.bi $fd0, [$sp], #8
+ fldi.bi $fd1, [$sp], #8
+ fldi.bi $fd2, [$sp], #8
+ fldi.bi $fd3, [$sp], #8
+ fldi.bi $fd4, [$sp], #8
+ fldi.bi $fd5, [$sp], #8
+ fldi.bi $fd6, [$sp], #8
+ fldi.bi $fd7, [$sp], #8
+.endm
diff --git a/libgcc/config/nds32/isr-library/restore_fpu_regs_02.inc b/libgcc/config/nds32/isr-library/restore_fpu_regs_02.inc
new file mode 100644
index 00000000000..cfeed32451d
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/restore_fpu_regs_02.inc
@@ -0,0 +1,43 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+.macro RESTORE_FPU_REGS_02
+ fldi.bi $fd0, [$sp], 8
+ fldi.bi $fd1, [$sp], 8
+ fldi.bi $fd2, [$sp], 8
+ fldi.bi $fd3, [$sp], 8
+ fldi.bi $fd4, [$sp], 8
+ fldi.bi $fd5, [$sp], 8
+ fldi.bi $fd6, [$sp], 8
+ fldi.bi $fd7, [$sp], 8
+ fldi.bi $fd8, [$sp], 8
+ fldi.bi $fd9, [$sp], 8
+ fldi.bi $fd10, [$sp], 8
+ fldi.bi $fd11, [$sp], 8
+ fldi.bi $fd12, [$sp], 8
+ fldi.bi $fd13, [$sp], 8
+ fldi.bi $fd14, [$sp], 8
+ fldi.bi $fd15, [$sp], 8
+.endm
diff --git a/libgcc/config/nds32/isr-library/restore_fpu_regs_03.inc b/libgcc/config/nds32/isr-library/restore_fpu_regs_03.inc
new file mode 100644
index 00000000000..61391c91259
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/restore_fpu_regs_03.inc
@@ -0,0 +1,59 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+.macro RESTORE_FPU_REGS_03
+ fldi.bi $fd0, [$sp], #8
+ fldi.bi $fd1, [$sp], #8
+ fldi.bi $fd2, [$sp], #8
+ fldi.bi $fd3, [$sp], #8
+ fldi.bi $fd4, [$sp], #8
+ fldi.bi $fd5, [$sp], #8
+ fldi.bi $fd6, [$sp], #8
+ fldi.bi $fd7, [$sp], #8
+ fldi.bi $fd8, [$sp], #8
+ fldi.bi $fd9, [$sp], #8
+ fldi.bi $fd10, [$sp], #8
+ fldi.bi $fd11, [$sp], #8
+ fldi.bi $fd12, [$sp], #8
+ fldi.bi $fd13, [$sp], #8
+ fldi.bi $fd14, [$sp], #8
+ fldi.bi $fd15, [$sp], #8
+ fldi.bi $fd16, [$sp], #8
+ fldi.bi $fd17, [$sp], #8
+ fldi.bi $fd18, [$sp], #8
+ fldi.bi $fd19, [$sp], #8
+ fldi.bi $fd20, [$sp], #8
+ fldi.bi $fd21, [$sp], #8
+ fldi.bi $fd22, [$sp], #8
+ fldi.bi $fd23, [$sp], #8
+ fldi.bi $fd24, [$sp], #8
+ fldi.bi $fd25, [$sp], #8
+ fldi.bi $fd26, [$sp], #8
+ fldi.bi $fd27, [$sp], #8
+ fldi.bi $fd28, [$sp], #8
+ fldi.bi $fd29, [$sp], #8
+ fldi.bi $fd30, [$sp], #8
+ fldi.bi $fd31, [$sp], #8
+.endm
diff --git a/libgcc/config/nds32/isr-library/restore_mac_regs.inc b/libgcc/config/nds32/isr-library/restore_mac_regs.inc
new file mode 100644
index 00000000000..770817dd817
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/restore_mac_regs.inc
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+.macro RESTORE_MAC_REGS
+#ifdef NDS32_DX_REGS
+ lmw.bim $r1, [$sp], $r4, #0x0
+ mtusr $r1, $d0.lo
+ mtusr $r2, $d0.hi
+ mtusr $r3, $d1.lo
+ mtusr $r4, $d1.hi
+#endif
+.endm
diff --git a/libgcc/config/nds32/isr-library/restore_partial.inc b/libgcc/config/nds32/isr-library/restore_partial.inc
new file mode 100644
index 00000000000..eeb815f93d6
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/restore_partial.inc
@@ -0,0 +1,47 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+.macro RESTORE_PARTIAL
+#if defined(NDS32_NESTED) || defined(NDS32_NESTED_READY)
+ setgie.d
+ dsb
+ lmw.bim $r1, [$sp], $r2, #0x0 /* Restore IPC, IPSW. */
+ mtsr $r1, $IPC /* Set IPC. */
+ mtsr $r2, $IPSW /* Set IPSW. */
+#endif
+ RESTORE_FPU_REGS
+ RESTORE_MAC_REGS
+#ifdef NDS32_EXT_IFC
+ lmw.bim $r1, [$sp], $r2, #0x0 /* Restore extra $r2 to keep
+ stack 8-byte alignment. */
+ mtusr $r1, $IFC_LP
+#endif
+ lmw.bim $r0, [$sp], $r5, #0x0 /* Restore all regs. */
+#ifdef __NDS32_REDUCED_REGS__
+ lmw.bim $r15, [$sp], $r15, #0x2
+#else
+ lmw.bim $r15, [$sp], $r27, #0x2 /* Restore all regs. */
+#endif
+.endm
diff --git a/libgcc/config/nds32/isr-library/save_all.inc b/libgcc/config/nds32/isr-library/save_all.inc
new file mode 100644
index 00000000000..2ac053d71f8
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/save_all.inc
@@ -0,0 +1,67 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+.macro SAVE_ALL_4B
+#ifdef __NDS32_REDUCED_REGS__
+ smw.adm $r15, [$sp], $r15, #0xf
+ smw.adm $r0, [$sp], $r10, #0x0
+#else /* not __NDS32_REDUCED_REGS__ */
+ smw.adm $r0, [$sp], $r27, #0xf
+#endif /* not __NDS32_REDUCED_REGS__ */
+#ifdef NDS32_EXT_IFC
+ mfusr $r1, $IFC_LP
+ smw.adm $r1, [$sp], $r2, #0x0 /* Save extra $r2 to keep
+ stack 8-byte alignment. */
+#endif
+ SAVE_MAC_REGS
+ SAVE_FPU_REGS
+ mfsr $r1, $IPC /* Get IPC. */
+ mfsr $r2, $IPSW /* Get IPSW. */
+ smw.adm $r1, [$sp], $r2, #0x0 /* Push IPC, IPSW. */
+ move $r1, $sp /* $r1 is ptr to NDS32_CONTEXT. */
+ mfsr $r0, $ITYPE /* Get VID to $r0. */
+ srli $r0, $r0, #5
+#ifdef __NDS32_ISA_V2__
+ andi $r0, $r0, #127
+#else
+ fexti33 $r0, #6
+#endif
+.endm
+
+.macro SAVE_ALL
+/* SAVE_REG_TBL code has been moved to
+ vector table generated by compiler. */
+#ifdef NDS32_EXT_IFC
+ mfusr $r1, $IFC_LP
+ smw.adm $r1, [$sp], $r2, #0x0 /* Save extra $r2 to keep
+ stack 8-byte alignment. */
+#endif
+ SAVE_MAC_REGS
+ SAVE_FPU_REGS
+ mfsr $r1, $IPC /* Get IPC. */
+ mfsr $r2, $IPSW /* Get IPSW. */
+ smw.adm $r1, [$sp], $r2, #0x0 /* Push IPC, IPSW. */
+ move $r1, $sp /* $r1 is ptr to NDS32_CONTEXT. */
+.endm
diff --git a/libgcc/config/nds32/isr-library/save_fpu_regs.inc b/libgcc/config/nds32/isr-library/save_fpu_regs.inc
new file mode 100644
index 00000000000..be3a504e440
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/save_fpu_regs.inc
@@ -0,0 +1,36 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+.macro SAVE_FPU_REGS
+#if defined(NDS32_EXT_FPU_CONFIG_0)
+ SAVE_FPU_REGS_00
+#elif defined(NDS32_EXT_FPU_CONFIG_1)
+ SAVE_FPU_REGS_01
+#elif defined(NDS32_EXT_FPU_CONFIG_2)
+ SAVE_FPU_REGS_02
+#elif defined(NDS32_EXT_FPU_CONFIG_3)
+ SAVE_FPU_REGS_03
+#endif
+.endm
diff --git a/libgcc/config/nds32/isr-library/save_fpu_regs_00.inc b/libgcc/config/nds32/isr-library/save_fpu_regs_00.inc
new file mode 100644
index 00000000000..2514f59b90e
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/save_fpu_regs_00.inc
@@ -0,0 +1,33 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+.macro SAVE_FPU_REGS_00
+ addi $sp, $sp, #-8
+ fsdi.bi $fd3, [$sp], #-8
+ fsdi.bi $fd2, [$sp], #-8
+ fsdi.bi $fd1, [$sp], #-8
+ fsdi.bi $fd0, [$sp], #-8
+ addi $sp, $sp, #8
+.endm
diff --git a/libgcc/config/nds32/isr-library/save_fpu_regs_01.inc b/libgcc/config/nds32/isr-library/save_fpu_regs_01.inc
new file mode 100644
index 00000000000..1d605f2acdd
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/save_fpu_regs_01.inc
@@ -0,0 +1,37 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+.macro SAVE_FPU_REGS_01
+ addi $sp, $sp, #-8
+ fsdi.bi $fd7, [$sp], #-8
+ fsdi.bi $fd6, [$sp], #-8
+ fsdi.bi $fd5, [$sp], #-8
+ fsdi.bi $fd4, [$sp], #-8
+ fsdi.bi $fd3, [$sp], #-8
+ fsdi.bi $fd2, [$sp], #-8
+ fsdi.bi $fd1, [$sp], #-8
+ fsdi.bi $fd0, [$sp], #-8
+ addi $sp, $sp, #8
+.endm
diff --git a/libgcc/config/nds32/isr-library/save_fpu_regs_02.inc b/libgcc/config/nds32/isr-library/save_fpu_regs_02.inc
new file mode 100644
index 00000000000..30cb833ad0f
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/save_fpu_regs_02.inc
@@ -0,0 +1,45 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+.macro SAVE_FPU_REGS_02
+ addi $sp, $sp, #-8
+ fsdi.bi $fd15, [$sp], #-8
+ fsdi.bi $fd14, [$sp], #-8
+ fsdi.bi $fd13, [$sp], #-8
+ fsdi.bi $fd12, [$sp], #-8
+ fsdi.bi $fd11, [$sp], #-8
+ fsdi.bi $fd10, [$sp], #-8
+ fsdi.bi $fd9, [$sp], #-8
+ fsdi.bi $fd8, [$sp], #-8
+ fsdi.bi $fd7, [$sp], #-8
+ fsdi.bi $fd6, [$sp], #-8
+ fsdi.bi $fd5, [$sp], #-8
+ fsdi.bi $fd4, [$sp], #-8
+ fsdi.bi $fd3, [$sp], #-8
+ fsdi.bi $fd2, [$sp], #-8
+ fsdi.bi $fd1, [$sp], #-8
+ fsdi.bi $fd0, [$sp], #-8
+ addi $sp, $sp, #8
+.endm
diff --git a/libgcc/config/nds32/isr-library/save_fpu_regs_03.inc b/libgcc/config/nds32/isr-library/save_fpu_regs_03.inc
new file mode 100644
index 00000000000..693e051a847
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/save_fpu_regs_03.inc
@@ -0,0 +1,61 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+.macro SAVE_FPU_REGS_03
+ addi $sp, $sp, #-8
+ fsdi.bi $fd31, [$sp], #-8
+ fsdi.bi $fd30, [$sp], #-8
+ fsdi.bi $fd29, [$sp], #-8
+ fsdi.bi $fd28, [$sp], #-8
+ fsdi.bi $fd27, [$sp], #-8
+ fsdi.bi $fd26, [$sp], #-8
+ fsdi.bi $fd25, [$sp], #-8
+ fsdi.bi $fd24, [$sp], #-8
+ fsdi.bi $fd23, [$sp], #-8
+ fsdi.bi $fd22, [$sp], #-8
+ fsdi.bi $fd21, [$sp], #-8
+ fsdi.bi $fd20, [$sp], #-8
+ fsdi.bi $fd19, [$sp], #-8
+ fsdi.bi $fd18, [$sp], #-8
+ fsdi.bi $fd17, [$sp], #-8
+ fsdi.bi $fd16, [$sp], #-8
+ fsdi.bi $fd15, [$sp], #-8
+ fsdi.bi $fd14, [$sp], #-8
+ fsdi.bi $fd13, [$sp], #-8
+ fsdi.bi $fd12, [$sp], #-8
+ fsdi.bi $fd11, [$sp], #-8
+ fsdi.bi $fd10, [$sp], #-8
+ fsdi.bi $fd9, [$sp], #-8
+ fsdi.bi $fd8, [$sp], #-8
+ fsdi.bi $fd7, [$sp], #-8
+ fsdi.bi $fd6, [$sp], #-8
+ fsdi.bi $fd5, [$sp], #-8
+ fsdi.bi $fd4, [$sp], #-8
+ fsdi.bi $fd3, [$sp], #-8
+ fsdi.bi $fd2, [$sp], #-8
+ fsdi.bi $fd1, [$sp], #-8
+ fsdi.bi $fd0, [$sp], #-8
+ addi $sp, $sp, #8
+.endm
diff --git a/libgcc/config/nds32/isr-library/save_mac_regs.inc b/libgcc/config/nds32/isr-library/save_mac_regs.inc
new file mode 100644
index 00000000000..14c1851736f
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/save_mac_regs.inc
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+.macro SAVE_MAC_REGS
+#ifdef NDS32_DX_REGS
+ mfusr $r1, $d0.lo
+ mfusr $r2, $d0.hi
+ mfusr $r3, $d1.lo
+ mfusr $r4, $d1.hi
+ smw.adm $r1, [$sp], $r4, #0x0
+#endif
+.endm
diff --git a/libgcc/config/nds32/isr-library/save_partial.inc b/libgcc/config/nds32/isr-library/save_partial.inc
new file mode 100644
index 00000000000..61df3966d1e
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/save_partial.inc
@@ -0,0 +1,69 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+.macro SAVE_PARTIAL_4B
+#ifdef __NDS32_REDUCED_REGS__
+ smw.adm $r15, [$sp], $r15, #0x2
+#else /* not __NDS32_REDUCED_REGS__ */
+ smw.adm $r15, [$sp], $r27, #0x2
+#endif /* not __NDS32_REDUCED_REGS__ */
+ smw.adm $r0, [$sp], $r5, #0x0
+#ifdef NDS32_EXT_IFC
+ mfusr $r1, $IFC_LP
+ smw.adm $r1, [$sp], $r2, #0x0 /* Save extra $r2 to keep
+ stack 8-byte alignment. */
+#endif
+ SAVE_MAC_REGS
+ SAVE_FPU_REGS
+#if defined(NDS32_NESTED) || defined(NDS32_NESTED_READY)
+ mfsr $r1, $IPC /* Get IPC. */
+ mfsr $r2, $IPSW /* Get IPSW. */
+ smw.adm $r1, [$sp], $r2, #0x0 /* Push IPC, IPSW. */
+#endif
+ mfsr $r0, $ITYPE /* Get VID to $r0. */
+ srli $r0, $r0, #5
+#ifdef __NDS32_ISA_V2__
+ andi $r0, $r0, #127
+#else
+ fexti33 $r0, #6
+#endif
+.endm
+
+.macro SAVE_PARTIAL
+/* SAVE_CALLER_REGS code has been moved to
+ vector table generated by compiler. */
+#ifdef NDS32_EXT_IFC
+ mfusr $r1, $IFC_LP
+ smw.adm $r1, [$sp], $r2, #0x0 /* Save extra $r2 to keep
+ stack 8-byte alignment. */
+#endif
+ SAVE_MAC_REGS
+ SAVE_FPU_REGS
+#if defined(NDS32_NESTED) || defined(NDS32_NESTED_READY)
+ mfsr $r1, $IPC /* Get IPC. */
+ mfsr $r2, $IPSW /* Get IPSW. */
+ smw.adm $r1, [$sp], $r2, #0x0 /* Push IPC, IPSW. */
+#endif
+.endm
diff --git a/libgcc/config/nds32/isr-library/vec_vid00.S b/libgcc/config/nds32/isr-library/vec_vid00.S
new file mode 100644
index 00000000000..cef2df23b21
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid00.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.00, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_00
+ .type _nds32_vector_00, @function
+_nds32_vector_00:
+1:
+ j 1b
+ .size _nds32_vector_00, .-_nds32_vector_00
diff --git a/libgcc/config/nds32/isr-library/vec_vid00_4b.S b/libgcc/config/nds32/isr-library/vec_vid00_4b.S
new file mode 100644
index 00000000000..957ac485e2a
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid00_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.00, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_00_4b
+ .type _nds32_vector_00_4b, @function
+_nds32_vector_00_4b:
+1:
+ j 1b
+ .size _nds32_vector_00_4b, .-_nds32_vector_00_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid01.S b/libgcc/config/nds32/isr-library/vec_vid01.S
new file mode 100644
index 00000000000..319d64bcd20
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid01.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.01, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_01
+ .type _nds32_vector_01, @function
+_nds32_vector_01:
+1:
+ j 1b
+ .size _nds32_vector_01, .-_nds32_vector_01
diff --git a/libgcc/config/nds32/isr-library/vec_vid01_4b.S b/libgcc/config/nds32/isr-library/vec_vid01_4b.S
new file mode 100644
index 00000000000..ad52fcb9cc1
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid01_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.01, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_01_4b
+ .type _nds32_vector_01_4b, @function
+_nds32_vector_01_4b:
+1:
+ j 1b
+ .size _nds32_vector_01_4b, .-_nds32_vector_01_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid02.S b/libgcc/config/nds32/isr-library/vec_vid02.S
new file mode 100644
index 00000000000..4c98c5cebb5
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid02.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.02, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_02
+ .type _nds32_vector_02, @function
+_nds32_vector_02:
+1:
+ j 1b
+ .size _nds32_vector_02, .-_nds32_vector_02
diff --git a/libgcc/config/nds32/isr-library/vec_vid02_4b.S b/libgcc/config/nds32/isr-library/vec_vid02_4b.S
new file mode 100644
index 00000000000..790356bc655
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid02_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.02, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_02_4b
+ .type _nds32_vector_02_4b, @function
+_nds32_vector_02_4b:
+1:
+ j 1b
+ .size _nds32_vector_02_4b, .-_nds32_vector_02_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid03.S b/libgcc/config/nds32/isr-library/vec_vid03.S
new file mode 100644
index 00000000000..7cca9aa7544
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid03.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.03, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_03
+ .type _nds32_vector_03, @function
+_nds32_vector_03:
+1:
+ j 1b
+ .size _nds32_vector_03, .-_nds32_vector_03
diff --git a/libgcc/config/nds32/isr-library/vec_vid03_4b.S b/libgcc/config/nds32/isr-library/vec_vid03_4b.S
new file mode 100644
index 00000000000..be756bf3d1d
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid03_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.03, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_03_4b
+ .type _nds32_vector_03_4b, @function
+_nds32_vector_03_4b:
+1:
+ j 1b
+ .size _nds32_vector_03_4b, .-_nds32_vector_03_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid04.S b/libgcc/config/nds32/isr-library/vec_vid04.S
new file mode 100644
index 00000000000..ec9ea16cc91
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid04.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.04, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_04
+ .type _nds32_vector_04, @function
+_nds32_vector_04:
+1:
+ j 1b
+ .size _nds32_vector_04, .-_nds32_vector_04
diff --git a/libgcc/config/nds32/isr-library/vec_vid04_4b.S b/libgcc/config/nds32/isr-library/vec_vid04_4b.S
new file mode 100644
index 00000000000..6883718814e
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid04_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.04, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_04_4b
+ .type _nds32_vector_04_4b, @function
+_nds32_vector_04_4b:
+1:
+ j 1b
+ .size _nds32_vector_04_4b, .-_nds32_vector_04_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid05.S b/libgcc/config/nds32/isr-library/vec_vid05.S
new file mode 100644
index 00000000000..38aa4d99d52
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid05.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.05, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_05
+ .type _nds32_vector_05, @function
+_nds32_vector_05:
+1:
+ j 1b
+ .size _nds32_vector_05, .-_nds32_vector_05
diff --git a/libgcc/config/nds32/isr-library/vec_vid05_4b.S b/libgcc/config/nds32/isr-library/vec_vid05_4b.S
new file mode 100644
index 00000000000..914287f69d4
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid05_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.05, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_05_4b
+ .type _nds32_vector_05_4b, @function
+_nds32_vector_05_4b:
+1:
+ j 1b
+ .size _nds32_vector_05_4b, .-_nds32_vector_05_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid06.S b/libgcc/config/nds32/isr-library/vec_vid06.S
new file mode 100644
index 00000000000..8b1bcfb7ee8
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid06.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.06, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_06
+ .type _nds32_vector_06, @function
+_nds32_vector_06:
+1:
+ j 1b
+ .size _nds32_vector_06, .-_nds32_vector_06
diff --git a/libgcc/config/nds32/isr-library/vec_vid06_4b.S b/libgcc/config/nds32/isr-library/vec_vid06_4b.S
new file mode 100644
index 00000000000..c0bd26e2e6e
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid06_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.06, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_06_4b
+ .type _nds32_vector_06_4b, @function
+_nds32_vector_06_4b:
+1:
+ j 1b
+ .size _nds32_vector_06_4b, .-_nds32_vector_06_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid07.S b/libgcc/config/nds32/isr-library/vec_vid07.S
new file mode 100644
index 00000000000..b708ada47e9
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid07.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.07, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_07
+ .type _nds32_vector_07, @function
+_nds32_vector_07:
+1:
+ j 1b
+ .size _nds32_vector_07, .-_nds32_vector_07
diff --git a/libgcc/config/nds32/isr-library/vec_vid07_4b.S b/libgcc/config/nds32/isr-library/vec_vid07_4b.S
new file mode 100644
index 00000000000..3532551ab5e
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid07_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.07, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_07_4b
+ .type _nds32_vector_07_4b, @function
+_nds32_vector_07_4b:
+1:
+ j 1b
+ .size _nds32_vector_07_4b, .-_nds32_vector_07_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid08.S b/libgcc/config/nds32/isr-library/vec_vid08.S
new file mode 100644
index 00000000000..3afb6e6cb1d
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid08.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.08, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_08
+ .type _nds32_vector_08, @function
+_nds32_vector_08:
+1:
+ j 1b
+ .size _nds32_vector_08, .-_nds32_vector_08
diff --git a/libgcc/config/nds32/isr-library/vec_vid08_4b.S b/libgcc/config/nds32/isr-library/vec_vid08_4b.S
new file mode 100644
index 00000000000..0493fefde64
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid08_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.08, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_08_4b
+ .type _nds32_vector_08_4b, @function
+_nds32_vector_08_4b:
+1:
+ j 1b
+ .size _nds32_vector_08_4b, .-_nds32_vector_08_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid09.S b/libgcc/config/nds32/isr-library/vec_vid09.S
new file mode 100644
index 00000000000..35747ec212d
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid09.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.09, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_09
+ .type _nds32_vector_09, @function
+_nds32_vector_09:
+1:
+ j 1b
+ .size _nds32_vector_09, .-_nds32_vector_09
diff --git a/libgcc/config/nds32/isr-library/vec_vid09_4b.S b/libgcc/config/nds32/isr-library/vec_vid09_4b.S
new file mode 100644
index 00000000000..d44f9b22ac0
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid09_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.09, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_09_4b
+ .type _nds32_vector_09_4b, @function
+_nds32_vector_09_4b:
+1:
+ j 1b
+ .size _nds32_vector_09_4b, .-_nds32_vector_09_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid10.S b/libgcc/config/nds32/isr-library/vec_vid10.S
new file mode 100644
index 00000000000..71ab8ac056b
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid10.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.10, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_10
+ .type _nds32_vector_10, @function
+_nds32_vector_10:
+1:
+ j 1b
+ .size _nds32_vector_10, .-_nds32_vector_10
diff --git a/libgcc/config/nds32/isr-library/vec_vid10_4b.S b/libgcc/config/nds32/isr-library/vec_vid10_4b.S
new file mode 100644
index 00000000000..49fd669f10d
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid10_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.10, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_10_4b
+ .type _nds32_vector_10_4b, @function
+_nds32_vector_10_4b:
+1:
+ j 1b
+ .size _nds32_vector_10_4b, .-_nds32_vector_10_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid11.S b/libgcc/config/nds32/isr-library/vec_vid11.S
new file mode 100644
index 00000000000..732559d17e2
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid11.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.11, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_11
+ .type _nds32_vector_11, @function
+_nds32_vector_11:
+1:
+ j 1b
+ .size _nds32_vector_11, .-_nds32_vector_11
diff --git a/libgcc/config/nds32/isr-library/vec_vid11_4b.S b/libgcc/config/nds32/isr-library/vec_vid11_4b.S
new file mode 100644
index 00000000000..e878e36c947
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid11_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.11, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_11_4b
+ .type _nds32_vector_11_4b, @function
+_nds32_vector_11_4b:
+1:
+ j 1b
+ .size _nds32_vector_11_4b, .-_nds32_vector_11_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid12.S b/libgcc/config/nds32/isr-library/vec_vid12.S
new file mode 100644
index 00000000000..5d78fbb2e68
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid12.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.12, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_12
+ .type _nds32_vector_12, @function
+_nds32_vector_12:
+1:
+ j 1b
+ .size _nds32_vector_12, .-_nds32_vector_12
diff --git a/libgcc/config/nds32/isr-library/vec_vid12_4b.S b/libgcc/config/nds32/isr-library/vec_vid12_4b.S
new file mode 100644
index 00000000000..a03e8d89b6d
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid12_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.12, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_12_4b
+ .type _nds32_vector_12_4b, @function
+_nds32_vector_12_4b:
+1:
+ j 1b
+ .size _nds32_vector_12_4b, .-_nds32_vector_12_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid13.S b/libgcc/config/nds32/isr-library/vec_vid13.S
new file mode 100644
index 00000000000..3df6a1e4299
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid13.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.13, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_13
+ .type _nds32_vector_13, @function
+_nds32_vector_13:
+1:
+ j 1b
+ .size _nds32_vector_13, .-_nds32_vector_13
diff --git a/libgcc/config/nds32/isr-library/vec_vid13_4b.S b/libgcc/config/nds32/isr-library/vec_vid13_4b.S
new file mode 100644
index 00000000000..2117edb43ce
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid13_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.13, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_13_4b
+ .type _nds32_vector_13_4b, @function
+_nds32_vector_13_4b:
+1:
+ j 1b
+ .size _nds32_vector_13_4b, .-_nds32_vector_13_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid14.S b/libgcc/config/nds32/isr-library/vec_vid14.S
new file mode 100644
index 00000000000..8a554bebad9
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid14.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.14, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_14
+ .type _nds32_vector_14, @function
+_nds32_vector_14:
+1:
+ j 1b
+ .size _nds32_vector_14, .-_nds32_vector_14
diff --git a/libgcc/config/nds32/isr-library/vec_vid14_4b.S b/libgcc/config/nds32/isr-library/vec_vid14_4b.S
new file mode 100644
index 00000000000..1c5bf2dbdaa
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid14_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.14, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_14_4b
+ .type _nds32_vector_14_4b, @function
+_nds32_vector_14_4b:
+1:
+ j 1b
+ .size _nds32_vector_14_4b, .-_nds32_vector_14_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid15.S b/libgcc/config/nds32/isr-library/vec_vid15.S
new file mode 100644
index 00000000000..1d49d62f42f
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid15.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.15, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_15
+ .type _nds32_vector_15, @function
+_nds32_vector_15:
+1:
+ j 1b
+ .size _nds32_vector_15, .-_nds32_vector_15
diff --git a/libgcc/config/nds32/isr-library/vec_vid15_4b.S b/libgcc/config/nds32/isr-library/vec_vid15_4b.S
new file mode 100644
index 00000000000..ffa8ea9aec8
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid15_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.15, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_15_4b
+ .type _nds32_vector_15_4b, @function
+_nds32_vector_15_4b:
+1:
+ j 1b
+ .size _nds32_vector_15_4b, .-_nds32_vector_15_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid16.S b/libgcc/config/nds32/isr-library/vec_vid16.S
new file mode 100644
index 00000000000..70d6ab36592
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid16.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.16, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_16
+ .type _nds32_vector_16, @function
+_nds32_vector_16:
+1:
+ j 1b
+ .size _nds32_vector_16, .-_nds32_vector_16
diff --git a/libgcc/config/nds32/isr-library/vec_vid16_4b.S b/libgcc/config/nds32/isr-library/vec_vid16_4b.S
new file mode 100644
index 00000000000..133fe6a2123
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid16_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.16, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_16_4b
+ .type _nds32_vector_16_4b, @function
+_nds32_vector_16_4b:
+1:
+ j 1b
+ .size _nds32_vector_16_4b, .-_nds32_vector_16_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid17.S b/libgcc/config/nds32/isr-library/vec_vid17.S
new file mode 100644
index 00000000000..8eb871eb7f5
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid17.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.17, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_17
+ .type _nds32_vector_17, @function
+_nds32_vector_17:
+1:
+ j 1b
+ .size _nds32_vector_17, .-_nds32_vector_17
diff --git a/libgcc/config/nds32/isr-library/vec_vid17_4b.S b/libgcc/config/nds32/isr-library/vec_vid17_4b.S
new file mode 100644
index 00000000000..e10e7d65963
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid17_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.17, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_17_4b
+ .type _nds32_vector_17_4b, @function
+_nds32_vector_17_4b:
+1:
+ j 1b
+ .size _nds32_vector_17_4b, .-_nds32_vector_17_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid18.S b/libgcc/config/nds32/isr-library/vec_vid18.S
new file mode 100644
index 00000000000..3699454153e
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid18.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.18, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_18
+ .type _nds32_vector_18, @function
+_nds32_vector_18:
+1:
+ j 1b
+ .size _nds32_vector_18, .-_nds32_vector_18
diff --git a/libgcc/config/nds32/isr-library/vec_vid18_4b.S b/libgcc/config/nds32/isr-library/vec_vid18_4b.S
new file mode 100644
index 00000000000..e52910210a8
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid18_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.18, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_18_4b
+ .type _nds32_vector_18_4b, @function
+_nds32_vector_18_4b:
+1:
+ j 1b
+ .size _nds32_vector_18_4b, .-_nds32_vector_18_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid19.S b/libgcc/config/nds32/isr-library/vec_vid19.S
new file mode 100644
index 00000000000..b572bf9516a
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid19.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.19, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_19
+ .type _nds32_vector_19, @function
+_nds32_vector_19:
+1:
+ j 1b
+ .size _nds32_vector_19, .-_nds32_vector_19
diff --git a/libgcc/config/nds32/isr-library/vec_vid19_4b.S b/libgcc/config/nds32/isr-library/vec_vid19_4b.S
new file mode 100644
index 00000000000..49462674f2a
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid19_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.19, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_19_4b
+ .type _nds32_vector_19_4b, @function
+_nds32_vector_19_4b:
+1:
+ j 1b
+ .size _nds32_vector_19_4b, .-_nds32_vector_19_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid20.S b/libgcc/config/nds32/isr-library/vec_vid20.S
new file mode 100644
index 00000000000..c8fa4194cfc
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid20.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.20, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_20
+ .type _nds32_vector_20, @function
+_nds32_vector_20:
+1:
+ j 1b
+ .size _nds32_vector_20, .-_nds32_vector_20
diff --git a/libgcc/config/nds32/isr-library/vec_vid20_4b.S b/libgcc/config/nds32/isr-library/vec_vid20_4b.S
new file mode 100644
index 00000000000..95ab9170308
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid20_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.20, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_20_4b
+ .type _nds32_vector_20_4b, @function
+_nds32_vector_20_4b:
+1:
+ j 1b
+ .size _nds32_vector_20_4b, .-_nds32_vector_20_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid21.S b/libgcc/config/nds32/isr-library/vec_vid21.S
new file mode 100644
index 00000000000..8fc8cc706b7
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid21.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.21, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_21
+ .type _nds32_vector_21, @function
+_nds32_vector_21:
+1:
+ j 1b
+ .size _nds32_vector_21, .-_nds32_vector_21
diff --git a/libgcc/config/nds32/isr-library/vec_vid21_4b.S b/libgcc/config/nds32/isr-library/vec_vid21_4b.S
new file mode 100644
index 00000000000..33956bbbc33
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid21_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.21, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_21_4b
+ .type _nds32_vector_21_4b, @function
+_nds32_vector_21_4b:
+1:
+ j 1b
+ .size _nds32_vector_21_4b, .-_nds32_vector_21_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid22.S b/libgcc/config/nds32/isr-library/vec_vid22.S
new file mode 100644
index 00000000000..8e71ecb856a
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid22.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.22, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_22
+ .type _nds32_vector_22, @function
+_nds32_vector_22:
+1:
+ j 1b
+ .size _nds32_vector_22, .-_nds32_vector_22
diff --git a/libgcc/config/nds32/isr-library/vec_vid22_4b.S b/libgcc/config/nds32/isr-library/vec_vid22_4b.S
new file mode 100644
index 00000000000..5ecd38261e7
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid22_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.22, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_22_4b
+ .type _nds32_vector_22_4b, @function
+_nds32_vector_22_4b:
+1:
+ j 1b
+ .size _nds32_vector_22_4b, .-_nds32_vector_22_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid23.S b/libgcc/config/nds32/isr-library/vec_vid23.S
new file mode 100644
index 00000000000..c9f2ae3bfb9
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid23.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.23, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_23
+ .type _nds32_vector_23, @function
+_nds32_vector_23:
+1:
+ j 1b
+ .size _nds32_vector_23, .-_nds32_vector_23
diff --git a/libgcc/config/nds32/isr-library/vec_vid23_4b.S b/libgcc/config/nds32/isr-library/vec_vid23_4b.S
new file mode 100644
index 00000000000..eb7ea1f15ee
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid23_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.23, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_23_4b
+ .type _nds32_vector_23_4b, @function
+_nds32_vector_23_4b:
+1:
+ j 1b
+ .size _nds32_vector_23_4b, .-_nds32_vector_23_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid24.S b/libgcc/config/nds32/isr-library/vec_vid24.S
new file mode 100644
index 00000000000..dc16e56267d
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid24.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.24, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_24
+ .type _nds32_vector_24, @function
+_nds32_vector_24:
+1:
+ j 1b
+ .size _nds32_vector_24, .-_nds32_vector_24
diff --git a/libgcc/config/nds32/isr-library/vec_vid24_4b.S b/libgcc/config/nds32/isr-library/vec_vid24_4b.S
new file mode 100644
index 00000000000..023cee9e83a
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid24_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.24, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_24_4b
+ .type _nds32_vector_24_4b, @function
+_nds32_vector_24_4b:
+1:
+ j 1b
+ .size _nds32_vector_24_4b, .-_nds32_vector_24_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid25.S b/libgcc/config/nds32/isr-library/vec_vid25.S
new file mode 100644
index 00000000000..cc0c0623150
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid25.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.25, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_25
+ .type _nds32_vector_25, @function
+_nds32_vector_25:
+1:
+ j 1b
+ .size _nds32_vector_25, .-_nds32_vector_25
diff --git a/libgcc/config/nds32/isr-library/vec_vid25_4b.S b/libgcc/config/nds32/isr-library/vec_vid25_4b.S
new file mode 100644
index 00000000000..f9c747829c2
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid25_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.25, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_25_4b
+ .type _nds32_vector_25_4b, @function
+_nds32_vector_25_4b:
+1:
+ j 1b
+ .size _nds32_vector_25_4b, .-_nds32_vector_25_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid26.S b/libgcc/config/nds32/isr-library/vec_vid26.S
new file mode 100644
index 00000000000..8afb5f78850
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid26.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.26, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_26
+ .type _nds32_vector_26, @function
+_nds32_vector_26:
+1:
+ j 1b
+ .size _nds32_vector_26, .-_nds32_vector_26
diff --git a/libgcc/config/nds32/isr-library/vec_vid26_4b.S b/libgcc/config/nds32/isr-library/vec_vid26_4b.S
new file mode 100644
index 00000000000..51aea6c5ffb
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid26_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.26, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_26_4b
+ .type _nds32_vector_26_4b, @function
+_nds32_vector_26_4b:
+1:
+ j 1b
+ .size _nds32_vector_26_4b, .-_nds32_vector_26_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid27.S b/libgcc/config/nds32/isr-library/vec_vid27.S
new file mode 100644
index 00000000000..5babf0761c5
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid27.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.27, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_27
+ .type _nds32_vector_27, @function
+_nds32_vector_27:
+1:
+ j 1b
+ .size _nds32_vector_27, .-_nds32_vector_27
diff --git a/libgcc/config/nds32/isr-library/vec_vid27_4b.S b/libgcc/config/nds32/isr-library/vec_vid27_4b.S
new file mode 100644
index 00000000000..7a6e8705f0f
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid27_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.27, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_27_4b
+ .type _nds32_vector_27_4b, @function
+_nds32_vector_27_4b:
+1:
+ j 1b
+ .size _nds32_vector_27_4b, .-_nds32_vector_27_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid28.S b/libgcc/config/nds32/isr-library/vec_vid28.S
new file mode 100644
index 00000000000..3600b9c1738
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid28.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.28, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_28
+ .type _nds32_vector_28, @function
+_nds32_vector_28:
+1:
+ j 1b
+ .size _nds32_vector_28, .-_nds32_vector_28
diff --git a/libgcc/config/nds32/isr-library/vec_vid28_4b.S b/libgcc/config/nds32/isr-library/vec_vid28_4b.S
new file mode 100644
index 00000000000..5c752956269
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid28_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.28, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_28_4b
+ .type _nds32_vector_28_4b, @function
+_nds32_vector_28_4b:
+1:
+ j 1b
+ .size _nds32_vector_28_4b, .-_nds32_vector_28_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid29.S b/libgcc/config/nds32/isr-library/vec_vid29.S
new file mode 100644
index 00000000000..02f8e9ceb62
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid29.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.29, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_29
+ .type _nds32_vector_29, @function
+_nds32_vector_29:
+1:
+ j 1b
+ .size _nds32_vector_29, .-_nds32_vector_29
diff --git a/libgcc/config/nds32/isr-library/vec_vid29_4b.S b/libgcc/config/nds32/isr-library/vec_vid29_4b.S
new file mode 100644
index 00000000000..48412f0c6b9
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid29_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.29, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_29_4b
+ .type _nds32_vector_29_4b, @function
+_nds32_vector_29_4b:
+1:
+ j 1b
+ .size _nds32_vector_29_4b, .-_nds32_vector_29_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid30.S b/libgcc/config/nds32/isr-library/vec_vid30.S
new file mode 100644
index 00000000000..e08d7e8be0f
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid30.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.30, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_30
+ .type _nds32_vector_30, @function
+_nds32_vector_30:
+1:
+ j 1b
+ .size _nds32_vector_30, .-_nds32_vector_30
diff --git a/libgcc/config/nds32/isr-library/vec_vid30_4b.S b/libgcc/config/nds32/isr-library/vec_vid30_4b.S
new file mode 100644
index 00000000000..36265727377
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid30_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.30, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_30_4b
+ .type _nds32_vector_30_4b, @function
+_nds32_vector_30_4b:
+1:
+ j 1b
+ .size _nds32_vector_30_4b, .-_nds32_vector_30_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid31.S b/libgcc/config/nds32/isr-library/vec_vid31.S
new file mode 100644
index 00000000000..b6aba1d2c40
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid31.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.31, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_31
+ .type _nds32_vector_31, @function
+_nds32_vector_31:
+1:
+ j 1b
+ .size _nds32_vector_31, .-_nds32_vector_31
diff --git a/libgcc/config/nds32/isr-library/vec_vid31_4b.S b/libgcc/config/nds32/isr-library/vec_vid31_4b.S
new file mode 100644
index 00000000000..460bf5266da
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid31_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.31, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_31_4b
+ .type _nds32_vector_31_4b, @function
+_nds32_vector_31_4b:
+1:
+ j 1b
+ .size _nds32_vector_31_4b, .-_nds32_vector_31_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid32.S b/libgcc/config/nds32/isr-library/vec_vid32.S
new file mode 100644
index 00000000000..278e191b43e
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid32.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.32, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_32
+ .type _nds32_vector_32, @function
+_nds32_vector_32:
+1:
+ j 1b
+ .size _nds32_vector_32, .-_nds32_vector_32
diff --git a/libgcc/config/nds32/isr-library/vec_vid32_4b.S b/libgcc/config/nds32/isr-library/vec_vid32_4b.S
new file mode 100644
index 00000000000..d3b74f8129c
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid32_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.32, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_32_4b
+ .type _nds32_vector_32_4b, @function
+_nds32_vector_32_4b:
+1:
+ j 1b
+ .size _nds32_vector_32_4b, .-_nds32_vector_32_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid33.S b/libgcc/config/nds32/isr-library/vec_vid33.S
new file mode 100644
index 00000000000..320289db05e
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid33.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.33, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_33
+ .type _nds32_vector_33, @function
+_nds32_vector_33:
+1:
+ j 1b
+ .size _nds32_vector_33, .-_nds32_vector_33
diff --git a/libgcc/config/nds32/isr-library/vec_vid33_4b.S b/libgcc/config/nds32/isr-library/vec_vid33_4b.S
new file mode 100644
index 00000000000..fd3c997697e
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid33_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.33, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_33_4b
+ .type _nds32_vector_33_4b, @function
+_nds32_vector_33_4b:
+1:
+ j 1b
+ .size _nds32_vector_33_4b, .-_nds32_vector_33_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid34.S b/libgcc/config/nds32/isr-library/vec_vid34.S
new file mode 100644
index 00000000000..b9a99893386
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid34.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.34, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_34
+ .type _nds32_vector_34, @function
+_nds32_vector_34:
+1:
+ j 1b
+ .size _nds32_vector_34, .-_nds32_vector_34
diff --git a/libgcc/config/nds32/isr-library/vec_vid34_4b.S b/libgcc/config/nds32/isr-library/vec_vid34_4b.S
new file mode 100644
index 00000000000..0b726f6790c
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid34_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.34, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_34_4b
+ .type _nds32_vector_34_4b, @function
+_nds32_vector_34_4b:
+1:
+ j 1b
+ .size _nds32_vector_34_4b, .-_nds32_vector_34_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid35.S b/libgcc/config/nds32/isr-library/vec_vid35.S
new file mode 100644
index 00000000000..e53017d88da
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid35.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.35, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_35
+ .type _nds32_vector_35, @function
+_nds32_vector_35:
+1:
+ j 1b
+ .size _nds32_vector_35, .-_nds32_vector_35
diff --git a/libgcc/config/nds32/isr-library/vec_vid35_4b.S b/libgcc/config/nds32/isr-library/vec_vid35_4b.S
new file mode 100644
index 00000000000..7ac998faa6d
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid35_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.35, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_35_4b
+ .type _nds32_vector_35_4b, @function
+_nds32_vector_35_4b:
+1:
+ j 1b
+ .size _nds32_vector_35_4b, .-_nds32_vector_35_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid36.S b/libgcc/config/nds32/isr-library/vec_vid36.S
new file mode 100644
index 00000000000..2d3779c9ef5
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid36.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.36, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_36
+ .type _nds32_vector_36, @function
+_nds32_vector_36:
+1:
+ j 1b
+ .size _nds32_vector_36, .-_nds32_vector_36
diff --git a/libgcc/config/nds32/isr-library/vec_vid36_4b.S b/libgcc/config/nds32/isr-library/vec_vid36_4b.S
new file mode 100644
index 00000000000..54230ac22b7
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid36_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.36, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_36_4b
+ .type _nds32_vector_36_4b, @function
+_nds32_vector_36_4b:
+1:
+ j 1b
+ .size _nds32_vector_36_4b, .-_nds32_vector_36_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid37.S b/libgcc/config/nds32/isr-library/vec_vid37.S
new file mode 100644
index 00000000000..1b4066f99d3
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid37.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.37, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_37
+ .type _nds32_vector_37, @function
+_nds32_vector_37:
+1:
+ j 1b
+ .size _nds32_vector_37, .-_nds32_vector_37
diff --git a/libgcc/config/nds32/isr-library/vec_vid37_4b.S b/libgcc/config/nds32/isr-library/vec_vid37_4b.S
new file mode 100644
index 00000000000..f3a50b2f60e
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid37_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.37, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_37_4b
+ .type _nds32_vector_37_4b, @function
+_nds32_vector_37_4b:
+1:
+ j 1b
+ .size _nds32_vector_37_4b, .-_nds32_vector_37_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid38.S b/libgcc/config/nds32/isr-library/vec_vid38.S
new file mode 100644
index 00000000000..d626d3c3703
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid38.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.38, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_38
+ .type _nds32_vector_38, @function
+_nds32_vector_38:
+1:
+ j 1b
+ .size _nds32_vector_38, .-_nds32_vector_38
diff --git a/libgcc/config/nds32/isr-library/vec_vid38_4b.S b/libgcc/config/nds32/isr-library/vec_vid38_4b.S
new file mode 100644
index 00000000000..677145fea4d
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid38_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.38, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_38_4b
+ .type _nds32_vector_38_4b, @function
+_nds32_vector_38_4b:
+1:
+ j 1b
+ .size _nds32_vector_38_4b, .-_nds32_vector_38_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid39.S b/libgcc/config/nds32/isr-library/vec_vid39.S
new file mode 100644
index 00000000000..bbb376378e0
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid39.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.39, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_39
+ .type _nds32_vector_39, @function
+_nds32_vector_39:
+1:
+ j 1b
+ .size _nds32_vector_39, .-_nds32_vector_39
diff --git a/libgcc/config/nds32/isr-library/vec_vid39_4b.S b/libgcc/config/nds32/isr-library/vec_vid39_4b.S
new file mode 100644
index 00000000000..b5cd07e6a6d
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid39_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.39, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_39_4b
+ .type _nds32_vector_39_4b, @function
+_nds32_vector_39_4b:
+1:
+ j 1b
+ .size _nds32_vector_39_4b, .-_nds32_vector_39_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid40.S b/libgcc/config/nds32/isr-library/vec_vid40.S
new file mode 100644
index 00000000000..48c2eea7537
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid40.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.40, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_40
+ .type _nds32_vector_40, @function
+_nds32_vector_40:
+1:
+ j 1b
+ .size _nds32_vector_40, .-_nds32_vector_40
diff --git a/libgcc/config/nds32/isr-library/vec_vid40_4b.S b/libgcc/config/nds32/isr-library/vec_vid40_4b.S
new file mode 100644
index 00000000000..201988c43db
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid40_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.40, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_40_4b
+ .type _nds32_vector_40_4b, @function
+_nds32_vector_40_4b:
+1:
+ j 1b
+ .size _nds32_vector_40_4b, .-_nds32_vector_40_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid41.S b/libgcc/config/nds32/isr-library/vec_vid41.S
new file mode 100644
index 00000000000..7be5dfdf55d
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid41.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.41, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_41
+ .type _nds32_vector_41, @function
+_nds32_vector_41:
+1:
+ j 1b
+ .size _nds32_vector_41, .-_nds32_vector_41
diff --git a/libgcc/config/nds32/isr-library/vec_vid41_4b.S b/libgcc/config/nds32/isr-library/vec_vid41_4b.S
new file mode 100644
index 00000000000..1b8b57132ea
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid41_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.41, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_41_4b
+ .type _nds32_vector_41_4b, @function
+_nds32_vector_41_4b:
+1:
+ j 1b
+ .size _nds32_vector_41_4b, .-_nds32_vector_41_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid42.S b/libgcc/config/nds32/isr-library/vec_vid42.S
new file mode 100644
index 00000000000..f16127ba843
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid42.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.42, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_42
+ .type _nds32_vector_42, @function
+_nds32_vector_42:
+1:
+ j 1b
+ .size _nds32_vector_42, .-_nds32_vector_42
diff --git a/libgcc/config/nds32/isr-library/vec_vid42_4b.S b/libgcc/config/nds32/isr-library/vec_vid42_4b.S
new file mode 100644
index 00000000000..9bf7a5dff32
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid42_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.42, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_42_4b
+ .type _nds32_vector_42_4b, @function
+_nds32_vector_42_4b:
+1:
+ j 1b
+ .size _nds32_vector_42_4b, .-_nds32_vector_42_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid43.S b/libgcc/config/nds32/isr-library/vec_vid43.S
new file mode 100644
index 00000000000..eecfa98e5c2
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid43.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.43, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_43
+ .type _nds32_vector_43, @function
+_nds32_vector_43:
+1:
+ j 1b
+ .size _nds32_vector_43, .-_nds32_vector_43
diff --git a/libgcc/config/nds32/isr-library/vec_vid43_4b.S b/libgcc/config/nds32/isr-library/vec_vid43_4b.S
new file mode 100644
index 00000000000..0c9e5a44ffb
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid43_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.43, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_43_4b
+ .type _nds32_vector_43_4b, @function
+_nds32_vector_43_4b:
+1:
+ j 1b
+ .size _nds32_vector_43_4b, .-_nds32_vector_43_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid44.S b/libgcc/config/nds32/isr-library/vec_vid44.S
new file mode 100644
index 00000000000..47e24a41831
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid44.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.44, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_44
+ .type _nds32_vector_44, @function
+_nds32_vector_44:
+1:
+ j 1b
+ .size _nds32_vector_44, .-_nds32_vector_44
diff --git a/libgcc/config/nds32/isr-library/vec_vid44_4b.S b/libgcc/config/nds32/isr-library/vec_vid44_4b.S
new file mode 100644
index 00000000000..43aa995b1e5
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid44_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.44, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_44_4b
+ .type _nds32_vector_44_4b, @function
+_nds32_vector_44_4b:
+1:
+ j 1b
+ .size _nds32_vector_44_4b, .-_nds32_vector_44_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid45.S b/libgcc/config/nds32/isr-library/vec_vid45.S
new file mode 100644
index 00000000000..711aba55969
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid45.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.45, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_45
+ .type _nds32_vector_45, @function
+_nds32_vector_45:
+1:
+ j 1b
+ .size _nds32_vector_45, .-_nds32_vector_45
diff --git a/libgcc/config/nds32/isr-library/vec_vid45_4b.S b/libgcc/config/nds32/isr-library/vec_vid45_4b.S
new file mode 100644
index 00000000000..96b505ead26
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid45_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.45, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_45_4b
+ .type _nds32_vector_45_4b, @function
+_nds32_vector_45_4b:
+1:
+ j 1b
+ .size _nds32_vector_45_4b, .-_nds32_vector_45_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid46.S b/libgcc/config/nds32/isr-library/vec_vid46.S
new file mode 100644
index 00000000000..0c86a8c4eb4
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid46.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.46, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_46
+ .type _nds32_vector_46, @function
+_nds32_vector_46:
+1:
+ j 1b
+ .size _nds32_vector_46, .-_nds32_vector_46
diff --git a/libgcc/config/nds32/isr-library/vec_vid46_4b.S b/libgcc/config/nds32/isr-library/vec_vid46_4b.S
new file mode 100644
index 00000000000..1e3dee61f5c
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid46_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.46, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_46_4b
+ .type _nds32_vector_46_4b, @function
+_nds32_vector_46_4b:
+1:
+ j 1b
+ .size _nds32_vector_46_4b, .-_nds32_vector_46_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid47.S b/libgcc/config/nds32/isr-library/vec_vid47.S
new file mode 100644
index 00000000000..72954018559
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid47.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.47, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_47
+ .type _nds32_vector_47, @function
+_nds32_vector_47:
+1:
+ j 1b
+ .size _nds32_vector_47, .-_nds32_vector_47
diff --git a/libgcc/config/nds32/isr-library/vec_vid47_4b.S b/libgcc/config/nds32/isr-library/vec_vid47_4b.S
new file mode 100644
index 00000000000..e8556c21fbc
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid47_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.47, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_47_4b
+ .type _nds32_vector_47_4b, @function
+_nds32_vector_47_4b:
+1:
+ j 1b
+ .size _nds32_vector_47_4b, .-_nds32_vector_47_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid48.S b/libgcc/config/nds32/isr-library/vec_vid48.S
new file mode 100644
index 00000000000..92c583aecb4
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid48.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.48, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_48
+ .type _nds32_vector_48, @function
+_nds32_vector_48:
+1:
+ j 1b
+ .size _nds32_vector_48, .-_nds32_vector_48
diff --git a/libgcc/config/nds32/isr-library/vec_vid48_4b.S b/libgcc/config/nds32/isr-library/vec_vid48_4b.S
new file mode 100644
index 00000000000..c998a55f90f
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid48_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.48, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_48_4b
+ .type _nds32_vector_48_4b, @function
+_nds32_vector_48_4b:
+1:
+ j 1b
+ .size _nds32_vector_48_4b, .-_nds32_vector_48_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid49.S b/libgcc/config/nds32/isr-library/vec_vid49.S
new file mode 100644
index 00000000000..c1b1677d032
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid49.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.49, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_49
+ .type _nds32_vector_49, @function
+_nds32_vector_49:
+1:
+ j 1b
+ .size _nds32_vector_49, .-_nds32_vector_49
diff --git a/libgcc/config/nds32/isr-library/vec_vid49_4b.S b/libgcc/config/nds32/isr-library/vec_vid49_4b.S
new file mode 100644
index 00000000000..0c18eee1761
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid49_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.49, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_49_4b
+ .type _nds32_vector_49_4b, @function
+_nds32_vector_49_4b:
+1:
+ j 1b
+ .size _nds32_vector_49_4b, .-_nds32_vector_49_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid50.S b/libgcc/config/nds32/isr-library/vec_vid50.S
new file mode 100644
index 00000000000..910ad028436
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid50.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.50, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_50
+ .type _nds32_vector_50, @function
+_nds32_vector_50:
+1:
+ j 1b
+ .size _nds32_vector_50, .-_nds32_vector_50
diff --git a/libgcc/config/nds32/isr-library/vec_vid50_4b.S b/libgcc/config/nds32/isr-library/vec_vid50_4b.S
new file mode 100644
index 00000000000..1ec0b700244
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid50_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.50, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_50_4b
+ .type _nds32_vector_50_4b, @function
+_nds32_vector_50_4b:
+1:
+ j 1b
+ .size _nds32_vector_50_4b, .-_nds32_vector_50_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid51.S b/libgcc/config/nds32/isr-library/vec_vid51.S
new file mode 100644
index 00000000000..2053ebccf3a
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid51.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.51, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_51
+ .type _nds32_vector_51, @function
+_nds32_vector_51:
+1:
+ j 1b
+ .size _nds32_vector_51, .-_nds32_vector_51
diff --git a/libgcc/config/nds32/isr-library/vec_vid51_4b.S b/libgcc/config/nds32/isr-library/vec_vid51_4b.S
new file mode 100644
index 00000000000..38c02107ce5
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid51_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.51, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_51_4b
+ .type _nds32_vector_51_4b, @function
+_nds32_vector_51_4b:
+1:
+ j 1b
+ .size _nds32_vector_51_4b, .-_nds32_vector_51_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid52.S b/libgcc/config/nds32/isr-library/vec_vid52.S
new file mode 100644
index 00000000000..6eaac798038
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid52.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.52, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_52
+ .type _nds32_vector_52, @function
+_nds32_vector_52:
+1:
+ j 1b
+ .size _nds32_vector_52, .-_nds32_vector_52
diff --git a/libgcc/config/nds32/isr-library/vec_vid52_4b.S b/libgcc/config/nds32/isr-library/vec_vid52_4b.S
new file mode 100644
index 00000000000..de8a9283042
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid52_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.52, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_52_4b
+ .type _nds32_vector_52_4b, @function
+_nds32_vector_52_4b:
+1:
+ j 1b
+ .size _nds32_vector_52_4b, .-_nds32_vector_52_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid53.S b/libgcc/config/nds32/isr-library/vec_vid53.S
new file mode 100644
index 00000000000..8ac761394b1
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid53.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.53, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_53
+ .type _nds32_vector_53, @function
+_nds32_vector_53:
+1:
+ j 1b
+ .size _nds32_vector_53, .-_nds32_vector_53
diff --git a/libgcc/config/nds32/isr-library/vec_vid53_4b.S b/libgcc/config/nds32/isr-library/vec_vid53_4b.S
new file mode 100644
index 00000000000..564346c2347
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid53_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.53, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_53_4b
+ .type _nds32_vector_53_4b, @function
+_nds32_vector_53_4b:
+1:
+ j 1b
+ .size _nds32_vector_53_4b, .-_nds32_vector_53_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid54.S b/libgcc/config/nds32/isr-library/vec_vid54.S
new file mode 100644
index 00000000000..ef222ada15d
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid54.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.54, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_54
+ .type _nds32_vector_54, @function
+_nds32_vector_54:
+1:
+ j 1b
+ .size _nds32_vector_54, .-_nds32_vector_54
diff --git a/libgcc/config/nds32/isr-library/vec_vid54_4b.S b/libgcc/config/nds32/isr-library/vec_vid54_4b.S
new file mode 100644
index 00000000000..104b7e7958e
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid54_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.54, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_54_4b
+ .type _nds32_vector_54_4b, @function
+_nds32_vector_54_4b:
+1:
+ j 1b
+ .size _nds32_vector_54_4b, .-_nds32_vector_54_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid55.S b/libgcc/config/nds32/isr-library/vec_vid55.S
new file mode 100644
index 00000000000..c061e69f1b9
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid55.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.55, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_55
+ .type _nds32_vector_55, @function
+_nds32_vector_55:
+1:
+ j 1b
+ .size _nds32_vector_55, .-_nds32_vector_55
diff --git a/libgcc/config/nds32/isr-library/vec_vid55_4b.S b/libgcc/config/nds32/isr-library/vec_vid55_4b.S
new file mode 100644
index 00000000000..15fced687f2
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid55_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.55, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_55_4b
+ .type _nds32_vector_55_4b, @function
+_nds32_vector_55_4b:
+1:
+ j 1b
+ .size _nds32_vector_55_4b, .-_nds32_vector_55_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid56.S b/libgcc/config/nds32/isr-library/vec_vid56.S
new file mode 100644
index 00000000000..d7c305a8754
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid56.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.56, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_56
+ .type _nds32_vector_56, @function
+_nds32_vector_56:
+1:
+ j 1b
+ .size _nds32_vector_56, .-_nds32_vector_56
diff --git a/libgcc/config/nds32/isr-library/vec_vid56_4b.S b/libgcc/config/nds32/isr-library/vec_vid56_4b.S
new file mode 100644
index 00000000000..e8b975c8f41
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid56_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.56, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_56_4b
+ .type _nds32_vector_56_4b, @function
+_nds32_vector_56_4b:
+1:
+ j 1b
+ .size _nds32_vector_56_4b, .-_nds32_vector_56_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid57.S b/libgcc/config/nds32/isr-library/vec_vid57.S
new file mode 100644
index 00000000000..b701bbab67f
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid57.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.57, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_57
+ .type _nds32_vector_57, @function
+_nds32_vector_57:
+1:
+ j 1b
+ .size _nds32_vector_57, .-_nds32_vector_57
diff --git a/libgcc/config/nds32/isr-library/vec_vid57_4b.S b/libgcc/config/nds32/isr-library/vec_vid57_4b.S
new file mode 100644
index 00000000000..ef29203f607
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid57_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.57, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_57_4b
+ .type _nds32_vector_57_4b, @function
+_nds32_vector_57_4b:
+1:
+ j 1b
+ .size _nds32_vector_57_4b, .-_nds32_vector_57_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid58.S b/libgcc/config/nds32/isr-library/vec_vid58.S
new file mode 100644
index 00000000000..211b27dae59
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid58.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.58, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_58
+ .type _nds32_vector_58, @function
+_nds32_vector_58:
+1:
+ j 1b
+ .size _nds32_vector_58, .-_nds32_vector_58
diff --git a/libgcc/config/nds32/isr-library/vec_vid58_4b.S b/libgcc/config/nds32/isr-library/vec_vid58_4b.S
new file mode 100644
index 00000000000..9eaefca6c49
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid58_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.58, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_58_4b
+ .type _nds32_vector_58_4b, @function
+_nds32_vector_58_4b:
+1:
+ j 1b
+ .size _nds32_vector_58_4b, .-_nds32_vector_58_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid59.S b/libgcc/config/nds32/isr-library/vec_vid59.S
new file mode 100644
index 00000000000..227edf2e097
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid59.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.59, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_59
+ .type _nds32_vector_59, @function
+_nds32_vector_59:
+1:
+ j 1b
+ .size _nds32_vector_59, .-_nds32_vector_59
diff --git a/libgcc/config/nds32/isr-library/vec_vid59_4b.S b/libgcc/config/nds32/isr-library/vec_vid59_4b.S
new file mode 100644
index 00000000000..30fccab1ca3
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid59_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.59, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_59_4b
+ .type _nds32_vector_59_4b, @function
+_nds32_vector_59_4b:
+1:
+ j 1b
+ .size _nds32_vector_59_4b, .-_nds32_vector_59_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid60.S b/libgcc/config/nds32/isr-library/vec_vid60.S
new file mode 100644
index 00000000000..68889685825
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid60.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.60, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_60
+ .type _nds32_vector_60, @function
+_nds32_vector_60:
+1:
+ j 1b
+ .size _nds32_vector_60, .-_nds32_vector_60
diff --git a/libgcc/config/nds32/isr-library/vec_vid60_4b.S b/libgcc/config/nds32/isr-library/vec_vid60_4b.S
new file mode 100644
index 00000000000..26d94ac5f96
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid60_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.60, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_60_4b
+ .type _nds32_vector_60_4b, @function
+_nds32_vector_60_4b:
+1:
+ j 1b
+ .size _nds32_vector_60_4b, .-_nds32_vector_60_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid61.S b/libgcc/config/nds32/isr-library/vec_vid61.S
new file mode 100644
index 00000000000..b3111e75c35
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid61.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.61, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_61
+ .type _nds32_vector_61, @function
+_nds32_vector_61:
+1:
+ j 1b
+ .size _nds32_vector_61, .-_nds32_vector_61
diff --git a/libgcc/config/nds32/isr-library/vec_vid61_4b.S b/libgcc/config/nds32/isr-library/vec_vid61_4b.S
new file mode 100644
index 00000000000..845125cf3ec
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid61_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.61, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_61_4b
+ .type _nds32_vector_61_4b, @function
+_nds32_vector_61_4b:
+1:
+ j 1b
+ .size _nds32_vector_61_4b, .-_nds32_vector_61_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid62.S b/libgcc/config/nds32/isr-library/vec_vid62.S
new file mode 100644
index 00000000000..d6342381b22
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid62.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.62, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_62
+ .type _nds32_vector_62, @function
+_nds32_vector_62:
+1:
+ j 1b
+ .size _nds32_vector_62, .-_nds32_vector_62
diff --git a/libgcc/config/nds32/isr-library/vec_vid62_4b.S b/libgcc/config/nds32/isr-library/vec_vid62_4b.S
new file mode 100644
index 00000000000..d4c4413dd73
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid62_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.62, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_62_4b
+ .type _nds32_vector_62_4b, @function
+_nds32_vector_62_4b:
+1:
+ j 1b
+ .size _nds32_vector_62_4b, .-_nds32_vector_62_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid63.S b/libgcc/config/nds32/isr-library/vec_vid63.S
new file mode 100644
index 00000000000..8d2770c3f21
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid63.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.63, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_63
+ .type _nds32_vector_63, @function
+_nds32_vector_63:
+1:
+ j 1b
+ .size _nds32_vector_63, .-_nds32_vector_63
diff --git a/libgcc/config/nds32/isr-library/vec_vid63_4b.S b/libgcc/config/nds32/isr-library/vec_vid63_4b.S
new file mode 100644
index 00000000000..6403a7b6ed7
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid63_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.63, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_63_4b
+ .type _nds32_vector_63_4b, @function
+_nds32_vector_63_4b:
+1:
+ j 1b
+ .size _nds32_vector_63_4b, .-_nds32_vector_63_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid64.S b/libgcc/config/nds32/isr-library/vec_vid64.S
new file mode 100644
index 00000000000..269bdf92f75
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid64.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.64, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_64
+ .type _nds32_vector_64, @function
+_nds32_vector_64:
+1:
+ j 1b
+ .size _nds32_vector_64, .-_nds32_vector_64
diff --git a/libgcc/config/nds32/isr-library/vec_vid64_4b.S b/libgcc/config/nds32/isr-library/vec_vid64_4b.S
new file mode 100644
index 00000000000..64691899043
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid64_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.64, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_64_4b
+ .type _nds32_vector_64_4b, @function
+_nds32_vector_64_4b:
+1:
+ j 1b
+ .size _nds32_vector_64_4b, .-_nds32_vector_64_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid65.S b/libgcc/config/nds32/isr-library/vec_vid65.S
new file mode 100644
index 00000000000..4fbf3e43b8c
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid65.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.65, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_65
+ .type _nds32_vector_65, @function
+_nds32_vector_65:
+1:
+ j 1b
+ .size _nds32_vector_65, .-_nds32_vector_65
diff --git a/libgcc/config/nds32/isr-library/vec_vid65_4b.S b/libgcc/config/nds32/isr-library/vec_vid65_4b.S
new file mode 100644
index 00000000000..25f0a8773f7
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid65_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.65, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_65_4b
+ .type _nds32_vector_65_4b, @function
+_nds32_vector_65_4b:
+1:
+ j 1b
+ .size _nds32_vector_65_4b, .-_nds32_vector_65_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid66.S b/libgcc/config/nds32/isr-library/vec_vid66.S
new file mode 100644
index 00000000000..ad8d6d2a475
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid66.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.66, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_66
+ .type _nds32_vector_66, @function
+_nds32_vector_66:
+1:
+ j 1b
+ .size _nds32_vector_66, .-_nds32_vector_66
diff --git a/libgcc/config/nds32/isr-library/vec_vid66_4b.S b/libgcc/config/nds32/isr-library/vec_vid66_4b.S
new file mode 100644
index 00000000000..d283d4337cf
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid66_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.66, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_66_4b
+ .type _nds32_vector_66_4b, @function
+_nds32_vector_66_4b:
+1:
+ j 1b
+ .size _nds32_vector_66_4b, .-_nds32_vector_66_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid67.S b/libgcc/config/nds32/isr-library/vec_vid67.S
new file mode 100644
index 00000000000..f3a97a6db7e
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid67.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.67, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_67
+ .type _nds32_vector_67, @function
+_nds32_vector_67:
+1:
+ j 1b
+ .size _nds32_vector_67, .-_nds32_vector_67
diff --git a/libgcc/config/nds32/isr-library/vec_vid67_4b.S b/libgcc/config/nds32/isr-library/vec_vid67_4b.S
new file mode 100644
index 00000000000..fb8283dcf9f
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid67_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.67, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_67_4b
+ .type _nds32_vector_67_4b, @function
+_nds32_vector_67_4b:
+1:
+ j 1b
+ .size _nds32_vector_67_4b, .-_nds32_vector_67_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid68.S b/libgcc/config/nds32/isr-library/vec_vid68.S
new file mode 100644
index 00000000000..815f4368633
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid68.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.68, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_68
+ .type _nds32_vector_68, @function
+_nds32_vector_68:
+1:
+ j 1b
+ .size _nds32_vector_68, .-_nds32_vector_68
diff --git a/libgcc/config/nds32/isr-library/vec_vid68_4b.S b/libgcc/config/nds32/isr-library/vec_vid68_4b.S
new file mode 100644
index 00000000000..94959a8cd1d
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid68_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.68, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_68_4b
+ .type _nds32_vector_68_4b, @function
+_nds32_vector_68_4b:
+1:
+ j 1b
+ .size _nds32_vector_68_4b, .-_nds32_vector_68_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid69.S b/libgcc/config/nds32/isr-library/vec_vid69.S
new file mode 100644
index 00000000000..cd1d17c605d
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid69.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.69, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_69
+ .type _nds32_vector_69, @function
+_nds32_vector_69:
+1:
+ j 1b
+ .size _nds32_vector_69, .-_nds32_vector_69
diff --git a/libgcc/config/nds32/isr-library/vec_vid69_4b.S b/libgcc/config/nds32/isr-library/vec_vid69_4b.S
new file mode 100644
index 00000000000..df0f7d36842
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid69_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.69, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_69_4b
+ .type _nds32_vector_69_4b, @function
+_nds32_vector_69_4b:
+1:
+ j 1b
+ .size _nds32_vector_69_4b, .-_nds32_vector_69_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid70.S b/libgcc/config/nds32/isr-library/vec_vid70.S
new file mode 100644
index 00000000000..4a2edce903b
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid70.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.70, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_70
+ .type _nds32_vector_70, @function
+_nds32_vector_70:
+1:
+ j 1b
+ .size _nds32_vector_70, .-_nds32_vector_70
diff --git a/libgcc/config/nds32/isr-library/vec_vid70_4b.S b/libgcc/config/nds32/isr-library/vec_vid70_4b.S
new file mode 100644
index 00000000000..cb12f9f3fd2
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid70_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.70, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_70_4b
+ .type _nds32_vector_70_4b, @function
+_nds32_vector_70_4b:
+1:
+ j 1b
+ .size _nds32_vector_70_4b, .-_nds32_vector_70_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid71.S b/libgcc/config/nds32/isr-library/vec_vid71.S
new file mode 100644
index 00000000000..9ae82659ce5
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid71.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.71, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_71
+ .type _nds32_vector_71, @function
+_nds32_vector_71:
+1:
+ j 1b
+ .size _nds32_vector_71, .-_nds32_vector_71
diff --git a/libgcc/config/nds32/isr-library/vec_vid71_4b.S b/libgcc/config/nds32/isr-library/vec_vid71_4b.S
new file mode 100644
index 00000000000..4f640b9b340
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid71_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.71, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_71_4b
+ .type _nds32_vector_71_4b, @function
+_nds32_vector_71_4b:
+1:
+ j 1b
+ .size _nds32_vector_71_4b, .-_nds32_vector_71_4b
diff --git a/libgcc/config/nds32/isr-library/vec_vid72.S b/libgcc/config/nds32/isr-library/vec_vid72.S
new file mode 100644
index 00000000000..ab07fdb0dd3
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid72.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.72, "ax"
+ .vec_size 16
+ .align 4
+ .weak _nds32_vector_72
+ .type _nds32_vector_72, @function
+_nds32_vector_72:
+1:
+ j 1b
+ .size _nds32_vector_72, .-_nds32_vector_72
diff --git a/libgcc/config/nds32/isr-library/vec_vid72_4b.S b/libgcc/config/nds32/isr-library/vec_vid72_4b.S
new file mode 100644
index 00000000000..d3864e1024c
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/vec_vid72_4b.S
@@ -0,0 +1,34 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_vector.72, "ax"
+ .vec_size 4
+ .align 2
+ .weak _nds32_vector_72_4b
+ .type _nds32_vector_72_4b, @function
+_nds32_vector_72_4b:
+1:
+ j 1b
+ .size _nds32_vector_72_4b, .-_nds32_vector_72_4b
diff --git a/libgcc/config/nds32/isr-library/wrh.S b/libgcc/config/nds32/isr-library/wrh.S
new file mode 100644
index 00000000000..fe964a51578
--- /dev/null
+++ b/libgcc/config/nds32/isr-library/wrh.S
@@ -0,0 +1,32 @@
+/* c-isr library stuff of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .nds32_wrh, "a"
+ .align 2
+ .weak _nds32_wrh
+ .type _nds32_wrh, @object
+_nds32_wrh:
+ .word 0
+ .size _nds32_wrh, .-_nds32_wrh
diff --git a/libgcc/config/nds32/lib1asmsrc-mculib.S b/libgcc/config/nds32/lib1asmsrc-mculib.S
new file mode 100644
index 00000000000..25295b6a9f2
--- /dev/null
+++ b/libgcc/config/nds32/lib1asmsrc-mculib.S
@@ -0,0 +1,5213 @@
+/* mculib libgcc routines of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .mdebug.abi_nds32
+ .previous
+
+
+/* ------------------------------------------- */
+/* FPBIT floating point operations for libgcc */
+/* ------------------------------------------- */
+
+#ifdef L_addsub_sf
+
+ .text
+ .align 2
+ .global __subsf3
+ .type __subsf3, @function
+__subsf3:
+ push $lp
+ pushm $r6, $r9
+
+ move $r2, #0x80000000
+ xor $r1, $r1, $r2
+
+ j .Lsfpadd
+
+ .global __addsf3
+ .type __addsf3, @function
+__addsf3:
+ push $lp
+ pushm $r6, $r9
+.Lsfpadd:
+ srli $r5, $r0, #23
+ andi $r5, $r5, #0xff
+ srli $r7, $r1, #23
+ andi $r7, $r7, #0xff
+ move $r3, #0x80000000
+ slli $r4, $r0, #8
+ or $r4, $r4, $r3
+ slli $r6, $r1, #8
+ or $r6, $r6, $r3
+
+ addi $r9, $r5, #-1
+ slti $r15, $r9, #0xfe
+ beqzs8 .LEspecA
+
+.LElab1:
+ addi $r9, $r7, #-1
+ slti $r15, $r9, #0xfe
+ beqzs8 .LEspecB
+
+.LElab2:
+ sub $r8, $r5, $r7
+ sltsi $r15, $r8, #0
+ bnezs8 .Li1
+ sltsi $r15, $r8, #0x20
+ bnezs8 .Li2
+ move $r6, #2
+ j .Le1
+.Li2:
+ move $r2, $r6
+ srl $r6, $r6, $r8
+ sll $r9, $r6, $r8
+ beq $r9, $r2, .Le1
+ ori $r6, $r6, #2
+ j .Le1
+.Li1:
+ move $r5, $r7
+ subri $r8, $r8, #0
+ sltsi $r15, $r8, #0x20
+ bnezs8 .Li4
+ move $r4, #2
+ j .Le1
+.Li4:
+ move $r2, $r4
+ srl $r4, $r4, $r8
+ sll $r9, $r4, $r8
+ beq $r9, $r2, .Le1
+ ori $r4, $r4, #2
+
+.Le1:
+ and $r8, $r0, $r3
+ xor $r9, $r8, $r1
+ sltsi $r15, $r9, #0
+ bnezs8 .LEsub1
+
+ #ADD($r4, $r6)
+ add $r4, $r4, $r6
+ slt $r15, $r4, $r6
+ beqzs8 .LEres
+ andi $r9, $r4, #1
+ beqz $r9, .Li7
+ ori $r4, $r4, #2
+.Li7:
+ srli $r4, $r4, #1
+ addi $r5, $r5, #1
+ subri $r15, $r5, #0xff
+ bnezs8 .LEres
+ move $r4, #0
+ j .LEres
+
+.LEsub1:
+ #SUB($r4, $r6)
+ move $r15, $r4
+ sub $r4, $r4, $r6
+ slt $r15, $r15, $r4
+ beqzs8 .Li9
+ subri $r4, $r4, #0
+ xor $r8, $r8, $r3
+ j .Le9
+.Li9:
+ beqz $r4, .LEzer
+.Le9:
+#ifdef __NDS32_PERF_EXT__
+ clz $r2, $r4
+#else
+ pushm $r0, $r1
+ pushm $r3, $r5
+ move $r0, $r4
+ bal __clzsi2
+ move $r2, $r0
+ popm $r3, $r5
+ popm $r0, $r1
+#endif
+ sub $r5, $r5, $r2
+ sll $r4, $r4, $r2
+
+.LEres:
+ blez $r5, .LEund
+
+.LElab12:
+ #ADD($r4, $0x80)
+ move $r15, #0x80
+ add $r4, $r4, $r15
+ slt $r15, $r4, $r15
+
+ #ADDC($r5, $0x0)
+ add $r5, $r5, $r15
+ srli $r9, $r4, #8
+ andi $r9, $r9, #1
+ sub $r4, $r4, $r9
+ slli $r4, $r4, #1
+ srli $r4, $r4, #9
+ slli $r9, $r5, #23
+ or $r4, $r4, $r9
+ or $r0, $r4, $r8
+
+.LE999:
+ popm $r6, $r9
+ pop $lp
+ ret5 $lp
+
+.LEund:
+ subri $r2, $r5, #1
+ slti $r15, $r2, #0x20
+ beqzs8 .LEzer
+ move $r9, #0x80000000
+ or $r4, $r4, $r9
+ subri $r9, $r2, #0x20
+ sll $r5, $r4, $r9
+ srl $r4, $r4, $r2
+ beqz $r5, .Li10
+ ori $r4, $r4, #1
+.Li10:
+ move $r5, #0
+ addi $r9, $r4, #0x80
+ sltsi $r15, $r9, #0
+ beqzs8 .LElab12
+ move $r5, #1
+ j .LElab12
+
+.LEspecA:
+ bnez $r5, .Li12
+ add $r4, $r4, $r4
+ beqz $r4, .Li13
+#ifdef __NDS32_PERF_EXT__
+ clz $r8, $r4
+#else
+ pushm $r0, $r5
+ move $r0, $r4
+ bal __clzsi2
+ move $r8, $r0
+ popm $r0, $r5
+#endif
+ sub $r5, $r5, $r8
+ sll $r4, $r4, $r8
+ j .LElab1
+.Li13:
+ subri $r15, $r7, #0xff
+ beqzs8 .LEspecB
+ move $r9, #0x80000000
+ bne $r1, $r9, .LEretB
+.Li12:
+ add $r9, $r4, $r4
+ bnez $r9, .LEnan
+ subri $r15, $r7, #0xff
+ bnezs8 .LEretA
+ xor $r9, $r0, $r1
+ sltsi $r15, $r9, #0
+ bnezs8 .LEnan
+ j .LEretB
+
+.LEspecB:
+ bnez $r7, .Li15
+ add $r6, $r6, $r6
+ beqz $r6, .LEretA
+#ifdef __NDS32_PERF_EXT__
+ clz $r8, $r6
+#else
+ pushm $r0, $r5
+ move $r0, $r6
+ bal __clzsi2
+ move $r8, $r0
+ popm $r0, $r5
+#endif
+ sub $r7, $r7, $r8
+ sll $r6, $r6, $r8
+ j .LElab2
+.Li15:
+ add $r9, $r6, $r6
+ bnez $r9, .LEnan
+
+.LEretB:
+ move $r0, $r1
+ j .LE999
+
+.LEretA:
+ j .LE999
+
+.LEzer:
+ move $r0, #0
+ j .LE999
+
+.LEnan:
+ move $r0, #0xffc00000
+ j .LE999
+ .size __subsf3, .-__subsf3
+ .size __addsf3, .-__addsf3
+#endif /* L_addsub_sf */
+
+
+
+#ifdef L_sf_to_si
+
+ .text
+ .align 2
+ .global __fixsfsi
+ .type __fixsfsi, @function
+__fixsfsi:
+ push $lp
+
+ slli $r1, $r0, #8
+ move $r3, #0x80000000
+ or $r1, $r1, $r3
+ srli $r3, $r0, #23
+ andi $r3, $r3, #0xff
+ subri $r2, $r3, #0x9e
+ blez $r2, .LJspec
+ sltsi $r15, $r2, #0x20
+ bnezs8 .Li42
+ move $r0, #0
+ j .LJ999
+.Li42:
+ srl $r1, $r1, $r2
+ sltsi $r15, $r0, #0
+ beqzs8 .Li43
+ subri $r1, $r1, #0
+.Li43:
+ move $r0, $r1
+
+.LJ999:
+ pop $lp
+ ret5 $lp
+
+.LJspec:
+ move $r3, #0x7f800000
+ slt $r15, $r3, $r0
+ beqzs8 .Li44
+ move $r0, #0x80000000
+ j .LJ999
+.Li44:
+ move $r0, #0x7fffffff
+ j .LJ999
+ .size __fixsfsi, .-__fixsfsi
+#endif /* L_sf_to_si */
+
+
+
+#ifdef L_divsi3
+
+ .text
+ .align 2
+ .globl __divsi3
+ .type __divsi3, @function
+__divsi3:
+ ! ---------------------------------------------------------------------
+ ! neg = 0;
+ ! if (a < 0)
+ ! { a = -a;
+ ! neg = !neg;
+ ! }
+ ! ---------------------------------------------------------------------
+ sltsi $r5, $r0, 0 ! $r5 <- neg = (a < 0) ? 1 : 0
+ subri $r4, $r0, 0 ! $r4 <- a = -a
+ cmovn $r0, $r4, $r5 ! $r0 <- a = neg ? -a : a
+.L2:
+ ! ---------------------------------------------------------------------
+ ! if (b < 0)
+ ! ---------------------------------------------------------------------
+ bgez $r1, .L3 ! if b >= 0, skip
+ ! ---------------------------------------------------------------------
+ ! { b=-b;
+ ! neg=!neg;
+ ! }
+ ! ---------------------------------------------------------------------
+ subri $r1, $r1, 0 ! $r1 <- b = -b
+ subri $r5, $r5, 1 ! $r5 <- neg = !neg
+.L3:
+ ! ---------------------------------------------------------------------
+ !!res = udivmodsi4 (a, b, 1);
+ ! res = 0;
+ ! if (den != 0)
+ ! ---------------------------------------------------------------------
+ movi $r2, 0 ! $r2 <- res = 0
+ beqz $r1, .L1 ! if den == 0, skip
+ ! ---------------------------------------------------------------------
+ ! bit = 1;
+ ! ---------------------------------------------------------------------
+ movi $r4, 1 ! $r4 <- bit = 1
+#ifndef __OPTIMIZE_SIZE__
+.L6:
+#endif
+ ! ---------------------------------------------------------------------
+ ! while (den < num && bit && !(den & (1L << 31)))
+ ! ---------------------------------------------------------------------
+ slt $ta, $r1, $r0 ! $ta <- den < num ?
+ beqz $ta, .L5 ! if no, skip
+ ! ---------------------------------------------------------------------
+ ! { den << = 1;
+ ! bit << = 1;
+ ! }
+ ! ---------------------------------------------------------------------
+#if defined (__OPTIMIZE_SIZE__) && !defined (__NDS32_ISA_V3M__)
+ clz $r3, $r1 ! $r3 <- leading zero count for den
+ clz $ta, $r0 ! $ta <- leading zero count for num
+ sub $r3, $r3, $ta ! $r3 <- number of bits to shift
+ sll $r1, $r1, $r3 ! $r1 <- den
+ sll $r4, $r4, $r3 ! $r2 <- bit
+#else
+ slli $r1, $r1, 1 ! $r1 <- den << = 1
+ slli $r4, $r4, 1 ! $r4 <- bit << = 1
+ b .L6 ! continue loop
+#endif
+.L5:
+ ! ---------------------------------------------------------------------
+ ! while (bit)
+ ! { if (num >= den)
+ ! ---------------------------------------------------------------------
+ slt $ta, $r0, $r1 ! $ta <- num < den ?
+ bnez $ta, .L9 ! if yes, skip
+ ! ---------------------------------------------------------------------
+ ! { num -= den;
+ ! res |= bit;
+ ! }
+ ! ---------------------------------------------------------------------
+ sub $r0, $r0, $r1 ! $r0 <- num -= den
+ or $r2, $r2, $r4 ! $r2 <- res |= bit
+.L9:
+ ! ---------------------------------------------------------------------
+ ! bit >> = 1;
+ ! den >> = 1;
+ ! }
+ !!if (modwanted)
+ !! return num;
+ !!return res;
+ ! ---------------------------------------------------------------------
+ srli $r4, $r4, 1 ! $r4 <- bit >> = 1
+ srli $r1, $r1, 1 ! $r1 <- den >> = 1
+ bnez $r4, .L5 ! if bit != 0, continue loop
+.L1:
+ ! ---------------------------------------------------------------------
+ ! if (neg)
+ ! res = -res;
+ ! return res;
+ ! ---------------------------------------------------------------------
+ subri $r0, $r2, 0 ! $r0 <- -res
+ cmovz $r0, $r2, $r5 ! $r0 <- neg ? -res : res
+ ! ---------------------------------------------------------------------
+ ret
+ .size __divsi3, .-__divsi3
+#endif /* L_divsi3 */
+
+
+
+#ifdef L_divdi3
+
+ !--------------------------------------
+ #ifdef __big_endian__
+ #define V1H $r0
+ #define V1L $r1
+ #define V2H $r2
+ #define V2L $r3
+ #else
+ #define V1H $r1
+ #define V1L $r0
+ #define V2H $r3
+ #define V2L $r2
+ #endif
+ !--------------------------------------
+ .text
+ .align 2
+ .globl __divdi3
+ .type __divdi3, @function
+__divdi3:
+ ! prologue
+#ifdef __NDS32_ISA_V3M__
+ push25 $r10, 0
+#else
+ smw.adm $r6, [$sp], $r10, 2
+#endif
+ ! end of prologue
+ move $r8, V1L
+ move $r9, V1H
+ move $r6, V2L
+ move $r7, V2H
+ movi $r10, 0
+ bgez V1H, .L80
+ bal __negdi2
+ move $r8, V1L
+ move $r9, V1H
+ movi $r10, -1
+.L80:
+ bgez $r7, .L81
+ move V1L, $r6
+ move V1H, $r7
+ bal __negdi2
+ move $r6, V1L
+ move $r7, V1H
+ nor $r10, $r10, $r10
+.L81:
+ move V2L, $r6
+ move V2H, $r7
+ move V1L, $r8
+ move V1H, $r9
+ movi $r4, 0
+ bal __udivmoddi4
+ beqz $r10, .L82
+ bal __negdi2
+.L82:
+ ! epilogue
+#ifdef __NDS32_ISA_V3M__
+ pop25 $r10, 0
+#else
+ lmw.bim $r6, [$sp], $r10, 2
+ ret
+#endif
+ .size __divdi3, .-__divdi3
+#endif /* L_divdi3 */
+
+
+
+#ifdef L_modsi3
+
+ .text
+ .align 2
+ .globl __modsi3
+ .type __modsi3, @function
+__modsi3:
+ ! ---------------------------------------------------------------------
+ ! neg=0;
+ ! if (a<0)
+ ! { a=-a;
+ ! neg=1;
+ ! }
+ ! ---------------------------------------------------------------------
+ sltsi $r5, $r0, 0 ! $r5 <- neg < 0 ? 1 : 0
+ subri $r4, $r0, 0 ! $r4 <- -a
+ cmovn $r0, $r4, $r5 ! $r0 <- |a|
+ ! ---------------------------------------------------------------------
+ ! if (b < 0)
+#ifndef __NDS32_PERF_EXT__
+ ! ---------------------------------------------------------------------
+ bgez $r1, .L3 ! if b >= 0, skip
+ ! ---------------------------------------------------------------------
+ ! b = -b;
+ ! ---------------------------------------------------------------------
+ subri $r1, $r1, 0 ! $r1 <- |b|
+.L3:
+ ! ---------------------------------------------------------------------
+ !!res = udivmodsi4 (a, b, 1);
+ ! if (den != 0)
+ ! ---------------------------------------------------------------------
+#else /* __NDS32_PERF_EXT__ */
+ ! b = -b;
+ !!res = udivmodsi4 (a, b, 1);
+ ! if (den != 0)
+ ! ---------------------------------------------------------------------
+ abs $r1, $r1 ! $r1 <- |b|
+#endif /* __NDS32_PERF_EXT__ */
+ beqz $r1, .L1 ! if den == 0, skip
+ ! ---------------------------------------------------------------------
+ ! { bit = 1;
+ ! res = 0;
+ ! ---------------------------------------------------------------------
+ movi $r4, 1 ! $r4 <- bit = 1
+#ifndef __OPTIMIZE_SIZE__
+.L6:
+#endif
+ ! ---------------------------------------------------------------------
+ ! while (den < num&&bit && !(den & (1L << 31)))
+ ! ---------------------------------------------------------------------
+ slt $ta, $r1, $r0 ! $ta <- den < num ?
+ beqz $ta, .L5 ! if no, skip
+ ! ---------------------------------------------------------------------
+ ! { den << = 1;
+ ! bit << = 1;
+ ! }
+ ! ---------------------------------------------------------------------
+#if defined (__OPTIMIZE_SIZE__) && ! defined (__NDS32_ISA_V3M__)
+ clz $r3, $r1 ! $r3 <- leading zero count for den
+ clz $ta, $r0 ! $ta <- leading zero count for num
+ sub $r3, $r3, $ta ! $r3 <- number of bits to shift
+ sll $r1, $r1, $r3 ! $r1 <- den
+ sll $r4, $r4, $r3 ! $r2 <- bit
+#else
+ slli $r1, $r1, 1 ! $r1 <- den << = 1
+ slli $r4, $r4, 1 ! $r4 <- bit << = 1
+ b .L6 ! continue loop
+#endif
+.L5:
+ ! ---------------------------------------------------------------------
+ ! while (bit)
+ ! { if (num >= den)
+ ! { num -= den;
+ ! res |= bit;
+ ! }
+ ! bit >> = 1;
+ ! den >> = 1;
+ ! }
+ ! }
+ !!if (modwanted)
+ !! return num;
+ !!return res;
+ ! ---------------------------------------------------------------------
+ sub $r2, $r0, $r1 ! $r2 <- num - den
+ slt $ta, $r0, $r1 ! $ta <- num < den ?
+ srli $r4, $r4, 1 ! $r4 <- bit >> = 1
+ cmovz $r0, $r2, $ta ! $r0 <- num = (num < den) ? num : num - den
+ srli $r1, $r1, 1 ! $r1 <- den >> = 1
+ bnez $r4, .L5 ! if bit != 0, continue loop
+.L1:
+ ! ---------------------------------------------------------------------
+ ! if (neg)
+ ! res = -res;
+ ! return res;
+ ! ---------------------------------------------------------------------
+ subri $r3, $r0, 0 ! $r3 <- -res
+ cmovn $r0, $r3, $r5 ! $r0 <- neg ? -res : res
+ ! ---------------------------------------------------------------------
+ ret
+ .size __modsi3, .-__modsi3
+#endif /* L_modsi3 */
+
+
+
+#ifdef L_moddi3
+
+ !--------------------------------------
+ #ifdef __big_endian__
+ #define V1H $r0
+ #define V1L $r1
+ #define V2H $r2
+ #define V2L $r3
+ #else
+ #define V1H $r1
+ #define V1L $r0
+ #define V2H $r3
+ #define V2L $r2
+ #endif
+ !--------------------------------------
+ .text
+ .align 2
+ .globl __moddi3
+ .type __moddi3, @function
+__moddi3:
+ ! =====================================================================
+ ! stack allocation:
+ ! sp+32 +-----------------------+
+ ! | $lp |
+ ! sp+28 +-----------------------+
+ ! | $r6 - $r10 |
+ ! sp+8 +-----------------------+
+ ! | |
+ ! sp+4 +-----------------------+
+ ! | |
+ ! sp +-----------------------+
+ ! =====================================================================
+ ! prologue
+#ifdef __NDS32_ISA_V3M__
+ push25 $r10, 8
+#else
+ smw.adm $r6, [$sp], $r10, 2
+ addi $sp, $sp, -8
+#endif
+ ! end of prologue
+ !------------------------------------------
+ ! __moddi3 (DWtype u, DWtype v)
+ ! {
+ ! word_type c = 0;
+ ! DWunion uu = {.ll = u};
+ ! DWunion vv = {.ll = v};
+ ! DWtype w;
+ ! if (uu.s.high < 0)
+ ! c = ~c,
+ ! uu.ll = -uu.ll;
+ !---------------------------------------------
+ move $r8, V1L
+ move $r9, V1H
+ move $r6, V2L
+ move $r7, V2H
+ movi $r10, 0 ! r10 = c = 0
+ bgez V1H, .L80 ! if u > 0 , go L80
+ bal __negdi2
+ move $r8, V1L
+ move $r9, V1H
+ movi $r10, -1 ! r10 = c = ~c
+ !------------------------------------------------
+ ! if (vv.s.high < 0)
+ ! vv.ll = -vv.ll;
+ !----------------------------------------------
+.L80:
+ bgez $r7, .L81 ! if v > 0 , go L81
+ move V1L, $r6
+ move V1H, $r7
+ bal __negdi2
+ move $r6, V1L
+ move $r7, V1H
+ !------------------------------------------
+ ! (void) __udivmoddi4 (uu.ll, vv.ll, &w);
+ ! if (c)
+ ! w = -w;
+ ! return w;
+ !-----------------------------------------
+.L81:
+ move V2L, $r6
+ move V2H, $r7
+ move V1L, $r8
+ move V1H, $r9
+ addi $r4, $sp, 0
+ bal __udivmoddi4
+ lwi $r0, [$sp+(0)] ! le: sp + 0 is low, be: sp + 0 is high
+ lwi $r1, [$sp+(4)] ! le: sp + 4 is low, be: sp + 4 is high
+ beqz $r10, .L82
+ bal __negdi2
+.L82:
+ ! epilogue
+#ifdef __NDS32_ISA_V3M__
+ pop25 $r10, 8
+#else
+ addi $sp, $sp, 8
+ lmw.bim $r6, [$sp], $r10, 2
+ ret
+#endif
+ .size __moddi3, .-__moddi3
+#endif /* L_moddi3 */
+
+
+
+#ifdef L_mulsi3
+
+ .text
+ .align 2
+ .globl __mulsi3
+ .type __mulsi3, @function
+__mulsi3:
+ ! ---------------------------------------------------------------------
+ ! r = 0;
+ ! while (a)
+ ! $r0: r
+ ! $r1: b
+ ! $r2: a
+ ! ---------------------------------------------------------------------
+ beqz $r0, .L7 ! if a == 0, done
+ move $r2, $r0 ! $r2 <- a
+ movi $r0, 0 ! $r0 <- r <- 0
+.L8:
+ ! ---------------------------------------------------------------------
+ ! { if (a & 1)
+ ! r += b;
+ ! a >> = 1;
+ ! b << = 1;
+ ! }
+ ! $r0: r
+ ! $r1: b
+ ! $r2: a
+ ! $r3: scratch
+ ! $r4: scratch
+ ! ---------------------------------------------------------------------
+ andi $r3, $r2, 1 ! $r3 <- a & 1
+ add $r4, $r0, $r1 ! $r4 <- r += b
+ cmovn $r0, $r4, $r3 ! $r0 <- r
+ srli $r2, $r2, 1 ! $r2 <- a >> = 1
+ slli $r1, $r1, 1 ! $r1 <- b << = 1
+ bnez $r2, .L8 ! if a != 0, continue loop
+.L7:
+ ! ---------------------------------------------------------------------
+ ! $r0: return code
+ ! ---------------------------------------------------------------------
+ ret
+ .size __mulsi3, .-__mulsi3
+#endif /* L_mulsi3 */
+
+
+
+#ifdef L_udivsi3
+
+ .text
+ .align 2
+ .globl __udivsi3
+ .type __udivsi3, @function
+__udivsi3:
+ ! ---------------------------------------------------------------------
+ !!res=udivmodsi4(a,b,0);
+ ! res=0;
+ ! if (den!=0)
+ ! ---------------------------------------------------------------------
+ movi $r2, 0 ! $r2 <- res=0
+ beqz $r1, .L1 ! if den==0, skip
+ ! ---------------------------------------------------------------------
+ ! { bit=1;
+ ! ---------------------------------------------------------------------
+ movi $r4, 1 ! $r4 <- bit=1
+#ifndef __OPTIMIZE_SIZE__
+.L6:
+#endif
+ ! ---------------------------------------------------------------------
+ ! while (den<num
+ ! ---------------------------------------------------------------------
+ slt $ta, $r1, $r0 ! $ta <- den<num?
+ beqz $ta, .L5 ! if no, skip
+ ! ---------------------------------------------------------------------
+ ! &&bit&&!(den&(1L<<31)))
+ ! ---------------------------------------------------------------------
+ bltz $r1, .L5 ! if den<0, skip
+ ! ---------------------------------------------------------------------
+ ! { den<<=1;
+ ! bit<<=1;
+ ! }
+ ! ---------------------------------------------------------------------
+#if defined (__OPTIMIZE_SIZE__) && ! defined (__NDS32_ISA_V3M__)
+ clz $r3, $r1 ! $r3 <- leading zero count for den
+ clz $ta, $r0 ! $ta <- leading zero count for num
+ sub $r3, $r3, $ta ! $r3 <- number of bits to shift
+ sll $r1, $r1, $r3 ! $r1 <- den
+ sll $r2, $r2, $r3 ! $r2 <- bit
+#else
+ slli $r1, $r1, 1 ! $r1 <- den<<=1
+ slli $r4, $r4, 1 ! $r4 <- bit<<=1
+ b .L6 ! continue loop
+#endif
+.L5:
+ ! ---------------------------------------------------------------------
+ ! while (bit)
+ ! { if (num>=den)
+ ! ---------------------------------------------------------------------
+ slt $ta, $r0, $r1 ! $ta <- num<den?
+ bnez $ta, .L9 ! if yes, skip
+ ! ---------------------------------------------------------------------
+ ! { num-=den;
+ ! res|=bit;
+ ! }
+ ! ---------------------------------------------------------------------
+ sub $r0, $r0, $r1 ! $r0 <- num-=den
+ or $r2, $r2, $r4 ! $r2 <- res|=bit
+.L9:
+ ! ---------------------------------------------------------------------
+ ! bit>>=1;
+ ! den>>=1;
+ ! }
+ ! }
+ !!if (modwanted)
+ !! return num;
+ !!return res;
+ ! ---------------------------------------------------------------------
+ srli $r4, $r4, 1 ! $r4 <- bit>>=1
+ srli $r1, $r1, 1 ! $r1 <- den>>=1
+ bnez $r4, .L5 ! if bit!=0, continue loop
+.L1:
+ ! ---------------------------------------------------------------------
+ ! return res;
+ ! ---------------------------------------------------------------------
+ move $r0, $r2 ! $r0 <- return value
+ ! ---------------------------------------------------------------------
+ ! ---------------------------------------------------------------------
+ ret
+ .size __udivsi3, .-__udivsi3
+#endif /* L_udivsi3 */
+
+
+
+#ifdef L_udivdi3
+
+ !--------------------------------------
+ #ifdef __big_endian__
+ #define V1H $r0
+ #define V1L $r1
+ #define V2H $r2
+ #define V2L $r3
+ #else
+ #define V1H $r1
+ #define V1L $r0
+ #define V2H $r3
+ #define V2L $r2
+ #endif
+ !--------------------------------------
+
+ .text
+ .align 2
+ .globl __udivdi3
+ .type __udivdi3, @function
+__udivdi3:
+ ! prologue
+#ifdef __NDS32_ISA_V3M__
+ push25 $r8, 0
+#else
+ smw.adm $r6, [$sp], $r8, 2
+#endif
+ ! end of prologue
+ movi $r4, 0
+ bal __udivmoddi4
+ ! epilogue
+#ifdef __NDS32_ISA_V3M__
+ pop25 $r8, 0
+#else
+ lmw.bim $r6, [$sp], $r8, 2
+ ret
+#endif
+ .size __udivdi3, .-__udivdi3
+#endif /* L_udivdi3 */
+
+
+
+#ifdef L_udivmoddi4
+
+ .text
+ .align 2
+ .globl fudiv_qrnnd
+ .type fudiv_qrnnd, @function
+ #ifdef __big_endian__
+ #define P1H $r0
+ #define P1L $r1
+ #define P2H $r2
+ #define P2L $r3
+ #define W6H $r4
+ #define W6L $r5
+ #define OFFSET_L 4
+ #define OFFSET_H 0
+ #else
+ #define P1H $r1
+ #define P1L $r0
+ #define P2H $r3
+ #define P2L $r2
+ #define W6H $r5
+ #define W6L $r4
+ #define OFFSET_L 0
+ #define OFFSET_H 4
+ #endif
+fudiv_qrnnd:
+ !------------------------------------------------------
+ ! function: fudiv_qrnnd(quotient, remainder, high_numerator, low_numerator, denominator)
+ ! divides a UDWtype, composed by the UWtype integers,HIGH_NUMERATOR (from $r4)
+ ! and LOW_NUMERATOR(from $r5) by DENOMINATOR(from $r6), and places the quotient
+ ! in $r7 and the remainder in $r8.
+ !------------------------------------------------------
+ ! in reg:$r4(n1), $r5(n0), $r6(d0)
+ ! __d1 = ((USItype) (d) >> ((4 * 8) / 2));
+ ! __d0 = ((USItype) (d) & (((USItype) 1 << ((4 * 8) / 2)) - 1));
+ ! __r1 = (n1) % __d1;
+ ! __q1 = (n1) / __d1;
+ ! __m = (USItype) __q1 * __d0;
+ ! __r1 = __r1 * ((USItype) 1 << ((4 * 8) / 2)) | ((USItype) (n0) >> ((4 * 8) / 2));
+ ! if (__r1 < __m)
+ ! {
+ !------------------------------------------------------
+ smw.adm $r0, [$sp], $r4, 2 ! store $lp, when use BASELINE_V1,and must store $r0-$r3
+ srli $r7, $r6, 16 ! $r7 = d1 =__ll_highpart (d)
+ movi $ta, 65535
+ and $r8, $r6, $ta ! $r8 = d0 = __ll_lowpart (d)
+
+ divr $r9, $r10, $r4, $r7 ! $r9 = q1, $r10 = r1
+ and $r4, $r5, $ta ! $r4 = __ll_lowpart (n0)
+ slli $r10, $r10, 16 ! $r10 = r1 << 16
+ srli $ta, $r5, 16 ! $ta = __ll_highpart (n0)
+
+ or $r10, $r10, $ta ! $r10 <- $r0|$r3=__r1
+ mul $r5, $r9, $r8 ! $r5 = m = __q1*__d0
+ slt $ta, $r10, $r5 ! $ta <- __r1<__m
+ beqz $ta, .L2 !if yes,skip
+ !------------------------------------------------------
+ ! __q1--, __r1 += (d);
+ ! if (__r1 >= (d))
+ ! {
+ !------------------------------------------------------
+
+ add $r10, $r10, $r6 !$r10 <- __r1+d=__r1
+ addi $r9, $r9, -1 !$r9 <- __q1--=__q1
+ slt $ta, $r10, $r6 !$ta <- __r1<d
+ bnez $ta, .L2 !if yes,skip
+ !------------------------------------------------------
+ ! if (__r1 < __m)
+ ! {
+ !------------------------------------------------------
+
+ slt $ta, $r10, $r5 !$ta <- __r1<__m
+ beqz $ta, .L2 !if yes,skip
+ !------------------------------------------------------
+ ! __q1--, __r1 += (d);
+ ! }
+ ! }
+ ! }
+ !------------------------------------------------------
+
+ addi $r9, $r9, -1 !$r9 <- __q1--=__q1
+ add $r10, $r10, $r6 !$r2 <- __r1+d=__r1
+.L2:
+ !------------------------------------------------------
+ ! __r1 -= __m;
+ ! __r0 = __r1 % __d1;
+ ! __q0 = __r1 / __d1;
+ ! __m = (USItype) __q0 * __d0;
+ ! __r0 = __r0 * ((USItype) 1 << ((4 * 8) / 2)) \
+ ! | ((USItype) (n0) & (((USItype) 1 << ((4 * 8) / 2)) - 1));
+ ! if (__r0 < __m)
+ ! {
+ !------------------------------------------------------
+ sub $r10, $r10, $r5 !$r10 <- __r1-__m=__r1
+ divr $r7, $r10, $r10, $r7 !$r7 <- r1/__d1=__q0,$r10 <- r1%__d1=__r0
+ slli $r10, $r10, 16 !$r10 <- __r0<<16
+ mul $r5, $r8, $r7 !$r5 <- __q0*__d0=__m
+ or $r10, $r4, $r10 !$r3 <- $r0|__ll_lowpart (n0) =__r0
+ slt $ta, $r10, $r5 !$ta <- __r0<__m
+ beqz $ta, .L5 !if yes,skip
+ !------------------------------------------------------
+ ! __q0--, __r0 += (d);
+ ! if (__r0 >= (d))
+ ! {
+ !------------------------------------------------------
+
+ add $r10, $r10, $r6 !$r10 <- __r0+d=__r0
+ addi $r7, $r7, -1 !$r7 <- __q0--=__q0
+ slt $ta, $r10, $r6 !$ta <- __r0<d
+ bnez $ta, .L5 !if yes,skip
+ !------------------------------------------------------
+ ! if (__r0 < __m)
+ ! {
+ !------------------------------------------------------
+
+ slt $ta, $r10, $r5 !$ta <- __r0<__m
+ beqz $ta, .L5 !if yes,skip
+ !------------------------------------------------------
+ ! __q0--, __r0 += (d);
+ ! }
+ ! }
+ ! }
+ !------------------------------------------------------
+
+ add $r10, $r10, $r6 !$r3 <- __r0+d=__r0
+ addi $r7, $r7, -1 !$r2 <- __q0--=__q0
+.L5:
+ !------------------------------------------------------
+ ! __r0 -= __m;
+ ! *q = (USItype) __q1 * ((USItype) 1 << ((4 * 8) / 2)) | __q0;
+ ! *r = __r0;
+ !}
+ !------------------------------------------------------
+
+ sub $r8, $r10, $r5 !$r8 = r = r0 = __r0-__m
+ slli $r9, $r9, 16 !$r9 <- __q1<<16
+ or $r7, $r9, $r7 !$r7 = q = $r9|__q0
+ lmw.bim $r0, [$sp], $r4, 2
+ ret
+ .size fudiv_qrnnd, .-fudiv_qrnnd
+
+ .align 2
+ .globl __udivmoddi4
+ .type __udivmoddi4, @function
+__udivmoddi4:
+ ! =====================================================================
+ ! stack allocation:
+ ! sp+40 +------------------+
+ ! | q1 |
+ ! sp+36 +------------------+
+ ! | q0 |
+ ! sp+32 +------------------+
+ ! | bm |
+ ! sp+28 +------------------+
+ ! | $lp |
+ ! sp+24 +------------------+
+ ! | $fp |
+ ! sp+20 +------------------+
+ ! | $r6 - $r10 |
+ ! sp +------------------+
+ ! =====================================================================
+
+ addi $sp, $sp, -40
+ smw.bi $r6, [$sp], $r10, 10
+ !------------------------------------------------------
+ ! d0 = dd.s.low;
+ ! d1 = dd.s.high;
+ ! n0 = nn.s.low;
+ ! n1 = nn.s.high;
+ ! if (d1 == 0)
+ ! {
+ !------------------------------------------------------
+
+ move $fp, $r4 !$fp <- rp
+ bnez P2H, .L9 !if yes,skip
+ !------------------------------------------------------
+ ! if (d0 > n1)
+ ! {
+ !------------------------------------------------------
+
+ slt $ta, P1H, P2L !$ta <- n1<d0
+ beqz $ta, .L10 !if yes,skip
+#ifndef __NDS32_PERF_EXT__
+ smw.adm $r0, [$sp], $r5, 0
+ move $r0, P2L
+ bal __clzsi2
+ move $r7, $r0
+ lmw.bim $r0, [$sp], $r5, 0
+#else
+ clz $r7, P2L
+#endif
+ swi $r7, [$sp+(28)]
+ beqz $r7, .L18 !if yes,skip
+ !------------------------------------------------------
+ ! d0 = d0 << bm;
+ ! n1 = (n1 << bm) | (n0 >> ((4 * 8) - bm));
+ ! n0 = n0 << bm;
+ ! }
+ !------------------------------------------------------
+
+ subri $r5, $r7, 32 !$r5 <- 32-bm
+ srl $r5, P1L, $r5 !$r5 <- n0>>$r5
+ sll $r6, P1H, $r7 !$r6 <- n1<<bm
+ or P1H, $r6, $r5 !P2h <- $r5|$r6=n1
+ sll P1L, P1L, $r7 !P1H <- n0<<bm=n0
+ sll P2L, P2L, $r7 !P2L <- d0<<bm=d0
+.L18:
+ !------------------------------------------------------
+ ! fudiv_qrnnd (&q0, &n0, n1, n0, d0);
+ ! q1 = 0;
+ ! } #if (d0 > n1)
+ !------------------------------------------------------
+
+ move $r4,P1H ! give fudiv_qrnnd args
+ move $r5,P1L !
+ move $r6,P2L !
+ bal fudiv_qrnnd !calcaulte q0 n0
+ movi $r6, 0 !P1L <- 0
+ swi $r7,[$sp+32] !q0
+ swi $r6,[$sp+36] !q1
+ move P1L,$r8 !n0
+ b .L19
+.L10:
+ !------------------------------------------------------
+ ! else #if (d0 > n1)
+ ! {
+ ! if(d0 == 0)
+ !------------------------------------------------------
+
+ bnez P2L, .L20 !if yes,skip
+ !------------------------------------------------------
+ ! d0 = 1 / d0;
+ !------------------------------------------------------
+
+ movi $r4, 1 !P1L <- 1
+ divr P2L, $r4, $r4, P2L !$r9=1/d0,P1L=1%d0
+.L20:
+
+#ifndef __NDS32_PERF_EXT__
+ smw.adm $r0, [$sp], $r5, 0
+ move $r0, P2L
+ bal __clzsi2
+ move $r7, $r0
+ lmw.bim $r0, [$sp], $r5, 0
+#else
+ clz $r7, P2L
+#endif
+ swi $r7,[$sp+(28)] ! store bm
+ beqz $r7, .L28 ! if yes,skip
+ !------------------------------------------------------
+ ! b = (4 * 8) - bm;
+ ! d0 = d0 << bm;
+ ! n2 = n1 >> b;
+ ! n1 = (n1 << bm) | (n0 >> b);
+ ! n0 = n0 << bm;
+ ! fudiv_qrnnd (&q1, &n1, n2, n1, d0);
+ ! }
+ !------------------------------------------------------
+
+ subri $r10, $r7, 32 !$r10 <- 32-bm=b
+ srl $r4, P1L, $r10 !$r4 <- n0>>b
+ sll $r5, P1H, $r7 !$r5 <- n1<<bm
+ or $r5, $r5, $r4 !$r5 <- $r5|$r4=n1 !for fun
+ sll P2L, P2L, $r7 !P2L <- d0<<bm=d0 !for fun
+ sll P1L, P1L, $r7 !P1L <- n0<<bm=n0
+ srl $r4, P1H, $r10 !$r4 <- n1>>b=n2 !for fun
+
+ move $r6,P2L !for fun
+ bal fudiv_qrnnd !caculate q1, n1
+
+ swi $r7,[$sp+(36)] ! q1 store
+ move P1H,$r8 ! n1 store
+
+ move $r4,$r8 ! prepare for next fudiv_qrnnd()
+ move $r5,P1L
+ move $r6,P2L
+ b .L29
+.L28:
+ !------------------------------------------------------
+ ! else // bm != 0
+ ! {
+ ! n1 -= d0;
+ ! q1 = 1;
+ !
+ !------------------------------------------------------
+
+ sub P1H, P1H, P2L !P1L <- n1-d0=n1
+ movi $ta, 1 !
+ swi $ta, [$sp+(36)] !1 -> [$sp+(36)]
+
+ move $r4,P1H ! give fudiv_qrnnd args
+ move $r5,P1L
+ move $r6,P2L
+.L29:
+ !------------------------------------------------------
+ ! fudiv_qrnnd (&q0, &n0, n1, n0, d0);
+ !------------------------------------------------------
+
+ bal fudiv_qrnnd !calcuate q0, n0
+ swi $r7,[$sp+(32)] !q0 store
+ move P1L,$r8 !n0
+.L19:
+ !------------------------------------------------------
+ ! if (rp != 0)
+ ! {
+ !------------------------------------------------------
+
+ beqz $fp, .L31 !if yes,skip
+ !------------------------------------------------------
+ ! rr.s.low = n0 >> bm;
+ ! rr.s.high = 0;
+ ! *rp = rr.ll;
+ ! }
+ !------------------------------------------------------
+
+ movi $r5, 0 !$r5 <- 0
+ lwi $r7,[$sp+(28)] !load bm
+ srl $r4, P1L, $r7 !$r4 <- n0>>bm
+ swi $r4, [$fp+OFFSET_L] !r0 !$r4 -> [$sp+(48)]
+ swi $r5, [$fp+OFFSET_H] !r1 !0 -> [$sp+(52)]
+ b .L31
+.L9:
+ !------------------------------------------------------
+ ! else # d1 == 0
+ ! {
+ ! if(d1 > n1)
+ ! {
+ !------------------------------------------------------
+
+ slt $ta, P1H, P2H !$ta <- n1<d1
+ beqz $ta, .L32 !if yes,skip
+ !------------------------------------------------------
+ ! q0 = 0;
+ ! q1 = 0;
+ ! if (rp != 0)
+ ! {
+ !------------------------------------------------------
+
+ movi $r5, 0 !$r5 <- 0
+ swi $r5, [$sp+(32)] !q0 !0 -> [$sp+(40)]=q1
+ swi $r5, [$sp+(36)] !q1 !0 -> [$sp+(32)]=q0
+ beqz $fp, .L31 !if yes,skip
+ !------------------------------------------------------
+ ! rr.s.low = n0;
+ ! rr.s.high = n1;
+ ! *rp = rr.ll;
+ ! }
+ !------------------------------------------------------
+
+ swi P1L, [$fp+OFFSET_L] !P1L -> [rp]
+ swi P1H, [$fp+OFFSET_H] !P1H -> [rp+4]
+ b .L31
+.L32:
+#ifndef __NDS32_PERF_EXT__
+ smw.adm $r0, [$sp], $r5, 0
+ move $r0, P2H
+ bal __clzsi2
+ move $r7, $r0
+ lmw.bim $r0, [$sp], $r5, 0
+#else
+ clz $r7,P2H
+#endif
+ swi $r7,[$sp+(28)] !$r7=bm store
+ beqz $r7, .L42 !if yes,skip
+ !------------------------------------------------------
+ ! USItype m1, m0;
+ ! b = (4 * 8) - bm;
+ ! d1 = (d0 >> b) | (d1 << bm);
+ ! d0 = d0 << bm;
+ ! n2 = n1 >> b;
+ ! n1 = (n0 >> b) | (n1 << bm);
+ ! n0 = n0 << bm;
+ ! fudiv_qrnnd (&q0, &n1, n2, n1, d1);
+ !------------------------------------------------------
+
+ subri $r10, $r7, 32 !$r10 <- 32-bm=b
+ srl $r5, P2L, $r10 !$r5 <- d0>>b
+ sll $r6, P2H, $r7 !$r6 <- d1<<bm
+ or $r6, $r5, $r6 !$r6 <- $r5|$r6=d1 !! func
+ move P2H, $r6 !P2H <- d1
+ srl $r4, P1H, $r10 !$r4 <- n1>>b=n2 !!! func
+ srl $r8, P1L, $r10 !$r8 <- n0>>b !!$r8
+ sll $r9, P1H, $r7 !$r9 <- n1<<bm
+ or $r5, $r8, $r9 !$r5 <- $r8|$r9=n1 !func
+ sll P2L, P2L, $r7 !P2L <- d0<<bm=d0
+ sll P1L, P1L, $r7 !P1L <- n0<<bm=n0
+
+ bal fudiv_qrnnd ! cal q0,n1
+ swi $r7,[$sp+(32)]
+ move P1H,$r8 ! fudiv_qrnnd (&q0, &n1, n2, n1, d1);
+ move $r6, $r7 ! from func
+
+ !----------------------------------------------------
+ ! #umul_ppmm (m1, m0, q0, d0);
+ ! do
+ ! { USItype __x0, __x1, __x2, __x3;
+ ! USItype __ul, __vl, __uh, __vh;
+ ! __ul = ((USItype) (q0) & (((USItype) 1 << ((4 * 8) / 2)) - 1));
+ ! __uh = ((USItype) (q0) >> ((4 * 8) / 2));
+ ! __vl = ((USItype) (d0) & (((USItype) 1 << ((4 * 8) / 2)) - 1));
+ ! __vh = ((USItype) (d0) >> ((4 * 8) / 2));
+ ! __x0 = (USItype) __ul * __vl;
+ ! __x1 = (USItype) __ul * __vh;
+ ! __x2 = (USItype) __uh * __vl;
+ ! __x3 = (USItype) __uh * __vh;
+ ! __x1 += ((USItype) (__x0) >> ((4 * 8) / 2));
+ ! __x1 += __x2;
+ ! if (__x1 < __x2)
+ ! __x3 += ((USItype) 1 << ((4 * 8) / 2));
+ ! (m1) = __x3 + ((USItype) (__x1) >> ((4 * 8) / 2));
+ ! (m0) = (USItype)(q0*d0);
+ ! }
+ ! if (m1 > n1)
+ !---------------------------------------------------
+#ifdef __NDS32_ISA_V3M__
+ !mulr64 $r4, P2L, $r6
+ smw.adm $r0, [$sp], $r3, 0
+ move P1L, P2L
+ move P2L, $r6
+ movi P1H, 0
+ movi P2H, 0
+ bal __muldi3
+ movd44 $r4, $r0
+ lmw.bim $r0, [$sp], $r3, 0
+ move $r8, W6H
+ move $r5, W6L
+#else
+ mulr64 $r4, P2L, $r6
+ move $r8, W6H
+ move $r5, W6L
+#endif
+ slt $ta, P1H, $r8 !$ta <- n1<m1
+ bnez $ta, .L46 !if yes,skip
+ !------------------------------------------------------
+ ! if(m1 == n1)
+ !------------------------------------------------------
+
+ bne $r8, P1H, .L45 !if yes,skip
+ !------------------------------------------------------
+ ! if(m0 > n0)
+ !------------------------------------------------------
+
+ slt $ta, P1L, $r5 !$ta <- n0<m0
+ beqz $ta, .L45 !if yes,skip
+.L46:
+ !------------------------------------------------------
+ ! {
+ ! q0--;
+ ! # sub_ddmmss (m1, m0, m1, m0, d1, d0);
+ ! do
+ ! { USItype __x;
+ ! __x = (m0) - (d0);
+ ! (m1) = (m1) - (d1) - (__x > (m0));
+ ! (m0) = __x;
+ ! }
+ ! }
+ !------------------------------------------------------
+
+ sub $r4, $r5, P2L !$r4 <- m0-d0=__x
+ addi $r6, $r6, -1 !$r6 <- q0--=q0
+ sub $r8, $r8, P2H !$r8 <- m1-d1
+ swi $r6, [$sp+(32)] ! q0 !$r6->[$sp+(32)]
+ slt $ta, $r5, $r4 !$ta <- m0<__x
+ sub $r8, $r8, $ta !$r8 <- P1H-P1L=m1
+ move $r5, $r4 !$r5 <- __x=m0
+.L45:
+ !------------------------------------------------------
+ ! q1 = 0;
+ ! if (rp != 0)
+ ! {
+ !------------------------------------------------------
+
+ movi $r4, 0 !$r4 <- 0
+ swi $r4, [$sp+(36)] !0 -> [$sp+(40)]=q1
+ beqz $fp, .L31 !if yes,skip
+ !------------------------------------------------------
+ ! # sub_ddmmss (n1, n0, n1, n0, m1, m0);
+ ! do
+ ! { USItype __x;
+ ! __x = (n0) - (m0);
+ ! (n1) = (n1) - (m1) - (__x > (n0));
+ ! (n0) = __x;
+ ! }
+ ! rr.s.low = (n1 << b) | (n0 >> bm);
+ ! rr.s.high = n1 >> bm;
+ ! *rp = rr.ll;
+ !------------------------------------------------------
+
+ sub $r4, P1H, $r8 !$r4 <- n1-m1
+ sub $r6, P1L, $r5 !$r6 <- n0-m0=__x=n0
+ slt $ta, P1L, $r6 !$ta <- n0<__x
+ sub P1H, $r4, $ta !P1H <- $r4-$ta=n1
+ move P1L, $r6
+
+ lwi $r7,[$sp+(28)] ! load bm
+ subri $r10,$r7,32
+ sll $r4, P1H, $r10 !$r4 <- n1<<b
+ srl $r5, P1L, $r7 !$r5 <- __x>>bm
+ or $r6, $r5, $r4 !$r6 <- $r5|$r4=rr.s.low
+ srl $r8, P1H, $r7 !$r8 <- n1>>bm =rr.s.high
+ swi $r6, [$fp+OFFSET_L] !
+ swi $r8, [$fp+OFFSET_H] !
+ b .L31
+.L42:
+ !------------------------------------------------------
+ ! else
+ ! {
+ ! if(n1 > d1)
+ !------------------------------------------------------
+
+ slt $ta, P2H, P1H !$ta <- P2H<P1H
+ bnez $ta, .L52 !if yes,skip
+ !------------------------------------------------------
+ ! if (n0 >= d0)
+ !------------------------------------------------------
+
+ slt $ta, P1L, P2L !$ta <- P1L<P2L
+ bnez $ta, .L51 !if yes,skip
+ !------------------------------------------------------
+ ! q0 = 1;
+ ! do
+ ! { USItype __x;
+ ! __x = (n0) - (d0);
+ ! (n1) = (n1) - (d1) - (__x > (n0));
+ ! (n0) = __x;
+ ! }
+ !------------------------------------------------------
+.L52:
+ sub $r4, P1H, P2H !$r4 <- P1H-P2H
+ sub $r6, P1L, P2L !$r6 <- no-d0=__x=n0
+ slt $ta, P1L, $r6 !$ta <- no<__x
+ sub P1H, $r4, $ta !P1H <- $r4-$ta=n1
+ move P1L, $r6 !n0
+ movi $r5, 1 !
+ swi $r5, [$sp+(32)] !1 -> [$sp+(32)]=q0
+ b .L54
+.L51:
+ !------------------------------------------------------
+ ! q0 = 0;
+ !------------------------------------------------------
+
+ movi $r5,0
+ swi $r5, [$sp+(32)] !$r5=0 -> [$sp+(32)]
+.L54:
+ !------------------------------------------------------
+ ! q1 = 0;
+ ! if (rp != 0)
+ ! {
+ !------------------------------------------------------
+
+ movi $r5, 0 !
+ swi $r5, [$sp+(36)] !0 -> [$sp+(36)]
+ beqz $fp, .L31
+ !------------------------------------------------------
+ ! rr.s.low = n0;
+ ! rr.s.high = n1;
+ ! *rp = rr.ll;
+ ! }
+ !------------------------------------------------------
+
+ swi P1L, [$fp+OFFSET_L] !remainder
+ swi P1H, [$fp+OFFSET_H] !
+.L31:
+ !------------------------------------------------------
+ ! const DWunion ww = {{.low = q0, .high = q1}};
+ ! return ww.ll;
+ !}
+ !------------------------------------------------------
+
+ lwi P1L, [$sp+(32)] !quotient
+ lwi P1H, [$sp+(36)]
+ lmw.bim $r6, [$sp], $r10, 10
+ addi $sp, $sp, 12
+ ret
+ .size __udivmoddi4, .-__udivmoddi4
+#endif /* L_udivmoddi4 */
+
+
+
+#ifdef L_umodsi3
+
+ ! =====================================================================
+ .text
+ .align 2
+ .globl __umodsi3
+ .type __umodsi3, @function
+__umodsi3:
+ ! ---------------------------------------------------------------------
+ !!res=udivmodsi4(a,b,1);
+ ! if (den==0)
+ ! return num;
+ ! ---------------------------------------------------------------------
+ beqz $r1, .L1 ! if den==0, skip
+ ! ---------------------------------------------------------------------
+ ! bit=1;
+ ! res=0;
+ ! ---------------------------------------------------------------------
+ movi $r4, 1 ! $r4 <- bit=1
+#ifndef __OPTIMIZE_SIZE__
+.L6:
+#endif
+ ! ---------------------------------------------------------------------
+ ! while (den<num
+ ! ---------------------------------------------------------------------
+ slt $ta, $r1, $r0 ! $ta <- den<num?
+ beqz $ta, .L5 ! if no, skip
+ ! ---------------------------------------------------------------------
+ ! &&bit&&!(den&(1L<<31)))
+ ! ---------------------------------------------------------------------
+ bltz $r1, .L5 ! if den<0, skip
+ ! ---------------------------------------------------------------------
+ ! { den<<=1;
+ ! bit<<=1;
+ ! }
+ ! ---------------------------------------------------------------------
+#if defined (__OPTIMIZE_SIZE__) && ! defined (__NDS32_ISA_V3M__)
+ clz $r3, $r1 ! $r3 <- leading zero count for den
+ clz $ta, $r0 ! $ta <- leading zero count for num
+ sub $r3, $r3, $ta ! $r3 <- number of bits to shift
+ sll $r1, $r1, $r3 ! $r1 <- den
+ sll $r4, $r4, $r3 ! $r2 <- bit
+#else
+ slli $r1, $r1, 1 ! $r1 <- den<<=1
+ slli $r4, $r4, 1 ! $r4 <- bit<<=1
+ b .L6 ! continue loop
+#endif
+.L5:
+ ! ---------------------------------------------------------------------
+ ! while (bit)
+ ! { if (num>=den)
+ ! { num-=den;
+ ! res|=bit;
+ ! }
+ ! bit>>=1;
+ ! den>>=1;
+ ! }
+ !!if (modwanted)
+ !! return num;
+ !!return res;
+ ! ---------------------------------------------------------------------
+ sub $r2, $r0, $r1 ! $r2 <- num-den
+ slt $ta, $r0, $r1 ! $ta <- num<den?
+ srli $r4, $r4, 1 ! $r4 <- bit>>=1
+ cmovz $r0, $r2, $ta ! $r0 <- num=(num<den)?num:num-den
+ srli $r1, $r1, 1 ! $r1 <- den>>=1
+ bnez $r4, .L5 ! if bit!=0, continue loop
+.L1:
+ ! ---------------------------------------------------------------------
+ ! return res;
+ ! ---------------------------------------------------------------------
+ ret
+ .size __umodsi3, .-__umodsi3
+#endif /* L_umodsi3 */
+
+
+
+#ifdef L_umoddi3
+
+ !--------------------------------------
+ #ifdef __big_endian__
+ #define V1H $r0
+ #define V1L $r1
+ #define V2H $r2
+ #define V2L $r3
+ #else
+ #define V1H $r1
+ #define V1L $r0
+ #define V2H $r3
+ #define V2L $r2
+ #endif
+ !--------------------------------------
+ .text
+ .align 2
+ .globl __umoddi3
+ .type __umoddi3, @function
+__umoddi3:
+ ! prologue
+ addi $sp, $sp, -12
+ swi $lp, [$sp+(0)]
+ ! end of prologue
+ addi $r4, $sp, 4
+ bal __udivmoddi4
+ lwi $r0, [$sp+(4)] ! __udivmoddi4 return low when LE mode or return high when BE mode
+ lwi $r1, [$sp+(8)] !
+.L82:
+ ! epilogue
+ lwi $lp, [$sp+(0)]
+ addi $sp, $sp, 12
+ ret
+ .size __umoddi3, .-__umoddi3
+#endif /* L_umoddi3 */
+
+
+
+#ifdef L_muldi3
+
+#ifdef __big_endian__
+ #define P1H $r0
+ #define P1L $r1
+ #define P2H $r2
+ #define P2L $r3
+
+ #define V2H $r4
+ #define V2L $r5
+#else
+ #define P1H $r1
+ #define P1L $r0
+ #define P2H $r3
+ #define P2L $r2
+
+ #define V2H $r5
+ #define V2L $r4
+#endif
+
+ ! ====================================================================
+ .text
+ .align 2
+ .globl __muldi3
+ .type __muldi3, @function
+__muldi3:
+ ! parameter passing for libgcc functions normally involves 2 doubles
+ !---------------------------------------
+#ifdef __NDS32_ISA_V3M__
+ ! There is no mulr64 instruction in Andes ISA V3M.
+ ! So we must provide a sequence of calculations to complete the job.
+ smw.adm $r6, [$sp], $r9, 0x0
+ zeh33 $r4, P1L
+ srli $r7, P1L, 16
+ zeh33 $r5, P2L
+ mul $r6, $r5, $r4
+ mul33 $r5, $r7
+ srli $r8, P2L, 16
+ mov55 $r9, $r5
+ maddr32 $r9, $r8, $r4
+ srli $r4, $r6, 16
+ add $r4, $r9, $r4
+ slt45 $r4, $r5
+ slli $r5, $r15, 16
+ maddr32 $r5, $r8, $r7
+ mul P2L, P1H, P2L
+ srli $r7, $r4, 16
+ maddr32 P2L, P2H, P1L
+ add333 P1H, $r5, $r7
+ slli $r4, $r4, 16
+ zeh33 $r6, $r6
+ add333 P1L, $r4, $r6
+ add333 P1H, P2L, P1H
+ lmw.bim $r6, [$sp], $r9, 0x0
+ ret
+#else /* not __NDS32_ISA_V3M__ */
+ mul $ta, P1L, P2H
+ mulr64 $r4, P1L, P2L
+ maddr32 $ta, P1H, P2L
+ move P1L, V2L
+ add P1H, $ta, V2H
+ ret
+#endif /* not __NDS32_ISA_V3M__ */
+ .size __muldi3, .-__muldi3
+#endif /* L_muldi3 */
+
+
+
+#ifdef L_addsub_df
+
+#ifndef __big_endian__
+ #define P1L $r0
+ #define P1H $r1
+ #define P2L $r2
+ #define P2H $r3
+ #define P3L $r4
+ #define P3H $r5
+ #define O1L $r7
+ #define O1H $r8
+#else
+ #define P1H $r0
+ #define P1L $r1
+ #define P2H $r2
+ #define P2L $r3
+ #define P3H $r4
+ #define P3L $r5
+ #define O1H $r7
+ #define O1L $r8
+#endif
+ .text
+ .align 2
+ .global __subdf3
+ .type __subdf3, @function
+__subdf3:
+ push $lp
+ pushm $r6, $r10
+
+ move $r4, #0x80000000
+ xor P2H, P2H, $r4
+
+ j .Lsdpadd
+
+ .global __adddf3
+ .type __adddf3, @function
+__adddf3:
+ push $lp
+ pushm $r6, $r10
+.Lsdpadd:
+ slli $r6, P1H, #1
+ srli $r6, $r6, #21
+ slli P3H, P1H, #11
+ srli $r10, P1L, #21
+ or P3H, P3H, $r10
+ slli P3L, P1L, #11
+ move O1L, #0x80000000
+ or P3H, P3H, O1L
+ slli $r9, P2H, #1
+ srli $r9, $r9, #21
+ slli O1H, P2H, #11
+ srli $r10, P2L, #21
+ or O1H, O1H, $r10
+ or O1H, O1H, O1L
+ slli O1L, P2L, #11
+
+ addi $r10, $r6, #-1
+ slti $r15, $r10, #0x7fe
+ beqzs8 .LEspecA
+
+.LElab1:
+ addi $r10, $r9, #-1
+ slti $r15, $r10, #0x7fe
+ beqzs8 .LEspecB
+
+.LElab2:
+ #NORMd($r4, P2L, P1L)
+ bnez P3H, .LL1
+ bnez P3L, .LL2
+ move $r6, #0
+ j .LL3
+.LL2:
+ move P3H, P3L
+ move P3L, #0
+ move P2L, #32
+ sub $r6, $r6, P2L
+.LL1:
+#ifndef __big_endian__
+#ifdef __NDS32_PERF_EXT__
+ clz $r2, $r5
+#else
+ pushm $r0, $r1
+ pushm $r3, $r5
+ move $r0, $r5
+ bal __clzsi2
+ move $r2, $r0
+ popm $r3, $r5
+ popm $r0, $r1
+#endif
+#else /* __big_endian__ */
+#ifdef __NDS32_PERF_EXT__
+ clz $r3, $r4
+#else
+ pushm $r0, $r2
+ pushm $r4, $r5
+ move $r0, $r4
+ bal __clzsi2
+ move $r3, $r0
+ popm $r4, $r5
+ popm $r0, $r2
+#endif
+#endif /* __big_endian__ */
+ beqz P2L, .LL3
+ sub $r6, $r6, P2L
+ subri P1L, P2L, #32
+ srl P1L, P3L, P1L
+ sll P3L, P3L, P2L
+ sll P3H, P3H, P2L
+ or P3H, P3H, P1L
+.LL3:
+ #NORMd End
+
+ #NORMd($r7, P2L, P1L)
+ bnez O1H, .LL4
+ bnez O1L, .LL5
+ move $r9, #0
+ j .LL6
+.LL5:
+ move O1H, O1L
+ move O1L, #0
+ move P2L, #32
+ sub $r9, $r9, P2L
+.LL4:
+#ifndef __big_endian__
+#ifdef __NDS32_PERF_EXT__
+ clz $r2, O1H
+#else
+ pushm $r0, $r1
+ pushm $r3, $r5
+ move $r0, O1H
+ bal __clzsi2
+ move $r2, $r0
+ popm $r3, $r5
+ popm $r0, $r1
+#endif
+#else /* __big_endian__ */
+#ifdef __NDS32_PERF_EXT__
+ clz $r3, O1H
+#else
+ pushm $r0, $r2
+ pushm $r4, $r5
+ move $r0, O1H
+ bal __clzsi2
+ move $r3, $r0
+ popm $r4, $r5
+ popm $r0, $r2
+#endif
+#endif /* __big_endian__ */
+ beqz P2L, .LL6
+ sub $r9, $r9, P2L
+ subri P1L, P2L, #32
+ srl P1L, O1L, P1L
+ sll O1L, O1L, P2L
+ sll O1H, O1H, P2L
+ or O1H, O1H, P1L
+.LL6:
+ #NORMd End
+
+ move $r10, #0x80000000
+ and P1H, P1H, $r10
+
+ beq $r6, $r9, .LEadd3
+ slts $r15, $r9, $r6
+ beqzs8 .Li1
+ sub $r9, $r6, $r9
+ move P2L, #0
+.LL7:
+ move $r10, #0x20
+ slt $r15, $r9, $r10
+ bnezs8 .LL8
+ or P2L, P2L, O1L
+ move O1L, O1H
+ move O1H, #0
+ addi $r9, $r9, #0xffffffe0
+ bnez O1L, .LL7
+.LL8:
+ beqz $r9, .LEadd3
+ move P1L, O1H
+ move $r10, O1L
+ srl O1L, O1L, $r9
+ srl O1H, O1H, $r9
+ subri $r9, $r9, #0x20
+ sll P1L, P1L, $r9
+ or O1L, O1L, P1L
+ sll $r10, $r10, $r9
+ or P2L, P2L, $r10
+ beqz P2L, .LEadd3
+ ori O1L, O1L, #1
+ j .LEadd3
+.Li1:
+ move $r15, $r6
+ move $r6, $r9
+ sub $r9, $r9, $r15
+ move P2L, #0
+.LL10:
+ move $r10, #0x20
+ slt $r15, $r9, $r10
+ bnezs8 .LL11
+ or P2L, P2L, P3L
+ move P3L, P3H
+ move P3H, #0
+ addi $r9, $r9, #0xffffffe0
+ bnez P3L, .LL10
+.LL11:
+ beqz $r9, .LEadd3
+ move P1L, P3H
+ move $r10, P3L
+ srl P3L, P3L, $r9
+ srl P3H, P3H, $r9
+ subri $r9, $r9, #0x20
+ sll P1L, P1L, $r9
+ or P3L, P3L, P1L
+ sll $r10, $r10, $r9
+ or P2L, P2L, $r10
+ beqz P2L, .LEadd3
+ ori P3L, P3L, #1
+
+.LEadd3:
+ xor $r10, P1H, P2H
+ sltsi $r15, $r10, #0
+ bnezs8 .LEsub1
+
+ #ADD(P3L, O1L)
+ add P3L, P3L, O1L
+ slt $r15, P3L, O1L
+
+ #ADDCC(P3H, O1H)
+ beqzs8 .LL13
+ add P3H, P3H, O1H
+ slt $r15, P3H, O1H
+ beqzs8 .LL14
+ addi P3H, P3H, #0x1
+ j .LL15
+.LL14:
+ move $r15, #1
+ add P3H, P3H, $r15
+ slt $r15, P3H, $r15
+ j .LL15
+.LL13:
+ add P3H, P3H, O1H
+ slt $r15, P3H, O1H
+.LL15:
+
+ beqzs8 .LEres
+ andi $r10, P3L, #1
+ beqz $r10, .Li3
+ ori P3L, P3L, #2
+.Li3:
+ srli P3L, P3L, #1
+ slli $r10, P3H, #31
+ or P3L, P3L, $r10
+ srli P3H, P3H, #1
+ move $r10, #0x80000000
+ or P3H, P3H, $r10
+ addi $r6, $r6, #1
+ subri $r15, $r6, #0x7ff
+ bnezs8 .LEres
+ move $r10, #0x7ff00000
+ or P1H, P1H, $r10
+ move P1L, #0
+ j .LEretA
+
+.LEsub1:
+ #SUB(P3L, O1L)
+ move $r15, P3L
+ sub P3L, P3L, O1L
+ slt $r15, $r15, P3L
+
+ #SUBCC(P3H, O1H)
+ beqzs8 .LL16
+ move $r15, P3H
+ sub P3H, P3H, O1H
+ slt $r15, $r15, P3H
+ beqzs8 .LL17
+ subi333 P3H, P3H, #1
+ j .LL18
+.LL17:
+ move $r15, P3H
+ subi333 P3H, P3H, #1
+ slt $r15, $r15, P3H
+ j .LL18
+.LL16:
+ move $r15, P3H
+ sub P3H, P3H, O1H
+ slt $r15, $r15, P3H
+.LL18:
+
+ beqzs8 .Li5
+ move $r10, #0x80000000
+ xor P1H, P1H, $r10
+
+ subri P3H, P3H, #0
+ beqz P3L, .LL19
+ subri P3L, P3L, #0
+ subi45 P3H, #1
+.LL19:
+
+.Li5:
+ #NORMd($r4, $r9, P1L)
+ bnez P3H, .LL20
+ bnez P3L, .LL21
+ move $r6, #0
+ j .LL22
+.LL21:
+ move P3H, P3L
+ move P3L, #0
+ move $r9, #32
+ sub $r6, $r6, $r9
+.LL20:
+#ifdef __NDS32_PERF_EXT__
+ clz $r9, P3H
+#else
+ pushm $r0, $r5
+ move $r0, P3H
+ bal __clzsi2
+ move $r9, $r0
+ popm $r0, $r5
+#endif
+ beqz $r9, .LL22
+ sub $r6, $r6, $r9
+ subri P1L, $r9, #32
+ srl P1L, P3L, P1L
+ sll P3L, P3L, $r9
+ sll P3H, P3H, $r9
+ or P3H, P3H, P1L
+.LL22:
+ #NORMd End
+
+ or $r10, P3H, P3L
+ bnez $r10, .LEres
+ move P1H, #0
+
+.LEres:
+ blez $r6, .LEund
+
+.LElab8:
+ #ADD(P3L, $0x400)
+ move $r15, #0x400
+ add P3L, P3L, $r15
+ slt $r15, P3L, $r15
+
+ #ADDCC(P3H, $0x0)
+ beqzs8 .LL25
+ add P3H, P3H, $r15
+ slt $r15, P3H, $r15
+.LL25:
+
+ #ADDC($r6, $0x0)
+ add $r6, $r6, $r15
+ srli $r10, P3L, #11
+ andi $r10, $r10, #1
+ sub P3L, P3L, $r10
+ srli P1L, P3L, #11
+ slli $r10, P3H, #21
+ or P1L, P1L, $r10
+ slli $r10, P3H, #1
+ srli $r10, $r10, #12
+ or P1H, P1H, $r10
+ slli $r10, $r6, #20
+ or P1H, P1H, $r10
+
+.LEretA:
+.LE999:
+ popm $r6, $r10
+ pop $lp
+ ret5 $lp
+
+.LEspecA:
+ #ADD(P3L, P3L)
+ move $r15, P3L
+ add P3L, P3L, P3L
+ slt $r15, P3L, $r15
+
+ #ADDC(P3H, P3H)
+ add P3H, P3H, P3H
+ add P3H, P3H, $r15
+ bnez $r6, .Li7
+ or $r10, P3H, P3L
+ beqz $r10, .Li8
+ j .LElab1
+.Li8:
+ subri $r15, $r9, #0x7ff
+ beqzs8 .LEspecB
+ add P3L, P2H, P2H
+ or $r10, P3L, P2L
+ bnez $r10, .LEretB
+ sltsi $r15, P2H, #0
+ bnezs8 .LEretA
+
+.LEretB:
+ move P1L, P2L
+ move P1H, P2H
+ j .LE999
+.Li7:
+ or $r10, P3H, P3L
+ bnez $r10, .LEnan
+ subri $r15, $r9, #0x7ff
+ bnezs8 .LEretA
+ xor $r10, P1H, P2H
+ sltsi $r15, $r10, #0
+ bnezs8 .LEnan
+ j .LEretB
+
+.LEspecB:
+ #ADD(O1L, O1L)
+ move $r15, O1L
+ add O1L, O1L, O1L
+ slt $r15, O1L, $r15
+
+ #ADDC(O1H, O1H)
+ add O1H, O1H, O1H
+ add O1H, O1H, $r15
+ bnez $r9, .Li11
+ or $r10, O1H, O1L
+ beqz $r10, .LEretA
+ j .LElab2
+.Li11:
+ or $r10, O1H, O1L
+ beqz $r10, .LEretB
+
+.LEnan:
+ move P1H, #0xfff80000
+ move P1L, #0
+ j .LEretA
+
+.LEund:
+ subri $r9, $r6, #1
+ move P2L, #0
+.LL26:
+ move $r10, #0x20
+ slt $r15, $r9, $r10
+ bnezs8 .LL27
+ or P2L, P2L, P3L
+ move P3L, P3H
+ move P3H, #0
+ addi $r9, $r9, #0xffffffe0
+ bnez P3L, .LL26
+.LL27:
+ beqz $r9, .LL28
+ move P1L, P3H
+ move $r10, P3L
+ srl P3L, P3L, $r9
+ srl P3H, P3H, $r9
+ subri $r9, $r9, #0x20
+ sll P1L, P1L, $r9
+ or P3L, P3L, P1L
+ sll $r10, $r10, $r9
+ or P2L, P2L, $r10
+ beqz P2L, .LL28
+ ori P3L, P3L, #1
+.LL28:
+ move $r6, #0
+ j .LElab8
+ .size __subdf3, .-__subdf3
+ .size __adddf3, .-__adddf3
+#endif /* L_addsub_df */
+
+
+
+#ifdef L_mul_sf
+
+#if !defined (__big_endian__)
+ #define P1L $r0
+ #define P1H $r1
+ #define P2L $r2
+ #define P2H $r3
+#else
+ #define P1H $r0
+ #define P1L $r1
+ #define P2H $r2
+ #define P2L $r3
+#endif
+ .text
+ .align 2
+ .global __mulsf3
+ .type __mulsf3, @function
+__mulsf3:
+ push $lp
+ pushm $r6, $r10
+
+ srli $r3, $r0, #23
+ andi $r3, $r3, #0xff
+ srli $r5, $r1, #23
+ andi $r5, $r5, #0xff
+ move $r6, #0x80000000
+ slli $r2, $r0, #8
+ or $r2, $r2, $r6
+ slli $r4, $r1, #8
+ or $r4, $r4, $r6
+ xor $r8, $r0, $r1
+ and $r6, $r6, $r8
+
+ addi $r8, $r3, #-1
+ slti $r15, $r8, #0xfe
+ beqzs8 .LFspecA
+
+.LFlab1:
+ addi $r8, $r5, #-1
+ slti $r15, $r8, #0xfe
+ beqzs8 .LFspecB
+
+.LFlab2:
+ move $r10, $r3
+/* This is a 64-bit multiple. ($r2, $r7) is (high, low). */
+#ifndef __NDS32_ISA_V3M__
+ mulr64 $r2, $r2, $r4
+#else
+ pushm $r0, $r1
+ pushm $r4, $r5
+ move P1L, $r2
+ movi P1H, #0
+ move P2L, $r4
+ movi P2H, #0
+ bal __muldi3
+ movd44 $r2, $r0
+ popm $r4, $r5
+ popm $r0, $r1
+#endif
+#ifndef __big_endian__
+ move $r7, $r2
+ move $r2, $r3
+#else
+ move $r7, $r3
+#endif
+ move $r3, $r10
+
+ beqz $r7, .Li17
+ ori $r2, $r2, #1
+
+.Li17:
+ sltsi $r15, $r2, #0
+ bnezs8 .Li18
+ slli $r2, $r2, #1
+ addi $r3, $r3, #-1
+.Li18:
+ addi $r8, $r5, #0xffffff82
+ add $r3, $r3, $r8
+ addi $r8, $r3, #-1
+ slti $r15, $r8, #0xfe
+ beqzs8 .LFoveund
+
+.LFlab8:
+ #ADD($r2, $0x80)
+ move $r15, #0x80
+ add $r2, $r2, $r15
+ slt $r15, $r2, $r15
+
+ #ADDC($r3, $0x0)
+ add $r3, $r3, $r15
+ srli $r8, $r2, #8
+ andi $r8, $r8, #1
+ sub $r2, $r2, $r8
+ slli $r2, $r2, #1
+ srli $r2, $r2, #9
+ slli $r8, $r3, #23
+ or $r2, $r2, $r8
+ or $r0, $r2, $r6
+
+.LF999:
+ popm $r6, $r10
+ pop $lp
+ ret5 $lp
+
+.LFspecA:
+ bnez $r3, .Li19
+ add $r2, $r2, $r2
+ beqz $r2, .Li20
+#ifdef __NDS32_PERF_EXT__
+ clz $r7, $r2
+#else
+ pushm $r0, $r5
+ move $r0, $r2
+ bal __clzsi2
+ move $r7, $r0
+ popm $r0, $r5
+#endif
+ sub $r3, $r3, $r7
+ sll $r2, $r2, $r7
+ j .LFlab1
+.Li20:
+ subri $r15, $r5, #0xff
+ beqzs8 .LFnan
+ j .LFzer
+.Li19:
+ add $r8, $r2, $r2
+ bnez $r8, .LFnan
+ bnez $r5, .Li21
+ add $r8, $r4, $r4
+ beqz $r8, .LFnan
+.Li21:
+ subri $r15, $r5, #0xff
+ bnezs8 .LFinf
+
+.LFspecB:
+ bnez $r5, .Li22
+ add $r4, $r4, $r4
+ beqz $r4, .LFzer
+#ifdef __NDS32_PERF_EXT__
+ clz $r7, $r4
+#else
+ pushm $r0, $r5
+ move $r0, $r4
+ bal __clzsi2
+ move $r7, $r0
+ popm $r0, $r5
+#endif
+ sub $r5, $r5, $r7
+ sll $r4, $r4, $r7
+ j .LFlab2
+
+.LFzer:
+ move $r0, $r6
+ j .LF999
+.Li22:
+ add $r8, $r4, $r4
+ bnez $r8, .LFnan
+
+.LFinf:
+ move $r8, #0x7f800000
+ or $r0, $r6, $r8
+ j .LF999
+
+.LFnan:
+ move $r0, #0xffc00000
+ j .LF999
+
+.LFoveund:
+ bgtz $r3, .LFinf
+ subri $r7, $r3, #1
+ slti $r15, $r7, #0x20
+ beqzs8 .LFzer
+ subri $r8, $r7, #0x20
+ sll $r3, $r2, $r8
+ srl $r2, $r2, $r7
+ beqz $r3, .Li25
+ ori $r2, $r2, #2
+.Li25:
+ move $r3, #0
+ addi $r8, $r2, #0x80
+ sltsi $r15, $r8, #0
+ beqzs8 .LFlab8
+ move $r3, #1
+ j .LFlab8
+ .size __mulsf3, .-__mulsf3
+#endif /* L_mul_sf */
+
+
+
+#ifdef L_mul_df
+
+#ifndef __big_endian__
+ #define P1L $r0
+ #define P1H $r1
+ #define P2L $r2
+ #define P2H $r3
+ #define P3L $r4
+ #define P3H $r5
+ #define O1L $r7
+ #define O1H $r8
+#else
+ #define P1H $r0
+ #define P1L $r1
+ #define P2H $r2
+ #define P2L $r3
+ #define P3H $r4
+ #define P3L $r5
+ #define O1H $r7
+ #define O1L $r8
+#endif
+ .text
+ .align 2
+ .global __muldf3
+ .type __muldf3, @function
+__muldf3:
+ push $lp
+ pushm $r6, $r10
+
+ slli $r6, P1H, #1
+ srli $r6, $r6, #21
+ slli P3H, P1H, #11
+ srli $r10, P1L, #21
+ or P3H, P3H, $r10
+ slli P3L, P1L, #11
+ move O1L, #0x80000000
+ or P3H, P3H, O1L
+ slli $r9, P2H, #1
+ srli $r9, $r9, #21
+ slli O1H, P2H, #11
+ srli $r10, P2L, #21
+ or O1H, O1H, $r10
+ or O1H, O1H, O1L
+ xor P1H, P1H, P2H
+ and P1H, P1H, O1L
+ slli O1L, P2L, #11
+
+ addi $r10, $r6, #-1
+ slti $r15, $r10, #0x7fe
+ beqzs8 .LFspecA
+
+.LFlab1:
+ addi $r10, $r9, #-1
+ slti $r15, $r10, #0x7fe
+ beqzs8 .LFspecB
+
+.LFlab2:
+ addi $r10, $r9, #0xfffffc02
+ add $r6, $r6, $r10
+
+ move $r10, $r8
+/* This is a 64-bit multiple. */
+#ifndef __big_endian__
+/* For little endian: ($r9, $r3) is (high, low). */
+#ifndef __NDS32_ISA_V3M__
+ mulr64 $r8, $r5, $r8
+#else
+ pushm $r0, $r5
+ move $r0, $r5
+ movi $r1, #0
+ move $r2, $r8
+ movi $r3, #0
+ bal __muldi3
+ movd44 $r8, $r0
+ popm $r0, $r5
+#endif
+ move $r3, $r8
+#else /* __big_endian__ */
+/* For big endain: ($r9, $r2) is (high, low). */
+#ifndef __NDS32_ISA_V3M__
+ mulr64 $r8, $r4, $r7
+#else
+ pushm $r0, $r5
+ move $r1, $r4
+ movi $r0, #0
+ move $r3, $r7
+ movi $r2, #0
+ bal __muldi3
+ movd44 $r8, $r0
+ popm $r0, $r5
+#endif
+ move $r2, $r9
+ move $r9, $r8
+#endif /* __big_endian__ */
+ move $r8, $r10
+
+ move $r10, P1H
+/* This is a 64-bit multiple. */
+#ifndef __big_endian__
+/* For little endian: ($r0, $r2) is (high, low). */
+#ifndef __NDS32_ISA_V3M__
+ mulr64 $r0, $r4, $r8
+#else
+ pushm $r2, $r5
+ move $r0, $r4
+ movi $r1, #0
+ move $r2, $r8
+ movi $r3, #0
+ bal __muldi3
+ popm $r2, $r5
+#endif
+ move $r2, $r0
+ move $r0, $r1
+#else /* __big_endian__ */
+/* For big endain: ($r1, $r3) is (high, low). */
+#ifndef __NDS32_ISA_V3M__
+ mulr64 $r0, $r5, $r7
+#else
+ pushm $r2, $r5
+ move $r1, $r5
+ movi $r0, #0
+ move $r3, $r7
+ movi $r2, #0
+ bal __muldi3
+ popm $r2, $r5
+#endif
+ move $r3, $r1
+ move $r1, $r0
+#endif /* __big_endian__ */
+ move P1H, $r10
+
+ #ADD(P2H, P1L)
+ add P2H, P2H, P1L
+ slt $r15, P2H, P1L
+
+ #ADDC($r9, $0x0)
+ add $r9, $r9, $r15
+
+ move $r10, P1H
+/* This is a 64-bit multiple. */
+#ifndef __big_endian__
+/* For little endian: ($r0, $r8) is (high, low). */
+#ifndef __NDS32_ISA_V3M__
+ mulr64 $r0, $r5, $r7
+#else
+ pushm $r2, $r5
+ move $r0, $r5
+ movi $r1, #0
+ move $r2, $r7
+ movi $r3, #0
+ bal __muldi3
+ popm $r2, $r5
+#endif
+ move $r8, $r0
+ move $r0, $r1
+#else /* __big_endian__ */
+/* For big endian: ($r1, $r7) is (high, low). */
+#ifndef __NDS32_ISA_V3M__
+ mulr64 $r0, $r4, $r8
+#else
+ pushm $r2, $r5
+ move $r1, $r4
+ movi $r0, #0
+ move $r3, $r8
+ movi $r2, #0
+ bal __muldi3
+ popm $r2, $r5
+#endif
+ move $r7, $r1
+ move $r1, $r0
+#endif /* __big_endian__ */
+ move P1H, $r10
+
+ #ADD(P2L, O1H)
+ add P2L, P2L, O1H
+ slt $r15, P2L, O1H
+
+
+ #ADDCC(P2H, P1L)
+ beqzs8 .LL29
+ add P2H, P2H, P1L
+ slt $r15, P2H, P1L
+ beqzs8 .LL30
+ addi P2H, P2H, #0x1
+ j .LL31
+.LL30:
+ move $r15, #1
+ add P2H, P2H, $r15
+ slt $r15, P2H, $r15
+ j .LL31
+.LL29:
+ add P2H, P2H, P1L
+ slt $r15, P2H, P1L
+.LL31:
+
+ #ADDC($r9, $0x0)
+ add $r9, $r9, $r15
+
+/* This is a 64-bit multiple. */
+#ifndef __big_endian__
+/* For little endian: ($r8, $r0) is (high, low). */
+ move $r10, $r9
+#ifndef __NDS32_ISA_V3M__
+ mulr64 $r8, $r4, $r7
+#else
+ pushm $r0, $r5
+ move $r0, $r4
+ movi $r1, #0
+ move $r2, $r7
+ movi $r3, #0
+ bal __muldi3
+ movd44 $r8, $r0
+ popm $r0, $r5
+#endif
+ move $r0, $r8
+ move $r8, $r9
+ move $r9, $r10
+#else /* __big_endian__ */
+/* For big endian: ($r7, $r1) is (high, low). */
+ move $r10, $r6
+#ifndef __NDS32_ISA_V3M__
+ mulr64 $r6, $r5, $r8
+#else
+ pushm $r0, $r5
+ move $r1, $r5
+ movi $r0, #0
+ move $r3, $r8
+ movi $r2, #0
+ bal __muldi3
+ movd44 $r6, $r0
+ popm $r0, $r5
+#endif
+ move $r1, $r7
+ move $r7, $r6
+ move $r6, $r10
+#endif /* __big_endian__ */
+
+ #ADD(P2L, O1H)
+ add P2L, P2L, O1H
+ slt $r15, P2L, O1H
+
+
+ #ADDCC(P2H, $0x0)
+ beqzs8 .LL34
+ add P2H, P2H, $r15
+ slt $r15, P2H, $r15
+.LL34:
+
+ #ADDC($r9, $0x0)
+ add $r9, $r9, $r15
+ or $r10, P1L, P2L
+ beqz $r10, .Li13
+ ori P2H, P2H, #1
+.Li13:
+ move P3H, $r9
+ move P3L, P2H
+ sltsi $r15, P3H, #0
+ bnezs8 .Li14
+
+ move $r15, P3L
+ add P3L, P3L, P3L
+ slt $r15, P3L, $r15
+ add P3H, P3H, P3H
+ add P3H, P3H, $r15
+ addi $r6, $r6, #-1
+.Li14:
+ addi $r10, $r6, #-1
+ slti $r15, $r10, #0x7fe
+ beqzs8 .LFoveund
+
+ #ADD(P3L, $0x400)
+ move $r15, #0x400
+ add P3L, P3L, $r15
+ slt $r15, P3L, $r15
+
+
+ #ADDCC(P3H, $0x0)
+ beqzs8 .LL37
+ add P3H, P3H, $r15
+ slt $r15, P3H, $r15
+.LL37:
+
+ #ADDC($r6, $0x0)
+ add $r6, $r6, $r15
+
+.LFlab8:
+ srli $r10, P3L, #11
+ andi $r10, $r10, #1
+ sub P3L, P3L, $r10
+ srli P1L, P3L, #11
+ slli $r10, P3H, #21
+ or P1L, P1L, $r10
+ slli $r10, P3H, #1
+ srli $r10, $r10, #12
+ or P1H, P1H, $r10
+ slli $r10, $r6, #20
+ or P1H, P1H, $r10
+
+.LFret:
+.LF999:
+ popm $r6, $r10
+ pop $lp
+ ret5 $lp
+
+.LFspecA:
+ #ADD(P3L, P3L)
+ move $r15, P3L
+ add P3L, P3L, P3L
+ slt $r15, P3L, $r15
+
+ #ADDC(P3H, P3H)
+ add P3H, P3H, P3H
+ add P3H, P3H, $r15
+ bnez $r6, .Li15
+ or $r10, P3H, P3L
+ beqz $r10, .Li16
+
+
+ #NORMd($r4, P1L, P2H)
+ bnez P3H, .LL38
+ bnez P3L, .LL39
+ move $r6, #0
+ j .LL40
+.LL39:
+ move P3H, P3L
+ move P3L, #0
+ move P1L, #32
+ sub $r6, $r6, P1L
+.LL38:
+#ifndef __big_endian__
+#ifdef __NDS32_PERF_EXT__
+ clz $r0, P3H
+#else
+ pushm $r1, P3H
+ move $r0, P3H
+ bal __clzsi2
+ popm $r1, $r5
+#endif
+#else /* __big_endian__ */
+#ifdef __NDS32_PERF_EXT__
+ clz $r1, $r4
+#else
+ push $r0
+ pushm $r2, $r5
+ move $r0, $r4
+ bal __clzsi2
+ move $r1, $r0
+ popm $r2, $r5
+ pop $r0
+#endif
+#endif /* __big_endian__ */
+ beqz P1L, .LL40
+ sub $r6, $r6, P1L
+ subri P2H, P1L, #32
+ srl P2H, P3L, P2H
+ sll P3L, P3L, P1L
+ sll P3H, P3H, P1L
+ or P3H, P3H, P2H
+.LL40:
+ #NORMd End
+
+ j .LFlab1
+.Li16:
+ subri $r15, $r9, #0x7ff
+ beqzs8 .LFnan
+ j .LFret
+.Li15:
+ or $r10, P3H, P3L
+ bnez $r10, .LFnan
+ bnez $r9, .Li17
+ slli $r10, O1H, #1
+ or $r10, $r10, O1L
+ beqz $r10, .LFnan
+.Li17:
+ subri $r15, $r9, #0x7ff
+ bnezs8 .LFinf
+
+.LFspecB:
+ #ADD(O1L, O1L)
+ move $r15, O1L
+ add O1L, O1L, O1L
+ slt $r15, O1L, $r15
+
+ #ADDC(O1H, O1H)
+ add O1H, O1H, O1H
+ add O1H, O1H, $r15
+ bnez $r9, .Li18
+ or $r10, O1H, O1L
+ beqz $r10, .Li19
+
+
+ #NORMd($r7, P2L, P1L)
+ bnez O1H, .LL41
+ bnez O1L, .LL42
+ move $r9, #0
+ j .LL43
+.LL42:
+ move O1H, O1L
+ move O1L, #0
+ move P2L, #32
+ sub $r9, $r9, P2L
+.LL41:
+#ifndef __big_endian__
+#ifdef __NDS32_PERF_EXT__
+ clz $r2, $r8
+#else
+ pushm $r0, $r1
+ pushm $r3, $r5
+ move $r0, $r8
+ bal __clzsi2
+ move $r2, $r0
+ popm $r3, $r5
+ popm $r0, $r1
+#endif
+#else /* __big_endian__ */
+#ifdef __NDS32_PERF_EXT__
+ clz $r3, $r7
+#else
+ pushm $r0, $r2
+ pushm $r4, $r5
+ move $r0, $r7
+ bal __clzsi2
+ move $r3, $r0
+ popm $r4, $r5
+ popm $r0, $r2
+#endif
+#endif /* __big_endian__ */
+ beqz P2L, .LL43
+ sub $r9, $r9, P2L
+ subri P1L, P2L, #32
+ srl P1L, O1L, P1L
+ sll O1L, O1L, P2L
+ sll O1H, O1H, P2L
+ or O1H, O1H, P1L
+.LL43:
+ #NORMd End
+
+ j .LFlab2
+.Li19:
+ move P1L, #0
+ j .LFret
+.Li18:
+ or $r10, O1H, O1L
+ bnez $r10, .LFnan
+
+.LFinf:
+ move $r10, #0x7ff00000
+ or P1H, P1H, $r10
+ move P1L, #0
+ j .LFret
+
+.LFnan:
+ move P1H, #0xfff80000
+ move P1L, #0
+ j .LFret
+
+.LFoveund:
+ bgtz $r6, .LFinf
+ subri P1L, $r6, #1
+ move P2L, #0
+.LL44:
+ move $r10, #0x20
+ slt $r15, P1L, $r10
+ bnezs8 .LL45
+ or P2L, P2L, P3L
+ move P3L, P3H
+ move P3H, #0
+ addi P1L, P1L, #0xffffffe0
+ bnez P3L, .LL44
+.LL45:
+ beqz P1L, .LL46
+ move P2H, P3H
+ move $r10, P3L
+ srl P3L, P3L, P1L
+ srl P3H, P3H, P1L
+ subri P1L, P1L, #0x20
+ sll P2H, P2H, P1L
+ or P3L, P3L, P2H
+ sll $r10, $r10, P1L
+ or P2L, P2L, $r10
+ beqz P2L, .LL46
+ ori P3L, P3L, #1
+.LL46:
+ #ADD(P3L, $0x400)
+ move $r15, #0x400
+ add P3L, P3L, $r15
+ slt $r15, P3L, $r15
+
+ #ADDC(P3H, $0x0)
+ add P3H, P3H, $r15
+ srli $r6, P3H, #31
+ j .LFlab8
+ .size __muldf3, .-__muldf3
+#endif /* L_mul_df */
+
+
+
+#ifdef L_div_sf
+
+ .text
+ .align 2
+ .global __divsf3
+ .type __divsf3, @function
+__divsf3:
+ push $lp
+ pushm $r6, $r10
+
+ move $r7, #0x80000000
+ srli $r4, $r0, #23
+ andi $r4, $r4, #0xff
+ srli $r6, $r1, #23
+ andi $r6, $r6, #0xff
+ slli $r3, $r0, #8
+ or $r3, $r3, $r7
+ slli $r5, $r1, #8
+ or $r5, $r5, $r7
+ xor $r10, $r0, $r1
+ and $r7, $r7, $r10
+
+ addi $r10, $r4, #-1
+ slti $r15, $r10, #0xfe
+ beqzs8 .LGspecA
+
+.LGlab1:
+ addi $r10, $r6, #-1
+ slti $r15, $r10, #0xfe
+ beqzs8 .LGspecB
+
+.LGlab2:
+ slt $r15, $r3, $r5
+ bnezs8 .Li27
+ srli $r3, $r3, #1
+ addi $r4, $r4, #1
+.Li27:
+ srli $r8, $r5, #14
+ divr $r0, $r2, $r3, $r8
+ andi $r9, $r5, #0x3fff
+ mul $r1, $r9, $r0
+ slli $r2, $r2, #14
+
+ #SUB($r2, $r1)
+ move $r15, $r2
+ sub $r2, $r2, $r1
+ slt $r15, $r15, $r2
+ beqzs8 .Li28
+ addi $r0, $r0, #-1
+
+ #ADD($r2, $r5)
+ add $r2, $r2, $r5
+ slt $r15, $r2, $r5
+.Li28:
+ divr $r3, $r2, $r2, $r8
+ mul $r1, $r9, $r3
+ slli $r2, $r2, #14
+
+ #SUB($r2, $r1)
+ move $r15, $r2
+ sub $r2, $r2, $r1
+ slt $r15, $r15, $r2
+ beqzs8 .Li29
+ addi $r3, $r3, #-1
+
+ #ADD($r2, $r5)
+ add $r2, $r2, $r5
+ slt $r15, $r2, $r5
+.Li29:
+ slli $r10, $r0, #14
+ add $r3, $r3, $r10
+ slli $r3, $r3, #4
+ beqz $r2, .Li30
+ ori $r3, $r3, #1
+.Li30:
+ subri $r10, $r6, #0x7e
+ add $r4, $r4, $r10
+ addi $r10, $r4, #-1
+ slti $r15, $r10, #0xfe
+ beqzs8 .LGoveund
+
+.LGlab8:
+ #ADD($r3, $0x80)
+ move $r15, #0x80
+ add $r3, $r3, $r15
+ slt $r15, $r3, $r15
+
+ #ADDC($r4, $0x0)
+ add $r4, $r4, $r15
+ srli $r10, $r3, #8
+ andi $r10, $r10, #1
+ sub $r3, $r3, $r10
+ slli $r3, $r3, #1
+ srli $r3, $r3, #9
+ slli $r10, $r4, #23
+ or $r3, $r3, $r10
+ or $r0, $r3, $r7
+
+.LG999:
+ popm $r6, $r10
+ pop $lp
+ ret5 $lp
+
+.LGspecA:
+ bnez $r4, .Li31
+ add $r3, $r3, $r3
+ beqz $r3, .Li31
+#ifdef __NDS32_PERF_EXT__
+ clz $r8, $r3
+#else
+ pushm $r0, $r5
+ move $r0, $r3
+ bal __clzsi2
+ move $r8, $r0
+ popm $r0, $r5
+#endif
+ sub $r4, $r4, $r8
+ sll $r3, $r3, $r8
+ j .LGlab1
+.Li31:
+ bne $r6, $r4, .Li33
+ add $r10, $r5, $r5
+ beqz $r10, .LGnan
+.Li33:
+ subri $r15, $r6, #0xff
+ beqzs8 .LGspecB
+ beqz $r4, .LGzer
+ add $r10, $r3, $r3
+ bnez $r10, .LGnan
+ j .LGinf
+
+.LGspecB:
+ bnez $r6, .Li34
+ add $r5, $r5, $r5
+ beqz $r5, .LGinf
+#ifdef __NDS32_PERF_EXT__
+ clz $r8, $r5
+#else
+ pushm $r0, $r5
+ move $r0, $r5
+ bal __clzsi2
+ move $r8, $r0
+ popm $r0, $r5
+#endif
+ sub $r6, $r6, $r8
+ sll $r5, $r5, $r8
+ j .LGlab2
+.Li34:
+ add $r10, $r5, $r5
+ bnez $r10, .LGnan
+
+.LGzer:
+ move $r0, $r7
+ j .LG999
+
+.LGoveund:
+ bgtz $r4, .LGinf
+ subri $r8, $r4, #1
+ slti $r15, $r8, #0x20
+ beqzs8 .LGzer
+ subri $r10, $r8, #0x20
+ sll $r4, $r3, $r10
+ srl $r3, $r3, $r8
+ beqz $r4, .Li37
+ ori $r3, $r3, #2
+.Li37:
+ move $r4, #0
+ addi $r10, $r3, #0x80
+ sltsi $r15, $r10, #0
+ beqzs8 .LGlab8
+ move $r4, #1
+ j .LGlab8
+
+.LGinf:
+ move $r10, #0x7f800000
+ or $r0, $r7, $r10
+ j .LG999
+
+.LGnan:
+ move $r0, #0xffc00000
+ j .LG999
+ .size __divsf3, .-__divsf3
+#endif /* L_div_sf */
+
+
+
+#ifdef L_div_df
+
+#ifndef __big_endian__
+ #define P1L $r0
+ #define P1H $r1
+ #define P2L $r2
+ #define P2H $r3
+ #define P3L $r4
+ #define P3H $r5
+ #define O1L $r7
+ #define O1H $r8
+#else
+ #define P1H $r0
+ #define P1L $r1
+ #define P2H $r2
+ #define P2L $r3
+ #define P3H $r4
+ #define P3L $r5
+ #define O1H $r7
+ #define O1L $r8
+#endif
+ .text
+ .align 2
+ .global __divdf3
+ .type __divdf3, @function
+__divdf3:
+ push $lp
+ pushm $r6, $r10
+
+ slli $r6, P1H, #1
+ srli $r6, $r6, #21
+ slli P3H, P1H, #11
+ srli $r10, P1L, #21
+ or P3H, P3H, $r10
+ slli P3L, P1L, #11
+ move O1L, #0x80000000
+ or P3H, P3H, O1L
+ slli $r9, P2H, #1
+ srli $r9, $r9, #21
+ slli O1H, P2H, #11
+ srli $r10, P2L, #21
+ or O1H, O1H, $r10
+ or O1H, O1H, O1L
+ xor P1H, P1H, P2H
+ and P1H, P1H, O1L
+ slli O1L, P2L, #11
+
+ addi $r10, $r6, #-1
+ slti $r15, $r10, #0x7fe
+ beqzs8 .LGspecA
+
+.LGlab1:
+ addi $r10, $r9, #-1
+ slti $r15, $r10, #0x7fe
+ beqzs8 .LGspecB
+
+.LGlab2:
+ sub $r6, $r6, $r9
+ addi $r6, $r6, #0x3ff
+ srli P3L, P3L, #1
+ slli $r10, P3H, #31
+ or P3L, P3L, $r10
+ srli P3H, P3H, #1
+ srli $r9, O1H, #16
+ divr P2H, P3H, P3H, $r9
+ move $r10, #0xffff
+ and P2L, O1H, $r10
+ mul P1L, P2L, P2H
+ slli P3H, P3H, #16
+ srli $r10, P3L, #16
+ or P3H, P3H, $r10
+
+ #SUB(P3H, P1L)
+ move $r15, P3H
+ sub P3H, P3H, P1L
+ slt $r15, $r15, P3H
+ beqzs8 .Li20
+
+.Lb21:
+ addi P2H, P2H, #-1
+ add P3H, P3H, O1H
+ slt $r15, P3H, O1H
+ beqzs8 .Lb21
+.Li20:
+ divr $r9, P3H, P3H, $r9
+ mul P1L, P2L, $r9
+ slli P3H, P3H, #16
+ move $r15, #0xffff
+ and $r10, P3L, $r15
+ or P3H, P3H, $r10
+
+ #SUB(P3H, P1L)
+ move $r15, P3H
+ sub P3H, P3H, P1L
+ slt $r15, $r15, P3H
+ beqzs8 .Li22
+
+.Lb23:
+ addi $r9, $r9, #-1
+ add P3H, P3H, O1H
+ slt $r15, P3H, O1H
+ beqzs8 .Lb23
+.Li22:
+ slli P2H, P2H, #16
+ add P2H, P2H, $r9
+
+/* This is a 64-bit multiple. */
+#ifndef __big_endian__
+/* For little endian: ($r0, $r9) is (high, low). */
+ move $r10, $r1
+#ifndef __NDS32_ISA_V3M__
+ mulr64 $r0, $r3, $r7
+#else
+ pushm $r2, $r5
+ move $r0, $r3
+ movi $r1, #0
+ move $r2, $r7
+ movi $r3, #0
+ bal __muldi3
+ popm $r2, $r5
+#endif
+ move $r9, $r0
+ move $r0, $r1
+ move $r1, $r10
+#else /* __big_endian__ */
+/* For big endian: ($r1, $r9) is (high, low). */
+ move $r10, $r0
+#ifndef __NDS32_ISA_V3M__
+ mulr64 $r0, $r2, $r8
+#else
+ pushm $r2, $r5
+ move $r1, $r2
+ movi $r0, #0
+ move $r3, $r8
+ movi $r2, #0
+ bal __muldi3
+ popm $r2, $r5
+#endif
+ move $r9, $r1
+ move $r1, $r0
+ move $r0, $r10
+#endif /* __big_endian__ */
+
+ move P3L, #0
+
+ #SUB(P3L, $r9)
+ move $r15, P3L
+ sub P3L, P3L, $r9
+ slt $r15, $r15, P3L
+
+
+ #SUBCC(P3H, P1L)
+ beqzs8 .LL47
+ move $r15, P3H
+ sub P3H, P3H, P1L
+ slt $r15, $r15, P3H
+ beqzs8 .LL48
+ subi333 P3H, P3H, #1
+ j .LL49
+.LL48:
+ move $r15, P3H
+ subi333 P3H, P3H, #1
+ slt $r15, $r15, P3H
+ j .LL49
+.LL47:
+ move $r15, P3H
+ sub P3H, P3H, P1L
+ slt $r15, $r15, P3H
+.LL49:
+
+ beqzs8 .Li24
+
+.LGlab3:
+ addi P2H, P2H, #-1
+
+ #ADD(P3L, O1L)
+ add P3L, P3L, O1L
+ slt $r15, P3L, O1L
+
+
+ #ADDCC(P3H, O1H)
+ beqzs8 .LL50
+ add P3H, P3H, O1H
+ slt $r15, P3H, O1H
+ beqzs8 .LL51
+ addi P3H, P3H, #0x1
+ j .LL52
+.LL51:
+ move $r15, #1
+ add P3H, P3H, $r15
+ slt $r15, P3H, $r15
+ j .LL52
+.LL50:
+ add P3H, P3H, O1H
+ slt $r15, P3H, O1H
+.LL52:
+
+ beqzs8 .LGlab3
+.Li24:
+ bne P3H, O1H, .Li25
+ move P1L, O1L
+ move P3H, P3L
+ move $r9, #0
+ move P2L, $r9
+ j .Le25
+.Li25:
+ srli P2L, O1H, #16
+ divr $r9, P3H, P3H, P2L
+ move $r10, #0xffff
+ and $r10, O1H, $r10
+ mul P1L, $r10, $r9
+ slli P3H, P3H, #16
+ srli $r15, P3L, #16
+ or P3H, P3H, $r15
+
+ #SUB(P3H, P1L)
+ move $r15, P3H
+ sub P3H, P3H, P1L
+ slt $r15, $r15, P3H
+ beqzs8 .Li26
+
+.Lb27:
+ addi $r9, $r9, #-1
+ add P3H, P3H, O1H
+ slt $r15, P3H, O1H
+ beqzs8 .Lb27
+.Li26:
+ divr P2L, P3H, P3H, P2L
+ mul P1L, $r10, P2L
+ slli P3H, P3H, #16
+ move $r10, #0xffff
+ and $r10, P3L, $r10
+ or P3H, P3H, $r10
+
+ #SUB(P3H, P1L)
+ move $r15, P3H
+ sub P3H, P3H, P1L
+ slt $r15, $r15, P3H
+ beqzs8 .Li28
+
+.Lb29:
+ addi P2L, P2L, #-1
+ add P3H, P3H, O1H
+ slt $r15, P3H, O1H
+ beqzs8 .Lb29
+.Li28:
+ slli $r9, $r9, #16
+ add $r9, $r9, P2L
+
+/* This is a 64-bit multiple. */
+#ifndef __big_endian__
+/* For little endian: ($r0, $r2) is (high, low). */
+ move $r10, $r1
+#ifndef __NDS32_ISA_V3M__
+ mulr64 $r0, $r9, $r7
+#else
+ pushm $r2, $r5
+ move $r0, $r9
+ movi $r1, #0
+ move $r2, $r7
+ movi $r3, #0
+ bal __muldi3
+ popm $r2, $r5
+#endif
+ move $r2, $r0
+ move $r0, $r1
+ move $r1, $r10
+#else /* __big_endian__ */
+/* For big endian: ($r1, $r3) is (high, low). */
+ move $r10, $r0
+#ifndef __NDS32_ISA_V3M__
+ mulr64 $r0, $r9, $r8
+#else
+ pushm $r2, $r5
+ move $r0, $r9
+ movi $r1, #0
+ move $r2, $r7
+ movi $r3, #0
+ bal __muldi3
+ popm $r2, $r5
+#endif
+ move $r3, $r1
+ move $r1, $r0
+ move $r0, $r10
+#endif /* __big_endian__ */
+
+.Le25:
+ move P3L, #0
+
+ #SUB(P3L, P2L)
+ move $r15, P3L
+ sub P3L, P3L, P2L
+ slt $r15, $r15, P3L
+
+
+ #SUBCC(P3H, P1L)
+ beqzs8 .LL53
+ move $r15, P3H
+ sub P3H, P3H, P1L
+ slt $r15, $r15, P3H
+ beqzs8 .LL54
+ subi333 P3H, P3H, #1
+ j .LL55
+.LL54:
+ move $r15, P3H
+ subi333 P3H, P3H, #1
+ slt $r15, $r15, P3H
+ j .LL55
+.LL53:
+ move $r15, P3H
+ sub P3H, P3H, P1L
+ slt $r15, $r15, P3H
+.LL55:
+
+ beqzs8 .Li30
+
+.LGlab4:
+ addi $r9, $r9, #-1
+
+ #ADD(P3L, O1L)
+ add P3L, P3L, O1L
+ slt $r15, P3L, O1L
+
+
+ #ADDCC(P3H, O1H)
+ beqzs8 .LL56
+ add P3H, P3H, O1H
+ slt $r15, P3H, O1H
+ beqzs8 .LL57
+ addi P3H, P3H, #0x1
+ j .LL58
+.LL57:
+ move $r15, #1
+ add P3H, P3H, $r15
+ slt $r15, P3H, $r15
+ j .LL58
+.LL56:
+ add P3H, P3H, O1H
+ slt $r15, P3H, O1H
+.LL58:
+
+ beqzs8 .LGlab4
+.Li30:
+ sltsi $r15, P2H, #0
+ bnezs8 .Li31
+
+ #ADD($r9, $r9)
+ move $r15, $r9
+ add $r9, $r9, $r9
+ slt $r15, $r9, $r15
+
+ #ADDC(P2H, P2H)
+ add P2H, P2H, P2H
+ add P2H, P2H, $r15
+ addi $r6, $r6, #-1
+.Li31:
+ or $r10, P3H, P3L
+ beqz $r10, .Li32
+ ori $r9, $r9, #1
+.Li32:
+ move P3H, P2H
+ move P3L, $r9
+ addi $r10, $r6, #-1
+ slti $r15, $r10, #0x7fe
+ beqzs8 .LGoveund
+
+ #ADD(P3L, $0x400)
+ move $r15, #0x400
+ add P3L, P3L, $r15
+ slt $r15, P3L, $r15
+
+
+ #ADDCC(P3H, $0x0)
+ beqzs8 .LL61
+ add P3H, P3H, $r15
+ slt $r15, P3H, $r15
+.LL61:
+
+ #ADDC($r6, $0x0)
+ add $r6, $r6, $r15
+
+.LGlab8:
+ srli $r10, P3L, #11
+ andi $r10, $r10, #1
+ sub P3L, P3L, $r10
+ srli P1L, P3L, #11
+ slli $r10, P3H, #21
+ or P1L, P1L, $r10
+ slli $r10, P3H, #1
+ srli $r10, $r10, #12
+ or P1H, P1H, $r10
+ slli $r10, $r6, #20
+ or P1H, P1H, $r10
+
+.LGret:
+.LG999:
+ popm $r6, $r10
+ pop $lp
+ ret5 $lp
+
+.LGoveund:
+ bgtz $r6, .LGinf
+ subri P2H, $r6, #1
+ move P1L, #0
+.LL62:
+ move $r10, #0x20
+ slt $r15, P2H, $r10
+ bnezs8 .LL63
+ or P1L, P1L, P3L
+ move P3L, P3H
+ move P3H, #0
+ addi P2H, P2H, #0xffffffe0
+ bnez P3L, .LL62
+.LL63:
+ beqz P2H, .LL64
+ move P2L, P3H
+ move $r10, P3L
+ srl P3L, P3L, P2H
+ srl P3H, P3H, P2H
+ subri P2H, P2H, #0x20
+ sll P2L, P2L, P2H
+ or P3L, P3L, P2L
+ sll $r10, $r10, P2H
+ or P1L, P1L, $r10
+ beqz P1L, .LL64
+ ori P3L, P3L, #1
+.LL64:
+ #ADD(P3L, $0x400)
+ move $r15, #0x400
+ add P3L, P3L, $r15
+ slt $r15, P3L, $r15
+
+ #ADDC(P3H, $0x0)
+ add P3H, P3H, $r15
+ srli $r6, P3H, #31
+ j .LGlab8
+
+.LGspecA:
+ #ADD(P3L, P3L)
+ move $r15, P3L
+ add P3L, P3L, P3L
+ slt $r15, P3L, $r15
+
+ #ADDC(P3H, P3H)
+ add P3H, P3H, P3H
+ add P3H, P3H, $r15
+ bnez $r6, .Li33
+ or $r10, P3H, P3L
+ beqz $r10, .Li33
+
+
+ #NORMd($r4, P2H, P2L)
+ bnez P3H, .LL65
+ bnez P3L, .LL66
+ move $r6, #0
+ j .LL67
+.LL66:
+ move P3H, P3L
+ move P3L, #0
+ move P2H, #32
+ sub $r6, $r6, P2H
+.LL65:
+#ifndef __big_endian__
+#ifdef __NDS32_PERF_EXT__
+ clz $r3, $r5
+#else
+ pushm $r0, $r2
+ pushm $r4, $r5
+ move $r0, $r5
+ bal __clzsi2
+ move $r3, $r0
+ popm $r4, $r5
+ popm $r0, $r2
+#endif
+#else /* __big_endian__ */
+#ifdef __NDS32_PERF_EXT__
+ clz $r2, $r4
+#else
+ pushm $r0, $r1
+ pushm $r3, $r5
+ move $r0, $r4
+ bal __clzsi2
+ move $r2, $r0
+ popm $r3, $r5
+ popm $r0, $r1
+#endif
+#endif /* __big_endian_ */
+ beqz P2H, .LL67
+ sub $r6, $r6, P2H
+ subri P2L, P2H, #32
+ srl P2L, P3L, P2L
+ sll P3L, P3L, P2H
+ sll P3H, P3H, P2H
+ or P3H, P3H, P2L
+.LL67:
+ #NORMd End
+
+ j .LGlab1
+.Li33:
+ bne $r6, $r9, .Li35
+ slli $r10, O1H, #1
+ or $r10, $r10, O1L
+ beqz $r10, .LGnan
+.Li35:
+ subri $r15, $r9, #0x7ff
+ beqzs8 .LGspecB
+ beqz $r6, .LGret
+ or $r10, P3H, P3L
+ bnez $r10, .LGnan
+
+.LGinf:
+ move $r10, #0x7ff00000
+ or P1H, P1H, $r10
+ move P1L, #0
+ j .LGret
+
+.LGspecB:
+ #ADD(O1L, O1L)
+ move $r15, O1L
+ add O1L, O1L, O1L
+ slt $r15, O1L, $r15
+
+ #ADDC(O1H, O1H)
+ add O1H, O1H, O1H
+ add O1H, O1H, $r15
+ bnez $r9, .Li36
+ or $r10, O1H, O1L
+ beqz $r10, .LGinf
+
+
+ #NORMd($r7, P2H, P2L)
+ bnez O1H, .LL68
+ bnez O1L, .LL69
+ move $r9, #0
+ j .LL70
+.LL69:
+ move O1H, O1L
+ move O1L, #0
+ move P2H, #32
+ sub $r9, $r9, P2H
+.LL68:
+#ifndef __big_endian__
+#ifdef __NDS32_PERF_EXT__
+ clz $r3, $r8
+#else
+ pushm $r0, $r2
+ pushm $r4, $r5
+ move $r0, $r8
+ bal __clzsi2
+ move $r3, $r0
+ popm $r4, $r5
+ popm $r0, $r2
+#endif
+#else /* __big_endian__ */
+#ifdef __NDS32_PERF_EXT__
+ clz $r2, $r7
+#else
+ pushm $r0, $r1
+ pushm $r3, $r5
+ move $r0, $r7
+ bal __clzsi2
+ move $r2, $r0
+ popm $r3, $r5
+ popm $r0, $r1
+#endif
+#endif /* __big_endian__ */
+ beqz P2H, .LL70
+ sub $r9, $r9, P2H
+ subri P2L, P2H, #32
+ srl P2L, O1L, P2L
+ sll O1L, O1L, P2H
+ sll O1H, O1H, P2H
+ or O1H, O1H, P2L
+.LL70:
+ #NORMd End
+
+ j .LGlab2
+.Li36:
+ or $r10, O1H, O1L
+ beqz $r10, .Li38
+
+.LGnan:
+ move P1H, #0xfff80000
+.Li38:
+ move P1L, #0
+ j .LGret
+ .size __divdf3, .-__divdf3
+#endif /* L_div_df */
+
+
+
+#ifdef L_negate_sf
+
+ .text
+ .align 2
+ .global __negsf2
+ .type __negsf2, @function
+__negsf2:
+ push $lp
+
+ move $r1, #0x80000000
+ xor $r0, $r0, $r1
+
+.LN999:
+ pop $lp
+ ret5 $lp
+ .size __negsf2, .-__negsf2
+#endif /* L_negate_sf */
+
+
+
+#ifdef L_negate_df
+
+#ifndef __big_endian__
+ #define P1H $r1
+#else
+ #define P1H $r0
+#endif
+ .text
+ .align 2
+ .global __negdf2
+ .type __negdf2, @function
+__negdf2:
+ push $lp
+
+ move $r2, #0x80000000
+ xor P1H, P1H, $r2
+
+.LP999:
+ pop $lp
+ ret5 $lp
+ .size __negdf2, .-__negdf2
+#endif /* L_negate_df */
+
+
+
+#ifdef L_sf_to_df
+
+#ifndef __big_endian__
+ #define O1L $r1
+ #define O1H $r2
+#else
+ #define O1H $r1
+ #define O1L $r2
+#endif
+ .text
+ .align 2
+ .global __extendsfdf2
+ .type __extendsfdf2, @function
+__extendsfdf2:
+ push $lp
+
+ srli $r3, $r0, #23
+ andi $r3, $r3, #0xff
+ move $r5, #0x80000000
+ and O1H, $r0, $r5
+ addi $r5, $r3, #-1
+ slti $r15, $r5, #0xfe
+ beqzs8 .LJspec
+
+.LJlab1:
+ addi $r3, $r3, #0x380
+ slli $r5, $r0, #9
+ srli $r5, $r5, #12
+ or O1H, O1H, $r5
+ slli O1L, $r0, #29
+
+.LJret:
+ slli $r5, $r3, #20
+ or O1H, O1H, $r5
+ move $r0, $r1
+ move $r1, $r2
+
+.LJ999:
+ pop $lp
+ ret5 $lp
+
+.LJspec:
+ move O1L, #0
+ add $r0, $r0, $r0
+ beqz $r0, .LJret
+ bnez $r3, .Li42
+
+.Lb43:
+ addi $r3, $r3, #-1
+ add $r0, $r0, $r0
+ move $r5, #0x800000
+ slt $r15, $r0, $r5
+ bnezs8 .Lb43
+ j .LJlab1
+.Li42:
+ move $r3, #0x7ff
+ move $r5, #0xff000000
+ slt $r15, $r5, $r0
+ beqzs8 .LJret
+ move O1H, #0xfff80000
+ j .LJret
+ .size __extendsfdf2, .-__extendsfdf2
+#endif /* L_sf_to_df */
+
+
+
+#ifdef L_df_to_sf
+
+#ifndef __big_endian__
+ #define P1L $r0
+ #define P1H $r1
+ #define P2L $r2
+ #define P2H $r3
+#else
+ #define P1H $r0
+ #define P1L $r1
+ #define P2H $r2
+ #define P2L $r3
+#endif
+ .text
+ .align 2
+ .global __truncdfsf2
+ .type __truncdfsf2, @function
+__truncdfsf2:
+ push $lp
+ pushm $r6, $r8
+
+ slli P2H, P1H, #11
+ srli $r7, P1L, #21
+ or P2H, P2H, $r7
+ slli P2L, P1L, #11
+ move $r7, #0x80000000
+ or P2H, P2H, $r7
+ and $r5, P1H, $r7
+ slli $r4, P1H, #1
+ srli $r4, $r4, #21
+ addi $r4, $r4, #0xfffffc80
+ addi $r7, $r4, #-1
+ slti $r15, $r7, #0xfe
+ beqzs8 .LKspec
+
+.LKlab1:
+ beqz P2L, .Li45
+ ori P2H, P2H, #1
+.Li45:
+ #ADD(P2H, $0x80)
+ move $r15, #0x80
+ add P2H, P2H, $r15
+ slt $r15, P2H, $r15
+
+ #ADDC($r4, $0x0)
+ add $r4, $r4, $r15
+ srli $r7, P2H, #8
+ andi $r7, $r7, #1
+ sub P2H, P2H, $r7
+ slli P2H, P2H, #1
+ srli P2H, P2H, #9
+ slli $r7, $r4, #23
+ or P2H, P2H, $r7
+ or $r0, P2H, $r5
+
+.LK999:
+ popm $r6, $r8
+ pop $lp
+ ret5 $lp
+
+.LKspec:
+ subri $r15, $r4, #0x47f
+ bnezs8 .Li46
+ slli $r7, P2H, #1
+ or $r7, $r7, P2L
+ beqz $r7, .Li46
+ move $r0, #0xffc00000
+ j .LK999
+.Li46:
+ sltsi $r15, $r4, #0xff
+ bnezs8 .Li48
+ move $r7, #0x7f800000
+ or $r0, $r5, $r7
+ j .LK999
+.Li48:
+ subri $r6, $r4, #1
+ move $r7, #0x20
+ slt $r15, $r6, $r7
+ bnezs8 .Li49
+ move $r0, $r5
+ j .LK999
+.Li49:
+ subri $r8, $r6, #0x20
+ sll $r7, P2H, $r8
+ or P2L, P2L, $r7
+ srl P2H, P2H, $r6
+ move $r4, #0
+ move $r7, #0x80000000
+ or P2H, P2H, $r7
+ j .LKlab1
+ .size __truncdfsf2, .-__truncdfsf2
+#endif /* L_df_to_sf */
+
+
+
+#ifdef L_df_to_si
+
+#ifndef __big_endian__
+ #define P1L $r0
+ #define P1H $r1
+#else
+ #define P1H $r0
+ #define P1L $r1
+#endif
+ .global __fixdfsi
+ .type __fixdfsi, @function
+__fixdfsi:
+ push $lp
+ pushm $r6, $r6
+
+ slli $r3, P1H, #11
+ srli $r6, P1L, #21
+ or $r3, $r3, $r6
+ move $r6, #0x80000000
+ or $r3, $r3, $r6
+ slli $r6, P1H, #1
+ srli $r6, $r6, #21
+ subri $r2, $r6, #0x41e
+ blez $r2, .LLnaninf
+ move $r6, #0x20
+ slt $r15, $r2, $r6
+ bnezs8 .LL72
+ move $r3, #0
+.LL72:
+ srl $r3, $r3, $r2
+ sltsi $r15, P1H, #0
+ beqzs8 .Li50
+ subri $r3, $r3, #0
+.Li50:
+ move $r0, $r3
+
+.LL999:
+ popm $r6, $r6
+ pop $lp
+ ret5 $lp
+
+.LLnaninf:
+ beqz P1L, .Li51
+ ori P1H, P1H, #1
+.Li51:
+ move $r6, #0x7ff00000
+ slt $r15, $r6, P1H
+ beqzs8 .Li52
+ move $r0, #0x80000000
+ j .LL999
+.Li52:
+ move $r0, #0x7fffffff
+ j .LL999
+ .size __fixdfsi, .-__fixdfsi
+#endif /* L_df_to_si */
+
+
+
+#ifdef L_fixsfdi
+
+#ifndef __big_endian__
+ #define O1L $r1
+ #define O1H $r2
+#else
+ #define O1H $r1
+ #define O1L $r2
+#endif
+ .text
+ .align 2
+ .global __fixsfdi
+ .type __fixsfdi, @function
+__fixsfdi:
+ push $lp
+
+ srli $r3, $r0, #23
+ andi $r3, $r3, #0xff
+ slli O1H, $r0, #8
+ move $r5, #0x80000000
+ or O1H, O1H, $r5
+ move O1L, #0
+ sltsi $r15, $r3, #0xbe
+ beqzs8 .LCinfnan
+ subri $r3, $r3, #0xbe
+.LL8:
+ move $r5, #0x20
+ slt $r15, $r3, $r5
+ bnezs8 .LL9
+ move O1L, O1H
+ move O1H, #0
+ addi $r3, $r3, #0xffffffe0
+ bnez O1L, .LL8
+.LL9:
+ beqz $r3, .LL10
+ move $r4, O1H
+ srl O1L, O1L, $r3
+ srl O1H, O1H, $r3
+ subri $r3, $r3, #0x20
+ sll $r4, $r4, $r3
+ or O1L, O1L, $r4
+.LL10:
+ sltsi $r15, $r0, #0
+ beqzs8 .LCret
+
+ subri O1H, O1H, #0
+ beqz O1L, .LL11
+ subri O1L, O1L, #0
+ subi45 O1H, #1
+.LL11:
+
+.LCret:
+ move $r0, $r1
+ move $r1, $r2
+
+.LC999:
+ pop $lp
+ ret5 $lp
+
+.LCinfnan:
+ sltsi $r15, $r0, #0
+ bnezs8 .LCret3
+ subri $r15, $r3, #0xff
+ bnezs8 .Li7
+ slli $r5, O1H, #1
+ beqz $r5, .Li7
+
+.LCret3:
+ move O1H, #0x80000000
+ j .LCret
+.Li7:
+ move O1H, #0x7fffffff
+ move O1L, #-1
+ j .LCret
+ .size __fixsfdi, .-__fixsfdi
+#endif /* L_fixsfdi */
+
+
+
+#ifdef L_fixdfdi
+
+#ifndef __big_endian__
+ #define P1L $r0
+ #define P1H $r1
+ #define O1L $r3
+ #define O1H $r4
+#else
+ #define P1H $r0
+ #define P1L $r1
+ #define O1H $r3
+ #define O1L $r4
+#endif
+ .text
+ .align 2
+ .global __fixdfdi
+ .type __fixdfdi, @function
+__fixdfdi:
+ push $lp
+ pushm $r6, $r6
+
+ slli $r5, P1H, #1
+ srli $r5, $r5, #21
+ slli O1H, P1H, #11
+ srli $r6, P1L, #21
+ or O1H, O1H, $r6
+ slli O1L, P1L, #11
+ move $r6, #0x80000000
+ or O1H, O1H, $r6
+ slti $r15, $r5, #0x43e
+ beqzs8 .LCnaninf
+ subri $r2, $r5, #0x43e
+.LL14:
+ move $r6, #0x20
+ slt $r15, $r2, $r6
+ bnezs8 .LL15
+ move O1L, O1H
+ move O1H, #0
+ addi $r2, $r2, #0xffffffe0
+ bnez O1L, .LL14
+.LL15:
+ beqz $r2, .LL16
+ move P1L, O1H
+ srl O1L, O1L, $r2
+ srl O1H, O1H, $r2
+ subri $r2, $r2, #0x20
+ sll P1L, P1L, $r2
+ or O1L, O1L, P1L
+.LL16:
+ sltsi $r15, P1H, #0
+ beqzs8 .LCret
+
+ subri O1H, O1H, #0
+ beqz O1L, .LL17
+ subri O1L, O1L, #0
+ subi45 O1H, #1
+.LL17:
+
+.LCret:
+ move P1L, O1L
+ move P1H, O1H
+
+.LC999:
+ popm $r6, $r6
+ pop $lp
+ ret5 $lp
+
+.LCnaninf:
+ sltsi $r15, P1H, #0
+ bnezs8 .LCret3
+ subri $r15, $r5, #0x7ff
+ bnezs8 .Li5
+ slli $r6, O1H, #1
+ or $r6, $r6, O1L
+ beqz $r6, .Li5
+
+.LCret3:
+ move O1H, #0x80000000
+ move O1L, #0
+ j .LCret
+.Li5:
+ move O1H, #0x7fffffff
+ move O1L, #-1
+ j .LCret
+ .size __fixdfdi, .-__fixdfdi
+#endif /* L_fixdfdi */
+
+
+
+#ifdef L_fixunssfsi
+
+ .global __fixunssfsi
+ .type __fixunssfsi, @function
+__fixunssfsi:
+ push $lp
+
+ slli $r1, $r0, #8
+ move $r3, #0x80000000
+ or $r1, $r1, $r3
+ srli $r3, $r0, #23
+ andi $r3, $r3, #0xff
+ subri $r2, $r3, #0x9e
+ sltsi $r15, $r2, #0
+ bnezs8 .LLspec
+ sltsi $r15, $r2, #0x20
+ bnezs8 .Li45
+ move $r0, #0
+ j .LL999
+.Li45:
+ srl $r1, $r1, $r2
+ sltsi $r15, $r0, #0
+ beqzs8 .Li46
+ subri $r1, $r1, #0
+.Li46:
+ move $r0, $r1
+
+.LL999:
+ pop $lp
+ ret5 $lp
+
+.LLspec:
+ move $r3, #0x7f800000
+ slt $r15, $r3, $r0
+ beqzs8 .Li47
+ move $r0, #0x80000000
+ j .LL999
+.Li47:
+ move $r0, #-1
+ j .LL999
+ .size __fixunssfsi, .-__fixunssfsi
+#endif /* L_fixunssfsi */
+
+
+
+#ifdef L_fixunsdfsi
+
+#ifndef __big_endian__
+ #define P1L $r0
+ #define P1H $r1
+#else
+ #define P1H $r0
+ #define P1L $r1
+#endif
+ .text
+ .align 2
+ .global __fixunsdfsi
+ .type __fixunsdfsi, @function
+__fixunsdfsi:
+ push $lp
+ pushm $r6, $r6
+
+ slli $r3, P1H, #11
+ srli $r6, P1L, #21
+ or $r3, $r3, $r6
+ move $r6, #0x80000000
+ or $r3, $r3, $r6
+ slli $r6, P1H, #1
+ srli $r6, $r6, #21
+ subri $r2, $r6, #0x41e
+ sltsi $r15, $r2, #0
+ bnezs8 .LNnaninf
+ move $r6, #0x20
+ slt $r15, $r2, $r6
+ bnezs8 .LL73
+ move $r3, #0
+.LL73:
+ srl $r3, $r3, $r2
+ sltsi $r15, P1H, #0
+ beqzs8 .Li53
+ subri $r3, $r3, #0
+.Li53:
+ move $r0, $r3
+
+.LN999:
+ popm $r6, $r6
+ pop $lp
+ ret5 $lp
+
+.LNnaninf:
+ beqz P1L, .Li54
+ ori P1H, P1H, #1
+.Li54:
+ move $r6, #0x7ff00000
+ slt $r15, $r6, P1H
+ beqzs8 .Li55
+ move $r0, #0x80000000
+ j .LN999
+.Li55:
+ move $r0, #-1
+ j .LN999
+ .size __fixunsdfsi, .-__fixunsdfsi
+#endif /* L_fixunsdfsi */
+
+
+
+#ifdef L_fixunssfdi
+
+#ifndef __big_endian__
+ #define O1L $r1
+ #define O1H $r2
+#else
+ #define O1H $r1
+ #define O1L $r2
+#endif
+ .text
+ .align 2
+ .global __fixunssfdi
+ .type __fixunssfdi, @function
+__fixunssfdi:
+ push $lp
+
+ srli $r3, $r0, #23
+ andi $r3, $r3, #0xff
+ slli O1H, $r0, #8
+ move $r5, #0x80000000
+ or O1H, O1H, $r5
+ move O1L, #0
+ sltsi $r15, $r3, #0xbe
+ beqzs8 .LDinfnan
+ subri $r3, $r3, #0xbe
+.LL12:
+ move $r5, #0x20
+ slt $r15, $r3, $r5
+ bnezs8 .LL13
+ move O1L, O1H
+ move O1H, #0
+ addi $r3, $r3, #0xffffffe0
+ bnez O1L, .LL12
+.LL13:
+ beqz $r3, .LL14
+ move $r4, O1H
+ srl O1L, O1L, $r3
+ srl O1H, O1H, $r3
+ subri $r3, $r3, #0x20
+ sll $r4, $r4, $r3
+ or O1L, O1L, $r4
+.LL14:
+ sltsi $r15, $r0, #0
+ beqzs8 .LDret
+
+ subri O1H, O1H, #0
+ beqz O1L, .LL15
+ subri O1L, O1L, #0
+ subi45 O1H, #1
+.LL15:
+
+.LDret:
+ move $r0, $r1
+ move $r1, $r2
+
+.LD999:
+ pop $lp
+ ret5 $lp
+
+.LDinfnan:
+ move O1H, #0x80000000
+ move O1L, #0
+ j .LDret
+ .size __fixunssfdi, .-__fixunssfdi
+#endif /* L_fixunssfdi */
+
+
+
+#ifdef L_fixunsdfdi
+
+#ifndef __big_endian__
+ #define P1L $r0
+ #define P1H $r1
+ #define O1L $r3
+ #define O1H $r4
+#else
+ #define P1H $r0
+ #define P1L $r1
+ #define O1H $r3
+ #define O1L $r4
+#endif
+ .text
+ .align 2
+ .global __fixunsdfdi
+ .type __fixunsdfdi, @function
+__fixunsdfdi:
+ push $lp
+ pushm $r6, $r6
+
+ slli $r5, P1H, #1
+ srli $r5, $r5, #21
+ slli O1H, P1H, #11
+ srli $r6, P1L, #21
+ or O1H, O1H, $r6
+ slli O1L, P1L, #11
+ move $r6, #0x80000000
+ or O1H, O1H, $r6
+ slti $r15, $r5, #0x43e
+ beqzs8 .LDnaninf
+ subri $r2, $r5, #0x43e
+.LL18:
+ move $r6, #0x20
+ slt $r15, $r2, $r6
+ bnezs8 .LL19
+ move O1L, O1H
+ move O1H, #0
+ addi $r2, $r2, #0xffffffe0
+ bnez O1L, .LL18
+.LL19:
+ beqz $r2, .LL20
+ move P1L, O1H
+ srl O1L, O1L, $r2
+ srl O1H, O1H, $r2
+ subri $r2, $r2, #0x20
+ sll P1L, P1L, $r2
+ or O1L, O1L, P1L
+.LL20:
+ sltsi $r15, P1H, #0
+ beqzs8 .LDret
+
+ subri O1H, O1H, #0
+ beqz O1L, .LL21
+ subri O1L, O1L, #0
+ subi45 O1H, #1
+.LL21:
+
+.LDret:
+ move P1L, O1L
+ move P1H, O1H
+
+.LD999:
+ popm $r6, $r6
+ pop $lp
+ ret5 $lp
+
+.LDnaninf:
+ move O1H, #0x80000000
+ move O1L, #0
+ j .LDret
+ .size __fixunsdfdi, .-__fixunsdfdi
+#endif /* L_fixunsdfdi */
+
+
+
+#ifdef L_si_to_sf
+
+ .text
+ .align 2
+ .global __floatsisf
+ .type __floatsisf, @function
+__floatsisf:
+ push $lp
+
+ move $r4, #0x80000000
+ and $r2, $r0, $r4
+ beqz $r0, .Li39
+ sltsi $r15, $r0, #0
+ beqzs8 .Li40
+ subri $r0, $r0, #0
+.Li40:
+ move $r1, #0x9e
+#ifdef __NDS32_PERF_EXT__
+ clz $r3, $r0
+#else
+ pushm $r0, $r2
+ pushm $r4, $r5
+ bal __clzsi2
+ move $r3, $r0
+ popm $r4, $r5
+ popm $r0, $r2
+#endif
+ sub $r1, $r1, $r3
+ sll $r0, $r0, $r3
+
+ #ADD($r0, $0x80)
+ move $r15, #0x80
+ add $r0, $r0, $r15
+ slt $r15, $r0, $r15
+
+ #ADDC($r1, $0x0)
+ add $r1, $r1, $r15
+ srai $r4, $r0, #8
+ andi $r4, $r4, #1
+ sub $r0, $r0, $r4
+ slli $r0, $r0, #1
+ srli $r0, $r0, #9
+ slli $r4, $r1, #23
+ or $r0, $r0, $r4
+.Li39:
+ or $r0, $r0, $r2
+
+.LH999:
+ pop $lp
+ ret5 $lp
+ .size __floatsisf, .-__floatsisf
+#endif /* L_si_to_sf */
+
+
+
+#ifdef L_si_to_df
+
+#ifndef __big_endian__
+ #define O1L $r1
+ #define O1H $r2
+ #define O2L $r4
+ #define O2H $r5
+#else
+ #define O1H $r1
+ #define O1L $r2
+ #define O2H $r4
+ #define O2L $r5
+#endif
+ .text
+ .align 2
+ .global __floatsidf
+ .type __floatsidf, @function
+__floatsidf:
+ push $lp
+ pushm $r6, $r6
+
+ move O1L, #0
+ move O2H, O1L
+ move $r3, O1L
+ move O1H, $r0
+ beqz O1H, .Li39
+ sltsi $r15, O1H, #0
+ beqzs8 .Li40
+ move O2H, #0x80000000
+
+ subri O1H, O1H, #0
+ beqz O1L, .LL71
+ subri O1L, O1L, #0
+ subi45 O1H, #1
+.LL71:
+.Li40:
+ move $r3, #0x41e
+#ifndef __big_endian__
+#ifdef __NDS32_PERF_EXT__
+ clz $r4, $r2
+#else
+ pushm $r0, $r3
+ push $r5
+ move $r0, $r2
+ bal __clzsi2
+ move $r4, $r0
+ pop $r5
+ popm $r0, $r3
+#endif
+#else /* __big_endian__ */
+#ifdef __NDS32_PERF_EXT__
+ clz $r5, $r1
+#else
+ pushm $r0, $r4
+ move $r0, $r1
+ bal __clzsi2
+ move $r5, $r0
+ popm $r0, $r4
+#endif
+#endif /* __big_endian__ */
+ sub $r3, $r3, O2L
+ sll O1H, O1H, O2L
+.Li39:
+ srli O2L, O1L, #11
+ slli $r6, O1H, #21
+ or O2L, O2L, $r6
+ slli $r6, O1H, #1
+ srli $r6, $r6, #12
+ or O2H, O2H, $r6
+ slli $r6, $r3, #20
+ or O2H, O2H, $r6
+ move $r0, $r4
+ move $r1, $r5
+
+.LH999:
+ popm $r6, $r6
+ pop $lp
+ ret5 $lp
+ .size __floatsidf, .-__floatsidf
+#endif /* L_si_to_df */
+
+
+
+#ifdef L_floatdisf
+
+#ifndef __big_endian__
+ #define P1L $r0
+ #define P1H $r1
+ #define P2L $r2
+ #define P2H $r3
+#else
+ #define P1H $r0
+ #define P1L $r1
+ #define P2H $r2
+ #define P2L $r3
+#endif
+ .text
+ .align 2
+ .global __floatdisf
+ .type __floatdisf, @function
+__floatdisf:
+ push $lp
+ pushm $r6, $r7
+
+ move $r7, #0x80000000
+ and $r5, P1H, $r7
+ move P2H, P1H
+ move P2L, P1L
+ or $r7, P1H, P1L
+ beqz $r7, .Li1
+ sltsi $r15, P1H, #0
+ beqzs8 .Li2
+
+ subri P2H, P2H, #0
+ beqz P2L, .LL1
+ subri P2L, P2L, #0
+ subi45 P2H, #1
+.LL1:
+.Li2:
+ move $r4, #0xbe
+
+
+ #NORMd($r2, $r6, P1L)
+ bnez P2H, .LL2
+ bnez P2L, .LL3
+ move $r4, #0
+ j .LL4
+.LL3:
+ move P2H, P2L
+ move P2L, #0
+ move $r6, #32
+ sub $r4, $r4, $r6
+.LL2:
+#ifdef __NDS32_PERF_EXT__
+ clz $r6, P2H
+#else
+ pushm $r0, $r5
+ move $r0, P2H
+ bal __clzsi2
+ move $r6, $r0
+ popm $r0, $r5
+#endif
+ beqz $r6, .LL4
+ sub $r4, $r4, $r6
+ subri P1L, $r6, #32
+ srl P1L, P2L, P1L
+ sll P2L, P2L, $r6
+ sll P2H, P2H, $r6
+ or P2H, P2H, P1L
+.LL4:
+ #NORMd End
+
+ beqz P2L, .Li3
+ ori P2H, P2H, #1
+.Li3:
+ #ADD(P2H, $0x80)
+ move $r15, #0x80
+ add P2H, P2H, $r15
+ slt $r15, P2H, $r15
+
+ #ADDC($r4, $0x0)
+ add $r4, $r4, $r15
+ srli $r7, P2H, #8
+ andi $r7, $r7, #1
+ sub P2H, P2H, $r7
+ slli P2H, P2H, #1
+ srli P2H, P2H, #9
+ slli $r7, $r4, #23
+ or P2H, P2H, $r7
+.Li1:
+ or $r0, P2H, $r5
+
+.LA999:
+ popm $r6, $r7
+ pop $lp
+ ret5 $lp
+ .size __floatdisf, .-__floatdisf
+#endif /* L_floatdisf */
+
+
+
+#ifdef L_floatdidf
+
+#ifndef __big_endian__
+ #define P1L $r0
+ #define P1H $r1
+ #define P2L $r2
+ #define P2H $r3
+ #define O1L $r5
+ #define O1H $r6
+#else
+ #define P1H $r0
+ #define P1L $r1
+ #define P2H $r2
+ #define P2L $r3
+ #define O1H $r5
+ #define O1L $r6
+#endif
+ .text
+ .align 2
+ .global __floatdidf
+ .type __floatdidf, @function
+__floatdidf:
+ push $lp
+ pushm $r6, $r8
+
+ move $r4, #0
+ move $r7, $r4
+ move P2H, P1H
+ move P2L, P1L
+ or $r8, P1H, P1L
+ beqz $r8, .Li1
+ move $r4, #0x43e
+ sltsi $r15, P1H, #0
+ beqzs8 .Li2
+ move $r7, #0x80000000
+
+ subri P2H, P2H, #0
+ beqz P2L, .LL1
+ subri P2L, P2L, #0
+ subi45 P2H, #1
+.LL1:
+
+.Li2:
+ #NORMd($r2, O1H, O1L)
+ bnez P2H, .LL2
+ bnez P2L, .LL3
+ move $r4, #0
+ j .LL4
+.LL3:
+ move P2H, P2L
+ move P2L, #0
+ move O1H, #32
+ sub $r4, $r4, O1H
+.LL2:
+#ifdef __NDS32_PERF_EXT__
+ clz O1H, P2H
+#else /* not __NDS32_PERF_EXT__ */
+/*
+ Replace clz with function call.
+ clz O1H, P2H
+ EL: clz $r6, $r3
+ EB: clz $r5, $r2
+*/
+#ifndef __big_endian__
+ pushm $r0, $r5
+ move $r0, $r3
+ bal __clzsi2
+ move $r6, $r0
+ popm $r0, $r5
+#else
+ pushm $r0, $r4
+ move $r0, $r2
+ bal __clzsi2
+ move $r5, $r0
+ popm $r0, $r4
+#endif
+#endif /* not __NDS32_PERF_EXT__ */
+ beqz O1H, .LL4
+ sub $r4, $r4, O1H
+ subri O1L, O1H, #32
+ srl O1L, P2L, O1L
+ sll P2L, P2L, O1H
+ sll P2H, P2H, O1H
+ or P2H, P2H, O1L
+.LL4:
+ #NORMd End
+
+ #ADD(P2L, $0x400)
+ move $r15, #0x400
+ add P2L, P2L, $r15
+ slt $r15, P2L, $r15
+
+
+ #ADDCC(P2H, $0x0)
+ beqzs8 .LL7
+ add P2H, P2H, $r15
+ slt $r15, P2H, $r15
+.LL7:
+
+ #ADDC($r4, $0x0)
+ add $r4, $r4, $r15
+ srli $r8, P2L, #11
+ andi $r8, $r8, #1
+ sub P2L, P2L, $r8
+.Li1:
+ srli O1L, P2L, #11
+ slli $r8, P2H, #21
+ or O1L, O1L, $r8
+ slli O1H, P2H, #1
+ srli O1H, O1H, #12
+ slli $r8, $r4, #20
+ or O1H, O1H, $r8
+ or O1H, O1H, $r7
+ move P1L, O1L
+ move P1H, O1H
+
+.LA999:
+ popm $r6, $r8
+ pop $lp
+ ret5 $lp
+ .size __floatdidf, .-__floatdidf
+#endif /* L_floatdidf */
+
+
+
+#ifdef L_floatunsisf
+
+ .text
+ .align 2
+ .global __floatunsisf
+ .type __floatunsisf, @function
+__floatunsisf:
+ push $lp
+
+ beqz $r0, .Li41
+ move $r2, #0x9e
+#ifdef __NDS32_PERF_EXT__
+ clz $r1, $r0
+#else
+ push $r0
+ pushm $r2, $r5
+ bal __clzsi2
+ move $r1, $r0
+ popm $r2, $r5
+ pop $r0
+#endif
+
+ sub $r2, $r2, $r1
+ sll $r0, $r0, $r1
+
+ #ADD($r0, $0x80)
+ move $r15, #0x80
+ add $r0, $r0, $r15
+ slt $r15, $r0, $r15
+
+ #ADDC($r2, $0x0)
+ add $r2, $r2, $r15
+ srli $r3, $r0, #8
+ andi $r3, $r3, #1
+ sub $r0, $r0, $r3
+ slli $r0, $r0, #1
+ srli $r0, $r0, #9
+ slli $r3, $r2, #23
+ or $r0, $r0, $r3
+
+.Li41:
+.LI999:
+ pop $lp
+ ret5 $lp
+ .size __floatunsisf, .-__floatunsisf
+#endif /* L_floatunsisf */
+
+
+
+#ifdef L_floatunsidf
+
+#ifndef __big_endian__
+ #define O1L $r1
+ #define O1H $r2
+ #define O2L $r4
+ #define O2H $r5
+#else
+ #define O1H $r1
+ #define O1L $r2
+ #define O2H $r4
+ #define O2L $r5
+#endif
+ .text
+ .align 2
+ .global __floatunsidf
+ .type __floatunsidf, @function
+__floatunsidf:
+ push $lp
+ pushm $r6, $r6
+
+ move O1L, #0
+ move $r3, O1L
+ move O1H, $r0
+ beqz O1H, .Li41
+ move $r3, #0x41e
+#ifndef __big_endian__
+#ifdef __NDS32_PERF_EXT__
+ clz $r5, $r2
+#else
+ pushm $r0, $r4
+ move $r0, $r2
+ bal __clzsi2
+ move $r5, $r0
+ popm $r0, $r4
+#endif
+#else /* __big_endian__ */
+#ifdef __NDS32_PERF_EXT__
+ clz $r4, $r1
+#else
+ pushm $r0, $r3
+ push $r5
+ move $r0, $r1
+ bal __clzsi2
+ move $r4, $r0
+ pop $r5
+ popm $r0, $r3
+#endif
+#endif /* __big_endian__ */
+ sub $r3, $r3, O2H
+ sll O1H, O1H, O2H
+.Li41:
+ srli O2L, O1L, #11
+ slli $r6, O1H, #21
+ or O2L, O2L, $r6
+ slli O2H, O1H, #1
+ srli O2H, O2H, #12
+ slli $r6, $r3, #20
+ or O2H, O2H, $r6
+ move $r0, $r4
+ move $r1, $r5
+
+.LI999:
+ popm $r6, $r6
+ pop $lp
+ ret5 $lp
+ .size __floatunsidf, .-__floatunsidf
+#endif /* L_floatunsidf */
+
+
+
+#ifdef L_floatundisf
+
+#ifndef __big_endian__
+ #define P1L $r0
+ #define P1H $r1
+ #define P2L $r2
+ #define P2H $r3
+#else
+ #define P1H $r0
+ #define P1L $r1
+ #define P2H $r2
+ #define P2L $r3
+#endif
+ .text
+ .align 2
+ .global __floatundisf
+ .type __floatundisf, @function
+__floatundisf:
+ push $lp
+ pushm $r6, $r6
+
+ move P2H, P1H
+ move P2L, P1L
+ or $r6, P1H, P1L
+ beqz $r6, .Li4
+ move $r4, #0xbe
+
+
+ #NORMd($r2, $r5, P1L)
+ bnez P2H, .LL5
+ bnez P2L, .LL6
+ move $r4, #0
+ j .LL7
+.LL6:
+ move P2H, P2L
+ move P2L, #0
+ move $r5, #32
+ sub $r4, $r4, $r5
+.LL5:
+#ifdef __NDS32_PERF_EXT__
+ clz $r5, P2H
+#else
+ pushm $r0, $r4
+ move $r0, P2H
+ bal __clzsi2
+ move $r5, $r0
+ popm $r0, $r4
+#endif
+ beqz $r5, .LL7
+ sub $r4, $r4, $r5
+ subri P1L, $r5, #32
+ srl P1L, P2L, P1L
+ sll P2L, P2L, $r5
+ sll P2H, P2H, $r5
+ or P2H, P2H, P1L
+.LL7:
+ #NORMd End
+
+ beqz P2L, .Li5
+ ori P2H, P2H, #1
+.Li5:
+ #ADD(P2H, $0x80)
+ move $r15, #0x80
+ add P2H, P2H, $r15
+ slt $r15, P2H, $r15
+
+ #ADDC($r4, $0x0)
+ add $r4, $r4, $r15
+ srli $r6, P2H, #8
+ andi $r6, $r6, #1
+ sub P2H, P2H, $r6
+ slli P2H, P2H, #1
+ srli P2H, P2H, #9
+ slli $r6, $r4, #23
+ or P2H, P2H, $r6
+.Li4:
+ move $r0, P2H
+
+.LB999:
+ popm $r6, $r6
+ pop $lp
+ ret5 $lp
+ .size __floatundisf, .-__floatundisf
+#endif /* L_floatundisf */
+
+
+
+#ifdef L_floatundidf
+
+#ifndef __big_endian__
+ #define P1L $r0
+ #define P1H $r1
+ #define P2L $r2
+ #define P2H $r3
+ #define O1L $r5
+ #define O1H $r6
+#else
+ #define P1H $r0
+ #define P1L $r1
+ #define P2H $r2
+ #define P2L $r3
+ #define O1H $r5
+ #define O1L $r6
+#endif
+ .text
+ .align 2
+ .global __floatundidf
+ .type __floatundidf, @function
+__floatundidf:
+ push $lp
+ pushm $r6, $r7
+
+ move $r4, #0
+ move P2H, P1H
+ move P2L, P1L
+ or $r7, P1H, P1L
+ beqz $r7, .Li3
+ move $r4, #0x43e
+
+
+ #NORMd($r2, O1H, O1L)
+ bnez P2H, .LL8
+ bnez P2L, .LL9
+ move $r4, #0
+ j .LL10
+.LL9:
+ move P2H, P2L
+ move P2L, #0
+ move O1H, #32
+ sub $r4, $r4, O1H
+.LL8:
+#ifdef __NDS32_PERF_EXT__
+ clz O1H, P2H
+#else /* not __NDS32_PERF_EXT__ */
+/*
+ Replace clz with function call.
+ clz O1H, P2H
+ EL: clz $r6, $r3
+ EB: clz $r5, $r2
+*/
+#ifndef __big_endian__
+ pushm $r0, $r5
+ move $r0, $r3
+ bal __clzsi2
+ move $r6, $r0
+ popm $r0, $r5
+#else
+ pushm $r0, $r4
+ move $r0, $r2
+ bal __clzsi2
+ move $r5, $r0
+ popm $r0, $r4
+#endif
+#endif /* not __NDS32_PERF_EXT__ */
+ beqz O1H, .LL10
+ sub $r4, $r4, O1H
+ subri O1L, O1H, #32
+ srl O1L, P2L, O1L
+ sll P2L, P2L, O1H
+ sll P2H, P2H, O1H
+ or P2H, P2H, O1L
+.LL10:
+ #NORMd End
+
+ #ADD(P2L, $0x400)
+ move $r15, #0x400
+ add P2L, P2L, $r15
+ slt $r15, P2L, $r15
+
+
+ #ADDCC(P2H, $0x0)
+ beqzs8 .LL13
+ add P2H, P2H, $r15
+ slt $r15, P2H, $r15
+.LL13:
+
+ #ADDC($r4, $0x0)
+ add $r4, $r4, $r15
+ srli $r7, P2L, #11
+ andi $r7, $r7, #1
+ sub P2L, P2L, $r7
+.Li3:
+ srli O1L, P2L, #11
+ slli $r7, P2H, #21
+ or O1L, O1L, $r7
+ slli O1H, P2H, #1
+ srli O1H, O1H, #12
+ slli $r7, $r4, #20
+ or O1H, O1H, $r7
+ move P1L, O1L
+ move P1H, O1H
+
+.LB999:
+ popm $r6, $r7
+ pop $lp
+ ret5 $lp
+ .size __floatundidf, .-__floatundidf
+#endif /* L_floatundidf */
+
+
+
+#ifdef L_compare_sf
+
+ .text
+ .align 2
+ .global __cmpsf2
+ .type __cmpsf2, @function
+__cmpsf2:
+ .global __eqsf2
+ .type __eqsf2, @function
+__eqsf2:
+ .global __ltsf2
+ .type __ltsf2, @function
+__ltsf2:
+ .global __lesf2
+ .type __lesf2, @function
+__lesf2:
+ .global __nesf2
+ .type __nesf2, @function
+__nesf2:
+ move $r4, #1
+ j .LA
+
+ .global __gesf2
+ .type __gesf2, @function
+__gesf2:
+ .global __gtsf2
+ .type __gtsf2, @function
+__gtsf2:
+ move $r4, #-1
+.LA:
+ push $lp
+
+ slli $r2, $r0, #1
+ slli $r3, $r1, #1
+ or $r5, $r2, $r3
+ beqz $r5, .LMequ
+ move $r5, #0xff000000
+ slt $r15, $r5, $r2
+ bnezs8 .LMnan
+ slt $r15, $r5, $r3
+ bnezs8 .LMnan
+ srli $r2, $r2, #1
+ sltsi $r15, $r0, #0
+ beqzs8 .Li48
+ subri $r2, $r2, #0
+.Li48:
+ srli $r3, $r3, #1
+ sltsi $r15, $r1, #0
+ beqzs8 .Li49
+ subri $r3, $r3, #0
+.Li49:
+ slts $r15, $r2, $r3
+ beqzs8 .Li50
+ move $r0, #-1
+ j .LM999
+.Li50:
+ slts $r15, $r3, $r2
+ beqzs8 .LMequ
+ move $r0, #1
+ j .LM999
+
+.LMequ:
+ move $r0, #0
+
+.LM999:
+ pop $lp
+ ret5 $lp
+
+.LMnan:
+ move $r0, $r4
+ j .LM999
+ .size __cmpsf2, .-__cmpsf2
+ .size __eqsf2, .-__eqsf2
+ .size __ltsf2, .-__ltsf2
+ .size __lesf2, .-__lesf2
+ .size __nesf2, .-__nesf2
+ .size __gesf2, .-__gesf2
+ .size __gtsf2, .-__gtsf2
+#endif /* L_compare_sf */
+
+
+
+#ifdef L_compare_df
+
+#ifdef __big_endian__
+ #define P1H $r0
+ #define P1L $r1
+ #define P2H $r2
+ #define P2L $r3
+#else
+ #define P1H $r1
+ #define P1L $r0
+ #define P2H $r3
+ #define P2L $r2
+#endif
+ .align 2
+ .globl __gtdf2
+ .globl __gedf2
+ .globl __ltdf2
+ .globl __ledf2
+ .globl __eqdf2
+ .globl __nedf2
+ .globl __cmpdf2
+ .type __gtdf2, @function
+ .type __gedf2, @function
+ .type __ltdf2, @function
+ .type __ledf2, @function
+ .type __eqdf2, @function
+ .type __nedf2, @function
+ .type __cmpdf2, @function
+__gtdf2:
+__gedf2:
+ movi $r4, -1
+ b .L1
+
+__ltdf2:
+__ledf2:
+__cmpdf2:
+__nedf2:
+__eqdf2:
+ movi $r4, 1
+.L1:
+#if defined (__NDS32_ISA_V3M__)
+ push25 $r10, 0
+#else
+ smw.adm $r6, [$sp], $r9, 0
+#endif
+
+ sethi $r5, 0x7ff00
+ and $r6, P1H, $r5 ! r6=aExp
+ and $r7, P2H, $r5 ! r7=bExp
+ slli $r8, P1H, 12 ! r8=aSig0
+ slli $r9, P2H, 12 ! r9=bSig0
+ beq $r6, $r5, .L11 ! aExp==0x7ff
+ beq $r7, $r5, .L12 ! bExp==0x7ff
+.L2:
+ slli $ta, P1H, 1 ! ta=ahigh<<1
+ or $ta, P1L, $ta !
+ xor $r5, P1H, P2H ! r5=ahigh^bhigh
+ beqz $ta, .L3 ! if(ahigh<<1)==0,go .L3
+ !-------------------------------
+ ! (ahigh<<1)!=0 || (bhigh<<1)!=0
+ !-------------------------------
+.L4:
+ beqz $r5, .L5 ! ahigh==bhigh, go .L5
+ !--------------------
+ ! a != b
+ !--------------------
+.L6:
+ bltz $r5, .L7 ! if(aSign!=bSign), go .L7
+ !--------------------
+ ! aSign==bSign
+ !--------------------
+ slt $ta, $r6, $r7 ! ta=(aExp<bExp)
+ bne $r6, $r7, .L8 ! if(aExp!=bExp),go .L8
+ slt $ta, $r8, $r9 ! ta=(aSig0<bSig0)
+ bne $r8, $r9, .L8 ! if(aSig0!=bSig0),go .L8
+ slt $ta, P1L, P2L ! ta=(aSig1<bSig1)
+.L8:
+ beqz $ta, .L10 ! if(|a|>|b|), go .L10
+ nor $r0, P2H, P2H ! if(|a|<|b|),return (~yh)
+.L14:
+#if defined (__NDS32_ISA_V3M__)
+ pop25 $r10, 0
+#else
+ lmw.bim $r6, [$sp], $r9, 0
+ ret
+#endif
+.L10:
+ ori $r0, P2H, 1 ! return (yh|1)
+ b .L14
+ !--------------------
+ ! (ahigh<<1)=0
+ !--------------------
+.L3:
+ slli $ta, P2H, 1 ! ta=bhigh<<1
+ or $ta, P2L, $ta !
+ bnez $ta, .L4 ! ta=(bhigh<<1)!=0,go .L4
+.L5:
+ xor $ta, P1L, P2L ! ta=alow^blow
+ bnez $ta, .L6 ! alow!=blow,go .L6
+ movi $r0, 0 ! a==b, return 0
+ b .L14
+ !--------------------
+ ! aExp=0x7ff;
+ !--------------------
+.L11:
+ or P1L, P1L, $r8 ! x1=(aSig0|aSig1)
+ bnez P1L, .L13 ! if(a=nan), go.L13
+ xor $ta, $r7, $r5 ! ta=(bExp^0x7ff)
+ bnez $ta, .L2 ! if(bExp!=0x7ff), go .L2
+ !--------------------
+ ! bExp=0x7ff;
+ !--------------------
+.L12:
+ or $ta, P2L, $r9 ! ta=(bSig0|bSig1)
+ beqz $ta, .L2 ! if(b!=nan), go .L2
+.L13:
+ move $r0, $r4
+ b .L14
+ !--------------------
+ ! aSign!=bSign
+ !--------------------
+.L7:
+ ori $r0, P1H, 1 ! if(aSign!=bSign), return (ahigh|1)
+ b .L14
+
+ .size __gtdf2, .-__gtdf2
+ .size __gedf2, .-__gedf2
+ .size __ltdf2, .-__ltdf2
+ .size __ledf2, .-__ledf2
+ .size __eqdf2, .-__eqdf2
+ .size __nedf2, .-__nedf2
+ .size __cmpdf2, .-__cmpdf2
+#endif /* L_compare_df */
+
+
+
+#ifdef L_unord_sf
+
+ .text
+ .align 2
+ .global __unordsf2
+ .type __unordsf2, @function
+__unordsf2:
+ push $lp
+
+ slli $r2, $r0, #1
+ move $r3, #0xff000000
+ slt $r15, $r3, $r2
+ beqzs8 .Li52
+ move $r0, #1
+ j .LP999
+.Li52:
+ slli $r2, $r1, #1
+ move $r3, #0xff000000
+ slt $r15, $r3, $r2
+ beqzs8 .Li53
+ move $r0, #1
+ j .LP999
+.Li53:
+ move $r0, #0
+
+.LP999:
+ pop $lp
+ ret5 $lp
+ .size __unordsf2, .-__unordsf2
+#endif /* L_unord_sf */
+
+
+
+#ifdef L_unord_df
+
+#ifndef __big_endian__
+ #define P1L $r0
+ #define P1H $r1
+ #define P2L $r2
+ #define P2H $r3
+#else
+ #define P1H $r0
+ #define P1L $r1
+ #define P2H $r2
+ #define P2L $r3
+#endif
+ .text
+ .align 2
+ .global __unorddf2
+ .type __unorddf2, @function
+__unorddf2:
+ push $lp
+
+ slli $r4, P1H, #1
+ beqz P1L, .Li66
+ addi $r4, $r4, #1
+.Li66:
+ move $r5, #0xffe00000
+ slt $r15, $r5, $r4
+ beqzs8 .Li67
+ move $r0, #1
+ j .LR999
+.Li67:
+ slli $r4, P2H, #1
+ beqz P2L, .Li68
+ addi $r4, $r4, #1
+.Li68:
+ move $r5, #0xffe00000
+ slt $r15, $r5, $r4
+ beqzs8 .Li69
+ move $r0, #1
+ j .LR999
+.Li69:
+ move $r0, #0
+
+.LR999:
+ pop $lp
+ ret5 $lp
+ .size __unorddf2, .-__unorddf2
+#endif /* L_unord_df */
+/* ------------------------------------------- */
+/* DPBIT floating point operations for libgcc */
+/* ------------------------------------------- */
diff --git a/libgcc/config/nds32/lib1asmsrc-newlib.S b/libgcc/config/nds32/lib1asmsrc-newlib.S
new file mode 100644
index 00000000000..6eb3fb0a753
--- /dev/null
+++ b/libgcc/config/nds32/lib1asmsrc-newlib.S
@@ -0,0 +1,204 @@
+/* newlib libgcc routines of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+ .section .mdebug.abi_nds32
+ .previous
+
+#ifdef L_divsi3
+
+ .text
+ .align 2
+ .globl __divsi3
+ .type __divsi3, @function
+__divsi3:
+ movi $r5, 0 ! res = 0
+ xor $r4, $r0, $r1 ! neg
+ bltz $r0, .L1
+ bltz $r1, .L2
+.L3:
+ movi $r2, 1 ! bit = 1
+ slt $r3, $r1, $r0 ! test if dividend is smaller than or equal to divisor
+ beqz $r3, .L5
+ bltz $r1, .L5
+
+.L4:
+ slli $r2, $r2, 1
+ beqz $r2, .L6
+ slli $r1, $r1, 1
+ slt $r3, $r1, $r0
+ beqz $r3, .L5
+ bgez $r1, .L4
+
+.L5:
+ slt $r3, $r0, $r1
+ bnez $r3, .L8
+ sub $r0, $r0, $r1
+ or $r5, $r5, $r2
+.L8:
+ srli $r1, $r1, 1
+ srli $r2, $r2, 1
+ bnez $r2, .L5
+.L6:
+ bgez $r4, .L7
+ subri $r5, $r5, 0 ! negate if $r4 < 0
+.L7:
+ move $r0, $r5
+ ret
+.L1:
+ subri $r0, $r0, 0 ! change neg to pos
+ bgez $r1, .L3
+.L2:
+ subri $r1, $r1, 0 ! change neg to pos
+ j .L3
+ .size __divsi3, .-__divsi3
+
+#endif /* L_divsi3 */
+
+
+#ifdef L_modsi3
+
+ .text
+ .align 2
+ .globl __modsi3
+ .type __modsi3, @function
+__modsi3:
+ movi $r5, 0 ! res = 0
+ move $r4, $r0 ! neg
+ bltz $r0, .L1
+ bltz $r1, .L2
+.L3:
+ movi $r2, 1 ! bit = 1
+ slt $r3, $r1, $r0 ! test if dividend is smaller than or equal to divisor
+ beqz $r3, .L5
+ bltz $r1, .L5
+
+.L4:
+ slli $r2, $r2, 1
+ beqz $r2, .L6
+ slli $r1, $r1, 1
+ slt $r3, $r1, $r0
+ beqz $r3, .L5
+ bgez $r1, .L4
+
+.L5:
+ slt $r3, $r0, $r1
+ bnez $r3, .L8
+ sub $r0, $r0, $r1
+ or $r5, $r5, $r2
+.L8:
+ srli $r1, $r1, 1
+ srli $r2, $r2, 1
+ bnez $r2, .L5
+.L6:
+ bgez $r4, .L7
+ subri $r0, $r0, 0 ! negate if $r4 < 0
+.L7:
+ ret
+.L1:
+ subri $r0, $r0, 0 ! change neg to pos
+ bgez $r1, .L3
+.L2:
+ subri $r1, $r1, 0 ! change neg to pos
+ j .L3
+ .size __modsi3, .-__modsi3
+
+#endif /* L_modsi3 */
+
+
+#ifdef L_udivsi3
+
+ .text
+ .align 2
+ .globl __udivsi3
+ .type __udivsi3, @function
+__udivsi3:
+ movi $r5, 0 ! res = 0
+ movi $r2, 1 ! bit = 1
+ slt $r3, $r1, $r0 ! test if dividend is smaller than or equal to divisor
+ beqz $r3, .L5
+ bltz $r1, .L5
+
+.L4:
+ slli $r2, $r2, 1
+ beqz $r2, .L6
+ slli $r1, $r1, 1
+ slt $r3, $r1, $r0
+ beqz $r3, .L5
+ bgez $r1, .L4
+
+.L5:
+ slt $r3, $r0, $r1
+ bnez $r3, .L8
+ sub $r0, $r0, $r1
+ or $r5, $r5, $r2
+.L8:
+ srli $r1, $r1, 1
+ srli $r2, $r2, 1
+ bnez $r2, .L5
+.L6:
+ move $r0, $r5
+ ret
+ .size __udivsi3, .-__udivsi3
+
+#endif /* L_udivsi3 */
+
+
+#ifdef L_umodsi3
+
+ .text
+ .align 2
+ .globl __umodsi3
+ .type __umodsi3, @function
+__umodsi3:
+ movi $r5, 0 ! res = 0
+ movi $r2, 1 ! bit = 1
+ slt $r3, $r1, $r0 ! test if dividend is smaller than or equal to divisor
+ beqz $r3, .L5
+ bltz $r1, .L5
+
+.L4:
+ slli $r2, $r2, 1
+ beqz $r2, .L6
+ slli $r1, $r1, 1
+ slt $r3, $r1, $r0
+ beqz $r3, .L5
+ bgez $r1, .L4
+
+.L5:
+ slt $r3, $r0, $r1
+ bnez $r3, .L8
+ sub $r0, $r0, $r1
+ or $r5, $r5, $r2
+.L8:
+ srli $r1, $r1, 1
+ srli $r2, $r2, 1
+ bnez $r2, .L5
+.L6:
+ ret
+ .size __umodsi3, .-__umodsi3
+
+#endif /* L_umodsi3 */
+
+/* ----------------------------------------------------------- */
diff --git a/libgcc/config/nds32/lib2csrc-mculib/_clzdi2.c b/libgcc/config/nds32/lib2csrc-mculib/_clzdi2.c
new file mode 100644
index 00000000000..7d39ea85b7a
--- /dev/null
+++ b/libgcc/config/nds32/lib2csrc-mculib/_clzdi2.c
@@ -0,0 +1,38 @@
+/* mculib libgcc routines of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+extern int __clzsi2 (int val);
+int
+__clzdi2 (long long val)
+{
+ if (val >> 32)
+ {
+ return __clzsi2 (val >> 32);
+ }
+ else
+ {
+ return __clzsi2 (val) + 32;
+ }
+}
diff --git a/libgcc/config/nds32/lib2csrc-mculib/_clzsi2.c b/libgcc/config/nds32/lib2csrc-mculib/_clzsi2.c
new file mode 100644
index 00000000000..9d0bdd96d80
--- /dev/null
+++ b/libgcc/config/nds32/lib2csrc-mculib/_clzsi2.c
@@ -0,0 +1,49 @@
+/* mculib libgcc routines of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ 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/>. */
+
+int
+__clzsi2 (int val)
+{
+ int i = 32;
+ int j = 16;
+ int temp;
+
+ for (; j; j >>= 1)
+ {
+ if (temp = val >> j)
+ {
+ if (j == 1)
+ {
+ return (i - 2);
+ }
+ else
+ {
+ i -= j;
+ val = temp;
+ }
+ }
+ }
+ return (i - val);
+}
diff --git a/libgcc/config/nds32/sfp-machine.h b/libgcc/config/nds32/sfp-machine.h
new file mode 100644
index 00000000000..62a1532de60
--- /dev/null
+++ b/libgcc/config/nds32/sfp-machine.h
@@ -0,0 +1,91 @@
+/* Machine settings for software floating-point emulation
+ of Andes NDS32 cpu for GNU compiler
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Contributed by Andes Technology Corporation.
+
+ This file is part of GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser General Public
+ License, the Free Software Foundation gives you unlimited
+ permission to link the compiled version of this file into
+ combinations with other programs, and to distribute those
+ combinations without any restriction coming from the use of this
+ file. (The Lesser General Public License restrictions do apply in
+ other respects; for example, they cover modification of the file,
+ and distribution when not linked into a combine executable.)
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#define _FP_W_TYPE_SIZE 32
+#define _FP_W_TYPE unsigned long
+#define _FP_WS_TYPE signed long
+#define _FP_I_TYPE long
+
+/* The type of the result of a floating point comparison. This must
+ match `__libgcc_cmp_return__' in GCC for the target. */
+typedef int __gcc_CMPtype __attribute__ ((mode (__libgcc_cmp_return__)));
+#define CMPtype __gcc_CMPtype
+
+#define _FP_MUL_MEAT_S(R,X,Y) \
+ _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_S,R,X,Y,umul_ppmm)
+#define _FP_MUL_MEAT_D(R,X,Y) \
+ _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm)
+#define _FP_MUL_MEAT_Q(R,X,Y) \
+ _FP_MUL_MEAT_4_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm)
+
+#define _FP_DIV_MEAT_S(R,X,Y) _FP_DIV_MEAT_1_loop(S,R,X,Y)
+#define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_2_udiv(D,R,X,Y)
+#define _FP_DIV_MEAT_Q(R,X,Y) _FP_DIV_MEAT_4_udiv(Q,R,X,Y)
+
+#define _FP_NANFRAC_S ((_FP_QNANBIT_S << 1) - 1)
+#define _FP_NANFRAC_D ((_FP_QNANBIT_D << 1) - 1), -1
+#define _FP_NANFRAC_Q ((_FP_QNANBIT_Q << 1) - 1), -1, -1, -1
+#define _FP_NANSIGN_S 0
+#define _FP_NANSIGN_D 0
+#define _FP_NANSIGN_Q 0
+
+#define _FP_KEEPNANFRACP 1
+#define _FP_QNANNEGATEDP 0
+
+/* Someone please check this. */
+#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \
+ do { \
+ if ((_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs) \
+ && !(_FP_FRAC_HIGH_RAW_##fs(Y) & _FP_QNANBIT_##fs)) \
+ { \
+ R##_s = Y##_s; \
+ _FP_FRAC_COPY_##wc(R,Y); \
+ } \
+ else \
+ { \
+ R##_s = X##_s; \
+ _FP_FRAC_COPY_##wc(R,X); \
+ } \
+ R##_c = FP_CLS_NAN; \
+ } while (0)
+
+#define __LITTLE_ENDIAN 1234
+#define __BIG_ENDIAN 4321
+
+#if defined __big_endian__
+# define __BYTE_ORDER __BIG_ENDIAN
+#else
+# define __BYTE_ORDER __LITTLE_ENDIAN
+#endif
+
+/* Define ALIASNAME as a strong alias for NAME. */
+# define strong_alias(name, aliasname) _strong_alias(name, aliasname)
+# define _strong_alias(name, aliasname) \
+ extern __typeof (name) aliasname __attribute__ ((alias (#name)));
diff --git a/libgcc/config/nds32/t-nds32 b/libgcc/config/nds32/t-nds32
new file mode 100644
index 00000000000..25c184aa2a9
--- /dev/null
+++ b/libgcc/config/nds32/t-nds32
@@ -0,0 +1,58 @@
+# Rules of libgcc and crtstuff of Andes NDS32 cpu for GNU compiler
+# Copyright (C) 2012-2013 Free Software Foundation, Inc.
+# Contributed by Andes Technology Corporation.
+#
+# This file is part of GCC.
+#
+# GCC is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published
+# by the Free Software Foundation; either version 3, or (at your
+# option) any later version.
+#
+# GCC is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+# License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+
+# Note:
+# Because GCC has its own make rules for crtbegin.o and crtend.o,
+# we cannot use crtbegin.o and crtend.o rules.
+# So we create crtbegin1.o and crtend1.o instead.
+# Make sure the linker script include these two objects
+# for building .ctors/.dtors sections.
+
+# Use -DCRT_BEGIN to create beginning parts of .init and .fini content
+# Make sure you are building crtbegin1.o with -O0 optimization,
+# otherwise the static function will be optimized out
+crtbegin1.o: $(srcdir)/config/nds32/initfini.c $(GCC_PASSES) $(CONFIG_H)
+ $(GCC_FOR_TARGET) $(INCLUDES) \
+ $(CFLAGS) \
+ -DCRT_BEGIN \
+ -finhibit-size-directive -fno-inline-functions \
+ -O0 -c $(srcdir)/config/nds32/initfini.c -o crtbegin1.o
+
+# Use -DCRT_END to create ending parts of .init and .fini content
+# Make sure you are building crtend1.o with -O0 optimization,
+# otherwise the static function will be optimized out
+crtend1.o: $(srcdir)/config/nds32/initfini.c $(GCC_PASSES) $(CONFIG_H)
+ $(GCC_FOR_TARGET) $(INCLUDES) \
+ $(CFLAGS) \
+ -DCRT_END \
+ -finhibit-size-directive -fno-inline-functions \
+ -O0 -c $(srcdir)/config/nds32/initfini.c -o crtend1.o
+
+# Use this rule if and only if your crt0.o does not come from library
+# Also, be sure to add 'crtzero.o' in extra_parts in libgcc/config.host
+# and change STARTFILE_SPEC in nds32.h
+#
+#crtzero.o: $(srcdir)/config/nds32/crtzero.S $(GCC_PASSES) $(CONFIG_H)
+# $(GCC_FOR_TARGET) $(INCLUDES) \
+# -c $(srcdir)/config/nds32/crtzero.S -o crtzero.o
+
+
+# ------------------------------------------------------------------------
diff --git a/libgcc/config/nds32/t-nds32-isr b/libgcc/config/nds32/t-nds32-isr
new file mode 100644
index 00000000000..24f798c3a56
--- /dev/null
+++ b/libgcc/config/nds32/t-nds32-isr
@@ -0,0 +1,212 @@
+# Rules of c-isr library stuff of Andes NDS32 cpu for GNU compiler
+# Copyright (C) 2012-2013 Free Software Foundation, Inc.
+# Contributed by Andes Technology Corporation.
+#
+# This file is part of GCC.
+#
+# GCC is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published
+# by the Free Software Foundation; either version 3, or (at your
+# option) any later version.
+#
+# GCC is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+# License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+
+###############################################################################
+# Makfile fragment rules for libnds32_isr.a to support ISR attribute extension
+###############################################################################
+
+# basic flags setting
+ISR_CFLAGS = $(CFLAGS) -c
+
+# the object files we would like to create
+LIBNDS32_ISR_16B_OBJS = \
+ vec_vid00.o vec_vid01.o vec_vid02.o vec_vid03.o \
+ vec_vid04.o vec_vid05.o vec_vid06.o vec_vid07.o \
+ vec_vid08.o vec_vid09.o vec_vid10.o vec_vid11.o \
+ vec_vid12.o vec_vid13.o vec_vid14.o vec_vid15.o \
+ vec_vid16.o vec_vid17.o vec_vid18.o vec_vid19.o \
+ vec_vid20.o vec_vid21.o vec_vid22.o vec_vid23.o \
+ vec_vid24.o vec_vid25.o vec_vid26.o vec_vid27.o \
+ vec_vid28.o vec_vid29.o vec_vid30.o vec_vid31.o \
+ vec_vid32.o vec_vid33.o vec_vid34.o vec_vid35.o \
+ vec_vid36.o vec_vid37.o vec_vid38.o vec_vid39.o \
+ vec_vid40.o vec_vid41.o vec_vid42.o vec_vid43.o \
+ vec_vid44.o vec_vid45.o vec_vid46.o vec_vid47.o \
+ vec_vid48.o vec_vid49.o vec_vid50.o vec_vid51.o \
+ vec_vid52.o vec_vid53.o vec_vid54.o vec_vid55.o \
+ vec_vid56.o vec_vid57.o vec_vid58.o vec_vid59.o \
+ vec_vid60.o vec_vid61.o vec_vid62.o vec_vid63.o \
+ vec_vid64.o vec_vid65.o vec_vid66.o vec_vid67.o \
+ vec_vid68.o vec_vid69.o vec_vid70.o vec_vid71.o \
+ vec_vid72.o \
+ excp_isr_ps_nn.o excp_isr_ps_ns.o excp_isr_ps_nr.o \
+ excp_isr_sa_nn.o excp_isr_sa_ns.o excp_isr_sa_nr.o \
+ intr_isr_ps_nn.o intr_isr_ps_ns.o intr_isr_ps_nr.o \
+ intr_isr_sa_nn.o intr_isr_sa_ns.o intr_isr_sa_nr.o \
+ reset.o
+
+LIBNDS32_ISR_4B_OBJS = \
+ vec_vid00_4b.o vec_vid01_4b.o vec_vid02_4b.o vec_vid03_4b.o \
+ vec_vid04_4b.o vec_vid05_4b.o vec_vid06_4b.o vec_vid07_4b.o \
+ vec_vid08_4b.o vec_vid09_4b.o vec_vid10_4b.o vec_vid11_4b.o \
+ vec_vid12_4b.o vec_vid13_4b.o vec_vid14_4b.o vec_vid15_4b.o \
+ vec_vid16_4b.o vec_vid17_4b.o vec_vid18_4b.o vec_vid19_4b.o \
+ vec_vid20_4b.o vec_vid21_4b.o vec_vid22_4b.o vec_vid23_4b.o \
+ vec_vid24_4b.o vec_vid25_4b.o vec_vid26_4b.o vec_vid27_4b.o \
+ vec_vid28_4b.o vec_vid29_4b.o vec_vid30_4b.o vec_vid31_4b.o \
+ vec_vid32_4b.o vec_vid33_4b.o vec_vid34_4b.o vec_vid35_4b.o \
+ vec_vid36_4b.o vec_vid37_4b.o vec_vid38_4b.o vec_vid39_4b.o \
+ vec_vid40_4b.o vec_vid41_4b.o vec_vid42_4b.o vec_vid43_4b.o \
+ vec_vid44_4b.o vec_vid45_4b.o vec_vid46_4b.o vec_vid47_4b.o \
+ vec_vid48_4b.o vec_vid49_4b.o vec_vid50_4b.o vec_vid51_4b.o \
+ vec_vid52_4b.o vec_vid53_4b.o vec_vid54_4b.o vec_vid55_4b.o \
+ vec_vid56_4b.o vec_vid57_4b.o vec_vid58_4b.o vec_vid59_4b.o \
+ vec_vid60_4b.o vec_vid61_4b.o vec_vid62_4b.o vec_vid63_4b.o \
+ vec_vid64_4b.o vec_vid65_4b.o vec_vid66_4b.o vec_vid67_4b.o \
+ vec_vid68_4b.o vec_vid69_4b.o vec_vid70_4b.o vec_vid71_4b.o \
+ vec_vid72_4b.o \
+ excp_isr_ps_nn_4b.o excp_isr_ps_ns_4b.o excp_isr_ps_nr_4b.o \
+ excp_isr_sa_nn_4b.o excp_isr_sa_ns_4b.o excp_isr_sa_nr_4b.o \
+ intr_isr_ps_nn_4b.o intr_isr_ps_ns_4b.o intr_isr_ps_nr_4b.o \
+ intr_isr_sa_nn_4b.o intr_isr_sa_ns_4b.o intr_isr_sa_nr_4b.o \
+ reset_4b.o
+
+LIBNDS32_ISR_COMMON_OBJS = \
+ jmptbl_vid00.o jmptbl_vid01.o jmptbl_vid02.o jmptbl_vid03.o \
+ jmptbl_vid04.o jmptbl_vid05.o jmptbl_vid06.o jmptbl_vid07.o \
+ jmptbl_vid08.o jmptbl_vid09.o jmptbl_vid10.o jmptbl_vid11.o \
+ jmptbl_vid12.o jmptbl_vid13.o jmptbl_vid14.o jmptbl_vid15.o \
+ jmptbl_vid16.o jmptbl_vid17.o jmptbl_vid18.o jmptbl_vid19.o \
+ jmptbl_vid20.o jmptbl_vid21.o jmptbl_vid22.o jmptbl_vid23.o \
+ jmptbl_vid24.o jmptbl_vid25.o jmptbl_vid26.o jmptbl_vid27.o \
+ jmptbl_vid28.o jmptbl_vid29.o jmptbl_vid30.o jmptbl_vid31.o \
+ jmptbl_vid32.o jmptbl_vid33.o jmptbl_vid34.o jmptbl_vid35.o \
+ jmptbl_vid36.o jmptbl_vid37.o jmptbl_vid38.o jmptbl_vid39.o \
+ jmptbl_vid40.o jmptbl_vid41.o jmptbl_vid42.o jmptbl_vid43.o \
+ jmptbl_vid44.o jmptbl_vid45.o jmptbl_vid46.o jmptbl_vid47.o \
+ jmptbl_vid48.o jmptbl_vid49.o jmptbl_vid50.o jmptbl_vid51.o \
+ jmptbl_vid52.o jmptbl_vid53.o jmptbl_vid54.o jmptbl_vid55.o \
+ jmptbl_vid56.o jmptbl_vid57.o jmptbl_vid58.o jmptbl_vid59.o \
+ jmptbl_vid60.o jmptbl_vid61.o jmptbl_vid62.o jmptbl_vid63.o \
+ jmptbl_vid64.o jmptbl_vid65.o jmptbl_vid66.o jmptbl_vid67.o \
+ jmptbl_vid68.o jmptbl_vid69.o jmptbl_vid70.o jmptbl_vid71.o \
+ jmptbl_vid72.o \
+ nmih.o \
+ wrh.o
+
+LIBNDS32_ISR_COMPLETE_OBJS = $(LIBNDS32_ISR_16B_OBJS) $(LIBNDS32_ISR_4B_OBJS) $(LIBNDS32_ISR_COMMON_OBJS)
+
+
+# Build common objects for ISR library
+nmih.o: $(srcdir)/config/nds32/isr-library/nmih.S
+ $(GCC_FOR_TARGET) $(ISR_CFLAGS) $(srcdir)/config/nds32/isr-library/nmih.S -o nmih.o
+
+wrh.o: $(srcdir)/config/nds32/isr-library/wrh.S
+ $(GCC_FOR_TARGET) $(ISR_CFLAGS) $(srcdir)/config/nds32/isr-library/wrh.S -o wrh.o
+
+jmptbl_vid%.o: $(srcdir)/config/nds32/isr-library/jmptbl_vid%.S
+ $(GCC_FOR_TARGET) $(ISR_CFLAGS) $< -o $@
+
+
+
+# Build 16b version objects for ISR library. (no "_4b" postfix string)
+vec_vid%.o: $(srcdir)/config/nds32/isr-library/vec_vid%.S
+ $(GCC_FOR_TARGET) $(ISR_CFLAGS) $< -o $@
+
+excp_isr_ps_nn.o: $(srcdir)/config/nds32/isr-library/excp_isr.S
+ $(GCC_FOR_TARGET) $(ISR_CFLAGS) $(srcdir)/config/nds32/isr-library/excp_isr.S -o excp_isr_ps_nn.o
+
+excp_isr_ps_ns.o: $(srcdir)/config/nds32/isr-library/excp_isr.S
+ $(GCC_FOR_TARGET) $(ISR_CFLAGS) -DNDS32_NESTED $(srcdir)/config/nds32/isr-library/excp_isr.S -o excp_isr_ps_ns.o
+
+excp_isr_ps_nr.o: $(srcdir)/config/nds32/isr-library/excp_isr.S
+ $(GCC_FOR_TARGET) $(ISR_CFLAGS) -DNDS32_NESTED_READY $(srcdir)/config/nds32/isr-library/excp_isr.S -o excp_isr_ps_nr.o
+
+excp_isr_sa_nn.o: $(srcdir)/config/nds32/isr-library/excp_isr.S
+ $(GCC_FOR_TARGET) $(ISR_CFLAGS) -DNDS32_SAVE_ALL_REGS $(srcdir)/config/nds32/isr-library/excp_isr.S -o excp_isr_sa_nn.o
+
+excp_isr_sa_ns.o: $(srcdir)/config/nds32/isr-library/excp_isr.S
+ $(GCC_FOR_TARGET) $(ISR_CFLAGS) -DNDS32_SAVE_ALL_REGS -DNDS32_NESTED $(srcdir)/config/nds32/isr-library/excp_isr.S -o excp_isr_sa_ns.o
+
+excp_isr_sa_nr.o: $(srcdir)/config/nds32/isr-library/excp_isr.S
+ $(GCC_FOR_TARGET) $(ISR_CFLAGS) -DNDS32_SAVE_ALL_REGS -DNDS32_NESTED_READY $(srcdir)/config/nds32/isr-library/excp_isr.S -o excp_isr_sa_nr.o
+
+intr_isr_ps_nn.o: $(srcdir)/config/nds32/isr-library/intr_isr.S
+ $(GCC_FOR_TARGET) $(ISR_CFLAGS) $(srcdir)/config/nds32/isr-library/intr_isr.S -o intr_isr_ps_nn.o
+
+intr_isr_ps_ns.o: $(srcdir)/config/nds32/isr-library/intr_isr.S
+ $(GCC_FOR_TARGET) $(ISR_CFLAGS) -DNDS32_NESTED $(srcdir)/config/nds32/isr-library/intr_isr.S -o intr_isr_ps_ns.o
+
+intr_isr_ps_nr.o: $(srcdir)/config/nds32/isr-library/intr_isr.S
+ $(GCC_FOR_TARGET) $(ISR_CFLAGS) -DNDS32_NESTED_READY $(srcdir)/config/nds32/isr-library/intr_isr.S -o intr_isr_ps_nr.o
+
+intr_isr_sa_nn.o: $(srcdir)/config/nds32/isr-library/intr_isr.S
+ $(GCC_FOR_TARGET) $(ISR_CFLAGS) -DNDS32_SAVE_ALL_REGS $(srcdir)/config/nds32/isr-library/intr_isr.S -o intr_isr_sa_nn.o
+
+intr_isr_sa_ns.o: $(srcdir)/config/nds32/isr-library/intr_isr.S
+ $(GCC_FOR_TARGET) $(ISR_CFLAGS) -DNDS32_SAVE_ALL_REGS -DNDS32_NESTED $(srcdir)/config/nds32/isr-library/intr_isr.S -o intr_isr_sa_ns.o
+
+intr_isr_sa_nr.o: $(srcdir)/config/nds32/isr-library/intr_isr.S
+ $(GCC_FOR_TARGET) $(ISR_CFLAGS) -DNDS32_SAVE_ALL_REGS -DNDS32_NESTED_READY $(srcdir)/config/nds32/isr-library/intr_isr.S -o intr_isr_sa_nr.o
+
+reset.o: $(srcdir)/config/nds32/isr-library/reset.S
+ $(GCC_FOR_TARGET) $(ISR_CFLAGS) $(srcdir)/config/nds32/isr-library/reset.S -o reset.o
+
+# Build 4b version objects for ISR library.
+vec_vid%_4b.o: $(srcdir)/config/nds32/isr-library/vec_vid%_4b.S
+ $(GCC_FOR_TARGET) $(ISR_CFLAGS) $< -o $@
+
+excp_isr_ps_nn_4b.o: $(srcdir)/config/nds32/isr-library/excp_isr_4b.S
+ $(GCC_FOR_TARGET) $(ISR_CFLAGS) $(srcdir)/config/nds32/isr-library/excp_isr_4b.S -o excp_isr_ps_nn_4b.o
+
+excp_isr_ps_ns_4b.o: $(srcdir)/config/nds32/isr-library/excp_isr_4b.S
+ $(GCC_FOR_TARGET) $(ISR_CFLAGS) -DNDS32_NESTED $(srcdir)/config/nds32/isr-library/excp_isr_4b.S -o excp_isr_ps_ns_4b.o
+
+excp_isr_ps_nr_4b.o: $(srcdir)/config/nds32/isr-library/excp_isr_4b.S
+ $(GCC_FOR_TARGET) $(ISR_CFLAGS) -DNDS32_NESTED_READY $(srcdir)/config/nds32/isr-library/excp_isr_4b.S -o excp_isr_ps_nr_4b.o
+
+excp_isr_sa_nn_4b.o: $(srcdir)/config/nds32/isr-library/excp_isr_4b.S
+ $(GCC_FOR_TARGET) $(ISR_CFLAGS) -DNDS32_SAVE_ALL_REGS $(srcdir)/config/nds32/isr-library/excp_isr_4b.S -o excp_isr_sa_nn_4b.o
+
+excp_isr_sa_ns_4b.o: $(srcdir)/config/nds32/isr-library/excp_isr_4b.S
+ $(GCC_FOR_TARGET) $(ISR_CFLAGS) -DNDS32_SAVE_ALL_REGS -DNDS32_NESTED $(srcdir)/config/nds32/isr-library/excp_isr_4b.S -o excp_isr_sa_ns_4b.o
+
+excp_isr_sa_nr_4b.o: $(srcdir)/config/nds32/isr-library/excp_isr_4b.S
+ $(GCC_FOR_TARGET) $(ISR_CFLAGS) -DNDS32_SAVE_ALL_REGS -DNDS32_NESTED_READY $(srcdir)/config/nds32/isr-library/excp_isr_4b.S -o excp_isr_sa_nr_4b.o
+
+intr_isr_ps_nn_4b.o: $(srcdir)/config/nds32/isr-library/intr_isr_4b.S
+ $(GCC_FOR_TARGET) $(ISR_CFLAGS) $(srcdir)/config/nds32/isr-library/intr_isr_4b.S -o intr_isr_ps_nn_4b.o
+
+intr_isr_ps_ns_4b.o: $(srcdir)/config/nds32/isr-library/intr_isr_4b.S
+ $(GCC_FOR_TARGET) $(ISR_CFLAGS) -DNDS32_NESTED $(srcdir)/config/nds32/isr-library/intr_isr_4b.S -o intr_isr_ps_ns_4b.o
+
+intr_isr_ps_nr_4b.o: $(srcdir)/config/nds32/isr-library/intr_isr_4b.S
+ $(GCC_FOR_TARGET) $(ISR_CFLAGS) -DNDS32_NESTED_READY $(srcdir)/config/nds32/isr-library/intr_isr_4b.S -o intr_isr_ps_nr_4b.o
+
+intr_isr_sa_nn_4b.o: $(srcdir)/config/nds32/isr-library/intr_isr_4b.S
+ $(GCC_FOR_TARGET) $(ISR_CFLAGS) -DNDS32_SAVE_ALL_REGS $(srcdir)/config/nds32/isr-library/intr_isr_4b.S -o intr_isr_sa_nn_4b.o
+
+intr_isr_sa_ns_4b.o: $(srcdir)/config/nds32/isr-library/intr_isr_4b.S
+ $(GCC_FOR_TARGET) $(ISR_CFLAGS) -DNDS32_SAVE_ALL_REGS -DNDS32_NESTED $(srcdir)/config/nds32/isr-library/intr_isr_4b.S -o intr_isr_sa_ns_4b.o
+
+intr_isr_sa_nr_4b.o: $(srcdir)/config/nds32/isr-library/intr_isr_4b.S
+ $(GCC_FOR_TARGET) $(ISR_CFLAGS) -DNDS32_SAVE_ALL_REGS -DNDS32_NESTED_READY $(srcdir)/config/nds32/isr-library/intr_isr_4b.S -o intr_isr_sa_nr_4b.o
+
+reset_4b.o: $(srcdir)/config/nds32/isr-library/reset_4b.S
+ $(GCC_FOR_TARGET) $(ISR_CFLAGS) $(srcdir)/config/nds32/isr-library/reset_4b.S -o reset_4b.o
+
+
+# The rule to create libnds32_isr.a file
+libnds32_isr.a: $(LIBNDS32_ISR_COMPLETE_OBJS)
+ $(AR) rc libnds32_isr.a $(LIBNDS32_ISR_COMPLETE_OBJS)
+
+
+# ------------------------------------------------------------------------
diff --git a/libgcc/config/nds32/t-nds32-mculib b/libgcc/config/nds32/t-nds32-mculib
new file mode 100644
index 00000000000..4fbcf4ff52e
--- /dev/null
+++ b/libgcc/config/nds32/t-nds32-mculib
@@ -0,0 +1,77 @@
+# Rules of mculib library makefile of Andes NDS32 cpu for GNU compiler
+# Copyright (C) 2012-2013 Free Software Foundation, Inc.
+# Contributed by Andes Technology Corporation.
+#
+# This file is part of GCC.
+#
+# GCC is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published
+# by the Free Software Foundation; either version 3, or (at your
+# option) any later version.
+#
+# GCC is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+# License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+# Compiler flags to use when compiling 'libgcc2.c'
+HOST_LIBGCC2_CFLAGS = -Os
+
+
+LIB1ASMSRC = nds32/lib1asmsrc-mculib.S
+
+LIB1ASMFUNCS = \
+ _addsub_sf \
+ _sf_to_si \
+ _divsi3 \
+ _divdi3 \
+ _modsi3 \
+ _moddi3 \
+ _mulsi3 \
+ _udivsi3 \
+ _udivdi3 \
+ _udivmoddi4 \
+ _umodsi3 \
+ _umoddi3 \
+ _muldi3 \
+ _addsub_df \
+ _mul_sf \
+ _mul_df \
+ _div_sf \
+ _div_df \
+ _negate_sf \
+ _negate_df \
+ _sf_to_df \
+ _df_to_sf \
+ _df_to_si \
+ _fixsfdi \
+ _fixdfdi \
+ _fixunssfsi \
+ _fixunsdfsi \
+ _fixunssfdi \
+ _fixunsdfdi \
+ _si_to_sf \
+ _si_to_df \
+ _floatdisf \
+ _floatdidf \
+ _floatunsisf \
+ _floatunsidf \
+ _floatundisf \
+ _floatundidf \
+ _compare_sf \
+ _compare_df \
+ _unord_sf \
+ _unord_df
+
+# List of functions not to build from libgcc2.c.
+LIB2FUNCS_EXCLUDE = _clzsi2 _clzdi2
+
+# List of extra C and assembler files(*.S) to add to static libgcc2.
+LIB2ADD_ST += $(srcdir)/config/nds32/lib2csrc-mculib/_clzsi2.c
+LIB2ADD_ST += $(srcdir)/config/nds32/lib2csrc-mculib/_clzdi2.c
+
+# ------------------------------------------------------------------------
diff --git a/libgcc/config/nds32/t-nds32-newlib b/libgcc/config/nds32/t-nds32-newlib
new file mode 100644
index 00000000000..b2549a084e9
--- /dev/null
+++ b/libgcc/config/nds32/t-nds32-newlib
@@ -0,0 +1,34 @@
+# Rules of newlib library makefile of Andes NDS32 cpu for GNU compiler
+# Copyright (C) 2012-2013 Free Software Foundation, Inc.
+# Contributed by Andes Technology Corporation.
+#
+# This file is part of GCC.
+#
+# GCC is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published
+# by the Free Software Foundation; either version 3, or (at your
+# option) any later version.
+#
+# GCC is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+# License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+# Compiler flags to use when compiling 'libgcc2.c'
+HOST_LIBGCC2_CFLAGS = -O2
+
+
+#LIB1ASMSRC = nds32/lib1asmsrc-newlib.S
+#LIB1ASMFUNCS = _divsi3 _modsi3 _udivsi3 _umodsi3
+
+# List of functions not to build from libgcc2.c.
+#LIB2FUNCS_EXCLUDE = _clzsi2
+
+# List of extra C and assembler files(*.S) to add to static libgcc2.
+#LIB2ADD_ST += $(srcdir)/config/nds32/lib2csrc-newlib/_clzsi2.c
+
+# ------------------------------------------------------------------------
diff --git a/libgcc/configure b/libgcc/configure
index 29fa46f597a..2bb1fb2d94f 100644
--- a/libgcc/configure
+++ b/libgcc/configure
@@ -4066,7 +4066,20 @@ if test "${libgcc_cv_dfp+set}" = set; then :
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
+
+#include <fenv.h>
+
+int
+main ()
+{
+
_Decimal32 x;
+int fe_except =
+ FE_INVALID|FE_DIVBYZERO|FE_OVERFLOW|FE_UNDERFLOW|FE_INEXACT;
+
+ ;
+ return 0;
+}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
libgcc_cv_dfp=yes
diff --git a/libgcc/configure.ac b/libgcc/configure.ac
index 186cd6e9cd7..560e988e048 100644
--- a/libgcc/configure.ac
+++ b/libgcc/configure.ac
@@ -182,7 +182,14 @@ AC_SUBST(long_double_type_size)
# Check for decimal float support.
AC_CACHE_CHECK([whether decimal floating point is supported], [libgcc_cv_dfp],
- [AC_COMPILE_IFELSE([_Decimal32 x;], [libgcc_cv_dfp=yes],
+ [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <fenv.h>
+]], [[
+_Decimal32 x;
+int fe_except =
+ FE_INVALID|FE_DIVBYZERO|FE_OVERFLOW|FE_UNDERFLOW|FE_INEXACT;
+]])],
+ [libgcc_cv_dfp=yes],
[libgcc_cv_dfp=no])])
decimal_float=$libgcc_cv_dfp
AC_SUBST(decimal_float)
diff --git a/libgcc/libgcov.c b/libgcc/libgcov.c
index 3c39331e6ba..6450fd76548 100644
--- a/libgcc/libgcov.c
+++ b/libgcc/libgcov.c
@@ -80,6 +80,7 @@ void __gcov_merge_delta (gcov_type *counters __attribute__ ((unused)),
#include <sys/stat.h>
#endif
+extern gcov_type function_counter ATTRIBUTE_HIDDEN;
extern void gcov_clear (void) ATTRIBUTE_HIDDEN;
extern void gcov_exit (void) ATTRIBUTE_HIDDEN;
extern int gcov_dump_complete ATTRIBUTE_HIDDEN;
@@ -350,6 +351,10 @@ gcov_compute_histogram (struct gcov_summary *sum)
}
}
+
+/* Counter for first visit of each function. */
+gcov_type function_counter;
+
/* Dump the coverage counts. We merge with existing counts when
possible, to avoid growing the .da files ad infinitum. We use this
program's checksum to make sure we only accumulate whole program
@@ -974,6 +979,27 @@ __gcov_merge_ior (gcov_type *counters, unsigned n_counters)
}
#endif
+/* Time profiles are merged so that minimum from all valid (greater than zero)
+ * is stored. There could be a fork that creates new counters. To have
+ * the profile stable, we chosen to pick the smallest function visit time. */
+
+#ifdef L_gcov_merge_time_profile
+void
+__gcov_merge_time_profile (gcov_type *counters, unsigned n_counters)
+{
+ unsigned int i;
+ gcov_type value;
+
+ for (i = 0; i < n_counters; i++)
+ {
+ value = gcov_read_counter ();
+
+ if (value && (!counters[i] || value < counters[i]))
+ counters[i] = value;
+ }
+}
+#endif /* L_gcov_merge_time_profile */
+
#ifdef L_gcov_merge_single
/* The profile merging function for choosing the most common value.
It is given an array COUNTERS of N_COUNTERS old counters and it
@@ -1202,6 +1228,18 @@ __gcov_indirect_call_profiler_v2 (gcov_type value, void* cur_func)
}
#endif
+#ifdef L_gcov_time_profiler
+
+/* Sets corresponding COUNTERS if there is no value. */
+
+void
+__gcov_time_profiler (gcov_type* counters)
+{
+ if (!counters[0])
+ counters[0] = ++function_counter;
+}
+#endif
+
#ifdef L_gcov_average_profiler
/* Increase corresponding COUNTER by VALUE. FIXME: Perhaps we want
to saturate up. */
diff --git a/libgcc/longlong.h b/libgcc/longlong.h
index c4b1b97be0a..5f00e548a70 100644
--- a/libgcc/longlong.h
+++ b/libgcc/longlong.h
@@ -188,16 +188,20 @@ extern UDItype __udiv_qrnnd (UDItype *, UDItype, UDItype, UDItype);
"rIJ" ((USItype) (bh)), \
"r" ((USItype) (al)), \
"rIJ" ((USItype) (bl)))
-/* Call libgcc routine. */
-#define umul_ppmm(w1, w0, u, v) \
-do { \
- DWunion __w; \
- __w.ll = __umulsidi3 (u, v); \
- w1 = __w.s.high; \
- w0 = __w.s.low; \
-} while (0)
-#define __umulsidi3 __umulsidi3
-UDItype __umulsidi3 (USItype, USItype);
+
+#define __umulsidi3(u,v) ((UDItype)(USItype)u*(USItype)v)
+#ifdef __ARC_NORM__
+#define count_leading_zeros(count, x) \
+ do \
+ { \
+ SItype c_; \
+ \
+ __asm__ ("norm.f\t%0,%1\n\tmov.mi\t%0,-1" : "=r" (c_) : "r" (x) : "cc");\
+ (count) = c_ + 1; \
+ } \
+ while (0)
+#define COUNT_LEADING_ZEROS_0 32
+#endif
#endif
#if defined (__arm__) && (defined (__thumb2__) || !defined (__thumb__)) \
@@ -285,12 +289,39 @@ UDItype __umulsidi3 (USItype, USItype);
#endif /* defined (__AVR__) */
-#if defined (__CRIS__) && __CRIS_arch_version >= 3
+#if defined (__CRIS__)
+
+#if __CRIS_arch_version >= 3
#define count_leading_zeros(COUNT, X) ((COUNT) = __builtin_clz (X))
+#define COUNT_LEADING_ZEROS_0 32
+#endif /* __CRIS_arch_version >= 3 */
+
#if __CRIS_arch_version >= 8
#define count_trailing_zeros(COUNT, X) ((COUNT) = __builtin_ctz (X))
-#endif
-#endif /* __CRIS__ */
+#endif /* __CRIS_arch_version >= 8 */
+
+#if __CRIS_arch_version >= 10
+#define __umulsidi3(u,v) ((UDItype)(USItype) (u) * (UDItype)(USItype) (v))
+#else
+#define __umulsidi3 __umulsidi3
+extern UDItype __umulsidi3 (USItype, USItype);
+#endif /* __CRIS_arch_version >= 10 */
+
+#define umul_ppmm(w1, w0, u, v) \
+ do { \
+ UDItype __x = __umulsidi3 (u, v); \
+ (w0) = (USItype) (__x); \
+ (w1) = (USItype) (__x >> 32); \
+ } while (0)
+
+/* FIXME: defining add_ssaaaa and sub_ddmmss should be advantageous for
+ DFmode ("double" intrinsics, avoiding two of the three insns handling
+ carry), but defining them as open-code C composing and doing the
+ operation in DImode (UDImode) shows that the DImode needs work:
+ register pressure from requiring neighboring registers and the
+ traffic to and from them come to dominate, in the 4.7 series. */
+
+#endif /* defined (__CRIS__) */
#if defined (__hppa) && W_TYPE_SIZE == 32
#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
diff --git a/libgcc/soft-fp/README b/libgcc/soft-fp/README
index 361386de771..d60e88b7fec 100644
--- a/libgcc/soft-fp/README
+++ b/libgcc/soft-fp/README
@@ -1,5 +1,4 @@
-Except for conversions involving TImode and conversions involving
-XFmode, the files in this directory are part of the GNU C Library, not part
-of GCC. As described at <http://gcc.gnu.org/codingconventions.html>, changes
-should be made to the GNU C Library and the changed files then imported
-into GCC.
+The files in this directory are part of the GNU C Library, not part of
+GCC. As described at <http://gcc.gnu.org/codingconventions.html>,
+changes should be made to the GNU C Library and the changed files then
+imported into GCC.
diff --git a/libgcc/soft-fp/adddf3.c b/libgcc/soft-fp/adddf3.c
index 55df554b050..5aadfa3318b 100644
--- a/libgcc/soft-fp/adddf3.c
+++ b/libgcc/soft-fp/adddf3.c
@@ -31,17 +31,20 @@
#include "soft-fp.h"
#include "double.h"
-DFtype __adddf3(DFtype a, DFtype b)
+DFtype
+__adddf3 (DFtype a, DFtype b)
{
FP_DECL_EX;
- FP_DECL_D(A); FP_DECL_D(B); FP_DECL_D(R);
+ FP_DECL_D (A);
+ FP_DECL_D (B);
+ FP_DECL_D (R);
DFtype r;
FP_INIT_ROUNDMODE;
- FP_UNPACK_SEMIRAW_D(A, a);
- FP_UNPACK_SEMIRAW_D(B, b);
- FP_ADD_D(R, A, B);
- FP_PACK_SEMIRAW_D(r, R);
+ FP_UNPACK_SEMIRAW_D (A, a);
+ FP_UNPACK_SEMIRAW_D (B, b);
+ FP_ADD_D (R, A, B);
+ FP_PACK_SEMIRAW_D (r, R);
FP_HANDLE_EXCEPTIONS;
return r;
diff --git a/libgcc/soft-fp/addsf3.c b/libgcc/soft-fp/addsf3.c
index 8a31449e379..ac571bad06b 100644
--- a/libgcc/soft-fp/addsf3.c
+++ b/libgcc/soft-fp/addsf3.c
@@ -31,17 +31,20 @@
#include "soft-fp.h"
#include "single.h"
-SFtype __addsf3(SFtype a, SFtype b)
+SFtype
+__addsf3 (SFtype a, SFtype b)
{
FP_DECL_EX;
- FP_DECL_S(A); FP_DECL_S(B); FP_DECL_S(R);
+ FP_DECL_S (A);
+ FP_DECL_S (B);
+ FP_DECL_S (R);
SFtype r;
FP_INIT_ROUNDMODE;
- FP_UNPACK_SEMIRAW_S(A, a);
- FP_UNPACK_SEMIRAW_S(B, b);
- FP_ADD_S(R, A, B);
- FP_PACK_SEMIRAW_S(r, R);
+ FP_UNPACK_SEMIRAW_S (A, a);
+ FP_UNPACK_SEMIRAW_S (B, b);
+ FP_ADD_S (R, A, B);
+ FP_PACK_SEMIRAW_S (r, R);
FP_HANDLE_EXCEPTIONS;
return r;
diff --git a/libgcc/soft-fp/addtf3.c b/libgcc/soft-fp/addtf3.c
index 7a2732513a9..1c0d266c66c 100644
--- a/libgcc/soft-fp/addtf3.c
+++ b/libgcc/soft-fp/addtf3.c
@@ -31,17 +31,20 @@
#include "soft-fp.h"
#include "quad.h"
-TFtype __addtf3(TFtype a, TFtype b)
+TFtype
+__addtf3 (TFtype a, TFtype b)
{
FP_DECL_EX;
- FP_DECL_Q(A); FP_DECL_Q(B); FP_DECL_Q(R);
+ FP_DECL_Q (A);
+ FP_DECL_Q (B);
+ FP_DECL_Q (R);
TFtype r;
FP_INIT_ROUNDMODE;
- FP_UNPACK_SEMIRAW_Q(A, a);
- FP_UNPACK_SEMIRAW_Q(B, b);
- FP_ADD_Q(R, A, B);
- FP_PACK_SEMIRAW_Q(r, R);
+ FP_UNPACK_SEMIRAW_Q (A, a);
+ FP_UNPACK_SEMIRAW_Q (B, b);
+ FP_ADD_Q (R, A, B);
+ FP_PACK_SEMIRAW_Q (r, R);
FP_HANDLE_EXCEPTIONS;
return r;
diff --git a/libgcc/soft-fp/divdf3.c b/libgcc/soft-fp/divdf3.c
index c3dcf8085e4..d357bf0222c 100644
--- a/libgcc/soft-fp/divdf3.c
+++ b/libgcc/soft-fp/divdf3.c
@@ -31,17 +31,20 @@
#include "soft-fp.h"
#include "double.h"
-DFtype __divdf3(DFtype a, DFtype b)
+DFtype
+__divdf3 (DFtype a, DFtype b)
{
FP_DECL_EX;
- FP_DECL_D(A); FP_DECL_D(B); FP_DECL_D(R);
+ FP_DECL_D (A);
+ FP_DECL_D (B);
+ FP_DECL_D (R);
DFtype r;
FP_INIT_ROUNDMODE;
- FP_UNPACK_D(A, a);
- FP_UNPACK_D(B, b);
- FP_DIV_D(R, A, B);
- FP_PACK_D(r, R);
+ FP_UNPACK_D (A, a);
+ FP_UNPACK_D (B, b);
+ FP_DIV_D (R, A, B);
+ FP_PACK_D (r, R);
FP_HANDLE_EXCEPTIONS;
return r;
diff --git a/libgcc/soft-fp/divsf3.c b/libgcc/soft-fp/divsf3.c
index 063462f8a16..b53b4031d7a 100644
--- a/libgcc/soft-fp/divsf3.c
+++ b/libgcc/soft-fp/divsf3.c
@@ -31,17 +31,20 @@
#include "soft-fp.h"
#include "single.h"
-SFtype __divsf3(SFtype a, SFtype b)
+SFtype
+__divsf3 (SFtype a, SFtype b)
{
FP_DECL_EX;
- FP_DECL_S(A); FP_DECL_S(B); FP_DECL_S(R);
+ FP_DECL_S (A);
+ FP_DECL_S (B);
+ FP_DECL_S (R);
SFtype r;
FP_INIT_ROUNDMODE;
- FP_UNPACK_S(A, a);
- FP_UNPACK_S(B, b);
- FP_DIV_S(R, A, B);
- FP_PACK_S(r, R);
+ FP_UNPACK_S (A, a);
+ FP_UNPACK_S (B, b);
+ FP_DIV_S (R, A, B);
+ FP_PACK_S (r, R);
FP_HANDLE_EXCEPTIONS;
return r;
diff --git a/libgcc/soft-fp/divtf3.c b/libgcc/soft-fp/divtf3.c
index 03d017ddb6e..5b7175da54c 100644
--- a/libgcc/soft-fp/divtf3.c
+++ b/libgcc/soft-fp/divtf3.c
@@ -31,17 +31,20 @@
#include "soft-fp.h"
#include "quad.h"
-TFtype __divtf3(TFtype a, TFtype b)
+TFtype
+__divtf3 (TFtype a, TFtype b)
{
FP_DECL_EX;
- FP_DECL_Q(A); FP_DECL_Q(B); FP_DECL_Q(R);
+ FP_DECL_Q (A);
+ FP_DECL_Q (B);
+ FP_DECL_Q (R);
TFtype r;
FP_INIT_ROUNDMODE;
- FP_UNPACK_Q(A, a);
- FP_UNPACK_Q(B, b);
- FP_DIV_Q(R, A, B);
- FP_PACK_Q(r, R);
+ FP_UNPACK_Q (A, a);
+ FP_UNPACK_Q (B, b);
+ FP_DIV_Q (R, A, B);
+ FP_PACK_Q (r, R);
FP_HANDLE_EXCEPTIONS;
return r;
diff --git a/libgcc/soft-fp/double.h b/libgcc/soft-fp/double.h
index 759c2eb661a..ef4576707a7 100644
--- a/libgcc/soft-fp/double.h
+++ b/libgcc/soft-fp/double.h
@@ -31,13 +31,15 @@
<http://www.gnu.org/licenses/>. */
#if _FP_W_TYPE_SIZE < 32
-#error "Here's a nickel kid. Go buy yourself a real computer."
+# error "Here's a nickel kid. Go buy yourself a real computer."
#endif
#if _FP_W_TYPE_SIZE < 64
-#define _FP_FRACTBITS_D (2 * _FP_W_TYPE_SIZE)
+# define _FP_FRACTBITS_D (2 * _FP_W_TYPE_SIZE)
+# define _FP_FRACTBITS_DW_D (4 * _FP_W_TYPE_SIZE)
#else
-#define _FP_FRACTBITS_D _FP_W_TYPE_SIZE
+# define _FP_FRACTBITS_D _FP_W_TYPE_SIZE
+# define _FP_FRACTBITS_DW_D (2 * _FP_W_TYPE_SIZE)
#endif
#define _FP_FRACBITS_D 53
@@ -49,215 +51,264 @@
#define _FP_EXPMAX_D 2047
#define _FP_QNANBIT_D \
- ((_FP_W_TYPE)1 << (_FP_FRACBITS_D-2) % _FP_W_TYPE_SIZE)
+ ((_FP_W_TYPE) 1 << (_FP_FRACBITS_D-2) % _FP_W_TYPE_SIZE)
#define _FP_QNANBIT_SH_D \
- ((_FP_W_TYPE)1 << (_FP_FRACBITS_D-2+_FP_WORKBITS) % _FP_W_TYPE_SIZE)
+ ((_FP_W_TYPE) 1 << (_FP_FRACBITS_D-2+_FP_WORKBITS) % _FP_W_TYPE_SIZE)
#define _FP_IMPLBIT_D \
- ((_FP_W_TYPE)1 << (_FP_FRACBITS_D-1) % _FP_W_TYPE_SIZE)
+ ((_FP_W_TYPE) 1 << (_FP_FRACBITS_D-1) % _FP_W_TYPE_SIZE)
#define _FP_IMPLBIT_SH_D \
- ((_FP_W_TYPE)1 << (_FP_FRACBITS_D-1+_FP_WORKBITS) % _FP_W_TYPE_SIZE)
+ ((_FP_W_TYPE) 1 << (_FP_FRACBITS_D-1+_FP_WORKBITS) % _FP_W_TYPE_SIZE)
#define _FP_OVERFLOW_D \
- ((_FP_W_TYPE)1 << _FP_WFRACBITS_D % _FP_W_TYPE_SIZE)
+ ((_FP_W_TYPE) 1 << _FP_WFRACBITS_D % _FP_W_TYPE_SIZE)
-typedef float DFtype __attribute__((mode(DF)));
+#define _FP_WFRACBITS_DW_D (2 * _FP_WFRACBITS_D)
+#define _FP_WFRACXBITS_DW_D (_FP_FRACTBITS_DW_D - _FP_WFRACBITS_DW_D)
+#define _FP_HIGHBIT_DW_D \
+ ((_FP_W_TYPE) 1 << (_FP_WFRACBITS_DW_D - 1) % _FP_W_TYPE_SIZE)
+
+typedef float DFtype __attribute__ ((mode (DF)));
#if _FP_W_TYPE_SIZE < 64
union _FP_UNION_D
{
DFtype flt;
- struct _FP_STRUCT_LAYOUT {
-#if __BYTE_ORDER == __BIG_ENDIAN
+ struct _FP_STRUCT_LAYOUT
+ {
+# if __BYTE_ORDER == __BIG_ENDIAN
unsigned sign : 1;
unsigned exp : _FP_EXPBITS_D;
unsigned frac1 : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0) - _FP_W_TYPE_SIZE;
unsigned frac0 : _FP_W_TYPE_SIZE;
-#else
+# else
unsigned frac0 : _FP_W_TYPE_SIZE;
unsigned frac1 : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0) - _FP_W_TYPE_SIZE;
unsigned exp : _FP_EXPBITS_D;
unsigned sign : 1;
-#endif
- } bits __attribute__((packed));
+# endif
+ } bits __attribute__ ((packed));
};
-#define FP_DECL_D(X) _FP_DECL(2,X)
-#define FP_UNPACK_RAW_D(X,val) _FP_UNPACK_RAW_2(D,X,val)
-#define FP_UNPACK_RAW_DP(X,val) _FP_UNPACK_RAW_2_P(D,X,val)
-#define FP_PACK_RAW_D(val,X) _FP_PACK_RAW_2(D,val,X)
-#define FP_PACK_RAW_DP(val,X) \
- do { \
- if (!FP_INHIBIT_RESULTS) \
- _FP_PACK_RAW_2_P(D,val,X); \
- } while (0)
-
-#define FP_UNPACK_D(X,val) \
- do { \
- _FP_UNPACK_RAW_2(D,X,val); \
- _FP_UNPACK_CANONICAL(D,2,X); \
- } while (0)
-
-#define FP_UNPACK_DP(X,val) \
- do { \
- _FP_UNPACK_RAW_2_P(D,X,val); \
- _FP_UNPACK_CANONICAL(D,2,X); \
- } while (0)
-
-#define FP_UNPACK_SEMIRAW_D(X,val) \
- do { \
- _FP_UNPACK_RAW_2(D,X,val); \
- _FP_UNPACK_SEMIRAW(D,2,X); \
- } while (0)
-
-#define FP_UNPACK_SEMIRAW_DP(X,val) \
- do { \
- _FP_UNPACK_RAW_2_P(D,X,val); \
- _FP_UNPACK_SEMIRAW(D,2,X); \
- } while (0)
-
-#define FP_PACK_D(val,X) \
- do { \
- _FP_PACK_CANONICAL(D,2,X); \
- _FP_PACK_RAW_2(D,val,X); \
- } while (0)
-
-#define FP_PACK_DP(val,X) \
- do { \
- _FP_PACK_CANONICAL(D,2,X); \
- if (!FP_INHIBIT_RESULTS) \
- _FP_PACK_RAW_2_P(D,val,X); \
- } while (0)
-
-#define FP_PACK_SEMIRAW_D(val,X) \
- do { \
- _FP_PACK_SEMIRAW(D,2,X); \
- _FP_PACK_RAW_2(D,val,X); \
- } while (0)
-
-#define FP_PACK_SEMIRAW_DP(val,X) \
- do { \
- _FP_PACK_SEMIRAW(D,2,X); \
- if (!FP_INHIBIT_RESULTS) \
- _FP_PACK_RAW_2_P(D,val,X); \
- } while (0)
-
-#define FP_ISSIGNAN_D(X) _FP_ISSIGNAN(D,2,X)
-#define FP_NEG_D(R,X) _FP_NEG(D,2,R,X)
-#define FP_ADD_D(R,X,Y) _FP_ADD(D,2,R,X,Y)
-#define FP_SUB_D(R,X,Y) _FP_SUB(D,2,R,X,Y)
-#define FP_MUL_D(R,X,Y) _FP_MUL(D,2,R,X,Y)
-#define FP_DIV_D(R,X,Y) _FP_DIV(D,2,R,X,Y)
-#define FP_SQRT_D(R,X) _FP_SQRT(D,2,R,X)
-#define _FP_SQRT_MEAT_D(R,S,T,X,Q) _FP_SQRT_MEAT_2(R,S,T,X,Q)
-
-#define FP_CMP_D(r,X,Y,un) _FP_CMP(D,2,r,X,Y,un)
-#define FP_CMP_EQ_D(r,X,Y) _FP_CMP_EQ(D,2,r,X,Y)
-#define FP_CMP_UNORD_D(r,X,Y) _FP_CMP_UNORD(D,2,r,X,Y)
-
-#define FP_TO_INT_D(r,X,rsz,rsg) _FP_TO_INT(D,2,r,X,rsz,rsg)
-#define FP_FROM_INT_D(X,r,rs,rt) _FP_FROM_INT(D,2,X,r,rs,rt)
-
-#define _FP_FRAC_HIGH_D(X) _FP_FRAC_HIGH_2(X)
-#define _FP_FRAC_HIGH_RAW_D(X) _FP_FRAC_HIGH_2(X)
+# define FP_DECL_D(X) _FP_DECL (2, X)
+# define FP_UNPACK_RAW_D(X, val) _FP_UNPACK_RAW_2 (D, X, val)
+# define FP_UNPACK_RAW_DP(X, val) _FP_UNPACK_RAW_2_P (D, X, val)
+# define FP_PACK_RAW_D(val, X) _FP_PACK_RAW_2 (D, val, X)
+# define FP_PACK_RAW_DP(val, X) \
+ do \
+ { \
+ if (!FP_INHIBIT_RESULTS) \
+ _FP_PACK_RAW_2_P (D, val, X); \
+ } \
+ while (0)
+
+# define FP_UNPACK_D(X, val) \
+ do \
+ { \
+ _FP_UNPACK_RAW_2 (D, X, val); \
+ _FP_UNPACK_CANONICAL (D, 2, X); \
+ } \
+ while (0)
+
+# define FP_UNPACK_DP(X, val) \
+ do \
+ { \
+ _FP_UNPACK_RAW_2_P (D, X, val); \
+ _FP_UNPACK_CANONICAL (D, 2, X); \
+ } \
+ while (0)
+
+# define FP_UNPACK_SEMIRAW_D(X, val) \
+ do \
+ { \
+ _FP_UNPACK_RAW_2 (D, X, val); \
+ _FP_UNPACK_SEMIRAW (D, 2, X); \
+ } \
+ while (0)
+
+# define FP_UNPACK_SEMIRAW_DP(X, val) \
+ do \
+ { \
+ _FP_UNPACK_RAW_2_P (D, X, val); \
+ _FP_UNPACK_SEMIRAW (D, 2, X); \
+ } \
+ while (0)
+
+# define FP_PACK_D(val, X) \
+ do \
+ { \
+ _FP_PACK_CANONICAL (D, 2, X); \
+ _FP_PACK_RAW_2 (D, val, X); \
+ } \
+ while (0)
+
+# define FP_PACK_DP(val, X) \
+ do \
+ { \
+ _FP_PACK_CANONICAL (D, 2, X); \
+ if (!FP_INHIBIT_RESULTS) \
+ _FP_PACK_RAW_2_P (D, val, X); \
+ } \
+ while (0)
+
+# define FP_PACK_SEMIRAW_D(val, X) \
+ do \
+ { \
+ _FP_PACK_SEMIRAW (D, 2, X); \
+ _FP_PACK_RAW_2 (D, val, X); \
+ } \
+ while (0)
+
+# define FP_PACK_SEMIRAW_DP(val, X) \
+ do \
+ { \
+ _FP_PACK_SEMIRAW (D, 2, X); \
+ if (!FP_INHIBIT_RESULTS) \
+ _FP_PACK_RAW_2_P (D, val, X); \
+ } \
+ while (0)
+
+# define FP_ISSIGNAN_D(X) _FP_ISSIGNAN (D, 2, X)
+# define FP_NEG_D(R, X) _FP_NEG (D, 2, R, X)
+# define FP_ADD_D(R, X, Y) _FP_ADD (D, 2, R, X, Y)
+# define FP_SUB_D(R, X, Y) _FP_SUB (D, 2, R, X, Y)
+# define FP_MUL_D(R, X, Y) _FP_MUL (D, 2, R, X, Y)
+# define FP_DIV_D(R, X, Y) _FP_DIV (D, 2, R, X, Y)
+# define FP_SQRT_D(R, X) _FP_SQRT (D, 2, R, X)
+# define _FP_SQRT_MEAT_D(R, S, T, X, Q) _FP_SQRT_MEAT_2 (R, S, T, X, Q)
+# define FP_FMA_D(R, X, Y, Z) _FP_FMA (D, 2, 4, R, X, Y, Z)
+
+# define FP_CMP_D(r, X, Y, un) _FP_CMP (D, 2, r, X, Y, un)
+# define FP_CMP_EQ_D(r, X, Y) _FP_CMP_EQ (D, 2, r, X, Y)
+# define FP_CMP_UNORD_D(r, X, Y) _FP_CMP_UNORD (D, 2, r, X, Y)
+
+# define FP_TO_INT_D(r, X, rsz, rsg) _FP_TO_INT (D, 2, r, X, rsz, rsg)
+# define FP_FROM_INT_D(X, r, rs, rt) _FP_FROM_INT (D, 2, X, r, rs, rt)
+
+# define _FP_FRAC_HIGH_D(X) _FP_FRAC_HIGH_2 (X)
+# define _FP_FRAC_HIGH_RAW_D(X) _FP_FRAC_HIGH_2 (X)
+
+# define _FP_FRAC_HIGH_DW_D(X) _FP_FRAC_HIGH_4 (X)
#else
union _FP_UNION_D
{
DFtype flt;
- struct _FP_STRUCT_LAYOUT {
-#if __BYTE_ORDER == __BIG_ENDIAN
+ struct _FP_STRUCT_LAYOUT
+ {
+# if __BYTE_ORDER == __BIG_ENDIAN
unsigned sign : 1;
unsigned exp : _FP_EXPBITS_D;
_FP_W_TYPE frac : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0);
-#else
+# else
_FP_W_TYPE frac : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0);
unsigned exp : _FP_EXPBITS_D;
unsigned sign : 1;
-#endif
- } bits __attribute__((packed));
+# endif
+ } bits __attribute__ ((packed));
};
-#define FP_DECL_D(X) _FP_DECL(1,X)
-#define FP_UNPACK_RAW_D(X,val) _FP_UNPACK_RAW_1(D,X,val)
-#define FP_UNPACK_RAW_DP(X,val) _FP_UNPACK_RAW_1_P(D,X,val)
-#define FP_PACK_RAW_D(val,X) _FP_PACK_RAW_1(D,val,X)
-#define FP_PACK_RAW_DP(val,X) \
- do { \
- if (!FP_INHIBIT_RESULTS) \
- _FP_PACK_RAW_1_P(D,val,X); \
- } while (0)
-
-#define FP_UNPACK_D(X,val) \
- do { \
- _FP_UNPACK_RAW_1(D,X,val); \
- _FP_UNPACK_CANONICAL(D,1,X); \
- } while (0)
-
-#define FP_UNPACK_DP(X,val) \
- do { \
- _FP_UNPACK_RAW_1_P(D,X,val); \
- _FP_UNPACK_CANONICAL(D,1,X); \
- } while (0)
-
-#define FP_UNPACK_SEMIRAW_D(X,val) \
- do { \
- _FP_UNPACK_RAW_1(D,X,val); \
- _FP_UNPACK_SEMIRAW(D,1,X); \
- } while (0)
-
-#define FP_UNPACK_SEMIRAW_DP(X,val) \
- do { \
- _FP_UNPACK_RAW_1_P(D,X,val); \
- _FP_UNPACK_SEMIRAW(D,1,X); \
- } while (0)
-
-#define FP_PACK_D(val,X) \
- do { \
- _FP_PACK_CANONICAL(D,1,X); \
- _FP_PACK_RAW_1(D,val,X); \
- } while (0)
-
-#define FP_PACK_DP(val,X) \
- do { \
- _FP_PACK_CANONICAL(D,1,X); \
- if (!FP_INHIBIT_RESULTS) \
- _FP_PACK_RAW_1_P(D,val,X); \
- } while (0)
-
-#define FP_PACK_SEMIRAW_D(val,X) \
- do { \
- _FP_PACK_SEMIRAW(D,1,X); \
- _FP_PACK_RAW_1(D,val,X); \
- } while (0)
-
-#define FP_PACK_SEMIRAW_DP(val,X) \
- do { \
- _FP_PACK_SEMIRAW(D,1,X); \
- if (!FP_INHIBIT_RESULTS) \
- _FP_PACK_RAW_1_P(D,val,X); \
- } while (0)
-
-#define FP_ISSIGNAN_D(X) _FP_ISSIGNAN(D,1,X)
-#define FP_NEG_D(R,X) _FP_NEG(D,1,R,X)
-#define FP_ADD_D(R,X,Y) _FP_ADD(D,1,R,X,Y)
-#define FP_SUB_D(R,X,Y) _FP_SUB(D,1,R,X,Y)
-#define FP_MUL_D(R,X,Y) _FP_MUL(D,1,R,X,Y)
-#define FP_DIV_D(R,X,Y) _FP_DIV(D,1,R,X,Y)
-#define FP_SQRT_D(R,X) _FP_SQRT(D,1,R,X)
-#define _FP_SQRT_MEAT_D(R,S,T,X,Q) _FP_SQRT_MEAT_1(R,S,T,X,Q)
+# define FP_DECL_D(X) _FP_DECL (1, X)
+# define FP_UNPACK_RAW_D(X, val) _FP_UNPACK_RAW_1 (D, X, val)
+# define FP_UNPACK_RAW_DP(X, val) _FP_UNPACK_RAW_1_P (D, X, val)
+# define FP_PACK_RAW_D(val, X) _FP_PACK_RAW_1 (D, val, X)
+# define FP_PACK_RAW_DP(val, X) \
+ do \
+ { \
+ if (!FP_INHIBIT_RESULTS) \
+ _FP_PACK_RAW_1_P (D, val, X); \
+ } \
+ while (0)
+
+# define FP_UNPACK_D(X, val) \
+ do \
+ { \
+ _FP_UNPACK_RAW_1 (D, X, val); \
+ _FP_UNPACK_CANONICAL (D, 1, X); \
+ } \
+ while (0)
+
+# define FP_UNPACK_DP(X, val) \
+ do \
+ { \
+ _FP_UNPACK_RAW_1_P (D, X, val); \
+ _FP_UNPACK_CANONICAL (D, 1, X); \
+ } \
+ while (0)
+
+# define FP_UNPACK_SEMIRAW_D(X, val) \
+ do \
+ { \
+ _FP_UNPACK_RAW_1 (D, X, val); \
+ _FP_UNPACK_SEMIRAW (D, 1, X); \
+ } \
+ while (0)
+
+# define FP_UNPACK_SEMIRAW_DP(X, val) \
+ do \
+ { \
+ _FP_UNPACK_RAW_1_P (D, X, val); \
+ _FP_UNPACK_SEMIRAW (D, 1, X); \
+ } \
+ while (0)
+
+# define FP_PACK_D(val, X) \
+ do \
+ { \
+ _FP_PACK_CANONICAL (D, 1, X); \
+ _FP_PACK_RAW_1 (D, val, X); \
+ } \
+ while (0)
+
+# define FP_PACK_DP(val, X) \
+ do \
+ { \
+ _FP_PACK_CANONICAL (D, 1, X); \
+ if (!FP_INHIBIT_RESULTS) \
+ _FP_PACK_RAW_1_P (D, val, X); \
+ } \
+ while (0)
+
+# define FP_PACK_SEMIRAW_D(val, X) \
+ do \
+ { \
+ _FP_PACK_SEMIRAW (D, 1, X); \
+ _FP_PACK_RAW_1 (D, val, X); \
+ } \
+ while (0)
+
+# define FP_PACK_SEMIRAW_DP(val, X) \
+ do \
+ { \
+ _FP_PACK_SEMIRAW (D, 1, X); \
+ if (!FP_INHIBIT_RESULTS) \
+ _FP_PACK_RAW_1_P (D, val, X); \
+ } \
+ while (0)
+
+# define FP_ISSIGNAN_D(X) _FP_ISSIGNAN (D, 1, X)
+# define FP_NEG_D(R, X) _FP_NEG (D, 1, R, X)
+# define FP_ADD_D(R, X, Y) _FP_ADD (D, 1, R, X, Y)
+# define FP_SUB_D(R, X, Y) _FP_SUB (D, 1, R, X, Y)
+# define FP_MUL_D(R, X, Y) _FP_MUL (D, 1, R, X, Y)
+# define FP_DIV_D(R, X, Y) _FP_DIV (D, 1, R, X, Y)
+# define FP_SQRT_D(R, X) _FP_SQRT (D, 1, R, X)
+# define _FP_SQRT_MEAT_D(R, S, T, X, Q) _FP_SQRT_MEAT_1 (R, S, T, X, Q)
+# define FP_FMA_D(R, X, Y, Z) _FP_FMA (D, 1, 2, R, X, Y, Z)
/* The implementation of _FP_MUL_D and _FP_DIV_D should be chosen by
the target machine. */
-#define FP_CMP_D(r,X,Y,un) _FP_CMP(D,1,r,X,Y,un)
-#define FP_CMP_EQ_D(r,X,Y) _FP_CMP_EQ(D,1,r,X,Y)
-#define FP_CMP_UNORD_D(r,X,Y) _FP_CMP_UNORD(D,1,r,X,Y)
+# define FP_CMP_D(r, X, Y, un) _FP_CMP (D, 1, r, X, Y, un)
+# define FP_CMP_EQ_D(r, X, Y) _FP_CMP_EQ (D, 1, r, X, Y)
+# define FP_CMP_UNORD_D(r, X, Y) _FP_CMP_UNORD (D, 1, r, X, Y)
+
+# define FP_TO_INT_D(r, X, rsz, rsg) _FP_TO_INT (D, 1, r, X, rsz, rsg)
+# define FP_FROM_INT_D(X, r, rs, rt) _FP_FROM_INT (D, 1, X, r, rs, rt)
-#define FP_TO_INT_D(r,X,rsz,rsg) _FP_TO_INT(D,1,r,X,rsz,rsg)
-#define FP_FROM_INT_D(X,r,rs,rt) _FP_FROM_INT(D,1,X,r,rs,rt)
+# define _FP_FRAC_HIGH_D(X) _FP_FRAC_HIGH_1 (X)
+# define _FP_FRAC_HIGH_RAW_D(X) _FP_FRAC_HIGH_1 (X)
-#define _FP_FRAC_HIGH_D(X) _FP_FRAC_HIGH_1(X)
-#define _FP_FRAC_HIGH_RAW_D(X) _FP_FRAC_HIGH_1(X)
+# define _FP_FRAC_HIGH_DW_D(X) _FP_FRAC_HIGH_2 (X)
#endif /* W_TYPE_SIZE < 64 */
diff --git a/libgcc/soft-fp/eqdf2.c b/libgcc/soft-fp/eqdf2.c
index c93c118f4e5..e8cfd7666a9 100644
--- a/libgcc/soft-fp/eqdf2.c
+++ b/libgcc/soft-fp/eqdf2.c
@@ -31,20 +31,23 @@
#include "soft-fp.h"
#include "double.h"
-CMPtype __eqdf2(DFtype a, DFtype b)
+CMPtype
+__eqdf2 (DFtype a, DFtype b)
{
FP_DECL_EX;
- FP_DECL_D(A); FP_DECL_D(B);
+ FP_DECL_D (A);
+ FP_DECL_D (B);
CMPtype r;
- FP_UNPACK_RAW_D(A, a);
- FP_UNPACK_RAW_D(B, b);
- FP_CMP_EQ_D(r, A, B);
- if (r && (FP_ISSIGNAN_D(A) || FP_ISSIGNAN_D(B)))
- FP_SET_EXCEPTION(FP_EX_INVALID);
+ FP_INIT_EXCEPTIONS;
+ FP_UNPACK_RAW_D (A, a);
+ FP_UNPACK_RAW_D (B, b);
+ FP_CMP_EQ_D (r, A, B);
+ if (r && (FP_ISSIGNAN_D (A) || FP_ISSIGNAN_D (B)))
+ FP_SET_EXCEPTION (FP_EX_INVALID);
FP_HANDLE_EXCEPTIONS;
return r;
}
-strong_alias(__eqdf2, __nedf2);
+strong_alias (__eqdf2, __nedf2);
diff --git a/libgcc/soft-fp/eqsf2.c b/libgcc/soft-fp/eqsf2.c
index e5b2a5f36aa..0bdb7fb2237 100644
--- a/libgcc/soft-fp/eqsf2.c
+++ b/libgcc/soft-fp/eqsf2.c
@@ -31,20 +31,23 @@
#include "soft-fp.h"
#include "single.h"
-CMPtype __eqsf2(SFtype a, SFtype b)
+CMPtype
+__eqsf2 (SFtype a, SFtype b)
{
FP_DECL_EX;
- FP_DECL_S(A); FP_DECL_S(B);
+ FP_DECL_S (A);
+ FP_DECL_S (B);
CMPtype r;
- FP_UNPACK_RAW_S(A, a);
- FP_UNPACK_RAW_S(B, b);
- FP_CMP_EQ_S(r, A, B);
- if (r && (FP_ISSIGNAN_S(A) || FP_ISSIGNAN_S(B)))
- FP_SET_EXCEPTION(FP_EX_INVALID);
+ FP_INIT_EXCEPTIONS;
+ FP_UNPACK_RAW_S (A, a);
+ FP_UNPACK_RAW_S (B, b);
+ FP_CMP_EQ_S (r, A, B);
+ if (r && (FP_ISSIGNAN_S (A) || FP_ISSIGNAN_S (B)))
+ FP_SET_EXCEPTION (FP_EX_INVALID);
FP_HANDLE_EXCEPTIONS;
return r;
}
-strong_alias(__eqsf2, __nesf2);
+strong_alias (__eqsf2, __nesf2);
diff --git a/libgcc/soft-fp/eqtf2.c b/libgcc/soft-fp/eqtf2.c
index 47b5d5cb618..edbc6f6832f 100644
--- a/libgcc/soft-fp/eqtf2.c
+++ b/libgcc/soft-fp/eqtf2.c
@@ -31,20 +31,23 @@
#include "soft-fp.h"
#include "quad.h"
-CMPtype __eqtf2(TFtype a, TFtype b)
+CMPtype
+__eqtf2 (TFtype a, TFtype b)
{
FP_DECL_EX;
- FP_DECL_Q(A); FP_DECL_Q(B);
+ FP_DECL_Q (A);
+ FP_DECL_Q (B);
CMPtype r;
- FP_UNPACK_RAW_Q(A, a);
- FP_UNPACK_RAW_Q(B, b);
- FP_CMP_EQ_Q(r, A, B);
- if (r && (FP_ISSIGNAN_Q(A) || FP_ISSIGNAN_Q(B)))
- FP_SET_EXCEPTION(FP_EX_INVALID);
+ FP_INIT_EXCEPTIONS;
+ FP_UNPACK_RAW_Q (A, a);
+ FP_UNPACK_RAW_Q (B, b);
+ FP_CMP_EQ_Q (r, A, B);
+ if (r && (FP_ISSIGNAN_Q (A) || FP_ISSIGNAN_Q (B)))
+ FP_SET_EXCEPTION (FP_EX_INVALID);
FP_HANDLE_EXCEPTIONS;
return r;
}
-strong_alias(__eqtf2, __netf2);
+strong_alias (__eqtf2, __netf2);
diff --git a/libgcc/soft-fp/extenddftf2.c b/libgcc/soft-fp/extenddftf2.c
index ff76a8cc2ff..2471fda9546 100644
--- a/libgcc/soft-fp/extenddftf2.c
+++ b/libgcc/soft-fp/extenddftf2.c
@@ -32,21 +32,22 @@
#include "double.h"
#include "quad.h"
-TFtype __extenddftf2(DFtype a)
+TFtype
+__extenddftf2 (DFtype a)
{
FP_DECL_EX;
- FP_DECL_D(A);
- FP_DECL_Q(R);
+ FP_DECL_D (A);
+ FP_DECL_Q (R);
TFtype r;
- FP_INIT_ROUNDMODE;
- FP_UNPACK_RAW_D(A, a);
+ FP_INIT_EXCEPTIONS;
+ FP_UNPACK_RAW_D (A, a);
#if (2 * _FP_W_TYPE_SIZE) < _FP_FRACBITS_Q
- FP_EXTEND(Q,D,4,2,R,A);
+ FP_EXTEND (Q, D, 4, 2, R, A);
#else
- FP_EXTEND(Q,D,2,1,R,A);
+ FP_EXTEND (Q, D, 2, 1, R, A);
#endif
- FP_PACK_RAW_Q(r, R);
+ FP_PACK_RAW_Q (r, R);
FP_HANDLE_EXCEPTIONS;
return r;
diff --git a/libgcc/soft-fp/extended.h b/libgcc/soft-fp/extended.h
index 74927550eb2..1189f7c7d2d 100644
--- a/libgcc/soft-fp/extended.h
+++ b/libgcc/soft-fp/extended.h
@@ -28,13 +28,15 @@
<http://www.gnu.org/licenses/>. */
#if _FP_W_TYPE_SIZE < 32
-#error "Here's a nickel, kid. Go buy yourself a real computer."
+# error "Here's a nickel, kid. Go buy yourself a real computer."
#endif
#if _FP_W_TYPE_SIZE < 64
-#define _FP_FRACTBITS_E (4*_FP_W_TYPE_SIZE)
+# define _FP_FRACTBITS_E (4*_FP_W_TYPE_SIZE)
+# define _FP_FRACTBITS_DW_E (8*_FP_W_TYPE_SIZE)
#else
-#define _FP_FRACTBITS_E (2*_FP_W_TYPE_SIZE)
+# define _FP_FRACTBITS_E (2*_FP_W_TYPE_SIZE)
+# define _FP_FRACTBITS_DW_E (4*_FP_W_TYPE_SIZE)
#endif
#define _FP_FRACBITS_E 64
@@ -46,152 +48,187 @@
#define _FP_EXPMAX_E 32767
#define _FP_QNANBIT_E \
- ((_FP_W_TYPE)1 << (_FP_FRACBITS_E-2) % _FP_W_TYPE_SIZE)
+ ((_FP_W_TYPE) 1 << (_FP_FRACBITS_E-2) % _FP_W_TYPE_SIZE)
#define _FP_QNANBIT_SH_E \
- ((_FP_W_TYPE)1 << (_FP_FRACBITS_E-2+_FP_WORKBITS) % _FP_W_TYPE_SIZE)
+ ((_FP_W_TYPE) 1 << (_FP_FRACBITS_E-2+_FP_WORKBITS) % _FP_W_TYPE_SIZE)
#define _FP_IMPLBIT_E \
- ((_FP_W_TYPE)1 << (_FP_FRACBITS_E-1) % _FP_W_TYPE_SIZE)
+ ((_FP_W_TYPE) 1 << (_FP_FRACBITS_E-1) % _FP_W_TYPE_SIZE)
#define _FP_IMPLBIT_SH_E \
- ((_FP_W_TYPE)1 << (_FP_FRACBITS_E-1+_FP_WORKBITS) % _FP_W_TYPE_SIZE)
+ ((_FP_W_TYPE) 1 << (_FP_FRACBITS_E-1+_FP_WORKBITS) % _FP_W_TYPE_SIZE)
#define _FP_OVERFLOW_E \
- ((_FP_W_TYPE)1 << (_FP_WFRACBITS_E % _FP_W_TYPE_SIZE))
+ ((_FP_W_TYPE) 1 << (_FP_WFRACBITS_E % _FP_W_TYPE_SIZE))
-typedef float XFtype __attribute__((mode(XF)));
+#define _FP_WFRACBITS_DW_E (2 * _FP_WFRACBITS_E)
+#define _FP_WFRACXBITS_DW_E (_FP_FRACTBITS_DW_E - _FP_WFRACBITS_DW_E)
+#define _FP_HIGHBIT_DW_E \
+ ((_FP_W_TYPE) 1 << (_FP_WFRACBITS_DW_E - 1) % _FP_W_TYPE_SIZE)
+
+typedef float XFtype __attribute__ ((mode (XF)));
#if _FP_W_TYPE_SIZE < 64
union _FP_UNION_E
{
- XFtype flt;
- struct _FP_STRUCT_LAYOUT
- {
-#if __BYTE_ORDER == __BIG_ENDIAN
- unsigned long pad1 : _FP_W_TYPE_SIZE;
- unsigned long pad2 : (_FP_W_TYPE_SIZE - 1 - _FP_EXPBITS_E);
- unsigned long sign : 1;
- unsigned long exp : _FP_EXPBITS_E;
- unsigned long frac1 : _FP_W_TYPE_SIZE;
- unsigned long frac0 : _FP_W_TYPE_SIZE;
-#else
- unsigned long frac0 : _FP_W_TYPE_SIZE;
- unsigned long frac1 : _FP_W_TYPE_SIZE;
- unsigned exp : _FP_EXPBITS_E;
- unsigned sign : 1;
-#endif /* not bigendian */
- } bits __attribute__((packed));
+ XFtype flt;
+ struct _FP_STRUCT_LAYOUT
+ {
+# if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned long pad1 : _FP_W_TYPE_SIZE;
+ unsigned long pad2 : (_FP_W_TYPE_SIZE - 1 - _FP_EXPBITS_E);
+ unsigned long sign : 1;
+ unsigned long exp : _FP_EXPBITS_E;
+ unsigned long frac1 : _FP_W_TYPE_SIZE;
+ unsigned long frac0 : _FP_W_TYPE_SIZE;
+# else
+ unsigned long frac0 : _FP_W_TYPE_SIZE;
+ unsigned long frac1 : _FP_W_TYPE_SIZE;
+ unsigned exp : _FP_EXPBITS_E;
+ unsigned sign : 1;
+# endif /* not bigendian */
+ } bits __attribute__ ((packed));
};
-#define FP_DECL_E(X) _FP_DECL(4,X)
-
-#define FP_UNPACK_RAW_E(X, val) \
- do { \
- union _FP_UNION_E _flo; _flo.flt = (val); \
- \
- X##_f[2] = 0; X##_f[3] = 0; \
- X##_f[0] = _flo.bits.frac0; \
- X##_f[1] = _flo.bits.frac1; \
- X##_e = _flo.bits.exp; \
- X##_s = _flo.bits.sign; \
- } while (0)
-
-#define FP_UNPACK_RAW_EP(X, val) \
- do { \
- union _FP_UNION_E *_flo = \
- (union _FP_UNION_E *)(val); \
- \
- X##_f[2] = 0; X##_f[3] = 0; \
- X##_f[0] = _flo->bits.frac0; \
- X##_f[1] = _flo->bits.frac1; \
- X##_e = _flo->bits.exp; \
- X##_s = _flo->bits.sign; \
- } while (0)
-
-#define FP_PACK_RAW_E(val, X) \
- do { \
- union _FP_UNION_E _flo; \
- \
- if (X##_e) X##_f[1] |= _FP_IMPLBIT_E; \
- else X##_f[1] &= ~(_FP_IMPLBIT_E); \
- _flo.bits.frac0 = X##_f[0]; \
- _flo.bits.frac1 = X##_f[1]; \
- _flo.bits.exp = X##_e; \
- _flo.bits.sign = X##_s; \
- \
- (val) = _flo.flt; \
- } while (0)
-
-#define FP_PACK_RAW_EP(val, X) \
- do { \
- if (!FP_INHIBIT_RESULTS) \
- { \
- union _FP_UNION_E *_flo = \
- (union _FP_UNION_E *)(val); \
- \
- if (X##_e) X##_f[1] |= _FP_IMPLBIT_E; \
- else X##_f[1] &= ~(_FP_IMPLBIT_E); \
- _flo->bits.frac0 = X##_f[0]; \
- _flo->bits.frac1 = X##_f[1]; \
- _flo->bits.exp = X##_e; \
- _flo->bits.sign = X##_s; \
- } \
- } while (0)
-
-#define FP_UNPACK_E(X,val) \
- do { \
- FP_UNPACK_RAW_E(X,val); \
- _FP_UNPACK_CANONICAL(E,4,X); \
- } while (0)
-
-#define FP_UNPACK_EP(X,val) \
- do { \
- FP_UNPACK_RAW_EP(X,val); \
- _FP_UNPACK_CANONICAL(E,4,X); \
- } while (0)
-
-#define FP_UNPACK_SEMIRAW_E(X,val) \
- do { \
- FP_UNPACK_RAW_E(X,val); \
- _FP_UNPACK_SEMIRAW(E,4,X); \
- } while (0)
-
-#define FP_UNPACK_SEMIRAW_EP(X,val) \
- do { \
- FP_UNPACK_RAW_EP(X,val); \
- _FP_UNPACK_SEMIRAW(E,4,X); \
- } while (0)
-
-#define FP_PACK_E(val,X) \
- do { \
- _FP_PACK_CANONICAL(E,4,X); \
- FP_PACK_RAW_E(val,X); \
- } while (0)
-
-#define FP_PACK_EP(val,X) \
- do { \
- _FP_PACK_CANONICAL(E,4,X); \
- FP_PACK_RAW_EP(val,X); \
- } while (0)
-
-#define FP_PACK_SEMIRAW_E(val,X) \
- do { \
- _FP_PACK_SEMIRAW(E,4,X); \
- FP_PACK_RAW_E(val,X); \
- } while (0)
-
-#define FP_PACK_SEMIRAW_EP(val,X) \
- do { \
- _FP_PACK_SEMIRAW(E,4,X); \
- FP_PACK_RAW_EP(val,X); \
- } while (0)
-
-#define FP_ISSIGNAN_E(X) _FP_ISSIGNAN(E,4,X)
-#define FP_NEG_E(R,X) _FP_NEG(E,4,R,X)
-#define FP_ADD_E(R,X,Y) _FP_ADD(E,4,R,X,Y)
-#define FP_SUB_E(R,X,Y) _FP_SUB(E,4,R,X,Y)
-#define FP_MUL_E(R,X,Y) _FP_MUL(E,4,R,X,Y)
-#define FP_DIV_E(R,X,Y) _FP_DIV(E,4,R,X,Y)
-#define FP_SQRT_E(R,X) _FP_SQRT(E,4,R,X)
+# define FP_DECL_E(X) _FP_DECL (4, X)
+
+# define FP_UNPACK_RAW_E(X, val) \
+ do \
+ { \
+ union _FP_UNION_E _flo; \
+ _flo.flt = (val); \
+ \
+ X##_f[2] = 0; \
+ X##_f[3] = 0; \
+ X##_f[0] = _flo.bits.frac0; \
+ X##_f[1] = _flo.bits.frac1; \
+ X##_e = _flo.bits.exp; \
+ X##_s = _flo.bits.sign; \
+ } \
+ while (0)
+
+# define FP_UNPACK_RAW_EP(X, val) \
+ do \
+ { \
+ union _FP_UNION_E *_flo = (union _FP_UNION_E *) (val); \
+ \
+ X##_f[2] = 0; \
+ X##_f[3] = 0; \
+ X##_f[0] = _flo->bits.frac0; \
+ X##_f[1] = _flo->bits.frac1; \
+ X##_e = _flo->bits.exp; \
+ X##_s = _flo->bits.sign; \
+ } \
+ while (0)
+
+# define FP_PACK_RAW_E(val, X) \
+ do \
+ { \
+ union _FP_UNION_E _flo; \
+ \
+ if (X##_e) \
+ X##_f[1] |= _FP_IMPLBIT_E; \
+ else \
+ X##_f[1] &= ~(_FP_IMPLBIT_E); \
+ _flo.bits.frac0 = X##_f[0]; \
+ _flo.bits.frac1 = X##_f[1]; \
+ _flo.bits.exp = X##_e; \
+ _flo.bits.sign = X##_s; \
+ \
+ (val) = _flo.flt; \
+ } \
+ while (0)
+
+# define FP_PACK_RAW_EP(val, X) \
+ do \
+ { \
+ if (!FP_INHIBIT_RESULTS) \
+ { \
+ union _FP_UNION_E *_flo = (union _FP_UNION_E *) (val); \
+ \
+ if (X##_e) \
+ X##_f[1] |= _FP_IMPLBIT_E; \
+ else \
+ X##_f[1] &= ~(_FP_IMPLBIT_E); \
+ _flo->bits.frac0 = X##_f[0]; \
+ _flo->bits.frac1 = X##_f[1]; \
+ _flo->bits.exp = X##_e; \
+ _flo->bits.sign = X##_s; \
+ } \
+ } \
+ while (0)
+
+# define FP_UNPACK_E(X, val) \
+ do \
+ { \
+ FP_UNPACK_RAW_E (X, val); \
+ _FP_UNPACK_CANONICAL (E, 4, X); \
+ } \
+ while (0)
+
+# define FP_UNPACK_EP(X, val) \
+ do \
+ { \
+ FP_UNPACK_RAW_EP (X, val); \
+ _FP_UNPACK_CANONICAL (E, 4, X); \
+ } \
+ while (0)
+
+# define FP_UNPACK_SEMIRAW_E(X, val) \
+ do \
+ { \
+ FP_UNPACK_RAW_E (X, val); \
+ _FP_UNPACK_SEMIRAW (E, 4, X); \
+ } \
+ while (0)
+
+# define FP_UNPACK_SEMIRAW_EP(X, val) \
+ do \
+ { \
+ FP_UNPACK_RAW_EP (X, val); \
+ _FP_UNPACK_SEMIRAW (E, 4, X); \
+ } \
+ while (0)
+
+# define FP_PACK_E(val, X) \
+ do \
+ { \
+ _FP_PACK_CANONICAL (E, 4, X); \
+ FP_PACK_RAW_E (val, X); \
+ } \
+ while (0)
+
+# define FP_PACK_EP(val, X) \
+ do \
+ { \
+ _FP_PACK_CANONICAL (E, 4, X); \
+ FP_PACK_RAW_EP (val, X); \
+ } \
+ while (0)
+
+# define FP_PACK_SEMIRAW_E(val, X) \
+ do \
+ { \
+ _FP_PACK_SEMIRAW (E, 4, X); \
+ FP_PACK_RAW_E (val, X); \
+ } \
+ while (0)
+
+# define FP_PACK_SEMIRAW_EP(val, X) \
+ do \
+ { \
+ _FP_PACK_SEMIRAW (E, 4, X); \
+ FP_PACK_RAW_EP (val, X); \
+ } \
+ while (0)
+
+# define FP_ISSIGNAN_E(X) _FP_ISSIGNAN (E, 4, X)
+# define FP_NEG_E(R, X) _FP_NEG (E, 4, R, X)
+# define FP_ADD_E(R, X, Y) _FP_ADD (E, 4, R, X, Y)
+# define FP_SUB_E(R, X, Y) _FP_SUB (E, 4, R, X, Y)
+# define FP_MUL_E(R, X, Y) _FP_MUL (E, 4, R, X, Y)
+# define FP_DIV_E(R, X, Y) _FP_DIV (E, 4, R, X, Y)
+# define FP_SQRT_E(R, X) _FP_SQRT (E, 4, R, X)
+# define FP_FMA_E(R, X, Y, Z) _FP_FMA (E, 4, 8, R, X, Y, Z)
/*
* Square root algorithms:
@@ -204,185 +241,218 @@ union _FP_UNION_E
* in two UWtype registers instead of four.
*/
-#define _FP_SQRT_MEAT_E(R, S, T, X, q) \
- do { \
- q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1); \
- _FP_FRAC_SRL_4(X, (_FP_WORKBITS)); \
- while (q) \
- { \
- T##_f[1] = S##_f[1] + q; \
- if (T##_f[1] <= X##_f[1]) \
- { \
- S##_f[1] = T##_f[1] + q; \
- X##_f[1] -= T##_f[1]; \
- R##_f[1] += q; \
- } \
- _FP_FRAC_SLL_2(X, 1); \
- q >>= 1; \
- } \
- q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1); \
- while (q) \
- { \
- T##_f[0] = S##_f[0] + q; \
- T##_f[1] = S##_f[1]; \
- if (T##_f[1] < X##_f[1] || \
- (T##_f[1] == X##_f[1] && \
- T##_f[0] <= X##_f[0])) \
- { \
- S##_f[0] = T##_f[0] + q; \
- S##_f[1] += (T##_f[0] > S##_f[0]); \
- _FP_FRAC_DEC_2(X, T); \
- R##_f[0] += q; \
- } \
- _FP_FRAC_SLL_2(X, 1); \
- q >>= 1; \
- } \
- _FP_FRAC_SLL_4(R, (_FP_WORKBITS)); \
- if (X##_f[0] | X##_f[1]) \
- { \
- if (S##_f[1] < X##_f[1] || \
- (S##_f[1] == X##_f[1] && \
- S##_f[0] < X##_f[0])) \
- R##_f[0] |= _FP_WORK_ROUND; \
- R##_f[0] |= _FP_WORK_STICKY; \
- } \
- } while (0)
-
-#define FP_CMP_E(r,X,Y,un) _FP_CMP(E,4,r,X,Y,un)
-#define FP_CMP_EQ_E(r,X,Y) _FP_CMP_EQ(E,4,r,X,Y)
-#define FP_CMP_UNORD_E(r,X,Y) _FP_CMP_UNORD(E,4,r,X,Y)
-
-#define FP_TO_INT_E(r,X,rsz,rsg) _FP_TO_INT(E,4,r,X,rsz,rsg)
-#define FP_FROM_INT_E(X,r,rs,rt) _FP_FROM_INT(E,4,X,r,rs,rt)
-
-#define _FP_FRAC_HIGH_E(X) (X##_f[2])
-#define _FP_FRAC_HIGH_RAW_E(X) (X##_f[1])
+# define _FP_SQRT_MEAT_E(R, S, T, X, q) \
+ do \
+ { \
+ q = (_FP_W_TYPE) 1 << (_FP_W_TYPE_SIZE - 1); \
+ _FP_FRAC_SRL_4 (X, (_FP_WORKBITS)); \
+ while (q) \
+ { \
+ T##_f[1] = S##_f[1] + q; \
+ if (T##_f[1] <= X##_f[1]) \
+ { \
+ S##_f[1] = T##_f[1] + q; \
+ X##_f[1] -= T##_f[1]; \
+ R##_f[1] += q; \
+ } \
+ _FP_FRAC_SLL_2 (X, 1); \
+ q >>= 1; \
+ } \
+ q = (_FP_W_TYPE) 1 << (_FP_W_TYPE_SIZE - 1); \
+ while (q) \
+ { \
+ T##_f[0] = S##_f[0] + q; \
+ T##_f[1] = S##_f[1]; \
+ if (T##_f[1] < X##_f[1] \
+ || (T##_f[1] == X##_f[1] \
+ && T##_f[0] <= X##_f[0])) \
+ { \
+ S##_f[0] = T##_f[0] + q; \
+ S##_f[1] += (T##_f[0] > S##_f[0]); \
+ _FP_FRAC_DEC_2 (X, T); \
+ R##_f[0] += q; \
+ } \
+ _FP_FRAC_SLL_2 (X, 1); \
+ q >>= 1; \
+ } \
+ _FP_FRAC_SLL_4 (R, (_FP_WORKBITS)); \
+ if (X##_f[0] | X##_f[1]) \
+ { \
+ if (S##_f[1] < X##_f[1] \
+ || (S##_f[1] == X##_f[1] \
+ && S##_f[0] < X##_f[0])) \
+ R##_f[0] |= _FP_WORK_ROUND; \
+ R##_f[0] |= _FP_WORK_STICKY; \
+ } \
+ } \
+ while (0)
+
+# define FP_CMP_E(r, X, Y, un) _FP_CMP (E, 4, r, X, Y, un)
+# define FP_CMP_EQ_E(r, X, Y) _FP_CMP_EQ (E, 4, r, X, Y)
+# define FP_CMP_UNORD_E(r, X, Y) _FP_CMP_UNORD (E, 4, r, X, Y)
+
+# define FP_TO_INT_E(r, X, rsz, rsg) _FP_TO_INT (E, 4, r, X, rsz, rsg)
+# define FP_FROM_INT_E(X, r, rs, rt) _FP_FROM_INT (E, 4, X, r, rs, rt)
+
+# define _FP_FRAC_HIGH_E(X) (X##_f[2])
+# define _FP_FRAC_HIGH_RAW_E(X) (X##_f[1])
+
+# define _FP_FRAC_HIGH_DW_E(X) (X##_f[4])
#else /* not _FP_W_TYPE_SIZE < 64 */
union _FP_UNION_E
{
XFtype flt;
- struct _FP_STRUCT_LAYOUT {
-#if __BYTE_ORDER == __BIG_ENDIAN
+ struct _FP_STRUCT_LAYOUT
+ {
+# if __BYTE_ORDER == __BIG_ENDIAN
_FP_W_TYPE pad : (_FP_W_TYPE_SIZE - 1 - _FP_EXPBITS_E);
unsigned sign : 1;
unsigned exp : _FP_EXPBITS_E;
_FP_W_TYPE frac : _FP_W_TYPE_SIZE;
-#else
+# else
_FP_W_TYPE frac : _FP_W_TYPE_SIZE;
unsigned exp : _FP_EXPBITS_E;
unsigned sign : 1;
-#endif
+# endif
} bits;
};
-#define FP_DECL_E(X) _FP_DECL(2,X)
-
-#define FP_UNPACK_RAW_E(X, val) \
- do { \
- union _FP_UNION_E _flo; _flo.flt = (val); \
- \
- X##_f0 = _flo.bits.frac; \
- X##_f1 = 0; \
- X##_e = _flo.bits.exp; \
- X##_s = _flo.bits.sign; \
- } while (0)
-
-#define FP_UNPACK_RAW_EP(X, val) \
- do { \
- union _FP_UNION_E *_flo = \
- (union _FP_UNION_E *)(val); \
- \
- X##_f0 = _flo->bits.frac; \
- X##_f1 = 0; \
- X##_e = _flo->bits.exp; \
- X##_s = _flo->bits.sign; \
- } while (0)
-
-#define FP_PACK_RAW_E(val, X) \
- do { \
- union _FP_UNION_E _flo; \
- \
- if (X##_e) X##_f0 |= _FP_IMPLBIT_E; \
- else X##_f0 &= ~(_FP_IMPLBIT_E); \
- _flo.bits.frac = X##_f0; \
- _flo.bits.exp = X##_e; \
- _flo.bits.sign = X##_s; \
- \
- (val) = _flo.flt; \
- } while (0)
-
-#define FP_PACK_RAW_EP(fs, val, X) \
- do { \
- if (!FP_INHIBIT_RESULTS) \
- { \
- union _FP_UNION_E *_flo = \
- (union _FP_UNION_E *)(val); \
+# define FP_DECL_E(X) _FP_DECL (2, X)
+
+# define FP_UNPACK_RAW_E(X, val) \
+ do \
+ { \
+ union _FP_UNION_E _flo; \
+ _flo.flt = (val); \
+ \
+ X##_f0 = _flo.bits.frac; \
+ X##_f1 = 0; \
+ X##_e = _flo.bits.exp; \
+ X##_s = _flo.bits.sign; \
+ } \
+ while (0)
+
+# define FP_UNPACK_RAW_EP(X, val) \
+ do \
+ { \
+ union _FP_UNION_E *_flo = (union _FP_UNION_E *) (val); \
\
- if (X##_e) X##_f0 |= _FP_IMPLBIT_E; \
- else X##_f0 &= ~(_FP_IMPLBIT_E); \
- _flo->bits.frac = X##_f0; \
- _flo->bits.exp = X##_e; \
- _flo->bits.sign = X##_s; \
- } \
- } while (0)
-
-
-#define FP_UNPACK_E(X,val) \
- do { \
- FP_UNPACK_RAW_E(X,val); \
- _FP_UNPACK_CANONICAL(E,2,X); \
- } while (0)
-
-#define FP_UNPACK_EP(X,val) \
- do { \
- FP_UNPACK_RAW_EP(X,val); \
- _FP_UNPACK_CANONICAL(E,2,X); \
- } while (0)
-
-#define FP_UNPACK_SEMIRAW_E(X,val) \
- do { \
- FP_UNPACK_RAW_E(X,val); \
- _FP_UNPACK_SEMIRAW(E,2,X); \
- } while (0)
-
-#define FP_UNPACK_SEMIRAW_EP(X,val) \
- do { \
- FP_UNPACK_RAW_EP(X,val); \
- _FP_UNPACK_SEMIRAW(E,2,X); \
- } while (0)
-
-#define FP_PACK_E(val,X) \
- do { \
- _FP_PACK_CANONICAL(E,2,X); \
- FP_PACK_RAW_E(val,X); \
- } while (0)
-
-#define FP_PACK_EP(val,X) \
- do { \
- _FP_PACK_CANONICAL(E,2,X); \
- FP_PACK_RAW_EP(val,X); \
- } while (0)
-
-#define FP_PACK_SEMIRAW_E(val,X) \
- do { \
- _FP_PACK_SEMIRAW(E,2,X); \
- FP_PACK_RAW_E(val,X); \
- } while (0)
-
-#define FP_PACK_SEMIRAW_EP(val,X) \
- do { \
- _FP_PACK_SEMIRAW(E,2,X); \
- FP_PACK_RAW_EP(val,X); \
- } while (0)
-
-#define FP_ISSIGNAN_E(X) _FP_ISSIGNAN(E,2,X)
-#define FP_NEG_E(R,X) _FP_NEG(E,2,R,X)
-#define FP_ADD_E(R,X,Y) _FP_ADD(E,2,R,X,Y)
-#define FP_SUB_E(R,X,Y) _FP_SUB(E,2,R,X,Y)
-#define FP_MUL_E(R,X,Y) _FP_MUL(E,2,R,X,Y)
-#define FP_DIV_E(R,X,Y) _FP_DIV(E,2,R,X,Y)
-#define FP_SQRT_E(R,X) _FP_SQRT(E,2,R,X)
+ X##_f0 = _flo->bits.frac; \
+ X##_f1 = 0; \
+ X##_e = _flo->bits.exp; \
+ X##_s = _flo->bits.sign; \
+ } \
+ while (0)
+
+# define FP_PACK_RAW_E(val, X) \
+ do \
+ { \
+ union _FP_UNION_E _flo; \
+ \
+ if (X##_e) \
+ X##_f0 |= _FP_IMPLBIT_E; \
+ else \
+ X##_f0 &= ~(_FP_IMPLBIT_E); \
+ _flo.bits.frac = X##_f0; \
+ _flo.bits.exp = X##_e; \
+ _flo.bits.sign = X##_s; \
+ \
+ (val) = _flo.flt; \
+ } \
+ while (0)
+
+# define FP_PACK_RAW_EP(fs, val, X) \
+ do \
+ { \
+ if (!FP_INHIBIT_RESULTS) \
+ { \
+ union _FP_UNION_E *_flo = (union _FP_UNION_E *) (val); \
+ \
+ if (X##_e) \
+ X##_f0 |= _FP_IMPLBIT_E; \
+ else \
+ X##_f0 &= ~(_FP_IMPLBIT_E); \
+ _flo->bits.frac = X##_f0; \
+ _flo->bits.exp = X##_e; \
+ _flo->bits.sign = X##_s; \
+ } \
+ } \
+ while (0)
+
+
+# define FP_UNPACK_E(X, val) \
+ do \
+ { \
+ FP_UNPACK_RAW_E (X, val); \
+ _FP_UNPACK_CANONICAL (E, 2, X); \
+ } \
+ while (0)
+
+# define FP_UNPACK_EP(X, val) \
+ do \
+ { \
+ FP_UNPACK_RAW_EP (X, val); \
+ _FP_UNPACK_CANONICAL (E, 2, X); \
+ } \
+ while (0)
+
+# define FP_UNPACK_SEMIRAW_E(X, val) \
+ do \
+ { \
+ FP_UNPACK_RAW_E (X, val); \
+ _FP_UNPACK_SEMIRAW (E, 2, X); \
+ } \
+ while (0)
+
+# define FP_UNPACK_SEMIRAW_EP(X, val) \
+ do \
+ { \
+ FP_UNPACK_RAW_EP (X, val); \
+ _FP_UNPACK_SEMIRAW (E, 2, X); \
+ } \
+ while (0)
+
+# define FP_PACK_E(val, X) \
+ do \
+ { \
+ _FP_PACK_CANONICAL (E, 2, X); \
+ FP_PACK_RAW_E (val, X); \
+ } \
+ while (0)
+
+# define FP_PACK_EP(val, X) \
+ do \
+ { \
+ _FP_PACK_CANONICAL (E, 2, X); \
+ FP_PACK_RAW_EP (val, X); \
+ } \
+ while (0)
+
+# define FP_PACK_SEMIRAW_E(val, X) \
+ do \
+ { \
+ _FP_PACK_SEMIRAW (E, 2, X); \
+ FP_PACK_RAW_E (val, X); \
+ } \
+ while (0)
+
+# define FP_PACK_SEMIRAW_EP(val, X) \
+ do \
+ { \
+ _FP_PACK_SEMIRAW (E, 2, X); \
+ FP_PACK_RAW_EP (val, X); \
+ } \
+ while (0)
+
+# define FP_ISSIGNAN_E(X) _FP_ISSIGNAN (E, 2, X)
+# define FP_NEG_E(R, X) _FP_NEG (E, 2, R, X)
+# define FP_ADD_E(R, X, Y) _FP_ADD (E, 2, R, X, Y)
+# define FP_SUB_E(R, X, Y) _FP_SUB (E, 2, R, X, Y)
+# define FP_MUL_E(R, X, Y) _FP_MUL (E, 2, R, X, Y)
+# define FP_DIV_E(R, X, Y) _FP_DIV (E, 2, R, X, Y)
+# define FP_SQRT_E(R, X) _FP_SQRT (E, 2, R, X)
+# define FP_FMA_E(R, X, Y, Z) _FP_FMA (E, 2, 4, R, X, Y, Z)
/*
* Square root algorithms:
@@ -392,39 +462,43 @@ union _FP_UNION_E
* in one UWtype registers instead of two, although we don't
* have to.
*/
-#define _FP_SQRT_MEAT_E(R, S, T, X, q) \
- do { \
- q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1); \
- _FP_FRAC_SRL_2(X, (_FP_WORKBITS)); \
- while (q) \
- { \
- T##_f0 = S##_f0 + q; \
- if (T##_f0 <= X##_f0) \
- { \
- S##_f0 = T##_f0 + q; \
- X##_f0 -= T##_f0; \
- R##_f0 += q; \
- } \
- _FP_FRAC_SLL_1(X, 1); \
- q >>= 1; \
- } \
- _FP_FRAC_SLL_2(R, (_FP_WORKBITS)); \
- if (X##_f0) \
- { \
- if (S##_f0 < X##_f0) \
- R##_f0 |= _FP_WORK_ROUND; \
- R##_f0 |= _FP_WORK_STICKY; \
- } \
- } while (0)
-
-#define FP_CMP_E(r,X,Y,un) _FP_CMP(E,2,r,X,Y,un)
-#define FP_CMP_EQ_E(r,X,Y) _FP_CMP_EQ(E,2,r,X,Y)
-#define FP_CMP_UNORD_E(r,X,Y) _FP_CMP_UNORD(E,2,r,X,Y)
-
-#define FP_TO_INT_E(r,X,rsz,rsg) _FP_TO_INT(E,2,r,X,rsz,rsg)
-#define FP_FROM_INT_E(X,r,rs,rt) _FP_FROM_INT(E,2,X,r,rs,rt)
-
-#define _FP_FRAC_HIGH_E(X) (X##_f1)
-#define _FP_FRAC_HIGH_RAW_E(X) (X##_f0)
+# define _FP_SQRT_MEAT_E(R, S, T, X, q) \
+ do \
+ { \
+ q = (_FP_W_TYPE) 1 << (_FP_W_TYPE_SIZE - 1); \
+ _FP_FRAC_SRL_2 (X, (_FP_WORKBITS)); \
+ while (q) \
+ { \
+ T##_f0 = S##_f0 + q; \
+ if (T##_f0 <= X##_f0) \
+ { \
+ S##_f0 = T##_f0 + q; \
+ X##_f0 -= T##_f0; \
+ R##_f0 += q; \
+ } \
+ _FP_FRAC_SLL_1 (X, 1); \
+ q >>= 1; \
+ } \
+ _FP_FRAC_SLL_2 (R, (_FP_WORKBITS)); \
+ if (X##_f0) \
+ { \
+ if (S##_f0 < X##_f0) \
+ R##_f0 |= _FP_WORK_ROUND; \
+ R##_f0 |= _FP_WORK_STICKY; \
+ } \
+ } \
+ while (0)
+
+# define FP_CMP_E(r, X, Y, un) _FP_CMP (E, 2, r, X, Y, un)
+# define FP_CMP_EQ_E(r, X, Y) _FP_CMP_EQ (E, 2, r, X, Y)
+# define FP_CMP_UNORD_E(r, X, Y) _FP_CMP_UNORD (E, 2, r, X, Y)
+
+# define FP_TO_INT_E(r, X, rsz, rsg) _FP_TO_INT (E, 2, r, X, rsz, rsg)
+# define FP_FROM_INT_E(X, r, rs, rt) _FP_FROM_INT (E, 2, X, r, rs, rt)
+
+# define _FP_FRAC_HIGH_E(X) (X##_f1)
+# define _FP_FRAC_HIGH_RAW_E(X) (X##_f0)
+
+# define _FP_FRAC_HIGH_DW_E(X) (X##_f[2])
#endif /* not _FP_W_TYPE_SIZE < 64 */
diff --git a/libgcc/soft-fp/extendsfdf2.c b/libgcc/soft-fp/extendsfdf2.c
index 7fc4046f8ae..2276de527f0 100644
--- a/libgcc/soft-fp/extendsfdf2.c
+++ b/libgcc/soft-fp/extendsfdf2.c
@@ -32,21 +32,22 @@
#include "single.h"
#include "double.h"
-DFtype __extendsfdf2(SFtype a)
+DFtype
+__extendsfdf2 (SFtype a)
{
FP_DECL_EX;
- FP_DECL_S(A);
- FP_DECL_D(R);
+ FP_DECL_S (A);
+ FP_DECL_D (R);
DFtype r;
- FP_INIT_ROUNDMODE;
- FP_UNPACK_RAW_S(A, a);
+ FP_INIT_EXCEPTIONS;
+ FP_UNPACK_RAW_S (A, a);
#if _FP_W_TYPE_SIZE < _FP_FRACBITS_D
- FP_EXTEND(D,S,2,1,R,A);
+ FP_EXTEND (D, S, 2, 1, R, A);
#else
- FP_EXTEND(D,S,1,1,R,A);
+ FP_EXTEND (D, S, 1, 1, R, A);
#endif
- FP_PACK_RAW_D(r, R);
+ FP_PACK_RAW_D (r, R);
FP_HANDLE_EXCEPTIONS;
return r;
diff --git a/libgcc/soft-fp/extendsftf2.c b/libgcc/soft-fp/extendsftf2.c
index 8271a88466b..51f60c45698 100644
--- a/libgcc/soft-fp/extendsftf2.c
+++ b/libgcc/soft-fp/extendsftf2.c
@@ -32,21 +32,22 @@
#include "single.h"
#include "quad.h"
-TFtype __extendsftf2(SFtype a)
+TFtype
+__extendsftf2 (SFtype a)
{
FP_DECL_EX;
- FP_DECL_S(A);
- FP_DECL_Q(R);
+ FP_DECL_S (A);
+ FP_DECL_Q (R);
TFtype r;
- FP_INIT_ROUNDMODE;
- FP_UNPACK_RAW_S(A, a);
+ FP_INIT_EXCEPTIONS;
+ FP_UNPACK_RAW_S (A, a);
#if (2 * _FP_W_TYPE_SIZE) < _FP_FRACBITS_Q
- FP_EXTEND(Q,S,4,1,R,A);
+ FP_EXTEND (Q, S, 4, 1, R, A);
#else
- FP_EXTEND(Q,S,2,1,R,A);
+ FP_EXTEND (Q, S, 2, 1, R, A);
#endif
- FP_PACK_RAW_Q(r, R);
+ FP_PACK_RAW_Q (r, R);
FP_HANDLE_EXCEPTIONS;
return r;
diff --git a/libgcc/soft-fp/extendxftf2.c b/libgcc/soft-fp/extendxftf2.c
index af29a2ae9cc..684052d8744 100644
--- a/libgcc/soft-fp/extendxftf2.c
+++ b/libgcc/soft-fp/extendxftf2.c
@@ -1,6 +1,6 @@
/* Software floating-point emulation.
Return a converted to IEEE quad
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007-2013 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Uros Bizjak (ubizjak@gmail.com).
@@ -24,29 +24,29 @@
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
- MA 02110-1301, USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
#include "soft-fp.h"
#include "extended.h"
#include "quad.h"
-TFtype __extendxftf2(XFtype a)
+TFtype
+__extendxftf2 (XFtype a)
{
FP_DECL_EX;
- FP_DECL_E(A);
- FP_DECL_Q(R);
+ FP_DECL_E (A);
+ FP_DECL_Q (R);
TFtype r;
FP_INIT_ROUNDMODE;
- FP_UNPACK_RAW_E(A, a);
+ FP_UNPACK_RAW_E (A, a);
#if (2 * _FP_W_TYPE_SIZE) < _FP_FRACBITS_Q
- FP_EXTEND(Q,E,4,4,R,A);
+ FP_EXTEND (Q, E, 4, 4, R, A);
#else
- FP_EXTEND(Q,E,2,2,R,A);
+ FP_EXTEND (Q, E, 2, 2, R, A);
#endif
- FP_PACK_RAW_Q(r, R);
+ FP_PACK_RAW_Q (r, R);
FP_HANDLE_EXCEPTIONS;
return r;
diff --git a/libgcc/soft-fp/fixdfdi.c b/libgcc/soft-fp/fixdfdi.c
index 71ce1d4d71c..7b926b3d692 100644
--- a/libgcc/soft-fp/fixdfdi.c
+++ b/libgcc/soft-fp/fixdfdi.c
@@ -31,14 +31,16 @@
#include "soft-fp.h"
#include "double.h"
-DItype __fixdfdi(DFtype a)
+DItype
+__fixdfdi (DFtype a)
{
FP_DECL_EX;
- FP_DECL_D(A);
+ FP_DECL_D (A);
UDItype r;
- FP_UNPACK_RAW_D(A, a);
- FP_TO_INT_D(r, A, DI_BITS, 1);
+ FP_INIT_EXCEPTIONS;
+ FP_UNPACK_RAW_D (A, a);
+ FP_TO_INT_D (r, A, DI_BITS, 1);
FP_HANDLE_EXCEPTIONS;
return r;
diff --git a/libgcc/soft-fp/fixdfsi.c b/libgcc/soft-fp/fixdfsi.c
index f0c9960644b..79b2d215059 100644
--- a/libgcc/soft-fp/fixdfsi.c
+++ b/libgcc/soft-fp/fixdfsi.c
@@ -31,14 +31,16 @@
#include "soft-fp.h"
#include "double.h"
-SItype __fixdfsi(DFtype a)
+SItype
+__fixdfsi (DFtype a)
{
FP_DECL_EX;
- FP_DECL_D(A);
+ FP_DECL_D (A);
USItype r;
- FP_UNPACK_RAW_D(A, a);
- FP_TO_INT_D(r, A, SI_BITS, 1);
+ FP_INIT_EXCEPTIONS;
+ FP_UNPACK_RAW_D (A, a);
+ FP_TO_INT_D (r, A, SI_BITS, 1);
FP_HANDLE_EXCEPTIONS;
return r;
diff --git a/libgcc/soft-fp/fixdfti.c b/libgcc/soft-fp/fixdfti.c
index 473165725e1..b5fe4f99fc1 100644
--- a/libgcc/soft-fp/fixdfti.c
+++ b/libgcc/soft-fp/fixdfti.c
@@ -1,6 +1,6 @@
/* Software floating-point emulation.
Convert IEEE double to 128bit signed integer
- Copyright (C) 2007, 2008 Free Software Foundation, Inc.
+ Copyright (C) 2007-2013 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Uros Bizjak (ubizjak@gmail.com).
@@ -24,21 +24,22 @@
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
- MA 02110-1301, USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
#include "soft-fp.h"
#include "double.h"
-TItype __fixdfti(DFtype a)
+TItype
+__fixdfti (DFtype a)
{
FP_DECL_EX;
- FP_DECL_D(A);
+ FP_DECL_D (A);
UTItype r;
- FP_UNPACK_RAW_D(A, a);
- FP_TO_INT_D(r, A, TI_BITS, 1);
+ FP_INIT_EXCEPTIONS;
+ FP_UNPACK_RAW_D (A, a);
+ FP_TO_INT_D (r, A, TI_BITS, 1);
FP_HANDLE_EXCEPTIONS;
return r;
diff --git a/libgcc/soft-fp/fixsfdi.c b/libgcc/soft-fp/fixsfdi.c
index 5f69d6a2885..df6b9c728a2 100644
--- a/libgcc/soft-fp/fixsfdi.c
+++ b/libgcc/soft-fp/fixsfdi.c
@@ -31,14 +31,16 @@
#include "soft-fp.h"
#include "single.h"
-DItype __fixsfdi(SFtype a)
+DItype
+__fixsfdi (SFtype a)
{
FP_DECL_EX;
- FP_DECL_S(A);
+ FP_DECL_S (A);
UDItype r;
- FP_UNPACK_RAW_S(A, a);
- FP_TO_INT_S(r, A, DI_BITS, 1);
+ FP_INIT_EXCEPTIONS;
+ FP_UNPACK_RAW_S (A, a);
+ FP_TO_INT_S (r, A, DI_BITS, 1);
FP_HANDLE_EXCEPTIONS;
return r;
diff --git a/libgcc/soft-fp/fixsfsi.c b/libgcc/soft-fp/fixsfsi.c
index 6fffdd73782..4c0bfd39db1 100644
--- a/libgcc/soft-fp/fixsfsi.c
+++ b/libgcc/soft-fp/fixsfsi.c
@@ -31,14 +31,16 @@
#include "soft-fp.h"
#include "single.h"
-SItype __fixsfsi(SFtype a)
+SItype
+__fixsfsi (SFtype a)
{
FP_DECL_EX;
- FP_DECL_S(A);
+ FP_DECL_S (A);
USItype r;
- FP_UNPACK_RAW_S(A, a);
- FP_TO_INT_S(r, A, SI_BITS, 1);
+ FP_INIT_EXCEPTIONS;
+ FP_UNPACK_RAW_S (A, a);
+ FP_TO_INT_S (r, A, SI_BITS, 1);
FP_HANDLE_EXCEPTIONS;
return r;
diff --git a/libgcc/soft-fp/fixsfti.c b/libgcc/soft-fp/fixsfti.c
index 779628eb403..6b5229fe91a 100644
--- a/libgcc/soft-fp/fixsfti.c
+++ b/libgcc/soft-fp/fixsfti.c
@@ -1,6 +1,6 @@
/* Software floating-point emulation.
Convert IEEE single to 128bit signed integer
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007-2013 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Uros Bizjak (ubizjak@gmail.com).
@@ -24,21 +24,22 @@
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
- MA 02110-1301, USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
#include "soft-fp.h"
#include "single.h"
-TItype __fixsfti(SFtype a)
+TItype
+__fixsfti (SFtype a)
{
FP_DECL_EX;
- FP_DECL_S(A);
+ FP_DECL_S (A);
UTItype r;
- FP_UNPACK_RAW_S(A, a);
- FP_TO_INT_S(r, A, TI_BITS, 1);
+ FP_INIT_EXCEPTIONS;
+ FP_UNPACK_RAW_S (A, a);
+ FP_TO_INT_S (r, A, TI_BITS, 1);
FP_HANDLE_EXCEPTIONS;
return r;
diff --git a/libgcc/soft-fp/fixtfdi.c b/libgcc/soft-fp/fixtfdi.c
index ac67bfbd3c0..a65173aa781 100644
--- a/libgcc/soft-fp/fixtfdi.c
+++ b/libgcc/soft-fp/fixtfdi.c
@@ -31,14 +31,16 @@
#include "soft-fp.h"
#include "quad.h"
-DItype __fixtfdi(TFtype a)
+DItype
+__fixtfdi (TFtype a)
{
FP_DECL_EX;
- FP_DECL_Q(A);
+ FP_DECL_Q (A);
UDItype r;
- FP_UNPACK_RAW_Q(A, a);
- FP_TO_INT_Q(r, A, DI_BITS, 1);
+ FP_INIT_EXCEPTIONS;
+ FP_UNPACK_RAW_Q (A, a);
+ FP_TO_INT_Q (r, A, DI_BITS, 1);
FP_HANDLE_EXCEPTIONS;
return r;
diff --git a/libgcc/soft-fp/fixtfsi.c b/libgcc/soft-fp/fixtfsi.c
index 8f27ff66f0e..bc0ea0b87d2 100644
--- a/libgcc/soft-fp/fixtfsi.c
+++ b/libgcc/soft-fp/fixtfsi.c
@@ -31,14 +31,16 @@
#include "soft-fp.h"
#include "quad.h"
-SItype __fixtfsi(TFtype a)
+SItype
+__fixtfsi (TFtype a)
{
FP_DECL_EX;
- FP_DECL_Q(A);
+ FP_DECL_Q (A);
USItype r;
- FP_UNPACK_RAW_Q(A, a);
- FP_TO_INT_Q(r, A, SI_BITS, 1);
+ FP_INIT_EXCEPTIONS;
+ FP_UNPACK_RAW_Q (A, a);
+ FP_TO_INT_Q (r, A, SI_BITS, 1);
FP_HANDLE_EXCEPTIONS;
return r;
diff --git a/libgcc/soft-fp/fixtfti.c b/libgcc/soft-fp/fixtfti.c
index 8311ea5a72c..573ca0ed11b 100644
--- a/libgcc/soft-fp/fixtfti.c
+++ b/libgcc/soft-fp/fixtfti.c
@@ -1,6 +1,6 @@
/* Software floating-point emulation.
Convert IEEE quad to 128bit signed integer
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007-2013 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Uros Bizjak (ubizjak@gmail.com).
@@ -24,21 +24,22 @@
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
- MA 02110-1301, USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
#include "soft-fp.h"
#include "quad.h"
-TItype __fixtfti(TFtype a)
+TItype
+__fixtfti (TFtype a)
{
FP_DECL_EX;
- FP_DECL_Q(A);
+ FP_DECL_Q (A);
UTItype r;
- FP_UNPACK_RAW_Q(A, a);
- FP_TO_INT_Q(r, A, TI_BITS, 1);
+ FP_INIT_EXCEPTIONS;
+ FP_UNPACK_RAW_Q (A, a);
+ FP_TO_INT_Q (r, A, TI_BITS, 1);
FP_HANDLE_EXCEPTIONS;
return r;
diff --git a/libgcc/soft-fp/fixunsdfdi.c b/libgcc/soft-fp/fixunsdfdi.c
index 82fe1c75380..8831cc3d19f 100644
--- a/libgcc/soft-fp/fixunsdfdi.c
+++ b/libgcc/soft-fp/fixunsdfdi.c
@@ -31,14 +31,16 @@
#include "soft-fp.h"
#include "double.h"
-UDItype __fixunsdfdi(DFtype a)
+UDItype
+__fixunsdfdi (DFtype a)
{
FP_DECL_EX;
- FP_DECL_D(A);
+ FP_DECL_D (A);
UDItype r;
- FP_UNPACK_RAW_D(A, a);
- FP_TO_INT_D(r, A, DI_BITS, 0);
+ FP_INIT_EXCEPTIONS;
+ FP_UNPACK_RAW_D (A, a);
+ FP_TO_INT_D (r, A, DI_BITS, 0);
FP_HANDLE_EXCEPTIONS;
return r;
diff --git a/libgcc/soft-fp/fixunsdfsi.c b/libgcc/soft-fp/fixunsdfsi.c
index 43287b00732..ff3744467a2 100644
--- a/libgcc/soft-fp/fixunsdfsi.c
+++ b/libgcc/soft-fp/fixunsdfsi.c
@@ -31,14 +31,16 @@
#include "soft-fp.h"
#include "double.h"
-USItype __fixunsdfsi(DFtype a)
+USItype
+__fixunsdfsi (DFtype a)
{
FP_DECL_EX;
- FP_DECL_D(A);
+ FP_DECL_D (A);
USItype r;
- FP_UNPACK_RAW_D(A, a);
- FP_TO_INT_D(r, A, SI_BITS, 0);
+ FP_INIT_EXCEPTIONS;
+ FP_UNPACK_RAW_D (A, a);
+ FP_TO_INT_D (r, A, SI_BITS, 0);
FP_HANDLE_EXCEPTIONS;
return r;
diff --git a/libgcc/soft-fp/fixunsdfti.c b/libgcc/soft-fp/fixunsdfti.c
index 48c41d4ac99..f124a7c6a8d 100644
--- a/libgcc/soft-fp/fixunsdfti.c
+++ b/libgcc/soft-fp/fixunsdfti.c
@@ -1,6 +1,6 @@
/* Software floating-point emulation.
Convert IEEE double to 128bit unsigned integer
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007-2013 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Uros Bizjak (ubizjak@gmail.com).
@@ -24,21 +24,22 @@
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
- MA 02110-1301, USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
#include "soft-fp.h"
#include "double.h"
-UTItype __fixunsdfti(DFtype a)
+UTItype
+__fixunsdfti (DFtype a)
{
FP_DECL_EX;
- FP_DECL_D(A);
+ FP_DECL_D (A);
UTItype r;
- FP_UNPACK_RAW_D(A, a);
- FP_TO_INT_D(r, A, TI_BITS, 0);
+ FP_INIT_EXCEPTIONS;
+ FP_UNPACK_RAW_D (A, a);
+ FP_TO_INT_D (r, A, TI_BITS, 0);
FP_HANDLE_EXCEPTIONS;
return r;
diff --git a/libgcc/soft-fp/fixunssfdi.c b/libgcc/soft-fp/fixunssfdi.c
index c0691c663cf..4261c5e6a7a 100644
--- a/libgcc/soft-fp/fixunssfdi.c
+++ b/libgcc/soft-fp/fixunssfdi.c
@@ -31,14 +31,16 @@
#include "soft-fp.h"
#include "single.h"
-UDItype __fixunssfdi(SFtype a)
+UDItype
+__fixunssfdi (SFtype a)
{
FP_DECL_EX;
- FP_DECL_S(A);
+ FP_DECL_S (A);
UDItype r;
- FP_UNPACK_RAW_S(A, a);
- FP_TO_INT_S(r, A, DI_BITS, 0);
+ FP_INIT_EXCEPTIONS;
+ FP_UNPACK_RAW_S (A, a);
+ FP_TO_INT_S (r, A, DI_BITS, 0);
FP_HANDLE_EXCEPTIONS;
return r;
diff --git a/libgcc/soft-fp/fixunssfsi.c b/libgcc/soft-fp/fixunssfsi.c
index 3d00ce8d56c..b4bb890299c 100644
--- a/libgcc/soft-fp/fixunssfsi.c
+++ b/libgcc/soft-fp/fixunssfsi.c
@@ -31,14 +31,16 @@
#include "soft-fp.h"
#include "single.h"
-USItype __fixunssfsi(SFtype a)
+USItype
+__fixunssfsi (SFtype a)
{
FP_DECL_EX;
- FP_DECL_S(A);
+ FP_DECL_S (A);
USItype r;
- FP_UNPACK_RAW_S(A, a);
- FP_TO_INT_S(r, A, SI_BITS, 0);
+ FP_INIT_EXCEPTIONS;
+ FP_UNPACK_RAW_S (A, a);
+ FP_TO_INT_S (r, A, SI_BITS, 0);
FP_HANDLE_EXCEPTIONS;
return r;
diff --git a/libgcc/soft-fp/fixunssfti.c b/libgcc/soft-fp/fixunssfti.c
index 89bcedbadc3..36d01b0cfe8 100644
--- a/libgcc/soft-fp/fixunssfti.c
+++ b/libgcc/soft-fp/fixunssfti.c
@@ -1,6 +1,6 @@
/* Software floating-point emulation.
Convert IEEE single to 128bit unsigned integer
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007-2013 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Uros Bizjak (ubizjak@gmail.com).
@@ -24,21 +24,22 @@
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
- MA 02110-1301, USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
#include "soft-fp.h"
#include "single.h"
-UTItype __fixunssfti(SFtype a)
+UTItype
+__fixunssfti (SFtype a)
{
FP_DECL_EX;
- FP_DECL_S(A);
+ FP_DECL_S (A);
UTItype r;
- FP_UNPACK_RAW_S(A, a);
- FP_TO_INT_S(r, A, TI_BITS, 0);
+ FP_INIT_EXCEPTIONS;
+ FP_UNPACK_RAW_S (A, a);
+ FP_TO_INT_S (r, A, TI_BITS, 0);
FP_HANDLE_EXCEPTIONS;
return r;
diff --git a/libgcc/soft-fp/fixunstfdi.c b/libgcc/soft-fp/fixunstfdi.c
index d6038fa8914..b2355a2ae9d 100644
--- a/libgcc/soft-fp/fixunstfdi.c
+++ b/libgcc/soft-fp/fixunstfdi.c
@@ -31,14 +31,16 @@
#include "soft-fp.h"
#include "quad.h"
-UDItype __fixunstfdi(TFtype a)
+UDItype
+__fixunstfdi (TFtype a)
{
FP_DECL_EX;
- FP_DECL_Q(A);
+ FP_DECL_Q (A);
UDItype r;
- FP_UNPACK_RAW_Q(A, a);
- FP_TO_INT_Q(r, A, DI_BITS, 0);
+ FP_INIT_EXCEPTIONS;
+ FP_UNPACK_RAW_Q (A, a);
+ FP_TO_INT_Q (r, A, DI_BITS, 0);
FP_HANDLE_EXCEPTIONS;
return r;
diff --git a/libgcc/soft-fp/fixunstfsi.c b/libgcc/soft-fp/fixunstfsi.c
index c8481f1caf0..efa1418da1d 100644
--- a/libgcc/soft-fp/fixunstfsi.c
+++ b/libgcc/soft-fp/fixunstfsi.c
@@ -31,14 +31,16 @@
#include "soft-fp.h"
#include "quad.h"
-USItype __fixunstfsi(TFtype a)
+USItype
+__fixunstfsi (TFtype a)
{
FP_DECL_EX;
- FP_DECL_Q(A);
+ FP_DECL_Q (A);
USItype r;
- FP_UNPACK_RAW_Q(A, a);
- FP_TO_INT_Q(r, A, SI_BITS, 0);
+ FP_INIT_EXCEPTIONS;
+ FP_UNPACK_RAW_Q (A, a);
+ FP_TO_INT_Q (r, A, SI_BITS, 0);
FP_HANDLE_EXCEPTIONS;
return r;
diff --git a/libgcc/soft-fp/fixunstfti.c b/libgcc/soft-fp/fixunstfti.c
index f62bd505c64..efe0cf5c5d5 100644
--- a/libgcc/soft-fp/fixunstfti.c
+++ b/libgcc/soft-fp/fixunstfti.c
@@ -1,6 +1,6 @@
/* Software floating-point emulation.
Convert IEEE quad to 128bit unsigned integer
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007-2013 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Uros Bizjak (ubizjak@gmail.com).
@@ -24,21 +24,22 @@
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
- MA 02110-1301, USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
#include "soft-fp.h"
#include "quad.h"
-UTItype __fixunstfti(TFtype a)
+UTItype
+__fixunstfti (TFtype a)
{
FP_DECL_EX;
- FP_DECL_Q(A);
+ FP_DECL_Q (A);
UTItype r;
- FP_UNPACK_RAW_Q(A, a);
- FP_TO_INT_Q(r, A, TI_BITS, 0);
+ FP_INIT_EXCEPTIONS;
+ FP_UNPACK_RAW_Q (A, a);
+ FP_TO_INT_Q (r, A, TI_BITS, 0);
FP_HANDLE_EXCEPTIONS;
return r;
diff --git a/libgcc/soft-fp/floatdidf.c b/libgcc/soft-fp/floatdidf.c
index f6f594a84f6..fc8719abd73 100644
--- a/libgcc/soft-fp/floatdidf.c
+++ b/libgcc/soft-fp/floatdidf.c
@@ -31,14 +31,16 @@
#include "soft-fp.h"
#include "double.h"
-DFtype __floatdidf(DItype i)
+DFtype
+__floatdidf (DItype i)
{
FP_DECL_EX;
- FP_DECL_D(A);
+ FP_DECL_D (A);
DFtype a;
- FP_FROM_INT_D(A, i, DI_BITS, UDItype);
- FP_PACK_RAW_D(a, A);
+ FP_INIT_ROUNDMODE;
+ FP_FROM_INT_D (A, i, DI_BITS, UDItype);
+ FP_PACK_RAW_D (a, A);
FP_HANDLE_EXCEPTIONS;
return a;
diff --git a/libgcc/soft-fp/floatdisf.c b/libgcc/soft-fp/floatdisf.c
index 72252e4a999..b6b6b425250 100644
--- a/libgcc/soft-fp/floatdisf.c
+++ b/libgcc/soft-fp/floatdisf.c
@@ -31,14 +31,16 @@
#include "soft-fp.h"
#include "single.h"
-SFtype __floatdisf(DItype i)
+SFtype
+__floatdisf (DItype i)
{
FP_DECL_EX;
- FP_DECL_S(A);
+ FP_DECL_S (A);
SFtype a;
- FP_FROM_INT_S(A, i, DI_BITS, UDItype);
- FP_PACK_RAW_S(a, A);
+ FP_INIT_ROUNDMODE;
+ FP_FROM_INT_S (A, i, DI_BITS, UDItype);
+ FP_PACK_RAW_S (a, A);
FP_HANDLE_EXCEPTIONS;
return a;
diff --git a/libgcc/soft-fp/floatditf.c b/libgcc/soft-fp/floatditf.c
index 68da6c60b0d..fc3fba361f7 100644
--- a/libgcc/soft-fp/floatditf.c
+++ b/libgcc/soft-fp/floatditf.c
@@ -28,18 +28,18 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
+#define FP_NO_EXCEPTIONS
#include "soft-fp.h"
#include "quad.h"
-TFtype __floatditf(DItype i)
+TFtype
+__floatditf (DItype i)
{
- FP_DECL_EX;
- FP_DECL_Q(A);
+ FP_DECL_Q (A);
TFtype a;
- FP_FROM_INT_Q(A, i, DI_BITS, UDItype);
- FP_PACK_RAW_Q(a, A);
- FP_HANDLE_EXCEPTIONS;
+ FP_FROM_INT_Q (A, i, DI_BITS, UDItype);
+ FP_PACK_RAW_Q (a, A);
return a;
}
diff --git a/libgcc/soft-fp/floatsidf.c b/libgcc/soft-fp/floatsidf.c
index ec578fba791..7df5265ffc8 100644
--- a/libgcc/soft-fp/floatsidf.c
+++ b/libgcc/soft-fp/floatsidf.c
@@ -28,18 +28,18 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
+#define FP_NO_EXCEPTIONS
#include "soft-fp.h"
#include "double.h"
-DFtype __floatsidf(SItype i)
+DFtype
+__floatsidf (SItype i)
{
- FP_DECL_EX;
- FP_DECL_D(A);
+ FP_DECL_D (A);
DFtype a;
- FP_FROM_INT_D(A, i, SI_BITS, USItype);
- FP_PACK_RAW_D(a, A);
- FP_HANDLE_EXCEPTIONS;
+ FP_FROM_INT_D (A, i, SI_BITS, USItype);
+ FP_PACK_RAW_D (a, A);
return a;
}
diff --git a/libgcc/soft-fp/floatsisf.c b/libgcc/soft-fp/floatsisf.c
index c9ff205d7fd..b55fd3329eb 100644
--- a/libgcc/soft-fp/floatsisf.c
+++ b/libgcc/soft-fp/floatsisf.c
@@ -31,14 +31,16 @@
#include "soft-fp.h"
#include "single.h"
-SFtype __floatsisf(SItype i)
+SFtype
+__floatsisf (SItype i)
{
FP_DECL_EX;
- FP_DECL_S(A);
+ FP_DECL_S (A);
SFtype a;
- FP_FROM_INT_S(A, i, SI_BITS, USItype);
- FP_PACK_RAW_S(a, A);
+ FP_INIT_ROUNDMODE;
+ FP_FROM_INT_S (A, i, SI_BITS, USItype);
+ FP_PACK_RAW_S (a, A);
FP_HANDLE_EXCEPTIONS;
return a;
diff --git a/libgcc/soft-fp/floatsitf.c b/libgcc/soft-fp/floatsitf.c
index 6e24b9ea634..d7c3078e4ba 100644
--- a/libgcc/soft-fp/floatsitf.c
+++ b/libgcc/soft-fp/floatsitf.c
@@ -28,18 +28,18 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
+#define FP_NO_EXCEPTIONS
#include "soft-fp.h"
#include "quad.h"
-TFtype __floatsitf(SItype i)
+TFtype
+__floatsitf (SItype i)
{
- FP_DECL_EX;
- FP_DECL_Q(A);
+ FP_DECL_Q (A);
TFtype a;
- FP_FROM_INT_Q(A, i, SI_BITS, USItype);
- FP_PACK_RAW_Q(a, A);
- FP_HANDLE_EXCEPTIONS;
+ FP_FROM_INT_Q (A, i, SI_BITS, USItype);
+ FP_PACK_RAW_Q (a, A);
return a;
}
diff --git a/libgcc/soft-fp/floattidf.c b/libgcc/soft-fp/floattidf.c
index 14b6ea36a7a..a28181b23a7 100644
--- a/libgcc/soft-fp/floattidf.c
+++ b/libgcc/soft-fp/floattidf.c
@@ -1,6 +1,6 @@
/* Software floating-point emulation.
Convert a 128bit signed integer to IEEE double
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007-2013 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Uros Bizjak (ubizjak@gmail.com).
@@ -24,21 +24,22 @@
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
- MA 02110-1301, USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
#include "soft-fp.h"
#include "double.h"
-DFtype __floattidf(TItype i)
+DFtype
+__floattidf (TItype i)
{
FP_DECL_EX;
- FP_DECL_D(A);
+ FP_DECL_D (A);
DFtype a;
- FP_FROM_INT_D(A, i, TI_BITS, UTItype);
- FP_PACK_RAW_D(a, A);
+ FP_INIT_ROUNDMODE;
+ FP_FROM_INT_D (A, i, TI_BITS, UTItype);
+ FP_PACK_RAW_D (a, A);
FP_HANDLE_EXCEPTIONS;
return a;
diff --git a/libgcc/soft-fp/floattisf.c b/libgcc/soft-fp/floattisf.c
index 475cafa2770..da810479450 100644
--- a/libgcc/soft-fp/floattisf.c
+++ b/libgcc/soft-fp/floattisf.c
@@ -1,6 +1,6 @@
/* Software floating-point emulation.
Convert a 128bit signed integer to IEEE single
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007-2013 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Uros Bizjak (ubizjak@gmail.com).
@@ -24,21 +24,22 @@
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
- MA 02110-1301, USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
#include "soft-fp.h"
#include "single.h"
-SFtype __floattisf(TItype i)
+SFtype
+__floattisf (TItype i)
{
FP_DECL_EX;
- FP_DECL_S(A);
+ FP_DECL_S (A);
SFtype a;
- FP_FROM_INT_S(A, i, TI_BITS, UTItype);
- FP_PACK_RAW_S(a, A);
+ FP_INIT_ROUNDMODE;
+ FP_FROM_INT_S (A, i, TI_BITS, UTItype);
+ FP_PACK_RAW_S (a, A);
FP_HANDLE_EXCEPTIONS;
return a;
diff --git a/libgcc/soft-fp/floattitf.c b/libgcc/soft-fp/floattitf.c
index 12bbb2772c2..ffe217a6226 100644
--- a/libgcc/soft-fp/floattitf.c
+++ b/libgcc/soft-fp/floattitf.c
@@ -1,6 +1,6 @@
/* Software floating-point emulation.
Convert a 128bit signed integer to IEEE quad
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007-2013 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Uros Bizjak (ubizjak@gmail.com).
@@ -24,21 +24,22 @@
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
- MA 02110-1301, USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
#include "soft-fp.h"
#include "quad.h"
-TFtype __floattitf(TItype i)
+TFtype
+__floattitf (TItype i)
{
FP_DECL_EX;
- FP_DECL_Q(A);
+ FP_DECL_Q (A);
TFtype a;
- FP_FROM_INT_Q(A, i, TI_BITS, UTItype);
- FP_PACK_RAW_Q(a, A);
+ FP_INIT_ROUNDMODE;
+ FP_FROM_INT_Q (A, i, TI_BITS, UTItype);
+ FP_PACK_RAW_Q (a, A);
FP_HANDLE_EXCEPTIONS;
return a;
diff --git a/libgcc/soft-fp/floatundidf.c b/libgcc/soft-fp/floatundidf.c
index 1babcec8e0b..8a041f827a4 100644
--- a/libgcc/soft-fp/floatundidf.c
+++ b/libgcc/soft-fp/floatundidf.c
@@ -31,14 +31,16 @@
#include "soft-fp.h"
#include "double.h"
-DFtype __floatundidf(UDItype i)
+DFtype
+__floatundidf (UDItype i)
{
FP_DECL_EX;
- FP_DECL_D(A);
+ FP_DECL_D (A);
DFtype a;
- FP_FROM_INT_D(A, i, DI_BITS, UDItype);
- FP_PACK_RAW_D(a, A);
+ FP_INIT_ROUNDMODE;
+ FP_FROM_INT_D (A, i, DI_BITS, UDItype);
+ FP_PACK_RAW_D (a, A);
FP_HANDLE_EXCEPTIONS;
return a;
diff --git a/libgcc/soft-fp/floatundisf.c b/libgcc/soft-fp/floatundisf.c
index 1c645c023d3..8dc750851af 100644
--- a/libgcc/soft-fp/floatundisf.c
+++ b/libgcc/soft-fp/floatundisf.c
@@ -31,14 +31,16 @@
#include "soft-fp.h"
#include "single.h"
-SFtype __floatundisf(UDItype i)
+SFtype
+__floatundisf (UDItype i)
{
FP_DECL_EX;
- FP_DECL_S(A);
+ FP_DECL_S (A);
SFtype a;
- FP_FROM_INT_S(A, i, DI_BITS, UDItype);
- FP_PACK_RAW_S(a, A);
+ FP_INIT_ROUNDMODE;
+ FP_FROM_INT_S (A, i, DI_BITS, UDItype);
+ FP_PACK_RAW_S (a, A);
FP_HANDLE_EXCEPTIONS;
return a;
diff --git a/libgcc/soft-fp/floatunditf.c b/libgcc/soft-fp/floatunditf.c
index fff73fdb67c..cc8a3fe06c9 100644
--- a/libgcc/soft-fp/floatunditf.c
+++ b/libgcc/soft-fp/floatunditf.c
@@ -28,19 +28,18 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
+#define FP_NO_EXCEPTIONS
#include "soft-fp.h"
#include "quad.h"
TFtype
-__floatunditf(UDItype i)
+__floatunditf (UDItype i)
{
- FP_DECL_EX;
- FP_DECL_Q(A);
+ FP_DECL_Q (A);
TFtype a;
- FP_FROM_INT_Q(A, i, DI_BITS, UDItype);
- FP_PACK_RAW_Q(a, A);
- FP_HANDLE_EXCEPTIONS;
+ FP_FROM_INT_Q (A, i, DI_BITS, UDItype);
+ FP_PACK_RAW_Q (a, A);
return a;
}
diff --git a/libgcc/soft-fp/floatunsidf.c b/libgcc/soft-fp/floatunsidf.c
index 548dc7c0c46..059029640c9 100644
--- a/libgcc/soft-fp/floatunsidf.c
+++ b/libgcc/soft-fp/floatunsidf.c
@@ -28,18 +28,18 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
+#define FP_NO_EXCEPTIONS
#include "soft-fp.h"
#include "double.h"
-DFtype __floatunsidf(USItype i)
+DFtype
+__floatunsidf (USItype i)
{
- FP_DECL_EX;
- FP_DECL_D(A);
+ FP_DECL_D (A);
DFtype a;
- FP_FROM_INT_D(A, i, SI_BITS, USItype);
- FP_PACK_RAW_D(a, A);
- FP_HANDLE_EXCEPTIONS;
+ FP_FROM_INT_D (A, i, SI_BITS, USItype);
+ FP_PACK_RAW_D (a, A);
return a;
}
diff --git a/libgcc/soft-fp/floatunsisf.c b/libgcc/soft-fp/floatunsisf.c
index 2c0cc897636..91c1e4d1a96 100644
--- a/libgcc/soft-fp/floatunsisf.c
+++ b/libgcc/soft-fp/floatunsisf.c
@@ -31,14 +31,16 @@
#include "soft-fp.h"
#include "single.h"
-SFtype __floatunsisf(USItype i)
+SFtype
+__floatunsisf (USItype i)
{
FP_DECL_EX;
- FP_DECL_S(A);
+ FP_DECL_S (A);
SFtype a;
- FP_FROM_INT_S(A, i, SI_BITS, USItype);
- FP_PACK_RAW_S(a, A);
+ FP_INIT_ROUNDMODE;
+ FP_FROM_INT_S (A, i, SI_BITS, USItype);
+ FP_PACK_RAW_S (a, A);
FP_HANDLE_EXCEPTIONS;
return a;
diff --git a/libgcc/soft-fp/floatunsitf.c b/libgcc/soft-fp/floatunsitf.c
index 1099c2ee849..b1eecfd7c95 100644
--- a/libgcc/soft-fp/floatunsitf.c
+++ b/libgcc/soft-fp/floatunsitf.c
@@ -28,19 +28,18 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
+#define FP_NO_EXCEPTIONS
#include "soft-fp.h"
#include "quad.h"
TFtype
-__floatunsitf(USItype i)
+__floatunsitf (USItype i)
{
- FP_DECL_EX;
- FP_DECL_Q(A);
+ FP_DECL_Q (A);
TFtype a;
- FP_FROM_INT_Q(A, i, SI_BITS, USItype);
- FP_PACK_RAW_Q(a, A);
- FP_HANDLE_EXCEPTIONS;
+ FP_FROM_INT_Q (A, i, SI_BITS, USItype);
+ FP_PACK_RAW_Q (a, A);
return a;
}
diff --git a/libgcc/soft-fp/floatuntidf.c b/libgcc/soft-fp/floatuntidf.c
index db1fe1aacb6..6a8981daec0 100644
--- a/libgcc/soft-fp/floatuntidf.c
+++ b/libgcc/soft-fp/floatuntidf.c
@@ -1,6 +1,6 @@
/* Software floating-point emulation.
Convert a 128bit unsigned integer to IEEE double
- Copyright (C) 1997,1999, 2006 Free Software Foundation, Inc.
+ Copyright (C) 1997-2013 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Uros Bizjak (ubizjak@gmail.com).
@@ -24,21 +24,22 @@
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
- MA 02110-1301, USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
#include "soft-fp.h"
#include "double.h"
-DFtype __floatuntidf(UTItype i)
+DFtype
+__floatuntidf (UTItype i)
{
FP_DECL_EX;
- FP_DECL_D(A);
+ FP_DECL_D (A);
DFtype a;
- FP_FROM_INT_D(A, i, TI_BITS, UTItype);
- FP_PACK_RAW_D(a, A);
+ FP_INIT_ROUNDMODE;
+ FP_FROM_INT_D (A, i, TI_BITS, UTItype);
+ FP_PACK_RAW_D (a, A);
FP_HANDLE_EXCEPTIONS;
return a;
diff --git a/libgcc/soft-fp/floatuntisf.c b/libgcc/soft-fp/floatuntisf.c
index 73914878b2e..94d0593f26f 100644
--- a/libgcc/soft-fp/floatuntisf.c
+++ b/libgcc/soft-fp/floatuntisf.c
@@ -1,6 +1,6 @@
/* Software floating-point emulation.
Convert a 128bit unsigned integer to IEEE single
- Copyright (C) 2007, 2008 Free Software Foundation, Inc.
+ Copyright (C) 2007-2013 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Uros Bizjak (ubizjak@gmail.com).
@@ -24,21 +24,22 @@
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
- MA 02110-1301, USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
#include "soft-fp.h"
#include "single.h"
-SFtype __floatuntisf(UTItype i)
+SFtype
+__floatuntisf (UTItype i)
{
FP_DECL_EX;
- FP_DECL_S(A);
+ FP_DECL_S (A);
SFtype a;
- FP_FROM_INT_S(A, i, TI_BITS, UTItype);
- FP_PACK_RAW_S(a, A);
+ FP_INIT_ROUNDMODE;
+ FP_FROM_INT_S (A, i, TI_BITS, UTItype);
+ FP_PACK_RAW_S (a, A);
FP_HANDLE_EXCEPTIONS;
return a;
diff --git a/libgcc/soft-fp/floatuntitf.c b/libgcc/soft-fp/floatuntitf.c
index 8d669012644..424bfef8fa8 100644
--- a/libgcc/soft-fp/floatuntitf.c
+++ b/libgcc/soft-fp/floatuntitf.c
@@ -1,6 +1,6 @@
/* Software floating-point emulation.
Convert a 128bit unsigned integer to IEEE quad
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007-2013 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Uros Bizjak (ubizjak@gmail.com).
@@ -24,21 +24,22 @@
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
- MA 02110-1301, USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
#include "soft-fp.h"
#include "quad.h"
-TFtype __floatuntitf(UTItype i)
+TFtype
+__floatuntitf (UTItype i)
{
FP_DECL_EX;
- FP_DECL_Q(A);
+ FP_DECL_Q (A);
TFtype a;
- FP_FROM_INT_Q(A, i, TI_BITS, UTItype);
- FP_PACK_RAW_Q(a, A);
+ FP_INIT_ROUNDMODE;
+ FP_FROM_INT_Q (A, i, TI_BITS, UTItype);
+ FP_PACK_RAW_Q (a, A);
FP_HANDLE_EXCEPTIONS;
return a;
diff --git a/libgcc/soft-fp/gedf2.c b/libgcc/soft-fp/gedf2.c
index 0ef9f5de2c8..5b6fad28492 100644
--- a/libgcc/soft-fp/gedf2.c
+++ b/libgcc/soft-fp/gedf2.c
@@ -31,20 +31,23 @@
#include "soft-fp.h"
#include "double.h"
-CMPtype __gedf2(DFtype a, DFtype b)
+CMPtype
+__gedf2 (DFtype a, DFtype b)
{
FP_DECL_EX;
- FP_DECL_D(A); FP_DECL_D(B);
+ FP_DECL_D (A);
+ FP_DECL_D (B);
CMPtype r;
- FP_UNPACK_RAW_D(A, a);
- FP_UNPACK_RAW_D(B, b);
- FP_CMP_D(r, A, B, -2);
- if (r == -2 && (FP_ISSIGNAN_D(A) || FP_ISSIGNAN_D(B)))
- FP_SET_EXCEPTION(FP_EX_INVALID);
+ FP_INIT_EXCEPTIONS;
+ FP_UNPACK_RAW_D (A, a);
+ FP_UNPACK_RAW_D (B, b);
+ FP_CMP_D (r, A, B, -2);
+ if (r == -2)
+ FP_SET_EXCEPTION (FP_EX_INVALID);
FP_HANDLE_EXCEPTIONS;
return r;
}
-strong_alias(__gedf2, __gtdf2);
+strong_alias (__gedf2, __gtdf2);
diff --git a/libgcc/soft-fp/gesf2.c b/libgcc/soft-fp/gesf2.c
index f0a83773104..4e5d9393f1e 100644
--- a/libgcc/soft-fp/gesf2.c
+++ b/libgcc/soft-fp/gesf2.c
@@ -31,20 +31,23 @@
#include "soft-fp.h"
#include "single.h"
-CMPtype __gesf2(SFtype a, SFtype b)
+CMPtype
+__gesf2 (SFtype a, SFtype b)
{
FP_DECL_EX;
- FP_DECL_S(A); FP_DECL_S(B);
+ FP_DECL_S (A);
+ FP_DECL_S (B);
CMPtype r;
- FP_UNPACK_RAW_S(A, a);
- FP_UNPACK_RAW_S(B, b);
- FP_CMP_S(r, A, B, -2);
- if (r == -2 && (FP_ISSIGNAN_S(A) || FP_ISSIGNAN_S(B)))
- FP_SET_EXCEPTION(FP_EX_INVALID);
+ FP_INIT_EXCEPTIONS;
+ FP_UNPACK_RAW_S (A, a);
+ FP_UNPACK_RAW_S (B, b);
+ FP_CMP_S (r, A, B, -2);
+ if (r == -2)
+ FP_SET_EXCEPTION (FP_EX_INVALID);
FP_HANDLE_EXCEPTIONS;
return r;
}
-strong_alias(__gesf2, __gtsf2);
+strong_alias (__gesf2, __gtsf2);
diff --git a/libgcc/soft-fp/getf2.c b/libgcc/soft-fp/getf2.c
index 705d48b9053..ed02f459ea2 100644
--- a/libgcc/soft-fp/getf2.c
+++ b/libgcc/soft-fp/getf2.c
@@ -31,20 +31,23 @@
#include "soft-fp.h"
#include "quad.h"
-CMPtype __getf2(TFtype a, TFtype b)
+CMPtype
+__getf2 (TFtype a, TFtype b)
{
FP_DECL_EX;
- FP_DECL_Q(A); FP_DECL_Q(B);
+ FP_DECL_Q (A);
+ FP_DECL_Q (B);
CMPtype r;
- FP_UNPACK_RAW_Q(A, a);
- FP_UNPACK_RAW_Q(B, b);
- FP_CMP_Q(r, A, B, -2);
- if (r == -2 && (FP_ISSIGNAN_Q(A) || FP_ISSIGNAN_Q(B)))
- FP_SET_EXCEPTION(FP_EX_INVALID);
+ FP_INIT_EXCEPTIONS;
+ FP_UNPACK_RAW_Q (A, a);
+ FP_UNPACK_RAW_Q (B, b);
+ FP_CMP_Q (r, A, B, -2);
+ if (r == -2)
+ FP_SET_EXCEPTION (FP_EX_INVALID);
FP_HANDLE_EXCEPTIONS;
return r;
}
-strong_alias(__getf2, __gttf2);
+strong_alias (__getf2, __gttf2);
diff --git a/libgcc/soft-fp/ledf2.c b/libgcc/soft-fp/ledf2.c
index 7b8f403bb80..476f1c47015 100644
--- a/libgcc/soft-fp/ledf2.c
+++ b/libgcc/soft-fp/ledf2.c
@@ -31,20 +31,23 @@
#include "soft-fp.h"
#include "double.h"
-CMPtype __ledf2(DFtype a, DFtype b)
+CMPtype
+__ledf2 (DFtype a, DFtype b)
{
FP_DECL_EX;
- FP_DECL_D(A); FP_DECL_D(B);
+ FP_DECL_D (A);
+ FP_DECL_D (B);
CMPtype r;
- FP_UNPACK_RAW_D(A, a);
- FP_UNPACK_RAW_D(B, b);
- FP_CMP_D(r, A, B, 2);
- if (r == 2 && (FP_ISSIGNAN_D(A) || FP_ISSIGNAN_D(B)))
- FP_SET_EXCEPTION(FP_EX_INVALID);
+ FP_INIT_EXCEPTIONS;
+ FP_UNPACK_RAW_D (A, a);
+ FP_UNPACK_RAW_D (B, b);
+ FP_CMP_D (r, A, B, 2);
+ if (r == 2)
+ FP_SET_EXCEPTION (FP_EX_INVALID);
FP_HANDLE_EXCEPTIONS;
return r;
}
-strong_alias(__ledf2, __ltdf2);
+strong_alias (__ledf2, __ltdf2);
diff --git a/libgcc/soft-fp/lesf2.c b/libgcc/soft-fp/lesf2.c
index 41f823b5fc2..ac2f748a36c 100644
--- a/libgcc/soft-fp/lesf2.c
+++ b/libgcc/soft-fp/lesf2.c
@@ -31,20 +31,23 @@
#include "soft-fp.h"
#include "single.h"
-CMPtype __lesf2(SFtype a, SFtype b)
+CMPtype
+__lesf2 (SFtype a, SFtype b)
{
FP_DECL_EX;
- FP_DECL_S(A); FP_DECL_S(B);
+ FP_DECL_S (A);
+ FP_DECL_S (B);
CMPtype r;
- FP_UNPACK_RAW_S(A, a);
- FP_UNPACK_RAW_S(B, b);
- FP_CMP_S(r, A, B, 2);
- if (r == 2 && (FP_ISSIGNAN_S(A) || FP_ISSIGNAN_S(B)))
- FP_SET_EXCEPTION(FP_EX_INVALID);
+ FP_INIT_EXCEPTIONS;
+ FP_UNPACK_RAW_S (A, a);
+ FP_UNPACK_RAW_S (B, b);
+ FP_CMP_S (r, A, B, 2);
+ if (r == 2)
+ FP_SET_EXCEPTION (FP_EX_INVALID);
FP_HANDLE_EXCEPTIONS;
return r;
}
-strong_alias(__lesf2, __ltsf2);
+strong_alias (__lesf2, __ltsf2);
diff --git a/libgcc/soft-fp/letf2.c b/libgcc/soft-fp/letf2.c
index 59342ca4cb9..a41055b9494 100644
--- a/libgcc/soft-fp/letf2.c
+++ b/libgcc/soft-fp/letf2.c
@@ -31,20 +31,23 @@
#include "soft-fp.h"
#include "quad.h"
-CMPtype __letf2(TFtype a, TFtype b)
+CMPtype
+__letf2 (TFtype a, TFtype b)
{
FP_DECL_EX;
- FP_DECL_Q(A); FP_DECL_Q(B);
+ FP_DECL_Q (A);
+ FP_DECL_Q (B);
CMPtype r;
- FP_UNPACK_RAW_Q(A, a);
- FP_UNPACK_RAW_Q(B, b);
- FP_CMP_Q(r, A, B, 2);
- if (r == 2 && (FP_ISSIGNAN_Q(A) || FP_ISSIGNAN_Q(B)))
- FP_SET_EXCEPTION(FP_EX_INVALID);
+ FP_INIT_EXCEPTIONS;
+ FP_UNPACK_RAW_Q (A, a);
+ FP_UNPACK_RAW_Q (B, b);
+ FP_CMP_Q (r, A, B, 2);
+ if (r == 2)
+ FP_SET_EXCEPTION (FP_EX_INVALID);
FP_HANDLE_EXCEPTIONS;
return r;
}
-strong_alias(__letf2, __lttf2);
+strong_alias (__letf2, __lttf2);
diff --git a/libgcc/soft-fp/muldf3.c b/libgcc/soft-fp/muldf3.c
index 8c08281b46f..dee3f76e5b9 100644
--- a/libgcc/soft-fp/muldf3.c
+++ b/libgcc/soft-fp/muldf3.c
@@ -31,17 +31,20 @@
#include "soft-fp.h"
#include "double.h"
-DFtype __muldf3(DFtype a, DFtype b)
+DFtype
+__muldf3 (DFtype a, DFtype b)
{
FP_DECL_EX;
- FP_DECL_D(A); FP_DECL_D(B); FP_DECL_D(R);
+ FP_DECL_D (A);
+ FP_DECL_D (B);
+ FP_DECL_D (R);
DFtype r;
FP_INIT_ROUNDMODE;
- FP_UNPACK_D(A, a);
- FP_UNPACK_D(B, b);
- FP_MUL_D(R, A, B);
- FP_PACK_D(r, R);
+ FP_UNPACK_D (A, a);
+ FP_UNPACK_D (B, b);
+ FP_MUL_D (R, A, B);
+ FP_PACK_D (r, R);
FP_HANDLE_EXCEPTIONS;
return r;
diff --git a/libgcc/soft-fp/mulsf3.c b/libgcc/soft-fp/mulsf3.c
index f0341a56c5f..f983b303479 100644
--- a/libgcc/soft-fp/mulsf3.c
+++ b/libgcc/soft-fp/mulsf3.c
@@ -31,17 +31,20 @@
#include "soft-fp.h"
#include "single.h"
-SFtype __mulsf3(SFtype a, SFtype b)
+SFtype
+__mulsf3 (SFtype a, SFtype b)
{
FP_DECL_EX;
- FP_DECL_S(A); FP_DECL_S(B); FP_DECL_S(R);
+ FP_DECL_S (A);
+ FP_DECL_S (B);
+ FP_DECL_S (R);
SFtype r;
FP_INIT_ROUNDMODE;
- FP_UNPACK_S(A, a);
- FP_UNPACK_S(B, b);
- FP_MUL_S(R, A, B);
- FP_PACK_S(r, R);
+ FP_UNPACK_S (A, a);
+ FP_UNPACK_S (B, b);
+ FP_MUL_S (R, A, B);
+ FP_PACK_S (r, R);
FP_HANDLE_EXCEPTIONS;
return r;
diff --git a/libgcc/soft-fp/multf3.c b/libgcc/soft-fp/multf3.c
index 35badf2fc8d..1306c63f8ad 100644
--- a/libgcc/soft-fp/multf3.c
+++ b/libgcc/soft-fp/multf3.c
@@ -31,17 +31,20 @@
#include "soft-fp.h"
#include "quad.h"
-TFtype __multf3(TFtype a, TFtype b)
+TFtype
+__multf3 (TFtype a, TFtype b)
{
FP_DECL_EX;
- FP_DECL_Q(A); FP_DECL_Q(B); FP_DECL_Q(R);
+ FP_DECL_Q (A);
+ FP_DECL_Q (B);
+ FP_DECL_Q (R);
TFtype r;
FP_INIT_ROUNDMODE;
- FP_UNPACK_Q(A, a);
- FP_UNPACK_Q(B, b);
- FP_MUL_Q(R, A, B);
- FP_PACK_Q(r, R);
+ FP_UNPACK_Q (A, a);
+ FP_UNPACK_Q (B, b);
+ FP_MUL_Q (R, A, B);
+ FP_PACK_Q (r, R);
FP_HANDLE_EXCEPTIONS;
return r;
diff --git a/libgcc/soft-fp/negdf2.c b/libgcc/soft-fp/negdf2.c
index 3cc6f5f400b..d74c16c1ede 100644
--- a/libgcc/soft-fp/negdf2.c
+++ b/libgcc/soft-fp/negdf2.c
@@ -31,17 +31,16 @@
#include "soft-fp.h"
#include "double.h"
-DFtype __negdf2(DFtype a)
+DFtype
+__negdf2 (DFtype a)
{
- FP_DECL_EX;
- FP_DECL_D(A); FP_DECL_D(R);
+ FP_DECL_D (A);
+ FP_DECL_D (R);
DFtype r;
- FP_UNPACK_D(A, a);
- FP_NEG_D(R, A);
- FP_PACK_D(r, R);
- FP_CLEAR_EXCEPTIONS;
- FP_HANDLE_EXCEPTIONS;
+ FP_UNPACK_RAW_D (A, a);
+ FP_NEG_D (R, A);
+ FP_PACK_RAW_D (r, R);
return r;
}
diff --git a/libgcc/soft-fp/negsf2.c b/libgcc/soft-fp/negsf2.c
index d8d59106036..0316105a5dc 100644
--- a/libgcc/soft-fp/negsf2.c
+++ b/libgcc/soft-fp/negsf2.c
@@ -31,17 +31,16 @@
#include "soft-fp.h"
#include "single.h"
-SFtype __negsf2(SFtype a)
+SFtype
+__negsf2 (SFtype a)
{
- FP_DECL_EX;
- FP_DECL_S(A); FP_DECL_S(R);
+ FP_DECL_S (A);
+ FP_DECL_S (R);
SFtype r;
- FP_UNPACK_S(A, a);
- FP_NEG_S(R, A);
- FP_PACK_S(r, R);
- FP_CLEAR_EXCEPTIONS;
- FP_HANDLE_EXCEPTIONS;
+ FP_UNPACK_RAW_S (A, a);
+ FP_NEG_S (R, A);
+ FP_PACK_RAW_S (r, R);
return r;
}
diff --git a/libgcc/soft-fp/negtf2.c b/libgcc/soft-fp/negtf2.c
index 1c08441487b..8540af24d27 100644
--- a/libgcc/soft-fp/negtf2.c
+++ b/libgcc/soft-fp/negtf2.c
@@ -31,17 +31,16 @@
#include "soft-fp.h"
#include "quad.h"
-TFtype __negtf2(TFtype a)
+TFtype
+__negtf2 (TFtype a)
{
- FP_DECL_EX;
- FP_DECL_Q(A); FP_DECL_Q(R);
+ FP_DECL_Q (A);
+ FP_DECL_Q (R);
TFtype r;
- FP_UNPACK_Q(A, a);
- FP_NEG_Q(R, A);
- FP_PACK_Q(r, R);
- FP_CLEAR_EXCEPTIONS;
- FP_HANDLE_EXCEPTIONS;
+ FP_UNPACK_RAW_Q (A, a);
+ FP_NEG_Q (R, A);
+ FP_PACK_RAW_Q (r, R);
return r;
}
diff --git a/libgcc/soft-fp/op-1.h b/libgcc/soft-fp/op-1.h
index 8e05e2fab7e..8ccb46a7962 100644
--- a/libgcc/soft-fp/op-1.h
+++ b/libgcc/soft-fp/op-1.h
@@ -31,103 +31,117 @@
<http://www.gnu.org/licenses/>. */
#define _FP_FRAC_DECL_1(X) _FP_W_TYPE X##_f
-#define _FP_FRAC_COPY_1(D,S) (D##_f = S##_f)
-#define _FP_FRAC_SET_1(X,I) (X##_f = I)
+#define _FP_FRAC_COPY_1(D, S) (D##_f = S##_f)
+#define _FP_FRAC_SET_1(X, I) (X##_f = I)
#define _FP_FRAC_HIGH_1(X) (X##_f)
#define _FP_FRAC_LOW_1(X) (X##_f)
-#define _FP_FRAC_WORD_1(X,w) (X##_f)
-
-#define _FP_FRAC_ADDI_1(X,I) (X##_f += I)
-#define _FP_FRAC_SLL_1(X,N) \
- do { \
- if (__builtin_constant_p(N) && (N) == 1) \
- X##_f += X##_f; \
- else \
- X##_f <<= (N); \
- } while (0)
-#define _FP_FRAC_SRL_1(X,N) (X##_f >>= N)
+#define _FP_FRAC_WORD_1(X, w) (X##_f)
+
+#define _FP_FRAC_ADDI_1(X, I) (X##_f += I)
+#define _FP_FRAC_SLL_1(X, N) \
+ do \
+ { \
+ if (__builtin_constant_p (N) && (N) == 1) \
+ X##_f += X##_f; \
+ else \
+ X##_f <<= (N); \
+ } \
+ while (0)
+#define _FP_FRAC_SRL_1(X, N) (X##_f >>= N)
/* Right shift with sticky-lsb. */
-#define _FP_FRAC_SRST_1(X,S,N,sz) __FP_FRAC_SRST_1(X##_f, S, N, sz)
-#define _FP_FRAC_SRS_1(X,N,sz) __FP_FRAC_SRS_1(X##_f, N, sz)
-
-#define __FP_FRAC_SRST_1(X,S,N,sz) \
-do { \
- S = (__builtin_constant_p(N) && (N) == 1 \
- ? X & 1 : (X << (_FP_W_TYPE_SIZE - (N))) != 0); \
- X = X >> (N); \
-} while (0)
-
-#define __FP_FRAC_SRS_1(X,N,sz) \
- (X = (X >> (N) | (__builtin_constant_p(N) && (N) == 1 \
- ? X & 1 : (X << (_FP_W_TYPE_SIZE - (N))) != 0)))
-
-#define _FP_FRAC_ADD_1(R,X,Y) (R##_f = X##_f + Y##_f)
-#define _FP_FRAC_SUB_1(R,X,Y) (R##_f = X##_f - Y##_f)
-#define _FP_FRAC_DEC_1(X,Y) (X##_f -= Y##_f)
-#define _FP_FRAC_CLZ_1(z, X) __FP_CLZ(z, X##_f)
+#define _FP_FRAC_SRST_1(X, S, N, sz) __FP_FRAC_SRST_1 (X##_f, S, N, sz)
+#define _FP_FRAC_SRS_1(X, N, sz) __FP_FRAC_SRS_1 (X##_f, N, sz)
+
+#define __FP_FRAC_SRST_1(X, S, N, sz) \
+ do \
+ { \
+ S = (__builtin_constant_p (N) && (N) == 1 \
+ ? X & 1 \
+ : (X << (_FP_W_TYPE_SIZE - (N))) != 0); \
+ X = X >> (N); \
+ } \
+ while (0)
+
+#define __FP_FRAC_SRS_1(X, N, sz) \
+ (X = (X >> (N) | (__builtin_constant_p (N) && (N) == 1 \
+ ? X & 1 \
+ : (X << (_FP_W_TYPE_SIZE - (N))) != 0)))
+
+#define _FP_FRAC_ADD_1(R, X, Y) (R##_f = X##_f + Y##_f)
+#define _FP_FRAC_SUB_1(R, X, Y) (R##_f = X##_f - Y##_f)
+#define _FP_FRAC_DEC_1(X, Y) (X##_f -= Y##_f)
+#define _FP_FRAC_CLZ_1(z, X) __FP_CLZ (z, X##_f)
/* Predicates */
-#define _FP_FRAC_NEGP_1(X) ((_FP_WS_TYPE)X##_f < 0)
+#define _FP_FRAC_NEGP_1(X) ((_FP_WS_TYPE) X##_f < 0)
#define _FP_FRAC_ZEROP_1(X) (X##_f == 0)
-#define _FP_FRAC_OVERP_1(fs,X) (X##_f & _FP_OVERFLOW_##fs)
-#define _FP_FRAC_CLEAR_OVERP_1(fs,X) (X##_f &= ~_FP_OVERFLOW_##fs)
+#define _FP_FRAC_OVERP_1(fs, X) (X##_f & _FP_OVERFLOW_##fs)
+#define _FP_FRAC_CLEAR_OVERP_1(fs, X) (X##_f &= ~_FP_OVERFLOW_##fs)
+#define _FP_FRAC_HIGHBIT_DW_1(fs, X) (X##_f & _FP_HIGHBIT_DW_##fs)
#define _FP_FRAC_EQ_1(X, Y) (X##_f == Y##_f)
#define _FP_FRAC_GE_1(X, Y) (X##_f >= Y##_f)
#define _FP_FRAC_GT_1(X, Y) (X##_f > Y##_f)
#define _FP_ZEROFRAC_1 0
#define _FP_MINFRAC_1 1
-#define _FP_MAXFRAC_1 (~(_FP_WS_TYPE)0)
+#define _FP_MAXFRAC_1 (~(_FP_WS_TYPE) 0)
/*
* Unpack the raw bits of a native fp value. Do not classify or
* normalize the data.
*/
-#define _FP_UNPACK_RAW_1(fs, X, val) \
- do { \
- union _FP_UNION_##fs _flo; _flo.flt = (val); \
- \
- X##_f = _flo.bits.frac; \
- X##_e = _flo.bits.exp; \
- X##_s = _flo.bits.sign; \
- } while (0)
-
-#define _FP_UNPACK_RAW_1_P(fs, X, val) \
- do { \
- union _FP_UNION_##fs *_flo = \
- (union _FP_UNION_##fs *)(val); \
- \
- X##_f = _flo->bits.frac; \
- X##_e = _flo->bits.exp; \
- X##_s = _flo->bits.sign; \
- } while (0)
+#define _FP_UNPACK_RAW_1(fs, X, val) \
+ do \
+ { \
+ union _FP_UNION_##fs _flo; \
+ _flo.flt = (val); \
+ \
+ X##_f = _flo.bits.frac; \
+ X##_e = _flo.bits.exp; \
+ X##_s = _flo.bits.sign; \
+ } \
+ while (0)
+
+#define _FP_UNPACK_RAW_1_P(fs, X, val) \
+ do \
+ { \
+ union _FP_UNION_##fs *_flo = (union _FP_UNION_##fs *) (val); \
+ \
+ X##_f = _flo->bits.frac; \
+ X##_e = _flo->bits.exp; \
+ X##_s = _flo->bits.sign; \
+ } \
+ while (0)
/*
* Repack the raw bits of a native fp value.
*/
-#define _FP_PACK_RAW_1(fs, val, X) \
- do { \
- union _FP_UNION_##fs _flo; \
- \
- _flo.bits.frac = X##_f; \
- _flo.bits.exp = X##_e; \
- _flo.bits.sign = X##_s; \
- \
- (val) = _flo.flt; \
- } while (0)
-
-#define _FP_PACK_RAW_1_P(fs, val, X) \
- do { \
- union _FP_UNION_##fs *_flo = \
- (union _FP_UNION_##fs *)(val); \
- \
- _flo->bits.frac = X##_f; \
- _flo->bits.exp = X##_e; \
- _flo->bits.sign = X##_s; \
- } while (0)
+#define _FP_PACK_RAW_1(fs, val, X) \
+ do \
+ { \
+ union _FP_UNION_##fs _flo; \
+ \
+ _flo.bits.frac = X##_f; \
+ _flo.bits.exp = X##_e; \
+ _flo.bits.sign = X##_s; \
+ \
+ (val) = _flo.flt; \
+ } \
+ while (0)
+
+#define _FP_PACK_RAW_1_P(fs, val, X) \
+ do \
+ { \
+ union _FP_UNION_##fs *_flo = (union _FP_UNION_##fs *) (val); \
+ \
+ _flo->bits.frac = X##_f; \
+ _flo->bits.exp = X##_e; \
+ _flo->bits.sign = X##_s; \
+ } \
+ while (0)
/*
@@ -137,57 +151,86 @@ do { \
/* Basic. Assuming the host word size is >= 2*FRACBITS, we can do the
multiplication immediately. */
+#define _FP_MUL_MEAT_DW_1_imm(wfracbits, R, X, Y) \
+ do \
+ { \
+ R##_f = X##_f * Y##_f; \
+ } \
+ while (0)
+
#define _FP_MUL_MEAT_1_imm(wfracbits, R, X, Y) \
- do { \
- R##_f = X##_f * Y##_f; \
- /* Normalize since we know where the msb of the multiplicands \
- were (bit B), we know that the msb of the of the product is \
- at either 2B or 2B-1. */ \
- _FP_FRAC_SRS_1(R, wfracbits-1, 2*wfracbits); \
- } while (0)
+ do \
+ { \
+ _FP_MUL_MEAT_DW_1_imm (wfracbits, R, X, Y); \
+ /* Normalize since we know where the msb of the multiplicands \
+ were (bit B), we know that the msb of the of the product is \
+ at either 2B or 2B-1. */ \
+ _FP_FRAC_SRS_1 (R, wfracbits-1, 2*wfracbits); \
+ } \
+ while (0)
/* Given a 1W * 1W => 2W primitive, do the extended multiplication. */
+#define _FP_MUL_MEAT_DW_1_wide(wfracbits, R, X, Y, doit) \
+ do \
+ { \
+ doit (R##_f1, R##_f0, X##_f, Y##_f); \
+ } \
+ while (0)
+
#define _FP_MUL_MEAT_1_wide(wfracbits, R, X, Y, doit) \
- do { \
- _FP_W_TYPE _Z_f0, _Z_f1; \
- doit(_Z_f1, _Z_f0, X##_f, Y##_f); \
- /* Normalize since we know where the msb of the multiplicands \
- were (bit B), we know that the msb of the of the product is \
- at either 2B or 2B-1. */ \
- _FP_FRAC_SRS_2(_Z, wfracbits-1, 2*wfracbits); \
- R##_f = _Z_f0; \
- } while (0)
+ do \
+ { \
+ _FP_FRAC_DECL_2 (_Z); \
+ _FP_MUL_MEAT_DW_1_wide (wfracbits, _Z, X, Y, doit); \
+ /* Normalize since we know where the msb of the multiplicands \
+ were (bit B), we know that the msb of the of the product is \
+ at either 2B or 2B-1. */ \
+ _FP_FRAC_SRS_2 (_Z, wfracbits-1, 2*wfracbits); \
+ R##_f = _Z_f0; \
+ } \
+ while (0)
/* Finally, a simple widening multiply algorithm. What fun! */
-#define _FP_MUL_MEAT_1_hard(wfracbits, R, X, Y) \
- do { \
- _FP_W_TYPE _xh, _xl, _yh, _yl, _z_f0, _z_f1, _a_f0, _a_f1; \
- \
- /* split the words in half */ \
- _xh = X##_f >> (_FP_W_TYPE_SIZE/2); \
- _xl = X##_f & (((_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE/2)) - 1); \
- _yh = Y##_f >> (_FP_W_TYPE_SIZE/2); \
- _yl = Y##_f & (((_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE/2)) - 1); \
+#define _FP_MUL_MEAT_DW_1_hard(wfracbits, R, X, Y) \
+ do \
+ { \
+ _FP_W_TYPE _xh, _xl, _yh, _yl; \
+ _FP_FRAC_DECL_2 (_a); \
\
- /* multiply the pieces */ \
- _z_f0 = _xl * _yl; \
- _a_f0 = _xh * _yl; \
- _a_f1 = _xl * _yh; \
- _z_f1 = _xh * _yh; \
+ /* split the words in half */ \
+ _xh = X##_f >> (_FP_W_TYPE_SIZE/2); \
+ _xl = X##_f & (((_FP_W_TYPE) 1 << (_FP_W_TYPE_SIZE/2)) - 1); \
+ _yh = Y##_f >> (_FP_W_TYPE_SIZE/2); \
+ _yl = Y##_f & (((_FP_W_TYPE) 1 << (_FP_W_TYPE_SIZE/2)) - 1); \
\
- /* reassemble into two full words */ \
- if ((_a_f0 += _a_f1) < _a_f1) \
- _z_f1 += (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE/2); \
- _a_f1 = _a_f0 >> (_FP_W_TYPE_SIZE/2); \
- _a_f0 = _a_f0 << (_FP_W_TYPE_SIZE/2); \
- _FP_FRAC_ADD_2(_z, _z, _a); \
+ /* multiply the pieces */ \
+ R##_f0 = _xl * _yl; \
+ _a_f0 = _xh * _yl; \
+ _a_f1 = _xl * _yh; \
+ R##_f1 = _xh * _yh; \
\
- /* normalize */ \
- _FP_FRAC_SRS_2(_z, wfracbits - 1, 2*wfracbits); \
- R##_f = _z_f0; \
- } while (0)
+ /* reassemble into two full words */ \
+ if ((_a_f0 += _a_f1) < _a_f1) \
+ R##_f1 += (_FP_W_TYPE) 1 << (_FP_W_TYPE_SIZE/2); \
+ _a_f1 = _a_f0 >> (_FP_W_TYPE_SIZE/2); \
+ _a_f0 = _a_f0 << (_FP_W_TYPE_SIZE/2); \
+ _FP_FRAC_ADD_2 (R, R, _a); \
+ } \
+ while (0)
+
+#define _FP_MUL_MEAT_1_hard(wfracbits, R, X, Y) \
+ do \
+ { \
+ _FP_FRAC_DECL_2 (_z); \
+ _FP_MUL_MEAT_DW_1_hard (wfracbits, _z, X, Y); \
+ \
+ /* normalize */ \
+ _FP_FRAC_SRS_2 (_z, wfracbits - 1, 2*wfracbits); \
+ R##_f = _z_f0; \
+ } \
+ while (0)
/*
@@ -199,15 +242,17 @@ do { \
C primitives or _FP_DIV_HELP_ldiv for the ISO function. Which you
choose will depend on what the compiler does with divrem4. */
-#define _FP_DIV_MEAT_1_imm(fs, R, X, Y, doit) \
- do { \
- _FP_W_TYPE _q, _r; \
- X##_f <<= (X##_f < Y##_f \
- ? R##_e--, _FP_WFRACBITS_##fs \
- : _FP_WFRACBITS_##fs - 1); \
- doit(_q, _r, X##_f, Y##_f); \
- R##_f = _q | (_r != 0); \
- } while (0)
+#define _FP_DIV_MEAT_1_imm(fs, R, X, Y, doit) \
+ do \
+ { \
+ _FP_W_TYPE _q, _r; \
+ X##_f <<= (X##_f < Y##_f \
+ ? R##_e--, _FP_WFRACBITS_##fs \
+ : _FP_WFRACBITS_##fs - 1); \
+ doit (_q, _r, X##_f, Y##_f); \
+ R##_f = _q | (_r != 0); \
+ } \
+ while (0)
/* GCC's longlong.h defines a 2W / 1W => (1W,1W) primitive udiv_qrnnd
that may be useful in this situation. This first is for a primitive
@@ -215,46 +260,50 @@ do { \
for UDIV_NEEDS_NORMALIZATION to tell which your machine needs. */
#define _FP_DIV_MEAT_1_udiv_norm(fs, R, X, Y) \
- do { \
- _FP_W_TYPE _nh, _nl, _q, _r, _y; \
+ do \
+ { \
+ _FP_W_TYPE _nh, _nl, _q, _r, _y; \
\
- /* Normalize Y -- i.e. make the most significant bit set. */ \
- _y = Y##_f << _FP_WFRACXBITS_##fs; \
+ /* Normalize Y -- i.e. make the most significant bit set. */ \
+ _y = Y##_f << _FP_WFRACXBITS_##fs; \
\
- /* Shift X op correspondingly high, that is, up one full word. */ \
- if (X##_f < Y##_f) \
- { \
- R##_e--; \
- _nl = 0; \
- _nh = X##_f; \
- } \
- else \
- { \
- _nl = X##_f << (_FP_W_TYPE_SIZE - 1); \
- _nh = X##_f >> 1; \
- } \
+ /* Shift X op correspondingly high, that is, up one full word. */ \
+ if (X##_f < Y##_f) \
+ { \
+ R##_e--; \
+ _nl = 0; \
+ _nh = X##_f; \
+ } \
+ else \
+ { \
+ _nl = X##_f << (_FP_W_TYPE_SIZE - 1); \
+ _nh = X##_f >> 1; \
+ } \
\
- udiv_qrnnd(_q, _r, _nh, _nl, _y); \
- R##_f = _q | (_r != 0); \
- } while (0)
+ udiv_qrnnd (_q, _r, _nh, _nl, _y); \
+ R##_f = _q | (_r != 0); \
+ } \
+ while (0)
#define _FP_DIV_MEAT_1_udiv(fs, R, X, Y) \
- do { \
- _FP_W_TYPE _nh, _nl, _q, _r; \
- if (X##_f < Y##_f) \
- { \
- R##_e--; \
- _nl = X##_f << _FP_WFRACBITS_##fs; \
- _nh = X##_f >> _FP_WFRACXBITS_##fs; \
- } \
- else \
- { \
- _nl = X##_f << (_FP_WFRACBITS_##fs - 1); \
- _nh = X##_f >> (_FP_WFRACXBITS_##fs + 1); \
- } \
- udiv_qrnnd(_q, _r, _nh, _nl, Y##_f); \
- R##_f = _q | (_r != 0); \
- } while (0)
+ do \
+ { \
+ _FP_W_TYPE _nh, _nl, _q, _r; \
+ if (X##_f < Y##_f) \
+ { \
+ R##_e--; \
+ _nl = X##_f << _FP_WFRACBITS_##fs; \
+ _nh = X##_f >> _FP_WFRACXBITS_##fs; \
+ } \
+ else \
+ { \
+ _nl = X##_f << (_FP_WFRACBITS_##fs - 1); \
+ _nh = X##_f >> (_FP_WFRACXBITS_##fs + 1); \
+ } \
+ udiv_qrnnd (_q, _r, _nh, _nl, Y##_f); \
+ R##_f = _q | (_r != 0); \
+ } \
+ while (0)
/*
@@ -263,27 +312,29 @@ do { \
* should be added for those machines where division is fast.
*/
-#define _FP_SQRT_MEAT_1(R, S, T, X, q) \
- do { \
- while (q != _FP_WORK_ROUND) \
- { \
- T##_f = S##_f + q; \
- if (T##_f <= X##_f) \
- { \
- S##_f = T##_f + q; \
- X##_f -= T##_f; \
- R##_f += q; \
- } \
- _FP_FRAC_SLL_1(X, 1); \
- q >>= 1; \
- } \
- if (X##_f) \
- { \
- if (S##_f < X##_f) \
- R##_f |= _FP_WORK_ROUND; \
- R##_f |= _FP_WORK_STICKY; \
- } \
- } while (0)
+#define _FP_SQRT_MEAT_1(R, S, T, X, q) \
+ do \
+ { \
+ while (q != _FP_WORK_ROUND) \
+ { \
+ T##_f = S##_f + q; \
+ if (T##_f <= X##_f) \
+ { \
+ S##_f = T##_f + q; \
+ X##_f -= T##_f; \
+ R##_f += q; \
+ } \
+ _FP_FRAC_SLL_1 (X, 1); \
+ q >>= 1; \
+ } \
+ if (X##_f) \
+ { \
+ if (S##_f < X##_f) \
+ R##_f |= _FP_WORK_ROUND; \
+ R##_f |= _FP_WORK_STICKY; \
+ } \
+ } \
+ while (0)
/*
* Assembly/disassembly for converting to/from integral types.
diff --git a/libgcc/soft-fp/op-2.h b/libgcc/soft-fp/op-2.h
index 48e01d26dc4..5ef4217de12 100644
--- a/libgcc/soft-fp/op-2.h
+++ b/libgcc/soft-fp/op-2.h
@@ -31,109 +31,113 @@
<http://www.gnu.org/licenses/>. */
#define _FP_FRAC_DECL_2(X) _FP_W_TYPE X##_f0, X##_f1
-#define _FP_FRAC_COPY_2(D,S) (D##_f0 = S##_f0, D##_f1 = S##_f1)
-#define _FP_FRAC_SET_2(X,I) __FP_FRAC_SET_2(X, I)
+#define _FP_FRAC_COPY_2(D, S) (D##_f0 = S##_f0, D##_f1 = S##_f1)
+#define _FP_FRAC_SET_2(X, I) __FP_FRAC_SET_2 (X, I)
#define _FP_FRAC_HIGH_2(X) (X##_f1)
#define _FP_FRAC_LOW_2(X) (X##_f0)
-#define _FP_FRAC_WORD_2(X,w) (X##_f##w)
-
-#define _FP_FRAC_SLL_2(X,N) \
-(void)(((N) < _FP_W_TYPE_SIZE) \
- ? ({ \
- if (__builtin_constant_p(N) && (N) == 1) \
- { \
- X##_f1 = X##_f1 + X##_f1 + (((_FP_WS_TYPE)(X##_f0)) < 0); \
- X##_f0 += X##_f0; \
- } \
- else \
- { \
- X##_f1 = X##_f1 << (N) | X##_f0 >> (_FP_W_TYPE_SIZE - (N)); \
- X##_f0 <<= (N); \
- } \
- 0; \
- }) \
- : ({ \
- X##_f1 = X##_f0 << ((N) - _FP_W_TYPE_SIZE); \
- X##_f0 = 0; \
- }))
-
-
-#define _FP_FRAC_SRL_2(X,N) \
-(void)(((N) < _FP_W_TYPE_SIZE) \
- ? ({ \
- X##_f0 = X##_f0 >> (N) | X##_f1 << (_FP_W_TYPE_SIZE - (N)); \
- X##_f1 >>= (N); \
- }) \
- : ({ \
- X##_f0 = X##_f1 >> ((N) - _FP_W_TYPE_SIZE); \
- X##_f1 = 0; \
- }))
+#define _FP_FRAC_WORD_2(X, w) (X##_f##w)
+
+#define _FP_FRAC_SLL_2(X, N) \
+ (void) (((N) < _FP_W_TYPE_SIZE) \
+ ? ({ \
+ if (__builtin_constant_p (N) && (N) == 1) \
+ { \
+ X##_f1 = X##_f1 + X##_f1 + (((_FP_WS_TYPE) (X##_f0)) < 0); \
+ X##_f0 += X##_f0; \
+ } \
+ else \
+ { \
+ X##_f1 = X##_f1 << (N) | X##_f0 >> (_FP_W_TYPE_SIZE - (N)); \
+ X##_f0 <<= (N); \
+ } \
+ 0; \
+ }) \
+ : ({ \
+ X##_f1 = X##_f0 << ((N) - _FP_W_TYPE_SIZE); \
+ X##_f0 = 0; \
+ }))
+
+
+#define _FP_FRAC_SRL_2(X, N) \
+ (void) (((N) < _FP_W_TYPE_SIZE) \
+ ? ({ \
+ X##_f0 = X##_f0 >> (N) | X##_f1 << (_FP_W_TYPE_SIZE - (N)); \
+ X##_f1 >>= (N); \
+ }) \
+ : ({ \
+ X##_f0 = X##_f1 >> ((N) - _FP_W_TYPE_SIZE); \
+ X##_f1 = 0; \
+ }))
/* Right shift with sticky-lsb. */
-#define _FP_FRAC_SRST_2(X,S, N,sz) \
-(void)(((N) < _FP_W_TYPE_SIZE) \
- ? ({ \
- S = (__builtin_constant_p(N) && (N) == 1 \
- ? X##_f0 & 1 \
- : (X##_f0 << (_FP_W_TYPE_SIZE - (N))) != 0); \
- X##_f0 = (X##_f1 << (_FP_W_TYPE_SIZE - (N)) | X##_f0 >> (N)); \
- X##_f1 >>= (N); \
- }) \
- : ({ \
- S = ((((N) == _FP_W_TYPE_SIZE \
- ? 0 \
- : (X##_f1 << (2*_FP_W_TYPE_SIZE - (N)))) \
- | X##_f0) != 0); \
- X##_f0 = (X##_f1 >> ((N) - _FP_W_TYPE_SIZE)); \
- X##_f1 = 0; \
- }))
-
-#define _FP_FRAC_SRS_2(X,N,sz) \
-(void)(((N) < _FP_W_TYPE_SIZE) \
- ? ({ \
- X##_f0 = (X##_f1 << (_FP_W_TYPE_SIZE - (N)) | X##_f0 >> (N) | \
- (__builtin_constant_p(N) && (N) == 1 \
- ? X##_f0 & 1 \
- : (X##_f0 << (_FP_W_TYPE_SIZE - (N))) != 0)); \
- X##_f1 >>= (N); \
- }) \
- : ({ \
- X##_f0 = (X##_f1 >> ((N) - _FP_W_TYPE_SIZE) | \
- ((((N) == _FP_W_TYPE_SIZE \
- ? 0 \
- : (X##_f1 << (2*_FP_W_TYPE_SIZE - (N)))) \
- | X##_f0) != 0)); \
- X##_f1 = 0; \
- }))
-
-#define _FP_FRAC_ADDI_2(X,I) \
- __FP_FRAC_ADDI_2(X##_f1, X##_f0, I)
-
-#define _FP_FRAC_ADD_2(R,X,Y) \
- __FP_FRAC_ADD_2(R##_f1, R##_f0, X##_f1, X##_f0, Y##_f1, Y##_f0)
-
-#define _FP_FRAC_SUB_2(R,X,Y) \
- __FP_FRAC_SUB_2(R##_f1, R##_f0, X##_f1, X##_f0, Y##_f1, Y##_f0)
-
-#define _FP_FRAC_DEC_2(X,Y) \
- __FP_FRAC_DEC_2(X##_f1, X##_f0, Y##_f1, Y##_f0)
-
-#define _FP_FRAC_CLZ_2(R,X) \
- do { \
- if (X##_f1) \
- __FP_CLZ(R,X##_f1); \
- else \
- { \
- __FP_CLZ(R,X##_f0); \
- R += _FP_W_TYPE_SIZE; \
- } \
- } while(0)
+#define _FP_FRAC_SRST_2(X, S, N, sz) \
+ (void) (((N) < _FP_W_TYPE_SIZE) \
+ ? ({ \
+ S = (__builtin_constant_p (N) && (N) == 1 \
+ ? X##_f0 & 1 \
+ : (X##_f0 << (_FP_W_TYPE_SIZE - (N))) != 0); \
+ X##_f0 = (X##_f1 << (_FP_W_TYPE_SIZE - (N)) | X##_f0 >> (N)); \
+ X##_f1 >>= (N); \
+ }) \
+ : ({ \
+ S = ((((N) == _FP_W_TYPE_SIZE \
+ ? 0 \
+ : (X##_f1 << (2*_FP_W_TYPE_SIZE - (N)))) \
+ | X##_f0) != 0); \
+ X##_f0 = (X##_f1 >> ((N) - _FP_W_TYPE_SIZE)); \
+ X##_f1 = 0; \
+ }))
+
+#define _FP_FRAC_SRS_2(X, N, sz) \
+ (void) (((N) < _FP_W_TYPE_SIZE) \
+ ? ({ \
+ X##_f0 = (X##_f1 << (_FP_W_TYPE_SIZE - (N)) | X##_f0 >> (N) \
+ | (__builtin_constant_p (N) && (N) == 1 \
+ ? X##_f0 & 1 \
+ : (X##_f0 << (_FP_W_TYPE_SIZE - (N))) != 0)); \
+ X##_f1 >>= (N); \
+ }) \
+ : ({ \
+ X##_f0 = (X##_f1 >> ((N) - _FP_W_TYPE_SIZE) \
+ | ((((N) == _FP_W_TYPE_SIZE \
+ ? 0 \
+ : (X##_f1 << (2*_FP_W_TYPE_SIZE - (N)))) \
+ | X##_f0) != 0)); \
+ X##_f1 = 0; \
+ }))
+
+#define _FP_FRAC_ADDI_2(X, I) \
+ __FP_FRAC_ADDI_2 (X##_f1, X##_f0, I)
+
+#define _FP_FRAC_ADD_2(R, X, Y) \
+ __FP_FRAC_ADD_2 (R##_f1, R##_f0, X##_f1, X##_f0, Y##_f1, Y##_f0)
+
+#define _FP_FRAC_SUB_2(R, X, Y) \
+ __FP_FRAC_SUB_2 (R##_f1, R##_f0, X##_f1, X##_f0, Y##_f1, Y##_f0)
+
+#define _FP_FRAC_DEC_2(X, Y) \
+ __FP_FRAC_DEC_2 (X##_f1, X##_f0, Y##_f1, Y##_f0)
+
+#define _FP_FRAC_CLZ_2(R, X) \
+ do \
+ { \
+ if (X##_f1) \
+ __FP_CLZ (R, X##_f1); \
+ else \
+ { \
+ __FP_CLZ (R, X##_f0); \
+ R += _FP_W_TYPE_SIZE; \
+ } \
+ } \
+ while (0)
/* Predicates */
-#define _FP_FRAC_NEGP_2(X) ((_FP_WS_TYPE)X##_f1 < 0)
+#define _FP_FRAC_NEGP_2(X) ((_FP_WS_TYPE) X##_f1 < 0)
#define _FP_FRAC_ZEROP_2(X) ((X##_f1 | X##_f0) == 0)
-#define _FP_FRAC_OVERP_2(fs,X) (_FP_FRAC_HIGH_##fs(X) & _FP_OVERFLOW_##fs)
-#define _FP_FRAC_CLEAR_OVERP_2(fs,X) (_FP_FRAC_HIGH_##fs(X) &= ~_FP_OVERFLOW_##fs)
+#define _FP_FRAC_OVERP_2(fs, X) (_FP_FRAC_HIGH_##fs (X) & _FP_OVERFLOW_##fs)
+#define _FP_FRAC_CLEAR_OVERP_2(fs, X) (_FP_FRAC_HIGH_##fs (X) &= ~_FP_OVERFLOW_##fs)
+#define _FP_FRAC_HIGHBIT_DW_2(fs, X) \
+ (_FP_FRAC_HIGH_DW_##fs (X) & _FP_HIGHBIT_DW_##fs)
#define _FP_FRAC_EQ_2(X, Y) (X##_f1 == Y##_f1 && X##_f0 == Y##_f0)
#define _FP_FRAC_GT_2(X, Y) \
(X##_f1 > Y##_f1 || (X##_f1 == Y##_f1 && X##_f0 > Y##_f0))
@@ -142,57 +146,62 @@
#define _FP_ZEROFRAC_2 0, 0
#define _FP_MINFRAC_2 0, 1
-#define _FP_MAXFRAC_2 (~(_FP_WS_TYPE)0), (~(_FP_WS_TYPE)0)
+#define _FP_MAXFRAC_2 (~(_FP_WS_TYPE) 0), (~(_FP_WS_TYPE) 0)
/*
* Internals
*/
-#define __FP_FRAC_SET_2(X,I1,I0) (X##_f0 = I0, X##_f1 = I1)
-
-#define __FP_CLZ_2(R, xh, xl) \
- do { \
- if (xh) \
- __FP_CLZ(R,xh); \
- else \
- { \
- __FP_CLZ(R,xl); \
- R += _FP_W_TYPE_SIZE; \
- } \
- } while(0)
+#define __FP_FRAC_SET_2(X, I1, I0) (X##_f0 = I0, X##_f1 = I1)
+
+#define __FP_CLZ_2(R, xh, xl) \
+ do \
+ { \
+ if (xh) \
+ __FP_CLZ (R, xh); \
+ else \
+ { \
+ __FP_CLZ (R, xl); \
+ R += _FP_W_TYPE_SIZE; \
+ } \
+ } \
+ while (0)
#if 0
-#ifndef __FP_FRAC_ADDI_2
-#define __FP_FRAC_ADDI_2(xh, xl, i) \
+# ifndef __FP_FRAC_ADDI_2
+# define __FP_FRAC_ADDI_2(xh, xl, i) \
(xh += ((xl += i) < i))
-#endif
-#ifndef __FP_FRAC_ADD_2
-#define __FP_FRAC_ADD_2(rh, rl, xh, xl, yh, yl) \
+# endif
+# ifndef __FP_FRAC_ADD_2
+# define __FP_FRAC_ADD_2(rh, rl, xh, xl, yh, yl) \
(rh = xh + yh + ((rl = xl + yl) < xl))
-#endif
-#ifndef __FP_FRAC_SUB_2
-#define __FP_FRAC_SUB_2(rh, rl, xh, xl, yh, yl) \
+# endif
+# ifndef __FP_FRAC_SUB_2
+# define __FP_FRAC_SUB_2(rh, rl, xh, xl, yh, yl) \
(rh = xh - yh - ((rl = xl - yl) > xl))
-#endif
-#ifndef __FP_FRAC_DEC_2
-#define __FP_FRAC_DEC_2(xh, xl, yh, yl) \
- do { \
- UWtype _t = xl; \
- xh -= yh + ((xl -= yl) > _t); \
- } while (0)
-#endif
+# endif
+# ifndef __FP_FRAC_DEC_2
+# define __FP_FRAC_DEC_2(xh, xl, yh, yl) \
+ do \
+ { \
+ UWtype _t = xl; \
+ xh -= yh + ((xl -= yl) > _t); \
+ } \
+ while (0)
+# endif
#else
-#undef __FP_FRAC_ADDI_2
-#define __FP_FRAC_ADDI_2(xh, xl, i) add_ssaaaa(xh, xl, xh, xl, 0, i)
-#undef __FP_FRAC_ADD_2
-#define __FP_FRAC_ADD_2 add_ssaaaa
-#undef __FP_FRAC_SUB_2
-#define __FP_FRAC_SUB_2 sub_ddmmss
-#undef __FP_FRAC_DEC_2
-#define __FP_FRAC_DEC_2(xh, xl, yh, yl) sub_ddmmss(xh, xl, xh, xl, yh, yl)
+# undef __FP_FRAC_ADDI_2
+# define __FP_FRAC_ADDI_2(xh, xl, i) add_ssaaaa (xh, xl, xh, xl, 0, i)
+# undef __FP_FRAC_ADD_2
+# define __FP_FRAC_ADD_2 add_ssaaaa
+# undef __FP_FRAC_SUB_2
+# define __FP_FRAC_SUB_2 sub_ddmmss
+# undef __FP_FRAC_DEC_2
+# define __FP_FRAC_DEC_2(xh, xl, yh, yl) \
+ sub_ddmmss (xh, xl, xh, xl, yh, yl)
#endif
@@ -201,54 +210,61 @@
* normalize the data.
*/
-#define _FP_UNPACK_RAW_2(fs, X, val) \
- do { \
- union _FP_UNION_##fs _flo; _flo.flt = (val); \
- \
- X##_f0 = _flo.bits.frac0; \
- X##_f1 = _flo.bits.frac1; \
- X##_e = _flo.bits.exp; \
- X##_s = _flo.bits.sign; \
- } while (0)
-
-#define _FP_UNPACK_RAW_2_P(fs, X, val) \
- do { \
- union _FP_UNION_##fs *_flo = \
- (union _FP_UNION_##fs *)(val); \
- \
- X##_f0 = _flo->bits.frac0; \
- X##_f1 = _flo->bits.frac1; \
- X##_e = _flo->bits.exp; \
- X##_s = _flo->bits.sign; \
- } while (0)
+#define _FP_UNPACK_RAW_2(fs, X, val) \
+ do \
+ { \
+ union _FP_UNION_##fs _flo; \
+ _flo.flt = (val); \
+ \
+ X##_f0 = _flo.bits.frac0; \
+ X##_f1 = _flo.bits.frac1; \
+ X##_e = _flo.bits.exp; \
+ X##_s = _flo.bits.sign; \
+ } \
+ while (0)
+
+#define _FP_UNPACK_RAW_2_P(fs, X, val) \
+ do \
+ { \
+ union _FP_UNION_##fs *_flo = (union _FP_UNION_##fs *) (val); \
+ \
+ X##_f0 = _flo->bits.frac0; \
+ X##_f1 = _flo->bits.frac1; \
+ X##_e = _flo->bits.exp; \
+ X##_s = _flo->bits.sign; \
+ } \
+ while (0)
/*
* Repack the raw bits of a native fp value.
*/
-#define _FP_PACK_RAW_2(fs, val, X) \
- do { \
- union _FP_UNION_##fs _flo; \
- \
- _flo.bits.frac0 = X##_f0; \
- _flo.bits.frac1 = X##_f1; \
- _flo.bits.exp = X##_e; \
- _flo.bits.sign = X##_s; \
- \
- (val) = _flo.flt; \
- } while (0)
-
-#define _FP_PACK_RAW_2_P(fs, val, X) \
- do { \
- union _FP_UNION_##fs *_flo = \
- (union _FP_UNION_##fs *)(val); \
- \
- _flo->bits.frac0 = X##_f0; \
- _flo->bits.frac1 = X##_f1; \
- _flo->bits.exp = X##_e; \
- _flo->bits.sign = X##_s; \
- } while (0)
+#define _FP_PACK_RAW_2(fs, val, X) \
+ do \
+ { \
+ union _FP_UNION_##fs _flo; \
+ \
+ _flo.bits.frac0 = X##_f0; \
+ _flo.bits.frac1 = X##_f1; \
+ _flo.bits.exp = X##_e; \
+ _flo.bits.sign = X##_s; \
+ \
+ (val) = _flo.flt; \
+ } \
+ while (0)
+
+#define _FP_PACK_RAW_2_P(fs, val, X) \
+ do \
+ { \
+ union _FP_UNION_##fs *_flo = (union _FP_UNION_##fs *) (val); \
+ \
+ _flo->bits.frac0 = X##_f0; \
+ _flo->bits.frac1 = X##_f1; \
+ _flo->bits.exp = X##_e; \
+ _flo->bits.sign = X##_s; \
+ } \
+ while (0)
/*
@@ -257,92 +273,128 @@
/* Given a 1W * 1W => 2W primitive, do the extended multiplication. */
-#define _FP_MUL_MEAT_2_wide(wfracbits, R, X, Y, doit) \
- do { \
- _FP_FRAC_DECL_4(_z); _FP_FRAC_DECL_2(_b); _FP_FRAC_DECL_2(_c); \
+#define _FP_MUL_MEAT_DW_2_wide(wfracbits, R, X, Y, doit) \
+ do \
+ { \
+ _FP_FRAC_DECL_2 (_b); \
+ _FP_FRAC_DECL_2 (_c); \
+ \
+ doit (_FP_FRAC_WORD_4 (R, 1), _FP_FRAC_WORD_4 (R, 0), X##_f0, Y##_f0); \
+ doit (_b_f1, _b_f0, X##_f0, Y##_f1); \
+ doit (_c_f1, _c_f0, X##_f1, Y##_f0); \
+ doit (_FP_FRAC_WORD_4 (R, 3), _FP_FRAC_WORD_4 (R, 2), X##_f1, Y##_f1); \
\
- doit(_FP_FRAC_WORD_4(_z,1), _FP_FRAC_WORD_4(_z,0), X##_f0, Y##_f0); \
- doit(_b_f1, _b_f0, X##_f0, Y##_f1); \
- doit(_c_f1, _c_f0, X##_f1, Y##_f0); \
- doit(_FP_FRAC_WORD_4(_z,3), _FP_FRAC_WORD_4(_z,2), X##_f1, Y##_f1); \
+ __FP_FRAC_ADD_3 (_FP_FRAC_WORD_4 (R, 3), _FP_FRAC_WORD_4 (R, 2), \
+ _FP_FRAC_WORD_4 (R, 1), 0, _b_f1, _b_f0, \
+ _FP_FRAC_WORD_4 (R, 3), _FP_FRAC_WORD_4 (R, 2), \
+ _FP_FRAC_WORD_4 (R, 1)); \
+ __FP_FRAC_ADD_3 (_FP_FRAC_WORD_4 (R, 3), _FP_FRAC_WORD_4 (R, 2), \
+ _FP_FRAC_WORD_4 (R, 1), 0, _c_f1, _c_f0, \
+ _FP_FRAC_WORD_4 (R, 3), _FP_FRAC_WORD_4 (R, 2), \
+ _FP_FRAC_WORD_4 (R, 1)); \
+ } \
+ while (0)
+
+#define _FP_MUL_MEAT_2_wide(wfracbits, R, X, Y, doit) \
+ do \
+ { \
+ _FP_FRAC_DECL_4 (_z); \
\
- __FP_FRAC_ADD_3(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
- _FP_FRAC_WORD_4(_z,1), 0, _b_f1, _b_f0, \
- _FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
- _FP_FRAC_WORD_4(_z,1)); \
- __FP_FRAC_ADD_3(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
- _FP_FRAC_WORD_4(_z,1), 0, _c_f1, _c_f0, \
- _FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
- _FP_FRAC_WORD_4(_z,1)); \
+ _FP_MUL_MEAT_DW_2_wide (wfracbits, _z, X, Y, doit); \
\
- /* Normalize since we know where the msb of the multiplicands \
- were (bit B), we know that the msb of the of the product is \
- at either 2B or 2B-1. */ \
- _FP_FRAC_SRS_4(_z, wfracbits-1, 2*wfracbits); \
- R##_f0 = _FP_FRAC_WORD_4(_z,0); \
- R##_f1 = _FP_FRAC_WORD_4(_z,1); \
- } while (0)
+ /* Normalize since we know where the msb of the multiplicands \
+ were (bit B), we know that the msb of the of the product is \
+ at either 2B or 2B-1. */ \
+ _FP_FRAC_SRS_4 (_z, wfracbits-1, 2*wfracbits); \
+ R##_f0 = _FP_FRAC_WORD_4 (_z, 0); \
+ R##_f1 = _FP_FRAC_WORD_4 (_z, 1); \
+ } \
+ while (0)
/* Given a 1W * 1W => 2W primitive, do the extended multiplication.
Do only 3 multiplications instead of four. This one is for machines
where multiplication is much more expensive than subtraction. */
-#define _FP_MUL_MEAT_2_wide_3mul(wfracbits, R, X, Y, doit) \
- do { \
- _FP_FRAC_DECL_4(_z); _FP_FRAC_DECL_2(_b); _FP_FRAC_DECL_2(_c); \
- _FP_W_TYPE _d; \
- int _c1, _c2; \
+#define _FP_MUL_MEAT_DW_2_wide_3mul(wfracbits, R, X, Y, doit) \
+ do \
+ { \
+ _FP_FRAC_DECL_2 (_b); \
+ _FP_FRAC_DECL_2 (_c); \
+ _FP_W_TYPE _d; \
+ int _c1, _c2; \
\
- _b_f0 = X##_f0 + X##_f1; \
- _c1 = _b_f0 < X##_f0; \
- _b_f1 = Y##_f0 + Y##_f1; \
- _c2 = _b_f1 < Y##_f0; \
- doit(_d, _FP_FRAC_WORD_4(_z,0), X##_f0, Y##_f0); \
- doit(_FP_FRAC_WORD_4(_z,2), _FP_FRAC_WORD_4(_z,1), _b_f0, _b_f1); \
- doit(_c_f1, _c_f0, X##_f1, Y##_f1); \
+ _b_f0 = X##_f0 + X##_f1; \
+ _c1 = _b_f0 < X##_f0; \
+ _b_f1 = Y##_f0 + Y##_f1; \
+ _c2 = _b_f1 < Y##_f0; \
+ doit (_d, _FP_FRAC_WORD_4 (R, 0), X##_f0, Y##_f0); \
+ doit (_FP_FRAC_WORD_4 (R, 2), _FP_FRAC_WORD_4 (R, 1), _b_f0, _b_f1); \
+ doit (_c_f1, _c_f0, X##_f1, Y##_f1); \
\
- _b_f0 &= -_c2; \
- _b_f1 &= -_c1; \
- __FP_FRAC_ADD_3(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
- _FP_FRAC_WORD_4(_z,1), (_c1 & _c2), 0, _d, \
- 0, _FP_FRAC_WORD_4(_z,2), _FP_FRAC_WORD_4(_z,1)); \
- __FP_FRAC_ADDI_2(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
- _b_f0); \
- __FP_FRAC_ADDI_2(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
- _b_f1); \
- __FP_FRAC_DEC_3(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
- _FP_FRAC_WORD_4(_z,1), \
- 0, _d, _FP_FRAC_WORD_4(_z,0)); \
- __FP_FRAC_DEC_3(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
- _FP_FRAC_WORD_4(_z,1), 0, _c_f1, _c_f0); \
- __FP_FRAC_ADD_2(_FP_FRAC_WORD_4(_z,3), _FP_FRAC_WORD_4(_z,2), \
- _c_f1, _c_f0, \
- _FP_FRAC_WORD_4(_z,3), _FP_FRAC_WORD_4(_z,2)); \
+ _b_f0 &= -_c2; \
+ _b_f1 &= -_c1; \
+ __FP_FRAC_ADD_3 (_FP_FRAC_WORD_4 (R, 3), _FP_FRAC_WORD_4 (R, 2), \
+ _FP_FRAC_WORD_4 (R, 1), (_c1 & _c2), 0, _d, \
+ 0, _FP_FRAC_WORD_4 (R, 2), _FP_FRAC_WORD_4 (R, 1)); \
+ __FP_FRAC_ADDI_2 (_FP_FRAC_WORD_4 (R, 3), _FP_FRAC_WORD_4 (R, 2), \
+ _b_f0); \
+ __FP_FRAC_ADDI_2 (_FP_FRAC_WORD_4 (R, 3), _FP_FRAC_WORD_4 (R, 2), \
+ _b_f1); \
+ __FP_FRAC_DEC_3 (_FP_FRAC_WORD_4 (R, 3), _FP_FRAC_WORD_4 (R, 2), \
+ _FP_FRAC_WORD_4 (R, 1), \
+ 0, _d, _FP_FRAC_WORD_4 (R, 0)); \
+ __FP_FRAC_DEC_3 (_FP_FRAC_WORD_4 (R, 3), _FP_FRAC_WORD_4 (R, 2), \
+ _FP_FRAC_WORD_4 (R, 1), 0, _c_f1, _c_f0); \
+ __FP_FRAC_ADD_2 (_FP_FRAC_WORD_4 (R, 3), _FP_FRAC_WORD_4 (R, 2), \
+ _c_f1, _c_f0, \
+ _FP_FRAC_WORD_4 (R, 3), _FP_FRAC_WORD_4 (R, 2)); \
+ } \
+ while (0)
+
+#define _FP_MUL_MEAT_2_wide_3mul(wfracbits, R, X, Y, doit) \
+ do \
+ { \
+ _FP_FRAC_DECL_4 (_z); \
\
- /* Normalize since we know where the msb of the multiplicands \
- were (bit B), we know that the msb of the of the product is \
- at either 2B or 2B-1. */ \
- _FP_FRAC_SRS_4(_z, wfracbits-1, 2*wfracbits); \
- R##_f0 = _FP_FRAC_WORD_4(_z,0); \
- R##_f1 = _FP_FRAC_WORD_4(_z,1); \
- } while (0)
+ _FP_MUL_MEAT_DW_2_wide_3mul (wfracbits, _z, X, Y, doit); \
+ \
+ /* Normalize since we know where the msb of the multiplicands \
+ were (bit B), we know that the msb of the of the product is \
+ at either 2B or 2B-1. */ \
+ _FP_FRAC_SRS_4 (_z, wfracbits-1, 2*wfracbits); \
+ R##_f0 = _FP_FRAC_WORD_4 (_z, 0); \
+ R##_f1 = _FP_FRAC_WORD_4 (_z, 1); \
+ } \
+ while (0)
+
+#define _FP_MUL_MEAT_DW_2_gmp(wfracbits, R, X, Y) \
+ do \
+ { \
+ _FP_W_TYPE _x[2], _y[2]; \
+ _x[0] = X##_f0; \
+ _x[1] = X##_f1; \
+ _y[0] = Y##_f0; \
+ _y[1] = Y##_f1; \
+ \
+ mpn_mul_n (R##_f, _x, _y, 2); \
+ } \
+ while (0)
#define _FP_MUL_MEAT_2_gmp(wfracbits, R, X, Y) \
- do { \
- _FP_FRAC_DECL_4(_z); \
- _FP_W_TYPE _x[2], _y[2]; \
- _x[0] = X##_f0; _x[1] = X##_f1; \
- _y[0] = Y##_f0; _y[1] = Y##_f1; \
+ do \
+ { \
+ _FP_FRAC_DECL_4 (_z); \
\
- mpn_mul_n(_z_f, _x, _y, 2); \
+ _FP_MUL_MEAT_DW_2_gmp (wfracbits, _z, X, Y); \
\
- /* Normalize since we know where the msb of the multiplicands \
- were (bit B), we know that the msb of the of the product is \
- at either 2B or 2B-1. */ \
- _FP_FRAC_SRS_4(_z, wfracbits-1, 2*wfracbits); \
- R##_f0 = _z_f[0]; \
- R##_f1 = _z_f[1]; \
- } while (0)
+ /* Normalize since we know where the msb of the multiplicands \
+ were (bit B), we know that the msb of the of the product is \
+ at either 2B or 2B-1. */ \
+ _FP_FRAC_SRS_4 (_z, wfracbits-1, 2*wfracbits); \
+ R##_f0 = _z_f[0]; \
+ R##_f1 = _z_f[1]; \
+ } \
+ while (0)
/* Do at most 120x120=240 bits multiplication using double floating
point multiplication. This is useful if floating point
@@ -353,190 +405,173 @@
SETFETZ is a macro which will disable all FPU exceptions and set rounding
towards zero, RESETFE should optionally reset it back. */
-#define _FP_MUL_MEAT_2_120_240_double(wfracbits, R, X, Y, setfetz, resetfe) \
- do { \
- static const double _const[] = { \
- /* 2^-24 */ 5.9604644775390625e-08, \
- /* 2^-48 */ 3.5527136788005009e-15, \
- /* 2^-72 */ 2.1175823681357508e-22, \
- /* 2^-96 */ 1.2621774483536189e-29, \
- /* 2^28 */ 2.68435456e+08, \
- /* 2^4 */ 1.600000e+01, \
- /* 2^-20 */ 9.5367431640625e-07, \
- /* 2^-44 */ 5.6843418860808015e-14, \
- /* 2^-68 */ 3.3881317890172014e-21, \
- /* 2^-92 */ 2.0194839173657902e-28, \
- /* 2^-116 */ 1.2037062152420224e-35}; \
- double _a240, _b240, _c240, _d240, _e240, _f240, \
- _g240, _h240, _i240, _j240, _k240; \
- union { double d; UDItype i; } _l240, _m240, _n240, _o240, \
- _p240, _q240, _r240, _s240; \
- UDItype _t240, _u240, _v240, _w240, _x240, _y240 = 0; \
- \
- if (wfracbits < 106 || wfracbits > 120) \
- abort(); \
- \
- setfetz; \
- \
- _e240 = (double)(long)(X##_f0 & 0xffffff); \
- _j240 = (double)(long)(Y##_f0 & 0xffffff); \
- _d240 = (double)(long)((X##_f0 >> 24) & 0xffffff); \
- _i240 = (double)(long)((Y##_f0 >> 24) & 0xffffff); \
- _c240 = (double)(long)(((X##_f1 << 16) & 0xffffff) | (X##_f0 >> 48)); \
- _h240 = (double)(long)(((Y##_f1 << 16) & 0xffffff) | (Y##_f0 >> 48)); \
- _b240 = (double)(long)((X##_f1 >> 8) & 0xffffff); \
- _g240 = (double)(long)((Y##_f1 >> 8) & 0xffffff); \
- _a240 = (double)(long)(X##_f1 >> 32); \
- _f240 = (double)(long)(Y##_f1 >> 32); \
- _e240 *= _const[3]; \
- _j240 *= _const[3]; \
- _d240 *= _const[2]; \
- _i240 *= _const[2]; \
- _c240 *= _const[1]; \
- _h240 *= _const[1]; \
- _b240 *= _const[0]; \
- _g240 *= _const[0]; \
- _s240.d = _e240*_j240;\
- _r240.d = _d240*_j240 + _e240*_i240;\
- _q240.d = _c240*_j240 + _d240*_i240 + _e240*_h240;\
- _p240.d = _b240*_j240 + _c240*_i240 + _d240*_h240 + _e240*_g240;\
- _o240.d = _a240*_j240 + _b240*_i240 + _c240*_h240 + _d240*_g240 + _e240*_f240;\
- _n240.d = _a240*_i240 + _b240*_h240 + _c240*_g240 + _d240*_f240; \
- _m240.d = _a240*_h240 + _b240*_g240 + _c240*_f240; \
- _l240.d = _a240*_g240 + _b240*_f240; \
- _k240 = _a240*_f240; \
- _r240.d += _s240.d; \
- _q240.d += _r240.d; \
- _p240.d += _q240.d; \
- _o240.d += _p240.d; \
- _n240.d += _o240.d; \
- _m240.d += _n240.d; \
- _l240.d += _m240.d; \
- _k240 += _l240.d; \
- _s240.d -= ((_const[10]+_s240.d)-_const[10]); \
- _r240.d -= ((_const[9]+_r240.d)-_const[9]); \
- _q240.d -= ((_const[8]+_q240.d)-_const[8]); \
- _p240.d -= ((_const[7]+_p240.d)-_const[7]); \
- _o240.d += _const[7]; \
- _n240.d += _const[6]; \
- _m240.d += _const[5]; \
- _l240.d += _const[4]; \
- if (_s240.d != 0.0) _y240 = 1; \
- if (_r240.d != 0.0) _y240 = 1; \
- if (_q240.d != 0.0) _y240 = 1; \
- if (_p240.d != 0.0) _y240 = 1; \
- _t240 = (DItype)_k240; \
- _u240 = _l240.i; \
- _v240 = _m240.i; \
- _w240 = _n240.i; \
- _x240 = _o240.i; \
- R##_f1 = (_t240 << (128 - (wfracbits - 1))) \
- | ((_u240 & 0xffffff) >> ((wfracbits - 1) - 104)); \
- R##_f0 = ((_u240 & 0xffffff) << (168 - (wfracbits - 1))) \
- | ((_v240 & 0xffffff) << (144 - (wfracbits - 1))) \
- | ((_w240 & 0xffffff) << (120 - (wfracbits - 1))) \
- | ((_x240 & 0xffffff) >> ((wfracbits - 1) - 96)) \
- | _y240; \
- resetfe; \
- } while (0)
+#define _FP_MUL_MEAT_2_120_240_double(wfracbits, R, X, Y, setfetz, resetfe) \
+ do \
+ { \
+ static const double _const[] = \
+ { \
+ /* 2^-24 */ 5.9604644775390625e-08, \
+ /* 2^-48 */ 3.5527136788005009e-15, \
+ /* 2^-72 */ 2.1175823681357508e-22, \
+ /* 2^-96 */ 1.2621774483536189e-29, \
+ /* 2^28 */ 2.68435456e+08, \
+ /* 2^4 */ 1.600000e+01, \
+ /* 2^-20 */ 9.5367431640625e-07, \
+ /* 2^-44 */ 5.6843418860808015e-14, \
+ /* 2^-68 */ 3.3881317890172014e-21, \
+ /* 2^-92 */ 2.0194839173657902e-28, \
+ /* 2^-116 */ 1.2037062152420224e-35 \
+ }; \
+ double _a240, _b240, _c240, _d240, _e240, _f240, \
+ _g240, _h240, _i240, _j240, _k240; \
+ union { double d; UDItype i; } _l240, _m240, _n240, _o240, \
+ _p240, _q240, _r240, _s240; \
+ UDItype _t240, _u240, _v240, _w240, _x240, _y240 = 0; \
+ \
+ if (wfracbits < 106 || wfracbits > 120) \
+ abort (); \
+ \
+ setfetz; \
+ \
+ _e240 = (double) (long) (X##_f0 & 0xffffff); \
+ _j240 = (double) (long) (Y##_f0 & 0xffffff); \
+ _d240 = (double) (long) ((X##_f0 >> 24) & 0xffffff); \
+ _i240 = (double) (long) ((Y##_f0 >> 24) & 0xffffff); \
+ _c240 = (double) (long) (((X##_f1 << 16) & 0xffffff) | (X##_f0 >> 48)); \
+ _h240 = (double) (long) (((Y##_f1 << 16) & 0xffffff) | (Y##_f0 >> 48)); \
+ _b240 = (double) (long) ((X##_f1 >> 8) & 0xffffff); \
+ _g240 = (double) (long) ((Y##_f1 >> 8) & 0xffffff); \
+ _a240 = (double) (long) (X##_f1 >> 32); \
+ _f240 = (double) (long) (Y##_f1 >> 32); \
+ _e240 *= _const[3]; \
+ _j240 *= _const[3]; \
+ _d240 *= _const[2]; \
+ _i240 *= _const[2]; \
+ _c240 *= _const[1]; \
+ _h240 *= _const[1]; \
+ _b240 *= _const[0]; \
+ _g240 *= _const[0]; \
+ _s240.d = _e240*_j240; \
+ _r240.d = _d240*_j240 + _e240*_i240; \
+ _q240.d = _c240*_j240 + _d240*_i240 + _e240*_h240; \
+ _p240.d = _b240*_j240 + _c240*_i240 + _d240*_h240 + _e240*_g240; \
+ _o240.d = _a240*_j240 + _b240*_i240 + _c240*_h240 + _d240*_g240 + _e240*_f240; \
+ _n240.d = _a240*_i240 + _b240*_h240 + _c240*_g240 + _d240*_f240; \
+ _m240.d = _a240*_h240 + _b240*_g240 + _c240*_f240; \
+ _l240.d = _a240*_g240 + _b240*_f240; \
+ _k240 = _a240*_f240; \
+ _r240.d += _s240.d; \
+ _q240.d += _r240.d; \
+ _p240.d += _q240.d; \
+ _o240.d += _p240.d; \
+ _n240.d += _o240.d; \
+ _m240.d += _n240.d; \
+ _l240.d += _m240.d; \
+ _k240 += _l240.d; \
+ _s240.d -= ((_const[10]+_s240.d)-_const[10]); \
+ _r240.d -= ((_const[9]+_r240.d)-_const[9]); \
+ _q240.d -= ((_const[8]+_q240.d)-_const[8]); \
+ _p240.d -= ((_const[7]+_p240.d)-_const[7]); \
+ _o240.d += _const[7]; \
+ _n240.d += _const[6]; \
+ _m240.d += _const[5]; \
+ _l240.d += _const[4]; \
+ if (_s240.d != 0.0) \
+ _y240 = 1; \
+ if (_r240.d != 0.0) \
+ _y240 = 1; \
+ if (_q240.d != 0.0) \
+ _y240 = 1; \
+ if (_p240.d != 0.0) \
+ _y240 = 1; \
+ _t240 = (DItype) _k240; \
+ _u240 = _l240.i; \
+ _v240 = _m240.i; \
+ _w240 = _n240.i; \
+ _x240 = _o240.i; \
+ R##_f1 = ((_t240 << (128 - (wfracbits - 1))) \
+ | ((_u240 & 0xffffff) >> ((wfracbits - 1) - 104))); \
+ R##_f0 = (((_u240 & 0xffffff) << (168 - (wfracbits - 1))) \
+ | ((_v240 & 0xffffff) << (144 - (wfracbits - 1))) \
+ | ((_w240 & 0xffffff) << (120 - (wfracbits - 1))) \
+ | ((_x240 & 0xffffff) >> ((wfracbits - 1) - 96)) \
+ | _y240); \
+ resetfe; \
+ } \
+ while (0)
/*
* Division algorithms:
*/
#define _FP_DIV_MEAT_2_udiv(fs, R, X, Y) \
- do { \
- _FP_W_TYPE _n_f2, _n_f1, _n_f0, _r_f1, _r_f0, _m_f1, _m_f0; \
- if (_FP_FRAC_GT_2(X, Y)) \
- { \
- _n_f2 = X##_f1 >> 1; \
- _n_f1 = X##_f1 << (_FP_W_TYPE_SIZE - 1) | X##_f0 >> 1; \
- _n_f0 = X##_f0 << (_FP_W_TYPE_SIZE - 1); \
- } \
- else \
- { \
- R##_e--; \
- _n_f2 = X##_f1; \
- _n_f1 = X##_f0; \
- _n_f0 = 0; \
- } \
- \
- /* Normalize, i.e. make the most significant bit of the \
- denominator set. */ \
- _FP_FRAC_SLL_2(Y, _FP_WFRACXBITS_##fs); \
+ do \
+ { \
+ _FP_W_TYPE _n_f2, _n_f1, _n_f0, _r_f1, _r_f0, _m_f1, _m_f0; \
+ if (_FP_FRAC_GE_2 (X, Y)) \
+ { \
+ _n_f2 = X##_f1 >> 1; \
+ _n_f1 = X##_f1 << (_FP_W_TYPE_SIZE - 1) | X##_f0 >> 1; \
+ _n_f0 = X##_f0 << (_FP_W_TYPE_SIZE - 1); \
+ } \
+ else \
+ { \
+ R##_e--; \
+ _n_f2 = X##_f1; \
+ _n_f1 = X##_f0; \
+ _n_f0 = 0; \
+ } \
\
- udiv_qrnnd(R##_f1, _r_f1, _n_f2, _n_f1, Y##_f1); \
- umul_ppmm(_m_f1, _m_f0, R##_f1, Y##_f0); \
- _r_f0 = _n_f0; \
- if (_FP_FRAC_GT_2(_m, _r)) \
- { \
- R##_f1--; \
- _FP_FRAC_ADD_2(_r, Y, _r); \
- if (_FP_FRAC_GE_2(_r, Y) && _FP_FRAC_GT_2(_m, _r)) \
- { \
- R##_f1--; \
- _FP_FRAC_ADD_2(_r, Y, _r); \
- } \
- } \
- _FP_FRAC_DEC_2(_r, _m); \
+ /* Normalize, i.e. make the most significant bit of the \
+ denominator set. */ \
+ _FP_FRAC_SLL_2 (Y, _FP_WFRACXBITS_##fs); \
\
- if (_r_f1 == Y##_f1) \
- { \
- /* This is a special case, not an optimization \
- (_r/Y##_f1 would not fit into UWtype). \
- As _r is guaranteed to be < Y, R##_f0 can be either \
- (UWtype)-1 or (UWtype)-2. But as we know what kind \
- of bits it is (sticky, guard, round), we don't care. \
- We also don't care what the reminder is, because the \
- guard bit will be set anyway. -jj */ \
- R##_f0 = -1; \
- } \
- else \
- { \
- udiv_qrnnd(R##_f0, _r_f1, _r_f1, _r_f0, Y##_f1); \
- umul_ppmm(_m_f1, _m_f0, R##_f0, Y##_f0); \
- _r_f0 = 0; \
- if (_FP_FRAC_GT_2(_m, _r)) \
- { \
- R##_f0--; \
- _FP_FRAC_ADD_2(_r, Y, _r); \
- if (_FP_FRAC_GE_2(_r, Y) && _FP_FRAC_GT_2(_m, _r)) \
- { \
- R##_f0--; \
- _FP_FRAC_ADD_2(_r, Y, _r); \
- } \
- } \
- if (!_FP_FRAC_EQ_2(_r, _m)) \
- R##_f0 |= _FP_WORK_STICKY; \
- } \
- } while (0)
-
-
-#define _FP_DIV_MEAT_2_gmp(fs, R, X, Y) \
- do { \
- _FP_W_TYPE _x[4], _y[2], _z[4]; \
- _y[0] = Y##_f0; _y[1] = Y##_f1; \
- _x[0] = _x[3] = 0; \
- if (_FP_FRAC_GT_2(X, Y)) \
- { \
- R##_e++; \
- _x[1] = (X##_f0 << (_FP_WFRACBITS_##fs-1 - _FP_W_TYPE_SIZE) | \
- X##_f1 >> (_FP_W_TYPE_SIZE - \
- (_FP_WFRACBITS_##fs-1 - _FP_W_TYPE_SIZE))); \
- _x[2] = X##_f1 << (_FP_WFRACBITS_##fs-1 - _FP_W_TYPE_SIZE); \
- } \
- else \
- { \
- _x[1] = (X##_f0 << (_FP_WFRACBITS_##fs - _FP_W_TYPE_SIZE) | \
- X##_f1 >> (_FP_W_TYPE_SIZE - \
- (_FP_WFRACBITS_##fs - _FP_W_TYPE_SIZE))); \
- _x[2] = X##_f1 << (_FP_WFRACBITS_##fs - _FP_W_TYPE_SIZE); \
- } \
+ udiv_qrnnd (R##_f1, _r_f1, _n_f2, _n_f1, Y##_f1); \
+ umul_ppmm (_m_f1, _m_f0, R##_f1, Y##_f0); \
+ _r_f0 = _n_f0; \
+ if (_FP_FRAC_GT_2 (_m, _r)) \
+ { \
+ R##_f1--; \
+ _FP_FRAC_ADD_2 (_r, Y, _r); \
+ if (_FP_FRAC_GE_2 (_r, Y) && _FP_FRAC_GT_2 (_m, _r)) \
+ { \
+ R##_f1--; \
+ _FP_FRAC_ADD_2 (_r, Y, _r); \
+ } \
+ } \
+ _FP_FRAC_DEC_2 (_r, _m); \
\
- (void) mpn_divrem (_z, 0, _x, 4, _y, 2); \
- R##_f1 = _z[1]; \
- R##_f0 = _z[0] | ((_x[0] | _x[1]) != 0); \
- } while (0)
+ if (_r_f1 == Y##_f1) \
+ { \
+ /* This is a special case, not an optimization \
+ (_r/Y##_f1 would not fit into UWtype). \
+ As _r is guaranteed to be < Y, R##_f0 can be either \
+ (UWtype)-1 or (UWtype)-2. But as we know what kind \
+ of bits it is (sticky, guard, round), we don't care. \
+ We also don't care what the reminder is, because the \
+ guard bit will be set anyway. -jj */ \
+ R##_f0 = -1; \
+ } \
+ else \
+ { \
+ udiv_qrnnd (R##_f0, _r_f1, _r_f1, _r_f0, Y##_f1); \
+ umul_ppmm (_m_f1, _m_f0, R##_f0, Y##_f0); \
+ _r_f0 = 0; \
+ if (_FP_FRAC_GT_2 (_m, _r)) \
+ { \
+ R##_f0--; \
+ _FP_FRAC_ADD_2 (_r, Y, _r); \
+ if (_FP_FRAC_GE_2 (_r, Y) && _FP_FRAC_GT_2 (_m, _r)) \
+ { \
+ R##_f0--; \
+ _FP_FRAC_ADD_2 (_r, Y, _r); \
+ } \
+ } \
+ if (!_FP_FRAC_EQ_2 (_r, _m)) \
+ R##_f0 |= _FP_WORK_STICKY; \
+ } \
+ } \
+ while (0)
/*
@@ -545,44 +580,46 @@
* should be added for those machines where division is fast.
*/
-#define _FP_SQRT_MEAT_2(R, S, T, X, q) \
- do { \
- while (q) \
- { \
- T##_f1 = S##_f1 + q; \
- if (T##_f1 <= X##_f1) \
- { \
- S##_f1 = T##_f1 + q; \
- X##_f1 -= T##_f1; \
- R##_f1 += q; \
- } \
- _FP_FRAC_SLL_2(X, 1); \
- q >>= 1; \
- } \
- q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1); \
- while (q != _FP_WORK_ROUND) \
- { \
- T##_f0 = S##_f0 + q; \
- T##_f1 = S##_f1; \
- if (T##_f1 < X##_f1 || \
- (T##_f1 == X##_f1 && T##_f0 <= X##_f0)) \
- { \
- S##_f0 = T##_f0 + q; \
- S##_f1 += (T##_f0 > S##_f0); \
- _FP_FRAC_DEC_2(X, T); \
- R##_f0 += q; \
- } \
- _FP_FRAC_SLL_2(X, 1); \
- q >>= 1; \
- } \
- if (X##_f0 | X##_f1) \
- { \
- if (S##_f1 < X##_f1 || \
- (S##_f1 == X##_f1 && S##_f0 < X##_f0)) \
- R##_f0 |= _FP_WORK_ROUND; \
- R##_f0 |= _FP_WORK_STICKY; \
- } \
- } while (0)
+#define _FP_SQRT_MEAT_2(R, S, T, X, q) \
+ do \
+ { \
+ while (q) \
+ { \
+ T##_f1 = S##_f1 + q; \
+ if (T##_f1 <= X##_f1) \
+ { \
+ S##_f1 = T##_f1 + q; \
+ X##_f1 -= T##_f1; \
+ R##_f1 += q; \
+ } \
+ _FP_FRAC_SLL_2 (X, 1); \
+ q >>= 1; \
+ } \
+ q = (_FP_W_TYPE) 1 << (_FP_W_TYPE_SIZE - 1); \
+ while (q != _FP_WORK_ROUND) \
+ { \
+ T##_f0 = S##_f0 + q; \
+ T##_f1 = S##_f1; \
+ if (T##_f1 < X##_f1 \
+ || (T##_f1 == X##_f1 && T##_f0 <= X##_f0)) \
+ { \
+ S##_f0 = T##_f0 + q; \
+ S##_f1 += (T##_f0 > S##_f0); \
+ _FP_FRAC_DEC_2 (X, T); \
+ R##_f0 += q; \
+ } \
+ _FP_FRAC_SLL_2 (X, 1); \
+ q >>= 1; \
+ } \
+ if (X##_f0 | X##_f1) \
+ { \
+ if (S##_f1 < X##_f1 \
+ || (S##_f1 == X##_f1 && S##_f0 < X##_f0)) \
+ R##_f0 |= _FP_WORK_ROUND; \
+ R##_f0 |= _FP_WORK_STICKY; \
+ } \
+ } \
+ while (0)
/*
@@ -591,19 +628,21 @@
*/
#define _FP_FRAC_ASSEMBLE_2(r, X, rsize) \
-(void)((rsize <= _FP_W_TYPE_SIZE) \
- ? ({ r = X##_f0; }) \
- : ({ \
- r = X##_f1; \
- r <<= _FP_W_TYPE_SIZE; \
- r += X##_f0; \
- }))
+ (void) ((rsize <= _FP_W_TYPE_SIZE) \
+ ? ({ r = X##_f0; }) \
+ : ({ \
+ r = X##_f1; \
+ r <<= _FP_W_TYPE_SIZE; \
+ r += X##_f0; \
+ }))
#define _FP_FRAC_DISASSEMBLE_2(X, r, rsize) \
- do { \
- X##_f0 = r; \
- X##_f1 = (rsize <= _FP_W_TYPE_SIZE ? 0 : r >> _FP_W_TYPE_SIZE); \
- } while (0)
+ do \
+ { \
+ X##_f0 = r; \
+ X##_f1 = (rsize <= _FP_W_TYPE_SIZE ? 0 : r >> _FP_W_TYPE_SIZE); \
+ } \
+ while (0)
/*
* Convert FP values between word sizes
@@ -613,4 +652,4 @@
#define _FP_FRAC_COPY_2_1(D, S) ((D##_f0 = S##_f), (D##_f1 = 0))
-#define _FP_FRAC_COPY_2_2(D,S) _FP_FRAC_COPY_2(D,S)
+#define _FP_FRAC_COPY_2_2(D, S) _FP_FRAC_COPY_2 (D, S)
diff --git a/libgcc/soft-fp/op-4.h b/libgcc/soft-fp/op-4.h
index 007b01f36c8..3515bdc497b 100644
--- a/libgcc/soft-fp/op-4.h
+++ b/libgcc/soft-fp/op-4.h
@@ -31,54 +31,58 @@
<http://www.gnu.org/licenses/>. */
#define _FP_FRAC_DECL_4(X) _FP_W_TYPE X##_f[4]
-#define _FP_FRAC_COPY_4(D,S) \
+#define _FP_FRAC_COPY_4(D, S) \
(D##_f[0] = S##_f[0], D##_f[1] = S##_f[1], \
D##_f[2] = S##_f[2], D##_f[3] = S##_f[3])
-#define _FP_FRAC_SET_4(X,I) __FP_FRAC_SET_4(X, I)
+#define _FP_FRAC_SET_4(X, I) __FP_FRAC_SET_4 (X, I)
#define _FP_FRAC_HIGH_4(X) (X##_f[3])
#define _FP_FRAC_LOW_4(X) (X##_f[0])
-#define _FP_FRAC_WORD_4(X,w) (X##_f[w])
-
-#define _FP_FRAC_SLL_4(X,N) \
- do { \
- _FP_I_TYPE _up, _down, _skip, _i; \
- _skip = (N) / _FP_W_TYPE_SIZE; \
- _up = (N) % _FP_W_TYPE_SIZE; \
- _down = _FP_W_TYPE_SIZE - _up; \
- if (!_up) \
- for (_i = 3; _i >= _skip; --_i) \
- X##_f[_i] = X##_f[_i-_skip]; \
- else \
- { \
- for (_i = 3; _i > _skip; --_i) \
- X##_f[_i] = X##_f[_i-_skip] << _up \
- | X##_f[_i-_skip-1] >> _down; \
- X##_f[_i--] = X##_f[0] << _up; \
- } \
- for (; _i >= 0; --_i) \
- X##_f[_i] = 0; \
- } while (0)
+#define _FP_FRAC_WORD_4(X, w) (X##_f[w])
+
+#define _FP_FRAC_SLL_4(X, N) \
+ do \
+ { \
+ _FP_I_TYPE _up, _down, _skip, _i; \
+ _skip = (N) / _FP_W_TYPE_SIZE; \
+ _up = (N) % _FP_W_TYPE_SIZE; \
+ _down = _FP_W_TYPE_SIZE - _up; \
+ if (!_up) \
+ for (_i = 3; _i >= _skip; --_i) \
+ X##_f[_i] = X##_f[_i-_skip]; \
+ else \
+ { \
+ for (_i = 3; _i > _skip; --_i) \
+ X##_f[_i] = (X##_f[_i-_skip] << _up \
+ | X##_f[_i-_skip-1] >> _down); \
+ X##_f[_i--] = X##_f[0] << _up; \
+ } \
+ for (; _i >= 0; --_i) \
+ X##_f[_i] = 0; \
+ } \
+ while (0)
/* This one was broken too */
-#define _FP_FRAC_SRL_4(X,N) \
- do { \
- _FP_I_TYPE _up, _down, _skip, _i; \
- _skip = (N) / _FP_W_TYPE_SIZE; \
- _down = (N) % _FP_W_TYPE_SIZE; \
- _up = _FP_W_TYPE_SIZE - _down; \
- if (!_down) \
- for (_i = 0; _i <= 3-_skip; ++_i) \
- X##_f[_i] = X##_f[_i+_skip]; \
- else \
- { \
- for (_i = 0; _i < 3-_skip; ++_i) \
- X##_f[_i] = X##_f[_i+_skip] >> _down \
- | X##_f[_i+_skip+1] << _up; \
- X##_f[_i++] = X##_f[3] >> _down; \
- } \
- for (; _i < 4; ++_i) \
- X##_f[_i] = 0; \
- } while (0)
+#define _FP_FRAC_SRL_4(X, N) \
+ do \
+ { \
+ _FP_I_TYPE _up, _down, _skip, _i; \
+ _skip = (N) / _FP_W_TYPE_SIZE; \
+ _down = (N) % _FP_W_TYPE_SIZE; \
+ _up = _FP_W_TYPE_SIZE - _down; \
+ if (!_down) \
+ for (_i = 0; _i <= 3-_skip; ++_i) \
+ X##_f[_i] = X##_f[_i+_skip]; \
+ else \
+ { \
+ for (_i = 0; _i < 3-_skip; ++_i) \
+ X##_f[_i] = (X##_f[_i+_skip] >> _down \
+ | X##_f[_i+_skip+1] << _up); \
+ X##_f[_i++] = X##_f[3] >> _down; \
+ } \
+ for (; _i < 4; ++_i) \
+ X##_f[_i] = 0; \
+ } \
+ while (0)
/* Right shift with sticky-lsb.
@@ -86,159 +90,172 @@
* but that if any of the bits that fall off the right hand side
* were one then we always set the LSbit.
*/
-#define _FP_FRAC_SRST_4(X,S,N,size) \
- do { \
- _FP_I_TYPE _up, _down, _skip, _i; \
- _FP_W_TYPE _s; \
- _skip = (N) / _FP_W_TYPE_SIZE; \
- _down = (N) % _FP_W_TYPE_SIZE; \
- _up = _FP_W_TYPE_SIZE - _down; \
- for (_s = _i = 0; _i < _skip; ++_i) \
- _s |= X##_f[_i]; \
- if (!_down) \
- for (_i = 0; _i <= 3-_skip; ++_i) \
- X##_f[_i] = X##_f[_i+_skip]; \
- else \
- { \
- _s |= X##_f[_i] << _up; \
- for (_i = 0; _i < 3-_skip; ++_i) \
- X##_f[_i] = X##_f[_i+_skip] >> _down \
- | X##_f[_i+_skip+1] << _up; \
- X##_f[_i++] = X##_f[3] >> _down; \
- } \
- for (; _i < 4; ++_i) \
- X##_f[_i] = 0; \
- S = (_s != 0); \
- } while (0)
-
-#define _FP_FRAC_SRS_4(X,N,size) \
- do { \
- int _sticky; \
- _FP_FRAC_SRST_4(X, _sticky, N, size); \
- X##_f[0] |= _sticky; \
- } while (0)
-
-#define _FP_FRAC_ADD_4(R,X,Y) \
- __FP_FRAC_ADD_4(R##_f[3], R##_f[2], R##_f[1], R##_f[0], \
- X##_f[3], X##_f[2], X##_f[1], X##_f[0], \
- Y##_f[3], Y##_f[2], Y##_f[1], Y##_f[0])
-
-#define _FP_FRAC_SUB_4(R,X,Y) \
- __FP_FRAC_SUB_4(R##_f[3], R##_f[2], R##_f[1], R##_f[0], \
- X##_f[3], X##_f[2], X##_f[1], X##_f[0], \
- Y##_f[3], Y##_f[2], Y##_f[1], Y##_f[0])
-
-#define _FP_FRAC_DEC_4(X,Y) \
- __FP_FRAC_DEC_4(X##_f[3], X##_f[2], X##_f[1], X##_f[0], \
- Y##_f[3], Y##_f[2], Y##_f[1], Y##_f[0])
-
-#define _FP_FRAC_ADDI_4(X,I) \
- __FP_FRAC_ADDI_4(X##_f[3], X##_f[2], X##_f[1], X##_f[0], I)
-
-#define _FP_ZEROFRAC_4 0,0,0,0
-#define _FP_MINFRAC_4 0,0,0,1
-#define _FP_MAXFRAC_4 (~(_FP_WS_TYPE)0), (~(_FP_WS_TYPE)0), (~(_FP_WS_TYPE)0), (~(_FP_WS_TYPE)0)
+#define _FP_FRAC_SRST_4(X, S, N, size) \
+ do \
+ { \
+ _FP_I_TYPE _up, _down, _skip, _i; \
+ _FP_W_TYPE _s; \
+ _skip = (N) / _FP_W_TYPE_SIZE; \
+ _down = (N) % _FP_W_TYPE_SIZE; \
+ _up = _FP_W_TYPE_SIZE - _down; \
+ for (_s = _i = 0; _i < _skip; ++_i) \
+ _s |= X##_f[_i]; \
+ if (!_down) \
+ for (_i = 0; _i <= 3-_skip; ++_i) \
+ X##_f[_i] = X##_f[_i+_skip]; \
+ else \
+ { \
+ _s |= X##_f[_i] << _up; \
+ for (_i = 0; _i < 3-_skip; ++_i) \
+ X##_f[_i] = (X##_f[_i+_skip] >> _down \
+ | X##_f[_i+_skip+1] << _up); \
+ X##_f[_i++] = X##_f[3] >> _down; \
+ } \
+ for (; _i < 4; ++_i) \
+ X##_f[_i] = 0; \
+ S = (_s != 0); \
+ } \
+ while (0)
+
+#define _FP_FRAC_SRS_4(X, N, size) \
+ do \
+ { \
+ int _sticky; \
+ _FP_FRAC_SRST_4 (X, _sticky, N, size); \
+ X##_f[0] |= _sticky; \
+ } \
+ while (0)
+
+#define _FP_FRAC_ADD_4(R, X, Y) \
+ __FP_FRAC_ADD_4 (R##_f[3], R##_f[2], R##_f[1], R##_f[0], \
+ X##_f[3], X##_f[2], X##_f[1], X##_f[0], \
+ Y##_f[3], Y##_f[2], Y##_f[1], Y##_f[0])
+
+#define _FP_FRAC_SUB_4(R, X, Y) \
+ __FP_FRAC_SUB_4 (R##_f[3], R##_f[2], R##_f[1], R##_f[0], \
+ X##_f[3], X##_f[2], X##_f[1], X##_f[0], \
+ Y##_f[3], Y##_f[2], Y##_f[1], Y##_f[0])
+
+#define _FP_FRAC_DEC_4(X, Y) \
+ __FP_FRAC_DEC_4 (X##_f[3], X##_f[2], X##_f[1], X##_f[0], \
+ Y##_f[3], Y##_f[2], Y##_f[1], Y##_f[0])
+
+#define _FP_FRAC_ADDI_4(X, I) \
+ __FP_FRAC_ADDI_4 (X##_f[3], X##_f[2], X##_f[1], X##_f[0], I)
+
+#define _FP_ZEROFRAC_4 0, 0, 0, 0
+#define _FP_MINFRAC_4 0, 0, 0, 1
+#define _FP_MAXFRAC_4 (~(_FP_WS_TYPE) 0), (~(_FP_WS_TYPE) 0), (~(_FP_WS_TYPE) 0), (~(_FP_WS_TYPE) 0)
#define _FP_FRAC_ZEROP_4(X) ((X##_f[0] | X##_f[1] | X##_f[2] | X##_f[3]) == 0)
-#define _FP_FRAC_NEGP_4(X) ((_FP_WS_TYPE)X##_f[3] < 0)
-#define _FP_FRAC_OVERP_4(fs,X) (_FP_FRAC_HIGH_##fs(X) & _FP_OVERFLOW_##fs)
-#define _FP_FRAC_CLEAR_OVERP_4(fs,X) (_FP_FRAC_HIGH_##fs(X) &= ~_FP_OVERFLOW_##fs)
-
-#define _FP_FRAC_EQ_4(X,Y) \
- (X##_f[0] == Y##_f[0] && X##_f[1] == Y##_f[1] \
- && X##_f[2] == Y##_f[2] && X##_f[3] == Y##_f[3])
-
-#define _FP_FRAC_GT_4(X,Y) \
- (X##_f[3] > Y##_f[3] || \
- (X##_f[3] == Y##_f[3] && (X##_f[2] > Y##_f[2] || \
- (X##_f[2] == Y##_f[2] && (X##_f[1] > Y##_f[1] || \
- (X##_f[1] == Y##_f[1] && X##_f[0] > Y##_f[0]) \
- )) \
- )) \
- )
-
-#define _FP_FRAC_GE_4(X,Y) \
- (X##_f[3] > Y##_f[3] || \
- (X##_f[3] == Y##_f[3] && (X##_f[2] > Y##_f[2] || \
- (X##_f[2] == Y##_f[2] && (X##_f[1] > Y##_f[1] || \
- (X##_f[1] == Y##_f[1] && X##_f[0] >= Y##_f[0]) \
- )) \
- )) \
- )
-
-
-#define _FP_FRAC_CLZ_4(R,X) \
- do { \
- if (X##_f[3]) \
- { \
- __FP_CLZ(R,X##_f[3]); \
- } \
- else if (X##_f[2]) \
- { \
- __FP_CLZ(R,X##_f[2]); \
- R += _FP_W_TYPE_SIZE; \
- } \
- else if (X##_f[1]) \
- { \
- __FP_CLZ(R,X##_f[1]); \
- R += _FP_W_TYPE_SIZE*2; \
- } \
- else \
- { \
- __FP_CLZ(R,X##_f[0]); \
- R += _FP_W_TYPE_SIZE*3; \
- } \
- } while(0)
-
-
-#define _FP_UNPACK_RAW_4(fs, X, val) \
- do { \
- union _FP_UNION_##fs _flo; _flo.flt = (val); \
- X##_f[0] = _flo.bits.frac0; \
- X##_f[1] = _flo.bits.frac1; \
- X##_f[2] = _flo.bits.frac2; \
- X##_f[3] = _flo.bits.frac3; \
- X##_e = _flo.bits.exp; \
- X##_s = _flo.bits.sign; \
- } while (0)
-
-#define _FP_UNPACK_RAW_4_P(fs, X, val) \
- do { \
- union _FP_UNION_##fs *_flo = \
- (union _FP_UNION_##fs *)(val); \
- \
- X##_f[0] = _flo->bits.frac0; \
- X##_f[1] = _flo->bits.frac1; \
- X##_f[2] = _flo->bits.frac2; \
- X##_f[3] = _flo->bits.frac3; \
- X##_e = _flo->bits.exp; \
- X##_s = _flo->bits.sign; \
- } while (0)
-
-#define _FP_PACK_RAW_4(fs, val, X) \
- do { \
- union _FP_UNION_##fs _flo; \
- _flo.bits.frac0 = X##_f[0]; \
- _flo.bits.frac1 = X##_f[1]; \
- _flo.bits.frac2 = X##_f[2]; \
- _flo.bits.frac3 = X##_f[3]; \
- _flo.bits.exp = X##_e; \
- _flo.bits.sign = X##_s; \
- (val) = _flo.flt; \
- } while (0)
-
-#define _FP_PACK_RAW_4_P(fs, val, X) \
- do { \
- union _FP_UNION_##fs *_flo = \
- (union _FP_UNION_##fs *)(val); \
- \
- _flo->bits.frac0 = X##_f[0]; \
- _flo->bits.frac1 = X##_f[1]; \
- _flo->bits.frac2 = X##_f[2]; \
- _flo->bits.frac3 = X##_f[3]; \
- _flo->bits.exp = X##_e; \
- _flo->bits.sign = X##_s; \
- } while (0)
+#define _FP_FRAC_NEGP_4(X) ((_FP_WS_TYPE) X##_f[3] < 0)
+#define _FP_FRAC_OVERP_4(fs, X) (_FP_FRAC_HIGH_##fs (X) & _FP_OVERFLOW_##fs)
+#define _FP_FRAC_HIGHBIT_DW_4(fs, X) \
+ (_FP_FRAC_HIGH_DW_##fs (X) & _FP_HIGHBIT_DW_##fs)
+#define _FP_FRAC_CLEAR_OVERP_4(fs, X) (_FP_FRAC_HIGH_##fs (X) &= ~_FP_OVERFLOW_##fs)
+
+#define _FP_FRAC_EQ_4(X, Y) \
+ (X##_f[0] == Y##_f[0] && X##_f[1] == Y##_f[1] \
+ && X##_f[2] == Y##_f[2] && X##_f[3] == Y##_f[3])
+
+#define _FP_FRAC_GT_4(X, Y) \
+ (X##_f[3] > Y##_f[3] \
+ || (X##_f[3] == Y##_f[3] \
+ && (X##_f[2] > Y##_f[2] \
+ || (X##_f[2] == Y##_f[2] \
+ && (X##_f[1] > Y##_f[1] \
+ || (X##_f[1] == Y##_f[1] \
+ && X##_f[0] > Y##_f[0]))))))
+
+#define _FP_FRAC_GE_4(X, Y) \
+ (X##_f[3] > Y##_f[3] \
+ || (X##_f[3] == Y##_f[3] \
+ && (X##_f[2] > Y##_f[2] \
+ || (X##_f[2] == Y##_f[2] \
+ && (X##_f[1] > Y##_f[1] \
+ || (X##_f[1] == Y##_f[1] \
+ && X##_f[0] >= Y##_f[0]))))))
+
+
+#define _FP_FRAC_CLZ_4(R, X) \
+ do \
+ { \
+ if (X##_f[3]) \
+ __FP_CLZ (R, X##_f[3]); \
+ else if (X##_f[2]) \
+ { \
+ __FP_CLZ (R, X##_f[2]); \
+ R += _FP_W_TYPE_SIZE; \
+ } \
+ else if (X##_f[1]) \
+ { \
+ __FP_CLZ (R, X##_f[1]); \
+ R += _FP_W_TYPE_SIZE*2; \
+ } \
+ else \
+ { \
+ __FP_CLZ (R, X##_f[0]); \
+ R += _FP_W_TYPE_SIZE*3; \
+ } \
+ } \
+ while (0)
+
+
+#define _FP_UNPACK_RAW_4(fs, X, val) \
+ do \
+ { \
+ union _FP_UNION_##fs _flo; \
+ _flo.flt = (val); \
+ X##_f[0] = _flo.bits.frac0; \
+ X##_f[1] = _flo.bits.frac1; \
+ X##_f[2] = _flo.bits.frac2; \
+ X##_f[3] = _flo.bits.frac3; \
+ X##_e = _flo.bits.exp; \
+ X##_s = _flo.bits.sign; \
+ } \
+ while (0)
+
+#define _FP_UNPACK_RAW_4_P(fs, X, val) \
+ do \
+ { \
+ union _FP_UNION_##fs *_flo = (union _FP_UNION_##fs *) (val); \
+ \
+ X##_f[0] = _flo->bits.frac0; \
+ X##_f[1] = _flo->bits.frac1; \
+ X##_f[2] = _flo->bits.frac2; \
+ X##_f[3] = _flo->bits.frac3; \
+ X##_e = _flo->bits.exp; \
+ X##_s = _flo->bits.sign; \
+ } \
+ while (0)
+
+#define _FP_PACK_RAW_4(fs, val, X) \
+ do \
+ { \
+ union _FP_UNION_##fs _flo; \
+ _flo.bits.frac0 = X##_f[0]; \
+ _flo.bits.frac1 = X##_f[1]; \
+ _flo.bits.frac2 = X##_f[2]; \
+ _flo.bits.frac3 = X##_f[3]; \
+ _flo.bits.exp = X##_e; \
+ _flo.bits.sign = X##_s; \
+ (val) = _flo.flt; \
+ } \
+ while (0)
+
+#define _FP_PACK_RAW_4_P(fs, val, X) \
+ do \
+ { \
+ union _FP_UNION_##fs *_flo = (union _FP_UNION_##fs *) (val); \
+ \
+ _flo->bits.frac0 = X##_f[0]; \
+ _flo->bits.frac1 = X##_f[1]; \
+ _flo->bits.frac2 = X##_f[2]; \
+ _flo->bits.frac3 = X##_f[3]; \
+ _flo->bits.exp = X##_e; \
+ _flo->bits.sign = X##_s; \
+ } \
+ while (0)
/*
* Multiplication algorithms:
@@ -246,188 +263,216 @@
/* Given a 1W * 1W => 2W primitive, do the extended multiplication. */
-#define _FP_MUL_MEAT_4_wide(wfracbits, R, X, Y, doit) \
- do { \
- _FP_FRAC_DECL_8(_z); _FP_FRAC_DECL_2(_b); _FP_FRAC_DECL_2(_c); \
- _FP_FRAC_DECL_2(_d); _FP_FRAC_DECL_2(_e); _FP_FRAC_DECL_2(_f); \
- \
- doit(_FP_FRAC_WORD_8(_z,1), _FP_FRAC_WORD_8(_z,0), X##_f[0], Y##_f[0]); \
- doit(_b_f1, _b_f0, X##_f[0], Y##_f[1]); \
- doit(_c_f1, _c_f0, X##_f[1], Y##_f[0]); \
- doit(_d_f1, _d_f0, X##_f[1], Y##_f[1]); \
- doit(_e_f1, _e_f0, X##_f[0], Y##_f[2]); \
- doit(_f_f1, _f_f0, X##_f[2], Y##_f[0]); \
- __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,3),_FP_FRAC_WORD_8(_z,2), \
- _FP_FRAC_WORD_8(_z,1), 0,_b_f1,_b_f0, \
- 0,0,_FP_FRAC_WORD_8(_z,1)); \
- __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,3),_FP_FRAC_WORD_8(_z,2), \
- _FP_FRAC_WORD_8(_z,1), 0,_c_f1,_c_f0, \
- _FP_FRAC_WORD_8(_z,3),_FP_FRAC_WORD_8(_z,2), \
- _FP_FRAC_WORD_8(_z,1)); \
- __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3), \
- _FP_FRAC_WORD_8(_z,2), 0,_d_f1,_d_f0, \
- 0,_FP_FRAC_WORD_8(_z,3),_FP_FRAC_WORD_8(_z,2)); \
- __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3), \
- _FP_FRAC_WORD_8(_z,2), 0,_e_f1,_e_f0, \
- _FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3), \
- _FP_FRAC_WORD_8(_z,2)); \
- __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3), \
- _FP_FRAC_WORD_8(_z,2), 0,_f_f1,_f_f0, \
- _FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3), \
- _FP_FRAC_WORD_8(_z,2)); \
- doit(_b_f1, _b_f0, X##_f[0], Y##_f[3]); \
- doit(_c_f1, _c_f0, X##_f[3], Y##_f[0]); \
- doit(_d_f1, _d_f0, X##_f[1], Y##_f[2]); \
- doit(_e_f1, _e_f0, X##_f[2], Y##_f[1]); \
- __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \
- _FP_FRAC_WORD_8(_z,3), 0,_b_f1,_b_f0, \
- 0,_FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3)); \
- __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \
- _FP_FRAC_WORD_8(_z,3), 0,_c_f1,_c_f0, \
- _FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \
- _FP_FRAC_WORD_8(_z,3)); \
- __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \
- _FP_FRAC_WORD_8(_z,3), 0,_d_f1,_d_f0, \
- _FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \
- _FP_FRAC_WORD_8(_z,3)); \
- __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \
- _FP_FRAC_WORD_8(_z,3), 0,_e_f1,_e_f0, \
- _FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \
- _FP_FRAC_WORD_8(_z,3)); \
- doit(_b_f1, _b_f0, X##_f[2], Y##_f[2]); \
- doit(_c_f1, _c_f0, X##_f[1], Y##_f[3]); \
- doit(_d_f1, _d_f0, X##_f[3], Y##_f[1]); \
- doit(_e_f1, _e_f0, X##_f[2], Y##_f[3]); \
- doit(_f_f1, _f_f0, X##_f[3], Y##_f[2]); \
- __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5), \
- _FP_FRAC_WORD_8(_z,4), 0,_b_f1,_b_f0, \
- 0,_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4)); \
- __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5), \
- _FP_FRAC_WORD_8(_z,4), 0,_c_f1,_c_f0, \
- _FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5), \
- _FP_FRAC_WORD_8(_z,4)); \
- __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5), \
- _FP_FRAC_WORD_8(_z,4), 0,_d_f1,_d_f0, \
- _FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5), \
- _FP_FRAC_WORD_8(_z,4)); \
- __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6), \
- _FP_FRAC_WORD_8(_z,5), 0,_e_f1,_e_f0, \
- 0,_FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5)); \
- __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6), \
- _FP_FRAC_WORD_8(_z,5), 0,_f_f1,_f_f0, \
- _FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6), \
- _FP_FRAC_WORD_8(_z,5)); \
- doit(_b_f1, _b_f0, X##_f[3], Y##_f[3]); \
- __FP_FRAC_ADD_2(_FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6), \
- _b_f1,_b_f0, \
- _FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6)); \
- \
- /* Normalize since we know where the msb of the multiplicands \
- were (bit B), we know that the msb of the of the product is \
- at either 2B or 2B-1. */ \
- _FP_FRAC_SRS_8(_z, wfracbits-1, 2*wfracbits); \
- __FP_FRAC_SET_4(R, _FP_FRAC_WORD_8(_z,3), _FP_FRAC_WORD_8(_z,2), \
- _FP_FRAC_WORD_8(_z,1), _FP_FRAC_WORD_8(_z,0)); \
- } while (0)
-
-#define _FP_MUL_MEAT_4_gmp(wfracbits, R, X, Y) \
- do { \
- _FP_FRAC_DECL_8(_z); \
- \
- mpn_mul_n(_z_f, _x_f, _y_f, 4); \
- \
- /* Normalize since we know where the msb of the multiplicands \
- were (bit B), we know that the msb of the of the product is \
- at either 2B or 2B-1. */ \
- _FP_FRAC_SRS_8(_z, wfracbits-1, 2*wfracbits); \
- __FP_FRAC_SET_4(R, _FP_FRAC_WORD_8(_z,3), _FP_FRAC_WORD_8(_z,2), \
- _FP_FRAC_WORD_8(_z,1), _FP_FRAC_WORD_8(_z,0)); \
- } while (0)
+#define _FP_MUL_MEAT_DW_4_wide(wfracbits, R, X, Y, doit) \
+ do \
+ { \
+ _FP_FRAC_DECL_2 (_b); \
+ _FP_FRAC_DECL_2 (_c); \
+ _FP_FRAC_DECL_2 (_d); \
+ _FP_FRAC_DECL_2 (_e); \
+ _FP_FRAC_DECL_2 (_f); \
+ \
+ doit (_FP_FRAC_WORD_8 (R, 1), _FP_FRAC_WORD_8 (R, 0), X##_f[0], Y##_f[0]); \
+ doit (_b_f1, _b_f0, X##_f[0], Y##_f[1]); \
+ doit (_c_f1, _c_f0, X##_f[1], Y##_f[0]); \
+ doit (_d_f1, _d_f0, X##_f[1], Y##_f[1]); \
+ doit (_e_f1, _e_f0, X##_f[0], Y##_f[2]); \
+ doit (_f_f1, _f_f0, X##_f[2], Y##_f[0]); \
+ __FP_FRAC_ADD_3 (_FP_FRAC_WORD_8 (R, 3), _FP_FRAC_WORD_8 (R, 2), \
+ _FP_FRAC_WORD_8 (R, 1), 0, _b_f1, _b_f0, \
+ 0, 0, _FP_FRAC_WORD_8 (R, 1)); \
+ __FP_FRAC_ADD_3 (_FP_FRAC_WORD_8 (R, 3), _FP_FRAC_WORD_8 (R, 2), \
+ _FP_FRAC_WORD_8 (R, 1), 0, _c_f1, _c_f0, \
+ _FP_FRAC_WORD_8 (R, 3), _FP_FRAC_WORD_8 (R, 2), \
+ _FP_FRAC_WORD_8 (R, 1)); \
+ __FP_FRAC_ADD_3 (_FP_FRAC_WORD_8 (R, 4), _FP_FRAC_WORD_8 (R, 3), \
+ _FP_FRAC_WORD_8 (R, 2), 0, _d_f1, _d_f0, \
+ 0, _FP_FRAC_WORD_8 (R, 3), _FP_FRAC_WORD_8 (R, 2)); \
+ __FP_FRAC_ADD_3 (_FP_FRAC_WORD_8 (R, 4), _FP_FRAC_WORD_8 (R, 3), \
+ _FP_FRAC_WORD_8 (R, 2), 0, _e_f1, _e_f0, \
+ _FP_FRAC_WORD_8 (R, 4), _FP_FRAC_WORD_8 (R, 3), \
+ _FP_FRAC_WORD_8 (R, 2)); \
+ __FP_FRAC_ADD_3 (_FP_FRAC_WORD_8 (R, 4), _FP_FRAC_WORD_8 (R, 3), \
+ _FP_FRAC_WORD_8 (R, 2), 0, _f_f1, _f_f0, \
+ _FP_FRAC_WORD_8 (R, 4), _FP_FRAC_WORD_8 (R, 3), \
+ _FP_FRAC_WORD_8 (R, 2)); \
+ doit (_b_f1, _b_f0, X##_f[0], Y##_f[3]); \
+ doit (_c_f1, _c_f0, X##_f[3], Y##_f[0]); \
+ doit (_d_f1, _d_f0, X##_f[1], Y##_f[2]); \
+ doit (_e_f1, _e_f0, X##_f[2], Y##_f[1]); \
+ __FP_FRAC_ADD_3 (_FP_FRAC_WORD_8 (R, 5), _FP_FRAC_WORD_8 (R, 4), \
+ _FP_FRAC_WORD_8 (R, 3), 0, _b_f1, _b_f0, \
+ 0, _FP_FRAC_WORD_8 (R, 4), _FP_FRAC_WORD_8 (R, 3)); \
+ __FP_FRAC_ADD_3 (_FP_FRAC_WORD_8 (R, 5), _FP_FRAC_WORD_8 (R, 4), \
+ _FP_FRAC_WORD_8 (R, 3), 0, _c_f1, _c_f0, \
+ _FP_FRAC_WORD_8 (R, 5), _FP_FRAC_WORD_8 (R, 4), \
+ _FP_FRAC_WORD_8 (R, 3)); \
+ __FP_FRAC_ADD_3 (_FP_FRAC_WORD_8 (R, 5), _FP_FRAC_WORD_8 (R, 4), \
+ _FP_FRAC_WORD_8 (R, 3), 0, _d_f1, _d_f0, \
+ _FP_FRAC_WORD_8 (R, 5), _FP_FRAC_WORD_8 (R, 4), \
+ _FP_FRAC_WORD_8 (R, 3)); \
+ __FP_FRAC_ADD_3 (_FP_FRAC_WORD_8 (R, 5), _FP_FRAC_WORD_8 (R, 4), \
+ _FP_FRAC_WORD_8 (R, 3), 0, _e_f1, _e_f0, \
+ _FP_FRAC_WORD_8 (R, 5), _FP_FRAC_WORD_8 (R, 4), \
+ _FP_FRAC_WORD_8 (R, 3)); \
+ doit (_b_f1, _b_f0, X##_f[2], Y##_f[2]); \
+ doit (_c_f1, _c_f0, X##_f[1], Y##_f[3]); \
+ doit (_d_f1, _d_f0, X##_f[3], Y##_f[1]); \
+ doit (_e_f1, _e_f0, X##_f[2], Y##_f[3]); \
+ doit (_f_f1, _f_f0, X##_f[3], Y##_f[2]); \
+ __FP_FRAC_ADD_3 (_FP_FRAC_WORD_8 (R, 6), _FP_FRAC_WORD_8 (R, 5), \
+ _FP_FRAC_WORD_8 (R, 4), 0, _b_f1, _b_f0, \
+ 0, _FP_FRAC_WORD_8 (R, 5), _FP_FRAC_WORD_8 (R, 4)); \
+ __FP_FRAC_ADD_3 (_FP_FRAC_WORD_8 (R, 6), _FP_FRAC_WORD_8 (R, 5), \
+ _FP_FRAC_WORD_8 (R, 4), 0, _c_f1, _c_f0, \
+ _FP_FRAC_WORD_8 (R, 6), _FP_FRAC_WORD_8 (R, 5), \
+ _FP_FRAC_WORD_8 (R, 4)); \
+ __FP_FRAC_ADD_3 (_FP_FRAC_WORD_8 (R, 6), _FP_FRAC_WORD_8 (R, 5), \
+ _FP_FRAC_WORD_8 (R, 4), 0, _d_f1, _d_f0, \
+ _FP_FRAC_WORD_8 (R, 6), _FP_FRAC_WORD_8 (R, 5), \
+ _FP_FRAC_WORD_8 (R, 4)); \
+ __FP_FRAC_ADD_3 (_FP_FRAC_WORD_8 (R, 7), _FP_FRAC_WORD_8 (R, 6), \
+ _FP_FRAC_WORD_8 (R, 5), 0, _e_f1, _e_f0, \
+ 0, _FP_FRAC_WORD_8 (R, 6), _FP_FRAC_WORD_8 (R, 5)); \
+ __FP_FRAC_ADD_3 (_FP_FRAC_WORD_8 (R, 7), _FP_FRAC_WORD_8 (R, 6), \
+ _FP_FRAC_WORD_8 (R, 5), 0, _f_f1, _f_f0, \
+ _FP_FRAC_WORD_8 (R, 7), _FP_FRAC_WORD_8 (R, 6), \
+ _FP_FRAC_WORD_8 (R, 5)); \
+ doit (_b_f1, _b_f0, X##_f[3], Y##_f[3]); \
+ __FP_FRAC_ADD_2 (_FP_FRAC_WORD_8 (R, 7), _FP_FRAC_WORD_8 (R, 6), \
+ _b_f1, _b_f0, \
+ _FP_FRAC_WORD_8 (R, 7), _FP_FRAC_WORD_8 (R, 6)); \
+ } \
+ while (0)
+
+#define _FP_MUL_MEAT_4_wide(wfracbits, R, X, Y, doit) \
+ do \
+ { \
+ _FP_FRAC_DECL_8 (_z); \
+ \
+ _FP_MUL_MEAT_DW_4_wide (wfracbits, _z, X, Y, doit); \
+ \
+ /* Normalize since we know where the msb of the multiplicands \
+ were (bit B), we know that the msb of the of the product is \
+ at either 2B or 2B-1. */ \
+ _FP_FRAC_SRS_8 (_z, wfracbits-1, 2*wfracbits); \
+ __FP_FRAC_SET_4 (R, _FP_FRAC_WORD_8 (_z, 3), _FP_FRAC_WORD_8 (_z, 2), \
+ _FP_FRAC_WORD_8 (_z, 1), _FP_FRAC_WORD_8 (_z, 0)); \
+ } \
+ while (0)
+
+#define _FP_MUL_MEAT_DW_4_gmp(wfracbits, R, X, Y) \
+ do \
+ { \
+ mpn_mul_n (R##_f, _x_f, _y_f, 4); \
+ } \
+ while (0)
+
+#define _FP_MUL_MEAT_4_gmp(wfracbits, R, X, Y) \
+ do \
+ { \
+ _FP_FRAC_DECL_8 (_z); \
+ \
+ _FP_MUL_MEAT_DW_4_gmp (wfracbits, _z, X, Y); \
+ \
+ /* Normalize since we know where the msb of the multiplicands \
+ were (bit B), we know that the msb of the of the product is \
+ at either 2B or 2B-1. */ \
+ _FP_FRAC_SRS_8 (_z, wfracbits-1, 2*wfracbits); \
+ __FP_FRAC_SET_4 (R, _FP_FRAC_WORD_8 (_z, 3), _FP_FRAC_WORD_8 (_z, 2), \
+ _FP_FRAC_WORD_8 (_z, 1), _FP_FRAC_WORD_8 (_z, 0)); \
+ } \
+ while (0)
/*
* Helper utility for _FP_DIV_MEAT_4_udiv:
* pppp = m * nnn
*/
-#define umul_ppppmnnn(p3,p2,p1,p0,m,n2,n1,n0) \
- do { \
- UWtype _t; \
- umul_ppmm(p1,p0,m,n0); \
- umul_ppmm(p2,_t,m,n1); \
- __FP_FRAC_ADDI_2(p2,p1,_t); \
- umul_ppmm(p3,_t,m,n2); \
- __FP_FRAC_ADDI_2(p3,p2,_t); \
- } while (0)
+#define umul_ppppmnnn(p3, p2, p1, p0, m, n2, n1, n0) \
+ do \
+ { \
+ UWtype _t; \
+ umul_ppmm (p1, p0, m, n0); \
+ umul_ppmm (p2, _t, m, n1); \
+ __FP_FRAC_ADDI_2 (p2, p1, _t); \
+ umul_ppmm (p3, _t, m, n2); \
+ __FP_FRAC_ADDI_2 (p3, p2, _t); \
+ } \
+ while (0)
/*
* Division algorithms:
*/
-#define _FP_DIV_MEAT_4_udiv(fs, R, X, Y) \
- do { \
- int _i; \
- _FP_FRAC_DECL_4(_n); _FP_FRAC_DECL_4(_m); \
- _FP_FRAC_SET_4(_n, _FP_ZEROFRAC_4); \
- if (_FP_FRAC_GT_4(X, Y)) \
- { \
- _n_f[3] = X##_f[0] << (_FP_W_TYPE_SIZE - 1); \
- _FP_FRAC_SRL_4(X, 1); \
- } \
- else \
- R##_e--; \
- \
- /* Normalize, i.e. make the most significant bit of the \
- denominator set. */ \
- _FP_FRAC_SLL_4(Y, _FP_WFRACXBITS_##fs); \
- \
- for (_i = 3; ; _i--) \
- { \
- if (X##_f[3] == Y##_f[3]) \
- { \
- /* This is a special case, not an optimization \
- (X##_f[3]/Y##_f[3] would not fit into UWtype). \
- As X## is guaranteed to be < Y, R##_f[_i] can be either \
- (UWtype)-1 or (UWtype)-2. */ \
- R##_f[_i] = -1; \
- if (!_i) \
- break; \
- __FP_FRAC_SUB_4(X##_f[3], X##_f[2], X##_f[1], X##_f[0], \
- Y##_f[2], Y##_f[1], Y##_f[0], 0, \
- X##_f[2], X##_f[1], X##_f[0], _n_f[_i]); \
- _FP_FRAC_SUB_4(X, Y, X); \
- if (X##_f[3] > Y##_f[3]) \
- { \
- R##_f[_i] = -2; \
- _FP_FRAC_ADD_4(X, Y, X); \
- } \
- } \
- else \
- { \
- udiv_qrnnd(R##_f[_i], X##_f[3], X##_f[3], X##_f[2], Y##_f[3]); \
- umul_ppppmnnn(_m_f[3], _m_f[2], _m_f[1], _m_f[0], \
- R##_f[_i], Y##_f[2], Y##_f[1], Y##_f[0]); \
- X##_f[2] = X##_f[1]; \
- X##_f[1] = X##_f[0]; \
- X##_f[0] = _n_f[_i]; \
- if (_FP_FRAC_GT_4(_m, X)) \
- { \
- R##_f[_i]--; \
- _FP_FRAC_ADD_4(X, Y, X); \
- if (_FP_FRAC_GE_4(X, Y) && _FP_FRAC_GT_4(_m, X)) \
- { \
- R##_f[_i]--; \
- _FP_FRAC_ADD_4(X, Y, X); \
- } \
- } \
- _FP_FRAC_DEC_4(X, _m); \
- if (!_i) \
- { \
- if (!_FP_FRAC_EQ_4(X, _m)) \
- R##_f[0] |= _FP_WORK_STICKY; \
- break; \
- } \
- } \
- } \
- } while (0)
+#define _FP_DIV_MEAT_4_udiv(fs, R, X, Y) \
+ do \
+ { \
+ int _i; \
+ _FP_FRAC_DECL_4 (_n); \
+ _FP_FRAC_DECL_4 (_m); \
+ _FP_FRAC_SET_4 (_n, _FP_ZEROFRAC_4); \
+ if (_FP_FRAC_GE_4 (X, Y)) \
+ { \
+ _n_f[3] = X##_f[0] << (_FP_W_TYPE_SIZE - 1); \
+ _FP_FRAC_SRL_4 (X, 1); \
+ } \
+ else \
+ R##_e--; \
+ \
+ /* Normalize, i.e. make the most significant bit of the \
+ denominator set. */ \
+ _FP_FRAC_SLL_4 (Y, _FP_WFRACXBITS_##fs); \
+ \
+ for (_i = 3; ; _i--) \
+ { \
+ if (X##_f[3] == Y##_f[3]) \
+ { \
+ /* This is a special case, not an optimization \
+ (X##_f[3]/Y##_f[3] would not fit into UWtype). \
+ As X## is guaranteed to be < Y, R##_f[_i] can be either \
+ (UWtype)-1 or (UWtype)-2. */ \
+ R##_f[_i] = -1; \
+ if (!_i) \
+ break; \
+ __FP_FRAC_SUB_4 (X##_f[3], X##_f[2], X##_f[1], X##_f[0], \
+ Y##_f[2], Y##_f[1], Y##_f[0], 0, \
+ X##_f[2], X##_f[1], X##_f[0], _n_f[_i]); \
+ _FP_FRAC_SUB_4 (X, Y, X); \
+ if (X##_f[3] > Y##_f[3]) \
+ { \
+ R##_f[_i] = -2; \
+ _FP_FRAC_ADD_4 (X, Y, X); \
+ } \
+ } \
+ else \
+ { \
+ udiv_qrnnd (R##_f[_i], X##_f[3], X##_f[3], X##_f[2], Y##_f[3]); \
+ umul_ppppmnnn (_m_f[3], _m_f[2], _m_f[1], _m_f[0], \
+ R##_f[_i], Y##_f[2], Y##_f[1], Y##_f[0]); \
+ X##_f[2] = X##_f[1]; \
+ X##_f[1] = X##_f[0]; \
+ X##_f[0] = _n_f[_i]; \
+ if (_FP_FRAC_GT_4 (_m, X)) \
+ { \
+ R##_f[_i]--; \
+ _FP_FRAC_ADD_4 (X, Y, X); \
+ if (_FP_FRAC_GE_4 (X, Y) && _FP_FRAC_GT_4 (_m, X)) \
+ { \
+ R##_f[_i]--; \
+ _FP_FRAC_ADD_4 (X, Y, X); \
+ } \
+ } \
+ _FP_FRAC_DEC_4 (X, _m); \
+ if (!_i) \
+ { \
+ if (!_FP_FRAC_EQ_4 (X, _m)) \
+ R##_f[0] |= _FP_WORK_STICKY; \
+ break; \
+ } \
+ } \
+ } \
+ } \
+ while (0)
/*
@@ -436,183 +481,203 @@
* should be added for those machines where division is fast.
*/
-#define _FP_SQRT_MEAT_4(R, S, T, X, q) \
- do { \
- while (q) \
- { \
- T##_f[3] = S##_f[3] + q; \
- if (T##_f[3] <= X##_f[3]) \
- { \
- S##_f[3] = T##_f[3] + q; \
- X##_f[3] -= T##_f[3]; \
- R##_f[3] += q; \
- } \
- _FP_FRAC_SLL_4(X, 1); \
- q >>= 1; \
- } \
- q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1); \
- while (q) \
- { \
- T##_f[2] = S##_f[2] + q; \
- T##_f[3] = S##_f[3]; \
- if (T##_f[3] < X##_f[3] || \
- (T##_f[3] == X##_f[3] && T##_f[2] <= X##_f[2])) \
- { \
- S##_f[2] = T##_f[2] + q; \
- S##_f[3] += (T##_f[2] > S##_f[2]); \
- __FP_FRAC_DEC_2(X##_f[3], X##_f[2], \
- T##_f[3], T##_f[2]); \
- R##_f[2] += q; \
- } \
- _FP_FRAC_SLL_4(X, 1); \
- q >>= 1; \
- } \
- q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1); \
- while (q) \
- { \
- T##_f[1] = S##_f[1] + q; \
- T##_f[2] = S##_f[2]; \
- T##_f[3] = S##_f[3]; \
- if (T##_f[3] < X##_f[3] || \
- (T##_f[3] == X##_f[3] && (T##_f[2] < X##_f[2] || \
- (T##_f[2] == X##_f[2] && T##_f[1] <= X##_f[1])))) \
- { \
- S##_f[1] = T##_f[1] + q; \
- S##_f[2] += (T##_f[1] > S##_f[1]); \
- S##_f[3] += (T##_f[2] > S##_f[2]); \
- __FP_FRAC_DEC_3(X##_f[3], X##_f[2], X##_f[1], \
- T##_f[3], T##_f[2], T##_f[1]); \
- R##_f[1] += q; \
- } \
- _FP_FRAC_SLL_4(X, 1); \
- q >>= 1; \
- } \
- q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1); \
- while (q != _FP_WORK_ROUND) \
- { \
- T##_f[0] = S##_f[0] + q; \
- T##_f[1] = S##_f[1]; \
- T##_f[2] = S##_f[2]; \
- T##_f[3] = S##_f[3]; \
- if (_FP_FRAC_GE_4(X,T)) \
- { \
- S##_f[0] = T##_f[0] + q; \
- S##_f[1] += (T##_f[0] > S##_f[0]); \
- S##_f[2] += (T##_f[1] > S##_f[1]); \
- S##_f[3] += (T##_f[2] > S##_f[2]); \
- _FP_FRAC_DEC_4(X, T); \
- R##_f[0] += q; \
- } \
- _FP_FRAC_SLL_4(X, 1); \
- q >>= 1; \
- } \
- if (!_FP_FRAC_ZEROP_4(X)) \
- { \
- if (_FP_FRAC_GT_4(X,S)) \
- R##_f[0] |= _FP_WORK_ROUND; \
- R##_f[0] |= _FP_WORK_STICKY; \
- } \
- } while (0)
+#define _FP_SQRT_MEAT_4(R, S, T, X, q) \
+ do \
+ { \
+ while (q) \
+ { \
+ T##_f[3] = S##_f[3] + q; \
+ if (T##_f[3] <= X##_f[3]) \
+ { \
+ S##_f[3] = T##_f[3] + q; \
+ X##_f[3] -= T##_f[3]; \
+ R##_f[3] += q; \
+ } \
+ _FP_FRAC_SLL_4 (X, 1); \
+ q >>= 1; \
+ } \
+ q = (_FP_W_TYPE) 1 << (_FP_W_TYPE_SIZE - 1); \
+ while (q) \
+ { \
+ T##_f[2] = S##_f[2] + q; \
+ T##_f[3] = S##_f[3]; \
+ if (T##_f[3] < X##_f[3] \
+ || (T##_f[3] == X##_f[3] && T##_f[2] <= X##_f[2])) \
+ { \
+ S##_f[2] = T##_f[2] + q; \
+ S##_f[3] += (T##_f[2] > S##_f[2]); \
+ __FP_FRAC_DEC_2 (X##_f[3], X##_f[2], \
+ T##_f[3], T##_f[2]); \
+ R##_f[2] += q; \
+ } \
+ _FP_FRAC_SLL_4 (X, 1); \
+ q >>= 1; \
+ } \
+ q = (_FP_W_TYPE) 1 << (_FP_W_TYPE_SIZE - 1); \
+ while (q) \
+ { \
+ T##_f[1] = S##_f[1] + q; \
+ T##_f[2] = S##_f[2]; \
+ T##_f[3] = S##_f[3]; \
+ if (T##_f[3] < X##_f[3] \
+ || (T##_f[3] == X##_f[3] \
+ && (T##_f[2] < X##_f[2] \
+ || (T##_f[2] == X##_f[2] \
+ && T##_f[1] <= X##_f[1])))) \
+ { \
+ S##_f[1] = T##_f[1] + q; \
+ S##_f[2] += (T##_f[1] > S##_f[1]); \
+ S##_f[3] += (T##_f[2] > S##_f[2]); \
+ __FP_FRAC_DEC_3 (X##_f[3], X##_f[2], X##_f[1], \
+ T##_f[3], T##_f[2], T##_f[1]); \
+ R##_f[1] += q; \
+ } \
+ _FP_FRAC_SLL_4 (X, 1); \
+ q >>= 1; \
+ } \
+ q = (_FP_W_TYPE) 1 << (_FP_W_TYPE_SIZE - 1); \
+ while (q != _FP_WORK_ROUND) \
+ { \
+ T##_f[0] = S##_f[0] + q; \
+ T##_f[1] = S##_f[1]; \
+ T##_f[2] = S##_f[2]; \
+ T##_f[3] = S##_f[3]; \
+ if (_FP_FRAC_GE_4 (X, T)) \
+ { \
+ S##_f[0] = T##_f[0] + q; \
+ S##_f[1] += (T##_f[0] > S##_f[0]); \
+ S##_f[2] += (T##_f[1] > S##_f[1]); \
+ S##_f[3] += (T##_f[2] > S##_f[2]); \
+ _FP_FRAC_DEC_4 (X, T); \
+ R##_f[0] += q; \
+ } \
+ _FP_FRAC_SLL_4 (X, 1); \
+ q >>= 1; \
+ } \
+ if (!_FP_FRAC_ZEROP_4 (X)) \
+ { \
+ if (_FP_FRAC_GT_4 (X, S)) \
+ R##_f[0] |= _FP_WORK_ROUND; \
+ R##_f[0] |= _FP_WORK_STICKY; \
+ } \
+ } \
+ while (0)
/*
* Internals
*/
-#define __FP_FRAC_SET_4(X,I3,I2,I1,I0) \
+#define __FP_FRAC_SET_4(X, I3, I2, I1, I0) \
(X##_f[3] = I3, X##_f[2] = I2, X##_f[1] = I1, X##_f[0] = I0)
#ifndef __FP_FRAC_ADD_3
-#define __FP_FRAC_ADD_3(r2,r1,r0,x2,x1,x0,y2,y1,y0) \
- do { \
- _FP_W_TYPE _c1, _c2; \
- r0 = x0 + y0; \
- _c1 = r0 < x0; \
- r1 = x1 + y1; \
- _c2 = r1 < x1; \
- r1 += _c1; \
- _c2 |= r1 < _c1; \
- r2 = x2 + y2 + _c2; \
- } while (0)
+# define __FP_FRAC_ADD_3(r2, r1, r0, x2, x1, x0, y2, y1, y0) \
+ do \
+ { \
+ _FP_W_TYPE __FP_FRAC_ADD_3_c1, __FP_FRAC_ADD_3_c2; \
+ r0 = x0 + y0; \
+ __FP_FRAC_ADD_3_c1 = r0 < x0; \
+ r1 = x1 + y1; \
+ __FP_FRAC_ADD_3_c2 = r1 < x1; \
+ r1 += __FP_FRAC_ADD_3_c1; \
+ __FP_FRAC_ADD_3_c2 |= r1 < __FP_FRAC_ADD_3_c1; \
+ r2 = x2 + y2 + __FP_FRAC_ADD_3_c2; \
+ } \
+ while (0)
#endif
#ifndef __FP_FRAC_ADD_4
-#define __FP_FRAC_ADD_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0) \
- do { \
- _FP_W_TYPE _c1, _c2, _c3; \
- r0 = x0 + y0; \
- _c1 = r0 < x0; \
- r1 = x1 + y1; \
- _c2 = r1 < x1; \
- r1 += _c1; \
- _c2 |= r1 < _c1; \
- r2 = x2 + y2; \
- _c3 = r2 < x2; \
- r2 += _c2; \
- _c3 |= r2 < _c2; \
- r3 = x3 + y3 + _c3; \
- } while (0)
+# define __FP_FRAC_ADD_4(r3, r2, r1, r0, x3, x2, x1, x0, y3, y2, y1, y0) \
+ do \
+ { \
+ _FP_W_TYPE _c1, _c2, _c3; \
+ r0 = x0 + y0; \
+ _c1 = r0 < x0; \
+ r1 = x1 + y1; \
+ _c2 = r1 < x1; \
+ r1 += _c1; \
+ _c2 |= r1 < _c1; \
+ r2 = x2 + y2; \
+ _c3 = r2 < x2; \
+ r2 += _c2; \
+ _c3 |= r2 < _c2; \
+ r3 = x3 + y3 + _c3; \
+ } \
+ while (0)
#endif
#ifndef __FP_FRAC_SUB_3
-#define __FP_FRAC_SUB_3(r2,r1,r0,x2,x1,x0,y2,y1,y0) \
- do { \
- _FP_W_TYPE _c1, _c2; \
- r0 = x0 - y0; \
- _c1 = r0 > x0; \
- r1 = x1 - y1; \
- _c2 = r1 > x1; \
- r1 -= _c1; \
- _c2 |= _c1 && (y1 == x1); \
- r2 = x2 - y2 - _c2; \
- } while (0)
+# define __FP_FRAC_SUB_3(r2, r1, r0, x2, x1, x0, y2, y1, y0) \
+ do \
+ { \
+ _FP_W_TYPE _c1, _c2; \
+ r0 = x0 - y0; \
+ _c1 = r0 > x0; \
+ r1 = x1 - y1; \
+ _c2 = r1 > x1; \
+ r1 -= _c1; \
+ _c2 |= _c1 && (y1 == x1); \
+ r2 = x2 - y2 - _c2; \
+ } \
+ while (0)
#endif
#ifndef __FP_FRAC_SUB_4
-#define __FP_FRAC_SUB_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0) \
- do { \
- _FP_W_TYPE _c1, _c2, _c3; \
- r0 = x0 - y0; \
- _c1 = r0 > x0; \
- r1 = x1 - y1; \
- _c2 = r1 > x1; \
- r1 -= _c1; \
- _c2 |= _c1 && (y1 == x1); \
- r2 = x2 - y2; \
- _c3 = r2 > x2; \
- r2 -= _c2; \
- _c3 |= _c2 && (y2 == x2); \
- r3 = x3 - y3 - _c3; \
- } while (0)
+# define __FP_FRAC_SUB_4(r3, r2, r1, r0, x3, x2, x1, x0, y3, y2, y1, y0) \
+ do \
+ { \
+ _FP_W_TYPE _c1, _c2, _c3; \
+ r0 = x0 - y0; \
+ _c1 = r0 > x0; \
+ r1 = x1 - y1; \
+ _c2 = r1 > x1; \
+ r1 -= _c1; \
+ _c2 |= _c1 && (y1 == x1); \
+ r2 = x2 - y2; \
+ _c3 = r2 > x2; \
+ r2 -= _c2; \
+ _c3 |= _c2 && (y2 == x2); \
+ r3 = x3 - y3 - _c3; \
+ } \
+ while (0)
#endif
#ifndef __FP_FRAC_DEC_3
-#define __FP_FRAC_DEC_3(x2,x1,x0,y2,y1,y0) \
- do { \
- UWtype _t0, _t1, _t2; \
- _t0 = x0, _t1 = x1, _t2 = x2; \
- __FP_FRAC_SUB_3 (x2, x1, x0, _t2, _t1, _t0, y2, y1, y0); \
- } while (0)
+# define __FP_FRAC_DEC_3(x2, x1, x0, y2, y1, y0) \
+ do \
+ { \
+ UWtype _t0, _t1, _t2; \
+ _t0 = x0, _t1 = x1, _t2 = x2; \
+ __FP_FRAC_SUB_3 (x2, x1, x0, _t2, _t1, _t0, y2, y1, y0); \
+ } \
+ while (0)
#endif
#ifndef __FP_FRAC_DEC_4
-#define __FP_FRAC_DEC_4(x3,x2,x1,x0,y3,y2,y1,y0) \
- do { \
- UWtype _t0, _t1, _t2, _t3; \
- _t0 = x0, _t1 = x1, _t2 = x2, _t3 = x3; \
- __FP_FRAC_SUB_4 (x3,x2,x1,x0,_t3,_t2,_t1,_t0, y3,y2,y1,y0); \
- } while (0)
+# define __FP_FRAC_DEC_4(x3, x2, x1, x0, y3, y2, y1, y0) \
+ do \
+ { \
+ UWtype _t0, _t1, _t2, _t3; \
+ _t0 = x0, _t1 = x1, _t2 = x2, _t3 = x3; \
+ __FP_FRAC_SUB_4 (x3, x2, x1, x0, _t3, _t2, _t1, _t0, y3, y2, y1, y0); \
+ } \
+ while (0)
#endif
#ifndef __FP_FRAC_ADDI_4
-#define __FP_FRAC_ADDI_4(x3,x2,x1,x0,i) \
- do { \
- UWtype _t; \
- _t = ((x0 += i) < i); \
- x1 += _t; _t = (x1 < _t); \
- x2 += _t; _t = (x2 < _t); \
- x3 += _t; \
- } while (0)
+# define __FP_FRAC_ADDI_4(x3, x2, x1, x0, i) \
+ do \
+ { \
+ UWtype _t; \
+ _t = ((x0 += i) < i); \
+ x1 += _t; \
+ _t = (x1 < _t); \
+ x2 += _t; \
+ _t = (x2 < _t); \
+ x3 += _t; \
+ } \
+ while (0)
#endif
/* Convert FP values between word sizes. This appears to be more
@@ -625,38 +690,42 @@
#define _FP_FRAC_COPY_1_4(D, S) (D##_f = S##_f[0])
#define _FP_FRAC_COPY_2_4(D, S) \
-do { \
- D##_f0 = S##_f[0]; \
- D##_f1 = S##_f[1]; \
-} while (0)
+ do \
+ { \
+ D##_f0 = S##_f[0]; \
+ D##_f1 = S##_f[1]; \
+ } \
+ while (0)
/* Assembly/disassembly for converting to/from integral types.
* No shifting or overflow handled here.
*/
/* Put the FP value X into r, which is an integer of size rsize. */
#define _FP_FRAC_ASSEMBLE_4(r, X, rsize) \
- do { \
- if (rsize <= _FP_W_TYPE_SIZE) \
- r = X##_f[0]; \
- else if (rsize <= 2*_FP_W_TYPE_SIZE) \
- { \
- r = X##_f[1]; \
- r <<= _FP_W_TYPE_SIZE; \
- r += X##_f[0]; \
- } \
- else \
+ do \
{ \
- /* I'm feeling lazy so we deal with int == 3words (implausible)*/ \
- /* and int == 4words as a single case. */ \
- r = X##_f[3]; \
- r <<= _FP_W_TYPE_SIZE; \
- r += X##_f[2]; \
- r <<= _FP_W_TYPE_SIZE; \
- r += X##_f[1]; \
- r <<= _FP_W_TYPE_SIZE; \
- r += X##_f[0]; \
+ if (rsize <= _FP_W_TYPE_SIZE) \
+ r = X##_f[0]; \
+ else if (rsize <= 2*_FP_W_TYPE_SIZE) \
+ { \
+ r = X##_f[1]; \
+ r <<= _FP_W_TYPE_SIZE; \
+ r += X##_f[0]; \
+ } \
+ else \
+ { \
+ /* I'm feeling lazy so we deal with int == 3words (implausible)*/ \
+ /* and int == 4words as a single case. */ \
+ r = X##_f[3]; \
+ r <<= _FP_W_TYPE_SIZE; \
+ r += X##_f[2]; \
+ r <<= _FP_W_TYPE_SIZE; \
+ r += X##_f[1]; \
+ r <<= _FP_W_TYPE_SIZE; \
+ r += X##_f[0]; \
+ } \
} \
- } while (0)
+ while (0)
/* "No disassemble Number Five!" */
/* move an integer of size rsize into X's fractional part. We rely on
@@ -664,24 +733,30 @@ do { \
* having to mask the values we store into it.
*/
#define _FP_FRAC_DISASSEMBLE_4(X, r, rsize) \
- do { \
- X##_f[0] = r; \
- X##_f[1] = (rsize <= _FP_W_TYPE_SIZE ? 0 : r >> _FP_W_TYPE_SIZE); \
- X##_f[2] = (rsize <= 2*_FP_W_TYPE_SIZE ? 0 : r >> 2*_FP_W_TYPE_SIZE); \
- X##_f[3] = (rsize <= 3*_FP_W_TYPE_SIZE ? 0 : r >> 3*_FP_W_TYPE_SIZE); \
- } while (0);
+ do \
+ { \
+ X##_f[0] = r; \
+ X##_f[1] = (rsize <= _FP_W_TYPE_SIZE ? 0 : r >> _FP_W_TYPE_SIZE); \
+ X##_f[2] = (rsize <= 2*_FP_W_TYPE_SIZE ? 0 : r >> 2*_FP_W_TYPE_SIZE); \
+ X##_f[3] = (rsize <= 3*_FP_W_TYPE_SIZE ? 0 : r >> 3*_FP_W_TYPE_SIZE); \
+ } \
+ while (0)
#define _FP_FRAC_COPY_4_1(D, S) \
-do { \
- D##_f[0] = S##_f; \
- D##_f[1] = D##_f[2] = D##_f[3] = 0; \
-} while (0)
+ do \
+ { \
+ D##_f[0] = S##_f; \
+ D##_f[1] = D##_f[2] = D##_f[3] = 0; \
+ } \
+ while (0)
#define _FP_FRAC_COPY_4_2(D, S) \
-do { \
- D##_f[0] = S##_f0; \
- D##_f[1] = S##_f1; \
- D##_f[2] = D##_f[3] = 0; \
-} while (0)
-
-#define _FP_FRAC_COPY_4_4(D,S) _FP_FRAC_COPY_4(D,S)
+ do \
+ { \
+ D##_f[0] = S##_f0; \
+ D##_f[1] = S##_f1; \
+ D##_f[2] = D##_f[3] = 0; \
+ } \
+ while (0)
+
+#define _FP_FRAC_COPY_4_4(D, S) _FP_FRAC_COPY_4 (D, S)
diff --git a/libgcc/soft-fp/op-8.h b/libgcc/soft-fp/op-8.h
index 8890d02201c..f1b23db80db 100644
--- a/libgcc/soft-fp/op-8.h
+++ b/libgcc/soft-fp/op-8.h
@@ -34,47 +34,51 @@
#define _FP_FRAC_DECL_8(X) _FP_W_TYPE X##_f[8]
#define _FP_FRAC_HIGH_8(X) (X##_f[7])
#define _FP_FRAC_LOW_8(X) (X##_f[0])
-#define _FP_FRAC_WORD_8(X,w) (X##_f[w])
+#define _FP_FRAC_WORD_8(X, w) (X##_f[w])
-#define _FP_FRAC_SLL_8(X,N) \
- do { \
- _FP_I_TYPE _up, _down, _skip, _i; \
- _skip = (N) / _FP_W_TYPE_SIZE; \
- _up = (N) % _FP_W_TYPE_SIZE; \
- _down = _FP_W_TYPE_SIZE - _up; \
- if (!_up) \
- for (_i = 7; _i >= _skip; --_i) \
- X##_f[_i] = X##_f[_i-_skip]; \
- else \
- { \
- for (_i = 7; _i > _skip; --_i) \
- X##_f[_i] = X##_f[_i-_skip] << _up \
- | X##_f[_i-_skip-1] >> _down; \
- X##_f[_i--] = X##_f[0] << _up; \
- } \
- for (; _i >= 0; --_i) \
- X##_f[_i] = 0; \
- } while (0)
+#define _FP_FRAC_SLL_8(X, N) \
+ do \
+ { \
+ _FP_I_TYPE _up, _down, _skip, _i; \
+ _skip = (N) / _FP_W_TYPE_SIZE; \
+ _up = (N) % _FP_W_TYPE_SIZE; \
+ _down = _FP_W_TYPE_SIZE - _up; \
+ if (!_up) \
+ for (_i = 7; _i >= _skip; --_i) \
+ X##_f[_i] = X##_f[_i-_skip]; \
+ else \
+ { \
+ for (_i = 7; _i > _skip; --_i) \
+ X##_f[_i] = (X##_f[_i-_skip] << _up \
+ | X##_f[_i-_skip-1] >> _down); \
+ X##_f[_i--] = X##_f[0] << _up; \
+ } \
+ for (; _i >= 0; --_i) \
+ X##_f[_i] = 0; \
+ } \
+ while (0)
-#define _FP_FRAC_SRL_8(X,N) \
- do { \
- _FP_I_TYPE _up, _down, _skip, _i; \
- _skip = (N) / _FP_W_TYPE_SIZE; \
- _down = (N) % _FP_W_TYPE_SIZE; \
- _up = _FP_W_TYPE_SIZE - _down; \
- if (!_down) \
- for (_i = 0; _i <= 7-_skip; ++_i) \
- X##_f[_i] = X##_f[_i+_skip]; \
- else \
- { \
- for (_i = 0; _i < 7-_skip; ++_i) \
- X##_f[_i] = X##_f[_i+_skip] >> _down \
- | X##_f[_i+_skip+1] << _up; \
- X##_f[_i++] = X##_f[7] >> _down; \
- } \
- for (; _i < 8; ++_i) \
- X##_f[_i] = 0; \
- } while (0)
+#define _FP_FRAC_SRL_8(X, N) \
+ do \
+ { \
+ _FP_I_TYPE _up, _down, _skip, _i; \
+ _skip = (N) / _FP_W_TYPE_SIZE; \
+ _down = (N) % _FP_W_TYPE_SIZE; \
+ _up = _FP_W_TYPE_SIZE - _down; \
+ if (!_down) \
+ for (_i = 0; _i <= 7-_skip; ++_i) \
+ X##_f[_i] = X##_f[_i+_skip]; \
+ else \
+ { \
+ for (_i = 0; _i < 7-_skip; ++_i) \
+ X##_f[_i] = (X##_f[_i+_skip] >> _down \
+ | X##_f[_i+_skip+1] << _up); \
+ X##_f[_i++] = X##_f[7] >> _down; \
+ } \
+ for (; _i < 8; ++_i) \
+ X##_f[_i] = 0; \
+ } \
+ while (0)
/* Right shift with sticky-lsb.
@@ -82,28 +86,31 @@
* but that if any of the bits that fall off the right hand side
* were one then we always set the LSbit.
*/
-#define _FP_FRAC_SRS_8(X,N,size) \
- do { \
- _FP_I_TYPE _up, _down, _skip, _i; \
- _FP_W_TYPE _s; \
- _skip = (N) / _FP_W_TYPE_SIZE; \
- _down = (N) % _FP_W_TYPE_SIZE; \
- _up = _FP_W_TYPE_SIZE - _down; \
- for (_s = _i = 0; _i < _skip; ++_i) \
- _s |= X##_f[_i]; \
- if (!_down) \
- for (_i = 0; _i <= 7-_skip; ++_i) \
- X##_f[_i] = X##_f[_i+_skip]; \
- else \
- { \
- _s |= X##_f[_i] << _up; \
- for (_i = 0; _i < 7-_skip; ++_i) \
- X##_f[_i] = X##_f[_i+_skip] >> _down \
- | X##_f[_i+_skip+1] << _up; \
- X##_f[_i++] = X##_f[7] >> _down; \
- } \
- for (; _i < 8; ++_i) \
- X##_f[_i] = 0; \
- /* don't fix the LSB until the very end when we're sure f[0] is stable */ \
- X##_f[0] |= (_s != 0); \
- } while (0)
+#define _FP_FRAC_SRS_8(X, N, size) \
+ do \
+ { \
+ _FP_I_TYPE _up, _down, _skip, _i; \
+ _FP_W_TYPE _s; \
+ _skip = (N) / _FP_W_TYPE_SIZE; \
+ _down = (N) % _FP_W_TYPE_SIZE; \
+ _up = _FP_W_TYPE_SIZE - _down; \
+ for (_s = _i = 0; _i < _skip; ++_i) \
+ _s |= X##_f[_i]; \
+ if (!_down) \
+ for (_i = 0; _i <= 7-_skip; ++_i) \
+ X##_f[_i] = X##_f[_i+_skip]; \
+ else \
+ { \
+ _s |= X##_f[_i] << _up; \
+ for (_i = 0; _i < 7-_skip; ++_i) \
+ X##_f[_i] = (X##_f[_i+_skip] >> _down \
+ | X##_f[_i+_skip+1] << _up); \
+ X##_f[_i++] = X##_f[7] >> _down; \
+ } \
+ for (; _i < 8; ++_i) \
+ X##_f[_i] = 0; \
+ /* don't fix the LSB until the very end when we're sure f[0] is \
+ stable */ \
+ X##_f[0] |= (_s != 0); \
+ } \
+ while (0)
diff --git a/libgcc/soft-fp/op-common.h b/libgcc/soft-fp/op-common.h
index c4acb991613..67cdc33b4cf 100644
--- a/libgcc/soft-fp/op-common.h
+++ b/libgcc/soft-fp/op-common.h
@@ -30,145 +30,157 @@
<http://www.gnu.org/licenses/>. */
#define _FP_DECL(wc, X) \
- _FP_I_TYPE X##_c __attribute__((unused)); \
- _FP_I_TYPE X##_s __attribute__((unused)); \
+ _FP_I_TYPE X##_c __attribute__ ((unused)); \
+ _FP_I_TYPE X##_s __attribute__ ((unused)); \
_FP_I_TYPE X##_e; \
- _FP_FRAC_DECL_##wc(X)
+ _FP_FRAC_DECL_##wc (X)
/* Test whether the qNaN bit denotes a signaling NaN. */
-#define _FP_FRAC_SNANP(fs, X) \
- ((_FP_QNANNEGATEDP) \
- ? (_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs) \
- : !(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs))
-#define _FP_FRAC_SNANP_SEMIRAW(fs, X) \
- ((_FP_QNANNEGATEDP) \
- ? (_FP_FRAC_HIGH_##fs(X) & _FP_QNANBIT_SH_##fs) \
- : !(_FP_FRAC_HIGH_##fs(X) & _FP_QNANBIT_SH_##fs))
+#define _FP_FRAC_SNANP(fs, X) \
+ ((_FP_QNANNEGATEDP) \
+ ? (_FP_FRAC_HIGH_RAW_##fs (X) & _FP_QNANBIT_##fs) \
+ : !(_FP_FRAC_HIGH_RAW_##fs (X) & _FP_QNANBIT_##fs))
+#define _FP_FRAC_SNANP_SEMIRAW(fs, X) \
+ ((_FP_QNANNEGATEDP) \
+ ? (_FP_FRAC_HIGH_##fs (X) & _FP_QNANBIT_SH_##fs) \
+ : !(_FP_FRAC_HIGH_##fs (X) & _FP_QNANBIT_SH_##fs))
/*
- * Finish truely unpacking a native fp value by classifying the kind
+ * Finish truly unpacking a native fp value by classifying the kind
* of fp value and normalizing both the exponent and the fraction.
*/
-#define _FP_UNPACK_CANONICAL(fs, wc, X) \
-do { \
- switch (X##_e) \
- { \
- default: \
- _FP_FRAC_HIGH_RAW_##fs(X) |= _FP_IMPLBIT_##fs; \
- _FP_FRAC_SLL_##wc(X, _FP_WORKBITS); \
- X##_e -= _FP_EXPBIAS_##fs; \
- X##_c = FP_CLS_NORMAL; \
- break; \
- \
- case 0: \
- if (_FP_FRAC_ZEROP_##wc(X)) \
- X##_c = FP_CLS_ZERO; \
- else \
- { \
- /* a denormalized number */ \
- _FP_I_TYPE _shift; \
- _FP_FRAC_CLZ_##wc(_shift, X); \
- _shift -= _FP_FRACXBITS_##fs; \
- _FP_FRAC_SLL_##wc(X, (_shift+_FP_WORKBITS)); \
- X##_e -= _FP_EXPBIAS_##fs - 1 + _shift; \
- X##_c = FP_CLS_NORMAL; \
- FP_SET_EXCEPTION(FP_EX_DENORM); \
- } \
- break; \
- \
- case _FP_EXPMAX_##fs: \
- if (_FP_FRAC_ZEROP_##wc(X)) \
- X##_c = FP_CLS_INF; \
- else \
- { \
- X##_c = FP_CLS_NAN; \
- /* Check for signaling NaN */ \
- if (_FP_FRAC_SNANP(fs, X)) \
- FP_SET_EXCEPTION(FP_EX_INVALID); \
- } \
- break; \
- } \
-} while (0)
+#define _FP_UNPACK_CANONICAL(fs, wc, X) \
+ do \
+ { \
+ switch (X##_e) \
+ { \
+ default: \
+ _FP_FRAC_HIGH_RAW_##fs (X) |= _FP_IMPLBIT_##fs; \
+ _FP_FRAC_SLL_##wc (X, _FP_WORKBITS); \
+ X##_e -= _FP_EXPBIAS_##fs; \
+ X##_c = FP_CLS_NORMAL; \
+ break; \
+ \
+ case 0: \
+ if (_FP_FRAC_ZEROP_##wc (X)) \
+ X##_c = FP_CLS_ZERO; \
+ else \
+ { \
+ /* a denormalized number */ \
+ _FP_I_TYPE _shift; \
+ _FP_FRAC_CLZ_##wc (_shift, X); \
+ _shift -= _FP_FRACXBITS_##fs; \
+ _FP_FRAC_SLL_##wc (X, (_shift+_FP_WORKBITS)); \
+ X##_e -= _FP_EXPBIAS_##fs - 1 + _shift; \
+ X##_c = FP_CLS_NORMAL; \
+ FP_SET_EXCEPTION (FP_EX_DENORM); \
+ } \
+ break; \
+ \
+ case _FP_EXPMAX_##fs: \
+ if (_FP_FRAC_ZEROP_##wc (X)) \
+ X##_c = FP_CLS_INF; \
+ else \
+ { \
+ X##_c = FP_CLS_NAN; \
+ /* Check for signaling NaN */ \
+ if (_FP_FRAC_SNANP (fs, X)) \
+ FP_SET_EXCEPTION (FP_EX_INVALID); \
+ } \
+ break; \
+ } \
+ } \
+ while (0)
/* Finish unpacking an fp value in semi-raw mode: the mantissa is
shifted by _FP_WORKBITS but the implicit MSB is not inserted and
other classification is not done. */
-#define _FP_UNPACK_SEMIRAW(fs, wc, X) _FP_FRAC_SLL_##wc(X, _FP_WORKBITS)
+#define _FP_UNPACK_SEMIRAW(fs, wc, X) _FP_FRAC_SLL_##wc (X, _FP_WORKBITS)
/* A semi-raw value has overflowed to infinity. Adjust the mantissa
and exponent appropriately. */
#define _FP_OVERFLOW_SEMIRAW(fs, wc, X) \
-do { \
- if (FP_ROUNDMODE == FP_RND_NEAREST \
- || (FP_ROUNDMODE == FP_RND_PINF && !X##_s) \
- || (FP_ROUNDMODE == FP_RND_MINF && X##_s)) \
+ do \
{ \
- X##_e = _FP_EXPMAX_##fs; \
- _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
+ if (FP_ROUNDMODE == FP_RND_NEAREST \
+ || (FP_ROUNDMODE == FP_RND_PINF && !X##_s) \
+ || (FP_ROUNDMODE == FP_RND_MINF && X##_s)) \
+ { \
+ X##_e = _FP_EXPMAX_##fs; \
+ _FP_FRAC_SET_##wc (X, _FP_ZEROFRAC_##wc); \
+ } \
+ else \
+ { \
+ X##_e = _FP_EXPMAX_##fs - 1; \
+ _FP_FRAC_SET_##wc (X, _FP_MAXFRAC_##wc); \
+ } \
+ FP_SET_EXCEPTION (FP_EX_INEXACT); \
+ FP_SET_EXCEPTION (FP_EX_OVERFLOW); \
} \
- else \
- { \
- X##_e = _FP_EXPMAX_##fs - 1; \
- _FP_FRAC_SET_##wc(X, _FP_MAXFRAC_##wc); \
- } \
- FP_SET_EXCEPTION(FP_EX_INEXACT); \
- FP_SET_EXCEPTION(FP_EX_OVERFLOW); \
-} while (0)
+ while (0)
/* Check for a semi-raw value being a signaling NaN and raise the
invalid exception if so. */
-#define _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X) \
-do { \
- if (X##_e == _FP_EXPMAX_##fs \
- && !_FP_FRAC_ZEROP_##wc(X) \
- && _FP_FRAC_SNANP_SEMIRAW(fs, X)) \
- FP_SET_EXCEPTION(FP_EX_INVALID); \
-} while (0)
+#define _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X) \
+ do \
+ { \
+ if (X##_e == _FP_EXPMAX_##fs \
+ && !_FP_FRAC_ZEROP_##wc (X) \
+ && _FP_FRAC_SNANP_SEMIRAW (fs, X)) \
+ FP_SET_EXCEPTION (FP_EX_INVALID); \
+ } \
+ while (0)
/* Choose a NaN result from an operation on two semi-raw NaN
values. */
#define _FP_CHOOSENAN_SEMIRAW(fs, wc, R, X, Y, OP) \
-do { \
- /* _FP_CHOOSENAN expects raw values, so shift as required. */ \
- _FP_FRAC_SRL_##wc(X, _FP_WORKBITS); \
- _FP_FRAC_SRL_##wc(Y, _FP_WORKBITS); \
- _FP_CHOOSENAN(fs, wc, R, X, Y, OP); \
- _FP_FRAC_SLL_##wc(R, _FP_WORKBITS); \
-} while (0)
+ do \
+ { \
+ /* _FP_CHOOSENAN expects raw values, so shift as required. */ \
+ _FP_FRAC_SRL_##wc (X, _FP_WORKBITS); \
+ _FP_FRAC_SRL_##wc (Y, _FP_WORKBITS); \
+ _FP_CHOOSENAN (fs, wc, R, X, Y, OP); \
+ _FP_FRAC_SLL_##wc (R, _FP_WORKBITS); \
+ } \
+ while (0)
/* Make the fractional part a quiet NaN, preserving the payload
if possible, otherwise make it the canonical quiet NaN and set
the sign bit accordingly. */
-#define _FP_SETQNAN(fs, wc, X) \
-do { \
- if (_FP_QNANNEGATEDP) \
- { \
- _FP_FRAC_HIGH_RAW_##fs(X) &= _FP_QNANBIT_##fs - 1; \
- if (_FP_FRAC_ZEROP_##wc(X)) \
- { \
- X##_s = _FP_NANSIGN_##fs; \
- _FP_FRAC_SET_##wc(X, _FP_NANFRAC_##fs); \
- } \
- } \
- else \
- _FP_FRAC_HIGH_RAW_##fs(X) |= _FP_QNANBIT_##fs; \
-} while (0)
-#define _FP_SETQNAN_SEMIRAW(fs, wc, X) \
-do { \
- if (_FP_QNANNEGATEDP) \
- { \
- _FP_FRAC_HIGH_##fs(X) &= _FP_QNANBIT_SH_##fs - 1; \
- if (_FP_FRAC_ZEROP_##wc(X)) \
- { \
- X##_s = _FP_NANSIGN_##fs; \
- _FP_FRAC_SET_##wc(X, _FP_NANFRAC_##fs); \
- _FP_FRAC_SLL_##wc(X, _FP_WORKBITS); \
- } \
- } \
- else \
- _FP_FRAC_HIGH_##fs(X) |= _FP_QNANBIT_SH_##fs; \
-} while (0)
+#define _FP_SETQNAN(fs, wc, X) \
+ do \
+ { \
+ if (_FP_QNANNEGATEDP) \
+ { \
+ _FP_FRAC_HIGH_RAW_##fs (X) &= _FP_QNANBIT_##fs - 1; \
+ if (_FP_FRAC_ZEROP_##wc (X)) \
+ { \
+ X##_s = _FP_NANSIGN_##fs; \
+ _FP_FRAC_SET_##wc (X, _FP_NANFRAC_##fs); \
+ } \
+ } \
+ else \
+ _FP_FRAC_HIGH_RAW_##fs (X) |= _FP_QNANBIT_##fs; \
+ } \
+ while (0)
+#define _FP_SETQNAN_SEMIRAW(fs, wc, X) \
+ do \
+ { \
+ if (_FP_QNANNEGATEDP) \
+ { \
+ _FP_FRAC_HIGH_##fs (X) &= _FP_QNANBIT_SH_##fs - 1; \
+ if (_FP_FRAC_ZEROP_##wc (X)) \
+ { \
+ X##_s = _FP_NANSIGN_##fs; \
+ _FP_FRAC_SET_##wc (X, _FP_NANFRAC_##fs); \
+ _FP_FRAC_SLL_##wc (X, _FP_WORKBITS); \
+ } \
+ } \
+ else \
+ _FP_FRAC_HIGH_##fs (X) |= _FP_QNANBIT_SH_##fs; \
+ } \
+ while (0)
/* Test whether a biased exponent is normal (not zero or maximum). */
#define _FP_EXP_NORMAL(fs, wc, X) (((X##_e + 1) & _FP_EXPMAX_##fs) > 1)
@@ -177,34 +189,36 @@ do { \
rounded and shifted right, with the rounding possibly increasing
the exponent (including changing a finite value to infinity). */
#define _FP_PACK_SEMIRAW(fs, wc, X) \
-do { \
- _FP_ROUND(wc, X); \
- if (X##_e == 0 && !_FP_FRAC_ZEROP_##wc(X)) \
- { \
+ do \
+ { \
+ _FP_ROUND (wc, X); \
+ if (X##_e == 0 && !_FP_FRAC_ZEROP_##wc (X)) \
+ { \
if ((FP_CUR_EXCEPTIONS & FP_EX_INEXACT) \
|| (FP_TRAPPING_EXCEPTIONS & FP_EX_UNDERFLOW)) \
- FP_SET_EXCEPTION(FP_EX_UNDERFLOW); \
- } \
- if (_FP_FRAC_HIGH_##fs(X) \
- & (_FP_OVERFLOW_##fs >> 1)) \
- { \
- _FP_FRAC_HIGH_##fs(X) &= ~(_FP_OVERFLOW_##fs >> 1); \
- X##_e++; \
- if (X##_e == _FP_EXPMAX_##fs) \
- _FP_OVERFLOW_SEMIRAW(fs, wc, X); \
- } \
- _FP_FRAC_SRL_##wc(X, _FP_WORKBITS); \
- if (X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X)) \
- { \
- if (!_FP_KEEPNANFRACP) \
+ FP_SET_EXCEPTION (FP_EX_UNDERFLOW); \
+ } \
+ if (_FP_FRAC_HIGH_##fs (X) \
+ & (_FP_OVERFLOW_##fs >> 1)) \
{ \
- _FP_FRAC_SET_##wc(X, _FP_NANFRAC_##fs); \
- X##_s = _FP_NANSIGN_##fs; \
+ _FP_FRAC_HIGH_##fs (X) &= ~(_FP_OVERFLOW_##fs >> 1); \
+ X##_e++; \
+ if (X##_e == _FP_EXPMAX_##fs) \
+ _FP_OVERFLOW_SEMIRAW (fs, wc, X); \
+ } \
+ _FP_FRAC_SRL_##wc (X, _FP_WORKBITS); \
+ if (X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (X)) \
+ { \
+ if (!_FP_KEEPNANFRACP) \
+ { \
+ _FP_FRAC_SET_##wc (X, _FP_NANFRAC_##fs); \
+ X##_s = _FP_NANSIGN_##fs; \
+ } \
+ else \
+ _FP_SETQNAN (fs, wc, X); \
} \
- else \
- _FP_SETQNAN(fs, wc, X); \
} \
-} while (0)
+ while (0)
/*
* Before packing the bits back into the native fp result, take care
@@ -213,701 +227,927 @@ do { \
* extracted -- but that is ok, we can regenerate them now.
*/
-#define _FP_PACK_CANONICAL(fs, wc, X) \
-do { \
- switch (X##_c) \
- { \
- case FP_CLS_NORMAL: \
- X##_e += _FP_EXPBIAS_##fs; \
- if (X##_e > 0) \
- { \
- _FP_ROUND(wc, X); \
- if (_FP_FRAC_OVERP_##wc(fs, X)) \
- { \
- _FP_FRAC_CLEAR_OVERP_##wc(fs, X); \
- X##_e++; \
- } \
- _FP_FRAC_SRL_##wc(X, _FP_WORKBITS); \
- if (X##_e >= _FP_EXPMAX_##fs) \
- { \
- /* overflow */ \
- switch (FP_ROUNDMODE) \
- { \
- case FP_RND_NEAREST: \
- X##_c = FP_CLS_INF; \
- break; \
- case FP_RND_PINF: \
- if (!X##_s) X##_c = FP_CLS_INF; \
- break; \
- case FP_RND_MINF: \
- if (X##_s) X##_c = FP_CLS_INF; \
- break; \
- } \
- if (X##_c == FP_CLS_INF) \
- { \
- /* Overflow to infinity */ \
- X##_e = _FP_EXPMAX_##fs; \
- _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
- } \
- else \
- { \
- /* Overflow to maximum normal */ \
- X##_e = _FP_EXPMAX_##fs - 1; \
- _FP_FRAC_SET_##wc(X, _FP_MAXFRAC_##wc); \
- } \
- FP_SET_EXCEPTION(FP_EX_OVERFLOW); \
- FP_SET_EXCEPTION(FP_EX_INEXACT); \
- } \
- } \
- else \
- { \
- /* we've got a denormalized number */ \
- X##_e = -X##_e + 1; \
- if (X##_e <= _FP_WFRACBITS_##fs) \
- { \
- _FP_FRAC_SRS_##wc(X, X##_e, _FP_WFRACBITS_##fs); \
- _FP_ROUND(wc, X); \
- if (_FP_FRAC_HIGH_##fs(X) \
- & (_FP_OVERFLOW_##fs >> 1)) \
- { \
- X##_e = 1; \
- _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
- FP_SET_EXCEPTION(FP_EX_INEXACT); \
- } \
- else \
- { \
- X##_e = 0; \
- _FP_FRAC_SRL_##wc(X, _FP_WORKBITS); \
- } \
- if ((FP_CUR_EXCEPTIONS & FP_EX_INEXACT) \
- || (FP_TRAPPING_EXCEPTIONS & FP_EX_UNDERFLOW)) \
- FP_SET_EXCEPTION(FP_EX_UNDERFLOW); \
- } \
- else \
- { \
- /* underflow to zero */ \
- X##_e = 0; \
- if (!_FP_FRAC_ZEROP_##wc(X)) \
- { \
- _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc); \
- _FP_ROUND(wc, X); \
- _FP_FRAC_LOW_##wc(X) >>= (_FP_WORKBITS); \
- } \
- FP_SET_EXCEPTION(FP_EX_UNDERFLOW); \
- } \
- } \
- break; \
- \
- case FP_CLS_ZERO: \
- X##_e = 0; \
- _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
- break; \
- \
- case FP_CLS_INF: \
- X##_e = _FP_EXPMAX_##fs; \
- _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
- break; \
- \
- case FP_CLS_NAN: \
- X##_e = _FP_EXPMAX_##fs; \
- if (!_FP_KEEPNANFRACP) \
- { \
- _FP_FRAC_SET_##wc(X, _FP_NANFRAC_##fs); \
- X##_s = _FP_NANSIGN_##fs; \
- } \
- else \
- _FP_SETQNAN(fs, wc, X); \
- break; \
- } \
-} while (0)
+#define _FP_PACK_CANONICAL(fs, wc, X) \
+ do \
+ { \
+ switch (X##_c) \
+ { \
+ case FP_CLS_NORMAL: \
+ X##_e += _FP_EXPBIAS_##fs; \
+ if (X##_e > 0) \
+ { \
+ _FP_ROUND (wc, X); \
+ if (_FP_FRAC_OVERP_##wc (fs, X)) \
+ { \
+ _FP_FRAC_CLEAR_OVERP_##wc (fs, X); \
+ X##_e++; \
+ } \
+ _FP_FRAC_SRL_##wc (X, _FP_WORKBITS); \
+ if (X##_e >= _FP_EXPMAX_##fs) \
+ { \
+ /* overflow */ \
+ switch (FP_ROUNDMODE) \
+ { \
+ case FP_RND_NEAREST: \
+ X##_c = FP_CLS_INF; \
+ break; \
+ case FP_RND_PINF: \
+ if (!X##_s) \
+ X##_c = FP_CLS_INF; \
+ break; \
+ case FP_RND_MINF: \
+ if (X##_s) \
+ X##_c = FP_CLS_INF; \
+ break; \
+ } \
+ if (X##_c == FP_CLS_INF) \
+ { \
+ /* Overflow to infinity */ \
+ X##_e = _FP_EXPMAX_##fs; \
+ _FP_FRAC_SET_##wc (X, _FP_ZEROFRAC_##wc); \
+ } \
+ else \
+ { \
+ /* Overflow to maximum normal */ \
+ X##_e = _FP_EXPMAX_##fs - 1; \
+ _FP_FRAC_SET_##wc (X, _FP_MAXFRAC_##wc); \
+ } \
+ FP_SET_EXCEPTION (FP_EX_OVERFLOW); \
+ FP_SET_EXCEPTION (FP_EX_INEXACT); \
+ } \
+ } \
+ else \
+ { \
+ /* we've got a denormalized number */ \
+ X##_e = -X##_e + 1; \
+ if (X##_e <= _FP_WFRACBITS_##fs) \
+ { \
+ _FP_FRAC_SRS_##wc (X, X##_e, _FP_WFRACBITS_##fs); \
+ _FP_ROUND (wc, X); \
+ if (_FP_FRAC_HIGH_##fs (X) \
+ & (_FP_OVERFLOW_##fs >> 1)) \
+ { \
+ X##_e = 1; \
+ _FP_FRAC_SET_##wc (X, _FP_ZEROFRAC_##wc); \
+ FP_SET_EXCEPTION (FP_EX_INEXACT); \
+ } \
+ else \
+ { \
+ X##_e = 0; \
+ _FP_FRAC_SRL_##wc (X, _FP_WORKBITS); \
+ } \
+ if ((FP_CUR_EXCEPTIONS & FP_EX_INEXACT) \
+ || (FP_TRAPPING_EXCEPTIONS & FP_EX_UNDERFLOW)) \
+ FP_SET_EXCEPTION (FP_EX_UNDERFLOW); \
+ } \
+ else \
+ { \
+ /* underflow to zero */ \
+ X##_e = 0; \
+ if (!_FP_FRAC_ZEROP_##wc (X)) \
+ { \
+ _FP_FRAC_SET_##wc (X, _FP_MINFRAC_##wc); \
+ _FP_ROUND (wc, X); \
+ _FP_FRAC_LOW_##wc (X) >>= (_FP_WORKBITS); \
+ } \
+ FP_SET_EXCEPTION (FP_EX_UNDERFLOW); \
+ } \
+ } \
+ break; \
+ \
+ case FP_CLS_ZERO: \
+ X##_e = 0; \
+ _FP_FRAC_SET_##wc (X, _FP_ZEROFRAC_##wc); \
+ break; \
+ \
+ case FP_CLS_INF: \
+ X##_e = _FP_EXPMAX_##fs; \
+ _FP_FRAC_SET_##wc (X, _FP_ZEROFRAC_##wc); \
+ break; \
+ \
+ case FP_CLS_NAN: \
+ X##_e = _FP_EXPMAX_##fs; \
+ if (!_FP_KEEPNANFRACP) \
+ { \
+ _FP_FRAC_SET_##wc (X, _FP_NANFRAC_##fs); \
+ X##_s = _FP_NANSIGN_##fs; \
+ } \
+ else \
+ _FP_SETQNAN (fs, wc, X); \
+ break; \
+ } \
+ } \
+ while (0)
/* This one accepts raw argument and not cooked, returns
* 1 if X is a signaling NaN.
*/
-#define _FP_ISSIGNAN(fs, wc, X) \
-({ \
- int __ret = 0; \
- if (X##_e == _FP_EXPMAX_##fs) \
- { \
- if (!_FP_FRAC_ZEROP_##wc(X) \
- && _FP_FRAC_SNANP(fs, X)) \
- __ret = 1; \
- } \
- __ret; \
-})
+#define _FP_ISSIGNAN(fs, wc, X) \
+ ({ \
+ int __ret = 0; \
+ if (X##_e == _FP_EXPMAX_##fs) \
+ { \
+ if (!_FP_FRAC_ZEROP_##wc (X) \
+ && _FP_FRAC_SNANP (fs, X)) \
+ __ret = 1; \
+ } \
+ __ret; \
+ })
/* Addition on semi-raw values. */
-#define _FP_ADD_INTERNAL(fs, wc, R, X, Y, OP) \
-do { \
- if (X##_s == Y##_s) \
- { \
- /* Addition. */ \
- R##_s = X##_s; \
- int ediff = X##_e - Y##_e; \
- if (ediff > 0) \
- { \
- R##_e = X##_e; \
- if (Y##_e == 0) \
- { \
- /* Y is zero or denormalized. */ \
- if (_FP_FRAC_ZEROP_##wc(Y)) \
- { \
- _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X); \
- _FP_FRAC_COPY_##wc(R, X); \
- goto add_done; \
- } \
- else \
- { \
- FP_SET_EXCEPTION(FP_EX_DENORM); \
- ediff--; \
- if (ediff == 0) \
- { \
- _FP_FRAC_ADD_##wc(R, X, Y); \
- goto add3; \
- } \
- if (X##_e == _FP_EXPMAX_##fs) \
- { \
- _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X); \
- _FP_FRAC_COPY_##wc(R, X); \
- goto add_done; \
- } \
- goto add1; \
- } \
- } \
- else if (X##_e == _FP_EXPMAX_##fs) \
- { \
- /* X is NaN or Inf, Y is normal. */ \
- _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X); \
- _FP_FRAC_COPY_##wc(R, X); \
- goto add_done; \
- } \
- \
- /* Insert implicit MSB of Y. */ \
- _FP_FRAC_HIGH_##fs(Y) |= _FP_IMPLBIT_SH_##fs; \
- \
- add1: \
- /* Shift the mantissa of Y to the right EDIFF steps; \
- remember to account later for the implicit MSB of X. */ \
- if (ediff <= _FP_WFRACBITS_##fs) \
- _FP_FRAC_SRS_##wc(Y, ediff, _FP_WFRACBITS_##fs); \
- else if (!_FP_FRAC_ZEROP_##wc(Y)) \
- _FP_FRAC_SET_##wc(Y, _FP_MINFRAC_##wc); \
- _FP_FRAC_ADD_##wc(R, X, Y); \
- } \
- else if (ediff < 0) \
- { \
- ediff = -ediff; \
- R##_e = Y##_e; \
- if (X##_e == 0) \
- { \
- /* X is zero or denormalized. */ \
- if (_FP_FRAC_ZEROP_##wc(X)) \
- { \
- _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, Y); \
- _FP_FRAC_COPY_##wc(R, Y); \
- goto add_done; \
- } \
- else \
- { \
- FP_SET_EXCEPTION(FP_EX_DENORM); \
- ediff--; \
- if (ediff == 0) \
- { \
- _FP_FRAC_ADD_##wc(R, Y, X); \
- goto add3; \
- } \
- if (Y##_e == _FP_EXPMAX_##fs) \
- { \
- _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, Y); \
- _FP_FRAC_COPY_##wc(R, Y); \
- goto add_done; \
- } \
- goto add2; \
- } \
- } \
- else if (Y##_e == _FP_EXPMAX_##fs) \
- { \
- /* Y is NaN or Inf, X is normal. */ \
- _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, Y); \
- _FP_FRAC_COPY_##wc(R, Y); \
- goto add_done; \
- } \
- \
- /* Insert implicit MSB of X. */ \
- _FP_FRAC_HIGH_##fs(X) |= _FP_IMPLBIT_SH_##fs; \
- \
- add2: \
- /* Shift the mantissa of X to the right EDIFF steps; \
- remember to account later for the implicit MSB of Y. */ \
- if (ediff <= _FP_WFRACBITS_##fs) \
- _FP_FRAC_SRS_##wc(X, ediff, _FP_WFRACBITS_##fs); \
- else if (!_FP_FRAC_ZEROP_##wc(X)) \
- _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc); \
- _FP_FRAC_ADD_##wc(R, Y, X); \
- } \
- else \
- { \
- /* ediff == 0. */ \
- if (!_FP_EXP_NORMAL(fs, wc, X)) \
- { \
- if (X##_e == 0) \
- { \
- /* X and Y are zero or denormalized. */ \
- R##_e = 0; \
- if (_FP_FRAC_ZEROP_##wc(X)) \
- { \
- if (!_FP_FRAC_ZEROP_##wc(Y)) \
- FP_SET_EXCEPTION(FP_EX_DENORM); \
- _FP_FRAC_COPY_##wc(R, Y); \
- goto add_done; \
- } \
- else if (_FP_FRAC_ZEROP_##wc(Y)) \
- { \
- FP_SET_EXCEPTION(FP_EX_DENORM); \
- _FP_FRAC_COPY_##wc(R, X); \
- goto add_done; \
- } \
- else \
- { \
- FP_SET_EXCEPTION(FP_EX_DENORM); \
- _FP_FRAC_ADD_##wc(R, X, Y); \
- if (_FP_FRAC_HIGH_##fs(R) & _FP_IMPLBIT_SH_##fs) \
- { \
- /* Normalized result. */ \
- _FP_FRAC_HIGH_##fs(R) \
- &= ~(_FP_W_TYPE)_FP_IMPLBIT_SH_##fs; \
- R##_e = 1; \
- } \
- goto add_done; \
- } \
- } \
- else \
- { \
- /* X and Y are NaN or Inf. */ \
- _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X); \
- _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, Y); \
- R##_e = _FP_EXPMAX_##fs; \
- if (_FP_FRAC_ZEROP_##wc(X)) \
- _FP_FRAC_COPY_##wc(R, Y); \
- else if (_FP_FRAC_ZEROP_##wc(Y)) \
- _FP_FRAC_COPY_##wc(R, X); \
- else \
- _FP_CHOOSENAN_SEMIRAW(fs, wc, R, X, Y, OP); \
- goto add_done; \
- } \
- } \
- /* The exponents of X and Y, both normal, are equal. The \
- implicit MSBs will always add to increase the \
- exponent. */ \
- _FP_FRAC_ADD_##wc(R, X, Y); \
- R##_e = X##_e + 1; \
- _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs); \
- if (R##_e == _FP_EXPMAX_##fs) \
- /* Overflow to infinity (depending on rounding mode). */ \
- _FP_OVERFLOW_SEMIRAW(fs, wc, R); \
- goto add_done; \
- } \
- add3: \
- if (_FP_FRAC_HIGH_##fs(R) & _FP_IMPLBIT_SH_##fs) \
- { \
- /* Overflow. */ \
- _FP_FRAC_HIGH_##fs(R) &= ~(_FP_W_TYPE)_FP_IMPLBIT_SH_##fs; \
- R##_e++; \
- _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs); \
- if (R##_e == _FP_EXPMAX_##fs) \
- /* Overflow to infinity (depending on rounding mode). */ \
- _FP_OVERFLOW_SEMIRAW(fs, wc, R); \
- } \
- add_done: ; \
- } \
- else \
- { \
- /* Subtraction. */ \
- int ediff = X##_e - Y##_e; \
- if (ediff > 0) \
- { \
- R##_e = X##_e; \
- R##_s = X##_s; \
- if (Y##_e == 0) \
- { \
- /* Y is zero or denormalized. */ \
- if (_FP_FRAC_ZEROP_##wc(Y)) \
- { \
- _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X); \
- _FP_FRAC_COPY_##wc(R, X); \
- goto sub_done; \
- } \
- else \
- { \
- FP_SET_EXCEPTION(FP_EX_DENORM); \
- ediff--; \
- if (ediff == 0) \
- { \
- _FP_FRAC_SUB_##wc(R, X, Y); \
- goto sub3; \
- } \
- if (X##_e == _FP_EXPMAX_##fs) \
- { \
- _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X); \
- _FP_FRAC_COPY_##wc(R, X); \
- goto sub_done; \
- } \
- goto sub1; \
- } \
- } \
- else if (X##_e == _FP_EXPMAX_##fs) \
- { \
- /* X is NaN or Inf, Y is normal. */ \
- _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X); \
- _FP_FRAC_COPY_##wc(R, X); \
- goto sub_done; \
- } \
- \
- /* Insert implicit MSB of Y. */ \
- _FP_FRAC_HIGH_##fs(Y) |= _FP_IMPLBIT_SH_##fs; \
- \
- sub1: \
- /* Shift the mantissa of Y to the right EDIFF steps; \
- remember to account later for the implicit MSB of X. */ \
- if (ediff <= _FP_WFRACBITS_##fs) \
- _FP_FRAC_SRS_##wc(Y, ediff, _FP_WFRACBITS_##fs); \
- else if (!_FP_FRAC_ZEROP_##wc(Y)) \
- _FP_FRAC_SET_##wc(Y, _FP_MINFRAC_##wc); \
- _FP_FRAC_SUB_##wc(R, X, Y); \
- } \
- else if (ediff < 0) \
- { \
- ediff = -ediff; \
- R##_e = Y##_e; \
- R##_s = Y##_s; \
- if (X##_e == 0) \
- { \
- /* X is zero or denormalized. */ \
- if (_FP_FRAC_ZEROP_##wc(X)) \
- { \
- _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, Y); \
- _FP_FRAC_COPY_##wc(R, Y); \
- goto sub_done; \
- } \
- else \
- { \
- FP_SET_EXCEPTION(FP_EX_DENORM); \
- ediff--; \
- if (ediff == 0) \
- { \
- _FP_FRAC_SUB_##wc(R, Y, X); \
- goto sub3; \
- } \
- if (Y##_e == _FP_EXPMAX_##fs) \
- { \
- _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, Y); \
- _FP_FRAC_COPY_##wc(R, Y); \
- goto sub_done; \
- } \
- goto sub2; \
- } \
- } \
- else if (Y##_e == _FP_EXPMAX_##fs) \
- { \
- /* Y is NaN or Inf, X is normal. */ \
- _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, Y); \
- _FP_FRAC_COPY_##wc(R, Y); \
- goto sub_done; \
- } \
- \
- /* Insert implicit MSB of X. */ \
- _FP_FRAC_HIGH_##fs(X) |= _FP_IMPLBIT_SH_##fs; \
- \
- sub2: \
- /* Shift the mantissa of X to the right EDIFF steps; \
- remember to account later for the implicit MSB of Y. */ \
- if (ediff <= _FP_WFRACBITS_##fs) \
- _FP_FRAC_SRS_##wc(X, ediff, _FP_WFRACBITS_##fs); \
- else if (!_FP_FRAC_ZEROP_##wc(X)) \
- _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc); \
- _FP_FRAC_SUB_##wc(R, Y, X); \
- } \
- else \
- { \
- /* ediff == 0. */ \
- if (!_FP_EXP_NORMAL(fs, wc, X)) \
- { \
- if (X##_e == 0) \
- { \
- /* X and Y are zero or denormalized. */ \
- R##_e = 0; \
- if (_FP_FRAC_ZEROP_##wc(X)) \
- { \
- _FP_FRAC_COPY_##wc(R, Y); \
- if (_FP_FRAC_ZEROP_##wc(Y)) \
- R##_s = (FP_ROUNDMODE == FP_RND_MINF); \
- else \
- { \
- FP_SET_EXCEPTION(FP_EX_DENORM); \
- R##_s = Y##_s; \
- } \
- goto sub_done; \
- } \
- else if (_FP_FRAC_ZEROP_##wc(Y)) \
- { \
- FP_SET_EXCEPTION(FP_EX_DENORM); \
- _FP_FRAC_COPY_##wc(R, X); \
- R##_s = X##_s; \
- goto sub_done; \
- } \
- else \
- { \
- FP_SET_EXCEPTION(FP_EX_DENORM); \
- _FP_FRAC_SUB_##wc(R, X, Y); \
- R##_s = X##_s; \
- if (_FP_FRAC_HIGH_##fs(R) & _FP_IMPLBIT_SH_##fs) \
- { \
- /* |X| < |Y|, negate result. */ \
- _FP_FRAC_SUB_##wc(R, Y, X); \
- R##_s = Y##_s; \
- } \
- else if (_FP_FRAC_ZEROP_##wc(R)) \
- R##_s = (FP_ROUNDMODE == FP_RND_MINF); \
- goto sub_done; \
- } \
- } \
- else \
- { \
- /* X and Y are NaN or Inf, of opposite signs. */ \
- _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X); \
- _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, Y); \
- R##_e = _FP_EXPMAX_##fs; \
- if (_FP_FRAC_ZEROP_##wc(X)) \
- { \
- if (_FP_FRAC_ZEROP_##wc(Y)) \
- { \
- /* Inf - Inf. */ \
- R##_s = _FP_NANSIGN_##fs; \
- _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
- _FP_FRAC_SLL_##wc(R, _FP_WORKBITS); \
- FP_SET_EXCEPTION(FP_EX_INVALID); \
- } \
- else \
- { \
- /* Inf - NaN. */ \
- R##_s = Y##_s; \
- _FP_FRAC_COPY_##wc(R, Y); \
- } \
- } \
- else \
- { \
- if (_FP_FRAC_ZEROP_##wc(Y)) \
- { \
- /* NaN - Inf. */ \
- R##_s = X##_s; \
- _FP_FRAC_COPY_##wc(R, X); \
- } \
- else \
- { \
- /* NaN - NaN. */ \
- _FP_CHOOSENAN_SEMIRAW(fs, wc, R, X, Y, OP); \
- } \
- } \
- goto sub_done; \
- } \
- } \
- /* The exponents of X and Y, both normal, are equal. The \
- implicit MSBs cancel. */ \
- R##_e = X##_e; \
- _FP_FRAC_SUB_##wc(R, X, Y); \
- R##_s = X##_s; \
- if (_FP_FRAC_HIGH_##fs(R) & _FP_IMPLBIT_SH_##fs) \
- { \
- /* |X| < |Y|, negate result. */ \
- _FP_FRAC_SUB_##wc(R, Y, X); \
- R##_s = Y##_s; \
- } \
- else if (_FP_FRAC_ZEROP_##wc(R)) \
- { \
- R##_e = 0; \
- R##_s = (FP_ROUNDMODE == FP_RND_MINF); \
- goto sub_done; \
- } \
- goto norm; \
- } \
- sub3: \
- if (_FP_FRAC_HIGH_##fs(R) & _FP_IMPLBIT_SH_##fs) \
- { \
- int diff; \
- /* Carry into most significant bit of larger one of X and Y, \
- canceling it; renormalize. */ \
- _FP_FRAC_HIGH_##fs(R) &= _FP_IMPLBIT_SH_##fs - 1; \
- norm: \
- _FP_FRAC_CLZ_##wc(diff, R); \
- diff -= _FP_WFRACXBITS_##fs; \
- _FP_FRAC_SLL_##wc(R, diff); \
- if (R##_e <= diff) \
- { \
- /* R is denormalized. */ \
- diff = diff - R##_e + 1; \
- _FP_FRAC_SRS_##wc(R, diff, _FP_WFRACBITS_##fs); \
- R##_e = 0; \
- } \
- else \
- { \
- R##_e -= diff; \
- _FP_FRAC_HIGH_##fs(R) &= ~(_FP_W_TYPE)_FP_IMPLBIT_SH_##fs; \
- } \
- } \
- sub_done: ; \
- } \
-} while (0)
+#define _FP_ADD_INTERNAL(fs, wc, R, X, Y, OP) \
+ do \
+ { \
+ if (X##_s == Y##_s) \
+ { \
+ /* Addition. */ \
+ R##_s = X##_s; \
+ int ediff = X##_e - Y##_e; \
+ if (ediff > 0) \
+ { \
+ R##_e = X##_e; \
+ if (Y##_e == 0) \
+ { \
+ /* Y is zero or denormalized. */ \
+ if (_FP_FRAC_ZEROP_##wc (Y)) \
+ { \
+ _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, X); \
+ _FP_FRAC_COPY_##wc (R, X); \
+ goto add_done; \
+ } \
+ else \
+ { \
+ FP_SET_EXCEPTION (FP_EX_DENORM); \
+ ediff--; \
+ if (ediff == 0) \
+ { \
+ _FP_FRAC_ADD_##wc (R, X, Y); \
+ goto add3; \
+ } \
+ if (X##_e == _FP_EXPMAX_##fs) \
+ { \
+ _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, X); \
+ _FP_FRAC_COPY_##wc (R, X); \
+ goto add_done; \
+ } \
+ goto add1; \
+ } \
+ } \
+ else if (X##_e == _FP_EXPMAX_##fs) \
+ { \
+ /* X is NaN or Inf, Y is normal. */ \
+ _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, X); \
+ _FP_FRAC_COPY_##wc (R, X); \
+ goto add_done; \
+ } \
+ \
+ /* Insert implicit MSB of Y. */ \
+ _FP_FRAC_HIGH_##fs (Y) |= _FP_IMPLBIT_SH_##fs; \
+ \
+ add1: \
+ /* Shift the mantissa of Y to the right EDIFF steps; \
+ remember to account later for the implicit MSB of X. */ \
+ if (ediff <= _FP_WFRACBITS_##fs) \
+ _FP_FRAC_SRS_##wc (Y, ediff, _FP_WFRACBITS_##fs); \
+ else if (!_FP_FRAC_ZEROP_##wc (Y)) \
+ _FP_FRAC_SET_##wc (Y, _FP_MINFRAC_##wc); \
+ _FP_FRAC_ADD_##wc (R, X, Y); \
+ } \
+ else if (ediff < 0) \
+ { \
+ ediff = -ediff; \
+ R##_e = Y##_e; \
+ if (X##_e == 0) \
+ { \
+ /* X is zero or denormalized. */ \
+ if (_FP_FRAC_ZEROP_##wc (X)) \
+ { \
+ _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, Y); \
+ _FP_FRAC_COPY_##wc (R, Y); \
+ goto add_done; \
+ } \
+ else \
+ { \
+ FP_SET_EXCEPTION (FP_EX_DENORM); \
+ ediff--; \
+ if (ediff == 0) \
+ { \
+ _FP_FRAC_ADD_##wc (R, Y, X); \
+ goto add3; \
+ } \
+ if (Y##_e == _FP_EXPMAX_##fs) \
+ { \
+ _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, Y); \
+ _FP_FRAC_COPY_##wc (R, Y); \
+ goto add_done; \
+ } \
+ goto add2; \
+ } \
+ } \
+ else if (Y##_e == _FP_EXPMAX_##fs) \
+ { \
+ /* Y is NaN or Inf, X is normal. */ \
+ _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, Y); \
+ _FP_FRAC_COPY_##wc (R, Y); \
+ goto add_done; \
+ } \
+ \
+ /* Insert implicit MSB of X. */ \
+ _FP_FRAC_HIGH_##fs (X) |= _FP_IMPLBIT_SH_##fs; \
+ \
+ add2: \
+ /* Shift the mantissa of X to the right EDIFF steps; \
+ remember to account later for the implicit MSB of Y. */ \
+ if (ediff <= _FP_WFRACBITS_##fs) \
+ _FP_FRAC_SRS_##wc (X, ediff, _FP_WFRACBITS_##fs); \
+ else if (!_FP_FRAC_ZEROP_##wc (X)) \
+ _FP_FRAC_SET_##wc (X, _FP_MINFRAC_##wc); \
+ _FP_FRAC_ADD_##wc (R, Y, X); \
+ } \
+ else \
+ { \
+ /* ediff == 0. */ \
+ if (!_FP_EXP_NORMAL (fs, wc, X)) \
+ { \
+ if (X##_e == 0) \
+ { \
+ /* X and Y are zero or denormalized. */ \
+ R##_e = 0; \
+ if (_FP_FRAC_ZEROP_##wc (X)) \
+ { \
+ if (!_FP_FRAC_ZEROP_##wc (Y)) \
+ FP_SET_EXCEPTION (FP_EX_DENORM); \
+ _FP_FRAC_COPY_##wc (R, Y); \
+ goto add_done; \
+ } \
+ else if (_FP_FRAC_ZEROP_##wc (Y)) \
+ { \
+ FP_SET_EXCEPTION (FP_EX_DENORM); \
+ _FP_FRAC_COPY_##wc (R, X); \
+ goto add_done; \
+ } \
+ else \
+ { \
+ FP_SET_EXCEPTION (FP_EX_DENORM); \
+ _FP_FRAC_ADD_##wc (R, X, Y); \
+ if (_FP_FRAC_HIGH_##fs (R) & _FP_IMPLBIT_SH_##fs) \
+ { \
+ /* Normalized result. */ \
+ _FP_FRAC_HIGH_##fs (R) \
+ &= ~(_FP_W_TYPE) _FP_IMPLBIT_SH_##fs; \
+ R##_e = 1; \
+ } \
+ goto add_done; \
+ } \
+ } \
+ else \
+ { \
+ /* X and Y are NaN or Inf. */ \
+ _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, X); \
+ _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, Y); \
+ R##_e = _FP_EXPMAX_##fs; \
+ if (_FP_FRAC_ZEROP_##wc (X)) \
+ _FP_FRAC_COPY_##wc (R, Y); \
+ else if (_FP_FRAC_ZEROP_##wc (Y)) \
+ _FP_FRAC_COPY_##wc (R, X); \
+ else \
+ _FP_CHOOSENAN_SEMIRAW (fs, wc, R, X, Y, OP); \
+ goto add_done; \
+ } \
+ } \
+ /* The exponents of X and Y, both normal, are equal. The \
+ implicit MSBs will always add to increase the \
+ exponent. */ \
+ _FP_FRAC_ADD_##wc (R, X, Y); \
+ R##_e = X##_e + 1; \
+ _FP_FRAC_SRS_##wc (R, 1, _FP_WFRACBITS_##fs); \
+ if (R##_e == _FP_EXPMAX_##fs) \
+ /* Overflow to infinity (depending on rounding mode). */ \
+ _FP_OVERFLOW_SEMIRAW (fs, wc, R); \
+ goto add_done; \
+ } \
+ add3: \
+ if (_FP_FRAC_HIGH_##fs (R) & _FP_IMPLBIT_SH_##fs) \
+ { \
+ /* Overflow. */ \
+ _FP_FRAC_HIGH_##fs (R) &= ~(_FP_W_TYPE) _FP_IMPLBIT_SH_##fs; \
+ R##_e++; \
+ _FP_FRAC_SRS_##wc (R, 1, _FP_WFRACBITS_##fs); \
+ if (R##_e == _FP_EXPMAX_##fs) \
+ /* Overflow to infinity (depending on rounding mode). */ \
+ _FP_OVERFLOW_SEMIRAW (fs, wc, R); \
+ } \
+ add_done: ; \
+ } \
+ else \
+ { \
+ /* Subtraction. */ \
+ int ediff = X##_e - Y##_e; \
+ if (ediff > 0) \
+ { \
+ R##_e = X##_e; \
+ R##_s = X##_s; \
+ if (Y##_e == 0) \
+ { \
+ /* Y is zero or denormalized. */ \
+ if (_FP_FRAC_ZEROP_##wc (Y)) \
+ { \
+ _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, X); \
+ _FP_FRAC_COPY_##wc (R, X); \
+ goto sub_done; \
+ } \
+ else \
+ { \
+ FP_SET_EXCEPTION (FP_EX_DENORM); \
+ ediff--; \
+ if (ediff == 0) \
+ { \
+ _FP_FRAC_SUB_##wc (R, X, Y); \
+ goto sub3; \
+ } \
+ if (X##_e == _FP_EXPMAX_##fs) \
+ { \
+ _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, X); \
+ _FP_FRAC_COPY_##wc (R, X); \
+ goto sub_done; \
+ } \
+ goto sub1; \
+ } \
+ } \
+ else if (X##_e == _FP_EXPMAX_##fs) \
+ { \
+ /* X is NaN or Inf, Y is normal. */ \
+ _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, X); \
+ _FP_FRAC_COPY_##wc (R, X); \
+ goto sub_done; \
+ } \
+ \
+ /* Insert implicit MSB of Y. */ \
+ _FP_FRAC_HIGH_##fs (Y) |= _FP_IMPLBIT_SH_##fs; \
+ \
+ sub1: \
+ /* Shift the mantissa of Y to the right EDIFF steps; \
+ remember to account later for the implicit MSB of X. */ \
+ if (ediff <= _FP_WFRACBITS_##fs) \
+ _FP_FRAC_SRS_##wc (Y, ediff, _FP_WFRACBITS_##fs); \
+ else if (!_FP_FRAC_ZEROP_##wc (Y)) \
+ _FP_FRAC_SET_##wc (Y, _FP_MINFRAC_##wc); \
+ _FP_FRAC_SUB_##wc (R, X, Y); \
+ } \
+ else if (ediff < 0) \
+ { \
+ ediff = -ediff; \
+ R##_e = Y##_e; \
+ R##_s = Y##_s; \
+ if (X##_e == 0) \
+ { \
+ /* X is zero or denormalized. */ \
+ if (_FP_FRAC_ZEROP_##wc (X)) \
+ { \
+ _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, Y); \
+ _FP_FRAC_COPY_##wc (R, Y); \
+ goto sub_done; \
+ } \
+ else \
+ { \
+ FP_SET_EXCEPTION (FP_EX_DENORM); \
+ ediff--; \
+ if (ediff == 0) \
+ { \
+ _FP_FRAC_SUB_##wc (R, Y, X); \
+ goto sub3; \
+ } \
+ if (Y##_e == _FP_EXPMAX_##fs) \
+ { \
+ _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, Y); \
+ _FP_FRAC_COPY_##wc (R, Y); \
+ goto sub_done; \
+ } \
+ goto sub2; \
+ } \
+ } \
+ else if (Y##_e == _FP_EXPMAX_##fs) \
+ { \
+ /* Y is NaN or Inf, X is normal. */ \
+ _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, Y); \
+ _FP_FRAC_COPY_##wc (R, Y); \
+ goto sub_done; \
+ } \
+ \
+ /* Insert implicit MSB of X. */ \
+ _FP_FRAC_HIGH_##fs (X) |= _FP_IMPLBIT_SH_##fs; \
+ \
+ sub2: \
+ /* Shift the mantissa of X to the right EDIFF steps; \
+ remember to account later for the implicit MSB of Y. */ \
+ if (ediff <= _FP_WFRACBITS_##fs) \
+ _FP_FRAC_SRS_##wc (X, ediff, _FP_WFRACBITS_##fs); \
+ else if (!_FP_FRAC_ZEROP_##wc (X)) \
+ _FP_FRAC_SET_##wc (X, _FP_MINFRAC_##wc); \
+ _FP_FRAC_SUB_##wc (R, Y, X); \
+ } \
+ else \
+ { \
+ /* ediff == 0. */ \
+ if (!_FP_EXP_NORMAL (fs, wc, X)) \
+ { \
+ if (X##_e == 0) \
+ { \
+ /* X and Y are zero or denormalized. */ \
+ R##_e = 0; \
+ if (_FP_FRAC_ZEROP_##wc (X)) \
+ { \
+ _FP_FRAC_COPY_##wc (R, Y); \
+ if (_FP_FRAC_ZEROP_##wc (Y)) \
+ R##_s = (FP_ROUNDMODE == FP_RND_MINF); \
+ else \
+ { \
+ FP_SET_EXCEPTION (FP_EX_DENORM); \
+ R##_s = Y##_s; \
+ } \
+ goto sub_done; \
+ } \
+ else if (_FP_FRAC_ZEROP_##wc (Y)) \
+ { \
+ FP_SET_EXCEPTION (FP_EX_DENORM); \
+ _FP_FRAC_COPY_##wc (R, X); \
+ R##_s = X##_s; \
+ goto sub_done; \
+ } \
+ else \
+ { \
+ FP_SET_EXCEPTION (FP_EX_DENORM); \
+ _FP_FRAC_SUB_##wc (R, X, Y); \
+ R##_s = X##_s; \
+ if (_FP_FRAC_HIGH_##fs (R) & _FP_IMPLBIT_SH_##fs) \
+ { \
+ /* |X| < |Y|, negate result. */ \
+ _FP_FRAC_SUB_##wc (R, Y, X); \
+ R##_s = Y##_s; \
+ } \
+ else if (_FP_FRAC_ZEROP_##wc (R)) \
+ R##_s = (FP_ROUNDMODE == FP_RND_MINF); \
+ goto sub_done; \
+ } \
+ } \
+ else \
+ { \
+ /* X and Y are NaN or Inf, of opposite signs. */ \
+ _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, X); \
+ _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, Y); \
+ R##_e = _FP_EXPMAX_##fs; \
+ if (_FP_FRAC_ZEROP_##wc (X)) \
+ { \
+ if (_FP_FRAC_ZEROP_##wc (Y)) \
+ { \
+ /* Inf - Inf. */ \
+ R##_s = _FP_NANSIGN_##fs; \
+ _FP_FRAC_SET_##wc (R, _FP_NANFRAC_##fs); \
+ _FP_FRAC_SLL_##wc (R, _FP_WORKBITS); \
+ FP_SET_EXCEPTION (FP_EX_INVALID); \
+ } \
+ else \
+ { \
+ /* Inf - NaN. */ \
+ R##_s = Y##_s; \
+ _FP_FRAC_COPY_##wc (R, Y); \
+ } \
+ } \
+ else \
+ { \
+ if (_FP_FRAC_ZEROP_##wc (Y)) \
+ { \
+ /* NaN - Inf. */ \
+ R##_s = X##_s; \
+ _FP_FRAC_COPY_##wc (R, X); \
+ } \
+ else \
+ { \
+ /* NaN - NaN. */ \
+ _FP_CHOOSENAN_SEMIRAW (fs, wc, R, X, Y, OP); \
+ } \
+ } \
+ goto sub_done; \
+ } \
+ } \
+ /* The exponents of X and Y, both normal, are equal. The \
+ implicit MSBs cancel. */ \
+ R##_e = X##_e; \
+ _FP_FRAC_SUB_##wc (R, X, Y); \
+ R##_s = X##_s; \
+ if (_FP_FRAC_HIGH_##fs (R) & _FP_IMPLBIT_SH_##fs) \
+ { \
+ /* |X| < |Y|, negate result. */ \
+ _FP_FRAC_SUB_##wc (R, Y, X); \
+ R##_s = Y##_s; \
+ } \
+ else if (_FP_FRAC_ZEROP_##wc (R)) \
+ { \
+ R##_e = 0; \
+ R##_s = (FP_ROUNDMODE == FP_RND_MINF); \
+ goto sub_done; \
+ } \
+ goto norm; \
+ } \
+ sub3: \
+ if (_FP_FRAC_HIGH_##fs (R) & _FP_IMPLBIT_SH_##fs) \
+ { \
+ int diff; \
+ /* Carry into most significant bit of larger one of X and Y, \
+ canceling it; renormalize. */ \
+ _FP_FRAC_HIGH_##fs (R) &= _FP_IMPLBIT_SH_##fs - 1; \
+ norm: \
+ _FP_FRAC_CLZ_##wc (diff, R); \
+ diff -= _FP_WFRACXBITS_##fs; \
+ _FP_FRAC_SLL_##wc (R, diff); \
+ if (R##_e <= diff) \
+ { \
+ /* R is denormalized. */ \
+ diff = diff - R##_e + 1; \
+ _FP_FRAC_SRS_##wc (R, diff, _FP_WFRACBITS_##fs); \
+ R##_e = 0; \
+ } \
+ else \
+ { \
+ R##_e -= diff; \
+ _FP_FRAC_HIGH_##fs (R) &= ~(_FP_W_TYPE) _FP_IMPLBIT_SH_##fs; \
+ } \
+ } \
+ sub_done: ; \
+ } \
+ } \
+ while (0)
-#define _FP_ADD(fs, wc, R, X, Y) _FP_ADD_INTERNAL(fs, wc, R, X, Y, '+')
-#define _FP_SUB(fs, wc, R, X, Y) \
- do { \
- if (!(Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y))) Y##_s ^= 1; \
- _FP_ADD_INTERNAL(fs, wc, R, X, Y, '-'); \
- } while (0)
+#define _FP_ADD(fs, wc, R, X, Y) _FP_ADD_INTERNAL (fs, wc, R, X, Y, '+')
+#define _FP_SUB(fs, wc, R, X, Y) \
+ do \
+ { \
+ if (!(Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (Y))) \
+ Y##_s ^= 1; \
+ _FP_ADD_INTERNAL (fs, wc, R, X, Y, '-'); \
+ } \
+ while (0)
/*
- * Main negation routine. FIXME -- when we care about setting exception
- * bits reliably, this will not do. We should examine all of the fp classes.
+ * Main negation routine. The input value is raw.
*/
-#define _FP_NEG(fs, wc, R, X) \
- do { \
- _FP_FRAC_COPY_##wc(R, X); \
- R##_c = X##_c; \
- R##_e = X##_e; \
- R##_s = 1 ^ X##_s; \
- } while (0)
+#define _FP_NEG(fs, wc, R, X) \
+ do \
+ { \
+ _FP_FRAC_COPY_##wc (R, X); \
+ R##_e = X##_e; \
+ R##_s = 1 ^ X##_s; \
+ } \
+ while (0)
/*
* Main multiplication routine. The input values should be cooked.
*/
-#define _FP_MUL(fs, wc, R, X, Y) \
-do { \
- R##_s = X##_s ^ Y##_s; \
- R##_e = X##_e + Y##_e + 1; \
- switch (_FP_CLS_COMBINE(X##_c, Y##_c)) \
- { \
- case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL): \
- R##_c = FP_CLS_NORMAL; \
- \
- _FP_MUL_MEAT_##fs(R,X,Y); \
- \
- if (_FP_FRAC_OVERP_##wc(fs, R)) \
- _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs); \
- else \
- R##_e--; \
- break; \
- \
- case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN): \
- _FP_CHOOSENAN(fs, wc, R, X, Y, '*'); \
- break; \
- \
- case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL): \
- case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF): \
- case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO): \
- R##_s = X##_s; \
- \
- case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF): \
- case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL): \
- case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL): \
- case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO): \
- _FP_FRAC_COPY_##wc(R, X); \
- R##_c = X##_c; \
- break; \
- \
- case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN): \
- case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN): \
- case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN): \
- R##_s = Y##_s; \
- \
- case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF): \
- case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO): \
- _FP_FRAC_COPY_##wc(R, Y); \
- R##_c = Y##_c; \
- break; \
- \
- case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO): \
- case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF): \
- R##_s = _FP_NANSIGN_##fs; \
- R##_c = FP_CLS_NAN; \
- _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
- FP_SET_EXCEPTION(FP_EX_INVALID); \
- break; \
- \
- default: \
- abort(); \
- } \
-} while (0)
+#define _FP_MUL(fs, wc, R, X, Y) \
+ do \
+ { \
+ R##_s = X##_s ^ Y##_s; \
+ R##_e = X##_e + Y##_e + 1; \
+ switch (_FP_CLS_COMBINE (X##_c, Y##_c)) \
+ { \
+ case _FP_CLS_COMBINE (FP_CLS_NORMAL, FP_CLS_NORMAL): \
+ R##_c = FP_CLS_NORMAL; \
+ \
+ _FP_MUL_MEAT_##fs (R, X, Y); \
+ \
+ if (_FP_FRAC_OVERP_##wc (fs, R)) \
+ _FP_FRAC_SRS_##wc (R, 1, _FP_WFRACBITS_##fs); \
+ else \
+ R##_e--; \
+ break; \
+ \
+ case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_NAN): \
+ _FP_CHOOSENAN (fs, wc, R, X, Y, '*'); \
+ break; \
+ \
+ case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_NORMAL): \
+ case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_INF): \
+ case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_ZERO): \
+ R##_s = X##_s; \
+ \
+ case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_INF): \
+ case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_NORMAL): \
+ case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_NORMAL): \
+ case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_ZERO): \
+ _FP_FRAC_COPY_##wc (R, X); \
+ R##_c = X##_c; \
+ break; \
+ \
+ case _FP_CLS_COMBINE (FP_CLS_NORMAL, FP_CLS_NAN): \
+ case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_NAN): \
+ case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_NAN): \
+ R##_s = Y##_s; \
+ \
+ case _FP_CLS_COMBINE (FP_CLS_NORMAL, FP_CLS_INF): \
+ case _FP_CLS_COMBINE (FP_CLS_NORMAL, FP_CLS_ZERO): \
+ _FP_FRAC_COPY_##wc (R, Y); \
+ R##_c = Y##_c; \
+ break; \
+ \
+ case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_ZERO): \
+ case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_INF): \
+ R##_s = _FP_NANSIGN_##fs; \
+ R##_c = FP_CLS_NAN; \
+ _FP_FRAC_SET_##wc (R, _FP_NANFRAC_##fs); \
+ FP_SET_EXCEPTION (FP_EX_INVALID); \
+ break; \
+ \
+ default: \
+ abort (); \
+ } \
+ } \
+ while (0)
+
+
+/* Fused multiply-add. The input values should be cooked. */
+
+#define _FP_FMA(fs, wc, dwc, R, X, Y, Z) \
+ do \
+ { \
+ FP_DECL_##fs (T); \
+ T##_s = X##_s ^ Y##_s; \
+ T##_e = X##_e + Y##_e + 1; \
+ switch (_FP_CLS_COMBINE (X##_c, Y##_c)) \
+ { \
+ case _FP_CLS_COMBINE (FP_CLS_NORMAL, FP_CLS_NORMAL): \
+ switch (Z##_c) \
+ { \
+ case FP_CLS_INF: \
+ case FP_CLS_NAN: \
+ R##_s = Z##_s; \
+ _FP_FRAC_COPY_##wc (R, Z); \
+ R##_c = Z##_c; \
+ break; \
+ \
+ case FP_CLS_ZERO: \
+ R##_c = FP_CLS_NORMAL; \
+ R##_s = T##_s; \
+ R##_e = T##_e; \
+ \
+ _FP_MUL_MEAT_##fs (R, X, Y); \
+ \
+ if (_FP_FRAC_OVERP_##wc (fs, R)) \
+ _FP_FRAC_SRS_##wc (R, 1, _FP_WFRACBITS_##fs); \
+ else \
+ R##_e--; \
+ break; \
+ \
+ case FP_CLS_NORMAL:; \
+ _FP_FRAC_DECL_##dwc (TD); \
+ _FP_FRAC_DECL_##dwc (ZD); \
+ _FP_FRAC_DECL_##dwc (RD); \
+ _FP_MUL_MEAT_DW_##fs (TD, X, Y); \
+ R##_e = T##_e; \
+ int tsh = _FP_FRAC_HIGHBIT_DW_##dwc (fs, TD) == 0; \
+ T##_e -= tsh; \
+ int ediff = T##_e - Z##_e; \
+ if (ediff >= 0) \
+ { \
+ int shift = _FP_WFRACBITS_##fs - tsh - ediff; \
+ if (shift <= -_FP_WFRACBITS_##fs) \
+ _FP_FRAC_SET_##dwc (ZD, _FP_MINFRAC_##dwc); \
+ else \
+ { \
+ _FP_FRAC_COPY_##dwc##_##wc (ZD, Z); \
+ if (shift < 0) \
+ _FP_FRAC_SRS_##dwc (ZD, -shift, \
+ _FP_WFRACBITS_DW_##fs); \
+ else if (shift > 0) \
+ _FP_FRAC_SLL_##dwc (ZD, shift); \
+ } \
+ R##_s = T##_s; \
+ if (T##_s == Z##_s) \
+ _FP_FRAC_ADD_##dwc (RD, TD, ZD); \
+ else \
+ { \
+ _FP_FRAC_SUB_##dwc (RD, TD, ZD); \
+ if (_FP_FRAC_NEGP_##dwc (RD)) \
+ { \
+ R##_s = Z##_s; \
+ _FP_FRAC_SUB_##dwc (RD, ZD, TD); \
+ } \
+ } \
+ } \
+ else \
+ { \
+ R##_e = Z##_e; \
+ R##_s = Z##_s; \
+ _FP_FRAC_COPY_##dwc##_##wc (ZD, Z); \
+ _FP_FRAC_SLL_##dwc (ZD, _FP_WFRACBITS_##fs); \
+ int shift = -ediff - tsh; \
+ if (shift >= _FP_WFRACBITS_DW_##fs) \
+ _FP_FRAC_SET_##dwc (TD, _FP_MINFRAC_##dwc); \
+ else if (shift > 0) \
+ _FP_FRAC_SRS_##dwc (TD, shift, \
+ _FP_WFRACBITS_DW_##fs); \
+ if (Z##_s == T##_s) \
+ _FP_FRAC_ADD_##dwc (RD, ZD, TD); \
+ else \
+ _FP_FRAC_SUB_##dwc (RD, ZD, TD); \
+ } \
+ if (_FP_FRAC_ZEROP_##dwc (RD)) \
+ { \
+ if (T##_s == Z##_s) \
+ R##_s = Z##_s; \
+ else \
+ R##_s = (FP_ROUNDMODE == FP_RND_MINF); \
+ _FP_FRAC_SET_##wc (R, _FP_ZEROFRAC_##wc); \
+ R##_c = FP_CLS_ZERO; \
+ } \
+ else \
+ { \
+ int rlz; \
+ _FP_FRAC_CLZ_##dwc (rlz, RD); \
+ rlz -= _FP_WFRACXBITS_DW_##fs; \
+ R##_e -= rlz; \
+ int shift = _FP_WFRACBITS_##fs - rlz; \
+ if (shift > 0) \
+ _FP_FRAC_SRS_##dwc (RD, shift, \
+ _FP_WFRACBITS_DW_##fs); \
+ else if (shift < 0) \
+ _FP_FRAC_SLL_##dwc (RD, -shift); \
+ _FP_FRAC_COPY_##wc##_##dwc (R, RD); \
+ R##_c = FP_CLS_NORMAL; \
+ } \
+ break; \
+ } \
+ goto done_fma; \
+ \
+ case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_NAN): \
+ _FP_CHOOSENAN (fs, wc, T, X, Y, '*'); \
+ break; \
+ \
+ case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_NORMAL): \
+ case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_INF): \
+ case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_ZERO): \
+ T##_s = X##_s; \
+ \
+ case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_INF): \
+ case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_NORMAL): \
+ case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_NORMAL): \
+ case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_ZERO): \
+ _FP_FRAC_COPY_##wc (T, X); \
+ T##_c = X##_c; \
+ break; \
+ \
+ case _FP_CLS_COMBINE (FP_CLS_NORMAL, FP_CLS_NAN): \
+ case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_NAN): \
+ case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_NAN): \
+ T##_s = Y##_s; \
+ \
+ case _FP_CLS_COMBINE (FP_CLS_NORMAL, FP_CLS_INF): \
+ case _FP_CLS_COMBINE (FP_CLS_NORMAL, FP_CLS_ZERO): \
+ _FP_FRAC_COPY_##wc (T, Y); \
+ T##_c = Y##_c; \
+ break; \
+ \
+ case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_ZERO): \
+ case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_INF): \
+ T##_s = _FP_NANSIGN_##fs; \
+ T##_c = FP_CLS_NAN; \
+ _FP_FRAC_SET_##wc (T, _FP_NANFRAC_##fs); \
+ FP_SET_EXCEPTION (FP_EX_INVALID); \
+ break; \
+ \
+ default: \
+ abort (); \
+ } \
+ \
+ /* T = X * Y is zero, infinity or NaN. */ \
+ switch (_FP_CLS_COMBINE (T##_c, Z##_c)) \
+ { \
+ case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_NAN): \
+ _FP_CHOOSENAN (fs, wc, R, T, Z, '+'); \
+ break; \
+ \
+ case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_NORMAL): \
+ case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_INF): \
+ case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_ZERO): \
+ case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_NORMAL): \
+ case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_ZERO): \
+ R##_s = T##_s; \
+ _FP_FRAC_COPY_##wc (R, T); \
+ R##_c = T##_c; \
+ break; \
+ \
+ case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_NAN): \
+ case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_NAN): \
+ case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_NORMAL): \
+ case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_INF): \
+ R##_s = Z##_s; \
+ _FP_FRAC_COPY_##wc (R, Z); \
+ R##_c = Z##_c; \
+ break; \
+ \
+ case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_INF): \
+ if (T##_s == Z##_s) \
+ { \
+ R##_s = Z##_s; \
+ _FP_FRAC_COPY_##wc (R, Z); \
+ R##_c = Z##_c; \
+ } \
+ else \
+ { \
+ R##_s = _FP_NANSIGN_##fs; \
+ R##_c = FP_CLS_NAN; \
+ _FP_FRAC_SET_##wc (R, _FP_NANFRAC_##fs); \
+ FP_SET_EXCEPTION (FP_EX_INVALID); \
+ } \
+ break; \
+ \
+ case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_ZERO): \
+ if (T##_s == Z##_s) \
+ R##_s = Z##_s; \
+ else \
+ R##_s = (FP_ROUNDMODE == FP_RND_MINF); \
+ _FP_FRAC_COPY_##wc (R, Z); \
+ R##_c = Z##_c; \
+ break; \
+ \
+ default: \
+ abort (); \
+ } \
+ done_fma: ; \
+ } \
+ while (0)
/*
* Main division routine. The input values should be cooked.
*/
-#define _FP_DIV(fs, wc, R, X, Y) \
-do { \
- R##_s = X##_s ^ Y##_s; \
- R##_e = X##_e - Y##_e; \
- switch (_FP_CLS_COMBINE(X##_c, Y##_c)) \
- { \
- case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL): \
- R##_c = FP_CLS_NORMAL; \
- \
- _FP_DIV_MEAT_##fs(R,X,Y); \
- break; \
- \
- case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN): \
- _FP_CHOOSENAN(fs, wc, R, X, Y, '/'); \
- break; \
- \
- case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL): \
- case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF): \
- case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO): \
- R##_s = X##_s; \
- _FP_FRAC_COPY_##wc(R, X); \
- R##_c = X##_c; \
- break; \
- \
- case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN): \
- case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN): \
- case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN): \
- R##_s = Y##_s; \
- _FP_FRAC_COPY_##wc(R, Y); \
- R##_c = Y##_c; \
- break; \
- \
- case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF): \
- case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF): \
- case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL): \
- R##_c = FP_CLS_ZERO; \
- break; \
- \
- case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO): \
- FP_SET_EXCEPTION(FP_EX_DIVZERO); \
- case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO): \
- case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL): \
- R##_c = FP_CLS_INF; \
- break; \
- \
- case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF): \
- case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO): \
- R##_s = _FP_NANSIGN_##fs; \
- R##_c = FP_CLS_NAN; \
- _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
- FP_SET_EXCEPTION(FP_EX_INVALID); \
- break; \
- \
- default: \
- abort(); \
- } \
-} while (0)
+#define _FP_DIV(fs, wc, R, X, Y) \
+ do \
+ { \
+ R##_s = X##_s ^ Y##_s; \
+ R##_e = X##_e - Y##_e; \
+ switch (_FP_CLS_COMBINE (X##_c, Y##_c)) \
+ { \
+ case _FP_CLS_COMBINE (FP_CLS_NORMAL, FP_CLS_NORMAL): \
+ R##_c = FP_CLS_NORMAL; \
+ \
+ _FP_DIV_MEAT_##fs (R, X, Y); \
+ break; \
+ \
+ case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_NAN): \
+ _FP_CHOOSENAN (fs, wc, R, X, Y, '/'); \
+ break; \
+ \
+ case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_NORMAL): \
+ case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_INF): \
+ case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_ZERO): \
+ R##_s = X##_s; \
+ _FP_FRAC_COPY_##wc (R, X); \
+ R##_c = X##_c; \
+ break; \
+ \
+ case _FP_CLS_COMBINE (FP_CLS_NORMAL, FP_CLS_NAN): \
+ case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_NAN): \
+ case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_NAN): \
+ R##_s = Y##_s; \
+ _FP_FRAC_COPY_##wc (R, Y); \
+ R##_c = Y##_c; \
+ break; \
+ \
+ case _FP_CLS_COMBINE (FP_CLS_NORMAL, FP_CLS_INF): \
+ case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_INF): \
+ case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_NORMAL): \
+ R##_c = FP_CLS_ZERO; \
+ break; \
+ \
+ case _FP_CLS_COMBINE (FP_CLS_NORMAL, FP_CLS_ZERO): \
+ FP_SET_EXCEPTION (FP_EX_DIVZERO); \
+ case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_ZERO): \
+ case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_NORMAL): \
+ R##_c = FP_CLS_INF; \
+ break; \
+ \
+ case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_INF): \
+ case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_ZERO): \
+ R##_s = _FP_NANSIGN_##fs; \
+ R##_c = FP_CLS_NAN; \
+ _FP_FRAC_SET_##wc (R, _FP_NANFRAC_##fs); \
+ FP_SET_EXCEPTION (FP_EX_INVALID); \
+ break; \
+ \
+ default: \
+ abort (); \
+ } \
+ } \
+ while (0)
/*
@@ -916,122 +1156,131 @@ do { \
*/
#define _FP_CMP(fs, wc, ret, X, Y, un) \
- do { \
- /* NANs are unordered */ \
- if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X)) \
- || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y))) \
- { \
- ret = un; \
- } \
- else \
- { \
- int __is_zero_x; \
- int __is_zero_y; \
+ do \
+ { \
+ /* NANs are unordered */ \
+ if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (X)) \
+ || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (Y))) \
+ { \
+ ret = un; \
+ } \
+ else \
+ { \
+ int __is_zero_x; \
+ int __is_zero_y; \
\
- __is_zero_x = (!X##_e && _FP_FRAC_ZEROP_##wc(X)) ? 1 : 0; \
- __is_zero_y = (!Y##_e && _FP_FRAC_ZEROP_##wc(Y)) ? 1 : 0; \
+ __is_zero_x = (!X##_e && _FP_FRAC_ZEROP_##wc (X)) ? 1 : 0; \
+ __is_zero_y = (!Y##_e && _FP_FRAC_ZEROP_##wc (Y)) ? 1 : 0; \
\
- if (__is_zero_x && __is_zero_y) \
- ret = 0; \
- else if (__is_zero_x) \
- ret = Y##_s ? 1 : -1; \
- else if (__is_zero_y) \
- ret = X##_s ? -1 : 1; \
- else if (X##_s != Y##_s) \
- ret = X##_s ? -1 : 1; \
- else if (X##_e > Y##_e) \
- ret = X##_s ? -1 : 1; \
- else if (X##_e < Y##_e) \
- ret = X##_s ? 1 : -1; \
- else if (_FP_FRAC_GT_##wc(X, Y)) \
- ret = X##_s ? -1 : 1; \
- else if (_FP_FRAC_GT_##wc(Y, X)) \
- ret = X##_s ? 1 : -1; \
- else \
- ret = 0; \
- } \
- } while (0)
+ if (__is_zero_x && __is_zero_y) \
+ ret = 0; \
+ else if (__is_zero_x) \
+ ret = Y##_s ? 1 : -1; \
+ else if (__is_zero_y) \
+ ret = X##_s ? -1 : 1; \
+ else if (X##_s != Y##_s) \
+ ret = X##_s ? -1 : 1; \
+ else if (X##_e > Y##_e) \
+ ret = X##_s ? -1 : 1; \
+ else if (X##_e < Y##_e) \
+ ret = X##_s ? 1 : -1; \
+ else if (_FP_FRAC_GT_##wc (X, Y)) \
+ ret = X##_s ? -1 : 1; \
+ else if (_FP_FRAC_GT_##wc (Y, X)) \
+ ret = X##_s ? 1 : -1; \
+ else \
+ ret = 0; \
+ } \
+ } \
+ while (0)
/* Simplification for strict equality. */
-#define _FP_CMP_EQ(fs, wc, ret, X, Y) \
- do { \
- /* NANs are unordered */ \
- if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X)) \
- || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y))) \
- { \
- ret = 1; \
- } \
- else \
- { \
- ret = !(X##_e == Y##_e \
- && _FP_FRAC_EQ_##wc(X, Y) \
- && (X##_s == Y##_s || (!X##_e && _FP_FRAC_ZEROP_##wc(X)))); \
- } \
- } while (0)
+#define _FP_CMP_EQ(fs, wc, ret, X, Y) \
+ do \
+ { \
+ /* NANs are unordered */ \
+ if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (X)) \
+ || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (Y))) \
+ { \
+ ret = 1; \
+ } \
+ else \
+ { \
+ ret = !(X##_e == Y##_e \
+ && _FP_FRAC_EQ_##wc (X, Y) \
+ && (X##_s == Y##_s || (!X##_e && _FP_FRAC_ZEROP_##wc (X)))); \
+ } \
+ } \
+ while (0)
/* Version to test unordered. */
#define _FP_CMP_UNORD(fs, wc, ret, X, Y) \
- do { \
- ret = ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X)) \
- || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y))); \
- } while (0)
+ do \
+ { \
+ ret = ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (X)) \
+ || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (Y))); \
+ } \
+ while (0)
/*
* Main square root routine. The input value should be cooked.
*/
-#define _FP_SQRT(fs, wc, R, X) \
-do { \
- _FP_FRAC_DECL_##wc(T); _FP_FRAC_DECL_##wc(S); \
- _FP_W_TYPE q; \
- switch (X##_c) \
- { \
- case FP_CLS_NAN: \
- _FP_FRAC_COPY_##wc(R, X); \
- R##_s = X##_s; \
- R##_c = FP_CLS_NAN; \
- break; \
- case FP_CLS_INF: \
- if (X##_s) \
- { \
- R##_s = _FP_NANSIGN_##fs; \
- R##_c = FP_CLS_NAN; /* NAN */ \
- _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
- FP_SET_EXCEPTION(FP_EX_INVALID); \
- } \
- else \
- { \
- R##_s = 0; \
- R##_c = FP_CLS_INF; /* sqrt(+inf) = +inf */ \
- } \
- break; \
- case FP_CLS_ZERO: \
- R##_s = X##_s; \
- R##_c = FP_CLS_ZERO; /* sqrt(+-0) = +-0 */ \
- break; \
- case FP_CLS_NORMAL: \
- R##_s = 0; \
- if (X##_s) \
- { \
- R##_c = FP_CLS_NAN; /* NAN */ \
- R##_s = _FP_NANSIGN_##fs; \
- _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
- FP_SET_EXCEPTION(FP_EX_INVALID); \
- break; \
- } \
- R##_c = FP_CLS_NORMAL; \
- if (X##_e & 1) \
- _FP_FRAC_SLL_##wc(X, 1); \
- R##_e = X##_e >> 1; \
- _FP_FRAC_SET_##wc(S, _FP_ZEROFRAC_##wc); \
- _FP_FRAC_SET_##wc(R, _FP_ZEROFRAC_##wc); \
- q = _FP_OVERFLOW_##fs >> 1; \
- _FP_SQRT_MEAT_##wc(R, S, T, X, q); \
- } \
- } while (0)
+#define _FP_SQRT(fs, wc, R, X) \
+ do \
+ { \
+ _FP_FRAC_DECL_##wc (T); \
+ _FP_FRAC_DECL_##wc (S); \
+ _FP_W_TYPE q; \
+ switch (X##_c) \
+ { \
+ case FP_CLS_NAN: \
+ _FP_FRAC_COPY_##wc (R, X); \
+ R##_s = X##_s; \
+ R##_c = FP_CLS_NAN; \
+ break; \
+ case FP_CLS_INF: \
+ if (X##_s) \
+ { \
+ R##_s = _FP_NANSIGN_##fs; \
+ R##_c = FP_CLS_NAN; /* NAN */ \
+ _FP_FRAC_SET_##wc (R, _FP_NANFRAC_##fs); \
+ FP_SET_EXCEPTION (FP_EX_INVALID); \
+ } \
+ else \
+ { \
+ R##_s = 0; \
+ R##_c = FP_CLS_INF; /* sqrt(+inf) = +inf */ \
+ } \
+ break; \
+ case FP_CLS_ZERO: \
+ R##_s = X##_s; \
+ R##_c = FP_CLS_ZERO; /* sqrt(+-0) = +-0 */ \
+ break; \
+ case FP_CLS_NORMAL: \
+ R##_s = 0; \
+ if (X##_s) \
+ { \
+ R##_c = FP_CLS_NAN; /* NAN */ \
+ R##_s = _FP_NANSIGN_##fs; \
+ _FP_FRAC_SET_##wc (R, _FP_NANFRAC_##fs); \
+ FP_SET_EXCEPTION (FP_EX_INVALID); \
+ break; \
+ } \
+ R##_c = FP_CLS_NORMAL; \
+ if (X##_e & 1) \
+ _FP_FRAC_SLL_##wc (X, 1); \
+ R##_e = X##_e >> 1; \
+ _FP_FRAC_SET_##wc (S, _FP_ZEROFRAC_##wc); \
+ _FP_FRAC_SET_##wc (R, _FP_ZEROFRAC_##wc); \
+ q = _FP_OVERFLOW_##fs >> 1; \
+ _FP_SQRT_MEAT_##wc (R, S, T, X, q); \
+ } \
+ } \
+ while (0)
/*
* Convert from FP to integer. Input is raw.
@@ -1049,292 +1298,306 @@ do { \
* depending on the sign in such case.
*/
#define _FP_TO_INT(fs, wc, r, X, rsize, rsigned) \
-do { \
- if (X##_e < _FP_EXPBIAS_##fs) \
+ do \
{ \
- r = 0; \
- if (X##_e == 0) \
+ if (X##_e < _FP_EXPBIAS_##fs) \
{ \
- if (!_FP_FRAC_ZEROP_##wc(X)) \
+ r = 0; \
+ if (X##_e == 0) \
{ \
- FP_SET_EXCEPTION(FP_EX_INEXACT); \
- FP_SET_EXCEPTION(FP_EX_DENORM); \
+ if (!_FP_FRAC_ZEROP_##wc (X)) \
+ { \
+ FP_SET_EXCEPTION (FP_EX_INEXACT); \
+ FP_SET_EXCEPTION (FP_EX_DENORM); \
+ } \
} \
+ else \
+ FP_SET_EXCEPTION (FP_EX_INEXACT); \
} \
- else \
- FP_SET_EXCEPTION(FP_EX_INEXACT); \
- } \
- else if (X##_e >= _FP_EXPBIAS_##fs + rsize - (rsigned > 0 || X##_s) \
- || (!rsigned && X##_s)) \
- { \
- /* Overflow or converting to the most negative integer. */ \
- if (rsigned) \
+ else if (X##_e >= _FP_EXPBIAS_##fs + rsize - (rsigned > 0 || X##_s) \
+ || (!rsigned && X##_s)) \
{ \
- r = 1; \
- r <<= rsize - 1; \
- r -= 1 - X##_s; \
- } else { \
- r = 0; \
- if (X##_s) \
- r = ~r; \
- } \
+ /* Overflow or converting to the most negative integer. */ \
+ if (rsigned) \
+ { \
+ r = 1; \
+ r <<= rsize - 1; \
+ r -= 1 - X##_s; \
+ } else { \
+ r = 0; \
+ if (!X##_s) \
+ r = ~r; \
+ } \
\
- if (rsigned && X##_s && X##_e == _FP_EXPBIAS_##fs + rsize - 1) \
- { \
- /* Possibly converting to most negative integer; check the \
- mantissa. */ \
- int inexact = 0; \
- (void)((_FP_FRACBITS_##fs > rsize) \
- ? ({ _FP_FRAC_SRST_##wc(X, inexact, \
- _FP_FRACBITS_##fs - rsize, \
- _FP_FRACBITS_##fs); 0; }) \
- : 0); \
- if (!_FP_FRAC_ZEROP_##wc(X)) \
- FP_SET_EXCEPTION(FP_EX_INVALID); \
- else if (inexact) \
- FP_SET_EXCEPTION(FP_EX_INEXACT); \
+ if (rsigned && X##_s && X##_e == _FP_EXPBIAS_##fs + rsize - 1) \
+ { \
+ /* Possibly converting to most negative integer; check the \
+ mantissa. */ \
+ int inexact = 0; \
+ (void) ((_FP_FRACBITS_##fs > rsize) \
+ ? ({ \
+ _FP_FRAC_SRST_##wc (X, inexact, \
+ _FP_FRACBITS_##fs - rsize, \
+ _FP_FRACBITS_##fs); \
+ 0; \
+ }) \
+ : 0); \
+ if (!_FP_FRAC_ZEROP_##wc (X)) \
+ FP_SET_EXCEPTION (FP_EX_INVALID); \
+ else if (inexact) \
+ FP_SET_EXCEPTION (FP_EX_INEXACT); \
+ } \
+ else \
+ FP_SET_EXCEPTION (FP_EX_INVALID); \
} \
else \
- FP_SET_EXCEPTION(FP_EX_INVALID); \
+ { \
+ _FP_FRAC_HIGH_RAW_##fs (X) |= _FP_IMPLBIT_##fs; \
+ if (X##_e >= _FP_EXPBIAS_##fs + _FP_FRACBITS_##fs - 1) \
+ { \
+ _FP_FRAC_ASSEMBLE_##wc (r, X, rsize); \
+ r <<= X##_e - _FP_EXPBIAS_##fs - _FP_FRACBITS_##fs + 1; \
+ } \
+ else \
+ { \
+ int inexact; \
+ _FP_FRAC_SRST_##wc (X, inexact, \
+ (_FP_FRACBITS_##fs + _FP_EXPBIAS_##fs - 1 \
+ - X##_e), \
+ _FP_FRACBITS_##fs); \
+ if (inexact) \
+ FP_SET_EXCEPTION (FP_EX_INEXACT); \
+ _FP_FRAC_ASSEMBLE_##wc (r, X, rsize); \
+ } \
+ if (rsigned && X##_s) \
+ r = -r; \
+ } \
} \
- else \
+ while (0)
+
+/* Convert integer to fp. Output is raw. RTYPE is unsigned even if
+ input is signed. */
+#define _FP_FROM_INT(fs, wc, X, r, rsize, rtype) \
+ do \
{ \
- _FP_FRAC_HIGH_RAW_##fs(X) |= _FP_IMPLBIT_##fs; \
- if (X##_e >= _FP_EXPBIAS_##fs + _FP_FRACBITS_##fs - 1) \
+ if (r) \
{ \
- _FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \
- r <<= X##_e - _FP_EXPBIAS_##fs - _FP_FRACBITS_##fs + 1; \
+ rtype ur_; \
+ \
+ if ((X##_s = (r < 0))) \
+ r = -(rtype) r; \
+ \
+ ur_ = (rtype) r; \
+ (void) ((rsize <= _FP_W_TYPE_SIZE) \
+ ? ({ \
+ int lz_; \
+ __FP_CLZ (lz_, (_FP_W_TYPE) ur_); \
+ X##_e = _FP_EXPBIAS_##fs + _FP_W_TYPE_SIZE - 1 - lz_; \
+ }) \
+ : ((rsize <= 2 * _FP_W_TYPE_SIZE) \
+ ? ({ \
+ int lz_; \
+ __FP_CLZ_2 (lz_, \
+ (_FP_W_TYPE) (ur_ >> _FP_W_TYPE_SIZE), \
+ (_FP_W_TYPE) ur_); \
+ X##_e = (_FP_EXPBIAS_##fs + 2 * _FP_W_TYPE_SIZE - 1 \
+ - lz_); \
+ }) \
+ : (abort (), 0))); \
+ \
+ if (rsize - 1 + _FP_EXPBIAS_##fs >= _FP_EXPMAX_##fs \
+ && X##_e >= _FP_EXPMAX_##fs) \
+ { \
+ /* Exponent too big; overflow to infinity. (May also \
+ happen after rounding below.) */ \
+ _FP_OVERFLOW_SEMIRAW (fs, wc, X); \
+ goto pack_semiraw; \
+ } \
+ \
+ if (rsize <= _FP_FRACBITS_##fs \
+ || X##_e < _FP_EXPBIAS_##fs + _FP_FRACBITS_##fs) \
+ { \
+ /* Exactly representable; shift left. */ \
+ _FP_FRAC_DISASSEMBLE_##wc (X, ur_, rsize); \
+ if (_FP_EXPBIAS_##fs + _FP_FRACBITS_##fs - 1 - X##_e > 0) \
+ _FP_FRAC_SLL_##wc (X, (_FP_EXPBIAS_##fs \
+ + _FP_FRACBITS_##fs - 1 - X##_e)); \
+ } \
+ else \
+ { \
+ /* More bits in integer than in floating type; need to \
+ round. */ \
+ if (_FP_EXPBIAS_##fs + _FP_WFRACBITS_##fs - 1 < X##_e) \
+ ur_ = ((ur_ >> (X##_e - _FP_EXPBIAS_##fs \
+ - _FP_WFRACBITS_##fs + 1)) \
+ | ((ur_ << (rsize - (X##_e - _FP_EXPBIAS_##fs \
+ - _FP_WFRACBITS_##fs + 1))) \
+ != 0)); \
+ _FP_FRAC_DISASSEMBLE_##wc (X, ur_, rsize); \
+ if ((_FP_EXPBIAS_##fs + _FP_WFRACBITS_##fs - 1 - X##_e) > 0) \
+ _FP_FRAC_SLL_##wc (X, (_FP_EXPBIAS_##fs \
+ + _FP_WFRACBITS_##fs - 1 - X##_e)); \
+ _FP_FRAC_HIGH_##fs (X) &= ~(_FP_W_TYPE) _FP_IMPLBIT_SH_##fs; \
+ pack_semiraw: \
+ _FP_PACK_SEMIRAW (fs, wc, X); \
+ } \
} \
else \
{ \
- int inexact; \
- _FP_FRAC_SRST_##wc(X, inexact, \
- (_FP_FRACBITS_##fs + _FP_EXPBIAS_##fs - 1 \
- - X##_e), \
- _FP_FRACBITS_##fs); \
- if (inexact) \
- FP_SET_EXCEPTION(FP_EX_INEXACT); \
- _FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \
+ X##_s = 0; \
+ X##_e = 0; \
+ _FP_FRAC_SET_##wc (X, _FP_ZEROFRAC_##wc); \
} \
- if (rsigned && X##_s) \
- r = -r; \
} \
-} while (0)
-
-/* Convert integer to fp. Output is raw. RTYPE is unsigned even if
- input is signed. */
-#define _FP_FROM_INT(fs, wc, X, r, rsize, rtype) \
- do { \
- if (r) \
- { \
- rtype ur_; \
- \
- if ((X##_s = (r < 0))) \
- r = -(rtype)r; \
- \
- ur_ = (rtype) r; \
- (void)((rsize <= _FP_W_TYPE_SIZE) \
- ? ({ \
- int lz_; \
- __FP_CLZ(lz_, (_FP_W_TYPE)ur_); \
- X##_e = _FP_EXPBIAS_##fs + _FP_W_TYPE_SIZE - 1 - lz_; \
- }) \
- : ((rsize <= 2 * _FP_W_TYPE_SIZE) \
- ? ({ \
- int lz_; \
- __FP_CLZ_2(lz_, (_FP_W_TYPE)(ur_ >> _FP_W_TYPE_SIZE), \
- (_FP_W_TYPE)ur_); \
- X##_e = (_FP_EXPBIAS_##fs + 2 * _FP_W_TYPE_SIZE - 1 \
- - lz_); \
- }) \
- : (abort(), 0))); \
- \
- if (rsize - 1 + _FP_EXPBIAS_##fs >= _FP_EXPMAX_##fs \
- && X##_e >= _FP_EXPMAX_##fs) \
- { \
- /* Exponent too big; overflow to infinity. (May also \
- happen after rounding below.) */ \
- _FP_OVERFLOW_SEMIRAW(fs, wc, X); \
- goto pack_semiraw; \
- } \
- \
- if (rsize <= _FP_FRACBITS_##fs \
- || X##_e < _FP_EXPBIAS_##fs + _FP_FRACBITS_##fs) \
- { \
- /* Exactly representable; shift left. */ \
- _FP_FRAC_DISASSEMBLE_##wc(X, ur_, rsize); \
- if (_FP_EXPBIAS_##fs + _FP_FRACBITS_##fs - 1 - X##_e > 0) \
- _FP_FRAC_SLL_##wc(X, (_FP_EXPBIAS_##fs \
- + _FP_FRACBITS_##fs - 1 - X##_e)); \
- } \
- else \
- { \
- /* More bits in integer than in floating type; need to \
- round. */ \
- if (_FP_EXPBIAS_##fs + _FP_WFRACBITS_##fs - 1 < X##_e) \
- ur_ = ((ur_ >> (X##_e - _FP_EXPBIAS_##fs \
- - _FP_WFRACBITS_##fs + 1)) \
- | ((ur_ << (rsize - (X##_e - _FP_EXPBIAS_##fs \
- - _FP_WFRACBITS_##fs + 1))) \
- != 0)); \
- _FP_FRAC_DISASSEMBLE_##wc(X, ur_, rsize); \
- if ((_FP_EXPBIAS_##fs + _FP_WFRACBITS_##fs - 1 - X##_e) > 0) \
- _FP_FRAC_SLL_##wc(X, (_FP_EXPBIAS_##fs \
- + _FP_WFRACBITS_##fs - 1 - X##_e)); \
- _FP_FRAC_HIGH_##fs(X) &= ~(_FP_W_TYPE)_FP_IMPLBIT_SH_##fs; \
- pack_semiraw: \
- _FP_PACK_SEMIRAW(fs, wc, X); \
- } \
- } \
- else \
- { \
- X##_s = 0; \
- X##_e = 0; \
- _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
- } \
- } while (0)
+ while (0)
/* Extend from a narrower floating-point format to a wider one. Input
and output are raw. */
-#define FP_EXTEND(dfs,sfs,dwc,swc,D,S) \
-do { \
- if (_FP_FRACBITS_##dfs < _FP_FRACBITS_##sfs \
- || (_FP_EXPMAX_##dfs - _FP_EXPBIAS_##dfs \
- < _FP_EXPMAX_##sfs - _FP_EXPBIAS_##sfs) \
- || (_FP_EXPBIAS_##dfs < _FP_EXPBIAS_##sfs + _FP_FRACBITS_##sfs - 1 \
- && _FP_EXPBIAS_##dfs != _FP_EXPBIAS_##sfs)) \
- abort(); \
- D##_s = S##_s; \
- _FP_FRAC_COPY_##dwc##_##swc(D, S); \
- if (_FP_EXP_NORMAL(sfs, swc, S)) \
- { \
- D##_e = S##_e + _FP_EXPBIAS_##dfs - _FP_EXPBIAS_##sfs; \
- _FP_FRAC_SLL_##dwc(D, (_FP_FRACBITS_##dfs - _FP_FRACBITS_##sfs)); \
- } \
- else \
- { \
- if (S##_e == 0) \
- { \
- if (_FP_FRAC_ZEROP_##swc(S)) \
- D##_e = 0; \
- else if (_FP_EXPBIAS_##dfs \
- < _FP_EXPBIAS_##sfs + _FP_FRACBITS_##sfs - 1) \
- { \
- FP_SET_EXCEPTION(FP_EX_DENORM); \
- _FP_FRAC_SLL_##dwc(D, (_FP_FRACBITS_##dfs \
- - _FP_FRACBITS_##sfs)); \
- D##_e = 0; \
- } \
- else \
- { \
- int _lz; \
- FP_SET_EXCEPTION(FP_EX_DENORM); \
- _FP_FRAC_CLZ_##swc(_lz, S); \
- _FP_FRAC_SLL_##dwc(D, \
- _lz + _FP_FRACBITS_##dfs \
- - _FP_FRACTBITS_##sfs); \
- D##_e = (_FP_EXPBIAS_##dfs - _FP_EXPBIAS_##sfs + 1 \
- + _FP_FRACXBITS_##sfs - _lz); \
- } \
- } \
- else \
- { \
- D##_e = _FP_EXPMAX_##dfs; \
- if (!_FP_FRAC_ZEROP_##swc(S)) \
- { \
- if (_FP_FRAC_SNANP(sfs, S)) \
- FP_SET_EXCEPTION(FP_EX_INVALID); \
- _FP_FRAC_SLL_##dwc(D, (_FP_FRACBITS_##dfs \
- - _FP_FRACBITS_##sfs)); \
- } \
- } \
- } \
-} while (0)
+#define FP_EXTEND(dfs, sfs, dwc, swc, D, S) \
+ do \
+ { \
+ if (_FP_FRACBITS_##dfs < _FP_FRACBITS_##sfs \
+ || (_FP_EXPMAX_##dfs - _FP_EXPBIAS_##dfs \
+ < _FP_EXPMAX_##sfs - _FP_EXPBIAS_##sfs) \
+ || (_FP_EXPBIAS_##dfs < _FP_EXPBIAS_##sfs + _FP_FRACBITS_##sfs - 1 \
+ && _FP_EXPBIAS_##dfs != _FP_EXPBIAS_##sfs)) \
+ abort (); \
+ D##_s = S##_s; \
+ _FP_FRAC_COPY_##dwc##_##swc (D, S); \
+ if (_FP_EXP_NORMAL (sfs, swc, S)) \
+ { \
+ D##_e = S##_e + _FP_EXPBIAS_##dfs - _FP_EXPBIAS_##sfs; \
+ _FP_FRAC_SLL_##dwc (D, (_FP_FRACBITS_##dfs - _FP_FRACBITS_##sfs)); \
+ } \
+ else \
+ { \
+ if (S##_e == 0) \
+ { \
+ if (_FP_FRAC_ZEROP_##swc (S)) \
+ D##_e = 0; \
+ else if (_FP_EXPBIAS_##dfs \
+ < _FP_EXPBIAS_##sfs + _FP_FRACBITS_##sfs - 1) \
+ { \
+ FP_SET_EXCEPTION (FP_EX_DENORM); \
+ _FP_FRAC_SLL_##dwc (D, (_FP_FRACBITS_##dfs \
+ - _FP_FRACBITS_##sfs)); \
+ D##_e = 0; \
+ } \
+ else \
+ { \
+ int _lz; \
+ FP_SET_EXCEPTION (FP_EX_DENORM); \
+ _FP_FRAC_CLZ_##swc (_lz, S); \
+ _FP_FRAC_SLL_##dwc (D, \
+ _lz + _FP_FRACBITS_##dfs \
+ - _FP_FRACTBITS_##sfs); \
+ D##_e = (_FP_EXPBIAS_##dfs - _FP_EXPBIAS_##sfs + 1 \
+ + _FP_FRACXBITS_##sfs - _lz); \
+ } \
+ } \
+ else \
+ { \
+ D##_e = _FP_EXPMAX_##dfs; \
+ if (!_FP_FRAC_ZEROP_##swc (S)) \
+ { \
+ if (_FP_FRAC_SNANP (sfs, S)) \
+ FP_SET_EXCEPTION (FP_EX_INVALID); \
+ _FP_FRAC_SLL_##dwc (D, (_FP_FRACBITS_##dfs \
+ - _FP_FRACBITS_##sfs)); \
+ _FP_SETQNAN (dfs, dwc, D); \
+ } \
+ } \
+ } \
+ } \
+ while (0)
/* Truncate from a wider floating-point format to a narrower one.
Input and output are semi-raw. */
-#define FP_TRUNC(dfs,sfs,dwc,swc,D,S) \
-do { \
- if (_FP_FRACBITS_##sfs < _FP_FRACBITS_##dfs \
- || (_FP_EXPBIAS_##sfs < _FP_EXPBIAS_##dfs + _FP_FRACBITS_##dfs - 1 \
- && _FP_EXPBIAS_##sfs != _FP_EXPBIAS_##dfs)) \
- abort(); \
- D##_s = S##_s; \
- if (_FP_EXP_NORMAL(sfs, swc, S)) \
- { \
- D##_e = S##_e + _FP_EXPBIAS_##dfs - _FP_EXPBIAS_##sfs; \
- if (D##_e >= _FP_EXPMAX_##dfs) \
- _FP_OVERFLOW_SEMIRAW(dfs, dwc, D); \
- else \
- { \
- if (D##_e <= 0) \
- { \
- if (D##_e < 1 - _FP_FRACBITS_##dfs) \
- { \
- _FP_FRAC_SET_##swc(S, _FP_ZEROFRAC_##swc); \
- _FP_FRAC_LOW_##swc(S) |= 1; \
- } \
- else \
- { \
- _FP_FRAC_HIGH_##sfs(S) |= _FP_IMPLBIT_SH_##sfs; \
- _FP_FRAC_SRS_##swc(S, (_FP_WFRACBITS_##sfs \
- - _FP_WFRACBITS_##dfs + 1 - D##_e), \
- _FP_WFRACBITS_##sfs); \
- } \
- D##_e = 0; \
- } \
- else \
- _FP_FRAC_SRS_##swc(S, (_FP_WFRACBITS_##sfs \
- - _FP_WFRACBITS_##dfs), \
- _FP_WFRACBITS_##sfs); \
- _FP_FRAC_COPY_##dwc##_##swc(D, S); \
- } \
- } \
- else \
- { \
- if (S##_e == 0) \
- { \
- D##_e = 0; \
- if (_FP_FRAC_ZEROP_##swc(S)) \
- _FP_FRAC_SET_##dwc(D, _FP_ZEROFRAC_##dwc); \
- else \
- { \
- FP_SET_EXCEPTION(FP_EX_DENORM); \
- if (_FP_EXPBIAS_##sfs \
- < _FP_EXPBIAS_##dfs + _FP_FRACBITS_##dfs - 1) \
- { \
- _FP_FRAC_SRS_##swc(S, (_FP_WFRACBITS_##sfs \
- - _FP_WFRACBITS_##dfs), \
- _FP_WFRACBITS_##sfs); \
- _FP_FRAC_COPY_##dwc##_##swc(D, S); \
- } \
- else \
- { \
- _FP_FRAC_SET_##dwc(D, _FP_ZEROFRAC_##dwc); \
- _FP_FRAC_LOW_##dwc(D) |= 1; \
- } \
- } \
- } \
- else \
- { \
- D##_e = _FP_EXPMAX_##dfs; \
- if (_FP_FRAC_ZEROP_##swc(S)) \
- _FP_FRAC_SET_##dwc(D, _FP_ZEROFRAC_##dwc); \
- else \
- { \
- _FP_CHECK_SIGNAN_SEMIRAW(sfs, swc, S); \
- _FP_FRAC_SRL_##swc(S, (_FP_WFRACBITS_##sfs \
- - _FP_WFRACBITS_##dfs)); \
- _FP_FRAC_COPY_##dwc##_##swc(D, S); \
- /* Semi-raw NaN must have all workbits cleared. */ \
- _FP_FRAC_LOW_##dwc(D) \
- &= ~(_FP_W_TYPE) ((1 << _FP_WORKBITS) - 1); \
- _FP_SETQNAN_SEMIRAW(dfs, dwc, D); \
- } \
- } \
- } \
-} while (0)
+#define FP_TRUNC(dfs, sfs, dwc, swc, D, S) \
+ do \
+ { \
+ if (_FP_FRACBITS_##sfs < _FP_FRACBITS_##dfs \
+ || (_FP_EXPBIAS_##sfs < _FP_EXPBIAS_##dfs + _FP_FRACBITS_##dfs - 1 \
+ && _FP_EXPBIAS_##sfs != _FP_EXPBIAS_##dfs)) \
+ abort (); \
+ D##_s = S##_s; \
+ if (_FP_EXP_NORMAL (sfs, swc, S)) \
+ { \
+ D##_e = S##_e + _FP_EXPBIAS_##dfs - _FP_EXPBIAS_##sfs; \
+ if (D##_e >= _FP_EXPMAX_##dfs) \
+ _FP_OVERFLOW_SEMIRAW (dfs, dwc, D); \
+ else \
+ { \
+ if (D##_e <= 0) \
+ { \
+ if (D##_e < 1 - _FP_FRACBITS_##dfs) \
+ { \
+ _FP_FRAC_SET_##swc (S, _FP_ZEROFRAC_##swc); \
+ _FP_FRAC_LOW_##swc (S) |= 1; \
+ } \
+ else \
+ { \
+ _FP_FRAC_HIGH_##sfs (S) |= _FP_IMPLBIT_SH_##sfs; \
+ _FP_FRAC_SRS_##swc (S, (_FP_WFRACBITS_##sfs \
+ - _FP_WFRACBITS_##dfs \
+ + 1 - D##_e), \
+ _FP_WFRACBITS_##sfs); \
+ } \
+ D##_e = 0; \
+ } \
+ else \
+ _FP_FRAC_SRS_##swc (S, (_FP_WFRACBITS_##sfs \
+ - _FP_WFRACBITS_##dfs), \
+ _FP_WFRACBITS_##sfs); \
+ _FP_FRAC_COPY_##dwc##_##swc (D, S); \
+ } \
+ } \
+ else \
+ { \
+ if (S##_e == 0) \
+ { \
+ D##_e = 0; \
+ if (_FP_FRAC_ZEROP_##swc (S)) \
+ _FP_FRAC_SET_##dwc (D, _FP_ZEROFRAC_##dwc); \
+ else \
+ { \
+ FP_SET_EXCEPTION (FP_EX_DENORM); \
+ if (_FP_EXPBIAS_##sfs \
+ < _FP_EXPBIAS_##dfs + _FP_FRACBITS_##dfs - 1) \
+ { \
+ _FP_FRAC_SRS_##swc (S, (_FP_WFRACBITS_##sfs \
+ - _FP_WFRACBITS_##dfs), \
+ _FP_WFRACBITS_##sfs); \
+ _FP_FRAC_COPY_##dwc##_##swc (D, S); \
+ } \
+ else \
+ { \
+ _FP_FRAC_SET_##dwc (D, _FP_ZEROFRAC_##dwc); \
+ _FP_FRAC_LOW_##dwc (D) |= 1; \
+ } \
+ } \
+ } \
+ else \
+ { \
+ D##_e = _FP_EXPMAX_##dfs; \
+ if (_FP_FRAC_ZEROP_##swc (S)) \
+ _FP_FRAC_SET_##dwc (D, _FP_ZEROFRAC_##dwc); \
+ else \
+ { \
+ _FP_CHECK_SIGNAN_SEMIRAW (sfs, swc, S); \
+ _FP_FRAC_SRL_##swc (S, (_FP_WFRACBITS_##sfs \
+ - _FP_WFRACBITS_##dfs)); \
+ _FP_FRAC_COPY_##dwc##_##swc (D, S); \
+ /* Semi-raw NaN must have all workbits cleared. */ \
+ _FP_FRAC_LOW_##dwc (D) \
+ &= ~(_FP_W_TYPE) ((1 << _FP_WORKBITS) - 1); \
+ _FP_SETQNAN_SEMIRAW (dfs, dwc, D); \
+ } \
+ } \
+ } \
+ } \
+ while (0)
/*
* Helper primitives.
@@ -1344,64 +1607,72 @@ do { \
#ifndef __FP_CLZ
/* GCC 3.4 and later provide the builtins for us. */
-#define __FP_CLZ(r, x) \
- do { \
- if (sizeof (_FP_W_TYPE) == sizeof (unsigned int)) \
- r = __builtin_clz (x); \
- else if (sizeof (_FP_W_TYPE) == sizeof (unsigned long)) \
- r = __builtin_clzl (x); \
- else if (sizeof (_FP_W_TYPE) == sizeof (unsigned long long)) \
- r = __builtin_clzll (x); \
- else \
- abort (); \
- } while (0)
+# define __FP_CLZ(r, x) \
+ do \
+ { \
+ if (sizeof (_FP_W_TYPE) == sizeof (unsigned int)) \
+ r = __builtin_clz (x); \
+ else if (sizeof (_FP_W_TYPE) == sizeof (unsigned long)) \
+ r = __builtin_clzl (x); \
+ else if (sizeof (_FP_W_TYPE) == sizeof (unsigned long long)) \
+ r = __builtin_clzll (x); \
+ else \
+ abort (); \
+ } \
+ while (0)
#endif /* ndef __FP_CLZ */
#define _FP_DIV_HELP_imm(q, r, n, d) \
- do { \
- q = n / d, r = n % d; \
- } while (0)
+ do \
+ { \
+ q = n / d, r = n % d; \
+ } \
+ while (0)
/* A restoring bit-by-bit division primitive. */
#define _FP_DIV_MEAT_N_loop(fs, wc, R, X, Y) \
- do { \
- int count = _FP_WFRACBITS_##fs; \
- _FP_FRAC_DECL_##wc (u); \
- _FP_FRAC_DECL_##wc (v); \
- _FP_FRAC_COPY_##wc (u, X); \
- _FP_FRAC_COPY_##wc (v, Y); \
- _FP_FRAC_SET_##wc (R, _FP_ZEROFRAC_##wc); \
- /* Normalize U and V. */ \
- _FP_FRAC_SLL_##wc (u, _FP_WFRACXBITS_##fs); \
- _FP_FRAC_SLL_##wc (v, _FP_WFRACXBITS_##fs); \
- /* First round. Since the operands are normalized, either the \
- first or second bit will be set in the fraction. Produce a \
- normalized result by checking which and adjusting the loop \
- count and exponent accordingly. */ \
- if (_FP_FRAC_GE_1 (u, v)) \
- { \
- _FP_FRAC_SUB_##wc (u, u, v); \
- _FP_FRAC_LOW_##wc (R) |= 1; \
- count--; \
- } \
- else \
- R##_e--; \
- /* Subsequent rounds. */ \
- do { \
- int msb = (_FP_WS_TYPE) _FP_FRAC_HIGH_##wc (u) < 0; \
- _FP_FRAC_SLL_##wc (u, 1); \
- _FP_FRAC_SLL_##wc (R, 1); \
- if (msb || _FP_FRAC_GE_1 (u, v)) \
+ do \
+ { \
+ int count = _FP_WFRACBITS_##fs; \
+ _FP_FRAC_DECL_##wc (u); \
+ _FP_FRAC_DECL_##wc (v); \
+ _FP_FRAC_COPY_##wc (u, X); \
+ _FP_FRAC_COPY_##wc (v, Y); \
+ _FP_FRAC_SET_##wc (R, _FP_ZEROFRAC_##wc); \
+ /* Normalize U and V. */ \
+ _FP_FRAC_SLL_##wc (u, _FP_WFRACXBITS_##fs); \
+ _FP_FRAC_SLL_##wc (v, _FP_WFRACXBITS_##fs); \
+ /* First round. Since the operands are normalized, either the \
+ first or second bit will be set in the fraction. Produce a \
+ normalized result by checking which and adjusting the loop \
+ count and exponent accordingly. */ \
+ if (_FP_FRAC_GE_1 (u, v)) \
{ \
_FP_FRAC_SUB_##wc (u, u, v); \
_FP_FRAC_LOW_##wc (R) |= 1; \
+ count--; \
} \
- } while (--count > 0); \
- /* If there's anything left in U, the result is inexact. */ \
- _FP_FRAC_LOW_##wc (R) |= !_FP_FRAC_ZEROP_##wc (u); \
- } while (0)
+ else \
+ R##_e--; \
+ /* Subsequent rounds. */ \
+ do \
+ { \
+ int msb = (_FP_WS_TYPE) _FP_FRAC_HIGH_##wc (u) < 0; \
+ _FP_FRAC_SLL_##wc (u, 1); \
+ _FP_FRAC_SLL_##wc (R, 1); \
+ if (msb || _FP_FRAC_GE_1 (u, v)) \
+ { \
+ _FP_FRAC_SUB_##wc (u, u, v); \
+ _FP_FRAC_LOW_##wc (R) |= 1; \
+ } \
+ } \
+ while (--count > 0); \
+ /* If there's anything left in U, the result is inexact. */ \
+ _FP_FRAC_LOW_##wc (R) |= !_FP_FRAC_ZEROP_##wc (u); \
+ } \
+ while (0)
#define _FP_DIV_MEAT_1_loop(fs, R, X, Y) _FP_DIV_MEAT_N_loop (fs, 1, R, X, Y)
#define _FP_DIV_MEAT_2_loop(fs, R, X, Y) _FP_DIV_MEAT_N_loop (fs, 2, R, X, Y)
diff --git a/libgcc/soft-fp/quad.h b/libgcc/soft-fp/quad.h
index f0aa07e74f1..5002da5a533 100644
--- a/libgcc/soft-fp/quad.h
+++ b/libgcc/soft-fp/quad.h
@@ -31,13 +31,15 @@
<http://www.gnu.org/licenses/>. */
#if _FP_W_TYPE_SIZE < 32
-#error "Here's a nickel, kid. Go buy yourself a real computer."
+# error "Here's a nickel, kid. Go buy yourself a real computer."
#endif
#if _FP_W_TYPE_SIZE < 64
-#define _FP_FRACTBITS_Q (4*_FP_W_TYPE_SIZE)
+# define _FP_FRACTBITS_Q (4*_FP_W_TYPE_SIZE)
+# define _FP_FRACTBITS_DW_Q (8*_FP_W_TYPE_SIZE)
#else
-#define _FP_FRACTBITS_Q (2*_FP_W_TYPE_SIZE)
+# define _FP_FRACTBITS_Q (2*_FP_W_TYPE_SIZE)
+# define _FP_FRACTBITS_DW_Q (4*_FP_W_TYPE_SIZE)
#endif
#define _FP_FRACBITS_Q 113
@@ -49,222 +51,271 @@
#define _FP_EXPMAX_Q 32767
#define _FP_QNANBIT_Q \
- ((_FP_W_TYPE)1 << (_FP_FRACBITS_Q-2) % _FP_W_TYPE_SIZE)
+ ((_FP_W_TYPE) 1 << (_FP_FRACBITS_Q-2) % _FP_W_TYPE_SIZE)
#define _FP_QNANBIT_SH_Q \
- ((_FP_W_TYPE)1 << (_FP_FRACBITS_Q-2+_FP_WORKBITS) % _FP_W_TYPE_SIZE)
+ ((_FP_W_TYPE) 1 << (_FP_FRACBITS_Q-2+_FP_WORKBITS) % _FP_W_TYPE_SIZE)
#define _FP_IMPLBIT_Q \
- ((_FP_W_TYPE)1 << (_FP_FRACBITS_Q-1) % _FP_W_TYPE_SIZE)
+ ((_FP_W_TYPE) 1 << (_FP_FRACBITS_Q-1) % _FP_W_TYPE_SIZE)
#define _FP_IMPLBIT_SH_Q \
- ((_FP_W_TYPE)1 << (_FP_FRACBITS_Q-1+_FP_WORKBITS) % _FP_W_TYPE_SIZE)
+ ((_FP_W_TYPE) 1 << (_FP_FRACBITS_Q-1+_FP_WORKBITS) % _FP_W_TYPE_SIZE)
#define _FP_OVERFLOW_Q \
- ((_FP_W_TYPE)1 << (_FP_WFRACBITS_Q % _FP_W_TYPE_SIZE))
+ ((_FP_W_TYPE) 1 << (_FP_WFRACBITS_Q % _FP_W_TYPE_SIZE))
-typedef float TFtype __attribute__((mode(TF)));
+#define _FP_WFRACBITS_DW_Q (2 * _FP_WFRACBITS_Q)
+#define _FP_WFRACXBITS_DW_Q (_FP_FRACTBITS_DW_Q - _FP_WFRACBITS_DW_Q)
+#define _FP_HIGHBIT_DW_Q \
+ ((_FP_W_TYPE) 1 << (_FP_WFRACBITS_DW_Q - 1) % _FP_W_TYPE_SIZE)
+
+typedef float TFtype __attribute__ ((mode (TF)));
#if _FP_W_TYPE_SIZE < 64
union _FP_UNION_Q
{
- TFtype flt;
- struct _FP_STRUCT_LAYOUT
- {
-#if __BYTE_ORDER == __BIG_ENDIAN
- unsigned sign : 1;
- unsigned exp : _FP_EXPBITS_Q;
- unsigned long frac3 : _FP_FRACBITS_Q - (_FP_IMPLBIT_Q != 0)-(_FP_W_TYPE_SIZE * 3);
- unsigned long frac2 : _FP_W_TYPE_SIZE;
- unsigned long frac1 : _FP_W_TYPE_SIZE;
- unsigned long frac0 : _FP_W_TYPE_SIZE;
-#else
- unsigned long frac0 : _FP_W_TYPE_SIZE;
- unsigned long frac1 : _FP_W_TYPE_SIZE;
- unsigned long frac2 : _FP_W_TYPE_SIZE;
- unsigned long frac3 : _FP_FRACBITS_Q - (_FP_IMPLBIT_Q != 0)-(_FP_W_TYPE_SIZE * 3);
- unsigned exp : _FP_EXPBITS_Q;
- unsigned sign : 1;
-#endif /* not bigendian */
- } bits __attribute__((packed));
+ TFtype flt;
+ struct _FP_STRUCT_LAYOUT
+ {
+# if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned sign : 1;
+ unsigned exp : _FP_EXPBITS_Q;
+ unsigned long frac3 : _FP_FRACBITS_Q - (_FP_IMPLBIT_Q != 0)-(_FP_W_TYPE_SIZE * 3);
+ unsigned long frac2 : _FP_W_TYPE_SIZE;
+ unsigned long frac1 : _FP_W_TYPE_SIZE;
+ unsigned long frac0 : _FP_W_TYPE_SIZE;
+# else
+ unsigned long frac0 : _FP_W_TYPE_SIZE;
+ unsigned long frac1 : _FP_W_TYPE_SIZE;
+ unsigned long frac2 : _FP_W_TYPE_SIZE;
+ unsigned long frac3 : _FP_FRACBITS_Q - (_FP_IMPLBIT_Q != 0)-(_FP_W_TYPE_SIZE * 3);
+ unsigned exp : _FP_EXPBITS_Q;
+ unsigned sign : 1;
+# endif /* not bigendian */
+ } bits __attribute__ ((packed));
};
-#define FP_DECL_Q(X) _FP_DECL(4,X)
-#define FP_UNPACK_RAW_Q(X,val) _FP_UNPACK_RAW_4(Q,X,val)
-#define FP_UNPACK_RAW_QP(X,val) _FP_UNPACK_RAW_4_P(Q,X,val)
-#define FP_PACK_RAW_Q(val,X) _FP_PACK_RAW_4(Q,val,X)
-#define FP_PACK_RAW_QP(val,X) \
- do { \
- if (!FP_INHIBIT_RESULTS) \
- _FP_PACK_RAW_4_P(Q,val,X); \
- } while (0)
-
-#define FP_UNPACK_Q(X,val) \
- do { \
- _FP_UNPACK_RAW_4(Q,X,val); \
- _FP_UNPACK_CANONICAL(Q,4,X); \
- } while (0)
-
-#define FP_UNPACK_QP(X,val) \
- do { \
- _FP_UNPACK_RAW_4_P(Q,X,val); \
- _FP_UNPACK_CANONICAL(Q,4,X); \
- } while (0)
-
-#define FP_UNPACK_SEMIRAW_Q(X,val) \
- do { \
- _FP_UNPACK_RAW_4(Q,X,val); \
- _FP_UNPACK_SEMIRAW(Q,4,X); \
- } while (0)
-
-#define FP_UNPACK_SEMIRAW_QP(X,val) \
- do { \
- _FP_UNPACK_RAW_4_P(Q,X,val); \
- _FP_UNPACK_SEMIRAW(Q,4,X); \
- } while (0)
-
-#define FP_PACK_Q(val,X) \
- do { \
- _FP_PACK_CANONICAL(Q,4,X); \
- _FP_PACK_RAW_4(Q,val,X); \
- } while (0)
-
-#define FP_PACK_QP(val,X) \
- do { \
- _FP_PACK_CANONICAL(Q,4,X); \
- if (!FP_INHIBIT_RESULTS) \
- _FP_PACK_RAW_4_P(Q,val,X); \
- } while (0)
-
-#define FP_PACK_SEMIRAW_Q(val,X) \
- do { \
- _FP_PACK_SEMIRAW(Q,4,X); \
- _FP_PACK_RAW_4(Q,val,X); \
- } while (0)
-
-#define FP_PACK_SEMIRAW_QP(val,X) \
- do { \
- _FP_PACK_SEMIRAW(Q,4,X); \
- if (!FP_INHIBIT_RESULTS) \
- _FP_PACK_RAW_4_P(Q,val,X); \
- } while (0)
-
-#define FP_ISSIGNAN_Q(X) _FP_ISSIGNAN(Q,4,X)
-#define FP_NEG_Q(R,X) _FP_NEG(Q,4,R,X)
-#define FP_ADD_Q(R,X,Y) _FP_ADD(Q,4,R,X,Y)
-#define FP_SUB_Q(R,X,Y) _FP_SUB(Q,4,R,X,Y)
-#define FP_MUL_Q(R,X,Y) _FP_MUL(Q,4,R,X,Y)
-#define FP_DIV_Q(R,X,Y) _FP_DIV(Q,4,R,X,Y)
-#define FP_SQRT_Q(R,X) _FP_SQRT(Q,4,R,X)
-#define _FP_SQRT_MEAT_Q(R,S,T,X,Q) _FP_SQRT_MEAT_4(R,S,T,X,Q)
-
-#define FP_CMP_Q(r,X,Y,un) _FP_CMP(Q,4,r,X,Y,un)
-#define FP_CMP_EQ_Q(r,X,Y) _FP_CMP_EQ(Q,4,r,X,Y)
-#define FP_CMP_UNORD_Q(r,X,Y) _FP_CMP_UNORD(Q,4,r,X,Y)
-
-#define FP_TO_INT_Q(r,X,rsz,rsg) _FP_TO_INT(Q,4,r,X,rsz,rsg)
-#define FP_FROM_INT_Q(X,r,rs,rt) _FP_FROM_INT(Q,4,X,r,rs,rt)
-
-#define _FP_FRAC_HIGH_Q(X) _FP_FRAC_HIGH_4(X)
-#define _FP_FRAC_HIGH_RAW_Q(X) _FP_FRAC_HIGH_4(X)
+# define FP_DECL_Q(X) _FP_DECL (4, X)
+# define FP_UNPACK_RAW_Q(X, val) _FP_UNPACK_RAW_4 (Q, X, val)
+# define FP_UNPACK_RAW_QP(X, val) _FP_UNPACK_RAW_4_P (Q, X, val)
+# define FP_PACK_RAW_Q(val, X) _FP_PACK_RAW_4 (Q, val, X)
+# define FP_PACK_RAW_QP(val, X) \
+ do \
+ { \
+ if (!FP_INHIBIT_RESULTS) \
+ _FP_PACK_RAW_4_P (Q, val, X); \
+ } \
+ while (0)
+
+# define FP_UNPACK_Q(X, val) \
+ do \
+ { \
+ _FP_UNPACK_RAW_4 (Q, X, val); \
+ _FP_UNPACK_CANONICAL (Q, 4, X); \
+ } \
+ while (0)
+
+# define FP_UNPACK_QP(X, val) \
+ do \
+ { \
+ _FP_UNPACK_RAW_4_P (Q, X, val); \
+ _FP_UNPACK_CANONICAL (Q, 4, X); \
+ } \
+ while (0)
+
+# define FP_UNPACK_SEMIRAW_Q(X, val) \
+ do \
+ { \
+ _FP_UNPACK_RAW_4 (Q, X, val); \
+ _FP_UNPACK_SEMIRAW (Q, 4, X); \
+ } \
+ while (0)
+
+# define FP_UNPACK_SEMIRAW_QP(X, val) \
+ do \
+ { \
+ _FP_UNPACK_RAW_4_P (Q, X, val); \
+ _FP_UNPACK_SEMIRAW (Q, 4, X); \
+ } \
+ while (0)
+
+# define FP_PACK_Q(val, X) \
+ do \
+ { \
+ _FP_PACK_CANONICAL (Q, 4, X); \
+ _FP_PACK_RAW_4 (Q, val, X); \
+ } \
+ while (0)
+
+# define FP_PACK_QP(val, X) \
+ do \
+ { \
+ _FP_PACK_CANONICAL (Q, 4, X); \
+ if (!FP_INHIBIT_RESULTS) \
+ _FP_PACK_RAW_4_P (Q, val, X); \
+ } \
+ while (0)
+
+# define FP_PACK_SEMIRAW_Q(val, X) \
+ do \
+ { \
+ _FP_PACK_SEMIRAW (Q, 4, X); \
+ _FP_PACK_RAW_4 (Q, val, X); \
+ } \
+ while (0)
+
+# define FP_PACK_SEMIRAW_QP(val, X) \
+ do \
+ { \
+ _FP_PACK_SEMIRAW (Q, 4, X); \
+ if (!FP_INHIBIT_RESULTS) \
+ _FP_PACK_RAW_4_P (Q, val, X); \
+ } \
+ while (0)
+
+# define FP_ISSIGNAN_Q(X) _FP_ISSIGNAN (Q, 4, X)
+# define FP_NEG_Q(R, X) _FP_NEG (Q, 4, R, X)
+# define FP_ADD_Q(R, X, Y) _FP_ADD (Q, 4, R, X, Y)
+# define FP_SUB_Q(R, X, Y) _FP_SUB (Q, 4, R, X, Y)
+# define FP_MUL_Q(R, X, Y) _FP_MUL (Q, 4, R, X, Y)
+# define FP_DIV_Q(R, X, Y) _FP_DIV (Q, 4, R, X, Y)
+# define FP_SQRT_Q(R, X) _FP_SQRT (Q, 4, R, X)
+# define _FP_SQRT_MEAT_Q(R, S, T, X, Q) _FP_SQRT_MEAT_4 (R, S, T, X, Q)
+# define FP_FMA_Q(R, X, Y, Z) _FP_FMA (Q, 4, 8, R, X, Y, Z)
+
+# define FP_CMP_Q(r, X, Y, un) _FP_CMP (Q, 4, r, X, Y, un)
+# define FP_CMP_EQ_Q(r, X, Y) _FP_CMP_EQ (Q, 4, r, X, Y)
+# define FP_CMP_UNORD_Q(r, X, Y) _FP_CMP_UNORD (Q, 4, r, X, Y)
+
+# define FP_TO_INT_Q(r, X, rsz, rsg) _FP_TO_INT (Q, 4, r, X, rsz, rsg)
+# define FP_FROM_INT_Q(X, r, rs, rt) _FP_FROM_INT (Q, 4, X, r, rs, rt)
+
+# define _FP_FRAC_HIGH_Q(X) _FP_FRAC_HIGH_4 (X)
+# define _FP_FRAC_HIGH_RAW_Q(X) _FP_FRAC_HIGH_4 (X)
+
+# define _FP_FRAC_HIGH_DW_Q(X) _FP_FRAC_HIGH_8 (X)
#else /* not _FP_W_TYPE_SIZE < 64 */
union _FP_UNION_Q
{
- TFtype flt /* __attribute__((mode(TF))) */ ;
- struct _FP_STRUCT_LAYOUT {
+ TFtype flt /* __attribute__ ((mode (TF))) */ ;
+ struct _FP_STRUCT_LAYOUT
+ {
_FP_W_TYPE a, b;
} longs;
- struct _FP_STRUCT_LAYOUT {
-#if __BYTE_ORDER == __BIG_ENDIAN
+ struct _FP_STRUCT_LAYOUT
+ {
+# if __BYTE_ORDER == __BIG_ENDIAN
unsigned sign : 1;
unsigned exp : _FP_EXPBITS_Q;
_FP_W_TYPE frac1 : _FP_FRACBITS_Q - (_FP_IMPLBIT_Q != 0) - _FP_W_TYPE_SIZE;
_FP_W_TYPE frac0 : _FP_W_TYPE_SIZE;
-#else
+# else
_FP_W_TYPE frac0 : _FP_W_TYPE_SIZE;
_FP_W_TYPE frac1 : _FP_FRACBITS_Q - (_FP_IMPLBIT_Q != 0) - _FP_W_TYPE_SIZE;
unsigned exp : _FP_EXPBITS_Q;
unsigned sign : 1;
-#endif
+# endif
} bits;
};
-#define FP_DECL_Q(X) _FP_DECL(2,X)
-#define FP_UNPACK_RAW_Q(X,val) _FP_UNPACK_RAW_2(Q,X,val)
-#define FP_UNPACK_RAW_QP(X,val) _FP_UNPACK_RAW_2_P(Q,X,val)
-#define FP_PACK_RAW_Q(val,X) _FP_PACK_RAW_2(Q,val,X)
-#define FP_PACK_RAW_QP(val,X) \
- do { \
- if (!FP_INHIBIT_RESULTS) \
- _FP_PACK_RAW_2_P(Q,val,X); \
- } while (0)
-
-#define FP_UNPACK_Q(X,val) \
- do { \
- _FP_UNPACK_RAW_2(Q,X,val); \
- _FP_UNPACK_CANONICAL(Q,2,X); \
- } while (0)
-
-#define FP_UNPACK_QP(X,val) \
- do { \
- _FP_UNPACK_RAW_2_P(Q,X,val); \
- _FP_UNPACK_CANONICAL(Q,2,X); \
- } while (0)
-
-#define FP_UNPACK_SEMIRAW_Q(X,val) \
- do { \
- _FP_UNPACK_RAW_2(Q,X,val); \
- _FP_UNPACK_SEMIRAW(Q,2,X); \
- } while (0)
-
-#define FP_UNPACK_SEMIRAW_QP(X,val) \
- do { \
- _FP_UNPACK_RAW_2_P(Q,X,val); \
- _FP_UNPACK_SEMIRAW(Q,2,X); \
- } while (0)
-
-#define FP_PACK_Q(val,X) \
- do { \
- _FP_PACK_CANONICAL(Q,2,X); \
- _FP_PACK_RAW_2(Q,val,X); \
- } while (0)
-
-#define FP_PACK_QP(val,X) \
- do { \
- _FP_PACK_CANONICAL(Q,2,X); \
- if (!FP_INHIBIT_RESULTS) \
- _FP_PACK_RAW_2_P(Q,val,X); \
- } while (0)
-
-#define FP_PACK_SEMIRAW_Q(val,X) \
- do { \
- _FP_PACK_SEMIRAW(Q,2,X); \
- _FP_PACK_RAW_2(Q,val,X); \
- } while (0)
-
-#define FP_PACK_SEMIRAW_QP(val,X) \
- do { \
- _FP_PACK_SEMIRAW(Q,2,X); \
- if (!FP_INHIBIT_RESULTS) \
- _FP_PACK_RAW_2_P(Q,val,X); \
- } while (0)
-
-#define FP_ISSIGNAN_Q(X) _FP_ISSIGNAN(Q,2,X)
-#define FP_NEG_Q(R,X) _FP_NEG(Q,2,R,X)
-#define FP_ADD_Q(R,X,Y) _FP_ADD(Q,2,R,X,Y)
-#define FP_SUB_Q(R,X,Y) _FP_SUB(Q,2,R,X,Y)
-#define FP_MUL_Q(R,X,Y) _FP_MUL(Q,2,R,X,Y)
-#define FP_DIV_Q(R,X,Y) _FP_DIV(Q,2,R,X,Y)
-#define FP_SQRT_Q(R,X) _FP_SQRT(Q,2,R,X)
-#define _FP_SQRT_MEAT_Q(R,S,T,X,Q) _FP_SQRT_MEAT_2(R,S,T,X,Q)
-
-#define FP_CMP_Q(r,X,Y,un) _FP_CMP(Q,2,r,X,Y,un)
-#define FP_CMP_EQ_Q(r,X,Y) _FP_CMP_EQ(Q,2,r,X,Y)
-#define FP_CMP_UNORD_Q(r,X,Y) _FP_CMP_UNORD(Q,2,r,X,Y)
-
-#define FP_TO_INT_Q(r,X,rsz,rsg) _FP_TO_INT(Q,2,r,X,rsz,rsg)
-#define FP_FROM_INT_Q(X,r,rs,rt) _FP_FROM_INT(Q,2,X,r,rs,rt)
-
-#define _FP_FRAC_HIGH_Q(X) _FP_FRAC_HIGH_2(X)
-#define _FP_FRAC_HIGH_RAW_Q(X) _FP_FRAC_HIGH_2(X)
+# define FP_DECL_Q(X) _FP_DECL (2, X)
+# define FP_UNPACK_RAW_Q(X, val) _FP_UNPACK_RAW_2 (Q, X, val)
+# define FP_UNPACK_RAW_QP(X, val) _FP_UNPACK_RAW_2_P (Q, X, val)
+# define FP_PACK_RAW_Q(val, X) _FP_PACK_RAW_2 (Q, val, X)
+# define FP_PACK_RAW_QP(val, X) \
+ do \
+ { \
+ if (!FP_INHIBIT_RESULTS) \
+ _FP_PACK_RAW_2_P (Q, val, X); \
+ } \
+ while (0)
+
+# define FP_UNPACK_Q(X, val) \
+ do \
+ { \
+ _FP_UNPACK_RAW_2 (Q, X, val); \
+ _FP_UNPACK_CANONICAL (Q, 2, X); \
+ } \
+ while (0)
+
+# define FP_UNPACK_QP(X, val) \
+ do \
+ { \
+ _FP_UNPACK_RAW_2_P (Q, X, val); \
+ _FP_UNPACK_CANONICAL (Q, 2, X); \
+ } \
+ while (0)
+
+# define FP_UNPACK_SEMIRAW_Q(X, val) \
+ do \
+ { \
+ _FP_UNPACK_RAW_2 (Q, X, val); \
+ _FP_UNPACK_SEMIRAW (Q, 2, X); \
+ } \
+ while (0)
+
+# define FP_UNPACK_SEMIRAW_QP(X, val) \
+ do \
+ { \
+ _FP_UNPACK_RAW_2_P (Q, X, val); \
+ _FP_UNPACK_SEMIRAW (Q, 2, X); \
+ } \
+ while (0)
+
+# define FP_PACK_Q(val, X) \
+ do \
+ { \
+ _FP_PACK_CANONICAL (Q, 2, X); \
+ _FP_PACK_RAW_2 (Q, val, X); \
+ } \
+ while (0)
+
+# define FP_PACK_QP(val, X) \
+ do \
+ { \
+ _FP_PACK_CANONICAL (Q, 2, X); \
+ if (!FP_INHIBIT_RESULTS) \
+ _FP_PACK_RAW_2_P (Q, val, X); \
+ } \
+ while (0)
+
+# define FP_PACK_SEMIRAW_Q(val, X) \
+ do \
+ { \
+ _FP_PACK_SEMIRAW (Q, 2, X); \
+ _FP_PACK_RAW_2 (Q, val, X); \
+ } \
+ while (0)
+
+# define FP_PACK_SEMIRAW_QP(val, X) \
+ do \
+ { \
+ _FP_PACK_SEMIRAW (Q, 2, X); \
+ if (!FP_INHIBIT_RESULTS) \
+ _FP_PACK_RAW_2_P (Q, val, X); \
+ } \
+ while (0)
+
+# define FP_ISSIGNAN_Q(X) _FP_ISSIGNAN (Q, 2, X)
+# define FP_NEG_Q(R, X) _FP_NEG (Q, 2, R, X)
+# define FP_ADD_Q(R, X, Y) _FP_ADD (Q, 2, R, X, Y)
+# define FP_SUB_Q(R, X, Y) _FP_SUB (Q, 2, R, X, Y)
+# define FP_MUL_Q(R, X, Y) _FP_MUL (Q, 2, R, X, Y)
+# define FP_DIV_Q(R, X, Y) _FP_DIV (Q, 2, R, X, Y)
+# define FP_SQRT_Q(R, X) _FP_SQRT (Q, 2, R, X)
+# define _FP_SQRT_MEAT_Q(R, S, T, X, Q) _FP_SQRT_MEAT_2 (R, S, T, X, Q)
+# define FP_FMA_Q(R, X, Y, Z) _FP_FMA (Q, 2, 4, R, X, Y, Z)
+
+# define FP_CMP_Q(r, X, Y, un) _FP_CMP (Q, 2, r, X, Y, un)
+# define FP_CMP_EQ_Q(r, X, Y) _FP_CMP_EQ (Q, 2, r, X, Y)
+# define FP_CMP_UNORD_Q(r, X, Y) _FP_CMP_UNORD (Q, 2, r, X, Y)
+
+# define FP_TO_INT_Q(r, X, rsz, rsg) _FP_TO_INT (Q, 2, r, X, rsz, rsg)
+# define FP_FROM_INT_Q(X, r, rs, rt) _FP_FROM_INT (Q, 2, X, r, rs, rt)
+
+# define _FP_FRAC_HIGH_Q(X) _FP_FRAC_HIGH_2 (X)
+# define _FP_FRAC_HIGH_RAW_Q(X) _FP_FRAC_HIGH_2 (X)
+
+# define _FP_FRAC_HIGH_DW_Q(X) _FP_FRAC_HIGH_4 (X)
#endif /* not _FP_W_TYPE_SIZE < 64 */
diff --git a/libgcc/soft-fp/single.h b/libgcc/soft-fp/single.h
index dec0031e9a9..af60c96e682 100644
--- a/libgcc/soft-fp/single.h
+++ b/libgcc/soft-fp/single.h
@@ -31,11 +31,17 @@
<http://www.gnu.org/licenses/>. */
#if _FP_W_TYPE_SIZE < 32
-#error "Here's a nickel kid. Go buy yourself a real computer."
+# error "Here's a nickel kid. Go buy yourself a real computer."
#endif
#define _FP_FRACTBITS_S _FP_W_TYPE_SIZE
+#if _FP_W_TYPE_SIZE < 64
+# define _FP_FRACTBITS_DW_S (2 * _FP_W_TYPE_SIZE)
+#else
+# define _FP_FRACTBITS_DW_S _FP_W_TYPE_SIZE
+#endif
+
#define _FP_FRACBITS_S 24
#define _FP_FRACXBITS_S (_FP_FRACTBITS_S - _FP_FRACBITS_S)
#define _FP_WFRACBITS_S (_FP_WORKBITS + _FP_FRACBITS_S)
@@ -43,21 +49,27 @@
#define _FP_EXPBITS_S 8
#define _FP_EXPBIAS_S 127
#define _FP_EXPMAX_S 255
-#define _FP_QNANBIT_S ((_FP_W_TYPE)1 << (_FP_FRACBITS_S-2))
-#define _FP_QNANBIT_SH_S ((_FP_W_TYPE)1 << (_FP_FRACBITS_S-2+_FP_WORKBITS))
-#define _FP_IMPLBIT_S ((_FP_W_TYPE)1 << (_FP_FRACBITS_S-1))
-#define _FP_IMPLBIT_SH_S ((_FP_W_TYPE)1 << (_FP_FRACBITS_S-1+_FP_WORKBITS))
-#define _FP_OVERFLOW_S ((_FP_W_TYPE)1 << (_FP_WFRACBITS_S))
+#define _FP_QNANBIT_S ((_FP_W_TYPE) 1 << (_FP_FRACBITS_S-2))
+#define _FP_QNANBIT_SH_S ((_FP_W_TYPE) 1 << (_FP_FRACBITS_S-2+_FP_WORKBITS))
+#define _FP_IMPLBIT_S ((_FP_W_TYPE) 1 << (_FP_FRACBITS_S-1))
+#define _FP_IMPLBIT_SH_S ((_FP_W_TYPE) 1 << (_FP_FRACBITS_S-1+_FP_WORKBITS))
+#define _FP_OVERFLOW_S ((_FP_W_TYPE) 1 << (_FP_WFRACBITS_S))
+
+#define _FP_WFRACBITS_DW_S (2 * _FP_WFRACBITS_S)
+#define _FP_WFRACXBITS_DW_S (_FP_FRACTBITS_DW_S - _FP_WFRACBITS_DW_S)
+#define _FP_HIGHBIT_DW_S \
+ ((_FP_W_TYPE) 1 << (_FP_WFRACBITS_DW_S - 1) % _FP_W_TYPE_SIZE)
/* The implementation of _FP_MUL_MEAT_S and _FP_DIV_MEAT_S should be
chosen by the target machine. */
-typedef float SFtype __attribute__((mode(SF)));
+typedef float SFtype __attribute__ ((mode (SF)));
union _FP_UNION_S
{
SFtype flt;
- struct _FP_STRUCT_LAYOUT {
+ struct _FP_STRUCT_LAYOUT
+ {
#if __BYTE_ORDER == __BIG_ENDIAN
unsigned sign : 1;
unsigned exp : _FP_EXPBITS_S;
@@ -67,84 +79,114 @@ union _FP_UNION_S
unsigned exp : _FP_EXPBITS_S;
unsigned sign : 1;
#endif
- } bits __attribute__((packed));
+ } bits __attribute__ ((packed));
};
-#define FP_DECL_S(X) _FP_DECL(1,X)
-#define FP_UNPACK_RAW_S(X,val) _FP_UNPACK_RAW_1(S,X,val)
-#define FP_UNPACK_RAW_SP(X,val) _FP_UNPACK_RAW_1_P(S,X,val)
-#define FP_PACK_RAW_S(val,X) _FP_PACK_RAW_1(S,val,X)
-#define FP_PACK_RAW_SP(val,X) \
- do { \
- if (!FP_INHIBIT_RESULTS) \
- _FP_PACK_RAW_1_P(S,val,X); \
- } while (0)
-
-#define FP_UNPACK_S(X,val) \
- do { \
- _FP_UNPACK_RAW_1(S,X,val); \
- _FP_UNPACK_CANONICAL(S,1,X); \
- } while (0)
-
-#define FP_UNPACK_SP(X,val) \
- do { \
- _FP_UNPACK_RAW_1_P(S,X,val); \
- _FP_UNPACK_CANONICAL(S,1,X); \
- } while (0)
-
-#define FP_UNPACK_SEMIRAW_S(X,val) \
- do { \
- _FP_UNPACK_RAW_1(S,X,val); \
- _FP_UNPACK_SEMIRAW(S,1,X); \
- } while (0)
-
-#define FP_UNPACK_SEMIRAW_SP(X,val) \
- do { \
- _FP_UNPACK_RAW_1_P(S,X,val); \
- _FP_UNPACK_SEMIRAW(S,1,X); \
- } while (0)
-
-#define FP_PACK_S(val,X) \
- do { \
- _FP_PACK_CANONICAL(S,1,X); \
- _FP_PACK_RAW_1(S,val,X); \
- } while (0)
-
-#define FP_PACK_SP(val,X) \
- do { \
- _FP_PACK_CANONICAL(S,1,X); \
- if (!FP_INHIBIT_RESULTS) \
- _FP_PACK_RAW_1_P(S,val,X); \
- } while (0)
-
-#define FP_PACK_SEMIRAW_S(val,X) \
- do { \
- _FP_PACK_SEMIRAW(S,1,X); \
- _FP_PACK_RAW_1(S,val,X); \
- } while (0)
-
-#define FP_PACK_SEMIRAW_SP(val,X) \
- do { \
- _FP_PACK_SEMIRAW(S,1,X); \
- if (!FP_INHIBIT_RESULTS) \
- _FP_PACK_RAW_1_P(S,val,X); \
- } while (0)
-
-#define FP_ISSIGNAN_S(X) _FP_ISSIGNAN(S,1,X)
-#define FP_NEG_S(R,X) _FP_NEG(S,1,R,X)
-#define FP_ADD_S(R,X,Y) _FP_ADD(S,1,R,X,Y)
-#define FP_SUB_S(R,X,Y) _FP_SUB(S,1,R,X,Y)
-#define FP_MUL_S(R,X,Y) _FP_MUL(S,1,R,X,Y)
-#define FP_DIV_S(R,X,Y) _FP_DIV(S,1,R,X,Y)
-#define FP_SQRT_S(R,X) _FP_SQRT(S,1,R,X)
-#define _FP_SQRT_MEAT_S(R,S,T,X,Q) _FP_SQRT_MEAT_1(R,S,T,X,Q)
-
-#define FP_CMP_S(r,X,Y,un) _FP_CMP(S,1,r,X,Y,un)
-#define FP_CMP_EQ_S(r,X,Y) _FP_CMP_EQ(S,1,r,X,Y)
-#define FP_CMP_UNORD_S(r,X,Y) _FP_CMP_UNORD(S,1,r,X,Y)
-
-#define FP_TO_INT_S(r,X,rsz,rsg) _FP_TO_INT(S,1,r,X,rsz,rsg)
-#define FP_FROM_INT_S(X,r,rs,rt) _FP_FROM_INT(S,1,X,r,rs,rt)
-
-#define _FP_FRAC_HIGH_S(X) _FP_FRAC_HIGH_1(X)
-#define _FP_FRAC_HIGH_RAW_S(X) _FP_FRAC_HIGH_1(X)
+#define FP_DECL_S(X) _FP_DECL (1, X)
+#define FP_UNPACK_RAW_S(X, val) _FP_UNPACK_RAW_1 (S, X, val)
+#define FP_UNPACK_RAW_SP(X, val) _FP_UNPACK_RAW_1_P (S, X, val)
+#define FP_PACK_RAW_S(val, X) _FP_PACK_RAW_1 (S, val, X)
+#define FP_PACK_RAW_SP(val, X) \
+ do \
+ { \
+ if (!FP_INHIBIT_RESULTS) \
+ _FP_PACK_RAW_1_P (S, val, X); \
+ } \
+ while (0)
+
+#define FP_UNPACK_S(X, val) \
+ do \
+ { \
+ _FP_UNPACK_RAW_1 (S, X, val); \
+ _FP_UNPACK_CANONICAL (S, 1, X); \
+ } \
+ while (0)
+
+#define FP_UNPACK_SP(X, val) \
+ do \
+ { \
+ _FP_UNPACK_RAW_1_P (S, X, val); \
+ _FP_UNPACK_CANONICAL (S, 1, X); \
+ } \
+ while (0)
+
+#define FP_UNPACK_SEMIRAW_S(X, val) \
+ do \
+ { \
+ _FP_UNPACK_RAW_1 (S, X, val); \
+ _FP_UNPACK_SEMIRAW (S, 1, X); \
+ } \
+ while (0)
+
+#define FP_UNPACK_SEMIRAW_SP(X, val) \
+ do \
+ { \
+ _FP_UNPACK_RAW_1_P (S, X, val); \
+ _FP_UNPACK_SEMIRAW (S, 1, X); \
+ } \
+ while (0)
+
+#define FP_PACK_S(val, X) \
+ do \
+ { \
+ _FP_PACK_CANONICAL (S, 1, X); \
+ _FP_PACK_RAW_1 (S, val, X); \
+ } \
+ while (0)
+
+#define FP_PACK_SP(val, X) \
+ do \
+ { \
+ _FP_PACK_CANONICAL (S, 1, X); \
+ if (!FP_INHIBIT_RESULTS) \
+ _FP_PACK_RAW_1_P (S, val, X); \
+ } \
+ while (0)
+
+#define FP_PACK_SEMIRAW_S(val, X) \
+ do \
+ { \
+ _FP_PACK_SEMIRAW (S, 1, X); \
+ _FP_PACK_RAW_1 (S, val, X); \
+ } \
+ while (0)
+
+#define FP_PACK_SEMIRAW_SP(val, X) \
+ do \
+ { \
+ _FP_PACK_SEMIRAW (S, 1, X); \
+ if (!FP_INHIBIT_RESULTS) \
+ _FP_PACK_RAW_1_P (S, val, X); \
+ } \
+ while (0)
+
+#define FP_ISSIGNAN_S(X) _FP_ISSIGNAN (S, 1, X)
+#define FP_NEG_S(R, X) _FP_NEG (S, 1, R, X)
+#define FP_ADD_S(R, X, Y) _FP_ADD (S, 1, R, X, Y)
+#define FP_SUB_S(R, X, Y) _FP_SUB (S, 1, R, X, Y)
+#define FP_MUL_S(R, X, Y) _FP_MUL (S, 1, R, X, Y)
+#define FP_DIV_S(R, X, Y) _FP_DIV (S, 1, R, X, Y)
+#define FP_SQRT_S(R, X) _FP_SQRT (S, 1, R, X)
+#define _FP_SQRT_MEAT_S(R, S, T, X, Q) _FP_SQRT_MEAT_1 (R, S, T, X, Q)
+
+#if _FP_W_TYPE_SIZE < 64
+# define FP_FMA_S(R, X, Y, Z) _FP_FMA (S, 1, 2, R, X, Y, Z)
+#else
+# define FP_FMA_S(R, X, Y, Z) _FP_FMA (S, 1, 1, R, X, Y, Z)
+#endif
+
+#define FP_CMP_S(r, X, Y, un) _FP_CMP (S, 1, r, X, Y, un)
+#define FP_CMP_EQ_S(r, X, Y) _FP_CMP_EQ (S, 1, r, X, Y)
+#define FP_CMP_UNORD_S(r, X, Y) _FP_CMP_UNORD (S, 1, r, X, Y)
+
+#define FP_TO_INT_S(r, X, rsz, rsg) _FP_TO_INT (S, 1, r, X, rsz, rsg)
+#define FP_FROM_INT_S(X, r, rs, rt) _FP_FROM_INT (S, 1, X, r, rs, rt)
+
+#define _FP_FRAC_HIGH_S(X) _FP_FRAC_HIGH_1 (X)
+#define _FP_FRAC_HIGH_RAW_S(X) _FP_FRAC_HIGH_1 (X)
+
+#if _FP_W_TYPE_SIZE < 64
+# define _FP_FRAC_HIGH_DW_S(X) _FP_FRAC_HIGH_2 (X)
+#else
+# define _FP_FRAC_HIGH_DW_S(X) _FP_FRAC_HIGH_1 (X)
+#endif
diff --git a/libgcc/soft-fp/soft-fp.h b/libgcc/soft-fp/soft-fp.h
index b1c6e619b5e..696fc8676c7 100644
--- a/libgcc/soft-fp/soft-fp.h
+++ b/libgcc/soft-fp/soft-fp.h
@@ -33,25 +33,25 @@
#define SOFT_FP_H
#ifdef _LIBC
-#include <sfp-machine.h>
+# include <sfp-machine.h>
#else
-#include "sfp-machine.h"
+# include "sfp-machine.h"
#endif
/* Allow sfp-machine to have its own byte order definitions. */
#ifndef __BYTE_ORDER
-#ifdef _LIBC
-#include <endian.h>
-#else
-#error "endianness not defined by sfp-machine.h"
-#endif
+# ifdef _LIBC
+# include <endian.h>
+# else
+# error "endianness not defined by sfp-machine.h"
+# endif
#endif
#define _FP_WORKBITS 3
-#define _FP_WORK_LSB ((_FP_W_TYPE)1 << 3)
-#define _FP_WORK_ROUND ((_FP_W_TYPE)1 << 2)
-#define _FP_WORK_GUARD ((_FP_W_TYPE)1 << 1)
-#define _FP_WORK_STICKY ((_FP_W_TYPE)1 << 0)
+#define _FP_WORK_LSB ((_FP_W_TYPE) 1 << 3)
+#define _FP_WORK_ROUND ((_FP_W_TYPE) 1 << 2)
+#define _FP_WORK_GUARD ((_FP_W_TYPE) 1 << 1)
+#define _FP_WORK_STICKY ((_FP_W_TYPE) 1 << 0)
#ifndef FP_RND_NEAREST
# define FP_RND_NEAREST 0
@@ -65,22 +65,22 @@
/* By default don't care about exceptions. */
#ifndef FP_EX_INVALID
-#define FP_EX_INVALID 0
+# define FP_EX_INVALID 0
#endif
#ifndef FP_EX_OVERFLOW
-#define FP_EX_OVERFLOW 0
+# define FP_EX_OVERFLOW 0
#endif
#ifndef FP_EX_UNDERFLOW
-#define FP_EX_UNDERFLOW 0
+# define FP_EX_UNDERFLOW 0
#endif
#ifndef FP_EX_DIVZERO
-#define FP_EX_DIVZERO 0
+# define FP_EX_DIVZERO 0
#endif
#ifndef FP_EX_INEXACT
-#define FP_EX_INEXACT 0
+# define FP_EX_INEXACT 0
#endif
#ifndef FP_EX_DENORM
-#define FP_EX_DENORM 0
+# define FP_EX_DENORM 0
#endif
/* _FP_STRUCT_LAYOUT may be defined as an attribute to determine the
@@ -90,23 +90,31 @@
differences in how consecutive bit-fields are laid out from the
default expected by soft-fp. */
#ifndef _FP_STRUCT_LAYOUT
-#define _FP_STRUCT_LAYOUT
+# define _FP_STRUCT_LAYOUT
#endif
#ifdef _FP_DECL_EX
-#define FP_DECL_EX \
+# define FP_DECL_EX \
int _fex = 0; \
_FP_DECL_EX
#else
-#define FP_DECL_EX int _fex = 0
+# define FP_DECL_EX int _fex = 0
#endif
+/* Initialize any machine-specific state used in FP_ROUNDMODE,
+ FP_TRAPPING_EXCEPTIONS or FP_HANDLE_EXCEPTIONS. */
#ifndef FP_INIT_ROUNDMODE
-#define FP_INIT_ROUNDMODE do {} while (0)
+# define FP_INIT_ROUNDMODE do {} while (0)
+#endif
+
+/* Initialize any machine-specific state used in
+ FP_HANDLE_EXCEPTIONS. */
+#ifndef FP_INIT_EXCEPTIONS
+# define FP_INIT_EXCEPTIONS FP_INIT_ROUNDMODE
#endif
#ifndef FP_HANDLE_EXCEPTIONS
-#define FP_HANDLE_EXCEPTIONS do {} while (0)
+# define FP_HANDLE_EXCEPTIONS do {} while (0)
#endif
#ifndef FP_INHIBIT_RESULTS
@@ -115,15 +123,12 @@
* check if some exceptions are unmasked
* and inhibit it in such a case.
*/
-#define FP_INHIBIT_RESULTS 0
+# define FP_INHIBIT_RESULTS 0
#endif
#define FP_SET_EXCEPTION(ex) \
_fex |= (ex)
-#define FP_UNSET_EXCEPTION(ex) \
- _fex &= ~(ex)
-
#define FP_CLEAR_EXCEPTIONS \
_fex = 0
@@ -131,58 +136,90 @@
(_fex)
#ifndef FP_TRAPPING_EXCEPTIONS
-#define FP_TRAPPING_EXCEPTIONS 0
+# define FP_TRAPPING_EXCEPTIONS 0
#endif
-#define _FP_ROUND_NEAREST(wc, X) \
-do { \
- if ((_FP_FRAC_LOW_##wc(X) & 15) != _FP_WORK_ROUND) \
- _FP_FRAC_ADDI_##wc(X, _FP_WORK_ROUND); \
-} while (0)
+/* A file using soft-fp may define FP_NO_EXCEPTIONS before including
+ soft-fp.h to indicate that, although a macro used there could raise
+ exceptions, or do rounding and potentially thereby raise
+ exceptions, for some arguments, for the particular arguments used
+ in that file no exceptions or rounding can occur. Such a file
+ should not itself use macros relating to handling exceptions and
+ rounding modes; this is only for indirect uses (in particular, in
+ _FP_FROM_INT and the macros it calls). */
+#ifdef FP_NO_EXCEPTIONS
-#define _FP_ROUND_ZERO(wc, X) (void)0
+# undef FP_SET_EXCEPTION
+# define FP_SET_EXCEPTION(ex) do {} while (0)
-#define _FP_ROUND_PINF(wc, X) \
-do { \
- if (!X##_s && (_FP_FRAC_LOW_##wc(X) & 7)) \
- _FP_FRAC_ADDI_##wc(X, _FP_WORK_LSB); \
-} while (0)
+# undef FP_CUR_EXCEPTIONS
+# define FP_CUR_EXCEPTIONS 0
-#define _FP_ROUND_MINF(wc, X) \
-do { \
- if (X##_s && (_FP_FRAC_LOW_##wc(X) & 7)) \
- _FP_FRAC_ADDI_##wc(X, _FP_WORK_LSB); \
-} while (0)
+# undef FP_TRAPPING_EXCEPTIONS
+# define FP_TRAPPING_EXCEPTIONS 0
+
+# undef FP_ROUNDMODE
+# define FP_ROUNDMODE FP_RND_ZERO
+
+#endif
+
+#define _FP_ROUND_NEAREST(wc, X) \
+ do \
+ { \
+ if ((_FP_FRAC_LOW_##wc (X) & 15) != _FP_WORK_ROUND) \
+ _FP_FRAC_ADDI_##wc (X, _FP_WORK_ROUND); \
+ } \
+ while (0)
+
+#define _FP_ROUND_ZERO(wc, X) (void) 0
+
+#define _FP_ROUND_PINF(wc, X) \
+ do \
+ { \
+ if (!X##_s && (_FP_FRAC_LOW_##wc (X) & 7)) \
+ _FP_FRAC_ADDI_##wc (X, _FP_WORK_LSB); \
+ } \
+ while (0)
+
+#define _FP_ROUND_MINF(wc, X) \
+ do \
+ { \
+ if (X##_s && (_FP_FRAC_LOW_##wc (X) & 7)) \
+ _FP_FRAC_ADDI_##wc (X, _FP_WORK_LSB); \
+ } \
+ while (0)
#define _FP_ROUND(wc, X) \
-do { \
- if (_FP_FRAC_LOW_##wc(X) & 7) \
- { \
- FP_SET_EXCEPTION(FP_EX_INEXACT); \
- switch (FP_ROUNDMODE) \
- { \
- case FP_RND_NEAREST: \
- _FP_ROUND_NEAREST(wc,X); \
- break; \
- case FP_RND_ZERO: \
- _FP_ROUND_ZERO(wc,X); \
- break; \
- case FP_RND_PINF: \
- _FP_ROUND_PINF(wc,X); \
- break; \
- case FP_RND_MINF: \
- _FP_ROUND_MINF(wc,X); \
- break; \
- } \
- } \
-} while (0)
+ do \
+ { \
+ if (_FP_FRAC_LOW_##wc (X) & 7) \
+ { \
+ FP_SET_EXCEPTION (FP_EX_INEXACT); \
+ switch (FP_ROUNDMODE) \
+ { \
+ case FP_RND_NEAREST: \
+ _FP_ROUND_NEAREST (wc, X); \
+ break; \
+ case FP_RND_ZERO: \
+ _FP_ROUND_ZERO (wc, X); \
+ break; \
+ case FP_RND_PINF: \
+ _FP_ROUND_PINF (wc, X); \
+ break; \
+ case FP_RND_MINF: \
+ _FP_ROUND_MINF (wc, X); \
+ break; \
+ } \
+ } \
+ } \
+ while (0)
#define FP_CLS_NORMAL 0
#define FP_CLS_ZERO 1
#define FP_CLS_INF 2
#define FP_CLS_NAN 3
-#define _FP_CLS_COMBINE(x,y) (((x) << 2) | (y))
+#define _FP_CLS_COMBINE(x, y) (((x) << 2) | (y))
#include "op-1.h"
#include "op-2.h"
@@ -194,35 +231,35 @@ do { \
#define UWtype _FP_W_TYPE
#define W_TYPE_SIZE _FP_W_TYPE_SIZE
-typedef int QItype __attribute__((mode(QI)));
-typedef int SItype __attribute__((mode(SI)));
-typedef int DItype __attribute__((mode(DI)));
-typedef unsigned int UQItype __attribute__((mode(QI)));
-typedef unsigned int USItype __attribute__((mode(SI)));
-typedef unsigned int UDItype __attribute__((mode(DI)));
+typedef int QItype __attribute__ ((mode (QI)));
+typedef int SItype __attribute__ ((mode (SI)));
+typedef int DItype __attribute__ ((mode (DI)));
+typedef unsigned int UQItype __attribute__ ((mode (QI)));
+typedef unsigned int USItype __attribute__ ((mode (SI)));
+typedef unsigned int UDItype __attribute__ ((mode (DI)));
#if _FP_W_TYPE_SIZE == 32
-typedef unsigned int UHWtype __attribute__((mode(HI)));
+typedef unsigned int UHWtype __attribute__ ((mode (HI)));
#elif _FP_W_TYPE_SIZE == 64
typedef USItype UHWtype;
#endif
#ifndef CMPtype
-#define CMPtype int
+# define CMPtype int
#endif
-#define SI_BITS (__CHAR_BIT__ * (int)sizeof(SItype))
-#define DI_BITS (__CHAR_BIT__ * (int)sizeof(DItype))
+#define SI_BITS (__CHAR_BIT__ * (int) sizeof (SItype))
+#define DI_BITS (__CHAR_BIT__ * (int) sizeof (DItype))
#ifndef umul_ppmm
-#ifdef _LIBC
-#include <stdlib/longlong.h>
-#else
-#include "longlong.h"
-#endif
+# ifdef _LIBC
+# include <stdlib/longlong.h>
+# else
+# include "longlong.h"
+# endif
#endif
#ifdef _LIBC
-#include <stdlib.h>
+# include <stdlib.h>
#else
extern void abort (void);
#endif
diff --git a/libgcc/soft-fp/subdf3.c b/libgcc/soft-fp/subdf3.c
index 032ac0f291f..6846e98dbd6 100644
--- a/libgcc/soft-fp/subdf3.c
+++ b/libgcc/soft-fp/subdf3.c
@@ -31,17 +31,20 @@
#include "soft-fp.h"
#include "double.h"
-DFtype __subdf3(DFtype a, DFtype b)
+DFtype
+__subdf3 (DFtype a, DFtype b)
{
FP_DECL_EX;
- FP_DECL_D(A); FP_DECL_D(B); FP_DECL_D(R);
+ FP_DECL_D (A);
+ FP_DECL_D (B);
+ FP_DECL_D (R);
DFtype r;
FP_INIT_ROUNDMODE;
- FP_UNPACK_SEMIRAW_D(A, a);
- FP_UNPACK_SEMIRAW_D(B, b);
- FP_SUB_D(R, A, B);
- FP_PACK_SEMIRAW_D(r, R);
+ FP_UNPACK_SEMIRAW_D (A, a);
+ FP_UNPACK_SEMIRAW_D (B, b);
+ FP_SUB_D (R, A, B);
+ FP_PACK_SEMIRAW_D (r, R);
FP_HANDLE_EXCEPTIONS;
return r;
diff --git a/libgcc/soft-fp/subsf3.c b/libgcc/soft-fp/subsf3.c
index c9f56c7176e..d46ddf58ae6 100644
--- a/libgcc/soft-fp/subsf3.c
+++ b/libgcc/soft-fp/subsf3.c
@@ -31,17 +31,20 @@
#include "soft-fp.h"
#include "single.h"
-SFtype __subsf3(SFtype a, SFtype b)
+SFtype
+__subsf3 (SFtype a, SFtype b)
{
FP_DECL_EX;
- FP_DECL_S(A); FP_DECL_S(B); FP_DECL_S(R);
+ FP_DECL_S (A);
+ FP_DECL_S (B);
+ FP_DECL_S (R);
SFtype r;
FP_INIT_ROUNDMODE;
- FP_UNPACK_SEMIRAW_S(A, a);
- FP_UNPACK_SEMIRAW_S(B, b);
- FP_SUB_S(R, A, B);
- FP_PACK_SEMIRAW_S(r, R);
+ FP_UNPACK_SEMIRAW_S (A, a);
+ FP_UNPACK_SEMIRAW_S (B, b);
+ FP_SUB_S (R, A, B);
+ FP_PACK_SEMIRAW_S (r, R);
FP_HANDLE_EXCEPTIONS;
return r;
diff --git a/libgcc/soft-fp/subtf3.c b/libgcc/soft-fp/subtf3.c
index a111d571e1b..88c6edeb612 100644
--- a/libgcc/soft-fp/subtf3.c
+++ b/libgcc/soft-fp/subtf3.c
@@ -31,17 +31,20 @@
#include "soft-fp.h"
#include "quad.h"
-TFtype __subtf3(TFtype a, TFtype b)
+TFtype
+__subtf3 (TFtype a, TFtype b)
{
FP_DECL_EX;
- FP_DECL_Q(A); FP_DECL_Q(B); FP_DECL_Q(R);
+ FP_DECL_Q (A);
+ FP_DECL_Q (B);
+ FP_DECL_Q (R);
TFtype r;
FP_INIT_ROUNDMODE;
- FP_UNPACK_SEMIRAW_Q(A, a);
- FP_UNPACK_SEMIRAW_Q(B, b);
- FP_SUB_Q(R, A, B);
- FP_PACK_SEMIRAW_Q(r, R);
+ FP_UNPACK_SEMIRAW_Q (A, a);
+ FP_UNPACK_SEMIRAW_Q (B, b);
+ FP_SUB_Q (R, A, B);
+ FP_PACK_SEMIRAW_Q (r, R);
FP_HANDLE_EXCEPTIONS;
return r;
diff --git a/libgcc/soft-fp/truncdfsf2.c b/libgcc/soft-fp/truncdfsf2.c
index e9a7223674f..3ec56fdf8ad 100644
--- a/libgcc/soft-fp/truncdfsf2.c
+++ b/libgcc/soft-fp/truncdfsf2.c
@@ -32,21 +32,22 @@
#include "single.h"
#include "double.h"
-SFtype __truncdfsf2(DFtype a)
+SFtype
+__truncdfsf2 (DFtype a)
{
FP_DECL_EX;
- FP_DECL_D(A);
- FP_DECL_S(R);
+ FP_DECL_D (A);
+ FP_DECL_S (R);
SFtype r;
FP_INIT_ROUNDMODE;
- FP_UNPACK_SEMIRAW_D(A, a);
+ FP_UNPACK_SEMIRAW_D (A, a);
#if _FP_W_TYPE_SIZE < _FP_FRACBITS_D
- FP_TRUNC(S,D,1,2,R,A);
+ FP_TRUNC (S, D, 1, 2, R, A);
#else
- FP_TRUNC(S,D,1,1,R,A);
+ FP_TRUNC (S, D, 1, 1, R, A);
#endif
- FP_PACK_SEMIRAW_S(r, R);
+ FP_PACK_SEMIRAW_S (r, R);
FP_HANDLE_EXCEPTIONS;
return r;
diff --git a/libgcc/soft-fp/trunctfdf2.c b/libgcc/soft-fp/trunctfdf2.c
index 35c6496362f..e9702101291 100644
--- a/libgcc/soft-fp/trunctfdf2.c
+++ b/libgcc/soft-fp/trunctfdf2.c
@@ -32,21 +32,22 @@
#include "double.h"
#include "quad.h"
-DFtype __trunctfdf2(TFtype a)
+DFtype
+__trunctfdf2 (TFtype a)
{
FP_DECL_EX;
- FP_DECL_Q(A);
- FP_DECL_D(R);
+ FP_DECL_Q (A);
+ FP_DECL_D (R);
DFtype r;
FP_INIT_ROUNDMODE;
- FP_UNPACK_SEMIRAW_Q(A, a);
+ FP_UNPACK_SEMIRAW_Q (A, a);
#if (2 * _FP_W_TYPE_SIZE) < _FP_FRACBITS_Q
- FP_TRUNC(D,Q,2,4,R,A);
+ FP_TRUNC (D, Q, 2, 4, R, A);
#else
- FP_TRUNC(D,Q,1,2,R,A);
+ FP_TRUNC (D, Q, 1, 2, R, A);
#endif
- FP_PACK_SEMIRAW_D(r, R);
+ FP_PACK_SEMIRAW_D (r, R);
FP_HANDLE_EXCEPTIONS;
return r;
diff --git a/libgcc/soft-fp/trunctfsf2.c b/libgcc/soft-fp/trunctfsf2.c
index 751c7c8d76e..d8a3728a0da 100644
--- a/libgcc/soft-fp/trunctfsf2.c
+++ b/libgcc/soft-fp/trunctfsf2.c
@@ -32,21 +32,22 @@
#include "single.h"
#include "quad.h"
-SFtype __trunctfsf2(TFtype a)
+SFtype
+__trunctfsf2 (TFtype a)
{
FP_DECL_EX;
- FP_DECL_Q(A);
- FP_DECL_S(R);
+ FP_DECL_Q (A);
+ FP_DECL_S (R);
SFtype r;
FP_INIT_ROUNDMODE;
- FP_UNPACK_SEMIRAW_Q(A, a);
+ FP_UNPACK_SEMIRAW_Q (A, a);
#if (2 * _FP_W_TYPE_SIZE) < _FP_FRACBITS_Q
- FP_TRUNC(S,Q,1,4,R,A);
+ FP_TRUNC (S, Q, 1, 4, R, A);
#else
- FP_TRUNC(S,Q,1,2,R,A);
+ FP_TRUNC (S, Q, 1, 2, R, A);
#endif
- FP_PACK_SEMIRAW_S(r, R);
+ FP_PACK_SEMIRAW_S (r, R);
FP_HANDLE_EXCEPTIONS;
return r;
diff --git a/libgcc/soft-fp/trunctfxf2.c b/libgcc/soft-fp/trunctfxf2.c
index 50d60bc5d53..750bec1808e 100644
--- a/libgcc/soft-fp/trunctfxf2.c
+++ b/libgcc/soft-fp/trunctfxf2.c
@@ -1,6 +1,6 @@
/* Software floating-point emulation.
Truncate IEEE quad into IEEE extended
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007-2013 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Uros Bizjak (ubizjak@gmail.com).
@@ -24,29 +24,29 @@
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
- MA 02110-1301, USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
#include "soft-fp.h"
#include "extended.h"
#include "quad.h"
-XFtype __trunctfxf2(TFtype a)
+XFtype
+__trunctfxf2 (TFtype a)
{
FP_DECL_EX;
- FP_DECL_Q(A);
- FP_DECL_E(R);
+ FP_DECL_Q (A);
+ FP_DECL_E (R);
XFtype r;
FP_INIT_ROUNDMODE;
- FP_UNPACK_SEMIRAW_Q(A, a);
+ FP_UNPACK_SEMIRAW_Q (A, a);
#if (2 * _FP_W_TYPE_SIZE) < _FP_FRACBITS_Q
- FP_TRUNC(E,Q,4,4,R,A);
+ FP_TRUNC (E, Q, 4, 4, R, A);
#else
- FP_TRUNC(E,Q,2,2,R,A);
+ FP_TRUNC (E, Q, 2, 2, R, A);
#endif
- FP_PACK_SEMIRAW_E(r, R);
+ FP_PACK_SEMIRAW_E (r, R);
FP_HANDLE_EXCEPTIONS;
return r;
diff --git a/libgcc/soft-fp/unorddf2.c b/libgcc/soft-fp/unorddf2.c
index 2e77f2d8ff7..641c8697251 100644
--- a/libgcc/soft-fp/unorddf2.c
+++ b/libgcc/soft-fp/unorddf2.c
@@ -30,14 +30,21 @@
#include "soft-fp.h"
#include "double.h"
-CMPtype __unorddf2(DFtype a, DFtype b)
+CMPtype
+__unorddf2 (DFtype a, DFtype b)
{
- FP_DECL_D(A); FP_DECL_D(B);
+ FP_DECL_EX;
+ FP_DECL_D (A);
+ FP_DECL_D (B);
CMPtype r;
- FP_UNPACK_RAW_D(A, a);
- FP_UNPACK_RAW_D(B, b);
- FP_CMP_UNORD_D(r, A, B);
+ FP_INIT_EXCEPTIONS;
+ FP_UNPACK_RAW_D (A, a);
+ FP_UNPACK_RAW_D (B, b);
+ FP_CMP_UNORD_D (r, A, B);
+ if (r && (FP_ISSIGNAN_D (A) || FP_ISSIGNAN_D (B)))
+ FP_SET_EXCEPTION (FP_EX_INVALID);
+ FP_HANDLE_EXCEPTIONS;
return r;
}
diff --git a/libgcc/soft-fp/unordsf2.c b/libgcc/soft-fp/unordsf2.c
index b5b5322c168..f271421283f 100644
--- a/libgcc/soft-fp/unordsf2.c
+++ b/libgcc/soft-fp/unordsf2.c
@@ -30,15 +30,21 @@
#include "soft-fp.h"
#include "single.h"
-CMPtype __unordsf2(SFtype a, SFtype b)
+CMPtype
+__unordsf2 (SFtype a, SFtype b)
{
- FP_DECL_S(A);
- FP_DECL_S(B);
+ FP_DECL_EX;
+ FP_DECL_S (A);
+ FP_DECL_S (B);
CMPtype r;
- FP_UNPACK_RAW_S(A, a);
- FP_UNPACK_RAW_S(B, b);
- FP_CMP_UNORD_S(r, A, B);
+ FP_INIT_EXCEPTIONS;
+ FP_UNPACK_RAW_S (A, a);
+ FP_UNPACK_RAW_S (B, b);
+ FP_CMP_UNORD_S (r, A, B);
+ if (r && (FP_ISSIGNAN_S (A) || FP_ISSIGNAN_S (B)))
+ FP_SET_EXCEPTION (FP_EX_INVALID);
+ FP_HANDLE_EXCEPTIONS;
return r;
}
diff --git a/libgcc/soft-fp/unordtf2.c b/libgcc/soft-fp/unordtf2.c
index 1a85c252c1a..38cc1a78b26 100644
--- a/libgcc/soft-fp/unordtf2.c
+++ b/libgcc/soft-fp/unordtf2.c
@@ -30,15 +30,21 @@
#include "soft-fp.h"
#include "quad.h"
-CMPtype __unordtf2(TFtype a, TFtype b)
+CMPtype
+__unordtf2 (TFtype a, TFtype b)
{
- FP_DECL_Q(A);
- FP_DECL_Q(B);
+ FP_DECL_EX;
+ FP_DECL_Q (A);
+ FP_DECL_Q (B);
CMPtype r;
- FP_UNPACK_RAW_Q(A, a);
- FP_UNPACK_RAW_Q(B, b);
- FP_CMP_UNORD_Q(r, A, B);
+ FP_INIT_EXCEPTIONS;
+ FP_UNPACK_RAW_Q (A, a);
+ FP_UNPACK_RAW_Q (B, b);
+ FP_CMP_UNORD_Q (r, A, B);
+ if (r && (FP_ISSIGNAN_Q (A) || FP_ISSIGNAN_Q (B)))
+ FP_SET_EXCEPTION (FP_EX_INVALID);
+ FP_HANDLE_EXCEPTIONS;
return r;
}
diff --git a/libgcc/sync.c b/libgcc/sync.c
index edb985eae26..17158c90217 100644
--- a/libgcc/sync.c
+++ b/libgcc/sync.c
@@ -67,27 +67,26 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#if defined FN
-/* Define macros for each __sync_* function type. Each macro defines a
- local function called <NAME>_<UNITS> that acts like __<NAME>_<UNITS>.
- TYPE is a type that has UNITS bytes. */
+/* Define functions called __sync_<NAME>_<UNITS>, with one macro per
+ signature. TYPE is a type that has UNITS bytes. */
#define DEFINE_V_PV(NAME, UNITS, TYPE) \
- static TYPE \
- NAME##_##UNITS (TYPE *ptr, TYPE value) \
+ TYPE \
+ __##NAME##_##UNITS (TYPE *ptr, TYPE value) \
{ \
return __##NAME (ptr, value); \
}
-#define DEFINE_V_PVV(NAME, UNITS, TYPE) \
- static TYPE \
- NAME##_##UNITS (TYPE *ptr, TYPE value1, TYPE value2) \
+#define DEFINE_V_PVV(NAME, UNITS, TYPE) \
+ TYPE \
+ __##NAME##_##UNITS (TYPE *ptr, TYPE value1, TYPE value2) \
{ \
return __##NAME (ptr, value1, value2); \
}
#define DEFINE_BOOL_PVV(NAME, UNITS, TYPE) \
- static _Bool \
- NAME##_##UNITS (TYPE *ptr, TYPE value1, TYPE value2) \
+ _Bool \
+ __##NAME##_##UNITS (TYPE *ptr, TYPE value1, TYPE value2) \
{ \
return __##NAME (ptr, value1, value2); \
}
@@ -118,9 +117,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define DEFINE1(NAME, UNITS, TYPE) \
static int unused[sizeof (TYPE) == UNITS ? 1 : -1] \
__attribute__((unused)); \
- local_##NAME (NAME, UNITS, TYPE); \
- typeof (NAME##_##UNITS) __##NAME##_##UNITS \
- __attribute__((alias (#NAME "_" #UNITS)));
+ local_##NAME (NAME, UNITS, TYPE);
/* As above, but performing macro expansion on the arguments. */
#define DEFINE(NAME, UNITS, TYPE) DEFINE1 (NAME, UNITS, TYPE)
@@ -167,13 +164,11 @@ DEFINE (FN, 8, UOItype)
#if defined Lsync_synchronize
-static void
-sync_synchronize (void)
+void
+__sync_synchronize (void)
{
__sync_synchronize ();
}
-typeof (sync_synchronize) __sync_synchronize \
- __attribute__((alias ("sync_synchronize")));
#endif
diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog
index 940d41444a5..2ccaa3dfe4f 100644
--- a/libgfortran/ChangeLog
+++ b/libgfortran/ChangeLog
@@ -1,3 +1,28 @@
+2013-11-10 Janne Blomqvist <jb@gcc.gnu.org>
+
+ * configure.ac: Check presence of mkostemp.
+ * io/unix.c (set_close_on_exec): New function.
+ (tempfile_open): Use mkostemp and O_CLOEXEC if available, fallback
+ to calling set_close_on_exec.
+ (regular_file): Add O_CLOEXEC to flags if defined.
+ (open_external): Call set_close_on_exec if O_CLOEXEC is not
+ defined.
+ * config.h.in: Regenerated.
+ * configure: Regenerated.
+ * Makefile.in: Regenerated.
+ * aclocal.m4: Regenerated.
+
+2013-10-01 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/55469
+ * io/list_read (parse_repeat, read_integer, read_character,
+ parse_real, read_real, check_type, list_formatted_read_scalar,
+ finish_list_read): Call list_free.
+
+2013-09-20 Alan Modra <amodra@gmail.com>
+
+ * configure: Regenerate.
+
2013-07-23 Uros Bizjak <ubizjak@gmail.com>
* config/fpu-387.h (get_fpu_rounding_mode): Read rounding mode
diff --git a/libgfortran/Makefile.in b/libgfortran/Makefile.in
index aa23e85e37b..62b9f7abffa 100644
--- a/libgfortran/Makefile.in
+++ b/libgfortran/Makefile.in
@@ -1,9 +1,9 @@
-# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# Makefile.in generated by automake 1.11.3 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
-# Inc.
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+# Foundation, Inc.
# This Makefile.in 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.
@@ -87,6 +87,12 @@ am__nobase_list = $(am__nobase_strip_setup); \
am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
am__installdirs = "$(DESTDIR)$(cafexeclibdir)" \
"$(DESTDIR)$(myexeclibdir)" "$(DESTDIR)$(toolexeclibdir)" \
"$(DESTDIR)$(toolexeclibdir)"
@@ -1276,7 +1282,7 @@ all: $(BUILT_SOURCES) config.h
.SUFFIXES:
.SUFFIXES: .F90 .c .f90 .lo .o .obj
-am--refresh:
+am--refresh: Makefile
@:
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
@@ -1312,10 +1318,8 @@ $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
$(am__aclocal_m4_deps):
config.h: stamp-h1
- @if test ! -f $@; then \
- rm -f stamp-h1; \
- $(MAKE) $(AM_MAKEFLAGS) stamp-h1; \
- else :; fi
+ @if test ! -f $@; then rm -f stamp-h1; else :; fi
+ @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) stamp-h1; else :; fi
stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
@rm -f stamp-h1
@@ -1422,11 +1426,11 @@ clean-toolexeclibLTLIBRARIES:
echo "rm -f \"$${dir}/so_locations\""; \
rm -f "$${dir}/so_locations"; \
done
-libcaf_single.la: $(libcaf_single_la_OBJECTS) $(libcaf_single_la_DEPENDENCIES)
+libcaf_single.la: $(libcaf_single_la_OBJECTS) $(libcaf_single_la_DEPENDENCIES) $(EXTRA_libcaf_single_la_DEPENDENCIES)
$(libcaf_single_la_LINK) -rpath $(cafexeclibdir) $(libcaf_single_la_OBJECTS) $(libcaf_single_la_LIBADD) $(LIBS)
-libgfortran.la: $(libgfortran_la_OBJECTS) $(libgfortran_la_DEPENDENCIES)
+libgfortran.la: $(libgfortran_la_OBJECTS) $(libgfortran_la_DEPENDENCIES) $(EXTRA_libgfortran_la_DEPENDENCIES)
$(libgfortran_la_LINK) -rpath $(toolexeclibdir) $(libgfortran_la_OBJECTS) $(libgfortran_la_LIBADD) $(LIBS)
-libgfortranbegin.la: $(libgfortranbegin_la_OBJECTS) $(libgfortranbegin_la_DEPENDENCIES)
+libgfortranbegin.la: $(libgfortranbegin_la_OBJECTS) $(libgfortranbegin_la_DEPENDENCIES) $(EXTRA_libgfortranbegin_la_DEPENDENCIES)
$(libgfortranbegin_la_LINK) -rpath $(myexeclibdir) $(libgfortranbegin_la_OBJECTS) $(libgfortranbegin_la_LIBADD) $(LIBS)
mostlyclean-compile:
@@ -5686,9 +5690,7 @@ uninstall-toolexeclibDATA:
@$(NORMAL_UNINSTALL)
@list='$(toolexeclib_DATA)'; test -n "$(toolexeclibdir)" || list=; \
files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
- test -n "$$files" || exit 0; \
- echo " ( cd '$(DESTDIR)$(toolexeclibdir)' && rm -f" $$files ")"; \
- cd "$(DESTDIR)$(toolexeclibdir)" && rm -f $$files
+ dir='$(DESTDIR)$(toolexeclibdir)'; $(am__uninstall_files_from_dir)
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
@@ -5760,10 +5762,15 @@ install-am: all-am
installcheck: installcheck-am
install-strip:
- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
- `test -z '$(STRIP)' || \
- echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
mostlyclean-generic:
clean-generic:
diff --git a/libgfortran/aclocal.m4 b/libgfortran/aclocal.m4
index 8673daa1a9d..351be9d255a 100644
--- a/libgfortran/aclocal.m4
+++ b/libgfortran/aclocal.m4
@@ -1,7 +1,8 @@
-# generated automatically by aclocal 1.11.1 -*- Autoconf -*-
+# generated automatically by aclocal 1.11.3 -*- Autoconf -*-
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-# 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+# 2005, 2006, 2007, 2008, 2009, 2010, 2011 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.
@@ -19,12 +20,15 @@ You have another version of autoconf. It may work, but is not guaranteed to.
If you have problems, you may need to regenerate the build system entirely.
To do so, use the procedure documented by the package, typically `autoreconf'.])])
-# Copyright (C) 2002, 2003, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+# Copyright (C) 2002, 2003, 2005, 2006, 2007, 2008, 2011 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.
+# serial 1
+
# AM_AUTOMAKE_VERSION(VERSION)
# ----------------------------
# Automake X.Y traces this macro to ensure aclocal.m4 has been
@@ -34,7 +38,7 @@ AC_DEFUN([AM_AUTOMAKE_VERSION],
[am__api_version='1.11'
dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
dnl require some minimum version. Point them to the right macro.
-m4_if([$1], [1.11.1], [],
+m4_if([$1], [1.11.3], [],
[AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
])
@@ -50,19 +54,21 @@ m4_define([_AM_AUTOCONF_VERSION], [])
# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
-[AM_AUTOMAKE_VERSION([1.11.1])dnl
+[AM_AUTOMAKE_VERSION([1.11.3])dnl
m4_ifndef([AC_AUTOCONF_VERSION],
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
# AM_AUX_DIR_EXPAND -*- Autoconf -*-
-# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
+# Copyright (C) 2001, 2003, 2005, 2011 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.
+# serial 1
+
# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to
# `$srcdir', `$srcdir/..', or `$srcdir/../..'.
@@ -144,14 +150,14 @@ AC_CONFIG_COMMANDS_PRE(
Usually this means the macro was only invoked conditionally.]])
fi])])
-# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009
-# Free Software Foundation, Inc.
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009,
+# 2010, 2011 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.
-# serial 10
+# serial 12
# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be
# written in clear, in which case automake, when reading aclocal.m4,
@@ -191,6 +197,7 @@ AC_CACHE_CHECK([dependency style of $depcc],
# 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'.
+ rm -rf conftest.dir
mkdir conftest.dir
# Copy depcomp to subdir because otherwise we won't find it if we're
# using a relative directory.
@@ -255,7 +262,7 @@ AC_CACHE_CHECK([dependency style of $depcc],
break
fi
;;
- msvisualcpp | msvcmsys)
+ msvc7 | msvc7msys | msvisualcpp | msvcmsys)
# This compiler won't grok `-c -o', but also, the minuso test has
# not run yet. These depmodes are late enough in the game, and
# so weak that their functioning should not be impacted.
@@ -320,10 +327,13 @@ AC_DEFUN([AM_DEP_TRACK],
if test "x$enable_dependency_tracking" != xno; then
am_depcomp="$ac_aux_dir/depcomp"
AMDEPBACKSLASH='\'
+ am__nodep='_no'
fi
AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
AC_SUBST([AMDEPBACKSLASH])dnl
_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl
+AC_SUBST([am__nodep])dnl
+_AM_SUBST_NOTMAKE([am__nodep])dnl
])
# Generate code to set up dependency tracking. -*- Autoconf -*-
@@ -545,12 +555,15 @@ for _am_header in $config_headers :; do
done
echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
-# Copyright (C) 2001, 2003, 2005, 2008 Free Software Foundation, Inc.
+# Copyright (C) 2001, 2003, 2005, 2008, 2011 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.
+# serial 1
+
# AM_PROG_INSTALL_SH
# ------------------
# Define $install_sh.
@@ -569,8 +582,8 @@ AC_SUBST(install_sh)])
# Add --enable-maintainer-mode option to configure. -*- Autoconf -*-
# From Jim Meyering
-# Copyright (C) 1996, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2008
-# Free Software Foundation, Inc.
+# Copyright (C) 1996, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2008,
+# 2011 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -590,7 +603,7 @@ AC_DEFUN([AM_MAINTAINER_MODE],
[disable], [m4_define([am_maintainer_other], [enable])],
[m4_define([am_maintainer_other], [enable])
m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])])
-AC_MSG_CHECKING([whether to am_maintainer_other maintainer-specific portions of Makefiles])
+AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
dnl maintainer-mode's default is 'disable' unless 'enable' is passed
AC_ARG_ENABLE([maintainer-mode],
[ --][am_maintainer_other][-maintainer-mode am_maintainer_other make rules and dependencies not useful
@@ -736,12 +749,15 @@ else
fi
])
-# Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+# Copyright (C) 2003, 2004, 2005, 2006, 2011 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.
+# serial 1
+
# AM_PROG_MKDIR_P
# ---------------
# Check for `mkdir -p'.
@@ -764,13 +780,14 @@ esac
# Helper functions for option handling. -*- Autoconf -*-
-# Copyright (C) 2001, 2002, 2003, 2005, 2008 Free Software Foundation, Inc.
+# Copyright (C) 2001, 2002, 2003, 2005, 2008, 2010 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.
-# serial 4
+# serial 5
# _AM_MANGLE_OPTION(NAME)
# -----------------------
@@ -778,13 +795,13 @@ AC_DEFUN([_AM_MANGLE_OPTION],
[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
# _AM_SET_OPTION(NAME)
-# ------------------------------
+# --------------------
# Set option NAME. Presently that only means defining a flag for this option.
AC_DEFUN([_AM_SET_OPTION],
[m4_define(_AM_MANGLE_OPTION([$1]), 1)])
# _AM_SET_OPTIONS(OPTIONS)
-# ----------------------------------
+# ------------------------
# OPTIONS is a space-separated list of Automake options.
AC_DEFUN([_AM_SET_OPTIONS],
[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
@@ -860,12 +877,14 @@ Check your system clock])
fi
AC_MSG_RESULT(yes)])
-# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
+# Copyright (C) 2001, 2003, 2005, 2011 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.
+# serial 1
+
# AM_PROG_INSTALL_STRIP
# ---------------------
# One issue with vendor `install' (even GNU) is that you can't
@@ -888,13 +907,13 @@ fi
INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
AC_SUBST([INSTALL_STRIP_PROGRAM])])
-# Copyright (C) 2006, 2008 Free Software Foundation, Inc.
+# Copyright (C) 2006, 2008, 2010 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.
-# serial 2
+# serial 3
# _AM_SUBST_NOTMAKE(VARIABLE)
# ---------------------------
@@ -903,13 +922,13 @@ AC_SUBST([INSTALL_STRIP_PROGRAM])])
AC_DEFUN([_AM_SUBST_NOTMAKE])
# AM_SUBST_NOTMAKE(VARIABLE)
-# ---------------------------
+# --------------------------
# Public sister of _AM_SUBST_NOTMAKE.
AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
# Check how to create a tarball. -*- Autoconf -*-
-# Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+# Copyright (C) 2004, 2005, 2012 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -931,10 +950,11 @@ AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
# a tarball read from stdin.
# $(am__untar) < result.tar
AC_DEFUN([_AM_PROG_TAR],
-[# Always define AMTAR for backward compatibility.
-AM_MISSING_PROG([AMTAR], [tar])
+[# Always define AMTAR for backward compatibility. Yes, it's still used
+# in the wild :-( We should find a proper way to deprecate it ...
+AC_SUBST([AMTAR], ['$${TAR-tar}'])
m4_if([$1], [v7],
- [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'],
+ [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'],
[m4_case([$1], [ustar],, [pax],,
[m4_fatal([Unknown tar format])])
AC_MSG_CHECKING([how to create a $1 tar archive])
diff --git a/libgfortran/config.h.in b/libgfortran/config.h.in
index d7c5ceb864e..74cf35c1e40 100644
--- a/libgfortran/config.h.in
+++ b/libgfortran/config.h.in
@@ -606,6 +606,9 @@
/* Define if you have __mingw_snprintf. */
#undef HAVE_MINGW_SNPRINTF
+/* Define to 1 if you have the `mkostemp' function. */
+#undef HAVE_MKOSTEMP
+
/* Define to 1 if you have the `mkstemp' function. */
#undef HAVE_MKSTEMP
diff --git a/libgfortran/configure b/libgfortran/configure
index 21c23107394..e7469078075 100755
--- a/libgfortran/configure
+++ b/libgfortran/configure
@@ -654,6 +654,7 @@ CPP
am__fastdepCC_FALSE
am__fastdepCC_TRUE
CCDEPMODE
+am__nodep
AMDEPBACKSLASH
AMDEP_FALSE
AMDEP_TRUE
@@ -2596,6 +2597,7 @@ as_fn_append ac_func_list " umask"
as_fn_append ac_func_list " getegid"
as_fn_append ac_func_list " secure_getenv"
as_fn_append ac_func_list " __secure_getenv"
+as_fn_append ac_func_list " mkostemp"
as_fn_append ac_header_list " math.h"
# Check that the precious variables saved in the cache have kept the same
# value.
@@ -3386,11 +3388,11 @@ MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
# We need awk for the "check" target. The system "awk" is bad on
# some platforms.
-# Always define AMTAR for backward compatibility.
+# Always define AMTAR for backward compatibility. Yes, it's still used
+# in the wild :-( We should find a proper way to deprecate it ...
+AMTAR='$${TAR-tar}'
-AMTAR=${AMTAR-"${am_missing_run}tar"}
-
-am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'
+am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'
@@ -3523,6 +3525,7 @@ fi
if test "x$enable_dependency_tracking" != xno; then
am_depcomp="$ac_aux_dir/depcomp"
AMDEPBACKSLASH='\'
+ am__nodep='_no'
fi
if test "x$enable_dependency_tracking" != xno; then
AMDEP_TRUE=
@@ -4340,6 +4343,7 @@ else
# 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'.
+ rm -rf conftest.dir
mkdir conftest.dir
# Copy depcomp to subdir because otherwise we won't find it if we're
# using a relative directory.
@@ -4399,7 +4403,7 @@ else
break
fi
;;
- msvisualcpp | msvcmsys)
+ msvc7 | msvc7msys | msvisualcpp | msvcmsys)
# This compiler won't grok `-c -o', but also, the minuso test has
# not run yet. These depmodes are late enough in the game, and
# so weak that their functioning should not be impacted.
@@ -5515,6 +5519,7 @@ else
# 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'.
+ rm -rf conftest.dir
mkdir conftest.dir
# Copy depcomp to subdir because otherwise we won't find it if we're
# using a relative directory.
@@ -5574,7 +5579,7 @@ else
break
fi
;;
- msvisualcpp | msvcmsys)
+ msvc7 | msvc7msys | msvisualcpp | msvcmsys)
# This compiler won't grok `-c -o', but also, the minuso test has
# not run yet. These depmodes are late enough in the game, and
# so weak that their functioning should not be impacted.
@@ -8060,7 +8065,7 @@ ia64-*-hpux*)
rm -rf conftest*
;;
-x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \
+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
@@ -8085,7 +8090,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
;;
esac
;;
- ppc64-*linux*|powerpc64-*linux*)
+ powerpc64le-*linux*)
+ LD="${LD-ld} -m elf32lppclinux"
+ ;;
+ powerpc64-*linux*)
LD="${LD-ld} -m elf32ppclinux"
;;
s390x-*linux*)
@@ -8104,7 +8112,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
x86_64-*linux*)
LD="${LD-ld} -m elf_x86_64"
;;
- ppc*-*linux*|powerpc*-*linux*)
+ powerpcle-*linux*)
+ LD="${LD-ld} -m elf64lppc"
+ ;;
+ powerpc-*linux*)
LD="${LD-ld} -m elf64ppc"
;;
s390*-*linux*|s390*-*tpf*)
@@ -12331,7 +12342,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 12334 "configure"
+#line 12345 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -12437,7 +12448,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 12440 "configure"
+#line 12451 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -16583,6 +16594,8 @@ done
+
+
fi
# Check strerror_r, cannot be above as versions with two and three arguments exist
diff --git a/libgfortran/configure.ac b/libgfortran/configure.ac
index 4609eba8aa1..6417373404f 100644
--- a/libgfortran/configure.ac
+++ b/libgfortran/configure.ac
@@ -280,7 +280,7 @@ else
strcasestr getrlimit gettimeofday stat fstat lstat getpwuid vsnprintf dup \
getcwd localtime_r gmtime_r getpwuid_r ttyname_r clock_gettime \
readlink getgid getpid getppid getuid geteuid umask getegid \
- secure_getenv __secure_getenv)
+ secure_getenv __secure_getenv mkostemp)
fi
# Check strerror_r, cannot be above as versions with two and three arguments exist
diff --git a/libgfortran/io/list_read.c b/libgfortran/io/list_read.c
index 82a98a56e97..d38a4a8d0b4 100644
--- a/libgfortran/io/list_read.c
+++ b/libgfortran/io/list_read.c
@@ -615,6 +615,7 @@ parse_repeat (st_parameter_dt *dtp)
free_saved (dtp);
if (c == EOF)
{
+ free_line (dtp);
hit_eof (dtp);
return 1;
}
@@ -904,11 +905,14 @@ read_integer (st_parameter_dt *dtp, int length)
free_saved (dtp);
if (c == EOF)
{
+ free_line (dtp);
hit_eof (dtp);
return;
}
else if (c != '\n')
eat_line (dtp);
+
+ free_line (dtp);
snprintf (message, MSGLEN, "Bad integer for item %d in list input",
dtp->u.p.item_count);
generate_error (&dtp->common, LIBERROR_READ_VALUE, message);
@@ -1078,7 +1082,6 @@ read_character (st_parameter_dt *dtp, int length __attribute__ ((unused)))
unget_char (dtp, c);
eat_separator (dtp);
dtp->u.p.saved_type = BT_CHARACTER;
- free_line (dtp);
}
else
{
@@ -1087,10 +1090,12 @@ read_character (st_parameter_dt *dtp, int length __attribute__ ((unused)))
dtp->u.p.item_count);
generate_error (&dtp->common, LIBERROR_READ_VALUE, message);
}
+ free_line (dtp);
return;
eof:
free_saved (dtp);
+ free_line (dtp);
hit_eof (dtp);
}
@@ -1285,11 +1290,14 @@ parse_real (st_parameter_dt *dtp, void *buffer, int length)
free_saved (dtp);
if (c == EOF)
{
+ free_line (dtp);
hit_eof (dtp);
return 1;
}
else if (c != '\n')
eat_line (dtp);
+
+ free_line (dtp);
snprintf (message, MSGLEN, "Bad floating point number for item %d",
dtp->u.p.item_count);
generate_error (&dtp->common, LIBERROR_READ_VALUE, message);
@@ -1390,11 +1398,14 @@ eol_4:
free_saved (dtp);
if (c == EOF)
{
+ free_line (dtp);
hit_eof (dtp);
return;
}
else if (c != '\n')
eat_line (dtp);
+
+ free_line (dtp);
snprintf (message, MSGLEN, "Bad complex value in item %d of list input",
dtp->u.p.item_count);
generate_error (&dtp->common, LIBERROR_READ_VALUE, message);
@@ -1629,7 +1640,10 @@ read_real (st_parameter_dt *dtp, void * dest, int length)
eat_separator (dtp);
push_char (dtp, '\0');
if (convert_real (dtp, dest, dtp->u.p.saved_string, length))
- return;
+ {
+ free_saved (dtp);
+ return;
+ }
free_saved (dtp);
dtp->u.p.saved_type = BT_REAL;
@@ -1767,12 +1781,14 @@ read_real (st_parameter_dt *dtp, void * dest, int length)
free_saved (dtp);
if (c == EOF)
{
+ free_line (dtp);
hit_eof (dtp);
return;
}
else if (c != '\n')
eat_line (dtp);
+ free_line (dtp);
snprintf (message, MSGLEN, "Bad real number in item %d of list input",
dtp->u.p.item_count);
generate_error (&dtp->common, LIBERROR_READ_VALUE, message);
@@ -1789,6 +1805,7 @@ check_type (st_parameter_dt *dtp, bt type, int kind)
if (dtp->u.p.saved_type != BT_UNKNOWN && dtp->u.p.saved_type != type)
{
+ free_line (dtp);
snprintf (message, MSGLEN, "Read type %s where %s was expected for item %d",
type_name (dtp->u.p.saved_type), type_name (type),
dtp->u.p.item_count);
@@ -1803,6 +1820,7 @@ check_type (st_parameter_dt *dtp, bt type, int kind)
if ((type != BT_COMPLEX && dtp->u.p.saved_length != kind)
|| (type == BT_COMPLEX && dtp->u.p.saved_length != kind*2))
{
+ free_line (dtp);
snprintf (message, MSGLEN,
"Read kind %d %s where kind %d is required for item %d",
type == BT_COMPLEX ? dtp->u.p.saved_length / 2
@@ -1978,7 +1996,10 @@ list_formatted_read_scalar (st_parameter_dt *dtp, bt type, void *p,
cleanup:
if (err == LIBERROR_END)
- hit_eof (dtp);
+ {
+ free_line (dtp);
+ hit_eof (dtp);
+ }
return err;
}
@@ -2026,7 +2047,10 @@ finish_list_read (st_parameter_dt *dtp)
err = eat_line (dtp);
if (err == LIBERROR_END)
- hit_eof (dtp);
+ {
+ free_line (dtp);
+ hit_eof (dtp);
+ }
}
/* NAMELIST INPUT
diff --git a/libgfortran/io/unix.c b/libgfortran/io/unix.c
index dd2715b6b6d..8a84ae4eef3 100644
--- a/libgfortran/io/unix.c
+++ b/libgfortran/io/unix.c
@@ -1070,6 +1070,20 @@ unpack_filename (char *cstring, const char *fstring, int len)
}
+/* Set the close-on-exec flag for an existing fd, if the system
+ supports such. */
+
+static void __attribute__ ((unused))
+set_close_on_exec (int fd __attribute__ ((unused)))
+{
+ /* Mingw does not define F_SETFD. */
+#if defined(F_SETFD) && defined(FD_CLOEXEC)
+ if (fd >= 0)
+ fcntl(fd, F_SETFD, FD_CLOEXEC);
+#endif
+}
+
+
/* Helper function for tempfile(). Tries to open a temporary file in
the directory specified by tempdir. If successful, the file name is
stored in fname and the descriptor returned. Returns -1 on
@@ -1109,7 +1123,12 @@ tempfile_open (const char *tempdir, char **fname)
mode_mask = umask (S_IXUSR | S_IRWXG | S_IRWXO);
#endif
+#if defined(HAVE_MKOSTEMP) && defined(O_CLOEXEC)
+ fd = mkostemp (template, O_RDWR | O_CREAT | O_EXCL | O_CLOEXEC);
+#else
fd = mkstemp (template);
+ set_close_on_exec (fd);
+#endif
#ifdef HAVE_UMASK
(void) umask (mode_mask);
@@ -1119,6 +1138,13 @@ tempfile_open (const char *tempdir, char **fname)
fd = -1;
int count = 0;
size_t slashlen = strlen (slash);
+ int flags = O_RDWR | O_CREAT | O_EXCL;
+#if defined(HAVE_CRLF) && defined(O_BINARY)
+ flags |= O_BINARY;
+#endif
+#ifdef O_CLOEXEC
+ flags |= O_CLOEXEC;
+#endif
do
{
snprintf (template, tempdirlen + 23, "%s%sgfortrantmpaaaXXXXXX",
@@ -1142,14 +1168,12 @@ tempfile_open (const char *tempdir, char **fname)
continue;
}
-#if defined(HAVE_CRLF) && defined(O_BINARY)
- fd = open (template, O_RDWR | O_CREAT | O_EXCL | O_BINARY,
- S_IRUSR | S_IWUSR);
-#else
- fd = open (template, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
-#endif
+ fd = open (template, flags, S_IRUSR | S_IWUSR);
}
while (fd == -1 && errno == EEXIST);
+#ifndef O_CLOEXEC
+ set_close_on_exec (fd);
+#endif
#endif /* HAVE_MKSTEMP */
*fname = template;
@@ -1323,6 +1347,10 @@ regular_file (st_parameter_open *opp, unit_flags *flags)
crflag |= O_BINARY;
#endif
+#ifdef O_CLOEXEC
+ crflag |= O_CLOEXEC;
+#endif
+
mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
fd = open (path, rwflag | crflag, mode);
if (flags->action != ACTION_UNSPECIFIED)
@@ -1386,6 +1414,9 @@ open_external (st_parameter_open *opp, unit_flags *flags)
/* regular_file resets flags->action if it is ACTION_UNSPECIFIED and
* if it succeeds */
fd = regular_file (opp, flags);
+#ifndef O_CLOEXEC
+ set_close_on_exec (fd);
+#endif
}
if (fd < 0)
diff --git a/libgo/MERGE b/libgo/MERGE
index 5b7344c007d..28586372b0e 100644
--- a/libgo/MERGE
+++ b/libgo/MERGE
@@ -1,4 +1,4 @@
-a7bd9a33067b
+7ebbddd21330
The first line of this file holds the Mercurial revision number of the
last merge done from the master library sources.
diff --git a/libgo/Makefile.am b/libgo/Makefile.am
index 6a81d336819..5a0c9d78bf3 100644
--- a/libgo/Makefile.am
+++ b/libgo/Makefile.am
@@ -37,7 +37,8 @@ AM_CPPFLAGS = -I $(srcdir)/runtime $(LIBFFIINCS) $(PTHREAD_CFLAGS)
ACLOCAL_AMFLAGS = -I ./config -I ../config
-AM_CFLAGS = -fexceptions -fplan9-extensions $(SPLIT_STACK) $(WARN_CFLAGS) \
+AM_CFLAGS = -fexceptions -fnon-call-exceptions -fplan9-extensions \
+ $(SPLIT_STACK) $(WARN_CFLAGS) \
$(STRINGOPS_FLAG) $(OSCFLAGS) \
-I $(srcdir)/../libgcc -I $(srcdir)/../libbacktrace \
-I $(MULTIBUILDTOP)../../gcc/include
@@ -103,6 +104,7 @@ toolexeclibgo_DATA = \
bufio.gox \
bytes.gox \
crypto.gox \
+ encoding.gox \
errors.gox \
expvar.gox \
flag.gox \
@@ -251,6 +253,11 @@ toolexeclibgoimage_DATA = \
image/jpeg.gox \
image/png.gox
+toolexeclibgoimagecolordir = $(toolexeclibgoimagedir)/color
+
+toolexeclibgoimagecolor_DATA = \
+ image/color/palette.gox
+
toolexeclibgoindexdir = $(toolexeclibgodir)/index
toolexeclibgoindex_DATA = \
@@ -424,6 +431,7 @@ runtime_files = \
runtime/go-caller.c \
runtime/go-callers.c \
runtime/go-can-convert-interface.c \
+ runtime/go-cdiv.c \
runtime/go-cgo.c \
runtime/go-check-interface.c \
runtime/go-construct-map.c \
@@ -572,6 +580,9 @@ go_bytes_c_files = \
go_crypto_files = \
go/crypto/crypto.go
+go_encoding_files = \
+ go/encoding/encoding.go
+
go_errors_files = \
go/errors/errors.go
@@ -668,7 +679,7 @@ go_net_fd_os_file =
go_net_newpollserver_file =
else # !LIBGO_IS_LINUX && !LIBGO_IS_RTEMS
if LIBGO_IS_NETBSD
-go_net_fd_os_file = go/net/fd_bsd.go
+go_net_fd_os_file =
go_net_newpollserver_file =
else # !LIBGO_IS_NETBSD && !LIBGO_IS_LINUX && !LIBGO_IS_RTEMS
# By default use select with pipes. Most systems should have
@@ -725,9 +736,13 @@ else
if LIBGO_IS_FREEBSD
go_net_sendfile_file = go/net/sendfile_freebsd.go
else
+if LIBGO_IS_DRAGONFLY
+go_net_sendfile_file = go/net/sendfile_dragonfly.go
+else
go_net_sendfile_file = go/net/sendfile_stub.go
endif
endif
+endif
if LIBGO_IS_LINUX
go_net_interface_file = go/net/interface_linux.go
@@ -735,9 +750,13 @@ else
if LIBGO_IS_NETBSD
go_net_interface_file = go/net/interface_netbsd.go
else
+if LIBGO_IS_DRAGONFLY
+go_net_interface_file = go/net/interface_dragonfly.go
+else
go_net_interface_file = go/net/interface_stub.go
endif
endif
+endif
if LIBGO_IS_LINUX
go_net_cloexec_file = go/net/sock_cloexec.go
@@ -745,13 +764,17 @@ else
go_net_cloexec_file = go/net/sys_cloexec.go
endif
-if LIBGO_IS_LINUX
-go_net_poll_file = go/net/fd_poll_runtime.go
+if LIBGO_IS_OPENBSD
+go_net_tcpsockopt_file = go/net/tcpsockopt_openbsd.go
else
if LIBGO_IS_DARWIN
-go_net_poll_file = go/net/fd_poll_runtime.go
+go_net_tcpsockopt_file = go/net/tcpsockopt_darwin.go
else
-go_net_poll_file = go/net/fd_poll_unix.go
+if LIBGO_IS_SOLARIS
+go_net_tcpsockopt_file = go/net/tcpsockopt_solaris.go
+else
+go_net_tcpsockopt_file = go/net/tcpsockopt_unix.go
+endif
endif
endif
@@ -765,6 +788,7 @@ go_net_files = \
go/net/dnsconfig_unix.go \
go/net/dnsmsg.go \
$(go_net_newpollserver_file) \
+ go/net/fd_mutex.go \
go/net/fd_unix.go \
$(go_net_fd_os_file) \
go/net/file_unix.go \
@@ -782,18 +806,21 @@ go_net_files = \
go/net/net.go \
go/net/parse.go \
go/net/pipe.go \
- $(go_net_poll_file) \
+ go/net/fd_poll_runtime.go \
go/net/port.go \
go/net/port_unix.go \
+ go/net/race0.go \
$(go_net_sendfile_file) \
+ go/net/singleflight.go \
go/net/sock_posix.go \
- go/net/sock_unix.go \
$(go_net_sock_file) \
go/net/sockopt_posix.go \
$(go_net_sockopt_file) \
$(go_net_sockoptip_file) \
go/net/tcpsock.go \
go/net/tcpsock_posix.go \
+ go/net/tcpsockopt_posix.go \
+ $(go_net_tcpsockopt_file) \
go/net/udpsock.go \
go/net/udpsock_posix.go \
go/net/unixsock.go \
@@ -817,6 +844,12 @@ go_os_dir_file = go/os/dir_regfile.go
endif
endif
+if LIBGO_IS_DARWIN
+go_os_getwd_file = go/os/getwd_darwin.go
+else
+go_os_getwd_file =
+endif
+
if LIBGO_IS_LINUX
go_os_sys_file = go/os/sys_linux.go
else
@@ -853,6 +886,9 @@ else
if LIBGO_IS_NETBSD
go_os_stat_file = go/os/stat_atimespec.go
else
+if LIBGO_IS_DRAGONFLY
+go_os_stat_file = go/os/stat_dragonfly.go
+else
go_os_stat_file = go/os/stat.go
endif
endif
@@ -860,6 +896,7 @@ endif
endif
endif
endif
+endif
if LIBGO_IS_LINUX
go_os_pipe_file = go/os/pipe_linux.go
@@ -873,7 +910,7 @@ go_os_files = \
go/os/doc.go \
go/os/env.go \
go/os/error.go \
- go/os/error_posix.go \
+ go/os/error_unix.go \
go/os/exec.go \
go/os/exec_posix.go \
go/os/exec_unix.go \
@@ -881,6 +918,7 @@ go_os_files = \
go/os/file_posix.go \
go/os/file_unix.go \
go/os/getwd.go \
+ $(go_os_getwd_file) \
go/os/path.go \
go/os/path_unix.go \
$(go_os_pipe_file) \
@@ -895,9 +933,28 @@ go_path_files = \
go/path/match.go \
go/path/path.go
+if LIBGO_IS_X86_64
+go_reflect_makefunc_file = \
+ go/reflect/makefuncgo_amd64.go
+go_reflect_makefunc_s_file = \
+ go/reflect/makefunc_amd64.S
+else
+if LIBGO_IS_386
+go_reflect_makefunc_file = \
+ go/reflect/makefuncgo_386.go
+go_reflect_makefunc_s_file = \
+ go/reflect/makefunc_386.S
+else
+go_reflect_makefunc_file =
+go_reflect_makefunc_s_file = \
+ go/reflect/makefunc_dummy.c
+endif
+endif
+
go_reflect_files = \
go/reflect/deepequal.go \
go/reflect/makefunc.go \
+ $(go_reflect_makefunc_file) \
go/reflect/type.go \
go/reflect/value.go
@@ -950,7 +1007,10 @@ go_strings_files = \
go/strings/reader.go \
go/strings/replace.go \
go/strings/search.go \
- go/strings/strings.go
+ go/strings/strings.go \
+ go/strings/strings_decl.go
+go_strings_c_files = \
+ go/strings/indexbyte.c
go_sync_files = \
go/sync/cond.go \
@@ -980,6 +1040,7 @@ go_syslog_c_files = \
go_testing_files = \
go/testing/allocs.go \
go/testing/benchmark.go \
+ go/testing/cover.go \
go/testing/example.go \
go/testing/testing.go
@@ -1028,6 +1089,7 @@ go_archive_tar_files = \
go_archive_zip_files = \
go/archive/zip/reader.go \
+ go/archive/zip/register.go \
go/archive/zip/struct.go \
go/archive/zip/writer.go
@@ -1078,6 +1140,7 @@ go_crypto_cipher_files = \
go/crypto/cipher/cfb.go \
go/crypto/cipher/cipher.go \
go/crypto/cipher/ctr.go \
+ go/crypto/cipher/gcm.go \
go/crypto/cipher/io.go \
go/crypto/cipher/ofb.go
go_crypto_des_files = \
@@ -1090,7 +1153,8 @@ go_crypto_ecdsa_files = \
go/crypto/ecdsa/ecdsa.go
go_crypto_elliptic_files = \
go/crypto/elliptic/elliptic.go \
- go/crypto/elliptic/p224.go
+ go/crypto/elliptic/p224.go \
+ go/crypto/elliptic/p256.go
go_crypto_hmac_files = \
go/crypto/hmac/hmac.go
go_crypto_md5_files = \
@@ -1105,6 +1169,7 @@ go_crypto_rc4_files = \
go/crypto/rc4/rc4_ref.go
go_crypto_rsa_files = \
go/crypto/rsa/pkcs1v15.go \
+ go/crypto/rsa/pss.go \
go/crypto/rsa/rsa.go
go_crypto_sha1_files = \
go/crypto/sha1/sha1.go \
@@ -1288,11 +1353,15 @@ go_image_color_files = \
go/image/color/color.go \
go/image/color/ycbcr.go
+go_image_color_palette_files = \
+ go/image/color/palette/palette.go
+
go_image_draw_files = \
go/image/draw/draw.go
go_image_gif_files = \
- go/image/gif/reader.go
+ go/image/gif/reader.go \
+ go/image/gif/writer.go
go_image_jpeg_files = \
go/image/jpeg/fdct.go \
@@ -1746,6 +1815,7 @@ libgo_go_objs = \
bytes.lo \
bytes/index.lo \
crypto.lo \
+ encoding.lo \
errors.lo \
expvar.lo \
flag.lo \
@@ -1761,11 +1831,13 @@ libgo_go_objs = \
os.lo \
path.lo \
reflect-go.lo \
+ reflect/makefunc.lo \
regexp.lo \
runtime-go.lo \
sort.lo \
strconv.lo \
strings.lo \
+ strings/index.lo \
sync.lo \
syscall.lo \
syscall/errno.lo \
@@ -1842,6 +1914,7 @@ libgo_go_objs = \
net/http/httputil.lo \
net/http/pprof.lo \
image/color.lo \
+ image/color/palette.lo \
image/draw.lo \
image/gif.lo \
image/jpeg.lo \
@@ -2012,6 +2085,15 @@ crypto/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: crypto/check
+@go_include@ encoding.lo.dep
+encoding.lo.dep: $(go_encoding_files)
+ $(BUILDDEPS)
+encoding.lo: $(go_encoding_files)
+ $(BUILDPACKAGE)
+encoding/check: $(CHECK_DEPS)
+ @$(CHECK)
+.PHONY: encoding/check
+
@go_include@ errors.lo.dep
errors.lo.dep: $(go_errors_files)
$(BUILDDEPS)
@@ -2147,6 +2229,9 @@ reflect-go.lo: $(go_reflect_files)
$(BUILDPACKAGE)
reflect/check: $(CHECK_DEPS)
@$(CHECK)
+reflect/makefunc.lo: $(go_reflect_makefunc_s_file)
+ @$(MKDIR_P) reflect
+ $(LTCOMPILE) -c -o $@ $<
.PHONY: reflect/check
@go_include@ regexp.lo.dep
@@ -2190,6 +2275,9 @@ strings.lo.dep: $(go_strings_files)
$(BUILDDEPS)
strings.lo: $(go_strings_files)
$(BUILDPACKAGE)
+strings/index.lo: $(go_strings_c_files)
+ @$(MKDIR_P) strings
+ $(LTCOMPILE) -c -o strings/index.lo $(srcdir)/go/strings/indexbyte.c
strings/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: strings/check
@@ -2797,6 +2885,15 @@ image/color/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: image/color/check
+@go_include@ image/color/palette.lo.dep
+image/color/palette.lo.dep: $(go_image_color_palette_files)
+ $(BUILDDEPS)
+image/color/palette.lo: $(go_image_color_palette_files)
+ $(BUILDPACKAGE)
+image/color/palette/check: $(CHECK_DEPS)
+ @$(CHECK)
+.PHONY: image/color/palette/check
+
@go_include@ image/draw.lo.dep
image/draw.lo.dep: $(go_image_draw_files)
$(BUILDDEPS)
@@ -3212,6 +3309,8 @@ bytes.gox: bytes.lo
$(BUILDGOX)
crypto.gox: crypto.lo
$(BUILDGOX)
+encoding.gox: encoding.lo
+ $(BUILDGOX)
errors.gox: errors.lo
$(BUILDGOX)
expvar.gox: expvar.lo
@@ -3409,6 +3508,9 @@ image/jpeg.gox: image/jpeg.lo
image/png.gox: image/png.lo
$(BUILDGOX)
+image/color/palette.gox: image/color/palette.lo
+ $(BUILDGOX)
+
index/suffixarray.gox: index/suffixarray.lo
$(BUILDGOX)
diff --git a/libgo/Makefile.in b/libgo/Makefile.in
index 7ef67162578..4a31920b04c 100644
--- a/libgo/Makefile.in
+++ b/libgo/Makefile.in
@@ -128,6 +128,7 @@ am__installdirs = "$(DESTDIR)$(toolexeclibdir)" \
"$(DESTDIR)$(toolexeclibgohashdir)" \
"$(DESTDIR)$(toolexeclibgohtmldir)" \
"$(DESTDIR)$(toolexeclibgoimagedir)" \
+ "$(DESTDIR)$(toolexeclibgoimagecolordir)" \
"$(DESTDIR)$(toolexeclibgoindexdir)" \
"$(DESTDIR)$(toolexeclibgoiodir)" \
"$(DESTDIR)$(toolexeclibgologdir)" \
@@ -155,19 +156,19 @@ libgobegin_a_OBJECTS = $(am_libgobegin_a_OBJECTS)
LTLIBRARIES = $(toolexeclib_LTLIBRARIES)
am__DEPENDENCIES_1 =
am__DEPENDENCIES_2 = bufio.lo bytes.lo bytes/index.lo crypto.lo \
- errors.lo expvar.lo flag.lo fmt.lo hash.lo html.lo image.lo \
- io.lo log.lo math.lo mime.lo net.lo os.lo path.lo \
- reflect-go.lo regexp.lo runtime-go.lo sort.lo strconv.lo \
- strings.lo sync.lo syscall.lo syscall/errno.lo \
- syscall/signame.lo syscall/wait.lo testing.lo time-go.lo \
- unicode.lo archive/tar.lo archive/zip.lo compress/bzip2.lo \
- compress/flate.lo compress/gzip.lo compress/lzw.lo \
- compress/zlib.lo container/heap.lo container/list.lo \
- container/ring.lo crypto/aes.lo crypto/cipher.lo crypto/des.lo \
- crypto/dsa.lo crypto/ecdsa.lo crypto/elliptic.lo \
- crypto/hmac.lo crypto/md5.lo crypto/rand.lo crypto/rc4.lo \
- crypto/rsa.lo crypto/sha1.lo crypto/sha256.lo crypto/sha512.lo \
- crypto/subtle.lo crypto/tls.lo crypto/x509.lo \
+ encoding.lo errors.lo expvar.lo flag.lo fmt.lo hash.lo html.lo \
+ image.lo io.lo log.lo math.lo mime.lo net.lo os.lo path.lo \
+ reflect-go.lo reflect/makefunc.lo regexp.lo runtime-go.lo \
+ sort.lo strconv.lo strings.lo strings/index.lo sync.lo \
+ syscall.lo syscall/errno.lo syscall/signame.lo syscall/wait.lo \
+ testing.lo time-go.lo unicode.lo archive/tar.lo archive/zip.lo \
+ compress/bzip2.lo compress/flate.lo compress/gzip.lo \
+ compress/lzw.lo compress/zlib.lo container/heap.lo \
+ container/list.lo container/ring.lo crypto/aes.lo \
+ crypto/cipher.lo crypto/des.lo crypto/dsa.lo crypto/ecdsa.lo \
+ crypto/elliptic.lo crypto/hmac.lo crypto/md5.lo crypto/rand.lo \
+ crypto/rc4.lo crypto/rsa.lo crypto/sha1.lo crypto/sha256.lo \
+ crypto/sha512.lo crypto/subtle.lo crypto/tls.lo crypto/x509.lo \
crypto/x509/pkix.lo database/sql.lo database/sql/driver.lo \
debug/dwarf.lo debug/elf.lo debug/gosym.lo debug/macho.lo \
debug/pe.lo encoding/ascii85.lo encoding/asn1.lo \
@@ -180,13 +181,13 @@ am__DEPENDENCIES_2 = bufio.lo bytes.lo bytes/index.lo crypto.lo \
hash/crc64.lo hash/fnv.lo net/http/cgi.lo \
net/http/cookiejar.lo net/http/fcgi.lo net/http/httptest.lo \
net/http/httputil.lo net/http/pprof.lo image/color.lo \
- image/draw.lo image/gif.lo image/jpeg.lo image/png.lo \
- index/suffixarray.lo io/ioutil.lo log/syslog.lo \
- log/syslog/syslog_c.lo math/big.lo math/cmplx.lo math/rand.lo \
- mime/multipart.lo net/http.lo net/mail.lo net/rpc.lo \
- net/smtp.lo net/textproto.lo net/url.lo old/regexp.lo \
- old/template.lo os/exec.lo $(am__DEPENDENCIES_1) os/signal.lo \
- os/user.lo path/filepath.lo regexp/syntax.lo \
+ image/color/palette.lo image/draw.lo image/gif.lo \
+ image/jpeg.lo image/png.lo index/suffixarray.lo io/ioutil.lo \
+ log/syslog.lo log/syslog/syslog_c.lo math/big.lo math/cmplx.lo \
+ math/rand.lo mime/multipart.lo net/http.lo net/mail.lo \
+ net/rpc.lo net/smtp.lo net/textproto.lo net/url.lo \
+ old/regexp.lo old/template.lo os/exec.lo $(am__DEPENDENCIES_1) \
+ os/signal.lo os/user.lo path/filepath.lo regexp/syntax.lo \
net/rpc/jsonrpc.lo runtime/debug.lo runtime/pprof.lo \
sync/atomic.lo sync/atomic_c.lo text/scanner.lo \
text/tabwriter.lo text/template.lo text/template/parse.lo \
@@ -218,7 +219,7 @@ libgo_la_DEPENDENCIES = $(am__DEPENDENCIES_2) \
@LIBGO_IS_LINUX_TRUE@am__objects_5 = getncpu-linux.lo
am__objects_6 = go-append.lo go-assert.lo go-assert-interface.lo \
go-byte-array-to-string.lo go-breakpoint.lo go-caller.lo \
- go-callers.lo go-can-convert-interface.lo go-cgo.lo \
+ go-callers.lo go-can-convert-interface.lo go-cdiv.lo go-cgo.lo \
go-check-interface.lo go-construct-map.lo \
go-convert-interface.lo go-copy.lo go-defer.lo \
go-deferred-recover.lo go-eface-compare.lo \
@@ -288,16 +289,16 @@ DATA = $(toolexeclibgo_DATA) $(toolexeclibgoarchive_DATA) \
$(toolexeclibgodebug_DATA) $(toolexeclibgoencoding_DATA) \
$(toolexeclibgoexp_DATA) $(toolexeclibgogo_DATA) \
$(toolexeclibgohash_DATA) $(toolexeclibgohtml_DATA) \
- $(toolexeclibgoimage_DATA) $(toolexeclibgoindex_DATA) \
- $(toolexeclibgoio_DATA) $(toolexeclibgolog_DATA) \
- $(toolexeclibgomath_DATA) $(toolexeclibgomime_DATA) \
- $(toolexeclibgonet_DATA) $(toolexeclibgonethttp_DATA) \
- $(toolexeclibgonetrpc_DATA) $(toolexeclibgoold_DATA) \
- $(toolexeclibgoos_DATA) $(toolexeclibgopath_DATA) \
- $(toolexeclibgoregexp_DATA) $(toolexeclibgoruntime_DATA) \
- $(toolexeclibgosync_DATA) $(toolexeclibgotesting_DATA) \
- $(toolexeclibgotext_DATA) $(toolexeclibgotexttemplate_DATA) \
- $(toolexeclibgounicode_DATA)
+ $(toolexeclibgoimage_DATA) $(toolexeclibgoimagecolor_DATA) \
+ $(toolexeclibgoindex_DATA) $(toolexeclibgoio_DATA) \
+ $(toolexeclibgolog_DATA) $(toolexeclibgomath_DATA) \
+ $(toolexeclibgomime_DATA) $(toolexeclibgonet_DATA) \
+ $(toolexeclibgonethttp_DATA) $(toolexeclibgonetrpc_DATA) \
+ $(toolexeclibgoold_DATA) $(toolexeclibgoos_DATA) \
+ $(toolexeclibgopath_DATA) $(toolexeclibgoregexp_DATA) \
+ $(toolexeclibgoruntime_DATA) $(toolexeclibgosync_DATA) \
+ $(toolexeclibgotesting_DATA) $(toolexeclibgotext_DATA) \
+ $(toolexeclibgotexttemplate_DATA) $(toolexeclibgounicode_DATA)
RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
distclean-recursive maintainer-clean-recursive
AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
@@ -471,7 +472,8 @@ WARN_CFLAGS = $(WARN_FLAGS) $(WERROR)
# -I/-D flags to pass when compiling.
AM_CPPFLAGS = -I $(srcdir)/runtime $(LIBFFIINCS) $(PTHREAD_CFLAGS)
ACLOCAL_AMFLAGS = -I ./config -I ../config
-AM_CFLAGS = -fexceptions -fplan9-extensions $(SPLIT_STACK) $(WARN_CFLAGS) \
+AM_CFLAGS = -fexceptions -fnon-call-exceptions -fplan9-extensions \
+ $(SPLIT_STACK) $(WARN_CFLAGS) \
$(STRINGOPS_FLAG) $(OSCFLAGS) \
-I $(srcdir)/../libgcc -I $(srcdir)/../libbacktrace \
-I $(MULTIBUILDTOP)../../gcc/include
@@ -534,6 +536,7 @@ toolexeclibgo_DATA = \
bufio.gox \
bytes.gox \
crypto.gox \
+ encoding.gox \
errors.gox \
expvar.gox \
flag.gox \
@@ -668,6 +671,10 @@ toolexeclibgoimage_DATA = \
image/jpeg.gox \
image/png.gox
+toolexeclibgoimagecolordir = $(toolexeclibgoimagedir)/color
+toolexeclibgoimagecolor_DATA = \
+ image/color/palette.gox
+
toolexeclibgoindexdir = $(toolexeclibgodir)/index
toolexeclibgoindex_DATA = \
index/suffixarray.gox
@@ -785,6 +792,7 @@ runtime_files = \
runtime/go-caller.c \
runtime/go-callers.c \
runtime/go-can-convert-interface.c \
+ runtime/go-cdiv.c \
runtime/go-cgo.c \
runtime/go-check-interface.c \
runtime/go-construct-map.c \
@@ -892,6 +900,9 @@ go_bytes_c_files = \
go_crypto_files = \
go/crypto/crypto.go
+go_encoding_files = \
+ go/encoding/encoding.go
+
go_errors_files = \
go/errors/errors.go
@@ -982,7 +993,7 @@ go_mime_files = \
# By default use select with pipes. Most systems should have
# something better.
@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_RTEMS_FALSE@go_net_fd_os_file = go/net/fd_select.go
-@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@@LIBGO_IS_RTEMS_FALSE@go_net_fd_os_file = go/net/fd_bsd.go
+@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@@LIBGO_IS_RTEMS_FALSE@go_net_fd_os_file =
@LIBGO_IS_LINUX_TRUE@@LIBGO_IS_RTEMS_FALSE@go_net_fd_os_file =
@LIBGO_IS_RTEMS_TRUE@go_net_fd_os_file = go/net/fd_select.go
@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_RTEMS_FALSE@go_net_newpollserver_file =
@@ -1013,17 +1024,20 @@ go_mime_files = \
@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@go_net_sockoptip_file = go/net/sockoptip_bsd.go go/net/sockoptip_posix.go
@LIBGO_IS_IRIX_TRUE@@LIBGO_IS_LINUX_FALSE@go_net_sockoptip_file = go/net/sockoptip_linux.go go/net/sockoptip_posix.go
@LIBGO_IS_LINUX_TRUE@go_net_sockoptip_file = go/net/sockoptip_linux.go go/net/sockoptip_posix.go
-@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_LINUX_FALSE@go_net_sendfile_file = go/net/sendfile_stub.go
+@LIBGO_IS_DRAGONFLY_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_LINUX_FALSE@go_net_sendfile_file = go/net/sendfile_stub.go
+@LIBGO_IS_DRAGONFLY_TRUE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_LINUX_FALSE@go_net_sendfile_file = go/net/sendfile_dragonfly.go
@LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_LINUX_FALSE@go_net_sendfile_file = go/net/sendfile_freebsd.go
@LIBGO_IS_LINUX_TRUE@go_net_sendfile_file = go/net/sendfile_linux.go
-@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@go_net_interface_file = go/net/interface_stub.go
+@LIBGO_IS_DRAGONFLY_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@go_net_interface_file = go/net/interface_stub.go
+@LIBGO_IS_DRAGONFLY_TRUE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@go_net_interface_file = go/net/interface_dragonfly.go
@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@go_net_interface_file = go/net/interface_netbsd.go
@LIBGO_IS_LINUX_TRUE@go_net_interface_file = go/net/interface_linux.go
@LIBGO_IS_LINUX_FALSE@go_net_cloexec_file = go/net/sys_cloexec.go
@LIBGO_IS_LINUX_TRUE@go_net_cloexec_file = go/net/sock_cloexec.go
-@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_LINUX_FALSE@go_net_poll_file = go/net/fd_poll_unix.go
-@LIBGO_IS_DARWIN_TRUE@@LIBGO_IS_LINUX_FALSE@go_net_poll_file = go/net/fd_poll_runtime.go
-@LIBGO_IS_LINUX_TRUE@go_net_poll_file = go/net/fd_poll_runtime.go
+@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_OPENBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_tcpsockopt_file = go/net/tcpsockopt_unix.go
+@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_OPENBSD_FALSE@@LIBGO_IS_SOLARIS_TRUE@go_net_tcpsockopt_file = go/net/tcpsockopt_solaris.go
+@LIBGO_IS_DARWIN_TRUE@@LIBGO_IS_OPENBSD_FALSE@go_net_tcpsockopt_file = go/net/tcpsockopt_darwin.go
+@LIBGO_IS_OPENBSD_TRUE@go_net_tcpsockopt_file = go/net/tcpsockopt_openbsd.go
go_net_files = \
go/net/cgo_unix.go \
$(go_net_cgo_file) \
@@ -1034,6 +1048,7 @@ go_net_files = \
go/net/dnsconfig_unix.go \
go/net/dnsmsg.go \
$(go_net_newpollserver_file) \
+ go/net/fd_mutex.go \
go/net/fd_unix.go \
$(go_net_fd_os_file) \
go/net/file_unix.go \
@@ -1051,18 +1066,21 @@ go_net_files = \
go/net/net.go \
go/net/parse.go \
go/net/pipe.go \
- $(go_net_poll_file) \
+ go/net/fd_poll_runtime.go \
go/net/port.go \
go/net/port_unix.go \
+ go/net/race0.go \
$(go_net_sendfile_file) \
+ go/net/singleflight.go \
go/net/sock_posix.go \
- go/net/sock_unix.go \
$(go_net_sock_file) \
go/net/sockopt_posix.go \
$(go_net_sockopt_file) \
$(go_net_sockoptip_file) \
go/net/tcpsock.go \
go/net/tcpsock_posix.go \
+ go/net/tcpsockopt_posix.go \
+ $(go_net_tcpsockopt_file) \
go/net/udpsock.go \
go/net/udpsock_posix.go \
go/net/unixsock.go \
@@ -1073,12 +1091,15 @@ go_net_files = \
@LIBGO_IS_386_TRUE@@LIBGO_IS_SOLARIS_TRUE@go_os_dir_file = go/os/dir_largefile.go
@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_os_dir_file = go/os/dir_regfile.go
@LIBGO_IS_LINUX_TRUE@@LIBGO_IS_SOLARIS_FALSE@go_os_dir_file = go/os/dir_largefile.go
+@LIBGO_IS_DARWIN_FALSE@go_os_getwd_file =
+@LIBGO_IS_DARWIN_TRUE@go_os_getwd_file = go/os/getwd_darwin.go
@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_RTEMS_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_os_sys_file = go/os/sys_bsd.go
@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_RTEMS_TRUE@@LIBGO_IS_SOLARIS_FALSE@go_os_sys_file = go/os/sys_uname.go
@LIBGO_IS_IRIX_TRUE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_os_sys_file = go/os/sys_uname.go
@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@go_os_sys_file = go/os/sys_uname.go
@LIBGO_IS_LINUX_TRUE@go_os_sys_file = go/os/sys_linux.go
-@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_OPENBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_os_stat_file = go/os/stat.go
+@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_DRAGONFLY_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_OPENBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_os_stat_file = go/os/stat.go
+@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_DRAGONFLY_TRUE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_OPENBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_os_stat_file = go/os/stat_dragonfly.go
@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@@LIBGO_IS_OPENBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_os_stat_file = go/os/stat_atimespec.go
@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_OPENBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_os_stat_file = go/os/stat_atimespec.go
@LIBGO_IS_DARWIN_TRUE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_OPENBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_os_stat_file = go/os/stat_atimespec.go
@@ -1093,7 +1114,7 @@ go_os_files = \
go/os/doc.go \
go/os/env.go \
go/os/error.go \
- go/os/error_posix.go \
+ go/os/error_unix.go \
go/os/exec.go \
go/os/exec_posix.go \
go/os/exec_unix.go \
@@ -1101,6 +1122,7 @@ go_os_files = \
go/os/file_posix.go \
go/os/file_unix.go \
go/os/getwd.go \
+ $(go_os_getwd_file) \
go/os/path.go \
go/os/path_unix.go \
$(go_os_pipe_file) \
@@ -1115,9 +1137,26 @@ go_path_files = \
go/path/match.go \
go/path/path.go
+@LIBGO_IS_386_FALSE@@LIBGO_IS_X86_64_FALSE@go_reflect_makefunc_file =
+@LIBGO_IS_386_TRUE@@LIBGO_IS_X86_64_FALSE@go_reflect_makefunc_file = \
+@LIBGO_IS_386_TRUE@@LIBGO_IS_X86_64_FALSE@ go/reflect/makefuncgo_386.go
+
+@LIBGO_IS_X86_64_TRUE@go_reflect_makefunc_file = \
+@LIBGO_IS_X86_64_TRUE@ go/reflect/makefuncgo_amd64.go
+
+@LIBGO_IS_386_FALSE@@LIBGO_IS_X86_64_FALSE@go_reflect_makefunc_s_file = \
+@LIBGO_IS_386_FALSE@@LIBGO_IS_X86_64_FALSE@ go/reflect/makefunc_dummy.c
+
+@LIBGO_IS_386_TRUE@@LIBGO_IS_X86_64_FALSE@go_reflect_makefunc_s_file = \
+@LIBGO_IS_386_TRUE@@LIBGO_IS_X86_64_FALSE@ go/reflect/makefunc_386.S
+
+@LIBGO_IS_X86_64_TRUE@go_reflect_makefunc_s_file = \
+@LIBGO_IS_X86_64_TRUE@ go/reflect/makefunc_amd64.S
+
go_reflect_files = \
go/reflect/deepequal.go \
go/reflect/makefunc.go \
+ $(go_reflect_makefunc_file) \
go/reflect/type.go \
go/reflect/value.go
@@ -1159,7 +1198,11 @@ go_strings_files = \
go/strings/reader.go \
go/strings/replace.go \
go/strings/search.go \
- go/strings/strings.go
+ go/strings/strings.go \
+ go/strings/strings_decl.go
+
+go_strings_c_files = \
+ go/strings/indexbyte.c
go_sync_files = \
go/sync/cond.go \
@@ -1183,6 +1226,7 @@ go_syslog_c_files = \
go_testing_files = \
go/testing/allocs.go \
go/testing/benchmark.go \
+ go/testing/cover.go \
go/testing/example.go \
go/testing/testing.go
@@ -1218,6 +1262,7 @@ go_archive_tar_files = \
go_archive_zip_files = \
go/archive/zip/reader.go \
+ go/archive/zip/register.go \
go/archive/zip/struct.go \
go/archive/zip/writer.go
@@ -1269,6 +1314,7 @@ go_crypto_cipher_files = \
go/crypto/cipher/cfb.go \
go/crypto/cipher/cipher.go \
go/crypto/cipher/ctr.go \
+ go/crypto/cipher/gcm.go \
go/crypto/cipher/io.go \
go/crypto/cipher/ofb.go
@@ -1285,7 +1331,8 @@ go_crypto_ecdsa_files = \
go_crypto_elliptic_files = \
go/crypto/elliptic/elliptic.go \
- go/crypto/elliptic/p224.go
+ go/crypto/elliptic/p224.go \
+ go/crypto/elliptic/p256.go
go_crypto_hmac_files = \
go/crypto/hmac/hmac.go
@@ -1305,6 +1352,7 @@ go_crypto_rc4_files = \
go_crypto_rsa_files = \
go/crypto/rsa/pkcs1v15.go \
+ go/crypto/rsa/pss.go \
go/crypto/rsa/rsa.go
go_crypto_sha1_files = \
@@ -1519,11 +1567,15 @@ go_image_color_files = \
go/image/color/color.go \
go/image/color/ycbcr.go
+go_image_color_palette_files = \
+ go/image/color/palette/palette.go
+
go_image_draw_files = \
go/image/draw/draw.go
go_image_gif_files = \
- go/image/gif/reader.go
+ go/image/gif/reader.go \
+ go/image/gif/writer.go
go_image_jpeg_files = \
go/image/jpeg/fdct.go \
@@ -1859,6 +1911,7 @@ libgo_go_objs = \
bytes.lo \
bytes/index.lo \
crypto.lo \
+ encoding.lo \
errors.lo \
expvar.lo \
flag.lo \
@@ -1874,11 +1927,13 @@ libgo_go_objs = \
os.lo \
path.lo \
reflect-go.lo \
+ reflect/makefunc.lo \
regexp.lo \
runtime-go.lo \
sort.lo \
strconv.lo \
strings.lo \
+ strings/index.lo \
sync.lo \
syscall.lo \
syscall/errno.lo \
@@ -1955,6 +2010,7 @@ libgo_go_objs = \
net/http/httputil.lo \
net/http/pprof.lo \
image/color.lo \
+ image/color/palette.lo \
image/draw.lo \
image/gif.lo \
image/jpeg.lo \
@@ -2376,6 +2432,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-caller.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-callers.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-can-convert-interface.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-cdiv.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-cgo.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-check-interface.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-construct-map.Plo@am__quote@
@@ -2562,6 +2619,13 @@ go-can-convert-interface.lo: runtime/go-can-convert-interface.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-can-convert-interface.lo `test -f 'runtime/go-can-convert-interface.c' || echo '$(srcdir)/'`runtime/go-can-convert-interface.c
+go-cdiv.lo: runtime/go-cdiv.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-cdiv.lo -MD -MP -MF $(DEPDIR)/go-cdiv.Tpo -c -o go-cdiv.lo `test -f 'runtime/go-cdiv.c' || echo '$(srcdir)/'`runtime/go-cdiv.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-cdiv.Tpo $(DEPDIR)/go-cdiv.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-cdiv.c' object='go-cdiv.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-cdiv.lo `test -f 'runtime/go-cdiv.c' || echo '$(srcdir)/'`runtime/go-cdiv.c
+
go-cgo.lo: runtime/go-cgo.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-cgo.lo -MD -MP -MF $(DEPDIR)/go-cgo.Tpo -c -o go-cgo.lo `test -f 'runtime/go-cgo.c' || echo '$(srcdir)/'`runtime/go-cgo.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-cgo.Tpo $(DEPDIR)/go-cgo.Plo
@@ -3532,6 +3596,26 @@ uninstall-toolexeclibgoimageDATA:
@list='$(toolexeclibgoimage_DATA)'; test -n "$(toolexeclibgoimagedir)" || list=; \
files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
dir='$(DESTDIR)$(toolexeclibgoimagedir)'; $(am__uninstall_files_from_dir)
+install-toolexeclibgoimagecolorDATA: $(toolexeclibgoimagecolor_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(toolexeclibgoimagecolordir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgoimagecolordir)"
+ @list='$(toolexeclibgoimagecolor_DATA)'; test -n "$(toolexeclibgoimagecolordir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(toolexeclibgoimagecolordir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(toolexeclibgoimagecolordir)" || exit $$?; \
+ done
+
+uninstall-toolexeclibgoimagecolorDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(toolexeclibgoimagecolor_DATA)'; test -n "$(toolexeclibgoimagecolordir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(toolexeclibgoimagecolordir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(toolexeclibgoimagecolordir)" && rm -f $$files
install-toolexeclibgoindexDATA: $(toolexeclibgoindex_DATA)
@$(NORMAL_INSTALL)
@list='$(toolexeclibgoindex_DATA)'; test -n "$(toolexeclibgoindexdir)" || list=; \
@@ -4051,7 +4135,7 @@ all-am: Makefile $(LIBRARIES) $(LTLIBRARIES) all-multi $(DATA) \
config.h
installdirs: installdirs-recursive
installdirs-am:
- for dir in "$(DESTDIR)$(toolexeclibdir)" "$(DESTDIR)$(toolexeclibdir)" "$(DESTDIR)$(toolexeclibgodir)" "$(DESTDIR)$(toolexeclibgoarchivedir)" "$(DESTDIR)$(toolexeclibgocompressdir)" "$(DESTDIR)$(toolexeclibgocontainerdir)" "$(DESTDIR)$(toolexeclibgocryptodir)" "$(DESTDIR)$(toolexeclibgocryptox509dir)" "$(DESTDIR)$(toolexeclibgodatabasedir)" "$(DESTDIR)$(toolexeclibgodatabasesqldir)" "$(DESTDIR)$(toolexeclibgodebugdir)" "$(DESTDIR)$(toolexeclibgoencodingdir)" "$(DESTDIR)$(toolexeclibgoexpdir)" "$(DESTDIR)$(toolexeclibgogodir)" "$(DESTDIR)$(toolexeclibgohashdir)" "$(DESTDIR)$(toolexeclibgohtmldir)" "$(DESTDIR)$(toolexeclibgoimagedir)" "$(DESTDIR)$(toolexeclibgoindexdir)" "$(DESTDIR)$(toolexeclibgoiodir)" "$(DESTDIR)$(toolexeclibgologdir)" "$(DESTDIR)$(toolexeclibgomathdir)" "$(DESTDIR)$(toolexeclibgomimedir)" "$(DESTDIR)$(toolexeclibgonetdir)" "$(DESTDIR)$(toolexeclibgonethttpdir)" "$(DESTDIR)$(toolexeclibgonetrpcdir)" "$(DESTDIR)$(toolexeclibgoolddir)" "$(DESTDIR)$(toolexeclibgoosdir)" "$(DESTDIR)$(toolexeclibgopathdir)" "$(DESTDIR)$(toolexeclibgoregexpdir)" "$(DESTDIR)$(toolexeclibgoruntimedir)" "$(DESTDIR)$(toolexeclibgosyncdir)" "$(DESTDIR)$(toolexeclibgotestingdir)" "$(DESTDIR)$(toolexeclibgotextdir)" "$(DESTDIR)$(toolexeclibgotexttemplatedir)" "$(DESTDIR)$(toolexeclibgounicodedir)"; do \
+ for dir in "$(DESTDIR)$(toolexeclibdir)" "$(DESTDIR)$(toolexeclibdir)" "$(DESTDIR)$(toolexeclibgodir)" "$(DESTDIR)$(toolexeclibgoarchivedir)" "$(DESTDIR)$(toolexeclibgocompressdir)" "$(DESTDIR)$(toolexeclibgocontainerdir)" "$(DESTDIR)$(toolexeclibgocryptodir)" "$(DESTDIR)$(toolexeclibgocryptox509dir)" "$(DESTDIR)$(toolexeclibgodatabasedir)" "$(DESTDIR)$(toolexeclibgodatabasesqldir)" "$(DESTDIR)$(toolexeclibgodebugdir)" "$(DESTDIR)$(toolexeclibgoencodingdir)" "$(DESTDIR)$(toolexeclibgoexpdir)" "$(DESTDIR)$(toolexeclibgogodir)" "$(DESTDIR)$(toolexeclibgohashdir)" "$(DESTDIR)$(toolexeclibgohtmldir)" "$(DESTDIR)$(toolexeclibgoimagedir)" "$(DESTDIR)$(toolexeclibgoimagecolordir)" "$(DESTDIR)$(toolexeclibgoindexdir)" "$(DESTDIR)$(toolexeclibgoiodir)" "$(DESTDIR)$(toolexeclibgologdir)" "$(DESTDIR)$(toolexeclibgomathdir)" "$(DESTDIR)$(toolexeclibgomimedir)" "$(DESTDIR)$(toolexeclibgonetdir)" "$(DESTDIR)$(toolexeclibgonethttpdir)" "$(DESTDIR)$(toolexeclibgonetrpcdir)" "$(DESTDIR)$(toolexeclibgoolddir)" "$(DESTDIR)$(toolexeclibgoosdir)" "$(DESTDIR)$(toolexeclibgopathdir)" "$(DESTDIR)$(toolexeclibgoregexpdir)" "$(DESTDIR)$(toolexeclibgoruntimedir)" "$(DESTDIR)$(toolexeclibgosyncdir)" "$(DESTDIR)$(toolexeclibgotestingdir)" "$(DESTDIR)$(toolexeclibgotextdir)" "$(DESTDIR)$(toolexeclibgotexttemplatedir)" "$(DESTDIR)$(toolexeclibgounicodedir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
install: install-recursive
@@ -4129,6 +4213,7 @@ install-exec-am: install-multi install-toolexeclibLIBRARIES \
install-toolexeclibgoencodingDATA install-toolexeclibgoexpDATA \
install-toolexeclibgogoDATA install-toolexeclibgohashDATA \
install-toolexeclibgohtmlDATA install-toolexeclibgoimageDATA \
+ install-toolexeclibgoimagecolorDATA \
install-toolexeclibgoindexDATA install-toolexeclibgoioDATA \
install-toolexeclibgologDATA install-toolexeclibgomathDATA \
install-toolexeclibgomimeDATA install-toolexeclibgonetDATA \
@@ -4196,6 +4281,7 @@ uninstall-am: uninstall-toolexeclibLIBRARIES \
uninstall-toolexeclibgohashDATA \
uninstall-toolexeclibgohtmlDATA \
uninstall-toolexeclibgoimageDATA \
+ uninstall-toolexeclibgoimagecolorDATA \
uninstall-toolexeclibgoindexDATA uninstall-toolexeclibgoioDATA \
uninstall-toolexeclibgologDATA uninstall-toolexeclibgomathDATA \
uninstall-toolexeclibgomimeDATA uninstall-toolexeclibgonetDATA \
@@ -4240,6 +4326,7 @@ uninstall-am: uninstall-toolexeclibLIBRARIES \
install-toolexeclibgoencodingDATA install-toolexeclibgoexpDATA \
install-toolexeclibgogoDATA install-toolexeclibgohashDATA \
install-toolexeclibgohtmlDATA install-toolexeclibgoimageDATA \
+ install-toolexeclibgoimagecolorDATA \
install-toolexeclibgoindexDATA install-toolexeclibgoioDATA \
install-toolexeclibgologDATA install-toolexeclibgomathDATA \
install-toolexeclibgomimeDATA install-toolexeclibgonetDATA \
@@ -4271,6 +4358,7 @@ uninstall-am: uninstall-toolexeclibLIBRARIES \
uninstall-toolexeclibgohashDATA \
uninstall-toolexeclibgohtmlDATA \
uninstall-toolexeclibgoimageDATA \
+ uninstall-toolexeclibgoimagecolorDATA \
uninstall-toolexeclibgoindexDATA uninstall-toolexeclibgoioDATA \
uninstall-toolexeclibgologDATA uninstall-toolexeclibgomathDATA \
uninstall-toolexeclibgomimeDATA uninstall-toolexeclibgonetDATA \
@@ -4428,6 +4516,15 @@ crypto/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: crypto/check
+@go_include@ encoding.lo.dep
+encoding.lo.dep: $(go_encoding_files)
+ $(BUILDDEPS)
+encoding.lo: $(go_encoding_files)
+ $(BUILDPACKAGE)
+encoding/check: $(CHECK_DEPS)
+ @$(CHECK)
+.PHONY: encoding/check
+
@go_include@ errors.lo.dep
errors.lo.dep: $(go_errors_files)
$(BUILDDEPS)
@@ -4563,6 +4660,9 @@ reflect-go.lo: $(go_reflect_files)
$(BUILDPACKAGE)
reflect/check: $(CHECK_DEPS)
@$(CHECK)
+reflect/makefunc.lo: $(go_reflect_makefunc_s_file)
+ @$(MKDIR_P) reflect
+ $(LTCOMPILE) -c -o $@ $<
.PHONY: reflect/check
@go_include@ regexp.lo.dep
@@ -4606,6 +4706,9 @@ strings.lo.dep: $(go_strings_files)
$(BUILDDEPS)
strings.lo: $(go_strings_files)
$(BUILDPACKAGE)
+strings/index.lo: $(go_strings_c_files)
+ @$(MKDIR_P) strings
+ $(LTCOMPILE) -c -o strings/index.lo $(srcdir)/go/strings/indexbyte.c
strings/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: strings/check
@@ -5213,6 +5316,15 @@ image/color/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: image/color/check
+@go_include@ image/color/palette.lo.dep
+image/color/palette.lo.dep: $(go_image_color_palette_files)
+ $(BUILDDEPS)
+image/color/palette.lo: $(go_image_color_palette_files)
+ $(BUILDPACKAGE)
+image/color/palette/check: $(CHECK_DEPS)
+ @$(CHECK)
+.PHONY: image/color/palette/check
+
@go_include@ image/draw.lo.dep
image/draw.lo.dep: $(go_image_draw_files)
$(BUILDDEPS)
@@ -5620,6 +5732,8 @@ bytes.gox: bytes.lo
$(BUILDGOX)
crypto.gox: crypto.lo
$(BUILDGOX)
+encoding.gox: encoding.lo
+ $(BUILDGOX)
errors.gox: errors.lo
$(BUILDGOX)
expvar.gox: expvar.lo
@@ -5817,6 +5931,9 @@ image/jpeg.gox: image/jpeg.lo
image/png.gox: image/png.lo
$(BUILDGOX)
+image/color/palette.gox: image/color/palette.lo
+ $(BUILDGOX)
+
index/suffixarray.gox: index/suffixarray.lo
$(BUILDGOX)
diff --git a/libgo/config.h.in b/libgo/config.h.in
index 349ace6a2ad..8af626d6208 100644
--- a/libgo/config.h.in
+++ b/libgo/config.h.in
@@ -3,6 +3,9 @@
/* Define if building universal (internal helper macro) */
#undef AC_APPLE_UNIVERSAL_BUILD
+/* Define to the flags needed for the .section .eh_frame directive. */
+#undef EH_FRAME_FLAGS
+
/* Define to 1 if you have the `accept4' function. */
#undef HAVE_ACCEPT4
@@ -12,6 +15,15 @@
/* Define to 1 if you have the `asinl' function. */
#undef HAVE_ASINL
+/* Define if your assembler supports GNU comdat group syntax. */
+#undef HAVE_AS_COMDAT_GAS
+
+/* Define if your assembler supports unwind section type. */
+#undef HAVE_AS_X86_64_UNWIND_SECTION_TYPE
+
+/* Define if your assembler supports PC relative relocs. */
+#undef HAVE_AS_X86_PCREL
+
/* Define to 1 if you have the `atan2l' function. */
#undef HAVE_ATAN2L
@@ -27,6 +39,9 @@
/* Define to 1 if you have the `dl_iterate_phdr' function. */
#undef HAVE_DL_ITERATE_PHDR
+/* Define to 1 if you have the `dup3' function. */
+#undef HAVE_DUP3
+
/* Define to 1 if you have the `epoll_create1' function. */
#undef HAVE_EPOLL_CREATE1
@@ -54,6 +69,9 @@
/* Define if _Unwind_GetIPInfo is available. */
#undef HAVE_GETIPINFO
+/* Define to 1 if you have the `getxattr' function. */
+#undef HAVE_GETXATTR
+
/* Define to 1 if you have the `inotify_add_watch' function. */
#undef HAVE_INOTIFY_ADD_WATCH
@@ -99,6 +117,9 @@
/* Define to 1 if you have the <linux/rtnetlink.h> header file. */
#undef HAVE_LINUX_RTNETLINK_H
+/* Define to 1 if you have the `listxattr' function. */
+#undef HAVE_LISTXATTR
+
/* Define to 1 if the system has the type `loff_t'. */
#undef HAVE_LOFF_T
@@ -126,6 +147,9 @@
/* Define to 1 if you have the `mknodat' function. */
#undef HAVE_MKNODAT
+/* Define to 1 if you have the <netinet/icmp6.h> header file. */
+#undef HAVE_NETINET_ICMP6_H
+
/* Define to 1 if you have the <netinet/if_ether.h> header file. */
#undef HAVE_NETINET_IF_ETHER_H
@@ -159,6 +183,9 @@
/* Define to 1 if you have the `pipe2' function. */
#undef HAVE_PIPE2
+/* Define to 1 if you have the `removexattr' function. */
+#undef HAVE_REMOVEXATTR
+
/* Define to 1 if you have the `renameat' function. */
#undef HAVE_RENAMEAT
@@ -168,6 +195,9 @@
/* Define to 1 if you have the `setenv' function. */
#undef HAVE_SETENV
+/* Define to 1 if you have the `setxattr' function. */
+#undef HAVE_SETXATTR
+
/* Define to 1 if you have the `sinl' function. */
#undef HAVE_SINL
diff --git a/libgo/configure b/libgo/configure
index a1e045cb625..d2ad366bbf0 100755
--- a/libgo/configure
+++ b/libgo/configure
@@ -659,6 +659,8 @@ LIBGO_IS_SOLARIS_FALSE
LIBGO_IS_SOLARIS_TRUE
LIBGO_IS_RTEMS_FALSE
LIBGO_IS_RTEMS_TRUE
+LIBGO_IS_DRAGONFLY_FALSE
+LIBGO_IS_DRAGONFLY_TRUE
LIBGO_IS_OPENBSD_FALSE
LIBGO_IS_OPENBSD_TRUE
LIBGO_IS_NETBSD_FALSE
@@ -11111,7 +11113,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11114 "configure"
+#line 11116 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -11217,7 +11219,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11220 "configure"
+#line 11222 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -13490,6 +13492,7 @@ is_irix=no
is_linux=no
is_netbsd=no
is_openbsd=no
+is_dragonfly=no
is_rtems=no
is_solaris=no
GOOS=unknown
@@ -13500,6 +13503,7 @@ case ${host} in
*-*-linux*) is_linux=yes; GOOS=linux ;;
*-*-netbsd*) is_netbsd=yes; GOOS=netbsd ;;
*-*-openbsd*) is_openbsd=yes; GOOS=openbsd ;;
+ *-*-dragonfly*) is_dragonfly=yes; GOOS=dragonfly ;;
*-*-rtems*) is_rtems=yes; GOOS=rtems ;;
*-*-solaris2*) is_solaris=yes; GOOS=solaris ;;
esac
@@ -13551,6 +13555,14 @@ else
LIBGO_IS_OPENBSD_FALSE=
fi
+ if test $is_dragonly = yes; then
+ LIBGO_IS_DRAGONFLY_TRUE=
+ LIBGO_IS_DRAGONFLY_FALSE='#'
+else
+ LIBGO_IS_DRAGONFLY_TRUE='#'
+ LIBGO_IS_DRAGONFLY_FALSE=
+fi
+
if test $is_rtems = yes; then
LIBGO_IS_RTEMS_TRUE=
LIBGO_IS_RTEMS_FALSE='#'
@@ -14600,7 +14612,7 @@ no)
;;
esac
-for ac_header in sys/file.h sys/mman.h syscall.h sys/epoll.h sys/inotify.h sys/ptrace.h sys/syscall.h sys/user.h sys/utsname.h sys/select.h sys/socket.h net/if.h net/if_arp.h net/route.h netpacket/packet.h sys/prctl.h sys/mount.h sys/vfs.h sys/statfs.h sys/timex.h sys/sysinfo.h utime.h linux/ether.h linux/fs.h linux/reboot.h netinet/in_syst.h netinet/ip.h netinet/ip_mroute.h netinet/if_ether.h
+for ac_header in sys/file.h sys/mman.h syscall.h sys/epoll.h sys/inotify.h sys/ptrace.h sys/syscall.h sys/user.h sys/utsname.h sys/select.h sys/socket.h net/if.h net/if_arp.h net/route.h netpacket/packet.h sys/prctl.h sys/mount.h sys/vfs.h sys/statfs.h sys/timex.h sys/sysinfo.h utime.h linux/ether.h linux/fs.h linux/reboot.h netinet/icmp6.h netinet/in_syst.h netinet/ip.h netinet/ip_mroute.h netinet/if_ether.h
do :
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
@@ -14706,7 +14718,7 @@ else
fi
-for ac_func in accept4 epoll_create1 faccessat fallocate fchmodat fchownat futimesat inotify_add_watch inotify_init inotify_init1 inotify_rm_watch mkdirat mknodat openat pipe2 renameat sync_file_range splice tee unlinkat unshare utimensat
+for ac_func in accept4 dup3 epoll_create1 faccessat fallocate fchmodat fchownat futimesat getxattr inotify_add_watch inotify_init inotify_init1 inotify_rm_watch listxattr mkdirat mknodat openat pipe2 removexattr renameat setxattr sync_file_range splice tee unlinkat unshare utimensat
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
@@ -15179,6 +15191,101 @@ $as_echo "#define SETCONTEXT_CLOBBERS_TLS 1" >>confdefs.h
fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether .eh_frame section should be read-only" >&5
+$as_echo_n "checking whether .eh_frame section should be read-only... " >&6; }
+if test "${libgo_cv_ro_eh_frame+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+
+libgo_cv_ro_eh_frame=no
+echo 'extern void foo (void); void bar (void) { foo (); foo (); }' > conftest.c
+if $CC $CFLAGS -S -fpic -fexceptions -o conftest.s conftest.c > /dev/null 2>&1; then
+ if grep '.section.*eh_frame.*"a"' conftest.s > /dev/null; then
+ libgo_cv_ro_eh_frame=yes
+ elif grep '.section.*eh_frame.*#alloc' conftest.c \
+ | grep -v '#write' > /dev/null; then
+ libgo_cv_ro_eh_frame=yes
+ fi
+fi
+rm -f conftest.*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgo_cv_ro_eh_frame" >&5
+$as_echo "$libgo_cv_ro_eh_frame" >&6; }
+if test "x$libgo_cv_ro_eh_frame" = xyes; then
+
+$as_echo "#define EH_FRAME_FLAGS \"a\"" >>confdefs.h
+
+else
+
+$as_echo "#define EH_FRAME_FLAGS \"aw\"" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if assembler supports GNU comdat group syntax" >&5
+$as_echo_n "checking if assembler supports GNU comdat group syntax... " >&6; }
+if test "${libgo_cv_as_comdat_gnu+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+
+echo '.section .text,"axG",@progbits,.foo,comdat' > conftest.s
+if $CC $CFLAGS -c conftest.s > /dev/null 2>&1; then
+ libgo_cv_as_comdat_gnu=yes
+else
+ libgo_cv_as_comdat_gnu=no
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgo_cv_as_comdat_gnu" >&5
+$as_echo "$libgo_cv_as_comdat_gnu" >&6; }
+if test "x$libgo_cv_as_comdat_gnu" = xyes; then
+
+$as_echo "#define HAVE_AS_COMDAT_GAS 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler supports pc related relocs" >&5
+$as_echo_n "checking assembler supports pc related relocs... " >&6; }
+if test "${libgo_cv_as_x86_pcrel+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+
+libgo_cv_as_x86_pcrel=yes
+echo '.text; foo: nop; .data; .long foo-.; .text' > conftest.s
+if $CC $CFLAGS -c conftest.s 2>&1 | $EGREP -i 'illegal|warning' > /dev/null; then
+ libgo_cv_as_x86_pcrel=no
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgo_cv_as_x86_pcrel" >&5
+$as_echo "$libgo_cv_as_x86_pcrel" >&6; }
+if test "x$libgo_cv_as_x86_pcrel" = xyes; then
+
+$as_echo "#define HAVE_AS_X86_PCREL 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler supports unwind section type" >&5
+$as_echo_n "checking assembler supports unwind section type... " >&6; }
+if test "${libgo_cv_as_x86_64_unwind_section_type+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+
+libgo_cv_as_x86_64_unwind_section_type=yes
+echo '.section .eh_frame,"a",@unwind' > conftest.s
+if $CC $CFLAGS -c conftest.s 2>&1 | grep -i warning > /dev/null; then
+ libgo_cv_as_x86_64_unwind_section_type=no
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgo_cv_as_x86_64_unwind_section_type" >&5
+$as_echo "$libgo_cv_as_x86_64_unwind_section_type" >&6; }
+if test "x$libgo_cv_as_x86_64_unwind_section_type" = xyes; then
+
+$as_echo "#define HAVE_AS_X86_64_UNWIND_SECTION_TYPE 1" >>confdefs.h
+
+fi
+
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
@@ -15407,6 +15514,10 @@ if test -z "${LIBGO_IS_OPENBSD_TRUE}" && test -z "${LIBGO_IS_OPENBSD_FALSE}"; th
as_fn_error "conditional \"LIBGO_IS_OPENBSD\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
+if test -z "${LIBGO_IS_DRAGONFLY_TRUE}" && test -z "${LIBGO_IS_DRAGONFLY_FALSE}"; then
+ as_fn_error "conditional \"LIBGO_IS_DRAGONFLY\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
if test -z "${LIBGO_IS_RTEMS_TRUE}" && test -z "${LIBGO_IS_RTEMS_FALSE}"; then
as_fn_error "conditional \"LIBGO_IS_RTEMS\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
diff --git a/libgo/configure.ac b/libgo/configure.ac
index 002aa88675c..1e84dc7c380 100644
--- a/libgo/configure.ac
+++ b/libgo/configure.ac
@@ -133,6 +133,7 @@ is_irix=no
is_linux=no
is_netbsd=no
is_openbsd=no
+is_dragonfly=no
is_rtems=no
is_solaris=no
GOOS=unknown
@@ -143,6 +144,7 @@ case ${host} in
*-*-linux*) is_linux=yes; GOOS=linux ;;
*-*-netbsd*) is_netbsd=yes; GOOS=netbsd ;;
*-*-openbsd*) is_openbsd=yes; GOOS=openbsd ;;
+ *-*-dragonfly*) is_dragonfly=yes; GOOS=dragonfly ;;
*-*-rtems*) is_rtems=yes; GOOS=rtems ;;
*-*-solaris2*) is_solaris=yes; GOOS=solaris ;;
esac
@@ -152,6 +154,7 @@ AM_CONDITIONAL(LIBGO_IS_IRIX, test $is_irix = yes)
AM_CONDITIONAL(LIBGO_IS_LINUX, test $is_linux = yes)
AM_CONDITIONAL(LIBGO_IS_NETBSD, test $is_netbsd = yes)
AM_CONDITIONAL(LIBGO_IS_OPENBSD, test $is_openbsd = yes)
+AM_CONDITIONAL(LIBGO_IS_DRAGONFLY, test $is_dragonly = yes)
AM_CONDITIONAL(LIBGO_IS_RTEMS, test $is_rtems = yes)
AM_CONDITIONAL(LIBGO_IS_SOLARIS, test $is_solaris = yes)
AC_SUBST(GOOS)
@@ -471,7 +474,7 @@ no)
;;
esac
-AC_CHECK_HEADERS(sys/file.h sys/mman.h syscall.h sys/epoll.h sys/inotify.h sys/ptrace.h sys/syscall.h sys/user.h sys/utsname.h sys/select.h sys/socket.h net/if.h net/if_arp.h net/route.h netpacket/packet.h sys/prctl.h sys/mount.h sys/vfs.h sys/statfs.h sys/timex.h sys/sysinfo.h utime.h linux/ether.h linux/fs.h linux/reboot.h netinet/in_syst.h netinet/ip.h netinet/ip_mroute.h netinet/if_ether.h)
+AC_CHECK_HEADERS(sys/file.h sys/mman.h syscall.h sys/epoll.h sys/inotify.h sys/ptrace.h sys/syscall.h sys/user.h sys/utsname.h sys/select.h sys/socket.h net/if.h net/if_arp.h net/route.h netpacket/packet.h sys/prctl.h sys/mount.h sys/vfs.h sys/statfs.h sys/timex.h sys/sysinfo.h utime.h linux/ether.h linux/fs.h linux/reboot.h netinet/icmp6.h netinet/in_syst.h netinet/ip.h netinet/ip_mroute.h netinet/if_ether.h)
AC_CHECK_HEADERS([linux/filter.h linux/if_addr.h linux/if_ether.h linux/if_tun.h linux/netlink.h linux/rtnetlink.h], [], [],
[#ifdef HAVE_SYS_SOCKET_H
@@ -503,7 +506,7 @@ AC_CHECK_FUNCS(strerror_r strsignal wait4 mincore setenv dl_iterate_phdr)
AM_CONDITIONAL(HAVE_STRERROR_R, test "$ac_cv_func_strerror_r" = yes)
AM_CONDITIONAL(HAVE_WAIT4, test "$ac_cv_func_wait4" = yes)
-AC_CHECK_FUNCS(accept4 epoll_create1 faccessat fallocate fchmodat fchownat futimesat inotify_add_watch inotify_init inotify_init1 inotify_rm_watch mkdirat mknodat openat pipe2 renameat sync_file_range splice tee unlinkat unshare utimensat)
+AC_CHECK_FUNCS(accept4 dup3 epoll_create1 faccessat fallocate fchmodat fchownat futimesat getxattr inotify_add_watch inotify_init inotify_init1 inotify_rm_watch listxattr mkdirat mknodat openat pipe2 removexattr renameat setxattr sync_file_range splice tee unlinkat unshare utimensat)
AC_TYPE_OFF_T
AC_CHECK_TYPES([loff_t])
@@ -757,6 +760,68 @@ if test "$libgo_cv_lib_setcontext_clobbers_tls" = "yes"; then
[Define if setcontext clobbers TLS variables])
fi
+AC_CACHE_CHECK([whether .eh_frame section should be read-only],
+libgo_cv_ro_eh_frame, [
+libgo_cv_ro_eh_frame=no
+echo 'extern void foo (void); void bar (void) { foo (); foo (); }' > conftest.c
+if $CC $CFLAGS -S -fpic -fexceptions -o conftest.s conftest.c > /dev/null 2>&1; then
+ if grep '.section.*eh_frame.*"a"' conftest.s > /dev/null; then
+ libgo_cv_ro_eh_frame=yes
+ elif grep '.section.*eh_frame.*#alloc' conftest.c \
+ | grep -v '#write' > /dev/null; then
+ libgo_cv_ro_eh_frame=yes
+ fi
+fi
+rm -f conftest.*
+])
+if test "x$libgo_cv_ro_eh_frame" = xyes; then
+ AC_DEFINE(EH_FRAME_FLAGS, "a",
+ [Define to the flags needed for the .section .eh_frame directive.])
+else
+ AC_DEFINE(EH_FRAME_FLAGS, "aw",
+ [Define to the flags needed for the .section .eh_frame directive.])
+fi
+
+AC_CACHE_CHECK([if assembler supports GNU comdat group syntax],
+libgo_cv_as_comdat_gnu, [
+echo '.section .text,"axG",@progbits,.foo,comdat' > conftest.s
+if $CC $CFLAGS -c conftest.s > /dev/null 2>&1; then
+ libgo_cv_as_comdat_gnu=yes
+else
+ libgo_cv_as_comdat_gnu=no
+fi
+])
+if test "x$libgo_cv_as_comdat_gnu" = xyes; then
+ AC_DEFINE(HAVE_AS_COMDAT_GAS, 1,
+ [Define if your assembler supports GNU comdat group syntax.])
+fi
+
+AC_CACHE_CHECK([assembler supports pc related relocs],
+libgo_cv_as_x86_pcrel, [
+libgo_cv_as_x86_pcrel=yes
+echo '.text; foo: nop; .data; .long foo-.; .text' > conftest.s
+if $CC $CFLAGS -c conftest.s 2>&1 | $EGREP -i 'illegal|warning' > /dev/null; then
+ libgo_cv_as_x86_pcrel=no
+fi
+])
+if test "x$libgo_cv_as_x86_pcrel" = xyes; then
+ AC_DEFINE(HAVE_AS_X86_PCREL, 1,
+ [Define if your assembler supports PC relative relocs.])
+fi
+
+AC_CACHE_CHECK([assembler supports unwind section type],
+libgo_cv_as_x86_64_unwind_section_type, [
+libgo_cv_as_x86_64_unwind_section_type=yes
+echo '.section .eh_frame,"a",@unwind' > conftest.s
+if $CC $CFLAGS -c conftest.s 2>&1 | grep -i warning > /dev/null; then
+ libgo_cv_as_x86_64_unwind_section_type=no
+fi
+])
+if test "x$libgo_cv_as_x86_64_unwind_section_type" = xyes; then
+ AC_DEFINE(HAVE_AS_X86_64_UNWIND_SECTION_TYPE, 1,
+ [Define if your assembler supports unwind section type.])
+fi
+
AC_CACHE_SAVE
if test ${multilib} = yes; then
diff --git a/libgo/go/archive/tar/common.go b/libgo/go/archive/tar/common.go
index 60d207c4897..1b961e3ec63 100644
--- a/libgo/go/archive/tar/common.go
+++ b/libgo/go/archive/tar/common.go
@@ -13,6 +13,7 @@
package tar
import (
+ "bytes"
"errors"
"fmt"
"os"
@@ -82,9 +83,9 @@ func (fi headerFileInfo) Sys() interface{} { return fi.h }
// Name returns the base name of the file.
func (fi headerFileInfo) Name() string {
if fi.IsDir() {
- return path.Clean(fi.h.Name)
+ return path.Base(path.Clean(fi.h.Name))
}
- return fi.h.Name
+ return path.Base(fi.h.Name)
}
// Mode returns the permission and mode bits for the headerFileInfo.
@@ -174,9 +175,29 @@ const (
c_ISSOCK = 0140000 // Socket
)
+// Keywords for the PAX Extended Header
+const (
+ paxAtime = "atime"
+ paxCharset = "charset"
+ paxComment = "comment"
+ paxCtime = "ctime" // please note that ctime is not a valid pax header.
+ paxGid = "gid"
+ paxGname = "gname"
+ paxLinkpath = "linkpath"
+ paxMtime = "mtime"
+ paxPath = "path"
+ paxSize = "size"
+ paxUid = "uid"
+ paxUname = "uname"
+ paxNone = ""
+)
+
// FileInfoHeader creates a partially-populated Header from fi.
// If fi describes a symlink, FileInfoHeader records link as the link target.
// If fi describes a directory, a slash is appended to the name.
+// Because os.FileInfo's Name method returns only the base name of
+// the file it describes, it may be necessary to modify the Name field
+// of the returned header to provide the full path name of the file.
func FileInfoHeader(fi os.FileInfo, link string) (*Header, error) {
if fi == nil {
return nil, errors.New("tar: FileInfo is nil")
@@ -257,3 +278,25 @@ func (sp *slicer) next(n int) (b []byte) {
b, *sp = s[0:n], s[n:]
return
}
+
+func isASCII(s string) bool {
+ for _, c := range s {
+ if c >= 0x80 {
+ return false
+ }
+ }
+ return true
+}
+
+func toASCII(s string) string {
+ if isASCII(s) {
+ return s
+ }
+ var buf bytes.Buffer
+ for _, c := range s {
+ if c < 0x80 {
+ buf.WriteByte(byte(c))
+ }
+ }
+ return buf.String()
+}
diff --git a/libgo/go/archive/tar/reader.go b/libgo/go/archive/tar/reader.go
index 05f82a40dd9..b2d62f3c51c 100644
--- a/libgo/go/archive/tar/reader.go
+++ b/libgo/go/archive/tar/reader.go
@@ -95,45 +95,45 @@ func (tr *Reader) Next() (*Header, error) {
func mergePAX(hdr *Header, headers map[string]string) error {
for k, v := range headers {
switch k {
- case "path":
+ case paxPath:
hdr.Name = v
- case "linkpath":
+ case paxLinkpath:
hdr.Linkname = v
- case "gname":
+ case paxGname:
hdr.Gname = v
- case "uname":
+ case paxUname:
hdr.Uname = v
- case "uid":
+ case paxUid:
uid, err := strconv.ParseInt(v, 10, 0)
if err != nil {
return err
}
hdr.Uid = int(uid)
- case "gid":
+ case paxGid:
gid, err := strconv.ParseInt(v, 10, 0)
if err != nil {
return err
}
hdr.Gid = int(gid)
- case "atime":
+ case paxAtime:
t, err := parsePAXTime(v)
if err != nil {
return err
}
hdr.AccessTime = t
- case "mtime":
+ case paxMtime:
t, err := parsePAXTime(v)
if err != nil {
return err
}
hdr.ModTime = t
- case "ctime":
+ case paxCtime:
t, err := parsePAXTime(v)
if err != nil {
return err
}
hdr.ChangeTime = t
- case "size":
+ case paxSize:
size, err := strconv.ParseInt(v, 10, 0)
if err != nil {
return err
@@ -243,13 +243,15 @@ func (tr *Reader) octal(b []byte) int64 {
return x
}
- // Removing leading spaces.
- for len(b) > 0 && b[0] == ' ' {
- b = b[1:]
- }
- // Removing trailing NULs and spaces.
- for len(b) > 0 && (b[len(b)-1] == ' ' || b[len(b)-1] == '\x00') {
- b = b[0 : len(b)-1]
+ // Because unused fields are filled with NULs, we need
+ // to skip leading NULs. Fields may also be padded with
+ // spaces or NULs.
+ // So we remove leading and trailing NULs and spaces to
+ // be sure.
+ b = bytes.Trim(b, " \x00")
+
+ if len(b) == 0 {
+ return 0
}
x, err := strconv.ParseUint(cString(b), 8, 64)
if err != nil {
diff --git a/libgo/go/archive/tar/reader_test.go b/libgo/go/archive/tar/reader_test.go
index 9a196823713..12856165656 100644
--- a/libgo/go/archive/tar/reader_test.go
+++ b/libgo/go/archive/tar/reader_test.go
@@ -142,6 +142,25 @@ var untarTests = []*untarTest{
},
},
},
+ {
+ file: "testdata/nil-uid.tar", // golang.org/issue/5290
+ headers: []*Header{
+ {
+ Name: "P1050238.JPG.log",
+ Mode: 0664,
+ Uid: 0,
+ Gid: 0,
+ Size: 14,
+ ModTime: time.Unix(1365454838, 0),
+ Typeflag: TypeReg,
+ Linkname: "",
+ Uname: "eyefi",
+ Gname: "eyefi",
+ Devmajor: 0,
+ Devminor: 0,
+ },
+ },
+ },
}
func TestReader(t *testing.T) {
@@ -152,6 +171,7 @@ testLoop:
t.Errorf("test %d: Unexpected error: %v", i, err)
continue
}
+ defer f.Close()
tr := NewReader(f)
for j, header := range test.headers {
hdr, err := tr.Next()
@@ -172,7 +192,6 @@ testLoop:
if hdr != nil || err != nil {
t.Errorf("test %d: Unexpected entry or error: hdr=%v err=%v", i, hdr, err)
}
- f.Close()
}
}
diff --git a/libgo/go/archive/tar/tar_test.go b/libgo/go/archive/tar/tar_test.go
index dd6310313af..616a9cc57ee 100644
--- a/libgo/go/archive/tar/tar_test.go
+++ b/libgo/go/archive/tar/tar_test.go
@@ -8,7 +8,9 @@ import (
"bytes"
"io/ioutil"
"os"
+ "path"
"reflect"
+ "strings"
"testing"
"time"
)
@@ -249,7 +251,14 @@ func TestHeaderRoundTrip(t *testing.T) {
t.Error(err)
continue
}
- if got, want := h2.Name, g.h.Name; got != want {
+ if strings.Contains(fi.Name(), "/") {
+ t.Errorf("FileInfo of %q contains slash: %q", g.h.Name, fi.Name())
+ }
+ name := path.Base(g.h.Name)
+ if fi.IsDir() {
+ name += "/"
+ }
+ if got, want := h2.Name, name; got != want {
t.Errorf("i=%d: Name: got %v, want %v", i, got, want)
}
if got, want := h2.Size, g.h.Size; got != want {
diff --git a/libgo/go/archive/tar/testdata/nil-uid.tar b/libgo/go/archive/tar/testdata/nil-uid.tar
new file mode 100644
index 00000000000..cc9cfaa33cc
--- /dev/null
+++ b/libgo/go/archive/tar/testdata/nil-uid.tar
Binary files differ
diff --git a/libgo/go/archive/tar/writer.go b/libgo/go/archive/tar/writer.go
index d92dd06eab1..549f1464c38 100644
--- a/libgo/go/archive/tar/writer.go
+++ b/libgo/go/archive/tar/writer.go
@@ -24,6 +24,7 @@ var (
ErrFieldTooLong = errors.New("archive/tar: header field too long")
ErrWriteAfterClose = errors.New("archive/tar: write after close")
errNameTooLong = errors.New("archive/tar: name too long")
+ errInvalidHeader = errors.New("archive/tar: header field too long or contains invalid values")
)
// A Writer provides sequential writing of a tar archive in POSIX.1 format.
@@ -37,6 +38,7 @@ type Writer struct {
pad int64 // amount of padding to write after current file entry
closed bool
usedBinary bool // whether the binary numeric field extension was used
+ preferPax bool // use pax header instead of binary numeric header
}
// NewWriter creates a new Writer writing to w.
@@ -65,16 +67,23 @@ func (tw *Writer) Flush() error {
}
// Write s into b, terminating it with a NUL if there is room.
-func (tw *Writer) cString(b []byte, s string) {
+// If the value is too long for the field and allowPax is true add a paxheader record instead
+func (tw *Writer) cString(b []byte, s string, allowPax bool, paxKeyword string, paxHeaders map[string]string) {
+ needsPaxHeader := allowPax && len(s) > len(b) || !isASCII(s)
+ if needsPaxHeader {
+ paxHeaders[paxKeyword] = s
+ return
+ }
if len(s) > len(b) {
if tw.err == nil {
tw.err = ErrFieldTooLong
}
return
}
- copy(b, s)
- if len(s) < len(b) {
- b[len(s)] = 0
+ ascii := toASCII(s)
+ copy(b, ascii)
+ if len(ascii) < len(b) {
+ b[len(ascii)] = 0
}
}
@@ -85,17 +94,27 @@ func (tw *Writer) octal(b []byte, x int64) {
for len(s)+1 < len(b) {
s = "0" + s
}
- tw.cString(b, s)
+ tw.cString(b, s, false, paxNone, nil)
}
// Write x into b, either as octal or as binary (GNUtar/star extension).
-func (tw *Writer) numeric(b []byte, x int64) {
+// If the value is too long for the field and writingPax is enabled both for the field and the add a paxheader record instead
+func (tw *Writer) numeric(b []byte, x int64, allowPax bool, paxKeyword string, paxHeaders map[string]string) {
// Try octal first.
s := strconv.FormatInt(x, 8)
if len(s) < len(b) {
tw.octal(b, x)
return
}
+
+ // If it is too long for octal, and pax is preferred, use a pax header
+ if allowPax && tw.preferPax {
+ tw.octal(b, 0)
+ s := strconv.FormatInt(x, 10)
+ paxHeaders[paxKeyword] = s
+ return
+ }
+
// Too big: use binary (big-endian).
tw.usedBinary = true
for i := len(b) - 1; x > 0 && i >= 0; i-- {
@@ -115,6 +134,15 @@ var (
// WriteHeader calls Flush if it is not the first header.
// Calling after a Close will return ErrWriteAfterClose.
func (tw *Writer) WriteHeader(hdr *Header) error {
+ return tw.writeHeader(hdr, true)
+}
+
+// WriteHeader writes hdr and prepares to accept the file's contents.
+// WriteHeader calls Flush if it is not the first header.
+// Calling after a Close will return ErrWriteAfterClose.
+// As this method is called internally by writePax header to allow it to
+// suppress writing the pax header.
+func (tw *Writer) writeHeader(hdr *Header, allowPax bool) error {
if tw.closed {
return ErrWriteAfterClose
}
@@ -124,31 +152,21 @@ func (tw *Writer) WriteHeader(hdr *Header) error {
if tw.err != nil {
return tw.err
}
- // Decide whether or not to use PAX extensions
+
+ // a map to hold pax header records, if any are needed
+ paxHeaders := make(map[string]string)
+
// TODO(shanemhansen): we might want to use PAX headers for
// subsecond time resolution, but for now let's just capture
- // the long name/long symlink use case.
- suffix := hdr.Name
- prefix := ""
- if len(hdr.Name) > fileNameSize || len(hdr.Linkname) > fileNameSize {
- var err error
- prefix, suffix, err = tw.splitUSTARLongName(hdr.Name)
- // Either we were unable to pack the long name into ustar format
- // or the link name is too long; use PAX headers.
- if err == errNameTooLong || len(hdr.Linkname) > fileNameSize {
- if err := tw.writePAXHeader(hdr); err != nil {
- return err
- }
- } else if err != nil {
- return err
- }
- }
- tw.nb = int64(hdr.Size)
- tw.pad = -tw.nb & (blockSize - 1) // blockSize is a power of two
+ // too long fields or non ascii characters
header := make([]byte, blockSize)
s := slicer(header)
- tw.cString(s.next(fileNameSize), suffix)
+
+ // keep a reference to the filename to allow to overwrite it later if we detect that we can use ustar longnames instead of pax
+ pathHeaderBytes := s.next(fileNameSize)
+
+ tw.cString(pathHeaderBytes, hdr.Name, true, paxPath, paxHeaders)
// Handle out of range ModTime carefully.
var modTime int64
@@ -156,27 +174,55 @@ func (tw *Writer) WriteHeader(hdr *Header) error {
modTime = hdr.ModTime.Unix()
}
- tw.octal(s.next(8), hdr.Mode) // 100:108
- tw.numeric(s.next(8), int64(hdr.Uid)) // 108:116
- tw.numeric(s.next(8), int64(hdr.Gid)) // 116:124
- tw.numeric(s.next(12), hdr.Size) // 124:136
- tw.numeric(s.next(12), modTime) // 136:148
- s.next(8) // chksum (148:156)
- s.next(1)[0] = hdr.Typeflag // 156:157
- tw.cString(s.next(100), hdr.Linkname) // linkname (157:257)
- copy(s.next(8), []byte("ustar\x0000")) // 257:265
- tw.cString(s.next(32), hdr.Uname) // 265:297
- tw.cString(s.next(32), hdr.Gname) // 297:329
- tw.numeric(s.next(8), hdr.Devmajor) // 329:337
- tw.numeric(s.next(8), hdr.Devminor) // 337:345
- tw.cString(s.next(155), prefix) // 345:500
+ tw.octal(s.next(8), hdr.Mode) // 100:108
+ tw.numeric(s.next(8), int64(hdr.Uid), true, paxUid, paxHeaders) // 108:116
+ tw.numeric(s.next(8), int64(hdr.Gid), true, paxGid, paxHeaders) // 116:124
+ tw.numeric(s.next(12), hdr.Size, true, paxSize, paxHeaders) // 124:136
+ tw.numeric(s.next(12), modTime, false, paxNone, nil) // 136:148 --- consider using pax for finer granularity
+ s.next(8) // chksum (148:156)
+ s.next(1)[0] = hdr.Typeflag // 156:157
+
+ tw.cString(s.next(100), hdr.Linkname, true, paxLinkpath, paxHeaders)
+
+ copy(s.next(8), []byte("ustar\x0000")) // 257:265
+ tw.cString(s.next(32), hdr.Uname, true, paxUname, paxHeaders) // 265:297
+ tw.cString(s.next(32), hdr.Gname, true, paxGname, paxHeaders) // 297:329
+ tw.numeric(s.next(8), hdr.Devmajor, false, paxNone, nil) // 329:337
+ tw.numeric(s.next(8), hdr.Devminor, false, paxNone, nil) // 337:345
+
+ // keep a reference to the prefix to allow to overwrite it later if we detect that we can use ustar longnames instead of pax
+ prefixHeaderBytes := s.next(155)
+ tw.cString(prefixHeaderBytes, "", false, paxNone, nil) // 345:500 prefix
+
// Use the GNU magic instead of POSIX magic if we used any GNU extensions.
if tw.usedBinary {
copy(header[257:265], []byte("ustar \x00"))
}
- // Use the ustar magic if we used ustar long names.
- if len(prefix) > 0 {
- copy(header[257:265], []byte("ustar\000"))
+
+ _, paxPathUsed := paxHeaders[paxPath]
+ // try to use a ustar header when only the name is too long
+ if !tw.preferPax && len(paxHeaders) == 1 && paxPathUsed {
+ suffix := hdr.Name
+ prefix := ""
+ if len(hdr.Name) > fileNameSize && isASCII(hdr.Name) {
+ var err error
+ prefix, suffix, err = tw.splitUSTARLongName(hdr.Name)
+ if err == nil {
+ // ok we can use a ustar long name instead of pax, now correct the fields
+
+ // remove the path field from the pax header. this will suppress the pax header
+ delete(paxHeaders, paxPath)
+
+ // update the path fields
+ tw.cString(pathHeaderBytes, suffix, false, paxNone, nil)
+ tw.cString(prefixHeaderBytes, prefix, false, paxNone, nil)
+
+ // Use the ustar magic if we used ustar long names.
+ if len(prefix) > 0 {
+ copy(header[257:265], []byte("ustar\000"))
+ }
+ }
+ }
}
// The chksum field is terminated by a NUL and a space.
@@ -190,8 +236,18 @@ func (tw *Writer) WriteHeader(hdr *Header) error {
return tw.err
}
- _, tw.err = tw.w.Write(header)
+ if len(paxHeaders) > 0 {
+ if !allowPax {
+ return errInvalidHeader
+ }
+ if err := tw.writePAXHeader(hdr, paxHeaders); err != nil {
+ return err
+ }
+ }
+ tw.nb = int64(hdr.Size)
+ tw.pad = (blockSize - (tw.nb % blockSize)) % blockSize
+ _, tw.err = tw.w.Write(header)
return tw.err
}
@@ -207,8 +263,11 @@ func (tw *Writer) splitUSTARLongName(name string) (prefix, suffix string, err er
length--
}
i := strings.LastIndex(name[:length], "/")
- nlen := length - i - 1
- if i <= 0 || nlen > fileNameSize || nlen == 0 {
+ // nlen contains the resulting length in the name field.
+ // plen contains the resulting length in the prefix field.
+ nlen := len(name) - i - 1
+ plen := i
+ if i <= 0 || nlen > fileNameSize || nlen == 0 || plen > fileNamePrefixSize {
err = errNameTooLong
return
}
@@ -218,7 +277,7 @@ func (tw *Writer) splitUSTARLongName(name string) (prefix, suffix string, err er
// writePaxHeader writes an extended pax header to the
// archive.
-func (tw *Writer) writePAXHeader(hdr *Header) error {
+func (tw *Writer) writePAXHeader(hdr *Header, paxHeaders map[string]string) error {
// Prepare extended header
ext := new(Header)
ext.Typeflag = TypeXHeader
@@ -229,18 +288,23 @@ func (tw *Writer) writePAXHeader(hdr *Header) error {
// with the current pid.
pid := os.Getpid()
dir, file := path.Split(hdr.Name)
- ext.Name = path.Join(dir,
- fmt.Sprintf("PaxHeaders.%d", pid), file)[0:100]
+ fullName := path.Join(dir,
+ fmt.Sprintf("PaxHeaders.%d", pid), file)
+
+ ascii := toASCII(fullName)
+ if len(ascii) > 100 {
+ ascii = ascii[:100]
+ }
+ ext.Name = ascii
// Construct the body
var buf bytes.Buffer
- if len(hdr.Name) > fileNameSize {
- fmt.Fprint(&buf, paxHeader("path="+hdr.Name))
- }
- if len(hdr.Linkname) > fileNameSize {
- fmt.Fprint(&buf, paxHeader("linkpath="+hdr.Linkname))
+
+ for k, v := range paxHeaders {
+ fmt.Fprint(&buf, paxHeader(k+"="+v))
}
+
ext.Size = int64(len(buf.Bytes()))
- if err := tw.WriteHeader(ext); err != nil {
+ if err := tw.writeHeader(ext, false); err != nil {
return err
}
if _, err := tw.Write(buf.Bytes()); err != nil {
diff --git a/libgo/go/archive/tar/writer_test.go b/libgo/go/archive/tar/writer_test.go
index 4cf7c72aff3..30ebf977acf 100644
--- a/libgo/go/archive/tar/writer_test.go
+++ b/libgo/go/archive/tar/writer_test.go
@@ -243,15 +243,110 @@ func TestPax(t *testing.T) {
}
}
+func TestPaxSymlink(t *testing.T) {
+ // Create an archive with a large linkname
+ fileinfo, err := os.Stat("testdata/small.txt")
+ if err != nil {
+ t.Fatal(err)
+ }
+ hdr, err := FileInfoHeader(fileinfo, "")
+ hdr.Typeflag = TypeSymlink
+ if err != nil {
+ t.Fatalf("os.Stat:1 %v", err)
+ }
+ // Force a PAX long linkname to be written
+ longLinkname := strings.Repeat("1234567890/1234567890", 10)
+ hdr.Linkname = longLinkname
+
+ hdr.Size = 0
+ var buf bytes.Buffer
+ writer := NewWriter(&buf)
+ if err := writer.WriteHeader(hdr); err != nil {
+ t.Fatal(err)
+ }
+ if err := writer.Close(); err != nil {
+ t.Fatal(err)
+ }
+ // Simple test to make sure PAX extensions are in effect
+ if !bytes.Contains(buf.Bytes(), []byte("PaxHeaders.")) {
+ t.Fatal("Expected at least one PAX header to be written.")
+ }
+ // Test that we can get a long name back out of the archive.
+ reader := NewReader(&buf)
+ hdr, err = reader.Next()
+ if err != nil {
+ t.Fatal(err)
+ }
+ if hdr.Linkname != longLinkname {
+ t.Fatal("Couldn't recover long link name")
+ }
+}
+
+func TestPaxNonAscii(t *testing.T) {
+ // Create an archive with non ascii. These should trigger a pax header
+ // because pax headers have a defined utf-8 encoding.
+ fileinfo, err := os.Stat("testdata/small.txt")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ hdr, err := FileInfoHeader(fileinfo, "")
+ if err != nil {
+ t.Fatalf("os.Stat:1 %v", err)
+ }
+
+ // some sample data
+ chineseFilename := "文件å"
+ chineseGroupname := "組"
+ chineseUsername := "用戶å"
+
+ hdr.Name = chineseFilename
+ hdr.Gname = chineseGroupname
+ hdr.Uname = chineseUsername
+
+ contents := strings.Repeat(" ", int(hdr.Size))
+
+ var buf bytes.Buffer
+ writer := NewWriter(&buf)
+ if err := writer.WriteHeader(hdr); err != nil {
+ t.Fatal(err)
+ }
+ if _, err = writer.Write([]byte(contents)); err != nil {
+ t.Fatal(err)
+ }
+ if err := writer.Close(); err != nil {
+ t.Fatal(err)
+ }
+ // Simple test to make sure PAX extensions are in effect
+ if !bytes.Contains(buf.Bytes(), []byte("PaxHeaders.")) {
+ t.Fatal("Expected at least one PAX header to be written.")
+ }
+ // Test that we can get a long name back out of the archive.
+ reader := NewReader(&buf)
+ hdr, err = reader.Next()
+ if err != nil {
+ t.Fatal(err)
+ }
+ if hdr.Name != chineseFilename {
+ t.Fatal("Couldn't recover unicode name")
+ }
+ if hdr.Gname != chineseGroupname {
+ t.Fatal("Couldn't recover unicode group")
+ }
+ if hdr.Uname != chineseUsername {
+ t.Fatal("Couldn't recover unicode user")
+ }
+}
+
func TestPAXHeader(t *testing.T) {
medName := strings.Repeat("CD", 50)
longName := strings.Repeat("AB", 100)
paxTests := [][2]string{
- {"name=/etc/hosts", "19 name=/etc/hosts\n"},
+ {paxPath + "=/etc/hosts", "19 path=/etc/hosts\n"},
{"a=b", "6 a=b\n"}, // Single digit length
{"a=names", "11 a=names\n"}, // Test case involving carries
- {"name=" + longName, fmt.Sprintf("210 name=%s\n", longName)},
- {"name=" + medName, fmt.Sprintf("110 name=%s\n", medName)}}
+ {paxPath + "=" + longName, fmt.Sprintf("210 path=%s\n", longName)},
+ {paxPath + "=" + medName, fmt.Sprintf("110 path=%s\n", medName)}}
for _, test := range paxTests {
key, expected := test[0], test[1]
@@ -260,3 +355,39 @@ func TestPAXHeader(t *testing.T) {
}
}
}
+
+func TestUSTARLongName(t *testing.T) {
+ // Create an archive with a path that failed to split with USTAR extension in previous versions.
+ fileinfo, err := os.Stat("testdata/small.txt")
+ if err != nil {
+ t.Fatal(err)
+ }
+ hdr, err := FileInfoHeader(fileinfo, "")
+ hdr.Typeflag = TypeDir
+ if err != nil {
+ t.Fatalf("os.Stat:1 %v", err)
+ }
+ // Force a PAX long name to be written. The name was taken from a practical example
+ // that fails and replaced ever char through numbers to anonymize the sample.
+ longName := "/0000_0000000/00000-000000000/0000_0000000/00000-0000000000000/0000_0000000/00000-0000000-00000000/0000_0000000/00000000/0000_0000000/000/0000_0000000/00000000v00/0000_0000000/000000/0000_0000000/0000000/0000_0000000/00000y-00/0000/0000/00000000/0x000000/"
+ hdr.Name = longName
+
+ hdr.Size = 0
+ var buf bytes.Buffer
+ writer := NewWriter(&buf)
+ if err := writer.WriteHeader(hdr); err != nil {
+ t.Fatal(err)
+ }
+ if err := writer.Close(); err != nil {
+ t.Fatal(err)
+ }
+ // Test that we can get a long name back out of the archive.
+ reader := NewReader(&buf)
+ hdr, err = reader.Next()
+ if err != nil {
+ t.Fatal(err)
+ }
+ if hdr.Name != longName {
+ t.Fatal("Couldn't recover long name")
+ }
+}
diff --git a/libgo/go/archive/zip/reader.go b/libgo/go/archive/zip/reader.go
index f19cf2d1f1e..116737337fb 100644
--- a/libgo/go/archive/zip/reader.go
+++ b/libgo/go/archive/zip/reader.go
@@ -6,13 +6,11 @@ package zip
import (
"bufio"
- "compress/flate"
"encoding/binary"
"errors"
"hash"
"hash/crc32"
"io"
- "io/ioutil"
"os"
)
@@ -116,6 +114,19 @@ func (rc *ReadCloser) Close() error {
return rc.f.Close()
}
+// DataOffset returns the offset of the file's possibly-compressed
+// data, relative to the beginning of the zip file.
+//
+// Most callers should instead use Open, which transparently
+// decompresses data and verifies checksums.
+func (f *File) DataOffset() (offset int64, err error) {
+ bodyOffset, err := f.findBodyOffset()
+ if err != nil {
+ return
+ }
+ return f.headerOffset + bodyOffset, nil
+}
+
// Open returns a ReadCloser that provides access to the File's contents.
// Multiple files may be read concurrently.
func (f *File) Open() (rc io.ReadCloser, err error) {
@@ -125,15 +136,12 @@ func (f *File) Open() (rc io.ReadCloser, err error) {
}
size := int64(f.CompressedSize64)
r := io.NewSectionReader(f.zipr, f.headerOffset+bodyOffset, size)
- switch f.Method {
- case Store: // (no compression)
- rc = ioutil.NopCloser(r)
- case Deflate:
- rc = flate.NewReader(r)
- default:
+ dcomp := decompressor(f.Method)
+ if dcomp == nil {
err = ErrAlgorithm
return
}
+ rc = dcomp(r)
var desr io.Reader
if f.hasDataDescriptor() {
desr = io.NewSectionReader(f.zipr, f.headerOffset+bodyOffset+size, dataDescriptorLen)
@@ -184,9 +192,8 @@ func (r *checksumReader) Close() error { return r.rc.Close() }
// findBodyOffset does the minimum work to verify the file has a header
// and returns the file body offset.
func (f *File) findBodyOffset() (int64, error) {
- r := io.NewSectionReader(f.zipr, f.headerOffset, f.zipsize-f.headerOffset)
var buf [fileHeaderLen]byte
- if _, err := io.ReadFull(r, buf[:]); err != nil {
+ if _, err := f.zipr.ReadAt(buf[:], f.headerOffset); err != nil {
return 0, err
}
b := readBuf(buf[:])
diff --git a/libgo/go/archive/zip/reader_test.go b/libgo/go/archive/zip/reader_test.go
index 833ba28ad52..78875ecbf0e 100644
--- a/libgo/go/archive/zip/reader_test.go
+++ b/libgo/go/archive/zip/reader_test.go
@@ -276,6 +276,7 @@ func readTestZip(t *testing.T, zt ZipTest) {
var rc *ReadCloser
rc, err = OpenReader(filepath.Join("testdata", zt.Name))
if err == nil {
+ defer rc.Close()
z = &rc.Reader
}
}
diff --git a/libgo/go/archive/zip/register.go b/libgo/go/archive/zip/register.go
new file mode 100644
index 00000000000..c046f081b73
--- /dev/null
+++ b/libgo/go/archive/zip/register.go
@@ -0,0 +1,71 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package zip
+
+import (
+ "compress/flate"
+ "io"
+ "io/ioutil"
+ "sync"
+)
+
+// A Compressor returns a compressing writer, writing to the
+// provided writer. On Close, any pending data should be flushed.
+type Compressor func(io.Writer) (io.WriteCloser, error)
+
+// Decompressor is a function that wraps a Reader with a decompressing Reader.
+// The decompressed ReadCloser is returned to callers who open files from
+// within the archive. These callers are responsible for closing this reader
+// when they're finished reading.
+type Decompressor func(io.Reader) io.ReadCloser
+
+var (
+ mu sync.RWMutex // guards compressor and decompressor maps
+
+ compressors = map[uint16]Compressor{
+ Store: func(w io.Writer) (io.WriteCloser, error) { return &nopCloser{w}, nil },
+ Deflate: func(w io.Writer) (io.WriteCloser, error) { return flate.NewWriter(w, 5) },
+ }
+
+ decompressors = map[uint16]Decompressor{
+ Store: ioutil.NopCloser,
+ Deflate: flate.NewReader,
+ }
+)
+
+// RegisterDecompressor allows custom decompressors for a specified method ID.
+func RegisterDecompressor(method uint16, d Decompressor) {
+ mu.Lock()
+ defer mu.Unlock()
+
+ if _, ok := decompressors[method]; ok {
+ panic("decompressor already registered")
+ }
+ decompressors[method] = d
+}
+
+// RegisterCompressor registers custom compressors for a specified method ID.
+// The common methods Store and Deflate are built in.
+func RegisterCompressor(method uint16, comp Compressor) {
+ mu.Lock()
+ defer mu.Unlock()
+
+ if _, ok := compressors[method]; ok {
+ panic("compressor already registered")
+ }
+ compressors[method] = comp
+}
+
+func compressor(method uint16) Compressor {
+ mu.RLock()
+ defer mu.RUnlock()
+ return compressors[method]
+}
+
+func decompressor(method uint16) Decompressor {
+ mu.RLock()
+ defer mu.RUnlock()
+ return decompressors[method]
+}
diff --git a/libgo/go/archive/zip/struct.go b/libgo/go/archive/zip/struct.go
index 73972d41cf0..65e5238c3b4 100644
--- a/libgo/go/archive/zip/struct.go
+++ b/libgo/go/archive/zip/struct.go
@@ -21,6 +21,7 @@ package zip
import (
"os"
+ "path"
"time"
)
@@ -99,7 +100,7 @@ type headerFileInfo struct {
fh *FileHeader
}
-func (fi headerFileInfo) Name() string { return fi.fh.Name }
+func (fi headerFileInfo) Name() string { return path.Base(fi.fh.Name) }
func (fi headerFileInfo) Size() int64 {
if fi.fh.UncompressedSize64 > 0 {
return int64(fi.fh.UncompressedSize64)
@@ -113,6 +114,9 @@ func (fi headerFileInfo) Sys() interface{} { return fi.fh }
// FileInfoHeader creates a partially-populated FileHeader from an
// os.FileInfo.
+// Because os.FileInfo's Name method returns only the base name of
+// the file it describes, it may be necessary to modify the Name field
+// of the returned header to provide the full path name of the file.
func FileInfoHeader(fi os.FileInfo) (*FileHeader, error) {
size := fi.Size()
fh := &FileHeader{
diff --git a/libgo/go/archive/zip/writer.go b/libgo/go/archive/zip/writer.go
index e9f147cea66..6c9800a78f7 100644
--- a/libgo/go/archive/zip/writer.go
+++ b/libgo/go/archive/zip/writer.go
@@ -6,7 +6,6 @@ package zip
import (
"bufio"
- "compress/flate"
"encoding/binary"
"errors"
"hash"
@@ -198,18 +197,15 @@ func (w *Writer) CreateHeader(fh *FileHeader) (io.Writer, error) {
compCount: &countWriter{w: w.cw},
crc32: crc32.NewIEEE(),
}
- switch fh.Method {
- case Store:
- fw.comp = nopCloser{fw.compCount}
- case Deflate:
- var err error
- fw.comp, err = flate.NewWriter(fw.compCount, 5)
- if err != nil {
- return nil, err
- }
- default:
+ comp := compressor(fh.Method)
+ if comp == nil {
return nil, ErrAlgorithm
}
+ var err error
+ fw.comp, err = comp(fw.compCount)
+ if err != nil {
+ return nil, err
+ }
fw.rawCount = &countWriter{w: fw.comp}
h := &header{
diff --git a/libgo/go/archive/zip/zip_test.go b/libgo/go/archive/zip/zip_test.go
index a8af206a88f..32a16a79efb 100644
--- a/libgo/go/archive/zip/zip_test.go
+++ b/libgo/go/archive/zip/zip_test.go
@@ -9,22 +9,24 @@ package zip
import (
"bytes"
"fmt"
+ "hash"
"io"
"io/ioutil"
+ "sort"
"strings"
"testing"
"time"
)
func TestOver65kFiles(t *testing.T) {
- if testing.Short() {
- t.Skip("slow test; skipping")
- }
buf := new(bytes.Buffer)
w := NewWriter(buf)
const nFiles = (1 << 16) + 42
for i := 0; i < nFiles; i++ {
- _, err := w.Create(fmt.Sprintf("%d.dat", i))
+ _, err := w.CreateHeader(&FileHeader{
+ Name: fmt.Sprintf("%d.dat", i),
+ Method: Store, // avoid Issue 6136 and Issue 6138
+ })
if err != nil {
t.Fatalf("creating file %d: %v", i, err)
}
@@ -105,29 +107,156 @@ func TestFileHeaderRoundTrip64(t *testing.T) {
testHeaderRoundTrip(fh, uint32max, fh.UncompressedSize64, t)
}
+type repeatedByte struct {
+ off int64
+ b byte
+ n int64
+}
+
+// rleBuffer is a run-length-encoded byte buffer.
+// It's an io.Writer (like a bytes.Buffer) and also an io.ReaderAt,
+// allowing random-access reads.
+type rleBuffer struct {
+ buf []repeatedByte
+}
+
+func (r *rleBuffer) Size() int64 {
+ if len(r.buf) == 0 {
+ return 0
+ }
+ last := &r.buf[len(r.buf)-1]
+ return last.off + last.n
+}
+
+func (r *rleBuffer) Write(p []byte) (n int, err error) {
+ var rp *repeatedByte
+ if len(r.buf) > 0 {
+ rp = &r.buf[len(r.buf)-1]
+ // Fast path, if p is entirely the same byte repeated.
+ if lastByte := rp.b; len(p) > 0 && p[0] == lastByte {
+ all := true
+ for _, b := range p {
+ if b != lastByte {
+ all = false
+ break
+ }
+ }
+ if all {
+ rp.n += int64(len(p))
+ return len(p), nil
+ }
+ }
+ }
+
+ for _, b := range p {
+ if rp == nil || rp.b != b {
+ r.buf = append(r.buf, repeatedByte{r.Size(), b, 1})
+ rp = &r.buf[len(r.buf)-1]
+ } else {
+ rp.n++
+ }
+ }
+ return len(p), nil
+}
+
+func (r *rleBuffer) ReadAt(p []byte, off int64) (n int, err error) {
+ if len(p) == 0 {
+ return
+ }
+ skipParts := sort.Search(len(r.buf), func(i int) bool {
+ part := &r.buf[i]
+ return part.off+part.n > off
+ })
+ parts := r.buf[skipParts:]
+ if len(parts) > 0 {
+ skipBytes := off - parts[0].off
+ for len(parts) > 0 {
+ part := parts[0]
+ for i := skipBytes; i < part.n; i++ {
+ if n == len(p) {
+ return
+ }
+ p[n] = part.b
+ n++
+ }
+ parts = parts[1:]
+ skipBytes = 0
+ }
+ }
+ if n != len(p) {
+ err = io.ErrUnexpectedEOF
+ }
+ return
+}
+
+// Just testing the rleBuffer used in the Zip64 test above. Not used by the zip code.
+func TestRLEBuffer(t *testing.T) {
+ b := new(rleBuffer)
+ var all []byte
+ writes := []string{"abcdeee", "eeeeeee", "eeeefghaaiii"}
+ for _, w := range writes {
+ b.Write([]byte(w))
+ all = append(all, w...)
+ }
+ if len(b.buf) != 10 {
+ t.Fatalf("len(b.buf) = %d; want 10", len(b.buf))
+ }
+
+ for i := 0; i < len(all); i++ {
+ for j := 0; j < len(all)-i; j++ {
+ buf := make([]byte, j)
+ n, err := b.ReadAt(buf, int64(i))
+ if err != nil || n != len(buf) {
+ t.Errorf("ReadAt(%d, %d) = %d, %v; want %d, nil", i, j, n, err, len(buf))
+ }
+ if !bytes.Equal(buf, all[i:i+j]) {
+ t.Errorf("ReadAt(%d, %d) = %q; want %q", i, j, buf, all[i:i+j])
+ }
+ }
+ }
+}
+
+// fakeHash32 is a dummy Hash32 that always returns 0.
+type fakeHash32 struct {
+ hash.Hash32
+}
+
+func (fakeHash32) Write(p []byte) (int, error) { return len(p), nil }
+func (fakeHash32) Sum32() uint32 { return 0 }
+
func TestZip64(t *testing.T) {
if testing.Short() {
t.Skip("slow test; skipping")
}
+ const size = 1 << 32 // before the "END\n" part
+ testZip64(t, size)
+}
+
+func testZip64(t testing.TB, size int64) {
+ const chunkSize = 1024
+ chunks := int(size / chunkSize)
// write 2^32 bytes plus "END\n" to a zip file
- buf := new(bytes.Buffer)
+ buf := new(rleBuffer)
w := NewWriter(buf)
- f, err := w.Create("huge.txt")
+ f, err := w.CreateHeader(&FileHeader{
+ Name: "huge.txt",
+ Method: Store,
+ })
if err != nil {
t.Fatal(err)
}
- chunk := make([]byte, 1024)
+ f.(*fileWriter).crc32 = fakeHash32{}
+ chunk := make([]byte, chunkSize)
for i := range chunk {
chunk[i] = '.'
}
- chunk[len(chunk)-1] = '\n'
- end := []byte("END\n")
- for i := 0; i < (1<<32)/1024; i++ {
+ for i := 0; i < chunks; i++ {
_, err := f.Write(chunk)
if err != nil {
t.Fatal("write chunk:", err)
}
}
+ end := []byte("END\n")
_, err = f.Write(end)
if err != nil {
t.Fatal("write end:", err)
@@ -137,7 +266,7 @@ func TestZip64(t *testing.T) {
}
// read back zip file and check that we get to the end of it
- r, err := NewReader(bytes.NewReader(buf.Bytes()), int64(buf.Len()))
+ r, err := NewReader(buf, int64(buf.Size()))
if err != nil {
t.Fatal("reader:", err)
}
@@ -146,7 +275,8 @@ func TestZip64(t *testing.T) {
if err != nil {
t.Fatal("opening:", err)
}
- for i := 0; i < (1<<32)/1024; i++ {
+ rc.(*checksumReader).hash = fakeHash32{}
+ for i := 0; i < chunks; i++ {
_, err := io.ReadFull(rc, chunk)
if err != nil {
t.Fatal("read:", err)
@@ -163,11 +293,13 @@ func TestZip64(t *testing.T) {
if err != nil {
t.Fatal("closing:", err)
}
- if got, want := f0.UncompressedSize, uint32(uint32max); got != want {
- t.Errorf("UncompressedSize %d, want %d", got, want)
+ if size == 1<<32 {
+ if got, want := f0.UncompressedSize, uint32(uint32max); got != want {
+ t.Errorf("UncompressedSize %d, want %d", got, want)
+ }
}
- if got, want := f0.UncompressedSize64, (1<<32)+uint64(len(end)); got != want {
+ if got, want := f0.UncompressedSize64, uint64(size)+uint64(len(end)); got != want {
t.Errorf("UncompressedSize64 %d, want %d", got, want)
}
}
@@ -253,3 +385,11 @@ func TestZeroLengthHeader(t *testing.T) {
}
testValidHeader(&h, t)
}
+
+// Just benchmarking how fast the Zip64 test above is. Not related to
+// our zip performance, since the test above disabled CRC32 and flate.
+func BenchmarkZip64Test(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ testZip64(b, 1<<26)
+ }
+}
diff --git a/libgo/go/bufio/bufio.go b/libgo/go/bufio/bufio.go
index df3501f2ca1..d1ff3c9edc1 100644
--- a/libgo/go/bufio/bufio.go
+++ b/libgo/go/bufio/bufio.go
@@ -51,12 +51,9 @@ func NewReaderSize(rd io.Reader, size int) *Reader {
if size < minReadBufferSize {
size = minReadBufferSize
}
- return &Reader{
- buf: make([]byte, size),
- rd: rd,
- lastByte: -1,
- lastRuneSize: -1,
- }
+ r := new(Reader)
+ r.reset(make([]byte, size), rd)
+ return r
}
// NewReader returns a new Reader whose buffer has the default size.
@@ -64,6 +61,21 @@ func NewReader(rd io.Reader) *Reader {
return NewReaderSize(rd, defaultBufSize)
}
+// Reset discards any buffered data, resets all state, and switches
+// the buffered reader to read from r.
+func (b *Reader) Reset(r io.Reader) {
+ b.reset(b.buf, r)
+}
+
+func (b *Reader) reset(buf []byte, r io.Reader) {
+ *b = Reader{
+ buf: buf,
+ rd: r,
+ lastByte: -1,
+ lastRuneSize: -1,
+ }
+}
+
var errNegativeRead = errors.New("bufio: reader returned negative count from Read")
// fill reads a new chunk into the buffer.
@@ -234,7 +246,7 @@ func (b *Reader) Buffered() int { return b.w - b.r }
// ReadSlice reads until the first occurrence of delim in the input,
// returning a slice pointing at the bytes in the buffer.
-// The bytes stop being valid at the next read call.
+// The bytes stop being valid at the next read.
// If ReadSlice encounters an error before finding a delimiter,
// it returns all the data in the buffer and the error itself (often io.EOF).
// ReadSlice fails with error ErrBufferFull if the buffer fills without a delim.
@@ -381,7 +393,8 @@ func (b *Reader) ReadBytes(delim byte) (line []byte, err error) {
// For simple uses, a Scanner may be more convenient.
func (b *Reader) ReadString(delim byte) (line string, err error) {
bytes, err := b.ReadBytes(delim)
- return string(bytes), err
+ line = string(bytes)
+ return line, err
}
// WriteTo implements io.WriterTo.
@@ -424,6 +437,9 @@ func (b *Reader) writeBuf(w io.Writer) (int64, error) {
// Writer implements buffering for an io.Writer object.
// If an error occurs writing to a Writer, no more data will be
// accepted and all subsequent writes will return the error.
+// After all data has been written, the client should call the
+// Flush method to guarantee all data has been forwarded to
+// the underlying io.Writer.
type Writer struct {
err error
buf []byte
@@ -434,28 +450,41 @@ type Writer struct {
// NewWriterSize returns a new Writer whose buffer has at least the specified
// size. If the argument io.Writer is already a Writer with large enough
// size, it returns the underlying Writer.
-func NewWriterSize(wr io.Writer, size int) *Writer {
+func NewWriterSize(w io.Writer, size int) *Writer {
// Is it already a Writer?
- b, ok := wr.(*Writer)
+ b, ok := w.(*Writer)
if ok && len(b.buf) >= size {
return b
}
if size <= 0 {
size = defaultBufSize
}
- b = new(Writer)
- b.buf = make([]byte, size)
- b.wr = wr
- return b
+ return &Writer{
+ buf: make([]byte, size),
+ wr: w,
+ }
}
// NewWriter returns a new Writer whose buffer has the default size.
-func NewWriter(wr io.Writer) *Writer {
- return NewWriterSize(wr, defaultBufSize)
+func NewWriter(w io.Writer) *Writer {
+ return NewWriterSize(w, defaultBufSize)
+}
+
+// Reset discards any unflushed buffered data, clears any error, and
+// resets b to write its output to w.
+func (b *Writer) Reset(w io.Writer) {
+ b.err = nil
+ b.n = 0
+ b.wr = w
}
// Flush writes any buffered data to the underlying io.Writer.
func (b *Writer) Flush() error {
+ err := b.flush()
+ return err
+}
+
+func (b *Writer) flush() error {
if b.err != nil {
return b.err
}
@@ -498,7 +527,7 @@ func (b *Writer) Write(p []byte) (nn int, err error) {
} else {
n = copy(b.buf[b.n:], p)
b.n += n
- b.Flush()
+ b.flush()
}
nn += n
p = p[n:]
@@ -517,7 +546,7 @@ func (b *Writer) WriteByte(c byte) error {
if b.err != nil {
return b.err
}
- if b.Available() <= 0 && b.Flush() != nil {
+ if b.Available() <= 0 && b.flush() != nil {
return b.err
}
b.buf[b.n] = c
@@ -540,7 +569,7 @@ func (b *Writer) WriteRune(r rune) (size int, err error) {
}
n := b.Available()
if n < utf8.UTFMax {
- if b.Flush(); b.err != nil {
+ if b.flush(); b.err != nil {
return 0, b.err
}
n = b.Available()
@@ -565,7 +594,7 @@ func (b *Writer) WriteString(s string) (int, error) {
b.n += n
nn += n
s = s[n:]
- b.Flush()
+ b.flush()
}
if b.err != nil {
return nn, b.err
@@ -585,23 +614,28 @@ func (b *Writer) ReadFrom(r io.Reader) (n int64, err error) {
}
var m int
for {
+ if b.Available() == 0 {
+ if err1 := b.flush(); err1 != nil {
+ return n, err1
+ }
+ }
m, err = r.Read(b.buf[b.n:])
if m == 0 {
break
}
b.n += m
n += int64(m)
- if b.Available() == 0 {
- if err1 := b.Flush(); err1 != nil {
- return n, err1
- }
- }
if err != nil {
break
}
}
if err == io.EOF {
- err = nil
+ // If we filled the buffer exactly, flush pre-emptively.
+ if b.Available() == 0 {
+ err = b.flush()
+ } else {
+ err = nil
+ }
}
return n, err
}
diff --git a/libgo/go/bufio/bufio_test.go b/libgo/go/bufio/bufio_test.go
index 79ed0f178e0..41bd3d45633 100644
--- a/libgo/go/bufio/bufio_test.go
+++ b/libgo/go/bufio/bufio_test.go
@@ -847,6 +847,10 @@ func TestWriterReadFrom(t *testing.T) {
t.Errorf("ws[%d],rs[%d]: w.ReadFrom(r) = %d, %v, want %d, nil", wi, ri, n, err, len(input))
continue
}
+ if err := w.Flush(); err != nil {
+ t.Errorf("Flush returned %v", err)
+ continue
+ }
if got, want := b.String(), string(input); got != want {
t.Errorf("ws[%d], rs[%d]:\ngot %q\nwant %q\n", wi, ri, got, want)
}
@@ -1003,6 +1007,56 @@ func TestReaderClearError(t *testing.T) {
}
}
+// Test for golang.org/issue/5947
+func TestWriterReadFromWhileFull(t *testing.T) {
+ buf := new(bytes.Buffer)
+ w := NewWriterSize(buf, 10)
+
+ // Fill buffer exactly.
+ n, err := w.Write([]byte("0123456789"))
+ if n != 10 || err != nil {
+ t.Fatalf("Write returned (%v, %v), want (10, nil)", n, err)
+ }
+
+ // Use ReadFrom to read in some data.
+ n2, err := w.ReadFrom(strings.NewReader("abcdef"))
+ if n2 != 6 || err != nil {
+ t.Fatalf("ReadFrom returned (%v, %v), want (6, nil)", n, err)
+ }
+}
+
+func TestReaderReset(t *testing.T) {
+ r := NewReader(strings.NewReader("foo foo"))
+ buf := make([]byte, 3)
+ r.Read(buf)
+ if string(buf) != "foo" {
+ t.Errorf("buf = %q; want foo", buf)
+ }
+ r.Reset(strings.NewReader("bar bar"))
+ all, err := ioutil.ReadAll(r)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if string(all) != "bar bar" {
+ t.Errorf("ReadAll = %q; want bar bar", all)
+ }
+}
+
+func TestWriterReset(t *testing.T) {
+ var buf1, buf2 bytes.Buffer
+ w := NewWriter(&buf1)
+ w.WriteString("foo")
+ w.Reset(&buf2) // and not flushed
+ w.WriteString("bar")
+ w.Flush()
+ if buf1.String() != "" {
+ t.Errorf("buf1 = %q; want empty", buf1.String())
+ }
+ if buf2.String() != "bar" {
+ t.Errorf("buf2 = %q; want bar", buf2.String())
+ }
+}
+
// An onlyReader only implements io.Reader, no matter what other methods the underlying implementation may have.
type onlyReader struct {
r io.Reader
@@ -1083,3 +1137,46 @@ func BenchmarkWriterCopyNoReadFrom(b *testing.B) {
io.Copy(dst, src)
}
}
+
+func BenchmarkReaderEmpty(b *testing.B) {
+ b.ReportAllocs()
+ str := strings.Repeat("x", 16<<10)
+ for i := 0; i < b.N; i++ {
+ br := NewReader(strings.NewReader(str))
+ n, err := io.Copy(ioutil.Discard, br)
+ if err != nil {
+ b.Fatal(err)
+ }
+ if n != int64(len(str)) {
+ b.Fatal("wrong length")
+ }
+ }
+}
+
+func BenchmarkWriterEmpty(b *testing.B) {
+ b.ReportAllocs()
+ str := strings.Repeat("x", 1<<10)
+ bs := []byte(str)
+ for i := 0; i < b.N; i++ {
+ bw := NewWriter(ioutil.Discard)
+ bw.Flush()
+ bw.WriteByte('a')
+ bw.Flush()
+ bw.WriteRune('B')
+ bw.Flush()
+ bw.Write(bs)
+ bw.Flush()
+ bw.WriteString(str)
+ bw.Flush()
+ }
+}
+
+func BenchmarkWriterFlush(b *testing.B) {
+ b.ReportAllocs()
+ bw := NewWriter(ioutil.Discard)
+ str := strings.Repeat("x", 50)
+ for i := 0; i < b.N; i++ {
+ bw.WriteString(str)
+ bw.Flush()
+ }
+}
diff --git a/libgo/go/bufio/example_test.go b/libgo/go/bufio/example_test.go
index 08a39441e66..3da91414219 100644
--- a/libgo/go/bufio/example_test.go
+++ b/libgo/go/bufio/example_test.go
@@ -12,6 +12,14 @@ import (
"strings"
)
+func ExampleWriter() {
+ w := bufio.NewWriter(os.Stdout)
+ fmt.Fprint(w, "Hello, ")
+ fmt.Fprint(w, "world!")
+ w.Flush() // Don't forget to flush!
+ // Output: Hello, world!
+}
+
// The simplest use of a Scanner, to read standard input as a set of lines.
func ExampleScanner_lines() {
scanner := bufio.NewScanner(os.Stdin)
diff --git a/libgo/go/bufio/scan.go b/libgo/go/bufio/scan.go
index 2e1a2e99973..423505fbcbb 100644
--- a/libgo/go/bufio/scan.go
+++ b/libgo/go/bufio/scan.go
@@ -44,8 +44,8 @@ type Scanner struct {
// to give. The return values are the number of bytes to advance the input
// and the next token to return to the user, plus an error, if any. If the
// data does not yet hold a complete token, for instance if it has no newline
-// while scanning lines, SplitFunc can return (0, nil) to signal the Scanner
-// to read more data into the slice and try again with a longer slice
+// while scanning lines, SplitFunc can return (0, nil, nil) to signal the
+// Scanner to read more data into the slice and try again with a longer slice
// starting at the same point in the input.
//
// If the returned error is non-nil, scanning stops and the error
@@ -287,7 +287,7 @@ func ScanLines(data []byte, atEOF bool) (advance int, token []byte, err error) {
return 0, nil, nil
}
-// isSpace returns whether the character is a Unicode white space character.
+// isSpace reports whether the character is a Unicode white space character.
// We avoid dependency on the unicode package, but check validity of the implementation
// in the tests.
func isSpace(r rune) bool {
diff --git a/libgo/go/builtin/builtin.go b/libgo/go/builtin/builtin.go
index 128a1b5f8fc..51550a459cb 100644
--- a/libgo/go/builtin/builtin.go
+++ b/libgo/go/builtin/builtin.go
@@ -236,6 +236,19 @@ func panic(v interface{})
// panicking.
func recover() interface{}
+// The print built-in function formats its arguments in an implementation-
+// specific way and writes the result to standard error.
+// Print is useful for bootstrapping and debugging; it is not guaranteed
+// to stay in the language.
+func print(args ...Type)
+
+// The println built-in function formats its arguments in an implementation-
+// specific way and writes the result to standard error.
+// Spaces are always added between arguments and a newline is appended.
+// Println is useful for bootstrapping and debugging; it is not guaranteed
+// to stay in the language.
+func println(args ...Type)
+
// The error built-in interface type is the conventional interface for
// representing an error condition, with the nil value representing no error.
type error interface {
diff --git a/libgo/go/bytes/bytes.go b/libgo/go/bytes/bytes.go
index e42f7443946..01a5d9ae4ec 100644
--- a/libgo/go/bytes/bytes.go
+++ b/libgo/go/bytes/bytes.go
@@ -11,32 +11,6 @@ import (
"unicode/utf8"
)
-// Compare returns an integer comparing two byte slices lexicographically.
-// The result will be 0 if a==b, -1 if a < b, and +1 if a > b.
-// A nil argument is equivalent to an empty slice.
-func Compare(a, b []byte) int {
- m := len(a)
- if m > len(b) {
- m = len(b)
- }
- for i, ac := range a[0:m] {
- bc := b[i]
- switch {
- case ac > bc:
- return 1
- case ac < bc:
- return -1
- }
- }
- switch {
- case len(a) < len(b):
- return -1
- case len(a) > len(b):
- return 1
- }
- return 0
-}
-
func equalPortable(a, b []byte) bool {
if len(a) != len(b) {
return false
@@ -103,7 +77,7 @@ func Count(s, sep []byte) int {
return count
}
-// Contains returns whether subslice is within b.
+// Contains reports whether subslice is within b.
func Contains(b, subslice []byte) bool {
return Index(b, subslice) != -1
}
@@ -401,10 +375,7 @@ func Repeat(b []byte, count int) []byte {
nb := make([]byte, len(b)*count)
bp := 0
for i := 0; i < count; i++ {
- for j := 0; j < len(b); j++ {
- nb[bp] = b[j]
- bp++
- }
+ bp += copy(nb[bp:], b)
}
return nb
}
diff --git a/libgo/go/bytes/bytes_decl.go b/libgo/go/bytes/bytes_decl.go
index fbf92827527..617d7489a6a 100644
--- a/libgo/go/bytes/bytes_decl.go
+++ b/libgo/go/bytes/bytes_decl.go
@@ -7,10 +7,18 @@ package bytes
//go:noescape
// IndexByte returns the index of the first instance of c in s, or -1 if c is not present in s.
-func IndexByte(s []byte, c byte) int // asm_$GOARCH.s
+func IndexByte(s []byte, c byte) int // ../runtime/asm_$GOARCH.s
//go:noescape
-// Equal returns a boolean reporting whether a == b.
+// Equal returns a boolean reporting whether a and b
+// are the same length and contain the same bytes.
// A nil argument is equivalent to an empty slice.
-func Equal(a, b []byte) bool // asm_arm.s or ../runtime/asm_{386,amd64}.s
+func Equal(a, b []byte) bool // ../runtime/asm_$GOARCH.s
+
+//go:noescape
+
+// Compare returns an integer comparing two byte slices lexicographically.
+// The result will be 0 if a==b, -1 if a < b, and +1 if a > b.
+// A nil argument is equivalent to an empty slice.
+func Compare(a, b []byte) int // ../runtime/noasm_arm.goc or ../runtime/asm_{386,amd64}.s
diff --git a/libgo/go/bytes/bytes_test.go b/libgo/go/bytes/bytes_test.go
index d296224ac42..ab5da4fbf08 100644
--- a/libgo/go/bytes/bytes_test.go
+++ b/libgo/go/bytes/bytes_test.go
@@ -47,7 +47,7 @@ type BinOpTest struct {
i int
}
-var compareTests = []struct {
+var equalTests = []struct {
a, b []byte
i int
}{
@@ -73,12 +73,8 @@ var compareTests = []struct {
{nil, []byte("a"), -1},
}
-func TestCompare(t *testing.T) {
+func TestEqual(t *testing.T) {
for _, tt := range compareTests {
- cmp := Compare(tt.a, tt.b)
- if cmp != tt.i {
- t.Errorf(`Compare(%q, %q) = %v`, tt.a, tt.b, cmp)
- }
eql := Equal(tt.a, tt.b)
if eql != (tt.i == 0) {
t.Errorf(`Equal(%q, %q) = %v`, tt.a, tt.b, eql)
@@ -90,7 +86,7 @@ func TestCompare(t *testing.T) {
}
}
-func TestEqual(t *testing.T) {
+func TestEqualExhaustive(t *testing.T) {
var size = 128
if testing.Short() {
size = 32
@@ -147,6 +143,7 @@ var indexTests = []BinOpTest{
{"", "a", -1},
{"", "foo", -1},
{"fo", "foo", -1},
+ {"foo", "baz", -1},
{"foo", "foo", 0},
{"oofofoofooo", "f", 2},
{"oofofoofooo", "foo", 4},
@@ -1086,6 +1083,24 @@ func TestTitle(t *testing.T) {
}
}
+var ToTitleTests = []TitleTest{
+ {"", ""},
+ {"a", "A"},
+ {" aaa aaa aaa ", " AAA AAA AAA "},
+ {" Aaa Aaa Aaa ", " AAA AAA AAA "},
+ {"123a456", "123A456"},
+ {"double-blind", "DOUBLE-BLIND"},
+ {"ÿøû", "ŸØÛ"},
+}
+
+func TestToTitle(t *testing.T) {
+ for _, tt := range ToTitleTests {
+ if s := string(ToTitle([]byte(tt.in))); s != tt.out {
+ t.Errorf("ToTitle(%q) = %q, want %q", tt.in, s, tt.out)
+ }
+ }
+}
+
var EqualFoldTests = []struct {
s, t string
out bool
@@ -1114,6 +1129,37 @@ func TestEqualFold(t *testing.T) {
}
}
+func TestBufferGrowNegative(t *testing.T) {
+ defer func() {
+ if err := recover(); err == nil {
+ t.Fatal("Grow(-1) should have paniced")
+ }
+ }()
+ var b Buffer
+ b.Grow(-1)
+}
+
+func TestBufferTruncateNegative(t *testing.T) {
+ defer func() {
+ if err := recover(); err == nil {
+ t.Fatal("Truncate(-1) should have paniced")
+ }
+ }()
+ var b Buffer
+ b.Truncate(-1)
+}
+
+func TestBufferTruncateOutOfRange(t *testing.T) {
+ defer func() {
+ if err := recover(); err == nil {
+ t.Fatal("Truncate(20) should have paniced")
+ }
+ }()
+ var b Buffer
+ b.Write(make([]byte, 10))
+ b.Truncate(20)
+}
+
var makeFieldsInput = func() []byte {
x := make([]byte, 1<<20)
// Input is ~10% space, ~10% 2-byte UTF-8, rest ASCII non-space.
diff --git a/libgo/go/bytes/compare_test.go b/libgo/go/bytes/compare_test.go
new file mode 100644
index 00000000000..0a36f5ad39b
--- /dev/null
+++ b/libgo/go/bytes/compare_test.go
@@ -0,0 +1,204 @@
+package bytes_test
+
+import (
+ . "bytes"
+ "testing"
+)
+
+var compareTests = []struct {
+ a, b []byte
+ i int
+}{
+ {[]byte(""), []byte(""), 0},
+ {[]byte("a"), []byte(""), 1},
+ {[]byte(""), []byte("a"), -1},
+ {[]byte("abc"), []byte("abc"), 0},
+ {[]byte("ab"), []byte("abc"), -1},
+ {[]byte("abc"), []byte("ab"), 1},
+ {[]byte("x"), []byte("ab"), 1},
+ {[]byte("ab"), []byte("x"), -1},
+ {[]byte("x"), []byte("a"), 1},
+ {[]byte("b"), []byte("x"), -1},
+ // test runtime·memeq's chunked implementation
+ {[]byte("abcdefgh"), []byte("abcdefgh"), 0},
+ {[]byte("abcdefghi"), []byte("abcdefghi"), 0},
+ {[]byte("abcdefghi"), []byte("abcdefghj"), -1},
+ // nil tests
+ {nil, nil, 0},
+ {[]byte(""), nil, 0},
+ {nil, []byte(""), 0},
+ {[]byte("a"), nil, 1},
+ {nil, []byte("a"), -1},
+}
+
+func TestCompare(t *testing.T) {
+ for _, tt := range compareTests {
+ cmp := Compare(tt.a, tt.b)
+ if cmp != tt.i {
+ t.Errorf(`Compare(%q, %q) = %v`, tt.a, tt.b, cmp)
+ }
+ }
+}
+
+func TestCompareIdenticalSlice(t *testing.T) {
+ var b = []byte("Hello Gophers!")
+ if Compare(b, b) != 0 {
+ t.Error("b != b")
+ }
+ if Compare(b, b[:1]) != 1 {
+ t.Error("b > b[:1] failed")
+ }
+}
+
+func TestCompareBytes(t *testing.T) {
+ n := 128
+ a := make([]byte, n+1)
+ b := make([]byte, n+1)
+ for len := 0; len < 128; len++ {
+ // randomish but deterministic data. No 0 or 255.
+ for i := 0; i < len; i++ {
+ a[i] = byte(1 + 31*i%254)
+ b[i] = byte(1 + 31*i%254)
+ }
+ // data past the end is different
+ for i := len; i <= n; i++ {
+ a[i] = 8
+ b[i] = 9
+ }
+ cmp := Compare(a[:len], b[:len])
+ if cmp != 0 {
+ t.Errorf(`CompareIdentical(%d) = %d`, len, cmp)
+ }
+ if len > 0 {
+ cmp = Compare(a[:len-1], b[:len])
+ if cmp != -1 {
+ t.Errorf(`CompareAshorter(%d) = %d`, len, cmp)
+ }
+ cmp = Compare(a[:len], b[:len-1])
+ if cmp != 1 {
+ t.Errorf(`CompareBshorter(%d) = %d`, len, cmp)
+ }
+ }
+ for k := 0; k < len; k++ {
+ b[k] = a[k] - 1
+ cmp = Compare(a[:len], b[:len])
+ if cmp != 1 {
+ t.Errorf(`CompareAbigger(%d,%d) = %d`, len, k, cmp)
+ }
+ b[k] = a[k] + 1
+ cmp = Compare(a[:len], b[:len])
+ if cmp != -1 {
+ t.Errorf(`CompareBbigger(%d,%d) = %d`, len, k, cmp)
+ }
+ b[k] = a[k]
+ }
+ }
+}
+
+func BenchmarkCompareBytesEqual(b *testing.B) {
+ b1 := []byte("Hello Gophers!")
+ b2 := []byte("Hello Gophers!")
+ for i := 0; i < b.N; i++ {
+ if Compare(b1, b2) != 0 {
+ b.Fatal("b1 != b2")
+ }
+ }
+}
+
+func BenchmarkCompareBytesToNil(b *testing.B) {
+ b1 := []byte("Hello Gophers!")
+ var b2 []byte
+ for i := 0; i < b.N; i++ {
+ if Compare(b1, b2) != 1 {
+ b.Fatal("b1 > b2 failed")
+ }
+ }
+}
+
+func BenchmarkCompareBytesEmpty(b *testing.B) {
+ b1 := []byte("")
+ b2 := b1
+ for i := 0; i < b.N; i++ {
+ if Compare(b1, b2) != 0 {
+ b.Fatal("b1 != b2")
+ }
+ }
+}
+
+func BenchmarkCompareBytesIdentical(b *testing.B) {
+ b1 := []byte("Hello Gophers!")
+ b2 := b1
+ for i := 0; i < b.N; i++ {
+ if Compare(b1, b2) != 0 {
+ b.Fatal("b1 != b2")
+ }
+ }
+}
+
+func BenchmarkCompareBytesSameLength(b *testing.B) {
+ b1 := []byte("Hello Gophers!")
+ b2 := []byte("Hello, Gophers")
+ for i := 0; i < b.N; i++ {
+ if Compare(b1, b2) != -1 {
+ b.Fatal("b1 < b2 failed")
+ }
+ }
+}
+
+func BenchmarkCompareBytesDifferentLength(b *testing.B) {
+ b1 := []byte("Hello Gophers!")
+ b2 := []byte("Hello, Gophers!")
+ for i := 0; i < b.N; i++ {
+ if Compare(b1, b2) != -1 {
+ b.Fatal("b1 < b2 failed")
+ }
+ }
+}
+
+func BenchmarkCompareBytesBigUnaligned(b *testing.B) {
+ b.StopTimer()
+ b1 := make([]byte, 0, 1<<20)
+ for len(b1) < 1<<20 {
+ b1 = append(b1, "Hello Gophers!"...)
+ }
+ b2 := append([]byte("hello"), b1...)
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ if Compare(b1, b2[len("hello"):]) != 0 {
+ b.Fatal("b1 != b2")
+ }
+ }
+ b.SetBytes(int64(len(b1)))
+}
+
+func BenchmarkCompareBytesBig(b *testing.B) {
+ b.StopTimer()
+ b1 := make([]byte, 0, 1<<20)
+ for len(b1) < 1<<20 {
+ b1 = append(b1, "Hello Gophers!"...)
+ }
+ b2 := append([]byte{}, b1...)
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ if Compare(b1, b2) != 0 {
+ b.Fatal("b1 != b2")
+ }
+ }
+ b.SetBytes(int64(len(b1)))
+}
+
+func BenchmarkCompareBytesBigIdentical(b *testing.B) {
+ b.StopTimer()
+ b1 := make([]byte, 0, 1<<20)
+ for len(b1) < 1<<20 {
+ b1 = append(b1, "Hello Gophers!"...)
+ }
+ b2 := b1
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ if Compare(b1, b2) != 0 {
+ b.Fatal("b1 != b2")
+ }
+ }
+ b.SetBytes(int64(len(b1)))
+}
diff --git a/libgo/go/bytes/indexbyte.c b/libgo/go/bytes/indexbyte.c
index cbc7847efe8..b248108e404 100644
--- a/libgo/go/bytes/indexbyte.c
+++ b/libgo/go/bytes/indexbyte.c
@@ -41,3 +41,33 @@ Equal (struct __go_open_array a, struct __go_open_array b)
return 0;
return __builtin_memcmp (a.__values, b.__values, a.__count) == 0;
}
+
+intgo Compare (struct __go_open_array a, struct __go_open_array b)
+ __asm__ (GOSYM_PREFIX "bytes.Compare")
+ __attribute__ ((no_split_stack));
+
+intgo
+Compare (struct __go_open_array a, struct __go_open_array b)
+{
+ intgo len;
+
+ len = a.__count;
+ if (len > b.__count)
+ len = b.__count;
+ if (len > 0)
+ {
+ intgo ret;
+
+ ret = __builtin_memcmp (a.__values, b.__values, len);
+ if (ret < 0)
+ return -1;
+ else if (ret > 0)
+ return 1;
+ }
+ if (a.__count < b.__count)
+ return -1;
+ else if (a.__count > b.__count)
+ return 1;
+ else
+ return 0;
+}
diff --git a/libgo/go/bytes/reader_test.go b/libgo/go/bytes/reader_test.go
index f0a3e26c4a7..19f014da030 100644
--- a/libgo/go/bytes/reader_test.go
+++ b/libgo/go/bytes/reader_test.go
@@ -113,6 +113,41 @@ func TestReaderWriteTo(t *testing.T) {
}
}
+func TestReaderLen(t *testing.T) {
+ const data = "hello world"
+ r := NewReader([]byte(data))
+ if got, want := r.Len(), 11; got != want {
+ t.Errorf("r.Len(): got %d, want %d", got, want)
+ }
+ if n, err := r.Read(make([]byte, 10)); err != nil || n != 10 {
+ t.Errorf("Read failed: read %d %v", n, err)
+ }
+ if got, want := r.Len(), 1; got != want {
+ t.Errorf("r.Len(): got %d, want %d", got, want)
+ }
+ if n, err := r.Read(make([]byte, 1)); err != nil || n != 1 {
+ t.Errorf("Read failed: read %d %v", n, err)
+ }
+ if got, want := r.Len(), 0; got != want {
+ t.Errorf("r.Len(): got %d, want %d", got, want)
+ }
+}
+
+func TestReaderDoubleUnreadRune(t *testing.T) {
+ buf := NewBuffer([]byte("groucho"))
+ if _, _, err := buf.ReadRune(); err != nil {
+ // should not happen
+ t.Fatal(err)
+ }
+ if err := buf.UnreadByte(); err != nil {
+ // should not happen
+ t.Fatal(err)
+ }
+ if err := buf.UnreadByte(); err == nil {
+ t.Fatal("UnreadByte: expected error, got nil")
+ }
+}
+
// verify that copying from an empty reader always has the same results,
// regardless of the presence of a WriteTo method.
func TestReaderCopyNothing(t *testing.T) {
diff --git a/libgo/go/compress/bzip2/bit_reader.go b/libgo/go/compress/bzip2/bit_reader.go
index ab1d6065143..32d1036ae1b 100644
--- a/libgo/go/compress/bzip2/bit_reader.go
+++ b/libgo/go/compress/bzip2/bit_reader.go
@@ -77,6 +77,14 @@ func (br *bitReader) ReadBit() bool {
return n != 0
}
+func (br *bitReader) TryReadBit() (bit byte, ok bool) {
+ if br.bits > 0 {
+ br.bits--
+ return byte(br.n>>br.bits) & 1, true
+ }
+ return 0, false
+}
+
func (br *bitReader) Err() error {
return br.err
}
diff --git a/libgo/go/compress/bzip2/bzip2.go b/libgo/go/compress/bzip2/bzip2.go
index 3dc8c620615..82e30c7c9d7 100644
--- a/libgo/go/compress/bzip2/bzip2.go
+++ b/libgo/go/compress/bzip2/bzip2.go
@@ -22,14 +22,17 @@ func (s StructuralError) Error() string {
// A reader decompresses bzip2 compressed data.
type reader struct {
- br bitReader
- setupDone bool // true if we have parsed the bzip2 header.
- blockSize int // blockSize in bytes, i.e. 900 * 1024.
- eof bool
- buf []byte // stores Burrows-Wheeler transformed data.
- c [256]uint // the `C' array for the inverse BWT.
- tt []uint32 // mirrors the `tt' array in the bzip2 source and contains the P array in the upper 24 bits.
- tPos uint32 // Index of the next output byte in tt.
+ br bitReader
+ fileCRC uint32
+ blockCRC uint32
+ wantBlockCRC uint32
+ setupDone bool // true if we have parsed the bzip2 header.
+ blockSize int // blockSize in bytes, i.e. 900 * 1024.
+ eof bool
+ buf []byte // stores Burrows-Wheeler transformed data.
+ c [256]uint // the `C' array for the inverse BWT.
+ tt []uint32 // mirrors the `tt' array in the bzip2 source and contains the P array in the upper 24 bits.
+ tPos uint32 // Index of the next output byte in tt.
preRLE []uint32 // contains the RLE data still to be processed.
preRLEUsed int // number of entries of preRLE used.
@@ -50,12 +53,14 @@ const bzip2BlockMagic = 0x314159265359
const bzip2FinalMagic = 0x177245385090
// setup parses the bzip2 header.
-func (bz2 *reader) setup() error {
+func (bz2 *reader) setup(needMagic bool) error {
br := &bz2.br
- magic := br.ReadBits(16)
- if magic != bzip2FileMagic {
- return StructuralError("bad magic value")
+ if needMagic {
+ magic := br.ReadBits(16)
+ if magic != bzip2FileMagic {
+ return StructuralError("bad magic value")
+ }
}
t := br.ReadBits(8)
@@ -68,8 +73,11 @@ func (bz2 *reader) setup() error {
return StructuralError("invalid compression level")
}
+ bz2.fileCRC = 0
bz2.blockSize = 100 * 1024 * (int(level) - '0')
- bz2.tt = make([]uint32, bz2.blockSize)
+ if bz2.blockSize > len(bz2.tt) {
+ bz2.tt = make([]uint32, bz2.blockSize)
+ }
return nil
}
@@ -79,7 +87,7 @@ func (bz2 *reader) Read(buf []byte) (n int, err error) {
}
if !bz2.setupDone {
- err = bz2.setup()
+ err = bz2.setup(true)
brErr := bz2.br.Err()
if brErr != nil {
err = brErr
@@ -98,14 +106,14 @@ func (bz2 *reader) Read(buf []byte) (n int, err error) {
return
}
-func (bz2 *reader) read(buf []byte) (n int, err error) {
+func (bz2 *reader) readFromBlock(buf []byte) int {
// bzip2 is a block based compressor, except that it has a run-length
// preprocessing step. The block based nature means that we can
// preallocate fixed-size buffers and reuse them. However, the RLE
// preprocessing would require allocating huge buffers to store the
// maximum expansion. Thus we process blocks all at once, except for
// the RLE which we decompress as required.
-
+ n := 0
for (bz2.repeats > 0 || bz2.preRLEUsed < len(bz2.preRLE)) && n < len(buf) {
// We have RLE data pending.
@@ -148,34 +156,87 @@ func (bz2 *reader) read(buf []byte) (n int, err error) {
n++
}
- if n > 0 {
- return
- }
+ return n
+}
- // No RLE data is pending so we need to read a block.
+func (bz2 *reader) read(buf []byte) (int, error) {
+ for {
+ n := bz2.readFromBlock(buf)
+ if n > 0 {
+ bz2.blockCRC = updateCRC(bz2.blockCRC, buf[:n])
+ return n, nil
+ }
- br := &bz2.br
- magic := br.ReadBits64(48)
- if magic == bzip2FinalMagic {
- br.ReadBits64(32) // ignored CRC
- bz2.eof = true
- return 0, io.EOF
- } else if magic != bzip2BlockMagic {
- return 0, StructuralError("bad magic value found")
- }
+ // End of block. Check CRC.
+ if bz2.blockCRC != bz2.wantBlockCRC {
+ bz2.br.err = StructuralError("block checksum mismatch")
+ return 0, bz2.br.err
+ }
- err = bz2.readBlock()
- if err != nil {
- return 0, err
- }
+ // Find next block.
+ br := &bz2.br
+ switch br.ReadBits64(48) {
+ default:
+ return 0, StructuralError("bad magic value found")
+
+ case bzip2BlockMagic:
+ // Start of block.
+ err := bz2.readBlock()
+ if err != nil {
+ return 0, err
+ }
- return bz2.read(buf)
+ case bzip2FinalMagic:
+ // Check end-of-file CRC.
+ wantFileCRC := uint32(br.ReadBits64(32))
+ if br.err != nil {
+ return 0, br.err
+ }
+ if bz2.fileCRC != wantFileCRC {
+ br.err = StructuralError("file checksum mismatch")
+ return 0, br.err
+ }
+
+ // Skip ahead to byte boundary.
+ // Is there a file concatenated to this one?
+ // It would start with BZ.
+ if br.bits%8 != 0 {
+ br.ReadBits(br.bits % 8)
+ }
+ b, err := br.r.ReadByte()
+ if err == io.EOF {
+ br.err = io.EOF
+ bz2.eof = true
+ return 0, io.EOF
+ }
+ if err != nil {
+ br.err = err
+ return 0, err
+ }
+ z, err := br.r.ReadByte()
+ if err != nil {
+ if err == io.EOF {
+ err = io.ErrUnexpectedEOF
+ }
+ br.err = err
+ return 0, err
+ }
+ if b != 'B' || z != 'Z' {
+ return 0, StructuralError("bad magic value in continuation file")
+ }
+ if err := bz2.setup(false); err != nil {
+ return 0, err
+ }
+ }
+ }
}
// readBlock reads a bzip2 block. The magic number should already have been consumed.
func (bz2 *reader) readBlock() (err error) {
br := &bz2.br
- br.ReadBits64(32) // skip checksum. TODO: check it if we can figure out what it is.
+ bz2.wantBlockCRC = uint32(br.ReadBits64(32)) // skip checksum. TODO: check it if we can figure out what it is.
+ bz2.blockCRC = 0
+ bz2.fileCRC = (bz2.fileCRC<<1 | bz2.fileCRC>>31) ^ bz2.wantBlockCRC
randomized := br.ReadBits(1)
if randomized != 0 {
return StructuralError("deprecated randomized files")
@@ -316,6 +377,9 @@ func (bz2 *reader) readBlock() (err error) {
if repeat > 0 {
// We have decoded a complete run-length so we need to
// replicate the last output symbol.
+ if repeat > bz2.blockSize-bufIndex {
+ return StructuralError("repeats past end of block")
+ }
for i := 0; i < repeat; i++ {
b := byte(mtf.First())
bz2.tt[bufIndex] = uint32(b)
@@ -339,6 +403,9 @@ func (bz2 *reader) readBlock() (err error) {
// doesn't need to be encoded and we have |v-1| in the next
// line.
b := byte(mtf.Decode(int(v - 1)))
+ if bufIndex >= bz2.blockSize {
+ return StructuralError("data exceeds block size")
+ }
bz2.tt[bufIndex] = uint32(b)
bz2.c[b]++
bufIndex++
@@ -385,3 +452,33 @@ func inverseBWT(tt []uint32, origPtr uint, c []uint) uint32 {
return tt[origPtr] >> 8
}
+
+// This is a standard CRC32 like in hash/crc32 except that all the shifts are reversed,
+// causing the bits in the input to be processed in the reverse of the usual order.
+
+var crctab [256]uint32
+
+func init() {
+ const poly = 0x04C11DB7
+ for i := range crctab {
+ crc := uint32(i) << 24
+ for j := 0; j < 8; j++ {
+ if crc&0x80000000 != 0 {
+ crc = (crc << 1) ^ poly
+ } else {
+ crc <<= 1
+ }
+ }
+ crctab[i] = crc
+ }
+}
+
+// updateCRC updates the crc value to incorporate the data in b.
+// The initial value is 0.
+func updateCRC(val uint32, b []byte) uint32 {
+ crc := ^val
+ for _, v := range b {
+ crc = crctab[byte(crc>>24)^v] ^ (crc << 8)
+ }
+ return ^crc
+}
diff --git a/libgo/go/compress/bzip2/bzip2_test.go b/libgo/go/compress/bzip2/bzip2_test.go
index 7b227ac9f36..ada1f9a0016 100644
--- a/libgo/go/compress/bzip2/bzip2_test.go
+++ b/libgo/go/compress/bzip2/bzip2_test.go
@@ -6,6 +6,7 @@ package bzip2
import (
"bytes"
+ "encoding/base64"
"encoding/hex"
"io"
"io/ioutil"
@@ -62,6 +63,19 @@ func TestHelloWorldBZ2(t *testing.T) {
}
}
+func TestConcat(t *testing.T) {
+ out, err := decompressHex(helloWorldBZ2Hex + helloWorldBZ2Hex)
+ if err != nil {
+ t.Errorf("error from Read: %s", err)
+ return
+ }
+
+ hello2 := bytes.Repeat(helloWorld, 2)
+ if !bytes.Equal(hello2, out) {
+ t.Errorf("got %x, want %x", out, hello2)
+ }
+}
+
func testZeros(t *testing.T, inHex string, n int) {
out, err := decompressHex(inHex)
if err != nil {
@@ -155,3 +169,195 @@ const rand2Hex = "92d5652616ac444a4a04af1a8a3964aca0450d43d6cf233bd03233f4ba92f8
const rand3BZ2Hex = "425a68393141592653593be669d00000327ffffffffffffffffffffffffffffffffffff7ffffffffffffffffffffffffffffffc002b3b2b1b6e2bae400004c00132300004c0d268c004c08c0130026001a008683234c0684c34008c230261a04c0260064d07a8d00034000d27a1268c9931a8d327a3427a41faa69ea0da264c1a34219326869b51b49a6469a3268c689fa53269a62794687a9a68f5189994c9e487a8f534fd49a3d34043629e8c93d04da4f4648d30d4f44d3234c4d3023d0840680984d309934c234d3131a000640984f536a6132601300130130c8d00d04d1841ea7a8d31a02609b40023460010c01a34d4c1a0d04d3069306810034d0d0d4c0046130d034d0131a9a64d321804c68003400098344c13000991808c0001a00000000098004d3d4da4604c47a13012140aadf8d673c922c607ef6212a8c0403adea4b28aee578900e653b9cdeb8d11e6b838815f3ebaad5a01c5408d84a332170aff8734d4e06612d3c2889f31925fb89e33561f5100ae89b1f7047102e729373d3667e58d73aaa80fa7be368a1cc2dadd81d81ec8e1b504bd772ca31d03649269b01ceddaca07bf3d4eba24de141be3f86f93601e03714c0f64654671684f9f9528626fd4e1b76753dc0c54b842486b8d59d8ab314e86ca818e7a1f079463cbbd70d9b79b283c7edc419406311022e4be98c2c1374df9cdde2d008ce1d00e5f06ad1024baf555631f70831fc1023034e62be7c4bcb648caf276963ffa20e96bb50377fe1c113da0db4625b50741c35a058edb009c6ee5dbf93b8a6b060eec568180e8db791b82aab96cbf4326ca98361461379425ba8dcc347be670bdba7641883e5526ae3d833f6e9cb9bac9557747c79e206151072f7f0071dff3880411846f66bf4075c7462f302b53cb3400a74cf35652ad5641ed33572fd54e7ed7f85f58a0acba89327e7c6be5c58cb71528b99df2431f1d0358f8d28d81d95292da631fb06701decabb205fac59ff0fb1df536afc681eece6ea658c4d9eaa45f1342aa1ff70bdaff2ddaf25ec88c22f12829a0553db1ec2505554cb17d7b282e213a5a2aa30431ded2bce665bb199d023840832fedb2c0c350a27291407ff77440792872137df281592e82076a05c64c345ffb058c64f7f7c207ef78420b7010520610f17e302cc4dfcfaef72a0ed091aab4b541eb0531bbe941ca2f792bf7b31ca6162882b68054a8470115bc2c19f2df2023f7800432b39b04d3a304e8085ba3f1f0ca5b1ba4d38d339e6084de979cdea6d0e244c6c9fa0366bd890621e3d30846f5e8497e21597b8f29bbf52c961a485dfbea647600da0fc1f25ce4d203a8352ece310c39073525044e7ac46acf2ed9120bae1b4f6f02364abfe343f80b290983160c103557af1c68416480d024cc31b6c06cfec011456f1e95c420a12b48b1c3fe220c2879a982fb099948ac440db844b9a112a5188c7783fd3b19593290785f908d95c9db4b280bafe89c1313aeec24772046d9bc089645f0d182a21184e143823c5f52de50e5d7e98d3d7ab56f5413bbccd1415c9bcff707def475b643fb7f29842582104d4cc1dbaaca8f10a2f44273c339e0984f2b1e06ab2f0771db01fafa8142298345f3196f23e5847bda024034b6f59b11c29e981c881456e40d211929fd4f766200258aad8212016322bd5c605790dcfdf1bd2a93d99c9b8f498722d311d7eae7ff420496a31804c55f4759a7b13aaaf5f7ce006c3a8a998897d5e0a504398c2b627852545baf440798bcc5cc049357cf3f17d9771e4528a1af3d77dc794a11346e1bdf5efe37a405b127b4c43b616d61fbc5dc914e14240ef99a7400"
const rand3Hex = "1744b384d68c042371244e13500d4bfb98c6244e3d71a5b700224420b59c593553f33bd786e3d0ce31626f511bc985f59d1a88aa38ba8ad6218d306abee60dd9172540232b95be1af146c69e72e5fde667a090dc3f93bdc5c5af0ab80acdbaa7a505f628c59dc0247b31a439cacf5010a94376d71521df08c178b02fb96fdb1809144ea38c68536187c53201fea8631fb0a880b4451ccdca7cc61f6aafca21cc7449d920599db61789ac3b1e164b3390124f95022aeea39ccca3ec1053f4fa10de2978e2861ea58e477085c2220021a0927aa94c5d0006b5055abba340e4f9eba22e969978dfd18e278a8b89d877328ae34268bc0174cfe211954c0036f078025217d1269fac1932a03b05a0b616012271bbe1fb554171c7a59b196d8a4479f45a77931b5d97aaf6c0c673cbe597b79b96e2a0c1eae2e66e46ccc8c85798e23ffe972ebdaa3f6caea243c004e60321eb47cd79137d78fd0613be606feacc5b3637bdc96a89c13746db8cad886f3ccf912b2178c823bcac395f06d28080269bdca2debf3419c66c690fd1adcfbd53e32e79443d7a42511a84cb22ca94fffad9149275a075b2f8ae0b021dcde9bf62b102db920733b897560518b06e1ad7f4b03458493ddaa7f4fa2c1609f7a1735aeeb1b3e2cea3ab45fc376323cc91873b7e9c90d07c192e38d3f5dfc9bfab1fd821c854da9e607ea596c391c7ec4161c6c4493929a8176badaa5a5af7211c623f29643a937677d3df0da9266181b7c4da5dd40376db677fe8f4a1dc456adf6f33c1e37cec471dd318c2647644fe52f93707a77da7d1702380a80e14cc0fdce7bf2eed48a529090bae0388ee277ce6c7018c5fb00b88362554362205c641f0d0fab94fd5b8357b5ff08b207fee023709bc126ec90cfb17c006754638f8186aaeb1265e80be0c1189ec07d01d5f6f96cb9ce82744147d18490de7dc72862f42f024a16968891a356f5e7e0e695d8c933ba5b5e43ad4c4ade5399bc2cae9bb6189b7870d7f22956194d277f28b10e01c10c6ffe3e065f7e2d6d056aa790db5649ca84dc64c35566c0af1b68c32b5b7874aaa66467afa44f40e9a0846a07ae75360a641dd2acc69d93219b2891f190621511e62a27f5e4fbe641ece1fa234fc7e9a74f48d2a760d82160d9540f649256b169d1fed6fbefdc491126530f3cbad7913e19fbd7aa53b1e243fbf28d5f38c10ebd77c8b986775975cc1d619efb27cdcd733fa1ca36cffe9c0a33cc9f02463c91a886601fd349efee85ef1462065ef9bd2c8f533220ad93138b8382d5938103ab25b2d9af8ae106e1211eb9b18793fba033900c809c02cd6d17e2f3e6fc84dae873411f8e87c3f0a8f1765b7825d185ce3730f299c3028d4a62da9ee95c2b870fb70c79370d485f9d5d9acb78926d20444033d960524d2776dc31988ec7c0dbf23b9905d"
+
+const (
+ digits = iota
+ twain
+)
+
+var testfiles = []string{
+ // Digits is the digits of the irrational number e. Its decimal representation
+ // does not repeat, but there are only 10 posible digits, so it should be
+ // reasonably compressible.
+ digits: "testdata/e.txt.bz2",
+ // Twain is Project Gutenberg's edition of Mark Twain's classic English novel.
+ twain: "testdata/Mark.Twain-Tom.Sawyer.txt.bz2",
+}
+
+func benchmarkDecode(b *testing.B, testfile int) {
+ compressed, err := ioutil.ReadFile(testfiles[testfile])
+ if err != nil {
+ b.Fatal(err)
+ }
+ b.SetBytes(int64(len(compressed)))
+ for i := 0; i < b.N; i++ {
+ r := bytes.NewBuffer(compressed)
+ io.Copy(ioutil.Discard, NewReader(r))
+ }
+}
+
+func BenchmarkDecodeDigits(b *testing.B) { benchmarkDecode(b, digits) }
+func BenchmarkDecodeTwain(b *testing.B) { benchmarkDecode(b, twain) }
+
+func TestBufferOverrun(t *testing.T) {
+ // Tests https://code.google.com/p/go/issues/detail?id=5747.
+ buffer := bytes.NewBuffer([]byte(bufferOverrunBase64))
+ decoder := base64.NewDecoder(base64.StdEncoding, buffer)
+ decompressor := NewReader(decoder)
+ // This shouldn't panic.
+ ioutil.ReadAll(decompressor)
+}
+
+var bufferOverrunBase64 string = `
+QlpoNTFBWSZTWTzyiGcACMP/////////////////////////////////3/7f3///
+////4N/fCZODak2Xo44GIHZgkGzDRbFAuwAAKoFV7T6AO6qwA6APb6s2rOoAkAAD
+oACUoDtndh0iQAPkAAAAaPWihQoCgr5t97Obju21ChQB0NBm3RbA7apXrRoBooAA
+AhA+IAHWl2Us3O7t9yieb3udvd76+4+fd33nd3HO1bVvfcGRne6+3vfPvfc++995
+w7k973eJhasLVec970tzDNXdX28LoPXZ3H3K9z0s5ufWAfes49d5594c3dUYtI+2
++h1dvtpRa+uvrVEAG9bl893RVEN7cWvroSqWjPMGgAQi7Gq8TJSgKKdjKFBIB9Ae
+LqWxleu715eXe7ml9e5098Z6G1vr7t1QZ6ot76YzPd3j7333t2ql2Chm7XrA9ICQ
+VF77z3rVBWqkSXtlfb099hyezAr6USbGpICTSCFAaqHrKo+tUnm32rpE4Ue+t2mj
+bKUeipEqwc93EdhhTwmQpOhhesC9iqDSPNTWYNSnUtBdm1nsA0nqqNd7OWwDXtFL
+ONmmA6Ubke26I9UblvWIPR5VOWOnctai443URunnDy77uVC59OfRvezlDu33Z7Ly
+3NNuuHW63088xu3t3NHZhkZbG7tXRlj00qOtbaXTJUUdspTbABR9R6EUwQAEAAAA
+EMEwRpoAAAABMmhoAAjBNNAaCMhponpoGpgJpk9TEyp6niGKZkAaAEfqMQ09U80p
++pMGSCKngIAAAAgAAg0AAJhGgABGCEaaTyTKeNI1PE0wkj01GajMSNPSZGnqbU9T
+anlPUNAHqGQ0DQAMg9TamgAAYRU/IAAICAmjQJgjQBMEwp5DTSaaYmhTeqfplPID
+U1T9TynoU82pT1NPU/VP0j1NHqRpk9TTR7SnqaNNGmmQAaAD1Aeo0PSAAAAaaBiK
+eBAQBGgIABGQA0AmBNNBoaAgaJmpglPEyYap6npiTT0agGjJjUaaDTQAAAAAAM1A
+9QAaAAAADU8iEAQAEyAJk0NNNJgIZTJ5E00YSemiaZNGm1MpGNJ+lPU9qm9U2RDM
+oY0EzJB6h6nqDID1NMBDDRpo1AGNAjCMmhkMgaYSJIgAAAQyAAEyBoATECCNhTT0
+U/IZAmCM1DSTxkzUE8p6NDaGiZGJqntTFHvUyU9qPQp7Kn5GgKNPU9QAGg9QAAA3
+wz0Pk/g/m/m9P9H4vxv2+dH3gCS8nhbbbbbYxtgNsBsG0m2MbG0NNtsbYNsaY0wb
+bBibGmm22mxptNpsaGNDTY02JsG0MY0xg2MaYNNDbGwG0L5vsK/F9DO+EAA447Kq
+p7Wdf6Y+5c20T7DfHyMXIzRKrZexw72uiQI+y55vOe52xpqbCLC2uR20JdER7Zvr
+7ufuKb6zhiBxLuj0eA27v8RpMLucw9Ohwcizi2wrpt+yU1FdpM7ZYPcwS3XTef+A
+Wzjxwhdrgw3aH1LeC1eZW900x8V9Nv4hTPXp4l067P/4ANVZFF/imOe/d5bdueam
+/DFFokQWnFaU+ZqLBCM+d0PialJQWnLqRQZk/KhfbbYc2pCUTgffcSYbrCM1N+8l
+HU6gSz+h2GJXs+tbrNviL83M97X0vcTn/F82P8wen8/3/h3sHY+sf9CSej9ThYTV
+3lQ+FUHpfpGD4kv7dYMV995dpDX/y3xR8FoXx1bjUxBTNxuutwQ/h/Eedn9wpn6w
+E3+ND8YhN1HSriIxRE/6uFyMv6/oC6Elarw3aHMMqHJkGiiz6tejmvnYLQa+Qm6G
+deZ7jXTZV6NlpocgDnRdimS06bTYSkvPAL/xoWNLkX6N6VljU0dfKSBmm2uZE/xu
+sutQ1EdP7GdjhglIq4xlOFUFEQpmX+xx7R8y6c0GSAaqusOjNZwxZRudOvmXm1tZ
+T+YnbeB2ir9eiHNrtJNSLD/J/WDyuQpwBUtLKo0krccY/wIILP7f86teb9Z/9oyz
+OX05qEWbObfhpRw+9+rCvp/35ML8KX3aHaI0n+tudbFRsV5FLW+Oa8ruLN4peyVL
+DWjTHrXNthq/s7zAJYMeFJZkZt5mT9rfpH+5g3nc+piOSZ+J5nHtOnKI7Ff8Xl+j
+0t76XTNucCHQ6whav1OHdF53TY5wuv5OzvrdnxoId8fTyUvERr0ERINu/8XxZZ5f
+B5/kTZ8bBO0wv54Jp+ED/GQI8lZHzIQCP3vfQhwnCTj9TvITic7P4mYLDbH3fyzR
+i+6EajCcpXLWSGf+ZXkOrWspDWDhXtEKas0v3UqWksqgY1rTj45krX4KihN+daXs
+pZl5WPlta5p06CX6Xm2SfzqkMw12/3ix1bpnnZ+kFeBNX7A+E9zzG6OZaN78GOpl
+9Ht/eZn9PqWdav852zr0zqkDK2H5IjdvNah+b1YVGdQGzwR4Nw+f13yEKnV+y66W
+djfq7zWp7m5w+hzfv+Ly8O7oet5Vvd8/wQvO7qzOZ2vjf9X8Tj8PnMb/nc/nKqRR
++ml4UEhOOwfCeJEEI109CMYSh91iAJqPjMyH6KjrPD7W25llZVcREYNCTg6htbQt
+M38wYoquCWP6tdKYlVIv14xTNUeUf4El/FunCf6csZkmv+9tfWx7t59wuKIa3saU
+tZs9M+3HFOZtz3OLg/Unoaj9BYazYqA78xBU9tZzrtmF/rQL9CGJt90o/oYnSfcS
+SL3haaw351LXWQ1XOsv1SmH3v6ymuxEpPPnEDmBELaTYsvvMIWJsmPZFFww++Kd7
+s/Jo0JFeUU7uNtI+gVosAIpVVuWfI/9tOIycz7I5Z7zjV+NR2OuZbYtW5F08KX4o
+2k/xuJIchcNFPtxPfw9dkDgscRbMckyFMrzuZ3IvrcGzk0J6iI5ytrv37bGpAXMz
+WK9mMMPebepNevmLjjo/QWoM968Sjv7ldlPS5AinHcXwsFv6dmmh8lJt7UOJWoKu
+lMD1cB2ksIGpMdv8iuqR42Rn/kn+17BhhUZcwDBaUXVdX6bKW7fxlUYbq+mlqIcf
+a9v8HF87M9ANbi9bq9onf9TD7nQ6Xf6vZci8TBPX+/GI0He6j31fTVQYW+NsQxvO
+J8xrx+e58CCLQNjxeIyPt+F+qk/QMiXw+LyxGVkV/XcGQT9X03jSDP6beJ5QG1JW
+9Q3qLv/YixWI7gPV9Mrhf2oRYTc/9KLFRhkE3SjKOTKuSSBKQ24fI+hEznamH71D
+66Hwez8/0et7AtTv9zvamv2OD5He6fMV4k+ePl6+qPfO5CdHtK+eCDZL5+4f5yrl
+gTcRFiq8fXbc5IaI5fbbc1KMM/2T0Mr7+Hwaco6FtXm0fmhCgTZRqY4pKiEIfmaz
+QwHNOOCrtMJ2VwsyMumt7xsOolGnizRev6lILH43qPcczQM7Gc5zRin80YvFt1Qm
+h/57Z0auR2h0fuX50MBO4XQ+26y5l6v4j902R66c0j3z2KHstKQ04J/h6LbuNQE4
+D6cu/lyfK69DxxX8wb8XaQkMUcJdo1LzqUGDAb3Kfn/A3P/JYc99MO9qv67+SxWb
+wYTyqKdWTd+1KbR/Rcn0Io5zI/QquX7FA1bxfMytjQ/X+l0fh0Pf+Hx97meH4fQL
+7/T8/sdTm9Tn8nELvedyhydLlPPTScINdXyLIq9wgIJr4fWPbp9ZhFh/56fdSgOG
+HDXg+gkXsN2Rddr4HQ5P3u+RhLzmSjhzoqY5EsPC4QvRlX9JXjB84rPV5USR66qa
+/kjw4156GJnzoXtydKJE53t6PHfZWO+3ujsfI6iAdshc7OFzGXiZB9PtItKodhYq
+nABkTKdcpu4+TOpf9h5piX5slsaBjkeTnj/Ba02ilboQfcDVigxrYn/iTH5ySWUW
+/lHtg78s5UZM8sErwhNe3N3w+6ZOMnU+5i86/xFNtqZfDdXTGy1H3PzGbdtZXYT+
+Ixx2vpwBYzbPVYHxKosM5rPiVmcTllI9nuoSfeh9ib4foFWauOpvdmhBDqpTpKTX
+u8EO2l2Z195G2RIV7TlKSxGWjR5sl/nALu1uzBeLd9zpSujzMTd1uTX9Qk/Q1S+r
+vaW6bm8qqPO4jb6Wx6XIkm321nrIF6Ae25d1+Dpv/P5G4NoLd2j6/EtENC3FeR5z
+oo7bA+tI8yEQRhiF0z1FlJXLD5ZbhNNWQm/j/IbzRfh8JtOFZU7ruShLvHXysW9S
+9V909tr9jn8/E/Hb5N/1NVNHnZu2HIUvJvHJiHd2ucmeI9PWUMnppmE65GQ5E9xV
+ZRlGEH0X85EvmHyEupkMrCC0oMv9RCq+/H8gcfpe00Hs/S+regT5p58cyYomh93v
+qvuw/A06BE/wzJESuYbN9pqYpoXqXFemW1NksHEJ2w+PYMJ27WJyD5FpaXB85VaW
+qMOhDfO8E3QdH8ybyKt/UgI8/tDGpFbyOlaVdIv1FXJhoLp8soAA4Djg6/KZ066N
+ZFYuS8WdjpSZGP4/Lw+1yaXlzNznc/k2uHe2uXP3uFuPcHx+Dm44utxldoO1uBPy
++jzOs14+MIgOjOHMVNqAbMd8fUedLlhJMCfMtm4uz01enLNKcMrtLlPIR37Yukh1
+YEMXYpm7eU4XU+j+Jj3pDyaXtXs+p1fWfTN/cy9/Oxs4umUXQ4uHh1kObtayDJ56
+/QMxiHobjHNKuKfMxsrYEwN+QVIyVjAwMDYuMjQ1AAA9IwJniiBLRkZDAAAXt0Ja
+aDQxQVkmU1lZtwytAACLf///////////////////+//////v//////////bv78//
+/+AXO133uwO2xB2UxIvbKXrCqCoURUBL2ytFI82AFdcOwMhVTHtk5rD3szEVNYD4
+aIQINCaMRoTaSn7SbSMJiYmEwieTEp+psqbMCp+VNPaFNpqbBNR7UmanlPUeKfqm
+j1PU0/VPU08o9Q9EeKHlPJtKbYqeTCYhN6U9T1NH6mp+lPyoGNTI/Knkyg1MggAg
+CaMEyQnqZoaaRtRtJpppppoDaTR6hpphGh6mmgHpMQBpkGTTEAAaAAAA00AZDag0
+ADIBkGgABqemiRNTI0k8aU0PRGRoAZlP0UAAAGgAAAyAADQaAAAaAAAAAAAAAAAA
+AaAAAAM0kgRBJ5MlPFP1Gj0jTTTUaekxNAbUGjTQMgaZANNAAAAaAADTQAAAAAAA
+ANAA0AAANADQ0QAAAAAAAAAaGgAAAAAAABoA0AAA0AAAAAAAAAAAAANAAAAAkSEI
+aTRpomp5DUxNNDTJPTKaep6T09Kemmo2JG0aTQ9ENogaaGhkABo0NHqaBoDTI0DC
+Gj0gNAMhoDQ9QMQNAGQAaDDwyMPIMlbG1vhRBTFo6JksSupgpAjPbY0ec02IGXjb
+eS+FBsh01+O4ZOaD+srUZCFaT4DRjVDLx7uKIsFtESIDUg1ZkhyCSYov05C00MtR
+BdNNa/AYPGOQZWcs+VegXOPrkushFbZ3mBoRD6WamClkpBaHZrUhUl02bIfRXX4w
+b3/9cW9nHDVxh2qFBxqgRKfmq7/Jc/tdJk05nVrGbckGVy2PnIy30CDhpWmqrSot
+K2bOnX0NbP1iy2cd0Na0ZmbRstm4MzMzbbMySTd35F7f+zPP8DC+NJLYcakkkkRd
+NZlupJt3OMFoDAD2g+N3FAMCydhIpoRHRQAdFI5nNg4ugEXHCYxkMyGCwtaJmial
+y0IMlpSYYM/weXNJAhFqS0GNmvaPEtYGjbvaucMdklOTmBX1vfVAkTYB1uXCSK64
+UNIixOqRKLuRCFtqIQtgwqaFrCkIYbbewErWABa+VGADWsJXJjfx5SJViLuwiGXq
+Ru6vCuwmU5CJiJz3UiBpmLv0r2wskxUhY4tzPVGQ9RMXJl65eLSNwZVwaSyGZ9Cm
+A3jztQUUpFeUryBTskW95iVwRMFrhBCwZBAFJBZvhMEMNoDJJlUoIhQkAkjbExp2
+YZio+ZYeAZUwmH1qUbdQixmxf0+61+aVgJ1hwxsO1yG3hFx4pfjc09ITVht0pG8u
+FtVFhPa1KE0gTRUSVXywkITucqk0Waz5Fs6qJpVHYdNrbYRFxnFsQGY1qmsTLjK6
+4QX5Rddo6krM/Bx9CqIAKq4CzVQYHrmIAd2EBhYmwVYwLvhzKIUrc2EirnGIvyuD
+O4YZDSwsVTA0BpVvUOjDErkCraBoSutcKwUSSLGhVvNYHLz3klgZD++wWsa/swLw
+gvNDY2De+sncOv8X2lq4HD95ZdwPuTIMXCwSbg4RrIqv+L0y6F17pqDecyQYPEj3
+iN/0BBeWZlJAyBMi5U3Q1zAlsK8IlDhaXGmvZrgISq5CfNjmUgxDeMggOKqxu4sI
+OrilS49Lkl1J3u3GjXTuH+rX+4ccyFAQnizCpPClcY77F59j63S6fr5vr+y99tuO
+7Ox7Wg/ljwhdyaK4xMmXczeJbx7x07htJNtC4xcQfAtvzeznLrN6MN/ILIBOI65I
+qIA2D5fHHj1XN4aN6TvOjWDaSbSWqxCSCvXUpzkNJAkWXAuTwF8k5uSJvQj/rVo0
+hAhEMEIYkCRGx9AX+byIuXWlLMbbVeliHNUL5AQYmNwLFu4SkmGD+UWtBMyVHQOQ
+ss0ggoVKSKOBUgnVS6ljt7WE1qXqJJ4QA1pEwYNLEaguEE1LtPNoVr5WzjbSbWPk
+V9OW3y9IneUDLoIV5pAkEFTEFGFVjeTFxtpzBBfGgycBxVCdz8eESBIzsamRchAa
+TQunQH8DHnpfod9QuAuRvc7JBlKUCYmCjMvynLcxIFohxCaYrDvGw4QbXZB7oWQ7
+hpoGlz23ayDfB8NrRRzdilsEQyQniu9ASLQg7RrGZnoTr1ai12IbCEUCGdFq03P5
+nBnRFAGmisQGcyykV9gKtcVMWLhCuVmXg86dndn7slUpRNSSEAU20oaWIm1maFTu
+E0DT4gTbg0nuhjtz3kNOz+i7sBm0bkXjxQWuLqlZEmp60ZTyRZJDUqKSEKg6hqcy
+ERxdU22CSNOO10RYUUiDVpKhPNdKTOIE1thp02sBNoNTFSht8WJtaBQ09qN3jd5r
+dOLX4IA5fevRyCCzDgRXfV4wzik4KROjmxmTMglBySlIMEzcXehnDXCRiZSlvwA2
+0YsIOROcm4UrIRFxJHctJH7OdN5u1aHVHb5UaLHpv48NgmFRE56KTSoaWunqm2st
+S0mrAdOiqcR12PWVbdVRJKcQ0DQuhwlAPcRtpxN3D4kbXJjToSYJIFw406G2CSaK
+jQMIJPZGlQmgyFhoCSzeGS1VSq5SKKQQxs5RqKUcVUNY57YUETb4mXzV84SPngKi
+nsce0mXByZq5BKUA9puHZWLNwQIYuDaJUNgG+E01E3pDYVNLKYQ0hsVesgV5gZY0
+htDsRdGtm0+iGnkN6+Ea9YJtUZNAkx2GgSoix12nTW0avTUfxR3oYcpvZ7IdtABE
+UhBcjG4qZtDZsS1JQHys243vhLaDTSvvTeBiJA2tmokqECTBcSOCAGkAxMKlVAva
+4IsLRaBBqhxDbcGtgdw03mFcLUaFuhtKuuEIEkUleJQwby/zwu9uvvZK4xTV+ECM
+a8lmzxKmqkBggYK1+xPdbmJclm6tSZhE/OSJtCEjs+unJIQkT9hCWgBJqGMS07Eh
+AJNmBiuVEVdTyjkIJkavuZmx2sJF13htgEZUCC23lZFOE6gWbM9WyYNJTM8yCQrb
+0Sx3OQvBML5cRATAQkSQkAJOAhoxpQkNi4ZiEVDbdtJAME0RXNDXGHA3M3Q0mm1o
+IEwbWpaM1DQCSMbGRCAu3iRIQiT6RlBpT1n3tfwvUXz3gIVlx3mEximY/kZW1kNG
+sgEJIrBisaEoGYPJ+1CQUYFBw+eGEHJQBpNHjErXUJY2iWHQ30hXwFBuMSxQ2lB5
+bg+/LX3euG6HsHUB1lFvBvaiaBrITVwkCTa1d0s9CHZCiDZjbWReKyrpPE2oSa7o
+LPrR4BJvys9ttjUpzETSSMxh8vsr9dXTwKBtK+1xCTGDQmNIaE29HmHdS5GSxpya
+MismcAUSEgSxHBrKtgsZzduG7vHZn16l3kFkVITtENIzS2JsiBwFTDlhgexsjBHv
+5HXOYxHBzoSDCcPZ0ctvkY9aS5XpoQuFYkGJgCsqjJZeUMNUEpDSbKcnUc1PifIA
+CbR2UoXawBlspkEBr9HBfvUi/MUakZVOf1WKYrqSaIXce62JOyhJLq3qJBloTA0F
+VbILEtM+heFmNRCFt70GJrExVJri0ArYbCRbADSGDBpBXxxb/6fo+s3C7uaL7RjM
+LV2IQBNrAJrKFeJwTsPnxbAsemirUx2lk1kaxschzdK4TQNJN5wQnolIFg401OZ4
+2na11LnT3lR+1k1TMJhiAjXMk0F1ooHnYlt9LKfJ3ZIOmeY+2l9bUQHWFNGyEyfj
+EAcu3kpGLq0Ez7XOS+EpAASRQTAYMATfVQibHLTT30zG732+pNe9za1JNt8sNJYn
+RjWuJ6jL5ILV0rcd9vT7X9fObvcXitpvJ2XBJE+PhX2HaTkyWeF9pwnlQNrTe9hV
+tzhA+ihZrDrHNmLcQjZbnv/IMubqq8egxY80t5n6vZ6U5TR6U9uZJvai1xtqAyCR
+NWkW52m00rDTEuO6BA4q2RHDWwbETF55rRsWLIgNW9qJCyMHPbTM/dMBmWMQSMxz
+4M2pRzt47SICxA327UqSCEERqMFybmYi3nUxePtLgHYplqRiw4ynMbXd/kiQ0LE0
+PKJSSCXA42ymziCpAxNWflzpzQdJZusahRFr6t6m+4p273/Taj7k+hZyNgBAgXAY
+8F7pTts6orLb8IA6o4TOwkwQYmKvKu9VwMrE7+GUhVIAgY9a8DyQMiDBkEAwh7S1
+KgCBfao8DK1CwSS8Z3WjL5MEgt93z2koUQCD/YxMBppiCMp7SDVSmkkIHptfGpeh
+t+M13Ccv1tavIASFiaQl6rBz3K4N3DSGwNkCibrvEAC0fQirOWnc4NVbcLKpFG1l
+NQXF/eqdT79wq1Mvlap3QSCLhcD2D3fCkKVWid4aSjtp9FOX1Uaf7P9eT93zd9Sv
+mj2yNLRUGzyI/0oONNSzmmkvJ5Cq2X2CdldIWMGZO57RJ8oyATAWTQmRmNkfh0Sx
+uuR/J9oUsomVy1AEntc0dlPivkqBkBqrxU3j5PnWkaI3ZRGc0gg9spCQEISh4xEU
+pMhVrnmDQLfLP8Ouqpx917MAw7hkjQk6BJFTAbXDsz3LSHIxo/gB8qrA1vbvdZZh
+LtR0frJdfdppX8nAQX/TAxOQ8+H6yw8a9i7/zJEfSYIhop59N/fhcWW2F14cj2Xc
+fyHaZ04lTO4uPnly91jwuFPaREuZVp8AxImIhlkxkAN61tWdWG7tEbaCgszh6VIz
+ThFnHo2Vi8SQXPrXCN7J9Tc9ZYiAYqoThV/u6SYsea5aZL8deOvKBQCgZZuIxX1z
+4EnfcqG176vY4VqMBIC4pMJz0WcHJYqN+j7BiwGoMBwExrIdTB7q4XIFLotcIpS0
+1MqyVsesvoQq7WObmGQXdMliMirSLcDuSx8Qy+4pIBgGDIyMp1qbonnGdcHYvU8S
+O0A8s/iua5oFdNZTWvbVI4FUH9sKcLiB3/fIAF+sB4n8q6L+UCfmbPcAo/crQ6b3
+HqhDBMY9J0q/jdz9GNYZ/1fbXdkUqAQKFePhtzJDRBZba27+LPQNMCcrHMq06F1T
+4QmLmkHt7LxB2pAczUO+T2O9bHEw/HWw+dYf2MoRDUw=
+`
diff --git a/libgo/go/compress/bzip2/huffman.go b/libgo/go/compress/bzip2/huffman.go
index f755019bb50..8f6b0c9cad3 100644
--- a/libgo/go/compress/bzip2/huffman.go
+++ b/libgo/go/compress/bzip2/huffman.go
@@ -33,14 +33,17 @@ const invalidNodeValue = 0xffff
// Decode reads bits from the given bitReader and navigates the tree until a
// symbol is found.
-func (t huffmanTree) Decode(br *bitReader) (v uint16) {
+func (t *huffmanTree) Decode(br *bitReader) (v uint16) {
nodeIndex := uint16(0) // node 0 is the root of the tree.
for {
node := &t.nodes[nodeIndex]
- bit := br.ReadBit()
+ bit, ok := br.TryReadBit()
+ if !ok && br.ReadBit() {
+ bit = 1
+ }
// bzip2 encodes left as a true bit.
- if bit {
+ if bit != 0 {
// left
if node.left == invalidNodeValue {
return node.leftValue
diff --git a/libgo/go/compress/bzip2/move_to_front.go b/libgo/go/compress/bzip2/move_to_front.go
index 0ed19dec39c..b7e75a700a1 100644
--- a/libgo/go/compress/bzip2/move_to_front.go
+++ b/libgo/go/compress/bzip2/move_to_front.go
@@ -15,10 +15,11 @@ type moveToFrontDecoder struct {
// Rather than actually keep the list in memory, the symbols are stored
// as a circular, double linked list with the symbol indexed by head
// at the front of the list.
- symbols []byte
- next []uint8
- prev []uint8
+ symbols [256]byte
+ next [256]uint8
+ prev [256]uint8
head uint8
+ len int
}
// newMTFDecoder creates a move-to-front decoder with an explicit initial list
@@ -28,12 +29,9 @@ func newMTFDecoder(symbols []byte) *moveToFrontDecoder {
panic("too many symbols")
}
- m := &moveToFrontDecoder{
- symbols: symbols,
- next: make([]uint8, len(symbols)),
- prev: make([]uint8, len(symbols)),
- }
-
+ m := new(moveToFrontDecoder)
+ copy(m.symbols[:], symbols)
+ m.len = len(symbols)
m.threadLinkedList()
return m
}
@@ -45,34 +43,29 @@ func newMTFDecoderWithRange(n int) *moveToFrontDecoder {
panic("newMTFDecoderWithRange: cannot have > 256 symbols")
}
- m := &moveToFrontDecoder{
- symbols: make([]uint8, n),
- next: make([]uint8, n),
- prev: make([]uint8, n),
- }
-
+ m := new(moveToFrontDecoder)
for i := 0; i < n; i++ {
- m.symbols[i] = byte(i)
+ m.symbols[byte(i)] = byte(i)
}
-
+ m.len = n
m.threadLinkedList()
return m
}
// threadLinkedList creates the initial linked-list pointers.
func (m *moveToFrontDecoder) threadLinkedList() {
- if len(m.symbols) == 0 {
+ if m.len == 0 {
return
}
- m.prev[0] = uint8(len(m.symbols) - 1)
+ m.prev[0] = uint8(m.len - 1)
- for i := 0; i < len(m.symbols)-1; i++ {
+ for i := byte(0); int(i) < m.len-1; i++ {
m.next[i] = uint8(i + 1)
m.prev[i+1] = uint8(i)
}
- m.next[len(m.symbols)-1] = 0
+ m.next[m.len-1] = 0
}
func (m *moveToFrontDecoder) Decode(n int) (b byte) {
diff --git a/libgo/go/compress/flate/copy.go b/libgo/go/compress/flate/copy.go
index 06e5d2e66d9..a3200a8f49e 100644
--- a/libgo/go/compress/flate/copy.go
+++ b/libgo/go/compress/flate/copy.go
@@ -6,12 +6,27 @@ package flate
// forwardCopy is like the built-in copy function except that it always goes
// forward from the start, even if the dst and src overlap.
-func forwardCopy(dst, src []byte) int {
- if len(src) > len(dst) {
- src = src[:len(dst)]
+// It is equivalent to:
+// for i := 0; i < n; i++ {
+// mem[dst+i] = mem[src+i]
+// }
+func forwardCopy(mem []byte, dst, src, n int) {
+ if dst <= src {
+ copy(mem[dst:dst+n], mem[src:src+n])
+ return
}
- for i, x := range src {
- dst[i] = x
+ for {
+ if dst >= src+n {
+ copy(mem[dst:dst+n], mem[src:src+n])
+ return
+ }
+ // There is some forward overlap. The destination
+ // will be filled with a repeated pattern of mem[src:src+k].
+ // We copy one instance of the pattern here, then repeat.
+ // Each time around this loop k will double.
+ k := dst - src
+ copy(mem[dst:dst+k], mem[src:src+k])
+ n -= k
+ dst += k
}
- return len(src)
}
diff --git a/libgo/go/compress/flate/copy_test.go b/libgo/go/compress/flate/copy_test.go
index a9281d446e9..2011b1547c9 100644
--- a/libgo/go/compress/flate/copy_test.go
+++ b/libgo/go/compress/flate/copy_test.go
@@ -30,10 +30,12 @@ func TestForwardCopy(t *testing.T) {
}
for _, tc := range testCases {
b := []byte("0123456789")
- dst := b[tc.dst0:tc.dst1]
- src := b[tc.src0:tc.src1]
- n := forwardCopy(dst, src)
- got := string(dst[:n])
+ n := tc.dst1 - tc.dst0
+ if tc.src1-tc.src0 < n {
+ n = tc.src1 - tc.src0
+ }
+ forwardCopy(b, tc.dst0, tc.src0, n)
+ got := string(b[tc.dst0 : tc.dst0+n])
if got != tc.want {
t.Errorf("dst=b[%d:%d], src=b[%d:%d]: got %q, want %q",
tc.dst0, tc.dst1, tc.src0, tc.src1, got, tc.want)
diff --git a/libgo/go/compress/flate/deflate.go b/libgo/go/compress/flate/deflate.go
index d357fe361a5..8c79df0c607 100644
--- a/libgo/go/compress/flate/deflate.go
+++ b/libgo/go/compress/flate/deflate.go
@@ -416,6 +416,50 @@ func (d *compressor) init(w io.Writer, level int) (err error) {
return nil
}
+var zeroes [32]int
+var bzeroes [256]byte
+
+func (d *compressor) reset(w io.Writer) {
+ d.w.reset(w)
+ d.sync = false
+ d.err = nil
+ switch d.compressionLevel.chain {
+ case 0:
+ // level was NoCompression.
+ for i := range d.window {
+ d.window[i] = 0
+ }
+ d.windowEnd = 0
+ default:
+ d.chainHead = -1
+ for s := d.hashHead; len(s) > 0; {
+ n := copy(s, zeroes[:])
+ s = s[n:]
+ }
+ for s := d.hashPrev; len(s) > 0; s = s[len(zeroes):] {
+ copy(s, zeroes[:])
+ }
+ d.hashOffset = 1
+
+ d.index, d.windowEnd = 0, 0
+ for s := d.window; len(s) > 0; {
+ n := copy(s, bzeroes[:])
+ s = s[n:]
+ }
+ d.blockStart, d.byteAvailable = 0, false
+
+ d.tokens = d.tokens[:maxFlateBlockTokens+1]
+ for i := 0; i <= maxFlateBlockTokens; i++ {
+ d.tokens[i] = 0
+ }
+ d.tokens = d.tokens[:0]
+ d.length = minMatchLength - 1
+ d.offset = 0
+ d.hash = 0
+ d.maxInsertIndex = 0
+ }
+}
+
func (d *compressor) close() error {
d.sync = true
d.step(d)
@@ -439,7 +483,6 @@ func (d *compressor) close() error {
// If level is in the range [-1, 9] then the error returned will be nil.
// Otherwise the error returned will be non-nil.
func NewWriter(w io.Writer, level int) (*Writer, error) {
- const logWindowSize = logMaxOffsetSize
var dw Writer
if err := dw.d.init(w, level); err != nil {
return nil, err
@@ -462,6 +505,7 @@ func NewWriterDict(w io.Writer, level int, dict []byte) (*Writer, error) {
zw.Write(dict)
zw.Flush()
dw.enabled = true
+ zw.dict = append(zw.dict, dict...) // duplicate dictionary for Reset method.
return zw, err
}
@@ -480,7 +524,8 @@ func (w *dictWriter) Write(b []byte) (n int, err error) {
// A Writer takes data written to it and writes the compressed
// form of that data to an underlying writer (see NewWriter).
type Writer struct {
- d compressor
+ d compressor
+ dict []byte
}
// Write writes data to w, which will eventually write the
@@ -506,3 +551,21 @@ func (w *Writer) Flush() error {
func (w *Writer) Close() error {
return w.d.close()
}
+
+// Reset discards the writer's state and makes it equivalent to
+// the result of NewWriter or NewWriterDict called with dst
+// and w's level and dictionary.
+func (w *Writer) Reset(dst io.Writer) {
+ if dw, ok := w.d.w.w.(*dictWriter); ok {
+ // w was created with NewWriterDict
+ dw.w = dst
+ w.d.reset(dw)
+ dw.enabled = false
+ w.Write(w.dict)
+ w.Flush()
+ dw.enabled = true
+ } else {
+ // w was created with NewWriter
+ w.d.reset(dst)
+ }
+}
diff --git a/libgo/go/compress/flate/deflate_test.go b/libgo/go/compress/flate/deflate_test.go
index 8c4a6d6b36f..730234c3850 100644
--- a/libgo/go/compress/flate/deflate_test.go
+++ b/libgo/go/compress/flate/deflate_test.go
@@ -9,6 +9,7 @@ import (
"fmt"
"io"
"io/ioutil"
+ "reflect"
"sync"
"testing"
)
@@ -424,3 +425,66 @@ func TestRegression2508(t *testing.T) {
}
w.Close()
}
+
+func TestWriterReset(t *testing.T) {
+ for level := 0; level <= 9; level++ {
+ if testing.Short() && level > 1 {
+ break
+ }
+ w, err := NewWriter(ioutil.Discard, level)
+ if err != nil {
+ t.Fatalf("NewWriter: %v", err)
+ }
+ buf := []byte("hello world")
+ for i := 0; i < 1024; i++ {
+ w.Write(buf)
+ }
+ w.Reset(ioutil.Discard)
+
+ wref, err := NewWriter(ioutil.Discard, level)
+ if err != nil {
+ t.Fatalf("NewWriter: %v", err)
+ }
+
+ // DeepEqual doesn't compare functions.
+ w.d.fill, wref.d.fill = nil, nil
+ w.d.step, wref.d.step = nil, nil
+ if !reflect.DeepEqual(w, wref) {
+ t.Errorf("level %d Writer not reset after Reset", level)
+ }
+ }
+ testResetOutput(t, func(w io.Writer) (*Writer, error) { return NewWriter(w, NoCompression) })
+ testResetOutput(t, func(w io.Writer) (*Writer, error) { return NewWriter(w, DefaultCompression) })
+ testResetOutput(t, func(w io.Writer) (*Writer, error) { return NewWriter(w, BestCompression) })
+ dict := []byte("we are the world")
+ testResetOutput(t, func(w io.Writer) (*Writer, error) { return NewWriterDict(w, NoCompression, dict) })
+ testResetOutput(t, func(w io.Writer) (*Writer, error) { return NewWriterDict(w, DefaultCompression, dict) })
+ testResetOutput(t, func(w io.Writer) (*Writer, error) { return NewWriterDict(w, BestCompression, dict) })
+}
+
+func testResetOutput(t *testing.T, newWriter func(w io.Writer) (*Writer, error)) {
+ buf := new(bytes.Buffer)
+ w, err := newWriter(buf)
+ if err != nil {
+ t.Fatalf("NewWriter: %v", err)
+ }
+ b := []byte("hello world")
+ for i := 0; i < 1024; i++ {
+ w.Write(b)
+ }
+ w.Close()
+ out1 := buf.String()
+
+ buf2 := new(bytes.Buffer)
+ w.Reset(buf2)
+ for i := 0; i < 1024; i++ {
+ w.Write(b)
+ }
+ w.Close()
+ out2 := buf2.String()
+
+ if out1 != out2 {
+ t.Errorf("got %q, expected %q", out2, out1)
+ }
+ t.Logf("got %d bytes", len(out1))
+}
diff --git a/libgo/go/compress/flate/flate_test.go b/libgo/go/compress/flate/flate_test.go
index aba820a1f95..57fea5ab4dc 100644
--- a/libgo/go/compress/flate/flate_test.go
+++ b/libgo/go/compress/flate/flate_test.go
@@ -24,3 +24,39 @@ func TestUncompressedSource(t *testing.T) {
t.Errorf("output[0] = %x, want 0x11", output[0])
}
}
+
+// The following test should not panic.
+func TestIssue5915(t *testing.T) {
+ bits := []int{4, 0, 0, 6, 4, 3, 2, 3, 3, 4, 4, 5, 0, 0, 0, 0, 5, 5, 6,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 8, 6, 0, 11, 0, 8, 0, 6, 6, 10, 8}
+ h := new(huffmanDecoder)
+ ok := h.init(bits)
+ if ok == true {
+ t.Fatalf("Given sequence of bits is bad, and should not succeed.")
+ }
+}
+
+// The following test should not panic.
+func TestIssue5962(t *testing.T) {
+ bits := []int{4, 0, 0, 6, 4, 3, 2, 3, 3, 4, 4, 5, 0, 0, 0, 0,
+ 5, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11}
+ h := new(huffmanDecoder)
+ ok := h.init(bits)
+ if ok == true {
+ t.Fatalf("Given sequence of bits is bad, and should not succeed.")
+ }
+}
+
+// The following test should not panic.
+func TestIssue6255(t *testing.T) {
+ bits1 := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 11}
+ bits2 := []int{11, 13}
+ h := new(huffmanDecoder)
+ if !h.init(bits1) {
+ t.Fatalf("Given sequence of bits is good and should succeed.")
+ }
+ if h.init(bits2) {
+ t.Fatalf("Given sequence of bits is bad and should not succeed.")
+ }
+}
diff --git a/libgo/go/compress/flate/huffman_bit_writer.go b/libgo/go/compress/flate/huffman_bit_writer.go
index 25e1da336aa..b182a710b9a 100644
--- a/libgo/go/compress/flate/huffman_bit_writer.go
+++ b/libgo/go/compress/flate/huffman_bit_writer.go
@@ -97,6 +97,31 @@ func newHuffmanBitWriter(w io.Writer) *huffmanBitWriter {
}
}
+func (w *huffmanBitWriter) reset(writer io.Writer) {
+ w.w = writer
+ w.bits, w.nbits, w.nbytes, w.err = 0, 0, 0, nil
+ w.bytes = [64]byte{}
+ for i := range w.codegen {
+ w.codegen[i] = 0
+ }
+ for _, s := range [...][]int32{w.literalFreq, w.offsetFreq, w.codegenFreq} {
+ for i := range s {
+ s[i] = 0
+ }
+ }
+ for _, enc := range [...]*huffmanEncoder{
+ w.literalEncoding,
+ w.offsetEncoding,
+ w.codegenEncoding} {
+ for i := range enc.code {
+ enc.code[i] = 0
+ }
+ for i := range enc.codeBits {
+ enc.codeBits[i] = 0
+ }
+ }
+}
+
func (w *huffmanBitWriter) flushBits() {
if w.err != nil {
w.nbits = 0
diff --git a/libgo/go/compress/flate/huffman_code.go b/libgo/go/compress/flate/huffman_code.go
index 009cce6267a..3b9fce466ed 100644
--- a/libgo/go/compress/flate/huffman_code.go
+++ b/libgo/go/compress/flate/huffman_code.go
@@ -19,23 +19,13 @@ type literalNode struct {
freq int32
}
-type chain struct {
- // The sum of the leaves in this tree
- freq int32
-
- // The number of literals to the left of this item at this level
- leafCount int32
-
- // The right child of this chain in the previous level.
- up *chain
-}
-
+// A levelInfo describes the state of the constructed tree for a given depth.
type levelInfo struct {
// Our level. for better printing
level int32
- // The most recent chain generated for this level
- lastChain *chain
+ // The frequency of the last node at this level
+ lastFreq int32
// The frequency of the next character to add to this level
nextCharFreq int32
@@ -47,12 +37,6 @@ type levelInfo struct {
// The number of chains remaining to generate for this level before moving
// up to the next level
needed int32
-
- // The levelInfo for level+1
- up *levelInfo
-
- // The levelInfo for level-1
- down *levelInfo
}
func maxNode() literalNode { return literalNode{math.MaxUint16, math.MaxInt32} }
@@ -121,6 +105,8 @@ func (h *huffmanEncoder) bitLength(freq []int32) int64 {
return total
}
+const maxBitsLimit = 16
+
// Return the number of literals assigned to each bit size in the Huffman encoding
//
// This method is only called when list.length >= 3
@@ -131,9 +117,13 @@ func (h *huffmanEncoder) bitLength(freq []int32) int64 {
// frequency, and has as its last element a special element with frequency
// MaxInt32
// maxBits The maximum number of bits that should be used to encode any literal.
+// Must be less than 16.
// return An integer array in which array[i] indicates the number of literals
// that should be encoded in i bits.
func (h *huffmanEncoder) bitCounts(list []literalNode, maxBits int32) []int32 {
+ if maxBits >= maxBitsLimit {
+ panic("flate: maxBits too large")
+ }
n := int32(len(list))
list = list[0 : n+1]
list[n] = maxNode()
@@ -148,53 +138,61 @@ func (h *huffmanEncoder) bitCounts(list []literalNode, maxBits int32) []int32 {
// A bogus "Level 0" whose sole purpose is so that
// level1.prev.needed==0. This makes level1.nextPairFreq
// be a legitimate value that never gets chosen.
- top := &levelInfo{needed: 0}
- chain2 := &chain{list[1].freq, 2, new(chain)}
+ var levels [maxBitsLimit]levelInfo
+ // leafCounts[i] counts the number of literals at the left
+ // of ancestors of the rightmost node at level i.
+ // leafCounts[i][j] is the number of literals at the left
+ // of the level j ancestor.
+ var leafCounts [maxBitsLimit][maxBitsLimit]int32
+
for level := int32(1); level <= maxBits; level++ {
// For every level, the first two items are the first two characters.
// We initialize the levels as if we had already figured this out.
- top = &levelInfo{
+ levels[level] = levelInfo{
level: level,
- lastChain: chain2,
+ lastFreq: list[1].freq,
nextCharFreq: list[2].freq,
nextPairFreq: list[0].freq + list[1].freq,
- down: top,
}
- top.down.up = top
+ leafCounts[level][level] = 2
if level == 1 {
- top.nextPairFreq = math.MaxInt32
+ levels[level].nextPairFreq = math.MaxInt32
}
}
// We need a total of 2*n - 2 items at top level and have already generated 2.
- top.needed = 2*n - 4
+ levels[maxBits].needed = 2*n - 4
- l := top
+ level := maxBits
for {
+ l := &levels[level]
if l.nextPairFreq == math.MaxInt32 && l.nextCharFreq == math.MaxInt32 {
// We've run out of both leafs and pairs.
// End all calculations for this level.
- // To m sure we never come back to this level or any lower level,
+ // To make sure we never come back to this level or any lower level,
// set nextPairFreq impossibly large.
- l.lastChain = nil
l.needed = 0
- l = l.up
- l.nextPairFreq = math.MaxInt32
+ levels[level+1].nextPairFreq = math.MaxInt32
+ level++
continue
}
- prevFreq := l.lastChain.freq
+ prevFreq := l.lastFreq
if l.nextCharFreq < l.nextPairFreq {
// The next item on this row is a leaf node.
- n := l.lastChain.leafCount + 1
- l.lastChain = &chain{l.nextCharFreq, n, l.lastChain.up}
+ n := leafCounts[level][level] + 1
+ l.lastFreq = l.nextCharFreq
+ // Lower leafCounts are the same of the previous node.
+ leafCounts[level][level] = n
l.nextCharFreq = list[n].freq
} else {
// The next item on this row is a pair from the previous row.
// nextPairFreq isn't valid until we generate two
// more values in the level below
- l.lastChain = &chain{l.nextPairFreq, l.lastChain.leafCount, l.down.lastChain}
- l.down.needed = 2
+ l.lastFreq = l.nextPairFreq
+ // Take leaf counts from the lower level, except counts[level] remains the same.
+ copy(leafCounts[level][:level], leafCounts[level-1][:level])
+ levels[l.level-1].needed = 2
}
if l.needed--; l.needed == 0 {
@@ -202,33 +200,33 @@ func (h *huffmanEncoder) bitCounts(list []literalNode, maxBits int32) []int32 {
// Continue calculating one level up. Fill in nextPairFreq
// of that level with the sum of the two nodes we've just calculated on
// this level.
- up := l.up
- if up == nil {
+ if l.level == maxBits {
// All done!
break
}
- up.nextPairFreq = prevFreq + l.lastChain.freq
- l = up
+ levels[l.level+1].nextPairFreq = prevFreq + l.lastFreq
+ level++
} else {
// If we stole from below, move down temporarily to replenish it.
- for l.down.needed > 0 {
- l = l.down
+ for levels[level-1].needed > 0 {
+ level--
}
}
}
// Somethings is wrong if at the end, the top level is null or hasn't used
// all of the leaves.
- if top.lastChain.leafCount != n {
- panic("top.lastChain.leafCount != n")
+ if leafCounts[maxBits][maxBits] != n {
+ panic("leafCounts[maxBits][maxBits] != n")
}
bitCount := make([]int32, maxBits+1)
bits := 1
- for chain := top.lastChain; chain.up != nil; chain = chain.up {
+ counts := &leafCounts[maxBits]
+ for level := maxBits; level > 0; level-- {
// chain.leafCount gives the number of literals requiring at least "bits"
// bits to encode.
- bitCount[bits] = chain.leafCount - chain.up.leafCount
+ bitCount[bits] = counts[level] - counts[level-1]
bits++
}
return bitCount
diff --git a/libgo/go/compress/flate/inflate.go b/libgo/go/compress/flate/inflate.go
index beca34b4d8c..3eb3b2b83e6 100644
--- a/libgo/go/compress/flate/inflate.go
+++ b/libgo/go/compress/flate/inflate.go
@@ -91,6 +91,10 @@ type huffmanDecoder struct {
// Initialize Huffman decoding tables from array of code lengths.
func (h *huffmanDecoder) init(bits []int) bool {
+ if h.min != 0 {
+ *h = huffmanDecoder{}
+ }
+
// Count number of codes of each length,
// compute min and max length.
var count [maxCodeLen]int
@@ -125,6 +129,9 @@ func (h *huffmanDecoder) init(bits []int) bool {
if i == huffmanChunkBits+1 {
// create link tables
link := code >> 1
+ if huffmanNumChunks < link {
+ return false
+ }
h.links = make([][]uint32, huffmanNumChunks-link)
for j := uint(link); j < huffmanNumChunks; j++ {
reverse := int(reverseByte[j>>8]) | int(reverseByte[j&0xff])<<8
@@ -154,7 +161,11 @@ func (h *huffmanDecoder) init(bits []int) bool {
h.chunks[off] = chunk
}
} else {
- linktab := h.links[h.chunks[reverse&(huffmanNumChunks-1)]>>huffmanValueShift]
+ value := h.chunks[reverse&(huffmanNumChunks-1)] >> huffmanValueShift
+ if value >= uint32(len(h.links)) {
+ return false
+ }
+ linktab := h.links[value]
reverse >>= huffmanChunkBits
for off := reverse; off < numLinks; off += 1 << uint(n-huffmanChunkBits) {
linktab[off] = chunk
@@ -511,7 +522,7 @@ func (f *decompressor) copyHist() bool {
if x := len(f.hist) - p; n > x {
n = x
}
- forwardCopy(f.hist[f.hp:f.hp+n], f.hist[p:p+n])
+ forwardCopy(f.hist[:], f.hp, p, n)
p += n
f.hp += n
f.copyLen -= n
@@ -633,6 +644,10 @@ func (f *decompressor) huffSym(h *huffmanDecoder) (int, error) {
if n > huffmanChunkBits {
chunk = h.links[chunk>>huffmanValueShift][(f.b>>huffmanChunkBits)&h.linkMask]
n = uint(chunk & huffmanCountMask)
+ if n == 0 {
+ f.err = CorruptInputError(f.roffset)
+ return 0, f.err
+ }
}
if n <= f.nb {
f.b >>= n
diff --git a/libgo/go/compress/flate/reader_test.go b/libgo/go/compress/flate/reader_test.go
index 54ed788dbd3..2a8ebbc9438 100644
--- a/libgo/go/compress/flate/reader_test.go
+++ b/libgo/go/compress/flate/reader_test.go
@@ -37,6 +37,7 @@ var testfiles = []string{
}
func benchmarkDecode(b *testing.B, testfile, level, n int) {
+ b.ReportAllocs()
b.StopTimer()
b.SetBytes(int64(n))
buf0, err := ioutil.ReadFile(testfiles[testfile])
@@ -55,7 +56,7 @@ func benchmarkDecode(b *testing.B, testfile, level, n int) {
if len(buf0) > n-i {
buf0 = buf0[:n-i]
}
- io.Copy(w, bytes.NewBuffer(buf0))
+ io.Copy(w, bytes.NewReader(buf0))
}
w.Close()
buf1 := compressed.Bytes()
@@ -63,7 +64,7 @@ func benchmarkDecode(b *testing.B, testfile, level, n int) {
runtime.GC()
b.StartTimer()
for i := 0; i < b.N; i++ {
- io.Copy(ioutil.Discard, NewReader(bytes.NewBuffer(buf1)))
+ io.Copy(ioutil.Discard, NewReader(bytes.NewReader(buf1)))
}
}
diff --git a/libgo/go/compress/gzip/gunzip_test.go b/libgo/go/compress/gzip/gunzip_test.go
index a1333580dc0..572fb584885 100644
--- a/libgo/go/compress/gzip/gunzip_test.go
+++ b/libgo/go/compress/gzip/gunzip_test.go
@@ -7,7 +7,10 @@ package gzip
import (
"bytes"
"io"
+ "io/ioutil"
+ "os"
"testing"
+ "time"
)
type gunzipTest struct {
@@ -302,3 +305,31 @@ func TestDecompressor(t *testing.T) {
}
}
}
+
+func TestIssue6550(t *testing.T) {
+ f, err := os.Open("testdata/issue6550.gz")
+ if err != nil {
+ t.Fatal(err)
+ }
+ gzip, err := NewReader(f)
+ if err != nil {
+ t.Fatalf("NewReader(testdata/issue6550.gz): %v", err)
+ }
+ defer gzip.Close()
+ done := make(chan bool, 1)
+ go func() {
+ _, err := io.Copy(ioutil.Discard, gzip)
+ if err == nil {
+ t.Errorf("Copy succeeded")
+ } else {
+ t.Logf("Copy failed (correctly): %v", err)
+ }
+ done <- true
+ }()
+ select {
+ case <-time.After(1 * time.Second):
+ t.Errorf("Copy hung")
+ case <-done:
+ // ok
+ }
+}
diff --git a/libgo/go/compress/gzip/gzip.go b/libgo/go/compress/gzip/gzip.go
index 45558b74289..fe32d6871ae 100644
--- a/libgo/go/compress/gzip/gzip.go
+++ b/libgo/go/compress/gzip/gzip.go
@@ -26,14 +26,15 @@ const (
// to its wrapped io.Writer.
type Writer struct {
Header
- w io.Writer
- level int
- compressor *flate.Writer
- digest hash.Hash32
- size uint32
- closed bool
- buf [10]byte
- err error
+ w io.Writer
+ level int
+ wroteHeader bool
+ compressor *flate.Writer
+ digest hash.Hash32
+ size uint32
+ closed bool
+ buf [10]byte
+ err error
}
// NewWriter creates a new Writer that satisfies writes by compressing data
@@ -62,14 +63,39 @@ func NewWriterLevel(w io.Writer, level int) (*Writer, error) {
if level < DefaultCompression || level > BestCompression {
return nil, fmt.Errorf("gzip: invalid compression level: %d", level)
}
- return &Writer{
+ z := new(Writer)
+ z.init(w, level)
+ return z, nil
+}
+
+func (z *Writer) init(w io.Writer, level int) {
+ digest := z.digest
+ if digest != nil {
+ digest.Reset()
+ } else {
+ digest = crc32.NewIEEE()
+ }
+ compressor := z.compressor
+ if compressor != nil {
+ compressor.Reset(w)
+ }
+ *z = Writer{
Header: Header{
OS: 255, // unknown
},
- w: w,
- level: level,
- digest: crc32.NewIEEE(),
- }, nil
+ w: w,
+ level: level,
+ digest: digest,
+ compressor: compressor,
+ }
+}
+
+// Reset discards the Writer z's state and makes it equivalent to the
+// result of its original state from NewWriter or NewWriterLevel, but
+// writing to w instead. This permits reusing a Writer rather than
+// allocating a new one.
+func (z *Writer) Reset(w io.Writer) {
+ z.init(w, z.level)
}
// GZIP (RFC 1952) is little-endian, unlike ZLIB (RFC 1950).
@@ -138,7 +164,8 @@ func (z *Writer) Write(p []byte) (int, error) {
}
var n int
// Write the GZIP header lazily.
- if z.compressor == nil {
+ if !z.wroteHeader {
+ z.wroteHeader = true
z.buf[0] = gzipID1
z.buf[1] = gzipID2
z.buf[2] = gzipDeflate
@@ -183,7 +210,9 @@ func (z *Writer) Write(p []byte) (int, error) {
return n, z.err
}
}
- z.compressor, _ = flate.NewWriter(z.w, z.level)
+ if z.compressor == nil {
+ z.compressor, _ = flate.NewWriter(z.w, z.level)
+ }
}
z.size += uint32(len(p))
z.digest.Write(p)
@@ -206,8 +235,11 @@ func (z *Writer) Flush() error {
if z.closed {
return nil
}
- if z.compressor == nil {
+ if !z.wroteHeader {
z.Write(nil)
+ if z.err != nil {
+ return z.err
+ }
}
z.err = z.compressor.Flush()
return z.err
@@ -222,7 +254,7 @@ func (z *Writer) Close() error {
return nil
}
z.closed = true
- if z.compressor == nil {
+ if !z.wroteHeader {
z.Write(nil)
if z.err != nil {
return z.err
diff --git a/libgo/go/compress/gzip/gzip_test.go b/libgo/go/compress/gzip/gzip_test.go
index 4d1af94381c..119be2e135b 100644
--- a/libgo/go/compress/gzip/gzip_test.go
+++ b/libgo/go/compress/gzip/gzip_test.go
@@ -197,3 +197,35 @@ func TestWriterFlush(t *testing.T) {
t.Fatal("Flush didn't flush any data")
}
}
+
+// Multiple gzip files concatenated form a valid gzip file.
+func TestConcat(t *testing.T) {
+ var buf bytes.Buffer
+ w := NewWriter(&buf)
+ w.Write([]byte("hello "))
+ w.Close()
+ w = NewWriter(&buf)
+ w.Write([]byte("world\n"))
+ w.Close()
+
+ r, err := NewReader(&buf)
+ data, err := ioutil.ReadAll(r)
+ if string(data) != "hello world\n" || err != nil {
+ t.Fatalf("ReadAll = %q, %v, want %q, nil", data, err, "hello world")
+ }
+}
+
+func TestWriterReset(t *testing.T) {
+ buf := new(bytes.Buffer)
+ buf2 := new(bytes.Buffer)
+ z := NewWriter(buf)
+ msg := []byte("hello world")
+ z.Write(msg)
+ z.Close()
+ z.Reset(buf2)
+ z.Write(msg)
+ z.Close()
+ if buf.String() != buf2.String() {
+ t.Errorf("buf2 %q != original buf of %q", buf2.String(), buf.String())
+ }
+}
diff --git a/libgo/go/compress/gzip/testdata/issue6550.gz b/libgo/go/compress/gzip/testdata/issue6550.gz
new file mode 100644
index 00000000000..57972b63668
--- /dev/null
+++ b/libgo/go/compress/gzip/testdata/issue6550.gz
Binary files differ
diff --git a/libgo/go/compress/zlib/writer.go b/libgo/go/compress/zlib/writer.go
index cd8dea460a4..99ff6549acb 100644
--- a/libgo/go/compress/zlib/writer.go
+++ b/libgo/go/compress/zlib/writer.go
@@ -70,6 +70,23 @@ func NewWriterLevelDict(w io.Writer, level int, dict []byte) (*Writer, error) {
}, nil
}
+// Reset clears the state of the Writer z such that it is equivalent to its
+// initial state from NewWriterLevel or NewWriterLevelDict, but instead writing
+// to w.
+func (z *Writer) Reset(w io.Writer) {
+ z.w = w
+ // z.level and z.dict left unchanged.
+ if z.compressor != nil {
+ z.compressor.Reset(w)
+ }
+ if z.digest != nil {
+ z.digest.Reset()
+ }
+ z.err = nil
+ z.scratch = [4]byte{}
+ z.wroteHeader = false
+}
+
// writeHeader writes the ZLIB header.
func (z *Writer) writeHeader() (err error) {
z.wroteHeader = true
@@ -111,11 +128,15 @@ func (z *Writer) writeHeader() (err error) {
return err
}
}
- z.compressor, err = flate.NewWriterDict(z.w, z.level, z.dict)
- if err != nil {
- return err
+ if z.compressor == nil {
+ // Initialize deflater unless the Writer is being reused
+ // after a Reset call.
+ z.compressor, err = flate.NewWriterDict(z.w, z.level, z.dict)
+ if err != nil {
+ return err
+ }
+ z.digest = adler32.New()
}
- z.digest = adler32.New()
return nil
}
diff --git a/libgo/go/compress/zlib/writer_test.go b/libgo/go/compress/zlib/writer_test.go
index aee1a5c2f54..cf9c8325455 100644
--- a/libgo/go/compress/zlib/writer_test.go
+++ b/libgo/go/compress/zlib/writer_test.go
@@ -89,6 +89,56 @@ func testLevelDict(t *testing.T, fn string, b0 []byte, level int, d string) {
}
}
+func testFileLevelDictReset(t *testing.T, fn string, level int, dict []byte) {
+ var b0 []byte
+ var err error
+ if fn != "" {
+ b0, err = ioutil.ReadFile(fn)
+ if err != nil {
+ t.Errorf("%s (level=%d): %v", fn, level, err)
+ return
+ }
+ }
+
+ // Compress once.
+ buf := new(bytes.Buffer)
+ var zlibw *Writer
+ if dict == nil {
+ zlibw, err = NewWriterLevel(buf, level)
+ } else {
+ zlibw, err = NewWriterLevelDict(buf, level, dict)
+ }
+ if err == nil {
+ _, err = zlibw.Write(b0)
+ }
+ if err == nil {
+ err = zlibw.Close()
+ }
+ if err != nil {
+ t.Errorf("%s (level=%d): %v", fn, level, err)
+ return
+ }
+ out := buf.String()
+
+ // Reset and comprses again.
+ buf2 := new(bytes.Buffer)
+ zlibw.Reset(buf2)
+ _, err = zlibw.Write(b0)
+ if err == nil {
+ err = zlibw.Close()
+ }
+ if err != nil {
+ t.Errorf("%s (level=%d): %v", fn, level, err)
+ return
+ }
+ out2 := buf2.String()
+
+ if out2 != out {
+ t.Errorf("%s (level=%d): different output after reset (got %d bytes, expected %d",
+ fn, level, len(out2), len(out))
+ }
+}
+
func TestWriter(t *testing.T) {
for i, s := range data {
b := []byte(s)
@@ -122,6 +172,21 @@ func TestWriterDict(t *testing.T) {
}
}
+func TestWriterReset(t *testing.T) {
+ const dictionary = "0123456789."
+ for _, fn := range filenames {
+ testFileLevelDictReset(t, fn, NoCompression, nil)
+ testFileLevelDictReset(t, fn, DefaultCompression, nil)
+ testFileLevelDictReset(t, fn, NoCompression, []byte(dictionary))
+ testFileLevelDictReset(t, fn, DefaultCompression, []byte(dictionary))
+ if !testing.Short() {
+ for level := BestSpeed; level <= BestCompression; level++ {
+ testFileLevelDictReset(t, fn, level, nil)
+ }
+ }
+ }
+}
+
func TestWriterDictIsUsed(t *testing.T) {
var input = []byte("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.")
var buf bytes.Buffer
diff --git a/libgo/go/container/heap/heap.go b/libgo/go/container/heap/heap.go
index c37e50e3c40..52c8507b421 100644
--- a/libgo/go/container/heap/heap.go
+++ b/libgo/go/container/heap/heap.go
@@ -6,6 +6,8 @@
// heap.Interface. A heap is a tree with the property that each node is the
// minimum-valued node in its subtree.
//
+// The minimum element in the tree is the root, at index 0.
+//
// A heap is a common way to implement a priority queue. To build a priority
// queue, implement the Heap interface with the (negative) priority as the
// ordering for the Less method, so Push adds items while Pop removes the
@@ -54,7 +56,7 @@ func Push(h Interface, x interface{}) {
// Pop removes the minimum element (according to Less) from the heap
// and returns it. The complexity is O(log(n)) where n = h.Len().
-// Same as Remove(h, 0).
+// It is equivalent to Remove(h, 0).
//
func Pop(h Interface) interface{} {
n := h.Len() - 1
@@ -76,6 +78,15 @@ func Remove(h Interface, i int) interface{} {
return h.Pop()
}
+// Fix reestablishes the heap ordering after the element at index i has changed its value.
+// Changing the value of the element at index i and then calling Fix is equivalent to,
+// but less expensive than, calling Remove(h, i) followed by a Push of the new value.
+// The complexity is O(log(n)) where n = h.Len().
+func Fix(h Interface, i int) {
+ down(h, i, h.Len())
+ up(h, i)
+}
+
func up(h Interface, j int) {
for {
i := (j - 1) / 2 // parent
diff --git a/libgo/go/container/heap/heap_test.go b/libgo/go/container/heap/heap_test.go
index 274d587d874..b3d054c5f39 100644
--- a/libgo/go/container/heap/heap_test.go
+++ b/libgo/go/container/heap/heap_test.go
@@ -5,6 +5,7 @@
package heap
import (
+ "math/rand"
"testing"
)
@@ -182,3 +183,31 @@ func BenchmarkDup(b *testing.B) {
}
}
}
+
+func TestFix(t *testing.T) {
+ h := new(myHeap)
+ h.verify(t, 0)
+
+ for i := 200; i > 0; i -= 10 {
+ Push(h, i)
+ }
+ h.verify(t, 0)
+
+ if (*h)[0] != 10 {
+ t.Fatalf("Expected head to be 10, was %d", (*h)[0])
+ }
+ (*h)[0] = 210
+ Fix(h, 0)
+ h.verify(t, 0)
+
+ for i := 100; i > 0; i-- {
+ elem := rand.Intn(h.Len())
+ if i&1 == 0 {
+ (*h)[elem] *= 2
+ } else {
+ (*h)[elem] /= 2
+ }
+ Fix(h, elem)
+ h.verify(t, 0)
+ }
+}
diff --git a/libgo/go/container/list/list.go b/libgo/go/container/list/list.go
index 562a5badbd3..ed2d15a4575 100755
--- a/libgo/go/container/list/list.go
+++ b/libgo/go/container/list/list.go
@@ -29,7 +29,7 @@ type Element struct {
// Next returns the next list element or nil.
func (e *Element) Next() *Element {
- if p := e.next; p != &e.list.root {
+ if p := e.next; e.list != nil && p != &e.list.root {
return p
}
return nil
@@ -37,7 +37,7 @@ func (e *Element) Next() *Element {
// Prev returns the previous list element or nil.
func (e *Element) Prev() *Element {
- if p := e.prev; p != &e.list.root {
+ if p := e.prev; e.list != nil && p != &e.list.root {
return p
}
return nil
@@ -62,6 +62,7 @@ func (l *List) Init() *List {
func New() *List { return new(List).Init() }
// Len returns the number of elements of list l.
+// The complexity is O(1).
func (l *List) Len() int { return l.len }
// Front returns the first element of list l or nil
@@ -126,7 +127,7 @@ func (l *List) Remove(e *Element) interface{} {
return e.Value
}
-// Pushfront inserts a new element e with value v at the front of list l and returns e.
+// PushFront inserts a new element e with value v at the front of list l and returns e.
func (l *List) PushFront(v interface{}) *Element {
l.lazyInit()
return l.insertValue(v, &l.root)
@@ -178,6 +179,24 @@ func (l *List) MoveToBack(e *Element) {
l.insert(l.remove(e), l.root.prev)
}
+// MoveBefore moves element e to its new position before mark.
+// If e is not an element of l, or e == mark, the list is not modified.
+func (l *List) MoveBefore(e, mark *Element) {
+ if e.list != l || e == mark {
+ return
+ }
+ l.insert(l.remove(e), mark.prev)
+}
+
+// MoveAfter moves element e to its new position after mark.
+// If e is not an element of l, or e == mark, the list is not modified.
+func (l *List) MoveAfter(e, mark *Element) {
+ if e.list != l || e == mark {
+ return
+ }
+ l.insert(l.remove(e), mark)
+}
+
// PushBackList inserts a copy of an other list at the back of list l.
// The lists l and other may be the same.
func (l *List) PushBackList(other *List) {
diff --git a/libgo/go/container/list/list_test.go b/libgo/go/container/list/list_test.go
index b4fc77d1403..ee52afe82b9 100755
--- a/libgo/go/container/list/list_test.go
+++ b/libgo/go/container/list/list_test.go
@@ -233,3 +233,55 @@ func TestIssue4103(t *testing.T) {
t.Errorf("l1.Len() = %d, want 3", n)
}
}
+
+func TestIssue6349(t *testing.T) {
+ l := New()
+ l.PushBack(1)
+ l.PushBack(2)
+
+ e := l.Front()
+ l.Remove(e)
+ if e.Value != 1 {
+ t.Errorf("e.value = %d, want 1", e.Value)
+ }
+ if e.Next() != nil {
+ t.Errorf("e.Next() != nil")
+ }
+ if e.Prev() != nil {
+ t.Errorf("e.Prev() != nil")
+ }
+}
+
+func TestMove(t *testing.T) {
+ l := New()
+ e1 := l.PushBack(1)
+ e2 := l.PushBack(2)
+ e3 := l.PushBack(3)
+ e4 := l.PushBack(4)
+
+ l.MoveAfter(e3, e3)
+ checkListPointers(t, l, []*Element{e1, e2, e3, e4})
+ l.MoveBefore(e2, e2)
+ checkListPointers(t, l, []*Element{e1, e2, e3, e4})
+
+ l.MoveAfter(e3, e2)
+ checkListPointers(t, l, []*Element{e1, e2, e3, e4})
+ l.MoveBefore(e2, e3)
+ checkListPointers(t, l, []*Element{e1, e2, e3, e4})
+
+ l.MoveBefore(e2, e4)
+ checkListPointers(t, l, []*Element{e1, e3, e2, e4})
+ e1, e2, e3, e4 = e1, e3, e2, e4
+
+ l.MoveBefore(e4, e1)
+ checkListPointers(t, l, []*Element{e4, e1, e2, e3})
+ e1, e2, e3, e4 = e4, e1, e2, e3
+
+ l.MoveAfter(e4, e1)
+ checkListPointers(t, l, []*Element{e1, e4, e2, e3})
+ e1, e2, e3, e4 = e1, e4, e2, e3
+
+ l.MoveAfter(e2, e3)
+ checkListPointers(t, l, []*Element{e1, e3, e2, e4})
+ e1, e2, e3, e4 = e1, e3, e2, e4
+}
diff --git a/libgo/go/crypto/cipher/cbc.go b/libgo/go/crypto/cipher/cbc.go
index 913a5643f22..4189677e390 100644
--- a/libgo/go/crypto/cipher/cbc.go
+++ b/libgo/go/crypto/cipher/cbc.go
@@ -61,6 +61,13 @@ func (x *cbcEncrypter) CryptBlocks(dst, src []byte) {
}
}
+func (x *cbcEncrypter) SetIV(iv []byte) {
+ if len(iv) != len(x.iv) {
+ panic("cipher: incorrect length IV")
+ }
+ copy(x.iv, iv)
+}
+
type cbcDecrypter cbc
// NewCBCDecrypter returns a BlockMode which decrypts in cipher block chaining
@@ -94,3 +101,10 @@ func (x *cbcDecrypter) CryptBlocks(dst, src []byte) {
dst = dst[x.blockSize:]
}
}
+
+func (x *cbcDecrypter) SetIV(iv []byte) {
+ if len(iv) != len(x.iv) {
+ panic("cipher: incorrect length IV")
+ }
+ copy(x.iv, iv)
+}
diff --git a/libgo/go/crypto/cipher/gcm.go b/libgo/go/crypto/cipher/gcm.go
new file mode 100644
index 00000000000..2bcb469852b
--- /dev/null
+++ b/libgo/go/crypto/cipher/gcm.go
@@ -0,0 +1,350 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package cipher
+
+import (
+ "crypto/subtle"
+ "errors"
+)
+
+// AEAD is a cipher mode providing authenticated encryption with associated
+// data.
+type AEAD interface {
+ // NonceSize returns the size of the nonce that must be passed to Seal
+ // and Open.
+ NonceSize() int
+
+ // Overhead returns the maximum difference between the lengths of a
+ // plaintext and ciphertext.
+ Overhead() int
+
+ // Seal encrypts and authenticates plaintext, authenticates the
+ // additional data and appends the result to dst, returning the updated
+ // slice. The nonce must be NonceSize() bytes long and unique for all
+ // time, for a given key.
+ //
+ // The plaintext and dst may alias exactly or not at all.
+ Seal(dst, nonce, plaintext, data []byte) []byte
+
+ // Open decrypts and authenticates ciphertext, authenticates the
+ // additional data and, if successful, appends the resulting plaintext
+ // to dst, returning the updated slice and true. On error, nil and
+ // false is returned. The nonce must be NonceSize() bytes long and both
+ // it and the additional data must match the value passed to Seal.
+ //
+ // The ciphertext and dst may alias exactly or not at all.
+ Open(dst, nonce, ciphertext, data []byte) ([]byte, error)
+}
+
+// gcmFieldElement represents a value in GF(2¹²â¸). In order to reflect the GCM
+// standard and make getUint64 suitable for marshaling these values, the bits
+// are stored backwards. For example:
+// the coefficient of xâ° can be obtained by v.low >> 63.
+// the coefficient of xâ¶Â³ can be obtained by v.low & 1.
+// the coefficient of xâ¶â´ can be obtained by v.high >> 63.
+// the coefficient of x¹²ⷠcan be obtained by v.high & 1.
+type gcmFieldElement struct {
+ low, high uint64
+}
+
+// gcm represents a Galois Counter Mode with a specific key. See
+// http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf
+type gcm struct {
+ cipher Block
+ // productTable contains the first sixteen powers of the key, H.
+ // However, they are in bit reversed order. See NewGCM.
+ productTable [16]gcmFieldElement
+}
+
+// NewGCM returns the given 128-bit, block cipher wrapped in Galois Counter Mode.
+func NewGCM(cipher Block) (AEAD, error) {
+ if cipher.BlockSize() != gcmBlockSize {
+ return nil, errors.New("cipher: NewGCM requires 128-bit block cipher")
+ }
+
+ var key [gcmBlockSize]byte
+ cipher.Encrypt(key[:], key[:])
+
+ g := &gcm{cipher: cipher}
+
+ // We precompute 16 multiples of |key|. However, when we do lookups
+ // into this table we'll be using bits from a field element and
+ // therefore the bits will be in the reverse order. So normally one
+ // would expect, say, 4*key to be in index 4 of the table but due to
+ // this bit ordering it will actually be in index 0010 (base 2) = 2.
+ x := gcmFieldElement{
+ getUint64(key[:8]),
+ getUint64(key[8:]),
+ }
+ g.productTable[reverseBits(1)] = x
+
+ for i := 2; i < 16; i += 2 {
+ g.productTable[reverseBits(i)] = gcmDouble(&g.productTable[reverseBits(i/2)])
+ g.productTable[reverseBits(i+1)] = gcmAdd(&g.productTable[reverseBits(i)], &x)
+ }
+
+ return g, nil
+}
+
+const (
+ gcmBlockSize = 16
+ gcmTagSize = 16
+ gcmNonceSize = 12
+)
+
+func (*gcm) NonceSize() int {
+ return gcmNonceSize
+}
+
+func (*gcm) Overhead() int {
+ return gcmTagSize
+}
+
+func (g *gcm) Seal(dst, nonce, plaintext, data []byte) []byte {
+ if len(nonce) != gcmNonceSize {
+ panic("cipher: incorrect nonce length given to GCM")
+ }
+
+ ret, out := sliceForAppend(dst, len(plaintext)+gcmTagSize)
+
+ // See GCM spec, section 7.1.
+ var counter, tagMask [gcmBlockSize]byte
+ copy(counter[:], nonce)
+ counter[gcmBlockSize-1] = 1
+
+ g.cipher.Encrypt(tagMask[:], counter[:])
+ gcmInc32(&counter)
+
+ g.counterCrypt(out, plaintext, &counter)
+ g.auth(out[len(plaintext):], out[:len(plaintext)], data, &tagMask)
+
+ return ret
+}
+
+var errOpen = errors.New("cipher: message authentication failed")
+
+func (g *gcm) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) {
+ if len(nonce) != gcmNonceSize {
+ panic("cipher: incorrect nonce length given to GCM")
+ }
+
+ if len(ciphertext) < gcmTagSize {
+ return nil, errOpen
+ }
+ tag := ciphertext[len(ciphertext)-gcmTagSize:]
+ ciphertext = ciphertext[:len(ciphertext)-gcmTagSize]
+
+ // See GCM spec, section 7.1.
+ var counter, tagMask [gcmBlockSize]byte
+ copy(counter[:], nonce)
+ counter[gcmBlockSize-1] = 1
+
+ g.cipher.Encrypt(tagMask[:], counter[:])
+ gcmInc32(&counter)
+
+ var expectedTag [gcmTagSize]byte
+ g.auth(expectedTag[:], ciphertext, data, &tagMask)
+
+ if subtle.ConstantTimeCompare(expectedTag[:], tag) != 1 {
+ return nil, errOpen
+ }
+
+ ret, out := sliceForAppend(dst, len(ciphertext))
+ g.counterCrypt(out, ciphertext, &counter)
+
+ return ret, nil
+}
+
+// reverseBits reverses the order of the bits of 4-bit number in i.
+func reverseBits(i int) int {
+ i = ((i << 2) & 0xc) | ((i >> 2) & 0x3)
+ i = ((i << 1) & 0xa) | ((i >> 1) & 0x5)
+ return i
+}
+
+// gcmAdd adds two elements of GF(2¹²â¸) and returns the sum.
+func gcmAdd(x, y *gcmFieldElement) gcmFieldElement {
+ // Addition in a characteristic 2 field is just XOR.
+ return gcmFieldElement{x.low ^ y.low, x.high ^ y.high}
+}
+
+// gcmDouble returns the result of doubling an element of GF(2¹²â¸).
+func gcmDouble(x *gcmFieldElement) (double gcmFieldElement) {
+ msbSet := x.high&1 == 1
+
+ // Because of the bit-ordering, doubling is actually a right shift.
+ double.high = x.high >> 1
+ double.high |= x.low << 63
+ double.low = x.low >> 1
+
+ // If the most-significant bit was set before shifting then it,
+ // conceptually, becomes a term of x^128. This is greater than the
+ // irreducible polynomial so the result has to be reduced. The
+ // irreducible polynomial is 1+x+x^2+x^7+x^128. We can subtract that to
+ // eliminate the term at x^128 which also means subtracting the other
+ // four terms. In characteristic 2 fields, subtraction == addition ==
+ // XOR.
+ if msbSet {
+ double.low ^= 0xe100000000000000
+ }
+
+ return
+}
+
+var gcmReductionTable = []uint16{
+ 0x0000, 0x1c20, 0x3840, 0x2460, 0x7080, 0x6ca0, 0x48c0, 0x54e0,
+ 0xe100, 0xfd20, 0xd940, 0xc560, 0x9180, 0x8da0, 0xa9c0, 0xb5e0,
+}
+
+// mul sets y to y*H, where H is the GCM key, fixed during NewGCM.
+func (g *gcm) mul(y *gcmFieldElement) {
+ var z gcmFieldElement
+
+ for i := 0; i < 2; i++ {
+ word := y.high
+ if i == 1 {
+ word = y.low
+ }
+
+ // Multiplication works by multiplying z by 16 and adding in
+ // one of the precomputed multiples of H.
+ for j := 0; j < 64; j += 4 {
+ msw := z.high & 0xf
+ z.high >>= 4
+ z.high |= z.low << 60
+ z.low >>= 4
+ z.low ^= uint64(gcmReductionTable[msw]) << 48
+
+ // the values in |table| are ordered for
+ // little-endian bit positions. See the comment
+ // in NewGCM.
+ t := &g.productTable[word&0xf]
+
+ z.low ^= t.low
+ z.high ^= t.high
+ word >>= 4
+ }
+ }
+
+ *y = z
+}
+
+// updateBlocks extends y with more polynomial terms from blocks, based on
+// Horner's rule. There must be a multiple of gcmBlockSize bytes in blocks.
+func (g *gcm) updateBlocks(y *gcmFieldElement, blocks []byte) {
+ for len(blocks) > 0 {
+ y.low ^= getUint64(blocks)
+ y.high ^= getUint64(blocks[8:])
+ g.mul(y)
+ blocks = blocks[gcmBlockSize:]
+ }
+}
+
+// update extends y with more polynomial terms from data. If data is not a
+// multiple of gcmBlockSize bytes long then the remainder is zero padded.
+func (g *gcm) update(y *gcmFieldElement, data []byte) {
+ fullBlocks := (len(data) >> 4) << 4
+ g.updateBlocks(y, data[:fullBlocks])
+
+ if len(data) != fullBlocks {
+ var partialBlock [gcmBlockSize]byte
+ copy(partialBlock[:], data[fullBlocks:])
+ g.updateBlocks(y, partialBlock[:])
+ }
+}
+
+// gcmInc32 treats the final four bytes of counterBlock as a big-endian value
+// and increments it.
+func gcmInc32(counterBlock *[16]byte) {
+ c := 1
+ for i := gcmBlockSize - 1; i >= gcmBlockSize-4; i-- {
+ c += int(counterBlock[i])
+ counterBlock[i] = byte(c)
+ c >>= 8
+ }
+}
+
+// sliceForAppend takes a slice and a requested number of bytes. It returns a
+// slice with the contents of the given slice followed by that many bytes and a
+// second slice that aliases into it and contains only the extra bytes. If the
+// original slice has sufficient capacity then no allocation is performed.
+func sliceForAppend(in []byte, n int) (head, tail []byte) {
+ if total := len(in) + n; cap(in) >= total {
+ head = in[:total]
+ } else {
+ head = make([]byte, total)
+ copy(head, in)
+ }
+ tail = head[len(in):]
+ return
+}
+
+// counterCrypt crypts in to out using g.cipher in counter mode.
+func (g *gcm) counterCrypt(out, in []byte, counter *[gcmBlockSize]byte) {
+ var mask [gcmBlockSize]byte
+
+ for len(in) >= gcmBlockSize {
+ g.cipher.Encrypt(mask[:], counter[:])
+ gcmInc32(counter)
+
+ for i := range mask {
+ out[i] = in[i] ^ mask[i]
+ }
+ out = out[gcmBlockSize:]
+ in = in[gcmBlockSize:]
+ }
+
+ if len(in) > 0 {
+ g.cipher.Encrypt(mask[:], counter[:])
+ gcmInc32(counter)
+
+ for i := range in {
+ out[i] = in[i] ^ mask[i]
+ }
+ }
+}
+
+// auth calculates GHASH(ciphertext, additionalData), masks the result with
+// tagMask and writes the result to out.
+func (g *gcm) auth(out, ciphertext, additionalData []byte, tagMask *[gcmTagSize]byte) {
+ var y gcmFieldElement
+ g.update(&y, additionalData)
+ g.update(&y, ciphertext)
+
+ y.low ^= uint64(len(additionalData)) * 8
+ y.high ^= uint64(len(ciphertext)) * 8
+
+ g.mul(&y)
+
+ putUint64(out, y.low)
+ putUint64(out[8:], y.high)
+
+ for i := range tagMask {
+ out[i] ^= tagMask[i]
+ }
+}
+
+func getUint64(data []byte) uint64 {
+ r := uint64(data[0])<<56 |
+ uint64(data[1])<<48 |
+ uint64(data[2])<<40 |
+ uint64(data[3])<<32 |
+ uint64(data[4])<<24 |
+ uint64(data[5])<<16 |
+ uint64(data[6])<<8 |
+ uint64(data[7])
+ return r
+}
+
+func putUint64(out []byte, v uint64) {
+ out[0] = byte(v >> 56)
+ out[1] = byte(v >> 48)
+ out[2] = byte(v >> 40)
+ out[3] = byte(v >> 32)
+ out[4] = byte(v >> 24)
+ out[5] = byte(v >> 16)
+ out[6] = byte(v >> 8)
+ out[7] = byte(v)
+}
diff --git a/libgo/go/crypto/cipher/gcm_test.go b/libgo/go/crypto/cipher/gcm_test.go
new file mode 100644
index 00000000000..02d42159006
--- /dev/null
+++ b/libgo/go/crypto/cipher/gcm_test.go
@@ -0,0 +1,175 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package cipher_test
+
+import (
+ "bytes"
+ "crypto/aes"
+ "crypto/cipher"
+ "encoding/hex"
+ "testing"
+)
+
+// AES-GCM test vectors taken from gcmEncryptExtIV128.rsp from
+// http://csrc.nist.gov/groups/STM/cavp/index.html.
+var aesGCMTests = []struct {
+ key, nonce, plaintext, ad, result string
+}{
+ {
+ "11754cd72aec309bf52f7687212e8957",
+ "3c819d9a9bed087615030b65",
+ "",
+ "",
+ "250327c674aaf477aef2675748cf6971",
+ },
+ {
+ "ca47248ac0b6f8372a97ac43508308ed",
+ "ffd2b598feabc9019262d2be",
+ "",
+ "",
+ "60d20404af527d248d893ae495707d1a",
+ },
+ {
+ "77be63708971c4e240d1cb79e8d77feb",
+ "e0e00f19fed7ba0136a797f3",
+ "",
+ "7a43ec1d9c0a5a78a0b16533a6213cab",
+ "209fcc8d3675ed938e9c7166709dd946",
+ },
+ {
+ "7680c5d3ca6154758e510f4d25b98820",
+ "f8f105f9c3df4965780321f8",
+ "",
+ "c94c410194c765e3dcc7964379758ed3",
+ "94dca8edfcf90bb74b153c8d48a17930",
+ },
+ {
+ "7fddb57453c241d03efbed3ac44e371c",
+ "ee283a3fc75575e33efd4887",
+ "d5de42b461646c255c87bd2962d3b9a2",
+ "",
+ "2ccda4a5415cb91e135c2a0f78c9b2fdb36d1df9b9d5e596f83e8b7f52971cb3",
+ },
+ {
+ "ab72c77b97cb5fe9a382d9fe81ffdbed",
+ "54cc7dc2c37ec006bcc6d1da",
+ "007c5e5b3e59df24a7c355584fc1518d",
+ "",
+ "0e1bde206a07a9c2c1b65300f8c649972b4401346697138c7a4891ee59867d0c",
+ },
+ {
+ "fe47fcce5fc32665d2ae399e4eec72ba",
+ "5adb9609dbaeb58cbd6e7275",
+ "7c0e88c88899a779228465074797cd4c2e1498d259b54390b85e3eef1c02df60e743f1b840382c4bccaf3bafb4ca8429bea063",
+ "88319d6e1d3ffa5f987199166c8a9b56c2aeba5a",
+ "98f4826f05a265e6dd2be82db241c0fbbbf9ffb1c173aa83964b7cf5393043736365253ddbc5db8778371495da76d269e5db3e291ef1982e4defedaa2249f898556b47",
+ },
+ {
+ "ec0c2ba17aa95cd6afffe949da9cc3a8",
+ "296bce5b50b7d66096d627ef",
+ "b85b3753535b825cbe5f632c0b843c741351f18aa484281aebec2f45bb9eea2d79d987b764b9611f6c0f8641843d5d58f3a242",
+ "f8d00f05d22bf68599bcdeb131292ad6e2df5d14",
+ "a7443d31c26bdf2a1c945e29ee4bd344a99cfaf3aa71f8b3f191f83c2adfc7a07162995506fde6309ffc19e716eddf1a828c5a890147971946b627c40016da1ecf3e77",
+ },
+ {
+ "2c1f21cf0f6fb3661943155c3e3d8492",
+ "23cb5ff362e22426984d1907",
+ "42f758836986954db44bf37c6ef5e4ac0adaf38f27252a1b82d02ea949c8a1a2dbc0d68b5615ba7c1220ff6510e259f06655d8",
+ "5d3624879d35e46849953e45a32a624d6a6c536ed9857c613b572b0333e701557a713e3f010ecdf9a6bd6c9e3e44b065208645aff4aabee611b391528514170084ccf587177f4488f33cfb5e979e42b6e1cfc0a60238982a7aec",
+ "81824f0e0d523db30d3da369fdc0d60894c7a0a20646dd015073ad2732bd989b14a222b6ad57af43e1895df9dca2a5344a62cc57a3ee28136e94c74838997ae9823f3a",
+ },
+ {
+ "d9f7d2411091f947b4d6f1e2d1f0fb2e",
+ "e1934f5db57cc983e6b180e7",
+ "73ed042327f70fe9c572a61545eda8b2a0c6e1d6c291ef19248e973aee6c312012f490c2c6f6166f4a59431e182663fcaea05a",
+ "0a8a18a7150e940c3d87b38e73baee9a5c049ee21795663e264b694a949822b639092d0e67015e86363583fcf0ca645af9f43375f05fdb4ce84f411dcbca73c2220dea03a20115d2e51398344b16bee1ed7c499b353d6c597af8",
+ "aaadbd5c92e9151ce3db7210b8714126b73e43436d242677afa50384f2149b831f1d573c7891c2a91fbc48db29967ec9542b2321b51ca862cb637cdd03b99a0f93b134",
+ },
+ {
+ "fe9bb47deb3a61e423c2231841cfd1fb",
+ "4d328eb776f500a2f7fb47aa",
+ "f1cc3818e421876bb6b8bbd6c9",
+ "",
+ "b88c5c1977b35b517b0aeae96743fd4727fe5cdb4b5b42818dea7ef8c9",
+ },
+ {
+ "6703df3701a7f54911ca72e24dca046a",
+ "12823ab601c350ea4bc2488c",
+ "793cd125b0b84a043e3ac67717",
+ "",
+ "b2051c80014f42f08735a7b0cd38e6bcd29962e5f2c13626b85a877101",
+ },
+}
+
+func TestAESGCM(t *testing.T) {
+ for i, test := range aesGCMTests {
+ key, _ := hex.DecodeString(test.key)
+ aes, err := aes.NewCipher(key)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ nonce, _ := hex.DecodeString(test.nonce)
+ plaintext, _ := hex.DecodeString(test.plaintext)
+ ad, _ := hex.DecodeString(test.ad)
+ aesgcm, err := cipher.NewGCM(aes)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ ct := aesgcm.Seal(nil, nonce, plaintext, ad)
+ if ctHex := hex.EncodeToString(ct); ctHex != test.result {
+ t.Errorf("#%d: got %s, want %s", i, ctHex, test.result)
+ continue
+ }
+
+ plaintext2, err := aesgcm.Open(nil, nonce, ct, ad)
+ if err != nil {
+ t.Errorf("#%d: Open failed", i)
+ continue
+ }
+
+ if !bytes.Equal(plaintext, plaintext2) {
+ t.Errorf("#%d: plaintext's don't match: got %x vs %x", i, plaintext2, plaintext)
+ continue
+ }
+
+ if len(ad) > 0 {
+ ad[0] ^= 0x80
+ if _, err := aesgcm.Open(nil, nonce, ct, ad); err == nil {
+ t.Errorf("#%d: Open was successful after altering additional data", i)
+ }
+ ad[0] ^= 0x80
+ }
+
+ nonce[0] ^= 0x80
+ if _, err := aesgcm.Open(nil, nonce, ct, ad); err == nil {
+ t.Errorf("#%d: Open was successful after altering nonce", i)
+ }
+ nonce[0] ^= 0x80
+
+ ct[0] ^= 0x80
+ if _, err := aesgcm.Open(nil, nonce, ct, ad); err == nil {
+ t.Errorf("#%d: Open was successful after altering ciphertext", i)
+ }
+ ct[0] ^= 0x80
+ }
+}
+
+func BenchmarkAESGCM(b *testing.B) {
+ buf := make([]byte, 1024)
+ b.SetBytes(int64(len(buf)))
+
+ var key [16]byte
+ var nonce [12]byte
+ aes, _ := aes.NewCipher(key[:])
+ aesgcm, _ := cipher.NewGCM(aes)
+ var out []byte
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ out = aesgcm.Seal(out[:0], nonce[:], buf, nonce[:])
+ }
+}
diff --git a/libgo/go/crypto/cipher/io.go b/libgo/go/crypto/cipher/io.go
index 807e8daeaf4..3938c0a4c88 100644
--- a/libgo/go/crypto/cipher/io.go
+++ b/libgo/go/crypto/cipher/io.go
@@ -25,6 +25,8 @@ func (r StreamReader) Read(dst []byte) (n int, err error) {
// StreamWriter wraps a Stream into an io.Writer. It calls XORKeyStream
// to process each slice of data which passes through. If any Write call
// returns short then the StreamWriter is out of sync and must be discarded.
+// A StreamWriter has no internal buffering; Close does not need
+// to be called to flush write data.
type StreamWriter struct {
S Stream
W io.Writer
@@ -43,8 +45,11 @@ func (w StreamWriter) Write(src []byte) (n int, err error) {
return
}
+// Close closes the underlying Writer and returns its Close return value, if the Writer
+// is also an io.Closer. Otherwise it returns nil.
func (w StreamWriter) Close() error {
- // This saves us from either requiring a WriteCloser or having a
- // StreamWriterCloser.
- return w.W.(io.Closer).Close()
+ if c, ok := w.W.(io.Closer); ok {
+ return c.Close()
+ }
+ return nil
}
diff --git a/libgo/go/crypto/crypto.go b/libgo/go/crypto/crypto.go
index ecefc657254..4b03628e692 100644
--- a/libgo/go/crypto/crypto.go
+++ b/libgo/go/crypto/crypto.go
@@ -7,6 +7,7 @@ package crypto
import (
"hash"
+ "strconv"
)
// Hash identifies a cryptographic hash function that is implemented in another
@@ -59,7 +60,7 @@ func (h Hash) New() hash.Hash {
return f()
}
}
- panic("crypto: requested hash function is unavailable")
+ panic("crypto: requested hash function #" + strconv.Itoa(int(h)) + " is unavailable")
}
// Available reports whether the given hash function is linked into the binary.
@@ -77,5 +78,8 @@ func RegisterHash(h Hash, f func() hash.Hash) {
hashes[h] = f
}
+// PublicKey represents a public key using an unspecified algorithm.
+type PublicKey interface{}
+
// PrivateKey represents a private key using an unspecified algorithm.
type PrivateKey interface{}
diff --git a/libgo/go/crypto/des/block.go b/libgo/go/crypto/des/block.go
index c11c62cd723..26355a22e71 100644
--- a/libgo/go/crypto/des/block.go
+++ b/libgo/go/crypto/des/block.go
@@ -10,7 +10,7 @@ import (
func cryptBlock(subkeys []uint64, dst, src []byte, decrypt bool) {
b := binary.BigEndian.Uint64(src)
- b = permuteBlock(b, initialPermutation[:])
+ b = permuteInitialBlock(b)
left, right := uint32(b>>32), uint32(b)
var subkey uint64
@@ -25,7 +25,7 @@ func cryptBlock(subkeys []uint64, dst, src []byte, decrypt bool) {
}
// switch left & right and perform final permutation
preOutput := (uint64(right) << 32) | uint64(left)
- binary.BigEndian.PutUint64(dst, permuteBlock(preOutput, finalPermutation[:]))
+ binary.BigEndian.PutUint64(dst, permuteFinalBlock(preOutput))
}
// Encrypt one block from src into dst, using the subkeys.
@@ -40,20 +40,24 @@ func decryptBlock(subkeys []uint64, dst, src []byte) {
// DES Feistel function
func feistel(right uint32, key uint64) (result uint32) {
- sBoxLocations := key ^ permuteBlock(uint64(right), expansionFunction[:])
+ sBoxLocations := key ^ expandBlock(right)
var sBoxResult uint32
for i := uint8(0); i < 8; i++ {
sBoxLocation := uint8(sBoxLocations>>42) & 0x3f
sBoxLocations <<= 6
// row determined by 1st and 6th bit
- row := (sBoxLocation & 0x1) | ((sBoxLocation & 0x20) >> 4)
// column is middle four bits
+ row := (sBoxLocation & 0x1) | ((sBoxLocation & 0x20) >> 4)
column := (sBoxLocation >> 1) & 0xf
- sBoxResult |= uint32(sBoxes[i][row][column]) << (4 * (7 - i))
+ sBoxResult ^= feistelBox[i][16*row+column]
}
- return uint32(permuteBlock(uint64(sBoxResult), permutationFunction[:]))
+ return sBoxResult
}
+// feistelBox[s][16*i+j] contains the output of permutationFunction
+// for sBoxes[s][i][j] << 4*(7-s)
+var feistelBox [8][64]uint32
+
// general purpose function to perform DES block permutations
func permuteBlock(src uint64, permutation []uint8) (block uint64) {
for position, n := range permutation {
@@ -63,6 +67,127 @@ func permuteBlock(src uint64, permutation []uint8) (block uint64) {
return
}
+func init() {
+ for s := range sBoxes {
+ for i := 0; i < 4; i++ {
+ for j := 0; j < 16; j++ {
+ f := uint64(sBoxes[s][i][j]) << (4 * (7 - uint(s)))
+ f = permuteBlock(uint64(f), permutationFunction[:])
+ feistelBox[s][16*i+j] = uint32(f)
+ }
+ }
+ }
+}
+
+// expandBlock expands an input block of 32 bits,
+// producing an output block of 48 bits.
+func expandBlock(src uint32) (block uint64) {
+ // rotate the 5 highest bits to the right.
+ src = (src << 5) | (src >> 27)
+ for i := 0; i < 8; i++ {
+ block <<= 6
+ // take the 6 bits on the right
+ block |= uint64(src) & (1<<6 - 1)
+ // advance by 4 bits.
+ src = (src << 4) | (src >> 28)
+ }
+ return
+}
+
+// permuteInitialBlock is equivalent to the permutation defined
+// by initialPermutation.
+func permuteInitialBlock(block uint64) uint64 {
+ // block = b7 b6 b5 b4 b3 b2 b1 b0 (8 bytes)
+ b1 := block >> 48
+ b2 := block << 48
+ block ^= b1 ^ b2 ^ b1<<48 ^ b2>>48
+
+ // block = b1 b0 b5 b4 b3 b2 b7 b6
+ b1 = block >> 32 & 0xff00ff
+ b2 = (block & 0xff00ff00)
+ block ^= b1<<32 ^ b2 ^ b1<<8 ^ b2<<24 // exchange b0 b4 with b3 b7
+
+ // block is now b1 b3 b5 b7 b0 b2 b4 b7, the permutation:
+ // ... 8
+ // ... 24
+ // ... 40
+ // ... 56
+ // 7 6 5 4 3 2 1 0
+ // 23 22 21 20 19 18 17 16
+ // ... 32
+ // ... 48
+
+ // exchange 4,5,6,7 with 32,33,34,35 etc.
+ b1 = block & 0x0f0f00000f0f0000
+ b2 = block & 0x0000f0f00000f0f0
+ block ^= b1 ^ b2 ^ b1>>12 ^ b2<<12
+
+ // block is the permutation:
+ //
+ // [+8] [+40]
+ //
+ // 7 6 5 4
+ // 23 22 21 20
+ // 3 2 1 0
+ // 19 18 17 16 [+32]
+
+ // exchange 0,1,4,5 with 18,19,22,23
+ b1 = block & 0x3300330033003300
+ b2 = block & 0x00cc00cc00cc00cc
+ block ^= b1 ^ b2 ^ b1>>6 ^ b2<<6
+
+ // block is the permutation:
+ // 15 14
+ // 13 12
+ // 11 10
+ // 9 8
+ // 7 6
+ // 5 4
+ // 3 2
+ // 1 0 [+16] [+32] [+64]
+
+ // exchange 0,2,4,6 with 9,11,13,15:
+ b1 = block & 0xaaaaaaaa55555555
+ block ^= b1 ^ b1>>33 ^ b1<<33
+
+ // block is the permutation:
+ // 6 14 22 30 38 46 54 62
+ // 4 12 20 28 36 44 52 60
+ // 2 10 18 26 34 42 50 58
+ // 0 8 16 24 32 40 48 56
+ // 7 15 23 31 39 47 55 63
+ // 5 13 21 29 37 45 53 61
+ // 3 11 19 27 35 43 51 59
+ // 1 9 17 25 33 41 49 57
+ return block
+}
+
+// permuteInitialBlock is equivalent to the permutation defined
+// by finalPermutation.
+func permuteFinalBlock(block uint64) uint64 {
+ // Perform the same bit exchanges as permuteInitialBlock
+ // but in reverse order.
+ b1 := block & 0xaaaaaaaa55555555
+ block ^= b1 ^ b1>>33 ^ b1<<33
+
+ b1 = block & 0x3300330033003300
+ b2 := block & 0x00cc00cc00cc00cc
+ block ^= b1 ^ b2 ^ b1>>6 ^ b2<<6
+
+ b1 = block & 0x0f0f00000f0f0000
+ b2 = block & 0x0000f0f00000f0f0
+ block ^= b1 ^ b2 ^ b1>>12 ^ b2<<12
+
+ b1 = block >> 32 & 0xff00ff
+ b2 = (block & 0xff00ff00)
+ block ^= b1<<32 ^ b2 ^ b1<<8 ^ b2<<24
+
+ b1 = block >> 48
+ b2 = block << 48
+ block ^= b1 ^ b2 ^ b1<<48 ^ b2>>48
+ return block
+}
+
// creates 16 28-bit blocks rotated according
// to the rotation schedule
func ksRotate(in uint32) (out []uint32) {
diff --git a/libgo/go/crypto/des/des_test.go b/libgo/go/crypto/des/des_test.go
index 2e87e99b67f..2bd525afecc 100644
--- a/libgo/go/crypto/des/des_test.go
+++ b/libgo/go/crypto/des/des_test.go
@@ -1504,20 +1504,63 @@ func TestSubstitutionTableKnownAnswerDecrypt(t *testing.T) {
}
}
-func ExampleNewTripleDESCipher() {
- // NewTripleDESCipher can also be used when EDE2 is required by
- // duplicating the first 8 bytes of the 16-byte key.
- ede2Key := []byte("example key 1234")
+func TestInitialPermute(t *testing.T) {
+ for i := uint(0); i < 64; i++ {
+ bit := uint64(1) << i
+ got := permuteInitialBlock(bit)
+ want := uint64(1) << finalPermutation[63-i]
+ if got != want {
+ t.Errorf("permute(%x) = %x, want %x", bit, got, want)
+ }
+ }
+}
- var tripleDESKey []byte
- tripleDESKey = append(tripleDESKey, ede2Key[:16]...)
- tripleDESKey = append(tripleDESKey, ede2Key[:8]...)
+func TestFinalPermute(t *testing.T) {
+ for i := uint(0); i < 64; i++ {
+ bit := uint64(1) << i
+ got := permuteFinalBlock(bit)
+ want := uint64(1) << initialPermutation[63-i]
+ if got != want {
+ t.Errorf("permute(%x) = %x, want %x", bit, got, want)
+ }
+ }
+}
- _, err := NewTripleDESCipher(tripleDESKey)
+func TestExpandBlock(t *testing.T) {
+ for i := uint(0); i < 32; i++ {
+ bit := uint32(1) << i
+ got := expandBlock(bit)
+ want := permuteBlock(uint64(bit), expansionFunction[:])
+ if got != want {
+ t.Errorf("expand(%x) = %x, want %x", bit, got, want)
+ }
+ }
+}
+
+func BenchmarkEncrypt(b *testing.B) {
+ tt := encryptDESTests[0]
+ c, err := NewCipher(tt.key)
if err != nil {
- panic(err)
+ b.Fatal("NewCipher:", err)
+ }
+ out := make([]byte, len(tt.in))
+ b.SetBytes(int64(len(out)))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ c.Encrypt(out, tt.in)
}
+}
- // See crypto/cipher for how to use a cipher.Block for encryption and
- // decryption.
+func BenchmarkDecrypt(b *testing.B) {
+ tt := encryptDESTests[0]
+ c, err := NewCipher(tt.key)
+ if err != nil {
+ b.Fatal("NewCipher:", err)
+ }
+ out := make([]byte, len(tt.out))
+ b.SetBytes(int64(len(out)))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ c.Decrypt(out, tt.out)
+ }
}
diff --git a/libgo/go/crypto/ecdsa/ecdsa.go b/libgo/go/crypto/ecdsa/ecdsa.go
index 25500022939..d02f15c34d9 100644
--- a/libgo/go/crypto/ecdsa/ecdsa.go
+++ b/libgo/go/crypto/ecdsa/ecdsa.go
@@ -123,8 +123,8 @@ func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err err
return
}
-// Verify verifies the signature in r, s of hash using the public key, pub. It
-// returns true iff the signature is valid.
+// Verify verifies the signature in r, s of hash using the public key, pub. Its
+// return value records whether the signature is valid.
func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool {
// See [NSA] 3.4.2
c := pub.Curve
diff --git a/libgo/go/crypto/elliptic/elliptic.go b/libgo/go/crypto/elliptic/elliptic.go
index 7a4ff6614c1..ba673f80ca6 100644
--- a/libgo/go/crypto/elliptic/elliptic.go
+++ b/libgo/go/crypto/elliptic/elliptic.go
@@ -322,7 +322,6 @@ func Unmarshal(curve Curve, data []byte) (x, y *big.Int) {
}
var initonce sync.Once
-var p256 *CurveParams
var p384 *CurveParams
var p521 *CurveParams
@@ -333,17 +332,6 @@ func initAll() {
initP521()
}
-func initP256() {
- // See FIPS 186-3, section D.2.3
- p256 = new(CurveParams)
- p256.P, _ = new(big.Int).SetString("115792089210356248762697446949407573530086143415290314195533631308867097853951", 10)
- p256.N, _ = new(big.Int).SetString("115792089210356248762697446949407573529996955224135760342422259061068512044369", 10)
- p256.B, _ = new(big.Int).SetString("5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", 16)
- p256.Gx, _ = new(big.Int).SetString("6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", 16)
- p256.Gy, _ = new(big.Int).SetString("4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", 16)
- p256.BitSize = 256
-}
-
func initP384() {
// See FIPS 186-3, section D.2.4
p384 = new(CurveParams)
diff --git a/libgo/go/crypto/elliptic/elliptic_test.go b/libgo/go/crypto/elliptic/elliptic_test.go
index 58f903966ce..4dc27c92bf4 100644
--- a/libgo/go/crypto/elliptic/elliptic_test.go
+++ b/libgo/go/crypto/elliptic/elliptic_test.go
@@ -322,6 +322,52 @@ func TestGenericBaseMult(t *testing.T) {
}
}
+func TestP256BaseMult(t *testing.T) {
+ p256 := P256()
+ p256Generic := p256.Params()
+
+ scalars := make([]*big.Int, 0, len(p224BaseMultTests)+1)
+ for _, e := range p224BaseMultTests {
+ k, _ := new(big.Int).SetString(e.k, 10)
+ scalars = append(scalars, k)
+ }
+ k := new(big.Int).SetInt64(1)
+ k.Lsh(k, 500)
+ scalars = append(scalars, k)
+
+ for i, k := range scalars {
+ x, y := p256.ScalarBaseMult(k.Bytes())
+ x2, y2 := p256Generic.ScalarBaseMult(k.Bytes())
+ if x.Cmp(x2) != 0 || y.Cmp(y2) != 0 {
+ t.Errorf("#%d: got (%x, %x), want (%x, %x)", i, x, y, x2, y2)
+ }
+
+ if testing.Short() && i > 5 {
+ break
+ }
+ }
+}
+
+func TestP256Mult(t *testing.T) {
+ p256 := P256()
+ p256Generic := p256.Params()
+
+ for i, e := range p224BaseMultTests {
+ x, _ := new(big.Int).SetString(e.x, 16)
+ y, _ := new(big.Int).SetString(e.y, 16)
+ k, _ := new(big.Int).SetString(e.k, 10)
+
+ xx, yy := p256.ScalarMult(x, y, k.Bytes())
+ xx2, yy2 := p256Generic.ScalarMult(x, y, k.Bytes())
+ if xx.Cmp(xx2) != 0 || yy.Cmp(yy2) != 0 {
+ t.Errorf("#%d: got (%x, %x), want (%x, %x)", i, xx, yy, xx2, yy2)
+ }
+ if testing.Short() && i > 5 {
+ break
+ }
+ }
+}
+
func TestInfinity(t *testing.T) {
tests := []struct {
name string
@@ -371,6 +417,17 @@ func BenchmarkBaseMult(b *testing.B) {
}
}
+func BenchmarkBaseMultP256(b *testing.B) {
+ b.ResetTimer()
+ p256 := P256()
+ e := p224BaseMultTests[25]
+ k, _ := new(big.Int).SetString(e.k, 10)
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ p256.ScalarBaseMult(k.Bytes())
+ }
+}
+
func TestMarshal(t *testing.T) {
p224 := P224()
_, x, y, err := GenerateKey(p224, rand.Reader)
diff --git a/libgo/go/crypto/elliptic/p256.go b/libgo/go/crypto/elliptic/p256.go
new file mode 100644
index 00000000000..82be51e62cd
--- /dev/null
+++ b/libgo/go/crypto/elliptic/p256.go
@@ -0,0 +1,1186 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package elliptic
+
+// This file contains a constant-time, 32-bit implementation of P256.
+
+import (
+ "math/big"
+)
+
+type p256Curve struct {
+ *CurveParams
+}
+
+var (
+ p256 p256Curve
+ // RInverse contains 1/R mod p - the inverse of the Montgomery constant
+ // (2**257).
+ p256RInverse *big.Int
+)
+
+func initP256() {
+ // See FIPS 186-3, section D.2.3
+ p256.CurveParams = new(CurveParams)
+ p256.P, _ = new(big.Int).SetString("115792089210356248762697446949407573530086143415290314195533631308867097853951", 10)
+ p256.N, _ = new(big.Int).SetString("115792089210356248762697446949407573529996955224135760342422259061068512044369", 10)
+ p256.B, _ = new(big.Int).SetString("5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", 16)
+ p256.Gx, _ = new(big.Int).SetString("6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", 16)
+ p256.Gy, _ = new(big.Int).SetString("4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", 16)
+ p256.BitSize = 256
+
+ p256RInverse, _ = new(big.Int).SetString("7fffffff00000001fffffffe8000000100000000ffffffff0000000180000000", 16)
+}
+
+func (curve p256Curve) Params() *CurveParams {
+ return curve.CurveParams
+}
+
+// p256GetScalar endian-swaps the big-endian scalar value from in and writes it
+// to out. If the scalar is equal or greater than the order of the group, it's
+// reduced modulo that order.
+func p256GetScalar(out *[32]byte, in []byte) {
+ n := new(big.Int).SetBytes(in)
+ var scalarBytes []byte
+
+ if n.Cmp(p256.N) >= 0 {
+ n.Mod(n, p256.N)
+ scalarBytes = n.Bytes()
+ } else {
+ scalarBytes = in
+ }
+
+ for i, v := range scalarBytes {
+ out[len(scalarBytes)-(1+i)] = v
+ }
+}
+
+func (p256Curve) ScalarBaseMult(scalar []byte) (x, y *big.Int) {
+ var scalarReversed [32]byte
+ p256GetScalar(&scalarReversed, scalar)
+
+ var x1, y1, z1 [p256Limbs]uint32
+ p256ScalarBaseMult(&x1, &y1, &z1, &scalarReversed)
+ return p256ToAffine(&x1, &y1, &z1)
+}
+
+func (p256Curve) ScalarMult(bigX, bigY *big.Int, scalar []byte) (x, y *big.Int) {
+ var scalarReversed [32]byte
+ p256GetScalar(&scalarReversed, scalar)
+
+ var px, py, x1, y1, z1 [p256Limbs]uint32
+ p256FromBig(&px, bigX)
+ p256FromBig(&py, bigY)
+ p256ScalarMult(&x1, &y1, &z1, &px, &py, &scalarReversed)
+ return p256ToAffine(&x1, &y1, &z1)
+}
+
+// Field elements are represented as nine, unsigned 32-bit words.
+//
+// The value of an field element is:
+// x[0] + (x[1] * 2**29) + (x[2] * 2**57) + ... + (x[8] * 2**228)
+//
+// That is, each limb is alternately 29 or 28-bits wide in little-endian
+// order.
+//
+// This means that a field element hits 2**257, rather than 2**256 as we would
+// like. A 28, 29, ... pattern would cause us to hit 2**256, but that causes
+// problems when multiplying as terms end up one bit short of a limb which
+// would require much bit-shifting to correct.
+//
+// Finally, the values stored in a field element are in Montgomery form. So the
+// value |y| is stored as (y*R) mod p, where p is the P-256 prime and R is
+// 2**257.
+
+const (
+ p256Limbs = 9
+ bottom29Bits = 0x1fffffff
+)
+
+var (
+ // p256One is the number 1 as a field element.
+ p256One = [p256Limbs]uint32{2, 0, 0, 0xffff800, 0x1fffffff, 0xfffffff, 0x1fbfffff, 0x1ffffff, 0}
+ p256Zero = [p256Limbs]uint32{0, 0, 0, 0, 0, 0, 0, 0, 0}
+ // p256P is the prime modulus as a field element.
+ p256P = [p256Limbs]uint32{0x1fffffff, 0xfffffff, 0x1fffffff, 0x3ff, 0, 0, 0x200000, 0xf000000, 0xfffffff}
+ // p2562P is the twice prime modulus as a field element.
+ p2562P = [p256Limbs]uint32{0x1ffffffe, 0xfffffff, 0x1fffffff, 0x7ff, 0, 0, 0x400000, 0xe000000, 0x1fffffff}
+)
+
+// p256Precomputed contains precomputed values to aid the calculation of scalar
+// multiples of the base point, G. It's actually two, equal length, tables
+// concatenated.
+//
+// The first table contains (x,y) field element pairs for 16 multiples of the
+// base point, G.
+//
+// Index | Index (binary) | Value
+// 0 | 0000 | 0G (all zeros, omitted)
+// 1 | 0001 | G
+// 2 | 0010 | 2**64G
+// 3 | 0011 | 2**64G + G
+// 4 | 0100 | 2**128G
+// 5 | 0101 | 2**128G + G
+// 6 | 0110 | 2**128G + 2**64G
+// 7 | 0111 | 2**128G + 2**64G + G
+// 8 | 1000 | 2**192G
+// 9 | 1001 | 2**192G + G
+// 10 | 1010 | 2**192G + 2**64G
+// 11 | 1011 | 2**192G + 2**64G + G
+// 12 | 1100 | 2**192G + 2**128G
+// 13 | 1101 | 2**192G + 2**128G + G
+// 14 | 1110 | 2**192G + 2**128G + 2**64G
+// 15 | 1111 | 2**192G + 2**128G + 2**64G + G
+//
+// The second table follows the same style, but the terms are 2**32G,
+// 2**96G, 2**160G, 2**224G.
+//
+// This is ~2KB of data.
+var p256Precomputed = [p256Limbs * 2 * 15 * 2]uint32{
+ 0x11522878, 0xe730d41, 0xdb60179, 0x4afe2ff, 0x12883add, 0xcaddd88, 0x119e7edc, 0xd4a6eab, 0x3120bee,
+ 0x1d2aac15, 0xf25357c, 0x19e45cdd, 0x5c721d0, 0x1992c5a5, 0xa237487, 0x154ba21, 0x14b10bb, 0xae3fe3,
+ 0xd41a576, 0x922fc51, 0x234994f, 0x60b60d3, 0x164586ae, 0xce95f18, 0x1fe49073, 0x3fa36cc, 0x5ebcd2c,
+ 0xb402f2f, 0x15c70bf, 0x1561925c, 0x5a26704, 0xda91e90, 0xcdc1c7f, 0x1ea12446, 0xe1ade1e, 0xec91f22,
+ 0x26f7778, 0x566847e, 0xa0bec9e, 0x234f453, 0x1a31f21a, 0xd85e75c, 0x56c7109, 0xa267a00, 0xb57c050,
+ 0x98fb57, 0xaa837cc, 0x60c0792, 0xcfa5e19, 0x61bab9e, 0x589e39b, 0xa324c5, 0x7d6dee7, 0x2976e4b,
+ 0x1fc4124a, 0xa8c244b, 0x1ce86762, 0xcd61c7e, 0x1831c8e0, 0x75774e1, 0x1d96a5a9, 0x843a649, 0xc3ab0fa,
+ 0x6e2e7d5, 0x7673a2a, 0x178b65e8, 0x4003e9b, 0x1a1f11c2, 0x7816ea, 0xf643e11, 0x58c43df, 0xf423fc2,
+ 0x19633ffa, 0x891f2b2, 0x123c231c, 0x46add8c, 0x54700dd, 0x59e2b17, 0x172db40f, 0x83e277d, 0xb0dd609,
+ 0xfd1da12, 0x35c6e52, 0x19ede20c, 0xd19e0c0, 0x97d0f40, 0xb015b19, 0x449e3f5, 0xe10c9e, 0x33ab581,
+ 0x56a67ab, 0x577734d, 0x1dddc062, 0xc57b10d, 0x149b39d, 0x26a9e7b, 0xc35df9f, 0x48764cd, 0x76dbcca,
+ 0xca4b366, 0xe9303ab, 0x1a7480e7, 0x57e9e81, 0x1e13eb50, 0xf466cf3, 0x6f16b20, 0x4ba3173, 0xc168c33,
+ 0x15cb5439, 0x6a38e11, 0x73658bd, 0xb29564f, 0x3f6dc5b, 0x53b97e, 0x1322c4c0, 0x65dd7ff, 0x3a1e4f6,
+ 0x14e614aa, 0x9246317, 0x1bc83aca, 0xad97eed, 0xd38ce4a, 0xf82b006, 0x341f077, 0xa6add89, 0x4894acd,
+ 0x9f162d5, 0xf8410ef, 0x1b266a56, 0xd7f223, 0x3e0cb92, 0xe39b672, 0x6a2901a, 0x69a8556, 0x7e7c0,
+ 0x9b7d8d3, 0x309a80, 0x1ad05f7f, 0xc2fb5dd, 0xcbfd41d, 0x9ceb638, 0x1051825c, 0xda0cf5b, 0x812e881,
+ 0x6f35669, 0x6a56f2c, 0x1df8d184, 0x345820, 0x1477d477, 0x1645db1, 0xbe80c51, 0xc22be3e, 0xe35e65a,
+ 0x1aeb7aa0, 0xc375315, 0xf67bc99, 0x7fdd7b9, 0x191fc1be, 0x61235d, 0x2c184e9, 0x1c5a839, 0x47a1e26,
+ 0xb7cb456, 0x93e225d, 0x14f3c6ed, 0xccc1ac9, 0x17fe37f3, 0x4988989, 0x1a90c502, 0x2f32042, 0xa17769b,
+ 0xafd8c7c, 0x8191c6e, 0x1dcdb237, 0x16200c0, 0x107b32a1, 0x66c08db, 0x10d06a02, 0x3fc93, 0x5620023,
+ 0x16722b27, 0x68b5c59, 0x270fcfc, 0xfad0ecc, 0xe5de1c2, 0xeab466b, 0x2fc513c, 0x407f75c, 0xbaab133,
+ 0x9705fe9, 0xb88b8e7, 0x734c993, 0x1e1ff8f, 0x19156970, 0xabd0f00, 0x10469ea7, 0x3293ac0, 0xcdc98aa,
+ 0x1d843fd, 0xe14bfe8, 0x15be825f, 0x8b5212, 0xeb3fb67, 0x81cbd29, 0xbc62f16, 0x2b6fcc7, 0xf5a4e29,
+ 0x13560b66, 0xc0b6ac2, 0x51ae690, 0xd41e271, 0xf3e9bd4, 0x1d70aab, 0x1029f72, 0x73e1c35, 0xee70fbc,
+ 0xad81baf, 0x9ecc49a, 0x86c741e, 0xfe6be30, 0x176752e7, 0x23d416, 0x1f83de85, 0x27de188, 0x66f70b8,
+ 0x181cd51f, 0x96b6e4c, 0x188f2335, 0xa5df759, 0x17a77eb6, 0xfeb0e73, 0x154ae914, 0x2f3ec51, 0x3826b59,
+ 0xb91f17d, 0x1c72949, 0x1362bf0a, 0xe23fddf, 0xa5614b0, 0xf7d8f, 0x79061, 0x823d9d2, 0x8213f39,
+ 0x1128ae0b, 0xd095d05, 0xb85c0c2, 0x1ecb2ef, 0x24ddc84, 0xe35e901, 0x18411a4a, 0xf5ddc3d, 0x3786689,
+ 0x52260e8, 0x5ae3564, 0x542b10d, 0x8d93a45, 0x19952aa4, 0x996cc41, 0x1051a729, 0x4be3499, 0x52b23aa,
+ 0x109f307e, 0x6f5b6bb, 0x1f84e1e7, 0x77a0cfa, 0x10c4df3f, 0x25a02ea, 0xb048035, 0xe31de66, 0xc6ecaa3,
+ 0x28ea335, 0x2886024, 0x1372f020, 0xf55d35, 0x15e4684c, 0xf2a9e17, 0x1a4a7529, 0xcb7beb1, 0xb2a78a1,
+ 0x1ab21f1f, 0x6361ccf, 0x6c9179d, 0xb135627, 0x1267b974, 0x4408bad, 0x1cbff658, 0xe3d6511, 0xc7d76f,
+ 0x1cc7a69, 0xe7ee31b, 0x54fab4f, 0x2b914f, 0x1ad27a30, 0xcd3579e, 0xc50124c, 0x50daa90, 0xb13f72,
+ 0xb06aa75, 0x70f5cc6, 0x1649e5aa, 0x84a5312, 0x329043c, 0x41c4011, 0x13d32411, 0xb04a838, 0xd760d2d,
+ 0x1713b532, 0xbaa0c03, 0x84022ab, 0x6bcf5c1, 0x2f45379, 0x18ae070, 0x18c9e11e, 0x20bca9a, 0x66f496b,
+ 0x3eef294, 0x67500d2, 0xd7f613c, 0x2dbbeb, 0xb741038, 0xe04133f, 0x1582968d, 0xbe985f7, 0x1acbc1a,
+ 0x1a6a939f, 0x33e50f6, 0xd665ed4, 0xb4b7bd6, 0x1e5a3799, 0x6b33847, 0x17fa56ff, 0x65ef930, 0x21dc4a,
+ 0x2b37659, 0x450fe17, 0xb357b65, 0xdf5efac, 0x15397bef, 0x9d35a7f, 0x112ac15f, 0x624e62e, 0xa90ae2f,
+ 0x107eecd2, 0x1f69bbe, 0x77d6bce, 0x5741394, 0x13c684fc, 0x950c910, 0x725522b, 0xdc78583, 0x40eeabb,
+ 0x1fde328a, 0xbd61d96, 0xd28c387, 0x9e77d89, 0x12550c40, 0x759cb7d, 0x367ef34, 0xae2a960, 0x91b8bdc,
+ 0x93462a9, 0xf469ef, 0xb2e9aef, 0xd2ca771, 0x54e1f42, 0x7aaa49, 0x6316abb, 0x2413c8e, 0x5425bf9,
+ 0x1bed3e3a, 0xf272274, 0x1f5e7326, 0x6416517, 0xea27072, 0x9cedea7, 0x6e7633, 0x7c91952, 0xd806dce,
+ 0x8e2a7e1, 0xe421e1a, 0x418c9e1, 0x1dbc890, 0x1b395c36, 0xa1dc175, 0x1dc4ef73, 0x8956f34, 0xe4b5cf2,
+ 0x1b0d3a18, 0x3194a36, 0x6c2641f, 0xe44124c, 0xa2f4eaa, 0xa8c25ba, 0xf927ed7, 0x627b614, 0x7371cca,
+ 0xba16694, 0x417bc03, 0x7c0a7e3, 0x9c35c19, 0x1168a205, 0x8b6b00d, 0x10e3edc9, 0x9c19bf2, 0x5882229,
+ 0x1b2b4162, 0xa5cef1a, 0x1543622b, 0x9bd433e, 0x364e04d, 0x7480792, 0x5c9b5b3, 0xe85ff25, 0x408ef57,
+ 0x1814cfa4, 0x121b41b, 0xd248a0f, 0x3b05222, 0x39bb16a, 0xc75966d, 0xa038113, 0xa4a1769, 0x11fbc6c,
+ 0x917e50e, 0xeec3da8, 0x169d6eac, 0x10c1699, 0xa416153, 0xf724912, 0x15cd60b7, 0x4acbad9, 0x5efc5fa,
+ 0xf150ed7, 0x122b51, 0x1104b40a, 0xcb7f442, 0xfbb28ff, 0x6ac53ca, 0x196142cc, 0x7bf0fa9, 0x957651,
+ 0x4e0f215, 0xed439f8, 0x3f46bd5, 0x5ace82f, 0x110916b6, 0x6db078, 0xffd7d57, 0xf2ecaac, 0xca86dec,
+ 0x15d6b2da, 0x965ecc9, 0x1c92b4c2, 0x1f3811, 0x1cb080f5, 0x2d8b804, 0x19d1c12d, 0xf20bd46, 0x1951fa7,
+ 0xa3656c3, 0x523a425, 0xfcd0692, 0xd44ddc8, 0x131f0f5b, 0xaf80e4a, 0xcd9fc74, 0x99bb618, 0x2db944c,
+ 0xa673090, 0x1c210e1, 0x178c8d23, 0x1474383, 0x10b8743d, 0x985a55b, 0x2e74779, 0x576138, 0x9587927,
+ 0x133130fa, 0xbe05516, 0x9f4d619, 0xbb62570, 0x99ec591, 0xd9468fe, 0x1d07782d, 0xfc72e0b, 0x701b298,
+ 0x1863863b, 0x85954b8, 0x121a0c36, 0x9e7fedf, 0xf64b429, 0x9b9d71e, 0x14e2f5d8, 0xf858d3a, 0x942eea8,
+ 0xda5b765, 0x6edafff, 0xa9d18cc, 0xc65e4ba, 0x1c747e86, 0xe4ea915, 0x1981d7a1, 0x8395659, 0x52ed4e2,
+ 0x87d43b7, 0x37ab11b, 0x19d292ce, 0xf8d4692, 0x18c3053f, 0x8863e13, 0x4c146c0, 0x6bdf55a, 0x4e4457d,
+ 0x16152289, 0xac78ec2, 0x1a59c5a2, 0x2028b97, 0x71c2d01, 0x295851f, 0x404747b, 0x878558d, 0x7d29aa4,
+ 0x13d8341f, 0x8daefd7, 0x139c972d, 0x6b7ea75, 0xd4a9dde, 0xff163d8, 0x81d55d7, 0xa5bef68, 0xb7b30d8,
+ 0xbe73d6f, 0xaa88141, 0xd976c81, 0x7e7a9cc, 0x18beb771, 0xd773cbd, 0x13f51951, 0x9d0c177, 0x1c49a78,
+}
+
+// Field element operations:
+
+// nonZeroToAllOnes returns:
+// 0xffffffff for 0 < x <= 2**31
+// 0 for x == 0 or x > 2**31.
+func nonZeroToAllOnes(x uint32) uint32 {
+ return ((x - 1) >> 31) - 1
+}
+
+// p256ReduceCarry adds a multiple of p in order to cancel |carry|,
+// which is a term at 2**257.
+//
+// On entry: carry < 2**3, inout[0,2,...] < 2**29, inout[1,3,...] < 2**28.
+// On exit: inout[0,2,..] < 2**30, inout[1,3,...] < 2**29.
+func p256ReduceCarry(inout *[p256Limbs]uint32, carry uint32) {
+ carry_mask := nonZeroToAllOnes(carry)
+
+ inout[0] += carry << 1
+ inout[3] += 0x10000000 & carry_mask
+ // carry < 2**3 thus (carry << 11) < 2**14 and we added 2**28 in the
+ // previous line therefore this doesn't underflow.
+ inout[3] -= carry << 11
+ inout[4] += (0x20000000 - 1) & carry_mask
+ inout[5] += (0x10000000 - 1) & carry_mask
+ inout[6] += (0x20000000 - 1) & carry_mask
+ inout[6] -= carry << 22
+ // This may underflow if carry is non-zero but, if so, we'll fix it in the
+ // next line.
+ inout[7] -= 1 & carry_mask
+ inout[7] += carry << 25
+}
+
+// p256Sum sets out = in+in2.
+//
+// On entry, in[i]+in2[i] must not overflow a 32-bit word.
+// On exit: out[0,2,...] < 2**30, out[1,3,...] < 2**29
+func p256Sum(out, in, in2 *[p256Limbs]uint32) {
+ carry := uint32(0)
+ for i := 0; ; i++ {
+ out[i] = in[i] + in2[i]
+ out[i] += carry
+ carry = out[i] >> 29
+ out[i] &= bottom29Bits
+
+ i++
+ if i == p256Limbs {
+ break
+ }
+
+ out[i] = in[i] + in2[i]
+ out[i] += carry
+ carry = out[i] >> 28
+ out[i] &= bottom28Bits
+ }
+
+ p256ReduceCarry(out, carry)
+}
+
+const (
+ two30m2 = 1<<30 - 1<<2
+ two30p13m2 = 1<<30 + 1<<13 - 1<<2
+ two31m2 = 1<<31 - 1<<2
+ two31p24m2 = 1<<31 + 1<<24 - 1<<2
+ two30m27m2 = 1<<30 - 1<<27 - 1<<2
+)
+
+// p256Zero31 is 0 mod p.
+var p256Zero31 = [p256Limbs]uint32{two31m3, two30m2, two31m2, two30p13m2, two31m2, two30m2, two31p24m2, two30m27m2, two31m2}
+
+// p256Diff sets out = in-in2.
+//
+// On entry: in[0,2,...] < 2**30, in[1,3,...] < 2**29 and
+// in2[0,2,...] < 2**30, in2[1,3,...] < 2**29.
+// On exit: out[0,2,...] < 2**30, out[1,3,...] < 2**29.
+func p256Diff(out, in, in2 *[p256Limbs]uint32) {
+ var carry uint32
+
+ for i := 0; ; i++ {
+ out[i] = in[i] - in2[i]
+ out[i] += p256Zero31[i]
+ out[i] += carry
+ carry = out[i] >> 29
+ out[i] &= bottom29Bits
+
+ i++
+ if i == p256Limbs {
+ break
+ }
+
+ out[i] = in[i] - in2[i]
+ out[i] += p256Zero31[i]
+ out[i] += carry
+ carry = out[i] >> 28
+ out[i] &= bottom28Bits
+ }
+
+ p256ReduceCarry(out, carry)
+}
+
+// p256ReduceDegree sets out = tmp/R mod p where tmp contains 64-bit words with
+// the same 29,28,... bit positions as an field element.
+//
+// The values in field elements are in Montgomery form: x*R mod p where R =
+// 2**257. Since we just multiplied two Montgomery values together, the result
+// is x*y*R*R mod p. We wish to divide by R in order for the result also to be
+// in Montgomery form.
+//
+// On entry: tmp[i] < 2**64
+// On exit: out[0,2,...] < 2**30, out[1,3,...] < 2**29
+func p256ReduceDegree(out *[p256Limbs]uint32, tmp [17]uint64) {
+ // The following table may be helpful when reading this code:
+ //
+ // Limb number: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10...
+ // Width (bits): 29| 28| 29| 28| 29| 28| 29| 28| 29| 28| 29
+ // Start bit: 0 | 29| 57| 86|114|143|171|200|228|257|285
+ // (odd phase): 0 | 28| 57| 85|114|142|171|199|228|256|285
+ var tmp2 [18]uint32
+ var carry, x, xMask uint32
+
+ // tmp contains 64-bit words with the same 29,28,29-bit positions as an
+ // field element. So the top of an element of tmp might overlap with
+ // another element two positions down. The following loop eliminates
+ // this overlap.
+ tmp2[0] = uint32(tmp[0]) & bottom29Bits
+
+ tmp2[1] = uint32(tmp[0]) >> 29
+ tmp2[1] |= (uint32(tmp[0]>>32) << 3) & bottom28Bits
+ tmp2[1] += uint32(tmp[1]) & bottom28Bits
+ carry = tmp2[1] >> 28
+ tmp2[1] &= bottom28Bits
+
+ for i := 2; i < 17; i++ {
+ tmp2[i] = (uint32(tmp[i-2] >> 32)) >> 25
+ tmp2[i] += (uint32(tmp[i-1])) >> 28
+ tmp2[i] += (uint32(tmp[i-1]>>32) << 4) & bottom29Bits
+ tmp2[i] += uint32(tmp[i]) & bottom29Bits
+ tmp2[i] += carry
+ carry = tmp2[i] >> 29
+ tmp2[i] &= bottom29Bits
+
+ i++
+ if i == 17 {
+ break
+ }
+ tmp2[i] = uint32(tmp[i-2]>>32) >> 25
+ tmp2[i] += uint32(tmp[i-1]) >> 29
+ tmp2[i] += ((uint32(tmp[i-1] >> 32)) << 3) & bottom28Bits
+ tmp2[i] += uint32(tmp[i]) & bottom28Bits
+ tmp2[i] += carry
+ carry = tmp2[i] >> 28
+ tmp2[i] &= bottom28Bits
+ }
+
+ tmp2[17] = uint32(tmp[15]>>32) >> 25
+ tmp2[17] += uint32(tmp[16]) >> 29
+ tmp2[17] += uint32(tmp[16]>>32) << 3
+ tmp2[17] += carry
+
+ // Montgomery elimination of terms:
+ //
+ // Since R is 2**257, we can divide by R with a bitwise shift if we can
+ // ensure that the right-most 257 bits are all zero. We can make that true
+ // by adding multiplies of p without affecting the value.
+ //
+ // So we eliminate limbs from right to left. Since the bottom 29 bits of p
+ // are all ones, then by adding tmp2[0]*p to tmp2 we'll make tmp2[0] == 0.
+ // We can do that for 8 further limbs and then right shift to eliminate the
+ // extra factor of R.
+ for i := 0; ; i += 2 {
+ tmp2[i+1] += tmp2[i] >> 29
+ x = tmp2[i] & bottom29Bits
+ xMask = nonZeroToAllOnes(x)
+ tmp2[i] = 0
+
+ // The bounds calculations for this loop are tricky. Each iteration of
+ // the loop eliminates two words by adding values to words to their
+ // right.
+ //
+ // The following table contains the amounts added to each word (as an
+ // offset from the value of i at the top of the loop). The amounts are
+ // accounted for from the first and second half of the loop separately
+ // and are written as, for example, 28 to mean a value <2**28.
+ //
+ // Word: 3 4 5 6 7 8 9 10
+ // Added in top half: 28 11 29 21 29 28
+ // 28 29
+ // 29
+ // Added in bottom half: 29 10 28 21 28 28
+ // 29
+ //
+ // The value that is currently offset 7 will be offset 5 for the next
+ // iteration and then offset 3 for the iteration after that. Therefore
+ // the total value added will be the values added at 7, 5 and 3.
+ //
+ // The following table accumulates these values. The sums at the bottom
+ // are written as, for example, 29+28, to mean a value < 2**29+2**28.
+ //
+ // Word: 3 4 5 6 7 8 9 10 11 12 13
+ // 28 11 10 29 21 29 28 28 28 28 28
+ // 29 28 11 28 29 28 29 28 29 28
+ // 29 28 21 21 29 21 29 21
+ // 10 29 28 21 28 21 28
+ // 28 29 28 29 28 29 28
+ // 11 10 29 10 29 10
+ // 29 28 11 28 11
+ // 29 29
+ // --------------------------------------------
+ // 30+ 31+ 30+ 31+ 30+
+ // 28+ 29+ 28+ 29+ 21+
+ // 21+ 28+ 21+ 28+ 10
+ // 10 21+ 10 21+
+ // 11 11
+ //
+ // So the greatest amount is added to tmp2[10] and tmp2[12]. If
+ // tmp2[10/12] has an initial value of <2**29, then the maximum value
+ // will be < 2**31 + 2**30 + 2**28 + 2**21 + 2**11, which is < 2**32,
+ // as required.
+ tmp2[i+3] += (x << 10) & bottom28Bits
+ tmp2[i+4] += (x >> 18)
+
+ tmp2[i+6] += (x << 21) & bottom29Bits
+ tmp2[i+7] += x >> 8
+
+ // At position 200, which is the starting bit position for word 7, we
+ // have a factor of 0xf000000 = 2**28 - 2**24.
+ tmp2[i+7] += 0x10000000 & xMask
+ tmp2[i+8] += (x - 1) & xMask
+ tmp2[i+7] -= (x << 24) & bottom28Bits
+ tmp2[i+8] -= x >> 4
+
+ tmp2[i+8] += 0x20000000 & xMask
+ tmp2[i+8] -= x
+ tmp2[i+8] += (x << 28) & bottom29Bits
+ tmp2[i+9] += ((x >> 1) - 1) & xMask
+
+ if i+1 == p256Limbs {
+ break
+ }
+ tmp2[i+2] += tmp2[i+1] >> 28
+ x = tmp2[i+1] & bottom28Bits
+ xMask = nonZeroToAllOnes(x)
+ tmp2[i+1] = 0
+
+ tmp2[i+4] += (x << 11) & bottom29Bits
+ tmp2[i+5] += (x >> 18)
+
+ tmp2[i+7] += (x << 21) & bottom28Bits
+ tmp2[i+8] += x >> 7
+
+ // At position 199, which is the starting bit of the 8th word when
+ // dealing with a context starting on an odd word, we have a factor of
+ // 0x1e000000 = 2**29 - 2**25. Since we have not updated i, the 8th
+ // word from i+1 is i+8.
+ tmp2[i+8] += 0x20000000 & xMask
+ tmp2[i+9] += (x - 1) & xMask
+ tmp2[i+8] -= (x << 25) & bottom29Bits
+ tmp2[i+9] -= x >> 4
+
+ tmp2[i+9] += 0x10000000 & xMask
+ tmp2[i+9] -= x
+ tmp2[i+10] += (x - 1) & xMask
+ }
+
+ // We merge the right shift with a carry chain. The words above 2**257 have
+ // widths of 28,29,... which we need to correct when copying them down.
+ carry = 0
+ for i := 0; i < 8; i++ {
+ // The maximum value of tmp2[i + 9] occurs on the first iteration and
+ // is < 2**30+2**29+2**28. Adding 2**29 (from tmp2[i + 10]) is
+ // therefore safe.
+ out[i] = tmp2[i+9]
+ out[i] += carry
+ out[i] += (tmp2[i+10] << 28) & bottom29Bits
+ carry = out[i] >> 29
+ out[i] &= bottom29Bits
+
+ i++
+ out[i] = tmp2[i+9] >> 1
+ out[i] += carry
+ carry = out[i] >> 28
+ out[i] &= bottom28Bits
+ }
+
+ out[8] = tmp2[17]
+ out[8] += carry
+ carry = out[8] >> 29
+ out[8] &= bottom29Bits
+
+ p256ReduceCarry(out, carry)
+}
+
+// p256Square sets out=in*in.
+//
+// On entry: in[0,2,...] < 2**30, in[1,3,...] < 2**29.
+// On exit: out[0,2,...] < 2**30, out[1,3,...] < 2**29.
+func p256Square(out, in *[p256Limbs]uint32) {
+ var tmp [17]uint64
+
+ tmp[0] = uint64(in[0]) * uint64(in[0])
+ tmp[1] = uint64(in[0]) * (uint64(in[1]) << 1)
+ tmp[2] = uint64(in[0])*(uint64(in[2])<<1) +
+ uint64(in[1])*(uint64(in[1])<<1)
+ tmp[3] = uint64(in[0])*(uint64(in[3])<<1) +
+ uint64(in[1])*(uint64(in[2])<<1)
+ tmp[4] = uint64(in[0])*(uint64(in[4])<<1) +
+ uint64(in[1])*(uint64(in[3])<<2) +
+ uint64(in[2])*uint64(in[2])
+ tmp[5] = uint64(in[0])*(uint64(in[5])<<1) +
+ uint64(in[1])*(uint64(in[4])<<1) +
+ uint64(in[2])*(uint64(in[3])<<1)
+ tmp[6] = uint64(in[0])*(uint64(in[6])<<1) +
+ uint64(in[1])*(uint64(in[5])<<2) +
+ uint64(in[2])*(uint64(in[4])<<1) +
+ uint64(in[3])*(uint64(in[3])<<1)
+ tmp[7] = uint64(in[0])*(uint64(in[7])<<1) +
+ uint64(in[1])*(uint64(in[6])<<1) +
+ uint64(in[2])*(uint64(in[5])<<1) +
+ uint64(in[3])*(uint64(in[4])<<1)
+ // tmp[8] has the greatest value of 2**61 + 2**60 + 2**61 + 2**60 + 2**60,
+ // which is < 2**64 as required.
+ tmp[8] = uint64(in[0])*(uint64(in[8])<<1) +
+ uint64(in[1])*(uint64(in[7])<<2) +
+ uint64(in[2])*(uint64(in[6])<<1) +
+ uint64(in[3])*(uint64(in[5])<<2) +
+ uint64(in[4])*uint64(in[4])
+ tmp[9] = uint64(in[1])*(uint64(in[8])<<1) +
+ uint64(in[2])*(uint64(in[7])<<1) +
+ uint64(in[3])*(uint64(in[6])<<1) +
+ uint64(in[4])*(uint64(in[5])<<1)
+ tmp[10] = uint64(in[2])*(uint64(in[8])<<1) +
+ uint64(in[3])*(uint64(in[7])<<2) +
+ uint64(in[4])*(uint64(in[6])<<1) +
+ uint64(in[5])*(uint64(in[5])<<1)
+ tmp[11] = uint64(in[3])*(uint64(in[8])<<1) +
+ uint64(in[4])*(uint64(in[7])<<1) +
+ uint64(in[5])*(uint64(in[6])<<1)
+ tmp[12] = uint64(in[4])*(uint64(in[8])<<1) +
+ uint64(in[5])*(uint64(in[7])<<2) +
+ uint64(in[6])*uint64(in[6])
+ tmp[13] = uint64(in[5])*(uint64(in[8])<<1) +
+ uint64(in[6])*(uint64(in[7])<<1)
+ tmp[14] = uint64(in[6])*(uint64(in[8])<<1) +
+ uint64(in[7])*(uint64(in[7])<<1)
+ tmp[15] = uint64(in[7]) * (uint64(in[8]) << 1)
+ tmp[16] = uint64(in[8]) * uint64(in[8])
+
+ p256ReduceDegree(out, tmp)
+}
+
+// p256Mul sets out=in*in2.
+//
+// On entry: in[0,2,...] < 2**30, in[1,3,...] < 2**29 and
+// in2[0,2,...] < 2**30, in2[1,3,...] < 2**29.
+// On exit: out[0,2,...] < 2**30, out[1,3,...] < 2**29.
+func p256Mul(out, in, in2 *[p256Limbs]uint32) {
+ var tmp [17]uint64
+
+ tmp[0] = uint64(in[0]) * uint64(in2[0])
+ tmp[1] = uint64(in[0])*(uint64(in2[1])<<0) +
+ uint64(in[1])*(uint64(in2[0])<<0)
+ tmp[2] = uint64(in[0])*(uint64(in2[2])<<0) +
+ uint64(in[1])*(uint64(in2[1])<<1) +
+ uint64(in[2])*(uint64(in2[0])<<0)
+ tmp[3] = uint64(in[0])*(uint64(in2[3])<<0) +
+ uint64(in[1])*(uint64(in2[2])<<0) +
+ uint64(in[2])*(uint64(in2[1])<<0) +
+ uint64(in[3])*(uint64(in2[0])<<0)
+ tmp[4] = uint64(in[0])*(uint64(in2[4])<<0) +
+ uint64(in[1])*(uint64(in2[3])<<1) +
+ uint64(in[2])*(uint64(in2[2])<<0) +
+ uint64(in[3])*(uint64(in2[1])<<1) +
+ uint64(in[4])*(uint64(in2[0])<<0)
+ tmp[5] = uint64(in[0])*(uint64(in2[5])<<0) +
+ uint64(in[1])*(uint64(in2[4])<<0) +
+ uint64(in[2])*(uint64(in2[3])<<0) +
+ uint64(in[3])*(uint64(in2[2])<<0) +
+ uint64(in[4])*(uint64(in2[1])<<0) +
+ uint64(in[5])*(uint64(in2[0])<<0)
+ tmp[6] = uint64(in[0])*(uint64(in2[6])<<0) +
+ uint64(in[1])*(uint64(in2[5])<<1) +
+ uint64(in[2])*(uint64(in2[4])<<0) +
+ uint64(in[3])*(uint64(in2[3])<<1) +
+ uint64(in[4])*(uint64(in2[2])<<0) +
+ uint64(in[5])*(uint64(in2[1])<<1) +
+ uint64(in[6])*(uint64(in2[0])<<0)
+ tmp[7] = uint64(in[0])*(uint64(in2[7])<<0) +
+ uint64(in[1])*(uint64(in2[6])<<0) +
+ uint64(in[2])*(uint64(in2[5])<<0) +
+ uint64(in[3])*(uint64(in2[4])<<0) +
+ uint64(in[4])*(uint64(in2[3])<<0) +
+ uint64(in[5])*(uint64(in2[2])<<0) +
+ uint64(in[6])*(uint64(in2[1])<<0) +
+ uint64(in[7])*(uint64(in2[0])<<0)
+ // tmp[8] has the greatest value but doesn't overflow. See logic in
+ // p256Square.
+ tmp[8] = uint64(in[0])*(uint64(in2[8])<<0) +
+ uint64(in[1])*(uint64(in2[7])<<1) +
+ uint64(in[2])*(uint64(in2[6])<<0) +
+ uint64(in[3])*(uint64(in2[5])<<1) +
+ uint64(in[4])*(uint64(in2[4])<<0) +
+ uint64(in[5])*(uint64(in2[3])<<1) +
+ uint64(in[6])*(uint64(in2[2])<<0) +
+ uint64(in[7])*(uint64(in2[1])<<1) +
+ uint64(in[8])*(uint64(in2[0])<<0)
+ tmp[9] = uint64(in[1])*(uint64(in2[8])<<0) +
+ uint64(in[2])*(uint64(in2[7])<<0) +
+ uint64(in[3])*(uint64(in2[6])<<0) +
+ uint64(in[4])*(uint64(in2[5])<<0) +
+ uint64(in[5])*(uint64(in2[4])<<0) +
+ uint64(in[6])*(uint64(in2[3])<<0) +
+ uint64(in[7])*(uint64(in2[2])<<0) +
+ uint64(in[8])*(uint64(in2[1])<<0)
+ tmp[10] = uint64(in[2])*(uint64(in2[8])<<0) +
+ uint64(in[3])*(uint64(in2[7])<<1) +
+ uint64(in[4])*(uint64(in2[6])<<0) +
+ uint64(in[5])*(uint64(in2[5])<<1) +
+ uint64(in[6])*(uint64(in2[4])<<0) +
+ uint64(in[7])*(uint64(in2[3])<<1) +
+ uint64(in[8])*(uint64(in2[2])<<0)
+ tmp[11] = uint64(in[3])*(uint64(in2[8])<<0) +
+ uint64(in[4])*(uint64(in2[7])<<0) +
+ uint64(in[5])*(uint64(in2[6])<<0) +
+ uint64(in[6])*(uint64(in2[5])<<0) +
+ uint64(in[7])*(uint64(in2[4])<<0) +
+ uint64(in[8])*(uint64(in2[3])<<0)
+ tmp[12] = uint64(in[4])*(uint64(in2[8])<<0) +
+ uint64(in[5])*(uint64(in2[7])<<1) +
+ uint64(in[6])*(uint64(in2[6])<<0) +
+ uint64(in[7])*(uint64(in2[5])<<1) +
+ uint64(in[8])*(uint64(in2[4])<<0)
+ tmp[13] = uint64(in[5])*(uint64(in2[8])<<0) +
+ uint64(in[6])*(uint64(in2[7])<<0) +
+ uint64(in[7])*(uint64(in2[6])<<0) +
+ uint64(in[8])*(uint64(in2[5])<<0)
+ tmp[14] = uint64(in[6])*(uint64(in2[8])<<0) +
+ uint64(in[7])*(uint64(in2[7])<<1) +
+ uint64(in[8])*(uint64(in2[6])<<0)
+ tmp[15] = uint64(in[7])*(uint64(in2[8])<<0) +
+ uint64(in[8])*(uint64(in2[7])<<0)
+ tmp[16] = uint64(in[8]) * (uint64(in2[8]) << 0)
+
+ p256ReduceDegree(out, tmp)
+}
+
+func p256Assign(out, in *[p256Limbs]uint32) {
+ *out = *in
+}
+
+// p256Invert calculates |out| = |in|^{-1}
+//
+// Based on Fermat's Little Theorem:
+// a^p = a (mod p)
+// a^{p-1} = 1 (mod p)
+// a^{p-2} = a^{-1} (mod p)
+func p256Invert(out, in *[p256Limbs]uint32) {
+ var ftmp, ftmp2 [p256Limbs]uint32
+
+ // each e_I will hold |in|^{2^I - 1}
+ var e2, e4, e8, e16, e32, e64 [p256Limbs]uint32
+
+ p256Square(&ftmp, in) // 2^1
+ p256Mul(&ftmp, in, &ftmp) // 2^2 - 2^0
+ p256Assign(&e2, &ftmp)
+ p256Square(&ftmp, &ftmp) // 2^3 - 2^1
+ p256Square(&ftmp, &ftmp) // 2^4 - 2^2
+ p256Mul(&ftmp, &ftmp, &e2) // 2^4 - 2^0
+ p256Assign(&e4, &ftmp)
+ p256Square(&ftmp, &ftmp) // 2^5 - 2^1
+ p256Square(&ftmp, &ftmp) // 2^6 - 2^2
+ p256Square(&ftmp, &ftmp) // 2^7 - 2^3
+ p256Square(&ftmp, &ftmp) // 2^8 - 2^4
+ p256Mul(&ftmp, &ftmp, &e4) // 2^8 - 2^0
+ p256Assign(&e8, &ftmp)
+ for i := 0; i < 8; i++ {
+ p256Square(&ftmp, &ftmp)
+ } // 2^16 - 2^8
+ p256Mul(&ftmp, &ftmp, &e8) // 2^16 - 2^0
+ p256Assign(&e16, &ftmp)
+ for i := 0; i < 16; i++ {
+ p256Square(&ftmp, &ftmp)
+ } // 2^32 - 2^16
+ p256Mul(&ftmp, &ftmp, &e16) // 2^32 - 2^0
+ p256Assign(&e32, &ftmp)
+ for i := 0; i < 32; i++ {
+ p256Square(&ftmp, &ftmp)
+ } // 2^64 - 2^32
+ p256Assign(&e64, &ftmp)
+ p256Mul(&ftmp, &ftmp, in) // 2^64 - 2^32 + 2^0
+ for i := 0; i < 192; i++ {
+ p256Square(&ftmp, &ftmp)
+ } // 2^256 - 2^224 + 2^192
+
+ p256Mul(&ftmp2, &e64, &e32) // 2^64 - 2^0
+ for i := 0; i < 16; i++ {
+ p256Square(&ftmp2, &ftmp2)
+ } // 2^80 - 2^16
+ p256Mul(&ftmp2, &ftmp2, &e16) // 2^80 - 2^0
+ for i := 0; i < 8; i++ {
+ p256Square(&ftmp2, &ftmp2)
+ } // 2^88 - 2^8
+ p256Mul(&ftmp2, &ftmp2, &e8) // 2^88 - 2^0
+ for i := 0; i < 4; i++ {
+ p256Square(&ftmp2, &ftmp2)
+ } // 2^92 - 2^4
+ p256Mul(&ftmp2, &ftmp2, &e4) // 2^92 - 2^0
+ p256Square(&ftmp2, &ftmp2) // 2^93 - 2^1
+ p256Square(&ftmp2, &ftmp2) // 2^94 - 2^2
+ p256Mul(&ftmp2, &ftmp2, &e2) // 2^94 - 2^0
+ p256Square(&ftmp2, &ftmp2) // 2^95 - 2^1
+ p256Square(&ftmp2, &ftmp2) // 2^96 - 2^2
+ p256Mul(&ftmp2, &ftmp2, in) // 2^96 - 3
+
+ p256Mul(out, &ftmp2, &ftmp) // 2^256 - 2^224 + 2^192 + 2^96 - 3
+}
+
+// p256Scalar3 sets out=3*out.
+//
+// On entry: out[0,2,...] < 2**30, out[1,3,...] < 2**29.
+// On exit: out[0,2,...] < 2**30, out[1,3,...] < 2**29.
+func p256Scalar3(out *[p256Limbs]uint32) {
+ var carry uint32
+
+ for i := 0; ; i++ {
+ out[i] *= 3
+ out[i] += carry
+ carry = out[i] >> 29
+ out[i] &= bottom29Bits
+
+ i++
+ if i == p256Limbs {
+ break
+ }
+
+ out[i] *= 3
+ out[i] += carry
+ carry = out[i] >> 28
+ out[i] &= bottom28Bits
+ }
+
+ p256ReduceCarry(out, carry)
+}
+
+// p256Scalar4 sets out=4*out.
+//
+// On entry: out[0,2,...] < 2**30, out[1,3,...] < 2**29.
+// On exit: out[0,2,...] < 2**30, out[1,3,...] < 2**29.
+func p256Scalar4(out *[p256Limbs]uint32) {
+ var carry, nextCarry uint32
+
+ for i := 0; ; i++ {
+ nextCarry = out[i] >> 27
+ out[i] <<= 2
+ out[i] &= bottom29Bits
+ out[i] += carry
+ carry = nextCarry + (out[i] >> 29)
+ out[i] &= bottom29Bits
+
+ i++
+ if i == p256Limbs {
+ break
+ }
+ nextCarry = out[i] >> 26
+ out[i] <<= 2
+ out[i] &= bottom28Bits
+ out[i] += carry
+ carry = nextCarry + (out[i] >> 28)
+ out[i] &= bottom28Bits
+ }
+
+ p256ReduceCarry(out, carry)
+}
+
+// p256Scalar8 sets out=8*out.
+//
+// On entry: out[0,2,...] < 2**30, out[1,3,...] < 2**29.
+// On exit: out[0,2,...] < 2**30, out[1,3,...] < 2**29.
+func p256Scalar8(out *[p256Limbs]uint32) {
+ var carry, nextCarry uint32
+
+ for i := 0; ; i++ {
+ nextCarry = out[i] >> 26
+ out[i] <<= 3
+ out[i] &= bottom29Bits
+ out[i] += carry
+ carry = nextCarry + (out[i] >> 29)
+ out[i] &= bottom29Bits
+
+ i++
+ if i == p256Limbs {
+ break
+ }
+ nextCarry = out[i] >> 25
+ out[i] <<= 3
+ out[i] &= bottom28Bits
+ out[i] += carry
+ carry = nextCarry + (out[i] >> 28)
+ out[i] &= bottom28Bits
+ }
+
+ p256ReduceCarry(out, carry)
+}
+
+// Group operations:
+//
+// Elements of the elliptic curve group are represented in Jacobian
+// coordinates: (x, y, z). An affine point (x', y') is x'=x/z**2, y'=y/z**3 in
+// Jacobian form.
+
+// p256PointDouble sets {xOut,yOut,zOut} = 2*{x,y,z}.
+//
+// See http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l
+func p256PointDouble(xOut, yOut, zOut, x, y, z *[p256Limbs]uint32) {
+ var delta, gamma, alpha, beta, tmp, tmp2 [p256Limbs]uint32
+
+ p256Square(&delta, z)
+ p256Square(&gamma, y)
+ p256Mul(&beta, x, &gamma)
+
+ p256Sum(&tmp, x, &delta)
+ p256Diff(&tmp2, x, &delta)
+ p256Mul(&alpha, &tmp, &tmp2)
+ p256Scalar3(&alpha)
+
+ p256Sum(&tmp, y, z)
+ p256Square(&tmp, &tmp)
+ p256Diff(&tmp, &tmp, &gamma)
+ p256Diff(zOut, &tmp, &delta)
+
+ p256Scalar4(&beta)
+ p256Square(xOut, &alpha)
+ p256Diff(xOut, xOut, &beta)
+ p256Diff(xOut, xOut, &beta)
+
+ p256Diff(&tmp, &beta, xOut)
+ p256Mul(&tmp, &alpha, &tmp)
+ p256Square(&tmp2, &gamma)
+ p256Scalar8(&tmp2)
+ p256Diff(yOut, &tmp, &tmp2)
+}
+
+// p256PointAddMixed sets {xOut,yOut,zOut} = {x1,y1,z1} + {x2,y2,1}.
+// (i.e. the second point is affine.)
+//
+// See http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-add-2007-bl
+//
+// Note that this function does not handle P+P, infinity+P nor P+infinity
+// correctly.
+func p256PointAddMixed(xOut, yOut, zOut, x1, y1, z1, x2, y2 *[p256Limbs]uint32) {
+ var z1z1, z1z1z1, s2, u2, h, i, j, r, rr, v, tmp [p256Limbs]uint32
+
+ p256Square(&z1z1, z1)
+ p256Sum(&tmp, z1, z1)
+
+ p256Mul(&u2, x2, &z1z1)
+ p256Mul(&z1z1z1, z1, &z1z1)
+ p256Mul(&s2, y2, &z1z1z1)
+ p256Diff(&h, &u2, x1)
+ p256Sum(&i, &h, &h)
+ p256Square(&i, &i)
+ p256Mul(&j, &h, &i)
+ p256Diff(&r, &s2, y1)
+ p256Sum(&r, &r, &r)
+ p256Mul(&v, x1, &i)
+
+ p256Mul(zOut, &tmp, &h)
+ p256Square(&rr, &r)
+ p256Diff(xOut, &rr, &j)
+ p256Diff(xOut, xOut, &v)
+ p256Diff(xOut, xOut, &v)
+
+ p256Diff(&tmp, &v, xOut)
+ p256Mul(yOut, &tmp, &r)
+ p256Mul(&tmp, y1, &j)
+ p256Diff(yOut, yOut, &tmp)
+ p256Diff(yOut, yOut, &tmp)
+}
+
+// p256PointAdd sets {xOut,yOut,zOut} = {x1,y1,z1} + {x2,y2,z2}.
+//
+// See http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-add-2007-bl
+//
+// Note that this function does not handle P+P, infinity+P nor P+infinity
+// correctly.
+func p256PointAdd(xOut, yOut, zOut, x1, y1, z1, x2, y2, z2 *[p256Limbs]uint32) {
+ var z1z1, z1z1z1, z2z2, z2z2z2, s1, s2, u1, u2, h, i, j, r, rr, v, tmp [p256Limbs]uint32
+
+ p256Square(&z1z1, z1)
+ p256Square(&z2z2, z2)
+ p256Mul(&u1, x1, &z2z2)
+
+ p256Sum(&tmp, z1, z2)
+ p256Square(&tmp, &tmp)
+ p256Diff(&tmp, &tmp, &z1z1)
+ p256Diff(&tmp, &tmp, &z2z2)
+
+ p256Mul(&z2z2z2, z2, &z2z2)
+ p256Mul(&s1, y1, &z2z2z2)
+
+ p256Mul(&u2, x2, &z1z1)
+ p256Mul(&z1z1z1, z1, &z1z1)
+ p256Mul(&s2, y2, &z1z1z1)
+ p256Diff(&h, &u2, &u1)
+ p256Sum(&i, &h, &h)
+ p256Square(&i, &i)
+ p256Mul(&j, &h, &i)
+ p256Diff(&r, &s2, &s1)
+ p256Sum(&r, &r, &r)
+ p256Mul(&v, &u1, &i)
+
+ p256Mul(zOut, &tmp, &h)
+ p256Square(&rr, &r)
+ p256Diff(xOut, &rr, &j)
+ p256Diff(xOut, xOut, &v)
+ p256Diff(xOut, xOut, &v)
+
+ p256Diff(&tmp, &v, xOut)
+ p256Mul(yOut, &tmp, &r)
+ p256Mul(&tmp, &s1, &j)
+ p256Diff(yOut, yOut, &tmp)
+ p256Diff(yOut, yOut, &tmp)
+}
+
+// p256CopyConditional sets out=in if mask = 0xffffffff in constant time.
+//
+// On entry: mask is either 0 or 0xffffffff.
+func p256CopyConditional(out, in *[p256Limbs]uint32, mask uint32) {
+ for i := 0; i < p256Limbs; i++ {
+ tmp := mask & (in[i] ^ out[i])
+ out[i] ^= tmp
+ }
+}
+
+// p256SelectAffinePoint sets {out_x,out_y} to the index'th entry of table.
+// On entry: index < 16, table[0] must be zero.
+func p256SelectAffinePoint(xOut, yOut *[p256Limbs]uint32, table []uint32, index uint32) {
+ for i := range xOut {
+ xOut[i] = 0
+ }
+ for i := range yOut {
+ yOut[i] = 0
+ }
+
+ for i := uint32(1); i < 16; i++ {
+ mask := i ^ index
+ mask |= mask >> 2
+ mask |= mask >> 1
+ mask &= 1
+ mask--
+ for j := range xOut {
+ xOut[j] |= table[0] & mask
+ table = table[1:]
+ }
+ for j := range yOut {
+ yOut[j] |= table[0] & mask
+ table = table[1:]
+ }
+ }
+}
+
+// p256SelectJacobianPoint sets {out_x,out_y,out_z} to the index'th entry of
+// table.
+// On entry: index < 16, table[0] must be zero.
+func p256SelectJacobianPoint(xOut, yOut, zOut *[p256Limbs]uint32, table *[16][3][p256Limbs]uint32, index uint32) {
+ for i := range xOut {
+ xOut[i] = 0
+ }
+ for i := range yOut {
+ yOut[i] = 0
+ }
+ for i := range zOut {
+ zOut[i] = 0
+ }
+
+ // The implicit value at index 0 is all zero. We don't need to perform that
+ // iteration of the loop because we already set out_* to zero.
+ for i := uint32(1); i < 16; i++ {
+ mask := i ^ index
+ mask |= mask >> 2
+ mask |= mask >> 1
+ mask &= 1
+ mask--
+ for j := range xOut {
+ xOut[j] |= table[i][0][j] & mask
+ }
+ for j := range yOut {
+ yOut[j] |= table[i][1][j] & mask
+ }
+ for j := range zOut {
+ zOut[j] |= table[i][2][j] & mask
+ }
+ }
+}
+
+// p256GetBit returns the bit'th bit of scalar.
+func p256GetBit(scalar *[32]uint8, bit uint) uint32 {
+ return uint32(((scalar[bit>>3]) >> (bit & 7)) & 1)
+}
+
+// p256ScalarBaseMult sets {xOut,yOut,zOut} = scalar*G where scalar is a
+// little-endian number. Note that the value of scalar must be less than the
+// order of the group.
+func p256ScalarBaseMult(xOut, yOut, zOut *[p256Limbs]uint32, scalar *[32]uint8) {
+ nIsInfinityMask := ^uint32(0)
+ var pIsNoninfiniteMask, mask, tableOffset uint32
+ var px, py, tx, ty, tz [p256Limbs]uint32
+
+ for i := range xOut {
+ xOut[i] = 0
+ }
+ for i := range yOut {
+ yOut[i] = 0
+ }
+ for i := range zOut {
+ zOut[i] = 0
+ }
+
+ // The loop adds bits at positions 0, 64, 128 and 192, followed by
+ // positions 32,96,160 and 224 and does this 32 times.
+ for i := uint(0); i < 32; i++ {
+ if i != 0 {
+ p256PointDouble(xOut, yOut, zOut, xOut, yOut, zOut)
+ }
+ tableOffset = 0
+ for j := uint(0); j <= 32; j += 32 {
+ bit0 := p256GetBit(scalar, 31-i+j)
+ bit1 := p256GetBit(scalar, 95-i+j)
+ bit2 := p256GetBit(scalar, 159-i+j)
+ bit3 := p256GetBit(scalar, 223-i+j)
+ index := bit0 | (bit1 << 1) | (bit2 << 2) | (bit3 << 3)
+
+ p256SelectAffinePoint(&px, &py, p256Precomputed[tableOffset:], index)
+ tableOffset += 30 * p256Limbs
+
+ // Since scalar is less than the order of the group, we know that
+ // {xOut,yOut,zOut} != {px,py,1}, unless both are zero, which we handle
+ // below.
+ p256PointAddMixed(&tx, &ty, &tz, xOut, yOut, zOut, &px, &py)
+ // The result of pointAddMixed is incorrect if {xOut,yOut,zOut} is zero
+ // (a.k.a. the point at infinity). We handle that situation by
+ // copying the point from the table.
+ p256CopyConditional(xOut, &px, nIsInfinityMask)
+ p256CopyConditional(yOut, &py, nIsInfinityMask)
+ p256CopyConditional(zOut, &p256One, nIsInfinityMask)
+
+ // Equally, the result is also wrong if the point from the table is
+ // zero, which happens when the index is zero. We handle that by
+ // only copying from {tx,ty,tz} to {xOut,yOut,zOut} if index != 0.
+ pIsNoninfiniteMask = nonZeroToAllOnes(index)
+ mask = pIsNoninfiniteMask & ^nIsInfinityMask
+ p256CopyConditional(xOut, &tx, mask)
+ p256CopyConditional(yOut, &ty, mask)
+ p256CopyConditional(zOut, &tz, mask)
+ // If p was not zero, then n is now non-zero.
+ nIsInfinityMask &= ^pIsNoninfiniteMask
+ }
+ }
+}
+
+// p256PointToAffine converts a Jacobian point to an affine point. If the input
+// is the point at infinity then it returns (0, 0) in constant time.
+func p256PointToAffine(xOut, yOut, x, y, z *[p256Limbs]uint32) {
+ var zInv, zInvSq [p256Limbs]uint32
+
+ p256Invert(&zInv, z)
+ p256Square(&zInvSq, &zInv)
+ p256Mul(xOut, x, &zInvSq)
+ p256Mul(&zInv, &zInv, &zInvSq)
+ p256Mul(yOut, y, &zInv)
+}
+
+// p256ToAffine returns a pair of *big.Int containing the affine representation
+// of {x,y,z}.
+func p256ToAffine(x, y, z *[p256Limbs]uint32) (xOut, yOut *big.Int) {
+ var xx, yy [p256Limbs]uint32
+ p256PointToAffine(&xx, &yy, x, y, z)
+ return p256ToBig(&xx), p256ToBig(&yy)
+}
+
+// p256ScalarMult sets {xOut,yOut,zOut} = scalar*{x,y}.
+func p256ScalarMult(xOut, yOut, zOut, x, y *[p256Limbs]uint32, scalar *[32]uint8) {
+ var px, py, pz, tx, ty, tz [p256Limbs]uint32
+ var precomp [16][3][p256Limbs]uint32
+ var nIsInfinityMask, index, pIsNoninfiniteMask, mask uint32
+
+ // We precompute 0,1,2,... times {x,y}.
+ precomp[1][0] = *x
+ precomp[1][1] = *y
+ precomp[1][2] = p256One
+
+ for i := 2; i < 16; i += 2 {
+ p256PointDouble(&precomp[i][0], &precomp[i][1], &precomp[i][2], &precomp[i/2][0], &precomp[i/2][1], &precomp[i/2][2])
+ p256PointAddMixed(&precomp[i+1][0], &precomp[i+1][1], &precomp[i+1][2], &precomp[i][0], &precomp[i][1], &precomp[i][2], x, y)
+ }
+
+ for i := range xOut {
+ xOut[i] = 0
+ }
+ for i := range yOut {
+ yOut[i] = 0
+ }
+ for i := range zOut {
+ zOut[i] = 0
+ }
+ nIsInfinityMask = ^uint32(0)
+
+ // We add in a window of four bits each iteration and do this 64 times.
+ for i := 0; i < 64; i++ {
+ if i != 0 {
+ p256PointDouble(xOut, yOut, zOut, xOut, yOut, zOut)
+ p256PointDouble(xOut, yOut, zOut, xOut, yOut, zOut)
+ p256PointDouble(xOut, yOut, zOut, xOut, yOut, zOut)
+ p256PointDouble(xOut, yOut, zOut, xOut, yOut, zOut)
+ }
+
+ index = uint32(scalar[31-i/2])
+ if (i & 1) == 1 {
+ index &= 15
+ } else {
+ index >>= 4
+ }
+
+ // See the comments in scalarBaseMult about handling infinities.
+ p256SelectJacobianPoint(&px, &py, &pz, &precomp, index)
+ p256PointAdd(&tx, &ty, &tz, xOut, yOut, zOut, &px, &py, &pz)
+ p256CopyConditional(xOut, &px, nIsInfinityMask)
+ p256CopyConditional(yOut, &py, nIsInfinityMask)
+ p256CopyConditional(zOut, &pz, nIsInfinityMask)
+
+ pIsNoninfiniteMask = nonZeroToAllOnes(index)
+ mask = pIsNoninfiniteMask & ^nIsInfinityMask
+ p256CopyConditional(xOut, &tx, mask)
+ p256CopyConditional(yOut, &ty, mask)
+ p256CopyConditional(zOut, &tz, mask)
+ nIsInfinityMask &= ^pIsNoninfiniteMask
+ }
+}
+
+// p256FromBig sets out = R*in.
+func p256FromBig(out *[p256Limbs]uint32, in *big.Int) {
+ tmp := new(big.Int).Lsh(in, 257)
+ tmp.Mod(tmp, p256.P)
+
+ for i := 0; i < p256Limbs; i++ {
+ if bits := tmp.Bits(); len(bits) > 0 {
+ out[i] = uint32(bits[0]) & bottom29Bits
+ } else {
+ out[i] = 0
+ }
+ tmp.Rsh(tmp, 29)
+
+ i++
+ if i == p256Limbs {
+ break
+ }
+
+ if bits := tmp.Bits(); len(bits) > 0 {
+ out[i] = uint32(bits[0]) & bottom28Bits
+ } else {
+ out[i] = 0
+ }
+ tmp.Rsh(tmp, 28)
+ }
+}
+
+// p256ToBig returns a *big.Int containing the value of in.
+func p256ToBig(in *[p256Limbs]uint32) *big.Int {
+ result, tmp := new(big.Int), new(big.Int)
+
+ result.SetInt64(int64(in[p256Limbs-1]))
+ for i := p256Limbs - 2; i >= 0; i-- {
+ if (i & 1) == 0 {
+ result.Lsh(result, 29)
+ } else {
+ result.Lsh(result, 28)
+ }
+ tmp.SetInt64(int64(in[i]))
+ result.Add(result, tmp)
+ }
+
+ result.Mul(result, p256RInverse)
+ result.Mod(result, p256.P)
+ return result
+}
diff --git a/libgo/go/crypto/md5/gen.go b/libgo/go/crypto/md5/gen.go
index 275b4aeea39..ccaa7c13d38 100644
--- a/libgo/go/crypto/md5/gen.go
+++ b/libgo/go/crypto/md5/gen.go
@@ -164,7 +164,7 @@ var program = `
// DO NOT EDIT.
// Generate with: go run gen.go{{if .Full}} -full{{end}} | gofmt >md5block.go
-// +build !amd64
+// +build !amd64,!386,!arm
package md5
diff --git a/libgo/go/crypto/md5/md5.go b/libgo/go/crypto/md5/md5.go
index 825e5c8a282..1a1f35fabc0 100644
--- a/libgo/go/crypto/md5/md5.go
+++ b/libgo/go/crypto/md5/md5.go
@@ -88,7 +88,11 @@ func (d *digest) Write(p []byte) (nn int, err error) {
func (d0 *digest) Sum(in []byte) []byte {
// Make a copy of d0 so that caller can keep writing and summing.
d := *d0
+ hash := d.checkSum()
+ return append(in, hash[:]...)
+}
+func (d *digest) checkSum() [Size]byte {
// Padding. Add a 1 bit and 0 bits until 56 bytes mod 64.
len := d.len
var tmp [64]byte
@@ -118,5 +122,13 @@ func (d0 *digest) Sum(in []byte) []byte {
digest[i*4+3] = byte(s >> 24)
}
- return append(in, digest[:]...)
+ return digest
+}
+
+// Sum returns the MD5 checksum of the data.
+func Sum(data []byte) [Size]byte {
+ var d digest
+ d.Reset()
+ d.Write(data)
+ return d.checkSum()
}
diff --git a/libgo/go/crypto/md5/md5_test.go b/libgo/go/crypto/md5/md5_test.go
index 3ef4519b9ad..a8b7a1a5252 100644
--- a/libgo/go/crypto/md5/md5_test.go
+++ b/libgo/go/crypto/md5/md5_test.go
@@ -53,6 +53,10 @@ var golden = []md5Test{
func TestGolden(t *testing.T) {
for i := 0; i < len(golden); i++ {
g := golden[i]
+ s := fmt.Sprintf("%x", Sum([]byte(g.in)))
+ if s != g.out {
+ t.Fatalf("Sum function: md5(%s) = %s want %s", g.in, s, g.out)
+ }
c := New()
buf := make([]byte, len(g.in)+4)
for j := 0; j < 3+4; j++ {
@@ -77,12 +81,28 @@ func TestGolden(t *testing.T) {
}
}
-func ExampleNew() {
- h := New()
- io.WriteString(h, "The fog is getting thicker!")
- io.WriteString(h, "And Leon's getting laaarger!")
- fmt.Printf("%x", h.Sum(nil))
- // Output: e2c569be17396eca2a2e3c11578123ed
+func TestLarge(t *testing.T) {
+ const N = 10000
+ ok := "2bb571599a4180e1d542f76904adc3df" // md5sum of "0123456789" * 1000
+ block := make([]byte, 10004)
+ c := New()
+ for offset := 0; offset < 4; offset++ {
+ for i := 0; i < N; i++ {
+ block[offset+i] = '0' + byte(i%10)
+ }
+ for blockSize := 10; blockSize <= N; blockSize *= 10 {
+ blocks := N / blockSize
+ b := block[offset : offset+blockSize]
+ c.Reset()
+ for i := 0; i < blocks; i++ {
+ c.Write(b)
+ }
+ s := fmt.Sprintf("%x", c.Sum(nil))
+ if s != ok {
+ t.Fatalf("md5 TestLarge offset=%d, blockSize=%d = %s want %s", offset, blockSize, s, ok)
+ }
+ }
+ }
}
var bench = New()
diff --git a/libgo/go/crypto/md5/md5block.go b/libgo/go/crypto/md5/md5block.go
index a376fbee99b..3e739e36ffd 100644
--- a/libgo/go/crypto/md5/md5block.go
+++ b/libgo/go/crypto/md5/md5block.go
@@ -1,7 +1,7 @@
// DO NOT EDIT.
// Generate with: go run gen.go -full | gofmt >md5block.go
-// +build !amd64,!386
+// +build !amd64,!386,!arm
package md5
diff --git a/libgo/go/crypto/md5/md5block_decl.go b/libgo/go/crypto/md5/md5block_decl.go
index 14190c6ff29..c4d6aaaf03a 100644
--- a/libgo/go/crypto/md5/md5block_decl.go
+++ b/libgo/go/crypto/md5/md5block_decl.go
@@ -2,8 +2,10 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build amd64 386
+// +build amd64 386 arm
package md5
+//go:noescape
+
func block(dig *digest, p []byte)
diff --git a/libgo/go/crypto/rand/rand.go b/libgo/go/crypto/rand/rand.go
index 59759038ee0..4da3adb7010 100644
--- a/libgo/go/crypto/rand/rand.go
+++ b/libgo/go/crypto/rand/rand.go
@@ -14,5 +14,8 @@ import "io"
// On Windows systems, Reader uses the CryptGenRandom API.
var Reader io.Reader
-// Read is a helper function that calls Reader.Read.
-func Read(b []byte) (n int, err error) { return Reader.Read(b) }
+// Read is a helper function that calls Reader.Read using io.ReadFull.
+// On return, n == len(b) if and only if err == nil.
+func Read(b []byte) (n int, err error) {
+ return io.ReadFull(Reader, b)
+}
diff --git a/libgo/go/crypto/rand/rand_unix.go b/libgo/go/crypto/rand/rand_unix.go
index 18f482472d3..238ceee557d 100644
--- a/libgo/go/crypto/rand/rand_unix.go
+++ b/libgo/go/crypto/rand/rand_unix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd linux netbsd openbsd plan9
+// +build darwin dragonfly freebsd linux netbsd openbsd plan9
// Unix cryptographically secure pseudorandom number
// generator.
diff --git a/libgo/go/crypto/rsa/pkcs1v15.go b/libgo/go/crypto/rsa/pkcs1v15.go
index 28ca5d73b39..1a055a3d623 100644
--- a/libgo/go/crypto/rsa/pkcs1v15.go
+++ b/libgo/go/crypto/rsa/pkcs1v15.go
@@ -124,7 +124,11 @@ func decryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (valid
lookingForIndex = subtle.ConstantTimeSelect(equals0, 0, lookingForIndex)
}
- valid = firstByteIsZero & secondByteIsTwo & (^lookingForIndex & 1)
+ // The PS padding must be at least 8 bytes long, and it starts two
+ // bytes into em.
+ validPS := subtle.ConstantTimeLessOrEq(2+8, index)
+
+ valid = firstByteIsZero & secondByteIsTwo & (^lookingForIndex & 1) & validPS
msg = em[index+1:]
return
}
diff --git a/libgo/go/crypto/rsa/pkcs1v15_test.go b/libgo/go/crypto/rsa/pkcs1v15_test.go
index bf9219bae1b..70bb2288996 100644
--- a/libgo/go/crypto/rsa/pkcs1v15_test.go
+++ b/libgo/go/crypto/rsa/pkcs1v15_test.go
@@ -197,6 +197,14 @@ func TestVerifyPKCS1v15(t *testing.T) {
}
}
+func TestOverlongMessagePKCS1v15(t *testing.T) {
+ ciphertext := decodeBase64("fjOVdirUzFoLlukv80dBllMLjXythIf22feqPrNo0YoIjzyzyoMFiLjAc/Y4krkeZ11XFThIrEvw\nkRiZcCq5ng==")
+ _, err := DecryptPKCS1v15(nil, rsaPrivateKey, ciphertext)
+ if err == nil {
+ t.Error("RSA decrypted a message that was too long.")
+ }
+}
+
// In order to generate new test vectors you'll need the PEM form of this key:
// -----BEGIN RSA PRIVATE KEY-----
// MIIBOgIBAAJBALKZD0nEffqM1ACuak0bijtqE2QrI/KLADv7l3kK3ppMyCuLKoF0
diff --git a/libgo/go/crypto/rsa/pss.go b/libgo/go/crypto/rsa/pss.go
new file mode 100644
index 00000000000..f9abec39490
--- /dev/null
+++ b/libgo/go/crypto/rsa/pss.go
@@ -0,0 +1,282 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package rsa
+
+// This file implementes the PSS signature scheme [1].
+//
+// [1] http://www.rsa.com/rsalabs/pkcs/files/h11300-wp-pkcs-1v2-2-rsa-cryptography-standard.pdf
+
+import (
+ "bytes"
+ "crypto"
+ "errors"
+ "hash"
+ "io"
+ "math/big"
+)
+
+func emsaPSSEncode(mHash []byte, emBits int, salt []byte, hash hash.Hash) ([]byte, error) {
+ // See [1], section 9.1.1
+ hLen := hash.Size()
+ sLen := len(salt)
+ emLen := (emBits + 7) / 8
+
+ // 1. If the length of M is greater than the input limitation for the
+ // hash function (2^61 - 1 octets for SHA-1), output "message too
+ // long" and stop.
+ //
+ // 2. Let mHash = Hash(M), an octet string of length hLen.
+
+ if len(mHash) != hLen {
+ return nil, errors.New("crypto/rsa: input must be hashed message")
+ }
+
+ // 3. If emLen < hLen + sLen + 2, output "encoding error" and stop.
+
+ if emLen < hLen+sLen+2 {
+ return nil, errors.New("crypto/rsa: encoding error")
+ }
+
+ em := make([]byte, emLen)
+ db := em[:emLen-sLen-hLen-2+1+sLen]
+ h := em[emLen-sLen-hLen-2+1+sLen : emLen-1]
+
+ // 4. Generate a random octet string salt of length sLen; if sLen = 0,
+ // then salt is the empty string.
+ //
+ // 5. Let
+ // M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt;
+ //
+ // M' is an octet string of length 8 + hLen + sLen with eight
+ // initial zero octets.
+ //
+ // 6. Let H = Hash(M'), an octet string of length hLen.
+
+ var prefix [8]byte
+
+ hash.Write(prefix[:])
+ hash.Write(mHash)
+ hash.Write(salt)
+
+ h = hash.Sum(h[:0])
+ hash.Reset()
+
+ // 7. Generate an octet string PS consisting of emLen - sLen - hLen - 2
+ // zero octets. The length of PS may be 0.
+ //
+ // 8. Let DB = PS || 0x01 || salt; DB is an octet string of length
+ // emLen - hLen - 1.
+
+ db[emLen-sLen-hLen-2] = 0x01
+ copy(db[emLen-sLen-hLen-1:], salt)
+
+ // 9. Let dbMask = MGF(H, emLen - hLen - 1).
+ //
+ // 10. Let maskedDB = DB \xor dbMask.
+
+ mgf1XOR(db, hash, h)
+
+ // 11. Set the leftmost 8 * emLen - emBits bits of the leftmost octet in
+ // maskedDB to zero.
+
+ db[0] &= (0xFF >> uint(8*emLen-emBits))
+
+ // 12. Let EM = maskedDB || H || 0xbc.
+ em[emLen-1] = 0xBC
+
+ // 13. Output EM.
+ return em, nil
+}
+
+func emsaPSSVerify(mHash, em []byte, emBits, sLen int, hash hash.Hash) error {
+ // 1. If the length of M is greater than the input limitation for the
+ // hash function (2^61 - 1 octets for SHA-1), output "inconsistent"
+ // and stop.
+ //
+ // 2. Let mHash = Hash(M), an octet string of length hLen.
+ hLen := hash.Size()
+ if hLen != len(mHash) {
+ return ErrVerification
+ }
+
+ // 3. If emLen < hLen + sLen + 2, output "inconsistent" and stop.
+ emLen := (emBits + 7) / 8
+ if emLen < hLen+sLen+2 {
+ return ErrVerification
+ }
+
+ // 4. If the rightmost octet of EM does not have hexadecimal value
+ // 0xbc, output "inconsistent" and stop.
+ if em[len(em)-1] != 0xBC {
+ return ErrVerification
+ }
+
+ // 5. Let maskedDB be the leftmost emLen - hLen - 1 octets of EM, and
+ // let H be the next hLen octets.
+ db := em[:emLen-hLen-1]
+ h := em[emLen-hLen-1 : len(em)-1]
+
+ // 6. If the leftmost 8 * emLen - emBits bits of the leftmost octet in
+ // maskedDB are not all equal to zero, output "inconsistent" and
+ // stop.
+ if em[0]&(0xFF<<uint(8-(8*emLen-emBits))) != 0 {
+ return ErrVerification
+ }
+
+ // 7. Let dbMask = MGF(H, emLen - hLen - 1).
+ //
+ // 8. Let DB = maskedDB \xor dbMask.
+ mgf1XOR(db, hash, h)
+
+ // 9. Set the leftmost 8 * emLen - emBits bits of the leftmost octet in DB
+ // to zero.
+ db[0] &= (0xFF >> uint(8*emLen-emBits))
+
+ if sLen == PSSSaltLengthAuto {
+ FindSaltLength:
+ for sLen = emLen - (hLen + 2); sLen >= 0; sLen-- {
+ switch db[emLen-hLen-sLen-2] {
+ case 1:
+ break FindSaltLength
+ case 0:
+ continue
+ default:
+ return ErrVerification
+ }
+ }
+ if sLen < 0 {
+ return ErrVerification
+ }
+ } else {
+ // 10. If the emLen - hLen - sLen - 2 leftmost octets of DB are not zero
+ // or if the octet at position emLen - hLen - sLen - 1 (the leftmost
+ // position is "position 1") does not have hexadecimal value 0x01,
+ // output "inconsistent" and stop.
+ for _, e := range db[:emLen-hLen-sLen-2] {
+ if e != 0x00 {
+ return ErrVerification
+ }
+ }
+ if db[emLen-hLen-sLen-2] != 0x01 {
+ return ErrVerification
+ }
+ }
+
+ // 11. Let salt be the last sLen octets of DB.
+ salt := db[len(db)-sLen:]
+
+ // 12. Let
+ // M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt ;
+ // M' is an octet string of length 8 + hLen + sLen with eight
+ // initial zero octets.
+ //
+ // 13. Let H' = Hash(M'), an octet string of length hLen.
+ var prefix [8]byte
+ hash.Write(prefix[:])
+ hash.Write(mHash)
+ hash.Write(salt)
+
+ h0 := hash.Sum(nil)
+
+ // 14. If H = H', output "consistent." Otherwise, output "inconsistent."
+ if !bytes.Equal(h0, h) {
+ return ErrVerification
+ }
+ return nil
+}
+
+// signPSSWithSalt calculates the signature of hashed using PSS [1] with specified salt.
+// Note that hashed must be the result of hashing the input message using the
+// given hash funcion. salt is a random sequence of bytes whose length will be
+// later used to verify the signature.
+func signPSSWithSalt(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed, salt []byte) (s []byte, err error) {
+ nBits := priv.N.BitLen()
+ em, err := emsaPSSEncode(hashed, nBits-1, salt, hash.New())
+ if err != nil {
+ return
+ }
+ m := new(big.Int).SetBytes(em)
+ c, err := decrypt(rand, priv, m)
+ if err != nil {
+ return
+ }
+ s = make([]byte, (nBits+7)/8)
+ copyWithLeftPad(s, c.Bytes())
+ return
+}
+
+const (
+ // PSSSaltLengthAuto causes the salt in a PSS signature to be as large
+ // as possible when signing, and to be auto-detected when verifying.
+ PSSSaltLengthAuto = 0
+ // PSSSaltLengthEqualsHash causes the salt length to equal the length
+ // of the hash used in the signature.
+ PSSSaltLengthEqualsHash = -1
+)
+
+// PSSOptions contains options for creating and verifying PSS signatures.
+type PSSOptions struct {
+ // SaltLength controls the length of the salt used in the PSS
+ // signature. It can either be a number of bytes, or one of the special
+ // PSSSaltLength constants.
+ SaltLength int
+}
+
+func (opts *PSSOptions) saltLength() int {
+ if opts == nil {
+ return PSSSaltLengthAuto
+ }
+ return opts.SaltLength
+}
+
+// SignPSS calculates the signature of hashed using RSASSA-PSS [1].
+// Note that hashed must be the result of hashing the input message using the
+// given hash funcion. The opts argument may be nil, in which case sensible
+// defaults are used.
+func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte, opts *PSSOptions) (s []byte, err error) {
+ saltLength := opts.saltLength()
+ switch saltLength {
+ case PSSSaltLengthAuto:
+ saltLength = (priv.N.BitLen()+7)/8 - 2 - hash.Size()
+ case PSSSaltLengthEqualsHash:
+ saltLength = hash.Size()
+ }
+
+ salt := make([]byte, saltLength)
+ if _, err = io.ReadFull(rand, salt); err != nil {
+ return
+ }
+ return signPSSWithSalt(rand, priv, hash, hashed, salt)
+}
+
+// VerifyPSS verifies a PSS signature.
+// hashed is the result of hashing the input message using the given hash
+// function and sig is the signature. A valid signature is indicated by
+// returning a nil error. The opts argument may be nil, in which case sensible
+// defaults are used.
+func VerifyPSS(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte, opts *PSSOptions) error {
+ return verifyPSS(pub, hash, hashed, sig, opts.saltLength())
+}
+
+// verifyPSS verifies a PSS signature with the given salt length.
+func verifyPSS(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte, saltLen int) error {
+ nBits := pub.N.BitLen()
+ if len(sig) != (nBits+7)/8 {
+ return ErrVerification
+ }
+ s := new(big.Int).SetBytes(sig)
+ m := encrypt(new(big.Int), pub, s)
+ emBits := nBits - 1
+ emLen := (emBits + 7) / 8
+ if emLen < len(m.Bytes()) {
+ return ErrVerification
+ }
+ em := make([]byte, emLen)
+ copyWithLeftPad(em, m.Bytes())
+ if saltLen == PSSSaltLengthEqualsHash {
+ saltLen = hash.Size()
+ }
+ return emsaPSSVerify(hashed, em, emBits, saltLen, hash.New())
+}
diff --git a/libgo/go/crypto/rsa/pss_test.go b/libgo/go/crypto/rsa/pss_test.go
new file mode 100644
index 00000000000..32e6fc39d29
--- /dev/null
+++ b/libgo/go/crypto/rsa/pss_test.go
@@ -0,0 +1,249 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package rsa
+
+import (
+ "bufio"
+ "bytes"
+ "compress/bzip2"
+ "crypto"
+ _ "crypto/md5"
+ "crypto/rand"
+ "crypto/sha1"
+ _ "crypto/sha256"
+ "encoding/hex"
+ "math/big"
+ "os"
+ "strconv"
+ "strings"
+ "testing"
+)
+
+func TestEMSAPSS(t *testing.T) {
+ // Test vector in file pss-int.txt from: ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip
+ msg := []byte{
+ 0x85, 0x9e, 0xef, 0x2f, 0xd7, 0x8a, 0xca, 0x00, 0x30, 0x8b,
+ 0xdc, 0x47, 0x11, 0x93, 0xbf, 0x55, 0xbf, 0x9d, 0x78, 0xdb,
+ 0x8f, 0x8a, 0x67, 0x2b, 0x48, 0x46, 0x34, 0xf3, 0xc9, 0xc2,
+ 0x6e, 0x64, 0x78, 0xae, 0x10, 0x26, 0x0f, 0xe0, 0xdd, 0x8c,
+ 0x08, 0x2e, 0x53, 0xa5, 0x29, 0x3a, 0xf2, 0x17, 0x3c, 0xd5,
+ 0x0c, 0x6d, 0x5d, 0x35, 0x4f, 0xeb, 0xf7, 0x8b, 0x26, 0x02,
+ 0x1c, 0x25, 0xc0, 0x27, 0x12, 0xe7, 0x8c, 0xd4, 0x69, 0x4c,
+ 0x9f, 0x46, 0x97, 0x77, 0xe4, 0x51, 0xe7, 0xf8, 0xe9, 0xe0,
+ 0x4c, 0xd3, 0x73, 0x9c, 0x6b, 0xbf, 0xed, 0xae, 0x48, 0x7f,
+ 0xb5, 0x56, 0x44, 0xe9, 0xca, 0x74, 0xff, 0x77, 0xa5, 0x3c,
+ 0xb7, 0x29, 0x80, 0x2f, 0x6e, 0xd4, 0xa5, 0xff, 0xa8, 0xba,
+ 0x15, 0x98, 0x90, 0xfc,
+ }
+ salt := []byte{
+ 0xe3, 0xb5, 0xd5, 0xd0, 0x02, 0xc1, 0xbc, 0xe5, 0x0c, 0x2b,
+ 0x65, 0xef, 0x88, 0xa1, 0x88, 0xd8, 0x3b, 0xce, 0x7e, 0x61,
+ }
+ expected := []byte{
+ 0x66, 0xe4, 0x67, 0x2e, 0x83, 0x6a, 0xd1, 0x21, 0xba, 0x24,
+ 0x4b, 0xed, 0x65, 0x76, 0xb8, 0x67, 0xd9, 0xa4, 0x47, 0xc2,
+ 0x8a, 0x6e, 0x66, 0xa5, 0xb8, 0x7d, 0xee, 0x7f, 0xbc, 0x7e,
+ 0x65, 0xaf, 0x50, 0x57, 0xf8, 0x6f, 0xae, 0x89, 0x84, 0xd9,
+ 0xba, 0x7f, 0x96, 0x9a, 0xd6, 0xfe, 0x02, 0xa4, 0xd7, 0x5f,
+ 0x74, 0x45, 0xfe, 0xfd, 0xd8, 0x5b, 0x6d, 0x3a, 0x47, 0x7c,
+ 0x28, 0xd2, 0x4b, 0xa1, 0xe3, 0x75, 0x6f, 0x79, 0x2d, 0xd1,
+ 0xdc, 0xe8, 0xca, 0x94, 0x44, 0x0e, 0xcb, 0x52, 0x79, 0xec,
+ 0xd3, 0x18, 0x3a, 0x31, 0x1f, 0xc8, 0x96, 0xda, 0x1c, 0xb3,
+ 0x93, 0x11, 0xaf, 0x37, 0xea, 0x4a, 0x75, 0xe2, 0x4b, 0xdb,
+ 0xfd, 0x5c, 0x1d, 0xa0, 0xde, 0x7c, 0xec, 0xdf, 0x1a, 0x89,
+ 0x6f, 0x9d, 0x8b, 0xc8, 0x16, 0xd9, 0x7c, 0xd7, 0xa2, 0xc4,
+ 0x3b, 0xad, 0x54, 0x6f, 0xbe, 0x8c, 0xfe, 0xbc,
+ }
+
+ hash := sha1.New()
+ hash.Write(msg)
+ hashed := hash.Sum(nil)
+
+ encoded, err := emsaPSSEncode(hashed, 1023, salt, sha1.New())
+ if err != nil {
+ t.Errorf("Error from emsaPSSEncode: %s\n", err)
+ }
+ if !bytes.Equal(encoded, expected) {
+ t.Errorf("Bad encoding. got %x, want %x", encoded, expected)
+ }
+
+ if err = emsaPSSVerify(hashed, encoded, 1023, len(salt), sha1.New()); err != nil {
+ t.Errorf("Bad verification: %s", err)
+ }
+}
+
+// TestPSSGolden tests all the test vectors in pss-vect.txt from
+// ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip
+func TestPSSGolden(t *testing.T) {
+ inFile, err := os.Open("testdata/pss-vect.txt.bz2")
+ if err != nil {
+ t.Fatalf("Failed to open input file: %s", err)
+ }
+ defer inFile.Close()
+
+ // The pss-vect.txt file contains RSA keys and then a series of
+ // signatures. A goroutine is used to preprocess the input by merging
+ // lines, removing spaces in hex values and identifying the start of
+ // new keys and signature blocks.
+ const newKeyMarker = "START NEW KEY"
+ const newSignatureMarker = "START NEW SIGNATURE"
+
+ values := make(chan string)
+
+ go func() {
+ defer close(values)
+ scanner := bufio.NewScanner(bzip2.NewReader(inFile))
+ var partialValue string
+ lastWasValue := true
+
+ for scanner.Scan() {
+ line := scanner.Text()
+ switch {
+ case len(line) == 0:
+ if len(partialValue) > 0 {
+ values <- strings.Replace(partialValue, " ", "", -1)
+ partialValue = ""
+ lastWasValue = true
+ }
+ continue
+ case strings.HasPrefix(line, "# ======") && lastWasValue:
+ values <- newKeyMarker
+ lastWasValue = false
+ case strings.HasPrefix(line, "# ------") && lastWasValue:
+ values <- newSignatureMarker
+ lastWasValue = false
+ case strings.HasPrefix(line, "#"):
+ continue
+ default:
+ partialValue += line
+ }
+ }
+ if err := scanner.Err(); err != nil {
+ panic(err)
+ }
+ }()
+
+ var key *PublicKey
+ var hashed []byte
+ hash := crypto.SHA1
+ h := hash.New()
+ opts := &PSSOptions{
+ SaltLength: PSSSaltLengthEqualsHash,
+ }
+
+ for marker := range values {
+ switch marker {
+ case newKeyMarker:
+ key = new(PublicKey)
+ nHex, ok := <-values
+ if !ok {
+ continue
+ }
+ key.N = bigFromHex(nHex)
+ key.E = intFromHex(<-values)
+ // We don't care for d, p, q, dP, dQ or qInv.
+ for i := 0; i < 6; i++ {
+ <-values
+ }
+ case newSignatureMarker:
+ msg := fromHex(<-values)
+ <-values // skip salt
+ sig := fromHex(<-values)
+
+ h.Reset()
+ h.Write(msg)
+ hashed = h.Sum(hashed[:0])
+
+ if err := VerifyPSS(key, hash, hashed, sig, opts); err != nil {
+ t.Error(err)
+ }
+ default:
+ t.Fatalf("unknown marker: " + marker)
+ }
+ }
+}
+
+// TestPSSOpenSSL ensures that we can verify a PSS signature from OpenSSL with
+// the default options. OpenSSL sets the salt length to be maximal.
+func TestPSSOpenSSL(t *testing.T) {
+ hash := crypto.SHA256
+ h := hash.New()
+ h.Write([]byte("testing"))
+ hashed := h.Sum(nil)
+
+ // Generated with `echo -n testing | openssl dgst -sign key.pem -sigopt rsa_padding_mode:pss -sha256 > sig`
+ sig := []byte{
+ 0x95, 0x59, 0x6f, 0xd3, 0x10, 0xa2, 0xe7, 0xa2, 0x92, 0x9d,
+ 0x4a, 0x07, 0x2e, 0x2b, 0x27, 0xcc, 0x06, 0xc2, 0x87, 0x2c,
+ 0x52, 0xf0, 0x4a, 0xcc, 0x05, 0x94, 0xf2, 0xc3, 0x2e, 0x20,
+ 0xd7, 0x3e, 0x66, 0x62, 0xb5, 0x95, 0x2b, 0xa3, 0x93, 0x9a,
+ 0x66, 0x64, 0x25, 0xe0, 0x74, 0x66, 0x8c, 0x3e, 0x92, 0xeb,
+ 0xc6, 0xe6, 0xc0, 0x44, 0xf3, 0xb4, 0xb4, 0x2e, 0x8c, 0x66,
+ 0x0a, 0x37, 0x9c, 0x69,
+ }
+
+ if err := VerifyPSS(&rsaPrivateKey.PublicKey, hash, hashed, sig, nil); err != nil {
+ t.Error(err)
+ }
+}
+
+func TestPSSSigning(t *testing.T) {
+ var saltLengthCombinations = []struct {
+ signSaltLength, verifySaltLength int
+ good bool
+ }{
+ {PSSSaltLengthAuto, PSSSaltLengthAuto, true},
+ {PSSSaltLengthEqualsHash, PSSSaltLengthAuto, true},
+ {PSSSaltLengthEqualsHash, PSSSaltLengthEqualsHash, true},
+ {PSSSaltLengthEqualsHash, 8, false},
+ {PSSSaltLengthAuto, PSSSaltLengthEqualsHash, false},
+ {8, 8, true},
+ }
+
+ hash := crypto.MD5
+ h := hash.New()
+ h.Write([]byte("testing"))
+ hashed := h.Sum(nil)
+ var opts PSSOptions
+
+ for i, test := range saltLengthCombinations {
+ opts.SaltLength = test.signSaltLength
+ sig, err := SignPSS(rand.Reader, rsaPrivateKey, hash, hashed, &opts)
+ if err != nil {
+ t.Errorf("#%d: error while signing: %s", i, err)
+ continue
+ }
+
+ opts.SaltLength = test.verifySaltLength
+ err = VerifyPSS(&rsaPrivateKey.PublicKey, hash, hashed, sig, &opts)
+ if (err == nil) != test.good {
+ t.Errorf("#%d: bad result, wanted: %t, got: %s", i, test.good, err)
+ }
+ }
+}
+
+func bigFromHex(hex string) *big.Int {
+ n, ok := new(big.Int).SetString(hex, 16)
+ if !ok {
+ panic("bad hex: " + hex)
+ }
+ return n
+}
+
+func intFromHex(hex string) int {
+ i, err := strconv.ParseInt(hex, 16, 32)
+ if err != nil {
+ panic(err)
+ }
+ return int(i)
+}
+
+func fromHex(hexStr string) []byte {
+ s, err := hex.DecodeString(hexStr)
+ if err != nil {
+ panic(err)
+ }
+ return s
+}
diff --git a/libgo/go/crypto/rsa/rsa.go b/libgo/go/crypto/rsa/rsa.go
index f56fb37ee54..c7353ea311a 100644
--- a/libgo/go/crypto/rsa/rsa.go
+++ b/libgo/go/crypto/rsa/rsa.go
@@ -5,8 +5,6 @@
// Package rsa implements RSA encryption as specified in PKCS#1.
package rsa
-// TODO(agl): Add support for PSS padding.
-
import (
"crypto/rand"
"crypto/subtle"
diff --git a/libgo/go/crypto/rsa/rsa_test.go b/libgo/go/crypto/rsa/rsa_test.go
index ffd96e62f64..cf193c669f3 100644
--- a/libgo/go/crypto/rsa/rsa_test.go
+++ b/libgo/go/crypto/rsa/rsa_test.go
@@ -120,8 +120,10 @@ func testKeyBasics(t *testing.T, priv *PrivateKey) {
}
func fromBase10(base10 string) *big.Int {
- i := new(big.Int)
- i.SetString(base10, 10)
+ i, ok := new(big.Int).SetString(base10, 10)
+ if !ok {
+ panic("bad number: " + base10)
+ }
return i
}
diff --git a/libgo/go/crypto/rsa/testdata/pss-vect.txt.bz2 b/libgo/go/crypto/rsa/testdata/pss-vect.txt.bz2
new file mode 100644
index 00000000000..ad3da1ac4ee
--- /dev/null
+++ b/libgo/go/crypto/rsa/testdata/pss-vect.txt.bz2
Binary files differ
diff --git a/libgo/go/crypto/sha1/sha1.go b/libgo/go/crypto/sha1/sha1.go
index 7cfde47dc07..8eb3f7a7988 100644
--- a/libgo/go/crypto/sha1/sha1.go
+++ b/libgo/go/crypto/sha1/sha1.go
@@ -90,9 +90,13 @@ func (d *digest) Write(p []byte) (nn int, err error) {
func (d0 *digest) Sum(in []byte) []byte {
// Make a copy of d0 so that caller can keep writing and summing.
d := *d0
+ hash := d.checkSum()
+ return append(in, hash[:]...)
+}
- // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64.
+func (d *digest) checkSum() [Size]byte {
len := d.len
+ // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64.
var tmp [64]byte
tmp[0] = 0x80
if len%64 < 56 {
@@ -120,5 +124,13 @@ func (d0 *digest) Sum(in []byte) []byte {
digest[i*4+3] = byte(s)
}
- return append(in, digest[:]...)
+ return digest
+}
+
+// Sum returns the SHA1 checksum of the data.
+func Sum(data []byte) [Size]byte {
+ var d digest
+ d.Reset()
+ d.Write(data)
+ return d.checkSum()
}
diff --git a/libgo/go/crypto/sha1/sha1_test.go b/libgo/go/crypto/sha1/sha1_test.go
index 57cd4313eb2..c3868d702ac 100644
--- a/libgo/go/crypto/sha1/sha1_test.go
+++ b/libgo/go/crypto/sha1/sha1_test.go
@@ -54,6 +54,10 @@ var golden = []sha1Test{
func TestGolden(t *testing.T) {
for i := 0; i < len(golden); i++ {
g := golden[i]
+ s := fmt.Sprintf("%x", Sum([]byte(g.in)))
+ if s != g.out {
+ t.Fatalf("Sum function: sha1(%s) = %s want %s", g.in, s, g.out)
+ }
c := New()
for j := 0; j < 3; j++ {
if j < 2 {
@@ -72,13 +76,6 @@ func TestGolden(t *testing.T) {
}
}
-func ExampleNew() {
- h := New()
- io.WriteString(h, "His money is twice tainted: 'taint yours and 'taint mine.")
- fmt.Printf("% x", h.Sum(nil))
- // Output: 59 7f 6a 54 00 10 f9 4c 15 d7 18 06 a9 9a 2c 87 10 e7 47 bd
-}
-
var bench = New()
var buf = make([]byte, 8192)
diff --git a/libgo/go/crypto/sha1/sha1block_decl.go b/libgo/go/crypto/sha1/sha1block_decl.go
index 3512a582991..4cb157fff6d 100644
--- a/libgo/go/crypto/sha1/sha1block_decl.go
+++ b/libgo/go/crypto/sha1/sha1block_decl.go
@@ -6,4 +6,6 @@
package sha1
+//go:noescape
+
func block(dig *digest, p []byte)
diff --git a/libgo/go/crypto/sha256/sha256.go b/libgo/go/crypto/sha256/sha256.go
index dc0e18f50df..d69ed24a3b4 100644
--- a/libgo/go/crypto/sha256/sha256.go
+++ b/libgo/go/crypto/sha256/sha256.go
@@ -134,9 +134,16 @@ func (d *digest) Write(p []byte) (nn int, err error) {
func (d0 *digest) Sum(in []byte) []byte {
// Make a copy of d0 so that caller can keep writing and summing.
d := *d0
+ hash := d.checkSum()
+ if d.is224 {
+ return append(in, hash[:Size224]...)
+ }
+ return append(in, hash[:]...)
+}
- // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64.
+func (d *digest) checkSum() [Size]byte {
len := d.len
+ // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64.
var tmp [64]byte
tmp[0] = 0x80
if len%64 < 56 {
@@ -157,10 +164,8 @@ func (d0 *digest) Sum(in []byte) []byte {
}
h := d.h[:]
- size := Size
if d.is224 {
h = d.h[:7]
- size = Size224
}
var digest [Size]byte
@@ -171,5 +176,24 @@ func (d0 *digest) Sum(in []byte) []byte {
digest[i*4+3] = byte(s)
}
- return append(in, digest[:size]...)
+ return digest
+}
+
+// Sum256 returns the SHA256 checksum of the data.
+func Sum256(data []byte) [Size]byte {
+ var d digest
+ d.Reset()
+ d.Write(data)
+ return d.checkSum()
+}
+
+// Sum224 returns the SHA224 checksum of the data.
+func Sum224(data []byte) (sum224 [Size224]byte) {
+ var d digest
+ d.is224 = true
+ d.Reset()
+ d.Write(data)
+ sum := d.checkSum()
+ copy(sum224[:], sum[:Size224])
+ return
}
diff --git a/libgo/go/crypto/sha256/sha256_test.go b/libgo/go/crypto/sha256/sha256_test.go
index 29bf1619aeb..bb1ec3b1626 100644
--- a/libgo/go/crypto/sha256/sha256_test.go
+++ b/libgo/go/crypto/sha256/sha256_test.go
@@ -88,6 +88,10 @@ var golden224 = []sha256Test{
func TestGolden(t *testing.T) {
for i := 0; i < len(golden); i++ {
g := golden[i]
+ s := fmt.Sprintf("%x", Sum256([]byte(g.in)))
+ if s != g.out {
+ t.Fatalf("Sum256 function: sha256(%s) = %s want %s", g.in, s, g.out)
+ }
c := New()
for j := 0; j < 3; j++ {
if j < 2 {
@@ -106,6 +110,10 @@ func TestGolden(t *testing.T) {
}
for i := 0; i < len(golden224); i++ {
g := golden224[i]
+ s := fmt.Sprintf("%x", Sum224([]byte(g.in)))
+ if s != g.out {
+ t.Fatalf("Sum224 function: sha224(%s) = %s want %s", g.in, s, g.out)
+ }
c := New224()
for j := 0; j < 3; j++ {
if j < 2 {
diff --git a/libgo/go/crypto/sha512/sha512.go b/libgo/go/crypto/sha512/sha512.go
index 4aec5293858..d2ada51373c 100644
--- a/libgo/go/crypto/sha512/sha512.go
+++ b/libgo/go/crypto/sha512/sha512.go
@@ -135,7 +135,14 @@ func (d0 *digest) Sum(in []byte) []byte {
// Make a copy of d0 so that caller can keep writing and summing.
d := new(digest)
*d = *d0
+ hash := d.checkSum()
+ if d.is384 {
+ return append(in, hash[:Size384]...)
+ }
+ return append(in, hash[:]...)
+}
+func (d *digest) checkSum() [Size]byte {
// Padding. Add a 1 bit and 0 bits until 112 bytes mod 128.
len := d.len
var tmp [128]byte
@@ -158,10 +165,8 @@ func (d0 *digest) Sum(in []byte) []byte {
}
h := d.h[:]
- size := Size
if d.is384 {
h = d.h[:6]
- size = Size384
}
var digest [Size]byte
@@ -176,5 +181,24 @@ func (d0 *digest) Sum(in []byte) []byte {
digest[i*8+7] = byte(s)
}
- return append(in, digest[:size]...)
+ return digest
+}
+
+// Sum512 returns the SHA512 checksum of the data.
+func Sum512(data []byte) [Size]byte {
+ var d digest
+ d.Reset()
+ d.Write(data)
+ return d.checkSum()
+}
+
+// Sum384 returns the SHA384 checksum of the data.
+func Sum384(data []byte) (sum384 [Size384]byte) {
+ var d digest
+ d.is384 = true
+ d.Reset()
+ d.Write(data)
+ sum := d.checkSum()
+ copy(sum384[:], sum[:Size384])
+ return
}
diff --git a/libgo/go/crypto/sha512/sha512_test.go b/libgo/go/crypto/sha512/sha512_test.go
index 6eafb1b5fa9..167c20ad075 100644
--- a/libgo/go/crypto/sha512/sha512_test.go
+++ b/libgo/go/crypto/sha512/sha512_test.go
@@ -88,6 +88,10 @@ var golden384 = []sha512Test{
func TestGolden(t *testing.T) {
for i := 0; i < len(golden); i++ {
g := golden[i]
+ s := fmt.Sprintf("%x", Sum512([]byte(g.in)))
+ if s != g.out {
+ t.Fatalf("Sum512 function: sha512(%s) = %s want %s", g.in, s, g.out)
+ }
c := New()
for j := 0; j < 3; j++ {
if j < 2 {
@@ -106,6 +110,10 @@ func TestGolden(t *testing.T) {
}
for i := 0; i < len(golden384); i++ {
g := golden384[i]
+ s := fmt.Sprintf("%x", Sum384([]byte(g.in)))
+ if s != g.out {
+ t.Fatalf("Sum384 function: sha384(%s) = %s want %s", g.in, s, g.out)
+ }
c := New384()
for j := 0; j < 3; j++ {
if j < 2 {
diff --git a/libgo/go/crypto/subtle/constant_time.go b/libgo/go/crypto/subtle/constant_time.go
index 57dbe9db555..dfb658465e9 100644
--- a/libgo/go/crypto/subtle/constant_time.go
+++ b/libgo/go/crypto/subtle/constant_time.go
@@ -55,3 +55,11 @@ func ConstantTimeCopy(v int, x, y []byte) {
}
return
}
+
+// ConstantTimeLessOrEq returns 1 if x <= y and 0 otherwise.
+// Its behavior is undefined if x or y are negative or > 2**31 - 1.
+func ConstantTimeLessOrEq(x, y int) int {
+ x32 := int32(x)
+ y32 := int32(y)
+ return int(((x32 - y32 - 1) >> 31) & 1)
+}
diff --git a/libgo/go/crypto/subtle/constant_time_test.go b/libgo/go/crypto/subtle/constant_time_test.go
index adab8e2e8dd..d8e321ec04a 100644
--- a/libgo/go/crypto/subtle/constant_time_test.go
+++ b/libgo/go/crypto/subtle/constant_time_test.go
@@ -103,3 +103,23 @@ func TestConstantTimeCopy(t *testing.T) {
t.Error(err)
}
}
+
+var lessOrEqTests = []struct {
+ x, y, result int
+}{
+ {0, 0, 1},
+ {1, 0, 0},
+ {0, 1, 1},
+ {10, 20, 1},
+ {20, 10, 0},
+ {10, 10, 1},
+}
+
+func TestConstantTimeLessOrEq(t *testing.T) {
+ for i, test := range lessOrEqTests {
+ result := ConstantTimeLessOrEq(test.x, test.y)
+ if result != test.result {
+ t.Errorf("#%d: %d <= %d gave %d, expected %d", i, test.x, test.y, result, test.result)
+ }
+ }
+}
diff --git a/libgo/go/crypto/tls/cipher_suites.go b/libgo/go/crypto/tls/cipher_suites.go
index a647e19aa19..39a51459d28 100644
--- a/libgo/go/crypto/tls/cipher_suites.go
+++ b/libgo/go/crypto/tls/cipher_suites.go
@@ -34,6 +34,22 @@ type keyAgreement interface {
generateClientKeyExchange(*Config, *clientHelloMsg, *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error)
}
+const (
+ // suiteECDH indicates that the cipher suite involves elliptic curve
+ // Diffie-Hellman. This means that it should only be selected when the
+ // client indicates that it supports ECC with a curve and point format
+ // that we're happy with.
+ suiteECDHE = 1 << iota
+ // suiteECDSA indicates that the cipher suite involves an ECDSA
+ // signature and therefore may only be selected when the server's
+ // certificate is ECDSA. If this is not set then the cipher suite is
+ // RSA based.
+ suiteECDSA
+ // suiteTLS12 indicates that the cipher suite should only be advertised
+ // and accepted when using TLS 1.2.
+ suiteTLS12
+)
+
// A cipherSuite is a specific combination of key agreement, cipher and MAC
// function. All cipher suites currently assume RSA key agreement.
type cipherSuite struct {
@@ -42,24 +58,30 @@ type cipherSuite struct {
keyLen int
macLen int
ivLen int
- ka func() keyAgreement
- // If elliptic is set, a server will only consider this ciphersuite if
- // the ClientHello indicated that the client supports an elliptic curve
- // and point format that we can handle.
- elliptic bool
- cipher func(key, iv []byte, isRead bool) interface{}
- mac func(version uint16, macKey []byte) macFunction
+ ka func(version uint16) keyAgreement
+ // flags is a bitmask of the suite* values, above.
+ flags int
+ cipher func(key, iv []byte, isRead bool) interface{}
+ mac func(version uint16, macKey []byte) macFunction
+ aead func(key, fixedNonce []byte) cipher.AEAD
}
var cipherSuites = []*cipherSuite{
- {TLS_RSA_WITH_RC4_128_SHA, 16, 20, 0, rsaKA, false, cipherRC4, macSHA1},
- {TLS_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, rsaKA, false, cipher3DES, macSHA1},
- {TLS_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, rsaKA, false, cipherAES, macSHA1},
- {TLS_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, rsaKA, false, cipherAES, macSHA1},
- {TLS_ECDHE_RSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheRSAKA, true, cipherRC4, macSHA1},
- {TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, ecdheRSAKA, true, cipher3DES, macSHA1},
- {TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheRSAKA, true, cipherAES, macSHA1},
- {TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheRSAKA, true, cipherAES, macSHA1},
+ // Ciphersuite order is chosen so that ECDHE comes before plain RSA
+ // and RC4 comes before AES (because of the Lucky13 attack).
+ {TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, ecdheRSAKA, suiteECDHE | suiteTLS12, nil, nil, aeadAESGCM},
+ {TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12, nil, nil, aeadAESGCM},
+ {TLS_ECDHE_RSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheRSAKA, suiteECDHE, cipherRC4, macSHA1, nil},
+ {TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheECDSAKA, suiteECDHE | suiteECDSA, cipherRC4, macSHA1, nil},
+ {TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheRSAKA, suiteECDHE, cipherAES, macSHA1, nil},
+ {TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA, cipherAES, macSHA1, nil},
+ {TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheRSAKA, suiteECDHE, cipherAES, macSHA1, nil},
+ {TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA, cipherAES, macSHA1, nil},
+ {TLS_RSA_WITH_RC4_128_SHA, 16, 20, 0, rsaKA, 0, cipherRC4, macSHA1, nil},
+ {TLS_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, rsaKA, 0, cipherAES, macSHA1, nil},
+ {TLS_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, rsaKA, 0, cipherAES, macSHA1, nil},
+ {TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, ecdheRSAKA, suiteECDHE, cipher3DES, macSHA1, nil},
+ {TLS_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, rsaKA, 0, cipher3DES, macSHA1, nil},
}
func cipherRC4(key, iv []byte, isRead bool) interface{} {
@@ -85,7 +107,7 @@ func cipherAES(key, iv []byte, isRead bool) interface{} {
// macSHA1 returns a macFunction for the given protocol version.
func macSHA1(version uint16, key []byte) macFunction {
- if version == versionSSL30 {
+ if version == VersionSSL30 {
mac := ssl30MAC{
h: sha1.New(),
key: make([]byte, len(key)),
@@ -98,7 +120,47 @@ func macSHA1(version uint16, key []byte) macFunction {
type macFunction interface {
Size() int
- MAC(digestBuf, seq, data []byte) []byte
+ MAC(digestBuf, seq, header, data []byte) []byte
+}
+
+// fixedNonceAEAD wraps an AEAD and prefixes a fixed portion of the nonce to
+// each call.
+type fixedNonceAEAD struct {
+ // sealNonce and openNonce are buffers where the larger nonce will be
+ // constructed. Since a seal and open operation may be running
+ // concurrently, there is a separate buffer for each.
+ sealNonce, openNonce []byte
+ aead cipher.AEAD
+}
+
+func (f *fixedNonceAEAD) NonceSize() int { return 8 }
+func (f *fixedNonceAEAD) Overhead() int { return f.aead.Overhead() }
+
+func (f *fixedNonceAEAD) Seal(out, nonce, plaintext, additionalData []byte) []byte {
+ copy(f.sealNonce[len(f.sealNonce)-8:], nonce)
+ return f.aead.Seal(out, f.sealNonce, plaintext, additionalData)
+}
+
+func (f *fixedNonceAEAD) Open(out, nonce, plaintext, additionalData []byte) ([]byte, error) {
+ copy(f.openNonce[len(f.openNonce)-8:], nonce)
+ return f.aead.Open(out, f.openNonce, plaintext, additionalData)
+}
+
+func aeadAESGCM(key, fixedNonce []byte) cipher.AEAD {
+ aes, err := aes.NewCipher(key)
+ if err != nil {
+ panic(err)
+ }
+ aead, err := cipher.NewGCM(aes)
+ if err != nil {
+ panic(err)
+ }
+
+ nonce1, nonce2 := make([]byte, 12), make([]byte, 12)
+ copy(nonce1, fixedNonce)
+ copy(nonce2, fixedNonce)
+
+ return &fixedNonceAEAD{nonce1, nonce2, aead}
}
// ssl30MAC implements the SSLv3 MAC function, as defined in
@@ -116,7 +178,7 @@ var ssl30Pad1 = [48]byte{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0
var ssl30Pad2 = [48]byte{0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c}
-func (s ssl30MAC) MAC(digestBuf, seq, record []byte) []byte {
+func (s ssl30MAC) MAC(digestBuf, seq, header, data []byte) []byte {
padLength := 48
if s.h.Size() == 20 {
padLength = 40
@@ -126,9 +188,9 @@ func (s ssl30MAC) MAC(digestBuf, seq, record []byte) []byte {
s.h.Write(s.key)
s.h.Write(ssl30Pad1[:padLength])
s.h.Write(seq)
- s.h.Write(record[:1])
- s.h.Write(record[3:5])
- s.h.Write(record[recordHeaderLen:])
+ s.h.Write(header[:1])
+ s.h.Write(header[3:5])
+ s.h.Write(data)
digestBuf = s.h.Sum(digestBuf[:0])
s.h.Reset()
@@ -147,19 +209,30 @@ func (s tls10MAC) Size() int {
return s.h.Size()
}
-func (s tls10MAC) MAC(digestBuf, seq, record []byte) []byte {
+func (s tls10MAC) MAC(digestBuf, seq, header, data []byte) []byte {
s.h.Reset()
s.h.Write(seq)
- s.h.Write(record)
+ s.h.Write(header)
+ s.h.Write(data)
return s.h.Sum(digestBuf[:0])
}
-func rsaKA() keyAgreement {
+func rsaKA(version uint16) keyAgreement {
return rsaKeyAgreement{}
}
-func ecdheRSAKA() keyAgreement {
- return new(ecdheRSAKeyAgreement)
+func ecdheECDSAKA(version uint16) keyAgreement {
+ return &ecdheKeyAgreement{
+ sigType: signatureECDSA,
+ version: version,
+ }
+}
+
+func ecdheRSAKA(version uint16) keyAgreement {
+ return &ecdheKeyAgreement{
+ sigType: signatureRSA,
+ version: version,
+ }
}
// mutualCipherSuite returns a cipherSuite given a list of supported
@@ -181,12 +254,17 @@ func mutualCipherSuite(have []uint16, want uint16) *cipherSuite {
// A list of the possible cipher suite ids. Taken from
// http://www.iana.org/assignments/tls-parameters/tls-parameters.xml
const (
- TLS_RSA_WITH_RC4_128_SHA uint16 = 0x0005
- TLS_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0x000a
- TLS_RSA_WITH_AES_128_CBC_SHA uint16 = 0x002f
- TLS_RSA_WITH_AES_256_CBC_SHA uint16 = 0x0035
- TLS_ECDHE_RSA_WITH_RC4_128_SHA uint16 = 0xc011
- TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xc012
- TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA uint16 = 0xc013
- TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA uint16 = 0xc014
+ TLS_RSA_WITH_RC4_128_SHA uint16 = 0x0005
+ TLS_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0x000a
+ TLS_RSA_WITH_AES_128_CBC_SHA uint16 = 0x002f
+ TLS_RSA_WITH_AES_256_CBC_SHA uint16 = 0x0035
+ TLS_ECDHE_ECDSA_WITH_RC4_128_SHA uint16 = 0xc007
+ TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA uint16 = 0xc009
+ TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA uint16 = 0xc00a
+ TLS_ECDHE_RSA_WITH_RC4_128_SHA uint16 = 0xc011
+ TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xc012
+ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA uint16 = 0xc013
+ TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA uint16 = 0xc014
+ TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0xc02f
+ TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 uint16 = 0xc02b
)
diff --git a/libgo/go/crypto/tls/common.go b/libgo/go/crypto/tls/common.go
index f86c90de74d..b7229d29f8b 100644
--- a/libgo/go/crypto/tls/common.go
+++ b/libgo/go/crypto/tls/common.go
@@ -9,22 +9,27 @@ import (
"crypto/rand"
"crypto/x509"
"io"
+ "math/big"
"strings"
"sync"
"time"
)
const (
+ VersionSSL30 = 0x0300
+ VersionTLS10 = 0x0301
+ VersionTLS11 = 0x0302
+ VersionTLS12 = 0x0303
+)
+
+const (
maxPlaintext = 16384 // maximum plaintext payload length
maxCiphertext = 16384 + 2048 // maximum ciphertext payload length
recordHeaderLen = 5 // record header length
maxHandshake = 65536 // maximum handshake we support (protocol max is 16 MB)
- versionSSL30 = 0x0300
- versionTLS10 = 0x0301
-
- minVersion = versionSSL30
- maxVersion = versionTLS10
+ minVersion = VersionSSL30
+ maxVersion = VersionTLS12
)
// TLS record types.
@@ -60,12 +65,13 @@ const (
// TLS extension numbers
var (
- extensionServerName uint16 = 0
- extensionStatusRequest uint16 = 5
- extensionSupportedCurves uint16 = 10
- extensionSupportedPoints uint16 = 11
- extensionSessionTicket uint16 = 35
- extensionNextProtoNeg uint16 = 13172 // not IANA assigned
+ extensionServerName uint16 = 0
+ extensionStatusRequest uint16 = 5
+ extensionSupportedCurves uint16 = 10
+ extensionSupportedPoints uint16 = 11
+ extensionSignatureAlgorithms uint16 = 13
+ extensionSessionTicket uint16 = 35
+ extensionNextProtoNeg uint16 = 13172 // not IANA assigned
)
// TLS Elliptic Curves
@@ -93,25 +99,60 @@ const (
certTypeDSSSign = 2 // A certificate containing a DSA key
certTypeRSAFixedDH = 3 // A certificate containing a static DH key
certTypeDSSFixedDH = 4 // A certificate containing a static DH key
+
+ // See RFC4492 sections 3 and 5.5.
+ certTypeECDSASign = 64 // A certificate containing an ECDSA-capable public key, signed with ECDSA.
+ certTypeRSAFixedECDH = 65 // A certificate containing an ECDH-capable public key, signed with RSA.
+ certTypeECDSAFixedECDH = 66 // A certificate containing an ECDH-capable public key, signed with ECDSA.
+
// Rest of these are reserved by the TLS spec
)
+// Hash functions for TLS 1.2 (See RFC 5246, section A.4.1)
+const (
+ hashSHA1 uint8 = 2
+ hashSHA256 uint8 = 4
+)
+
+// Signature algorithms for TLS 1.2 (See RFC 5246, section A.4.1)
+const (
+ signatureRSA uint8 = 1
+ signatureECDSA uint8 = 3
+)
+
+// signatureAndHash mirrors the TLS 1.2, SignatureAndHashAlgorithm struct. See
+// RFC 5246, section A.4.1.
+type signatureAndHash struct {
+ hash, signature uint8
+}
+
+// supportedSKXSignatureAlgorithms contains the signature and hash algorithms
+// that the code advertises as supported in a TLS 1.2 ClientHello.
+var supportedSKXSignatureAlgorithms = []signatureAndHash{
+ {hashSHA256, signatureRSA},
+ {hashSHA256, signatureECDSA},
+ {hashSHA1, signatureRSA},
+ {hashSHA1, signatureECDSA},
+}
+
+// supportedClientCertSignatureAlgorithms contains the signature and hash
+// algorithms that the code advertises as supported in a TLS 1.2
+// CertificateRequest.
+var supportedClientCertSignatureAlgorithms = []signatureAndHash{
+ {hashSHA256, signatureRSA},
+ {hashSHA256, signatureECDSA},
+}
+
// ConnectionState records basic TLS details about the connection.
type ConnectionState struct {
- HandshakeComplete bool
- DidResume bool
- CipherSuite uint16
- NegotiatedProtocol string
- NegotiatedProtocolIsMutual bool
-
- // ServerName contains the server name indicated by the client, if any.
- // (Only valid for server connections.)
- ServerName string
-
- // the certificate chain that was presented by the other side
- PeerCertificates []*x509.Certificate
- // the verified certificate chains built from PeerCertificates.
- VerifiedChains [][]*x509.Certificate
+ HandshakeComplete bool // TLS handshake is complete
+ DidResume bool // connection resumes a previous TLS connection
+ CipherSuite uint16 // cipher suite in use (TLS_RSA_WITH_RC4_128_SHA, ...)
+ NegotiatedProtocol string // negotiated next protocol (from Config.NextProtos)
+ NegotiatedProtocolIsMutual bool // negotiated protocol was advertised by server
+ ServerName string // server name requested by client, if any (server side only)
+ PeerCertificates []*x509.Certificate // certificate chain presented by remote peer
+ VerifiedChains [][]*x509.Certificate // verified chains built from PeerCertificates
}
// ClientAuthType declares the policy the server will follow for
@@ -204,6 +245,15 @@ type Config struct {
// connections using that key are compromised.
SessionTicketKey [32]byte
+ // MinVersion contains the minimum SSL/TLS version that is acceptable.
+ // If zero, then SSLv3 is taken as the minimum.
+ MinVersion uint16
+
+ // MaxVersion contains the maximum SSL/TLS version that is acceptable.
+ // If zero, then the maximum version supported by this package is used,
+ // which is currently TLS 1.2.
+ MaxVersion uint16
+
serverInitOnce sync.Once // guards calling (*Config).serverInit
}
@@ -248,6 +298,35 @@ func (c *Config) cipherSuites() []uint16 {
return s
}
+func (c *Config) minVersion() uint16 {
+ if c == nil || c.MinVersion == 0 {
+ return minVersion
+ }
+ return c.MinVersion
+}
+
+func (c *Config) maxVersion() uint16 {
+ if c == nil || c.MaxVersion == 0 {
+ return maxVersion
+ }
+ return c.MaxVersion
+}
+
+// mutualVersion returns the protocol version to use given the advertised
+// version of the peer.
+func (c *Config) mutualVersion(vers uint16) (uint16, bool) {
+ minVersion := c.minVersion()
+ maxVersion := c.maxVersion()
+
+ if vers < minVersion {
+ return 0, false
+ }
+ if vers > maxVersion {
+ vers = maxVersion
+ }
+ return vers, true
+}
+
// getCertificateForName returns the best certificate for the given name,
// defaulting to the first element of c.Certificates if there are no good
// options.
@@ -304,7 +383,7 @@ func (c *Config) BuildNameToCertificate() {
// A Certificate is a chain of one or more certificates, leaf first.
type Certificate struct {
Certificate [][]byte
- PrivateKey crypto.PrivateKey // supported types: *rsa.PrivateKey
+ PrivateKey crypto.PrivateKey // supported types: *rsa.PrivateKey, *ecdsa.PrivateKey
// OCSPStaple contains an optional OCSP response which will be served
// to clients that request it.
OCSPStaple []byte
@@ -327,18 +406,13 @@ type handshakeMessage interface {
unmarshal([]byte) bool
}
-// mutualVersion returns the protocol version to use given the advertised
-// version of the peer.
-func mutualVersion(vers uint16) (uint16, bool) {
- if vers < minVersion {
- return 0, false
- }
- if vers > maxVersion {
- vers = maxVersion
- }
- return vers, true
+// TODO(jsing): Make these available to both crypto/x509 and crypto/tls.
+type dsaSignature struct {
+ R, S *big.Int
}
+type ecdsaSignature dsaSignature
+
var emptyConfig Config
func defaultConfig() *Config {
diff --git a/libgo/go/crypto/tls/conn.go b/libgo/go/crypto/tls/conn.go
index d8c2be00a26..2e64b88a689 100644
--- a/libgo/go/crypto/tls/conn.go
+++ b/libgo/go/crypto/tls/conn.go
@@ -146,6 +146,9 @@ func (hc *halfConn) changeCipherSpec() error {
hc.mac = hc.nextMac
hc.nextCipher = nil
hc.nextMac = nil
+ for i := range hc.seq {
+ hc.seq[i] = 0
+ }
return nil
}
@@ -229,8 +232,16 @@ func roundUp(a, b int) int {
return a + (b-a%b)%b
}
-// decrypt checks and strips the mac and decrypts the data in b.
-func (hc *halfConn) decrypt(b *block) (bool, alert) {
+// cbcMode is an interface for block ciphers using cipher block chaining.
+type cbcMode interface {
+ cipher.BlockMode
+ SetIV([]byte)
+}
+
+// decrypt checks and strips the mac and decrypts the data in b. Returns a
+// success boolean, the number of bytes to skip from the start of the record in
+// order to get the application payload, and an optional alert value.
+func (hc *halfConn) decrypt(b *block) (ok bool, prefixLen int, alertValue alert) {
// pull out payload
payload := b.data[recordHeaderLen:]
@@ -240,26 +251,54 @@ func (hc *halfConn) decrypt(b *block) (bool, alert) {
}
paddingGood := byte(255)
+ explicitIVLen := 0
// decrypt
if hc.cipher != nil {
switch c := hc.cipher.(type) {
case cipher.Stream:
c.XORKeyStream(payload, payload)
- case cipher.BlockMode:
+ case cipher.AEAD:
+ explicitIVLen = 8
+ if len(payload) < explicitIVLen {
+ return false, 0, alertBadRecordMAC
+ }
+ nonce := payload[:8]
+ payload = payload[8:]
+
+ var additionalData [13]byte
+ copy(additionalData[:], hc.seq[:])
+ copy(additionalData[8:], b.data[:3])
+ n := len(payload) - c.Overhead()
+ additionalData[11] = byte(n >> 8)
+ additionalData[12] = byte(n)
+ var err error
+ payload, err = c.Open(payload[:0], nonce, payload, additionalData[:])
+ if err != nil {
+ return false, 0, alertBadRecordMAC
+ }
+ b.resize(recordHeaderLen + explicitIVLen + len(payload))
+ case cbcMode:
blockSize := c.BlockSize()
+ if hc.version >= VersionTLS11 {
+ explicitIVLen = blockSize
+ }
- if len(payload)%blockSize != 0 || len(payload) < roundUp(macSize+1, blockSize) {
- return false, alertBadRecordMAC
+ if len(payload)%blockSize != 0 || len(payload) < roundUp(explicitIVLen+macSize+1, blockSize) {
+ return false, 0, alertBadRecordMAC
}
+ if explicitIVLen > 0 {
+ c.SetIV(payload[:explicitIVLen])
+ payload = payload[explicitIVLen:]
+ }
c.CryptBlocks(payload, payload)
- if hc.version == versionSSL30 {
+ if hc.version == VersionSSL30 {
payload, paddingGood = removePaddingSSL30(payload)
} else {
payload, paddingGood = removePadding(payload)
}
- b.resize(recordHeaderLen + len(payload))
+ b.resize(recordHeaderLen + explicitIVLen + len(payload))
// note that we still have a timing side-channel in the
// MAC check, below. An attacker can align the record
@@ -279,25 +318,25 @@ func (hc *halfConn) decrypt(b *block) (bool, alert) {
// check, strip mac
if hc.mac != nil {
if len(payload) < macSize {
- return false, alertBadRecordMAC
+ return false, 0, alertBadRecordMAC
}
// strip mac off payload, b.data
n := len(payload) - macSize
b.data[3] = byte(n >> 8)
b.data[4] = byte(n)
- b.resize(recordHeaderLen + n)
+ b.resize(recordHeaderLen + explicitIVLen + n)
remoteMAC := payload[n:]
- localMAC := hc.mac.MAC(hc.inDigestBuf, hc.seq[0:], b.data)
- hc.incSeq()
+ localMAC := hc.mac.MAC(hc.inDigestBuf, hc.seq[0:], b.data[:recordHeaderLen], payload[:n])
if subtle.ConstantTimeCompare(localMAC, remoteMAC) != 1 || paddingGood != 255 {
- return false, alertBadRecordMAC
+ return false, 0, alertBadRecordMAC
}
hc.inDigestBuf = localMAC
}
+ hc.incSeq()
- return true, 0
+ return true, recordHeaderLen + explicitIVLen, 0
}
// padToBlockSize calculates the needed padding block, if any, for a payload.
@@ -318,11 +357,10 @@ func padToBlockSize(payload []byte, blockSize int) (prefix, finalBlock []byte) {
}
// encrypt encrypts and macs the data in b.
-func (hc *halfConn) encrypt(b *block) (bool, alert) {
+func (hc *halfConn) encrypt(b *block, explicitIVLen int) (bool, alert) {
// mac
if hc.mac != nil {
- mac := hc.mac.MAC(hc.outDigestBuf, hc.seq[0:], b.data)
- hc.incSeq()
+ mac := hc.mac.MAC(hc.outDigestBuf, hc.seq[0:], b.data[:recordHeaderLen], b.data[recordHeaderLen+explicitIVLen:])
n := len(b.data)
b.resize(n + len(mac))
@@ -337,11 +375,30 @@ func (hc *halfConn) encrypt(b *block) (bool, alert) {
switch c := hc.cipher.(type) {
case cipher.Stream:
c.XORKeyStream(payload, payload)
- case cipher.BlockMode:
- prefix, finalBlock := padToBlockSize(payload, c.BlockSize())
- b.resize(recordHeaderLen + len(prefix) + len(finalBlock))
- c.CryptBlocks(b.data[recordHeaderLen:], prefix)
- c.CryptBlocks(b.data[recordHeaderLen+len(prefix):], finalBlock)
+ case cipher.AEAD:
+ payloadLen := len(b.data) - recordHeaderLen - explicitIVLen
+ b.resize(len(b.data) + c.Overhead())
+ nonce := b.data[recordHeaderLen : recordHeaderLen+explicitIVLen]
+ payload := b.data[recordHeaderLen+explicitIVLen:]
+ payload = payload[:payloadLen]
+
+ var additionalData [13]byte
+ copy(additionalData[:], hc.seq[:])
+ copy(additionalData[8:], b.data[:3])
+ additionalData[11] = byte(payloadLen >> 8)
+ additionalData[12] = byte(payloadLen)
+
+ c.Seal(payload[:0], nonce, payload, additionalData[:])
+ case cbcMode:
+ blockSize := c.BlockSize()
+ if explicitIVLen > 0 {
+ c.SetIV(payload[:explicitIVLen])
+ payload = payload[explicitIVLen:]
+ }
+ prefix, finalBlock := padToBlockSize(payload, blockSize)
+ b.resize(recordHeaderLen + explicitIVLen + len(prefix) + len(finalBlock))
+ c.CryptBlocks(b.data[recordHeaderLen+explicitIVLen:], prefix)
+ c.CryptBlocks(b.data[recordHeaderLen+explicitIVLen+len(prefix):], finalBlock)
default:
panic("unknown cipher type")
}
@@ -351,6 +408,7 @@ func (hc *halfConn) encrypt(b *block) (bool, alert) {
n := len(b.data) - recordHeaderLen
b.data[3] = byte(n >> 8)
b.data[4] = byte(n)
+ hc.incSeq()
return true, 0
}
@@ -534,10 +592,11 @@ Again:
// Process message.
b, c.rawInput = c.in.splitBlock(b, recordHeaderLen+n)
- b.off = recordHeaderLen
- if ok, err := c.in.decrypt(b); !ok {
+ ok, off, err := c.in.decrypt(b)
+ if !ok {
return c.sendAlert(err)
}
+ b.off = off
data := b.data[b.off:]
if len(data) > maxPlaintext {
c.sendAlert(alertRecordOverflow)
@@ -637,18 +696,52 @@ func (c *Conn) writeRecord(typ recordType, data []byte) (n int, err error) {
if m > maxPlaintext {
m = maxPlaintext
}
- b.resize(recordHeaderLen + m)
+ explicitIVLen := 0
+ explicitIVIsSeq := false
+
+ var cbc cbcMode
+ if c.out.version >= VersionTLS11 {
+ var ok bool
+ if cbc, ok = c.out.cipher.(cbcMode); ok {
+ explicitIVLen = cbc.BlockSize()
+ }
+ }
+ if explicitIVLen == 0 {
+ if _, ok := c.out.cipher.(cipher.AEAD); ok {
+ explicitIVLen = 8
+ // The AES-GCM construction in TLS has an
+ // explicit nonce so that the nonce can be
+ // random. However, the nonce is only 8 bytes
+ // which is too small for a secure, random
+ // nonce. Therefore we use the sequence number
+ // as the nonce.
+ explicitIVIsSeq = true
+ }
+ }
+ b.resize(recordHeaderLen + explicitIVLen + m)
b.data[0] = byte(typ)
vers := c.vers
if vers == 0 {
- vers = maxVersion
+ // Some TLS servers fail if the record version is
+ // greater than TLS 1.0 for the initial ClientHello.
+ vers = VersionTLS10
}
b.data[1] = byte(vers >> 8)
b.data[2] = byte(vers)
b.data[3] = byte(m >> 8)
b.data[4] = byte(m)
- copy(b.data[recordHeaderLen:], data)
- c.out.encrypt(b)
+ if explicitIVLen > 0 {
+ explicitIV := b.data[recordHeaderLen : recordHeaderLen+explicitIVLen]
+ if explicitIVIsSeq {
+ copy(explicitIV, c.out.seq[:])
+ } else {
+ if _, err = io.ReadFull(c.config.rand(), explicitIV); err != nil {
+ break
+ }
+ }
+ }
+ copy(b.data[recordHeaderLen+explicitIVLen:], data)
+ c.out.encrypt(b, explicitIVLen)
_, err = c.conn.Write(b.data)
if err != nil {
break
@@ -709,7 +802,9 @@ func (c *Conn) readHandshake() (interface{}, error) {
case typeCertificate:
m = new(certificateMsg)
case typeCertificateRequest:
- m = new(certificateRequestMsg)
+ m = &certificateRequestMsg{
+ hasSignatureAndHash: c.vers >= VersionTLS12,
+ }
case typeCertificateStatus:
m = new(certificateStatusMsg)
case typeServerKeyExchange:
@@ -719,7 +814,9 @@ func (c *Conn) readHandshake() (interface{}, error) {
case typeClientKeyExchange:
m = new(clientKeyExchangeMsg)
case typeCertificateVerify:
- m = new(certificateVerifyMsg)
+ m = &certificateVerifyMsg{
+ hasSignatureAndHash: c.vers >= VersionTLS12,
+ }
case typeNextProtocol:
m = new(nextProtoMsg)
case typeFinished:
@@ -768,7 +865,7 @@ func (c *Conn) Write(b []byte) (int, error) {
// http://www.imperialviolet.org/2012/01/15/beastfollowup.html
var m int
- if len(b) > 1 && c.vers <= versionTLS10 {
+ if len(b) > 1 && c.vers <= VersionTLS10 {
if _, ok := c.out.cipher.(cipher.BlockMode); ok {
n, err := c.writeRecord(recordTypeApplicationData, b[:1])
if err != nil {
@@ -792,21 +889,32 @@ func (c *Conn) Read(b []byte) (n int, err error) {
c.in.Lock()
defer c.in.Unlock()
- for c.input == nil && c.error() == nil {
- if err := c.readRecord(recordTypeApplicationData); err != nil {
- // Soft error, like EAGAIN
+ // Some OpenSSL servers send empty records in order to randomize the
+ // CBC IV. So this loop ignores a limited number of empty records.
+ const maxConsecutiveEmptyRecords = 100
+ for emptyRecordCount := 0; emptyRecordCount <= maxConsecutiveEmptyRecords; emptyRecordCount++ {
+ for c.input == nil && c.error() == nil {
+ if err := c.readRecord(recordTypeApplicationData); err != nil {
+ // Soft error, like EAGAIN
+ return 0, err
+ }
+ }
+ if err := c.error(); err != nil {
return 0, err
}
+
+ n, err = c.input.Read(b)
+ if c.input.off >= len(c.input.data) {
+ c.in.freeBlock(c.input)
+ c.input = nil
+ }
+
+ if n != 0 || err != nil {
+ return n, err
+ }
}
- if err := c.error(); err != nil {
- return 0, err
- }
- n, err = c.input.Read(b)
- if c.input.off >= len(c.input.data) {
- c.in.freeBlock(c.input)
- c.input = nil
- }
- return n, nil
+
+ return 0, io.ErrNoProgress
}
// Close closes the connection.
diff --git a/libgo/go/crypto/tls/generate_cert.go b/libgo/go/crypto/tls/generate_cert.go
index 215644d2435..b417ea4640f 100644
--- a/libgo/go/crypto/tls/generate_cert.go
+++ b/libgo/go/crypto/tls/generate_cert.go
@@ -30,7 +30,7 @@ var (
validFrom = flag.String("start-date", "", "Creation date formatted as Jan 1 15:04:05 2011")
validFor = flag.Duration("duration", 365*24*time.Hour, "Duration that certificate is valid for")
isCA = flag.Bool("ca", false, "whether this cert should be its own Certificate Authority")
- rsaBits = flag.Int("rsa-bits", 1024, "Size of RSA key to generate")
+ rsaBits = flag.Int("rsa-bits", 2048, "Size of RSA key to generate")
)
func main() {
diff --git a/libgo/go/crypto/tls/handshake_client.go b/libgo/go/crypto/tls/handshake_client.go
index 7db13bf70d8..85e4adefcb0 100644
--- a/libgo/go/crypto/tls/handshake_client.go
+++ b/libgo/go/crypto/tls/handshake_client.go
@@ -6,25 +6,23 @@ package tls
import (
"bytes"
- "crypto"
+ "crypto/ecdsa"
"crypto/rsa"
"crypto/subtle"
"crypto/x509"
+ "encoding/asn1"
"errors"
"io"
"strconv"
)
func (c *Conn) clientHandshake() error {
- finishedHash := newFinishedHash(versionTLS10)
-
if c.config == nil {
c.config = defaultConfig()
}
hello := &clientHelloMsg{
- vers: maxVersion,
- cipherSuites: c.config.cipherSuites(),
+ vers: c.config.maxVersion(),
compressionMethods: []uint8{compressionNone},
random: make([]byte, 32),
ocspStapling: true,
@@ -34,6 +32,25 @@ func (c *Conn) clientHandshake() error {
nextProtoNeg: len(c.config.NextProtos) > 0,
}
+ possibleCipherSuites := c.config.cipherSuites()
+ hello.cipherSuites = make([]uint16, 0, len(possibleCipherSuites))
+
+NextCipherSuite:
+ for _, suiteId := range possibleCipherSuites {
+ for _, suite := range cipherSuites {
+ if suite.id != suiteId {
+ continue
+ }
+ // Don't advertise TLS 1.2-only cipher suites unless
+ // we're attempting TLS 1.2.
+ if hello.vers < VersionTLS12 && suite.flags&suiteTLS12 != 0 {
+ continue
+ }
+ hello.cipherSuites = append(hello.cipherSuites, suiteId)
+ continue NextCipherSuite
+ }
+ }
+
t := uint32(c.config.time().Unix())
hello.random[0] = byte(t >> 24)
hello.random[1] = byte(t >> 16)
@@ -45,7 +62,10 @@ func (c *Conn) clientHandshake() error {
return errors.New("short read from Rand")
}
- finishedHash.Write(hello.marshal())
+ if hello.vers >= VersionTLS12 {
+ hello.signatureAndHashes = supportedSKXSignatureAlgorithms
+ }
+
c.writeRecord(recordTypeHandshake, hello.marshal())
msg, err := c.readHandshake()
@@ -56,16 +76,19 @@ func (c *Conn) clientHandshake() error {
if !ok {
return c.sendAlert(alertUnexpectedMessage)
}
- finishedHash.Write(serverHello.marshal())
- vers, ok := mutualVersion(serverHello.vers)
- if !ok || vers < versionTLS10 {
+ vers, ok := c.config.mutualVersion(serverHello.vers)
+ if !ok || vers < VersionTLS10 {
// TLS 1.0 is the minimum version supported as a client.
return c.sendAlert(alertProtocolVersion)
}
c.vers = vers
c.haveVers = true
+ finishedHash := newFinishedHash(c.vers)
+ finishedHash.Write(hello.marshal())
+ finishedHash.Write(serverHello.marshal())
+
if serverHello.compressionMethod != compressionNone {
return c.sendAlert(alertUnexpectedMessage)
}
@@ -121,7 +144,10 @@ func (c *Conn) clientHandshake() error {
}
}
- if _, ok := certs[0].PublicKey.(*rsa.PublicKey); !ok {
+ switch certs[0].PublicKey.(type) {
+ case *rsa.PublicKey, *ecdsa.PublicKey:
+ break
+ default:
return c.sendAlert(alertUnsupportedCertificate)
}
@@ -148,7 +174,7 @@ func (c *Conn) clientHandshake() error {
return err
}
- keyAgreement := suite.ka()
+ keyAgreement := suite.ka(c.vers)
skx, ok := msg.(*serverKeyExchangeMsg)
if ok {
@@ -165,7 +191,7 @@ func (c *Conn) clientHandshake() error {
}
}
- var certToSend *Certificate
+ var chainToSend *Certificate
var certRequested bool
certReq, ok := msg.(*certificateRequestMsg)
if ok {
@@ -184,12 +210,13 @@ func (c *Conn) clientHandshake() error {
finishedHash.Write(certReq.marshal())
- // For now, we only know how to sign challenges with RSA
- rsaAvail := false
+ var rsaAvail, ecdsaAvail bool
for _, certType := range certReq.certificateTypes {
- if certType == certTypeRSASign {
+ switch certType {
+ case certTypeRSASign:
rsaAvail = true
- break
+ case certTypeECDSASign:
+ ecdsaAvail = true
}
}
@@ -197,35 +224,42 @@ func (c *Conn) clientHandshake() error {
// where SignatureAlgorithm is RSA and the Issuer is in
// certReq.certificateAuthorities
findCert:
- for i, cert := range c.config.Certificates {
- if !rsaAvail {
+ for i, chain := range c.config.Certificates {
+ if !rsaAvail && !ecdsaAvail {
continue
}
- leaf := cert.Leaf
- if leaf == nil {
- if leaf, err = x509.ParseCertificate(cert.Certificate[0]); err != nil {
- c.sendAlert(alertInternalError)
- return errors.New("tls: failed to parse client certificate #" + strconv.Itoa(i) + ": " + err.Error())
+ for j, cert := range chain.Certificate {
+ x509Cert := chain.Leaf
+ // parse the certificate if this isn't the leaf
+ // node, or if chain.Leaf was nil
+ if j != 0 || x509Cert == nil {
+ if x509Cert, err = x509.ParseCertificate(cert); err != nil {
+ c.sendAlert(alertInternalError)
+ return errors.New("tls: failed to parse client certificate #" + strconv.Itoa(i) + ": " + err.Error())
+ }
}
- }
-
- if leaf.PublicKeyAlgorithm != x509.RSA {
- continue
- }
- if len(certReq.certificateAuthorities) == 0 {
- // they gave us an empty list, so just take the
- // first RSA cert from c.config.Certificates
- certToSend = &cert
- break
- }
+ switch {
+ case rsaAvail && x509Cert.PublicKeyAlgorithm == x509.RSA:
+ case ecdsaAvail && x509Cert.PublicKeyAlgorithm == x509.ECDSA:
+ default:
+ continue findCert
+ }
- for _, ca := range certReq.certificateAuthorities {
- if bytes.Equal(leaf.RawIssuer, ca) {
- certToSend = &cert
+ if len(certReq.certificateAuthorities) == 0 {
+ // they gave us an empty list, so just take the
+ // first RSA cert from c.config.Certificates
+ chainToSend = &chain
break findCert
}
+
+ for _, ca := range certReq.certificateAuthorities {
+ if bytes.Equal(x509Cert.RawIssuer, ca) {
+ chainToSend = &chain
+ break findCert
+ }
+ }
}
}
@@ -246,8 +280,8 @@ func (c *Conn) clientHandshake() error {
// certificate to send.
if certRequested {
certMsg = new(certificateMsg)
- if certToSend != nil {
- certMsg.certificates = certToSend.Certificate
+ if chainToSend != nil {
+ certMsg.certificates = chainToSend.Certificate
}
finishedHash.Write(certMsg.marshal())
c.writeRecord(recordTypeHandshake, certMsg.marshal())
@@ -263,12 +297,29 @@ func (c *Conn) clientHandshake() error {
c.writeRecord(recordTypeHandshake, ckx.marshal())
}
- if certToSend != nil {
- certVerify := new(certificateVerifyMsg)
- digest := make([]byte, 0, 36)
- digest = finishedHash.serverMD5.Sum(digest)
- digest = finishedHash.serverSHA1.Sum(digest)
- signed, err := rsa.SignPKCS1v15(c.config.rand(), c.config.Certificates[0].PrivateKey.(*rsa.PrivateKey), crypto.MD5SHA1, digest)
+ if chainToSend != nil {
+ var signed []byte
+ certVerify := &certificateVerifyMsg{
+ hasSignatureAndHash: c.vers >= VersionTLS12,
+ }
+
+ switch key := c.config.Certificates[0].PrivateKey.(type) {
+ case *ecdsa.PrivateKey:
+ digest, _, hashId := finishedHash.hashForClientCertificate(signatureECDSA)
+ r, s, err := ecdsa.Sign(c.config.rand(), key, digest)
+ if err == nil {
+ signed, err = asn1.Marshal(ecdsaSignature{r, s})
+ }
+ certVerify.signatureAndHash.signature = signatureECDSA
+ certVerify.signatureAndHash.hash = hashId
+ case *rsa.PrivateKey:
+ digest, hashFunc, hashId := finishedHash.hashForClientCertificate(signatureRSA)
+ signed, err = rsa.SignPKCS1v15(c.config.rand(), key, hashFunc, digest)
+ certVerify.signatureAndHash.signature = signatureRSA
+ certVerify.signatureAndHash.hash = hashId
+ default:
+ err = errors.New("unknown private key type")
+ }
if err != nil {
return c.sendAlert(alertInternalError)
}
@@ -282,8 +333,14 @@ func (c *Conn) clientHandshake() error {
clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
keysFromMasterSecret(c.vers, masterSecret, hello.random, serverHello.random, suite.macLen, suite.keyLen, suite.ivLen)
- clientCipher := suite.cipher(clientKey, clientIV, false /* not for reading */)
- clientHash := suite.mac(c.vers, clientMAC)
+ var clientCipher interface{}
+ var clientHash macFunction
+ if suite.cipher != nil {
+ clientCipher = suite.cipher(clientKey, clientIV, false /* not for reading */)
+ clientHash = suite.mac(c.vers, clientMAC)
+ } else {
+ clientCipher = suite.aead(clientKey, clientIV)
+ }
c.out.prepareCipherSpec(c.vers, clientCipher, clientHash)
c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
@@ -303,8 +360,14 @@ func (c *Conn) clientHandshake() error {
finishedHash.Write(finished.marshal())
c.writeRecord(recordTypeHandshake, finished.marshal())
- serverCipher := suite.cipher(serverKey, serverIV, true /* for reading */)
- serverHash := suite.mac(c.vers, serverMAC)
+ var serverCipher interface{}
+ var serverHash macFunction
+ if suite.cipher != nil {
+ serverCipher = suite.cipher(serverKey, serverIV, true /* for reading */)
+ serverHash = suite.mac(c.vers, serverMAC)
+ } else {
+ serverCipher = suite.aead(serverKey, serverIV)
+ }
c.in.prepareCipherSpec(c.vers, serverCipher, serverHash)
c.readRecord(recordTypeChangeCipherSpec)
if err := c.error(); err != nil {
diff --git a/libgo/go/crypto/tls/handshake_client_test.go b/libgo/go/crypto/tls/handshake_client_test.go
index 9673947a409..6c564001b0d 100644
--- a/libgo/go/crypto/tls/handshake_client_test.go
+++ b/libgo/go/crypto/tls/handshake_client_test.go
@@ -39,16 +39,56 @@ func testClientScript(t *testing.T, name string, clientScript [][]byte, config *
}
}
-func TestHandshakeClientRC4(t *testing.T) {
+func TestHandshakeClientRSARC4(t *testing.T) {
var config = *testConfig
config.CipherSuites = []uint16{TLS_RSA_WITH_RC4_128_SHA}
- testClientScript(t, "RC4", rc4ClientScript, &config)
+ testClientScript(t, "RSA-RC4", rsaRC4ClientScript, &config)
}
-func TestHandshakeClientECDHEAES(t *testing.T) {
+func TestHandshakeClientECDHERSAAES(t *testing.T) {
var config = *testConfig
config.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA}
- testClientScript(t, "ECDHE-AES", ecdheAESClientScript, &config)
+ testClientScript(t, "ECDHE-RSA-AES", ecdheRSAAESClientScript, &config)
+}
+
+func TestHandshakeClientECDHECDSAAES(t *testing.T) {
+ var config = *testConfig
+ config.CipherSuites = []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA}
+ config.Certificates = nil
+ config.BuildNameToCertificate()
+ testClientScript(t, "ECDHE-ECDSA-AES", ecdheECDSAAESClientScript, &config)
+}
+
+func TestLongClientCerticiateChain(t *testing.T) {
+ config := *testConfig
+ cert, _ := X509KeyPair(testClientChainCertificate, testClientChainCertificate)
+ config.Certificates = []Certificate{cert}
+ testClientScript(t, "Long client certificate chains", clientChainCertificateScript, &config)
+}
+
+func TestHandshakeClientTLS11(t *testing.T) {
+ var config = *testConfig
+ config.MaxVersion = VersionTLS11
+ config.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA}
+ testClientScript(t, "TLS11-ECDHE-AES", tls11ECDHEAESClientScript, &config)
+}
+
+func TestHandshakeClientTLS12(t *testing.T) {
+ config := *testConfig
+ config.MaxVersion = VersionTLS12
+ config.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA}
+ cert, _ := X509KeyPair(testClientChainCertificate, testClientChainCertificate)
+ config.Certificates = []Certificate{cert}
+ testClientScript(t, "TLS12", clientTLS12Script, &config)
+}
+
+func TestHandshakeClientTLS12ClientCert(t *testing.T) {
+ config := *testConfig
+ config.MaxVersion = VersionTLS12
+ config.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}
+ cert, _ := X509KeyPair(testClientChainCertificate, testClientChainCertificate)
+ config.Certificates = []Certificate{cert}
+ testClientScript(t, "TLS12ClientCert", clientTLS12ClientCertScript, &config)
}
var connect = flag.Bool("connect", false, "connect to a TLS server on :10443")
@@ -79,6 +119,48 @@ func TestRunClient(t *testing.T) {
record.WriteTo(os.Stdout)
}
+func TestEmptyRecords(t *testing.T) {
+ // emptyRecordScript contains a TLS connection with an empty record as
+ // the first application data from the server. This test ensures that
+ // the empty record doesn't cause (0, nil) to be returned from
+ // Conn.Read.
+ config := *testConfig
+ config.CipherSuites = []uint16{TLS_RSA_WITH_AES_256_CBC_SHA}
+
+ c, s := net.Pipe()
+ cli := Client(c, &config)
+ go func() {
+ buf := make([]byte, 1024)
+ n, err := cli.Read(buf)
+ defer c.Close()
+ defer cli.Close()
+
+ if err != nil {
+ t.Fatalf("error reading from tls.Client: %s", err)
+ }
+ const expectedLength = 197
+ if n != expectedLength {
+ t.Fatalf("incorrect length reading from tls.Client, got %d, want %d", n, expectedLength)
+ }
+ }()
+
+ defer c.Close()
+ for i, b := range emptyRecordScript {
+ if i%2 == 1 {
+ s.Write(b)
+ continue
+ }
+ bb := make([]byte, len(b))
+ _, err := io.ReadFull(s, bb)
+ if err != nil {
+ t.Fatalf("#%d: %s", i, err)
+ }
+ if !bytes.Equal(b, bb) {
+ t.Fatalf("#%d: mismatch on read: got:%x want:%x", i, bb, b)
+ }
+ }
+}
+
// Script of interaction with gnutls implementation.
// The values for this test are obtained by building and running in client mode:
// % go test -test.run "TestRunClient" -connect
@@ -110,7 +192,7 @@ func TestRunClient(t *testing.T) {
// CSqGSIb3DQEBBQUAA0EAhTZAc8G7GtrUWZ8tonAxRnTsg26oyDxRrzms7EC86CJG
// HZnWRiok1IsFCEv7NRFukrt3uuQSu/TIXpyBqJdgTA==
// -----END CERTIFICATE-----
-var rc4ClientScript = [][]byte{
+var rsaRC4ClientScript = [][]byte{
{
0x16, 0x03, 0x01, 0x00, 0x4a, 0x01, 0x00, 0x00,
0x46, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -231,7 +313,7 @@ var rc4ClientScript = [][]byte{
},
}
-var ecdheAESClientScript = [][]byte{
+var ecdheRSAAESClientScript = [][]byte{
{
0x16, 0x03, 0x01, 0x00, 0x4a, 0x01, 0x00, 0x00,
0x46, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -406,3 +488,2563 @@ var ecdheAESClientScript = [][]byte{
0x57, 0x33, 0xc3, 0xbc, 0x3f, 0x7a, 0x4d,
},
}
+
+var emptyRecordScript = [][]byte{
+ {
+ 0x16, 0x03, 0x01, 0x00, 0x4a, 0x01, 0x00, 0x00,
+ 0x46, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x35,
+ 0x01, 0x00, 0x00, 0x1b, 0x00, 0x05, 0x00, 0x05,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00,
+ 0x08, 0x00, 0x06, 0x00, 0x17, 0x00, 0x18, 0x00,
+ 0x19, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00,
+ },
+ {
+ 0x16, 0x03, 0x01, 0x00, 0x4a, 0x02, 0x00, 0x00,
+ 0x46, 0x03, 0x01, 0x51, 0x71, 0x8e, 0x03, 0x02,
+ 0xef, 0x09, 0xf2, 0x0e, 0xf5, 0x3b, 0x29, 0x9a,
+ 0xa8, 0x8b, 0x46, 0xa3, 0xd4, 0xb4, 0xc1, 0x14,
+ 0xc3, 0x19, 0x99, 0xba, 0x3d, 0x78, 0xcf, 0x50,
+ 0xd1, 0xe7, 0x26, 0x20, 0xa0, 0x37, 0x6d, 0xc9,
+ 0xae, 0x93, 0x33, 0x81, 0x20, 0xe3, 0xc1, 0x90,
+ 0x64, 0x6e, 0x67, 0x93, 0xdb, 0xb4, 0x04, 0x16,
+ 0xc4, 0x25, 0xdd, 0x10, 0x79, 0x3c, 0x18, 0x0a,
+ 0x7c, 0xfd, 0x28, 0x65, 0x00, 0x35, 0x00, 0x16,
+ 0x03, 0x01, 0x09, 0x9e, 0x0b, 0x00, 0x09, 0x9a,
+ 0x00, 0x09, 0x97, 0x00, 0x04, 0xea, 0x30, 0x82,
+ 0x04, 0xe6, 0x30, 0x82, 0x03, 0xce, 0xa0, 0x03,
+ 0x02, 0x01, 0x02, 0x02, 0x11, 0x00, 0xff, 0xab,
+ 0x02, 0x93, 0xe0, 0x72, 0x99, 0x18, 0x6c, 0x9e,
+ 0x96, 0xb8, 0xb9, 0xf7, 0x47, 0xcb, 0x30, 0x0d,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x41, 0x31,
+ 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+ 0x13, 0x02, 0x46, 0x52, 0x31, 0x12, 0x30, 0x10,
+ 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x09, 0x47,
+ 0x41, 0x4e, 0x44, 0x49, 0x20, 0x53, 0x41, 0x53,
+ 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04,
+ 0x03, 0x13, 0x15, 0x47, 0x61, 0x6e, 0x64, 0x69,
+ 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72,
+ 0x64, 0x20, 0x53, 0x53, 0x4c, 0x20, 0x43, 0x41,
+ 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x33, 0x30, 0x31,
+ 0x31, 0x34, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x5a, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x31, 0x31,
+ 0x34, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a,
+ 0x30, 0x62, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03,
+ 0x55, 0x04, 0x0b, 0x13, 0x18, 0x44, 0x6f, 0x6d,
+ 0x61, 0x69, 0x6e, 0x20, 0x43, 0x6f, 0x6e, 0x74,
+ 0x72, 0x6f, 0x6c, 0x20, 0x56, 0x61, 0x6c, 0x69,
+ 0x64, 0x61, 0x74, 0x65, 0x64, 0x31, 0x24, 0x30,
+ 0x22, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x1b,
+ 0x47, 0x61, 0x6e, 0x64, 0x69, 0x20, 0x53, 0x74,
+ 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x57,
+ 0x69, 0x6c, 0x64, 0x63, 0x61, 0x72, 0x64, 0x20,
+ 0x53, 0x53, 0x4c, 0x31, 0x17, 0x30, 0x15, 0x06,
+ 0x03, 0x55, 0x04, 0x03, 0x14, 0x0e, 0x2a, 0x2e,
+ 0x66, 0x72, 0x65, 0x65, 0x6e, 0x6f, 0x64, 0x65,
+ 0x2e, 0x6e, 0x65, 0x74, 0x30, 0x82, 0x01, 0x22,
+ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+ 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03,
+ 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a,
+ 0x02, 0x82, 0x01, 0x01, 0x00, 0xdc, 0xe3, 0xfd,
+ 0xce, 0xc1, 0x66, 0x62, 0x28, 0x8b, 0x99, 0x65,
+ 0x72, 0x52, 0x88, 0x93, 0x5b, 0x3f, 0x8d, 0xde,
+ 0x2b, 0xb0, 0xa0, 0xf4, 0xbd, 0xb4, 0x07, 0x5f,
+ 0x9e, 0x01, 0x47, 0x60, 0x57, 0x5f, 0xdf, 0xdc,
+ 0x63, 0x28, 0x1c, 0x1e, 0x5b, 0xc8, 0xe6, 0x29,
+ 0xdd, 0xeb, 0x26, 0x63, 0xd5, 0xbf, 0x83, 0xb2,
+ 0x2d, 0xcd, 0x2c, 0xa0, 0xb6, 0x91, 0xad, 0xaf,
+ 0x95, 0x21, 0x1d, 0x1f, 0x39, 0x8d, 0x3e, 0x17,
+ 0xd6, 0xbd, 0x99, 0xf5, 0x6c, 0xd4, 0xcb, 0x79,
+ 0x12, 0x3e, 0x11, 0xb9, 0x7e, 0x62, 0xbc, 0x2d,
+ 0xbf, 0xe0, 0x55, 0x1b, 0x5c, 0x1e, 0xce, 0x31,
+ 0xd9, 0xf8, 0x56, 0x68, 0x95, 0x2b, 0x15, 0x84,
+ 0x35, 0xae, 0x98, 0x2c, 0x63, 0x01, 0xb2, 0x0d,
+ 0xab, 0xa8, 0x61, 0xef, 0x7f, 0x15, 0x2c, 0x6d,
+ 0xf7, 0x67, 0x1d, 0xb8, 0x8d, 0xf6, 0xa2, 0x1c,
+ 0x4e, 0x85, 0xf0, 0xea, 0x1a, 0x2b, 0xc8, 0xac,
+ 0x70, 0x86, 0x9a, 0xbb, 0x9e, 0x9d, 0xbd, 0xc9,
+ 0x87, 0x2b, 0x9f, 0x5e, 0x40, 0x44, 0x9b, 0xba,
+ 0x96, 0x45, 0x24, 0xbc, 0x49, 0xb8, 0xfe, 0x26,
+ 0x3a, 0x1d, 0x1a, 0x0a, 0x3a, 0x90, 0x9c, 0x75,
+ 0x51, 0x59, 0x89, 0x98, 0x1a, 0x56, 0xe1, 0x3a,
+ 0x1a, 0xba, 0xff, 0xb4, 0x37, 0x7d, 0xd8, 0x99,
+ 0xe2, 0xeb, 0x45, 0x27, 0xe2, 0x42, 0x42, 0x46,
+ 0xbb, 0x00, 0x29, 0x9f, 0x30, 0xc9, 0x1e, 0x6c,
+ 0xce, 0x59, 0x0e, 0xbe, 0x16, 0x03, 0x31, 0xec,
+ 0x10, 0xc1, 0x6d, 0xca, 0x9d, 0x5f, 0x6d, 0xf1,
+ 0x26, 0x11, 0xe5, 0x50, 0xa1, 0xbb, 0x67, 0xb2,
+ 0xe0, 0x2b, 0xed, 0x76, 0x5b, 0xc7, 0x68, 0xc0,
+ 0x18, 0xad, 0x91, 0x9e, 0xb5, 0xd4, 0x4d, 0x21,
+ 0xcd, 0x98, 0xd9, 0xe0, 0x05, 0x0a, 0x4d, 0x24,
+ 0xa3, 0xe6, 0x12, 0x04, 0xdd, 0x50, 0xe6, 0xc8,
+ 0x7a, 0x69, 0xb9, 0x32, 0x43, 0x02, 0x03, 0x01,
+ 0x00, 0x01, 0xa3, 0x82, 0x01, 0xb6, 0x30, 0x82,
+ 0x01, 0xb2, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d,
+ 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xb6,
+ 0xa8, 0xff, 0xa2, 0xa8, 0x2f, 0xd0, 0xa6, 0xcd,
+ 0x4b, 0xb1, 0x68, 0xf3, 0xe7, 0x50, 0x10, 0x31,
+ 0xa7, 0x79, 0x21, 0x30, 0x1d, 0x06, 0x03, 0x55,
+ 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x62, 0x37,
+ 0xd4, 0x3c, 0xbf, 0xd9, 0xc2, 0x99, 0xf3, 0x28,
+ 0x3e, 0xdb, 0xca, 0xee, 0xf3, 0xb3, 0xc8, 0x73,
+ 0xb0, 0x3c, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d,
+ 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02,
+ 0x05, 0xa0, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d,
+ 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, 0x00,
+ 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04,
+ 0x16, 0x30, 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01,
+ 0x05, 0x05, 0x07, 0x03, 0x01, 0x06, 0x08, 0x2b,
+ 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x30,
+ 0x60, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, 0x59,
+ 0x30, 0x57, 0x30, 0x4b, 0x06, 0x0b, 0x2b, 0x06,
+ 0x01, 0x04, 0x01, 0xb2, 0x31, 0x01, 0x02, 0x02,
+ 0x1a, 0x30, 0x3c, 0x30, 0x3a, 0x06, 0x08, 0x2b,
+ 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16,
+ 0x2e, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f,
+ 0x77, 0x77, 0x77, 0x2e, 0x67, 0x61, 0x6e, 0x64,
+ 0x69, 0x2e, 0x6e, 0x65, 0x74, 0x2f, 0x63, 0x6f,
+ 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x73, 0x2f,
+ 0x66, 0x72, 0x2f, 0x73, 0x73, 0x6c, 0x2f, 0x63,
+ 0x70, 0x73, 0x2f, 0x70, 0x64, 0x66, 0x2f, 0x30,
+ 0x08, 0x06, 0x06, 0x67, 0x81, 0x0c, 0x01, 0x02,
+ 0x01, 0x30, 0x3c, 0x06, 0x03, 0x55, 0x1d, 0x1f,
+ 0x04, 0x35, 0x30, 0x33, 0x30, 0x31, 0xa0, 0x2f,
+ 0xa0, 0x2d, 0x86, 0x2b, 0x68, 0x74, 0x74, 0x70,
+ 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e, 0x67,
+ 0x61, 0x6e, 0x64, 0x69, 0x2e, 0x6e, 0x65, 0x74,
+ 0x2f, 0x47, 0x61, 0x6e, 0x64, 0x69, 0x53, 0x74,
+ 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x53, 0x53,
+ 0x4c, 0x43, 0x41, 0x2e, 0x63, 0x72, 0x6c, 0x30,
+ 0x6a, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05,
+ 0x07, 0x01, 0x01, 0x04, 0x5e, 0x30, 0x5c, 0x30,
+ 0x37, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05,
+ 0x07, 0x30, 0x02, 0x86, 0x2b, 0x68, 0x74, 0x74,
+ 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x74, 0x2e,
+ 0x67, 0x61, 0x6e, 0x64, 0x69, 0x2e, 0x6e, 0x65,
+ 0x74, 0x2f, 0x47, 0x61, 0x6e, 0x64, 0x69, 0x53,
+ 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x53,
+ 0x53, 0x4c, 0x43, 0x41, 0x2e, 0x63, 0x72, 0x74,
+ 0x30, 0x21, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05,
+ 0x05, 0x07, 0x30, 0x01, 0x86, 0x15, 0x68, 0x74,
+ 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, 0x73,
+ 0x70, 0x2e, 0x67, 0x61, 0x6e, 0x64, 0x69, 0x2e,
+ 0x6e, 0x65, 0x74, 0x30, 0x27, 0x06, 0x03, 0x55,
+ 0x1d, 0x11, 0x04, 0x20, 0x30, 0x1e, 0x82, 0x0e,
+ 0x2a, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x6e, 0x6f,
+ 0x64, 0x65, 0x2e, 0x6e, 0x65, 0x74, 0x82, 0x0c,
+ 0x66, 0x72, 0x65, 0x65, 0x6e, 0x6f, 0x64, 0x65,
+ 0x2e, 0x6e, 0x65, 0x74, 0x30, 0x0d, 0x06, 0x09,
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+ 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00,
+ 0x5b, 0x4a, 0x3a, 0x1d, 0x75, 0xe0, 0xc0, 0x9e,
+ 0xc9, 0x16, 0x66, 0x7f, 0x73, 0x95, 0x6e, 0x35,
+ 0xe4, 0x27, 0xfa, 0x8c, 0x9d, 0xee, 0xb1, 0x37,
+ 0x42, 0x3f, 0x54, 0x6a, 0x9d, 0x41, 0x84, 0x57,
+ 0xe1, 0x03, 0x3d, 0x69, 0x61, 0x77, 0x3b, 0x91,
+ 0xa2, 0x70, 0x94, 0xb6, 0x8e, 0x41, 0x63, 0x70,
+ 0xf2, 0x16, 0x04, 0x50, 0x05, 0x14, 0xfb, 0x59,
+ 0x7d, 0x89, 0x09, 0x3f, 0xb6, 0xef, 0xca, 0x3c,
+ 0x89, 0x88, 0x08, 0xe9, 0xa1, 0xf3, 0x33, 0x31,
+ 0x05, 0x4d, 0x70, 0xff, 0xdd, 0xa7, 0xd2, 0xe2,
+ 0xa0, 0x94, 0x3a, 0xf7, 0xc2, 0x9f, 0xad, 0x2b,
+ 0x2e, 0x20, 0xfa, 0x6c, 0xe1, 0xfc, 0xe6, 0x62,
+ 0x22, 0xa1, 0x38, 0x93, 0xec, 0x3e, 0xce, 0xfd,
+ 0x1f, 0xdd, 0xd4, 0x7c, 0x39, 0x46, 0x8b, 0xb4,
+ 0x64, 0xfa, 0xa1, 0x46, 0x87, 0x78, 0x2c, 0xd7,
+ 0x9c, 0xdd, 0x60, 0xd6, 0xda, 0x8e, 0xd8, 0x29,
+ 0x6d, 0x61, 0xa7, 0x29, 0x07, 0x76, 0xfc, 0xf9,
+ 0xbd, 0xfd, 0x14, 0xeb, 0x44, 0x70, 0xff, 0xd0,
+ 0x23, 0x99, 0x83, 0xc5, 0x5c, 0x56, 0x88, 0xaa,
+ 0x34, 0xda, 0xa6, 0xb3, 0x9a, 0xbf, 0xda, 0x58,
+ 0x1e, 0xa4, 0xb8, 0xc0, 0x40, 0x9d, 0xf0, 0xfc,
+ 0xf1, 0x23, 0xc2, 0xbc, 0x59, 0xe1, 0x82, 0xed,
+ 0x5d, 0xfb, 0x99, 0xaf, 0xf5, 0xf5, 0x15, 0xb8,
+ 0x8b, 0x59, 0xce, 0xaa, 0xca, 0xdf, 0xdc, 0x94,
+ 0x11, 0xe0, 0x96, 0xbf, 0x9f, 0x54, 0xa4, 0x9f,
+ 0x54, 0x36, 0x4a, 0xe8, 0x93, 0xda, 0xf4, 0x8c,
+ 0xb0, 0x6b, 0x8d, 0x4a, 0x9e, 0x11, 0xae, 0xcb,
+ 0xcb, 0x33, 0x8a, 0x4d, 0xcd, 0x4e, 0xa5, 0x9b,
+ 0xe9, 0x14, 0x46, 0x43, 0x9b, 0x96, 0x5f, 0x6d,
+ 0xf2, 0xea, 0x40, 0xef, 0x14, 0xc3, 0x99, 0x9f,
+ 0x23, 0x1e, 0xa5, 0x13, 0xab, 0x08, 0xea, 0x8f,
+ 0x68, 0x5b, 0x7d, 0x71, 0xdf, 0x18, 0xd1, 0x57,
+ 0x00, 0x04, 0xa7, 0x30, 0x82, 0x04, 0xa3, 0x30,
+ 0x82, 0x03, 0x8b, 0xa0, 0x03, 0x02, 0x01, 0x02,
+ 0x02, 0x10, 0x5a, 0xb6, 0x1d, 0xac, 0x1e, 0x4d,
+ 0xa2, 0x06, 0x14, 0xc7, 0x55, 0x3d, 0x3d, 0xa9,
+ 0xb2, 0xdc, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
+ 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05,
+ 0x00, 0x30, 0x81, 0x97, 0x31, 0x0b, 0x30, 0x09,
+ 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55,
+ 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+ 0x04, 0x08, 0x13, 0x02, 0x55, 0x54, 0x31, 0x17,
+ 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13,
+ 0x0e, 0x53, 0x61, 0x6c, 0x74, 0x20, 0x4c, 0x61,
+ 0x6b, 0x65, 0x20, 0x43, 0x69, 0x74, 0x79, 0x31,
+ 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, 0x0a,
+ 0x13, 0x15, 0x54, 0x68, 0x65, 0x20, 0x55, 0x53,
+ 0x45, 0x52, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20,
+ 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x31,
+ 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0b,
+ 0x13, 0x18, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
+ 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x75, 0x73, 0x65,
+ 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x63,
+ 0x6f, 0x6d, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03,
+ 0x55, 0x04, 0x03, 0x13, 0x16, 0x55, 0x54, 0x4e,
+ 0x2d, 0x55, 0x53, 0x45, 0x52, 0x46, 0x69, 0x72,
+ 0x73, 0x74, 0x2d, 0x48, 0x61, 0x72, 0x64, 0x77,
+ 0x61, 0x72, 0x65, 0x30, 0x1e, 0x17, 0x0d, 0x30,
+ 0x38, 0x31, 0x30, 0x32, 0x33, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x32, 0x30,
+ 0x30, 0x35, 0x33, 0x30, 0x31, 0x30, 0x34, 0x38,
+ 0x33, 0x38, 0x5a, 0x30, 0x41, 0x31, 0x0b, 0x30,
+ 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+ 0x46, 0x52, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03,
+ 0x55, 0x04, 0x0a, 0x13, 0x09, 0x47, 0x41, 0x4e,
+ 0x44, 0x49, 0x20, 0x53, 0x41, 0x53, 0x31, 0x1e,
+ 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
+ 0x15, 0x47, 0x61, 0x6e, 0x64, 0x69, 0x20, 0x53,
+ 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20,
+ 0x53, 0x53, 0x4c, 0x20, 0x43, 0x41, 0x30, 0x82,
+ 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
+ 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05,
+ 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82,
+ 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xb6,
+ 0x54, 0x3d, 0xa5, 0xdb, 0x0d, 0x22, 0x78, 0x50,
+ 0x6a, 0x5a, 0x23, 0x89, 0x3f, 0x97, 0xa1, 0xd4,
+ 0x07, 0x1a, 0xa9, 0x58, 0x08, 0x9b, 0xa0, 0x15,
+ 0xc3, 0x32, 0xb6, 0xb7, 0xf1, 0xe8, 0xb9, 0xa5,
+ 0x6f, 0xad, 0x37, 0xf6, 0x6e, 0x71, 0x1b, 0xb4,
+ 0x75, 0x2d, 0x48, 0x5e, 0x9f, 0xc6, 0x15, 0xaa,
+ 0x81, 0xef, 0xe5, 0xc4, 0x88, 0x95, 0x8a, 0x3a,
+ 0x6c, 0x77, 0xcc, 0xb5, 0xcd, 0x65, 0xe4, 0x67,
+ 0xe5, 0x73, 0xc9, 0x50, 0x52, 0x94, 0xc1, 0x27,
+ 0x49, 0x3e, 0xa0, 0x6b, 0x41, 0x16, 0x41, 0xb6,
+ 0x94, 0x99, 0x41, 0xae, 0x3e, 0xcb, 0xe2, 0x06,
+ 0x46, 0x09, 0xe9, 0x4d, 0xbe, 0xc9, 0x4c, 0x55,
+ 0xa9, 0x18, 0x7e, 0xa6, 0xdf, 0x6e, 0xfd, 0x4a,
+ 0xb2, 0xcc, 0x6c, 0x4e, 0xd9, 0xc8, 0x50, 0x15,
+ 0x93, 0xb3, 0xf2, 0xe9, 0xe3, 0xc2, 0x6a, 0xad,
+ 0x3a, 0xd5, 0xfb, 0xc3, 0x79, 0x50, 0x9f, 0x25,
+ 0x79, 0x29, 0xb2, 0x47, 0x64, 0x7c, 0x20, 0x3e,
+ 0xe2, 0x08, 0x4d, 0x93, 0x29, 0x14, 0xb6, 0x34,
+ 0x6e, 0xcf, 0x71, 0x46, 0x7e, 0x76, 0x10, 0xf4,
+ 0xfd, 0x6c, 0xaa, 0x01, 0xd2, 0xc2, 0x06, 0xde,
+ 0x92, 0x83, 0xcc, 0x58, 0x90, 0x2e, 0x92, 0xde,
+ 0x1e, 0x65, 0xb7, 0x63, 0x2f, 0x3d, 0xb2, 0xeb,
+ 0x70, 0x8c, 0x4c, 0xe0, 0xbe, 0x15, 0x9d, 0xde,
+ 0xc1, 0x4d, 0x56, 0xf8, 0x0b, 0xc6, 0x8e, 0x07,
+ 0xb9, 0x5d, 0xdf, 0x95, 0xf0, 0x7b, 0x40, 0x1f,
+ 0x1a, 0x2c, 0xd7, 0x9c, 0x2b, 0x4b, 0x76, 0xf4,
+ 0x59, 0xf5, 0x43, 0xc1, 0x2c, 0x66, 0x10, 0x9e,
+ 0x9e, 0x66, 0x96, 0x60, 0x9d, 0x1c, 0x74, 0x1b,
+ 0x4e, 0x18, 0x5c, 0x08, 0xb0, 0x6e, 0x6c, 0xca,
+ 0x69, 0x1a, 0x02, 0xe9, 0xbb, 0xca, 0x78, 0xef,
+ 0x66, 0x2e, 0xe3, 0x32, 0xfd, 0x41, 0x5c, 0x95,
+ 0x74, 0x81, 0x4d, 0xf4, 0xda, 0xfe, 0x4b, 0x02,
+ 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01, 0x3e,
+ 0x30, 0x82, 0x01, 0x3a, 0x30, 0x1f, 0x06, 0x03,
+ 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80,
+ 0x14, 0xa1, 0x72, 0x5f, 0x26, 0x1b, 0x28, 0x98,
+ 0x43, 0x95, 0x5d, 0x07, 0x37, 0xd5, 0x85, 0x96,
+ 0x9d, 0x4b, 0xd2, 0xc3, 0x45, 0x30, 0x1d, 0x06,
+ 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14,
+ 0xb6, 0xa8, 0xff, 0xa2, 0xa8, 0x2f, 0xd0, 0xa6,
+ 0xcd, 0x4b, 0xb1, 0x68, 0xf3, 0xe7, 0x50, 0x10,
+ 0x31, 0xa7, 0x79, 0x21, 0x30, 0x0e, 0x06, 0x03,
+ 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04,
+ 0x03, 0x02, 0x01, 0x06, 0x30, 0x12, 0x06, 0x03,
+ 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08,
+ 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x00,
+ 0x30, 0x18, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04,
+ 0x11, 0x30, 0x0f, 0x30, 0x0d, 0x06, 0x0b, 0x2b,
+ 0x06, 0x01, 0x04, 0x01, 0xb2, 0x31, 0x01, 0x02,
+ 0x02, 0x1a, 0x30, 0x44, 0x06, 0x03, 0x55, 0x1d,
+ 0x1f, 0x04, 0x3d, 0x30, 0x3b, 0x30, 0x39, 0xa0,
+ 0x37, 0xa0, 0x35, 0x86, 0x33, 0x68, 0x74, 0x74,
+ 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e,
+ 0x75, 0x73, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73,
+ 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x55, 0x54,
+ 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, 0x46, 0x69,
+ 0x72, 0x73, 0x74, 0x2d, 0x48, 0x61, 0x72, 0x64,
+ 0x77, 0x61, 0x72, 0x65, 0x2e, 0x63, 0x72, 0x6c,
+ 0x30, 0x74, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05,
+ 0x05, 0x07, 0x01, 0x01, 0x04, 0x68, 0x30, 0x66,
+ 0x30, 0x3d, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05,
+ 0x05, 0x07, 0x30, 0x02, 0x86, 0x31, 0x68, 0x74,
+ 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x74,
+ 0x2e, 0x75, 0x73, 0x65, 0x72, 0x74, 0x72, 0x75,
+ 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x55,
+ 0x54, 0x4e, 0x41, 0x64, 0x64, 0x54, 0x72, 0x75,
+ 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72,
+ 0x5f, 0x43, 0x41, 0x2e, 0x63, 0x72, 0x74, 0x30,
+ 0x25, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05,
+ 0x07, 0x30, 0x01, 0x86, 0x19, 0x68, 0x74, 0x74,
+ 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, 0x73, 0x70,
+ 0x2e, 0x75, 0x73, 0x65, 0x72, 0x74, 0x72, 0x75,
+ 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x0d,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01,
+ 0x01, 0x00, 0x19, 0x53, 0xbf, 0x03, 0x3d, 0x9b,
+ 0xe2, 0x6b, 0x5a, 0xfd, 0xba, 0x49, 0x1f, 0x4f,
+ 0xec, 0xe1, 0xc6, 0x82, 0x39, 0x3c, 0xd2, 0x03,
+ 0x04, 0x0f, 0xab, 0x7b, 0x3e, 0x82, 0xa9, 0x85,
+ 0x10, 0x1f, 0xf4, 0xde, 0x32, 0xaf, 0x58, 0x3f,
+ 0xff, 0x70, 0xf3, 0x30, 0x1d, 0x97, 0x2d, 0x4c,
+ 0x9a, 0xe2, 0xec, 0x0c, 0x3e, 0x14, 0x2d, 0x2f,
+ 0x98, 0x48, 0x9d, 0xae, 0x16, 0x6a, 0xac, 0x2d,
+ 0x42, 0xaa, 0xb5, 0x64, 0xa4, 0x70, 0xbb, 0xeb,
+ 0x73, 0x94, 0x7b, 0x46, 0x4c, 0xe7, 0x7a, 0x14,
+ 0x76, 0x5b, 0x4c, 0x1d, 0x84, 0xa1, 0x20, 0x74,
+ 0x1f, 0x2e, 0x4b, 0x5c, 0x70, 0x88, 0xdc, 0xbd,
+ 0xf7, 0x19, 0x3d, 0xed, 0x59, 0x0d, 0xe2, 0x3f,
+ 0x26, 0xe2, 0x9c, 0xac, 0xa4, 0x3c, 0x95, 0x1c,
+ 0xf8, 0xbe, 0x8c, 0x03, 0xae, 0xf0, 0xe5, 0x9c,
+ 0x4d, 0xbc, 0xc7, 0x9b, 0x58, 0x00, 0xbf, 0xaf,
+ 0xad, 0xfa, 0x37, 0x6e, 0x71, 0x6d, 0x18, 0x34,
+ 0x0e, 0xc1, 0xea, 0x6a, 0xf8, 0x0d, 0xdf, 0x69,
+ 0x54, 0x56, 0x15, 0xf2, 0x28, 0xb3, 0xfe, 0xa4,
+ 0x63, 0xec, 0xc5, 0x04, 0x64, 0x60, 0xbb, 0xfe,
+ 0x2a, 0xf0, 0xf4, 0x87, 0xa1, 0xb0, 0xae, 0xbd,
+ 0xaa, 0xe4, 0x2f, 0xe3, 0x03, 0x0b, 0x2f, 0x66,
+ 0x5f, 0x85, 0xa4, 0x32, 0x7b, 0x46, 0xed, 0x25,
+ 0x0c, 0xe7, 0xf1, 0xb7, 0xe7, 0x19, 0xfd, 0x60,
+ 0xba, 0x5f, 0x87, 0x77, 0xde, 0x98, 0x07, 0x96,
+ 0xe4, 0x5e, 0xea, 0x63, 0x7d, 0xa8, 0xde, 0x55,
+ 0xda, 0x61, 0x5c, 0x3c, 0x90, 0x83, 0x43, 0x04,
+ 0x07, 0x3c, 0xdd, 0xf3, 0xf8, 0x9f, 0x06, 0x52,
+ 0x0a, 0xde, 0xc7, 0xb6, 0x7b, 0x8f, 0xe1, 0x11,
+ 0xf7, 0x04, 0x7a, 0x35, 0xff, 0x6a, 0xbc, 0x5b,
+ 0xc7, 0x50, 0x49, 0x08, 0x70, 0x6f, 0x94, 0x43,
+ 0xcd, 0x9e, 0xc7, 0x70, 0xf1, 0xdb, 0xd0, 0x6d,
+ 0xda, 0x8f, 0x16, 0x03, 0x01, 0x00, 0x0e, 0x0d,
+ 0x00, 0x00, 0x06, 0x03, 0x01, 0x02, 0x40, 0x00,
+ 0x00, 0x0e, 0x00, 0x00, 0x00,
+ },
+ {
+ 0x16, 0x03, 0x01, 0x02, 0xbe, 0x0b, 0x00, 0x02,
+ 0xba, 0x00, 0x02, 0xb7, 0x00, 0x02, 0xb4, 0x30,
+ 0x82, 0x02, 0xb0, 0x30, 0x82, 0x02, 0x19, 0xa0,
+ 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0x85,
+ 0xb0, 0xbb, 0xa4, 0x8a, 0x7f, 0xb8, 0xca, 0x30,
+ 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x45,
+ 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
+ 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30,
+ 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a,
+ 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61,
+ 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03,
+ 0x55, 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74,
+ 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69,
+ 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74,
+ 0x79, 0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e, 0x17,
+ 0x0d, 0x31, 0x30, 0x30, 0x34, 0x32, 0x34, 0x30,
+ 0x39, 0x30, 0x39, 0x33, 0x38, 0x5a, 0x17, 0x0d,
+ 0x31, 0x31, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39,
+ 0x30, 0x39, 0x33, 0x38, 0x5a, 0x30, 0x45, 0x31,
+ 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+ 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11,
+ 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53,
+ 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74,
+ 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55,
+ 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65,
+ 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64,
+ 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79,
+ 0x20, 0x4c, 0x74, 0x64, 0x30, 0x81, 0x9f, 0x30,
+ 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81,
+ 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81,
+ 0x00, 0xbb, 0x79, 0xd6, 0xf5, 0x17, 0xb5, 0xe5,
+ 0xbf, 0x46, 0x10, 0xd0, 0xdc, 0x69, 0xbe, 0xe6,
+ 0x2b, 0x07, 0x43, 0x5a, 0xd0, 0x03, 0x2d, 0x8a,
+ 0x7a, 0x43, 0x85, 0xb7, 0x14, 0x52, 0xe7, 0xa5,
+ 0x65, 0x4c, 0x2c, 0x78, 0xb8, 0x23, 0x8c, 0xb5,
+ 0xb4, 0x82, 0xe5, 0xde, 0x1f, 0x95, 0x3b, 0x7e,
+ 0x62, 0xa5, 0x2c, 0xa5, 0x33, 0xd6, 0xfe, 0x12,
+ 0x5c, 0x7a, 0x56, 0xfc, 0xf5, 0x06, 0xbf, 0xfa,
+ 0x58, 0x7b, 0x26, 0x3f, 0xb5, 0xcd, 0x04, 0xd3,
+ 0xd0, 0xc9, 0x21, 0x96, 0x4a, 0xc7, 0xf4, 0x54,
+ 0x9f, 0x5a, 0xbf, 0xef, 0x42, 0x71, 0x00, 0xfe,
+ 0x18, 0x99, 0x07, 0x7f, 0x7e, 0x88, 0x7d, 0x7d,
+ 0xf1, 0x04, 0x39, 0xc4, 0xa2, 0x2e, 0xdb, 0x51,
+ 0xc9, 0x7c, 0xe3, 0xc0, 0x4c, 0x3b, 0x32, 0x66,
+ 0x01, 0xcf, 0xaf, 0xb1, 0x1d, 0xb8, 0x71, 0x9a,
+ 0x1d, 0xdb, 0xdb, 0x89, 0x6b, 0xae, 0xda, 0x2d,
+ 0x79, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81,
+ 0xa7, 0x30, 0x81, 0xa4, 0x30, 0x1d, 0x06, 0x03,
+ 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xb1,
+ 0xad, 0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb,
+ 0x69, 0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e,
+ 0x18, 0x88, 0x39, 0x30, 0x75, 0x06, 0x03, 0x55,
+ 0x1d, 0x23, 0x04, 0x6e, 0x30, 0x6c, 0x80, 0x14,
+ 0xb1, 0xad, 0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28,
+ 0xdb, 0x69, 0xce, 0x23, 0x69, 0xde, 0xd3, 0x26,
+ 0x8e, 0x18, 0x88, 0x39, 0xa1, 0x49, 0xa4, 0x47,
+ 0x30, 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
+ 0x55, 0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31,
+ 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08,
+ 0x13, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53,
+ 0x74, 0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f,
+ 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, 0x49,
+ 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20,
+ 0x57, 0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20,
+ 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x82,
+ 0x09, 0x00, 0x85, 0xb0, 0xbb, 0xa4, 0x8a, 0x7f,
+ 0xb8, 0xca, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d,
+ 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff,
+ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+ 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03,
+ 0x81, 0x81, 0x00, 0x08, 0x6c, 0x45, 0x24, 0xc7,
+ 0x6b, 0xb1, 0x59, 0xab, 0x0c, 0x52, 0xcc, 0xf2,
+ 0xb0, 0x14, 0xd7, 0x87, 0x9d, 0x7a, 0x64, 0x75,
+ 0xb5, 0x5a, 0x95, 0x66, 0xe4, 0xc5, 0x2b, 0x8e,
+ 0xae, 0x12, 0x66, 0x1f, 0xeb, 0x4f, 0x38, 0xb3,
+ 0x6e, 0x60, 0xd3, 0x92, 0xfd, 0xf7, 0x41, 0x08,
+ 0xb5, 0x25, 0x13, 0xb1, 0x18, 0x7a, 0x24, 0xfb,
+ 0x30, 0x1d, 0xba, 0xed, 0x98, 0xb9, 0x17, 0xec,
+ 0xe7, 0xd7, 0x31, 0x59, 0xdb, 0x95, 0xd3, 0x1d,
+ 0x78, 0xea, 0x50, 0x56, 0x5c, 0xd5, 0x82, 0x5a,
+ 0x2d, 0x5a, 0x5f, 0x33, 0xc4, 0xb6, 0xd8, 0xc9,
+ 0x75, 0x90, 0x96, 0x8c, 0x0f, 0x52, 0x98, 0xb5,
+ 0xcd, 0x98, 0x1f, 0x89, 0x20, 0x5f, 0xf2, 0xa0,
+ 0x1c, 0xa3, 0x1b, 0x96, 0x94, 0xdd, 0xa9, 0xfd,
+ 0x57, 0xe9, 0x70, 0xe8, 0x26, 0x6d, 0x71, 0x99,
+ 0x9b, 0x26, 0x6e, 0x38, 0x50, 0x29, 0x6c, 0x90,
+ 0xa7, 0xbd, 0xd9, 0x16, 0x03, 0x01, 0x01, 0x06,
+ 0x10, 0x00, 0x01, 0x02, 0x01, 0x00, 0x25, 0x48,
+ 0x6c, 0x0a, 0xde, 0x9d, 0x3a, 0x57, 0xe4, 0x2e,
+ 0xb9, 0xfc, 0xb4, 0x46, 0x1f, 0x20, 0x4f, 0x58,
+ 0x4d, 0x12, 0x08, 0xb4, 0x3e, 0x4c, 0xf5, 0xa8,
+ 0xa5, 0x16, 0x40, 0x29, 0x19, 0x04, 0x4d, 0xf9,
+ 0x54, 0x3a, 0x32, 0xd7, 0x79, 0xf2, 0x0e, 0xc1,
+ 0x7b, 0x0c, 0x62, 0x71, 0xbb, 0xb4, 0x8c, 0xe7,
+ 0x84, 0xd5, 0xf8, 0x11, 0x77, 0x7f, 0x87, 0x6c,
+ 0xfc, 0x25, 0xf3, 0x2d, 0x97, 0x3d, 0x1f, 0xf5,
+ 0xfc, 0x64, 0x94, 0x9f, 0xdd, 0x90, 0x82, 0xdd,
+ 0x11, 0x74, 0x74, 0x59, 0xa2, 0x1a, 0x71, 0xb2,
+ 0x55, 0x6d, 0x18, 0xca, 0x85, 0x47, 0x8b, 0x79,
+ 0x73, 0x06, 0x24, 0x38, 0xc3, 0x34, 0x98, 0x84,
+ 0x62, 0x81, 0xd8, 0xad, 0x54, 0xad, 0x13, 0xa5,
+ 0xf4, 0xe4, 0x82, 0x85, 0xd3, 0xe3, 0x9e, 0xeb,
+ 0xb5, 0xf5, 0x95, 0x83, 0x0e, 0xb9, 0x7d, 0xb6,
+ 0xda, 0x0c, 0xf6, 0x14, 0x6a, 0x60, 0x8c, 0x75,
+ 0x56, 0xf0, 0xe9, 0x60, 0xe0, 0x4c, 0xf4, 0x4e,
+ 0x84, 0x8b, 0x4f, 0xf4, 0x2f, 0xde, 0xb7, 0xec,
+ 0x61, 0xd3, 0x77, 0x07, 0x6e, 0x41, 0x57, 0xc9,
+ 0xd9, 0x1d, 0x75, 0xee, 0x42, 0x63, 0xdc, 0x58,
+ 0xad, 0xfc, 0xc7, 0xe1, 0x77, 0x49, 0xb1, 0x58,
+ 0x21, 0x96, 0x00, 0x55, 0x90, 0x6b, 0xf6, 0x2a,
+ 0x5a, 0x19, 0x25, 0x93, 0x59, 0x9d, 0xaf, 0x79,
+ 0x9b, 0x18, 0x5d, 0xf6, 0x5d, 0x64, 0x4b, 0x9a,
+ 0xf4, 0xde, 0xf2, 0x7f, 0xbd, 0x93, 0x7e, 0x45,
+ 0x3e, 0x17, 0xae, 0xbf, 0x52, 0xe1, 0xba, 0x8e,
+ 0x0b, 0xbc, 0x1e, 0x91, 0x9d, 0xf1, 0x4e, 0x0b,
+ 0xab, 0x9e, 0x5c, 0x4c, 0x6f, 0xf7, 0xf3, 0x8d,
+ 0x8c, 0x6d, 0xeb, 0x46, 0x05, 0x36, 0x7e, 0x2f,
+ 0x9c, 0xa1, 0x86, 0x15, 0xe1, 0xe4, 0xb4, 0x20,
+ 0x06, 0x44, 0x7b, 0x3c, 0x8b, 0x13, 0x96, 0xf5,
+ 0x02, 0xb1, 0x4f, 0x3c, 0x2d, 0x4a, 0x16, 0x03,
+ 0x01, 0x00, 0x86, 0x0f, 0x00, 0x00, 0x82, 0x00,
+ 0x80, 0x52, 0xb1, 0x0d, 0xfc, 0x85, 0x34, 0x56,
+ 0xb9, 0xdf, 0xa7, 0x8e, 0xf4, 0xfd, 0x02, 0x46,
+ 0x8a, 0x23, 0xcc, 0x53, 0x3b, 0x0f, 0xa7, 0x61,
+ 0xf3, 0xb5, 0xbf, 0xfe, 0x59, 0x77, 0x10, 0xd6,
+ 0x56, 0x93, 0x19, 0x6b, 0x2c, 0xf1, 0x35, 0x71,
+ 0xe3, 0x36, 0x2f, 0xa0, 0x90, 0x4e, 0x5a, 0xdf,
+ 0x8d, 0x06, 0x88, 0xcf, 0xb1, 0x06, 0x56, 0x8b,
+ 0x74, 0x8f, 0x02, 0x8e, 0x10, 0xd2, 0xab, 0x8d,
+ 0x3f, 0x3e, 0x02, 0xf1, 0x1a, 0x80, 0x6d, 0x0f,
+ 0x9e, 0x77, 0xd8, 0xfa, 0x92, 0xb3, 0x16, 0x40,
+ 0xeb, 0x9e, 0xca, 0xd7, 0xe4, 0x31, 0xcc, 0x63,
+ 0x5f, 0xe2, 0x4c, 0x85, 0x0e, 0xf2, 0xdd, 0xd3,
+ 0xfe, 0x7e, 0xa7, 0x60, 0x1c, 0xb4, 0x00, 0xd8,
+ 0xbe, 0x4b, 0x9b, 0x66, 0x78, 0x0f, 0xfb, 0x3b,
+ 0x52, 0x30, 0x2b, 0x8b, 0xd9, 0xef, 0x82, 0x0a,
+ 0xa4, 0x18, 0x1d, 0xb0, 0xb5, 0xbf, 0x54, 0x97,
+ 0x0c, 0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16,
+ 0x03, 0x01, 0x00, 0x30, 0xa1, 0x74, 0x22, 0xd8,
+ 0x86, 0x6a, 0xbe, 0x53, 0x34, 0x1d, 0xb3, 0x73,
+ 0xff, 0x51, 0xc0, 0xce, 0x8e, 0x7d, 0x9b, 0xab,
+ 0xcb, 0x8b, 0x79, 0xae, 0x04, 0x01, 0xa7, 0xf2,
+ 0x8e, 0x9d, 0xab, 0xa3, 0x73, 0x80, 0x5c, 0xff,
+ 0x96, 0x20, 0xbb, 0x8d, 0xc0, 0x02, 0x66, 0x6c,
+ 0x83, 0x4b, 0x78, 0x20,
+ },
+ {
+ 0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03,
+ 0x01, 0x00, 0x30, 0x29, 0xd4, 0xfd, 0x03, 0x8b,
+ 0x30, 0x20, 0xf7, 0xca, 0xc0, 0x6c, 0x83, 0x5d,
+ 0x73, 0xcb, 0x81, 0x60, 0xe0, 0x9a, 0x09, 0xcb,
+ 0x33, 0x03, 0x80, 0x81, 0x4e, 0x84, 0x47, 0xd5,
+ 0x74, 0x6c, 0x3b, 0xb5, 0xc0, 0x48, 0x0d, 0x52,
+ 0xdd, 0xbe, 0xc2, 0x06, 0xf5, 0x79, 0x2b, 0x3e,
+ 0x99, 0x56, 0x94, 0x17, 0x03, 0x01, 0x00, 0x20,
+ 0x26, 0x46, 0x90, 0x9d, 0xef, 0x59, 0x00, 0xb6,
+ 0x70, 0xe8, 0x1e, 0x1a, 0x80, 0x8b, 0x04, 0xb2,
+ 0xfc, 0x51, 0xf8, 0x93, 0xbe, 0x00, 0x28, 0xba,
+ 0xb8, 0xdc, 0x51, 0x7e, 0x92, 0x80, 0xfa, 0xf2,
+ 0x17, 0x03, 0x01, 0x00, 0xe0, 0xb8, 0x2e, 0xc4,
+ 0x6b, 0x3f, 0xda, 0x39, 0x87, 0x7f, 0x03, 0x43,
+ 0x28, 0xdd, 0xb9, 0xf9, 0x9e, 0x16, 0xf5, 0xce,
+ 0x3f, 0x7e, 0x6a, 0x7b, 0xb3, 0x60, 0x14, 0xe1,
+ 0xea, 0x54, 0xc5, 0xe6, 0x05, 0x0a, 0x6c, 0xe0,
+ 0xef, 0x58, 0x29, 0x8a, 0x77, 0x64, 0x77, 0x5d,
+ 0x9c, 0xe2, 0xe0, 0x3c, 0x6d, 0x87, 0x82, 0xbe,
+ 0x47, 0x63, 0xd4, 0xfd, 0x0c, 0x25, 0xc4, 0xb1,
+ 0xfe, 0x29, 0x6f, 0x84, 0xfb, 0xab, 0x6e, 0xa7,
+ 0xf9, 0x22, 0x89, 0x97, 0x5b, 0x91, 0x0a, 0x07,
+ 0xe0, 0xef, 0x3d, 0x67, 0xee, 0x87, 0xa8, 0x33,
+ 0x02, 0x64, 0x33, 0xca, 0x15, 0x10, 0xb9, 0x57,
+ 0xd8, 0xe5, 0x1a, 0x4b, 0xe3, 0x45, 0xc1, 0x62,
+ 0x85, 0x50, 0xf1, 0x79, 0x54, 0xe1, 0x2e, 0x25,
+ 0x01, 0x3c, 0xdb, 0x2d, 0x39, 0x14, 0x2f, 0x9b,
+ 0xd0, 0x1d, 0xc1, 0xac, 0x73, 0x7d, 0xa4, 0xed,
+ 0x89, 0x98, 0xb1, 0xae, 0x8a, 0x9e, 0xc8, 0xa7,
+ 0xfe, 0x55, 0x27, 0xb5, 0xb5, 0xa2, 0xec, 0x7e,
+ 0xe3, 0x6b, 0x45, 0x19, 0xfa, 0x20, 0x1c, 0x33,
+ 0x83, 0x22, 0x33, 0x97, 0xd2, 0x5a, 0xc4, 0xf8,
+ 0x9a, 0x03, 0x13, 0x85, 0xf2, 0x2b, 0x04, 0x59,
+ 0x27, 0xd7, 0x0b, 0x42, 0x47, 0x9b, 0x7d, 0x4d,
+ 0xb2, 0x1a, 0x85, 0x7f, 0x97, 0xc2, 0xf2, 0x10,
+ 0xf0, 0xfa, 0x4e, 0x4b, 0x62, 0x43, 0x3a, 0x09,
+ 0x2e, 0xcd, 0x8f, 0xa8, 0xb6, 0x0b, 0x5f, 0x34,
+ 0xd7, 0x3b, 0xba, 0xd9, 0xe5, 0x01, 0x2d, 0x35,
+ 0xae, 0xc5, 0x4c, 0xab, 0x40, 0x64, 0xc2, 0xc9,
+ 0x8c, 0x69, 0x44, 0xf4, 0xb8, 0xb5, 0x3a, 0x05,
+ 0x3c, 0x29, 0x19, 0xb4, 0x09, 0x17, 0x03, 0x01,
+ 0x00, 0x20, 0xc8, 0xc5, 0xb7, 0xe3, 0xd2, 0x3e,
+ 0x27, 0xb5, 0x71, 0x8f, 0x52, 0x0b, 0xce, 0x17,
+ 0x64, 0x86, 0xa4, 0x34, 0x16, 0x1b, 0x61, 0x64,
+ 0x7c, 0xb3, 0xf2, 0xe5, 0x3e, 0xfd, 0xdd, 0xfb,
+ 0x40, 0x78, 0x17, 0x03, 0x01, 0x00, 0x50, 0x8e,
+ 0x79, 0xf0, 0x8e, 0x76, 0x5d, 0x34, 0x09, 0xdc,
+ 0xec, 0x6d, 0xc3, 0x43, 0x1d, 0xcb, 0x2d, 0xaa,
+ 0x08, 0x7a, 0x51, 0x94, 0x4e, 0xc5, 0x26, 0xe4,
+ 0x0b, 0x8e, 0x8f, 0x51, 0xf2, 0x9f, 0xeb, 0xc3,
+ 0x18, 0x43, 0x95, 0x15, 0xfc, 0x59, 0x18, 0x25,
+ 0x47, 0xb6, 0x4a, 0x6e, 0xa3, 0xa4, 0x3b, 0xa3,
+ 0x47, 0x34, 0x74, 0x6b, 0xc5, 0x3d, 0x41, 0x14,
+ 0x64, 0xd5, 0x69, 0x5f, 0x77, 0xf3, 0x7c, 0x41,
+ 0xc6, 0xed, 0x2e, 0xcf, 0xff, 0x40, 0xf2, 0xce,
+ 0xbb, 0xa7, 0x4e, 0x73, 0x88, 0x98, 0x10,
+ },
+ {
+ 0x15, 0x03, 0x01, 0x00, 0x20, 0x1a, 0xbc, 0x70,
+ 0x24, 0xf8, 0xfb, 0xf2, 0x4a, 0xf9, 0x44, 0x1e,
+ 0x58, 0xf8, 0xaa, 0x41, 0x24, 0xe8, 0x80, 0x33,
+ 0x45, 0x18, 0xa1, 0x5d, 0xee, 0x16, 0x80, 0xae,
+ 0x40, 0x41, 0x8e, 0x41, 0x9b,
+ },
+}
+
+var tls11ECDHEAESClientScript = [][]byte{
+ {
+ 0x16, 0x03, 0x01, 0x00, 0x4a, 0x01, 0x00, 0x00,
+ 0x46, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xc0, 0x13,
+ 0x01, 0x00, 0x00, 0x1b, 0x00, 0x05, 0x00, 0x05,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00,
+ 0x08, 0x00, 0x06, 0x00, 0x17, 0x00, 0x18, 0x00,
+ 0x19, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00,
+ },
+ {
+ 0x16, 0x03, 0x02, 0x00, 0x54, 0x02, 0x00, 0x00,
+ 0x50, 0x03, 0x02, 0x51, 0x9f, 0xa2, 0x21, 0x1a,
+ 0xb7, 0x75, 0x42, 0x69, 0xd3, 0x14, 0xdd, 0x05,
+ 0x1e, 0xda, 0x13, 0x71, 0x8d, 0x6a, 0x45, 0x97,
+ 0xcb, 0xee, 0x0e, 0x77, 0x01, 0x0d, 0x6e, 0xe5,
+ 0x22, 0x70, 0x16, 0x20, 0x69, 0xfc, 0xa6, 0x9a,
+ 0xe8, 0x21, 0xcc, 0x46, 0x65, 0x05, 0xb4, 0x48,
+ 0x0f, 0x34, 0x63, 0x2c, 0xac, 0xa4, 0xf5, 0x4b,
+ 0x64, 0xd1, 0x07, 0x13, 0xa7, 0xe4, 0x5b, 0xa3,
+ 0x4d, 0x31, 0x41, 0x53, 0xc0, 0x13, 0x00, 0x00,
+ 0x08, 0x00, 0x0b, 0x00, 0x04, 0x03, 0x00, 0x01,
+ 0x02, 0x16, 0x03, 0x02, 0x02, 0x39, 0x0b, 0x00,
+ 0x02, 0x35, 0x00, 0x02, 0x32, 0x00, 0x02, 0x2f,
+ 0x30, 0x82, 0x02, 0x2b, 0x30, 0x82, 0x01, 0xd5,
+ 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00,
+ 0xb1, 0x35, 0x13, 0x65, 0x11, 0x20, 0xc5, 0x92,
+ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+ 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30,
+ 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+ 0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13,
+ 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13,
+ 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74,
+ 0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06,
+ 0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e,
+ 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57,
+ 0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50,
+ 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e,
+ 0x17, 0x0d, 0x31, 0x32, 0x30, 0x34, 0x30, 0x36,
+ 0x31, 0x37, 0x31, 0x30, 0x31, 0x33, 0x5a, 0x17,
+ 0x0d, 0x31, 0x35, 0x30, 0x34, 0x30, 0x36, 0x31,
+ 0x37, 0x31, 0x30, 0x31, 0x33, 0x5a, 0x30, 0x45,
+ 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
+ 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30,
+ 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a,
+ 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61,
+ 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03,
+ 0x55, 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74,
+ 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69,
+ 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74,
+ 0x79, 0x20, 0x4c, 0x74, 0x64, 0x30, 0x5c, 0x30,
+ 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b,
+ 0x00, 0x30, 0x48, 0x02, 0x41, 0x00, 0x9f, 0xb3,
+ 0xc3, 0x84, 0x27, 0x95, 0xff, 0x12, 0x31, 0x52,
+ 0x0f, 0x15, 0xef, 0x46, 0x11, 0xc4, 0xad, 0x80,
+ 0xe6, 0x36, 0x5b, 0x0f, 0xdd, 0x80, 0xd7, 0x61,
+ 0x8d, 0xe0, 0xfc, 0x72, 0x45, 0x09, 0x34, 0xfe,
+ 0x55, 0x66, 0x45, 0x43, 0x4c, 0x68, 0x97, 0x6a,
+ 0xfe, 0xa8, 0xa0, 0xa5, 0xdf, 0x5f, 0x78, 0xff,
+ 0xee, 0xd7, 0x64, 0xb8, 0x3f, 0x04, 0xcb, 0x6f,
+ 0xff, 0x2a, 0xfe, 0xfe, 0xb9, 0xed, 0x02, 0x03,
+ 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7, 0x30, 0x81,
+ 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e,
+ 0x04, 0x16, 0x04, 0x14, 0x78, 0xa6, 0x97, 0x9a,
+ 0x63, 0xb5, 0xc5, 0xa1, 0xa5, 0x33, 0xba, 0x22,
+ 0x7c, 0x23, 0x6e, 0x5b, 0x1b, 0x7a, 0xcc, 0x2b,
+ 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04,
+ 0x6e, 0x30, 0x6c, 0x80, 0x14, 0x78, 0xa6, 0x97,
+ 0x9a, 0x63, 0xb5, 0xc5, 0xa1, 0xa5, 0x33, 0xba,
+ 0x22, 0x7c, 0x23, 0x6e, 0x5b, 0x1b, 0x7a, 0xcc,
+ 0x2b, 0xa1, 0x49, 0xa4, 0x47, 0x30, 0x45, 0x31,
+ 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+ 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11,
+ 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53,
+ 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74,
+ 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55,
+ 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65,
+ 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64,
+ 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79,
+ 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09, 0x00, 0xb1,
+ 0x35, 0x13, 0x65, 0x11, 0x20, 0xc5, 0x92, 0x30,
+ 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05,
+ 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06,
+ 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
+ 0x01, 0x05, 0x05, 0x00, 0x03, 0x41, 0x00, 0x85,
+ 0x36, 0x40, 0x73, 0xc1, 0xbb, 0x1a, 0xda, 0xd4,
+ 0x59, 0x9f, 0x2d, 0xa2, 0x70, 0x31, 0x46, 0x74,
+ 0xec, 0x83, 0x6e, 0xa8, 0xc8, 0x3c, 0x51, 0xaf,
+ 0x39, 0xac, 0xec, 0x40, 0xbc, 0xe8, 0x22, 0x46,
+ 0x1d, 0x99, 0xd6, 0x46, 0x2a, 0x24, 0xd4, 0x8b,
+ 0x05, 0x08, 0x4b, 0xfb, 0x35, 0x11, 0x6e, 0x92,
+ 0xbb, 0x77, 0xba, 0xe4, 0x12, 0xbb, 0xf4, 0xc8,
+ 0x5e, 0x9c, 0x81, 0xa8, 0x97, 0x60, 0x4c, 0x16,
+ 0x03, 0x02, 0x00, 0x8b, 0x0c, 0x00, 0x00, 0x87,
+ 0x03, 0x00, 0x17, 0x41, 0x04, 0x34, 0xde, 0x50,
+ 0x32, 0x8f, 0x25, 0x6b, 0x37, 0x2c, 0x36, 0x24,
+ 0x27, 0x0e, 0xf9, 0x67, 0xb4, 0xf8, 0x29, 0x1c,
+ 0xa5, 0xa4, 0x59, 0x9a, 0xca, 0x40, 0x26, 0x15,
+ 0x61, 0x72, 0x34, 0x4a, 0xd3, 0x0c, 0xac, 0x69,
+ 0xcb, 0x2a, 0x9e, 0xf8, 0x80, 0xfb, 0x7a, 0xc4,
+ 0xd4, 0x4b, 0x91, 0x1b, 0xbe, 0x24, 0x26, 0xad,
+ 0x19, 0x24, 0xbe, 0x32, 0x58, 0xfb, 0xc7, 0x77,
+ 0xce, 0x7e, 0x71, 0x51, 0x1a, 0x00, 0x40, 0x1a,
+ 0x0b, 0xe8, 0x91, 0x84, 0x64, 0x54, 0xb6, 0x19,
+ 0xe8, 0xd4, 0x43, 0x7c, 0x09, 0x0c, 0x2e, 0xba,
+ 0x42, 0xb9, 0x74, 0xc3, 0x6c, 0x06, 0x9b, 0xa6,
+ 0x7e, 0x92, 0xe9, 0xee, 0x7c, 0x74, 0xa9, 0xd3,
+ 0x63, 0xf0, 0x16, 0x20, 0x60, 0x71, 0x8e, 0x24,
+ 0xc7, 0x7f, 0xc5, 0x5b, 0x9c, 0x19, 0x0c, 0x80,
+ 0x15, 0x61, 0xbf, 0xb6, 0xed, 0x5b, 0x7b, 0x90,
+ 0xc5, 0x05, 0x13, 0x72, 0x45, 0x79, 0xdf, 0x16,
+ 0x03, 0x02, 0x00, 0x04, 0x0e, 0x00, 0x00, 0x00,
+ },
+ {
+ 0x16, 0x03, 0x02, 0x00, 0x46, 0x10, 0x00, 0x00,
+ 0x42, 0x41, 0x04, 0x1e, 0x18, 0x37, 0xef, 0x0d,
+ 0x19, 0x51, 0x88, 0x35, 0x75, 0x71, 0xb5, 0xe5,
+ 0x54, 0x5b, 0x12, 0x2e, 0x8f, 0x09, 0x67, 0xfd,
+ 0xa7, 0x24, 0x20, 0x3e, 0xb2, 0x56, 0x1c, 0xce,
+ 0x97, 0x28, 0x5e, 0xf8, 0x2b, 0x2d, 0x4f, 0x9e,
+ 0xf1, 0x07, 0x9f, 0x6c, 0x4b, 0x5b, 0x83, 0x56,
+ 0xe2, 0x32, 0x42, 0xe9, 0x58, 0xb6, 0xd7, 0x49,
+ 0xa6, 0xb5, 0x68, 0x1a, 0x41, 0x03, 0x56, 0x6b,
+ 0xdc, 0x5a, 0x89, 0x14, 0x03, 0x02, 0x00, 0x01,
+ 0x01, 0x16, 0x03, 0x02, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x50,
+ 0x32, 0x26, 0x51, 0xbd, 0xbd, 0x3c, 0x4f, 0x72,
+ 0xbf, 0xbc, 0x91, 0x70, 0x4b, 0x5d, 0x43, 0x4a,
+ 0x65, 0x26, 0x0d, 0xaa, 0xed, 0x00, 0x91, 0xaf,
+ 0x4f, 0x47, 0x09, 0xaa, 0x79, 0xc4, 0x47, 0x21,
+ 0x71, 0xd8, 0x2b, 0xc1, 0x51, 0xc8, 0xef, 0xed,
+ 0x67, 0xde, 0x97, 0xef, 0x18, 0x53,
+ },
+ {
+ 0x14, 0x03, 0x02, 0x00, 0x01, 0x01, 0x16, 0x03,
+ 0x02, 0x00, 0x40, 0x72, 0x20, 0xbf, 0xd1, 0xbd,
+ 0x83, 0x53, 0x57, 0xb0, 0x4e, 0xac, 0xba, 0x1a,
+ 0x2b, 0x2d, 0xeb, 0x8a, 0x48, 0x17, 0xfa, 0x69,
+ 0xf9, 0xb5, 0x94, 0x8e, 0x6f, 0x9c, 0xda, 0x59,
+ 0xba, 0x6c, 0x7c, 0x82, 0xe2, 0x53, 0xa9, 0x46,
+ 0xdc, 0x33, 0xa0, 0x9b, 0xf0, 0x1e, 0xf1, 0x53,
+ 0x83, 0x48, 0xbf, 0x5e, 0xef, 0x03, 0x2b, 0x50,
+ 0x7a, 0xa6, 0xf8, 0xc3, 0x9e, 0x24, 0x43, 0x3a,
+ 0xdf, 0x44, 0x3e,
+ },
+ {
+ 0x17, 0x03, 0x02, 0x00, 0x30, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x0b, 0x8f,
+ 0x6b, 0xf9, 0xd3, 0x9f, 0x2b, 0x49, 0xe0, 0x62,
+ 0x9a, 0x0b, 0x3e, 0xa2, 0x72, 0x8b, 0x96, 0x0c,
+ 0x41, 0x09, 0x95, 0x9e, 0x6b, 0x26, 0xa1, 0x46,
+ 0xca, 0xb8, 0xb6, 0xd2, 0xd4, 0x15, 0x03, 0x02,
+ 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xa0, 0xd4, 0x84, 0xc6, 0x7e, 0x1c,
+ 0x2f, 0xbd, 0x6b, 0x45, 0x31, 0x1d, 0x7d, 0x8f,
+ 0x31, 0x39, 0x5a, 0x4e, 0xaa, 0xf1, 0x0a, 0x8a,
+ 0x6c, 0x33, 0x59, 0x19, 0xd8, 0x75, 0x80, 0xab,
+ 0x93, 0x81,
+ },
+}
+
+var clientChainCertificateScript = [][]byte{
+ {
+ 0x16, 0x03, 0x01, 0x00, 0x4a, 0x01, 0x00, 0x00,
+ 0x46, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x05,
+ 0x01, 0x00, 0x00, 0x1b, 0x00, 0x05, 0x00, 0x05,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00,
+ 0x08, 0x00, 0x06, 0x00, 0x17, 0x00, 0x18, 0x00,
+ 0x19, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00,
+ },
+ {
+ 0x16, 0x03, 0x01, 0x00, 0x4a, 0x02, 0x00, 0x00,
+ 0x46, 0x03, 0x01, 0x51, 0xa2, 0x9b, 0x8b, 0xd4,
+ 0xe6, 0x33, 0xa2, 0x70, 0x38, 0x37, 0xba, 0x55,
+ 0x86, 0xcf, 0x87, 0xea, 0x6d, 0x2c, 0x3e, 0x17,
+ 0xc2, 0x09, 0xf8, 0x4d, 0xb0, 0x5d, 0x93, 0x2b,
+ 0x15, 0x99, 0x0c, 0x20, 0x5d, 0x61, 0x21, 0x2c,
+ 0xed, 0x49, 0x32, 0x29, 0x08, 0x6e, 0x21, 0x58,
+ 0x00, 0xdb, 0x34, 0xb7, 0x37, 0xcd, 0x27, 0x75,
+ 0x31, 0x1e, 0x6c, 0x74, 0xa6, 0xef, 0xa2, 0xc4,
+ 0x2b, 0x6c, 0xc3, 0x03, 0x00, 0x05, 0x00, 0x16,
+ 0x03, 0x01, 0x03, 0xef, 0x0b, 0x00, 0x03, 0xeb,
+ 0x00, 0x03, 0xe8, 0x00, 0x03, 0xe5, 0x30, 0x82,
+ 0x03, 0xe1, 0x30, 0x82, 0x02, 0xc9, 0xa0, 0x03,
+ 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0xcc, 0x22,
+ 0x4c, 0x4b, 0x98, 0xa2, 0x88, 0xfc, 0x30, 0x0d,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81, 0x86,
+ 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
+ 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30,
+ 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02,
+ 0x4e, 0x59, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03,
+ 0x55, 0x04, 0x07, 0x0c, 0x08, 0x42, 0x72, 0x6f,
+ 0x6f, 0x6b, 0x6c, 0x79, 0x6e, 0x31, 0x21, 0x30,
+ 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x18,
+ 0x4d, 0x79, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69,
+ 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41,
+ 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79,
+ 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04,
+ 0x03, 0x0c, 0x08, 0x6d, 0x79, 0x63, 0x61, 0x2e,
+ 0x6f, 0x72, 0x67, 0x31, 0x21, 0x30, 0x1f, 0x06,
+ 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
+ 0x09, 0x01, 0x16, 0x12, 0x6a, 0x76, 0x73, 0x68,
+ 0x61, 0x68, 0x69, 0x64, 0x40, 0x67, 0x6d, 0x61,
+ 0x69, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e,
+ 0x17, 0x0d, 0x31, 0x33, 0x30, 0x35, 0x32, 0x36,
+ 0x32, 0x31, 0x30, 0x35, 0x30, 0x31, 0x5a, 0x17,
+ 0x0d, 0x32, 0x33, 0x30, 0x35, 0x32, 0x34, 0x32,
+ 0x31, 0x30, 0x35, 0x30, 0x31, 0x5a, 0x30, 0x81,
+ 0x86, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+ 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b,
+ 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c,
+ 0x02, 0x4e, 0x59, 0x31, 0x11, 0x30, 0x0f, 0x06,
+ 0x03, 0x55, 0x04, 0x07, 0x0c, 0x08, 0x42, 0x72,
+ 0x6f, 0x6f, 0x6b, 0x6c, 0x79, 0x6e, 0x31, 0x21,
+ 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c,
+ 0x18, 0x4d, 0x79, 0x20, 0x43, 0x65, 0x72, 0x74,
+ 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20,
+ 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74,
+ 0x79, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55,
+ 0x04, 0x03, 0x0c, 0x08, 0x6d, 0x79, 0x63, 0x61,
+ 0x2e, 0x6f, 0x72, 0x67, 0x31, 0x21, 0x30, 0x1f,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x09, 0x01, 0x16, 0x12, 0x6a, 0x76, 0x73,
+ 0x68, 0x61, 0x68, 0x69, 0x64, 0x40, 0x67, 0x6d,
+ 0x61, 0x69, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x30,
+ 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01,
+ 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30,
+ 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00,
+ 0xf0, 0xfb, 0xad, 0x80, 0x5e, 0x37, 0xd3, 0x6d,
+ 0xee, 0x2e, 0xcc, 0xbc, 0x0c, 0xd7, 0x56, 0x4b,
+ 0x56, 0x45, 0xcd, 0x28, 0xb6, 0x22, 0xe9, 0xe2,
+ 0x0f, 0xd1, 0x87, 0x2a, 0x27, 0xce, 0x77, 0x8d,
+ 0x6e, 0x0e, 0x0f, 0xfb, 0x66, 0xe1, 0xb5, 0x0e,
+ 0x9a, 0xb6, 0x05, 0x8e, 0xb3, 0xe1, 0xc5, 0x77,
+ 0x86, 0x5b, 0x46, 0xd2, 0x0b, 0x92, 0x03, 0x1b,
+ 0x89, 0x0c, 0x1b, 0x10, 0x0e, 0x99, 0x8f, 0xe2,
+ 0x17, 0xe8, 0xc2, 0x30, 0x00, 0x47, 0xd6, 0xfc,
+ 0xf9, 0x0f, 0x3b, 0x75, 0x34, 0x8d, 0x4d, 0xb0,
+ 0x99, 0xb7, 0xa0, 0x6d, 0xa0, 0xb6, 0xad, 0xda,
+ 0x07, 0x5e, 0x38, 0x2e, 0x02, 0xe4, 0x30, 0x6d,
+ 0xae, 0x13, 0x72, 0xd4, 0xc8, 0xce, 0x14, 0x07,
+ 0xae, 0x23, 0x8c, 0x8f, 0x9e, 0x8c, 0x60, 0xd6,
+ 0x06, 0xb9, 0xef, 0x00, 0x18, 0xc0, 0x1d, 0x25,
+ 0x1e, 0xda, 0x3e, 0x2f, 0xcf, 0x2b, 0x56, 0x84,
+ 0x9e, 0x30, 0x21, 0xc7, 0x29, 0xf6, 0x03, 0x8a,
+ 0x24, 0xf9, 0x34, 0xac, 0x65, 0x9d, 0x80, 0x36,
+ 0xc8, 0x3b, 0x15, 0x10, 0xbd, 0x51, 0xe9, 0xbc,
+ 0x02, 0xe1, 0xe9, 0xb3, 0x5a, 0x9a, 0x99, 0x41,
+ 0x1b, 0x27, 0xa0, 0x4d, 0x50, 0x9e, 0x27, 0x7f,
+ 0xa1, 0x7d, 0x09, 0x87, 0xbd, 0x8a, 0xca, 0x5f,
+ 0xb1, 0xa5, 0x08, 0xb8, 0x04, 0xd4, 0x52, 0x89,
+ 0xaa, 0xe0, 0x7d, 0x42, 0x2e, 0x2f, 0x15, 0xee,
+ 0x66, 0x57, 0x0f, 0x13, 0x19, 0x45, 0xa8, 0x4b,
+ 0x5d, 0x81, 0x66, 0xcc, 0x12, 0x37, 0x94, 0x5e,
+ 0xfd, 0x3c, 0x10, 0x81, 0x51, 0x3f, 0xfa, 0x0f,
+ 0xdd, 0xa1, 0x89, 0x03, 0xa9, 0x78, 0x91, 0xf5,
+ 0x3b, 0xf3, 0xbc, 0xac, 0xbe, 0x93, 0x30, 0x2e,
+ 0xbe, 0xca, 0x7f, 0x46, 0xd3, 0x28, 0xb4, 0x4e,
+ 0x91, 0x7b, 0x5b, 0x43, 0x6c, 0xaf, 0x9b, 0x5c,
+ 0x6a, 0x6d, 0x5a, 0xdb, 0x79, 0x5e, 0x6a, 0x6b,
+ 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x50, 0x30,
+ 0x4e, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e,
+ 0x04, 0x16, 0x04, 0x14, 0x6b, 0x1e, 0x00, 0xa8,
+ 0x9f, 0xfa, 0x7d, 0x00, 0xf9, 0xe0, 0x9d, 0x0f,
+ 0x90, 0x8c, 0x90, 0xa8, 0xa1, 0x37, 0x6b, 0xda,
+ 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04,
+ 0x18, 0x30, 0x16, 0x80, 0x14, 0x6b, 0x1e, 0x00,
+ 0xa8, 0x9f, 0xfa, 0x7d, 0x00, 0xf9, 0xe0, 0x9d,
+ 0x0f, 0x90, 0x8c, 0x90, 0xa8, 0xa1, 0x37, 0x6b,
+ 0xda, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13,
+ 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30,
+ 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82,
+ 0x01, 0x01, 0x00, 0xcd, 0x6f, 0x73, 0x4d, 0x56,
+ 0x0b, 0xf3, 0x2e, 0x1c, 0xe2, 0x02, 0x0c, 0x14,
+ 0xbb, 0x2f, 0xdd, 0x3c, 0x43, 0xfe, 0xdf, 0x94,
+ 0x2d, 0xa9, 0x89, 0x81, 0x51, 0xf8, 0x5f, 0xa7,
+ 0xa0, 0x13, 0xaa, 0xcc, 0xb0, 0x18, 0xe2, 0x57,
+ 0x3e, 0x0d, 0x29, 0x93, 0xe8, 0x95, 0xd5, 0x1b,
+ 0x53, 0xd2, 0x51, 0xf2, 0xbd, 0xf5, 0x9e, 0x7b,
+ 0x22, 0x65, 0x62, 0x5c, 0xc4, 0x4c, 0x1d, 0xe8,
+ 0xe9, 0xc3, 0xd4, 0x2b, 0xe7, 0x78, 0xcb, 0x10,
+ 0xf3, 0xfe, 0x06, 0x83, 0xdc, 0x3a, 0x1e, 0x62,
+ 0x10, 0xc0, 0x46, 0x77, 0xc6, 0x9d, 0x9f, 0xab,
+ 0x96, 0x25, 0x5c, 0xfb, 0x26, 0xc1, 0x15, 0x1f,
+ 0xa5, 0x33, 0xee, 0x4f, 0x9a, 0x14, 0x6a, 0x14,
+ 0x97, 0x93, 0x2b, 0x95, 0x0b, 0xdc, 0xa8, 0xd7,
+ 0x69, 0x2e, 0xf0, 0x01, 0x0e, 0xfd, 0x4e, 0xd0,
+ 0xd9, 0xa8, 0xe5, 0x65, 0xde, 0xfb, 0xca, 0xca,
+ 0x1c, 0x5f, 0xf9, 0x53, 0xa0, 0x87, 0xe7, 0x33,
+ 0x9b, 0x2f, 0xcf, 0xe4, 0x13, 0xfc, 0xec, 0x7a,
+ 0x6c, 0xb0, 0x90, 0x13, 0x9b, 0xb6, 0xc5, 0x03,
+ 0xf6, 0x0e, 0x5e, 0xe2, 0xe4, 0x26, 0xc1, 0x7e,
+ 0x53, 0xfe, 0x69, 0xa3, 0xc7, 0xd8, 0x8e, 0x6e,
+ 0x94, 0x32, 0xa0, 0xde, 0xca, 0xb6, 0xcc, 0xd6,
+ 0x01, 0xd5, 0x78, 0x40, 0x28, 0x63, 0x9b, 0xee,
+ 0xcf, 0x09, 0x3b, 0x35, 0x04, 0xf0, 0x14, 0x02,
+ 0xf6, 0x80, 0x0e, 0x90, 0xb2, 0x94, 0xd2, 0x25,
+ 0x16, 0xb8, 0x7a, 0x76, 0x87, 0x84, 0x9f, 0x84,
+ 0xc5, 0xaf, 0xc2, 0x6d, 0x68, 0x7a, 0x84, 0x9c,
+ 0xc6, 0x8a, 0x63, 0x60, 0x87, 0x6a, 0x25, 0xc1,
+ 0xa1, 0x78, 0x0f, 0xba, 0xe8, 0x5f, 0xe1, 0xba,
+ 0xac, 0xa4, 0x6f, 0xdd, 0x09, 0x3f, 0x12, 0xcb,
+ 0x1d, 0xf3, 0xcf, 0x48, 0xd7, 0xd3, 0x26, 0xe8,
+ 0x9c, 0xc3, 0x53, 0xb3, 0xba, 0xdc, 0x32, 0x99,
+ 0x98, 0x96, 0xd6, 0x16, 0x03, 0x01, 0x00, 0x99,
+ 0x0d, 0x00, 0x00, 0x91, 0x03, 0x01, 0x02, 0x40,
+ 0x00, 0x8b, 0x00, 0x89, 0x30, 0x81, 0x86, 0x31,
+ 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+ 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09,
+ 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02, 0x4e,
+ 0x59, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55,
+ 0x04, 0x07, 0x0c, 0x08, 0x42, 0x72, 0x6f, 0x6f,
+ 0x6b, 0x6c, 0x79, 0x6e, 0x31, 0x21, 0x30, 0x1f,
+ 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x18, 0x4d,
+ 0x79, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66,
+ 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75,
+ 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31,
+ 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x03,
+ 0x0c, 0x08, 0x6d, 0x79, 0x63, 0x61, 0x2e, 0x6f,
+ 0x72, 0x67, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09,
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09,
+ 0x01, 0x16, 0x12, 0x6a, 0x76, 0x73, 0x68, 0x61,
+ 0x68, 0x69, 0x64, 0x40, 0x67, 0x6d, 0x61, 0x69,
+ 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x0e, 0x00, 0x00,
+ 0x00,
+ },
+ {
+ 0x16, 0x03, 0x01, 0x0a, 0xfb, 0x0b, 0x00, 0x0a,
+ 0xf7, 0x00, 0x0a, 0xf4, 0x00, 0x03, 0x7e, 0x30,
+ 0x82, 0x03, 0x7a, 0x30, 0x82, 0x02, 0x62, 0x02,
+ 0x09, 0x00, 0xb4, 0x47, 0x58, 0x57, 0x2b, 0x67,
+ 0xc8, 0xc2, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
+ 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05,
+ 0x00, 0x30, 0x81, 0x80, 0x31, 0x0b, 0x30, 0x09,
+ 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55,
+ 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+ 0x04, 0x08, 0x0c, 0x02, 0x4e, 0x59, 0x31, 0x11,
+ 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c,
+ 0x08, 0x42, 0x72, 0x6f, 0x6f, 0x6b, 0x6c, 0x79,
+ 0x6e, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55,
+ 0x04, 0x0a, 0x0c, 0x0c, 0x4d, 0x79, 0x20, 0x43,
+ 0x41, 0x20, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74,
+ 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04,
+ 0x03, 0x0c, 0x0e, 0x6d, 0x79, 0x63, 0x61, 0x63,
+ 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x63, 0x6f,
+ 0x6d, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01,
+ 0x16, 0x12, 0x6a, 0x76, 0x73, 0x68, 0x61, 0x68,
+ 0x69, 0x64, 0x40, 0x67, 0x6d, 0x61, 0x69, 0x6c,
+ 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d,
+ 0x31, 0x33, 0x30, 0x35, 0x32, 0x36, 0x32, 0x31,
+ 0x34, 0x34, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x31,
+ 0x33, 0x30, 0x36, 0x32, 0x35, 0x32, 0x31, 0x34,
+ 0x34, 0x30, 0x30, 0x5a, 0x30, 0x7d, 0x31, 0x0b,
+ 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
+ 0x02, 0x55, 0x53, 0x31, 0x11, 0x30, 0x0f, 0x06,
+ 0x03, 0x55, 0x04, 0x08, 0x0c, 0x08, 0x4e, 0x65,
+ 0x77, 0x20, 0x59, 0x6f, 0x72, 0x6b, 0x31, 0x11,
+ 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c,
+ 0x08, 0x42, 0x72, 0x6f, 0x6f, 0x6b, 0x6c, 0x79,
+ 0x6e, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55,
+ 0x04, 0x0a, 0x0c, 0x07, 0x4d, 0x79, 0x20, 0x4c,
+ 0x65, 0x61, 0x66, 0x31, 0x13, 0x30, 0x11, 0x06,
+ 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0a, 0x6d, 0x79,
+ 0x6c, 0x65, 0x61, 0x66, 0x2e, 0x63, 0x6f, 0x6d,
+ 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a, 0x86,
+ 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16,
+ 0x12, 0x6a, 0x76, 0x73, 0x68, 0x61, 0x68, 0x69,
+ 0x64, 0x40, 0x67, 0x6d, 0x61, 0x69, 0x6c, 0x2e,
+ 0x63, 0x6f, 0x6d, 0x30, 0x82, 0x01, 0x22, 0x30,
+ 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82,
+ 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02,
+ 0x82, 0x01, 0x01, 0x00, 0xa0, 0xa3, 0xef, 0xc1,
+ 0x44, 0x7d, 0xa2, 0xe3, 0x71, 0x98, 0x27, 0x63,
+ 0xb3, 0x1d, 0x71, 0x50, 0xa6, 0x34, 0x15, 0xcb,
+ 0xc9, 0x2a, 0xc3, 0xea, 0xe4, 0x9e, 0x9c, 0x49,
+ 0xa6, 0x01, 0x9b, 0x7e, 0xa9, 0xb5, 0x7a, 0xff,
+ 0x15, 0x92, 0x71, 0xc8, 0x97, 0x9c, 0x25, 0xb7,
+ 0x79, 0x2b, 0xff, 0xab, 0xc6, 0xb1, 0xa7, 0x00,
+ 0x90, 0xb2, 0x8b, 0xd7, 0x71, 0xd5, 0xc2, 0x3a,
+ 0xe6, 0x82, 0x42, 0x37, 0x89, 0x41, 0x04, 0xb0,
+ 0xba, 0xc7, 0x5b, 0x8a, 0x43, 0x9f, 0x97, 0x39,
+ 0x0c, 0x0f, 0xd5, 0x6d, 0x9e, 0x8d, 0xeb, 0xc0,
+ 0x26, 0xc5, 0x18, 0xe8, 0x7a, 0x3d, 0x32, 0x2e,
+ 0x38, 0x90, 0x40, 0x5b, 0x39, 0x2c, 0x07, 0xcb,
+ 0x24, 0x10, 0xc5, 0xc9, 0x3b, 0xe3, 0x66, 0x47,
+ 0x57, 0xb9, 0x6a, 0xad, 0x44, 0xf8, 0xd0, 0x70,
+ 0x62, 0x3b, 0x8e, 0xed, 0x60, 0x5f, 0x22, 0xf8,
+ 0xb8, 0x0c, 0xc9, 0x41, 0x2b, 0xc9, 0x80, 0x6e,
+ 0x4e, 0x1b, 0xe1, 0x20, 0xfc, 0x47, 0xa4, 0xac,
+ 0xc3, 0x3f, 0xe6, 0xc2, 0x81, 0x79, 0x03, 0x37,
+ 0x25, 0x89, 0xca, 0xd6, 0xa5, 0x46, 0x91, 0x63,
+ 0x41, 0xc5, 0x3e, 0xd5, 0xed, 0x7f, 0x4f, 0x8d,
+ 0x06, 0xc0, 0x89, 0x00, 0xbe, 0x37, 0x7b, 0x7e,
+ 0x73, 0xca, 0x70, 0x00, 0x14, 0x34, 0xbe, 0x47,
+ 0xbc, 0xb2, 0x6a, 0x28, 0xa5, 0x29, 0x84, 0xa8,
+ 0x9d, 0xc8, 0x1e, 0x77, 0x66, 0x1f, 0x9f, 0xaa,
+ 0x2b, 0x47, 0xdb, 0xdd, 0x6b, 0x9c, 0xa8, 0xfc,
+ 0x82, 0x36, 0x94, 0x62, 0x0d, 0x5c, 0x3f, 0xb2,
+ 0x01, 0xb4, 0xa5, 0xb8, 0xc6, 0x0e, 0x94, 0x5b,
+ 0xec, 0x5e, 0xbb, 0x7a, 0x63, 0x24, 0xf1, 0xf9,
+ 0xd6, 0x50, 0x08, 0xc1, 0xa3, 0xcc, 0x90, 0x07,
+ 0x5b, 0x04, 0x04, 0x42, 0x74, 0xcf, 0x37, 0xfa,
+ 0xf0, 0xa5, 0xd9, 0xd3, 0x86, 0x89, 0x89, 0x18,
+ 0xf3, 0x4c, 0xe2, 0x11, 0x02, 0x03, 0x01, 0x00,
+ 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48,
+ 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00,
+ 0x03, 0x82, 0x01, 0x01, 0x00, 0x90, 0xbb, 0xf9,
+ 0x5e, 0xba, 0x17, 0x1f, 0xac, 0x21, 0x9f, 0x6b,
+ 0x4a, 0x46, 0xd0, 0x6d, 0x3c, 0x8f, 0x3d, 0xf8,
+ 0x5e, 0x3e, 0x72, 0xaf, 0xa0, 0x1a, 0xf3, 0xff,
+ 0x89, 0xac, 0x5b, 0x7a, 0xe2, 0x91, 0x2a, 0x23,
+ 0x85, 0xc6, 0x4d, 0x47, 0x67, 0x01, 0x08, 0xa8,
+ 0x05, 0x1d, 0x01, 0x60, 0x50, 0x5f, 0x59, 0xad,
+ 0xfe, 0x7b, 0xc6, 0x0c, 0x54, 0x90, 0x68, 0x70,
+ 0x67, 0x2e, 0xed, 0x87, 0xf8, 0x69, 0x8a, 0xac,
+ 0x32, 0xfe, 0x6f, 0x90, 0x19, 0x2a, 0x64, 0x8d,
+ 0x82, 0x66, 0x05, 0x43, 0x88, 0xee, 0xf2, 0x30,
+ 0xed, 0xa4, 0x8f, 0xbf, 0xd6, 0x57, 0x20, 0xd4,
+ 0x43, 0x1d, 0x52, 0x96, 0x6f, 0xae, 0x09, 0x96,
+ 0x01, 0x52, 0x38, 0xe3, 0xaf, 0x99, 0xd7, 0xdc,
+ 0x14, 0x99, 0xc4, 0x8b, 0x0e, 0x04, 0x0f, 0xb3,
+ 0x14, 0x14, 0xd4, 0xa5, 0x93, 0xe1, 0xc9, 0x8a,
+ 0x81, 0xef, 0x63, 0xfc, 0x36, 0x77, 0x05, 0x06,
+ 0xf0, 0x2a, 0x04, 0x0a, 0xbe, 0x2e, 0xce, 0x81,
+ 0x3d, 0x23, 0xa1, 0xda, 0xd8, 0xeb, 0xc6, 0xea,
+ 0x5e, 0xcf, 0x28, 0x36, 0x51, 0x31, 0x95, 0x5e,
+ 0x40, 0x04, 0xed, 0xac, 0xc1, 0xc8, 0x56, 0x69,
+ 0x87, 0xec, 0x3b, 0x03, 0x3e, 0x9d, 0x0f, 0x4c,
+ 0x4c, 0xeb, 0xd7, 0xba, 0x26, 0xdf, 0xe3, 0xde,
+ 0x10, 0xee, 0x93, 0x62, 0x8d, 0x73, 0x52, 0x6e,
+ 0xff, 0x37, 0x36, 0x98, 0x7b, 0x2d, 0x56, 0x4c,
+ 0xba, 0x09, 0xb8, 0xa7, 0xf0, 0x3b, 0x16, 0x81,
+ 0xca, 0xdb, 0x43, 0xab, 0xec, 0x4c, 0x6e, 0x7c,
+ 0xc1, 0x0b, 0x22, 0x22, 0x43, 0x1d, 0xb6, 0x0c,
+ 0xc1, 0xb9, 0xcf, 0xe4, 0x53, 0xee, 0x1d, 0x3e,
+ 0x88, 0xa7, 0x13, 0xbe, 0x7f, 0xbd, 0xae, 0x72,
+ 0xcf, 0xcd, 0x63, 0xd2, 0xc3, 0x18, 0x58, 0x92,
+ 0xa2, 0xad, 0xb5, 0x09, 0x9d, 0x91, 0x03, 0xdd,
+ 0x3c, 0xe2, 0x1c, 0xde, 0x78, 0x00, 0x03, 0x88,
+ 0x30, 0x82, 0x03, 0x84, 0x30, 0x82, 0x02, 0x6c,
+ 0x02, 0x09, 0x00, 0xab, 0xed, 0xa6, 0xe4, 0x4a,
+ 0x2b, 0x2b, 0xf8, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05,
+ 0x05, 0x00, 0x30, 0x81, 0x86, 0x31, 0x0b, 0x30,
+ 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+ 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
+ 0x55, 0x04, 0x08, 0x0c, 0x02, 0x4e, 0x59, 0x31,
+ 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x07,
+ 0x0c, 0x08, 0x42, 0x72, 0x6f, 0x6f, 0x6b, 0x6c,
+ 0x79, 0x6e, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03,
+ 0x55, 0x04, 0x0a, 0x0c, 0x18, 0x4d, 0x79, 0x20,
+ 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63,
+ 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68,
+ 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x11, 0x30,
+ 0x0f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x08,
+ 0x6d, 0x79, 0x63, 0x61, 0x2e, 0x6f, 0x72, 0x67,
+ 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a, 0x86,
+ 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16,
+ 0x12, 0x6a, 0x76, 0x73, 0x68, 0x61, 0x68, 0x69,
+ 0x64, 0x40, 0x67, 0x6d, 0x61, 0x69, 0x6c, 0x2e,
+ 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x31,
+ 0x33, 0x30, 0x35, 0x32, 0x36, 0x32, 0x31, 0x31,
+ 0x38, 0x34, 0x30, 0x5a, 0x17, 0x0d, 0x31, 0x33,
+ 0x30, 0x36, 0x32, 0x35, 0x32, 0x31, 0x31, 0x38,
+ 0x34, 0x30, 0x5a, 0x30, 0x81, 0x80, 0x31, 0x0b,
+ 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
+ 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06,
+ 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02, 0x4e, 0x59,
+ 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04,
+ 0x07, 0x0c, 0x08, 0x42, 0x72, 0x6f, 0x6f, 0x6b,
+ 0x6c, 0x79, 0x6e, 0x31, 0x15, 0x30, 0x13, 0x06,
+ 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0c, 0x4d, 0x79,
+ 0x20, 0x43, 0x41, 0x20, 0x43, 0x6c, 0x69, 0x65,
+ 0x6e, 0x74, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03,
+ 0x55, 0x04, 0x03, 0x0c, 0x0e, 0x6d, 0x79, 0x63,
+ 0x61, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e,
+ 0x63, 0x6f, 0x6d, 0x31, 0x21, 0x30, 0x1f, 0x06,
+ 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
+ 0x09, 0x01, 0x16, 0x12, 0x6a, 0x76, 0x73, 0x68,
+ 0x61, 0x68, 0x69, 0x64, 0x40, 0x67, 0x6d, 0x61,
+ 0x69, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x82,
+ 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
+ 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05,
+ 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82,
+ 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xce,
+ 0x13, 0xf0, 0x72, 0xb0, 0x61, 0xc8, 0x18, 0x37,
+ 0x8a, 0x41, 0x3d, 0x20, 0xa1, 0x1c, 0xcb, 0xbf,
+ 0xf6, 0x3b, 0x74, 0x26, 0x2a, 0x96, 0x11, 0xec,
+ 0x53, 0xa1, 0xcc, 0x7d, 0x77, 0x56, 0x45, 0x0f,
+ 0x36, 0xb7, 0xf2, 0x48, 0x92, 0x1a, 0x62, 0xcc,
+ 0xb6, 0xc0, 0xa1, 0x2f, 0x44, 0x2b, 0xc1, 0x89,
+ 0xcb, 0x6e, 0x1e, 0xdb, 0x57, 0x92, 0xd5, 0x97,
+ 0x60, 0x8c, 0x41, 0x2c, 0xd9, 0x20, 0xfe, 0xe9,
+ 0x1f, 0x8e, 0xfc, 0x7f, 0x02, 0x44, 0x0f, 0x28,
+ 0x81, 0xd6, 0x0c, 0xcd, 0xbc, 0xf0, 0x57, 0x6c,
+ 0xcc, 0xa7, 0xba, 0x06, 0xa0, 0xa6, 0x91, 0xda,
+ 0xef, 0x46, 0x8a, 0x60, 0x0f, 0x52, 0x6c, 0x90,
+ 0x6c, 0x8c, 0x44, 0xaf, 0xb0, 0x9d, 0x90, 0xba,
+ 0x21, 0x58, 0xa0, 0x3c, 0xee, 0x54, 0xb5, 0x29,
+ 0x26, 0x1f, 0x0a, 0xac, 0xef, 0x48, 0x68, 0x33,
+ 0xd0, 0x33, 0xd0, 0x8b, 0x1a, 0xec, 0x6e, 0x2f,
+ 0xb5, 0x4a, 0x53, 0xc2, 0x1a, 0xd2, 0xf1, 0x50,
+ 0x05, 0x59, 0x5c, 0xd9, 0xda, 0x03, 0x0a, 0x47,
+ 0xb7, 0xdd, 0xf7, 0x3a, 0x69, 0xf5, 0x4e, 0xea,
+ 0x4a, 0xc2, 0xca, 0x54, 0xb0, 0x8b, 0x76, 0xe1,
+ 0x02, 0x2d, 0x52, 0x67, 0xb9, 0xdd, 0x50, 0xc9,
+ 0x3b, 0x07, 0x24, 0x22, 0x6a, 0x00, 0x1d, 0x58,
+ 0x83, 0xa8, 0xec, 0x95, 0xf1, 0xda, 0xe2, 0x73,
+ 0xa0, 0xa1, 0x72, 0x60, 0x9e, 0x86, 0x53, 0xcb,
+ 0x45, 0xa8, 0xc2, 0xa0, 0x50, 0xa0, 0x53, 0xd6,
+ 0xfc, 0x18, 0x84, 0xb5, 0x4a, 0x26, 0xd0, 0xa2,
+ 0xaa, 0xd0, 0xff, 0xb6, 0xfe, 0x3a, 0x9c, 0xb5,
+ 0x19, 0x3b, 0x3f, 0xe1, 0x48, 0x0d, 0xa4, 0x09,
+ 0x4f, 0x83, 0xc9, 0xc0, 0xc9, 0xa6, 0x0b, 0x58,
+ 0x1f, 0x1c, 0x7b, 0xac, 0xa2, 0x42, 0xbc, 0x61,
+ 0xf4, 0x21, 0x8a, 0x00, 0xda, 0x14, 0xa0, 0x60,
+ 0x03, 0xfe, 0x93, 0x12, 0x6c, 0x56, 0xcd, 0x02,
+ 0x03, 0x01, 0x00, 0x01, 0x30, 0x0d, 0x06, 0x09,
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+ 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00,
+ 0x25, 0x29, 0x3b, 0x1e, 0xc3, 0x58, 0x32, 0xe6,
+ 0x23, 0xc8, 0xee, 0x18, 0xf0, 0x1d, 0x62, 0x6d,
+ 0x3b, 0x59, 0x99, 0x3a, 0xfe, 0x49, 0x72, 0x07,
+ 0x3f, 0x58, 0x93, 0xdb, 0xc0, 0xaf, 0xb0, 0xb3,
+ 0x5c, 0xd1, 0x5c, 0x98, 0xc8, 0xea, 0x4a, 0xe4,
+ 0x58, 0x73, 0x0d, 0x57, 0xc5, 0x13, 0x7c, 0x5c,
+ 0x79, 0x66, 0xda, 0x04, 0x1d, 0xe5, 0x98, 0xda,
+ 0x35, 0x47, 0x44, 0xb0, 0xd2, 0x7a, 0x66, 0x9d,
+ 0xcd, 0x41, 0xa5, 0x8f, 0xa1, 0x11, 0xb2, 0x1a,
+ 0x87, 0xc0, 0xcd, 0x55, 0xed, 0xb4, 0x7b, 0x33,
+ 0x72, 0xeb, 0xf7, 0xe3, 0x7b, 0x8b, 0x02, 0x86,
+ 0xe9, 0x2b, 0x26, 0x32, 0x9f, 0x99, 0xf1, 0xcb,
+ 0x93, 0xab, 0xb9, 0x16, 0xb3, 0x9a, 0xb2, 0x22,
+ 0x13, 0x21, 0x1f, 0x5b, 0xcc, 0xa2, 0x59, 0xbb,
+ 0x69, 0xf2, 0xb8, 0x07, 0x80, 0xce, 0x0c, 0xf7,
+ 0x98, 0x4c, 0x85, 0xc2, 0x96, 0x6a, 0x22, 0x05,
+ 0xe9, 0xbe, 0x48, 0xb0, 0x02, 0x5b, 0x69, 0x28,
+ 0x18, 0x88, 0x96, 0xe3, 0xd7, 0xc6, 0x7a, 0xd3,
+ 0xe9, 0x99, 0xff, 0x9d, 0xc3, 0x61, 0x4d, 0x9a,
+ 0x96, 0xf2, 0xc6, 0x33, 0x4d, 0xe5, 0x5d, 0x5a,
+ 0x68, 0x64, 0x5a, 0x82, 0x35, 0x65, 0x25, 0xe3,
+ 0x8c, 0x5b, 0xb0, 0xf6, 0x96, 0x56, 0xbc, 0xbf,
+ 0x97, 0x76, 0x4b, 0x66, 0x44, 0x81, 0xa4, 0xc4,
+ 0xa7, 0x31, 0xc5, 0xa1, 0x4f, 0xe8, 0xa4, 0xca,
+ 0x20, 0xf5, 0x01, 0x5b, 0x99, 0x4f, 0x5a, 0xf4,
+ 0xf0, 0x78, 0xbf, 0x71, 0x49, 0xd5, 0xf1, 0xc1,
+ 0xa2, 0x18, 0xfd, 0x72, 0x5b, 0x16, 0xe8, 0x92,
+ 0xc7, 0x37, 0x48, 0xaf, 0xee, 0x24, 0xfc, 0x35,
+ 0x0b, 0xc2, 0xdd, 0x05, 0xc7, 0x6e, 0xa3, 0x29,
+ 0xbb, 0x29, 0x7d, 0xd3, 0x2b, 0x94, 0x80, 0xc3,
+ 0x40, 0x53, 0x0e, 0x03, 0x54, 0x3d, 0x7b, 0x8b,
+ 0xce, 0xf9, 0xa4, 0x03, 0x27, 0x63, 0xec, 0x51,
+ 0x00, 0x03, 0xe5, 0x30, 0x82, 0x03, 0xe1, 0x30,
+ 0x82, 0x02, 0xc9, 0xa0, 0x03, 0x02, 0x01, 0x02,
+ 0x02, 0x09, 0x00, 0xcc, 0x22, 0x4c, 0x4b, 0x98,
+ 0xa2, 0x88, 0xfc, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05,
+ 0x05, 0x00, 0x30, 0x81, 0x86, 0x31, 0x0b, 0x30,
+ 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+ 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
+ 0x55, 0x04, 0x08, 0x0c, 0x02, 0x4e, 0x59, 0x31,
+ 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x07,
+ 0x0c, 0x08, 0x42, 0x72, 0x6f, 0x6f, 0x6b, 0x6c,
+ 0x79, 0x6e, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03,
+ 0x55, 0x04, 0x0a, 0x0c, 0x18, 0x4d, 0x79, 0x20,
+ 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63,
+ 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68,
+ 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x11, 0x30,
+ 0x0f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x08,
+ 0x6d, 0x79, 0x63, 0x61, 0x2e, 0x6f, 0x72, 0x67,
+ 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a, 0x86,
+ 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16,
+ 0x12, 0x6a, 0x76, 0x73, 0x68, 0x61, 0x68, 0x69,
+ 0x64, 0x40, 0x67, 0x6d, 0x61, 0x69, 0x6c, 0x2e,
+ 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x31,
+ 0x33, 0x30, 0x35, 0x32, 0x36, 0x32, 0x31, 0x30,
+ 0x35, 0x30, 0x31, 0x5a, 0x17, 0x0d, 0x32, 0x33,
+ 0x30, 0x35, 0x32, 0x34, 0x32, 0x31, 0x30, 0x35,
+ 0x30, 0x31, 0x5a, 0x30, 0x81, 0x86, 0x31, 0x0b,
+ 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
+ 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06,
+ 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02, 0x4e, 0x59,
+ 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04,
+ 0x07, 0x0c, 0x08, 0x42, 0x72, 0x6f, 0x6f, 0x6b,
+ 0x6c, 0x79, 0x6e, 0x31, 0x21, 0x30, 0x1f, 0x06,
+ 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x18, 0x4d, 0x79,
+ 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69,
+ 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74,
+ 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x11,
+ 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c,
+ 0x08, 0x6d, 0x79, 0x63, 0x61, 0x2e, 0x6f, 0x72,
+ 0x67, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01,
+ 0x16, 0x12, 0x6a, 0x76, 0x73, 0x68, 0x61, 0x68,
+ 0x69, 0x64, 0x40, 0x67, 0x6d, 0x61, 0x69, 0x6c,
+ 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x82, 0x01, 0x22,
+ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+ 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03,
+ 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a,
+ 0x02, 0x82, 0x01, 0x01, 0x00, 0xf0, 0xfb, 0xad,
+ 0x80, 0x5e, 0x37, 0xd3, 0x6d, 0xee, 0x2e, 0xcc,
+ 0xbc, 0x0c, 0xd7, 0x56, 0x4b, 0x56, 0x45, 0xcd,
+ 0x28, 0xb6, 0x22, 0xe9, 0xe2, 0x0f, 0xd1, 0x87,
+ 0x2a, 0x27, 0xce, 0x77, 0x8d, 0x6e, 0x0e, 0x0f,
+ 0xfb, 0x66, 0xe1, 0xb5, 0x0e, 0x9a, 0xb6, 0x05,
+ 0x8e, 0xb3, 0xe1, 0xc5, 0x77, 0x86, 0x5b, 0x46,
+ 0xd2, 0x0b, 0x92, 0x03, 0x1b, 0x89, 0x0c, 0x1b,
+ 0x10, 0x0e, 0x99, 0x8f, 0xe2, 0x17, 0xe8, 0xc2,
+ 0x30, 0x00, 0x47, 0xd6, 0xfc, 0xf9, 0x0f, 0x3b,
+ 0x75, 0x34, 0x8d, 0x4d, 0xb0, 0x99, 0xb7, 0xa0,
+ 0x6d, 0xa0, 0xb6, 0xad, 0xda, 0x07, 0x5e, 0x38,
+ 0x2e, 0x02, 0xe4, 0x30, 0x6d, 0xae, 0x13, 0x72,
+ 0xd4, 0xc8, 0xce, 0x14, 0x07, 0xae, 0x23, 0x8c,
+ 0x8f, 0x9e, 0x8c, 0x60, 0xd6, 0x06, 0xb9, 0xef,
+ 0x00, 0x18, 0xc0, 0x1d, 0x25, 0x1e, 0xda, 0x3e,
+ 0x2f, 0xcf, 0x2b, 0x56, 0x84, 0x9e, 0x30, 0x21,
+ 0xc7, 0x29, 0xf6, 0x03, 0x8a, 0x24, 0xf9, 0x34,
+ 0xac, 0x65, 0x9d, 0x80, 0x36, 0xc8, 0x3b, 0x15,
+ 0x10, 0xbd, 0x51, 0xe9, 0xbc, 0x02, 0xe1, 0xe9,
+ 0xb3, 0x5a, 0x9a, 0x99, 0x41, 0x1b, 0x27, 0xa0,
+ 0x4d, 0x50, 0x9e, 0x27, 0x7f, 0xa1, 0x7d, 0x09,
+ 0x87, 0xbd, 0x8a, 0xca, 0x5f, 0xb1, 0xa5, 0x08,
+ 0xb8, 0x04, 0xd4, 0x52, 0x89, 0xaa, 0xe0, 0x7d,
+ 0x42, 0x2e, 0x2f, 0x15, 0xee, 0x66, 0x57, 0x0f,
+ 0x13, 0x19, 0x45, 0xa8, 0x4b, 0x5d, 0x81, 0x66,
+ 0xcc, 0x12, 0x37, 0x94, 0x5e, 0xfd, 0x3c, 0x10,
+ 0x81, 0x51, 0x3f, 0xfa, 0x0f, 0xdd, 0xa1, 0x89,
+ 0x03, 0xa9, 0x78, 0x91, 0xf5, 0x3b, 0xf3, 0xbc,
+ 0xac, 0xbe, 0x93, 0x30, 0x2e, 0xbe, 0xca, 0x7f,
+ 0x46, 0xd3, 0x28, 0xb4, 0x4e, 0x91, 0x7b, 0x5b,
+ 0x43, 0x6c, 0xaf, 0x9b, 0x5c, 0x6a, 0x6d, 0x5a,
+ 0xdb, 0x79, 0x5e, 0x6a, 0x6b, 0x02, 0x03, 0x01,
+ 0x00, 0x01, 0xa3, 0x50, 0x30, 0x4e, 0x30, 0x1d,
+ 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04,
+ 0x14, 0x6b, 0x1e, 0x00, 0xa8, 0x9f, 0xfa, 0x7d,
+ 0x00, 0xf9, 0xe0, 0x9d, 0x0f, 0x90, 0x8c, 0x90,
+ 0xa8, 0xa1, 0x37, 0x6b, 0xda, 0x30, 0x1f, 0x06,
+ 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16,
+ 0x80, 0x14, 0x6b, 0x1e, 0x00, 0xa8, 0x9f, 0xfa,
+ 0x7d, 0x00, 0xf9, 0xe0, 0x9d, 0x0f, 0x90, 0x8c,
+ 0x90, 0xa8, 0xa1, 0x37, 0x6b, 0xda, 0x30, 0x0c,
+ 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30,
+ 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, 0x09,
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+ 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00,
+ 0xcd, 0x6f, 0x73, 0x4d, 0x56, 0x0b, 0xf3, 0x2e,
+ 0x1c, 0xe2, 0x02, 0x0c, 0x14, 0xbb, 0x2f, 0xdd,
+ 0x3c, 0x43, 0xfe, 0xdf, 0x94, 0x2d, 0xa9, 0x89,
+ 0x81, 0x51, 0xf8, 0x5f, 0xa7, 0xa0, 0x13, 0xaa,
+ 0xcc, 0xb0, 0x18, 0xe2, 0x57, 0x3e, 0x0d, 0x29,
+ 0x93, 0xe8, 0x95, 0xd5, 0x1b, 0x53, 0xd2, 0x51,
+ 0xf2, 0xbd, 0xf5, 0x9e, 0x7b, 0x22, 0x65, 0x62,
+ 0x5c, 0xc4, 0x4c, 0x1d, 0xe8, 0xe9, 0xc3, 0xd4,
+ 0x2b, 0xe7, 0x78, 0xcb, 0x10, 0xf3, 0xfe, 0x06,
+ 0x83, 0xdc, 0x3a, 0x1e, 0x62, 0x10, 0xc0, 0x46,
+ 0x77, 0xc6, 0x9d, 0x9f, 0xab, 0x96, 0x25, 0x5c,
+ 0xfb, 0x26, 0xc1, 0x15, 0x1f, 0xa5, 0x33, 0xee,
+ 0x4f, 0x9a, 0x14, 0x6a, 0x14, 0x97, 0x93, 0x2b,
+ 0x95, 0x0b, 0xdc, 0xa8, 0xd7, 0x69, 0x2e, 0xf0,
+ 0x01, 0x0e, 0xfd, 0x4e, 0xd0, 0xd9, 0xa8, 0xe5,
+ 0x65, 0xde, 0xfb, 0xca, 0xca, 0x1c, 0x5f, 0xf9,
+ 0x53, 0xa0, 0x87, 0xe7, 0x33, 0x9b, 0x2f, 0xcf,
+ 0xe4, 0x13, 0xfc, 0xec, 0x7a, 0x6c, 0xb0, 0x90,
+ 0x13, 0x9b, 0xb6, 0xc5, 0x03, 0xf6, 0x0e, 0x5e,
+ 0xe2, 0xe4, 0x26, 0xc1, 0x7e, 0x53, 0xfe, 0x69,
+ 0xa3, 0xc7, 0xd8, 0x8e, 0x6e, 0x94, 0x32, 0xa0,
+ 0xde, 0xca, 0xb6, 0xcc, 0xd6, 0x01, 0xd5, 0x78,
+ 0x40, 0x28, 0x63, 0x9b, 0xee, 0xcf, 0x09, 0x3b,
+ 0x35, 0x04, 0xf0, 0x14, 0x02, 0xf6, 0x80, 0x0e,
+ 0x90, 0xb2, 0x94, 0xd2, 0x25, 0x16, 0xb8, 0x7a,
+ 0x76, 0x87, 0x84, 0x9f, 0x84, 0xc5, 0xaf, 0xc2,
+ 0x6d, 0x68, 0x7a, 0x84, 0x9c, 0xc6, 0x8a, 0x63,
+ 0x60, 0x87, 0x6a, 0x25, 0xc1, 0xa1, 0x78, 0x0f,
+ 0xba, 0xe8, 0x5f, 0xe1, 0xba, 0xac, 0xa4, 0x6f,
+ 0xdd, 0x09, 0x3f, 0x12, 0xcb, 0x1d, 0xf3, 0xcf,
+ 0x48, 0xd7, 0xd3, 0x26, 0xe8, 0x9c, 0xc3, 0x53,
+ 0xb3, 0xba, 0xdc, 0x32, 0x99, 0x98, 0x96, 0xd6,
+ 0x16, 0x03, 0x01, 0x01, 0x06, 0x10, 0x00, 0x01,
+ 0x02, 0x01, 0x00, 0x6e, 0xea, 0x15, 0x6f, 0x21,
+ 0xbd, 0x2d, 0x14, 0xde, 0x9d, 0x02, 0xeb, 0xdf,
+ 0x3b, 0x09, 0x75, 0xaf, 0x32, 0x80, 0x0c, 0xe2,
+ 0xc2, 0x7b, 0x0d, 0xca, 0x24, 0x96, 0xf6, 0x3e,
+ 0xa5, 0x97, 0xba, 0x0c, 0x50, 0x7e, 0xb3, 0x68,
+ 0x58, 0xc6, 0xd8, 0xec, 0xab, 0xa9, 0xd9, 0x3a,
+ 0xb1, 0x49, 0xea, 0x2f, 0xd7, 0xdb, 0x15, 0x1b,
+ 0xb5, 0xaf, 0xec, 0xcc, 0x40, 0x5c, 0xe6, 0x0f,
+ 0xc4, 0x33, 0x71, 0xe7, 0x41, 0xc0, 0x04, 0x89,
+ 0x60, 0x3e, 0xb7, 0xe6, 0xda, 0x38, 0x62, 0x27,
+ 0x6a, 0xd9, 0xfb, 0x93, 0x94, 0x9d, 0xc1, 0x63,
+ 0x92, 0x5c, 0x88, 0x19, 0x38, 0x81, 0x79, 0x9d,
+ 0x59, 0x48, 0x5e, 0xd3, 0xc8, 0xea, 0xcb, 0x6e,
+ 0x66, 0x66, 0x03, 0xdc, 0x0c, 0x2d, 0x95, 0xb1,
+ 0x4d, 0x68, 0xc7, 0xc5, 0x6e, 0xfa, 0x94, 0x14,
+ 0xdf, 0x2c, 0x70, 0x69, 0x04, 0xf4, 0x69, 0xf1,
+ 0xf0, 0x07, 0xbd, 0x23, 0x53, 0x63, 0xb3, 0x41,
+ 0xec, 0xa7, 0x10, 0xa5, 0x04, 0x84, 0x24, 0xb5,
+ 0xf5, 0x0c, 0x0f, 0x5d, 0x02, 0x47, 0x79, 0x60,
+ 0x76, 0xbb, 0xdf, 0x60, 0xa6, 0xd7, 0x4d, 0x08,
+ 0x7d, 0xa6, 0x85, 0x4f, 0x61, 0xac, 0x96, 0x3d,
+ 0xbc, 0xaf, 0x07, 0xb0, 0x7c, 0xb6, 0x23, 0x3e,
+ 0x1f, 0x0a, 0x62, 0x77, 0x97, 0x77, 0xae, 0x33,
+ 0x55, 0x0f, 0x85, 0xdf, 0xdc, 0xbe, 0xc6, 0xe0,
+ 0xe0, 0x14, 0x83, 0x4c, 0x50, 0xf0, 0xe5, 0x2d,
+ 0xdc, 0x0b, 0x74, 0x7f, 0xc3, 0x28, 0x98, 0x16,
+ 0xda, 0x74, 0xe6, 0x40, 0xc2, 0xf0, 0xea, 0xc0,
+ 0x00, 0xd5, 0xfc, 0x16, 0xe4, 0x43, 0xa1, 0xfc,
+ 0x31, 0x19, 0x81, 0x62, 0xec, 0x2b, 0xfe, 0xcc,
+ 0xe8, 0x19, 0xed, 0xa1, 0x1e, 0x6a, 0x49, 0x73,
+ 0xde, 0xc4, 0xe9, 0x22, 0x0a, 0x21, 0xde, 0x45,
+ 0x1e, 0x55, 0x12, 0xd9, 0x44, 0xef, 0x4e, 0xaa,
+ 0x5e, 0x26, 0x57, 0x16, 0x03, 0x01, 0x01, 0x06,
+ 0x0f, 0x00, 0x01, 0x02, 0x01, 0x00, 0x23, 0xde,
+ 0xb0, 0x39, 0x60, 0xe9, 0x82, 0xb8, 0xed, 0x17,
+ 0x78, 0xd2, 0x37, 0x0e, 0x85, 0x69, 0xda, 0xcc,
+ 0x9f, 0x54, 0x4d, 0xda, 0xce, 0xe8, 0x5a, 0xeb,
+ 0x3c, 0x61, 0x4c, 0x7a, 0x84, 0x1f, 0x21, 0x03,
+ 0xb3, 0x8a, 0x74, 0x3b, 0x6a, 0x9e, 0x4f, 0x44,
+ 0xd9, 0x75, 0x0a, 0xd8, 0x7e, 0x56, 0xa3, 0xef,
+ 0x5a, 0xfe, 0x8a, 0x35, 0xce, 0x29, 0x18, 0xfe,
+ 0xa6, 0x61, 0x8e, 0x8f, 0x00, 0x90, 0x2d, 0x85,
+ 0xe3, 0x6c, 0x0e, 0x8d, 0x8c, 0x27, 0x80, 0x8c,
+ 0x9f, 0x51, 0xe9, 0xd3, 0xe6, 0x7d, 0x70, 0xe9,
+ 0xfb, 0xcb, 0xb8, 0x24, 0x94, 0x30, 0x9b, 0xba,
+ 0x01, 0x14, 0x49, 0x9f, 0xaf, 0x09, 0xd8, 0x26,
+ 0x1b, 0x23, 0xa4, 0xb8, 0xd9, 0x44, 0x0a, 0xdc,
+ 0x4e, 0x27, 0xe7, 0x32, 0xf5, 0x9c, 0xf3, 0x8d,
+ 0xa0, 0xc5, 0xc4, 0xbe, 0x92, 0x02, 0x85, 0x4f,
+ 0x33, 0x8f, 0xa7, 0xf7, 0x87, 0xa9, 0x44, 0xf3,
+ 0x64, 0xbd, 0x32, 0x04, 0xeb, 0xc5, 0xc3, 0x62,
+ 0xe9, 0xda, 0x2f, 0x95, 0x5c, 0xf7, 0x58, 0x3e,
+ 0xad, 0x35, 0xd7, 0x7e, 0xad, 0xdd, 0x32, 0x8d,
+ 0xce, 0x81, 0x08, 0xad, 0x49, 0xf7, 0xdb, 0xf7,
+ 0xaf, 0xe3, 0xc6, 0xb2, 0xdd, 0x76, 0x0c, 0xcf,
+ 0x0f, 0x87, 0x79, 0x90, 0x10, 0x79, 0xc6, 0xc8,
+ 0x7b, 0xe6, 0x23, 0xf2, 0xda, 0x33, 0xca, 0xe1,
+ 0xf0, 0x59, 0x42, 0x43, 0x03, 0x56, 0x19, 0xe3,
+ 0x8b, 0xe6, 0xa8, 0x70, 0xbc, 0x80, 0xfa, 0x24,
+ 0xae, 0x03, 0x13, 0x30, 0x0d, 0x1f, 0xab, 0xb7,
+ 0x82, 0xd9, 0x24, 0x90, 0x80, 0xbf, 0x75, 0xe1,
+ 0x0d, 0x1c, 0xb2, 0xfe, 0x92, 0x2c, 0x4d, 0x21,
+ 0xe9, 0x5d, 0xa1, 0x68, 0xf3, 0x16, 0xd8, 0x3f,
+ 0xb2, 0xc3, 0x00, 0x3e, 0xd8, 0x42, 0x25, 0x5c,
+ 0x90, 0x11, 0xc0, 0x1b, 0xd4, 0x26, 0x5c, 0x37,
+ 0x47, 0xbd, 0xf8, 0x1e, 0x34, 0xa9, 0x14, 0x03,
+ 0x01, 0x00, 0x01, 0x01, 0x16, 0x03, 0x01, 0x00,
+ 0x24, 0x8f, 0x94, 0x7e, 0x01, 0xee, 0xd5, 0x4f,
+ 0x83, 0x41, 0x31, 0xc0, 0x36, 0x81, 0x46, 0xc3,
+ 0xc0, 0xcc, 0x9c, 0xea, 0x0f, 0x29, 0x04, 0x10,
+ 0x43, 0x1e, 0x08, 0x6e, 0x08, 0xce, 0xb2, 0x62,
+ 0xa6, 0x0f, 0x68, 0x9f, 0x99,
+ },
+ {
+ 0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03,
+ 0x01, 0x00, 0x24, 0xd9, 0x46, 0x5b, 0xbf, 0xfd,
+ 0x8a, 0xa1, 0x08, 0xd5, 0xf3, 0x0c, 0x1c, 0xd8,
+ 0xa8, 0xb3, 0xe5, 0x89, 0x83, 0x9e, 0x23, 0x47,
+ 0x81, 0x66, 0x77, 0x11, 0x98, 0xe5, 0xf4, 0xac,
+ 0x06, 0xe9, 0x4c, 0x05, 0x8b, 0xc4, 0x16,
+ },
+ {
+ 0x17, 0x03, 0x01, 0x00, 0x1a, 0xc5, 0x28, 0xfd,
+ 0x71, 0xc0, 0xe6, 0x89, 0xb8, 0x82, 0x92, 0x1b,
+ 0xdd, 0x39, 0xe5, 0xbf, 0x41, 0x82, 0x1f, 0xc1,
+ 0xbc, 0x85, 0xe5, 0x32, 0x1b, 0x93, 0x46, 0x15,
+ 0x03, 0x01, 0x00, 0x16, 0x1a, 0x8b, 0x10, 0x42,
+ 0x12, 0xb2, 0xbd, 0xd3, 0xf1, 0x74, 0x1f, 0xc2,
+ 0x10, 0x08, 0xc2, 0x79, 0x99, 0x2c, 0x55, 0xef,
+ 0x4a, 0xbd,
+ },
+}
+
+// $ openssl s_server -tls1_2 -cert server.crt -key server.key \
+// -cipher ECDHE-RSA-AES128-SHA -port 10443
+// $ go test -test.run "TestRunClient" -connect -ciphersuites=0xc013 \
+// -minversion=0x0303 -maxversion=0x0303
+var clientTLS12Script = [][]byte{
+ {
+ 0x16, 0x03, 0x01, 0x00, 0x58, 0x01, 0x00, 0x00,
+ 0x54, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xc0, 0x13,
+ 0x01, 0x00, 0x00, 0x29, 0x00, 0x05, 0x00, 0x05,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00,
+ 0x08, 0x00, 0x06, 0x00, 0x17, 0x00, 0x18, 0x00,
+ 0x19, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00,
+ 0x0d, 0x00, 0x0a, 0x00, 0x08, 0x04, 0x01, 0x04,
+ 0x03, 0x02, 0x01, 0x02, 0x03,
+ },
+ {
+ 0x16, 0x03, 0x03, 0x00, 0x54, 0x02, 0x00, 0x00,
+ 0x50, 0x03, 0x03, 0x52, 0x65, 0x67, 0xbd, 0xe8,
+ 0x72, 0x03, 0x6a, 0x52, 0x8d, 0x28, 0x2c, 0x9a,
+ 0x53, 0xff, 0xc2, 0xa1, 0x62, 0x5f, 0x54, 0xfb,
+ 0x73, 0x00, 0xcf, 0x4d, 0x28, 0x36, 0xc2, 0xee,
+ 0xfd, 0x78, 0xf0, 0x20, 0x6f, 0xbe, 0x49, 0xec,
+ 0x5b, 0x6f, 0xf9, 0x53, 0x42, 0x69, 0x0d, 0x6d,
+ 0x8b, 0x68, 0x2e, 0xca, 0x3c, 0x3c, 0x88, 0x9e,
+ 0x8b, 0xf9, 0x32, 0x65, 0x09, 0xd6, 0xa0, 0x7d,
+ 0xea, 0xc6, 0xd5, 0xc4, 0xc0, 0x13, 0x00, 0x00,
+ 0x08, 0x00, 0x0b, 0x00, 0x04, 0x03, 0x00, 0x01,
+ 0x02, 0x16, 0x03, 0x03, 0x02, 0x39, 0x0b, 0x00,
+ 0x02, 0x35, 0x00, 0x02, 0x32, 0x00, 0x02, 0x2f,
+ 0x30, 0x82, 0x02, 0x2b, 0x30, 0x82, 0x01, 0xd5,
+ 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00,
+ 0xb1, 0x35, 0x13, 0x65, 0x11, 0x20, 0xc5, 0x92,
+ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+ 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30,
+ 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+ 0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13,
+ 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13,
+ 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74,
+ 0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06,
+ 0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e,
+ 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57,
+ 0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50,
+ 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e,
+ 0x17, 0x0d, 0x31, 0x32, 0x30, 0x34, 0x30, 0x36,
+ 0x31, 0x37, 0x31, 0x30, 0x31, 0x33, 0x5a, 0x17,
+ 0x0d, 0x31, 0x35, 0x30, 0x34, 0x30, 0x36, 0x31,
+ 0x37, 0x31, 0x30, 0x31, 0x33, 0x5a, 0x30, 0x45,
+ 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
+ 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30,
+ 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a,
+ 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61,
+ 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03,
+ 0x55, 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74,
+ 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69,
+ 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74,
+ 0x79, 0x20, 0x4c, 0x74, 0x64, 0x30, 0x5c, 0x30,
+ 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b,
+ 0x00, 0x30, 0x48, 0x02, 0x41, 0x00, 0x9f, 0xb3,
+ 0xc3, 0x84, 0x27, 0x95, 0xff, 0x12, 0x31, 0x52,
+ 0x0f, 0x15, 0xef, 0x46, 0x11, 0xc4, 0xad, 0x80,
+ 0xe6, 0x36, 0x5b, 0x0f, 0xdd, 0x80, 0xd7, 0x61,
+ 0x8d, 0xe0, 0xfc, 0x72, 0x45, 0x09, 0x34, 0xfe,
+ 0x55, 0x66, 0x45, 0x43, 0x4c, 0x68, 0x97, 0x6a,
+ 0xfe, 0xa8, 0xa0, 0xa5, 0xdf, 0x5f, 0x78, 0xff,
+ 0xee, 0xd7, 0x64, 0xb8, 0x3f, 0x04, 0xcb, 0x6f,
+ 0xff, 0x2a, 0xfe, 0xfe, 0xb9, 0xed, 0x02, 0x03,
+ 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7, 0x30, 0x81,
+ 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e,
+ 0x04, 0x16, 0x04, 0x14, 0x78, 0xa6, 0x97, 0x9a,
+ 0x63, 0xb5, 0xc5, 0xa1, 0xa5, 0x33, 0xba, 0x22,
+ 0x7c, 0x23, 0x6e, 0x5b, 0x1b, 0x7a, 0xcc, 0x2b,
+ 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04,
+ 0x6e, 0x30, 0x6c, 0x80, 0x14, 0x78, 0xa6, 0x97,
+ 0x9a, 0x63, 0xb5, 0xc5, 0xa1, 0xa5, 0x33, 0xba,
+ 0x22, 0x7c, 0x23, 0x6e, 0x5b, 0x1b, 0x7a, 0xcc,
+ 0x2b, 0xa1, 0x49, 0xa4, 0x47, 0x30, 0x45, 0x31,
+ 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+ 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11,
+ 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53,
+ 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74,
+ 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55,
+ 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65,
+ 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64,
+ 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79,
+ 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09, 0x00, 0xb1,
+ 0x35, 0x13, 0x65, 0x11, 0x20, 0xc5, 0x92, 0x30,
+ 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05,
+ 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06,
+ 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
+ 0x01, 0x05, 0x05, 0x00, 0x03, 0x41, 0x00, 0x85,
+ 0x36, 0x40, 0x73, 0xc1, 0xbb, 0x1a, 0xda, 0xd4,
+ 0x59, 0x9f, 0x2d, 0xa2, 0x70, 0x31, 0x46, 0x74,
+ 0xec, 0x83, 0x6e, 0xa8, 0xc8, 0x3c, 0x51, 0xaf,
+ 0x39, 0xac, 0xec, 0x40, 0xbc, 0xe8, 0x22, 0x46,
+ 0x1d, 0x99, 0xd6, 0x46, 0x2a, 0x24, 0xd4, 0x8b,
+ 0x05, 0x08, 0x4b, 0xfb, 0x35, 0x11, 0x6e, 0x92,
+ 0xbb, 0x77, 0xba, 0xe4, 0x12, 0xbb, 0xf4, 0xc8,
+ 0x5e, 0x9c, 0x81, 0xa8, 0x97, 0x60, 0x4c, 0x16,
+ 0x03, 0x03, 0x00, 0x8d, 0x0c, 0x00, 0x00, 0x89,
+ 0x03, 0x00, 0x17, 0x41, 0x04, 0x48, 0x93, 0x62,
+ 0x6a, 0xf8, 0x7c, 0x94, 0xcc, 0xcc, 0x0a, 0x9b,
+ 0x5e, 0x11, 0xad, 0x0b, 0x30, 0xc4, 0x5d, 0xf7,
+ 0x63, 0x24, 0xc1, 0xb0, 0x40, 0x5f, 0xff, 0x9f,
+ 0x0d, 0x7e, 0xd5, 0xa5, 0xd0, 0x4f, 0x80, 0x16,
+ 0xa8, 0x66, 0x18, 0x31, 0x1f, 0x81, 0xb2, 0x9a,
+ 0x41, 0x62, 0x5b, 0xcf, 0x73, 0xac, 0x4a, 0x64,
+ 0xb5, 0xc1, 0x46, 0x4d, 0x8a, 0xac, 0x25, 0xba,
+ 0x81, 0x7f, 0xbe, 0x64, 0x68, 0x04, 0x01, 0x00,
+ 0x40, 0x4e, 0x3f, 0x1e, 0x04, 0x4c, 0xef, 0xd2,
+ 0xa6, 0x82, 0xe6, 0x7c, 0x76, 0x23, 0x17, 0xb9,
+ 0xe7, 0x52, 0x15, 0x6b, 0x3d, 0xb2, 0xb1, 0x17,
+ 0x7d, 0xe6, 0xde, 0x06, 0x87, 0x30, 0xb0, 0xb5,
+ 0x57, 0xae, 0xdf, 0xb2, 0xdc, 0x8d, 0xab, 0x76,
+ 0x9c, 0xaa, 0x45, 0x6d, 0x23, 0x5d, 0xc1, 0xa8,
+ 0x7b, 0x79, 0x79, 0xb1, 0x3c, 0xdc, 0xf5, 0x33,
+ 0x2c, 0xa1, 0x62, 0x3e, 0xbd, 0xf5, 0x5d, 0x6c,
+ 0x87, 0x16, 0x03, 0x03, 0x00, 0x04, 0x0e, 0x00,
+ 0x00, 0x00,
+ },
+ {
+ 0x16, 0x03, 0x03, 0x00, 0x46, 0x10, 0x00, 0x00,
+ 0x42, 0x41, 0x04, 0x1e, 0x18, 0x37, 0xef, 0x0d,
+ 0x19, 0x51, 0x88, 0x35, 0x75, 0x71, 0xb5, 0xe5,
+ 0x54, 0x5b, 0x12, 0x2e, 0x8f, 0x09, 0x67, 0xfd,
+ 0xa7, 0x24, 0x20, 0x3e, 0xb2, 0x56, 0x1c, 0xce,
+ 0x97, 0x28, 0x5e, 0xf8, 0x2b, 0x2d, 0x4f, 0x9e,
+ 0xf1, 0x07, 0x9f, 0x6c, 0x4b, 0x5b, 0x83, 0x56,
+ 0xe2, 0x32, 0x42, 0xe9, 0x58, 0xb6, 0xd7, 0x49,
+ 0xa6, 0xb5, 0x68, 0x1a, 0x41, 0x03, 0x56, 0x6b,
+ 0xdc, 0x5a, 0x89, 0x14, 0x03, 0x03, 0x00, 0x01,
+ 0x01, 0x16, 0x03, 0x03, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xee, 0x17,
+ 0x54, 0x51, 0xb6, 0x1d, 0x8e, 0xe4, 0x6b, 0xed,
+ 0x5b, 0xa1, 0x27, 0x7f, 0xdc, 0xa9, 0xa5, 0xcf,
+ 0x38, 0xe6, 0x5d, 0x17, 0x34, 0xf9, 0xc0, 0x07,
+ 0xb8, 0xbe, 0x56, 0xe6, 0xd6, 0x6a, 0xb6, 0x26,
+ 0x4e, 0x45, 0x8d, 0x48, 0xe9, 0xc6, 0xb1, 0xa1,
+ 0xea, 0xdc, 0xb1, 0x37, 0xd9, 0xf6,
+ },
+ {
+ 0x14, 0x03, 0x03, 0x00, 0x01, 0x01, 0x16, 0x03,
+ 0x03, 0x00, 0x40, 0x00, 0x68, 0xc5, 0x27, 0xd5,
+ 0x3d, 0xba, 0x04, 0xde, 0x63, 0xf1, 0x5b, 0xc3,
+ 0x86, 0xb9, 0x82, 0xc7, 0xb3, 0x90, 0x31, 0xea,
+ 0x15, 0xe1, 0x42, 0x76, 0x7d, 0x90, 0xcb, 0xc9,
+ 0xd1, 0x05, 0xe6, 0x8c, 0x76, 0xc7, 0x9a, 0x35,
+ 0x67, 0xa2, 0x70, 0x9a, 0x8a, 0x6c, 0xb5, 0x6b,
+ 0xc7, 0x87, 0xf3, 0x65, 0x0a, 0xa0, 0x98, 0xba,
+ 0x57, 0xbb, 0x31, 0x7b, 0x1f, 0x1a, 0xf7, 0x2a,
+ 0xf3, 0x12, 0xf6,
+ },
+ {
+ 0x17, 0x03, 0x03, 0x00, 0x30, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x10, 0x80,
+ 0x54, 0x1e, 0x72, 0xd3, 0x1a, 0x86, 0x1c, 0xc4,
+ 0x4a, 0x9b, 0xd4, 0x80, 0xd2, 0x03, 0x35, 0x0d,
+ 0xe4, 0x12, 0xc2, 0x3d, 0x79, 0x4a, 0x2c, 0xba,
+ 0xc2, 0xad, 0xf3, 0xd2, 0x16, 0x15, 0x03, 0x03,
+ 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x9b, 0x68, 0x78, 0x92, 0x28,
+ 0x62, 0x02, 0x65, 0x87, 0x90, 0xe4, 0x32, 0xd7,
+ 0x72, 0x08, 0x70, 0xb8, 0x52, 0x32, 0x1f, 0x97,
+ 0xd4, 0x6a, 0xc6, 0x28, 0x83, 0xb0, 0x1d, 0x6e,
+ 0x16, 0xd5,
+ },
+}
+
+// $ openssl s_server -tls1_2 -cert server.crt -key server.key \
+// -port 10443 -verify 0
+// $ go test -test.run "TestRunClient" -connect -ciphersuites=0xc02f \
+// -maxversion=0x0303
+var clientTLS12ClientCertScript = [][]byte{
+ {
+ 0x16, 0x03, 0x01, 0x00, 0x58, 0x01, 0x00, 0x00,
+ 0x54, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xc0, 0x2f,
+ 0x01, 0x00, 0x00, 0x29, 0x00, 0x05, 0x00, 0x05,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00,
+ 0x08, 0x00, 0x06, 0x00, 0x17, 0x00, 0x18, 0x00,
+ 0x19, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00,
+ 0x0d, 0x00, 0x0a, 0x00, 0x08, 0x04, 0x01, 0x04,
+ 0x03, 0x02, 0x01, 0x02, 0x03,
+ },
+ {
+ 0x16, 0x03, 0x03, 0x00, 0x54, 0x02, 0x00, 0x00,
+ 0x50, 0x03, 0x03, 0x52, 0x65, 0x67, 0xe0, 0xe8,
+ 0xf1, 0x13, 0x2a, 0x83, 0x28, 0xa8, 0x2e, 0x76,
+ 0x69, 0xe6, 0x89, 0x55, 0x6c, 0x48, 0x49, 0x2e,
+ 0x00, 0xf6, 0x87, 0x6c, 0x13, 0xa1, 0xd4, 0xaa,
+ 0xd0, 0x76, 0x3b, 0x20, 0xe4, 0xd6, 0x5b, 0x1d,
+ 0x11, 0xf2, 0x42, 0xf2, 0x82, 0x0c, 0x0d, 0x66,
+ 0x6d, 0xec, 0x52, 0xf8, 0x4a, 0xd9, 0x45, 0xcf,
+ 0xe4, 0x4a, 0xba, 0x8b, 0xf1, 0xab, 0x55, 0xe4,
+ 0x57, 0x18, 0xa9, 0x36, 0xc0, 0x2f, 0x00, 0x00,
+ 0x08, 0x00, 0x0b, 0x00, 0x04, 0x03, 0x00, 0x01,
+ 0x02, 0x16, 0x03, 0x03, 0x02, 0x39, 0x0b, 0x00,
+ 0x02, 0x35, 0x00, 0x02, 0x32, 0x00, 0x02, 0x2f,
+ 0x30, 0x82, 0x02, 0x2b, 0x30, 0x82, 0x01, 0xd5,
+ 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00,
+ 0xb1, 0x35, 0x13, 0x65, 0x11, 0x20, 0xc5, 0x92,
+ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+ 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30,
+ 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+ 0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13,
+ 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13,
+ 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74,
+ 0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06,
+ 0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e,
+ 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57,
+ 0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50,
+ 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e,
+ 0x17, 0x0d, 0x31, 0x32, 0x30, 0x34, 0x30, 0x36,
+ 0x31, 0x37, 0x31, 0x30, 0x31, 0x33, 0x5a, 0x17,
+ 0x0d, 0x31, 0x35, 0x30, 0x34, 0x30, 0x36, 0x31,
+ 0x37, 0x31, 0x30, 0x31, 0x33, 0x5a, 0x30, 0x45,
+ 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
+ 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30,
+ 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a,
+ 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61,
+ 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03,
+ 0x55, 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74,
+ 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69,
+ 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74,
+ 0x79, 0x20, 0x4c, 0x74, 0x64, 0x30, 0x5c, 0x30,
+ 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b,
+ 0x00, 0x30, 0x48, 0x02, 0x41, 0x00, 0x9f, 0xb3,
+ 0xc3, 0x84, 0x27, 0x95, 0xff, 0x12, 0x31, 0x52,
+ 0x0f, 0x15, 0xef, 0x46, 0x11, 0xc4, 0xad, 0x80,
+ 0xe6, 0x36, 0x5b, 0x0f, 0xdd, 0x80, 0xd7, 0x61,
+ 0x8d, 0xe0, 0xfc, 0x72, 0x45, 0x09, 0x34, 0xfe,
+ 0x55, 0x66, 0x45, 0x43, 0x4c, 0x68, 0x97, 0x6a,
+ 0xfe, 0xa8, 0xa0, 0xa5, 0xdf, 0x5f, 0x78, 0xff,
+ 0xee, 0xd7, 0x64, 0xb8, 0x3f, 0x04, 0xcb, 0x6f,
+ 0xff, 0x2a, 0xfe, 0xfe, 0xb9, 0xed, 0x02, 0x03,
+ 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7, 0x30, 0x81,
+ 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e,
+ 0x04, 0x16, 0x04, 0x14, 0x78, 0xa6, 0x97, 0x9a,
+ 0x63, 0xb5, 0xc5, 0xa1, 0xa5, 0x33, 0xba, 0x22,
+ 0x7c, 0x23, 0x6e, 0x5b, 0x1b, 0x7a, 0xcc, 0x2b,
+ 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04,
+ 0x6e, 0x30, 0x6c, 0x80, 0x14, 0x78, 0xa6, 0x97,
+ 0x9a, 0x63, 0xb5, 0xc5, 0xa1, 0xa5, 0x33, 0xba,
+ 0x22, 0x7c, 0x23, 0x6e, 0x5b, 0x1b, 0x7a, 0xcc,
+ 0x2b, 0xa1, 0x49, 0xa4, 0x47, 0x30, 0x45, 0x31,
+ 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+ 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11,
+ 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53,
+ 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74,
+ 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55,
+ 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65,
+ 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64,
+ 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79,
+ 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09, 0x00, 0xb1,
+ 0x35, 0x13, 0x65, 0x11, 0x20, 0xc5, 0x92, 0x30,
+ 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05,
+ 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06,
+ 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
+ 0x01, 0x05, 0x05, 0x00, 0x03, 0x41, 0x00, 0x85,
+ 0x36, 0x40, 0x73, 0xc1, 0xbb, 0x1a, 0xda, 0xd4,
+ 0x59, 0x9f, 0x2d, 0xa2, 0x70, 0x31, 0x46, 0x74,
+ 0xec, 0x83, 0x6e, 0xa8, 0xc8, 0x3c, 0x51, 0xaf,
+ 0x39, 0xac, 0xec, 0x40, 0xbc, 0xe8, 0x22, 0x46,
+ 0x1d, 0x99, 0xd6, 0x46, 0x2a, 0x24, 0xd4, 0x8b,
+ 0x05, 0x08, 0x4b, 0xfb, 0x35, 0x11, 0x6e, 0x92,
+ 0xbb, 0x77, 0xba, 0xe4, 0x12, 0xbb, 0xf4, 0xc8,
+ 0x5e, 0x9c, 0x81, 0xa8, 0x97, 0x60, 0x4c, 0x16,
+ 0x03, 0x03, 0x00, 0x8d, 0x0c, 0x00, 0x00, 0x89,
+ 0x03, 0x00, 0x17, 0x41, 0x04, 0xaa, 0xf0, 0x0c,
+ 0xa3, 0x60, 0xcf, 0x69, 0x1e, 0xad, 0x16, 0x9a,
+ 0x01, 0x40, 0xc6, 0x22, 0xc4, 0xbb, 0x06, 0x3b,
+ 0x84, 0x65, 0xea, 0xc7, 0xa2, 0x96, 0x79, 0x17,
+ 0x2f, 0xc7, 0xbe, 0x56, 0x39, 0xe4, 0x79, 0xf3,
+ 0xad, 0x17, 0xf3, 0x7e, 0xe2, 0x7b, 0xa2, 0x6f,
+ 0x3f, 0x96, 0xea, 0xe5, 0x0e, 0xea, 0x39, 0x79,
+ 0x77, 0xeb, 0x14, 0x18, 0xbb, 0x7c, 0x95, 0xda,
+ 0xa7, 0x51, 0x09, 0xba, 0xd7, 0x04, 0x01, 0x00,
+ 0x40, 0x82, 0x3e, 0xce, 0xee, 0x7e, 0xba, 0x3b,
+ 0x51, 0xb1, 0xba, 0x71, 0x2e, 0x54, 0xa9, 0xb9,
+ 0xe2, 0xb1, 0x59, 0x17, 0xa1, 0xac, 0x76, 0xb4,
+ 0x4e, 0xf1, 0xae, 0x65, 0x17, 0x2b, 0x43, 0x06,
+ 0x31, 0x29, 0x0b, 0xa0, 0x1e, 0xb6, 0xfa, 0x35,
+ 0xe8, 0x63, 0x06, 0xde, 0x13, 0x89, 0x83, 0x69,
+ 0x3b, 0xc2, 0x15, 0x73, 0x1c, 0xc5, 0x07, 0xe9,
+ 0x38, 0x9b, 0x06, 0x81, 0x1b, 0x97, 0x7c, 0xa6,
+ 0x89, 0x16, 0x03, 0x03, 0x00, 0x30, 0x0d, 0x00,
+ 0x00, 0x28, 0x03, 0x01, 0x02, 0x40, 0x00, 0x20,
+ 0x06, 0x01, 0x06, 0x02, 0x06, 0x03, 0x05, 0x01,
+ 0x05, 0x02, 0x05, 0x03, 0x04, 0x01, 0x04, 0x02,
+ 0x04, 0x03, 0x03, 0x01, 0x03, 0x02, 0x03, 0x03,
+ 0x02, 0x01, 0x02, 0x02, 0x02, 0x03, 0x01, 0x01,
+ 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ },
+ {
+ 0x16, 0x03, 0x03, 0x0a, 0xfb, 0x0b, 0x00, 0x0a,
+ 0xf7, 0x00, 0x0a, 0xf4, 0x00, 0x03, 0x7e, 0x30,
+ 0x82, 0x03, 0x7a, 0x30, 0x82, 0x02, 0x62, 0x02,
+ 0x09, 0x00, 0xb4, 0x47, 0x58, 0x57, 0x2b, 0x67,
+ 0xc8, 0xc2, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
+ 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05,
+ 0x00, 0x30, 0x81, 0x80, 0x31, 0x0b, 0x30, 0x09,
+ 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55,
+ 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+ 0x04, 0x08, 0x0c, 0x02, 0x4e, 0x59, 0x31, 0x11,
+ 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c,
+ 0x08, 0x42, 0x72, 0x6f, 0x6f, 0x6b, 0x6c, 0x79,
+ 0x6e, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55,
+ 0x04, 0x0a, 0x0c, 0x0c, 0x4d, 0x79, 0x20, 0x43,
+ 0x41, 0x20, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74,
+ 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04,
+ 0x03, 0x0c, 0x0e, 0x6d, 0x79, 0x63, 0x61, 0x63,
+ 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x63, 0x6f,
+ 0x6d, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01,
+ 0x16, 0x12, 0x6a, 0x76, 0x73, 0x68, 0x61, 0x68,
+ 0x69, 0x64, 0x40, 0x67, 0x6d, 0x61, 0x69, 0x6c,
+ 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d,
+ 0x31, 0x33, 0x30, 0x35, 0x32, 0x36, 0x32, 0x31,
+ 0x34, 0x34, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x31,
+ 0x33, 0x30, 0x36, 0x32, 0x35, 0x32, 0x31, 0x34,
+ 0x34, 0x30, 0x30, 0x5a, 0x30, 0x7d, 0x31, 0x0b,
+ 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
+ 0x02, 0x55, 0x53, 0x31, 0x11, 0x30, 0x0f, 0x06,
+ 0x03, 0x55, 0x04, 0x08, 0x0c, 0x08, 0x4e, 0x65,
+ 0x77, 0x20, 0x59, 0x6f, 0x72, 0x6b, 0x31, 0x11,
+ 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c,
+ 0x08, 0x42, 0x72, 0x6f, 0x6f, 0x6b, 0x6c, 0x79,
+ 0x6e, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55,
+ 0x04, 0x0a, 0x0c, 0x07, 0x4d, 0x79, 0x20, 0x4c,
+ 0x65, 0x61, 0x66, 0x31, 0x13, 0x30, 0x11, 0x06,
+ 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0a, 0x6d, 0x79,
+ 0x6c, 0x65, 0x61, 0x66, 0x2e, 0x63, 0x6f, 0x6d,
+ 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a, 0x86,
+ 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16,
+ 0x12, 0x6a, 0x76, 0x73, 0x68, 0x61, 0x68, 0x69,
+ 0x64, 0x40, 0x67, 0x6d, 0x61, 0x69, 0x6c, 0x2e,
+ 0x63, 0x6f, 0x6d, 0x30, 0x82, 0x01, 0x22, 0x30,
+ 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82,
+ 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02,
+ 0x82, 0x01, 0x01, 0x00, 0xa0, 0xa3, 0xef, 0xc1,
+ 0x44, 0x7d, 0xa2, 0xe3, 0x71, 0x98, 0x27, 0x63,
+ 0xb3, 0x1d, 0x71, 0x50, 0xa6, 0x34, 0x15, 0xcb,
+ 0xc9, 0x2a, 0xc3, 0xea, 0xe4, 0x9e, 0x9c, 0x49,
+ 0xa6, 0x01, 0x9b, 0x7e, 0xa9, 0xb5, 0x7a, 0xff,
+ 0x15, 0x92, 0x71, 0xc8, 0x97, 0x9c, 0x25, 0xb7,
+ 0x79, 0x2b, 0xff, 0xab, 0xc6, 0xb1, 0xa7, 0x00,
+ 0x90, 0xb2, 0x8b, 0xd7, 0x71, 0xd5, 0xc2, 0x3a,
+ 0xe6, 0x82, 0x42, 0x37, 0x89, 0x41, 0x04, 0xb0,
+ 0xba, 0xc7, 0x5b, 0x8a, 0x43, 0x9f, 0x97, 0x39,
+ 0x0c, 0x0f, 0xd5, 0x6d, 0x9e, 0x8d, 0xeb, 0xc0,
+ 0x26, 0xc5, 0x18, 0xe8, 0x7a, 0x3d, 0x32, 0x2e,
+ 0x38, 0x90, 0x40, 0x5b, 0x39, 0x2c, 0x07, 0xcb,
+ 0x24, 0x10, 0xc5, 0xc9, 0x3b, 0xe3, 0x66, 0x47,
+ 0x57, 0xb9, 0x6a, 0xad, 0x44, 0xf8, 0xd0, 0x70,
+ 0x62, 0x3b, 0x8e, 0xed, 0x60, 0x5f, 0x22, 0xf8,
+ 0xb8, 0x0c, 0xc9, 0x41, 0x2b, 0xc9, 0x80, 0x6e,
+ 0x4e, 0x1b, 0xe1, 0x20, 0xfc, 0x47, 0xa4, 0xac,
+ 0xc3, 0x3f, 0xe6, 0xc2, 0x81, 0x79, 0x03, 0x37,
+ 0x25, 0x89, 0xca, 0xd6, 0xa5, 0x46, 0x91, 0x63,
+ 0x41, 0xc5, 0x3e, 0xd5, 0xed, 0x7f, 0x4f, 0x8d,
+ 0x06, 0xc0, 0x89, 0x00, 0xbe, 0x37, 0x7b, 0x7e,
+ 0x73, 0xca, 0x70, 0x00, 0x14, 0x34, 0xbe, 0x47,
+ 0xbc, 0xb2, 0x6a, 0x28, 0xa5, 0x29, 0x84, 0xa8,
+ 0x9d, 0xc8, 0x1e, 0x77, 0x66, 0x1f, 0x9f, 0xaa,
+ 0x2b, 0x47, 0xdb, 0xdd, 0x6b, 0x9c, 0xa8, 0xfc,
+ 0x82, 0x36, 0x94, 0x62, 0x0d, 0x5c, 0x3f, 0xb2,
+ 0x01, 0xb4, 0xa5, 0xb8, 0xc6, 0x0e, 0x94, 0x5b,
+ 0xec, 0x5e, 0xbb, 0x7a, 0x63, 0x24, 0xf1, 0xf9,
+ 0xd6, 0x50, 0x08, 0xc1, 0xa3, 0xcc, 0x90, 0x07,
+ 0x5b, 0x04, 0x04, 0x42, 0x74, 0xcf, 0x37, 0xfa,
+ 0xf0, 0xa5, 0xd9, 0xd3, 0x86, 0x89, 0x89, 0x18,
+ 0xf3, 0x4c, 0xe2, 0x11, 0x02, 0x03, 0x01, 0x00,
+ 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48,
+ 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00,
+ 0x03, 0x82, 0x01, 0x01, 0x00, 0x90, 0xbb, 0xf9,
+ 0x5e, 0xba, 0x17, 0x1f, 0xac, 0x21, 0x9f, 0x6b,
+ 0x4a, 0x46, 0xd0, 0x6d, 0x3c, 0x8f, 0x3d, 0xf8,
+ 0x5e, 0x3e, 0x72, 0xaf, 0xa0, 0x1a, 0xf3, 0xff,
+ 0x89, 0xac, 0x5b, 0x7a, 0xe2, 0x91, 0x2a, 0x23,
+ 0x85, 0xc6, 0x4d, 0x47, 0x67, 0x01, 0x08, 0xa8,
+ 0x05, 0x1d, 0x01, 0x60, 0x50, 0x5f, 0x59, 0xad,
+ 0xfe, 0x7b, 0xc6, 0x0c, 0x54, 0x90, 0x68, 0x70,
+ 0x67, 0x2e, 0xed, 0x87, 0xf8, 0x69, 0x8a, 0xac,
+ 0x32, 0xfe, 0x6f, 0x90, 0x19, 0x2a, 0x64, 0x8d,
+ 0x82, 0x66, 0x05, 0x43, 0x88, 0xee, 0xf2, 0x30,
+ 0xed, 0xa4, 0x8f, 0xbf, 0xd6, 0x57, 0x20, 0xd4,
+ 0x43, 0x1d, 0x52, 0x96, 0x6f, 0xae, 0x09, 0x96,
+ 0x01, 0x52, 0x38, 0xe3, 0xaf, 0x99, 0xd7, 0xdc,
+ 0x14, 0x99, 0xc4, 0x8b, 0x0e, 0x04, 0x0f, 0xb3,
+ 0x14, 0x14, 0xd4, 0xa5, 0x93, 0xe1, 0xc9, 0x8a,
+ 0x81, 0xef, 0x63, 0xfc, 0x36, 0x77, 0x05, 0x06,
+ 0xf0, 0x2a, 0x04, 0x0a, 0xbe, 0x2e, 0xce, 0x81,
+ 0x3d, 0x23, 0xa1, 0xda, 0xd8, 0xeb, 0xc6, 0xea,
+ 0x5e, 0xcf, 0x28, 0x36, 0x51, 0x31, 0x95, 0x5e,
+ 0x40, 0x04, 0xed, 0xac, 0xc1, 0xc8, 0x56, 0x69,
+ 0x87, 0xec, 0x3b, 0x03, 0x3e, 0x9d, 0x0f, 0x4c,
+ 0x4c, 0xeb, 0xd7, 0xba, 0x26, 0xdf, 0xe3, 0xde,
+ 0x10, 0xee, 0x93, 0x62, 0x8d, 0x73, 0x52, 0x6e,
+ 0xff, 0x37, 0x36, 0x98, 0x7b, 0x2d, 0x56, 0x4c,
+ 0xba, 0x09, 0xb8, 0xa7, 0xf0, 0x3b, 0x16, 0x81,
+ 0xca, 0xdb, 0x43, 0xab, 0xec, 0x4c, 0x6e, 0x7c,
+ 0xc1, 0x0b, 0x22, 0x22, 0x43, 0x1d, 0xb6, 0x0c,
+ 0xc1, 0xb9, 0xcf, 0xe4, 0x53, 0xee, 0x1d, 0x3e,
+ 0x88, 0xa7, 0x13, 0xbe, 0x7f, 0xbd, 0xae, 0x72,
+ 0xcf, 0xcd, 0x63, 0xd2, 0xc3, 0x18, 0x58, 0x92,
+ 0xa2, 0xad, 0xb5, 0x09, 0x9d, 0x91, 0x03, 0xdd,
+ 0x3c, 0xe2, 0x1c, 0xde, 0x78, 0x00, 0x03, 0x88,
+ 0x30, 0x82, 0x03, 0x84, 0x30, 0x82, 0x02, 0x6c,
+ 0x02, 0x09, 0x00, 0xab, 0xed, 0xa6, 0xe4, 0x4a,
+ 0x2b, 0x2b, 0xf8, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05,
+ 0x05, 0x00, 0x30, 0x81, 0x86, 0x31, 0x0b, 0x30,
+ 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+ 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
+ 0x55, 0x04, 0x08, 0x0c, 0x02, 0x4e, 0x59, 0x31,
+ 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x07,
+ 0x0c, 0x08, 0x42, 0x72, 0x6f, 0x6f, 0x6b, 0x6c,
+ 0x79, 0x6e, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03,
+ 0x55, 0x04, 0x0a, 0x0c, 0x18, 0x4d, 0x79, 0x20,
+ 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63,
+ 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68,
+ 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x11, 0x30,
+ 0x0f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x08,
+ 0x6d, 0x79, 0x63, 0x61, 0x2e, 0x6f, 0x72, 0x67,
+ 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a, 0x86,
+ 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16,
+ 0x12, 0x6a, 0x76, 0x73, 0x68, 0x61, 0x68, 0x69,
+ 0x64, 0x40, 0x67, 0x6d, 0x61, 0x69, 0x6c, 0x2e,
+ 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x31,
+ 0x33, 0x30, 0x35, 0x32, 0x36, 0x32, 0x31, 0x31,
+ 0x38, 0x34, 0x30, 0x5a, 0x17, 0x0d, 0x31, 0x33,
+ 0x30, 0x36, 0x32, 0x35, 0x32, 0x31, 0x31, 0x38,
+ 0x34, 0x30, 0x5a, 0x30, 0x81, 0x80, 0x31, 0x0b,
+ 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
+ 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06,
+ 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02, 0x4e, 0x59,
+ 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04,
+ 0x07, 0x0c, 0x08, 0x42, 0x72, 0x6f, 0x6f, 0x6b,
+ 0x6c, 0x79, 0x6e, 0x31, 0x15, 0x30, 0x13, 0x06,
+ 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0c, 0x4d, 0x79,
+ 0x20, 0x43, 0x41, 0x20, 0x43, 0x6c, 0x69, 0x65,
+ 0x6e, 0x74, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03,
+ 0x55, 0x04, 0x03, 0x0c, 0x0e, 0x6d, 0x79, 0x63,
+ 0x61, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e,
+ 0x63, 0x6f, 0x6d, 0x31, 0x21, 0x30, 0x1f, 0x06,
+ 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
+ 0x09, 0x01, 0x16, 0x12, 0x6a, 0x76, 0x73, 0x68,
+ 0x61, 0x68, 0x69, 0x64, 0x40, 0x67, 0x6d, 0x61,
+ 0x69, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x82,
+ 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
+ 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05,
+ 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82,
+ 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xce,
+ 0x13, 0xf0, 0x72, 0xb0, 0x61, 0xc8, 0x18, 0x37,
+ 0x8a, 0x41, 0x3d, 0x20, 0xa1, 0x1c, 0xcb, 0xbf,
+ 0xf6, 0x3b, 0x74, 0x26, 0x2a, 0x96, 0x11, 0xec,
+ 0x53, 0xa1, 0xcc, 0x7d, 0x77, 0x56, 0x45, 0x0f,
+ 0x36, 0xb7, 0xf2, 0x48, 0x92, 0x1a, 0x62, 0xcc,
+ 0xb6, 0xc0, 0xa1, 0x2f, 0x44, 0x2b, 0xc1, 0x89,
+ 0xcb, 0x6e, 0x1e, 0xdb, 0x57, 0x92, 0xd5, 0x97,
+ 0x60, 0x8c, 0x41, 0x2c, 0xd9, 0x20, 0xfe, 0xe9,
+ 0x1f, 0x8e, 0xfc, 0x7f, 0x02, 0x44, 0x0f, 0x28,
+ 0x81, 0xd6, 0x0c, 0xcd, 0xbc, 0xf0, 0x57, 0x6c,
+ 0xcc, 0xa7, 0xba, 0x06, 0xa0, 0xa6, 0x91, 0xda,
+ 0xef, 0x46, 0x8a, 0x60, 0x0f, 0x52, 0x6c, 0x90,
+ 0x6c, 0x8c, 0x44, 0xaf, 0xb0, 0x9d, 0x90, 0xba,
+ 0x21, 0x58, 0xa0, 0x3c, 0xee, 0x54, 0xb5, 0x29,
+ 0x26, 0x1f, 0x0a, 0xac, 0xef, 0x48, 0x68, 0x33,
+ 0xd0, 0x33, 0xd0, 0x8b, 0x1a, 0xec, 0x6e, 0x2f,
+ 0xb5, 0x4a, 0x53, 0xc2, 0x1a, 0xd2, 0xf1, 0x50,
+ 0x05, 0x59, 0x5c, 0xd9, 0xda, 0x03, 0x0a, 0x47,
+ 0xb7, 0xdd, 0xf7, 0x3a, 0x69, 0xf5, 0x4e, 0xea,
+ 0x4a, 0xc2, 0xca, 0x54, 0xb0, 0x8b, 0x76, 0xe1,
+ 0x02, 0x2d, 0x52, 0x67, 0xb9, 0xdd, 0x50, 0xc9,
+ 0x3b, 0x07, 0x24, 0x22, 0x6a, 0x00, 0x1d, 0x58,
+ 0x83, 0xa8, 0xec, 0x95, 0xf1, 0xda, 0xe2, 0x73,
+ 0xa0, 0xa1, 0x72, 0x60, 0x9e, 0x86, 0x53, 0xcb,
+ 0x45, 0xa8, 0xc2, 0xa0, 0x50, 0xa0, 0x53, 0xd6,
+ 0xfc, 0x18, 0x84, 0xb5, 0x4a, 0x26, 0xd0, 0xa2,
+ 0xaa, 0xd0, 0xff, 0xb6, 0xfe, 0x3a, 0x9c, 0xb5,
+ 0x19, 0x3b, 0x3f, 0xe1, 0x48, 0x0d, 0xa4, 0x09,
+ 0x4f, 0x83, 0xc9, 0xc0, 0xc9, 0xa6, 0x0b, 0x58,
+ 0x1f, 0x1c, 0x7b, 0xac, 0xa2, 0x42, 0xbc, 0x61,
+ 0xf4, 0x21, 0x8a, 0x00, 0xda, 0x14, 0xa0, 0x60,
+ 0x03, 0xfe, 0x93, 0x12, 0x6c, 0x56, 0xcd, 0x02,
+ 0x03, 0x01, 0x00, 0x01, 0x30, 0x0d, 0x06, 0x09,
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+ 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00,
+ 0x25, 0x29, 0x3b, 0x1e, 0xc3, 0x58, 0x32, 0xe6,
+ 0x23, 0xc8, 0xee, 0x18, 0xf0, 0x1d, 0x62, 0x6d,
+ 0x3b, 0x59, 0x99, 0x3a, 0xfe, 0x49, 0x72, 0x07,
+ 0x3f, 0x58, 0x93, 0xdb, 0xc0, 0xaf, 0xb0, 0xb3,
+ 0x5c, 0xd1, 0x5c, 0x98, 0xc8, 0xea, 0x4a, 0xe4,
+ 0x58, 0x73, 0x0d, 0x57, 0xc5, 0x13, 0x7c, 0x5c,
+ 0x79, 0x66, 0xda, 0x04, 0x1d, 0xe5, 0x98, 0xda,
+ 0x35, 0x47, 0x44, 0xb0, 0xd2, 0x7a, 0x66, 0x9d,
+ 0xcd, 0x41, 0xa5, 0x8f, 0xa1, 0x11, 0xb2, 0x1a,
+ 0x87, 0xc0, 0xcd, 0x55, 0xed, 0xb4, 0x7b, 0x33,
+ 0x72, 0xeb, 0xf7, 0xe3, 0x7b, 0x8b, 0x02, 0x86,
+ 0xe9, 0x2b, 0x26, 0x32, 0x9f, 0x99, 0xf1, 0xcb,
+ 0x93, 0xab, 0xb9, 0x16, 0xb3, 0x9a, 0xb2, 0x22,
+ 0x13, 0x21, 0x1f, 0x5b, 0xcc, 0xa2, 0x59, 0xbb,
+ 0x69, 0xf2, 0xb8, 0x07, 0x80, 0xce, 0x0c, 0xf7,
+ 0x98, 0x4c, 0x85, 0xc2, 0x96, 0x6a, 0x22, 0x05,
+ 0xe9, 0xbe, 0x48, 0xb0, 0x02, 0x5b, 0x69, 0x28,
+ 0x18, 0x88, 0x96, 0xe3, 0xd7, 0xc6, 0x7a, 0xd3,
+ 0xe9, 0x99, 0xff, 0x9d, 0xc3, 0x61, 0x4d, 0x9a,
+ 0x96, 0xf2, 0xc6, 0x33, 0x4d, 0xe5, 0x5d, 0x5a,
+ 0x68, 0x64, 0x5a, 0x82, 0x35, 0x65, 0x25, 0xe3,
+ 0x8c, 0x5b, 0xb0, 0xf6, 0x96, 0x56, 0xbc, 0xbf,
+ 0x97, 0x76, 0x4b, 0x66, 0x44, 0x81, 0xa4, 0xc4,
+ 0xa7, 0x31, 0xc5, 0xa1, 0x4f, 0xe8, 0xa4, 0xca,
+ 0x20, 0xf5, 0x01, 0x5b, 0x99, 0x4f, 0x5a, 0xf4,
+ 0xf0, 0x78, 0xbf, 0x71, 0x49, 0xd5, 0xf1, 0xc1,
+ 0xa2, 0x18, 0xfd, 0x72, 0x5b, 0x16, 0xe8, 0x92,
+ 0xc7, 0x37, 0x48, 0xaf, 0xee, 0x24, 0xfc, 0x35,
+ 0x0b, 0xc2, 0xdd, 0x05, 0xc7, 0x6e, 0xa3, 0x29,
+ 0xbb, 0x29, 0x7d, 0xd3, 0x2b, 0x94, 0x80, 0xc3,
+ 0x40, 0x53, 0x0e, 0x03, 0x54, 0x3d, 0x7b, 0x8b,
+ 0xce, 0xf9, 0xa4, 0x03, 0x27, 0x63, 0xec, 0x51,
+ 0x00, 0x03, 0xe5, 0x30, 0x82, 0x03, 0xe1, 0x30,
+ 0x82, 0x02, 0xc9, 0xa0, 0x03, 0x02, 0x01, 0x02,
+ 0x02, 0x09, 0x00, 0xcc, 0x22, 0x4c, 0x4b, 0x98,
+ 0xa2, 0x88, 0xfc, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05,
+ 0x05, 0x00, 0x30, 0x81, 0x86, 0x31, 0x0b, 0x30,
+ 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+ 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
+ 0x55, 0x04, 0x08, 0x0c, 0x02, 0x4e, 0x59, 0x31,
+ 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x07,
+ 0x0c, 0x08, 0x42, 0x72, 0x6f, 0x6f, 0x6b, 0x6c,
+ 0x79, 0x6e, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03,
+ 0x55, 0x04, 0x0a, 0x0c, 0x18, 0x4d, 0x79, 0x20,
+ 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63,
+ 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68,
+ 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x11, 0x30,
+ 0x0f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x08,
+ 0x6d, 0x79, 0x63, 0x61, 0x2e, 0x6f, 0x72, 0x67,
+ 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a, 0x86,
+ 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16,
+ 0x12, 0x6a, 0x76, 0x73, 0x68, 0x61, 0x68, 0x69,
+ 0x64, 0x40, 0x67, 0x6d, 0x61, 0x69, 0x6c, 0x2e,
+ 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x31,
+ 0x33, 0x30, 0x35, 0x32, 0x36, 0x32, 0x31, 0x30,
+ 0x35, 0x30, 0x31, 0x5a, 0x17, 0x0d, 0x32, 0x33,
+ 0x30, 0x35, 0x32, 0x34, 0x32, 0x31, 0x30, 0x35,
+ 0x30, 0x31, 0x5a, 0x30, 0x81, 0x86, 0x31, 0x0b,
+ 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
+ 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06,
+ 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02, 0x4e, 0x59,
+ 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04,
+ 0x07, 0x0c, 0x08, 0x42, 0x72, 0x6f, 0x6f, 0x6b,
+ 0x6c, 0x79, 0x6e, 0x31, 0x21, 0x30, 0x1f, 0x06,
+ 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x18, 0x4d, 0x79,
+ 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69,
+ 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74,
+ 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x11,
+ 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c,
+ 0x08, 0x6d, 0x79, 0x63, 0x61, 0x2e, 0x6f, 0x72,
+ 0x67, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01,
+ 0x16, 0x12, 0x6a, 0x76, 0x73, 0x68, 0x61, 0x68,
+ 0x69, 0x64, 0x40, 0x67, 0x6d, 0x61, 0x69, 0x6c,
+ 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x82, 0x01, 0x22,
+ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+ 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03,
+ 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a,
+ 0x02, 0x82, 0x01, 0x01, 0x00, 0xf0, 0xfb, 0xad,
+ 0x80, 0x5e, 0x37, 0xd3, 0x6d, 0xee, 0x2e, 0xcc,
+ 0xbc, 0x0c, 0xd7, 0x56, 0x4b, 0x56, 0x45, 0xcd,
+ 0x28, 0xb6, 0x22, 0xe9, 0xe2, 0x0f, 0xd1, 0x87,
+ 0x2a, 0x27, 0xce, 0x77, 0x8d, 0x6e, 0x0e, 0x0f,
+ 0xfb, 0x66, 0xe1, 0xb5, 0x0e, 0x9a, 0xb6, 0x05,
+ 0x8e, 0xb3, 0xe1, 0xc5, 0x77, 0x86, 0x5b, 0x46,
+ 0xd2, 0x0b, 0x92, 0x03, 0x1b, 0x89, 0x0c, 0x1b,
+ 0x10, 0x0e, 0x99, 0x8f, 0xe2, 0x17, 0xe8, 0xc2,
+ 0x30, 0x00, 0x47, 0xd6, 0xfc, 0xf9, 0x0f, 0x3b,
+ 0x75, 0x34, 0x8d, 0x4d, 0xb0, 0x99, 0xb7, 0xa0,
+ 0x6d, 0xa0, 0xb6, 0xad, 0xda, 0x07, 0x5e, 0x38,
+ 0x2e, 0x02, 0xe4, 0x30, 0x6d, 0xae, 0x13, 0x72,
+ 0xd4, 0xc8, 0xce, 0x14, 0x07, 0xae, 0x23, 0x8c,
+ 0x8f, 0x9e, 0x8c, 0x60, 0xd6, 0x06, 0xb9, 0xef,
+ 0x00, 0x18, 0xc0, 0x1d, 0x25, 0x1e, 0xda, 0x3e,
+ 0x2f, 0xcf, 0x2b, 0x56, 0x84, 0x9e, 0x30, 0x21,
+ 0xc7, 0x29, 0xf6, 0x03, 0x8a, 0x24, 0xf9, 0x34,
+ 0xac, 0x65, 0x9d, 0x80, 0x36, 0xc8, 0x3b, 0x15,
+ 0x10, 0xbd, 0x51, 0xe9, 0xbc, 0x02, 0xe1, 0xe9,
+ 0xb3, 0x5a, 0x9a, 0x99, 0x41, 0x1b, 0x27, 0xa0,
+ 0x4d, 0x50, 0x9e, 0x27, 0x7f, 0xa1, 0x7d, 0x09,
+ 0x87, 0xbd, 0x8a, 0xca, 0x5f, 0xb1, 0xa5, 0x08,
+ 0xb8, 0x04, 0xd4, 0x52, 0x89, 0xaa, 0xe0, 0x7d,
+ 0x42, 0x2e, 0x2f, 0x15, 0xee, 0x66, 0x57, 0x0f,
+ 0x13, 0x19, 0x45, 0xa8, 0x4b, 0x5d, 0x81, 0x66,
+ 0xcc, 0x12, 0x37, 0x94, 0x5e, 0xfd, 0x3c, 0x10,
+ 0x81, 0x51, 0x3f, 0xfa, 0x0f, 0xdd, 0xa1, 0x89,
+ 0x03, 0xa9, 0x78, 0x91, 0xf5, 0x3b, 0xf3, 0xbc,
+ 0xac, 0xbe, 0x93, 0x30, 0x2e, 0xbe, 0xca, 0x7f,
+ 0x46, 0xd3, 0x28, 0xb4, 0x4e, 0x91, 0x7b, 0x5b,
+ 0x43, 0x6c, 0xaf, 0x9b, 0x5c, 0x6a, 0x6d, 0x5a,
+ 0xdb, 0x79, 0x5e, 0x6a, 0x6b, 0x02, 0x03, 0x01,
+ 0x00, 0x01, 0xa3, 0x50, 0x30, 0x4e, 0x30, 0x1d,
+ 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04,
+ 0x14, 0x6b, 0x1e, 0x00, 0xa8, 0x9f, 0xfa, 0x7d,
+ 0x00, 0xf9, 0xe0, 0x9d, 0x0f, 0x90, 0x8c, 0x90,
+ 0xa8, 0xa1, 0x37, 0x6b, 0xda, 0x30, 0x1f, 0x06,
+ 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16,
+ 0x80, 0x14, 0x6b, 0x1e, 0x00, 0xa8, 0x9f, 0xfa,
+ 0x7d, 0x00, 0xf9, 0xe0, 0x9d, 0x0f, 0x90, 0x8c,
+ 0x90, 0xa8, 0xa1, 0x37, 0x6b, 0xda, 0x30, 0x0c,
+ 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30,
+ 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, 0x09,
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+ 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00,
+ 0xcd, 0x6f, 0x73, 0x4d, 0x56, 0x0b, 0xf3, 0x2e,
+ 0x1c, 0xe2, 0x02, 0x0c, 0x14, 0xbb, 0x2f, 0xdd,
+ 0x3c, 0x43, 0xfe, 0xdf, 0x94, 0x2d, 0xa9, 0x89,
+ 0x81, 0x51, 0xf8, 0x5f, 0xa7, 0xa0, 0x13, 0xaa,
+ 0xcc, 0xb0, 0x18, 0xe2, 0x57, 0x3e, 0x0d, 0x29,
+ 0x93, 0xe8, 0x95, 0xd5, 0x1b, 0x53, 0xd2, 0x51,
+ 0xf2, 0xbd, 0xf5, 0x9e, 0x7b, 0x22, 0x65, 0x62,
+ 0x5c, 0xc4, 0x4c, 0x1d, 0xe8, 0xe9, 0xc3, 0xd4,
+ 0x2b, 0xe7, 0x78, 0xcb, 0x10, 0xf3, 0xfe, 0x06,
+ 0x83, 0xdc, 0x3a, 0x1e, 0x62, 0x10, 0xc0, 0x46,
+ 0x77, 0xc6, 0x9d, 0x9f, 0xab, 0x96, 0x25, 0x5c,
+ 0xfb, 0x26, 0xc1, 0x15, 0x1f, 0xa5, 0x33, 0xee,
+ 0x4f, 0x9a, 0x14, 0x6a, 0x14, 0x97, 0x93, 0x2b,
+ 0x95, 0x0b, 0xdc, 0xa8, 0xd7, 0x69, 0x2e, 0xf0,
+ 0x01, 0x0e, 0xfd, 0x4e, 0xd0, 0xd9, 0xa8, 0xe5,
+ 0x65, 0xde, 0xfb, 0xca, 0xca, 0x1c, 0x5f, 0xf9,
+ 0x53, 0xa0, 0x87, 0xe7, 0x33, 0x9b, 0x2f, 0xcf,
+ 0xe4, 0x13, 0xfc, 0xec, 0x7a, 0x6c, 0xb0, 0x90,
+ 0x13, 0x9b, 0xb6, 0xc5, 0x03, 0xf6, 0x0e, 0x5e,
+ 0xe2, 0xe4, 0x26, 0xc1, 0x7e, 0x53, 0xfe, 0x69,
+ 0xa3, 0xc7, 0xd8, 0x8e, 0x6e, 0x94, 0x32, 0xa0,
+ 0xde, 0xca, 0xb6, 0xcc, 0xd6, 0x01, 0xd5, 0x78,
+ 0x40, 0x28, 0x63, 0x9b, 0xee, 0xcf, 0x09, 0x3b,
+ 0x35, 0x04, 0xf0, 0x14, 0x02, 0xf6, 0x80, 0x0e,
+ 0x90, 0xb2, 0x94, 0xd2, 0x25, 0x16, 0xb8, 0x7a,
+ 0x76, 0x87, 0x84, 0x9f, 0x84, 0xc5, 0xaf, 0xc2,
+ 0x6d, 0x68, 0x7a, 0x84, 0x9c, 0xc6, 0x8a, 0x63,
+ 0x60, 0x87, 0x6a, 0x25, 0xc1, 0xa1, 0x78, 0x0f,
+ 0xba, 0xe8, 0x5f, 0xe1, 0xba, 0xac, 0xa4, 0x6f,
+ 0xdd, 0x09, 0x3f, 0x12, 0xcb, 0x1d, 0xf3, 0xcf,
+ 0x48, 0xd7, 0xd3, 0x26, 0xe8, 0x9c, 0xc3, 0x53,
+ 0xb3, 0xba, 0xdc, 0x32, 0x99, 0x98, 0x96, 0xd6,
+ 0x16, 0x03, 0x03, 0x00, 0x46, 0x10, 0x00, 0x00,
+ 0x42, 0x41, 0x04, 0x1e, 0x18, 0x37, 0xef, 0x0d,
+ 0x19, 0x51, 0x88, 0x35, 0x75, 0x71, 0xb5, 0xe5,
+ 0x54, 0x5b, 0x12, 0x2e, 0x8f, 0x09, 0x67, 0xfd,
+ 0xa7, 0x24, 0x20, 0x3e, 0xb2, 0x56, 0x1c, 0xce,
+ 0x97, 0x28, 0x5e, 0xf8, 0x2b, 0x2d, 0x4f, 0x9e,
+ 0xf1, 0x07, 0x9f, 0x6c, 0x4b, 0x5b, 0x83, 0x56,
+ 0xe2, 0x32, 0x42, 0xe9, 0x58, 0xb6, 0xd7, 0x49,
+ 0xa6, 0xb5, 0x68, 0x1a, 0x41, 0x03, 0x56, 0x6b,
+ 0xdc, 0x5a, 0x89, 0x16, 0x03, 0x03, 0x01, 0x08,
+ 0x0f, 0x00, 0x01, 0x04, 0x04, 0x01, 0x01, 0x00,
+ 0x7e, 0xe4, 0x65, 0x02, 0x8e, 0xb3, 0x34, 0x6a,
+ 0x47, 0x71, 0xd1, 0xb0, 0x8d, 0x3c, 0x0c, 0xe1,
+ 0xde, 0x7e, 0x5f, 0xb4, 0x15, 0x2d, 0x32, 0x0a,
+ 0x2a, 0xdb, 0x9b, 0x40, 0xba, 0xce, 0x8b, 0xf5,
+ 0x74, 0xc1, 0x68, 0x20, 0x7c, 0x87, 0x23, 0x13,
+ 0xc3, 0x13, 0xa7, 0xdb, 0xec, 0x59, 0xa0, 0x40,
+ 0x9e, 0x64, 0x03, 0x60, 0xac, 0x76, 0xff, 0x01,
+ 0x34, 0x7b, 0x32, 0x26, 0xd9, 0x41, 0x31, 0x93,
+ 0xaa, 0x30, 0x51, 0x83, 0x85, 0x40, 0xeb, 0x4e,
+ 0x66, 0x39, 0x83, 0xb1, 0x30, 0x0d, 0x96, 0x01,
+ 0xee, 0x81, 0x53, 0x5e, 0xec, 0xa9, 0xc9, 0xdf,
+ 0x7e, 0xc1, 0x09, 0x47, 0x8b, 0x35, 0xdb, 0x10,
+ 0x15, 0xd4, 0xc7, 0x5a, 0x39, 0xe3, 0xc0, 0xf3,
+ 0x93, 0x38, 0x11, 0xdc, 0x71, 0xbb, 0xc7, 0x62,
+ 0x2b, 0x85, 0xad, 0x6b, 0x4f, 0x09, 0xb3, 0x31,
+ 0xa8, 0xe5, 0xd1, 0xb3, 0xa9, 0x21, 0x37, 0x50,
+ 0xc8, 0x7d, 0xc3, 0xd2, 0xf7, 0x00, 0xd3, 0xdb,
+ 0x0f, 0x82, 0xf2, 0x43, 0xcf, 0x36, 0x6c, 0x98,
+ 0x63, 0xd8, 0x1d, 0xb3, 0xf3, 0xde, 0x63, 0x79,
+ 0x64, 0xf0, 0xdb, 0x46, 0x04, 0xe1, 0x1c, 0x57,
+ 0x0f, 0x9e, 0x96, 0xb9, 0x93, 0x45, 0x71, 0x1c,
+ 0x8b, 0x65, 0x7d, 0x1e, 0xad, 0xbd, 0x03, 0x51,
+ 0xae, 0x44, 0xef, 0x97, 0x45, 0x0d, 0x8d, 0x41,
+ 0x5c, 0x80, 0x7b, 0xe6, 0xe0, 0xbc, 0xa6, 0x72,
+ 0x95, 0xa0, 0x97, 0xe1, 0xbb, 0xc0, 0xcc, 0xe5,
+ 0x1e, 0xc3, 0xbe, 0xd7, 0x42, 0x2a, 0xf3, 0x75,
+ 0x8a, 0x44, 0x67, 0x3c, 0xe5, 0x68, 0x78, 0xe5,
+ 0x40, 0x1f, 0xf0, 0x89, 0x57, 0xda, 0xee, 0x45,
+ 0xf4, 0x44, 0x81, 0x01, 0x77, 0xf0, 0x4a, 0x14,
+ 0xb1, 0x3f, 0x60, 0x2b, 0xeb, 0x42, 0x38, 0xa6,
+ 0xfb, 0xe5, 0x4d, 0x71, 0xdc, 0x7d, 0x0a, 0x72,
+ 0x56, 0x28, 0x9d, 0xa6, 0x8e, 0x74, 0x2d, 0xbd,
+ 0x14, 0x03, 0x03, 0x00, 0x01, 0x01, 0x16, 0x03,
+ 0x03, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x31, 0x4d, 0x58, 0x94, 0x0b,
+ 0x0b, 0x06, 0x5f, 0xae, 0x57, 0x17, 0x98, 0x86,
+ 0xaa, 0x49, 0x17, 0x7f, 0xbd, 0x41, 0x05, 0xa5,
+ 0x74, 0x1c, 0x58, 0xc8, 0x38, 0x2d, 0x99, 0x5d,
+ 0xe5, 0x12, 0x43,
+ },
+ {
+ 0x14, 0x03, 0x03, 0x00, 0x01, 0x01, 0x16, 0x03,
+ 0x03, 0x00, 0x28, 0xf2, 0x60, 0xc2, 0x75, 0x27,
+ 0x64, 0xf4, 0x05, 0x98, 0xc9, 0xd3, 0xa8, 0x00,
+ 0x4c, 0xa0, 0x49, 0x82, 0x68, 0xf1, 0x21, 0x05,
+ 0x7b, 0x4b, 0x25, 0x3e, 0xe1, 0x5f, 0x0f, 0x84,
+ 0x26, 0x2d, 0x16, 0x2e, 0xc0, 0xfd, 0xdf, 0x0a,
+ 0xf4, 0xba, 0x19,
+ },
+ {
+ 0x17, 0x03, 0x03, 0x00, 0x1e, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x35, 0xef, 0x9d,
+ 0x6a, 0x86, 0x98, 0xc5, 0xca, 0x55, 0xca, 0x89,
+ 0x29, 0xb4, 0x55, 0xd4, 0x41, 0x08, 0x96, 0xe0,
+ 0xf3, 0x39, 0xfc, 0x15, 0x03, 0x03, 0x00, 0x1a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x02, 0x63, 0x1b, 0xaa, 0xc6, 0xc9, 0x6d, 0x72,
+ 0x24, 0x10, 0x55, 0xa9, 0x8c, 0x3b, 0x23, 0xce,
+ 0xd8, 0x4a,
+ },
+}
+
+var testClientChainCertificate = fromHex(
+ "2d2d2d2d2d424547494e2050524956415445204b" +
+ "45592d2d2d2d2d0a4d494945766749424144414e" +
+ "42676b71686b6947397730424151454641415343" +
+ "424b67776767536b41674541416f494241514367" +
+ "6f2b2f4252483269343347590a4a324f7a485846" +
+ "51706a515679386b71772b726b6e70784a706747" +
+ "6266716d31657638566b6e48496c35776c74336b" +
+ "722f367647736163416b4c4b4c313348560a776a" +
+ "726d676b493369554545734c7248573470446e35" +
+ "633544412f56625a364e3638416d78526a6f656a" +
+ "30794c6a6951514673354c41664c4a4244467954" +
+ "766a0a5a6b64587557717452506a51634749376a" +
+ "75316758794c3475417a4a5153764a6747354f47" +
+ "2b45672f45656b724d4d2f35734b4265514d334a" +
+ "596e4b317156470a6b574e427854375637583950" +
+ "6a5162416951432b4e33742b6338707741425130" +
+ "766b6538736d6f6f70536d45714a3349486e646d" +
+ "48352b714b306662335775630a715079434e7052" +
+ "694456772f7367473070626a4744705262374636" +
+ "37656d4d6b38666e5755416a426f387951423173" +
+ "4542454a307a7a6636384b585a3034614a0a6952" +
+ "6a7a544f495241674d424141454367674542414a" +
+ "4b613676326b5a3144596146786e586d7369624c" +
+ "386734426f67514c6a42307362524a6d746b6b4d" +
+ "54370a685343325873537551522f446c654d7148" +
+ "664555786731784a717579597643544d44585972" +
+ "473667354a5051744d4432465a424a7239626c65" +
+ "467138386c706a0a543766514e793571354c2b4f" +
+ "682f6b62433835436e623641753641656978776d" +
+ "2b6e77665a4f3766726b6278306d35516b715975" +
+ "5739392f452b69502b454e570a76396a68773436" +
+ "76515065563236494b79717656462b4f7362722f" +
+ "6152316138707948336361566e3579594a433346" +
+ "5855756c6f5a77516331714a6b4c434c4c0a375a" +
+ "49744f525a78514c486d4d4a654d44722f5a4942" +
+ "34675467645650636145375a4d5141714d6d3066" +
+ "4c6b6d7671723149526b77642f6831455a645650" +
+ "79320a742f6b6b43413039566336663749556575" +
+ "6f67706d705a50303130564e376b6277394a6348" +
+ "75544561564543675945417a47395679426e6d62" +
+ "6858496c57764f0a71583747524f2f5231636a2b" +
+ "6b564e35377876674b54756b35592b7a4d774a48" +
+ "32626c57435945513251753974446c476854756b" +
+ "664273385746772b6e6263460a7a6f706d535245" +
+ "6c6d464d2f6141536d464733574e5a7072696a68" +
+ "504b77726338376470636b31703131635a415478" +
+ "5a413168566d43743457616343673634690a4d74" +
+ "64507a334e2f34416147664956794d2b69624949" +
+ "35332f515543675945417953693556735a356f6a" +
+ "644a795077426e6c6142554231686f2b336b7068" +
+ "70770a7264572b2b4d796b51494a345564534437" +
+ "3052486e5a315839754359713978616671746c51" +
+ "664c44395963442f436d665264706461586c5673" +
+ "5249467a5a556c0a454630557149644e77337046" +
+ "68634f4a6d6e5a3241434470434342476f763542" +
+ "6e3068302b3137686a4b376f69315833716e4542" +
+ "7857326c7462593476556a500a44394c5330666e" +
+ "4a76703043675942504a527330714c4a4a464333" +
+ "6669796b712f57574d38727474354b364a584b50" +
+ "734b674b53644144577a7463316645434d0a7a65" +
+ "2b394a6a5a376b4d77557063666a644c2b745047" +
+ "3455563048326c524375635735414131396d7058" +
+ "50367454494733713737655a6b416e65516f6163" +
+ "41340a716c3073583051476c6a5763414e30464b" +
+ "6f4759733975582b6378445a6e7265362f52392f" +
+ "3930567766443237454c57546373677734633463" +
+ "514b42675143420a6f5432326e745a5a59396d6e" +
+ "72455a36752f492f4a332f35664e396737783733" +
+ "3177746e463745745a5361575453587364597256" +
+ "466b564f6362505135494a6f0a714a6a7249372b" +
+ "474a4d69376f6a4c69642f4c45656f31764f3163" +
+ "454158334f43723236554e38612f6c7434394f5a" +
+ "69354c337348556b756c475951755671650a6737" +
+ "6e6e4632437749544c34503645486443575a4461" +
+ "7a4136626d7375524f2b6462536e335a6c567651" +
+ "4b42674859524c5a665458536c44755264776977" +
+ "746b0a513148546b6d6b57694156726c4f577864" +
+ "5858456d546130303045574c46446145797a7358" +
+ "7834424863357166776b5a4e746b634a56396e58" +
+ "63536e647441530a35767a427a676e797a4f7962" +
+ "68315878484a3966427472414f3847555878446c" +
+ "6634394457616753393449763072596e616b7656" +
+ "2f673039786875415763366e0a5365757230576b" +
+ "5376453847666653734d485149584c456b0a2d2d" +
+ "2d2d2d454e442050524956415445204b45592d2d" +
+ "2d2d2d0a2d2d2d2d2d424547494e204345525449" +
+ "4649434154452d2d2d2d2d0a4d494944656a4343" +
+ "416d494343514330523168584b326649776a414e" +
+ "42676b71686b6947397730424151554641444342" +
+ "6744454c4d416b474131554542684d430a56564d" +
+ "78437a414a42674e564241674d416b355a4d5245" +
+ "77447759445651514844416843636d3976613278" +
+ "35626a45564d424d47413155454367774d54586b" +
+ "670a51304567513278705a5735304d5263774651" +
+ "5944565151444441357465574e68593278705a57" +
+ "35304c6d4e76625445684d423847435371475349" +
+ "62334451454a0a41525953616e5a7a6147466f61" +
+ "5752415a32316861577775593239744d42345844" +
+ "54457a4d4455794e6a49784e4451774d466f5844" +
+ "54457a4d4459794e5449780a4e4451774d466f77" +
+ "6654454c4d416b474131554542684d4356564d78" +
+ "4554415042674e564241674d4345356c6479425a" +
+ "62334a724d52457744775944565151480a444168" +
+ "43636d397661327835626a45514d413447413155" +
+ "454367774854586b67544756685a6a45544d4245" +
+ "47413155454177774b62586c735a57466d4c6d4e" +
+ "760a625445684d42384743537147534962334451" +
+ "454a41525953616e5a7a6147466f615752415a32" +
+ "316861577775593239744d494942496a414e4267" +
+ "6b71686b69470a397730424151454641414f4341" +
+ "5138414d49494243674b43415145416f4b507677" +
+ "5552396f754e786d43646a73783178554b593046" +
+ "63764a4b735071354a36630a536159426d333670" +
+ "7458722f465a4a78794a65634a6264354b2f2b72" +
+ "7872476e414a43796939647831634936356f4a43" +
+ "4e346c42424c43367831754b51352b580a4f5177" +
+ "50315732656a6576414a73555936486f394d6934" +
+ "346b4542624f5377487979515178636b3734325a" +
+ "4856376c7172555434304842694f343774594638" +
+ "690a2b4c674d7955457279594275546876684950" +
+ "7848704b7a44502b624367586b444e79574a7974" +
+ "616c5270466a5163552b3165312f543430477749" +
+ "6b41766a64370a666e504b634141554e4c354876" +
+ "4c4a714b4b5570684b6964794235335a682b6671" +
+ "697448323931726e4b6a38676a61555967316350" +
+ "374942744b5734786736550a572b78657533706a" +
+ "4a504835316c41497761504d6b41646242415243" +
+ "644d38332b76436c32644f4769596b5938307a69" +
+ "45514944415141424d413047435371470a534962" +
+ "3344514542425155414134494241514351752f6c" +
+ "65756863667243476661307047304730386a7a33" +
+ "34586a357972364161382f2b4a72467436347045" +
+ "710a493458475455646e4151696f425230425946" +
+ "42665761332b6538594d564a426f634763753759" +
+ "6634615971734d7635766b426b715a4932435a67" +
+ "5644694f37790a4d4f326b6a372f575679445551" +
+ "7831536c6d2b75435a5942556a6a6a72356e5833" +
+ "42535a7849734f42412b7a46425455705a506879" +
+ "597142373250384e6e63460a427641714241712b" +
+ "4c73364250534f6832746a72787570657a796732" +
+ "55544756586b414537617a4279465a70682b7737" +
+ "417a36644430784d363965364a742f6a0a336844" +
+ "756b324b4e63314a752f7a63326d487374566b79" +
+ "364362696e384473576763726251367673544735" +
+ "3877517369496b4d6474677a4275632f6b552b34" +
+ "640a506f696e4537352f766135797a38316a3073" +
+ "4d59574a4b697262554a6e5a454433547a69484e" +
+ "35340a2d2d2d2d2d454e44204345525449464943" +
+ "4154452d2d2d2d2d0a2d2d2d2d2d424547494e20" +
+ "43455254494649434154452d2d2d2d2d0a4d4949" +
+ "4468444343416d7743435143723761626b536973" +
+ "722b44414e42676b71686b694739773042415155" +
+ "4641444342686a454c4d416b474131554542684d" +
+ "430a56564d78437a414a42674e564241674d416b" +
+ "355a4d524577447759445651514844416843636d" +
+ "397661327835626a45684d423847413155454367" +
+ "775954586b670a5132567964476c6d61574e6864" +
+ "4755675158563061473979615852354d52457744" +
+ "775944565151444441687465574e684c6d39795a" +
+ "7a45684d423847435371470a534962334451454a" +
+ "41525953616e5a7a6147466f615752415a323168" +
+ "61577775593239744d4234584454457a4d445579" +
+ "4e6a49784d5467304d466f584454457a0a4d4459" +
+ "794e5449784d5467304d466f7767594178437a41" +
+ "4a42674e5642415954416c56544d517377435159" +
+ "445651514944414a4f575445524d413847413155" +
+ "450a42777749516e4a7662327473655734784654" +
+ "415442674e5642416f4d4445313549454e424945" +
+ "4e7361575675644445584d425547413155454177" +
+ "774f62586c6a0a59574e73615756756443356a62" +
+ "3230784954416642676b71686b69473977304243" +
+ "514557456d70326332686861476c6b5147647459" +
+ "576c734c6d4e76625443430a415349774451594a" +
+ "4b6f5a496876634e415145424251414467674550" +
+ "4144434341516f4367674542414d345438484b77" +
+ "596367594e34704250534368484d752f0a396a74" +
+ "304a697157456578546f63783964315a46447a61" +
+ "33386b6953476d4c4d747343684c30517277596e" +
+ "4c6268376256354c566c32434d51537a5a495037" +
+ "700a4834373866774a454479694231677a4e7650" +
+ "4258624d796e75676167707048613730614b5941" +
+ "3953624a42736a455376734a3251756946596f44" +
+ "7a75564c55700a4a68384b724f3949614450514d" +
+ "39434c477578754c37564b553849613076465142" +
+ "566c6332646f44436b6533336663366166564f36" +
+ "6b7243796c5377693362680a416931535a376e64" +
+ "554d6b37427951696167416457494f6f374a5878" +
+ "32754a7a6f4b4679594a364755387446714d4b67" +
+ "554b425431767759684c564b4a7443690a717444" +
+ "2f747634366e4c555a4f7a2f685341326b43552b" +
+ "447963444a7067745948787837724b4a43764748" +
+ "3049596f41326853675941502b6b784a73567330" +
+ "430a417745414154414e42676b71686b69473977" +
+ "30424151554641414f43415145414a536b374873" +
+ "4e594d75596a794f3459384231696254745a6d54" +
+ "722b535849480a5031695432384376734c4e6330" +
+ "567959794f704b3546687a445666464533786365" +
+ "5762614242336c6d4e6f3152305377306e706d6e" +
+ "63314270592b68456249610a6838444e56653230" +
+ "657a4e79362f666a6534734368756b724a6a4b66" +
+ "6d66484c6b36753546724f617369495449523962" +
+ "7a4b4a5a75326e79754165417a677a330a6d4579" +
+ "4677705a7149675870766b6977416c74704b4269" +
+ "496c755058786e7254365a6e2f6e634e68545a71" +
+ "573873597a54655664576d686b576f49315a5358" +
+ "6a0a6a46757739705a57764c2b58646b746d5249" +
+ "476b784b637878614650364b544b495055425735" +
+ "6c5057765477654c397853645878776149592f58" +
+ "4a62467569530a787a6449722b346b2f44554c77" +
+ "7430467832366a4b62737066644d726c49444451" +
+ "464d4f413151396534764f2b6151444a32507355" +
+ "513d3d0a2d2d2d2d2d454e442043455254494649" +
+ "434154452d2d2d2d2d0a2d2d2d2d2d424547494e" +
+ "2043455254494649434154452d2d2d2d2d0a4d49" +
+ "49443454434341736d67417749424167494a414d" +
+ "7769544575596f6f6a384d413047435371475349" +
+ "623344514542425155414d4947474d5173774351" +
+ "59440a5651514745774a56557a454c4d416b4741" +
+ "31554543417743546c6b784554415042674e5642" +
+ "41634d43454a796232397262486c754d53457748" +
+ "7759445651514b0a4442684e655342445a584a30" +
+ "61575a70593246305a5342426458526f62334a70" +
+ "64486b784554415042674e5642414d4d43473135" +
+ "5932457562334a6e4d5345770a4877594a4b6f5a" +
+ "496876634e41516b4246684a71646e4e6f595768" +
+ "705a45426e625746706243356a62323077486863" +
+ "4e4d544d774e5449324d6a45774e5441780a5768" +
+ "634e4d6a4d774e5449304d6a45774e544178576a" +
+ "4342686a454c4d416b474131554542684d435656" +
+ "4d78437a414a42674e564241674d416b355a4d52" +
+ "45770a447759445651514844416843636d397661" +
+ "327835626a45684d423847413155454367775954" +
+ "586b675132567964476c6d61574e686447556751" +
+ "585630614739790a615852354d52457744775944" +
+ "565151444441687465574e684c6d39795a7a4568" +
+ "4d42384743537147534962334451454a41525953" +
+ "616e5a7a6147466f615752410a5a323168615777" +
+ "75593239744d494942496a414e42676b71686b69" +
+ "47397730424151454641414f43415138414d4949" +
+ "4243674b434151454138507574674634330a3032" +
+ "33754c737938444e645753315a467a5369324975" +
+ "6e69443947484b69664f6434317544672f375a75" +
+ "4731447071324259367a34635633686c74473067" +
+ "75530a4178754a4442735144706d503468666f77" +
+ "6a4141523962382b5138376454534e5462435a74" +
+ "3642746f4c6174326764654f4334433544427472" +
+ "684e79314d6a4f0a46416575493479506e6f7867" +
+ "31676135377741597742306c48746f2b4c383872" +
+ "566f53654d4348484b665944696954354e4b786c" +
+ "6e59413279447356454c31520a3662774334656d" +
+ "7a5770715a5152736e6f4531516e69642f6f5830" +
+ "4a6837324b796c2b7870516934424e5253696172" +
+ "67665549754c7858755a6c635045786c460a7145" +
+ "74646757624d456a65555876303845494652502f" +
+ "6f503361474a41366c346b665537383779737670" +
+ "4d774c72374b663062544b4c524f6b5874625132" +
+ "79760a6d31787162567262655635716177494441" +
+ "5141426f314177546a416442674e564851344546" +
+ "67515561783441714a2f3666514435344a30506b" +
+ "497951714b45330a61396f77487759445652306a" +
+ "42426777466f415561783441714a2f3666514435" +
+ "344a30506b497951714b453361396f7744415944" +
+ "5652305442415577417745420a2f7a414e42676b" +
+ "71686b6947397730424151554641414f43415145" +
+ "417a57397a5456594c387934633467494d464c73" +
+ "76335478442f742b554c616d4a675648340a5836" +
+ "65674536724d73426a69567a344e4b5a506f6c64" +
+ "556255394a52387233316e6e73695a574a637845" +
+ "7764364f6e443143766e654d7351382f34476739" +
+ "77360a486d495177455a33787032667135596c58" +
+ "50736d775255667054507554356f55616853586b" +
+ "7975564339796f31326b753841454f2f55375132" +
+ "616a6c5a6437370a79736f63582f6c546f49666e" +
+ "4d3573767a2b51542f4f7836624c435145357532" +
+ "78515032446c376935436242666c502b61615048" +
+ "324935756c444b67337371320a7a4e5942315868" +
+ "414b474f623773384a4f7a554538425143396f41" +
+ "4f6b4c4b55306955577548703268345366684d57" +
+ "76776d316f656f5363786f706a594964710a4a63" +
+ "476865412b3636462f687571796b6239304a5078" +
+ "4c4c48665050534e66544a75696377314f7a7574" +
+ "77796d5a695731673d3d0a2d2d2d2d2d454e4420" +
+ "43455254494649434154452d2d2d2d2d0a",
+)
+
+// Script of interaction with openssl implementation:
+//
+// openssl s_server -cipher ECDHE-ECDSA-AES128-SHA \
+// -key server.key -cert server.crt -port 10443
+//
+// The values for this test are obtained by building and running in client mode:
+// % go test -test.run "TestRunClient" -connect -ciphersuites=0xc009
+// The recorded bytes are written to stdout.
+//
+// The server private key is:
+//
+// -----BEGIN EC PARAMETERS-----
+// BgUrgQQAIw==
+// -----END EC PARAMETERS-----
+// -----BEGIN EC PRIVATE KEY-----
+// MIHcAgEBBEIBmIPpCa0Kyeo9M/nq5mHxeFIGlw+MqakWcvHu3Keo7xK9ZWG7JG3a
+// XfS01efjqSZJvF2DoL+Sly4A5iBn0Me9mdegBwYFK4EEACOhgYkDgYYABADEoe2+
+// mPkLSHM2fsMWVhEi8j1TwztNIT3Na3Xm9rDcmt8mwbyyh/ByMnyzZC8ckLzqaCMQ
+// fv7jJcBIOmngKG3TNwDvBGLdDaCccGKD2IHTZDGqnpcxvZawaMCbI952ZD8aXH/p
+// Eg5YWLZfcN2b2OrV1/XVzLm2nzBmW2aaIOIn5b/+Ow==
+// -----END EC PRIVATE KEY-----
+//
+// and certificate is:
+//
+// -----BEGIN CERTIFICATE-----
+// MIICADCCAWICCQC4vy1HoNLr9DAJBgcqhkjOPQQBMEUxCzAJBgNVBAYTAkFVMRMw
+// EQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0
+// eSBMdGQwHhcNMTIxMTIyMTUwNjMyWhcNMjIxMTIwMTUwNjMyWjBFMQswCQYDVQQG
+// EwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lk
+// Z2l0cyBQdHkgTHRkMIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQAxKHtvpj5C0hz
+// Nn7DFlYRIvI9U8M7TSE9zWt15vaw3JrfJsG8sofwcjJ8s2QvHJC86mgjEH7+4yXA
+// SDpp4Cht0zcA7wRi3Q2gnHBig9iB02Qxqp6XMb2WsGjAmyPedmQ/Glx/6RIOWFi2
+// X3Ddm9jq1df11cy5tp8wZltmmiDiJ+W//jswCQYHKoZIzj0EAQOBjAAwgYgCQgGI
+// ok/r4kXFSH0brPXtmJ2uR3DAXhu2L73xtk23YUDTEaLO7gt+kn7/dp3DO36lP876
+// EOJZ7EctfKzaTpcOFaBv0AJCAU38vmcTnC0FDr0/o4wlwTMTgw2UBrvUN3r27HrJ
+// hi7d1xFpf4V8Vt77MXgr5Md4Da7Lvp5ONiQxe2oPOZUSB48q
+// -----END CERTIFICATE-----
+var ecdheECDSAAESClientScript = [][]byte{
+ {
+ 0x16, 0x03, 0x01, 0x00, 0x4a, 0x01, 0x00, 0x00,
+ 0x46, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xc0, 0x09,
+ 0x01, 0x00, 0x00, 0x1b, 0x00, 0x05, 0x00, 0x05,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00,
+ 0x08, 0x00, 0x06, 0x00, 0x17, 0x00, 0x18, 0x00,
+ 0x19, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00,
+ },
+ {
+ 0x16, 0x03, 0x01, 0x00, 0x54, 0x02, 0x00, 0x00,
+ 0x50, 0x03, 0x01, 0x50, 0xd7, 0x19, 0xc9, 0x03,
+ 0xc2, 0x3a, 0xc6, 0x1f, 0x0a, 0x84, 0x9e, 0xd7,
+ 0xf4, 0x7e, 0x07, 0x6d, 0xa8, 0xe4, 0xa9, 0x4f,
+ 0x22, 0x50, 0xa2, 0x19, 0x24, 0x44, 0x42, 0x65,
+ 0xaa, 0xba, 0x3a, 0x20, 0x90, 0x70, 0xb7, 0xe5,
+ 0x57, 0xed, 0xb1, 0xb1, 0x43, 0x4b, 0xa1, 0x4e,
+ 0xee, 0x7a, 0x5b, 0x88, 0xf6, 0xa6, 0x73, 0x3b,
+ 0xcb, 0xa7, 0xbd, 0x57, 0x50, 0xf2, 0x72, 0x8c,
+ 0xbc, 0x45, 0x73, 0xaa, 0xc0, 0x09, 0x00, 0x00,
+ 0x08, 0x00, 0x0b, 0x00, 0x04, 0x03, 0x00, 0x01,
+ 0x02, 0x16, 0x03, 0x01, 0x02, 0x0e, 0x0b, 0x00,
+ 0x02, 0x0a, 0x00, 0x02, 0x07, 0x00, 0x02, 0x04,
+ 0x30, 0x82, 0x02, 0x00, 0x30, 0x82, 0x01, 0x62,
+ 0x02, 0x09, 0x00, 0xb8, 0xbf, 0x2d, 0x47, 0xa0,
+ 0xd2, 0xeb, 0xf4, 0x30, 0x09, 0x06, 0x07, 0x2a,
+ 0x86, 0x48, 0xce, 0x3d, 0x04, 0x01, 0x30, 0x45,
+ 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
+ 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30,
+ 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a,
+ 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61,
+ 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03,
+ 0x55, 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74,
+ 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69,
+ 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74,
+ 0x79, 0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e, 0x17,
+ 0x0d, 0x31, 0x32, 0x31, 0x31, 0x32, 0x32, 0x31,
+ 0x35, 0x30, 0x36, 0x33, 0x32, 0x5a, 0x17, 0x0d,
+ 0x32, 0x32, 0x31, 0x31, 0x32, 0x30, 0x31, 0x35,
+ 0x30, 0x36, 0x33, 0x32, 0x5a, 0x30, 0x45, 0x31,
+ 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+ 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11,
+ 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53,
+ 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74,
+ 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55,
+ 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65,
+ 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64,
+ 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79,
+ 0x20, 0x4c, 0x74, 0x64, 0x30, 0x81, 0x9b, 0x30,
+ 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d,
+ 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00,
+ 0x23, 0x03, 0x81, 0x86, 0x00, 0x04, 0x00, 0xc4,
+ 0xa1, 0xed, 0xbe, 0x98, 0xf9, 0x0b, 0x48, 0x73,
+ 0x36, 0x7e, 0xc3, 0x16, 0x56, 0x11, 0x22, 0xf2,
+ 0x3d, 0x53, 0xc3, 0x3b, 0x4d, 0x21, 0x3d, 0xcd,
+ 0x6b, 0x75, 0xe6, 0xf6, 0xb0, 0xdc, 0x9a, 0xdf,
+ 0x26, 0xc1, 0xbc, 0xb2, 0x87, 0xf0, 0x72, 0x32,
+ 0x7c, 0xb3, 0x64, 0x2f, 0x1c, 0x90, 0xbc, 0xea,
+ 0x68, 0x23, 0x10, 0x7e, 0xfe, 0xe3, 0x25, 0xc0,
+ 0x48, 0x3a, 0x69, 0xe0, 0x28, 0x6d, 0xd3, 0x37,
+ 0x00, 0xef, 0x04, 0x62, 0xdd, 0x0d, 0xa0, 0x9c,
+ 0x70, 0x62, 0x83, 0xd8, 0x81, 0xd3, 0x64, 0x31,
+ 0xaa, 0x9e, 0x97, 0x31, 0xbd, 0x96, 0xb0, 0x68,
+ 0xc0, 0x9b, 0x23, 0xde, 0x76, 0x64, 0x3f, 0x1a,
+ 0x5c, 0x7f, 0xe9, 0x12, 0x0e, 0x58, 0x58, 0xb6,
+ 0x5f, 0x70, 0xdd, 0x9b, 0xd8, 0xea, 0xd5, 0xd7,
+ 0xf5, 0xd5, 0xcc, 0xb9, 0xb6, 0x9f, 0x30, 0x66,
+ 0x5b, 0x66, 0x9a, 0x20, 0xe2, 0x27, 0xe5, 0xbf,
+ 0xfe, 0x3b, 0x30, 0x09, 0x06, 0x07, 0x2a, 0x86,
+ 0x48, 0xce, 0x3d, 0x04, 0x01, 0x03, 0x81, 0x8c,
+ 0x00, 0x30, 0x81, 0x88, 0x02, 0x42, 0x01, 0x88,
+ 0xa2, 0x4f, 0xeb, 0xe2, 0x45, 0xc5, 0x48, 0x7d,
+ 0x1b, 0xac, 0xf5, 0xed, 0x98, 0x9d, 0xae, 0x47,
+ 0x70, 0xc0, 0x5e, 0x1b, 0xb6, 0x2f, 0xbd, 0xf1,
+ 0xb6, 0x4d, 0xb7, 0x61, 0x40, 0xd3, 0x11, 0xa2,
+ 0xce, 0xee, 0x0b, 0x7e, 0x92, 0x7e, 0xff, 0x76,
+ 0x9d, 0xc3, 0x3b, 0x7e, 0xa5, 0x3f, 0xce, 0xfa,
+ 0x10, 0xe2, 0x59, 0xec, 0x47, 0x2d, 0x7c, 0xac,
+ 0xda, 0x4e, 0x97, 0x0e, 0x15, 0xa0, 0x6f, 0xd0,
+ 0x02, 0x42, 0x01, 0x4d, 0xfc, 0xbe, 0x67, 0x13,
+ 0x9c, 0x2d, 0x05, 0x0e, 0xbd, 0x3f, 0xa3, 0x8c,
+ 0x25, 0xc1, 0x33, 0x13, 0x83, 0x0d, 0x94, 0x06,
+ 0xbb, 0xd4, 0x37, 0x7a, 0xf6, 0xec, 0x7a, 0xc9,
+ 0x86, 0x2e, 0xdd, 0xd7, 0x11, 0x69, 0x7f, 0x85,
+ 0x7c, 0x56, 0xde, 0xfb, 0x31, 0x78, 0x2b, 0xe4,
+ 0xc7, 0x78, 0x0d, 0xae, 0xcb, 0xbe, 0x9e, 0x4e,
+ 0x36, 0x24, 0x31, 0x7b, 0x6a, 0x0f, 0x39, 0x95,
+ 0x12, 0x07, 0x8f, 0x2a, 0x16, 0x03, 0x01, 0x00,
+ 0xd6, 0x0c, 0x00, 0x00, 0xd2, 0x03, 0x00, 0x17,
+ 0x41, 0x04, 0x33, 0xed, 0xe1, 0x10, 0x3d, 0xe2,
+ 0xb0, 0x81, 0x5e, 0x01, 0x1b, 0x00, 0x4a, 0x7d,
+ 0xdc, 0xc5, 0x78, 0x02, 0xb1, 0x9a, 0x78, 0x92,
+ 0x34, 0xd9, 0x23, 0xcc, 0x01, 0xfb, 0x0c, 0x49,
+ 0x1c, 0x4a, 0x59, 0x8a, 0x80, 0x1b, 0x34, 0xf0,
+ 0xe8, 0x87, 0x1b, 0x7c, 0xfb, 0x72, 0xf5, 0xea,
+ 0xf9, 0xf3, 0xff, 0xa6, 0x3e, 0x4e, 0xac, 0xbc,
+ 0xee, 0x14, 0x2b, 0x87, 0xd4, 0x0b, 0xda, 0x19,
+ 0x60, 0x2b, 0x00, 0x8b, 0x30, 0x81, 0x88, 0x02,
+ 0x42, 0x01, 0x75, 0x46, 0x4f, 0x97, 0x9f, 0xc5,
+ 0xf9, 0x4c, 0x38, 0xcf, 0x3b, 0x37, 0x1a, 0x6b,
+ 0x53, 0xfc, 0x05, 0x73, 0x7d, 0x98, 0x2c, 0x5b,
+ 0x76, 0xd4, 0x37, 0x1f, 0x50, 0x6d, 0xad, 0xc6,
+ 0x0f, 0x8f, 0x7b, 0xcc, 0x60, 0x8e, 0x04, 0x00,
+ 0x21, 0x80, 0xa8, 0xa5, 0x98, 0xf2, 0x42, 0xf2,
+ 0xc3, 0xf6, 0x44, 0x50, 0xc4, 0x7a, 0xae, 0x6f,
+ 0x74, 0xa0, 0x7f, 0x07, 0x7a, 0x0b, 0xbb, 0x41,
+ 0x9e, 0x3c, 0x0b, 0x02, 0x42, 0x01, 0xbe, 0x64,
+ 0xaa, 0x12, 0x03, 0xfb, 0xd8, 0x4f, 0x93, 0xf9,
+ 0x92, 0x54, 0x0d, 0x9c, 0x9d, 0x53, 0x88, 0x19,
+ 0x69, 0x94, 0xfc, 0xd6, 0xf7, 0x60, 0xcf, 0x70,
+ 0x64, 0x15, 0x1b, 0x02, 0x22, 0x56, 0xb0, 0x2c,
+ 0xb1, 0x72, 0x4c, 0x9e, 0x7b, 0xf0, 0x53, 0x97,
+ 0x43, 0xac, 0x11, 0x62, 0xe5, 0x5a, 0xf1, 0x7e,
+ 0x87, 0x8f, 0x5c, 0x43, 0x1d, 0xae, 0x56, 0x28,
+ 0xdb, 0x76, 0x15, 0xd8, 0x1c, 0x73, 0xce, 0x16,
+ 0x03, 0x01, 0x00, 0x04, 0x0e, 0x00, 0x00, 0x00,
+ },
+ {
+ 0x16, 0x03, 0x01, 0x00, 0x46, 0x10, 0x00, 0x00,
+ 0x42, 0x41, 0x04, 0x1e, 0x18, 0x37, 0xef, 0x0d,
+ 0x19, 0x51, 0x88, 0x35, 0x75, 0x71, 0xb5, 0xe5,
+ 0x54, 0x5b, 0x12, 0x2e, 0x8f, 0x09, 0x67, 0xfd,
+ 0xa7, 0x24, 0x20, 0x3e, 0xb2, 0x56, 0x1c, 0xce,
+ 0x97, 0x28, 0x5e, 0xf8, 0x2b, 0x2d, 0x4f, 0x9e,
+ 0xf1, 0x07, 0x9f, 0x6c, 0x4b, 0x5b, 0x83, 0x56,
+ 0xe2, 0x32, 0x42, 0xe9, 0x58, 0xb6, 0xd7, 0x49,
+ 0xa6, 0xb5, 0x68, 0x1a, 0x41, 0x03, 0x56, 0x6b,
+ 0xdc, 0x5a, 0x89, 0x14, 0x03, 0x01, 0x00, 0x01,
+ 0x01, 0x16, 0x03, 0x01, 0x00, 0x30, 0x1a, 0x45,
+ 0x92, 0x3b, 0xac, 0x8d, 0x91, 0x89, 0xd3, 0x2c,
+ 0xf4, 0x3c, 0x5f, 0x70, 0xf1, 0x79, 0xa5, 0x6a,
+ 0xcf, 0x97, 0x8f, 0x3f, 0x73, 0x08, 0xca, 0x3f,
+ 0x55, 0xb0, 0x28, 0xd1, 0x6f, 0xcd, 0x9b, 0xca,
+ 0xb6, 0xb7, 0xd0, 0xa5, 0x21, 0x5b, 0x08, 0xf8,
+ 0x42, 0xe2, 0xdf, 0x25, 0x6a, 0x16,
+ },
+ {
+ 0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03,
+ 0x01, 0x00, 0x30, 0x30, 0x83, 0xb6, 0x51, 0x8a,
+ 0x85, 0x4a, 0xee, 0xe4, 0xb6, 0xae, 0xf3, 0xc1,
+ 0xdc, 0xd2, 0x04, 0xb3, 0xd0, 0x25, 0x47, 0x5f,
+ 0xac, 0x83, 0xa3, 0x7d, 0xcf, 0x47, 0x92, 0xed,
+ 0x92, 0x6c, 0xd1, 0x6e, 0xfd, 0x63, 0xf5, 0x2d,
+ 0x89, 0xd8, 0x04, 0x8c, 0x62, 0x71, 0xae, 0x5e,
+ 0x32, 0x48, 0xf8,
+ },
+ {
+ 0x17, 0x03, 0x01, 0x00, 0x20, 0xcf, 0x5e, 0xba,
+ 0xf4, 0x47, 0x32, 0x35, 0x9b, 0x85, 0xdc, 0xb3,
+ 0xff, 0x77, 0x90, 0xd9, 0x2b, 0xbd, 0x59, 0x2a,
+ 0x33, 0xe4, 0x6e, 0x9b, 0xfc, 0x1c, 0x73, 0x3f,
+ 0x5e, 0x1e, 0xe3, 0xa4, 0xc2, 0x17, 0x03, 0x01,
+ 0x00, 0x20, 0x05, 0xdf, 0x2d, 0x9b, 0x29, 0x7f,
+ 0x97, 0xcd, 0x49, 0x04, 0x53, 0x22, 0x1a, 0xa1,
+ 0xa1, 0xe6, 0x38, 0x3a, 0x56, 0x37, 0x1f, 0xd8,
+ 0x3a, 0x12, 0x2c, 0xf0, 0xeb, 0x61, 0x35, 0x76,
+ 0xe5, 0xf0, 0x15, 0x03, 0x01, 0x00, 0x20, 0xa5,
+ 0x56, 0xb5, 0x49, 0x4b, 0xc2, 0xd4, 0x4c, 0xf6,
+ 0x95, 0x15, 0x7d, 0x41, 0x1d, 0x5c, 0x00, 0x0e,
+ 0x20, 0xb1, 0x0a, 0xbc, 0xc9, 0x2a, 0x09, 0x17,
+ 0xb4, 0xaa, 0x1c, 0x79, 0xda, 0x79, 0x27,
+ },
+}
diff --git a/libgo/go/crypto/tls/handshake_messages.go b/libgo/go/crypto/tls/handshake_messages.go
index cdd49170777..83952000f6e 100644
--- a/libgo/go/crypto/tls/handshake_messages.go
+++ b/libgo/go/crypto/tls/handshake_messages.go
@@ -20,6 +20,7 @@ type clientHelloMsg struct {
supportedPoints []uint8
ticketSupported bool
sessionTicket []uint8
+ signatureAndHashes []signatureAndHash
}
func (m *clientHelloMsg) equal(i interface{}) bool {
@@ -40,7 +41,8 @@ func (m *clientHelloMsg) equal(i interface{}) bool {
eqUint16s(m.supportedCurves, m1.supportedCurves) &&
bytes.Equal(m.supportedPoints, m1.supportedPoints) &&
m.ticketSupported == m1.ticketSupported &&
- bytes.Equal(m.sessionTicket, m1.sessionTicket)
+ bytes.Equal(m.sessionTicket, m1.sessionTicket) &&
+ eqSignatureAndHashes(m.signatureAndHashes, m1.signatureAndHashes)
}
func (m *clientHelloMsg) marshal() []byte {
@@ -74,6 +76,10 @@ func (m *clientHelloMsg) marshal() []byte {
extensionsLength += len(m.sessionTicket)
numExtensions++
}
+ if len(m.signatureAndHashes) > 0 {
+ extensionsLength += 2 + 2*len(m.signatureAndHashes)
+ numExtensions++
+ }
if numExtensions > 0 {
extensionsLength += 4 * numExtensions
length += 2 + extensionsLength
@@ -199,6 +205,25 @@ func (m *clientHelloMsg) marshal() []byte {
copy(z, m.sessionTicket)
z = z[len(m.sessionTicket):]
}
+ if len(m.signatureAndHashes) > 0 {
+ // https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
+ z[0] = byte(extensionSignatureAlgorithms >> 8)
+ z[1] = byte(extensionSignatureAlgorithms)
+ l := 2 + 2*len(m.signatureAndHashes)
+ z[2] = byte(l >> 8)
+ z[3] = byte(l)
+ z = z[4:]
+
+ l -= 2
+ z[0] = byte(l >> 8)
+ z[1] = byte(l)
+ z = z[2:]
+ for _, sigAndHash := range m.signatureAndHashes {
+ z[0] = sigAndHash.hash
+ z[1] = sigAndHash.signature
+ z = z[2:]
+ }
+ }
m.raw = x
@@ -249,6 +274,7 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool {
m.ocspStapling = false
m.ticketSupported = false
m.sessionTicket = nil
+ m.signatureAndHashes = nil
if len(data) == 0 {
// ClientHello is optionally followed by extension data
@@ -336,6 +362,23 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool {
// http://tools.ietf.org/html/rfc5077#section-3.2
m.ticketSupported = true
m.sessionTicket = data[:length]
+ case extensionSignatureAlgorithms:
+ // https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
+ if length < 2 || length&1 != 0 {
+ return false
+ }
+ l := int(data[0])<<8 | int(data[1])
+ if l != length-2 {
+ return false
+ }
+ n := l / 2
+ d := data[2:]
+ m.signatureAndHashes = make([]signatureAndHash, n)
+ for i := range m.signatureAndHashes {
+ m.signatureAndHashes[i].hash = d[0]
+ m.signatureAndHashes[i].signature = d[1]
+ d = d[2:]
+ }
}
data = data[length:]
}
@@ -899,8 +942,14 @@ func (m *nextProtoMsg) unmarshal(data []byte) bool {
}
type certificateRequestMsg struct {
- raw []byte
+ raw []byte
+ // hasSignatureAndHash indicates whether this message includes a list
+ // of signature and hash functions. This change was introduced with TLS
+ // 1.2.
+ hasSignatureAndHash bool
+
certificateTypes []byte
+ signatureAndHashes []signatureAndHash
certificateAuthorities [][]byte
}
@@ -912,7 +961,8 @@ func (m *certificateRequestMsg) equal(i interface{}) bool {
return bytes.Equal(m.raw, m1.raw) &&
bytes.Equal(m.certificateTypes, m1.certificateTypes) &&
- eqByteSlices(m.certificateAuthorities, m1.certificateAuthorities)
+ eqByteSlices(m.certificateAuthorities, m1.certificateAuthorities) &&
+ eqSignatureAndHashes(m.signatureAndHashes, m1.signatureAndHashes)
}
func (m *certificateRequestMsg) marshal() (x []byte) {
@@ -928,6 +978,10 @@ func (m *certificateRequestMsg) marshal() (x []byte) {
}
length += casLength
+ if m.hasSignatureAndHash {
+ length += 2 + 2*len(m.signatureAndHashes)
+ }
+
x = make([]byte, 4+length)
x[0] = typeCertificateRequest
x[1] = uint8(length >> 16)
@@ -938,6 +992,19 @@ func (m *certificateRequestMsg) marshal() (x []byte) {
copy(x[5:], m.certificateTypes)
y := x[5+len(m.certificateTypes):]
+
+ if m.hasSignatureAndHash {
+ n := len(m.signatureAndHashes) * 2
+ y[0] = uint8(n >> 8)
+ y[1] = uint8(n)
+ y = y[2:]
+ for _, sigAndHash := range m.signatureAndHashes {
+ y[0] = sigAndHash.hash
+ y[1] = sigAndHash.signature
+ y = y[2:]
+ }
+ }
+
y[0] = uint8(casLength >> 8)
y[1] = uint8(casLength)
y = y[2:]
@@ -978,6 +1045,27 @@ func (m *certificateRequestMsg) unmarshal(data []byte) bool {
data = data[numCertTypes:]
+ if m.hasSignatureAndHash {
+ if len(data) < 2 {
+ return false
+ }
+ sigAndHashLen := uint16(data[0])<<8 | uint16(data[1])
+ data = data[2:]
+ if sigAndHashLen&1 != 0 {
+ return false
+ }
+ if len(data) < int(sigAndHashLen) {
+ return false
+ }
+ numSigAndHash := sigAndHashLen / 2
+ m.signatureAndHashes = make([]signatureAndHash, numSigAndHash)
+ for i := range m.signatureAndHashes {
+ m.signatureAndHashes[i].hash = data[0]
+ m.signatureAndHashes[i].signature = data[1]
+ data = data[2:]
+ }
+ }
+
if len(data) < 2 {
return false
}
@@ -1013,8 +1101,10 @@ func (m *certificateRequestMsg) unmarshal(data []byte) bool {
}
type certificateVerifyMsg struct {
- raw []byte
- signature []byte
+ raw []byte
+ hasSignatureAndHash bool
+ signatureAndHash signatureAndHash
+ signature []byte
}
func (m *certificateVerifyMsg) equal(i interface{}) bool {
@@ -1024,6 +1114,9 @@ func (m *certificateVerifyMsg) equal(i interface{}) bool {
}
return bytes.Equal(m.raw, m1.raw) &&
+ m.hasSignatureAndHash == m1.hasSignatureAndHash &&
+ m.signatureAndHash.hash == m1.signatureAndHash.hash &&
+ m.signatureAndHash.signature == m1.signatureAndHash.signature &&
bytes.Equal(m.signature, m1.signature)
}
@@ -1035,14 +1128,23 @@ func (m *certificateVerifyMsg) marshal() (x []byte) {
// See http://tools.ietf.org/html/rfc4346#section-7.4.8
siglength := len(m.signature)
length := 2 + siglength
+ if m.hasSignatureAndHash {
+ length += 2
+ }
x = make([]byte, 4+length)
x[0] = typeCertificateVerify
x[1] = uint8(length >> 16)
x[2] = uint8(length >> 8)
x[3] = uint8(length)
- x[4] = uint8(siglength >> 8)
- x[5] = uint8(siglength)
- copy(x[6:], m.signature)
+ y := x[4:]
+ if m.hasSignatureAndHash {
+ y[0] = m.signatureAndHash.hash
+ y[1] = m.signatureAndHash.signature
+ y = y[2:]
+ }
+ y[0] = uint8(siglength >> 8)
+ y[1] = uint8(siglength)
+ copy(y[2:], m.signature)
m.raw = x
@@ -1061,12 +1163,23 @@ func (m *certificateVerifyMsg) unmarshal(data []byte) bool {
return false
}
- siglength := int(data[4])<<8 + int(data[5])
- if len(data)-6 != siglength {
+ data = data[4:]
+ if m.hasSignatureAndHash {
+ m.signatureAndHash.hash = data[0]
+ m.signatureAndHash.signature = data[1]
+ data = data[2:]
+ }
+
+ if len(data) < 2 {
+ return false
+ }
+ siglength := int(data[0])<<8 + int(data[1])
+ data = data[2:]
+ if len(data) != siglength {
return false
}
- m.signature = data[6:]
+ m.signature = data
return true
}
@@ -1165,3 +1278,16 @@ func eqByteSlices(x, y [][]byte) bool {
}
return true
}
+
+func eqSignatureAndHashes(x, y []signatureAndHash) bool {
+ if len(x) != len(y) {
+ return false
+ }
+ for i, v := range x {
+ v2 := y[i]
+ if v.hash != v2.hash || v.signature != v2.signature {
+ return false
+ }
+ }
+ return true
+}
diff --git a/libgo/go/crypto/tls/handshake_messages_test.go b/libgo/go/crypto/tls/handshake_messages_test.go
index 3434bad9fba..4f569eeb138 100644
--- a/libgo/go/crypto/tls/handshake_messages_test.go
+++ b/libgo/go/crypto/tls/handshake_messages_test.go
@@ -135,6 +135,9 @@ func (*clientHelloMsg) Generate(rand *rand.Rand, size int) reflect.Value {
m.sessionTicket = randomBytes(rand.Intn(300), rand)
}
}
+ if rand.Intn(10) > 5 {
+ m.signatureAndHashes = supportedSKXSignatureAlgorithms
+ }
return reflect.ValueOf(m)
}
diff --git a/libgo/go/crypto/tls/handshake_server.go b/libgo/go/crypto/tls/handshake_server.go
index 823730c605c..c9ccf675cd8 100644
--- a/libgo/go/crypto/tls/handshake_server.go
+++ b/libgo/go/crypto/tls/handshake_server.go
@@ -6,9 +6,11 @@ package tls
import (
"crypto"
+ "crypto/ecdsa"
"crypto/rsa"
"crypto/subtle"
"crypto/x509"
+ "encoding/asn1"
"errors"
"io"
)
@@ -21,10 +23,12 @@ type serverHandshakeState struct {
hello *serverHelloMsg
suite *cipherSuite
ellipticOk bool
+ ecdsaOk bool
sessionState *sessionState
finishedHash finishedHash
masterSecret []byte
certsFromClient [][]byte
+ cert *Certificate
}
// serverHandshake performs a TLS handshake as a server.
@@ -98,7 +102,7 @@ func (hs *serverHandshakeState) readClientHello() (isResume bool, err error) {
if !ok {
return false, c.sendAlert(alertUnexpectedMessage)
}
- c.vers, ok = mutualVersion(hs.clientHello.vers)
+ c.vers, ok = config.mutualVersion(hs.clientHello.vers)
if !ok {
return false, c.sendAlert(alertProtocolVersion)
}
@@ -156,11 +160,25 @@ Curves:
if len(hs.clientHello.serverName) > 0 {
c.serverName = hs.clientHello.serverName
}
- if hs.clientHello.nextProtoNeg {
+ // Although sending an empty NPN extension is reasonable, Firefox has
+ // had a bug around this. Best to send nothing at all if
+ // config.NextProtos is empty. See
+ // https://code.google.com/p/go/issues/detail?id=5445.
+ if hs.clientHello.nextProtoNeg && len(config.NextProtos) > 0 {
hs.hello.nextProtoNeg = true
hs.hello.nextProtos = config.NextProtos
}
+ if len(config.Certificates) == 0 {
+ return false, c.sendAlert(alertInternalError)
+ }
+ hs.cert = &config.Certificates[0]
+ if len(hs.clientHello.serverName) > 0 {
+ hs.cert = config.getCertificateForName(hs.clientHello.serverName)
+ }
+
+ _, hs.ecdsaOk = hs.cert.PrivateKey.(*ecdsa.PrivateKey)
+
if hs.checkForResumption() {
return true, nil
}
@@ -175,7 +193,7 @@ Curves:
}
for _, id := range preferenceList {
- if hs.suite = c.tryCipherSuite(id, supportedList, hs.ellipticOk); hs.suite != nil {
+ if hs.suite = c.tryCipherSuite(id, supportedList, c.vers, hs.ellipticOk, hs.ecdsaOk); hs.suite != nil {
break
}
}
@@ -199,7 +217,7 @@ func (hs *serverHandshakeState) checkForResumption() bool {
if hs.sessionState.vers > hs.clientHello.vers {
return false
}
- if vers, ok := mutualVersion(hs.sessionState.vers); !ok || vers != hs.sessionState.vers {
+ if vers, ok := c.config.mutualVersion(hs.sessionState.vers); !ok || vers != hs.sessionState.vers {
return false
}
@@ -216,7 +234,7 @@ func (hs *serverHandshakeState) checkForResumption() bool {
}
// Check that we also support the ciphersuite from the session.
- hs.suite = c.tryCipherSuite(hs.sessionState.cipherSuite, c.config.cipherSuites(), hs.ellipticOk)
+ hs.suite = c.tryCipherSuite(hs.sessionState.cipherSuite, c.config.cipherSuites(), hs.sessionState.vers, hs.ellipticOk, hs.ecdsaOk)
if hs.suite == nil {
return false
}
@@ -258,15 +276,7 @@ func (hs *serverHandshakeState) doFullHandshake() error {
config := hs.c.config
c := hs.c
- if len(config.Certificates) == 0 {
- return c.sendAlert(alertInternalError)
- }
- cert := &config.Certificates[0]
- if len(hs.clientHello.serverName) > 0 {
- cert = config.getCertificateForName(hs.clientHello.serverName)
- }
-
- if hs.clientHello.ocspStapling && len(cert.OCSPStaple) > 0 {
+ if hs.clientHello.ocspStapling && len(hs.cert.OCSPStaple) > 0 {
hs.hello.ocspStapling = true
}
@@ -276,20 +286,20 @@ func (hs *serverHandshakeState) doFullHandshake() error {
c.writeRecord(recordTypeHandshake, hs.hello.marshal())
certMsg := new(certificateMsg)
- certMsg.certificates = cert.Certificate
+ certMsg.certificates = hs.cert.Certificate
hs.finishedHash.Write(certMsg.marshal())
c.writeRecord(recordTypeHandshake, certMsg.marshal())
if hs.hello.ocspStapling {
certStatus := new(certificateStatusMsg)
certStatus.statusType = statusTypeOCSP
- certStatus.response = cert.OCSPStaple
+ certStatus.response = hs.cert.OCSPStaple
hs.finishedHash.Write(certStatus.marshal())
c.writeRecord(recordTypeHandshake, certStatus.marshal())
}
- keyAgreement := hs.suite.ka()
- skx, err := keyAgreement.generateServerKeyExchange(config, cert, hs.clientHello, hs.hello)
+ keyAgreement := hs.suite.ka(c.vers)
+ skx, err := keyAgreement.generateServerKeyExchange(config, hs.cert, hs.clientHello, hs.hello)
if err != nil {
c.sendAlert(alertHandshakeFailure)
return err
@@ -302,7 +312,14 @@ func (hs *serverHandshakeState) doFullHandshake() error {
if config.ClientAuth >= RequestClientCert {
// Request a client certificate
certReq := new(certificateRequestMsg)
- certReq.certificateTypes = []byte{certTypeRSASign}
+ certReq.certificateTypes = []byte{
+ byte(certTypeRSASign),
+ byte(certTypeECDSASign),
+ }
+ if c.vers >= VersionTLS12 {
+ certReq.hasSignatureAndHash = true
+ certReq.signatureAndHashes = supportedClientCertSignatureAlgorithms
+ }
// An empty list of certificateAuthorities signals to
// the client that it may send any certificate in response
@@ -320,7 +337,7 @@ func (hs *serverHandshakeState) doFullHandshake() error {
hs.finishedHash.Write(helloDone.marshal())
c.writeRecord(recordTypeHandshake, helloDone.marshal())
- var pub *rsa.PublicKey // public key for client auth, if any
+ var pub crypto.PublicKey // public key for client auth, if any
msg, err := c.readHandshake()
if err != nil {
@@ -365,7 +382,7 @@ func (hs *serverHandshakeState) doFullHandshake() error {
// If we received a client cert in response to our certificate request message,
// the client will send us a certificateVerifyMsg immediately after the
- // clientKeyExchangeMsg. This message is a MD5SHA1 digest of all preceding
+ // clientKeyExchangeMsg. This message is a digest of all preceding
// handshake-layer messages that is signed using the private key corresponding
// to the client's certificate. This allows us to verify that the client is in
// possession of the private key of the certificate.
@@ -379,10 +396,25 @@ func (hs *serverHandshakeState) doFullHandshake() error {
return c.sendAlert(alertUnexpectedMessage)
}
- digest := make([]byte, 0, 36)
- digest = hs.finishedHash.serverMD5.Sum(digest)
- digest = hs.finishedHash.serverSHA1.Sum(digest)
- err = rsa.VerifyPKCS1v15(pub, crypto.MD5SHA1, digest, certVerify.signature)
+ switch key := pub.(type) {
+ case *ecdsa.PublicKey:
+ ecdsaSig := new(ecdsaSignature)
+ if _, err = asn1.Unmarshal(certVerify.signature, ecdsaSig); err != nil {
+ break
+ }
+ if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 {
+ err = errors.New("ECDSA signature contained zero or negative values")
+ break
+ }
+ digest, _, _ := hs.finishedHash.hashForClientCertificate(signatureECDSA)
+ if !ecdsa.Verify(key, digest, ecdsaSig.R, ecdsaSig.S) {
+ err = errors.New("ECDSA verification failure")
+ break
+ }
+ case *rsa.PublicKey:
+ digest, hashFunc, _ := hs.finishedHash.hashForClientCertificate(signatureRSA)
+ err = rsa.VerifyPKCS1v15(key, hashFunc, digest, certVerify.signature)
+ }
if err != nil {
c.sendAlert(alertBadCertificate)
return errors.New("could not validate signature of connection nonces: " + err.Error())
@@ -391,7 +423,7 @@ func (hs *serverHandshakeState) doFullHandshake() error {
hs.finishedHash.Write(certVerify.marshal())
}
- preMasterSecret, err := keyAgreement.processClientKeyExchange(config, cert, ckx, c.vers)
+ preMasterSecret, err := keyAgreement.processClientKeyExchange(config, hs.cert, ckx, c.vers)
if err != nil {
c.sendAlert(alertHandshakeFailure)
return err
@@ -407,12 +439,20 @@ func (hs *serverHandshakeState) establishKeys() error {
clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
keysFromMasterSecret(c.vers, hs.masterSecret, hs.clientHello.random, hs.hello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen)
- clientCipher := hs.suite.cipher(clientKey, clientIV, true /* for reading */)
- clientHash := hs.suite.mac(c.vers, clientMAC)
- c.in.prepareCipherSpec(c.vers, clientCipher, clientHash)
+ var clientCipher, serverCipher interface{}
+ var clientHash, serverHash macFunction
- serverCipher := hs.suite.cipher(serverKey, serverIV, false /* not for reading */)
- serverHash := hs.suite.mac(c.vers, serverMAC)
+ if hs.suite.aead == nil {
+ clientCipher = hs.suite.cipher(clientKey, clientIV, true /* for reading */)
+ clientHash = hs.suite.mac(c.vers, clientMAC)
+ serverCipher = hs.suite.cipher(serverKey, serverIV, false /* not for reading */)
+ serverHash = hs.suite.mac(c.vers, serverMAC)
+ } else {
+ clientCipher = hs.suite.aead(clientKey, clientIV)
+ serverCipher = hs.suite.aead(serverKey, serverIV)
+ }
+
+ c.in.prepareCipherSpec(c.vers, clientCipher, clientHash)
c.out.prepareCipherSpec(c.vers, serverCipher, serverHash)
return nil
@@ -502,7 +542,7 @@ func (hs *serverHandshakeState) sendFinished() error {
// processCertsFromClient takes a chain of client certificates either from a
// Certificates message or from a sessionState and verifies them. It returns
// the public key of the leaf certificate.
-func (hs *serverHandshakeState) processCertsFromClient(certificates [][]byte) (*rsa.PublicKey, error) {
+func (hs *serverHandshakeState) processCertsFromClient(certificates [][]byte) (crypto.PublicKey, error) {
c := hs.c
hs.certsFromClient = certificates
@@ -549,8 +589,11 @@ func (hs *serverHandshakeState) processCertsFromClient(certificates [][]byte) (*
}
if len(certs) > 0 {
- pub, ok := certs[0].PublicKey.(*rsa.PublicKey)
- if !ok {
+ var pub crypto.PublicKey
+ switch key := certs[0].PublicKey.(type) {
+ case *ecdsa.PublicKey, *rsa.PublicKey:
+ pub = key
+ default:
return nil, c.sendAlert(alertUnsupportedCertificate)
}
c.peerCertificates = certs
@@ -562,7 +605,7 @@ func (hs *serverHandshakeState) processCertsFromClient(certificates [][]byte) (*
// tryCipherSuite returns a cipherSuite with the given id if that cipher suite
// is acceptable to use.
-func (c *Conn) tryCipherSuite(id uint16, supportedCipherSuites []uint16, ellipticOk bool) *cipherSuite {
+func (c *Conn) tryCipherSuite(id uint16, supportedCipherSuites []uint16, version uint16, ellipticOk, ecdsaOk bool) *cipherSuite {
for _, supported := range supportedCipherSuites {
if id == supported {
var candidate *cipherSuite
@@ -578,7 +621,13 @@ func (c *Conn) tryCipherSuite(id uint16, supportedCipherSuites []uint16, ellipti
}
// Don't select a ciphersuite which we can't
// support for this client.
- if candidate.elliptic && !ellipticOk {
+ if (candidate.flags&suiteECDHE != 0) && !ellipticOk {
+ continue
+ }
+ if (candidate.flags&suiteECDSA != 0) != ecdsaOk {
+ continue
+ }
+ if version < VersionTLS12 && candidate.flags&suiteTLS12 != 0 {
continue
}
return candidate
diff --git a/libgo/go/crypto/tls/handshake_server_test.go b/libgo/go/crypto/tls/handshake_server_test.go
index bf8cbe3ae6b..c08eba7f17c 100644
--- a/libgo/go/crypto/tls/handshake_server_test.go
+++ b/libgo/go/crypto/tls/handshake_server_test.go
@@ -6,6 +6,8 @@ package tls
import (
"bytes"
+ "crypto/ecdsa"
+ "crypto/elliptic"
"crypto/rsa"
"crypto/x509"
"encoding/hex"
@@ -41,13 +43,15 @@ func init() {
testConfig.Time = func() time.Time { return time.Unix(0, 0) }
testConfig.Rand = zeroSource{}
testConfig.Certificates = make([]Certificate, 2)
- testConfig.Certificates[0].Certificate = [][]byte{testCertificate}
- testConfig.Certificates[0].PrivateKey = testPrivateKey
+ testConfig.Certificates[0].Certificate = [][]byte{testRSACertificate}
+ testConfig.Certificates[0].PrivateKey = testRSAPrivateKey
testConfig.Certificates[1].Certificate = [][]byte{testSNICertificate}
- testConfig.Certificates[1].PrivateKey = testPrivateKey
+ testConfig.Certificates[1].PrivateKey = testRSAPrivateKey
testConfig.BuildNameToCertificate()
testConfig.CipherSuites = []uint16{TLS_RSA_WITH_RC4_128_SHA}
testConfig.InsecureSkipVerify = true
+ testConfig.MinVersion = VersionSSL30
+ testConfig.MaxVersion = VersionTLS10
}
func testClientHelloFailure(t *testing.T, m handshakeMessage, expected error) {
@@ -100,6 +104,53 @@ func TestNoCompressionOverlap(t *testing.T) {
testClientHelloFailure(t, clientHello, alertHandshakeFailure)
}
+func TestTLS12OnlyCipherSuites(t *testing.T) {
+ // Test that a Server doesn't select a TLS 1.2-only cipher suite when
+ // the client negotiates TLS 1.1.
+ var zeros [32]byte
+
+ clientHello := &clientHelloMsg{
+ vers: VersionTLS11,
+ random: zeros[:],
+ cipherSuites: []uint16{
+ // The Server, by default, will use the client's
+ // preference order. So the GCM cipher suite
+ // will be selected unless it's excluded because
+ // of the version in this ClientHello.
+ TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+ TLS_RSA_WITH_RC4_128_SHA,
+ },
+ compressionMethods: []uint8{compressionNone},
+ supportedCurves: []uint16{curveP256, curveP384, curveP521},
+ supportedPoints: []uint8{pointFormatUncompressed},
+ }
+
+ c, s := net.Pipe()
+ var reply interface{}
+ var clientErr error
+ go func() {
+ cli := Client(c, testConfig)
+ cli.vers = clientHello.vers
+ cli.writeRecord(recordTypeHandshake, clientHello.marshal())
+ reply, clientErr = cli.readHandshake()
+ c.Close()
+ }()
+ config := *testConfig
+ config.CipherSuites = clientHello.cipherSuites
+ Server(s, &config).Handshake()
+ s.Close()
+ if clientErr != nil {
+ t.Fatal(clientErr)
+ }
+ serverHello, ok := reply.(*serverHelloMsg)
+ if !ok {
+ t.Fatalf("didn't get ServerHello message in reply. Got %v\n", reply)
+ }
+ if s := serverHello.cipherSuite; s != TLS_RSA_WITH_RC4_128_SHA {
+ t.Fatalf("bad cipher suite from server: %x", s)
+ }
+}
+
func TestAlertForwarding(t *testing.T) {
c, s := net.Pipe()
go func() {
@@ -110,7 +161,7 @@ func TestAlertForwarding(t *testing.T) {
err := Server(s, testConfig).Handshake()
s.Close()
if e, ok := err.(*net.OpError); !ok || e.Err != error(alertUnknownCA) {
- t.Errorf("Got error: %s; expected: %s", err, alertUnknownCA)
+ t.Errorf("Got error: %s; expected: %s", err, error(alertUnknownCA))
}
}
@@ -145,6 +196,7 @@ func TestCipherSuitePreference(t *testing.T) {
serverConfig := &Config{
CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA},
Certificates: testConfig.Certificates,
+ MaxVersion: VersionTLS11,
}
clientConfig := &Config{
CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_RC4_128_SHA},
@@ -211,22 +263,33 @@ func testServerScript(t *testing.T, name string, serverScript [][]byte, config *
}
}
-func TestHandshakeServerRC4(t *testing.T) {
- testServerScript(t, "RC4", rc4ServerScript, testConfig, nil)
+func TestHandshakeServerRSARC4(t *testing.T) {
+ testServerScript(t, "RSA-RC4", rsaRC4ServerScript, testConfig, nil)
}
-func TestHandshakeServer3DES(t *testing.T) {
+func TestHandshakeServerRSA3DES(t *testing.T) {
des3Config := new(Config)
*des3Config = *testConfig
des3Config.CipherSuites = []uint16{TLS_RSA_WITH_3DES_EDE_CBC_SHA}
- testServerScript(t, "3DES", des3ServerScript, des3Config, nil)
+ testServerScript(t, "RSA-3DES", rsaDES3ServerScript, des3Config, nil)
}
-func TestHandshakeServerAES(t *testing.T) {
+func TestHandshakeServerRSAAES(t *testing.T) {
aesConfig := new(Config)
*aesConfig = *testConfig
aesConfig.CipherSuites = []uint16{TLS_RSA_WITH_AES_128_CBC_SHA}
- testServerScript(t, "AES", aesServerScript, aesConfig, nil)
+ testServerScript(t, "RSA-AES", rsaAESServerScript, aesConfig, nil)
+}
+
+func TestHandshakeServerECDHEECDSAAES(t *testing.T) {
+ ecdsaConfig := new(Config)
+ *ecdsaConfig = *testConfig
+ ecdsaConfig.Certificates = make([]Certificate, 1)
+ ecdsaConfig.Certificates[0].Certificate = [][]byte{testECDSACertificate}
+ ecdsaConfig.Certificates[0].PrivateKey = testECDSAPrivateKey
+ ecdsaConfig.BuildNameToCertificate()
+ ecdsaConfig.CipherSuites = []uint16{TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA}
+ testServerScript(t, "ECDHE-ECDSA-AES", ecdheECDSAAESServerScript, ecdsaConfig, nil)
}
func TestHandshakeServerSSLv3(t *testing.T) {
@@ -245,6 +308,15 @@ func TestResumption(t *testing.T) {
testServerScript(t, "Resume", serverResumeTest, testConfig, nil)
}
+func TestTLS12ClientCertServer(t *testing.T) {
+ config := *testConfig
+ config.MaxVersion = VersionTLS12
+ config.ClientAuth = RequireAnyClientCert
+ config.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_RC4_128_SHA}
+
+ testServerScript(t, "TLS12", tls12ServerScript, &config, nil)
+}
+
type clientauthTest struct {
name string
clientauth ClientAuthType
@@ -252,16 +324,67 @@ type clientauthTest struct {
script [][]byte
}
-func TestClientAuth(t *testing.T) {
- for _, cat := range clientauthTests {
+func TestClientAuthRSA(t *testing.T) {
+ for _, cat := range clientauthRSATests {
+ t.Log("running", cat.name)
+ cfg := new(Config)
+ *cfg = *testConfig
+ cfg.ClientAuth = cat.clientauth
+ testServerScript(t, cat.name, cat.script, cfg, cat.peers)
+ }
+}
+
+func TestClientAuthECDSA(t *testing.T) {
+ for _, cat := range clientauthECDSATests {
t.Log("running", cat.name)
cfg := new(Config)
*cfg = *testConfig
+ cfg.Certificates = make([]Certificate, 1)
+ cfg.Certificates[0].Certificate = [][]byte{testECDSACertificate}
+ cfg.Certificates[0].PrivateKey = testECDSAPrivateKey
+ cfg.BuildNameToCertificate()
+ cfg.CipherSuites = []uint16{TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA}
cfg.ClientAuth = cat.clientauth
testServerScript(t, cat.name, cat.script, cfg, cat.peers)
}
}
+// TestCipherSuiteCertPreferance ensures that we select an RSA ciphersuite with
+// an RSA certificate and an ECDSA ciphersuite with an ECDSA certificate.
+func TestCipherSuiteCertPreferance(t *testing.T) {
+ var config = *testConfig
+ config.CipherSuites = []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA}
+ config.MaxVersion = VersionTLS11
+ config.PreferServerCipherSuites = true
+ testServerScript(t, "CipherSuiteCertPreference", tls11ECDHEAESServerScript, &config, nil)
+
+ config = *testConfig
+ config.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA}
+ config.Certificates = []Certificate{
+ Certificate{
+ Certificate: [][]byte{testECDSACertificate},
+ PrivateKey: testECDSAPrivateKey,
+ },
+ }
+ config.BuildNameToCertificate()
+ config.PreferServerCipherSuites = true
+ testServerScript(t, "CipherSuiteCertPreference2", ecdheECDSAAESServerScript, &config, nil)
+}
+
+func TestTLS11Server(t *testing.T) {
+ var config = *testConfig
+ config.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA}
+ config.MaxVersion = VersionTLS11
+ testServerScript(t, "TLS11", tls11ECDHEAESServerScript, &config, nil)
+}
+
+func TestAESGCM(t *testing.T) {
+ var config = *testConfig
+ config.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}
+ config.MaxVersion = VersionTLS12
+ testServerScript(t, "AES-GCM", aesGCMServerScript, &config, nil)
+}
+
// recordingConn is a net.Conn that records the traffic that passes through it.
// WriteTo can be used to produce Go code that contains the recorded traffic.
type recordingConn struct {
@@ -331,10 +454,28 @@ var serve = flag.Bool("serve", false, "run a TLS server on :10443")
var testCipherSuites = flag.String("ciphersuites",
"0x"+strconv.FormatInt(int64(TLS_RSA_WITH_RC4_128_SHA), 16),
"cipher suites to accept in serving mode")
+var testMinVersion = flag.String("minversion",
+ "0x"+strconv.FormatInt(int64(VersionSSL30), 16),
+ "minimum version to negotiate")
+var testMaxVersion = flag.String("maxversion",
+ "0x"+strconv.FormatInt(int64(VersionTLS10), 16),
+ "maximum version to negotiate")
var testClientAuth = flag.Int("clientauth", 0, "value for tls.Config.ClientAuth")
func GetTestConfig() *Config {
var config = *testConfig
+
+ minVersion, err := strconv.ParseUint(*testMinVersion, 0, 64)
+ if err != nil {
+ panic(err)
+ }
+ config.MinVersion = uint16(minVersion)
+ maxVersion, err := strconv.ParseUint(*testMaxVersion, 0, 64)
+ if err != nil {
+ panic(err)
+ }
+ config.MaxVersion = uint16(maxVersion)
+
suites := strings.Split(*testCipherSuites, ",")
config.CipherSuites = make([]uint16, len(suites))
for i := range suites {
@@ -345,6 +486,25 @@ func GetTestConfig() *Config {
config.CipherSuites[i] = uint16(suite)
}
+ ecdsa := false
+ for _, suite := range config.CipherSuites {
+ switch suite {
+ case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
+ TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
+ TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:
+ ecdsa = true
+ }
+ }
+ if ecdsa {
+ config.Certificates = nil
+ if !*connect {
+ config.Certificates = make([]Certificate, 1)
+ config.Certificates[0].Certificate = [][]byte{testECDSACertificate}
+ config.Certificates[0].PrivateKey = testECDSAPrivateKey
+ }
+ config.BuildNameToCertificate()
+ }
+
config.ClientAuth = ClientAuthType(*testClientAuth)
return &config
}
@@ -403,11 +563,13 @@ func fromHex(s string) []byte {
return b
}
-var testCertificate = fromHex("308202b030820219a00302010202090085b0bba48a7fb8ca300d06092a864886f70d01010505003045310b3009060355040613024155311330110603550408130a536f6d652d53746174653121301f060355040a1318496e7465726e6574205769646769747320507479204c7464301e170d3130303432343039303933385a170d3131303432343039303933385a3045310b3009060355040613024155311330110603550408130a536f6d652d53746174653121301f060355040a1318496e7465726e6574205769646769747320507479204c746430819f300d06092a864886f70d010101050003818d0030818902818100bb79d6f517b5e5bf4610d0dc69bee62b07435ad0032d8a7a4385b71452e7a5654c2c78b8238cb5b482e5de1f953b7e62a52ca533d6fe125c7a56fcf506bffa587b263fb5cd04d3d0c921964ac7f4549f5abfef427100fe1899077f7e887d7df10439c4a22edb51c97ce3c04c3b326601cfafb11db8719a1ddbdb896baeda2d790203010001a381a73081a4301d0603551d0e04160414b1ade2855acfcb28db69ce2369ded3268e18883930750603551d23046e306c8014b1ade2855acfcb28db69ce2369ded3268e188839a149a4473045310b3009060355040613024155311330110603550408130a536f6d652d53746174653121301f060355040a1318496e7465726e6574205769646769747320507479204c746482090085b0bba48a7fb8ca300c0603551d13040530030101ff300d06092a864886f70d010105050003818100086c4524c76bb159ab0c52ccf2b014d7879d7a6475b55a9566e4c52b8eae12661feb4f38b36e60d392fdf74108b52513b1187a24fb301dbaed98b917ece7d73159db95d31d78ea50565cd5825a2d5a5f33c4b6d8c97590968c0f5298b5cd981f89205ff2a01ca31b9694dda9fd57e970e8266d71999b266e3850296c90a7bdd9")
+var testRSACertificate = fromHex("308202b030820219a00302010202090085b0bba48a7fb8ca300d06092a864886f70d01010505003045310b3009060355040613024155311330110603550408130a536f6d652d53746174653121301f060355040a1318496e7465726e6574205769646769747320507479204c7464301e170d3130303432343039303933385a170d3131303432343039303933385a3045310b3009060355040613024155311330110603550408130a536f6d652d53746174653121301f060355040a1318496e7465726e6574205769646769747320507479204c746430819f300d06092a864886f70d010101050003818d0030818902818100bb79d6f517b5e5bf4610d0dc69bee62b07435ad0032d8a7a4385b71452e7a5654c2c78b8238cb5b482e5de1f953b7e62a52ca533d6fe125c7a56fcf506bffa587b263fb5cd04d3d0c921964ac7f4549f5abfef427100fe1899077f7e887d7df10439c4a22edb51c97ce3c04c3b326601cfafb11db8719a1ddbdb896baeda2d790203010001a381a73081a4301d0603551d0e04160414b1ade2855acfcb28db69ce2369ded3268e18883930750603551d23046e306c8014b1ade2855acfcb28db69ce2369ded3268e188839a149a4473045310b3009060355040613024155311330110603550408130a536f6d652d53746174653121301f060355040a1318496e7465726e6574205769646769747320507479204c746482090085b0bba48a7fb8ca300c0603551d13040530030101ff300d06092a864886f70d010105050003818100086c4524c76bb159ab0c52ccf2b014d7879d7a6475b55a9566e4c52b8eae12661feb4f38b36e60d392fdf74108b52513b1187a24fb301dbaed98b917ece7d73159db95d31d78ea50565cd5825a2d5a5f33c4b6d8c97590968c0f5298b5cd981f89205ff2a01ca31b9694dda9fd57e970e8266d71999b266e3850296c90a7bdd9")
+
+var testECDSACertificate = fromHex("3082020030820162020900b8bf2d47a0d2ebf4300906072a8648ce3d04013045310b3009060355040613024155311330110603550408130a536f6d652d53746174653121301f060355040a1318496e7465726e6574205769646769747320507479204c7464301e170d3132313132323135303633325a170d3232313132303135303633325a3045310b3009060355040613024155311330110603550408130a536f6d652d53746174653121301f060355040a1318496e7465726e6574205769646769747320507479204c746430819b301006072a8648ce3d020106052b81040023038186000400c4a1edbe98f90b4873367ec316561122f23d53c33b4d213dcd6b75e6f6b0dc9adf26c1bcb287f072327cb3642f1c90bcea6823107efee325c0483a69e0286dd33700ef0462dd0da09c706283d881d36431aa9e9731bd96b068c09b23de76643f1a5c7fe9120e5858b65f70dd9bd8ead5d7f5d5ccb9b69f30665b669a20e227e5bffe3b300906072a8648ce3d040103818c0030818802420188a24febe245c5487d1bacf5ed989dae4770c05e1bb62fbdf1b64db76140d311a2ceee0b7e927eff769dc33b7ea53fcefa10e259ec472d7cacda4e970e15a06fd00242014dfcbe67139c2d050ebd3fa38c25c13313830d9406bbd4377af6ec7ac9862eddd711697f857c56defb31782be4c7780daecbbe9e4e3624317b6a0f399512078f2a")
var testSNICertificate = fromHex("308201f23082015da003020102020100300b06092a864886f70d01010530283110300e060355040a130741636d6520436f311430120603550403130b736e69746573742e636f6d301e170d3132303431313137343033355a170d3133303431313137343533355a30283110300e060355040a130741636d6520436f311430120603550403130b736e69746573742e636f6d30819d300b06092a864886f70d01010103818d0030818902818100bb79d6f517b5e5bf4610d0dc69bee62b07435ad0032d8a7a4385b71452e7a5654c2c78b8238cb5b482e5de1f953b7e62a52ca533d6fe125c7a56fcf506bffa587b263fb5cd04d3d0c921964ac7f4549f5abfef427100fe1899077f7e887d7df10439c4a22edb51c97ce3c04c3b326601cfafb11db8719a1ddbdb896baeda2d790203010001a3323030300e0603551d0f0101ff0404030200a0300d0603551d0e0406040401020304300f0603551d2304083006800401020304300b06092a864886f70d0101050381810089c6455f1c1f5ef8eb1ab174ee2439059f5c4259bb1a8d86cdb1d056f56a717da40e95ab90f59e8deaf627c157995094db0802266eb34fc6842dea8a4b68d9c1389103ab84fb9e1f85d9b5d23ff2312c8670fbb540148245a4ebafe264d90c8a4cf4f85b0fac12ac2fc4a3154bad52462868af96c62c6525d652b6e31845bdcc")
-var testPrivateKey = &rsa.PrivateKey{
+var testRSAPrivateKey = &rsa.PrivateKey{
PublicKey: rsa.PublicKey{
N: bigFromString("131650079503776001033793877885499001334664249354723305978524647182322416328664556247316495448366990052837680518067798333412266673813370895702118944398081598789828837447552603077848001020611640547221687072142537202428102790818451901395596882588063427854225330436740647715202971973145151161964464812406232198521"),
E: 65537,
@@ -419,6 +581,22 @@ var testPrivateKey = &rsa.PrivateKey{
},
}
+var testECDSAPrivateKey = &ecdsa.PrivateKey{
+ PublicKey: ecdsa.PublicKey{
+ Curve: &elliptic.CurveParams{
+ P: bigFromString("6864797660130609714981900799081393217269435300143305409394463459185543183397656052122559640661454554977296311391480858037121987999716643812574028291115057151"),
+ N: bigFromString("6864797660130609714981900799081393217269435300143305409394463459185543183397655394245057746333217197532963996371363321113864768612440380340372808892707005449"),
+ B: bigFromString("1093849038073734274511112390766805569936207598951683748994586394495953116150735016013708737573759623248592132296706313309438452531591012912142327488478985984"),
+ Gx: bigFromString("2661740802050217063228768716723360960729859168756973147706671368418802944996427808491545080627771902352094241225065558662157113545570916814161637315895999846"),
+ Gy: bigFromString("3757180025770020463545507224491183603594455134769762486694567779615544477440556316691234405012945539562144444537289428522585666729196580810124344277578376784"),
+ BitSize: 521,
+ },
+ X: bigFromString("2636411247892461147287360222306590634450676461695221912739908880441342231985950069527906976759812296359387337367668045707086543273113073382714101597903639351"),
+ Y: bigFromString("3204695818431246682253994090650952614555094516658732116404513121125038617915183037601737180082382202488628239201196033284060130040574800684774115478859677243"),
+ },
+ D: bigFromString("5477294338614160138026852784385529180817726002953041720191098180813046231640184669647735805135001309477695746518160084669446643325196003346204701381388769751"),
+}
+
func loadPEMCert(in string) *x509.Certificate {
block, _ := pem.Decode([]byte(in))
if block.Type == "CERTIFICATE" && len(block.Headers) == 0 {
@@ -435,7 +613,7 @@ func loadPEMCert(in string) *x509.Certificate {
// The values for this test are obtained by building and running in server mode:
// % go test -test.run "TestRunServer" -serve
// The recorded bytes are written to stdout.
-var rc4ServerScript = [][]byte{
+var rsaRC4ServerScript = [][]byte{
{
0x16, 0x03, 0x01, 0x00, 0x54, 0x01, 0x00, 0x00,
0x50, 0x03, 0x01, 0x50, 0x77, 0x3d, 0xbd, 0x32,
@@ -592,7 +770,7 @@ var rc4ServerScript = [][]byte{
},
}
-var des3ServerScript = [][]byte{
+var rsaDES3ServerScript = [][]byte{
{
0x16, 0x03, 0x00, 0x00, 0xc5, 0x01, 0x00, 0x00,
0xc1, 0x03, 0x03, 0x50, 0xae, 0x5d, 0x38, 0xec,
@@ -801,7 +979,7 @@ var des3ServerScript = [][]byte{
},
}
-var aesServerScript = [][]byte{
+var rsaAESServerScript = [][]byte{
{
0x16, 0x03, 0x00, 0x00, 0xc5, 0x01, 0x00, 0x00,
0xc1, 0x03, 0x03, 0x50, 0xae, 0x5c, 0xe9, 0x5e,
@@ -1027,6 +1205,216 @@ var aesServerScript = [][]byte{
},
}
+// Generated using:
+// $ go test -test.run TestRunServer -serve -ciphersuites=0xc00a
+// $ openssl s_client -host 127.0.0.1 -port 10443 -cipher ECDHE-ECDSA-AES256-SHA
+var ecdheECDSAAESServerScript = [][]byte{
+ {
+ 0x16, 0x03, 0x01, 0x00, 0xa0, 0x01, 0x00, 0x00,
+ 0x9c, 0x03, 0x03, 0x50, 0xd7, 0x18, 0x31, 0x49,
+ 0xde, 0x19, 0x8d, 0x08, 0x5c, 0x4b, 0x60, 0x67,
+ 0x0f, 0xfe, 0xd0, 0x62, 0xf9, 0x31, 0x48, 0x17,
+ 0x9e, 0x50, 0xc1, 0xd8, 0x35, 0x24, 0x0e, 0xa6,
+ 0x09, 0x06, 0x51, 0x00, 0x00, 0x04, 0xc0, 0x0a,
+ 0x00, 0xff, 0x01, 0x00, 0x00, 0x6f, 0x00, 0x0b,
+ 0x00, 0x04, 0x03, 0x00, 0x01, 0x02, 0x00, 0x0a,
+ 0x00, 0x34, 0x00, 0x32, 0x00, 0x0e, 0x00, 0x0d,
+ 0x00, 0x19, 0x00, 0x0b, 0x00, 0x0c, 0x00, 0x18,
+ 0x00, 0x09, 0x00, 0x0a, 0x00, 0x16, 0x00, 0x17,
+ 0x00, 0x08, 0x00, 0x06, 0x00, 0x07, 0x00, 0x14,
+ 0x00, 0x15, 0x00, 0x04, 0x00, 0x05, 0x00, 0x12,
+ 0x00, 0x13, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03,
+ 0x00, 0x0f, 0x00, 0x10, 0x00, 0x11, 0x00, 0x23,
+ 0x00, 0x00, 0x00, 0x0d, 0x00, 0x22, 0x00, 0x20,
+ 0x06, 0x01, 0x06, 0x02, 0x06, 0x03, 0x05, 0x01,
+ 0x05, 0x02, 0x05, 0x03, 0x04, 0x01, 0x04, 0x02,
+ 0x04, 0x03, 0x03, 0x01, 0x03, 0x02, 0x03, 0x03,
+ 0x02, 0x01, 0x02, 0x02, 0x02, 0x03, 0x01, 0x01,
+ 0x00, 0x0f, 0x00, 0x01, 0x01,
+ },
+ {
+ 0x16, 0x03, 0x01, 0x00, 0x30, 0x02, 0x00, 0x00,
+ 0x2c, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xc0, 0x0a, 0x00, 0x00,
+ 0x04, 0x00, 0x23, 0x00, 0x00, 0x16, 0x03, 0x01,
+ 0x02, 0x0e, 0x0b, 0x00, 0x02, 0x0a, 0x00, 0x02,
+ 0x07, 0x00, 0x02, 0x04, 0x30, 0x82, 0x02, 0x00,
+ 0x30, 0x82, 0x01, 0x62, 0x02, 0x09, 0x00, 0xb8,
+ 0xbf, 0x2d, 0x47, 0xa0, 0xd2, 0xeb, 0xf4, 0x30,
+ 0x09, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d,
+ 0x04, 0x01, 0x30, 0x45, 0x31, 0x0b, 0x30, 0x09,
+ 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x41,
+ 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
+ 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, 0x65,
+ 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x21,
+ 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13,
+ 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
+ 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, 0x74,
+ 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74,
+ 0x64, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x32, 0x31,
+ 0x31, 0x32, 0x32, 0x31, 0x35, 0x30, 0x36, 0x33,
+ 0x32, 0x5a, 0x17, 0x0d, 0x32, 0x32, 0x31, 0x31,
+ 0x32, 0x30, 0x31, 0x35, 0x30, 0x36, 0x33, 0x32,
+ 0x5a, 0x30, 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06,
+ 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x41, 0x55,
+ 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04,
+ 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d,
+ 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x21, 0x30,
+ 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x18,
+ 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74,
+ 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, 0x74, 0x73,
+ 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64,
+ 0x30, 0x81, 0x9b, 0x30, 0x10, 0x06, 0x07, 0x2a,
+ 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05,
+ 0x2b, 0x81, 0x04, 0x00, 0x23, 0x03, 0x81, 0x86,
+ 0x00, 0x04, 0x00, 0xc4, 0xa1, 0xed, 0xbe, 0x98,
+ 0xf9, 0x0b, 0x48, 0x73, 0x36, 0x7e, 0xc3, 0x16,
+ 0x56, 0x11, 0x22, 0xf2, 0x3d, 0x53, 0xc3, 0x3b,
+ 0x4d, 0x21, 0x3d, 0xcd, 0x6b, 0x75, 0xe6, 0xf6,
+ 0xb0, 0xdc, 0x9a, 0xdf, 0x26, 0xc1, 0xbc, 0xb2,
+ 0x87, 0xf0, 0x72, 0x32, 0x7c, 0xb3, 0x64, 0x2f,
+ 0x1c, 0x90, 0xbc, 0xea, 0x68, 0x23, 0x10, 0x7e,
+ 0xfe, 0xe3, 0x25, 0xc0, 0x48, 0x3a, 0x69, 0xe0,
+ 0x28, 0x6d, 0xd3, 0x37, 0x00, 0xef, 0x04, 0x62,
+ 0xdd, 0x0d, 0xa0, 0x9c, 0x70, 0x62, 0x83, 0xd8,
+ 0x81, 0xd3, 0x64, 0x31, 0xaa, 0x9e, 0x97, 0x31,
+ 0xbd, 0x96, 0xb0, 0x68, 0xc0, 0x9b, 0x23, 0xde,
+ 0x76, 0x64, 0x3f, 0x1a, 0x5c, 0x7f, 0xe9, 0x12,
+ 0x0e, 0x58, 0x58, 0xb6, 0x5f, 0x70, 0xdd, 0x9b,
+ 0xd8, 0xea, 0xd5, 0xd7, 0xf5, 0xd5, 0xcc, 0xb9,
+ 0xb6, 0x9f, 0x30, 0x66, 0x5b, 0x66, 0x9a, 0x20,
+ 0xe2, 0x27, 0xe5, 0xbf, 0xfe, 0x3b, 0x30, 0x09,
+ 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04,
+ 0x01, 0x03, 0x81, 0x8c, 0x00, 0x30, 0x81, 0x88,
+ 0x02, 0x42, 0x01, 0x88, 0xa2, 0x4f, 0xeb, 0xe2,
+ 0x45, 0xc5, 0x48, 0x7d, 0x1b, 0xac, 0xf5, 0xed,
+ 0x98, 0x9d, 0xae, 0x47, 0x70, 0xc0, 0x5e, 0x1b,
+ 0xb6, 0x2f, 0xbd, 0xf1, 0xb6, 0x4d, 0xb7, 0x61,
+ 0x40, 0xd3, 0x11, 0xa2, 0xce, 0xee, 0x0b, 0x7e,
+ 0x92, 0x7e, 0xff, 0x76, 0x9d, 0xc3, 0x3b, 0x7e,
+ 0xa5, 0x3f, 0xce, 0xfa, 0x10, 0xe2, 0x59, 0xec,
+ 0x47, 0x2d, 0x7c, 0xac, 0xda, 0x4e, 0x97, 0x0e,
+ 0x15, 0xa0, 0x6f, 0xd0, 0x02, 0x42, 0x01, 0x4d,
+ 0xfc, 0xbe, 0x67, 0x13, 0x9c, 0x2d, 0x05, 0x0e,
+ 0xbd, 0x3f, 0xa3, 0x8c, 0x25, 0xc1, 0x33, 0x13,
+ 0x83, 0x0d, 0x94, 0x06, 0xbb, 0xd4, 0x37, 0x7a,
+ 0xf6, 0xec, 0x7a, 0xc9, 0x86, 0x2e, 0xdd, 0xd7,
+ 0x11, 0x69, 0x7f, 0x85, 0x7c, 0x56, 0xde, 0xfb,
+ 0x31, 0x78, 0x2b, 0xe4, 0xc7, 0x78, 0x0d, 0xae,
+ 0xcb, 0xbe, 0x9e, 0x4e, 0x36, 0x24, 0x31, 0x7b,
+ 0x6a, 0x0f, 0x39, 0x95, 0x12, 0x07, 0x8f, 0x2a,
+ 0x16, 0x03, 0x01, 0x01, 0x1a, 0x0c, 0x00, 0x01,
+ 0x16, 0x03, 0x00, 0x19, 0x85, 0x04, 0x01, 0x39,
+ 0xdc, 0xee, 0x44, 0x17, 0x5e, 0xdb, 0xd7, 0x27,
+ 0xaf, 0xb6, 0x56, 0xd9, 0xb4, 0x43, 0x5a, 0x99,
+ 0xcf, 0xaa, 0x31, 0x37, 0x0c, 0x6f, 0x3a, 0xa0,
+ 0xf8, 0x53, 0xc4, 0x74, 0xd1, 0x91, 0x0a, 0x46,
+ 0xf5, 0x38, 0x3b, 0x5c, 0x09, 0xd8, 0x97, 0xdc,
+ 0x4b, 0xaa, 0x70, 0x26, 0x48, 0xf2, 0xd6, 0x0b,
+ 0x31, 0xc9, 0xf8, 0xd4, 0x98, 0x43, 0xe1, 0x6c,
+ 0xd5, 0xc7, 0xb2, 0x8e, 0x0b, 0x01, 0xe6, 0xb6,
+ 0x00, 0x28, 0x80, 0x7b, 0xfc, 0x96, 0x8f, 0x0d,
+ 0xa2, 0x4f, 0xb0, 0x79, 0xaf, 0xdc, 0x61, 0x28,
+ 0x63, 0x33, 0x78, 0xf6, 0x31, 0x39, 0xfd, 0x8a,
+ 0xf4, 0x15, 0x18, 0x11, 0xfe, 0xdb, 0xd5, 0x07,
+ 0xda, 0x2c, 0xed, 0x49, 0xa0, 0x23, 0xbf, 0xd0,
+ 0x3a, 0x38, 0x1d, 0x54, 0xae, 0x1c, 0x7b, 0xea,
+ 0x29, 0xee, 0xd0, 0x38, 0xc1, 0x76, 0xa7, 0x7f,
+ 0x2a, 0xf4, 0xce, 0x1e, 0xac, 0xcc, 0x94, 0x79,
+ 0x90, 0x33, 0x00, 0x8b, 0x30, 0x81, 0x88, 0x02,
+ 0x42, 0x00, 0xc6, 0x85, 0x8e, 0x06, 0xb7, 0x04,
+ 0x04, 0xe9, 0xcd, 0x9e, 0x3e, 0xcb, 0x66, 0x23,
+ 0x95, 0xb4, 0x42, 0x9c, 0x64, 0x81, 0x39, 0x05,
+ 0x3f, 0xb5, 0x21, 0xf8, 0x28, 0xaf, 0x60, 0x6b,
+ 0x4d, 0x3d, 0xba, 0xa1, 0x4b, 0x5e, 0x77, 0xef,
+ 0xe7, 0x59, 0x28, 0xfe, 0x1d, 0xc1, 0x27, 0xa2,
+ 0xff, 0xa8, 0xde, 0x33, 0x48, 0xb3, 0xc1, 0x85,
+ 0x6a, 0x42, 0x9b, 0xf9, 0x7e, 0x7e, 0x31, 0xc2,
+ 0xe5, 0xbd, 0x66, 0x02, 0x42, 0x00, 0xad, 0x7d,
+ 0x06, 0x35, 0xab, 0xec, 0x8d, 0xac, 0xd4, 0xba,
+ 0x1b, 0x49, 0x5e, 0x05, 0x5f, 0xf0, 0x97, 0x93,
+ 0x82, 0xb8, 0x2b, 0x8d, 0x91, 0x98, 0x63, 0x8e,
+ 0xb4, 0x14, 0x62, 0xdb, 0x1e, 0xc9, 0x2b, 0x30,
+ 0xf8, 0x41, 0x9b, 0xa6, 0xe6, 0xbc, 0xde, 0x0e,
+ 0x68, 0x30, 0x22, 0x50, 0xe6, 0x98, 0x97, 0x7b,
+ 0x69, 0xf7, 0x93, 0xed, 0xcd, 0x19, 0x2f, 0x44,
+ 0x6c, 0x2e, 0xdf, 0x25, 0xee, 0xcc, 0x46, 0x16,
+ 0x03, 0x01, 0x00, 0x04, 0x0e, 0x00, 0x00, 0x00,
+ },
+ {
+ 0x16, 0x03, 0x01, 0x00, 0x8a, 0x10, 0x00, 0x00,
+ 0x86, 0x85, 0x04, 0x00, 0x1c, 0xc5, 0xe8, 0xb3,
+ 0x42, 0xb4, 0xad, 0xca, 0x45, 0xcd, 0x42, 0x7b,
+ 0xfb, 0x0c, 0xea, 0x32, 0x26, 0xd4, 0x8a, 0xef,
+ 0xdf, 0xc9, 0xff, 0xd2, 0xe0, 0x36, 0xea, 0x4e,
+ 0xbb, 0x3e, 0xf4, 0x9c, 0x76, 0x4f, 0x44, 0xbd,
+ 0x84, 0x72, 0xdd, 0xcb, 0xe5, 0x28, 0x8d, 0x31,
+ 0x72, 0x3b, 0xd3, 0xf2, 0x9a, 0x13, 0xfb, 0x8a,
+ 0xa7, 0x72, 0xca, 0x21, 0x6c, 0xea, 0xbf, 0xe9,
+ 0x8c, 0x0a, 0xcc, 0x8f, 0xd6, 0x00, 0x20, 0x87,
+ 0xf3, 0x7d, 0x18, 0xc5, 0xfd, 0x9e, 0xdd, 0x6b,
+ 0x06, 0xdc, 0x52, 0xeb, 0x14, 0xc0, 0x67, 0x5a,
+ 0x06, 0xd8, 0x98, 0x19, 0x14, 0xe7, 0xd4, 0x36,
+ 0x32, 0xee, 0xb7, 0xfa, 0xe2, 0x85, 0x4a, 0x16,
+ 0x42, 0x0c, 0xa6, 0x21, 0xcf, 0x1f, 0xae, 0x10,
+ 0x8b, 0x28, 0x32, 0x19, 0xa4, 0x0a, 0xd7, 0xce,
+ 0xe6, 0xe1, 0x93, 0xfb, 0x5f, 0x08, 0x8b, 0x42,
+ 0xa2, 0x20, 0xed, 0x0d, 0x62, 0xca, 0xed, 0x14,
+ 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03, 0x01,
+ 0x00, 0x30, 0x2e, 0x33, 0xc0, 0x57, 0x6c, 0xb4,
+ 0x1b, 0xd2, 0x63, 0xe8, 0x67, 0x10, 0x2d, 0x87,
+ 0x71, 0x6e, 0x19, 0x60, 0xf4, 0xa4, 0x10, 0x52,
+ 0x73, 0x2d, 0x09, 0x5e, 0xdb, 0x6c, 0xdc, 0xcf,
+ 0x2d, 0xff, 0x03, 0x11, 0x95, 0x76, 0x90, 0xd7,
+ 0x87, 0x54, 0x43, 0xed, 0xc2, 0x36, 0x69, 0x14,
+ 0x72, 0x4a,
+ },
+ {
+ 0x16, 0x03, 0x01, 0x00, 0x72, 0x04, 0x00, 0x00,
+ 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65,
+ 0xe8, 0x8b, 0xde, 0xef, 0xba, 0xc5, 0x7e, 0x04,
+ 0xab, 0xfd, 0x79, 0x56, 0xf3, 0xe1, 0xa5, 0x3e,
+ 0x02, 0xdf, 0x69, 0x6d, 0x1f, 0x41, 0x9f, 0xbc,
+ 0x93, 0xe2, 0x6c, 0xf1, 0xb1, 0x38, 0xf5, 0x2b,
+ 0x8c, 0x4c, 0xf4, 0x74, 0xe1, 0x79, 0x35, 0x34,
+ 0x97, 0x9b, 0xd5, 0xba, 0xfd, 0xf7, 0x2f, 0x2d,
+ 0x9e, 0x84, 0x54, 0xee, 0x77, 0x59, 0x23, 0x8f,
+ 0xc8, 0x84, 0xb4, 0xd6, 0xea, 0x4c, 0x44, 0x8a,
+ 0xc6, 0x9c, 0xf9, 0x9b, 0x27, 0xea, 0x4f, 0x28,
+ 0x72, 0x33, 0x12, 0x20, 0x7c, 0xd7, 0x3f, 0x56,
+ 0xa6, 0x76, 0xc7, 0x48, 0xe4, 0x2d, 0x6f, 0x14,
+ 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03, 0x01,
+ 0x00, 0x30, 0x36, 0xe3, 0xd4, 0xf7, 0xb1, 0x69,
+ 0x18, 0x8d, 0x09, 0xba, 0x52, 0x1e, 0xd5, 0x7d,
+ 0x2c, 0x15, 0x3a, 0xd6, 0xe3, 0x99, 0x30, 0x2c,
+ 0x99, 0x97, 0xbc, 0x19, 0x3c, 0x63, 0xa1, 0x25,
+ 0x68, 0xbc, 0x8a, 0x16, 0x47, 0xec, 0xae, 0x13,
+ 0xa4, 0x03, 0x96, 0x29, 0x11, 0x92, 0x90, 0x1a,
+ 0xc8, 0xa4, 0x17, 0x03, 0x01, 0x00, 0x20, 0xc1,
+ 0x10, 0x1d, 0xa6, 0xf1, 0xe2, 0x8a, 0xcc, 0x37,
+ 0x7d, 0x8e, 0x05, 0x00, 0xfb, 0xd1, 0x9f, 0xc7,
+ 0x11, 0xd2, 0x00, 0xb4, 0x27, 0x0a, 0x25, 0x14,
+ 0xd9, 0x79, 0x1b, 0xcb, 0x4d, 0x81, 0x61, 0x17,
+ 0x03, 0x01, 0x00, 0x30, 0x5c, 0x7c, 0x2d, 0xc0,
+ 0x9e, 0xa6, 0xc4, 0x8e, 0xfd, 0xf4, 0xe2, 0xe5,
+ 0xe4, 0xe6, 0x56, 0x9f, 0x7d, 0x4c, 0x4c, 0x2d,
+ 0xb7, 0xa9, 0xac, 0xfa, 0x9f, 0x12, 0x7f, 0x2d,
+ 0x30, 0x57, 0xe4, 0x8e, 0x30, 0x86, 0x65, 0x59,
+ 0xcd, 0x24, 0xda, 0xe2, 0x8a, 0x7b, 0x0c, 0x5e,
+ 0x86, 0x05, 0x06, 0x2a, 0x15, 0x03, 0x01, 0x00,
+ 0x20, 0xd6, 0xb7, 0x70, 0xf8, 0x47, 0xbc, 0x0f,
+ 0xf4, 0x66, 0x98, 0x1b, 0x1e, 0x8a, 0x8c, 0x0b,
+ 0xa1, 0x4a, 0x04, 0x29, 0x60, 0x72, 0x8b, 0xc4,
+ 0x73, 0xc1, 0xd6, 0x41, 0x72, 0xb7, 0x17, 0x39,
+ 0xda,
+ },
+}
+
var sslv3ServerScript = [][]byte{
{
0x16, 0x03, 0x00, 0x00, 0x54, 0x01, 0x00, 0x00,
@@ -1559,38 +1947,115 @@ var serverResumeTest = [][]byte{
},
}
-var clientauthTests = []clientauthTest{
+var clientauthRSATests = []clientauthTest{
// Server asks for cert with empty CA list, client doesn't give it.
// go test -run "TestRunServer" -serve -clientauth 1
{"RequestClientCert, none given", RequestClientCert, nil, [][]byte{
{
- 0x16, 0x03, 0x01, 0x00, 0x54, 0x01, 0x00, 0x00,
- 0x50, 0x03, 0x01, 0x50, 0x77, 0x43, 0x9e, 0x31,
- 0xe6, 0x36, 0x5e, 0x5e, 0x24, 0xe4, 0x0d, 0x26,
- 0x34, 0xa7, 0x1c, 0x2e, 0x59, 0x6d, 0xa5, 0x3e,
- 0x72, 0xf3, 0xa3, 0x1c, 0xbc, 0xb3, 0x27, 0xaf,
- 0x92, 0x5b, 0x7d, 0x00, 0x00, 0x28, 0x00, 0x39,
- 0x00, 0x38, 0x00, 0x35, 0x00, 0x16, 0x00, 0x13,
- 0x00, 0x0a, 0x00, 0x33, 0x00, 0x32, 0x00, 0x2f,
- 0x00, 0x05, 0x00, 0x04, 0x00, 0x15, 0x00, 0x12,
- 0x00, 0x09, 0x00, 0x14, 0x00, 0x11, 0x00, 0x08,
- 0x00, 0x06, 0x00, 0x03, 0x00, 0xff, 0x02, 0x01,
- 0x00,
+ 0x16, 0x03, 0x01, 0x01, 0x1e, 0x01, 0x00, 0x01,
+ 0x1a, 0x03, 0x03, 0x51, 0xe5, 0x6c, 0xb5, 0x5a,
+ 0xc2, 0xf5, 0xf0, 0x92, 0x94, 0x8a, 0x64, 0x18,
+ 0xa4, 0x2b, 0x82, 0x07, 0xbc, 0xd9, 0xd9, 0xf9,
+ 0x7b, 0xd2, 0xd0, 0xee, 0xa2, 0x70, 0x4e, 0x23,
+ 0x88, 0x7c, 0x95, 0x00, 0x00, 0x82, 0xc0, 0x30,
+ 0xc0, 0x2c, 0xc0, 0x28, 0xc0, 0x24, 0xc0, 0x14,
+ 0xc0, 0x0a, 0x00, 0xa3, 0x00, 0x9f, 0x00, 0x6b,
+ 0x00, 0x6a, 0x00, 0x39, 0x00, 0x38, 0xc0, 0x32,
+ 0xc0, 0x2e, 0xc0, 0x2a, 0xc0, 0x26, 0xc0, 0x0f,
+ 0xc0, 0x05, 0x00, 0x9d, 0x00, 0x3d, 0x00, 0x35,
+ 0xc0, 0x12, 0xc0, 0x08, 0x00, 0x16, 0x00, 0x13,
+ 0xc0, 0x0d, 0xc0, 0x03, 0x00, 0x0a, 0xc0, 0x2f,
+ 0xc0, 0x2b, 0xc0, 0x27, 0xc0, 0x23, 0xc0, 0x13,
+ 0xc0, 0x09, 0x00, 0xa2, 0x00, 0x9e, 0x00, 0x67,
+ 0x00, 0x40, 0x00, 0x33, 0x00, 0x32, 0xc0, 0x31,
+ 0xc0, 0x2d, 0xc0, 0x29, 0xc0, 0x25, 0xc0, 0x0e,
+ 0xc0, 0x04, 0x00, 0x9c, 0x00, 0x3c, 0x00, 0x2f,
+ 0x00, 0x07, 0xc0, 0x11, 0xc0, 0x07, 0xc0, 0x0c,
+ 0xc0, 0x02, 0x00, 0x05, 0x00, 0x04, 0x00, 0x15,
+ 0x00, 0x12, 0x00, 0x09, 0x00, 0x14, 0x00, 0x11,
+ 0x00, 0x08, 0x00, 0x06, 0x00, 0x03, 0x00, 0xff,
+ 0x01, 0x00, 0x00, 0x6f, 0x00, 0x0b, 0x00, 0x04,
+ 0x03, 0x00, 0x01, 0x02, 0x00, 0x0a, 0x00, 0x34,
+ 0x00, 0x32, 0x00, 0x0e, 0x00, 0x0d, 0x00, 0x19,
+ 0x00, 0x0b, 0x00, 0x0c, 0x00, 0x18, 0x00, 0x09,
+ 0x00, 0x0a, 0x00, 0x16, 0x00, 0x17, 0x00, 0x08,
+ 0x00, 0x06, 0x00, 0x07, 0x00, 0x14, 0x00, 0x15,
+ 0x00, 0x04, 0x00, 0x05, 0x00, 0x12, 0x00, 0x13,
+ 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x0f,
+ 0x00, 0x10, 0x00, 0x11, 0x00, 0x23, 0x00, 0x00,
+ 0x00, 0x0d, 0x00, 0x22, 0x00, 0x20, 0x06, 0x01,
+ 0x06, 0x02, 0x06, 0x03, 0x05, 0x01, 0x05, 0x02,
+ 0x05, 0x03, 0x04, 0x01, 0x04, 0x02, 0x04, 0x03,
+ 0x03, 0x01, 0x03, 0x02, 0x03, 0x03, 0x02, 0x01,
+ 0x02, 0x02, 0x02, 0x03, 0x01, 0x01, 0x00, 0x0f,
+ 0x00, 0x01, 0x01,
},
{
- 0x16, 0x03, 0x01, 0x00, 0x2a, 0x02, 0x00, 0x00,
- 0x26, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x16, 0x03, 0x01, 0x00, 0x30, 0x02, 0x00, 0x00,
+ 0x2c, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x16,
- 0x03, 0x01, 0x02, 0xbe, 0x0b, 0x00, 0x02, 0xba,
- 0x00, 0x02, 0xb7, 0x00, 0x02, 0xb4, 0x30, 0x82,
- 0x02, 0xb0, 0x30, 0x82, 0x02, 0x19, 0xa0, 0x03,
- 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0x85, 0xb0,
- 0xbb, 0xa4, 0x8a, 0x7f, 0xb8, 0xca, 0x30, 0x0d,
- 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
- 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x45, 0x31,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
+ 0x04, 0x00, 0x23, 0x00, 0x00, 0x16, 0x03, 0x01,
+ 0x02, 0xbe, 0x0b, 0x00, 0x02, 0xba, 0x00, 0x02,
+ 0xb7, 0x00, 0x02, 0xb4, 0x30, 0x82, 0x02, 0xb0,
+ 0x30, 0x82, 0x02, 0x19, 0xa0, 0x03, 0x02, 0x01,
+ 0x02, 0x02, 0x09, 0x00, 0x85, 0xb0, 0xbb, 0xa4,
+ 0x8a, 0x7f, 0xb8, 0xca, 0x30, 0x0d, 0x06, 0x09,
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+ 0x05, 0x05, 0x00, 0x30, 0x45, 0x31, 0x0b, 0x30,
+ 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+ 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
+ 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d,
+ 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31,
+ 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a,
+ 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e,
+ 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69,
+ 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c,
+ 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x30,
+ 0x30, 0x34, 0x32, 0x34, 0x30, 0x39, 0x30, 0x39,
+ 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x31, 0x31, 0x30,
+ 0x34, 0x32, 0x34, 0x30, 0x39, 0x30, 0x39, 0x33,
+ 0x38, 0x5a, 0x30, 0x45, 0x31, 0x0b, 0x30, 0x09,
+ 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x41,
+ 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
+ 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, 0x65,
+ 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x21,
+ 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13,
+ 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
+ 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, 0x74,
+ 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74,
+ 0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09,
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+ 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30,
+ 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xbb, 0x79,
+ 0xd6, 0xf5, 0x17, 0xb5, 0xe5, 0xbf, 0x46, 0x10,
+ 0xd0, 0xdc, 0x69, 0xbe, 0xe6, 0x2b, 0x07, 0x43,
+ 0x5a, 0xd0, 0x03, 0x2d, 0x8a, 0x7a, 0x43, 0x85,
+ 0xb7, 0x14, 0x52, 0xe7, 0xa5, 0x65, 0x4c, 0x2c,
+ 0x78, 0xb8, 0x23, 0x8c, 0xb5, 0xb4, 0x82, 0xe5,
+ 0xde, 0x1f, 0x95, 0x3b, 0x7e, 0x62, 0xa5, 0x2c,
+ 0xa5, 0x33, 0xd6, 0xfe, 0x12, 0x5c, 0x7a, 0x56,
+ 0xfc, 0xf5, 0x06, 0xbf, 0xfa, 0x58, 0x7b, 0x26,
+ 0x3f, 0xb5, 0xcd, 0x04, 0xd3, 0xd0, 0xc9, 0x21,
+ 0x96, 0x4a, 0xc7, 0xf4, 0x54, 0x9f, 0x5a, 0xbf,
+ 0xef, 0x42, 0x71, 0x00, 0xfe, 0x18, 0x99, 0x07,
+ 0x7f, 0x7e, 0x88, 0x7d, 0x7d, 0xf1, 0x04, 0x39,
+ 0xc4, 0xa2, 0x2e, 0xdb, 0x51, 0xc9, 0x7c, 0xe3,
+ 0xc0, 0x4c, 0x3b, 0x32, 0x66, 0x01, 0xcf, 0xaf,
+ 0xb1, 0x1d, 0xb8, 0x71, 0x9a, 0x1d, 0xdb, 0xdb,
+ 0x89, 0x6b, 0xae, 0xda, 0x2d, 0x79, 0x02, 0x03,
+ 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7, 0x30, 0x81,
+ 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e,
+ 0x04, 0x16, 0x04, 0x14, 0xb1, 0xad, 0xe2, 0x85,
+ 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69, 0xce, 0x23,
+ 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18, 0x88, 0x39,
+ 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04,
+ 0x6e, 0x30, 0x6c, 0x80, 0x14, 0xb1, 0xad, 0xe2,
+ 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69, 0xce,
+ 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18, 0x88,
+ 0x39, 0xa1, 0x49, 0xa4, 0x47, 0x30, 0x45, 0x31,
0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11,
0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53,
@@ -1599,158 +2064,200 @@ var clientauthTests = []clientauthTest{
0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65,
0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64,
0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79,
- 0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d,
- 0x31, 0x30, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39,
- 0x30, 0x39, 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x31,
- 0x31, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39, 0x30,
- 0x39, 0x33, 0x38, 0x5a, 0x30, 0x45, 0x31, 0x0b,
- 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
- 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06,
- 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f,
- 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65,
- 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04,
- 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72,
- 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67,
- 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20,
- 0x4c, 0x74, 0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d,
- 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
- 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d,
- 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00,
- 0xbb, 0x79, 0xd6, 0xf5, 0x17, 0xb5, 0xe5, 0xbf,
- 0x46, 0x10, 0xd0, 0xdc, 0x69, 0xbe, 0xe6, 0x2b,
- 0x07, 0x43, 0x5a, 0xd0, 0x03, 0x2d, 0x8a, 0x7a,
- 0x43, 0x85, 0xb7, 0x14, 0x52, 0xe7, 0xa5, 0x65,
- 0x4c, 0x2c, 0x78, 0xb8, 0x23, 0x8c, 0xb5, 0xb4,
- 0x82, 0xe5, 0xde, 0x1f, 0x95, 0x3b, 0x7e, 0x62,
- 0xa5, 0x2c, 0xa5, 0x33, 0xd6, 0xfe, 0x12, 0x5c,
- 0x7a, 0x56, 0xfc, 0xf5, 0x06, 0xbf, 0xfa, 0x58,
- 0x7b, 0x26, 0x3f, 0xb5, 0xcd, 0x04, 0xd3, 0xd0,
- 0xc9, 0x21, 0x96, 0x4a, 0xc7, 0xf4, 0x54, 0x9f,
- 0x5a, 0xbf, 0xef, 0x42, 0x71, 0x00, 0xfe, 0x18,
- 0x99, 0x07, 0x7f, 0x7e, 0x88, 0x7d, 0x7d, 0xf1,
- 0x04, 0x39, 0xc4, 0xa2, 0x2e, 0xdb, 0x51, 0xc9,
- 0x7c, 0xe3, 0xc0, 0x4c, 0x3b, 0x32, 0x66, 0x01,
- 0xcf, 0xaf, 0xb1, 0x1d, 0xb8, 0x71, 0x9a, 0x1d,
- 0xdb, 0xdb, 0x89, 0x6b, 0xae, 0xda, 0x2d, 0x79,
- 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7,
- 0x30, 0x81, 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55,
- 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xb1, 0xad,
- 0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69,
- 0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18,
- 0x88, 0x39, 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d,
- 0x23, 0x04, 0x6e, 0x30, 0x6c, 0x80, 0x14, 0xb1,
- 0xad, 0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb,
- 0x69, 0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e,
- 0x18, 0x88, 0x39, 0xa1, 0x49, 0xa4, 0x47, 0x30,
- 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
- 0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13,
- 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13,
- 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74,
- 0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06,
- 0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e,
- 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57,
- 0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50,
- 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09,
- 0x00, 0x85, 0xb0, 0xbb, 0xa4, 0x8a, 0x7f, 0xb8,
- 0xca, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13,
- 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30,
- 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
- 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81,
- 0x81, 0x00, 0x08, 0x6c, 0x45, 0x24, 0xc7, 0x6b,
- 0xb1, 0x59, 0xab, 0x0c, 0x52, 0xcc, 0xf2, 0xb0,
- 0x14, 0xd7, 0x87, 0x9d, 0x7a, 0x64, 0x75, 0xb5,
- 0x5a, 0x95, 0x66, 0xe4, 0xc5, 0x2b, 0x8e, 0xae,
- 0x12, 0x66, 0x1f, 0xeb, 0x4f, 0x38, 0xb3, 0x6e,
- 0x60, 0xd3, 0x92, 0xfd, 0xf7, 0x41, 0x08, 0xb5,
- 0x25, 0x13, 0xb1, 0x18, 0x7a, 0x24, 0xfb, 0x30,
- 0x1d, 0xba, 0xed, 0x98, 0xb9, 0x17, 0xec, 0xe7,
- 0xd7, 0x31, 0x59, 0xdb, 0x95, 0xd3, 0x1d, 0x78,
- 0xea, 0x50, 0x56, 0x5c, 0xd5, 0x82, 0x5a, 0x2d,
- 0x5a, 0x5f, 0x33, 0xc4, 0xb6, 0xd8, 0xc9, 0x75,
- 0x90, 0x96, 0x8c, 0x0f, 0x52, 0x98, 0xb5, 0xcd,
- 0x98, 0x1f, 0x89, 0x20, 0x5f, 0xf2, 0xa0, 0x1c,
- 0xa3, 0x1b, 0x96, 0x94, 0xdd, 0xa9, 0xfd, 0x57,
- 0xe9, 0x70, 0xe8, 0x26, 0x6d, 0x71, 0x99, 0x9b,
- 0x26, 0x6e, 0x38, 0x50, 0x29, 0x6c, 0x90, 0xa7,
- 0xbd, 0xd9, 0x16, 0x03, 0x01, 0x00, 0x08, 0x0d,
- 0x00, 0x00, 0x04, 0x01, 0x01, 0x00, 0x00, 0x16,
- 0x03, 0x01, 0x00, 0x04, 0x0e, 0x00, 0x00, 0x00,
+ 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09, 0x00, 0x85,
+ 0xb0, 0xbb, 0xa4, 0x8a, 0x7f, 0xb8, 0xca, 0x30,
+ 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05,
+ 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06,
+ 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
+ 0x01, 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00,
+ 0x08, 0x6c, 0x45, 0x24, 0xc7, 0x6b, 0xb1, 0x59,
+ 0xab, 0x0c, 0x52, 0xcc, 0xf2, 0xb0, 0x14, 0xd7,
+ 0x87, 0x9d, 0x7a, 0x64, 0x75, 0xb5, 0x5a, 0x95,
+ 0x66, 0xe4, 0xc5, 0x2b, 0x8e, 0xae, 0x12, 0x66,
+ 0x1f, 0xeb, 0x4f, 0x38, 0xb3, 0x6e, 0x60, 0xd3,
+ 0x92, 0xfd, 0xf7, 0x41, 0x08, 0xb5, 0x25, 0x13,
+ 0xb1, 0x18, 0x7a, 0x24, 0xfb, 0x30, 0x1d, 0xba,
+ 0xed, 0x98, 0xb9, 0x17, 0xec, 0xe7, 0xd7, 0x31,
+ 0x59, 0xdb, 0x95, 0xd3, 0x1d, 0x78, 0xea, 0x50,
+ 0x56, 0x5c, 0xd5, 0x82, 0x5a, 0x2d, 0x5a, 0x5f,
+ 0x33, 0xc4, 0xb6, 0xd8, 0xc9, 0x75, 0x90, 0x96,
+ 0x8c, 0x0f, 0x52, 0x98, 0xb5, 0xcd, 0x98, 0x1f,
+ 0x89, 0x20, 0x5f, 0xf2, 0xa0, 0x1c, 0xa3, 0x1b,
+ 0x96, 0x94, 0xdd, 0xa9, 0xfd, 0x57, 0xe9, 0x70,
+ 0xe8, 0x26, 0x6d, 0x71, 0x99, 0x9b, 0x26, 0x6e,
+ 0x38, 0x50, 0x29, 0x6c, 0x90, 0xa7, 0xbd, 0xd9,
+ 0x16, 0x03, 0x01, 0x00, 0x09, 0x0d, 0x00, 0x00,
+ 0x05, 0x02, 0x01, 0x40, 0x00, 0x00, 0x16, 0x03,
+ 0x01, 0x00, 0x04, 0x0e, 0x00, 0x00, 0x00,
},
{
0x16, 0x03, 0x01, 0x00, 0x07, 0x0b, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0x16, 0x03, 0x01, 0x00,
- 0x86, 0x10, 0x00, 0x00, 0x82, 0x00, 0x80, 0x04,
- 0x58, 0x63, 0x26, 0x32, 0x1b, 0x34, 0xbe, 0x10,
- 0xe4, 0xe4, 0x3e, 0xcd, 0x36, 0x7f, 0xa8, 0xa8,
- 0xe0, 0x19, 0xe8, 0x94, 0x13, 0xd9, 0x35, 0xc4,
- 0x71, 0xb4, 0x91, 0xd4, 0xbc, 0x74, 0x57, 0x9f,
- 0x93, 0xb7, 0x5d, 0x3b, 0x9c, 0xff, 0x5d, 0x79,
- 0xdb, 0x86, 0xfc, 0xdc, 0x74, 0x1e, 0x0c, 0xc6,
- 0xe8, 0x93, 0xcf, 0xaf, 0xba, 0x1d, 0xfd, 0x8a,
- 0xeb, 0xef, 0xbf, 0xfa, 0xa6, 0xe7, 0x53, 0x98,
- 0x60, 0x4e, 0x0e, 0x60, 0x7d, 0xea, 0x40, 0x8d,
- 0x1d, 0x8f, 0xa3, 0xc6, 0x83, 0xbc, 0xef, 0xb7,
- 0x9a, 0x4a, 0xe7, 0x99, 0xee, 0x0b, 0xc7, 0x46,
- 0x75, 0x45, 0x66, 0xe8, 0x5f, 0x4b, 0x08, 0xa4,
- 0xc1, 0x36, 0xd0, 0x36, 0x2c, 0xf2, 0x9a, 0x44,
- 0x1e, 0x5f, 0x22, 0xf4, 0xbe, 0x66, 0x66, 0x17,
- 0xd8, 0xb6, 0x0a, 0x89, 0xed, 0x22, 0x80, 0xdb,
- 0xad, 0x05, 0xd1, 0xb5, 0x93, 0xa1, 0x1c, 0x14,
+ 0x86, 0x10, 0x00, 0x00, 0x82, 0x00, 0x80, 0x36,
+ 0xfc, 0xd8, 0xc8, 0xa2, 0x67, 0xc8, 0xc6, 0xf4,
+ 0x28, 0x70, 0xe1, 0x5a, 0x02, 0x8f, 0xef, 0x42,
+ 0xe0, 0xd3, 0xb8, 0xd6, 0x6b, 0xe4, 0xee, 0x5c,
+ 0xcf, 0x42, 0xc4, 0xfa, 0xcd, 0x0f, 0xfe, 0xf4,
+ 0x76, 0x76, 0x47, 0x73, 0xa8, 0x72, 0x8f, 0xa2,
+ 0x56, 0x81, 0x83, 0xb8, 0x84, 0x72, 0x67, 0xdd,
+ 0xbe, 0x05, 0x4b, 0x84, 0xd9, 0xd2, 0xb6, 0xc2,
+ 0xe7, 0x20, 0xac, 0x1f, 0x46, 0x9d, 0x05, 0x47,
+ 0x8e, 0x89, 0xc0, 0x42, 0x57, 0x4a, 0xa2, 0x98,
+ 0xe5, 0x39, 0x4f, 0xc4, 0x27, 0x6d, 0x43, 0xa8,
+ 0x83, 0x76, 0xe6, 0xad, 0xe3, 0x17, 0x68, 0x31,
+ 0xcb, 0x7e, 0xfc, 0xe7, 0x4b, 0x76, 0x3d, 0x3c,
+ 0xfa, 0x77, 0x65, 0xc9, 0x4c, 0x5b, 0xce, 0x5e,
+ 0xf7, 0x8b, 0xa8, 0xa6, 0xdd, 0xb2, 0xef, 0x0b,
+ 0x46, 0x83, 0xdf, 0x0a, 0x8c, 0x22, 0x12, 0x6e,
+ 0xe1, 0x45, 0x54, 0x88, 0xd1, 0xe8, 0xd2, 0x14,
0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03, 0x01,
- 0x00, 0x24, 0x62, 0x6f, 0x3d, 0x30, 0x56, 0x97,
- 0xde, 0x03, 0x67, 0xa9, 0x63, 0x21, 0xb6, 0xe6,
- 0x05, 0x69, 0x94, 0xfb, 0x50, 0xc1, 0x99, 0xdd,
- 0xf6, 0xe8, 0x60, 0xbd, 0xe6, 0xba, 0xe3, 0x50,
- 0x0a, 0xcd, 0xde, 0x14, 0x16, 0xc4,
+ 0x00, 0x24, 0x30, 0x8c, 0x7d, 0x40, 0xfc, 0x5e,
+ 0x80, 0x9c, 0xc4, 0x7c, 0x62, 0x01, 0xa1, 0x37,
+ 0xcf, 0x1a, 0x75, 0x28, 0x8d, 0xeb, 0x63, 0xcc,
+ 0x02, 0xa6, 0x66, 0xdf, 0x36, 0x01, 0xb3, 0x9d,
+ 0x38, 0x42, 0x16, 0x91, 0xf0, 0x02,
},
{
- 0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03,
- 0x01, 0x00, 0x24, 0xf0, 0x21, 0xf6, 0x84, 0x6a,
- 0xe3, 0x6b, 0x8a, 0xc5, 0x46, 0x50, 0xca, 0x40,
- 0xea, 0x4e, 0x82, 0xc1, 0x70, 0x25, 0xd8, 0x7d,
- 0x60, 0xf5, 0x51, 0x7f, 0x64, 0x03, 0x9f, 0x53,
- 0xec, 0xfb, 0x57, 0xa9, 0xfc, 0x26, 0x15, 0x17,
- 0x03, 0x01, 0x00, 0x21, 0xa6, 0xc6, 0x94, 0x2b,
- 0xa9, 0xcb, 0x93, 0xff, 0xb6, 0xa6, 0xe7, 0xc5,
- 0x37, 0x86, 0x15, 0x37, 0x57, 0xce, 0xef, 0x54,
- 0x96, 0x5d, 0x50, 0xa0, 0x50, 0x69, 0x5e, 0x82,
- 0x61, 0x8d, 0x42, 0xfb, 0x78, 0x15, 0x03, 0x01,
- 0x00, 0x16, 0x45, 0xd1, 0x86, 0x68, 0x59, 0xc1,
- 0xaf, 0xac, 0x5c, 0x46, 0x8a, 0x68, 0x69, 0x0c,
- 0xd7, 0x67, 0xbf, 0xf0, 0x3e, 0xee, 0x45, 0x55,
+ 0x16, 0x03, 0x01, 0x00, 0x72, 0x04, 0x00, 0x00,
+ 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65,
+ 0xe8, 0x4b, 0xd1, 0xef, 0xba, 0x96, 0x9a, 0x2a,
+ 0x6c, 0x8c, 0x7e, 0x38, 0x10, 0x46, 0x86, 0x1d,
+ 0x19, 0x1d, 0x62, 0x29, 0x3f, 0x58, 0xfb, 0x6d,
+ 0x89, 0xd2, 0x81, 0x9a, 0x1c, 0xb3, 0x58, 0xb3,
+ 0x19, 0x39, 0x17, 0x47, 0x49, 0xc9, 0xfe, 0x4a,
+ 0x7a, 0x32, 0xac, 0x2c, 0x43, 0xf9, 0xa9, 0xea,
+ 0xec, 0x51, 0x46, 0xf1, 0xb8, 0x59, 0x23, 0x70,
+ 0xce, 0x7c, 0xb9, 0x47, 0x70, 0xa3, 0xc9, 0xae,
+ 0x47, 0x7b, 0x7e, 0xc7, 0xcf, 0x76, 0x12, 0x76,
+ 0x18, 0x90, 0x12, 0xcd, 0xf3, 0xd4, 0x27, 0x81,
+ 0xfc, 0x46, 0x03, 0x3e, 0x05, 0x87, 0x6f, 0x14,
+ 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03, 0x01,
+ 0x00, 0x24, 0xc3, 0xa0, 0x29, 0xb1, 0x52, 0x82,
+ 0xef, 0x85, 0xa1, 0x64, 0x0f, 0xe4, 0xa3, 0xfb,
+ 0xa7, 0x1d, 0x22, 0x4c, 0xcb, 0xd6, 0x5b, 0x18,
+ 0x61, 0xc7, 0x7c, 0xf2, 0x67, 0x4a, 0xc7, 0x11,
+ 0x9d, 0x8e, 0x0e, 0x15, 0x22, 0xcf, 0x17, 0x03,
+ 0x01, 0x00, 0x21, 0xfd, 0xbb, 0xf1, 0xa9, 0x7c,
+ 0xbf, 0x92, 0xb3, 0xfa, 0x2c, 0x08, 0x6f, 0x22,
+ 0x78, 0x80, 0xf2, 0x2e, 0x86, 0x26, 0x21, 0x36,
+ 0x3f, 0x32, 0xdf, 0xb6, 0x47, 0xa5, 0xf8, 0x27,
+ 0xc1, 0xe9, 0x53, 0x90, 0x15, 0x03, 0x01, 0x00,
+ 0x16, 0xfe, 0xef, 0x2e, 0xa0, 0x5d, 0xe0, 0xce,
+ 0x94, 0x20, 0x56, 0x61, 0x6e, 0xe5, 0x62, 0xce,
+ 0x27, 0x57, 0x3e, 0x30, 0x32, 0x77, 0x53,
},
}},
+
// Server asks for cert with empty CA list, client gives one
// go test -run "TestRunServer" -serve -clientauth 1
{"RequestClientCert, client gives it", RequestClientCert, []*x509.Certificate{clientCertificate}, [][]byte{
{
- 0x16, 0x03, 0x01, 0x00, 0x54, 0x01, 0x00, 0x00,
- 0x50, 0x03, 0x01, 0x50, 0x77, 0x43, 0x47, 0xfd,
- 0x1d, 0xb0, 0x60, 0x4c, 0x25, 0x86, 0x45, 0x4a,
- 0xe5, 0x3f, 0x80, 0x56, 0x18, 0x91, 0x5c, 0xe2,
- 0x62, 0xc5, 0x77, 0xc2, 0x92, 0xdd, 0xdc, 0x39,
- 0x23, 0x1d, 0xc5, 0x00, 0x00, 0x28, 0x00, 0x39,
- 0x00, 0x38, 0x00, 0x35, 0x00, 0x16, 0x00, 0x13,
- 0x00, 0x0a, 0x00, 0x33, 0x00, 0x32, 0x00, 0x2f,
- 0x00, 0x05, 0x00, 0x04, 0x00, 0x15, 0x00, 0x12,
- 0x00, 0x09, 0x00, 0x14, 0x00, 0x11, 0x00, 0x08,
- 0x00, 0x06, 0x00, 0x03, 0x00, 0xff, 0x02, 0x01,
- 0x00,
+ 0x16, 0x03, 0x01, 0x01, 0x1e, 0x01, 0x00, 0x01,
+ 0x1a, 0x03, 0x03, 0x51, 0xe5, 0x74, 0x0e, 0x95,
+ 0x6f, 0x4f, 0x4a, 0xbf, 0xb7, 0xc0, 0x6c, 0xac,
+ 0xd9, 0xfe, 0x7d, 0xd0, 0x51, 0x19, 0x62, 0x62,
+ 0x1c, 0x6e, 0x57, 0x77, 0xd2, 0x31, 0xaf, 0x88,
+ 0xb9, 0xc0, 0x1d, 0x00, 0x00, 0x82, 0xc0, 0x30,
+ 0xc0, 0x2c, 0xc0, 0x28, 0xc0, 0x24, 0xc0, 0x14,
+ 0xc0, 0x0a, 0x00, 0xa3, 0x00, 0x9f, 0x00, 0x6b,
+ 0x00, 0x6a, 0x00, 0x39, 0x00, 0x38, 0xc0, 0x32,
+ 0xc0, 0x2e, 0xc0, 0x2a, 0xc0, 0x26, 0xc0, 0x0f,
+ 0xc0, 0x05, 0x00, 0x9d, 0x00, 0x3d, 0x00, 0x35,
+ 0xc0, 0x12, 0xc0, 0x08, 0x00, 0x16, 0x00, 0x13,
+ 0xc0, 0x0d, 0xc0, 0x03, 0x00, 0x0a, 0xc0, 0x2f,
+ 0xc0, 0x2b, 0xc0, 0x27, 0xc0, 0x23, 0xc0, 0x13,
+ 0xc0, 0x09, 0x00, 0xa2, 0x00, 0x9e, 0x00, 0x67,
+ 0x00, 0x40, 0x00, 0x33, 0x00, 0x32, 0xc0, 0x31,
+ 0xc0, 0x2d, 0xc0, 0x29, 0xc0, 0x25, 0xc0, 0x0e,
+ 0xc0, 0x04, 0x00, 0x9c, 0x00, 0x3c, 0x00, 0x2f,
+ 0x00, 0x07, 0xc0, 0x11, 0xc0, 0x07, 0xc0, 0x0c,
+ 0xc0, 0x02, 0x00, 0x05, 0x00, 0x04, 0x00, 0x15,
+ 0x00, 0x12, 0x00, 0x09, 0x00, 0x14, 0x00, 0x11,
+ 0x00, 0x08, 0x00, 0x06, 0x00, 0x03, 0x00, 0xff,
+ 0x01, 0x00, 0x00, 0x6f, 0x00, 0x0b, 0x00, 0x04,
+ 0x03, 0x00, 0x01, 0x02, 0x00, 0x0a, 0x00, 0x34,
+ 0x00, 0x32, 0x00, 0x0e, 0x00, 0x0d, 0x00, 0x19,
+ 0x00, 0x0b, 0x00, 0x0c, 0x00, 0x18, 0x00, 0x09,
+ 0x00, 0x0a, 0x00, 0x16, 0x00, 0x17, 0x00, 0x08,
+ 0x00, 0x06, 0x00, 0x07, 0x00, 0x14, 0x00, 0x15,
+ 0x00, 0x04, 0x00, 0x05, 0x00, 0x12, 0x00, 0x13,
+ 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x0f,
+ 0x00, 0x10, 0x00, 0x11, 0x00, 0x23, 0x00, 0x00,
+ 0x00, 0x0d, 0x00, 0x22, 0x00, 0x20, 0x06, 0x01,
+ 0x06, 0x02, 0x06, 0x03, 0x05, 0x01, 0x05, 0x02,
+ 0x05, 0x03, 0x04, 0x01, 0x04, 0x02, 0x04, 0x03,
+ 0x03, 0x01, 0x03, 0x02, 0x03, 0x03, 0x02, 0x01,
+ 0x02, 0x02, 0x02, 0x03, 0x01, 0x01, 0x00, 0x0f,
+ 0x00, 0x01, 0x01,
},
{
- 0x16, 0x03, 0x01, 0x00, 0x2a, 0x02, 0x00, 0x00,
- 0x26, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x16, 0x03, 0x01, 0x00, 0x30, 0x02, 0x00, 0x00,
+ 0x2c, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x16,
- 0x03, 0x01, 0x02, 0xbe, 0x0b, 0x00, 0x02, 0xba,
- 0x00, 0x02, 0xb7, 0x00, 0x02, 0xb4, 0x30, 0x82,
- 0x02, 0xb0, 0x30, 0x82, 0x02, 0x19, 0xa0, 0x03,
- 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0x85, 0xb0,
- 0xbb, 0xa4, 0x8a, 0x7f, 0xb8, 0xca, 0x30, 0x0d,
- 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
- 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x45, 0x31,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
+ 0x04, 0x00, 0x23, 0x00, 0x00, 0x16, 0x03, 0x01,
+ 0x02, 0xbe, 0x0b, 0x00, 0x02, 0xba, 0x00, 0x02,
+ 0xb7, 0x00, 0x02, 0xb4, 0x30, 0x82, 0x02, 0xb0,
+ 0x30, 0x82, 0x02, 0x19, 0xa0, 0x03, 0x02, 0x01,
+ 0x02, 0x02, 0x09, 0x00, 0x85, 0xb0, 0xbb, 0xa4,
+ 0x8a, 0x7f, 0xb8, 0xca, 0x30, 0x0d, 0x06, 0x09,
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+ 0x05, 0x05, 0x00, 0x30, 0x45, 0x31, 0x0b, 0x30,
+ 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+ 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
+ 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d,
+ 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31,
+ 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a,
+ 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e,
+ 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69,
+ 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c,
+ 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x30,
+ 0x30, 0x34, 0x32, 0x34, 0x30, 0x39, 0x30, 0x39,
+ 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x31, 0x31, 0x30,
+ 0x34, 0x32, 0x34, 0x30, 0x39, 0x30, 0x39, 0x33,
+ 0x38, 0x5a, 0x30, 0x45, 0x31, 0x0b, 0x30, 0x09,
+ 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x41,
+ 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
+ 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, 0x65,
+ 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x21,
+ 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13,
+ 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
+ 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, 0x74,
+ 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74,
+ 0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09,
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+ 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30,
+ 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xbb, 0x79,
+ 0xd6, 0xf5, 0x17, 0xb5, 0xe5, 0xbf, 0x46, 0x10,
+ 0xd0, 0xdc, 0x69, 0xbe, 0xe6, 0x2b, 0x07, 0x43,
+ 0x5a, 0xd0, 0x03, 0x2d, 0x8a, 0x7a, 0x43, 0x85,
+ 0xb7, 0x14, 0x52, 0xe7, 0xa5, 0x65, 0x4c, 0x2c,
+ 0x78, 0xb8, 0x23, 0x8c, 0xb5, 0xb4, 0x82, 0xe5,
+ 0xde, 0x1f, 0x95, 0x3b, 0x7e, 0x62, 0xa5, 0x2c,
+ 0xa5, 0x33, 0xd6, 0xfe, 0x12, 0x5c, 0x7a, 0x56,
+ 0xfc, 0xf5, 0x06, 0xbf, 0xfa, 0x58, 0x7b, 0x26,
+ 0x3f, 0xb5, 0xcd, 0x04, 0xd3, 0xd0, 0xc9, 0x21,
+ 0x96, 0x4a, 0xc7, 0xf4, 0x54, 0x9f, 0x5a, 0xbf,
+ 0xef, 0x42, 0x71, 0x00, 0xfe, 0x18, 0x99, 0x07,
+ 0x7f, 0x7e, 0x88, 0x7d, 0x7d, 0xf1, 0x04, 0x39,
+ 0xc4, 0xa2, 0x2e, 0xdb, 0x51, 0xc9, 0x7c, 0xe3,
+ 0xc0, 0x4c, 0x3b, 0x32, 0x66, 0x01, 0xcf, 0xaf,
+ 0xb1, 0x1d, 0xb8, 0x71, 0x9a, 0x1d, 0xdb, 0xdb,
+ 0x89, 0x6b, 0xae, 0xda, 0x2d, 0x79, 0x02, 0x03,
+ 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7, 0x30, 0x81,
+ 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e,
+ 0x04, 0x16, 0x04, 0x14, 0xb1, 0xad, 0xe2, 0x85,
+ 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69, 0xce, 0x23,
+ 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18, 0x88, 0x39,
+ 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04,
+ 0x6e, 0x30, 0x6c, 0x80, 0x14, 0xb1, 0xad, 0xe2,
+ 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69, 0xce,
+ 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18, 0x88,
+ 0x39, 0xa1, 0x49, 0xa4, 0x47, 0x30, 0x45, 0x31,
0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11,
0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53,
@@ -1759,82 +2266,31 @@ var clientauthTests = []clientauthTest{
0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65,
0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64,
0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79,
- 0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d,
- 0x31, 0x30, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39,
- 0x30, 0x39, 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x31,
- 0x31, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39, 0x30,
- 0x39, 0x33, 0x38, 0x5a, 0x30, 0x45, 0x31, 0x0b,
- 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
- 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06,
- 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f,
- 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65,
- 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04,
- 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72,
- 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67,
- 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20,
- 0x4c, 0x74, 0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d,
- 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
- 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d,
- 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00,
- 0xbb, 0x79, 0xd6, 0xf5, 0x17, 0xb5, 0xe5, 0xbf,
- 0x46, 0x10, 0xd0, 0xdc, 0x69, 0xbe, 0xe6, 0x2b,
- 0x07, 0x43, 0x5a, 0xd0, 0x03, 0x2d, 0x8a, 0x7a,
- 0x43, 0x85, 0xb7, 0x14, 0x52, 0xe7, 0xa5, 0x65,
- 0x4c, 0x2c, 0x78, 0xb8, 0x23, 0x8c, 0xb5, 0xb4,
- 0x82, 0xe5, 0xde, 0x1f, 0x95, 0x3b, 0x7e, 0x62,
- 0xa5, 0x2c, 0xa5, 0x33, 0xd6, 0xfe, 0x12, 0x5c,
- 0x7a, 0x56, 0xfc, 0xf5, 0x06, 0xbf, 0xfa, 0x58,
- 0x7b, 0x26, 0x3f, 0xb5, 0xcd, 0x04, 0xd3, 0xd0,
- 0xc9, 0x21, 0x96, 0x4a, 0xc7, 0xf4, 0x54, 0x9f,
- 0x5a, 0xbf, 0xef, 0x42, 0x71, 0x00, 0xfe, 0x18,
- 0x99, 0x07, 0x7f, 0x7e, 0x88, 0x7d, 0x7d, 0xf1,
- 0x04, 0x39, 0xc4, 0xa2, 0x2e, 0xdb, 0x51, 0xc9,
- 0x7c, 0xe3, 0xc0, 0x4c, 0x3b, 0x32, 0x66, 0x01,
- 0xcf, 0xaf, 0xb1, 0x1d, 0xb8, 0x71, 0x9a, 0x1d,
- 0xdb, 0xdb, 0x89, 0x6b, 0xae, 0xda, 0x2d, 0x79,
- 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7,
- 0x30, 0x81, 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55,
- 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xb1, 0xad,
- 0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69,
- 0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18,
- 0x88, 0x39, 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d,
- 0x23, 0x04, 0x6e, 0x30, 0x6c, 0x80, 0x14, 0xb1,
- 0xad, 0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb,
- 0x69, 0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e,
- 0x18, 0x88, 0x39, 0xa1, 0x49, 0xa4, 0x47, 0x30,
- 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
- 0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13,
- 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13,
- 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74,
- 0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06,
- 0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e,
- 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57,
- 0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50,
- 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09,
- 0x00, 0x85, 0xb0, 0xbb, 0xa4, 0x8a, 0x7f, 0xb8,
- 0xca, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13,
- 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30,
- 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
- 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81,
- 0x81, 0x00, 0x08, 0x6c, 0x45, 0x24, 0xc7, 0x6b,
- 0xb1, 0x59, 0xab, 0x0c, 0x52, 0xcc, 0xf2, 0xb0,
- 0x14, 0xd7, 0x87, 0x9d, 0x7a, 0x64, 0x75, 0xb5,
- 0x5a, 0x95, 0x66, 0xe4, 0xc5, 0x2b, 0x8e, 0xae,
- 0x12, 0x66, 0x1f, 0xeb, 0x4f, 0x38, 0xb3, 0x6e,
- 0x60, 0xd3, 0x92, 0xfd, 0xf7, 0x41, 0x08, 0xb5,
- 0x25, 0x13, 0xb1, 0x18, 0x7a, 0x24, 0xfb, 0x30,
- 0x1d, 0xba, 0xed, 0x98, 0xb9, 0x17, 0xec, 0xe7,
- 0xd7, 0x31, 0x59, 0xdb, 0x95, 0xd3, 0x1d, 0x78,
- 0xea, 0x50, 0x56, 0x5c, 0xd5, 0x82, 0x5a, 0x2d,
- 0x5a, 0x5f, 0x33, 0xc4, 0xb6, 0xd8, 0xc9, 0x75,
- 0x90, 0x96, 0x8c, 0x0f, 0x52, 0x98, 0xb5, 0xcd,
- 0x98, 0x1f, 0x89, 0x20, 0x5f, 0xf2, 0xa0, 0x1c,
- 0xa3, 0x1b, 0x96, 0x94, 0xdd, 0xa9, 0xfd, 0x57,
- 0xe9, 0x70, 0xe8, 0x26, 0x6d, 0x71, 0x99, 0x9b,
- 0x26, 0x6e, 0x38, 0x50, 0x29, 0x6c, 0x90, 0xa7,
- 0xbd, 0xd9, 0x16, 0x03, 0x01, 0x00, 0x08, 0x0d,
- 0x00, 0x00, 0x04, 0x01, 0x01, 0x00, 0x00, 0x16,
- 0x03, 0x01, 0x00, 0x04, 0x0e, 0x00, 0x00, 0x00,
+ 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09, 0x00, 0x85,
+ 0xb0, 0xbb, 0xa4, 0x8a, 0x7f, 0xb8, 0xca, 0x30,
+ 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05,
+ 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06,
+ 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
+ 0x01, 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00,
+ 0x08, 0x6c, 0x45, 0x24, 0xc7, 0x6b, 0xb1, 0x59,
+ 0xab, 0x0c, 0x52, 0xcc, 0xf2, 0xb0, 0x14, 0xd7,
+ 0x87, 0x9d, 0x7a, 0x64, 0x75, 0xb5, 0x5a, 0x95,
+ 0x66, 0xe4, 0xc5, 0x2b, 0x8e, 0xae, 0x12, 0x66,
+ 0x1f, 0xeb, 0x4f, 0x38, 0xb3, 0x6e, 0x60, 0xd3,
+ 0x92, 0xfd, 0xf7, 0x41, 0x08, 0xb5, 0x25, 0x13,
+ 0xb1, 0x18, 0x7a, 0x24, 0xfb, 0x30, 0x1d, 0xba,
+ 0xed, 0x98, 0xb9, 0x17, 0xec, 0xe7, 0xd7, 0x31,
+ 0x59, 0xdb, 0x95, 0xd3, 0x1d, 0x78, 0xea, 0x50,
+ 0x56, 0x5c, 0xd5, 0x82, 0x5a, 0x2d, 0x5a, 0x5f,
+ 0x33, 0xc4, 0xb6, 0xd8, 0xc9, 0x75, 0x90, 0x96,
+ 0x8c, 0x0f, 0x52, 0x98, 0xb5, 0xcd, 0x98, 0x1f,
+ 0x89, 0x20, 0x5f, 0xf2, 0xa0, 0x1c, 0xa3, 0x1b,
+ 0x96, 0x94, 0xdd, 0xa9, 0xfd, 0x57, 0xe9, 0x70,
+ 0xe8, 0x26, 0x6d, 0x71, 0x99, 0x9b, 0x26, 0x6e,
+ 0x38, 0x50, 0x29, 0x6c, 0x90, 0xa7, 0xbd, 0xd9,
+ 0x16, 0x03, 0x01, 0x00, 0x09, 0x0d, 0x00, 0x00,
+ 0x05, 0x02, 0x01, 0x40, 0x00, 0x00, 0x16, 0x03,
+ 0x01, 0x00, 0x04, 0x0e, 0x00, 0x00, 0x00,
},
{
0x16, 0x03, 0x01, 0x01, 0xfb, 0x0b, 0x00, 0x01,
@@ -1902,66 +2358,778 @@ var clientauthTests = []clientauthTest{
0x51, 0x8d, 0x10, 0x7e, 0x4f, 0x94, 0x67, 0xdf,
0xa3, 0x4e, 0x70, 0x73, 0x8e, 0x90, 0x91, 0x85,
0x16, 0x03, 0x01, 0x00, 0x86, 0x10, 0x00, 0x00,
- 0x82, 0x00, 0x80, 0x81, 0x46, 0x43, 0xf9, 0xe7,
- 0xda, 0x8c, 0x92, 0x3a, 0x78, 0x1a, 0x86, 0xb3,
- 0xbe, 0x83, 0x22, 0xb6, 0xaa, 0x57, 0x37, 0x68,
- 0x9e, 0x54, 0x3f, 0xd3, 0xce, 0x4d, 0x5e, 0x2a,
- 0xdc, 0xb0, 0x49, 0x02, 0xbb, 0xc0, 0x45, 0x58,
- 0x79, 0x10, 0xc7, 0x94, 0x60, 0x9f, 0x1b, 0x5f,
- 0x18, 0x31, 0x37, 0x9c, 0xe0, 0xe6, 0xdf, 0x5e,
- 0x70, 0x44, 0xf6, 0x8b, 0xdf, 0xf1, 0xf6, 0x43,
- 0xc8, 0x2f, 0xd1, 0xce, 0xd0, 0xd6, 0x64, 0x4f,
- 0xe8, 0x2b, 0xfa, 0xd3, 0xd0, 0xd1, 0x2e, 0xaa,
- 0x9b, 0x1d, 0x13, 0x5c, 0xbe, 0x57, 0x41, 0x6c,
- 0x5e, 0x8d, 0xea, 0xa9, 0x3c, 0x58, 0xa0, 0x30,
- 0x92, 0x77, 0x7a, 0xed, 0x64, 0x58, 0xe5, 0x7f,
- 0x6a, 0x93, 0x89, 0x66, 0x3d, 0x13, 0x16, 0x56,
- 0xa0, 0xad, 0xdc, 0x68, 0x95, 0x87, 0x81, 0xd0,
- 0x90, 0x4d, 0x5f, 0xfe, 0x3e, 0x83, 0x15, 0x2e,
- 0x50, 0x3c, 0xdd, 0x16, 0x03, 0x01, 0x00, 0x86,
- 0x0f, 0x00, 0x00, 0x82, 0x00, 0x80, 0x2b, 0xf8,
- 0x56, 0x48, 0xbb, 0x02, 0x37, 0x15, 0x02, 0x74,
- 0x33, 0x53, 0x65, 0xa7, 0x7c, 0x2f, 0xc6, 0x5d,
- 0x80, 0x59, 0xc1, 0xc2, 0x3b, 0xa9, 0xde, 0x4e,
- 0x70, 0x51, 0xd2, 0xde, 0x58, 0x7f, 0xd8, 0xb9,
- 0xb6, 0x3b, 0xc8, 0xaa, 0xfc, 0x3d, 0x53, 0x2d,
- 0x61, 0x4d, 0xf5, 0x60, 0x12, 0xc2, 0xa5, 0x39,
- 0x0c, 0xa7, 0xc6, 0xac, 0x26, 0x4b, 0xf4, 0x5f,
- 0xe9, 0xf4, 0xf2, 0x73, 0x48, 0xe4, 0x3b, 0xee,
- 0xf2, 0xee, 0xc0, 0xee, 0xfb, 0x5b, 0x60, 0xc2,
- 0x74, 0xe6, 0xf6, 0x43, 0x3e, 0xa4, 0xf7, 0x97,
- 0x3d, 0xfc, 0xe9, 0x44, 0x21, 0x18, 0x46, 0x05,
- 0x33, 0xf8, 0xfe, 0x35, 0x5b, 0xe6, 0x8f, 0xef,
- 0x4d, 0x4c, 0x87, 0xf6, 0xb4, 0x6e, 0x6b, 0x39,
- 0xd8, 0xaa, 0x1b, 0x33, 0xc9, 0x1c, 0x66, 0x48,
- 0xbe, 0xfa, 0xb5, 0x92, 0x09, 0xfd, 0xb9, 0xb9,
- 0xca, 0xe6, 0x6d, 0x71, 0xc6, 0x89, 0x14, 0x03,
+ 0x82, 0x00, 0x80, 0x0a, 0x4e, 0x89, 0xdf, 0x3a,
+ 0x3f, 0xf0, 0x4f, 0xef, 0x1a, 0x90, 0xd4, 0x3c,
+ 0xaf, 0x10, 0x57, 0xb0, 0xa1, 0x5f, 0xcd, 0x62,
+ 0x01, 0xe9, 0x0c, 0x36, 0x42, 0xfd, 0xaf, 0x23,
+ 0xf9, 0x14, 0xa6, 0x72, 0x26, 0x4e, 0x01, 0xdb,
+ 0xac, 0xb7, 0x4c, 0xe6, 0xa9, 0x52, 0xe2, 0xec,
+ 0x26, 0x8c, 0x7a, 0x64, 0xf8, 0x0b, 0x4c, 0x2f,
+ 0xa9, 0xcb, 0x75, 0xaf, 0x60, 0xd4, 0xb4, 0xe6,
+ 0xe8, 0xdb, 0x78, 0x78, 0x85, 0xf6, 0x0c, 0x95,
+ 0xcc, 0xb6, 0x55, 0xb9, 0xba, 0x9e, 0x91, 0xbc,
+ 0x66, 0xdb, 0x1e, 0x28, 0xab, 0x73, 0xce, 0x8b,
+ 0xd0, 0xd3, 0xe8, 0xbc, 0xd0, 0x21, 0x28, 0xbd,
+ 0xfb, 0x74, 0x64, 0xde, 0x3b, 0x3b, 0xd3, 0x4c,
+ 0x32, 0x40, 0x82, 0xba, 0x91, 0x1e, 0xe8, 0x47,
+ 0xc2, 0x09, 0xb7, 0x16, 0xaa, 0x25, 0xa9, 0x3c,
+ 0x6c, 0xa7, 0xf8, 0xc9, 0x54, 0x84, 0xc6, 0xf7,
+ 0x56, 0x05, 0xa4, 0x16, 0x03, 0x01, 0x00, 0x86,
+ 0x0f, 0x00, 0x00, 0x82, 0x00, 0x80, 0x4b, 0xab,
+ 0xda, 0xac, 0x2a, 0xb3, 0xe6, 0x34, 0x55, 0xcd,
+ 0xf2, 0x4b, 0x67, 0xe3, 0xd3, 0xff, 0xa3, 0xf4,
+ 0x79, 0x82, 0x01, 0x47, 0x8a, 0xe3, 0x9f, 0x89,
+ 0x70, 0xbe, 0x24, 0x24, 0xb7, 0x69, 0x60, 0xed,
+ 0x55, 0xa0, 0xca, 0x72, 0xb6, 0x4a, 0xbc, 0x1d,
+ 0xe2, 0x3f, 0xb5, 0x31, 0xda, 0x02, 0xf6, 0x37,
+ 0x51, 0xf8, 0x4c, 0x88, 0x2e, 0xb3, 0x8a, 0xe8,
+ 0x7b, 0x4a, 0x90, 0x36, 0xe4, 0xa6, 0x31, 0x95,
+ 0x8b, 0xa0, 0xc6, 0x91, 0x12, 0xb9, 0x35, 0x4e,
+ 0x72, 0xeb, 0x5c, 0xa2, 0xe8, 0x4c, 0x68, 0xf9,
+ 0x69, 0xfa, 0x70, 0x60, 0x6c, 0x7f, 0x32, 0x99,
+ 0xf1, 0xc3, 0x2d, 0xb4, 0x59, 0x58, 0x87, 0xaf,
+ 0x67, 0x62, 0x90, 0xe7, 0x8d, 0xd0, 0xa3, 0x77,
+ 0x33, 0xc2, 0x9b, 0xd5, 0x9c, 0xc7, 0xea, 0x25,
+ 0x98, 0x76, 0x9c, 0xe0, 0x6a, 0x03, 0x3a, 0x10,
+ 0xfd, 0x10, 0x3d, 0x55, 0x53, 0xa0, 0x14, 0x03,
0x01, 0x00, 0x01, 0x01, 0x16, 0x03, 0x01, 0x00,
- 0x24, 0xe3, 0x2b, 0xef, 0x17, 0xd5, 0xa6, 0x4c,
- 0x2e, 0x10, 0xac, 0x9c, 0xfe, 0x0f, 0x18, 0x43,
- 0x95, 0x00, 0x81, 0xf7, 0x7c, 0x00, 0x5b, 0x89,
- 0x52, 0x41, 0xe4, 0x8a, 0x8a, 0x34, 0x31, 0x09,
- 0x48, 0x7c, 0xc5, 0xc3, 0x83,
+ 0x24, 0xd5, 0x12, 0xfc, 0xb9, 0x5a, 0xe3, 0x27,
+ 0x01, 0xbe, 0xc3, 0x77, 0x17, 0x1a, 0xbb, 0x4f,
+ 0xae, 0xd5, 0xa7, 0xee, 0x56, 0x61, 0x0d, 0x40,
+ 0xf4, 0xa4, 0xb5, 0xcc, 0x76, 0xfd, 0xbd, 0x13,
+ 0x04, 0xe1, 0xb8, 0xc7, 0x36,
},
{
- 0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03,
- 0x01, 0x00, 0x24, 0x24, 0xaa, 0xaa, 0x56, 0x8b,
- 0x41, 0x87, 0x01, 0xbe, 0x80, 0x05, 0x51, 0x36,
- 0x08, 0xfc, 0xaf, 0xff, 0x7f, 0xf4, 0x74, 0x84,
- 0x88, 0xdc, 0xb8, 0x8e, 0x70, 0x6c, 0x22, 0x04,
- 0xee, 0x45, 0x8d, 0xda, 0xed, 0xc6, 0x05, 0x17,
- 0x03, 0x01, 0x00, 0x21, 0x91, 0x49, 0x4b, 0xed,
- 0xa3, 0x41, 0xe9, 0x88, 0x3b, 0xa3, 0x01, 0xee,
- 0x77, 0x4e, 0x12, 0xb4, 0xcd, 0x5e, 0xcc, 0x45,
- 0x02, 0x5a, 0x20, 0xd6, 0xe8, 0xac, 0xcb, 0x60,
- 0xcb, 0x1b, 0xef, 0xf9, 0xc2, 0x15, 0x03, 0x01,
- 0x00, 0x16, 0xd4, 0xcd, 0x92, 0x3c, 0x10, 0x93,
- 0x68, 0xc3, 0xdd, 0xaf, 0xe9, 0xcb, 0x5d, 0x94,
- 0x1a, 0x06, 0x81, 0xa7, 0x78, 0x0f, 0xc3, 0x03,
+ 0x16, 0x03, 0x01, 0x02, 0x67, 0x04, 0x00, 0x02,
+ 0x63, 0x00, 0x00, 0x00, 0x00, 0x02, 0x5d, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65,
+ 0xe8, 0x4b, 0xd1, 0xef, 0xba, 0x1f, 0xe2, 0x69,
+ 0x07, 0x7f, 0x85, 0x2d, 0x4e, 0x2a, 0x2e, 0xbd,
+ 0x05, 0xe9, 0xc1, 0x6c, 0x9e, 0xbf, 0x47, 0x18,
+ 0x91, 0x77, 0xf7, 0xe8, 0xb6, 0x27, 0x37, 0xa6,
+ 0x6b, 0x87, 0x29, 0xbb, 0x3b, 0xe5, 0x68, 0x62,
+ 0x04, 0x3e, 0xad, 0x4d, 0xff, 0xad, 0xf1, 0x22,
+ 0x87, 0x8d, 0xf6, 0x04, 0x3b, 0x59, 0x22, 0xf7,
+ 0xfd, 0x88, 0x0e, 0xa4, 0x09, 0xc0, 0x0d, 0x10,
+ 0x80, 0x10, 0x79, 0xee, 0x70, 0x96, 0xdb, 0x22,
+ 0x8b, 0xb7, 0xac, 0xe0, 0x98, 0xad, 0xe9, 0xe3,
+ 0xcb, 0xea, 0x9f, 0xe6, 0x83, 0x28, 0x7c, 0x7e,
+ 0x4e, 0x9a, 0x8d, 0xd9, 0xf3, 0x86, 0xf4, 0x89,
+ 0x8b, 0x79, 0x8f, 0xbb, 0xe9, 0x74, 0x02, 0x02,
+ 0x14, 0x04, 0xea, 0xba, 0x16, 0x10, 0xa1, 0x85,
+ 0xbe, 0x4e, 0x4e, 0x92, 0xc5, 0x83, 0xf6, 0x1e,
+ 0x1f, 0xd4, 0x25, 0xc2, 0xc2, 0xb9, 0xce, 0x33,
+ 0x63, 0x66, 0x79, 0x1f, 0x54, 0x35, 0xc1, 0xe8,
+ 0x89, 0x34, 0x78, 0x94, 0x36, 0x14, 0xef, 0x01,
+ 0x1f, 0xf1, 0xbd, 0x77, 0x2c, 0x4d, 0xac, 0x5c,
+ 0x5c, 0x4a, 0xc6, 0xed, 0xd8, 0x0e, 0x72, 0x84,
+ 0x83, 0xdc, 0x56, 0x84, 0xc8, 0xf3, 0x89, 0x56,
+ 0xfd, 0x89, 0xc1, 0xc9, 0x9a, 0x29, 0x91, 0x7e,
+ 0x19, 0xe9, 0x8b, 0x5b, 0x11, 0x15, 0x4e, 0x6c,
+ 0xf4, 0x89, 0xe7, 0x6d, 0x68, 0x1e, 0xf9, 0x6c,
+ 0x23, 0x72, 0x05, 0x68, 0x82, 0x60, 0x84, 0x1f,
+ 0x83, 0x20, 0x09, 0x86, 0x10, 0x81, 0xec, 0xec,
+ 0xdc, 0x25, 0x53, 0x20, 0xfa, 0xa9, 0x41, 0x64,
+ 0xd6, 0x20, 0xf3, 0xf4, 0x52, 0xf2, 0x80, 0x62,
+ 0x83, 0xc9, 0x23, 0x66, 0x44, 0x95, 0x5a, 0x99,
+ 0x8a, 0xe1, 0x26, 0x63, 0xc1, 0x8b, 0x31, 0xf9,
+ 0x21, 0x06, 0x77, 0x04, 0x27, 0xf2, 0x0c, 0x63,
+ 0x83, 0x45, 0xa0, 0xa9, 0x7b, 0xcf, 0xdf, 0xd7,
+ 0x56, 0x75, 0xbc, 0xdd, 0x95, 0x36, 0xb1, 0x75,
+ 0x39, 0x05, 0x00, 0x3c, 0x8a, 0x79, 0xd6, 0xe9,
+ 0xf0, 0x4b, 0xdc, 0x51, 0x6b, 0x01, 0x94, 0x16,
+ 0x87, 0x12, 0x92, 0x6c, 0x07, 0xc1, 0xf5, 0x58,
+ 0xb7, 0x2a, 0x81, 0xf5, 0xa0, 0x37, 0x8b, 0xa6,
+ 0x22, 0xfe, 0x28, 0x0a, 0x7e, 0x68, 0xe2, 0xda,
+ 0x6c, 0x53, 0xee, 0x0e, 0x8d, 0x2d, 0x8b, 0x0b,
+ 0xda, 0xf8, 0x99, 0x3e, 0x0e, 0xed, 0x9f, 0xc1,
+ 0x2b, 0xf6, 0xfe, 0xe9, 0x52, 0x38, 0x7b, 0x83,
+ 0x9a, 0x50, 0xa6, 0xd7, 0x49, 0x83, 0x43, 0x7e,
+ 0x82, 0xec, 0xc7, 0x09, 0x3d, 0x3d, 0xb1, 0xee,
+ 0xe8, 0xc5, 0x6a, 0xc3, 0x3d, 0x4b, 0x4c, 0x6a,
+ 0xbb, 0x0b, 0x2c, 0x24, 0x2e, 0xdb, 0x7d, 0x57,
+ 0x87, 0xb4, 0x80, 0xa5, 0xae, 0xff, 0x54, 0xa8,
+ 0xa5, 0x27, 0x69, 0x95, 0xc8, 0xe7, 0x79, 0xc7,
+ 0x89, 0x2a, 0x73, 0x49, 0xcb, 0xf5, 0xc5, 0xbc,
+ 0x4a, 0xe0, 0x73, 0xa9, 0xbc, 0x88, 0x64, 0x96,
+ 0x98, 0xa5, 0x1e, 0xe3, 0x43, 0xc1, 0x7d, 0x78,
+ 0xc7, 0x94, 0x72, 0xd4, 0x2c, 0x6e, 0x85, 0x39,
+ 0x9a, 0xaf, 0xdb, 0xa1, 0xe9, 0xe2, 0xcb, 0x37,
+ 0x04, 0xc6, 0x8c, 0x81, 0xd3, 0x2a, 0xb7, 0xbe,
+ 0x6c, 0x07, 0x1f, 0x5e, 0xd9, 0x00, 0xd2, 0xf7,
+ 0xe1, 0xa7, 0xbc, 0x0c, 0xb6, 0x6d, 0xfb, 0x3f,
+ 0x3d, 0x24, 0xaa, 0xfb, 0x7e, 0xe1, 0xb5, 0x1b,
+ 0xff, 0x38, 0xaa, 0x69, 0x59, 0x38, 0x52, 0x9a,
+ 0x0e, 0x6d, 0xbc, 0xde, 0x4f, 0x13, 0x09, 0x17,
+ 0xc4, 0xa9, 0x05, 0x84, 0xbc, 0x50, 0xef, 0x40,
+ 0xb0, 0x4c, 0x24, 0x32, 0xed, 0x94, 0x2c, 0xdd,
+ 0xda, 0x20, 0x24, 0x67, 0xe2, 0xea, 0x71, 0x3d,
+ 0x4a, 0x04, 0x0d, 0x98, 0x29, 0x20, 0x4c, 0xeb,
+ 0x70, 0xce, 0x45, 0x9e, 0x5a, 0xaf, 0xb6, 0xa3,
+ 0x92, 0xc8, 0x28, 0xf2, 0xe3, 0xe8, 0x8a, 0x5d,
+ 0x0a, 0x33, 0x79, 0x9b, 0x6a, 0xf3, 0x30, 0x01,
+ 0x1d, 0x47, 0xbd, 0x01, 0xcc, 0x4d, 0x71, 0xc0,
+ 0x56, 0xfa, 0xfd, 0x37, 0xed, 0x0f, 0x27, 0xc0,
+ 0xbb, 0xa0, 0xee, 0xc3, 0x79, 0x8b, 0xe7, 0x41,
+ 0x8f, 0xfa, 0x3a, 0xcb, 0x45, 0x3b, 0x85, 0x9f,
+ 0x06, 0x90, 0xb2, 0x51, 0x7a, 0xc3, 0x11, 0x41,
+ 0x4b, 0xe3, 0x26, 0x94, 0x3e, 0xa2, 0xfd, 0x0a,
+ 0xda, 0x50, 0xf6, 0x50, 0x78, 0x19, 0x6c, 0x52,
+ 0xd1, 0x12, 0x76, 0xc2, 0x50, 0x2f, 0x0b, 0xca,
+ 0x33, 0xe5, 0x79, 0x93, 0x14, 0x03, 0x01, 0x00,
+ 0x01, 0x01, 0x16, 0x03, 0x01, 0x00, 0x24, 0x2b,
+ 0x51, 0x42, 0x95, 0x6b, 0xca, 0x9f, 0x42, 0x5d,
+ 0xd2, 0xd9, 0x67, 0xf9, 0x49, 0x30, 0xfd, 0x2a,
+ 0x46, 0xd3, 0x04, 0xf4, 0x86, 0xf9, 0x11, 0x34,
+ 0x82, 0xac, 0xe2, 0xc2, 0x2d, 0xc4, 0xd0, 0xfe,
+ 0xa9, 0xc9, 0x4b, 0x17, 0x03, 0x01, 0x00, 0x21,
+ 0x65, 0x1c, 0xe9, 0x5c, 0xb6, 0xe2, 0x7c, 0x8e,
+ 0x49, 0x12, 0x1b, 0xe6, 0x40, 0xd3, 0x97, 0x21,
+ 0x76, 0x01, 0xe5, 0x80, 0x5e, 0xf3, 0x11, 0x47,
+ 0x25, 0x02, 0x78, 0x8e, 0x6b, 0xae, 0xb3, 0xf3,
+ 0x59, 0x15, 0x03, 0x01, 0x00, 0x16, 0x38, 0xc1,
+ 0x99, 0x2e, 0xf8, 0x6f, 0x45, 0xa4, 0x10, 0x79,
+ 0x5b, 0xc1, 0x47, 0x9a, 0xf6, 0x5c, 0x90, 0xeb,
+ 0xa6, 0xe3, 0x1a, 0x24,
},
}},
}
+var tls11ECDHEAESServerScript = [][]byte{
+ {
+ 0x16, 0x03, 0x01, 0x01, 0x46, 0x01, 0x00, 0x01,
+ 0x42, 0x03, 0x03, 0x51, 0x9f, 0xa3, 0xb0, 0xb7,
+ 0x1d, 0x26, 0x93, 0x36, 0xc0, 0x8d, 0x7e, 0xf8,
+ 0x4f, 0x6f, 0xc9, 0x3c, 0x31, 0x1e, 0x7f, 0xb1,
+ 0xf0, 0xc1, 0x0f, 0xf9, 0x0c, 0xa2, 0xd5, 0xca,
+ 0x48, 0xe5, 0x35, 0x00, 0x00, 0xd0, 0xc0, 0x30,
+ 0xc0, 0x2c, 0xc0, 0x28, 0xc0, 0x24, 0xc0, 0x14,
+ 0xc0, 0x0a, 0xc0, 0x22, 0xc0, 0x21, 0x00, 0xa5,
+ 0x00, 0xa3, 0x00, 0xa1, 0x00, 0x9f, 0x00, 0x6b,
+ 0x00, 0x6a, 0x00, 0x69, 0x00, 0x68, 0x00, 0x39,
+ 0x00, 0x38, 0x00, 0x37, 0x00, 0x36, 0x00, 0x88,
+ 0x00, 0x87, 0x00, 0x86, 0x00, 0x85, 0xc0, 0x32,
+ 0xc0, 0x2e, 0xc0, 0x2a, 0xc0, 0x26, 0xc0, 0x0f,
+ 0xc0, 0x05, 0x00, 0x9d, 0x00, 0x3d, 0x00, 0x35,
+ 0x00, 0x84, 0xc0, 0x12, 0xc0, 0x08, 0xc0, 0x1c,
+ 0xc0, 0x1b, 0x00, 0x16, 0x00, 0x13, 0x00, 0x10,
+ 0x00, 0x0d, 0xc0, 0x0d, 0xc0, 0x03, 0x00, 0x0a,
+ 0xc0, 0x2f, 0xc0, 0x2b, 0xc0, 0x27, 0xc0, 0x23,
+ 0xc0, 0x13, 0xc0, 0x09, 0xc0, 0x1f, 0xc0, 0x1e,
+ 0x00, 0xa4, 0x00, 0xa2, 0x00, 0xa0, 0x00, 0x9e,
+ 0x00, 0x67, 0x00, 0x40, 0x00, 0x3f, 0x00, 0x3e,
+ 0x00, 0x33, 0x00, 0x32, 0x00, 0x31, 0x00, 0x30,
+ 0x00, 0x9a, 0x00, 0x99, 0x00, 0x98, 0x00, 0x97,
+ 0x00, 0x45, 0x00, 0x44, 0x00, 0x43, 0x00, 0x42,
+ 0xc0, 0x31, 0xc0, 0x2d, 0xc0, 0x29, 0xc0, 0x25,
+ 0xc0, 0x0e, 0xc0, 0x04, 0x00, 0x9c, 0x00, 0x3c,
+ 0x00, 0x2f, 0x00, 0x96, 0x00, 0x41, 0x00, 0x07,
+ 0xc0, 0x11, 0xc0, 0x07, 0xc0, 0x0c, 0xc0, 0x02,
+ 0x00, 0x05, 0x00, 0x04, 0x00, 0x15, 0x00, 0x12,
+ 0x00, 0x0f, 0x00, 0x0c, 0x00, 0x09, 0x00, 0x14,
+ 0x00, 0x11, 0x00, 0x0e, 0x00, 0x0b, 0x00, 0x08,
+ 0x00, 0x06, 0x00, 0x03, 0x00, 0xff, 0x01, 0x00,
+ 0x00, 0x49, 0x00, 0x0b, 0x00, 0x04, 0x03, 0x00,
+ 0x01, 0x02, 0x00, 0x0a, 0x00, 0x34, 0x00, 0x32,
+ 0x00, 0x0e, 0x00, 0x0d, 0x00, 0x19, 0x00, 0x0b,
+ 0x00, 0x0c, 0x00, 0x18, 0x00, 0x09, 0x00, 0x0a,
+ 0x00, 0x16, 0x00, 0x17, 0x00, 0x08, 0x00, 0x06,
+ 0x00, 0x07, 0x00, 0x14, 0x00, 0x15, 0x00, 0x04,
+ 0x00, 0x05, 0x00, 0x12, 0x00, 0x13, 0x00, 0x01,
+ 0x00, 0x02, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x10,
+ 0x00, 0x11, 0x00, 0x23, 0x00, 0x00, 0x00, 0x0f,
+ 0x00, 0x01, 0x01,
+ },
+ {
+ 0x16, 0x03, 0x02, 0x00, 0x30, 0x02, 0x00, 0x00,
+ 0x2c, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xc0, 0x13, 0x00, 0x00,
+ 0x04, 0x00, 0x23, 0x00, 0x00, 0x16, 0x03, 0x02,
+ 0x02, 0xbe, 0x0b, 0x00, 0x02, 0xba, 0x00, 0x02,
+ 0xb7, 0x00, 0x02, 0xb4, 0x30, 0x82, 0x02, 0xb0,
+ 0x30, 0x82, 0x02, 0x19, 0xa0, 0x03, 0x02, 0x01,
+ 0x02, 0x02, 0x09, 0x00, 0x85, 0xb0, 0xbb, 0xa4,
+ 0x8a, 0x7f, 0xb8, 0xca, 0x30, 0x0d, 0x06, 0x09,
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+ 0x05, 0x05, 0x00, 0x30, 0x45, 0x31, 0x0b, 0x30,
+ 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+ 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
+ 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d,
+ 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31,
+ 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a,
+ 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e,
+ 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69,
+ 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c,
+ 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x30,
+ 0x30, 0x34, 0x32, 0x34, 0x30, 0x39, 0x30, 0x39,
+ 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x31, 0x31, 0x30,
+ 0x34, 0x32, 0x34, 0x30, 0x39, 0x30, 0x39, 0x33,
+ 0x38, 0x5a, 0x30, 0x45, 0x31, 0x0b, 0x30, 0x09,
+ 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x41,
+ 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
+ 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, 0x65,
+ 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x21,
+ 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13,
+ 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
+ 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, 0x74,
+ 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74,
+ 0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09,
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+ 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30,
+ 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xbb, 0x79,
+ 0xd6, 0xf5, 0x17, 0xb5, 0xe5, 0xbf, 0x46, 0x10,
+ 0xd0, 0xdc, 0x69, 0xbe, 0xe6, 0x2b, 0x07, 0x43,
+ 0x5a, 0xd0, 0x03, 0x2d, 0x8a, 0x7a, 0x43, 0x85,
+ 0xb7, 0x14, 0x52, 0xe7, 0xa5, 0x65, 0x4c, 0x2c,
+ 0x78, 0xb8, 0x23, 0x8c, 0xb5, 0xb4, 0x82, 0xe5,
+ 0xde, 0x1f, 0x95, 0x3b, 0x7e, 0x62, 0xa5, 0x2c,
+ 0xa5, 0x33, 0xd6, 0xfe, 0x12, 0x5c, 0x7a, 0x56,
+ 0xfc, 0xf5, 0x06, 0xbf, 0xfa, 0x58, 0x7b, 0x26,
+ 0x3f, 0xb5, 0xcd, 0x04, 0xd3, 0xd0, 0xc9, 0x21,
+ 0x96, 0x4a, 0xc7, 0xf4, 0x54, 0x9f, 0x5a, 0xbf,
+ 0xef, 0x42, 0x71, 0x00, 0xfe, 0x18, 0x99, 0x07,
+ 0x7f, 0x7e, 0x88, 0x7d, 0x7d, 0xf1, 0x04, 0x39,
+ 0xc4, 0xa2, 0x2e, 0xdb, 0x51, 0xc9, 0x7c, 0xe3,
+ 0xc0, 0x4c, 0x3b, 0x32, 0x66, 0x01, 0xcf, 0xaf,
+ 0xb1, 0x1d, 0xb8, 0x71, 0x9a, 0x1d, 0xdb, 0xdb,
+ 0x89, 0x6b, 0xae, 0xda, 0x2d, 0x79, 0x02, 0x03,
+ 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7, 0x30, 0x81,
+ 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e,
+ 0x04, 0x16, 0x04, 0x14, 0xb1, 0xad, 0xe2, 0x85,
+ 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69, 0xce, 0x23,
+ 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18, 0x88, 0x39,
+ 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04,
+ 0x6e, 0x30, 0x6c, 0x80, 0x14, 0xb1, 0xad, 0xe2,
+ 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69, 0xce,
+ 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18, 0x88,
+ 0x39, 0xa1, 0x49, 0xa4, 0x47, 0x30, 0x45, 0x31,
+ 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+ 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11,
+ 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53,
+ 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74,
+ 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55,
+ 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65,
+ 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64,
+ 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79,
+ 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09, 0x00, 0x85,
+ 0xb0, 0xbb, 0xa4, 0x8a, 0x7f, 0xb8, 0xca, 0x30,
+ 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05,
+ 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06,
+ 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
+ 0x01, 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00,
+ 0x08, 0x6c, 0x45, 0x24, 0xc7, 0x6b, 0xb1, 0x59,
+ 0xab, 0x0c, 0x52, 0xcc, 0xf2, 0xb0, 0x14, 0xd7,
+ 0x87, 0x9d, 0x7a, 0x64, 0x75, 0xb5, 0x5a, 0x95,
+ 0x66, 0xe4, 0xc5, 0x2b, 0x8e, 0xae, 0x12, 0x66,
+ 0x1f, 0xeb, 0x4f, 0x38, 0xb3, 0x6e, 0x60, 0xd3,
+ 0x92, 0xfd, 0xf7, 0x41, 0x08, 0xb5, 0x25, 0x13,
+ 0xb1, 0x18, 0x7a, 0x24, 0xfb, 0x30, 0x1d, 0xba,
+ 0xed, 0x98, 0xb9, 0x17, 0xec, 0xe7, 0xd7, 0x31,
+ 0x59, 0xdb, 0x95, 0xd3, 0x1d, 0x78, 0xea, 0x50,
+ 0x56, 0x5c, 0xd5, 0x82, 0x5a, 0x2d, 0x5a, 0x5f,
+ 0x33, 0xc4, 0xb6, 0xd8, 0xc9, 0x75, 0x90, 0x96,
+ 0x8c, 0x0f, 0x52, 0x98, 0xb5, 0xcd, 0x98, 0x1f,
+ 0x89, 0x20, 0x5f, 0xf2, 0xa0, 0x1c, 0xa3, 0x1b,
+ 0x96, 0x94, 0xdd, 0xa9, 0xfd, 0x57, 0xe9, 0x70,
+ 0xe8, 0x26, 0x6d, 0x71, 0x99, 0x9b, 0x26, 0x6e,
+ 0x38, 0x50, 0x29, 0x6c, 0x90, 0xa7, 0xbd, 0xd9,
+ 0x16, 0x03, 0x02, 0x01, 0x0f, 0x0c, 0x00, 0x01,
+ 0x0b, 0x03, 0x00, 0x19, 0x85, 0x04, 0x01, 0x39,
+ 0xdc, 0xee, 0x44, 0x17, 0x5e, 0xdb, 0xd7, 0x27,
+ 0xaf, 0xb6, 0x56, 0xd9, 0xb4, 0x43, 0x5a, 0x99,
+ 0xcf, 0xaa, 0x31, 0x37, 0x0c, 0x6f, 0x3a, 0xa0,
+ 0xf8, 0x53, 0xc4, 0x74, 0xd1, 0x91, 0x0a, 0x46,
+ 0xf5, 0x38, 0x3b, 0x5c, 0x09, 0xd8, 0x97, 0xdc,
+ 0x4b, 0xaa, 0x70, 0x26, 0x48, 0xf2, 0xd6, 0x0b,
+ 0x31, 0xc9, 0xf8, 0xd4, 0x98, 0x43, 0xe1, 0x6c,
+ 0xd5, 0xc7, 0xb2, 0x8e, 0x0b, 0x01, 0xe6, 0xb6,
+ 0x00, 0x28, 0x80, 0x7b, 0xfc, 0x96, 0x8f, 0x0d,
+ 0xa2, 0x4f, 0xb0, 0x79, 0xaf, 0xdc, 0x61, 0x28,
+ 0x63, 0x33, 0x78, 0xf6, 0x31, 0x39, 0xfd, 0x8a,
+ 0xf4, 0x15, 0x18, 0x11, 0xfe, 0xdb, 0xd5, 0x07,
+ 0xda, 0x2c, 0xed, 0x49, 0xa0, 0x23, 0xbf, 0xd0,
+ 0x3a, 0x38, 0x1d, 0x54, 0xae, 0x1c, 0x7b, 0xea,
+ 0x29, 0xee, 0xd0, 0x38, 0xc1, 0x76, 0xa7, 0x7f,
+ 0x2a, 0xf4, 0xce, 0x1e, 0xac, 0xcc, 0x94, 0x79,
+ 0x90, 0x33, 0x00, 0x80, 0x16, 0x83, 0x9b, 0xf9,
+ 0x72, 0xdb, 0x9f, 0x55, 0x02, 0xe1, 0x04, 0xf7,
+ 0xb5, 0x3f, 0x4c, 0x71, 0x13, 0x5a, 0x91, 0xe9,
+ 0x1d, 0xeb, 0x9d, 0x9c, 0xfb, 0x88, 0xef, 0xca,
+ 0xec, 0x7d, 0x9b, 0xdd, 0xd9, 0xee, 0x2b, 0x8e,
+ 0xef, 0xf8, 0xb6, 0xc7, 0x7d, 0xfe, 0xda, 0x7f,
+ 0x90, 0x2e, 0x53, 0xf1, 0x64, 0x95, 0xfc, 0x66,
+ 0xfc, 0x87, 0x27, 0xb6, 0x9f, 0xc8, 0x3a, 0x95,
+ 0x68, 0x17, 0xe1, 0x7d, 0xf1, 0x88, 0xe8, 0x17,
+ 0x5f, 0x99, 0x90, 0x3f, 0x47, 0x47, 0x81, 0x06,
+ 0xe2, 0x8e, 0x22, 0x56, 0x8f, 0xc2, 0x14, 0xe5,
+ 0x62, 0xa7, 0x0d, 0x41, 0x3c, 0xc7, 0x4a, 0x0a,
+ 0x74, 0x4b, 0xda, 0x00, 0x8e, 0x4f, 0x90, 0xe6,
+ 0xd7, 0x68, 0xe5, 0x8b, 0xf2, 0x3f, 0x53, 0x1d,
+ 0x7a, 0xe6, 0xb3, 0xe9, 0x8a, 0xc9, 0x4d, 0x19,
+ 0xa6, 0xcf, 0xf9, 0xed, 0x5e, 0x26, 0xdc, 0x90,
+ 0x1c, 0x41, 0xad, 0x7c, 0x16, 0x03, 0x02, 0x00,
+ 0x04, 0x0e, 0x00, 0x00, 0x00,
+ },
+ {
+ 0x16, 0x03, 0x02, 0x00, 0x8a, 0x10, 0x00, 0x00,
+ 0x86, 0x85, 0x04, 0x01, 0x11, 0xf2, 0xa4, 0x2d,
+ 0x1a, 0x75, 0x6c, 0xbc, 0x2d, 0x91, 0x95, 0x07,
+ 0xbe, 0xd6, 0x41, 0x7a, 0xbb, 0xc2, 0x7b, 0xa6,
+ 0x9b, 0xe3, 0xdc, 0x41, 0x7f, 0x1e, 0x2e, 0xcc,
+ 0x6d, 0xa3, 0x85, 0x53, 0x98, 0x9f, 0x2d, 0xe6,
+ 0x3c, 0xb9, 0x82, 0xa6, 0x80, 0x53, 0x9b, 0x71,
+ 0xfd, 0x27, 0xe5, 0xe5, 0xdf, 0x13, 0xba, 0x56,
+ 0x62, 0x30, 0x4a, 0x57, 0x27, 0xa7, 0xcc, 0x26,
+ 0x54, 0xe8, 0x65, 0x6e, 0x4d, 0x00, 0xbf, 0x8a,
+ 0xcc, 0x89, 0x6a, 0x6c, 0x88, 0xda, 0x79, 0x4f,
+ 0xc5, 0xad, 0x6d, 0x1d, 0x7c, 0x53, 0x7b, 0x1a,
+ 0x96, 0xf2, 0xf8, 0x30, 0x01, 0x0b, 0xc2, 0xf0,
+ 0x78, 0x41, 0xf4, 0x0d, 0xe0, 0xbe, 0xb9, 0x36,
+ 0xe0, 0xb7, 0xee, 0x16, 0xeb, 0x25, 0x67, 0x04,
+ 0xc0, 0x2e, 0xd8, 0x34, 0x4a, 0x65, 0xa5, 0xf1,
+ 0x95, 0x75, 0xc7, 0x39, 0xa9, 0x68, 0xa9, 0x53,
+ 0x93, 0x5b, 0xca, 0x7b, 0x7f, 0xc0, 0x63, 0x14,
+ 0x03, 0x02, 0x00, 0x01, 0x01, 0x16, 0x03, 0x02,
+ 0x00, 0x40, 0x01, 0xb1, 0xae, 0x1b, 0x8a, 0x65,
+ 0xf8, 0x37, 0x50, 0x39, 0x76, 0xef, 0xaa, 0xda,
+ 0x84, 0xc9, 0x5f, 0x80, 0xdc, 0xfa, 0xe0, 0x46,
+ 0x5a, 0xc7, 0x77, 0x9d, 0x76, 0x03, 0xa6, 0xd5,
+ 0x0e, 0xbf, 0x25, 0x30, 0x5c, 0x99, 0x7d, 0xcd,
+ 0x2b, 0xaa, 0x2e, 0x8c, 0xdd, 0xda, 0xaa, 0xd7,
+ 0xf1, 0xf6, 0x33, 0x47, 0x51, 0x1e, 0x83, 0xa1,
+ 0x83, 0x04, 0xd2, 0xb2, 0xc8, 0xbc, 0x11, 0xc5,
+ 0x1a, 0x87,
+ },
+ {
+ 0x16, 0x03, 0x02, 0x00, 0x72, 0x04, 0x00, 0x00,
+ 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65,
+ 0xeb, 0x8b, 0xc7, 0xef, 0xba, 0xe8, 0x0f, 0x69,
+ 0xfe, 0xfb, 0xc3, 0x3d, 0x90, 0x5d, 0xd7, 0xb2,
+ 0x51, 0x64, 0xac, 0xc3, 0xae, 0x33, 0x03, 0x42,
+ 0x45, 0x2d, 0xa7, 0x57, 0xbd, 0xa3, 0x85, 0x64,
+ 0xa6, 0xfe, 0x5c, 0x33, 0x04, 0x93, 0xf2, 0x7c,
+ 0x06, 0x6d, 0xd7, 0xd7, 0xcf, 0x4a, 0xaf, 0xb2,
+ 0xdd, 0x06, 0xdc, 0x28, 0x14, 0x59, 0x23, 0x02,
+ 0xef, 0x97, 0x6a, 0xe8, 0xec, 0xca, 0x10, 0x44,
+ 0xcd, 0xb8, 0x50, 0x16, 0x46, 0x5a, 0x05, 0xda,
+ 0x04, 0xb3, 0x0e, 0xe9, 0xf0, 0x74, 0xc5, 0x23,
+ 0xc2, 0x0e, 0xa1, 0x54, 0x66, 0x7b, 0xe8, 0x14,
+ 0x03, 0x02, 0x00, 0x01, 0x01, 0x16, 0x03, 0x02,
+ 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x6b, 0x43, 0x1c, 0x58, 0xbc, 0x85,
+ 0xf7, 0xc1, 0x76, 0xbc, 0x72, 0x33, 0x41, 0x6b,
+ 0xb8, 0xf8, 0xfd, 0x53, 0x21, 0xc2, 0x41, 0x1b,
+ 0x72, 0x4f, 0xce, 0x97, 0xca, 0x14, 0x23, 0x4d,
+ 0xbc, 0x44, 0xd6, 0xd7, 0xfc, 0xbc, 0xfd, 0xfd,
+ 0x5d, 0x33, 0x42, 0x1b, 0x52, 0x40, 0x0a, 0x2b,
+ 0x6c, 0x98, 0x17, 0x03, 0x02, 0x00, 0x40, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d,
+ 0x31, 0xef, 0x03, 0x7d, 0xa5, 0x74, 0x92, 0x24,
+ 0x34, 0xae, 0x4e, 0xc9, 0xfc, 0x59, 0xcb, 0x64,
+ 0xf4, 0x45, 0xb1, 0xac, 0x02, 0xf2, 0x87, 0xe7,
+ 0x2f, 0xfd, 0x01, 0xca, 0x78, 0x02, 0x2e, 0x3a,
+ 0x38, 0xcd, 0xb1, 0xe0, 0xf2, 0x2e, 0xf6, 0x27,
+ 0xa0, 0xac, 0x1f, 0x91, 0x43, 0xc2, 0x3d, 0x15,
+ 0x03, 0x02, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x9f, 0x30, 0x24, 0x56,
+ 0x2c, 0xde, 0xa0, 0xe6, 0x44, 0x35, 0x30, 0x51,
+ 0xec, 0xd4, 0x69, 0x2d, 0x46, 0x64, 0x04, 0x21,
+ 0xfe, 0x7c, 0x4d, 0xc5, 0xd0, 0x8c, 0xf9, 0xd2,
+ 0x3f, 0x88, 0x69, 0xd5,
+ },
+}
+
+// $ go test -run TestRunServer -serve -clientauth 1 \
+// -ciphersuites=0xc011 -minversion=0x0303 -maxversion=0x0303
+var tls12ServerScript = [][]byte{
+ {
+ 0x16, 0x03, 0x01, 0x01, 0x1e, 0x01, 0x00, 0x01,
+ 0x1a, 0x03, 0x03, 0x51, 0xe5, 0x76, 0x84, 0x0e,
+ 0xb9, 0x17, 0xca, 0x08, 0x47, 0xd9, 0xbd, 0xd0,
+ 0x94, 0xd1, 0x97, 0xca, 0x5b, 0xe7, 0x20, 0xac,
+ 0x8e, 0xbb, 0xc7, 0x29, 0xe9, 0x26, 0xcf, 0x7d,
+ 0xb3, 0xdc, 0x99, 0x00, 0x00, 0x82, 0xc0, 0x30,
+ 0xc0, 0x2c, 0xc0, 0x28, 0xc0, 0x24, 0xc0, 0x14,
+ 0xc0, 0x0a, 0x00, 0xa3, 0x00, 0x9f, 0x00, 0x6b,
+ 0x00, 0x6a, 0x00, 0x39, 0x00, 0x38, 0xc0, 0x32,
+ 0xc0, 0x2e, 0xc0, 0x2a, 0xc0, 0x26, 0xc0, 0x0f,
+ 0xc0, 0x05, 0x00, 0x9d, 0x00, 0x3d, 0x00, 0x35,
+ 0xc0, 0x12, 0xc0, 0x08, 0x00, 0x16, 0x00, 0x13,
+ 0xc0, 0x0d, 0xc0, 0x03, 0x00, 0x0a, 0xc0, 0x2f,
+ 0xc0, 0x2b, 0xc0, 0x27, 0xc0, 0x23, 0xc0, 0x13,
+ 0xc0, 0x09, 0x00, 0xa2, 0x00, 0x9e, 0x00, 0x67,
+ 0x00, 0x40, 0x00, 0x33, 0x00, 0x32, 0xc0, 0x31,
+ 0xc0, 0x2d, 0xc0, 0x29, 0xc0, 0x25, 0xc0, 0x0e,
+ 0xc0, 0x04, 0x00, 0x9c, 0x00, 0x3c, 0x00, 0x2f,
+ 0x00, 0x07, 0xc0, 0x11, 0xc0, 0x07, 0xc0, 0x0c,
+ 0xc0, 0x02, 0x00, 0x05, 0x00, 0x04, 0x00, 0x15,
+ 0x00, 0x12, 0x00, 0x09, 0x00, 0x14, 0x00, 0x11,
+ 0x00, 0x08, 0x00, 0x06, 0x00, 0x03, 0x00, 0xff,
+ 0x01, 0x00, 0x00, 0x6f, 0x00, 0x0b, 0x00, 0x04,
+ 0x03, 0x00, 0x01, 0x02, 0x00, 0x0a, 0x00, 0x34,
+ 0x00, 0x32, 0x00, 0x0e, 0x00, 0x0d, 0x00, 0x19,
+ 0x00, 0x0b, 0x00, 0x0c, 0x00, 0x18, 0x00, 0x09,
+ 0x00, 0x0a, 0x00, 0x16, 0x00, 0x17, 0x00, 0x08,
+ 0x00, 0x06, 0x00, 0x07, 0x00, 0x14, 0x00, 0x15,
+ 0x00, 0x04, 0x00, 0x05, 0x00, 0x12, 0x00, 0x13,
+ 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x0f,
+ 0x00, 0x10, 0x00, 0x11, 0x00, 0x23, 0x00, 0x00,
+ 0x00, 0x0d, 0x00, 0x22, 0x00, 0x20, 0x06, 0x01,
+ 0x06, 0x02, 0x06, 0x03, 0x05, 0x01, 0x05, 0x02,
+ 0x05, 0x03, 0x04, 0x01, 0x04, 0x02, 0x04, 0x03,
+ 0x03, 0x01, 0x03, 0x02, 0x03, 0x03, 0x02, 0x01,
+ 0x02, 0x02, 0x02, 0x03, 0x01, 0x01, 0x00, 0x0f,
+ 0x00, 0x01, 0x01,
+ },
+ {
+ 0x16, 0x03, 0x03, 0x00, 0x30, 0x02, 0x00, 0x00,
+ 0x2c, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xc0, 0x11, 0x00, 0x00,
+ 0x04, 0x00, 0x23, 0x00, 0x00, 0x16, 0x03, 0x03,
+ 0x02, 0xbe, 0x0b, 0x00, 0x02, 0xba, 0x00, 0x02,
+ 0xb7, 0x00, 0x02, 0xb4, 0x30, 0x82, 0x02, 0xb0,
+ 0x30, 0x82, 0x02, 0x19, 0xa0, 0x03, 0x02, 0x01,
+ 0x02, 0x02, 0x09, 0x00, 0x85, 0xb0, 0xbb, 0xa4,
+ 0x8a, 0x7f, 0xb8, 0xca, 0x30, 0x0d, 0x06, 0x09,
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+ 0x05, 0x05, 0x00, 0x30, 0x45, 0x31, 0x0b, 0x30,
+ 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+ 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
+ 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d,
+ 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31,
+ 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a,
+ 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e,
+ 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69,
+ 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c,
+ 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x30,
+ 0x30, 0x34, 0x32, 0x34, 0x30, 0x39, 0x30, 0x39,
+ 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x31, 0x31, 0x30,
+ 0x34, 0x32, 0x34, 0x30, 0x39, 0x30, 0x39, 0x33,
+ 0x38, 0x5a, 0x30, 0x45, 0x31, 0x0b, 0x30, 0x09,
+ 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x41,
+ 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
+ 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, 0x65,
+ 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x21,
+ 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13,
+ 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
+ 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, 0x74,
+ 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74,
+ 0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09,
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+ 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30,
+ 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xbb, 0x79,
+ 0xd6, 0xf5, 0x17, 0xb5, 0xe5, 0xbf, 0x46, 0x10,
+ 0xd0, 0xdc, 0x69, 0xbe, 0xe6, 0x2b, 0x07, 0x43,
+ 0x5a, 0xd0, 0x03, 0x2d, 0x8a, 0x7a, 0x43, 0x85,
+ 0xb7, 0x14, 0x52, 0xe7, 0xa5, 0x65, 0x4c, 0x2c,
+ 0x78, 0xb8, 0x23, 0x8c, 0xb5, 0xb4, 0x82, 0xe5,
+ 0xde, 0x1f, 0x95, 0x3b, 0x7e, 0x62, 0xa5, 0x2c,
+ 0xa5, 0x33, 0xd6, 0xfe, 0x12, 0x5c, 0x7a, 0x56,
+ 0xfc, 0xf5, 0x06, 0xbf, 0xfa, 0x58, 0x7b, 0x26,
+ 0x3f, 0xb5, 0xcd, 0x04, 0xd3, 0xd0, 0xc9, 0x21,
+ 0x96, 0x4a, 0xc7, 0xf4, 0x54, 0x9f, 0x5a, 0xbf,
+ 0xef, 0x42, 0x71, 0x00, 0xfe, 0x18, 0x99, 0x07,
+ 0x7f, 0x7e, 0x88, 0x7d, 0x7d, 0xf1, 0x04, 0x39,
+ 0xc4, 0xa2, 0x2e, 0xdb, 0x51, 0xc9, 0x7c, 0xe3,
+ 0xc0, 0x4c, 0x3b, 0x32, 0x66, 0x01, 0xcf, 0xaf,
+ 0xb1, 0x1d, 0xb8, 0x71, 0x9a, 0x1d, 0xdb, 0xdb,
+ 0x89, 0x6b, 0xae, 0xda, 0x2d, 0x79, 0x02, 0x03,
+ 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7, 0x30, 0x81,
+ 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e,
+ 0x04, 0x16, 0x04, 0x14, 0xb1, 0xad, 0xe2, 0x85,
+ 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69, 0xce, 0x23,
+ 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18, 0x88, 0x39,
+ 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04,
+ 0x6e, 0x30, 0x6c, 0x80, 0x14, 0xb1, 0xad, 0xe2,
+ 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69, 0xce,
+ 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18, 0x88,
+ 0x39, 0xa1, 0x49, 0xa4, 0x47, 0x30, 0x45, 0x31,
+ 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+ 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11,
+ 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53,
+ 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74,
+ 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55,
+ 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65,
+ 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64,
+ 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79,
+ 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09, 0x00, 0x85,
+ 0xb0, 0xbb, 0xa4, 0x8a, 0x7f, 0xb8, 0xca, 0x30,
+ 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05,
+ 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06,
+ 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
+ 0x01, 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00,
+ 0x08, 0x6c, 0x45, 0x24, 0xc7, 0x6b, 0xb1, 0x59,
+ 0xab, 0x0c, 0x52, 0xcc, 0xf2, 0xb0, 0x14, 0xd7,
+ 0x87, 0x9d, 0x7a, 0x64, 0x75, 0xb5, 0x5a, 0x95,
+ 0x66, 0xe4, 0xc5, 0x2b, 0x8e, 0xae, 0x12, 0x66,
+ 0x1f, 0xeb, 0x4f, 0x38, 0xb3, 0x6e, 0x60, 0xd3,
+ 0x92, 0xfd, 0xf7, 0x41, 0x08, 0xb5, 0x25, 0x13,
+ 0xb1, 0x18, 0x7a, 0x24, 0xfb, 0x30, 0x1d, 0xba,
+ 0xed, 0x98, 0xb9, 0x17, 0xec, 0xe7, 0xd7, 0x31,
+ 0x59, 0xdb, 0x95, 0xd3, 0x1d, 0x78, 0xea, 0x50,
+ 0x56, 0x5c, 0xd5, 0x82, 0x5a, 0x2d, 0x5a, 0x5f,
+ 0x33, 0xc4, 0xb6, 0xd8, 0xc9, 0x75, 0x90, 0x96,
+ 0x8c, 0x0f, 0x52, 0x98, 0xb5, 0xcd, 0x98, 0x1f,
+ 0x89, 0x20, 0x5f, 0xf2, 0xa0, 0x1c, 0xa3, 0x1b,
+ 0x96, 0x94, 0xdd, 0xa9, 0xfd, 0x57, 0xe9, 0x70,
+ 0xe8, 0x26, 0x6d, 0x71, 0x99, 0x9b, 0x26, 0x6e,
+ 0x38, 0x50, 0x29, 0x6c, 0x90, 0xa7, 0xbd, 0xd9,
+ 0x16, 0x03, 0x03, 0x01, 0x11, 0x0c, 0x00, 0x01,
+ 0x0d, 0x03, 0x00, 0x19, 0x85, 0x04, 0x01, 0x39,
+ 0xdc, 0xee, 0x44, 0x17, 0x5e, 0xdb, 0xd7, 0x27,
+ 0xaf, 0xb6, 0x56, 0xd9, 0xb4, 0x43, 0x5a, 0x99,
+ 0xcf, 0xaa, 0x31, 0x37, 0x0c, 0x6f, 0x3a, 0xa0,
+ 0xf8, 0x53, 0xc4, 0x74, 0xd1, 0x91, 0x0a, 0x46,
+ 0xf5, 0x38, 0x3b, 0x5c, 0x09, 0xd8, 0x97, 0xdc,
+ 0x4b, 0xaa, 0x70, 0x26, 0x48, 0xf2, 0xd6, 0x0b,
+ 0x31, 0xc9, 0xf8, 0xd4, 0x98, 0x43, 0xe1, 0x6c,
+ 0xd5, 0xc7, 0xb2, 0x8e, 0x0b, 0x01, 0xe6, 0xb6,
+ 0x00, 0x28, 0x80, 0x7b, 0xfc, 0x96, 0x8f, 0x0d,
+ 0xa2, 0x4f, 0xb0, 0x79, 0xaf, 0xdc, 0x61, 0x28,
+ 0x63, 0x33, 0x78, 0xf6, 0x31, 0x39, 0xfd, 0x8a,
+ 0xf4, 0x15, 0x18, 0x11, 0xfe, 0xdb, 0xd5, 0x07,
+ 0xda, 0x2c, 0xed, 0x49, 0xa0, 0x23, 0xbf, 0xd0,
+ 0x3a, 0x38, 0x1d, 0x54, 0xae, 0x1c, 0x7b, 0xea,
+ 0x29, 0xee, 0xd0, 0x38, 0xc1, 0x76, 0xa7, 0x7f,
+ 0x2a, 0xf4, 0xce, 0x1e, 0xac, 0xcc, 0x94, 0x79,
+ 0x90, 0x33, 0x04, 0x01, 0x00, 0x80, 0x4a, 0xf9,
+ 0xf5, 0x0a, 0x61, 0x37, 0x7e, 0x4e, 0x92, 0xb5,
+ 0x1c, 0x91, 0x21, 0xb2, 0xb5, 0x17, 0x00, 0xbf,
+ 0x01, 0x5f, 0x30, 0xec, 0x62, 0x08, 0xd6, 0x9d,
+ 0x1a, 0x08, 0x05, 0x72, 0x8b, 0xf4, 0x49, 0x85,
+ 0xa7, 0xbf, 0x3f, 0x75, 0x58, 0x3e, 0x26, 0x82,
+ 0xc3, 0x28, 0x07, 0xf9, 0x41, 0x7d, 0x03, 0x14,
+ 0x3b, 0xc3, 0x05, 0x64, 0xff, 0x52, 0xf4, 0x75,
+ 0x6a, 0x87, 0xcd, 0xdf, 0x93, 0x31, 0x0a, 0x71,
+ 0x60, 0x17, 0xc6, 0x33, 0xf0, 0x79, 0xb6, 0x7b,
+ 0xd0, 0x9c, 0xa0, 0x5f, 0x74, 0x14, 0x2c, 0x5a,
+ 0xb4, 0x3f, 0x39, 0xf5, 0xe4, 0x9f, 0xbe, 0x6d,
+ 0x21, 0xd2, 0xa9, 0x42, 0xf7, 0xdc, 0xa6, 0x65,
+ 0xb7, 0x6a, 0x7e, 0x2e, 0x14, 0xd3, 0xf6, 0xf3,
+ 0x4b, 0x4c, 0x5b, 0x1a, 0x70, 0x7a, 0xbc, 0xb0,
+ 0x12, 0xf3, 0x6e, 0x0c, 0xcf, 0x43, 0x22, 0xae,
+ 0x5b, 0xba, 0x00, 0xf8, 0xfd, 0xaf, 0x16, 0x03,
+ 0x03, 0x00, 0x0f, 0x0d, 0x00, 0x00, 0x0b, 0x02,
+ 0x01, 0x40, 0x00, 0x04, 0x04, 0x01, 0x04, 0x03,
+ 0x00, 0x00, 0x16, 0x03, 0x03, 0x00, 0x04, 0x0e,
+ 0x00, 0x00, 0x00,
+ },
+ {
+ 0x16, 0x03, 0x03, 0x01, 0xfb, 0x0b, 0x00, 0x01,
+ 0xf7, 0x00, 0x01, 0xf4, 0x00, 0x01, 0xf1, 0x30,
+ 0x82, 0x01, 0xed, 0x30, 0x82, 0x01, 0x58, 0xa0,
+ 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x00, 0x30,
+ 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x05, 0x30, 0x26, 0x31, 0x10,
+ 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13,
+ 0x07, 0x41, 0x63, 0x6d, 0x65, 0x20, 0x43, 0x6f,
+ 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04,
+ 0x03, 0x13, 0x09, 0x31, 0x32, 0x37, 0x2e, 0x30,
+ 0x2e, 0x30, 0x2e, 0x31, 0x30, 0x1e, 0x17, 0x0d,
+ 0x31, 0x31, 0x31, 0x32, 0x30, 0x38, 0x30, 0x37,
+ 0x35, 0x35, 0x31, 0x32, 0x5a, 0x17, 0x0d, 0x31,
+ 0x32, 0x31, 0x32, 0x30, 0x37, 0x30, 0x38, 0x30,
+ 0x30, 0x31, 0x32, 0x5a, 0x30, 0x26, 0x31, 0x10,
+ 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13,
+ 0x07, 0x41, 0x63, 0x6d, 0x65, 0x20, 0x43, 0x6f,
+ 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04,
+ 0x03, 0x13, 0x09, 0x31, 0x32, 0x37, 0x2e, 0x30,
+ 0x2e, 0x30, 0x2e, 0x31, 0x30, 0x81, 0x9c, 0x30,
+ 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x01, 0x03, 0x81, 0x8c, 0x00,
+ 0x30, 0x81, 0x88, 0x02, 0x81, 0x80, 0x4e, 0xd0,
+ 0x7b, 0x31, 0xe3, 0x82, 0x64, 0xd9, 0x59, 0xc0,
+ 0xc2, 0x87, 0xa4, 0x5e, 0x1e, 0x8b, 0x73, 0x33,
+ 0xc7, 0x63, 0x53, 0xdf, 0x66, 0x92, 0x06, 0x84,
+ 0xf6, 0x64, 0xd5, 0x8f, 0xe4, 0x36, 0xa7, 0x1d,
+ 0x2b, 0xe8, 0xb3, 0x20, 0x36, 0x45, 0x23, 0xb5,
+ 0xe3, 0x95, 0xae, 0xed, 0xe0, 0xf5, 0x20, 0x9c,
+ 0x8d, 0x95, 0xdf, 0x7f, 0x5a, 0x12, 0xef, 0x87,
+ 0xe4, 0x5b, 0x68, 0xe4, 0xe9, 0x0e, 0x74, 0xec,
+ 0x04, 0x8a, 0x7f, 0xde, 0x93, 0x27, 0xc4, 0x01,
+ 0x19, 0x7a, 0xbd, 0xf2, 0xdc, 0x3d, 0x14, 0xab,
+ 0xd0, 0x54, 0xca, 0x21, 0x0c, 0xd0, 0x4d, 0x6e,
+ 0x87, 0x2e, 0x5c, 0xc5, 0xd2, 0xbb, 0x4d, 0x4b,
+ 0x4f, 0xce, 0xb6, 0x2c, 0xf7, 0x7e, 0x88, 0xec,
+ 0x7c, 0xd7, 0x02, 0x91, 0x74, 0xa6, 0x1e, 0x0c,
+ 0x1a, 0xda, 0xe3, 0x4a, 0x5a, 0x2e, 0xde, 0x13,
+ 0x9c, 0x4c, 0x40, 0x88, 0x59, 0x93, 0x02, 0x03,
+ 0x01, 0x00, 0x01, 0xa3, 0x32, 0x30, 0x30, 0x30,
+ 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01,
+ 0xff, 0x04, 0x04, 0x03, 0x02, 0x00, 0xa0, 0x30,
+ 0x0d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x06,
+ 0x04, 0x04, 0x01, 0x02, 0x03, 0x04, 0x30, 0x0f,
+ 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x08, 0x30,
+ 0x06, 0x80, 0x04, 0x01, 0x02, 0x03, 0x04, 0x30,
+ 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x05, 0x03, 0x81, 0x81, 0x00,
+ 0x36, 0x1f, 0xb3, 0x7a, 0x0c, 0x75, 0xc9, 0x6e,
+ 0x37, 0x46, 0x61, 0x2b, 0xd5, 0xbd, 0xc0, 0xa7,
+ 0x4b, 0xcc, 0x46, 0x9a, 0x81, 0x58, 0x7c, 0x85,
+ 0x79, 0x29, 0xc8, 0xc8, 0xc6, 0x67, 0xdd, 0x32,
+ 0x56, 0x45, 0x2b, 0x75, 0xb6, 0xe9, 0x24, 0xa9,
+ 0x50, 0x9a, 0xbe, 0x1f, 0x5a, 0xfa, 0x1a, 0x15,
+ 0xd9, 0xcc, 0x55, 0x95, 0x72, 0x16, 0x83, 0xb9,
+ 0xc2, 0xb6, 0x8f, 0xfd, 0x88, 0x8c, 0x38, 0x84,
+ 0x1d, 0xab, 0x5d, 0x92, 0x31, 0x13, 0x4f, 0xfd,
+ 0x83, 0x3b, 0xc6, 0x9d, 0xf1, 0x11, 0x62, 0xb6,
+ 0x8b, 0xec, 0xab, 0x67, 0xbe, 0xc8, 0x64, 0xb0,
+ 0x11, 0x50, 0x46, 0x58, 0x17, 0x6b, 0x99, 0x1c,
+ 0xd3, 0x1d, 0xfc, 0x06, 0xf1, 0x0e, 0xe5, 0x96,
+ 0xa8, 0x0c, 0xf9, 0x78, 0x20, 0xb7, 0x44, 0x18,
+ 0x51, 0x8d, 0x10, 0x7e, 0x4f, 0x94, 0x67, 0xdf,
+ 0xa3, 0x4e, 0x70, 0x73, 0x8e, 0x90, 0x91, 0x85,
+ 0x16, 0x03, 0x03, 0x00, 0x8a, 0x10, 0x00, 0x00,
+ 0x86, 0x85, 0x04, 0x01, 0x5d, 0x3a, 0x92, 0x59,
+ 0x7f, 0x9a, 0x22, 0x36, 0x0e, 0x1b, 0x1d, 0x2a,
+ 0x05, 0xb7, 0xa4, 0xb6, 0x5d, 0xfc, 0x51, 0x6e,
+ 0x15, 0xe5, 0x89, 0x7c, 0xe2, 0xfa, 0x87, 0x38,
+ 0x05, 0x79, 0x15, 0x92, 0xb4, 0x8f, 0x88, 0x8f,
+ 0x9d, 0x5d, 0xa0, 0xaf, 0xf8, 0xce, 0xf9, 0x6f,
+ 0x83, 0xf4, 0x08, 0x69, 0xe4, 0x91, 0xc5, 0xed,
+ 0xb9, 0xc5, 0xa8, 0x1f, 0x4b, 0xec, 0xef, 0x91,
+ 0xc1, 0xa3, 0x34, 0x24, 0x18, 0x00, 0x2d, 0xcd,
+ 0xe6, 0x44, 0xef, 0x5a, 0x3e, 0x52, 0x63, 0x5b,
+ 0x36, 0x1f, 0x7e, 0xce, 0x9e, 0xaa, 0xda, 0x8d,
+ 0xb5, 0xc9, 0xea, 0xd8, 0x1b, 0xd1, 0x1c, 0x7c,
+ 0x07, 0xfc, 0x3c, 0x2d, 0x70, 0x1f, 0xf9, 0x4d,
+ 0xcb, 0xaa, 0xad, 0x07, 0xd5, 0x6d, 0xbd, 0xa6,
+ 0x61, 0xf3, 0x2f, 0xa3, 0x9c, 0x45, 0x02, 0x4a,
+ 0xac, 0x6c, 0xb6, 0x37, 0x95, 0xb1, 0x4a, 0xb5,
+ 0x0a, 0x4e, 0x60, 0x67, 0xd7, 0xe0, 0x04, 0x16,
+ 0x03, 0x03, 0x00, 0x88, 0x0f, 0x00, 0x00, 0x84,
+ 0x04, 0x01, 0x00, 0x80, 0x08, 0x83, 0x53, 0xf0,
+ 0xf8, 0x14, 0xf5, 0xc2, 0xd1, 0x8b, 0xf0, 0xa5,
+ 0xc1, 0xd8, 0x1a, 0x36, 0x4b, 0x75, 0x77, 0x02,
+ 0x19, 0xd8, 0x11, 0x3f, 0x5a, 0x36, 0xfc, 0xe9,
+ 0x2b, 0x4b, 0xf9, 0xfe, 0xda, 0x8a, 0x0f, 0x6e,
+ 0x3d, 0xd3, 0x52, 0x87, 0xf7, 0x9c, 0x78, 0x39,
+ 0xa8, 0xf1, 0xd7, 0xf7, 0x4e, 0x35, 0x33, 0xf9,
+ 0xc5, 0x76, 0xa8, 0x12, 0xc4, 0x91, 0x33, 0x1d,
+ 0x93, 0x8c, 0xbf, 0xb1, 0x83, 0x00, 0x90, 0xc5,
+ 0x52, 0x3e, 0xe0, 0x0a, 0xe8, 0x92, 0x75, 0xdf,
+ 0x54, 0x5f, 0x9f, 0x95, 0x76, 0x62, 0xb5, 0x85,
+ 0x69, 0xa4, 0x86, 0x85, 0x6c, 0xf3, 0x6b, 0x2a,
+ 0x72, 0x7b, 0x4d, 0x42, 0x33, 0x67, 0x4a, 0xce,
+ 0xb5, 0xdb, 0x9b, 0xae, 0xc0, 0xb0, 0x10, 0xeb,
+ 0x3b, 0xf4, 0xc2, 0x9a, 0x64, 0x47, 0x4c, 0x1e,
+ 0xa5, 0x91, 0x7f, 0x6d, 0xd1, 0x03, 0xf5, 0x4a,
+ 0x90, 0x69, 0x18, 0xb1, 0x14, 0x03, 0x03, 0x00,
+ 0x01, 0x01, 0x16, 0x03, 0x03, 0x00, 0x24, 0x59,
+ 0xfc, 0x7e, 0xae, 0xb3, 0xbf, 0xab, 0x4d, 0xdb,
+ 0x4e, 0xab, 0xa9, 0x6d, 0x6b, 0x4c, 0x60, 0xb6,
+ 0x16, 0xe0, 0xab, 0x7f, 0x52, 0x2d, 0xa1, 0xfc,
+ 0xe1, 0x80, 0xd2, 0x8a, 0xa1, 0xe5, 0x8f, 0xa1,
+ 0x70, 0x93, 0x23,
+ },
+ {
+ 0x16, 0x03, 0x03, 0x02, 0x67, 0x04, 0x00, 0x02,
+ 0x63, 0x00, 0x00, 0x00, 0x00, 0x02, 0x5d, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65,
+ 0xea, 0x8b, 0xc5, 0xef, 0xba, 0x64, 0xb7, 0x23,
+ 0x08, 0x86, 0x4f, 0x37, 0xe0, 0x8f, 0xbd, 0x75,
+ 0x71, 0x2b, 0xcb, 0x20, 0x75, 0x11, 0x3b, 0xa2,
+ 0x9e, 0x39, 0x3c, 0x03, 0xef, 0x6e, 0x41, 0xd7,
+ 0xcf, 0x1a, 0x2c, 0xf2, 0xfe, 0xc2, 0xd3, 0x65,
+ 0x59, 0x00, 0x9d, 0x03, 0xb4, 0xf2, 0x20, 0xe4,
+ 0x33, 0x80, 0xcd, 0xf6, 0xe4, 0x59, 0x22, 0xf7,
+ 0xfd, 0x88, 0x0e, 0xa4, 0x09, 0xc0, 0x0d, 0x10,
+ 0x80, 0x10, 0x79, 0xee, 0x70, 0x96, 0xdb, 0x22,
+ 0x8b, 0xb7, 0xac, 0xe0, 0x98, 0xad, 0xe9, 0xe3,
+ 0xcb, 0xea, 0x9f, 0xe6, 0x83, 0x28, 0x7c, 0x7e,
+ 0x4e, 0x9a, 0x8d, 0xd9, 0xf3, 0x86, 0xf4, 0x89,
+ 0x8b, 0x79, 0x8f, 0xbb, 0xe9, 0x74, 0x02, 0x02,
+ 0x14, 0x04, 0xea, 0xba, 0x16, 0x10, 0xa1, 0x85,
+ 0xbe, 0x4e, 0x4e, 0x92, 0xc5, 0x83, 0xf6, 0x1e,
+ 0x1f, 0xd4, 0x25, 0xc2, 0xc2, 0xb9, 0xce, 0x33,
+ 0x63, 0x66, 0x79, 0x1f, 0x54, 0x35, 0xc1, 0xe8,
+ 0x89, 0x34, 0x78, 0x94, 0x36, 0x14, 0xef, 0x01,
+ 0x1f, 0xf1, 0xbd, 0x77, 0x2c, 0x4d, 0xac, 0x5c,
+ 0x5c, 0x4a, 0xc6, 0xed, 0xd8, 0x0e, 0x72, 0x84,
+ 0x83, 0xdc, 0x56, 0x84, 0xc8, 0xf3, 0x89, 0x56,
+ 0xfd, 0x89, 0xc1, 0xc9, 0x9a, 0x29, 0x91, 0x7e,
+ 0x19, 0xe9, 0x8b, 0x5b, 0x11, 0x15, 0x4e, 0x6c,
+ 0xf4, 0x89, 0xe7, 0x6d, 0x68, 0x1e, 0xf9, 0x6c,
+ 0x23, 0x72, 0x05, 0x68, 0x82, 0x60, 0x84, 0x1f,
+ 0x83, 0x20, 0x09, 0x86, 0x10, 0x81, 0xec, 0xec,
+ 0xdc, 0x25, 0x53, 0x20, 0xfa, 0xa9, 0x41, 0x64,
+ 0xd6, 0x20, 0xf3, 0xf4, 0x52, 0xf2, 0x80, 0x62,
+ 0x83, 0xc9, 0x23, 0x66, 0x44, 0x95, 0x5a, 0x99,
+ 0x8a, 0xe1, 0x26, 0x63, 0xc1, 0x8b, 0x31, 0xf9,
+ 0x21, 0x06, 0x77, 0x04, 0x27, 0xf2, 0x0c, 0x63,
+ 0x83, 0x45, 0xa0, 0xa9, 0x7b, 0xcf, 0xdf, 0xd7,
+ 0x56, 0x75, 0xbc, 0xdd, 0x95, 0x36, 0xb1, 0x75,
+ 0x39, 0x05, 0x00, 0x3c, 0x8a, 0x79, 0xd6, 0xe9,
+ 0xf0, 0x4b, 0xdc, 0x51, 0x6b, 0x01, 0x94, 0x16,
+ 0x87, 0x12, 0x92, 0x6c, 0x07, 0xc1, 0xf5, 0x58,
+ 0xb7, 0x2a, 0x81, 0xf5, 0xa0, 0x37, 0x8b, 0xa6,
+ 0x22, 0xfe, 0x28, 0x0a, 0x7e, 0x68, 0xe2, 0xda,
+ 0x6c, 0x53, 0xee, 0x0e, 0x8d, 0x2d, 0x8b, 0x0b,
+ 0xda, 0xf8, 0x99, 0x3e, 0x0e, 0xed, 0x9f, 0xc1,
+ 0x2b, 0xf6, 0xfe, 0xe9, 0x52, 0x38, 0x7b, 0x83,
+ 0x9a, 0x50, 0xa6, 0xd7, 0x49, 0x83, 0x43, 0x7e,
+ 0x82, 0xec, 0xc7, 0x09, 0x3d, 0x3d, 0xb1, 0xee,
+ 0xe8, 0xc5, 0x6a, 0xc3, 0x3d, 0x4b, 0x4c, 0x6a,
+ 0xbb, 0x0b, 0x2c, 0x24, 0x2e, 0xdb, 0x7d, 0x57,
+ 0x87, 0xb4, 0x80, 0xa5, 0xae, 0xff, 0x54, 0xa8,
+ 0xa5, 0x27, 0x69, 0x95, 0xc8, 0xe7, 0x79, 0xc7,
+ 0x89, 0x2a, 0x73, 0x49, 0xcb, 0xf5, 0xc5, 0xbc,
+ 0x4a, 0xe0, 0x73, 0xa9, 0xbc, 0x88, 0x64, 0x96,
+ 0x98, 0xa5, 0x1e, 0xe3, 0x43, 0xc1, 0x7d, 0x78,
+ 0xc7, 0x94, 0x72, 0xd4, 0x2c, 0x6e, 0x85, 0x39,
+ 0x9a, 0xaf, 0xdb, 0xa1, 0xe9, 0xe2, 0xcb, 0x37,
+ 0x04, 0xc6, 0x8c, 0x81, 0xd3, 0x2a, 0xb7, 0xbe,
+ 0x6c, 0x07, 0x1f, 0x5e, 0xd9, 0x00, 0xd2, 0xf7,
+ 0xe1, 0xa7, 0xbc, 0x0c, 0xb6, 0x6d, 0xfb, 0x3f,
+ 0x3d, 0x24, 0xaa, 0xfb, 0x7e, 0xe1, 0xb5, 0x1b,
+ 0xff, 0x38, 0xaa, 0x69, 0x59, 0x38, 0x52, 0x9a,
+ 0x0e, 0x6d, 0xbc, 0xde, 0x4f, 0x13, 0x09, 0x17,
+ 0xc4, 0xa9, 0x05, 0x84, 0xbc, 0x50, 0xef, 0x40,
+ 0xb0, 0x4c, 0x24, 0x32, 0xed, 0x94, 0x2c, 0xdd,
+ 0xda, 0x20, 0x24, 0x67, 0xe2, 0xea, 0x71, 0x3d,
+ 0x4a, 0x04, 0x0d, 0x98, 0x29, 0x20, 0x4c, 0xeb,
+ 0x70, 0xce, 0x45, 0x9e, 0x5a, 0xaf, 0xb6, 0xa3,
+ 0x92, 0xc8, 0x28, 0xf2, 0xe3, 0xe8, 0x8a, 0x5d,
+ 0x0a, 0x33, 0x79, 0x9b, 0x6a, 0xf3, 0x30, 0x01,
+ 0x1d, 0x47, 0xbd, 0x01, 0xcc, 0x4d, 0x71, 0xc0,
+ 0x56, 0xfa, 0xfd, 0x37, 0xed, 0x0f, 0x27, 0xc0,
+ 0xbb, 0xa0, 0xee, 0xc3, 0x79, 0x8b, 0xe7, 0x41,
+ 0x8f, 0xfa, 0x3a, 0xcb, 0x45, 0x3b, 0x85, 0x9f,
+ 0x06, 0x90, 0xb2, 0x51, 0xc0, 0x48, 0x10, 0xac,
+ 0x2a, 0xec, 0xec, 0x48, 0x7a, 0x19, 0x47, 0xc4,
+ 0x2a, 0xeb, 0xb3, 0xa2, 0x07, 0x22, 0x32, 0x78,
+ 0xf4, 0x73, 0x5e, 0x92, 0x42, 0x15, 0xa1, 0x90,
+ 0x91, 0xd0, 0xeb, 0x12, 0x14, 0x03, 0x03, 0x00,
+ 0x01, 0x01, 0x16, 0x03, 0x03, 0x00, 0x24, 0x45,
+ 0x4b, 0x80, 0x42, 0x46, 0xde, 0xbb, 0xe7, 0x76,
+ 0xd1, 0x33, 0x92, 0xfc, 0x46, 0x17, 0x6d, 0x21,
+ 0xf6, 0x0e, 0x16, 0xca, 0x9b, 0x9b, 0x04, 0x65,
+ 0x16, 0x40, 0x44, 0x64, 0xbc, 0x58, 0xfa, 0x2a,
+ 0x49, 0xe9, 0xed, 0x17, 0x03, 0x03, 0x00, 0x21,
+ 0x89, 0x71, 0xcd, 0x56, 0x54, 0xbf, 0x73, 0xde,
+ 0xfb, 0x4b, 0x4e, 0xf1, 0x7f, 0xc6, 0x75, 0xa6,
+ 0xbd, 0x6b, 0x6c, 0xd9, 0xdc, 0x0c, 0x71, 0xb4,
+ 0xb9, 0xbb, 0x6e, 0xfa, 0x9e, 0xc7, 0xc7, 0x4c,
+ 0x24, 0x15, 0x03, 0x03, 0x00, 0x16, 0x62, 0xea,
+ 0x65, 0x69, 0x68, 0x4a, 0xce, 0xa7, 0x9e, 0xce,
+ 0xc0, 0xf1, 0x5c, 0x96, 0xd9, 0x1f, 0x49, 0xac,
+ 0x2d, 0x05, 0x89, 0x94,
+ },
+}
+
// cert.pem and key.pem were generated with generate_cert.go
// Thus, they have no ExtKeyUsage fields and trigger an error
// when verification is turned on.
@@ -1999,3 +3167,630 @@ qTdQRYlHRftgnWK1AkANibn9PRYJ7mJyJ9Dyj2QeNcSkSTzrt0tPvUMf4+meJymN
1Ntu5+S1DLLzfxlaljWG6ylW6DNxujCyuXIV2rvA
-----END RSA PRIVATE KEY-----
*/
+
+var clientECDSACertificate = loadPEMCert(`
+-----BEGIN CERTIFICATE-----
+MIIB/DCCAV4CCQCaMIRsJjXZFzAJBgcqhkjOPQQBMEUxCzAJBgNVBAYTAkFVMRMw
+EQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0
+eSBMdGQwHhcNMTIxMTE0MTMyNTUzWhcNMjIxMTEyMTMyNTUzWjBBMQswCQYDVQQG
+EwJBVTEMMAoGA1UECBMDTlNXMRAwDgYDVQQHEwdQeXJtb250MRIwEAYDVQQDEwlK
+b2VsIFNpbmcwgZswEAYHKoZIzj0CAQYFK4EEACMDgYYABACVjJF1FMBexFe01MNv
+ja5oHt1vzobhfm6ySD6B5U7ixohLZNz1MLvT/2XMW/TdtWo+PtAd3kfDdq0Z9kUs
+jLzYHQFMH3CQRnZIi4+DzEpcj0B22uCJ7B0rxE4wdihBsmKo+1vx+U56jb0JuK7q
+ixgnTy5w/hOWusPTQBbNZU6sER7m8TAJBgcqhkjOPQQBA4GMADCBiAJCAOAUxGBg
+C3JosDJdYUoCdFzCgbkWqD8pyDbHgf9stlvZcPE4O1BIKJTLCRpS8V3ujfK58PDa
+2RU6+b0DeoeiIzXsAkIBo9SKeDUcSpoj0gq+KxAxnZxfvuiRs9oa9V2jI/Umi0Vw
+jWVim34BmT0Y9hCaOGGbLlfk+syxis7iI6CH8OFnUes=
+-----END CERTIFICATE-----
+`)
+
+/* corresponding key for cert is:
+-----BEGIN EC PARAMETERS-----
+BgUrgQQAIw==
+-----END EC PARAMETERS-----
+-----BEGIN EC PRIVATE KEY-----
+MIHcAgEBBEIBkJN9X4IqZIguiEVKMqeBUP5xtRsEv4HJEtOpOGLELwO53SD78Ew8
+k+wLWoqizS3NpQyMtrU8JFdWfj+C57UNkOugBwYFK4EEACOhgYkDgYYABACVjJF1
+FMBexFe01MNvja5oHt1vzobhfm6ySD6B5U7ixohLZNz1MLvT/2XMW/TdtWo+PtAd
+3kfDdq0Z9kUsjLzYHQFMH3CQRnZIi4+DzEpcj0B22uCJ7B0rxE4wdihBsmKo+1vx
++U56jb0JuK7qixgnTy5w/hOWusPTQBbNZU6sER7m8Q==
+-----END EC PRIVATE KEY-----
+*/
+var clientauthECDSATests = []clientauthTest{
+ // Server asks for cert with empty CA list, client gives one
+ // go test -run "TestRunServer" -serve \
+ // -clientauth 1 -ciphersuites=0xc00a
+ // openssl s_client -host 127.0.0.1 -port 10443 \
+ // -cipher ECDHE-ECDSA-AES256-SHA -key client.key -cert client.crt
+ {"RequestClientCert, client gives it", RequestClientCert, []*x509.Certificate{clientECDSACertificate}, [][]byte{
+ {
+ 0x16, 0x03, 0x01, 0x00, 0xa0, 0x01, 0x00, 0x00,
+ 0x9c, 0x03, 0x03, 0x51, 0xe5, 0x73, 0xc5, 0xae,
+ 0x51, 0x94, 0xb4, 0xf2, 0xe8, 0xf6, 0x03, 0x0e,
+ 0x3b, 0x34, 0xaf, 0xf0, 0xdc, 0x1b, 0xcc, 0xd8,
+ 0x0c, 0x45, 0x82, 0xd4, 0xd6, 0x76, 0x04, 0x6e,
+ 0x4f, 0x7a, 0x24, 0x00, 0x00, 0x04, 0xc0, 0x0a,
+ 0x00, 0xff, 0x01, 0x00, 0x00, 0x6f, 0x00, 0x0b,
+ 0x00, 0x04, 0x03, 0x00, 0x01, 0x02, 0x00, 0x0a,
+ 0x00, 0x34, 0x00, 0x32, 0x00, 0x0e, 0x00, 0x0d,
+ 0x00, 0x19, 0x00, 0x0b, 0x00, 0x0c, 0x00, 0x18,
+ 0x00, 0x09, 0x00, 0x0a, 0x00, 0x16, 0x00, 0x17,
+ 0x00, 0x08, 0x00, 0x06, 0x00, 0x07, 0x00, 0x14,
+ 0x00, 0x15, 0x00, 0x04, 0x00, 0x05, 0x00, 0x12,
+ 0x00, 0x13, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03,
+ 0x00, 0x0f, 0x00, 0x10, 0x00, 0x11, 0x00, 0x23,
+ 0x00, 0x00, 0x00, 0x0d, 0x00, 0x22, 0x00, 0x20,
+ 0x06, 0x01, 0x06, 0x02, 0x06, 0x03, 0x05, 0x01,
+ 0x05, 0x02, 0x05, 0x03, 0x04, 0x01, 0x04, 0x02,
+ 0x04, 0x03, 0x03, 0x01, 0x03, 0x02, 0x03, 0x03,
+ 0x02, 0x01, 0x02, 0x02, 0x02, 0x03, 0x01, 0x01,
+ 0x00, 0x0f, 0x00, 0x01, 0x01,
+ },
+ {
+ 0x16, 0x03, 0x01, 0x00, 0x30, 0x02, 0x00, 0x00,
+ 0x2c, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xc0, 0x0a, 0x00, 0x00,
+ 0x04, 0x00, 0x23, 0x00, 0x00, 0x16, 0x03, 0x01,
+ 0x02, 0x0e, 0x0b, 0x00, 0x02, 0x0a, 0x00, 0x02,
+ 0x07, 0x00, 0x02, 0x04, 0x30, 0x82, 0x02, 0x00,
+ 0x30, 0x82, 0x01, 0x62, 0x02, 0x09, 0x00, 0xb8,
+ 0xbf, 0x2d, 0x47, 0xa0, 0xd2, 0xeb, 0xf4, 0x30,
+ 0x09, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d,
+ 0x04, 0x01, 0x30, 0x45, 0x31, 0x0b, 0x30, 0x09,
+ 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x41,
+ 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
+ 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, 0x65,
+ 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x21,
+ 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13,
+ 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
+ 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, 0x74,
+ 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74,
+ 0x64, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x32, 0x31,
+ 0x31, 0x32, 0x32, 0x31, 0x35, 0x30, 0x36, 0x33,
+ 0x32, 0x5a, 0x17, 0x0d, 0x32, 0x32, 0x31, 0x31,
+ 0x32, 0x30, 0x31, 0x35, 0x30, 0x36, 0x33, 0x32,
+ 0x5a, 0x30, 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06,
+ 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x41, 0x55,
+ 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04,
+ 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d,
+ 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x21, 0x30,
+ 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x18,
+ 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74,
+ 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, 0x74, 0x73,
+ 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64,
+ 0x30, 0x81, 0x9b, 0x30, 0x10, 0x06, 0x07, 0x2a,
+ 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05,
+ 0x2b, 0x81, 0x04, 0x00, 0x23, 0x03, 0x81, 0x86,
+ 0x00, 0x04, 0x00, 0xc4, 0xa1, 0xed, 0xbe, 0x98,
+ 0xf9, 0x0b, 0x48, 0x73, 0x36, 0x7e, 0xc3, 0x16,
+ 0x56, 0x11, 0x22, 0xf2, 0x3d, 0x53, 0xc3, 0x3b,
+ 0x4d, 0x21, 0x3d, 0xcd, 0x6b, 0x75, 0xe6, 0xf6,
+ 0xb0, 0xdc, 0x9a, 0xdf, 0x26, 0xc1, 0xbc, 0xb2,
+ 0x87, 0xf0, 0x72, 0x32, 0x7c, 0xb3, 0x64, 0x2f,
+ 0x1c, 0x90, 0xbc, 0xea, 0x68, 0x23, 0x10, 0x7e,
+ 0xfe, 0xe3, 0x25, 0xc0, 0x48, 0x3a, 0x69, 0xe0,
+ 0x28, 0x6d, 0xd3, 0x37, 0x00, 0xef, 0x04, 0x62,
+ 0xdd, 0x0d, 0xa0, 0x9c, 0x70, 0x62, 0x83, 0xd8,
+ 0x81, 0xd3, 0x64, 0x31, 0xaa, 0x9e, 0x97, 0x31,
+ 0xbd, 0x96, 0xb0, 0x68, 0xc0, 0x9b, 0x23, 0xde,
+ 0x76, 0x64, 0x3f, 0x1a, 0x5c, 0x7f, 0xe9, 0x12,
+ 0x0e, 0x58, 0x58, 0xb6, 0x5f, 0x70, 0xdd, 0x9b,
+ 0xd8, 0xea, 0xd5, 0xd7, 0xf5, 0xd5, 0xcc, 0xb9,
+ 0xb6, 0x9f, 0x30, 0x66, 0x5b, 0x66, 0x9a, 0x20,
+ 0xe2, 0x27, 0xe5, 0xbf, 0xfe, 0x3b, 0x30, 0x09,
+ 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04,
+ 0x01, 0x03, 0x81, 0x8c, 0x00, 0x30, 0x81, 0x88,
+ 0x02, 0x42, 0x01, 0x88, 0xa2, 0x4f, 0xeb, 0xe2,
+ 0x45, 0xc5, 0x48, 0x7d, 0x1b, 0xac, 0xf5, 0xed,
+ 0x98, 0x9d, 0xae, 0x47, 0x70, 0xc0, 0x5e, 0x1b,
+ 0xb6, 0x2f, 0xbd, 0xf1, 0xb6, 0x4d, 0xb7, 0x61,
+ 0x40, 0xd3, 0x11, 0xa2, 0xce, 0xee, 0x0b, 0x7e,
+ 0x92, 0x7e, 0xff, 0x76, 0x9d, 0xc3, 0x3b, 0x7e,
+ 0xa5, 0x3f, 0xce, 0xfa, 0x10, 0xe2, 0x59, 0xec,
+ 0x47, 0x2d, 0x7c, 0xac, 0xda, 0x4e, 0x97, 0x0e,
+ 0x15, 0xa0, 0x6f, 0xd0, 0x02, 0x42, 0x01, 0x4d,
+ 0xfc, 0xbe, 0x67, 0x13, 0x9c, 0x2d, 0x05, 0x0e,
+ 0xbd, 0x3f, 0xa3, 0x8c, 0x25, 0xc1, 0x33, 0x13,
+ 0x83, 0x0d, 0x94, 0x06, 0xbb, 0xd4, 0x37, 0x7a,
+ 0xf6, 0xec, 0x7a, 0xc9, 0x86, 0x2e, 0xdd, 0xd7,
+ 0x11, 0x69, 0x7f, 0x85, 0x7c, 0x56, 0xde, 0xfb,
+ 0x31, 0x78, 0x2b, 0xe4, 0xc7, 0x78, 0x0d, 0xae,
+ 0xcb, 0xbe, 0x9e, 0x4e, 0x36, 0x24, 0x31, 0x7b,
+ 0x6a, 0x0f, 0x39, 0x95, 0x12, 0x07, 0x8f, 0x2a,
+ 0x16, 0x03, 0x01, 0x01, 0x1a, 0x0c, 0x00, 0x01,
+ 0x16, 0x03, 0x00, 0x19, 0x85, 0x04, 0x01, 0x39,
+ 0xdc, 0xee, 0x44, 0x17, 0x5e, 0xdb, 0xd7, 0x27,
+ 0xaf, 0xb6, 0x56, 0xd9, 0xb4, 0x43, 0x5a, 0x99,
+ 0xcf, 0xaa, 0x31, 0x37, 0x0c, 0x6f, 0x3a, 0xa0,
+ 0xf8, 0x53, 0xc4, 0x74, 0xd1, 0x91, 0x0a, 0x46,
+ 0xf5, 0x38, 0x3b, 0x5c, 0x09, 0xd8, 0x97, 0xdc,
+ 0x4b, 0xaa, 0x70, 0x26, 0x48, 0xf2, 0xd6, 0x0b,
+ 0x31, 0xc9, 0xf8, 0xd4, 0x98, 0x43, 0xe1, 0x6c,
+ 0xd5, 0xc7, 0xb2, 0x8e, 0x0b, 0x01, 0xe6, 0xb6,
+ 0x00, 0x28, 0x80, 0x7b, 0xfc, 0x96, 0x8f, 0x0d,
+ 0xa2, 0x4f, 0xb0, 0x79, 0xaf, 0xdc, 0x61, 0x28,
+ 0x63, 0x33, 0x78, 0xf6, 0x31, 0x39, 0xfd, 0x8a,
+ 0xf4, 0x15, 0x18, 0x11, 0xfe, 0xdb, 0xd5, 0x07,
+ 0xda, 0x2c, 0xed, 0x49, 0xa0, 0x23, 0xbf, 0xd0,
+ 0x3a, 0x38, 0x1d, 0x54, 0xae, 0x1c, 0x7b, 0xea,
+ 0x29, 0xee, 0xd0, 0x38, 0xc1, 0x76, 0xa7, 0x7f,
+ 0x2a, 0xf4, 0xce, 0x1e, 0xac, 0xcc, 0x94, 0x79,
+ 0x90, 0x33, 0x00, 0x8b, 0x30, 0x81, 0x88, 0x02,
+ 0x42, 0x00, 0xc6, 0x85, 0x8e, 0x06, 0xb7, 0x04,
+ 0x04, 0xe9, 0xcd, 0x9e, 0x3e, 0xcb, 0x66, 0x23,
+ 0x95, 0xb4, 0x42, 0x9c, 0x64, 0x81, 0x39, 0x05,
+ 0x3f, 0xb5, 0x21, 0xf8, 0x28, 0xaf, 0x60, 0x6b,
+ 0x4d, 0x3d, 0xba, 0xa1, 0x4b, 0x5e, 0x77, 0xef,
+ 0xe7, 0x59, 0x28, 0xfe, 0x1d, 0xc1, 0x27, 0xa2,
+ 0xff, 0xa8, 0xde, 0x33, 0x48, 0xb3, 0xc1, 0x85,
+ 0x6a, 0x42, 0x9b, 0xf9, 0x7e, 0x7e, 0x31, 0xc2,
+ 0xe5, 0xbd, 0x66, 0x02, 0x42, 0x00, 0xad, 0x7d,
+ 0x06, 0x35, 0xab, 0xec, 0x8d, 0xac, 0xd4, 0xba,
+ 0x1b, 0x49, 0x5e, 0x05, 0x5f, 0xf0, 0x97, 0x93,
+ 0x82, 0xb8, 0x2b, 0x8d, 0x91, 0x98, 0x63, 0x8e,
+ 0xb4, 0x14, 0x62, 0xdb, 0x1e, 0xc9, 0x2b, 0x30,
+ 0xf8, 0x41, 0x9b, 0xa6, 0xe6, 0xbc, 0xde, 0x0e,
+ 0x68, 0x30, 0x21, 0xf4, 0xa8, 0xa9, 0x1b, 0xec,
+ 0x44, 0x4f, 0x5d, 0x02, 0x2f, 0x60, 0x45, 0x60,
+ 0xba, 0xe0, 0x4e, 0xc0, 0xd4, 0x3b, 0x01, 0x16,
+ 0x03, 0x01, 0x00, 0x09, 0x0d, 0x00, 0x00, 0x05,
+ 0x02, 0x01, 0x40, 0x00, 0x00, 0x16, 0x03, 0x01,
+ 0x00, 0x04, 0x0e, 0x00, 0x00, 0x00,
+ },
+ {
+ 0x16, 0x03, 0x01, 0x02, 0x0a, 0x0b, 0x00, 0x02,
+ 0x06, 0x00, 0x02, 0x03, 0x00, 0x02, 0x00, 0x30,
+ 0x82, 0x01, 0xfc, 0x30, 0x82, 0x01, 0x5e, 0x02,
+ 0x09, 0x00, 0x9a, 0x30, 0x84, 0x6c, 0x26, 0x35,
+ 0xd9, 0x17, 0x30, 0x09, 0x06, 0x07, 0x2a, 0x86,
+ 0x48, 0xce, 0x3d, 0x04, 0x01, 0x30, 0x45, 0x31,
+ 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+ 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11,
+ 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53,
+ 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74,
+ 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55,
+ 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65,
+ 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64,
+ 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79,
+ 0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d,
+ 0x31, 0x32, 0x31, 0x31, 0x31, 0x34, 0x31, 0x33,
+ 0x32, 0x35, 0x35, 0x33, 0x5a, 0x17, 0x0d, 0x32,
+ 0x32, 0x31, 0x31, 0x31, 0x32, 0x31, 0x33, 0x32,
+ 0x35, 0x35, 0x33, 0x5a, 0x30, 0x41, 0x31, 0x0b,
+ 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
+ 0x02, 0x41, 0x55, 0x31, 0x0c, 0x30, 0x0a, 0x06,
+ 0x03, 0x55, 0x04, 0x08, 0x13, 0x03, 0x4e, 0x53,
+ 0x57, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55,
+ 0x04, 0x07, 0x13, 0x07, 0x50, 0x79, 0x72, 0x6d,
+ 0x6f, 0x6e, 0x74, 0x31, 0x12, 0x30, 0x10, 0x06,
+ 0x03, 0x55, 0x04, 0x03, 0x13, 0x09, 0x4a, 0x6f,
+ 0x65, 0x6c, 0x20, 0x53, 0x69, 0x6e, 0x67, 0x30,
+ 0x81, 0x9b, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86,
+ 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b,
+ 0x81, 0x04, 0x00, 0x23, 0x03, 0x81, 0x86, 0x00,
+ 0x04, 0x00, 0x95, 0x8c, 0x91, 0x75, 0x14, 0xc0,
+ 0x5e, 0xc4, 0x57, 0xb4, 0xd4, 0xc3, 0x6f, 0x8d,
+ 0xae, 0x68, 0x1e, 0xdd, 0x6f, 0xce, 0x86, 0xe1,
+ 0x7e, 0x6e, 0xb2, 0x48, 0x3e, 0x81, 0xe5, 0x4e,
+ 0xe2, 0xc6, 0x88, 0x4b, 0x64, 0xdc, 0xf5, 0x30,
+ 0xbb, 0xd3, 0xff, 0x65, 0xcc, 0x5b, 0xf4, 0xdd,
+ 0xb5, 0x6a, 0x3e, 0x3e, 0xd0, 0x1d, 0xde, 0x47,
+ 0xc3, 0x76, 0xad, 0x19, 0xf6, 0x45, 0x2c, 0x8c,
+ 0xbc, 0xd8, 0x1d, 0x01, 0x4c, 0x1f, 0x70, 0x90,
+ 0x46, 0x76, 0x48, 0x8b, 0x8f, 0x83, 0xcc, 0x4a,
+ 0x5c, 0x8f, 0x40, 0x76, 0xda, 0xe0, 0x89, 0xec,
+ 0x1d, 0x2b, 0xc4, 0x4e, 0x30, 0x76, 0x28, 0x41,
+ 0xb2, 0x62, 0xa8, 0xfb, 0x5b, 0xf1, 0xf9, 0x4e,
+ 0x7a, 0x8d, 0xbd, 0x09, 0xb8, 0xae, 0xea, 0x8b,
+ 0x18, 0x27, 0x4f, 0x2e, 0x70, 0xfe, 0x13, 0x96,
+ 0xba, 0xc3, 0xd3, 0x40, 0x16, 0xcd, 0x65, 0x4e,
+ 0xac, 0x11, 0x1e, 0xe6, 0xf1, 0x30, 0x09, 0x06,
+ 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x01,
+ 0x03, 0x81, 0x8c, 0x00, 0x30, 0x81, 0x88, 0x02,
+ 0x42, 0x00, 0xe0, 0x14, 0xc4, 0x60, 0x60, 0x0b,
+ 0x72, 0x68, 0xb0, 0x32, 0x5d, 0x61, 0x4a, 0x02,
+ 0x74, 0x5c, 0xc2, 0x81, 0xb9, 0x16, 0xa8, 0x3f,
+ 0x29, 0xc8, 0x36, 0xc7, 0x81, 0xff, 0x6c, 0xb6,
+ 0x5b, 0xd9, 0x70, 0xf1, 0x38, 0x3b, 0x50, 0x48,
+ 0x28, 0x94, 0xcb, 0x09, 0x1a, 0x52, 0xf1, 0x5d,
+ 0xee, 0x8d, 0xf2, 0xb9, 0xf0, 0xf0, 0xda, 0xd9,
+ 0x15, 0x3a, 0xf9, 0xbd, 0x03, 0x7a, 0x87, 0xa2,
+ 0x23, 0x35, 0xec, 0x02, 0x42, 0x01, 0xa3, 0xd4,
+ 0x8a, 0x78, 0x35, 0x1c, 0x4a, 0x9a, 0x23, 0xd2,
+ 0x0a, 0xbe, 0x2b, 0x10, 0x31, 0x9d, 0x9c, 0x5f,
+ 0xbe, 0xe8, 0x91, 0xb3, 0xda, 0x1a, 0xf5, 0x5d,
+ 0xa3, 0x23, 0xf5, 0x26, 0x8b, 0x45, 0x70, 0x8d,
+ 0x65, 0x62, 0x9b, 0x7e, 0x01, 0x99, 0x3d, 0x18,
+ 0xf6, 0x10, 0x9a, 0x38, 0x61, 0x9b, 0x2e, 0x57,
+ 0xe4, 0xfa, 0xcc, 0xb1, 0x8a, 0xce, 0xe2, 0x23,
+ 0xa0, 0x87, 0xf0, 0xe1, 0x67, 0x51, 0xeb, 0x16,
+ 0x03, 0x01, 0x00, 0x8a, 0x10, 0x00, 0x00, 0x86,
+ 0x85, 0x04, 0x00, 0xcd, 0x1c, 0xe8, 0x66, 0x5b,
+ 0xa8, 0x9d, 0x83, 0x2f, 0x7e, 0x1d, 0x0b, 0x59,
+ 0x23, 0xbc, 0x30, 0xcf, 0xa3, 0xaf, 0x21, 0xdc,
+ 0xf2, 0x57, 0x49, 0x56, 0x30, 0x25, 0x7c, 0x84,
+ 0x5d, 0xad, 0xaa, 0x9c, 0x7b, 0x2a, 0x95, 0x58,
+ 0x3d, 0x30, 0x87, 0x01, 0x3b, 0xb7, 0xea, 0xcb,
+ 0xc4, 0xa3, 0xeb, 0x22, 0xbf, 0x2d, 0x61, 0x17,
+ 0x8c, 0x9b, 0xe8, 0x1b, 0xb2, 0x87, 0x16, 0x78,
+ 0xd5, 0xfd, 0x8b, 0xdd, 0x00, 0x0f, 0xda, 0x8e,
+ 0xfd, 0x28, 0x36, 0xeb, 0xe4, 0xc5, 0x42, 0x14,
+ 0xc7, 0xbd, 0x29, 0x5e, 0x9a, 0xed, 0x5e, 0xc1,
+ 0xf7, 0xf4, 0xbd, 0xbd, 0x15, 0x9c, 0xe8, 0x44,
+ 0x71, 0xa7, 0xb6, 0xe9, 0xfa, 0x7e, 0x97, 0xcb,
+ 0x96, 0x3e, 0x53, 0x76, 0xfb, 0x11, 0x1f, 0x36,
+ 0x8f, 0x30, 0xfb, 0x71, 0x3a, 0x75, 0x3a, 0x25,
+ 0x7b, 0xa2, 0xc1, 0xf9, 0x3e, 0x58, 0x5f, 0x07,
+ 0x16, 0xed, 0xe1, 0xf7, 0xc1, 0xb1, 0x16, 0x03,
+ 0x01, 0x00, 0x90, 0x0f, 0x00, 0x00, 0x8c, 0x00,
+ 0x8a, 0x30, 0x81, 0x87, 0x02, 0x42, 0x00, 0xb2,
+ 0xd3, 0x91, 0xe6, 0xd5, 0x9b, 0xb2, 0xb8, 0x03,
+ 0xf4, 0x85, 0x4d, 0x43, 0x79, 0x1f, 0xb6, 0x6f,
+ 0x0c, 0xcd, 0x67, 0x5f, 0x5e, 0xca, 0xee, 0xb3,
+ 0xe4, 0xab, 0x1e, 0x58, 0xc3, 0x04, 0xa9, 0x8a,
+ 0xa7, 0xcf, 0xaa, 0x33, 0x88, 0xd5, 0x35, 0xd2,
+ 0x80, 0x8f, 0xfa, 0x1b, 0x3c, 0x3d, 0xf7, 0x80,
+ 0x50, 0xde, 0x80, 0x30, 0x64, 0xee, 0xc0, 0xb3,
+ 0x91, 0x6e, 0x5d, 0x1e, 0xc0, 0xdc, 0x3a, 0x93,
+ 0x02, 0x41, 0x4e, 0xca, 0x98, 0x41, 0x8c, 0x36,
+ 0xf2, 0x12, 0xbf, 0x8e, 0x0f, 0x69, 0x8e, 0xf8,
+ 0x7b, 0x9d, 0xba, 0x9c, 0x5c, 0x48, 0x79, 0xf4,
+ 0xba, 0x3d, 0x06, 0xa5, 0xab, 0x47, 0xe0, 0x1a,
+ 0x45, 0x28, 0x3a, 0x8f, 0xbf, 0x14, 0x24, 0x36,
+ 0xd1, 0x1d, 0x29, 0xdc, 0xde, 0x72, 0x5b, 0x76,
+ 0x41, 0x67, 0xe8, 0xe5, 0x71, 0x4a, 0x77, 0xe9,
+ 0xed, 0x02, 0x19, 0xdd, 0xe4, 0xaa, 0xe9, 0x2d,
+ 0xe7, 0x47, 0x32, 0x14, 0x03, 0x01, 0x00, 0x01,
+ 0x01, 0x16, 0x03, 0x01, 0x00, 0x30, 0xfa, 0xc3,
+ 0xf2, 0x35, 0xd0, 0x6d, 0x32, 0x78, 0x6a, 0xd6,
+ 0xe6, 0x70, 0x5e, 0x00, 0x4c, 0x35, 0xf1, 0xe0,
+ 0x21, 0xcf, 0xc3, 0x78, 0xcd, 0xe0, 0x2b, 0x0b,
+ 0xf4, 0xeb, 0xf9, 0xc0, 0x38, 0xf2, 0x9a, 0x31,
+ 0x55, 0x07, 0x2b, 0x8d, 0x68, 0x40, 0x31, 0x08,
+ 0xaa, 0xe3, 0x16, 0xcf, 0x4b, 0xd4,
+ },
+ {
+ 0x16, 0x03, 0x01, 0x02, 0x76, 0x04, 0x00, 0x02,
+ 0x72, 0x00, 0x00, 0x00, 0x00, 0x02, 0x6c, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65,
+ 0xe8, 0x8b, 0xde, 0xef, 0xba, 0xf9, 0xdb, 0x95,
+ 0x24, 0xa5, 0x49, 0xb3, 0x23, 0xd8, 0x73, 0x88,
+ 0x50, 0x42, 0xed, 0xeb, 0xa3, 0xd8, 0xab, 0x31,
+ 0x9c, 0xd0, 0x00, 0x01, 0xef, 0xc0, 0xbf, 0xab,
+ 0x59, 0x55, 0xb5, 0xb9, 0xef, 0xa5, 0xa6, 0xec,
+ 0x69, 0xed, 0x00, 0x2f, 0x47, 0xdb, 0x75, 0x52,
+ 0x0c, 0xe5, 0x86, 0xb7, 0x02, 0x59, 0x22, 0xf7,
+ 0xfd, 0x8b, 0xff, 0xa4, 0x09, 0xc0, 0x1c, 0x10,
+ 0x80, 0x10, 0x7f, 0x4c, 0x7a, 0x94, 0x40, 0x10,
+ 0x0d, 0xda, 0x8a, 0xe5, 0x4a, 0xbc, 0xd0, 0xc0,
+ 0x4b, 0xa5, 0x33, 0x97, 0xc6, 0xe7, 0x40, 0x7f,
+ 0x7f, 0x8c, 0xf9, 0xf8, 0xc8, 0xb8, 0xfb, 0x8c,
+ 0xdd, 0x28, 0x81, 0xae, 0xfd, 0x37, 0x20, 0x3a,
+ 0x40, 0x37, 0x99, 0xc4, 0x21, 0x01, 0xc4, 0x91,
+ 0xb0, 0x5e, 0x11, 0xc5, 0xa9, 0xfd, 0x9a, 0x02,
+ 0x7e, 0x97, 0x6a, 0x86, 0x89, 0xb8, 0xc1, 0x32,
+ 0x4c, 0x7e, 0x6d, 0x47, 0x61, 0x0e, 0xe3, 0xc2,
+ 0xf0, 0x62, 0x3c, 0xc6, 0x71, 0x4f, 0xbb, 0x47,
+ 0x65, 0xb1, 0xd9, 0x22, 0x79, 0x15, 0xea, 0x1f,
+ 0x4b, 0x2a, 0x8a, 0xa4, 0xc8, 0x73, 0x34, 0xba,
+ 0x83, 0xe4, 0x70, 0x99, 0xc9, 0xcf, 0xbe, 0x64,
+ 0x99, 0xb9, 0xfa, 0xe9, 0xaf, 0x5d, 0xc7, 0x20,
+ 0x26, 0xde, 0xc5, 0x06, 0x12, 0x36, 0x4f, 0x4d,
+ 0xc0, 0xbb, 0x81, 0x5b, 0x5e, 0x38, 0xc3, 0x07,
+ 0x21, 0x04, 0x1a, 0x53, 0x9c, 0x59, 0xac, 0x2d,
+ 0xe6, 0xa5, 0x93, 0xa5, 0x19, 0xc6, 0xb0, 0xf7,
+ 0x56, 0x5d, 0xdf, 0xd1, 0xf4, 0xfd, 0x44, 0x6d,
+ 0xc6, 0xa2, 0x31, 0xa7, 0x35, 0x42, 0x18, 0x50,
+ 0x0c, 0x4f, 0x6e, 0xe3, 0x3b, 0xa3, 0xaa, 0x1c,
+ 0xbe, 0x41, 0x0d, 0xce, 0x6c, 0x62, 0xe1, 0x96,
+ 0x2d, 0xbd, 0x14, 0x31, 0xe3, 0xc4, 0x5b, 0xbf,
+ 0xf6, 0xde, 0xec, 0x42, 0xe8, 0xc7, 0x2a, 0x0b,
+ 0xdb, 0x2d, 0x7c, 0xf0, 0x3f, 0x45, 0x32, 0x45,
+ 0x09, 0x47, 0x09, 0x0f, 0x21, 0x22, 0x45, 0x06,
+ 0x11, 0xb8, 0xf9, 0xe6, 0x67, 0x90, 0x4b, 0x4a,
+ 0xde, 0x81, 0xfb, 0xeb, 0xe7, 0x9a, 0x08, 0x30,
+ 0xcf, 0x51, 0xe1, 0xd9, 0xfa, 0x79, 0xa3, 0xcc,
+ 0x65, 0x1a, 0x83, 0x86, 0xc9, 0x7a, 0x41, 0xf5,
+ 0xdf, 0xa0, 0x7c, 0x44, 0x23, 0x17, 0xf3, 0x62,
+ 0xe8, 0xa9, 0x31, 0x1e, 0x6b, 0x05, 0x4b, 0x4f,
+ 0x9d, 0x91, 0x46, 0x92, 0xa6, 0x25, 0x32, 0xca,
+ 0xa1, 0x75, 0xda, 0xe6, 0x80, 0x3e, 0x7f, 0xd1,
+ 0x26, 0x57, 0x07, 0x42, 0xe4, 0x91, 0xff, 0xbd,
+ 0x44, 0xae, 0x98, 0x5c, 0x1d, 0xdf, 0x11, 0xe3,
+ 0xae, 0x87, 0x5e, 0xb7, 0x69, 0xad, 0x34, 0x7f,
+ 0x3a, 0x07, 0x7c, 0xdf, 0xfc, 0x76, 0x17, 0x8b,
+ 0x62, 0xc8, 0xe1, 0x78, 0x2a, 0xc8, 0xb9, 0x8a,
+ 0xbb, 0x5c, 0xfb, 0x38, 0x74, 0x91, 0x6e, 0x12,
+ 0x0c, 0x1f, 0x8e, 0xe1, 0xc2, 0x01, 0xd8, 0x9d,
+ 0x23, 0x0f, 0xc4, 0x67, 0x5d, 0xe5, 0x67, 0x4b,
+ 0x94, 0x6e, 0x69, 0x72, 0x90, 0x2d, 0x52, 0x78,
+ 0x8e, 0x61, 0xba, 0xdf, 0x4e, 0xf5, 0xdc, 0xfb,
+ 0x73, 0xbe, 0x03, 0x70, 0xd9, 0x01, 0x30, 0xf3,
+ 0xa1, 0xbb, 0x9a, 0x5f, 0xec, 0x9e, 0xed, 0x8d,
+ 0xdd, 0x53, 0xfd, 0x60, 0xc3, 0x2b, 0x7a, 0x00,
+ 0x2c, 0xf9, 0x0a, 0x57, 0x47, 0x45, 0x43, 0xb3,
+ 0x23, 0x01, 0x9c, 0xee, 0x54, 0x4d, 0x58, 0xd3,
+ 0x71, 0x1c, 0xc9, 0xd3, 0x30, 0x9e, 0x14, 0xa5,
+ 0xf3, 0xbf, 0x4d, 0x9b, 0xb7, 0x13, 0x21, 0xae,
+ 0xd2, 0x8d, 0x6e, 0x6f, 0x1c, 0xcc, 0xb2, 0x41,
+ 0xb2, 0x64, 0x56, 0x83, 0xce, 0xd1, 0x0c, 0x79,
+ 0x32, 0x78, 0xef, 0xc5, 0x21, 0xb1, 0xe8, 0xc4,
+ 0x42, 0xa7, 0x8d, 0xc1, 0xfa, 0xa1, 0x9c, 0x3c,
+ 0x21, 0xd8, 0xe9, 0x90, 0xe2, 0x7c, 0x14, 0x26,
+ 0xfe, 0x61, 0x3e, 0xf9, 0x71, 0x1d, 0x5d, 0x49,
+ 0x3b, 0xb1, 0xb8, 0x42, 0xa1, 0xb8, 0x1c, 0x75,
+ 0x7d, 0xee, 0xed, 0xfc, 0xe6, 0x20, 0x2b, 0x9e,
+ 0x10, 0x52, 0xda, 0x56, 0x4d, 0x64, 0x6c, 0x41,
+ 0xc1, 0xf7, 0x60, 0x0c, 0x10, 0x65, 0x6f, 0xd4,
+ 0xe9, 0x9b, 0x0d, 0x83, 0x13, 0xc8, 0x5a, 0xa3,
+ 0x56, 0x2a, 0x42, 0xc6, 0x1c, 0xfe, 0xdb, 0xba,
+ 0x3d, 0x04, 0x12, 0xfd, 0x28, 0xeb, 0x78, 0xdd,
+ 0xbc, 0xc8, 0x0d, 0xa1, 0xce, 0xd4, 0x54, 0xbf,
+ 0xaf, 0xe1, 0x60, 0x0c, 0xa3, 0xc3, 0xc3, 0x62,
+ 0x58, 0xc1, 0x79, 0xa7, 0x95, 0x41, 0x09, 0x24,
+ 0xc6, 0x9a, 0x50, 0x14, 0x03, 0x01, 0x00, 0x01,
+ 0x01, 0x16, 0x03, 0x01, 0x00, 0x30, 0x4d, 0x7b,
+ 0x5f, 0x28, 0x5e, 0x68, 0x6c, 0xa3, 0x65, 0xc7,
+ 0x7e, 0x49, 0x6c, 0xb3, 0x67, 0xbb, 0xd0, 0x75,
+ 0xa2, 0x9e, 0x8c, 0x92, 0x4f, 0x8c, 0x33, 0x14,
+ 0x7c, 0x6c, 0xf1, 0x74, 0x97, 0xc3, 0xe0, 0x10,
+ 0xe9, 0x0d, 0xc2, 0x30, 0x5c, 0x23, 0xee, 0x1d,
+ 0x16, 0x2e, 0xb9, 0x96, 0x2b, 0x2d, 0x17, 0x03,
+ 0x01, 0x00, 0x20, 0xf2, 0xc8, 0xa7, 0x1b, 0x60,
+ 0x46, 0xee, 0xe5, 0x7e, 0xc9, 0x35, 0xb3, 0xf1,
+ 0x7c, 0x32, 0x0c, 0x85, 0x94, 0x59, 0x57, 0x27,
+ 0xb0, 0xbd, 0x52, 0x86, 0x90, 0xf1, 0xb7, 0x4d,
+ 0x1e, 0xc1, 0x16, 0x17, 0x03, 0x01, 0x00, 0x30,
+ 0xff, 0x85, 0x50, 0xdf, 0x3f, 0xfc, 0xa2, 0x61,
+ 0x1a, 0x12, 0xc0, 0x1e, 0x10, 0x32, 0x88, 0x50,
+ 0xa0, 0x2c, 0x80, 0xda, 0x77, 0xea, 0x09, 0x47,
+ 0xe0, 0x85, 0x07, 0x29, 0x45, 0x65, 0x19, 0xa3,
+ 0x8d, 0x99, 0xb8, 0xbf, 0xb6, 0xbc, 0x76, 0xe2,
+ 0x50, 0x24, 0x82, 0x0a, 0xfd, 0xdd, 0x35, 0x09,
+ 0x15, 0x03, 0x01, 0x00, 0x20, 0xe7, 0x36, 0xf6,
+ 0x61, 0xd2, 0x95, 0x3c, 0xb6, 0x65, 0x7b, 0xb2,
+ 0xb8, 0xdf, 0x03, 0x53, 0xeb, 0xf7, 0x16, 0xe0,
+ 0xe0, 0x15, 0x22, 0x71, 0x70, 0x62, 0x73, 0xad,
+ 0xb5, 0x1a, 0x77, 0x44, 0x57,
+ },
+ }},
+}
+
+var aesGCMServerScript = [][]byte{
+ {
+ 0x16, 0x03, 0x01, 0x01, 0x1c, 0x01, 0x00, 0x01,
+ 0x18, 0x03, 0x03, 0x52, 0x1e, 0x74, 0xf0, 0xb0,
+ 0xc1, 0x8b, 0x16, 0xf9, 0x74, 0xfc, 0x16, 0xc4,
+ 0x11, 0x18, 0x96, 0x08, 0x25, 0x38, 0x4f, 0x98,
+ 0x98, 0xbe, 0xb5, 0x61, 0xdf, 0x94, 0x15, 0xcc,
+ 0x9b, 0x61, 0xef, 0x00, 0x00, 0x80, 0xc0, 0x30,
+ 0xc0, 0x2c, 0xc0, 0x28, 0xc0, 0x24, 0xc0, 0x14,
+ 0xc0, 0x0a, 0x00, 0xa3, 0x00, 0x9f, 0x00, 0x6b,
+ 0x00, 0x6a, 0x00, 0x39, 0x00, 0x38, 0xc0, 0x32,
+ 0xc0, 0x2e, 0xc0, 0x2a, 0xc0, 0x26, 0xc0, 0x0f,
+ 0xc0, 0x05, 0x00, 0x9d, 0x00, 0x3d, 0x00, 0x35,
+ 0xc0, 0x12, 0xc0, 0x08, 0x00, 0x16, 0x00, 0x13,
+ 0xc0, 0x0d, 0xc0, 0x03, 0x00, 0x0a, 0xc0, 0x2f,
+ 0xc0, 0x2b, 0xc0, 0x27, 0xc0, 0x23, 0xc0, 0x13,
+ 0xc0, 0x09, 0x00, 0xa2, 0x00, 0x9e, 0x00, 0x67,
+ 0x00, 0x40, 0x00, 0x33, 0x00, 0x32, 0xc0, 0x31,
+ 0xc0, 0x2d, 0xc0, 0x29, 0xc0, 0x25, 0xc0, 0x0e,
+ 0xc0, 0x04, 0x00, 0x9c, 0x00, 0x3c, 0x00, 0x2f,
+ 0xc0, 0x11, 0xc0, 0x07, 0xc0, 0x0c, 0xc0, 0x02,
+ 0x00, 0x05, 0x00, 0x04, 0x00, 0x15, 0x00, 0x12,
+ 0x00, 0x09, 0x00, 0x14, 0x00, 0x11, 0x00, 0x08,
+ 0x00, 0x06, 0x00, 0x03, 0x00, 0xff, 0x01, 0x00,
+ 0x00, 0x6f, 0x00, 0x0b, 0x00, 0x04, 0x03, 0x00,
+ 0x01, 0x02, 0x00, 0x0a, 0x00, 0x34, 0x00, 0x32,
+ 0x00, 0x0e, 0x00, 0x0d, 0x00, 0x19, 0x00, 0x0b,
+ 0x00, 0x0c, 0x00, 0x18, 0x00, 0x09, 0x00, 0x0a,
+ 0x00, 0x16, 0x00, 0x17, 0x00, 0x08, 0x00, 0x06,
+ 0x00, 0x07, 0x00, 0x14, 0x00, 0x15, 0x00, 0x04,
+ 0x00, 0x05, 0x00, 0x12, 0x00, 0x13, 0x00, 0x01,
+ 0x00, 0x02, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x10,
+ 0x00, 0x11, 0x00, 0x23, 0x00, 0x00, 0x00, 0x0d,
+ 0x00, 0x22, 0x00, 0x20, 0x06, 0x01, 0x06, 0x02,
+ 0x06, 0x03, 0x05, 0x01, 0x05, 0x02, 0x05, 0x03,
+ 0x04, 0x01, 0x04, 0x02, 0x04, 0x03, 0x03, 0x01,
+ 0x03, 0x02, 0x03, 0x03, 0x02, 0x01, 0x02, 0x02,
+ 0x02, 0x03, 0x01, 0x01, 0x00, 0x0f, 0x00, 0x01,
+ 0x01,
+ },
+ {
+ 0x16, 0x03, 0x03, 0x00, 0x30, 0x02, 0x00, 0x00,
+ 0x2c, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xc0, 0x2f, 0x00, 0x00,
+ 0x04, 0x00, 0x23, 0x00, 0x00, 0x16, 0x03, 0x03,
+ 0x02, 0xbe, 0x0b, 0x00, 0x02, 0xba, 0x00, 0x02,
+ 0xb7, 0x00, 0x02, 0xb4, 0x30, 0x82, 0x02, 0xb0,
+ 0x30, 0x82, 0x02, 0x19, 0xa0, 0x03, 0x02, 0x01,
+ 0x02, 0x02, 0x09, 0x00, 0x85, 0xb0, 0xbb, 0xa4,
+ 0x8a, 0x7f, 0xb8, 0xca, 0x30, 0x0d, 0x06, 0x09,
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+ 0x05, 0x05, 0x00, 0x30, 0x45, 0x31, 0x0b, 0x30,
+ 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+ 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
+ 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d,
+ 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31,
+ 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a,
+ 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e,
+ 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69,
+ 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c,
+ 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x30,
+ 0x30, 0x34, 0x32, 0x34, 0x30, 0x39, 0x30, 0x39,
+ 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x31, 0x31, 0x30,
+ 0x34, 0x32, 0x34, 0x30, 0x39, 0x30, 0x39, 0x33,
+ 0x38, 0x5a, 0x30, 0x45, 0x31, 0x0b, 0x30, 0x09,
+ 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x41,
+ 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
+ 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, 0x65,
+ 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x21,
+ 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13,
+ 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
+ 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, 0x74,
+ 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74,
+ 0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09,
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+ 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30,
+ 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xbb, 0x79,
+ 0xd6, 0xf5, 0x17, 0xb5, 0xe5, 0xbf, 0x46, 0x10,
+ 0xd0, 0xdc, 0x69, 0xbe, 0xe6, 0x2b, 0x07, 0x43,
+ 0x5a, 0xd0, 0x03, 0x2d, 0x8a, 0x7a, 0x43, 0x85,
+ 0xb7, 0x14, 0x52, 0xe7, 0xa5, 0x65, 0x4c, 0x2c,
+ 0x78, 0xb8, 0x23, 0x8c, 0xb5, 0xb4, 0x82, 0xe5,
+ 0xde, 0x1f, 0x95, 0x3b, 0x7e, 0x62, 0xa5, 0x2c,
+ 0xa5, 0x33, 0xd6, 0xfe, 0x12, 0x5c, 0x7a, 0x56,
+ 0xfc, 0xf5, 0x06, 0xbf, 0xfa, 0x58, 0x7b, 0x26,
+ 0x3f, 0xb5, 0xcd, 0x04, 0xd3, 0xd0, 0xc9, 0x21,
+ 0x96, 0x4a, 0xc7, 0xf4, 0x54, 0x9f, 0x5a, 0xbf,
+ 0xef, 0x42, 0x71, 0x00, 0xfe, 0x18, 0x99, 0x07,
+ 0x7f, 0x7e, 0x88, 0x7d, 0x7d, 0xf1, 0x04, 0x39,
+ 0xc4, 0xa2, 0x2e, 0xdb, 0x51, 0xc9, 0x7c, 0xe3,
+ 0xc0, 0x4c, 0x3b, 0x32, 0x66, 0x01, 0xcf, 0xaf,
+ 0xb1, 0x1d, 0xb8, 0x71, 0x9a, 0x1d, 0xdb, 0xdb,
+ 0x89, 0x6b, 0xae, 0xda, 0x2d, 0x79, 0x02, 0x03,
+ 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7, 0x30, 0x81,
+ 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e,
+ 0x04, 0x16, 0x04, 0x14, 0xb1, 0xad, 0xe2, 0x85,
+ 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69, 0xce, 0x23,
+ 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18, 0x88, 0x39,
+ 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04,
+ 0x6e, 0x30, 0x6c, 0x80, 0x14, 0xb1, 0xad, 0xe2,
+ 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69, 0xce,
+ 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18, 0x88,
+ 0x39, 0xa1, 0x49, 0xa4, 0x47, 0x30, 0x45, 0x31,
+ 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+ 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11,
+ 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53,
+ 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74,
+ 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55,
+ 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65,
+ 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64,
+ 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79,
+ 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09, 0x00, 0x85,
+ 0xb0, 0xbb, 0xa4, 0x8a, 0x7f, 0xb8, 0xca, 0x30,
+ 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05,
+ 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06,
+ 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
+ 0x01, 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00,
+ 0x08, 0x6c, 0x45, 0x24, 0xc7, 0x6b, 0xb1, 0x59,
+ 0xab, 0x0c, 0x52, 0xcc, 0xf2, 0xb0, 0x14, 0xd7,
+ 0x87, 0x9d, 0x7a, 0x64, 0x75, 0xb5, 0x5a, 0x95,
+ 0x66, 0xe4, 0xc5, 0x2b, 0x8e, 0xae, 0x12, 0x66,
+ 0x1f, 0xeb, 0x4f, 0x38, 0xb3, 0x6e, 0x60, 0xd3,
+ 0x92, 0xfd, 0xf7, 0x41, 0x08, 0xb5, 0x25, 0x13,
+ 0xb1, 0x18, 0x7a, 0x24, 0xfb, 0x30, 0x1d, 0xba,
+ 0xed, 0x98, 0xb9, 0x17, 0xec, 0xe7, 0xd7, 0x31,
+ 0x59, 0xdb, 0x95, 0xd3, 0x1d, 0x78, 0xea, 0x50,
+ 0x56, 0x5c, 0xd5, 0x82, 0x5a, 0x2d, 0x5a, 0x5f,
+ 0x33, 0xc4, 0xb6, 0xd8, 0xc9, 0x75, 0x90, 0x96,
+ 0x8c, 0x0f, 0x52, 0x98, 0xb5, 0xcd, 0x98, 0x1f,
+ 0x89, 0x20, 0x5f, 0xf2, 0xa0, 0x1c, 0xa3, 0x1b,
+ 0x96, 0x94, 0xdd, 0xa9, 0xfd, 0x57, 0xe9, 0x70,
+ 0xe8, 0x26, 0x6d, 0x71, 0x99, 0x9b, 0x26, 0x6e,
+ 0x38, 0x50, 0x29, 0x6c, 0x90, 0xa7, 0xbd, 0xd9,
+ 0x16, 0x03, 0x03, 0x01, 0x11, 0x0c, 0x00, 0x01,
+ 0x0d, 0x03, 0x00, 0x19, 0x85, 0x04, 0x01, 0x39,
+ 0xdc, 0xee, 0x44, 0x17, 0x5e, 0xdb, 0xd7, 0x27,
+ 0xaf, 0xb6, 0x56, 0xd9, 0xb4, 0x43, 0x5a, 0x99,
+ 0xcf, 0xaa, 0x31, 0x37, 0x0c, 0x6f, 0x3a, 0xa0,
+ 0xf8, 0x53, 0xc4, 0x74, 0xd1, 0x91, 0x0a, 0x46,
+ 0xf5, 0x38, 0x3b, 0x5c, 0x09, 0xd8, 0x97, 0xdc,
+ 0x4b, 0xaa, 0x70, 0x26, 0x48, 0xf2, 0xd6, 0x0b,
+ 0x31, 0xc9, 0xf8, 0xd4, 0x98, 0x43, 0xe1, 0x6c,
+ 0xd5, 0xc7, 0xb2, 0x8e, 0x0b, 0x01, 0xe6, 0xb6,
+ 0x00, 0x28, 0x80, 0x7b, 0xfc, 0x96, 0x8f, 0x0d,
+ 0xa2, 0x4f, 0xb0, 0x79, 0xaf, 0xdc, 0x61, 0x28,
+ 0x63, 0x33, 0x78, 0xf6, 0x31, 0x39, 0xfd, 0x8a,
+ 0xf4, 0x15, 0x18, 0x11, 0xfe, 0xdb, 0xd5, 0x07,
+ 0xda, 0x2c, 0xed, 0x49, 0xa0, 0x23, 0xbf, 0xd0,
+ 0x3a, 0x38, 0x1d, 0x54, 0xae, 0x1c, 0x7b, 0xea,
+ 0x29, 0xee, 0xd0, 0x38, 0xc1, 0x76, 0xa7, 0x7f,
+ 0x2a, 0xf4, 0xce, 0x1e, 0xac, 0xcc, 0x94, 0x79,
+ 0x90, 0x33, 0x04, 0x01, 0x00, 0x80, 0x0d, 0x8e,
+ 0x79, 0xe6, 0x86, 0xf6, 0xb6, 0xfb, 0x6b, 0x6a,
+ 0xcc, 0x55, 0xe4, 0x80, 0x4d, 0xc5, 0x0c, 0xc6,
+ 0xa3, 0x9f, 0x1d, 0x39, 0xd2, 0x98, 0x57, 0x31,
+ 0xa2, 0x90, 0x73, 0xe8, 0xd2, 0xcd, 0xb0, 0x93,
+ 0x1a, 0x60, 0x0f, 0x38, 0x02, 0x3b, 0x1b, 0x25,
+ 0x56, 0xec, 0x44, 0xab, 0xbe, 0x2e, 0x0c, 0xc0,
+ 0x6e, 0x54, 0x91, 0x50, 0xd6, 0xb1, 0xa2, 0x98,
+ 0x14, 0xa8, 0x35, 0x62, 0x9d, 0xca, 0xfb, 0x0f,
+ 0x64, 0x2b, 0x05, 0xa0, 0xa0, 0x57, 0xef, 0xcd,
+ 0x95, 0x45, 0x13, 0x5a, 0x9b, 0x3d, 0xdb, 0x42,
+ 0x54, 0x7f, 0xb9, 0x17, 0x08, 0x7f, 0xb2, 0xf0,
+ 0xb1, 0xc3, 0xdf, 0x67, 0x95, 0xe2, 0x73, 0xf2,
+ 0x76, 0xa3, 0x97, 0xfd, 0x9c, 0x92, 0x4a, 0xdb,
+ 0x95, 0x1e, 0x91, 0x95, 0xae, 0x3d, 0xae, 0x58,
+ 0xb5, 0x03, 0x6f, 0x5c, 0x3a, 0x19, 0xab, 0x92,
+ 0xa5, 0x09, 0x6b, 0x40, 0x61, 0xb0, 0x16, 0x03,
+ 0x03, 0x00, 0x04, 0x0e, 0x00, 0x00, 0x00,
+ },
+ {
+ 0x16, 0x03, 0x03, 0x00, 0x8a, 0x10, 0x00, 0x00,
+ 0x86, 0x85, 0x04, 0x01, 0xba, 0xb8, 0xad, 0x69,
+ 0x20, 0x5e, 0xc1, 0x61, 0xc3, 0x0f, 0xb4, 0x30,
+ 0x64, 0x66, 0x70, 0x96, 0x33, 0x3c, 0x8e, 0x12,
+ 0x56, 0xbf, 0x6d, 0xb8, 0x6d, 0xc6, 0xba, 0xea,
+ 0xfc, 0x38, 0xc0, 0x8b, 0x87, 0xa8, 0xf3, 0x87,
+ 0xa1, 0xd5, 0xb6, 0xb0, 0x72, 0xc7, 0xd4, 0x19,
+ 0x56, 0xa0, 0x91, 0xe1, 0x45, 0xc7, 0xf1, 0x7d,
+ 0xb0, 0x1d, 0x78, 0x18, 0xf6, 0x3d, 0xbf, 0x1a,
+ 0x23, 0x93, 0x0b, 0x19, 0xb1, 0x00, 0x56, 0xc9,
+ 0x5e, 0x89, 0xd4, 0x9d, 0xd9, 0x5b, 0xe0, 0xb8,
+ 0xff, 0x2f, 0x7d, 0x93, 0xae, 0x5b, 0xa5, 0x1f,
+ 0x1f, 0x2b, 0x09, 0xe5, 0xf6, 0x07, 0x26, 0xa3,
+ 0xed, 0xcb, 0x6a, 0x1a, 0xd6, 0x14, 0x83, 0x9b,
+ 0xd3, 0x9d, 0x47, 0x1b, 0xf3, 0x72, 0x5f, 0x69,
+ 0x21, 0x8f, 0xfa, 0x09, 0x38, 0x1a, 0x6b, 0x91,
+ 0xcf, 0x19, 0x32, 0x54, 0x58, 0x8e, 0xee, 0xaf,
+ 0xeb, 0x06, 0x9b, 0x3a, 0x34, 0x16, 0x66, 0x14,
+ 0x03, 0x03, 0x00, 0x01, 0x01, 0x16, 0x03, 0x03,
+ 0x00, 0x28, 0xc6, 0x96, 0x67, 0x62, 0xcc, 0x47,
+ 0x01, 0xb5, 0xbd, 0xb7, 0x24, 0xd3, 0xb6, 0xfd,
+ 0xb8, 0x46, 0xce, 0x82, 0x6d, 0x31, 0x1f, 0x15,
+ 0x11, 0x8f, 0xed, 0x62, 0x71, 0x5f, 0xae, 0xb6,
+ 0xa9, 0x0c, 0x24, 0x1d, 0xe8, 0x26, 0x51, 0xca,
+ 0x7c, 0x42,
+ },
+ {
+ 0x16, 0x03, 0x03, 0x00, 0x72, 0x04, 0x00, 0x00,
+ 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65,
+ 0xea, 0x8b, 0xfb, 0xef, 0xba, 0xc8, 0x88, 0x94,
+ 0x44, 0x99, 0x5f, 0x02, 0x68, 0x3a, 0x12, 0x67,
+ 0x7f, 0xb9, 0x39, 0x71, 0x84, 0xe0, 0x30, 0xe6,
+ 0x90, 0x6c, 0xcf, 0x32, 0x29, 0x29, 0x5c, 0x5a,
+ 0x8b, 0x7d, 0xaa, 0x11, 0x28, 0x26, 0xb5, 0xce,
+ 0xd2, 0x88, 0xd5, 0xb0, 0x5f, 0x94, 0x37, 0xa2,
+ 0x48, 0xd9, 0x53, 0xb2, 0xab, 0x59, 0x23, 0x3d,
+ 0x81, 0x6e, 0x64, 0x89, 0xca, 0x1a, 0x84, 0x16,
+ 0xdf, 0x31, 0x10, 0xde, 0x52, 0x7f, 0x50, 0xf3,
+ 0xd9, 0x27, 0xa0, 0xe8, 0x34, 0x15, 0x9e, 0x11,
+ 0xdd, 0xba, 0xce, 0x40, 0x17, 0xf3, 0x67, 0x14,
+ 0x03, 0x03, 0x00, 0x01, 0x01, 0x16, 0x03, 0x03,
+ 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x35, 0xcb, 0x17, 0x66, 0xee, 0xfd,
+ 0x27, 0xdb, 0xb8, 0xa8, 0x8a, 0xf1, 0x56, 0x67,
+ 0x89, 0x0d, 0x13, 0xac, 0xe2, 0x31, 0xb9, 0xa2,
+ 0x26, 0xbb, 0x1c, 0xcf, 0xd1, 0xb2, 0x48, 0x1d,
+ 0x0d, 0xb1, 0x17, 0x03, 0x03, 0x00, 0x25, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc0,
+ 0x89, 0x7c, 0x58, 0x6a, 0x9b, 0x00, 0x05, 0x8c,
+ 0x7f, 0x28, 0x54, 0x61, 0x44, 0x10, 0xee, 0x85,
+ 0x26, 0xa8, 0x04, 0xcd, 0xca, 0x85, 0x60, 0xf2,
+ 0xeb, 0x22, 0xbd, 0x9e, 0x15, 0x03, 0x03, 0x00,
+ 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x10, 0xe4, 0xe5, 0xf9, 0x85, 0xe3, 0xb0,
+ 0xec, 0x84, 0x29, 0x91, 0x05, 0x7d, 0x86, 0xe3,
+ 0x97, 0xeb, 0xb2,
+ },
+}
diff --git a/libgo/go/crypto/tls/key_agreement.go b/libgo/go/crypto/tls/key_agreement.go
index b6e73fe293b..7e820c1e7e9 100644
--- a/libgo/go/crypto/tls/key_agreement.go
+++ b/libgo/go/crypto/tls/key_agreement.go
@@ -6,11 +6,14 @@ package tls
import (
"crypto"
+ "crypto/ecdsa"
"crypto/elliptic"
"crypto/md5"
"crypto/rsa"
"crypto/sha1"
+ "crypto/sha256"
"crypto/x509"
+ "encoding/asn1"
"errors"
"io"
"math/big"
@@ -36,7 +39,7 @@ func (ka rsaKeyAgreement) processClientKeyExchange(config *Config, cert *Certifi
}
ciphertext := ckx.ciphertext
- if version != versionSSL30 {
+ if version != VersionSSL30 {
ciphertextLen := int(ckx.ciphertext[0])<<8 | int(ckx.ciphertext[1])
if ciphertextLen != len(ckx.ciphertext)-2 {
return nil, errors.New("bad ClientKeyExchange")
@@ -82,34 +85,94 @@ func (ka rsaKeyAgreement) generateClientKeyExchange(config *Config, clientHello
return preMasterSecret, ckx, nil
}
+// sha1Hash calculates a SHA1 hash over the given byte slices.
+func sha1Hash(slices [][]byte) []byte {
+ hsha1 := sha1.New()
+ for _, slice := range slices {
+ hsha1.Write(slice)
+ }
+ return hsha1.Sum(nil)
+}
+
// md5SHA1Hash implements TLS 1.0's hybrid hash function which consists of the
// concatenation of an MD5 and SHA1 hash.
-func md5SHA1Hash(slices ...[]byte) []byte {
+func md5SHA1Hash(slices [][]byte) []byte {
md5sha1 := make([]byte, md5.Size+sha1.Size)
hmd5 := md5.New()
for _, slice := range slices {
hmd5.Write(slice)
}
copy(md5sha1, hmd5.Sum(nil))
+ copy(md5sha1[md5.Size:], sha1Hash(slices))
+ return md5sha1
+}
- hsha1 := sha1.New()
+// sha256Hash implements TLS 1.2's hash function.
+func sha256Hash(slices [][]byte) []byte {
+ h := sha256.New()
for _, slice := range slices {
- hsha1.Write(slice)
+ h.Write(slice)
}
- copy(md5sha1[md5.Size:], hsha1.Sum(nil))
- return md5sha1
+ return h.Sum(nil)
+}
+
+// hashForServerKeyExchange hashes the given slices and returns their digest
+// and the identifier of the hash function used. The hashFunc argument is only
+// used for >= TLS 1.2 and precisely identifies the hash function to use.
+func hashForServerKeyExchange(sigType, hashFunc uint8, version uint16, slices ...[]byte) ([]byte, crypto.Hash, error) {
+ if version >= VersionTLS12 {
+ switch hashFunc {
+ case hashSHA256:
+ return sha256Hash(slices), crypto.SHA256, nil
+ case hashSHA1:
+ return sha1Hash(slices), crypto.SHA1, nil
+ default:
+ return nil, crypto.Hash(0), errors.New("tls: unknown hash function used by peer")
+ }
+ }
+ if sigType == signatureECDSA {
+ return sha1Hash(slices), crypto.SHA1, nil
+ }
+ return md5SHA1Hash(slices), crypto.MD5SHA1, nil
+}
+
+// pickTLS12HashForSignature returns a TLS 1.2 hash identifier for signing a
+// ServerKeyExchange given the signature type being used and the client's
+// advertized list of supported signature and hash combinations.
+func pickTLS12HashForSignature(sigType uint8, clientSignatureAndHashes []signatureAndHash) (uint8, error) {
+ if len(clientSignatureAndHashes) == 0 {
+ // If the client didn't specify any signature_algorithms
+ // extension then we can assume that it supports SHA1. See
+ // http://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
+ return hashSHA1, nil
+ }
+
+ for _, sigAndHash := range clientSignatureAndHashes {
+ if sigAndHash.signature != sigType {
+ continue
+ }
+ switch sigAndHash.hash {
+ case hashSHA1, hashSHA256:
+ return sigAndHash.hash, nil
+ }
+ }
+
+ return 0, errors.New("tls: client doesn't support any common hash functions")
}
// ecdheRSAKeyAgreement implements a TLS key agreement where the server
// generates a ephemeral EC public/private key pair and signs it. The
-// pre-master secret is then calculated using ECDH.
-type ecdheRSAKeyAgreement struct {
+// pre-master secret is then calculated using ECDH. The signature may
+// either be ECDSA or RSA.
+type ecdheKeyAgreement struct {
+ version uint16
+ sigType uint8
privateKey []byte
curve elliptic.Curve
x, y *big.Int
}
-func (ka *ecdheRSAKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
+func (ka *ecdheKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
var curveid uint16
Curve:
@@ -150,16 +213,55 @@ Curve:
serverECDHParams[3] = byte(len(ecdhePublic))
copy(serverECDHParams[4:], ecdhePublic)
- md5sha1 := md5SHA1Hash(clientHello.random, hello.random, serverECDHParams)
- sig, err := rsa.SignPKCS1v15(config.rand(), cert.PrivateKey.(*rsa.PrivateKey), crypto.MD5SHA1, md5sha1)
+ var tls12HashId uint8
+ if ka.version >= VersionTLS12 {
+ if tls12HashId, err = pickTLS12HashForSignature(ka.sigType, clientHello.signatureAndHashes); err != nil {
+ return nil, err
+ }
+ }
+
+ digest, hashFunc, err := hashForServerKeyExchange(ka.sigType, tls12HashId, ka.version, clientHello.random, hello.random, serverECDHParams)
if err != nil {
- return nil, errors.New("failed to sign ECDHE parameters: " + err.Error())
+ return nil, err
+ }
+ var sig []byte
+ switch ka.sigType {
+ case signatureECDSA:
+ privKey, ok := cert.PrivateKey.(*ecdsa.PrivateKey)
+ if !ok {
+ return nil, errors.New("ECDHE ECDSA requires an ECDSA server private key")
+ }
+ r, s, err := ecdsa.Sign(config.rand(), privKey, digest)
+ if err != nil {
+ return nil, errors.New("failed to sign ECDHE parameters: " + err.Error())
+ }
+ sig, err = asn1.Marshal(ecdsaSignature{r, s})
+ case signatureRSA:
+ privKey, ok := cert.PrivateKey.(*rsa.PrivateKey)
+ if !ok {
+ return nil, errors.New("ECDHE RSA requires a RSA server private key")
+ }
+ sig, err = rsa.SignPKCS1v15(config.rand(), privKey, hashFunc, digest)
+ if err != nil {
+ return nil, errors.New("failed to sign ECDHE parameters: " + err.Error())
+ }
+ default:
+ return nil, errors.New("unknown ECDHE signature algorithm")
}
skx := new(serverKeyExchangeMsg)
- skx.key = make([]byte, len(serverECDHParams)+2+len(sig))
+ sigAndHashLen := 0
+ if ka.version >= VersionTLS12 {
+ sigAndHashLen = 2
+ }
+ skx.key = make([]byte, len(serverECDHParams)+sigAndHashLen+2+len(sig))
copy(skx.key, serverECDHParams)
k := skx.key[len(serverECDHParams):]
+ if ka.version >= VersionTLS12 {
+ k[0] = tls12HashId
+ k[1] = ka.sigType
+ k = k[2:]
+ }
k[0] = byte(len(sig) >> 8)
k[1] = byte(len(sig))
copy(k[2:], sig)
@@ -167,7 +269,7 @@ Curve:
return skx, nil
}
-func (ka *ecdheRSAKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
+func (ka *ecdheKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
if len(ckx.ciphertext) == 0 || int(ckx.ciphertext[0]) != len(ckx.ciphertext)-1 {
return nil, errors.New("bad ClientKeyExchange")
}
@@ -185,7 +287,7 @@ func (ka *ecdheRSAKeyAgreement) processClientKeyExchange(config *Config, cert *C
var errServerKeyExchange = errors.New("invalid ServerKeyExchange")
-func (ka *ecdheRSAKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
+func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
if len(skx.key) < 4 {
return errServerKeyExchange
}
@@ -219,17 +321,62 @@ func (ka *ecdheRSAKeyAgreement) processServerKeyExchange(config *Config, clientH
if len(sig) < 2 {
return errServerKeyExchange
}
+
+ var tls12HashId uint8
+ if ka.version >= VersionTLS12 {
+ // handle SignatureAndHashAlgorithm
+ var sigAndHash []uint8
+ sigAndHash, sig = sig[:2], sig[2:]
+ if sigAndHash[1] != ka.sigType {
+ return errServerKeyExchange
+ }
+ tls12HashId = sigAndHash[0]
+ if len(sig) < 2 {
+ return errServerKeyExchange
+ }
+ }
sigLen := int(sig[0])<<8 | int(sig[1])
if sigLen+2 != len(sig) {
return errServerKeyExchange
}
sig = sig[2:]
- md5sha1 := md5SHA1Hash(clientHello.random, serverHello.random, serverECDHParams)
- return rsa.VerifyPKCS1v15(cert.PublicKey.(*rsa.PublicKey), crypto.MD5SHA1, md5sha1, sig)
+ digest, hashFunc, err := hashForServerKeyExchange(ka.sigType, tls12HashId, ka.version, clientHello.random, serverHello.random, serverECDHParams)
+ if err != nil {
+ return err
+ }
+ switch ka.sigType {
+ case signatureECDSA:
+ pubKey, ok := cert.PublicKey.(*ecdsa.PublicKey)
+ if !ok {
+ return errors.New("ECDHE ECDSA requires a ECDSA server public key")
+ }
+ ecdsaSig := new(ecdsaSignature)
+ if _, err := asn1.Unmarshal(sig, ecdsaSig); err != nil {
+ return err
+ }
+ if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 {
+ return errors.New("ECDSA signature contained zero or negative values")
+ }
+ if !ecdsa.Verify(pubKey, digest, ecdsaSig.R, ecdsaSig.S) {
+ return errors.New("ECDSA verification failure")
+ }
+ case signatureRSA:
+ pubKey, ok := cert.PublicKey.(*rsa.PublicKey)
+ if !ok {
+ return errors.New("ECDHE RSA requires a RSA server public key")
+ }
+ if err := rsa.VerifyPKCS1v15(pubKey, hashFunc, digest, sig); err != nil {
+ return err
+ }
+ default:
+ return errors.New("unknown ECDHE signature algorithm")
+ }
+
+ return nil
}
-func (ka *ecdheRSAKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
+func (ka *ecdheKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
if ka.curve == nil {
return nil, nil, errors.New("missing ServerKeyExchange message")
}
diff --git a/libgo/go/crypto/tls/prf.go b/libgo/go/crypto/tls/prf.go
index df1eaad0586..fb8b3ab4d1e 100644
--- a/libgo/go/crypto/tls/prf.go
+++ b/libgo/go/crypto/tls/prf.go
@@ -5,9 +5,11 @@
package tls
import (
+ "crypto"
"crypto/hmac"
"crypto/md5"
"crypto/sha1"
+ "crypto/sha256"
"hash"
)
@@ -43,8 +45,8 @@ func pHash(result, secret, seed []byte, hash func() hash.Hash) {
}
}
-// pRF10 implements the TLS 1.0 pseudo-random function, as defined in RFC 2246, section 5.
-func pRF10(result, secret, label, seed []byte) {
+// prf10 implements the TLS 1.0 pseudo-random function, as defined in RFC 2246, section 5.
+func prf10(result, secret, label, seed []byte) {
hashSHA1 := sha1.New
hashMD5 := md5.New
@@ -62,9 +64,18 @@ func pRF10(result, secret, label, seed []byte) {
}
}
-// pRF30 implements the SSL 3.0 pseudo-random function, as defined in
+// prf12 implements the TLS 1.2 pseudo-random function, as defined in RFC 5246, section 5.
+func prf12(result, secret, label, seed []byte) {
+ labelAndSeed := make([]byte, len(label)+len(seed))
+ copy(labelAndSeed, label)
+ copy(labelAndSeed[len(label):], seed)
+
+ pHash(result, secret, labelAndSeed, sha256.New)
+}
+
+// prf30 implements the SSL 3.0 pseudo-random function, as defined in
// www.mozilla.org/projects/security/pki/nss/ssl/draft302.txt section 6.
-func pRF30(result, secret, label, seed []byte) {
+func prf30(result, secret, label, seed []byte) {
hashSHA1 := sha1.New()
hashMD5 := md5.New()
@@ -106,19 +117,27 @@ var keyExpansionLabel = []byte("key expansion")
var clientFinishedLabel = []byte("client finished")
var serverFinishedLabel = []byte("server finished")
+func prfForVersion(version uint16) func(result, secret, label, seed []byte) {
+ switch version {
+ case VersionSSL30:
+ return prf30
+ case VersionTLS10, VersionTLS11:
+ return prf10
+ case VersionTLS12:
+ return prf12
+ default:
+ panic("unknown version")
+ }
+}
+
// masterFromPreMasterSecret generates the master secret from the pre-master
// secret. See http://tools.ietf.org/html/rfc5246#section-8.1
func masterFromPreMasterSecret(version uint16, preMasterSecret, clientRandom, serverRandom []byte) []byte {
- prf := pRF10
- if version == versionSSL30 {
- prf = pRF30
- }
-
var seed [tlsRandomLength * 2]byte
copy(seed[0:len(clientRandom)], clientRandom)
copy(seed[len(clientRandom):], serverRandom)
masterSecret := make([]byte, masterSecretLength)
- prf(masterSecret, preMasterSecret, masterSecretLabel, seed[0:])
+ prfForVersion(version)(masterSecret, preMasterSecret, masterSecretLabel, seed[0:])
return masterSecret
}
@@ -126,18 +145,13 @@ func masterFromPreMasterSecret(version uint16, preMasterSecret, clientRandom, se
// secret, given the lengths of the MAC key, cipher key and IV, as defined in
// RFC 2246, section 6.3.
func keysFromMasterSecret(version uint16, masterSecret, clientRandom, serverRandom []byte, macLen, keyLen, ivLen int) (clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV []byte) {
- prf := pRF10
- if version == versionSSL30 {
- prf = pRF30
- }
-
var seed [tlsRandomLength * 2]byte
copy(seed[0:len(clientRandom)], serverRandom)
copy(seed[len(serverRandom):], clientRandom)
n := 2*macLen + 2*keyLen + 2*ivLen
keyMaterial := make([]byte, n)
- prf(keyMaterial, masterSecret, keyExpansionLabel, seed[0:])
+ prfForVersion(version)(keyMaterial, masterSecret, keyExpansionLabel, seed[0:])
clientMAC = keyMaterial[:macLen]
keyMaterial = keyMaterial[macLen:]
serverMAC = keyMaterial[:macLen]
@@ -153,37 +167,34 @@ func keysFromMasterSecret(version uint16, masterSecret, clientRandom, serverRand
}
func newFinishedHash(version uint16) finishedHash {
- return finishedHash{md5.New(), sha1.New(), md5.New(), sha1.New(), version}
+ if version >= VersionTLS12 {
+ return finishedHash{sha256.New(), sha256.New(), nil, nil, version}
+ }
+ return finishedHash{sha1.New(), sha1.New(), md5.New(), md5.New(), version}
}
// A finishedHash calculates the hash of a set of handshake messages suitable
// for including in a Finished message.
type finishedHash struct {
- clientMD5 hash.Hash
- clientSHA1 hash.Hash
- serverMD5 hash.Hash
- serverSHA1 hash.Hash
- version uint16
+ client hash.Hash
+ server hash.Hash
+
+ // Prior to TLS 1.2, an additional MD5 hash is required.
+ clientMD5 hash.Hash
+ serverMD5 hash.Hash
+
+ version uint16
}
func (h finishedHash) Write(msg []byte) (n int, err error) {
- h.clientMD5.Write(msg)
- h.clientSHA1.Write(msg)
- h.serverMD5.Write(msg)
- h.serverSHA1.Write(msg)
- return len(msg), nil
-}
+ h.client.Write(msg)
+ h.server.Write(msg)
-// finishedSum10 calculates the contents of the verify_data member of a TLSv1
-// Finished message given the MD5 and SHA1 hashes of a set of handshake
-// messages.
-func finishedSum10(md5, sha1, label, masterSecret []byte) []byte {
- seed := make([]byte, len(md5)+len(sha1))
- copy(seed, md5)
- copy(seed[len(md5):], sha1)
- out := make([]byte, finishedVerifyLength)
- pRF10(out, masterSecret, label, seed)
- return out
+ if h.version < VersionTLS12 {
+ h.clientMD5.Write(msg)
+ h.serverMD5.Write(msg)
+ }
+ return len(msg), nil
}
// finishedSum30 calculates the contents of the verify_data member of a SSLv3
@@ -224,23 +235,57 @@ var ssl3ServerFinishedMagic = [4]byte{0x53, 0x52, 0x56, 0x52}
// clientSum returns the contents of the verify_data member of a client's
// Finished message.
func (h finishedHash) clientSum(masterSecret []byte) []byte {
- if h.version == versionSSL30 {
- return finishedSum30(h.clientMD5, h.clientSHA1, masterSecret, ssl3ClientFinishedMagic)
+ if h.version == VersionSSL30 {
+ return finishedSum30(h.clientMD5, h.client, masterSecret, ssl3ClientFinishedMagic)
}
- md5 := h.clientMD5.Sum(nil)
- sha1 := h.clientSHA1.Sum(nil)
- return finishedSum10(md5, sha1, clientFinishedLabel, masterSecret)
+ out := make([]byte, finishedVerifyLength)
+ if h.version >= VersionTLS12 {
+ seed := h.client.Sum(nil)
+ prf12(out, masterSecret, clientFinishedLabel, seed)
+ } else {
+ seed := make([]byte, 0, md5.Size+sha1.Size)
+ seed = h.clientMD5.Sum(seed)
+ seed = h.client.Sum(seed)
+ prf10(out, masterSecret, clientFinishedLabel, seed)
+ }
+ return out
}
// serverSum returns the contents of the verify_data member of a server's
// Finished message.
func (h finishedHash) serverSum(masterSecret []byte) []byte {
- if h.version == versionSSL30 {
- return finishedSum30(h.serverMD5, h.serverSHA1, masterSecret, ssl3ServerFinishedMagic)
+ if h.version == VersionSSL30 {
+ return finishedSum30(h.serverMD5, h.server, masterSecret, ssl3ServerFinishedMagic)
+ }
+
+ out := make([]byte, finishedVerifyLength)
+ if h.version >= VersionTLS12 {
+ seed := h.server.Sum(nil)
+ prf12(out, masterSecret, serverFinishedLabel, seed)
+ } else {
+ seed := make([]byte, 0, md5.Size+sha1.Size)
+ seed = h.serverMD5.Sum(seed)
+ seed = h.server.Sum(seed)
+ prf10(out, masterSecret, serverFinishedLabel, seed)
+ }
+ return out
+}
+
+// hashForClientCertificate returns a digest, hash function, and TLS 1.2 hash
+// id suitable for signing by a TLS client certificate.
+func (h finishedHash) hashForClientCertificate(sigType uint8) ([]byte, crypto.Hash, uint8) {
+ if h.version >= VersionTLS12 {
+ digest := h.server.Sum(nil)
+ return digest, crypto.SHA256, hashSHA256
+ }
+ if sigType == signatureECDSA {
+ digest := h.server.Sum(nil)
+ return digest, crypto.SHA1, hashSHA1
}
- md5 := h.serverMD5.Sum(nil)
- sha1 := h.serverSHA1.Sum(nil)
- return finishedSum10(md5, sha1, serverFinishedLabel, masterSecret)
+ digest := make([]byte, 0, 36)
+ digest = h.serverMD5.Sum(digest)
+ digest = h.server.Sum(digest)
+ return digest, crypto.MD5SHA1, 0 /* not specified in TLS 1.2. */
}
diff --git a/libgo/go/crypto/tls/prf_test.go b/libgo/go/crypto/tls/prf_test.go
index 773a2b2ffc8..a9b6c9e4c79 100644
--- a/libgo/go/crypto/tls/prf_test.go
+++ b/libgo/go/crypto/tls/prf_test.go
@@ -72,7 +72,7 @@ func TestKeysFromPreMasterSecret(t *testing.T) {
// These test vectors were generated from GnuTLS using `gnutls-cli --insecure -d 9 `
var testKeysFromTests = []testKeysFromTest{
{
- versionTLS10,
+ VersionTLS10,
"0302cac83ad4b1db3b9ab49ad05957de2a504a634a386fc600889321e1a971f57479466830ac3e6f468e87f5385fa0c5",
"4ae66303755184a3917fcb44880605fcc53baa01912b22ed94473fc69cebd558",
"4ae663020ec16e6bb5130be918cfcafd4d765979a3136a5d50c593446e4e44db",
@@ -85,7 +85,7 @@ var testKeysFromTests = []testKeysFromTest{
16,
},
{
- versionTLS10,
+ VersionTLS10,
"03023f7527316bc12cbcd69e4b9e8275d62c028f27e65c745cfcddc7ce01bd3570a111378b63848127f1c36e5f9e4890",
"4ae66364b5ea56b20ce4e25555aed2d7e67f42788dd03f3fee4adae0459ab106",
"4ae66363ab815cbf6a248b87d6b556184e945e9b97fbdf247858b0bdafacfa1c",
@@ -98,7 +98,7 @@ var testKeysFromTests = []testKeysFromTest{
16,
},
{
- versionTLS10,
+ VersionTLS10,
"832d515f1d61eebb2be56ba0ef79879efb9b527504abb386fb4310ed5d0e3b1f220d3bb6b455033a2773e6d8bdf951d278a187482b400d45deb88a5d5a6bb7d6a7a1decc04eb9ef0642876cd4a82d374d3b6ff35f0351dc5d411104de431375355addc39bfb1f6329fb163b0bc298d658338930d07d313cd980a7e3d9196cac1",
"4ae663b2ee389c0de147c509d8f18f5052afc4aaf9699efe8cb05ece883d3a5e",
"4ae664d503fd4cff50cfc1fb8fc606580f87b0fcdac9554ba0e01d785bdf278e",
@@ -111,7 +111,7 @@ var testKeysFromTests = []testKeysFromTest{
16,
},
{
- versionSSL30,
+ VersionSSL30,
"832d515f1d61eebb2be56ba0ef79879efb9b527504abb386fb4310ed5d0e3b1f220d3bb6b455033a2773e6d8bdf951d278a187482b400d45deb88a5d5a6bb7d6a7a1decc04eb9ef0642876cd4a82d374d3b6ff35f0351dc5d411104de431375355addc39bfb1f6329fb163b0bc298d658338930d07d313cd980a7e3d9196cac1",
"4ae663b2ee389c0de147c509d8f18f5052afc4aaf9699efe8cb05ece883d3a5e",
"4ae664d503fd4cff50cfc1fb8fc606580f87b0fcdac9554ba0e01d785bdf278e",
diff --git a/libgo/go/crypto/tls/tls.go b/libgo/go/crypto/tls/tls.go
index 9230656d6a4..6c67506fc36 100644
--- a/libgo/go/crypto/tls/tls.go
+++ b/libgo/go/crypto/tls/tls.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Package tls partially implements TLS 1.0, as specified in RFC 2246.
+// Package tls partially implements TLS 1.2, as specified in RFC 5246.
package tls
import (
diff --git a/libgo/go/crypto/x509/cert_pool.go b/libgo/go/crypto/x509/cert_pool.go
index 505f4d4f776..babe94d41c5 100644
--- a/libgo/go/crypto/x509/cert_pool.go
+++ b/libgo/go/crypto/x509/cert_pool.go
@@ -25,9 +25,10 @@ func NewCertPool() *CertPool {
}
// findVerifiedParents attempts to find certificates in s which have signed the
-// given certificate. If no such certificate can be found or the signature
-// doesn't match, it returns nil.
-func (s *CertPool) findVerifiedParents(cert *Certificate) (parents []int) {
+// given certificate. If any candidates were rejected then errCert will be set
+// to one of them, arbitrarily, and err will contain the reason that it was
+// rejected.
+func (s *CertPool) findVerifiedParents(cert *Certificate) (parents []int, errCert *Certificate, err error) {
if s == nil {
return
}
@@ -41,8 +42,10 @@ func (s *CertPool) findVerifiedParents(cert *Certificate) (parents []int) {
}
for _, c := range candidates {
- if cert.CheckSignatureFrom(s.certs[c]) == nil {
+ if err = cert.CheckSignatureFrom(s.certs[c]); err == nil {
parents = append(parents, c)
+ } else {
+ errCert = s.certs[c]
}
}
diff --git a/libgo/go/crypto/x509/pkcs1.go b/libgo/go/crypto/x509/pkcs1.go
index 873d3966eb5..acebe351398 100644
--- a/libgo/go/crypto/x509/pkcs1.go
+++ b/libgo/go/crypto/x509/pkcs1.go
@@ -52,7 +52,7 @@ func ParsePKCS1PrivateKey(der []byte) (key *rsa.PrivateKey, err error) {
}
if priv.N.Sign() <= 0 || priv.D.Sign() <= 0 || priv.P.Sign() <= 0 || priv.Q.Sign() <= 0 {
- return nil, errors.New("private key contains zero or negative value")
+ return nil, errors.New("x509: private key contains zero or negative value")
}
key = new(rsa.PrivateKey)
@@ -67,7 +67,7 @@ func ParsePKCS1PrivateKey(der []byte) (key *rsa.PrivateKey, err error) {
key.Primes[1] = priv.Q
for i, a := range priv.AdditionalPrimes {
if a.Prime.Sign() <= 0 {
- return nil, errors.New("private key contains zero or negative prime")
+ return nil, errors.New("x509: private key contains zero or negative prime")
}
key.Primes[i+2] = a.Prime
// We ignore the other two values because rsa will calculate
diff --git a/libgo/go/crypto/x509/pkcs8.go b/libgo/go/crypto/x509/pkcs8.go
index 8e1585e15cc..ba19989cba1 100644
--- a/libgo/go/crypto/x509/pkcs8.go
+++ b/libgo/go/crypto/x509/pkcs8.go
@@ -32,7 +32,7 @@ func ParsePKCS8PrivateKey(der []byte) (key interface{}, err error) {
case privKey.Algo.Algorithm.Equal(oidPublicKeyRSA):
key, err = ParsePKCS1PrivateKey(privKey.PrivateKey)
if err != nil {
- return nil, errors.New("crypto/x509: failed to parse RSA private key embedded in PKCS#8: " + err.Error())
+ return nil, errors.New("x509: failed to parse RSA private key embedded in PKCS#8: " + err.Error())
}
return key, nil
@@ -44,11 +44,11 @@ func ParsePKCS8PrivateKey(der []byte) (key interface{}, err error) {
}
key, err = parseECPrivateKey(namedCurveOID, privKey.PrivateKey)
if err != nil {
- return nil, errors.New("crypto/x509: failed to parse EC private key embedded in PKCS#8: " + err.Error())
+ return nil, errors.New("x509: failed to parse EC private key embedded in PKCS#8: " + err.Error())
}
return key, nil
default:
- return nil, fmt.Errorf("crypto/x509: PKCS#8 wrapping contained private key with unknown algorithm: %v", privKey.Algo.Algorithm)
+ return nil, fmt.Errorf("x509: PKCS#8 wrapping contained private key with unknown algorithm: %v", privKey.Algo.Algorithm)
}
}
diff --git a/libgo/go/crypto/x509/pkix/pkix.go b/libgo/go/crypto/x509/pkix/pkix.go
index 738659011fa..5034946f710 100644
--- a/libgo/go/crypto/x509/pkix/pkix.go
+++ b/libgo/go/crypto/x509/pkix/pkix.go
@@ -144,7 +144,7 @@ type CertificateList struct {
SignatureValue asn1.BitString
}
-// HasExpired returns true iff now is past the expiry time of certList.
+// HasExpired reports whether now is past the expiry time of certList.
func (certList *CertificateList) HasExpired(now time.Time) bool {
return now.After(certList.TBSCertList.NextUpdate)
}
diff --git a/libgo/go/crypto/x509/root_unix.go b/libgo/go/crypto/x509/root_unix.go
index 1b25a94d08d..324f855b135 100644
--- a/libgo/go/crypto/x509/root_unix.go
+++ b/libgo/go/crypto/x509/root_unix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build freebsd linux openbsd netbsd
+// +build dragonfly freebsd linux openbsd netbsd
package x509
@@ -10,11 +10,11 @@ import "io/ioutil"
// Possible certificate files; stop after finding one.
var certFiles = []string{
- "/etc/ssl/certs/ca-certificates.crt", // Linux etc
+ "/etc/ssl/certs/ca-certificates.crt", // Debian/Ubuntu/Gentoo etc.
"/etc/pki/tls/certs/ca-bundle.crt", // Fedora/RHEL
"/etc/ssl/ca-bundle.pem", // OpenSUSE
"/etc/ssl/cert.pem", // OpenBSD
- "/usr/local/share/certs/ca-root-nss.crt", // FreeBSD
+ "/usr/local/share/certs/ca-root-nss.crt", // FreeBSD/DragonFly
}
func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) {
diff --git a/libgo/go/crypto/x509/root_windows.go b/libgo/go/crypto/x509/root_windows.go
index e8f70a49da8..81018b78fe6 100644
--- a/libgo/go/crypto/x509/root_windows.go
+++ b/libgo/go/crypto/x509/root_windows.go
@@ -89,7 +89,7 @@ func checkChainTrustStatus(c *Certificate, chainCtx *syscall.CertChainContext) e
case syscall.CERT_TRUST_IS_NOT_TIME_VALID:
return CertificateInvalidError{c, Expired}
default:
- return UnknownAuthorityError{c}
+ return UnknownAuthorityError{c, nil, nil}
}
}
return nil
@@ -129,9 +129,9 @@ func checkChainSSLServerPolicy(c *Certificate, chainCtx *syscall.CertChainContex
case syscall.CERT_E_CN_NO_MATCH:
return HostnameError{c, opts.DNSName}
case syscall.CERT_E_UNTRUSTEDROOT:
- return UnknownAuthorityError{c}
+ return UnknownAuthorityError{c, nil, nil}
default:
- return UnknownAuthorityError{c}
+ return UnknownAuthorityError{c, nil, nil}
}
}
diff --git a/libgo/go/crypto/x509/sec1.go b/libgo/go/crypto/x509/sec1.go
index 8a2840fbef5..7de66754eeb 100644
--- a/libgo/go/crypto/x509/sec1.go
+++ b/libgo/go/crypto/x509/sec1.go
@@ -33,6 +33,20 @@ func ParseECPrivateKey(der []byte) (key *ecdsa.PrivateKey, err error) {
return parseECPrivateKey(nil, der)
}
+// MarshalECPrivateKey marshals an EC private key into ASN.1, DER format.
+func MarshalECPrivateKey(key *ecdsa.PrivateKey) ([]byte, error) {
+ oid, ok := oidFromNamedCurve(key.Curve)
+ if !ok {
+ return nil, errors.New("x509: unknown elliptic curve")
+ }
+ return asn1.Marshal(ecPrivateKey{
+ Version: 1,
+ PrivateKey: key.D.Bytes(),
+ NamedCurveOID: oid,
+ PublicKey: asn1.BitString{Bytes: elliptic.Marshal(key.Curve, key.X, key.Y)},
+ })
+}
+
// parseECPrivateKey parses an ASN.1 Elliptic Curve Private Key Structure.
// The OID for the named curve may be provided from another source (such as
// the PKCS8 container) - if it is provided then use this instead of the OID
@@ -40,10 +54,10 @@ func ParseECPrivateKey(der []byte) (key *ecdsa.PrivateKey, err error) {
func parseECPrivateKey(namedCurveOID *asn1.ObjectIdentifier, der []byte) (key *ecdsa.PrivateKey, err error) {
var privKey ecPrivateKey
if _, err := asn1.Unmarshal(der, &privKey); err != nil {
- return nil, errors.New("crypto/x509: failed to parse EC private key: " + err.Error())
+ return nil, errors.New("x509: failed to parse EC private key: " + err.Error())
}
if privKey.Version != ecPrivKeyVersion {
- return nil, fmt.Errorf("crypto/x509: unknown EC private key version %d", privKey.Version)
+ return nil, fmt.Errorf("x509: unknown EC private key version %d", privKey.Version)
}
var curve elliptic.Curve
@@ -53,12 +67,12 @@ func parseECPrivateKey(namedCurveOID *asn1.ObjectIdentifier, der []byte) (key *e
curve = namedCurveFromOID(privKey.NamedCurveOID)
}
if curve == nil {
- return nil, errors.New("crypto/x509: unknown elliptic curve")
+ return nil, errors.New("x509: unknown elliptic curve")
}
k := new(big.Int).SetBytes(privKey.PrivateKey)
if k.Cmp(curve.Params().N) >= 0 {
- return nil, errors.New("crypto/x509: invalid elliptic curve private key value")
+ return nil, errors.New("x509: invalid elliptic curve private key value")
}
priv := new(ecdsa.PrivateKey)
priv.Curve = curve
diff --git a/libgo/go/crypto/x509/sec1_test.go b/libgo/go/crypto/x509/sec1_test.go
index 7135699d283..95f18e77de0 100644
--- a/libgo/go/crypto/x509/sec1_test.go
+++ b/libgo/go/crypto/x509/sec1_test.go
@@ -5,6 +5,7 @@
package x509
import (
+ "bytes"
"encoding/hex"
"testing"
)
@@ -15,8 +16,15 @@ var ecPrivateKeyHex = `3081a40201010430bdb9839c08ee793d1157886a7a758a3c8b2a17a4d
func TestParseECPrivateKey(t *testing.T) {
derBytes, _ := hex.DecodeString(ecPrivateKeyHex)
- _, err := ParseECPrivateKey(derBytes)
+ key, err := ParseECPrivateKey(derBytes)
if err != nil {
t.Errorf("failed to decode EC private key: %s", err)
}
+ serialized, err := MarshalECPrivateKey(key)
+ if err != nil {
+ t.Fatalf("failed to encode EC private key: %s", err)
+ }
+ if !bytes.Equal(serialized, derBytes) {
+ t.Fatalf("serialized key differs: got %x, want %x", serialized, derBytes)
+ }
}
diff --git a/libgo/go/crypto/x509/verify.go b/libgo/go/crypto/x509/verify.go
index b29ddbc80f0..8327463ca86 100644
--- a/libgo/go/crypto/x509/verify.go
+++ b/libgo/go/crypto/x509/verify.go
@@ -5,6 +5,7 @@
package x509
import (
+ "fmt"
"net"
"runtime"
"strings"
@@ -91,10 +92,27 @@ func (h HostnameError) Error() string {
// UnknownAuthorityError results when the certificate issuer is unknown
type UnknownAuthorityError struct {
cert *Certificate
+ // hintErr contains an error that may be helpful in determining why an
+ // authority wasn't found.
+ hintErr error
+ // hintCert contains a possible authority certificate that was rejected
+ // because of the error in hintErr.
+ hintCert *Certificate
}
func (e UnknownAuthorityError) Error() string {
- return "x509: certificate signed by unknown authority"
+ s := "x509: certificate signed by unknown authority"
+ if e.hintErr != nil {
+ certName := e.hintCert.Subject.CommonName
+ if len(certName) == 0 {
+ if len(e.hintCert.Subject.Organization) > 0 {
+ certName = e.hintCert.Subject.Organization[0]
+ }
+ certName = "serial:" + e.hintCert.SerialNumber.String()
+ }
+ s += fmt.Sprintf(" (possibly because of %q while trying to verify candidate authority certificate %q)", e.hintErr, certName)
+ }
+ return s
}
// SystemRootsError results when we fail to load the system root certificates.
@@ -136,14 +154,18 @@ func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *V
}
if len(c.PermittedDNSDomains) > 0 {
+ ok := false
for _, domain := range c.PermittedDNSDomains {
if opts.DNSName == domain ||
(strings.HasSuffix(opts.DNSName, domain) &&
len(opts.DNSName) >= 1+len(domain) &&
opts.DNSName[len(opts.DNSName)-len(domain)-1] == '.') {
- continue
+ ok = true
+ break
}
+ }
+ if !ok {
return CertificateInvalidError{c, CANotAuthorizedForThisName}
}
}
@@ -249,7 +271,8 @@ func appendToFreshChain(chain []*Certificate, cert *Certificate) []*Certificate
}
func (c *Certificate) buildChains(cache map[int][][]*Certificate, currentChain []*Certificate, opts *VerifyOptions) (chains [][]*Certificate, err error) {
- for _, rootNum := range opts.Roots.findVerifiedParents(c) {
+ possibleRoots, failedRoot, rootErr := opts.Roots.findVerifiedParents(c)
+ for _, rootNum := range possibleRoots {
root := opts.Roots.certs[rootNum]
err = root.isValid(rootCertificate, currentChain, opts)
if err != nil {
@@ -258,8 +281,9 @@ func (c *Certificate) buildChains(cache map[int][][]*Certificate, currentChain [
chains = append(chains, appendToFreshChain(currentChain, root))
}
+ possibleIntermediates, failedIntermediate, intermediateErr := opts.Intermediates.findVerifiedParents(c)
nextIntermediate:
- for _, intermediateNum := range opts.Intermediates.findVerifiedParents(c) {
+ for _, intermediateNum := range possibleIntermediates {
intermediate := opts.Intermediates.certs[intermediateNum]
for _, cert := range currentChain {
if cert == intermediate {
@@ -284,7 +308,13 @@ nextIntermediate:
}
if len(chains) == 0 && err == nil {
- err = UnknownAuthorityError{c}
+ hintErr := rootErr
+ hintCert := failedRoot
+ if hintErr == nil {
+ hintErr = intermediateErr
+ hintCert = failedIntermediate
+ }
+ err = UnknownAuthorityError{c, hintErr, hintCert}
}
return
diff --git a/libgo/go/crypto/x509/verify_test.go b/libgo/go/crypto/x509/verify_test.go
index 5103ed814aa..ba6c13d4510 100644
--- a/libgo/go/crypto/x509/verify_test.go
+++ b/libgo/go/crypto/x509/verify_test.go
@@ -127,6 +127,18 @@ var verifyTests = []verifyTest{
},
},
{
+ leaf: googleLeafWithInvalidHash,
+ intermediates: []string{thawteIntermediate},
+ roots: []string{verisignRoot},
+ currentTime: 1302726541,
+ dnsName: "www.google.com",
+
+ // The specific error message may not occur when using system
+ // verification.
+ systemSkip: true,
+ errorCallback: expectHashError,
+ },
+ {
// The default configuration should reject an S/MIME chain.
leaf: smimeLeaf,
roots: []string{smimeIntermediate},
@@ -171,6 +183,24 @@ var verifyTests = []verifyTest{
{"mega.co.nz", "EssentialSSL CA", "COMODO Certification Authority"},
},
},
+ {
+ // Check that a name constrained intermediate works even when
+ // it lists multiple constraints.
+ leaf: nameConstraintsLeaf,
+ intermediates: []string{nameConstraintsIntermediate1, nameConstraintsIntermediate2},
+ roots: []string{globalSignRoot},
+ currentTime: 1382387896,
+ dnsName: "secure.iddl.vt.edu",
+
+ expectedChains: [][]string{
+ {
+ "Technology-enhanced Learning and Online Strategies",
+ "Virginia Tech Global Qualified Server CA",
+ "Trusted Root CA G2",
+ "GlobalSign Root CA",
+ },
+ },
+ },
}
func expectHostnameError(t *testing.T, i int, err error) (ok bool) {
@@ -213,6 +243,18 @@ func expectSystemRootsError(t *testing.T, i int, err error) bool {
return true
}
+func expectHashError(t *testing.T, i int, err error) bool {
+ if err == nil {
+ t.Errorf("#%d: no error resulted from invalid hash", i)
+ return false
+ }
+ if expected := "algorithm unimplemented"; !strings.Contains(err.Error(), expected) {
+ t.Errorf("#%d: error resulting from invalid hash didn't contain '%s', rather it was: %s", i, expected, err)
+ return false
+ }
+ return true
+}
+
func certificateFromPEM(pemBytes string) (*Certificate, error) {
block, _ := pem.Decode([]byte(pemBytes))
if block == nil {
@@ -400,6 +442,28 @@ u2ONgJd8IyAPkU0Wueru9G2Jysa9zCRo1kNbzipYvzwY4OA8Ys+WAi0oR1A04Se6
z5nRUP8pJcA2NhUzUnC+MY+f6H/nEQyNv4SgQhqAibAxWEEHXw==
-----END CERTIFICATE-----`
+// googleLeafWithInvalidHash is the same as googleLeaf, but the signature
+// algorithm in the certificate contains a nonsense OID.
+const googleLeafWithInvalidHash = `-----BEGIN CERTIFICATE-----
+MIIDITCCAoqgAwIBAgIQL9+89q6RUm0PmqPfQDQ+mjANBgkqhkiG9w0BATIFADBM
+MQswCQYDVQQGEwJaQTElMCMGA1UEChMcVGhhd3RlIENvbnN1bHRpbmcgKFB0eSkg
+THRkLjEWMBQGA1UEAxMNVGhhd3RlIFNHQyBDQTAeFw0wOTEyMTgwMDAwMDBaFw0x
+MTEyMTgyMzU5NTlaMGgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlh
+MRYwFAYDVQQHFA1Nb3VudGFpbiBWaWV3MRMwEQYDVQQKFApHb29nbGUgSW5jMRcw
+FQYDVQQDFA53d3cuZ29vZ2xlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
+gYEA6PmGD5D6htffvXImttdEAoN4c9kCKO+IRTn7EOh8rqk41XXGOOsKFQebg+jN
+gtXj9xVoRaELGYW84u+E593y17iYwqG7tcFR39SDAqc9BkJb4SLD3muFXxzW2k6L
+05vuuWciKh0R73mkszeK9P4Y/bz5RiNQl/Os/CRGK1w7t0UCAwEAAaOB5zCB5DAM
+BgNVHRMBAf8EAjAAMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwudGhhd3Rl
+LmNvbS9UaGF3dGVTR0NDQS5jcmwwKAYDVR0lBCEwHwYIKwYBBQUHAwEGCCsGAQUF
+BwMCBglghkgBhvhCBAEwcgYIKwYBBQUHAQEEZjBkMCIGCCsGAQUFBzABhhZodHRw
+Oi8vb2NzcC50aGF3dGUuY29tMD4GCCsGAQUFBzAChjJodHRwOi8vd3d3LnRoYXd0
+ZS5jb20vcmVwb3NpdG9yeS9UaGF3dGVfU0dDX0NBLmNydDANBgkqhkiG9w0BAVAF
+AAOBgQCfQ89bxFApsb/isJr/aiEdLRLDLE5a+RLizrmCUi3nHX4adpaQedEkUjh5
+u2ONgJd8IyAPkU0Wueru9G2Jysa9zCRo1kNbzipYvzwY4OA8Ys+WAi0oR1A04Se6
+z5nRUP8pJcA2NhUzUnC+MY+f6H/nEQyNv4SgQhqAibAxWEEHXw==
+-----END CERTIFICATE-----`
+
const dnssecExpLeaf = `-----BEGIN CERTIFICATE-----
MIIGzTCCBbWgAwIBAgIDAdD6MA0GCSqGSIb3DQEBBQUAMIGMMQswCQYDVQQGEwJJ
TDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0
@@ -522,6 +586,50 @@ um0ABj6y6koQOdjQK/W/7HW/lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkySh
NOsF/5oirpt9P/FlUQqmMGqz9IgcgA38corog14=
-----END CERTIFICATE-----`
+const startComRootSHA256 = `-----BEGIN CERTIFICATE-----
+MIIHhzCCBW+gAwIBAgIBLTANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJJTDEW
+MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg
+Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh
+dGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0NjM3WhcNMzYwOTE3MTk0NjM2WjB9
+MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMi
+U2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3Rh
+cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA
+A4ICDwAwggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZk
+pMyONvg45iPwbm2xPN1yo4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rf
+OQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/C
+Ji/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/deMotHweXMAEtcnn6RtYT
+Kqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt2PZE4XNi
+HzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMM
+Av+Z6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w
++2OqqGwaVLRcJXrJosmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+
+Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3
+Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVcUjyJthkqcwEKDwOzEmDyei+B
+26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT37uMdBNSSwID
+AQABo4ICEDCCAgwwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD
+VR0OBBYEFE4L7xqkQFulF2mHMMo0aEPQQa7yMB8GA1UdIwQYMBaAFE4L7xqkQFul
+F2mHMMo0aEPQQa7yMIIBWgYDVR0gBIIBUTCCAU0wggFJBgsrBgEEAYG1NwEBATCC
+ATgwLgYIKwYBBQUHAgEWImh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL3BvbGljeS5w
+ZGYwNAYIKwYBBQUHAgEWKGh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL2ludGVybWVk
+aWF0ZS5wZGYwgc8GCCsGAQUFBwICMIHCMCcWIFN0YXJ0IENvbW1lcmNpYWwgKFN0
+YXJ0Q29tKSBMdGQuMAMCAQEagZZMaW1pdGVkIExpYWJpbGl0eSwgcmVhZCB0aGUg
+c2VjdGlvbiAqTGVnYWwgTGltaXRhdGlvbnMqIG9mIHRoZSBTdGFydENvbSBDZXJ0
+aWZpY2F0aW9uIEF1dGhvcml0eSBQb2xpY3kgYXZhaWxhYmxlIGF0IGh0dHA6Ly93
+d3cuc3RhcnRzc2wuY29tL3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgG
+CWCGSAGG+EIBDQQrFilTdGFydENvbSBGcmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1
+dGhvcml0eTANBgkqhkiG9w0BAQsFAAOCAgEAjo/n3JR5fPGFf59Jb2vKXfuM/gTF
+wWLRfUKKvFO3lANmMD+x5wqnUCBVJX92ehQN6wQOQOY+2IirByeDqXWmN3PH/UvS
+Ta0XQMhGvjt/UfzDtgUx3M2FIk5xt/JxXrAaxrqTi3iSSoX4eA+D/i+tLPfkpLst
+0OcNOrg+zvZ49q5HJMqjNTbOx8aHmNrs++myziebiMMEofYLWWivydsQD032ZGNc
+pRJvkrKTlMeIFw6Ttn5ii5B/q06f/ON1FE8qMt9bDeD1e5MNq6HPh+GlBEXoPBKl
+CcWw0bdT82AUuoVpaiF8H3VhFyAXe2w7QSlc4axa0c2Mm+tgHRns9+Ww2vl5GKVF
+P0lDV9LdJNUso/2RjSe15esUBppMeyG7Oq0wBhjA2MFrLH9ZXF2RsXAiV+uKa0hK
+1Q8p7MZAwC+ITGgBF3f0JBlPvfrhsiAhS90a2Cl9qrjeVOwhVYBsHvUwyKMQ5bLm
+KhQxw4UtjJixhlpPiVktucf3HMiKf8CdBUrmQk9io20ppB+Fq9vlgcitKj1MXVuE
+JnHEhV5xJMqlG2zYYdMa4FTbzrqpMrUi9nNBCV24F10OD5mQ1kfabwo6YigUZ4LZ
+8dCAWZvLMdibD4x3TrVoivJs9iQOLWxwxXPR3hTQcY+203sC9uO41Alua551hDnm
+fyWl8kgAwKQB2j8=
+-----END CERTIFICATE-----`
+
const smimeLeaf = `-----BEGIN CERTIFICATE-----
MIIFBjCCA+6gAwIBAgISESFvrjT8XcJTEe6rBlPptILlMA0GCSqGSIb3DQEBBQUA
MFQxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMSowKAYD
@@ -663,3 +771,168 @@ zJVSk/BwJVmcIGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5dd
BA6+C4OmF4O5MBKgxTMVBbkN+8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IB
ZQ==
-----END CERTIFICATE-----`
+
+var nameConstraintsLeaf = `-----BEGIN CERTIFICATE-----
+MIIHMTCCBRmgAwIBAgIIIZaV/3ezOJkwDQYJKoZIhvcNAQEFBQAwgcsxCzAJBgNV
+BAYTAlVTMREwDwYDVQQIEwhWaXJnaW5pYTETMBEGA1UEBxMKQmxhY2tzYnVyZzEj
+MCEGA1UECxMaR2xvYmFsIFF1YWxpZmllZCBTZXJ2ZXIgQ0ExPDA6BgNVBAoTM1Zp
+cmdpbmlhIFBvbHl0ZWNobmljIEluc3RpdHV0ZSBhbmQgU3RhdGUgVW5pdmVyc2l0
+eTExMC8GA1UEAxMoVmlyZ2luaWEgVGVjaCBHbG9iYWwgUXVhbGlmaWVkIFNlcnZl
+ciBDQTAeFw0xMzA5MTkxNDM2NTVaFw0xNTA5MTkxNDM2NTVaMIHNMQswCQYDVQQG
+EwJVUzERMA8GA1UECAwIVmlyZ2luaWExEzARBgNVBAcMCkJsYWNrc2J1cmcxPDA6
+BgNVBAoMM1ZpcmdpbmlhIFBvbHl0ZWNobmljIEluc3RpdHV0ZSBhbmQgU3RhdGUg
+VW5pdmVyc2l0eTE7MDkGA1UECwwyVGVjaG5vbG9neS1lbmhhbmNlZCBMZWFybmlu
+ZyBhbmQgT25saW5lIFN0cmF0ZWdpZXMxGzAZBgNVBAMMEnNlY3VyZS5pZGRsLnZ0
+LmVkdTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKkOyPpsOK/6IuPG
+WnIBlVwlHzeYf+cUlggqkLq0b0+vZbiTXgio9/VCuNQ8opSoss7J7o3ygV9to+9Y
+YwJKVC5WDT/y5JWpQey0CWILymViJnpNSwnxBc8A+Q8w5NUGDd/UhtPx/U8/hqbd
+WPDYj2hbOqyq8UlRhfS5pwtnv6BbCTaY11I6FhCLK7zttISyTuWCf9p9o/ggiipP
+ii/5oh4dkl+r5SfuSp5GPNHlYO8lWqys5NAPoDD4fc/kuflcK7Exx7XJ+Oqu0W0/
+psjEY/tES1ZgDWU/ParcxxFpFmKHbD5DXsfPOObzkVWXIY6tGMutSlE1Froy/Nn0
+OZsAOrcCAwEAAaOCAhMwggIPMIG4BggrBgEFBQcBAQSBqzCBqDBYBggrBgEFBQcw
+AoZMaHR0cDovL3d3dy5wa2kudnQuZWR1L2dsb2JhbHF1YWxpZmllZHNlcnZlci9j
+YWNlcnQvZ2xvYmFscXVhbGlmaWVkc2VydmVyLmNydDBMBggrBgEFBQcwAYZAaHR0
+cDovL3Z0Y2EtcC5lcHJvdi5zZXRpLnZ0LmVkdTo4MDgwL2VqYmNhL3B1YmxpY3dl
+Yi9zdGF0dXMvb2NzcDAdBgNVHQ4EFgQUp7xbO6iHkvtZbPE4jmndmnAbSEcwDAYD
+VR0TAQH/BAIwADAfBgNVHSMEGDAWgBS8YmAn1eM1SBfpS6tFatDIqHdxjDBqBgNV
+HSAEYzBhMA4GDCsGAQQBtGgFAgICATAOBgwrBgEEAbRoBQICAQEwPwYMKwYBBAG0
+aAUCAgMBMC8wLQYIKwYBBQUHAgEWIWh0dHA6Ly93d3cucGtpLnZ0LmVkdS9nbG9i
+YWwvY3BzLzBKBgNVHR8EQzBBMD+gPaA7hjlodHRwOi8vd3d3LnBraS52dC5lZHUv
+Z2xvYmFscXVhbGlmaWVkc2VydmVyL2NybC9jYWNybC5jcmwwDgYDVR0PAQH/BAQD
+AgTwMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAdBgNVHREEFjAUghJz
+ZWN1cmUuaWRkbC52dC5lZHUwDQYJKoZIhvcNAQEFBQADggIBAEgoYo4aUtatY3gI
+OyyKp7QlIOaLbTJZywESHqy+L5EGDdJW2DJV+mcE0LDGvqa2/1Lo+AR1ntsZwfOi
+Y718JwgVVaX/RCd5+QKP25c5/x72xI8hb/L1bgS0ED9b0YAhd7Qm1K1ot82+6mqX
+DW6WiGeDr8Z07MQ3143qQe2rBlq+QI69DYzm2GOqAIAnUIWv7tCyLUm31b4DwmrJ
+TeudVreTKUbBNB1TWRFHEPkWhjjXKZnNGRO11wHXcyBu6YekIvVZ+vmx8ePee4jJ
+3GFOi7lMuWOeq57jTVL7KOKaKLVXBb6gqo5aq+Wwt8RUD5MakrCAEeQZj7DKaFmZ
+oQCO0Pxrsl3InCGvxnGzT+bFVO9nJ/BAMj7hknFdm9Jr6Bg5q33Z+gnf909AD9QF
+ESqUSykaHu2LVdJx2MaCH1CyKnRgMw5tEwE15EXpUjCm24m8FMOYC+rNtf18pgrz
+5D8Jhh+oxK9PjcBYqXNtnioIxiMCYcV0q5d4w4BYFEh71tk7/bYB0R55CsBUVPmp
+timWNOdRd57Tfpk3USaVsumWZAf9MP3wPiC7gb4d5tYEEAG5BuDT8ruFw838wU8G
+1VvAVutSiYBg7k3NYO7AUqZ+Ax4klQX3aM9lgonmJ78Qt94UPtbptrfZ4/lSqEf8
+GBUwDrQNTb+gsXsDkjd5lcYxNx6l
+-----END CERTIFICATE-----`
+
+var nameConstraintsIntermediate1 = `-----BEGIN CERTIFICATE-----
+MIINLjCCDBagAwIBAgIRIqpyf/YoGgvHc8HiDAxAI8owDQYJKoZIhvcNAQEFBQAw
+XDELMAkGA1UEBhMCQkUxFTATBgNVBAsTDFRydXN0ZWQgUm9vdDEZMBcGA1UEChMQ
+R2xvYmFsU2lnbiBudi1zYTEbMBkGA1UEAxMSVHJ1c3RlZCBSb290IENBIEcyMB4X
+DTEyMTIxMzAwMDAwMFoXDTE3MTIxMzAwMDAwMFowgcsxCzAJBgNVBAYTAlVTMREw
+DwYDVQQIEwhWaXJnaW5pYTETMBEGA1UEBxMKQmxhY2tzYnVyZzEjMCEGA1UECxMa
+R2xvYmFsIFF1YWxpZmllZCBTZXJ2ZXIgQ0ExPDA6BgNVBAoTM1ZpcmdpbmlhIFBv
+bHl0ZWNobmljIEluc3RpdHV0ZSBhbmQgU3RhdGUgVW5pdmVyc2l0eTExMC8GA1UE
+AxMoVmlyZ2luaWEgVGVjaCBHbG9iYWwgUXVhbGlmaWVkIFNlcnZlciBDQTCCAiIw
+DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALgIZhEaptBWADBqdJ45ueFGzMXa
+GHnzNxoxR1fQIaaRQNdCg4cw3A4dWKMeEgYLtsp65ai3Xfw62Qaus0+KJ3RhgV+r
+ihqK81NUzkls78fJlADVDI4fCTlothsrE1CTOMiy97jKHai5mVTiWxmcxpmjv7fm
+5Nhc+uHgh2hIz6npryq495mD51ZrUTIaqAQN6Pw/VHfAmR524vgriTOjtp1t4lA9
+pXGWjF/vkhAKFFheOQSQ00rngo2wHgCqMla64UTN0oz70AsCYNZ3jDLx0kOP0YmM
+R3Ih91VA63kLqPXA0R6yxmmhhxLZ5bcyAy1SLjr1N302MIxLM/pSy6aquEnbELhz
+qyp9yGgRyGJay96QH7c4RJY6gtcoPDbldDcHI9nXngdAL4DrZkJ9OkDkJLyqG66W
+ZTF5q4EIs6yMdrywz0x7QP+OXPJrjYpbeFs6tGZCFnWPFfmHCRJF8/unofYrheq+
+9J7Jx3U55S/k57NXbAM1RAJOuMTlfn9Etf9Dpoac9poI4Liav6rBoUQk3N3JWqnV
+HNx/NdCyJ1/6UbKMJUZsStAVglsi6lVPo289HHOE4f7iwl3SyekizVOp01wUin3y
+cnbZB/rXmZbwapSxTTSBf0EIOr9i4EGfnnhCAVA9U5uLrI5OEB69IY8PNX0071s3
+Z2a2fio5c8m3JkdrAgMBAAGjggh5MIIIdTAOBgNVHQ8BAf8EBAMCAQYwTAYDVR0g
+BEUwQzBBBgkrBgEEAaAyATwwNDAyBggrBgEFBQcCARYmaHR0cHM6Ly93d3cuZ2xv
+YmFsc2lnbi5jb20vcmVwb3NpdG9yeS8wEgYDVR0TAQH/BAgwBgEB/wIBADCCBtAG
+A1UdHgSCBscwggbDoIIGvzASghAzZGJsYWNrc2J1cmcub3JnMBiCFmFjY2VsZXJh
+dGV2aXJnaW5pYS5jb20wGIIWYWNjZWxlcmF0ZXZpcmdpbmlhLm9yZzALgglhY3Zj
+cC5vcmcwCYIHYmV2Lm5ldDAJggdiZXYub3JnMAuCCWNsaWdzLm9yZzAMggpjbWl3
+ZWIub3JnMBeCFWVhc3Rlcm5icm9va3Ryb3V0Lm5ldDAXghVlYXN0ZXJuYnJvb2t0
+cm91dC5vcmcwEYIPZWNvcnJpZG9ycy5pbmZvMBOCEWVkZ2FycmVzZWFyY2gub3Jn
+MBKCEGdldC1lZHVjYXRlZC5jb20wE4IRZ2V0LWVkdWNhdGVkLmluZm8wEYIPZ2V0
+ZWR1Y2F0ZWQubmV0MBKCEGdldC1lZHVjYXRlZC5uZXQwEYIPZ2V0ZWR1Y2F0ZWQu
+b3JnMBKCEGdldC1lZHVjYXRlZC5vcmcwD4INaG9raWVjbHViLmNvbTAQgg5ob2tp
+ZXBob3RvLmNvbTAPgg1ob2tpZXNob3AuY29tMBGCD2hva2llc3BvcnRzLmNvbTAS
+ghBob2tpZXRpY2tldHMuY29tMBKCEGhvdGVscm9hbm9rZS5jb20wE4IRaHVtYW53
+aWxkbGlmZS5vcmcwF4IVaW5uYXR2aXJnaW5pYXRlY2guY29tMA+CDWlzY2hwMjAx
+MS5vcmcwD4INbGFuZHJlaGFiLm9yZzAggh5uYXRpb25hbHRpcmVyZXNlYXJjaGNl
+bnRlci5jb20wFYITbmV0d29ya3ZpcmdpbmlhLm5ldDAMggpwZHJjdnQuY29tMBiC
+FnBldGVkeWVyaXZlcmNvdXJzZS5jb20wDYILcmFkaW9pcS5vcmcwFYITcml2ZXJj
+b3Vyc2Vnb2xmLmNvbTALgglzZGltaS5vcmcwEIIOc292YW1vdGlvbi5jb20wHoIc
+c3VzdGFpbmFibGUtYmlvbWF0ZXJpYWxzLmNvbTAeghxzdXN0YWluYWJsZS1iaW9t
+YXRlcmlhbHMub3JnMBWCE3RoaXNpc3RoZWZ1dHVyZS5jb20wGIIWdGhpcy1pcy10
+aGUtZnV0dXJlLmNvbTAVghN0aGlzaXN0aGVmdXR1cmUubmV0MBiCFnRoaXMtaXMt
+dGhlLWZ1dHVyZS5uZXQwCoIIdmFkcy5vcmcwDIIKdmFsZWFmLm9yZzANggt2YXRl
+Y2guaW5mbzANggt2YXRlY2gubW9iaTAcghp2YXRlY2hsaWZlbG9uZ2xlYXJuaW5n
+LmNvbTAcghp2YXRlY2hsaWZlbG9uZ2xlYXJuaW5nLm5ldDAcghp2YXRlY2hsaWZl
+bG9uZ2xlYXJuaW5nLm9yZzAKggh2Y29tLmVkdTASghB2aXJnaW5pYXZpZXcubmV0
+MDSCMnZpcmdpbmlhcG9seXRlY2huaWNpbnN0aXR1dGVhbmRzdGF0ZXVuaXZlcnNp
+dHkuY29tMDWCM3ZpcmdpbmlhcG9seXRlY2huaWNpbnN0aXR1dGVhbmRzdGF0ZXVu
+aXZlcnNpdHkuaW5mbzA0gjJ2aXJnaW5pYXBvbHl0ZWNobmljaW5zdGl0dXRlYW5k
+c3RhdGV1bml2ZXJzaXR5Lm5ldDA0gjJ2aXJnaW5pYXBvbHl0ZWNobmljaW5zdGl0
+dXRlYW5kc3RhdGV1bml2ZXJzaXR5Lm9yZzAZghd2aXJnaW5pYXB1YmxpY3JhZGlv
+Lm9yZzASghB2aXJnaW5pYXRlY2guZWR1MBOCEXZpcmdpbmlhdGVjaC5tb2JpMByC
+GnZpcmdpbmlhdGVjaGZvdW5kYXRpb24ub3JnMAiCBnZ0LmVkdTALggl2dGFyYy5v
+cmcwDIIKdnQtYXJjLm9yZzALggl2dGNyYy5jb20wCoIIdnRpcC5vcmcwDIIKdnRs
+ZWFuLm9yZzAWghR2dGtub3dsZWRnZXdvcmtzLmNvbTAYghZ2dGxpZmVsb25nbGVh
+cm5pbmcuY29tMBiCFnZ0bGlmZWxvbmdsZWFybmluZy5uZXQwGIIWdnRsaWZlbG9u
+Z2xlYXJuaW5nLm9yZzATghF2dHNwb3J0c21lZGlhLmNvbTALggl2dHdlaS5jb20w
+D4INd2l3YXR3ZXJjLmNvbTAKggh3dnRmLm9yZzAIgQZ2dC5lZHUwd6R1MHMxCzAJ
+BgNVBAYTAlVTMREwDwYDVQQIEwhWaXJnaW5pYTETMBEGA1UEBxMKQmxhY2tzYnVy
+ZzE8MDoGA1UEChMzVmlyZ2luaWEgUG9seXRlY2huaWMgSW5zdGl0dXRlIGFuZCBT
+dGF0ZSBVbml2ZXJzaXR5MCcGA1UdJQQgMB4GCCsGAQUFBwMCBggrBgEFBQcDAQYI
+KwYBBQUHAwkwPQYDVR0fBDYwNDAyoDCgLoYsaHR0cDovL2NybC5nbG9iYWxzaWdu
+LmNvbS9ncy90cnVzdHJvb3RnMi5jcmwwgYQGCCsGAQUFBwEBBHgwdjAzBggrBgEF
+BQcwAYYnaHR0cDovL29jc3AyLmdsb2JhbHNpZ24uY29tL3RydXN0cm9vdGcyMD8G
+CCsGAQUFBzAChjNodHRwOi8vc2VjdXJlLmdsb2JhbHNpZ24uY29tL2NhY2VydC90
+cnVzdHJvb3RnMi5jcnQwHQYDVR0OBBYEFLxiYCfV4zVIF+lLq0Vq0Miod3GMMB8G
+A1UdIwQYMBaAFBT25YsxtkWASkxt/MKHico2w5BiMA0GCSqGSIb3DQEBBQUAA4IB
+AQAyJm/lOB2Er4tHXhc/+fSufSzgjohJgYfMkvG4LknkvnZ1BjliefR8tTXX49d2
+SCDFWfGjqyJZwavavkl/4p3oXPG/nAMDMvxh4YAT+CfEK9HH+6ICV087kD4BLegi
++aFJMj8MMdReWCzn5sLnSR1rdse2mo2arX3Uod14SW+PGrbUmTuWNyvRbz3fVmxp
+UdbGmj3laknO9YPsBGgHfv73pVVsTJkW4ZfY/7KdD/yaVv6ophpOB3coXfjl2+kd
+Z4ypn2zK+cx9IL/LSewqd/7W9cD55PCUy4X9OTbEmAccwiz3LB66mQoUGfdHdkoB
+jUY+v9vLQXmaVwI0AYL7g9LN
+-----END CERTIFICATE-----`
+
+var nameConstraintsIntermediate2 = `-----BEGIN CERTIFICATE-----
+MIIEXTCCA0WgAwIBAgILBAAAAAABNuk6OrMwDQYJKoZIhvcNAQEFBQAwVzELMAkG
+A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv
+b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw0xMjA0MjUxMTAw
+MDBaFw0yNzA0MjUxMTAwMDBaMFwxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVz
+dGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExGzAZBgNVBAMTElRy
+dXN0ZWQgUm9vdCBDQSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+AKyuvqrtcMr7g7EuNbu4sKwxM127UsCmx1RxbxxgcArGS7rjiefpBH/w4LYrymjf
+vcw1ueyMNoqLo9nJMz/ORXupb35NNfE667prQYHa+tTjl1IiKpB7QUwt3wXPuTMF
+Ja1tXtjKzkqJyuJlNuPKT76HcjgNqgV1s9qG44MD5I2JvI12du8zI1bgdQ+l/KsX
+kTfbGjUvhOLOlVNWVQDpL+YMIrGqgBYxy5TUNgrAcRtwpNdS2KkF5otSmMweVb5k
+hoUVv3u8UxQH/WWbNhHq1RrIlg/0rBUfi/ziShYFSB7U+aLx5DxPphTFBiDquQGp
+tB+FC4JvnukDStFihZCZ1R8CAwEAAaOCASMwggEfMA4GA1UdDwEB/wQEAwIBBjAP
+BgNVHRMBAf8EBTADAQH/MEcGA1UdIARAMD4wPAYEVR0gADA0MDIGCCsGAQUFBwIB
+FiZodHRwczovL3d3dy5nbG9iYWxzaWduLmNvbS9yZXBvc2l0b3J5LzAdBgNVHQ4E
+FgQUFPblizG2RYBKTG38woeJyjbDkGIwMwYDVR0fBCwwKjAooCagJIYiaHR0cDov
+L2NybC5nbG9iYWxzaWduLm5ldC9yb290LmNybDA+BggrBgEFBQcBAQQyMDAwLgYI
+KwYBBQUHMAGGImh0dHA6Ly9vY3NwMi5nbG9iYWxzaWduLmNvbS9yb290cjEwHwYD
+VR0jBBgwFoAUYHtmGkUNl8qJUC99BM00qP/8/UswDQYJKoZIhvcNAQEFBQADggEB
+AL7IG0l+k4LkcpI+a/kvZsSRwSM4uA6zGX34e78A2oytr8RG8bJwVb8+AHMUD+Xe
+2kYdh/Uj/waQXfqR0OgxQXL9Ct4ZM+JlR1avsNKXWL5AwYXAXCOB3J5PW2XOck7H
+Zw0vRbGQhjWjQx+B4KOUFg1b3ov/z6Xkr3yaCfRQhXh7KC0Bc0RXPPG5Nv5lCW+z
+tbbg0zMm3kyfQITRusMSg6IBsDJqOnjaiaKQRcXiD0Sk43ZXb2bUKMxC7+Td3QL4
+RyHcWJbQ7YylLTS/x+jxWIcOQ0oO5/54t5PTQ14neYhOz9x4gUk2AYAW6d1vePwb
+hcC8roQwkHT7HvfYBoc74FM=
+-----END CERTIFICATE-----`
+
+var globalSignRoot = `-----BEGIN CERTIFICATE-----
+MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG
+A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv
+b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw
+MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i
+YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT
+aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ
+jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp
+xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp
+1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG
+snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ
+U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8
+9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E
+BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B
+AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz
+yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE
+38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP
+AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad
+DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME
+HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==
+-----END CERTIFICATE-----`
diff --git a/libgo/go/crypto/x509/x509.go b/libgo/go/crypto/x509/x509.go
index 4dfea2c9499..57f68ba7edc 100644
--- a/libgo/go/crypto/x509/x509.go
+++ b/libgo/go/crypto/x509/x509.go
@@ -40,38 +40,60 @@ func ParsePKIXPublicKey(derBytes []byte) (pub interface{}, err error) {
}
algo := getPublicKeyAlgorithmFromOID(pki.Algorithm.Algorithm)
if algo == UnknownPublicKeyAlgorithm {
- return nil, errors.New("ParsePKIXPublicKey: unknown public key algorithm")
+ return nil, errors.New("x509: unknown public key algorithm")
}
return parsePublicKey(algo, &pki)
}
-// MarshalPKIXPublicKey serialises a public key to DER-encoded PKIX format.
-func MarshalPKIXPublicKey(pub interface{}) ([]byte, error) {
- var pubBytes []byte
-
+func marshalPublicKey(pub interface{}) (publicKeyBytes []byte, publicKeyAlgorithm pkix.AlgorithmIdentifier, err error) {
switch pub := pub.(type) {
case *rsa.PublicKey:
- pubBytes, _ = asn1.Marshal(rsaPublicKey{
+ publicKeyBytes, err = asn1.Marshal(rsaPublicKey{
N: pub.N,
E: pub.E,
})
+ publicKeyAlgorithm.Algorithm = oidPublicKeyRSA
+ // This is a NULL parameters value which is technically
+ // superfluous, but most other code includes it and, by
+ // doing this, we match their public key hashes.
+ publicKeyAlgorithm.Parameters = asn1.RawValue{
+ Tag: 5,
+ }
+ case *ecdsa.PublicKey:
+ publicKeyBytes = elliptic.Marshal(pub.Curve, pub.X, pub.Y)
+ oid, ok := oidFromNamedCurve(pub.Curve)
+ if !ok {
+ return nil, pkix.AlgorithmIdentifier{}, errors.New("x509: unsupported elliptic curve")
+ }
+ publicKeyAlgorithm.Algorithm = oidPublicKeyECDSA
+ var paramBytes []byte
+ paramBytes, err = asn1.Marshal(oid)
+ if err != nil {
+ return
+ }
+ publicKeyAlgorithm.Parameters.FullBytes = paramBytes
default:
- return nil, errors.New("MarshalPKIXPublicKey: unknown public key type")
+ return nil, pkix.AlgorithmIdentifier{}, errors.New("x509: only RSA and ECDSA public keys supported")
+ }
+
+ return publicKeyBytes, publicKeyAlgorithm, nil
+}
+
+// MarshalPKIXPublicKey serialises a public key to DER-encoded PKIX format.
+func MarshalPKIXPublicKey(pub interface{}) ([]byte, error) {
+ var publicKeyBytes []byte
+ var publicKeyAlgorithm pkix.AlgorithmIdentifier
+ var err error
+
+ if publicKeyBytes, publicKeyAlgorithm, err = marshalPublicKey(pub); err != nil {
+ return nil, err
}
pkix := pkixPublicKey{
- Algo: pkix.AlgorithmIdentifier{
- Algorithm: []int{1, 2, 840, 113549, 1, 1, 1},
- // This is a NULL parameters value which is technically
- // superfluous, but most other code includes it and, by
- // doing this, we match their public key hashes.
- Parameters: asn1.RawValue{
- Tag: 5,
- },
- },
+ Algo: publicKeyAlgorithm,
BitString: asn1.BitString{
- Bytes: pubBytes,
- BitLength: 8 * len(pubBytes),
+ Bytes: publicKeyBytes,
+ BitLength: 8 * len(publicKeyBytes),
},
}
@@ -453,6 +475,18 @@ type Certificate struct {
NotBefore, NotAfter time.Time // Validity bounds.
KeyUsage KeyUsage
+ // Extensions contains raw X.509 extensions. When parsing certificates,
+ // this can be used to extract non-critical extensions that are not
+ // parsed by this package. When marshaling certificates, the Extensions
+ // field is ignored, see ExtraExtensions.
+ Extensions []pkix.Extension
+
+ // ExtraExtensions contains extensions to be copied, raw, into any
+ // marshaled certificates. Values override any extensions that would
+ // otherwise be produced based on the other fields. The ExtraExtensions
+ // field is not populated when parsing certificates, see Extensions.
+ ExtraExtensions []pkix.Extension
+
ExtKeyUsage []ExtKeyUsage // Sequence of extended key usages.
UnknownExtKeyUsage []asn1.ObjectIdentifier // Encountered extended key usages unknown to this package.
@@ -463,6 +497,10 @@ type Certificate struct {
SubjectKeyId []byte
AuthorityKeyId []byte
+ // RFC 5280, 4.2.2.1 (Authority Information Access)
+ OCSPServer []string
+ IssuingCertificateURL []string
+
// Subject Alternate Name values
DNSNames []string
EmailAddresses []string
@@ -472,12 +510,15 @@ type Certificate struct {
PermittedDNSDomainsCritical bool // if true then the name constraints are marked critical.
PermittedDNSDomains []string
+ // CRL Distribution Points
+ CRLDistributionPoints []string
+
PolicyIdentifiers []asn1.ObjectIdentifier
}
// ErrUnsupportedAlgorithm results from attempting to perform an operation that
// involves algorithms that are not currently implemented.
-var ErrUnsupportedAlgorithm = errors.New("crypto/x509: cannot verify signature: algorithm unimplemented")
+var ErrUnsupportedAlgorithm = errors.New("x509: cannot verify signature: algorithm unimplemented")
// ConstraintViolationError results when a requested usage is not permitted by
// a certificate. For example: checking a signature when the public key isn't a
@@ -485,7 +526,7 @@ var ErrUnsupportedAlgorithm = errors.New("crypto/x509: cannot verify signature:
type ConstraintViolationError struct{}
func (ConstraintViolationError) Error() string {
- return "crypto/x509: invalid signature: parent certificate cannot sign this kind of certificate"
+ return "x509: invalid signature: parent certificate cannot sign this kind of certificate"
}
func (c *Certificate) Equal(other *Certificate) bool {
@@ -604,10 +645,10 @@ func (c *Certificate) CheckSignature(algo SignatureAlgorithm, signed, signature
return err
}
if dsaSig.R.Sign() <= 0 || dsaSig.S.Sign() <= 0 {
- return errors.New("DSA signature contained zero or negative values")
+ return errors.New("x509: DSA signature contained zero or negative values")
}
if !dsa.Verify(pub, digest, dsaSig.R, dsaSig.S) {
- return errors.New("DSA verification failure")
+ return errors.New("x509: DSA verification failure")
}
return
case *ecdsa.PublicKey:
@@ -616,10 +657,10 @@ func (c *Certificate) CheckSignature(algo SignatureAlgorithm, signed, signature
return err
}
if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 {
- return errors.New("crypto/x509: ECDSA signature contained zero or negative values")
+ return errors.New("x509: ECDSA signature contained zero or negative values")
}
if !ecdsa.Verify(pub, digest, ecdsaSig.R, ecdsaSig.S) {
- return errors.New("crypto/x509: ECDSA verification failure")
+ return errors.New("x509: ECDSA verification failure")
}
return
}
@@ -635,7 +676,7 @@ func (c *Certificate) CheckCRLSignature(crl *pkix.CertificateList) (err error) {
type UnhandledCriticalExtension struct{}
func (h UnhandledCriticalExtension) Error() string {
- return "unhandled critical extension"
+ return "x509: unhandled critical extension"
}
type basicConstraints struct {
@@ -659,6 +700,24 @@ type generalSubtree struct {
Name string `asn1:"tag:2,optional,ia5"`
}
+// RFC 5280, 4.2.2.1
+type authorityInfoAccess struct {
+ Method asn1.ObjectIdentifier
+ Location asn1.RawValue
+}
+
+// RFC 5280, 4.2.1.14
+type distributionPoint struct {
+ DistributionPoint distributionPointName `asn1:"optional,tag:0"`
+ Reason asn1.BitString `asn1:"optional,tag:1"`
+ CRLIssuer asn1.RawValue `asn1:"optional,tag:2"`
+}
+
+type distributionPointName struct {
+ FullName asn1.RawValue `asn1:"optional,tag:0"`
+ RelativeName pkix.RDNSequence `asn1:"optional,tag:1"`
+}
+
func parsePublicKey(algo PublicKeyAlgorithm, keyData *publicKeyInfo) (interface{}, error) {
asn1Data := keyData.PublicKey.RightAlign()
switch algo {
@@ -694,7 +753,7 @@ func parsePublicKey(algo PublicKeyAlgorithm, keyData *publicKeyInfo) (interface{
return nil, err
}
if p.Sign() <= 0 || params.P.Sign() <= 0 || params.Q.Sign() <= 0 || params.G.Sign() <= 0 {
- return nil, errors.New("zero or negative DSA parameter")
+ return nil, errors.New("x509: zero or negative DSA parameter")
}
pub := &dsa.PublicKey{
Parameters: dsa.Parameters{
@@ -714,11 +773,11 @@ func parsePublicKey(algo PublicKeyAlgorithm, keyData *publicKeyInfo) (interface{
}
namedCurve := namedCurveFromOID(*namedCurveOID)
if namedCurve == nil {
- return nil, errors.New("crypto/x509: unsupported elliptic curve")
+ return nil, errors.New("x509: unsupported elliptic curve")
}
x, y := elliptic.Unmarshal(namedCurve, asn1Data)
if x == nil {
- return nil, errors.New("crypto/x509: failed to unmarshal elliptic curve point")
+ return nil, errors.New("x509: failed to unmarshal elliptic curve point")
}
pub := &ecdsa.PublicKey{
Curve: namedCurve,
@@ -752,7 +811,7 @@ func parseCertificate(in *certificate) (*Certificate, error) {
}
if in.TBSCertificate.SerialNumber.Sign() < 0 {
- return nil, errors.New("negative serial number")
+ return nil, errors.New("x509: negative serial number")
}
out.Version = in.TBSCertificate.Version + 1
@@ -773,6 +832,8 @@ func parseCertificate(in *certificate) (*Certificate, error) {
out.NotAfter = in.TBSCertificate.Validity.NotAfter
for _, e := range in.TBSCertificate.Extensions {
+ out.Extensions = append(out.Extensions, e)
+
if len(e.Id) == 4 && e.Id[0] == 2 && e.Id[1] == 5 && e.Id[2] == 29 {
switch e.Id[3] {
case 15:
@@ -896,6 +957,39 @@ func parseCertificate(in *certificate) (*Certificate, error) {
}
continue
+ case 31:
+ // RFC 5280, 4.2.1.14
+
+ // CRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint
+ //
+ // DistributionPoint ::= SEQUENCE {
+ // distributionPoint [0] DistributionPointName OPTIONAL,
+ // reasons [1] ReasonFlags OPTIONAL,
+ // cRLIssuer [2] GeneralNames OPTIONAL }
+ //
+ // DistributionPointName ::= CHOICE {
+ // fullName [0] GeneralNames,
+ // nameRelativeToCRLIssuer [1] RelativeDistinguishedName }
+
+ var cdp []distributionPoint
+ _, err := asn1.Unmarshal(e.Value, &cdp)
+ if err != nil {
+ return nil, err
+ }
+
+ for _, dp := range cdp {
+ var n asn1.RawValue
+ _, err = asn1.Unmarshal(dp.DistributionPoint.FullName.Bytes, &n)
+ if err != nil {
+ return nil, err
+ }
+
+ if n.Tag == 6 {
+ out.CRLDistributionPoints = append(out.CRLDistributionPoints, string(n.Bytes))
+ }
+ }
+ continue
+
case 35:
// RFC 5280, 4.2.1.1
var a authKeyId
@@ -952,6 +1046,24 @@ func parseCertificate(in *certificate) (*Certificate, error) {
out.PolicyIdentifiers[i] = policy.Policy
}
}
+ } else if e.Id.Equal(oidExtensionAuthorityInfoAccess) {
+ // RFC 5280 4.2.2.1: Authority Information Access
+ var aia []authorityInfoAccess
+ if _, err = asn1.Unmarshal(e.Value, &aia); err != nil {
+ return nil, err
+ }
+
+ for _, v := range aia {
+ // GeneralName: uniformResourceIdentifier [6] IA5String
+ if v.Location.Tag != 6 {
+ continue
+ }
+ if v.Method.Equal(oidAuthorityInfoAccessOcsp) {
+ out.OCSPServer = append(out.OCSPServer, string(v.Location.Bytes))
+ } else if v.Method.Equal(oidAuthorityInfoAccessIssuers) {
+ out.IssuingCertificateURL = append(out.IssuingCertificateURL, string(v.Location.Bytes))
+ }
+ }
}
if e.Critical {
@@ -1011,21 +1123,40 @@ func reverseBitsInAByte(in byte) byte {
}
var (
- oidExtensionSubjectKeyId = []int{2, 5, 29, 14}
- oidExtensionKeyUsage = []int{2, 5, 29, 15}
- oidExtensionExtendedKeyUsage = []int{2, 5, 29, 37}
- oidExtensionAuthorityKeyId = []int{2, 5, 29, 35}
- oidExtensionBasicConstraints = []int{2, 5, 29, 19}
- oidExtensionSubjectAltName = []int{2, 5, 29, 17}
- oidExtensionCertificatePolicies = []int{2, 5, 29, 32}
- oidExtensionNameConstraints = []int{2, 5, 29, 30}
+ oidExtensionSubjectKeyId = []int{2, 5, 29, 14}
+ oidExtensionKeyUsage = []int{2, 5, 29, 15}
+ oidExtensionExtendedKeyUsage = []int{2, 5, 29, 37}
+ oidExtensionAuthorityKeyId = []int{2, 5, 29, 35}
+ oidExtensionBasicConstraints = []int{2, 5, 29, 19}
+ oidExtensionSubjectAltName = []int{2, 5, 29, 17}
+ oidExtensionCertificatePolicies = []int{2, 5, 29, 32}
+ oidExtensionNameConstraints = []int{2, 5, 29, 30}
+ oidExtensionCRLDistributionPoints = []int{2, 5, 29, 31}
+ oidExtensionAuthorityInfoAccess = []int{1, 3, 6, 1, 5, 5, 7, 1, 1}
+)
+
+var (
+ oidAuthorityInfoAccessOcsp = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 48, 1}
+ oidAuthorityInfoAccessIssuers = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 48, 2}
)
+// oidNotInExtensions returns whether an extension with the given oid exists in
+// extensions.
+func oidInExtensions(oid asn1.ObjectIdentifier, extensions []pkix.Extension) bool {
+ for _, e := range extensions {
+ if e.Id.Equal(oid) {
+ return true
+ }
+ }
+ return false
+}
+
func buildExtensions(template *Certificate) (ret []pkix.Extension, err error) {
- ret = make([]pkix.Extension, 8 /* maximum number of elements. */)
+ ret = make([]pkix.Extension, 10 /* maximum number of elements. */)
n := 0
- if template.KeyUsage != 0 {
+ if template.KeyUsage != 0 &&
+ !oidInExtensions(oidExtensionKeyUsage, template.ExtraExtensions) {
ret[n].Id = oidExtensionKeyUsage
ret[n].Critical = true
@@ -1045,7 +1176,8 @@ func buildExtensions(template *Certificate) (ret []pkix.Extension, err error) {
n++
}
- if len(template.ExtKeyUsage) > 0 || len(template.UnknownExtKeyUsage) > 0 {
+ if (len(template.ExtKeyUsage) > 0 || len(template.UnknownExtKeyUsage) > 0) &&
+ !oidInExtensions(oidExtensionExtendedKeyUsage, template.ExtraExtensions) {
ret[n].Id = oidExtensionExtendedKeyUsage
var oids []asn1.ObjectIdentifier
@@ -1066,7 +1198,7 @@ func buildExtensions(template *Certificate) (ret []pkix.Extension, err error) {
n++
}
- if template.BasicConstraintsValid {
+ if template.BasicConstraintsValid && !oidInExtensions(oidExtensionBasicConstraints, template.ExtraExtensions) {
ret[n].Id = oidExtensionBasicConstraints
ret[n].Value, err = asn1.Marshal(basicConstraints{template.IsCA, template.MaxPathLen})
ret[n].Critical = true
@@ -1076,7 +1208,7 @@ func buildExtensions(template *Certificate) (ret []pkix.Extension, err error) {
n++
}
- if len(template.SubjectKeyId) > 0 {
+ if len(template.SubjectKeyId) > 0 && !oidInExtensions(oidExtensionSubjectKeyId, template.ExtraExtensions) {
ret[n].Id = oidExtensionSubjectKeyId
ret[n].Value, err = asn1.Marshal(template.SubjectKeyId)
if err != nil {
@@ -1085,7 +1217,7 @@ func buildExtensions(template *Certificate) (ret []pkix.Extension, err error) {
n++
}
- if len(template.AuthorityKeyId) > 0 {
+ if len(template.AuthorityKeyId) > 0 && !oidInExtensions(oidExtensionAuthorityKeyId, template.ExtraExtensions) {
ret[n].Id = oidExtensionAuthorityKeyId
ret[n].Value, err = asn1.Marshal(authKeyId{template.AuthorityKeyId})
if err != nil {
@@ -1094,7 +1226,31 @@ func buildExtensions(template *Certificate) (ret []pkix.Extension, err error) {
n++
}
- if len(template.DNSNames) > 0 || len(template.EmailAddresses) > 0 || len(template.IPAddresses) > 0 {
+ if (len(template.OCSPServer) > 0 || len(template.IssuingCertificateURL) > 0) &&
+ !oidInExtensions(oidExtensionAuthorityInfoAccess, template.ExtraExtensions) {
+ ret[n].Id = oidExtensionAuthorityInfoAccess
+ var aiaValues []authorityInfoAccess
+ for _, name := range template.OCSPServer {
+ aiaValues = append(aiaValues, authorityInfoAccess{
+ Method: oidAuthorityInfoAccessOcsp,
+ Location: asn1.RawValue{Tag: 6, Class: 2, Bytes: []byte(name)},
+ })
+ }
+ for _, name := range template.IssuingCertificateURL {
+ aiaValues = append(aiaValues, authorityInfoAccess{
+ Method: oidAuthorityInfoAccessIssuers,
+ Location: asn1.RawValue{Tag: 6, Class: 2, Bytes: []byte(name)},
+ })
+ }
+ ret[n].Value, err = asn1.Marshal(aiaValues)
+ if err != nil {
+ return
+ }
+ n++
+ }
+
+ if (len(template.DNSNames) > 0 || len(template.EmailAddresses) > 0 || len(template.IPAddresses) > 0) &&
+ !oidInExtensions(oidExtensionSubjectAltName, template.ExtraExtensions) {
ret[n].Id = oidExtensionSubjectAltName
var rawValues []asn1.RawValue
for _, name := range template.DNSNames {
@@ -1118,7 +1274,8 @@ func buildExtensions(template *Certificate) (ret []pkix.Extension, err error) {
n++
}
- if len(template.PolicyIdentifiers) > 0 {
+ if len(template.PolicyIdentifiers) > 0 &&
+ !oidInExtensions(oidExtensionCertificatePolicies, template.ExtraExtensions) {
ret[n].Id = oidExtensionCertificatePolicies
policies := make([]policyInformation, len(template.PolicyIdentifiers))
for i, policy := range template.PolicyIdentifiers {
@@ -1131,7 +1288,8 @@ func buildExtensions(template *Certificate) (ret []pkix.Extension, err error) {
n++
}
- if len(template.PermittedDNSDomains) > 0 {
+ if len(template.PermittedDNSDomains) > 0 &&
+ !oidInExtensions(oidExtensionNameConstraints, template.ExtraExtensions) {
ret[n].Id = oidExtensionNameConstraints
ret[n].Critical = template.PermittedDNSDomainsCritical
@@ -1147,10 +1305,33 @@ func buildExtensions(template *Certificate) (ret []pkix.Extension, err error) {
n++
}
+ if len(template.CRLDistributionPoints) > 0 &&
+ !oidInExtensions(oidExtensionCRLDistributionPoints, template.ExtraExtensions) {
+ ret[n].Id = oidExtensionCRLDistributionPoints
+
+ var crlDp []distributionPoint
+ for _, name := range template.CRLDistributionPoints {
+ rawFullName, _ := asn1.Marshal(asn1.RawValue{Tag: 6, Class: 2, Bytes: []byte(name)})
+
+ dp := distributionPoint{
+ DistributionPoint: distributionPointName{
+ FullName: asn1.RawValue{Tag: 0, Class: 2, Bytes: rawFullName},
+ },
+ }
+ crlDp = append(crlDp, dp)
+ }
+
+ ret[n].Value, err = asn1.Marshal(crlDp)
+ if err != nil {
+ return
+ }
+ n++
+ }
+
// Adding another extension here? Remember to update the maximum number
// of elements in the make() at the top of the function.
- return ret[0:n], nil
+ return append(ret[:n], template.ExtraExtensions...), nil
}
func subjectBytes(cert *Certificate) ([]byte, error) {
@@ -1179,28 +1360,8 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub interf
var publicKeyBytes []byte
var publicKeyAlgorithm pkix.AlgorithmIdentifier
- switch pub := pub.(type) {
- case *rsa.PublicKey:
- publicKeyBytes, err = asn1.Marshal(rsaPublicKey{
- N: pub.N,
- E: pub.E,
- })
- publicKeyAlgorithm.Algorithm = oidPublicKeyRSA
- case *ecdsa.PublicKey:
- oid, ok := oidFromNamedCurve(pub.Curve)
- if !ok {
- return nil, errors.New("x509: unknown elliptic curve")
- }
- publicKeyAlgorithm.Algorithm = oidPublicKeyECDSA
- var paramBytes []byte
- paramBytes, err = asn1.Marshal(oid)
- if err != nil {
- return
- }
- publicKeyAlgorithm.Parameters.FullBytes = paramBytes
- publicKeyBytes = elliptic.Marshal(pub.Curve, pub.X, pub.Y)
- default:
- return nil, errors.New("x509: only RSA and ECDSA public keys supported")
+ if publicKeyBytes, publicKeyAlgorithm, err = marshalPublicKey(pub); err != nil {
+ return nil, err
}
var signatureAlgorithm pkix.AlgorithmIdentifier
diff --git a/libgo/go/crypto/x509/x509_test.go b/libgo/go/crypto/x509/x509_test.go
index abd4fe84d7e..f1097e992e7 100644
--- a/libgo/go/crypto/x509/x509_test.go
+++ b/libgo/go/crypto/x509/x509_test.go
@@ -237,6 +237,11 @@ func TestCertificateParse(t *testing.T) {
if err := certs[0].VerifyHostname("mail.google.com"); err != nil {
t.Error(err)
}
+
+ const expectedExtensions = 4
+ if n := len(certs[0].Extensions); n != expectedExtensions {
+ t.Errorf("want %d extensions, got %d", expectedExtensions, n)
+ }
}
var certBytes = "308203223082028ba00302010202106edf0d9499fd4533dd1297fc42a93be1300d06092a864886" +
@@ -308,7 +313,8 @@ func TestCreateSelfSignedCertificate(t *testing.T) {
}
testExtKeyUsage := []ExtKeyUsage{ExtKeyUsageClientAuth, ExtKeyUsageServerAuth}
- testUnknownExtKeyUsage := []asn1.ObjectIdentifier{[]int{1, 2, 3}, []int{3, 2, 1}}
+ testUnknownExtKeyUsage := []asn1.ObjectIdentifier{[]int{1, 2, 3}, []int{2, 59, 1}}
+ extraExtensionData := []byte("extra extension")
for _, test := range tests {
commonName := "test.example.com"
@@ -330,12 +336,30 @@ func TestCreateSelfSignedCertificate(t *testing.T) {
BasicConstraintsValid: true,
IsCA: true,
+ OCSPServer: []string{"http://ocsp.example.com"},
+ IssuingCertificateURL: []string{"http://crt.example.com/ca1.crt"},
+
DNSNames: []string{"test.example.com"},
EmailAddresses: []string{"gopher@golang.org"},
IPAddresses: []net.IP{net.IPv4(127, 0, 0, 1).To4(), net.ParseIP("2001:4860:0:2001::68")},
PolicyIdentifiers: []asn1.ObjectIdentifier{[]int{1, 2, 3}},
PermittedDNSDomains: []string{".example.com", "example.com"},
+
+ CRLDistributionPoints: []string{"http://crl1.example.com/ca1.crl", "http://crl2.example.com/ca1.crl"},
+
+ ExtraExtensions: []pkix.Extension{
+ {
+ Id: []int{1, 2, 3, 4},
+ Value: extraExtensionData,
+ },
+ // This extension should override the SubjectKeyId, above.
+ {
+ Id: oidExtensionSubjectKeyId,
+ Critical: false,
+ Value: []byte{0x04, 0x04, 4, 3, 2, 1},
+ },
+ },
}
derBytes, err := CreateCertificate(random, &template, &template, test.pub, test.priv)
@@ -374,6 +398,14 @@ func TestCreateSelfSignedCertificate(t *testing.T) {
t.Errorf("%s: unknown extkeyusage wasn't correctly copied from the template. Got %v, want %v", test.name, cert.UnknownExtKeyUsage, testUnknownExtKeyUsage)
}
+ if !reflect.DeepEqual(cert.OCSPServer, template.OCSPServer) {
+ t.Errorf("%s: OCSP servers differ from template. Got %v, want %v", test.name, cert.OCSPServer, template.OCSPServer)
+ }
+
+ if !reflect.DeepEqual(cert.IssuingCertificateURL, template.IssuingCertificateURL) {
+ t.Errorf("%s: Issuing certificate URLs differ from template. Got %v, want %v", test.name, cert.IssuingCertificateURL, template.IssuingCertificateURL)
+ }
+
if !reflect.DeepEqual(cert.DNSNames, template.DNSNames) {
t.Errorf("%s: SAN DNS names differ from template. Got %v, want %v", test.name, cert.DNSNames, template.DNSNames)
}
@@ -386,6 +418,18 @@ func TestCreateSelfSignedCertificate(t *testing.T) {
t.Errorf("%s: SAN IPs differ from template. Got %v, want %v", test.name, cert.IPAddresses, template.IPAddresses)
}
+ if !reflect.DeepEqual(cert.CRLDistributionPoints, template.CRLDistributionPoints) {
+ t.Errorf("%s: CRL distribution points differ from template. Got %v, want %v", test.name, cert.CRLDistributionPoints, template.CRLDistributionPoints)
+ }
+
+ if !bytes.Equal(cert.SubjectKeyId, []byte{4, 3, 2, 1}) {
+ t.Errorf("%s: ExtraExtensions didn't override SubjectKeyId", test.name)
+ }
+
+ if bytes.Index(derBytes, extraExtensionData) == -1 {
+ t.Errorf("%s: didn't find extra extension in DER output", test.name)
+ }
+
if test.checkSig {
err = cert.CheckSignatureFrom(cert)
if err != nil {
diff --git a/libgo/go/database/sql/convert_test.go b/libgo/go/database/sql/convert_test.go
index 950e24fc3a8..a39c2c54fba 100644
--- a/libgo/go/database/sql/convert_test.go
+++ b/libgo/go/database/sql/convert_test.go
@@ -267,14 +267,14 @@ func TestValueConverters(t *testing.T) {
goterr = err.Error()
}
if goterr != tt.err {
- t.Errorf("test %d: %s(%T(%v)) error = %q; want error = %q",
+ t.Errorf("test %d: %T(%T(%v)) error = %q; want error = %q",
i, tt.c, tt.in, tt.in, goterr, tt.err)
}
if tt.err != "" {
continue
}
if !reflect.DeepEqual(out, tt.out) {
- t.Errorf("test %d: %s(%T(%v)) = %v (%T); want %v (%T)",
+ t.Errorf("test %d: %T(%T(%v)) = %v (%T); want %v (%T)",
i, tt.c, tt.in, tt.in, out, out, tt.out, tt.out)
}
}
diff --git a/libgo/go/database/sql/driver/types_test.go b/libgo/go/database/sql/driver/types_test.go
index ab82bca7166..1ce0ff06541 100644
--- a/libgo/go/database/sql/driver/types_test.go
+++ b/libgo/go/database/sql/driver/types_test.go
@@ -51,14 +51,14 @@ func TestValueConverters(t *testing.T) {
goterr = err.Error()
}
if goterr != tt.err {
- t.Errorf("test %d: %s(%T(%v)) error = %q; want error = %q",
+ t.Errorf("test %d: %T(%T(%v)) error = %q; want error = %q",
i, tt.c, tt.in, tt.in, goterr, tt.err)
}
if tt.err != "" {
continue
}
if !reflect.DeepEqual(out, tt.out) {
- t.Errorf("test %d: %s(%T(%v)) = %v (%T); want %v (%T)",
+ t.Errorf("test %d: %T(%T(%v)) = %v (%T); want %v (%T)",
i, tt.c, tt.in, tt.in, out, out, tt.out, tt.out)
}
}
diff --git a/libgo/go/database/sql/fakedb_test.go b/libgo/go/database/sql/fakedb_test.go
index d900e2cebe8..a8adfdd9424 100644
--- a/libgo/go/database/sql/fakedb_test.go
+++ b/libgo/go/database/sql/fakedb_test.go
@@ -38,6 +38,8 @@ type fakeDriver struct {
mu sync.Mutex // guards 3 following fields
openCount int // conn opens
closeCount int // conn closes
+ waitCh chan struct{}
+ waitingCh chan struct{}
dbs map[string]*fakeDB
}
@@ -146,6 +148,12 @@ func (d *fakeDriver) Open(dsn string) (driver.Conn, error) {
if len(parts) >= 2 && parts[1] == "badConn" {
conn.bad = true
}
+ if d.waitCh != nil {
+ d.waitingCh <- struct{}{}
+ <-d.waitCh
+ d.waitCh = nil
+ d.waitingCh = nil
+ }
return conn, nil
}
@@ -447,6 +455,10 @@ func (c *fakeConn) Prepare(query string) (driver.Stmt, error) {
return c.prepareCreate(stmt, parts)
case "INSERT":
return c.prepareInsert(stmt, parts)
+ case "NOSERT":
+ // Do all the prep-work like for an INSERT but don't actually insert the row.
+ // Used for some of the concurrent tests.
+ return c.prepareInsert(stmt, parts)
default:
stmt.Close()
return nil, errf("unsupported command type %q", cmd)
@@ -497,13 +509,20 @@ func (s *fakeStmt) Exec(args []driver.Value) (driver.Result, error) {
}
return driver.ResultNoRows, nil
case "INSERT":
- return s.execInsert(args)
+ return s.execInsert(args, true)
+ case "NOSERT":
+ // Do all the prep-work like for an INSERT but don't actually insert the row.
+ // Used for some of the concurrent tests.
+ return s.execInsert(args, false)
}
fmt.Printf("EXEC statement, cmd=%q: %#v\n", s.cmd, s)
return nil, fmt.Errorf("unimplemented statement Exec command type of %q", s.cmd)
}
-func (s *fakeStmt) execInsert(args []driver.Value) (driver.Result, error) {
+// When doInsert is true, add the row to the table.
+// When doInsert is false do prep-work and error checking, but don't
+// actually add the row to the table.
+func (s *fakeStmt) execInsert(args []driver.Value, doInsert bool) (driver.Result, error) {
db := s.c.db
if len(args) != s.placeholders {
panic("error in pkg db; should only get here if size is correct")
@@ -518,7 +537,10 @@ func (s *fakeStmt) execInsert(args []driver.Value) (driver.Result, error) {
t.mu.Lock()
defer t.mu.Unlock()
- cols := make([]interface{}, len(t.colname))
+ var cols []interface{}
+ if doInsert {
+ cols = make([]interface{}, len(t.colname))
+ }
argPos := 0
for n, colname := range s.colName {
colidx := t.columnIndex(colname)
@@ -532,10 +554,14 @@ func (s *fakeStmt) execInsert(args []driver.Value) (driver.Result, error) {
} else {
val = s.colValue[n]
}
- cols[colidx] = val
+ if doInsert {
+ cols[colidx] = val
+ }
}
- t.rows = append(t.rows, &row{cols: cols})
+ if doInsert {
+ t.rows = append(t.rows, &row{cols: cols})
+ }
return driver.RowsAffected(1), nil
}
@@ -608,9 +634,10 @@ rows:
}
cursor := &rowsCursor{
- pos: -1,
- rows: mrows,
- cols: s.colName,
+ pos: -1,
+ rows: mrows,
+ cols: s.colName,
+ errPos: -1,
}
return cursor, nil
}
@@ -635,6 +662,10 @@ type rowsCursor struct {
rows []*row
closed bool
+ // errPos and err are for making Next return early with error.
+ errPos int
+ err error
+
// a clone of slices to give out to clients, indexed by the
// the original slice's first byte address. we clone them
// just so we're able to corrupt them on close.
@@ -660,6 +691,9 @@ func (rc *rowsCursor) Next(dest []driver.Value) error {
return errors.New("fakedb: cursor is closed")
}
rc.pos++
+ if rc.pos == rc.errPos {
+ return rc.err
+ }
if rc.pos >= len(rc.rows) {
return io.EOF // per interface spec
}
diff --git a/libgo/go/database/sql/sql.go b/libgo/go/database/sql/sql.go
index a80782bfedc..f7b4f8cdab8 100644
--- a/libgo/go/database/sql/sql.go
+++ b/libgo/go/database/sql/sql.go
@@ -7,9 +7,13 @@
//
// The sql package must be used in conjunction with a database driver.
// See http://golang.org/s/sqldrivers for a list of drivers.
+//
+// For more usage examples, see the wiki page at
+// http://golang.org/s/sqlwiki.
package sql
import (
+ "container/list"
"database/sql/driver"
"errors"
"fmt"
@@ -192,12 +196,22 @@ type DB struct {
driver driver.Driver
dsn string
- mu sync.Mutex // protects following fields
- freeConn []*driverConn
+ mu sync.Mutex // protects following fields
+ freeConn *list.List // of *driverConn
+ connRequests *list.List // of connRequest
+ numOpen int
+ pendingOpens int
+ // Used to sygnal the need for new connections
+ // a goroutine running connectionOpener() reads on this chan and
+ // maybeOpenNewConnections sends on the chan (one send per needed connection)
+ // It is closed during db.Close(). The close tells the connectionOpener
+ // goroutine to exit.
+ openerCh chan struct{}
closed bool
dep map[finalCloser]depSet
lastPut map[*driverConn]string // stacktrace of last conn's put; debug only
maxIdle int // zero means defaultMaxIdleConns; negative means 0
+ maxOpen int // <= 0 means unlimited
}
// driverConn wraps a driver.Conn with a mutex, to
@@ -217,6 +231,13 @@ type driverConn struct {
inUse bool
onPut []func() // code (with db.mu held) run when conn is next returned
dbmuClosed bool // same as closed, but guarded by db.mu, for connIfFree
+ // This is the Element returned by db.freeConn.PushFront(conn).
+ // It's used by connIfFree to remove the conn from the freeConn list.
+ listElem *list.Element
+}
+
+func (dc *driverConn) releaseConn(err error) {
+ dc.db.putConn(dc, err)
}
func (dc *driverConn) removeOpenStmt(si driver.Stmt) {
@@ -250,15 +271,14 @@ func (dc *driverConn) prepareLocked(query string) (driver.Stmt, error) {
}
// the dc.db's Mutex is held.
-func (dc *driverConn) closeDBLocked() error {
+func (dc *driverConn) closeDBLocked() func() error {
dc.Lock()
+ defer dc.Unlock()
if dc.closed {
- dc.Unlock()
- return errors.New("sql: duplicate driverConn close")
+ return func() error { return errors.New("sql: duplicate driverConn close") }
}
dc.closed = true
- dc.Unlock() // not defer; removeDep finalClose calls may need to lock
- return dc.db.removeDepLocked(dc, dc)()
+ return dc.db.removeDepLocked(dc, dc)
}
func (dc *driverConn) Close() error {
@@ -289,8 +309,13 @@ func (dc *driverConn) finalClose() error {
err := dc.ci.Close()
dc.ci = nil
dc.finalClosed = true
-
dc.Unlock()
+
+ dc.db.mu.Lock()
+ dc.db.numOpen--
+ dc.db.maybeOpenNewConnections()
+ dc.db.mu.Unlock()
+
return err
}
@@ -353,26 +378,36 @@ func (db *DB) removeDep(x finalCloser, dep interface{}) error {
func (db *DB) removeDepLocked(x finalCloser, dep interface{}) func() error {
//println(fmt.Sprintf("removeDep(%T %p, %T %p)", x, x, dep, dep))
- done := false
- xdep := db.dep[x]
- if xdep != nil {
- delete(xdep, dep)
- if len(xdep) == 0 {
- delete(db.dep, x)
- done = true
- }
+ xdep, ok := db.dep[x]
+ if !ok {
+ panic(fmt.Sprintf("unpaired removeDep: no deps for %T", x))
}
- if !done {
+ l0 := len(xdep)
+ delete(xdep, dep)
+
+ switch len(xdep) {
+ case l0:
+ // Nothing removed. Shouldn't happen.
+ panic(fmt.Sprintf("unpaired removeDep: no %T dep on %T", dep, x))
+ case 0:
+ // No more dependencies.
+ delete(db.dep, x)
+ return x.finalClose
+ default:
+ // Dependencies remain.
return func() error { return nil }
}
- return func() error {
- //println(fmt.Sprintf("calling final close on %T %v (%#v)", x, x, x))
- return x.finalClose()
- }
}
+// This is the size of the connectionOpener request chan (dn.openerCh).
+// This value should be larger than the maximum typical value
+// used for db.maxOpen. If maxOpen is significantly larger than
+// connectionRequestQueueSize then it is possible for ALL calls into the *DB
+// to block until the connectionOpener can satify the backlog of requests.
+var connectionRequestQueueSize = 1000000
+
// Open opens a database specified by its database driver name and a
// driver-specific data source name, usually consisting of at least a
// database name and connection information.
@@ -391,10 +426,14 @@ func Open(driverName, dataSourceName string) (*DB, error) {
return nil, fmt.Errorf("sql: unknown driver %q (forgotten import?)", driverName)
}
db := &DB{
- driver: driveri,
- dsn: dataSourceName,
- lastPut: make(map[*driverConn]string),
- }
+ driver: driveri,
+ dsn: dataSourceName,
+ openerCh: make(chan struct{}, connectionRequestQueueSize),
+ lastPut: make(map[*driverConn]string),
+ }
+ db.freeConn = list.New()
+ db.connRequests = list.New()
+ go db.connectionOpener()
return db, nil
}
@@ -415,16 +454,32 @@ func (db *DB) Ping() error {
// Close closes the database, releasing any open resources.
func (db *DB) Close() error {
db.mu.Lock()
- defer db.mu.Unlock()
+ if db.closed { // Make DB.Close idempotent
+ db.mu.Unlock()
+ return nil
+ }
+ close(db.openerCh)
var err error
- for _, dc := range db.freeConn {
- err1 := dc.closeDBLocked()
+ fns := make([]func() error, 0, db.freeConn.Len())
+ for db.freeConn.Front() != nil {
+ dc := db.freeConn.Front().Value.(*driverConn)
+ dc.listElem = nil
+ fns = append(fns, dc.closeDBLocked())
+ db.freeConn.Remove(db.freeConn.Front())
+ }
+ db.closed = true
+ for db.connRequests.Front() != nil {
+ req := db.connRequests.Front().Value.(connRequest)
+ db.connRequests.Remove(db.connRequests.Front())
+ close(req)
+ }
+ db.mu.Unlock()
+ for _, fn := range fns {
+ err1 := fn()
if err1 != nil {
err = err1
}
}
- db.freeConn = nil
- db.closed = true
return err
}
@@ -446,50 +501,168 @@ func (db *DB) maxIdleConnsLocked() int {
// SetMaxIdleConns sets the maximum number of connections in the idle
// connection pool.
//
+// If MaxOpenConns is greater than 0 but less than the new MaxIdleConns
+// then the new MaxIdleConns will be reduced to match the MaxOpenConns limit
+//
// If n <= 0, no idle connections are retained.
func (db *DB) SetMaxIdleConns(n int) {
db.mu.Lock()
- defer db.mu.Unlock()
if n > 0 {
db.maxIdle = n
} else {
// No idle connections.
db.maxIdle = -1
}
- for len(db.freeConn) > 0 && len(db.freeConn) > n {
- nfree := len(db.freeConn)
- dc := db.freeConn[nfree-1]
- db.freeConn[nfree-1] = nil
- db.freeConn = db.freeConn[:nfree-1]
- go dc.Close()
+ // Make sure maxIdle doesn't exceed maxOpen
+ if db.maxOpen > 0 && db.maxIdleConnsLocked() > db.maxOpen {
+ db.maxIdle = db.maxOpen
+ }
+ var closing []*driverConn
+ for db.freeConn.Len() > db.maxIdleConnsLocked() {
+ dc := db.freeConn.Back().Value.(*driverConn)
+ dc.listElem = nil
+ db.freeConn.Remove(db.freeConn.Back())
+ closing = append(closing, dc)
+ }
+ db.mu.Unlock()
+ for _, c := range closing {
+ c.Close()
}
}
+// SetMaxOpenConns sets the maximum number of open connections to the database.
+//
+// If MaxIdleConns is greater than 0 and the new MaxOpenConns is less than
+// MaxIdleConns, then MaxIdleConns will be reduced to match the new
+// MaxOpenConns limit
+//
+// If n <= 0, then there is no limit on the number of open connections.
+// The default is 0 (unlimited).
+func (db *DB) SetMaxOpenConns(n int) {
+ db.mu.Lock()
+ db.maxOpen = n
+ if n < 0 {
+ db.maxOpen = 0
+ }
+ syncMaxIdle := db.maxOpen > 0 && db.maxIdleConnsLocked() > db.maxOpen
+ db.mu.Unlock()
+ if syncMaxIdle {
+ db.SetMaxIdleConns(n)
+ }
+}
+
+// Assumes db.mu is locked.
+// If there are connRequests and the connection limit hasn't been reached,
+// then tell the connectionOpener to open new connections.
+func (db *DB) maybeOpenNewConnections() {
+ numRequests := db.connRequests.Len() - db.pendingOpens
+ if db.maxOpen > 0 {
+ numCanOpen := db.maxOpen - (db.numOpen + db.pendingOpens)
+ if numRequests > numCanOpen {
+ numRequests = numCanOpen
+ }
+ }
+ for numRequests > 0 {
+ db.pendingOpens++
+ numRequests--
+ db.openerCh <- struct{}{}
+ }
+}
+
+// Runs in a seperate goroutine, opens new connections when requested.
+func (db *DB) connectionOpener() {
+ for _ = range db.openerCh {
+ db.openNewConnection()
+ }
+}
+
+// Open one new connection
+func (db *DB) openNewConnection() {
+ ci, err := db.driver.Open(db.dsn)
+ db.mu.Lock()
+ defer db.mu.Unlock()
+ if db.closed {
+ if err == nil {
+ ci.Close()
+ }
+ return
+ }
+ db.pendingOpens--
+ if err != nil {
+ db.putConnDBLocked(nil, err)
+ return
+ }
+ dc := &driverConn{
+ db: db,
+ ci: ci,
+ }
+ if db.putConnDBLocked(dc, err) {
+ db.addDepLocked(dc, dc)
+ db.numOpen++
+ } else {
+ ci.Close()
+ }
+}
+
+// connRequest represents one request for a new connection
+// When there are no idle connections available, DB.conn will create
+// a new connRequest and put it on the db.connRequests list.
+type connRequest chan<- interface{} // takes either a *driverConn or an error
+
+var errDBClosed = errors.New("sql: database is closed")
+
// conn returns a newly-opened or cached *driverConn
func (db *DB) conn() (*driverConn, error) {
db.mu.Lock()
if db.closed {
db.mu.Unlock()
- return nil, errors.New("sql: database is closed")
+ return nil, errDBClosed
+ }
+
+ // If db.maxOpen > 0 and the number of open connections is over the limit
+ // or there are no free connection, then make a request and wait.
+ if db.maxOpen > 0 && (db.numOpen >= db.maxOpen || db.freeConn.Len() == 0) {
+ // Make the connRequest channel. It's buffered so that the
+ // connectionOpener doesn't block while waiting for the req to be read.
+ ch := make(chan interface{}, 1)
+ req := connRequest(ch)
+ db.connRequests.PushBack(req)
+ db.maybeOpenNewConnections()
+ db.mu.Unlock()
+ ret, ok := <-ch
+ if !ok {
+ return nil, errDBClosed
+ }
+ switch ret.(type) {
+ case *driverConn:
+ return ret.(*driverConn), nil
+ case error:
+ return nil, ret.(error)
+ default:
+ panic("sql: Unexpected type passed through connRequest.ch")
+ }
}
- if n := len(db.freeConn); n > 0 {
- conn := db.freeConn[n-1]
- db.freeConn = db.freeConn[:n-1]
+
+ if f := db.freeConn.Front(); f != nil {
+ conn := f.Value.(*driverConn)
+ conn.listElem = nil
+ db.freeConn.Remove(f)
conn.inUse = true
db.mu.Unlock()
return conn, nil
}
- db.mu.Unlock()
+ db.mu.Unlock()
ci, err := db.driver.Open(db.dsn)
if err != nil {
return nil, err
}
+ db.mu.Lock()
+ db.numOpen++
dc := &driverConn{
db: db,
ci: ci,
}
- db.mu.Lock()
db.addDepLocked(dc, dc)
dc.inUse = true
db.mu.Unlock()
@@ -511,18 +684,15 @@ var (
func (db *DB) connIfFree(wanted *driverConn) (*driverConn, error) {
db.mu.Lock()
defer db.mu.Unlock()
- if wanted.inUse {
- return nil, errConnBusy
- }
if wanted.dbmuClosed {
return nil, errConnClosed
}
- for i, conn := range db.freeConn {
- if conn != wanted {
- continue
- }
- db.freeConn[i] = db.freeConn[len(db.freeConn)-1]
- db.freeConn = db.freeConn[:len(db.freeConn)-1]
+ if wanted.inUse {
+ return nil, errConnBusy
+ }
+ if wanted.listElem != nil {
+ db.freeConn.Remove(wanted.listElem)
+ wanted.listElem = nil
wanted.inUse = true
return wanted, nil
}
@@ -582,20 +752,50 @@ func (db *DB) putConn(dc *driverConn, err error) {
if err == driver.ErrBadConn {
// Don't reuse bad connections.
+ // Since the conn is considered bad and is being discarded, treat it
+ // as closed. Don't decrement the open count here, finalClose will
+ // take care of that.
+ db.maybeOpenNewConnections()
db.mu.Unlock()
+ dc.Close()
return
}
if putConnHook != nil {
putConnHook(db, dc)
}
- if n := len(db.freeConn); !db.closed && n < db.maxIdleConnsLocked() {
- db.freeConn = append(db.freeConn, dc)
- db.mu.Unlock()
- return
- }
+ added := db.putConnDBLocked(dc, nil)
db.mu.Unlock()
- dc.Close()
+ if !added {
+ dc.Close()
+ }
+}
+
+// Satisfy a connRequest or put the driverConn in the idle pool and return true
+// or return false.
+// putConnDBLocked will satisfy a connRequest if there is one, or it will
+// return the *driverConn to the freeConn list if err != nil and the idle
+// connection limit would not be reached.
+// If err != nil, the value of dc is ignored.
+// If err == nil, then dc must not equal nil.
+// If a connRequest was fullfilled or the *driverConn was placed in the
+// freeConn list, then true is returned, otherwise false is returned.
+func (db *DB) putConnDBLocked(dc *driverConn, err error) bool {
+ if db.connRequests.Len() > 0 {
+ req := db.connRequests.Front().Value.(connRequest)
+ db.connRequests.Remove(db.connRequests.Front())
+ if err != nil {
+ req <- err
+ } else {
+ dc.inUse = true
+ req <- dc
+ }
+ return true
+ } else if err == nil && !db.closed && db.maxIdleConnsLocked() > 0 && db.maxIdleConnsLocked() > db.freeConn.Len() {
+ dc.listElem = db.freeConn.PushFront(dc)
+ return true
+ }
+ return false
}
// Prepare creates a prepared statement for later queries or executions.
@@ -710,9 +910,7 @@ func (db *DB) query(query string, args []interface{}) (*Rows, error) {
return nil, err
}
- releaseConn := func(err error) { db.putConn(ci, err) }
-
- return db.queryConn(ci, releaseConn, query, args)
+ return db.queryConn(ci, ci.releaseConn, query, args)
}
// queryConn executes a query on the given connection.
@@ -754,10 +952,10 @@ func (db *DB) queryConn(dc *driverConn, releaseConn func(error), query string, a
ds := driverStmt{dc, si}
rowsi, err := rowsiFromStatement(ds, args...)
if err != nil {
- releaseConn(err)
dc.Lock()
si.Close()
dc.Unlock()
+ releaseConn(err)
return nil, err
}
@@ -1154,8 +1352,7 @@ func (s *Stmt) connStmt() (ci *driverConn, releaseConn func(error), si driver.St
}
conn := cs.dc
- releaseConn = func(err error) { s.db.putConn(conn, err) }
- return conn, releaseConn, cs.si, nil
+ return conn, conn.releaseConn, cs.si, nil
}
// Query executes a prepared query statement with the given arguments
@@ -1245,27 +1442,32 @@ func (s *Stmt) Close() error {
return s.stickyErr
}
s.mu.Lock()
- defer s.mu.Unlock()
if s.closed {
+ s.mu.Unlock()
return nil
}
s.closed = true
if s.tx != nil {
s.txsi.Close()
+ s.mu.Unlock()
return nil
}
+ s.mu.Unlock()
return s.db.removeDep(s, s)
}
func (s *Stmt) finalClose() error {
- for _, v := range s.css {
- s.db.noteUnusedDriverStatement(v.dc, v.si)
- v.dc.removeOpenStmt(v.si)
- s.db.removeDep(v.dc, s)
+ s.mu.Lock()
+ defer s.mu.Unlock()
+ if s.css != nil {
+ for _, v := range s.css {
+ s.db.noteUnusedDriverStatement(v.dc, v.si)
+ v.dc.removeOpenStmt(v.si)
+ }
+ s.css = nil
}
- s.css = nil
return nil
}
@@ -1289,7 +1491,7 @@ type Rows struct {
closed bool
lastcols []driver.Value
- lasterr error
+ lasterr error // non-nil only if closed is true
closeStmt driver.Stmt // if non-nil, statement to Close on close
}
@@ -1301,20 +1503,19 @@ func (rs *Rows) Next() bool {
if rs.closed {
return false
}
- if rs.lasterr != nil {
- return false
- }
if rs.lastcols == nil {
rs.lastcols = make([]driver.Value, len(rs.rowsi.Columns()))
}
rs.lasterr = rs.rowsi.Next(rs.lastcols)
- if rs.lasterr == io.EOF {
+ if rs.lasterr != nil {
rs.Close()
+ return false
}
- return rs.lasterr == nil
+ return true
}
// Err returns the error, if any, that was encountered during iteration.
+// Err may be called after an explicit or implicit Close.
func (rs *Rows) Err() error {
if rs.lasterr == io.EOF {
return nil
@@ -1349,10 +1550,7 @@ func (rs *Rows) Columns() ([]string, error) {
// is of type []byte, a copy is made and the caller owns the result.
func (rs *Rows) Scan(dest ...interface{}) error {
if rs.closed {
- return errors.New("sql: Rows closed")
- }
- if rs.lasterr != nil {
- return rs.lasterr
+ return errors.New("sql: Rows are closed")
}
if rs.lastcols == nil {
return errors.New("sql: Scan called without calling Next")
@@ -1369,15 +1567,20 @@ func (rs *Rows) Scan(dest ...interface{}) error {
return nil
}
-// Close closes the Rows, preventing further enumeration. If the
-// end is encountered, the Rows are closed automatically. Close
-// is idempotent.
+var rowsCloseHook func(*Rows, *error)
+
+// Close closes the Rows, preventing further enumeration. If Next returns
+// false, the Rows are closed automatically and it will suffice to check the
+// result of Err. Close is idempotent and does not affect the result of Err.
func (rs *Rows) Close() error {
if rs.closed {
return nil
}
rs.closed = true
err := rs.rowsi.Close()
+ if fn := rowsCloseHook; fn != nil {
+ fn(rs, &err)
+ }
if rs.closeStmt != nil {
rs.closeStmt.Close()
}
@@ -1414,13 +1617,13 @@ func (r *Row) Scan(dest ...interface{}) error {
// from Next will not be modified again." (for instance, if
// they were obtained from the network anyway) But for now we
// don't care.
+ defer r.rows.Close()
for _, dp := range dest {
if _, ok := dp.(*RawBytes); ok {
return errors.New("sql: RawBytes isn't allowed on Row.Scan")
}
}
- defer r.rows.Close()
if !r.rows.Next() {
return ErrNoRows
}
diff --git a/libgo/go/database/sql/sql_test.go b/libgo/go/database/sql/sql_test.go
index e6cc667fa97..093c0d64cac 100644
--- a/libgo/go/database/sql/sql_test.go
+++ b/libgo/go/database/sql/sql_test.go
@@ -5,7 +5,10 @@
package sql
import (
+ "database/sql/driver"
+ "errors"
"fmt"
+ "math/rand"
"reflect"
"runtime"
"strings"
@@ -21,14 +24,12 @@ func init() {
}
freedFrom := make(map[dbConn]string)
putConnHook = func(db *DB, c *driverConn) {
- for _, oc := range db.freeConn {
- if oc == c {
- // print before panic, as panic may get lost due to conflicting panic
- // (all goroutines asleep) elsewhere, since we might not unlock
- // the mutex in freeConn here.
- println("double free of conn. conflicts are:\nA) " + freedFrom[dbConn{db, c}] + "\n\nand\nB) " + stack())
- panic("double free of conn.")
- }
+ if c.listElem != nil {
+ // print before panic, as panic may get lost due to conflicting panic
+ // (all goroutines asleep) elsewhere, since we might not unlock
+ // the mutex in freeConn here.
+ println("double free of conn. conflicts are:\nA) " + freedFrom[dbConn{db, c}] + "\n\nand\nB) " + stack())
+ panic("double free of conn.")
}
freedFrom[dbConn{db, c}] = stack()
}
@@ -38,15 +39,7 @@ const fakeDBName = "foo"
var chrisBirthday = time.Unix(123456789, 0)
-type testOrBench interface {
- Fatalf(string, ...interface{})
- Errorf(string, ...interface{})
- Fatal(...interface{})
- Error(...interface{})
- Logf(string, ...interface{})
-}
-
-func newTestDB(t testOrBench, name string) *DB {
+func newTestDB(t testing.TB, name string) *DB {
db, err := Open("test", fakeDBName)
if err != nil {
t.Fatalf("Open: %v", err)
@@ -68,14 +61,14 @@ func newTestDB(t testOrBench, name string) *DB {
return db
}
-func exec(t testOrBench, db *DB, query string, args ...interface{}) {
+func exec(t testing.TB, db *DB, query string, args ...interface{}) {
_, err := db.Exec(query, args...)
if err != nil {
t.Fatalf("Exec of %q: %v", query, err)
}
}
-func closeDB(t testOrBench, db *DB) {
+func closeDB(t testing.TB, db *DB) {
if e := recover(); e != nil {
fmt.Printf("Panic: %v\n", e)
panic(e)
@@ -86,29 +79,36 @@ func closeDB(t testOrBench, db *DB) {
t.Errorf("Error closing fakeConn: %v", err)
}
})
- for i, dc := range db.freeConn {
+ for node, i := db.freeConn.Front(), 0; node != nil; node, i = node.Next(), i+1 {
+ dc := node.Value.(*driverConn)
if n := len(dc.openStmt); n > 0 {
// Just a sanity check. This is legal in
// general, but if we make the tests clean up
// their statements first, then we can safely
// verify this is always zero here, and any
// other value is a leak.
- t.Errorf("while closing db, freeConn %d/%d had %d open stmts; want 0", i, len(db.freeConn), n)
+ t.Errorf("while closing db, freeConn %d/%d had %d open stmts; want 0", i, db.freeConn.Len(), n)
}
}
err := db.Close()
if err != nil {
t.Fatalf("error closing DB: %v", err)
}
+ db.mu.Lock()
+ count := db.numOpen
+ db.mu.Unlock()
+ if count != 0 {
+ t.Fatalf("%d connections still open after closing DB", db.numOpen)
+ }
}
// numPrepares assumes that db has exactly 1 idle conn and returns
// its count of calls to Prepare
func numPrepares(t *testing.T, db *DB) int {
- if n := len(db.freeConn); n != 1 {
+ if n := db.freeConn.Len(); n != 1 {
t.Fatalf("free conns = %d; want 1", n)
}
- return db.freeConn[0].ci.(*fakeConn).numPrepare
+ return (db.freeConn.Front().Value.(*driverConn)).ci.(*fakeConn).numPrepare
}
func (db *DB) numDeps() int {
@@ -133,7 +133,7 @@ func (db *DB) numDepsPollUntil(want int, d time.Duration) int {
func (db *DB) numFreeConns() int {
db.mu.Lock()
defer db.mu.Unlock()
- return len(db.freeConn)
+ return db.freeConn.Len()
}
func (db *DB) dumpDeps(t *testing.T) {
@@ -252,6 +252,9 @@ func TestRowsColumns(t *testing.T) {
if !reflect.DeepEqual(cols, want) {
t.Errorf("got %#v; want %#v", cols, want)
}
+ if err := rows.Close(); err != nil {
+ t.Errorf("error closing rows: %s", err)
+ }
}
func TestQueryRow(t *testing.T) {
@@ -648,10 +651,10 @@ func TestQueryRowClosingStmt(t *testing.T) {
if err != nil {
t.Fatal(err)
}
- if len(db.freeConn) != 1 {
+ if db.freeConn.Len() != 1 {
t.Fatalf("expected 1 free conn")
}
- fakeConn := db.freeConn[0].ci.(*fakeConn)
+ fakeConn := (db.freeConn.Front().Value.(*driverConn)).ci.(*fakeConn)
if made, closed := fakeConn.stmtsMade, fakeConn.stmtsClosed; made != closed {
t.Errorf("statement close mismatch: made %d, closed %d", made, closed)
}
@@ -847,13 +850,13 @@ func TestMaxIdleConns(t *testing.T) {
t.Fatal(err)
}
tx.Commit()
- if got := len(db.freeConn); got != 1 {
+ if got := db.freeConn.Len(); got != 1 {
t.Errorf("freeConns = %d; want 1", got)
}
db.SetMaxIdleConns(0)
- if got := len(db.freeConn); got != 0 {
+ if got := db.freeConn.Len(); got != 0 {
t.Errorf("freeConns after set to zero = %d; want 0", got)
}
@@ -862,11 +865,146 @@ func TestMaxIdleConns(t *testing.T) {
t.Fatal(err)
}
tx.Commit()
- if got := len(db.freeConn); got != 0 {
+ if got := db.freeConn.Len(); got != 0 {
t.Errorf("freeConns = %d; want 0", got)
}
}
+func TestMaxOpenConns(t *testing.T) {
+ if testing.Short() {
+ t.Skip("skipping in short mode")
+ }
+ defer setHookpostCloseConn(nil)
+ setHookpostCloseConn(func(_ *fakeConn, err error) {
+ if err != nil {
+ t.Errorf("Error closing fakeConn: %v", err)
+ }
+ })
+
+ db := newTestDB(t, "magicquery")
+ defer closeDB(t, db)
+
+ driver := db.driver.(*fakeDriver)
+
+ // Force the number of open connections to 0 so we can get an accurate
+ // count for the test
+ db.SetMaxIdleConns(0)
+
+ if g, w := db.numFreeConns(), 0; g != w {
+ t.Errorf("free conns = %d; want %d", g, w)
+ }
+
+ if n := db.numDepsPollUntil(0, time.Second); n > 0 {
+ t.Errorf("number of dependencies = %d; expected 0", n)
+ db.dumpDeps(t)
+ }
+
+ driver.mu.Lock()
+ opens0 := driver.openCount
+ closes0 := driver.closeCount
+ driver.mu.Unlock()
+
+ db.SetMaxIdleConns(10)
+ db.SetMaxOpenConns(10)
+
+ stmt, err := db.Prepare("SELECT|magicquery|op|op=?,millis=?")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // Start 50 parallel slow queries.
+ const (
+ nquery = 50
+ sleepMillis = 25
+ nbatch = 2
+ )
+ var wg sync.WaitGroup
+ for batch := 0; batch < nbatch; batch++ {
+ for i := 0; i < nquery; i++ {
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ var op string
+ if err := stmt.QueryRow("sleep", sleepMillis).Scan(&op); err != nil && err != ErrNoRows {
+ t.Error(err)
+ }
+ }()
+ }
+ // Sleep for twice the expected length of time for the
+ // batch of 50 queries above to finish before starting
+ // the next round.
+ time.Sleep(2 * sleepMillis * time.Millisecond)
+ }
+ wg.Wait()
+
+ if g, w := db.numFreeConns(), 10; g != w {
+ t.Errorf("free conns = %d; want %d", g, w)
+ }
+
+ if n := db.numDepsPollUntil(20, time.Second); n > 20 {
+ t.Errorf("number of dependencies = %d; expected <= 20", n)
+ db.dumpDeps(t)
+ }
+
+ driver.mu.Lock()
+ opens := driver.openCount - opens0
+ closes := driver.closeCount - closes0
+ driver.mu.Unlock()
+
+ if opens > 10 {
+ t.Logf("open calls = %d", opens)
+ t.Logf("close calls = %d", closes)
+ t.Errorf("db connections opened = %d; want <= 10", opens)
+ db.dumpDeps(t)
+ }
+
+ if err := stmt.Close(); err != nil {
+ t.Fatal(err)
+ }
+
+ if g, w := db.numFreeConns(), 10; g != w {
+ t.Errorf("free conns = %d; want %d", g, w)
+ }
+
+ if n := db.numDepsPollUntil(10, time.Second); n > 10 {
+ t.Errorf("number of dependencies = %d; expected <= 10", n)
+ db.dumpDeps(t)
+ }
+
+ db.SetMaxOpenConns(5)
+
+ if g, w := db.numFreeConns(), 5; g != w {
+ t.Errorf("free conns = %d; want %d", g, w)
+ }
+
+ if n := db.numDepsPollUntil(5, time.Second); n > 5 {
+ t.Errorf("number of dependencies = %d; expected 0", n)
+ db.dumpDeps(t)
+ }
+
+ db.SetMaxOpenConns(0)
+
+ if g, w := db.numFreeConns(), 5; g != w {
+ t.Errorf("free conns = %d; want %d", g, w)
+ }
+
+ if n := db.numDepsPollUntil(5, time.Second); n > 5 {
+ t.Errorf("number of dependencies = %d; expected 0", n)
+ db.dumpDeps(t)
+ }
+
+ db.SetMaxIdleConns(0)
+
+ if g, w := db.numFreeConns(), 0; g != w {
+ t.Errorf("free conns = %d; want %d", g, w)
+ }
+
+ if n := db.numDepsPollUntil(0, time.Second); n > 0 {
+ t.Errorf("number of dependencies = %d; expected 0", n)
+ db.dumpDeps(t)
+ }
+}
+
// golang.org/issue/5323
func TestStmtCloseDeps(t *testing.T) {
if testing.Short() {
@@ -932,8 +1070,8 @@ func TestStmtCloseDeps(t *testing.T) {
driver.mu.Lock()
opens := driver.openCount - opens0
closes := driver.closeCount - closes0
- driver.mu.Unlock()
openDelta := (driver.openCount - driver.closeCount) - openDelta0
+ driver.mu.Unlock()
if openDelta > 2 {
t.Logf("open calls = %d", opens)
@@ -991,10 +1129,10 @@ func TestCloseConnBeforeStmts(t *testing.T) {
t.Fatal(err)
}
- if len(db.freeConn) != 1 {
- t.Fatalf("expected 1 freeConn; got %d", len(db.freeConn))
+ if db.freeConn.Len() != 1 {
+ t.Fatalf("expected 1 freeConn; got %d", db.freeConn.Len())
}
- dc := db.freeConn[0]
+ dc := db.freeConn.Front().Value.(*driverConn)
if dc.closed {
t.Errorf("conn shouldn't be closed")
}
@@ -1046,7 +1184,393 @@ func TestRowsCloseOrder(t *testing.T) {
}
}
-func manyConcurrentQueries(t testOrBench) {
+func TestRowsImplicitClose(t *testing.T) {
+ db := newTestDB(t, "people")
+ defer closeDB(t, db)
+
+ rows, err := db.Query("SELECT|people|age,name|")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ want, fail := 2, errors.New("fail")
+ r := rows.rowsi.(*rowsCursor)
+ r.errPos, r.err = want, fail
+
+ got := 0
+ for rows.Next() {
+ got++
+ }
+ if got != want {
+ t.Errorf("got %d rows, want %d", got, want)
+ }
+ if err := rows.Err(); err != fail {
+ t.Errorf("got error %v, want %v", err, fail)
+ }
+ if !r.closed {
+ t.Errorf("r.closed is false, want true")
+ }
+}
+
+func TestStmtCloseOrder(t *testing.T) {
+ db := newTestDB(t, "people")
+ defer closeDB(t, db)
+
+ db.SetMaxIdleConns(0)
+ setStrictFakeConnClose(t)
+ defer setStrictFakeConnClose(nil)
+
+ _, err := db.Query("SELECT|non_existent|name|")
+ if err == nil {
+ t.Fatal("Quering non-existent table should fail")
+ }
+}
+
+type concurrentTest interface {
+ init(t testing.TB, db *DB)
+ finish(t testing.TB)
+ test(t testing.TB) error
+}
+
+type concurrentDBQueryTest struct {
+ db *DB
+}
+
+func (c *concurrentDBQueryTest) init(t testing.TB, db *DB) {
+ c.db = db
+}
+
+func (c *concurrentDBQueryTest) finish(t testing.TB) {
+ c.db = nil
+}
+
+func (c *concurrentDBQueryTest) test(t testing.TB) error {
+ rows, err := c.db.Query("SELECT|people|name|")
+ if err != nil {
+ t.Error(err)
+ return err
+ }
+ var name string
+ for rows.Next() {
+ rows.Scan(&name)
+ }
+ rows.Close()
+ return nil
+}
+
+type concurrentDBExecTest struct {
+ db *DB
+}
+
+func (c *concurrentDBExecTest) init(t testing.TB, db *DB) {
+ c.db = db
+}
+
+func (c *concurrentDBExecTest) finish(t testing.TB) {
+ c.db = nil
+}
+
+func (c *concurrentDBExecTest) test(t testing.TB) error {
+ _, err := c.db.Exec("NOSERT|people|name=Chris,age=?,photo=CPHOTO,bdate=?", 3, chrisBirthday)
+ if err != nil {
+ t.Error(err)
+ return err
+ }
+ return nil
+}
+
+type concurrentStmtQueryTest struct {
+ db *DB
+ stmt *Stmt
+}
+
+func (c *concurrentStmtQueryTest) init(t testing.TB, db *DB) {
+ c.db = db
+ var err error
+ c.stmt, err = db.Prepare("SELECT|people|name|")
+ if err != nil {
+ t.Fatal(err)
+ }
+}
+
+func (c *concurrentStmtQueryTest) finish(t testing.TB) {
+ if c.stmt != nil {
+ c.stmt.Close()
+ c.stmt = nil
+ }
+ c.db = nil
+}
+
+func (c *concurrentStmtQueryTest) test(t testing.TB) error {
+ rows, err := c.stmt.Query()
+ if err != nil {
+ t.Errorf("error on query: %v", err)
+ return err
+ }
+
+ var name string
+ for rows.Next() {
+ rows.Scan(&name)
+ }
+ rows.Close()
+ return nil
+}
+
+type concurrentStmtExecTest struct {
+ db *DB
+ stmt *Stmt
+}
+
+func (c *concurrentStmtExecTest) init(t testing.TB, db *DB) {
+ c.db = db
+ var err error
+ c.stmt, err = db.Prepare("NOSERT|people|name=Chris,age=?,photo=CPHOTO,bdate=?")
+ if err != nil {
+ t.Fatal(err)
+ }
+}
+
+func (c *concurrentStmtExecTest) finish(t testing.TB) {
+ if c.stmt != nil {
+ c.stmt.Close()
+ c.stmt = nil
+ }
+ c.db = nil
+}
+
+func (c *concurrentStmtExecTest) test(t testing.TB) error {
+ _, err := c.stmt.Exec(3, chrisBirthday)
+ if err != nil {
+ t.Errorf("error on exec: %v", err)
+ return err
+ }
+ return nil
+}
+
+type concurrentTxQueryTest struct {
+ db *DB
+ tx *Tx
+}
+
+func (c *concurrentTxQueryTest) init(t testing.TB, db *DB) {
+ c.db = db
+ var err error
+ c.tx, err = c.db.Begin()
+ if err != nil {
+ t.Fatal(err)
+ }
+}
+
+func (c *concurrentTxQueryTest) finish(t testing.TB) {
+ if c.tx != nil {
+ c.tx.Rollback()
+ c.tx = nil
+ }
+ c.db = nil
+}
+
+func (c *concurrentTxQueryTest) test(t testing.TB) error {
+ rows, err := c.db.Query("SELECT|people|name|")
+ if err != nil {
+ t.Error(err)
+ return err
+ }
+ var name string
+ for rows.Next() {
+ rows.Scan(&name)
+ }
+ rows.Close()
+ return nil
+}
+
+type concurrentTxExecTest struct {
+ db *DB
+ tx *Tx
+}
+
+func (c *concurrentTxExecTest) init(t testing.TB, db *DB) {
+ c.db = db
+ var err error
+ c.tx, err = c.db.Begin()
+ if err != nil {
+ t.Fatal(err)
+ }
+}
+
+func (c *concurrentTxExecTest) finish(t testing.TB) {
+ if c.tx != nil {
+ c.tx.Rollback()
+ c.tx = nil
+ }
+ c.db = nil
+}
+
+func (c *concurrentTxExecTest) test(t testing.TB) error {
+ _, err := c.tx.Exec("NOSERT|people|name=Chris,age=?,photo=CPHOTO,bdate=?", 3, chrisBirthday)
+ if err != nil {
+ t.Error(err)
+ return err
+ }
+ return nil
+}
+
+type concurrentTxStmtQueryTest struct {
+ db *DB
+ tx *Tx
+ stmt *Stmt
+}
+
+func (c *concurrentTxStmtQueryTest) init(t testing.TB, db *DB) {
+ c.db = db
+ var err error
+ c.tx, err = c.db.Begin()
+ if err != nil {
+ t.Fatal(err)
+ }
+ c.stmt, err = c.tx.Prepare("SELECT|people|name|")
+ if err != nil {
+ t.Fatal(err)
+ }
+}
+
+func (c *concurrentTxStmtQueryTest) finish(t testing.TB) {
+ if c.stmt != nil {
+ c.stmt.Close()
+ c.stmt = nil
+ }
+ if c.tx != nil {
+ c.tx.Rollback()
+ c.tx = nil
+ }
+ c.db = nil
+}
+
+func (c *concurrentTxStmtQueryTest) test(t testing.TB) error {
+ rows, err := c.stmt.Query()
+ if err != nil {
+ t.Errorf("error on query: %v", err)
+ return err
+ }
+
+ var name string
+ for rows.Next() {
+ rows.Scan(&name)
+ }
+ rows.Close()
+ return nil
+}
+
+type concurrentTxStmtExecTest struct {
+ db *DB
+ tx *Tx
+ stmt *Stmt
+}
+
+func (c *concurrentTxStmtExecTest) init(t testing.TB, db *DB) {
+ c.db = db
+ var err error
+ c.tx, err = c.db.Begin()
+ if err != nil {
+ t.Fatal(err)
+ }
+ c.stmt, err = c.tx.Prepare("NOSERT|people|name=Chris,age=?,photo=CPHOTO,bdate=?")
+ if err != nil {
+ t.Fatal(err)
+ }
+}
+
+func (c *concurrentTxStmtExecTest) finish(t testing.TB) {
+ if c.stmt != nil {
+ c.stmt.Close()
+ c.stmt = nil
+ }
+ if c.tx != nil {
+ c.tx.Rollback()
+ c.tx = nil
+ }
+ c.db = nil
+}
+
+func (c *concurrentTxStmtExecTest) test(t testing.TB) error {
+ _, err := c.stmt.Exec(3, chrisBirthday)
+ if err != nil {
+ t.Errorf("error on exec: %v", err)
+ return err
+ }
+ return nil
+}
+
+type concurrentRandomTest struct {
+ tests []concurrentTest
+}
+
+func (c *concurrentRandomTest) init(t testing.TB, db *DB) {
+ c.tests = []concurrentTest{
+ new(concurrentDBQueryTest),
+ new(concurrentDBExecTest),
+ new(concurrentStmtQueryTest),
+ new(concurrentStmtExecTest),
+ new(concurrentTxQueryTest),
+ new(concurrentTxExecTest),
+ new(concurrentTxStmtQueryTest),
+ new(concurrentTxStmtExecTest),
+ }
+ for _, ct := range c.tests {
+ ct.init(t, db)
+ }
+}
+
+func (c *concurrentRandomTest) finish(t testing.TB) {
+ for _, ct := range c.tests {
+ ct.finish(t)
+ }
+}
+
+func (c *concurrentRandomTest) test(t testing.TB) error {
+ ct := c.tests[rand.Intn(len(c.tests))]
+ return ct.test(t)
+}
+
+func doConcurrentTest(t testing.TB, ct concurrentTest) {
+ maxProcs, numReqs := 1, 500
+ if testing.Short() {
+ maxProcs, numReqs = 4, 50
+ }
+ defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(maxProcs))
+
+ db := newTestDB(t, "people")
+ defer closeDB(t, db)
+
+ ct.init(t, db)
+ defer ct.finish(t)
+
+ var wg sync.WaitGroup
+ wg.Add(numReqs)
+
+ reqs := make(chan bool)
+ defer close(reqs)
+
+ for i := 0; i < maxProcs*2; i++ {
+ go func() {
+ for _ = range reqs {
+ err := ct.test(t)
+ if err != nil {
+ wg.Done()
+ continue
+ }
+ wg.Done()
+ }
+ }()
+ }
+
+ for i := 0; i < numReqs; i++ {
+ reqs <- true
+ }
+
+ wg.Wait()
+}
+
+func manyConcurrentQueries(t testing.TB) {
maxProcs, numReqs := 16, 500
if testing.Short() {
maxProcs, numReqs = 4, 50
@@ -1096,13 +1620,174 @@ func manyConcurrentQueries(t testOrBench) {
wg.Wait()
}
+func TestIssue6081(t *testing.T) {
+ db := newTestDB(t, "people")
+ defer closeDB(t, db)
+
+ drv := db.driver.(*fakeDriver)
+ drv.mu.Lock()
+ opens0 := drv.openCount
+ closes0 := drv.closeCount
+ drv.mu.Unlock()
+
+ stmt, err := db.Prepare("SELECT|people|name|")
+ if err != nil {
+ t.Fatal(err)
+ }
+ rowsCloseHook = func(rows *Rows, err *error) {
+ *err = driver.ErrBadConn
+ }
+ defer func() { rowsCloseHook = nil }()
+ for i := 0; i < 10; i++ {
+ rows, err := stmt.Query()
+ if err != nil {
+ t.Fatal(err)
+ }
+ rows.Close()
+ }
+ if n := len(stmt.css); n > 1 {
+ t.Errorf("len(css slice) = %d; want <= 1", n)
+ }
+ stmt.Close()
+ if n := len(stmt.css); n != 0 {
+ t.Errorf("len(css slice) after Close = %d; want 0", n)
+ }
+
+ drv.mu.Lock()
+ opens := drv.openCount - opens0
+ closes := drv.closeCount - closes0
+ drv.mu.Unlock()
+ if opens < 9 {
+ t.Errorf("opens = %d; want >= 9", opens)
+ }
+ if closes < 9 {
+ t.Errorf("closes = %d; want >= 9", closes)
+ }
+}
+
func TestConcurrency(t *testing.T) {
- manyConcurrentQueries(t)
+ doConcurrentTest(t, new(concurrentDBQueryTest))
+ doConcurrentTest(t, new(concurrentDBExecTest))
+ doConcurrentTest(t, new(concurrentStmtQueryTest))
+ doConcurrentTest(t, new(concurrentStmtExecTest))
+ doConcurrentTest(t, new(concurrentTxQueryTest))
+ doConcurrentTest(t, new(concurrentTxExecTest))
+ doConcurrentTest(t, new(concurrentTxStmtQueryTest))
+ doConcurrentTest(t, new(concurrentTxStmtExecTest))
+ doConcurrentTest(t, new(concurrentRandomTest))
+}
+
+func TestConnectionLeak(t *testing.T) {
+ db := newTestDB(t, "people")
+ defer closeDB(t, db)
+ // Start by opening defaultMaxIdleConns
+ rows := make([]*Rows, defaultMaxIdleConns)
+ // We need to SetMaxOpenConns > MaxIdleConns, so the DB can open
+ // a new connection and we can fill the idle queue with the released
+ // connections.
+ db.SetMaxOpenConns(len(rows) + 1)
+ for ii := range rows {
+ r, err := db.Query("SELECT|people|name|")
+ if err != nil {
+ t.Fatal(err)
+ }
+ r.Next()
+ if err := r.Err(); err != nil {
+ t.Fatal(err)
+ }
+ rows[ii] = r
+ }
+ // Now we have defaultMaxIdleConns busy connections. Open
+ // a new one, but wait until the busy connections are released
+ // before returning control to DB.
+ drv := db.driver.(*fakeDriver)
+ drv.waitCh = make(chan struct{}, 1)
+ drv.waitingCh = make(chan struct{}, 1)
+ var wg sync.WaitGroup
+ wg.Add(1)
+ go func() {
+ r, err := db.Query("SELECT|people|name|")
+ if err != nil {
+ t.Fatal(err)
+ }
+ r.Close()
+ wg.Done()
+ }()
+ // Wait until the goroutine we've just created has started waiting.
+ <-drv.waitingCh
+ // Now close the busy connections. This provides a connection for
+ // the blocked goroutine and then fills up the idle queue.
+ for _, v := range rows {
+ v.Close()
+ }
+ // At this point we give the new connection to DB. This connection is
+ // now useless, since the idle queue is full and there are no pending
+ // requests. DB should deal with this situation without leaking the
+ // connection.
+ drv.waitCh <- struct{}{}
+ wg.Wait()
+}
+
+func BenchmarkConcurrentDBExec(b *testing.B) {
+ b.ReportAllocs()
+ ct := new(concurrentDBExecTest)
+ for i := 0; i < b.N; i++ {
+ doConcurrentTest(b, ct)
+ }
+}
+
+func BenchmarkConcurrentStmtQuery(b *testing.B) {
+ b.ReportAllocs()
+ ct := new(concurrentStmtQueryTest)
+ for i := 0; i < b.N; i++ {
+ doConcurrentTest(b, ct)
+ }
+}
+
+func BenchmarkConcurrentStmtExec(b *testing.B) {
+ b.ReportAllocs()
+ ct := new(concurrentStmtExecTest)
+ for i := 0; i < b.N; i++ {
+ doConcurrentTest(b, ct)
+ }
+}
+
+func BenchmarkConcurrentTxQuery(b *testing.B) {
+ b.ReportAllocs()
+ ct := new(concurrentTxQueryTest)
+ for i := 0; i < b.N; i++ {
+ doConcurrentTest(b, ct)
+ }
+}
+
+func BenchmarkConcurrentTxExec(b *testing.B) {
+ b.ReportAllocs()
+ ct := new(concurrentTxExecTest)
+ for i := 0; i < b.N; i++ {
+ doConcurrentTest(b, ct)
+ }
+}
+
+func BenchmarkConcurrentTxStmtQuery(b *testing.B) {
+ b.ReportAllocs()
+ ct := new(concurrentTxStmtQueryTest)
+ for i := 0; i < b.N; i++ {
+ doConcurrentTest(b, ct)
+ }
+}
+
+func BenchmarkConcurrentTxStmtExec(b *testing.B) {
+ b.ReportAllocs()
+ ct := new(concurrentTxStmtExecTest)
+ for i := 0; i < b.N; i++ {
+ doConcurrentTest(b, ct)
+ }
}
-func BenchmarkConcurrency(b *testing.B) {
+func BenchmarkConcurrentRandom(b *testing.B) {
b.ReportAllocs()
+ ct := new(concurrentRandomTest)
for i := 0; i < b.N; i++ {
- manyConcurrentQueries(b)
+ doConcurrentTest(b, ct)
}
}
diff --git a/libgo/go/debug/dwarf/entry.go b/libgo/go/debug/dwarf/entry.go
index ada723163a4..4775283ca3a 100644
--- a/libgo/go/debug/dwarf/entry.go
+++ b/libgo/go/debug/dwarf/entry.go
@@ -10,7 +10,10 @@
package dwarf
-import "errors"
+import (
+ "errors"
+ "strconv"
+)
// a single entry's description: a sequence of attributes
type abbrev struct {
@@ -152,7 +155,7 @@ func (b *buf) entry(atab abbrevTable, ubase Offset) *Entry {
var val interface{}
switch fmt {
default:
- b.error("unknown entry attr format")
+ b.error("unknown entry attr format 0x" + strconv.FormatInt(int64(fmt), 16))
// address
case formAddr:
diff --git a/libgo/go/debug/dwarf/type.go b/libgo/go/debug/dwarf/type.go
index 54000fbd75e..1fbae6c144e 100644
--- a/libgo/go/debug/dwarf/type.go
+++ b/libgo/go/debug/dwarf/type.go
@@ -271,24 +271,43 @@ func (d *Data) Type(off Offset) (Type, error) {
// d.Type recursively, to handle circular types correctly.
var typ Type
+ nextDepth := 0
+
// Get next child; set err if error happens.
next := func() *Entry {
if !e.Children {
return nil
}
- kid, err1 := r.Next()
- if err1 != nil {
- err = err1
- return nil
- }
- if kid == nil {
- err = DecodeError{"info", r.b.off, "unexpected end of DWARF entries"}
- return nil
- }
- if kid.Tag == 0 {
- return nil
+ // Only return direct children.
+ // Skip over composite entries that happen to be nested
+ // inside this one. Most DWARF generators wouldn't generate
+ // such a thing, but clang does.
+ // See golang.org/issue/6472.
+ for {
+ kid, err1 := r.Next()
+ if err1 != nil {
+ err = err1
+ return nil
+ }
+ if kid == nil {
+ err = DecodeError{"info", r.b.off, "unexpected end of DWARF entries"}
+ return nil
+ }
+ if kid.Tag == 0 {
+ if nextDepth > 0 {
+ nextDepth--
+ continue
+ }
+ return nil
+ }
+ if kid.Children {
+ nextDepth++
+ }
+ if nextDepth > 0 {
+ continue
+ }
+ return kid
}
- return kid
}
// Get Type referred to by Entry's AttrType field.
diff --git a/libgo/go/debug/elf/file_test.go b/libgo/go/debug/elf/file_test.go
index f9aa7265af0..38b5f9e7075 100644
--- a/libgo/go/debug/elf/file_test.go
+++ b/libgo/go/debug/elf/file_test.go
@@ -166,6 +166,7 @@ func TestOpen(t *testing.T) {
} else {
f, err = Open(tt.file)
}
+ defer f.Close()
if err != nil {
t.Errorf("cannot open file %s: %v", tt.file, err)
continue
diff --git a/libgo/go/debug/gosym/pclntab.go b/libgo/go/debug/gosym/pclntab.go
index 9d7b0d15f36..3e6a8046b3e 100644
--- a/libgo/go/debug/gosym/pclntab.go
+++ b/libgo/go/debug/gosym/pclntab.go
@@ -8,16 +8,47 @@
package gosym
-import "encoding/binary"
+import (
+ "encoding/binary"
+ "sync"
+)
+// A LineTable is a data structure mapping program counters to line numbers.
+//
+// In Go 1.1 and earlier, each function (represented by a Func) had its own LineTable,
+// and the line number corresponded to a numbering of all source lines in the
+// program, across all files. That absolute line number would then have to be
+// converted separately to a file name and line number within the file.
+//
+// In Go 1.2, the format of the data changed so that there is a single LineTable
+// for the entire program, shared by all Funcs, and there are no absolute line
+// numbers, just line numbers within specific files.
+//
+// For the most part, LineTable's methods should be treated as an internal
+// detail of the package; callers should use the methods on Table instead.
type LineTable struct {
Data []byte
PC uint64
Line int
+
+ // Go 1.2 state
+ mu sync.Mutex
+ go12 int // is this in Go 1.2 format? -1 no, 0 unknown, 1 yes
+ binary binary.ByteOrder
+ quantum uint32
+ ptrsize uint32
+ functab []byte
+ nfunctab uint32
+ filetab []byte
+ nfiletab uint32
+ fileMap map[string]uint32
}
-// TODO(rsc): Need to pull in quantum from architecture definition.
-const quantum = 1
+// NOTE(rsc): This is wrong for GOARCH=arm, which uses a quantum of 4,
+// but we have no idea whether we're using arm or not. This only
+// matters in the old (pre-Go 1.2) symbol table format, so it's not worth
+// fixing.
+const oldQuantum = 1
func (t *LineTable) parse(targetPC uint64, targetLine int) (b []byte, pc uint64, line int) {
// The PC/line table can be thought of as a sequence of
@@ -46,31 +77,42 @@ func (t *LineTable) parse(targetPC uint64, targetLine int) (b []byte, pc uint64,
case code <= 128:
line -= int(code - 64)
default:
- pc += quantum * uint64(code-128)
+ pc += oldQuantum * uint64(code-128)
continue
}
- pc += quantum
+ pc += oldQuantum
}
return b, pc, line
}
func (t *LineTable) slice(pc uint64) *LineTable {
data, pc, line := t.parse(pc, -1)
- return &LineTable{data, pc, line}
+ return &LineTable{Data: data, PC: pc, Line: line}
}
+// PCToLine returns the line number for the given program counter.
+// Callers should use Table's PCToLine method instead.
func (t *LineTable) PCToLine(pc uint64) int {
+ if t.isGo12() {
+ return t.go12PCToLine(pc)
+ }
_, _, line := t.parse(pc, -1)
return line
}
+// LineToPC returns the program counter for the given line number,
+// considering only program counters before maxpc.
+// Callers should use Table's LineToPC method instead.
func (t *LineTable) LineToPC(line int, maxpc uint64) uint64 {
+ if t.isGo12() {
+ return 0
+ }
_, pc, line1 := t.parse(maxpc, line)
if line1 != line {
return 0
}
// Subtract quantum from PC to account for post-line increment
- return pc - quantum
+ return pc - oldQuantum
}
// NewLineTable returns a new PC/line table
@@ -78,5 +120,307 @@ func (t *LineTable) LineToPC(line int, maxpc uint64) uint64 {
// Text must be the start address of the
// corresponding text segment.
func NewLineTable(data []byte, text uint64) *LineTable {
- return &LineTable{data, text, 0}
+ return &LineTable{Data: data, PC: text, Line: 0}
+}
+
+// Go 1.2 symbol table format.
+// See golang.org/s/go12symtab.
+//
+// A general note about the methods here: rather than try to avoid
+// index out of bounds errors, we trust Go to detect them, and then
+// we recover from the panics and treat them as indicative of a malformed
+// or incomplete table.
+//
+// The methods called by symtab.go, which begin with "go12" prefixes,
+// are expected to have that recovery logic.
+
+// isGo12 reports whether this is a Go 1.2 (or later) symbol table.
+func (t *LineTable) isGo12() bool {
+ t.go12Init()
+ return t.go12 == 1
+}
+
+const go12magic = 0xfffffffb
+
+// uintptr returns the pointer-sized value encoded at b.
+// The pointer size is dictated by the table being read.
+func (t *LineTable) uintptr(b []byte) uint64 {
+ if t.ptrsize == 4 {
+ return uint64(t.binary.Uint32(b))
+ }
+ return t.binary.Uint64(b)
+}
+
+// go12init initializes the Go 1.2 metadata if t is a Go 1.2 symbol table.
+func (t *LineTable) go12Init() {
+ t.mu.Lock()
+ defer t.mu.Unlock()
+ if t.go12 != 0 {
+ return
+ }
+
+ defer func() {
+ // If we panic parsing, assume it's not a Go 1.2 symbol table.
+ recover()
+ }()
+
+ // Check header: 4-byte magic, two zeros, pc quantum, pointer size.
+ t.go12 = -1 // not Go 1.2 until proven otherwise
+ if len(t.Data) < 16 || t.Data[4] != 0 || t.Data[5] != 0 ||
+ (t.Data[6] != 1 && t.Data[6] != 4) || // pc quantum
+ (t.Data[7] != 4 && t.Data[7] != 8) { // pointer size
+ return
+ }
+
+ switch uint32(go12magic) {
+ case binary.LittleEndian.Uint32(t.Data):
+ t.binary = binary.LittleEndian
+ case binary.BigEndian.Uint32(t.Data):
+ t.binary = binary.BigEndian
+ default:
+ return
+ }
+
+ t.quantum = uint32(t.Data[6])
+ t.ptrsize = uint32(t.Data[7])
+
+ t.nfunctab = uint32(t.uintptr(t.Data[8:]))
+ t.functab = t.Data[8+t.ptrsize:]
+ functabsize := t.nfunctab*2*t.ptrsize + t.ptrsize
+ fileoff := t.binary.Uint32(t.functab[functabsize:])
+ t.functab = t.functab[:functabsize]
+ t.filetab = t.Data[fileoff:]
+ t.nfiletab = t.binary.Uint32(t.filetab)
+ t.filetab = t.filetab[:t.nfiletab*4]
+
+ t.go12 = 1 // so far so good
+}
+
+// findFunc returns the func corresponding to the given program counter.
+func (t *LineTable) findFunc(pc uint64) []byte {
+ if pc < t.uintptr(t.functab) || pc >= t.uintptr(t.functab[len(t.functab)-int(t.ptrsize):]) {
+ return nil
+ }
+
+ // The function table is a list of 2*nfunctab+1 uintptrs,
+ // alternating program counters and offsets to func structures.
+ f := t.functab
+ nf := t.nfunctab
+ for nf > 0 {
+ m := nf / 2
+ fm := f[2*t.ptrsize*m:]
+ if t.uintptr(fm) <= pc && pc < t.uintptr(fm[2*t.ptrsize:]) {
+ return t.Data[t.uintptr(fm[t.ptrsize:]):]
+ } else if pc < t.uintptr(fm) {
+ nf = m
+ } else {
+ f = f[(m+1)*2*t.ptrsize:]
+ nf -= m + 1
+ }
+ }
+ return nil
+}
+
+// readvarint reads, removes, and returns a varint from *pp.
+func (t *LineTable) readvarint(pp *[]byte) uint32 {
+ var v, shift uint32
+ p := *pp
+ for shift = 0; ; shift += 7 {
+ b := p[0]
+ p = p[1:]
+ v |= (uint32(b) & 0x7F) << shift
+ if b&0x80 == 0 {
+ break
+ }
+ }
+ *pp = p
+ return v
+}
+
+// string returns a Go string found at off.
+func (t *LineTable) string(off uint32) string {
+ for i := off; ; i++ {
+ if t.Data[i] == 0 {
+ return string(t.Data[off:i])
+ }
+ }
+}
+
+// step advances to the next pc, value pair in the encoded table.
+func (t *LineTable) step(p *[]byte, pc *uint64, val *int32, first bool) bool {
+ uvdelta := t.readvarint(p)
+ if uvdelta == 0 && !first {
+ return false
+ }
+ if uvdelta&1 != 0 {
+ uvdelta = ^(uvdelta >> 1)
+ } else {
+ uvdelta >>= 1
+ }
+ vdelta := int32(uvdelta)
+ pcdelta := t.readvarint(p) * t.quantum
+ *pc += uint64(pcdelta)
+ *val += vdelta
+ return true
+}
+
+// pcvalue reports the value associated with the target pc.
+// off is the offset to the beginning of the pc-value table,
+// and entry is the start PC for the corresponding function.
+func (t *LineTable) pcvalue(off uint32, entry, targetpc uint64) int32 {
+ if off == 0 {
+ return -1
+ }
+ p := t.Data[off:]
+
+ val := int32(-1)
+ pc := entry
+ for t.step(&p, &pc, &val, pc == entry) {
+ if targetpc < pc {
+ return val
+ }
+ }
+ return -1
+}
+
+// findFileLine scans one function in the binary looking for a
+// program counter in the given file on the given line.
+// It does so by running the pc-value tables mapping program counter
+// to file number. Since most functions come from a single file, these
+// are usually short and quick to scan. If a file match is found, then the
+// code goes to the expense of looking for a simultaneous line number match.
+func (t *LineTable) findFileLine(entry uint64, filetab, linetab uint32, filenum, line int32) uint64 {
+ if filetab == 0 || linetab == 0 {
+ return 0
+ }
+
+ fp := t.Data[filetab:]
+ fl := t.Data[linetab:]
+ fileVal := int32(-1)
+ filePC := entry
+ lineVal := int32(-1)
+ linePC := entry
+ fileStartPC := filePC
+ for t.step(&fp, &filePC, &fileVal, filePC == entry) {
+ if fileVal == filenum && fileStartPC < filePC {
+ // fileVal is in effect starting at fileStartPC up to
+ // but not including filePC, and it's the file we want.
+ // Run the PC table looking for a matching line number
+ // or until we reach filePC.
+ lineStartPC := linePC
+ for linePC < filePC && t.step(&fl, &linePC, &lineVal, linePC == entry) {
+ // lineVal is in effect until linePC, and lineStartPC < filePC.
+ if lineVal == line {
+ if fileStartPC <= lineStartPC {
+ return lineStartPC
+ }
+ if fileStartPC < linePC {
+ return fileStartPC
+ }
+ }
+ lineStartPC = linePC
+ }
+ }
+ fileStartPC = filePC
+ }
+ return 0
+}
+
+// go12PCToLine maps program counter to line number for the Go 1.2 pcln table.
+func (t *LineTable) go12PCToLine(pc uint64) (line int) {
+ defer func() {
+ if recover() != nil {
+ line = -1
+ }
+ }()
+
+ f := t.findFunc(pc)
+ if f == nil {
+ return -1
+ }
+ entry := t.uintptr(f)
+ linetab := t.binary.Uint32(f[t.ptrsize+5*4:])
+ return int(t.pcvalue(linetab, entry, pc))
+}
+
+// go12PCToFile maps program counter to file name for the Go 1.2 pcln table.
+func (t *LineTable) go12PCToFile(pc uint64) (file string) {
+ defer func() {
+ if recover() != nil {
+ file = ""
+ }
+ }()
+
+ f := t.findFunc(pc)
+ if f == nil {
+ return ""
+ }
+ entry := t.uintptr(f)
+ filetab := t.binary.Uint32(f[t.ptrsize+4*4:])
+ fno := t.pcvalue(filetab, entry, pc)
+ if fno <= 0 {
+ return ""
+ }
+ return t.string(t.binary.Uint32(t.filetab[4*fno:]))
+}
+
+// go12LineToPC maps a (file, line) pair to a program counter for the Go 1.2 pcln table.
+func (t *LineTable) go12LineToPC(file string, line int) (pc uint64) {
+ defer func() {
+ if recover() != nil {
+ pc = 0
+ }
+ }()
+
+ t.initFileMap()
+ filenum := t.fileMap[file]
+ if filenum == 0 {
+ return 0
+ }
+
+ // Scan all functions.
+ // If this turns out to be a bottleneck, we could build a map[int32][]int32
+ // mapping file number to a list of functions with code from that file.
+ for i := uint32(0); i < t.nfunctab; i++ {
+ f := t.Data[t.uintptr(t.functab[2*t.ptrsize*i+t.ptrsize:]):]
+ entry := t.uintptr(f)
+ filetab := t.binary.Uint32(f[t.ptrsize+4*4:])
+ linetab := t.binary.Uint32(f[t.ptrsize+5*4:])
+ pc := t.findFileLine(entry, filetab, linetab, int32(filenum), int32(line))
+ if pc != 0 {
+ return pc
+ }
+ }
+ return 0
+}
+
+// initFileMap initializes the map from file name to file number.
+func (t *LineTable) initFileMap() {
+ t.mu.Lock()
+ defer t.mu.Unlock()
+
+ if t.fileMap != nil {
+ return
+ }
+ m := make(map[string]uint32)
+
+ for i := uint32(1); i < t.nfiletab; i++ {
+ s := t.string(t.binary.Uint32(t.filetab[4*i:]))
+ m[s] = i
+ }
+ t.fileMap = m
+}
+
+// go12MapFiles adds to m a key for every file in the Go 1.2 LineTable.
+// Every key maps to obj. That's not a very interesting map, but it provides
+// a way for callers to obtain the list of files in the program.
+func (t *LineTable) go12MapFiles(m map[string]*Obj, obj *Obj) {
+ defer func() {
+ recover()
+ }()
+
+ t.initFileMap()
+ for file := range t.fileMap {
+ m[file] = obj
+ }
}
diff --git a/libgo/go/debug/gosym/pclntab_test.go b/libgo/go/debug/gosym/pclntab_test.go
index 20acba612f2..35502e8c395 100644
--- a/libgo/go/debug/gosym/pclntab_test.go
+++ b/libgo/go/debug/gosym/pclntab_test.go
@@ -21,9 +21,17 @@ var (
pclinetestBinary string
)
-func dotest() bool {
- // For now, only works on ELF platforms.
- if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" {
+func dotest(self bool) bool {
+ // For now, only works on amd64 platforms.
+ if runtime.GOARCH != "amd64" {
+ return false
+ }
+ // Self test reads test binary; only works on Linux.
+ if self && runtime.GOOS != "linux" {
+ return false
+ }
+ // Command below expects "sh", so Unix.
+ if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
return false
}
if pclinetestBinary != "" {
@@ -41,7 +49,7 @@ func dotest() bool {
// the resulting binary looks like it was built from pclinetest.s,
// but we have renamed it to keep it away from the go tool.
pclinetestBinary = filepath.Join(pclineTempDir, "pclinetest")
- command := fmt.Sprintf("go tool 6a -o %s.6 pclinetest.asm && go tool 6l -E main -o %s %s.6",
+ command := fmt.Sprintf("go tool 6a -o %s.6 pclinetest.asm && go tool 6l -H linux -E main -o %s %s.6",
pclinetestBinary, pclinetestBinary, pclinetestBinary)
cmd := exec.Command("sh", "-c", command)
cmd.Stdout = os.Stdout
@@ -100,12 +108,16 @@ func parse(file string, f *elf.File, t *testing.T) (*elf.File, *Table) {
var goarch = os.Getenv("O")
func TestLineFromAline(t *testing.T) {
- if !dotest() {
+ if !dotest(true) {
return
}
defer endtest()
tab := getTable(t)
+ if tab.go12line != nil {
+ // aline's don't exist in the Go 1.2 table.
+ t.Skip("not relevant to Go 1.2 symbol table")
+ }
// Find the sym package
pkg := tab.LookupFunc("debug/gosym.TestLineFromAline").Obj
@@ -148,12 +160,16 @@ func TestLineFromAline(t *testing.T) {
}
func TestLineAline(t *testing.T) {
- if !dotest() {
+ if !dotest(true) {
return
}
defer endtest()
tab := getTable(t)
+ if tab.go12line != nil {
+ // aline's don't exist in the Go 1.2 table.
+ t.Skip("not relevant to Go 1.2 symbol table")
+ }
for _, o := range tab.Files {
// A source file can appear multiple times in a
@@ -190,7 +206,7 @@ func TestLineAline(t *testing.T) {
}
func TestPCLine(t *testing.T) {
- if !dotest() {
+ if !dotest(false) {
return
}
defer endtest()
@@ -206,16 +222,17 @@ func TestPCLine(t *testing.T) {
sym := tab.LookupFunc("linefrompc")
wantLine := 0
for pc := sym.Entry; pc < sym.End; pc++ {
- file, line, fn := tab.PCToLine(pc)
off := pc - text.Addr // TODO(rsc): should not need off; bug in 8g
+ if textdat[off] == 255 {
+ break
+ }
wantLine += int(textdat[off])
- t.Logf("off is %d", off)
+ t.Logf("off is %d %#x (max %d)", off, textdat[off], sym.End-pc)
+ file, line, fn := tab.PCToLine(pc)
if fn == nil {
t.Errorf("failed to get line of PC %#x", pc)
- } else if !strings.HasSuffix(file, "pclinetest.asm") {
- t.Errorf("expected %s (%s) at PC %#x, got %s (%s)", "pclinetest.asm", sym.Name, pc, file, fn.Name)
- } else if line != wantLine || fn != sym {
- t.Errorf("expected :%d (%s) at PC %#x, got :%d (%s)", wantLine, sym.Name, pc, line, fn.Name)
+ } else if !strings.HasSuffix(file, "pclinetest.asm") || line != wantLine || fn != sym {
+ t.Errorf("PCToLine(%#x) = %s:%d (%s), want %s:%d (%s)", pc, file, line, fn.Name, "pclinetest.asm", wantLine, sym.Name)
}
}
@@ -227,6 +244,9 @@ func TestPCLine(t *testing.T) {
for pc := sym.Value; pc < sym.End; pc += 2 + uint64(textdat[off]) {
file, line, fn := tab.PCToLine(pc)
off = pc - text.Addr
+ if textdat[off] == 255 {
+ break
+ }
wantLine += int(textdat[off])
if line != wantLine {
t.Errorf("expected line %d at PC %#x in pcfromline, got %d", wantLine, pc, line)
diff --git a/libgo/go/debug/gosym/symtab.go b/libgo/go/debug/gosym/symtab.go
index 81ed4fb27dc..9ab05bac2f7 100644
--- a/libgo/go/debug/gosym/symtab.go
+++ b/libgo/go/debug/gosym/symtab.go
@@ -34,7 +34,7 @@ type Sym struct {
Func *Func
}
-// Static returns whether this symbol is static (not visible outside its file).
+// Static reports whether this symbol is static (not visible outside its file).
func (s *Sym) Static() bool { return s.Type >= 'a' }
// PackageName returns the package part of the symbol name,
@@ -77,10 +77,26 @@ type Func struct {
Obj *Obj
}
-// An Obj represents a single object file.
+// An Obj represents a collection of functions in a symbol table.
+//
+// The exact method of division of a binary into separate Objs is an internal detail
+// of the symbol table format.
+//
+// In early versions of Go each source file became a different Obj.
+//
+// In Go 1 and Go 1.1, each package produced one Obj for all Go sources
+// and one Obj per C source file.
+//
+// In Go 1.2, there is a single Obj for the entire program.
type Obj struct {
+ // Funcs is a list of functions in the Obj.
Funcs []Func
- Paths []Sym
+
+ // In Go 1.1 and earlier, Paths is a list of symbols corresponding
+ // to the source file names that produced the Obj.
+ // In Go 1.2, Paths is nil.
+ // Use the keys of Table.Files to obtain a list of source files.
+ Paths []Sym // meta
}
/*
@@ -93,9 +109,10 @@ type Obj struct {
type Table struct {
Syms []Sym
Funcs []Func
- Files map[string]*Obj
- Objs []Obj
- // textEnd uint64;
+ Files map[string]*Obj // nil for Go 1.2 and later binaries
+ Objs []Obj // nil for Go 1.2 and later binaries
+
+ go12line *LineTable // Go 1.2 line number table
}
type sym struct {
@@ -105,10 +122,11 @@ type sym struct {
name []byte
}
-var littleEndianSymtab = []byte{0xFD, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00}
-var bigEndianSymtab = []byte{0xFF, 0xFF, 0xFF, 0xFD, 0x00, 0x00, 0x00}
-
-var oldLittleEndianSymtab = []byte{0xFE, 0xFF, 0xFF, 0xFF, 0x00, 0x00}
+var (
+ littleEndianSymtab = []byte{0xFD, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00}
+ bigEndianSymtab = []byte{0xFF, 0xFF, 0xFF, 0xFD, 0x00, 0x00, 0x00}
+ oldLittleEndianSymtab = []byte{0xFE, 0xFF, 0xFF, 0xFF, 0x00, 0x00}
+)
func walksymtab(data []byte, fn func(sym) error) error {
var order binary.ByteOrder = binary.BigEndian
@@ -260,6 +278,9 @@ func NewTable(symtab []byte, pcln *LineTable) (*Table, error) {
}
var t Table
+ if pcln.isGo12() {
+ t.go12line = pcln
+ }
fname := make(map[uint16]string)
t.Syms = make([]Sym, 0, n)
nf := 0
@@ -316,17 +337,29 @@ func NewTable(symtab []byte, pcln *LineTable) (*Table, error) {
}
t.Funcs = make([]Func, 0, nf)
- t.Objs = make([]Obj, 0, nz)
t.Files = make(map[string]*Obj)
+ var obj *Obj
+ if t.go12line != nil {
+ // Put all functions into one Obj.
+ t.Objs = make([]Obj, 1)
+ obj = &t.Objs[0]
+ t.go12line.go12MapFiles(t.Files, obj)
+ } else {
+ t.Objs = make([]Obj, 0, nz)
+ }
+
// Count text symbols and attach frame sizes, parameters, and
// locals to them. Also, find object file boundaries.
- var obj *Obj
lastf := 0
for i := 0; i < len(t.Syms); i++ {
sym := &t.Syms[i]
switch sym.Type {
case 'Z', 'z': // path symbol
+ if t.go12line != nil {
+ // Go 1.2 binaries have the file information elsewhere. Ignore.
+ break
+ }
// Finish the current object
if obj != nil {
obj.Funcs = t.Funcs[lastf:]
@@ -395,7 +428,12 @@ func NewTable(symtab []byte, pcln *LineTable) (*Table, error) {
fn.Sym = sym
fn.Entry = sym.Value
fn.Obj = obj
- if pcln != nil {
+ if t.go12line != nil {
+ // All functions share the same line table.
+ // It knows how to narrow down to a specific
+ // function quickly.
+ fn.LineTable = t.go12line
+ } else if pcln != nil {
fn.LineTable = pcln.slice(fn.Entry)
pcln = fn.LineTable
}
@@ -448,18 +486,32 @@ func (t *Table) PCToLine(pc uint64) (file string, line int, fn *Func) {
if fn = t.PCToFunc(pc); fn == nil {
return
}
- file, line = fn.Obj.lineFromAline(fn.LineTable.PCToLine(pc))
+ if t.go12line != nil {
+ file = t.go12line.go12PCToFile(pc)
+ line = t.go12line.go12PCToLine(pc)
+ } else {
+ file, line = fn.Obj.lineFromAline(fn.LineTable.PCToLine(pc))
+ }
return
}
// LineToPC looks up the first program counter on the given line in
-// the named file. Returns UnknownPathError or UnknownLineError if
+// the named file. It returns UnknownPathError or UnknownLineError if
// there is an error looking up this line.
func (t *Table) LineToPC(file string, line int) (pc uint64, fn *Func, err error) {
obj, ok := t.Files[file]
if !ok {
return 0, nil, UnknownFileError(file)
}
+
+ if t.go12line != nil {
+ pc := t.go12line.go12LineToPC(file, line)
+ if pc == 0 {
+ return 0, nil, &UnknownLineError{file, line}
+ }
+ return pc, t.PCToFunc(pc), nil
+ }
+
abs, err := obj.alineFromLine(file, line)
if err != nil {
return
@@ -503,9 +555,7 @@ func (t *Table) LookupFunc(name string) *Func {
}
// SymByAddr returns the text, data, or bss symbol starting at the given address.
-// TODO(rsc): Allow lookup by any address within the symbol.
func (t *Table) SymByAddr(addr uint64) *Sym {
- // TODO(austin) Maybe make a map
for i := range t.Syms {
s := &t.Syms[i]
switch s.Type {
@@ -522,6 +572,13 @@ func (t *Table) SymByAddr(addr uint64) *Sym {
* Object files
*/
+// This is legacy code for Go 1.1 and earlier, which used the
+// Plan 9 format for pc-line tables. This code was never quite
+// correct. It's probably very close, and it's usually correct, but
+// we never quite found all the corner cases.
+//
+// Go 1.2 and later use a simpler format, documented at golang.org/s/go12symtab.
+
func (o *Obj) lineFromAline(aline int) (string, int) {
type stackEnt struct {
path string
@@ -533,8 +590,6 @@ func (o *Obj) lineFromAline(aline int) (string, int) {
noPath := &stackEnt{"", 0, 0, nil}
tos := noPath
- // TODO(austin) I have no idea how 'Z' symbols work, except
- // that they pop the stack.
pathloop:
for _, s := range o.Paths {
val := int(s.Value)
diff --git a/libgo/go/encoding/asn1/asn1.go b/libgo/go/encoding/asn1/asn1.go
index cac9d64b5e9..992356c263b 100644
--- a/libgo/go/encoding/asn1/asn1.go
+++ b/libgo/go/encoding/asn1/asn1.go
@@ -32,14 +32,14 @@ type StructuralError struct {
Msg string
}
-func (e StructuralError) Error() string { return "ASN.1 structure error: " + e.Msg }
+func (e StructuralError) Error() string { return "asn1: structure error: " + e.Msg }
// A SyntaxError suggests that the ASN.1 data is invalid.
type SyntaxError struct {
Msg string
}
-func (e SyntaxError) Error() string { return "ASN.1 syntax error: " + e.Msg }
+func (e SyntaxError) Error() string { return "asn1: syntax error: " + e.Msg }
// We start by dealing with each of the primitive types in turn.
@@ -51,7 +51,19 @@ func parseBool(bytes []byte) (ret bool, err error) {
return
}
- return bytes[0] != 0, nil
+ // DER demands that "If the encoding represents the boolean value TRUE,
+ // its single contents octet shall have all eight bits set to one."
+ // Thus only 0 and 255 are valid encoded values.
+ switch bytes[0] {
+ case 0:
+ ret = false
+ case 0xff:
+ ret = true
+ default:
+ err = SyntaxError{"invalid boolean"}
+ }
+
+ return
}
// INTEGER
@@ -171,7 +183,7 @@ func parseBitString(bytes []byte) (ret BitString, err error) {
// An ObjectIdentifier represents an ASN.1 OBJECT IDENTIFIER.
type ObjectIdentifier []int
-// Equal returns true iff oi and other represent the same identifier.
+// Equal reports whether oi and other represent the same identifier.
func (oi ObjectIdentifier) Equal(other ObjectIdentifier) bool {
if len(oi) != len(other) {
return false
@@ -198,12 +210,24 @@ func parseObjectIdentifier(bytes []byte) (s []int, err error) {
// encoded differently) and then every varint is a single byte long.
s = make([]int, len(bytes)+1)
- // The first byte is 40*value1 + value2:
- s[0] = int(bytes[0]) / 40
- s[1] = int(bytes[0]) % 40
+ // The first varint is 40*value1 + value2:
+ // According to this packing, value1 can take the values 0, 1 and 2 only.
+ // When value1 = 0 or value1 = 1, then value2 is <= 39. When value1 = 2,
+ // then there are no restrictions on value2.
+ v, offset, err := parseBase128Int(bytes, 0)
+ if err != nil {
+ return
+ }
+ if v < 80 {
+ s[0] = v / 40
+ s[1] = v % 40
+ } else {
+ s[0] = 2
+ s[1] = v - 80
+ }
+
i := 2
- for offset := 1; offset < len(bytes); i++ {
- var v int
+ for ; offset < len(bytes); i++ {
v, offset, err = parseBase128Int(bytes, offset)
if err != nil {
return
@@ -573,7 +597,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
}
} else {
if fieldType != flagType {
- err = StructuralError{"Zero length explicit tag was not an asn1.Flag"}
+ err = StructuralError{"zero length explicit tag was not an asn1.Flag"}
return
}
v.SetBool(true)
diff --git a/libgo/go/encoding/asn1/asn1_test.go b/libgo/go/encoding/asn1/asn1_test.go
index 6e98dcf0b99..f68804ebffd 100644
--- a/libgo/go/encoding/asn1/asn1_test.go
+++ b/libgo/go/encoding/asn1/asn1_test.go
@@ -12,6 +12,32 @@ import (
"time"
)
+type boolTest struct {
+ in []byte
+ ok bool
+ out bool
+}
+
+var boolTestData = []boolTest{
+ {[]byte{0x00}, true, false},
+ {[]byte{0xff}, true, true},
+ {[]byte{0x00, 0x00}, false, false},
+ {[]byte{0xff, 0xff}, false, false},
+ {[]byte{0x01}, false, false},
+}
+
+func TestParseBool(t *testing.T) {
+ for i, test := range boolTestData {
+ ret, err := parseBool(test.in)
+ if (err == nil) != test.ok {
+ t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok)
+ }
+ if test.ok && ret != test.out {
+ t.Errorf("#%d: Bad result: %v (expected %v)", i, ret, test.out)
+ }
+ }
+}
+
type int64Test struct {
in []byte
ok bool
@@ -183,6 +209,7 @@ var objectIdentifierTestData = []objectIdentifierTest{
{[]byte{85}, true, []int{2, 5}},
{[]byte{85, 0x02}, true, []int{2, 5, 2}},
{[]byte{85, 0x02, 0xc0, 0x00}, true, []int{2, 5, 2, 0x2000}},
+ {[]byte{0x81, 0x34, 0x03}, true, []int{2, 100, 3}},
{[]byte{85, 0x02, 0xc0, 0x80, 0x80, 0x80, 0x80}, false, []int{}},
}
@@ -378,7 +405,7 @@ var unmarshalTestData = []struct {
{[]byte{0x30, 0x03, 0x81, 0x01, 0x01}, &TestContextSpecificTags{1}},
{[]byte{0x30, 0x08, 0xa1, 0x03, 0x02, 0x01, 0x01, 0x02, 0x01, 0x02}, &TestContextSpecificTags2{1, 2}},
{[]byte{0x01, 0x01, 0x00}, newBool(false)},
- {[]byte{0x01, 0x01, 0x01}, newBool(true)},
+ {[]byte{0x01, 0x01, 0xff}, newBool(true)},
{[]byte{0x30, 0x0b, 0x13, 0x03, 0x66, 0x6f, 0x6f, 0x02, 0x01, 0x22, 0x02, 0x01, 0x33}, &TestElementsAfterString{"foo", 0x22, 0x33}},
{[]byte{0x30, 0x05, 0x02, 0x03, 0x12, 0x34, 0x56}, &TestBigInt{big.NewInt(0x123456)}},
}
diff --git a/libgo/go/encoding/asn1/marshal.go b/libgo/go/encoding/asn1/marshal.go
index adaf80dcdb0..ed17e41a55c 100644
--- a/libgo/go/encoding/asn1/marshal.go
+++ b/libgo/go/encoding/asn1/marshal.go
@@ -240,11 +240,11 @@ func marshalBitString(out *forkableWriter, b BitString) (err error) {
}
func marshalObjectIdentifier(out *forkableWriter, oid []int) (err error) {
- if len(oid) < 2 || oid[0] > 6 || oid[1] >= 40 {
+ if len(oid) < 2 || oid[0] > 2 || (oid[0] < 2 && oid[1] >= 40) {
return StructuralError{"invalid object identifier"}
}
- err = out.WriteByte(byte(oid[0]*40 + oid[1]))
+ err = marshalBase128Int(out, int64(oid[0]*40+oid[1]))
if err != nil {
return
}
@@ -304,7 +304,7 @@ func marshalUTCTime(out *forkableWriter, t time.Time) (err error) {
case 2000 <= year && year < 2050:
err = marshalTwoDigits(out, int(year-2000))
default:
- return StructuralError{"Cannot represent time as UTCTime"}
+ return StructuralError{"cannot represent time as UTCTime"}
}
if err != nil {
return
@@ -441,11 +441,11 @@ func marshalBody(out *forkableWriter, value reflect.Value, params fieldParameter
return
}
- var params fieldParameters
+ var fp fieldParameters
for i := 0; i < v.Len(); i++ {
var pre *forkableWriter
pre, out = out.fork()
- err = marshalField(pre, v.Index(i), params)
+ err = marshalField(pre, v.Index(i), fp)
if err != nil {
return
}
@@ -501,7 +501,7 @@ func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters)
class := classUniversal
if params.stringType != 0 && tag != tagPrintableString {
- return StructuralError{"Explicit string type given to non-string member"}
+ return StructuralError{"explicit string type given to non-string member"}
}
if tag == tagPrintableString {
@@ -525,7 +525,7 @@ func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters)
if params.set {
if tag != tagSequence {
- return StructuralError{"Non sequence tagged as set"}
+ return StructuralError{"non sequence tagged as set"}
}
tag = tagSet
}
diff --git a/libgo/go/encoding/asn1/marshal_test.go b/libgo/go/encoding/asn1/marshal_test.go
index b4dbe71ef3c..763c86da23f 100644
--- a/libgo/go/encoding/asn1/marshal_test.go
+++ b/libgo/go/encoding/asn1/marshal_test.go
@@ -87,6 +87,7 @@ var marshalTests = []marshalTest{
{BitString{[]byte{0x81, 0xf0}, 12}, "03030481f0"},
{ObjectIdentifier([]int{1, 2, 3, 4}), "06032a0304"},
{ObjectIdentifier([]int{1, 2, 840, 133549, 1, 1, 5}), "06092a864888932d010105"},
+ {ObjectIdentifier([]int{2, 100, 3}), "0603813403"},
{"test", "130474657374"},
{
"" +
diff --git a/libgo/go/encoding/binary/binary.go b/libgo/go/encoding/binary/binary.go
index edbac197d64..f3466b9af03 100644
--- a/libgo/go/encoding/binary/binary.go
+++ b/libgo/go/encoding/binary/binary.go
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Package binary implements translation between numbers and byte sequences
-// and encoding and decoding of varints.
+// Package binary implements simple translation between numbers and byte
+// sequences and encoding and decoding of varints.
//
// Numbers are translated by reading and writing fixed-size values.
// A fixed-size value is either a fixed-size arithmetic
@@ -13,6 +13,11 @@
// Varints are a method of encoding integers using one or more bytes;
// numbers with smaller absolute value take a smaller number of bytes.
// For a specification, see http://code.google.com/apis/protocolbuffers/docs/encoding.html.
+//
+// This package favors simplicity over efficiency. Clients that require
+// high-performance serialization, especially for large data structures,
+// should look at more advanced solutions such as the encoding/gob
+// package or protocol buffers.
package binary
import (
@@ -129,30 +134,65 @@ func (bigEndian) GoString() string { return "binary.BigEndian" }
// blank (_) field names is skipped; i.e., blank field names
// may be used for padding.
func Read(r io.Reader, order ByteOrder, data interface{}) error {
- // Fast path for basic types.
- if n := intDestSize(data); n != 0 {
+ // Fast path for basic types and slices.
+ if n := intDataSize(data); n != 0 {
var b [8]byte
- bs := b[:n]
+ var bs []byte
+ if n > len(b) {
+ bs = make([]byte, n)
+ } else {
+ bs = b[:n]
+ }
if _, err := io.ReadFull(r, bs); err != nil {
return err
}
- switch v := data.(type) {
+ switch data := data.(type) {
case *int8:
- *v = int8(b[0])
+ *data = int8(b[0])
case *uint8:
- *v = b[0]
+ *data = b[0]
case *int16:
- *v = int16(order.Uint16(bs))
+ *data = int16(order.Uint16(bs))
case *uint16:
- *v = order.Uint16(bs)
+ *data = order.Uint16(bs)
case *int32:
- *v = int32(order.Uint32(bs))
+ *data = int32(order.Uint32(bs))
case *uint32:
- *v = order.Uint32(bs)
+ *data = order.Uint32(bs)
case *int64:
- *v = int64(order.Uint64(bs))
+ *data = int64(order.Uint64(bs))
case *uint64:
- *v = order.Uint64(bs)
+ *data = order.Uint64(bs)
+ case []int8:
+ for i, x := range bs { // Easier to loop over the input for 8-bit values.
+ data[i] = int8(x)
+ }
+ case []uint8:
+ copy(data, bs)
+ case []int16:
+ for i := range data {
+ data[i] = int16(order.Uint16(bs[2*i:]))
+ }
+ case []uint16:
+ for i := range data {
+ data[i] = order.Uint16(bs[2*i:])
+ }
+ case []int32:
+ for i := range data {
+ data[i] = int32(order.Uint32(bs[4*i:]))
+ }
+ case []uint32:
+ for i := range data {
+ data[i] = order.Uint32(bs[4*i:])
+ }
+ case []int64:
+ for i := range data {
+ data[i] = int64(order.Uint64(bs[8*i:]))
+ }
+ case []uint64:
+ for i := range data {
+ data[i] = order.Uint64(bs[8*i:])
+ }
}
return nil
}
@@ -187,60 +227,95 @@ func Read(r io.Reader, order ByteOrder, data interface{}) error {
// When writing structs, zero values are written for fields
// with blank (_) field names.
func Write(w io.Writer, order ByteOrder, data interface{}) error {
- // Fast path for basic types.
- var b [8]byte
- var bs []byte
- switch v := data.(type) {
- case *int8:
- bs = b[:1]
- b[0] = byte(*v)
- case int8:
- bs = b[:1]
- b[0] = byte(v)
- case *uint8:
- bs = b[:1]
- b[0] = *v
- case uint8:
- bs = b[:1]
- b[0] = byte(v)
- case *int16:
- bs = b[:2]
- order.PutUint16(bs, uint16(*v))
- case int16:
- bs = b[:2]
- order.PutUint16(bs, uint16(v))
- case *uint16:
- bs = b[:2]
- order.PutUint16(bs, *v)
- case uint16:
- bs = b[:2]
- order.PutUint16(bs, v)
- case *int32:
- bs = b[:4]
- order.PutUint32(bs, uint32(*v))
- case int32:
- bs = b[:4]
- order.PutUint32(bs, uint32(v))
- case *uint32:
- bs = b[:4]
- order.PutUint32(bs, *v)
- case uint32:
- bs = b[:4]
- order.PutUint32(bs, v)
- case *int64:
- bs = b[:8]
- order.PutUint64(bs, uint64(*v))
- case int64:
- bs = b[:8]
- order.PutUint64(bs, uint64(v))
- case *uint64:
- bs = b[:8]
- order.PutUint64(bs, *v)
- case uint64:
- bs = b[:8]
- order.PutUint64(bs, v)
- }
- if bs != nil {
+ // Fast path for basic types and slices.
+ if n := intDataSize(data); n != 0 {
+ var b [8]byte
+ var bs []byte
+ if n > len(b) {
+ bs = make([]byte, n)
+ } else {
+ bs = b[:n]
+ }
+ switch v := data.(type) {
+ case *int8:
+ bs = b[:1]
+ b[0] = byte(*v)
+ case int8:
+ bs = b[:1]
+ b[0] = byte(v)
+ case []int8:
+ for i, x := range v {
+ bs[i] = byte(x)
+ }
+ case *uint8:
+ bs = b[:1]
+ b[0] = *v
+ case uint8:
+ bs = b[:1]
+ b[0] = byte(v)
+ case []uint8:
+ bs = v
+ case *int16:
+ bs = b[:2]
+ order.PutUint16(bs, uint16(*v))
+ case int16:
+ bs = b[:2]
+ order.PutUint16(bs, uint16(v))
+ case []int16:
+ for i, x := range v {
+ order.PutUint16(bs[2*i:], uint16(x))
+ }
+ case *uint16:
+ bs = b[:2]
+ order.PutUint16(bs, *v)
+ case uint16:
+ bs = b[:2]
+ order.PutUint16(bs, v)
+ case []uint16:
+ for i, x := range v {
+ order.PutUint16(bs[2*i:], x)
+ }
+ case *int32:
+ bs = b[:4]
+ order.PutUint32(bs, uint32(*v))
+ case int32:
+ bs = b[:4]
+ order.PutUint32(bs, uint32(v))
+ case []int32:
+ for i, x := range v {
+ order.PutUint32(bs[4*i:], uint32(x))
+ }
+ case *uint32:
+ bs = b[:4]
+ order.PutUint32(bs, *v)
+ case uint32:
+ bs = b[:4]
+ order.PutUint32(bs, v)
+ case []uint32:
+ for i, x := range v {
+ order.PutUint32(bs[4*i:], x)
+ }
+ case *int64:
+ bs = b[:8]
+ order.PutUint64(bs, uint64(*v))
+ case int64:
+ bs = b[:8]
+ order.PutUint64(bs, uint64(v))
+ case []int64:
+ for i, x := range v {
+ order.PutUint64(bs[8*i:], uint64(x))
+ }
+ case *uint64:
+ bs = b[:8]
+ order.PutUint64(bs, *v)
+ case uint64:
+ bs = b[:8]
+ order.PutUint64(bs, v)
+ case []uint64:
+ for i, x := range v {
+ order.PutUint64(bs[8*i:], x)
+ }
+ }
_, err := w.Write(bs)
return err
}
@@ -530,18 +605,34 @@ func (e *encoder) skip(v reflect.Value) {
e.buf = e.buf[n:]
}
-// intDestSize returns the size of the integer that ptrType points to,
-// or 0 if the type is not supported.
-func intDestSize(ptrType interface{}) int {
- switch ptrType.(type) {
- case *int8, *uint8:
+// intDataSize returns the size of the data required to represent the data when encoded.
+// It returns zero if the type cannot be implemented by the fast path in Read or Write.
+func intDataSize(data interface{}) int {
+ switch data := data.(type) {
+ case int8, *int8, *uint8:
return 1
- case *int16, *uint16:
+ case []int8:
+ return len(data)
+ case []uint8:
+ return len(data)
+ case int16, *int16, *uint16:
return 2
- case *int32, *uint32:
+ case []int16:
+ return 2 * len(data)
+ case []uint16:
+ return 2 * len(data)
+ case int32, *int32, *uint32:
return 4
- case *int64, *uint64:
+ case []int32:
+ return 4 * len(data)
+ case []uint32:
+ return 4 * len(data)
+ case int64, *int64, *uint64:
return 8
+ case []int64:
+ return 8 * len(data)
+ case []uint64:
+ return 8 * len(data)
}
return 0
}
diff --git a/libgo/go/encoding/binary/binary_test.go b/libgo/go/encoding/binary/binary_test.go
index 056f0998f27..fdfee7d8711 100644
--- a/libgo/go/encoding/binary/binary_test.go
+++ b/libgo/go/encoding/binary/binary_test.go
@@ -141,6 +141,52 @@ func TestWriteSlice(t *testing.T) {
checkResult(t, "WriteSlice", BigEndian, err, buf.Bytes(), src)
}
+// Addresses of arrays are easier to manipulate with reflection than are slices.
+var intArrays = []interface{}{
+ &[100]int8{},
+ &[100]int16{},
+ &[100]int32{},
+ &[100]int64{},
+ &[100]uint8{},
+ &[100]uint16{},
+ &[100]uint32{},
+ &[100]uint64{},
+}
+
+func TestSliceRoundTrip(t *testing.T) {
+ buf := new(bytes.Buffer)
+ for _, array := range intArrays {
+ src := reflect.ValueOf(array).Elem()
+ unsigned := false
+ switch src.Index(0).Kind() {
+ case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+ unsigned = true
+ }
+ for i := 0; i < src.Len(); i++ {
+ if unsigned {
+ src.Index(i).SetUint(uint64(i * 0x07654321))
+ } else {
+ src.Index(i).SetInt(int64(i * 0x07654321))
+ }
+ }
+ buf.Reset()
+ srcSlice := src.Slice(0, src.Len())
+ err := Write(buf, BigEndian, srcSlice.Interface())
+ if err != nil {
+ t.Fatal(err)
+ }
+ dst := reflect.New(src.Type()).Elem()
+ dstSlice := dst.Slice(0, dst.Len())
+ err = Read(buf, BigEndian, dstSlice.Interface())
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !reflect.DeepEqual(src.Interface(), dst.Interface()) {
+ t.Fatal(src)
+ }
+ }
+}
+
func TestWriteT(t *testing.T) {
buf := new(bytes.Buffer)
ts := T{}
@@ -312,3 +358,16 @@ func BenchmarkWriteInts(b *testing.B) {
b.Fatalf("first half doesn't match: %x %x", buf.Bytes(), big[:30])
}
}
+
+func BenchmarkWriteSlice1000Int32s(b *testing.B) {
+ slice := make([]int32, 1000)
+ buf := new(bytes.Buffer)
+ var w io.Writer = buf
+ b.SetBytes(4 * 1000)
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ buf.Reset()
+ Write(w, BigEndian, slice)
+ }
+ b.StopTimer()
+}
diff --git a/libgo/go/encoding/csv/reader.go b/libgo/go/encoding/csv/reader.go
index b099caf60a8..b328dcc375c 100644
--- a/libgo/go/encoding/csv/reader.go
+++ b/libgo/go/encoding/csv/reader.go
@@ -72,7 +72,7 @@ func (e *ParseError) Error() string {
// These are the errors that can be returned in ParseError.Error
var (
- ErrTrailingComma = errors.New("extra delimiter at end of line")
+ ErrTrailingComma = errors.New("extra delimiter at end of line") // no longer used
ErrBareQuote = errors.New("bare \" in non-quoted-field")
ErrQuote = errors.New("extraneous \" in field")
ErrFieldCount = errors.New("wrong number of fields in line")
@@ -98,16 +98,14 @@ var (
// If LazyQuotes is true, a quote may appear in an unquoted field and a
// non-doubled quote may appear in a quoted field.
//
-// If TrailingComma is true, the last field may be an unquoted empty field.
-//
// If TrimLeadingSpace is true, leading white space in a field is ignored.
type Reader struct {
- Comma rune // Field delimiter (set to ',' by NewReader)
- Comment rune // Comment character for start of line
- FieldsPerRecord int // Number of expected fields per record
- LazyQuotes bool // Allow lazy quotes
- TrailingComma bool // Allow trailing comma
- TrimLeadingSpace bool // Trim leading space
+ Comma rune // field delimiter (set to ',' by NewReader)
+ Comment rune // comment character for start of line
+ FieldsPerRecord int // number of expected fields per record
+ LazyQuotes bool // allow lazy quotes
+ TrailingComma bool // ignored; here for backwards compatibility
+ TrimLeadingSpace bool // trim leading space
line int
column int
r *bufio.Reader
@@ -257,23 +255,15 @@ func (r *Reader) parseField() (haveField bool, delim rune, err error) {
r.field.Reset()
r1, err := r.readRune()
- if err != nil {
- // If we have EOF and are not at the start of a line
- // then we return the empty field. We have already
- // checked for trailing commas if needed.
- if err == io.EOF && r.column != 0 {
- return true, 0, err
- }
- return false, 0, err
+ for err == nil && r.TrimLeadingSpace && r1 != '\n' && unicode.IsSpace(r1) {
+ r1, err = r.readRune()
}
- if r.TrimLeadingSpace {
- for r1 != '\n' && unicode.IsSpace(r1) {
- r1, err = r.readRune()
- if err != nil {
- return false, 0, err
- }
- }
+ if err == io.EOF && r.column != 0 {
+ return true, 0, err
+ }
+ if err != nil {
+ return false, 0, err
}
switch r1 {
@@ -349,25 +339,5 @@ func (r *Reader) parseField() (haveField bool, delim rune, err error) {
return false, 0, err
}
- if !r.TrailingComma {
- // We don't allow trailing commas. See if we
- // are at the end of the line (being mindful
- // of trimming spaces).
- c := r.column
- r1, err = r.readRune()
- if r.TrimLeadingSpace {
- for r1 != '\n' && unicode.IsSpace(r1) {
- r1, err = r.readRune()
- if err != nil {
- break
- }
- }
- }
- if err == io.EOF || r1 == '\n' {
- r.column = c // report the comma
- return false, 0, r.error(ErrTrailingComma)
- }
- r.unreadRune()
- }
return true, r1, nil
}
diff --git a/libgo/go/encoding/csv/reader_test.go b/libgo/go/encoding/csv/reader_test.go
index 5fd84a76bdf..123df06bc85 100644
--- a/libgo/go/encoding/csv/reader_test.go
+++ b/libgo/go/encoding/csv/reader_test.go
@@ -171,32 +171,32 @@ field"`,
Output: [][]string{{"a", "b", "c"}, {"d", "e"}},
},
{
- Name: "BadTrailingCommaEOF",
- Input: "a,b,c,",
- Error: "extra delimiter at end of line", Line: 1, Column: 5,
+ Name: "TrailingCommaEOF",
+ Input: "a,b,c,",
+ Output: [][]string{{"a", "b", "c", ""}},
},
{
- Name: "BadTrailingCommaEOL",
- Input: "a,b,c,\n",
- Error: "extra delimiter at end of line", Line: 1, Column: 5,
+ Name: "TrailingCommaEOL",
+ Input: "a,b,c,\n",
+ Output: [][]string{{"a", "b", "c", ""}},
},
{
- Name: "BadTrailingCommaSpaceEOF",
+ Name: "TrailingCommaSpaceEOF",
TrimLeadingSpace: true,
Input: "a,b,c, ",
- Error: "extra delimiter at end of line", Line: 1, Column: 5,
+ Output: [][]string{{"a", "b", "c", ""}},
},
{
- Name: "BadTrailingCommaSpaceEOL",
+ Name: "TrailingCommaSpaceEOL",
TrimLeadingSpace: true,
Input: "a,b,c, \n",
- Error: "extra delimiter at end of line", Line: 1, Column: 5,
+ Output: [][]string{{"a", "b", "c", ""}},
},
{
- Name: "BadTrailingCommaLine3",
+ Name: "TrailingCommaLine3",
TrimLeadingSpace: true,
Input: "a,b,c\nd,e,f\ng,hi,",
- Error: "extra delimiter at end of line", Line: 3, Column: 4,
+ Output: [][]string{{"a", "b", "c"}, {"d", "e", "f"}, {"g", "hi", ""}},
},
{
Name: "NotTrailingComma3",
@@ -231,7 +231,7 @@ x,,,
},
},
{
- Name: "Issue 2366",
+ Name: "TrailingCommaIneffective1",
TrailingComma: true,
TrimLeadingSpace: true,
Input: "a,b,\nc,d,e",
@@ -241,11 +241,14 @@ x,,,
},
},
{
- Name: "Issue 2366a",
+ Name: "TrailingCommaIneffective2",
TrailingComma: false,
TrimLeadingSpace: true,
Input: "a,b,\nc,d,e",
- Error: "extra delimiter at end of line",
+ Output: [][]string{
+ {"a", "b", ""},
+ {"c", "d", "e"},
+ },
},
}
diff --git a/libgo/go/encoding/encoding.go b/libgo/go/encoding/encoding.go
new file mode 100644
index 00000000000..6d218071b7a
--- /dev/null
+++ b/libgo/go/encoding/encoding.go
@@ -0,0 +1,48 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package encoding defines interfaces shared by other packages that
+// convert data to and from byte-level and textual representations.
+// Packages that check for these interfaces include encoding/gob,
+// encoding/json, and encoding/xml. As a result, implementing an
+// interface once can make a type useful in multiple encodings.
+// Standard types that implement these interfaces include time.Time and net.IP.
+// The interfaces come in pairs that produce and consume encoded data.
+package encoding
+
+// BinaryMarshaler is the interface implemented by an object that can
+// marshal itself into a binary form.
+//
+// MarshalBinary encodes the receiver into a binary form and returns the result.
+type BinaryMarshaler interface {
+ MarshalBinary() (data []byte, err error)
+}
+
+// BinaryUnmarshaler is the interface implemented by an object that can
+// unmarshal a binary representation of itself.
+//
+// UnmarshalBinary must be able to decode the form generated by MarshalBinary.
+// UnmarshalBinary must copy the data if it wishes to retain the data
+// after returning.
+type BinaryUnmarshaler interface {
+ UnmarshalBinary(data []byte) error
+}
+
+// TextMarshaler is the interface implemented by an object that can
+// marshal itself into a textual form.
+//
+// MarshalText encodes the receiver into UTF-8-encoded text and returns the result.
+type TextMarshaler interface {
+ MarshalText() (text []byte, err error)
+}
+
+// TextUnmarshaler is the interface implemented by an object that can
+// unmarshal a textual representation of itself.
+//
+// UnmarshalText must be able to decode the form generated by MarshalText.
+// UnmarshalText must copy the text if it wishes to retain the text
+// after returning.
+type TextUnmarshaler interface {
+ UnmarshalText(text []byte) error
+}
diff --git a/libgo/go/encoding/gob/codec_test.go b/libgo/go/encoding/gob/codec_test.go
index 9e38e31d5da..b40f78360c2 100644
--- a/libgo/go/encoding/gob/codec_test.go
+++ b/libgo/go/encoding/gob/codec_test.go
@@ -1009,24 +1009,6 @@ func TestBadRecursiveType(t *testing.T) {
// Can't test decode easily because we can't encode one, so we can't pass one to a Decoder.
}
-type Bad0 struct {
- CH chan int
- C float64
-}
-
-func TestInvalidField(t *testing.T) {
- var bad0 Bad0
- bad0.CH = make(chan int)
- b := new(bytes.Buffer)
- dummyEncoder := new(Encoder) // sufficient for this purpose.
- dummyEncoder.encode(b, reflect.ValueOf(&bad0), userType(reflect.TypeOf(&bad0)))
- if err := dummyEncoder.err; err == nil {
- t.Error("expected error; got none")
- } else if strings.Index(err.Error(), "type") < 0 {
- t.Error("expected type error; got", err)
- }
-}
-
type Indirect struct {
A ***[3]int
S ***[]int
diff --git a/libgo/go/encoding/gob/debug.go b/libgo/go/encoding/gob/debug.go
index 31d1351fc4f..6117eb08373 100644
--- a/libgo/go/encoding/gob/debug.go
+++ b/libgo/go/encoding/gob/debug.go
@@ -415,6 +415,16 @@ func (deb *debugger) typeDefinition(indent tab, id typeId) {
deb.delta(1)
com := deb.common()
wire.GobEncoderT = &gobEncoderType{com}
+ case 5: // BinaryMarshaler type, one field of {{Common}}
+ // Field number 0 is CommonType
+ deb.delta(1)
+ com := deb.common()
+ wire.BinaryMarshalerT = &gobEncoderType{com}
+ case 6: // TextMarshaler type, one field of {{Common}}
+ // Field number 0 is CommonType
+ deb.delta(1)
+ com := deb.common()
+ wire.TextMarshalerT = &gobEncoderType{com}
default:
errorf("bad field in type %d", fieldNum)
}
diff --git a/libgo/go/encoding/gob/decode.go b/libgo/go/encoding/gob/decode.go
index 7cc7565409c..3e76f4c9066 100644
--- a/libgo/go/encoding/gob/decode.go
+++ b/libgo/go/encoding/gob/decode.go
@@ -9,6 +9,7 @@ package gob
import (
"bytes"
+ "encoding"
"errors"
"io"
"math"
@@ -450,11 +451,11 @@ type decEngine struct {
// allocate makes sure storage is available for an object of underlying type rtyp
// that is indir levels of indirection through p.
-func allocate(rtyp reflect.Type, p uintptr, indir int) uintptr {
+func allocate(rtyp reflect.Type, p unsafe.Pointer, indir int) unsafe.Pointer {
if indir == 0 {
return p
}
- up := unsafe.Pointer(p)
+ up := p
if indir > 1 {
up = decIndirect(up, indir)
}
@@ -462,13 +463,13 @@ func allocate(rtyp reflect.Type, p uintptr, indir int) uintptr {
// Allocate object.
*(*unsafe.Pointer)(up) = unsafe.Pointer(reflect.New(rtyp).Pointer())
}
- return *(*uintptr)(up)
+ return *(*unsafe.Pointer)(up)
}
// decodeSingle decodes a top-level value that is not a struct and stores it through p.
// Such values are preceded by a zero, making them have the memory layout of a
// struct field (although with an illegal field number).
-func (dec *Decoder) decodeSingle(engine *decEngine, ut *userTypeInfo, basep uintptr) {
+func (dec *Decoder) decodeSingle(engine *decEngine, ut *userTypeInfo, basep unsafe.Pointer) {
state := dec.newDecoderState(&dec.buf)
state.fieldnum = singletonField
delta := int(state.decodeUint())
@@ -479,7 +480,7 @@ func (dec *Decoder) decodeSingle(engine *decEngine, ut *userTypeInfo, basep uint
if instr.indir != ut.indir {
errorf("internal error: inconsistent indirection instr %d ut %d", instr.indir, ut.indir)
}
- ptr := unsafe.Pointer(basep) // offset will be zero
+ ptr := basep // offset will be zero
if instr.indir > 1 {
ptr = decIndirect(ptr, instr.indir)
}
@@ -492,7 +493,7 @@ func (dec *Decoder) decodeSingle(engine *decEngine, ut *userTypeInfo, basep uint
// differ from ut.indir, which was computed when the engine was built.
// This state cannot arise for decodeSingle, which is called directly
// from the user's value, not from the innards of an engine.
-func (dec *Decoder) decodeStruct(engine *decEngine, ut *userTypeInfo, p uintptr, indir int) {
+func (dec *Decoder) decodeStruct(engine *decEngine, ut *userTypeInfo, p unsafe.Pointer, indir int) {
p = allocate(ut.base, p, indir)
state := dec.newDecoderState(&dec.buf)
state.fieldnum = -1
@@ -511,7 +512,7 @@ func (dec *Decoder) decodeStruct(engine *decEngine, ut *userTypeInfo, p uintptr,
break
}
instr := &engine.instr[fieldnum]
- p := unsafe.Pointer(basep + instr.offset)
+ p := unsafe.Pointer(uintptr(basep) + instr.offset)
if instr.indir > 1 {
p = decIndirect(p, instr.indir)
}
@@ -559,25 +560,25 @@ func (dec *Decoder) ignoreSingle(engine *decEngine) {
}
// decodeArrayHelper does the work for decoding arrays and slices.
-func (dec *Decoder) decodeArrayHelper(state *decoderState, p uintptr, elemOp decOp, elemWid uintptr, length, elemIndir int, ovfl error) {
+func (dec *Decoder) decodeArrayHelper(state *decoderState, p unsafe.Pointer, elemOp decOp, elemWid uintptr, length, elemIndir int, ovfl error) {
instr := &decInstr{elemOp, 0, elemIndir, 0, ovfl}
for i := 0; i < length; i++ {
if state.b.Len() == 0 {
errorf("decoding array or slice: length exceeds input size (%d elements)", length)
}
- up := unsafe.Pointer(p)
+ up := p
if elemIndir > 1 {
up = decIndirect(up, elemIndir)
}
elemOp(instr, state, up)
- p += uintptr(elemWid)
+ p = unsafe.Pointer(uintptr(p) + elemWid)
}
}
// decodeArray decodes an array and stores it through p, that is, p points to the zeroth element.
// The length is an unsigned integer preceding the elements. Even though the length is redundant
// (it's part of the type), it's a useful check and is included in the encoding.
-func (dec *Decoder) decodeArray(atyp reflect.Type, state *decoderState, p uintptr, elemOp decOp, elemWid uintptr, length, indir, elemIndir int, ovfl error) {
+func (dec *Decoder) decodeArray(atyp reflect.Type, state *decoderState, p unsafe.Pointer, elemOp decOp, elemWid uintptr, length, indir, elemIndir int, ovfl error) {
if indir > 0 {
p = allocate(atyp, p, 1) // All but the last level has been allocated by dec.Indirect
}
@@ -591,7 +592,7 @@ func (dec *Decoder) decodeArray(atyp reflect.Type, state *decoderState, p uintpt
// unlike the other items we can't use a pointer directly.
func decodeIntoValue(state *decoderState, op decOp, indir int, v reflect.Value, ovfl error) reflect.Value {
instr := &decInstr{op, 0, indir, 0, ovfl}
- up := unsafe.Pointer(unsafeAddr(v))
+ up := unsafeAddr(v)
if indir > 1 {
up = decIndirect(up, indir)
}
@@ -603,7 +604,7 @@ func decodeIntoValue(state *decoderState, op decOp, indir int, v reflect.Value,
// Maps are encoded as a length followed by key:value pairs.
// Because the internals of maps are not visible to us, we must
// use reflection rather than pointer magic.
-func (dec *Decoder) decodeMap(mtyp reflect.Type, state *decoderState, p uintptr, keyOp, elemOp decOp, indir, keyIndir, elemIndir int, ovfl error) {
+func (dec *Decoder) decodeMap(mtyp reflect.Type, state *decoderState, p unsafe.Pointer, keyOp, elemOp decOp, indir, keyIndir, elemIndir int, ovfl error) {
if indir > 0 {
p = allocate(mtyp, p, 1) // All but the last level has been allocated by dec.Indirect
}
@@ -673,7 +674,7 @@ func (dec *Decoder) decodeSlice(atyp reflect.Type, state *decoderState, p uintpt
hdrp.Cap = n
}
hdrp.Len = n
- dec.decodeArrayHelper(state, hdrp.Data, elemOp, elemWid, n, elemIndir, ovfl)
+ dec.decodeArrayHelper(state, unsafe.Pointer(hdrp.Data), elemOp, elemWid, n, elemIndir, ovfl)
}
// ignoreSlice skips over the data for a slice value with no destination.
@@ -693,7 +694,7 @@ func setInterfaceValue(ivalue reflect.Value, value reflect.Value) {
// decodeInterface decodes an interface value and stores it through p.
// Interfaces are encoded as the name of a concrete type followed by a value.
// If the name is empty, the value is nil and no value is sent.
-func (dec *Decoder) decodeInterface(ityp reflect.Type, state *decoderState, p uintptr, indir int) {
+func (dec *Decoder) decodeInterface(ityp reflect.Type, state *decoderState, p unsafe.Pointer, indir int) {
// Create a writable interface reflect.Value. We need one even for the nil case.
ivalue := allocValue(ityp)
// Read the name of the concrete type.
@@ -767,15 +768,22 @@ func (dec *Decoder) ignoreInterface(state *decoderState) {
// decodeGobDecoder decodes something implementing the GobDecoder interface.
// The data is encoded as a byte slice.
-func (dec *Decoder) decodeGobDecoder(state *decoderState, v reflect.Value) {
+func (dec *Decoder) decodeGobDecoder(ut *userTypeInfo, state *decoderState, v reflect.Value) {
// Read the bytes for the value.
b := make([]byte, state.decodeUint())
_, err := state.b.Read(b)
if err != nil {
error_(err)
}
- // We know it's a GobDecoder, so just call the method directly.
- err = v.Interface().(GobDecoder).GobDecode(b)
+ // We know it's one of these.
+ switch ut.externalDec {
+ case xGob:
+ err = v.Interface().(GobDecoder).GobDecode(b)
+ case xBinary:
+ err = v.Interface().(encoding.BinaryUnmarshaler).UnmarshalBinary(b)
+ case xText:
+ err = v.Interface().(encoding.TextUnmarshaler).UnmarshalText(b)
+ }
if err != nil {
error_(err)
}
@@ -825,9 +833,10 @@ var decIgnoreOpMap = map[typeId]decOp{
func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string, inProgress map[reflect.Type]*decOp) (*decOp, int) {
ut := userType(rt)
// If the type implements GobEncoder, we handle it without further processing.
- if ut.isGobDecoder {
+ if ut.externalDec != 0 {
return dec.gobDecodeOpFor(ut)
}
+
// If this type is already in progress, it's a recursive type (e.g. map[string]*T).
// Return the pointer to the op we're already building.
if opPtr := inProgress[rt]; opPtr != nil {
@@ -850,7 +859,7 @@ func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string, inProg
elemOp, elemIndir := dec.decOpFor(elemId, t.Elem(), name, inProgress)
ovfl := overflow(name)
op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
- state.dec.decodeArray(t, state, uintptr(p), *elemOp, t.Elem().Size(), t.Len(), i.indir, elemIndir, ovfl)
+ state.dec.decodeArray(t, state, p, *elemOp, t.Elem().Size(), t.Len(), i.indir, elemIndir, ovfl)
}
case reflect.Map:
@@ -860,8 +869,7 @@ func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string, inProg
elemOp, elemIndir := dec.decOpFor(elemId, t.Elem(), "element of "+name, inProgress)
ovfl := overflow(name)
op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
- up := unsafe.Pointer(p)
- state.dec.decodeMap(t, state, uintptr(up), *keyOp, *elemOp, i.indir, keyIndir, elemIndir, ovfl)
+ state.dec.decodeMap(t, state, p, *keyOp, *elemOp, i.indir, keyIndir, elemIndir, ovfl)
}
case reflect.Slice:
@@ -890,11 +898,11 @@ func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string, inProg
}
op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
// indirect through enginePtr to delay evaluation for recursive structs.
- dec.decodeStruct(*enginePtr, userType(typ), uintptr(p), i.indir)
+ dec.decodeStruct(*enginePtr, userType(typ), p, i.indir)
}
case reflect.Interface:
op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
- state.dec.decodeInterface(t, state, uintptr(p), i.indir)
+ state.dec.decodeInterface(t, state, p, i.indir)
}
}
}
@@ -955,7 +963,7 @@ func (dec *Decoder) decIgnoreOpFor(wireId typeId) decOp {
state.dec.ignoreStruct(*enginePtr)
}
- case wire.GobEncoderT != nil:
+ case wire.GobEncoderT != nil, wire.BinaryMarshalerT != nil, wire.TextMarshalerT != nil:
op = func(i *decInstr, state *decoderState, p unsafe.Pointer) {
state.dec.ignoreGobDecoder(state)
}
@@ -994,7 +1002,7 @@ func (dec *Decoder) gobDecodeOpFor(ut *userTypeInfo) (*decOp, int) {
} else {
v = reflect.NewAt(rcvrType, p).Elem()
}
- state.dec.decodeGobDecoder(state, v)
+ state.dec.decodeGobDecoder(ut, state, v)
}
return &op, int(ut.indir)
@@ -1011,12 +1019,18 @@ func (dec *Decoder) compatibleType(fr reflect.Type, fw typeId, inProgress map[re
inProgress[fr] = fw
ut := userType(fr)
wire, ok := dec.wireType[fw]
- // If fr is a GobDecoder, the wire type must be GobEncoder.
- // And if fr is not a GobDecoder, the wire type must not be either.
- if ut.isGobDecoder != (ok && wire.GobEncoderT != nil) { // the parentheses look odd but are correct.
+ // If wire was encoded with an encoding method, fr must have that method.
+ // And if not, it must not.
+ // At most one of the booleans in ut is set.
+ // We could possibly relax this constraint in the future in order to
+ // choose the decoding method using the data in the wireType.
+ // The parentheses look odd but are correct.
+ if (ut.externalDec == xGob) != (ok && wire.GobEncoderT != nil) ||
+ (ut.externalDec == xBinary) != (ok && wire.BinaryMarshalerT != nil) ||
+ (ut.externalDec == xText) != (ok && wire.TextMarshalerT != nil) {
return false
}
- if ut.isGobDecoder { // This test trumps all others.
+ if ut.externalDec != 0 { // This test trumps all others.
return true
}
switch t := ut.base; t.Kind() {
@@ -1115,8 +1129,7 @@ func (dec *Decoder) compileIgnoreSingle(remoteId typeId) (engine *decEngine, err
func (dec *Decoder) compileDec(remoteId typeId, ut *userTypeInfo) (engine *decEngine, err error) {
rt := ut.base
srt := rt
- if srt.Kind() != reflect.Struct ||
- ut.isGobDecoder {
+ if srt.Kind() != reflect.Struct || ut.externalDec != 0 {
return dec.compileSingle(remoteId, ut)
}
var wireStruct *structType
@@ -1224,14 +1237,14 @@ func (dec *Decoder) decodeValue(wireId typeId, val reflect.Value) {
return
}
engine := *enginePtr
- if st := base; st.Kind() == reflect.Struct && !ut.isGobDecoder {
+ if st := base; st.Kind() == reflect.Struct && ut.externalDec == 0 {
if engine.numInstr == 0 && st.NumField() > 0 && len(dec.wireType[wireId].StructT.Field) > 0 {
name := base.Name()
errorf("type mismatch: no fields matched compiling decoder for %s", name)
}
- dec.decodeStruct(engine, ut, uintptr(unsafeAddr(val)), ut.indir)
+ dec.decodeStruct(engine, ut, unsafeAddr(val), ut.indir)
} else {
- dec.decodeSingle(engine, ut, uintptr(unsafeAddr(val)))
+ dec.decodeSingle(engine, ut, unsafeAddr(val))
}
}
@@ -1283,13 +1296,13 @@ func init() {
// into existing structs or slices cannot be addressed,
// so simulate it by returning a pointer to a copy.
// Each call allocates once.
-func unsafeAddr(v reflect.Value) uintptr {
+func unsafeAddr(v reflect.Value) unsafe.Pointer {
if v.CanAddr() {
- return v.UnsafeAddr()
+ return unsafe.Pointer(v.UnsafeAddr())
}
x := reflect.New(v.Type()).Elem()
x.Set(v)
- return x.UnsafeAddr()
+ return unsafe.Pointer(x.UnsafeAddr())
}
// Gob depends on being able to take the address
diff --git a/libgo/go/encoding/gob/doc.go b/libgo/go/encoding/gob/doc.go
index 5bd61b12eb1..28f0c05a5c5 100644
--- a/libgo/go/encoding/gob/doc.go
+++ b/libgo/go/encoding/gob/doc.go
@@ -8,6 +8,12 @@ Encoder (transmitter) and a Decoder (receiver). A typical use is transporting
arguments and results of remote procedure calls (RPCs) such as those provided by
package "rpc".
+The implementation compiles a custom codec for each data type in the stream and
+is most efficient when a single Encoder is used to transmit a stream of values,
+amortizing the cost of compilation.
+
+Basics
+
A stream of gobs is self-describing. Each data item in the stream is preceded by
a specification of its type, expressed in terms of a small set of predefined
types. Pointers are not transmitted, but the things they point to are
@@ -20,6 +26,8 @@ all type information is sent before it is needed. At the receive side, a
Decoder retrieves values from the encoded stream and unpacks them into local
variables.
+Types and Values
+
The source and destination values/types need not correspond exactly. For structs,
fields (identified by name) that are in the source but absent from the receiving
variable will be ignored. Fields that are in the receiving variable but missing
@@ -67,19 +75,29 @@ point values may be received into any floating point variable. However,
the destination variable must be able to represent the value or the decode
operation will fail.
-Structs, arrays and slices are also supported. Structs encode and
-decode only exported fields. Strings and arrays of bytes are supported
-with a special, efficient representation (see below). When a slice
-is decoded, if the existing slice has capacity the slice will be
-extended in place; if not, a new array is allocated. Regardless,
-the length of the resulting slice reports the number of elements
-decoded.
+Structs, arrays and slices are also supported. Structs encode and decode only
+exported fields. Strings and arrays of bytes are supported with a special,
+efficient representation (see below). When a slice is decoded, if the existing
+slice has capacity the slice will be extended in place; if not, a new array is
+allocated. Regardless, the length of the resulting slice reports the number of
+elements decoded.
+
+Functions and channels will not be sent in a gob. Attempting to encode such a value
+at top the level will fail. A struct field of chan or func type is treated exactly
+like an unexported field and is ignored.
+
+Gob can encode a value of any type implementing the GobEncoder,
+encoding.BinaryMarshaler, or encoding.TextMarshaler interfaces by calling the
+corresponding method, in that order of preference.
+
+Gob can decode a value of any type implementing the GobDecoder,
+encoding.BinaryUnmarshaler, or encoding.TextUnmarshaler interfaces by calling
+the corresponding method, again in that order of preference.
-Functions and channels cannot be sent in a gob. Attempting
-to encode a value that contains one will fail.
+Encoding Details
-The rest of this comment documents the encoding, details that are not important
-for most users. Details are presented bottom-up.
+This section documents the encoding, details that are not important for most
+users. Details are presented bottom-up.
An unsigned integer is sent one of two ways. If it is less than 128, it is sent
as a byte with that value. Otherwise it is sent as a minimal-length big-endian
diff --git a/libgo/go/encoding/gob/encode.go b/libgo/go/encoding/gob/encode.go
index ea37a6cbd58..d158b6442a8 100644
--- a/libgo/go/encoding/gob/encode.go
+++ b/libgo/go/encoding/gob/encode.go
@@ -6,6 +6,7 @@ package gob
import (
"bytes"
+ "encoding"
"math"
"reflect"
"unsafe"
@@ -338,14 +339,14 @@ type encEngine struct {
const singletonField = 0
// encodeSingle encodes a single top-level non-struct value.
-func (enc *Encoder) encodeSingle(b *bytes.Buffer, engine *encEngine, basep uintptr) {
+func (enc *Encoder) encodeSingle(b *bytes.Buffer, engine *encEngine, basep unsafe.Pointer) {
state := enc.newEncoderState(b)
state.fieldnum = singletonField
// There is no surrounding struct to frame the transmission, so we must
// generate data even if the item is zero. To do this, set sendZero.
state.sendZero = true
instr := &engine.instr[singletonField]
- p := unsafe.Pointer(basep) // offset will be zero
+ p := basep // offset will be zero
if instr.indir > 0 {
if p = encIndirect(p, instr.indir); p == nil {
return
@@ -356,12 +357,12 @@ func (enc *Encoder) encodeSingle(b *bytes.Buffer, engine *encEngine, basep uintp
}
// encodeStruct encodes a single struct value.
-func (enc *Encoder) encodeStruct(b *bytes.Buffer, engine *encEngine, basep uintptr) {
+func (enc *Encoder) encodeStruct(b *bytes.Buffer, engine *encEngine, basep unsafe.Pointer) {
state := enc.newEncoderState(b)
state.fieldnum = -1
for i := 0; i < len(engine.instr); i++ {
instr := &engine.instr[i]
- p := unsafe.Pointer(basep + instr.offset)
+ p := unsafe.Pointer(uintptr(basep) + instr.offset)
if instr.indir > 0 {
if p = encIndirect(p, instr.indir); p == nil {
continue
@@ -373,22 +374,22 @@ func (enc *Encoder) encodeStruct(b *bytes.Buffer, engine *encEngine, basep uintp
}
// encodeArray encodes the array whose 0th element is at p.
-func (enc *Encoder) encodeArray(b *bytes.Buffer, p uintptr, op encOp, elemWid uintptr, elemIndir int, length int) {
+func (enc *Encoder) encodeArray(b *bytes.Buffer, p unsafe.Pointer, op encOp, elemWid uintptr, elemIndir int, length int) {
state := enc.newEncoderState(b)
state.fieldnum = -1
state.sendZero = true
state.encodeUint(uint64(length))
for i := 0; i < length; i++ {
elemp := p
- up := unsafe.Pointer(elemp)
if elemIndir > 0 {
- if up = encIndirect(up, elemIndir); up == nil {
+ up := encIndirect(elemp, elemIndir)
+ if up == nil {
errorf("encodeArray: nil element")
}
- elemp = uintptr(up)
+ elemp = up
}
- op(nil, state, unsafe.Pointer(elemp))
- p += uintptr(elemWid)
+ op(nil, state, elemp)
+ p = unsafe.Pointer(uintptr(p) + elemWid)
}
enc.freeEncoderState(state)
}
@@ -401,7 +402,7 @@ func encodeReflectValue(state *encoderState, v reflect.Value, op encOp, indir in
if !v.IsValid() {
errorf("encodeReflectValue: nil element")
}
- op(nil, state, unsafe.Pointer(unsafeAddr(v)))
+ op(nil, state, unsafeAddr(v))
}
// encodeMap encodes a map as unsigned count followed by key:value pairs.
@@ -474,7 +475,7 @@ func (enc *Encoder) encodeInterface(b *bytes.Buffer, iv reflect.Value) {
enc.freeEncoderState(state)
}
-// isZero returns whether the value is the zero of its type.
+// isZero reports whether the value is the zero of its type.
func isZero(val reflect.Value) bool {
switch val.Kind() {
case reflect.Array:
@@ -511,10 +512,20 @@ func isZero(val reflect.Value) bool {
// encGobEncoder encodes a value that implements the GobEncoder interface.
// The data is sent as a byte array.
-func (enc *Encoder) encodeGobEncoder(b *bytes.Buffer, v reflect.Value) {
+func (enc *Encoder) encodeGobEncoder(b *bytes.Buffer, ut *userTypeInfo, v reflect.Value) {
// TODO: should we catch panics from the called method?
- // We know it's a GobEncoder, so just call the method directly.
- data, err := v.Interface().(GobEncoder).GobEncode()
+
+ var data []byte
+ var err error
+ // We know it's one of these.
+ switch ut.externalEnc {
+ case xGob:
+ data, err = v.Interface().(GobEncoder).GobEncode()
+ case xBinary:
+ data, err = v.Interface().(encoding.BinaryMarshaler).MarshalBinary()
+ case xText:
+ data, err = v.Interface().(encoding.TextMarshaler).MarshalText()
+ }
if err != nil {
error_(err)
}
@@ -550,7 +561,7 @@ var encOpTable = [...]encOp{
func (enc *Encoder) encOpFor(rt reflect.Type, inProgress map[reflect.Type]*encOp) (*encOp, int) {
ut := userType(rt)
// If the type implements GobEncoder, we handle it without further processing.
- if ut.isGobEncoder {
+ if ut.externalEnc != 0 {
return enc.gobEncodeOpFor(ut)
}
// If this type is already in progress, it's a recursive type (e.g. map[string]*T).
@@ -575,21 +586,21 @@ func (enc *Encoder) encOpFor(rt reflect.Type, inProgress map[reflect.Type]*encOp
break
}
// Slices have a header; we decode it to find the underlying array.
- elemOp, indir := enc.encOpFor(t.Elem(), inProgress)
+ elemOp, elemIndir := enc.encOpFor(t.Elem(), inProgress)
op = func(i *encInstr, state *encoderState, p unsafe.Pointer) {
slice := (*reflect.SliceHeader)(p)
if !state.sendZero && slice.Len == 0 {
return
}
state.update(i)
- state.enc.encodeArray(state.b, slice.Data, *elemOp, t.Elem().Size(), indir, int(slice.Len))
+ state.enc.encodeArray(state.b, unsafe.Pointer(slice.Data), *elemOp, t.Elem().Size(), elemIndir, int(slice.Len))
}
case reflect.Array:
// True arrays have size in the type.
- elemOp, indir := enc.encOpFor(t.Elem(), inProgress)
+ elemOp, elemIndir := enc.encOpFor(t.Elem(), inProgress)
op = func(i *encInstr, state *encoderState, p unsafe.Pointer) {
state.update(i)
- state.enc.encodeArray(state.b, uintptr(p), *elemOp, t.Elem().Size(), indir, t.Len())
+ state.enc.encodeArray(state.b, p, *elemOp, t.Elem().Size(), elemIndir, t.Len())
}
case reflect.Map:
keyOp, keyIndir := enc.encOpFor(t.Key(), inProgress)
@@ -615,7 +626,7 @@ func (enc *Encoder) encOpFor(rt reflect.Type, inProgress map[reflect.Type]*encOp
op = func(i *encInstr, state *encoderState, p unsafe.Pointer) {
state.update(i)
// indirect through info to delay evaluation for recursive structs
- state.enc.encodeStruct(state.b, info.encoder, uintptr(p))
+ state.enc.encodeStruct(state.b, info.encoder, p)
}
case reflect.Interface:
op = func(i *encInstr, state *encoderState, p unsafe.Pointer) {
@@ -661,7 +672,7 @@ func (enc *Encoder) gobEncodeOpFor(ut *userTypeInfo) (*encOp, int) {
return
}
state.update(i)
- state.enc.encodeGobEncoder(state.b, v)
+ state.enc.encodeGobEncoder(state.b, ut, v)
}
return &op, int(ut.encIndir) // encIndir: op will get called with p == address of receiver.
}
@@ -672,14 +683,13 @@ func (enc *Encoder) compileEnc(ut *userTypeInfo) *encEngine {
engine := new(encEngine)
seen := make(map[reflect.Type]*encOp)
rt := ut.base
- if ut.isGobEncoder {
+ if ut.externalEnc != 0 {
rt = ut.user
}
- if !ut.isGobEncoder &&
- srt.Kind() == reflect.Struct {
+ if ut.externalEnc == 0 && srt.Kind() == reflect.Struct {
for fieldNum, wireFieldNum := 0, 0; fieldNum < srt.NumField(); fieldNum++ {
f := srt.Field(fieldNum)
- if !isExported(f.Name) {
+ if !isSent(&f) {
continue
}
op, indir := enc.encOpFor(f.Type, seen)
@@ -736,13 +746,13 @@ func (enc *Encoder) encode(b *bytes.Buffer, value reflect.Value, ut *userTypeInf
defer catchError(&enc.err)
engine := enc.lockAndGetEncEngine(ut)
indir := ut.indir
- if ut.isGobEncoder {
+ if ut.externalEnc != 0 {
indir = int(ut.encIndir)
}
for i := 0; i < indir; i++ {
value = reflect.Indirect(value)
}
- if !ut.isGobEncoder && value.Type().Kind() == reflect.Struct {
+ if ut.externalEnc == 0 && value.Type().Kind() == reflect.Struct {
enc.encodeStruct(b, engine, unsafeAddr(value))
} else {
enc.encodeSingle(b, engine, unsafeAddr(value))
diff --git a/libgo/go/encoding/gob/encoder.go b/libgo/go/encoding/gob/encoder.go
index f669c3d5b24..a3301c3bd33 100644
--- a/libgo/go/encoding/gob/encoder.go
+++ b/libgo/go/encoding/gob/encoder.go
@@ -6,7 +6,6 @@ package gob
import (
"bytes"
- "errors"
"io"
"reflect"
"sync"
@@ -54,10 +53,6 @@ func (enc *Encoder) popWriter() {
enc.w = enc.w[0 : len(enc.w)-1]
}
-func (enc *Encoder) badType(rt reflect.Type) {
- enc.setError(errors.New("gob: can't encode type " + rt.String()))
-}
-
func (enc *Encoder) setError(err error) {
if enc.err == nil { // remember the first.
enc.err = err
@@ -135,7 +130,7 @@ func (enc *Encoder) sendActualType(w io.Writer, state *encoderState, ut *userTyp
// sendType sends the type info to the other side, if necessary.
func (enc *Encoder) sendType(w io.Writer, state *encoderState, origt reflect.Type) (sent bool) {
ut := userType(origt)
- if ut.isGobEncoder {
+ if ut.externalEnc != 0 {
// The rules are different: regardless of the underlying type's representation,
// we need to tell the other side that the base type is a GobEncoder.
return enc.sendActualType(w, state, ut, ut.base)
@@ -163,8 +158,7 @@ func (enc *Encoder) sendType(w io.Writer, state *encoderState, origt reflect.Typ
// structs must be sent so we know their fields.
break
case reflect.Chan, reflect.Func:
- // Probably a bad field in a struct.
- enc.badType(rt)
+ // If we get here, it's a field of a struct; ignore it.
return
}
@@ -184,7 +178,7 @@ func (enc *Encoder) sendTypeDescriptor(w io.Writer, state *encoderState, ut *use
// Make sure the type is known to the other side.
// First, have we already sent this type?
rt := ut.base
- if ut.isGobEncoder {
+ if ut.externalEnc != 0 {
rt = ut.user
}
if _, alreadySent := enc.sent[rt]; !alreadySent {
diff --git a/libgo/go/encoding/gob/encoder_test.go b/libgo/go/encoding/gob/encoder_test.go
index b684772c691..4ecf51d122b 100644
--- a/libgo/go/encoding/gob/encoder_test.go
+++ b/libgo/go/encoding/gob/encoder_test.go
@@ -131,7 +131,7 @@ func TestBadData(t *testing.T) {
corruptDataCheck("\x03now is the time for all good men", errBadType, t)
}
-// Types not supported by the Encoder.
+// Types not supported at top level by the Encoder.
var unsupportedValues = []interface{}{
make(chan int),
func(a int) bool { return true },
@@ -662,19 +662,35 @@ func TestSequentialDecoder(t *testing.T) {
}
}
-// Should be able to have unrepresentable fields (chan, func) as long as they
-// are unexported.
+// Should be able to have unrepresentable fields (chan, func, *chan etc.); we just ignore them.
type Bug2 struct {
- A int
- b chan int
-}
-
-func TestUnexportedChan(t *testing.T) {
- b := Bug2{23, make(chan int)}
- var stream bytes.Buffer
- enc := NewEncoder(&stream)
- if err := enc.Encode(b); err != nil {
- t.Fatalf("error encoding unexported channel: %s", err)
+ A int
+ C chan int
+ CP *chan int
+ F func()
+ FPP **func()
+}
+
+func TestChanFuncIgnored(t *testing.T) {
+ c := make(chan int)
+ f := func() {}
+ fp := &f
+ b0 := Bug2{23, c, &c, f, &fp}
+ var buf bytes.Buffer
+ enc := NewEncoder(&buf)
+ if err := enc.Encode(b0); err != nil {
+ t.Fatal("error encoding:", err)
+ }
+ var b1 Bug2
+ err := NewDecoder(&buf).Decode(&b1)
+ if err != nil {
+ t.Fatal("decode:", err)
+ }
+ if b1.A != b0.A {
+ t.Fatalf("got %d want %d", b1.A, b0.A)
+ }
+ if b1.C != nil || b1.CP != nil || b1.F != nil || b1.FPP != nil {
+ t.Fatal("unexpected value for chan or func")
}
}
diff --git a/libgo/go/encoding/gob/gobencdec_test.go b/libgo/go/encoding/gob/gobencdec_test.go
index ddcd80b1a7a..301551db48a 100644
--- a/libgo/go/encoding/gob/gobencdec_test.go
+++ b/libgo/go/encoding/gob/gobencdec_test.go
@@ -34,6 +34,14 @@ type Gobber int
type ValueGobber string // encodes with a value, decodes with a pointer.
+type BinaryGobber int
+
+type BinaryValueGobber string
+
+type TextGobber int
+
+type TextValueGobber string
+
// The relevant methods
func (g *ByteStruct) GobEncode() ([]byte, error) {
@@ -101,6 +109,24 @@ func (g *Gobber) GobDecode(data []byte) error {
return err
}
+func (g *BinaryGobber) MarshalBinary() ([]byte, error) {
+ return []byte(fmt.Sprintf("VALUE=%d", *g)), nil
+}
+
+func (g *BinaryGobber) UnmarshalBinary(data []byte) error {
+ _, err := fmt.Sscanf(string(data), "VALUE=%d", (*int)(g))
+ return err
+}
+
+func (g *TextGobber) MarshalText() ([]byte, error) {
+ return []byte(fmt.Sprintf("VALUE=%d", *g)), nil
+}
+
+func (g *TextGobber) UnmarshalText(data []byte) error {
+ _, err := fmt.Sscanf(string(data), "VALUE=%d", (*int)(g))
+ return err
+}
+
func (v ValueGobber) GobEncode() ([]byte, error) {
return []byte(fmt.Sprintf("VALUE=%s", v)), nil
}
@@ -110,6 +136,24 @@ func (v *ValueGobber) GobDecode(data []byte) error {
return err
}
+func (v BinaryValueGobber) MarshalBinary() ([]byte, error) {
+ return []byte(fmt.Sprintf("VALUE=%s", v)), nil
+}
+
+func (v *BinaryValueGobber) UnmarshalBinary(data []byte) error {
+ _, err := fmt.Sscanf(string(data), "VALUE=%s", (*string)(v))
+ return err
+}
+
+func (v TextValueGobber) MarshalText() ([]byte, error) {
+ return []byte(fmt.Sprintf("VALUE=%s", v)), nil
+}
+
+func (v *TextValueGobber) UnmarshalText(data []byte) error {
+ _, err := fmt.Sscanf(string(data), "VALUE=%s", (*string)(v))
+ return err
+}
+
// Structs that include GobEncodable fields.
type GobTest0 struct {
@@ -130,28 +174,42 @@ type GobTest2 struct {
type GobTest3 struct {
X int // guarantee we have something in common with GobTest*
G *Gobber
+ B *BinaryGobber
+ T *TextGobber
}
type GobTest4 struct {
- X int // guarantee we have something in common with GobTest*
- V ValueGobber
+ X int // guarantee we have something in common with GobTest*
+ V ValueGobber
+ BV BinaryValueGobber
+ TV TextValueGobber
}
type GobTest5 struct {
- X int // guarantee we have something in common with GobTest*
- V *ValueGobber
+ X int // guarantee we have something in common with GobTest*
+ V *ValueGobber
+ BV *BinaryValueGobber
+ TV *TextValueGobber
}
type GobTest6 struct {
- X int // guarantee we have something in common with GobTest*
- V ValueGobber
- W *ValueGobber
+ X int // guarantee we have something in common with GobTest*
+ V ValueGobber
+ W *ValueGobber
+ BV BinaryValueGobber
+ BW *BinaryValueGobber
+ TV TextValueGobber
+ TW *TextValueGobber
}
type GobTest7 struct {
- X int // guarantee we have something in common with GobTest*
- V *ValueGobber
- W ValueGobber
+ X int // guarantee we have something in common with GobTest*
+ V *ValueGobber
+ W ValueGobber
+ BV *BinaryValueGobber
+ BW BinaryValueGobber
+ TV *TextValueGobber
+ TW TextValueGobber
}
type GobTestIgnoreEncoder struct {
@@ -198,7 +256,9 @@ func TestGobEncoderField(t *testing.T) {
// Now a field that's not a structure.
b.Reset()
gobber := Gobber(23)
- err = enc.Encode(GobTest3{17, &gobber})
+ bgobber := BinaryGobber(24)
+ tgobber := TextGobber(25)
+ err = enc.Encode(GobTest3{17, &gobber, &bgobber, &tgobber})
if err != nil {
t.Fatal("encode error:", err)
}
@@ -207,7 +267,7 @@ func TestGobEncoderField(t *testing.T) {
if err != nil {
t.Fatal("decode error:", err)
}
- if *y.G != 23 {
+ if *y.G != 23 || *y.B != 24 || *y.T != 25 {
t.Errorf("expected '23 got %d", *y.G)
}
}
@@ -357,7 +417,7 @@ func TestGobEncoderValueEncoder(t *testing.T) {
// first, string in field to byte in field
b := new(bytes.Buffer)
enc := NewEncoder(b)
- err := enc.Encode(GobTest4{17, ValueGobber("hello")})
+ err := enc.Encode(GobTest4{17, ValueGobber("hello"), BinaryValueGobber("ΚαλημέÏα"), TextValueGobber("ã“ã‚“ã«ã¡ã¯")})
if err != nil {
t.Fatal("encode error:", err)
}
@@ -367,8 +427,8 @@ func TestGobEncoderValueEncoder(t *testing.T) {
if err != nil {
t.Fatal("decode error:", err)
}
- if *x.V != "hello" {
- t.Errorf("expected `hello` got %s", x.V)
+ if *x.V != "hello" || *x.BV != "ΚαλημέÏα" || *x.TV != "ã“ã‚“ã«ã¡ã¯" {
+ t.Errorf("expected `hello` got %s", *x.V)
}
}
@@ -377,13 +437,17 @@ func TestGobEncoderValueEncoder(t *testing.T) {
func TestGobEncoderValueThenPointer(t *testing.T) {
v := ValueGobber("forty-two")
w := ValueGobber("six-by-nine")
+ bv := BinaryValueGobber("1nanocentury")
+ bw := BinaryValueGobber("Ï€seconds")
+ tv := TextValueGobber("gravitationalacceleration")
+ tw := TextValueGobber("π²ft/s²")
// this was a bug: encoding a GobEncoder by value before a GobEncoder
// pointer would cause duplicate type definitions to be sent.
b := new(bytes.Buffer)
enc := NewEncoder(b)
- if err := enc.Encode(GobTest6{42, v, &w}); err != nil {
+ if err := enc.Encode(GobTest6{42, v, &w, bv, &bw, tv, &tw}); err != nil {
t.Fatal("encode error:", err)
}
dec := NewDecoder(b)
@@ -391,6 +455,7 @@ func TestGobEncoderValueThenPointer(t *testing.T) {
if err := dec.Decode(x); err != nil {
t.Fatal("decode error:", err)
}
+
if got, want := x.V, v; got != want {
t.Errorf("v = %q, want %q", got, want)
}
@@ -399,6 +464,24 @@ func TestGobEncoderValueThenPointer(t *testing.T) {
} else if *got != want {
t.Errorf("w = %q, want %q", *got, want)
}
+
+ if got, want := x.BV, bv; got != want {
+ t.Errorf("bv = %q, want %q", got, want)
+ }
+ if got, want := x.BW, bw; got == nil {
+ t.Errorf("bw = nil, want %q", want)
+ } else if *got != want {
+ t.Errorf("bw = %q, want %q", *got, want)
+ }
+
+ if got, want := x.TV, tv; got != want {
+ t.Errorf("tv = %q, want %q", got, want)
+ }
+ if got, want := x.TW, tw; got == nil {
+ t.Errorf("tw = nil, want %q", want)
+ } else if *got != want {
+ t.Errorf("tw = %q, want %q", *got, want)
+ }
}
// Test that we can use a pointer then a value type of a GobEncoder
@@ -406,10 +489,14 @@ func TestGobEncoderValueThenPointer(t *testing.T) {
func TestGobEncoderPointerThenValue(t *testing.T) {
v := ValueGobber("forty-two")
w := ValueGobber("six-by-nine")
+ bv := BinaryValueGobber("1nanocentury")
+ bw := BinaryValueGobber("Ï€seconds")
+ tv := TextValueGobber("gravitationalacceleration")
+ tw := TextValueGobber("π²ft/s²")
b := new(bytes.Buffer)
enc := NewEncoder(b)
- if err := enc.Encode(GobTest7{42, &v, w}); err != nil {
+ if err := enc.Encode(GobTest7{42, &v, w, &bv, bw, &tv, tw}); err != nil {
t.Fatal("encode error:", err)
}
dec := NewDecoder(b)
@@ -417,14 +504,33 @@ func TestGobEncoderPointerThenValue(t *testing.T) {
if err := dec.Decode(x); err != nil {
t.Fatal("decode error:", err)
}
+
if got, want := x.V, v; got == nil {
t.Errorf("v = nil, want %q", want)
} else if *got != want {
- t.Errorf("v = %q, want %q", got, want)
+ t.Errorf("v = %q, want %q", *got, want)
}
if got, want := x.W, w; got != want {
t.Errorf("w = %q, want %q", got, want)
}
+
+ if got, want := x.BV, bv; got == nil {
+ t.Errorf("bv = nil, want %q", want)
+ } else if *got != want {
+ t.Errorf("bv = %q, want %q", *got, want)
+ }
+ if got, want := x.BW, bw; got != want {
+ t.Errorf("bw = %q, want %q", got, want)
+ }
+
+ if got, want := x.TV, tv; got == nil {
+ t.Errorf("tv = nil, want %q", want)
+ } else if *got != want {
+ t.Errorf("tv = %q, want %q", *got, want)
+ }
+ if got, want := x.TW, tw; got != want {
+ t.Errorf("tw = %q, want %q", got, want)
+ }
}
func TestGobEncoderFieldTypeError(t *testing.T) {
@@ -521,7 +627,9 @@ func TestGobEncoderIgnoreNonStructField(t *testing.T) {
// First a field that's a structure.
enc := NewEncoder(b)
gobber := Gobber(23)
- err := enc.Encode(GobTest3{17, &gobber})
+ bgobber := BinaryGobber(24)
+ tgobber := TextGobber(25)
+ err := enc.Encode(GobTest3{17, &gobber, &bgobber, &tgobber})
if err != nil {
t.Fatal("encode error:", err)
}
diff --git a/libgo/go/encoding/gob/timing_test.go b/libgo/go/encoding/gob/timing_test.go
index f589675dd98..9fbb0ac6d5a 100644
--- a/libgo/go/encoding/gob/timing_test.go
+++ b/libgo/go/encoding/gob/timing_test.go
@@ -6,7 +6,6 @@ package gob
import (
"bytes"
- "fmt"
"io"
"os"
"runtime"
@@ -50,6 +49,9 @@ func BenchmarkEndToEndByteBuffer(b *testing.B) {
}
func TestCountEncodeMallocs(t *testing.T) {
+ if testing.Short() {
+ t.Skip("skipping malloc count in short mode")
+ }
if runtime.GOMAXPROCS(0) > 1 {
t.Skip("skipping; GOMAXPROCS>1")
}
@@ -66,10 +68,15 @@ func TestCountEncodeMallocs(t *testing.T) {
t.Fatal("encode:", err)
}
})
- fmt.Printf("mallocs per encode of type Bench: %v\n", allocs)
+ if allocs != 0 {
+ t.Fatalf("mallocs per encode of type Bench: %v; wanted 0\n", allocs)
+ }
}
func TestCountDecodeMallocs(t *testing.T) {
+ if testing.Short() {
+ t.Skip("skipping malloc count in short mode")
+ }
if runtime.GOMAXPROCS(0) > 1 {
t.Skip("skipping; GOMAXPROCS>1")
}
@@ -96,5 +103,7 @@ func TestCountDecodeMallocs(t *testing.T) {
t.Fatal("decode:", err)
}
})
- fmt.Printf("mallocs per decode of type Bench: %v\n", allocs)
+ if allocs != 3 {
+ t.Fatalf("mallocs per decode of type Bench: %v; wanted 3\n", allocs)
+ }
}
diff --git a/libgo/go/encoding/gob/type.go b/libgo/go/encoding/gob/type.go
index 7fa0b499f02..65bf17b7f02 100644
--- a/libgo/go/encoding/gob/type.go
+++ b/libgo/go/encoding/gob/type.go
@@ -5,6 +5,7 @@
package gob
import (
+ "encoding"
"errors"
"fmt"
"os"
@@ -18,14 +19,21 @@ import (
// to the package. It's computed once and stored in a map keyed by reflection
// type.
type userTypeInfo struct {
- user reflect.Type // the type the user handed us
- base reflect.Type // the base type after all indirections
- indir int // number of indirections to reach the base type
- isGobEncoder bool // does the type implement GobEncoder?
- isGobDecoder bool // does the type implement GobDecoder?
- encIndir int8 // number of indirections to reach the receiver type; may be negative
- decIndir int8 // number of indirections to reach the receiver type; may be negative
-}
+ user reflect.Type // the type the user handed us
+ base reflect.Type // the base type after all indirections
+ indir int // number of indirections to reach the base type
+ externalEnc int // xGob, xBinary, or xText
+ externalDec int // xGob, xBinary or xText
+ encIndir int8 // number of indirections to reach the receiver type; may be negative
+ decIndir int8 // number of indirections to reach the receiver type; may be negative
+}
+
+// externalEncoding bits
+const (
+ xGob = 1 + iota // GobEncoder or GobDecoder
+ xBinary // encoding.BinaryMarshaler or encoding.BinaryUnmarshaler
+ xText // encoding.TextMarshaler or encoding.TextUnmarshaler
+)
var (
// Protected by an RWMutex because we read it a lot and write
@@ -75,15 +83,34 @@ func validUserType(rt reflect.Type) (ut *userTypeInfo, err error) {
}
ut.indir++
}
- ut.isGobEncoder, ut.encIndir = implementsInterface(ut.user, gobEncoderInterfaceType)
- ut.isGobDecoder, ut.decIndir = implementsInterface(ut.user, gobDecoderInterfaceType)
+
+ if ok, indir := implementsInterface(ut.user, gobEncoderInterfaceType); ok {
+ ut.externalEnc, ut.encIndir = xGob, indir
+ } else if ok, indir := implementsInterface(ut.user, binaryMarshalerInterfaceType); ok {
+ ut.externalEnc, ut.encIndir = xBinary, indir
+ } else if ok, indir := implementsInterface(ut.user, textMarshalerInterfaceType); ok {
+ ut.externalEnc, ut.encIndir = xText, indir
+ }
+
+ if ok, indir := implementsInterface(ut.user, gobDecoderInterfaceType); ok {
+ ut.externalDec, ut.decIndir = xGob, indir
+ } else if ok, indir := implementsInterface(ut.user, binaryUnmarshalerInterfaceType); ok {
+ ut.externalDec, ut.decIndir = xBinary, indir
+ } else if ok, indir := implementsInterface(ut.user, textUnmarshalerInterfaceType); ok {
+ ut.externalDec, ut.decIndir = xText, indir
+ }
+
userTypeCache[rt] = ut
return
}
var (
- gobEncoderInterfaceType = reflect.TypeOf((*GobEncoder)(nil)).Elem()
- gobDecoderInterfaceType = reflect.TypeOf((*GobDecoder)(nil)).Elem()
+ gobEncoderInterfaceType = reflect.TypeOf((*GobEncoder)(nil)).Elem()
+ gobDecoderInterfaceType = reflect.TypeOf((*GobDecoder)(nil)).Elem()
+ binaryMarshalerInterfaceType = reflect.TypeOf((*encoding.BinaryMarshaler)(nil)).Elem()
+ binaryUnmarshalerInterfaceType = reflect.TypeOf((*encoding.BinaryUnmarshaler)(nil)).Elem()
+ textMarshalerInterfaceType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
+ textUnmarshalerInterfaceType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
)
// implementsInterface reports whether the type implements the
@@ -412,7 +439,7 @@ func newStructType(name string) *structType {
// works through typeIds and userTypeInfos alone.
func newTypeObject(name string, ut *userTypeInfo, rt reflect.Type) (gobType, error) {
// Does this type implement GobEncoder?
- if ut.isGobEncoder {
+ if ut.externalEnc != 0 {
return newGobEncoderType(name), nil
}
var err error
@@ -499,7 +526,7 @@ func newTypeObject(name string, ut *userTypeInfo, rt reflect.Type) (gobType, err
idToType[st.id()] = st
for i := 0; i < t.NumField(); i++ {
f := t.Field(i)
- if !isExported(f.Name) {
+ if !isSent(&f) {
continue
}
typ := userType(f.Type).base
@@ -534,6 +561,25 @@ func isExported(name string) bool {
return unicode.IsUpper(rune)
}
+// isSent reports whether this struct field is to be transmitted.
+// It will be transmitted only if it is exported and not a chan or func field
+// or pointer to chan or func.
+func isSent(field *reflect.StructField) bool {
+ if !isExported(field.Name) {
+ return false
+ }
+ // If the field is a chan or func or pointer thereto, don't send it.
+ // That is, treat it like an unexported field.
+ typ := field.Type
+ for typ.Kind() == reflect.Ptr {
+ typ = typ.Elem()
+ }
+ if typ.Kind() == reflect.Chan || typ.Kind() == reflect.Func {
+ return false
+ }
+ return true
+}
+
// getBaseType returns the Gob type describing the given reflect.Type's base type.
// typeLock must be held.
func getBaseType(name string, rt reflect.Type) (gobType, error) {
@@ -593,11 +639,13 @@ func bootstrapType(name string, e interface{}, expect typeId) typeId {
// To maintain binary compatibility, if you extend this type, always put
// the new fields last.
type wireType struct {
- ArrayT *arrayType
- SliceT *sliceType
- StructT *structType
- MapT *mapType
- GobEncoderT *gobEncoderType
+ ArrayT *arrayType
+ SliceT *sliceType
+ StructT *structType
+ MapT *mapType
+ GobEncoderT *gobEncoderType
+ BinaryMarshalerT *gobEncoderType
+ TextMarshalerT *gobEncoderType
}
func (w *wireType) string() string {
@@ -616,6 +664,10 @@ func (w *wireType) string() string {
return w.MapT.Name
case w.GobEncoderT != nil:
return w.GobEncoderT.Name
+ case w.BinaryMarshalerT != nil:
+ return w.BinaryMarshalerT.Name
+ case w.TextMarshalerT != nil:
+ return w.TextMarshalerT.Name
}
return unknown
}
@@ -631,7 +683,7 @@ var typeInfoMap = make(map[reflect.Type]*typeInfo) // protected by typeLock
// typeLock must be held.
func getTypeInfo(ut *userTypeInfo) (*typeInfo, error) {
rt := ut.base
- if ut.isGobEncoder {
+ if ut.externalEnc != 0 {
// We want the user type, not the base type.
rt = ut.user
}
@@ -646,12 +698,20 @@ func getTypeInfo(ut *userTypeInfo) (*typeInfo, error) {
}
info.id = gt.id()
- if ut.isGobEncoder {
+ if ut.externalEnc != 0 {
userType, err := getType(rt.Name(), ut, rt)
if err != nil {
return nil, err
}
- info.wire = &wireType{GobEncoderT: userType.id().gobType().(*gobEncoderType)}
+ gt := userType.id().gobType().(*gobEncoderType)
+ switch ut.externalEnc {
+ case xGob:
+ info.wire = &wireType{GobEncoderT: gt}
+ case xBinary:
+ info.wire = &wireType{BinaryMarshalerT: gt}
+ case xText:
+ info.wire = &wireType{TextMarshalerT: gt}
+ }
typeInfoMap[ut.user] = info
return info, nil
}
diff --git a/libgo/go/encoding/json/decode.go b/libgo/go/encoding/json/decode.go
index 62ac294b89f..458fb39ec01 100644
--- a/libgo/go/encoding/json/decode.go
+++ b/libgo/go/encoding/json/decode.go
@@ -8,6 +8,7 @@
package json
import (
+ "encoding"
"encoding/base64"
"errors"
"fmt"
@@ -37,9 +38,7 @@ import (
// keys to the keys used by Marshal (either the struct field name or its tag),
// preferring an exact match but also accepting a case-insensitive match.
//
-// To unmarshal JSON into an interface value, Unmarshal unmarshals
-// the JSON into the concrete value contained in the interface value.
-// If the interface value is nil, that is, has no concrete value stored in it,
+// To unmarshal JSON into an interface value,
// Unmarshal stores one of these in the interface value:
//
// bool, for JSON booleans
@@ -293,7 +292,7 @@ func (d *decodeState) value(v reflect.Value) {
// until it gets to a non-pointer.
// if it encounters an Unmarshaler, indirect stops and returns that.
// if decodingNull is true, indirect stops at the last pointer so it can be set to nil.
-func (d *decodeState) indirect(v reflect.Value, decodingNull bool) (Unmarshaler, reflect.Value) {
+func (d *decodeState) indirect(v reflect.Value, decodingNull bool) (Unmarshaler, encoding.TextUnmarshaler, reflect.Value) {
// If v is a named type and is addressable,
// start with its address, so that if the type has pointer methods,
// we find them.
@@ -322,28 +321,38 @@ func (d *decodeState) indirect(v reflect.Value, decodingNull bool) (Unmarshaler,
v.Set(reflect.New(v.Type().Elem()))
}
if v.Type().NumMethod() > 0 {
- if unmarshaler, ok := v.Interface().(Unmarshaler); ok {
- return unmarshaler, reflect.Value{}
+ if u, ok := v.Interface().(Unmarshaler); ok {
+ return u, nil, reflect.Value{}
+ }
+ if u, ok := v.Interface().(encoding.TextUnmarshaler); ok {
+ return nil, u, reflect.Value{}
}
}
v = v.Elem()
}
- return nil, v
+ return nil, nil, v
}
// array consumes an array from d.data[d.off-1:], decoding into the value v.
// the first byte of the array ('[') has been read already.
func (d *decodeState) array(v reflect.Value) {
// Check for unmarshaler.
- unmarshaler, pv := d.indirect(v, false)
- if unmarshaler != nil {
+ u, ut, pv := d.indirect(v, false)
+ if u != nil {
d.off--
- err := unmarshaler.UnmarshalJSON(d.next())
+ err := u.UnmarshalJSON(d.next())
if err != nil {
d.error(err)
}
return
}
+ if ut != nil {
+ d.saveError(&UnmarshalTypeError{"array", v.Type()})
+ d.off--
+ d.next()
+ return
+ }
+
v = pv
// Check type of target.
@@ -434,15 +443,21 @@ func (d *decodeState) array(v reflect.Value) {
// the first byte of the object ('{') has been read already.
func (d *decodeState) object(v reflect.Value) {
// Check for unmarshaler.
- unmarshaler, pv := d.indirect(v, false)
- if unmarshaler != nil {
+ u, ut, pv := d.indirect(v, false)
+ if u != nil {
d.off--
- err := unmarshaler.UnmarshalJSON(d.next())
+ err := u.UnmarshalJSON(d.next())
if err != nil {
d.error(err)
}
return
}
+ if ut != nil {
+ d.saveError(&UnmarshalTypeError{"object", v.Type()})
+ d.off--
+ d.next() // skip over { } in input
+ return
+ }
v = pv
// Decoding into nil interface? Switch to non-reflect code.
@@ -611,14 +626,37 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
return
}
wantptr := item[0] == 'n' // null
- unmarshaler, pv := d.indirect(v, wantptr)
- if unmarshaler != nil {
- err := unmarshaler.UnmarshalJSON(item)
+ u, ut, pv := d.indirect(v, wantptr)
+ if u != nil {
+ err := u.UnmarshalJSON(item)
+ if err != nil {
+ d.error(err)
+ }
+ return
+ }
+ if ut != nil {
+ if item[0] != '"' {
+ if fromQuoted {
+ d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
+ } else {
+ d.saveError(&UnmarshalTypeError{"string", v.Type()})
+ }
+ }
+ s, ok := unquoteBytes(item)
+ if !ok {
+ if fromQuoted {
+ d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
+ } else {
+ d.error(errPhase)
+ }
+ }
+ err := ut.UnmarshalText(s)
if err != nil {
d.error(err)
}
return
}
+
v = pv
switch c := item[0]; c {
diff --git a/libgo/go/encoding/json/decode_test.go b/libgo/go/encoding/json/decode_test.go
index f845f69ab7f..22c5f89f798 100644
--- a/libgo/go/encoding/json/decode_test.go
+++ b/libgo/go/encoding/json/decode_test.go
@@ -6,6 +6,7 @@ package json
import (
"bytes"
+ "encoding"
"fmt"
"image"
"reflect"
@@ -50,8 +51,6 @@ type tx struct {
x int
}
-var txType = reflect.TypeOf((*tx)(nil)).Elem()
-
// A type that can unmarshal itself.
type unmarshaler struct {
@@ -59,7 +58,7 @@ type unmarshaler struct {
}
func (u *unmarshaler) UnmarshalJSON(b []byte) error {
- *u = unmarshaler{true} // All we need to see that UnmarshalJson is called.
+ *u = unmarshaler{true} // All we need to see that UnmarshalJSON is called.
return nil
}
@@ -67,6 +66,26 @@ type ustruct struct {
M unmarshaler
}
+type unmarshalerText struct {
+ T bool
+}
+
+// needed for re-marshaling tests
+func (u *unmarshalerText) MarshalText() ([]byte, error) {
+ return []byte(""), nil
+}
+
+func (u *unmarshalerText) UnmarshalText(b []byte) error {
+ *u = unmarshalerText{true} // All we need to see that UnmarshalText is called.
+ return nil
+}
+
+var _ encoding.TextUnmarshaler = (*unmarshalerText)(nil)
+
+type ustructText struct {
+ M unmarshalerText
+}
+
var (
um0, um1 unmarshaler // target2 of unmarshaling
ump = &um1
@@ -74,6 +93,13 @@ var (
umslice = []unmarshaler{{true}}
umslicep = new([]unmarshaler)
umstruct = ustruct{unmarshaler{true}}
+
+ um0T, um1T unmarshalerText // target2 of unmarshaling
+ umpT = &um1T
+ umtrueT = unmarshalerText{true}
+ umsliceT = []unmarshalerText{{true}}
+ umslicepT = new([]unmarshalerText)
+ umstructT = ustructText{unmarshalerText{true}}
)
// Test data structures for anonymous fields.
@@ -184,6 +210,12 @@ type Ambig struct {
Second int `json:"Hello"`
}
+type XYZ struct {
+ X interface{}
+ Y interface{}
+ Z interface{}
+}
+
var unmarshalTests = []unmarshalTest{
// basic types
{in: `true`, ptr: new(bool), out: true},
@@ -263,6 +295,13 @@ var unmarshalTests = []unmarshalTest{
{in: `[{"T":false}]`, ptr: &umslicep, out: &umslice},
{in: `{"M":{"T":false}}`, ptr: &umstruct, out: umstruct},
+ // UnmarshalText interface test
+ {in: `"X"`, ptr: &um0T, out: umtrueT}, // use "false" so test will fail if custom unmarshaler is not called
+ {in: `"X"`, ptr: &umpT, out: &umtrueT},
+ {in: `["X"]`, ptr: &umsliceT, out: umsliceT},
+ {in: `["X"]`, ptr: &umslicepT, out: &umsliceT},
+ {in: `{"M":"X"}`, ptr: &umstructT, out: umstructT},
+
{
in: `{
"Level0": 1,
@@ -391,17 +430,23 @@ func TestMarshal(t *testing.T) {
}
}
+var badUTF8 = []struct {
+ in, out string
+}{
+ {"hello\xffworld", `"hello\ufffdworld"`},
+ {"", `""`},
+ {"\xff", `"\ufffd"`},
+ {"\xff\xff", `"\ufffd\ufffd"`},
+ {"a\xffb", `"a\ufffdb"`},
+ {"\xe6\x97\xa5\xe6\x9c\xac\xff\xaa\x9e", `"日本\ufffd\ufffd\ufffd"`},
+}
+
func TestMarshalBadUTF8(t *testing.T) {
- s := "hello\xffworld"
- b, err := Marshal(s)
- if err == nil {
- t.Fatal("Marshal bad UTF8: no error")
- }
- if len(b) != 0 {
- t.Fatal("Marshal returned data")
- }
- if _, ok := err.(*InvalidUTF8Error); !ok {
- t.Fatalf("Marshal did not return InvalidUTF8Error: %T %v", err, err)
+ for _, tt := range badUTF8 {
+ b, err := Marshal(tt.in)
+ if string(b) != tt.out || err != nil {
+ t.Errorf("Marshal(%q) = %#q, %v, want %#q, nil", tt.in, b, err, tt.out)
+ }
}
}
@@ -417,6 +462,45 @@ func TestMarshalNumberZeroVal(t *testing.T) {
}
}
+func TestMarshalEmbeds(t *testing.T) {
+ top := &Top{
+ Level0: 1,
+ Embed0: Embed0{
+ Level1b: 2,
+ Level1c: 3,
+ },
+ Embed0a: &Embed0a{
+ Level1a: 5,
+ Level1b: 6,
+ },
+ Embed0b: &Embed0b{
+ Level1a: 8,
+ Level1b: 9,
+ Level1c: 10,
+ Level1d: 11,
+ Level1e: 12,
+ },
+ Loop: Loop{
+ Loop1: 13,
+ Loop2: 14,
+ },
+ Embed0p: Embed0p{
+ Point: image.Point{X: 15, Y: 16},
+ },
+ Embed0q: Embed0q{
+ Point: Point{Z: 17},
+ },
+ }
+ b, err := Marshal(top)
+ if err != nil {
+ t.Fatal(err)
+ }
+ want := "{\"Level0\":1,\"Level1b\":2,\"Level1c\":3,\"Level1a\":5,\"LEVEL1B\":6,\"e\":{\"Level1a\":8,\"Level1b\":9,\"Level1c\":10,\"Level1d\":11,\"x\":12},\"Loop1\":13,\"Loop2\":14,\"X\":15,\"Y\":16,\"Z\":17}"
+ if string(b) != want {
+ t.Errorf("Wrong marshal result.\n got: %q\nwant: %q", b, want)
+ }
+}
+
func TestUnmarshal(t *testing.T) {
for i, tt := range unmarshalTests {
var scan scanner
@@ -432,7 +516,7 @@ func TestUnmarshal(t *testing.T) {
}
// v = new(right-type)
v := reflect.New(reflect.TypeOf(tt.ptr).Elem())
- dec := NewDecoder(bytes.NewBuffer(in))
+ dec := NewDecoder(bytes.NewReader(in))
if tt.useNumber {
dec.UseNumber()
}
@@ -457,16 +541,18 @@ func TestUnmarshal(t *testing.T) {
continue
}
vv := reflect.New(reflect.TypeOf(tt.ptr).Elem())
- dec = NewDecoder(bytes.NewBuffer(enc))
+ dec = NewDecoder(bytes.NewReader(enc))
if tt.useNumber {
dec.UseNumber()
}
if err := dec.Decode(vv.Interface()); err != nil {
- t.Errorf("#%d: error re-unmarshaling: %v", i, err)
+ t.Errorf("#%d: error re-unmarshaling %#q: %v", i, enc, err)
continue
}
if !reflect.DeepEqual(v.Elem().Interface(), vv.Elem().Interface()) {
t.Errorf("#%d: mismatch\nhave: %#+v\nwant: %#+v", i, v.Elem().Interface(), vv.Elem().Interface())
+ t.Errorf(" In: %q", strings.Map(noSpace, string(in)))
+ t.Errorf("Marshal: %q", strings.Map(noSpace, string(enc)))
continue
}
}
@@ -568,14 +654,14 @@ func TestUnmarshalPtrPtr(t *testing.T) {
}
func TestEscape(t *testing.T) {
- const input = `"foobar"<html>`
- const expected = `"\"foobar\"\u003chtml\u003e"`
+ const input = `"foobar"<html>` + " [\u2028 \u2029]"
+ const expected = `"\"foobar\"\u003chtml\u003e [\u2028 \u2029]"`
b, err := Marshal(input)
if err != nil {
t.Fatalf("Marshal error: %v", err)
}
if s := string(b); s != expected {
- t.Errorf("Encoding of [%s] was [%s], want [%s]", input, s, expected)
+ t.Errorf("Encoding of [%s]:\n got [%s]\nwant [%s]", input, s, expected)
}
}
@@ -934,15 +1020,20 @@ func TestRefUnmarshal(t *testing.T) {
// Ref is defined in encode_test.go.
R0 Ref
R1 *Ref
+ R2 RefText
+ R3 *RefText
}
want := S{
R0: 12,
R1: new(Ref),
+ R2: 13,
+ R3: new(RefText),
}
*want.R1 = 12
+ *want.R3 = 13
var got S
- if err := Unmarshal([]byte(`{"R0":"ref","R1":"ref"}`), &got); err != nil {
+ if err := Unmarshal([]byte(`{"R0":"ref","R1":"ref","R2":"ref","R3":"ref"}`), &got); err != nil {
t.Fatalf("Unmarshal: %v", err)
}
if !reflect.DeepEqual(got, want) {
@@ -1064,7 +1155,6 @@ func TestUnmarshalNulls(t *testing.T) {
func TestStringKind(t *testing.T) {
type stringKind string
- type aMap map[stringKind]int
var m1, m2 map[stringKind]int
m1 = map[stringKind]int{
@@ -1191,3 +1281,38 @@ func TestSkipArrayObjects(t *testing.T) {
t.Errorf("got error %q, want nil", err)
}
}
+
+// Test semantics of pre-filled struct fields and pre-filled map fields.
+// Issue 4900.
+func TestPrefilled(t *testing.T) {
+ ptrToMap := func(m map[string]interface{}) *map[string]interface{} { return &m }
+
+ // Values here change, cannot reuse table across runs.
+ var prefillTests = []struct {
+ in string
+ ptr interface{}
+ out interface{}
+ }{
+ {
+ in: `{"X": 1, "Y": 2}`,
+ ptr: &XYZ{X: float32(3), Y: int16(4), Z: 1.5},
+ out: &XYZ{X: float64(1), Y: float64(2), Z: 1.5},
+ },
+ {
+ in: `{"X": 1, "Y": 2}`,
+ ptr: ptrToMap(map[string]interface{}{"X": float32(3), "Y": int16(4), "Z": 1.5}),
+ out: ptrToMap(map[string]interface{}{"X": float64(1), "Y": float64(2), "Z": 1.5}),
+ },
+ }
+
+ for _, tt := range prefillTests {
+ ptrstr := fmt.Sprintf("%v", tt.ptr)
+ err := Unmarshal([]byte(tt.in), tt.ptr) // tt.ptr edited here
+ if err != nil {
+ t.Errorf("Unmarshal: %v", err)
+ }
+ if !reflect.DeepEqual(tt.ptr, tt.out) {
+ t.Errorf("Unmarshal(%#q, %s): have %v, want %v", tt.in, ptrstr, tt.ptr, tt.out)
+ }
+ }
+}
diff --git a/libgo/go/encoding/json/encode.go b/libgo/go/encoding/json/encode.go
index 85727ba61c0..7d6c71d7a90 100644
--- a/libgo/go/encoding/json/encode.go
+++ b/libgo/go/encoding/json/encode.go
@@ -12,6 +12,7 @@ package json
import (
"bytes"
+ "encoding"
"encoding/base64"
"math"
"reflect"
@@ -149,14 +150,14 @@ func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) {
return buf.Bytes(), nil
}
-// HTMLEscape appends to dst the JSON-encoded src with <, >, and &
-// characters inside string literals changed to \u003c, \u003e, \u0026
+// HTMLEscape appends to dst the JSON-encoded src with <, >, &, U+2028 and U+2029
+// characters inside string literals changed to \u003c, \u003e, \u0026, \u2028, \u2029
// so that the JSON will be safe to embed inside HTML <script> tags.
// For historical reasons, web browsers don't honor standard HTML
// escaping within <script> tags, so an alternative JSON encoding must
// be used.
func HTMLEscape(dst *bytes.Buffer, src []byte) {
- // < > & can only appear in string literals,
+ // The characters can only appear in string literals,
// so just scan the string one byte at a time.
start := 0
for i, c := range src {
@@ -169,6 +170,15 @@ func HTMLEscape(dst *bytes.Buffer, src []byte) {
dst.WriteByte(hex[c&0xF])
start = i + 1
}
+ // Convert U+2028 and U+2029 (E2 80 A8 and E2 80 A9).
+ if c == 0xE2 && i+2 < len(src) && src[i+1] == 0x80 && src[i+2]&^1 == 0xA8 {
+ if start < i {
+ dst.Write(src[start:i])
+ }
+ dst.WriteString(`\u202`)
+ dst.WriteByte(hex[src[i+2]&0xF])
+ start = i + 3
+ }
}
if start < len(src) {
dst.Write(src[start:])
@@ -200,8 +210,12 @@ func (e *UnsupportedValueError) Error() string {
return "json: unsupported value: " + e.Str
}
-// An InvalidUTF8Error is returned by Marshal when attempting
-// to encode a string value with invalid UTF-8 sequences.
+// Before Go 1.2, an InvalidUTF8Error was returned by Marshal when
+// attempting to encode a string value with invalid UTF-8 sequences.
+// As of Go 1.2, Marshal instead coerces the string to valid UTF-8 by
+// replacing invalid bytes with the Unicode replacement rune U+FFFD.
+// This error is no longer generated but is kept for backwards compatibility
+// with programs that might mention it.
type InvalidUTF8Error struct {
S string // the whole string value that caused the error
}
@@ -227,12 +241,35 @@ type encodeState struct {
scratch [64]byte
}
+// TODO(bradfitz): use a sync.Cache here
+var encodeStatePool = make(chan *encodeState, 8)
+
+func newEncodeState() *encodeState {
+ select {
+ case e := <-encodeStatePool:
+ e.Reset()
+ return e
+ default:
+ return new(encodeState)
+ }
+}
+
+func putEncodeState(e *encodeState) {
+ select {
+ case encodeStatePool <- e:
+ default:
+ }
+}
+
func (e *encodeState) marshal(v interface{}) (err error) {
defer func() {
if r := recover(); r != nil {
if _, ok := r.(runtime.Error); ok {
panic(r)
}
+ if s, ok := r.(string); ok {
+ panic(s)
+ }
err = r.(error)
}
}()
@@ -265,186 +302,438 @@ func isEmptyValue(v reflect.Value) bool {
}
func (e *encodeState) reflectValue(v reflect.Value) {
- e.reflectValueQuoted(v, false)
+ valueEncoder(v)(e, v, false)
+}
+
+type encoderFunc func(e *encodeState, v reflect.Value, quoted bool)
+
+var encoderCache struct {
+ sync.RWMutex
+ m map[reflect.Type]encoderFunc
}
-// reflectValueQuoted writes the value in v to the output.
-// If quoted is true, the serialization is wrapped in a JSON string.
-func (e *encodeState) reflectValueQuoted(v reflect.Value, quoted bool) {
+func valueEncoder(v reflect.Value) encoderFunc {
if !v.IsValid() {
- e.WriteString("null")
- return
+ return invalidValueEncoder
}
+ return typeEncoder(v.Type())
+}
- m, ok := v.Interface().(Marshaler)
- if !ok {
- // T doesn't match the interface. Check against *T too.
- if v.Kind() != reflect.Ptr && v.CanAddr() {
- m, ok = v.Addr().Interface().(Marshaler)
- if ok {
- v = v.Addr()
- }
- }
+func typeEncoder(t reflect.Type) encoderFunc {
+ encoderCache.RLock()
+ f := encoderCache.m[t]
+ encoderCache.RUnlock()
+ if f != nil {
+ return f
+ }
+
+ // To deal with recursive types, populate the map with an
+ // indirect func before we build it. This type waits on the
+ // real func (f) to be ready and then calls it. This indirect
+ // func is only used for recursive types.
+ encoderCache.Lock()
+ if encoderCache.m == nil {
+ encoderCache.m = make(map[reflect.Type]encoderFunc)
+ }
+ var wg sync.WaitGroup
+ wg.Add(1)
+ encoderCache.m[t] = func(e *encodeState, v reflect.Value, quoted bool) {
+ wg.Wait()
+ f(e, v, quoted)
+ }
+ encoderCache.Unlock()
+
+ // Compute fields without lock.
+ // Might duplicate effort but won't hold other computations back.
+ f = newTypeEncoder(t, true)
+ wg.Done()
+ encoderCache.Lock()
+ encoderCache.m[t] = f
+ encoderCache.Unlock()
+ return f
+}
+
+var (
+ marshalerType = reflect.TypeOf(new(Marshaler)).Elem()
+ textMarshalerType = reflect.TypeOf(new(encoding.TextMarshaler)).Elem()
+)
+
+// newTypeEncoder constructs an encoderFunc for a type.
+// The returned encoder only checks CanAddr when allowAddr is true.
+func newTypeEncoder(t reflect.Type, allowAddr bool) encoderFunc {
+ if t.Implements(marshalerType) {
+ return marshalerEncoder
}
- if ok && (v.Kind() != reflect.Ptr || !v.IsNil()) {
- b, err := m.MarshalJSON()
- if err == nil {
- // copy JSON into buffer, checking validity.
- err = compact(&e.Buffer, b, true)
+ if t.Kind() != reflect.Ptr && allowAddr {
+ if reflect.PtrTo(t).Implements(marshalerType) {
+ return newCondAddrEncoder(addrMarshalerEncoder, newTypeEncoder(t, false))
}
- if err != nil {
- e.error(&MarshalerError{v.Type(), err})
+ }
+
+ if t.Implements(textMarshalerType) {
+ return textMarshalerEncoder
+ }
+ if t.Kind() != reflect.Ptr && allowAddr {
+ if reflect.PtrTo(t).Implements(textMarshalerType) {
+ return newCondAddrEncoder(addrTextMarshalerEncoder, newTypeEncoder(t, false))
}
+ }
+
+ switch t.Kind() {
+ case reflect.Bool:
+ return boolEncoder
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return intEncoder
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ return uintEncoder
+ case reflect.Float32:
+ return float32Encoder
+ case reflect.Float64:
+ return float64Encoder
+ case reflect.String:
+ return stringEncoder
+ case reflect.Interface:
+ return interfaceEncoder
+ case reflect.Struct:
+ return newStructEncoder(t)
+ case reflect.Map:
+ return newMapEncoder(t)
+ case reflect.Slice:
+ return newSliceEncoder(t)
+ case reflect.Array:
+ return newArrayEncoder(t)
+ case reflect.Ptr:
+ return newPtrEncoder(t)
+ default:
+ return unsupportedTypeEncoder
+ }
+}
+
+func invalidValueEncoder(e *encodeState, v reflect.Value, quoted bool) {
+ e.WriteString("null")
+}
+
+func marshalerEncoder(e *encodeState, v reflect.Value, quoted bool) {
+ if v.Kind() == reflect.Ptr && v.IsNil() {
+ e.WriteString("null")
+ return
+ }
+ m := v.Interface().(Marshaler)
+ b, err := m.MarshalJSON()
+ if err == nil {
+ // copy JSON into buffer, checking validity.
+ err = compact(&e.Buffer, b, true)
+ }
+ if err != nil {
+ e.error(&MarshalerError{v.Type(), err})
+ }
+}
+
+func addrMarshalerEncoder(e *encodeState, v reflect.Value, quoted bool) {
+ va := v.Addr()
+ if va.IsNil() {
+ e.WriteString("null")
return
}
+ m := va.Interface().(Marshaler)
+ b, err := m.MarshalJSON()
+ if err == nil {
+ // copy JSON into buffer, checking validity.
+ err = compact(&e.Buffer, b, true)
+ }
+ if err != nil {
+ e.error(&MarshalerError{v.Type(), err})
+ }
+}
- writeString := (*encodeState).WriteString
+func textMarshalerEncoder(e *encodeState, v reflect.Value, quoted bool) {
+ if v.Kind() == reflect.Ptr && v.IsNil() {
+ e.WriteString("null")
+ return
+ }
+ m := v.Interface().(encoding.TextMarshaler)
+ b, err := m.MarshalText()
+ if err == nil {
+ _, err = e.stringBytes(b)
+ }
+ if err != nil {
+ e.error(&MarshalerError{v.Type(), err})
+ }
+}
+
+func addrTextMarshalerEncoder(e *encodeState, v reflect.Value, quoted bool) {
+ va := v.Addr()
+ if va.IsNil() {
+ e.WriteString("null")
+ return
+ }
+ m := va.Interface().(encoding.TextMarshaler)
+ b, err := m.MarshalText()
+ if err == nil {
+ _, err = e.stringBytes(b)
+ }
+ if err != nil {
+ e.error(&MarshalerError{v.Type(), err})
+ }
+}
+
+func boolEncoder(e *encodeState, v reflect.Value, quoted bool) {
+ if quoted {
+ e.WriteByte('"')
+ }
+ if v.Bool() {
+ e.WriteString("true")
+ } else {
+ e.WriteString("false")
+ }
+ if quoted {
+ e.WriteByte('"')
+ }
+}
+
+func intEncoder(e *encodeState, v reflect.Value, quoted bool) {
+ b := strconv.AppendInt(e.scratch[:0], v.Int(), 10)
+ if quoted {
+ e.WriteByte('"')
+ }
+ e.Write(b)
if quoted {
- writeString = (*encodeState).string
+ e.WriteByte('"')
}
+}
- switch v.Kind() {
- case reflect.Bool:
- x := v.Bool()
- if x {
- writeString(e, "true")
- } else {
- writeString(e, "false")
- }
+func uintEncoder(e *encodeState, v reflect.Value, quoted bool) {
+ b := strconv.AppendUint(e.scratch[:0], v.Uint(), 10)
+ if quoted {
+ e.WriteByte('"')
+ }
+ e.Write(b)
+ if quoted {
+ e.WriteByte('"')
+ }
+}
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- b := strconv.AppendInt(e.scratch[:0], v.Int(), 10)
- if quoted {
- writeString(e, string(b))
- } else {
- e.Write(b)
+type floatEncoder int // number of bits
+
+func (bits floatEncoder) encode(e *encodeState, v reflect.Value, quoted bool) {
+ f := v.Float()
+ if math.IsInf(f, 0) || math.IsNaN(f) {
+ e.error(&UnsupportedValueError{v, strconv.FormatFloat(f, 'g', -1, int(bits))})
+ }
+ b := strconv.AppendFloat(e.scratch[:0], f, 'g', -1, int(bits))
+ if quoted {
+ e.WriteByte('"')
+ }
+ e.Write(b)
+ if quoted {
+ e.WriteByte('"')
+ }
+}
+
+var (
+ float32Encoder = (floatEncoder(32)).encode
+ float64Encoder = (floatEncoder(64)).encode
+)
+
+func stringEncoder(e *encodeState, v reflect.Value, quoted bool) {
+ if v.Type() == numberType {
+ numStr := v.String()
+ if numStr == "" {
+ numStr = "0" // Number's zero-val
}
- case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
- b := strconv.AppendUint(e.scratch[:0], v.Uint(), 10)
- if quoted {
- writeString(e, string(b))
- } else {
- e.Write(b)
+ e.WriteString(numStr)
+ return
+ }
+ if quoted {
+ sb, err := Marshal(v.String())
+ if err != nil {
+ e.error(err)
}
- case reflect.Float32, reflect.Float64:
- f := v.Float()
- if math.IsInf(f, 0) || math.IsNaN(f) {
- e.error(&UnsupportedValueError{v, strconv.FormatFloat(f, 'g', -1, v.Type().Bits())})
+ e.string(string(sb))
+ } else {
+ e.string(v.String())
+ }
+}
+
+func interfaceEncoder(e *encodeState, v reflect.Value, quoted bool) {
+ if v.IsNil() {
+ e.WriteString("null")
+ return
+ }
+ e.reflectValue(v.Elem())
+}
+
+func unsupportedTypeEncoder(e *encodeState, v reflect.Value, quoted bool) {
+ e.error(&UnsupportedTypeError{v.Type()})
+}
+
+type structEncoder struct {
+ fields []field
+ fieldEncs []encoderFunc
+}
+
+func (se *structEncoder) encode(e *encodeState, v reflect.Value, quoted bool) {
+ e.WriteByte('{')
+ first := true
+ for i, f := range se.fields {
+ fv := fieldByIndex(v, f.index)
+ if !fv.IsValid() || f.omitEmpty && isEmptyValue(fv) {
+ continue
}
- b := strconv.AppendFloat(e.scratch[:0], f, 'g', -1, v.Type().Bits())
- if quoted {
- writeString(e, string(b))
+ if first {
+ first = false
} else {
- e.Write(b)
- }
- case reflect.String:
- if v.Type() == numberType {
- numStr := v.String()
- if numStr == "" {
- numStr = "0" // Number's zero-val
- }
- e.WriteString(numStr)
- break
- }
- if quoted {
- sb, err := Marshal(v.String())
- if err != nil {
- e.error(err)
- }
- e.string(string(sb))
- } else {
- e.string(v.String())
+ e.WriteByte(',')
}
+ e.string(f.name)
+ e.WriteByte(':')
+ se.fieldEncs[i](e, fv, f.quoted)
+ }
+ e.WriteByte('}')
+}
- case reflect.Struct:
- e.WriteByte('{')
- first := true
- for _, f := range cachedTypeFields(v.Type()) {
- fv := fieldByIndex(v, f.index)
- if !fv.IsValid() || f.omitEmpty && isEmptyValue(fv) {
- continue
- }
- if first {
- first = false
- } else {
- e.WriteByte(',')
- }
- e.string(f.name)
- e.WriteByte(':')
- e.reflectValueQuoted(fv, f.quoted)
- }
- e.WriteByte('}')
+func newStructEncoder(t reflect.Type) encoderFunc {
+ fields := cachedTypeFields(t)
+ se := &structEncoder{
+ fields: fields,
+ fieldEncs: make([]encoderFunc, len(fields)),
+ }
+ for i, f := range fields {
+ se.fieldEncs[i] = typeEncoder(typeByIndex(t, f.index))
+ }
+ return se.encode
+}
- case reflect.Map:
- if v.Type().Key().Kind() != reflect.String {
- e.error(&UnsupportedTypeError{v.Type()})
- }
- if v.IsNil() {
- e.WriteString("null")
- break
- }
- e.WriteByte('{')
- var sv stringValues = v.MapKeys()
- sort.Sort(sv)
- for i, k := range sv {
- if i > 0 {
- e.WriteByte(',')
- }
- e.string(k.String())
- e.WriteByte(':')
- e.reflectValue(v.MapIndex(k))
- }
- e.WriteByte('}')
+type mapEncoder struct {
+ elemEnc encoderFunc
+}
- case reflect.Slice:
- if v.IsNil() {
- e.WriteString("null")
- break
- }
- if v.Type().Elem().Kind() == reflect.Uint8 {
- // Byte slices get special treatment; arrays don't.
- s := v.Bytes()
- e.WriteByte('"')
- if len(s) < 1024 {
- // for small buffers, using Encode directly is much faster.
- dst := make([]byte, base64.StdEncoding.EncodedLen(len(s)))
- base64.StdEncoding.Encode(dst, s)
- e.Write(dst)
- } else {
- // for large buffers, avoid unnecessary extra temporary
- // buffer space.
- enc := base64.NewEncoder(base64.StdEncoding, e)
- enc.Write(s)
- enc.Close()
- }
- e.WriteByte('"')
- break
- }
- // Slices can be marshalled as nil, but otherwise are handled
- // as arrays.
- fallthrough
- case reflect.Array:
- e.WriteByte('[')
- n := v.Len()
- for i := 0; i < n; i++ {
- if i > 0 {
- e.WriteByte(',')
- }
- e.reflectValue(v.Index(i))
+func (me *mapEncoder) encode(e *encodeState, v reflect.Value, _ bool) {
+ if v.IsNil() {
+ e.WriteString("null")
+ return
+ }
+ e.WriteByte('{')
+ var sv stringValues = v.MapKeys()
+ sort.Sort(sv)
+ for i, k := range sv {
+ if i > 0 {
+ e.WriteByte(',')
}
- e.WriteByte(']')
+ e.string(k.String())
+ e.WriteByte(':')
+ me.elemEnc(e, v.MapIndex(k), false)
+ }
+ e.WriteByte('}')
+}
- case reflect.Interface, reflect.Ptr:
- if v.IsNil() {
- e.WriteString("null")
- return
+func newMapEncoder(t reflect.Type) encoderFunc {
+ if t.Key().Kind() != reflect.String {
+ return unsupportedTypeEncoder
+ }
+ me := &mapEncoder{typeEncoder(t.Elem())}
+ return me.encode
+}
+
+func encodeByteSlice(e *encodeState, v reflect.Value, _ bool) {
+ if v.IsNil() {
+ e.WriteString("null")
+ return
+ }
+ s := v.Bytes()
+ e.WriteByte('"')
+ if len(s) < 1024 {
+ // for small buffers, using Encode directly is much faster.
+ dst := make([]byte, base64.StdEncoding.EncodedLen(len(s)))
+ base64.StdEncoding.Encode(dst, s)
+ e.Write(dst)
+ } else {
+ // for large buffers, avoid unnecessary extra temporary
+ // buffer space.
+ enc := base64.NewEncoder(base64.StdEncoding, e)
+ enc.Write(s)
+ enc.Close()
+ }
+ e.WriteByte('"')
+}
+
+// sliceEncoder just wraps an arrayEncoder, checking to make sure the value isn't nil.
+type sliceEncoder struct {
+ arrayEnc encoderFunc
+}
+
+func (se *sliceEncoder) encode(e *encodeState, v reflect.Value, _ bool) {
+ if v.IsNil() {
+ e.WriteString("null")
+ return
+ }
+ se.arrayEnc(e, v, false)
+}
+
+func newSliceEncoder(t reflect.Type) encoderFunc {
+ // Byte slices get special treatment; arrays don't.
+ if t.Elem().Kind() == reflect.Uint8 {
+ return encodeByteSlice
+ }
+ enc := &sliceEncoder{newArrayEncoder(t)}
+ return enc.encode
+}
+
+type arrayEncoder struct {
+ elemEnc encoderFunc
+}
+
+func (ae *arrayEncoder) encode(e *encodeState, v reflect.Value, _ bool) {
+ e.WriteByte('[')
+ n := v.Len()
+ for i := 0; i < n; i++ {
+ if i > 0 {
+ e.WriteByte(',')
}
- e.reflectValue(v.Elem())
+ ae.elemEnc(e, v.Index(i), false)
+ }
+ e.WriteByte(']')
+}
- default:
- e.error(&UnsupportedTypeError{v.Type()})
+func newArrayEncoder(t reflect.Type) encoderFunc {
+ enc := &arrayEncoder{typeEncoder(t.Elem())}
+ return enc.encode
+}
+
+type ptrEncoder struct {
+ elemEnc encoderFunc
+}
+
+func (pe *ptrEncoder) encode(e *encodeState, v reflect.Value, _ bool) {
+ if v.IsNil() {
+ e.WriteString("null")
+ return
+ }
+ pe.elemEnc(e, v.Elem(), false)
+}
+
+func newPtrEncoder(t reflect.Type) encoderFunc {
+ enc := &ptrEncoder{typeEncoder(t.Elem())}
+ return enc.encode
+}
+
+type condAddrEncoder struct {
+ canAddrEnc, elseEnc encoderFunc
+}
+
+func (ce *condAddrEncoder) encode(e *encodeState, v reflect.Value, quoted bool) {
+ if v.CanAddr() {
+ ce.canAddrEnc(e, v, quoted)
+ } else {
+ ce.elseEnc(e, v, quoted)
}
- return
+}
+
+// newCondAddrEncoder returns an encoder that checks whether its value
+// CanAddr and delegates to canAddrEnc if so, else to elseEnc.
+func newCondAddrEncoder(canAddrEnc, elseEnc encoderFunc) encoderFunc {
+ enc := &condAddrEncoder{canAddrEnc: canAddrEnc, elseEnc: elseEnc}
+ return enc.encode
}
func isValidTag(s string) bool {
@@ -479,6 +768,16 @@ func fieldByIndex(v reflect.Value, index []int) reflect.Value {
return v
}
+func typeByIndex(t reflect.Type, index []int) reflect.Type {
+ for _, i := range index {
+ if t.Kind() == reflect.Ptr {
+ t = t.Elem()
+ }
+ t = t.Field(i).Type
+ }
+ return t
+}
+
// stringValues is a slice of reflect.Value holding *reflect.StringValue.
// It implements the methods to sort by string.
type stringValues []reflect.Value
@@ -488,13 +787,14 @@ func (sv stringValues) Swap(i, j int) { sv[i], sv[j] = sv[j], sv[i] }
func (sv stringValues) Less(i, j int) bool { return sv.get(i) < sv.get(j) }
func (sv stringValues) get(i int) string { return sv[i].String() }
+// NOTE: keep in sync with stringBytes below.
func (e *encodeState) string(s string) (int, error) {
len0 := e.Len()
e.WriteByte('"')
start := 0
for i := 0; i < len(s); {
if b := s[i]; b < utf8.RuneSelf {
- if 0x20 <= b && b != '\\' && b != '"' && b != '<' && b != '>' {
+ if 0x20 <= b && b != '\\' && b != '"' && b != '<' && b != '>' && b != '&' {
i++
continue
}
@@ -526,7 +826,30 @@ func (e *encodeState) string(s string) (int, error) {
}
c, size := utf8.DecodeRuneInString(s[i:])
if c == utf8.RuneError && size == 1 {
- e.error(&InvalidUTF8Error{s})
+ if start < i {
+ e.WriteString(s[start:i])
+ }
+ e.WriteString(`\ufffd`)
+ i += size
+ start = i
+ continue
+ }
+ // U+2028 is LINE SEPARATOR.
+ // U+2029 is PARAGRAPH SEPARATOR.
+ // They are both technically valid characters in JSON strings,
+ // but don't work in JSONP, which has to be evaluated as JavaScript,
+ // and can lead to security holes there. It is valid JSON to
+ // escape them, so we do so unconditionally.
+ // See http://timelessrepo.com/json-isnt-a-javascript-subset for discussion.
+ if c == '\u2028' || c == '\u2029' {
+ if start < i {
+ e.WriteString(s[start:i])
+ }
+ e.WriteString(`\u202`)
+ e.WriteByte(hex[c&0xF])
+ i += size
+ start = i
+ continue
}
i += size
}
@@ -537,6 +860,79 @@ func (e *encodeState) string(s string) (int, error) {
return e.Len() - len0, nil
}
+// NOTE: keep in sync with string above.
+func (e *encodeState) stringBytes(s []byte) (int, error) {
+ len0 := e.Len()
+ e.WriteByte('"')
+ start := 0
+ for i := 0; i < len(s); {
+ if b := s[i]; b < utf8.RuneSelf {
+ if 0x20 <= b && b != '\\' && b != '"' && b != '<' && b != '>' && b != '&' {
+ i++
+ continue
+ }
+ if start < i {
+ e.Write(s[start:i])
+ }
+ switch b {
+ case '\\', '"':
+ e.WriteByte('\\')
+ e.WriteByte(b)
+ case '\n':
+ e.WriteByte('\\')
+ e.WriteByte('n')
+ case '\r':
+ e.WriteByte('\\')
+ e.WriteByte('r')
+ default:
+ // This encodes bytes < 0x20 except for \n and \r,
+ // as well as < and >. The latter are escaped because they
+ // can lead to security holes when user-controlled strings
+ // are rendered into JSON and served to some browsers.
+ e.WriteString(`\u00`)
+ e.WriteByte(hex[b>>4])
+ e.WriteByte(hex[b&0xF])
+ }
+ i++
+ start = i
+ continue
+ }
+ c, size := utf8.DecodeRune(s[i:])
+ if c == utf8.RuneError && size == 1 {
+ if start < i {
+ e.Write(s[start:i])
+ }
+ e.WriteString(`\ufffd`)
+ i += size
+ start = i
+ continue
+ }
+ // U+2028 is LINE SEPARATOR.
+ // U+2029 is PARAGRAPH SEPARATOR.
+ // They are both technically valid characters in JSON strings,
+ // but don't work in JSONP, which has to be evaluated as JavaScript,
+ // and can lead to security holes there. It is valid JSON to
+ // escape them, so we do so unconditionally.
+ // See http://timelessrepo.com/json-isnt-a-javascript-subset for discussion.
+ if c == '\u2028' || c == '\u2029' {
+ if start < i {
+ e.Write(s[start:i])
+ }
+ e.WriteString(`\u202`)
+ e.WriteByte(hex[c&0xF])
+ i += size
+ start = i
+ continue
+ }
+ i += size
+ }
+ if start < len(s) {
+ e.Write(s[start:])
+ }
+ e.WriteByte('"')
+ return e.Len() - len0, nil
+}
+
// A field represents a single field found in a struct.
type field struct {
name string
diff --git a/libgo/go/encoding/json/encode_test.go b/libgo/go/encoding/json/encode_test.go
index 5be0a992e1c..9395db7cb6f 100644
--- a/libgo/go/encoding/json/encode_test.go
+++ b/libgo/go/encoding/json/encode_test.go
@@ -9,6 +9,7 @@ import (
"math"
"reflect"
"testing"
+ "unicode"
)
type Optionals struct {
@@ -146,19 +147,46 @@ func (Val) MarshalJSON() ([]byte, error) {
return []byte(`"val"`), nil
}
+// RefText has Marshaler and Unmarshaler methods with pointer receiver.
+type RefText int
+
+func (*RefText) MarshalText() ([]byte, error) {
+ return []byte(`"ref"`), nil
+}
+
+func (r *RefText) UnmarshalText([]byte) error {
+ *r = 13
+ return nil
+}
+
+// ValText has Marshaler methods with value receiver.
+type ValText int
+
+func (ValText) MarshalText() ([]byte, error) {
+ return []byte(`"val"`), nil
+}
+
func TestRefValMarshal(t *testing.T) {
var s = struct {
R0 Ref
R1 *Ref
+ R2 RefText
+ R3 *RefText
V0 Val
V1 *Val
+ V2 ValText
+ V3 *ValText
}{
R0: 12,
R1: new(Ref),
+ R2: 14,
+ R3: new(RefText),
V0: 13,
V1: new(Val),
+ V2: 15,
+ V3: new(ValText),
}
- const want = `{"R0":"ref","R1":"ref","V0":"val","V1":"val"}`
+ const want = `{"R0":"ref","R1":"ref","R2":"\"ref\"","R3":"\"ref\"","V0":"val","V1":"val","V2":"\"val\"","V3":"\"val\""}`
b, err := Marshal(&s)
if err != nil {
t.Fatalf("Marshal: %v", err)
@@ -175,15 +203,32 @@ func (C) MarshalJSON() ([]byte, error) {
return []byte(`"<&>"`), nil
}
+// CText implements Marshaler and returns unescaped text.
+type CText int
+
+func (CText) MarshalText() ([]byte, error) {
+ return []byte(`"<&>"`), nil
+}
+
func TestMarshalerEscaping(t *testing.T) {
var c C
- const want = `"\u003c\u0026\u003e"`
+ want := `"\u003c\u0026\u003e"`
b, err := Marshal(c)
if err != nil {
- t.Fatalf("Marshal: %v", err)
+ t.Fatalf("Marshal(c): %v", err)
}
if got := string(b); got != want {
- t.Errorf("got %q, want %q", got, want)
+ t.Errorf("Marshal(c) = %#q, want %#q", got, want)
+ }
+
+ var ct CText
+ want = `"\"\u003c\u0026\u003e\""`
+ b, err = Marshal(ct)
+ if err != nil {
+ t.Fatalf("Marshal(ct): %v", err)
+ }
+ if got := string(b); got != want {
+ t.Errorf("Marshal(ct) = %#q, want %#q", got, want)
}
}
@@ -310,3 +355,73 @@ func TestDuplicatedFieldDisappears(t *testing.T) {
t.Fatalf("Marshal: got %s want %s", got, want)
}
}
+
+func TestStringBytes(t *testing.T) {
+ // Test that encodeState.stringBytes and encodeState.string use the same encoding.
+ es := &encodeState{}
+ var r []rune
+ for i := '\u0000'; i <= unicode.MaxRune; i++ {
+ r = append(r, i)
+ }
+ s := string(r) + "\xff\xff\xffhello" // some invalid UTF-8 too
+ _, err := es.string(s)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ esBytes := &encodeState{}
+ _, err = esBytes.stringBytes([]byte(s))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ enc := es.Buffer.String()
+ encBytes := esBytes.Buffer.String()
+ if enc != encBytes {
+ i := 0
+ for i < len(enc) && i < len(encBytes) && enc[i] == encBytes[i] {
+ i++
+ }
+ enc = enc[i:]
+ encBytes = encBytes[i:]
+ i = 0
+ for i < len(enc) && i < len(encBytes) && enc[len(enc)-i-1] == encBytes[len(encBytes)-i-1] {
+ i++
+ }
+ enc = enc[:len(enc)-i]
+ encBytes = encBytes[:len(encBytes)-i]
+
+ if len(enc) > 20 {
+ enc = enc[:20] + "..."
+ }
+ if len(encBytes) > 20 {
+ encBytes = encBytes[:20] + "..."
+ }
+
+ t.Errorf("encodings differ at %#q vs %#q", enc, encBytes)
+ }
+}
+
+func TestIssue6458(t *testing.T) {
+ type Foo struct {
+ M RawMessage
+ }
+ x := Foo{RawMessage(`"foo"`)}
+
+ b, err := Marshal(&x)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if want := `{"M":"foo"}`; string(b) != want {
+ t.Errorf("Marshal(&x) = %#q; want %#q", b, want)
+ }
+
+ b, err = Marshal(x)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if want := `{"M":"ImZvbyI="}`; string(b) != want {
+ t.Errorf("Marshal(x) = %#q; want %#q", b, want)
+ }
+}
diff --git a/libgo/go/encoding/json/indent.go b/libgo/go/encoding/json/indent.go
index e8dfa4ec436..11ef709cce7 100644
--- a/libgo/go/encoding/json/indent.go
+++ b/libgo/go/encoding/json/indent.go
@@ -27,6 +27,15 @@ func compact(dst *bytes.Buffer, src []byte, escape bool) error {
dst.WriteByte(hex[c&0xF])
start = i + 1
}
+ // Convert U+2028 and U+2029 (E2 80 A8 and E2 80 A9).
+ if c == 0xE2 && i+2 < len(src) && src[i+1] == 0x80 && src[i+2]&^1 == 0xA8 {
+ if start < i {
+ dst.Write(src[start:i])
+ }
+ dst.WriteString(`\u202`)
+ dst.WriteByte(hex[src[i+2]&0xF])
+ start = i + 3
+ }
v := scan.step(&scan, int(c))
if v >= scanSkipSpace {
if v == scanError {
diff --git a/libgo/go/encoding/json/scanner.go b/libgo/go/encoding/json/scanner.go
index 054b6b3d564..a4609c89505 100644
--- a/libgo/go/encoding/json/scanner.go
+++ b/libgo/go/encoding/json/scanner.go
@@ -390,7 +390,7 @@ func stateInStringEscU123(s *scanner, c int) int {
return s.error(c, "in \\u hexadecimal character escape")
}
-// stateInStringEscU123 is the state after reading `-` during a number.
+// stateNeg is the state after reading `-` during a number.
func stateNeg(s *scanner, c int) int {
if c == '0' {
s.step = state0
diff --git a/libgo/go/encoding/json/scanner_test.go b/libgo/go/encoding/json/scanner_test.go
index 77d3455d307..90e45ff0369 100644
--- a/libgo/go/encoding/json/scanner_test.go
+++ b/libgo/go/encoding/json/scanner_test.go
@@ -63,6 +63,25 @@ func TestCompact(t *testing.T) {
}
}
+func TestCompactSeparators(t *testing.T) {
+ // U+2028 and U+2029 should be escaped inside strings.
+ // They should not appear outside strings.
+ tests := []struct {
+ in, compact string
+ }{
+ {"{\"\u2028\": 1}", `{"\u2028":1}`},
+ {"{\"\u2029\" :2}", `{"\u2029":2}`},
+ }
+ for _, tt := range tests {
+ var buf bytes.Buffer
+ if err := Compact(&buf, []byte(tt.in)); err != nil {
+ t.Errorf("Compact(%q): %v", tt.in, err)
+ } else if s := buf.String(); s != tt.compact {
+ t.Errorf("Compact(%q) = %q, want %q", tt.in, s, tt.compact)
+ }
+ }
+}
+
func TestIndent(t *testing.T) {
var buf bytes.Buffer
for _, tt := range examples {
diff --git a/libgo/go/encoding/json/stream.go b/libgo/go/encoding/json/stream.go
index 00f4726cf7f..1928abadb7d 100644
--- a/libgo/go/encoding/json/stream.go
+++ b/libgo/go/encoding/json/stream.go
@@ -148,7 +148,7 @@ func NewEncoder(w io.Writer) *Encoder {
return &Encoder{w: w}
}
-// Encode writes the JSON encoding of v to the connection.
+// Encode writes the JSON encoding of v to the stream.
//
// See the documentation for Marshal for details about the
// conversion of Go values to JSON.
@@ -156,8 +156,8 @@ func (enc *Encoder) Encode(v interface{}) error {
if enc.err != nil {
return enc.err
}
- enc.e.Reset()
- err := enc.e.marshal(v)
+ e := newEncodeState()
+ err := e.marshal(v)
if err != nil {
return err
}
@@ -168,11 +168,12 @@ func (enc *Encoder) Encode(v interface{}) error {
// is required if the encoded value was a number,
// so that the reader knows there aren't more
// digits coming.
- enc.e.WriteByte('\n')
+ e.WriteByte('\n')
- if _, err = enc.w.Write(enc.e.Bytes()); err != nil {
+ if _, err = enc.w.Write(e.Bytes()); err != nil {
enc.err = err
}
+ putEncodeState(e)
return err
}
diff --git a/libgo/go/encoding/json/stream_test.go b/libgo/go/encoding/json/stream_test.go
index 07c9e1d390c..b562e87690d 100644
--- a/libgo/go/encoding/json/stream_test.go
+++ b/libgo/go/encoding/json/stream_test.go
@@ -191,3 +191,16 @@ func TestBlocking(t *testing.T) {
w.Close()
}
}
+
+func BenchmarkEncoderEncode(b *testing.B) {
+ b.ReportAllocs()
+ type T struct {
+ X, Y string
+ }
+ v := &T{"foo", "bar"}
+ for i := 0; i < b.N; i++ {
+ if err := NewEncoder(ioutil.Discard).Encode(v); err != nil {
+ b.Fatal(err)
+ }
+ }
+}
diff --git a/libgo/go/encoding/json/tags.go b/libgo/go/encoding/json/tags.go
index 58cda2027c6..c38fd5102f6 100644
--- a/libgo/go/encoding/json/tags.go
+++ b/libgo/go/encoding/json/tags.go
@@ -21,7 +21,7 @@ func parseTag(tag string) (string, tagOptions) {
return tag, tagOptions("")
}
-// Contains returns whether checks that a comma-separated list of options
+// Contains reports whether a comma-separated list of options
// contains a particular substr flag. substr must be surrounded by a
// string boundary or commas.
func (o tagOptions) Contains(optionName string) bool {
diff --git a/libgo/go/encoding/xml/marshal.go b/libgo/go/encoding/xml/marshal.go
index 47b00176342..d9522e0b39f 100644
--- a/libgo/go/encoding/xml/marshal.go
+++ b/libgo/go/encoding/xml/marshal.go
@@ -7,12 +7,12 @@ package xml
import (
"bufio"
"bytes"
+ "encoding"
"fmt"
"io"
"reflect"
"strconv"
"strings"
- "time"
)
const (
@@ -75,6 +75,41 @@ func Marshal(v interface{}) ([]byte, error) {
return b.Bytes(), nil
}
+// Marshaler is the interface implemented by objects that can marshal
+// themselves into valid XML elements.
+//
+// MarshalXML encodes the receiver as zero or more XML elements.
+// By convention, arrays or slices are typically encoded as a sequence
+// of elements, one per entry.
+// Using start as the element tag is not required, but doing so
+// will enable Unmarshal to match the XML elements to the correct
+// struct field.
+// One common implementation strategy is to construct a separate
+// value with a layout corresponding to the desired XML and then
+// to encode it using e.EncodeElement.
+// Another common strategy is to use repeated calls to e.EncodeToken
+// to generate the XML output one token at a time.
+// The sequence of encoded tokens must make up zero or more valid
+// XML elements.
+type Marshaler interface {
+ MarshalXML(e *Encoder, start StartElement) error
+}
+
+// MarshalerAttr is the interface implemented by objects that can marshal
+// themselves into valid XML attributes.
+//
+// MarshalXMLAttr returns an XML attribute with the encoded value of the receiver.
+// Using name as the attribute name is not required, but doing so
+// will enable Unmarshal to match the attribute to the correct
+// struct field.
+// If MarshalXMLAttr returns the zero attribute Attr{}, no attribute
+// will be generated in the output.
+// MarshalXMLAttr is used only for struct fields with the
+// "attr" option in the field tag.
+type MarshalerAttr interface {
+ MarshalXMLAttr(name Name) (Attr, error)
+}
+
// MarshalIndent works like Marshal, but each XML element begins on a new
// indented line that starts with prefix and is followed by one or more
// copies of indent according to the nesting depth.
@@ -90,36 +125,124 @@ func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) {
// An Encoder writes XML data to an output stream.
type Encoder struct {
- printer
+ p printer
}
// NewEncoder returns a new encoder that writes to w.
func NewEncoder(w io.Writer) *Encoder {
- return &Encoder{printer{Writer: bufio.NewWriter(w)}}
+ e := &Encoder{printer{Writer: bufio.NewWriter(w)}}
+ e.p.encoder = e
+ return e
}
// Indent sets the encoder to generate XML in which each element
// begins on a new indented line that starts with prefix and is followed by
// one or more copies of indent according to the nesting depth.
func (enc *Encoder) Indent(prefix, indent string) {
- enc.prefix = prefix
- enc.indent = indent
+ enc.p.prefix = prefix
+ enc.p.indent = indent
}
// Encode writes the XML encoding of v to the stream.
//
// See the documentation for Marshal for details about the conversion
// of Go values to XML.
+//
+// Encode calls Flush before returning.
func (enc *Encoder) Encode(v interface{}) error {
- err := enc.marshalValue(reflect.ValueOf(v), nil)
+ err := enc.p.marshalValue(reflect.ValueOf(v), nil, nil)
if err != nil {
return err
}
- return enc.Flush()
+ return enc.p.Flush()
+}
+
+// EncodeElement writes the XML encoding of v to the stream,
+// using start as the outermost tag in the encoding.
+//
+// See the documentation for Marshal for details about the conversion
+// of Go values to XML.
+//
+// EncodeElement calls Flush before returning.
+func (enc *Encoder) EncodeElement(v interface{}, start StartElement) error {
+ err := enc.p.marshalValue(reflect.ValueOf(v), nil, &start)
+ if err != nil {
+ return err
+ }
+ return enc.p.Flush()
+}
+
+var (
+ endComment = []byte("-->")
+ endProcInst = []byte("?>")
+ endDirective = []byte(">")
+)
+
+// EncodeToken writes the given XML token to the stream.
+// It returns an error if StartElement and EndElement tokens are not properly matched.
+//
+// EncodeToken does not call Flush, because usually it is part of a larger operation
+// such as Encode or EncodeElement (or a custom Marshaler's MarshalXML invoked
+// during those), and those will call Flush when finished.
+//
+// Callers that create an Encoder and then invoke EncodeToken directly, without
+// using Encode or EncodeElement, need to call Flush when finished to ensure
+// that the XML is written to the underlying writer.
+func (enc *Encoder) EncodeToken(t Token) error {
+ p := &enc.p
+ switch t := t.(type) {
+ case StartElement:
+ if err := p.writeStart(&t); err != nil {
+ return err
+ }
+ case EndElement:
+ if err := p.writeEnd(t.Name); err != nil {
+ return err
+ }
+ case CharData:
+ EscapeText(p, t)
+ case Comment:
+ if bytes.Contains(t, endComment) {
+ return fmt.Errorf("xml: EncodeToken of Comment containing --> marker")
+ }
+ p.WriteString("<!--")
+ p.Write(t)
+ p.WriteString("-->")
+ return p.cachedWriteError()
+ case ProcInst:
+ if t.Target == "xml" || !isNameString(t.Target) {
+ return fmt.Errorf("xml: EncodeToken of ProcInst with invalid Target")
+ }
+ if bytes.Contains(t.Inst, endProcInst) {
+ return fmt.Errorf("xml: EncodeToken of ProcInst containing ?> marker")
+ }
+ p.WriteString("<?")
+ p.WriteString(t.Target)
+ if len(t.Inst) > 0 {
+ p.WriteByte(' ')
+ p.Write(t.Inst)
+ }
+ p.WriteString("?>")
+ case Directive:
+ if bytes.Contains(t, endDirective) {
+ return fmt.Errorf("xml: EncodeToken of Directive containing > marker")
+ }
+ p.WriteString("<!")
+ p.Write(t)
+ p.WriteString(">")
+ }
+ return p.cachedWriteError()
+}
+
+// Flush flushes any buffered XML to the underlying writer.
+// See the EncodeToken documentation for details about when it is necessary.
+func (enc *Encoder) Flush() error {
+ return enc.p.Flush()
}
type printer struct {
*bufio.Writer
+ encoder *Encoder
seq int
indent string
prefix string
@@ -128,13 +251,15 @@ type printer struct {
putNewline bool
attrNS map[string]string // map prefix -> name space
attrPrefix map[string]string // map name space -> prefix
+ prefixes []string
+ tags []Name
}
// createAttrPrefix finds the name space prefix attribute to use for the given name space,
-// defining a new prefix if necessary. It returns the prefix and whether it is new.
-func (p *printer) createAttrPrefix(url string) (prefix string, isNew bool) {
- if prefix = p.attrPrefix[url]; prefix != "" {
- return prefix, false
+// defining a new prefix if necessary. It returns the prefix.
+func (p *printer) createAttrPrefix(url string) string {
+ if prefix := p.attrPrefix[url]; prefix != "" {
+ return prefix
}
// The "http://www.w3.org/XML/1998/namespace" name space is predefined as "xml"
@@ -142,7 +267,7 @@ func (p *printer) createAttrPrefix(url string) (prefix string, isNew bool) {
// (The "http://www.w3.org/2000/xmlns/" name space is also predefined as "xmlns",
// but users should not be trying to use that one directly - that's our job.)
if url == xmlURL {
- return "xml", false
+ return "xml"
}
// Need to define a new name space.
@@ -153,7 +278,7 @@ func (p *printer) createAttrPrefix(url string) (prefix string, isNew bool) {
// Pick a name. We try to use the final element of the path
// but fall back to _.
- prefix = strings.TrimRight(url, "/")
+ prefix := strings.TrimRight(url, "/")
if i := strings.LastIndex(prefix, "/"); i >= 0 {
prefix = prefix[i+1:]
}
@@ -183,7 +308,9 @@ func (p *printer) createAttrPrefix(url string) (prefix string, isNew bool) {
EscapeText(p, []byte(url))
p.WriteString(`" `)
- return prefix, true
+ p.prefixes = append(p.prefixes, prefix)
+
+ return prefix
}
// deleteAttrPrefix removes an attribute name space prefix.
@@ -192,9 +319,34 @@ func (p *printer) deleteAttrPrefix(prefix string) {
delete(p.attrNS, prefix)
}
+func (p *printer) markPrefix() {
+ p.prefixes = append(p.prefixes, "")
+}
+
+func (p *printer) popPrefix() {
+ for len(p.prefixes) > 0 {
+ prefix := p.prefixes[len(p.prefixes)-1]
+ p.prefixes = p.prefixes[:len(p.prefixes)-1]
+ if prefix == "" {
+ break
+ }
+ p.deleteAttrPrefix(prefix)
+ }
+}
+
+var (
+ marshalerType = reflect.TypeOf((*Marshaler)(nil)).Elem()
+ marshalerAttrType = reflect.TypeOf((*MarshalerAttr)(nil)).Elem()
+ textMarshalerType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
+)
+
// marshalValue writes one or more XML elements representing val.
// If val was obtained from a struct field, finfo must have its details.
-func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo) error {
+func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo, startTemplate *StartElement) error {
+ if startTemplate != nil && startTemplate.Name.Local == "" {
+ return fmt.Errorf("xml: EncodeElement of StartElement with missing name")
+ }
+
if !val.IsValid() {
return nil
}
@@ -202,21 +354,45 @@ func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo) error {
return nil
}
+ // Drill into interfaces and pointers.
+ // This can turn into an infinite loop given a cyclic chain,
+ // but it matches the Go 1 behavior.
+ for val.Kind() == reflect.Interface || val.Kind() == reflect.Ptr {
+ if val.IsNil() {
+ return nil
+ }
+ val = val.Elem()
+ }
+
kind := val.Kind()
typ := val.Type()
- // Drill into pointers/interfaces
- if kind == reflect.Ptr || kind == reflect.Interface {
- if val.IsNil() {
- return nil
+ // Check for marshaler.
+ if val.CanInterface() && typ.Implements(marshalerType) {
+ return p.marshalInterface(val.Interface().(Marshaler), defaultStart(typ, finfo, startTemplate))
+ }
+ if val.CanAddr() {
+ pv := val.Addr()
+ if pv.CanInterface() && pv.Type().Implements(marshalerType) {
+ return p.marshalInterface(pv.Interface().(Marshaler), defaultStart(pv.Type(), finfo, startTemplate))
+ }
+ }
+
+ // Check for text marshaler.
+ if val.CanInterface() && typ.Implements(textMarshalerType) {
+ return p.marshalTextInterface(val.Interface().(encoding.TextMarshaler), defaultStart(typ, finfo, startTemplate))
+ }
+ if val.CanAddr() {
+ pv := val.Addr()
+ if pv.CanInterface() && pv.Type().Implements(textMarshalerType) {
+ return p.marshalTextInterface(pv.Interface().(encoding.TextMarshaler), defaultStart(pv.Type(), finfo, startTemplate))
}
- return p.marshalValue(val.Elem(), finfo)
}
// Slices and arrays iterate over the elements. They do not have an enclosing tag.
if (kind == reflect.Slice || kind == reflect.Array) && typ.Elem().Kind() != reflect.Uint8 {
for i, n := 0, val.Len(); i < n; i++ {
- if err := p.marshalValue(val.Index(i), finfo); err != nil {
+ if err := p.marshalValue(val.Index(i), finfo, startTemplate); err != nil {
return err
}
}
@@ -228,40 +404,34 @@ func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo) error {
return err
}
+ // Create start element.
// Precedence for the XML element name is:
+ // 0. startTemplate
// 1. XMLName field in underlying struct;
// 2. field name/tag in the struct field; and
// 3. type name
- var xmlns, name string
- if tinfo.xmlname != nil {
+ var start StartElement
+
+ if startTemplate != nil {
+ start.Name = startTemplate.Name
+ start.Attr = append(start.Attr, startTemplate.Attr...)
+ } else if tinfo.xmlname != nil {
xmlname := tinfo.xmlname
if xmlname.name != "" {
- xmlns, name = xmlname.xmlns, xmlname.name
+ start.Name.Space, start.Name.Local = xmlname.xmlns, xmlname.name
} else if v, ok := xmlname.value(val).Interface().(Name); ok && v.Local != "" {
- xmlns, name = v.Space, v.Local
+ start.Name = v
}
}
- if name == "" && finfo != nil {
- xmlns, name = finfo.xmlns, finfo.name
+ if start.Name.Local == "" && finfo != nil {
+ start.Name.Space, start.Name.Local = finfo.xmlns, finfo.name
}
- if name == "" {
- name = typ.Name()
+ if start.Name.Local == "" {
+ name := typ.Name()
if name == "" {
return &UnsupportedTypeError{typ}
}
- }
-
- p.writeIndent(1)
- p.WriteByte('<')
- p.WriteString(name)
-
- if xmlns != "" {
- p.WriteString(` xmlns="`)
- // TODO: EscapeString, to avoid the allocation.
- if err := EscapeText(p, []byte(xmlns)); err != nil {
- return err
- }
- p.WriteByte('"')
+ start.Name.Local = name
}
// Attributes
@@ -271,67 +441,243 @@ func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo) error {
continue
}
fv := finfo.value(val)
+ name := Name{Space: finfo.xmlns, Local: finfo.name}
+
if finfo.flags&fOmitEmpty != 0 && isEmptyValue(fv) {
continue
}
- p.WriteByte(' ')
- if finfo.xmlns != "" {
- prefix, created := p.createAttrPrefix(finfo.xmlns)
- if created {
- defer p.deleteAttrPrefix(prefix)
+
+ if fv.Kind() == reflect.Interface && fv.IsNil() {
+ continue
+ }
+
+ if fv.CanInterface() && fv.Type().Implements(marshalerAttrType) {
+ attr, err := fv.Interface().(MarshalerAttr).MarshalXMLAttr(name)
+ if err != nil {
+ return err
}
- p.WriteString(prefix)
- p.WriteByte(':')
+ if attr.Name.Local != "" {
+ start.Attr = append(start.Attr, attr)
+ }
+ continue
}
- p.WriteString(finfo.name)
- p.WriteString(`="`)
- if err := p.marshalSimple(fv.Type(), fv); err != nil {
+
+ if fv.CanAddr() {
+ pv := fv.Addr()
+ if pv.CanInterface() && pv.Type().Implements(marshalerAttrType) {
+ attr, err := pv.Interface().(MarshalerAttr).MarshalXMLAttr(name)
+ if err != nil {
+ return err
+ }
+ if attr.Name.Local != "" {
+ start.Attr = append(start.Attr, attr)
+ }
+ continue
+ }
+ }
+
+ if fv.CanInterface() && fv.Type().Implements(textMarshalerType) {
+ text, err := fv.Interface().(encoding.TextMarshaler).MarshalText()
+ if err != nil {
+ return err
+ }
+ start.Attr = append(start.Attr, Attr{name, string(text)})
+ continue
+ }
+
+ if fv.CanAddr() {
+ pv := fv.Addr()
+ if pv.CanInterface() && pv.Type().Implements(textMarshalerType) {
+ text, err := pv.Interface().(encoding.TextMarshaler).MarshalText()
+ if err != nil {
+ return err
+ }
+ start.Attr = append(start.Attr, Attr{name, string(text)})
+ continue
+ }
+ }
+
+ // Dereference or skip nil pointer, interface values.
+ switch fv.Kind() {
+ case reflect.Ptr, reflect.Interface:
+ if fv.IsNil() {
+ continue
+ }
+ fv = fv.Elem()
+ }
+
+ s, b, err := p.marshalSimple(fv.Type(), fv)
+ if err != nil {
return err
}
- p.WriteByte('"')
+ if b != nil {
+ s = string(b)
+ }
+ start.Attr = append(start.Attr, Attr{name, s})
+ }
+
+ if err := p.writeStart(&start); err != nil {
+ return err
}
- p.WriteByte('>')
if val.Kind() == reflect.Struct {
err = p.marshalStruct(tinfo, val)
} else {
- err = p.marshalSimple(typ, val)
+ s, b, err1 := p.marshalSimple(typ, val)
+ if err1 != nil {
+ err = err1
+ } else if b != nil {
+ EscapeText(p, b)
+ } else {
+ p.EscapeString(s)
+ }
}
if err != nil {
return err
}
- p.writeIndent(-1)
- p.WriteByte('<')
- p.WriteByte('/')
- p.WriteString(name)
- p.WriteByte('>')
+ if err := p.writeEnd(start.Name); err != nil {
+ return err
+ }
return p.cachedWriteError()
}
-var timeType = reflect.TypeOf(time.Time{})
+// defaultStart returns the default start element to use,
+// given the reflect type, field info, and start template.
+func defaultStart(typ reflect.Type, finfo *fieldInfo, startTemplate *StartElement) StartElement {
+ var start StartElement
+ // Precedence for the XML element name is as above,
+ // except that we do not look inside structs for the first field.
+ if startTemplate != nil {
+ start.Name = startTemplate.Name
+ start.Attr = append(start.Attr, startTemplate.Attr...)
+ } else if finfo != nil && finfo.name != "" {
+ start.Name.Local = finfo.name
+ start.Name.Space = finfo.xmlns
+ } else if typ.Name() != "" {
+ start.Name.Local = typ.Name()
+ } else {
+ // Must be a pointer to a named type,
+ // since it has the Marshaler methods.
+ start.Name.Local = typ.Elem().Name()
+ }
+ return start
+}
-func (p *printer) marshalSimple(typ reflect.Type, val reflect.Value) error {
- // Normally we don't see structs, but this can happen for an attribute.
- if val.Type() == timeType {
- p.WriteString(val.Interface().(time.Time).Format(time.RFC3339Nano))
- return nil
+// marshalInterface marshals a Marshaler interface value.
+func (p *printer) marshalInterface(val Marshaler, start StartElement) error {
+ // Push a marker onto the tag stack so that MarshalXML
+ // cannot close the XML tags that it did not open.
+ p.tags = append(p.tags, Name{})
+ n := len(p.tags)
+
+ err := val.MarshalXML(p.encoder, start)
+ if err != nil {
+ return err
+ }
+
+ // Make sure MarshalXML closed all its tags. p.tags[n-1] is the mark.
+ if len(p.tags) > n {
+ return fmt.Errorf("xml: %s.MarshalXML wrote invalid XML: <%s> not closed", receiverType(val), p.tags[len(p.tags)-1].Local)
+ }
+ p.tags = p.tags[:n-1]
+ return nil
+}
+
+// marshalTextInterface marshals a TextMarshaler interface value.
+func (p *printer) marshalTextInterface(val encoding.TextMarshaler, start StartElement) error {
+ if err := p.writeStart(&start); err != nil {
+ return err
+ }
+ text, err := val.MarshalText()
+ if err != nil {
+ return err
+ }
+ EscapeText(p, text)
+ return p.writeEnd(start.Name)
+}
+
+// writeStart writes the given start element.
+func (p *printer) writeStart(start *StartElement) error {
+ if start.Name.Local == "" {
+ return fmt.Errorf("xml: start tag with no name")
+ }
+
+ p.tags = append(p.tags, start.Name)
+ p.markPrefix()
+
+ p.writeIndent(1)
+ p.WriteByte('<')
+ p.WriteString(start.Name.Local)
+
+ if start.Name.Space != "" {
+ p.WriteString(` xmlns="`)
+ p.EscapeString(start.Name.Space)
+ p.WriteByte('"')
+ }
+
+ // Attributes
+ for _, attr := range start.Attr {
+ name := attr.Name
+ if name.Local == "" {
+ continue
+ }
+ p.WriteByte(' ')
+ if name.Space != "" {
+ p.WriteString(p.createAttrPrefix(name.Space))
+ p.WriteByte(':')
+ }
+ p.WriteString(name.Local)
+ p.WriteString(`="`)
+ p.EscapeString(attr.Value)
+ p.WriteByte('"')
}
+ p.WriteByte('>')
+ return nil
+}
+
+func (p *printer) writeEnd(name Name) error {
+ if name.Local == "" {
+ return fmt.Errorf("xml: end tag with no name")
+ }
+ if len(p.tags) == 0 || p.tags[len(p.tags)-1].Local == "" {
+ return fmt.Errorf("xml: end tag </%s> without start tag", name.Local)
+ }
+ if top := p.tags[len(p.tags)-1]; top != name {
+ if top.Local != name.Local {
+ return fmt.Errorf("xml: end tag </%s> does not match start tag <%s>", name.Local, top.Local)
+ }
+ return fmt.Errorf("xml: end tag </%s> in namespace %s does not match start tag <%s> in namespace %s", name.Local, name.Space, top.Local, top.Space)
+ }
+ p.tags = p.tags[:len(p.tags)-1]
+
+ p.writeIndent(-1)
+ p.WriteByte('<')
+ p.WriteByte('/')
+ p.WriteString(name.Local)
+ p.WriteByte('>')
+ p.popPrefix()
+ return nil
+}
+
+func (p *printer) marshalSimple(typ reflect.Type, val reflect.Value) (string, []byte, error) {
switch val.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- p.WriteString(strconv.FormatInt(val.Int(), 10))
+ return strconv.FormatInt(val.Int(), 10), nil, nil
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
- p.WriteString(strconv.FormatUint(val.Uint(), 10))
+ return strconv.FormatUint(val.Uint(), 10), nil, nil
case reflect.Float32, reflect.Float64:
- p.WriteString(strconv.FormatFloat(val.Float(), 'g', -1, val.Type().Bits()))
+ return strconv.FormatFloat(val.Float(), 'g', -1, val.Type().Bits()), nil, nil
case reflect.String:
- // TODO: Add EscapeString.
- EscapeText(p, []byte(val.String()))
+ return val.String(), nil, nil
case reflect.Bool:
- p.WriteString(strconv.FormatBool(val.Bool()))
+ return strconv.FormatBool(val.Bool()), nil, nil
case reflect.Array:
- // will be [...]byte
+ if typ.Elem().Kind() != reflect.Uint8 {
+ break
+ }
+ // [...]byte
var bytes []byte
if val.CanAddr() {
bytes = val.Slice(0, val.Len()).Bytes()
@@ -339,32 +685,57 @@ func (p *printer) marshalSimple(typ reflect.Type, val reflect.Value) error {
bytes = make([]byte, val.Len())
reflect.Copy(reflect.ValueOf(bytes), val)
}
- EscapeText(p, bytes)
+ return "", bytes, nil
case reflect.Slice:
- // will be []byte
- EscapeText(p, val.Bytes())
- default:
- return &UnsupportedTypeError{typ}
+ if typ.Elem().Kind() != reflect.Uint8 {
+ break
+ }
+ // []byte
+ return "", val.Bytes(), nil
}
- return p.cachedWriteError()
+ return "", nil, &UnsupportedTypeError{typ}
}
var ddBytes = []byte("--")
func (p *printer) marshalStruct(tinfo *typeInfo, val reflect.Value) error {
- if val.Type() == timeType {
- _, err := p.WriteString(val.Interface().(time.Time).Format(time.RFC3339Nano))
- return err
- }
- s := parentStack{printer: p}
+ s := parentStack{p: p}
for i := range tinfo.fields {
finfo := &tinfo.fields[i]
if finfo.flags&fAttr != 0 {
continue
}
vf := finfo.value(val)
+
+ // Dereference or skip nil pointer, interface values.
+ switch vf.Kind() {
+ case reflect.Ptr, reflect.Interface:
+ if !vf.IsNil() {
+ vf = vf.Elem()
+ }
+ }
+
switch finfo.flags & fMode {
case fCharData:
+ if vf.CanInterface() && vf.Type().Implements(textMarshalerType) {
+ data, err := vf.Interface().(encoding.TextMarshaler).MarshalText()
+ if err != nil {
+ return err
+ }
+ Escape(p, data)
+ continue
+ }
+ if vf.CanAddr() {
+ pv := vf.Addr()
+ if pv.CanInterface() && pv.Type().Implements(textMarshalerType) {
+ data, err := pv.Interface().(encoding.TextMarshaler).MarshalText()
+ if err != nil {
+ return err
+ }
+ Escape(p, data)
+ continue
+ }
+ }
var scratch [64]byte
switch vf.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
@@ -385,10 +756,6 @@ func (p *printer) marshalStruct(tinfo *typeInfo, val reflect.Value) error {
return err
}
}
- case reflect.Struct:
- if vf.Type() == timeType {
- Escape(p, []byte(vf.Interface().(time.Time).Format(time.RFC3339Nano)))
- }
}
continue
@@ -444,14 +811,18 @@ func (p *printer) marshalStruct(tinfo *typeInfo, val reflect.Value) error {
}
case fElement, fElement | fAny:
- s.trim(finfo.parents)
+ if err := s.trim(finfo.parents); err != nil {
+ return err
+ }
if len(finfo.parents) > len(s.stack) {
if vf.Kind() != reflect.Ptr && vf.Kind() != reflect.Interface || !vf.IsNil() {
- s.push(finfo.parents[len(s.stack):])
+ if err := s.push(finfo.parents[len(s.stack):]); err != nil {
+ return err
+ }
}
}
}
- if err := p.marshalValue(vf, finfo); err != nil {
+ if err := p.marshalValue(vf, finfo, nil); err != nil {
return err
}
}
@@ -497,14 +868,14 @@ func (p *printer) writeIndent(depthDelta int) {
}
type parentStack struct {
- *printer
+ p *printer
stack []string
}
// trim updates the XML context to match the longest common prefix of the stack
// and the given parents. A closing tag will be written for every parent
// popped. Passing a zero slice or nil will close all the elements.
-func (s *parentStack) trim(parents []string) {
+func (s *parentStack) trim(parents []string) error {
split := 0
for ; split < len(parents) && split < len(s.stack); split++ {
if parents[split] != s.stack[split] {
@@ -512,23 +883,23 @@ func (s *parentStack) trim(parents []string) {
}
}
for i := len(s.stack) - 1; i >= split; i-- {
- s.writeIndent(-1)
- s.WriteString("</")
- s.WriteString(s.stack[i])
- s.WriteByte('>')
+ if err := s.p.writeEnd(Name{Local: s.stack[i]}); err != nil {
+ return err
+ }
}
s.stack = parents[:split]
+ return nil
}
// push adds parent elements to the stack and writes open tags.
-func (s *parentStack) push(parents []string) {
+func (s *parentStack) push(parents []string) error {
for i := 0; i < len(parents); i++ {
- s.writeIndent(1)
- s.WriteByte('<')
- s.WriteString(parents[i])
- s.WriteByte('>')
+ if err := s.p.writeStart(&StartElement{Name: Name{Local: parents[i]}}); err != nil {
+ return err
+ }
}
s.stack = append(s.stack, parents...)
+ return nil
}
// A MarshalXMLError is returned when Marshal encounters a type
diff --git a/libgo/go/encoding/xml/marshal_test.go b/libgo/go/encoding/xml/marshal_test.go
index ca14a1e53db..d34118a3d8b 100644
--- a/libgo/go/encoding/xml/marshal_test.go
+++ b/libgo/go/encoding/xml/marshal_test.go
@@ -276,6 +276,54 @@ type Strings struct {
X []string `xml:"A>B,omitempty"`
}
+type PointerFieldsTest struct {
+ XMLName Name `xml:"dummy"`
+ Name *string `xml:"name,attr"`
+ Age *uint `xml:"age,attr"`
+ Empty *string `xml:"empty,attr"`
+ Contents *string `xml:",chardata"`
+}
+
+type ChardataEmptyTest struct {
+ XMLName Name `xml:"test"`
+ Contents *string `xml:",chardata"`
+}
+
+type MyMarshalerTest struct {
+}
+
+var _ Marshaler = (*MyMarshalerTest)(nil)
+
+func (m *MyMarshalerTest) MarshalXML(e *Encoder, start StartElement) error {
+ e.EncodeToken(start)
+ e.EncodeToken(CharData([]byte("hello world")))
+ e.EncodeToken(EndElement{start.Name})
+ return nil
+}
+
+type MyMarshalerAttrTest struct {
+}
+
+var _ MarshalerAttr = (*MyMarshalerAttrTest)(nil)
+
+func (m *MyMarshalerAttrTest) MarshalXMLAttr(name Name) (Attr, error) {
+ return Attr{name, "hello world"}, nil
+}
+
+type MarshalerStruct struct {
+ Foo MyMarshalerAttrTest `xml:",attr"`
+}
+
+func ifaceptr(x interface{}) interface{} {
+ return &x
+}
+
+var (
+ nameAttr = "Sarah"
+ ageAttr = uint(12)
+ contentsAttr = "lorem ipsum"
+)
+
// Unless explicitly stated as such (or *Plain), all of the
// tests below are two-way tests. When introducing new tests,
// please try to make them two-way as well to ensure that
@@ -312,6 +360,7 @@ var marshalTests = []struct {
{Value: &Plain{NamedType("potato")}, ExpectXML: `<Plain><V>potato</V></Plain>`},
{Value: &Plain{[]int{1, 2, 3}}, ExpectXML: `<Plain><V>1</V><V>2</V><V>3</V></Plain>`},
{Value: &Plain{[3]int{1, 2, 3}}, ExpectXML: `<Plain><V>1</V><V>2</V><V>3</V></Plain>`},
+ {Value: ifaceptr(true), MarshalOnly: true, ExpectXML: `<bool>true</bool>`},
// Test time.
{
@@ -673,6 +722,20 @@ var marshalTests = []struct {
ExpectXML: `<OmitAttrTest></OmitAttrTest>`,
},
+ // pointer fields
+ {
+ Value: &PointerFieldsTest{Name: &nameAttr, Age: &ageAttr, Contents: &contentsAttr},
+ ExpectXML: `<dummy name="Sarah" age="12">lorem ipsum</dummy>`,
+ MarshalOnly: true,
+ },
+
+ // empty chardata pointer field
+ {
+ Value: &ChardataEmptyTest{},
+ ExpectXML: `<test></test>`,
+ MarshalOnly: true,
+ },
+
// omitempty on fields
{
Value: &OmitFieldTest{
@@ -811,6 +874,15 @@ var marshalTests = []struct {
ExpectXML: `<Strings><A></A></Strings>`,
Value: &Strings{},
},
+ // Custom marshalers.
+ {
+ ExpectXML: `<MyMarshalerTest>hello world</MyMarshalerTest>`,
+ Value: &MyMarshalerTest{},
+ },
+ {
+ ExpectXML: `<MarshalerStruct Foo="hello world"></MarshalerStruct>`,
+ Value: &MarshalerStruct{},
+ },
}
func TestMarshal(t *testing.T) {
@@ -837,6 +909,10 @@ type AttrParent struct {
X string `xml:"X>Y,attr"`
}
+type BadAttr struct {
+ Name []string `xml:"name,attr"`
+}
+
var marshalErrorTests = []struct {
Value interface{}
Err string
@@ -869,6 +945,10 @@ var marshalErrorTests = []struct {
Value: &AttrParent{},
Err: `xml: X>Y chain not valid with attr flag`,
},
+ {
+ Value: BadAttr{[]string{"X", "Y"}},
+ Err: `xml: unsupported type: []string`,
+ },
}
var marshalIndentTests = []struct {
@@ -1009,6 +1089,23 @@ func TestMarshalWriteIOErrors(t *testing.T) {
}
}
+func TestMarshalFlush(t *testing.T) {
+ var buf bytes.Buffer
+ enc := NewEncoder(&buf)
+ if err := enc.EncodeToken(CharData("hello world")); err != nil {
+ t.Fatalf("enc.EncodeToken: %v", err)
+ }
+ if buf.Len() > 0 {
+ t.Fatalf("enc.EncodeToken caused actual write: %q", buf.Bytes())
+ }
+ if err := enc.Flush(); err != nil {
+ t.Fatalf("enc.Flush: %v", err)
+ }
+ if buf.String() != "hello world" {
+ t.Fatalf("after enc.Flush, buf.String() = %q, want %q", buf.String(), "hello world")
+ }
+}
+
func BenchmarkMarshal(b *testing.B) {
for i := 0; i < b.N; i++ {
Marshal(atomValue)
@@ -1021,3 +1118,34 @@ func BenchmarkUnmarshal(b *testing.B) {
Unmarshal(xml, &Feed{})
}
}
+
+// golang.org/issue/6556
+func TestStructPointerMarshal(t *testing.T) {
+ type A struct {
+ XMLName string `xml:"a"`
+ B []interface{}
+ }
+ type C struct {
+ XMLName Name
+ Value string `xml:"value"`
+ }
+
+ a := new(A)
+ a.B = append(a.B, &C{
+ XMLName: Name{Local: "c"},
+ Value: "x",
+ })
+
+ b, err := Marshal(a)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if x := string(b); x != "<a><c><value>x</value></c></a>" {
+ t.Fatal(x)
+ }
+ var v A
+ err = Unmarshal(b, &v)
+ if err != nil {
+ t.Fatal(err)
+ }
+}
diff --git a/libgo/go/encoding/xml/read.go b/libgo/go/encoding/xml/read.go
index a7a2a9655bb..da7ad3baedc 100644
--- a/libgo/go/encoding/xml/read.go
+++ b/libgo/go/encoding/xml/read.go
@@ -6,11 +6,12 @@ package xml
import (
"bytes"
+ "encoding"
"errors"
+ "fmt"
"reflect"
"strconv"
"strings"
- "time"
)
// BUG(rsc): Mapping between XML elements and data structures is inherently flawed:
@@ -57,7 +58,7 @@ import (
// If there is no such field, the character data is discarded.
//
// * If the XML element contains comments, they are accumulated in
-// the first struct field that has tag ",comments". The struct
+// the first struct field that has tag ",comment". The struct
// field may have type []byte or string. If there is no such
// field, the comments are discarded.
//
@@ -137,6 +138,136 @@ type UnmarshalError string
func (e UnmarshalError) Error() string { return string(e) }
+// Unmarshaler is the interface implemented by objects that can unmarshal
+// an XML element description of themselves.
+//
+// UnmarshalXML decodes a single XML element
+// beginning with the given start element.
+// If it returns an error, the outer call to Unmarshal stops and
+// returns that error.
+// UnmarshalXML must consume exactly one XML element.
+// One common implementation strategy is to unmarshal into
+// a separate value with a layout matching the expected XML
+// using d.DecodeElement, and then to copy the data from
+// that value into the receiver.
+// Another common strategy is to use d.Token to process the
+// XML object one token at a time.
+// UnmarshalXML may not use d.RawToken.
+type Unmarshaler interface {
+ UnmarshalXML(d *Decoder, start StartElement) error
+}
+
+// UnmarshalerAttr is the interface implemented by objects that can unmarshal
+// an XML attribute description of themselves.
+//
+// UnmarshalXMLAttr decodes a single XML attribute.
+// If it returns an error, the outer call to Unmarshal stops and
+// returns that error.
+// UnmarshalXMLAttr is used only for struct fields with the
+// "attr" option in the field tag.
+type UnmarshalerAttr interface {
+ UnmarshalXMLAttr(attr Attr) error
+}
+
+// receiverType returns the receiver type to use in an expression like "%s.MethodName".
+func receiverType(val interface{}) string {
+ t := reflect.TypeOf(val)
+ if t.Name() != "" {
+ return t.String()
+ }
+ return "(" + t.String() + ")"
+}
+
+// unmarshalInterface unmarshals a single XML element into val.
+// start is the opening tag of the element.
+func (p *Decoder) unmarshalInterface(val Unmarshaler, start *StartElement) error {
+ // Record that decoder must stop at end tag corresponding to start.
+ p.pushEOF()
+
+ p.unmarshalDepth++
+ err := val.UnmarshalXML(p, *start)
+ p.unmarshalDepth--
+ if err != nil {
+ p.popEOF()
+ return err
+ }
+
+ if !p.popEOF() {
+ return fmt.Errorf("xml: %s.UnmarshalXML did not consume entire <%s> element", receiverType(val), start.Name.Local)
+ }
+
+ return nil
+}
+
+// unmarshalTextInterface unmarshals a single XML element into val.
+// The chardata contained in the element (but not its children)
+// is passed to the text unmarshaler.
+func (p *Decoder) unmarshalTextInterface(val encoding.TextUnmarshaler, start *StartElement) error {
+ var buf []byte
+ depth := 1
+ for depth > 0 {
+ t, err := p.Token()
+ if err != nil {
+ return err
+ }
+ switch t := t.(type) {
+ case CharData:
+ if depth == 1 {
+ buf = append(buf, t...)
+ }
+ case StartElement:
+ depth++
+ case EndElement:
+ depth--
+ }
+ }
+ return val.UnmarshalText(buf)
+}
+
+// unmarshalAttr unmarshals a single XML attribute into val.
+func (p *Decoder) unmarshalAttr(val reflect.Value, attr Attr) error {
+ if val.Kind() == reflect.Ptr {
+ if val.IsNil() {
+ val.Set(reflect.New(val.Type().Elem()))
+ }
+ val = val.Elem()
+ }
+
+ if val.CanInterface() && val.Type().Implements(unmarshalerAttrType) {
+ // This is an unmarshaler with a non-pointer receiver,
+ // so it's likely to be incorrect, but we do what we're told.
+ return val.Interface().(UnmarshalerAttr).UnmarshalXMLAttr(attr)
+ }
+ if val.CanAddr() {
+ pv := val.Addr()
+ if pv.CanInterface() && pv.Type().Implements(unmarshalerAttrType) {
+ return pv.Interface().(UnmarshalerAttr).UnmarshalXMLAttr(attr)
+ }
+ }
+
+ // Not an UnmarshalerAttr; try encoding.TextUnmarshaler.
+ if val.CanInterface() && val.Type().Implements(textUnmarshalerType) {
+ // This is an unmarshaler with a non-pointer receiver,
+ // so it's likely to be incorrect, but we do what we're told.
+ return val.Interface().(encoding.TextUnmarshaler).UnmarshalText([]byte(attr.Value))
+ }
+ if val.CanAddr() {
+ pv := val.Addr()
+ if pv.CanInterface() && pv.Type().Implements(textUnmarshalerType) {
+ return pv.Interface().(encoding.TextUnmarshaler).UnmarshalText([]byte(attr.Value))
+ }
+ }
+
+ copyValue(val, []byte(attr.Value))
+ return nil
+}
+
+var (
+ unmarshalerType = reflect.TypeOf((*Unmarshaler)(nil)).Elem()
+ unmarshalerAttrType = reflect.TypeOf((*UnmarshalerAttr)(nil)).Elem()
+ textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
+)
+
// Unmarshal a single XML element into val.
func (p *Decoder) unmarshal(val reflect.Value, start *StartElement) error {
// Find start element if we need it.
@@ -153,11 +284,35 @@ func (p *Decoder) unmarshal(val reflect.Value, start *StartElement) error {
}
}
- if pv := val; pv.Kind() == reflect.Ptr {
- if pv.IsNil() {
- pv.Set(reflect.New(pv.Type().Elem()))
+ if val.Kind() == reflect.Ptr {
+ if val.IsNil() {
+ val.Set(reflect.New(val.Type().Elem()))
+ }
+ val = val.Elem()
+ }
+
+ if val.CanInterface() && val.Type().Implements(unmarshalerType) {
+ // This is an unmarshaler with a non-pointer receiver,
+ // so it's likely to be incorrect, but we do what we're told.
+ return p.unmarshalInterface(val.Interface().(Unmarshaler), start)
+ }
+
+ if val.CanAddr() {
+ pv := val.Addr()
+ if pv.CanInterface() && pv.Type().Implements(unmarshalerType) {
+ return p.unmarshalInterface(pv.Interface().(Unmarshaler), start)
+ }
+ }
+
+ if val.CanInterface() && val.Type().Implements(textUnmarshalerType) {
+ return p.unmarshalTextInterface(val.Interface().(encoding.TextUnmarshaler), start)
+ }
+
+ if val.CanAddr() {
+ pv := val.Addr()
+ if pv.CanInterface() && pv.Type().Implements(textUnmarshalerType) {
+ return p.unmarshalTextInterface(pv.Interface().(encoding.TextUnmarshaler), start)
}
- val = pv.Elem()
}
var (
@@ -222,10 +377,6 @@ func (p *Decoder) unmarshal(val reflect.Value, start *StartElement) error {
v.Set(reflect.ValueOf(start.Name))
break
}
- if typ == timeType {
- saveData = v
- break
- }
sv = v
tinfo, err = getTypeInfo(typ)
@@ -264,7 +415,9 @@ func (p *Decoder) unmarshal(val reflect.Value, start *StartElement) error {
// Look for attribute.
for _, a := range start.Attr {
if a.Name.Local == finfo.name && (finfo.xmlns == "" || finfo.xmlns == a.Name.Space) {
- copyValue(strv, []byte(a.Value))
+ if err := p.unmarshalAttr(strv, a); err != nil {
+ return err
+ }
break
}
}
@@ -352,6 +505,23 @@ Loop:
}
}
+ if saveData.IsValid() && saveData.CanInterface() && saveData.Type().Implements(textUnmarshalerType) {
+ if err := saveData.Interface().(encoding.TextUnmarshaler).UnmarshalText(data); err != nil {
+ return err
+ }
+ saveData = reflect.Value{}
+ }
+
+ if saveData.IsValid() && saveData.CanAddr() {
+ pv := saveData.Addr()
+ if pv.CanInterface() && pv.Type().Implements(textUnmarshalerType) {
+ if err := pv.Interface().(encoding.TextUnmarshaler).UnmarshalText(data); err != nil {
+ return err
+ }
+ saveData = reflect.Value{}
+ }
+ }
+
if err := copyValue(saveData, data); err != nil {
return err
}
@@ -374,6 +544,8 @@ Loop:
}
func copyValue(dst reflect.Value, src []byte) (err error) {
+ dst0 := dst
+
if dst.Kind() == reflect.Ptr {
if dst.IsNil() {
dst.Set(reflect.New(dst.Type().Elem()))
@@ -384,9 +556,9 @@ func copyValue(dst reflect.Value, src []byte) (err error) {
// Save accumulated data.
switch dst.Kind() {
case reflect.Invalid:
- // Probably a commendst.
+ // Probably a comment.
default:
- return errors.New("cannot happen: unknown type " + dst.Type().String())
+ return errors.New("cannot unmarshal into " + dst0.Type().String())
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
itmp, err := strconv.ParseInt(string(src), 10, dst.Type().Bits())
if err != nil {
@@ -419,14 +591,6 @@ func copyValue(dst reflect.Value, src []byte) (err error) {
src = []byte{}
}
dst.SetBytes(src)
- case reflect.Struct:
- if dst.Type() == timeType {
- tv, err := time.Parse(time.RFC3339, string(src))
- if err != nil {
- return err
- }
- dst.Set(reflect.ValueOf(tv))
- }
}
return nil
}
diff --git a/libgo/go/encoding/xml/read_test.go b/libgo/go/encoding/xml/read_test.go
index 7d28c5d7d6c..1404c900f50 100644
--- a/libgo/go/encoding/xml/read_test.go
+++ b/libgo/go/encoding/xml/read_test.go
@@ -5,6 +5,7 @@
package xml
import (
+ "io"
"reflect"
"strings"
"testing"
@@ -621,3 +622,66 @@ func TestMarshalNSAttr(t *testing.T) {
t.Errorf("Unmarshal = %q, want %q", dst, src)
}
}
+
+type MyCharData struct {
+ body string
+}
+
+func (m *MyCharData) UnmarshalXML(d *Decoder, start StartElement) error {
+ for {
+ t, err := d.Token()
+ if err == io.EOF { // found end of element
+ break
+ }
+ if err != nil {
+ return err
+ }
+ if char, ok := t.(CharData); ok {
+ m.body += string(char)
+ }
+ }
+ return nil
+}
+
+var _ Unmarshaler = (*MyCharData)(nil)
+
+func (m *MyCharData) UnmarshalXMLAttr(attr Attr) error {
+ panic("must not call")
+}
+
+type MyAttr struct {
+ attr string
+}
+
+func (m *MyAttr) UnmarshalXMLAttr(attr Attr) error {
+ m.attr = attr.Value
+ return nil
+}
+
+var _ UnmarshalerAttr = (*MyAttr)(nil)
+
+type MyStruct struct {
+ Data *MyCharData
+ Attr *MyAttr `xml:",attr"`
+
+ Data2 MyCharData
+ Attr2 MyAttr `xml:",attr"`
+}
+
+func TestUnmarshaler(t *testing.T) {
+ xml := `<?xml version="1.0" encoding="utf-8"?>
+ <MyStruct Attr="attr1" Attr2="attr2">
+ <Data>hello <!-- comment -->world</Data>
+ <Data2>howdy <!-- comment -->world</Data2>
+ </MyStruct>
+ `
+
+ var m MyStruct
+ if err := Unmarshal([]byte(xml), &m); err != nil {
+ t.Fatal(err)
+ }
+
+ if m.Data == nil || m.Attr == nil || m.Data.body != "hello world" || m.Attr.attr != "attr1" || m.Data2.body != "howdy world" || m.Attr2.attr != "attr2" {
+ t.Errorf("m=%#+v\n", m)
+ }
+}
diff --git a/libgo/go/encoding/xml/xml.go b/libgo/go/encoding/xml/xml.go
index 021f7e47d91..5b9d670024e 100644
--- a/libgo/go/encoding/xml/xml.go
+++ b/libgo/go/encoding/xml/xml.go
@@ -16,6 +16,7 @@ package xml
import (
"bufio"
"bytes"
+ "errors"
"fmt"
"io"
"strconv"
@@ -66,6 +67,11 @@ func (e StartElement) Copy() StartElement {
return e
}
+// End returns the corresponding XML end element.
+func (e StartElement) End() EndElement {
+ return EndElement{e.Name}
+}
+
// An EndElement represents an XML end element.
type EndElement struct {
Name Name
@@ -144,6 +150,10 @@ type Decoder struct {
// d.Entity = HTMLEntity
//
// creates a parser that can handle typical HTML.
+ //
+ // Strict mode does not enforce the requirements of the XML name spaces TR.
+ // In particular it does not reject name space tags using undefined prefixes.
+ // Such tags are recorded with the unknown prefix as the name space URL.
Strict bool
// When Strict == false, AutoClose indicates a set of elements to
@@ -174,18 +184,19 @@ type Decoder struct {
// the attribute xmlns="DefaultSpace".
DefaultSpace string
- r io.ByteReader
- buf bytes.Buffer
- saved *bytes.Buffer
- stk *stack
- free *stack
- needClose bool
- toClose Name
- nextToken Token
- nextByte int
- ns map[string]string
- err error
- line int
+ r io.ByteReader
+ buf bytes.Buffer
+ saved *bytes.Buffer
+ stk *stack
+ free *stack
+ needClose bool
+ toClose Name
+ nextToken Token
+ nextByte int
+ ns map[string]string
+ err error
+ line int
+ unmarshalDepth int
}
// NewDecoder creates a new XML parser reading from r.
@@ -223,10 +234,14 @@ func NewDecoder(r io.Reader) *Decoder {
// If Token encounters an unrecognized name space prefix,
// it uses the prefix as the Space rather than report an error.
func (d *Decoder) Token() (t Token, err error) {
+ if d.stk != nil && d.stk.kind == stkEOF {
+ err = io.EOF
+ return
+ }
if d.nextToken != nil {
t = d.nextToken
d.nextToken = nil
- } else if t, err = d.RawToken(); err != nil {
+ } else if t, err = d.rawToken(); err != nil {
return
}
@@ -322,6 +337,7 @@ type stack struct {
const (
stkStart = iota
stkNs
+ stkEOF
)
func (d *Decoder) push(kind int) *stack {
@@ -347,6 +363,43 @@ func (d *Decoder) pop() *stack {
return s
}
+// Record that after the current element is finished
+// (that element is already pushed on the stack)
+// Token should return EOF until popEOF is called.
+func (d *Decoder) pushEOF() {
+ // Walk down stack to find Start.
+ // It might not be the top, because there might be stkNs
+ // entries above it.
+ start := d.stk
+ for start.kind != stkStart {
+ start = start.next
+ }
+ // The stkNs entries below a start are associated with that
+ // element too; skip over them.
+ for start.next != nil && start.next.kind == stkNs {
+ start = start.next
+ }
+ s := d.free
+ if s != nil {
+ d.free = s.next
+ } else {
+ s = new(stack)
+ }
+ s.kind = stkEOF
+ s.next = start.next
+ start.next = s
+}
+
+// Undo a pushEOF.
+// The element must have been finished, so the EOF should be at the top of the stack.
+func (d *Decoder) popEOF() bool {
+ if d.stk == nil || d.stk.kind != stkEOF {
+ return false
+ }
+ d.pop()
+ return true
+}
+
// Record that we are starting an element with the given name.
func (d *Decoder) pushElement(name Name) {
s := d.push(stkStart)
@@ -395,9 +448,9 @@ func (d *Decoder) popElement(t *EndElement) bool {
return false
}
- // Pop stack until a Start is on the top, undoing the
+ // Pop stack until a Start or EOF is on the top, undoing the
// translations that were associated with the element we just closed.
- for d.stk != nil && d.stk.kind != stkStart {
+ for d.stk != nil && d.stk.kind != stkStart && d.stk.kind != stkEOF {
s := d.pop()
if s.ok {
d.ns[s.name.Local] = s.name.Space
@@ -429,10 +482,19 @@ func (d *Decoder) autoClose(t Token) (Token, bool) {
return nil, false
}
+var errRawToken = errors.New("xml: cannot use RawToken from UnmarshalXML method")
+
// RawToken is like Token but does not verify that
// start and end elements match and does not translate
// name space prefixes to their corresponding URLs.
func (d *Decoder) RawToken() (Token, error) {
+ if d.unmarshalDepth > 0 {
+ return nil, errRawToken
+ }
+ return d.rawToken()
+}
+
+func (d *Decoder) rawToken() (Token, error) {
if d.err != nil {
return nil, d.err
}
@@ -484,8 +546,7 @@ func (d *Decoder) RawToken() (Token, error) {
case '?':
// <?: Processing instruction.
- // TODO(rsc): Should parse the <?xml declaration to make sure
- // the version is 1.0 and the encoding is UTF-8.
+ // TODO(rsc): Should parse the <?xml declaration to make sure the version is 1.0.
var target string
if target, ok = d.name(); !ok {
if d.err == nil {
@@ -1112,6 +1173,30 @@ func isName(s []byte) bool {
return true
}
+func isNameString(s string) bool {
+ if len(s) == 0 {
+ return false
+ }
+ c, n := utf8.DecodeRuneInString(s)
+ if c == utf8.RuneError && n == 1 {
+ return false
+ }
+ if !unicode.Is(first, c) {
+ return false
+ }
+ for n < len(s) {
+ s = s[n:]
+ c, n = utf8.DecodeRuneInString(s)
+ if c == utf8.RuneError && n == 1 {
+ return false
+ }
+ if !unicode.Is(first, c) && !unicode.Is(second, c) {
+ return false
+ }
+ }
+ return true
+}
+
// These tables were generated by cut and paste from Appendix B of
// the XML spec at http://www.xml.com/axml/testaxml.htm
// and then reformatting. First corresponds to (Letter | '_' | ':')
@@ -1758,7 +1843,7 @@ func EscapeText(w io.Writer, s []byte) error {
case '\r':
esc = esc_cr
default:
- if !isInCharacterRange(r) {
+ if !isInCharacterRange(r) || (r == 0xFFFD && width == 1) {
esc = esc_fffd
break
}
@@ -1778,6 +1863,45 @@ func EscapeText(w io.Writer, s []byte) error {
return nil
}
+// EscapeString writes to p the properly escaped XML equivalent
+// of the plain text data s.
+func (p *printer) EscapeString(s string) {
+ var esc []byte
+ last := 0
+ for i := 0; i < len(s); {
+ r, width := utf8.DecodeRuneInString(s[i:])
+ i += width
+ switch r {
+ case '"':
+ esc = esc_quot
+ case '\'':
+ esc = esc_apos
+ case '&':
+ esc = esc_amp
+ case '<':
+ esc = esc_lt
+ case '>':
+ esc = esc_gt
+ case '\t':
+ esc = esc_tab
+ case '\n':
+ esc = esc_nl
+ case '\r':
+ esc = esc_cr
+ default:
+ if !isInCharacterRange(r) || (r == 0xFFFD && width == 1) {
+ esc = esc_fffd
+ break
+ }
+ continue
+ }
+ p.WriteString(s[last : i-width])
+ p.Write(esc)
+ last = i
+ }
+ p.WriteString(s[last:])
+}
+
// Escape is like EscapeText but omits the error return value.
// It is provided for backwards compatibility with Go 1.0.
// Code targeting Go 1.1 or later should use EscapeText.
diff --git a/libgo/go/encoding/xml/xml_test.go b/libgo/go/encoding/xml/xml_test.go
index eeedbe575f8..7723ab1c9f0 100644
--- a/libgo/go/encoding/xml/xml_test.go
+++ b/libgo/go/encoding/xml/xml_test.go
@@ -11,6 +11,7 @@ import (
"reflect"
"strings"
"testing"
+ "unicode/utf8"
)
const testInput = `
@@ -246,10 +247,8 @@ func (d *downCaser) Read(p []byte) (int, error) {
}
func TestRawTokenAltEncoding(t *testing.T) {
- sawEncoding := ""
d := NewDecoder(strings.NewReader(testInputAltEncoding))
d.CharsetReader = func(charset string, input io.Reader) (io.Reader, error) {
- sawEncoding = charset
if charset != "x-testing-uppercase" {
t.Fatalf("unexpected charset %q", charset)
}
@@ -714,3 +713,14 @@ func TestEscapeTextInvalidChar(t *testing.T) {
t.Errorf("have %v, want %v", text, expected)
}
}
+
+func TestIssue5880(t *testing.T) {
+ type T []byte
+ data, err := Marshal(T{192, 168, 0, 1})
+ if err != nil {
+ t.Errorf("Marshal error: %v", err)
+ }
+ if !utf8.Valid(data) {
+ t.Errorf("Marshal generated invalid UTF-8: %x", data)
+ }
+}
diff --git a/libgo/go/flag/export_test.go b/libgo/go/flag/export_test.go
index 7b190807a8a..56cda58b36c 100644
--- a/libgo/go/flag/export_test.go
+++ b/libgo/go/flag/export_test.go
@@ -12,11 +12,6 @@ import "os"
// After calling ResetForTesting, parse errors in flag handling will not
// exit the program.
func ResetForTesting(usage func()) {
- commandLine = NewFlagSet(os.Args[0], ContinueOnError)
+ CommandLine = NewFlagSet(os.Args[0], ContinueOnError)
Usage = usage
}
-
-// CommandLine returns the default FlagSet.
-func CommandLine() *FlagSet {
- return commandLine
-}
diff --git a/libgo/go/flag/flag.go b/libgo/go/flag/flag.go
index 85dd8c3b37a..e7c863ee92d 100644
--- a/libgo/go/flag/flag.go
+++ b/libgo/go/flag/flag.go
@@ -89,6 +89,8 @@ func (b *boolValue) Set(s string) error {
return err
}
+func (b *boolValue) Get() interface{} { return bool(*b) }
+
func (b *boolValue) String() string { return fmt.Sprintf("%v", *b) }
func (b *boolValue) IsBoolFlag() bool { return true }
@@ -114,6 +116,8 @@ func (i *intValue) Set(s string) error {
return err
}
+func (i *intValue) Get() interface{} { return int(*i) }
+
func (i *intValue) String() string { return fmt.Sprintf("%v", *i) }
// -- int64 Value
@@ -130,6 +134,8 @@ func (i *int64Value) Set(s string) error {
return err
}
+func (i *int64Value) Get() interface{} { return int64(*i) }
+
func (i *int64Value) String() string { return fmt.Sprintf("%v", *i) }
// -- uint Value
@@ -146,6 +152,8 @@ func (i *uintValue) Set(s string) error {
return err
}
+func (i *uintValue) Get() interface{} { return uint(*i) }
+
func (i *uintValue) String() string { return fmt.Sprintf("%v", *i) }
// -- uint64 Value
@@ -162,6 +170,8 @@ func (i *uint64Value) Set(s string) error {
return err
}
+func (i *uint64Value) Get() interface{} { return uint64(*i) }
+
func (i *uint64Value) String() string { return fmt.Sprintf("%v", *i) }
// -- string Value
@@ -177,6 +187,8 @@ func (s *stringValue) Set(val string) error {
return nil
}
+func (s *stringValue) Get() interface{} { return string(*s) }
+
func (s *stringValue) String() string { return fmt.Sprintf("%s", *s) }
// -- float64 Value
@@ -193,6 +205,8 @@ func (f *float64Value) Set(s string) error {
return err
}
+func (f *float64Value) Get() interface{} { return float64(*f) }
+
func (f *float64Value) String() string { return fmt.Sprintf("%v", *f) }
// -- time.Duration Value
@@ -209,6 +223,8 @@ func (d *durationValue) Set(s string) error {
return err
}
+func (d *durationValue) Get() interface{} { return time.Duration(*d) }
+
func (d *durationValue) String() string { return (*time.Duration)(d).String() }
// Value is the interface to the dynamic value stored in a flag.
@@ -222,6 +238,15 @@ type Value interface {
Set(string) error
}
+// Getter is an interface that allows the contents of a Value to be retrieved.
+// It wraps the Value interface, rather than being part of it, because it
+// appeared after Go 1 and its compatibility rules. All Value types provided
+// by this package satisfy the Getter interface.
+type Getter interface {
+ Value
+ Get() interface{}
+}
+
// ErrorHandling defines how to handle flag parsing errors.
type ErrorHandling int
@@ -231,7 +256,8 @@ const (
PanicOnError
)
-// A FlagSet represents a set of defined flags.
+// A FlagSet represents a set of defined flags. The zero value of a FlagSet
+// has no name and has ContinueOnError error handling.
type FlagSet struct {
// Usage is the function called when an error occurs while parsing flags.
// The field is a function (not a method) that may be changed to point to
@@ -296,7 +322,7 @@ func (f *FlagSet) VisitAll(fn func(*Flag)) {
// VisitAll visits the command-line flags in lexicographical order, calling
// fn for each. It visits all flags, even those not set.
func VisitAll(fn func(*Flag)) {
- commandLine.VisitAll(fn)
+ CommandLine.VisitAll(fn)
}
// Visit visits the flags in lexicographical order, calling fn for each.
@@ -310,7 +336,7 @@ func (f *FlagSet) Visit(fn func(*Flag)) {
// Visit visits the command-line flags in lexicographical order, calling fn
// for each. It visits only those flags that have been set.
func Visit(fn func(*Flag)) {
- commandLine.Visit(fn)
+ CommandLine.Visit(fn)
}
// Lookup returns the Flag structure of the named flag, returning nil if none exists.
@@ -321,7 +347,7 @@ func (f *FlagSet) Lookup(name string) *Flag {
// Lookup returns the Flag structure of the named command-line flag,
// returning nil if none exists.
func Lookup(name string) *Flag {
- return commandLine.formal[name]
+ return CommandLine.formal[name]
}
// Set sets the value of the named flag.
@@ -343,7 +369,7 @@ func (f *FlagSet) Set(name, value string) error {
// Set sets the value of the named command-line flag.
func Set(name, value string) error {
- return commandLine.Set(name, value)
+ return CommandLine.Set(name, value)
}
// PrintDefaults prints, to standard error unless configured
@@ -361,16 +387,20 @@ func (f *FlagSet) PrintDefaults() {
// PrintDefaults prints to standard error the default values of all defined command-line flags.
func PrintDefaults() {
- commandLine.PrintDefaults()
+ CommandLine.PrintDefaults()
}
// defaultUsage is the default function to print a usage message.
func defaultUsage(f *FlagSet) {
- fmt.Fprintf(f.out(), "Usage of %s:\n", f.name)
+ if f.name == "" {
+ fmt.Fprintf(f.out(), "Usage:\n")
+ } else {
+ fmt.Fprintf(f.out(), "Usage of %s:\n", f.name)
+ }
f.PrintDefaults()
}
-// NOTE: Usage is not just defaultUsage(commandLine)
+// NOTE: Usage is not just defaultUsage(CommandLine)
// because it serves (via godoc flag Usage) as the example
// for how to write your own usage function.
@@ -385,7 +415,7 @@ var Usage = func() {
func (f *FlagSet) NFlag() int { return len(f.actual) }
// NFlag returns the number of command-line flags that have been set.
-func NFlag() int { return len(commandLine.actual) }
+func NFlag() int { return len(CommandLine.actual) }
// Arg returns the i'th argument. Arg(0) is the first remaining argument
// after flags have been processed.
@@ -399,20 +429,20 @@ func (f *FlagSet) Arg(i int) string {
// Arg returns the i'th command-line argument. Arg(0) is the first remaining argument
// after flags have been processed.
func Arg(i int) string {
- return commandLine.Arg(i)
+ return CommandLine.Arg(i)
}
// NArg is the number of arguments remaining after flags have been processed.
func (f *FlagSet) NArg() int { return len(f.args) }
// NArg is the number of arguments remaining after flags have been processed.
-func NArg() int { return len(commandLine.args) }
+func NArg() int { return len(CommandLine.args) }
// Args returns the non-flag arguments.
func (f *FlagSet) Args() []string { return f.args }
// Args returns the non-flag command-line arguments.
-func Args() []string { return commandLine.args }
+func Args() []string { return CommandLine.args }
// BoolVar defines a bool flag with specified name, default value, and usage string.
// The argument p points to a bool variable in which to store the value of the flag.
@@ -423,7 +453,7 @@ func (f *FlagSet) BoolVar(p *bool, name string, value bool, usage string) {
// BoolVar defines a bool flag with specified name, default value, and usage string.
// The argument p points to a bool variable in which to store the value of the flag.
func BoolVar(p *bool, name string, value bool, usage string) {
- commandLine.Var(newBoolValue(value, p), name, usage)
+ CommandLine.Var(newBoolValue(value, p), name, usage)
}
// Bool defines a bool flag with specified name, default value, and usage string.
@@ -437,7 +467,7 @@ func (f *FlagSet) Bool(name string, value bool, usage string) *bool {
// Bool defines a bool flag with specified name, default value, and usage string.
// The return value is the address of a bool variable that stores the value of the flag.
func Bool(name string, value bool, usage string) *bool {
- return commandLine.Bool(name, value, usage)
+ return CommandLine.Bool(name, value, usage)
}
// IntVar defines an int flag with specified name, default value, and usage string.
@@ -449,7 +479,7 @@ func (f *FlagSet) IntVar(p *int, name string, value int, usage string) {
// IntVar defines an int flag with specified name, default value, and usage string.
// The argument p points to an int variable in which to store the value of the flag.
func IntVar(p *int, name string, value int, usage string) {
- commandLine.Var(newIntValue(value, p), name, usage)
+ CommandLine.Var(newIntValue(value, p), name, usage)
}
// Int defines an int flag with specified name, default value, and usage string.
@@ -463,7 +493,7 @@ func (f *FlagSet) Int(name string, value int, usage string) *int {
// Int defines an int flag with specified name, default value, and usage string.
// The return value is the address of an int variable that stores the value of the flag.
func Int(name string, value int, usage string) *int {
- return commandLine.Int(name, value, usage)
+ return CommandLine.Int(name, value, usage)
}
// Int64Var defines an int64 flag with specified name, default value, and usage string.
@@ -475,7 +505,7 @@ func (f *FlagSet) Int64Var(p *int64, name string, value int64, usage string) {
// Int64Var defines an int64 flag with specified name, default value, and usage string.
// The argument p points to an int64 variable in which to store the value of the flag.
func Int64Var(p *int64, name string, value int64, usage string) {
- commandLine.Var(newInt64Value(value, p), name, usage)
+ CommandLine.Var(newInt64Value(value, p), name, usage)
}
// Int64 defines an int64 flag with specified name, default value, and usage string.
@@ -489,7 +519,7 @@ func (f *FlagSet) Int64(name string, value int64, usage string) *int64 {
// Int64 defines an int64 flag with specified name, default value, and usage string.
// The return value is the address of an int64 variable that stores the value of the flag.
func Int64(name string, value int64, usage string) *int64 {
- return commandLine.Int64(name, value, usage)
+ return CommandLine.Int64(name, value, usage)
}
// UintVar defines a uint flag with specified name, default value, and usage string.
@@ -501,7 +531,7 @@ func (f *FlagSet) UintVar(p *uint, name string, value uint, usage string) {
// UintVar defines a uint flag with specified name, default value, and usage string.
// The argument p points to a uint variable in which to store the value of the flag.
func UintVar(p *uint, name string, value uint, usage string) {
- commandLine.Var(newUintValue(value, p), name, usage)
+ CommandLine.Var(newUintValue(value, p), name, usage)
}
// Uint defines a uint flag with specified name, default value, and usage string.
@@ -515,7 +545,7 @@ func (f *FlagSet) Uint(name string, value uint, usage string) *uint {
// Uint defines a uint flag with specified name, default value, and usage string.
// The return value is the address of a uint variable that stores the value of the flag.
func Uint(name string, value uint, usage string) *uint {
- return commandLine.Uint(name, value, usage)
+ return CommandLine.Uint(name, value, usage)
}
// Uint64Var defines a uint64 flag with specified name, default value, and usage string.
@@ -527,7 +557,7 @@ func (f *FlagSet) Uint64Var(p *uint64, name string, value uint64, usage string)
// Uint64Var defines a uint64 flag with specified name, default value, and usage string.
// The argument p points to a uint64 variable in which to store the value of the flag.
func Uint64Var(p *uint64, name string, value uint64, usage string) {
- commandLine.Var(newUint64Value(value, p), name, usage)
+ CommandLine.Var(newUint64Value(value, p), name, usage)
}
// Uint64 defines a uint64 flag with specified name, default value, and usage string.
@@ -541,7 +571,7 @@ func (f *FlagSet) Uint64(name string, value uint64, usage string) *uint64 {
// Uint64 defines a uint64 flag with specified name, default value, and usage string.
// The return value is the address of a uint64 variable that stores the value of the flag.
func Uint64(name string, value uint64, usage string) *uint64 {
- return commandLine.Uint64(name, value, usage)
+ return CommandLine.Uint64(name, value, usage)
}
// StringVar defines a string flag with specified name, default value, and usage string.
@@ -553,7 +583,7 @@ func (f *FlagSet) StringVar(p *string, name string, value string, usage string)
// StringVar defines a string flag with specified name, default value, and usage string.
// The argument p points to a string variable in which to store the value of the flag.
func StringVar(p *string, name string, value string, usage string) {
- commandLine.Var(newStringValue(value, p), name, usage)
+ CommandLine.Var(newStringValue(value, p), name, usage)
}
// String defines a string flag with specified name, default value, and usage string.
@@ -567,7 +597,7 @@ func (f *FlagSet) String(name string, value string, usage string) *string {
// String defines a string flag with specified name, default value, and usage string.
// The return value is the address of a string variable that stores the value of the flag.
func String(name string, value string, usage string) *string {
- return commandLine.String(name, value, usage)
+ return CommandLine.String(name, value, usage)
}
// Float64Var defines a float64 flag with specified name, default value, and usage string.
@@ -579,7 +609,7 @@ func (f *FlagSet) Float64Var(p *float64, name string, value float64, usage strin
// Float64Var defines a float64 flag with specified name, default value, and usage string.
// The argument p points to a float64 variable in which to store the value of the flag.
func Float64Var(p *float64, name string, value float64, usage string) {
- commandLine.Var(newFloat64Value(value, p), name, usage)
+ CommandLine.Var(newFloat64Value(value, p), name, usage)
}
// Float64 defines a float64 flag with specified name, default value, and usage string.
@@ -593,7 +623,7 @@ func (f *FlagSet) Float64(name string, value float64, usage string) *float64 {
// Float64 defines a float64 flag with specified name, default value, and usage string.
// The return value is the address of a float64 variable that stores the value of the flag.
func Float64(name string, value float64, usage string) *float64 {
- return commandLine.Float64(name, value, usage)
+ return CommandLine.Float64(name, value, usage)
}
// DurationVar defines a time.Duration flag with specified name, default value, and usage string.
@@ -605,7 +635,7 @@ func (f *FlagSet) DurationVar(p *time.Duration, name string, value time.Duration
// DurationVar defines a time.Duration flag with specified name, default value, and usage string.
// The argument p points to a time.Duration variable in which to store the value of the flag.
func DurationVar(p *time.Duration, name string, value time.Duration, usage string) {
- commandLine.Var(newDurationValue(value, p), name, usage)
+ CommandLine.Var(newDurationValue(value, p), name, usage)
}
// Duration defines a time.Duration flag with specified name, default value, and usage string.
@@ -619,7 +649,7 @@ func (f *FlagSet) Duration(name string, value time.Duration, usage string) *time
// Duration defines a time.Duration flag with specified name, default value, and usage string.
// The return value is the address of a time.Duration variable that stores the value of the flag.
func Duration(name string, value time.Duration, usage string) *time.Duration {
- return commandLine.Duration(name, value, usage)
+ return CommandLine.Duration(name, value, usage)
}
// Var defines a flag with the specified name and usage string. The type and
@@ -633,7 +663,12 @@ func (f *FlagSet) Var(value Value, name string, usage string) {
flag := &Flag{name, usage, value, value.String()}
_, alreadythere := f.formal[name]
if alreadythere {
- msg := fmt.Sprintf("%s flag redefined: %s", f.name, name)
+ var msg string
+ if f.name == "" {
+ msg = fmt.Sprintf("flag redefined: %s", name)
+ } else {
+ msg = fmt.Sprintf("%s flag redefined: %s", f.name, name)
+ }
fmt.Fprintln(f.out(), msg)
panic(msg) // Happens only if flags are declared with identical names
}
@@ -650,7 +685,7 @@ func (f *FlagSet) Var(value Value, name string, usage string) {
// of strings by giving the slice the methods of Value; in particular, Set would
// decompose the comma-separated string into the slice.
func Var(value Value, name string, usage string) {
- commandLine.Var(value, name, usage)
+ CommandLine.Var(value, name, usage)
}
// failf prints to standard error a formatted error and usage message and
@@ -663,9 +698,9 @@ func (f *FlagSet) failf(format string, a ...interface{}) error {
}
// usage calls the Usage method for the flag set, or the usage function if
-// the flag set is commandLine.
+// the flag set is CommandLine.
func (f *FlagSet) usage() {
- if f == commandLine {
+ if f == CommandLine {
Usage()
} else if f.Usage == nil {
defaultUsage(f)
@@ -674,7 +709,7 @@ func (f *FlagSet) usage() {
}
}
-// parseOne parses one flag. It returns whether a flag was seen.
+// parseOne parses one flag. It reports whether a flag was seen.
func (f *FlagSet) parseOne() (bool, error) {
if len(f.args) == 0 {
return false, nil
@@ -781,17 +816,19 @@ func (f *FlagSet) Parsed() bool {
// Parse parses the command-line flags from os.Args[1:]. Must be called
// after all flags are defined and before flags are accessed by the program.
func Parse() {
- // Ignore errors; commandLine is set for ExitOnError.
- commandLine.Parse(os.Args[1:])
+ // Ignore errors; CommandLine is set for ExitOnError.
+ CommandLine.Parse(os.Args[1:])
}
// Parsed returns true if the command-line flags have been parsed.
func Parsed() bool {
- return commandLine.Parsed()
+ return CommandLine.Parsed()
}
-// The default set of command-line flags, parsed from os.Args.
-var commandLine = NewFlagSet(os.Args[0], ExitOnError)
+// CommandLine is the default set of command-line flags, parsed from os.Args.
+// The top-level functions such as BoolVar, Arg, and on are wrappers for the
+// methods of CommandLine.
+var CommandLine = NewFlagSet(os.Args[0], ExitOnError)
// NewFlagSet returns a new, empty flag set with the specified name and
// error handling property.
diff --git a/libgo/go/flag/flag_test.go b/libgo/go/flag/flag_test.go
index ddd54b2777f..2c038726979 100644
--- a/libgo/go/flag/flag_test.go
+++ b/libgo/go/flag/flag_test.go
@@ -92,10 +92,54 @@ func TestEverything(t *testing.T) {
}
}
+func TestGet(t *testing.T) {
+ ResetForTesting(nil)
+ Bool("test_bool", true, "bool value")
+ Int("test_int", 1, "int value")
+ Int64("test_int64", 2, "int64 value")
+ Uint("test_uint", 3, "uint value")
+ Uint64("test_uint64", 4, "uint64 value")
+ String("test_string", "5", "string value")
+ Float64("test_float64", 6, "float64 value")
+ Duration("test_duration", 7, "time.Duration value")
+
+ visitor := func(f *Flag) {
+ if len(f.Name) > 5 && f.Name[0:5] == "test_" {
+ g, ok := f.Value.(Getter)
+ if !ok {
+ t.Errorf("Visit: value does not satisfy Getter: %T", f.Value)
+ return
+ }
+ switch f.Name {
+ case "test_bool":
+ ok = g.Get() == true
+ case "test_int":
+ ok = g.Get() == int(1)
+ case "test_int64":
+ ok = g.Get() == int64(2)
+ case "test_uint":
+ ok = g.Get() == uint(3)
+ case "test_uint64":
+ ok = g.Get() == uint64(4)
+ case "test_string":
+ ok = g.Get() == "5"
+ case "test_float64":
+ ok = g.Get() == float64(6)
+ case "test_duration":
+ ok = g.Get() == time.Duration(7)
+ }
+ if !ok {
+ t.Errorf("Visit: bad value %T(%v) for %s", g.Get(), g.Get(), f.Name)
+ }
+ }
+ }
+ VisitAll(visitor)
+}
+
func TestUsage(t *testing.T) {
called := false
ResetForTesting(func() { called = true })
- if CommandLine().Parse([]string{"-x"}) == nil {
+ if CommandLine.Parse([]string{"-x"}) == nil {
t.Error("parse did not fail for unknown flag")
}
if !called {
@@ -171,7 +215,7 @@ func testParse(f *FlagSet, t *testing.T) {
func TestParse(t *testing.T) {
ResetForTesting(func() { t.Error("bad parse") })
- testParse(CommandLine(), t)
+ testParse(CommandLine, t)
}
func TestFlagSetParse(t *testing.T) {
@@ -267,7 +311,7 @@ func TestChangingArgs(t *testing.T) {
defer func() { os.Args = oldArgs }()
os.Args = []string{"cmd", "-before", "subcmd", "-after", "args"}
before := Bool("before", false, "")
- if err := CommandLine().Parse(os.Args[1:]); err != nil {
+ if err := CommandLine.Parse(os.Args[1:]); err != nil {
t.Fatal(err)
}
cmd := Arg(0)
diff --git a/libgo/go/fmt/doc.go b/libgo/go/fmt/doc.go
index b8dd995c77b..095fd03b23d 100644
--- a/libgo/go/fmt/doc.go
+++ b/libgo/go/fmt/doc.go
@@ -118,6 +118,28 @@
convert the value before recurring:
func (x X) String() string { return Sprintf("<%s>", string(x)) }
+ Explicit argument indexes:
+
+ In Printf, Sprintf, and Fprintf, the default behavior is for each
+ formatting verb to format successive arguments passed in the call.
+ However, the notation [n] immediately before the verb indicates that the
+ nth one-indexed argument is to be formatted instead. The same notation
+ before a '*' for a width or precision selects the argument index holding
+ the value. After processing a bracketed expression [n], arguments n+1,
+ n+2, etc. will be processed unless otherwise directed.
+
+ For example,
+ fmt.Sprintf("%[2]d %[1]d\n", 11, 22)
+ will yield "22, 11", while
+ fmt.Sprintf("%[3]*.[2]*[1]f", 12.0, 2, 6),
+ equivalent to
+ fmt.Sprintf("%6.2f", 12.0),
+ will yield " 12.00". Because an explicit index affects subsequent verbs,
+ this notation can be used to print the same values multiple times
+ by resetting the index for the first argument to be repeated:
+ fmt.Sprintf("%d %d %#[1]x %#x", 16, 17)
+ will yield "16 17 0x10 0x11".
+
Format errors:
If an invalid argument is given for a verb, such as providing
@@ -133,6 +155,9 @@
Non-int for width or precision: %!(BADWIDTH) or %!(BADPREC)
Printf("%*s", 4.5, "hi"): %!(BADWIDTH)hi
Printf("%.*s", 4.5, "hi"): %!(BADPREC)hi
+ Invalid or invalid use of argument index: %!(BADINDEX)
+ Printf("%*[2]d", 7): %!d(BADINDEX)
+ Printf("%.[2]d", 7): %!d(BADINDEX)
All errors begin with the string "%!" followed sometimes
by a single character (the verb) and end with a parenthesized
@@ -144,9 +169,9 @@
through the fmt package. For example, if a String method
calls panic("bad"), the resulting formatted message will look
like
- %s(PANIC=bad)
+ %!s(PANIC=bad)
- The %s just shows the print verb in use when the failure
+ The %!s just shows the print verb in use when the failure
occurred.
Scanning
@@ -190,6 +215,10 @@
stops if it does not, with the return value of the function
indicating the number of arguments scanned.
+ In all the scanning functions, a carriage return followed
+ immediately by a newline is treated as a plain newline
+ (\r\n means the same as \n).
+
In all the scanning functions, if an operand implements method
Scan (that is, it implements the Scanner interface) that
method will be used to scan the text for that operand. Also,
diff --git a/libgo/go/fmt/fmt_test.go b/libgo/go/fmt/fmt_test.go
index df9e5a0af24..bbca2c574b0 100644
--- a/libgo/go/fmt/fmt_test.go
+++ b/libgo/go/fmt/fmt_test.go
@@ -110,7 +110,7 @@ var bslice = barray[:]
var b byte
-var fmttests = []struct {
+var fmtTests = []struct {
fmt string
val interface{}
out string
@@ -227,6 +227,8 @@ var fmttests = []struct {
{"%+.3g", -1.0, "-1"},
{"% .3g", -1.0, "-1"},
{"% .3g", 1.0, " 1"},
+ {"%b", float32(1.0), "8388608p-23"},
+ {"%b", 1.0, "4503599627370496p-52"},
// complex values
{"%+.3e", 0i, "(+0.000e+00+0.000e+00i)"},
@@ -247,6 +249,8 @@ var fmttests = []struct {
{"% .3E", -1 - 2i, "(-1.000E+00-2.000E+00i)"},
{"%+.3g", complex64(1 + 2i), "(+1+2i)"},
{"%+.3g", complex128(1 + 2i), "(+1+2i)"},
+ {"%b", complex64(1 + 2i), "(8388608p-23+8388608p-22i)"},
+ {"%b", 1 + 2i, "(4503599627370496p-52+4503599627370496p-51i)"},
// erroneous formats
{"", 2, "%!(EXTRA int=2)"},
@@ -493,6 +497,17 @@ var fmttests = []struct {
// Used to crash because nByte didn't allow for a sign.
{"%b", int64(-1 << 63), "-1000000000000000000000000000000000000000000000000000000000000000"},
+ // Used to panic.
+ {"%0100d", 1, "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001"},
+ {"%0100d", -1, "-000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001"},
+ {"%0.100f", 1.0, "1.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"},
+ {"%0.100f", -1.0, "-1.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"},
+
+ // Zero padding floats used to put the minus sign in the middle.
+ {"%020f", -1.0, "-000000000001.000000"},
+ {"%20f", -1.0, " -1.000000"},
+ {"%0100f", -1.0, "-00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.000000"},
+
// Complex fmt used to leave the plus flag set for future entries in the array
// causing +2+0i and +3+0i instead of 2+0i and 3+0i.
{"%v", []complex64{1, 2, 3}, "[(1+0i) (2+0i) (3+0i)]"},
@@ -503,7 +518,7 @@ var fmttests = []struct {
}
func TestSprintf(t *testing.T) {
- for _, tt := range fmttests {
+ for _, tt := range fmtTests {
s := Sprintf(tt.fmt, tt.val)
if i := strings.Index(tt.out, "PTR"); i >= 0 {
pattern := "PTR"
@@ -539,6 +554,55 @@ func TestSprintf(t *testing.T) {
}
}
+type SE []interface{} // slice of empty; notational compactness.
+
+var reorderTests = []struct {
+ fmt string
+ val SE
+ out string
+}{
+ {"%[1]d", SE{1}, "1"},
+ {"%[2]d", SE{2, 1}, "1"},
+ {"%[2]d %[1]d", SE{1, 2}, "2 1"},
+ {"%[2]*[1]d", SE{2, 5}, " 2"},
+ {"%6.2f", SE{12.0}, " 12.00"}, // Explicit version of next line.
+ {"%[3]*.[2]*[1]f", SE{12.0, 2, 6}, " 12.00"},
+ {"%[1]*.[2]*[3]f", SE{6, 2, 12.0}, " 12.00"},
+ {"%10f", SE{12.0}, " 12.000000"},
+ {"%[1]*[3]f", SE{10, 99, 12.0}, " 12.000000"},
+ {"%.6f", SE{12.0}, "12.000000"}, // Explicit version of next line.
+ {"%.[1]*[3]f", SE{6, 99, 12.0}, "12.000000"},
+ {"%6.f", SE{12.0}, " 12"}, // // Explicit version of next line; empty precision means zero.
+ {"%[1]*.[3]f", SE{6, 3, 12.0}, " 12"},
+ // An actual use! Print the same arguments twice.
+ {"%d %d %d %#[1]o %#o %#o", SE{11, 12, 13}, "11 12 13 013 014 015"},
+
+ // Erroneous cases.
+ {"%[d", SE{2, 1}, "%!d(BADINDEX)"},
+ {"%]d", SE{2, 1}, "%!](int=2)d%!(EXTRA int=1)"},
+ {"%[]d", SE{2, 1}, "%!d(BADINDEX)"},
+ {"%[-3]d", SE{2, 1}, "%!d(BADINDEX)"},
+ {"%[99]d", SE{2, 1}, "%!d(BADINDEX)"},
+ {"%[3]", SE{2, 1}, "%!(NOVERB)"},
+ {"%[1].2d", SE{5, 6}, "%!d(BADINDEX)"},
+ {"%[1]2d", SE{2, 1}, "%!d(BADINDEX)"},
+ {"%3.[2]d", SE{7}, "%!d(BADINDEX)"},
+ {"%.[2]d", SE{7}, "%!d(BADINDEX)"},
+ {"%d %d %d %#[1]o %#o %#o %#o", SE{11, 12, 13}, "11 12 13 013 014 015 %!o(MISSING)"},
+ {"%[5]d %[2]d %d", SE{1, 2, 3}, "%!d(BADINDEX) 2 3"},
+ {"%d %[3]d %d", SE{1, 2}, "1 %!d(BADINDEX) 2"}, // Erroneous index does not affect sequence.
+}
+
+func TestReorder(t *testing.T) {
+ for _, tt := range reorderTests {
+ s := Sprintf(tt.fmt, tt.val...)
+ if s != tt.out {
+ t.Errorf("Sprintf(%q, %v) = <%s> want <%s>", tt.fmt, tt.val, s, tt.out)
+ } else {
+ }
+ }
+}
+
func BenchmarkSprintfEmpty(b *testing.B) {
for i := 0; i < b.N; i++ {
Sprintf("")
@@ -607,6 +671,9 @@ var mallocTest = []struct {
var _ bytes.Buffer
func TestCountMallocs(t *testing.T) {
+ if testing.Short() {
+ t.Skip("skipping malloc count in short mode")
+ }
if runtime.GOMAXPROCS(0) > 1 {
t.Skip("skipping; GOMAXPROCS>1")
}
@@ -832,16 +899,16 @@ var panictests = []struct {
}{
// String
{"%s", (*Panic)(nil), "<nil>"}, // nil pointer special case
- {"%s", Panic{io.ErrUnexpectedEOF}, "%s(PANIC=unexpected EOF)"},
- {"%s", Panic{3}, "%s(PANIC=3)"},
+ {"%s", Panic{io.ErrUnexpectedEOF}, "%!s(PANIC=unexpected EOF)"},
+ {"%s", Panic{3}, "%!s(PANIC=3)"},
// GoString
{"%#v", (*Panic)(nil), "<nil>"}, // nil pointer special case
- {"%#v", Panic{io.ErrUnexpectedEOF}, "%v(PANIC=unexpected EOF)"},
- {"%#v", Panic{3}, "%v(PANIC=3)"},
+ {"%#v", Panic{io.ErrUnexpectedEOF}, "%!v(PANIC=unexpected EOF)"},
+ {"%#v", Panic{3}, "%!v(PANIC=3)"},
// Format
{"%s", (*PanicF)(nil), "<nil>"}, // nil pointer special case
- {"%s", PanicF{io.ErrUnexpectedEOF}, "%s(PANIC=unexpected EOF)"},
- {"%s", PanicF{3}, "%s(PANIC=3)"},
+ {"%s", PanicF{io.ErrUnexpectedEOF}, "%!s(PANIC=unexpected EOF)"},
+ {"%s", PanicF{3}, "%!s(PANIC=3)"},
}
func TestPanics(t *testing.T) {
@@ -861,7 +928,7 @@ type Recur struct {
failed *bool
}
-func (r Recur) String() string {
+func (r *Recur) String() string {
if recurCount++; recurCount > 10 {
*r.failed = true
return "FAIL"
@@ -874,13 +941,13 @@ func (r Recur) String() string {
func TestBadVerbRecursion(t *testing.T) {
failed := false
- r := Recur{3, &failed}
+ r := &Recur{3, &failed}
Sprintf("recur@%p value: %d\n", &r, r.i)
if failed {
t.Error("fail with pointer")
}
failed = false
- r = Recur{4, &failed}
+ r = &Recur{4, &failed}
Sprintf("recur@%p, value: %d\n", r, r.i)
if failed {
t.Error("fail with value")
diff --git a/libgo/go/fmt/format.go b/libgo/go/fmt/format.go
index 5665db12c5d..2e2b0716edc 100644
--- a/libgo/go/fmt/format.go
+++ b/libgo/go/fmt/format.go
@@ -24,8 +24,6 @@ const (
var padZeroBytes = make([]byte, nByte)
var padSpaceBytes = make([]byte, nByte)
-var newline = []byte{'\n'}
-
func init() {
for i := 0; i < nByte; i++ {
padZeroBytes[i] = '0'
@@ -162,6 +160,11 @@ func (f *fmt) integer(a int64, base uint64, signedness bool, digits string) {
}
var buf []byte = f.intbuf[0:]
+ if f.widPresent && f.wid > nByte {
+ // We're going to need a bigger boat.
+ buf = make([]byte, f.wid)
+ }
+
negative := signedness == signed && a < 0
if negative {
a = -a
@@ -184,7 +187,7 @@ func (f *fmt) integer(a int64, base uint64, signedness bool, digits string) {
// a is made into unsigned ua. we could make things
// marginally faster by splitting the 32-bit case out into a separate
// block but it's not worth the duplication, so ua has 64 bits.
- i := len(f.intbuf)
+ i := len(buf)
ua := uint64(a)
for ua >= base {
i--
@@ -193,7 +196,7 @@ func (f *fmt) integer(a int64, base uint64, signedness bool, digits string) {
}
i--
buf[i] = digits[ua]
- for i > 0 && prec > nByte-i {
+ for i > 0 && prec > len(buf)-i {
i--
buf[i] = '0'
}
@@ -356,6 +359,14 @@ func (f *fmt) formatFloat(v float64, verb byte, prec, n int) {
// The formatted number starts at slice[1].
switch slice[1] {
case '-', '+':
+ // If we're zero padding, want the sign before the leading zeros.
+ // Achieve this by writing the sign out and padding the postive number.
+ if f.zero && f.widPresent && f.wid > len(slice) {
+ f.buf.WriteByte(slice[1])
+ f.wid--
+ f.pad(slice[2:])
+ return
+ }
// We're set; drop the leading space.
slice = slice[1:]
default:
@@ -418,6 +429,8 @@ func (f *fmt) fmt_c64(v complex64, verb rune) {
oldPlus := f.plus
for i := 0; ; i++ {
switch verb {
+ case 'b':
+ f.fmt_fb32(r)
case 'e':
f.fmt_e32(r)
case 'E':
@@ -446,6 +459,8 @@ func (f *fmt) fmt_c128(v complex128, verb rune) {
oldPlus := f.plus
for i := 0; ; i++ {
switch verb {
+ case 'b':
+ f.fmt_fb64(r)
case 'e':
f.fmt_e64(r)
case 'E':
diff --git a/libgo/go/fmt/print.go b/libgo/go/fmt/print.go
index 5f37fd12085..1ea816d6d5f 100644
--- a/libgo/go/fmt/print.go
+++ b/libgo/go/fmt/print.go
@@ -16,19 +16,21 @@ import (
// Some constants in the form of bytes, to avoid string overhead.
// Needlessly fastidious, I suppose.
var (
- commaSpaceBytes = []byte(", ")
- nilAngleBytes = []byte("<nil>")
- nilParenBytes = []byte("(nil)")
- nilBytes = []byte("nil")
- mapBytes = []byte("map[")
- missingBytes = []byte("(MISSING)")
- panicBytes = []byte("(PANIC=")
- extraBytes = []byte("%!(EXTRA ")
- irparenBytes = []byte("i)")
- bytesBytes = []byte("[]byte{")
- badWidthBytes = []byte("%!(BADWIDTH)")
- badPrecBytes = []byte("%!(BADPREC)")
- noVerbBytes = []byte("%!(NOVERB)")
+ commaSpaceBytes = []byte(", ")
+ nilAngleBytes = []byte("<nil>")
+ nilParenBytes = []byte("(nil)")
+ nilBytes = []byte("nil")
+ mapBytes = []byte("map[")
+ percentBangBytes = []byte("%!")
+ missingBytes = []byte("(MISSING)")
+ badIndexBytes = []byte("(BADINDEX)")
+ panicBytes = []byte("(PANIC=")
+ extraBytes = []byte("%!(EXTRA ")
+ irparenBytes = []byte("i)")
+ bytesBytes = []byte("[]byte{")
+ badWidthBytes = []byte("%!(BADWIDTH)")
+ badPrecBytes = []byte("%!(BADPREC)")
+ noVerbBytes = []byte("%!(NOVERB)")
)
// State represents the printer state passed to custom formatters.
@@ -42,7 +44,7 @@ type State interface {
// Precision returns the value of the precision option and whether it has been set.
Precision() (prec int, ok bool)
- // Flag returns whether the flag c, a character, has been set.
+ // Flag reports whether the flag c, a character, has been set.
Flag(c int) bool
}
@@ -109,13 +111,17 @@ type pp struct {
panicking bool
erroring bool // printing an error condition
buf buffer
- // field holds the current item, as an interface{}.
- field interface{}
+ // arg holds the current item, as an interface{}.
+ arg interface{}
// value holds the current item, as a reflect.Value, and will be
// the zero Value if the item has not been reflected.
- value reflect.Value
- runeBuf [utf8.UTFMax]byte
- fmt fmt
+ value reflect.Value
+ // reordered records whether the format string used argument reordering.
+ reordered bool
+ // goodArgNum records whether the most recent reordering directive was valid.
+ goodArgNum bool
+ runeBuf [utf8.UTFMax]byte
+ fmt fmt
}
// A cache holds a set of reusable objects.
@@ -170,7 +176,7 @@ func (p *pp) free() {
return
}
p.buf = p.buf[:0]
- p.field = nil
+ p.arg = nil
p.value = reflect.Value{}
ppFree.put(p)
}
@@ -212,9 +218,9 @@ func (p *pp) Write(b []byte) (ret int, err error) {
func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) {
p := newPrinter()
p.doPrintf(format, a)
- n64, err := w.Write(p.buf)
+ n, err = w.Write(p.buf)
p.free()
- return int(n64), err
+ return
}
// Printf formats according to a format specifier and writes to standard output.
@@ -246,9 +252,9 @@ func Errorf(format string, a ...interface{}) error {
func Fprint(w io.Writer, a ...interface{}) (n int, err error) {
p := newPrinter()
p.doPrint(a, false, false)
- n64, err := w.Write(p.buf)
+ n, err = w.Write(p.buf)
p.free()
- return int(n64), err
+ return
}
// Print formats using the default formats for its operands and writes to standard output.
@@ -278,9 +284,9 @@ func Sprint(a ...interface{}) string {
func Fprintln(w io.Writer, a ...interface{}) (n int, err error) {
p := newPrinter()
p.doPrint(a, true, true)
- n64, err := w.Write(p.buf)
+ n, err = w.Write(p.buf)
p.free()
- return int(n64), err
+ return
}
// Println formats using the default formats for its operands and writes to standard output.
@@ -300,8 +306,8 @@ func Sprintln(a ...interface{}) string {
return s
}
-// getField gets the i'th arg of the struct value.
-// If the arg itself is an interface, return a value for
+// getField gets the i'th field of the struct value.
+// If the field is itself is an interface, return a value for
// the thing inside the interface, not the interface itself.
func getField(v reflect.Value, i int) reflect.Value {
val := v.Field(i)
@@ -340,10 +346,10 @@ func (p *pp) badVerb(verb rune) {
p.add(verb)
p.add('(')
switch {
- case p.field != nil:
- p.buf.WriteString(reflect.TypeOf(p.field).String())
+ case p.arg != nil:
+ p.buf.WriteString(reflect.TypeOf(p.arg).String())
p.add('=')
- p.printField(p.field, 'v', false, false, 0)
+ p.printArg(p.arg, 'v', false, false, 0)
case p.value.IsValid():
p.buf.WriteString(p.value.Type().String())
p.add('=')
@@ -505,7 +511,7 @@ func (p *pp) fmtFloat64(v float64, verb rune) {
func (p *pp) fmtComplex64(v complex64, verb rune) {
switch verb {
- case 'e', 'E', 'f', 'F', 'g', 'G':
+ case 'b', 'e', 'E', 'f', 'F', 'g', 'G':
p.fmt.fmt_c64(v, verb)
case 'v':
p.fmt.fmt_c64(v, 'g')
@@ -516,7 +522,7 @@ func (p *pp) fmtComplex64(v complex64, verb rune) {
func (p *pp) fmtComplex128(v complex128, verb rune) {
switch verb {
- case 'e', 'E', 'f', 'F', 'g', 'G':
+ case 'b', 'e', 'E', 'f', 'F', 'g', 'G':
p.fmt.fmt_c128(v, verb)
case 'v':
p.fmt.fmt_c128(v, 'g')
@@ -566,7 +572,7 @@ func (p *pp) fmtBytes(v []byte, verb rune, goSyntax bool, typ reflect.Type, dept
p.buf.WriteByte(' ')
}
}
- p.printField(c, 'v', p.fmt.plus, goSyntax, depth+1)
+ p.printArg(c, 'v', p.fmt.plus, goSyntax, depth+1)
}
if goSyntax {
p.buf.WriteByte('}')
@@ -635,31 +641,29 @@ func (p *pp) fmtPointer(value reflect.Value, verb rune, goSyntax bool) {
var (
intBits = reflect.TypeOf(0).Bits()
- floatBits = reflect.TypeOf(0.0).Bits()
- complexBits = reflect.TypeOf(1i).Bits()
uintptrBits = reflect.TypeOf(uintptr(0)).Bits()
)
-func (p *pp) catchPanic(field interface{}, verb rune) {
+func (p *pp) catchPanic(arg interface{}, verb rune) {
if err := recover(); err != nil {
// If it's a nil pointer, just say "<nil>". The likeliest causes are a
// Stringer that fails to guard against nil or a nil pointer for a
// value receiver, and in either case, "<nil>" is a nice result.
- if v := reflect.ValueOf(field); v.Kind() == reflect.Ptr && v.IsNil() {
+ if v := reflect.ValueOf(arg); v.Kind() == reflect.Ptr && v.IsNil() {
p.buf.Write(nilAngleBytes)
return
}
// Otherwise print a concise panic message. Most of the time the panic
// value will print itself nicely.
if p.panicking {
- // Nested panics; the recursion in printField cannot succeed.
+ // Nested panics; the recursion in printArg cannot succeed.
panic(err)
}
- p.buf.WriteByte('%')
+ p.buf.Write(percentBangBytes)
p.add(verb)
p.buf.Write(panicBytes)
p.panicking = true
- p.printField(err, 'v', false, false, 0)
+ p.printArg(err, 'v', false, false, 0)
p.panicking = false
p.buf.WriteByte(')')
}
@@ -670,10 +674,10 @@ func (p *pp) handleMethods(verb rune, plus, goSyntax bool, depth int) (wasString
return
}
// Is it a Formatter?
- if formatter, ok := p.field.(Formatter); ok {
+ if formatter, ok := p.arg.(Formatter); ok {
handled = true
wasString = false
- defer p.catchPanic(p.field, verb)
+ defer p.catchPanic(p.arg, verb)
formatter.Format(p, verb)
return
}
@@ -682,13 +686,13 @@ func (p *pp) handleMethods(verb rune, plus, goSyntax bool, depth int) (wasString
p.fmt.plus = false
}
- // If we're doing Go syntax and the field knows how to supply it, take care of it now.
+ // If we're doing Go syntax and the argument knows how to supply it, take care of it now.
if goSyntax {
p.fmt.sharp = false
- if stringer, ok := p.field.(GoStringer); ok {
+ if stringer, ok := p.arg.(GoStringer); ok {
wasString = false
handled = true
- defer p.catchPanic(p.field, verb)
+ defer p.catchPanic(p.arg, verb)
// Print the result of GoString unadorned.
p.fmtString(stringer.GoString(), 's', false)
return
@@ -703,19 +707,19 @@ func (p *pp) handleMethods(verb rune, plus, goSyntax bool, depth int) (wasString
// The duplication in the bodies is necessary:
// setting wasString and handled, and deferring catchPanic,
// must happen before calling the method.
- switch v := p.field.(type) {
+ switch v := p.arg.(type) {
case error:
wasString = false
handled = true
- defer p.catchPanic(p.field, verb)
- p.printField(v.Error(), verb, plus, false, depth)
+ defer p.catchPanic(p.arg, verb)
+ p.printArg(v.Error(), verb, plus, false, depth)
return
case Stringer:
wasString = false
handled = true
- defer p.catchPanic(p.field, verb)
- p.printField(v.String(), verb, plus, false, depth)
+ defer p.catchPanic(p.arg, verb)
+ p.printArg(v.String(), verb, plus, false, depth)
return
}
}
@@ -724,11 +728,11 @@ func (p *pp) handleMethods(verb rune, plus, goSyntax bool, depth int) (wasString
return
}
-func (p *pp) printField(field interface{}, verb rune, plus, goSyntax bool, depth int) (wasString bool) {
- p.field = field
+func (p *pp) printArg(arg interface{}, verb rune, plus, goSyntax bool, depth int) (wasString bool) {
+ p.arg = arg
p.value = reflect.Value{}
- if field == nil {
+ if arg == nil {
if verb == 'T' || verb == 'v' {
p.fmt.pad(nilAngleBytes)
} else {
@@ -741,10 +745,10 @@ func (p *pp) printField(field interface{}, verb rune, plus, goSyntax bool, depth
// %T (the value's type) and %p (its address) are special; we always do them first.
switch verb {
case 'T':
- p.printField(reflect.TypeOf(field).String(), 's', false, false, 0)
+ p.printArg(reflect.TypeOf(arg).String(), 's', false, false, 0)
return false
case 'p':
- p.fmtPointer(reflect.ValueOf(field), verb, goSyntax)
+ p.fmtPointer(reflect.ValueOf(arg), verb, goSyntax)
return false
}
@@ -762,7 +766,7 @@ func (p *pp) printField(field interface{}, verb rune, plus, goSyntax bool, depth
}
// Some types can be done without reflection.
- switch f := field.(type) {
+ switch f := arg.(type) {
case bool:
p.fmtBool(f, verb)
case float32:
@@ -770,7 +774,7 @@ func (p *pp) printField(field interface{}, verb rune, plus, goSyntax bool, depth
case float64:
p.fmtFloat64(f, verb)
case complex64:
- p.fmtComplex64(complex64(f), verb)
+ p.fmtComplex64(f, verb)
case complex128:
p.fmtComplex128(f, verb)
case int:
@@ -806,17 +810,17 @@ func (p *pp) printField(field interface{}, verb rune, plus, goSyntax bool, depth
p.fmt.plus = oldPlus
p.fmt.sharp = oldSharp
// If the type is not simple, it might have methods.
- if wasString, handled := p.handleMethods(verb, plus, goSyntax, depth); handled {
- return wasString
+ if isString, handled := p.handleMethods(verb, plus, goSyntax, depth); handled {
+ return isString
}
// Need to use reflection
- return p.printReflectValue(reflect.ValueOf(field), verb, plus, goSyntax, depth)
+ return p.printReflectValue(reflect.ValueOf(arg), verb, plus, goSyntax, depth)
}
- p.field = nil
+ p.arg = nil
return
}
-// printValue is like printField but starts with a reflect value, not an interface{} value.
+// printValue is like printArg but starts with a reflect value, not an interface{} value.
func (p *pp) printValue(value reflect.Value, verb rune, plus, goSyntax bool, depth int) (wasString bool) {
if !value.IsValid() {
if verb == 'T' || verb == 'v' {
@@ -831,7 +835,7 @@ func (p *pp) printValue(value reflect.Value, verb rune, plus, goSyntax bool, dep
// %T (the value's type) and %p (its address) are special; we always do them first.
switch verb {
case 'T':
- p.printField(value.Type().String(), 's', false, false, 0)
+ p.printArg(value.Type().String(), 's', false, false, 0)
return false
case 'p':
p.fmtPointer(value, verb, goSyntax)
@@ -839,19 +843,19 @@ func (p *pp) printValue(value reflect.Value, verb rune, plus, goSyntax bool, dep
}
// Handle values with special methods.
- // Call always, even when field == nil, because handleMethods clears p.fmt.plus for us.
- p.field = nil // Make sure it's cleared, for safety.
+ // Call always, even when arg == nil, because handleMethods clears p.fmt.plus for us.
+ p.arg = nil // Make sure it's cleared, for safety.
if value.CanInterface() {
- p.field = value.Interface()
+ p.arg = value.Interface()
}
- if wasString, handled := p.handleMethods(verb, plus, goSyntax, depth); handled {
- return wasString
+ if isString, handled := p.handleMethods(verb, plus, goSyntax, depth); handled {
+ return isString
}
return p.printReflectValue(value, verb, plus, goSyntax, depth)
}
-// printReflectValue is the fallback for both printField and printValue.
+// printReflectValue is the fallback for both printArg and printValue.
// It uses reflect to print the value.
func (p *pp) printReflectValue(value reflect.Value, verb rune, plus, goSyntax bool, depth int) (wasString bool) {
oldValue := p.value
@@ -863,18 +867,18 @@ BigSwitch:
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
p.fmtInt64(f.Int(), verb)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
- p.fmtUint64(uint64(f.Uint()), verb, goSyntax)
+ p.fmtUint64(f.Uint(), verb, goSyntax)
case reflect.Float32, reflect.Float64:
if f.Type().Size() == 4 {
p.fmtFloat32(float32(f.Float()), verb)
} else {
- p.fmtFloat64(float64(f.Float()), verb)
+ p.fmtFloat64(f.Float(), verb)
}
case reflect.Complex64, reflect.Complex128:
if f.Type().Size() == 8 {
p.fmtComplex64(complex64(f.Complex()), verb)
} else {
- p.fmtComplex128(complex128(f.Complex()), verb)
+ p.fmtComplex128(f.Complex(), verb)
}
case reflect.String:
p.fmtString(f.String(), verb, goSyntax)
@@ -1015,20 +1019,59 @@ BigSwitch:
return wasString
}
-// intFromArg gets the fieldnumth element of a. On return, isInt reports whether the argument has type int.
-func intFromArg(a []interface{}, end, i, fieldnum int) (num int, isInt bool, newi, newfieldnum int) {
- newi, newfieldnum = end, fieldnum
- if i < end && fieldnum < len(a) {
- num, isInt = a[fieldnum].(int)
- newi, newfieldnum = i+1, fieldnum+1
+// intFromArg gets the argNumth element of a. On return, isInt reports whether the argument has type int.
+func intFromArg(a []interface{}, argNum int) (num int, isInt bool, newArgNum int) {
+ newArgNum = argNum
+ if argNum < len(a) {
+ num, isInt = a[argNum].(int)
+ newArgNum = argNum + 1
}
return
}
+// parseArgNumber returns the value of the bracketed number, minus 1
+// (explicit argument numbers are one-indexed but we want zero-indexed).
+// The opening bracket is known to be present at format[0].
+// The returned values are the index, the number of bytes to consume
+// up to the closing paren, if present, and whether the number parsed
+// ok. The bytes to consume will be 1 if no closing paren is present.
+func parseArgNumber(format string) (index int, wid int, ok bool) {
+ // Find closing bracket.
+ for i := 1; i < len(format); i++ {
+ if format[i] == ']' {
+ width, ok, newi := parsenum(format, 1, i)
+ if !ok || newi != i {
+ return 0, i + 1, false
+ }
+ return width - 1, i + 1, true // arg numbers are one-indexed and skip paren.
+ }
+ }
+ return 0, 1, false
+}
+
+// argNumber returns the next argument to evaluate, which is either the value of the passed-in
+// argNum or the value of the bracketed integer that begins format[i:]. It also returns
+// the new value of i, that is, the index of the next byte of the format to process.
+func (p *pp) argNumber(argNum int, format string, i int, numArgs int) (newArgNum, newi int, found bool) {
+ if len(format) <= i || format[i] != '[' {
+ return argNum, i, false
+ }
+ p.reordered = true
+ index, wid, ok := parseArgNumber(format[i:])
+ if ok && 0 <= index && index < numArgs {
+ return index, i + wid, true
+ }
+ p.goodArgNum = false
+ return argNum, i + wid, true
+}
+
func (p *pp) doPrintf(format string, a []interface{}) {
end := len(format)
- fieldnum := 0 // we process one field per non-trivial format
+ argNum := 0 // we process one argument per non-trivial format
+ afterIndex := false // previous item in format was an index like [3].
+ p.reordered = false
for i := 0; i < end; {
+ p.goodArgNum = true
lasti := i
for i < end && format[i] != '%' {
i++
@@ -1043,7 +1086,8 @@ func (p *pp) doPrintf(format string, a []interface{}) {
// Process one verb
i++
- // flags and widths
+
+ // Do we have flags?
p.fmt.clearflags()
F:
for ; i < end; i++ {
@@ -1062,30 +1106,52 @@ func (p *pp) doPrintf(format string, a []interface{}) {
break F
}
}
- // do we have width?
+
+ // Do we have an explicit argument index?
+ argNum, i, afterIndex = p.argNumber(argNum, format, i, len(a))
+
+ // Do we have width?
if i < end && format[i] == '*' {
- p.fmt.wid, p.fmt.widPresent, i, fieldnum = intFromArg(a, end, i, fieldnum)
+ i++
+ p.fmt.wid, p.fmt.widPresent, argNum = intFromArg(a, argNum)
if !p.fmt.widPresent {
p.buf.Write(badWidthBytes)
}
+ afterIndex = false
} else {
p.fmt.wid, p.fmt.widPresent, i = parsenum(format, i, end)
+ if afterIndex && p.fmt.widPresent { // "%[3]2d"
+ p.goodArgNum = false
+ }
}
- // do we have precision?
+
+ // Do we have precision?
if i+1 < end && format[i] == '.' {
- if format[i+1] == '*' {
- p.fmt.prec, p.fmt.precPresent, i, fieldnum = intFromArg(a, end, i+1, fieldnum)
+ i++
+ if afterIndex { // "%[3].2d"
+ p.goodArgNum = false
+ }
+ argNum, i, afterIndex = p.argNumber(argNum, format, i, len(a))
+ if format[i] == '*' {
+ i++
+ p.fmt.prec, p.fmt.precPresent, argNum = intFromArg(a, argNum)
if !p.fmt.precPresent {
p.buf.Write(badPrecBytes)
}
+ afterIndex = false
} else {
- p.fmt.prec, p.fmt.precPresent, i = parsenum(format, i+1, end)
+ p.fmt.prec, p.fmt.precPresent, i = parsenum(format, i, end)
if !p.fmt.precPresent {
p.fmt.prec = 0
p.fmt.precPresent = true
}
}
}
+
+ if !afterIndex {
+ argNum, i, afterIndex = p.argNumber(argNum, format, i, len(a))
+ }
+
if i >= end {
p.buf.Write(noVerbBytes)
continue
@@ -1097,30 +1163,38 @@ func (p *pp) doPrintf(format string, a []interface{}) {
p.buf.WriteByte('%') // We ignore width and prec.
continue
}
- if fieldnum >= len(a) { // out of operands
- p.buf.WriteByte('%')
+ if !p.goodArgNum {
+ p.buf.Write(percentBangBytes)
+ p.add(c)
+ p.buf.Write(badIndexBytes)
+ continue
+ } else if argNum >= len(a) { // out of operands
+ p.buf.Write(percentBangBytes)
p.add(c)
p.buf.Write(missingBytes)
continue
}
- field := a[fieldnum]
- fieldnum++
+ arg := a[argNum]
+ argNum++
goSyntax := c == 'v' && p.fmt.sharp
plus := c == 'v' && p.fmt.plus
- p.printField(field, c, plus, goSyntax, 0)
+ p.printArg(arg, c, plus, goSyntax, 0)
}
- if fieldnum < len(a) {
+ // Check for extra arguments unless the call accessed the arguments
+ // out of order, in which case it's too expensive to detect if they've all
+ // been used and arguably OK if they're not.
+ if !p.reordered && argNum < len(a) {
p.buf.Write(extraBytes)
- for ; fieldnum < len(a); fieldnum++ {
- field := a[fieldnum]
- if field != nil {
- p.buf.WriteString(reflect.TypeOf(field).String())
+ for ; argNum < len(a); argNum++ {
+ arg := a[argNum]
+ if arg != nil {
+ p.buf.WriteString(reflect.TypeOf(arg).String())
p.buf.WriteByte('=')
}
- p.printField(field, 'v', false, false, 0)
- if fieldnum+1 < len(a) {
+ p.printArg(arg, 'v', false, false, 0)
+ if argNum+1 < len(a) {
p.buf.Write(commaSpaceBytes)
}
}
@@ -1130,17 +1204,17 @@ func (p *pp) doPrintf(format string, a []interface{}) {
func (p *pp) doPrint(a []interface{}, addspace, addnewline bool) {
prevString := false
- for fieldnum := 0; fieldnum < len(a); fieldnum++ {
+ for argNum := 0; argNum < len(a); argNum++ {
p.fmt.clearflags()
// always add spaces if we're doing Println
- field := a[fieldnum]
- if fieldnum > 0 {
- isString := field != nil && reflect.TypeOf(field).Kind() == reflect.String
+ arg := a[argNum]
+ if argNum > 0 {
+ isString := arg != nil && reflect.TypeOf(arg).Kind() == reflect.String
if addspace || !isString && !prevString {
p.buf.WriteByte(' ')
}
}
- prevString = p.printField(field, 'v', false, false, 0)
+ prevString = p.printArg(arg, 'v', false, false, 0)
}
if addnewline {
p.buf.WriteByte('\n')
diff --git a/libgo/go/fmt/scan.go b/libgo/go/fmt/scan.go
index bf888c4d88c..5b1be5891b8 100644
--- a/libgo/go/fmt/scan.go
+++ b/libgo/go/fmt/scan.go
@@ -168,12 +168,12 @@ type ss struct {
// ssave holds the parts of ss that need to be
// saved and restored on recursive scans.
type ssave struct {
- validSave bool // is or was a part of an actual ss.
- nlIsEnd bool // whether newline terminates scan
- nlIsSpace bool // whether newline counts as white space
- fieldLimit int // max value of ss.count for this field; fieldLimit <= limit
- limit int // max value of ss.count.
- maxWid int // width of this field.
+ validSave bool // is or was a part of an actual ss.
+ nlIsEnd bool // whether newline terminates scan
+ nlIsSpace bool // whether newline counts as white space
+ argLimit int // max value of ss.count for this arg; argLimit <= limit
+ limit int // max value of ss.count.
+ maxWid int // width of this arg.
}
// The Read method is only in ScanState so that ScanState
@@ -192,7 +192,7 @@ func (s *ss) ReadRune() (r rune, size int, err error) {
s.peekRune = -1
return
}
- if s.atEOF || s.nlIsEnd && s.prevRune == '\n' || s.count >= s.fieldLimit {
+ if s.atEOF || s.nlIsEnd && s.prevRune == '\n' || s.count >= s.argLimit {
err = io.EOF
return
}
@@ -389,7 +389,7 @@ func newScanState(r io.Reader, nlIsSpace, nlIsEnd bool) (s *ss, old ssave) {
s, ok := r.(*ss)
if ok {
old = s.ssave
- s.limit = s.fieldLimit
+ s.limit = s.argLimit
s.nlIsEnd = nlIsEnd || s.nlIsEnd
s.nlIsSpace = nlIsSpace
return
@@ -407,7 +407,7 @@ func newScanState(r io.Reader, nlIsSpace, nlIsEnd bool) (s *ss, old ssave) {
s.peekRune = -1
s.atEOF = false
s.limit = hugeWid
- s.fieldLimit = hugeWid
+ s.argLimit = hugeWid
s.maxWid = hugeWid
s.validSave = true
s.count = 0
@@ -437,6 +437,9 @@ func (s *ss) skipSpace(stopAtNewline bool) {
if r == eof {
return
}
+ if r == '\r' && s.peek("\n") {
+ continue
+ }
if r == '\n' {
if stopAtNewline {
break
@@ -476,11 +479,6 @@ func (s *ss) token(skipSpace bool, f func(rune) bool) []byte {
return s.buf
}
-// typeError indicates that the type of the operand did not match the format
-func (s *ss) typeError(field interface{}, expected string) {
- s.errorString("expected field of type pointer to " + expected + "; found " + reflect.TypeOf(field).String())
-}
-
var complexError = errors.New("syntax error scanning complex number")
var boolError = errors.New("syntax error scanning boolean")
@@ -781,7 +779,7 @@ func (s *ss) convertFloat(str string, n int) float64 {
}
s.error(err)
}
- n, err := strconv.Atoi(str[p+1:])
+ m, err := strconv.Atoi(str[p+1:])
if err != nil {
// Put full string into error.
if e, ok := err.(*strconv.NumError); ok {
@@ -789,7 +787,7 @@ func (s *ss) convertFloat(str string, n int) float64 {
}
s.error(err)
}
- return math.Ldexp(f, n)
+ return math.Ldexp(f, m)
}
f, err := strconv.ParseFloat(str, n)
if err != nil {
@@ -858,8 +856,7 @@ func (s *ss) quotedString() string {
// In a legal backslash escape, no matter how long, only the character
// immediately after the escape can itself be a backslash or quote.
// Thus we only need to protect the first character after the backslash.
- r := s.mustReadRune()
- s.buf.WriteRune(r)
+ s.buf.WriteRune(s.mustReadRune())
} else if r == '"' {
break
}
@@ -886,7 +883,7 @@ func (s *ss) hexDigit(d rune) int {
case 'A', 'B', 'C', 'D', 'E', 'F':
return 10 + digit - 'A'
}
- s.errorString("Scan: illegal hex digit")
+ s.errorString("illegal hex digit")
return 0
}
@@ -916,7 +913,7 @@ func (s *ss) hexString() string {
s.buf.WriteByte(b)
}
if len(s.buf) == 0 {
- s.errorString("Scan: no hex data for %x string")
+ s.errorString("no hex data for %x string")
return ""
}
return string(s.buf)
@@ -927,11 +924,11 @@ const floatVerbs = "beEfFgGv"
const hugeWid = 1 << 30
// scanOne scans a single value, deriving the scanner from the type of the argument.
-func (s *ss) scanOne(verb rune, field interface{}) {
+func (s *ss) scanOne(verb rune, arg interface{}) {
s.buf = s.buf[:0]
var err error
// If the parameter has its own Scan method, use that.
- if v, ok := field.(Scanner); ok {
+ if v, ok := arg.(Scanner); ok {
err = v.Scan(s, verb)
if err != nil {
if err == io.EOF {
@@ -942,7 +939,7 @@ func (s *ss) scanOne(verb rune, field interface{}) {
return
}
- switch v := field.(type) {
+ switch v := arg.(type) {
case *bool:
*v = s.scanBool(verb)
case *complex64:
@@ -995,7 +992,7 @@ func (s *ss) scanOne(verb rune, field interface{}) {
val := reflect.ValueOf(v)
ptr := val
if ptr.Kind() != reflect.Ptr {
- s.errorString("Scan: type not a pointer: " + val.Type().String())
+ s.errorString("type not a pointer: " + val.Type().String())
return
}
switch v := ptr.Elem(); v.Kind() {
@@ -1011,7 +1008,7 @@ func (s *ss) scanOne(verb rune, field interface{}) {
// For now, can only handle (renamed) []byte.
typ := v.Type()
if typ.Elem().Kind() != reflect.Uint8 {
- s.errorString("Scan: can't handle type: " + val.Type().String())
+ s.errorString("can't scan type: " + val.Type().String())
}
str := s.convertString(verb)
v.Set(reflect.MakeSlice(typ, len(str), len(str)))
@@ -1025,7 +1022,7 @@ func (s *ss) scanOne(verb rune, field interface{}) {
case reflect.Complex64, reflect.Complex128:
v.SetComplex(s.scanComplex(verb, v.Type().Bits()))
default:
- s.errorString("Scan: can't handle type: " + val.Type().String())
+ s.errorString("can't scan type: " + val.Type().String())
}
}
}
@@ -1046,8 +1043,8 @@ func errorHandler(errp *error) {
// doScan does the real work for scanning without a format string.
func (s *ss) doScan(a []interface{}) (numProcessed int, err error) {
defer errorHandler(&err)
- for _, field := range a {
- s.scanOne('v', field)
+ for _, arg := range a {
+ s.scanOne('v', arg)
numProcessed++
}
// Check for newline if required.
@@ -1058,7 +1055,7 @@ func (s *ss) doScan(a []interface{}) (numProcessed int, err error) {
break
}
if !isSpace(r) {
- s.errorString("Scan: expected newline")
+ s.errorString("expected newline")
break
}
}
@@ -1144,9 +1141,9 @@ func (s *ss) doScanf(format string, a []interface{}) (numProcessed int, err erro
if !widPresent {
s.maxWid = hugeWid
}
- s.fieldLimit = s.limit
- if f := s.count + s.maxWid; f < s.fieldLimit {
- s.fieldLimit = f
+ s.argLimit = s.limit
+ if f := s.count + s.maxWid; f < s.argLimit {
+ s.argLimit = f
}
c, w := utf8.DecodeRuneInString(format[i:])
@@ -1156,11 +1153,11 @@ func (s *ss) doScanf(format string, a []interface{}) (numProcessed int, err erro
s.errorString("too few operands for format %" + format[i-w:])
break
}
- field := a[numProcessed]
+ arg := a[numProcessed]
- s.scanOne(c, field)
+ s.scanOne(c, arg)
numProcessed++
- s.fieldLimit = s.limit
+ s.argLimit = s.limit
}
if numProcessed < len(a) {
s.errorString("too many operands")
diff --git a/libgo/go/fmt/scan_test.go b/libgo/go/fmt/scan_test.go
index 4e2c0feb2cb..d903f0c3ff7 100644
--- a/libgo/go/fmt/scan_test.go
+++ b/libgo/go/fmt/scan_test.go
@@ -54,7 +54,6 @@ var (
float32Val float32
float64Val float64
stringVal string
- stringVal1 string
bytesVal []byte
runeVal rune
complex64Val complex64
@@ -192,6 +191,10 @@ var scanTests = []ScanTest{
{"-.45e1-1e2i\n", &complex128Val, complex128(-.45e1 - 100i)},
{"hello\n", &stringVal, "hello"},
+ // Carriage-return followed by newline. (We treat \r\n as \n always.)
+ {"hello\r\n", &stringVal, "hello"},
+ {"27\r\n", &uint8Val, uint8(27)},
+
// Renamed types
{"true\n", &renamedBoolVal, renamedBool(true)},
{"F\n", &renamedBoolVal, renamedBool(false)},
diff --git a/libgo/go/go/ast/ast.go b/libgo/go/go/ast/ast.go
index bf533d1d24f..6e635cd0166 100644
--- a/libgo/go/go/ast/ast.go
+++ b/libgo/go/go/ast/ast.go
@@ -297,6 +297,8 @@ type (
Lbrack token.Pos // position of "["
Low Expr // begin of slice range; or nil
High Expr // end of slice range; or nil
+ Max Expr // maximum capacity of slice; or nil
+ Slice3 bool // true if 3-index slice (2 colons present)
Rbrack token.Pos // position of "]"
}
@@ -304,8 +306,10 @@ type (
// type assertion.
//
TypeAssertExpr struct {
- X Expr // expression
- Type Expr // asserted type; nil means type switch X.(type)
+ X Expr // expression
+ Lparen token.Pos // position of "("
+ Type Expr // asserted type; nil means type switch X.(type)
+ Rparen token.Pos // position of ")"
}
// A CallExpr node represents an expression followed by an argument list.
@@ -385,8 +389,8 @@ type (
// A FuncType node represents a function type.
FuncType struct {
- Func token.Pos // position of "func" keyword
- Params *FieldList // (incoming) parameters; or nil
+ Func token.Pos // position of "func" keyword (token.NoPos if there is no "func")
+ Params *FieldList // (incoming) parameters; non-nil
Results *FieldList // (outgoing) results; or nil
}
@@ -407,7 +411,7 @@ type (
// A ChanType node represents a channel type.
ChanType struct {
Begin token.Pos // position of "chan" keyword or "<-" (whichever comes first)
- Arrow token.Pos // position of "<-" (noPos if there is no "<-")
+ Arrow token.Pos // position of "<-" (token.NoPos if there is no "<-")
Dir ChanDir // channel direction
Value Expr // value type
}
@@ -438,10 +442,15 @@ func (x *BinaryExpr) Pos() token.Pos { return x.X.Pos() }
func (x *KeyValueExpr) Pos() token.Pos { return x.Key.Pos() }
func (x *ArrayType) Pos() token.Pos { return x.Lbrack }
func (x *StructType) Pos() token.Pos { return x.Struct }
-func (x *FuncType) Pos() token.Pos { return x.Func }
-func (x *InterfaceType) Pos() token.Pos { return x.Interface }
-func (x *MapType) Pos() token.Pos { return x.Map }
-func (x *ChanType) Pos() token.Pos { return x.Begin }
+func (x *FuncType) Pos() token.Pos {
+ if x.Func.IsValid() || x.Params == nil { // see issue 3870
+ return x.Func
+ }
+ return x.Params.Pos() // interface method declarations have no "func" keyword
+}
+func (x *InterfaceType) Pos() token.Pos { return x.Interface }
+func (x *MapType) Pos() token.Pos { return x.Map }
+func (x *ChanType) Pos() token.Pos { return x.Begin }
func (x *BadExpr) End() token.Pos { return x.To }
func (x *Ident) End() token.Pos { return token.Pos(int(x.NamePos) + len(x.Name)) }
@@ -451,26 +460,21 @@ func (x *Ellipsis) End() token.Pos {
}
return x.Ellipsis + 3 // len("...")
}
-func (x *BasicLit) End() token.Pos { return token.Pos(int(x.ValuePos) + len(x.Value)) }
-func (x *FuncLit) End() token.Pos { return x.Body.End() }
-func (x *CompositeLit) End() token.Pos { return x.Rbrace + 1 }
-func (x *ParenExpr) End() token.Pos { return x.Rparen + 1 }
-func (x *SelectorExpr) End() token.Pos { return x.Sel.End() }
-func (x *IndexExpr) End() token.Pos { return x.Rbrack + 1 }
-func (x *SliceExpr) End() token.Pos { return x.Rbrack + 1 }
-func (x *TypeAssertExpr) End() token.Pos {
- if x.Type != nil {
- return x.Type.End()
- }
- return x.X.End()
-}
-func (x *CallExpr) End() token.Pos { return x.Rparen + 1 }
-func (x *StarExpr) End() token.Pos { return x.X.End() }
-func (x *UnaryExpr) End() token.Pos { return x.X.End() }
-func (x *BinaryExpr) End() token.Pos { return x.Y.End() }
-func (x *KeyValueExpr) End() token.Pos { return x.Value.End() }
-func (x *ArrayType) End() token.Pos { return x.Elt.End() }
-func (x *StructType) End() token.Pos { return x.Fields.End() }
+func (x *BasicLit) End() token.Pos { return token.Pos(int(x.ValuePos) + len(x.Value)) }
+func (x *FuncLit) End() token.Pos { return x.Body.End() }
+func (x *CompositeLit) End() token.Pos { return x.Rbrace + 1 }
+func (x *ParenExpr) End() token.Pos { return x.Rparen + 1 }
+func (x *SelectorExpr) End() token.Pos { return x.Sel.End() }
+func (x *IndexExpr) End() token.Pos { return x.Rbrack + 1 }
+func (x *SliceExpr) End() token.Pos { return x.Rbrack + 1 }
+func (x *TypeAssertExpr) End() token.Pos { return x.Rparen + 1 }
+func (x *CallExpr) End() token.Pos { return x.Rparen + 1 }
+func (x *StarExpr) End() token.Pos { return x.X.End() }
+func (x *UnaryExpr) End() token.Pos { return x.X.End() }
+func (x *BinaryExpr) End() token.Pos { return x.Y.End() }
+func (x *KeyValueExpr) End() token.Pos { return x.Value.End() }
+func (x *ArrayType) End() token.Pos { return x.Elt.End() }
+func (x *StructType) End() token.Pos { return x.Fields.End() }
func (x *FuncType) End() token.Pos {
if x.Results != nil {
return x.Results.End()
@@ -511,23 +515,21 @@ func (*ChanType) exprNode() {}
// ----------------------------------------------------------------------------
// Convenience functions for Idents
-var noPos token.Pos
-
// NewIdent creates a new Ident without position.
// Useful for ASTs generated by code other than the Go parser.
//
-func NewIdent(name string) *Ident { return &Ident{noPos, name, nil} }
+func NewIdent(name string) *Ident { return &Ident{token.NoPos, name, nil} }
-// IsExported returns whether name is an exported Go symbol
-// (i.e., whether it begins with an uppercase letter).
+// IsExported reports whether name is an exported Go symbol
+// (that is, whether it begins with an upper-case letter).
//
func IsExported(name string) bool {
ch, _ := utf8.DecodeRuneInString(name)
return unicode.IsUpper(ch)
}
-// IsExported returns whether id is an exported Go symbol
-// (i.e., whether it begins with an uppercase letter).
+// IsExported reports whether id is an exported Go symbol
+// (that is, whether it begins with an uppercase letter).
//
func (id *Ident) IsExported() bool { return IsExported(id.Name) }
@@ -919,7 +921,7 @@ type (
Doc *CommentGroup // associated documentation; or nil
Recv *FieldList // receiver (methods); or nil (functions)
Name *Ident // function/method name
- Type *FuncType // position of Func keyword, parameters and results
+ Type *FuncType // function signature: parameters, results, and position of "func" keyword
Body *BlockStmt // function body; or nil (forward declaration)
}
)
diff --git a/libgo/go/go/ast/commentmap.go b/libgo/go/go/ast/commentmap.go
index 252d460af9a..1fb4867dd28 100644
--- a/libgo/go/go/ast/commentmap.go
+++ b/libgo/go/go/ast/commentmap.go
@@ -129,11 +129,11 @@ func (s *nodeStack) pop(pos token.Pos) (top Node) {
//
// A comment group g is associated with a node n if:
//
-// - g starts on the same line as n ends
-// - g starts on the line immediately following n, and there is
-// at least one empty line after g and before the next node
-// - g starts before n and is not associated to the node before n
-// via the previous rules
+// - g starts on the same line as n ends
+// - g starts on the line immediately following n, and there is
+// at least one empty line after g and before the next node
+// - g starts before n and is not associated to the node before n
+// via the previous rules
//
// NewCommentMap tries to associate a comment group to the "largest"
// node possible: For instance, if the comment is a line comment
diff --git a/libgo/go/go/ast/filter.go b/libgo/go/go/ast/filter.go
index 71c9ed7766b..fc3eeb4a1db 100644
--- a/libgo/go/go/ast/filter.go
+++ b/libgo/go/go/ast/filter.go
@@ -308,7 +308,7 @@ func nameOf(f *FuncDecl) string {
// separator is an empty //-style comment that is interspersed between
// different comment groups when they are concatenated into a single group
//
-var separator = &Comment{noPos, "//"}
+var separator = &Comment{token.NoPos, "//"}
// MergePackageFiles creates a file AST by merging the ASTs of the
// files belonging to a package. The mode flags control merging behavior.
diff --git a/libgo/go/go/ast/import.go b/libgo/go/go/ast/import.go
index a68a4840f8e..d2770d16cf8 100644
--- a/libgo/go/go/ast/import.go
+++ b/libgo/go/go/ast/import.go
@@ -11,6 +11,7 @@ import (
)
// SortImports sorts runs of consecutive import lines in import blocks in f.
+// It also removes duplicate imports when it is possible to do so without data loss.
func SortImports(fset *token.FileSet, f *File) {
for _, d := range f.Decls {
d, ok := d.(*GenDecl)
@@ -27,14 +28,25 @@ func SortImports(fset *token.FileSet, f *File) {
// Identify and sort runs of specs on successive lines.
i := 0
+ specs := d.Specs[:0]
for j, s := range d.Specs {
if j > i && fset.Position(s.Pos()).Line > 1+fset.Position(d.Specs[j-1].End()).Line {
// j begins a new run. End this one.
- sortSpecs(fset, f, d.Specs[i:j])
+ specs = append(specs, sortSpecs(fset, f, d.Specs[i:j])...)
i = j
}
}
- sortSpecs(fset, f, d.Specs[i:])
+ specs = append(specs, sortSpecs(fset, f, d.Specs[i:])...)
+ d.Specs = specs
+
+ // Deduping can leave a blank line before the rparen; clean that up.
+ if len(d.Specs) > 0 {
+ lastSpec := d.Specs[len(d.Specs)-1]
+ lastLine := fset.Position(lastSpec.Pos()).Line
+ if rParenLine := fset.Position(d.Rparen).Line; rParenLine > lastLine+1 {
+ fset.File(d.Rparen).MergeLine(rParenLine - 1)
+ }
+ }
}
}
@@ -46,22 +58,41 @@ func importPath(s Spec) string {
return ""
}
+func importName(s Spec) string {
+ n := s.(*ImportSpec).Name
+ if n == nil {
+ return ""
+ }
+ return n.Name
+}
+
+func importComment(s Spec) string {
+ c := s.(*ImportSpec).Comment
+ if c == nil {
+ return ""
+ }
+ return c.Text()
+}
+
+// collapse indicates whether prev may be removed, leaving only next.
+func collapse(prev, next Spec) bool {
+ if importPath(next) != importPath(prev) || importName(next) != importName(prev) {
+ return false
+ }
+ return prev.(*ImportSpec).Comment == nil
+}
+
type posSpan struct {
Start token.Pos
End token.Pos
}
-func sortSpecs(fset *token.FileSet, f *File, specs []Spec) {
- // Avoid work if already sorted (also catches < 2 entries).
- sorted := true
- for i, s := range specs {
- if i > 0 && importPath(specs[i-1]) > importPath(s) {
- sorted = false
- break
- }
- }
- if sorted {
- return
+func sortSpecs(fset *token.FileSet, f *File, specs []Spec) []Spec {
+ // Can't short-circuit here even if specs are already sorted,
+ // since they might yet need deduplication.
+ // A lone import, however, may be safely ignored.
+ if len(specs) <= 1 {
+ return specs
}
// Record positions for specs.
@@ -101,10 +132,26 @@ func sortSpecs(fset *token.FileSet, f *File, specs []Spec) {
}
// Sort the import specs by import path.
+ // Remove duplicates, when possible without data loss.
// Reassign the import paths to have the same position sequence.
// Reassign each comment to abut the end of its spec.
// Sort the comments by new position.
- sort.Sort(byImportPath(specs))
+ sort.Sort(byImportSpec(specs))
+
+ // Dedup. Thanks to our sorting, we can just consider
+ // adjacent pairs of imports.
+ deduped := specs[:0]
+ for i, s := range specs {
+ if i == len(specs)-1 || !collapse(s, specs[i+1]) {
+ deduped = append(deduped, s)
+ } else {
+ p := s.Pos()
+ fset.File(p).MergeLine(fset.Position(p).Line)
+ }
+ }
+ specs = deduped
+
+ // Fix up comment positions
for i, s := range specs {
s := s.(*ImportSpec)
if s.Name != nil {
@@ -118,14 +165,29 @@ func sortSpecs(fset *token.FileSet, f *File, specs []Spec) {
}
}
}
+
sort.Sort(byCommentPos(comments))
+
+ return specs
}
-type byImportPath []Spec // slice of *ImportSpec
+type byImportSpec []Spec // slice of *ImportSpec
-func (x byImportPath) Len() int { return len(x) }
-func (x byImportPath) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
-func (x byImportPath) Less(i, j int) bool { return importPath(x[i]) < importPath(x[j]) }
+func (x byImportSpec) Len() int { return len(x) }
+func (x byImportSpec) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
+func (x byImportSpec) Less(i, j int) bool {
+ ipath := importPath(x[i])
+ jpath := importPath(x[j])
+ if ipath != jpath {
+ return ipath < jpath
+ }
+ iname := importName(x[i])
+ jname := importName(x[j])
+ if iname != jname {
+ return iname < jname
+ }
+ return importComment(x[i]) < importComment(x[j])
+}
type byCommentPos []*CommentGroup
diff --git a/libgo/go/go/ast/walk.go b/libgo/go/go/ast/walk.go
index fef2503c37e..fedffb3f22f 100644
--- a/libgo/go/go/ast/walk.go
+++ b/libgo/go/go/ast/walk.go
@@ -122,6 +122,9 @@ func Walk(v Visitor, node Node) {
if n.High != nil {
Walk(v, n.High)
}
+ if n.Max != nil {
+ Walk(v, n.Max)
+ }
case *TypeAssertExpr:
Walk(v, n.X)
diff --git a/libgo/go/go/build/build.go b/libgo/go/go/build/build.go
index cc89afb218d..50d2fb4aeba 100644
--- a/libgo/go/go/build/build.go
+++ b/libgo/go/go/build/build.go
@@ -258,21 +258,23 @@ func (ctxt *Context) SrcDirs() []string {
var Default Context = defaultContext()
var cgoEnabled = map[string]bool{
- "darwin/386": true,
- "darwin/amd64": true,
- "freebsd/386": true,
- "freebsd/amd64": true,
- "freebsd/arm": true,
- "linux/386": true,
- "linux/amd64": true,
- "linux/arm": true,
- "netbsd/386": true,
- "netbsd/amd64": true,
- "netbsd/arm": true,
- "openbsd/386": true,
- "openbsd/amd64": true,
- "windows/386": true,
- "windows/amd64": true,
+ "darwin/386": true,
+ "darwin/amd64": true,
+ "dragonfly/386": true,
+ "dragonfly/amd64": true,
+ "freebsd/386": true,
+ "freebsd/amd64": true,
+ "freebsd/arm": true,
+ "linux/386": true,
+ "linux/amd64": true,
+ "linux/arm": true,
+ "netbsd/386": true,
+ "netbsd/amd64": true,
+ "netbsd/arm": true,
+ "openbsd/386": true,
+ "openbsd/amd64": true,
+ "windows/386": true,
+ "windows/amd64": true,
}
func defaultContext() Context {
@@ -293,7 +295,7 @@ func defaultContext() Context {
// When we reach Go 1.3 the line will read
// c.ReleaseTags = []string{"go1.1", "go1.2", "go1.3"}
// and so on.
- c.ReleaseTags = []string{"go1.1"}
+ c.ReleaseTags = []string{"go1.1", "go1.2"}
switch os.Getenv("CGO_ENABLED") {
case "1":
@@ -337,32 +339,37 @@ const (
// A Package describes the Go package found in a directory.
type Package struct {
- Dir string // directory containing package sources
- Name string // package name
- Doc string // documentation synopsis
- ImportPath string // import path of package ("" if unknown)
- Root string // root of Go tree where this package lives
- SrcRoot string // package source root directory ("" if unknown)
- PkgRoot string // package install root directory ("" if unknown)
- BinDir string // command install directory ("" if unknown)
- Goroot bool // package found in Go root
- PkgObj string // installed .a file
+ Dir string // directory containing package sources
+ Name string // package name
+ Doc string // documentation synopsis
+ ImportPath string // import path of package ("" if unknown)
+ Root string // root of Go tree where this package lives
+ SrcRoot string // package source root directory ("" if unknown)
+ PkgRoot string // package install root directory ("" if unknown)
+ BinDir string // command install directory ("" if unknown)
+ Goroot bool // package found in Go root
+ PkgObj string // installed .a file
+ AllTags []string // tags that can influence file selection in this directory
+ ConflictDir string // this directory shadows Dir in $GOPATH
// Source files
GoFiles []string // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles)
CgoFiles []string // .go source files that import "C"
IgnoredGoFiles []string // .go source files ignored for this build
CFiles []string // .c source files
- HFiles []string // .h source files
+ CXXFiles []string // .cc, .cpp and .cxx source files
+ HFiles []string // .h, .hh, .hpp and .hxx source files
SFiles []string // .s source files
- SysoFiles []string // .syso system object files to add to archive
SwigFiles []string // .swig files
SwigCXXFiles []string // .swigcxx files
+ SysoFiles []string // .syso system object files to add to archive
// Cgo directives
- CgoPkgConfig []string // Cgo pkg-config directives
CgoCFLAGS []string // Cgo CFLAGS directives
+ CgoCPPFLAGS []string // Cgo CPPFLAGS directives
+ CgoCXXFLAGS []string // Cgo CXXFLAGS directives
CgoLDFLAGS []string // Cgo LDFLAGS directives
+ CgoPkgConfig []string // Cgo pkg-config directives
// Dependency information
Imports []string // imports from GoFiles, CgoFiles
@@ -391,13 +398,22 @@ func (ctxt *Context) ImportDir(dir string, mode ImportMode) (*Package, error) {
}
// NoGoError is the error used by Import to describe a directory
-// containing no Go source files.
+// containing no buildable Go source files. (It may still contain
+// test files, files hidden by build tags, and so on.)
type NoGoError struct {
Dir string
}
func (e *NoGoError) Error() string {
- return "no Go source files in " + e.Dir
+ return "no buildable Go source files in " + e.Dir
+}
+
+func nameExt(name string) string {
+ i := strings.LastIndex(name, ".")
+ if i < 0 {
+ return ""
+ }
+ return name[i:]
}
// Import returns details about the Go package named by the import path,
@@ -429,7 +445,7 @@ func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Packa
switch ctxt.Compiler {
case "gccgo":
dir, elem := pathpkg.Split(p.ImportPath)
- pkga = "pkg/gccgo/" + dir + "lib" + elem + ".a"
+ pkga = "pkg/gccgo_" + ctxt.GOOS + "_" + ctxt.GOARCH + "/" + dir + "lib" + elem + ".a"
case "gc":
suffix := ""
if ctxt.InstallSuffix != "" {
@@ -469,11 +485,13 @@ func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Packa
// else first.
if ctxt.GOROOT != "" {
if dir := ctxt.joinPath(ctxt.GOROOT, "src", "pkg", sub); ctxt.isDir(dir) {
+ p.ConflictDir = dir
goto Found
}
}
for _, earlyRoot := range all[:i] {
if dir := ctxt.joinPath(earlyRoot, "src", sub); ctxt.isDir(dir) {
+ p.ConflictDir = dir
goto Found
}
}
@@ -575,63 +593,21 @@ Found:
imported := make(map[string][]token.Position)
testImported := make(map[string][]token.Position)
xTestImported := make(map[string][]token.Position)
+ allTags := make(map[string]bool)
fset := token.NewFileSet()
for _, d := range dirs {
if d.IsDir() {
continue
}
- name := d.Name()
- if strings.HasPrefix(name, "_") ||
- strings.HasPrefix(name, ".") {
- continue
- }
-
- i := strings.LastIndex(name, ".")
- if i < 0 {
- i = len(name)
- }
- ext := name[i:]
-
- if !ctxt.UseAllFiles && !ctxt.goodOSArchFile(name) {
- if ext == ".go" {
- p.IgnoredGoFiles = append(p.IgnoredGoFiles, name)
- }
- continue
- }
- switch ext {
- case ".go", ".c", ".s", ".h", ".S", ".swig", ".swigcxx":
- // tentatively okay - read to make sure
- case ".syso":
- // binary objects to add to package archive
- // Likely of the form foo_windows.syso, but
- // the name was vetted above with goodOSArchFile.
- p.SysoFiles = append(p.SysoFiles, name)
- continue
- default:
- // skip
- continue
- }
+ name := d.Name()
+ ext := nameExt(name)
- filename := ctxt.joinPath(p.Dir, name)
- f, err := ctxt.openFile(filename)
+ match, data, filename, err := ctxt.matchFile(p.Dir, name, true, allTags)
if err != nil {
return p, err
}
-
- var data []byte
- if strings.HasSuffix(filename, ".go") {
- data, err = readImports(f, false)
- } else {
- data, err = readComments(f)
- }
- f.Close()
- if err != nil {
- return p, fmt.Errorf("read %s: %v", filename, err)
- }
-
- // Look for +build comments to accept or reject the file.
- if !ctxt.UseAllFiles && !ctxt.shouldBuild(data) {
+ if !match {
if ext == ".go" {
p.IgnoredGoFiles = append(p.IgnoredGoFiles, name)
}
@@ -643,7 +619,10 @@ Found:
case ".c":
p.CFiles = append(p.CFiles, name)
continue
- case ".h":
+ case ".cc", ".cpp", ".cxx":
+ p.CXXFiles = append(p.CXXFiles, name)
+ continue
+ case ".h", ".hh", ".hpp", ".hxx":
p.HFiles = append(p.HFiles, name)
continue
case ".s":
@@ -658,6 +637,12 @@ Found:
case ".swigcxx":
p.SwigCXXFiles = append(p.SwigCXXFiles, name)
continue
+ case ".syso":
+ // binary objects to add to package archive
+ // Likely of the form foo_windows.syso, but
+ // the name was vetted above with goodOSArchFile.
+ p.SysoFiles = append(p.SysoFiles, name)
+ continue
}
pf, err := parser.ParseFile(fset, filename, data, parser.ImportsOnly|parser.ParseComments)
@@ -730,8 +715,11 @@ Found:
}
}
if isCgo {
+ allTags["cgo"] = true
if ctxt.CgoEnabled {
p.CgoFiles = append(p.CgoFiles, name)
+ } else {
+ p.IgnoredGoFiles = append(p.IgnoredGoFiles, name)
}
} else if isXTest {
p.XTestGoFiles = append(p.XTestGoFiles, name)
@@ -741,10 +729,15 @@ Found:
p.GoFiles = append(p.GoFiles, name)
}
}
- if p.Name == "" {
+ if len(p.GoFiles)+len(p.CgoFiles)+len(p.TestGoFiles)+len(p.XTestGoFiles) == 0 {
return p, &NoGoError{p.Dir}
}
+ for tag := range allTags {
+ p.AllTags = append(p.AllTags, tag)
+ }
+ sort.Strings(p.AllTags)
+
p.Imports, p.ImportPos = cleanImports(imported)
p.TestImports, p.TestImportPos = cleanImports(testImported)
p.XTestImports, p.XTestImportPos = cleanImports(xTestImported)
@@ -760,6 +753,79 @@ Found:
return p, pkgerr
}
+// MatchFile reports whether the file with the given name in the given directory
+// matches the context and would be included in a Package created by ImportDir
+// of that directory.
+//
+// MatchFile considers the name of the file and may use ctxt.OpenFile to
+// read some or all of the file's content.
+func (ctxt *Context) MatchFile(dir, name string) (match bool, err error) {
+ match, _, _, err = ctxt.matchFile(dir, name, false, nil)
+ return
+}
+
+// matchFile determines whether the file with the given name in the given directory
+// should be included in the package being constructed.
+// It returns the data read from the file.
+// If returnImports is true and name denotes a Go program, matchFile reads
+// until the end of the imports (and returns that data) even though it only
+// considers text until the first non-comment.
+// If allTags is non-nil, matchFile records any encountered build tag
+// by setting allTags[tag] = true.
+func (ctxt *Context) matchFile(dir, name string, returnImports bool, allTags map[string]bool) (match bool, data []byte, filename string, err error) {
+ if strings.HasPrefix(name, "_") ||
+ strings.HasPrefix(name, ".") {
+ return
+ }
+
+ i := strings.LastIndex(name, ".")
+ if i < 0 {
+ i = len(name)
+ }
+ ext := name[i:]
+
+ if !ctxt.goodOSArchFile(name, allTags) && !ctxt.UseAllFiles {
+ return
+ }
+
+ switch ext {
+ case ".go", ".c", ".cc", ".cxx", ".cpp", ".s", ".h", ".hh", ".hpp", ".hxx", ".S", ".swig", ".swigcxx":
+ // tentatively okay - read to make sure
+ case ".syso":
+ // binary, no reading
+ match = true
+ return
+ default:
+ // skip
+ return
+ }
+
+ filename = ctxt.joinPath(dir, name)
+ f, err := ctxt.openFile(filename)
+ if err != nil {
+ return
+ }
+
+ if strings.HasSuffix(filename, ".go") {
+ data, err = readImports(f, false)
+ } else {
+ data, err = readComments(f)
+ }
+ f.Close()
+ if err != nil {
+ err = fmt.Errorf("read %s: %v", filename, err)
+ return
+ }
+
+ // Look for +build comments to accept or reject the file.
+ if !ctxt.shouldBuild(data, allTags) && !ctxt.UseAllFiles {
+ return
+ }
+
+ match = true
+ return
+}
+
func cleanImports(m map[string][]token.Position) ([]string, map[string][]token.Position) {
all := make([]string, 0, len(m))
for path := range m {
@@ -794,7 +860,7 @@ var slashslash = []byte("//")
//
// marks the file as applicable only on Windows and Linux.
//
-func (ctxt *Context) shouldBuild(content []byte) bool {
+func (ctxt *Context) shouldBuild(content []byte, allTags map[string]bool) bool {
// Pass 1. Identify leading run of // comments and blank lines,
// which must be followed by a blank line.
end := 0
@@ -819,6 +885,7 @@ func (ctxt *Context) shouldBuild(content []byte) bool {
// Pass 2. Process each line in the run.
p = content
+ allok := true
for len(p) > 0 {
line := p
if i := bytes.IndexByte(line, '\n'); i >= 0 {
@@ -835,24 +902,24 @@ func (ctxt *Context) shouldBuild(content []byte) bool {
if f[0] == "+build" {
ok := false
for _, tok := range f[1:] {
- if ctxt.match(tok) {
+ if ctxt.match(tok, allTags) {
ok = true
- break
}
}
if !ok {
- return false // this one doesn't match
+ allok = false
}
}
}
}
}
- return true // everything matches
+
+ return allok
}
// saveCgo saves the information from the #cgo lines in the import "C" comment.
-// These lines set CFLAGS and LDFLAGS and pkg-config directives that affect
-// the way cgo's C code is built.
+// These lines set CFLAGS, CPPFLAGS, CXXFLAGS and LDFLAGS and pkg-config directives
+// that affect the way cgo's C code is built.
//
// TODO(rsc): This duplicates code in cgo.
// Once the dust settles, remove this code from cgo.
@@ -887,7 +954,7 @@ func (ctxt *Context) saveCgo(filename string, di *Package, cg *ast.CommentGroup)
if len(cond) > 0 {
ok := false
for _, c := range cond {
- if ctxt.match(c) {
+ if ctxt.match(c, nil) {
ok = true
break
}
@@ -902,7 +969,7 @@ func (ctxt *Context) saveCgo(filename string, di *Package, cg *ast.CommentGroup)
return fmt.Errorf("%s: invalid #cgo line: %s", filename, orig)
}
for _, arg := range args {
- if !safeName(arg) {
+ if !safeCgoName(arg) {
return fmt.Errorf("%s: malformed #cgo argument: %s", filename, arg)
}
}
@@ -910,6 +977,10 @@ func (ctxt *Context) saveCgo(filename string, di *Package, cg *ast.CommentGroup)
switch verb {
case "CFLAGS":
di.CgoCFLAGS = append(di.CgoCFLAGS, args...)
+ case "CPPFLAGS":
+ di.CgoCPPFLAGS = append(di.CgoCPPFLAGS, args...)
+ case "CXXFLAGS":
+ di.CgoCXXFLAGS = append(di.CgoCXXFLAGS, args...)
case "LDFLAGS":
di.CgoLDFLAGS = append(di.CgoLDFLAGS, args...)
case "pkg-config":
@@ -921,9 +992,12 @@ func (ctxt *Context) saveCgo(filename string, di *Package, cg *ast.CommentGroup)
return nil
}
-var safeBytes = []byte("+-.,/0123456789=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz:")
+// NOTE: $ is not safe for the shell, but it is allowed here because of linker options like -Wl,$ORIGIN.
+// We never pass these arguments to a shell (just to programs we construct argv for), so this should be okay.
+// See golang.org/issue/6038.
+var safeBytes = []byte("+-.,/0123456789=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz:$")
-func safeName(s string) bool {
+func safeCgoName(s string) bool {
if s == "" {
return false
}
@@ -1008,19 +1082,28 @@ func splitQuoted(s string) (r []string, err error) {
// !tag (if tag is not listed in ctxt.BuildTags or ctxt.ReleaseTags)
// a comma-separated list of any of these
//
-func (ctxt *Context) match(name string) bool {
+func (ctxt *Context) match(name string, allTags map[string]bool) bool {
if name == "" {
+ if allTags != nil {
+ allTags[name] = true
+ }
return false
}
if i := strings.Index(name, ","); i >= 0 {
// comma-separated list
- return ctxt.match(name[:i]) && ctxt.match(name[i+1:])
+ ok1 := ctxt.match(name[:i], allTags)
+ ok2 := ctxt.match(name[i+1:], allTags)
+ return ok1 && ok2
}
if strings.HasPrefix(name, "!!") { // bad syntax, reject always
return false
}
if strings.HasPrefix(name, "!") { // negation
- return len(name) > 1 && !ctxt.match(name[1:])
+ return len(name) > 1 && !ctxt.match(name[1:], allTags)
+ }
+
+ if allTags != nil {
+ allTags[name] = true
}
// Tags must be letters, digits, underscores or dots.
@@ -1065,7 +1148,7 @@ func (ctxt *Context) match(name string) bool {
// name_$(GOARCH)_test.*
// name_$(GOOS)_$(GOARCH)_test.*
//
-func (ctxt *Context) goodOSArchFile(name string) bool {
+func (ctxt *Context) goodOSArchFile(name string, allTags map[string]bool) bool {
if dot := strings.Index(name, "."); dot != -1 {
name = name[:dot]
}
@@ -1075,12 +1158,22 @@ func (ctxt *Context) goodOSArchFile(name string) bool {
}
n := len(l)
if n >= 2 && knownOS[l[n-2]] && knownArch[l[n-1]] {
+ if allTags != nil {
+ allTags[l[n-2]] = true
+ allTags[l[n-1]] = true
+ }
return l[n-2] == ctxt.GOOS && l[n-1] == ctxt.GOARCH
}
if n >= 1 && knownOS[l[n-1]] {
+ if allTags != nil {
+ allTags[l[n-1]] = true
+ }
return l[n-1] == ctxt.GOOS
}
if n >= 1 && knownArch[l[n-1]] {
+ if allTags != nil {
+ allTags[l[n-1]] = true
+ }
return l[n-1] == ctxt.GOARCH
}
return true
diff --git a/libgo/go/go/build/build_test.go b/libgo/go/go/build/build_test.go
index d8cf98840d7..fca8d4bdb27 100644
--- a/libgo/go/go/build/build_test.go
+++ b/libgo/go/go/build/build_test.go
@@ -5,38 +5,49 @@
package build
import (
+ "io"
"os"
"path/filepath"
+ "reflect"
"runtime"
+ "strings"
"testing"
)
func TestMatch(t *testing.T) {
ctxt := Default
what := "default"
- match := func(tag string) {
- if !ctxt.match(tag) {
+ match := func(tag string, want map[string]bool) {
+ m := make(map[string]bool)
+ if !ctxt.match(tag, m) {
t.Errorf("%s context should match %s, does not", what, tag)
}
+ if !reflect.DeepEqual(m, want) {
+ t.Errorf("%s tags = %v, want %v", tag, m, want)
+ }
}
- nomatch := func(tag string) {
- if ctxt.match(tag) {
+ nomatch := func(tag string, want map[string]bool) {
+ m := make(map[string]bool)
+ if ctxt.match(tag, m) {
t.Errorf("%s context should NOT match %s, does", what, tag)
}
+ if !reflect.DeepEqual(m, want) {
+ t.Errorf("%s tags = %v, want %v", tag, m, want)
+ }
}
- match(runtime.GOOS + "," + runtime.GOARCH)
- match(runtime.GOOS + "," + runtime.GOARCH + ",!foo")
- nomatch(runtime.GOOS + "," + runtime.GOARCH + ",foo")
+ match(runtime.GOOS+","+runtime.GOARCH, map[string]bool{runtime.GOOS: true, runtime.GOARCH: true})
+ match(runtime.GOOS+","+runtime.GOARCH+",!foo", map[string]bool{runtime.GOOS: true, runtime.GOARCH: true, "foo": true})
+ nomatch(runtime.GOOS+","+runtime.GOARCH+",foo", map[string]bool{runtime.GOOS: true, runtime.GOARCH: true, "foo": true})
what = "modified"
ctxt.BuildTags = []string{"foo"}
- match(runtime.GOOS + "," + runtime.GOARCH)
- match(runtime.GOOS + "," + runtime.GOARCH + ",foo")
- nomatch(runtime.GOOS + "," + runtime.GOARCH + ",!foo")
- match(runtime.GOOS + "," + runtime.GOARCH + ",!bar")
- nomatch(runtime.GOOS + "," + runtime.GOARCH + ",bar")
- nomatch("!")
+ match(runtime.GOOS+","+runtime.GOARCH, map[string]bool{runtime.GOOS: true, runtime.GOARCH: true})
+ match(runtime.GOOS+","+runtime.GOARCH+",foo", map[string]bool{runtime.GOOS: true, runtime.GOARCH: true, "foo": true})
+ nomatch(runtime.GOOS+","+runtime.GOARCH+",!foo", map[string]bool{runtime.GOOS: true, runtime.GOARCH: true, "foo": true})
+ match(runtime.GOOS+","+runtime.GOARCH+",!bar", map[string]bool{runtime.GOOS: true, runtime.GOARCH: true, "bar": true})
+ nomatch(runtime.GOOS+","+runtime.GOARCH+",bar", map[string]bool{runtime.GOOS: true, runtime.GOARCH: true, "bar": true})
+ nomatch("!", map[string]bool{})
}
func TestDotSlashImport(t *testing.T) {
@@ -92,28 +103,84 @@ func TestLocalDirectory(t *testing.T) {
func TestShouldBuild(t *testing.T) {
const file1 = "// +build tag1\n\n" +
"package main\n"
+ want1 := map[string]bool{"tag1": true}
const file2 = "// +build cgo\n\n" +
"// This package implements parsing of tags like\n" +
"// +build tag1\n" +
"package build"
+ want2 := map[string]bool{"cgo": true}
const file3 = "// Copyright The Go Authors.\n\n" +
"package build\n\n" +
"// shouldBuild checks tags given by lines of the form\n" +
"// +build tag\n" +
"func shouldBuild(content []byte)\n"
+ want3 := map[string]bool{}
ctx := &Context{BuildTags: []string{"tag1"}}
- if !ctx.shouldBuild([]byte(file1)) {
- t.Errorf("should not build file1, expected the contrary")
+ m := map[string]bool{}
+ if !ctx.shouldBuild([]byte(file1), m) {
+ t.Errorf("shouldBuild(file1) = false, want true")
+ }
+ if !reflect.DeepEqual(m, want1) {
+ t.Errorf("shoudBuild(file1) tags = %v, want %v", m, want1)
+ }
+
+ m = map[string]bool{}
+ if ctx.shouldBuild([]byte(file2), m) {
+ t.Errorf("shouldBuild(file2) = true, want fakse")
}
- if ctx.shouldBuild([]byte(file2)) {
- t.Errorf("should build file2, expected the contrary")
+ if !reflect.DeepEqual(m, want2) {
+ t.Errorf("shoudBuild(file2) tags = %v, want %v", m, want2)
}
+ m = map[string]bool{}
ctx = &Context{BuildTags: nil}
- if !ctx.shouldBuild([]byte(file3)) {
- t.Errorf("should not build file3, expected the contrary")
+ if !ctx.shouldBuild([]byte(file3), m) {
+ t.Errorf("shouldBuild(file3) = false, want true")
+ }
+ if !reflect.DeepEqual(m, want3) {
+ t.Errorf("shoudBuild(file3) tags = %v, want %v", m, want3)
+ }
+}
+
+type readNopCloser struct {
+ io.Reader
+}
+
+func (r readNopCloser) Close() error {
+ return nil
+}
+
+var matchFileTests = []struct {
+ name string
+ data string
+ match bool
+}{
+ {"foo_arm.go", "", true},
+ {"foo1_arm.go", "// +build linux\n\npackage main\n", false},
+ {"foo_darwin.go", "", false},
+ {"foo.go", "", true},
+ {"foo1.go", "// +build linux\n\npackage main\n", false},
+ {"foo.badsuffix", "", false},
+}
+
+func TestMatchFile(t *testing.T) {
+ for _, tt := range matchFileTests {
+ ctxt := Context{GOARCH: "arm", GOOS: "plan9"}
+ ctxt.OpenFile = func(path string) (r io.ReadCloser, err error) {
+ if path != "x+"+tt.name {
+ t.Fatalf("OpenFile asked for %q, expected %q", path, "x+"+tt.name)
+ }
+ return &readNopCloser{strings.NewReader(tt.data)}, nil
+ }
+ ctxt.JoinPath = func(elem ...string) string {
+ return strings.Join(elem, "+")
+ }
+ match, err := ctxt.MatchFile("x", tt.name)
+ if match != tt.match || err != nil {
+ t.Fatalf("MatchFile(%q) = %v, %v, want %v, nil", tt.name, match, err, tt.match)
+ }
}
}
diff --git a/libgo/go/go/build/deps_test.go b/libgo/go/go/build/deps_test.go
index 71b1bcf060b..dd162c7db7f 100644
--- a/libgo/go/go/build/deps_test.go
+++ b/libgo/go/go/build/deps_test.go
@@ -82,24 +82,27 @@ var pkgDeps = map[string][]string{
// L3 adds reflection and some basic utility packages
// and interface definitions, but nothing that makes
// system calls.
- "crypto": {"L2", "hash"}, // interfaces
- "crypto/cipher": {"L2"}, // interfaces
- "encoding/base32": {"L2"},
- "encoding/base64": {"L2"},
- "encoding/binary": {"L2", "reflect"},
- "hash": {"L2"}, // interfaces
- "hash/adler32": {"L2", "hash"},
- "hash/crc32": {"L2", "hash"},
- "hash/crc64": {"L2", "hash"},
- "hash/fnv": {"L2", "hash"},
- "image": {"L2", "image/color"}, // interfaces
- "image/color": {"L2"}, // interfaces
- "reflect": {"L2"},
+ "crypto": {"L2", "hash"}, // interfaces
+ "crypto/cipher": {"L2", "crypto/subtle"}, // interfaces
+ "crypto/subtle": {},
+ "encoding/base32": {"L2"},
+ "encoding/base64": {"L2"},
+ "encoding/binary": {"L2", "reflect"},
+ "hash": {"L2"}, // interfaces
+ "hash/adler32": {"L2", "hash"},
+ "hash/crc32": {"L2", "hash"},
+ "hash/crc64": {"L2", "hash"},
+ "hash/fnv": {"L2", "hash"},
+ "image": {"L2", "image/color"}, // interfaces
+ "image/color": {"L2"}, // interfaces
+ "image/color/palette": {"L2", "image/color"},
+ "reflect": {"L2"},
"L3": {
"L2",
"crypto",
"crypto/cipher",
+ "crypto/subtle",
"encoding/base32",
"encoding/base64",
"encoding/binary",
@@ -110,6 +113,7 @@ var pkgDeps = map[string][]string{
"hash/fnv",
"image",
"image/color",
+ "image/color/palette",
"reflect",
},
@@ -183,26 +187,27 @@ var pkgDeps = map[string][]string{
"compress/gzip": {"L4", "compress/flate"},
"compress/lzw": {"L4"},
"compress/zlib": {"L4", "compress/flate"},
- "database/sql": {"L4", "database/sql/driver"},
+ "database/sql": {"L4", "container/list", "database/sql/driver"},
"database/sql/driver": {"L4", "time"},
"debug/dwarf": {"L4"},
"debug/elf": {"L4", "OS", "debug/dwarf"},
"debug/gosym": {"L4"},
"debug/macho": {"L4", "OS", "debug/dwarf"},
"debug/pe": {"L4", "OS", "debug/dwarf"},
+ "encoding": {"L4"},
"encoding/ascii85": {"L4"},
"encoding/asn1": {"L4", "math/big"},
"encoding/csv": {"L4"},
- "encoding/gob": {"L4", "OS"},
+ "encoding/gob": {"L4", "OS", "encoding"},
"encoding/hex": {"L4"},
- "encoding/json": {"L4"},
+ "encoding/json": {"L4", "encoding"},
"encoding/pem": {"L4"},
- "encoding/xml": {"L4"},
+ "encoding/xml": {"L4", "encoding"},
"flag": {"L4", "OS"},
"go/build": {"L4", "OS", "GOPARSER"},
"html": {"L4"},
"image/draw": {"L4"},
- "image/gif": {"L4", "compress/lzw"},
+ "image/gif": {"L4", "compress/lzw", "image/color/palette", "image/draw"},
"image/jpeg": {"L4"},
"image/png": {"L4", "compress/zlib"},
"index/suffixarray": {"L4", "regexp"},
@@ -228,7 +233,8 @@ var pkgDeps = map[string][]string{
// that shows up in programs that use cgo.
"C": {},
- "os/user": {"L4", "CGO", "syscall"},
+ // Plan 9 alone needs io/ioutil and os.
+ "os/user": {"L4", "CGO", "io/ioutil", "os", "syscall"},
// Basic networking.
// Because net must be used by any package that wants to
@@ -248,15 +254,10 @@ var pkgDeps = map[string][]string{
"net/mail": {"L4", "NET", "OS"},
"net/textproto": {"L4", "OS", "net"},
- // Support libraries for crypto that aren't L2.
- "CRYPTO-SUPPORT": {
- "crypto/subtle",
- },
-
// Core crypto.
"crypto/aes": {"L3"},
"crypto/des": {"L3"},
- "crypto/hmac": {"L3", "CRYPTO-SUPPORT"},
+ "crypto/hmac": {"L3"},
"crypto/md5": {"L3"},
"crypto/rc4": {"L3"},
"crypto/sha1": {"L3"},
@@ -264,7 +265,6 @@ var pkgDeps = map[string][]string{
"crypto/sha512": {"L3"},
"CRYPTO": {
- "CRYPTO-SUPPORT",
"crypto/aes",
"crypto/des",
"crypto/hmac",
@@ -359,7 +359,7 @@ func allowed(pkg string) map[string]bool {
}
var bools = []bool{false, true}
-var geese = []string{"darwin", "freebsd", "linux", "netbsd", "openbsd", "plan9", "windows"}
+var geese = []string{"darwin", "dragonfly", "freebsd", "linux", "netbsd", "openbsd", "plan9", "windows"}
var goarches = []string{"386", "amd64", "arm"}
type osPkg struct {
@@ -392,6 +392,9 @@ func TestDependencies(t *testing.T) {
if allowedErrors[osPkg{ctxt.GOOS, pkg}] {
continue
}
+ if !ctxt.CgoEnabled && pkg == "runtime/cgo" {
+ continue
+ }
// Some of the combinations we try might not
// be reasonable (like arm,plan9,cgo), so ignore
// errors for the auto-generated combinations.
diff --git a/libgo/go/go/build/doc.go b/libgo/go/go/build/doc.go
index b5fc071d61a..b2f04ea45cf 100644
--- a/libgo/go/go/build/doc.go
+++ b/libgo/go/go/build/doc.go
@@ -94,6 +94,7 @@
// - the compiler being used, either "gc" or "gccgo"
// - "cgo", if ctxt.CgoEnabled is true
// - "go1.1", from Go version 1.1 onward
+// - "go1.2", from Go version 1.2 onward
// - any additional words listed in ctxt.BuildTags
//
// If a file's name, after stripping the extension and a possible _test suffix,
diff --git a/libgo/go/go/build/syslist_test.go b/libgo/go/go/build/syslist_test.go
index 9157faf8cb9..3be2928f525 100644
--- a/libgo/go/go/build/syslist_test.go
+++ b/libgo/go/go/build/syslist_test.go
@@ -55,7 +55,7 @@ var tests = []GoodFileTest{
func TestGoodOSArch(t *testing.T) {
for _, test := range tests {
- if Default.goodOSArchFile(test.name) != test.result {
+ if Default.goodOSArchFile(test.name, make(map[string]bool)) != test.result {
t.Fatalf("goodOSArchFile(%q) != %v", test.name, test.result)
}
}
diff --git a/libgo/go/go/doc/comment.go b/libgo/go/go/doc/comment.go
index c4b7e6ae6e1..5c8c43e0c1a 100644
--- a/libgo/go/go/doc/comment.go
+++ b/libgo/go/go/doc/comment.go
@@ -239,9 +239,14 @@ func anchorID(line string) string {
// nor to have trailing spaces at the end of lines.
// The comment markers have already been removed.
//
-// Turn each run of multiple \n into </p><p>.
-// Turn each run of indented lines into a <pre> block without indent.
-// Enclose headings with header tags.
+// Each span of unindented non-blank lines is converted into
+// a single paragraph. There is one exception to the rule: a span that
+// consists of a single line, is followed by another paragraph span,
+// begins with a capital letter, and contains no punctuation
+// is formatted as a heading.
+//
+// A span of indented lines is converted into a <pre> block,
+// with the common indent prefix removed.
//
// URLs in the comment text are converted into links; if the URL also appears
// in the words map, the link is taken from the map (if the corresponding map
diff --git a/libgo/go/go/doc/doc_test.go b/libgo/go/go/doc/doc_test.go
index 8043038b4ae..ad8ba5378f3 100644
--- a/libgo/go/go/doc/doc_test.go
+++ b/libgo/go/go/doc/doc_test.go
@@ -32,6 +32,7 @@ func readTemplate(filename string) *template.Template {
t.Funcs(template.FuncMap{
"node": nodeFmt,
"synopsis": synopsisFmt,
+ "indent": indentFmt,
})
return template.Must(t.ParseFiles(filepath.Join(dataDir, filename)))
}
@@ -55,6 +56,15 @@ func synopsisFmt(s string) string {
return "// " + strings.Replace(s, "\n", " ", -1)
}
+func indentFmt(indent, s string) string {
+ end := ""
+ if strings.HasSuffix(s, "\n") {
+ end = "\n"
+ s = s[:len(s)-1]
+ }
+ return indent + strings.Replace(s, "\n", "\n"+indent, -1) + end
+}
+
func isGoFile(fi os.FileInfo) bool {
name := fi.Name()
return !fi.IsDir() &&
diff --git a/libgo/go/go/doc/example.go b/libgo/go/go/doc/example.go
index 2761083c7ee..2358ed38902 100644
--- a/libgo/go/go/doc/example.go
+++ b/libgo/go/go/doc/example.go
@@ -265,7 +265,7 @@ func playExample(file *ast.File, body *ast.BlockStmt) *ast.File {
// Synthesize main function.
funcDecl := &ast.FuncDecl{
Name: ast.NewIdent("main"),
- Type: &ast.FuncType{},
+ Type: &ast.FuncType{Params: &ast.FieldList{}}, // FuncType.Params must be non-nil
Body: body,
}
diff --git a/libgo/go/go/doc/example_test.go b/libgo/go/go/doc/example_test.go
index e0477e3f693..e154ea8bfc5 100644
--- a/libgo/go/go/doc/example_test.go
+++ b/libgo/go/go/doc/example_test.go
@@ -159,8 +159,8 @@ func main() {
`
func TestExamples(t *testing.T) {
- fs := token.NewFileSet()
- file, err := parser.ParseFile(fs, "test.go", strings.NewReader(exampleTestFile), parser.ParseComments)
+ fset := token.NewFileSet()
+ file, err := parser.ParseFile(fset, "test.go", strings.NewReader(exampleTestFile), parser.ParseComments)
if err != nil {
t.Fatal(err)
}
@@ -174,11 +174,11 @@ func TestExamples(t *testing.T) {
if e.Play == nil {
g = "<nil>"
} else {
- b := new(bytes.Buffer)
- if err := format.Node(b, fs, e.Play); err != nil {
+ var buf bytes.Buffer
+ if err := format.Node(&buf, fset, e.Play); err != nil {
t.Fatal(err)
}
- g = b.String()
+ g = buf.String()
}
if g != w {
t.Errorf("%s: got Play == %q, want %q", c.Name, g, w)
diff --git a/libgo/go/go/doc/reader.go b/libgo/go/go/doc/reader.go
index 4fa6fd9d599..ed82c47cd99 100644
--- a/libgo/go/go/doc/reader.go
+++ b/libgo/go/go/doc/reader.go
@@ -414,7 +414,7 @@ func (r *reader) readNote(list []*ast.Comment) {
// We remove any formatting so that we don't
// get spurious line breaks/indentation when
// showing the TODO body.
- body := clean(text[m[1]:])
+ body := clean(text[m[1]:], keepNL)
if body != "" {
marker := text[m[2]:m[3]]
r.notes[marker] = append(r.notes[marker], &Note{
diff --git a/libgo/go/go/doc/synopsis.go b/libgo/go/go/doc/synopsis.go
index 2d18174393e..d1ad86c7416 100644
--- a/libgo/go/go/doc/synopsis.go
+++ b/libgo/go/go/doc/synopsis.go
@@ -27,14 +27,20 @@ func firstSentenceLen(s string) int {
return len(s)
}
+const (
+ keepNL = 1 << iota
+)
+
// clean replaces each sequence of space, \n, \r, or \t characters
// with a single space and removes any trailing and leading spaces.
-func clean(s string) string {
+// If the keepNL flag is set, newline characters are passed through
+// instead of being change to spaces.
+func clean(s string, flags int) string {
var b []byte
p := byte(' ')
for i := 0; i < len(s); i++ {
q := s[i]
- if q == '\n' || q == '\r' || q == '\t' {
+ if (flags&keepNL) == 0 && q == '\n' || q == '\r' || q == '\t' {
q = ' '
}
if q != ' ' || p != ' ' {
@@ -57,7 +63,7 @@ func clean(s string) string {
// is the empty string.
//
func Synopsis(s string) string {
- s = clean(s[0:firstSentenceLen(s)])
+ s = clean(s[0:firstSentenceLen(s)], 0)
for _, prefix := range IllegalPrefixes {
if strings.HasPrefix(strings.ToLower(s), prefix) {
return ""
diff --git a/libgo/go/go/doc/testdata/a.0.golden b/libgo/go/go/doc/testdata/a.0.golden
index cd98f4e0ebe..7e680b80b4c 100644
--- a/libgo/go/go/doc/testdata/a.0.golden
+++ b/libgo/go/go/doc/testdata/a.0.golden
@@ -9,24 +9,44 @@ FILENAMES
testdata/a1.go
BUGS .Bugs is now deprecated, please use .Notes instead
- // bug0
- // bug1
+ bug0
+
+ bug1
+
BUGS
- // bug0 (uid: uid)
- // bug1 (uid: uid)
+BUG(uid) bug0
+
+BUG(uid) bug1
+
NOTES
- // 1 of 4 - this is the first line of note 1 - note 1 continues on ... (uid: foo)
- // 2 of 4 (uid: foo)
- // 3 of 4 (uid: bar)
- // 4 of 4 - this is the last line of note 4 (uid: bar)
- // This note which contains a (parenthesized) subphrase must ... (uid: bam)
- // The ':' after the marker and uid is optional. (uid: xxx)
+NOTE(uid)
+
+NOTE(foo) 1 of 4 - this is the first line of note 1
+ - note 1 continues on this 2nd line
+ - note 1 continues on this 3rd line
+
+NOTE(foo) 2 of 4
+
+NOTE(bar) 3 of 4
+
+NOTE(bar) 4 of 4
+ - this is the last line of note 4
+
+NOTE(bam) This note which contains a (parenthesized) subphrase
+ must appear in its entirety.
+
+NOTE(xxx) The ':' after the marker and uid is optional.
+
SECBUGS
- // sec hole 0 need to fix asap (uid: uid)
+SECBUG(uid) sec hole 0
+ need to fix asap
+
TODOS
- // todo0 (uid: uid)
- // todo1 (uid: uid)
+TODO(uid) todo0
+
+TODO(uid) todo1
+
diff --git a/libgo/go/go/doc/testdata/a.1.golden b/libgo/go/go/doc/testdata/a.1.golden
index cd98f4e0ebe..7e680b80b4c 100644
--- a/libgo/go/go/doc/testdata/a.1.golden
+++ b/libgo/go/go/doc/testdata/a.1.golden
@@ -9,24 +9,44 @@ FILENAMES
testdata/a1.go
BUGS .Bugs is now deprecated, please use .Notes instead
- // bug0
- // bug1
+ bug0
+
+ bug1
+
BUGS
- // bug0 (uid: uid)
- // bug1 (uid: uid)
+BUG(uid) bug0
+
+BUG(uid) bug1
+
NOTES
- // 1 of 4 - this is the first line of note 1 - note 1 continues on ... (uid: foo)
- // 2 of 4 (uid: foo)
- // 3 of 4 (uid: bar)
- // 4 of 4 - this is the last line of note 4 (uid: bar)
- // This note which contains a (parenthesized) subphrase must ... (uid: bam)
- // The ':' after the marker and uid is optional. (uid: xxx)
+NOTE(uid)
+
+NOTE(foo) 1 of 4 - this is the first line of note 1
+ - note 1 continues on this 2nd line
+ - note 1 continues on this 3rd line
+
+NOTE(foo) 2 of 4
+
+NOTE(bar) 3 of 4
+
+NOTE(bar) 4 of 4
+ - this is the last line of note 4
+
+NOTE(bam) This note which contains a (parenthesized) subphrase
+ must appear in its entirety.
+
+NOTE(xxx) The ':' after the marker and uid is optional.
+
SECBUGS
- // sec hole 0 need to fix asap (uid: uid)
+SECBUG(uid) sec hole 0
+ need to fix asap
+
TODOS
- // todo0 (uid: uid)
- // todo1 (uid: uid)
+TODO(uid) todo0
+
+TODO(uid) todo1
+
diff --git a/libgo/go/go/doc/testdata/a.2.golden b/libgo/go/go/doc/testdata/a.2.golden
index cd98f4e0ebe..7e680b80b4c 100644
--- a/libgo/go/go/doc/testdata/a.2.golden
+++ b/libgo/go/go/doc/testdata/a.2.golden
@@ -9,24 +9,44 @@ FILENAMES
testdata/a1.go
BUGS .Bugs is now deprecated, please use .Notes instead
- // bug0
- // bug1
+ bug0
+
+ bug1
+
BUGS
- // bug0 (uid: uid)
- // bug1 (uid: uid)
+BUG(uid) bug0
+
+BUG(uid) bug1
+
NOTES
- // 1 of 4 - this is the first line of note 1 - note 1 continues on ... (uid: foo)
- // 2 of 4 (uid: foo)
- // 3 of 4 (uid: bar)
- // 4 of 4 - this is the last line of note 4 (uid: bar)
- // This note which contains a (parenthesized) subphrase must ... (uid: bam)
- // The ':' after the marker and uid is optional. (uid: xxx)
+NOTE(uid)
+
+NOTE(foo) 1 of 4 - this is the first line of note 1
+ - note 1 continues on this 2nd line
+ - note 1 continues on this 3rd line
+
+NOTE(foo) 2 of 4
+
+NOTE(bar) 3 of 4
+
+NOTE(bar) 4 of 4
+ - this is the last line of note 4
+
+NOTE(bam) This note which contains a (parenthesized) subphrase
+ must appear in its entirety.
+
+NOTE(xxx) The ':' after the marker and uid is optional.
+
SECBUGS
- // sec hole 0 need to fix asap (uid: uid)
+SECBUG(uid) sec hole 0
+ need to fix asap
+
TODOS
- // todo0 (uid: uid)
- // todo1 (uid: uid)
+TODO(uid) todo0
+
+TODO(uid) todo1
+
diff --git a/libgo/go/go/doc/testdata/bugpara.0.golden b/libgo/go/go/doc/testdata/bugpara.0.golden
new file mode 100644
index 00000000000..5804859501e
--- /dev/null
+++ b/libgo/go/go/doc/testdata/bugpara.0.golden
@@ -0,0 +1,20 @@
+//
+PACKAGE bugpara
+
+IMPORTPATH
+ testdata/bugpara
+
+FILENAMES
+ testdata/bugpara.go
+
+BUGS .Bugs is now deprecated, please use .Notes instead
+ Sometimes bugs have multiple paragraphs.
+
+ Like this one.
+
+
+BUGS
+BUG(rsc) Sometimes bugs have multiple paragraphs.
+
+ Like this one.
+
diff --git a/libgo/go/go/doc/testdata/bugpara.1.golden b/libgo/go/go/doc/testdata/bugpara.1.golden
new file mode 100644
index 00000000000..5804859501e
--- /dev/null
+++ b/libgo/go/go/doc/testdata/bugpara.1.golden
@@ -0,0 +1,20 @@
+//
+PACKAGE bugpara
+
+IMPORTPATH
+ testdata/bugpara
+
+FILENAMES
+ testdata/bugpara.go
+
+BUGS .Bugs is now deprecated, please use .Notes instead
+ Sometimes bugs have multiple paragraphs.
+
+ Like this one.
+
+
+BUGS
+BUG(rsc) Sometimes bugs have multiple paragraphs.
+
+ Like this one.
+
diff --git a/libgo/go/go/doc/testdata/bugpara.2.golden b/libgo/go/go/doc/testdata/bugpara.2.golden
new file mode 100644
index 00000000000..5804859501e
--- /dev/null
+++ b/libgo/go/go/doc/testdata/bugpara.2.golden
@@ -0,0 +1,20 @@
+//
+PACKAGE bugpara
+
+IMPORTPATH
+ testdata/bugpara
+
+FILENAMES
+ testdata/bugpara.go
+
+BUGS .Bugs is now deprecated, please use .Notes instead
+ Sometimes bugs have multiple paragraphs.
+
+ Like this one.
+
+
+BUGS
+BUG(rsc) Sometimes bugs have multiple paragraphs.
+
+ Like this one.
+
diff --git a/libgo/go/go/doc/testdata/bugpara.go b/libgo/go/go/doc/testdata/bugpara.go
new file mode 100644
index 00000000000..f5345a79753
--- /dev/null
+++ b/libgo/go/go/doc/testdata/bugpara.go
@@ -0,0 +1,5 @@
+package bugpara
+
+// BUG(rsc): Sometimes bugs have multiple paragraphs.
+//
+// Like this one.
diff --git a/libgo/go/go/doc/testdata/template.txt b/libgo/go/go/doc/testdata/template.txt
index 26482f7c246..1b073826116 100644
--- a/libgo/go/go/doc/testdata/template.txt
+++ b/libgo/go/go/doc/testdata/template.txt
@@ -61,8 +61,8 @@ TYPES
*/}}{{with .Bugs}}
BUGS .Bugs is now deprecated, please use .Notes instead
-{{range .}} {{synopsis .}}
+{{range .}}{{indent "\t" .}}
{{end}}{{end}}{{with .Notes}}{{range $marker, $content := .}}
{{$marker}}S
-{{range $content}} {{synopsis .Body}} (uid: {{.UID}})
+{{range $content}}{{$marker}}({{.UID}}){{indent "\t" .Body}}
{{end}}{{end}}{{end}} \ No newline at end of file
diff --git a/libgo/go/go/doc/testdata/testing.0.golden b/libgo/go/go/doc/testdata/testing.0.golden
index 15a90398664..f8348f1ac34 100644
--- a/libgo/go/go/doc/testdata/testing.0.golden
+++ b/libgo/go/go/doc/testdata/testing.0.golden
@@ -57,7 +57,7 @@ TYPES
// FailNow marks the function as having failed and stops its ...
func (c *B) FailNow()
- // Failed returns whether the function has failed.
+ // Failed reports whether the function has failed.
func (c *B) Failed() bool
// Fatal is equivalent to Log() followed by FailNow().
@@ -136,7 +136,7 @@ TYPES
// FailNow marks the function as having failed and stops its ...
func (c *T) FailNow()
- // Failed returns whether the function has failed.
+ // Failed reports whether the function has failed.
func (c *T) Failed() bool
// Fatal is equivalent to Log() followed by FailNow().
diff --git a/libgo/go/go/doc/testdata/testing.1.golden b/libgo/go/go/doc/testdata/testing.1.golden
index ffdb5c3b588..282bb1015ad 100644
--- a/libgo/go/go/doc/testdata/testing.1.golden
+++ b/libgo/go/go/doc/testdata/testing.1.golden
@@ -130,7 +130,7 @@ TYPES
// FailNow marks the function as having failed and stops its ...
func (c *B) FailNow()
- // Failed returns whether the function has failed.
+ // Failed reports whether the function has failed.
func (c *B) Failed() bool
// Fatal is equivalent to Log() followed by FailNow().
@@ -232,7 +232,7 @@ TYPES
// FailNow marks the function as having failed and stops its ...
func (c *T) FailNow()
- // Failed returns whether the function has failed.
+ // Failed reports whether the function has failed.
func (c *T) Failed() bool
// Fatal is equivalent to Log() followed by FailNow().
@@ -278,7 +278,7 @@ TYPES
// FailNow marks the function as having failed and stops its ...
func (c *common) FailNow()
- // Failed returns whether the function has failed.
+ // Failed reports whether the function has failed.
func (c *common) Failed() bool
// Fatal is equivalent to Log() followed by FailNow().
diff --git a/libgo/go/go/doc/testdata/testing.2.golden b/libgo/go/go/doc/testdata/testing.2.golden
index 15a90398664..f8348f1ac34 100644
--- a/libgo/go/go/doc/testdata/testing.2.golden
+++ b/libgo/go/go/doc/testdata/testing.2.golden
@@ -57,7 +57,7 @@ TYPES
// FailNow marks the function as having failed and stops its ...
func (c *B) FailNow()
- // Failed returns whether the function has failed.
+ // Failed reports whether the function has failed.
func (c *B) Failed() bool
// Fatal is equivalent to Log() followed by FailNow().
@@ -136,7 +136,7 @@ TYPES
// FailNow marks the function as having failed and stops its ...
func (c *T) FailNow()
- // Failed returns whether the function has failed.
+ // Failed reports whether the function has failed.
func (c *T) Failed() bool
// Fatal is equivalent to Log() followed by FailNow().
diff --git a/libgo/go/go/doc/testdata/testing.go b/libgo/go/go/doc/testdata/testing.go
index c2499ad7799..93ed494c32b 100644
--- a/libgo/go/go/doc/testdata/testing.go
+++ b/libgo/go/go/doc/testdata/testing.go
@@ -130,7 +130,7 @@ type T struct {
// Fail marks the function as having failed but continues execution.
func (c *common) Fail() { c.failed = true }
-// Failed returns whether the function has failed.
+// Failed reports whether the function has failed.
func (c *common) Failed() bool { return c.failed }
// FailNow marks the function as having failed and stops its execution.
diff --git a/libgo/go/go/format/format_test.go b/libgo/go/go/format/format_test.go
index 7d7940bb517..93f0992477c 100644
--- a/libgo/go/go/format/format_test.go
+++ b/libgo/go/go/format/format_test.go
@@ -90,7 +90,6 @@ var tests = []string{
"\n\t\t\n\n\t\t\tx := 0\n\t\t\tconst s = `\nfoo\n`\n\n\n", // no indentation inside raw strings
// erroneous programs
- "ERRORvar x",
"ERROR1 + 2 +",
"ERRORx := 0",
}
diff --git a/libgo/go/go/parser/interface.go b/libgo/go/go/parser/interface.go
index 149257ca6b1..0f83ca93143 100644
--- a/libgo/go/go/parser/interface.go
+++ b/libgo/go/go/parser/interface.go
@@ -15,6 +15,7 @@ import (
"io/ioutil"
"os"
"path/filepath"
+ "strings"
)
// If src != nil, readSource converts src to a []byte if possible;
@@ -115,11 +116,13 @@ func ParseFile(fset *token.FileSet, filename string, src interface{}, mode Mode)
return
}
-// ParseDir calls ParseFile for the files in the directory specified by path and
-// returns a map of package name -> package AST with all the packages found. If
-// filter != nil, only the files with os.FileInfo entries passing through the filter
-// are considered. The mode bits are passed to ParseFile unchanged. Position
-// information is recorded in the file set fset.
+// ParseDir calls ParseFile for all files with names ending in ".go" in the
+// directory specified by path and returns a map of package name -> package
+// AST with all the packages found.
+//
+// If filter != nil, only the files with os.FileInfo entries passing through
+// the filter (and ending in ".go") are considered. The mode bits are passed
+// to ParseFile unchanged. Position information is recorded in fset.
//
// If the directory couldn't be read, a nil map and the respective error are
// returned. If a parse error occurred, a non-nil but incomplete map and the
@@ -139,7 +142,7 @@ func ParseDir(fset *token.FileSet, path string, filter func(os.FileInfo) bool, m
pkgs = make(map[string]*ast.Package)
for _, d := range list {
- if filter == nil || filter(d) {
+ if strings.HasSuffix(d.Name(), ".go") && (filter == nil || filter(d)) {
filename := filepath.Join(path, d.Name())
if src, err := ParseFile(fset, filename, nil, mode); err == nil {
name := src.Name.Name
diff --git a/libgo/go/go/parser/parser.go b/libgo/go/go/parser/parser.go
index f4a690a6f28..c4523318f26 100644
--- a/libgo/go/go/parser/parser.go
+++ b/libgo/go/go/parser/parser.go
@@ -64,7 +64,7 @@ type parser struct {
}
func (p *parser) init(fset *token.FileSet, filename string, src []byte, mode Mode) {
- p.file = fset.AddFile(filename, fset.Base(), len(src))
+ p.file = fset.AddFile(filename, -1, len(src))
var m scanner.Mode
if mode&ParseComments != 0 {
m = scanner.ScanComments
@@ -1150,7 +1150,7 @@ func (p *parser) parseTypeAssertion(x ast.Expr) ast.Expr {
defer un(trace(p, "TypeAssertion"))
}
- p.expect(token.LPAREN)
+ lparen := p.expect(token.LPAREN)
var typ ast.Expr
if p.tok == token.TYPE {
// type switch: typ == nil
@@ -1158,9 +1158,9 @@ func (p *parser) parseTypeAssertion(x ast.Expr) ast.Expr {
} else {
typ = p.parseType()
}
- p.expect(token.RPAREN)
+ rparen := p.expect(token.RPAREN)
- return &ast.TypeAssertExpr{X: x, Type: typ}
+ return &ast.TypeAssertExpr{X: x, Type: typ, Lparen: lparen, Rparen: rparen}
}
func (p *parser) parseIndexOrSlice(x ast.Expr) ast.Expr {
@@ -1170,25 +1170,27 @@ func (p *parser) parseIndexOrSlice(x ast.Expr) ast.Expr {
lbrack := p.expect(token.LBRACK)
p.exprLev++
- var low, high ast.Expr
- isSlice := false
+ var index [3]ast.Expr // change the 3 to 2 to disable slice expressions w/ cap
if p.tok != token.COLON {
- low = p.parseRhs()
+ index[0] = p.parseRhs()
}
- if p.tok == token.COLON {
- isSlice = true
+ ncolons := 0
+ for p.tok == token.COLON && ncolons < len(index)-1 {
p.next()
- if p.tok != token.RBRACK {
- high = p.parseRhs()
+ ncolons++
+ if p.tok != token.COLON && p.tok != token.RBRACK && p.tok != token.EOF {
+ index[ncolons] = p.parseRhs()
}
}
p.exprLev--
rbrack := p.expect(token.RBRACK)
- if isSlice {
- return &ast.SliceExpr{X: x, Lbrack: lbrack, Low: low, High: high, Rbrack: rbrack}
+ if ncolons > 0 {
+ // slice expression
+ return &ast.SliceExpr{X: x, Lbrack: lbrack, Low: index[0], High: index[1], Max: index[2], Slice3: ncolons == 2, Rbrack: rbrack}
}
- return &ast.IndexExpr{X: x, Lbrack: lbrack, Index: low, Rbrack: rbrack}
+
+ return &ast.IndexExpr{X: x, Lbrack: lbrack, Index: index[0], Rbrack: rbrack}
}
func (p *parser) parseCallOrConversion(fun ast.Expr) *ast.CallExpr {
@@ -1406,7 +1408,7 @@ L:
}
switch p.tok {
case token.IDENT:
- x = p.parseSelector(p.checkExpr(x))
+ x = p.parseSelector(p.checkExprOrType(x))
case token.LPAREN:
x = p.parseTypeAssertion(p.checkExpr(x))
default:
@@ -2145,12 +2147,13 @@ func (p *parser) parseImportSpec(doc *ast.CommentGroup, _ token.Token, _ int) as
ident = p.parseIdent()
}
- var path *ast.BasicLit
+ pos := p.pos
+ var path string
if p.tok == token.STRING {
- if !isValidImport(p.lit) {
- p.error(p.pos, "invalid import path: "+p.lit)
+ path = p.lit
+ if !isValidImport(path) {
+ p.error(pos, "invalid import path: "+path)
}
- path = &ast.BasicLit{ValuePos: p.pos, Kind: p.tok, Value: p.lit}
p.next()
} else {
p.expect(token.STRING) // use expect() error handling
@@ -2161,7 +2164,7 @@ func (p *parser) parseImportSpec(doc *ast.CommentGroup, _ token.Token, _ int) as
spec := &ast.ImportSpec{
Doc: doc,
Name: ident,
- Path: path,
+ Path: &ast.BasicLit{ValuePos: pos, Kind: token.STRING, Value: path},
Comment: p.lineComment,
}
p.imports = append(p.imports, spec)
@@ -2177,8 +2180,9 @@ func (p *parser) parseValueSpec(doc *ast.CommentGroup, keyword token.Token, iota
idents := p.parseIdentList()
typ := p.tryType()
var values []ast.Expr
- if p.tok == token.ASSIGN || keyword == token.CONST && (typ != nil || iota == 0) || keyword == token.VAR && typ == nil {
- p.expect(token.ASSIGN)
+ // always permit optional initialization for more tolerant parsing
+ if p.tok == token.ASSIGN {
+ p.next()
values = p.parseRhsList()
}
p.expectSemi() // call before accessing p.linecomment
@@ -2381,7 +2385,7 @@ func (p *parser) parseFile() *ast.File {
// Go spec: The package clause is not a declaration;
// the package name does not appear in any scope.
ident := p.parseIdent()
- if ident.Name == "_" {
+ if ident.Name == "_" && p.mode&DeclarationErrors != 0 {
p.error(p.pos, "invalid package name _")
}
p.expectSemi()
diff --git a/libgo/go/go/parser/parser_test.go b/libgo/go/go/parser/parser_test.go
index 48813d10612..0a34b7e505e 100644
--- a/libgo/go/go/parser/parser_test.go
+++ b/libgo/go/go/parser/parser_test.go
@@ -34,13 +34,12 @@ func TestParse(t *testing.T) {
func nameFilter(filename string) bool {
switch filename {
- case "parser.go":
- case "interface.go":
- case "parser_test.go":
- default:
- return false
+ case "parser.go", "interface.go", "parser_test.go":
+ return true
+ case "parser.go.orig":
+ return true // permit but should be ignored by ParseDir
}
- return true
+ return false
}
func dirFilter(f os.FileInfo) bool { return nameFilter(f.Name()) }
@@ -51,14 +50,17 @@ func TestParseDir(t *testing.T) {
if err != nil {
t.Fatalf("ParseDir(%s): %v", path, err)
}
- if len(pkgs) != 1 {
- t.Errorf("incorrect number of packages: %d", len(pkgs))
+ if n := len(pkgs); n != 1 {
+ t.Errorf("got %d packages; want 1", n)
}
pkg := pkgs["parser"]
if pkg == nil {
t.Errorf(`package "parser" not found`)
return
}
+ if n := len(pkg.Files); n != 3 {
+ t.Errorf("got %d package files; want 3", n)
+ }
for filename := range pkg.Files {
if !nameFilter(filename) {
t.Errorf("unexpected package file: %s", filename)
diff --git a/libgo/go/go/parser/short_test.go b/libgo/go/go/parser/short_test.go
index 62277c0d26b..0ef0c560c4a 100644
--- a/libgo/go/go/parser/short_test.go
+++ b/libgo/go/go/parser/short_test.go
@@ -33,6 +33,8 @@ var valids = []string{
`package p; func f() { if ; true {} };`,
`package p; func f() { switch ; {} };`,
`package p; func f() { for _ = range "foo" + "bar" {} };`,
+ `package p; func f() { var s []int; g(s[:], s[i:], s[:j], s[i:j], s[i:j:k], s[:j:k]) };`,
+ `package p; var ( _ = (struct {*T}).m; _ = (interface {T}).m )`,
}
func TestValid(t *testing.T) {
@@ -46,7 +48,6 @@ var invalids = []string{
`package p; func f() { if { /* ERROR "expected operand" */ } };`,
`package p; func f() { if ; { /* ERROR "expected operand" */ } };`,
`package p; func f() { if f(); { /* ERROR "expected operand" */ } };`,
- `package p; const c; /* ERROR "expected '='" */`,
`package p; func f() { if _ /* ERROR "expected condition" */ = range x; true {} };`,
`package p; func f() { switch _ /* ERROR "expected condition" */ = range x; true {} };`,
`package p; func f() { for _ = range x ; /* ERROR "expected '{'" */ ; {} };`,
@@ -74,6 +75,9 @@ var invalids = []string{
`package p; func f() { if x := g(); x = /* ERROR "expected '=='" */ 0 {}};`,
`package p; func f() { _ = x = /* ERROR "expected '=='" */ 0 {}};`,
`package p; func f() { _ = 1 == func()int { var x bool; x = x = /* ERROR "expected '=='" */ true; return x }() };`,
+ `package p; func f() { var s []int; _ = s[] /* ERROR "expected operand" */ };`,
+ `package p; func f() { var s []int; _ = s[::: /* ERROR "expected ']'" */ ] };`,
+ `package p; func f() { var s []int; _ = s[i:j:k: /* ERROR "expected ']'" */ l] };`,
}
func TestInvalid(t *testing.T) {
diff --git a/libgo/go/go/printer/nodes.go b/libgo/go/go/printer/nodes.go
index 7cd068e22ef..583c6c37090 100644
--- a/libgo/go/go/printer/nodes.go
+++ b/libgo/go/go/printer/nodes.go
@@ -754,13 +754,13 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int) {
case *ast.TypeAssertExpr:
p.expr1(x.X, token.HighestPrec, depth)
- p.print(token.PERIOD, token.LPAREN)
+ p.print(token.PERIOD, x.Lparen, token.LPAREN)
if x.Type != nil {
p.expr(x.Type)
} else {
p.print(token.TYPE)
}
- p.print(token.RPAREN)
+ p.print(x.Rparen, token.RPAREN)
case *ast.IndexExpr:
// TODO(gri): should treat[] like parentheses and undo one level of depth
@@ -773,17 +773,25 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int) {
// TODO(gri): should treat[] like parentheses and undo one level of depth
p.expr1(x.X, token.HighestPrec, 1)
p.print(x.Lbrack, token.LBRACK)
- if x.Low != nil {
- p.expr0(x.Low, depth+1)
- }
- // blanks around ":" if both sides exist and either side is a binary expression
- if depth <= 1 && x.Low != nil && x.High != nil && (isBinary(x.Low) || isBinary(x.High)) {
- p.print(blank, token.COLON, blank)
- } else {
- p.print(token.COLON)
+ indices := []ast.Expr{x.Low, x.High}
+ if x.Max != nil {
+ indices = append(indices, x.Max)
}
- if x.High != nil {
- p.expr0(x.High, depth+1)
+ for i, y := range indices {
+ if i > 0 {
+ // blanks around ":" if both sides exist and either side is a binary expression
+ // TODO(gri) once we have committed a variant of a[i:j:k] we may want to fine-
+ // tune the formatting here
+ x := indices[i-1]
+ if depth <= 1 && x != nil && y != nil && (isBinary(x) || isBinary(y)) {
+ p.print(blank, token.COLON, blank)
+ } else {
+ p.print(token.COLON)
+ }
+ }
+ if y != nil {
+ p.expr0(y, depth+1)
+ }
}
p.print(x.Rbrack, token.RBRACK)
diff --git a/libgo/go/go/printer/testdata/expressions.golden b/libgo/go/go/printer/testdata/expressions.golden
index 4291c557ce2..fbe8275b3a5 100644
--- a/libgo/go/go/printer/testdata/expressions.golden
+++ b/libgo/go/go/printer/testdata/expressions.golden
@@ -114,6 +114,23 @@ func _() {
x < y || z > 42
}
+// slice expressions with cap
+func _() {
+ _ = x[a:b:c]
+ _ = x[a:b : c+d]
+ _ = x[a : b+d : c]
+ _ = x[a : b+d : c+d]
+ _ = x[a+d : b:c]
+ _ = x[a+d : b : c+d]
+ _ = x[a+d : b+d : c]
+ _ = x[a+d : b+d : c+d]
+
+ _ = x[:b:c]
+ _ = x[:b : c+d]
+ _ = x[:b+d : c]
+ _ = x[:b+d : c+d]
+}
+
func _() {
_ = a + b
_ = a + b + c
diff --git a/libgo/go/go/printer/testdata/expressions.input b/libgo/go/go/printer/testdata/expressions.input
index 1ec12a05049..f4d20fa0f77 100644
--- a/libgo/go/go/printer/testdata/expressions.input
+++ b/libgo/go/go/printer/testdata/expressions.input
@@ -116,6 +116,23 @@ func _() {
}
+// slice expressions with cap
+func _() {
+ _ = x[a:b:c]
+ _ = x[a:b:c+d]
+ _ = x[a:b+d:c]
+ _ = x[a:b+d:c+d]
+ _ = x[a+d:b:c]
+ _ = x[a+d:b:c+d]
+ _ = x[a+d:b+d:c]
+ _ = x[a+d:b+d:c+d]
+
+ _ = x[:b:c]
+ _ = x[:b:c+d]
+ _ = x[:b+d:c]
+ _ = x[:b+d:c+d]
+}
+
func _() {
_ = a+b
_ = a+b+c
diff --git a/libgo/go/go/printer/testdata/expressions.raw b/libgo/go/go/printer/testdata/expressions.raw
index 062900e0724..97bc81dad87 100644
--- a/libgo/go/go/printer/testdata/expressions.raw
+++ b/libgo/go/go/printer/testdata/expressions.raw
@@ -114,6 +114,23 @@ func _() {
x < y || z > 42
}
+// slice expressions with cap
+func _() {
+ _ = x[a:b:c]
+ _ = x[a:b : c+d]
+ _ = x[a : b+d : c]
+ _ = x[a : b+d : c+d]
+ _ = x[a+d : b:c]
+ _ = x[a+d : b : c+d]
+ _ = x[a+d : b+d : c]
+ _ = x[a+d : b+d : c+d]
+
+ _ = x[:b:c]
+ _ = x[:b : c+d]
+ _ = x[:b+d : c]
+ _ = x[:b+d : c+d]
+}
+
func _() {
_ = a + b
_ = a + b + c
diff --git a/libgo/go/go/token/position.go b/libgo/go/go/token/position.go
index f5d99956186..e6f0ae6a673 100644
--- a/libgo/go/go/token/position.go
+++ b/libgo/go/go/token/position.go
@@ -97,7 +97,7 @@ type File struct {
size int // file size as provided to AddFile
// lines and infos are protected by set.mutex
- lines []int
+ lines []int // lines contains the offset of the first character for each line (the first entry is always 0)
infos []lineInfo
}
@@ -136,6 +136,29 @@ func (f *File) AddLine(offset int) {
f.set.mutex.Unlock()
}
+// MergeLine merges a line with the following line. It is akin to replacing
+// the newline character at the end of the line with a space (to not change the
+// remaining offsets). To obtain the line number, consult e.g. Position.Line.
+// MergeLine will panic if given an invalid line number.
+//
+func (f *File) MergeLine(line int) {
+ if line <= 0 {
+ panic("illegal line number (line numbering starts at 1)")
+ }
+ f.set.mutex.Lock()
+ defer f.set.mutex.Unlock()
+ if line >= len(f.lines) {
+ panic("illegal line number")
+ }
+ // To merge the line numbered <line> with the line numbered <line+1>,
+ // we need to remove the entry in lines corresponding to the line
+ // numbered <line+1>. The entry in lines corresponding to the line
+ // numbered <line+1> is located at index <line>, since indices in lines
+ // are 0-based and line numbers are 1-based.
+ copy(f.lines[line:], f.lines[line+1:])
+ f.lines = f.lines[:len(f.lines)-1]
+}
+
// SetLines sets the line offsets for a file and returns true if successful.
// The line offsets are the offsets of the first character of each line;
// for instance for the content "ab\nc\n" the line offsets are {0, 3}.
@@ -314,7 +337,8 @@ func (s *FileSet) Base() int {
// AddFile adds a new file with a given filename, base offset, and file size
// to the file set s and returns the file. Multiple files may have the same
// name. The base offset must not be smaller than the FileSet's Base(), and
-// size must not be negative.
+// size must not be negative. As a special case, if a negative base is provided,
+// the current value of the FileSet's Base() is used instead.
//
// Adding the file will set the file set's Base() value to base + size + 1
// as the minimum base value for the next file. The following relationship
@@ -329,6 +353,9 @@ func (s *FileSet) Base() int {
func (s *FileSet) AddFile(filename string, base, size int) *File {
s.mutex.Lock()
defer s.mutex.Unlock()
+ if base < 0 {
+ base = s.base
+ }
if base < s.base || size < 0 {
panic("illegal base or size")
}
diff --git a/libgo/go/go/token/position_test.go b/libgo/go/go/token/position_test.go
index 1d36c22268d..ef6cfd93c25 100644
--- a/libgo/go/go/token/position_test.go
+++ b/libgo/go/go/token/position_test.go
@@ -167,7 +167,13 @@ func TestLineInfo(t *testing.T) {
func TestFiles(t *testing.T) {
fset := NewFileSet()
for i, test := range tests {
- fset.AddFile(test.filename, fset.Base(), test.size)
+ base := fset.Base()
+ if i%2 == 1 {
+ // Setting a negative base is equivalent to
+ // fset.Base(), so test some of each.
+ base = -1
+ }
+ fset.AddFile(test.filename, base, test.size)
j := 0
fset.Iterate(func(f *File) bool {
if f.Name() != tests[j].filename {
diff --git a/libgo/go/hash/hash.go b/libgo/go/hash/hash.go
index aa895cf9847..8d138d07f93 100644
--- a/libgo/go/hash/hash.go
+++ b/libgo/go/hash/hash.go
@@ -9,7 +9,7 @@ import "io"
// Hash is the common interface implemented by all hash functions.
type Hash interface {
- // Write adds more data to the running hash.
+ // Write (via the embedded io.Writer interface) adds more data to the running hash.
// It never returns an error.
io.Writer
@@ -17,7 +17,7 @@ type Hash interface {
// It does not change the underlying hash state.
Sum(b []byte) []byte
- // Reset resets the hash to one with zero bytes written.
+ // Reset resets the Hash to its initial state.
Reset()
// Size returns the number of bytes Sum will return.
diff --git a/libgo/go/html/escape.go b/libgo/go/html/escape.go
index eff0384e089..dd5dfa7cd75 100644
--- a/libgo/go/html/escape.go
+++ b/libgo/go/html/escape.go
@@ -187,16 +187,6 @@ func unescape(b []byte) []byte {
return b
}
-// lower lower-cases the A-Z bytes in b in-place, so that "aBc" becomes "abc".
-func lower(b []byte) []byte {
- for i, c := range b {
- if 'A' <= c && c <= 'Z' {
- b[i] = c + 'a' - 'A'
- }
- }
- return b
-}
-
const escapedChars = `&'<>"`
func escape(w writer, s string) error {
diff --git a/libgo/go/html/escape_test.go b/libgo/go/html/escape_test.go
new file mode 100644
index 00000000000..b405d4b4a77
--- /dev/null
+++ b/libgo/go/html/escape_test.go
@@ -0,0 +1,97 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package html
+
+import "testing"
+
+type unescapeTest struct {
+ // A short description of the test case.
+ desc string
+ // The HTML text.
+ html string
+ // The unescaped text.
+ unescaped string
+}
+
+var unescapeTests = []unescapeTest{
+ // Handle no entities.
+ {
+ "copy",
+ "A\ttext\nstring",
+ "A\ttext\nstring",
+ },
+ // Handle simple named entities.
+ {
+ "simple",
+ "&amp; &gt; &lt;",
+ "& > <",
+ },
+ // Handle hitting the end of the string.
+ {
+ "stringEnd",
+ "&amp &amp",
+ "& &",
+ },
+ // Handle entities with two codepoints.
+ {
+ "multiCodepoint",
+ "text &gesl; blah",
+ "text \u22db\ufe00 blah",
+ },
+ // Handle decimal numeric entities.
+ {
+ "decimalEntity",
+ "Delta = &#916; ",
+ "Delta = Δ ",
+ },
+ // Handle hexadecimal numeric entities.
+ {
+ "hexadecimalEntity",
+ "Lambda = &#x3bb; = &#X3Bb ",
+ "Lambda = λ = λ ",
+ },
+ // Handle numeric early termination.
+ {
+ "numericEnds",
+ "&# &#x &#128;43 &copy = &#169f = &#xa9",
+ "&# &#x €43 © = ©f = ©",
+ },
+ // Handle numeric ISO-8859-1 entity replacements.
+ {
+ "numericReplacements",
+ "Footnote&#x87;",
+ "Footnote‡",
+ },
+}
+
+func TestUnescape(t *testing.T) {
+ for _, tt := range unescapeTests {
+ unescaped := UnescapeString(tt.html)
+ if unescaped != tt.unescaped {
+ t.Errorf("TestUnescape %s: want %q, got %q", tt.desc, tt.unescaped, unescaped)
+ }
+ }
+}
+
+func TestUnescapeEscape(t *testing.T) {
+ ss := []string{
+ ``,
+ `abc def`,
+ `a & b`,
+ `a&amp;b`,
+ `a &amp b`,
+ `&quot;`,
+ `"`,
+ `"<&>"`,
+ `&quot;&lt;&amp;&gt;&quot;`,
+ `3&5==1 && 0<1, "0&lt;1", a+acute=&aacute;`,
+ `The special characters are: <, >, &, ' and "`,
+ }
+ for _, s := range ss {
+ if got := UnescapeString(EscapeString(s)); got != s {
+ t.Errorf("got %q want %q", got, s)
+ }
+ }
+}
diff --git a/libgo/go/html/template/clone_test.go b/libgo/go/html/template/clone_test.go
index 2663cddc24b..e11bff2c5df 100644
--- a/libgo/go/html/template/clone_test.go
+++ b/libgo/go/html/template/clone_test.go
@@ -6,6 +6,8 @@ package template
import (
"bytes"
+ "errors"
+ "io/ioutil"
"testing"
"text/template/parse"
)
@@ -146,3 +148,41 @@ func TestCloneCrash(t *testing.T) {
Must(t1.New("t1").Parse(`{{define "foo"}}foo{{end}}`))
t1.Clone()
}
+
+// Ensure that this guarantee from the docs is upheld:
+// "Further calls to Parse in the copy will add templates
+// to the copy but not to the original."
+func TestCloneThenParse(t *testing.T) {
+ t0 := Must(New("t0").Parse(`{{define "a"}}{{template "embedded"}}{{end}}`))
+ t1 := Must(t0.Clone())
+ Must(t1.Parse(`{{define "embedded"}}t1{{end}}`))
+ if len(t0.Templates())+1 != len(t1.Templates()) {
+ t.Error("adding a template to a clone added it to the original")
+ }
+ // double check that the embedded template isn't available in the original
+ err := t0.ExecuteTemplate(ioutil.Discard, "a", nil)
+ if err == nil {
+ t.Error("expected 'no such template' error")
+ }
+}
+
+// https://code.google.com/p/go/issues/detail?id=5980
+func TestFuncMapWorksAfterClone(t *testing.T) {
+ funcs := FuncMap{"customFunc": func() (string, error) {
+ return "", errors.New("issue5980")
+ }}
+
+ // get the expected error output (no clone)
+ uncloned := Must(New("").Funcs(funcs).Parse("{{customFunc}}"))
+ wantErr := uncloned.Execute(ioutil.Discard, nil)
+
+ // toClone must be the same as uncloned. It has to be recreated from scratch,
+ // since cloning cannot occur after execution.
+ toClone := Must(New("").Funcs(funcs).Parse("{{customFunc}}"))
+ cloned := Must(toClone.Clone())
+ gotErr := cloned.Execute(ioutil.Discard, nil)
+
+ if wantErr.Error() != gotErr.Error() {
+ t.Errorf("clone error message mismatch want %q got %q", wantErr, gotErr)
+ }
+}
diff --git a/libgo/go/html/template/content.go b/libgo/go/html/template/content.go
index 9d1f74f6f01..41b1116a661 100644
--- a/libgo/go/html/template/content.go
+++ b/libgo/go/html/template/content.go
@@ -74,6 +74,9 @@ const (
// indirect returns the value, after dereferencing as many times
// as necessary to reach the base type (or nil).
func indirect(a interface{}) interface{} {
+ if a == nil {
+ return nil
+ }
if t := reflect.TypeOf(a); t.Kind() != reflect.Ptr {
// Avoid creating a reflect.Value if it's not a pointer.
return a
@@ -94,6 +97,9 @@ var (
// as necessary to reach the base type (or nil) or an implementation of fmt.Stringer
// or error,
func indirectToStringerOrError(a interface{}) interface{} {
+ if a == nil {
+ return nil
+ }
v := reflect.ValueOf(a)
for !v.Type().Implements(fmtStringerType) && !v.Type().Implements(errorType) && v.Kind() == reflect.Ptr && !v.IsNil() {
v = v.Elem()
diff --git a/libgo/go/html/template/content_test.go b/libgo/go/html/template/content_test.go
index 3c32e5e89cf..5f3ffe2d325 100644
--- a/libgo/go/html/template/content_test.go
+++ b/libgo/go/html/template/content_test.go
@@ -123,29 +123,29 @@ func TestTypedContent(t *testing.T) {
{
`<script>alert({{.}})</script>`,
[]string{
- `"\u003cb\u003e \"foo%\" O'Reilly &bar;"`,
+ `"\u003cb\u003e \"foo%\" O'Reilly \u0026bar;"`,
`"a[href =~ \"//example.com\"]#foo"`,
- `"Hello, \u003cb\u003eWorld\u003c/b\u003e &amp;tc!"`,
+ `"Hello, \u003cb\u003eWorld\u003c/b\u003e \u0026amp;tc!"`,
`" dir=\"ltr\""`,
// Not escaped.
`c && alert("Hello, World!");`,
// Escape sequence not over-escaped.
`"Hello, World & O'Reilly\x21"`,
- `"greeting=H%69&addressee=(World)"`,
+ `"greeting=H%69\u0026addressee=(World)"`,
},
},
{
`<button onclick="alert({{.}})">`,
[]string{
- `&#34;\u003cb\u003e \&#34;foo%\&#34; O&#39;Reilly &amp;bar;&#34;`,
+ `&#34;\u003cb\u003e \&#34;foo%\&#34; O&#39;Reilly \u0026bar;&#34;`,
`&#34;a[href =~ \&#34;//example.com\&#34;]#foo&#34;`,
- `&#34;Hello, \u003cb\u003eWorld\u003c/b\u003e &amp;amp;tc!&#34;`,
+ `&#34;Hello, \u003cb\u003eWorld\u003c/b\u003e \u0026amp;tc!&#34;`,
`&#34; dir=\&#34;ltr\&#34;&#34;`,
// Not JS escaped but HTML escaped.
`c &amp;&amp; alert(&#34;Hello, World!&#34;);`,
// Escape sequence not over-escaped.
`&#34;Hello, World &amp; O&#39;Reilly\x21&#34;`,
- `&#34;greeting=H%69&amp;addressee=(World)&#34;`,
+ `&#34;greeting=H%69\u0026addressee=(World)&#34;`,
},
},
{
@@ -259,3 +259,22 @@ func TestStringer(t *testing.T) {
t.Errorf("expected %q got %q", expect, b.String())
}
}
+
+// https://code.google.com/p/go/issues/detail?id=5982
+func TestEscapingNilNonemptyInterfaces(t *testing.T) {
+ tmpl := Must(New("x").Parse("{{.E}}"))
+
+ got := new(bytes.Buffer)
+ testData := struct{ E error }{} // any non-empty interface here will do; error is just ready at hand
+ tmpl.Execute(got, testData)
+
+ // Use this data instead of just hard-coding "&lt;nil&gt;" to avoid
+ // dependencies on the html escaper and the behavior of fmt w.r.t. nil.
+ want := new(bytes.Buffer)
+ data := struct{ E string }{E: fmt.Sprint(nil)}
+ tmpl.Execute(want, data)
+
+ if !bytes.Equal(want.Bytes(), got.Bytes()) {
+ t.Errorf("expected %q got %q", string(want.Bytes()), string(got.Bytes()))
+ }
+}
diff --git a/libgo/go/html/template/context.go b/libgo/go/html/template/context.go
index 7202221b831..eb47e2be3c7 100644
--- a/libgo/go/html/template/context.go
+++ b/libgo/go/html/template/context.go
@@ -29,7 +29,7 @@ func (c context) String() string {
return fmt.Sprintf("{%v %v %v %v %v %v %v}", c.state, c.delim, c.urlPart, c.jsCtx, c.attr, c.element, c.err)
}
-// eq returns whether two contexts are equal.
+// eq reports whether two contexts are equal.
func (c context) eq(d context) bool {
return c.state == d.state &&
c.delim == d.delim &&
diff --git a/libgo/go/html/template/css.go b/libgo/go/html/template/css.go
index 3bcd9849831..634f183f796 100644
--- a/libgo/go/html/template/css.go
+++ b/libgo/go/html/template/css.go
@@ -11,7 +11,7 @@ import (
"unicode/utf8"
)
-// endsWithCSSKeyword returns whether b ends with an ident that
+// endsWithCSSKeyword reports whether b ends with an ident that
// case-insensitively matches the lower-case kw.
func endsWithCSSKeyword(b []byte, kw string) bool {
i := len(b) - len(kw)
@@ -34,7 +34,7 @@ func endsWithCSSKeyword(b []byte, kw string) bool {
return string(bytes.ToLower(b[i:])) == kw
}
-// isCSSNmchar returns whether rune is allowed anywhere in a CSS identifier.
+// isCSSNmchar reports whether rune is allowed anywhere in a CSS identifier.
func isCSSNmchar(r rune) bool {
// Based on the CSS3 nmchar production but ignores multi-rune escape
// sequences.
@@ -99,7 +99,7 @@ func decodeCSS(s []byte) []byte {
return b
}
-// isHex returns whether the given character is a hex digit.
+// isHex reports whether the given character is a hex digit.
func isHex(c byte) bool {
return '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F'
}
@@ -144,7 +144,7 @@ func skipCSSSpace(c []byte) []byte {
return c
}
-// isCSSSpace returns whether b is a CSS space char as defined in wc.
+// isCSSSpace reports whether b is a CSS space char as defined in wc.
func isCSSSpace(b byte) bool {
switch b {
case '\t', '\n', '\f', '\r', ' ':
diff --git a/libgo/go/html/template/escape.go b/libgo/go/html/template/escape.go
index 4829bfcc438..9ae9749db0c 100644
--- a/libgo/go/html/template/escape.go
+++ b/libgo/go/html/template/escape.go
@@ -35,11 +35,13 @@ func escapeTemplates(tmpl *Template, names ...string) error {
for _, name := range names {
if t := tmpl.set[name]; t != nil {
t.text.Tree = nil
+ t.Tree = nil
}
}
return err
}
tmpl.escaped = true
+ tmpl.Tree = tmpl.text.Tree
}
e.commit()
return nil
@@ -301,7 +303,7 @@ func indexOfStr(s string, strs []string, eq func(a, b string) bool) int {
return -1
}
-// escFnsEq returns whether the two escaping functions are equivalent.
+// escFnsEq reports whether the two escaping functions are equivalent.
func escFnsEq(a, b string) bool {
if e := equivEscapers[a]; e != "" {
a = e
diff --git a/libgo/go/html/template/escape_test.go b/libgo/go/html/template/escape_test.go
index de3659ba8fe..58383a6cd4e 100644
--- a/libgo/go/html/template/escape_test.go
+++ b/libgo/go/html/template/escape_test.go
@@ -538,7 +538,7 @@ func TestEscape(t *testing.T) {
{
"typed HTML in script",
`<button onclick="alert({{.W}})">`,
- `<button onclick="alert(&#34;&amp;iexcl;\u003cb class=\&#34;foo\&#34;\u003eHello\u003c/b\u003e, \u003ctextarea\u003eO&#39;World\u003c/textarea\u003e!&#34;)">`,
+ `<button onclick="alert(&#34;\u0026iexcl;\u003cb class=\&#34;foo\&#34;\u003eHello\u003c/b\u003e, \u003ctextarea\u003eO&#39;World\u003c/textarea\u003e!&#34;)">`,
},
{
"typed HTML in RCDATA",
@@ -655,6 +655,11 @@ func TestEscape(t *testing.T) {
for _, test := range tests {
tmpl := New(test.name)
tmpl = Must(tmpl.Parse(test.input))
+ // Check for bug 6459: Tree field was not set in Parse.
+ if tmpl.Tree != tmpl.text.Tree {
+ t.Errorf("%s: tree not set properly", test.name)
+ continue
+ }
b := new(bytes.Buffer)
if err := tmpl.Execute(b, data); err != nil {
t.Errorf("%s: template execution failed: %s", test.name, err)
@@ -673,6 +678,10 @@ func TestEscape(t *testing.T) {
t.Errorf("%s: escaped output for pointer: want\n\t%q\ngot\n\t%q", test.name, w, g)
continue
}
+ if tmpl.Tree != tmpl.text.Tree {
+ t.Errorf("%s: tree mismatch", test.name)
+ continue
+ }
}
}
diff --git a/libgo/go/html/template/js.go b/libgo/go/html/template/js.go
index a9740931fc2..d594e0ad711 100644
--- a/libgo/go/html/template/js.go
+++ b/libgo/go/html/template/js.go
@@ -341,7 +341,7 @@ var jsRegexpReplacementTable = []string{
'}': `\}`,
}
-// isJSIdentPart returns whether the given rune is a JS identifier part.
+// isJSIdentPart reports whether the given rune is a JS identifier part.
// It does not handle all the non-Latin letters, joiners, and combining marks,
// but it does handle every codepoint that can occur in a numeric literal or
// a keyword.
diff --git a/libgo/go/html/template/template.go b/libgo/go/html/template/template.go
index e183898d50f..11cc34a50a3 100644
--- a/libgo/go/html/template/template.go
+++ b/libgo/go/html/template/template.go
@@ -21,7 +21,9 @@ type Template struct {
// We could embed the text/template field, but it's safer not to because
// we need to keep our version of the name space and the underlying
// template's in sync.
- text *template.Template
+ text *template.Template
+ // The underlying template's parse tree, updated to be HTML-safe.
+ Tree *parse.Tree
*nameSpace // common to all associated templates
}
@@ -126,8 +128,10 @@ func (t *Template) Parse(src string) (*Template, error) {
if tmpl == nil {
tmpl = t.new(name)
}
+ // Restore our record of this text/template to its unescaped original state.
tmpl.escaped = false
tmpl.text = v
+ tmpl.Tree = v.Tree
}
return t, nil
}
@@ -149,6 +153,7 @@ func (t *Template) AddParseTree(name string, tree *parse.Tree) (*Template, error
ret := &Template{
false,
text,
+ text.Tree,
t.nameSpace,
}
t.set[name] = ret
@@ -176,6 +181,7 @@ func (t *Template) Clone() (*Template, error) {
ret := &Template{
false,
textClone,
+ textClone.Tree,
&nameSpace{
set: make(map[string]*Template),
},
@@ -186,15 +192,11 @@ func (t *Template) Clone() (*Template, error) {
if src == nil || src.escaped {
return nil, fmt.Errorf("html/template: cannot Clone %q after it has executed", t.Name())
}
- if x.Tree != nil {
- x.Tree = &parse.Tree{
- Name: x.Tree.Name,
- Root: x.Tree.Root.CopyList(),
- }
- }
+ x.Tree = x.Tree.Copy()
ret.set[name] = &Template{
false,
x,
+ x.Tree,
ret.nameSpace,
}
}
@@ -206,6 +208,7 @@ func New(name string) *Template {
tmpl := &Template{
false,
template.New(name),
+ nil,
&nameSpace{
set: make(map[string]*Template),
},
@@ -228,6 +231,7 @@ func (t *Template) new(name string) *Template {
tmpl := &Template{
false,
t.text.New(name),
+ nil,
t.nameSpace,
}
tmpl.set[name] = tmpl
diff --git a/libgo/go/html/template/transition.go b/libgo/go/html/template/transition.go
index 564eb202075..7f30a7ab8de 100644
--- a/libgo/go/html/template/transition.go
+++ b/libgo/go/html/template/transition.go
@@ -504,12 +504,12 @@ var elementNameMap = map[string]element{
"title": elementTitle,
}
-// asciiAlpha returns whether c is an ASCII letter.
+// asciiAlpha reports whether c is an ASCII letter.
func asciiAlpha(c byte) bool {
return 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z'
}
-// asciiAlphaNum returns whether c is an ASCII letter or digit.
+// asciiAlphaNum reports whether c is an ASCII letter or digit.
func asciiAlphaNum(c byte) bool {
return asciiAlpha(c) || '0' <= c && c <= '9'
}
diff --git a/libgo/go/image/color/color.go b/libgo/go/image/color/color.go
index 29a7b8a4001..ff596a76a36 100644
--- a/libgo/go/image/color/color.go
+++ b/libgo/go/image/color/color.go
@@ -253,13 +253,6 @@ func gray16Model(c Color) Color {
// Palette is a palette of colors.
type Palette []Color
-func diff(a, b uint32) uint32 {
- if a > b {
- return a - b
- }
- return b - a
-}
-
// Convert returns the palette color closest to c in Euclidean R,G,B space.
func (p Palette) Convert(c Color) Color {
if len(p) == 0 {
@@ -271,19 +264,20 @@ func (p Palette) Convert(c Color) Color {
// Index returns the index of the palette color closest to c in Euclidean
// R,G,B space.
func (p Palette) Index(c Color) int {
+ // A batch version of this computation is in image/draw/draw.go.
+
cr, cg, cb, _ := c.RGBA()
- // Shift by 1 bit to avoid potential uint32 overflow in sum-squared-difference.
- cr >>= 1
- cg >>= 1
- cb >>= 1
ret, bestSSD := 0, uint32(1<<32-1)
for i, v := range p {
vr, vg, vb, _ := v.RGBA()
- vr >>= 1
- vg >>= 1
- vb >>= 1
- dr, dg, db := diff(cr, vr), diff(cg, vg), diff(cb, vb)
- ssd := (dr * dr) + (dg * dg) + (db * db)
+ // We shift by 1 bit to avoid potential uint32 overflow in
+ // sum-squared-difference.
+ delta := (int32(cr) - int32(vr)) >> 1
+ ssd := uint32(delta * delta)
+ delta = (int32(cg) - int32(vg)) >> 1
+ ssd += uint32(delta * delta)
+ delta = (int32(cb) - int32(vb)) >> 1
+ ssd += uint32(delta * delta)
if ssd < bestSSD {
if ssd == 0 {
return i
diff --git a/libgo/go/image/color/palette/gen.go b/libgo/go/image/color/palette/gen.go
new file mode 100644
index 00000000000..f20c021de13
--- /dev/null
+++ b/libgo/go/image/color/palette/gen.go
@@ -0,0 +1,97 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+package main
+
+// This program generates palette.go. Invoke it as
+// go run gen.go | gofmt > palette.go
+
+import (
+ "fmt"
+)
+
+func main() {
+ fmt.Println("// generated by go run gen.go; DO NOT EDIT")
+ fmt.Println()
+ fmt.Println("// Package palette provides standard color palettes.")
+ fmt.Println("package palette")
+ fmt.Println()
+ fmt.Println(`import "image/color"`)
+ fmt.Println()
+ printPlan9()
+ printWebSafe()
+}
+
+func printPlan9() {
+ c, lines := [3]int{}, [256]string{}
+ for r, i := 0, 0; r != 4; r++ {
+ for v := 0; v != 4; v, i = v+1, i+16 {
+ for g, j := 0, v-r; g != 4; g++ {
+ for b := 0; b != 4; b, j = b+1, j+1 {
+ den := r
+ if g > den {
+ den = g
+ }
+ if b > den {
+ den = b
+ }
+ if den == 0 {
+ c[0] = 0x11 * v
+ c[1] = 0x11 * v
+ c[2] = 0x11 * v
+ } else {
+ num := 17 * (4*den + v)
+ c[0] = r * num / den
+ c[1] = g * num / den
+ c[2] = b * num / den
+ }
+ lines[i+(j&0x0f)] =
+ fmt.Sprintf("\tcolor.RGBA{0x%02x, 0x%02x, 0x%02x, 0xff},", c[0], c[1], c[2])
+ }
+ }
+ }
+ }
+ fmt.Println("// Plan9 is a 256-color palette that partitions the 24-bit RGB space")
+ fmt.Println("// into 4×4×4 subdivision, with 4 shades in each subcube. Compared to the")
+ fmt.Println("// WebSafe, the idea is to reduce the color resolution by dicing the")
+ fmt.Println("// color cube into fewer cells, and to use the extra space to increase the")
+ fmt.Println("// intensity resolution. This results in 16 gray shades (4 gray subcubes with")
+ fmt.Println("// 4 samples in each), 13 shades of each primary and secondary color (3")
+ fmt.Println("// subcubes with 4 samples plus black) and a reasonable selection of colors")
+ fmt.Println("// covering the rest of the color cube. The advantage is better representation")
+ fmt.Println("// of continuous tones.")
+ fmt.Println("//")
+ fmt.Println("// This palette was used in the Plan 9 Operating System, described at")
+ fmt.Println("// http://plan9.bell-labs.com/magic/man2html/6/color")
+ fmt.Println("var Plan9 = []color.Color{")
+ for _, line := range lines {
+ fmt.Println(line)
+ }
+ fmt.Println("}")
+ fmt.Println()
+}
+
+func printWebSafe() {
+ lines := [6 * 6 * 6]string{}
+ for r := 0; r < 6; r++ {
+ for g := 0; g < 6; g++ {
+ for b := 0; b < 6; b++ {
+ lines[36*r+6*g+b] =
+ fmt.Sprintf("\tcolor.RGBA{0x%02x, 0x%02x, 0x%02x, 0xff},", 0x33*r, 0x33*g, 0x33*b)
+ }
+ }
+ }
+ fmt.Println("// WebSafe is a 216-color palette that was popularized by early versions")
+ fmt.Println("// of Netscape Navigator. It is also known as the Netscape Color Cube.")
+ fmt.Println("//")
+ fmt.Println("// See http://en.wikipedia.org/wiki/Web_colors#Web-safe_colors for details.")
+ fmt.Println("var WebSafe = []color.Color{")
+ for _, line := range lines {
+ fmt.Println(line)
+ }
+ fmt.Println("}")
+ fmt.Println()
+}
diff --git a/libgo/go/image/color/palette/palette.go b/libgo/go/image/color/palette/palette.go
new file mode 100644
index 00000000000..3aba7401d1a
--- /dev/null
+++ b/libgo/go/image/color/palette/palette.go
@@ -0,0 +1,500 @@
+// generated by go run gen.go; DO NOT EDIT
+
+// Package palette provides standard color palettes.
+package palette
+
+import "image/color"
+
+// Plan9 is a 256-color palette that partitions the 24-bit RGB space
+// into 4×4×4 subdivision, with 4 shades in each subcube. Compared to the
+// WebSafe, the idea is to reduce the color resolution by dicing the
+// color cube into fewer cells, and to use the extra space to increase the
+// intensity resolution. This results in 16 gray shades (4 gray subcubes with
+// 4 samples in each), 13 shades of each primary and secondary color (3
+// subcubes with 4 samples plus black) and a reasonable selection of colors
+// covering the rest of the color cube. The advantage is better representation
+// of continuous tones.
+//
+// This palette was used in the Plan 9 Operating System, described at
+// http://plan9.bell-labs.com/magic/man2html/6/color
+var Plan9 = []color.Color{
+ color.RGBA{0x00, 0x00, 0x00, 0xff},
+ color.RGBA{0x00, 0x00, 0x44, 0xff},
+ color.RGBA{0x00, 0x00, 0x88, 0xff},
+ color.RGBA{0x00, 0x00, 0xcc, 0xff},
+ color.RGBA{0x00, 0x44, 0x00, 0xff},
+ color.RGBA{0x00, 0x44, 0x44, 0xff},
+ color.RGBA{0x00, 0x44, 0x88, 0xff},
+ color.RGBA{0x00, 0x44, 0xcc, 0xff},
+ color.RGBA{0x00, 0x88, 0x00, 0xff},
+ color.RGBA{0x00, 0x88, 0x44, 0xff},
+ color.RGBA{0x00, 0x88, 0x88, 0xff},
+ color.RGBA{0x00, 0x88, 0xcc, 0xff},
+ color.RGBA{0x00, 0xcc, 0x00, 0xff},
+ color.RGBA{0x00, 0xcc, 0x44, 0xff},
+ color.RGBA{0x00, 0xcc, 0x88, 0xff},
+ color.RGBA{0x00, 0xcc, 0xcc, 0xff},
+ color.RGBA{0x00, 0xdd, 0xdd, 0xff},
+ color.RGBA{0x11, 0x11, 0x11, 0xff},
+ color.RGBA{0x00, 0x00, 0x55, 0xff},
+ color.RGBA{0x00, 0x00, 0x99, 0xff},
+ color.RGBA{0x00, 0x00, 0xdd, 0xff},
+ color.RGBA{0x00, 0x55, 0x00, 0xff},
+ color.RGBA{0x00, 0x55, 0x55, 0xff},
+ color.RGBA{0x00, 0x4c, 0x99, 0xff},
+ color.RGBA{0x00, 0x49, 0xdd, 0xff},
+ color.RGBA{0x00, 0x99, 0x00, 0xff},
+ color.RGBA{0x00, 0x99, 0x4c, 0xff},
+ color.RGBA{0x00, 0x99, 0x99, 0xff},
+ color.RGBA{0x00, 0x93, 0xdd, 0xff},
+ color.RGBA{0x00, 0xdd, 0x00, 0xff},
+ color.RGBA{0x00, 0xdd, 0x49, 0xff},
+ color.RGBA{0x00, 0xdd, 0x93, 0xff},
+ color.RGBA{0x00, 0xee, 0x9e, 0xff},
+ color.RGBA{0x00, 0xee, 0xee, 0xff},
+ color.RGBA{0x22, 0x22, 0x22, 0xff},
+ color.RGBA{0x00, 0x00, 0x66, 0xff},
+ color.RGBA{0x00, 0x00, 0xaa, 0xff},
+ color.RGBA{0x00, 0x00, 0xee, 0xff},
+ color.RGBA{0x00, 0x66, 0x00, 0xff},
+ color.RGBA{0x00, 0x66, 0x66, 0xff},
+ color.RGBA{0x00, 0x55, 0xaa, 0xff},
+ color.RGBA{0x00, 0x4f, 0xee, 0xff},
+ color.RGBA{0x00, 0xaa, 0x00, 0xff},
+ color.RGBA{0x00, 0xaa, 0x55, 0xff},
+ color.RGBA{0x00, 0xaa, 0xaa, 0xff},
+ color.RGBA{0x00, 0x9e, 0xee, 0xff},
+ color.RGBA{0x00, 0xee, 0x00, 0xff},
+ color.RGBA{0x00, 0xee, 0x4f, 0xff},
+ color.RGBA{0x00, 0xff, 0x55, 0xff},
+ color.RGBA{0x00, 0xff, 0xaa, 0xff},
+ color.RGBA{0x00, 0xff, 0xff, 0xff},
+ color.RGBA{0x33, 0x33, 0x33, 0xff},
+ color.RGBA{0x00, 0x00, 0x77, 0xff},
+ color.RGBA{0x00, 0x00, 0xbb, 0xff},
+ color.RGBA{0x00, 0x00, 0xff, 0xff},
+ color.RGBA{0x00, 0x77, 0x00, 0xff},
+ color.RGBA{0x00, 0x77, 0x77, 0xff},
+ color.RGBA{0x00, 0x5d, 0xbb, 0xff},
+ color.RGBA{0x00, 0x55, 0xff, 0xff},
+ color.RGBA{0x00, 0xbb, 0x00, 0xff},
+ color.RGBA{0x00, 0xbb, 0x5d, 0xff},
+ color.RGBA{0x00, 0xbb, 0xbb, 0xff},
+ color.RGBA{0x00, 0xaa, 0xff, 0xff},
+ color.RGBA{0x00, 0xff, 0x00, 0xff},
+ color.RGBA{0x44, 0x00, 0x44, 0xff},
+ color.RGBA{0x44, 0x00, 0x88, 0xff},
+ color.RGBA{0x44, 0x00, 0xcc, 0xff},
+ color.RGBA{0x44, 0x44, 0x00, 0xff},
+ color.RGBA{0x44, 0x44, 0x44, 0xff},
+ color.RGBA{0x44, 0x44, 0x88, 0xff},
+ color.RGBA{0x44, 0x44, 0xcc, 0xff},
+ color.RGBA{0x44, 0x88, 0x00, 0xff},
+ color.RGBA{0x44, 0x88, 0x44, 0xff},
+ color.RGBA{0x44, 0x88, 0x88, 0xff},
+ color.RGBA{0x44, 0x88, 0xcc, 0xff},
+ color.RGBA{0x44, 0xcc, 0x00, 0xff},
+ color.RGBA{0x44, 0xcc, 0x44, 0xff},
+ color.RGBA{0x44, 0xcc, 0x88, 0xff},
+ color.RGBA{0x44, 0xcc, 0xcc, 0xff},
+ color.RGBA{0x44, 0x00, 0x00, 0xff},
+ color.RGBA{0x55, 0x00, 0x00, 0xff},
+ color.RGBA{0x55, 0x00, 0x55, 0xff},
+ color.RGBA{0x4c, 0x00, 0x99, 0xff},
+ color.RGBA{0x49, 0x00, 0xdd, 0xff},
+ color.RGBA{0x55, 0x55, 0x00, 0xff},
+ color.RGBA{0x55, 0x55, 0x55, 0xff},
+ color.RGBA{0x4c, 0x4c, 0x99, 0xff},
+ color.RGBA{0x49, 0x49, 0xdd, 0xff},
+ color.RGBA{0x4c, 0x99, 0x00, 0xff},
+ color.RGBA{0x4c, 0x99, 0x4c, 0xff},
+ color.RGBA{0x4c, 0x99, 0x99, 0xff},
+ color.RGBA{0x49, 0x93, 0xdd, 0xff},
+ color.RGBA{0x49, 0xdd, 0x00, 0xff},
+ color.RGBA{0x49, 0xdd, 0x49, 0xff},
+ color.RGBA{0x49, 0xdd, 0x93, 0xff},
+ color.RGBA{0x49, 0xdd, 0xdd, 0xff},
+ color.RGBA{0x4f, 0xee, 0xee, 0xff},
+ color.RGBA{0x66, 0x00, 0x00, 0xff},
+ color.RGBA{0x66, 0x00, 0x66, 0xff},
+ color.RGBA{0x55, 0x00, 0xaa, 0xff},
+ color.RGBA{0x4f, 0x00, 0xee, 0xff},
+ color.RGBA{0x66, 0x66, 0x00, 0xff},
+ color.RGBA{0x66, 0x66, 0x66, 0xff},
+ color.RGBA{0x55, 0x55, 0xaa, 0xff},
+ color.RGBA{0x4f, 0x4f, 0xee, 0xff},
+ color.RGBA{0x55, 0xaa, 0x00, 0xff},
+ color.RGBA{0x55, 0xaa, 0x55, 0xff},
+ color.RGBA{0x55, 0xaa, 0xaa, 0xff},
+ color.RGBA{0x4f, 0x9e, 0xee, 0xff},
+ color.RGBA{0x4f, 0xee, 0x00, 0xff},
+ color.RGBA{0x4f, 0xee, 0x4f, 0xff},
+ color.RGBA{0x4f, 0xee, 0x9e, 0xff},
+ color.RGBA{0x55, 0xff, 0xaa, 0xff},
+ color.RGBA{0x55, 0xff, 0xff, 0xff},
+ color.RGBA{0x77, 0x00, 0x00, 0xff},
+ color.RGBA{0x77, 0x00, 0x77, 0xff},
+ color.RGBA{0x5d, 0x00, 0xbb, 0xff},
+ color.RGBA{0x55, 0x00, 0xff, 0xff},
+ color.RGBA{0x77, 0x77, 0x00, 0xff},
+ color.RGBA{0x77, 0x77, 0x77, 0xff},
+ color.RGBA{0x5d, 0x5d, 0xbb, 0xff},
+ color.RGBA{0x55, 0x55, 0xff, 0xff},
+ color.RGBA{0x5d, 0xbb, 0x00, 0xff},
+ color.RGBA{0x5d, 0xbb, 0x5d, 0xff},
+ color.RGBA{0x5d, 0xbb, 0xbb, 0xff},
+ color.RGBA{0x55, 0xaa, 0xff, 0xff},
+ color.RGBA{0x55, 0xff, 0x00, 0xff},
+ color.RGBA{0x55, 0xff, 0x55, 0xff},
+ color.RGBA{0x88, 0x00, 0x88, 0xff},
+ color.RGBA{0x88, 0x00, 0xcc, 0xff},
+ color.RGBA{0x88, 0x44, 0x00, 0xff},
+ color.RGBA{0x88, 0x44, 0x44, 0xff},
+ color.RGBA{0x88, 0x44, 0x88, 0xff},
+ color.RGBA{0x88, 0x44, 0xcc, 0xff},
+ color.RGBA{0x88, 0x88, 0x00, 0xff},
+ color.RGBA{0x88, 0x88, 0x44, 0xff},
+ color.RGBA{0x88, 0x88, 0x88, 0xff},
+ color.RGBA{0x88, 0x88, 0xcc, 0xff},
+ color.RGBA{0x88, 0xcc, 0x00, 0xff},
+ color.RGBA{0x88, 0xcc, 0x44, 0xff},
+ color.RGBA{0x88, 0xcc, 0x88, 0xff},
+ color.RGBA{0x88, 0xcc, 0xcc, 0xff},
+ color.RGBA{0x88, 0x00, 0x00, 0xff},
+ color.RGBA{0x88, 0x00, 0x44, 0xff},
+ color.RGBA{0x99, 0x00, 0x4c, 0xff},
+ color.RGBA{0x99, 0x00, 0x99, 0xff},
+ color.RGBA{0x93, 0x00, 0xdd, 0xff},
+ color.RGBA{0x99, 0x4c, 0x00, 0xff},
+ color.RGBA{0x99, 0x4c, 0x4c, 0xff},
+ color.RGBA{0x99, 0x4c, 0x99, 0xff},
+ color.RGBA{0x93, 0x49, 0xdd, 0xff},
+ color.RGBA{0x99, 0x99, 0x00, 0xff},
+ color.RGBA{0x99, 0x99, 0x4c, 0xff},
+ color.RGBA{0x99, 0x99, 0x99, 0xff},
+ color.RGBA{0x93, 0x93, 0xdd, 0xff},
+ color.RGBA{0x93, 0xdd, 0x00, 0xff},
+ color.RGBA{0x93, 0xdd, 0x49, 0xff},
+ color.RGBA{0x93, 0xdd, 0x93, 0xff},
+ color.RGBA{0x93, 0xdd, 0xdd, 0xff},
+ color.RGBA{0x99, 0x00, 0x00, 0xff},
+ color.RGBA{0xaa, 0x00, 0x00, 0xff},
+ color.RGBA{0xaa, 0x00, 0x55, 0xff},
+ color.RGBA{0xaa, 0x00, 0xaa, 0xff},
+ color.RGBA{0x9e, 0x00, 0xee, 0xff},
+ color.RGBA{0xaa, 0x55, 0x00, 0xff},
+ color.RGBA{0xaa, 0x55, 0x55, 0xff},
+ color.RGBA{0xaa, 0x55, 0xaa, 0xff},
+ color.RGBA{0x9e, 0x4f, 0xee, 0xff},
+ color.RGBA{0xaa, 0xaa, 0x00, 0xff},
+ color.RGBA{0xaa, 0xaa, 0x55, 0xff},
+ color.RGBA{0xaa, 0xaa, 0xaa, 0xff},
+ color.RGBA{0x9e, 0x9e, 0xee, 0xff},
+ color.RGBA{0x9e, 0xee, 0x00, 0xff},
+ color.RGBA{0x9e, 0xee, 0x4f, 0xff},
+ color.RGBA{0x9e, 0xee, 0x9e, 0xff},
+ color.RGBA{0x9e, 0xee, 0xee, 0xff},
+ color.RGBA{0xaa, 0xff, 0xff, 0xff},
+ color.RGBA{0xbb, 0x00, 0x00, 0xff},
+ color.RGBA{0xbb, 0x00, 0x5d, 0xff},
+ color.RGBA{0xbb, 0x00, 0xbb, 0xff},
+ color.RGBA{0xaa, 0x00, 0xff, 0xff},
+ color.RGBA{0xbb, 0x5d, 0x00, 0xff},
+ color.RGBA{0xbb, 0x5d, 0x5d, 0xff},
+ color.RGBA{0xbb, 0x5d, 0xbb, 0xff},
+ color.RGBA{0xaa, 0x55, 0xff, 0xff},
+ color.RGBA{0xbb, 0xbb, 0x00, 0xff},
+ color.RGBA{0xbb, 0xbb, 0x5d, 0xff},
+ color.RGBA{0xbb, 0xbb, 0xbb, 0xff},
+ color.RGBA{0xaa, 0xaa, 0xff, 0xff},
+ color.RGBA{0xaa, 0xff, 0x00, 0xff},
+ color.RGBA{0xaa, 0xff, 0x55, 0xff},
+ color.RGBA{0xaa, 0xff, 0xaa, 0xff},
+ color.RGBA{0xcc, 0x00, 0xcc, 0xff},
+ color.RGBA{0xcc, 0x44, 0x00, 0xff},
+ color.RGBA{0xcc, 0x44, 0x44, 0xff},
+ color.RGBA{0xcc, 0x44, 0x88, 0xff},
+ color.RGBA{0xcc, 0x44, 0xcc, 0xff},
+ color.RGBA{0xcc, 0x88, 0x00, 0xff},
+ color.RGBA{0xcc, 0x88, 0x44, 0xff},
+ color.RGBA{0xcc, 0x88, 0x88, 0xff},
+ color.RGBA{0xcc, 0x88, 0xcc, 0xff},
+ color.RGBA{0xcc, 0xcc, 0x00, 0xff},
+ color.RGBA{0xcc, 0xcc, 0x44, 0xff},
+ color.RGBA{0xcc, 0xcc, 0x88, 0xff},
+ color.RGBA{0xcc, 0xcc, 0xcc, 0xff},
+ color.RGBA{0xcc, 0x00, 0x00, 0xff},
+ color.RGBA{0xcc, 0x00, 0x44, 0xff},
+ color.RGBA{0xcc, 0x00, 0x88, 0xff},
+ color.RGBA{0xdd, 0x00, 0x93, 0xff},
+ color.RGBA{0xdd, 0x00, 0xdd, 0xff},
+ color.RGBA{0xdd, 0x49, 0x00, 0xff},
+ color.RGBA{0xdd, 0x49, 0x49, 0xff},
+ color.RGBA{0xdd, 0x49, 0x93, 0xff},
+ color.RGBA{0xdd, 0x49, 0xdd, 0xff},
+ color.RGBA{0xdd, 0x93, 0x00, 0xff},
+ color.RGBA{0xdd, 0x93, 0x49, 0xff},
+ color.RGBA{0xdd, 0x93, 0x93, 0xff},
+ color.RGBA{0xdd, 0x93, 0xdd, 0xff},
+ color.RGBA{0xdd, 0xdd, 0x00, 0xff},
+ color.RGBA{0xdd, 0xdd, 0x49, 0xff},
+ color.RGBA{0xdd, 0xdd, 0x93, 0xff},
+ color.RGBA{0xdd, 0xdd, 0xdd, 0xff},
+ color.RGBA{0xdd, 0x00, 0x00, 0xff},
+ color.RGBA{0xdd, 0x00, 0x49, 0xff},
+ color.RGBA{0xee, 0x00, 0x4f, 0xff},
+ color.RGBA{0xee, 0x00, 0x9e, 0xff},
+ color.RGBA{0xee, 0x00, 0xee, 0xff},
+ color.RGBA{0xee, 0x4f, 0x00, 0xff},
+ color.RGBA{0xee, 0x4f, 0x4f, 0xff},
+ color.RGBA{0xee, 0x4f, 0x9e, 0xff},
+ color.RGBA{0xee, 0x4f, 0xee, 0xff},
+ color.RGBA{0xee, 0x9e, 0x00, 0xff},
+ color.RGBA{0xee, 0x9e, 0x4f, 0xff},
+ color.RGBA{0xee, 0x9e, 0x9e, 0xff},
+ color.RGBA{0xee, 0x9e, 0xee, 0xff},
+ color.RGBA{0xee, 0xee, 0x00, 0xff},
+ color.RGBA{0xee, 0xee, 0x4f, 0xff},
+ color.RGBA{0xee, 0xee, 0x9e, 0xff},
+ color.RGBA{0xee, 0xee, 0xee, 0xff},
+ color.RGBA{0xee, 0x00, 0x00, 0xff},
+ color.RGBA{0xff, 0x00, 0x00, 0xff},
+ color.RGBA{0xff, 0x00, 0x55, 0xff},
+ color.RGBA{0xff, 0x00, 0xaa, 0xff},
+ color.RGBA{0xff, 0x00, 0xff, 0xff},
+ color.RGBA{0xff, 0x55, 0x00, 0xff},
+ color.RGBA{0xff, 0x55, 0x55, 0xff},
+ color.RGBA{0xff, 0x55, 0xaa, 0xff},
+ color.RGBA{0xff, 0x55, 0xff, 0xff},
+ color.RGBA{0xff, 0xaa, 0x00, 0xff},
+ color.RGBA{0xff, 0xaa, 0x55, 0xff},
+ color.RGBA{0xff, 0xaa, 0xaa, 0xff},
+ color.RGBA{0xff, 0xaa, 0xff, 0xff},
+ color.RGBA{0xff, 0xff, 0x00, 0xff},
+ color.RGBA{0xff, 0xff, 0x55, 0xff},
+ color.RGBA{0xff, 0xff, 0xaa, 0xff},
+ color.RGBA{0xff, 0xff, 0xff, 0xff},
+}
+
+// WebSafe is a 216-color palette that was popularized by early versions
+// of Netscape Navigator. It is also known as the Netscape Color Cube.
+//
+// See http://en.wikipedia.org/wiki/Web_colors#Web-safe_colors for details.
+var WebSafe = []color.Color{
+ color.RGBA{0x00, 0x00, 0x00, 0xff},
+ color.RGBA{0x00, 0x00, 0x33, 0xff},
+ color.RGBA{0x00, 0x00, 0x66, 0xff},
+ color.RGBA{0x00, 0x00, 0x99, 0xff},
+ color.RGBA{0x00, 0x00, 0xcc, 0xff},
+ color.RGBA{0x00, 0x00, 0xff, 0xff},
+ color.RGBA{0x00, 0x33, 0x00, 0xff},
+ color.RGBA{0x00, 0x33, 0x33, 0xff},
+ color.RGBA{0x00, 0x33, 0x66, 0xff},
+ color.RGBA{0x00, 0x33, 0x99, 0xff},
+ color.RGBA{0x00, 0x33, 0xcc, 0xff},
+ color.RGBA{0x00, 0x33, 0xff, 0xff},
+ color.RGBA{0x00, 0x66, 0x00, 0xff},
+ color.RGBA{0x00, 0x66, 0x33, 0xff},
+ color.RGBA{0x00, 0x66, 0x66, 0xff},
+ color.RGBA{0x00, 0x66, 0x99, 0xff},
+ color.RGBA{0x00, 0x66, 0xcc, 0xff},
+ color.RGBA{0x00, 0x66, 0xff, 0xff},
+ color.RGBA{0x00, 0x99, 0x00, 0xff},
+ color.RGBA{0x00, 0x99, 0x33, 0xff},
+ color.RGBA{0x00, 0x99, 0x66, 0xff},
+ color.RGBA{0x00, 0x99, 0x99, 0xff},
+ color.RGBA{0x00, 0x99, 0xcc, 0xff},
+ color.RGBA{0x00, 0x99, 0xff, 0xff},
+ color.RGBA{0x00, 0xcc, 0x00, 0xff},
+ color.RGBA{0x00, 0xcc, 0x33, 0xff},
+ color.RGBA{0x00, 0xcc, 0x66, 0xff},
+ color.RGBA{0x00, 0xcc, 0x99, 0xff},
+ color.RGBA{0x00, 0xcc, 0xcc, 0xff},
+ color.RGBA{0x00, 0xcc, 0xff, 0xff},
+ color.RGBA{0x00, 0xff, 0x00, 0xff},
+ color.RGBA{0x00, 0xff, 0x33, 0xff},
+ color.RGBA{0x00, 0xff, 0x66, 0xff},
+ color.RGBA{0x00, 0xff, 0x99, 0xff},
+ color.RGBA{0x00, 0xff, 0xcc, 0xff},
+ color.RGBA{0x00, 0xff, 0xff, 0xff},
+ color.RGBA{0x33, 0x00, 0x00, 0xff},
+ color.RGBA{0x33, 0x00, 0x33, 0xff},
+ color.RGBA{0x33, 0x00, 0x66, 0xff},
+ color.RGBA{0x33, 0x00, 0x99, 0xff},
+ color.RGBA{0x33, 0x00, 0xcc, 0xff},
+ color.RGBA{0x33, 0x00, 0xff, 0xff},
+ color.RGBA{0x33, 0x33, 0x00, 0xff},
+ color.RGBA{0x33, 0x33, 0x33, 0xff},
+ color.RGBA{0x33, 0x33, 0x66, 0xff},
+ color.RGBA{0x33, 0x33, 0x99, 0xff},
+ color.RGBA{0x33, 0x33, 0xcc, 0xff},
+ color.RGBA{0x33, 0x33, 0xff, 0xff},
+ color.RGBA{0x33, 0x66, 0x00, 0xff},
+ color.RGBA{0x33, 0x66, 0x33, 0xff},
+ color.RGBA{0x33, 0x66, 0x66, 0xff},
+ color.RGBA{0x33, 0x66, 0x99, 0xff},
+ color.RGBA{0x33, 0x66, 0xcc, 0xff},
+ color.RGBA{0x33, 0x66, 0xff, 0xff},
+ color.RGBA{0x33, 0x99, 0x00, 0xff},
+ color.RGBA{0x33, 0x99, 0x33, 0xff},
+ color.RGBA{0x33, 0x99, 0x66, 0xff},
+ color.RGBA{0x33, 0x99, 0x99, 0xff},
+ color.RGBA{0x33, 0x99, 0xcc, 0xff},
+ color.RGBA{0x33, 0x99, 0xff, 0xff},
+ color.RGBA{0x33, 0xcc, 0x00, 0xff},
+ color.RGBA{0x33, 0xcc, 0x33, 0xff},
+ color.RGBA{0x33, 0xcc, 0x66, 0xff},
+ color.RGBA{0x33, 0xcc, 0x99, 0xff},
+ color.RGBA{0x33, 0xcc, 0xcc, 0xff},
+ color.RGBA{0x33, 0xcc, 0xff, 0xff},
+ color.RGBA{0x33, 0xff, 0x00, 0xff},
+ color.RGBA{0x33, 0xff, 0x33, 0xff},
+ color.RGBA{0x33, 0xff, 0x66, 0xff},
+ color.RGBA{0x33, 0xff, 0x99, 0xff},
+ color.RGBA{0x33, 0xff, 0xcc, 0xff},
+ color.RGBA{0x33, 0xff, 0xff, 0xff},
+ color.RGBA{0x66, 0x00, 0x00, 0xff},
+ color.RGBA{0x66, 0x00, 0x33, 0xff},
+ color.RGBA{0x66, 0x00, 0x66, 0xff},
+ color.RGBA{0x66, 0x00, 0x99, 0xff},
+ color.RGBA{0x66, 0x00, 0xcc, 0xff},
+ color.RGBA{0x66, 0x00, 0xff, 0xff},
+ color.RGBA{0x66, 0x33, 0x00, 0xff},
+ color.RGBA{0x66, 0x33, 0x33, 0xff},
+ color.RGBA{0x66, 0x33, 0x66, 0xff},
+ color.RGBA{0x66, 0x33, 0x99, 0xff},
+ color.RGBA{0x66, 0x33, 0xcc, 0xff},
+ color.RGBA{0x66, 0x33, 0xff, 0xff},
+ color.RGBA{0x66, 0x66, 0x00, 0xff},
+ color.RGBA{0x66, 0x66, 0x33, 0xff},
+ color.RGBA{0x66, 0x66, 0x66, 0xff},
+ color.RGBA{0x66, 0x66, 0x99, 0xff},
+ color.RGBA{0x66, 0x66, 0xcc, 0xff},
+ color.RGBA{0x66, 0x66, 0xff, 0xff},
+ color.RGBA{0x66, 0x99, 0x00, 0xff},
+ color.RGBA{0x66, 0x99, 0x33, 0xff},
+ color.RGBA{0x66, 0x99, 0x66, 0xff},
+ color.RGBA{0x66, 0x99, 0x99, 0xff},
+ color.RGBA{0x66, 0x99, 0xcc, 0xff},
+ color.RGBA{0x66, 0x99, 0xff, 0xff},
+ color.RGBA{0x66, 0xcc, 0x00, 0xff},
+ color.RGBA{0x66, 0xcc, 0x33, 0xff},
+ color.RGBA{0x66, 0xcc, 0x66, 0xff},
+ color.RGBA{0x66, 0xcc, 0x99, 0xff},
+ color.RGBA{0x66, 0xcc, 0xcc, 0xff},
+ color.RGBA{0x66, 0xcc, 0xff, 0xff},
+ color.RGBA{0x66, 0xff, 0x00, 0xff},
+ color.RGBA{0x66, 0xff, 0x33, 0xff},
+ color.RGBA{0x66, 0xff, 0x66, 0xff},
+ color.RGBA{0x66, 0xff, 0x99, 0xff},
+ color.RGBA{0x66, 0xff, 0xcc, 0xff},
+ color.RGBA{0x66, 0xff, 0xff, 0xff},
+ color.RGBA{0x99, 0x00, 0x00, 0xff},
+ color.RGBA{0x99, 0x00, 0x33, 0xff},
+ color.RGBA{0x99, 0x00, 0x66, 0xff},
+ color.RGBA{0x99, 0x00, 0x99, 0xff},
+ color.RGBA{0x99, 0x00, 0xcc, 0xff},
+ color.RGBA{0x99, 0x00, 0xff, 0xff},
+ color.RGBA{0x99, 0x33, 0x00, 0xff},
+ color.RGBA{0x99, 0x33, 0x33, 0xff},
+ color.RGBA{0x99, 0x33, 0x66, 0xff},
+ color.RGBA{0x99, 0x33, 0x99, 0xff},
+ color.RGBA{0x99, 0x33, 0xcc, 0xff},
+ color.RGBA{0x99, 0x33, 0xff, 0xff},
+ color.RGBA{0x99, 0x66, 0x00, 0xff},
+ color.RGBA{0x99, 0x66, 0x33, 0xff},
+ color.RGBA{0x99, 0x66, 0x66, 0xff},
+ color.RGBA{0x99, 0x66, 0x99, 0xff},
+ color.RGBA{0x99, 0x66, 0xcc, 0xff},
+ color.RGBA{0x99, 0x66, 0xff, 0xff},
+ color.RGBA{0x99, 0x99, 0x00, 0xff},
+ color.RGBA{0x99, 0x99, 0x33, 0xff},
+ color.RGBA{0x99, 0x99, 0x66, 0xff},
+ color.RGBA{0x99, 0x99, 0x99, 0xff},
+ color.RGBA{0x99, 0x99, 0xcc, 0xff},
+ color.RGBA{0x99, 0x99, 0xff, 0xff},
+ color.RGBA{0x99, 0xcc, 0x00, 0xff},
+ color.RGBA{0x99, 0xcc, 0x33, 0xff},
+ color.RGBA{0x99, 0xcc, 0x66, 0xff},
+ color.RGBA{0x99, 0xcc, 0x99, 0xff},
+ color.RGBA{0x99, 0xcc, 0xcc, 0xff},
+ color.RGBA{0x99, 0xcc, 0xff, 0xff},
+ color.RGBA{0x99, 0xff, 0x00, 0xff},
+ color.RGBA{0x99, 0xff, 0x33, 0xff},
+ color.RGBA{0x99, 0xff, 0x66, 0xff},
+ color.RGBA{0x99, 0xff, 0x99, 0xff},
+ color.RGBA{0x99, 0xff, 0xcc, 0xff},
+ color.RGBA{0x99, 0xff, 0xff, 0xff},
+ color.RGBA{0xcc, 0x00, 0x00, 0xff},
+ color.RGBA{0xcc, 0x00, 0x33, 0xff},
+ color.RGBA{0xcc, 0x00, 0x66, 0xff},
+ color.RGBA{0xcc, 0x00, 0x99, 0xff},
+ color.RGBA{0xcc, 0x00, 0xcc, 0xff},
+ color.RGBA{0xcc, 0x00, 0xff, 0xff},
+ color.RGBA{0xcc, 0x33, 0x00, 0xff},
+ color.RGBA{0xcc, 0x33, 0x33, 0xff},
+ color.RGBA{0xcc, 0x33, 0x66, 0xff},
+ color.RGBA{0xcc, 0x33, 0x99, 0xff},
+ color.RGBA{0xcc, 0x33, 0xcc, 0xff},
+ color.RGBA{0xcc, 0x33, 0xff, 0xff},
+ color.RGBA{0xcc, 0x66, 0x00, 0xff},
+ color.RGBA{0xcc, 0x66, 0x33, 0xff},
+ color.RGBA{0xcc, 0x66, 0x66, 0xff},
+ color.RGBA{0xcc, 0x66, 0x99, 0xff},
+ color.RGBA{0xcc, 0x66, 0xcc, 0xff},
+ color.RGBA{0xcc, 0x66, 0xff, 0xff},
+ color.RGBA{0xcc, 0x99, 0x00, 0xff},
+ color.RGBA{0xcc, 0x99, 0x33, 0xff},
+ color.RGBA{0xcc, 0x99, 0x66, 0xff},
+ color.RGBA{0xcc, 0x99, 0x99, 0xff},
+ color.RGBA{0xcc, 0x99, 0xcc, 0xff},
+ color.RGBA{0xcc, 0x99, 0xff, 0xff},
+ color.RGBA{0xcc, 0xcc, 0x00, 0xff},
+ color.RGBA{0xcc, 0xcc, 0x33, 0xff},
+ color.RGBA{0xcc, 0xcc, 0x66, 0xff},
+ color.RGBA{0xcc, 0xcc, 0x99, 0xff},
+ color.RGBA{0xcc, 0xcc, 0xcc, 0xff},
+ color.RGBA{0xcc, 0xcc, 0xff, 0xff},
+ color.RGBA{0xcc, 0xff, 0x00, 0xff},
+ color.RGBA{0xcc, 0xff, 0x33, 0xff},
+ color.RGBA{0xcc, 0xff, 0x66, 0xff},
+ color.RGBA{0xcc, 0xff, 0x99, 0xff},
+ color.RGBA{0xcc, 0xff, 0xcc, 0xff},
+ color.RGBA{0xcc, 0xff, 0xff, 0xff},
+ color.RGBA{0xff, 0x00, 0x00, 0xff},
+ color.RGBA{0xff, 0x00, 0x33, 0xff},
+ color.RGBA{0xff, 0x00, 0x66, 0xff},
+ color.RGBA{0xff, 0x00, 0x99, 0xff},
+ color.RGBA{0xff, 0x00, 0xcc, 0xff},
+ color.RGBA{0xff, 0x00, 0xff, 0xff},
+ color.RGBA{0xff, 0x33, 0x00, 0xff},
+ color.RGBA{0xff, 0x33, 0x33, 0xff},
+ color.RGBA{0xff, 0x33, 0x66, 0xff},
+ color.RGBA{0xff, 0x33, 0x99, 0xff},
+ color.RGBA{0xff, 0x33, 0xcc, 0xff},
+ color.RGBA{0xff, 0x33, 0xff, 0xff},
+ color.RGBA{0xff, 0x66, 0x00, 0xff},
+ color.RGBA{0xff, 0x66, 0x33, 0xff},
+ color.RGBA{0xff, 0x66, 0x66, 0xff},
+ color.RGBA{0xff, 0x66, 0x99, 0xff},
+ color.RGBA{0xff, 0x66, 0xcc, 0xff},
+ color.RGBA{0xff, 0x66, 0xff, 0xff},
+ color.RGBA{0xff, 0x99, 0x00, 0xff},
+ color.RGBA{0xff, 0x99, 0x33, 0xff},
+ color.RGBA{0xff, 0x99, 0x66, 0xff},
+ color.RGBA{0xff, 0x99, 0x99, 0xff},
+ color.RGBA{0xff, 0x99, 0xcc, 0xff},
+ color.RGBA{0xff, 0x99, 0xff, 0xff},
+ color.RGBA{0xff, 0xcc, 0x00, 0xff},
+ color.RGBA{0xff, 0xcc, 0x33, 0xff},
+ color.RGBA{0xff, 0xcc, 0x66, 0xff},
+ color.RGBA{0xff, 0xcc, 0x99, 0xff},
+ color.RGBA{0xff, 0xcc, 0xcc, 0xff},
+ color.RGBA{0xff, 0xcc, 0xff, 0xff},
+ color.RGBA{0xff, 0xff, 0x00, 0xff},
+ color.RGBA{0xff, 0xff, 0x33, 0xff},
+ color.RGBA{0xff, 0xff, 0x66, 0xff},
+ color.RGBA{0xff, 0xff, 0x99, 0xff},
+ color.RGBA{0xff, 0xff, 0xcc, 0xff},
+ color.RGBA{0xff, 0xff, 0xff, 0xff},
+}
diff --git a/libgo/go/image/decode_example_test.go b/libgo/go/image/decode_example_test.go
index aa5a841c0a5..21e90fea4f8 100644
--- a/libgo/go/image/decode_example_test.go
+++ b/libgo/go/image/decode_example_test.go
@@ -6,10 +6,11 @@
package image_test
import (
+ "encoding/base64"
"fmt"
"image"
"log"
- "os"
+ "strings"
// Package image/jpeg is not used explicitly in the code below,
// but is imported for its initialization side-effect, which allows
@@ -21,15 +22,15 @@ import (
)
func Example() {
- // Open the file.
- file, err := os.Open("testdata/video-001.jpeg")
- if err != nil {
- log.Fatal(err)
- }
- defer file.Close()
-
- // Decode the image.
- m, _, err := image.Decode(file)
+ // Decode the JPEG data. If reading from file, create a reader with
+ //
+ // reader, err := os.Open("testdata/video-001.q50.420.jpeg")
+ // if err != nil {
+ // log.Fatal(err)
+ // }
+ // defer reader.Close()
+ reader := base64.NewDecoder(base64.StdEncoding, strings.NewReader(data))
+ m, _, err := image.Decode(reader)
if err != nil {
log.Fatal(err)
}
@@ -60,20 +61,80 @@ func Example() {
}
// Output:
// bin red green blue alpha
- // 0x0000-0x0fff: 471 819 7596 0
- // 0x1000-0x1fff: 576 2892 726 0
- // 0x2000-0x2fff: 1038 2330 943 0
- // 0x3000-0x3fff: 883 2321 1014 0
- // 0x4000-0x4fff: 501 1295 525 0
- // 0x5000-0x5fff: 302 962 242 0
- // 0x6000-0x6fff: 219 358 150 0
- // 0x7000-0x7fff: 352 281 192 0
- // 0x8000-0x8fff: 3688 216 246 0
- // 0x9000-0x9fff: 2277 237 283 0
- // 0xa000-0xafff: 971 254 357 0
- // 0xb000-0xbfff: 317 306 429 0
- // 0xc000-0xcfff: 203 402 401 0
- // 0xd000-0xdfff: 256 394 241 0
- // 0xe000-0xefff: 378 343 173 0
- // 0xf000-0xffff: 3018 2040 1932 15450
+ // 0x0000-0x0fff: 353 759 7228 0
+ // 0x1000-0x1fff: 629 2944 1036 0
+ // 0x2000-0x2fff: 1075 2319 984 0
+ // 0x3000-0x3fff: 838 2291 988 0
+ // 0x4000-0x4fff: 540 1302 542 0
+ // 0x5000-0x5fff: 319 971 263 0
+ // 0x6000-0x6fff: 316 377 178 0
+ // 0x7000-0x7fff: 581 280 216 0
+ // 0x8000-0x8fff: 3457 228 274 0
+ // 0x9000-0x9fff: 2294 237 334 0
+ // 0xa000-0xafff: 938 283 370 0
+ // 0xb000-0xbfff: 322 338 401 0
+ // 0xc000-0xcfff: 229 386 295 0
+ // 0xd000-0xdfff: 263 416 281 0
+ // 0xe000-0xefff: 538 433 312 0
+ // 0xf000-0xffff: 2758 1886 1748 15450
}
+
+const data = `
+/9j/4AAQSkZJRgABAQIAHAAcAAD/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdA
+SFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2Nj
+Y2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wAARCABnAJYDASIAAhEBAxEB/8QA
+HwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIh
+MUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVW
+V1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXG
+x8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQF
+BgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAV
+YnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOE
+hYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq
+8vP09fb3+Pn6/9oADAMBAAIRAxEAPwDlwKMD0pwzSiuK57QzGDxS7D6in8Y5ximnAPUfSlcq4m3ilUYp
+2OKXHvRcVxnTtS7c07HNFK4DQPakC4PNOA+tOx70XAjK/So5gBGP94fzqfvUVx/qxx/EP51UXqRP4WSE
+cmgjilP3jSEZqS0IO/NGDnpUiocDg/McDjvV6HTPOdVWYgsM5KcfzzQ2JySM2jp6VYu7SWzmMUwG4cgj
+kMPUVBjjtTGtRu0Zopw+lFFxhinrGzuqqMsxAA9yaXFSRv5cqSEcIwYj6GpuZ30O30fSLKzhUpbpNMv3
+5XGTn29BV28jt7pPLuIVljPBBFVreYx+VbqAjycgt3x14zRcNOxGyVFHQkIc/wA61exyKLbuzjdZ046d
+ftEuTEw3Rk9SPT8P8Kpbea3tchbyVae4JkjbbGpGdwOM89Af6ViFTWUtGdcXoM2+woK1JtpNtTcoZt+l
+Jt7ZqTbRtouFyPFRXI/c9D94fzqzioLsfuD/ALw/nVReqIn8LJCOTSY+tSMOTmkIpXLRu+F0t5pJxPHG
+wjjUAuBjJJz1+laD6Pai+WaK9SBX6puzn6ZP+NV/Dkdtc6ZNbyAFwxLAHDYPv6VoQ21nPNEEiQGEFRtk
+Gf0NaWTOeW7Of8QwGG4MRZnEbYXPJwRnOR0zWNXW+KrqBLUWi5EjbWCgcAA9c/gRXKYqZaGlK/LqMH0F
+FLtHvRSNiYD2pSDTgpp6p0ywUHoTULXYxcktzrdCf7Xo8LP/AKyEmMNjJ46dfbFWJ5TDGNwB9lFUvDV9
+YrbfYGbyrjcWG88S57g+vtV26ZIvMlumKwwjLZ6V0WfU54yTvYwtbubea2WNWbzg4bYQeBgj8OtYeKhj
+u4y2HQxqxOD1xzxmrWAQCCGB6EGsaikndmsJxeiYzBo280/Z7UbayuaXGY5oIp+2lx9KLjIsVDeD/Rj/
+ALy/zq1t96r3y4tT/vL/ADq4P3kRP4WSleTSFKkkKoCW4GaqNcMxIjXj1pxjKT0FKrGC1Nrw3vGrKkYz
+5kTAr6455/HH510UdwPtRgWCbzF5+YYUf4Vwun39xpmoR3qASMmQUJwGU9Rnt/8AWrpbrxhb8/ZdOmaQ
+gAGZwFH5ZJrpVKVlY5ZYhN6kXiu2eO/ikZlIljAAB5yM549OawSOOlPuLqe+umuLqTfM4OSOAo7ADsKh
+hl/cRsTuJHPv7mlKi3sVTxNtGP20VJhThgSQaK52mnZnUqsWrpkyeUrr5pABOAPU1AGaXUCWJISHGPfP
+P8qL7BiKnsMg46H3qrbzupbj5mPTPTpXVSglG551SpzSsXJ4/MBUgYIxyKpySyGBYJriV1D7kRpCVH4V
+bSeNJ4xchni3DeqnBI+td7F4b0mKIRjT45VbktJlzk455+n6VtYzv2PNwFZWBHBGKVJDGVC54/nXQeMN
+NttLNkba1jgWVWDmM8bhg4/nzXLSSbXVj6fyNKUdNRp21RtIRJGrjuM0u3FQ2DbodvcEkfQmrW2vLqLl
+k0ejCXNFMj2/jQV9qkxSYNRcsZiq2oI32N2CkhWXJxwOe9XMcVt6hoPn6dFaW0wgRpNzvKDlz6+/0rai
+ryv2Jm9LHJai+ZRGCBjnr71ErdAxAY9B611t1Y2cunbbaOQ3FvKZI3UqGlZMbiWwfcfhV231iwvLSM3U
+lt5Uq52TuZG+hGMA12xXJGxxzjzybOQtNOvb5j9ktZJhnBIHyg+5PFX38JayqK/2eLJIBUTgkDA9q7ex
+itrSHFpGsUbndhRgc+g7VNIyfZJAoJZUbb3I46CtFJMylBo8sdWhmYMuCnylc9wef5VUT7+1chc5NS7h
+sUZO5RtIPUH3pkBDOxxxmqM9TQtn+WilhHfHaik43KTG3Z4IyPyrNVjGCsZ+dmwv6V3cXhSG8sYpJLud
+JJIwxChdoJGcYx/Wkg8DafA4knvLiQr/ALqj+VQpKw3FtnFFfvbiSMgZJ6/jXp2n3d9cQRBTFsKD96EP
+oOxPU/8A68VVtbbRtMVntbePKDLTSHJH/Aj/AEqHTvE66rq72VugMMcbSGTnL4wMAfjT5n0HyW3L+s6b
+baxaJBdzN+7bcrxkAhun0rz3VNCv7e7lgigknWI43xLu6jjIHTjtXqfkpPGVYsBkghTikgsYIN/lhgXb
+cxLkknp/ShczQ7xtY8vtEmhkj8yGRBuCnehUcnHcVtmwfJ/fQ8e7f/E12txZW91C0U6b42xlST2OR/Ko
+Bo1gM/uW55/1jf41nOipu7LhV5FZHIGzI6zwj/vr/Ck+yr3uYf8Ax7/CutbQdMb71tn/ALaN/jSf8I/p
+X/PoP++2/wAan6rAr6wzkWt0II+1Rc/7Lf4Vd1eeCSKBbdZDdShYoiZNoyfY10P/AAj2lf8APmP++2/x
+oPh/SjKspsozIuNrZORjp3qo0FHYPb3OZt7ae3SzjuItsiRSAgnccl/UA+3Q1yNjKLR4ZZYY5VD7tkv3
+WwO/+e1evPp9nI257aJm6bioz1z1+tY+s6Hplnot9PbWMMcqwOFcLyOO1bJWMZSTOPHi+9w3mosrlyd2
+9lCj02g9P/1e9a3hzxAbl2ikZRcdQueHHt7j864Y8Z4I4oRzG6urFWU5BHBB7HNJxTFGbR6he6Vpmtgm
+eLy5zwZI/lb8fX8azIvBUUTHdfSFP4QsYB/HNZ+k+KEnRY75hHOvAk6K/v7H9K6yyvlnQBmDZ6GsnzR0
+N0oy1RzOtaN/Y1tHNFO06u+zYy4I4Jzx9KKveJblXuordSGES5b6n/62PzorKVdp2LjQTVyWz8UWEWlq
+jSgyxfJt6EgdDzWTdeLIZGO7zHI/hVajGmWWP+PWL8qwlAIURrhpMAHHJA71pRcZrToZzcoEuo6heakA
+GHk245CZ6/X1qPTLq40q+W5t2QybSpDAkEEc55/zilk5k2r91eKhLDzWz2rpsczbbuemeD76fUNG865I
+MiysmQMZAAwa3a5j4ftu0ByP+fh/5CulkLLG7INzhSVHqe1Fh3uOoqn9qQQxyhndmHIxwOmSR2xQ13KD
+KoiBZOV9JBnt707MVy5RWdNdy7wRGf3bfMinnO1jg+vY03WXLaJO3mhQ20b0zwpYf0qlG7S7icrJs08U
+VwumgC+YiQyeVtZH567hzj8aSL949oGhE/2v5pJCDkksQwBHC4/+vXQ8LZ2uYxxCavY7us/xCcaBfn0h
+b+VP0bnSrb94ZMJgOecj1rl/GfidUE2k2gy5+SeQjgA/wj3rlas2jdao48qrjLAGkSKPk4Gc1WMj92I+
+lIJnU8OfxPWo5inBokmtQTmM4OOh71b0q6vbFmWCbaxHyqQGAP0PT8KhSTzVyo5ocSKA5VfTOTmqsmRd
+pl99XjPzThzK3zOeOSeveirNmkgg/fIpYsTkYORxRXmzlTjJqx6EVUcU7mhkKCzdAK59QI9zYxtG1fYU
+UVtgtmY4nZEa8Ak9aqFv3rfSiiu1nMeifDv/AJF+T/r4f+QrqqKKQwzQenNFFMCOKFIgNuThdoJ5OPSk
+ubeK6t3gnXdG4wwziiii/UTKMOg6dbzJLFE4dSCP3rEdeOM8805tDsGMvySgSsS6rM6gk9eAcUUVftZt
+3uyVGNthuq3Eei6DK8H7sRR7YuMgHtXkc8rzTNLM26RyWY+p70UVnLY0iEsUipG7rhZBlDkc1HgYoorM
+0HwyBXGeRjmrcUhMg2ghezd//rUUVcTKW5s2jZtY/QDaOKKKK8ip8bPRj8KP/9k=
+`
diff --git a/libgo/go/image/draw/draw.go b/libgo/go/image/draw/draw.go
index 56d30dd6f82..661230e7c59 100644
--- a/libgo/go/image/draw/draw.go
+++ b/libgo/go/image/draw/draw.go
@@ -16,6 +16,19 @@ import (
// m is the maximum color value returned by image.Color.RGBA.
const m = 1<<16 - 1
+// Image is an image.Image with a Set method to change a single pixel.
+type Image interface {
+ image.Image
+ Set(x, y int, c color.Color)
+}
+
+// Quantizer produces a palette for an image.
+type Quantizer interface {
+ // Quantize appends up to cap(p) - len(p) colors to p and returns the
+ // updated palette suitable for converting m to a paletted image.
+ Quantize(p color.Palette, m image.Image) color.Palette
+}
+
// Op is a Porter-Duff compositing operator.
type Op int
@@ -26,15 +39,31 @@ const (
Src
)
-// A draw.Image is an image.Image with a Set method to change a single pixel.
-type Image interface {
- image.Image
- Set(x, y int, c color.Color)
+// Draw implements the Drawer interface by calling the Draw function with this
+// Op.
+func (op Op) Draw(dst Image, r image.Rectangle, src image.Image, sp image.Point) {
+ DrawMask(dst, r, src, sp, nil, image.Point{}, op)
}
-// Draw calls DrawMask with a nil mask.
-func Draw(dst Image, r image.Rectangle, src image.Image, sp image.Point, op Op) {
- DrawMask(dst, r, src, sp, nil, image.ZP, op)
+// Drawer contains the Draw method.
+type Drawer interface {
+ // Draw aligns r.Min in dst with sp in src and then replaces the
+ // rectangle r in dst with the result of drawing src on dst.
+ Draw(dst Image, r image.Rectangle, src image.Image, sp image.Point)
+}
+
+// FloydSteinberg is a Drawer that is the Src Op with Floyd-Steinberg error
+// diffusion.
+var FloydSteinberg Drawer = floydSteinberg{}
+
+type floydSteinberg struct{}
+
+func (floydSteinberg) Draw(dst Image, r image.Rectangle, src image.Image, sp image.Point) {
+ clip(dst, &r, src, &sp, nil, nil)
+ if r.Empty() {
+ return
+ }
+ drawPaletted(dst, r, src, sp, true)
}
// clip clips r against each image's bounds (after translating into the
@@ -58,6 +87,17 @@ func clip(dst Image, r *image.Rectangle, src image.Image, sp *image.Point, mask
(*mp).Y += dy
}
+func processBackward(dst Image, r image.Rectangle, src image.Image, sp image.Point) bool {
+ return image.Image(dst) == src &&
+ r.Overlaps(r.Add(sp.Sub(r.Min))) &&
+ (sp.Y < r.Min.Y || (sp.Y == r.Min.Y && sp.X < r.Min.X))
+}
+
+// Draw calls DrawMask with a nil mask.
+func Draw(dst Image, r image.Rectangle, src image.Image, sp image.Point, op Op) {
+ DrawMask(dst, r, src, sp, nil, image.Point{}, op)
+}
+
// DrawMask aligns r.Min in dst with sp in src and mp in mask and then replaces the rectangle r
// in dst with the result of a Porter-Duff composition. A nil mask is treated as opaque.
func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point, mask image.Image, mp image.Point, op Op) {
@@ -67,7 +107,8 @@ func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point, mas
}
// Fast paths for special cases. If none of them apply, then we fall back to a general but slow implementation.
- if dst0, ok := dst.(*image.RGBA); ok {
+ switch dst0 := dst.(type) {
+ case *image.RGBA:
if op == Over {
if mask == nil {
switch src0 := src.(type) {
@@ -113,19 +154,20 @@ func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point, mas
}
drawRGBA(dst0, r, src, sp, mask, mp, op)
return
+ case *image.Paletted:
+ if op == Src && mask == nil && !processBackward(dst, r, src, sp) {
+ drawPaletted(dst0, r, src, sp, false)
+ }
}
x0, x1, dx := r.Min.X, r.Max.X, 1
y0, y1, dy := r.Min.Y, r.Max.Y, 1
- if image.Image(dst) == src && r.Overlaps(r.Add(sp.Sub(r.Min))) {
- // Rectangles overlap: process backward?
- if sp.Y < r.Min.Y || sp.Y == r.Min.Y && sp.X < r.Min.X {
- x0, x1, dx = x1-1, x0-1, -1
- y0, y1, dy = y1-1, y0-1, -1
- }
+ if processBackward(dst, r, src, sp) {
+ x0, x1, dx = x1-1, x0-1, -1
+ y0, y1, dy = y1-1, y0-1, -1
}
- var out *color.RGBA64
+ var out color.RGBA64
sy := sp.Y + y0 - r.Min.Y
my := mp.Y + y0 - r.Min.Y
for y := y0; y != y1; y, sy, my = y+dy, sy+dy, my+dy {
@@ -147,9 +189,6 @@ func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point, mas
dst.Set(x, y, src.At(sx, sy))
default:
sr, sg, sb, sa := src.At(sx, sy).RGBA()
- if out == nil {
- out = new(color.RGBA64)
- }
if op == Over {
dr, dg, db, da := dst.At(x, y).RGBA()
a := m - (sa * ma / m)
@@ -163,7 +202,11 @@ func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point, mas
out.B = uint16(sb * ma / m)
out.A = uint16(sa * ma / m)
}
- dst.Set(x, y, out)
+ // The third argument is &out instead of out (and out is
+ // declared outside of the inner loop) to avoid the implicit
+ // conversion to color.Color here allocating memory in the
+ // inner loop if sizeof(color.RGBA64) > sizeof(uintptr).
+ dst.Set(x, y, &out)
}
}
}
@@ -500,3 +543,131 @@ func drawRGBA(dst *image.RGBA, r image.Rectangle, src image.Image, sp image.Poin
i0 += dy * dst.Stride
}
}
+
+// clamp clamps i to the interval [0, 0xffff].
+func clamp(i int32) int32 {
+ if i < 0 {
+ return 0
+ }
+ if i > 0xffff {
+ return 0xffff
+ }
+ return i
+}
+
+func drawPaletted(dst Image, r image.Rectangle, src image.Image, sp image.Point, floydSteinberg bool) {
+ // TODO(nigeltao): handle the case where the dst and src overlap.
+ // Does it even make sense to try and do Floyd-Steinberg whilst
+ // walking the image backward (right-to-left bottom-to-top)?
+
+ // If dst is an *image.Paletted, we have a fast path for dst.Set and
+ // dst.At. The dst.Set equivalent is a batch version of the algorithm
+ // used by color.Palette's Index method in image/color/color.go, plus
+ // optional Floyd-Steinberg error diffusion.
+ palette, pix, stride := [][3]int32(nil), []byte(nil), 0
+ if p, ok := dst.(*image.Paletted); ok {
+ palette = make([][3]int32, len(p.Palette))
+ for i, col := range p.Palette {
+ r, g, b, _ := col.RGBA()
+ palette[i][0] = int32(r)
+ palette[i][1] = int32(g)
+ palette[i][2] = int32(b)
+ }
+ pix, stride = p.Pix[p.PixOffset(r.Min.X, r.Min.Y):], p.Stride
+ }
+
+ // quantErrorCurr and quantErrorNext are the Floyd-Steinberg quantization
+ // errors that have been propagated to the pixels in the current and next
+ // rows. The +2 simplifies calculation near the edges.
+ var quantErrorCurr, quantErrorNext [][3]int32
+ if floydSteinberg {
+ quantErrorCurr = make([][3]int32, r.Dx()+2)
+ quantErrorNext = make([][3]int32, r.Dx()+2)
+ }
+
+ // Loop over each source pixel.
+ out := color.RGBA64{A: 0xffff}
+ for y := 0; y != r.Dy(); y++ {
+ for x := 0; x != r.Dx(); x++ {
+ // er, eg and eb are the pixel's R,G,B values plus the
+ // optional Floyd-Steinberg error.
+ sr, sg, sb, _ := src.At(sp.X+x, sp.Y+y).RGBA()
+ er, eg, eb := int32(sr), int32(sg), int32(sb)
+ if floydSteinberg {
+ er = clamp(er + quantErrorCurr[x+1][0]/16)
+ eg = clamp(eg + quantErrorCurr[x+1][1]/16)
+ eb = clamp(eb + quantErrorCurr[x+1][2]/16)
+ }
+
+ if palette != nil {
+ // Find the closest palette color in Euclidean R,G,B space: the
+ // one that minimizes sum-squared-difference. We shift by 1 bit
+ // to avoid potential uint32 overflow in sum-squared-difference.
+ // TODO(nigeltao): consider smarter algorithms.
+ bestIndex, bestSSD := 0, uint32(1<<32-1)
+ for index, p := range palette {
+ delta := (er - p[0]) >> 1
+ ssd := uint32(delta * delta)
+ delta = (eg - p[1]) >> 1
+ ssd += uint32(delta * delta)
+ delta = (eb - p[2]) >> 1
+ ssd += uint32(delta * delta)
+ if ssd < bestSSD {
+ bestIndex, bestSSD = index, ssd
+ if ssd == 0 {
+ break
+ }
+ }
+ }
+ pix[y*stride+x] = byte(bestIndex)
+
+ if !floydSteinberg {
+ continue
+ }
+ er -= int32(palette[bestIndex][0])
+ eg -= int32(palette[bestIndex][1])
+ eb -= int32(palette[bestIndex][2])
+
+ } else {
+ out.R = uint16(er)
+ out.G = uint16(eg)
+ out.B = uint16(eb)
+ // The third argument is &out instead of out (and out is
+ // declared outside of the inner loop) to avoid the implicit
+ // conversion to color.Color here allocating memory in the
+ // inner loop if sizeof(color.RGBA64) > sizeof(uintptr).
+ dst.Set(r.Min.X+x, r.Min.Y+y, &out)
+
+ if !floydSteinberg {
+ continue
+ }
+ sr, sg, sb, _ = dst.At(r.Min.X+x, r.Min.Y+y).RGBA()
+ er -= int32(sr)
+ eg -= int32(sg)
+ eb -= int32(sb)
+ }
+
+ // Propagate the Floyd-Steinberg quantization error.
+ quantErrorNext[x+0][0] += er * 3
+ quantErrorNext[x+0][1] += eg * 3
+ quantErrorNext[x+0][2] += eb * 3
+ quantErrorNext[x+1][0] += er * 5
+ quantErrorNext[x+1][1] += eg * 5
+ quantErrorNext[x+1][2] += eb * 5
+ quantErrorNext[x+2][0] += er * 1
+ quantErrorNext[x+2][1] += eg * 1
+ quantErrorNext[x+2][2] += eb * 1
+ quantErrorCurr[x+2][0] += er * 7
+ quantErrorCurr[x+2][1] += eg * 7
+ quantErrorCurr[x+2][2] += eb * 7
+ }
+
+ // Recycle the quantization error buffers.
+ if floydSteinberg {
+ quantErrorCurr, quantErrorNext = quantErrorNext, quantErrorCurr
+ for i := range quantErrorNext {
+ quantErrorNext[i] = [3]int32{}
+ }
+ }
+ }
+}
diff --git a/libgo/go/image/draw/draw_test.go b/libgo/go/image/draw/draw_test.go
index 1db75b3e3f6..0dd7fbd479a 100644
--- a/libgo/go/image/draw/draw_test.go
+++ b/libgo/go/image/draw/draw_test.go
@@ -7,6 +7,8 @@ package draw
import (
"image"
"image/color"
+ "image/png"
+ "os"
"testing"
)
@@ -352,3 +354,76 @@ func TestFill(t *testing.T) {
check("whole")
}
}
+
+// TestFloydSteinbergCheckerboard tests that the result of Floyd-Steinberg
+// error diffusion of a uniform 50% gray source image with a black-and-white
+// palette is a checkerboard pattern.
+func TestFloydSteinbergCheckerboard(t *testing.T) {
+ b := image.Rect(0, 0, 640, 480)
+ // We can't represent 50% exactly, but 0x7fff / 0xffff is close enough.
+ src := &image.Uniform{color.Gray16{0x7fff}}
+ dst := image.NewPaletted(b, color.Palette{color.Black, color.White})
+ FloydSteinberg.Draw(dst, b, src, image.Point{})
+ nErr := 0
+ for y := b.Min.Y; y < b.Max.Y; y++ {
+ for x := b.Min.X; x < b.Max.X; x++ {
+ got := dst.Pix[dst.PixOffset(x, y)]
+ want := uint8(x+y) % 2
+ if got != want {
+ t.Errorf("at (%d, %d): got %d, want %d", x, y, got, want)
+ if nErr++; nErr == 10 {
+ t.Fatal("there may be more errors")
+ }
+ }
+ }
+ }
+}
+
+// embeddedPaletted is an Image that behaves like an *image.Paletted but whose
+// type is not *image.Paletted.
+type embeddedPaletted struct {
+ *image.Paletted
+}
+
+// TestPaletted tests that the drawPaletted function behaves the same
+// regardless of whether dst is an *image.Paletted.
+func TestPaletted(t *testing.T) {
+ f, err := os.Open("../testdata/video-001.png")
+ if err != nil {
+ t.Fatalf("open: %v", err)
+ }
+ defer f.Close()
+ src, err := png.Decode(f)
+ if err != nil {
+ t.Fatalf("decode: %v", err)
+ }
+ b := src.Bounds()
+
+ cgaPalette := color.Palette{
+ color.RGBA{0x00, 0x00, 0x00, 0xff},
+ color.RGBA{0x55, 0xff, 0xff, 0xff},
+ color.RGBA{0xff, 0x55, 0xff, 0xff},
+ color.RGBA{0xff, 0xff, 0xff, 0xff},
+ }
+ drawers := map[string]Drawer{
+ "src": Src,
+ "floyd-steinberg": FloydSteinberg,
+ }
+
+loop:
+ for dName, d := range drawers {
+ dst0 := image.NewPaletted(b, cgaPalette)
+ dst1 := image.NewPaletted(b, cgaPalette)
+ d.Draw(dst0, b, src, image.Point{})
+ d.Draw(embeddedPaletted{dst1}, b, src, image.Point{})
+ for y := b.Min.Y; y < b.Max.Y; y++ {
+ for x := b.Min.X; x < b.Max.X; x++ {
+ if !eq(dst0.At(x, y), dst1.At(x, y)) {
+ t.Errorf("%s: at (%d, %d), %v versus %v",
+ dName, x, y, dst0.At(x, y), dst1.At(x, y))
+ continue loop
+ }
+ }
+ }
+ }
+}
diff --git a/libgo/go/image/format.go b/libgo/go/image/format.go
index 36635bcc538..3668de4e685 100644
--- a/libgo/go/image/format.go
+++ b/libgo/go/image/format.go
@@ -47,7 +47,7 @@ func asReader(r io.Reader) reader {
return bufio.NewReader(r)
}
-// Match returns whether magic matches b. Magic may contain "?" wildcards.
+// Match reports whether magic matches b. Magic may contain "?" wildcards.
func match(magic string, b []byte) bool {
if len(magic) != len(b) {
return false
@@ -73,7 +73,7 @@ func sniff(r reader) format {
// Decode decodes an image that has been encoded in a registered format.
// The string returned is the format name used during format registration.
-// Format registration is typically done by the init method of the codec-
+// Format registration is typically done by an init function in the codec-
// specific package.
func Decode(r io.Reader) (Image, string, error) {
rr := asReader(r)
@@ -88,7 +88,7 @@ func Decode(r io.Reader) (Image, string, error) {
// DecodeConfig decodes the color model and dimensions of an image that has
// been encoded in a registered format. The string returned is the format name
// used during format registration. Format registration is typically done by
-// the init method of the codec-specific package.
+// an init function in the codec-specific package.
func DecodeConfig(r io.Reader) (Config, string, error) {
rr := asReader(r)
f := sniff(rr)
diff --git a/libgo/go/image/geom.go b/libgo/go/image/geom.go
index e123483314c..6ebaf67da84 100644
--- a/libgo/go/image/geom.go
+++ b/libgo/go/image/geom.go
@@ -38,7 +38,7 @@ func (p Point) Div(k int) Point {
return Point{p.X / k, p.Y / k}
}
-// In returns whether p is in r.
+// In reports whether p is in r.
func (p Point) In(r Rectangle) bool {
return r.Min.X <= p.X && p.X < r.Max.X &&
r.Min.Y <= p.Y && p.Y < r.Max.Y
@@ -60,7 +60,7 @@ func (p Point) Mod(r Rectangle) Point {
return p.Add(r.Min)
}
-// Eq returns whether p and q are equal.
+// Eq reports whether p and q are equal.
func (p Point) Eq(q Point) bool {
return p.X == q.X && p.Y == q.Y
}
@@ -179,24 +179,24 @@ func (r Rectangle) Union(s Rectangle) Rectangle {
return r
}
-// Empty returns whether the rectangle contains no points.
+// Empty reports whether the rectangle contains no points.
func (r Rectangle) Empty() bool {
return r.Min.X >= r.Max.X || r.Min.Y >= r.Max.Y
}
-// Eq returns whether r and s are equal.
+// Eq reports whether r and s are equal.
func (r Rectangle) Eq(s Rectangle) bool {
return r.Min.X == s.Min.X && r.Min.Y == s.Min.Y &&
r.Max.X == s.Max.X && r.Max.Y == s.Max.Y
}
-// Overlaps returns whether r and s have a non-empty intersection.
+// Overlaps reports whether r and s have a non-empty intersection.
func (r Rectangle) Overlaps(s Rectangle) bool {
return r.Min.X < s.Max.X && s.Min.X < r.Max.X &&
r.Min.Y < s.Max.Y && s.Min.Y < r.Max.Y
}
-// In returns whether every point in r is in s.
+// In reports whether every point in r is in s.
func (r Rectangle) In(s Rectangle) bool {
if r.Empty() {
return true
diff --git a/libgo/go/image/gif/reader.go b/libgo/go/image/gif/reader.go
index 8e8531f9b6b..8b0298a29f3 100644
--- a/libgo/go/image/gif/reader.go
+++ b/libgo/go/image/gif/reader.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Package gif implements a GIF image decoder.
+// Package gif implements a GIF image decoder and encoder.
//
// The GIF specification is at http://www.w3.org/Graphics/GIF/spec-gif89a.txt.
package gif
@@ -20,6 +20,7 @@ import (
var (
errNotEnough = errors.New("gif: not enough image data")
errTooMuch = errors.New("gif: too much image data")
+ errBadPixel = errors.New("gif: invalid pixel value")
)
// If the io.Reader does not also have ReadByte, then decode will introduce its own buffering.
@@ -189,6 +190,7 @@ func (d *decoder) decode(r io.Reader, configOnly bool) error {
// A wonderfully Go-like piece of magic.
br := &blockReader{r: d.r}
lzwr := lzw.NewReader(br, lzw.LSB, int(litWidth))
+ defer lzwr.Close()
if _, err = io.ReadFull(lzwr, m.Pix); err != nil {
if err != io.ErrUnexpectedEOF {
return err
@@ -210,6 +212,15 @@ func (d *decoder) decode(r io.Reader, configOnly bool) error {
return errTooMuch
}
+ // Check that the color indexes are inside the palette.
+ if len(m.Palette) < 256 {
+ for _, pixel := range m.Pix {
+ if int(pixel) >= len(m.Palette) {
+ return errBadPixel
+ }
+ }
+ }
+
// Undo the interlacing if necessary.
if d.imageFields&ifInterlace != 0 {
uninterlace(m)
diff --git a/libgo/go/image/gif/reader_test.go b/libgo/go/image/gif/reader_test.go
index dcc6c6dd3e4..09867132d3d 100644
--- a/libgo/go/image/gif/reader_test.go
+++ b/libgo/go/image/gif/reader_test.go
@@ -9,16 +9,16 @@ import (
"testing"
)
-func TestDecode(t *testing.T) {
- // header and trailer are parts of a valid 2x1 GIF image.
- const (
- header = "GIF89a" +
- "\x02\x00\x01\x00" + // width=2, height=1
- "\x80\x00\x00" + // headerFields=(a color map of 2 pixels), backgroundIndex, aspect
- "\x10\x20\x30\x40\x50\x60" // the color map, also known as a palette
- trailer = "\x3b"
- )
+// header, palette and trailer are parts of a valid 2x1 GIF image.
+const (
+ headerStr = "GIF89a" +
+ "\x02\x00\x01\x00" + // width=2, height=1
+ "\x80\x00\x00" // headerFields=(a color map of 2 pixels), backgroundIndex, aspect
+ paletteStr = "\x10\x20\x30\x40\x50\x60" // the color map, also known as a palette
+ trailerStr = "\x3b"
+)
+func TestDecode(t *testing.T) {
// lzwEncode returns an LZW encoding (with 2-bit literals) of n zeroes.
lzwEncode := func(n int) []byte {
b := &bytes.Buffer{}
@@ -41,7 +41,8 @@ func TestDecode(t *testing.T) {
}
for _, tc := range testCases {
b := &bytes.Buffer{}
- b.WriteString(header)
+ b.WriteString(headerStr)
+ b.WriteString(paletteStr)
// Write an image with bounds 2x1 but tc.nPix pixels. If tc.nPix != 2
// then this should result in an invalid GIF image. First, write a
// magic 0x2c (image descriptor) byte, bounds=(0,0)-(2,1), a flags
@@ -60,7 +61,7 @@ func TestDecode(t *testing.T) {
b.WriteString("\x01\x02") // A 1-byte payload with an 0x02 byte.
}
b.WriteByte(0x00) // An empty block signifies the end of the image data.
- b.WriteString(trailer)
+ b.WriteString(trailerStr)
got, err := Decode(b)
if err != tc.wantErr {
@@ -114,7 +115,7 @@ func try(t *testing.T, b []byte, want string) {
}
func TestBounds(t *testing.T) {
- // make a local copy of testGIF
+ // Make a local copy of testGIF.
gif := make([]byte, len(testGIF))
copy(gif, testGIF)
// Make the bounds too big, just by one.
@@ -136,3 +137,61 @@ func TestBounds(t *testing.T) {
}
try(t, gif, want)
}
+
+func TestNoPalette(t *testing.T) {
+ b := &bytes.Buffer{}
+
+ // Manufacture a GIF with no palette, so any pixel at all
+ // will be invalid.
+ b.WriteString(headerStr[:len(headerStr)-3])
+ b.WriteString("\x00\x00\x00") // No global palette.
+
+ // Image descriptor: 2x1, no local palette.
+ b.WriteString("\x2c\x00\x00\x00\x00\x02\x00\x01\x00\x00\x02")
+
+ // Encode the pixels: neither is in range, because there is no palette.
+ pix := []byte{0, 128}
+ enc := &bytes.Buffer{}
+ w := lzw.NewWriter(enc, lzw.LSB, 2)
+ w.Write(pix)
+ w.Close()
+ b.WriteByte(byte(len(enc.Bytes())))
+ b.Write(enc.Bytes())
+ b.WriteByte(0x00) // An empty block signifies the end of the image data.
+
+ b.WriteString(trailerStr)
+
+ try(t, b.Bytes(), "gif: invalid pixel value")
+}
+
+func TestPixelOutsidePaletteRange(t *testing.T) {
+ for _, pval := range []byte{0, 1, 2, 3, 255} {
+ b := &bytes.Buffer{}
+
+ // Manufacture a GIF with a 2 color palette.
+ b.WriteString(headerStr)
+ b.WriteString(paletteStr)
+
+ // Image descriptor: 2x1, no local palette.
+ b.WriteString("\x2c\x00\x00\x00\x00\x02\x00\x01\x00\x00\x02")
+
+ // Encode the pixels; some pvals trigger the expected error.
+ pix := []byte{pval, pval}
+ enc := &bytes.Buffer{}
+ w := lzw.NewWriter(enc, lzw.LSB, 2)
+ w.Write(pix)
+ w.Close()
+ b.WriteByte(byte(len(enc.Bytes())))
+ b.Write(enc.Bytes())
+ b.WriteByte(0x00) // An empty block signifies the end of the image data.
+
+ b.WriteString(trailerStr)
+
+ // No error expected, unless the pixels are beyond the 2 color palette.
+ want := ""
+ if pval >= 2 {
+ want = "gif: invalid pixel value"
+ }
+ try(t, b.Bytes(), want)
+ }
+}
diff --git a/libgo/go/image/gif/writer.go b/libgo/go/image/gif/writer.go
new file mode 100644
index 00000000000..15cd40fadf6
--- /dev/null
+++ b/libgo/go/image/gif/writer.go
@@ -0,0 +1,323 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package gif
+
+import (
+ "bufio"
+ "compress/lzw"
+ "errors"
+ "image"
+ "image/color"
+ "image/color/palette"
+ "image/draw"
+ "io"
+)
+
+// Graphic control extension fields.
+const (
+ gcLabel = 0xF9
+ gcBlockSize = 0x04
+)
+
+var log2Lookup = [8]int{2, 4, 8, 16, 32, 64, 128, 256}
+
+func log2(x int) int {
+ for i, v := range log2Lookup {
+ if x <= v {
+ return i
+ }
+ }
+ return -1
+}
+
+// Little-endian.
+func writeUint16(b []uint8, u uint16) {
+ b[0] = uint8(u)
+ b[1] = uint8(u >> 8)
+}
+
+// writer is a buffered writer.
+type writer interface {
+ Flush() error
+ io.Writer
+ io.ByteWriter
+}
+
+// encoder encodes an image to the GIF format.
+type encoder struct {
+ // w is the writer to write to. err is the first error encountered during
+ // writing. All attempted writes after the first error become no-ops.
+ w writer
+ err error
+ // g is a reference to the data that is being encoded.
+ g *GIF
+ // buf is a scratch buffer. It must be at least 768 so we can write the color map.
+ buf [1024]byte
+}
+
+// blockWriter writes the block structure of GIF image data, which
+// comprises (n, (n bytes)) blocks, with 1 <= n <= 255. It is the
+// writer given to the LZW encoder, which is thus immune to the
+// blocking.
+type blockWriter struct {
+ e *encoder
+}
+
+func (b blockWriter) Write(data []byte) (int, error) {
+ if b.e.err != nil {
+ return 0, b.e.err
+ }
+ if len(data) == 0 {
+ return 0, nil
+ }
+ total := 0
+ for total < len(data) {
+ n := copy(b.e.buf[1:256], data[total:])
+ total += n
+ b.e.buf[0] = uint8(n)
+
+ n, b.e.err = b.e.w.Write(b.e.buf[:n+1])
+ if b.e.err != nil {
+ return 0, b.e.err
+ }
+ }
+ return total, b.e.err
+}
+
+func (e *encoder) flush() {
+ if e.err != nil {
+ return
+ }
+ e.err = e.w.Flush()
+}
+
+func (e *encoder) write(p []byte) {
+ if e.err != nil {
+ return
+ }
+ _, e.err = e.w.Write(p)
+}
+
+func (e *encoder) writeByte(b byte) {
+ if e.err != nil {
+ return
+ }
+ e.err = e.w.WriteByte(b)
+}
+
+func (e *encoder) writeHeader() {
+ if e.err != nil {
+ return
+ }
+ _, e.err = io.WriteString(e.w, "GIF89a")
+ if e.err != nil {
+ return
+ }
+
+ pm := e.g.Image[0]
+ // Logical screen width and height.
+ writeUint16(e.buf[0:2], uint16(pm.Bounds().Dx()))
+ writeUint16(e.buf[2:4], uint16(pm.Bounds().Dy()))
+ e.write(e.buf[:4])
+
+ // All frames have a local color table, so a global color table
+ // is not needed.
+ e.buf[0] = 0x00
+ e.buf[1] = 0x00 // Background Color Index.
+ e.buf[2] = 0x00 // Pixel Aspect Ratio.
+ e.write(e.buf[:3])
+
+ // Add animation info if necessary.
+ if len(e.g.Image) > 1 {
+ e.buf[0] = 0x21 // Extension Introducer.
+ e.buf[1] = 0xff // Application Label.
+ e.buf[2] = 0x0b // Block Size.
+ e.write(e.buf[:3])
+ _, e.err = io.WriteString(e.w, "NETSCAPE2.0") // Application Identifier.
+ if e.err != nil {
+ return
+ }
+ e.buf[0] = 0x03 // Block Size.
+ e.buf[1] = 0x01 // Sub-block Index.
+ writeUint16(e.buf[2:4], uint16(e.g.LoopCount))
+ e.buf[4] = 0x00 // Block Terminator.
+ e.write(e.buf[:5])
+ }
+}
+
+func (e *encoder) writeColorTable(p color.Palette, size int) {
+ if e.err != nil {
+ return
+ }
+
+ for i := 0; i < log2Lookup[size]; i++ {
+ if i < len(p) {
+ r, g, b, _ := p[i].RGBA()
+ e.buf[3*i+0] = uint8(r >> 8)
+ e.buf[3*i+1] = uint8(g >> 8)
+ e.buf[3*i+2] = uint8(b >> 8)
+ } else {
+ // Pad with black.
+ e.buf[3*i+0] = 0x00
+ e.buf[3*i+1] = 0x00
+ e.buf[3*i+2] = 0x00
+ }
+ }
+ e.write(e.buf[:3*log2Lookup[size]])
+}
+
+func (e *encoder) writeImageBlock(pm *image.Paletted, delay int) {
+ if e.err != nil {
+ return
+ }
+
+ if len(pm.Palette) == 0 {
+ e.err = errors.New("gif: cannot encode image block with empty palette")
+ return
+ }
+
+ b := pm.Bounds()
+ if b.Dx() >= 1<<16 || b.Dy() >= 1<<16 || b.Min.X < 0 || b.Min.X >= 1<<16 || b.Min.Y < 0 || b.Min.Y >= 1<<16 {
+ e.err = errors.New("gif: image block is too large to encode")
+ return
+ }
+
+ transparentIndex := -1
+ for i, c := range pm.Palette {
+ if _, _, _, a := c.RGBA(); a == 0 {
+ transparentIndex = i
+ break
+ }
+ }
+
+ if delay > 0 || transparentIndex != -1 {
+ e.buf[0] = sExtension // Extension Introducer.
+ e.buf[1] = gcLabel // Graphic Control Label.
+ e.buf[2] = gcBlockSize // Block Size.
+ if transparentIndex != -1 {
+ e.buf[3] = 0x01
+ } else {
+ e.buf[3] = 0x00
+ }
+ writeUint16(e.buf[4:6], uint16(delay)) // Delay Time (1/100ths of a second)
+
+ // Transparent color index.
+ if transparentIndex != -1 {
+ e.buf[6] = uint8(transparentIndex)
+ } else {
+ e.buf[6] = 0x00
+ }
+ e.buf[7] = 0x00 // Block Terminator.
+ e.write(e.buf[:8])
+ }
+ e.buf[0] = sImageDescriptor
+ writeUint16(e.buf[1:3], uint16(b.Min.X))
+ writeUint16(e.buf[3:5], uint16(b.Min.Y))
+ writeUint16(e.buf[5:7], uint16(b.Dx()))
+ writeUint16(e.buf[7:9], uint16(b.Dy()))
+ e.write(e.buf[:9])
+
+ paddedSize := log2(len(pm.Palette)) // Size of Local Color Table: 2^(1+n).
+ // Interlacing is not supported.
+ e.writeByte(0x80 | uint8(paddedSize))
+
+ // Local Color Table.
+ e.writeColorTable(pm.Palette, paddedSize)
+
+ litWidth := paddedSize + 1
+ if litWidth < 2 {
+ litWidth = 2
+ }
+ e.writeByte(uint8(litWidth)) // LZW Minimum Code Size.
+
+ lzww := lzw.NewWriter(blockWriter{e: e}, lzw.LSB, litWidth)
+ _, e.err = lzww.Write(pm.Pix)
+ if e.err != nil {
+ lzww.Close()
+ return
+ }
+ lzww.Close()
+ e.writeByte(0x00) // Block Terminator.
+}
+
+// Options are the encoding parameters.
+type Options struct {
+ // NumColors is the maximum number of colors used in the image.
+ // It ranges from 1 to 256.
+ NumColors int
+
+ // Quantizer is used to produce a palette with size NumColors.
+ // palette.Plan9 is used in place of a nil Quantizer.
+ Quantizer draw.Quantizer
+
+ // Drawer is used to convert the source image to the desired palette.
+ // draw.FloydSteinberg is used in place of a nil Drawer.
+ Drawer draw.Drawer
+}
+
+// EncodeAll writes the images in g to w in GIF format with the
+// given loop count and delay between frames.
+func EncodeAll(w io.Writer, g *GIF) error {
+ if len(g.Image) == 0 {
+ return errors.New("gif: must provide at least one image")
+ }
+
+ if len(g.Image) != len(g.Delay) {
+ return errors.New("gif: mismatched image and delay lengths")
+ }
+ if g.LoopCount < 0 {
+ g.LoopCount = 0
+ }
+
+ e := encoder{g: g}
+ if ww, ok := w.(writer); ok {
+ e.w = ww
+ } else {
+ e.w = bufio.NewWriter(w)
+ }
+
+ e.writeHeader()
+ for i, pm := range g.Image {
+ e.writeImageBlock(pm, g.Delay[i])
+ }
+ e.writeByte(sTrailer)
+ e.flush()
+ return e.err
+}
+
+// Encode writes the Image m to w in GIF format.
+func Encode(w io.Writer, m image.Image, o *Options) error {
+ // Check for bounds and size restrictions.
+ b := m.Bounds()
+ if b.Dx() >= 1<<16 || b.Dy() >= 1<<16 {
+ return errors.New("gif: image is too large to encode")
+ }
+
+ opts := Options{}
+ if o != nil {
+ opts = *o
+ }
+ if opts.NumColors < 1 || 256 < opts.NumColors {
+ opts.NumColors = 256
+ }
+ if opts.Drawer == nil {
+ opts.Drawer = draw.FloydSteinberg
+ }
+
+ pm, ok := m.(*image.Paletted)
+ if !ok || len(pm.Palette) > opts.NumColors {
+ // TODO: Pick a better sub-sample of the Plan 9 palette.
+ pm = image.NewPaletted(b, palette.Plan9[:opts.NumColors])
+ if opts.Quantizer != nil {
+ pm.Palette = opts.Quantizer.Quantize(make(color.Palette, 0, opts.NumColors), m)
+ }
+ opts.Drawer.Draw(pm, b, m, image.ZP)
+ }
+
+ return EncodeAll(w, &GIF{
+ Image: []*image.Paletted{pm},
+ Delay: []int{0},
+ })
+}
diff --git a/libgo/go/image/gif/writer_test.go b/libgo/go/image/gif/writer_test.go
new file mode 100644
index 00000000000..c1ada769c2c
--- /dev/null
+++ b/libgo/go/image/gif/writer_test.go
@@ -0,0 +1,204 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package gif
+
+import (
+ "bytes"
+ "image"
+ "image/color"
+ _ "image/png"
+ "io/ioutil"
+ "math/rand"
+ "os"
+ "testing"
+)
+
+func readImg(filename string) (image.Image, error) {
+ f, err := os.Open(filename)
+ if err != nil {
+ return nil, err
+ }
+ defer f.Close()
+ m, _, err := image.Decode(f)
+ return m, err
+}
+
+func readGIF(filename string) (*GIF, error) {
+ f, err := os.Open(filename)
+ if err != nil {
+ return nil, err
+ }
+ defer f.Close()
+ return DecodeAll(f)
+}
+
+func delta(u0, u1 uint32) int64 {
+ d := int64(u0) - int64(u1)
+ if d < 0 {
+ return -d
+ }
+ return d
+}
+
+// averageDelta returns the average delta in RGB space. The two images must
+// have the same bounds.
+func averageDelta(m0, m1 image.Image) int64 {
+ b := m0.Bounds()
+ var sum, n int64
+ for y := b.Min.Y; y < b.Max.Y; y++ {
+ for x := b.Min.X; x < b.Max.X; x++ {
+ c0 := m0.At(x, y)
+ c1 := m1.At(x, y)
+ r0, g0, b0, _ := c0.RGBA()
+ r1, g1, b1, _ := c1.RGBA()
+ sum += delta(r0, r1)
+ sum += delta(g0, g1)
+ sum += delta(b0, b1)
+ n += 3
+ }
+ }
+ return sum / n
+}
+
+var testCase = []struct {
+ filename string
+ tolerance int64
+}{
+ {"../testdata/video-001.png", 1 << 12},
+ {"../testdata/video-001.gif", 0},
+ {"../testdata/video-001.interlaced.gif", 0},
+}
+
+func TestWriter(t *testing.T) {
+ for _, tc := range testCase {
+ m0, err := readImg(tc.filename)
+ if err != nil {
+ t.Error(tc.filename, err)
+ continue
+ }
+ var buf bytes.Buffer
+ err = Encode(&buf, m0, nil)
+ if err != nil {
+ t.Error(tc.filename, err)
+ continue
+ }
+ m1, err := Decode(&buf)
+ if err != nil {
+ t.Error(tc.filename, err)
+ continue
+ }
+ if m0.Bounds() != m1.Bounds() {
+ t.Errorf("%s, bounds differ: %v and %v", tc.filename, m0.Bounds(), m1.Bounds())
+ continue
+ }
+ // Compare the average delta to the tolerance level.
+ avgDelta := averageDelta(m0, m1)
+ if avgDelta > tc.tolerance {
+ t.Errorf("%s: average delta is too high. expected: %d, got %d", tc.filename, tc.tolerance, avgDelta)
+ continue
+ }
+ }
+}
+
+var frames = []string{
+ "../testdata/video-001.gif",
+ "../testdata/video-005.gray.gif",
+}
+
+func TestEncodeAll(t *testing.T) {
+ g0 := &GIF{
+ Image: make([]*image.Paletted, len(frames)),
+ Delay: make([]int, len(frames)),
+ LoopCount: 5,
+ }
+ for i, f := range frames {
+ m, err := readGIF(f)
+ if err != nil {
+ t.Error(f, err)
+ }
+ g0.Image[i] = m.Image[0]
+ }
+ var buf bytes.Buffer
+ if err := EncodeAll(&buf, g0); err != nil {
+ t.Fatal("EncodeAll:", err)
+ }
+ g1, err := DecodeAll(&buf)
+ if err != nil {
+ t.Fatal("DecodeAll:", err)
+ }
+ if g0.LoopCount != g1.LoopCount {
+ t.Errorf("loop counts differ: %d and %d", g0.LoopCount, g1.LoopCount)
+ }
+ for i := range g0.Image {
+ m0, m1 := g0.Image[i], g1.Image[i]
+ if m0.Bounds() != m1.Bounds() {
+ t.Errorf("%s, bounds differ: %v and %v", frames[i], m0.Bounds(), m1.Bounds())
+ }
+ d0, d1 := g0.Delay[i], g1.Delay[i]
+ if d0 != d1 {
+ t.Errorf("%s: delay values differ: %d and %d", frames[i], d0, d1)
+ }
+ }
+
+ g1.Delay = make([]int, 1)
+ if err := EncodeAll(ioutil.Discard, g1); err == nil {
+ t.Error("expected error from mismatched delay and image slice lengths")
+ }
+ if err := EncodeAll(ioutil.Discard, &GIF{}); err == nil {
+ t.Error("expected error from providing empty gif")
+ }
+}
+
+func BenchmarkEncode(b *testing.B) {
+ b.StopTimer()
+
+ bo := image.Rect(0, 0, 640, 480)
+ rnd := rand.New(rand.NewSource(123))
+
+ // Restrict to a 256-color paletted image to avoid quantization path.
+ palette := make(color.Palette, 256)
+ for i := range palette {
+ palette[i] = color.RGBA{
+ uint8(rnd.Intn(256)),
+ uint8(rnd.Intn(256)),
+ uint8(rnd.Intn(256)),
+ 255,
+ }
+ }
+ img := image.NewPaletted(image.Rect(0, 0, 640, 480), palette)
+ for y := bo.Min.Y; y < bo.Max.Y; y++ {
+ for x := bo.Min.X; x < bo.Max.X; x++ {
+ img.Set(x, y, palette[rnd.Intn(256)])
+ }
+ }
+
+ b.SetBytes(640 * 480 * 4)
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ Encode(ioutil.Discard, img, nil)
+ }
+}
+
+func BenchmarkQuantizedEncode(b *testing.B) {
+ b.StopTimer()
+ img := image.NewRGBA(image.Rect(0, 0, 640, 480))
+ bo := img.Bounds()
+ rnd := rand.New(rand.NewSource(123))
+ for y := bo.Min.Y; y < bo.Max.Y; y++ {
+ for x := bo.Min.X; x < bo.Max.X; x++ {
+ img.SetRGBA(x, y, color.RGBA{
+ uint8(rnd.Intn(256)),
+ uint8(rnd.Intn(256)),
+ uint8(rnd.Intn(256)),
+ 255,
+ })
+ }
+ }
+ b.SetBytes(640 * 480 * 4)
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ Encode(ioutil.Discard, img, nil)
+ }
+}
diff --git a/libgo/go/image/image.go b/libgo/go/image/image.go
index 03ac6060671..32a89ef34ca 100644
--- a/libgo/go/image/image.go
+++ b/libgo/go/image/image.go
@@ -126,7 +126,7 @@ func (p *RGBA) SubImage(r Rectangle) Image {
}
}
-// Opaque scans the entire image and returns whether or not it is fully opaque.
+// Opaque scans the entire image and reports whether it is fully opaque.
func (p *RGBA) Opaque() bool {
if p.Rect.Empty() {
return true
@@ -234,7 +234,7 @@ func (p *RGBA64) SubImage(r Rectangle) Image {
}
}
-// Opaque scans the entire image and returns whether or not it is fully opaque.
+// Opaque scans the entire image and reports whether it is fully opaque.
func (p *RGBA64) Opaque() bool {
if p.Rect.Empty() {
return true
@@ -329,7 +329,7 @@ func (p *NRGBA) SubImage(r Rectangle) Image {
}
}
-// Opaque scans the entire image and returns whether or not it is fully opaque.
+// Opaque scans the entire image and reports whether it is fully opaque.
func (p *NRGBA) Opaque() bool {
if p.Rect.Empty() {
return true
@@ -437,7 +437,7 @@ func (p *NRGBA64) SubImage(r Rectangle) Image {
}
}
-// Opaque scans the entire image and returns whether or not it is fully opaque.
+// Opaque scans the entire image and reports whether it is fully opaque.
func (p *NRGBA64) Opaque() bool {
if p.Rect.Empty() {
return true
@@ -525,7 +525,7 @@ func (p *Alpha) SubImage(r Rectangle) Image {
}
}
-// Opaque scans the entire image and returns whether or not it is fully opaque.
+// Opaque scans the entire image and reports whether it is fully opaque.
func (p *Alpha) Opaque() bool {
if p.Rect.Empty() {
return true
@@ -616,7 +616,7 @@ func (p *Alpha16) SubImage(r Rectangle) Image {
}
}
-// Opaque scans the entire image and returns whether or not it is fully opaque.
+// Opaque scans the entire image and reports whether it is fully opaque.
func (p *Alpha16) Opaque() bool {
if p.Rect.Empty() {
return true
@@ -704,7 +704,7 @@ func (p *Gray) SubImage(r Rectangle) Image {
}
}
-// Opaque scans the entire image and returns whether or not it is fully opaque.
+// Opaque scans the entire image and reports whether it is fully opaque.
func (p *Gray) Opaque() bool {
return true
}
@@ -782,7 +782,7 @@ func (p *Gray16) SubImage(r Rectangle) Image {
}
}
-// Opaque scans the entire image and returns whether or not it is fully opaque.
+// Opaque scans the entire image and reports whether it is fully opaque.
func (p *Gray16) Opaque() bool {
return true
}
@@ -873,7 +873,7 @@ func (p *Paletted) SubImage(r Rectangle) Image {
}
}
-// Opaque scans the entire image and returns whether or not it is fully opaque.
+// Opaque scans the entire image and reports whether it is fully opaque.
func (p *Paletted) Opaque() bool {
var present [256]bool
i0, i1 := 0, p.Rect.Dx()
diff --git a/libgo/go/image/jpeg/dct_test.go b/libgo/go/image/jpeg/dct_test.go
index 7389f7e4fe8..845e7588789 100644
--- a/libgo/go/image/jpeg/dct_test.go
+++ b/libgo/go/image/jpeg/dct_test.go
@@ -90,7 +90,7 @@ func TestDCT(t *testing.T) {
}
}
-// differ returns whether any pair-wise elements in b0 and b1 differ by 2 or
+// differ reports whether any pair-wise elements in b0 and b1 differ by 2 or
// more. That tolerance is because there isn't a single definitive decoding of
// a given JPEG image, even before the YCbCr to RGB conversion; implementations
// can have different IDCT rounding errors.
diff --git a/libgo/go/image/jpeg/reader.go b/libgo/go/image/jpeg/reader.go
index 862d8dc1b21..356d56220a7 100644
--- a/libgo/go/image/jpeg/reader.go
+++ b/libgo/go/image/jpeg/reader.go
@@ -174,10 +174,10 @@ func (d *decoder) processSOF(n int) error {
// values for the Cr and Cb components must be (1, 1).
if i == 0 {
if hv != 0x11 && hv != 0x21 && hv != 0x22 && hv != 0x12 {
- return UnsupportedError("luma downsample ratio")
+ return UnsupportedError("luma/chroma downsample ratio")
}
} else if hv != 0x11 {
- return UnsupportedError("chroma downsample ratio")
+ return UnsupportedError("luma/chroma downsample ratio")
}
}
return nil
diff --git a/libgo/go/image/names.go b/libgo/go/image/names.go
index 04ee2cfb47c..8985f492140 100644
--- a/libgo/go/image/names.go
+++ b/libgo/go/image/names.go
@@ -41,7 +41,7 @@ func (c *Uniform) Bounds() Rectangle { return Rectangle{Point{-1e9, -1e9}, Point
func (c *Uniform) At(x, y int) color.Color { return c.C }
-// Opaque scans the entire image and returns whether or not it is fully opaque.
+// Opaque scans the entire image and reports whether it is fully opaque.
func (c *Uniform) Opaque() bool {
_, _, _, a := c.C.RGBA()
return a == 0xffff
diff --git a/libgo/go/io/io.go b/libgo/go/io/io.go
index ec2cd6056fe..f7073ffc068 100644
--- a/libgo/go/io/io.go
+++ b/libgo/go/io/io.go
@@ -91,10 +91,14 @@ type Closer interface {
// Seek sets the offset for the next Read or Write to offset,
// interpreted according to whence: 0 means relative to the origin of
// the file, 1 means relative to the current offset, and 2 means
-// relative to the end. Seek returns the new offset and an Error, if
+// relative to the end. Seek returns the new offset and an error, if
// any.
+//
+// Seeking to a negative offset is an error. Seeking to any positive
+// offset is legal, but the behavior of subsequent I/O operations on
+// the underlying object is implementation-dependent.
type Seeker interface {
- Seek(offset int64, whence int) (ret int64, err error)
+ Seek(offset int64, whence int) (int64, error)
}
// ReadWriter is the interface that groups the basic Read and Write methods.
@@ -329,20 +333,20 @@ func CopyN(dst Writer, src Reader, n int64) (written int64, err error) {
// Because Copy is defined to read from src until EOF, it does
// not treat an EOF from Read as an error to be reported.
//
-// If dst implements the ReaderFrom interface,
-// the copy is implemented by calling dst.ReadFrom(src).
-// Otherwise, if src implements the WriterTo interface,
+// If src implements the WriterTo interface,
// the copy is implemented by calling src.WriteTo(dst).
+// Otherwise, if dst implements the ReaderFrom interface,
+// the copy is implemented by calling dst.ReadFrom(src).
func Copy(dst Writer, src Reader) (written int64, err error) {
- // If the writer has a ReadFrom method, use it to do the copy.
+ // If the reader has a WriteTo method, use it to do the copy.
// Avoids an allocation and a copy.
- if rt, ok := dst.(ReaderFrom); ok {
- return rt.ReadFrom(src)
- }
- // Similarly, if the reader has a WriteTo method, use it to do the copy.
if wt, ok := src.(WriterTo); ok {
return wt.WriteTo(dst)
}
+ // Similarly, if the writer has a ReadFrom method, use it to do the copy.
+ if rt, ok := dst.(ReaderFrom); ok {
+ return rt.ReadFrom(src)
+ }
buf := make([]byte, 32*1024)
for {
nr, er := src.Read(buf)
@@ -426,7 +430,7 @@ func (s *SectionReader) Read(p []byte) (n int, err error) {
var errWhence = errors.New("Seek: invalid whence")
var errOffset = errors.New("Seek: invalid offset")
-func (s *SectionReader) Seek(offset int64, whence int) (ret int64, err error) {
+func (s *SectionReader) Seek(offset int64, whence int) (int64, error) {
switch whence {
default:
return 0, errWhence
@@ -437,7 +441,7 @@ func (s *SectionReader) Seek(offset int64, whence int) (ret int64, err error) {
case 2:
offset += s.limit
}
- if offset < s.base || offset > s.limit {
+ if offset < s.base {
return 0, errOffset
}
s.off = offset
diff --git a/libgo/go/io/io_test.go b/libgo/go/io/io_test.go
index 1bc451e444a..bd7a82f17b6 100644
--- a/libgo/go/io/io_test.go
+++ b/libgo/go/io/io_test.go
@@ -52,6 +52,32 @@ func TestCopyWriteTo(t *testing.T) {
}
}
+// Version of bytes.Buffer that checks whether WriteTo was called or not
+type writeToChecker struct {
+ bytes.Buffer
+ writeToCalled bool
+}
+
+func (wt *writeToChecker) WriteTo(w Writer) (int64, error) {
+ wt.writeToCalled = true
+ return wt.Buffer.WriteTo(w)
+}
+
+// It's preferable to choose WriterTo over ReaderFrom, since a WriterTo can issue one large write,
+// while the ReaderFrom must read until EOF, potentially allocating when running out of buffer.
+// Make sure that we choose WriterTo when both are implemented.
+func TestCopyPriority(t *testing.T) {
+ rb := new(writeToChecker)
+ wb := new(bytes.Buffer)
+ rb.WriteString("hello, world.")
+ Copy(wb, rb)
+ if wb.String() != "hello, world." {
+ t.Errorf("Copy did not work properly")
+ } else if !rb.writeToCalled {
+ t.Errorf("WriteTo was not prioritized over ReadFrom")
+ }
+}
+
func TestCopyN(t *testing.T) {
rb := new(Buffer)
wb := new(Buffer)
@@ -234,7 +260,7 @@ func TestTeeReader(t *testing.T) {
}
}
-func TestSectionReader_ReadAt(tst *testing.T) {
+func TestSectionReader_ReadAt(t *testing.T) {
dat := "a long sample data, 1234567890"
tests := []struct {
data string
@@ -256,12 +282,40 @@ func TestSectionReader_ReadAt(tst *testing.T) {
{data: dat, off: 3, n: len(dat) / 2, bufLen: len(dat)/2 - 2, at: 2, exp: dat[5 : 5+len(dat)/2-2], err: nil},
{data: dat, off: 3, n: len(dat) / 2, bufLen: len(dat)/2 + 2, at: 2, exp: dat[5 : 5+len(dat)/2-2], err: EOF},
}
- for i, t := range tests {
- r := strings.NewReader(t.data)
- s := NewSectionReader(r, int64(t.off), int64(t.n))
- buf := make([]byte, t.bufLen)
- if n, err := s.ReadAt(buf, int64(t.at)); n != len(t.exp) || string(buf[:n]) != t.exp || err != t.err {
- tst.Fatalf("%d: ReadAt(%d) = %q, %v; expected %q, %v", i, t.at, buf[:n], err, t.exp, t.err)
+ for i, tt := range tests {
+ r := strings.NewReader(tt.data)
+ s := NewSectionReader(r, int64(tt.off), int64(tt.n))
+ buf := make([]byte, tt.bufLen)
+ if n, err := s.ReadAt(buf, int64(tt.at)); n != len(tt.exp) || string(buf[:n]) != tt.exp || err != tt.err {
+ t.Fatalf("%d: ReadAt(%d) = %q, %v; expected %q, %v", i, tt.at, buf[:n], err, tt.exp, tt.err)
}
}
}
+
+func TestSectionReader_Seek(t *testing.T) {
+ // Verifies that NewSectionReader's Seeker behaves like bytes.NewReader (which is like strings.NewReader)
+ br := bytes.NewReader([]byte("foo"))
+ sr := NewSectionReader(br, 0, int64(len("foo")))
+
+ for whence := 0; whence <= 2; whence++ {
+ for offset := int64(-3); offset <= 4; offset++ {
+ brOff, brErr := br.Seek(offset, whence)
+ srOff, srErr := sr.Seek(offset, whence)
+ if (brErr != nil) != (srErr != nil) || brOff != srOff {
+ t.Errorf("For whence %d, offset %d: bytes.Reader.Seek = (%v, %v) != SectionReader.Seek = (%v, %v)",
+ whence, offset, brOff, brErr, srErr, srOff)
+ }
+ }
+ }
+
+ // And verify we can just seek past the end and get an EOF
+ got, err := sr.Seek(100, 0)
+ if err != nil || got != 100 {
+ t.Errorf("Seek = %v, %v; want 100, nil", got, err)
+ }
+
+ n, err := sr.Read(make([]byte, 10))
+ if n != 0 || err != EOF {
+ t.Errorf("Read = %v, %v; want 0, EOF", n, err)
+ }
+}
diff --git a/libgo/go/io/ioutil/ioutil.go b/libgo/go/io/ioutil/ioutil.go
index 6b395c69bdc..b2508b7899e 100644
--- a/libgo/go/io/ioutil/ioutil.go
+++ b/libgo/go/io/ioutil/ioutil.go
@@ -78,10 +78,12 @@ func WriteFile(filename string, data []byte, perm os.FileMode) error {
return err
}
n, err := f.Write(data)
- f.Close()
if err == nil && n < len(data) {
err = io.ErrShortWrite
}
+ if err1 := f.Close(); err == nil {
+ err = err1
+ }
return err
}
@@ -130,6 +132,10 @@ func (devNull) Write(p []byte) (int, error) {
return len(p), nil
}
+func (devNull) WriteString(s string) (int, error) {
+ return len(s), nil
+}
+
func (devNull) ReadFrom(r io.Reader) (n int64, err error) {
buf := blackHole()
defer blackHolePut(buf)
diff --git a/libgo/go/io/pipe.go b/libgo/go/io/pipe.go
index f3f0f175706..f65354a7f25 100644
--- a/libgo/go/io/pipe.go
+++ b/libgo/go/io/pipe.go
@@ -74,6 +74,10 @@ func (p *pipe) write(b []byte) (n int, err error) {
p.l.Lock()
defer p.l.Unlock()
+ if p.werr != nil {
+ err = ErrClosedPipe
+ return
+ }
p.data = b
p.rwait.Signal()
for {
diff --git a/libgo/go/io/pipe_test.go b/libgo/go/io/pipe_test.go
index 7718151b0e5..b16e6530693 100644
--- a/libgo/go/io/pipe_test.go
+++ b/libgo/go/io/pipe_test.go
@@ -268,3 +268,35 @@ func TestWriteNil(t *testing.T) {
ReadFull(r, b[0:2])
r.Close()
}
+
+func TestWriteAfterWriterClose(t *testing.T) {
+ r, w := Pipe()
+
+ done := make(chan bool)
+ var writeErr error
+ go func() {
+ _, err := w.Write([]byte("hello"))
+ if err != nil {
+ t.Errorf("got error: %q; expected none", err)
+ }
+ w.Close()
+ _, writeErr = w.Write([]byte("world"))
+ done <- true
+ }()
+
+ buf := make([]byte, 100)
+ var result string
+ n, err := ReadFull(r, buf)
+ if err != nil && err != ErrUnexpectedEOF {
+ t.Fatalf("got: %q; want: %q", err, ErrUnexpectedEOF)
+ }
+ result = string(buf[0:n])
+ <-done
+
+ if result != "hello" {
+ t.Errorf("got: %q; want: %q", result, "hello")
+ }
+ if writeErr != ErrClosedPipe {
+ t.Errorf("got: %q; want: %q", writeErr, ErrClosedPipe)
+ }
+}
diff --git a/libgo/go/log/syslog/syslog.go b/libgo/go/log/syslog/syslog.go
index 20acab8ffc0..0cbfa9011b8 100644
--- a/libgo/go/log/syslog/syslog.go
+++ b/libgo/go/log/syslog/syslog.go
@@ -91,13 +91,20 @@ type Writer struct {
conn serverConn
}
+// This interface and the separate syslog_unix.go file exist for
+// Solaris support as implemented by gccgo. On Solaris you can not
+// simply open a TCP connection to the syslog daemon. The gccgo
+// sources have a syslog_solaris.go file that implements unixSyslog to
+// return a type that satisfies this interface and simply calls the C
+// library syslog function.
type serverConn interface {
writeString(p Priority, hostname, tag, s, nl string) error
close() error
}
type netConn struct {
- conn net.Conn
+ local bool
+ conn net.Conn
}
// New establishes a new connection to the system log daemon. Each
@@ -157,7 +164,7 @@ func (w *Writer) connect() (err error) {
var c net.Conn
c, err = net.Dial(w.network, w.raddr)
if err == nil {
- w.conn = netConn{c}
+ w.conn = &netConn{conn: c}
if w.hostname == "" {
w.hostname = c.LocalAddr().String()
}
@@ -212,7 +219,7 @@ func (w *Writer) Err(m string) (err error) {
return err
}
-// Wanring logs a message with severity LOG_WARNING, ignoring the
+// Warning logs a message with severity LOG_WARNING, ignoring the
// severity passed to New.
func (w *Writer) Warning(m string) (err error) {
_, err = w.writeAndRetry(LOG_WARNING, m)
@@ -266,11 +273,27 @@ func (w *Writer) write(p Priority, msg string) (int, error) {
nl = "\n"
}
- w.conn.writeString(p, w.hostname, w.tag, msg, nl)
+ err := w.conn.writeString(p, w.hostname, w.tag, msg, nl)
+ if err != nil {
+ return 0, err
+ }
+ // Note: return the length of the input, not the number of
+ // bytes printed by Fprintf, because this must behave like
+ // an io.Writer.
return len(msg), nil
}
-func (n netConn) writeString(p Priority, hostname, tag, msg, nl string) error {
+func (n *netConn) writeString(p Priority, hostname, tag, msg, nl string) error {
+ if n.local {
+ // Compared to the network form below, the changes are:
+ // 1. Use time.Stamp instead of time.RFC3339.
+ // 2. Drop the hostname field from the Fprintf.
+ timestamp := time.Now().Format(time.Stamp)
+ _, err := fmt.Fprintf(n.conn, "<%d>%s %s[%d]: %s%s",
+ p, timestamp,
+ tag, os.Getpid(), msg, nl)
+ return err
+ }
timestamp := time.Now().Format(time.RFC3339)
_, err := fmt.Fprintf(n.conn, "<%d>%s %s %s[%d]: %s%s",
p, timestamp, hostname,
@@ -278,7 +301,7 @@ func (n netConn) writeString(p Priority, hostname, tag, msg, nl string) error {
return err
}
-func (n netConn) close() error {
+func (n *netConn) close() error {
return n.conn.Close()
}
diff --git a/libgo/go/log/syslog/syslog_test.go b/libgo/go/log/syslog/syslog_test.go
index ec4525190f4..760a5c7d1e9 100644
--- a/libgo/go/log/syslog/syslog_test.go
+++ b/libgo/go/log/syslog/syslog_test.go
@@ -122,7 +122,9 @@ func TestWithSimulated(t *testing.T) {
for _, tr := range transport {
done := make(chan string)
- addr, _, _ := startServer(tr, "", done)
+ addr, sock, srvWG := startServer(tr, "", done)
+ defer srvWG.Wait()
+ defer sock.Close()
if tr == "unix" || tr == "unixgram" {
defer os.Remove(addr)
}
@@ -142,7 +144,8 @@ func TestWithSimulated(t *testing.T) {
func TestFlap(t *testing.T) {
net := "unix"
done := make(chan string)
- addr, sock, _ := startServer(net, "", done)
+ addr, sock, srvWG := startServer(net, "", done)
+ defer srvWG.Wait()
defer os.Remove(addr)
defer sock.Close()
@@ -158,7 +161,8 @@ func TestFlap(t *testing.T) {
check(t, msg, <-done)
// restart the server
- _, sock2, _ := startServer(net, addr, done)
+ _, sock2, srvWG2 := startServer(net, addr, done)
+ defer srvWG2.Wait()
defer sock2.Close()
// and try retransmitting
@@ -249,12 +253,14 @@ func TestWrite(t *testing.T) {
} else {
for _, test := range tests {
done := make(chan string)
- addr, sock, _ := startServer("udp", "", done)
+ addr, sock, srvWG := startServer("udp", "", done)
+ defer srvWG.Wait()
defer sock.Close()
l, err := Dial("udp", addr, test.pri, test.pre)
if err != nil {
t.Fatalf("syslog.Dial() failed: %v", err)
}
+ defer l.Close()
_, err = io.WriteString(l, test.msg)
if err != nil {
t.Fatalf("WriteString() failed: %v", err)
@@ -271,7 +277,8 @@ func TestWrite(t *testing.T) {
}
func TestConcurrentWrite(t *testing.T) {
- addr, sock, _ := startServer("udp", "", make(chan string))
+ addr, sock, srvWG := startServer("udp", "", make(chan string, 1))
+ defer srvWG.Wait()
defer sock.Close()
w, err := Dial("udp", addr, LOG_USER|LOG_ERR, "how's it going?")
if err != nil {
@@ -281,12 +288,12 @@ func TestConcurrentWrite(t *testing.T) {
for i := 0; i < 10; i++ {
wg.Add(1)
go func() {
+ defer wg.Done()
err := w.Info("test")
if err != nil {
t.Errorf("Info() failed: %v", err)
return
}
- wg.Done()
}()
}
wg.Wait()
@@ -296,8 +303,10 @@ func TestConcurrentReconnect(t *testing.T) {
crashy = true
defer func() { crashy = false }()
+ const N = 10
+ const M = 100
net := "unix"
- done := make(chan string)
+ done := make(chan string, N*M)
addr, sock, srvWG := startServer(net, "", done)
defer os.Remove(addr)
@@ -310,7 +319,7 @@ func TestConcurrentReconnect(t *testing.T) {
// we are looking for 500 out of 1000 events
// here because lots of log messages are lost
// in buffers (kernel and/or bufio)
- if ct > 500 {
+ if ct > N*M/2 {
break
}
}
@@ -318,21 +327,22 @@ func TestConcurrentReconnect(t *testing.T) {
}()
var wg sync.WaitGroup
- for i := 0; i < 10; i++ {
- wg.Add(1)
+ wg.Add(N)
+ for i := 0; i < N; i++ {
go func() {
+ defer wg.Done()
w, err := Dial(net, addr, LOG_USER|LOG_ERR, "tag")
if err != nil {
t.Fatalf("syslog.Dial() failed: %v", err)
}
- for i := 0; i < 100; i++ {
+ defer w.Close()
+ for i := 0; i < M; i++ {
err := w.Info("test")
if err != nil {
t.Errorf("Info() failed: %v", err)
return
}
}
- wg.Done()
}()
}
wg.Wait()
diff --git a/libgo/go/log/syslog/syslog_unix.go b/libgo/go/log/syslog/syslog_unix.go
index 1716d60feaa..28a294af963 100644
--- a/libgo/go/log/syslog/syslog_unix.go
+++ b/libgo/go/log/syslog/syslog_unix.go
@@ -23,7 +23,7 @@ func unixSyslog() (conn serverConn, err error) {
if err != nil {
continue
} else {
- return netConn{conn}, nil
+ return &netConn{conn: conn, local: true}, nil
}
}
}
diff --git a/libgo/go/math/asin.go b/libgo/go/math/asin.go
index 0d4fa9ebb50..46a5fe9d808 100644
--- a/libgo/go/math/asin.go
+++ b/libgo/go/math/asin.go
@@ -11,7 +11,7 @@ package math
after appropriate range reduction.
*/
-// Asin returns the arcsine of x.
+// Asin returns the arcsine, in radians, of x.
//
// Special cases are:
// Asin(±0) = ±0
@@ -50,7 +50,7 @@ func asin(x float64) float64 {
return temp
}
-// Acos returns the arccosine of x.
+// Acos returns the arccosine, in radians, of x.
//
// Special case is:
// Acos(x) = NaN if x < -1 or x > 1
diff --git a/libgo/go/math/atan.go b/libgo/go/math/atan.go
index 986ba068661..d942bce0968 100644
--- a/libgo/go/math/atan.go
+++ b/libgo/go/math/atan.go
@@ -87,7 +87,7 @@ func satan(x float64) float64 {
return Pi/4 + xatan((x-1)/(x+1)) + 0.5*Morebits
}
-// Atan returns the arctangent of x.
+// Atan returns the arctangent, in radians, of x.
//
// Special cases are:
// Atan(±0) = ±0
diff --git a/libgo/go/math/big/int.go b/libgo/go/math/big/int.go
index d1b5602d668..7bbb152d79c 100644
--- a/libgo/go/math/big/int.go
+++ b/libgo/go/math/big/int.go
@@ -563,13 +563,13 @@ func (z *Int) SetBytes(buf []byte) *Int {
return z
}
-// Bytes returns the absolute value of z as a big-endian byte slice.
+// Bytes returns the absolute value of x as a big-endian byte slice.
func (x *Int) Bytes() []byte {
buf := make([]byte, len(x.abs)*_S)
return buf[x.abs.bytes(buf):]
}
-// BitLen returns the length of the absolute value of z in bits.
+// BitLen returns the length of the absolute value of x in bits.
// The bit length of 0 is 0.
func (x *Int) BitLen() int {
return x.abs.bitLen()
@@ -703,14 +703,15 @@ func (z *Int) binaryGCD(a, b *Int) *Int {
// reduce t
t.Rsh(t, t.abs.trailingZeroBits())
if t.neg {
- v.Neg(t)
+ v, t = t, v
+ v.neg = len(v.abs) > 0 && !v.neg // 0 has no sign
} else {
- u.Set(t)
+ u, t = t, u
}
t.Sub(u, v)
}
- return u.Lsh(u, k)
+ return z.Lsh(u, k)
}
// ProbablyPrime performs n Miller-Rabin tests to check whether x is prime.
@@ -951,6 +952,9 @@ const intGobVersion byte = 1
// GobEncode implements the gob.GobEncoder interface.
func (x *Int) GobEncode() ([]byte, error) {
+ if x == nil {
+ return nil, nil
+ }
buf := make([]byte, 1+len(x.abs)*_S) // extra byte for version and sign bit
i := x.abs.bytes(buf) - 1 // i >= 0
b := intGobVersion << 1 // make space for sign bit
@@ -964,7 +968,9 @@ func (x *Int) GobEncode() ([]byte, error) {
// GobDecode implements the gob.GobDecoder interface.
func (z *Int) GobDecode(buf []byte) error {
if len(buf) == 0 {
- return errors.New("Int.GobDecode: no data")
+ // Other side sent a nil or default value.
+ *z = Int{}
+ return nil
}
b := buf[0]
if b>>1 != intGobVersion {
diff --git a/libgo/go/math/big/int_test.go b/libgo/go/math/big/int_test.go
index 6c981e7752e..87b975d5c4b 100644
--- a/libgo/go/math/big/int_test.go
+++ b/libgo/go/math/big/int_test.go
@@ -89,7 +89,7 @@ func testFunZZ(t *testing.T, msg string, f funZZ, a argZZ) {
var z Int
f(&z, a.x, a.y)
if !isNormalized(&z) {
- t.Errorf("%s%v is not normalized", z, msg)
+ t.Errorf("%s%v is not normalized", msg, z)
}
if (&z).Cmp(a.z) != 0 {
t.Errorf("%s%+v\n\tgot z = %v; want %v", msg, a, &z, a.z)
@@ -1484,6 +1484,32 @@ func TestIntGobEncoding(t *testing.T) {
}
}
+// Sending a nil Int pointer (inside a slice) on a round trip through gob should yield a zero.
+// TODO: top-level nils.
+func TestGobEncodingNilIntInSlice(t *testing.T) {
+ buf := new(bytes.Buffer)
+ enc := gob.NewEncoder(buf)
+ dec := gob.NewDecoder(buf)
+
+ var in = make([]*Int, 1)
+ err := enc.Encode(&in)
+ if err != nil {
+ t.Errorf("gob encode failed: %q", err)
+ }
+ var out []*Int
+ err = dec.Decode(&out)
+ if err != nil {
+ t.Fatalf("gob decode failed: %q", err)
+ }
+ if len(out) != 1 {
+ t.Fatalf("wrong len; want 1 got %d", len(out))
+ }
+ var zero Int
+ if out[0].Cmp(&zero) != 0 {
+ t.Errorf("transmission of (*Int)(nill) failed: got %s want 0", out)
+ }
+}
+
func TestIntJSONEncoding(t *testing.T) {
for _, test := range encodingTests {
var tx Int
diff --git a/libgo/go/math/big/nat_test.go b/libgo/go/math/big/nat_test.go
index 2dd7bf63968..1d4dfe80d3d 100644
--- a/libgo/go/math/big/nat_test.go
+++ b/libgo/go/math/big/nat_test.go
@@ -685,7 +685,7 @@ func runModWTests(t *testing.T, tests []modWTest) {
r := in.abs.modW(d.abs[0])
if r != out.abs[0] {
- t.Errorf("#%d failed: got %s want %s", i, r, out)
+ t.Errorf("#%d failed: got %d want %s", i, r, out)
}
}
}
diff --git a/libgo/go/math/big/rat.go b/libgo/go/math/big/rat.go
index 75d044fe21d..7faee61a465 100644
--- a/libgo/go/math/big/rat.go
+++ b/libgo/go/math/big/rat.go
@@ -164,8 +164,9 @@ func quotToFloat(a, b nat) (f float64, exact bool) {
}
// Float64 returns the nearest float64 value for x and a bool indicating
-// whether f represents x exactly. The sign of f always matches the sign
-// of x, even if f == 0.
+// whether f represents x exactly. If the magnitude of x is too large to
+// be represented by a float64, f is an infinity and exact is false.
+// The sign of f always matches the sign of x, even if f == 0.
func (x *Rat) Float64() (f float64, exact bool) {
b := x.b.abs
if len(b) == 0 {
@@ -545,6 +546,9 @@ const ratGobVersion byte = 1
// GobEncode implements the gob.GobEncoder interface.
func (x *Rat) GobEncode() ([]byte, error) {
+ if x == nil {
+ return nil, nil
+ }
buf := make([]byte, 1+4+(len(x.a.abs)+len(x.b.abs))*_S) // extra bytes for version and sign bit (1), and numerator length (4)
i := x.b.abs.bytes(buf)
j := x.a.abs.bytes(buf[0:i])
@@ -566,7 +570,9 @@ func (x *Rat) GobEncode() ([]byte, error) {
// GobDecode implements the gob.GobDecoder interface.
func (z *Rat) GobDecode(buf []byte) error {
if len(buf) == 0 {
- return errors.New("Rat.GobDecode: no data")
+ // Other side sent a nil or default value.
+ *z = Rat{}
+ return nil
}
b := buf[0]
if b>>1 != ratGobVersion {
diff --git a/libgo/go/math/big/rat_test.go b/libgo/go/math/big/rat_test.go
index 1c2c642379c..0d432637ba1 100644
--- a/libgo/go/math/big/rat_test.go
+++ b/libgo/go/math/big/rat_test.go
@@ -407,6 +407,32 @@ func TestRatGobEncoding(t *testing.T) {
}
}
+// Sending a nil Rat pointer (inside a slice) on a round trip through gob should yield a zero.
+// TODO: top-level nils.
+func TestGobEncodingNilRatInSlice(t *testing.T) {
+ buf := new(bytes.Buffer)
+ enc := gob.NewEncoder(buf)
+ dec := gob.NewDecoder(buf)
+
+ var in = make([]*Rat, 1)
+ err := enc.Encode(&in)
+ if err != nil {
+ t.Errorf("gob encode failed: %q", err)
+ }
+ var out []*Rat
+ err = dec.Decode(&out)
+ if err != nil {
+ t.Fatalf("gob decode failed: %q", err)
+ }
+ if len(out) != 1 {
+ t.Fatalf("wrong len; want 1 got %d", len(out))
+ }
+ var zero Rat
+ if out[0].Cmp(&zero) != 0 {
+ t.Errorf("transmission of (*Int)(nill) failed: got %s want 0", out)
+ }
+}
+
func TestIssue2379(t *testing.T) {
// 1) no aliasing
q := NewRat(3, 2)
diff --git a/libgo/go/math/bits.go b/libgo/go/math/bits.go
index 0df0b1cc9f1..d85ee9cb137 100644
--- a/libgo/go/math/bits.go
+++ b/libgo/go/math/bits.go
@@ -27,7 +27,7 @@ func Inf(sign int) float64 {
// NaN returns an IEEE 754 ``not-a-number'' value.
func NaN() float64 { return Float64frombits(uvnan) }
-// IsNaN returns whether f is an IEEE 754 ``not-a-number'' value.
+// IsNaN reports whether f is an IEEE 754 ``not-a-number'' value.
func IsNaN(f float64) (is bool) {
// IEEE 754 says that only NaNs satisfy f != f.
// To avoid the floating-point hardware, could use:
@@ -36,10 +36,10 @@ func IsNaN(f float64) (is bool) {
return f != f
}
-// IsInf returns whether f is an infinity, according to sign.
-// If sign > 0, IsInf returns whether f is positive infinity.
-// If sign < 0, IsInf returns whether f is negative infinity.
-// If sign == 0, IsInf returns whether f is either infinity.
+// IsInf reports whether f is an infinity, according to sign.
+// If sign > 0, IsInf reports whether f is positive infinity.
+// If sign < 0, IsInf reports whether f is negative infinity.
+// If sign == 0, IsInf reports whether f is either infinity.
func IsInf(f float64, sign int) bool {
// Test for infinity by comparing against maximum float.
// To avoid the floating-point hardware, could use:
diff --git a/libgo/go/math/rand/rand.go b/libgo/go/math/rand/rand.go
index 94f84a85fbe..2157cdb4658 100644
--- a/libgo/go/math/rand/rand.go
+++ b/libgo/go/math/rand/rand.go
@@ -3,6 +3,12 @@
// license that can be found in the LICENSE file.
// Package rand implements pseudo-random number generators.
+//
+// Random numbers are generated by a Source. Top-level functions, such as
+// Float64 and Int, use a default shared Source that produces a deterministic
+// sequence of values each time a program is run. Use the Seed function to
+// initialize the default Source if different behavior is required for each run.
+// The default Source is safe for concurrent use by multiple goroutines.
package rand
import "sync"
@@ -113,47 +119,57 @@ func (r *Rand) Perm(n int) []int {
var globalRand = New(&lockedSource{src: NewSource(1)})
-// Seed uses the provided seed value to initialize the generator to a
+// Seed uses the provided seed value to initialize the default Source to a
// deterministic state. If Seed is not called, the generator behaves as
// if seeded by Seed(1).
func Seed(seed int64) { globalRand.Seed(seed) }
-// Int63 returns a non-negative pseudo-random 63-bit integer as an int64.
+// Int63 returns a non-negative pseudo-random 63-bit integer as an int64
+// from the default Source.
func Int63() int64 { return globalRand.Int63() }
-// Uint32 returns a pseudo-random 32-bit value as a uint32.
+// Uint32 returns a pseudo-random 32-bit value as a uint32
+// from the default Source.
func Uint32() uint32 { return globalRand.Uint32() }
-// Int31 returns a non-negative pseudo-random 31-bit integer as an int32.
+// Int31 returns a non-negative pseudo-random 31-bit integer as an int32
+// from the default Source.
func Int31() int32 { return globalRand.Int31() }
-// Int returns a non-negative pseudo-random int.
+// Int returns a non-negative pseudo-random int from the default Source.
func Int() int { return globalRand.Int() }
-// Int63n returns, as an int64, a non-negative pseudo-random number in [0,n).
+// Int63n returns, as an int64, a non-negative pseudo-random number in [0,n)
+// from the default Source.
// It panics if n <= 0.
func Int63n(n int64) int64 { return globalRand.Int63n(n) }
-// Int31n returns, as an int32, a non-negative pseudo-random number in [0,n).
+// Int31n returns, as an int32, a non-negative pseudo-random number in [0,n)
+// from the default Source.
// It panics if n <= 0.
func Int31n(n int32) int32 { return globalRand.Int31n(n) }
-// Intn returns, as an int, a non-negative pseudo-random number in [0,n).
+// Intn returns, as an int, a non-negative pseudo-random number in [0,n)
+// from the default Source.
// It panics if n <= 0.
func Intn(n int) int { return globalRand.Intn(n) }
-// Float64 returns, as a float64, a pseudo-random number in [0.0,1.0).
+// Float64 returns, as a float64, a pseudo-random number in [0.0,1.0)
+// from the default Source.
func Float64() float64 { return globalRand.Float64() }
-// Float32 returns, as a float32, a pseudo-random number in [0.0,1.0).
+// Float32 returns, as a float32, a pseudo-random number in [0.0,1.0)
+// from the default Source.
func Float32() float32 { return globalRand.Float32() }
-// Perm returns, as a slice of n ints, a pseudo-random permutation of the integers [0,n).
+// Perm returns, as a slice of n ints, a pseudo-random permutation of the integers [0,n)
+// from the default Source.
func Perm(n int) []int { return globalRand.Perm(n) }
// NormFloat64 returns a normally distributed float64 in the range
// [-math.MaxFloat64, +math.MaxFloat64] with
-// standard normal distribution (mean = 0, stddev = 1).
+// standard normal distribution (mean = 0, stddev = 1)
+// from the default Source.
// To produce a different normal distribution, callers can
// adjust the output using:
//
@@ -163,7 +179,7 @@ func NormFloat64() float64 { return globalRand.NormFloat64() }
// ExpFloat64 returns an exponentially distributed float64 in the range
// (0, +math.MaxFloat64] with an exponential distribution whose rate parameter
-// (lambda) is 1 and whose mean is 1/lambda (1).
+// (lambda) is 1 and whose mean is 1/lambda (1) from the default Source.
// To produce a distribution with a different rate parameter,
// callers can adjust the output using:
//
diff --git a/libgo/go/math/sin.go b/libgo/go/math/sin.go
index 13fe408ba06..1c5491f6dc4 100644
--- a/libgo/go/math/sin.go
+++ b/libgo/go/math/sin.go
@@ -109,7 +109,7 @@ var _cos = [...]float64{
4.16666666666665929218E-2, // 0x3fa555555555554b
}
-// Cos returns the cosine of x.
+// Cos returns the cosine of the radian argument x.
//
// Special cases are:
// Cos(±Inf) = NaN
@@ -171,7 +171,7 @@ func cos(x float64) float64 {
return y
}
-// Sin returns the sine of x.
+// Sin returns the sine of the radian argument x.
//
// Special cases are:
// Sin(±0) = ±0
diff --git a/libgo/go/math/tan.go b/libgo/go/math/tan.go
index 640f404fbe6..e544b276b5d 100644
--- a/libgo/go/math/tan.go
+++ b/libgo/go/math/tan.go
@@ -73,7 +73,7 @@ var _tanQ = [...]float64{
-5.38695755929454629881E7, //0xc189afe03cbe5a31
}
-// Tan returns the tangent of x.
+// Tan returns the tangent of the radian argument x.
//
// Special cases are:
// Tan(±0) = ±0
diff --git a/libgo/go/mime/grammar.go b/libgo/go/mime/grammar.go
index 09e941e3ec0..2347324aa5a 100644
--- a/libgo/go/mime/grammar.go
+++ b/libgo/go/mime/grammar.go
@@ -30,16 +30,3 @@ func isToken(s string) bool {
}
return strings.IndexFunc(s, isNotTokenChar) < 0
}
-
-// isQText returns true if rune is in 'qtext' as defined by RFC 822.
-func isQText(r int) bool {
- // CHAR = <any ASCII character> ; ( 0-177, 0.-127.)
- // qtext = <any CHAR excepting <">, ; => may be folded
- // "\" & CR, and including
- // linear-white-space>
- switch r {
- case '"', '\\', '\r':
- return false
- }
- return r < 0x80
-}
diff --git a/libgo/go/mime/mediatype.go b/libgo/go/mime/mediatype.go
index 8396c0a155b..608f759da8f 100644
--- a/libgo/go/mime/mediatype.go
+++ b/libgo/go/mime/mediatype.go
@@ -47,7 +47,7 @@ func FormatMediaType(t string, param map[string]string) string {
b.WriteByte('"')
offset := 0
for index, character := range value {
- if character == '"' || character == '\r' {
+ if character == '"' || character == '\\' {
b.WriteString(value[offset:index])
offset = index
b.WriteByte('\\')
diff --git a/libgo/go/mime/mediatype_test.go b/libgo/go/mime/mediatype_test.go
index e41ead237a5..29511445bcf 100644
--- a/libgo/go/mime/mediatype_test.go
+++ b/libgo/go/mime/mediatype_test.go
@@ -282,8 +282,17 @@ type formatTest struct {
var formatTests = []formatTest{
{"noslash", nil, ""},
+ {"foo bar/baz", nil, ""},
+ {"foo/bar baz", nil, ""},
{"foo/BAR", nil, "foo/bar"},
{"foo/BAR", map[string]string{"X": "Y"}, "foo/bar; x=Y"},
+ {"foo/BAR", map[string]string{"space": "With space"}, `foo/bar; space="With space"`},
+ {"foo/BAR", map[string]string{"quote": `With "quote`}, `foo/bar; quote="With \"quote"`},
+ {"foo/BAR", map[string]string{"bslash": `With \backslash`}, `foo/bar; bslash="With \\backslash"`},
+ {"foo/BAR", map[string]string{"both": `With \backslash and "quote`}, `foo/bar; both="With \\backslash and \"quote"`},
+ {"foo/BAR", map[string]string{"": "empty attribute"}, ""},
+ {"foo/BAR", map[string]string{"bad attribute": "baz"}, ""},
+ {"foo/BAR", map[string]string{"nonascii": "not an ascii character: ä"}, ""},
}
func TestFormatMediaType(t *testing.T) {
diff --git a/libgo/go/mime/multipart/multipart.go b/libgo/go/mime/multipart/multipart.go
index 2c862a64791..2b4f5b433ec 100644
--- a/libgo/go/mime/multipart/multipart.go
+++ b/libgo/go/mime/multipart/multipart.go
@@ -272,7 +272,7 @@ func (r *Reader) NextPart() (*Part, error) {
}
}
-// isFinalBoundary returns whether line is the final boundary line
+// isFinalBoundary reports whether line is the final boundary line
// indicating that all parts are over.
// It matches `^--boundary--[ \t]*(\r\n)?$`
func (mr *Reader) isFinalBoundary(line []byte) bool {
@@ -307,8 +307,8 @@ func (mr *Reader) isBoundaryDelimiterLine(line []byte) (ret bool) {
return bytes.Equal(rest, mr.nl)
}
-// peekBufferIsEmptyPart returns whether the provided peek-ahead
-// buffer represents an empty part. This is only called if we've not
+// peekBufferIsEmptyPart reports whether the provided peek-ahead
+// buffer represents an empty part. It is called only if we've not
// already read any bytes in this part and checks for the case of MIME
// software not writing the \r\n on empty parts. Some does, some
// doesn't.
diff --git a/libgo/go/mime/type_plan9.go b/libgo/go/mime/type_plan9.go
new file mode 100644
index 00000000000..b8f0511ee7d
--- /dev/null
+++ b/libgo/go/mime/type_plan9.go
@@ -0,0 +1,53 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package mime
+
+import (
+ "bufio"
+ "os"
+ "strings"
+)
+
+var typeFiles = []string{
+ "/sys/lib/mimetypes",
+}
+
+func loadMimeFile(filename string) {
+ f, err := os.Open(filename)
+ if err != nil {
+ return
+ }
+ defer f.Close()
+
+ scanner := bufio.NewScanner(f)
+ for scanner.Scan() {
+ fields := strings.Fields(scanner.Text())
+ if len(fields) <= 2 || fields[0][0] != '.' {
+ continue
+ }
+ if fields[1] == "-" || fields[2] == "-" {
+ continue
+ }
+ setExtensionType(fields[0], fields[1]+"/"+fields[2])
+ }
+ if err := scanner.Err(); err != nil {
+ panic(err)
+ }
+}
+
+func initMime() {
+ for _, filename := range typeFiles {
+ loadMimeFile(filename)
+ }
+}
+
+func initMimeForTests() map[string]string {
+ typeFiles = []string{"testdata/test.types.plan9"}
+ return map[string]string{
+ ".t1": "application/test",
+ ".t2": "text/test; charset=utf-8",
+ ".png": "image/png",
+ }
+}
diff --git a/libgo/go/mime/type_unix.go b/libgo/go/mime/type_unix.go
index 857a0ab6765..713e301cdf2 100644
--- a/libgo/go/mime/type_unix.go
+++ b/libgo/go/mime/type_unix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd linux netbsd openbsd plan9
+// +build darwin dragonfly freebsd linux netbsd openbsd
package mime
diff --git a/libgo/go/net/cgo_bsd.go b/libgo/go/net/cgo_bsd.go
index 27c3e9acb94..3852fc22987 100644
--- a/libgo/go/net/cgo_bsd.go
+++ b/libgo/go/net/cgo_bsd.go
@@ -2,7 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd
+// +build !netgo
+// +build darwin dragonfly freebsd
package net
diff --git a/libgo/go/net/cgo_linux.go b/libgo/go/net/cgo_linux.go
index 650575cce6c..77522f9141b 100644
--- a/libgo/go/net/cgo_linux.go
+++ b/libgo/go/net/cgo_linux.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build cgo,!netgo
+
package net
/*
diff --git a/libgo/go/net/cgo_netbsd.go b/libgo/go/net/cgo_netbsd.go
index 27334af641a..3c13103831f 100644
--- a/libgo/go/net/cgo_netbsd.go
+++ b/libgo/go/net/cgo_netbsd.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build cgo,!netgo
+
package net
/*
diff --git a/libgo/go/net/cgo_openbsd.go b/libgo/go/net/cgo_openbsd.go
index aeaf8e568ad..09c5ad2d9fd 100644
--- a/libgo/go/net/cgo_openbsd.go
+++ b/libgo/go/net/cgo_openbsd.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build cgo,!netgo
+
package net
/*
diff --git a/libgo/go/net/cgo_stub.go b/libgo/go/net/cgo_stub.go
index 52e57d7400e..f533c14212f 100644
--- a/libgo/go/net/cgo_stub.go
+++ b/libgo/go/net/cgo_stub.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build !cgo
+// +build !cgo netgo
// Stub cgo routines for systems that do not use cgo to do network lookups.
diff --git a/libgo/go/net/cgo_unix.go b/libgo/go/net/cgo_unix.go
index ce54d827c8e..0abf43410e1 100644
--- a/libgo/go/net/cgo_unix.go
+++ b/libgo/go/net/cgo_unix.go
@@ -2,7 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd linux netbsd openbsd
+// +build !netgo
+// +build darwin dragonfly freebsd linux netbsd openbsd
package net
@@ -50,6 +51,9 @@ func cgoLookupHost(name string) (addrs []string, err error, completed bool) {
}
func cgoLookupPort(net, service string) (port int, err error, completed bool) {
+ acquireThread()
+ defer releaseThread()
+
var res *syscall.Addrinfo
var hints syscall.Addrinfo
@@ -99,6 +103,9 @@ func cgoLookupPort(net, service string) (port int, err error, completed bool) {
}
func cgoLookupIPCNAME(name string) (addrs []IP, cname string, err error, completed bool) {
+ acquireThread()
+ defer releaseThread()
+
var res *syscall.Addrinfo
var hints syscall.Addrinfo
@@ -114,7 +121,18 @@ func cgoLookupIPCNAME(name string) (addrs []IP, cname string, err error, complet
if gerrno == syscall.EAI_NONAME {
str = noSuchHost
} else if gerrno == syscall.EAI_SYSTEM {
- str = syscall.GetErrno().Error()
+ errno := syscall.GetErrno()
+ if errno == 0 {
+ // err should not be nil, but sometimes getaddrinfo returns
+ // gerrno == C.EAI_SYSTEM with err == nil on Linux.
+ // The report claims that it happens when we have too many
+ // open files, so use syscall.EMFILE (too many open files in system).
+ // Most system calls would return ENFILE (too many open files),
+ // so at the least EMFILE should be easy to recognize if this
+ // comes up again. golang.org/issue/6232.
+ errno = syscall.EMFILE
+ }
+ str = errno.Error()
} else {
str = bytePtrToString(libc_gai_strerror(gerrno))
}
@@ -160,6 +178,9 @@ func cgoLookupCNAME(name string) (cname string, err error, completed bool) {
}
func copyIP(x IP) IP {
+ if len(x) < 16 {
+ return x.To16()
+ }
y := make(IP, len(x))
copy(y, x)
return y
diff --git a/libgo/go/net/dial.go b/libgo/go/net/dial.go
index b18d283626c..6304818bf14 100644
--- a/libgo/go/net/dial.go
+++ b/libgo/go/net/dial.go
@@ -37,6 +37,13 @@ type Dialer struct {
// network being dialed.
// If nil, a local address is automatically chosen.
LocalAddr Addr
+
+ // DualStack allows a single dial to attempt to establish
+ // multiple IPv4 and IPv6 connections and to return the first
+ // established connection when the network is "tcp" and the
+ // destination is a host name that has multiple address family
+ // DNS records.
+ DualStack bool
}
// Return either now+Timeout or Deadline, whichever comes first.
@@ -82,13 +89,13 @@ func parseNetwork(net string) (afnet string, proto int, err error) {
return "", 0, UnknownNetworkError(net)
}
-func resolveAddr(op, net, addr string, deadline time.Time) (Addr, error) {
+func resolveAddr(op, net, addr string, deadline time.Time) (netaddr, error) {
afnet, _, err := parseNetwork(net)
if err != nil {
- return nil, &OpError{op, net, nil, err}
+ return nil, err
}
if op == "dial" && addr == "" {
- return nil, &OpError{op, net, nil, errMissingAddress}
+ return nil, errMissingAddress
}
switch afnet {
case "unix", "unixgram", "unixpacket":
@@ -143,12 +150,74 @@ func DialTimeout(network, address string, timeout time.Duration) (Conn, error) {
// See func Dial for a description of the network and address
// parameters.
func (d *Dialer) Dial(network, address string) (Conn, error) {
- return resolveAndDial(network, address, d.LocalAddr, d.deadline())
+ ra, err := resolveAddr("dial", network, address, d.deadline())
+ if err != nil {
+ return nil, &OpError{Op: "dial", Net: network, Addr: nil, Err: err}
+ }
+ dialer := func(deadline time.Time) (Conn, error) {
+ return dialSingle(network, address, d.LocalAddr, ra.toAddr(), deadline)
+ }
+ if ras, ok := ra.(addrList); ok && d.DualStack && network == "tcp" {
+ dialer = func(deadline time.Time) (Conn, error) {
+ return dialMulti(network, address, d.LocalAddr, ras, deadline)
+ }
+ }
+ return dial(network, ra.toAddr(), dialer, d.deadline())
}
-func dial(net, addr string, la, ra Addr, deadline time.Time) (c Conn, err error) {
+// dialMulti attempts to establish connections to each destination of
+// the list of addresses. It will return the first established
+// connection and close the other connections. Otherwise it returns
+// error on the last attempt.
+func dialMulti(net, addr string, la Addr, ras addrList, deadline time.Time) (Conn, error) {
+ type racer struct {
+ Conn
+ Addr
+ error
+ }
+ // Sig controls the flow of dial results on lane. It passes a
+ // token to the next racer and also indicates the end of flow
+ // by using closed channel.
+ sig := make(chan bool, 1)
+ lane := make(chan racer, 1)
+ for _, ra := range ras {
+ go func(ra Addr) {
+ c, err := dialSingle(net, addr, la, ra, deadline)
+ if _, ok := <-sig; ok {
+ lane <- racer{c, ra, err}
+ } else if err == nil {
+ // We have to return the resources
+ // that belong to the other
+ // connections here for avoiding
+ // unnecessary resource starvation.
+ c.Close()
+ }
+ }(ra.toAddr())
+ }
+ defer close(sig)
+ var failAddr Addr
+ lastErr := errTimeout
+ nracers := len(ras)
+ for nracers > 0 {
+ sig <- true
+ select {
+ case racer := <-lane:
+ if racer.error == nil {
+ return racer.Conn, nil
+ }
+ failAddr = racer.Addr
+ lastErr = racer.error
+ nracers--
+ }
+ }
+ return nil, &OpError{Op: "dial", Net: net, Addr: failAddr, Err: lastErr}
+}
+
+// dialSingle attempts to establish and returns a single connection to
+// the destination address.
+func dialSingle(net, addr string, la, ra Addr, deadline time.Time) (c Conn, err error) {
if la != nil && la.Network() != ra.Network() {
- return nil, &OpError{"dial", net, ra, errors.New("mismatched local addr type " + la.Network())}
+ return nil, &OpError{Op: "dial", Net: net, Addr: ra, Err: errors.New("mismatched local address type " + la.Network())}
}
switch ra := ra.(type) {
case *TCPAddr:
@@ -164,21 +233,14 @@ func dial(net, addr string, la, ra Addr, deadline time.Time) (c Conn, err error)
la, _ := la.(*UnixAddr)
c, err = dialUnix(net, la, ra, deadline)
default:
- err = &OpError{"dial", net + " " + addr, ra, UnknownNetworkError(net)}
+ return nil, &OpError{Op: "dial", Net: net, Addr: ra, Err: &AddrError{Err: "unexpected address type", Addr: addr}}
}
if err != nil {
- return nil, err
+ return nil, err // c is non-nil interface containing nil pointer
}
- return
-}
-
-type stringAddr struct {
- net, addr string
+ return c, nil
}
-func (a stringAddr) Network() string { return a.net }
-func (a stringAddr) String() string { return a.addr }
-
// Listen announces on the local network address laddr.
// The network net must be a stream-oriented network: "tcp", "tcp4",
// "tcp6", "unix" or "unixpacket".
@@ -186,15 +248,21 @@ func (a stringAddr) String() string { return a.addr }
func Listen(net, laddr string) (Listener, error) {
la, err := resolveAddr("listen", net, laddr, noDeadline)
if err != nil {
- return nil, err
+ return nil, &OpError{Op: "listen", Net: net, Addr: nil, Err: err}
}
- switch la := la.(type) {
+ var l Listener
+ switch la := la.toAddr().(type) {
case *TCPAddr:
- return ListenTCP(net, la)
+ l, err = ListenTCP(net, la)
case *UnixAddr:
- return ListenUnix(net, la)
+ l, err = ListenUnix(net, la)
+ default:
+ return nil, &OpError{Op: "listen", Net: net, Addr: la, Err: &AddrError{Err: "unexpected address type", Addr: laddr}}
}
- return nil, UnknownNetworkError(net)
+ if err != nil {
+ return nil, err // l is non-nil interface containing nil pointer
+ }
+ return l, nil
}
// ListenPacket announces on the local network address laddr.
@@ -204,15 +272,21 @@ func Listen(net, laddr string) (Listener, error) {
func ListenPacket(net, laddr string) (PacketConn, error) {
la, err := resolveAddr("listen", net, laddr, noDeadline)
if err != nil {
- return nil, err
+ return nil, &OpError{Op: "listen", Net: net, Addr: nil, Err: err}
}
- switch la := la.(type) {
+ var l PacketConn
+ switch la := la.toAddr().(type) {
case *UDPAddr:
- return ListenUDP(net, la)
+ l, err = ListenUDP(net, la)
case *IPAddr:
- return ListenIP(net, la)
+ l, err = ListenIP(net, la)
case *UnixAddr:
- return ListenUnixgram(net, la)
+ l, err = ListenUnixgram(net, la)
+ default:
+ return nil, &OpError{Op: "listen", Net: net, Addr: la, Err: &AddrError{Err: "unexpected address type", Addr: laddr}}
+ }
+ if err != nil {
+ return nil, err // l is non-nil interface containing nil pointer
}
- return nil, UnknownNetworkError(net)
+ return l, nil
}
diff --git a/libgo/go/net/dial_gen.go b/libgo/go/net/dial_gen.go
index 19f86816821..ada6233003f 100644
--- a/libgo/go/net/dial_gen.go
+++ b/libgo/go/net/dial_gen.go
@@ -12,62 +12,35 @@ import (
var testingIssue5349 bool // used during tests
-// resolveAndDialChannel is the simple pure-Go implementation of
-// resolveAndDial, still used on operating systems where the deadline
-// hasn't been pushed down into the pollserver. (Plan 9 and some old
-// versions of Windows)
-func resolveAndDialChannel(net, addr string, localAddr Addr, deadline time.Time) (Conn, error) {
+// dialChannel is the simple pure-Go implementation of dial, still
+// used on operating systems where the deadline hasn't been pushed
+// down into the pollserver. (Plan 9 and some old versions of Windows)
+func dialChannel(net string, ra Addr, dialer func(time.Time) (Conn, error), deadline time.Time) (Conn, error) {
var timeout time.Duration
if !deadline.IsZero() {
timeout = deadline.Sub(time.Now())
}
if timeout <= 0 {
- ra, err := resolveAddr("dial", net, addr, noDeadline)
- if err != nil {
- return nil, err
- }
- return dial(net, addr, localAddr, ra, noDeadline)
+ return dialer(noDeadline)
}
t := time.NewTimer(timeout)
defer t.Stop()
- type pair struct {
+ type racer struct {
Conn
error
}
- ch := make(chan pair, 1)
- resolvedAddr := make(chan Addr, 1)
+ ch := make(chan racer, 1)
go func() {
if testingIssue5349 {
time.Sleep(time.Millisecond)
}
- ra, err := resolveAddr("dial", net, addr, noDeadline)
- if err != nil {
- ch <- pair{nil, err}
- return
- }
- resolvedAddr <- ra // in case we need it for OpError
- c, err := dial(net, addr, localAddr, ra, noDeadline)
- ch <- pair{c, err}
+ c, err := dialer(noDeadline)
+ ch <- racer{c, err}
}()
select {
case <-t.C:
- // Try to use the real Addr in our OpError, if we resolved it
- // before the timeout. Otherwise we just use stringAddr.
- var ra Addr
- select {
- case a := <-resolvedAddr:
- ra = a
- default:
- ra = &stringAddr{net, addr}
- }
- err := &OpError{
- Op: "dial",
- Net: net,
- Addr: ra,
- Err: &timeoutError{},
- }
- return nil, err
- case p := <-ch:
- return p.Conn, p.error
+ return nil, &OpError{Op: "dial", Net: net, Addr: ra, Err: errTimeout}
+ case racer := <-ch:
+ return racer.Conn, racer.error
}
}
diff --git a/libgo/go/net/dial_test.go b/libgo/go/net/dial_test.go
index 03a0bad7a5b..c7ffdd3d9c8 100644
--- a/libgo/go/net/dial_test.go
+++ b/libgo/go/net/dial_test.go
@@ -5,13 +5,17 @@
package net
import (
+ "bytes"
"flag"
"fmt"
"io"
"os"
+ "os/exec"
"reflect"
"regexp"
"runtime"
+ "strconv"
+ "sync"
"testing"
"time"
)
@@ -137,7 +141,7 @@ func TestSelfConnect(t *testing.T) {
n = 1000
}
switch runtime.GOOS {
- case "darwin", "freebsd", "netbsd", "openbsd", "plan9", "solaris", "windows":
+ case "darwin", "dragonfly", "freebsd", "netbsd", "openbsd", "plan9", "solaris", "windows":
// Non-Linux systems take a long time to figure
// out that there is nothing listening on localhost.
n = 100
@@ -314,6 +318,96 @@ func TestDialTimeoutFDLeak(t *testing.T) {
}
}
+func numTCP() (ntcp, nopen, nclose int, err error) {
+ lsof, err := exec.Command("lsof", "-n", "-p", strconv.Itoa(os.Getpid())).Output()
+ if err != nil {
+ return 0, 0, 0, err
+ }
+ ntcp += bytes.Count(lsof, []byte("TCP"))
+ for _, state := range []string{"LISTEN", "SYN_SENT", "SYN_RECEIVED", "ESTABLISHED"} {
+ nopen += bytes.Count(lsof, []byte(state))
+ }
+ for _, state := range []string{"CLOSED", "CLOSE_WAIT", "LAST_ACK", "FIN_WAIT_1", "FIN_WAIT_2", "CLOSING", "TIME_WAIT"} {
+ nclose += bytes.Count(lsof, []byte(state))
+ }
+ return ntcp, nopen, nclose, nil
+}
+
+func TestDialMultiFDLeak(t *testing.T) {
+ if !supportsIPv4 || !supportsIPv6 {
+ t.Skip("neither ipv4 nor ipv6 is supported")
+ }
+
+ halfDeadServer := func(dss *dualStackServer, ln Listener) {
+ for {
+ if c, err := ln.Accept(); err != nil {
+ return
+ } else {
+ // It just keeps established
+ // connections like a half-dead server
+ // does.
+ dss.putConn(c)
+ }
+ }
+ }
+ dss, err := newDualStackServer([]streamListener{
+ {net: "tcp4", addr: "127.0.0.1"},
+ {net: "tcp6", addr: "[::1]"},
+ })
+ if err != nil {
+ t.Fatalf("newDualStackServer failed: %v", err)
+ }
+ defer dss.teardown()
+ if err := dss.buildup(halfDeadServer); err != nil {
+ t.Fatalf("dualStackServer.buildup failed: %v", err)
+ }
+
+ _, before, _, err := numTCP()
+ if err != nil {
+ t.Skipf("skipping test; error finding or running lsof: %v", err)
+ }
+
+ var wg sync.WaitGroup
+ portnum, _, _ := dtoi(dss.port, 0)
+ ras := addrList{
+ // Losers that will fail to connect, see RFC 6890.
+ &TCPAddr{IP: IPv4(198, 18, 0, 254), Port: portnum},
+ &TCPAddr{IP: ParseIP("2001:2::254"), Port: portnum},
+
+ // Winner candidates of this race.
+ &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: portnum},
+ &TCPAddr{IP: IPv6loopback, Port: portnum},
+
+ // Losers that will have established connections.
+ &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: portnum},
+ &TCPAddr{IP: IPv6loopback, Port: portnum},
+ }
+ const T1 = 10 * time.Millisecond
+ const T2 = 2 * T1
+ const N = 10
+ for i := 0; i < N; i++ {
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ if c, err := dialMulti("tcp", "fast failover test", nil, ras, time.Now().Add(T1)); err == nil {
+ c.Close()
+ }
+ }()
+ }
+ wg.Wait()
+ time.Sleep(T2)
+
+ ntcp, after, nclose, err := numTCP()
+ if err != nil {
+ t.Skipf("skipping test; error finding or running lsof: %v", err)
+ }
+ t.Logf("tcp sessions: %v, open sessions: %v, closing sessions: %v", ntcp, after, nclose)
+
+ if after != before {
+ t.Fatalf("got %v open sessions; expected %v", after, before)
+ }
+}
+
func numFD() int {
if runtime.GOOS == "linux" {
f, err := os.Open("/proc/self/fd")
@@ -331,17 +425,22 @@ func numFD() int {
panic("numFDs not implemented on " + runtime.GOOS)
}
-var testPoller = flag.Bool("poller", false, "platform supports runtime-integrated poller")
-
// Assert that a failed Dial attempt does not leak
// runtime.PollDesc structures
func TestDialFailPDLeak(t *testing.T) {
- if !*testPoller {
- t.Skip("test disabled; use -poller to enable")
+ if testing.Short() {
+ t.Skip("skipping test in short mode")
+ }
+ if runtime.GOOS == "windows" && runtime.GOARCH == "386" {
+ // Just skip the test because it takes too long.
+ t.Skipf("skipping test on %q/%q", runtime.GOOS, runtime.GOARCH)
}
- const loops = 10
- const count = 20000
+ maxprocs := runtime.GOMAXPROCS(0)
+ loops := 10 + maxprocs
+ // 500 is enough to turn over the chunk of pollcache.
+ // See allocPollDesc in runtime/netpoll.goc.
+ const count = 500
var old runtime.MemStats // used by sysdelta
runtime.ReadMemStats(&old)
sysdelta := func() uint64 {
@@ -354,19 +453,26 @@ func TestDialFailPDLeak(t *testing.T) {
d := &Dialer{Timeout: time.Nanosecond} // don't bother TCP with handshaking
failcount := 0
for i := 0; i < loops; i++ {
+ var wg sync.WaitGroup
for i := 0; i < count; i++ {
- conn, err := d.Dial("tcp", "127.0.0.1:1")
- if err == nil {
- t.Error("dial should not succeed")
- conn.Close()
- t.FailNow()
- }
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ if c, err := d.Dial("tcp", "127.0.0.1:1"); err == nil {
+ t.Error("dial should not succeed")
+ c.Close()
+ }
+ }()
+ }
+ wg.Wait()
+ if t.Failed() {
+ t.FailNow()
}
if delta := sysdelta(); delta > 0 {
failcount++
}
// there are always some allocations on the first loop
- if failcount > 3 {
+ if failcount > maxprocs+2 {
t.Error("detected possible memory leak in runtime")
t.FailNow()
}
@@ -381,7 +487,6 @@ func TestDialer(t *testing.T) {
defer ln.Close()
ch := make(chan error, 1)
go func() {
- var err error
c, err := ln.Accept()
if err != nil {
ch <- fmt.Errorf("Accept failed: %v", err)
@@ -407,3 +512,46 @@ func TestDialer(t *testing.T) {
t.Error(err)
}
}
+
+func TestDialDualStackLocalhost(t *testing.T) {
+ if ips, err := LookupIP("localhost"); err != nil {
+ t.Fatalf("LookupIP failed: %v", err)
+ } else if len(ips) < 2 || !supportsIPv4 || !supportsIPv6 {
+ t.Skip("localhost doesn't have a pair of different address family IP addresses")
+ }
+
+ touchAndByeServer := func(dss *dualStackServer, ln Listener) {
+ for {
+ if c, err := ln.Accept(); err != nil {
+ return
+ } else {
+ c.Close()
+ }
+ }
+ }
+ dss, err := newDualStackServer([]streamListener{
+ {net: "tcp4", addr: "127.0.0.1"},
+ {net: "tcp6", addr: "[::1]"},
+ })
+ if err != nil {
+ t.Fatalf("newDualStackServer failed: %v", err)
+ }
+ defer dss.teardown()
+ if err := dss.buildup(touchAndByeServer); err != nil {
+ t.Fatalf("dualStackServer.buildup failed: %v", err)
+ }
+
+ d := &Dialer{DualStack: true}
+ for _ = range dss.lns {
+ if c, err := d.Dial("tcp", "localhost:"+dss.port); err != nil {
+ t.Errorf("Dial failed: %v", err)
+ } else {
+ if addr := c.LocalAddr().(*TCPAddr); addr.IP.To4() != nil {
+ dss.teardownNetwork("tcp4")
+ } else if addr.IP.To16() != nil && addr.IP.To4() == nil {
+ dss.teardownNetwork("tcp6")
+ }
+ c.Close()
+ }
+ }
+}
diff --git a/libgo/go/net/dialgoogle_test.go b/libgo/go/net/dialgoogle_test.go
index 73a94f5bf1c..b4ebad0e0dc 100644
--- a/libgo/go/net/dialgoogle_test.go
+++ b/libgo/go/net/dialgoogle_test.go
@@ -16,6 +16,59 @@ import (
// If an IPv6 tunnel is running, we can try dialing a real IPv6 address.
var testIPv6 = flag.Bool("ipv6", false, "assume ipv6 tunnel is present")
+func TestResolveGoogle(t *testing.T) {
+ if testing.Short() || !*testExternal {
+ t.Skip("skipping test to avoid external network")
+ }
+
+ for _, network := range []string{"tcp", "tcp4", "tcp6"} {
+ addr, err := ResolveTCPAddr(network, "www.google.com:http")
+ if err != nil {
+ if (network == "tcp" || network == "tcp4") && !supportsIPv4 {
+ t.Logf("ipv4 is not supported: %v", err)
+ } else if network == "tcp6" && !supportsIPv6 {
+ t.Logf("ipv6 is not supported: %v", err)
+ } else {
+ t.Errorf("ResolveTCPAddr failed: %v", err)
+ }
+ continue
+ }
+ if (network == "tcp" || network == "tcp4") && addr.IP.To4() == nil {
+ t.Errorf("got %v; expected an IPv4 address on %v", addr, network)
+ } else if network == "tcp6" && (addr.IP.To16() == nil || addr.IP.To4() != nil) {
+ t.Errorf("got %v; expected an IPv6 address on %v", addr, network)
+ }
+ }
+}
+
+func TestDialGoogle(t *testing.T) {
+ if testing.Short() || !*testExternal {
+ t.Skip("skipping test to avoid external network")
+ }
+
+ d := &Dialer{DualStack: true}
+ for _, network := range []string{"tcp", "tcp4", "tcp6"} {
+ if network == "tcp" && !supportsIPv4 && !supportsIPv6 {
+ t.Logf("skipping test; both ipv4 and ipv6 are not supported")
+ continue
+ } else if network == "tcp4" && !supportsIPv4 {
+ t.Logf("skipping test; ipv4 is not supported")
+ continue
+ } else if network == "tcp6" && !supportsIPv6 {
+ t.Logf("skipping test; ipv6 is not supported")
+ continue
+ } else if network == "tcp6" && !*testIPv6 {
+ t.Logf("test disabled; use -ipv6 to enable")
+ continue
+ }
+ if c, err := d.Dial(network, "www.google.com:http"); err != nil {
+ t.Errorf("Dial failed: %v", err)
+ } else {
+ c.Close()
+ }
+ }
+}
+
// fd is already connected to the destination, port 80.
// Run an HTTP request to fetch the appropriate page.
func fetchGoogle(t *testing.T, fd Conn, network, addr string) {
@@ -54,6 +107,30 @@ var googleaddrsipv4 = []string{
"[0:0:0:0:0:ffff::%d.%d.%d.%d]:80",
}
+func TestDNSThreadLimit(t *testing.T) {
+ if testing.Short() || !*testExternal {
+ t.Skip("skipping test to avoid external network")
+ }
+
+ const N = 10000
+ c := make(chan int, N)
+ for i := 0; i < N; i++ {
+ go func(i int) {
+ LookupIP(fmt.Sprintf("%d.net-test.golang.org", i))
+ c <- 1
+ }(i)
+ }
+ // Don't bother waiting for the stragglers; stop at 0.9 N.
+ for i := 0; i < N*9/10; i++ {
+ if i%100 == 0 {
+ //println("TestDNSThreadLimit:", i)
+ }
+ <-c
+ }
+
+ // If we're still here, it worked.
+}
+
func TestDialGoogleIPv4(t *testing.T) {
if testing.Short() || !*testExternal {
t.Skip("skipping test to avoid external network")
diff --git a/libgo/go/net/dnsclient.go b/libgo/go/net/dnsclient.go
index 76b192645aa..01db4372945 100644
--- a/libgo/go/net/dnsclient.go
+++ b/libgo/go/net/dnsclient.go
@@ -122,12 +122,9 @@ func isDomainName(s string) bool {
if len(s) > 255 {
return false
}
- if s[len(s)-1] != '.' { // simplify checking loop: make name end in dot
- s += "."
- }
last := byte('.')
- ok := false // ok once we've seen a letter
+ ok := false // Ok once we've seen a letter.
partlen := 0
for i := 0; i < len(s); i++ {
c := s[i]
@@ -141,13 +138,13 @@ func isDomainName(s string) bool {
// fine
partlen++
case c == '-':
- // byte before dash cannot be dot
+ // Byte before dash cannot be dot.
if last == '.' {
return false
}
partlen++
case c == '.':
- // byte before dot cannot be dot, dash
+ // Byte before dot cannot be dot, dash.
if last == '.' || last == '-' {
return false
}
@@ -158,6 +155,9 @@ func isDomainName(s string) bool {
}
last = c
}
+ if last == '-' || partlen > 63 {
+ return false
+ }
return ok
}
diff --git a/libgo/go/net/dnsclient_unix.go b/libgo/go/net/dnsclient_unix.go
index 9e21bb4a0f6..16cf420dcdb 100644
--- a/libgo/go/net/dnsclient_unix.go
+++ b/libgo/go/net/dnsclient_unix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd linux netbsd openbsd
+// +build darwin dragonfly freebsd linux netbsd openbsd
// DNS client: see RFC 1035.
// Has to be linked into package net for Dial.
@@ -17,6 +17,7 @@
package net
import (
+ "io"
"math/rand"
"sync"
"time"
@@ -25,6 +26,7 @@ import (
// Send a request on the connection and hope for a reply.
// Up to cfg.attempts attempts.
func exchange(cfg *dnsConfig, c Conn, name string, qtype uint16) (*dnsMsg, error) {
+ _, useTCP := c.(*TCPConn)
if len(name) >= 256 {
return nil, &DNSError{Err: "name too long", Name: name}
}
@@ -38,7 +40,10 @@ func exchange(cfg *dnsConfig, c Conn, name string, qtype uint16) (*dnsMsg, error
if !ok {
return nil, &DNSError{Err: "internal error - cannot pack message", Name: name}
}
-
+ if useTCP {
+ mlen := uint16(len(msg))
+ msg = append([]byte{byte(mlen >> 8), byte(mlen)}, msg...)
+ }
for attempt := 0; attempt < cfg.attempts; attempt++ {
n, err := c.Write(msg)
if err != nil {
@@ -46,20 +51,33 @@ func exchange(cfg *dnsConfig, c Conn, name string, qtype uint16) (*dnsMsg, error
}
if cfg.timeout == 0 {
- c.SetReadDeadline(time.Time{})
+ c.SetReadDeadline(noDeadline)
} else {
c.SetReadDeadline(time.Now().Add(time.Duration(cfg.timeout) * time.Second))
}
-
- buf := make([]byte, 2000) // More than enough.
- n, err = c.Read(buf)
+ buf := make([]byte, 2000)
+ if useTCP {
+ n, err = io.ReadFull(c, buf[:2])
+ if err != nil {
+ if e, ok := err.(Error); ok && e.Timeout() {
+ continue
+ }
+ }
+ mlen := int(buf[0])<<8 | int(buf[1])
+ if mlen > len(buf) {
+ buf = make([]byte, mlen)
+ }
+ n, err = io.ReadFull(c, buf[:mlen])
+ } else {
+ n, err = c.Read(buf)
+ }
if err != nil {
if e, ok := err.(Error); ok && e.Timeout() {
continue
}
return nil, err
}
- buf = buf[0:n]
+ buf = buf[:n]
in := new(dnsMsg)
if !in.Unpack(buf) || in.id != out.id {
continue
@@ -98,6 +116,19 @@ func tryOneName(cfg *dnsConfig, name string, qtype uint16) (cname string, addrs
err = merr
continue
}
+ if msg.truncated { // see RFC 5966
+ c, cerr = Dial("tcp", server)
+ if cerr != nil {
+ err = cerr
+ continue
+ }
+ msg, merr = exchange(cfg, c, name, qtype)
+ c.Close()
+ if merr != nil {
+ err = merr
+ continue
+ }
+ }
cname, addrs, err = answer(name, server, msg, qtype)
if err == nil || err.(*DNSError).Err == noSuchHost {
break
@@ -180,6 +211,12 @@ func lookup(name string, qtype uint16) (cname string, addrs []dnsRR, err error)
if err == nil {
return
}
+ if e, ok := err.(*DNSError); ok {
+ // Show original name passed to lookup, not suffixed one.
+ // In general we might have tried many suffixes; showing
+ // just one is misleading. See also golang.org/issue/6324.
+ e.Name = name
+ }
return
}
diff --git a/libgo/go/net/dnsclient_unix_test.go b/libgo/go/net/dnsclient_unix_test.go
new file mode 100644
index 00000000000..47dcb563bc5
--- /dev/null
+++ b/libgo/go/net/dnsclient_unix_test.go
@@ -0,0 +1,27 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd
+
+package net
+
+import (
+ "testing"
+)
+
+func TestTCPLookup(t *testing.T) {
+ if testing.Short() || !*testExternal {
+ t.Skip("skipping test to avoid external network")
+ }
+ c, err := Dial("tcp", "8.8.8.8:53")
+ if err != nil {
+ t.Fatalf("Dial failed: %v", err)
+ }
+ defer c.Close()
+ cfg := &dnsConfig{timeout: 10, attempts: 3}
+ _, err = exchange(cfg, c, "com.", dnsTypeALL)
+ if err != nil {
+ t.Fatalf("exchange failed: %v", err)
+ }
+}
diff --git a/libgo/go/net/dnsconfig_unix.go b/libgo/go/net/dnsconfig_unix.go
index bb46cc9007c..2f0f6c031f1 100644
--- a/libgo/go/net/dnsconfig_unix.go
+++ b/libgo/go/net/dnsconfig_unix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd linux netbsd openbsd
+// +build darwin dragonfly freebsd linux netbsd openbsd
// Read system DNS config from /etc/resolv.conf
diff --git a/libgo/go/net/dnsname_test.go b/libgo/go/net/dnsname_test.go
index 70df693f789..57dd25fe4c6 100644
--- a/libgo/go/net/dnsname_test.go
+++ b/libgo/go/net/dnsname_test.go
@@ -5,6 +5,7 @@
package net
import (
+ "strings"
"testing"
)
@@ -16,7 +17,6 @@ type testCase struct {
var tests = []testCase{
// RFC2181, section 11.
{"_xmpp-server._tcp.google.com", true},
- {"_xmpp-server._tcp.google.com", true},
{"foo.com", true},
{"1foo.com", true},
{"26.0.0.73.com", true},
@@ -24,6 +24,10 @@ var tests = []testCase{
{"fo1o.com", true},
{"foo1.com", true},
{"a.b..com", false},
+ {"a.b-.com", false},
+ {"a.b.com-", false},
+ {"a.b..", false},
+ {"b.com.", true},
}
func getTestCases(ch chan<- testCase) {
@@ -63,3 +67,17 @@ func TestDNSNames(t *testing.T) {
}
}
}
+
+func BenchmarkDNSNames(b *testing.B) {
+ benchmarks := append(tests, []testCase{
+ {strings.Repeat("a", 63), true},
+ {strings.Repeat("a", 64), false},
+ }...)
+ for n := 0; n < b.N; n++ {
+ for _, tc := range benchmarks {
+ if isDomainName(tc.name) != tc.result {
+ b.Errorf("isDomainName(%q) = %v; want %v", tc.name, !tc.result, tc.result)
+ }
+ }
+ }
+}
diff --git a/libgo/go/net/fd_bsd.go b/libgo/go/net/fd_bsd.go
deleted file mode 100644
index 8bb1ae53847..00000000000
--- a/libgo/go/net/fd_bsd.go
+++ /dev/null
@@ -1,123 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build freebsd netbsd openbsd
-
-// Waiting for FDs via kqueue/kevent.
-
-package net
-
-import (
- "os"
- "syscall"
-)
-
-type pollster struct {
- kq int
- eventbuf [10]syscall.Kevent_t
- events []syscall.Kevent_t
-
- // An event buffer for AddFD/DelFD.
- // Must hold pollServer lock.
- kbuf [1]syscall.Kevent_t
-}
-
-func newpollster() (p *pollster, err error) {
- p = new(pollster)
- if p.kq, err = syscall.Kqueue(); err != nil {
- return nil, os.NewSyscallError("kqueue", err)
- }
- syscall.CloseOnExec(p.kq)
- p.events = p.eventbuf[0:0]
- return p, nil
-}
-
-// First return value is whether the pollServer should be woken up.
-// This version always returns false.
-func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, error) {
- // pollServer is locked.
-
- var kmode int
- if mode == 'r' {
- kmode = syscall.EVFILT_READ
- } else {
- kmode = syscall.EVFILT_WRITE
- }
- ev := &p.kbuf[0]
- // EV_ADD - add event to kqueue list
- // EV_ONESHOT - delete the event the first time it triggers
- flags := syscall.EV_ADD
- if !repeat {
- flags |= syscall.EV_ONESHOT
- }
- syscall.SetKevent(ev, fd, kmode, flags)
-
- n, err := syscall.Kevent(p.kq, p.kbuf[:], nil, nil)
- if err != nil {
- return false, os.NewSyscallError("kevent", err)
- }
- if n != 1 || (ev.Flags&syscall.EV_ERROR) == 0 || int(ev.Ident) != fd || int(ev.Filter) != kmode {
- return false, os.NewSyscallError("kqueue phase error", err)
- }
- if ev.Data != 0 {
- return false, syscall.Errno(int(ev.Data))
- }
- return false, nil
-}
-
-// Return value is whether the pollServer should be woken up.
-// This version always returns false.
-func (p *pollster) DelFD(fd int, mode int) bool {
- // pollServer is locked.
-
- var kmode int
- if mode == 'r' {
- kmode = syscall.EVFILT_READ
- } else {
- kmode = syscall.EVFILT_WRITE
- }
- ev := &p.kbuf[0]
- // EV_DELETE - delete event from kqueue list
- syscall.SetKevent(ev, fd, kmode, syscall.EV_DELETE)
- syscall.Kevent(p.kq, p.kbuf[:], nil, nil)
- return false
-}
-
-func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err error) {
- var t *syscall.Timespec
- for len(p.events) == 0 {
- if nsec > 0 {
- if t == nil {
- t = new(syscall.Timespec)
- }
- *t = syscall.NsecToTimespec(nsec)
- }
-
- s.Unlock()
- n, err := syscall.Kevent(p.kq, nil, p.eventbuf[:], t)
- s.Lock()
-
- if err != nil {
- if err == syscall.EINTR {
- continue
- }
- return -1, 0, os.NewSyscallError("kevent", err)
- }
- if n == 0 {
- return -1, 0, nil
- }
- p.events = p.eventbuf[:n]
- }
- ev := &p.events[0]
- p.events = p.events[1:]
- fd = int(ev.Ident)
- if ev.Filter == syscall.EVFILT_READ {
- mode = 'r'
- } else {
- mode = 'w'
- }
- return fd, mode, nil
-}
-
-func (p *pollster) Close() error { return os.NewSyscallError("close", syscall.Close(p.kq)) }
diff --git a/libgo/go/net/fd_mutex.go b/libgo/go/net/fd_mutex.go
new file mode 100644
index 00000000000..6d5509d7f2a
--- /dev/null
+++ b/libgo/go/net/fd_mutex.go
@@ -0,0 +1,184 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package net
+
+import "sync/atomic"
+
+// fdMutex is a specialized synchronization primitive
+// that manages lifetime of an fd and serializes access
+// to Read and Write methods on netFD.
+type fdMutex struct {
+ state uint64
+ rsema uint32
+ wsema uint32
+}
+
+// fdMutex.state is organized as follows:
+// 1 bit - whether netFD is closed, if set all subsequent lock operations will fail.
+// 1 bit - lock for read operations.
+// 1 bit - lock for write operations.
+// 20 bits - total number of references (read+write+misc).
+// 20 bits - number of outstanding read waiters.
+// 20 bits - number of outstanding write waiters.
+const (
+ mutexClosed = 1 << 0
+ mutexRLock = 1 << 1
+ mutexWLock = 1 << 2
+ mutexRef = 1 << 3
+ mutexRefMask = (1<<20 - 1) << 3
+ mutexRWait = 1 << 23
+ mutexRMask = (1<<20 - 1) << 23
+ mutexWWait = 1 << 43
+ mutexWMask = (1<<20 - 1) << 43
+)
+
+// Read operations must do RWLock(true)/RWUnlock(true).
+// Write operations must do RWLock(false)/RWUnlock(false).
+// Misc operations must do Incref/Decref. Misc operations include functions like
+// setsockopt and setDeadline. They need to use Incref/Decref to ensure that
+// they operate on the correct fd in presence of a concurrent Close call
+// (otherwise fd can be closed under their feet).
+// Close operation must do IncrefAndClose/Decref.
+
+// RWLock/Incref return whether fd is open.
+// RWUnlock/Decref return whether fd is closed and there are no remaining references.
+
+func (mu *fdMutex) Incref() bool {
+ for {
+ old := atomic.LoadUint64(&mu.state)
+ if old&mutexClosed != 0 {
+ return false
+ }
+ new := old + mutexRef
+ if new&mutexRefMask == 0 {
+ panic("net: inconsistent fdMutex")
+ }
+ if atomic.CompareAndSwapUint64(&mu.state, old, new) {
+ return true
+ }
+ }
+}
+
+func (mu *fdMutex) IncrefAndClose() bool {
+ for {
+ old := atomic.LoadUint64(&mu.state)
+ if old&mutexClosed != 0 {
+ return false
+ }
+ // Mark as closed and acquire a reference.
+ new := (old | mutexClosed) + mutexRef
+ if new&mutexRefMask == 0 {
+ panic("net: inconsistent fdMutex")
+ }
+ // Remove all read and write waiters.
+ new &^= mutexRMask | mutexWMask
+ if atomic.CompareAndSwapUint64(&mu.state, old, new) {
+ // Wake all read and write waiters,
+ // they will observe closed flag after wakeup.
+ for old&mutexRMask != 0 {
+ old -= mutexRWait
+ runtime_Semrelease(&mu.rsema)
+ }
+ for old&mutexWMask != 0 {
+ old -= mutexWWait
+ runtime_Semrelease(&mu.wsema)
+ }
+ return true
+ }
+ }
+}
+
+func (mu *fdMutex) Decref() bool {
+ for {
+ old := atomic.LoadUint64(&mu.state)
+ if old&mutexRefMask == 0 {
+ panic("net: inconsistent fdMutex")
+ }
+ new := old - mutexRef
+ if atomic.CompareAndSwapUint64(&mu.state, old, new) {
+ return new&(mutexClosed|mutexRefMask) == mutexClosed
+ }
+ }
+}
+
+func (mu *fdMutex) RWLock(read bool) bool {
+ var mutexBit, mutexWait, mutexMask uint64
+ var mutexSema *uint32
+ if read {
+ mutexBit = mutexRLock
+ mutexWait = mutexRWait
+ mutexMask = mutexRMask
+ mutexSema = &mu.rsema
+ } else {
+ mutexBit = mutexWLock
+ mutexWait = mutexWWait
+ mutexMask = mutexWMask
+ mutexSema = &mu.wsema
+ }
+ for {
+ old := atomic.LoadUint64(&mu.state)
+ if old&mutexClosed != 0 {
+ return false
+ }
+ var new uint64
+ if old&mutexBit == 0 {
+ // Lock is free, acquire it.
+ new = (old | mutexBit) + mutexRef
+ if new&mutexRefMask == 0 {
+ panic("net: inconsistent fdMutex")
+ }
+ } else {
+ // Wait for lock.
+ new = old + mutexWait
+ if new&mutexMask == 0 {
+ panic("net: inconsistent fdMutex")
+ }
+ }
+ if atomic.CompareAndSwapUint64(&mu.state, old, new) {
+ if old&mutexBit == 0 {
+ return true
+ }
+ runtime_Semacquire(mutexSema)
+ // The signaller has subtracted mutexWait.
+ }
+ }
+}
+
+func (mu *fdMutex) RWUnlock(read bool) bool {
+ var mutexBit, mutexWait, mutexMask uint64
+ var mutexSema *uint32
+ if read {
+ mutexBit = mutexRLock
+ mutexWait = mutexRWait
+ mutexMask = mutexRMask
+ mutexSema = &mu.rsema
+ } else {
+ mutexBit = mutexWLock
+ mutexWait = mutexWWait
+ mutexMask = mutexWMask
+ mutexSema = &mu.wsema
+ }
+ for {
+ old := atomic.LoadUint64(&mu.state)
+ if old&mutexBit == 0 || old&mutexRefMask == 0 {
+ panic("net: inconsistent fdMutex")
+ }
+ // Drop lock, drop reference and wake read waiter if present.
+ new := (old &^ mutexBit) - mutexRef
+ if old&mutexMask != 0 {
+ new -= mutexWait
+ }
+ if atomic.CompareAndSwapUint64(&mu.state, old, new) {
+ if old&mutexMask != 0 {
+ runtime_Semrelease(mutexSema)
+ }
+ return new&(mutexClosed|mutexRefMask) == mutexClosed
+ }
+ }
+}
+
+// Implemented in runtime package.
+func runtime_Semacquire(sema *uint32)
+func runtime_Semrelease(sema *uint32)
diff --git a/libgo/go/net/fd_mutex_test.go b/libgo/go/net/fd_mutex_test.go
new file mode 100644
index 00000000000..8383084b7a2
--- /dev/null
+++ b/libgo/go/net/fd_mutex_test.go
@@ -0,0 +1,186 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package net
+
+import (
+ "math/rand"
+ "runtime"
+ "testing"
+ "time"
+)
+
+func TestMutexLock(t *testing.T) {
+ var mu fdMutex
+
+ if !mu.Incref() {
+ t.Fatal("broken")
+ }
+ if mu.Decref() {
+ t.Fatal("broken")
+ }
+
+ if !mu.RWLock(true) {
+ t.Fatal("broken")
+ }
+ if mu.RWUnlock(true) {
+ t.Fatal("broken")
+ }
+
+ if !mu.RWLock(false) {
+ t.Fatal("broken")
+ }
+ if mu.RWUnlock(false) {
+ t.Fatal("broken")
+ }
+}
+
+func TestMutexClose(t *testing.T) {
+ var mu fdMutex
+ if !mu.IncrefAndClose() {
+ t.Fatal("broken")
+ }
+
+ if mu.Incref() {
+ t.Fatal("broken")
+ }
+ if mu.RWLock(true) {
+ t.Fatal("broken")
+ }
+ if mu.RWLock(false) {
+ t.Fatal("broken")
+ }
+ if mu.IncrefAndClose() {
+ t.Fatal("broken")
+ }
+}
+
+func TestMutexCloseUnblock(t *testing.T) {
+ c := make(chan bool)
+ var mu fdMutex
+ mu.RWLock(true)
+ for i := 0; i < 4; i++ {
+ go func() {
+ if mu.RWLock(true) {
+ t.Fatal("broken")
+ }
+ c <- true
+ }()
+ }
+ // Concurrent goroutines must not be able to read lock the mutex.
+ time.Sleep(time.Millisecond)
+ select {
+ case <-c:
+ t.Fatal("broken")
+ default:
+ }
+ mu.IncrefAndClose() // Must unblock the readers.
+ for i := 0; i < 4; i++ {
+ select {
+ case <-c:
+ case <-time.After(10 * time.Second):
+ t.Fatal("broken")
+ }
+ }
+ if mu.Decref() {
+ t.Fatal("broken")
+ }
+ if !mu.RWUnlock(true) {
+ t.Fatal("broken")
+ }
+}
+
+func TestMutexPanic(t *testing.T) {
+ ensurePanics := func(f func()) {
+ defer func() {
+ if recover() == nil {
+ t.Fatal("does not panic")
+ }
+ }()
+ f()
+ }
+
+ var mu fdMutex
+ ensurePanics(func() { mu.Decref() })
+ ensurePanics(func() { mu.RWUnlock(true) })
+ ensurePanics(func() { mu.RWUnlock(false) })
+
+ ensurePanics(func() { mu.Incref(); mu.Decref(); mu.Decref() })
+ ensurePanics(func() { mu.RWLock(true); mu.RWUnlock(true); mu.RWUnlock(true) })
+ ensurePanics(func() { mu.RWLock(false); mu.RWUnlock(false); mu.RWUnlock(false) })
+
+ // ensure that it's still not broken
+ mu.Incref()
+ mu.Decref()
+ mu.RWLock(true)
+ mu.RWUnlock(true)
+ mu.RWLock(false)
+ mu.RWUnlock(false)
+}
+
+func TestMutexStress(t *testing.T) {
+ P := 8
+ N := int(1e6)
+ if testing.Short() {
+ P = 4
+ N = 1e4
+ }
+ defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(P))
+ done := make(chan bool)
+ var mu fdMutex
+ var readState [2]uint64
+ var writeState [2]uint64
+ for p := 0; p < P; p++ {
+ go func() {
+ r := rand.New(rand.NewSource(rand.Int63()))
+ for i := 0; i < N; i++ {
+ switch r.Intn(3) {
+ case 0:
+ if !mu.Incref() {
+ t.Fatal("broken")
+ }
+ if mu.Decref() {
+ t.Fatal("broken")
+ }
+ case 1:
+ if !mu.RWLock(true) {
+ t.Fatal("broken")
+ }
+ // Ensure that it provides mutual exclusion for readers.
+ if readState[0] != readState[1] {
+ t.Fatal("broken")
+ }
+ readState[0]++
+ readState[1]++
+ if mu.RWUnlock(true) {
+ t.Fatal("broken")
+ }
+ case 2:
+ if !mu.RWLock(false) {
+ t.Fatal("broken")
+ }
+ // Ensure that it provides mutual exclusion for writers.
+ if writeState[0] != writeState[1] {
+ t.Fatal("broken")
+ }
+ writeState[0]++
+ writeState[1]++
+ if mu.RWUnlock(false) {
+ t.Fatal("broken")
+ }
+ }
+ }
+ done <- true
+ }()
+ }
+ for p := 0; p < P; p++ {
+ <-done
+ }
+ if !mu.IncrefAndClose() {
+ t.Fatal("broken")
+ }
+ if !mu.Decref() {
+ t.Fatal("broken")
+ }
+}
diff --git a/libgo/go/net/fd_plan9.go b/libgo/go/net/fd_plan9.go
index e9527a3743b..acc82940217 100644
--- a/libgo/go/net/fd_plan9.go
+++ b/libgo/go/net/fd_plan9.go
@@ -18,15 +18,13 @@ type netFD struct {
laddr, raddr Addr
}
-var canCancelIO = true // used for testing current package
-
func sysInit() {
}
-func resolveAndDial(net, addr string, localAddr Addr, deadline time.Time) (Conn, error) {
+func dial(net string, ra Addr, dialer func(time.Time) (Conn, error), deadline time.Time) (Conn, error) {
// On plan9, use the relatively inefficient
// goroutine-racing implementation.
- return resolveAndDialChannel(net, addr, localAddr, deadline)
+ return dialChannel(net, ra, dialer, deadline)
}
func newFD(proto, name string, ctl, data *os.File, laddr, raddr Addr) *netFD {
@@ -108,15 +106,15 @@ func (fd *netFD) file(f *os.File, s string) (*os.File, error) {
return os.NewFile(uintptr(dfd), s), nil
}
-func setDeadline(fd *netFD, t time.Time) error {
+func (fd *netFD) setDeadline(t time.Time) error {
return syscall.EPLAN9
}
-func setReadDeadline(fd *netFD, t time.Time) error {
+func (fd *netFD) setReadDeadline(t time.Time) error {
return syscall.EPLAN9
}
-func setWriteDeadline(fd *netFD, t time.Time) error {
+func (fd *netFD) setWriteDeadline(t time.Time) error {
return syscall.EPLAN9
}
@@ -127,3 +125,7 @@ func setReadBuffer(fd *netFD, bytes int) error {
func setWriteBuffer(fd *netFD, bytes int) error {
return syscall.EPLAN9
}
+
+func skipRawSocketTests() (skip bool, skipmsg string, err error) {
+ return true, "skipping test on plan9", nil
+}
diff --git a/libgo/go/net/fd_poll_runtime.go b/libgo/go/net/fd_poll_runtime.go
index e3b4f7e4648..e2b2768864a 100644
--- a/libgo/go/net/fd_poll_runtime.go
+++ b/libgo/go/net/fd_poll_runtime.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin linux
+// +build darwin dragonfly freebsd linux netbsd openbsd windows
package net
@@ -13,27 +13,23 @@ import (
)
func runtime_pollServerInit()
-func runtime_pollOpen(fd int) (uintptr, int)
+func runtime_pollOpen(fd uintptr) (uintptr, int)
func runtime_pollClose(ctx uintptr)
func runtime_pollWait(ctx uintptr, mode int) int
+func runtime_pollWaitCanceled(ctx uintptr, mode int) int
func runtime_pollReset(ctx uintptr, mode int) int
func runtime_pollSetDeadline(ctx uintptr, d int64, mode int)
func runtime_pollUnblock(ctx uintptr)
-var canCancelIO = true // used for testing current package
-
type pollDesc struct {
runtimeCtx uintptr
}
var serverInit sync.Once
-func sysInit() {
-}
-
func (pd *pollDesc) Init(fd *netFD) error {
serverInit.Do(runtime_pollServerInit)
- ctx, errno := runtime_pollOpen(fd.sysfd)
+ ctx, errno := runtime_pollOpen(uintptr(fd.sysfd))
if errno != 0 {
return syscall.Errno(errno)
}
@@ -42,7 +38,11 @@ func (pd *pollDesc) Init(fd *netFD) error {
}
func (pd *pollDesc) Close() {
+ if pd.runtimeCtx == 0 {
+ return
+ }
runtime_pollClose(pd.runtimeCtx)
+ pd.runtimeCtx = 0
}
func (pd *pollDesc) Lock() {
@@ -57,28 +57,49 @@ func (pd *pollDesc) Wakeup() {
// Evict evicts fd from the pending list, unblocking any I/O running on fd.
// Return value is whether the pollServer should be woken up.
func (pd *pollDesc) Evict() bool {
+ if pd.runtimeCtx == 0 {
+ return false
+ }
runtime_pollUnblock(pd.runtimeCtx)
return false
}
-func (pd *pollDesc) PrepareRead() error {
- res := runtime_pollReset(pd.runtimeCtx, 'r')
+func (pd *pollDesc) Prepare(mode int) error {
+ res := runtime_pollReset(pd.runtimeCtx, mode)
return convertErr(res)
}
+func (pd *pollDesc) PrepareRead() error {
+ return pd.Prepare('r')
+}
+
func (pd *pollDesc) PrepareWrite() error {
- res := runtime_pollReset(pd.runtimeCtx, 'w')
+ return pd.Prepare('w')
+}
+
+func (pd *pollDesc) Wait(mode int) error {
+ res := runtime_pollWait(pd.runtimeCtx, mode)
return convertErr(res)
}
func (pd *pollDesc) WaitRead() error {
- res := runtime_pollWait(pd.runtimeCtx, 'r')
- return convertErr(res)
+ return pd.Wait('r')
}
func (pd *pollDesc) WaitWrite() error {
- res := runtime_pollWait(pd.runtimeCtx, 'w')
- return convertErr(res)
+ return pd.Wait('w')
+}
+
+func (pd *pollDesc) WaitCanceled(mode int) {
+ runtime_pollWaitCanceled(pd.runtimeCtx, mode)
+}
+
+func (pd *pollDesc) WaitCanceledRead() {
+ pd.WaitCanceled('r')
+}
+
+func (pd *pollDesc) WaitCanceledWrite() {
+ pd.WaitCanceled('w')
}
func convertErr(res int) error {
@@ -90,19 +111,20 @@ func convertErr(res int) error {
case 2:
return errTimeout
}
+ println("unreachable: ", res)
panic("unreachable")
}
-func setReadDeadline(fd *netFD, t time.Time) error {
- return setDeadlineImpl(fd, t, 'r')
+func (fd *netFD) setDeadline(t time.Time) error {
+ return setDeadlineImpl(fd, t, 'r'+'w')
}
-func setWriteDeadline(fd *netFD, t time.Time) error {
- return setDeadlineImpl(fd, t, 'w')
+func (fd *netFD) setReadDeadline(t time.Time) error {
+ return setDeadlineImpl(fd, t, 'r')
}
-func setDeadline(fd *netFD, t time.Time) error {
- return setDeadlineImpl(fd, t, 'r'+'w')
+func (fd *netFD) setWriteDeadline(t time.Time) error {
+ return setDeadlineImpl(fd, t, 'w')
}
func setDeadlineImpl(fd *netFD, t time.Time, mode int) error {
@@ -110,7 +132,7 @@ func setDeadlineImpl(fd *netFD, t time.Time, mode int) error {
if t.IsZero() {
d = 0
}
- if err := fd.incref(false); err != nil {
+ if err := fd.incref(); err != nil {
return err
}
runtime_pollSetDeadline(fd.pd.runtimeCtx, d, mode)
diff --git a/libgo/go/net/fd_poll_unix.go b/libgo/go/net/fd_poll_unix.go
deleted file mode 100644
index 307e577e999..00000000000
--- a/libgo/go/net/fd_poll_unix.go
+++ /dev/null
@@ -1,360 +0,0 @@
-// Copyright 2013 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build freebsd netbsd openbsd
-
-package net
-
-import (
- "os"
- "runtime"
- "sync"
- "syscall"
- "time"
-)
-
-// A pollServer helps FDs determine when to retry a non-blocking
-// read or write after they get EAGAIN. When an FD needs to wait,
-// call s.WaitRead() or s.WaitWrite() to pass the request to the poll server.
-// When the pollServer finds that i/o on FD should be possible
-// again, it will send on fd.cr/fd.cw to wake any waiting goroutines.
-//
-// To avoid races in closing, all fd operations are locked and
-// refcounted. when netFD.Close() is called, it calls syscall.Shutdown
-// and sets a closing flag. Only when the last reference is removed
-// will the fd be closed.
-
-type pollServer struct {
- pr, pw *os.File
- poll *pollster // low-level OS hooks
- sync.Mutex // controls pending and deadline
- pending map[int]*pollDesc
- deadline int64 // next deadline (nsec since 1970)
-}
-
-// A pollDesc contains netFD state related to pollServer.
-type pollDesc struct {
- // immutable after Init()
- pollServer *pollServer
- sysfd int
- cr, cw chan error
-
- // mutable, protected by pollServer mutex
- closing bool
- ncr, ncw int
-
- // mutable, safe for concurrent access
- rdeadline, wdeadline deadline
-}
-
-func newPollServer() (s *pollServer, err error) {
- s = new(pollServer)
- if s.pr, s.pw, err = os.Pipe(); err != nil {
- return nil, err
- }
- if err = syscall.SetNonblock(int(s.pr.Fd()), true); err != nil {
- goto Errno
- }
- if err = syscall.SetNonblock(int(s.pw.Fd()), true); err != nil {
- goto Errno
- }
- if s.poll, err = newpollster(); err != nil {
- goto Error
- }
- if _, err = s.poll.AddFD(int(s.pr.Fd()), 'r', true); err != nil {
- s.poll.Close()
- goto Error
- }
- s.pending = make(map[int]*pollDesc)
- go s.Run()
- return s, nil
-
-Errno:
- err = &os.PathError{
- Op: "setnonblock",
- Path: s.pr.Name(),
- Err: err,
- }
-Error:
- s.pr.Close()
- s.pw.Close()
- return nil, err
-}
-
-func (s *pollServer) AddFD(pd *pollDesc, mode int) error {
- s.Lock()
- intfd := pd.sysfd
- if intfd < 0 || pd.closing {
- // fd closed underfoot
- s.Unlock()
- return errClosing
- }
-
- var t int64
- key := intfd << 1
- if mode == 'r' {
- pd.ncr++
- t = pd.rdeadline.value()
- } else {
- pd.ncw++
- key++
- t = pd.wdeadline.value()
- }
- s.pending[key] = pd
- doWakeup := false
- if t > 0 && (s.deadline == 0 || t < s.deadline) {
- s.deadline = t
- doWakeup = true
- }
-
- wake, err := s.poll.AddFD(intfd, mode, false)
- s.Unlock()
- if err != nil {
- return err
- }
- if wake || doWakeup {
- s.Wakeup()
- }
- return nil
-}
-
-// Evict evicts pd from the pending list, unblocking
-// any I/O running on pd. The caller must have locked
-// pollserver.
-// Return value is whether the pollServer should be woken up.
-func (s *pollServer) Evict(pd *pollDesc) bool {
- pd.closing = true
- doWakeup := false
- if s.pending[pd.sysfd<<1] == pd {
- s.WakeFD(pd, 'r', errClosing)
- if s.poll.DelFD(pd.sysfd, 'r') {
- doWakeup = true
- }
- delete(s.pending, pd.sysfd<<1)
- }
- if s.pending[pd.sysfd<<1|1] == pd {
- s.WakeFD(pd, 'w', errClosing)
- if s.poll.DelFD(pd.sysfd, 'w') {
- doWakeup = true
- }
- delete(s.pending, pd.sysfd<<1|1)
- }
- return doWakeup
-}
-
-var wakeupbuf [1]byte
-
-func (s *pollServer) Wakeup() { s.pw.Write(wakeupbuf[0:]) }
-
-func (s *pollServer) LookupFD(fd int, mode int) *pollDesc {
- key := fd << 1
- if mode == 'w' {
- key++
- }
- netfd, ok := s.pending[key]
- if !ok {
- return nil
- }
- delete(s.pending, key)
- return netfd
-}
-
-func (s *pollServer) WakeFD(pd *pollDesc, mode int, err error) {
- if mode == 'r' {
- for pd.ncr > 0 {
- pd.ncr--
- pd.cr <- err
- }
- } else {
- for pd.ncw > 0 {
- pd.ncw--
- pd.cw <- err
- }
- }
-}
-
-func (s *pollServer) CheckDeadlines() {
- now := time.Now().UnixNano()
- // TODO(rsc): This will need to be handled more efficiently,
- // probably with a heap indexed by wakeup time.
-
- var nextDeadline int64
- for key, pd := range s.pending {
- var t int64
- var mode int
- if key&1 == 0 {
- mode = 'r'
- } else {
- mode = 'w'
- }
- if mode == 'r' {
- t = pd.rdeadline.value()
- } else {
- t = pd.wdeadline.value()
- }
- if t > 0 {
- if t <= now {
- delete(s.pending, key)
- s.poll.DelFD(pd.sysfd, mode)
- s.WakeFD(pd, mode, errTimeout)
- } else if nextDeadline == 0 || t < nextDeadline {
- nextDeadline = t
- }
- }
- }
- s.deadline = nextDeadline
-}
-
-func (s *pollServer) Run() {
- var scratch [100]byte
- s.Lock()
- defer s.Unlock()
- for {
- var timeout int64 // nsec to wait for or 0 for none
- if s.deadline > 0 {
- timeout = s.deadline - time.Now().UnixNano()
- if timeout <= 0 {
- s.CheckDeadlines()
- continue
- }
- }
- fd, mode, err := s.poll.WaitFD(s, timeout)
- if err != nil {
- print("pollServer WaitFD: ", err.Error(), "\n")
- return
- }
- if fd < 0 {
- // Timeout happened.
- s.CheckDeadlines()
- continue
- }
- if fd == int(s.pr.Fd()) {
- // Drain our wakeup pipe (we could loop here,
- // but it's unlikely that there are more than
- // len(scratch) wakeup calls).
- s.pr.Read(scratch[0:])
- s.CheckDeadlines()
- } else {
- pd := s.LookupFD(fd, mode)
- if pd == nil {
- // This can happen because the WaitFD runs without
- // holding s's lock, so there might be a pending wakeup
- // for an fd that has been evicted. No harm done.
- continue
- }
- s.WakeFD(pd, mode, nil)
- }
- }
-}
-
-func (pd *pollDesc) Close() {
-}
-
-func (pd *pollDesc) Lock() {
- pd.pollServer.Lock()
-}
-
-func (pd *pollDesc) Unlock() {
- pd.pollServer.Unlock()
-}
-
-func (pd *pollDesc) Wakeup() {
- pd.pollServer.Wakeup()
-}
-
-func (pd *pollDesc) PrepareRead() error {
- if pd.rdeadline.expired() {
- return errTimeout
- }
- return nil
-}
-
-func (pd *pollDesc) PrepareWrite() error {
- if pd.wdeadline.expired() {
- return errTimeout
- }
- return nil
-}
-
-func (pd *pollDesc) WaitRead() error {
- err := pd.pollServer.AddFD(pd, 'r')
- if err == nil {
- err = <-pd.cr
- }
- return err
-}
-
-func (pd *pollDesc) WaitWrite() error {
- err := pd.pollServer.AddFD(pd, 'w')
- if err == nil {
- err = <-pd.cw
- }
- return err
-}
-
-func (pd *pollDesc) Evict() bool {
- return pd.pollServer.Evict(pd)
-}
-
-// Spread network FDs over several pollServers.
-
-var pollMaxN int
-var pollservers []*pollServer
-var startServersOnce []func()
-
-var canCancelIO = true // used for testing current package
-
-func sysInit() {
- pollMaxN = runtime.NumCPU()
- if pollMaxN > 8 {
- pollMaxN = 8 // No improvement then.
- }
- pollservers = make([]*pollServer, pollMaxN)
- startServersOnce = make([]func(), pollMaxN)
- for i := 0; i < pollMaxN; i++ {
- k := i
- once := new(sync.Once)
- startServersOnce[i] = func() { once.Do(func() { startServer(k) }) }
- }
-}
-
-func startServer(k int) {
- p, err := newPollServer()
- if err != nil {
- panic(err)
- }
- pollservers[k] = p
-}
-
-func (pd *pollDesc) Init(fd *netFD) error {
- pollN := runtime.GOMAXPROCS(0)
- if pollN > pollMaxN {
- pollN = pollMaxN
- }
- k := fd.sysfd % pollN
- startServersOnce[k]()
- pd.sysfd = fd.sysfd
- pd.pollServer = pollservers[k]
- pd.cr = make(chan error, 1)
- pd.cw = make(chan error, 1)
- return nil
-}
-
-// TODO(dfc) these unused error returns could be removed
-
-func setReadDeadline(fd *netFD, t time.Time) error {
- fd.pd.rdeadline.setTime(t)
- return nil
-}
-
-func setWriteDeadline(fd *netFD, t time.Time) error {
- fd.pd.wdeadline.setTime(t)
- return nil
-}
-
-func setDeadline(fd *netFD, t time.Time) error {
- setReadDeadline(fd, t)
- setWriteDeadline(fd, t)
- return nil
-}
diff --git a/libgo/go/net/fd_posix_test.go b/libgo/go/net/fd_posix_test.go
deleted file mode 100644
index 8be0335d61c..00000000000
--- a/libgo/go/net/fd_posix_test.go
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build darwin freebsd linux netbsd openbsd windows
-
-package net
-
-import (
- "testing"
- "time"
-)
-
-var deadlineSetTimeTests = []struct {
- input time.Time
- expected int64
-}{
- {time.Time{}, 0},
- {time.Date(2009, 11, 10, 23, 00, 00, 00, time.UTC), 1257894000000000000}, // 2009-11-10 23:00:00 +0000 UTC
-}
-
-func TestDeadlineSetTime(t *testing.T) {
- for _, tt := range deadlineSetTimeTests {
- var d deadline
- d.setTime(tt.input)
- actual := d.value()
- expected := int64(0)
- if !tt.input.IsZero() {
- expected = tt.input.UnixNano()
- }
- if actual != expected {
- t.Errorf("set/value failed: expected %v, actual %v", expected, actual)
- }
- }
-}
-
-var deadlineExpiredTests = []struct {
- deadline time.Time
- expired bool
-}{
- // note, times are relative to the start of the test run, not
- // the start of TestDeadlineExpired
- {time.Now().Add(5 * time.Minute), false},
- {time.Now().Add(-5 * time.Minute), true},
- {time.Time{}, false}, // no deadline set
-}
-
-func TestDeadlineExpired(t *testing.T) {
- for _, tt := range deadlineExpiredTests {
- var d deadline
- d.set(tt.deadline.UnixNano())
- expired := d.expired()
- if expired != tt.expired {
- t.Errorf("expire failed: expected %v, actual %v", tt.expired, expired)
- }
- }
-}
diff --git a/libgo/go/net/fd_unix.go b/libgo/go/net/fd_unix.go
index 8c59bff989c..4911ab0abe3 100644
--- a/libgo/go/net/fd_unix.go
+++ b/libgo/go/net/fd_unix.go
@@ -2,70 +2,59 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd linux netbsd openbsd
+// +build darwin dragonfly freebsd linux netbsd openbsd
package net
import (
"io"
"os"
- "sync"
+ "runtime"
+ "sync/atomic"
"syscall"
"time"
)
// Network file descriptor.
type netFD struct {
- // locking/lifetime of sysfd
- sysmu sync.Mutex
- sysref int
-
- // must lock both sysmu and pollDesc to write
- // can lock either to read
- closing bool
+ // locking/lifetime of sysfd + serialize access to Read and Write methods
+ fdmu fdMutex
// immutable until Close
sysfd int
family int
sotype int
isConnected bool
- sysfile *os.File
net string
laddr Addr
raddr Addr
- // serialize access to Read and Write methods
- rio, wio sync.Mutex
-
// wait server
pd pollDesc
}
-func resolveAndDial(net, addr string, localAddr Addr, deadline time.Time) (Conn, error) {
- ra, err := resolveAddr("dial", net, addr, deadline)
- if err != nil {
- return nil, err
- }
- return dial(net, addr, localAddr, ra, deadline)
+func sysInit() {
}
-func newFD(fd, family, sotype int, net string) (*netFD, error) {
- netfd := &netFD{
- sysfd: fd,
- family: family,
- sotype: sotype,
- net: net,
- }
- if err := netfd.pd.Init(netfd); err != nil {
- return nil, err
+func dial(network string, ra Addr, dialer func(time.Time) (Conn, error), deadline time.Time) (Conn, error) {
+ return dialer(deadline)
+}
+
+func newFD(sysfd, family, sotype int, net string) (*netFD, error) {
+ return &netFD{sysfd: sysfd, family: family, sotype: sotype, net: net}, nil
+}
+
+func (fd *netFD) init() error {
+ if err := fd.pd.Init(fd); err != nil {
+ return err
}
- return netfd, nil
+ return nil
}
func (fd *netFD) setAddr(laddr, raddr Addr) {
fd.laddr = laddr
fd.raddr = raddr
- fd.sysfile = os.NewFile(uintptr(fd.sysfd), fd.net)
+ runtime.SetFinalizer(fd, (*netFD).Close)
}
func (fd *netFD) name() string {
@@ -80,8 +69,9 @@ func (fd *netFD) name() string {
}
func (fd *netFD) connect(la, ra syscall.Sockaddr) error {
- fd.wio.Lock()
- defer fd.wio.Unlock()
+ // Do not need to call fd.writeLock here,
+ // because fd is not yet accessible to user,
+ // so no concurrent operations are possible.
if err := fd.pd.PrepareWrite(); err != nil {
return err
}
@@ -100,48 +90,69 @@ func (fd *netFD) connect(la, ra syscall.Sockaddr) error {
return nil
}
+func (fd *netFD) destroy() {
+ // Poller may want to unregister fd in readiness notification mechanism,
+ // so this must be executed before closesocket.
+ fd.pd.Close()
+ closesocket(fd.sysfd)
+ fd.sysfd = -1
+ runtime.SetFinalizer(fd, nil)
+}
+
// Add a reference to this fd.
-// If closing==true, pollDesc must be locked; mark the fd as closing.
// Returns an error if the fd cannot be used.
-func (fd *netFD) incref(closing bool) error {
- fd.sysmu.Lock()
- if fd.closing {
- fd.sysmu.Unlock()
+func (fd *netFD) incref() error {
+ if !fd.fdmu.Incref() {
return errClosing
}
- fd.sysref++
- if closing {
- fd.closing = true
- }
- fd.sysmu.Unlock()
return nil
}
-// Remove a reference to this FD and close if we've been asked to do so (and
-// there are no references left.
+// Remove a reference to this FD and close if we've been asked to do so
+// (and there are no references left).
func (fd *netFD) decref() {
- fd.sysmu.Lock()
- fd.sysref--
- if fd.closing && fd.sysref == 0 {
- // Poller may want to unregister fd in readiness notification mechanism,
- // so this must be executed before sysfile.Close().
- fd.pd.Close()
- if fd.sysfile != nil {
- fd.sysfile.Close()
- fd.sysfile = nil
- } else {
- closesocket(fd.sysfd)
- }
- fd.sysfd = -1
+ if fd.fdmu.Decref() {
+ fd.destroy()
+ }
+}
+
+// Add a reference to this fd and lock for reading.
+// Returns an error if the fd cannot be used.
+func (fd *netFD) readLock() error {
+ if !fd.fdmu.RWLock(true) {
+ return errClosing
+ }
+ return nil
+}
+
+// Unlock for reading and remove a reference to this FD.
+func (fd *netFD) readUnlock() {
+ if fd.fdmu.RWUnlock(true) {
+ fd.destroy()
+ }
+}
+
+// Add a reference to this fd and lock for writing.
+// Returns an error if the fd cannot be used.
+func (fd *netFD) writeLock() error {
+ if !fd.fdmu.RWLock(false) {
+ return errClosing
+ }
+ return nil
+}
+
+// Unlock for writing and remove a reference to this FD.
+func (fd *netFD) writeUnlock() {
+ if fd.fdmu.RWUnlock(false) {
+ fd.destroy()
}
- fd.sysmu.Unlock()
}
func (fd *netFD) Close() error {
fd.pd.Lock() // needed for both fd.incref(true) and pollDesc.Evict
- if err := fd.incref(true); err != nil {
+ if !fd.fdmu.IncrefAndClose() {
fd.pd.Unlock()
- return err
+ return errClosing
}
// Unblock any I/O. Once it all unblocks and returns,
// so that it cannot be referring to fd.sysfd anymore,
@@ -158,7 +169,7 @@ func (fd *netFD) Close() error {
}
func (fd *netFD) shutdown(how int) error {
- if err := fd.incref(false); err != nil {
+ if err := fd.incref(); err != nil {
return err
}
defer fd.decref()
@@ -178,12 +189,10 @@ func (fd *netFD) CloseWrite() error {
}
func (fd *netFD) Read(p []byte) (n int, err error) {
- fd.rio.Lock()
- defer fd.rio.Unlock()
- if err := fd.incref(false); err != nil {
+ if err := fd.readLock(); err != nil {
return 0, err
}
- defer fd.decref()
+ defer fd.readUnlock()
if err := fd.pd.PrepareRead(); err != nil {
return 0, &OpError{"read", fd.net, fd.raddr, err}
}
@@ -207,12 +216,10 @@ func (fd *netFD) Read(p []byte) (n int, err error) {
}
func (fd *netFD) ReadFrom(p []byte) (n int, sa syscall.Sockaddr, err error) {
- fd.rio.Lock()
- defer fd.rio.Unlock()
- if err := fd.incref(false); err != nil {
+ if err := fd.readLock(); err != nil {
return 0, nil, err
}
- defer fd.decref()
+ defer fd.readUnlock()
if err := fd.pd.PrepareRead(); err != nil {
return 0, nil, &OpError{"read", fd.net, fd.laddr, err}
}
@@ -236,12 +243,10 @@ func (fd *netFD) ReadFrom(p []byte) (n int, sa syscall.Sockaddr, err error) {
}
func (fd *netFD) ReadMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err error) {
- fd.rio.Lock()
- defer fd.rio.Unlock()
- if err := fd.incref(false); err != nil {
+ if err := fd.readLock(); err != nil {
return 0, 0, 0, nil, err
}
- defer fd.decref()
+ defer fd.readUnlock()
if err := fd.pd.PrepareRead(); err != nil {
return 0, 0, 0, nil, &OpError{"read", fd.net, fd.laddr, err}
}
@@ -272,12 +277,10 @@ func chkReadErr(n int, err error, fd *netFD) error {
}
func (fd *netFD) Write(p []byte) (nn int, err error) {
- fd.wio.Lock()
- defer fd.wio.Unlock()
- if err := fd.incref(false); err != nil {
+ if err := fd.writeLock(); err != nil {
return 0, err
}
- defer fd.decref()
+ defer fd.writeUnlock()
if err := fd.pd.PrepareWrite(); err != nil {
return 0, &OpError{"write", fd.net, fd.raddr, err}
}
@@ -311,12 +314,10 @@ func (fd *netFD) Write(p []byte) (nn int, err error) {
}
func (fd *netFD) WriteTo(p []byte, sa syscall.Sockaddr) (n int, err error) {
- fd.wio.Lock()
- defer fd.wio.Unlock()
- if err := fd.incref(false); err != nil {
+ if err := fd.writeLock(); err != nil {
return 0, err
}
- defer fd.decref()
+ defer fd.writeUnlock()
if err := fd.pd.PrepareWrite(); err != nil {
return 0, &OpError{"write", fd.net, fd.raddr, err}
}
@@ -338,12 +339,10 @@ func (fd *netFD) WriteTo(p []byte, sa syscall.Sockaddr) (n int, err error) {
}
func (fd *netFD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oobn int, err error) {
- fd.wio.Lock()
- defer fd.wio.Unlock()
- if err := fd.incref(false); err != nil {
+ if err := fd.writeLock(); err != nil {
return 0, 0, err
}
- defer fd.decref()
+ defer fd.writeUnlock()
if err := fd.pd.PrepareWrite(); err != nil {
return 0, 0, &OpError{"write", fd.net, fd.raddr, err}
}
@@ -366,12 +365,10 @@ func (fd *netFD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oob
}
func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (netfd *netFD, err error) {
- fd.rio.Lock()
- defer fd.rio.Unlock()
- if err := fd.incref(false); err != nil {
+ if err := fd.readLock(); err != nil {
return nil, err
}
- defer fd.decref()
+ defer fd.readUnlock()
var s int
var rsa syscall.Sockaddr
@@ -399,20 +396,68 @@ func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (netfd *netFD, err e
closesocket(s)
return nil, err
}
+ if err = netfd.init(); err != nil {
+ fd.Close()
+ return nil, err
+ }
lsa, _ := syscall.Getsockname(netfd.sysfd)
netfd.setAddr(toAddr(lsa), toAddr(rsa))
return netfd, nil
}
-func (fd *netFD) dup() (f *os.File, err error) {
+// tryDupCloexec indicates whether F_DUPFD_CLOEXEC should be used.
+// If the kernel doesn't support it, this is set to 0.
+var tryDupCloexec = int32(1)
+
+func dupCloseOnExec(fd int) (newfd int, err error) {
+ if atomic.LoadInt32(&tryDupCloexec) == 1 && syscall.F_DUPFD_CLOEXEC != 0 {
+ r0, _, e1 := syscall.Syscall(syscall.SYS_FCNTL, uintptr(fd), syscall.F_DUPFD_CLOEXEC, 0)
+ if runtime.GOOS == "darwin" && e1 == syscall.EBADF {
+ // On OS X 10.6 and below (but we only support
+ // >= 10.6), F_DUPFD_CLOEXEC is unsupported
+ // and fcntl there falls back (undocumented)
+ // to doing an ioctl instead, returning EBADF
+ // in this case because fd is not of the
+ // expected device fd type. Treat it as
+ // EINVAL instead, so we fall back to the
+ // normal dup path.
+ // TODO: only do this on 10.6 if we can detect 10.6
+ // cheaply.
+ e1 = syscall.EINVAL
+ }
+ switch e1 {
+ case 0:
+ return int(r0), nil
+ case syscall.EINVAL:
+ // Old kernel. Fall back to the portable way
+ // from now on.
+ atomic.StoreInt32(&tryDupCloexec, 0)
+ default:
+ return -1, e1
+ }
+ }
+ return dupCloseOnExecOld(fd)
+}
+
+// dupCloseOnExecUnixOld is the traditional way to dup an fd and
+// set its O_CLOEXEC bit, using two system calls.
+func dupCloseOnExecOld(fd int) (newfd int, err error) {
syscall.ForkLock.RLock()
- ns, err := syscall.Dup(fd.sysfd)
+ defer syscall.ForkLock.RUnlock()
+ newfd, err = syscall.Dup(fd)
+ if err != nil {
+ return -1, err
+ }
+ syscall.CloseOnExec(newfd)
+ return
+}
+
+func (fd *netFD) dup() (f *os.File, err error) {
+ ns, err := dupCloseOnExec(fd.sysfd)
if err != nil {
syscall.ForkLock.RUnlock()
return nil, &OpError{"dup", fd.net, fd.laddr, err}
}
- syscall.CloseOnExec(ns)
- syscall.ForkLock.RUnlock()
// We want blocking mode for the new fd, hence the double negative.
// This also puts the old fd into blocking mode, meaning that
@@ -428,3 +473,10 @@ func (fd *netFD) dup() (f *os.File, err error) {
func closesocket(s int) error {
return syscall.Close(s)
}
+
+func skipRawSocketTests() (skip bool, skipmsg string, err error) {
+ if os.Getuid() != 0 {
+ return true, "skipping test; must be root", nil
+ }
+ return false, "", nil
+}
diff --git a/libgo/go/net/fd_unix_test.go b/libgo/go/net/fd_unix_test.go
index 664ef1bf19d..65d3e69a764 100644
--- a/libgo/go/net/fd_unix_test.go
+++ b/libgo/go/net/fd_unix_test.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd linux netbsd openbsd
+// +build darwin dragonfly freebsd linux netbsd openbsd
package net
diff --git a/libgo/go/net/fd_windows.go b/libgo/go/net/fd_windows.go
index fefd174bafa..64d56c73e06 100644
--- a/libgo/go/net/fd_windows.go
+++ b/libgo/go/net/fd_windows.go
@@ -15,7 +15,10 @@ import (
"unsafe"
)
-var initErr error
+var (
+ initErr error
+ ioSync uint64
+)
// CancelIo Windows API cancels all outstanding IO for a particular
// socket on current thread. To overcome that limitation, we run
@@ -27,7 +30,11 @@ var initErr error
// package uses CancelIoEx API, if present, otherwise it fallback
// to CancelIo.
-var canCancelIO bool // determines if CancelIoEx API is present
+var (
+ canCancelIO bool // determines if CancelIoEx API is present
+ skipSyncNotif bool
+ hasLoadSetFileCompletionNotificationModes bool
+)
func sysInit() {
var d syscall.WSAData
@@ -40,6 +47,27 @@ func sysInit() {
lookupPort = newLookupPort
lookupIP = newLookupIP
}
+
+ hasLoadSetFileCompletionNotificationModes = syscall.LoadSetFileCompletionNotificationModes() == nil
+ if hasLoadSetFileCompletionNotificationModes {
+ // It's not safe to use FILE_SKIP_COMPLETION_PORT_ON_SUCCESS if non IFS providers are installed:
+ // http://support.microsoft.com/kb/2568167
+ skipSyncNotif = true
+ protos := [2]int32{syscall.IPPROTO_TCP, 0}
+ var buf [32]syscall.WSAProtocolInfo
+ len := uint32(unsafe.Sizeof(buf))
+ n, err := syscall.WSAEnumProtocols(&protos[0], &buf[0], &len)
+ if err != nil {
+ skipSyncNotif = false
+ } else {
+ for i := int32(0); i < n; i++ {
+ if buf[i].ServiceFlags1&syscall.XP1_IFS_HANDLES == 0 {
+ skipSyncNotif = false
+ break
+ }
+ }
+ }
+ }
}
func closesocket(s syscall.Handle) error {
@@ -47,128 +75,62 @@ func closesocket(s syscall.Handle) error {
}
func canUseConnectEx(net string) bool {
- if net == "udp" || net == "udp4" || net == "udp6" {
+ switch net {
+ case "udp", "udp4", "udp6", "ip", "ip4", "ip6":
// ConnectEx windows API does not support connectionless sockets.
return false
}
return syscall.LoadConnectEx() == nil
}
-func resolveAndDial(net, addr string, localAddr Addr, deadline time.Time) (Conn, error) {
+func dial(net string, ra Addr, dialer func(time.Time) (Conn, error), deadline time.Time) (Conn, error) {
if !canUseConnectEx(net) {
// Use the relatively inefficient goroutine-racing
// implementation of DialTimeout.
- return resolveAndDialChannel(net, addr, localAddr, deadline)
- }
- ra, err := resolveAddr("dial", net, addr, deadline)
- if err != nil {
- return nil, err
+ return dialChannel(net, ra, dialer, deadline)
}
- return dial(net, addr, localAddr, ra, deadline)
+ return dialer(deadline)
}
-// Interface for all IO operations.
-type anOpIface interface {
- Op() *anOp
- Name() string
- Submit() error
-}
-
-// IO completion result parameters.
-type ioResult struct {
- qty uint32
- err error
-}
-
-// anOp implements functionality common to all IO operations.
-type anOp struct {
+// operation contains superset of data necessary to perform all async IO.
+type operation struct {
// Used by IOCP interface, it must be first field
// of the struct, as our code rely on it.
o syscall.Overlapped
- resultc chan ioResult
- errnoc chan error
- fd *netFD
-}
+ // fields used by runtime.netpoll
+ runtimeCtx uintptr
+ mode int32
+ errno int32
+ qty uint32
-func (o *anOp) Init(fd *netFD, mode int) {
- o.fd = fd
- var i int
- if mode == 'r' {
- i = 0
- } else {
- i = 1
- }
- if fd.resultc[i] == nil {
- fd.resultc[i] = make(chan ioResult, 1)
- }
- o.resultc = fd.resultc[i]
- if fd.errnoc[i] == nil {
- fd.errnoc[i] = make(chan error)
- }
- o.errnoc = fd.errnoc[i]
+ // fields used only by net package
+ fd *netFD
+ errc chan error
+ buf syscall.WSABuf
+ sa syscall.Sockaddr
+ rsa *syscall.RawSockaddrAny
+ rsan int32
+ handle syscall.Handle
+ flags uint32
}
-func (o *anOp) Op() *anOp {
- return o
-}
-
-// bufOp is used by IO operations that read / write
-// data from / to client buffer.
-type bufOp struct {
- anOp
- buf syscall.WSABuf
-}
-
-func (o *bufOp) Init(fd *netFD, buf []byte, mode int) {
- o.anOp.Init(fd, mode)
+func (o *operation) InitBuf(buf []byte) {
o.buf.Len = uint32(len(buf))
- if len(buf) == 0 {
- o.buf.Buf = nil
- } else {
+ o.buf.Buf = nil
+ if len(buf) != 0 {
o.buf.Buf = (*byte)(unsafe.Pointer(&buf[0]))
}
}
-// resultSrv will retrieve all IO completion results from
-// iocp and send them to the correspondent waiting client
-// goroutine via channel supplied in the request.
-type resultSrv struct {
- iocp syscall.Handle
-}
-
-func runtime_blockingSyscallHint()
-
-func (s *resultSrv) Run() {
- var o *syscall.Overlapped
- var key uint32
- var r ioResult
- for {
- r.err = syscall.GetQueuedCompletionStatus(s.iocp, &(r.qty), &key, &o, 0)
- if r.err == syscall.Errno(syscall.WAIT_TIMEOUT) && o == nil {
- runtime_blockingSyscallHint()
- r.err = syscall.GetQueuedCompletionStatus(s.iocp, &(r.qty), &key, &o, syscall.INFINITE)
- }
- switch {
- case r.err == nil:
- // Dequeued successfully completed IO packet.
- case r.err == syscall.Errno(syscall.WAIT_TIMEOUT) && o == nil:
- // Wait has timed out (should not happen now, but might be used in the future).
- panic("GetQueuedCompletionStatus timed out")
- case o == nil:
- // Failed to dequeue anything -> report the error.
- panic("GetQueuedCompletionStatus failed " + r.err.Error())
- default:
- // Dequeued failed IO packet.
- }
- (*anOp)(unsafe.Pointer(o)).resultc <- r
- }
-}
-
// ioSrv executes net IO requests.
type ioSrv struct {
- submchan chan anOpIface // submit IO requests
- canchan chan anOpIface // cancel IO requests
+ req chan ioSrvReq
+}
+
+type ioSrvReq struct {
+ o *operation
+ submit func(o *operation) error // if nil, cancel the operation
}
// ProcessRemoteIO will execute submit IO requests on behalf
@@ -179,192 +141,182 @@ type ioSrv struct {
func (s *ioSrv) ProcessRemoteIO() {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
- for {
- select {
- case o := <-s.submchan:
- o.Op().errnoc <- o.Submit()
- case o := <-s.canchan:
- o.Op().errnoc <- syscall.CancelIo(syscall.Handle(o.Op().fd.sysfd))
+ for r := range s.req {
+ if r.submit != nil {
+ r.o.errc <- r.submit(r.o)
+ } else {
+ r.o.errc <- syscall.CancelIo(r.o.fd.sysfd)
}
}
}
-// ExecIO executes a single IO operation oi. It submits and cancels
+// ExecIO executes a single IO operation o. It submits and cancels
// IO in the current thread for systems where Windows CancelIoEx API
// is available. Alternatively, it passes the request onto
-// a special goroutine and waits for completion or cancels request.
-// deadline is unix nanos.
-func (s *ioSrv) ExecIO(oi anOpIface, deadline int64) (int, error) {
- var err error
- o := oi.Op()
- // Calculate timeout delta.
- var delta int64
- if deadline != 0 {
- delta = deadline - time.Now().UnixNano()
- if delta <= 0 {
- return 0, &OpError{oi.Name(), o.fd.net, o.fd.laddr, errTimeout}
- }
+// runtime netpoll and waits for completion or cancels request.
+func (s *ioSrv) ExecIO(o *operation, name string, submit func(o *operation) error) (int, error) {
+ fd := o.fd
+ // Notify runtime netpoll about starting IO.
+ err := fd.pd.Prepare(int(o.mode))
+ if err != nil {
+ return 0, &OpError{name, fd.net, fd.laddr, err}
}
// Start IO.
if canCancelIO {
- err = oi.Submit()
+ err = submit(o)
} else {
// Send request to a special dedicated thread,
// so it can stop the IO with CancelIO later.
- s.submchan <- oi
- err = <-o.errnoc
+ s.req <- ioSrvReq{o, submit}
+ err = <-o.errc
}
switch err {
case nil:
- // IO completed immediately, but we need to get our completion message anyway.
+ // IO completed immediately
+ if o.fd.skipSyncNotif {
+ // No completion message will follow, so return immediately.
+ return int(o.qty), nil
+ }
+ // Need to get our completion message anyway.
case syscall.ERROR_IO_PENDING:
// IO started, and we have to wait for its completion.
err = nil
default:
- return 0, &OpError{oi.Name(), o.fd.net, o.fd.laddr, err}
- }
- // Setup timer, if deadline is given.
- var timer <-chan time.Time
- if delta > 0 {
- t := time.NewTimer(time.Duration(delta) * time.Nanosecond)
- defer t.Stop()
- timer = t.C
+ return 0, &OpError{name, fd.net, fd.laddr, err}
}
// Wait for our request to complete.
- var r ioResult
- var cancelled, timeout bool
- select {
- case r = <-o.resultc:
- case <-timer:
- cancelled = true
- timeout = true
- case <-o.fd.closec:
- cancelled = true
- }
- if cancelled {
- // Cancel it.
- if canCancelIO {
- err := syscall.CancelIoEx(syscall.Handle(o.Op().fd.sysfd), &o.o)
- // Assuming ERROR_NOT_FOUND is returned, if IO is completed.
- if err != nil && err != syscall.ERROR_NOT_FOUND {
- // TODO(brainman): maybe do something else, but panic.
- panic(err)
- }
- } else {
- s.canchan <- oi
- <-o.errnoc
- }
- // Wait for IO to be canceled or complete successfully.
- r = <-o.resultc
- if r.err == syscall.ERROR_OPERATION_ABORTED { // IO Canceled
- if timeout {
- r.err = errTimeout
- } else {
- r.err = errClosing
- }
+ err = fd.pd.Wait(int(o.mode))
+ if err == nil {
+ // All is good. Extract our IO results and return.
+ if o.errno != 0 {
+ err = syscall.Errno(o.errno)
+ return 0, &OpError{name, fd.net, fd.laddr, err}
}
+ return int(o.qty), nil
+ }
+ // IO is interrupted by "close" or "timeout"
+ netpollErr := err
+ switch netpollErr {
+ case errClosing, errTimeout:
+ // will deal with those.
+ default:
+ panic("net: unexpected runtime.netpoll error: " + netpollErr.Error())
}
- if r.err != nil {
- err = &OpError{oi.Name(), o.fd.net, o.fd.laddr, r.err}
+ // Cancel our request.
+ if canCancelIO {
+ err := syscall.CancelIoEx(fd.sysfd, &o.o)
+ // Assuming ERROR_NOT_FOUND is returned, if IO is completed.
+ if err != nil && err != syscall.ERROR_NOT_FOUND {
+ // TODO(brainman): maybe do something else, but panic.
+ panic(err)
+ }
+ } else {
+ s.req <- ioSrvReq{o, nil}
+ <-o.errc
+ }
+ // Wait for cancellation to complete.
+ fd.pd.WaitCanceled(int(o.mode))
+ if o.errno != 0 {
+ err = syscall.Errno(o.errno)
+ if err == syscall.ERROR_OPERATION_ABORTED { // IO Canceled
+ err = netpollErr
+ }
+ return 0, &OpError{name, fd.net, fd.laddr, err}
}
- return int(r.qty), err
+ // We issued cancellation request. But, it seems, IO operation succeeded
+ // before cancellation request run. We need to treat IO operation as
+ // succeeded (the bytes are actually sent/recv from network).
+ return int(o.qty), nil
}
// Start helper goroutines.
-var resultsrv *resultSrv
-var iosrv *ioSrv
+var rsrv, wsrv *ioSrv
var onceStartServer sync.Once
func startServer() {
- resultsrv = new(resultSrv)
- var err error
- resultsrv.iocp, err = syscall.CreateIoCompletionPort(syscall.InvalidHandle, 0, 0, 1)
- if err != nil {
- panic("CreateIoCompletionPort: " + err.Error())
- }
- go resultsrv.Run()
-
- iosrv = new(ioSrv)
+ rsrv = new(ioSrv)
+ wsrv = new(ioSrv)
if !canCancelIO {
- // Only CancelIo API is available. Lets start special goroutine
- // locked to an OS thread, that both starts and cancels IO.
- iosrv.submchan = make(chan anOpIface)
- iosrv.canchan = make(chan anOpIface)
- go iosrv.ProcessRemoteIO()
+ // Only CancelIo API is available. Lets start two special goroutines
+ // locked to an OS thread, that both starts and cancels IO. One will
+ // process read requests, while other will do writes.
+ rsrv.req = make(chan ioSrvReq)
+ go rsrv.ProcessRemoteIO()
+ wsrv.req = make(chan ioSrvReq)
+ go wsrv.ProcessRemoteIO()
}
}
// Network file descriptor.
type netFD struct {
- // locking/lifetime of sysfd
- sysmu sync.Mutex
- sysref int
- closing bool
+ // locking/lifetime of sysfd + serialize access to Read and Write methods
+ fdmu fdMutex
// immutable until Close
- sysfd syscall.Handle
- family int
- sotype int
- isConnected bool
- net string
- laddr Addr
- raddr Addr
- resultc [2]chan ioResult // read/write completion results
- errnoc [2]chan error // read/write submit or cancel operation errors
- closec chan bool // used by Close to cancel pending IO
+ sysfd syscall.Handle
+ family int
+ sotype int
+ isConnected bool
+ skipSyncNotif bool
+ net string
+ laddr Addr
+ raddr Addr
- // serialize access to Read and Write methods
- rio, wio sync.Mutex
+ rop operation // read operation
+ wop operation // write operation
- // read and write deadlines
- rdeadline, wdeadline deadline
+ // wait server
+ pd pollDesc
}
-func allocFD(fd syscall.Handle, family, sotype int, net string) *netFD {
- netfd := &netFD{
- sysfd: fd,
- family: family,
- sotype: sotype,
- net: net,
- closec: make(chan bool),
- }
- return netfd
-}
-
-func newFD(fd syscall.Handle, family, proto int, net string) (*netFD, error) {
+func newFD(sysfd syscall.Handle, family, sotype int, net string) (*netFD, error) {
if initErr != nil {
return nil, initErr
}
onceStartServer.Do(startServer)
- // Associate our socket with resultsrv.iocp.
- if _, err := syscall.CreateIoCompletionPort(syscall.Handle(fd), resultsrv.iocp, 0, 0); err != nil {
- return nil, err
+ return &netFD{sysfd: sysfd, family: family, sotype: sotype, net: net}, nil
+}
+
+func (fd *netFD) init() error {
+ if err := fd.pd.Init(fd); err != nil {
+ return err
+ }
+ if hasLoadSetFileCompletionNotificationModes {
+ // We do not use events, so we can skip them always.
+ flags := uint8(syscall.FILE_SKIP_SET_EVENT_ON_HANDLE)
+ // It's not safe to skip completion notifications for UDP:
+ // http://blogs.technet.com/b/winserverperformance/archive/2008/06/26/designing-applications-for-high-performance-part-iii.aspx
+ if skipSyncNotif && fd.net == "tcp" {
+ flags |= syscall.FILE_SKIP_COMPLETION_PORT_ON_SUCCESS
+ }
+ err := syscall.SetFileCompletionNotificationModes(fd.sysfd, flags)
+ if err == nil && flags&syscall.FILE_SKIP_COMPLETION_PORT_ON_SUCCESS != 0 {
+ fd.skipSyncNotif = true
+ }
}
- return allocFD(fd, family, proto, net), nil
+ fd.rop.mode = 'r'
+ fd.wop.mode = 'w'
+ fd.rop.fd = fd
+ fd.wop.fd = fd
+ fd.rop.runtimeCtx = fd.pd.runtimeCtx
+ fd.wop.runtimeCtx = fd.pd.runtimeCtx
+ if !canCancelIO {
+ fd.rop.errc = make(chan error)
+ fd.wop.errc = make(chan error)
+ }
+ return nil
}
func (fd *netFD) setAddr(laddr, raddr Addr) {
fd.laddr = laddr
fd.raddr = raddr
- runtime.SetFinalizer(fd, (*netFD).closesocket)
-}
-
-// Make new connection.
-
-type connectOp struct {
- anOp
- ra syscall.Sockaddr
-}
-
-func (o *connectOp) Submit() error {
- return syscall.ConnectEx(o.fd.sysfd, o.ra, nil, 0, nil, &o.o)
-}
-
-func (o *connectOp) Name() string {
- return "ConnectEx"
+ runtime.SetFinalizer(fd, (*netFD).Close)
}
func (fd *netFD) connect(la, ra syscall.Sockaddr) error {
+ // Do not need to call fd.writeLock here,
+ // because fd is not yet accessible to user,
+ // so no concurrent operations are possible.
if !canUseConnectEx(fd.net) {
return syscall.Connect(fd.sysfd, ra)
}
@@ -383,10 +335,11 @@ func (fd *netFD) connect(la, ra syscall.Sockaddr) error {
}
}
// Call ConnectEx API.
- var o connectOp
- o.Init(fd, 'w')
- o.ra = ra
- _, err := iosrv.ExecIO(&o, fd.wdeadline.value())
+ o := &fd.wop
+ o.sa = ra
+ _, err := wsrv.ExecIO(o, "ConnectEx", func(o *operation) error {
+ return syscall.ConnectEx(o.fd.sysfd, o.sa, nil, 0, nil, &o.o)
+ })
if err != nil {
return err
}
@@ -394,61 +347,80 @@ func (fd *netFD) connect(la, ra syscall.Sockaddr) error {
return syscall.Setsockopt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_UPDATE_CONNECT_CONTEXT, (*byte)(unsafe.Pointer(&fd.sysfd)), int32(unsafe.Sizeof(fd.sysfd)))
}
+func (fd *netFD) destroy() {
+ if fd.sysfd == syscall.InvalidHandle {
+ return
+ }
+ // Poller may want to unregister fd in readiness notification mechanism,
+ // so this must be executed before closesocket.
+ fd.pd.Close()
+ closesocket(fd.sysfd)
+ fd.sysfd = syscall.InvalidHandle
+ // no need for a finalizer anymore
+ runtime.SetFinalizer(fd, nil)
+}
+
// Add a reference to this fd.
-// If closing==true, mark the fd as closing.
// Returns an error if the fd cannot be used.
-func (fd *netFD) incref(closing bool) error {
- if fd == nil {
+func (fd *netFD) incref() error {
+ if !fd.fdmu.Incref() {
return errClosing
}
- fd.sysmu.Lock()
- if fd.closing {
- fd.sysmu.Unlock()
- return errClosing
+ return nil
+}
+
+// Remove a reference to this FD and close if we've been asked to do so
+// (and there are no references left).
+func (fd *netFD) decref() {
+ if fd.fdmu.Decref() {
+ fd.destroy()
}
- fd.sysref++
- if closing {
- fd.closing = true
+}
+
+// Add a reference to this fd and lock for reading.
+// Returns an error if the fd cannot be used.
+func (fd *netFD) readLock() error {
+ if !fd.fdmu.RWLock(true) {
+ return errClosing
}
- closing = fd.closing
- fd.sysmu.Unlock()
return nil
}
-// Remove a reference to this FD and close if we've been asked to do so (and
-// there are no references left.
-func (fd *netFD) decref() {
- if fd == nil {
- return
+// Unlock for reading and remove a reference to this FD.
+func (fd *netFD) readUnlock() {
+ if fd.fdmu.RWUnlock(true) {
+ fd.destroy()
+ }
+}
+
+// Add a reference to this fd and lock for writing.
+// Returns an error if the fd cannot be used.
+func (fd *netFD) writeLock() error {
+ if !fd.fdmu.RWLock(false) {
+ return errClosing
}
- fd.sysmu.Lock()
- fd.sysref--
- if fd.closing && fd.sysref == 0 && fd.sysfd != syscall.InvalidHandle {
- closesocket(fd.sysfd)
- fd.sysfd = syscall.InvalidHandle
- // no need for a finalizer anymore
- runtime.SetFinalizer(fd, nil)
+ return nil
+}
+
+// Unlock for writing and remove a reference to this FD.
+func (fd *netFD) writeUnlock() {
+ if fd.fdmu.RWUnlock(false) {
+ fd.destroy()
}
- fd.sysmu.Unlock()
}
func (fd *netFD) Close() error {
- if err := fd.incref(true); err != nil {
- return err
+ if !fd.fdmu.IncrefAndClose() {
+ return errClosing
}
- defer fd.decref()
// unblock pending reader and writer
- close(fd.closec)
- // wait for both reader and writer to exit
- fd.rio.Lock()
- defer fd.rio.Unlock()
- fd.wio.Lock()
- defer fd.wio.Unlock()
+ fd.pd.Evict()
+ fd.decref()
return nil
}
func (fd *netFD) shutdown(how int) error {
- if err := fd.incref(false); err != nil {
+ if err := fd.incref(); err != nil {
return err
}
defer fd.decref()
@@ -467,72 +439,42 @@ func (fd *netFD) CloseWrite() error {
return fd.shutdown(syscall.SHUT_WR)
}
-func (fd *netFD) closesocket() error {
- return closesocket(fd.sysfd)
-}
-
-// Read from network.
-
-type readOp struct {
- bufOp
-}
-
-func (o *readOp) Submit() error {
- var d, f uint32
- return syscall.WSARecv(syscall.Handle(o.fd.sysfd), &o.buf, 1, &d, &f, &o.o, nil)
-}
-
-func (o *readOp) Name() string {
- return "WSARecv"
-}
-
func (fd *netFD) Read(buf []byte) (int, error) {
- if err := fd.incref(false); err != nil {
+ if err := fd.readLock(); err != nil {
return 0, err
}
- defer fd.decref()
- fd.rio.Lock()
- defer fd.rio.Unlock()
- var o readOp
- o.Init(fd, buf, 'r')
- n, err := iosrv.ExecIO(&o, fd.rdeadline.value())
+ defer fd.readUnlock()
+ o := &fd.rop
+ o.InitBuf(buf)
+ n, err := rsrv.ExecIO(o, "WSARecv", func(o *operation) error {
+ return syscall.WSARecv(o.fd.sysfd, &o.buf, 1, &o.qty, &o.flags, &o.o, nil)
+ })
if err == nil && n == 0 {
err = io.EOF
}
+ if raceenabled {
+ raceAcquire(unsafe.Pointer(&ioSync))
+ }
return n, err
}
-// ReadFrom from network.
-
-type readFromOp struct {
- bufOp
- rsa syscall.RawSockaddrAny
- rsan int32
-}
-
-func (o *readFromOp) Submit() error {
- var d, f uint32
- return syscall.WSARecvFrom(o.fd.sysfd, &o.buf, 1, &d, &f, &o.rsa, &o.rsan, &o.o, nil)
-}
-
-func (o *readFromOp) Name() string {
- return "WSARecvFrom"
-}
-
func (fd *netFD) ReadFrom(buf []byte) (n int, sa syscall.Sockaddr, err error) {
if len(buf) == 0 {
return 0, nil, nil
}
- if err := fd.incref(false); err != nil {
+ if err := fd.readLock(); err != nil {
return 0, nil, err
}
- defer fd.decref()
- fd.rio.Lock()
- defer fd.rio.Unlock()
- var o readFromOp
- o.Init(fd, buf, 'r')
- o.rsan = int32(unsafe.Sizeof(o.rsa))
- n, err = iosrv.ExecIO(&o, fd.rdeadline.value())
+ defer fd.readUnlock()
+ o := &fd.rop
+ o.InitBuf(buf)
+ n, err = rsrv.ExecIO(o, "WSARecvFrom", func(o *operation) error {
+ if o.rsa == nil {
+ o.rsa = new(syscall.RawSockaddrAny)
+ }
+ o.rsan = int32(unsafe.Sizeof(*o.rsa))
+ return syscall.WSARecvFrom(o.fd.sysfd, &o.buf, 1, &o.qty, &o.flags, o.rsa, &o.rsan, &o.o, nil)
+ })
if err != nil {
return 0, nil, err
}
@@ -540,89 +482,42 @@ func (fd *netFD) ReadFrom(buf []byte) (n int, sa syscall.Sockaddr, err error) {
return
}
-// Write to network.
-
-type writeOp struct {
- bufOp
-}
-
-func (o *writeOp) Submit() error {
- var d uint32
- return syscall.WSASend(o.fd.sysfd, &o.buf, 1, &d, 0, &o.o, nil)
-}
-
-func (o *writeOp) Name() string {
- return "WSASend"
-}
-
func (fd *netFD) Write(buf []byte) (int, error) {
- if err := fd.incref(false); err != nil {
+ if err := fd.writeLock(); err != nil {
return 0, err
}
- defer fd.decref()
- fd.wio.Lock()
- defer fd.wio.Unlock()
- var o writeOp
- o.Init(fd, buf, 'w')
- return iosrv.ExecIO(&o, fd.wdeadline.value())
-}
-
-// WriteTo to network.
-
-type writeToOp struct {
- bufOp
- sa syscall.Sockaddr
-}
-
-func (o *writeToOp) Submit() error {
- var d uint32
- return syscall.WSASendto(o.fd.sysfd, &o.buf, 1, &d, 0, o.sa, &o.o, nil)
-}
-
-func (o *writeToOp) Name() string {
- return "WSASendto"
+ defer fd.writeUnlock()
+ if raceenabled {
+ raceReleaseMerge(unsafe.Pointer(&ioSync))
+ }
+ o := &fd.wop
+ o.InitBuf(buf)
+ return wsrv.ExecIO(o, "WSASend", func(o *operation) error {
+ return syscall.WSASend(o.fd.sysfd, &o.buf, 1, &o.qty, 0, &o.o, nil)
+ })
}
func (fd *netFD) WriteTo(buf []byte, sa syscall.Sockaddr) (int, error) {
if len(buf) == 0 {
return 0, nil
}
- if err := fd.incref(false); err != nil {
+ if err := fd.writeLock(); err != nil {
return 0, err
}
- defer fd.decref()
- fd.wio.Lock()
- defer fd.wio.Unlock()
- var o writeToOp
- o.Init(fd, buf, 'w')
+ defer fd.writeUnlock()
+ o := &fd.wop
+ o.InitBuf(buf)
o.sa = sa
- return iosrv.ExecIO(&o, fd.wdeadline.value())
-}
-
-// Accept new network connections.
-
-type acceptOp struct {
- anOp
- newsock syscall.Handle
- attrs [2]syscall.RawSockaddrAny // space for local and remote address only
-}
-
-func (o *acceptOp) Submit() error {
- var d uint32
- l := uint32(unsafe.Sizeof(o.attrs[0]))
- return syscall.AcceptEx(o.fd.sysfd, o.newsock,
- (*byte)(unsafe.Pointer(&o.attrs[0])), 0, l, l, &d, &o.o)
-}
-
-func (o *acceptOp) Name() string {
- return "AcceptEx"
+ return wsrv.ExecIO(o, "WSASendto", func(o *operation) error {
+ return syscall.WSASendto(o.fd.sysfd, &o.buf, 1, &o.qty, 0, o.sa, &o.o, nil)
+ })
}
func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (*netFD, error) {
- if err := fd.incref(false); err != nil {
+ if err := fd.readLock(); err != nil {
return nil, err
}
- defer fd.decref()
+ defer fd.readUnlock()
// Get new socket.
s, err := sysSocket(fd.family, fd.sotype, 0)
@@ -631,43 +526,67 @@ func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (*netFD, error) {
}
// Associate our new socket with IOCP.
- onceStartServer.Do(startServer)
- if _, err := syscall.CreateIoCompletionPort(s, resultsrv.iocp, 0, 0); err != nil {
+ netfd, err := newFD(s, fd.family, fd.sotype, fd.net)
+ if err != nil {
closesocket(s)
- return nil, &OpError{"CreateIoCompletionPort", fd.net, fd.laddr, err}
+ return nil, &OpError{"accept", fd.net, fd.laddr, err}
+ }
+ if err := netfd.init(); err != nil {
+ fd.Close()
+ return nil, err
}
// Submit accept request.
- var o acceptOp
- o.Init(fd, 'r')
- o.newsock = s
- _, err = iosrv.ExecIO(&o, fd.rdeadline.value())
+ o := &fd.rop
+ o.handle = s
+ var rawsa [2]syscall.RawSockaddrAny
+ o.rsan = int32(unsafe.Sizeof(rawsa[0]))
+ _, err = rsrv.ExecIO(o, "AcceptEx", func(o *operation) error {
+ return syscall.AcceptEx(o.fd.sysfd, o.handle, (*byte)(unsafe.Pointer(&rawsa[0])), 0, uint32(o.rsan), uint32(o.rsan), &o.qty, &o.o)
+ })
if err != nil {
- closesocket(s)
+ netfd.Close()
return nil, err
}
// Inherit properties of the listening socket.
err = syscall.Setsockopt(s, syscall.SOL_SOCKET, syscall.SO_UPDATE_ACCEPT_CONTEXT, (*byte)(unsafe.Pointer(&fd.sysfd)), int32(unsafe.Sizeof(fd.sysfd)))
if err != nil {
- closesocket(s)
+ netfd.Close()
return nil, &OpError{"Setsockopt", fd.net, fd.laddr, err}
}
// Get local and peer addr out of AcceptEx buffer.
var lrsa, rrsa *syscall.RawSockaddrAny
var llen, rlen int32
- l := uint32(unsafe.Sizeof(*lrsa))
- syscall.GetAcceptExSockaddrs((*byte)(unsafe.Pointer(&o.attrs[0])),
- 0, l, l, &lrsa, &llen, &rrsa, &rlen)
+ syscall.GetAcceptExSockaddrs((*byte)(unsafe.Pointer(&rawsa[0])),
+ 0, uint32(o.rsan), uint32(o.rsan), &lrsa, &llen, &rrsa, &rlen)
lsa, _ := lrsa.Sockaddr()
rsa, _ := rrsa.Sockaddr()
- netfd := allocFD(s, fd.family, fd.sotype, fd.net)
netfd.setAddr(toAddr(lsa), toAddr(rsa))
return netfd, nil
}
+func skipRawSocketTests() (skip bool, skipmsg string, err error) {
+ // From http://msdn.microsoft.com/en-us/library/windows/desktop/ms740548.aspx:
+ // Note: To use a socket of type SOCK_RAW requires administrative privileges.
+ // Users running Winsock applications that use raw sockets must be a member of
+ // the Administrators group on the local computer, otherwise raw socket calls
+ // will fail with an error code of WSAEACCES. On Windows Vista and later, access
+ // for raw sockets is enforced at socket creation. In earlier versions of Windows,
+ // access for raw sockets is enforced during other socket operations.
+ s, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_RAW, 0)
+ if err == syscall.WSAEACCES {
+ return true, "skipping test; no access to raw socket allowed", nil
+ }
+ if err != nil {
+ return true, "", err
+ }
+ defer syscall.Closesocket(s)
+ return false, "", nil
+}
+
// Unimplemented functions.
func (fd *netFD) dup() (*os.File, error) {
diff --git a/libgo/go/net/file_unix.go b/libgo/go/net/file_unix.go
index 4c8403e4063..8fe1b0eb035 100644
--- a/libgo/go/net/file_unix.go
+++ b/libgo/go/net/file_unix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd linux netbsd openbsd
+// +build darwin dragonfly freebsd linux netbsd openbsd
package net
@@ -12,14 +12,11 @@ import (
)
func newFileFD(f *os.File) (*netFD, error) {
- syscall.ForkLock.RLock()
- fd, err := syscall.Dup(int(f.Fd()))
+ fd, err := dupCloseOnExec(int(f.Fd()))
if err != nil {
- syscall.ForkLock.RUnlock()
return nil, os.NewSyscallError("dup", err)
}
- syscall.CloseOnExec(fd)
- syscall.ForkLock.RUnlock()
+
if err = syscall.SetNonblock(fd, true); err != nil {
closesocket(fd)
return nil, err
@@ -70,6 +67,10 @@ func newFileFD(f *os.File) (*netFD, error) {
closesocket(fd)
return nil, err
}
+ if err := netfd.init(); err != nil {
+ netfd.Close()
+ return nil, err
+ }
netfd.setAddr(laddr, raddr)
return netfd, nil
}
diff --git a/libgo/go/net/http/cgi/child.go b/libgo/go/net/http/cgi/child.go
index 100b8b77760..45fc2e57cd7 100644
--- a/libgo/go/net/http/cgi/child.go
+++ b/libgo/go/net/http/cgi/child.go
@@ -100,10 +100,21 @@ func RequestFromMap(params map[string]string) (*http.Request, error) {
uriStr += "?" + s
}
}
+
+ // There's apparently a de-facto standard for this.
+ // http://docstore.mik.ua/orelly/linux/cgi/ch03_02.htm#ch03-35636
+ if s := params["HTTPS"]; s == "on" || s == "ON" || s == "1" {
+ r.TLS = &tls.ConnectionState{HandshakeComplete: true}
+ }
+
if r.Host != "" {
- // Hostname is provided, so we can reasonably construct a URL,
- // even if we have to assume 'http' for the scheme.
- rawurl := "http://" + r.Host + uriStr
+ // Hostname is provided, so we can reasonably construct a URL.
+ rawurl := r.Host + uriStr
+ if r.TLS == nil {
+ rawurl = "http://" + rawurl
+ } else {
+ rawurl = "https://" + rawurl
+ }
url, err := url.Parse(rawurl)
if err != nil {
return nil, errors.New("cgi: failed to parse host and REQUEST_URI into a URL: " + rawurl)
@@ -120,12 +131,6 @@ func RequestFromMap(params map[string]string) (*http.Request, error) {
r.URL = url
}
- // There's apparently a de-facto standard for this.
- // http://docstore.mik.ua/orelly/linux/cgi/ch03_02.htm#ch03-35636
- if s := params["HTTPS"]; s == "on" || s == "ON" || s == "1" {
- r.TLS = &tls.ConnectionState{HandshakeComplete: true}
- }
-
// Request.RemoteAddr has its port set by Go's standard http
// server, so we do here too. We don't have one, though, so we
// use a dummy one.
diff --git a/libgo/go/net/http/cgi/child_test.go b/libgo/go/net/http/cgi/child_test.go
index 74e068014bb..075d8411bcf 100644
--- a/libgo/go/net/http/cgi/child_test.go
+++ b/libgo/go/net/http/cgi/child_test.go
@@ -21,7 +21,6 @@ func TestRequest(t *testing.T) {
"REQUEST_URI": "/path?a=b",
"CONTENT_LENGTH": "123",
"CONTENT_TYPE": "text/xml",
- "HTTPS": "1",
"REMOTE_ADDR": "5.6.7.8",
}
req, err := RequestFromMap(env)
@@ -58,14 +57,37 @@ func TestRequest(t *testing.T) {
if req.Trailer == nil {
t.Errorf("unexpected nil Trailer")
}
- if req.TLS == nil {
- t.Errorf("expected non-nil TLS")
+ if req.TLS != nil {
+ t.Errorf("expected nil TLS")
}
if e, g := "5.6.7.8:0", req.RemoteAddr; e != g {
t.Errorf("RemoteAddr: got %q; want %q", g, e)
}
}
+func TestRequestWithTLS(t *testing.T) {
+ env := map[string]string{
+ "SERVER_PROTOCOL": "HTTP/1.1",
+ "REQUEST_METHOD": "GET",
+ "HTTP_HOST": "example.com",
+ "HTTP_REFERER": "elsewhere",
+ "REQUEST_URI": "/path?a=b",
+ "CONTENT_TYPE": "text/xml",
+ "HTTPS": "1",
+ "REMOTE_ADDR": "5.6.7.8",
+ }
+ req, err := RequestFromMap(env)
+ if err != nil {
+ t.Fatalf("RequestFromMap: %v", err)
+ }
+ if g, e := req.URL.String(), "https://example.com/path?a=b"; e != g {
+ t.Errorf("expected URL %q; got %q", e, g)
+ }
+ if req.TLS == nil {
+ t.Errorf("expected non-nil TLS")
+ }
+}
+
func TestRequestWithoutHost(t *testing.T) {
env := map[string]string{
"SERVER_PROTOCOL": "HTTP/1.1",
diff --git a/libgo/go/net/http/client.go b/libgo/go/net/http/client.go
index a34d47be1fa..22f2e865cf7 100644
--- a/libgo/go/net/http/client.go
+++ b/libgo/go/net/http/client.go
@@ -74,8 +74,8 @@ type RoundTripper interface {
// authentication, or cookies.
//
// RoundTrip should not modify the request, except for
- // consuming the Body. The request's URL and Header fields
- // are guaranteed to be initialized.
+ // consuming and closing the Body. The request's URL and
+ // Header fields are guaranteed to be initialized.
RoundTrip(*Request) (*Response, error)
}
@@ -161,7 +161,9 @@ func send(req *Request, t RoundTripper) (resp *Response, err error) {
}
if u := req.URL.User; u != nil {
- req.Header.Set("Authorization", "Basic "+base64.URLEncoding.EncodeToString([]byte(u.String())))
+ username := u.Username()
+ password, _ := u.Password()
+ req.Header.Set("Authorization", "Basic "+basicAuth(username, password))
}
resp, err = t.RoundTrip(req)
if err != nil {
@@ -173,6 +175,16 @@ func send(req *Request, t RoundTripper) (resp *Response, err error) {
return resp, nil
}
+// See 2 (end of page 4) http://www.ietf.org/rfc/rfc2617.txt
+// "To receive authorization, the client sends the userid and password,
+// separated by a single colon (":") character, within a base64
+// encoded string in the credentials."
+// It is not meant to be urlencoded.
+func basicAuth(username, password string) string {
+ auth := username + ":" + password
+ return base64.StdEncoding.EncodeToString([]byte(auth))
+}
+
// True if the specified HTTP status code is one for which the Get utility should
// automatically redirect.
func shouldRedirectGet(statusCode int) bool {
@@ -335,6 +347,9 @@ func Post(url string, bodyType string, body io.Reader) (resp *Response, err erro
// Post issues a POST to the specified URL.
//
// Caller should close resp.Body when done reading from it.
+//
+// If the provided body is also an io.Closer, it is closed after the
+// body is successfully written to the server.
func (c *Client) Post(url string, bodyType string, body io.Reader) (resp *Response, err error) {
req, err := NewRequest("POST", url, body)
if err != nil {
diff --git a/libgo/go/net/http/client_test.go b/libgo/go/net/http/client_test.go
index 73f1fe3c10a..997d04151c2 100644
--- a/libgo/go/net/http/client_test.go
+++ b/libgo/go/net/http/client_test.go
@@ -10,6 +10,7 @@ import (
"bytes"
"crypto/tls"
"crypto/x509"
+ "encoding/base64"
"errors"
"fmt"
"io"
@@ -665,6 +666,36 @@ func TestClientWithIncorrectTLSServerName(t *testing.T) {
}
}
+// Test for golang.org/issue/5829; the Transport should respect TLSClientConfig.ServerName
+// when not empty.
+//
+// tls.Config.ServerName (non-empty, set to "example.com") takes
+// precedence over "some-other-host.tld" which previously incorrectly
+// took precedence. We don't actually connect to (or even resolve)
+// "some-other-host.tld", though, because of the Transport.Dial hook.
+//
+// The httptest.Server has a cert with "example.com" as its name.
+func TestTransportUsesTLSConfigServerName(t *testing.T) {
+ defer afterTest(t)
+ ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+ w.Write([]byte("Hello"))
+ }))
+ defer ts.Close()
+
+ tr := newTLSTransport(t, ts)
+ tr.TLSClientConfig.ServerName = "example.com" // one of httptest's Server cert names
+ tr.Dial = func(netw, addr string) (net.Conn, error) {
+ return net.Dial(netw, ts.Listener.Addr().String())
+ }
+ defer tr.CloseIdleConnections()
+ c := &Client{Transport: tr}
+ res, err := c.Get("https://some-other-host.tld/")
+ if err != nil {
+ t.Fatal(err)
+ }
+ res.Body.Close()
+}
+
// Verify Response.ContentLength is populated. http://golang.org/issue/4126
func TestClientHeadContentLength(t *testing.T) {
defer afterTest(t)
@@ -700,3 +731,71 @@ func TestClientHeadContentLength(t *testing.T) {
}
}
}
+
+func TestEmptyPasswordAuth(t *testing.T) {
+ defer afterTest(t)
+ gopher := "gopher"
+ ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+ auth := r.Header.Get("Authorization")
+ if strings.HasPrefix(auth, "Basic ") {
+ encoded := auth[6:]
+ decoded, err := base64.StdEncoding.DecodeString(encoded)
+ if err != nil {
+ t.Fatal(err)
+ }
+ expected := gopher + ":"
+ s := string(decoded)
+ if expected != s {
+ t.Errorf("Invalid Authorization header. Got %q, wanted %q", s, expected)
+ }
+ } else {
+ t.Errorf("Invalid auth %q", auth)
+ }
+ }))
+ defer ts.Close()
+ c := &Client{}
+ req, err := NewRequest("GET", ts.URL, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ req.URL.User = url.User(gopher)
+ resp, err := c.Do(req)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer resp.Body.Close()
+}
+
+func TestBasicAuth(t *testing.T) {
+ defer afterTest(t)
+ tr := &recordingTransport{}
+ client := &Client{Transport: tr}
+
+ url := "http://My%20User:My%20Pass@dummy.faketld/"
+ expected := "My User:My Pass"
+ client.Get(url)
+
+ if tr.req.Method != "GET" {
+ t.Errorf("got method %q, want %q", tr.req.Method, "GET")
+ }
+ if tr.req.URL.String() != url {
+ t.Errorf("got URL %q, want %q", tr.req.URL.String(), url)
+ }
+ if tr.req.Header == nil {
+ t.Fatalf("expected non-nil request Header")
+ }
+ auth := tr.req.Header.Get("Authorization")
+ if strings.HasPrefix(auth, "Basic ") {
+ encoded := auth[6:]
+ decoded, err := base64.StdEncoding.DecodeString(encoded)
+ if err != nil {
+ t.Fatal(err)
+ }
+ s := string(decoded)
+ if expected != s {
+ t.Errorf("Invalid Authorization header. Got %q, wanted %q", s, expected)
+ }
+ } else {
+ t.Errorf("Invalid auth %q", auth)
+ }
+}
diff --git a/libgo/go/net/http/cookie.go b/libgo/go/net/http/cookie.go
index 155b09223e4..8b01c508eb1 100644
--- a/libgo/go/net/http/cookie.go
+++ b/libgo/go/net/http/cookie.go
@@ -7,6 +7,8 @@ package http
import (
"bytes"
"fmt"
+ "log"
+ "net"
"strconv"
"strings"
"time"
@@ -139,12 +141,25 @@ func SetCookie(w ResponseWriter, cookie *Cookie) {
// header (if other fields are set).
func (c *Cookie) String() string {
var b bytes.Buffer
- fmt.Fprintf(&b, "%s=%s", sanitizeName(c.Name), sanitizeValue(c.Value))
+ fmt.Fprintf(&b, "%s=%s", sanitizeCookieName(c.Name), sanitizeCookieValue(c.Value))
if len(c.Path) > 0 {
- fmt.Fprintf(&b, "; Path=%s", sanitizeValue(c.Path))
+ fmt.Fprintf(&b, "; Path=%s", sanitizeCookiePath(c.Path))
}
if len(c.Domain) > 0 {
- fmt.Fprintf(&b, "; Domain=%s", sanitizeValue(c.Domain))
+ if validCookieDomain(c.Domain) {
+ // A c.Domain containing illegal characters is not
+ // sanitized but simply dropped which turns the cookie
+ // into a host-only cookie. A leading dot is okay
+ // but won't be sent.
+ d := c.Domain
+ if d[0] == '.' {
+ d = d[1:]
+ }
+ fmt.Fprintf(&b, "; Domain=%s", d)
+ } else {
+ log.Printf("net/http: invalid Cookie.Domain %q; dropping domain attribute",
+ c.Domain)
+ }
}
if c.Expires.Unix() > 0 {
fmt.Fprintf(&b, "; Expires=%s", c.Expires.UTC().Format(time.RFC1123))
@@ -207,16 +222,122 @@ func readCookies(h Header, filter string) []*Cookie {
return cookies
}
+// validCookieDomain returns wheter v is a valid cookie domain-value.
+func validCookieDomain(v string) bool {
+ if isCookieDomainName(v) {
+ return true
+ }
+ if net.ParseIP(v) != nil && !strings.Contains(v, ":") {
+ return true
+ }
+ return false
+}
+
+// isCookieDomainName returns whether s is a valid domain name or a valid
+// domain name with a leading dot '.'. It is almost a direct copy of
+// package net's isDomainName.
+func isCookieDomainName(s string) bool {
+ if len(s) == 0 {
+ return false
+ }
+ if len(s) > 255 {
+ return false
+ }
+
+ if s[0] == '.' {
+ // A cookie a domain attribute may start with a leading dot.
+ s = s[1:]
+ }
+ last := byte('.')
+ ok := false // Ok once we've seen a letter.
+ partlen := 0
+ for i := 0; i < len(s); i++ {
+ c := s[i]
+ switch {
+ default:
+ return false
+ case 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z':
+ // No '_' allowed here (in contrast to package net).
+ ok = true
+ partlen++
+ case '0' <= c && c <= '9':
+ // fine
+ partlen++
+ case c == '-':
+ // Byte before dash cannot be dot.
+ if last == '.' {
+ return false
+ }
+ partlen++
+ case c == '.':
+ // Byte before dot cannot be dot, dash.
+ if last == '.' || last == '-' {
+ return false
+ }
+ if partlen > 63 || partlen == 0 {
+ return false
+ }
+ partlen = 0
+ }
+ last = c
+ }
+ if last == '-' || partlen > 63 {
+ return false
+ }
+
+ return ok
+}
+
var cookieNameSanitizer = strings.NewReplacer("\n", "-", "\r", "-")
-func sanitizeName(n string) string {
+func sanitizeCookieName(n string) string {
return cookieNameSanitizer.Replace(n)
}
-var cookieValueSanitizer = strings.NewReplacer("\n", " ", "\r", " ", ";", " ")
+// http://tools.ietf.org/html/rfc6265#section-4.1.1
+// cookie-value = *cookie-octet / ( DQUOTE *cookie-octet DQUOTE )
+// cookie-octet = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E
+// ; US-ASCII characters excluding CTLs,
+// ; whitespace DQUOTE, comma, semicolon,
+// ; and backslash
+func sanitizeCookieValue(v string) string {
+ return sanitizeOrWarn("Cookie.Value", validCookieValueByte, v)
+}
+
+func validCookieValueByte(b byte) bool {
+ return 0x20 < b && b < 0x7f && b != '"' && b != ',' && b != ';' && b != '\\'
+}
+
+// path-av = "Path=" path-value
+// path-value = <any CHAR except CTLs or ";">
+func sanitizeCookiePath(v string) string {
+ return sanitizeOrWarn("Cookie.Path", validCookiePathByte, v)
+}
-func sanitizeValue(v string) string {
- return cookieValueSanitizer.Replace(v)
+func validCookiePathByte(b byte) bool {
+ return 0x20 <= b && b < 0x7f && b != ';'
+}
+
+func sanitizeOrWarn(fieldName string, valid func(byte) bool, v string) string {
+ ok := true
+ for i := 0; i < len(v); i++ {
+ if valid(v[i]) {
+ continue
+ }
+ log.Printf("net/http: invalid byte %q in %s; dropping invalid bytes", v[i], fieldName)
+ ok = false
+ break
+ }
+ if ok {
+ return v
+ }
+ buf := make([]byte, 0, len(v))
+ for i := 0; i < len(v); i++ {
+ if b := v[i]; valid(b) {
+ buf = append(buf, b)
+ }
+ }
+ return string(buf)
}
func unquoteCookieValue(v string) string {
diff --git a/libgo/go/net/http/cookie_test.go b/libgo/go/net/http/cookie_test.go
index f84f73936c7..11b01cc5713 100644
--- a/libgo/go/net/http/cookie_test.go
+++ b/libgo/go/net/http/cookie_test.go
@@ -26,12 +26,28 @@ var writeSetCookiesTests = []struct {
},
{
&Cookie{Name: "cookie-3", Value: "three", Domain: ".example.com"},
- "cookie-3=three; Domain=.example.com",
+ "cookie-3=three; Domain=example.com",
},
{
&Cookie{Name: "cookie-4", Value: "four", Path: "/restricted/"},
"cookie-4=four; Path=/restricted/",
},
+ {
+ &Cookie{Name: "cookie-5", Value: "five", Domain: "wrong;bad.abc"},
+ "cookie-5=five",
+ },
+ {
+ &Cookie{Name: "cookie-6", Value: "six", Domain: "bad-.abc"},
+ "cookie-6=six",
+ },
+ {
+ &Cookie{Name: "cookie-7", Value: "seven", Domain: "127.0.0.1"},
+ "cookie-7=seven; Domain=127.0.0.1",
+ },
+ {
+ &Cookie{Name: "cookie-8", Value: "eight", Domain: "::1"},
+ "cookie-8=eight",
+ },
}
func TestWriteSetCookies(t *testing.T) {
@@ -226,3 +242,34 @@ func TestReadCookies(t *testing.T) {
}
}
}
+
+func TestCookieSanitizeValue(t *testing.T) {
+ tests := []struct {
+ in, want string
+ }{
+ {"foo", "foo"},
+ {"foo bar", "foobar"},
+ {"\x00\x7e\x7f\x80", "\x7e"},
+ {`"withquotes"`, "withquotes"},
+ }
+ for _, tt := range tests {
+ if got := sanitizeCookieValue(tt.in); got != tt.want {
+ t.Errorf("sanitizeCookieValue(%q) = %q; want %q", tt.in, got, tt.want)
+ }
+ }
+}
+
+func TestCookieSanitizePath(t *testing.T) {
+ tests := []struct {
+ in, want string
+ }{
+ {"/path", "/path"},
+ {"/path with space/", "/path with space/"},
+ {"/just;no;semicolon\x00orstuff/", "/justnosemicolonorstuff/"},
+ }
+ for _, tt := range tests {
+ if got := sanitizeCookiePath(tt.in); got != tt.want {
+ t.Errorf("sanitizeCookiePath(%q) = %q; want %q", tt.in, got, tt.want)
+ }
+ }
+}
diff --git a/libgo/go/net/http/cookiejar/jar.go b/libgo/go/net/http/cookiejar/jar.go
index 5977d48b631..389ab58e418 100644
--- a/libgo/go/net/http/cookiejar/jar.go
+++ b/libgo/go/net/http/cookiejar/jar.go
@@ -142,7 +142,7 @@ func (e *entry) pathMatch(requestPath string) bool {
return false
}
-// hasDotSuffix returns whether s ends in "."+suffix.
+// hasDotSuffix reports whether s ends in "."+suffix.
func hasDotSuffix(s, suffix string) bool {
return len(s) > len(suffix) && s[len(s)-len(suffix)-1] == '.' && s[len(s)-len(suffix):] == suffix
}
@@ -316,7 +316,7 @@ func canonicalHost(host string) (string, error) {
return toASCII(host)
}
-// hasPort returns whether host contains a port number. host may be a host
+// hasPort reports whether host contains a port number. host may be a host
// name, an IPv4 or an IPv6 address.
func hasPort(host string) bool {
colons := strings.Count(host, ":")
@@ -357,7 +357,7 @@ func jarKey(host string, psl PublicSuffixList) string {
return host[prevDot+1:]
}
-// isIP returns whether host is an IP address.
+// isIP reports whether host is an IP address.
func isIP(host string) bool {
return net.ParseIP(host) != nil
}
@@ -380,7 +380,7 @@ func defaultPath(path string) string {
// is compared to c.Expires to determine deletion of c. defPath and host are the
// default-path and the canonical host name of the URL c was received from.
//
-// remove is whether the jar should delete this cookie, as it has already
+// remove records whether the jar should delete this cookie, as it has already
// expired with respect to now. In this case, e may be incomplete, but it will
// be valid to call e.id (which depends on e's Name, Domain and Path).
//
diff --git a/libgo/go/net/http/doc.go b/libgo/go/net/http/doc.go
index b6ae8b87a2f..b1216e8dafa 100644
--- a/libgo/go/net/http/doc.go
+++ b/libgo/go/net/http/doc.go
@@ -5,7 +5,7 @@
/*
Package http provides HTTP client and server implementations.
-Get, Head, Post, and PostForm make HTTP requests:
+Get, Head, Post, and PostForm make HTTP (or HTTPS) requests:
resp, err := http.Get("http://example.com/")
...
diff --git a/libgo/go/net/http/example_test.go b/libgo/go/net/http/example_test.go
index bc60df7f2b5..88b97d9e3d7 100644
--- a/libgo/go/net/http/example_test.go
+++ b/libgo/go/net/http/example_test.go
@@ -68,3 +68,21 @@ func ExampleStripPrefix() {
// URL's path before the FileServer sees it:
http.Handle("/tmpfiles/", http.StripPrefix("/tmpfiles/", http.FileServer(http.Dir("/tmp"))))
}
+
+type apiHandler struct{}
+
+func (apiHandler) ServeHTTP(http.ResponseWriter, *http.Request) {}
+
+func ExampleServeMux_Handle() {
+ mux := http.NewServeMux()
+ mux.Handle("/api/", apiHandler{})
+ mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
+ // The "/" pattern matches everything, so we need to check
+ // that we're at the root here.
+ if req.URL.Path != "/" {
+ http.NotFound(w, req)
+ return
+ }
+ fmt.Fprintf(w, "Welcome to the home page!")
+ })
+}
diff --git a/libgo/go/net/http/export_test.go b/libgo/go/net/http/export_test.go
index 3fc24532676..22b7f279689 100644
--- a/libgo/go/net/http/export_test.go
+++ b/libgo/go/net/http/export_test.go
@@ -16,6 +16,8 @@ func NewLoggingConn(baseName string, c net.Conn) net.Conn {
return newLoggingConn(baseName, c)
}
+var ExportAppendTime = appendTime
+
func (t *Transport) NumPendingRequestsForTesting() int {
t.reqMu.Lock()
defer t.reqMu.Unlock()
@@ -48,6 +50,12 @@ func (t *Transport) IdleConnCountForTesting(cacheKey string) int {
return len(conns)
}
+func (t *Transport) IdleConnChMapSizeForTesting() int {
+ t.idleMu.Lock()
+ defer t.idleMu.Unlock()
+ return len(t.idleConnCh)
+}
+
func NewTestTimeoutHandler(handler Handler, ch <-chan time.Time) Handler {
f := func() <-chan time.Time {
return ch
diff --git a/libgo/go/net/http/fs.go b/libgo/go/net/http/fs.go
index b6bea0dfaad..8b32ca1d0ea 100644
--- a/libgo/go/net/http/fs.go
+++ b/libgo/go/net/http/fs.go
@@ -105,23 +105,31 @@ func dirList(w ResponseWriter, f File) {
//
// Note that *os.File implements the io.ReadSeeker interface.
func ServeContent(w ResponseWriter, req *Request, name string, modtime time.Time, content io.ReadSeeker) {
- size, err := content.Seek(0, os.SEEK_END)
- if err != nil {
- Error(w, "seeker can't seek", StatusInternalServerError)
- return
- }
- _, err = content.Seek(0, os.SEEK_SET)
- if err != nil {
- Error(w, "seeker can't seek", StatusInternalServerError)
- return
+ sizeFunc := func() (int64, error) {
+ size, err := content.Seek(0, os.SEEK_END)
+ if err != nil {
+ return 0, errSeeker
+ }
+ _, err = content.Seek(0, os.SEEK_SET)
+ if err != nil {
+ return 0, errSeeker
+ }
+ return size, nil
}
- serveContent(w, req, name, modtime, size, content)
+ serveContent(w, req, name, modtime, sizeFunc, content)
}
+// errSeeker is returned by ServeContent's sizeFunc when the content
+// doesn't seek properly. The underlying Seeker's error text isn't
+// included in the sizeFunc reply so it's not sent over HTTP to end
+// users.
+var errSeeker = errors.New("seeker can't seek")
+
// if name is empty, filename is unknown. (used for mime type, before sniffing)
// if modtime.IsZero(), modtime is unknown.
// content must be seeked to the beginning of the file.
-func serveContent(w ResponseWriter, r *Request, name string, modtime time.Time, size int64, content io.ReadSeeker) {
+// The sizeFunc is called at most once. Its error, if any, is sent in the HTTP response.
+func serveContent(w ResponseWriter, r *Request, name string, modtime time.Time, sizeFunc func() (int64, error), content io.ReadSeeker) {
if checkLastModified(w, r, modtime) {
return
}
@@ -132,16 +140,17 @@ func serveContent(w ResponseWriter, r *Request, name string, modtime time.Time,
code := StatusOK
- // If Content-Type isn't set, use the file's extension to find it.
- ctype := w.Header().Get("Content-Type")
- if ctype == "" {
+ // If Content-Type isn't set, use the file's extension to find it, but
+ // if the Content-Type is unset explicitly, do not sniff the type.
+ ctypes, haveType := w.Header()["Content-Type"]
+ var ctype string
+ if !haveType {
ctype = mime.TypeByExtension(filepath.Ext(name))
if ctype == "" {
// read a chunk to decide between utf-8 text and binary
- var buf [1024]byte
+ var buf [sniffLen]byte
n, _ := io.ReadFull(content, buf[:])
- b := buf[:n]
- ctype = DetectContentType(b)
+ ctype = DetectContentType(buf[:n])
_, err := content.Seek(0, os.SEEK_SET) // rewind to output whole file
if err != nil {
Error(w, "seeker can't seek", StatusInternalServerError)
@@ -149,6 +158,14 @@ func serveContent(w ResponseWriter, r *Request, name string, modtime time.Time,
}
}
w.Header().Set("Content-Type", ctype)
+ } else if len(ctypes) > 0 {
+ ctype = ctypes[0]
+ }
+
+ size, err := sizeFunc()
+ if err != nil {
+ Error(w, err.Error(), StatusInternalServerError)
+ return
}
// handle Content-Range header.
@@ -160,7 +177,7 @@ func serveContent(w ResponseWriter, r *Request, name string, modtime time.Time,
Error(w, err.Error(), StatusRequestedRangeNotSatisfiable)
return
}
- if sumRangesSize(ranges) >= size {
+ if sumRangesSize(ranges) > size {
// The total number of bytes in all the ranges
// is larger than the size of the file by
// itself, so this is probably an attack, or a
@@ -378,7 +395,8 @@ func serveFile(w ResponseWriter, r *Request, fs FileSystem, name string, redirec
}
// serverContent will check modification time
- serveContent(w, r, d.Name(), d.ModTime(), d.Size(), f)
+ sizeFunc := func() (int64, error) { return d.Size(), nil }
+ serveContent(w, r, d.Name(), d.ModTime(), sizeFunc, f)
}
// localRedirect gives a Moved Permanently response.
diff --git a/libgo/go/net/http/fs_test.go b/libgo/go/net/http/fs_test.go
index d38966764b1..dd3e9fefeac 100644
--- a/libgo/go/net/http/fs_test.go
+++ b/libgo/go/net/http/fs_test.go
@@ -20,8 +20,10 @@ import (
"os/exec"
"path"
"path/filepath"
+ "reflect"
"regexp"
"runtime"
+ "strconv"
"strings"
"testing"
"time"
@@ -36,6 +38,8 @@ type wantRange struct {
start, end int64 // range [start,end)
}
+var itoa = strconv.Itoa
+
var ServeFileRangeTests = []struct {
r string
code int
@@ -50,7 +54,11 @@ var ServeFileRangeTests = []struct {
{r: "bytes=0-0,-2", code: StatusPartialContent, ranges: []wantRange{{0, 1}, {testFileLen - 2, testFileLen}}},
{r: "bytes=0-1,5-8", code: StatusPartialContent, ranges: []wantRange{{0, 2}, {5, 9}}},
{r: "bytes=0-1,5-", code: StatusPartialContent, ranges: []wantRange{{0, 2}, {5, testFileLen}}},
+ {r: "bytes=5-1000", code: StatusPartialContent, ranges: []wantRange{{5, testFileLen}}},
{r: "bytes=0-,1-,2-,3-,4-", code: StatusOK}, // ignore wasteful range request
+ {r: "bytes=0-" + itoa(testFileLen-2), code: StatusPartialContent, ranges: []wantRange{{0, testFileLen - 1}}},
+ {r: "bytes=0-" + itoa(testFileLen-1), code: StatusPartialContent, ranges: []wantRange{{0, testFileLen}}},
+ {r: "bytes=0-" + itoa(testFileLen), code: StatusPartialContent, ranges: []wantRange{{0, testFileLen}}},
}
func TestServeFile(t *testing.T) {
@@ -259,6 +267,9 @@ func TestFileServerImplicitLeadingSlash(t *testing.T) {
}
func TestDirJoin(t *testing.T) {
+ if runtime.GOOS == "windows" {
+ t.Skip("skipping test on windows")
+ }
wfi, err := os.Stat("/etc/hosts")
if err != nil {
t.Skip("skipping test; no /etc/hosts file")
@@ -309,24 +320,29 @@ func TestServeFileContentType(t *testing.T) {
defer afterTest(t)
const ctype = "icecream/chocolate"
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
- if r.FormValue("override") == "1" {
+ switch r.FormValue("override") {
+ case "1":
w.Header().Set("Content-Type", ctype)
+ case "2":
+ // Explicitly inhibit sniffing.
+ w.Header()["Content-Type"] = []string{}
}
ServeFile(w, r, "testdata/file")
}))
defer ts.Close()
- get := func(override, want string) {
+ get := func(override string, want []string) {
resp, err := Get(ts.URL + "?override=" + override)
if err != nil {
t.Fatal(err)
}
- if h := resp.Header.Get("Content-Type"); h != want {
- t.Errorf("Content-Type mismatch: got %q, want %q", h, want)
+ if h := resp.Header["Content-Type"]; !reflect.DeepEqual(h, want) {
+ t.Errorf("Content-Type mismatch: got %v, want %v", h, want)
}
resp.Body.Close()
}
- get("0", "text/plain; charset=utf-8")
- get("1", ctype)
+ get("0", []string{"text/plain; charset=utf-8"})
+ get("1", []string{ctype})
+ get("2", nil)
}
func TestServeFileMimeType(t *testing.T) {
@@ -567,7 +583,10 @@ func TestServeContent(t *testing.T) {
defer ts.Close()
type testCase struct {
- file string
+ // One of file or content must be set:
+ file string
+ content io.ReadSeeker
+
modtime time.Time
serveETag string // optional
serveContentType string // optional
@@ -615,6 +634,14 @@ func TestServeContent(t *testing.T) {
},
wantStatus: 304,
},
+ "not_modified_etag_no_seek": {
+ content: panicOnSeek{nil}, // should never be called
+ serveETag: `"foo"`,
+ reqHeader: map[string]string{
+ "If-None-Match": `"foo"`,
+ },
+ wantStatus: 304,
+ },
"range_good": {
file: "testdata/style.css",
serveETag: `"A"`,
@@ -638,15 +665,21 @@ func TestServeContent(t *testing.T) {
},
}
for testName, tt := range tests {
- f, err := os.Open(tt.file)
- if err != nil {
- t.Fatalf("test %q: %v", testName, err)
+ var content io.ReadSeeker
+ if tt.file != "" {
+ f, err := os.Open(tt.file)
+ if err != nil {
+ t.Fatalf("test %q: %v", testName, err)
+ }
+ defer f.Close()
+ content = f
+ } else {
+ content = tt.content
}
- defer f.Close()
servec <- serveParam{
name: filepath.Base(tt.file),
- content: f,
+ content: content,
modtime: tt.modtime,
etag: tt.serveETag,
contentType: tt.serveContentType,
@@ -768,3 +801,5 @@ func TestLinuxSendfileChild(*testing.T) {
panic(err)
}
}
+
+type panicOnSeek struct{ io.ReadSeeker }
diff --git a/libgo/go/net/http/header.go b/libgo/go/net/http/header.go
index 6374237fba1..ca1ae07c25d 100644
--- a/libgo/go/net/http/header.go
+++ b/libgo/go/net/http/header.go
@@ -173,7 +173,7 @@ func (h Header) WriteSubset(w io.Writer, exclude map[string]bool) error {
// canonical key for "accept-encoding" is "Accept-Encoding".
func CanonicalHeaderKey(s string) string { return textproto.CanonicalMIMEHeaderKey(s) }
-// hasToken returns whether token appears with v, ASCII
+// hasToken reports whether token appears with v, ASCII
// case-insensitive, with space or comma boundaries.
// token must be all lowercase.
// v may contain mixed cased.
diff --git a/libgo/go/net/http/header_test.go b/libgo/go/net/http/header_test.go
index 584f1005440..2c896c5ad23 100644
--- a/libgo/go/net/http/header_test.go
+++ b/libgo/go/net/http/header_test.go
@@ -193,6 +193,9 @@ func BenchmarkHeaderWriteSubset(b *testing.B) {
}
func TestHeaderWriteSubsetMallocs(t *testing.T) {
+ if testing.Short() {
+ t.Skip("skipping malloc count in short mode")
+ }
t.Skip("Skipping alloc count test on gccgo")
if runtime.GOMAXPROCS(0) > 1 {
t.Skip("skipping; GOMAXPROCS>1")
@@ -202,6 +205,6 @@ func TestHeaderWriteSubsetMallocs(t *testing.T) {
testHeader.WriteSubset(&buf, nil)
})
if n > 0 {
- t.Errorf("mallocs = %d; want 0", n)
+ t.Errorf("mallocs = %g; want 0", n)
}
}
diff --git a/libgo/go/net/http/request.go b/libgo/go/net/http/request.go
index 6d4569146fd..57b5d094847 100644
--- a/libgo/go/net/http/request.go
+++ b/libgo/go/net/http/request.go
@@ -10,7 +10,6 @@ import (
"bufio"
"bytes"
"crypto/tls"
- "encoding/base64"
"errors"
"fmt"
"io"
@@ -106,7 +105,16 @@ type Request struct {
// following a hyphen uppercase and the rest lowercase.
Header Header
- // The message body.
+ // Body is the request's body.
+ //
+ // For client requests, a nil body means the request has no
+ // body, such as a GET request. The HTTP Client's Transport
+ // is responsible for calling the Close method.
+ //
+ // For server requests, the Request Body is always non-nil
+ // but will return EOF immediately when no body is present.
+ // The Server will close the request body. The ServeHTTP
+ // Handler does not need to.
Body io.ReadCloser
// ContentLength records the length of the associated content.
@@ -183,7 +191,7 @@ type Request struct {
TLS *tls.ConnectionState
}
-// ProtoAtLeast returns whether the HTTP protocol used
+// ProtoAtLeast reports whether the HTTP protocol used
// in the request is at least major.minor.
func (r *Request) ProtoAtLeast(major, minor int) bool {
return r.ProtoMajor > major ||
@@ -216,7 +224,7 @@ func (r *Request) Cookie(name string) (*Cookie, error) {
// means all cookies, if any, are written into the same line,
// separated by semicolon.
func (r *Request) AddCookie(c *Cookie) {
- s := fmt.Sprintf("%s=%s", sanitizeName(c.Name), sanitizeValue(c.Value))
+ s := fmt.Sprintf("%s=%s", sanitizeCookieName(c.Name), sanitizeCookieValue(c.Value))
if c := r.Header.Get("Cookie"); c != "" {
r.Header.Set("Cookie", c+"; "+s)
} else {
@@ -283,6 +291,11 @@ func valueOrDefault(value, def string) string {
return def
}
+// NOTE: This is not intended to reflect the actual Go version being used.
+// It was changed from "Go http package" to "Go 1.1 package http" at the
+// time of the Go 1.1 release because the former User-Agent had ended up
+// on a blacklist for some intrusion detection systems.
+// See https://codereview.appspot.com/7532043.
const defaultUserAgent = "Go 1.1 package http"
// Write writes an HTTP/1.1 request -- header and body -- in wire format.
@@ -424,6 +437,10 @@ func ParseHTTPVersion(vers string) (major, minor int, ok bool) {
}
// NewRequest returns a new Request given a method, URL, and optional body.
+//
+// If the provided body is also an io.Closer, the returned
+// Request.Body is set to body and will be closed by the Client
+// methods Do, Post, and PostForm, and Transport.RoundTrip.
func NewRequest(method, urlStr string, body io.Reader) (*Request, error) {
u, err := url.Parse(urlStr)
if err != nil {
@@ -463,8 +480,7 @@ func NewRequest(method, urlStr string, body io.Reader) (*Request, error) {
// With HTTP Basic Authentication the provided username and password
// are not encrypted.
func (r *Request) SetBasicAuth(username, password string) {
- s := username + ":" + password
- r.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(s)))
+ r.Header.Set("Authorization", "Basic "+basicAuth(username, password))
}
// parseRequestLine parses "GET /foo HTTP/1.1" into its three parts.
diff --git a/libgo/go/net/http/request_test.go b/libgo/go/net/http/request_test.go
index 692485c49d9..89303c33602 100644
--- a/libgo/go/net/http/request_test.go
+++ b/libgo/go/net/http/request_test.go
@@ -332,7 +332,7 @@ func TestRequestWriteBufferedWriter(t *testing.T) {
func testMissingFile(t *testing.T, req *Request) {
f, fh, err := req.FormFile("missing")
if f != nil {
- t.Errorf("FormFile file = %q, want nil", f)
+ t.Errorf("FormFile file = %v, want nil", f)
}
if fh != nil {
t.Errorf("FormFile file header = %q, want nil", fh)
diff --git a/libgo/go/net/http/response.go b/libgo/go/net/http/response.go
index 9a7e4e319b0..35d0ba3bb15 100644
--- a/libgo/go/net/http/response.go
+++ b/libgo/go/net/http/response.go
@@ -32,7 +32,7 @@ type Response struct {
ProtoMinor int // e.g. 0
// Header maps header keys to values. If the response had multiple
- // headers with the same key, they will be concatenated, with comma
+ // headers with the same key, they may be concatenated, with comma
// delimiters. (Section 4.2 of RFC 2616 requires that multiple headers
// be semantically equivalent to a comma-delimited sequence.) Values
// duplicated by other fields in this struct (e.g., ContentLength) are
@@ -98,18 +98,17 @@ func (r *Response) Location() (*url.URL, error) {
return url.Parse(lv)
}
-// ReadResponse reads and returns an HTTP response from r. The
-// req parameter specifies the Request that corresponds to
-// this Response. Clients must call resp.Body.Close when finished
-// reading resp.Body. After that call, clients can inspect
-// resp.Trailer to find key/value pairs included in the response
-// trailer.
-func ReadResponse(r *bufio.Reader, req *Request) (resp *Response, err error) {
-
+// ReadResponse reads and returns an HTTP response from r.
+// The req parameter optionally specifies the Request that corresponds
+// to this Response. If nil, a GET request is assumed.
+// Clients must call resp.Body.Close when finished reading resp.Body.
+// After that call, clients can inspect resp.Trailer to find key/value
+// pairs included in the response trailer.
+func ReadResponse(r *bufio.Reader, req *Request) (*Response, error) {
tp := textproto.NewReader(r)
- resp = new(Response)
-
- resp.Request = req
+ resp := &Response{
+ Request: req,
+ }
// Parse the first line of the response.
line, err := tp.ReadLine()
@@ -168,7 +167,7 @@ func fixPragmaCacheControl(header Header) {
}
}
-// ProtoAtLeast returns whether the HTTP protocol used
+// ProtoAtLeast reports whether the HTTP protocol used
// in the response is at least major.minor.
func (r *Response) ProtoAtLeast(major, minor int) bool {
return r.ProtoMajor > major ||
diff --git a/libgo/go/net/http/response_test.go b/libgo/go/net/http/response_test.go
index 02796e88b4c..5044306a876 100644
--- a/libgo/go/net/http/response_test.go
+++ b/libgo/go/net/http/response_test.go
@@ -348,6 +348,29 @@ some body`,
"some body",
},
+
+ // Unchunked response without Content-Length, Request is nil
+ {
+ "HTTP/1.0 200 OK\r\n" +
+ "Connection: close\r\n" +
+ "\r\n" +
+ "Body here\n",
+
+ Response{
+ Status: "200 OK",
+ StatusCode: 200,
+ Proto: "HTTP/1.0",
+ ProtoMajor: 1,
+ ProtoMinor: 0,
+ Header: Header{
+ "Connection": {"close"}, // TODO(rsc): Delete?
+ },
+ Close: true,
+ ContentLength: -1,
+ },
+
+ "Body here\n",
+ },
}
func TestReadResponse(t *testing.T) {
@@ -565,3 +588,42 @@ func TestResponseStatusStutter(t *testing.T) {
t.Errorf("stutter in status: %s", buf.String())
}
}
+
+func TestResponseContentLengthShortBody(t *testing.T) {
+ const shortBody = "Short body, not 123 bytes."
+ br := bufio.NewReader(strings.NewReader("HTTP/1.1 200 OK\r\n" +
+ "Content-Length: 123\r\n" +
+ "\r\n" +
+ shortBody))
+ res, err := ReadResponse(br, &Request{Method: "GET"})
+ if err != nil {
+ t.Fatal(err)
+ }
+ if res.ContentLength != 123 {
+ t.Fatalf("Content-Length = %d; want 123", res.ContentLength)
+ }
+ var buf bytes.Buffer
+ n, err := io.Copy(&buf, res.Body)
+ if n != int64(len(shortBody)) {
+ t.Errorf("Copied %d bytes; want %d, len(%q)", n, len(shortBody), shortBody)
+ }
+ if buf.String() != shortBody {
+ t.Errorf("Read body %q; want %q", buf.String(), shortBody)
+ }
+ if err != io.ErrUnexpectedEOF {
+ t.Errorf("io.Copy error = %#v; want io.ErrUnexpectedEOF", err)
+ }
+}
+
+func TestNeedsSniff(t *testing.T) {
+ // needsSniff returns true with an empty response.
+ r := &response{}
+ if got, want := r.needsSniff(), true; got != want {
+ t.Errorf("needsSniff = %t; want %t", got, want)
+ }
+ // needsSniff returns false when Content-Type = nil.
+ r.handlerHeader = Header{"Content-Type": nil}
+ if got, want := r.needsSniff(), false; got != want {
+ t.Errorf("needsSniff empty Content-Type = %t; want %t", got, want)
+ }
+}
diff --git a/libgo/go/net/http/serve_test.go b/libgo/go/net/http/serve_test.go
index d7b321597c4..8961cf491f8 100644
--- a/libgo/go/net/http/serve_test.go
+++ b/libgo/go/net/http/serve_test.go
@@ -116,6 +116,34 @@ func (c *testConn) Close() error {
return nil
}
+// reqBytes treats req as a request (with \n delimiters) and returns it with \r\n delimiters,
+// ending in \r\n\r\n
+func reqBytes(req string) []byte {
+ return []byte(strings.Replace(strings.TrimSpace(req), "\n", "\r\n", -1) + "\r\n\r\n")
+}
+
+type handlerTest struct {
+ handler Handler
+}
+
+func newHandlerTest(h Handler) handlerTest {
+ return handlerTest{h}
+}
+
+func (ht handlerTest) rawResponse(req string) string {
+ reqb := reqBytes(req)
+ var output bytes.Buffer
+ conn := &rwTestConn{
+ Reader: bytes.NewReader(reqb),
+ Writer: &output,
+ closec: make(chan bool, 1),
+ }
+ ln := &oneConnListener{conn: conn}
+ go Serve(ln, ht.handler)
+ <-conn.closec
+ return output.String()
+}
+
func TestConsumingBodyOnNextConn(t *testing.T) {
conn := new(testConn)
for i := 0; i < 2; i++ {
@@ -241,6 +269,152 @@ func TestHostHandlers(t *testing.T) {
}
}
+var serveMuxRegister = []struct {
+ pattern string
+ h Handler
+}{
+ {"/dir/", serve(200)},
+ {"/search", serve(201)},
+ {"codesearch.google.com/search", serve(202)},
+ {"codesearch.google.com/", serve(203)},
+ {"example.com/", HandlerFunc(checkQueryStringHandler)},
+}
+
+// serve returns a handler that sends a response with the given code.
+func serve(code int) HandlerFunc {
+ return func(w ResponseWriter, r *Request) {
+ w.WriteHeader(code)
+ }
+}
+
+// checkQueryStringHandler checks if r.URL.RawQuery has the same value
+// as the URL excluding the scheme and the query string and sends 200
+// response code if it is, 500 otherwise.
+func checkQueryStringHandler(w ResponseWriter, r *Request) {
+ u := *r.URL
+ u.Scheme = "http"
+ u.Host = r.Host
+ u.RawQuery = ""
+ if "http://"+r.URL.RawQuery == u.String() {
+ w.WriteHeader(200)
+ } else {
+ w.WriteHeader(500)
+ }
+}
+
+var serveMuxTests = []struct {
+ method string
+ host string
+ path string
+ code int
+ pattern string
+}{
+ {"GET", "google.com", "/", 404, ""},
+ {"GET", "google.com", "/dir", 301, "/dir/"},
+ {"GET", "google.com", "/dir/", 200, "/dir/"},
+ {"GET", "google.com", "/dir/file", 200, "/dir/"},
+ {"GET", "google.com", "/search", 201, "/search"},
+ {"GET", "google.com", "/search/", 404, ""},
+ {"GET", "google.com", "/search/foo", 404, ""},
+ {"GET", "codesearch.google.com", "/search", 202, "codesearch.google.com/search"},
+ {"GET", "codesearch.google.com", "/search/", 203, "codesearch.google.com/"},
+ {"GET", "codesearch.google.com", "/search/foo", 203, "codesearch.google.com/"},
+ {"GET", "codesearch.google.com", "/", 203, "codesearch.google.com/"},
+ {"GET", "images.google.com", "/search", 201, "/search"},
+ {"GET", "images.google.com", "/search/", 404, ""},
+ {"GET", "images.google.com", "/search/foo", 404, ""},
+ {"GET", "google.com", "/../search", 301, "/search"},
+ {"GET", "google.com", "/dir/..", 301, ""},
+ {"GET", "google.com", "/dir/..", 301, ""},
+ {"GET", "google.com", "/dir/./file", 301, "/dir/"},
+
+ // The /foo -> /foo/ redirect applies to CONNECT requests
+ // but the path canonicalization does not.
+ {"CONNECT", "google.com", "/dir", 301, "/dir/"},
+ {"CONNECT", "google.com", "/../search", 404, ""},
+ {"CONNECT", "google.com", "/dir/..", 200, "/dir/"},
+ {"CONNECT", "google.com", "/dir/..", 200, "/dir/"},
+ {"CONNECT", "google.com", "/dir/./file", 200, "/dir/"},
+}
+
+func TestServeMuxHandler(t *testing.T) {
+ mux := NewServeMux()
+ for _, e := range serveMuxRegister {
+ mux.Handle(e.pattern, e.h)
+ }
+
+ for _, tt := range serveMuxTests {
+ r := &Request{
+ Method: tt.method,
+ Host: tt.host,
+ URL: &url.URL{
+ Path: tt.path,
+ },
+ }
+ h, pattern := mux.Handler(r)
+ rr := httptest.NewRecorder()
+ h.ServeHTTP(rr, r)
+ if pattern != tt.pattern || rr.Code != tt.code {
+ t.Errorf("%s %s %s = %d, %q, want %d, %q", tt.method, tt.host, tt.path, rr.Code, pattern, tt.code, tt.pattern)
+ }
+ }
+}
+
+var serveMuxTests2 = []struct {
+ method string
+ host string
+ url string
+ code int
+ redirOk bool
+}{
+ {"GET", "google.com", "/", 404, false},
+ {"GET", "example.com", "/test/?example.com/test/", 200, false},
+ {"GET", "example.com", "test/?example.com/test/", 200, true},
+}
+
+// TestServeMuxHandlerRedirects tests that automatic redirects generated by
+// mux.Handler() shouldn't clear the request's query string.
+func TestServeMuxHandlerRedirects(t *testing.T) {
+ mux := NewServeMux()
+ for _, e := range serveMuxRegister {
+ mux.Handle(e.pattern, e.h)
+ }
+
+ for _, tt := range serveMuxTests2 {
+ tries := 1
+ turl := tt.url
+ for tries > 0 {
+ u, e := url.Parse(turl)
+ if e != nil {
+ t.Fatal(e)
+ }
+ r := &Request{
+ Method: tt.method,
+ Host: tt.host,
+ URL: u,
+ }
+ h, _ := mux.Handler(r)
+ rr := httptest.NewRecorder()
+ h.ServeHTTP(rr, r)
+ if rr.Code != 301 {
+ if rr.Code != tt.code {
+ t.Errorf("%s %s %s = %d, want %d", tt.method, tt.host, tt.url, rr.Code, tt.code)
+ }
+ break
+ }
+ if !tt.redirOk {
+ t.Errorf("%s %s %s, unexpected redirect", tt.method, tt.host, tt.url)
+ break
+ }
+ turl = rr.HeaderMap.Get("Location")
+ tries--
+ }
+ if tries < 0 {
+ t.Errorf("%s %s %s, too many redirects", tt.method, tt.host, tt.url)
+ }
+ }
+}
+
// Tests for http://code.google.com/p/go/issues/detail?id=900
func TestMuxRedirectLeadingSlashes(t *testing.T) {
paths := []string{"//foo.txt", "///foo.txt", "/../../foo.txt"}
@@ -626,22 +800,20 @@ func Test304Responses(t *testing.T) {
}
}
-// TestHeadResponses verifies that responses to HEAD requests don't
-// declare that they're chunking in their response headers, aren't
-// allowed to produce output, and don't set a Content-Type since
-// the real type of the body data cannot be inferred.
+// TestHeadResponses verifies that all MIME type sniffing and Content-Length
+// counting of GET requests also happens on HEAD requests.
func TestHeadResponses(t *testing.T) {
defer afterTest(t)
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
- _, err := w.Write([]byte("Ignored body"))
- if err != ErrBodyNotAllowed {
- t.Errorf("on Write, expected ErrBodyNotAllowed, got %v", err)
+ _, err := w.Write([]byte("<html>"))
+ if err != nil {
+ t.Errorf("ResponseWriter.Write: %v", err)
}
// Also exercise the ReaderFrom path
- _, err = io.Copy(w, strings.NewReader("Ignored body"))
- if err != ErrBodyNotAllowed {
- t.Errorf("on Copy, expected ErrBodyNotAllowed, got %v", err)
+ _, err = io.Copy(w, strings.NewReader("789a"))
+ if err != nil {
+ t.Errorf("Copy(ResponseWriter, ...): %v", err)
}
}))
defer ts.Close()
@@ -652,9 +824,11 @@ func TestHeadResponses(t *testing.T) {
if len(res.TransferEncoding) > 0 {
t.Errorf("expected no TransferEncoding; got %v", res.TransferEncoding)
}
- ct := res.Header.Get("Content-Type")
- if ct != "" {
- t.Errorf("expected no Content-Type; got %s", ct)
+ if ct := res.Header.Get("Content-Type"); ct != "text/html; charset=utf-8" {
+ t.Errorf("Content-Type: %q; want text/html; charset=utf-8", ct)
+ }
+ if v := res.ContentLength; v != 10 {
+ t.Errorf("Content-Length: %d; want 10", v)
}
body, err := ioutil.ReadAll(res.Body)
if err != nil {
@@ -975,6 +1149,23 @@ func TestRedirectMunging(t *testing.T) {
}
}
+func TestRedirectBadPath(t *testing.T) {
+ // This used to crash. It's not valid input (bad path), but it
+ // shouldn't crash.
+ rr := httptest.NewRecorder()
+ req := &Request{
+ Method: "GET",
+ URL: &url.URL{
+ Scheme: "http",
+ Path: "not-empty-but-no-leading-slash", // bogus
+ },
+ }
+ Redirect(rr, req, "", 304)
+ if rr.Code != 304 {
+ t.Errorf("Code = %d; want 304", rr.Code)
+ }
+}
+
// TestZeroLengthPostAndResponse exercises an optimization done by the Transport:
// when there is no body (either because the method doesn't permit a body, or an
// explicit Content-Length of zero is present), then the transport can re-use the
@@ -1408,10 +1599,7 @@ For:
func TestCloseNotifierChanLeak(t *testing.T) {
defer afterTest(t)
- req := []byte(strings.Replace(`GET / HTTP/1.0
-Host: golang.org
-
-`, "\n", "\r\n", -1))
+ req := reqBytes("GET / HTTP/1.0\nHost: golang.org")
for i := 0; i < 20; i++ {
var output bytes.Buffer
conn := &rwTestConn{
@@ -1493,11 +1681,6 @@ func TestOptions(t *testing.T) {
// ones, even if the handler modifies them (~erroneously) after the
// first Write.
func TestHeaderToWire(t *testing.T) {
- req := []byte(strings.Replace(`GET / HTTP/1.1
-Host: golang.org
-
-`, "\n", "\r\n", -1))
-
tests := []struct {
name string
handler func(ResponseWriter, *Request)
@@ -1660,17 +1843,10 @@ Host: golang.org
},
}
for _, tc := range tests {
- var output bytes.Buffer
- conn := &rwTestConn{
- Reader: bytes.NewReader(req),
- Writer: &output,
- closec: make(chan bool, 1),
- }
- ln := &oneConnListener{conn: conn}
- go Serve(ln, HandlerFunc(tc.handler))
- <-conn.closec
- if err := tc.check(output.String()); err != nil {
- t.Errorf("%s: %v\nGot response:\n%s", tc.name, err, output.Bytes())
+ ht := newHandlerTest(HandlerFunc(tc.handler))
+ got := ht.rawResponse("GET / HTTP/1.1\nHost: golang.org")
+ if err := tc.check(got); err != nil {
+ t.Errorf("%s: %v\nGot response:\n%s", tc.name, err, got)
}
}
}
@@ -1726,7 +1902,200 @@ func TestAcceptMaxFds(t *testing.T) {
}
}
+func TestWriteAfterHijack(t *testing.T) {
+ req := reqBytes("GET / HTTP/1.1\nHost: golang.org")
+ var buf bytes.Buffer
+ wrotec := make(chan bool, 1)
+ conn := &rwTestConn{
+ Reader: bytes.NewReader(req),
+ Writer: &buf,
+ closec: make(chan bool, 1),
+ }
+ handler := HandlerFunc(func(rw ResponseWriter, r *Request) {
+ conn, bufrw, err := rw.(Hijacker).Hijack()
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ go func() {
+ bufrw.Write([]byte("[hijack-to-bufw]"))
+ bufrw.Flush()
+ conn.Write([]byte("[hijack-to-conn]"))
+ conn.Close()
+ wrotec <- true
+ }()
+ })
+ ln := &oneConnListener{conn: conn}
+ go Serve(ln, handler)
+ <-conn.closec
+ <-wrotec
+ if g, w := buf.String(), "[hijack-to-bufw][hijack-to-conn]"; g != w {
+ t.Errorf("wrote %q; want %q", g, w)
+ }
+}
+
+// http://code.google.com/p/go/issues/detail?id=5955
+// Note that this does not test the "request too large"
+// exit path from the http server. This is intentional;
+// not sending Connection: close is just a minor wire
+// optimization and is pointless if dealing with a
+// badly behaved client.
+func TestHTTP10ConnectionHeader(t *testing.T) {
+ defer afterTest(t)
+
+ mux := NewServeMux()
+ mux.Handle("/", HandlerFunc(func(resp ResponseWriter, req *Request) {}))
+ ts := httptest.NewServer(mux)
+ defer ts.Close()
+
+ // net/http uses HTTP/1.1 for requests, so write requests manually
+ tests := []struct {
+ req string // raw http request
+ expect []string // expected Connection header(s)
+ }{
+ {
+ req: "GET / HTTP/1.0\r\n\r\n",
+ expect: nil,
+ },
+ {
+ req: "OPTIONS * HTTP/1.0\r\n\r\n",
+ expect: nil,
+ },
+ {
+ req: "GET / HTTP/1.0\r\nConnection: keep-alive\r\n\r\n",
+ expect: []string{"keep-alive"},
+ },
+ }
+
+ for _, tt := range tests {
+ conn, err := net.Dial("tcp", ts.Listener.Addr().String())
+ if err != nil {
+ t.Fatal("dial err:", err)
+ }
+
+ _, err = fmt.Fprint(conn, tt.req)
+ if err != nil {
+ t.Fatal("conn write err:", err)
+ }
+
+ resp, err := ReadResponse(bufio.NewReader(conn), &Request{Method: "GET"})
+ if err != nil {
+ t.Fatal("ReadResponse err:", err)
+ }
+ conn.Close()
+ resp.Body.Close()
+
+ got := resp.Header["Connection"]
+ if !reflect.DeepEqual(got, tt.expect) {
+ t.Errorf("wrong Connection headers for request %q. Got %q expect %q", tt.req, got, tt.expect)
+ }
+ }
+}
+
+// See golang.org/issue/5660
+func TestServerReaderFromOrder(t *testing.T) {
+ defer afterTest(t)
+ pr, pw := io.Pipe()
+ const size = 3 << 20
+ ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {
+ rw.Header().Set("Content-Type", "text/plain") // prevent sniffing path
+ done := make(chan bool)
+ go func() {
+ io.Copy(rw, pr)
+ close(done)
+ }()
+ time.Sleep(25 * time.Millisecond) // give Copy a chance to break things
+ n, err := io.Copy(ioutil.Discard, req.Body)
+ if err != nil {
+ t.Errorf("handler Copy: %v", err)
+ return
+ }
+ if n != size {
+ t.Errorf("handler Copy = %d; want %d", n, size)
+ }
+ pw.Write([]byte("hi"))
+ pw.Close()
+ <-done
+ }))
+ defer ts.Close()
+
+ req, err := NewRequest("POST", ts.URL, io.LimitReader(neverEnding('a'), size))
+ if err != nil {
+ t.Fatal(err)
+ }
+ res, err := DefaultClient.Do(req)
+ if err != nil {
+ t.Fatal(err)
+ }
+ all, err := ioutil.ReadAll(res.Body)
+ if err != nil {
+ t.Fatal(err)
+ }
+ res.Body.Close()
+ if string(all) != "hi" {
+ t.Errorf("Body = %q; want hi", all)
+ }
+}
+
+// Issue 6157
+func TestNoContentTypeOnNotModified(t *testing.T) {
+ ht := newHandlerTest(HandlerFunc(func(w ResponseWriter, r *Request) {
+ if r.URL.Path == "/header" {
+ w.Header().Set("Content-Length", "123")
+ }
+ w.WriteHeader(StatusNotModified)
+ if r.URL.Path == "/more" {
+ w.Write([]byte("stuff"))
+ }
+ }))
+ for _, req := range []string{
+ "GET / HTTP/1.0",
+ "GET /header HTTP/1.0",
+ "GET /more HTTP/1.0",
+ "GET / HTTP/1.1",
+ "GET /header HTTP/1.1",
+ "GET /more HTTP/1.1",
+ } {
+ got := ht.rawResponse(req)
+ if !strings.Contains(got, "304 Not Modified") {
+ t.Errorf("Non-304 Not Modified for %q: %s", req, got)
+ } else if strings.Contains(got, "Content-Length") {
+ t.Errorf("Got a Content-Length from %q: %s", req, got)
+ }
+ }
+}
+
+func TestResponseWriterWriteStringAllocs(t *testing.T) {
+ t.Skip("allocs test unreliable with gccgo")
+ ht := newHandlerTest(HandlerFunc(func(w ResponseWriter, r *Request) {
+ if r.URL.Path == "/s" {
+ io.WriteString(w, "Hello world")
+ } else {
+ w.Write([]byte("Hello world"))
+ }
+ }))
+ before := testing.AllocsPerRun(25, func() { ht.rawResponse("GET / HTTP/1.0") })
+ after := testing.AllocsPerRun(25, func() { ht.rawResponse("GET /s HTTP/1.0") })
+ if int(after) >= int(before) {
+ t.Errorf("WriteString allocs of %v >= Write allocs of %v", after, before)
+ }
+}
+
+func TestAppendTime(t *testing.T) {
+ var b [len(TimeFormat)]byte
+ t1 := time.Date(2013, 9, 21, 15, 41, 0, 0, time.FixedZone("CEST", 2*60*60))
+ res := ExportAppendTime(b[:0], t1)
+ t2, err := ParseTime(string(res))
+ if err != nil {
+ t.Fatalf("Error parsing time: %s", err)
+ }
+ if !t1.Equal(t2) {
+ t.Fatalf("Times differ; expected: %v, got %v (%s)", t1, t2, string(res))
+ }
+}
+
func BenchmarkClientServer(b *testing.B) {
+ b.ReportAllocs()
b.StopTimer()
ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, r *Request) {
fmt.Fprintf(rw, "Hello world.\n")
@@ -1761,6 +2130,7 @@ func BenchmarkClientServerParallel64(b *testing.B) {
}
func benchmarkClientServerParallel(b *testing.B, conc int) {
+ b.ReportAllocs()
b.StopTimer()
ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, r *Request) {
fmt.Fprintf(rw, "Hello world.\n")
@@ -1805,6 +2175,7 @@ func benchmarkClientServerParallel(b *testing.B, conc int) {
// $ go tool pprof http.test http.prof
// (pprof) web
func BenchmarkServer(b *testing.B) {
+ b.ReportAllocs()
// Child process mode;
if url := os.Getenv("TEST_BENCH_SERVER_URL"); url != "" {
n, err := strconv.Atoi(os.Getenv("TEST_BENCH_CLIENT_N"))
@@ -1851,15 +2222,14 @@ func BenchmarkServer(b *testing.B) {
func BenchmarkServerFakeConnNoKeepAlive(b *testing.B) {
b.ReportAllocs()
- req := []byte(strings.Replace(`GET / HTTP/1.0
+ req := reqBytes(`GET / HTTP/1.0
Host: golang.org
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.52 Safari/537.17
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
-
-`, "\n", "\r\n", -1))
+`)
res := []byte("Hello world!\n")
conn := &testConn{
@@ -1905,15 +2275,14 @@ func (r *repeatReader) Read(p []byte) (n int, err error) {
func BenchmarkServerFakeConnWithKeepAlive(b *testing.B) {
b.ReportAllocs()
- req := []byte(strings.Replace(`GET / HTTP/1.1
+ req := reqBytes(`GET / HTTP/1.1
Host: golang.org
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.52 Safari/537.17
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
-
-`, "\n", "\r\n", -1))
+`)
res := []byte("Hello world!\n")
conn := &rwTestConn{
@@ -1940,10 +2309,9 @@ Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
func BenchmarkServerFakeConnWithKeepAliveLite(b *testing.B) {
b.ReportAllocs()
- req := []byte(strings.Replace(`GET / HTTP/1.1
+ req := reqBytes(`GET / HTTP/1.1
Host: golang.org
-
-`, "\n", "\r\n", -1))
+`)
res := []byte("Hello world!\n")
conn := &rwTestConn{
@@ -2003,10 +2371,9 @@ func BenchmarkServerHandlerNoHeader(b *testing.B) {
func benchmarkHandler(b *testing.B, h Handler) {
b.ReportAllocs()
- req := []byte(strings.Replace(`GET / HTTP/1.1
+ req := reqBytes(`GET / HTTP/1.1
Host: golang.org
-
-`, "\n", "\r\n", -1))
+`)
conn := &rwTestConn{
Reader: &repeatReader{content: req, count: b.N},
Writer: ioutil.Discard,
diff --git a/libgo/go/net/http/server.go b/libgo/go/net/http/server.go
index b2596070500..0e46863d5ae 100644
--- a/libgo/go/net/http/server.go
+++ b/libgo/go/net/http/server.go
@@ -16,6 +16,7 @@ import (
"log"
"net"
"net/url"
+ "os"
"path"
"runtime"
"strconv"
@@ -109,8 +110,6 @@ type conn struct {
sr liveSwitchReader // where the LimitReader reads from; usually the rwc
lr *io.LimitedReader // io.LimitReader(sr)
buf *bufio.ReadWriter // buffered(lr,rwc), reading from bufio->limitReader->sr->rwc
- bufswr *switchReader // the *switchReader io.Reader source of buf
- bufsww *switchWriter // the *switchWriter io.Writer dest of buf
tlsState *tls.ConnectionState // or nil when not using TLS
mu sync.Mutex // guards the following
@@ -246,6 +245,10 @@ func (cw *chunkWriter) Write(p []byte) (n int, err error) {
if !cw.wroteHeader {
cw.writeHeader(p)
}
+ if cw.res.req.Method == "HEAD" {
+ // Eat writes.
+ return len(p), nil
+ }
if cw.chunking {
_, err = fmt.Fprintf(cw.res.conn.buf, "%x\r\n", len(p))
if err != nil {
@@ -278,7 +281,7 @@ func (cw *chunkWriter) close() {
// zero EOF chunk, trailer key/value pairs (currently
// unsupported in Go's server), followed by a blank
// line.
- io.WriteString(cw.res.conn.buf, "0\r\n\r\n")
+ cw.res.conn.buf.WriteString("0\r\n\r\n")
}
}
@@ -320,6 +323,10 @@ type response struct {
requestBodyLimitHit bool
handlerDone bool // set true when the handler exits
+
+ // Buffers for Date and Content-Length
+ dateBuf [len(TimeFormat)]byte
+ clenBuf [10]byte
}
// requestTooLarge is called by maxBytesReader when too much input has
@@ -332,16 +339,50 @@ func (w *response) requestTooLarge() {
}
}
-// needsSniff returns whether a Content-Type still needs to be sniffed.
+// needsSniff reports whether a Content-Type still needs to be sniffed.
func (w *response) needsSniff() bool {
- return !w.cw.wroteHeader && w.handlerHeader.Get("Content-Type") == "" && w.written < sniffLen
+ _, haveType := w.handlerHeader["Content-Type"]
+ return !w.cw.wroteHeader && !haveType && w.written < sniffLen
}
+// writerOnly hides an io.Writer value's optional ReadFrom method
+// from io.Copy.
type writerOnly struct {
io.Writer
}
+func srcIsRegularFile(src io.Reader) (isRegular bool, err error) {
+ switch v := src.(type) {
+ case *os.File:
+ fi, err := v.Stat()
+ if err != nil {
+ return false, err
+ }
+ return fi.Mode().IsRegular(), nil
+ case *io.LimitedReader:
+ return srcIsRegularFile(v.R)
+ default:
+ return
+ }
+}
+
+// ReadFrom is here to optimize copying from an *os.File regular file
+// to a *net.TCPConn with sendfile.
func (w *response) ReadFrom(src io.Reader) (n int64, err error) {
+ // Our underlying w.conn.rwc is usually a *TCPConn (with its
+ // own ReadFrom method). If not, or if our src isn't a regular
+ // file, just fall back to the normal copy method.
+ rf, ok := w.conn.rwc.(io.ReaderFrom)
+ regFile, err := srcIsRegularFile(src)
+ if err != nil {
+ return 0, err
+ }
+ if !ok || !regFile {
+ return io.Copy(writerOnly{w}, src)
+ }
+
+ // sendfile path:
+
if !w.wroteHeader {
w.WriteHeader(StatusOK)
}
@@ -359,16 +400,12 @@ func (w *response) ReadFrom(src io.Reader) (n int64, err error) {
// Now that cw has been flushed, its chunking field is guaranteed initialized.
if !w.cw.chunking && w.bodyAllowed() {
- if rf, ok := w.conn.rwc.(io.ReaderFrom); ok {
- n0, err := rf.ReadFrom(src)
- n += n0
- w.written += n0
- return n, err
- }
+ n0, err := rf.ReadFrom(src)
+ n += n0
+ w.written += n0
+ return n, err
}
- // Fall back to default io.Copy implementation.
- // Use wrapper to hide w.ReadFrom from io.Copy.
n0, err := io.Copy(writerOnly{w}, src)
n += n0
return n, err
@@ -392,34 +429,20 @@ func (srv *Server) newConn(rwc net.Conn) (c *conn, err error) {
}
c.sr = liveSwitchReader{r: c.rwc}
c.lr = io.LimitReader(&c.sr, noLimit).(*io.LimitedReader)
- br, sr := newBufioReader(c.lr)
- bw, sw := newBufioWriterSize(c.rwc, 4<<10)
+ br := newBufioReader(c.lr)
+ bw := newBufioWriterSize(c.rwc, 4<<10)
c.buf = bufio.NewReadWriter(br, bw)
- c.bufswr = sr
- c.bufsww = sw
return c, nil
}
-// TODO: remove this, if issue 5100 is fixed
-type bufioReaderPair struct {
- br *bufio.Reader
- sr *switchReader // from which the bufio.Reader is reading
-}
-
-// TODO: remove this, if issue 5100 is fixed
-type bufioWriterPair struct {
- bw *bufio.Writer
- sw *switchWriter // to which the bufio.Writer is writing
-}
-
// TODO: use a sync.Cache instead
var (
- bufioReaderCache = make(chan bufioReaderPair, 4)
- bufioWriterCache2k = make(chan bufioWriterPair, 4)
- bufioWriterCache4k = make(chan bufioWriterPair, 4)
+ bufioReaderCache = make(chan *bufio.Reader, 4)
+ bufioWriterCache2k = make(chan *bufio.Writer, 4)
+ bufioWriterCache4k = make(chan *bufio.Writer, 4)
)
-func bufioWriterCache(size int) chan bufioWriterPair {
+func bufioWriterCache(size int) chan *bufio.Writer {
switch size {
case 2 << 10:
return bufioWriterCache2k
@@ -429,55 +452,38 @@ func bufioWriterCache(size int) chan bufioWriterPair {
return nil
}
-func newBufioReader(r io.Reader) (*bufio.Reader, *switchReader) {
+func newBufioReader(r io.Reader) *bufio.Reader {
select {
case p := <-bufioReaderCache:
- p.sr.Reader = r
- return p.br, p.sr
+ p.Reset(r)
+ return p
default:
- sr := &switchReader{r}
- return bufio.NewReader(sr), sr
+ return bufio.NewReader(r)
}
}
-func putBufioReader(br *bufio.Reader, sr *switchReader) {
- if n := br.Buffered(); n > 0 {
- io.CopyN(ioutil.Discard, br, int64(n))
- }
- br.Read(nil) // clears br.err
- sr.Reader = nil
+func putBufioReader(br *bufio.Reader) {
+ br.Reset(nil)
select {
- case bufioReaderCache <- bufioReaderPair{br, sr}:
+ case bufioReaderCache <- br:
default:
}
}
-func newBufioWriterSize(w io.Writer, size int) (*bufio.Writer, *switchWriter) {
+func newBufioWriterSize(w io.Writer, size int) *bufio.Writer {
select {
case p := <-bufioWriterCache(size):
- p.sw.Writer = w
- return p.bw, p.sw
+ p.Reset(w)
+ return p
default:
- sw := &switchWriter{w}
- return bufio.NewWriterSize(sw, size), sw
+ return bufio.NewWriterSize(w, size)
}
}
-func putBufioWriter(bw *bufio.Writer, sw *switchWriter) {
- if bw.Buffered() > 0 {
- // It must have failed to flush to its target
- // earlier. We can't reuse this bufio.Writer.
- return
- }
- if err := bw.Flush(); err != nil {
- // Its sticky error field is set, which is returned by
- // Flush even when there's no data buffered. This
- // bufio Writer is dead to us. Don't reuse it.
- return
- }
- sw.Writer = nil
+func putBufioWriter(bw *bufio.Writer) {
+ bw.Reset(nil)
select {
- case bufioWriterCache(bw.Available()) <- bufioWriterPair{bw, sw}:
+ case bufioWriterCache(bw.Available()) <- bw:
default:
}
}
@@ -508,7 +514,7 @@ func (ecr *expectContinueReader) Read(p []byte) (n int, err error) {
}
if !ecr.resp.wroteContinue && !ecr.resp.conn.hijacked() {
ecr.resp.wroteContinue = true
- io.WriteString(ecr.resp.conn.buf, "HTTP/1.1 100 Continue\r\n\r\n")
+ ecr.resp.conn.buf.WriteString("HTTP/1.1 100 Continue\r\n\r\n")
ecr.resp.conn.buf.Flush()
}
return ecr.readCloser.Read(p)
@@ -525,6 +531,28 @@ func (ecr *expectContinueReader) Close() error {
// It is like time.RFC1123 but hard codes GMT as the time zone.
const TimeFormat = "Mon, 02 Jan 2006 15:04:05 GMT"
+// appendTime is a non-allocating version of []byte(t.UTC().Format(TimeFormat))
+func appendTime(b []byte, t time.Time) []byte {
+ const days = "SunMonTueWedThuFriSat"
+ const months = "JanFebMarAprMayJunJulAugSepOctNovDec"
+
+ t = t.UTC()
+ yy, mm, dd := t.Date()
+ hh, mn, ss := t.Clock()
+ day := days[3*t.Weekday():]
+ mon := months[3*(mm-1):]
+
+ return append(b,
+ day[0], day[1], day[2], ',', ' ',
+ byte('0'+dd/10), byte('0'+dd%10), ' ',
+ mon[0], mon[1], mon[2], ' ',
+ byte('0'+yy/1000), byte('0'+(yy/100)%10), byte('0'+(yy/10)%10), byte('0'+yy%10), ' ',
+ byte('0'+hh/10), byte('0'+hh%10), ':',
+ byte('0'+mn/10), byte('0'+mn%10), ':',
+ byte('0'+ss/10), byte('0'+ss%10), ' ',
+ 'G', 'M', 'T')
+}
+
var errTooLarge = errors.New("http: request too large")
// Read next request from connection.
@@ -562,7 +590,7 @@ func (c *conn) readRequest() (w *response, err error) {
contentLength: -1,
}
w.cw.res = w
- w.w, w.sw = newBufioWriterSize(&w.cw, bufferBeforeChunkingSize)
+ w.w = newBufioWriterSize(&w.cw, bufferBeforeChunkingSize)
return w, nil
}
@@ -620,27 +648,45 @@ func (w *response) WriteHeader(code int) {
// the response Header map and all its 1-element slices.
type extraHeader struct {
contentType string
- contentLength string
connection string
- date string
transferEncoding string
+ date []byte // written if not nil
+ contentLength []byte // written if not nil
}
// Sorted the same as extraHeader.Write's loop.
var extraHeaderKeys = [][]byte{
- []byte("Content-Type"), []byte("Content-Length"),
- []byte("Connection"), []byte("Date"), []byte("Transfer-Encoding"),
+ []byte("Content-Type"),
+ []byte("Connection"),
+ []byte("Transfer-Encoding"),
}
-// The value receiver, despite copying 5 strings to the stack,
-// prevents an extra allocation. The escape analysis isn't smart
-// enough to realize this doesn't mutate h.
-func (h extraHeader) Write(w io.Writer) {
- for i, v := range []string{h.contentType, h.contentLength, h.connection, h.date, h.transferEncoding} {
+var (
+ headerContentLength = []byte("Content-Length: ")
+ headerDate = []byte("Date: ")
+)
+
+// Write writes the headers described in h to w.
+//
+// This method has a value receiver, despite the somewhat large size
+// of h, because it prevents an allocation. The escape analysis isn't
+// smart enough to realize this function doesn't mutate h.
+func (h extraHeader) Write(w *bufio.Writer) {
+ if h.date != nil {
+ w.Write(headerDate)
+ w.Write(h.date)
+ w.Write(crlf)
+ }
+ if h.contentLength != nil {
+ w.Write(headerContentLength)
+ w.Write(h.contentLength)
+ w.Write(crlf)
+ }
+ for i, v := range []string{h.contentType, h.connection, h.transferEncoding} {
if v != "" {
w.Write(extraHeaderKeys[i])
w.Write(colonSpace)
- io.WriteString(w, v)
+ w.WriteString(v)
w.Write(crlf)
}
}
@@ -661,6 +707,7 @@ func (cw *chunkWriter) writeHeader(p []byte) {
cw.wroteHeader = true
w := cw.res
+ isHEAD := w.req.Method == "HEAD"
// header is written out to w.conn.buf below. Depending on the
// state of the handler, we either own the map or not. If we
@@ -692,9 +739,17 @@ func (cw *chunkWriter) writeHeader(p []byte) {
// response header and this is our first (and last) write, set
// it, even to zero. This helps HTTP/1.0 clients keep their
// "keep-alive" connections alive.
- if w.handlerDone && header.get("Content-Length") == "" && w.req.Method != "HEAD" {
+ // Exceptions: 304 responses never get Content-Length, and if
+ // it was a HEAD request, we don't know the difference between
+ // 0 actual bytes and 0 bytes because the handler noticed it
+ // was a HEAD request and chose not to write anything. So for
+ // HEAD, the handler should either write the Content-Length or
+ // write non-zero bytes. If it's actually 0 bytes and the
+ // handler never looked at the Request.Method, we just don't
+ // send a Content-Length header.
+ if w.handlerDone && w.status != StatusNotModified && header.get("Content-Length") == "" && (!isHEAD || len(p) > 0) {
w.contentLength = int64(len(p))
- setHeader.contentLength = strconv.Itoa(len(p))
+ setHeader.contentLength = strconv.AppendInt(cw.res.clenBuf[:0], int64(len(p)), 10)
}
// If this was an HTTP/1.0 request with keep-alive and we sent a
@@ -709,7 +764,7 @@ func (cw *chunkWriter) writeHeader(p []byte) {
// Check for a explicit (and valid) Content-Length header.
hasCL := w.contentLength != -1
- if w.req.wantsHttp10KeepAlive() && (w.req.Method == "HEAD" || hasCL) {
+ if w.req.wantsHttp10KeepAlive() && (isHEAD || hasCL) {
_, connectionHeaderSet := header["Connection"]
if !connectionHeaderSet {
setHeader.connection = "keep-alive"
@@ -749,13 +804,14 @@ func (cw *chunkWriter) writeHeader(p []byte) {
}
} else {
// If no content type, apply sniffing algorithm to body.
- if header.get("Content-Type") == "" && w.req.Method != "HEAD" {
+ _, haveType := header["Content-Type"]
+ if !haveType {
setHeader.contentType = DetectContentType(p)
}
}
if _, ok := header["Date"]; !ok {
- setHeader.date = time.Now().UTC().Format(TimeFormat)
+ setHeader.date = appendTime(cw.res.dateBuf[:0], time.Now())
}
te := header.get("Transfer-Encoding")
@@ -801,12 +857,14 @@ func (cw *chunkWriter) writeHeader(p []byte) {
if w.closeAfterReply && !hasToken(cw.header.get("Connection"), "close") {
delHeader("Connection")
- setHeader.connection = "close"
+ if w.req.ProtoAtLeast(1, 1) {
+ setHeader.connection = "close"
+ }
}
- io.WriteString(w.conn.buf, statusLine(w.req, code))
+ w.conn.buf.WriteString(statusLine(w.req, code))
cw.header.WriteSubset(w.conn.buf, excludeHeader)
- setHeader.Write(w.conn.buf)
+ setHeader.Write(w.conn.buf.Writer)
w.conn.buf.Write(crlf)
}
@@ -861,7 +919,7 @@ func (w *response) bodyAllowed() bool {
if !w.wroteHeader {
panic("")
}
- return w.status != StatusNotModified && w.req.Method != "HEAD"
+ return w.status != StatusNotModified
}
// The Life Of A Write is like this:
@@ -897,6 +955,15 @@ func (w *response) bodyAllowed() bool {
// bufferBeforeChunkingSize smaller and having bufio's fast-paths deal
// with this instead.
func (w *response) Write(data []byte) (n int, err error) {
+ return w.write(len(data), data, "")
+}
+
+func (w *response) WriteString(data string) (n int, err error) {
+ return w.write(len(data), nil, data)
+}
+
+// either dataB or dataS is non-zero.
+func (w *response) write(lenData int, dataB []byte, dataS string) (n int, err error) {
if w.conn.hijacked() {
log.Print("http: response.Write on hijacked connection")
return 0, ErrHijacked
@@ -904,18 +971,22 @@ func (w *response) Write(data []byte) (n int, err error) {
if !w.wroteHeader {
w.WriteHeader(StatusOK)
}
- if len(data) == 0 {
+ if lenData == 0 {
return 0, nil
}
if !w.bodyAllowed() {
return 0, ErrBodyNotAllowed
}
- w.written += int64(len(data)) // ignoring errors, for errorKludge
+ w.written += int64(lenData) // ignoring errors, for errorKludge
if w.contentLength != -1 && w.written > w.contentLength {
return 0, ErrContentLength
}
- return w.w.Write(data)
+ if dataB != nil {
+ return w.w.Write(dataB)
+ } else {
+ return w.w.WriteString(dataS)
+ }
}
func (w *response) finishRequest() {
@@ -926,7 +997,7 @@ func (w *response) finishRequest() {
}
w.w.Flush()
- putBufioWriter(w.w, w.sw)
+ putBufioWriter(w.w)
w.cw.close()
w.conn.buf.Flush()
@@ -939,7 +1010,7 @@ func (w *response) finishRequest() {
w.req.MultipartForm.RemoveAll()
}
- if w.contentLength != -1 && w.bodyAllowed() && w.contentLength != w.written {
+ if w.req.Method != "HEAD" && w.contentLength != -1 && w.bodyAllowed() && w.contentLength != w.written {
// Did not write enough. Avoid getting out of sync.
w.closeAfterReply = true
}
@@ -959,11 +1030,11 @@ func (c *conn) finalFlush() {
// Steal the bufio.Reader (~4KB worth of memory) and its associated
// reader for a future connection.
- putBufioReader(c.buf.Reader, c.bufswr)
+ putBufioReader(c.buf.Reader)
// Steal the bufio.Writer (~4KB worth of memory) and its associated
// writer for a future connection.
- putBufioWriter(c.buf.Writer, c.bufsww)
+ putBufioWriter(c.buf.Writer)
c.buf = nil
}
@@ -1001,7 +1072,7 @@ func (c *conn) closeWriteAndWait() {
time.Sleep(rstAvoidanceDelay)
}
-// validNPN returns whether the proto is not a blacklisted Next
+// validNPN reports whether the proto is not a blacklisted Next
// Protocol Negotiation protocol. Empty and built-in protocol types
// are blacklisted and can't be overridden with alternate
// implementations.
@@ -1152,6 +1223,7 @@ func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
// Helper handlers
// Error replies to the request with the specified error message and HTTP code.
+// The error message should be plain text.
func Error(w ResponseWriter, error string, code int) {
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
w.WriteHeader(code)
@@ -1288,6 +1360,10 @@ func RedirectHandler(url string, code int) Handler {
// former will receive requests for any other paths in the
// "/images/" subtree.
//
+// Note that since a pattern ending in a slash names a rooted subtree,
+// the pattern "/" matches all paths not matched by other registered
+// patterns, not just the URL with Path == "/".
+//
// Patterns may optionally begin with a host name, restricting matches to
// URLs on that host only. Host-specific patterns take precedence over
// general patterns, so that a handler might register for the two patterns
@@ -1378,7 +1454,9 @@ func (mux *ServeMux) Handler(r *Request) (h Handler, pattern string) {
if r.Method != "CONNECT" {
if p := cleanPath(r.URL.Path); p != r.URL.Path {
_, pattern = mux.handler(r.Host, p)
- return RedirectHandler(p, StatusMovedPermanently), pattern
+ url := *r.URL
+ url.Path = p
+ return RedirectHandler(url.String(), StatusMovedPermanently), pattern
}
}
@@ -1408,7 +1486,9 @@ func (mux *ServeMux) handler(host, path string) (h Handler, pattern string) {
// pattern most closely matches the request URL.
func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) {
if r.RequestURI == "*" {
- w.Header().Set("Connection", "close")
+ if r.ProtoAtLeast(1, 1) {
+ w.Header().Set("Connection", "close")
+ }
w.WriteHeader(StatusBadRequest)
return
}
@@ -1771,7 +1851,15 @@ func (globalOptionsHandler) ServeHTTP(w ResponseWriter, r *Request) {
}
// eofReader is a non-nil io.ReadCloser that always returns EOF.
-var eofReader = ioutil.NopCloser(strings.NewReader(""))
+// It embeds a *strings.Reader so it still has a WriteTo method
+// and io.Copy won't need a buffer.
+var eofReader = &struct {
+ *strings.Reader
+ io.Closer
+}{
+ strings.NewReader(""),
+ ioutil.NopCloser(nil),
+}
// initNPNRequest is an HTTP handler that initializes certain
// uninitialized fields in its *Request. Such partially-initialized
diff --git a/libgo/go/net/http/server_test.go b/libgo/go/net/http/server_test.go
deleted file mode 100644
index e8b69f76cce..00000000000
--- a/libgo/go/net/http/server_test.go
+++ /dev/null
@@ -1,104 +0,0 @@
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package http_test
-
-import (
- . "net/http"
- "net/http/httptest"
- "net/url"
- "testing"
-)
-
-var serveMuxRegister = []struct {
- pattern string
- h Handler
-}{
- {"/dir/", serve(200)},
- {"/search", serve(201)},
- {"codesearch.google.com/search", serve(202)},
- {"codesearch.google.com/", serve(203)},
-}
-
-// serve returns a handler that sends a response with the given code.
-func serve(code int) HandlerFunc {
- return func(w ResponseWriter, r *Request) {
- w.WriteHeader(code)
- }
-}
-
-var serveMuxTests = []struct {
- method string
- host string
- path string
- code int
- pattern string
-}{
- {"GET", "google.com", "/", 404, ""},
- {"GET", "google.com", "/dir", 301, "/dir/"},
- {"GET", "google.com", "/dir/", 200, "/dir/"},
- {"GET", "google.com", "/dir/file", 200, "/dir/"},
- {"GET", "google.com", "/search", 201, "/search"},
- {"GET", "google.com", "/search/", 404, ""},
- {"GET", "google.com", "/search/foo", 404, ""},
- {"GET", "codesearch.google.com", "/search", 202, "codesearch.google.com/search"},
- {"GET", "codesearch.google.com", "/search/", 203, "codesearch.google.com/"},
- {"GET", "codesearch.google.com", "/search/foo", 203, "codesearch.google.com/"},
- {"GET", "codesearch.google.com", "/", 203, "codesearch.google.com/"},
- {"GET", "images.google.com", "/search", 201, "/search"},
- {"GET", "images.google.com", "/search/", 404, ""},
- {"GET", "images.google.com", "/search/foo", 404, ""},
- {"GET", "google.com", "/../search", 301, "/search"},
- {"GET", "google.com", "/dir/..", 301, ""},
- {"GET", "google.com", "/dir/..", 301, ""},
- {"GET", "google.com", "/dir/./file", 301, "/dir/"},
-
- // The /foo -> /foo/ redirect applies to CONNECT requests
- // but the path canonicalization does not.
- {"CONNECT", "google.com", "/dir", 301, "/dir/"},
- {"CONNECT", "google.com", "/../search", 404, ""},
- {"CONNECT", "google.com", "/dir/..", 200, "/dir/"},
- {"CONNECT", "google.com", "/dir/..", 200, "/dir/"},
- {"CONNECT", "google.com", "/dir/./file", 200, "/dir/"},
-}
-
-func TestServeMuxHandler(t *testing.T) {
- mux := NewServeMux()
- for _, e := range serveMuxRegister {
- mux.Handle(e.pattern, e.h)
- }
-
- for _, tt := range serveMuxTests {
- r := &Request{
- Method: tt.method,
- Host: tt.host,
- URL: &url.URL{
- Path: tt.path,
- },
- }
- h, pattern := mux.Handler(r)
- rr := httptest.NewRecorder()
- h.ServeHTTP(rr, r)
- if pattern != tt.pattern || rr.Code != tt.code {
- t.Errorf("%s %s %s = %d, %q, want %d, %q", tt.method, tt.host, tt.path, rr.Code, pattern, tt.code, tt.pattern)
- }
- }
-}
-
-func TestServerRedirect(t *testing.T) {
- // This used to crash. It's not valid input (bad path), but it
- // shouldn't crash.
- rr := httptest.NewRecorder()
- req := &Request{
- Method: "GET",
- URL: &url.URL{
- Scheme: "http",
- Path: "not-empty-but-no-leading-slash", // bogus
- },
- }
- Redirect(rr, req, "", 304)
- if rr.Code != 304 {
- t.Errorf("Code = %d; want 304", rr.Code)
- }
-}
diff --git a/libgo/go/net/http/sniff_test.go b/libgo/go/net/http/sniff_test.go
index 106d94ec1cb..24ca27afc16 100644
--- a/libgo/go/net/http/sniff_test.go
+++ b/libgo/go/net/http/sniff_test.go
@@ -12,6 +12,7 @@ import (
"log"
. "net/http"
"net/http/httptest"
+ "reflect"
"strconv"
"strings"
"testing"
@@ -84,6 +85,29 @@ func TestServerContentType(t *testing.T) {
}
}
+// Issue 5953: shouldn't sniff if the handler set a Content-Type header,
+// even if it's the empty string.
+func TestServerIssue5953(t *testing.T) {
+ defer afterTest(t)
+ ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+ w.Header()["Content-Type"] = []string{""}
+ fmt.Fprintf(w, "<html><head></head><body>hi</body></html>")
+ }))
+ defer ts.Close()
+
+ resp, err := Get(ts.URL)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ got := resp.Header["Content-Type"]
+ want := []string{""}
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("Content-Type = %q; want %q", got, want)
+ }
+ resp.Body.Close()
+}
+
func TestContentTypeWithCopy(t *testing.T) {
defer afterTest(t)
diff --git a/libgo/go/net/http/transfer.go b/libgo/go/net/http/transfer.go
index 53569bcc2fc..bacd83732de 100644
--- a/libgo/go/net/http/transfer.go
+++ b/libgo/go/net/http/transfer.go
@@ -238,7 +238,7 @@ type transferReader struct {
Trailer Header
}
-// bodyAllowedForStatus returns whether a given response status code
+// bodyAllowedForStatus reports whether a given response status code
// permits a body. See RFC2616, section 4.4.
func bodyAllowedForStatus(status int) bool {
switch {
@@ -254,7 +254,7 @@ func bodyAllowedForStatus(status int) bool {
// msg is *Request or *Response.
func readTransfer(msg interface{}, r *bufio.Reader) (err error) {
- t := &transferReader{}
+ t := &transferReader{RequestMethod: "GET"}
// Unify input
isResponse := false
@@ -262,11 +262,13 @@ func readTransfer(msg interface{}, r *bufio.Reader) (err error) {
case *Response:
t.Header = rr.Header
t.StatusCode = rr.StatusCode
- t.RequestMethod = rr.Request.Method
t.ProtoMajor = rr.ProtoMajor
t.ProtoMinor = rr.ProtoMinor
t.Close = shouldClose(t.ProtoMajor, t.ProtoMinor, t.Header)
isResponse = true
+ if rr.Request != nil {
+ t.RequestMethod = rr.Request.Method
+ }
case *Request:
t.Header = rr.Header
t.ProtoMajor = rr.ProtoMajor
@@ -274,7 +276,6 @@ func readTransfer(msg interface{}, r *bufio.Reader) (err error) {
// Transfer semantics for Requests are exactly like those for
// Responses with status code 200, responding to a GET method
t.StatusCode = 200
- t.RequestMethod = "GET"
default:
panic("unexpected type")
}
@@ -328,12 +329,12 @@ func readTransfer(msg interface{}, r *bufio.Reader) (err error) {
switch {
case chunked(t.TransferEncoding):
if noBodyExpected(t.RequestMethod) {
- t.Body = &body{Reader: eofReader, closing: t.Close}
+ t.Body = eofReader
} else {
t.Body = &body{Reader: newChunkedReader(r), hdr: msg, r: r, closing: t.Close}
}
case realLength == 0:
- t.Body = &body{Reader: eofReader, closing: t.Close}
+ t.Body = eofReader
case realLength > 0:
t.Body = &body{Reader: io.LimitReader(r, realLength), closing: t.Close}
default:
@@ -343,7 +344,7 @@ func readTransfer(msg interface{}, r *bufio.Reader) (err error) {
t.Body = &body{Reader: r, closing: t.Close}
} else {
// Persistent connection (i.e. HTTP/1.1)
- t.Body = &body{Reader: eofReader, closing: t.Close}
+ t.Body = eofReader
}
}
@@ -518,8 +519,6 @@ type body struct {
r *bufio.Reader // underlying wire-format reader for the trailer
closing bool // is the connection to be closed after reading body?
closed bool
-
- res *response // response writer for server requests, else nil
}
// ErrBodyReadAfterClose is returned when reading a Request or Response
@@ -534,13 +533,22 @@ func (b *body) Read(p []byte) (n int, err error) {
}
n, err = b.Reader.Read(p)
- // Read the final trailer once we hit EOF.
- if err == io.EOF && b.hdr != nil {
- if e := b.readTrailer(); e != nil {
- err = e
+ if err == io.EOF {
+ // Chunked case. Read the trailer.
+ if b.hdr != nil {
+ if e := b.readTrailer(); e != nil {
+ err = e
+ }
+ b.hdr = nil
+ } else {
+ // If the server declared the Content-Length, our body is a LimitedReader
+ // and we need to check whether this EOF arrived early.
+ if lr, ok := b.Reader.(*io.LimitedReader); ok && lr.N > 0 {
+ err = io.ErrUnexpectedEOF
+ }
}
- b.hdr = nil
}
+
return n, err
}
@@ -618,14 +626,6 @@ func (b *body) Close() error {
case b.hdr == nil && b.closing:
// no trailer and closing the connection next.
// no point in reading to EOF.
- case b.res != nil && b.res.requestBodyLimitHit:
- // In a server request, don't continue reading from the client
- // if we've already hit the maximum body size set by the
- // handler. If this is set, that also means the TCP connection
- // is about to be closed, so getting to the next HTTP request
- // in the stream is not necessary.
- case b.Reader == eofReader:
- // Nothing to read. No need to io.Copy from it.
default:
// Fully consume the body, which will also lead to us reading
// the trailer headers after the body, if present.
diff --git a/libgo/go/net/http/transport.go b/libgo/go/net/http/transport.go
index 4cd0533ffc2..f6871afacd7 100644
--- a/libgo/go/net/http/transport.go
+++ b/libgo/go/net/http/transport.go
@@ -13,7 +13,6 @@ import (
"bufio"
"compress/gzip"
"crypto/tls"
- "encoding/base64"
"errors"
"fmt"
"io"
@@ -109,9 +108,11 @@ func ProxyFromEnvironment(req *Request) (*url.URL, error) {
}
proxyURL, err := url.Parse(proxy)
if err != nil || !strings.HasPrefix(proxyURL.Scheme, "http") {
- if u, err := url.Parse("http://" + proxy); err == nil {
- proxyURL = u
- err = nil
+ // proxy was bogus. Try prepending "http://" to it and
+ // see if that parses correctly. If not, we fall
+ // through and complain about the original one.
+ if proxyURL, err := url.Parse("http://" + proxy); err == nil {
+ return proxyURL, nil
}
}
if err != nil {
@@ -215,6 +216,7 @@ func (t *Transport) CloseIdleConnections() {
t.idleMu.Lock()
m := t.idleConn
t.idleConn = nil
+ t.idleConnCh = nil
t.idleMu.Unlock()
if m == nil {
return
@@ -270,7 +272,9 @@ func (cm *connectMethod) proxyAuth() string {
return ""
}
if u := cm.proxyURL.User; u != nil {
- return "Basic " + base64.URLEncoding.EncodeToString([]byte(u.String()))
+ username := u.Username()
+ password, _ := u.Password()
+ return "Basic " + basicAuth(username, password)
}
return ""
}
@@ -293,8 +297,10 @@ func (t *Transport) putIdleConn(pconn *persistConn) bool {
max = DefaultMaxIdleConnsPerHost
}
t.idleMu.Lock()
+
+ waitingDialer := t.idleConnCh[key]
select {
- case t.idleConnCh[key] <- pconn:
+ case waitingDialer <- pconn:
// We're done with this pconn and somebody else is
// currently waiting for a conn of this type (they're
// actively dialing, but this conn is ready
@@ -303,6 +309,11 @@ func (t *Transport) putIdleConn(pconn *persistConn) bool {
t.idleMu.Unlock()
return true
default:
+ if waitingDialer != nil {
+ // They had populated this, but their dial won
+ // first, so we can clean up this map entry.
+ delete(t.idleConnCh, key)
+ }
}
if t.idleConn == nil {
t.idleConn = make(map[string][]*persistConn)
@@ -322,7 +333,13 @@ func (t *Transport) putIdleConn(pconn *persistConn) bool {
return true
}
+// getIdleConnCh returns a channel to receive and return idle
+// persistent connection for the given connectMethod.
+// It may return nil, if persistent connections are not being used.
func (t *Transport) getIdleConnCh(cm *connectMethod) chan *persistConn {
+ if t.DisableKeepAlives {
+ return nil
+ }
key := cm.key()
t.idleMu.Lock()
defer t.idleMu.Unlock()
@@ -498,8 +515,8 @@ func (t *Transport) dialConn(cm *connectMethod) (*persistConn, error) {
if err = conn.(*tls.Conn).Handshake(); err != nil {
return nil, err
}
- if t.TLSClientConfig == nil || !t.TLSClientConfig.InsecureSkipVerify {
- if err = conn.(*tls.Conn).VerifyHostname(cm.tlsHost()); err != nil {
+ if !cfg.InsecureSkipVerify {
+ if err = conn.(*tls.Conn).VerifyHostname(cfg.ServerName); err != nil {
return nil, err
}
}
@@ -831,10 +848,15 @@ func (pc *persistConn) roundTrip(req *transportRequest) (resp *Response, err err
// uncompress the gzip stream if we were the layer that
// requested it.
requestedGzip := false
- if !pc.t.DisableCompression && req.Header.Get("Accept-Encoding") == "" {
+ if !pc.t.DisableCompression && req.Header.Get("Accept-Encoding") == "" && req.Method != "HEAD" {
// Request gzip only, not deflate. Deflate is ambiguous and
// not as universally supported anyway.
// See: http://www.gzip.org/zlib/zlib_faq.html#faq38
+ //
+ // Note that we don't request this for HEAD requests,
+ // due to a bug in nginx:
+ // http://trac.nginx.org/nginx/ticket/358
+ // http://golang.org/issue/5522
requestedGzip = true
req.extraHeaders().Set("Accept-Encoding", "gzip")
}
diff --git a/libgo/go/net/http/transport_test.go b/libgo/go/net/http/transport_test.go
index 9f64a6e4b5f..e4df30a98de 100644
--- a/libgo/go/net/http/transport_test.go
+++ b/libgo/go/net/http/transport_test.go
@@ -15,6 +15,7 @@ import (
"io"
"io/ioutil"
"net"
+ "net/http"
. "net/http"
"net/http/httptest"
"net/url"
@@ -469,6 +470,7 @@ func TestTransportHeadResponses(t *testing.T) {
res, err := c.Head(ts.URL)
if err != nil {
t.Errorf("error on loop %d: %v", i, err)
+ continue
}
if e, g := "123", res.Header.Get("Content-Length"); e != g {
t.Errorf("loop %d: expected Content-Length header of %q, got %q", i, e, g)
@@ -476,6 +478,11 @@ func TestTransportHeadResponses(t *testing.T) {
if e, g := int64(123), res.ContentLength; e != g {
t.Errorf("loop %d: expected res.ContentLength of %v, got %v", i, e, g)
}
+ if all, err := ioutil.ReadAll(res.Body); err != nil {
+ t.Errorf("loop %d: Body ReadAll: %v", i, err)
+ } else if len(all) != 0 {
+ t.Errorf("Bogus body %q", all)
+ }
}
}
@@ -553,12 +560,13 @@ func TestRoundTripGzip(t *testing.T) {
res, err := DefaultTransport.RoundTrip(req)
var body []byte
if test.compressed {
- gzip, err := gzip.NewReader(res.Body)
+ var r *gzip.Reader
+ r, err = gzip.NewReader(res.Body)
if err != nil {
t.Errorf("%d. gzip NewReader: %v", i, err)
continue
}
- body, err = ioutil.ReadAll(gzip)
+ body, err = ioutil.ReadAll(r)
res.Body.Close()
} else {
body, err = ioutil.ReadAll(res.Body)
@@ -585,13 +593,16 @@ func TestTransportGzip(t *testing.T) {
const testString = "The test string aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
const nRandBytes = 1024 * 1024
ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {
+ if req.Method == "HEAD" {
+ if g := req.Header.Get("Accept-Encoding"); g != "" {
+ t.Errorf("HEAD request sent with Accept-Encoding of %q; want none", g)
+ }
+ return
+ }
if g, e := req.Header.Get("Accept-Encoding"), "gzip"; g != e {
t.Errorf("Accept-Encoding = %q, want %q", g, e)
}
rw.Header().Set("Content-Encoding", "gzip")
- if req.Method == "HEAD" {
- return
- }
var w io.Writer = rw
var buf bytes.Buffer
@@ -819,7 +830,7 @@ func TestTransportPersistConnLeakShortBody(t *testing.T) {
}
nhigh := runtime.NumGoroutine()
tr.CloseIdleConnections()
- time.Sleep(50 * time.Millisecond)
+ time.Sleep(400 * time.Millisecond)
runtime.GC()
nfinal := runtime.NumGoroutine()
@@ -1571,6 +1582,77 @@ func TestProxyFromEnvironment(t *testing.T) {
}
}
+func TestIdleConnChannelLeak(t *testing.T) {
+ var mu sync.Mutex
+ var n int
+
+ ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+ mu.Lock()
+ n++
+ mu.Unlock()
+ }))
+ defer ts.Close()
+
+ tr := &Transport{
+ Dial: func(netw, addr string) (net.Conn, error) {
+ return net.Dial(netw, ts.Listener.Addr().String())
+ },
+ }
+ defer tr.CloseIdleConnections()
+
+ c := &Client{Transport: tr}
+
+ // First, without keep-alives.
+ for _, disableKeep := range []bool{true, false} {
+ tr.DisableKeepAlives = disableKeep
+ for i := 0; i < 5; i++ {
+ _, err := c.Get(fmt.Sprintf("http://foo-host-%d.tld/", i))
+ if err != nil {
+ t.Fatal(err)
+ }
+ }
+ if got := tr.IdleConnChMapSizeForTesting(); got != 0 {
+ t.Fatalf("ForDisableKeepAlives = %v, map size = %d; want 0", disableKeep, got)
+ }
+ }
+}
+
+// Verify the status quo: that the Client.Post function coerces its
+// body into a ReadCloser if it's a Closer, and that the Transport
+// then closes it.
+func TestTransportClosesRequestBody(t *testing.T) {
+ defer afterTest(t)
+ ts := httptest.NewServer(http.HandlerFunc(func(w ResponseWriter, r *Request) {
+ io.Copy(ioutil.Discard, r.Body)
+ }))
+ defer ts.Close()
+
+ tr := &Transport{}
+ defer tr.CloseIdleConnections()
+ cl := &Client{Transport: tr}
+
+ closes := 0
+
+ res, err := cl.Post(ts.URL, "text/plain", countCloseReader{&closes, strings.NewReader("hello")})
+ if err != nil {
+ t.Fatal(err)
+ }
+ res.Body.Close()
+ if closes != 1 {
+ t.Errorf("closes = %d; want 1", closes)
+ }
+}
+
+type countCloseReader struct {
+ n *int
+ io.Reader
+}
+
+func (cr countCloseReader) Close() error {
+ (*cr.n)++
+ return nil
+}
+
// rgz is a gzip quine that uncompresses to itself.
var rgz = []byte{
0x1f, 0x8b, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00,
diff --git a/libgo/go/net/http/z_last_test.go b/libgo/go/net/http/z_last_test.go
index 2161db7365d..5a0cc119849 100644
--- a/libgo/go/net/http/z_last_test.go
+++ b/libgo/go/net/http/z_last_test.go
@@ -23,7 +23,6 @@ func interestingGoroutines() (gs []string) {
}
stack := strings.TrimSpace(sl[1])
if stack == "" ||
- strings.Contains(stack, "created by net.newPollServer") ||
strings.Contains(stack, "created by net.startServer") ||
strings.Contains(stack, "created by testing.RunTests") ||
strings.Contains(stack, "closeWriteAndWait") ||
diff --git a/libgo/go/net/interface_bsd.go b/libgo/go/net/interface_bsd.go
index 716b60a97f4..16775579d05 100644
--- a/libgo/go/net/interface_bsd.go
+++ b/libgo/go/net/interface_bsd.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd netbsd openbsd
+// +build darwin dragonfly freebsd netbsd openbsd
package net
diff --git a/libgo/go/net/interface_dragonfly.go b/libgo/go/net/interface_dragonfly.go
new file mode 100644
index 00000000000..c9ce5a7ac15
--- /dev/null
+++ b/libgo/go/net/interface_dragonfly.go
@@ -0,0 +1,12 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package net
+
+// interfaceMulticastAddrTable returns addresses for a specific
+// interface.
+func interfaceMulticastAddrTable(ifi *Interface) ([]Addr, error) {
+ // TODO(mikio): Implement this like other platforms.
+ return nil, nil
+}
diff --git a/libgo/go/net/interface_test.go b/libgo/go/net/interface_test.go
index e31894abf73..efabb5f3c25 100644
--- a/libgo/go/net/interface_test.go
+++ b/libgo/go/net/interface_test.go
@@ -108,12 +108,23 @@ func testInterfaceMulticastAddrs(t *testing.T, ifi *Interface) {
func testAddrs(t *testing.T, ifat []Addr) {
for _, ifa := range ifat {
switch ifa := ifa.(type) {
- case *IPAddr, *IPNet:
- if ifa == nil {
- t.Errorf("\tunexpected value: %v", ifa)
+ case *IPAddr:
+ if ifa == nil || ifa.IP == nil {
+ t.Errorf("\tunexpected value: %v, %v", ifa, ifa.IP)
} else {
t.Logf("\tinterface address %q", ifa.String())
}
+ case *IPNet:
+ if ifa == nil || ifa.IP == nil || ifa.Mask == nil {
+ t.Errorf("\tunexpected value: %v, %v, %v", ifa, ifa.IP, ifa.Mask)
+ } else {
+ _, prefixLen := ifa.Mask.Size()
+ if ifa.IP.To4() != nil && prefixLen != 8*IPv4len || ifa.IP.To16() != nil && ifa.IP.To4() == nil && prefixLen != 8*IPv6len {
+ t.Errorf("\tunexpected value: %v, %v, %v, %v", ifa, ifa.IP, ifa.Mask, prefixLen)
+ } else {
+ t.Logf("\tinterface address %q", ifa.String())
+ }
+ }
default:
t.Errorf("\tunexpected type: %T", ifa)
}
diff --git a/libgo/go/net/ip.go b/libgo/go/net/ip.go
index 0e42da21683..fd6a7d4ee8b 100644
--- a/libgo/go/net/ip.go
+++ b/libgo/go/net/ip.go
@@ -12,6 +12,8 @@
package net
+import "errors"
+
// IP address lengths (bytes).
const (
IPv4len = 4
@@ -310,6 +312,43 @@ func (ip IP) String() string {
return s
}
+// ipEmptyString is like ip.String except that it returns
+// an empty string when ip is unset.
+func ipEmptyString(ip IP) string {
+ if len(ip) == 0 {
+ return ""
+ }
+ return ip.String()
+}
+
+// MarshalText implements the encoding.TextMarshaler interface.
+// The encoding is the same as returned by String.
+func (ip IP) MarshalText() ([]byte, error) {
+ if len(ip) == 0 {
+ return []byte(""), nil
+ }
+ if len(ip) != IPv4len && len(ip) != IPv6len {
+ return nil, errors.New("invalid IP address")
+ }
+ return []byte(ip.String()), nil
+}
+
+// UnmarshalText implements the encoding.TextUnmarshaler interface.
+// The IP address is expected in a form accepted by ParseIP.
+func (ip *IP) UnmarshalText(text []byte) error {
+ if len(text) == 0 {
+ *ip = nil
+ return nil
+ }
+ s := string(text)
+ x := ParseIP(s)
+ if x == nil {
+ return &ParseError{"IP address", s}
+ }
+ *ip = x
+ return nil
+}
+
// Equal returns true if ip and x are the same IP address.
// An IPv4 address and that same address in IPv6 form are
// considered to be equal.
diff --git a/libgo/go/net/ip_test.go b/libgo/go/net/ip_test.go
index 16f30d446b5..26b53729b85 100644
--- a/libgo/go/net/ip_test.go
+++ b/libgo/go/net/ip_test.go
@@ -32,6 +32,32 @@ func TestParseIP(t *testing.T) {
if out := ParseIP(tt.in); !reflect.DeepEqual(out, tt.out) {
t.Errorf("ParseIP(%q) = %v, want %v", tt.in, out, tt.out)
}
+ if tt.in == "" {
+ // Tested in TestMarshalEmptyIP below.
+ continue
+ }
+ var out IP
+ if err := out.UnmarshalText([]byte(tt.in)); !reflect.DeepEqual(out, tt.out) || (tt.out == nil) != (err != nil) {
+ t.Errorf("IP.UnmarshalText(%q) = %v, %v, want %v", tt.in, out, err, tt.out)
+ }
+ }
+}
+
+// Issue 6339
+func TestMarshalEmptyIP(t *testing.T) {
+ for _, in := range [][]byte{nil, []byte("")} {
+ var out = IP{1, 2, 3, 4}
+ if err := out.UnmarshalText(in); err != nil || out != nil {
+ t.Errorf("UnmarshalText(%v) = %v, %v; want nil, nil", in, out, err)
+ }
+ }
+ var ip IP
+ got, err := ip.MarshalText()
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !reflect.DeepEqual(got, []byte("")) {
+ t.Errorf(`got %#v, want []byte("")`, got)
}
}
@@ -47,13 +73,19 @@ var ipStringTests = []struct {
{IP{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0, 0, 0x1, 0, 0, 0, 0, 0, 0}, "2001:db8:0:0:1::"},
{IP{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0, 0, 0x1, 0, 0, 0, 0, 0, 0x1}, "2001:db8::1:0:0:1"},
{IP{0x20, 0x1, 0xD, 0xB8, 0, 0, 0, 0, 0, 0xA, 0, 0xB, 0, 0xC, 0, 0xD}, "2001:db8::a:b:c:d"},
- {nil, "<nil>"},
+ {IPv4(192, 168, 0, 1), "192.168.0.1"},
+ {nil, ""},
}
func TestIPString(t *testing.T) {
for _, tt := range ipStringTests {
- if out := tt.in.String(); out != tt.out {
- t.Errorf("IP.String(%v) = %q, want %q", tt.in, out, tt.out)
+ if tt.in != nil {
+ if out := tt.in.String(); out != tt.out {
+ t.Errorf("IP.String(%v) = %q, want %q", tt.in, out, tt.out)
+ }
+ }
+ if out, err := tt.in.MarshalText(); string(out) != tt.out || err != nil {
+ t.Errorf("IP.MarshalText(%v) = %q, %v, want %q, nil", tt.in, out, err, tt.out)
}
}
}
diff --git a/libgo/go/net/ipraw_test.go b/libgo/go/net/ipraw_test.go
index 12c199d1cf4..ea183f1d3eb 100644
--- a/libgo/go/net/ipraw_test.go
+++ b/libgo/go/net/ipraw_test.go
@@ -6,19 +6,19 @@ package net
import (
"bytes"
- "errors"
"fmt"
"os"
"reflect"
+ "runtime"
"testing"
"time"
)
type resolveIPAddrTest struct {
- net string
- litAddr string
- addr *IPAddr
- err error
+ net string
+ litAddrOrName string
+ addr *IPAddr
+ err error
}
var resolveIPAddrTests = []resolveIPAddrTest{
@@ -29,6 +29,7 @@ var resolveIPAddrTests = []resolveIPAddrTest{
{"ip", "::1", &IPAddr{IP: ParseIP("::1")}, nil},
{"ip6", "::1", &IPAddr{IP: ParseIP("::1")}, nil},
{"ip6:ipv6-icmp", "::1", &IPAddr{IP: ParseIP("::1")}, nil},
+ {"ip6:IPv6-ICMP", "::1", &IPAddr{IP: ParseIP("::1")}, nil},
{"ip", "::1%en0", &IPAddr{IP: ParseIP("::1"), Zone: "en0"}, nil},
{"ip6", "::1%911", &IPAddr{IP: ParseIP("::1"), Zone: "911"}, nil},
@@ -49,13 +50,28 @@ func init() {
{"ip6", "fe80::1%" + index, &IPAddr{IP: ParseIP("fe80::1"), Zone: index}, nil},
}...)
}
+ if ips, err := LookupIP("localhost"); err == nil && len(ips) > 1 && supportsIPv4 && supportsIPv6 {
+ resolveIPAddrTests = append(resolveIPAddrTests, []resolveIPAddrTest{
+ {"ip", "localhost", &IPAddr{IP: IPv4(127, 0, 0, 1)}, nil},
+ {"ip4", "localhost", &IPAddr{IP: IPv4(127, 0, 0, 1)}, nil},
+ {"ip6", "localhost", &IPAddr{IP: IPv6loopback}, nil},
+ }...)
+ }
+}
+
+func skipRawSocketTest(t *testing.T) (skip bool, skipmsg string) {
+ skip, skipmsg, err := skipRawSocketTests()
+ if err != nil {
+ t.Fatal(err)
+ }
+ return skip, skipmsg
}
func TestResolveIPAddr(t *testing.T) {
for _, tt := range resolveIPAddrTests {
- addr, err := ResolveIPAddr(tt.net, tt.litAddr)
+ addr, err := ResolveIPAddr(tt.net, tt.litAddrOrName)
if err != tt.err {
- condFatalf(t, "ResolveIPAddr(%v, %v) failed: %v", tt.net, tt.litAddr, err)
+ t.Fatalf("ResolveIPAddr(%v, %v) failed: %v", tt.net, tt.litAddrOrName, err)
} else if !reflect.DeepEqual(addr, tt.addr) {
t.Fatalf("got %#v; expected %#v", addr, tt.addr)
}
@@ -72,8 +88,8 @@ var icmpEchoTests = []struct {
}
func TestConnICMPEcho(t *testing.T) {
- if os.Getuid() != 0 {
- t.Skip("skipping test; must be root")
+ if skip, skipmsg := skipRawSocketTest(t); skip {
+ t.Skip(skipmsg)
}
for i, tt := range icmpEchoTests {
@@ -97,7 +113,7 @@ func TestConnICMPEcho(t *testing.T) {
typ = icmpv6EchoRequest
}
xid, xseq := os.Getpid()&0xffff, i+1
- b, err := (&icmpMessage{
+ wb, err := (&icmpMessage{
Type: typ, Code: 0,
Body: &icmpEcho{
ID: xid, Seq: xseq,
@@ -107,18 +123,19 @@ func TestConnICMPEcho(t *testing.T) {
if err != nil {
t.Fatalf("icmpMessage.Marshal failed: %v", err)
}
- if _, err := c.Write(b); err != nil {
+ if _, err := c.Write(wb); err != nil {
t.Fatalf("Conn.Write failed: %v", err)
}
var m *icmpMessage
+ rb := make([]byte, 20+len(wb))
for {
- if _, err := c.Read(b); err != nil {
+ if _, err := c.Read(rb); err != nil {
t.Fatalf("Conn.Read failed: %v", err)
}
if net == "ip4" {
- b = ipv4Payload(b)
+ rb = ipv4Payload(rb)
}
- if m, err = parseICMPMessage(b); err != nil {
+ if m, err = parseICMPMessage(rb); err != nil {
t.Fatalf("parseICMPMessage failed: %v", err)
}
switch m.Type {
@@ -139,8 +156,8 @@ func TestConnICMPEcho(t *testing.T) {
}
func TestPacketConnICMPEcho(t *testing.T) {
- if os.Getuid() != 0 {
- t.Skip("skipping test; must be root")
+ if skip, skipmsg := skipRawSocketTest(t); skip {
+ t.Skip(skipmsg)
}
for i, tt := range icmpEchoTests {
@@ -168,7 +185,7 @@ func TestPacketConnICMPEcho(t *testing.T) {
typ = icmpv6EchoRequest
}
xid, xseq := os.Getpid()&0xffff, i+1
- b, err := (&icmpMessage{
+ wb, err := (&icmpMessage{
Type: typ, Code: 0,
Body: &icmpEcho{
ID: xid, Seq: xseq,
@@ -178,19 +195,20 @@ func TestPacketConnICMPEcho(t *testing.T) {
if err != nil {
t.Fatalf("icmpMessage.Marshal failed: %v", err)
}
- if _, err := c.WriteTo(b, ra); err != nil {
+ if _, err := c.WriteTo(wb, ra); err != nil {
t.Fatalf("PacketConn.WriteTo failed: %v", err)
}
var m *icmpMessage
+ rb := make([]byte, 20+len(wb))
for {
- if _, _, err := c.ReadFrom(b); err != nil {
+ if _, _, err := c.ReadFrom(rb); err != nil {
t.Fatalf("PacketConn.ReadFrom failed: %v", err)
}
- // TODO: fix issue 3944
+ // See BUG section.
//if net == "ip4" {
- // b = ipv4Payload(b)
+ // rb = ipv4Payload(rb)
//}
- if m, err = parseICMPMessage(b); err != nil {
+ if m, err = parseICMPMessage(rb); err != nil {
t.Fatalf("parseICMPMessage failed: %v", err)
}
switch m.Type {
@@ -218,115 +236,6 @@ func ipv4Payload(b []byte) []byte {
return b[hdrlen:]
}
-const (
- icmpv4EchoRequest = 8
- icmpv4EchoReply = 0
- icmpv6EchoRequest = 128
- icmpv6EchoReply = 129
-)
-
-// icmpMessage represents an ICMP message.
-type icmpMessage struct {
- Type int // type
- Code int // code
- Checksum int // checksum
- Body icmpMessageBody // body
-}
-
-// icmpMessageBody represents an ICMP message body.
-type icmpMessageBody interface {
- Len() int
- Marshal() ([]byte, error)
-}
-
-// Marshal returns the binary enconding of the ICMP echo request or
-// reply message m.
-func (m *icmpMessage) Marshal() ([]byte, error) {
- b := []byte{byte(m.Type), byte(m.Code), 0, 0}
- if m.Body != nil && m.Body.Len() != 0 {
- mb, err := m.Body.Marshal()
- if err != nil {
- return nil, err
- }
- b = append(b, mb...)
- }
- switch m.Type {
- case icmpv6EchoRequest, icmpv6EchoReply:
- return b, nil
- }
- csumcv := len(b) - 1 // checksum coverage
- s := uint32(0)
- for i := 0; i < csumcv; i += 2 {
- s += uint32(b[i+1])<<8 | uint32(b[i])
- }
- if csumcv&1 == 0 {
- s += uint32(b[csumcv])
- }
- s = s>>16 + s&0xffff
- s = s + s>>16
- // Place checksum back in header; using ^= avoids the
- // assumption the checksum bytes are zero.
- b[2] ^= byte(^s & 0xff)
- b[3] ^= byte(^s >> 8)
- return b, nil
-}
-
-// parseICMPMessage parses b as an ICMP message.
-func parseICMPMessage(b []byte) (*icmpMessage, error) {
- msglen := len(b)
- if msglen < 4 {
- return nil, errors.New("message too short")
- }
- m := &icmpMessage{Type: int(b[0]), Code: int(b[1]), Checksum: int(b[2])<<8 | int(b[3])}
- if msglen > 4 {
- var err error
- switch m.Type {
- case icmpv4EchoRequest, icmpv4EchoReply, icmpv6EchoRequest, icmpv6EchoReply:
- m.Body, err = parseICMPEcho(b[4:])
- if err != nil {
- return nil, err
- }
- }
- }
- return m, nil
-}
-
-// imcpEcho represenets an ICMP echo request or reply message body.
-type icmpEcho struct {
- ID int // identifier
- Seq int // sequence number
- Data []byte // data
-}
-
-func (p *icmpEcho) Len() int {
- if p == nil {
- return 0
- }
- return 4 + len(p.Data)
-}
-
-// Marshal returns the binary enconding of the ICMP echo request or
-// reply message body p.
-func (p *icmpEcho) Marshal() ([]byte, error) {
- b := make([]byte, 4+len(p.Data))
- b[0], b[1] = byte(p.ID>>8), byte(p.ID&0xff)
- b[2], b[3] = byte(p.Seq>>8), byte(p.Seq&0xff)
- copy(b[4:], p.Data)
- return b, nil
-}
-
-// parseICMPEcho parses b as an ICMP echo request or reply message
-// body.
-func parseICMPEcho(b []byte) (*icmpEcho, error) {
- bodylen := len(b)
- p := &icmpEcho{ID: int(b[0])<<8 | int(b[1]), Seq: int(b[2])<<8 | int(b[3])}
- if bodylen > 4 {
- p.Data = make([]byte, bodylen-4)
- copy(p.Data, b[4:])
- }
- return p, nil
-}
-
var ipConnLocalNameTests = []struct {
net string
laddr *IPAddr
@@ -337,8 +246,13 @@ var ipConnLocalNameTests = []struct {
}
func TestIPConnLocalName(t *testing.T) {
- if os.Getuid() != 0 {
- t.Skip("skipping test; must be root")
+ switch runtime.GOOS {
+ case "plan9", "windows":
+ t.Skipf("skipping test on %q", runtime.GOOS)
+ default:
+ if os.Getuid() != 0 {
+ t.Skip("skipping test; must be root")
+ }
}
for _, tt := range ipConnLocalNameTests {
@@ -354,8 +268,13 @@ func TestIPConnLocalName(t *testing.T) {
}
func TestIPConnRemoteName(t *testing.T) {
- if os.Getuid() != 0 {
- t.Skip("skipping test; must be root")
+ switch runtime.GOOS {
+ case "plan9", "windows":
+ t.Skipf("skipping test on %q", runtime.GOOS)
+ default:
+ if os.Getuid() != 0 {
+ t.Skip("skipping test; must be root")
+ }
}
raddr := &IPAddr{IP: IPv4(127, 0, 0, 10).To4()}
diff --git a/libgo/go/net/iprawsock.go b/libgo/go/net/iprawsock.go
index 0be94eb70eb..5cc361390ff 100644
--- a/libgo/go/net/iprawsock.go
+++ b/libgo/go/net/iprawsock.go
@@ -23,6 +23,13 @@ func (a *IPAddr) String() string {
return a.IP.String()
}
+func (a *IPAddr) toAddr() Addr {
+ if a == nil {
+ return nil
+ }
+ return a
+}
+
// ResolveIPAddr parses addr as an IP address of the form "host" or
// "ipv6-host%zone" and resolves the domain name on the network net,
// which must be "ip", "ip4" or "ip6".
@@ -43,5 +50,5 @@ func ResolveIPAddr(net, addr string) (*IPAddr, error) {
if err != nil {
return nil, err
}
- return a.(*IPAddr), nil
+ return a.toAddr().(*IPAddr), nil
}
diff --git a/libgo/go/net/iprawsock_posix.go b/libgo/go/net/iprawsock_posix.go
index caeeb465383..72285325761 100644
--- a/libgo/go/net/iprawsock_posix.go
+++ b/libgo/go/net/iprawsock_posix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd linux netbsd openbsd windows
+// +build darwin dragonfly freebsd linux netbsd openbsd windows
package net
@@ -11,6 +11,18 @@ import (
"time"
)
+// BUG(mikio): On every POSIX platform, reads from the "ip4" network
+// using the ReadFrom or ReadFromIP method might not return a complete
+// IPv4 packet, including its header, even if there is space
+// available. This can occur even in cases where Read or ReadMsgIP
+// could return a complete packet. For this reason, it is recommended
+// that you do not uses these methods if it is important to receive a
+// full packet.
+//
+// The Go 1 compatibliity guidelines make it impossible for us to
+// change the behavior of these methods; use Read or ReadMsgIP
+// instead.
+
func sockaddrToIP(sa syscall.Sockaddr) Addr {
switch sa := sa.(type) {
case *syscall.SockaddrInet4:
@@ -39,14 +51,10 @@ func (a *IPAddr) isWildcard() bool {
}
func (a *IPAddr) sockaddr(family int) (syscall.Sockaddr, error) {
- return ipToSockaddr(family, a.IP, 0, a.Zone)
-}
-
-func (a *IPAddr) toAddr() sockaddr {
- if a == nil { // nil *IPAddr
- return nil // nil interface
+ if a == nil {
+ return nil, nil
}
- return a
+ return ipToSockaddr(family, a.IP, 0, a.Zone)
}
// IPConn is the implementation of the Conn and PacketConn interfaces
@@ -125,6 +133,9 @@ func (c *IPConn) WriteToIP(b []byte, addr *IPAddr) (int, error) {
if !c.ok() {
return 0, syscall.EINVAL
}
+ if addr == nil {
+ return 0, &OpError{Op: "write", Net: c.fd.net, Addr: nil, Err: errMissingAddress}
+ }
sa, err := addr.sockaddr(c.fd.family)
if err != nil {
return 0, &OpError{"write", c.fd.net, addr, err}
@@ -151,6 +162,9 @@ func (c *IPConn) WriteMsgIP(b, oob []byte, addr *IPAddr) (n, oobn int, err error
if !c.ok() {
return 0, 0, syscall.EINVAL
}
+ if addr == nil {
+ return 0, 0, &OpError{Op: "write", Net: c.fd.net, Addr: nil, Err: errMissingAddress}
+ }
sa, err := addr.sockaddr(c.fd.family)
if err != nil {
return 0, 0, &OpError{"write", c.fd.net, addr, err}
@@ -168,19 +182,19 @@ func DialIP(netProto string, laddr, raddr *IPAddr) (*IPConn, error) {
func dialIP(netProto string, laddr, raddr *IPAddr, deadline time.Time) (*IPConn, error) {
net, proto, err := parseNetwork(netProto)
if err != nil {
- return nil, err
+ return nil, &OpError{Op: "dial", Net: netProto, Addr: raddr, Err: err}
}
switch net {
case "ip", "ip4", "ip6":
default:
- return nil, UnknownNetworkError(netProto)
+ return nil, &OpError{Op: "dial", Net: netProto, Addr: raddr, Err: UnknownNetworkError(netProto)}
}
if raddr == nil {
- return nil, &OpError{"dial", netProto, nil, errMissingAddress}
+ return nil, &OpError{Op: "dial", Net: netProto, Addr: nil, Err: errMissingAddress}
}
- fd, err := internetSocket(net, laddr.toAddr(), raddr.toAddr(), deadline, syscall.SOCK_RAW, proto, "dial", sockaddrToIP)
+ fd, err := internetSocket(net, laddr, raddr, deadline, syscall.SOCK_RAW, proto, "dial", sockaddrToIP)
if err != nil {
- return nil, err
+ return nil, &OpError{Op: "dial", Net: netProto, Addr: raddr, Err: err}
}
return newIPConn(fd), nil
}
@@ -192,16 +206,16 @@ func dialIP(netProto string, laddr, raddr *IPAddr, deadline time.Time) (*IPConn,
func ListenIP(netProto string, laddr *IPAddr) (*IPConn, error) {
net, proto, err := parseNetwork(netProto)
if err != nil {
- return nil, err
+ return nil, &OpError{Op: "dial", Net: netProto, Addr: laddr, Err: err}
}
switch net {
case "ip", "ip4", "ip6":
default:
- return nil, UnknownNetworkError(netProto)
+ return nil, &OpError{Op: "listen", Net: netProto, Addr: laddr, Err: UnknownNetworkError(netProto)}
}
- fd, err := internetSocket(net, laddr.toAddr(), nil, noDeadline, syscall.SOCK_RAW, proto, "listen", sockaddrToIP)
+ fd, err := internetSocket(net, laddr, nil, noDeadline, syscall.SOCK_RAW, proto, "listen", sockaddrToIP)
if err != nil {
- return nil, err
+ return nil, &OpError{Op: "listen", Net: netProto, Addr: laddr, Err: err}
}
return newIPConn(fd), nil
}
diff --git a/libgo/go/net/ipsock.go b/libgo/go/net/ipsock.go
index d930595879c..8b586ef7c3e 100644
--- a/libgo/go/net/ipsock.go
+++ b/libgo/go/net/ipsock.go
@@ -6,68 +6,135 @@
package net
-import "time"
+import (
+ "errors"
+ "time"
+)
-var supportsIPv6, supportsIPv4map bool
+var (
+ // supportsIPv4 reports whether the platform supports IPv4
+ // networking functionality.
+ supportsIPv4 bool
+
+ // supportsIPv6 reports whether the platfrom supports IPv6
+ // networking functionality.
+ supportsIPv6 bool
+
+ // supportsIPv4map reports whether the platform supports
+ // mapping an IPv4 address inside an IPv6 address at transport
+ // layer protocols. See RFC 4291, RFC 4038 and RFC 3493.
+ supportsIPv4map bool
+)
func init() {
sysInit()
+ supportsIPv4 = probeIPv4Stack()
supportsIPv6, supportsIPv4map = probeIPv6Stack()
}
-func firstFavoriteAddr(filter func(IP) IP, addrs []string) (addr IP) {
- if filter == nil {
- // We'll take any IP address, but since the dialing code
- // does not yet try multiple addresses, prefer to use
- // an IPv4 address if possible. This is especially relevant
- // if localhost resolves to [ipv6-localhost, ipv4-localhost].
- // Too much code assumes localhost == ipv4-localhost.
- addr = firstSupportedAddr(ipv4only, addrs)
- if addr == nil {
- addr = firstSupportedAddr(anyaddr, addrs)
- }
- } else {
- addr = firstSupportedAddr(filter, addrs)
+// A netaddr represents a network endpoint address or a list of
+// network endpoint addresses.
+type netaddr interface {
+ // toAddr returns the address represented in Addr interface.
+ // It returns a nil interface when the address is nil.
+ toAddr() Addr
+}
+
+// An addrList represents a list of network endpoint addresses.
+type addrList []netaddr
+
+func (al addrList) toAddr() Addr {
+ switch len(al) {
+ case 0:
+ return nil
+ case 1:
+ return al[0].toAddr()
+ default:
+ // For now, we'll roughly pick first one without
+ // considering dealing with any preferences such as
+ // DNS TTL, transport path quality, network routing
+ // information.
+ return al[0].toAddr()
}
- return
}
-func firstSupportedAddr(filter func(IP) IP, addrs []string) IP {
- for _, s := range addrs {
- if addr := filter(ParseIP(s)); addr != nil {
- return addr
+var errNoSuitableAddress = errors.New("no suitable address found")
+
+// firstFavoriteAddr returns an address or a list of addresses that
+// implement the netaddr interface. Known filters are nil, ipv4only
+// and ipv6only. It returns any address when filter is nil. The result
+// contains at least one address when error is nil.
+func firstFavoriteAddr(filter func(IP) IP, ips []IP, inetaddr func(IP) netaddr) (netaddr, error) {
+ if filter != nil {
+ return firstSupportedAddr(filter, ips, inetaddr)
+ }
+ var (
+ ipv4, ipv6, swap bool
+ list addrList
+ )
+ for _, ip := range ips {
+ // We'll take any IP address, but since the dialing
+ // code does not yet try multiple addresses
+ // effectively, prefer to use an IPv4 address if
+ // possible. This is especially relevant if localhost
+ // resolves to [ipv6-localhost, ipv4-localhost]. Too
+ // much code assumes localhost == ipv4-localhost.
+ if ip4 := ipv4only(ip); ip4 != nil && !ipv4 {
+ list = append(list, inetaddr(ip4))
+ ipv4 = true
+ if ipv6 {
+ swap = true
+ }
+ } else if ip6 := ipv6only(ip); ip6 != nil && !ipv6 {
+ list = append(list, inetaddr(ip6))
+ ipv6 = true
+ }
+ if ipv4 && ipv6 {
+ if swap {
+ list[0], list[1] = list[1], list[0]
+ }
+ break
}
}
- return nil
+ switch len(list) {
+ case 0:
+ return nil, errNoSuitableAddress
+ case 1:
+ return list[0], nil
+ default:
+ return list, nil
+ }
}
-func anyaddr(x IP) IP {
- if x4 := x.To4(); x4 != nil {
- return x4
+func firstSupportedAddr(filter func(IP) IP, ips []IP, inetaddr func(IP) netaddr) (netaddr, error) {
+ for _, ip := range ips {
+ if ip := filter(ip); ip != nil {
+ return inetaddr(ip), nil
+ }
}
- if supportsIPv6 {
- return x
+ return nil, errNoSuitableAddress
+}
+
+// ipv4only returns IPv4 addresses that we can use with the kernel's
+// IPv4 addressing modes. If ip is an IPv4 address, ipv4only returns ip.
+// Otherwise it returns nil.
+func ipv4only(ip IP) IP {
+ if supportsIPv4 && ip.To4() != nil {
+ return ip
}
return nil
}
-func ipv4only(x IP) IP { return x.To4() }
-
-func ipv6only(x IP) IP {
- // Only return addresses that we can use
- // with the kernel's IPv6 addressing modes.
- if len(x) == IPv6len && x.To4() == nil && supportsIPv6 {
- return x
+// ipv6only returns IPv6 addresses that we can use with the kernel's
+// IPv6 addressing modes. It returns IPv4-mapped IPv6 addresses as
+// nils and returns other IPv6 address types as IPv6 addresses.
+func ipv6only(ip IP) IP {
+ if supportsIPv6 && len(ip) == IPv6len && ip.To4() == nil {
+ return ip
}
return nil
}
-type InvalidAddrError string
-
-func (e InvalidAddrError) Error() string { return string(e) }
-func (e InvalidAddrError) Timeout() bool { return false }
-func (e InvalidAddrError) Temporary() bool { return false }
-
// SplitHostPort splits a network address of the form "host:port",
// "[host]:port" or "[ipv6-host%zone]:port" into host or
// ipv6-host%zone and port. A literal address or host name for IPv6
@@ -161,7 +228,13 @@ func JoinHostPort(host, port string) string {
return host + ":" + port
}
-func resolveInternetAddr(net, addr string, deadline time.Time) (Addr, error) {
+// resolveInternetAddr resolves addr that is either a literal IP
+// address or a DNS name and returns an internet protocol family
+// address. It returns a list that contains a pair of different
+// address family addresses when addr is a DNS name and the name has
+// mutiple address family records. The result contains at least one
+// address when error is nil.
+func resolveInternetAddr(net, addr string, deadline time.Time) (netaddr, error) {
var (
err error
host, port, zone string
@@ -184,30 +257,32 @@ func resolveInternetAddr(net, addr string, deadline time.Time) (Addr, error) {
default:
return nil, UnknownNetworkError(net)
}
- inetaddr := func(net string, ip IP, port int, zone string) Addr {
+ inetaddr := func(ip IP) netaddr {
switch net {
case "tcp", "tcp4", "tcp6":
- return &TCPAddr{IP: ip, Port: port, Zone: zone}
+ return &TCPAddr{IP: ip, Port: portnum, Zone: zone}
case "udp", "udp4", "udp6":
- return &UDPAddr{IP: ip, Port: port, Zone: zone}
+ return &UDPAddr{IP: ip, Port: portnum, Zone: zone}
case "ip", "ip4", "ip6":
return &IPAddr{IP: ip, Zone: zone}
+ default:
+ panic("unexpected network: " + net)
}
- return nil
}
if host == "" {
- return inetaddr(net, nil, portnum, zone), nil
+ return inetaddr(nil), nil
}
- // Try as an IP address.
- if ip := parseIPv4(host); ip != nil {
- return inetaddr(net, ip, portnum, zone), nil
+ // Try as a literal IP address.
+ var ip IP
+ if ip = parseIPv4(host); ip != nil {
+ return inetaddr(ip), nil
}
- if ip, zone := parseIPv6(host, true); ip != nil {
- return inetaddr(net, ip, portnum, zone), nil
+ if ip, zone = parseIPv6(host, true); ip != nil {
+ return inetaddr(ip), nil
}
- // Try as a domain name.
+ // Try as a DNS name.
host, zone = splitHostZone(host)
- addrs, err := lookupHostDeadline(host, deadline)
+ ips, err := lookupIPDeadline(host, deadline)
if err != nil {
return nil, err
}
@@ -218,12 +293,7 @@ func resolveInternetAddr(net, addr string, deadline time.Time) (Addr, error) {
if net != "" && net[len(net)-1] == '6' || zone != "" {
filter = ipv6only
}
- ip := firstFavoriteAddr(filter, addrs)
- if ip == nil {
- // should not happen
- return nil, &AddrError{"LookupHost returned no suitable address", addrs[0]}
- }
- return inetaddr(net, ip, portnum, zone), nil
+ return firstFavoriteAddr(filter, ips, inetaddr)
}
func zoneToString(zone int) string {
diff --git a/libgo/go/net/ipsock_plan9.go b/libgo/go/net/ipsock_plan9.go
index c7d542dabc6..fcec4164f4c 100644
--- a/libgo/go/net/ipsock_plan9.go
+++ b/libgo/go/net/ipsock_plan9.go
@@ -12,13 +12,18 @@ import (
"syscall"
)
-// /sys/include/ape/sys/socket.h:/SOMAXCONN
-var listenerBacklog = 5
+func probeIPv4Stack() bool {
+ // TODO(mikio): implement this when Plan 9 supports IPv6-only
+ // kernel.
+ return true
+}
// probeIPv6Stack returns two boolean values. If the first boolean
// value is true, kernel supports basic IPv6 functionality. If the
// second boolean value is true, kernel supports IPv6 IPv4-mapping.
func probeIPv6Stack() (supportsIPv6, supportsIPv4map bool) {
+ // TODO(mikio): implement this once Plan 9 gets an IPv6
+ // protocol stack implementation.
return false, false
}
diff --git a/libgo/go/net/ipsock_posix.go b/libgo/go/net/ipsock_posix.go
index 4c37616ecf8..a83e5256174 100644
--- a/libgo/go/net/ipsock_posix.go
+++ b/libgo/go/net/ipsock_posix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd linux netbsd openbsd windows
+// +build darwin dragonfly freebsd linux netbsd openbsd windows
// Internet protocol family sockets for POSIX
@@ -13,6 +13,17 @@ import (
"time"
)
+func probeIPv4Stack() bool {
+ s, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_STREAM, syscall.IPPROTO_TCP)
+ switch err {
+ case syscall.EAFNOSUPPORT, syscall.EPROTONOSUPPORT:
+ return false
+ case nil:
+ closesocket(s)
+ }
+ return true
+}
+
// Should we try to use the IPv4 socket interface if we're
// only dealing with IPv4 sockets? As long as the host system
// understands IPv6, it's okay to pass IPv4 addresses to the IPv6
@@ -28,8 +39,8 @@ import (
// boolean value is true, kernel supports IPv6 IPv4-mapping.
func probeIPv6Stack() (supportsIPv6, supportsIPv4map bool) {
var probes = []struct {
- la TCPAddr
- ok bool
+ laddr TCPAddr
+ ok bool
}{
// IPv6 communication capability
{TCPAddr{IP: ParseIP("::1")}, false},
@@ -44,12 +55,11 @@ func probeIPv6Stack() (supportsIPv6, supportsIPv4map bool) {
}
defer closesocket(s)
syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, 0)
- sa, err := probes[i].la.toAddr().sockaddr(syscall.AF_INET6)
+ sa, err := probes[i].laddr.sockaddr(syscall.AF_INET6)
if err != nil {
continue
}
- err = syscall.Bind(s, sa)
- if err != nil {
+ if err := syscall.Bind(s, sa); err != nil {
continue
}
probes[i].ok = true
@@ -121,40 +131,9 @@ func favoriteAddrFamily(net string, laddr, raddr sockaddr, mode string) (family
// Internet sockets (TCP, UDP, IP)
-// A sockaddr represents a TCP, UDP or IP network address that can
-// be converted into a syscall.Sockaddr.
-type sockaddr interface {
- Addr
- family() int
- isWildcard() bool
- sockaddr(family int) (syscall.Sockaddr, error)
-}
-
func internetSocket(net string, laddr, raddr sockaddr, deadline time.Time, sotype, proto int, mode string, toAddr func(syscall.Sockaddr) Addr) (fd *netFD, err error) {
- var la, ra syscall.Sockaddr
family, ipv6only := favoriteAddrFamily(net, laddr, raddr, mode)
- if laddr != nil {
- if la, err = laddr.sockaddr(family); err != nil {
- goto Error
- }
- }
- if raddr != nil {
- if ra, err = raddr.sockaddr(family); err != nil {
- goto Error
- }
- }
- fd, err = socket(net, family, sotype, proto, ipv6only, la, ra, deadline, toAddr)
- if err != nil {
- goto Error
- }
- return fd, nil
-
-Error:
- addr := raddr
- if mode == "listen" {
- addr = laddr
- }
- return nil, &OpError{mode, net, addr, err}
+ return socket(net, family, sotype, proto, ipv6only, laddr, raddr, deadline, toAddr)
}
func ipToSockaddr(family int, ip IP, port int, zone string) (syscall.Sockaddr, error) {
diff --git a/libgo/go/net/ipsock_test.go b/libgo/go/net/ipsock_test.go
new file mode 100644
index 00000000000..9ecaaec69f6
--- /dev/null
+++ b/libgo/go/net/ipsock_test.go
@@ -0,0 +1,193 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package net
+
+import (
+ "reflect"
+ "testing"
+)
+
+var testInetaddr = func(ip IP) netaddr { return &TCPAddr{IP: ip, Port: 5682} }
+
+var firstFavoriteAddrTests = []struct {
+ filter func(IP) IP
+ ips []IP
+ inetaddr func(IP) netaddr
+ addr netaddr
+ err error
+}{
+ {
+ nil,
+ []IP{
+ IPv4(127, 0, 0, 1),
+ IPv6loopback,
+ },
+ testInetaddr,
+ addrList{
+ &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
+ &TCPAddr{IP: IPv6loopback, Port: 5682},
+ },
+ nil,
+ },
+ {
+ nil,
+ []IP{
+ IPv6loopback,
+ IPv4(127, 0, 0, 1),
+ },
+ testInetaddr,
+ addrList{
+ &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
+ &TCPAddr{IP: IPv6loopback, Port: 5682},
+ },
+ nil,
+ },
+ {
+ nil,
+ []IP{
+ IPv4(127, 0, 0, 1),
+ IPv4(192, 168, 0, 1),
+ },
+ testInetaddr,
+ &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
+ nil,
+ },
+ {
+ nil,
+ []IP{
+ IPv6loopback,
+ ParseIP("fe80::1"),
+ },
+ testInetaddr,
+ &TCPAddr{IP: IPv6loopback, Port: 5682},
+ nil,
+ },
+ {
+ nil,
+ []IP{
+ IPv4(127, 0, 0, 1),
+ IPv4(192, 168, 0, 1),
+ IPv6loopback,
+ ParseIP("fe80::1"),
+ },
+ testInetaddr,
+ addrList{
+ &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
+ &TCPAddr{IP: IPv6loopback, Port: 5682},
+ },
+ nil,
+ },
+ {
+ nil,
+ []IP{
+ IPv6loopback,
+ ParseIP("fe80::1"),
+ IPv4(127, 0, 0, 1),
+ IPv4(192, 168, 0, 1),
+ },
+ testInetaddr,
+ addrList{
+ &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
+ &TCPAddr{IP: IPv6loopback, Port: 5682},
+ },
+ nil,
+ },
+ {
+ nil,
+ []IP{
+ IPv4(127, 0, 0, 1),
+ IPv6loopback,
+ IPv4(192, 168, 0, 1),
+ ParseIP("fe80::1"),
+ },
+ testInetaddr,
+ addrList{
+ &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
+ &TCPAddr{IP: IPv6loopback, Port: 5682},
+ },
+ nil,
+ },
+ {
+ nil,
+ []IP{
+ IPv6loopback,
+ IPv4(127, 0, 0, 1),
+ ParseIP("fe80::1"),
+ IPv4(192, 168, 0, 1),
+ },
+ testInetaddr,
+ addrList{
+ &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
+ &TCPAddr{IP: IPv6loopback, Port: 5682},
+ },
+ nil,
+ },
+
+ {
+ ipv4only,
+ []IP{
+ IPv4(127, 0, 0, 1),
+ IPv6loopback,
+ },
+ testInetaddr,
+ &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
+ nil,
+ },
+ {
+ ipv4only,
+ []IP{
+ IPv6loopback,
+ IPv4(127, 0, 0, 1),
+ },
+ testInetaddr,
+ &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5682},
+ nil,
+ },
+
+ {
+ ipv6only,
+ []IP{
+ IPv4(127, 0, 0, 1),
+ IPv6loopback,
+ },
+ testInetaddr,
+ &TCPAddr{IP: IPv6loopback, Port: 5682},
+ nil,
+ },
+ {
+ ipv6only,
+ []IP{
+ IPv6loopback,
+ IPv4(127, 0, 0, 1),
+ },
+ testInetaddr,
+ &TCPAddr{IP: IPv6loopback, Port: 5682},
+ nil,
+ },
+
+ {nil, nil, testInetaddr, nil, errNoSuitableAddress},
+
+ {ipv4only, nil, testInetaddr, nil, errNoSuitableAddress},
+ {ipv4only, []IP{IPv6loopback}, testInetaddr, nil, errNoSuitableAddress},
+
+ {ipv6only, nil, testInetaddr, nil, errNoSuitableAddress},
+ {ipv6only, []IP{IPv4(127, 0, 0, 1)}, testInetaddr, nil, errNoSuitableAddress},
+}
+
+func TestFirstFavoriteAddr(t *testing.T) {
+ if !supportsIPv4 || !supportsIPv6 {
+ t.Skip("ipv4 or ipv6 is not supported")
+ }
+
+ for i, tt := range firstFavoriteAddrTests {
+ addr, err := firstFavoriteAddr(tt.filter, tt.ips, tt.inetaddr)
+ if err != tt.err {
+ t.Errorf("#%v: got %v; expected %v", i, err, tt.err)
+ }
+ if !reflect.DeepEqual(addr, tt.addr) {
+ t.Errorf("#%v: got %v; expected %v", i, addr, tt.addr)
+ }
+ }
+}
diff --git a/libgo/go/net/lookup.go b/libgo/go/net/lookup.go
index bec93ec08cd..20f20578cde 100644
--- a/libgo/go/net/lookup.go
+++ b/libgo/go/net/lookup.go
@@ -4,9 +4,20 @@
package net
-import (
- "time"
-)
+import "time"
+
+// protocols contains minimal mappings between internet protocol
+// names and numbers for platforms that don't have a complete list of
+// protocol numbers.
+//
+// See http://www.iana.org/assignments/protocol-numbers
+var protocols = map[string]int{
+ "icmp": 1, "ICMP": 1,
+ "igmp": 2, "IGMP": 2,
+ "tcp": 6, "TCP": 6,
+ "udp": 17, "UDP": 17,
+ "ipv6-icmp": 58, "IPV6-ICMP": 58, "IPv6-ICMP": 58,
+}
// LookupHost looks up the given host using the local resolver.
// It returns an array of that host's addresses.
@@ -14,9 +25,36 @@ func LookupHost(host string) (addrs []string, err error) {
return lookupHost(host)
}
-func lookupHostDeadline(host string, deadline time.Time) (addrs []string, err error) {
+// LookupIP looks up host using the local resolver.
+// It returns an array of that host's IPv4 and IPv6 addresses.
+func LookupIP(host string) (addrs []IP, err error) {
+ return lookupIPMerge(host)
+}
+
+var lookupGroup singleflight
+
+// lookupIPMerge wraps lookupIP, but makes sure that for any given
+// host, only one lookup is in-flight at a time. The returned memory
+// is always owned by the caller.
+func lookupIPMerge(host string) (addrs []IP, err error) {
+ addrsi, err, shared := lookupGroup.Do(host, func() (interface{}, error) {
+ return lookupIP(host)
+ })
+ if err != nil {
+ return nil, err
+ }
+ addrs = addrsi.([]IP)
+ if shared {
+ clone := make([]IP, len(addrs))
+ copy(clone, addrs)
+ addrs = clone
+ }
+ return addrs, nil
+}
+
+func lookupIPDeadline(host string, deadline time.Time) (addrs []IP, err error) {
if deadline.IsZero() {
- return lookupHost(host)
+ return lookupIPMerge(host)
}
// TODO(bradfitz): consider pushing the deadline down into the
@@ -34,12 +72,12 @@ func lookupHostDeadline(host string, deadline time.Time) (addrs []string, err er
t := time.NewTimer(timeout)
defer t.Stop()
type res struct {
- addrs []string
+ addrs []IP
err error
}
resc := make(chan res, 1)
go func() {
- a, err := lookupHost(host)
+ a, err := lookupIPMerge(host)
resc <- res{a, err}
}()
select {
@@ -51,12 +89,6 @@ func lookupHostDeadline(host string, deadline time.Time) (addrs []string, err er
return
}
-// LookupIP looks up host using the local resolver.
-// It returns an array of that host's IPv4 and IPv6 addresses.
-func LookupIP(host string) (addrs []IP, err error) {
- return lookupIP(host)
-}
-
// LookupPort looks up the port for the given network and service.
func LookupPort(network, service string) (port int, err error) {
return lookupPort(network, service)
diff --git a/libgo/go/net/lookup_plan9.go b/libgo/go/net/lookup_plan9.go
index 94c55332869..f1204a99f7b 100644
--- a/libgo/go/net/lookup_plan9.go
+++ b/libgo/go/net/lookup_plan9.go
@@ -186,9 +186,9 @@ func lookupSRV(service, proto, name string) (cname string, addrs []*SRV, err err
if len(f) < 6 {
continue
}
- port, _, portOk := dtoi(f[2], 0)
+ port, _, portOk := dtoi(f[4], 0)
priority, _, priorityOk := dtoi(f[3], 0)
- weight, _, weightOk := dtoi(f[4], 0)
+ weight, _, weightOk := dtoi(f[2], 0)
if !(portOk && priorityOk && weightOk) {
continue
}
@@ -224,10 +224,10 @@ func lookupNS(name string) (ns []*NS, err error) {
}
for _, line := range lines {
f := getFields(line)
- if len(f) < 4 {
+ if len(f) < 3 {
continue
}
- ns = append(ns, &NS{f[3]})
+ ns = append(ns, &NS{f[2]})
}
return
}
diff --git a/libgo/go/net/lookup_unix.go b/libgo/go/net/lookup_unix.go
index fa98eed5f26..59e9f63210c 100644
--- a/libgo/go/net/lookup_unix.go
+++ b/libgo/go/net/lookup_unix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd linux netbsd openbsd
+// +build darwin dragonfly freebsd linux netbsd openbsd
package net
@@ -11,15 +11,11 @@ import (
"sync"
)
-var (
- protocols map[string]int
- onceReadProtocols sync.Once
-)
+var onceReadProtocols sync.Once
// readProtocols loads contents of /etc/protocols into protocols map
// for quick access.
func readProtocols() {
- protocols = make(map[string]int)
if file, err := open("/etc/protocols"); err == nil {
for line, ok := file.readLine(); ok; line, ok = file.readLine() {
// tcp 6 TCP # transmission control protocol
@@ -31,9 +27,13 @@ func readProtocols() {
continue
}
if proto, _, ok := dtoi(f[1], 0); ok {
- protocols[f[0]] = proto
+ if _, ok := protocols[f[0]]; !ok {
+ protocols[f[0]] = proto
+ }
for _, alias := range f[2:] {
- protocols[alias] = proto
+ if _, ok := protocols[alias]; !ok {
+ protocols[alias] = proto
+ }
}
}
}
diff --git a/libgo/go/net/lookup_windows.go b/libgo/go/net/lookup_windows.go
index 3b29724f27a..130364231d4 100644
--- a/libgo/go/net/lookup_windows.go
+++ b/libgo/go/net/lookup_windows.go
@@ -34,12 +34,19 @@ func lookupProtocol(name string) (proto int, err error) {
}
ch := make(chan result)
go func() {
+ acquireThread()
+ defer releaseThread()
runtime.LockOSThread()
defer runtime.UnlockOSThread()
proto, err := getprotobyname(name)
ch <- result{proto: proto, err: err}
}()
r := <-ch
+ if r.err != nil {
+ if proto, ok := protocols[name]; ok {
+ return proto, nil
+ }
+ }
return r.proto, r.err
}
@@ -56,6 +63,7 @@ func lookupHost(name string) (addrs []string, err error) {
}
func gethostbyname(name string) (addrs []IP, err error) {
+ // caller already acquired thread
h, err := syscall.GetHostByName(name)
if err != nil {
return nil, os.NewSyscallError("GetHostByName", err)
@@ -83,6 +91,8 @@ func oldLookupIP(name string) (addrs []IP, err error) {
}
ch := make(chan result)
go func() {
+ acquireThread()
+ defer releaseThread()
runtime.LockOSThread()
defer runtime.UnlockOSThread()
addrs, err := gethostbyname(name)
@@ -93,6 +103,8 @@ func oldLookupIP(name string) (addrs []IP, err error) {
}
func newLookupIP(name string) (addrs []IP, err error) {
+ acquireThread()
+ defer releaseThread()
hints := syscall.AddrinfoW{
Family: syscall.AF_UNSPEC,
Socktype: syscall.SOCK_STREAM,
@@ -122,6 +134,8 @@ func newLookupIP(name string) (addrs []IP, err error) {
}
func getservbyname(network, service string) (port int, err error) {
+ acquireThread()
+ defer releaseThread()
switch network {
case "tcp4", "tcp6":
network = "tcp"
@@ -144,6 +158,8 @@ func oldLookupPort(network, service string) (port int, err error) {
}
ch := make(chan result)
go func() {
+ acquireThread()
+ defer releaseThread()
runtime.LockOSThread()
defer runtime.UnlockOSThread()
port, err := getservbyname(network, service)
@@ -154,6 +170,8 @@ func oldLookupPort(network, service string) (port int, err error) {
}
func newLookupPort(network, service string) (port int, err error) {
+ acquireThread()
+ defer releaseThread()
var stype int32
switch network {
case "tcp4", "tcp6":
@@ -188,6 +206,8 @@ func newLookupPort(network, service string) (port int, err error) {
}
func lookupCNAME(name string) (cname string, err error) {
+ acquireThread()
+ defer releaseThread()
var r *syscall.DNSRecord
e := syscall.DnsQuery(name, syscall.DNS_TYPE_CNAME, 0, nil, &r, nil)
if e != nil {
@@ -202,6 +222,8 @@ func lookupCNAME(name string) (cname string, err error) {
}
func lookupSRV(service, proto, name string) (cname string, addrs []*SRV, err error) {
+ acquireThread()
+ defer releaseThread()
var target string
if service == "" && proto == "" {
target = name
@@ -224,6 +246,8 @@ func lookupSRV(service, proto, name string) (cname string, addrs []*SRV, err err
}
func lookupMX(name string) (mx []*MX, err error) {
+ acquireThread()
+ defer releaseThread()
var r *syscall.DNSRecord
e := syscall.DnsQuery(name, syscall.DNS_TYPE_MX, 0, nil, &r, nil)
if e != nil {
@@ -240,6 +264,8 @@ func lookupMX(name string) (mx []*MX, err error) {
}
func lookupNS(name string) (ns []*NS, err error) {
+ acquireThread()
+ defer releaseThread()
var r *syscall.DNSRecord
e := syscall.DnsQuery(name, syscall.DNS_TYPE_NS, 0, nil, &r, nil)
if e != nil {
@@ -255,6 +281,8 @@ func lookupNS(name string) (ns []*NS, err error) {
}
func lookupTXT(name string) (txt []string, err error) {
+ acquireThread()
+ defer releaseThread()
var r *syscall.DNSRecord
e := syscall.DnsQuery(name, syscall.DNS_TYPE_TEXT, 0, nil, &r, nil)
if e != nil {
@@ -273,6 +301,8 @@ func lookupTXT(name string) (txt []string, err error) {
}
func lookupAddr(addr string) (name []string, err error) {
+ acquireThread()
+ defer releaseThread()
arpa, err := reverseaddr(addr)
if err != nil {
return nil, err
diff --git a/libgo/go/net/mail/message.go b/libgo/go/net/mail/message.go
index 96c796e7804..dc2ab44dab2 100644
--- a/libgo/go/net/mail/message.go
+++ b/libgo/go/net/mail/message.go
@@ -342,7 +342,9 @@ func (p *addrParser) consumePhrase() (phrase string, err error) {
word, err = p.consumeQuotedString()
} else {
// atom
- word, err = p.consumeAtom(false)
+ // We actually parse dot-atom here to be more permissive
+ // than what RFC 5322 specifies.
+ word, err = p.consumeAtom(true)
}
// RFC 2047 encoded-word starts with =?, ends with ?=, and has two other ?s.
@@ -519,7 +521,7 @@ func isAtext(c byte, dot bool) bool {
return bytes.IndexByte(atextChars, c) >= 0
}
-// isQtext returns true if c is an RFC 5322 qtest character.
+// isQtext returns true if c is an RFC 5322 qtext character.
func isQtext(c byte) bool {
// Printable US-ASCII, excluding backslash or quote.
if c == '\\' || c == '"' {
diff --git a/libgo/go/net/mail/message_test.go b/libgo/go/net/mail/message_test.go
index 2e746f4a722..3c037f38385 100644
--- a/libgo/go/net/mail/message_test.go
+++ b/libgo/go/net/mail/message_test.go
@@ -225,6 +225,16 @@ func TestAddressParsing(t *testing.T) {
},
},
},
+ // Custom example with "." in name. For issue 4938
+ {
+ `Asem H. <noreply@example.com>`,
+ []*Address{
+ {
+ Name: `Asem H.`,
+ Address: "noreply@example.com",
+ },
+ },
+ },
}
for _, test := range tests {
if len(test.exp) == 1 {
diff --git a/libgo/go/net/mockicmp_test.go b/libgo/go/net/mockicmp_test.go
new file mode 100644
index 00000000000..e742365ea03
--- /dev/null
+++ b/libgo/go/net/mockicmp_test.go
@@ -0,0 +1,116 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package net
+
+import "errors"
+
+const (
+ icmpv4EchoRequest = 8
+ icmpv4EchoReply = 0
+ icmpv6EchoRequest = 128
+ icmpv6EchoReply = 129
+)
+
+// icmpMessage represents an ICMP message.
+type icmpMessage struct {
+ Type int // type
+ Code int // code
+ Checksum int // checksum
+ Body icmpMessageBody // body
+}
+
+// icmpMessageBody represents an ICMP message body.
+type icmpMessageBody interface {
+ Len() int
+ Marshal() ([]byte, error)
+}
+
+// Marshal returns the binary enconding of the ICMP echo request or
+// reply message m.
+func (m *icmpMessage) Marshal() ([]byte, error) {
+ b := []byte{byte(m.Type), byte(m.Code), 0, 0}
+ if m.Body != nil && m.Body.Len() != 0 {
+ mb, err := m.Body.Marshal()
+ if err != nil {
+ return nil, err
+ }
+ b = append(b, mb...)
+ }
+ switch m.Type {
+ case icmpv6EchoRequest, icmpv6EchoReply:
+ return b, nil
+ }
+ csumcv := len(b) - 1 // checksum coverage
+ s := uint32(0)
+ for i := 0; i < csumcv; i += 2 {
+ s += uint32(b[i+1])<<8 | uint32(b[i])
+ }
+ if csumcv&1 == 0 {
+ s += uint32(b[csumcv])
+ }
+ s = s>>16 + s&0xffff
+ s = s + s>>16
+ // Place checksum back in header; using ^= avoids the
+ // assumption the checksum bytes are zero.
+ b[2] ^= byte(^s)
+ b[3] ^= byte(^s >> 8)
+ return b, nil
+}
+
+// parseICMPMessage parses b as an ICMP message.
+func parseICMPMessage(b []byte) (*icmpMessage, error) {
+ msglen := len(b)
+ if msglen < 4 {
+ return nil, errors.New("message too short")
+ }
+ m := &icmpMessage{Type: int(b[0]), Code: int(b[1]), Checksum: int(b[2])<<8 | int(b[3])}
+ if msglen > 4 {
+ var err error
+ switch m.Type {
+ case icmpv4EchoRequest, icmpv4EchoReply, icmpv6EchoRequest, icmpv6EchoReply:
+ m.Body, err = parseICMPEcho(b[4:])
+ if err != nil {
+ return nil, err
+ }
+ }
+ }
+ return m, nil
+}
+
+// imcpEcho represenets an ICMP echo request or reply message body.
+type icmpEcho struct {
+ ID int // identifier
+ Seq int // sequence number
+ Data []byte // data
+}
+
+func (p *icmpEcho) Len() int {
+ if p == nil {
+ return 0
+ }
+ return 4 + len(p.Data)
+}
+
+// Marshal returns the binary enconding of the ICMP echo request or
+// reply message body p.
+func (p *icmpEcho) Marshal() ([]byte, error) {
+ b := make([]byte, 4+len(p.Data))
+ b[0], b[1] = byte(p.ID>>8), byte(p.ID)
+ b[2], b[3] = byte(p.Seq>>8), byte(p.Seq)
+ copy(b[4:], p.Data)
+ return b, nil
+}
+
+// parseICMPEcho parses b as an ICMP echo request or reply message
+// body.
+func parseICMPEcho(b []byte) (*icmpEcho, error) {
+ bodylen := len(b)
+ p := &icmpEcho{ID: int(b[0])<<8 | int(b[1]), Seq: int(b[2])<<8 | int(b[3])}
+ if bodylen > 4 {
+ p.Data = make([]byte, bodylen-4)
+ copy(p.Data, b[4:])
+ }
+ return p, nil
+}
diff --git a/libgo/go/net/mockserver_test.go b/libgo/go/net/mockserver_test.go
new file mode 100644
index 00000000000..68ded5d7577
--- /dev/null
+++ b/libgo/go/net/mockserver_test.go
@@ -0,0 +1,82 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package net
+
+import "sync"
+
+type streamListener struct {
+ net, addr string
+ ln Listener
+}
+
+type dualStackServer struct {
+ lnmu sync.RWMutex
+ lns []streamListener
+ port string
+
+ cmu sync.RWMutex
+ cs []Conn // established connections at the passive open side
+}
+
+func (dss *dualStackServer) buildup(server func(*dualStackServer, Listener)) error {
+ for i := range dss.lns {
+ go server(dss, dss.lns[i].ln)
+ }
+ return nil
+}
+
+func (dss *dualStackServer) putConn(c Conn) error {
+ dss.cmu.Lock()
+ dss.cs = append(dss.cs, c)
+ dss.cmu.Unlock()
+ return nil
+}
+
+func (dss *dualStackServer) teardownNetwork(net string) error {
+ dss.lnmu.Lock()
+ for i := range dss.lns {
+ if net == dss.lns[i].net && dss.lns[i].ln != nil {
+ dss.lns[i].ln.Close()
+ dss.lns[i].ln = nil
+ }
+ }
+ dss.lnmu.Unlock()
+ return nil
+}
+
+func (dss *dualStackServer) teardown() error {
+ dss.lnmu.Lock()
+ for i := range dss.lns {
+ if dss.lns[i].ln != nil {
+ dss.lns[i].ln.Close()
+ }
+ }
+ dss.lnmu.Unlock()
+ dss.cmu.Lock()
+ for _, c := range dss.cs {
+ c.Close()
+ }
+ dss.cmu.Unlock()
+ return nil
+}
+
+func newDualStackServer(lns []streamListener) (*dualStackServer, error) {
+ dss := &dualStackServer{lns: lns, port: "0"}
+ for i := range dss.lns {
+ ln, err := Listen(dss.lns[i].net, dss.lns[i].addr+":"+dss.port)
+ if err != nil {
+ dss.teardown()
+ return nil, err
+ }
+ dss.lns[i].ln = ln
+ if dss.port == "0" {
+ if _, dss.port, err = SplitHostPort(ln.Addr().String()); err != nil {
+ dss.teardown()
+ return nil, err
+ }
+ }
+ }
+ return dss, nil
+}
diff --git a/libgo/go/net/multicast_test.go b/libgo/go/net/multicast_test.go
index 8ff02a3c933..5660fd42f8c 100644
--- a/libgo/go/net/multicast_test.go
+++ b/libgo/go/net/multicast_test.go
@@ -158,7 +158,7 @@ func checkMulticastListener(c *UDPConn, ip IP) error {
func multicastRIBContains(ip IP) (bool, error) {
switch runtime.GOOS {
- case "netbsd", "openbsd", "plan9", "solaris", "windows":
+ case "dragonfly", "netbsd", "openbsd", "plan9", "solaris", "windows":
return true, nil // not implemented yet
case "linux":
if runtime.GOARCH == "arm" || runtime.GOARCH == "alpha" {
diff --git a/libgo/go/net/net.go b/libgo/go/net/net.go
index 72b2b646c48..2e6db555143 100644
--- a/libgo/go/net/net.go
+++ b/libgo/go/net/net.go
@@ -46,7 +46,6 @@ import (
"errors"
"io"
"os"
- "sync"
"syscall"
"time"
)
@@ -160,7 +159,7 @@ func (c *conn) SetDeadline(t time.Time) error {
if !c.ok() {
return syscall.EINVAL
}
- return setDeadline(c.fd, t)
+ return c.fd.setDeadline(t)
}
// SetReadDeadline implements the Conn SetReadDeadline method.
@@ -168,7 +167,7 @@ func (c *conn) SetReadDeadline(t time.Time) error {
if !c.ok() {
return syscall.EINVAL
}
- return setReadDeadline(c.fd, t)
+ return c.fd.setReadDeadline(t)
}
// SetWriteDeadline implements the Conn SetWriteDeadline method.
@@ -176,7 +175,7 @@ func (c *conn) SetWriteDeadline(t time.Time) error {
if !c.ok() {
return syscall.EINVAL
}
- return setWriteDeadline(c.fd, t)
+ return c.fd.setWriteDeadline(t)
}
// SetReadBuffer sets the size of the operating system's
@@ -259,6 +258,8 @@ type PacketConn interface {
SetWriteDeadline(t time.Time) error
}
+var listenerBacklog = maxListenerBacklog()
+
// A Listener is a generic network listener for stream-oriented protocols.
//
// Multiple goroutines may invoke methods on a Listener simultaneously.
@@ -370,6 +371,12 @@ func (e UnknownNetworkError) Error() string { return "unknown network " + stri
func (e UnknownNetworkError) Temporary() bool { return false }
func (e UnknownNetworkError) Timeout() bool { return false }
+type InvalidAddrError string
+
+func (e InvalidAddrError) Error() string { return string(e) }
+func (e InvalidAddrError) Timeout() bool { return false }
+func (e InvalidAddrError) Temporary() bool { return false }
+
// DNSConfigError represents an error reading the machine's DNS configuration.
type DNSConfigError struct {
Err error
@@ -393,35 +400,22 @@ func genericReadFrom(w io.Writer, r io.Reader) (n int64, err error) {
return io.Copy(writerOnly{w}, r)
}
-// deadline is an atomically-accessed number of nanoseconds since 1970
-// or 0, if no deadline is set.
-type deadline struct {
- sync.Mutex
- val int64
-}
+// Limit the number of concurrent cgo-using goroutines, because
+// each will block an entire operating system thread. The usual culprit
+// is resolving many DNS names in separate goroutines but the DNS
+// server is not responding. Then the many lookups each use a different
+// thread, and the system or the program runs out of threads.
-func (d *deadline) expired() bool {
- t := d.value()
- return t > 0 && time.Now().UnixNano() >= t
-}
+var threadLimit = make(chan struct{}, 500)
-func (d *deadline) value() (v int64) {
- d.Lock()
- v = d.val
- d.Unlock()
- return
-}
+// Using send for acquire is fine here because we are not using this
+// to protect any memory. All we care about is the number of goroutines
+// making calls at a time.
-func (d *deadline) set(v int64) {
- d.Lock()
- d.val = v
- d.Unlock()
+func acquireThread() {
+ threadLimit <- struct{}{}
}
-func (d *deadline) setTime(t time.Time) {
- if t.IsZero() {
- d.set(0)
- } else {
- d.set(t.UnixNano())
- }
+func releaseThread() {
+ <-threadLimit
}
diff --git a/libgo/go/net/net_test.go b/libgo/go/net/net_test.go
index 1a512a5b110..1320096df8f 100644
--- a/libgo/go/net/net_test.go
+++ b/libgo/go/net/net_test.go
@@ -25,6 +25,7 @@ func TestShutdown(t *testing.T) {
}
go func() {
+ defer ln.Close()
c, err := ln.Accept()
if err != nil {
t.Fatalf("Accept: %v", err)
@@ -75,7 +76,10 @@ func TestShutdownUnix(t *testing.T) {
if err != nil {
t.Fatalf("ListenUnix on %s: %s", tmpname, err)
}
- defer os.Remove(tmpname)
+ defer func() {
+ ln.Close()
+ os.Remove(tmpname)
+ }()
go func() {
c, err := ln.Accept()
@@ -214,3 +218,41 @@ func TestTCPClose(t *testing.T) {
t.Fatal(err)
}
}
+
+func TestErrorNil(t *testing.T) {
+ c, err := Dial("tcp", "127.0.0.1:65535")
+ if err == nil {
+ t.Fatal("Dial 127.0.0.1:65535 succeeded")
+ }
+ if c != nil {
+ t.Fatalf("Dial returned non-nil interface %T(%v) with err != nil", c, c)
+ }
+
+ // Make Listen fail by relistening on the same address.
+ l, err := Listen("tcp", "127.0.0.1:0")
+ if err != nil {
+ t.Fatal("Listen 127.0.0.1:0: %v", err)
+ }
+ defer l.Close()
+ l1, err := Listen("tcp", l.Addr().String())
+ if err == nil {
+ t.Fatal("second Listen %v: %v", l.Addr(), err)
+ }
+ if l1 != nil {
+ t.Fatalf("Listen returned non-nil interface %T(%v) with err != nil", l1, l1)
+ }
+
+ // Make ListenPacket fail by relistening on the same address.
+ lp, err := ListenPacket("udp", "127.0.0.1:0")
+ if err != nil {
+ t.Fatal("Listen 127.0.0.1:0: %v", err)
+ }
+ defer lp.Close()
+ lp1, err := ListenPacket("udp", lp.LocalAddr().String())
+ if err == nil {
+ t.Fatal("second Listen %v: %v", lp.LocalAddr(), err)
+ }
+ if lp1 != nil {
+ t.Fatalf("ListenPacket returned non-nil interface %T(%v) with err != nil", lp1, lp1)
+ }
+}
diff --git a/libgo/go/net/packetconn_test.go b/libgo/go/net/packetconn_test.go
index ec5dd710f55..945003f67ad 100644
--- a/libgo/go/net/packetconn_test.go
+++ b/libgo/go/net/packetconn_test.go
@@ -21,6 +21,45 @@ func strfunc(s string) func() string {
}
}
+func packetConnTestData(t *testing.T, net string, i int) ([]byte, func()) {
+ switch net {
+ case "udp":
+ return []byte("UDP PACKETCONN TEST"), nil
+ case "ip":
+ if skip, skipmsg := skipRawSocketTest(t); skip {
+ return nil, func() {
+ t.Logf(skipmsg)
+ }
+ }
+ b, err := (&icmpMessage{
+ Type: icmpv4EchoRequest, Code: 0,
+ Body: &icmpEcho{
+ ID: os.Getpid() & 0xffff, Seq: i + 1,
+ Data: []byte("IP PACKETCONN TEST"),
+ },
+ }).Marshal()
+ if err != nil {
+ return nil, func() {
+ t.Fatalf("icmpMessage.Marshal failed: %v", err)
+ }
+ }
+ return b, nil
+ case "unixgram":
+ switch runtime.GOOS {
+ case "plan9", "windows":
+ return nil, func() {
+ t.Logf("skipping %q test on %q", net, runtime.GOOS)
+ }
+ default:
+ return []byte("UNIXGRAM PACKETCONN TEST"), nil
+ }
+ default:
+ return nil, func() {
+ t.Logf("skipping %q test", net)
+ }
+ }
+}
+
var packetConnTests = []struct {
net string
addr1 func() string
@@ -42,37 +81,10 @@ func TestPacketConn(t *testing.T) {
}
for i, tt := range packetConnTests {
- var wb []byte
netstr := strings.Split(tt.net, ":")
- switch netstr[0] {
- case "udp":
- wb = []byte("UDP PACKETCONN TEST")
- case "ip":
- switch runtime.GOOS {
- case "plan9":
- continue
- }
- if os.Getuid() != 0 {
- continue
- }
- var err error
- wb, err = (&icmpMessage{
- Type: icmpv4EchoRequest, Code: 0,
- Body: &icmpEcho{
- ID: os.Getpid() & 0xffff, Seq: i + 1,
- Data: []byte("IP PACKETCONN TEST"),
- },
- }).Marshal()
- if err != nil {
- t.Fatalf("icmpMessage.Marshal failed: %v", err)
- }
- case "unixgram":
- switch runtime.GOOS {
- case "plan9", "windows":
- continue
- }
- wb = []byte("UNIXGRAM PACKETCONN TEST")
- default:
+ wb, skipOrFatalFn := packetConnTestData(t, netstr[0], i)
+ if skipOrFatalFn != nil {
+ skipOrFatalFn()
continue
}
@@ -127,35 +139,9 @@ func TestConnAndPacketConn(t *testing.T) {
for i, tt := range packetConnTests {
var wb []byte
netstr := strings.Split(tt.net, ":")
- switch netstr[0] {
- case "udp":
- wb = []byte("UDP PACKETCONN TEST")
- case "ip":
- switch runtime.GOOS {
- case "plan9":
- continue
- }
- if os.Getuid() != 0 {
- continue
- }
- var err error
- wb, err = (&icmpMessage{
- Type: icmpv4EchoRequest, Code: 0,
- Body: &icmpEcho{
- ID: os.Getpid() & 0xffff, Seq: i + 1,
- Data: []byte("IP PACKETCONN TEST"),
- },
- }).Marshal()
- if err != nil {
- t.Fatalf("icmpMessage.Marshal failed: %v", err)
- }
- case "unixgram":
- switch runtime.GOOS {
- case "plan9", "windows":
- continue
- }
- wb = []byte("UNIXGRAM PACKETCONN TEST")
- default:
+ wb, skipOrFatalFn := packetConnTestData(t, netstr[0], i)
+ if skipOrFatalFn != nil {
+ skipOrFatalFn()
continue
}
@@ -186,7 +172,7 @@ func TestConnAndPacketConn(t *testing.T) {
}
rb1 := make([]byte, 128)
if _, _, err := c1.ReadFrom(rb1); err != nil {
- t.Fatalf("PacetConn.ReadFrom failed: %v", err)
+ t.Fatalf("PacketConn.ReadFrom failed: %v", err)
}
var dst Addr
switch netstr[0] {
diff --git a/libgo/go/net/parse_test.go b/libgo/go/net/parse_test.go
index 9df0c534b33..b86bc32884b 100644
--- a/libgo/go/net/parse_test.go
+++ b/libgo/go/net/parse_test.go
@@ -23,12 +23,14 @@ func TestReadLine(t *testing.T) {
if err != nil {
t.Fatalf("open %s: %v", filename, err)
}
+ defer fd.Close()
br := bufio.NewReader(fd)
file, err := open(filename)
if file == nil {
t.Fatalf("net.open(%s) = nil", filename)
}
+ defer file.close()
lineno := 1
byteno := 0
diff --git a/libgo/go/net/port_unix.go b/libgo/go/net/port_unix.go
index 16780da1160..3cd9ca2aa71 100644
--- a/libgo/go/net/port_unix.go
+++ b/libgo/go/net/port_unix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd linux netbsd openbsd
+// +build darwin dragonfly freebsd linux netbsd openbsd
// Read system port mappings from /etc/services
diff --git a/libgo/go/net/protoconn_test.go b/libgo/go/net/protoconn_test.go
index b59925e01c1..5a8958b0866 100644
--- a/libgo/go/net/protoconn_test.go
+++ b/libgo/go/net/protoconn_test.go
@@ -103,6 +103,7 @@ func TestTCPConnSpecificMethods(t *testing.T) {
}
defer c.Close()
c.SetKeepAlive(false)
+ c.SetKeepAlivePeriod(3 * time.Second)
c.SetLinger(0)
c.SetNoDelay(false)
c.LocalAddr()
@@ -160,15 +161,20 @@ func TestUDPConnSpecificMethods(t *testing.T) {
} else {
f.Close()
}
+
+ defer func() {
+ if p := recover(); p != nil {
+ t.Fatalf("UDPConn.WriteToUDP or WriteMsgUDP panicked: %v", p)
+ }
+ }()
+
+ c.WriteToUDP(wb, nil)
+ c.WriteMsgUDP(wb, nil, nil)
}
func TestIPConnSpecificMethods(t *testing.T) {
- switch runtime.GOOS {
- case "plan9":
- t.Skipf("skipping test on %q", runtime.GOOS)
- }
- if os.Getuid() != 0 {
- t.Skipf("skipping test; must be root")
+ if skip, skipmsg := skipRawSocketTest(t); skip {
+ t.Skip(skipmsg)
}
la, err := ResolveIPAddr("ip4", "127.0.0.1")
@@ -198,7 +204,7 @@ func TestIPConnSpecificMethods(t *testing.T) {
if err != nil {
t.Fatalf("icmpMessage.Marshal failed: %v", err)
}
- rb := make([]byte, 20+128)
+ rb := make([]byte, 20+len(wb))
if _, err := c.WriteToIP(wb, c.LocalAddr().(*IPAddr)); err != nil {
t.Fatalf("IPConn.WriteToIP failed: %v", err)
}
@@ -217,6 +223,15 @@ func TestIPConnSpecificMethods(t *testing.T) {
} else {
f.Close()
}
+
+ defer func() {
+ if p := recover(); p != nil {
+ t.Fatalf("IPConn.WriteToIP or WriteMsgIP panicked: %v", p)
+ }
+ }()
+
+ c.WriteToIP(wb, nil)
+ c.WriteMsgIP(wb, nil, nil)
}
func TestUnixListenerSpecificMethods(t *testing.T) {
@@ -357,4 +372,15 @@ func TestUnixConnSpecificMethods(t *testing.T) {
} else {
f.Close()
}
+
+ defer func() {
+ if p := recover(); p != nil {
+ t.Fatalf("UnixConn.WriteToUnix or WriteMsgUnix panicked: %v", p)
+ }
+ }()
+
+ c1.WriteToUnix(wb, nil)
+ c1.WriteMsgUnix(wb, nil, nil)
+ c3.WriteToUnix(wb, nil)
+ c3.WriteMsgUnix(wb, nil, nil)
}
diff --git a/libgo/go/net/race.go b/libgo/go/net/race.go
new file mode 100644
index 00000000000..2f02a6c226b
--- /dev/null
+++ b/libgo/go/net/race.go
@@ -0,0 +1,31 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build race
+// +build windows
+
+package net
+
+import (
+ "runtime"
+ "unsafe"
+)
+
+const raceenabled = true
+
+func raceAcquire(addr unsafe.Pointer) {
+ runtime.RaceAcquire(addr)
+}
+
+func raceReleaseMerge(addr unsafe.Pointer) {
+ runtime.RaceReleaseMerge(addr)
+}
+
+func raceReadRange(addr unsafe.Pointer, len int) {
+ runtime.RaceReadRange(addr, len)
+}
+
+func raceWriteRange(addr unsafe.Pointer, len int) {
+ runtime.RaceWriteRange(addr, len)
+}
diff --git a/libgo/go/net/race0.go b/libgo/go/net/race0.go
new file mode 100644
index 00000000000..f5042977931
--- /dev/null
+++ b/libgo/go/net/race0.go
@@ -0,0 +1,26 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !race
+// +build windows
+
+package net
+
+import (
+ "unsafe"
+)
+
+const raceenabled = false
+
+func raceAcquire(addr unsafe.Pointer) {
+}
+
+func raceReleaseMerge(addr unsafe.Pointer) {
+}
+
+func raceReadRange(addr unsafe.Pointer, len int) {
+}
+
+func raceWriteRange(addr unsafe.Pointer, len int) {
+}
diff --git a/libgo/go/net/rpc/client.go b/libgo/go/net/rpc/client.go
index 4b0c9c3bba2..c524d0a0a2d 100644
--- a/libgo/go/net/rpc/client.go
+++ b/libgo/go/net/rpc/client.go
@@ -58,6 +58,7 @@ type Client struct {
// argument to force the body of the response to be read and then
// discarded.
type ClientCodec interface {
+ // WriteRequest must be safe for concurrent use by multiple goroutines.
WriteRequest(*Request, interface{}) error
ReadResponseHeader(*Response) error
ReadResponseBody(interface{}) error
@@ -160,7 +161,7 @@ func (client *Client) input() {
}
client.mutex.Unlock()
client.sending.Unlock()
- if err != io.EOF && !closing {
+ if debugLog && err != io.EOF && !closing {
log.Println("rpc: client protocol error:", err)
}
}
@@ -172,7 +173,9 @@ func (call *Call) done() {
default:
// We don't want to block here. It is the caller's responsibility to make
// sure the channel has enough buffer space. See comment in Go().
- log.Println("rpc: discarding Call reply due to insufficient Done chan capacity")
+ if debugLog {
+ log.Println("rpc: discarding Call reply due to insufficient Done chan capacity")
+ }
}
}
diff --git a/libgo/go/net/rpc/debug.go b/libgo/go/net/rpc/debug.go
index 663663fe941..926466d6255 100644
--- a/libgo/go/net/rpc/debug.go
+++ b/libgo/go/net/rpc/debug.go
@@ -38,6 +38,9 @@ const debugText = `<html>
var debug = template.Must(template.New("RPC debug").Parse(debugText))
+// If set, print log statements for internal and I/O errors.
+var debugLog = false
+
type debugMethod struct {
Type *methodType
Name string
diff --git a/libgo/go/net/rpc/jsonrpc/server.go b/libgo/go/net/rpc/jsonrpc/server.go
index 5bc05fd0a71..16ec0fe9ad5 100644
--- a/libgo/go/net/rpc/jsonrpc/server.go
+++ b/libgo/go/net/rpc/jsonrpc/server.go
@@ -20,8 +20,7 @@ type serverCodec struct {
c io.Closer
// temporary work space
- req serverRequest
- resp serverResponse
+ req serverRequest
// JSON-RPC clients can use arbitrary json values as request IDs.
// Package rpc expects uint64 request IDs.
diff --git a/libgo/go/net/rpc/server.go b/libgo/go/net/rpc/server.go
index e71b6fb1a43..7eb2dcf5a9f 100644
--- a/libgo/go/net/rpc/server.go
+++ b/libgo/go/net/rpc/server.go
@@ -247,10 +247,12 @@ func (server *Server) register(rcvr interface{}, name string, useName bool) erro
sname = name
}
if sname == "" {
- log.Fatal("rpc: no service name for type", s.typ.String())
+ s := "rpc.Register: no service name for type " + s.typ.String()
+ log.Print(s)
+ return errors.New(s)
}
if !isExported(sname) && !useName {
- s := "rpc Register: type " + sname + " is not exported"
+ s := "rpc.Register: type " + sname + " is not exported"
log.Print(s)
return errors.New(s)
}
@@ -258,13 +260,13 @@ func (server *Server) register(rcvr interface{}, name string, useName bool) erro
return errors.New("rpc: service already defined: " + sname)
}
s.name = sname
- s.method = make(map[string]*methodType)
// Install the methods
s.method = suitableMethods(s.typ, true)
if len(s.method) == 0 {
str := ""
+
// To help the user, see if a pointer receiver would work.
method := suitableMethods(reflect.PtrTo(s.typ), false)
if len(method) != 0 {
@@ -356,7 +358,7 @@ func (server *Server) sendResponse(sending *sync.Mutex, req *Request, reply inte
resp.Seq = req.Seq
sending.Lock()
err := codec.WriteResponse(resp, reply)
- if err != nil {
+ if debugLog && err != nil {
log.Println("rpc: writing response:", err)
}
sending.Unlock()
@@ -434,7 +436,7 @@ func (server *Server) ServeCodec(codec ServerCodec) {
for {
service, mtype, req, argv, replyv, keepReading, err := server.readRequest(codec)
if err != nil {
- if err != io.EOF {
+ if debugLog && err != io.EOF {
log.Println("rpc:", err)
}
if !keepReading {
@@ -560,20 +562,23 @@ func (server *Server) readRequestHeader(codec ServerCodec) (service *service, mt
// we can still recover and move on to the next request.
keepReading = true
- serviceMethod := strings.Split(req.ServiceMethod, ".")
- if len(serviceMethod) != 2 {
+ dot := strings.LastIndex(req.ServiceMethod, ".")
+ if dot < 0 {
err = errors.New("rpc: service/method request ill-formed: " + req.ServiceMethod)
return
}
+ serviceName := req.ServiceMethod[:dot]
+ methodName := req.ServiceMethod[dot+1:]
+
// Look up the request.
server.mu.RLock()
- service = server.serviceMap[serviceMethod[0]]
+ service = server.serviceMap[serviceName]
server.mu.RUnlock()
if service == nil {
err = errors.New("rpc: can't find service " + req.ServiceMethod)
return
}
- mtype = service.method[serviceMethod[1]]
+ mtype = service.method[methodName]
if mtype == nil {
err = errors.New("rpc: can't find method " + req.ServiceMethod)
}
@@ -612,6 +617,7 @@ func RegisterName(name string, rcvr interface{}) error {
type ServerCodec interface {
ReadRequestHeader(*Request) error
ReadRequestBody(interface{}) error
+ // WriteResponse must be safe for concurrent use by multiple goroutines.
WriteResponse(*Response, interface{}) error
Close() error
diff --git a/libgo/go/net/rpc/server_test.go b/libgo/go/net/rpc/server_test.go
index eb17210abc9..3b9a88380cf 100644
--- a/libgo/go/net/rpc/server_test.go
+++ b/libgo/go/net/rpc/server_test.go
@@ -84,6 +84,7 @@ func listenTCP() (net.Listener, string) {
func startServer() {
Register(new(Arith))
+ RegisterName("net.rpc.Arith", new(Arith))
var l net.Listener
l, serverAddr = listenTCP()
@@ -97,11 +98,13 @@ func startServer() {
func startNewServer() {
newServer = NewServer()
newServer.Register(new(Arith))
+ newServer.RegisterName("net.rpc.Arith", new(Arith))
+ newServer.RegisterName("newServer.Arith", new(Arith))
var l net.Listener
l, newServerAddr = listenTCP()
log.Println("NewServer test RPC server listening on", newServerAddr)
- go Accept(l)
+ go newServer.Accept(l)
newServer.HandleHTTP(newHttpPath, "/bar")
httpOnce.Do(startHttpServer)
@@ -118,6 +121,7 @@ func TestRPC(t *testing.T) {
testRPC(t, serverAddr)
newOnce.Do(startNewServer)
testRPC(t, newServerAddr)
+ testNewServerRPC(t, newServerAddr)
}
func testRPC(t *testing.T, addr string) {
@@ -125,6 +129,7 @@ func testRPC(t *testing.T, addr string) {
if err != nil {
t.Fatal("dialing", err)
}
+ defer client.Close()
// Synchronous calls
args := &Args{7, 8}
@@ -233,6 +238,36 @@ func testRPC(t *testing.T, addr string) {
if reply.C != args.A*args.B {
t.Errorf("Mul: expected %d got %d", reply.C, args.A*args.B)
}
+
+ // ServiceName contain "." character
+ args = &Args{7, 8}
+ reply = new(Reply)
+ err = client.Call("net.rpc.Arith.Add", args, reply)
+ if err != nil {
+ t.Errorf("Add: expected no error but got string %q", err.Error())
+ }
+ if reply.C != args.A+args.B {
+ t.Errorf("Add: expected %d got %d", reply.C, args.A+args.B)
+ }
+}
+
+func testNewServerRPC(t *testing.T, addr string) {
+ client, err := Dial("tcp", addr)
+ if err != nil {
+ t.Fatal("dialing", err)
+ }
+ defer client.Close()
+
+ // Synchronous calls
+ args := &Args{7, 8}
+ reply := new(Reply)
+ err = client.Call("newServer.Arith.Add", args, reply)
+ if err != nil {
+ t.Errorf("Add: expected no error but got string %q", err.Error())
+ }
+ if reply.C != args.A+args.B {
+ t.Errorf("Add: expected %d got %d", reply.C, args.A+args.B)
+ }
}
func TestHTTP(t *testing.T) {
@@ -253,6 +288,7 @@ func testHTTPRPC(t *testing.T, path string) {
if err != nil {
t.Fatal("dialing", err)
}
+ defer client.Close()
// Synchronous calls
args := &Args{7, 8}
@@ -329,6 +365,7 @@ func TestServeRequest(t *testing.T) {
func testServeRequest(t *testing.T, server *Server) {
client := CodecEmulator{server: server}
+ defer client.Close()
args := &Args{7, 8}
reply := new(Reply)
@@ -411,6 +448,7 @@ func (WriteFailCodec) Close() error {
func TestSendDeadlock(t *testing.T) {
client := NewClientWithCodec(WriteFailCodec(0))
+ defer client.Close()
done := make(chan bool)
go func() {
@@ -449,6 +487,8 @@ func countMallocs(dial func() (*Client, error), t *testing.T) float64 {
if err != nil {
t.Fatal("error dialing", err)
}
+ defer client.Close()
+
args := &Args{7, 8}
reply := new(Reply)
return testing.AllocsPerRun(100, func() {
@@ -463,6 +503,9 @@ func countMallocs(dial func() (*Client, error), t *testing.T) float64 {
}
func TestCountMallocs(t *testing.T) {
+ if testing.Short() {
+ t.Skip("skipping malloc count in short mode")
+ }
if runtime.GOMAXPROCS(0) > 1 {
t.Skip("skipping; GOMAXPROCS>1")
}
@@ -470,6 +513,9 @@ func TestCountMallocs(t *testing.T) {
}
func TestCountMallocsOverHTTP(t *testing.T) {
+ if testing.Short() {
+ t.Skip("skipping malloc count in short mode")
+ }
if runtime.GOMAXPROCS(0) > 1 {
t.Skip("skipping; GOMAXPROCS>1")
}
@@ -496,6 +542,8 @@ func (writeCrasher) Write(p []byte) (int, error) {
func TestClientWriteError(t *testing.T) {
w := &writeCrasher{done: make(chan bool)}
c := NewClient(w)
+ defer c.Close()
+
res := false
err := c.Call("foo", 1, &res)
if err == nil {
@@ -552,6 +600,7 @@ func benchmarkEndToEnd(dial func() (*Client, error), b *testing.B) {
if err != nil {
b.Fatal("error dialing:", err)
}
+ defer client.Close()
// Synchronous calls
args := &Args{7, 8}
@@ -587,6 +636,7 @@ func benchmarkEndToEndAsync(dial func() (*Client, error), b *testing.B) {
if err != nil {
b.Fatal("error dialing:", err)
}
+ defer client.Close()
// Asynchronous calls
args := &Args{7, 8}
diff --git a/libgo/go/net/sendfile_dragonfly.go b/libgo/go/net/sendfile_dragonfly.go
new file mode 100644
index 00000000000..a2219c16337
--- /dev/null
+++ b/libgo/go/net/sendfile_dragonfly.go
@@ -0,0 +1,103 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package net
+
+import (
+ "io"
+ "os"
+ "syscall"
+)
+
+// maxSendfileSize is the largest chunk size we ask the kernel to copy
+// at a time.
+const maxSendfileSize int = 4 << 20
+
+// sendFile copies the contents of r to c using the sendfile
+// system call to minimize copies.
+//
+// if handled == true, sendFile returns the number of bytes copied and any
+// non-EOF error.
+//
+// if handled == false, sendFile performed no work.
+func sendFile(c *netFD, r io.Reader) (written int64, err error, handled bool) {
+ // DragonFly uses 0 as the "until EOF" value. If you pass in more bytes than the
+ // file contains, it will loop back to the beginning ad nauseum until it's sent
+ // exactly the number of bytes told to. As such, we need to know exactly how many
+ // bytes to send.
+ var remain int64 = 0
+
+ lr, ok := r.(*io.LimitedReader)
+ if ok {
+ remain, r = lr.N, lr.R
+ if remain <= 0 {
+ return 0, nil, true
+ }
+ }
+ f, ok := r.(*os.File)
+ if !ok {
+ return 0, nil, false
+ }
+
+ if remain == 0 {
+ fi, err := f.Stat()
+ if err != nil {
+ return 0, err, false
+ }
+
+ remain = fi.Size()
+ }
+
+ // The other quirk with DragonFly's sendfile implementation is that it doesn't
+ // use the current position of the file -- if you pass it offset 0, it starts
+ // from offset 0. There's no way to tell it "start from current position", so
+ // we have to manage that explicitly.
+ pos, err := f.Seek(0, os.SEEK_CUR)
+ if err != nil {
+ return 0, err, false
+ }
+
+ if err := c.writeLock(); err != nil {
+ return 0, err, true
+ }
+ defer c.writeUnlock()
+
+ dst := c.sysfd
+ src := int(f.Fd())
+ for remain > 0 {
+ n := maxSendfileSize
+ if int64(n) > remain {
+ n = int(remain)
+ }
+ pos1 := pos
+ n, err1 := syscall.Sendfile(dst, src, &pos1, n)
+ if n > 0 {
+ pos += int64(n)
+ written += int64(n)
+ remain -= int64(n)
+ }
+ if n == 0 && err1 == nil {
+ break
+ }
+ if err1 == syscall.EAGAIN {
+ if err1 = c.pd.WaitWrite(); err1 == nil {
+ continue
+ }
+ }
+ if err1 == syscall.EINTR {
+ continue
+ }
+ if err1 != nil {
+ // This includes syscall.ENOSYS (no kernel
+ // support) and syscall.EINVAL (fd types which
+ // don't implement sendfile together)
+ err = &OpError{"sendfile", c.net, c.raddr, err1}
+ break
+ }
+ }
+ if lr != nil {
+ lr.N = remain
+ }
+ return written, err, written > 0
+}
diff --git a/libgo/go/net/sendfile_freebsd.go b/libgo/go/net/sendfile_freebsd.go
index dc5b767557b..42fe799efbd 100644
--- a/libgo/go/net/sendfile_freebsd.go
+++ b/libgo/go/net/sendfile_freebsd.go
@@ -58,12 +58,10 @@ func sendFile(c *netFD, r io.Reader) (written int64, err error, handled bool) {
return 0, err, false
}
- c.wio.Lock()
- defer c.wio.Unlock()
- if err := c.incref(false); err != nil {
+ if err := c.writeLock(); err != nil {
return 0, err, true
}
- defer c.decref()
+ defer c.writeUnlock()
dst := c.sysfd
src := int(f.Fd())
diff --git a/libgo/go/net/sendfile_linux.go b/libgo/go/net/sendfile_linux.go
index 6f1323b3dcd..5e117636a80 100644
--- a/libgo/go/net/sendfile_linux.go
+++ b/libgo/go/net/sendfile_linux.go
@@ -36,12 +36,10 @@ func sendFile(c *netFD, r io.Reader) (written int64, err error, handled bool) {
return 0, nil, false
}
- c.wio.Lock()
- defer c.wio.Unlock()
- if err := c.incref(false); err != nil {
+ if err := c.writeLock(); err != nil {
return 0, err, true
}
- defer c.decref()
+ defer c.writeUnlock()
dst := c.sysfd
src := int(f.Fd())
diff --git a/libgo/go/net/sendfile_windows.go b/libgo/go/net/sendfile_windows.go
index 2d64f2f5bff..b128ba27b00 100644
--- a/libgo/go/net/sendfile_windows.go
+++ b/libgo/go/net/sendfile_windows.go
@@ -10,20 +10,6 @@ import (
"syscall"
)
-type sendfileOp struct {
- anOp
- src syscall.Handle // source
- n uint32
-}
-
-func (o *sendfileOp) Submit() (err error) {
- return syscall.TransmitFile(o.fd.sysfd, o.src, o.n, 0, &o.o, nil, syscall.TF_WRITE_BEHIND)
-}
-
-func (o *sendfileOp) Name() string {
- return "TransmitFile"
-}
-
// sendFile copies the contents of r to c using the TransmitFile
// system call to minimize copies.
//
@@ -33,7 +19,7 @@ func (o *sendfileOp) Name() string {
// if handled == false, sendFile performed no work.
//
// Note that sendfile for windows does not suppport >2GB file.
-func sendFile(c *netFD, r io.Reader) (written int64, err error, handled bool) {
+func sendFile(fd *netFD, r io.Reader) (written int64, err error, handled bool) {
var n int64 = 0 // by default, copy until EOF
lr, ok := r.(*io.LimitedReader)
@@ -48,18 +34,17 @@ func sendFile(c *netFD, r io.Reader) (written int64, err error, handled bool) {
return 0, nil, false
}
- if err := c.incref(false); err != nil {
+ if err := fd.writeLock(); err != nil {
return 0, err, true
}
- defer c.decref()
- c.wio.Lock()
- defer c.wio.Unlock()
-
- var o sendfileOp
- o.Init(c, 'w')
- o.n = uint32(n)
- o.src = syscall.Handle(f.Fd())
- done, err := iosrv.ExecIO(&o, 0)
+ defer fd.writeUnlock()
+
+ o := &fd.wop
+ o.qty = uint32(n)
+ o.handle = syscall.Handle(f.Fd())
+ done, err := wsrv.ExecIO(o, "TransmitFile", func(o *operation) error {
+ return syscall.TransmitFile(o.fd.sysfd, o.handle, o.qty, 0, &o.o, nil, syscall.TF_WRITE_BEHIND)
+ })
if err != nil {
return 0, err, false
}
diff --git a/libgo/go/net/singleflight.go b/libgo/go/net/singleflight.go
new file mode 100644
index 00000000000..dc58affdaac
--- /dev/null
+++ b/libgo/go/net/singleflight.go
@@ -0,0 +1,53 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package net
+
+import "sync"
+
+// call is an in-flight or completed singleflight.Do call
+type call struct {
+ wg sync.WaitGroup
+ val interface{}
+ err error
+ dups int
+}
+
+// singleflight represents a class of work and forms a namespace in
+// which units of work can be executed with duplicate suppression.
+type singleflight struct {
+ mu sync.Mutex // protects m
+ m map[string]*call // lazily initialized
+}
+
+// Do executes and returns the results of the given function, making
+// sure that only one execution is in-flight for a given key at a
+// time. If a duplicate comes in, the duplicate caller waits for the
+// original to complete and receives the same results.
+// The return value shared indicates whether v was given to multiple callers.
+func (g *singleflight) Do(key string, fn func() (interface{}, error)) (v interface{}, err error, shared bool) {
+ g.mu.Lock()
+ if g.m == nil {
+ g.m = make(map[string]*call)
+ }
+ if c, ok := g.m[key]; ok {
+ c.dups++
+ g.mu.Unlock()
+ c.wg.Wait()
+ return c.val, c.err, true
+ }
+ c := new(call)
+ c.wg.Add(1)
+ g.m[key] = c
+ g.mu.Unlock()
+
+ c.val, c.err = fn()
+ c.wg.Done()
+
+ g.mu.Lock()
+ delete(g.m, key)
+ g.mu.Unlock()
+
+ return c.val, c.err, c.dups > 0
+}
diff --git a/libgo/go/net/smtp/smtp.go b/libgo/go/net/smtp/smtp.go
index 4b917787701..a0a478a8524 100644
--- a/libgo/go/net/smtp/smtp.go
+++ b/libgo/go/net/smtp/smtp.go
@@ -41,12 +41,13 @@ type Client struct {
}
// Dial returns a new Client connected to an SMTP server at addr.
+// The addr must include a port number.
func Dial(addr string) (*Client, error) {
conn, err := net.Dial("tcp", addr)
if err != nil {
return nil, err
}
- host := addr[:strings.Index(addr, ":")]
+ host, _, _ := net.SplitHostPort(addr)
return NewClient(conn, host)
}
@@ -63,6 +64,11 @@ func NewClient(conn net.Conn, host string) (*Client, error) {
return c, nil
}
+// Close closes the connection.
+func (c *Client) Close() error {
+ return c.Text.Close()
+}
+
// hello runs a hello exchange if needed.
func (c *Client) hello() error {
if !c.didHello {
@@ -190,7 +196,9 @@ func (c *Client) Auth(a Auth) error {
default:
err = &textproto.Error{Code: code, Msg: msg64}
}
- resp, err = a.Next(msg, code == 334)
+ if err == nil {
+ resp, err = a.Next(msg, code == 334)
+ }
if err != nil {
// abort the AUTH
c.cmd(501, "*")
@@ -256,15 +264,17 @@ func (c *Client) Data() (io.WriteCloser, error) {
return &dataCloser{c, c.Text.DotWriter()}, nil
}
-// SendMail connects to the server at addr, switches to TLS if possible,
-// authenticates with mechanism a if possible, and then sends an email from
-// address from, to addresses to, with message msg.
+// SendMail connects to the server at addr, switches to TLS if
+// possible, authenticates with the optional mechanism a if possible,
+// and then sends an email from address from, to addresses to, with
+// message msg.
func SendMail(addr string, a Auth, from string, to []string, msg []byte) error {
c, err := Dial(addr)
if err != nil {
return err
}
- if err := c.hello(); err != nil {
+ defer c.Close()
+ if err = c.hello(); err != nil {
return err
}
if ok, _ := c.Extension("STARTTLS"); ok {
diff --git a/libgo/go/net/smtp/smtp_test.go b/libgo/go/net/smtp/smtp_test.go
index c190b32c054..2133dc7c7ba 100644
--- a/libgo/go/net/smtp/smtp_test.go
+++ b/libgo/go/net/smtp/smtp_test.go
@@ -238,6 +238,7 @@ func TestNewClient(t *testing.T) {
if err != nil {
t.Fatalf("NewClient: %v\n(after %v)", err, out())
}
+ defer c.Close()
if ok, args := c.Extension("aUtH"); !ok || args != "LOGIN PLAIN" {
t.Fatalf("Expected AUTH supported")
}
@@ -278,6 +279,7 @@ func TestNewClient2(t *testing.T) {
if err != nil {
t.Fatalf("NewClient: %v", err)
}
+ defer c.Close()
if ok, _ := c.Extension("DSN"); ok {
t.Fatalf("Shouldn't support DSN")
}
@@ -323,6 +325,7 @@ func TestHello(t *testing.T) {
if err != nil {
t.Fatalf("NewClient: %v", err)
}
+ defer c.Close()
c.localName = "customhost"
err = nil
@@ -501,3 +504,47 @@ SendMail is working for me.
.
QUIT
`
+
+func TestAuthFailed(t *testing.T) {
+ server := strings.Join(strings.Split(authFailedServer, "\n"), "\r\n")
+ client := strings.Join(strings.Split(authFailedClient, "\n"), "\r\n")
+ var cmdbuf bytes.Buffer
+ bcmdbuf := bufio.NewWriter(&cmdbuf)
+ var fake faker
+ fake.ReadWriter = bufio.NewReadWriter(bufio.NewReader(strings.NewReader(server)), bcmdbuf)
+ c, err := NewClient(fake, "fake.host")
+ if err != nil {
+ t.Fatalf("NewClient: %v", err)
+ }
+ defer c.Close()
+
+ c.tls = true
+ c.serverName = "smtp.google.com"
+ err = c.Auth(PlainAuth("", "user", "pass", "smtp.google.com"))
+
+ if err == nil {
+ t.Error("Auth: expected error; got none")
+ } else if err.Error() != "535 Invalid credentials\nplease see www.example.com" {
+ t.Errorf("Auth: got error: %v, want: %s", err, "535 Invalid credentials\nplease see www.example.com")
+ }
+
+ bcmdbuf.Flush()
+ actualcmds := cmdbuf.String()
+ if client != actualcmds {
+ t.Errorf("Got:\n%s\nExpected:\n%s", actualcmds, client)
+ }
+}
+
+var authFailedServer = `220 hello world
+250-mx.google.com at your service
+250 AUTH LOGIN PLAIN
+535-Invalid credentials
+535 please see www.example.com
+221 Goodbye
+`
+
+var authFailedClient = `EHLO localhost
+AUTH PLAIN AHVzZXIAcGFzcw==
+*
+QUIT
+`
diff --git a/libgo/go/net/sock_bsd.go b/libgo/go/net/sock_bsd.go
index d99349265eb..6c37109f5e4 100644
--- a/libgo/go/net/sock_bsd.go
+++ b/libgo/go/net/sock_bsd.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd netbsd openbsd
+// +build darwin dragonfly freebsd netbsd openbsd
package net
diff --git a/libgo/go/net/sock_plan9.go b/libgo/go/net/sock_plan9.go
new file mode 100644
index 00000000000..88d9ed15cf1
--- /dev/null
+++ b/libgo/go/net/sock_plan9.go
@@ -0,0 +1,10 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package net
+
+func maxListenerBacklog() int {
+ // /sys/include/ape/sys/socket.h:/SOMAXCONN
+ return 5
+}
diff --git a/libgo/go/net/sock_posix.go b/libgo/go/net/sock_posix.go
index be89c26db2a..c2d343c5858 100644
--- a/libgo/go/net/sock_posix.go
+++ b/libgo/go/net/sock_posix.go
@@ -2,78 +2,197 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd linux netbsd openbsd windows
+// +build darwin dragonfly freebsd linux netbsd openbsd windows
package net
import (
+ "os"
"syscall"
"time"
)
-var listenerBacklog = maxListenerBacklog()
+// A sockaddr represents a TCP, UDP, IP or Unix network endpoint
+// address that can be converted into a syscall.Sockaddr.
+type sockaddr interface {
+ Addr
-// Generic POSIX socket creation.
-func socket(net string, f, t, p int, ipv6only bool, ulsa, ursa syscall.Sockaddr, deadline time.Time, toAddr func(syscall.Sockaddr) Addr) (fd *netFD, err error) {
- s, err := sysSocket(f, t, p)
+ netaddr
+
+ // family returns the platform-dependent address family
+ // identifier.
+ family() int
+
+ // isWildcard reports whether the address is a wildcard
+ // address.
+ isWildcard() bool
+
+ // sockaddr returns the address converted into a syscall
+ // sockaddr type that implements syscall.Sockaddr
+ // interface. It returns a nil interface when the address is
+ // nil.
+ sockaddr(family int) (syscall.Sockaddr, error)
+}
+
+// socket returns a network file descriptor that is ready for
+// asynchronous I/O using the network poller.
+func socket(net string, family, sotype, proto int, ipv6only bool, laddr, raddr sockaddr, deadline time.Time, toAddr func(syscall.Sockaddr) Addr) (fd *netFD, err error) {
+ s, err := sysSocket(family, sotype, proto)
if err != nil {
return nil, err
}
-
- if err = setDefaultSockopts(s, f, t, ipv6only); err != nil {
+ if err = setDefaultSockopts(s, family, sotype, ipv6only); err != nil {
closesocket(s)
return nil, err
}
-
- // This socket is used by a listener.
- if ulsa != nil && ursa == nil {
- // We provide a socket that listens to a wildcard
- // address with reusable UDP port when the given ulsa
- // is an appropriate UDP multicast address prefix.
- // This makes it possible for a single UDP listener
- // to join multiple different group addresses, for
- // multiple UDP listeners that listen on the same UDP
- // port to join the same group address.
- if ulsa, err = listenerSockaddr(s, f, ulsa, toAddr); err != nil {
- closesocket(s)
- return nil, err
- }
+ if fd, err = newFD(s, family, sotype, net); err != nil {
+ closesocket(s)
+ return nil, err
}
- if ulsa != nil {
- if err = syscall.Bind(s, ulsa); err != nil {
- closesocket(s)
- return nil, err
+ // This function makes a network file descriptor for the
+ // following applications:
+ //
+ // - An endpoint holder that opens a passive stream
+ // connenction, known as a stream listener
+ //
+ // - An endpoint holder that opens a destination-unspecific
+ // datagram connection, known as a datagram listener
+ //
+ // - An endpoint holder that opens an active stream or a
+ // destination-specific datagram connection, known as a
+ // dialer
+ //
+ // - An endpoint holder that opens the other connection, such
+ // as talking to the protocol stack inside the kernel
+ //
+ // For stream and datagram listeners, they will only require
+ // named sockets, so we can assume that it's just a request
+ // from stream or datagram listeners when laddr is not nil but
+ // raddr is nil. Otherwise we assume it's just for dialers or
+ // the other connection holders.
+
+ if laddr != nil && raddr == nil {
+ switch sotype {
+ case syscall.SOCK_STREAM, syscall.SOCK_SEQPACKET:
+ if err := fd.listenStream(laddr, listenerBacklog, toAddr); err != nil {
+ fd.Close()
+ return nil, err
+ }
+ return fd, nil
+ case syscall.SOCK_DGRAM:
+ if err := fd.listenDatagram(laddr, toAddr); err != nil {
+ fd.Close()
+ return nil, err
+ }
+ return fd, nil
}
}
-
- if fd, err = newFD(s, f, t, net); err != nil {
- closesocket(s)
+ if err := fd.dial(laddr, raddr, deadline, toAddr); err != nil {
+ fd.Close()
return nil, err
}
+ return fd, nil
+}
- // This socket is used by a dialer.
- if ursa != nil {
- if !deadline.IsZero() {
- setWriteDeadline(fd, deadline)
+func (fd *netFD) dial(laddr, raddr sockaddr, deadline time.Time, toAddr func(syscall.Sockaddr) Addr) error {
+ var err error
+ var lsa syscall.Sockaddr
+ if laddr != nil {
+ if lsa, err = laddr.sockaddr(fd.family); err != nil {
+ return err
+ } else if lsa != nil {
+ if err := syscall.Bind(fd.sysfd, lsa); err != nil {
+ return os.NewSyscallError("bind", err)
+ }
}
- if err = fd.connect(ulsa, ursa); err != nil {
- fd.Close()
- return nil, err
+ }
+ if err := fd.init(); err != nil {
+ return err
+ }
+ var rsa syscall.Sockaddr
+ if raddr != nil {
+ if rsa, err = raddr.sockaddr(fd.family); err != nil {
+ return err
+ } else if rsa != nil {
+ if !deadline.IsZero() {
+ fd.setWriteDeadline(deadline)
+ }
+ if err := fd.connect(lsa, rsa); err != nil {
+ return err
+ }
+ fd.isConnected = true
+ if !deadline.IsZero() {
+ fd.setWriteDeadline(noDeadline)
+ }
}
- fd.isConnected = true
- if !deadline.IsZero() {
- setWriteDeadline(fd, time.Time{})
+ }
+ lsa, _ = syscall.Getsockname(fd.sysfd)
+ if rsa, _ = syscall.Getpeername(fd.sysfd); rsa != nil {
+ fd.setAddr(toAddr(lsa), toAddr(rsa))
+ } else {
+ fd.setAddr(toAddr(lsa), raddr)
+ }
+ return nil
+}
+
+func (fd *netFD) listenStream(laddr sockaddr, backlog int, toAddr func(syscall.Sockaddr) Addr) error {
+ if err := setDefaultListenerSockopts(fd.sysfd); err != nil {
+ return err
+ }
+ if lsa, err := laddr.sockaddr(fd.family); err != nil {
+ return err
+ } else if lsa != nil {
+ if err := syscall.Bind(fd.sysfd, lsa); err != nil {
+ return os.NewSyscallError("bind", err)
}
}
+ if err := syscall.Listen(fd.sysfd, backlog); err != nil {
+ return os.NewSyscallError("listen", err)
+ }
+ if err := fd.init(); err != nil {
+ return err
+ }
+ lsa, _ := syscall.Getsockname(fd.sysfd)
+ fd.setAddr(toAddr(lsa), nil)
+ return nil
+}
- lsa, _ := syscall.Getsockname(s)
- laddr := toAddr(lsa)
- rsa, _ := syscall.Getpeername(s)
- if rsa == nil {
- rsa = ursa
- }
- raddr := toAddr(rsa)
- fd.setAddr(laddr, raddr)
- return fd, nil
+func (fd *netFD) listenDatagram(laddr sockaddr, toAddr func(syscall.Sockaddr) Addr) error {
+ switch addr := laddr.(type) {
+ case *UDPAddr:
+ // We provide a socket that listens to a wildcard
+ // address with reusable UDP port when the given laddr
+ // is an appropriate UDP multicast address prefix.
+ // This makes it possible for a single UDP listener to
+ // join multiple different group addresses, for
+ // multiple UDP listeners that listen on the same UDP
+ // port to join the same group address.
+ if addr.IP != nil && addr.IP.IsMulticast() {
+ if err := setDefaultMulticastSockopts(fd.sysfd); err != nil {
+ return err
+ }
+ addr := *addr
+ switch fd.family {
+ case syscall.AF_INET:
+ addr.IP = IPv4zero
+ case syscall.AF_INET6:
+ addr.IP = IPv6unspecified
+ }
+ laddr = &addr
+ }
+ }
+ if lsa, err := laddr.sockaddr(fd.family); err != nil {
+ return err
+ } else if lsa != nil {
+ if err := syscall.Bind(fd.sysfd, lsa); err != nil {
+ return os.NewSyscallError("bind", err)
+ }
+ }
+ if err := fd.init(); err != nil {
+ return err
+ }
+ lsa, _ := syscall.Getsockname(fd.sysfd)
+ fd.setAddr(toAddr(lsa), nil)
+ return nil
}
diff --git a/libgo/go/net/sock_unix.go b/libgo/go/net/sock_unix.go
deleted file mode 100644
index b0d6d4900f2..00000000000
--- a/libgo/go/net/sock_unix.go
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build darwin freebsd linux netbsd openbsd
-
-package net
-
-import "syscall"
-
-func listenerSockaddr(s, f int, la syscall.Sockaddr, toAddr func(syscall.Sockaddr) Addr) (syscall.Sockaddr, error) {
- a := toAddr(la)
- if a == nil {
- return la, nil
- }
- switch a := a.(type) {
- case *TCPAddr, *UnixAddr:
- if err := setDefaultListenerSockopts(s); err != nil {
- return nil, err
- }
- case *UDPAddr:
- if a.IP.IsMulticast() {
- if err := setDefaultMulticastSockopts(s); err != nil {
- return nil, err
- }
- switch f {
- case syscall.AF_INET:
- a.IP = IPv4zero
- case syscall.AF_INET6:
- a.IP = IPv6unspecified
- }
- return a.sockaddr(f)
- }
- }
- return la, nil
-}
diff --git a/libgo/go/net/sock_windows.go b/libgo/go/net/sock_windows.go
index 41368d39e81..6ccde3a24b9 100644
--- a/libgo/go/net/sock_windows.go
+++ b/libgo/go/net/sock_windows.go
@@ -12,33 +12,6 @@ func maxListenerBacklog() int {
return syscall.SOMAXCONN
}
-func listenerSockaddr(s syscall.Handle, f int, la syscall.Sockaddr, toAddr func(syscall.Sockaddr) Addr) (syscall.Sockaddr, error) {
- a := toAddr(la)
- if a == nil {
- return la, nil
- }
- switch a := a.(type) {
- case *TCPAddr, *UnixAddr:
- if err := setDefaultListenerSockopts(s); err != nil {
- return nil, err
- }
- case *UDPAddr:
- if a.IP.IsMulticast() {
- if err := setDefaultMulticastSockopts(s); err != nil {
- return nil, err
- }
- switch f {
- case syscall.AF_INET:
- a.IP = IPv4zero
- case syscall.AF_INET6:
- a.IP = IPv6unspecified
- }
- return a.sockaddr(f)
- }
- }
- return la, nil
-}
-
func sysSocket(f, t, p int) (syscall.Handle, error) {
// See ../syscall/exec_unix.go for description of ForkLock.
syscall.ForkLock.RLock()
diff --git a/libgo/go/net/sockopt_bsd.go b/libgo/go/net/sockopt_bsd.go
index af88814b4b9..4b9c2f9afbe 100644
--- a/libgo/go/net/sockopt_bsd.go
+++ b/libgo/go/net/sockopt_bsd.go
@@ -2,9 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd netbsd openbsd
-
-// Socket options for BSD variants
+// +build darwin dragonfly freebsd netbsd openbsd
package net
@@ -13,40 +11,26 @@ import (
"syscall"
)
-func setDefaultSockopts(s, f, t int, ipv6only bool) error {
- switch f {
- case syscall.AF_INET6:
- if ipv6only {
- syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, 1)
- } else {
- // Allow both IP versions even if the OS default
- // is otherwise. Note that some operating systems
- // never admit this option.
- syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, 0)
- }
+func setDefaultSockopts(s, family, sotype int, ipv6only bool) error {
+ if family == syscall.AF_INET6 && sotype != syscall.SOCK_RAW {
+ // Allow both IP versions even if the OS default
+ // is otherwise. Note that some operating systems
+ // never admit this option.
+ syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, boolint(ipv6only))
}
// Allow broadcast.
- err := syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1)
- if err != nil {
- return os.NewSyscallError("setsockopt", err)
- }
- return nil
+ return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1))
}
func setDefaultListenerSockopts(s int) error {
// Allow reuse of recently-used addresses.
- err := syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
- if err != nil {
- return os.NewSyscallError("setsockopt", err)
- }
- return nil
+ return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1))
}
func setDefaultMulticastSockopts(s int) error {
// Allow multicast UDP and raw IP datagram sockets to listen
// concurrently across multiple listeners.
- err := syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
- if err != nil {
+ if err := syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1); err != nil {
return os.NewSyscallError("setsockopt", err)
}
// Allow reuse of recently-used ports.
@@ -54,10 +38,7 @@ func setDefaultMulticastSockopts(s int) error {
// to make an effective multicast application that requires
// quick draw possible.
if syscall.SO_REUSEPORT != 0 {
- err = syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEPORT, 1)
- if err != nil {
- return os.NewSyscallError("setsockopt", err)
- }
+ return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEPORT, 1))
}
return nil
}
diff --git a/libgo/go/net/sockopt_linux.go b/libgo/go/net/sockopt_linux.go
index 0f47538c541..54c20b1409b 100644
--- a/libgo/go/net/sockopt_linux.go
+++ b/libgo/go/net/sockopt_linux.go
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Socket options for Linux
-
package net
import (
@@ -11,41 +9,24 @@ import (
"syscall"
)
-func setDefaultSockopts(s, f, t int, ipv6only bool) error {
- switch f {
- case syscall.AF_INET6:
- if ipv6only {
- syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, 1)
- } else {
- // Allow both IP versions even if the OS default
- // is otherwise. Note that some operating systems
- // never admit this option.
- syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, 0)
- }
+func setDefaultSockopts(s, family, sotype int, ipv6only bool) error {
+ if family == syscall.AF_INET6 && sotype != syscall.SOCK_RAW {
+ // Allow both IP versions even if the OS default
+ // is otherwise. Note that some operating systems
+ // never admit this option.
+ syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, boolint(ipv6only))
}
// Allow broadcast.
- err := syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1)
- if err != nil {
- return os.NewSyscallError("setsockopt", err)
- }
- return nil
+ return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1))
}
func setDefaultListenerSockopts(s int) error {
// Allow reuse of recently-used addresses.
- err := syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
- if err != nil {
- return os.NewSyscallError("setsockopt", err)
- }
- return nil
+ return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1))
}
func setDefaultMulticastSockopts(s int) error {
// Allow multicast UDP and raw IP datagram sockets to listen
// concurrently across multiple listeners.
- err := syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
- if err != nil {
- return os.NewSyscallError("setsockopt", err)
- }
- return nil
+ return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1))
}
diff --git a/libgo/go/net/sockopt_posix.go b/libgo/go/net/sockopt_posix.go
index 1590f4e98de..ff3bc689940 100644
--- a/libgo/go/net/sockopt_posix.go
+++ b/libgo/go/net/sockopt_posix.go
@@ -2,9 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd linux netbsd openbsd windows
-
-// Socket options
+// +build darwin dragonfly freebsd linux netbsd openbsd windows
package net
@@ -103,7 +101,7 @@ done:
}
func setReadBuffer(fd *netFD, bytes int) error {
- if err := fd.incref(false); err != nil {
+ if err := fd.incref(); err != nil {
return err
}
defer fd.decref()
@@ -111,7 +109,7 @@ func setReadBuffer(fd *netFD, bytes int) error {
}
func setWriteBuffer(fd *netFD, bytes int) error {
- if err := fd.incref(false); err != nil {
+ if err := fd.incref(); err != nil {
return err
}
defer fd.decref()
@@ -119,21 +117,13 @@ func setWriteBuffer(fd *netFD, bytes int) error {
}
func setKeepAlive(fd *netFD, keepalive bool) error {
- if err := fd.incref(false); err != nil {
+ if err := fd.incref(); err != nil {
return err
}
defer fd.decref()
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, boolint(keepalive)))
}
-func setNoDelay(fd *netFD, noDelay bool) error {
- if err := fd.incref(false); err != nil {
- return err
- }
- defer fd.decref()
- return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_TCP, syscall.TCP_NODELAY, boolint(noDelay)))
-}
-
func setLinger(fd *netFD, sec int) error {
var l syscall.Linger
if sec >= 0 {
@@ -143,7 +133,7 @@ func setLinger(fd *netFD, sec int) error {
l.Onoff = 0
l.Linger = 0
}
- if err := fd.incref(false); err != nil {
+ if err := fd.incref(); err != nil {
return err
}
defer fd.decref()
diff --git a/libgo/go/net/sockopt_windows.go b/libgo/go/net/sockopt_windows.go
index 0861fe8f4bf..cb64a40c695 100644
--- a/libgo/go/net/sockopt_windows.go
+++ b/libgo/go/net/sockopt_windows.go
@@ -2,27 +2,19 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Socket options for Windows
-
package net
import (
"os"
"syscall"
- "time"
)
-func setDefaultSockopts(s syscall.Handle, f, t int, ipv6only bool) error {
- switch f {
- case syscall.AF_INET6:
- if ipv6only {
- syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, 1)
- } else {
- // Allow both IP versions even if the OS default
- // is otherwise. Note that some operating systems
- // never admit this option.
- syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, 0)
- }
+func setDefaultSockopts(s syscall.Handle, family, sotype int, ipv6only bool) error {
+ if family == syscall.AF_INET6 && sotype != syscall.SOCK_RAW {
+ // Allow both IP versions even if the OS default
+ // is otherwise. Note that some operating systems
+ // never admit this option.
+ syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, boolint(ipv6only))
}
// Allow broadcast.
syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1)
@@ -42,27 +34,5 @@ func setDefaultListenerSockopts(s syscall.Handle) error {
func setDefaultMulticastSockopts(s syscall.Handle) error {
// Allow multicast UDP and raw IP datagram sockets to listen
// concurrently across multiple listeners.
- err := syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
- if err != nil {
- return os.NewSyscallError("setsockopt", err)
- }
- return nil
-}
-
-// TODO(dfc) these unused error returns could be removed
-
-func setReadDeadline(fd *netFD, t time.Time) error {
- fd.rdeadline.setTime(t)
- return nil
-}
-
-func setWriteDeadline(fd *netFD, t time.Time) error {
- fd.wdeadline.setTime(t)
- return nil
-}
-
-func setDeadline(fd *netFD, t time.Time) error {
- setReadDeadline(fd, t)
- setWriteDeadline(fd, t)
- return nil
+ return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1))
}
diff --git a/libgo/go/net/sockoptip_bsd.go b/libgo/go/net/sockoptip_bsd.go
index 263f8552176..2199e480d42 100644
--- a/libgo/go/net/sockoptip_bsd.go
+++ b/libgo/go/net/sockoptip_bsd.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd netbsd openbsd
+// +build darwin dragonfly freebsd netbsd openbsd
package net
@@ -18,25 +18,17 @@ func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error {
}
var a [4]byte
copy(a[:], ip.To4())
- if err := fd.incref(false); err != nil {
+ if err := fd.incref(); err != nil {
return err
}
defer fd.decref()
- err = syscall.SetsockoptInet4Addr(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF, a)
- if err != nil {
- return os.NewSyscallError("setsockopt", err)
- }
- return nil
+ return os.NewSyscallError("setsockopt", syscall.SetsockoptInet4Addr(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF, a))
}
func setIPv4MulticastLoopback(fd *netFD, v bool) error {
- if err := fd.incref(false); err != nil {
+ if err := fd.incref(); err != nil {
return err
}
defer fd.decref()
- err := syscall.SetsockoptByte(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP, byte(boolint(v)))
- if err != nil {
- return os.NewSyscallError("setsockopt", err)
- }
- return nil
+ return os.NewSyscallError("setsockopt", syscall.SetsockoptByte(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP, byte(boolint(v))))
}
diff --git a/libgo/go/net/sockoptip_linux.go b/libgo/go/net/sockoptip_linux.go
index 225fb0c4c6c..a69b778e4d1 100644
--- a/libgo/go/net/sockoptip_linux.go
+++ b/libgo/go/net/sockoptip_linux.go
@@ -15,25 +15,17 @@ func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error {
v = int32(ifi.Index)
}
mreq := &syscall.IPMreqn{Ifindex: v}
- if err := fd.incref(false); err != nil {
+ if err := fd.incref(); err != nil {
return err
}
defer fd.decref()
- err := syscall.SetsockoptIPMreqn(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF, mreq)
- if err != nil {
- return os.NewSyscallError("setsockopt", err)
- }
- return nil
+ return os.NewSyscallError("setsockopt", syscall.SetsockoptIPMreqn(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF, mreq))
}
func setIPv4MulticastLoopback(fd *netFD, v bool) error {
- if err := fd.incref(false); err != nil {
+ if err := fd.incref(); err != nil {
return err
}
defer fd.decref()
- err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP, boolint(v))
- if err != nil {
- return os.NewSyscallError("setsockopt", err)
- }
- return nil
+ return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP, boolint(v)))
}
diff --git a/libgo/go/net/sockoptip_posix.go b/libgo/go/net/sockoptip_posix.go
index e4c56a0e4b2..c2579be9114 100644
--- a/libgo/go/net/sockoptip_posix.go
+++ b/libgo/go/net/sockoptip_posix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd linux netbsd openbsd windows
+// +build darwin dragonfly freebsd linux netbsd openbsd windows
package net
@@ -16,15 +16,11 @@ func joinIPv4Group(fd *netFD, ifi *Interface, ip IP) error {
if err := setIPv4MreqToInterface(mreq, ifi); err != nil {
return err
}
- if err := fd.incref(false); err != nil {
+ if err := fd.incref(); err != nil {
return err
}
defer fd.decref()
- err := syscall.SetsockoptIPMreq(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_ADD_MEMBERSHIP, mreq)
- if err != nil {
- return os.NewSyscallError("setsockopt", err)
- }
- return nil
+ return os.NewSyscallError("setsockopt", syscall.SetsockoptIPMreq(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_ADD_MEMBERSHIP, mreq))
}
func setIPv6MulticastInterface(fd *netFD, ifi *Interface) error {
@@ -32,27 +28,19 @@ func setIPv6MulticastInterface(fd *netFD, ifi *Interface) error {
if ifi != nil {
v = ifi.Index
}
- if err := fd.incref(false); err != nil {
+ if err := fd.incref(); err != nil {
return err
}
defer fd.decref()
- err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_IF, v)
- if err != nil {
- return os.NewSyscallError("setsockopt", err)
- }
- return nil
+ return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_IF, v))
}
func setIPv6MulticastLoopback(fd *netFD, v bool) error {
- if err := fd.incref(false); err != nil {
+ if err := fd.incref(); err != nil {
return err
}
defer fd.decref()
- err := syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_LOOP, boolint(v))
- if err != nil {
- return os.NewSyscallError("setsockopt", err)
- }
- return nil
+ return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_LOOP, boolint(v)))
}
func joinIPv6Group(fd *netFD, ifi *Interface, ip IP) error {
@@ -61,13 +49,9 @@ func joinIPv6Group(fd *netFD, ifi *Interface, ip IP) error {
if ifi != nil {
mreq.Interface = uint32(ifi.Index)
}
- if err := fd.incref(false); err != nil {
+ if err := fd.incref(); err != nil {
return err
}
defer fd.decref()
- err := syscall.SetsockoptIPv6Mreq(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_JOIN_GROUP, mreq)
- if err != nil {
- return os.NewSyscallError("setsockopt", err)
- }
- return nil
+ return os.NewSyscallError("setsockopt", syscall.SetsockoptIPv6Mreq(fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_JOIN_GROUP, mreq))
}
diff --git a/libgo/go/net/sockoptip_windows.go b/libgo/go/net/sockoptip_windows.go
index 3e248441ab3..7b11f207aaf 100644
--- a/libgo/go/net/sockoptip_windows.go
+++ b/libgo/go/net/sockoptip_windows.go
@@ -17,26 +17,17 @@ func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error {
}
var a [4]byte
copy(a[:], ip.To4())
- if err := fd.incref(false); err != nil {
+ if err := fd.incref(); err != nil {
return err
}
defer fd.decref()
- err = syscall.Setsockopt(fd.sysfd, int32(syscall.IPPROTO_IP), int32(syscall.IP_MULTICAST_IF), (*byte)(unsafe.Pointer(&a[0])), 4)
- if err != nil {
- return os.NewSyscallError("setsockopt", err)
- }
- return nil
+ return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF, (*byte)(unsafe.Pointer(&a[0])), 4))
}
func setIPv4MulticastLoopback(fd *netFD, v bool) error {
- if err := fd.incref(false); err != nil {
+ if err := fd.incref(); err != nil {
return err
}
defer fd.decref()
- vv := int32(boolint(v))
- err := syscall.Setsockopt(fd.sysfd, int32(syscall.IPPROTO_IP), int32(syscall.IP_MULTICAST_LOOP), (*byte)(unsafe.Pointer(&vv)), 4)
- if err != nil {
- return os.NewSyscallError("setsockopt", err)
- }
- return nil
+ return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP, boolint(v)))
}
diff --git a/libgo/go/net/sys_cloexec.go b/libgo/go/net/sys_cloexec.go
index 17e8749087d..bbfcc1a4fc4 100644
--- a/libgo/go/net/sys_cloexec.go
+++ b/libgo/go/net/sys_cloexec.go
@@ -5,7 +5,7 @@
// This file implements sysSocket and accept for platforms that do not
// provide a fast path for setting SetNonblock and CloseOnExec.
-// +build darwin freebsd netbsd openbsd
+// +build darwin dragonfly freebsd netbsd openbsd
package net
diff --git a/libgo/go/net/tcp_test.go b/libgo/go/net/tcp_test.go
index a71b02b4774..62fd99f5c0b 100644
--- a/libgo/go/net/tcp_test.go
+++ b/libgo/go/net/tcp_test.go
@@ -6,8 +6,10 @@ package net
import (
"fmt"
+ "io"
"reflect"
"runtime"
+ "sync"
"testing"
"time"
)
@@ -59,7 +61,7 @@ func BenchmarkTCP6PersistentTimeout(b *testing.B) {
func benchmarkTCP(b *testing.B, persistent, timeout bool, laddr string) {
const msgLen = 512
conns := b.N
- numConcurrent := runtime.GOMAXPROCS(-1) * 16
+ numConcurrent := runtime.GOMAXPROCS(-1) * 2
msgs := 1
if persistent {
conns = numConcurrent
@@ -147,11 +149,134 @@ func benchmarkTCP(b *testing.B, persistent, timeout bool, laddr string) {
}
}
+func BenchmarkTCP4ConcurrentReadWrite(b *testing.B) {
+ benchmarkTCPConcurrentReadWrite(b, "127.0.0.1:0")
+}
+
+func BenchmarkTCP6ConcurrentReadWrite(b *testing.B) {
+ if !supportsIPv6 {
+ b.Skip("ipv6 is not supported")
+ }
+ benchmarkTCPConcurrentReadWrite(b, "[::1]:0")
+}
+
+func benchmarkTCPConcurrentReadWrite(b *testing.B, laddr string) {
+ // The benchmark creates GOMAXPROCS client/server pairs.
+ // Each pair creates 4 goroutines: client reader/writer and server reader/writer.
+ // The benchmark stresses concurrent reading and writing to the same connection.
+ // Such pattern is used in net/http and net/rpc.
+
+ b.StopTimer()
+
+ P := runtime.GOMAXPROCS(0)
+ N := b.N / P
+ W := 1000
+
+ // Setup P client/server connections.
+ clients := make([]Conn, P)
+ servers := make([]Conn, P)
+ ln, err := Listen("tcp", laddr)
+ if err != nil {
+ b.Fatalf("Listen failed: %v", err)
+ }
+ defer ln.Close()
+ done := make(chan bool)
+ go func() {
+ for p := 0; p < P; p++ {
+ s, err := ln.Accept()
+ if err != nil {
+ b.Fatalf("Accept failed: %v", err)
+ }
+ servers[p] = s
+ }
+ done <- true
+ }()
+ for p := 0; p < P; p++ {
+ c, err := Dial("tcp", ln.Addr().String())
+ if err != nil {
+ b.Fatalf("Dial failed: %v", err)
+ }
+ clients[p] = c
+ }
+ <-done
+
+ b.StartTimer()
+
+ var wg sync.WaitGroup
+ wg.Add(4 * P)
+ for p := 0; p < P; p++ {
+ // Client writer.
+ go func(c Conn) {
+ defer wg.Done()
+ var buf [1]byte
+ for i := 0; i < N; i++ {
+ v := byte(i)
+ for w := 0; w < W; w++ {
+ v *= v
+ }
+ buf[0] = v
+ _, err := c.Write(buf[:])
+ if err != nil {
+ b.Fatalf("Write failed: %v", err)
+ }
+ }
+ }(clients[p])
+
+ // Pipe between server reader and server writer.
+ pipe := make(chan byte, 128)
+
+ // Server reader.
+ go func(s Conn) {
+ defer wg.Done()
+ var buf [1]byte
+ for i := 0; i < N; i++ {
+ _, err := s.Read(buf[:])
+ if err != nil {
+ b.Fatalf("Read failed: %v", err)
+ }
+ pipe <- buf[0]
+ }
+ }(servers[p])
+
+ // Server writer.
+ go func(s Conn) {
+ defer wg.Done()
+ var buf [1]byte
+ for i := 0; i < N; i++ {
+ v := <-pipe
+ for w := 0; w < W; w++ {
+ v *= v
+ }
+ buf[0] = v
+ _, err := s.Write(buf[:])
+ if err != nil {
+ b.Fatalf("Write failed: %v", err)
+ }
+ }
+ s.Close()
+ }(servers[p])
+
+ // Client reader.
+ go func(c Conn) {
+ defer wg.Done()
+ var buf [1]byte
+ for i := 0; i < N; i++ {
+ _, err := c.Read(buf[:])
+ if err != nil {
+ b.Fatalf("Read failed: %v", err)
+ }
+ }
+ c.Close()
+ }(clients[p])
+ }
+ wg.Wait()
+}
+
type resolveTCPAddrTest struct {
- net string
- litAddr string
- addr *TCPAddr
- err error
+ net string
+ litAddrOrName string
+ addr *TCPAddr
+ err error
}
var resolveTCPAddrTests = []resolveTCPAddrTest{
@@ -167,6 +292,8 @@ var resolveTCPAddrTests = []resolveTCPAddrTest{
{"", "127.0.0.1:0", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 0}, nil}, // Go 1.0 behavior
{"", "[::1]:0", &TCPAddr{IP: ParseIP("::1"), Port: 0}, nil}, // Go 1.0 behavior
+ {"tcp", ":12345", &TCPAddr{Port: 12345}, nil},
+
{"http", "127.0.0.1:0", nil, UnknownNetworkError("http")},
}
@@ -178,16 +305,33 @@ func init() {
{"tcp6", "[fe80::1%" + index + "]:4", &TCPAddr{IP: ParseIP("fe80::1"), Port: 4, Zone: index}, nil},
}...)
}
+ if ips, err := LookupIP("localhost"); err == nil && len(ips) > 1 && supportsIPv4 && supportsIPv6 {
+ resolveTCPAddrTests = append(resolveTCPAddrTests, []resolveTCPAddrTest{
+ {"tcp", "localhost:5", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5}, nil},
+ {"tcp4", "localhost:6", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 6}, nil},
+ {"tcp6", "localhost:7", &TCPAddr{IP: IPv6loopback, Port: 7}, nil},
+ }...)
+ }
}
func TestResolveTCPAddr(t *testing.T) {
for _, tt := range resolveTCPAddrTests {
- addr, err := ResolveTCPAddr(tt.net, tt.litAddr)
+ addr, err := ResolveTCPAddr(tt.net, tt.litAddrOrName)
if err != tt.err {
- t.Fatalf("ResolveTCPAddr(%v, %v) failed: %v", tt.net, tt.litAddr, err)
+ t.Fatalf("ResolveTCPAddr(%q, %q) failed: %v", tt.net, tt.litAddrOrName, err)
}
if !reflect.DeepEqual(addr, tt.addr) {
- t.Fatalf("got %#v; expected %#v", addr, tt.addr)
+ t.Fatalf("ResolveTCPAddr(%q, %q) = %#v, want %#v", tt.net, tt.litAddrOrName, addr, tt.addr)
+ }
+ if err == nil {
+ str := addr.String()
+ addr1, err := ResolveTCPAddr(tt.net, str)
+ if err != nil {
+ t.Fatalf("ResolveTCPAddr(%q, %q) [from %q]: %v", tt.net, str, tt.litAddrOrName, err)
+ }
+ if !reflect.DeepEqual(addr1, addr) {
+ t.Fatalf("ResolveTCPAddr(%q, %q) [from %q] = %#v, want %#v", tt.net, str, tt.litAddrOrName, addr1, addr)
+ }
}
}
}
@@ -294,3 +438,153 @@ func TestIPv6LinkLocalUnicastTCP(t *testing.T) {
<-done
}
}
+
+func TestTCPConcurrentAccept(t *testing.T) {
+ defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
+ ln, err := Listen("tcp", "127.0.0.1:0")
+ if err != nil {
+ t.Fatalf("Listen failed: %v", err)
+ }
+ const N = 10
+ var wg sync.WaitGroup
+ wg.Add(N)
+ for i := 0; i < N; i++ {
+ go func() {
+ for {
+ c, err := ln.Accept()
+ if err != nil {
+ break
+ }
+ c.Close()
+ }
+ wg.Done()
+ }()
+ }
+ for i := 0; i < 10*N; i++ {
+ c, err := Dial("tcp", ln.Addr().String())
+ if err != nil {
+ t.Fatalf("Dial failed: %v", err)
+ }
+ c.Close()
+ }
+ ln.Close()
+ wg.Wait()
+}
+
+func TestTCPReadWriteMallocs(t *testing.T) {
+ if testing.Short() {
+ t.Skip("skipping malloc count in short mode")
+ }
+ ln, err := Listen("tcp", "127.0.0.1:0")
+ if err != nil {
+ t.Fatalf("Listen failed: %v", err)
+ }
+ defer ln.Close()
+ var server Conn
+ errc := make(chan error)
+ go func() {
+ var err error
+ server, err = ln.Accept()
+ errc <- err
+ }()
+ client, err := Dial("tcp", ln.Addr().String())
+ if err != nil {
+ t.Fatalf("Dial failed: %v", err)
+ }
+ if err := <-errc; err != nil {
+ t.Fatalf("Accept failed: %v", err)
+ }
+ defer server.Close()
+ var buf [128]byte
+ mallocs := testing.AllocsPerRun(1000, func() {
+ _, err := server.Write(buf[:])
+ if err != nil {
+ t.Fatalf("Write failed: %v", err)
+ }
+ _, err = io.ReadFull(client, buf[:])
+ if err != nil {
+ t.Fatalf("Read failed: %v", err)
+ }
+ })
+ if mallocs > 0 {
+ t.Fatalf("Got %v allocs, want 0", mallocs)
+ }
+}
+
+func TestTCPStress(t *testing.T) {
+ const conns = 2
+ const msgLen = 512
+ msgs := int(1e4)
+ if testing.Short() {
+ msgs = 1e2
+ }
+
+ sendMsg := func(c Conn, buf []byte) bool {
+ n, err := c.Write(buf)
+ if n != len(buf) || err != nil {
+ t.Logf("Write failed: %v", err)
+ return false
+ }
+ return true
+ }
+ recvMsg := func(c Conn, buf []byte) bool {
+ for read := 0; read != len(buf); {
+ n, err := c.Read(buf)
+ read += n
+ if err != nil {
+ t.Logf("Read failed: %v", err)
+ return false
+ }
+ }
+ return true
+ }
+
+ ln, err := Listen("tcp", "127.0.0.1:0")
+ if err != nil {
+ t.Fatalf("Listen failed: %v", err)
+ }
+ defer ln.Close()
+ // Acceptor.
+ go func() {
+ for {
+ c, err := ln.Accept()
+ if err != nil {
+ break
+ }
+ // Server connection.
+ go func(c Conn) {
+ defer c.Close()
+ var buf [msgLen]byte
+ for m := 0; m < msgs; m++ {
+ if !recvMsg(c, buf[:]) || !sendMsg(c, buf[:]) {
+ break
+ }
+ }
+ }(c)
+ }
+ }()
+ done := make(chan bool)
+ for i := 0; i < conns; i++ {
+ // Client connection.
+ go func() {
+ defer func() {
+ done <- true
+ }()
+ c, err := Dial("tcp", ln.Addr().String())
+ if err != nil {
+ t.Logf("Dial failed: %v", err)
+ return
+ }
+ defer c.Close()
+ var buf [msgLen]byte
+ for m := 0; m < msgs; m++ {
+ if !sendMsg(c, buf[:]) || !recvMsg(c, buf[:]) {
+ break
+ }
+ }
+ }()
+ }
+ for i := 0; i < conns; i++ {
+ <-done
+ }
+}
diff --git a/libgo/go/net/tcpsock.go b/libgo/go/net/tcpsock.go
index 4d9ebd214e0..f3dfbd23d34 100644
--- a/libgo/go/net/tcpsock.go
+++ b/libgo/go/net/tcpsock.go
@@ -18,10 +18,18 @@ func (a *TCPAddr) String() string {
if a == nil {
return "<nil>"
}
+ ip := ipEmptyString(a.IP)
if a.Zone != "" {
- return JoinHostPort(a.IP.String()+"%"+a.Zone, itoa(a.Port))
+ return JoinHostPort(ip+"%"+a.Zone, itoa(a.Port))
}
- return JoinHostPort(a.IP.String(), itoa(a.Port))
+ return JoinHostPort(ip, itoa(a.Port))
+}
+
+func (a *TCPAddr) toAddr() Addr {
+ if a == nil {
+ return nil
+ }
+ return a
}
// ResolveTCPAddr parses addr as a TCP address of the form "host:port"
@@ -42,5 +50,5 @@ func ResolveTCPAddr(net, addr string) (*TCPAddr, error) {
if err != nil {
return nil, err
}
- return a.(*TCPAddr), nil
+ return a.toAddr().(*TCPAddr), nil
}
diff --git a/libgo/go/net/tcpsock_plan9.go b/libgo/go/net/tcpsock_plan9.go
index 48334fed7e4..cf9c0f89047 100644
--- a/libgo/go/net/tcpsock_plan9.go
+++ b/libgo/go/net/tcpsock_plan9.go
@@ -65,6 +65,11 @@ func (c *TCPConn) SetKeepAlive(keepalive bool) error {
return syscall.EPLAN9
}
+// SetKeepAlivePeriod sets period between keep alives.
+func (c *TCPConn) SetKeepAlivePeriod(d time.Duration) error {
+ return syscall.EPLAN9
+}
+
// SetNoDelay controls whether the operating system should delay
// packet transmission in hopes of sending fewer packets (Nagle's
// algorithm). The default is true (no delay), meaning that data is
@@ -106,7 +111,7 @@ type TCPListener struct {
}
// AcceptTCP accepts the next incoming call and returns the new
-// connection and the remote address.
+// connection.
func (l *TCPListener) AcceptTCP() (*TCPConn, error) {
if l == nil || l.fd == nil || l.fd.ctl == nil {
return nil, syscall.EINVAL
@@ -153,7 +158,7 @@ func (l *TCPListener) SetDeadline(t time.Time) error {
if l == nil || l.fd == nil || l.fd.ctl == nil {
return syscall.EINVAL
}
- return setDeadline(l.fd, t)
+ return l.fd.setDeadline(t)
}
// File returns a copy of the underlying os.File, set to blocking
diff --git a/libgo/go/net/tcpsock_posix.go b/libgo/go/net/tcpsock_posix.go
index 876edb101ca..00c692e4233 100644
--- a/libgo/go/net/tcpsock_posix.go
+++ b/libgo/go/net/tcpsock_posix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd linux netbsd openbsd windows
+// +build darwin dragonfly freebsd linux netbsd openbsd windows
package net
@@ -46,14 +46,10 @@ func (a *TCPAddr) isWildcard() bool {
}
func (a *TCPAddr) sockaddr(family int) (syscall.Sockaddr, error) {
- return ipToSockaddr(family, a.IP, a.Port, a.Zone)
-}
-
-func (a *TCPAddr) toAddr() sockaddr {
- if a == nil { // nil *TCPAddr
- return nil // nil interface
+ if a == nil {
+ return nil, nil
}
- return a
+ return ipToSockaddr(family, a.IP, a.Port, a.Zone)
}
// TCPConn is an implementation of the Conn interface for TCP network
@@ -121,6 +117,14 @@ func (c *TCPConn) SetKeepAlive(keepalive bool) error {
return setKeepAlive(c.fd, keepalive)
}
+// SetKeepAlivePeriod sets period between keep alives.
+func (c *TCPConn) SetKeepAlivePeriod(d time.Duration) error {
+ if !c.ok() {
+ return syscall.EINVAL
+ }
+ return setKeepAlivePeriod(c.fd, d)
+}
+
// SetNoDelay controls whether the operating system should delay
// packet transmission in hopes of sending fewer packets (Nagle's
// algorithm). The default is true (no delay), meaning that data is
@@ -139,16 +143,16 @@ func DialTCP(net string, laddr, raddr *TCPAddr) (*TCPConn, error) {
switch net {
case "tcp", "tcp4", "tcp6":
default:
- return nil, UnknownNetworkError(net)
+ return nil, &OpError{Op: "dial", Net: net, Addr: raddr, Err: UnknownNetworkError(net)}
}
if raddr == nil {
- return nil, &OpError{"dial", net, nil, errMissingAddress}
+ return nil, &OpError{Op: "dial", Net: net, Addr: nil, Err: errMissingAddress}
}
return dialTCP(net, laddr, raddr, noDeadline)
}
func dialTCP(net string, laddr, raddr *TCPAddr, deadline time.Time) (*TCPConn, error) {
- fd, err := internetSocket(net, laddr.toAddr(), raddr.toAddr(), deadline, syscall.SOCK_STREAM, 0, "dial", sockaddrToTCP)
+ fd, err := internetSocket(net, laddr, raddr, deadline, syscall.SOCK_STREAM, 0, "dial", sockaddrToTCP)
// TCP has a rarely used mechanism called a 'simultaneous connection' in
// which Dial("tcp", addr1, addr2) run on the machine at addr1 can
@@ -178,11 +182,11 @@ func dialTCP(net string, laddr, raddr *TCPAddr, deadline time.Time) (*TCPConn, e
if err == nil {
fd.Close()
}
- fd, err = internetSocket(net, laddr.toAddr(), raddr.toAddr(), deadline, syscall.SOCK_STREAM, 0, "dial", sockaddrToTCP)
+ fd, err = internetSocket(net, laddr, raddr, deadline, syscall.SOCK_STREAM, 0, "dial", sockaddrToTCP)
}
if err != nil {
- return nil, err
+ return nil, &OpError{Op: "dial", Net: net, Addr: raddr, Err: err}
}
return newTCPConn(fd), nil
}
@@ -221,7 +225,7 @@ type TCPListener struct {
}
// AcceptTCP accepts the next incoming call and returns the new
-// connection and the remote address.
+// connection.
func (l *TCPListener) AcceptTCP() (*TCPConn, error) {
if l == nil || l.fd == nil {
return nil, syscall.EINVAL
@@ -261,7 +265,7 @@ func (l *TCPListener) SetDeadline(t time.Time) error {
if l == nil || l.fd == nil {
return syscall.EINVAL
}
- return setDeadline(l.fd, t)
+ return l.fd.setDeadline(t)
}
// File returns a copy of the underlying os.File, set to blocking
@@ -281,19 +285,14 @@ func ListenTCP(net string, laddr *TCPAddr) (*TCPListener, error) {
switch net {
case "tcp", "tcp4", "tcp6":
default:
- return nil, UnknownNetworkError(net)
+ return nil, &OpError{Op: "listen", Net: net, Addr: laddr, Err: UnknownNetworkError(net)}
}
if laddr == nil {
laddr = &TCPAddr{}
}
- fd, err := internetSocket(net, laddr.toAddr(), nil, noDeadline, syscall.SOCK_STREAM, 0, "listen", sockaddrToTCP)
- if err != nil {
- return nil, err
- }
- err = syscall.Listen(fd.sysfd, listenerBacklog)
+ fd, err := internetSocket(net, laddr, nil, noDeadline, syscall.SOCK_STREAM, 0, "listen", sockaddrToTCP)
if err != nil {
- fd.Close()
- return nil, &OpError{"listen", net, laddr, err}
+ return nil, &OpError{Op: "listen", Net: net, Addr: laddr, Err: err}
}
return &TCPListener{fd}, nil
}
diff --git a/libgo/go/net/tcpsockopt_darwin.go b/libgo/go/net/tcpsockopt_darwin.go
new file mode 100644
index 00000000000..33140849c95
--- /dev/null
+++ b/libgo/go/net/tcpsockopt_darwin.go
@@ -0,0 +1,27 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// TCP socket options for darwin
+
+package net
+
+import (
+ "os"
+ "syscall"
+ "time"
+)
+
+// Set keep alive period.
+func setKeepAlivePeriod(fd *netFD, d time.Duration) error {
+ if err := fd.incref(); err != nil {
+ return err
+ }
+ defer fd.decref()
+
+ // The kernel expects seconds so round to next highest second.
+ d += (time.Second - time.Nanosecond)
+ secs := int(d.Seconds())
+
+ return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_TCP, syscall.TCP_KEEPALIVE, secs))
+}
diff --git a/libgo/go/net/tcpsockopt_openbsd.go b/libgo/go/net/tcpsockopt_openbsd.go
new file mode 100644
index 00000000000..3480f932c80
--- /dev/null
+++ b/libgo/go/net/tcpsockopt_openbsd.go
@@ -0,0 +1,27 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// TCP socket options for openbsd
+
+package net
+
+import (
+ "os"
+ "syscall"
+ "time"
+)
+
+// Set keep alive period.
+func setKeepAlivePeriod(fd *netFD, d time.Duration) error {
+ if err := fd.incref(); err != nil {
+ return err
+ }
+ defer fd.decref()
+
+ // The kernel expects seconds so round to next highest second.
+ d += (time.Second - time.Nanosecond)
+ secs := int(d.Seconds())
+
+ return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_TCP, syscall.SO_KEEPALIVE, secs))
+}
diff --git a/libgo/go/net/tcpsockopt_posix.go b/libgo/go/net/tcpsockopt_posix.go
new file mode 100644
index 00000000000..e03476ac634
--- /dev/null
+++ b/libgo/go/net/tcpsockopt_posix.go
@@ -0,0 +1,20 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd windows
+
+package net
+
+import (
+ "os"
+ "syscall"
+)
+
+func setNoDelay(fd *netFD, noDelay bool) error {
+ if err := fd.incref(); err != nil {
+ return err
+ }
+ defer fd.decref()
+ return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_TCP, syscall.TCP_NODELAY, boolint(noDelay)))
+}
diff --git a/libgo/go/net/tcpsockopt_solaris.go b/libgo/go/net/tcpsockopt_solaris.go
new file mode 100644
index 00000000000..a285e2d8d61
--- /dev/null
+++ b/libgo/go/net/tcpsockopt_solaris.go
@@ -0,0 +1,25 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package net
+
+import (
+ "os"
+ "syscall"
+ "time"
+)
+
+// Set keep alive period.
+func setKeepAlivePeriod(fd *netFD, d time.Duration) error {
+ if err := fd.incref(); err != nil {
+ return err
+ }
+ defer fd.decref()
+
+ // The kernel expects milliseconds so round to next highest millisecond.
+ d += (time.Millisecond - time.Nanosecond)
+ msecs := int(d.Nanoseconds() / time.Millisecond)
+
+ return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_TCP, syscall.TCP_KEEPALIVE_THRESHOLD, msecs))
+}
diff --git a/libgo/go/net/tcpsockopt_unix.go b/libgo/go/net/tcpsockopt_unix.go
new file mode 100644
index 00000000000..89d9143b52e
--- /dev/null
+++ b/libgo/go/net/tcpsockopt_unix.go
@@ -0,0 +1,31 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build dragonfly freebsd linux netbsd
+
+package net
+
+import (
+ "os"
+ "syscall"
+ "time"
+)
+
+// Set keep alive period.
+func setKeepAlivePeriod(fd *netFD, d time.Duration) error {
+ if err := fd.incref(); err != nil {
+ return err
+ }
+ defer fd.decref()
+
+ // The kernel expects seconds so round to next highest second.
+ d += (time.Second - time.Nanosecond)
+ secs := int(d.Seconds())
+
+ err := os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_TCP, syscall.TCP_KEEPINTVL, secs))
+ if err != nil {
+ return err
+ }
+ return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_TCP, syscall.TCP_KEEPIDLE, secs))
+}
diff --git a/libgo/go/net/tcpsockopt_windows.go b/libgo/go/net/tcpsockopt_windows.go
new file mode 100644
index 00000000000..0bf4312f248
--- /dev/null
+++ b/libgo/go/net/tcpsockopt_windows.go
@@ -0,0 +1,21 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// TCP socket options for windows
+
+package net
+
+import (
+ "time"
+)
+
+func setKeepAlivePeriod(fd *netFD, d time.Duration) error {
+ if err := fd.incref(); err != nil {
+ return err
+ }
+ defer fd.decref()
+
+ // We can't actually set this per connection. Act as a noop rather than an error.
+ return nil
+}
diff --git a/libgo/go/net/textproto/reader.go b/libgo/go/net/textproto/reader.go
index 5bd26ac8d61..56ece5b087c 100644
--- a/libgo/go/net/textproto/reader.go
+++ b/libgo/go/net/textproto/reader.go
@@ -203,7 +203,7 @@ func parseCodeLine(line string, expectCode int) (code int, continued bool, messa
// ReadCodeLine reads a response code line of the form
// code message
-// where code is a 3-digit status code and the message
+// where code is a three-digit status code and the message
// extends to the rest of the line. An example of such a line is:
// 220 plan9.bell-labs.com ESMTP
//
@@ -231,7 +231,7 @@ func (r *Reader) ReadCodeLine(expectCode int) (code int, message string, err err
// ...
// code message line n
//
-// where code is a 3-digit status code. The first line starts with the
+// where code is a three-digit status code. The first line starts with the
// code and a hyphen. The response is terminated by a line that starts
// with the same code followed by a space. Each line in message is
// separated by a newline (\n).
@@ -456,7 +456,16 @@ func (r *Reader) ReadDotLines() ([]string, error) {
// }
//
func (r *Reader) ReadMIMEHeader() (MIMEHeader, error) {
- m := make(MIMEHeader, 4)
+ // Avoid lots of small slice allocations later by allocating one
+ // large one ahead of time which we'll cut up into smaller
+ // slices. If this isn't big enough later, we allocate small ones.
+ var strs []string
+ hint := r.upcomingHeaderNewlines()
+ if hint > 0 {
+ strs = make([]string, hint)
+ }
+
+ m := make(MIMEHeader, hint)
for {
kv, err := r.readContinuedLineSlice()
if len(kv) == 0 {
@@ -483,7 +492,18 @@ func (r *Reader) ReadMIMEHeader() (MIMEHeader, error) {
}
value := string(kv[i:])
- m[key] = append(m[key], value)
+ vv := m[key]
+ if vv == nil && len(strs) > 0 {
+ // More than likely this will be a single-element key.
+ // Most headers aren't multi-valued.
+ // Set the capacity on strs[0] to 1, so any future append
+ // won't extend the slice into the other strings.
+ vv, strs = strs[:1:1], strs[1:]
+ vv[0] = value
+ m[key] = vv
+ } else {
+ m[key] = append(vv, value)
+ }
if err != nil {
return m, err
@@ -491,6 +511,29 @@ func (r *Reader) ReadMIMEHeader() (MIMEHeader, error) {
}
}
+// upcomingHeaderNewlines returns an approximation of the number of newlines
+// that will be in this header. If it gets confused, it returns 0.
+func (r *Reader) upcomingHeaderNewlines() (n int) {
+ // Try to determine the 'hint' size.
+ r.R.Peek(1) // force a buffer load if empty
+ s := r.R.Buffered()
+ if s == 0 {
+ return
+ }
+ peek, _ := r.R.Peek(s)
+ for len(peek) > 0 {
+ i := bytes.IndexByte(peek, '\n')
+ if i < 3 {
+ // Not present (-1) or found within the next few bytes,
+ // implying we're at the end ("\r\n\r\n" or "\n\n")
+ return
+ }
+ n++
+ peek = peek[i+1:]
+ }
+ return
+}
+
// CanonicalMIMEHeaderKey returns the canonical format of the
// MIME header key s. The canonicalization converts the first
// letter and any letter following a hyphen to upper case;
diff --git a/libgo/go/net/textproto/textproto.go b/libgo/go/net/textproto/textproto.go
index eb6ced1c52e..026eb026b1d 100644
--- a/libgo/go/net/textproto/textproto.go
+++ b/libgo/go/net/textproto/textproto.go
@@ -105,7 +105,7 @@ func Dial(network, addr string) (*Conn, error) {
// if _, _, err = c.ReadCodeLine(110); err != nil {
// return nil, err
// }
-// text, err := c.ReadDotAll()
+// text, err := c.ReadDotBytes()
// if err != nil {
// return nil, err
// }
diff --git a/libgo/go/net/timeout_test.go b/libgo/go/net/timeout_test.go
index 2e92147b8e3..35d427a69c0 100644
--- a/libgo/go/net/timeout_test.go
+++ b/libgo/go/net/timeout_test.go
@@ -325,9 +325,6 @@ func TestReadWriteDeadline(t *testing.T) {
t.Skipf("skipping test on %q", runtime.GOOS)
}
- if !canCancelIO {
- t.Skip("skipping test on this system")
- }
const (
readTimeout = 50 * time.Millisecond
writeTimeout = 250 * time.Millisecond
@@ -496,7 +493,10 @@ func testVariousDeadlines(t *testing.T, maxProcs int) {
clientc <- copyRes{n, err, d}
}()
- const tooLong = 2000 * time.Millisecond
+ tooLong := 2 * time.Second
+ if runtime.GOOS == "windows" {
+ tooLong = 5 * time.Second
+ }
select {
case res := <-clientc:
if isTimeout(res.err) {
@@ -549,7 +549,7 @@ func TestReadDeadlineDataAvailable(t *testing.T) {
}
defer c.Close()
if res := <-servec; res.err != nil || res.n != int64(len(msg)) {
- t.Fatalf("unexpected server Write: n=%d, err=%d; want n=%d, err=nil", res.n, res.err, len(msg))
+ t.Fatalf("unexpected server Write: n=%d, err=%v; want n=%d, err=nil", res.n, res.err, len(msg))
}
c.SetReadDeadline(time.Now().Add(-5 * time.Second)) // in the psat.
buf := make([]byte, len(msg)/2)
@@ -703,3 +703,40 @@ func TestProlongTimeout(t *testing.T) {
c.Write(buf[:])
}
}
+
+func TestDeadlineRace(t *testing.T) {
+ switch runtime.GOOS {
+ case "plan9":
+ t.Skipf("skipping test on %q", runtime.GOOS)
+ }
+
+ N := 1000
+ if testing.Short() {
+ N = 50
+ }
+ defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
+ ln := newLocalListener(t)
+ defer ln.Close()
+ c, err := Dial("tcp", ln.Addr().String())
+ if err != nil {
+ t.Fatalf("Dial: %v", err)
+ }
+ defer c.Close()
+ done := make(chan bool)
+ go func() {
+ t := time.NewTicker(2 * time.Microsecond).C
+ for i := 0; i < N; i++ {
+ if err := c.SetDeadline(time.Now().Add(2 * time.Microsecond)); err != nil {
+ break
+ }
+ <-t
+ }
+ done <- true
+ }()
+ var buf [1]byte
+ for i := 0; i < N; i++ {
+ c.Read(buf[:]) // ignore possible timeout errors
+ }
+ c.Close()
+ <-done
+}
diff --git a/libgo/go/net/udp_test.go b/libgo/go/net/udp_test.go
index 4278f6dd4bc..6f4d2152c3c 100644
--- a/libgo/go/net/udp_test.go
+++ b/libgo/go/net/udp_test.go
@@ -5,53 +5,31 @@
package net
import (
- "fmt"
"reflect"
"runtime"
+ "strings"
"testing"
)
-type resolveUDPAddrTest struct {
- net string
- litAddr string
- addr *UDPAddr
- err error
-}
-
-var resolveUDPAddrTests = []resolveUDPAddrTest{
- {"udp", "127.0.0.1:0", &UDPAddr{IP: IPv4(127, 0, 0, 1), Port: 0}, nil},
- {"udp4", "127.0.0.1:65535", &UDPAddr{IP: IPv4(127, 0, 0, 1), Port: 65535}, nil},
-
- {"udp", "[::1]:1", &UDPAddr{IP: ParseIP("::1"), Port: 1}, nil},
- {"udp6", "[::1]:65534", &UDPAddr{IP: ParseIP("::1"), Port: 65534}, nil},
-
- {"udp", "[::1%en0]:1", &UDPAddr{IP: ParseIP("::1"), Port: 1, Zone: "en0"}, nil},
- {"udp6", "[::1%911]:2", &UDPAddr{IP: ParseIP("::1"), Port: 2, Zone: "911"}, nil},
-
- {"", "127.0.0.1:0", &UDPAddr{IP: IPv4(127, 0, 0, 1), Port: 0}, nil}, // Go 1.0 behavior
- {"", "[::1]:0", &UDPAddr{IP: ParseIP("::1"), Port: 0}, nil}, // Go 1.0 behavior
-
- {"sip", "127.0.0.1:0", nil, UnknownNetworkError("sip")},
-}
-
-func init() {
- if ifi := loopbackInterface(); ifi != nil {
- index := fmt.Sprintf("%v", ifi.Index)
- resolveUDPAddrTests = append(resolveUDPAddrTests, []resolveUDPAddrTest{
- {"udp6", "[fe80::1%" + ifi.Name + "]:3", &UDPAddr{IP: ParseIP("fe80::1"), Port: 3, Zone: zoneToString(ifi.Index)}, nil},
- {"udp6", "[fe80::1%" + index + "]:4", &UDPAddr{IP: ParseIP("fe80::1"), Port: 4, Zone: index}, nil},
- }...)
- }
-}
-
func TestResolveUDPAddr(t *testing.T) {
- for _, tt := range resolveUDPAddrTests {
- addr, err := ResolveUDPAddr(tt.net, tt.litAddr)
+ for _, tt := range resolveTCPAddrTests {
+ net := strings.Replace(tt.net, "tcp", "udp", -1)
+ addr, err := ResolveUDPAddr(net, tt.litAddrOrName)
if err != tt.err {
- t.Fatalf("ResolveUDPAddr(%v, %v) failed: %v", tt.net, tt.litAddr, err)
+ t.Fatalf("ResolveUDPAddr(%q, %q) failed: %v", net, tt.litAddrOrName, err)
}
- if !reflect.DeepEqual(addr, tt.addr) {
- t.Fatalf("got %#v; expected %#v", addr, tt.addr)
+ if !reflect.DeepEqual(addr, (*UDPAddr)(tt.addr)) {
+ t.Fatalf("ResolveUDPAddr(%q, %q) = %#v, want %#v", net, tt.litAddrOrName, addr, tt.addr)
+ }
+ if err == nil {
+ str := addr.String()
+ addr1, err := ResolveUDPAddr(net, str)
+ if err != nil {
+ t.Fatalf("ResolveUDPAddr(%q, %q) [from %q]: %v", net, str, tt.litAddrOrName, err)
+ }
+ if !reflect.DeepEqual(addr1, addr) {
+ t.Fatalf("ResolveUDPAddr(%q, %q) [from %q] = %#v, want %#v", net, str, tt.litAddrOrName, addr1, addr)
+ }
}
}
}
@@ -224,7 +202,7 @@ func TestIPv6LinkLocalUnicastUDP(t *testing.T) {
{"udp6", "[" + laddr + "%" + ifi.Name + "]:0", false},
}
switch runtime.GOOS {
- case "darwin", "freebsd", "openbsd", "netbsd":
+ case "darwin", "dragonfly", "freebsd", "openbsd", "netbsd":
tests = append(tests, []test{
{"udp", "[localhost%" + ifi.Name + "]:0", true},
{"udp6", "[localhost%" + ifi.Name + "]:0", true},
diff --git a/libgo/go/net/udpsock.go b/libgo/go/net/udpsock.go
index 5ce7d6bea0f..0dd0dbd7114 100644
--- a/libgo/go/net/udpsock.go
+++ b/libgo/go/net/udpsock.go
@@ -22,10 +22,18 @@ func (a *UDPAddr) String() string {
if a == nil {
return "<nil>"
}
+ ip := ipEmptyString(a.IP)
if a.Zone != "" {
- return JoinHostPort(a.IP.String()+"%"+a.Zone, itoa(a.Port))
+ return JoinHostPort(ip+"%"+a.Zone, itoa(a.Port))
}
- return JoinHostPort(a.IP.String(), itoa(a.Port))
+ return JoinHostPort(ip, itoa(a.Port))
+}
+
+func (a *UDPAddr) toAddr() Addr {
+ if a == nil {
+ return nil
+ }
+ return a
}
// ResolveUDPAddr parses addr as a UDP address of the form "host:port"
@@ -46,5 +54,5 @@ func ResolveUDPAddr(net, addr string) (*UDPAddr, error) {
if err != nil {
return nil, err
}
- return a.(*UDPAddr), nil
+ return a.toAddr().(*UDPAddr), nil
}
diff --git a/libgo/go/net/udpsock_plan9.go b/libgo/go/net/udpsock_plan9.go
index 12a34839905..73621706d5c 100644
--- a/libgo/go/net/udpsock_plan9.go
+++ b/libgo/go/net/udpsock_plan9.go
@@ -73,6 +73,9 @@ func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (int, error) {
if !c.ok() || c.fd.data == nil {
return 0, syscall.EINVAL
}
+ if addr == nil {
+ return 0, &OpError{Op: "write", Net: c.fd.dir, Addr: nil, Err: errMissingAddress}
+ }
h := new(udpHeader)
h.raddr = addr.IP.To16()
h.laddr = c.fd.laddr.(*UDPAddr).IP.To16()
diff --git a/libgo/go/net/udpsock_posix.go b/libgo/go/net/udpsock_posix.go
index b90cb030d81..142da8186f1 100644
--- a/libgo/go/net/udpsock_posix.go
+++ b/libgo/go/net/udpsock_posix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd linux netbsd openbsd windows
+// +build darwin dragonfly freebsd linux netbsd openbsd windows
package net
@@ -39,14 +39,10 @@ func (a *UDPAddr) isWildcard() bool {
}
func (a *UDPAddr) sockaddr(family int) (syscall.Sockaddr, error) {
- return ipToSockaddr(family, a.IP, a.Port, a.Zone)
-}
-
-func (a *UDPAddr) toAddr() sockaddr {
- if a == nil { // nil *UDPAddr
- return nil // nil interface
+ if a == nil {
+ return nil, nil
}
- return a
+ return ipToSockaddr(family, a.IP, a.Port, a.Zone)
}
// UDPConn is the implementation of the Conn and PacketConn interfaces
@@ -121,6 +117,9 @@ func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (int, error) {
if c.fd.isConnected {
return 0, &OpError{"write", c.fd.net, addr, ErrWriteToConnected}
}
+ if addr == nil {
+ return 0, &OpError{Op: "write", Net: c.fd.net, Addr: nil, Err: errMissingAddress}
+ }
sa, err := addr.sockaddr(c.fd.family)
if err != nil {
return 0, &OpError{"write", c.fd.net, addr, err}
@@ -150,6 +149,9 @@ func (c *UDPConn) WriteMsgUDP(b, oob []byte, addr *UDPAddr) (n, oobn int, err er
if c.fd.isConnected {
return 0, 0, &OpError{"write", c.fd.net, addr, ErrWriteToConnected}
}
+ if addr == nil {
+ return 0, 0, &OpError{Op: "write", Net: c.fd.net, Addr: nil, Err: errMissingAddress}
+ }
sa, err := addr.sockaddr(c.fd.family)
if err != nil {
return 0, 0, &OpError{"write", c.fd.net, addr, err}
@@ -161,21 +163,21 @@ func (c *UDPConn) WriteMsgUDP(b, oob []byte, addr *UDPAddr) (n, oobn int, err er
// which must be "udp", "udp4", or "udp6". If laddr is not nil, it is
// used as the local address for the connection.
func DialUDP(net string, laddr, raddr *UDPAddr) (*UDPConn, error) {
- return dialUDP(net, laddr, raddr, noDeadline)
-}
-
-func dialUDP(net string, laddr, raddr *UDPAddr, deadline time.Time) (*UDPConn, error) {
switch net {
case "udp", "udp4", "udp6":
default:
- return nil, UnknownNetworkError(net)
+ return nil, &OpError{Op: "dial", Net: net, Addr: raddr, Err: UnknownNetworkError(net)}
}
if raddr == nil {
- return nil, &OpError{"dial", net, nil, errMissingAddress}
+ return nil, &OpError{Op: "dial", Net: net, Addr: nil, Err: errMissingAddress}
}
- fd, err := internetSocket(net, laddr.toAddr(), raddr.toAddr(), deadline, syscall.SOCK_DGRAM, 0, "dial", sockaddrToUDP)
+ return dialUDP(net, laddr, raddr, noDeadline)
+}
+
+func dialUDP(net string, laddr, raddr *UDPAddr, deadline time.Time) (*UDPConn, error) {
+ fd, err := internetSocket(net, laddr, raddr, deadline, syscall.SOCK_DGRAM, 0, "dial", sockaddrToUDP)
if err != nil {
- return nil, err
+ return nil, &OpError{Op: "dial", Net: net, Addr: raddr, Err: err}
}
return newUDPConn(fd), nil
}
@@ -191,14 +193,14 @@ func ListenUDP(net string, laddr *UDPAddr) (*UDPConn, error) {
switch net {
case "udp", "udp4", "udp6":
default:
- return nil, UnknownNetworkError(net)
+ return nil, &OpError{Op: "listen", Net: net, Addr: laddr, Err: UnknownNetworkError(net)}
}
if laddr == nil {
laddr = &UDPAddr{}
}
- fd, err := internetSocket(net, laddr.toAddr(), nil, noDeadline, syscall.SOCK_DGRAM, 0, "listen", sockaddrToUDP)
+ fd, err := internetSocket(net, laddr, nil, noDeadline, syscall.SOCK_DGRAM, 0, "listen", sockaddrToUDP)
if err != nil {
- return nil, err
+ return nil, &OpError{Op: "listen", Net: net, Addr: laddr, Err: err}
}
return newUDPConn(fd), nil
}
@@ -211,25 +213,25 @@ func ListenMulticastUDP(net string, ifi *Interface, gaddr *UDPAddr) (*UDPConn, e
switch net {
case "udp", "udp4", "udp6":
default:
- return nil, UnknownNetworkError(net)
+ return nil, &OpError{Op: "listen", Net: net, Addr: gaddr, Err: UnknownNetworkError(net)}
}
if gaddr == nil || gaddr.IP == nil {
- return nil, &OpError{"listen", net, nil, errMissingAddress}
+ return nil, &OpError{Op: "listen", Net: net, Addr: nil, Err: errMissingAddress}
}
- fd, err := internetSocket(net, gaddr.toAddr(), nil, noDeadline, syscall.SOCK_DGRAM, 0, "listen", sockaddrToUDP)
+ fd, err := internetSocket(net, gaddr, nil, noDeadline, syscall.SOCK_DGRAM, 0, "listen", sockaddrToUDP)
if err != nil {
- return nil, err
+ return nil, &OpError{Op: "listen", Net: net, Addr: gaddr, Err: err}
}
c := newUDPConn(fd)
if ip4 := gaddr.IP.To4(); ip4 != nil {
if err := listenIPv4MulticastUDP(c, ifi, ip4); err != nil {
c.Close()
- return nil, &OpError{"listen", net, &IPAddr{IP: ip4}, err}
+ return nil, &OpError{Op: "listen", Net: net, Addr: &IPAddr{IP: ip4}, Err: err}
}
} else {
if err := listenIPv6MulticastUDP(c, ifi, gaddr.IP); err != nil {
c.Close()
- return nil, &OpError{"listen", net, &IPAddr{IP: gaddr.IP}, err}
+ return nil, &OpError{Op: "listen", Net: net, Addr: &IPAddr{IP: gaddr.IP}, Err: err}
}
}
return c, nil
diff --git a/libgo/go/net/unicast_posix_test.go b/libgo/go/net/unicast_posix_test.go
index b0588f4e529..5deb8f47c6c 100644
--- a/libgo/go/net/unicast_posix_test.go
+++ b/libgo/go/net/unicast_posix_test.go
@@ -349,12 +349,16 @@ func checkDualStackSecondListener(t *testing.T, net, laddr string, xerr, err err
if xerr == nil && err != nil || xerr != nil && err == nil {
t.Fatalf("Second Listen(%q, %q) returns %v, expected %v", net, laddr, err, xerr)
}
- l.(*TCPListener).Close()
+ if err == nil {
+ l.(*TCPListener).Close()
+ }
case "udp", "udp4", "udp6":
if xerr == nil && err != nil || xerr != nil && err == nil {
t.Fatalf("Second ListenPacket(%q, %q) returns %v, expected %v", net, laddr, err, xerr)
}
- l.(*UDPConn).Close()
+ if err == nil {
+ l.(*UDPConn).Close()
+ }
default:
t.Fatalf("Unexpected network: %q", net)
}
@@ -436,8 +440,8 @@ func TestWildWildcardListener(t *testing.T) {
}
defer func() {
- if recover() != nil {
- t.Fatalf("panicked")
+ if p := recover(); p != nil {
+ t.Fatalf("Listen, ListenPacket or protocol-specific Listen panicked: %v", p)
}
}()
diff --git a/libgo/go/net/unix_test.go b/libgo/go/net/unix_test.go
index 5e63e9d9dec..91df3ff8876 100644
--- a/libgo/go/net/unix_test.go
+++ b/libgo/go/net/unix_test.go
@@ -107,7 +107,7 @@ func TestReadUnixgramWithZeroBytesBuffer(t *testing.T) {
}
}
-func TestUnixAutobind(t *testing.T) {
+func TestUnixgramAutobind(t *testing.T) {
if runtime.GOOS != "linux" {
t.Skip("skipping: autobind is linux only")
}
@@ -139,8 +139,21 @@ func TestUnixAutobind(t *testing.T) {
}
}
+func TestUnixAutobindClose(t *testing.T) {
+ if runtime.GOOS != "linux" {
+ t.Skip("skipping: autobind is linux only")
+ }
+ laddr := &UnixAddr{Name: "", Net: "unix"}
+ ln, err := ListenUnix("unix", laddr)
+ if err != nil {
+ t.Fatalf("ListenUnix failed: %v", err)
+ }
+ ln.Close()
+}
+
func TestUnixConnLocalAndRemoteNames(t *testing.T) {
for _, laddr := range []string{"", testUnixAddr()} {
+ laddr := laddr
taddr := testUnixAddr()
ta, err := ResolveUnixAddr("unix", taddr)
if err != nil {
@@ -196,6 +209,7 @@ func TestUnixConnLocalAndRemoteNames(t *testing.T) {
func TestUnixgramConnLocalAndRemoteNames(t *testing.T) {
for _, laddr := range []string{"", testUnixAddr()} {
+ laddr := laddr
taddr := testUnixAddr()
ta, err := ResolveUnixAddr("unixgram", taddr)
if err != nil {
@@ -212,7 +226,6 @@ func TestUnixgramConnLocalAndRemoteNames(t *testing.T) {
var la *UnixAddr
if laddr != "" {
- var err error
if la, err = ResolveUnixAddr("unixgram", laddr); err != nil {
t.Fatalf("ResolveUnixAddr failed: %v", err)
}
diff --git a/libgo/go/net/unixsock.go b/libgo/go/net/unixsock.go
index 21a19eca2c0..85955845b80 100644
--- a/libgo/go/net/unixsock.go
+++ b/libgo/go/net/unixsock.go
@@ -24,8 +24,8 @@ func (a *UnixAddr) String() string {
}
func (a *UnixAddr) toAddr() Addr {
- if a == nil { // nil *UnixAddr
- return nil // nil interface
+ if a == nil {
+ return nil
}
return a
}
diff --git a/libgo/go/net/unixsock_plan9.go b/libgo/go/net/unixsock_plan9.go
index 8a1281fb1a4..c60c1d83bb3 100644
--- a/libgo/go/net/unixsock_plan9.go
+++ b/libgo/go/net/unixsock_plan9.go
@@ -97,7 +97,7 @@ func ListenUnix(net string, laddr *UnixAddr) (*UnixListener, error) {
}
// AcceptUnix accepts the next incoming call and returns the new
-// connection and the remote address.
+// connection.
func (l *UnixListener) AcceptUnix() (*UnixConn, error) {
return nil, syscall.EPLAN9
}
diff --git a/libgo/go/net/unixsock_posix.go b/libgo/go/net/unixsock_posix.go
index 5db30df95fc..b82f3cee0b5 100644
--- a/libgo/go/net/unixsock_posix.go
+++ b/libgo/go/net/unixsock_posix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd linux netbsd openbsd windows
+// +build darwin dragonfly freebsd linux netbsd openbsd windows
package net
@@ -13,14 +13,7 @@ import (
"time"
)
-func (a *UnixAddr) isUnnamed() bool {
- if a == nil || a.Name == "" {
- return true
- }
- return false
-}
-
-func unixSocket(net string, laddr, raddr *UnixAddr, mode string, deadline time.Time) (*netFD, error) {
+func unixSocket(net string, laddr, raddr sockaddr, mode string, deadline time.Time) (*netFD, error) {
var sotype int
switch net {
case "unix":
@@ -33,19 +26,18 @@ func unixSocket(net string, laddr, raddr *UnixAddr, mode string, deadline time.T
return nil, UnknownNetworkError(net)
}
- var la, ra syscall.Sockaddr
switch mode {
case "dial":
- if !laddr.isUnnamed() {
- la = &syscall.SockaddrUnix{Name: laddr.Name}
+ if laddr != nil && laddr.isWildcard() {
+ laddr = nil
}
- if raddr != nil {
- ra = &syscall.SockaddrUnix{Name: raddr.Name}
- } else if sotype != syscall.SOCK_DGRAM || laddr.isUnnamed() {
- return nil, &OpError{Op: mode, Net: net, Err: errMissingAddress}
+ if raddr != nil && raddr.isWildcard() {
+ raddr = nil
+ }
+ if raddr == nil && (sotype != syscall.SOCK_DGRAM || laddr == nil) {
+ return nil, errMissingAddress
}
case "listen":
- la = &syscall.SockaddrUnix{Name: laddr.Name}
default:
return nil, errors.New("unknown mode: " + mode)
}
@@ -57,19 +49,11 @@ func unixSocket(net string, laddr, raddr *UnixAddr, mode string, deadline time.T
f = sockaddrToUnixpacket
}
- fd, err := socket(net, syscall.AF_UNIX, sotype, 0, false, la, ra, deadline, f)
+ fd, err := socket(net, syscall.AF_UNIX, sotype, 0, false, laddr, raddr, deadline, f)
if err != nil {
- goto error
+ return nil, err
}
return fd, nil
-
-error:
- addr := raddr
- switch mode {
- case "listen":
- addr = laddr
- }
- return nil, &OpError{Op: mode, Net: net, Addr: addr, Err: err}
}
func sockaddrToUnix(sa syscall.Sockaddr) Addr {
@@ -106,6 +90,21 @@ func sotypeToNet(sotype int) string {
}
}
+func (a *UnixAddr) family() int {
+ return syscall.AF_UNIX
+}
+
+func (a *UnixAddr) isWildcard() bool {
+ return a == nil || a.Name == ""
+}
+
+func (a *UnixAddr) sockaddr(family int) (syscall.Sockaddr, error) {
+ if a == nil {
+ return nil, nil
+ }
+ return &syscall.SockaddrUnix{Name: a.Name}, nil
+}
+
// UnixConn is an implementation of the Conn interface for connections
// to Unix domain sockets.
type UnixConn struct {
@@ -172,6 +171,9 @@ func (c *UnixConn) WriteToUnix(b []byte, addr *UnixAddr) (n int, err error) {
if !c.ok() {
return 0, syscall.EINVAL
}
+ if addr == nil {
+ return 0, &OpError{Op: "write", Net: c.fd.net, Addr: nil, Err: errMissingAddress}
+ }
if addr.Net != sotypeToNet(c.fd.sotype) {
return 0, syscall.EAFNOSUPPORT
}
@@ -230,18 +232,18 @@ func (c *UnixConn) CloseWrite() error {
// which must be "unix", "unixgram" or "unixpacket". If laddr is not
// nil, it is used as the local address for the connection.
func DialUnix(net string, laddr, raddr *UnixAddr) (*UnixConn, error) {
- return dialUnix(net, laddr, raddr, noDeadline)
-}
-
-func dialUnix(net string, laddr, raddr *UnixAddr, deadline time.Time) (*UnixConn, error) {
switch net {
case "unix", "unixgram", "unixpacket":
default:
- return nil, UnknownNetworkError(net)
+ return nil, &OpError{Op: "dial", Net: net, Addr: raddr, Err: UnknownNetworkError(net)}
}
+ return dialUnix(net, laddr, raddr, noDeadline)
+}
+
+func dialUnix(net string, laddr, raddr *UnixAddr, deadline time.Time) (*UnixConn, error) {
fd, err := unixSocket(net, laddr, raddr, "dial", deadline)
if err != nil {
- return nil, err
+ return nil, &OpError{Op: "dial", Net: net, Addr: raddr, Err: err}
}
return newUnixConn(fd), nil
}
@@ -260,25 +262,20 @@ func ListenUnix(net string, laddr *UnixAddr) (*UnixListener, error) {
switch net {
case "unix", "unixpacket":
default:
- return nil, UnknownNetworkError(net)
+ return nil, &OpError{Op: "listen", Net: net, Addr: laddr, Err: UnknownNetworkError(net)}
}
if laddr == nil {
- return nil, &OpError{"listen", net, nil, errMissingAddress}
+ return nil, &OpError{Op: "listen", Net: net, Addr: nil, Err: errMissingAddress}
}
fd, err := unixSocket(net, laddr, nil, "listen", noDeadline)
if err != nil {
- return nil, err
- }
- err = syscall.Listen(fd.sysfd, listenerBacklog)
- if err != nil {
- fd.Close()
return nil, &OpError{Op: "listen", Net: net, Addr: laddr, Err: err}
}
- return &UnixListener{fd, laddr.Name}, nil
+ return &UnixListener{fd, fd.laddr.String()}, nil
}
// AcceptUnix accepts the next incoming call and returns the new
-// connection and the remote address.
+// connection.
func (l *UnixListener) AcceptUnix() (*UnixConn, error) {
if l == nil || l.fd == nil {
return nil, syscall.EINVAL
@@ -333,7 +330,7 @@ func (l *UnixListener) SetDeadline(t time.Time) (err error) {
if l == nil || l.fd == nil {
return syscall.EINVAL
}
- return setDeadline(l.fd, t)
+ return l.fd.setDeadline(t)
}
// File returns a copy of the underlying os.File, set to blocking
@@ -353,14 +350,14 @@ func ListenUnixgram(net string, laddr *UnixAddr) (*UnixConn, error) {
switch net {
case "unixgram":
default:
- return nil, UnknownNetworkError(net)
+ return nil, &OpError{Op: "listen", Net: net, Addr: laddr, Err: UnknownNetworkError(net)}
}
if laddr == nil {
- return nil, &OpError{"listen", net, nil, errMissingAddress}
+ return nil, &OpError{Op: "listen", Net: net, Addr: nil, Err: errMissingAddress}
}
fd, err := unixSocket(net, laddr, nil, "listen", noDeadline)
if err != nil {
- return nil, err
+ return nil, &OpError{Op: "listen", Net: net, Addr: laddr, Err: err}
}
return newUnixConn(fd), nil
}
diff --git a/libgo/go/net/url/url.go b/libgo/go/net/url/url.go
index 459dc473ceb..597cb51c883 100644
--- a/libgo/go/net/url/url.go
+++ b/libgo/go/net/url/url.go
@@ -451,14 +451,17 @@ func (u *URL) String() string {
} else {
if u.Scheme != "" || u.Host != "" || u.User != nil {
buf.WriteString("//")
- if u := u.User; u != nil {
- buf.WriteString(u.String())
+ if ui := u.User; ui != nil {
+ buf.WriteString(ui.String())
buf.WriteByte('@')
}
if h := u.Host; h != "" {
buf.WriteString(h)
}
}
+ if u.Path != "" && u.Path[0] != '/' && u.Host != "" {
+ buf.WriteByte('/')
+ }
buf.WriteString(escape(u.Path, encodePath))
}
if u.RawQuery != "" {
diff --git a/libgo/go/net/url/url_test.go b/libgo/go/net/url/url_test.go
index 9d81289ceba..7578eb15b90 100644
--- a/libgo/go/net/url/url_test.go
+++ b/libgo/go/net/url/url_test.go
@@ -260,6 +260,14 @@ var urltests = []URLTest{
},
"mailto:webmaster@golang.org",
},
+ // Relative path
+ {
+ "a/b/c",
+ &URL{
+ Path: "a/b/c",
+ },
+ "a/b/c",
+ },
}
// more useful string for debugging than fmt's struct printer
@@ -372,6 +380,22 @@ func DoTestString(t *testing.T, parse func(string) (*URL, error), name string, t
func TestURLString(t *testing.T) {
DoTestString(t, Parse, "Parse", urltests)
+
+ // no leading slash on path should prepend
+ // slash on String() call
+ noslash := URLTest{
+ "http://www.google.com/search",
+ &URL{
+ Scheme: "http",
+ Host: "www.google.com",
+ Path: "search",
+ },
+ "",
+ }
+ s := noslash.out.String()
+ if s != noslash.in {
+ t.Errorf("Expected %s; go %s", noslash.in, s)
+ }
}
type EscapeTest struct {
diff --git a/libgo/go/os/dir_unix.go b/libgo/go/os/dir_unix.go
index f41f939a97b..9fa7ad664f4 100644
--- a/libgo/go/os/dir_unix.go
+++ b/libgo/go/os/dir_unix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd linux netbsd openbsd
+// +build darwin dragonfly freebsd linux netbsd openbsd
package os
diff --git a/libgo/go/os/doc.go b/libgo/go/os/doc.go
index 2cc17530c2f..a954e313d13 100644
--- a/libgo/go/os/doc.go
+++ b/libgo/go/os/doc.go
@@ -58,7 +58,7 @@ func (p *ProcessState) SystemTime() time.Duration {
return p.systemTime()
}
-// Exited returns whether the program has exited.
+// Exited reports whether the program has exited.
func (p *ProcessState) Exited() bool {
return p.exited()
}
@@ -106,6 +106,9 @@ func Hostname() (name string, err error) {
// directory, Readdir returns the FileInfo read until that point
// and a non-nil error.
func (f *File) Readdir(n int) (fi []FileInfo, err error) {
+ if f == nil {
+ return nil, ErrInvalid
+ }
return f.readdir(n)
}
@@ -122,5 +125,8 @@ func (f *File) Readdir(n int) (fi []FileInfo, err error) {
// directory, Readdirnames returns the names read until that point and
// a non-nil error.
func (f *File) Readdirnames(n int) (names []string, err error) {
+ if f == nil {
+ return nil, ErrInvalid
+ }
return f.readdirnames(n)
}
diff --git a/libgo/go/os/env_unix_test.go b/libgo/go/os/env_unix_test.go
index 7eb4dc0ff4a..e16d71a6492 100644
--- a/libgo/go/os/env_unix_test.go
+++ b/libgo/go/os/env_unix_test.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd linux netbsd openbsd
+// +build darwin dragonfly freebsd linux netbsd openbsd
package os_test
diff --git a/libgo/go/os/error.go b/libgo/go/os/error.go
index a7977ff1914..8810e693067 100644
--- a/libgo/go/os/error.go
+++ b/libgo/go/os/error.go
@@ -43,20 +43,23 @@ func NewSyscallError(syscall string, err error) error {
return &SyscallError{syscall, err}
}
-// IsExist returns whether the error is known to report that a file or directory
-// already exists. It is satisfied by ErrExist as well as some syscall errors.
+// IsExist returns a boolean indicating whether the error is known to report
+// that a file or directory already exists. It is satisfied by ErrExist as
+// well as some syscall errors.
func IsExist(err error) bool {
return isExist(err)
}
-// IsNotExist returns whether the error is known to report that a file or directory
-// does not exist. It is satisfied by ErrNotExist as well as some syscall errors.
+// IsNotExist returns a boolean indicating whether the error is known to
+// report that a file or directory does not exist. It is satisfied by
+// ErrNotExist as well as some syscall errors.
func IsNotExist(err error) bool {
return isNotExist(err)
}
-// IsPermission returns whether the error is known to report that permission is denied.
-// It is satisfied by ErrPermission as well as some syscall errors.
+// IsPermission returns a boolean indicating whether the error is known to
+// report that permission is denied. It is satisfied by ErrPermission as well
+// as some syscall errors.
func IsPermission(err error) bool {
return isPermission(err)
}
diff --git a/libgo/go/os/error_posix.go b/libgo/go/os/error_posix.go
deleted file mode 100644
index 81b626aecb2..00000000000
--- a/libgo/go/os/error_posix.go
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build darwin freebsd linux netbsd openbsd
-
-package os
-
-import "syscall"
-
-func isExist(err error) bool {
- switch pe := err.(type) {
- case nil:
- return false
- case *PathError:
- err = pe.Err
- case *LinkError:
- err = pe.Err
- }
- return err == syscall.EEXIST || err == ErrExist
-}
-
-func isNotExist(err error) bool {
- switch pe := err.(type) {
- case nil:
- return false
- case *PathError:
- err = pe.Err
- case *LinkError:
- err = pe.Err
- }
- return err == syscall.ENOENT || err == ErrNotExist
-}
-
-func isPermission(err error) bool {
- switch pe := err.(type) {
- case nil:
- return false
- case *PathError:
- err = pe.Err
- case *LinkError:
- err = pe.Err
- }
- return err == syscall.EACCES || err == syscall.EPERM || err == ErrPermission
-}
diff --git a/libgo/go/os/error_unix.go b/libgo/go/os/error_unix.go
new file mode 100644
index 00000000000..6250349e5ba
--- /dev/null
+++ b/libgo/go/os/error_unix.go
@@ -0,0 +1,45 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd
+
+package os
+
+import "syscall"
+
+func isExist(err error) bool {
+ switch pe := err.(type) {
+ case nil:
+ return false
+ case *PathError:
+ err = pe.Err
+ case *LinkError:
+ err = pe.Err
+ }
+ return err == syscall.EEXIST || err == ErrExist
+}
+
+func isNotExist(err error) bool {
+ switch pe := err.(type) {
+ case nil:
+ return false
+ case *PathError:
+ err = pe.Err
+ case *LinkError:
+ err = pe.Err
+ }
+ return err == syscall.ENOENT || err == ErrNotExist
+}
+
+func isPermission(err error) bool {
+ switch pe := err.(type) {
+ case nil:
+ return false
+ case *PathError:
+ err = pe.Err
+ case *LinkError:
+ err = pe.Err
+ }
+ return err == syscall.EACCES || err == syscall.EPERM || err == ErrPermission
+}
diff --git a/libgo/go/os/exec/exec.go b/libgo/go/os/exec/exec.go
index a3bbcf3005a..491cc242bb2 100644
--- a/libgo/go/os/exec/exec.go
+++ b/libgo/go/os/exec/exec.go
@@ -13,6 +13,7 @@ import (
"io"
"os"
"strconv"
+ "sync"
"syscall"
)
@@ -357,6 +358,10 @@ func (c *Cmd) CombinedOutput() ([]byte, error) {
// StdinPipe returns a pipe that will be connected to the command's
// standard input when the command starts.
+// The pipe will be closed automatically after Wait sees the command exit.
+// A caller need only call Close to force the pipe to close sooner.
+// For example, if the command being run will not exit until standard input
+// is closed, the caller must close the pipe.
func (c *Cmd) StdinPipe() (io.WriteCloser, error) {
if c.Stdin != nil {
return nil, errors.New("exec: Stdin already set")
@@ -370,13 +375,33 @@ func (c *Cmd) StdinPipe() (io.WriteCloser, error) {
}
c.Stdin = pr
c.closeAfterStart = append(c.closeAfterStart, pr)
- c.closeAfterWait = append(c.closeAfterWait, pw)
- return pw, nil
+ wc := &closeOnce{File: pw}
+ c.closeAfterWait = append(c.closeAfterWait, wc)
+ return wc, nil
+}
+
+type closeOnce struct {
+ *os.File
+
+ close sync.Once
+ closeErr error
+}
+
+func (c *closeOnce) Close() error {
+ c.close.Do(func() {
+ c.closeErr = c.File.Close()
+ })
+ return c.closeErr
}
// StdoutPipe returns a pipe that will be connected to the command's
// standard output when the command starts.
-// The pipe will be closed automatically after Wait sees the command exit.
+//
+// Wait will close the pipe after seeing the command exit, so most callers
+// need not close the pipe themselves; however, an implication is that
+// it is incorrect to call Wait before all reads from the pipe have completed.
+// For the same reason, it is incorrect to call Run when using StdoutPipe.
+// See the example for idiomatic usage.
func (c *Cmd) StdoutPipe() (io.ReadCloser, error) {
if c.Stdout != nil {
return nil, errors.New("exec: Stdout already set")
@@ -396,7 +421,12 @@ func (c *Cmd) StdoutPipe() (io.ReadCloser, error) {
// StderrPipe returns a pipe that will be connected to the command's
// standard error when the command starts.
-// The pipe will be closed automatically after Wait sees the command exit.
+//
+// Wait will close the pipe after seeing the command exit, so most callers
+// need not close the pipe themselves; however, an implication is that
+// it is incorrect to call Wait before all reads from the pipe have completed.
+// For the same reason, it is incorrect to use Run when using StderrPipe.
+// See the StdoutPipe example for idiomatic usage.
func (c *Cmd) StderrPipe() (io.ReadCloser, error) {
if c.Stderr != nil {
return nil, errors.New("exec: Stderr already set")
diff --git a/libgo/go/os/exec/exec_test.go b/libgo/go/os/exec/exec_test.go
index fa7e88c6596..b6addcd45a6 100644
--- a/libgo/go/os/exec/exec_test.go
+++ b/libgo/go/os/exec/exec_test.go
@@ -156,6 +156,34 @@ func TestPipes(t *testing.T) {
check("Wait", err)
}
+const stdinCloseTestString = "Some test string."
+
+// Issue 6270.
+func TestStdinClose(t *testing.T) {
+ check := func(what string, err error) {
+ if err != nil {
+ t.Fatalf("%s: %v", what, err)
+ }
+ }
+ cmd := helperCommand("stdinClose")
+ stdin, err := cmd.StdinPipe()
+ check("StdinPipe", err)
+ // Check that we can access methods of the underlying os.File.`
+ if _, ok := stdin.(interface {
+ Fd() uintptr
+ }); !ok {
+ t.Error("can't access methods of underlying *os.File")
+ }
+ check("Start", cmd.Start())
+ go func() {
+ _, err := io.Copy(stdin, strings.NewReader(stdinCloseTestString))
+ check("Copy", err)
+ // Before the fix, this next line would race with cmd.Wait.
+ check("Close", stdin.Close())
+ }()
+ check("Wait", cmd.Wait())
+}
+
// Issue 5071
func TestPipeLookPathLeak(t *testing.T) {
fd0 := numOpenFDS(t)
@@ -199,8 +227,29 @@ func basefds() uintptr {
return n
}
+func closeUnexpectedFds(t *testing.T, m string) {
+ for fd := basefds(); fd <= 101; fd++ {
+ err := os.NewFile(fd, "").Close()
+ if err == nil {
+ t.Logf("%s: Something already leaked - closed fd %d", m, fd)
+ }
+ }
+}
+
func TestExtraFilesFDShuffle(t *testing.T) {
- t.Skip("TODO: TestExtraFilesFDShuffle is too non-portable; skipping")
+ t.Skip("flaky test; see http://golang.org/issue/5780")
+ switch runtime.GOOS {
+ case "darwin":
+ // TODO(cnicolaou): http://golang.org/issue/2603
+ // leads to leaked file descriptors in this test when it's
+ // run from a builder.
+ closeUnexpectedFds(t, "TestExtraFilesFDShuffle")
+ case "netbsd":
+ // http://golang.org/issue/3955
+ closeUnexpectedFds(t, "TestExtraFilesFDShuffle")
+ case "windows":
+ t.Skip("no operating system support; skipping")
+ }
// syscall.StartProcess maps all the FDs passed to it in
// ProcAttr.Files (the concatenation of stdin,stdout,stderr and
@@ -300,12 +349,7 @@ func TestExtraFiles(t *testing.T) {
// our environment.
if !testedAlreadyLeaked {
testedAlreadyLeaked = true
- for fd := basefds(); fd <= 101; fd++ {
- err := os.NewFile(fd, "").Close()
- if err == nil {
- t.Logf("Something already leaked - closed fd %d", fd)
- }
- }
+ closeUnexpectedFds(t, "TestExtraFiles")
}
// Force network usage, to verify the epoll (or whatever) fd
@@ -434,7 +478,7 @@ func TestHelperProcess(*testing.T) {
// Determine which command to use to display open files.
ofcmd := "lsof"
switch runtime.GOOS {
- case "freebsd", "netbsd", "openbsd":
+ case "dragonfly", "freebsd", "netbsd", "openbsd":
ofcmd = "fstat"
}
@@ -495,6 +539,17 @@ func TestHelperProcess(*testing.T) {
os.Exit(1)
}
}
+ case "stdinClose":
+ b, err := ioutil.ReadAll(os.Stdin)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Error: %v\n", err)
+ os.Exit(1)
+ }
+ if s := string(b); s != stdinCloseTestString {
+ fmt.Fprintf(os.Stderr, "Error: Read %q, want %q", s, stdinCloseTestString)
+ os.Exit(1)
+ }
+ os.Exit(0)
case "read3": // read fd 3
fd3 := os.NewFile(3, "fd3")
bs, err := ioutil.ReadAll(fd3)
@@ -503,6 +558,9 @@ func TestHelperProcess(*testing.T) {
os.Exit(1)
}
switch runtime.GOOS {
+ case "dragonfly":
+ // TODO(jsing): Determine why DragonFly is leaking
+ // file descriptors...
case "darwin":
// TODO(bradfitz): broken? Sometimes.
// http://golang.org/issue/2603
@@ -544,13 +602,11 @@ func TestHelperProcess(*testing.T) {
n, _ := strconv.Atoi(args[0])
os.Exit(n)
case "describefiles":
- for fd := uintptr(3); fd < 25; fd++ {
- f := os.NewFile(fd, fmt.Sprintf("fd-%d", fd))
- ln, err := net.FileListener(f)
- if err == nil {
- fmt.Printf("fd%d: listener %s\n", fd, ln.Addr())
- ln.Close()
- }
+ f := os.NewFile(3, fmt.Sprintf("fd3"))
+ ln, err := net.FileListener(f)
+ if err == nil {
+ fmt.Printf("fd3: listener %s\n", ln.Addr())
+ ln.Close()
}
os.Exit(0)
case "extraFilesAndPipes":
diff --git a/libgo/go/os/exec/lp_plan9.go b/libgo/go/os/exec/lp_plan9.go
index 6846a35c85f..5aa8a54ed81 100644
--- a/libgo/go/os/exec/lp_plan9.go
+++ b/libgo/go/os/exec/lp_plan9.go
@@ -28,6 +28,7 @@ func findExecutable(file string) error {
// in the directories named by the path environment variable.
// If file begins with "/", "#", "./", or "../", it is tried
// directly and the path is not consulted.
+// The result may be an absolute path or a path relative to the current directory.
func LookPath(file string) (string, error) {
// skip the path lookup for these prefixes
skip := []string{"/", "#", "./", "../"}
diff --git a/libgo/go/os/exec/lp_unix.go b/libgo/go/os/exec/lp_unix.go
index 1d1ec07da4d..7ff2d201bcb 100644
--- a/libgo/go/os/exec/lp_unix.go
+++ b/libgo/go/os/exec/lp_unix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd linux netbsd openbsd
+// +build darwin dragonfly freebsd linux netbsd openbsd
package exec
@@ -29,6 +29,7 @@ func findExecutable(file string) error {
// LookPath searches for an executable binary named file
// in the directories named by the PATH environment variable.
// If file contains a slash, it is tried directly and the PATH is not consulted.
+// The result may be an absolute path or a path relative to the current directory.
func LookPath(file string) (string, error) {
// NOTE(rsc): I wish we could use the Plan 9 behavior here
// (only bypass the path if file begins with / or ./ or ../)
diff --git a/libgo/go/os/exec/lp_unix_test.go b/libgo/go/os/exec/lp_unix_test.go
index 625d7848641..f1ab6deffdc 100644
--- a/libgo/go/os/exec/lp_unix_test.go
+++ b/libgo/go/os/exec/lp_unix_test.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd linux netbsd openbsd
+// +build darwin dragonfly freebsd linux netbsd openbsd
package exec
diff --git a/libgo/go/os/exec/lp_windows.go b/libgo/go/os/exec/lp_windows.go
index 7c7289bceea..c3efd67e9e1 100644
--- a/libgo/go/os/exec/lp_windows.go
+++ b/libgo/go/os/exec/lp_windows.go
@@ -24,14 +24,21 @@ func chkStat(file string) error {
return nil
}
+func hasExt(file string) bool {
+ i := strings.LastIndex(file, ".")
+ if i < 0 {
+ return false
+ }
+ return strings.LastIndexAny(file, `:\/`) < i
+}
+
func findExecutable(file string, exts []string) (string, error) {
if len(exts) == 0 {
return file, chkStat(file)
}
- f := strings.ToLower(file)
- for _, e := range exts {
- if strings.HasSuffix(f, e) {
- return file, chkStat(file)
+ if hasExt(file) {
+ if chkStat(file) == nil {
+ return file, nil
}
}
for _, e := range exts {
@@ -47,6 +54,7 @@ func findExecutable(file string, exts []string) (string, error) {
// If file contains a slash, it is tried directly and the PATH is not consulted.
// LookPath also uses PATHEXT environment variable to match
// a suitable candidate.
+// The result may be an absolute path or a path relative to the current directory.
func LookPath(file string) (f string, err error) {
x := os.Getenv(`PATHEXT`)
if x == `` {
diff --git a/libgo/go/os/exec_posix.go b/libgo/go/os/exec_posix.go
index f7b10f3c690..fb123aefbcc 100644
--- a/libgo/go/os/exec_posix.go
+++ b/libgo/go/os/exec_posix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd linux netbsd openbsd windows
+// +build darwin dragonfly freebsd linux netbsd openbsd windows
package os
diff --git a/libgo/go/os/exec_unix.go b/libgo/go/os/exec_unix.go
index fa3ba8a19e4..5572e628e6e 100644
--- a/libgo/go/os/exec_unix.go
+++ b/libgo/go/os/exec_unix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd linux netbsd openbsd
+// +build darwin dragonfly freebsd linux netbsd openbsd
package os
diff --git a/libgo/go/os/exec_windows.go b/libgo/go/os/exec_windows.go
index 4aa2ade631e..c4f3d4f8530 100644
--- a/libgo/go/os/exec_windows.go
+++ b/libgo/go/os/exec_windows.go
@@ -42,13 +42,22 @@ func (p *Process) wait() (ps *ProcessState, err error) {
return &ProcessState{p.Pid, syscall.WaitStatus{ExitCode: ec}, &u}, nil
}
+func terminateProcess(pid, exitcode int) error {
+ h, e := syscall.OpenProcess(syscall.PROCESS_TERMINATE, false, uint32(pid))
+ if e != nil {
+ return NewSyscallError("OpenProcess", e)
+ }
+ defer syscall.CloseHandle(h)
+ e = syscall.TerminateProcess(h, uint32(exitcode))
+ return NewSyscallError("TerminateProcess", e)
+}
+
func (p *Process) signal(sig Signal) error {
if p.done() {
return errors.New("os: process already finished")
}
if sig == Kill {
- e := syscall.TerminateProcess(syscall.Handle(p.handle), 1)
- return NewSyscallError("TerminateProcess", e)
+ return terminateProcess(p.Pid, 1)
}
// TODO(rsc): Handle Interrupt too?
return syscall.Errno(syscall.EWINDOWS)
diff --git a/libgo/go/os/export_test.go b/libgo/go/os/export_test.go
index 9c6ef429744..9fa7936ae63 100644
--- a/libgo/go/os/export_test.go
+++ b/libgo/go/os/export_test.go
@@ -7,3 +7,4 @@ package os
// Export for testing.
var Atime = atime
+var LstatP = &lstat
diff --git a/libgo/go/os/file.go b/libgo/go/os/file.go
index 32cac6d89a4..2dd1fcf282f 100644
--- a/libgo/go/os/file.go
+++ b/libgo/go/os/file.go
@@ -174,6 +174,9 @@ func (f *File) WriteAt(b []byte, off int64) (n int, err error) {
// relative to the current offset, and 2 means relative to the end.
// It returns the new offset and an error, if any.
func (f *File) Seek(offset int64, whence int) (ret int64, err error) {
+ if f == nil {
+ return 0, ErrInvalid
+ }
r, e := f.seek(offset, whence)
if e == nil && f.dirinfo != nil && r != 0 {
e = syscall.EISDIR
@@ -216,6 +219,9 @@ func Chdir(dir string) error {
// which must be a directory.
// If there is an error, it will be of type *PathError.
func (f *File) Chdir() error {
+ if f == nil {
+ return ErrInvalid
+ }
if e := syscall.Fchdir(f.fd); e != nil {
return &PathError{"chdir", f.name, e}
}
@@ -238,3 +244,6 @@ func Open(name string) (file *File, err error) {
func Create(name string) (file *File, err error) {
return OpenFile(name, O_RDWR|O_CREATE|O_TRUNC, 0666)
}
+
+// lstat is overridden in tests.
+var lstat = Lstat
diff --git a/libgo/go/os/file_plan9.go b/libgo/go/os/file_plan9.go
index d6d39a89973..708163ee1c0 100644
--- a/libgo/go/os/file_plan9.go
+++ b/libgo/go/os/file_plan9.go
@@ -133,6 +133,9 @@ func OpenFile(name string, flag int, perm FileMode) (file *File, err error) {
// Close closes the File, rendering it unusable for I/O.
// It returns an error, if any.
func (f *File) Close() error {
+ if f == nil {
+ return ErrInvalid
+ }
return f.file.close()
}
@@ -156,6 +159,9 @@ func (file *file) close() error {
// Stat returns the FileInfo structure describing file.
// If there is an error, it will be of type *PathError.
func (f *File) Stat() (fi FileInfo, err error) {
+ if f == nil {
+ return nil, ErrInvalid
+ }
d, err := dirstat(f)
if err != nil {
return nil, err
@@ -167,8 +173,11 @@ func (f *File) Stat() (fi FileInfo, err error) {
// It does not change the I/O offset.
// If there is an error, it will be of type *PathError.
func (f *File) Truncate(size int64) error {
- var d syscall.Dir
+ if f == nil {
+ return ErrInvalid
+ }
+ var d syscall.Dir
d.Null()
d.Length = size
@@ -188,6 +197,9 @@ const chmodMask = uint32(syscall.DMAPPEND | syscall.DMEXCL | syscall.DMTMP | Mod
// Chmod changes the mode of the file to mode.
// If there is an error, it will be of type *PathError.
func (f *File) Chmod(mode FileMode) error {
+ if f == nil {
+ return ErrInvalid
+ }
var d syscall.Dir
odir, e := dirstat(f)
@@ -419,6 +431,9 @@ func Lchown(name string, uid, gid int) error {
// Chown changes the numeric uid and gid of the named file.
// If there is an error, it will be of type *PathError.
func (f *File) Chown(uid, gid int) error {
+ if f == nil {
+ return ErrInvalid
+ }
return &PathError{"chown", f.name, syscall.EPLAN9}
}
diff --git a/libgo/go/os/file_posix.go b/libgo/go/os/file_posix.go
index 3df43feaa13..a8bef359b95 100644
--- a/libgo/go/os/file_posix.go
+++ b/libgo/go/os/file_posix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd linux netbsd openbsd windows
+// +build darwin dragonfly freebsd linux netbsd openbsd windows
package os
@@ -86,6 +86,9 @@ func Chmod(name string, mode FileMode) error {
// Chmod changes the mode of the file to mode.
// If there is an error, it will be of type *PathError.
func (f *File) Chmod(mode FileMode) error {
+ if f == nil {
+ return ErrInvalid
+ }
if e := syscall.Fchmod(f.fd, syscallMode(mode)); e != nil {
return &PathError{"chmod", f.name, e}
}
@@ -115,6 +118,9 @@ func Lchown(name string, uid, gid int) error {
// Chown changes the numeric uid and gid of the named file.
// If there is an error, it will be of type *PathError.
func (f *File) Chown(uid, gid int) error {
+ if f == nil {
+ return ErrInvalid
+ }
if e := syscall.Fchown(f.fd, uid, gid); e != nil {
return &PathError{"chown", f.name, e}
}
@@ -125,6 +131,9 @@ func (f *File) Chown(uid, gid int) error {
// It does not change the I/O offset.
// If there is an error, it will be of type *PathError.
func (f *File) Truncate(size int64) error {
+ if f == nil {
+ return ErrInvalid
+ }
if e := syscall.Ftruncate(f.fd, size); e != nil {
return &PathError{"truncate", f.name, e}
}
diff --git a/libgo/go/os/file_unix.go b/libgo/go/os/file_unix.go
index 993a4380c18..79eeaec5023 100644
--- a/libgo/go/os/file_unix.go
+++ b/libgo/go/os/file_unix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd linux netbsd openbsd
+// +build darwin dragonfly freebsd linux netbsd openbsd
package os
@@ -95,6 +95,9 @@ func OpenFile(name string, flag int, perm FileMode) (file *File, err error) {
// Close closes the File, rendering it unusable for I/O.
// It returns an error, if any.
func (f *File) Close() error {
+ if f == nil {
+ return ErrInvalid
+ }
return f.file.close()
}
@@ -128,6 +131,9 @@ func (file *file) close() error {
// Stat returns the FileInfo structure describing file.
// If there is an error, it will be of type *PathError.
func (f *File) Stat() (fi FileInfo, err error) {
+ if f == nil {
+ return nil, ErrInvalid
+ }
var stat syscall.Stat_t
err = syscall.Fstat(f.fd, &stat)
if err != nil {
@@ -169,11 +175,14 @@ func (f *File) readdir(n int) (fi []FileInfo, err error) {
names, err := f.Readdirnames(n)
fi = make([]FileInfo, len(names))
for i, filename := range names {
- fip, err := Lstat(dirname + filename)
- if err == nil {
+ fip, lerr := lstat(dirname + filename)
+ if lerr == nil {
fi[i] = fip
} else {
fi[i] = &fileStat{name: filename}
+ if err == nil {
+ err = lerr
+ }
}
}
return fi, err
diff --git a/libgo/go/os/getwd.go b/libgo/go/os/getwd.go
index 0235c5d779b..8c5ff7fca51 100644
--- a/libgo/go/os/getwd.go
+++ b/libgo/go/os/getwd.go
@@ -14,6 +14,10 @@ var getwdCache struct {
dir string
}
+// useSyscallwd determines whether to use the return value of
+// syscall.Getwd based on its error.
+var useSyscallwd = func(error) bool { return true }
+
// Getwd returns a rooted path name corresponding to the
// current directory. If the current directory can be
// reached via multiple paths (due to symbolic links),
@@ -22,7 +26,9 @@ func Getwd() (pwd string, err error) {
// If the operating system provides a Getwd call, use it.
if syscall.ImplementsGetwd {
s, e := syscall.Getwd()
- return s, NewSyscallError("getwd", e)
+ if useSyscallwd(e) {
+ return s, NewSyscallError("getwd", e)
+ }
}
// Otherwise, we're trying to find our way back to ".".
diff --git a/libgo/go/os/getwd_darwin.go b/libgo/go/os/getwd_darwin.go
new file mode 100644
index 00000000000..e51ffcd5e71
--- /dev/null
+++ b/libgo/go/os/getwd_darwin.go
@@ -0,0 +1,15 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package os
+
+import "syscall"
+
+func init() {
+ useSyscallwd = useSyscallwdDarwin
+}
+
+func useSyscallwdDarwin(err error) bool {
+ return err != syscall.ENOTSUP
+}
diff --git a/libgo/go/os/os_test.go b/libgo/go/os/os_test.go
index 40ca44df9ff..882e3da1517 100644
--- a/libgo/go/os/os_test.go
+++ b/libgo/go/os/os_test.go
@@ -11,11 +11,13 @@ import (
"io"
"io/ioutil"
. "os"
+ osexec "os/exec"
"path/filepath"
"runtime"
"strings"
"syscall"
"testing"
+ "text/template"
"time"
)
@@ -295,6 +297,7 @@ func TestReaddirnamesOneAtATime(t *testing.T) {
if err2 != nil {
t.Fatalf("open %q failed: %v", dir, err2)
}
+ defer file1.Close()
small := smallReaddirnames(file1, len(all)+100, t) // +100 in case we screw up
if len(small) < len(all) {
t.Fatalf("len(small) is %d, less than %d", len(small), len(all))
@@ -522,6 +525,7 @@ func exec(t *testing.T, dir, cmd string, args []string, expect string) {
if err != nil {
t.Fatalf("Pipe: %v", err)
}
+ defer r.Close()
attr := &ProcAttr{Dir: dir, Files: []*File{nil, w, Stderr}}
p, err := StartProcess(cmd, args, attr)
if err != nil {
@@ -819,9 +823,16 @@ func TestOpenError(t *testing.T) {
if !strings.HasSuffix(syscallErrStr, expectedErrStr) {
t.Errorf("Open(%q, %d) = _, %q; want suffix %q", tt.path, tt.mode, syscallErrStr, expectedErrStr)
}
- } else {
- t.Errorf("Open(%q, %d) = _, %q; want %q", tt.path, tt.mode, perr.Err.Error(), tt.error.Error())
+ continue
+ }
+ if runtime.GOOS == "dragonfly" {
+ // DragonFly incorrectly returns EACCES rather
+ // EISDIR when a directory is opened for write.
+ if tt.error == syscall.EISDIR && perr.Err == syscall.EACCES {
+ continue
+ }
}
+ t.Errorf("Open(%q, %d) = _, %q; want %q", tt.path, tt.mode, perr.Err.Error(), tt.error.Error())
}
}
}
@@ -840,6 +851,7 @@ func run(t *testing.T, cmd []string) string {
if err != nil {
t.Fatal(err)
}
+ defer r.Close()
p, err := StartProcess("/bin/hostname", []string{"hostname"}, &ProcAttr{Files: []*File{nil, w, Stderr}})
if err != nil {
t.Fatal(err)
@@ -1112,3 +1124,89 @@ func TestStatDirModeExec(t *testing.T) {
t.Errorf("Stat %q: mode %#o want %#o", path, dir.Mode()&mode, mode)
}
}
+
+func TestReadAtEOF(t *testing.T) {
+ f := newFile("TestReadAtEOF", t)
+ defer Remove(f.Name())
+ defer f.Close()
+
+ _, err := f.ReadAt(make([]byte, 10), 0)
+ switch err {
+ case io.EOF:
+ // all good
+ case nil:
+ t.Fatalf("ReadAt succeeded")
+ default:
+ t.Fatalf("ReadAt failed: %s", err)
+ }
+}
+
+func testKillProcess(t *testing.T, processKiller func(p *Process)) {
+ t.Skip("gccgo does not have a go command")
+ dir, err := ioutil.TempDir("", "go-build")
+ if err != nil {
+ t.Fatalf("Failed to create temp directory: %v", err)
+ }
+ defer RemoveAll(dir)
+
+ src := filepath.Join(dir, "main.go")
+ f, err := Create(src)
+ if err != nil {
+ t.Fatalf("Failed to create %v: %v", src, err)
+ }
+ st := template.Must(template.New("source").Parse(`
+package main
+import "time"
+func main() {
+ time.Sleep(time.Second)
+}
+`))
+ err = st.Execute(f, nil)
+ if err != nil {
+ f.Close()
+ t.Fatalf("Failed to execute template: %v", err)
+ }
+ f.Close()
+
+ exe := filepath.Join(dir, "main.exe")
+ output, err := osexec.Command("go", "build", "-o", exe, src).CombinedOutput()
+ if err != nil {
+ t.Fatalf("Failed to build exe %v: %v %v", exe, err, string(output))
+ }
+
+ cmd := osexec.Command(exe)
+ err = cmd.Start()
+ if err != nil {
+ t.Fatalf("Failed to start test process: %v", err)
+ }
+ go func() {
+ time.Sleep(100 * time.Millisecond)
+ processKiller(cmd.Process)
+ }()
+ err = cmd.Wait()
+ if err == nil {
+ t.Errorf("Test process succeeded, but expected to fail")
+ }
+}
+
+func TestKillStartProcess(t *testing.T) {
+ testKillProcess(t, func(p *Process) {
+ err := p.Kill()
+ if err != nil {
+ t.Fatalf("Failed to kill test process: %v", err)
+ }
+ })
+}
+
+func TestKillFindProcess(t *testing.T) {
+ testKillProcess(t, func(p *Process) {
+ p2, err := FindProcess(p.Pid)
+ if err != nil {
+ t.Fatalf("Failed to find test process: %v", err)
+ }
+ err = p2.Kill()
+ if err != nil {
+ t.Fatalf("Failed to kill test process: %v", err)
+ }
+ })
+}
diff --git a/libgo/go/os/os_unix_test.go b/libgo/go/os/os_unix_test.go
index f8e330beba4..80d57aa4222 100644
--- a/libgo/go/os/os_unix_test.go
+++ b/libgo/go/os/os_unix_test.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd linux netbsd openbsd
+// +build darwin dragonfly freebsd linux netbsd openbsd
package os_test
@@ -28,7 +28,7 @@ func checkUidGid(t *testing.T, path string, uid, gid int) {
}
func TestChown(t *testing.T) {
- // Chown is not supported under windows or Plan 9.
+ // Chown is not supported under windows os Plan 9.
// Plan9 provides a native ChownPlan9 version instead.
if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
return
@@ -74,3 +74,41 @@ func TestChown(t *testing.T) {
checkUidGid(t, f.Name(), int(sys.Uid), gid)
}
}
+
+func TestReaddirWithBadLstat(t *testing.T) {
+ handle, err := Open(sfdir)
+ failfile := sfdir + "/" + sfname
+ if err != nil {
+ t.Fatalf("Couldn't open %s: %s", sfdir, err)
+ }
+
+ *LstatP = func(file string) (FileInfo, error) {
+ if file == failfile {
+ var fi FileInfo
+ return fi, ErrInvalid
+ }
+ return Lstat(file)
+ }
+ defer func() { *LstatP = Lstat }()
+
+ dirs, err := handle.Readdir(-1)
+ if err != ErrInvalid {
+ t.Fatalf("Expected Readdir to return ErrInvalid, got %v", err)
+ }
+ foundfail := false
+ for _, dir := range dirs {
+ if dir.Name() == sfname {
+ foundfail = true
+ if dir.Sys() != nil {
+ t.Errorf("Expected Readdir for %s should not contain Sys", failfile)
+ }
+ } else {
+ if dir.Sys() == nil {
+ t.Errorf("Readdir for every file other than %s should contain Sys, but %s/%s didn't either", failfile, sfdir, dir.Name())
+ }
+ }
+ }
+ if !foundfail {
+ t.Fatalf("Expected %s from Readdir, but didn't find it", failfile)
+ }
+}
diff --git a/libgo/go/os/path_test.go b/libgo/go/os/path_test.go
index 16c4120dc6c..27abf59826f 100644
--- a/libgo/go/os/path_test.go
+++ b/libgo/go/os/path_test.go
@@ -91,7 +91,7 @@ func TestRemoveAll(t *testing.T) {
if err = RemoveAll(path); err != nil {
t.Fatalf("RemoveAll %q (first): %s", path, err)
}
- if _, err := Lstat(path); err == nil {
+ if _, err = Lstat(path); err == nil {
t.Fatalf("Lstat %q succeeded after RemoveAll (first)", path)
}
@@ -153,7 +153,7 @@ func TestRemoveAll(t *testing.T) {
Chmod(dpath, 0777)
for _, s := range []string{fpath, path + "/zzz"} {
- if _, err := Lstat(s); err == nil {
+ if _, err = Lstat(s); err == nil {
t.Fatalf("Lstat %q succeeded after partial RemoveAll", s)
}
}
@@ -161,7 +161,7 @@ func TestRemoveAll(t *testing.T) {
if err = RemoveAll(path); err != nil {
t.Fatalf("RemoveAll %q after partial RemoveAll: %s", path, err)
}
- if _, err := Lstat(path); err == nil {
+ if _, err = Lstat(path); err == nil {
t.Fatalf("Lstat %q succeeded after RemoveAll (final)", path)
}
}
diff --git a/libgo/go/os/path_unix.go b/libgo/go/os/path_unix.go
index 30a167b1adc..3bf63bf8042 100644
--- a/libgo/go/os/path_unix.go
+++ b/libgo/go/os/path_unix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd linux netbsd openbsd
+// +build darwin dragonfly freebsd linux netbsd openbsd
package os
diff --git a/libgo/go/os/pipe_bsd.go b/libgo/go/os/pipe_bsd.go
index a2ce9a39f56..73d35b4d5eb 100644
--- a/libgo/go/os/pipe_bsd.go
+++ b/libgo/go/os/pipe_bsd.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd netbsd openbsd
+// +build darwin dragonfly freebsd netbsd openbsd
package os
diff --git a/libgo/go/os/signal/signal_test.go b/libgo/go/os/signal/signal_test.go
index d13833306f8..741f2a0edfc 100644
--- a/libgo/go/os/signal/signal_test.go
+++ b/libgo/go/os/signal/signal_test.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd linux netbsd openbsd
+// +build darwin dragonfly freebsd linux netbsd openbsd
package signal
@@ -36,8 +36,8 @@ func TestSignal(t *testing.T) {
Notify(c, syscall.SIGHUP)
defer Stop(c)
- t.Logf("sighup...")
// Send this process a SIGHUP
+ t.Logf("sighup...")
syscall.Kill(syscall.Getpid(), syscall.SIGHUP)
waitSig(t, c, syscall.SIGHUP)
@@ -45,18 +45,18 @@ func TestSignal(t *testing.T) {
c1 := make(chan os.Signal, 1)
Notify(c1)
- t.Logf("sigwinch...")
// Send this process a SIGWINCH
+ t.Logf("sigwinch...")
syscall.Kill(syscall.Getpid(), syscall.SIGWINCH)
waitSig(t, c1, syscall.SIGWINCH)
// Send two more SIGHUPs, to make sure that
// they get delivered on c1 and that not reading
// from c does not block everything.
- t.Logf("sigwinch...")
+ t.Logf("sighup...")
syscall.Kill(syscall.Getpid(), syscall.SIGHUP)
waitSig(t, c1, syscall.SIGHUP)
- t.Logf("sigwinch...")
+ t.Logf("sighup...")
syscall.Kill(syscall.Getpid(), syscall.SIGHUP)
waitSig(t, c1, syscall.SIGHUP)
diff --git a/libgo/go/os/signal/signal_unix.go b/libgo/go/os/signal/signal_unix.go
index 6b4c8ab662e..318488dc04a 100644
--- a/libgo/go/os/signal/signal_unix.go
+++ b/libgo/go/os/signal/signal_unix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd linux netbsd openbsd windows
+// +build darwin dragonfly freebsd linux netbsd openbsd windows
package signal
diff --git a/libgo/go/os/stat_dragonfly.go b/libgo/go/os/stat_dragonfly.go
new file mode 100644
index 00000000000..605c1d9b64f
--- /dev/null
+++ b/libgo/go/os/stat_dragonfly.go
@@ -0,0 +1,61 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package os
+
+import (
+ "syscall"
+ "time"
+)
+
+func sameFile(fs1, fs2 *fileStat) bool {
+ stat1 := fs1.sys.(*syscall.Stat_t)
+ stat2 := fs2.sys.(*syscall.Stat_t)
+ return stat1.Dev == stat2.Dev && stat1.Ino == stat2.Ino
+}
+
+func fileInfoFromStat(st *syscall.Stat_t, name string) FileInfo {
+ fs := &fileStat{
+ name: basename(name),
+ size: int64(st.Size),
+ modTime: timespecToTime(st.Mtim),
+ sys: st,
+ }
+ fs.mode = FileMode(st.Mode & 0777)
+ switch st.Mode & syscall.S_IFMT {
+ case syscall.S_IFBLK:
+ fs.mode |= ModeDevice
+ case syscall.S_IFCHR:
+ fs.mode |= ModeDevice | ModeCharDevice
+ case syscall.S_IFDIR:
+ fs.mode |= ModeDir
+ case syscall.S_IFIFO:
+ fs.mode |= ModeNamedPipe
+ case syscall.S_IFLNK:
+ fs.mode |= ModeSymlink
+ case syscall.S_IFREG:
+ // nothing to do
+ case syscall.S_IFSOCK:
+ fs.mode |= ModeSocket
+ }
+ if st.Mode&syscall.S_ISGID != 0 {
+ fs.mode |= ModeSetgid
+ }
+ if st.Mode&syscall.S_ISUID != 0 {
+ fs.mode |= ModeSetuid
+ }
+ if st.Mode&syscall.S_ISVTX != 0 {
+ fs.mode |= ModeSticky
+ }
+ return fs
+}
+
+func timespecToTime(ts syscall.Timespec) time.Time {
+ return time.Unix(int64(ts.Sec), int64(ts.Nsec))
+}
+
+// For testing.
+func atime(fi FileInfo) time.Time {
+ return timespecToTime(fi.Sys().(*syscall.Stat_t).Atim)
+}
diff --git a/libgo/go/os/sys_bsd.go b/libgo/go/os/sys_bsd.go
index 0f263f1c121..9ad2f8546b9 100644
--- a/libgo/go/os/sys_bsd.go
+++ b/libgo/go/os/sys_bsd.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd netbsd openbsd
+// +build darwin dragonfly freebsd netbsd openbsd
// os code shared between *BSD systems including OS X (Darwin)
// and FreeBSD.
diff --git a/libgo/go/os/user/lookup_plan9.go b/libgo/go/os/user/lookup_plan9.go
new file mode 100644
index 00000000000..f7ef3482b7e
--- /dev/null
+++ b/libgo/go/os/user/lookup_plan9.go
@@ -0,0 +1,46 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package user
+
+import (
+ "fmt"
+ "io/ioutil"
+ "os"
+ "syscall"
+)
+
+// Partial os/user support on Plan 9.
+// Supports Current(), but not Lookup()/LookupId().
+// The latter two would require parsing /adm/users.
+const (
+ userFile = "/dev/user"
+)
+
+func current() (*User, error) {
+ ubytes, err := ioutil.ReadFile(userFile)
+ if err != nil {
+ return nil, fmt.Errorf("user: %s", err)
+ }
+
+ uname := string(ubytes)
+
+ u := &User{
+ Uid: uname,
+ Gid: uname,
+ Username: uname,
+ Name: uname,
+ HomeDir: os.Getenv("home"),
+ }
+
+ return u, nil
+}
+
+func lookup(username string) (*User, error) {
+ return nil, syscall.EPLAN9
+}
+
+func lookupId(uid string) (*User, error) {
+ return nil, syscall.EPLAN9
+}
diff --git a/libgo/go/os/user/lookup_stubs.go b/libgo/go/os/user/lookup_stubs.go
index ad06907b5d5..86f0e6e645a 100644
--- a/libgo/go/os/user/lookup_stubs.go
+++ b/libgo/go/os/user/lookup_stubs.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build !cgo,!windows
+// +build !cgo,!windows,!plan9
package user
diff --git a/libgo/go/os/user/lookup_unix.go b/libgo/go/os/user/lookup_unix.go
index e1e2777ff06..eca97a63d6b 100644
--- a/libgo/go/os/user/lookup_unix.go
+++ b/libgo/go/os/user/lookup_unix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd linux netbsd openbsd
+// +build darwin dragonfly freebsd linux netbsd openbsd
// +build cgo
package user
diff --git a/libgo/go/os/user/lookup_windows.go b/libgo/go/os/user/lookup_windows.go
index a0a8a4ec10f..99c325ff010 100644
--- a/libgo/go/os/user/lookup_windows.go
+++ b/libgo/go/os/user/lookup_windows.go
@@ -10,37 +10,63 @@ import (
"unsafe"
)
-func lookupFullName(domain, username, domainAndUser string) (string, error) {
- // try domain controller first
- name, e := syscall.TranslateAccountName(domainAndUser,
+func isDomainJoined() (bool, error) {
+ var domain *uint16
+ var status uint32
+ err := syscall.NetGetJoinInformation(nil, &domain, &status)
+ if err != nil {
+ return false, err
+ }
+ syscall.NetApiBufferFree((*byte)(unsafe.Pointer(domain)))
+ return status == syscall.NetSetupDomainName, nil
+}
+
+func lookupFullNameDomain(domainAndUser string) (string, error) {
+ return syscall.TranslateAccountName(domainAndUser,
syscall.NameSamCompatible, syscall.NameDisplay, 50)
+}
+
+func lookupFullNameServer(servername, username string) (string, error) {
+ s, e := syscall.UTF16PtrFromString(servername)
if e != nil {
- // domain lookup failed, perhaps this pc is not part of domain
- d, e := syscall.UTF16PtrFromString(domain)
- if e != nil {
- return "", e
- }
- u, e := syscall.UTF16PtrFromString(username)
- if e != nil {
- return "", e
- }
- var p *byte
- e = syscall.NetUserGetInfo(d, u, 10, &p)
- if e != nil {
- // path executed when a domain user is disconnected from the domain
- // pretend username is fullname
- return username, nil
- }
- defer syscall.NetApiBufferFree(p)
- i := (*syscall.UserInfo10)(unsafe.Pointer(p))
- if i.FullName == nil {
- return "", nil
- }
- name = syscall.UTF16ToString((*[1024]uint16)(unsafe.Pointer(i.FullName))[:])
+ return "", e
}
+ u, e := syscall.UTF16PtrFromString(username)
+ if e != nil {
+ return "", e
+ }
+ var p *byte
+ e = syscall.NetUserGetInfo(s, u, 10, &p)
+ if e != nil {
+ return "", e
+ }
+ defer syscall.NetApiBufferFree(p)
+ i := (*syscall.UserInfo10)(unsafe.Pointer(p))
+ if i.FullName == nil {
+ return "", nil
+ }
+ name := syscall.UTF16ToString((*[1024]uint16)(unsafe.Pointer(i.FullName))[:])
return name, nil
}
+func lookupFullName(domain, username, domainAndUser string) (string, error) {
+ joined, err := isDomainJoined()
+ if err == nil && joined {
+ name, err := lookupFullNameDomain(domainAndUser)
+ if err == nil {
+ return name, nil
+ }
+ }
+ name, err := lookupFullNameServer(domain, username)
+ if err == nil {
+ return name, nil
+ }
+ // domain worked neigher as a domain nor as a server
+ // could be domain server unavailable
+ // pretend username is fullname
+ return username, nil
+}
+
func newUser(usid *syscall.SID, gid, dir string) (*User, error) {
username, domain, t, e := usid.LookupAccount("")
if e != nil {
@@ -73,6 +99,7 @@ func current() (*User, error) {
if e != nil {
return nil, e
}
+ defer t.Close()
u, e := t.GetTokenUser()
if e != nil {
return nil, e
diff --git a/libgo/go/os/user/user.go b/libgo/go/os/user/user.go
index 841f2263f95..e8680fe5465 100644
--- a/libgo/go/os/user/user.go
+++ b/libgo/go/os/user/user.go
@@ -16,6 +16,8 @@ var implemented = true // set to false by lookup_stubs.go's init
// On posix systems Uid and Gid contain a decimal number
// representing uid and gid. On windows Uid and Gid
// contain security identifier (SID) in a string format.
+// On Plan 9, Uid, Gid, Username, and Name will be the
+// contents of /dev/user.
type User struct {
Uid string // user id
Gid string // primary group id
diff --git a/libgo/go/os/user/user_test.go b/libgo/go/os/user/user_test.go
index 444a9aacd47..9d9420e8090 100644
--- a/libgo/go/os/user/user_test.go
+++ b/libgo/go/os/user/user_test.go
@@ -13,12 +13,6 @@ func check(t *testing.T) {
if !implemented {
t.Skip("user: not implemented; skipping tests")
}
- switch runtime.GOOS {
- case "linux", "freebsd", "darwin", "windows":
- // test supported
- default:
- t.Skipf("user: Lookup not implemented on %q; skipping test", runtime.GOOS)
- }
}
func TestCurrent(t *testing.T) {
@@ -61,6 +55,10 @@ func compare(t *testing.T, want, got *User) {
func TestLookup(t *testing.T) {
check(t)
+ if runtime.GOOS == "plan9" {
+ t.Skipf("Lookup not implemented on %q", runtime.GOOS)
+ }
+
want, err := Current()
if err != nil {
t.Fatalf("Current: %v", err)
@@ -75,6 +73,10 @@ func TestLookup(t *testing.T) {
func TestLookupId(t *testing.T) {
check(t)
+ if runtime.GOOS == "plan9" {
+ t.Skipf("LookupId not implemented on %q", runtime.GOOS)
+ }
+
want, err := Current()
if err != nil {
t.Fatalf("Current: %v", err)
diff --git a/libgo/go/path/filepath/match.go b/libgo/go/path/filepath/match.go
index db8b0260ca8..3d84145d7f8 100644
--- a/libgo/go/path/filepath/match.go
+++ b/libgo/go/path/filepath/match.go
@@ -132,6 +132,12 @@ func matchChunk(chunk, s string) (rest string, ok bool, err error) {
r, n := utf8.DecodeRuneInString(s)
s = s[n:]
chunk = chunk[1:]
+ // We can't end right after '[', we're expecting at least
+ // a closing bracket and possibly a caret.
+ if len(chunk) == 0 {
+ err = ErrBadPattern
+ return
+ }
// possibly negated
negated := chunk[0] == '^'
if negated {
diff --git a/libgo/go/path/filepath/match_test.go b/libgo/go/path/filepath/match_test.go
index 1095cc5c454..6a2fd927e41 100644
--- a/libgo/go/path/filepath/match_test.go
+++ b/libgo/go/path/filepath/match_test.go
@@ -65,6 +65,11 @@ var matchTests = []MatchTest{
{"[-x]", "a", false, ErrBadPattern},
{"\\", "a", false, ErrBadPattern},
{"[a-b-c]", "a", false, ErrBadPattern},
+ {"[", "a", false, ErrBadPattern},
+ {"[^", "a", false, ErrBadPattern},
+ {"[^bc", "a", false, ErrBadPattern},
+ {"a[", "a", false, nil},
+ {"a[", "ab", false, ErrBadPattern},
{"*x", "xxx", true, nil},
}
diff --git a/libgo/go/path/filepath/path_test.go b/libgo/go/path/filepath/path_test.go
index 607bfed11ba..3a6e83d8fad 100644
--- a/libgo/go/path/filepath/path_test.go
+++ b/libgo/go/path/filepath/path_test.go
@@ -107,6 +107,9 @@ func TestClean(t *testing.T) {
}
}
+ if testing.Short() {
+ t.Skip("skipping malloc count in short mode")
+ }
if runtime.GOMAXPROCS(0) > 1 {
t.Log("skipping AllocsPerRun checks; GOMAXPROCS>1")
return
@@ -633,6 +636,10 @@ func simpleJoin(dir, path string) string {
}
func TestEvalSymlinks(t *testing.T) {
+ if runtime.GOOS == "plan9" {
+ t.Skip("Skipping test: symlinks don't exist under Plan 9")
+ }
+
tmpDir, err := ioutil.TempDir("", "evalsymlink")
if err != nil {
t.Fatal("creating temp dir:", err)
@@ -926,28 +933,33 @@ func TestDriveLetterInEvalSymlinks(t *testing.T) {
differently.
func TestBug3486(t *testing.T) { // http://code.google.com/p/go/issues/detail?id=3486
- root, err := filepath.EvalSymlinks(runtime.GOROOT())
+ root, err := filepath.EvalSymlinks(runtime.GOROOT() + "/test")
if err != nil {
t.Fatal(err)
}
- lib := filepath.Join(root, "lib")
- src := filepath.Join(root, "src")
- seenSrc := false
+ bugs := filepath.Join(root, "bugs")
+ ken := filepath.Join(root, "ken")
+ seenBugs := false
+ seenKen := false
filepath.Walk(root, func(pth string, info os.FileInfo, err error) error {
if err != nil {
t.Fatal(err)
}
switch pth {
- case lib:
+ case bugs:
+ seenBugs = true
return filepath.SkipDir
- case src:
- seenSrc = true
+ case ken:
+ if !seenBugs {
+ t.Fatal("filepath.Walk out of order - ken before bugs")
+ }
+ seenKen = true
}
return nil
})
- if !seenSrc {
- t.Fatalf("%q not seen", src)
+ if !seenKen {
+ t.Fatalf("%q not seen", ken)
}
}
diff --git a/libgo/go/path/filepath/path_unix.go b/libgo/go/path/filepath/path_unix.go
index cff7b2c65c5..d927b342be0 100644
--- a/libgo/go/path/filepath/path_unix.go
+++ b/libgo/go/path/filepath/path_unix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd linux netbsd openbsd
+// +build darwin dragonfly freebsd linux netbsd openbsd
package filepath
diff --git a/libgo/go/path/match_test.go b/libgo/go/path/match_test.go
index 730b6b90395..6b0676f81fd 100644
--- a/libgo/go/path/match_test.go
+++ b/libgo/go/path/match_test.go
@@ -61,6 +61,11 @@ var matchTests = []MatchTest{
{"[-x]", "a", false, ErrBadPattern},
{"\\", "a", false, ErrBadPattern},
{"[a-b-c]", "a", false, ErrBadPattern},
+ {"[", "a", false, ErrBadPattern},
+ {"[^", "a", false, ErrBadPattern},
+ {"[^bc", "a", false, ErrBadPattern},
+ {"a[", "a", false, nil},
+ {"a[", "ab", false, ErrBadPattern},
{"*x", "xxx", true, nil},
}
diff --git a/libgo/go/path/path_test.go b/libgo/go/path/path_test.go
index 62974401126..512d936e457 100644
--- a/libgo/go/path/path_test.go
+++ b/libgo/go/path/path_test.go
@@ -72,7 +72,12 @@ func TestClean(t *testing.T) {
t.Errorf("Clean(%q) = %q, want %q", test.result, s, test.result)
}
}
+}
+func TestCleanMallocs(t *testing.T) {
+ if testing.Short() {
+ t.Skip("skipping malloc count in short mode")
+ }
if runtime.GOMAXPROCS(0) > 1 {
t.Log("skipping AllocsPerRun checks; GOMAXPROCS>1")
return
diff --git a/libgo/go/reflect/all_test.go b/libgo/go/reflect/all_test.go
index 6528e60459b..6ab02f7d854 100644
--- a/libgo/go/reflect/all_test.go
+++ b/libgo/go/reflect/all_test.go
@@ -169,16 +169,20 @@ var typeTests = []pair{
}
var valueTests = []pair{
+ {new(int), "132"},
{new(int8), "8"},
{new(int16), "16"},
{new(int32), "32"},
{new(int64), "64"},
+ {new(uint), "132"},
{new(uint8), "8"},
{new(uint16), "16"},
{new(uint32), "32"},
{new(uint64), "64"},
{new(float32), "256.25"},
{new(float64), "512.125"},
+ {new(complex64), "532.125+10i"},
+ {new(complex128), "564.25+1i"},
{new(string), "stringy cheese"},
{new(bool), "true"},
{new(*int8), "*int8(0)"},
@@ -944,7 +948,7 @@ func TestMap(t *testing.T) {
newm := newmap.Interface().(map[string]int)
if len(newm) != len(m) {
- t.Errorf("length after copy: newm=%d, m=%d", newm, m)
+ t.Errorf("length after copy: newm=%d, m=%d", len(newm), len(m))
}
for k, v := range newm {
@@ -1430,11 +1434,13 @@ func TestFunc(t *testing.T) {
}
}
-/*
-
-Not yet implemented for gccgo.
-
func TestMakeFunc(t *testing.T) {
+ switch runtime.GOARCH {
+ case "amd64", "386":
+ default:
+ t.Skip("MakeFunc not implemented for " + runtime.GOARCH)
+ }
+
f := dummy
fv := MakeFunc(TypeOf(f), func(in []Value) []Value { return in })
ValueOf(&f).Elem().Set(fv)
@@ -1452,7 +1458,29 @@ func TestMakeFunc(t *testing.T) {
}
}
-*/
+func TestMakeFuncInterface(t *testing.T) {
+ switch runtime.GOARCH {
+ case "amd64", "386":
+ default:
+ t.Skip("MakeFunc not implemented for " + runtime.GOARCH)
+ }
+
+ fn := func(i int) int { return i }
+ incr := func(in []Value) []Value {
+ return []Value{ValueOf(int(in[0].Int() + 1))}
+ }
+ fv := MakeFunc(TypeOf(fn), incr)
+ ValueOf(&fn).Elem().Set(fv)
+ if r := fn(2); r != 3 {
+ t.Errorf("Call returned %d, want 3", r)
+ }
+ if r := fv.Call([]Value{ValueOf(14)})[0].Int(); r != 15 {
+ t.Errorf("Call returned %d, want 15", r)
+ }
+ if r := fv.Interface().(func(int) int)(26); r != 27 {
+ t.Errorf("Call returned %d, want 27", r)
+ }
+}
type Point struct {
x, y int
@@ -1606,6 +1634,25 @@ func TestMethodValue(t *testing.T) {
t.Errorf("Pointer Value MethodByName returned %d; want 325", i)
}
+ // Curried method of pointer to pointer.
+ pp := &p
+ v = ValueOf(&pp).Elem().Method(1)
+ if tt := v.Type(); tt != tfunc {
+ t.Errorf("Pointer Pointer Value Method Type is %s; want %s", tt, tfunc)
+ }
+ i = ValueOf(v.Interface()).Call([]Value{ValueOf(14)})[0].Int()
+ if i != 350 {
+ t.Errorf("Pointer Pointer Value Method returned %d; want 350", i)
+ }
+ v = ValueOf(&pp).Elem().MethodByName("Dist")
+ if tt := v.Type(); tt != tfunc {
+ t.Errorf("Pointer Pointer Value MethodByName Type is %s; want %s", tt, tfunc)
+ }
+ i = ValueOf(v.Interface()).Call([]Value{ValueOf(15)})[0].Int()
+ if i != 375 {
+ t.Errorf("Pointer Pointer Value MethodByName returned %d; want 375", i)
+ }
+
// Curried method of interface value.
// Have to wrap interface value in a struct to get at it.
// Passing it to ValueOf directly would
@@ -1620,17 +1667,17 @@ func TestMethodValue(t *testing.T) {
if tt := v.Type(); tt != tfunc {
t.Errorf("Interface Method Type is %s; want %s", tt, tfunc)
}
- i = ValueOf(v.Interface()).Call([]Value{ValueOf(14)})[0].Int()
- if i != 350 {
- t.Errorf("Interface Method returned %d; want 350", i)
+ i = ValueOf(v.Interface()).Call([]Value{ValueOf(16)})[0].Int()
+ if i != 400 {
+ t.Errorf("Interface Method returned %d; want 400", i)
}
v = pv.MethodByName("Dist")
if tt := v.Type(); tt != tfunc {
t.Errorf("Interface MethodByName Type is %s; want %s", tt, tfunc)
}
- i = ValueOf(v.Interface()).Call([]Value{ValueOf(15)})[0].Int()
- if i != 375 {
- t.Errorf("Interface MethodByName returned %d; want 375", i)
+ i = ValueOf(v.Interface()).Call([]Value{ValueOf(17)})[0].Int()
+ if i != 425 {
+ t.Errorf("Interface MethodByName returned %d; want 425", i)
}
}
@@ -2306,6 +2353,9 @@ func TestAddr(t *testing.T) {
/* gccgo does do allocations here.
func noAlloc(t *testing.T, n int, f func(int)) {
+ if testing.Short() {
+ t.Skip("skipping malloc count in short mode")
+ }
if runtime.GOMAXPROCS(0) > 1 {
t.Skip("skipping; GOMAXPROCS>1")
}
@@ -2389,6 +2439,74 @@ func TestSlice(t *testing.T) {
}
}
+func TestSlice3(t *testing.T) {
+ xs := []int{1, 2, 3, 4, 5, 6, 7, 8}
+ v := ValueOf(xs).Slice3(3, 5, 7).Interface().([]int)
+ if len(v) != 2 {
+ t.Errorf("len(xs.Slice3(3, 5, 7)) = %d", len(v))
+ }
+ if cap(v) != 4 {
+ t.Errorf("cap(xs.Slice3(3, 5, 7)) = %d", cap(v))
+ }
+ if !DeepEqual(v[0:4], xs[3:7:7]) {
+ t.Errorf("xs.Slice3(3, 5, 7)[0:4] = %v", v[0:4])
+ }
+ rv := ValueOf(&xs).Elem()
+ shouldPanic(func() { rv.Slice3(1, 2, 1) })
+ shouldPanic(func() { rv.Slice3(1, 1, 11) })
+ shouldPanic(func() { rv.Slice3(2, 2, 1) })
+
+ xa := [8]int{10, 20, 30, 40, 50, 60, 70, 80}
+ v = ValueOf(&xa).Elem().Slice3(2, 5, 6).Interface().([]int)
+ if len(v) != 3 {
+ t.Errorf("len(xa.Slice(2, 5, 6)) = %d", len(v))
+ }
+ if cap(v) != 4 {
+ t.Errorf("cap(xa.Slice(2, 5, 6)) = %d", cap(v))
+ }
+ if !DeepEqual(v[0:4], xa[2:6:6]) {
+ t.Errorf("xs.Slice(2, 5, 6)[0:4] = %v", v[0:4])
+ }
+ rv = ValueOf(&xa).Elem()
+ shouldPanic(func() { rv.Slice3(1, 2, 1) })
+ shouldPanic(func() { rv.Slice3(1, 1, 11) })
+ shouldPanic(func() { rv.Slice3(2, 2, 1) })
+
+ s := "hello world"
+ rv = ValueOf(&s).Elem()
+ shouldPanic(func() { rv.Slice3(1, 2, 3) })
+}
+
+func TestSetLenCap(t *testing.T) {
+ xs := []int{1, 2, 3, 4, 5, 6, 7, 8}
+ xa := [8]int{10, 20, 30, 40, 50, 60, 70, 80}
+
+ vs := ValueOf(&xs).Elem()
+ shouldPanic(func() { vs.SetLen(10) })
+ shouldPanic(func() { vs.SetCap(10) })
+ shouldPanic(func() { vs.SetLen(-1) })
+ shouldPanic(func() { vs.SetCap(-1) })
+ shouldPanic(func() { vs.SetCap(6) }) // smaller than len
+ vs.SetLen(5)
+ if len(xs) != 5 || cap(xs) != 8 {
+ t.Errorf("after SetLen(5), len, cap = %d, %d, want 5, 8", len(xs), cap(xs))
+ }
+ vs.SetCap(6)
+ if len(xs) != 5 || cap(xs) != 6 {
+ t.Errorf("after SetCap(6), len, cap = %d, %d, want 5, 6", len(xs), cap(xs))
+ }
+ vs.SetCap(5)
+ if len(xs) != 5 || cap(xs) != 5 {
+ t.Errorf("after SetCap(5), len, cap = %d, %d, want 5, 5", len(xs), cap(xs))
+ }
+ shouldPanic(func() { vs.SetCap(4) }) // smaller than len
+ shouldPanic(func() { vs.SetLen(6) }) // bigger than cap
+
+ va := ValueOf(&xa).Elem()
+ shouldPanic(func() { va.SetLen(8) })
+ shouldPanic(func() { va.SetCap(8) })
+}
+
func TestVariadic(t *testing.T) {
var b bytes.Buffer
V := ValueOf
@@ -2406,6 +2524,15 @@ func TestVariadic(t *testing.T) {
}
}
+func TestFuncArg(t *testing.T) {
+ f1 := func(i int, f func(int) int) int { return f(i) }
+ f2 := func(i int) int { return i + 1 }
+ r := ValueOf(f1).Call([]Value{ValueOf(100), ValueOf(f2)})
+ if r[0].Int() != 101 {
+ t.Errorf("function returned %d, want 101", r[0].Int())
+ }
+}
+
var tagGetTests = []struct {
Tag StructTag
Key string
@@ -2925,17 +3052,28 @@ func TestConvert(t *testing.T) {
all[t2] = true
canConvert[[2]Type{t1, t2}] = true
+ // vout1 represents the in value converted to the in type.
v1 := tt.in
vout1 := v1.Convert(t1)
out1 := vout1.Interface()
if vout1.Type() != tt.in.Type() || !DeepEqual(out1, tt.in.Interface()) {
- t.Errorf("ValueOf(%T(%v)).Convert(%s) = %T(%v), want %T(%v)", tt.in.Interface(), tt.in.Interface(), t1, out1, out1, tt.in.Interface(), tt.in.Interface())
+ t.Errorf("ValueOf(%T(%[1]v)).Convert(%s) = %T(%[3]v), want %T(%[4]v)", tt.in.Interface(), t1, out1, tt.in.Interface())
+ }
+
+ // vout2 represents the in value converted to the out type.
+ vout2 := v1.Convert(t2)
+ out2 := vout2.Interface()
+ if vout2.Type() != tt.out.Type() || !DeepEqual(out2, tt.out.Interface()) {
+ t.Errorf("ValueOf(%T(%[1]v)).Convert(%s) = %T(%[3]v), want %T(%[4]v)", tt.in.Interface(), t2, out2, tt.out.Interface())
}
- vout := v1.Convert(t2)
- out := vout.Interface()
- if vout.Type() != tt.out.Type() || !DeepEqual(out, tt.out.Interface()) {
- t.Errorf("ValueOf(%T(%v)).Convert(%s) = %T(%v), want %T(%v)", tt.in.Interface(), tt.in.Interface(), t2, out, out, tt.out.Interface(), tt.out.Interface())
+ // vout3 represents a new value of the out type, set to vout2. This makes
+ // sure the converted value vout2 is really usable as a regular value.
+ vout3 := New(t2).Elem()
+ vout3.Set(vout2)
+ out3 := vout3.Interface()
+ if vout3.Type() != tt.out.Type() || !DeepEqual(out3, tt.out.Interface()) {
+ t.Errorf("Set(ValueOf(%T(%[1]v)).Convert(%s)) = %T(%[3]v), want %T(%[4]v)", tt.in.Interface(), t2, out3, tt.out.Interface())
}
if IsRO(v1) {
@@ -2944,8 +3082,11 @@ func TestConvert(t *testing.T) {
if IsRO(vout1) {
t.Errorf("self-conversion output %v is RO, should not be", vout1)
}
- if IsRO(vout) {
- t.Errorf("conversion output %v is RO, should not be", vout)
+ if IsRO(vout2) {
+ t.Errorf("conversion output %v is RO, should not be", vout2)
+ }
+ if IsRO(vout3) {
+ t.Errorf("set(conversion output) %v is RO, should not be", vout3)
}
if !IsRO(MakeRO(v1).Convert(t1)) {
t.Errorf("RO self-conversion output %v is not RO, should be", v1)
@@ -3372,6 +3513,46 @@ func BenchmarkFieldByName3(b *testing.B) {
}
}
+type S struct {
+ i1 int64
+ i2 int64
+}
+
+func BenchmarkInterfaceBig(b *testing.B) {
+ v := ValueOf(S{})
+ for i := 0; i < b.N; i++ {
+ v.Interface()
+ }
+ b.StopTimer()
+}
+
+func TestAllocsInterfaceBig(t *testing.T) {
+ if testing.Short() {
+ t.Skip("skipping malloc count in short mode")
+ }
+ v := ValueOf(S{})
+ if allocs := testing.AllocsPerRun(100, func() { v.Interface() }); allocs > 0 {
+ t.Error("allocs:", allocs)
+ }
+}
+
+func BenchmarkInterfaceSmall(b *testing.B) {
+ v := ValueOf(int64(0))
+ for i := 0; i < b.N; i++ {
+ v.Interface()
+ }
+}
+
+func TestAllocsInterfaceSmall(t *testing.T) {
+ if testing.Short() {
+ t.Skip("skipping malloc count in short mode")
+ }
+ v := ValueOf(int64(0))
+ if allocs := testing.AllocsPerRun(100, func() { v.Interface() }); allocs > 0 {
+ t.Error("allocs:", allocs)
+ }
+}
+
// An exhaustive is a mechanism for writing exhaustive or stochastic tests.
// The basic usage is:
//
diff --git a/libgo/go/reflect/deepequal.go b/libgo/go/reflect/deepequal.go
index 915afed4cda..e3bf3dcac0c 100644
--- a/libgo/go/reflect/deepequal.go
+++ b/libgo/go/reflect/deepequal.go
@@ -9,18 +9,17 @@ package reflect
// During deepValueEqual, must keep track of checks that are
// in progress. The comparison algorithm assumes that all
// checks in progress are true when it reencounters them.
-// Visited are stored in a map indexed by 17 * a1 + a2;
+// Visited comparisons are stored in a map indexed by visit.
type visit struct {
- a1 uintptr
- a2 uintptr
- typ Type
- next *visit
+ a1 uintptr
+ a2 uintptr
+ typ Type
}
// Tests for deep equality using reflected types. The map argument tracks
// comparisons that have already been seen, which allows short circuiting on
// recursive types.
-func deepValueEqual(v1, v2 Value, visited map[uintptr]*visit, depth int) (b bool) {
+func deepValueEqual(v1, v2 Value, visited map[visit]bool, depth int) bool {
if !v1.IsValid() || !v2.IsValid() {
return v1.IsValid() == v2.IsValid()
}
@@ -29,8 +28,15 @@ func deepValueEqual(v1, v2 Value, visited map[uintptr]*visit, depth int) (b bool
}
// if depth > 10 { panic("deepValueEqual") } // for debugging
+ hard := func(k Kind) bool {
+ switch k {
+ case Array, Map, Slice, Struct:
+ return true
+ }
+ return false
+ }
- if v1.CanAddr() && v2.CanAddr() {
+ if v1.CanAddr() && v2.CanAddr() && hard(v1.Kind()) {
addr1 := v1.UnsafeAddr()
addr2 := v2.UnsafeAddr()
if addr1 > addr2 {
@@ -44,17 +50,14 @@ func deepValueEqual(v1, v2 Value, visited map[uintptr]*visit, depth int) (b bool
}
// ... or already seen
- h := 17*addr1 + addr2
- seen := visited[h]
typ := v1.Type()
- for p := seen; p != nil; p = p.next {
- if p.a1 == addr1 && p.a2 == addr2 && p.typ == typ {
- return true
- }
+ v := visit{addr1, addr2, typ}
+ if visited[v] {
+ return true
}
// Remember for later.
- visited[h] = &visit{addr1, addr2, typ, seen}
+ visited[v] = true
}
switch v1.Kind() {
@@ -75,6 +78,9 @@ func deepValueEqual(v1, v2 Value, visited map[uintptr]*visit, depth int) (b bool
if v1.Len() != v2.Len() {
return false
}
+ if v1.Pointer() == v2.Pointer() {
+ return true
+ }
for i := 0; i < v1.Len(); i++ {
if !deepValueEqual(v1.Index(i), v2.Index(i), visited, depth+1) {
return false
@@ -102,6 +108,9 @@ func deepValueEqual(v1, v2 Value, visited map[uintptr]*visit, depth int) (b bool
if v1.Len() != v2.Len() {
return false
}
+ if v1.Pointer() == v2.Pointer() {
+ return true
+ }
for _, k := range v1.MapKeys() {
if !deepValueEqual(v1.MapIndex(k), v2.MapIndex(k), visited, depth+1) {
return false
@@ -135,5 +144,5 @@ func DeepEqual(a1, a2 interface{}) bool {
if v1.Type() != v2.Type() {
return false
}
- return deepValueEqual(v1, v2, make(map[uintptr]*visit), 0)
+ return deepValueEqual(v1, v2, make(map[visit]bool), 0)
}
diff --git a/libgo/go/reflect/example_test.go b/libgo/go/reflect/example_test.go
index 62455c00ad9..cca28eeece8 100644
--- a/libgo/go/reflect/example_test.go
+++ b/libgo/go/reflect/example_test.go
@@ -50,3 +50,17 @@ func ExampleMakeFunc() {
// 1 0
// 3.14 2.72
}
+
+func ExampleStructTag() {
+ type S struct {
+ F string `species:"gopher" color:"blue"`
+ }
+
+ s := S{}
+ st := reflect.TypeOf(s)
+ field := st.Field(0)
+ fmt.Println(field.Tag.Get("color"), field.Tag.Get("species"))
+
+ // Output:
+ // blue gopher
+}
diff --git a/libgo/go/reflect/makefunc.go b/libgo/go/reflect/makefunc.go
index f03beb34483..505c543a082 100644
--- a/libgo/go/reflect/makefunc.go
+++ b/libgo/go/reflect/makefunc.go
@@ -7,6 +7,7 @@
package reflect
import (
+ "runtime"
"unsafe"
)
@@ -22,7 +23,7 @@ type makeFuncImpl struct {
// that wraps the function fn. When called, that new function
// does the following:
//
-// - converts its arguments to a list of Values args.
+// - converts its arguments to a slice of Values.
// - runs results := fn(args).
// - returns the results as a slice of Values, one per formal result.
//
@@ -45,14 +46,33 @@ func MakeFunc(typ Type, fn func(args []Value) (results []Value)) Value {
panic("reflect: call of MakeFunc with non-Func type")
}
+ switch runtime.GOARCH {
+ case "amd64", "386":
+ default:
+ panic("reflect.MakeFunc not implemented for " + runtime.GOARCH)
+ }
+
t := typ.common()
ftyp := (*funcType)(unsafe.Pointer(t))
- _, _ = t, ftyp
+ // Indirect Go func value (dummy) to obtain
+ // actual code address. (A Go func value is a pointer
+ // to a C function pointer. http://golang.org/s/go11func.)
+ dummy := makeFuncStub
+ code := **(**uintptr)(unsafe.Pointer(&dummy))
- panic("reflect MakeFunc not implemented")
+ impl := &makeFuncImpl{code: code, typ: ftyp, fn: fn}
+
+ return Value{t, unsafe.Pointer(&impl), flag(Func<<flagKindShift) | flagIndir}
}
+// makeFuncStub is an assembly function that is the code half of
+// the function returned from MakeFunc. It expects a *callReflectFunc
+// as its context register, and its job is to invoke callReflect(ctxt, frame)
+// where ctxt is the context register and frame is a pointer to the first
+// word in the passed-in argument frame.
+func makeFuncStub()
+
// makeMethodValue converts v from the rcvr+method index representation
// of a method value to an actual method func value, which is
// basically the receiver value with a special bit set, into a true
diff --git a/libgo/go/reflect/makefunc_386.S b/libgo/go/reflect/makefunc_386.S
new file mode 100644
index 00000000000..5878bc44c56
--- /dev/null
+++ b/libgo/go/reflect/makefunc_386.S
@@ -0,0 +1,198 @@
+/* Copyright 2013 The Go Authors. All rights reserved.
+ Use of this source code is governed by a BSD-style
+ license that can be found in the LICENSE file.
+
+ MakeFunc 386 assembly code. */
+
+#include "config.h"
+
+ .globl reflect.makeFuncStub
+
+#ifdef __ELF__
+ .type reflect.makeFuncStub,@function
+#endif
+
+reflect.makeFuncStub:
+.LFB1:
+
+ /* Go does not provide any equivalent to the regparm function
+ attribute, so on Go we do not need to worry about passing
+ parameters in registers. We just pass a pointer to the
+ arguments on the stack.
+
+ We do need to pick up the return values, though, so we pass
+ a pointer to a struct that looks like this.
+ struct {
+ esp uint32 // 0x0
+ eax uint32 // 0x4
+ st0 uint64 // 0x8
+ }
+ */
+
+ pushl %ebp
+.LCFI0:
+ movl %esp, %ebp
+.LCFI1:
+ pushl %ebx /* In case this is PIC. */
+ subl $36, %esp /* Enough for args and to align stack. */
+.LCFI2:
+
+#ifdef __PIC__
+ call __x86.get_pc_thunk.bx
+ addl $_GLOBAL_OFFSET_TABLE_, %ebx
+#endif
+
+ leal 8(%ebp), %eax /* Set esp field in struct. */
+ movl %eax, -24(%ebp)
+
+#ifdef __PIC__
+ call __go_get_closure@PLT
+#else
+ call __go_get_closure
+#endif
+
+ movl %eax, 4(%esp)
+
+ leal -24(%ebp), %eax
+ movl %eax, (%esp)
+
+#ifdef __PIC__
+ call reflect.MakeFuncStubGo@PLT
+#else
+ call reflect.MakeFuncStubGo
+#endif
+
+ /* Set return registers. */
+
+ movl -20(%ebp), %eax
+ fldl -16(%ebp)
+
+#ifdef __SSE2__
+ /* In case we are compiling with -msseregparm. This won't work
+ correctly if only SSE1 is supported, but that seems unlikely. */
+ movsd -16(%ebp), %xmm0
+#endif
+
+ addl $36, %esp
+ popl %ebx
+.LCFI3:
+ popl %ebp
+.LCFI4:
+ ret
+.LFE1:
+#ifdef __ELF__
+ .size reflect.makeFuncStub, . - reflect.makeFuncStub
+#endif
+
+#ifdef __PIC__
+#ifdef HAVE_AS_COMDAT_GAS
+ .section .text.__x86.get_pc_thunk.bx,"axG",@progbits,__x86.get_pc_thunk.bx,comdat
+#else
+ /* Sun as needs a different syntax. */
+ .section .text.__x86.get_pc_thunk.bx%__x86.get_pc_thunk.bx,"ax",@progbits
+ .group __x86.get_pc_thunk.bx,.text.__x86.get_pc_thunk.bx%__x86.get_pc_thunk.bx,#comdat
+#endif
+ .globl __x86.get_pc_thunk.bx
+ .hidden __x86.get_pc_thunk.bx
+#ifdef __ELF__
+ .type __x86.get_pc_thunk.bx, @function
+#endif
+__x86.get_pc_thunk.bx:
+.LFB2:
+ movl (%esp), %ebx
+ ret
+.LFE2:
+#ifdef __ELF__
+ .size __x86.get_pc_thunk.bx, . - __x86.get_pc_thunk.bx
+#endif
+#endif
+
+#ifdef __ELF__
+#if defined __PIC__
+# if defined __sun__ && defined __svr4__
+/* 32-bit Solaris 2/x86 uses datarel encoding for PIC. GNU ld before 2.22
+ doesn't correctly sort .eh_frame_hdr with mixed encodings, so match this. */
+# define FDE_ENCODING 0x30 /* datarel */
+# define FDE_ENCODE(X) X@GOTOFF
+# else
+# define FDE_ENCODING 0x1b /* pcrel sdata4 */
+# if defined HAVE_AS_X86_PCREL
+# define FDE_ENCODE(X) X-.
+# else
+# define FDE_ENCODE(X) X@rel
+# endif
+# endif
+#else
+# define FDE_ENCODING 0 /* absolute */
+# define FDE_ENCODE(X) X
+#endif
+
+ .section .eh_frame,EH_FRAME_FLAGS,@progbits
+.Lframe1:
+ .long .LECIE1-.LSCIE1 /* Length of Common Information Entry */
+.LSCIE1:
+ .long 0x0 /* CIE Identifier Tag */
+ .byte 0x1 /* CIE Version */
+ .ascii "zR\0" /* CIE Augmentation */
+ .byte 0x1 /* .uleb128 0x1; CIE Code Alignment Factor */
+ .byte 0x7c /* .sleb128 -4; CIE Data Alignment Factor */
+ .byte 0x8 /* CIE RA Column */
+ .byte 0x1 /* .uleb128 0x1; Augmentation size */
+ .byte FDE_ENCODING
+ .byte 0xc /* DW_CFA_def_cfa */
+ .byte 0x4 /* .uleb128 0x4 */
+ .byte 0x4 /* .uleb128 0x4 */
+ .byte 0x88 /* DW_CFA_offset, column 0x8 */
+ .byte 0x1 /* .uleb128 0x1 */
+ .align 4
+.LECIE1:
+.LSFDE1:
+ .long .LEFDE1-.LASFDE1 /* FDE Length */
+.LASFDE1:
+ .long .LASFDE1-.Lframe1 /* FDE CIE offset */
+ .long FDE_ENCODE(.LFB1) /* FDE initial location */
+ .long .LFE1-.LFB1 /* FDE address range */
+ .byte 0x0 /* .uleb128 0x0; Augmentation size */
+ .byte 0x4 /* DW_CFA_advance_loc4 */
+ .long .LCFI0-.LFB1
+ .byte 0xe /* DW_CFA_def_cfa_offset */
+ .byte 0x8 /* .uleb128 0x8 */
+ .byte 0x85 /* DW_CFA_offset, column 0x5 */
+ .byte 0x2 /* .uleb128 0x2 */
+ .byte 0x4 /* DW_CFA_advance_loc4 */
+ .long .LCFI1-.LCFI0
+ .byte 0xd /* DW_CFA_def_cfa_register */
+ .byte 0x5 /* .uleb128 0x5 */
+ .byte 0x4 /* DW_CFA_advance_loc4 */
+ .long .LCFI2-.LCFI1
+ .byte 0x83 /* .DW_CFA_offset, column 0x3 */
+ .byte 0x3 /* .uleb128 0x3 */
+ .byte 0x4 /* DW_CFA_advance_loc4 */
+ .long .LCFI3-.LCFI2
+ .byte 0xc3 /* DW_CFA_restore, column 0x3 */
+ .byte 0x4 /* DW_CFA_advance_loc4 */
+ .long .LCFI4-.LCFI3
+ .byte 0xc5 /* DW_CFA_restore, column 0x5 */
+ .byte 0xc /* DW_CFA_def_cfa */
+ .byte 0x4 /* .uleb128 0x4 */
+ .byte 0x4 /* .uleb128 0x4 */
+ .align 4
+.LEFDE1:
+#ifdef __PIC__
+.LSFDE2:
+ .long .LEFDE2-.LASFDE2 /* FDE Length */
+.LASFDE2:
+ .long .LASFDE2-.Lframe1 /* FDE CIE offset */
+ .long FDE_ENCODE(.LFB2) /* FDE initial location */
+ .long .LFE2-.LFB2 /* FDE address range */
+ .byte 0x0 /* .uleb128 0x0; Augmentation size */
+ .align 4
+.LEFDE2:
+#endif /* __PIC__ */
+#endif /* __ELF__ */
+
+#if defined(__ELF__) && defined(__linux__)
+ .section .note.GNU-stack,"",@progbits
+ .section .note.GNU-split-stack,"",@progbits
+ .section .note.GNU-no-split-stack,"",@progbits
+#endif
diff --git a/libgo/go/reflect/makefunc_amd64.S b/libgo/go/reflect/makefunc_amd64.S
new file mode 100644
index 00000000000..9d12f193f01
--- /dev/null
+++ b/libgo/go/reflect/makefunc_amd64.S
@@ -0,0 +1,162 @@
+# Copyright 2013 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+# MakeFunc amd64 assembly code.
+
+#include "config.h"
+
+ .global reflect.makeFuncStub
+
+#ifdef __ELF__
+ .type reflect.makeFuncStub,@function
+#endif
+
+reflect.makeFuncStub:
+.LFB1:
+
+ # Store all the parameter registers in a struct that looks
+ # like:
+ # struct {
+ # rax uint64 // 0x0
+ # rdi uint64 // 0x8
+ # rsi uint64 // 0x10
+ # rdx uint64 // 0x18
+ # rcx uint64 // 0x20
+ # r8 uint64 // 0x28
+ # r9 uint64 // 0x30
+ # rsp uint64 // 0x38 Pointer to arguments on stack.
+ # xmm0 [2]uint64 // 0x40
+ # xmm1 [2]uint64 // 0x50
+ # xmm2 [2]uint64 // 0x60
+ # xmm3 [2]uint64 // 0x70
+ # xmm4 [2]uint64 // 0x80
+ # xmm5 [2]uint64 // 0x90
+ # xmm6 [2]uint64 // 0xa0
+ # xmm7 [2]uint64 // 0xb0
+ # };
+
+ pushq %rbp
+.LCFI0:
+ movq %rsp, %rbp
+.LCFI1:
+
+ subq $0xc0, %rsp # Space for struct on stack.
+
+ movq %rax, 0x0(%rsp)
+ movq %rdi, 0x8(%rsp)
+ movq %rsi, 0x10(%rsp)
+ movq %rdx, 0x18(%rsp)
+ movq %rcx, 0x20(%rsp)
+ movq %r8, 0x28(%rsp)
+ movq %r9, 0x30(%rsp)
+ leaq 16(%rbp), %rax
+ movq %rax, 0x38(%rsp)
+ movdqa %xmm0, 0x40(%rsp)
+ movdqa %xmm1, 0x50(%rsp)
+ movdqa %xmm2, 0x60(%rsp)
+ movdqa %xmm3, 0x70(%rsp)
+ movdqa %xmm4, 0x80(%rsp)
+ movdqa %xmm5, 0x90(%rsp)
+ movdqa %xmm6, 0xa0(%rsp)
+ movdqa %xmm7, 0xb0(%rsp)
+
+ # Get function type.
+#ifdef __PIC__
+ call __go_get_closure@PLT
+#else
+ call __go_get_closure
+#endif
+ movq %rax, %rsi
+
+ movq %rsp, %rdi
+
+#ifdef __PIC__
+ call reflect.MakeFuncStubGo@PLT
+#else
+ call reflect.MakeFuncStubGo
+#endif
+
+ # The structure will be updated with any return values. Load
+ # all possible return registers before returning to the caller.
+
+ movq 0x0(%rsp), %rax
+ movq 0x18(%rsp), %rdx
+ movq 0x8(%rsp), %rdi
+ movq 0x10(%rsp), %rsi
+ movdqa 0x40(%rsp), %xmm0
+ movdqa 0x50(%rsp), %xmm1
+
+ # long double values are returned on the floating point stack,
+ # but we don't worry about that since Go doesn't have a long
+ # double type.
+
+ leave
+.LCFI2:
+
+ ret
+.LFE1:
+
+#ifdef __ELF__
+ .size reflect.makeFuncStub, . - reflect.makeFuncStub
+#endif
+
+#ifdef __ELF__
+#ifdef HAVE_AS_X86_64_UNWIND_SECTION_TYPE
+ .section .eh_frame,"a",@unwind
+#else
+ .section .eh_frame,"a",@progbits
+#endif
+.Lframe1:
+ .long .LECIE1-.LSCIE1 /* Length of Common Information Entry */
+.LSCIE1:
+ .long 0x0 /* CIE Identifier Tag */
+ .byte 0x1 /* CIE Version */
+ .ascii "zR\0" /* CIE Augmentation */
+ .uleb128 1 /* CIE Code Alignment Factor */
+ .sleb128 -8 /* CIE Data Alignment Factor */
+ .byte 0x10 /* CIE RA Column */
+ .uleb128 1 /* Augmentation size */
+ .byte 0x1b /* FDE Encoding (pcrel sdata4) */
+ .byte 0xc /* DW_CFA_def_cfa, %rsp offset 8 */
+ .uleb128 7
+ .uleb128 8
+ .byte 0x80+16 /* DW_CFA_offset, %rip offset 1*-8 */
+ .uleb128 1
+ .align 8
+.LECIE1:
+.LSFDE1:
+ .long .LEFDE1-.LASFDE1 /* FDE Length */
+.LASFDE1:
+ .long .LASFDE1-.Lframe1 /* FDE CIE offset */
+#if HAVE_AS_X86_PCREL
+ .long .LFB1-. /* FDE initial location */
+#else
+ .long .LFB1@rel
+#endif
+ .long .LFE1-.LFB1 /* FDE address range */
+ .uleb128 0x0 /* Augmentation size */
+ .byte 0x4 /* DW_CFA_advance_loc4 */
+ .long .LCFI0-.LFB1
+ .byte 0xe /* DW_CFA_def_cfa_offset */
+ .uleb128 16
+ .byte 0x86 /* DW_CFA_offset, column 0x6 */
+ .uleb128 2
+ .byte 0x4 /* DW_CFA_advance_loc4 */
+ .long .LCFI1-.LCFI0
+ .byte 0xd /* DW_CFA_def_cfa_register */
+ .uleb128 6
+ .byte 0x2 /* DW_CFA_advance_loc1 */
+ .byte .LCFI2-.LCFI1
+ .byte 0xc /* DW_CFA_def_cfa */
+ .uleb128 7
+ .uleb128 8
+ .align 8
+.LEFDE1:
+#endif /* __ELF__ */
+
+#if defined(__ELF__) && defined(__linux__)
+ .section .note.GNU-stack,"",@progbits
+ .section .note.GNU-split-stack,"",@progbits
+ .section .note.GNU-no-split-stack,"",@progbits
+#endif
diff --git a/libgo/go/reflect/makefunc_dummy.c b/libgo/go/reflect/makefunc_dummy.c
new file mode 100644
index 00000000000..aba48df3eb8
--- /dev/null
+++ b/libgo/go/reflect/makefunc_dummy.c
@@ -0,0 +1,12 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !amd64
+
+// Dummy function for processors without makefunc support.
+
+void makeFuncStub () __asm__ ("reflect.makeFuncStub");
+void makeFuncStub ()
+{
+}
diff --git a/libgo/go/reflect/makefuncgo_386.go b/libgo/go/reflect/makefuncgo_386.go
new file mode 100644
index 00000000000..0fac1f488a4
--- /dev/null
+++ b/libgo/go/reflect/makefuncgo_386.go
@@ -0,0 +1,135 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// MakeFunc 386 implementation.
+
+package reflect
+
+import "unsafe"
+
+// The assembler stub will pass a pointer to this structure. We
+// assume that no parameters are passed in registers--that is, we do
+// not support the -mregparm option. On return we will set the
+// registers that might hold result values.
+type i386Regs struct {
+ esp uint32
+ eax uint32 // Value to return in %eax.
+ st0 uint64 // Value to return in %st(0).
+}
+
+// MakeFuncStubGo implements the 386 calling convention for MakeFunc.
+// This should not be called. It is exported so that assembly code
+// can call it.
+
+func MakeFuncStubGo(regs *i386Regs, c *makeFuncImpl) {
+ ftyp := c.typ
+
+ // See if the result requires a struct. If it does, the first
+ // parameter is a pointer to the struct.
+ retStruct := false
+ retEmpty := false
+ switch len(ftyp.out) {
+ case 0:
+ retEmpty = true
+ case 1:
+ if ftyp.out[0].size == 0 {
+ retEmpty = true
+ } else {
+ switch ftyp.out[0].Kind() {
+ case Complex64, Complex128, Array, Interface, Slice, String, Struct:
+ retStruct = true
+ }
+ }
+ default:
+ size := uintptr(0)
+ for _, typ := range ftyp.out {
+ size += typ.size
+ }
+ if size == 0 {
+ retEmpty = true
+ } else {
+ retStruct = true
+ }
+ }
+
+ in := make([]Value, 0, len(ftyp.in))
+ ap := uintptr(regs.esp)
+
+ var retPtr unsafe.Pointer
+ if retStruct {
+ retPtr = *(*unsafe.Pointer)(unsafe.Pointer(ap))
+ ap += ptrSize
+ }
+
+ for _, rt := range ftyp.in {
+ ap = align(ap, ptrSize)
+
+ // We have to copy the argument onto the heap in case
+ // the function hangs on the reflect.Value we pass it.
+ p := unsafe_New(rt)
+ memmove(p, unsafe.Pointer(ap), rt.size)
+
+ v := Value{rt, p, flag(rt.Kind()<<flagKindShift) | flagIndir}
+ in = append(in, v)
+ ap += rt.size
+ }
+
+ // Call the real function.
+
+ out := c.fn(in)
+
+ if len(out) != len(ftyp.out) {
+ panic("reflect: wrong return count from function created by MakeFunc")
+ }
+
+ for i, typ := range ftyp.out {
+ v := out[i]
+ if v.typ != typ {
+ panic("reflect: function created by MakeFunc using " + funcName(c.fn) +
+ " returned wrong type: have " +
+ out[i].typ.String() + " for " + typ.String())
+ }
+ if v.flag&flagRO != 0 {
+ panic("reflect: function created by MakeFunc using " + funcName(c.fn) +
+ " returned value obtained from unexported field")
+ }
+ }
+
+ if retEmpty {
+ return
+ }
+
+ if retStruct {
+ off := uintptr(0)
+ for i, typ := range ftyp.out {
+ v := out[i]
+ off = align(off, uintptr(typ.fieldAlign))
+ addr := unsafe.Pointer(uintptr(retPtr) + off)
+ if v.flag&flagIndir == 0 && (v.kind() == Ptr || v.kind() == UnsafePointer) {
+ storeIword(addr, iword(v.val), typ.size)
+ } else {
+ memmove(addr, v.val, typ.size)
+ }
+ off += typ.size
+ }
+ regs.eax = uint32(uintptr(retPtr))
+ return
+ }
+
+ if len(ftyp.out) != 1 {
+ panic("inconsistency")
+ }
+
+ v := out[0]
+ w := v.iword()
+ if v.Kind() != Ptr && v.Kind() != UnsafePointer {
+ w = loadIword(unsafe.Pointer(w), v.typ.size)
+ }
+ switch v.Kind() {
+ case Float32, Float64:
+ regs.st0 = uint64(uintptr(w))
+ default:
+ regs.eax = uint32(uintptr(w))
+ }
+}
diff --git a/libgo/go/reflect/makefuncgo_amd64.go b/libgo/go/reflect/makefuncgo_amd64.go
new file mode 100644
index 00000000000..ecc50a42520
--- /dev/null
+++ b/libgo/go/reflect/makefuncgo_amd64.go
@@ -0,0 +1,493 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// MakeFunc amd64 implementation.
+
+package reflect
+
+import "unsafe"
+
+// The assembler stub will pass a pointer to this structure.
+// This will come in holding all the registers that might hold
+// function parameters. On return we will set the registers that
+// might hold result values.
+type amd64Regs struct {
+ rax uint64
+ rdi uint64
+ rsi uint64
+ rdx uint64
+ rcx uint64
+ r8 uint64
+ r9 uint64
+ rsp uint64
+ xmm0 [2]uint64
+ xmm1 [2]uint64
+ xmm2 [2]uint64
+ xmm3 [2]uint64
+ xmm4 [2]uint64
+ xmm5 [2]uint64
+ xmm6 [2]uint64
+ xmm7 [2]uint64
+}
+
+// Argument classifications. The amd64 ELF ABI uses several more, but
+// these are the only ones that arise for Go types.
+type amd64Class int
+
+const (
+ amd64Integer amd64Class = iota
+ amd64SSE
+ amd64NoClass
+ amd64Memory
+)
+
+// amd64Classify returns the one or two register classes needed to
+// pass the value of type. Go types never need more than two
+// registers. amd64Memory means the value is stored in memory.
+// amd64NoClass means the register is not used.
+func amd64Classify(typ *rtype) (amd64Class, amd64Class) {
+ switch typ.Kind() {
+ default:
+ panic("internal error--unknown kind in amd64Classify")
+
+ case Bool, Int, Int8, Int16, Int32, Int64,
+ Uint, Uint8, Uint16, Uint32, Uint64,
+ Uintptr, Chan, Func, Map, Ptr, UnsafePointer:
+
+ return amd64Integer, amd64NoClass
+
+ case Float32, Float64, Complex64:
+ return amd64SSE, amd64NoClass
+
+ case Complex128:
+ return amd64SSE, amd64SSE
+
+ case Array:
+ if typ.size == 0 {
+ return amd64NoClass, amd64NoClass
+ } else if typ.size > 16 {
+ return amd64Memory, amd64NoClass
+ }
+ atyp := (*arrayType)(unsafe.Pointer(typ))
+ eclass1, eclass2 := amd64Classify(atyp.elem)
+ if eclass1 == amd64Memory {
+ return amd64Memory, amd64NoClass
+ }
+ if eclass2 == amd64NoClass && typ.size > 8 {
+ eclass2 = eclass1
+ }
+ return eclass1, eclass2
+
+ case Interface:
+ return amd64Integer, amd64Integer
+
+ case Slice:
+ return amd64Memory, amd64NoClass
+
+ case String:
+ return amd64Integer, amd64Integer
+
+ case Struct:
+ if typ.size == 0 {
+ return amd64NoClass, amd64NoClass
+ } else if typ.size > 16 {
+ return amd64Memory, amd64NoClass
+ }
+ var first, second amd64Class
+ f := amd64NoClass
+ onFirst := true
+ styp := (*structType)(unsafe.Pointer(typ))
+ for _, field := range styp.fields {
+ if onFirst && field.offset >= 8 {
+ first = f
+ f = amd64NoClass
+ onFirst = false
+ }
+ fclass1, fclass2 := amd64Classify(field.typ)
+ f = amd64MergeClasses(f, fclass1)
+ if fclass2 != amd64NoClass {
+ if !onFirst {
+ panic("amd64Classify inconsistent")
+ }
+ first = f
+ f = fclass2
+ onFirst = false
+ }
+ }
+ if onFirst {
+ first = f
+ second = amd64NoClass
+ } else {
+ second = f
+ }
+ if first == amd64Memory || second == amd64Memory {
+ return amd64Memory, amd64NoClass
+ }
+ return first, second
+ }
+}
+
+// amd64MergeClasses merges two register classes as described in the
+// amd64 ELF ABI.
+func amd64MergeClasses(c1, c2 amd64Class) amd64Class {
+ switch {
+ case c1 == c2:
+ return c1
+ case c1 == amd64NoClass:
+ return c2
+ case c2 == amd64NoClass:
+ return c1
+ case c1 == amd64Memory || c2 == amd64Memory:
+ return amd64Memory
+ case c1 == amd64Integer || c2 == amd64Integer:
+ return amd64Integer
+ default:
+ return amd64SSE
+ }
+}
+
+// MakeFuncStubGo implements the amd64 calling convention for
+// MakeFunc. This should not be called. It is exported so that
+// assembly code can call it.
+
+func MakeFuncStubGo(regs *amd64Regs, c *makeFuncImpl) {
+ ftyp := c.typ
+
+ // See if the result requires a struct. If it does, the first
+ // parameter is a pointer to the struct.
+ var ret1, ret2 amd64Class
+ switch len(ftyp.out) {
+ case 0:
+ ret1, ret2 = amd64NoClass, amd64NoClass
+ case 1:
+ ret1, ret2 = amd64Classify(ftyp.out[0])
+ default:
+ off := uintptr(0)
+ f := amd64NoClass
+ onFirst := true
+ for _, rt := range ftyp.out {
+ off = align(off, uintptr(rt.fieldAlign))
+
+ if onFirst && off >= 8 {
+ ret1 = f
+ f = amd64NoClass
+ onFirst = false
+ }
+
+ off += rt.size
+ if off > 16 {
+ break
+ }
+
+ fclass1, fclass2 := amd64Classify(rt)
+ f = amd64MergeClasses(f, fclass1)
+ if fclass2 != amd64NoClass {
+ if !onFirst {
+ panic("amd64Classify inconsistent")
+ }
+ ret1 = f
+ f = fclass2
+ onFirst = false
+ }
+ }
+ if off > 16 {
+ ret1, ret2 = amd64Memory, amd64NoClass
+ } else {
+ if onFirst {
+ ret1, ret2 = f, amd64NoClass
+ } else {
+ ret2 = f
+ }
+ }
+ if ret1 == amd64Memory || ret2 == amd64Memory {
+ ret1, ret2 = amd64Memory, amd64NoClass
+ }
+ }
+
+ in := make([]Value, 0, len(ftyp.in))
+ intreg := 0
+ ssereg := 0
+ ap := uintptr(regs.rsp)
+
+ maxIntregs := 6 // When we support Windows, this would be 4.
+ maxSSEregs := 8
+
+ if ret1 == amd64Memory {
+ // We are returning a value in memory, which means
+ // that the first argument is a hidden parameter
+ // pointing to that return area.
+ intreg++
+ }
+
+argloop:
+ for _, rt := range ftyp.in {
+ c1, c2 := amd64Classify(rt)
+
+ fl := flag(rt.Kind()) << flagKindShift
+ if c2 == amd64NoClass {
+
+ // Argument is passed in a single register or
+ // in memory.
+
+ switch c1 {
+ case amd64NoClass:
+ v := Value{rt, nil, fl | flagIndir}
+ in = append(in, v)
+ continue argloop
+ case amd64Integer:
+ if intreg < maxIntregs {
+ reg := amd64IntregVal(regs, intreg)
+ iw := unsafe.Pointer(reg)
+ if k := rt.Kind(); k != Ptr && k != UnsafePointer {
+ iw = unsafe.Pointer(&reg)
+ fl |= flagIndir
+ }
+ v := Value{rt, iw, fl}
+ in = append(in, v)
+ intreg++
+ continue argloop
+ }
+ case amd64SSE:
+ if ssereg < maxSSEregs {
+ reg := amd64SSEregVal(regs, ssereg)
+ v := Value{rt, unsafe.Pointer(&reg), fl | flagIndir}
+ in = append(in, v)
+ ssereg++
+ continue argloop
+ }
+ }
+
+ in, ap = amd64Memarg(in, ap, rt)
+ continue argloop
+ }
+
+ // Argument is passed in two registers.
+
+ nintregs := 0
+ nsseregs := 0
+ switch c1 {
+ case amd64Integer:
+ nintregs++
+ case amd64SSE:
+ nsseregs++
+ default:
+ panic("inconsistent")
+ }
+ switch c2 {
+ case amd64Integer:
+ nintregs++
+ case amd64SSE:
+ nsseregs++
+ default:
+ panic("inconsistent")
+ }
+
+ // If the whole argument does not fit in registers, it
+ // is passed in memory.
+
+ if intreg+nintregs > maxIntregs || ssereg+nsseregs > maxSSEregs {
+ in, ap = amd64Memarg(in, ap, rt)
+ continue argloop
+ }
+
+ var word1, word2 uintptr
+ switch c1 {
+ case amd64Integer:
+ word1 = amd64IntregVal(regs, intreg)
+ intreg++
+ case amd64SSE:
+ word1 = amd64SSEregVal(regs, ssereg)
+ ssereg++
+ }
+ switch c2 {
+ case amd64Integer:
+ word2 = amd64IntregVal(regs, intreg)
+ intreg++
+ case amd64SSE:
+ word2 = amd64SSEregVal(regs, ssereg)
+ ssereg++
+ }
+
+ p := unsafe_New(rt)
+ *(*uintptr)(p) = word1
+ *(*uintptr)(unsafe.Pointer(uintptr(p) + ptrSize)) = word2
+ v := Value{rt, p, fl | flagIndir}
+ in = append(in, v)
+ }
+
+ // All the real arguments have been found and turned into
+ // Value's. Call the real function.
+
+ out := c.fn(in)
+
+ if len(out) != len(ftyp.out) {
+ panic("reflect: wrong return count from function created by MakeFunc")
+ }
+
+ for i, typ := range ftyp.out {
+ v := out[i]
+ if v.typ != typ {
+ panic("reflect: function created by MakeFunc using " + funcName(c.fn) +
+ " returned wrong type: have " +
+ out[i].typ.String() + " for " + typ.String())
+ }
+ if v.flag&flagRO != 0 {
+ panic("reflect: function created by MakeFunc using " + funcName(c.fn) +
+ " returned value obtained from unexported field")
+ }
+ }
+
+ if ret1 == amd64NoClass {
+ return
+ }
+
+ if ret1 == amd64Memory {
+ // The address of the memory area was passed as a
+ // hidden parameter in %rdi.
+ ptr := unsafe.Pointer(uintptr(regs.rdi))
+ off := uintptr(0)
+ for i, typ := range ftyp.out {
+ v := out[i]
+ off = align(off, uintptr(typ.fieldAlign))
+ addr := unsafe.Pointer(uintptr(ptr) + off)
+ if v.flag&flagIndir == 0 && (v.kind() == Ptr || v.kind() == UnsafePointer) {
+ storeIword(addr, iword(v.val), typ.size)
+ } else {
+ memmove(addr, v.val, typ.size)
+ }
+ off += typ.size
+ }
+ return
+ }
+
+ if len(out) == 1 && ret2 == amd64NoClass {
+ v := out[0]
+ w := v.iword()
+ if v.Kind() != Ptr && v.Kind() != UnsafePointer {
+ w = loadIword(unsafe.Pointer(w), v.typ.size)
+ }
+ switch ret1 {
+ case amd64Integer:
+ regs.rax = uint64(uintptr(w))
+ case amd64SSE:
+ regs.xmm0[0] = uint64(uintptr(w))
+ regs.xmm0[1] = 0
+ default:
+ panic("inconsistency")
+ }
+ return
+ }
+
+ var buf [2]unsafe.Pointer
+ ptr := unsafe.Pointer(&buf[0])
+ off := uintptr(0)
+ for i, typ := range ftyp.out {
+ v := out[i]
+ off = align(off, uintptr(typ.fieldAlign))
+ addr := unsafe.Pointer(uintptr(ptr) + off)
+ if v.flag&flagIndir == 0 && (v.kind() == Ptr || v.kind() == UnsafePointer) {
+ storeIword(addr, iword(v.val), typ.size)
+ } else {
+ memmove(addr, v.val, typ.size)
+ }
+ off += uintptr(typ.size)
+ }
+
+ switch ret1 {
+ case amd64Integer:
+ regs.rax = *(*uint64)(unsafe.Pointer(&buf[0]))
+ case amd64SSE:
+ regs.xmm0[0] = *(*uint64)(unsafe.Pointer(&buf[0]))
+ regs.xmm0[1] = 0
+ default:
+ panic("inconsistency")
+ }
+
+ switch ret2 {
+ case amd64Integer:
+ reg := *(*uint64)(unsafe.Pointer(&buf[1]))
+ if ret1 == amd64Integer {
+ regs.rdx = reg
+ } else {
+ regs.rax = reg
+ }
+ case amd64SSE:
+ reg := *(*uint64)(unsafe.Pointer(&buf[1]))
+ if ret1 == amd64Integer {
+ regs.xmm0[0] = reg
+ regs.xmm0[1] = 0
+ } else {
+ regs.xmm1[0] = reg
+ regs.xmm1[1] = 0
+ }
+ case amd64NoClass:
+ default:
+ panic("inconsistency")
+ }
+}
+
+// The amd64Memarg function adds an argument passed in memory.
+func amd64Memarg(in []Value, ap uintptr, rt *rtype) ([]Value, uintptr) {
+ ap = align(ap, ptrSize)
+ ap = align(ap, uintptr(rt.align))
+
+ // We have to copy the argument onto the heap in case the
+ // function hangs onto the reflect.Value we pass it.
+ p := unsafe_New(rt)
+ memmove(p, unsafe.Pointer(ap), rt.size)
+
+ v := Value{rt, p, flag(rt.Kind()<<flagKindShift) | flagIndir}
+ in = append(in, v)
+ ap += rt.size
+ return in, ap
+}
+
+// The amd64IntregVal function returns the value of integer register i.
+func amd64IntregVal(regs *amd64Regs, i int) uintptr {
+ var r uint64
+ switch i {
+ case 0:
+ r = regs.rdi
+ case 1:
+ r = regs.rsi
+ case 2:
+ r = regs.rdx
+ case 3:
+ r = regs.rcx
+ case 4:
+ r = regs.r8
+ case 5:
+ r = regs.r9
+ default:
+ panic("amd64IntregVal: bad index")
+ }
+ return uintptr(r)
+}
+
+// The amd64SSEregVal function returns the value of SSE register i.
+// Note that although SSE registers can hold two uinptr's, for the
+// types we use in Go we only ever use the least significant one. The
+// most significant one would only be used for 128 bit types.
+func amd64SSEregVal(regs *amd64Regs, i int) uintptr {
+ var r uint64
+ switch i {
+ case 0:
+ r = regs.xmm0[0]
+ case 1:
+ r = regs.xmm1[0]
+ case 2:
+ r = regs.xmm2[0]
+ case 3:
+ r = regs.xmm3[0]
+ case 4:
+ r = regs.xmm4[0]
+ case 5:
+ r = regs.xmm5[0]
+ case 6:
+ r = regs.xmm6[0]
+ case 7:
+ r = regs.xmm7[0]
+ }
+ return uintptr(r)
+}
diff --git a/libgo/go/reflect/type.go b/libgo/go/reflect/type.go
index d084f38eba7..aaac2c3487f 100644
--- a/libgo/go/reflect/type.go
+++ b/libgo/go/reflect/type.go
@@ -191,6 +191,14 @@ type Type interface {
uncommon() *uncommonType
}
+// BUG(rsc): FieldByName and related functions consider struct field names to be equal
+// if the names are equal, even if they are unexported names originating
+// in different packages. The practical effect of this is that the result of
+// t.FieldByName("x") is not well defined if the struct type t contains
+// multiple fields named x (embedded from different packages).
+// FieldByName may return one of the fields named x or may report that there are none.
+// See golang.org/issue/4876 for more details.
+
/*
* These data structures are known to the compiler (../../cmd/gc/reflect.c).
* A few are known to ../runtime/type.go to convey to debuggers.
@@ -320,6 +328,8 @@ type mapType struct {
rtype `reflect:"map"`
key *rtype // map key type
elem *rtype // map element (value) type
+ // bucket *rtype // internal bucket structure
+ // hmap *rtype // internal map header
}
// ptrType represents a pointer type.
@@ -358,7 +368,6 @@ const (
_GC_ARRAY_START
_GC_ARRAY_NEXT
_GC_CALL
- _GC_MAP_PTR
_GC_CHAN_PTR
_GC_STRING
_GC_EFACE
@@ -1382,11 +1391,11 @@ func cachePut(k cacheKey, t *rtype) Type {
return t
}
-// garbage collection bytecode program for chan or map.
+// garbage collection bytecode program for chan.
// See ../../cmd/gc/reflect.c:/^dgcsym1 and :/^dgcsym.
-type chanMapGC struct {
+type chanGC struct {
width uintptr // sizeof(map)
- op uintptr // _GC_MAP_PTR or _GC_CHAN_PTR
+ op uintptr // _GC_CHAN_PTR
off uintptr // 0
typ *rtype // map type
end uintptr // _GC_END
@@ -1500,6 +1509,8 @@ func MapOf(key, elem Type) Type {
mt.key = ktyp
mt.elem = etyp
+ // mt.bucket = bucketOf(ktyp, etyp)
+ // mt.hmap = hMapOf(mt.bucket)
mt.uncommonType = nil
mt.ptrToThis = nil
@@ -1510,6 +1521,118 @@ func MapOf(key, elem Type) Type {
return cachePut(ckey, &mt.rtype)
}
+// Make sure these routines stay in sync with ../../pkg/runtime/hashmap.c!
+// These types exist only for GC, so we only fill out GC relevant info.
+// Currently, that's just size and the GC program. We also fill in string
+// for possible debugging use.
+const (
+ _BUCKETSIZE = 8
+ _MAXKEYSIZE = 128
+ _MAXVALSIZE = 128
+)
+
+func bucketOf(ktyp, etyp *rtype) *rtype {
+ if ktyp.size > _MAXKEYSIZE {
+ ktyp = PtrTo(ktyp).(*rtype)
+ }
+ if etyp.size > _MAXVALSIZE {
+ etyp = PtrTo(etyp).(*rtype)
+ }
+ ptrsize := unsafe.Sizeof(uintptr(0))
+
+ gc := make([]uintptr, 1) // first entry is size, filled in at the end
+ offset := _BUCKETSIZE * unsafe.Sizeof(uint8(0)) // topbits
+ gc = append(gc, _GC_PTR, offset, 0 /*self pointer set below*/) // overflow
+ offset += ptrsize
+
+ // keys
+ if ktyp.kind&kindNoPointers == 0 {
+ gc = append(gc, _GC_ARRAY_START, offset, _BUCKETSIZE, ktyp.size)
+ gc = appendGCProgram(gc, ktyp)
+ gc = append(gc, _GC_ARRAY_NEXT)
+ }
+ offset += _BUCKETSIZE * ktyp.size
+
+ // values
+ if etyp.kind&kindNoPointers == 0 {
+ gc = append(gc, _GC_ARRAY_START, offset, _BUCKETSIZE, etyp.size)
+ gc = appendGCProgram(gc, etyp)
+ gc = append(gc, _GC_ARRAY_NEXT)
+ }
+ offset += _BUCKETSIZE * etyp.size
+
+ gc = append(gc, _GC_END)
+ gc[0] = offset
+ gc[3] = uintptr(unsafe.Pointer(&gc[0])) // set self pointer
+
+ b := new(rtype)
+ b.size = offset
+ // b.gc = unsafe.Pointer(&gc[0])
+ s := "bucket(" + *ktyp.string + "," + *etyp.string + ")"
+ b.string = &s
+ return b
+}
+
+// Take the GC program for "t" and append it to the GC program "gc".
+func appendGCProgram(gc []uintptr, t *rtype) []uintptr {
+ // p := t.gc
+ var p unsafe.Pointer
+ p = unsafe.Pointer(uintptr(p) + unsafe.Sizeof(uintptr(0))) // skip size
+loop:
+ for {
+ var argcnt int
+ switch *(*uintptr)(p) {
+ case _GC_END:
+ // Note: _GC_END not included in append
+ break loop
+ case _GC_ARRAY_NEXT:
+ argcnt = 0
+ case _GC_APTR, _GC_STRING, _GC_EFACE, _GC_IFACE:
+ argcnt = 1
+ case _GC_PTR, _GC_CALL, _GC_CHAN_PTR, _GC_SLICE:
+ argcnt = 2
+ case _GC_ARRAY_START, _GC_REGION:
+ argcnt = 3
+ default:
+ panic("unknown GC program op for " + *t.string + ": " + strconv.FormatUint(*(*uint64)(p), 10))
+ }
+ for i := 0; i < argcnt+1; i++ {
+ gc = append(gc, *(*uintptr)(p))
+ p = unsafe.Pointer(uintptr(p) + unsafe.Sizeof(uintptr(0)))
+ }
+ }
+ return gc
+}
+func hMapOf(bucket *rtype) *rtype {
+ ptrsize := unsafe.Sizeof(uintptr(0))
+
+ // make gc program & compute hmap size
+ gc := make([]uintptr, 1) // first entry is size, filled in at the end
+ offset := unsafe.Sizeof(uint(0)) // count
+ offset += unsafe.Sizeof(uint32(0)) // flags
+ offset += unsafe.Sizeof(uint32(0)) // hash0
+ offset += unsafe.Sizeof(uint8(0)) // B
+ offset += unsafe.Sizeof(uint8(0)) // keysize
+ offset += unsafe.Sizeof(uint8(0)) // valuesize
+ offset = (offset + 1) / 2 * 2
+ offset += unsafe.Sizeof(uint16(0)) // bucketsize
+ offset = (offset + ptrsize - 1) / ptrsize * ptrsize
+ // gc = append(gc, _GC_PTR, offset, uintptr(bucket.gc)) // buckets
+ offset += ptrsize
+ // gc = append(gc, _GC_PTR, offset, uintptr(bucket.gc)) // oldbuckets
+ offset += ptrsize
+ offset += ptrsize // nevacuate
+ gc = append(gc, _GC_END)
+ gc[0] = offset
+
+ h := new(rtype)
+ h.size = offset
+ // h.gc = unsafe.Pointer(&gc[0])
+ s := "hmap(" + *bucket.string + ")"
+ h.string = &s
+ return h
+}
+
// garbage collection bytecode program for slice of non-zero-length values.
// See ../../cmd/gc/reflect.c:/^dgcsym1 and :/^dgcsym.
type sliceGC struct {
diff --git a/libgo/go/reflect/value.go b/libgo/go/reflect/value.go
index 69a87031e56..216ee3f1ca2 100644
--- a/libgo/go/reflect/value.go
+++ b/libgo/go/reflect/value.go
@@ -433,7 +433,7 @@ func (v Value) call(op string, in []Value) []Value {
if v.flag&flagMethod != 0 {
nin++
}
- firstPointer := len(in) > 0 && Kind(t.In(0).(*rtype).kind) != Ptr && v.flag&flagMethod == 0 && isMethod(v.typ)
+ firstPointer := len(in) > 0 && t.In(0).Kind() != Ptr && v.flag&flagMethod == 0 && isMethod(v.typ)
params := make([]unsafe.Pointer, nin)
off := 0
if v.flag&flagMethod != 0 {
@@ -497,8 +497,10 @@ func isMethod(t *rtype) bool {
sawRet := false
for i, c := range s {
if c == '(' {
+ if parens == 0 {
+ params++
+ }
parens++
- params++
} else if c == ')' {
parens--
} else if parens == 0 && c == ' ' && s[i+1] != '(' && !sawRet {
@@ -509,75 +511,6 @@ func isMethod(t *rtype) bool {
return params > 2
}
-// callReflect is the call implementation used by a function
-// returned by MakeFunc. In many ways it is the opposite of the
-// method Value.call above. The method above converts a call using Values
-// into a call of a function with a concrete argument frame, while
-// callReflect converts a call of a function with a concrete argument
-// frame into a call using Values.
-// It is in this file so that it can be next to the call method above.
-// The remainder of the MakeFunc implementation is in makefunc.go.
-func callReflect(ctxt *makeFuncImpl, frame unsafe.Pointer) {
- ftyp := ctxt.typ
- f := ctxt.fn
-
- // Copy argument frame into Values.
- ptr := frame
- off := uintptr(0)
- in := make([]Value, 0, len(ftyp.in))
- for _, arg := range ftyp.in {
- typ := arg
- off += -off & uintptr(typ.align-1)
- v := Value{typ, nil, flag(typ.Kind()) << flagKindShift}
- if typ.size <= ptrSize {
- // value fits in word.
- v.val = unsafe.Pointer(loadIword(unsafe.Pointer(uintptr(ptr)+off), typ.size))
- } else {
- // value does not fit in word.
- // Must make a copy, because f might keep a reference to it,
- // and we cannot let f keep a reference to the stack frame
- // after this function returns, not even a read-only reference.
- v.val = unsafe_New(typ)
- memmove(v.val, unsafe.Pointer(uintptr(ptr)+off), typ.size)
- v.flag |= flagIndir
- }
- in = append(in, v)
- off += typ.size
- }
-
- // Call underlying function.
- out := f(in)
- if len(out) != len(ftyp.out) {
- panic("reflect: wrong return count from function created by MakeFunc")
- }
-
- // Copy results back into argument frame.
- if len(ftyp.out) > 0 {
- off += -off & (ptrSize - 1)
- for i, arg := range ftyp.out {
- typ := arg
- v := out[i]
- if v.typ != typ {
- panic("reflect: function created by MakeFunc using " + funcName(f) +
- " returned wrong type: have " +
- out[i].typ.String() + " for " + typ.String())
- }
- if v.flag&flagRO != 0 {
- panic("reflect: function created by MakeFunc using " + funcName(f) +
- " returned value obtained from unexported field")
- }
- off += -off & uintptr(typ.align-1)
- addr := unsafe.Pointer(uintptr(ptr) + off)
- if v.flag&flagIndir == 0 {
- storeIword(addr, iword(v.val), typ.size)
- } else {
- memmove(addr, v.val, typ.size)
- }
- off += typ.size
- }
- }
-}
-
// methodReceiver returns information about the receiver
// described by v. The Value v may or may not have the
// flagMethod bit set, so the kind cached in v.flag should
@@ -628,47 +561,6 @@ func align(x, n uintptr) uintptr {
return (x + n - 1) &^ (n - 1)
}
-// frameSize returns the sizes of the argument and result frame
-// for a function of the given type. The rcvr bool specifies whether
-// a one-word receiver should be included in the total.
-func frameSize(t *rtype, rcvr bool) (total, in, outOffset, out uintptr) {
- if rcvr {
- // extra word for receiver interface word
- total += ptrSize
- }
-
- nin := t.NumIn()
- in = -total
- for i := 0; i < nin; i++ {
- tv := t.In(i)
- total = align(total, uintptr(tv.Align()))
- total += tv.Size()
- }
- in += total
- total = align(total, ptrSize)
- nout := t.NumOut()
- outOffset = total
- out = -total
- for i := 0; i < nout; i++ {
- tv := t.Out(i)
- total = align(total, uintptr(tv.Align()))
- total += tv.Size()
- }
- out += total
-
- // total must be > 0 in order for &args[0] to be valid.
- // the argument copying is going to round it up to
- // a multiple of ptrSize anyway, so make it ptrSize to begin with.
- if total < ptrSize {
- total = ptrSize
- }
-
- // round to pointer
- total = align(total, ptrSize)
-
- return
-}
-
// funcName returns the name of f, for use in error messages.
func funcName(f func([]Value) []Value) string {
pc := *(*uintptr)(unsafe.Pointer(&f))
@@ -961,10 +853,7 @@ func (v Value) CanInterface() bool {
// Interface returns v's current value as an interface{}.
// It is equivalent to:
// var i interface{} = (v's underlying value)
-// If v is a method obtained by invoking Value.Method
-// (as opposed to Type.Method), Interface cannot return an
-// interface value, so it panics.
-// It also panics if the Value was obtained by accessing
+// It panics if the Value was obtained by accessing
// unexported struct fields.
func (v Value) Interface() (i interface{}) {
return valueInterface(v, true)
@@ -1002,7 +891,8 @@ func valueInterface(v Value, safe bool) interface{} {
eface.typ = toType(v.typ).common()
eface.word = v.iword()
- if v.flag&flagIndir != 0 && v.kind() != Ptr && v.kind() != UnsafePointer {
+ // Don't need to allocate if v is not addressable or fits in one word.
+ if v.flag&flagAddr != 0 && v.kind() != Ptr && v.kind() != UnsafePointer {
// eface.word is a pointer to the actual data,
// which might be changed. We need to return
// a pointer to unchanging data, so make a copy.
@@ -1478,6 +1368,19 @@ func (v Value) SetLen(n int) {
s.Len = n
}
+// SetCap sets v's capacity to n.
+// It panics if v's Kind is not Slice or if n is smaller than the length or
+// greater than the capacity of the slice.
+func (v Value) SetCap(n int) {
+ v.mustBeAssignable()
+ v.mustBe(Slice)
+ s := (*SliceHeader)(v.val)
+ if n < int(s.Len) || n > int(s.Cap) {
+ panic("reflect: slice capacity out of range in SetCap")
+ }
+ s.Cap = n
+}
+
// SetMapIndex sets the value associated with key in the map v to val.
// It panics if v's Kind is not Map.
// If val is the zero Value, SetMapIndex deletes the key from the map.
@@ -1534,17 +1437,18 @@ func (v Value) SetString(x string) {
*(*string)(v.val) = x
}
-// Slice returns a slice of v.
-// It panics if v's Kind is not Array, Slice or String, or if v is an unaddressable array.
-func (v Value) Slice(beg, end int) Value {
+// Slice returns v[i:j].
+// It panics if v's Kind is not Array, Slice or String, or if v is an unaddressable array,
+// or if the indexes are out of bounds.
+func (v Value) Slice(i, j int) Value {
var (
cap int
typ *sliceType
base unsafe.Pointer
)
- switch k := v.kind(); k {
+ switch kind := v.kind(); kind {
default:
- panic(&ValueError{"reflect.Value.Slice", k})
+ panic(&ValueError{"reflect.Value.Slice", kind})
case Array:
if v.flag&flagAddr == 0 {
@@ -1563,17 +1467,17 @@ func (v Value) Slice(beg, end int) Value {
case String:
s := (*StringHeader)(v.val)
- if beg < 0 || end < beg || end > s.Len {
+ if i < 0 || j < i || j > s.Len {
panic("reflect.Value.Slice: string slice index out of bounds")
}
var x string
val := (*StringHeader)(unsafe.Pointer(&x))
- val.Data = s.Data + uintptr(beg)
- val.Len = end - beg
+ val.Data = s.Data + uintptr(i)
+ val.Len = j - i
return Value{v.typ, unsafe.Pointer(&x), v.flag}
}
- if beg < 0 || end < beg || end > cap {
+ if i < 0 || j < i || j > cap {
panic("reflect.Value.Slice: slice index out of bounds")
}
@@ -1582,9 +1486,56 @@ func (v Value) Slice(beg, end int) Value {
// Reinterpret as *SliceHeader to edit.
s := (*SliceHeader)(unsafe.Pointer(&x))
- s.Data = uintptr(base) + uintptr(beg)*typ.elem.Size()
- s.Len = end - beg
- s.Cap = cap - beg
+ s.Data = uintptr(base) + uintptr(i)*typ.elem.Size()
+ s.Len = j - i
+ s.Cap = cap - i
+
+ fl := v.flag&flagRO | flagIndir | flag(Slice)<<flagKindShift
+ return Value{typ.common(), unsafe.Pointer(&x), fl}
+}
+
+// Slice3 is the 3-index form of the slice operation: it returns v[i:j:k].
+// It panics if v's Kind is not Array or Slice, or if v is an unaddressable array,
+// or if the indexes are out of bounds.
+func (v Value) Slice3(i, j, k int) Value {
+ var (
+ cap int
+ typ *sliceType
+ base unsafe.Pointer
+ )
+ switch kind := v.kind(); kind {
+ default:
+ panic(&ValueError{"reflect.Value.Slice3", kind})
+
+ case Array:
+ if v.flag&flagAddr == 0 {
+ panic("reflect.Value.Slice: slice of unaddressable array")
+ }
+ tt := (*arrayType)(unsafe.Pointer(v.typ))
+ cap = int(tt.len)
+ typ = (*sliceType)(unsafe.Pointer(tt.slice))
+ base = v.val
+
+ case Slice:
+ typ = (*sliceType)(unsafe.Pointer(v.typ))
+ s := (*SliceHeader)(v.val)
+ base = unsafe.Pointer(s.Data)
+ cap = s.Cap
+ }
+
+ if i < 0 || j < i || k < j || k > cap {
+ panic("reflect.Value.Slice3: slice index out of bounds")
+ }
+
+ // Declare slice so that the garbage collector
+ // can see the base pointer in it.
+ var x []unsafe.Pointer
+
+ // Reinterpret as *SliceHeader to edit.
+ s := (*SliceHeader)(unsafe.Pointer(&x))
+ s.Data = uintptr(base) + uintptr(i)*typ.elem.Size()
+ s.Len = j - i
+ s.Cap = k - i
fl := v.flag&flagRO | flagIndir | flag(Slice)<<flagKindShift
return Value{typ.common(), unsafe.Pointer(&x), fl}
diff --git a/libgo/go/regexp/all_test.go b/libgo/go/regexp/all_test.go
index 9c4d64f582b..e914a7ccb48 100644
--- a/libgo/go/regexp/all_test.go
+++ b/libgo/go/regexp/all_test.go
@@ -308,14 +308,14 @@ func TestReplaceAllFunc(t *testing.T) {
}
actual := re.ReplaceAllStringFunc(tc.input, tc.replacement)
if actual != tc.output {
- t.Errorf("%q.ReplaceFunc(%q,%q) = %q; want %q",
- tc.pattern, tc.input, tc.replacement, actual, tc.output)
+ t.Errorf("%q.ReplaceFunc(%q,fn) = %q; want %q",
+ tc.pattern, tc.input, actual, tc.output)
}
// now try bytes
actual = string(re.ReplaceAllFunc([]byte(tc.input), func(s []byte) []byte { return []byte(tc.replacement(string(s))) }))
if actual != tc.output {
- t.Errorf("%q.ReplaceFunc(%q,%q) = %q; want %q",
- tc.pattern, tc.input, tc.replacement, actual, tc.output)
+ t.Errorf("%q.ReplaceFunc(%q,fn) = %q; want %q",
+ tc.pattern, tc.input, actual, tc.output)
}
}
}
diff --git a/libgo/go/regexp/exec2_test.go b/libgo/go/regexp/exec2_test.go
new file mode 100644
index 00000000000..7b86b41156e
--- /dev/null
+++ b/libgo/go/regexp/exec2_test.go
@@ -0,0 +1,20 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !race
+
+package regexp
+
+import (
+ "testing"
+)
+
+// This test is excluded when running under the race detector because
+// it is a very expensive test and takes too long.
+func TestRE2Exhaustive(t *testing.T) {
+ if testing.Short() {
+ t.Skip("skipping TestRE2Exhaustive during short test")
+ }
+ testRE2(t, "testdata/re2-exhaustive.txt.bz2")
+}
diff --git a/libgo/go/regexp/exec_test.go b/libgo/go/regexp/exec_test.go
index 9dfaed713f7..70d069c0611 100644
--- a/libgo/go/regexp/exec_test.go
+++ b/libgo/go/regexp/exec_test.go
@@ -9,7 +9,6 @@ import (
"compress/bzip2"
"fmt"
"io"
- "math/rand"
"os"
"path/filepath"
"regexp/syntax"
@@ -67,13 +66,6 @@ func TestRE2Search(t *testing.T) {
testRE2(t, "testdata/re2-search.txt")
}
-func TestRE2Exhaustive(t *testing.T) {
- if testing.Short() {
- t.Skip("skipping TestRE2Exhaustive during short test")
- }
- testRE2(t, "testdata/re2-exhaustive.txt.bz2")
-}
-
func testRE2(t *testing.T, file string) {
f, err := os.Open(file)
if err != nil {
@@ -650,11 +642,17 @@ func makeText(n int) []byte {
return text[:n]
}
text = make([]byte, n)
+ x := ^uint32(0)
for i := range text {
- if rand.Intn(30) == 0 {
+ x += x
+ x ^= 1
+ if int32(x) < 0 {
+ x ^= 0x88888eef
+ }
+ if x%31 == 0 {
text[i] = '\n'
} else {
- text[i] = byte(rand.Intn(0x7E+1-0x20) + 0x20)
+ text[i] = byte(x%(0x7E+1-0x20) + 0x20)
}
}
return text
@@ -691,7 +689,7 @@ func BenchmarkMatchEasy1_1K(b *testing.B) { benchmark(b, easy1, 1<<10) }
func BenchmarkMatchEasy1_32K(b *testing.B) { benchmark(b, easy1, 32<<10) }
func BenchmarkMatchEasy1_1M(b *testing.B) { benchmark(b, easy1, 1<<20) }
func BenchmarkMatchEasy1_32M(b *testing.B) { benchmark(b, easy1, 32<<20) }
-func BenchmarkMatchMedium_32(b *testing.B) { benchmark(b, medium, 1<<0) }
+func BenchmarkMatchMedium_32(b *testing.B) { benchmark(b, medium, 32<<0) }
func BenchmarkMatchMedium_1K(b *testing.B) { benchmark(b, medium, 1<<10) }
func BenchmarkMatchMedium_32K(b *testing.B) { benchmark(b, medium, 32<<10) }
func BenchmarkMatchMedium_1M(b *testing.B) { benchmark(b, medium, 1<<20) }
diff --git a/libgo/go/regexp/regexp.go b/libgo/go/regexp/regexp.go
index c392b376f1b..0046026eaeb 100644
--- a/libgo/go/regexp/regexp.go
+++ b/libgo/go/regexp/regexp.go
@@ -375,21 +375,18 @@ func (re *Regexp) LiteralPrefix() (prefix string, complete bool) {
return re.prefix, re.prefixComplete
}
-// MatchReader returns whether the Regexp matches the text read by the
-// RuneReader. The return value is a boolean: true for match, false for no
-// match.
+// MatchReader reports whether the Regexp matches the text read by the
+// RuneReader.
func (re *Regexp) MatchReader(r io.RuneReader) bool {
return re.doExecute(r, nil, "", 0, 0) != nil
}
-// MatchString returns whether the Regexp matches the string s.
-// The return value is a boolean: true for match, false for no match.
+// MatchString reports whether the Regexp matches the string s.
func (re *Regexp) MatchString(s string) bool {
return re.doExecute(nil, nil, s, 0, 0) != nil
}
-// Match returns whether the Regexp matches the byte slice b.
-// The return value is a boolean: true for match, false for no match.
+// Match reports whether the Regexp matches the byte slice b.
func (re *Regexp) Match(b []byte) bool {
return re.doExecute(nil, b, "", 0, 0) != nil
}
diff --git a/libgo/go/regexp/syntax/doc.go b/libgo/go/regexp/syntax/doc.go
index bcb5d051bc9..e52632ef726 100644
--- a/libgo/go/regexp/syntax/doc.go
+++ b/libgo/go/regexp/syntax/doc.go
@@ -64,8 +64,8 @@ Empty strings:
^ at beginning of text or line (flag m=true)
$ at end of text (like \z not \Z) or line (flag m=true)
\A at beginning of text
- \b at word boundary (\w on one side and \W, \A, or \z on the other)
- \B not a word boundary
+ \b at ASCII word boundary (\w on one side and \W, \A, or \z on the other)
+ \B not an ASCII word boundary
\z at end of text
Escape sequences:
@@ -104,8 +104,8 @@ Perl character classes:
\D not digits (== [^0-9])
\s whitespace (== [\t\n\f\r ])
\S not whitespace (== [^\t\n\f\r ])
- \w word characters (== [0-9A-Za-z_])
- \W not word characters (== [^0-9A-Za-z_])
+ \w ASCII word characters (== [0-9A-Za-z_])
+ \W not ASCII word characters (== [^0-9A-Za-z_])
ASCII character classes:
[:alnum:] alphanumeric (== [0-9A-Za-z])
diff --git a/libgo/go/regexp/syntax/parse.go b/libgo/go/regexp/syntax/parse.go
index 30e0e8b7fe4..42d0bf4a16f 100644
--- a/libgo/go/regexp/syntax/parse.go
+++ b/libgo/go/regexp/syntax/parse.go
@@ -651,7 +651,7 @@ func literalRegexp(s string, flags Flags) *Regexp {
// Parse parses a regular expression string s, controlled by the specified
// Flags, and returns a regular expression parse tree. The syntax is
-// described in the top-level comment for package regexp.
+// described in the top-level comment.
func Parse(s string, flags Flags) (*Regexp, error) {
if flags&Literal != 0 {
// Trivial parser for literal string.
diff --git a/libgo/go/regexp/syntax/parse_test.go b/libgo/go/regexp/syntax/parse_test.go
index 81fd9dc0136..269d6c3b874 100644
--- a/libgo/go/regexp/syntax/parse_test.go
+++ b/libgo/go/regexp/syntax/parse_test.go
@@ -542,7 +542,7 @@ func TestToStringEquivalentParse(t *testing.T) {
// but "{" is a shorter equivalent in some contexts.
nre, err := Parse(s, testFlags)
if err != nil {
- t.Errorf("Parse(%#q.String() = %#q): %v", tt.Regexp, t, err)
+ t.Errorf("Parse(%#q.String() = %#q): %v", tt.Regexp, s, err)
continue
}
nd := dump(nre)
diff --git a/libgo/go/regexp/syntax/prog.go b/libgo/go/regexp/syntax/prog.go
index 902d3b3a57e..a482a82f215 100644
--- a/libgo/go/regexp/syntax/prog.go
+++ b/libgo/go/regexp/syntax/prog.go
@@ -56,23 +56,26 @@ const (
// Passing r2 == -1 indicates that the position is
// at the end of the text.
func EmptyOpContext(r1, r2 rune) EmptyOp {
- var op EmptyOp
- if r1 < 0 {
- op |= EmptyBeginText | EmptyBeginLine
- }
- if r1 == '\n' {
+ var op EmptyOp = EmptyNoWordBoundary
+ var boundary byte
+ switch {
+ case IsWordChar(r1):
+ boundary = 1
+ case r1 == '\n':
op |= EmptyBeginLine
+ case r1 < 0:
+ op |= EmptyBeginText | EmptyBeginLine
}
- if r2 < 0 {
- op |= EmptyEndText | EmptyEndLine
- }
- if r2 == '\n' {
+ switch {
+ case IsWordChar(r2):
+ boundary ^= 1
+ case r2 == '\n':
op |= EmptyEndLine
+ case r2 < 0:
+ op |= EmptyEndText | EmptyEndLine
}
- if IsWordChar(r1) != IsWordChar(r2) {
- op |= EmptyWordBoundary
- } else {
- op |= EmptyNoWordBoundary
+ if boundary != 0 { // IsWordChar(r1) != IsWordChar(r2)
+ op ^= (EmptyWordBoundary | EmptyNoWordBoundary)
}
return op
}
diff --git a/libgo/go/regexp/syntax/prog_test.go b/libgo/go/regexp/syntax/prog_test.go
index 663d5a8d778..cd71abc2a47 100644
--- a/libgo/go/regexp/syntax/prog_test.go
+++ b/libgo/go/regexp/syntax/prog_test.go
@@ -103,3 +103,14 @@ func TestCompile(t *testing.T) {
}
}
}
+
+func BenchmarkEmptyOpContext(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ var r1 rune = -1
+ for _, r2 := range "foo, bar, baz\nsome input text.\n" {
+ EmptyOpContext(r1, r2)
+ r1 = r2
+ }
+ EmptyOpContext(r1, -1)
+ }
+}
diff --git a/libgo/go/runtime/append_test.go b/libgo/go/runtime/append_test.go
index 36390181e87..937c8259fdd 100644
--- a/libgo/go/runtime/append_test.go
+++ b/libgo/go/runtime/append_test.go
@@ -38,10 +38,18 @@ func BenchmarkAppend4Bytes(b *testing.B) {
benchmarkAppendBytes(b, 4)
}
+func BenchmarkAppend7Bytes(b *testing.B) {
+ benchmarkAppendBytes(b, 7)
+}
+
func BenchmarkAppend8Bytes(b *testing.B) {
benchmarkAppendBytes(b, 8)
}
+func BenchmarkAppend15Bytes(b *testing.B) {
+ benchmarkAppendBytes(b, 15)
+}
+
func BenchmarkAppend16Bytes(b *testing.B) {
benchmarkAppendBytes(b, 16)
}
@@ -121,3 +129,43 @@ func TestAppendOverlap(t *testing.T) {
t.Errorf("overlap failed: got %q want %q", got, want)
}
}
+
+func benchmarkCopySlice(b *testing.B, l int) {
+ s := make([]byte, l)
+ buf := make([]byte, 4096)
+ var n int
+ for i := 0; i < b.N; i++ {
+ n = copy(buf, s)
+ }
+ b.SetBytes(int64(n))
+}
+
+func benchmarkCopyStr(b *testing.B, l int) {
+ s := string(make([]byte, l))
+ buf := make([]byte, 4096)
+ var n int
+ for i := 0; i < b.N; i++ {
+ n = copy(buf, s)
+ }
+ b.SetBytes(int64(n))
+}
+
+func BenchmarkCopy1Byte(b *testing.B) { benchmarkCopySlice(b, 1) }
+func BenchmarkCopy2Byte(b *testing.B) { benchmarkCopySlice(b, 2) }
+func BenchmarkCopy4Byte(b *testing.B) { benchmarkCopySlice(b, 4) }
+func BenchmarkCopy8Byte(b *testing.B) { benchmarkCopySlice(b, 8) }
+func BenchmarkCopy12Byte(b *testing.B) { benchmarkCopySlice(b, 12) }
+func BenchmarkCopy16Byte(b *testing.B) { benchmarkCopySlice(b, 16) }
+func BenchmarkCopy32Byte(b *testing.B) { benchmarkCopySlice(b, 32) }
+func BenchmarkCopy128Byte(b *testing.B) { benchmarkCopySlice(b, 128) }
+func BenchmarkCopy1024Byte(b *testing.B) { benchmarkCopySlice(b, 1024) }
+
+func BenchmarkCopy1String(b *testing.B) { benchmarkCopyStr(b, 1) }
+func BenchmarkCopy2String(b *testing.B) { benchmarkCopyStr(b, 2) }
+func BenchmarkCopy4String(b *testing.B) { benchmarkCopyStr(b, 4) }
+func BenchmarkCopy8String(b *testing.B) { benchmarkCopyStr(b, 8) }
+func BenchmarkCopy12String(b *testing.B) { benchmarkCopyStr(b, 12) }
+func BenchmarkCopy16String(b *testing.B) { benchmarkCopyStr(b, 16) }
+func BenchmarkCopy32String(b *testing.B) { benchmarkCopyStr(b, 32) }
+func BenchmarkCopy128String(b *testing.B) { benchmarkCopyStr(b, 128) }
+func BenchmarkCopy1024String(b *testing.B) { benchmarkCopyStr(b, 1024) }
diff --git a/libgo/go/runtime/crash_cgo_test.go b/libgo/go/runtime/crash_cgo_test.go
index 6b93bd199bf..b534b89e559 100644
--- a/libgo/go/runtime/crash_cgo_test.go
+++ b/libgo/go/runtime/crash_cgo_test.go
@@ -7,6 +7,7 @@
package runtime_test
import (
+ "runtime"
"testing"
)
@@ -15,13 +16,23 @@ func TestCgoCrashHandler(t *testing.T) {
}
func TestCgoSignalDeadlock(t *testing.T) {
- /* gccgo does not have a go command
+ if testing.Short() && runtime.GOOS == "windows" {
+ t.Skip("Skipping in short mode") // takes up to 64 seconds
+ }
+ t.Skip("gccgo does not have a go command")
got := executeTest(t, cgoSignalDeadlockSource, nil)
want := "OK\n"
if got != want {
t.Fatalf("expected %q, but got %q", want, got)
}
- */
+}
+
+func TestCgoTraceback(t *testing.T) {
+ got := executeTest(t, cgoTracebackSource, nil)
+ want := "OK\n"
+ if got != want {
+ t.Fatalf("expected %q, but got %q", want, got)
+ }
}
const cgoSignalDeadlockSource = `
@@ -88,3 +99,22 @@ func main() {
fmt.Printf("OK\n")
}
`
+
+const cgoTracebackSource = `
+package main
+
+/* void foo(void) {} */
+import "C"
+
+import (
+ "fmt"
+ "runtime"
+)
+
+func main() {
+ C.foo()
+ buf := make([]byte, 1)
+ runtime.Stack(buf, true)
+ fmt.Printf("OK\n")
+}
+`
diff --git a/libgo/go/runtime/crash_test.go b/libgo/go/runtime/crash_test.go
index 918249afc75..d8bfdbdad6d 100644
--- a/libgo/go/runtime/crash_test.go
+++ b/libgo/go/runtime/crash_test.go
@@ -14,7 +14,7 @@ import (
"text/template"
)
-// testEnv excludes GOGCTRACE from the environment
+// testEnv excludes GODEBUG from the environment
// to prevent its output from breaking tests that
// are trying to parse other command output.
func testEnv(cmd *exec.Cmd) *exec.Cmd {
@@ -22,7 +22,7 @@ func testEnv(cmd *exec.Cmd) *exec.Cmd {
panic("environment already set")
}
for _, env := range os.Environ() {
- if strings.HasPrefix(env, "GOGCTRACE=") {
+ if strings.HasPrefix(env, "GODEBUG=") {
continue
}
cmd.Env = append(cmd.Env, env)
@@ -31,6 +31,7 @@ func testEnv(cmd *exec.Cmd) *exec.Cmd {
}
func executeTest(t *testing.T, templ string, data interface{}) string {
+ t.Skip("gccgo does not have a go command")
checkStaleRuntime(t)
st := template.Must(template.New("crashSource").Parse(templ))
@@ -44,14 +45,16 @@ func executeTest(t *testing.T, templ string, data interface{}) string {
src := filepath.Join(dir, "main.go")
f, err := os.Create(src)
if err != nil {
- t.Fatalf("failed to create %v: %v", src, err)
+ t.Fatalf("failed to create file: %v", err)
}
err = st.Execute(f, data)
if err != nil {
f.Close()
t.Fatalf("failed to execute template: %v", err)
}
- f.Close()
+ if err := f.Close(); err != nil {
+ t.Fatalf("failed to close file: %v", err)
+ }
got, _ := testEnv(exec.Command("go", "run", src)).CombinedOutput()
return string(got)
@@ -69,16 +72,14 @@ func checkStaleRuntime(t *testing.T) {
}
func testCrashHandler(t *testing.T, cgo bool) {
- /* gccgo does not have a go command
type crashTest struct {
Cgo bool
}
- got := executeTest(t, crashSource, &crashTest{Cgo: cgo})
+ output := executeTest(t, crashSource, &crashTest{Cgo: cgo})
want := "main: recovered done\nnew-thread: recovered done\nsecond-new-thread: recovered done\nmain-again: recovered done\n"
- if got != want {
- t.Fatalf("expected %q, but got %q", want, got)
+ if output != want {
+ t.Fatalf("output:\n%s\n\nwanted:\n%s", output, want)
}
- */
}
func TestCrashHandler(t *testing.T) {
@@ -86,13 +87,11 @@ func TestCrashHandler(t *testing.T) {
}
func testDeadlock(t *testing.T, source string) {
- /* gccgo does not have a go command.
- got := executeTest(t, source, nil)
+ output := executeTest(t, source, nil)
want := "fatal error: all goroutines are asleep - deadlock!\n"
- if !strings.HasPrefix(got, want) {
- t.Fatalf("expected %q, but got %q", want, got)
+ if !strings.HasPrefix(output, want) {
+ t.Fatalf("output does not start with %q:\n%s", want, output)
}
- */
}
func TestSimpleDeadlock(t *testing.T) {
@@ -112,13 +111,26 @@ func TestLockedDeadlock2(t *testing.T) {
}
func TestGoexitDeadlock(t *testing.T) {
- /* gccgo does not have a go command
- got := executeTest(t, goexitDeadlockSource, nil)
- want := ""
- if got != want {
- t.Fatalf("expected %q, but got %q", want, got)
+ output := executeTest(t, goexitDeadlockSource, nil)
+ if output != "" {
+ t.Fatalf("expected no output, got:\n%s", output)
+ }
+}
+
+func TestStackOverflow(t *testing.T) {
+ output := executeTest(t, stackOverflowSource, nil)
+ want := "runtime: goroutine stack exceeds 4194304-byte limit\nfatal error: stack overflow"
+ if !strings.HasPrefix(output, want) {
+ t.Fatalf("output does not start with %q:\n%s", want, output)
+ }
+}
+
+func TestThreadExhaustion(t *testing.T) {
+ output := executeTest(t, threadExhaustionSource, nil)
+ want := "runtime: program exceeds 10-thread limit\nfatal error: thread exhaustion"
+ if !strings.HasPrefix(output, want) {
+ t.Fatalf("output does not start with %q:\n%s", want, output)
}
- */
}
const crashSource = `
@@ -223,3 +235,41 @@ func main() {
runtime.Goexit()
}
`
+
+const stackOverflowSource = `
+package main
+
+import "runtime/debug"
+
+func main() {
+ debug.SetMaxStack(4<<20)
+ f(make([]byte, 10))
+}
+
+func f(x []byte) byte {
+ var buf [64<<10]byte
+ return x[0] + f(buf[:])
+}
+`
+
+const threadExhaustionSource = `
+package main
+
+import (
+ "runtime"
+ "runtime/debug"
+)
+
+func main() {
+ debug.SetMaxThreads(10)
+ c := make(chan int)
+ for i := 0; i < 100; i++ {
+ go func() {
+ runtime.LockOSThread()
+ c <- 0
+ select{}
+ }()
+ <-c
+ }
+}
+`
diff --git a/libgo/go/runtime/debug/garbage.go b/libgo/go/runtime/debug/garbage.go
index 8f30264264f..8337d5d5b34 100644
--- a/libgo/go/runtime/debug/garbage.go
+++ b/libgo/go/runtime/debug/garbage.go
@@ -24,6 +24,8 @@ func readGCStats(*[]time.Duration)
func enableGC(bool) bool
func setGCPercent(int) int
func freeOSMemory()
+func setMaxStack(int) int
+func setMaxThreads(int) int
// ReadGCStats reads statistics about garbage collection into stats.
// The number of entries in the pause history is system-dependent;
@@ -99,3 +101,35 @@ func SetGCPercent(percent int) int {
func FreeOSMemory() {
freeOSMemory()
}
+
+// SetMaxStack sets the maximum amount of memory that
+// can be used by a single goroutine stack.
+// If any goroutine exceeds this limit while growing its stack,
+// the program crashes.
+// SetMaxStack returns the previous setting.
+// The initial setting is 1 GB on 64-bit systems, 250 MB on 32-bit systems.
+//
+// SetMaxStack is useful mainly for limiting the damage done by
+// goroutines that enter an infinite recursion. It only limits future
+// stack growth.
+func SetMaxStack(bytes int) int {
+ return setMaxStack(bytes)
+}
+
+// SetMaxThreads sets the maximum number of operating system
+// threads that the Go program can use. If it attempts to use more than
+// this many, the program crashes.
+// SetMaxThreads returns the previous setting.
+// The initial setting is 10,000 threads.
+//
+// The limit controls the number of operating system threads, not the number
+// of goroutines. A Go program creates a new thread only when a goroutine
+// is ready to run but all the existing threads are blocked in system calls, cgo calls,
+// or are locked to other goroutines due to use of runtime.LockOSThread.
+//
+// SetMaxThreads is useful mainly for limiting the damage done by
+// programs that create an unbounded number of threads. The idea is
+// to take down the program before it takes down the operating system.
+func SetMaxThreads(threads int) int {
+ return setMaxThreads(threads)
+}
diff --git a/libgo/go/runtime/debug/stack_test.go b/libgo/go/runtime/debug/stack_test.go
index bbd662618fd..263d7155997 100644
--- a/libgo/go/runtime/debug/stack_test.go
+++ b/libgo/go/runtime/debug/stack_test.go
@@ -49,10 +49,10 @@ func TestStack(t *testing.T) {
n++
}
}
- frame("src/pkg/runtime/debug/stack_test.go", "\t(*T).ptrmethod: return Stack()")
- frame("src/pkg/runtime/debug/stack_test.go", "\tT.method: return t.ptrmethod()")
- frame("src/pkg/runtime/debug/stack_test.go", "\tTestStack: b := T(0).method()")
- frame("src/pkg/testing/testing.go", "")
+ frame("stack_test.go", "\tmethod.N15_runtime_debug.T: return Stack()")
+ frame("stack_test.go", "\tmethod.N15_runtime_debug.T: return t.ptrmethod()")
+ frame("stack_test.go", "\tTestStack: b := T(0).method()")
+ frame("testing/testing.go", "")
}
func check(t *testing.T, line, has string) {
diff --git a/libgo/go/runtime/error.go b/libgo/go/runtime/error.go
index f7f81e95d3e..88d5df5e415 100644
--- a/libgo/go/runtime/error.go
+++ b/libgo/go/runtime/error.go
@@ -106,6 +106,22 @@ func NewErrorString(s string, ret *interface{}) {
*ret = errorString(s)
}
+// An errorCString represents a runtime error described by a single C string.
+type errorCString uintptr
+
+func (e errorCString) RuntimeError() {}
+
+func cstringToGo(uintptr) string
+
+func (e errorCString) Error() string {
+ return "runtime error: " + cstringToGo(uintptr(e))
+}
+
+// For calling from C.
+func NewErrorCString(s uintptr, ret *interface{}) {
+ *ret = errorCString(s)
+}
+
type stringer interface {
String() string
}
diff --git a/libgo/go/runtime/export_test.go b/libgo/go/runtime/export_test.go
index e22fa62c46c..2f678b6bc9c 100644
--- a/libgo/go/runtime/export_test.go
+++ b/libgo/go/runtime/export_test.go
@@ -65,3 +65,20 @@ func testSchedLocalQueueSteal()
var TestSchedLocalQueue1 = testSchedLocalQueue
var TestSchedLocalQueueSteal1 = testSchedLocalQueueSteal
+
+// func haveGoodHash() bool
+// func stringHash(s string, seed uintptr) uintptr
+// func bytesHash(b []byte, seed uintptr) uintptr
+// func int32Hash(i uint32, seed uintptr) uintptr
+// func int64Hash(i uint64, seed uintptr) uintptr
+
+// var HaveGoodHash = haveGoodHash
+// var StringHash = stringHash
+// var BytesHash = bytesHash
+// var Int32Hash = int32Hash
+// var Int64Hash = int64Hash
+
+// func GogoBytes() int32
+
+var hashLoad float64 // declared in hashmap.c
+var HashLoad = &hashLoad
diff --git a/libgo/go/runtime/extern.go b/libgo/go/runtime/extern.go
index 72e1a0a3b76..527e9cdf89c 100644
--- a/libgo/go/runtime/extern.go
+++ b/libgo/go/runtime/extern.go
@@ -21,11 +21,20 @@ is GOGC=100. Setting GOGC=off disables the garbage collector entirely.
The runtime/debug package's SetGCPercent function allows changing this
percentage at run time. See http://golang.org/pkg/runtime/debug/#SetGCPercent.
-The GOGCTRACE variable controls debug output from the garbage collector.
-Setting GOGCTRACE=1 causes the garbage collector to emit a single line to standard
-error at each collection, summarizing the amount of memory collected and the
-length of the pause. Setting GOGCTRACE=2 emits the same summary but also
-repeats each collection.
+The GODEBUG variable controls debug output from the runtime. GODEBUG value is
+a comma-separated list of name=val pairs. Supported names are:
+
+ gctrace: setting gctrace=1 causes the garbage collector to emit a single line to standard
+ error at each collection, summarizing the amount of memory collected and the
+ length of the pause. Setting gctrace=2 emits the same summary but also
+ repeats each collection.
+
+ schedtrace: setting schedtrace=X causes the scheduler to emit a single line to standard
+ error every X milliseconds, summarizing the scheduler state.
+
+ scheddetail: setting schedtrace=X and scheddetail=1 causes the scheduler to emit
+ detailed multiline info every X milliseconds, describing state of the scheduler,
+ processors, threads and goroutines.
The GOMAXPROCS variable limits the number of operating system threads that
can execute user-level Go code simultaneously. There is no limit to the number of threads
@@ -77,9 +86,8 @@ func Caller(skip int) (pc uintptr, file string, line int, ok bool)
// It returns the number of entries written to pc.
func Callers(skip int, pc []uintptr) int
-type Func struct { // Keep in sync with runtime.h:struct Func
- name string
- entry uintptr // entry pc
+type Func struct {
+ opaque struct{} // unexported field to disallow conversions
}
// FuncForPC returns a *Func describing the function that contains the
@@ -87,10 +95,14 @@ type Func struct { // Keep in sync with runtime.h:struct Func
func FuncForPC(pc uintptr) *Func
// Name returns the name of the function.
-func (f *Func) Name() string { return f.name }
+func (f *Func) Name() string {
+ return funcname_go(f)
+}
// Entry returns the entry address of the function.
-func (f *Func) Entry() uintptr { return f.entry }
+func (f *Func) Entry() uintptr {
+ return funcentry_go(f)
+}
// FileLine returns the file name and line number of the
// source code corresponding to the program counter pc.
@@ -102,6 +114,8 @@ func (f *Func) FileLine(pc uintptr) (file string, line int) {
// implemented in symtab.c
func funcline_go(*Func, uintptr) (string, int)
+func funcname_go(*Func) string
+func funcentry_go(*Func) uintptr
// SetFinalizer sets the finalizer associated with x to f.
// When the garbage collector finds an unreachable block
@@ -116,8 +130,9 @@ func funcline_go(*Func, uintptr) (string, int)
// The argument x must be a pointer to an object allocated by
// calling new or by taking the address of a composite literal.
// The argument f must be a function that takes a single argument
-// of x's type and can have arbitrary ignored return values.
-// If either of these is not true, SetFinalizer aborts the program.
+// to which x's type can be assigned, and can have arbitrary ignored return
+// values. If either of these is not true, SetFinalizer aborts the
+// program.
//
// Finalizers are run in dependency order: if A points at B, both have
// finalizers, and they are otherwise unreachable, only the finalizer
diff --git a/libgo/go/runtime/gc_test.go b/libgo/go/runtime/gc_test.go
index 05ee34869cc..1b3ccbf7d93 100644
--- a/libgo/go/runtime/gc_test.go
+++ b/libgo/go/runtime/gc_test.go
@@ -138,7 +138,9 @@ func TestGcRescan(t *testing.T) {
for i := 0; i < 10; i++ {
p := &Y{}
p.c = make(chan error)
- p.nextx = &head.X
+ if head != nil {
+ p.nextx = &head.X
+ }
p.nexty = head
p.p = new(int)
*p.p = 42
diff --git a/libgo/go/runtime/malloc_test.go b/libgo/go/runtime/malloc_test.go
new file mode 100644
index 00000000000..054f6a7d744
--- /dev/null
+++ b/libgo/go/runtime/malloc_test.go
@@ -0,0 +1,156 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime_test
+
+import (
+ "flag"
+ . "runtime"
+ "testing"
+ "time"
+ "unsafe"
+)
+
+func TestMemStats(t *testing.T) {
+ // Test that MemStats has sane values.
+ st := new(MemStats)
+ ReadMemStats(st)
+ if st.HeapSys == 0 || /* st.StackSys == 0 || */ st.MSpanSys == 0 || st.MCacheSys == 0 ||
+ st.BuckHashSys == 0 || st.GCSys == 0 || st.OtherSys == 0 {
+ t.Fatalf("Zero sys value: %+v", *st)
+ }
+ if st.Sys != st.HeapSys+st.StackSys+st.MSpanSys+st.MCacheSys+
+ st.BuckHashSys+st.GCSys+st.OtherSys {
+ t.Fatalf("Bad sys value: %+v", *st)
+ }
+}
+
+var mallocSink uintptr
+
+func BenchmarkMalloc8(b *testing.B) {
+ var x uintptr
+ for i := 0; i < b.N; i++ {
+ p := new(int64)
+ x ^= uintptr(unsafe.Pointer(p))
+ }
+ mallocSink = x
+}
+
+func BenchmarkMalloc16(b *testing.B) {
+ var x uintptr
+ for i := 0; i < b.N; i++ {
+ p := new([2]int64)
+ x ^= uintptr(unsafe.Pointer(p))
+ }
+ mallocSink = x
+}
+
+func BenchmarkMallocTypeInfo8(b *testing.B) {
+ var x uintptr
+ for i := 0; i < b.N; i++ {
+ p := new(struct {
+ p [8 / unsafe.Sizeof(uintptr(0))]*int
+ })
+ x ^= uintptr(unsafe.Pointer(p))
+ }
+ mallocSink = x
+}
+
+func BenchmarkMallocTypeInfo16(b *testing.B) {
+ var x uintptr
+ for i := 0; i < b.N; i++ {
+ p := new(struct {
+ p [16 / unsafe.Sizeof(uintptr(0))]*int
+ })
+ x ^= uintptr(unsafe.Pointer(p))
+ }
+ mallocSink = x
+}
+
+var n = flag.Int("n", 1000, "number of goroutines")
+
+func BenchmarkGoroutineSelect(b *testing.B) {
+ quit := make(chan struct{})
+ read := func(ch chan struct{}) {
+ for {
+ select {
+ case _, ok := <-ch:
+ if !ok {
+ return
+ }
+ case <-quit:
+ return
+ }
+ }
+ }
+ benchHelper(b, *n, read)
+}
+
+func BenchmarkGoroutineBlocking(b *testing.B) {
+ read := func(ch chan struct{}) {
+ for {
+ if _, ok := <-ch; !ok {
+ return
+ }
+ }
+ }
+ benchHelper(b, *n, read)
+}
+
+func BenchmarkGoroutineForRange(b *testing.B) {
+ read := func(ch chan struct{}) {
+ for _ = range ch {
+ }
+ }
+ benchHelper(b, *n, read)
+}
+
+func benchHelper(b *testing.B, n int, read func(chan struct{})) {
+ m := make([]chan struct{}, n)
+ for i := range m {
+ m[i] = make(chan struct{}, 1)
+ go read(m[i])
+ }
+ b.StopTimer()
+ b.ResetTimer()
+ GC()
+
+ for i := 0; i < b.N; i++ {
+ for _, ch := range m {
+ if ch != nil {
+ ch <- struct{}{}
+ }
+ }
+ time.Sleep(10 * time.Millisecond)
+ b.StartTimer()
+ GC()
+ b.StopTimer()
+ }
+
+ for _, ch := range m {
+ close(ch)
+ }
+ time.Sleep(10 * time.Millisecond)
+}
+
+func BenchmarkGoroutineIdle(b *testing.B) {
+ quit := make(chan struct{})
+ fn := func() {
+ <-quit
+ }
+ for i := 0; i < *n; i++ {
+ go fn()
+ }
+
+ GC()
+ b.ResetTimer()
+
+ for i := 0; i < b.N; i++ {
+ GC()
+ }
+
+ b.StopTimer()
+ close(quit)
+ time.Sleep(10 * time.Millisecond)
+}
diff --git a/libgo/go/runtime/map_test.go b/libgo/go/runtime/map_test.go
index 535c59e5f34..c53066aea6a 100644
--- a/libgo/go/runtime/map_test.go
+++ b/libgo/go/runtime/map_test.go
@@ -378,3 +378,41 @@ func testMapLookups(t *testing.T, m map[string]string) {
}
}
}
+
+// Tests whether the iterator returns the right elements when
+// started in the middle of a grow, when the keys are NaNs.
+func TestMapNanGrowIterator(t *testing.T) {
+ m := make(map[float64]int)
+ nan := math.NaN()
+ const nBuckets = 16
+ // To fill nBuckets buckets takes LOAD * nBuckets keys.
+ nKeys := int(nBuckets * *runtime.HashLoad)
+
+ // Get map to full point with nan keys.
+ for i := 0; i < nKeys; i++ {
+ m[nan] = i
+ }
+ // Trigger grow
+ m[1.0] = 1
+ delete(m, 1.0)
+
+ // Run iterator
+ found := make(map[int]struct{})
+ for _, v := range m {
+ if v != -1 {
+ if _, repeat := found[v]; repeat {
+ t.Fatalf("repeat of value %d", v)
+ }
+ found[v] = struct{}{}
+ }
+ if len(found) == nKeys/2 {
+ // Halfway through iteration, finish grow.
+ for i := 0; i < nBuckets; i++ {
+ delete(m, 1.0)
+ }
+ }
+ }
+ if len(found) != nKeys {
+ t.Fatalf("missing value")
+ }
+}
diff --git a/libgo/go/runtime/mapspeed_test.go b/libgo/go/runtime/mapspeed_test.go
index 3b7fbfd638b..d643d98985f 100644
--- a/libgo/go/runtime/mapspeed_test.go
+++ b/libgo/go/runtime/mapspeed_test.go
@@ -32,6 +32,33 @@ func BenchmarkHashStringSpeed(b *testing.B) {
}
}
+type chunk [17]byte
+
+func BenchmarkHashBytesSpeed(b *testing.B) {
+ // a bunch of chunks, each with a different alignment mod 16
+ var chunks [size]chunk
+ // initialize each to a different value
+ for i := 0; i < size; i++ {
+ chunks[i][0] = byte(i)
+ }
+ // put into a map
+ m := make(map[chunk]int, size)
+ for i, c := range chunks {
+ m[c] = i
+ }
+ idx := 0
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ if m[chunks[idx]] != idx {
+ b.Error("bad map entry for chunk")
+ }
+ idx++
+ if idx == size {
+ idx = 0
+ }
+ }
+}
+
func BenchmarkHashInt32Speed(b *testing.B) {
ints := make([]int32, size)
for i := 0; i < size; i++ {
@@ -206,3 +233,38 @@ func BenchmarkNewEmptyMap(b *testing.B) {
_ = make(map[int]int)
}
}
+
+func BenchmarkMapIter(b *testing.B) {
+ m := make(map[int]bool)
+ for i := 0; i < 8; i++ {
+ m[i] = true
+ }
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ for _, _ = range m {
+ }
+ }
+}
+
+func BenchmarkMapIterEmpty(b *testing.B) {
+ m := make(map[int]bool)
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ for _, _ = range m {
+ }
+ }
+}
+
+func BenchmarkSameLengthMap(b *testing.B) {
+ // long strings, same length, differ in first few
+ // and last few bytes.
+ m := make(map[string]bool)
+ s1 := "foo" + strings.Repeat("-", 100) + "bar"
+ s2 := "goo" + strings.Repeat("-", 100) + "ber"
+ m[s1] = true
+ m[s2] = true
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _ = m[s1]
+ }
+}
diff --git a/libgo/go/runtime/mem.go b/libgo/go/runtime/mem.go
index fd423c82fdf..ba6d1cf6ab9 100644
--- a/libgo/go/runtime/mem.go
+++ b/libgo/go/runtime/mem.go
@@ -14,7 +14,7 @@ type MemStats struct {
// General statistics.
Alloc uint64 // bytes allocated and still in use
TotalAlloc uint64 // bytes allocated (even if freed)
- Sys uint64 // bytes obtained from system (should be sum of XxxSys below)
+ Sys uint64 // bytes obtained from system (sum of XxxSys below)
Lookups uint64 // number of pointer lookups
Mallocs uint64 // number of mallocs
Frees uint64 // number of frees
@@ -37,6 +37,8 @@ type MemStats struct {
MCacheInuse uint64 // mcache structures
MCacheSys uint64
BuckHashSys uint64 // profiling bucket hash table
+ GCSys uint64 // GC metadata
+ OtherSys uint64 // other system allocations
// Garbage collector statistics.
NextGC uint64 // next run in HeapAlloc time (bytes)
diff --git a/libgo/go/runtime/memmove_test.go b/libgo/go/runtime/memmove_test.go
new file mode 100644
index 00000000000..9525f06826e
--- /dev/null
+++ b/libgo/go/runtime/memmove_test.go
@@ -0,0 +1,116 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime_test
+
+import (
+ "testing"
+)
+
+func TestMemmove(t *testing.T) {
+ size := 256
+ if testing.Short() {
+ size = 128 + 16
+ }
+ src := make([]byte, size)
+ dst := make([]byte, size)
+ for i := 0; i < size; i++ {
+ src[i] = byte(128 + (i & 127))
+ }
+ for i := 0; i < size; i++ {
+ dst[i] = byte(i & 127)
+ }
+ for n := 0; n <= size; n++ {
+ for x := 0; x <= size-n; x++ { // offset in src
+ for y := 0; y <= size-n; y++ { // offset in dst
+ copy(dst[y:y+n], src[x:x+n])
+ for i := 0; i < y; i++ {
+ if dst[i] != byte(i&127) {
+ t.Fatalf("prefix dst[%d] = %d", i, dst[i])
+ }
+ }
+ for i := y; i < y+n; i++ {
+ if dst[i] != byte(128+((i-y+x)&127)) {
+ t.Fatalf("copied dst[%d] = %d", i, dst[i])
+ }
+ dst[i] = byte(i & 127) // reset dst
+ }
+ for i := y + n; i < size; i++ {
+ if dst[i] != byte(i&127) {
+ t.Fatalf("suffix dst[%d] = %d", i, dst[i])
+ }
+ }
+ }
+ }
+ }
+}
+
+func TestMemmoveAlias(t *testing.T) {
+ size := 256
+ if testing.Short() {
+ size = 128 + 16
+ }
+ buf := make([]byte, size)
+ for i := 0; i < size; i++ {
+ buf[i] = byte(i)
+ }
+ for n := 0; n <= size; n++ {
+ for x := 0; x <= size-n; x++ { // src offset
+ for y := 0; y <= size-n; y++ { // dst offset
+ copy(buf[y:y+n], buf[x:x+n])
+ for i := 0; i < y; i++ {
+ if buf[i] != byte(i) {
+ t.Fatalf("prefix buf[%d] = %d", i, buf[i])
+ }
+ }
+ for i := y; i < y+n; i++ {
+ if buf[i] != byte(i-y+x) {
+ t.Fatalf("copied buf[%d] = %d", i, buf[i])
+ }
+ buf[i] = byte(i) // reset buf
+ }
+ for i := y + n; i < size; i++ {
+ if buf[i] != byte(i) {
+ t.Fatalf("suffix buf[%d] = %d", i, buf[i])
+ }
+ }
+ }
+ }
+ }
+}
+
+func bmMemmove(n int, b *testing.B) {
+ x := make([]byte, n)
+ y := make([]byte, n)
+ b.SetBytes(int64(n))
+ for i := 0; i < b.N; i++ {
+ copy(x, y)
+ }
+}
+
+func BenchmarkMemmove0(b *testing.B) { bmMemmove(0, b) }
+func BenchmarkMemmove1(b *testing.B) { bmMemmove(1, b) }
+func BenchmarkMemmove2(b *testing.B) { bmMemmove(2, b) }
+func BenchmarkMemmove3(b *testing.B) { bmMemmove(3, b) }
+func BenchmarkMemmove4(b *testing.B) { bmMemmove(4, b) }
+func BenchmarkMemmove5(b *testing.B) { bmMemmove(5, b) }
+func BenchmarkMemmove6(b *testing.B) { bmMemmove(6, b) }
+func BenchmarkMemmove7(b *testing.B) { bmMemmove(7, b) }
+func BenchmarkMemmove8(b *testing.B) { bmMemmove(8, b) }
+func BenchmarkMemmove9(b *testing.B) { bmMemmove(9, b) }
+func BenchmarkMemmove10(b *testing.B) { bmMemmove(10, b) }
+func BenchmarkMemmove11(b *testing.B) { bmMemmove(11, b) }
+func BenchmarkMemmove12(b *testing.B) { bmMemmove(12, b) }
+func BenchmarkMemmove13(b *testing.B) { bmMemmove(13, b) }
+func BenchmarkMemmove14(b *testing.B) { bmMemmove(14, b) }
+func BenchmarkMemmove15(b *testing.B) { bmMemmove(15, b) }
+func BenchmarkMemmove16(b *testing.B) { bmMemmove(16, b) }
+func BenchmarkMemmove32(b *testing.B) { bmMemmove(32, b) }
+func BenchmarkMemmove64(b *testing.B) { bmMemmove(64, b) }
+func BenchmarkMemmove128(b *testing.B) { bmMemmove(128, b) }
+func BenchmarkMemmove256(b *testing.B) { bmMemmove(256, b) }
+func BenchmarkMemmove512(b *testing.B) { bmMemmove(512, b) }
+func BenchmarkMemmove1024(b *testing.B) { bmMemmove(1024, b) }
+func BenchmarkMemmove2048(b *testing.B) { bmMemmove(2048, b) }
+func BenchmarkMemmove4096(b *testing.B) { bmMemmove(4096, b) }
diff --git a/libgo/go/runtime/mfinal_test.go b/libgo/go/runtime/mfinal_test.go
index de632717a57..6efef9bb034 100644
--- a/libgo/go/runtime/mfinal_test.go
+++ b/libgo/go/runtime/mfinal_test.go
@@ -9,8 +9,94 @@ import (
"sync"
"sync/atomic"
"testing"
+ "time"
)
+type Tintptr *int // assignable to *int
+type Tint int // *Tint implements Tinter, interface{}
+
+func (t *Tint) m() {}
+
+type Tinter interface {
+ m()
+}
+
+func TestFinalizerType(t *testing.T) {
+ if runtime.GOARCH != "amd64" {
+ t.Skipf("Skipping on non-amd64 machine")
+ }
+
+ ch := make(chan bool, 10)
+ finalize := func(x *int) {
+ if *x != 97531 {
+ t.Errorf("finalizer %d, want %d", *x, 97531)
+ }
+ ch <- true
+ }
+
+ var finalizerTests = []struct {
+ convert func(*int) interface{}
+ finalizer interface{}
+ }{
+ {func(x *int) interface{} { return x }, func(v *int) { finalize(v) }},
+ {func(x *int) interface{} { return Tintptr(x) }, func(v Tintptr) { finalize(v) }},
+ {func(x *int) interface{} { return Tintptr(x) }, func(v *int) { finalize(v) }},
+ {func(x *int) interface{} { return (*Tint)(x) }, func(v *Tint) { finalize((*int)(v)) }},
+ {func(x *int) interface{} { return (*Tint)(x) }, func(v Tinter) { finalize((*int)(v.(*Tint))) }},
+ }
+
+ for _, tt := range finalizerTests {
+ go func() {
+ v := new(int)
+ *v = 97531
+ runtime.SetFinalizer(tt.convert(v), tt.finalizer)
+ v = nil
+ }()
+ time.Sleep(1 * time.Second)
+ runtime.GC()
+ select {
+ case <-ch:
+ case <-time.After(time.Second * 4):
+ t.Errorf("finalizer for type %T didn't run", tt.finalizer)
+ }
+ }
+}
+
+type bigValue struct {
+ fill uint64
+ it bool
+ up string
+}
+
+func TestFinalizerInterfaceBig(t *testing.T) {
+ if runtime.GOARCH != "amd64" {
+ t.Skipf("Skipping on non-amd64 machine")
+ }
+ ch := make(chan bool)
+ go func() {
+ v := &bigValue{0xDEADBEEFDEADBEEF, true, "It matters not how strait the gate"}
+ old := *v
+ runtime.SetFinalizer(v, func(v interface{}) {
+ i, ok := v.(*bigValue)
+ if !ok {
+ t.Errorf("finalizer called with type %T, want *bigValue", v)
+ }
+ if *i != old {
+ t.Errorf("finalizer called with %+v, want %+v", *i, old)
+ }
+ close(ch)
+ })
+ v = nil
+ }()
+ time.Sleep(1 * time.Second)
+ runtime.GC()
+ select {
+ case <-ch:
+ case <-time.After(4 * time.Second):
+ t.Errorf("finalizer for type *bigValue didn't run")
+ }
+}
+
func fin(v *int) {
}
diff --git a/libgo/go/runtime/norace_test.go b/libgo/go/runtime/norace_test.go
new file mode 100644
index 00000000000..a3d5b00860c
--- /dev/null
+++ b/libgo/go/runtime/norace_test.go
@@ -0,0 +1,58 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// The file contains tests that can not run under race detector for some reason.
+// +build !race
+
+package runtime_test
+
+import (
+ "runtime"
+ "sync/atomic"
+ "testing"
+)
+
+// Syscall tests split stack between Entersyscall and Exitsyscall under race detector.
+func BenchmarkSyscall(b *testing.B) {
+ benchmarkSyscall(b, 0, 1)
+}
+
+func BenchmarkSyscallWork(b *testing.B) {
+ benchmarkSyscall(b, 100, 1)
+}
+
+func BenchmarkSyscallExcess(b *testing.B) {
+ benchmarkSyscall(b, 0, 4)
+}
+
+func BenchmarkSyscallExcessWork(b *testing.B) {
+ benchmarkSyscall(b, 100, 4)
+}
+
+func benchmarkSyscall(b *testing.B, work, excess int) {
+ const CallsPerSched = 1000
+ procs := runtime.GOMAXPROCS(-1) * excess
+ N := int32(b.N / CallsPerSched)
+ c := make(chan bool, procs)
+ for p := 0; p < procs; p++ {
+ go func() {
+ foo := 42
+ for atomic.AddInt32(&N, -1) >= 0 {
+ runtime.Gosched()
+ for g := 0; g < CallsPerSched; g++ {
+ runtime.Entersyscall()
+ for i := 0; i < work; i++ {
+ foo *= 2
+ foo /= 2
+ }
+ runtime.Exitsyscall()
+ }
+ }
+ c <- foo == 42
+ }()
+ }
+ for p := 0; p < procs; p++ {
+ <-c
+ }
+}
diff --git a/libgo/go/runtime/parfor_test.go b/libgo/go/runtime/parfor_test.go
index 4c69a68ceea..de64285b8a8 100644
--- a/libgo/go/runtime/parfor_test.go
+++ b/libgo/go/runtime/parfor_test.go
@@ -102,11 +102,6 @@ func TestParForSetup(t *testing.T) {
// Test parallel parallelfor.
func TestParForParallel(t *testing.T) {
- if GOARCH != "amd64" {
- t.Log("temporarily disabled, see http://golang.org/issue/4155")
- return
- }
-
N := uint64(1e7)
if testing.Short() {
N /= 10
diff --git a/libgo/go/runtime/pprof/pprof.go b/libgo/go/runtime/pprof/pprof.go
index 32c1098b994..3b8428519d7 100644
--- a/libgo/go/runtime/pprof/pprof.go
+++ b/libgo/go/runtime/pprof/pprof.go
@@ -20,8 +20,8 @@ import (
"text/tabwriter"
)
-// BUG(rsc): A bug in the OS X Snow Leopard 64-bit kernel prevents
-// CPU profiling from giving accurate results on that system.
+// BUG(rsc): Profiles are incomplete and inaccuate on NetBSD, OpenBSD, and OS X.
+// See http://golang.org/issue/6047 for details.
// A Profile is a collection of stack traces showing the call sequences
// that led to instances of a particular event, such as allocation.
@@ -666,7 +666,7 @@ func writeBlock(w io.Writer, debug int) error {
}
fmt.Fprint(w, "\n")
if debug > 0 {
- printStackRecord(w, r.Stack(), false)
+ printStackRecord(w, r.Stack(), true)
}
}
diff --git a/libgo/go/runtime/pprof/pprof_test.go b/libgo/go/runtime/pprof/pprof_test.go
index 5762e17d36d..bdbbf42f028 100644
--- a/libgo/go/runtime/pprof/pprof_test.go
+++ b/libgo/go/runtime/pprof/pprof_test.go
@@ -9,57 +9,66 @@ import (
"fmt"
"hash/crc32"
"os/exec"
+ "regexp"
"runtime"
. "runtime/pprof"
"strings"
+ "sync"
"testing"
+ "time"
"unsafe"
)
func TestCPUProfile(t *testing.T) {
- switch runtime.GOOS {
- case "darwin":
- out, err := exec.Command("uname", "-a").CombinedOutput()
- if err != nil {
- t.Fatal(err)
- }
- vers := string(out)
- t.Logf("uname -a: %v", vers)
- // Lion uses "Darwin Kernel Version 11".
- if strings.Contains(vers, "Darwin Kernel Version 10") && strings.Contains(vers, "RELEASE_X86_64") {
- t.Skip("skipping test on known-broken kernel (64-bit Leopard / Snow Leopard)")
+ buf := make([]byte, 100000)
+ testCPUProfile(t, []string{"crc32.update"}, func() {
+ // This loop takes about a quarter second on a 2 GHz laptop.
+ // We only need to get one 100 Hz clock tick, so we've got
+ // a 25x safety buffer.
+ for i := 0; i < 1000; i++ {
+ crc32.ChecksumIEEE(buf)
}
- case "plan9":
- // unimplemented
- return
- }
+ })
+}
+func TestCPUProfileMultithreaded(t *testing.T) {
buf := make([]byte, 100000)
- var prof bytes.Buffer
- if err := StartCPUProfile(&prof); err != nil {
- t.Fatal(err)
- }
- // This loop takes about a quarter second on a 2 GHz laptop.
- // We only need to get one 100 Hz clock tick, so we've got
- // a 25x safety buffer.
- for i := 0; i < 1000; i++ {
- crc32.ChecksumIEEE(buf)
- }
- StopCPUProfile()
+ defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(2))
+ testCPUProfile(t, []string{"crc32.update"}, func() {
+ c := make(chan int)
+ go func() {
+ for i := 0; i < 2000; i++ {
+ crc32.Update(0, crc32.IEEETable, buf)
+ }
+ c <- 1
+ }()
+ // This loop takes about a quarter second on a 2 GHz laptop.
+ // We only need to get one 100 Hz clock tick, so we've got
+ // a 25x safety buffer.
+ for i := 0; i < 2000; i++ {
+ crc32.ChecksumIEEE(buf)
+ }
+ <-c
+ })
+}
+func parseProfile(t *testing.T, bytes []byte, f func(uintptr, []uintptr)) {
// Convert []byte to []uintptr.
- bytes := prof.Bytes()
l := len(bytes) / int(unsafe.Sizeof(uintptr(0)))
val := *(*[]uintptr)(unsafe.Pointer(&bytes))
val = val[:l]
- if l < 13 {
- t.Fatalf("profile too short: %#x", val)
+ // 5 for the header, 2 for the per-sample header on at least one sample, 3 for the trailer.
+ if l < 5+2+3 {
+ t.Logf("profile too short: %#x", val)
+ if badOS[runtime.GOOS] {
+ t.Skipf("ignoring failure on %s; see golang.org/issue/6047", runtime.GOOS)
+ return
+ }
+ t.FailNow()
}
- fmt.Println(val, l)
hd, val, tl := val[:5], val[5:l-3], val[l-3:]
- fmt.Println(hd, val, tl)
if hd[0] != 0 || hd[1] != 3 || hd[2] != 0 || hd[3] != 1e6/100 || hd[4] != 0 {
t.Fatalf("unexpected header %#x", hd)
}
@@ -68,26 +77,300 @@ func TestCPUProfile(t *testing.T) {
t.Fatalf("malformed end-of-data marker %#x", tl)
}
- // Check that profile is well formed and contains ChecksumIEEE.
- found := false
for len(val) > 0 {
if len(val) < 2 || val[0] < 1 || val[1] < 1 || uintptr(len(val)) < 2+val[1] {
t.Fatalf("malformed profile. leftover: %#x", val)
}
- for _, pc := range val[2 : 2+val[1]] {
+ f(val[0], val[2:2+val[1]])
+ val = val[2+val[1]:]
+ }
+}
+
+func testCPUProfile(t *testing.T, need []string, f func()) {
+ switch runtime.GOOS {
+ case "darwin":
+ out, err := exec.Command("uname", "-a").CombinedOutput()
+ if err != nil {
+ t.Fatal(err)
+ }
+ vers := string(out)
+ t.Logf("uname -a: %v", vers)
+ case "plan9":
+ // unimplemented
+ return
+ }
+
+ var prof bytes.Buffer
+ if err := StartCPUProfile(&prof); err != nil {
+ t.Fatal(err)
+ }
+ f()
+ StopCPUProfile()
+
+ // Check that profile is well formed and contains ChecksumIEEE.
+ have := make([]uintptr, len(need))
+ parseProfile(t, prof.Bytes(), func(count uintptr, stk []uintptr) {
+ for _, pc := range stk {
f := runtime.FuncForPC(pc)
if f == nil {
continue
}
- if strings.Contains(f.Name(), "ChecksumIEEE") ||
- (strings.Contains(f.Name(), "update") && strings.Contains(f.Name(), "crc32")) {
- found = true
+ for i, name := range need {
+ if strings.Contains(f.Name(), name) {
+ have[i] += count
+ }
}
}
- val = val[2+val[1]:]
+ })
+
+ var total uintptr
+ for i, name := range need {
+ total += have[i]
+ t.Logf("%s: %d\n", name, have[i])
+ }
+ ok := true
+ if total == 0 {
+ t.Logf("no CPU profile samples collected")
+ ok = false
+ }
+ min := total / uintptr(len(have)) / 3
+ for i, name := range need {
+ if have[i] < min {
+ t.Logf("%s has %d samples out of %d, want at least %d, ideally %d", name, have[i], total, min, total/uintptr(len(have)))
+ ok = false
+ }
+ }
+
+ if !ok {
+ if badOS[runtime.GOOS] {
+ t.Skipf("ignoring failure on %s; see golang.org/issue/6047", runtime.GOOS)
+ return
+ }
+ t.FailNow()
+ }
+}
+
+func TestCPUProfileWithFork(t *testing.T) {
+ // Fork can hang if preempted with signals frequently enough (see issue 5517).
+ // Ensure that we do not do this.
+ heap := 1 << 30
+ if testing.Short() {
+ heap = 100 << 20
}
+ // This makes fork slower.
+ garbage := make([]byte, heap)
+ // Need to touch the slice, otherwise it won't be paged in.
+ done := make(chan bool)
+ go func() {
+ for i := range garbage {
+ garbage[i] = 42
+ }
+ done <- true
+ }()
+ <-done
- if !found {
- t.Fatal("did not find ChecksumIEEE in the profile")
+ var prof bytes.Buffer
+ if err := StartCPUProfile(&prof); err != nil {
+ t.Fatal(err)
}
+ defer StopCPUProfile()
+
+ for i := 0; i < 10; i++ {
+ exec.Command("go").CombinedOutput()
+ }
+}
+
+// Test that profiler does not observe runtime.gogo as "user" goroutine execution.
+// If it did, it would see inconsistent state and would either record an incorrect stack
+// or crash because the stack was malformed.
+func TestGoroutineSwitch(t *testing.T) {
+ if runtime.GOOS == "windows" {
+ t.Skip("flaky test; see http://golang.org/issue/6417")
+ }
+ // How much to try. These defaults take about 1 seconds
+ // on a 2012 MacBook Pro. The ones in short mode take
+ // about 0.1 seconds.
+ tries := 10
+ count := 1000000
+ if testing.Short() {
+ tries = 1
+ }
+ for try := 0; try < tries; try++ {
+ var prof bytes.Buffer
+ if err := StartCPUProfile(&prof); err != nil {
+ t.Fatal(err)
+ }
+ for i := 0; i < count; i++ {
+ runtime.Gosched()
+ }
+ StopCPUProfile()
+
+ // Read profile to look for entries for runtime.gogo with an attempt at a traceback.
+ // The special entry
+ parseProfile(t, prof.Bytes(), func(count uintptr, stk []uintptr) {
+ // An entry with two frames with 'System' in its top frame
+ // exists to record a PC without a traceback. Those are okay.
+ if len(stk) == 2 {
+ f := runtime.FuncForPC(stk[1])
+ if f != nil && f.Name() == "System" {
+ return
+ }
+ }
+
+ // Otherwise, should not see runtime.gogo.
+ // The place we'd see it would be the inner most frame.
+ f := runtime.FuncForPC(stk[0])
+ if f != nil && f.Name() == "runtime.gogo" {
+ var buf bytes.Buffer
+ for _, pc := range stk {
+ f := runtime.FuncForPC(pc)
+ if f == nil {
+ fmt.Fprintf(&buf, "%#x ?:0\n", pc)
+ } else {
+ file, line := f.FileLine(pc)
+ fmt.Fprintf(&buf, "%#x %s:%d\n", pc, file, line)
+ }
+ }
+ t.Fatalf("found profile entry for runtime.gogo:\n%s", buf.String())
+ }
+ })
+ }
+}
+
+// Operating systems that are expected to fail the tests. See issue 6047.
+var badOS = map[string]bool{
+ "darwin": true,
+ "netbsd": true,
+ "openbsd": true,
+}
+
+func TestBlockProfile(t *testing.T) {
+ t.Skip("lots of details are different for gccgo; FIXME")
+ type TestCase struct {
+ name string
+ f func()
+ re string
+ }
+ tests := [...]TestCase{
+ {"chan recv", blockChanRecv, `
+[0-9]+ [0-9]+ @ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+
+# 0x[0-9,a-f]+ runtime\.chanrecv1\+0x[0-9,a-f]+ .*/src/pkg/runtime/chan.c:[0-9]+
+# 0x[0-9,a-f]+ runtime/pprof_test\.blockChanRecv\+0x[0-9,a-f]+ .*/src/pkg/runtime/pprof/pprof_test.go:[0-9]+
+# 0x[0-9,a-f]+ runtime/pprof_test\.TestBlockProfile\+0x[0-9,a-f]+ .*/src/pkg/runtime/pprof/pprof_test.go:[0-9]+
+`},
+ {"chan send", blockChanSend, `
+[0-9]+ [0-9]+ @ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+
+# 0x[0-9,a-f]+ runtime\.chansend1\+0x[0-9,a-f]+ .*/src/pkg/runtime/chan.c:[0-9]+
+# 0x[0-9,a-f]+ runtime/pprof_test\.blockChanSend\+0x[0-9,a-f]+ .*/src/pkg/runtime/pprof/pprof_test.go:[0-9]+
+# 0x[0-9,a-f]+ runtime/pprof_test\.TestBlockProfile\+0x[0-9,a-f]+ .*/src/pkg/runtime/pprof/pprof_test.go:[0-9]+
+`},
+ {"chan close", blockChanClose, `
+[0-9]+ [0-9]+ @ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+
+# 0x[0-9,a-f]+ runtime\.chanrecv1\+0x[0-9,a-f]+ .*/src/pkg/runtime/chan.c:[0-9]+
+# 0x[0-9,a-f]+ runtime/pprof_test\.blockChanClose\+0x[0-9,a-f]+ .*/src/pkg/runtime/pprof/pprof_test.go:[0-9]+
+# 0x[0-9,a-f]+ runtime/pprof_test\.TestBlockProfile\+0x[0-9,a-f]+ .*/src/pkg/runtime/pprof/pprof_test.go:[0-9]+
+`},
+ {"select recv async", blockSelectRecvAsync, `
+[0-9]+ [0-9]+ @ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+
+# 0x[0-9,a-f]+ runtime\.selectgo\+0x[0-9,a-f]+ .*/src/pkg/runtime/chan.c:[0-9]+
+# 0x[0-9,a-f]+ runtime/pprof_test\.blockSelectRecvAsync\+0x[0-9,a-f]+ .*/src/pkg/runtime/pprof/pprof_test.go:[0-9]+
+# 0x[0-9,a-f]+ runtime/pprof_test\.TestBlockProfile\+0x[0-9,a-f]+ .*/src/pkg/runtime/pprof/pprof_test.go:[0-9]+
+`},
+ {"select send sync", blockSelectSendSync, `
+[0-9]+ [0-9]+ @ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+
+# 0x[0-9,a-f]+ runtime\.selectgo\+0x[0-9,a-f]+ .*/src/pkg/runtime/chan.c:[0-9]+
+# 0x[0-9,a-f]+ runtime/pprof_test\.blockSelectSendSync\+0x[0-9,a-f]+ .*/src/pkg/runtime/pprof/pprof_test.go:[0-9]+
+# 0x[0-9,a-f]+ runtime/pprof_test\.TestBlockProfile\+0x[0-9,a-f]+ .*/src/pkg/runtime/pprof/pprof_test.go:[0-9]+
+`},
+ {"mutex", blockMutex, `
+[0-9]+ [0-9]+ @ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+
+# 0x[0-9,a-f]+ sync\.\(\*Mutex\)\.Lock\+0x[0-9,a-f]+ .*/src/pkg/sync/mutex\.go:[0-9]+
+# 0x[0-9,a-f]+ runtime/pprof_test\.blockMutex\+0x[0-9,a-f]+ .*/src/pkg/runtime/pprof/pprof_test.go:[0-9]+
+# 0x[0-9,a-f]+ runtime/pprof_test\.TestBlockProfile\+0x[0-9,a-f]+ .*/src/pkg/runtime/pprof/pprof_test.go:[0-9]+
+`},
+ }
+
+ runtime.SetBlockProfileRate(1)
+ defer runtime.SetBlockProfileRate(0)
+ for _, test := range tests {
+ test.f()
+ }
+ var w bytes.Buffer
+ Lookup("block").WriteTo(&w, 1)
+ prof := w.String()
+
+ if !strings.HasPrefix(prof, "--- contention:\ncycles/second=") {
+ t.Fatalf("Bad profile header:\n%v", prof)
+ }
+
+ for _, test := range tests {
+ if !regexp.MustCompile(test.re).MatchString(prof) {
+ t.Fatalf("Bad %v entry, expect:\n%v\ngot:\n%v", test.name, test.re, prof)
+ }
+ }
+}
+
+const blockDelay = 10 * time.Millisecond
+
+func blockChanRecv() {
+ c := make(chan bool)
+ go func() {
+ time.Sleep(blockDelay)
+ c <- true
+ }()
+ <-c
+}
+
+func blockChanSend() {
+ c := make(chan bool)
+ go func() {
+ time.Sleep(blockDelay)
+ <-c
+ }()
+ c <- true
+}
+
+func blockChanClose() {
+ c := make(chan bool)
+ go func() {
+ time.Sleep(blockDelay)
+ close(c)
+ }()
+ <-c
+}
+
+func blockSelectRecvAsync() {
+ c := make(chan bool, 1)
+ c2 := make(chan bool, 1)
+ go func() {
+ time.Sleep(blockDelay)
+ c <- true
+ }()
+ select {
+ case <-c:
+ case <-c2:
+ }
+}
+
+func blockSelectSendSync() {
+ c := make(chan bool)
+ c2 := make(chan bool)
+ go func() {
+ time.Sleep(blockDelay)
+ <-c
+ }()
+ select {
+ case c <- true:
+ case c2 <- true:
+ }
+}
+
+func blockMutex() {
+ var mu sync.Mutex
+ mu.Lock()
+ go func() {
+ time.Sleep(blockDelay)
+ mu.Unlock()
+ }()
+ mu.Lock()
}
diff --git a/libgo/go/runtime/proc_test.go b/libgo/go/runtime/proc_test.go
index 21fb9c2f7f7..29f71e7448c 100644
--- a/libgo/go/runtime/proc_test.go
+++ b/libgo/go/runtime/proc_test.go
@@ -8,6 +8,7 @@ import (
"math"
"runtime"
"sync/atomic"
+ "syscall"
"testing"
"time"
)
@@ -92,6 +93,35 @@ func TestYieldLocked(t *testing.T) {
<-c
}
+func TestGoroutineParallelism(t *testing.T) {
+ P := 4
+ N := 10
+ if testing.Short() {
+ P = 3
+ N = 3
+ }
+ defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(P))
+ for try := 0; try < N; try++ {
+ done := make(chan bool)
+ x := uint32(0)
+ for p := 0; p < P; p++ {
+ // Test that all P goroutines are scheduled at the same time
+ go func(p int) {
+ for i := 0; i < 3; i++ {
+ expected := uint32(P*i + p)
+ for atomic.LoadUint32(&x) != expected {
+ }
+ atomic.StoreUint32(&x, expected+1)
+ }
+ done <- true
+ }(p)
+ }
+ for p := 0; p < P; p++ {
+ <-done
+ }
+ }
+}
+
func TestBlockLocked(t *testing.T) {
const N = 10
c := make(chan bool)
@@ -107,86 +137,212 @@ func TestBlockLocked(t *testing.T) {
}
}
-func stackGrowthRecursive(i int) {
- var pad [128]uint64
- if i != 0 && pad[0] == 0 {
- stackGrowthRecursive(i - 1)
+func TestTimerFairness(t *testing.T) {
+ done := make(chan bool)
+ c := make(chan bool)
+ for i := 0; i < 2; i++ {
+ go func() {
+ for {
+ select {
+ case c <- true:
+ case <-done:
+ return
+ }
+ }
+ }()
+ }
+
+ timer := time.After(20 * time.Millisecond)
+ for {
+ select {
+ case <-c:
+ case <-timer:
+ close(done)
+ return
+ }
}
}
-func TestSchedLocalQueue(t *testing.T) {
- runtime.TestSchedLocalQueue1()
+func TestTimerFairness2(t *testing.T) {
+ done := make(chan bool)
+ c := make(chan bool)
+ for i := 0; i < 2; i++ {
+ go func() {
+ timer := time.After(20 * time.Millisecond)
+ var buf [1]byte
+ for {
+ syscall.Read(0, buf[0:0])
+ select {
+ case c <- true:
+ case <-c:
+ case <-timer:
+ done <- true
+ return
+ }
+ }
+ }()
+ }
+ <-done
+ <-done
}
-func TestSchedLocalQueueSteal(t *testing.T) {
- runtime.TestSchedLocalQueueSteal1()
+// The function is used to test preemption at split stack checks.
+// Declaring a var avoids inlining at the call site.
+var preempt = func() int {
+ var a [128]int
+ sum := 0
+ for _, v := range a {
+ sum += v
+ }
+ return sum
}
-func benchmarkStackGrowth(b *testing.B, rec int) {
- const CallsPerSched = 1000
- procs := runtime.GOMAXPROCS(-1)
- N := int32(b.N / CallsPerSched)
- c := make(chan bool, procs)
- for p := 0; p < procs; p++ {
- go func() {
- for atomic.AddInt32(&N, -1) >= 0 {
- runtime.Gosched()
- for g := 0; g < CallsPerSched; g++ {
- stackGrowthRecursive(rec)
+func TestPreemption(t *testing.T) {
+ t.Skip("gccgo does not implement preemption")
+ // Test that goroutines are preempted at function calls.
+ N := 5
+ if testing.Short() {
+ N = 2
+ }
+ c := make(chan bool)
+ var x uint32
+ for g := 0; g < 2; g++ {
+ go func(g int) {
+ for i := 0; i < N; i++ {
+ for atomic.LoadUint32(&x) != uint32(g) {
+ preempt()
}
+ atomic.StoreUint32(&x, uint32(1-g))
}
c <- true
+ }(g)
+ }
+ <-c
+ <-c
+}
+
+func TestPreemptionGC(t *testing.T) {
+ t.Skip("gccgo does not implement preemption")
+ // Test that pending GC preempts running goroutines.
+ P := 5
+ N := 10
+ if testing.Short() {
+ P = 3
+ N = 2
+ }
+ defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(P + 1))
+ var stop uint32
+ for i := 0; i < P; i++ {
+ go func() {
+ for atomic.LoadUint32(&stop) == 0 {
+ preempt()
+ }
}()
}
- for p := 0; p < procs; p++ {
- <-c
+ for i := 0; i < N; i++ {
+ runtime.Gosched()
+ runtime.GC()
}
+ atomic.StoreUint32(&stop, 1)
}
-func BenchmarkStackGrowth(b *testing.B) {
- benchmarkStackGrowth(b, 10)
+func stackGrowthRecursive(i int) {
+ var pad [128]uint64
+ if i != 0 && pad[0] == 0 {
+ stackGrowthRecursive(i - 1)
+ }
}
-func BenchmarkStackGrowthDeep(b *testing.B) {
- benchmarkStackGrowth(b, 1024)
+func TestPreemptSplitBig(t *testing.T) {
+ if testing.Short() {
+ t.Skip("skipping in -short mode")
+ }
+ t.Skip("gccgo does not implement preemption")
+ defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(2))
+ stop := make(chan int)
+ go big(stop)
+ for i := 0; i < 3; i++ {
+ time.Sleep(10 * time.Microsecond) // let big start running
+ runtime.GC()
+ }
+ close(stop)
+}
+
+func big(stop chan int) int {
+ n := 0
+ for {
+ // delay so that gc is sure to have asked for a preemption
+ for i := 0; i < 1e9; i++ {
+ n++
+ }
+
+ // call bigframe, which used to miss the preemption in its prologue.
+ bigframe(stop)
+
+ // check if we've been asked to stop.
+ select {
+ case <-stop:
+ return n
+ }
+ }
+}
+
+func bigframe(stop chan int) int {
+ // not splitting the stack will overflow.
+ // small will notice that it needs a stack split and will
+ // catch the overflow.
+ var x [8192]byte
+ return small(stop, &x)
}
-func BenchmarkSyscall(b *testing.B) {
- benchmarkSyscall(b, 0, 1)
+func small(stop chan int, x *[8192]byte) int {
+ for i := range x {
+ x[i] = byte(i)
+ }
+ sum := 0
+ for i := range x {
+ sum += int(x[i])
+ }
+
+ // keep small from being a leaf function, which might
+ // make it not do any stack check at all.
+ nonleaf(stop)
+
+ return sum
}
-func BenchmarkSyscallWork(b *testing.B) {
- benchmarkSyscall(b, 100, 1)
+func nonleaf(stop chan int) bool {
+ // do something that won't be inlined:
+ select {
+ case <-stop:
+ return true
+ default:
+ return false
+ }
}
-func BenchmarkSyscallExcess(b *testing.B) {
- benchmarkSyscall(b, 0, 4)
+func TestSchedLocalQueue(t *testing.T) {
+ runtime.TestSchedLocalQueue1()
}
-func BenchmarkSyscallExcessWork(b *testing.B) {
- benchmarkSyscall(b, 100, 4)
+func TestSchedLocalQueueSteal(t *testing.T) {
+ runtime.TestSchedLocalQueueSteal1()
}
-func benchmarkSyscall(b *testing.B, work, excess int) {
+func benchmarkStackGrowth(b *testing.B, rec int) {
const CallsPerSched = 1000
- procs := runtime.GOMAXPROCS(-1) * excess
+ procs := runtime.GOMAXPROCS(-1)
N := int32(b.N / CallsPerSched)
c := make(chan bool, procs)
for p := 0; p < procs; p++ {
go func() {
- foo := 42
for atomic.AddInt32(&N, -1) >= 0 {
runtime.Gosched()
for g := 0; g < CallsPerSched; g++ {
- runtime.Entersyscall()
- for i := 0; i < work; i++ {
- foo *= 2
- foo /= 2
- }
- runtime.Exitsyscall()
+ stackGrowthRecursive(rec)
}
}
- c <- foo == 42
+ c <- true
}()
}
for p := 0; p < procs; p++ {
@@ -194,6 +350,14 @@ func benchmarkSyscall(b *testing.B, work, excess int) {
}
}
+func BenchmarkStackGrowth(b *testing.B) {
+ benchmarkStackGrowth(b, 10)
+}
+
+func BenchmarkStackGrowthDeep(b *testing.B) {
+ benchmarkStackGrowth(b, 1024)
+}
+
func BenchmarkCreateGoroutines(b *testing.B) {
benchmarkCreateGoroutines(b, 1)
}
diff --git a/libgo/go/runtime/runtime_test.go b/libgo/go/runtime/runtime_test.go
index e458793491d..d1219295612 100644
--- a/libgo/go/runtime/runtime_test.go
+++ b/libgo/go/runtime/runtime_test.go
@@ -6,6 +6,12 @@ package runtime_test
import (
"io"
+ // "io/ioutil"
+ // "os"
+ // "os/exec"
+ // . "runtime"
+ // "strconv"
+ // "strings"
"testing"
)
@@ -79,3 +85,43 @@ func BenchmarkDeferMany(b *testing.B) {
}(1, 2, 3)
}
}
+
+/* The go tool is not present in gccgo.
+
+// The profiling signal handler needs to know whether it is executing runtime.gogo.
+// The constant RuntimeGogoBytes in arch_*.h gives the size of the function;
+// we don't have a way to obtain it from the linker (perhaps someday).
+// Test that the constant matches the size determined by 'go tool nm -S'.
+// The value reported will include the padding between runtime.gogo and the
+// next function in memory. That's fine.
+func TestRuntimeGogoBytes(t *testing.T) {
+ dir, err := ioutil.TempDir("", "go-build")
+ if err != nil {
+ t.Fatalf("failed to create temp directory: %v", err)
+ }
+ defer os.RemoveAll(dir)
+
+ out, err := exec.Command("go", "build", "-o", dir+"/hello", "../../../test/helloworld.go").CombinedOutput()
+ if err != nil {
+ t.Fatalf("building hello world: %v\n%s", err, out)
+ }
+
+ out, err = exec.Command("go", "tool", "nm", "-S", dir+"/hello").CombinedOutput()
+ if err != nil {
+ t.Fatalf("go tool nm: %v\n%s", err, out)
+ }
+
+ for _, line := range strings.Split(string(out), "\n") {
+ f := strings.Fields(line)
+ if len(f) == 4 && f[3] == "runtime.gogo" {
+ size, _ := strconv.Atoi(f[1])
+ if GogoBytes() != int32(size) {
+ t.Fatalf("RuntimeGogoBytes = %d, should be %d", GogoBytes(), size)
+ }
+ return
+ }
+ }
+
+ t.Fatalf("go tool nm did not report size for runtime.gogo")
+}
+*/
diff --git a/libgo/go/sort/example_interface_test.go b/libgo/go/sort/example_interface_test.go
index 4c88821be7c..442204ea9eb 100644
--- a/libgo/go/sort/example_interface_test.go
+++ b/libgo/go/sort/example_interface_test.go
@@ -9,69 +9,36 @@ import (
"sort"
)
-type Grams int
-
-func (g Grams) String() string { return fmt.Sprintf("%dg", int(g)) }
-
-type Organ struct {
- Name string
- Weight Grams
+type Person struct {
+ Name string
+ Age int
}
-type Organs []*Organ
-
-func (s Organs) Len() int { return len(s) }
-func (s Organs) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
-
-// ByName implements sort.Interface by providing Less and using the Len and
-// Swap methods of the embedded Organs value.
-type ByName struct{ Organs }
-
-func (s ByName) Less(i, j int) bool { return s.Organs[i].Name < s.Organs[j].Name }
+func (p Person) String() string {
+ return fmt.Sprintf("%s: %d", p.Name, p.Age)
+}
-// ByWeight implements sort.Interface by providing Less and using the Len and
-// Swap methods of the embedded Organs value.
-type ByWeight struct{ Organs }
+// ByAge implements sort.Interface for []Person based on
+// the Age field.
+type ByAge []Person
-func (s ByWeight) Less(i, j int) bool { return s.Organs[i].Weight < s.Organs[j].Weight }
+func (a ByAge) Len() int { return len(a) }
+func (a ByAge) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
+func (a ByAge) Less(i, j int) bool { return a[i].Age < a[j].Age }
-func ExampleInterface() {
- s := []*Organ{
- {"brain", 1340},
- {"heart", 290},
- {"liver", 1494},
- {"pancreas", 131},
- {"prostate", 62},
- {"spleen", 162},
+func Example() {
+ people := []Person{
+ {"Bob", 31},
+ {"John", 42},
+ {"Michael", 17},
+ {"Jenny", 26},
}
- sort.Sort(ByWeight{s})
- fmt.Println("Organs by weight:")
- printOrgans(s)
-
- sort.Sort(ByName{s})
- fmt.Println("Organs by name:")
- printOrgans(s)
+ fmt.Println(people)
+ sort.Sort(ByAge(people))
+ fmt.Println(people)
// Output:
- // Organs by weight:
- // prostate (62g)
- // pancreas (131g)
- // spleen (162g)
- // heart (290g)
- // brain (1340g)
- // liver (1494g)
- // Organs by name:
- // brain (1340g)
- // heart (290g)
- // liver (1494g)
- // pancreas (131g)
- // prostate (62g)
- // spleen (162g)
-}
-
-func printOrgans(s []*Organ) {
- for _, o := range s {
- fmt.Printf("%-8s (%v)\n", o.Name, o.Weight)
- }
+ // [Bob: 31 John: 42 Michael: 17 Jenny: 26]
+ // [Michael: 17 Jenny: 26 Bob: 31 John: 42]
}
diff --git a/libgo/go/sort/example_multi_test.go b/libgo/go/sort/example_multi_test.go
index d0a9e7dc374..ac316540fd5 100644
--- a/libgo/go/sort/example_multi_test.go
+++ b/libgo/go/sort/example_multi_test.go
@@ -26,6 +26,7 @@ type multiSorter struct {
// Sort sorts the argument slice according to the less functions passed to OrderedBy.
func (ms *multiSorter) Sort(changes []Change) {
+ ms.changes = changes
sort.Sort(ms)
}
@@ -33,8 +34,7 @@ func (ms *multiSorter) Sort(changes []Change) {
// Call its Sort method to sort the data.
func OrderedBy(less ...lessFunc) *multiSorter {
return &multiSorter{
- changes: changes,
- less: less,
+ less: less,
}
}
@@ -108,11 +108,10 @@ func Example_sortMultiKeys() {
OrderedBy(user).Sort(changes)
fmt.Println("By user:", changes)
- // multiSorter implements the Sort interface, so we can also do this.
- sort.Sort(OrderedBy(user, increasingLines))
+ // More examples.
+ OrderedBy(user, increasingLines).Sort(changes)
fmt.Println("By user,<lines:", changes)
- // More examples.
OrderedBy(user, decreasingLines).Sort(changes)
fmt.Println("By user,>lines:", changes)
@@ -123,10 +122,10 @@ func Example_sortMultiKeys() {
fmt.Println("By language,<lines,user:", changes)
// Output:
- //By user: [{dmr C 100} {glenda Go 200} {gri Smalltalk 80} {gri Go 100} {ken Go 200} {ken C 150} {r Go 100} {r C 150} {rsc Go 200}]
- //By user,<lines: [{dmr C 100} {glenda Go 200} {gri Smalltalk 80} {gri Go 100} {ken C 150} {ken Go 200} {r Go 100} {r C 150} {rsc Go 200}]
- //By user,>lines: [{dmr C 100} {glenda Go 200} {gri Go 100} {gri Smalltalk 80} {ken Go 200} {ken C 150} {r C 150} {r Go 100} {rsc Go 200}]
- //By language,<lines: [{dmr C 100} {ken C 150} {r C 150} {gri Go 100} {r Go 100} {ken Go 200} {glenda Go 200} {rsc Go 200} {gri Smalltalk 80}]
- //By language,<lines,user: [{dmr C 100} {ken C 150} {r C 150} {gri Go 100} {r Go 100} {glenda Go 200} {ken Go 200} {rsc Go 200} {gri Smalltalk 80}]
+ // By user: [{dmr C 100} {glenda Go 200} {gri Smalltalk 80} {gri Go 100} {ken Go 200} {ken C 150} {r Go 100} {r C 150} {rsc Go 200}]
+ // By user,<lines: [{dmr C 100} {glenda Go 200} {gri Smalltalk 80} {gri Go 100} {ken C 150} {ken Go 200} {r Go 100} {r C 150} {rsc Go 200}]
+ // By user,>lines: [{dmr C 100} {glenda Go 200} {gri Go 100} {gri Smalltalk 80} {ken Go 200} {ken C 150} {r C 150} {r Go 100} {rsc Go 200}]
+ // By language,<lines: [{dmr C 100} {ken C 150} {r C 150} {gri Go 100} {r Go 100} {ken Go 200} {glenda Go 200} {rsc Go 200} {gri Smalltalk 80}]
+ // By language,<lines,user: [{dmr C 100} {ken C 150} {r C 150} {gri Go 100} {r Go 100} {glenda Go 200} {ken Go 200} {rsc Go 200} {gri Smalltalk 80}]
}
diff --git a/libgo/go/sort/example_wrapper_test.go b/libgo/go/sort/example_wrapper_test.go
new file mode 100644
index 00000000000..cf6d74cf754
--- /dev/null
+++ b/libgo/go/sort/example_wrapper_test.go
@@ -0,0 +1,77 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sort_test
+
+import (
+ "fmt"
+ "sort"
+)
+
+type Grams int
+
+func (g Grams) String() string { return fmt.Sprintf("%dg", int(g)) }
+
+type Organ struct {
+ Name string
+ Weight Grams
+}
+
+type Organs []*Organ
+
+func (s Organs) Len() int { return len(s) }
+func (s Organs) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+
+// ByName implements sort.Interface by providing Less and using the Len and
+// Swap methods of the embedded Organs value.
+type ByName struct{ Organs }
+
+func (s ByName) Less(i, j int) bool { return s.Organs[i].Name < s.Organs[j].Name }
+
+// ByWeight implements sort.Interface by providing Less and using the Len and
+// Swap methods of the embedded Organs value.
+type ByWeight struct{ Organs }
+
+func (s ByWeight) Less(i, j int) bool { return s.Organs[i].Weight < s.Organs[j].Weight }
+
+func Example_sortWrapper() {
+ s := []*Organ{
+ {"brain", 1340},
+ {"heart", 290},
+ {"liver", 1494},
+ {"pancreas", 131},
+ {"prostate", 62},
+ {"spleen", 162},
+ }
+
+ sort.Sort(ByWeight{s})
+ fmt.Println("Organs by weight:")
+ printOrgans(s)
+
+ sort.Sort(ByName{s})
+ fmt.Println("Organs by name:")
+ printOrgans(s)
+
+ // Output:
+ // Organs by weight:
+ // prostate (62g)
+ // pancreas (131g)
+ // spleen (162g)
+ // heart (290g)
+ // brain (1340g)
+ // liver (1494g)
+ // Organs by name:
+ // brain (1340g)
+ // heart (290g)
+ // liver (1494g)
+ // pancreas (131g)
+ // prostate (62g)
+ // spleen (162g)
+}
+
+func printOrgans(s []*Organ) {
+ for _, o := range s {
+ fmt.Printf("%-8s (%v)\n", o.Name, o.Weight)
+ }
+}
diff --git a/libgo/go/sort/search_test.go b/libgo/go/sort/search_test.go
index 80b9abdea8e..4265b9520a6 100644
--- a/libgo/go/sort/search_test.go
+++ b/libgo/go/sort/search_test.go
@@ -128,6 +128,9 @@ func runSearchWrappers() {
}
func TestSearchWrappersDontAlloc(t *testing.T) {
+ if testing.Short() {
+ t.Skip("skipping malloc count in short mode")
+ }
if runtime.GOMAXPROCS(0) > 1 {
t.Skip("skipping; GOMAXPROCS>1")
}
diff --git a/libgo/go/sort/sort.go b/libgo/go/sort/sort.go
index d3092e80191..f06eb3827ab 100644
--- a/libgo/go/sort/sort.go
+++ b/libgo/go/sort/sort.go
@@ -12,8 +12,8 @@ package sort
type Interface interface {
// Len is the number of elements in the collection.
Len() int
- // Less returns whether the element with index i should sort
- // before the element with index j.
+ // Less reports whether the element with
+ // index i should sort before the element with index j.
Less(i, j int) bool
// Swap swaps the elements with indexes i and j.
Swap(i, j int)
@@ -283,3 +283,192 @@ func Float64sAreSorted(a []float64) bool { return IsSorted(Float64Slice(a)) }
// StringsAreSorted tests whether a slice of strings is sorted in increasing order.
func StringsAreSorted(a []string) bool { return IsSorted(StringSlice(a)) }
+
+// Notes on stable sorting:
+// The used algorithms are simple and provable correct on all input and use
+// only logarithmic additional stack space. They perform well if compared
+// experimentaly to other stable in-place sorting algorithms.
+//
+// Remarks on other algoritms evaluated:
+// - GCC's 4.6.3 stable_sort with merge_without_buffer from libstdc++:
+// Not faster.
+// - GCC's __rotate for block rotations: Not faster.
+// - "Practical in-place mergesort" from Jyrki Katajainen, Tomi A. Pasanen
+// and Jukka Teuhola; Nordic Journal of Computing 3,1 (1996), 27-40:
+// The given algorithms are in-place, number of Swap and Assignments
+// grow as n log n but the algorithm is not stable.
+// - "Fast Stable In-Plcae Sorting with O(n) Data Moves" J.I. Munro and
+// V. Raman in Algorithmica (1996) 16, 115-160:
+// This algorithm either needs additional 2n bits or works only if there
+// are enough different elements available to encode some permutations
+// which have to be undone later (so not stable an any input).
+// - All the optimal in-place sorting/merging algorithms I found are either
+// unstable or rely on enough different elements in each step to encode the
+// performed block rearrangements. See also "In-Place Merging Algorithms",
+// Denham Coates-Evely, Department of Computer Science, Kings College,
+// January 2004 and the reverences in there.
+// - Often "optimal" algorithms are optimal in the number of assignments
+// but Interface has only Swap as operation.
+
+// Stable sorts data while keeping the original order of equal elements.
+//
+// It makes one call to data.Len to determine n, O(n*log(n)) calls to
+// data.Less and O(n*log(n)*log(n)) calls to data.Swap.
+func Stable(data Interface) {
+ n := data.Len()
+ blockSize := 20
+ a, b := 0, blockSize
+ for b <= n {
+ insertionSort(data, a, b)
+ a = b
+ b += blockSize
+ }
+ insertionSort(data, a, n)
+
+ for blockSize < n {
+ a, b = 0, 2*blockSize
+ for b <= n {
+ symMerge(data, a, a+blockSize, b)
+ a = b
+ b += 2 * blockSize
+ }
+ symMerge(data, a, a+blockSize, n)
+ blockSize *= 2
+ }
+}
+
+// SymMerge merges the two sorted subsequences data[a:m] and data[m:b] using
+// the SymMerge algorithm from Pok-Son Kim and Arne Kutzner, "Stable Minimum
+// Storage Merging by Symmetric Comparisons", in Susanne Albers and Tomasz
+// Radzik, editors, Algorithms - ESA 2004, volume 3221 of Lecture Notes in
+// Computer Science, pages 714-723. Springer, 2004.
+//
+// Let M = m-a and N = b-n. Wolog M < N.
+// The recursion depth is bound by ceil(log(N+M)).
+// The algorithm needs O(M*log(N/M + 1)) calls to data.Less.
+// The algorithm needs O((M+N)*log(M)) calls to data.Swap.
+//
+// The paper gives O((M+N)*log(M)) as the number of assignments assuming a
+// rotation algorithm wich uses O(M+N+gcd(M+N)) assignments. The argumentation
+// in the paper carries through for Swap operations, especially as the block
+// swapping rotate uses only O(M+N) Swaps.
+func symMerge(data Interface, a, m, b int) {
+ if a >= m || m >= b {
+ return
+ }
+
+ mid := a + (b-a)/2
+ n := mid + m
+ start := 0
+ if m > mid {
+ start = n - b
+ r, p := mid, n-1
+ for start < r {
+ c := start + (r-start)/2
+ if !data.Less(p-c, c) {
+ start = c + 1
+ } else {
+ r = c
+ }
+ }
+ } else {
+ start = a
+ r, p := m, n-1
+ for start < r {
+ c := start + (r-start)/2
+ if !data.Less(p-c, c) {
+ start = c + 1
+ } else {
+ r = c
+ }
+ }
+ }
+ end := n - start
+ rotate(data, start, m, end)
+ symMerge(data, a, start, mid)
+ symMerge(data, mid, end, b)
+}
+
+// Rotate two consecutives blocks u = data[a:m] and v = data[m:b] in data:
+// Data of the form 'x u v y' is changed to 'x v u y'.
+// Rotate performs at most b-a many calls to data.Swap.
+func rotate(data Interface, a, m, b int) {
+ i := m - a
+ if i == 0 {
+ return
+ }
+ j := b - m
+ if j == 0 {
+ return
+ }
+
+ if i == j {
+ swapRange(data, a, m, i)
+ return
+ }
+
+ p := a + i
+ for i != j {
+ if i > j {
+ swapRange(data, p-i, p, j)
+ i -= j
+ } else {
+ swapRange(data, p-i, p+j-i, i)
+ j -= i
+ }
+ }
+ swapRange(data, p-i, p, i)
+}
+
+/*
+Complexity of Stable Sorting
+
+
+Complexity of block swapping rotation
+
+Each Swap puts one new element into its correct, final position.
+Elements which reach their final position are no longer moved.
+Thus block swapping rotation needs |u|+|v| calls to Swaps.
+This is best possible as each element might need a move.
+
+Pay attention when comparing to other optimal algorithms which
+typically count the number of assignments instead of swaps:
+E.g. the optimal algorithm of Dudzinski and Dydek for in-place
+rotations uses O(u + v + gcd(u,v)) assignments which is
+better than our O(3 * (u+v)) as gcd(u,v) <= u.
+
+
+Stable sorting by SymMerge and BlockSwap rotations
+
+SymMerg complexity for same size input M = N:
+Calls to Less: O(M*log(N/M+1)) = O(N*log(2)) = O(N)
+Calls to Swap: O((M+N)*log(M)) = O(2*N*log(N)) = O(N*log(N))
+
+(The following argument does not fuzz over a missing -1 or
+other stuff which does not impact the final result).
+
+Let n = data.Len(). Assume n = 2^k.
+
+Plain merge sort performs log(n) = k iterations.
+On iteration i the algorithm merges 2^(k-i) blocks, each of size 2^i.
+
+Thus iteration i of merge sort performs:
+Calls to Less O(2^(k-i) * 2^i) = O(2^k) = O(2^log(n)) = O(n)
+Calls to Swap O(2^(k-i) * 2^i * log(2^i)) = O(2^k * i) = O(n*i)
+
+In total k = log(n) iterations are performed; so in total:
+Calls to Less O(log(n) * n)
+Calls to Swap O(n + 2*n + 3*n + ... + (k-1)*n + k*n)
+ = O((k/2) * k * n) = O(n * k^2) = O(n * log^2(n))
+
+
+Above results should generalize to arbitrary n = 2^k + p
+and should not be influenced by the initial insertion sort phase:
+Insertion sort is O(n^2) on Swap and Less, thus O(bs^2) per block of
+size bs at n/bs blocks: O(bs*n) Swaps and Less during insertion sort.
+Merge sort iterations start at i = log(bs). With t = log(bs) constant:
+Calls to Less O((log(n)-t) * n + bs*n) = O(log(n)*n + (bs-t)*n)
+ = O(n * log(n))
+Calls to Swap O(n * log^2(n) - (t^2+t)/2*n) = O(n * log^2(n))
+
+*/
diff --git a/libgo/go/sort/sort_test.go b/libgo/go/sort/sort_test.go
index 5daf8482b9c..6c36f30e0ee 100644
--- a/libgo/go/sort/sort_test.go
+++ b/libgo/go/sort/sort_test.go
@@ -122,6 +122,19 @@ func BenchmarkSortString1K(b *testing.B) {
}
}
+func BenchmarkStableString1K(b *testing.B) {
+ b.StopTimer()
+ for i := 0; i < b.N; i++ {
+ data := make([]string, 1<<10)
+ for i := 0; i < len(data); i++ {
+ data[i] = strconv.Itoa(i ^ 0x2cc)
+ }
+ b.StartTimer()
+ Stable(StringSlice(data))
+ b.StopTimer()
+ }
+}
+
func BenchmarkSortInt1K(b *testing.B) {
b.StopTimer()
for i := 0; i < b.N; i++ {
@@ -135,6 +148,19 @@ func BenchmarkSortInt1K(b *testing.B) {
}
}
+func BenchmarkStableInt1K(b *testing.B) {
+ b.StopTimer()
+ for i := 0; i < b.N; i++ {
+ data := make([]int, 1<<10)
+ for i := 0; i < len(data); i++ {
+ data[i] = i ^ 0x2cc
+ }
+ b.StartTimer()
+ Stable(IntSlice(data))
+ b.StopTimer()
+ }
+}
+
func BenchmarkSortInt64K(b *testing.B) {
b.StopTimer()
for i := 0; i < b.N; i++ {
@@ -148,6 +174,19 @@ func BenchmarkSortInt64K(b *testing.B) {
}
}
+func BenchmarkStableInt64K(b *testing.B) {
+ b.StopTimer()
+ for i := 0; i < b.N; i++ {
+ data := make([]int, 1<<16)
+ for i := 0; i < len(data); i++ {
+ data[i] = i ^ 0xcccc
+ }
+ b.StartTimer()
+ Stable(IntSlice(data))
+ b.StopTimer()
+ }
+}
+
const (
_Sawtooth = iota
_Rand
@@ -204,7 +243,7 @@ func lg(n int) int {
return i
}
-func testBentleyMcIlroy(t *testing.T, sort func(Interface)) {
+func testBentleyMcIlroy(t *testing.T, sort func(Interface), maxswap func(int) int) {
sizes := []int{100, 1023, 1024, 1025}
if testing.Short() {
sizes = []int{100, 127, 128, 129}
@@ -278,7 +317,7 @@ func testBentleyMcIlroy(t *testing.T, sort func(Interface)) {
}
desc := fmt.Sprintf("n=%d m=%d dist=%s mode=%s", n, m, dists[dist], modes[mode])
- d := &testingData{desc: desc, t: t, data: mdata[0:n], maxswap: n * lg(n) * 12 / 10}
+ d := &testingData{desc: desc, t: t, data: mdata[0:n], maxswap: maxswap(n)}
sort(d)
// Uncomment if you are trying to improve the number of compares/swaps.
//t.Logf("%s: ncmp=%d, nswp=%d", desc, d.ncmp, d.nswap)
@@ -303,11 +342,15 @@ func testBentleyMcIlroy(t *testing.T, sort func(Interface)) {
}
func TestSortBM(t *testing.T) {
- testBentleyMcIlroy(t, Sort)
+ testBentleyMcIlroy(t, Sort, func(n int) int { return n * lg(n) * 12 / 10 })
}
func TestHeapsortBM(t *testing.T) {
- testBentleyMcIlroy(t, Heapsort)
+ testBentleyMcIlroy(t, Heapsort, func(n int) int { return n * lg(n) * 12 / 10 })
+}
+
+func TestStableBM(t *testing.T) {
+ testBentleyMcIlroy(t, Stable, func(n int) int { return n * lg(n) * lg(n) / 3 })
}
// This is based on the "antiquicksort" implementation by M. Douglas McIlroy.
@@ -357,3 +400,154 @@ func TestAdversary(t *testing.T) {
d := &adversaryTestingData{data, make(map[int]int), 0}
Sort(d) // This should degenerate to heapsort.
}
+
+func TestStableInts(t *testing.T) {
+ data := ints
+ Stable(IntSlice(data[0:]))
+ if !IntsAreSorted(data[0:]) {
+ t.Errorf("nsorted %v\n got %v", ints, data)
+ }
+}
+
+type intPairs []struct {
+ a, b int
+}
+
+// IntPairs compare on a only.
+func (d intPairs) Len() int { return len(d) }
+func (d intPairs) Less(i, j int) bool { return d[i].a < d[j].a }
+func (d intPairs) Swap(i, j int) { d[i], d[j] = d[j], d[i] }
+
+// Record initial order in B.
+func (d intPairs) initB() {
+ for i := range d {
+ d[i].b = i
+ }
+}
+
+// InOrder checks if a-equal elements were not reordered.
+func (d intPairs) inOrder() bool {
+ lastA, lastB := -1, 0
+ for i := 0; i < len(d); i++ {
+ if lastA != d[i].a {
+ lastA = d[i].a
+ lastB = d[i].b
+ continue
+ }
+ if d[i].b <= lastB {
+ return false
+ }
+ lastB = d[i].b
+ }
+ return true
+}
+
+func TestStability(t *testing.T) {
+ n, m := 100000, 1000
+ if testing.Short() {
+ n, m = 1000, 100
+ }
+ data := make(intPairs, n)
+
+ // random distribution
+ for i := 0; i < len(data); i++ {
+ data[i].a = rand.Intn(m)
+ }
+ if IsSorted(data) {
+ t.Fatalf("terrible rand.rand")
+ }
+ data.initB()
+ Stable(data)
+ if !IsSorted(data) {
+ t.Errorf("Stable didn't sort %d ints", n)
+ }
+ if !data.inOrder() {
+ t.Errorf("Stable wasn't stable on %d ints", n)
+ }
+
+ // already sorted
+ data.initB()
+ Stable(data)
+ if !IsSorted(data) {
+ t.Errorf("Stable shuffeled sorted %d ints (order)", n)
+ }
+ if !data.inOrder() {
+ t.Errorf("Stable shuffeled sorted %d ints (stability)", n)
+ }
+
+ // sorted reversed
+ for i := 0; i < len(data); i++ {
+ data[i].a = len(data) - i
+ }
+ data.initB()
+ Stable(data)
+ if !IsSorted(data) {
+ t.Errorf("Stable didn't sort %d ints", n)
+ }
+ if !data.inOrder() {
+ t.Errorf("Stable wasn't stable on %d ints", n)
+ }
+}
+
+var countOpsSizes = []int{1e2, 3e2, 1e3, 3e3, 1e4, 3e4, 1e5, 3e5, 1e6}
+
+func countOps(t *testing.T, algo func(Interface), name string) {
+ sizes := countOpsSizes
+ if testing.Short() {
+ sizes = sizes[:5]
+ }
+ if !testing.Verbose() {
+ t.Skip("Counting skipped as non-verbose mode.")
+ }
+ for _, n := range sizes {
+ td := testingData{
+ desc: name,
+ t: t,
+ data: make([]int, n),
+ maxswap: 1<<31 - 1,
+ }
+ for i := 0; i < n; i++ {
+ td.data[i] = rand.Intn(n / 5)
+ }
+ algo(&td)
+ t.Logf("%s %8d elements: %11d Swap, %10d Less", name, n, td.nswap, td.ncmp)
+ }
+}
+
+func TestCountStableOps(t *testing.T) { countOps(t, Stable, "Stable") }
+func TestCountSortOps(t *testing.T) { countOps(t, Sort, "Sort ") }
+
+func bench(b *testing.B, size int, algo func(Interface), name string) {
+ b.StopTimer()
+ data := make(intPairs, size)
+ x := ^uint32(0)
+ for i := 0; i < b.N; i++ {
+ for n := size - 3; n <= size+3; n++ {
+ for i := 0; i < len(data); i++ {
+ x += x
+ x ^= 1
+ if int32(x) < 0 {
+ x ^= 0x88888eef
+ }
+ data[i].a = int(x % uint32(n/5))
+ }
+ data.initB()
+ b.StartTimer()
+ algo(data)
+ b.StopTimer()
+ if !IsSorted(data) {
+ b.Errorf("%s did not sort %d ints", name, n)
+ }
+ if name == "Stable" && !data.inOrder() {
+ b.Errorf("%s unstable on %d ints", name, n)
+ }
+ }
+ }
+}
+
+func BenchmarkSort1e2(b *testing.B) { bench(b, 1e2, Sort, "Sort") }
+func BenchmarkStable1e2(b *testing.B) { bench(b, 1e2, Stable, "Stable") }
+func BenchmarkSort1e4(b *testing.B) { bench(b, 1e4, Sort, "Sort") }
+func BenchmarkStable1e4(b *testing.B) { bench(b, 1e4, Stable, "Stable") }
+func BenchmarkSort1e6(b *testing.B) { bench(b, 1e6, Sort, "Sort") }
+func BenchmarkStable1e6(b *testing.B) { bench(b, 1e6, Stable, "Stable") }
diff --git a/libgo/go/strconv/atof.go b/libgo/go/strconv/atof.go
index c9e243aa06d..1dc521f270c 100644
--- a/libgo/go/strconv/atof.go
+++ b/libgo/go/strconv/atof.go
@@ -542,11 +542,11 @@ func atof64(s string) (f float64, err error) {
// The errors that ParseFloat returns have concrete type *NumError
// and include err.Num = s.
//
-// If s is not syntactically well-formed, ParseFloat returns err.Error = ErrSyntax.
+// If s is not syntactically well-formed, ParseFloat returns err.Err = ErrSyntax.
//
// If s is syntactically well-formed but is more than 1/2 ULP
// away from the largest floating point number of the given size,
-// ParseFloat returns f = ±Inf, err.Error = ErrRange.
+// ParseFloat returns f = ±Inf, err.Err = ErrRange.
func ParseFloat(s string, bitSize int) (f float64, err error) {
if bitSize == 32 {
f1, err1 := atof32(s)
diff --git a/libgo/go/strconv/atoi.go b/libgo/go/strconv/atoi.go
index 21c69009653..2d0db7155f7 100644
--- a/libgo/go/strconv/atoi.go
+++ b/libgo/go/strconv/atoi.go
@@ -33,7 +33,8 @@ func rangeError(fn, str string) *NumError {
const intSize = 32 << uint(^uint(0)>>63)
-const IntSize = intSize // number of bits in int, uint (32 or 64)
+// IntSize is the size in bits of an int or uint value.
+const IntSize = intSize
// Return the first number n such that n*base >= 1<<64.
func cutoff64(base int) uint64 {
@@ -141,9 +142,9 @@ Error:
//
// The errors that ParseInt returns have concrete type *NumError
// and include err.Num = s. If s is empty or contains invalid
-// digits, err.Error = ErrSyntax; if the value corresponding
+// digits, err.Err = ErrSyntax; if the value corresponding
// to s cannot be represented by a signed integer of the
-// given size, err.Error = ErrRange.
+// given size, err.Err = ErrRange.
func ParseInt(s string, base int, bitSize int) (i int64, err error) {
const fnParseInt = "ParseInt"
diff --git a/libgo/go/strconv/quote.go b/libgo/go/strconv/quote.go
index 8cbef88b517..7d6cdcf0b54 100644
--- a/libgo/go/strconv/quote.go
+++ b/libgo/go/strconv/quote.go
@@ -133,7 +133,7 @@ func QuoteRuneToASCII(r rune) string {
return quoteWith(string(r), '\'', true)
}
-// AppendQuoteRune appends a single-quoted Go character literal representing the rune,
+// AppendQuoteRuneToASCII appends a single-quoted Go character literal representing the rune,
// as generated by QuoteRuneToASCII, to dst and returns the extended buffer.
func AppendQuoteRuneToASCII(dst []byte, r rune) []byte {
return append(dst, QuoteRuneToASCII(r)...)
diff --git a/libgo/go/strconv/strconv_test.go b/libgo/go/strconv/strconv_test.go
index 381874b8bb1..207e00e75dc 100644
--- a/libgo/go/strconv/strconv_test.go
+++ b/libgo/go/strconv/strconv_test.go
@@ -46,6 +46,9 @@ var (
)
func TestCountMallocs(t *testing.T) {
+ if testing.Short() {
+ t.Skip("skipping malloc count in short mode")
+ }
if runtime.GOMAXPROCS(0) > 1 {
t.Skip("skipping; GOMAXPROCS>1")
}
diff --git a/libgo/go/strings/indexbyte.c b/libgo/go/strings/indexbyte.c
new file mode 100644
index 00000000000..27f4240b44c
--- /dev/null
+++ b/libgo/go/strings/indexbyte.c
@@ -0,0 +1,29 @@
+/* indexbyte.c -- implement strings.IndexByte for Go.
+
+ Copyright 2013 The Go Authors. All rights reserved.
+ Use of this source code is governed by a BSD-style
+ license that can be found in the LICENSE file. */
+
+#include <stddef.h>
+
+#include "runtime.h"
+#include "go-string.h"
+
+/* This is in C so that the compiler can optimize it appropriately.
+ We deliberately don't split the stack in case it does call the
+ library function, which shouldn't need much stack space. */
+
+intgo IndexByte (String, char)
+ __asm__ (GOSYM_PREFIX "strings.IndexByte")
+ __attribute__ ((no_split_stack));
+
+intgo
+IndexByte (String s, char b)
+{
+ const char *p;
+
+ p = __builtin_memchr ((const char *) s.str, b, s.len);
+ if (p == NULL)
+ return -1;
+ return p - (const char *) s.str;
+}
diff --git a/libgo/go/strings/strings.go b/libgo/go/strings/strings.go
index 986f6d61ebc..5d46211d84e 100644
--- a/libgo/go/strings/strings.go
+++ b/libgo/go/strings/strings.go
@@ -130,14 +130,7 @@ func Index(s, sep string) int {
case n == 0:
return 0
case n == 1:
- c := sep[0]
- // special case worth making fast
- for i := 0; i < len(s); i++ {
- if s[i] == c {
- return i
- }
- }
- return -1
+ return IndexByte(s, sep[0])
case n == len(s):
if sep == s {
return 0
@@ -432,10 +425,7 @@ func Repeat(s string, count int) string {
b := make([]byte, len(s)*count)
bp := 0
for i := 0; i < count; i++ {
- for j := 0; j < len(s); j++ {
- b[bp] = s[j]
- bp++
- }
+ bp += copy(b[bp:], s)
}
return string(b)
}
diff --git a/libgo/go/strings/strings_decl.go b/libgo/go/strings/strings_decl.go
new file mode 100644
index 00000000000..810a696af27
--- /dev/null
+++ b/libgo/go/strings/strings_decl.go
@@ -0,0 +1,8 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package strings
+
+// IndexByte returns the index of the first instance of c in s, or -1 if c is not present in s.
+func IndexByte(s string, c byte) int // ../runtime/asm_$GOARCH.s
diff --git a/libgo/go/strings/strings_test.go b/libgo/go/strings/strings_test.go
index 68b658ca466..df0dd7165ab 100644
--- a/libgo/go/strings/strings_test.go
+++ b/libgo/go/strings/strings_test.go
@@ -168,6 +168,15 @@ func BenchmarkIndex(b *testing.B) {
}
}
+func BenchmarkIndexByte(b *testing.B) {
+ if got := IndexByte(benchmarkString, 'v'); got != 17 {
+ b.Fatalf("wrong index: expected 17, got=%d", got)
+ }
+ for i := 0; i < b.N; i++ {
+ IndexByte(benchmarkString, 'v')
+ }
+}
+
var explodetests = []struct {
s string
n int
@@ -1001,6 +1010,30 @@ func TestEqualFold(t *testing.T) {
}
}
+var CountTests = []struct {
+ s, sep string
+ num int
+}{
+ {"", "", 1},
+ {"", "notempty", 0},
+ {"notempty", "", 9},
+ {"smaller", "not smaller", 0},
+ {"12345678987654321", "6", 2},
+ {"611161116", "6", 3},
+ {"notequal", "NotEqual", 0},
+ {"equal", "equal", 1},
+ {"abc1231231123q", "123", 3},
+ {"11111", "11", 2},
+}
+
+func TestCount(t *testing.T) {
+ for _, tt := range CountTests {
+ if num := Count(tt.s, tt.sep); num != tt.num {
+ t.Errorf("Count(\"%s\", \"%s\") = %d, want %d", tt.s, tt.sep, num, tt.num)
+ }
+ }
+}
+
func makeBenchInputHard() string {
tokens := [...]string{
"<a>", "<p>", "<b>", "<strong>",
diff --git a/libgo/go/sync/atomic/64bit_arm.go b/libgo/go/sync/atomic/64bit_arm.go
index f070e78bd3c..c08f214c7ef 100644
--- a/libgo/go/sync/atomic/64bit_arm.go
+++ b/libgo/go/sync/atomic/64bit_arm.go
@@ -34,3 +34,13 @@ func addUint64(val *uint64, delta uint64) (new uint64) {
}
return
}
+
+func swapUint64(addr *uint64, new uint64) (old uint64) {
+ for {
+ old = *addr
+ if CompareAndSwapUint64(addr, old, new) {
+ break
+ }
+ }
+ return
+}
diff --git a/libgo/go/sync/atomic/atomic.c b/libgo/go/sync/atomic/atomic.c
index 32430df2ba2..f0ba57b3cca 100644
--- a/libgo/go/sync/atomic/atomic.c
+++ b/libgo/go/sync/atomic/atomic.c
@@ -8,8 +8,69 @@
#include "runtime.h"
+int32_t SwapInt32 (int32_t *, int32_t)
+ __asm__ (GOSYM_PREFIX "sync_atomic.SwapInt32")
+ __attribute__ ((no_split_stack));
+
+int32_t
+SwapInt32 (int32_t *addr, int32_t new)
+{
+ return __atomic_exchange_n (addr, new, __ATOMIC_SEQ_CST);
+}
+
+int64_t SwapInt64 (int64_t *, int64_t)
+ __asm__ (GOSYM_PREFIX "sync_atomic.SwapInt64")
+ __attribute__ ((no_split_stack));
+
+int64_t
+SwapInt64 (int64_t *addr, int64_t new)
+{
+ return __atomic_exchange_n (addr, new, __ATOMIC_SEQ_CST);
+}
+
+uint32_t SwapUint32 (uint32_t *, uint32_t)
+ __asm__ (GOSYM_PREFIX "sync_atomic.SwapUint32")
+ __attribute__ ((no_split_stack));
+
+uint32_t
+SwapUint32 (uint32_t *addr, uint32_t new)
+{
+ return __atomic_exchange_n (addr, new, __ATOMIC_SEQ_CST);
+}
+
+uint64_t SwapUint64 (uint64_t *, uint64_t)
+ __asm__ (GOSYM_PREFIX "sync_atomic.SwapUint64")
+ __attribute__ ((no_split_stack));
+
+uint64_t
+SwapUint64 (uint64_t *addr, uint64_t new)
+{
+ return __atomic_exchange_n (addr, new, __ATOMIC_SEQ_CST);
+}
+
+uintptr_t SwapUintptr (uintptr_t *, uintptr_t)
+ __asm__ (GOSYM_PREFIX "sync_atomic.SwapUintptr")
+ __attribute__ ((no_split_stack));
+
+uintptr_t
+SwapUintptr (uintptr_t *addr, uintptr_t new)
+{
+ return __atomic_exchange_n (addr, new, __ATOMIC_SEQ_CST);
+}
+
+void *SwapPointer (void **, void *)
+ __asm__ (GOSYM_PREFIX "sync_atomic.SwapPointer")
+ __attribute__ ((no_split_stack));
+
+void *
+SwapPointer (void **addr, void *new)
+{
+ return __atomic_exchange_n (addr, new, __ATOMIC_SEQ_CST);
+}
+
_Bool CompareAndSwapInt32 (int32_t *, int32_t, int32_t)
- __asm__ (GOSYM_PREFIX "sync_atomic.CompareAndSwapInt32");
+ __asm__ (GOSYM_PREFIX "sync_atomic.CompareAndSwapInt32")
+ __attribute__ ((no_split_stack));
_Bool
CompareAndSwapInt32 (int32_t *val, int32_t old, int32_t new)
@@ -18,7 +79,8 @@ CompareAndSwapInt32 (int32_t *val, int32_t old, int32_t new)
}
_Bool CompareAndSwapInt64 (int64_t *, int64_t, int64_t)
- __asm__ (GOSYM_PREFIX "sync_atomic.CompareAndSwapInt64");
+ __asm__ (GOSYM_PREFIX "sync_atomic.CompareAndSwapInt64")
+ __attribute__ ((no_split_stack));
_Bool
CompareAndSwapInt64 (int64_t *val, int64_t old, int64_t new)
@@ -27,7 +89,8 @@ CompareAndSwapInt64 (int64_t *val, int64_t old, int64_t new)
}
_Bool CompareAndSwapUint32 (uint32_t *, uint32_t, uint32_t)
- __asm__ (GOSYM_PREFIX "sync_atomic.CompareAndSwapUint32");
+ __asm__ (GOSYM_PREFIX "sync_atomic.CompareAndSwapUint32")
+ __attribute__ ((no_split_stack));
_Bool
CompareAndSwapUint32 (uint32_t *val, uint32_t old, uint32_t new)
@@ -36,7 +99,8 @@ CompareAndSwapUint32 (uint32_t *val, uint32_t old, uint32_t new)
}
_Bool CompareAndSwapUint64 (uint64_t *, uint64_t, uint64_t)
- __asm__ (GOSYM_PREFIX "sync_atomic.CompareAndSwapUint64");
+ __asm__ (GOSYM_PREFIX "sync_atomic.CompareAndSwapUint64")
+ __attribute__ ((no_split_stack));
_Bool
CompareAndSwapUint64 (uint64_t *val, uint64_t old, uint64_t new)
@@ -45,7 +109,8 @@ CompareAndSwapUint64 (uint64_t *val, uint64_t old, uint64_t new)
}
_Bool CompareAndSwapUintptr (uintptr_t *, uintptr_t, uintptr_t)
- __asm__ (GOSYM_PREFIX "sync_atomic.CompareAndSwapUintptr");
+ __asm__ (GOSYM_PREFIX "sync_atomic.CompareAndSwapUintptr")
+ __attribute__ ((no_split_stack));
_Bool
CompareAndSwapUintptr (uintptr_t *val, uintptr_t old, uintptr_t new)
@@ -54,7 +119,8 @@ CompareAndSwapUintptr (uintptr_t *val, uintptr_t old, uintptr_t new)
}
_Bool CompareAndSwapPointer (void **, void *, void *)
- __asm__ (GOSYM_PREFIX "sync_atomic.CompareAndSwapPointer");
+ __asm__ (GOSYM_PREFIX "sync_atomic.CompareAndSwapPointer")
+ __attribute__ ((no_split_stack));
_Bool
CompareAndSwapPointer (void **val, void *old, void *new)
@@ -63,7 +129,8 @@ CompareAndSwapPointer (void **val, void *old, void *new)
}
int32_t AddInt32 (int32_t *, int32_t)
- __asm__ (GOSYM_PREFIX "sync_atomic.AddInt32");
+ __asm__ (GOSYM_PREFIX "sync_atomic.AddInt32")
+ __attribute__ ((no_split_stack));
int32_t
AddInt32 (int32_t *val, int32_t delta)
@@ -72,7 +139,8 @@ AddInt32 (int32_t *val, int32_t delta)
}
uint32_t AddUint32 (uint32_t *, uint32_t)
- __asm__ (GOSYM_PREFIX "sync_atomic.AddUint32");
+ __asm__ (GOSYM_PREFIX "sync_atomic.AddUint32")
+ __attribute__ ((no_split_stack));
uint32_t
AddUint32 (uint32_t *val, uint32_t delta)
@@ -81,7 +149,8 @@ AddUint32 (uint32_t *val, uint32_t delta)
}
int64_t AddInt64 (int64_t *, int64_t)
- __asm__ (GOSYM_PREFIX "sync_atomic.AddInt64");
+ __asm__ (GOSYM_PREFIX "sync_atomic.AddInt64")
+ __attribute__ ((no_split_stack));
int64_t
AddInt64 (int64_t *val, int64_t delta)
@@ -90,7 +159,8 @@ AddInt64 (int64_t *val, int64_t delta)
}
uint64_t AddUint64 (uint64_t *, uint64_t)
- __asm__ (GOSYM_PREFIX "sync_atomic.AddUint64");
+ __asm__ (GOSYM_PREFIX "sync_atomic.AddUint64")
+ __attribute__ ((no_split_stack));
uint64_t
AddUint64 (uint64_t *val, uint64_t delta)
@@ -99,7 +169,8 @@ AddUint64 (uint64_t *val, uint64_t delta)
}
uintptr_t AddUintptr (uintptr_t *, uintptr_t)
- __asm__ (GOSYM_PREFIX "sync_atomic.AddUintptr");
+ __asm__ (GOSYM_PREFIX "sync_atomic.AddUintptr")
+ __attribute__ ((no_split_stack));
uintptr_t
AddUintptr (uintptr_t *val, uintptr_t delta)
@@ -108,7 +179,8 @@ AddUintptr (uintptr_t *val, uintptr_t delta)
}
int32_t LoadInt32 (int32_t *addr)
- __asm__ (GOSYM_PREFIX "sync_atomic.LoadInt32");
+ __asm__ (GOSYM_PREFIX "sync_atomic.LoadInt32")
+ __attribute__ ((no_split_stack));
int32_t
LoadInt32 (int32_t *addr)
@@ -122,7 +194,8 @@ LoadInt32 (int32_t *addr)
}
int64_t LoadInt64 (int64_t *addr)
- __asm__ (GOSYM_PREFIX "sync_atomic.LoadInt64");
+ __asm__ (GOSYM_PREFIX "sync_atomic.LoadInt64")
+ __attribute__ ((no_split_stack));
int64_t
LoadInt64 (int64_t *addr)
@@ -136,7 +209,8 @@ LoadInt64 (int64_t *addr)
}
uint32_t LoadUint32 (uint32_t *addr)
- __asm__ (GOSYM_PREFIX "sync_atomic.LoadUint32");
+ __asm__ (GOSYM_PREFIX "sync_atomic.LoadUint32")
+ __attribute__ ((no_split_stack));
uint32_t
LoadUint32 (uint32_t *addr)
@@ -150,7 +224,8 @@ LoadUint32 (uint32_t *addr)
}
uint64_t LoadUint64 (uint64_t *addr)
- __asm__ (GOSYM_PREFIX "sync_atomic.LoadUint64");
+ __asm__ (GOSYM_PREFIX "sync_atomic.LoadUint64")
+ __attribute__ ((no_split_stack));
uint64_t
LoadUint64 (uint64_t *addr)
@@ -164,7 +239,8 @@ LoadUint64 (uint64_t *addr)
}
uintptr_t LoadUintptr (uintptr_t *addr)
- __asm__ (GOSYM_PREFIX "sync_atomic.LoadUintptr");
+ __asm__ (GOSYM_PREFIX "sync_atomic.LoadUintptr")
+ __attribute__ ((no_split_stack));
uintptr_t
LoadUintptr (uintptr_t *addr)
@@ -178,7 +254,8 @@ LoadUintptr (uintptr_t *addr)
}
void *LoadPointer (void **addr)
- __asm__ (GOSYM_PREFIX "sync_atomic.LoadPointer");
+ __asm__ (GOSYM_PREFIX "sync_atomic.LoadPointer")
+ __attribute__ ((no_split_stack));
void *
LoadPointer (void **addr)
@@ -192,7 +269,8 @@ LoadPointer (void **addr)
}
void StoreInt32 (int32_t *addr, int32_t val)
- __asm__ (GOSYM_PREFIX "sync_atomic.StoreInt32");
+ __asm__ (GOSYM_PREFIX "sync_atomic.StoreInt32")
+ __attribute__ ((no_split_stack));
void
StoreInt32 (int32_t *addr, int32_t val)
@@ -205,7 +283,8 @@ StoreInt32 (int32_t *addr, int32_t val)
}
void StoreInt64 (int64_t *addr, int64_t val)
- __asm__ (GOSYM_PREFIX "sync_atomic.StoreInt64");
+ __asm__ (GOSYM_PREFIX "sync_atomic.StoreInt64")
+ __attribute__ ((no_split_stack));
void
StoreInt64 (int64_t *addr, int64_t val)
@@ -218,7 +297,8 @@ StoreInt64 (int64_t *addr, int64_t val)
}
void StoreUint32 (uint32_t *addr, uint32_t val)
- __asm__ (GOSYM_PREFIX "sync_atomic.StoreUint32");
+ __asm__ (GOSYM_PREFIX "sync_atomic.StoreUint32")
+ __attribute__ ((no_split_stack));
void
StoreUint32 (uint32_t *addr, uint32_t val)
@@ -231,7 +311,8 @@ StoreUint32 (uint32_t *addr, uint32_t val)
}
void StoreUint64 (uint64_t *addr, uint64_t val)
- __asm__ (GOSYM_PREFIX "sync_atomic.StoreUint64");
+ __asm__ (GOSYM_PREFIX "sync_atomic.StoreUint64")
+ __attribute__ ((no_split_stack));
void
StoreUint64 (uint64_t *addr, uint64_t val)
@@ -244,7 +325,8 @@ StoreUint64 (uint64_t *addr, uint64_t val)
}
void StoreUintptr (uintptr_t *addr, uintptr_t val)
- __asm__ (GOSYM_PREFIX "sync_atomic.StoreUintptr");
+ __asm__ (GOSYM_PREFIX "sync_atomic.StoreUintptr")
+ __attribute__ ((no_split_stack));
void
StoreUintptr (uintptr_t *addr, uintptr_t val)
@@ -257,7 +339,8 @@ StoreUintptr (uintptr_t *addr, uintptr_t val)
}
void StorePointer (void **addr, void *val)
- __asm__ (GOSYM_PREFIX "sync_atomic.StorePointer");
+ __asm__ (GOSYM_PREFIX "sync_atomic.StorePointer")
+ __attribute__ ((no_split_stack));
void
StorePointer (void **addr, void *val)
diff --git a/libgo/go/sync/atomic/atomic_test.go b/libgo/go/sync/atomic/atomic_test.go
index c6c33dc3c69..06dd5f7ce89 100644
--- a/libgo/go/sync/atomic/atomic_test.go
+++ b/libgo/go/sync/atomic/atomic_test.go
@@ -5,7 +5,9 @@
package atomic_test
import (
+ "fmt"
"runtime"
+ "strings"
. "sync/atomic"
"testing"
"unsafe"
@@ -38,6 +40,142 @@ var test64err = func() (err interface{}) {
return nil
}()
+func TestSwapInt32(t *testing.T) {
+ var x struct {
+ before int32
+ i int32
+ after int32
+ }
+ x.before = magic32
+ x.after = magic32
+ var j int32
+ for delta := int32(1); delta+delta > delta; delta += delta {
+ k := SwapInt32(&x.i, delta)
+ if x.i != delta || k != j {
+ t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
+ }
+ j = delta
+ }
+ if x.before != magic32 || x.after != magic32 {
+ t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
+ }
+}
+
+func TestSwapUint32(t *testing.T) {
+ var x struct {
+ before uint32
+ i uint32
+ after uint32
+ }
+ x.before = magic32
+ x.after = magic32
+ var j uint32
+ for delta := uint32(1); delta+delta > delta; delta += delta {
+ k := SwapUint32(&x.i, delta)
+ if x.i != delta || k != j {
+ t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
+ }
+ j = delta
+ }
+ if x.before != magic32 || x.after != magic32 {
+ t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
+ }
+}
+
+func TestSwapInt64(t *testing.T) {
+ if test64err != nil {
+ t.Skipf("Skipping 64-bit tests: %v", test64err)
+ }
+ var x struct {
+ before int64
+ i int64
+ after int64
+ }
+ x.before = magic64
+ x.after = magic64
+ var j int64
+ for delta := int64(1); delta+delta > delta; delta += delta {
+ k := SwapInt64(&x.i, delta)
+ if x.i != delta || k != j {
+ t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
+ }
+ j = delta
+ }
+ if x.before != magic64 || x.after != magic64 {
+ t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uint64(magic64), uint64(magic64))
+ }
+}
+
+func TestSwapUint64(t *testing.T) {
+ if test64err != nil {
+ t.Skipf("Skipping 64-bit tests: %v", test64err)
+ }
+ var x struct {
+ before uint64
+ i uint64
+ after uint64
+ }
+ x.before = magic64
+ x.after = magic64
+ var j uint64
+ for delta := uint64(1); delta+delta > delta; delta += delta {
+ k := SwapUint64(&x.i, delta)
+ if x.i != delta || k != j {
+ t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
+ }
+ j = delta
+ }
+ if x.before != magic64 || x.after != magic64 {
+ t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uint64(magic64), uint64(magic64))
+ }
+}
+
+func TestSwapUintptr(t *testing.T) {
+ var x struct {
+ before uintptr
+ i uintptr
+ after uintptr
+ }
+ var m uint64 = magic64
+ magicptr := uintptr(m)
+ x.before = magicptr
+ x.after = magicptr
+ var j uintptr
+ for delta := uintptr(1); delta+delta > delta; delta += delta {
+ k := SwapUintptr(&x.i, delta)
+ if x.i != delta || k != j {
+ t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
+ }
+ j = delta
+ }
+ if x.before != magicptr || x.after != magicptr {
+ t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
+ }
+}
+
+func TestSwapPointer(t *testing.T) {
+ var x struct {
+ before uintptr
+ i unsafe.Pointer
+ after uintptr
+ }
+ var m uint64 = magic64
+ magicptr := uintptr(m)
+ x.before = magicptr
+ x.after = magicptr
+ var j uintptr
+ for delta := uintptr(1); delta+delta > delta; delta += delta {
+ k := SwapPointer(&x.i, unsafe.Pointer(delta))
+ if uintptr(x.i) != delta || uintptr(k) != j {
+ t.Fatalf("delta=%d i=%d j=%d k=%d", delta, x.i, j, k)
+ }
+ j = delta
+ }
+ if x.before != magicptr || x.after != magicptr {
+ t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
+ }
+}
+
func TestAddInt32(t *testing.T) {
var x struct {
before int32
@@ -241,7 +379,7 @@ func TestCompareAndSwapInt64(t *testing.T) {
}
}
-func TestCompareAndSwapUint64(t *testing.T) {
+func testCompareAndSwapUint64(t *testing.T, cas func(*uint64, uint64, uint64) bool) {
if test64err != nil {
t.Skipf("Skipping 64-bit tests: %v", test64err)
}
@@ -254,14 +392,14 @@ func TestCompareAndSwapUint64(t *testing.T) {
x.after = magic64
for val := uint64(1); val+val > val; val += val {
x.i = val
- if !CompareAndSwapUint64(&x.i, val, val+1) {
+ if !cas(&x.i, val, val+1) {
t.Fatalf("should have swapped %#x %#x", val, val+1)
}
if x.i != val+1 {
t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
}
x.i = val + 1
- if CompareAndSwapUint64(&x.i, val, val+2) {
+ if cas(&x.i, val, val+2) {
t.Fatalf("should not have swapped %#x %#x", val, val+2)
}
if x.i != val+1 {
@@ -273,6 +411,10 @@ func TestCompareAndSwapUint64(t *testing.T) {
}
}
+func TestCompareAndSwapUint64(t *testing.T) {
+ testCompareAndSwapUint64(t, CompareAndSwapUint64)
+}
+
func TestCompareAndSwapUintptr(t *testing.T) {
var x struct {
before uintptr
@@ -608,27 +750,85 @@ func TestStorePointer(t *testing.T) {
// uses the atomic operation to add 1 to a value. After running
// multiple hammers in parallel, check that we end with the correct
// total.
-
-var hammer32 = []struct {
- name string
- f func(*uint32, int)
-}{
- {"AddInt32", hammerAddInt32},
- {"AddUint32", hammerAddUint32},
- {"AddUintptr", hammerAddUintptr32},
- {"CompareAndSwapInt32", hammerCompareAndSwapInt32},
- {"CompareAndSwapUint32", hammerCompareAndSwapUint32},
- {"CompareAndSwapUintptr", hammerCompareAndSwapUintptr32},
- {"CompareAndSwapPointer", hammerCompareAndSwapPointer32},
+// Swap can't add 1, so it uses a different scheme.
+// The functions repeatedly generate a pseudo-random number such that
+// low bits are equal to high bits, swap, check that the old value
+// has low and high bits equal.
+
+var hammer32 = map[string]func(*uint32, int){
+ "SwapInt32": hammerSwapInt32,
+ "SwapUint32": hammerSwapUint32,
+ "SwapUintptr": hammerSwapUintptr32,
+ "SwapPointer": hammerSwapPointer32,
+ "AddInt32": hammerAddInt32,
+ "AddUint32": hammerAddUint32,
+ "AddUintptr": hammerAddUintptr32,
+ "CompareAndSwapInt32": hammerCompareAndSwapInt32,
+ "CompareAndSwapUint32": hammerCompareAndSwapUint32,
+ "CompareAndSwapUintptr": hammerCompareAndSwapUintptr32,
+ "CompareAndSwapPointer": hammerCompareAndSwapPointer32,
}
func init() {
var v uint64 = 1 << 50
if uintptr(v) != 0 {
// 64-bit system; clear uintptr tests
- hammer32[2].f = nil
- hammer32[5].f = nil
- hammer32[6].f = nil
+ delete(hammer32, "SwapUintptr")
+ delete(hammer32, "SwapPointer")
+ delete(hammer32, "AddUintptr")
+ delete(hammer32, "CompareAndSwapUintptr")
+ delete(hammer32, "CompareAndSwapPointer")
+ }
+}
+
+func hammerSwapInt32(uaddr *uint32, count int) {
+ addr := (*int32)(unsafe.Pointer(uaddr))
+ seed := int(uintptr(unsafe.Pointer(&count)))
+ for i := 0; i < count; i++ {
+ new := uint32(seed+i)<<16 | uint32(seed+i)<<16>>16
+ old := uint32(SwapInt32(addr, int32(new)))
+ if old>>16 != old<<16>>16 {
+ panic(fmt.Sprintf("SwapInt32 is not atomic: %v", old))
+ }
+ }
+}
+
+func hammerSwapUint32(addr *uint32, count int) {
+ seed := int(uintptr(unsafe.Pointer(&count)))
+ for i := 0; i < count; i++ {
+ new := uint32(seed+i)<<16 | uint32(seed+i)<<16>>16
+ old := SwapUint32(addr, new)
+ if old>>16 != old<<16>>16 {
+ panic(fmt.Sprintf("SwapUint32 is not atomic: %v", old))
+ }
+ }
+}
+
+func hammerSwapUintptr32(uaddr *uint32, count int) {
+ // only safe when uintptr is 32-bit.
+ // not called on 64-bit systems.
+ addr := (*uintptr)(unsafe.Pointer(uaddr))
+ seed := int(uintptr(unsafe.Pointer(&count)))
+ for i := 0; i < count; i++ {
+ new := uintptr(seed+i)<<16 | uintptr(seed+i)<<16>>16
+ old := SwapUintptr(addr, new)
+ if old>>16 != old<<16>>16 {
+ panic(fmt.Sprintf("SwapUintptr is not atomic: %v", old))
+ }
+ }
+}
+
+func hammerSwapPointer32(uaddr *uint32, count int) {
+ // only safe when uintptr is 32-bit.
+ // not called on 64-bit systems.
+ addr := (*unsafe.Pointer)(unsafe.Pointer(uaddr))
+ seed := int(uintptr(unsafe.Pointer(&count)))
+ for i := 0; i < count; i++ {
+ new := uintptr(seed+i)<<16 | uintptr(seed+i)<<16>>16
+ old := uintptr(SwapPointer(addr, unsafe.Pointer(new)))
+ if old>>16 != old<<16>>16 {
+ panic(fmt.Sprintf("SwapPointer is not atomic: %v", old))
+ }
}
}
@@ -713,47 +913,103 @@ func TestHammer32(t *testing.T) {
}
defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(p))
- for _, tt := range hammer32 {
- if tt.f == nil {
- continue
- }
+ for name, testf := range hammer32 {
c := make(chan int)
var val uint32
for i := 0; i < p; i++ {
go func() {
- tt.f(&val, n)
- c <- 1
+ defer func() {
+ if err := recover(); err != nil {
+ t.Error(err.(string))
+ }
+ c <- 1
+ }()
+ testf(&val, n)
}()
}
for i := 0; i < p; i++ {
<-c
}
- if val != uint32(n)*p {
- t.Fatalf("%s: val=%d want %d", tt.name, val, n*p)
+ if !strings.HasPrefix(name, "Swap") && val != uint32(n)*p {
+ t.Fatalf("%s: val=%d want %d", name, val, n*p)
}
}
}
-var hammer64 = []struct {
- name string
- f func(*uint64, int)
-}{
- {"AddInt64", hammerAddInt64},
- {"AddUint64", hammerAddUint64},
- {"AddUintptr", hammerAddUintptr64},
- {"CompareAndSwapInt64", hammerCompareAndSwapInt64},
- {"CompareAndSwapUint64", hammerCompareAndSwapUint64},
- {"CompareAndSwapUintptr", hammerCompareAndSwapUintptr64},
- {"CompareAndSwapPointer", hammerCompareAndSwapPointer64},
+var hammer64 = map[string]func(*uint64, int){
+ "SwapInt64": hammerSwapInt64,
+ "SwapUint64": hammerSwapUint64,
+ "SwapUintptr": hammerSwapUintptr64,
+ "SwapPointer": hammerSwapPointer64,
+ "AddInt64": hammerAddInt64,
+ "AddUint64": hammerAddUint64,
+ "AddUintptr": hammerAddUintptr64,
+ "CompareAndSwapInt64": hammerCompareAndSwapInt64,
+ "CompareAndSwapUint64": hammerCompareAndSwapUint64,
+ "CompareAndSwapUintptr": hammerCompareAndSwapUintptr64,
+ "CompareAndSwapPointer": hammerCompareAndSwapPointer64,
}
func init() {
var v uint64 = 1 << 50
if uintptr(v) == 0 {
// 32-bit system; clear uintptr tests
- hammer64[2].f = nil
- hammer64[5].f = nil
- hammer64[6].f = nil
+ delete(hammer64, "SwapUintptr")
+ delete(hammer64, "SwapPointer")
+ delete(hammer64, "AddUintptr")
+ delete(hammer64, "CompareAndSwapUintptr")
+ delete(hammer64, "CompareAndSwapPointer")
+ }
+}
+
+func hammerSwapInt64(uaddr *uint64, count int) {
+ addr := (*int64)(unsafe.Pointer(uaddr))
+ seed := int(uintptr(unsafe.Pointer(&count)))
+ for i := 0; i < count; i++ {
+ new := uint64(seed+i)<<32 | uint64(seed+i)<<32>>32
+ old := uint64(SwapInt64(addr, int64(new)))
+ if old>>32 != old<<32>>32 {
+ panic(fmt.Sprintf("SwapInt64 is not atomic: %v", old))
+ }
+ }
+}
+
+func hammerSwapUint64(addr *uint64, count int) {
+ seed := int(uintptr(unsafe.Pointer(&count)))
+ for i := 0; i < count; i++ {
+ new := uint64(seed+i)<<32 | uint64(seed+i)<<32>>32
+ old := SwapUint64(addr, new)
+ if old>>32 != old<<32>>32 {
+ panic(fmt.Sprintf("SwapUint64 is not atomic: %v", old))
+ }
+ }
+}
+
+func hammerSwapUintptr64(uaddr *uint64, count int) {
+ // only safe when uintptr is 64-bit.
+ // not called on 32-bit systems.
+ addr := (*uintptr)(unsafe.Pointer(uaddr))
+ seed := int(uintptr(unsafe.Pointer(&count)))
+ for i := 0; i < count; i++ {
+ new := uintptr(seed+i)<<32 | uintptr(seed+i)<<32>>32
+ old := SwapUintptr(addr, new)
+ if old>>32 != old<<32>>32 {
+ panic(fmt.Sprintf("SwapUintptr is not atomic: %v", old))
+ }
+ }
+}
+
+func hammerSwapPointer64(uaddr *uint64, count int) {
+ // only safe when uintptr is 64-bit.
+ // not called on 32-bit systems.
+ addr := (*unsafe.Pointer)(unsafe.Pointer(uaddr))
+ seed := int(uintptr(unsafe.Pointer(&count)))
+ for i := 0; i < count; i++ {
+ new := uintptr(seed+i)<<32 | uintptr(seed+i)<<32>>32
+ old := uintptr(SwapPointer(addr, unsafe.Pointer(new)))
+ if old>>32 != old<<32>>32 {
+ panic(fmt.Sprintf("SwapPointer is not atomic: %v", old))
+ }
}
}
@@ -841,23 +1097,25 @@ func TestHammer64(t *testing.T) {
}
defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(p))
- for _, tt := range hammer64 {
- if tt.f == nil {
- continue
- }
+ for name, testf := range hammer64 {
c := make(chan int)
var val uint64
for i := 0; i < p; i++ {
go func() {
- tt.f(&val, n)
- c <- 1
+ defer func() {
+ if err := recover(); err != nil {
+ t.Error(err.(string))
+ }
+ c <- 1
+ }()
+ testf(&val, n)
}()
}
for i := 0; i < p; i++ {
<-c
}
- if val != uint64(n)*p {
- t.Fatalf("%s: val=%d want %d", tt.name, val, n*p)
+ if !strings.HasPrefix(name, "Swap") && val != uint64(n)*p {
+ t.Fatalf("%s: val=%d want %d", name, val, n*p)
}
}
}
@@ -1205,3 +1463,46 @@ func TestUnaligned64(t *testing.T) {
shouldPanic(t, "CompareAndSwapUint64", func() { CompareAndSwapUint64(p, 1, 2) })
shouldPanic(t, "AddUint64", func() { AddUint64(p, 3) })
}
+
+func TestNilDeref(t *testing.T) {
+ funcs := [...]func(){
+ func() { CompareAndSwapInt32(nil, 0, 0) },
+ func() { CompareAndSwapInt64(nil, 0, 0) },
+ func() { CompareAndSwapUint32(nil, 0, 0) },
+ func() { CompareAndSwapUint64(nil, 0, 0) },
+ func() { CompareAndSwapUintptr(nil, 0, 0) },
+ func() { CompareAndSwapPointer(nil, nil, nil) },
+ func() { SwapInt32(nil, 0) },
+ func() { SwapUint32(nil, 0) },
+ func() { SwapInt64(nil, 0) },
+ func() { SwapUint64(nil, 0) },
+ func() { SwapUintptr(nil, 0) },
+ func() { SwapPointer(nil, nil) },
+ func() { AddInt32(nil, 0) },
+ func() { AddUint32(nil, 0) },
+ func() { AddInt64(nil, 0) },
+ func() { AddUint64(nil, 0) },
+ func() { AddUintptr(nil, 0) },
+ func() { LoadInt32(nil) },
+ func() { LoadInt64(nil) },
+ func() { LoadUint32(nil) },
+ func() { LoadUint64(nil) },
+ func() { LoadUintptr(nil) },
+ func() { LoadPointer(nil) },
+ func() { StoreInt32(nil, 0) },
+ func() { StoreInt64(nil, 0) },
+ func() { StoreUint32(nil, 0) },
+ func() { StoreUint64(nil, 0) },
+ func() { StoreUintptr(nil, 0) },
+ func() { StorePointer(nil, nil) },
+ }
+ for _, f := range funcs {
+ func() {
+ defer func() {
+ runtime.GC()
+ recover()
+ }()
+ f()
+ }()
+ }
+}
diff --git a/libgo/go/sync/atomic/doc.go b/libgo/go/sync/atomic/doc.go
index 27a12c98488..17ba72fa171 100644
--- a/libgo/go/sync/atomic/doc.go
+++ b/libgo/go/sync/atomic/doc.go
@@ -13,6 +13,13 @@
// Share memory by communicating;
// don't communicate by sharing memory.
//
+// The swap operation, implemented by the SwapT functions, is the atomic
+// equivalent of:
+//
+// old = *addr
+// *addr = new
+// return old
+//
// The compare-and-swap operation, implemented by the CompareAndSwapT
// functions, is the atomic equivalent of:
//
@@ -40,11 +47,31 @@ import (
// BUG(rsc): On x86-32, the 64-bit functions use instructions unavailable before the Pentium MMX.
//
+// On non-Linux ARM, the 64-bit functions use instructions unavailable before the ARMv6k core.
+//
// On both ARM and x86-32, it is the caller's responsibility to arrange for 64-bit
// alignment of 64-bit words accessed atomically. The first word in a global
// variable or in an allocated struct or slice can be relied upon to be
// 64-bit aligned.
+// SwapInt32 atomically stores new into *addr and returns the previous *addr value.
+func SwapInt32(addr *int32, new int32) (old int32)
+
+// SwapInt64 atomically stores new into *addr and returns the previous *addr value.
+func SwapInt64(addr *int64, new int64) (old int64)
+
+// SwapUint32 atomically stores new into *addr and returns the previous *addr value.
+func SwapUint32(addr *uint32, new uint32) (old uint32)
+
+// SwapUint64 atomically stores new into *addr and returns the previous *addr value.
+func SwapUint64(addr *uint64, new uint64) (old uint64)
+
+// SwapUintptr atomically stores new into *addr and returns the previous *addr value.
+func SwapUintptr(addr *uintptr, new uintptr) (old uintptr)
+
+// SwapPointer atomically stores new into *addr and returns the previous *addr value.
+func SwapPointer(addr *unsafe.Pointer, new unsafe.Pointer) (old unsafe.Pointer)
+
// CompareAndSwapInt32 executes the compare-and-swap operation for an int32 value.
func CompareAndSwapInt32(addr *int32, old, new int32) (swapped bool)
@@ -67,12 +94,16 @@ func CompareAndSwapPointer(addr *unsafe.Pointer, old, new unsafe.Pointer) (swapp
func AddInt32(addr *int32, delta int32) (new int32)
// AddUint32 atomically adds delta to *addr and returns the new value.
+// To subtract a signed positive constant value c from x, do AddUint32(&x, ^uint32(c-1)).
+// In particular, to decrement x, do AddUint32(&x, ^uint32(0)).
func AddUint32(addr *uint32, delta uint32) (new uint32)
// AddInt64 atomically adds delta to *addr and returns the new value.
func AddInt64(addr *int64, delta int64) (new int64)
// AddUint64 atomically adds delta to *addr and returns the new value.
+// To subtract a signed positive constant value c from x, do AddUint64(&x, ^uint64(c-1)).
+// In particular, to decrement x, do AddUint64(&x, ^uint64(0)).
func AddUint64(addr *uint64, delta uint64) (new uint64)
// AddUintptr atomically adds delta to *addr and returns the new value.
diff --git a/libgo/go/sync/atomic/race.go b/libgo/go/sync/atomic/race.go
index 2320b57070e..6cbbf12cb64 100644
--- a/libgo/go/sync/atomic/race.go
+++ b/libgo/go/sync/atomic/race.go
@@ -20,6 +20,54 @@ import (
var mtx uint32 = 1 // same for all
+func SwapInt32(addr *int32, new int32) (old int32) {
+ return int32(SwapUint32((*uint32)(unsafe.Pointer(addr)), uint32(new)))
+}
+
+func SwapUint32(addr *uint32, new uint32) (old uint32) {
+ _ = *addr
+ runtime.RaceSemacquire(&mtx)
+ runtime.RaceRead(unsafe.Pointer(addr))
+ runtime.RaceAcquire(unsafe.Pointer(addr))
+ old = *addr
+ *addr = new
+ runtime.RaceReleaseMerge(unsafe.Pointer(addr))
+ runtime.RaceSemrelease(&mtx)
+ return
+}
+
+func SwapInt64(addr *int64, new int64) (old int64) {
+ return int64(SwapUint64((*uint64)(unsafe.Pointer(addr)), uint64(new)))
+}
+
+func SwapUint64(addr *uint64, new uint64) (old uint64) {
+ _ = *addr
+ runtime.RaceSemacquire(&mtx)
+ runtime.RaceRead(unsafe.Pointer(addr))
+ runtime.RaceAcquire(unsafe.Pointer(addr))
+ old = *addr
+ *addr = new
+ runtime.RaceReleaseMerge(unsafe.Pointer(addr))
+ runtime.RaceSemrelease(&mtx)
+ return
+}
+
+func SwapUintptr(addr *uintptr, new uintptr) (old uintptr) {
+ return uintptr(SwapPointer((*unsafe.Pointer)(unsafe.Pointer(addr)), unsafe.Pointer(new)))
+}
+
+func SwapPointer(addr *unsafe.Pointer, new unsafe.Pointer) (old unsafe.Pointer) {
+ _ = *addr
+ runtime.RaceSemacquire(&mtx)
+ runtime.RaceRead(unsafe.Pointer(addr))
+ runtime.RaceAcquire(unsafe.Pointer(addr))
+ old = *addr
+ *addr = new
+ runtime.RaceReleaseMerge(unsafe.Pointer(addr))
+ runtime.RaceSemrelease(&mtx)
+ return
+}
+
func CompareAndSwapInt32(val *int32, old, new int32) bool {
return CompareAndSwapUint32((*uint32)(unsafe.Pointer(val)), uint32(old), uint32(new))
}
diff --git a/libgo/go/sync/cond.go b/libgo/go/sync/cond.go
index 13547a8a11b..9e6bc170f19 100644
--- a/libgo/go/sync/cond.go
+++ b/libgo/go/sync/cond.go
@@ -4,6 +4,11 @@
package sync
+import (
+ "sync/atomic"
+ "unsafe"
+)
+
// Cond implements a condition variable, a rendezvous point
// for goroutines waiting for or announcing the occurrence
// of an event.
@@ -11,27 +16,16 @@ package sync
// Each Cond has an associated Locker L (often a *Mutex or *RWMutex),
// which must be held when changing the condition and
// when calling the Wait method.
+//
+// A Cond can be created as part of other structures.
+// A Cond must not be copied after first use.
type Cond struct {
- L Locker // held while observing or changing the condition
- m Mutex // held to avoid internal races
-
- // We must be careful to make sure that when Signal
- // releases a semaphore, the corresponding acquire is
- // executed by a goroutine that was already waiting at
- // the time of the call to Signal, not one that arrived later.
- // To ensure this, we segment waiting goroutines into
- // generations punctuated by calls to Signal. Each call to
- // Signal begins another generation if there are no goroutines
- // left in older generations for it to wake. Because of this
- // optimization (only begin another generation if there
- // are no older goroutines left), we only need to keep track
- // of the two most recent generations, which we call old
- // and new.
- oldWaiters int // number of waiters in old generation...
- oldSema *uint32 // ... waiting on this semaphore
+ // L is held while observing or changing the condition
+ L Locker
- newWaiters int // number of waiters in new generation...
- newSema *uint32 // ... waiting on this semaphore
+ sema syncSema
+ waiters uint32 // number of waiters
+ checker copyChecker
}
// NewCond returns a new Cond with Locker l.
@@ -56,22 +50,16 @@ func NewCond(l Locker) *Cond {
// c.L.Unlock()
//
func (c *Cond) Wait() {
+ c.checker.check()
if raceenabled {
- _ = c.m.state
raceDisable()
}
- c.m.Lock()
- if c.newSema == nil {
- c.newSema = new(uint32)
- }
- s := c.newSema
- c.newWaiters++
- c.m.Unlock()
+ atomic.AddUint32(&c.waiters, 1)
if raceenabled {
raceEnable()
}
c.L.Unlock()
- runtime_Semacquire(s)
+ runtime_Syncsemacquire(&c.sema)
c.L.Lock()
}
@@ -80,26 +68,7 @@ func (c *Cond) Wait() {
// It is allowed but not required for the caller to hold c.L
// during the call.
func (c *Cond) Signal() {
- if raceenabled {
- _ = c.m.state
- raceDisable()
- }
- c.m.Lock()
- if c.oldWaiters == 0 && c.newWaiters > 0 {
- // Retire old generation; rename new to old.
- c.oldWaiters = c.newWaiters
- c.oldSema = c.newSema
- c.newWaiters = 0
- c.newSema = nil
- }
- if c.oldWaiters > 0 {
- c.oldWaiters--
- runtime_Semrelease(c.oldSema)
- }
- c.m.Unlock()
- if raceenabled {
- raceEnable()
- }
+ c.signalImpl(false)
}
// Broadcast wakes all goroutines waiting on c.
@@ -107,27 +76,43 @@ func (c *Cond) Signal() {
// It is allowed but not required for the caller to hold c.L
// during the call.
func (c *Cond) Broadcast() {
+ c.signalImpl(true)
+}
+
+func (c *Cond) signalImpl(all bool) {
+ c.checker.check()
if raceenabled {
- _ = c.m.state
raceDisable()
}
- c.m.Lock()
- // Wake both generations.
- if c.oldWaiters > 0 {
- for i := 0; i < c.oldWaiters; i++ {
- runtime_Semrelease(c.oldSema)
+ for {
+ old := atomic.LoadUint32(&c.waiters)
+ if old == 0 {
+ if raceenabled {
+ raceEnable()
+ }
+ return
}
- c.oldWaiters = 0
- }
- if c.newWaiters > 0 {
- for i := 0; i < c.newWaiters; i++ {
- runtime_Semrelease(c.newSema)
+ new := old - 1
+ if all {
+ new = 0
+ }
+ if atomic.CompareAndSwapUint32(&c.waiters, old, new) {
+ if raceenabled {
+ raceEnable()
+ }
+ runtime_Syncsemrelease(&c.sema, old-new)
+ return
}
- c.newWaiters = 0
- c.newSema = nil
}
- c.m.Unlock()
- if raceenabled {
- raceEnable()
+}
+
+// copyChecker holds back pointer to itself to detect object copying.
+type copyChecker uintptr
+
+func (c *copyChecker) check() {
+ if uintptr(*c) != uintptr(unsafe.Pointer(c)) &&
+ !atomic.CompareAndSwapUintptr((*uintptr)(c), 0, uintptr(unsafe.Pointer(c))) &&
+ uintptr(*c) != uintptr(unsafe.Pointer(c)) {
+ panic("sync.Cond is copied")
}
}
diff --git a/libgo/go/sync/cond_test.go b/libgo/go/sync/cond_test.go
index cefacb184e1..467c80621de 100644
--- a/libgo/go/sync/cond_test.go
+++ b/libgo/go/sync/cond_test.go
@@ -5,6 +5,8 @@ package sync_test
import (
. "sync"
+
+ "runtime"
"testing"
)
@@ -124,3 +126,130 @@ func TestCondBroadcast(t *testing.T) {
}
c.Broadcast()
}
+
+func TestRace(t *testing.T) {
+ x := 0
+ c := NewCond(&Mutex{})
+ done := make(chan bool)
+ go func() {
+ c.L.Lock()
+ x = 1
+ c.Wait()
+ if x != 2 {
+ t.Fatal("want 2")
+ }
+ x = 3
+ c.Signal()
+ c.L.Unlock()
+ done <- true
+ }()
+ go func() {
+ c.L.Lock()
+ for {
+ if x == 1 {
+ x = 2
+ c.Signal()
+ break
+ }
+ c.L.Unlock()
+ runtime.Gosched()
+ c.L.Lock()
+ }
+ c.L.Unlock()
+ done <- true
+ }()
+ go func() {
+ c.L.Lock()
+ for {
+ if x == 2 {
+ c.Wait()
+ if x != 3 {
+ t.Fatal("want 3")
+ }
+ break
+ }
+ if x == 3 {
+ break
+ }
+ c.L.Unlock()
+ runtime.Gosched()
+ c.L.Lock()
+ }
+ c.L.Unlock()
+ done <- true
+ }()
+ <-done
+ <-done
+ <-done
+}
+
+func TestCondCopy(t *testing.T) {
+ defer func() {
+ err := recover()
+ if err == nil || err.(string) != "sync.Cond is copied" {
+ t.Fatalf("got %v, expect sync.Cond is copied", err)
+ }
+ }()
+ c := Cond{L: &Mutex{}}
+ c.Signal()
+ c2 := c
+ c2.Signal()
+}
+
+func BenchmarkCond1(b *testing.B) {
+ benchmarkCond(b, 1)
+}
+
+func BenchmarkCond2(b *testing.B) {
+ benchmarkCond(b, 2)
+}
+
+func BenchmarkCond4(b *testing.B) {
+ benchmarkCond(b, 4)
+}
+
+func BenchmarkCond8(b *testing.B) {
+ benchmarkCond(b, 8)
+}
+
+func BenchmarkCond16(b *testing.B) {
+ benchmarkCond(b, 16)
+}
+
+func BenchmarkCond32(b *testing.B) {
+ benchmarkCond(b, 32)
+}
+
+func benchmarkCond(b *testing.B, waiters int) {
+ c := NewCond(&Mutex{})
+ done := make(chan bool)
+ id := 0
+
+ for routine := 0; routine < waiters+1; routine++ {
+ go func() {
+ for i := 0; i < b.N; i++ {
+ c.L.Lock()
+ if id == -1 {
+ c.L.Unlock()
+ break
+ }
+ id++
+ if id == waiters+1 {
+ id = 0
+ c.Broadcast()
+ } else {
+ c.Wait()
+ }
+ c.L.Unlock()
+ }
+ c.L.Lock()
+ id = -1
+ c.Broadcast()
+ c.L.Unlock()
+ done <- true
+ }()
+ }
+ for routine := 0; routine < waiters+1; routine++ {
+ <-done
+ }
+}
diff --git a/libgo/go/sync/example_test.go b/libgo/go/sync/example_test.go
index 031c87f03b1..bdd3af6feda 100644
--- a/libgo/go/sync/example_test.go
+++ b/libgo/go/sync/example_test.go
@@ -6,10 +6,15 @@ package sync_test
import (
"fmt"
- "net/http"
"sync"
)
+type httpPkg struct{}
+
+func (httpPkg) Get(url string) {}
+
+var http httpPkg
+
// This example fetches several URLs concurrently,
// using a WaitGroup to block until all the fetches are complete.
func ExampleWaitGroup() {
diff --git a/libgo/go/sync/once.go b/libgo/go/sync/once.go
index 1699e86a9eb..161ae3b3e96 100644
--- a/libgo/go/sync/once.go
+++ b/libgo/go/sync/once.go
@@ -14,8 +14,8 @@ type Once struct {
done uint32
}
-// Do calls the function f if and only if the method is being called for the
-// first time with this receiver. In other words, given
+// Do calls the function f if and only if Do is being called for the
+// first time for this instance of Once. In other words, given
// var once Once
// if once.Do(f) is called multiple times, only the first call will invoke f,
// even if f has a different value in each invocation. A new instance of
diff --git a/libgo/go/sync/race.go b/libgo/go/sync/race.go
index d9431af6ffb..fd0277dcc95 100644
--- a/libgo/go/sync/race.go
+++ b/libgo/go/sync/race.go
@@ -32,3 +32,11 @@ func raceDisable() {
func raceEnable() {
runtime.RaceEnable()
}
+
+func raceRead(addr unsafe.Pointer) {
+ runtime.RaceRead(addr)
+}
+
+func raceWrite(addr unsafe.Pointer) {
+ runtime.RaceWrite(addr)
+}
diff --git a/libgo/go/sync/race0.go b/libgo/go/sync/race0.go
index bef14f974f1..65ada1c5d38 100644
--- a/libgo/go/sync/race0.go
+++ b/libgo/go/sync/race0.go
@@ -26,3 +26,9 @@ func raceDisable() {
func raceEnable() {
}
+
+func raceRead(addr unsafe.Pointer) {
+}
+
+func raceWrite(addr unsafe.Pointer) {
+}
diff --git a/libgo/go/sync/runtime.go b/libgo/go/sync/runtime.go
index e99599c11ae..3bf47ea52aa 100644
--- a/libgo/go/sync/runtime.go
+++ b/libgo/go/sync/runtime.go
@@ -4,6 +4,8 @@
package sync
+import "unsafe"
+
// defined in package runtime
// Semacquire waits until *s > 0 and then atomically decrements it.
@@ -16,3 +18,19 @@ func runtime_Semacquire(s *uint32)
// It is intended as a simple wakeup primitive for use by the synchronization
// library and should not be used directly.
func runtime_Semrelease(s *uint32)
+
+// Opaque representation of SyncSema in runtime/sema.goc.
+type syncSema [3]uintptr
+
+// Syncsemacquire waits for a pairing Syncsemrelease on the same semaphore s.
+func runtime_Syncsemacquire(s *syncSema)
+
+// Syncsemrelease waits for n pairing Syncsemacquire on the same semaphore s.
+func runtime_Syncsemrelease(s *syncSema, n uint32)
+
+// Ensure that sync and runtime agree on size of syncSema.
+func runtime_Syncsemcheck(size uintptr)
+func init() {
+ var s syncSema
+ runtime_Syncsemcheck(unsafe.Sizeof(s))
+}
diff --git a/libgo/go/sync/waitgroup.go b/libgo/go/sync/waitgroup.go
index ca38837833e..22681115cb6 100644
--- a/libgo/go/sync/waitgroup.go
+++ b/libgo/go/sync/waitgroup.go
@@ -43,12 +43,23 @@ type WaitGroup struct {
// other event to be waited for. See the WaitGroup example.
func (wg *WaitGroup) Add(delta int) {
if raceenabled {
- _ = wg.m.state
- raceReleaseMerge(unsafe.Pointer(wg))
+ _ = wg.m.state // trigger nil deref early
+ if delta < 0 {
+ // Synchronize decrements with Wait.
+ raceReleaseMerge(unsafe.Pointer(wg))
+ }
raceDisable()
defer raceEnable()
}
v := atomic.AddInt32(&wg.counter, int32(delta))
+ if raceenabled {
+ if delta > 0 && v == int32(delta) {
+ // The first increment must be synchronized with Wait.
+ // Need to model this as a read, because there can be
+ // several concurrent wg.counter transitions from 0.
+ raceRead(unsafe.Pointer(&wg.sema))
+ }
+ }
if v < 0 {
panic("sync: negative WaitGroup counter")
}
@@ -72,7 +83,7 @@ func (wg *WaitGroup) Done() {
// Wait blocks until the WaitGroup counter is zero.
func (wg *WaitGroup) Wait() {
if raceenabled {
- _ = wg.m.state
+ _ = wg.m.state // trigger nil deref early
raceDisable()
}
if atomic.LoadInt32(&wg.counter) == 0 {
@@ -83,7 +94,7 @@ func (wg *WaitGroup) Wait() {
return
}
wg.m.Lock()
- atomic.AddInt32(&wg.waiters, 1)
+ w := atomic.AddInt32(&wg.waiters, 1)
// This code is racing with the unlocked path in Add above.
// The code above modifies counter and then reads waiters.
// We must modify waiters and then read counter (the opposite order)
@@ -101,6 +112,13 @@ func (wg *WaitGroup) Wait() {
}
return
}
+ if raceenabled && w == 1 {
+ // Wait must be synchronized with the first Add.
+ // Need to model this is as a write to race with the read in Add.
+ // As a consequence, can do the write only for the first waiter,
+ // otherwise concurrent Waits will race with each other.
+ raceWrite(unsafe.Pointer(&wg.sema))
+ }
if wg.sema == nil {
wg.sema = new(uint32)
}
diff --git a/libgo/go/syscall/bpf_bsd.go b/libgo/go/syscall/bpf_bsd.go
index f98036c42cd..cc6c1e77c50 100644
--- a/libgo/go/syscall/bpf_bsd.go
+++ b/libgo/go/syscall/bpf_bsd.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd netbsd openbsd
+// +build darwin dragonfly freebsd netbsd openbsd
// Berkeley packet filter for BSD variants
diff --git a/libgo/go/syscall/consistency_unix_test.go b/libgo/go/syscall/consistency_unix_test.go
new file mode 100644
index 00000000000..73630bc6149
--- /dev/null
+++ b/libgo/go/syscall/consistency_unix_test.go
@@ -0,0 +1,34 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build freebsd dragonfly darwin linux netbsd openbsd
+
+// This file tests that some basic syscalls are consistent across
+// all Unixes.
+
+package syscall_test
+
+import "syscall"
+
+// {Set,Get}priority and needed constants for them
+func _() {
+ var (
+ _ func(int, int, int) error = syscall.Setpriority
+ _ func(int, int) (int, error) = syscall.Getpriority
+ )
+ const (
+ _ int = syscall.PRIO_USER
+ _ int = syscall.PRIO_PROCESS
+ _ int = syscall.PRIO_PGRP
+ )
+}
+
+// termios functions and constants
+func _() {
+ const (
+ _ int = syscall.TCIFLUSH
+ _ int = syscall.TCIOFLUSH
+ _ int = syscall.TCOFLUSH
+ )
+}
diff --git a/libgo/go/syscall/env_unix.go b/libgo/go/syscall/env_unix.go
index f47947140d7..f64202ed110 100644
--- a/libgo/go/syscall/env_unix.go
+++ b/libgo/go/syscall/env_unix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd linux netbsd openbsd
+// +build darwin dragonfly freebsd linux netbsd openbsd
// Unix environment variables.
diff --git a/libgo/go/syscall/env_windows.go b/libgo/go/syscall/env_windows.go
index 39bd5022efd..420b3872464 100644
--- a/libgo/go/syscall/env_windows.go
+++ b/libgo/go/syscall/env_windows.go
@@ -28,20 +28,13 @@ func Getenv(key string) (value string, found bool) {
n = 0
}
}
- if n == 0 {
- return "", false
- }
return string(utf16.Decode(b[0:n])), true
}
func Setenv(key, value string) error {
- var v *uint16
- var err error
- if len(value) > 0 {
- v, err = UTF16PtrFromString(value)
- if err != nil {
- return err
- }
+ v, err := UTF16PtrFromString(value)
+ if err != nil {
+ return err
}
keyp, err := UTF16PtrFromString(key)
if err != nil {
diff --git a/libgo/go/syscall/exec_bsd.go b/libgo/go/syscall/exec_bsd.go
index a07129c8253..217e0c842df 100644
--- a/libgo/go/syscall/exec_bsd.go
+++ b/libgo/go/syscall/exec_bsd.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd netbsd openbsd
+// +build darwin dragonfly freebsd netbsd openbsd
package syscall
@@ -20,12 +20,17 @@ type SysProcAttr struct {
Noctty bool // Detach fd 0 from controlling terminal
}
+// Implemented in runtime package.
+func runtime_BeforeFork()
+func runtime_AfterFork()
+
// Fork, dup fd onto 0..len(fd), and exec(argv0, argvv, envv) in child.
// If a dup or exec fails, write the errno error to pipe.
// (Pipe is close-on-exec so if exec succeeds, it will be closed.)
// In the child, this function must not acquire any locks, because
// they might have been locked at the time of the fork. This means
// no rescheduling, no malloc calls, and no new stack segments.
+// For the same reason compiler does not race instrument it.
// The calls to RawSyscall are okay because they are assembly
// functions that do not grow the stack.
func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr *ProcAttr, sys *SysProcAttr, pipe int) (pid int, err Errno) {
@@ -53,13 +58,16 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
// About to call fork.
// No more allocation or calls of non-assembly functions.
+ runtime_BeforeFork()
r1, err1 = raw_fork()
if err1 != 0 {
+ runtime_AfterFork()
return 0, err1
}
if r1 != 0 {
// parent; return PID
+ runtime_AfterFork()
return int(r1), 0
}
diff --git a/libgo/go/syscall/exec_linux.go b/libgo/go/syscall/exec_linux.go
index b9d8a747a1d..5d14ec385a4 100644
--- a/libgo/go/syscall/exec_linux.go
+++ b/libgo/go/syscall/exec_linux.go
@@ -23,14 +23,20 @@ type SysProcAttr struct {
Noctty bool // Detach fd 0 from controlling terminal
Ctty int // Controlling TTY fd (Linux only)
Pdeathsig Signal // Signal that the process will get when its parent dies (Linux only)
+ Cloneflags uintptr // Flags for clone calls (Linux only)
}
+// Implemented in runtime package.
+func runtime_BeforeFork()
+func runtime_AfterFork()
+
// Fork, dup fd onto 0..len(fd), and exec(argv0, argvv, envv) in child.
// If a dup or exec fails, write the errno error to pipe.
// (Pipe is close-on-exec so if exec succeeds, it will be closed.)
// In the child, this function must not acquire any locks, because
// they might have been locked at the time of the fork. This means
// no rescheduling, no malloc calls, and no new stack segments.
+// For the same reason compiler does not race instrument it.
// The calls to RawSyscall are okay because they are assembly
// functions that do not grow the stack.
func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr *ProcAttr, sys *SysProcAttr, pipe int) (pid int, err Errno) {
@@ -58,13 +64,16 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
// About to call fork.
// No more allocation or calls of non-assembly functions.
+ runtime_BeforeFork()
r1, err1 = raw_fork()
if err1 != 0 {
+ runtime_AfterFork()
return 0, err1
}
if r1 != 0 {
// parent; return PID
+ runtime_AfterFork()
return int(r1), 0
}
@@ -250,11 +259,6 @@ childerror:
for {
raw_exit(253)
}
-
- // Calling panic is not actually safe,
- // but the for loop above won't break
- // and this shuts up the compiler.
- panic("unreached")
}
// Try to open a pipe with O_CLOEXEC set on both file descriptors.
diff --git a/libgo/go/syscall/exec_unix.go b/libgo/go/syscall/exec_unix.go
index d4aa959c1e0..c31b8d5c4f6 100644
--- a/libgo/go/syscall/exec_unix.go
+++ b/libgo/go/syscall/exec_unix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd linux netbsd openbsd
+// +build darwin dragonfly freebsd linux netbsd openbsd
// Fork, exec, wait, etc.
diff --git a/libgo/go/syscall/libcall_linux.go b/libgo/go/syscall/libcall_linux.go
index 79de2f389e9..60eecd9ef89 100644
--- a/libgo/go/syscall/libcall_linux.go
+++ b/libgo/go/syscall/libcall_linux.go
@@ -190,6 +190,9 @@ func Accept4(fd int, flags int) (nfd int, sa Sockaddr, err error) {
//sys Adjtimex(buf *Timex) (state int, err error)
//adjtimex(buf *Timex) _C_int
+//sysnb Dup3(oldfd int, newfd int, flags int) (err error)
+//dup3(oldfd _C_int, newfd _C_int, flags _C_int) _C_int
+
//sys Faccessat(dirfd int, path string, mode uint32, flags int) (err error)
//faccessat(dirfd _C_int, pathname *byte, mode _C_int, flags _C_int) _C_int
@@ -268,6 +271,9 @@ func ParseDirent(buf []byte, max int, names []string) (consumed int, count int,
return origlen - len(buf), count, names
}
+//sys Getxattr(path string, attr string, dest []byte) (sz int, err error)
+//getxattr(path *byte, attr *byte, buf *byte, count Size_t) Ssize_t
+
//sys InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err error)
//inotify_add_watch(fd _C_int, pathname *byte, mask uint32) _C_int
@@ -283,6 +289,9 @@ func ParseDirent(buf []byte, max int, names []string) (consumed int, count int,
//sys Klogctl(typ int, buf []byte) (n int, err error)
//klogctl(typ _C_int, bufp *byte, len _C_int) _C_int
+//sys Listxattr(path string, dest []byte) (sz int, err error)
+//listxattr(path *byte, list *byte, size Size_t) Ssize_t
+
//sys Mkdirat(dirfd int, path string, mode uint32) (err error)
//mkdirat(dirfd _C_int, path *byte, mode Mode_t) _C_int
@@ -305,6 +314,9 @@ func Pipe2(p []int, flags int) (err error) {
//sys PivotRoot(newroot string, putold string) (err error)
//pivot_root(newroot *byte, putold *byte) _C_int
+//sys Removexattr(path string, attr string) (err error)
+//removexattr(path *byte, name *byte) _C_int
+
//sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error)
//renameat(olddirfd _C_int, oldpath *byte, newdirfd _C_int, newpath *byte) _C_int
@@ -338,6 +350,9 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
//sysnb Setresuid(ruid int, eguid int, suid int) (err error)
//setresuid(ruid Uid_t, euid Uid_t, suid Uid_t) _C_int
+//sys Setxattr(path string, attr string, data []byte, flags int) (err error)
+//setxattr(path *byte, name *byte, value *byte, size Size_t, flags _C_int) _C_int
+
//sys splice(rfd int, roff *_loff_t, wfd int, woff *_loff_t, len int, flags int) (n int64, err error)
//splice(rfd _C_int, roff *_loff_t, wfd _C_int, woff *_loff_t, len Size_t, flags _C_uint) Ssize_t
func Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error) {
diff --git a/libgo/go/syscall/libcall_posix.go b/libgo/go/syscall/libcall_posix.go
index 1e7823b541c..91ff59b6cfa 100644
--- a/libgo/go/syscall/libcall_posix.go
+++ b/libgo/go/syscall/libcall_posix.go
@@ -238,6 +238,9 @@ func FDZero(set *FdSet) {
//sysnb Getppid() (ppid int)
//getppid() Pid_t
+//sys Getpriority(which int, who int) (prio int, err error)
+//getpriority(which _C_int, who _C_int) _C_int
+
//sysnb Getrlimit(resource int, rlim *Rlimit) (err error)
//getrlimit(resource _C_int, rlim *Rlimit) _C_int
@@ -307,6 +310,9 @@ func Gettimeofday(tv *Timeval) (err error) {
//sysnb Setpgid(pid int, pgid int) (err error)
//setpgid(pid Pid_t, pgid Pid_t) _C_int
+//sys Setpriority(which int, who int, prio int) (err error)
+//setpriority(which _C_int, who _C_int, prio _C_int) _C_int
+
//sysnb Setreuid(ruid int, euid int) (err error)
//setreuid(ruid Uid_t, euid Uid_t) _C_int
diff --git a/libgo/go/syscall/passfd_test.go b/libgo/go/syscall/passfd_test.go
index 5d9980f3d15..e8ac32d3f57 100644
--- a/libgo/go/syscall/passfd_test.go
+++ b/libgo/go/syscall/passfd_test.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build linux darwin freebsd netbsd openbsd
+// +build linux dragonfly darwin freebsd netbsd openbsd
package syscall_test
@@ -13,6 +13,7 @@ import (
"net"
"os"
"os/exec"
+ "runtime"
"syscall"
"testing"
"time"
@@ -26,6 +27,10 @@ import (
// "-test.run=^TestPassFD$" and an environment variable used to signal
// that the test should become the child process instead.
func TestPassFD(t *testing.T) {
+ if runtime.GOOS == "dragonfly" {
+ // TODO(jsing): Figure out why sendmsg is returning EINVAL.
+ t.Skip("Skipping test on dragonfly")
+ }
if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {
passFDChild()
return
diff --git a/libgo/go/syscall/race0.go b/libgo/go/syscall/race0.go
index e94fb47afbe..b02f882fd05 100644
--- a/libgo/go/syscall/race0.go
+++ b/libgo/go/syscall/race0.go
@@ -17,3 +17,9 @@ func raceAcquire(addr unsafe.Pointer) {
func raceReleaseMerge(addr unsafe.Pointer) {
}
+
+func raceReadRange(addr unsafe.Pointer, len int) {
+}
+
+func raceWriteRange(addr unsafe.Pointer, len int) {
+}
diff --git a/libgo/go/syscall/rlimit_linux_test.go b/libgo/go/syscall/rlimit_linux_test.go
new file mode 100644
index 00000000000..4ec720e9360
--- /dev/null
+++ b/libgo/go/syscall/rlimit_linux_test.go
@@ -0,0 +1,41 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package syscall_test
+
+import (
+ "syscall"
+ "testing"
+)
+
+func TestRlimit(t *testing.T) {
+ var rlimit, zero syscall.Rlimit
+ err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rlimit)
+ if err != nil {
+ t.Fatalf("Getrlimit: save failed: %v", err)
+ }
+ if zero == rlimit {
+ t.Fatalf("Getrlimit: save failed: got zero value %#v", rlimit)
+ }
+ set := rlimit
+ set.Cur = set.Max - 1
+ err = syscall.Setrlimit(syscall.RLIMIT_NOFILE, &set)
+ if err != nil {
+ t.Fatalf("Setrlimit: set failed: %#v %v", set, err)
+ }
+ var get syscall.Rlimit
+ err = syscall.Getrlimit(syscall.RLIMIT_NOFILE, &get)
+ if err != nil {
+ t.Fatalf("Getrlimit: get failed: %v", err)
+ }
+ set = rlimit
+ set.Cur = set.Max - 1
+ if set != get {
+ t.Fatalf("Rlimit: change failed: wanted %#v got %#v", set, get)
+ }
+ err = syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rlimit)
+ if err != nil {
+ t.Fatalf("Setrlimit: restore failed: %#v %v", rlimit, err)
+ }
+}
diff --git a/libgo/go/syscall/route_bsd.go b/libgo/go/syscall/route_bsd.go
index 62c5ce1a31b..638073592d5 100644
--- a/libgo/go/syscall/route_bsd.go
+++ b/libgo/go/syscall/route_bsd.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd netbsd openbsd
+// +build darwin dragonfly freebsd netbsd openbsd
// Routing sockets and messages
@@ -13,10 +13,14 @@ import "unsafe"
// Round the length of a raw sockaddr up to align it properly.
func rsaAlignOf(salen int) int {
salign := sizeofPtr
- // NOTE: It seems like 64-bit Darwin kernel still requires 32-bit
- // aligned access to BSD subsystem.
- if darwinAMD64 {
+ // NOTE: It seems like 64-bit Darwin kernel still requires
+ // 32-bit aligned access to BSD subsystem. Also NetBSD 6
+ // kernel and beyond require 64-bit aligned access to routing
+ // facilities.
+ if darwin64Bit {
salign = 4
+ } else if netbsd32Bit {
+ salign = 8
}
if salen == 0 {
return salign
@@ -142,6 +146,12 @@ func (m *InterfaceAddrMessage) sockaddr() (sas []Sockaddr) {
return nil
}
b := m.Data[:]
+ // We still see AF_UNSPEC in socket addresses on some
+ // platforms. To identify each address family correctly, we
+ // will use the address family of RTAX_NETMASK as a preferred
+ // one on the 32-bit NetBSD kernel, also use the length of
+ // RTAX_NETMASK socket address on the FreeBSD kernel.
+ preferredFamily := uint8(AF_UNSPEC)
for i := uint(0); i < RTAX_MAX; i++ {
if m.Header.Addrs&rtaIfaMask&(1<<i) == 0 {
continue
@@ -149,14 +159,29 @@ func (m *InterfaceAddrMessage) sockaddr() (sas []Sockaddr) {
rsa := (*RawSockaddr)(unsafe.Pointer(&b[0]))
switch i {
case RTAX_IFA:
+ if rsa.Family == AF_UNSPEC {
+ rsa.Family = preferredFamily
+ }
sa, err := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa)))
if err != nil {
return nil
}
sas = append(sas, sa)
case RTAX_NETMASK:
- if rsa.Family == AF_UNSPEC {
- rsa.Family = AF_INET // an old fasion, AF_UNSPEC means AF_INET
+ switch rsa.Family {
+ case AF_UNSPEC:
+ switch rsa.Len {
+ case SizeofSockaddrInet4:
+ rsa.Family = AF_INET
+ case SizeofSockaddrInet6:
+ rsa.Family = AF_INET6
+ default:
+ rsa.Family = AF_INET // an old fashion, AF_UNSPEC means AF_INET
+ }
+ case AF_INET, AF_INET6:
+ preferredFamily = rsa.Family
+ default:
+ return nil
}
sa, err := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa)))
if err != nil {
diff --git a/libgo/go/syscall/route_dragonfly.go b/libgo/go/syscall/route_dragonfly.go
new file mode 100644
index 00000000000..acad7a2be8f
--- /dev/null
+++ b/libgo/go/syscall/route_dragonfly.go
@@ -0,0 +1,72 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Routing sockets and messages for Dragonfly
+
+package syscall
+
+import "unsafe"
+
+func (any *anyMessage) toRoutingMessage(b []byte) RoutingMessage {
+ switch any.Type {
+ case RTM_ADD, RTM_DELETE, RTM_CHANGE, RTM_GET, RTM_LOSING, RTM_REDIRECT, RTM_MISS, RTM_LOCK, RTM_RESOLVE:
+ p := (*RouteMessage)(unsafe.Pointer(any))
+ return &RouteMessage{Header: p.Header, Data: b[SizeofRtMsghdr:any.Msglen]}
+ case RTM_IFINFO:
+ p := (*InterfaceMessage)(unsafe.Pointer(any))
+ return &InterfaceMessage{Header: p.Header, Data: b[SizeofIfMsghdr:any.Msglen]}
+ case RTM_IFANNOUNCE:
+ p := (*InterfaceAnnounceMessage)(unsafe.Pointer(any))
+ return &InterfaceAnnounceMessage{Header: p.Header}
+ case RTM_NEWADDR, RTM_DELADDR:
+ p := (*InterfaceAddrMessage)(unsafe.Pointer(any))
+ return &InterfaceAddrMessage{Header: p.Header, Data: b[SizeofIfaMsghdr:any.Msglen]}
+ case RTM_NEWMADDR, RTM_DELMADDR:
+ p := (*InterfaceMulticastAddrMessage)(unsafe.Pointer(any))
+ return &InterfaceMulticastAddrMessage{Header: p.Header, Data: b[SizeofIfmaMsghdr:any.Msglen]}
+ }
+ return nil
+}
+
+// InterfaceAnnounceMessage represents a routing message containing
+// network interface arrival and depature information.
+type InterfaceAnnounceMessage struct {
+ Header IfAnnounceMsghdr
+}
+
+func (m *InterfaceAnnounceMessage) sockaddr() (sas []Sockaddr) { return nil }
+
+// InterfaceMulticastAddrMessage represents a routing message
+// containing network interface address entries.
+type InterfaceMulticastAddrMessage struct {
+ Header IfmaMsghdr
+ Data []byte
+}
+
+const rtaIfmaMask = RTA_GATEWAY | RTA_IFP | RTA_IFA
+
+func (m *InterfaceMulticastAddrMessage) sockaddr() (sas []Sockaddr) {
+ if m.Header.Addrs&rtaIfmaMask == 0 {
+ return nil
+ }
+ b := m.Data[:]
+ for i := uint(0); i < RTAX_MAX; i++ {
+ if m.Header.Addrs&rtaIfmaMask&(1<<i) == 0 {
+ continue
+ }
+ rsa := (*RawSockaddr)(unsafe.Pointer(&b[0]))
+ switch i {
+ case RTAX_IFA:
+ sa, e := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa)))
+ if e != nil {
+ return nil
+ }
+ sas = append(sas, sa)
+ case RTAX_GATEWAY, RTAX_IFP:
+ // nothing to do
+ }
+ b = b[rsaAlignOf(int(rsa.Len)):]
+ }
+ return sas
+}
diff --git a/libgo/go/syscall/security_windows.go b/libgo/go/syscall/security_windows.go
index 017b270146f..b22ecf578e0 100644
--- a/libgo/go/syscall/security_windows.go
+++ b/libgo/go/syscall/security_windows.go
@@ -58,6 +58,14 @@ func TranslateAccountName(username string, from, to uint32, initSize int) (strin
return UTF16ToString(b), nil
}
+const (
+ // do not reorder
+ NetSetupUnknownStatus = iota
+ NetSetupUnjoined
+ NetSetupWorkgroupName
+ NetSetupDomainName
+)
+
type UserInfo10 struct {
Name *uint16
Comment *uint16
@@ -66,6 +74,7 @@ type UserInfo10 struct {
}
//sys NetUserGetInfo(serverName *uint16, userName *uint16, level uint32, buf **byte) (neterr error) = netapi32.NetUserGetInfo
+//sys NetGetJoinInformation(server *uint16, name **uint16, bufType *uint32) (neterr error) = netapi32.NetGetJoinInformation
//sys NetApiBufferFree(buf *byte) (neterr error) = netapi32.NetApiBufferFree
const (
diff --git a/libgo/go/syscall/signame.c b/libgo/go/syscall/signame.c
index 6f5c2972bab..0453c06d4c4 100644
--- a/libgo/go/syscall/signame.c
+++ b/libgo/go/syscall/signame.c
@@ -31,7 +31,7 @@ Signame (intgo sig)
s = buf;
}
len = __builtin_strlen (s);
- data = runtime_mallocgc (len, FlagNoPointers, 0, 0);
+ data = runtime_mallocgc (len, 0, FlagNoScan);
__builtin_memcpy (data, s, len);
ret.str = data;
ret.len = len;
diff --git a/libgo/go/syscall/sockcmsg_unix.go b/libgo/go/syscall/sockcmsg_unix.go
index 03c17908ec4..5bc4c2acfbd 100644
--- a/libgo/go/syscall/sockcmsg_unix.go
+++ b/libgo/go/syscall/sockcmsg_unix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd linux netbsd openbsd
+// +build darwin dragonfly freebsd linux netbsd openbsd
// Socket control messages
@@ -18,7 +18,7 @@ func cmsgAlignOf(salen int) int {
salign := int(sizeofPtr)
// NOTE: It seems like 64-bit Darwin kernel still requires 32-bit
// aligned access to BSD subsystem.
- if darwinAMD64 {
+ if darwin64Bit {
salign = 4
}
// NOTE: Solaris always uses 32-bit alignment,
diff --git a/libgo/go/syscall/socket.go b/libgo/go/syscall/socket.go
index cc98d6b79fd..29c70559cce 100644
--- a/libgo/go/syscall/socket.go
+++ b/libgo/go/syscall/socket.go
@@ -272,6 +272,10 @@ func SetsockoptTimeval(fd, level, opt int, tv *Timeval) (err error) {
return setsockopt(fd, level, opt, (*byte)(unsafe.Pointer(tv)), Socklen_t(unsafe.Sizeof(*tv)))
}
+func SetsockoptICMPv6Filter(fd, level, opt int, filter *ICMPv6Filter) error {
+ return setsockopt(fd, level, opt, (*byte)(unsafe.Pointer(filter)), SizeofICMPv6Filter)
+}
+
type Linger struct {
Onoff int32
Linger int32
diff --git a/libgo/go/syscall/syscall_test.go b/libgo/go/syscall/syscall_test.go
new file mode 100644
index 00000000000..2a39b54f1b2
--- /dev/null
+++ b/libgo/go/syscall/syscall_test.go
@@ -0,0 +1,30 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package syscall_test
+
+import (
+ "syscall"
+ "testing"
+)
+
+func testSetGetenv(t *testing.T, key, value string) {
+ err := syscall.Setenv(key, value)
+ if err != nil {
+ t.Fatalf("Setenv failed to set %q: %v", value, err)
+ }
+ newvalue, found := syscall.Getenv(key)
+ if !found {
+ t.Fatalf("Getenv failed to find %v variable (want value %q)", key, value)
+ }
+ if newvalue != value {
+ t.Fatalf("Getenv(%v) = %q; want %q", key, newvalue, value)
+ }
+}
+
+func TestEnv(t *testing.T) {
+ testSetGetenv(t, "TESTENV", "AVALUE")
+ // make sure TESTENV gets set to "", not deleted
+ testSetGetenv(t, "TESTENV", "")
+}
diff --git a/libgo/go/syscall/syscall_unix.go b/libgo/go/syscall/syscall_unix.go
index fb62681a9e1..966090a076a 100644
--- a/libgo/go/syscall/syscall_unix.go
+++ b/libgo/go/syscall/syscall_unix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd linux netbsd openbsd
+// +build darwin dragonfly freebsd linux netbsd openbsd
package syscall
@@ -24,7 +24,10 @@ func c_syscall32(trap int32, a1, a2, a3, a4, a5, a6 int32) int32
//extern syscall
func c_syscall64(trap int64, a1, a2, a3, a4, a5, a6 int64) int64
-const darwinAMD64 = runtime.GOOS == "darwin" && runtime.GOARCH == "amd64"
+const (
+ darwin64Bit = runtime.GOOS == "darwin" && sizeofPtr == 8
+ netbsd32Bit = runtime.GOOS == "netbsd" && sizeofPtr == 4
+)
// Do a system call. We look at the size of uintptr to see how to pass
// the arguments, so that we don't pass a 64-bit value when the function
@@ -182,8 +185,13 @@ func (s Signal) String() string {
func Read(fd int, p []byte) (n int, err error) {
n, err = read(fd, p)
- if raceenabled && err == nil {
- raceAcquire(unsafe.Pointer(&ioSync))
+ if raceenabled {
+ if n > 0 {
+ raceWriteRange(unsafe.Pointer(&p[0]), n)
+ }
+ if err == nil {
+ raceAcquire(unsafe.Pointer(&ioSync))
+ }
}
return
}
@@ -192,7 +200,11 @@ func Write(fd int, p []byte) (n int, err error) {
if raceenabled {
raceReleaseMerge(unsafe.Pointer(&ioSync))
}
- return write(fd, p)
+ n, err = write(fd, p)
+ if raceenabled && n > 0 {
+ raceReadRange(unsafe.Pointer(&p[0]), n)
+ }
+ return
}
var ioSync int64
diff --git a/libgo/go/testing/allocs.go b/libgo/go/testing/allocs.go
index d142a330b08..9ec47bd4602 100644
--- a/libgo/go/testing/allocs.go
+++ b/libgo/go/testing/allocs.go
@@ -9,6 +9,7 @@ import (
)
// AllocsPerRun returns the average number of allocations during calls to f.
+// Although the return value has type float64, it will always be an integral value.
//
// To compute the number of allocations, the function will first be run once as
// a warm-up. The average number of allocations over the specified number of
@@ -36,6 +37,9 @@ func AllocsPerRun(runs int, f func()) (avg float64) {
runtime.ReadMemStats(&memstats)
mallocs += memstats.Mallocs
- // Average the mallocs over the runs (not counting the warm-up)
- return float64(mallocs) / float64(runs)
+ // Average the mallocs over the runs (not counting the warm-up).
+ // We are forced to return a float64 because the API is silly, but do
+ // the division as integers so we can ask if AllocsPerRun()==1
+ // instead of AllocsPerRun()<2.
+ return float64(mallocs / uint64(runs))
}
diff --git a/libgo/go/testing/benchmark.go b/libgo/go/testing/benchmark.go
index 25fb2d61918..3473c5b2cbf 100644
--- a/libgo/go/testing/benchmark.go
+++ b/libgo/go/testing/benchmark.go
@@ -138,7 +138,7 @@ func max(x, y int) int {
func roundDown10(n int) int {
var tens = 0
// tens = floor(log_10(n))
- for n > 10 {
+ for n >= 10 {
n = n / 10
tens++
}
@@ -153,13 +153,16 @@ func roundDown10(n int) int {
// roundUp rounds x up to a number of the form [1eX, 2eX, 5eX].
func roundUp(n int) int {
base := roundDown10(n)
- if n < (2 * base) {
+ switch {
+ case n <= base:
+ return base
+ case n <= (2 * base):
return 2 * base
- }
- if n < (5 * base) {
+ case n <= (5 * base):
return 5 * base
+ default:
+ return 10 * base
}
- return 10 * base
}
// run times the benchmark function in a separate goroutine.
diff --git a/libgo/go/testing/benchmark_test.go b/libgo/go/testing/benchmark_test.go
new file mode 100644
index 00000000000..94e994dfae0
--- /dev/null
+++ b/libgo/go/testing/benchmark_test.go
@@ -0,0 +1,58 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package testing_test
+
+import (
+ "testing"
+)
+
+var roundDownTests = []struct {
+ v, expected int
+}{
+ {1, 1},
+ {9, 1},
+ {10, 10},
+ {11, 10},
+ {100, 100},
+ {101, 100},
+ {999, 100},
+ {1000, 1000},
+ {1001, 1000},
+}
+
+func TestRoundDown10(t *testing.T) {
+ for _, tt := range roundDownTests {
+ actual := testing.RoundDown10(tt.v)
+ if tt.expected != actual {
+ t.Errorf("roundDown10(%d): expected %d, actual %d", tt.v, tt.expected, actual)
+ }
+ }
+}
+
+var roundUpTests = []struct {
+ v, expected int
+}{
+ {0, 1},
+ {1, 1},
+ {2, 2},
+ {5, 5},
+ {9, 10},
+ {999, 1000},
+ {1000, 1000},
+ {1400, 2000},
+ {1700, 2000},
+ {4999, 5000},
+ {5000, 5000},
+ {5001, 10000},
+}
+
+func TestRoundUp(t *testing.T) {
+ for _, tt := range roundUpTests {
+ actual := testing.RoundUp(tt.v)
+ if tt.expected != actual {
+ t.Errorf("roundUp(%d): expected %d, actual %d", tt.v, tt.expected, actual)
+ }
+ }
+}
diff --git a/libgo/go/testing/cover.go b/libgo/go/testing/cover.go
new file mode 100644
index 00000000000..dd29364d87e
--- /dev/null
+++ b/libgo/go/testing/cover.go
@@ -0,0 +1,86 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Support for test coverage.
+
+package testing
+
+import (
+ "fmt"
+ "os"
+)
+
+// CoverBlock records the coverage data for a single basic block.
+// NOTE: This struct is internal to the testing infrastructure and may change.
+// It is not covered (yet) by the Go 1 compatibility guidelines.
+type CoverBlock struct {
+ Line0 uint32
+ Col0 uint16
+ Line1 uint32
+ Col1 uint16
+ Stmts uint16
+}
+
+var cover Cover
+
+// Cover records information about test coverage checking.
+// NOTE: This struct is internal to the testing infrastructure and may change.
+// It is not covered (yet) by the Go 1 compatibility guidelines.
+type Cover struct {
+ Mode string
+ Counters map[string][]uint32
+ Blocks map[string][]CoverBlock
+ CoveredPackages string
+}
+
+// RegisterCover records the coverage data accumulators for the tests.
+// NOTE: This function is internal to the testing infrastructure and may change.
+// It is not covered (yet) by the Go 1 compatibility guidelines.
+func RegisterCover(c Cover) {
+ cover = c
+}
+
+// mustBeNil checks the error and, if present, reports it and exits.
+func mustBeNil(err error) {
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "testing: %s\n", err)
+ os.Exit(2)
+ }
+}
+
+// coverReport reports the coverage percentage and writes a coverage profile if requested.
+func coverReport() {
+ var f *os.File
+ var err error
+ if *coverProfile != "" {
+ f, err = os.Create(toOutputDir(*coverProfile))
+ mustBeNil(err)
+ fmt.Fprintf(f, "mode: %s\n", cover.Mode)
+ defer func() { mustBeNil(f.Close()) }()
+ }
+
+ var active, total int64
+ for name, counts := range cover.Counters {
+ blocks := cover.Blocks[name]
+ for i, count := range counts {
+ stmts := int64(blocks[i].Stmts)
+ total += stmts
+ if count > 0 {
+ active += stmts
+ }
+ if f != nil {
+ _, err := fmt.Fprintf(f, "%s:%d.%d,%d.%d %d %d\n", name,
+ blocks[i].Line0, blocks[i].Col0,
+ blocks[i].Line1, blocks[i].Col1,
+ stmts,
+ count)
+ mustBeNil(err)
+ }
+ }
+ }
+ if total == 0 {
+ total = 1
+ }
+ fmt.Printf("coverage: %.1f%% of statements%s\n", 100*float64(active)/float64(total), cover.CoveredPackages)
+}
diff --git a/libgo/go/testing/export_test.go b/libgo/go/testing/export_test.go
new file mode 100644
index 00000000000..89781b439f4
--- /dev/null
+++ b/libgo/go/testing/export_test.go
@@ -0,0 +1,10 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package testing
+
+var (
+ RoundDown10 = roundDown10
+ RoundUp = roundUp
+)
diff --git a/libgo/go/testing/quick/quick.go b/libgo/go/testing/quick/quick.go
index 761a6471b57..bc79cc32922 100644
--- a/libgo/go/testing/quick/quick.go
+++ b/libgo/go/testing/quick/quick.go
@@ -34,7 +34,7 @@ func randFloat32(rand *rand.Rand) float32 {
// randFloat64 generates a random float taking the full range of a float64.
func randFloat64(rand *rand.Rand) float64 {
- f := rand.Float64()
+ f := rand.Float64() * math.MaxFloat64
if rand.Int()&1 == 1 {
f = -f
}
@@ -56,90 +56,88 @@ func Value(t reflect.Type, rand *rand.Rand) (value reflect.Value, ok bool) {
return m.Generate(rand, complexSize), true
}
+ v := reflect.New(t).Elem()
switch concrete := t; concrete.Kind() {
case reflect.Bool:
- return reflect.ValueOf(rand.Int()&1 == 0), true
+ v.SetBool(rand.Int()&1 == 0)
case reflect.Float32:
- return reflect.ValueOf(randFloat32(rand)), true
+ v.SetFloat(float64(randFloat32(rand)))
case reflect.Float64:
- return reflect.ValueOf(randFloat64(rand)), true
+ v.SetFloat(randFloat64(rand))
case reflect.Complex64:
- return reflect.ValueOf(complex(randFloat32(rand), randFloat32(rand))), true
+ v.SetComplex(complex(float64(randFloat32(rand)), float64(randFloat32(rand))))
case reflect.Complex128:
- return reflect.ValueOf(complex(randFloat64(rand), randFloat64(rand))), true
+ v.SetComplex(complex(randFloat64(rand), randFloat64(rand)))
case reflect.Int16:
- return reflect.ValueOf(int16(randInt64(rand))), true
+ v.SetInt(randInt64(rand))
case reflect.Int32:
- return reflect.ValueOf(int32(randInt64(rand))), true
+ v.SetInt(randInt64(rand))
case reflect.Int64:
- return reflect.ValueOf(randInt64(rand)), true
+ v.SetInt(randInt64(rand))
case reflect.Int8:
- return reflect.ValueOf(int8(randInt64(rand))), true
+ v.SetInt(randInt64(rand))
case reflect.Int:
- return reflect.ValueOf(int(randInt64(rand))), true
+ v.SetInt(randInt64(rand))
case reflect.Uint16:
- return reflect.ValueOf(uint16(randInt64(rand))), true
+ v.SetUint(uint64(randInt64(rand)))
case reflect.Uint32:
- return reflect.ValueOf(uint32(randInt64(rand))), true
+ v.SetUint(uint64(randInt64(rand)))
case reflect.Uint64:
- return reflect.ValueOf(uint64(randInt64(rand))), true
+ v.SetUint(uint64(randInt64(rand)))
case reflect.Uint8:
- return reflect.ValueOf(uint8(randInt64(rand))), true
+ v.SetUint(uint64(randInt64(rand)))
case reflect.Uint:
- return reflect.ValueOf(uint(randInt64(rand))), true
+ v.SetUint(uint64(randInt64(rand)))
case reflect.Uintptr:
- return reflect.ValueOf(uintptr(randInt64(rand))), true
+ v.SetUint(uint64(randInt64(rand)))
case reflect.Map:
numElems := rand.Intn(complexSize)
- m := reflect.MakeMap(concrete)
+ v.Set(reflect.MakeMap(concrete))
for i := 0; i < numElems; i++ {
key, ok1 := Value(concrete.Key(), rand)
value, ok2 := Value(concrete.Elem(), rand)
if !ok1 || !ok2 {
return reflect.Value{}, false
}
- m.SetMapIndex(key, value)
+ v.SetMapIndex(key, value)
}
- return m, true
case reflect.Ptr:
- v, ok := Value(concrete.Elem(), rand)
+ elem, ok := Value(concrete.Elem(), rand)
if !ok {
return reflect.Value{}, false
}
- p := reflect.New(concrete.Elem())
- p.Elem().Set(v)
- return p, true
+ v.Set(reflect.New(concrete.Elem()))
+ v.Elem().Set(elem)
case reflect.Slice:
numElems := rand.Intn(complexSize)
- s := reflect.MakeSlice(concrete, numElems, numElems)
+ v.Set(reflect.MakeSlice(concrete, numElems, numElems))
for i := 0; i < numElems; i++ {
- v, ok := Value(concrete.Elem(), rand)
+ elem, ok := Value(concrete.Elem(), rand)
if !ok {
return reflect.Value{}, false
}
- s.Index(i).Set(v)
+ v.Index(i).Set(elem)
}
- return s, true
case reflect.String:
numChars := rand.Intn(complexSize)
codePoints := make([]rune, numChars)
for i := 0; i < numChars; i++ {
codePoints[i] = rune(rand.Intn(0x10ffff))
}
- return reflect.ValueOf(string(codePoints)), true
+ v.SetString(string(codePoints))
case reflect.Struct:
- s := reflect.New(t).Elem()
- for i := 0; i < s.NumField(); i++ {
- v, ok := Value(concrete.Field(i).Type, rand)
+ for i := 0; i < v.NumField(); i++ {
+ elem, ok := Value(concrete.Field(i).Type, rand)
if !ok {
return reflect.Value{}, false
}
- s.Field(i).Set(v)
+ v.Field(i).Set(elem)
}
- return s, true
default:
return reflect.Value{}, false
}
+
+ return v, true
}
// A Config structure contains options for running a test.
diff --git a/libgo/go/testing/quick/quick_test.go b/libgo/go/testing/quick/quick_test.go
index a178ec28e69..36745ae2aba 100644
--- a/libgo/go/testing/quick/quick_test.go
+++ b/libgo/go/testing/quick/quick_test.go
@@ -13,32 +13,82 @@ import (
func fBool(a bool) bool { return a }
+type TestBoolAlias bool
+
+func fBoolAlias(a TestBoolAlias) TestBoolAlias { return a }
+
func fFloat32(a float32) float32 { return a }
+type TestFloat32Alias float32
+
+func fFloat32Alias(a TestFloat32Alias) TestFloat32Alias { return a }
+
func fFloat64(a float64) float64 { return a }
+type TestFloat64Alias float64
+
+func fFloat64Alias(a TestFloat64Alias) TestFloat64Alias { return a }
+
func fComplex64(a complex64) complex64 { return a }
+type TestComplex64Alias complex64
+
+func fComplex64Alias(a TestComplex64Alias) TestComplex64Alias { return a }
+
func fComplex128(a complex128) complex128 { return a }
+type TestComplex128Alias complex128
+
+func fComplex128Alias(a TestComplex128Alias) TestComplex128Alias { return a }
+
func fInt16(a int16) int16 { return a }
+type TestInt16Alias int16
+
+func fInt16Alias(a TestInt16Alias) TestInt16Alias { return a }
+
func fInt32(a int32) int32 { return a }
+type TestInt32Alias int32
+
+func fInt32Alias(a TestInt32Alias) TestInt32Alias { return a }
+
func fInt64(a int64) int64 { return a }
+type TestInt64Alias int64
+
+func fInt64Alias(a TestInt64Alias) TestInt64Alias { return a }
+
func fInt8(a int8) int8 { return a }
+type TestInt8Alias int8
+
+func fInt8Alias(a TestInt8Alias) TestInt8Alias { return a }
+
func fInt(a int) int { return a }
-func fUInt8(a uint8) uint8 { return a }
+type TestIntAlias int
+
+func fIntAlias(a TestIntAlias) TestIntAlias { return a }
func fMap(a map[int]int) map[int]int { return a }
+type TestMapAlias map[int]int
+
+func fMapAlias(a TestMapAlias) TestMapAlias { return a }
+
func fSlice(a []byte) []byte { return a }
+type TestSliceAlias []byte
+
+func fSliceAlias(a TestSliceAlias) TestSliceAlias { return a }
+
func fString(a string) string { return a }
+type TestStringAlias string
+
+func fStringAlias(a TestStringAlias) TestStringAlias { return a }
+
type TestStruct struct {
A int
B string
@@ -46,23 +96,55 @@ type TestStruct struct {
func fStruct(a TestStruct) TestStruct { return a }
+type TestStructAlias TestStruct
+
+func fStructAlias(a TestStructAlias) TestStructAlias { return a }
+
func fUint16(a uint16) uint16 { return a }
+type TestUint16Alias uint16
+
+func fUint16Alias(a TestUint16Alias) TestUint16Alias { return a }
+
func fUint32(a uint32) uint32 { return a }
+type TestUint32Alias uint32
+
+func fUint32Alias(a TestUint32Alias) TestUint32Alias { return a }
+
func fUint64(a uint64) uint64 { return a }
+type TestUint64Alias uint64
+
+func fUint64Alias(a TestUint64Alias) TestUint64Alias { return a }
+
func fUint8(a uint8) uint8 { return a }
+type TestUint8Alias uint8
+
+func fUint8Alias(a TestUint8Alias) TestUint8Alias { return a }
+
func fUint(a uint) uint { return a }
+type TestUintAlias uint
+
+func fUintAlias(a TestUintAlias) TestUintAlias { return a }
+
func fUintptr(a uintptr) uintptr { return a }
+type TestUintptrAlias uintptr
+
+func fUintptrAlias(a TestUintptrAlias) TestUintptrAlias { return a }
+
func fIntptr(a *int) *int {
b := *a
return &b
}
+type TestIntptrAlias *int
+
+func fIntptrAlias(a TestIntptrAlias) TestIntptrAlias { return a }
+
func reportError(property string, err error, t *testing.T) {
if err != nil {
t.Errorf("%s: %s", property, err)
@@ -71,30 +153,51 @@ func reportError(property string, err error, t *testing.T) {
func TestCheckEqual(t *testing.T) {
reportError("fBool", CheckEqual(fBool, fBool, nil), t)
+ reportError("fBoolAlias", CheckEqual(fBoolAlias, fBoolAlias, nil), t)
reportError("fFloat32", CheckEqual(fFloat32, fFloat32, nil), t)
+ reportError("fFloat32Alias", CheckEqual(fFloat32Alias, fFloat32Alias, nil), t)
reportError("fFloat64", CheckEqual(fFloat64, fFloat64, nil), t)
+ reportError("fFloat64Alias", CheckEqual(fFloat64Alias, fFloat64Alias, nil), t)
if runtime.GOARCH != "alpha" {
reportError("fComplex64", CheckEqual(fComplex64, fComplex64, nil), t)
+ reportError("fComplex64Alias", CheckEqual(fComplex64Alias, fComplex64Alias, nil), t)
reportError("fComplex128", CheckEqual(fComplex128, fComplex128, nil), t)
+ reportError("fComplex128Alias", CheckEqual(fComplex128Alias, fComplex128Alias, nil), t)
}
reportError("fInt16", CheckEqual(fInt16, fInt16, nil), t)
+ reportError("fInt16Alias", CheckEqual(fInt16Alias, fInt16Alias, nil), t)
reportError("fInt32", CheckEqual(fInt32, fInt32, nil), t)
+ reportError("fInt32Alias", CheckEqual(fInt32Alias, fInt32Alias, nil), t)
reportError("fInt64", CheckEqual(fInt64, fInt64, nil), t)
+ reportError("fInt64Alias", CheckEqual(fInt64Alias, fInt64Alias, nil), t)
reportError("fInt8", CheckEqual(fInt8, fInt8, nil), t)
+ reportError("fInt8Alias", CheckEqual(fInt8Alias, fInt8Alias, nil), t)
reportError("fInt", CheckEqual(fInt, fInt, nil), t)
- reportError("fUInt8", CheckEqual(fUInt8, fUInt8, nil), t)
+ reportError("fIntAlias", CheckEqual(fIntAlias, fIntAlias, nil), t)
reportError("fInt32", CheckEqual(fInt32, fInt32, nil), t)
+ reportError("fInt32Alias", CheckEqual(fInt32Alias, fInt32Alias, nil), t)
reportError("fMap", CheckEqual(fMap, fMap, nil), t)
+ reportError("fMapAlias", CheckEqual(fMapAlias, fMapAlias, nil), t)
reportError("fSlice", CheckEqual(fSlice, fSlice, nil), t)
+ reportError("fSliceAlias", CheckEqual(fSliceAlias, fSliceAlias, nil), t)
reportError("fString", CheckEqual(fString, fString, nil), t)
+ reportError("fStringAlias", CheckEqual(fStringAlias, fStringAlias, nil), t)
reportError("fStruct", CheckEqual(fStruct, fStruct, nil), t)
+ reportError("fStructAlias", CheckEqual(fStructAlias, fStructAlias, nil), t)
reportError("fUint16", CheckEqual(fUint16, fUint16, nil), t)
+ reportError("fUint16Alias", CheckEqual(fUint16Alias, fUint16Alias, nil), t)
reportError("fUint32", CheckEqual(fUint32, fUint32, nil), t)
+ reportError("fUint32Alias", CheckEqual(fUint32Alias, fUint32Alias, nil), t)
reportError("fUint64", CheckEqual(fUint64, fUint64, nil), t)
+ reportError("fUint64Alias", CheckEqual(fUint64Alias, fUint64Alias, nil), t)
reportError("fUint8", CheckEqual(fUint8, fUint8, nil), t)
+ reportError("fUint8Alias", CheckEqual(fUint8Alias, fUint8Alias, nil), t)
reportError("fUint", CheckEqual(fUint, fUint, nil), t)
+ reportError("fUintAlias", CheckEqual(fUintAlias, fUintAlias, nil), t)
reportError("fUintptr", CheckEqual(fUintptr, fUintptr, nil), t)
+ reportError("fUintptrAlias", CheckEqual(fUintptrAlias, fUintptrAlias, nil), t)
reportError("fIntptr", CheckEqual(fIntptr, fIntptr, nil), t)
+ reportError("fIntptrAlias", CheckEqual(fIntptrAlias, fIntptrAlias, nil), t)
}
// This tests that ArbitraryValue is working by checking that all the arbitrary
diff --git a/libgo/go/testing/testing.go b/libgo/go/testing/testing.go
index 312d2873296..5019e076269 100644
--- a/libgo/go/testing/testing.go
+++ b/libgo/go/testing/testing.go
@@ -23,10 +23,10 @@
// Functions of the form
// func BenchmarkXxx(*testing.B)
// are considered benchmarks, and are executed by the "go test" command when
-// the -test.bench flag is provided. Benchmarks are run sequentially.
+// its -bench flag is provided. Benchmarks are run sequentially.
//
// For a description of the testing flags, see
-// http://golang.org/cmd/go/#Description_of_testing_flags.
+// http://golang.org/cmd/go/#hdr-Description_of_testing_flags.
//
// A sample benchmark function looks like this:
// func BenchmarkHello(b *testing.B) {
@@ -114,8 +114,15 @@ var (
// full test of the package.
short = flag.Bool("test.short", false, "run smaller test suite to save time")
+ // The directory in which to create profile files and the like. When run from
+ // "go test", the binary always runs in the source directory for the package;
+ // this flag lets "go test" tell the binary to write the files in the directory where
+ // the "go test" command is run.
+ outputDir = flag.String("test.outputdir", "", "directory in which to write profiles")
+
// Report as tests are run; default is silent for success.
chatty = flag.Bool("test.v", false, "verbose: print additional output")
+ coverProfile = flag.String("test.coverprofile", "", "write a coverage profile to the named file after execution")
match = flag.String("test.run", "", "regular expression to select tests and examples to run")
memProfile = flag.String("test.memprofile", "", "write a memory profile to the named file after execution")
memProfileRate = flag.Int("test.memprofilerate", 0, "if >=0, sets runtime.MemProfileRate")
@@ -189,6 +196,31 @@ func decorate(s string) string {
return buf.String()
}
+// TB is the interface common to T and B.
+type TB interface {
+ Error(args ...interface{})
+ Errorf(format string, args ...interface{})
+ Fail()
+ FailNow()
+ Failed() bool
+ Fatal(args ...interface{})
+ Fatalf(format string, args ...interface{})
+ Log(args ...interface{})
+ Logf(format string, args ...interface{})
+ Skip(args ...interface{})
+ SkipNow()
+ Skipf(format string, args ...interface{})
+ Skipped() bool
+
+ // A private method to prevent users implementing the
+ // interface and so future additions to it will not
+ // violate Go 1 compatibility.
+ private()
+}
+
+var _ TB = (*T)(nil)
+var _ TB = (*B)(nil)
+
// T is a type passed to Test functions to manage test state and support formatted test logs.
// Logs are accumulated during execution and dumped to standard error when done.
type T struct {
@@ -197,6 +229,8 @@ type T struct {
startParallel chan bool // Parallel tests will wait on this.
}
+func (c *common) private() {}
+
// Fail marks the function as having failed but continues execution.
func (c *common) Fail() {
c.mu.Lock()
@@ -323,6 +357,9 @@ func (c *common) Skipped() bool {
func (t *T) Parallel() {
t.signal <- (*T)(nil) // Release main testing loop
<-t.startParallel // Wait for serial tests to finish
+ // Assuming Parallel is the first thing a test does, which is reasonable,
+ // reinitialize the test's start time because it's actually starting now.
+ t.start = time.Now()
}
// An internal type but exported because it is cross-package; part of the implementation
@@ -333,8 +370,6 @@ type InternalTest struct {
}
func tRunner(t *T, test *InternalTest) {
- t.start = time.Now()
-
// When this goroutine is done, either because test.F(t)
// returned normally or because a test failure triggered
// a call to runtime.Goexit, record the duration and send
@@ -350,6 +385,7 @@ func tRunner(t *T, test *InternalTest) {
t.signal <- t
}()
+ t.start = time.Now()
test.F(t)
}
@@ -364,12 +400,12 @@ func Main(matchString func(pat, str string) (bool, error), tests []InternalTest,
haveExamples = len(examples) > 0
testOk := RunTests(matchString, tests)
exampleOk := RunExamples(matchString, examples)
+ stopAlarm()
if !testOk || !exampleOk {
fmt.Println("FAIL")
os.Exit(1)
}
fmt.Println("PASS")
- stopAlarm()
RunBenchmarks(matchString, benchmarks)
after()
}
@@ -466,7 +502,7 @@ func before() {
runtime.MemProfileRate = *memProfileRate
}
if *cpuProfile != "" {
- f, err := os.Create(*cpuProfile)
+ f, err := os.Create(toOutputDir(*cpuProfile))
if err != nil {
fmt.Fprintf(os.Stderr, "testing: %s", err)
return
@@ -481,6 +517,10 @@ func before() {
if *blockProfile != "" && *blockProfileRate >= 0 {
runtime.SetBlockProfileRate(*blockProfileRate)
}
+ if *coverProfile != "" && cover.Mode == "" {
+ fmt.Fprintf(os.Stderr, "testing: cannot use -test.coverprofile because test binary was not built with coverage enabled\n")
+ os.Exit(2)
+ }
}
// after runs after all testing.
@@ -489,27 +529,60 @@ func after() {
pprof.StopCPUProfile() // flushes profile to disk
}
if *memProfile != "" {
- f, err := os.Create(*memProfile)
+ f, err := os.Create(toOutputDir(*memProfile))
if err != nil {
- fmt.Fprintf(os.Stderr, "testing: %s", err)
- return
+ fmt.Fprintf(os.Stderr, "testing: %s\n", err)
+ os.Exit(2)
}
if err = pprof.WriteHeapProfile(f); err != nil {
- fmt.Fprintf(os.Stderr, "testing: can't write %s: %s", *memProfile, err)
+ fmt.Fprintf(os.Stderr, "testing: can't write %s: %s\n", *memProfile, err)
+ os.Exit(2)
}
f.Close()
}
if *blockProfile != "" && *blockProfileRate >= 0 {
- f, err := os.Create(*blockProfile)
+ f, err := os.Create(toOutputDir(*blockProfile))
if err != nil {
- fmt.Fprintf(os.Stderr, "testing: %s", err)
- return
+ fmt.Fprintf(os.Stderr, "testing: %s\n", err)
+ os.Exit(2)
}
if err = pprof.Lookup("block").WriteTo(f, 0); err != nil {
- fmt.Fprintf(os.Stderr, "testing: can't write %s: %s", *blockProfile, err)
+ fmt.Fprintf(os.Stderr, "testing: can't write %s: %s\n", *blockProfile, err)
+ os.Exit(2)
}
f.Close()
}
+ if cover.Mode != "" {
+ coverReport()
+ }
+}
+
+// toOutputDir returns the file name relocated, if required, to outputDir.
+// Simple implementation to avoid pulling in path/filepath.
+func toOutputDir(path string) string {
+ if *outputDir == "" || path == "" {
+ return path
+ }
+ if runtime.GOOS == "windows" {
+ // On Windows, it's clumsy, but we can be almost always correct
+ // by just looking for a drive letter and a colon.
+ // Absolute paths always have a drive letter (ignoring UNC).
+ // Problem: if path == "C:A" and outputdir == "C:\Go" it's unclear
+ // what to do, but even then path/filepath doesn't help.
+ // TODO: Worth doing better? Probably not, because we're here only
+ // under the management of go test.
+ if len(path) >= 2 {
+ letter, colon := path[0], path[1]
+ if ('a' <= letter && letter <= 'z' || 'A' <= letter && letter <= 'Z') && colon == ':' {
+ // If path starts with a drive letter we're stuck with it regardless.
+ return path
+ }
+ }
+ }
+ if os.IsPathSeparator(path[0]) {
+ return path
+ }
+ return fmt.Sprintf("%s%c%s", *outputDir, os.PathSeparator, path)
}
var timer *time.Timer
@@ -517,7 +590,9 @@ var timer *time.Timer
// startAlarm starts an alarm if requested.
func startAlarm() {
if *timeout > 0 {
- timer = time.AfterFunc(*timeout, alarm)
+ timer = time.AfterFunc(*timeout, func() {
+ panic(fmt.Sprintf("test timed out after %v", *timeout))
+ })
}
}
@@ -528,22 +603,20 @@ func stopAlarm() {
}
}
-// alarm is called if the timeout expires.
-func alarm() {
- panic("test timed out")
-}
-
func parseCpuList() {
- if len(*cpuListStr) == 0 {
- cpuList = append(cpuList, runtime.GOMAXPROCS(-1))
- } else {
- for _, val := range strings.Split(*cpuListStr, ",") {
- cpu, err := strconv.Atoi(val)
- if err != nil || cpu <= 0 {
- fmt.Fprintf(os.Stderr, "testing: invalid value %q for -test.cpu", val)
- os.Exit(1)
- }
- cpuList = append(cpuList, cpu)
+ for _, val := range strings.Split(*cpuListStr, ",") {
+ val = strings.TrimSpace(val)
+ if val == "" {
+ continue
+ }
+ cpu, err := strconv.Atoi(val)
+ if err != nil || cpu <= 0 {
+ fmt.Fprintf(os.Stderr, "testing: invalid value %q for -test.cpu\n", val)
+ os.Exit(1)
}
+ cpuList = append(cpuList, cpu)
+ }
+ if cpuList == nil {
+ cpuList = append(cpuList, runtime.GOMAXPROCS(-1))
}
}
diff --git a/libgo/go/text/template/doc.go b/libgo/go/text/template/doc.go
index 2da339ce835..f622ac7dcee 100644
--- a/libgo/go/text/template/doc.go
+++ b/libgo/go/text/template/doc.go
@@ -44,7 +44,8 @@ data, defined in detail below.
*/
// {{/* a comment */}}
// A comment; discarded. May contain newlines.
-// Comments do not nest.
+// Comments do not nest and must start and end at the
+// delimiters, as shown here.
/*
{{pipeline}}
@@ -62,6 +63,12 @@ data, defined in detail below.
If the value of the pipeline is empty, T0 is executed;
otherwise, T1 is executed. Dot is unaffected.
+ {{if pipeline}} T1 {{else if pipeline}} T0 {{end}}
+ To simplify the appearance of if-else chains, the else action
+ of an if may include another if directly; the effect is exactly
+ the same as writing
+ {{if pipeline}} T1 {{else}}{{if pipeline}} T0 {{end}}{{end}}
+
{{range pipeline}} T1 {{end}}
The value of the pipeline must be an array, slice, map, or channel.
If the value of the pipeline has length zero, nothing is output;
@@ -300,8 +307,41 @@ Predefined global functions are named as follows.
Returns the escaped value of the textual representation of
its arguments in a form suitable for embedding in a URL query.
-The boolean functions take any zero value to be false and a non-zero value to
-be true.
+The boolean functions take any zero value to be false and a non-zero
+value to be true.
+
+There is also a set of binary comparison operators defined as
+functions:
+
+ eq
+ Returns the boolean truth of arg1 == arg2
+ ne
+ Returns the boolean truth of arg1 != arg2
+ lt
+ Returns the boolean truth of arg1 < arg2
+ le
+ Returns the boolean truth of arg1 <= arg2
+ gt
+ Returns the boolean truth of arg1 > arg2
+ ge
+ Returns the boolean truth of arg1 >= arg2
+
+For simpler multi-way equality tests, eq (only) accepts two or more
+arguments and compares the second and subsequent to the first,
+returning in effect
+
+ arg1==arg2 || arg1==arg3 || arg1==arg4 ...
+
+(Unlike with || in Go, however, eq is a function call and all the
+arguments will be evaluated.)
+
+The comparison functions work on basic types only (or named basic
+types, such as "type Celsius float32"). They implement the Go rules
+for comparison of values, except that size and exact type are
+ignored, so any integer value may be compared with any other integer
+value, any unsigned integer value may be compared with any other
+unsigned integer value, and so on. However, as usual, one may not
+compare an int with a float32 and so on.
Associated templates
diff --git a/libgo/go/text/template/exec.go b/libgo/go/text/template/exec.go
index 8ec8174a162..43b0b266eca 100644
--- a/libgo/go/text/template/exec.go
+++ b/libgo/go/text/template/exec.go
@@ -201,7 +201,7 @@ func (s *state) walkIfOrWith(typ parse.NodeType, dot reflect.Value, pipe *parse.
}
}
-// isTrue returns whether the value is 'true', in the sense of not the zero of its type,
+// isTrue reports whether the value is 'true', in the sense of not the zero of its type,
// and whether the value has a meaningful truth value.
func isTrue(val reflect.Value) (truth, ok bool) {
if !val.IsValid() {
@@ -755,12 +755,21 @@ func indirect(v reflect.Value) (rv reflect.Value, isNil bool) {
// the template.
func (s *state) printValue(n parse.Node, v reflect.Value) {
s.at(n)
+ iface, ok := printableValue(v)
+ if !ok {
+ s.errorf("can't print %s of type %s", n, v.Type())
+ }
+ fmt.Fprint(s.wr, iface)
+}
+
+// printableValue returns the, possibly indirected, interface value inside v that
+// is best for a call to formatted printer.
+func printableValue(v reflect.Value) (interface{}, bool) {
if v.Kind() == reflect.Ptr {
v, _ = indirect(v) // fmt.Fprint handles nil.
}
if !v.IsValid() {
- fmt.Fprint(s.wr, "<no value>")
- return
+ return "<no value>", true
}
if !v.Type().Implements(errorType) && !v.Type().Implements(fmtStringerType) {
@@ -769,11 +778,11 @@ func (s *state) printValue(n parse.Node, v reflect.Value) {
} else {
switch v.Kind() {
case reflect.Chan, reflect.Func:
- s.errorf("can't print %s of type %s", n, v.Type())
+ return nil, false
}
}
}
- fmt.Fprint(s.wr, v.Interface())
+ return v.Interface(), true
}
// Types to help sort the keys in a map for reproducible output.
diff --git a/libgo/go/text/template/exec_test.go b/libgo/go/text/template/exec_test.go
index 0ab20acc934..f60702de8f1 100644
--- a/libgo/go/text/template/exec_test.go
+++ b/libgo/go/text/template/exec_test.go
@@ -24,7 +24,7 @@ type T struct {
U16 uint16
X string
FloatZero float64
- ComplexZero float64
+ ComplexZero complex128
// Nested structs.
U *U
// Struct with String method.
@@ -57,6 +57,7 @@ type T struct {
Err error
// Pointers
PI *int
+ PS *string
PSI *[]int
NIL *int
// Function (not method)
@@ -64,6 +65,7 @@ type T struct {
VariadicFunc func(...string) string
VariadicFuncInt func(int, ...string) string
NilOKFunc func(*int) bool
+ ErrFunc func() (string, error)
// Template to test evaluation of templates.
Tmpl *Template
// Unexported field; cannot be accessed by template.
@@ -124,11 +126,13 @@ var tVal = &T{
Str: bytes.NewBuffer([]byte("foozle")),
Err: errors.New("erroozle"),
PI: newInt(23),
+ PS: newString("a string"),
PSI: newIntSlice(21, 22, 23),
BinaryFunc: func(a, b string) string { return fmt.Sprintf("[%s=%s]", a, b) },
VariadicFunc: func(s ...string) string { return fmt.Sprint("<", strings.Join(s, "+"), ">") },
VariadicFuncInt: func(a int, s ...string) string { return fmt.Sprint(a, "=<", strings.Join(s, "+"), ">") },
NilOKFunc: func(s *int) bool { return s == nil },
+ ErrFunc: func() (string, error) { return "bla", nil },
Tmpl: Must(New("x").Parse("test template")), // "x" is the value of .X
}
@@ -141,9 +145,11 @@ var iVal I = tVal
// Helpers for creation.
func newInt(n int) *int {
- p := new(int)
- *p = n
- return p
+ return &n
+}
+
+func newString(s string) *string {
+ return &s
}
func newIntSlice(n ...int) *[]int {
@@ -280,6 +286,7 @@ var execTests = []execTest{
// Pointers.
{"*int", "{{.PI}}", "23", tVal, true},
+ {"*string", "{{.PS}}", "a string", tVal, true},
{"*[]int", "{{.PSI}}", "[21 22 23]", tVal, true},
{"*[]int[1]", "{{index .PSI 1}}", "22", tVal, true},
{"NIL", "{{.NIL}}", "<nil>", tVal, true},
@@ -322,6 +329,7 @@ var execTests = []execTest{
{"if .BinaryFunc call", "{{ if .BinaryFunc}}{{call .BinaryFunc `1` `2`}}{{end}}", "[1=2]", tVal, true},
{"if not .BinaryFunc call", "{{ if not .BinaryFunc}}{{call .BinaryFunc `1` `2`}}{{else}}No{{end}}", "No", tVal, true},
{"Interface Call", `{{stringer .S}}`, "foozle", map[string]interface{}{"S": bytes.NewBufferString("foozle")}, true},
+ {".ErrFunc", "{{call .ErrFunc}}", "bla", tVal, true},
// Erroneous function calls (check args).
{".BinaryFuncTooFew", "{{call .BinaryFunc `1`}}", "", tVal, false},
@@ -366,6 +374,8 @@ var execTests = []execTest{
{"if map not unset", "{{if not .MXI.none}}ZERO{{else}}NON-ZERO{{end}}", "ZERO", tVal, true},
{"if $x with $y int", "{{if $x := true}}{{with $y := .I}}{{$x}},{{$y}}{{end}}{{end}}", "true,17", tVal, true},
{"if $x with $x int", "{{if $x := true}}{{with $x := .I}}{{$x}},{{end}}{{$x}}{{end}}", "17,true", tVal, true},
+ {"if else if", "{{if false}}FALSE{{else if true}}TRUE{{end}}", "TRUE", tVal, true},
+ {"if else chain", "{{if eq 1 3}}1{{else if eq 2 3}}2{{else if eq 3 3}}3{{end}}", "3", tVal, true},
// Print etc.
{"print", `{{print "hello, print"}}`, "hello, print", tVal, true},
@@ -388,6 +398,7 @@ var execTests = []execTest{
"&lt;script&gt;alert(&#34;XSS&#34;);&lt;/script&gt;", nil, true},
{"html pipeline", `{{printf "<script>alert(\"XSS\");</script>" | html}}`,
"&lt;script&gt;alert(&#34;XSS&#34;);&lt;/script&gt;", nil, true},
+ {"html", `{{html .PS}}`, "a string", tVal, true},
// JavaScript.
{"js", `{{js .}}`, `It\'d be nice.`, `It'd be nice.`, true},
@@ -860,3 +871,111 @@ func TestMessageForExecuteEmpty(t *testing.T) {
t.Fatal(err)
}
}
+
+type cmpTest struct {
+ expr string
+ truth string
+ ok bool
+}
+
+var cmpTests = []cmpTest{
+ {"eq true true", "true", true},
+ {"eq true false", "false", true},
+ {"eq 1+2i 1+2i", "true", true},
+ {"eq 1+2i 1+3i", "false", true},
+ {"eq 1.5 1.5", "true", true},
+ {"eq 1.5 2.5", "false", true},
+ {"eq 1 1", "true", true},
+ {"eq 1 2", "false", true},
+ {"eq `xy` `xy`", "true", true},
+ {"eq `xy` `xyz`", "false", true},
+ {"eq .Xuint .Xuint", "true", true},
+ {"eq .Xuint .Yuint", "false", true},
+ {"eq 3 4 5 6 3", "true", true},
+ {"eq 3 4 5 6 7", "false", true},
+ {"ne true true", "false", true},
+ {"ne true false", "true", true},
+ {"ne 1+2i 1+2i", "false", true},
+ {"ne 1+2i 1+3i", "true", true},
+ {"ne 1.5 1.5", "false", true},
+ {"ne 1.5 2.5", "true", true},
+ {"ne 1 1", "false", true},
+ {"ne 1 2", "true", true},
+ {"ne `xy` `xy`", "false", true},
+ {"ne `xy` `xyz`", "true", true},
+ {"ne .Xuint .Xuint", "false", true},
+ {"ne .Xuint .Yuint", "true", true},
+ {"lt 1.5 1.5", "false", true},
+ {"lt 1.5 2.5", "true", true},
+ {"lt 1 1", "false", true},
+ {"lt 1 2", "true", true},
+ {"lt `xy` `xy`", "false", true},
+ {"lt `xy` `xyz`", "true", true},
+ {"lt .Xuint .Xuint", "false", true},
+ {"lt .Xuint .Yuint", "true", true},
+ {"le 1.5 1.5", "true", true},
+ {"le 1.5 2.5", "true", true},
+ {"le 2.5 1.5", "false", true},
+ {"le 1 1", "true", true},
+ {"le 1 2", "true", true},
+ {"le 2 1", "false", true},
+ {"le `xy` `xy`", "true", true},
+ {"le `xy` `xyz`", "true", true},
+ {"le `xyz` `xy`", "false", true},
+ {"le .Xuint .Xuint", "true", true},
+ {"le .Xuint .Yuint", "true", true},
+ {"le .Yuint .Xuint", "false", true},
+ {"gt 1.5 1.5", "false", true},
+ {"gt 1.5 2.5", "false", true},
+ {"gt 1 1", "false", true},
+ {"gt 2 1", "true", true},
+ {"gt 1 2", "false", true},
+ {"gt `xy` `xy`", "false", true},
+ {"gt `xy` `xyz`", "false", true},
+ {"gt .Xuint .Xuint", "false", true},
+ {"gt .Xuint .Yuint", "false", true},
+ {"gt .Yuint .Xuint", "true", true},
+ {"ge 1.5 1.5", "true", true},
+ {"ge 1.5 2.5", "false", true},
+ {"ge 2.5 1.5", "true", true},
+ {"ge 1 1", "true", true},
+ {"ge 1 2", "false", true},
+ {"ge 2 1", "true", true},
+ {"ge `xy` `xy`", "true", true},
+ {"ge `xy` `xyz`", "false", true},
+ {"ge `xyz` `xy`", "true", true},
+ {"ge .Xuint .Xuint", "true", true},
+ {"ge .Xuint .Yuint", "false", true},
+ {"ge .Yuint .Xuint", "true", true},
+ // Errors
+ {"eq `xy` 1", "", false}, // Different types.
+ {"lt true true", "", false}, // Unordered types.
+ {"lt 1+0i 1+0i", "", false}, // Unordered types.
+}
+
+func TestComparison(t *testing.T) {
+ b := new(bytes.Buffer)
+ var cmpStruct = struct {
+ Xuint, Yuint uint
+ }{3, 4}
+ for _, test := range cmpTests {
+ text := fmt.Sprintf("{{if %s}}true{{else}}false{{end}}", test.expr)
+ tmpl, err := New("empty").Parse(text)
+ if err != nil {
+ t.Fatal(err)
+ }
+ b.Reset()
+ err = tmpl.Execute(b, &cmpStruct)
+ if test.ok && err != nil {
+ t.Errorf("%s errored incorrectly: %s", test.expr, err)
+ continue
+ }
+ if !test.ok && err == nil {
+ t.Errorf("%s did not error", test.expr)
+ continue
+ }
+ if b.String() != test.truth {
+ t.Errorf("%s: want %s; got %s", test.expr, test.truth, b.String())
+ }
+ }
+}
diff --git a/libgo/go/text/template/funcs.go b/libgo/go/text/template/funcs.go
index 8187663648a..e854122624e 100644
--- a/libgo/go/text/template/funcs.go
+++ b/libgo/go/text/template/funcs.go
@@ -6,6 +6,7 @@ package template
import (
"bytes"
+ "errors"
"fmt"
"io"
"net/url"
@@ -35,6 +36,14 @@ var builtins = FuncMap{
"printf": fmt.Sprintf,
"println": fmt.Sprintln,
"urlquery": URLQueryEscaper,
+
+ // Comparisons
+ "eq": eq, // ==
+ "ge": ge, // >=
+ "gt": gt, // >
+ "le": le, // <=
+ "lt": lt, // <
+ "ne": ne, // !=
}
var builtinFuncs = createValueFuncs(builtins)
@@ -199,7 +208,7 @@ func call(fn interface{}, args ...interface{}) (interface{}, error) {
argv[i] = value
}
result := v.Call(argv)
- if len(result) == 2 {
+ if len(result) == 2 && !result[1].IsNil() {
return result[0].Interface(), result[1].Interface().(error)
}
return result[0].Interface(), nil
@@ -248,6 +257,160 @@ func not(arg interface{}) (truth bool) {
return !truth
}
+// Comparison.
+
+// TODO: Perhaps allow comparison between signed and unsigned integers.
+
+var (
+ errBadComparisonType = errors.New("invalid type for comparison")
+ errBadComparison = errors.New("incompatible types for comparison")
+ errNoComparison = errors.New("missing argument for comparison")
+)
+
+type kind int
+
+const (
+ invalidKind kind = iota
+ boolKind
+ complexKind
+ intKind
+ floatKind
+ integerKind
+ stringKind
+ uintKind
+)
+
+func basicKind(v reflect.Value) (kind, error) {
+ switch v.Kind() {
+ case reflect.Bool:
+ return boolKind, nil
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return intKind, nil
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ return uintKind, nil
+ case reflect.Float32, reflect.Float64:
+ return floatKind, nil
+ case reflect.Complex64, reflect.Complex128:
+ return complexKind, nil
+ case reflect.String:
+ return stringKind, nil
+ }
+ return invalidKind, errBadComparisonType
+}
+
+// eq evaluates the comparison a == b || a == c || ...
+func eq(arg1 interface{}, arg2 ...interface{}) (bool, error) {
+ v1 := reflect.ValueOf(arg1)
+ k1, err := basicKind(v1)
+ if err != nil {
+ return false, err
+ }
+ if len(arg2) == 0 {
+ return false, errNoComparison
+ }
+ for _, arg := range arg2 {
+ v2 := reflect.ValueOf(arg)
+ k2, err := basicKind(v2)
+ if err != nil {
+ return false, err
+ }
+ if k1 != k2 {
+ return false, errBadComparison
+ }
+ truth := false
+ switch k1 {
+ case boolKind:
+ truth = v1.Bool() == v2.Bool()
+ case complexKind:
+ truth = v1.Complex() == v2.Complex()
+ case floatKind:
+ truth = v1.Float() == v2.Float()
+ case intKind:
+ truth = v1.Int() == v2.Int()
+ case stringKind:
+ truth = v1.String() == v2.String()
+ case uintKind:
+ truth = v1.Uint() == v2.Uint()
+ default:
+ panic("invalid kind")
+ }
+ if truth {
+ return true, nil
+ }
+ }
+ return false, nil
+}
+
+// ne evaluates the comparison a != b.
+func ne(arg1, arg2 interface{}) (bool, error) {
+ // != is the inverse of ==.
+ equal, err := eq(arg1, arg2)
+ return !equal, err
+}
+
+// lt evaluates the comparison a < b.
+func lt(arg1, arg2 interface{}) (bool, error) {
+ v1 := reflect.ValueOf(arg1)
+ k1, err := basicKind(v1)
+ if err != nil {
+ return false, err
+ }
+ v2 := reflect.ValueOf(arg2)
+ k2, err := basicKind(v2)
+ if err != nil {
+ return false, err
+ }
+ if k1 != k2 {
+ return false, errBadComparison
+ }
+ truth := false
+ switch k1 {
+ case boolKind, complexKind:
+ return false, errBadComparisonType
+ case floatKind:
+ truth = v1.Float() < v2.Float()
+ case intKind:
+ truth = v1.Int() < v2.Int()
+ case stringKind:
+ truth = v1.String() < v2.String()
+ case uintKind:
+ truth = v1.Uint() < v2.Uint()
+ default:
+ panic("invalid kind")
+ }
+ return truth, nil
+}
+
+// le evaluates the comparison <= b.
+func le(arg1, arg2 interface{}) (bool, error) {
+ // <= is < or ==.
+ lessThan, err := lt(arg1, arg2)
+ if lessThan || err != nil {
+ return lessThan, err
+ }
+ return eq(arg1, arg2)
+}
+
+// gt evaluates the comparison a > b.
+func gt(arg1, arg2 interface{}) (bool, error) {
+ // > is the inverse of <=.
+ lessOrEqual, err := le(arg1, arg2)
+ if err != nil {
+ return false, err
+ }
+ return !lessOrEqual, nil
+}
+
+// ge evaluates the comparison a >= b.
+func ge(arg1, arg2 interface{}) (bool, error) {
+ // >= is the inverse of <.
+ lessThan, err := lt(arg1, arg2)
+ if err != nil {
+ return false, err
+ }
+ return !lessThan, nil
+}
+
// HTML escaping.
var (
@@ -298,15 +461,7 @@ func HTMLEscapeString(s string) string {
// HTMLEscaper returns the escaped HTML equivalent of the textual
// representation of its arguments.
func HTMLEscaper(args ...interface{}) string {
- ok := false
- var s string
- if len(args) == 1 {
- s, ok = args[0].(string)
- }
- if !ok {
- s = fmt.Sprint(args...)
- }
- return HTMLEscapeString(s)
+ return HTMLEscapeString(evalArgs(args))
}
// JavaScript escaping.
@@ -391,26 +546,35 @@ func jsIsSpecial(r rune) bool {
// JSEscaper returns the escaped JavaScript equivalent of the textual
// representation of its arguments.
func JSEscaper(args ...interface{}) string {
- ok := false
- var s string
- if len(args) == 1 {
- s, ok = args[0].(string)
- }
- if !ok {
- s = fmt.Sprint(args...)
- }
- return JSEscapeString(s)
+ return JSEscapeString(evalArgs(args))
}
// URLQueryEscaper returns the escaped value of the textual representation of
// its arguments in a form suitable for embedding in a URL query.
func URLQueryEscaper(args ...interface{}) string {
- s, ok := "", false
+ return url.QueryEscape(evalArgs(args))
+}
+
+// evalArgs formats the list of arguments into a string. It is therefore equivalent to
+// fmt.Sprint(args...)
+// except that each argument is indirected (if a pointer), as required,
+// using the same rules as the default string evaluation during template
+// execution.
+func evalArgs(args []interface{}) string {
+ ok := false
+ var s string
+ // Fast path for simple common case.
if len(args) == 1 {
s, ok = args[0].(string)
}
if !ok {
+ for i, arg := range args {
+ a, ok := printableValue(reflect.ValueOf(arg))
+ if ok {
+ args[i] = a
+ } // else left fmt do its thing
+ }
s = fmt.Sprint(args...)
}
- return url.QueryEscape(s)
+ return s
}
diff --git a/libgo/go/text/template/multi_test.go b/libgo/go/text/template/multi_test.go
index bd98bd047ec..1f6ed5d8e22 100644
--- a/libgo/go/text/template/multi_test.go
+++ b/libgo/go/text/template/multi_test.go
@@ -33,10 +33,10 @@ var multiParseTests = []multiParseTest{
nil},
{"one", `{{define "foo"}} FOO {{end}}`, noError,
[]string{"foo"},
- []string{`" FOO "`}},
+ []string{" FOO "}},
{"two", `{{define "foo"}} FOO {{end}}{{define "bar"}} BAR {{end}}`, noError,
[]string{"foo", "bar"},
- []string{`" FOO "`, `" BAR "`}},
+ []string{" FOO ", " BAR "}},
// errors
{"missing end", `{{define "foo"}} FOO `, hasError,
nil,
diff --git a/libgo/go/text/template/parse/lex.go b/libgo/go/text/template/parse/lex.go
index 23c0cf0793c..1674aaf9cd4 100644
--- a/libgo/go/text/template/parse/lex.go
+++ b/libgo/go/text/template/parse/lex.go
@@ -243,11 +243,16 @@ func lexLeftDelim(l *lexer) stateFn {
// lexComment scans a comment. The left comment marker is known to be present.
func lexComment(l *lexer) stateFn {
l.pos += Pos(len(leftComment))
- i := strings.Index(l.input[l.pos:], rightComment+l.rightDelim)
+ i := strings.Index(l.input[l.pos:], rightComment)
if i < 0 {
return l.errorf("unclosed comment")
}
- l.pos += Pos(i + len(rightComment) + len(l.rightDelim))
+ l.pos += Pos(i + len(rightComment))
+ if !strings.HasPrefix(l.input[l.pos:], l.rightDelim) {
+ return l.errorf("comment ends before closing delimiter")
+
+ }
+ l.pos += Pos(len(l.rightDelim))
l.ignore()
return lexText
}
diff --git a/libgo/go/text/template/parse/lex_test.go b/libgo/go/text/template/parse/lex_test.go
index d2264c991c9..d251ccffb6c 100644
--- a/libgo/go/text/template/parse/lex_test.go
+++ b/libgo/go/text/template/parse/lex_test.go
@@ -336,6 +336,16 @@ var lexTests = []lexTest{
{itemText, 0, "hello-"},
{itemError, 0, `unclosed comment`},
}},
+ {"text with comment close separted from delim", "hello-{{/* */ }}-world", []item{
+ {itemText, 0, "hello-"},
+ {itemError, 0, `comment ends before closing delimiter`},
+ }},
+ // This one is an error that we can't catch because it breaks templates with
+ // minimized JavaScript. Should have fixed it before Go 1.1.
+ {"unmatched right delimiter", "hello-{.}}-world", []item{
+ {itemText, 0, "hello-{.}}-world"},
+ tEOF,
+ }},
}
// collect gathers the emitted items into a slice.
diff --git a/libgo/go/text/template/parse/node.go b/libgo/go/text/template/parse/node.go
index 9d0d09eb5fa..dc6a3bb929c 100644
--- a/libgo/go/text/template/parse/node.go
+++ b/libgo/go/text/template/parse/node.go
@@ -13,6 +13,8 @@ import (
"strings"
)
+var textFormat = "%s" // Changed to "%q" in tests for better error messages.
+
// A Node is an element in the parse tree. The interface is trivial.
// The interface contains an unexported method so that only
// types local to this package can satisfy it.
@@ -125,7 +127,7 @@ func newText(pos Pos, text string) *TextNode {
}
func (t *TextNode) String() string {
- return fmt.Sprintf("%q", t.Text)
+ return fmt.Sprintf(textFormat, t.Text)
}
func (t *TextNode) Copy() Node {
diff --git a/libgo/go/text/template/parse/parse.go b/libgo/go/text/template/parse/parse.go
index 802e298c230..34112fb7b35 100644
--- a/libgo/go/text/template/parse/parse.go
+++ b/libgo/go/text/template/parse/parse.go
@@ -14,7 +14,6 @@ import (
"runtime"
"strconv"
"strings"
- "unicode"
)
// Tree is the representation of a single parsed template.
@@ -31,6 +30,19 @@ type Tree struct {
vars []string // variables defined at the moment.
}
+// Copy returns a copy of the Tree. Any parsing state is discarded.
+func (t *Tree) Copy() *Tree {
+ if t == nil {
+ return nil
+ }
+ return &Tree{
+ Name: t.Name,
+ ParseName: t.ParseName,
+ Root: t.Root.CopyList(),
+ text: t.text,
+ }
+}
+
// Parse returns a map from template name to parse.Tree, created by parsing the
// templates described in the argument string. The top-level template will be
// given the specified name. If an error is encountered, parsing stops and an
@@ -200,27 +212,6 @@ func (t *Tree) stopParse() {
t.funcs = nil
}
-// atEOF returns true if, possibly after spaces, we're at EOF.
-func (t *Tree) atEOF() bool {
- for {
- token := t.peek()
- switch token.typ {
- case itemEOF:
- return true
- case itemText:
- for _, r := range token.val {
- if !unicode.IsSpace(r) {
- return false
- }
- }
- t.next() // skip spaces.
- continue
- }
- break
- }
- return false
-}
-
// Parse parses the template definition string to construct a representation of
// the template for execution. If either action delimiter string is empty, the
// default ("{{" or "}}") is used. Embedded template definitions are added to
@@ -431,7 +422,7 @@ func (t *Tree) pipeline(context string) (pipe *PipeNode) {
}
}
-func (t *Tree) parseControl(context string) (pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) {
+func (t *Tree) parseControl(allowElseIf bool, context string) (pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) {
defer t.popVars(len(t.vars))
line = t.lex.lineNumber()
pipe = t.pipeline(context)
@@ -440,6 +431,23 @@ func (t *Tree) parseControl(context string) (pos Pos, line int, pipe *PipeNode,
switch next.Type() {
case nodeEnd: //done
case nodeElse:
+ if allowElseIf {
+ // Special case for "else if". If the "else" is followed immediately by an "if",
+ // the elseControl will have left the "if" token pending. Treat
+ // {{if a}}_{{else if b}}_{{end}}
+ // as
+ // {{if a}}_{{else}}{{if b}}_{{end}}{{end}}.
+ // To do this, parse the if as usual and stop at it {{end}}; the subsequent{{end}}
+ // is assumed. This technique works even for long if-else-if chains.
+ // TODO: Should we allow else-if in with and range?
+ if t.peek().typ == itemIf {
+ t.next() // Consume the "if" token.
+ elseList = newList(next.Position())
+ elseList.append(t.ifControl())
+ // Do not consume the next item - only one {{end}} required.
+ break
+ }
+ }
elseList, next = t.itemList()
if next.Type() != nodeEnd {
t.errorf("expected end; found %s", next)
@@ -453,7 +461,7 @@ func (t *Tree) parseControl(context string) (pos Pos, line int, pipe *PipeNode,
// {{if pipeline}} itemList {{else}} itemList {{end}}
// If keyword is past.
func (t *Tree) ifControl() Node {
- return newIf(t.parseControl("if"))
+ return newIf(t.parseControl(true, "if"))
}
// Range:
@@ -461,7 +469,7 @@ func (t *Tree) ifControl() Node {
// {{range pipeline}} itemList {{else}} itemList {{end}}
// Range keyword is past.
func (t *Tree) rangeControl() Node {
- return newRange(t.parseControl("range"))
+ return newRange(t.parseControl(false, "range"))
}
// With:
@@ -469,7 +477,7 @@ func (t *Tree) rangeControl() Node {
// {{with pipeline}} itemList {{else}} itemList {{end}}
// If keyword is past.
func (t *Tree) withControl() Node {
- return newWith(t.parseControl("with"))
+ return newWith(t.parseControl(false, "with"))
}
// End:
@@ -483,6 +491,12 @@ func (t *Tree) endControl() Node {
// {{else}}
// Else keyword is past.
func (t *Tree) elseControl() Node {
+ // Special case for "else if".
+ peek := t.peekNonSpace()
+ if peek.typ == itemIf {
+ // We see "{{else if ... " but in effect rewrite it to {{else}}{{if ... ".
+ return newElse(peek.pos, t.lex.lineNumber())
+ }
return newElse(t.expect(itemRightDelim, "else").pos, t.lex.lineNumber())
}
diff --git a/libgo/go/text/template/parse/parse_test.go b/libgo/go/text/template/parse/parse_test.go
index 695c76ebfe3..ba1a18ec542 100644
--- a/libgo/go/text/template/parse/parse_test.go
+++ b/libgo/go/text/template/parse/parse_test.go
@@ -194,6 +194,10 @@ var parseTests = []parseTest{
`{{if .X}}"hello"{{end}}`},
{"if with else", "{{if .X}}true{{else}}false{{end}}", noError,
`{{if .X}}"true"{{else}}"false"{{end}}`},
+ {"if with else if", "{{if .X}}true{{else if .Y}}false{{end}}", noError,
+ `{{if .X}}"true"{{else}}{{if .Y}}"false"{{end}}{{end}}`},
+ {"if else chain", "+{{if .X}}X{{else if .Y}}Y{{else if .Z}}Z{{end}}+", noError,
+ `"+"{{if .X}}"X"{{else}}{{if .Y}}"Y"{{else}}{{if .Z}}"Z"{{end}}{{end}}{{end}}"+"`},
{"simple range", "{{range .X}}hello{{end}}", noError,
`{{range .X}}"hello"{{end}}`},
{"chained field range", "{{range .X.Y.Z}}hello{{end}}", noError,
@@ -238,6 +242,7 @@ var parseTests = []parseTest{
{"dot applied to parentheses", "{{printf (printf .).}}", hasError, ""},
{"adjacent args", "{{printf 3`x`}}", hasError, ""},
{"adjacent args with .", "{{printf `x`.}}", hasError, ""},
+ {"extra end after if", "{{if .X}}a{{else if .Y}}b{{end}}{{end}}", hasError, ""},
// Equals (and other chars) do not assignments make (yet).
{"bug0a", "{{$x := 0}}{{$x}}", noError, "{{$x := 0}}{{$x}}"},
{"bug0b", "{{$x = 1}}{{$x}}", hasError, ""},
@@ -256,6 +261,8 @@ var builtins = map[string]interface{}{
}
func testParse(doCopy bool, t *testing.T) {
+ textFormat = "%q"
+ defer func() { textFormat = "%s" }()
for _, test := range parseTests {
tmpl, err := New(test.name).Parse(test.input, "", "", make(map[string]*Tree), builtins)
switch {
@@ -305,7 +312,7 @@ var isEmptyTests = []isEmptyTest{
{"spaces only", " \t\n \t\n", true},
{"definition", `{{define "x"}}something{{end}}`, true},
{"definitions and space", "{{define `x`}}something{{end}}\n\n{{define `y`}}something{{end}}\n\n", true},
- {"definitions and text", "{{define `x`}}something{{end}}\nx\n{{define `y`}}something{{end}}\ny\n}}", false},
+ {"definitions and text", "{{define `x`}}something{{end}}\nx\n{{define `y`}}something{{end}}\ny\n", false},
{"definition and action", "{{define `x`}}something{{end}}{{if 3}}foo{{end}}", false},
}
@@ -325,6 +332,22 @@ func TestIsEmpty(t *testing.T) {
}
}
+func TestErrorContextWithTreeCopy(t *testing.T) {
+ tree, err := New("root").Parse("{{if true}}{{end}}", "", "", make(map[string]*Tree), nil)
+ if err != nil {
+ t.Fatalf("unexpected tree parse failure: %v", err)
+ }
+ treeCopy := tree.Copy()
+ wantLocation, wantContext := tree.ErrorContext(tree.Root.Nodes[0])
+ gotLocation, gotContext := treeCopy.ErrorContext(treeCopy.Root.Nodes[0])
+ if wantLocation != gotLocation {
+ t.Errorf("wrong error location want %q got %q", wantLocation, gotLocation)
+ }
+ if wantContext != gotContext {
+ t.Errorf("wrong error location want %q got %q", wantContext, gotContext)
+ }
+}
+
// All failures, and the result is a string that must appear in the error message.
var errorTests = []parseTest{
// Check line numbers are accurate.
diff --git a/libgo/go/time/export_test.go b/libgo/go/time/export_test.go
index 130ca8f7ebe..dbd553af49d 100644
--- a/libgo/go/time/export_test.go
+++ b/libgo/go/time/export_test.go
@@ -17,3 +17,5 @@ func ForceUSPacificForTesting() {
ResetLocalOnceForTest()
localOnce.Do(initTestingZone)
}
+
+var ParseTimeZone = parseTimeZone
diff --git a/libgo/go/time/format.go b/libgo/go/time/format.go
index 7fe0402312f..6f92c126268 100644
--- a/libgo/go/time/format.go
+++ b/libgo/go/time/format.go
@@ -59,35 +59,39 @@ const (
)
const (
- _ = iota
- stdLongMonth = iota + stdNeedDate // "January"
- stdMonth // "Jan"
- stdNumMonth // "1"
- stdZeroMonth // "01"
- stdLongWeekDay // "Monday"
- stdWeekDay // "Mon"
- stdDay // "2"
- stdUnderDay // "_2"
- stdZeroDay // "02"
- stdHour = iota + stdNeedClock // "15"
- stdHour12 // "3"
- stdZeroHour12 // "03"
- stdMinute // "4"
- stdZeroMinute // "04"
- stdSecond // "5"
- stdZeroSecond // "05"
- stdLongYear = iota + stdNeedDate // "2006"
- stdYear // "06"
- stdPM = iota + stdNeedClock // "PM"
- stdpm // "pm"
- stdTZ = iota // "MST"
- stdISO8601TZ // "Z0700" // prints Z for UTC
- stdISO8601ColonTZ // "Z07:00" // prints Z for UTC
- stdNumTZ // "-0700" // always numeric
- stdNumShortTZ // "-07" // always numeric
- stdNumColonTZ // "-07:00" // always numeric
- stdFracSecond0 // ".0", ".00", ... , trailing zeros included
- stdFracSecond9 // ".9", ".99", ..., trailing zeros omitted
+ _ = iota
+ stdLongMonth = iota + stdNeedDate // "January"
+ stdMonth // "Jan"
+ stdNumMonth // "1"
+ stdZeroMonth // "01"
+ stdLongWeekDay // "Monday"
+ stdWeekDay // "Mon"
+ stdDay // "2"
+ stdUnderDay // "_2"
+ stdZeroDay // "02"
+ stdHour = iota + stdNeedClock // "15"
+ stdHour12 // "3"
+ stdZeroHour12 // "03"
+ stdMinute // "4"
+ stdZeroMinute // "04"
+ stdSecond // "5"
+ stdZeroSecond // "05"
+ stdLongYear = iota + stdNeedDate // "2006"
+ stdYear // "06"
+ stdPM = iota + stdNeedClock // "PM"
+ stdpm // "pm"
+ stdTZ = iota // "MST"
+ stdISO8601TZ // "Z0700" // prints Z for UTC
+ stdISO8601SecondsTZ // "Z070000"
+ stdISO8601ColonTZ // "Z07:00" // prints Z for UTC
+ stdISO8601ColonSecondsTZ // "Z07:00:00"
+ stdNumTZ // "-0700" // always numeric
+ stdNumSecondsTz // "-070000"
+ stdNumShortTZ // "-07" // always numeric
+ stdNumColonTZ // "-07:00" // always numeric
+ stdNumColonSecondsTZ // "-07:00:00"
+ stdFracSecond0 // ".0", ".00", ... , trailing zeros included
+ stdFracSecond9 // ".9", ".99", ..., trailing zeros omitted
stdNeedDate = 1 << 8 // need month, day, year
stdNeedClock = 2 << 8 // need hour, minute, second
@@ -98,6 +102,16 @@ const (
// std0x records the std values for "01", "02", ..., "06".
var std0x = [...]int{stdZeroMonth, stdZeroDay, stdZeroHour12, stdZeroMinute, stdZeroSecond, stdYear}
+// startsWithLowerCase reports whether the the string has a lower-case letter at the beginning.
+// Its purpose is to prevent matching strings like "Month" when looking for "Mon".
+func startsWithLowerCase(str string) bool {
+ if len(str) == 0 {
+ return false
+ }
+ c := str[0]
+ return 'a' <= c && c <= 'z'
+}
+
// nextStdChunk finds the first occurrence of a std string in
// layout and returns the text before, the std string, and the text after.
func nextStdChunk(layout string) (prefix string, std int, suffix string) {
@@ -108,7 +122,9 @@ func nextStdChunk(layout string) (prefix string, std int, suffix string) {
if len(layout) >= i+7 && layout[i:i+7] == "January" {
return layout[0:i], stdLongMonth, layout[i+7:]
}
- return layout[0:i], stdMonth, layout[i+3:]
+ if !startsWithLowerCase(layout[i+3:]) {
+ return layout[0:i], stdMonth, layout[i+3:]
+ }
}
case 'M': // Monday, Mon, MST
@@ -117,7 +133,9 @@ func nextStdChunk(layout string) (prefix string, std int, suffix string) {
if len(layout) >= i+6 && layout[i:i+6] == "Monday" {
return layout[0:i], stdLongWeekDay, layout[i+6:]
}
- return layout[0:i], stdWeekDay, layout[i+3:]
+ if !startsWithLowerCase(layout[i+3:]) {
+ return layout[0:i], stdWeekDay, layout[i+3:]
+ }
}
if layout[i:i+3] == "MST" {
return layout[0:i], stdTZ, layout[i+3:]
@@ -165,7 +183,13 @@ func nextStdChunk(layout string) (prefix string, std int, suffix string) {
return layout[0:i], stdpm, layout[i+2:]
}
- case '-': // -0700, -07:00, -07
+ case '-': // -070000, -07:00:00, -0700, -07:00, -07
+ if len(layout) >= i+7 && layout[i:i+7] == "-070000" {
+ return layout[0:i], stdNumSecondsTz, layout[i+7:]
+ }
+ if len(layout) >= i+9 && layout[i:i+9] == "-07:00:00" {
+ return layout[0:i], stdNumColonSecondsTZ, layout[i+9:]
+ }
if len(layout) >= i+5 && layout[i:i+5] == "-0700" {
return layout[0:i], stdNumTZ, layout[i+5:]
}
@@ -175,13 +199,21 @@ func nextStdChunk(layout string) (prefix string, std int, suffix string) {
if len(layout) >= i+3 && layout[i:i+3] == "-07" {
return layout[0:i], stdNumShortTZ, layout[i+3:]
}
- case 'Z': // Z0700, Z07:00
+
+ case 'Z': // Z070000, Z07:00:00, Z0700, Z07:00,
+ if len(layout) >= i+7 && layout[i:i+7] == "Z070000" {
+ return layout[0:i], stdISO8601SecondsTZ, layout[i+7:]
+ }
+ if len(layout) >= i+9 && layout[i:i+9] == "Z07:00:00" {
+ return layout[0:i], stdISO8601ColonSecondsTZ, layout[i+9:]
+ }
if len(layout) >= i+5 && layout[i:i+5] == "Z0700" {
return layout[0:i], stdISO8601TZ, layout[i+5:]
}
if len(layout) >= i+6 && layout[i:i+6] == "Z07:00" {
return layout[0:i], stdISO8601ColonTZ, layout[i+6:]
}
+
case '.': // .000 or .999 - repeated digits for fractional seconds.
if i+1 < len(layout) && (layout[i+1] == '0' || layout[i+1] == '9') {
ch := layout[i+1]
@@ -321,8 +353,8 @@ var atoiError = errors.New("time: invalid number")
// Duplicates functionality in strconv, but avoids dependency.
func atoi(s string) (x int, err error) {
neg := false
- if s != "" && s[0] == '-' {
- neg = true
+ if s != "" && (s[0] == '-' || s[0] == '+') {
+ neg = s[0] == '-'
s = s[1:]
}
q, rem, err := leadingInt(s)
@@ -507,17 +539,19 @@ func (t Time) Format(layout string) string {
} else {
b = append(b, "am"...)
}
- case stdISO8601TZ, stdISO8601ColonTZ, stdNumTZ, stdNumColonTZ:
+ case stdISO8601TZ, stdISO8601ColonTZ, stdISO8601SecondsTZ, stdISO8601ColonSecondsTZ, stdNumTZ, stdNumColonTZ, stdNumSecondsTz, stdNumColonSecondsTZ:
// Ugly special case. We cheat and take the "Z" variants
// to mean "the time zone as formatted for ISO 8601".
- if offset == 0 && (std == stdISO8601TZ || std == stdISO8601ColonTZ) {
+ if offset == 0 && (std == stdISO8601TZ || std == stdISO8601ColonTZ || std == stdISO8601SecondsTZ || std == stdISO8601ColonSecondsTZ) {
b = append(b, 'Z')
break
}
zone := offset / 60 // convert to minutes
+ absoffset := offset
if zone < 0 {
b = append(b, '-')
zone = -zone
+ absoffset = -absoffset
} else {
b = append(b, '+')
}
@@ -526,6 +560,15 @@ func (t Time) Format(layout string) string {
b = append(b, ':')
}
b = appendUint(b, uint(zone%60), '0')
+
+ // append seconds if appropriate
+ if std == stdISO8601SecondsTZ || std == stdNumSecondsTz || std == stdNumColonSecondsTZ || std == stdISO8601ColonSecondsTZ {
+ if std == stdNumColonSecondsTZ || std == stdISO8601ColonSecondsTZ {
+ b = append(b, ':')
+ }
+ b = appendUint(b, uint(absoffset%60), '0')
+ }
+
case stdTZ:
if name != "" {
b = append(b, name...)
@@ -780,7 +823,7 @@ func parse(layout, value string, defaultLocation, local *Location) (Time, error)
// Special case: do we have a fractional second but no
// fractional second in the format?
if len(value) >= 2 && value[0] == '.' && isDigit(value, 1) {
- _, std, _ := nextStdChunk(layout)
+ _, std, _ = nextStdChunk(layout)
std &= stdMask
if std == stdFracSecond0 || std == stdFracSecond9 {
// Fractional second in the layout; proceed normally
@@ -821,13 +864,13 @@ func parse(layout, value string, defaultLocation, local *Location) (Time, error)
default:
err = errBad
}
- case stdISO8601TZ, stdISO8601ColonTZ, stdNumTZ, stdNumShortTZ, stdNumColonTZ:
+ case stdISO8601TZ, stdISO8601ColonTZ, stdISO8601SecondsTZ, stdISO8601ColonSecondsTZ, stdNumTZ, stdNumShortTZ, stdNumColonTZ, stdNumSecondsTz, stdNumColonSecondsTZ:
if (std == stdISO8601TZ || std == stdISO8601ColonTZ) && len(value) >= 1 && value[0] == 'Z' {
value = value[1:]
z = UTC
break
}
- var sign, hour, min string
+ var sign, hour, min, seconds string
if std == stdISO8601ColonTZ || std == stdNumColonTZ {
if len(value) < 6 {
err = errBad
@@ -837,26 +880,45 @@ func parse(layout, value string, defaultLocation, local *Location) (Time, error)
err = errBad
break
}
- sign, hour, min, value = value[0:1], value[1:3], value[4:6], value[6:]
+ sign, hour, min, seconds, value = value[0:1], value[1:3], value[4:6], "00", value[6:]
} else if std == stdNumShortTZ {
if len(value) < 3 {
err = errBad
break
}
- sign, hour, min, value = value[0:1], value[1:3], "00", value[3:]
+ sign, hour, min, seconds, value = value[0:1], value[1:3], "00", "00", value[3:]
+ } else if std == stdISO8601ColonSecondsTZ || std == stdNumColonSecondsTZ {
+ if len(value) < 9 {
+ err = errBad
+ break
+ }
+ if value[3] != ':' || value[6] != ':' {
+ err = errBad
+ break
+ }
+ sign, hour, min, seconds, value = value[0:1], value[1:3], value[4:6], value[7:9], value[9:]
+ } else if std == stdISO8601SecondsTZ || std == stdNumSecondsTz {
+ if len(value) < 7 {
+ err = errBad
+ break
+ }
+ sign, hour, min, seconds, value = value[0:1], value[1:3], value[3:5], value[5:7], value[7:]
} else {
if len(value) < 5 {
err = errBad
break
}
- sign, hour, min, value = value[0:1], value[1:3], value[3:5], value[5:]
+ sign, hour, min, seconds, value = value[0:1], value[1:3], value[3:5], "00", value[5:]
}
- var hr, mm int
+ var hr, mm, ss int
hr, err = atoi(hour)
if err == nil {
mm, err = atoi(min)
}
- zoneOffset = (hr*60 + mm) * 60 // offset is in seconds
+ if err == nil {
+ ss, err = atoi(seconds)
+ }
+ zoneOffset = (hr*60+mm)*60 + ss // offset is in seconds
switch sign[0] {
case '+':
case '-':
@@ -871,25 +933,12 @@ func parse(layout, value string, defaultLocation, local *Location) (Time, error)
value = value[3:]
break
}
-
- if len(value) >= 3 && value[2] == 'T' {
- p, value = value[0:3], value[3:]
- } else if len(value) >= 4 && value[3] == 'T' {
- p, value = value[0:4], value[4:]
- } else {
+ n, ok := parseTimeZone(value)
+ if !ok {
err = errBad
break
}
- for i := 0; i < len(p); i++ {
- if p[i] < 'A' || 'Z' < p[i] {
- err = errBad
- }
- }
- if err != nil {
- break
- }
- // It's a valid format.
- zoneName = p
+ zoneName, value = value[:n], value[n:]
case stdFracSecond0:
// stdFracSecond0 requires the exact number of digits as specified in
@@ -962,7 +1011,11 @@ func parse(layout, value string, defaultLocation, local *Location) (Time, error)
}
// Otherwise, create fake zone with unknown offset.
- t.loc = FixedZone(zoneName, 0)
+ if len(zoneName) > 3 && zoneName[:3] == "GMT" {
+ offset, _ = atoi(zoneName[3:]) // Guaranteed OK by parseGMT.
+ offset *= 3600
+ }
+ t.loc = FixedZone(zoneName, offset)
return t, nil
}
@@ -970,6 +1023,81 @@ func parse(layout, value string, defaultLocation, local *Location) (Time, error)
return Date(year, Month(month), day, hour, min, sec, nsec, defaultLocation), nil
}
+// parseTimeZone parses a time zone string and returns its length. Time zones
+// are human-generated and unpredictable. We can't do precise error checking.
+// On the other hand, for a correct parse there must be a time zone at the
+// beginning of the string, so it's almost always true that there's one
+// there. We look at the beginning of the string for a run of upper-case letters.
+// If there are more than 5, it's an error.
+// If there are 4 or 5 and the last is a T, it's a time zone.
+// If there are 3, it's a time zone.
+// Otherwise, other than special cases, it's not a time zone.
+// GMT is special because it can have an hour offset.
+func parseTimeZone(value string) (length int, ok bool) {
+ if len(value) < 3 {
+ return 0, false
+ }
+ // Special case 1: This is the only zone with a lower-case letter.
+ if len(value) >= 4 && value[:4] == "ChST" {
+ return 4, true
+ }
+ // Special case 2: GMT may have an hour offset; treat it specially.
+ if value[:3] == "GMT" {
+ length = parseGMT(value)
+ return length, true
+ }
+ // How many upper-case letters are there? Need at least three, at most five.
+ var nUpper int
+ for nUpper = 0; nUpper < 6; nUpper++ {
+ if nUpper >= len(value) {
+ break
+ }
+ if c := value[nUpper]; c < 'A' || 'Z' < c {
+ break
+ }
+ }
+ switch nUpper {
+ case 0, 1, 2, 6:
+ return 0, false
+ case 5: // Must end in T to match.
+ if value[4] == 'T' {
+ return 5, true
+ }
+ case 4: // Must end in T to match.
+ if value[3] == 'T' {
+ return 4, true
+ }
+ case 3:
+ return 3, true
+ }
+ return 0, false
+}
+
+// parseGMT parses a GMT time zone. The input string is known to start "GMT".
+// The function checks whether that is followed by a sign and a number in the
+// range -14 through 12 excluding zero.
+func parseGMT(value string) int {
+ value = value[3:]
+ if len(value) == 0 {
+ return 3
+ }
+ sign := value[0]
+ if sign != '-' && sign != '+' {
+ return 3
+ }
+ x, rem, err := leadingInt(value[1:])
+ if err != nil {
+ return 3
+ }
+ if sign == '-' {
+ x = -x
+ }
+ if x == 0 || x < -14 || 12 < x {
+ return 3
+ }
+ return 3 + len(value) - len(rem)
+}
+
func parseNanoseconds(value string, nbytes int) (ns int, rangeErrString string, err error) {
if value[0] != '.' {
err = errBad
@@ -1076,11 +1204,11 @@ func ParseDuration(s string) (Duration, error) {
if err != nil {
return 0, errors.New("time: invalid duration " + orig)
}
- scale := 1
+ scale := 1.0
for n := pl - len(s); n > 0; n-- {
scale *= 10
}
- g += float64(x) / float64(scale)
+ g += float64(x) / scale
post = pl != len(s)
}
if !pre && !post {
diff --git a/libgo/go/time/genzabbrs.go b/libgo/go/time/genzabbrs.go
new file mode 100644
index 00000000000..7c637cb43a7
--- /dev/null
+++ b/libgo/go/time/genzabbrs.go
@@ -0,0 +1,145 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+//
+// usage:
+//
+// go run genzabbrs.go | gofmt > $GOROOT/src/pkg/time/zoneinfo_abbrs_windows.go
+//
+
+package main
+
+import (
+ "encoding/xml"
+ "io/ioutil"
+ "log"
+ "net/http"
+ "os"
+ "sort"
+ "text/template"
+ "time"
+)
+
+// getAbbrs finds timezone abbreviations (standard and daylight saving time)
+// for location l.
+func getAbbrs(l *time.Location) (st, dt string) {
+ t := time.Date(time.Now().Year(), 0, 0, 0, 0, 0, 0, l)
+ abbr1, off1 := t.Zone()
+ for i := 0; i < 12; i++ {
+ t = t.AddDate(0, 1, 0)
+ abbr2, off2 := t.Zone()
+ if abbr1 != abbr2 {
+ if off2-off1 < 0 { // southern hemisphere
+ abbr1, abbr2 = abbr2, abbr1
+ }
+ return abbr1, abbr2
+ }
+ }
+ return abbr1, abbr1
+}
+
+type zone struct {
+ WinName string
+ UnixName string
+ StTime string
+ DSTime string
+}
+
+type zones []*zone
+
+func (zs zones) Len() int { return len(zs) }
+func (zs zones) Swap(i, j int) { zs[i], zs[j] = zs[j], zs[i] }
+func (zs zones) Less(i, j int) bool { return zs[i].UnixName < zs[j].UnixName }
+
+const wzURL = "http://unicode.org/cldr/data/common/supplemental/windowsZones.xml"
+
+type MapZone struct {
+ Other string `xml:"other,attr"`
+ Territory string `xml:"territory,attr"`
+ Type string `xml:"type,attr"`
+}
+
+type SupplementalData struct {
+ Zones []MapZone `xml:"windowsZones>mapTimezones>mapZone"`
+}
+
+func readWindowsZones() (zones, error) {
+ r, err := http.Get(wzURL)
+ if err != nil {
+ return nil, err
+ }
+ defer r.Body.Close()
+
+ data, err := ioutil.ReadAll(r.Body)
+ if err != nil {
+ return nil, err
+ }
+
+ var sd SupplementalData
+ err = xml.Unmarshal(data, &sd)
+ if err != nil {
+ return nil, err
+ }
+ zs := make(zones, 0)
+ for _, z := range sd.Zones {
+ if z.Territory != "001" {
+ // to avoid dups. I don't know why.
+ continue
+ }
+ l, err := time.LoadLocation(z.Type)
+ if err != nil {
+ return nil, err
+ }
+ st, dt := getAbbrs(l)
+ zs = append(zs, &zone{
+ WinName: z.Other,
+ UnixName: z.Type,
+ StTime: st,
+ DSTime: dt,
+ })
+ }
+ return zs, nil
+}
+
+func main() {
+ zs, err := readWindowsZones()
+ if err != nil {
+ log.Fatal(err)
+ }
+ sort.Sort(zs)
+ var v = struct {
+ URL string
+ Zs zones
+ }{
+ wzURL,
+ zs,
+ }
+ err = template.Must(template.New("prog").Parse(prog)).Execute(os.Stdout, v)
+ if err != nil {
+ log.Fatal(err)
+ }
+}
+
+const prog = `
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// generated by genzabbrs.go from
+// {{.URL}}
+
+package time
+
+type abbr struct {
+ std string
+ dst string
+}
+
+var abbrs = map[string]abbr{
+{{range .Zs}} "{{.WinName}}": {"{{.StTime}}", "{{.DSTime}}"}, // {{.UnixName}}
+{{end}}}
+
+`
diff --git a/libgo/go/time/internal_test.go b/libgo/go/time/internal_test.go
index 918a9f33be6..87fdd3216fa 100644
--- a/libgo/go/time/internal_test.go
+++ b/libgo/go/time/internal_test.go
@@ -4,6 +4,11 @@
package time
+import (
+ "errors"
+ "runtime"
+)
+
func init() {
// force US/Pacific for time zone tests
ForceUSPacificForTesting()
@@ -11,3 +16,65 @@ func init() {
var Interrupt = interrupt
var DaysIn = daysIn
+
+func empty(now int64, arg interface{}) {}
+
+// Test that a runtimeTimer with a duration so large it overflows
+// does not cause other timers to hang.
+//
+// This test has to be in internal_test.go since it fiddles with
+// unexported data structures.
+func CheckRuntimeTimerOverflow() error {
+ // We manually create a runtimeTimer to bypass the overflow
+ // detection logic in NewTimer: we're testing the underlying
+ // runtime.addtimer function.
+ r := &runtimeTimer{
+ when: nano() + (1<<63 - 1),
+ f: empty,
+ arg: nil,
+ }
+ startTimer(r)
+
+ timeout := 100 * Millisecond
+ if runtime.GOOS == "windows" {
+ // Allow more time for gobuilder to succeed.
+ timeout = Second
+ }
+
+ // Start a goroutine that should send on t.C before the timeout.
+ t := NewTimer(1)
+
+ defer func() {
+ // Subsequent tests won't work correctly if we don't stop the
+ // overflow timer and kick the timer proc back into service.
+ //
+ // The timer proc is now sleeping and can only be awoken by
+ // adding a timer to the *beginning* of the heap. We can't
+ // wake it up by calling NewTimer since other tests may have
+ // left timers running that should have expired before ours.
+ // Instead we zero the overflow timer duration and start it
+ // once more.
+ stopTimer(r)
+ t.Stop()
+ r.when = 0
+ startTimer(r)
+ }()
+
+ // Try to receive from t.C before the timeout. It will succeed
+ // iff the previous sleep was able to finish. We're forced to
+ // spin and yield after trying to receive since we can't start
+ // any more timers (they might hang due to the same bug we're
+ // now testing).
+ stop := Now().Add(timeout)
+ for {
+ select {
+ case <-t.C:
+ return nil // It worked!
+ default:
+ if Now().After(stop) {
+ return errors.New("runtime timer stuck: overflow in addtimer")
+ }
+ runtime.Gosched()
+ }
+ }
+}
diff --git a/libgo/go/time/sleep.go b/libgo/go/time/sleep.go
index 591fa27b090..4f55bebe62a 100644
--- a/libgo/go/time/sleep.go
+++ b/libgo/go/time/sleep.go
@@ -4,7 +4,8 @@
package time
-// Sleep pauses the current goroutine for the duration d.
+// Sleep pauses the current goroutine for at least the duration d.
+// A negative or zero duration causes Sleep to return immediately.
func Sleep(d Duration)
func nano() int64 {
diff --git a/libgo/go/time/sleep_test.go b/libgo/go/time/sleep_test.go
index 762549d3a4d..cb09a84469e 100644
--- a/libgo/go/time/sleep_test.go
+++ b/libgo/go/time/sleep_test.go
@@ -9,6 +9,7 @@ import (
"fmt"
"runtime"
"sort"
+ "sync"
"sync/atomic"
"testing"
. "time"
@@ -68,33 +69,94 @@ func TestAfterStress(t *testing.T) {
atomic.StoreUint32(&stop, 1)
}
+func benchmark(b *testing.B, bench func(n int)) {
+ garbage := make([]*Timer, 1<<17)
+ for i := 0; i < len(garbage); i++ {
+ garbage[i] = AfterFunc(Hour, nil)
+ }
+
+ const batch = 1000
+ P := runtime.GOMAXPROCS(-1)
+ N := int32(b.N / batch)
+
+ b.ResetTimer()
+
+ var wg sync.WaitGroup
+ wg.Add(P)
+
+ for p := 0; p < P; p++ {
+ go func() {
+ for atomic.AddInt32(&N, -1) >= 0 {
+ bench(batch)
+ }
+ wg.Done()
+ }()
+ }
+
+ wg.Wait()
+
+ b.StopTimer()
+ for i := 0; i < len(garbage); i++ {
+ garbage[i].Stop()
+ }
+}
+
func BenchmarkAfterFunc(b *testing.B) {
- i := b.N
- c := make(chan bool)
- var f func()
- f = func() {
- i--
- if i >= 0 {
- AfterFunc(0, f)
- } else {
- c <- true
+ benchmark(b, func(n int) {
+ c := make(chan bool)
+ var f func()
+ f = func() {
+ n--
+ if n >= 0 {
+ AfterFunc(0, f)
+ } else {
+ c <- true
+ }
}
- }
- AfterFunc(0, f)
- <-c
+ AfterFunc(0, f)
+ <-c
+ })
}
func BenchmarkAfter(b *testing.B) {
- for i := 0; i < b.N; i++ {
- <-After(1)
- }
+ benchmark(b, func(n int) {
+ for i := 0; i < n; i++ {
+ <-After(1)
+ }
+ })
}
func BenchmarkStop(b *testing.B) {
- for i := 0; i < b.N; i++ {
- NewTimer(1 * Second).Stop()
- }
+ benchmark(b, func(n int) {
+ for i := 0; i < n; i++ {
+ NewTimer(1 * Second).Stop()
+ }
+ })
+}
+
+func BenchmarkSimultaneousAfterFunc(b *testing.B) {
+ benchmark(b, func(n int) {
+ var wg sync.WaitGroup
+ wg.Add(n)
+ for i := 0; i < n; i++ {
+ AfterFunc(0, wg.Done)
+ }
+ wg.Wait()
+ })
+}
+
+func BenchmarkStartStop(b *testing.B) {
+ benchmark(b, func(n int) {
+ timers := make([]*Timer, n)
+ for i := 0; i < n; i++ {
+ timers[i] = AfterFunc(Hour, nil)
+ }
+
+ for i := 0; i < n; i++ {
+ timers[i].Stop()
+ }
+ })
}
func TestAfter(t *testing.T) {
@@ -315,3 +377,29 @@ func TestOverflowSleep(t *testing.T) {
t.Fatalf("negative timeout didn't fire")
}
}
+
+// Test that a panic while deleting a timer does not leave
+// the timers mutex held, deadlocking a ticker.Stop in a defer.
+func TestIssue5745(t *testing.T) {
+ ticker := NewTicker(Hour)
+ defer func() {
+ // would deadlock here before the fix due to
+ // lock taken before the segfault.
+ ticker.Stop()
+
+ if r := recover(); r == nil {
+ t.Error("Expected panic, but none happened.")
+ }
+ }()
+
+ // cause a panic due to a segfault
+ var timer *Timer
+ timer.Stop()
+ t.Error("Should be unreachable.")
+}
+
+func TestOverflowRuntimeTimer(t *testing.T) {
+ if err := CheckRuntimeTimerOverflow(); err != nil {
+ t.Fatalf(err.Error())
+ }
+}
diff --git a/libgo/go/time/sys_unix.go b/libgo/go/time/sys_unix.go
index 7f69b492c9f..60a3ce08f90 100644
--- a/libgo/go/time/sys_unix.go
+++ b/libgo/go/time/sys_unix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd linux netbsd openbsd
+// +build darwin dragonfly freebsd linux netbsd openbsd
package time
diff --git a/libgo/go/time/time.go b/libgo/go/time/time.go
index d291672af10..c504df74013 100644
--- a/libgo/go/time/time.go
+++ b/libgo/go/time/time.go
@@ -39,7 +39,14 @@ type Time struct {
// nsec specifies a non-negative nanosecond
// offset within the second named by Seconds.
// It must be in the range [0, 999999999].
- nsec int32
+ //
+ // It is declared as uintptr instead of int32 or uint32
+ // to avoid garbage collector aliasing in the case where
+ // on a 64-bit system the int32 or uint32 field is written
+ // over the low half of a pointer, creating another pointer.
+ // TODO(rsc): When the garbage collector is completely
+ // precise, change back to int32.
+ nsec uintptr
// loc specifies the Location that should be used to
// determine the minute, hour, month, day, and year
@@ -424,6 +431,11 @@ func (t Time) YearDay() int {
// largest representable duration to approximately 290 years.
type Duration int64
+const (
+ minDuration Duration = -1 << 63
+ maxDuration Duration = 1<<63 - 1
+)
+
// Common durations. There is no definition for units of Day or larger
// to avoid confusion across daylight savings time zone transitions.
//
@@ -600,21 +612,33 @@ func (d Duration) Hours() float64 {
// Add returns the time t+d.
func (t Time) Add(d Duration) Time {
t.sec += int64(d / 1e9)
- t.nsec += int32(d % 1e9)
- if t.nsec >= 1e9 {
+ nsec := int32(t.nsec) + int32(d%1e9)
+ if nsec >= 1e9 {
t.sec++
- t.nsec -= 1e9
- } else if t.nsec < 0 {
+ nsec -= 1e9
+ } else if nsec < 0 {
t.sec--
- t.nsec += 1e9
+ nsec += 1e9
}
+ t.nsec = uintptr(nsec)
return t
}
-// Sub returns the duration t-u.
+// Sub returns the duration t-u. If the result exceeds the maximum (or minimum)
+// value that can be stored in a Duration, the maximum (or minimum) duration
+// will be returned.
// To compute t-d for a duration d, use t.Add(-d).
func (t Time) Sub(u Time) Duration {
- return Duration(t.sec-u.sec)*Second + Duration(t.nsec-u.nsec)
+ d := Duration(t.sec-u.sec)*Second + Duration(int32(t.nsec)-int32(u.nsec))
+ // Check for overflow or underflow.
+ switch {
+ case u.Add(d).Equal(t):
+ return d // d is correct
+ case t.Before(u):
+ return minDuration // t - u is negative out of range
+ default:
+ return maxDuration // t - u is positive out of range
+ }
}
// Since returns the time elapsed since t.
@@ -645,7 +669,6 @@ const (
daysPer400Years = 365*400 + 97
daysPer100Years = 365*100 + 24
daysPer4Years = 365*4 + 1
- days1970To2001 = 31*365 + 8
)
// date computes the year, day of year, and when full=true,
@@ -760,7 +783,7 @@ func now() (sec int64, nsec int32)
// Now returns the current local time.
func Now() Time {
sec, nsec := now()
- return Time{sec + unixToInternal, nsec, Local}
+ return Time{sec + unixToInternal, uintptr(nsec), Local}
}
// UTC returns t with the location set to UTC.
@@ -816,10 +839,10 @@ func (t Time) UnixNano() int64 {
return (t.sec+internalToUnix)*1e9 + int64(t.nsec)
}
-const timeGobVersion byte = 1
+const timeBinaryVersion byte = 1
-// GobEncode implements the gob.GobEncoder interface.
-func (t Time) GobEncode() ([]byte, error) {
+// MarshalBinary implements the encoding.BinaryMarshaler interface.
+func (t Time) MarshalBinary() ([]byte, error) {
var offsetMin int16 // minutes east of UTC. -1 is UTC.
if t.Location() == &utcLoc {
@@ -827,17 +850,17 @@ func (t Time) GobEncode() ([]byte, error) {
} else {
_, offset := t.Zone()
if offset%60 != 0 {
- return nil, errors.New("Time.GobEncode: zone offset has fractional minute")
+ return nil, errors.New("Time.MarshalBinary: zone offset has fractional minute")
}
offset /= 60
if offset < -32768 || offset == -1 || offset > 32767 {
- return nil, errors.New("Time.GobEncode: unexpected zone offset")
+ return nil, errors.New("Time.MarshalBinary: unexpected zone offset")
}
offsetMin = int16(offset)
}
enc := []byte{
- timeGobVersion, // byte 0 : version
+ timeBinaryVersion, // byte 0 : version
byte(t.sec >> 56), // bytes 1-8: seconds
byte(t.sec >> 48),
byte(t.sec >> 40),
@@ -857,18 +880,19 @@ func (t Time) GobEncode() ([]byte, error) {
return enc, nil
}
-// GobDecode implements the gob.GobDecoder interface.
-func (t *Time) GobDecode(buf []byte) error {
+// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface.
+func (t *Time) UnmarshalBinary(data []byte) error {
+ buf := data
if len(buf) == 0 {
- return errors.New("Time.GobDecode: no data")
+ return errors.New("Time.UnmarshalBinary: no data")
}
- if buf[0] != timeGobVersion {
- return errors.New("Time.GobDecode: unsupported version")
+ if buf[0] != timeBinaryVersion {
+ return errors.New("Time.UnmarshalBinary: unsupported version")
}
if len(buf) != /*version*/ 1+ /*sec*/ 8+ /*nsec*/ 4+ /*zone offset*/ 2 {
- return errors.New("Time.GobDecode: invalid length")
+ return errors.New("Time.UnmarshalBinary: invalid length")
}
buf = buf[1:]
@@ -876,7 +900,7 @@ func (t *Time) GobDecode(buf []byte) error {
int64(buf[3])<<32 | int64(buf[2])<<40 | int64(buf[1])<<48 | int64(buf[0])<<56
buf = buf[8:]
- t.nsec = int32(buf[3]) | int32(buf[2])<<8 | int32(buf[1])<<16 | int32(buf[0])<<24
+ t.nsec = uintptr(int32(buf[3]) | int32(buf[2])<<8 | int32(buf[1])<<16 | int32(buf[0])<<24)
buf = buf[4:]
offset := int(int16(buf[1])|int16(buf[0])<<8) * 60
@@ -892,8 +916,22 @@ func (t *Time) GobDecode(buf []byte) error {
return nil
}
+// TODO(rsc): Remove GobEncoder, GobDecoder, MarshalJSON, UnmarshalJSON in Go 2.
+// The same semantics will be provided by the generic MarshalBinary, MarshalText,
+// UnmarshalBinary, UnmarshalText.
+
+// GobEncode implements the gob.GobEncoder interface.
+func (t Time) GobEncode() ([]byte, error) {
+ return t.MarshalBinary()
+}
+
+// GobDecode implements the gob.GobDecoder interface.
+func (t *Time) GobDecode(data []byte) error {
+ return t.UnmarshalBinary(data)
+}
+
// MarshalJSON implements the json.Marshaler interface.
-// Time is formatted as RFC3339.
+// The time is a quoted string in RFC 3339 format, with sub-second precision added if present.
func (t Time) MarshalJSON() ([]byte, error) {
if y := t.Year(); y < 0 || y >= 10000 {
return nil, errors.New("Time.MarshalJSON: year outside of range [0,9999]")
@@ -902,13 +940,30 @@ func (t Time) MarshalJSON() ([]byte, error) {
}
// UnmarshalJSON implements the json.Unmarshaler interface.
-// Time is expected in RFC3339 format.
+// The time is expected to be a quoted string in RFC 3339 format.
func (t *Time) UnmarshalJSON(data []byte) (err error) {
// Fractional seconds are handled implicitly by Parse.
*t, err = Parse(`"`+RFC3339+`"`, string(data))
return
}
+// MarshalText implements the encoding.TextMarshaler interface.
+// The time is formatted in RFC 3339 format, with sub-second precision added if present.
+func (t Time) MarshalText() ([]byte, error) {
+ if y := t.Year(); y < 0 || y >= 10000 {
+ return nil, errors.New("Time.MarshalText: year outside of range [0,9999]")
+ }
+ return []byte(t.Format(RFC3339Nano)), nil
+}
+
+// UnmarshalText implements the encoding.TextUnmarshaler interface.
+// The time is expected to be in RFC 3339 format.
+func (t *Time) UnmarshalText(data []byte) (err error) {
+ // Fractional seconds are handled implicitly by Parse.
+ *t, err = Parse(RFC3339, string(data))
+ return
+}
+
// Unix returns the local Time corresponding to the given Unix time,
// sec seconds and nsec nanoseconds since January 1, 1970 UTC.
// It is valid to pass nsec outside the range [0, 999999999].
@@ -922,7 +977,7 @@ func Unix(sec int64, nsec int64) Time {
sec--
}
}
- return Time{sec + unixToInternal, int32(nsec), Local}
+ return Time{sec + unixToInternal, uintptr(nsec), Local}
}
func isLeap(year int) bool {
@@ -1031,7 +1086,7 @@ func Date(year int, month Month, day, hour, min, sec, nsec int, loc *Location) T
unix -= int64(offset)
}
- return Time{unix + unixToInternal, int32(nsec), loc}
+ return Time{unix + unixToInternal, uintptr(nsec), loc}
}
// Truncate returns the result of rounding t down to a multiple of d (since the zero time).
@@ -1063,13 +1118,14 @@ func (t Time) Round(d Duration) Time {
// but it's still here in case we change our minds.
func div(t Time, d Duration) (qmod2 int, r Duration) {
neg := false
+ nsec := int32(t.nsec)
if t.sec < 0 {
// Operate on absolute value.
neg = true
t.sec = -t.sec
- t.nsec = -t.nsec
- if t.nsec < 0 {
- t.nsec += 1e9
+ nsec = -nsec
+ if nsec < 0 {
+ nsec += 1e9
t.sec-- // t.sec >= 1 before the -- so safe
}
}
@@ -1077,14 +1133,14 @@ func div(t Time, d Duration) (qmod2 int, r Duration) {
switch {
// Special case: 2d divides 1 second.
case d < Second && Second%(d+d) == 0:
- qmod2 = int(t.nsec/int32(d)) & 1
- r = Duration(t.nsec % int32(d))
+ qmod2 = int(nsec/int32(d)) & 1
+ r = Duration(nsec % int32(d))
// Special case: d is a multiple of 1 second.
case d%Second == 0:
d1 := int64(d / Second)
qmod2 = int(t.sec/d1) & 1
- r = Duration(t.sec%d1)*Second + Duration(t.nsec)
+ r = Duration(t.sec%d1)*Second + Duration(nsec)
// General case.
// This could be faster if more cleverness were applied,
@@ -1101,7 +1157,7 @@ func div(t Time, d Duration) (qmod2 int, r Duration) {
if u0 < u0x {
u1++
}
- u0x, u0 = u0, u0+uint64(t.nsec)
+ u0x, u0 = u0, u0+uint64(nsec)
if u0 < u0x {
u1++
}
diff --git a/libgo/go/time/time_test.go b/libgo/go/time/time_test.go
index a0ee37ae3b4..22b751c5255 100644
--- a/libgo/go/time/time_test.go
+++ b/libgo/go/time/time_test.go
@@ -413,6 +413,8 @@ var formatTests = []FormatTest{
{"am/pm", "3pm", "9pm"},
{"AM/PM", "3PM", "9PM"},
{"two-digit year", "06 01 02", "09 02 04"},
+ // Three-letter months and days must not be followed by lower-case letter.
+ {"Janet", "Hi Janet, the Month is January", "Hi Janet, the Month is February"},
// Time stamps, Fractional seconds.
{"Stamp", Stamp, "Feb 4 21:00:57"},
{"StampMilli", StampMilli, "Feb 4 21:00:57.012"},
@@ -505,6 +507,11 @@ var parseTests = []ParseTest{
// Leading zeros in other places should not be taken as fractional seconds.
{"zero1", "2006.01.02.15.04.05.0", "2010.02.04.21.00.57.0", false, false, 1, 1},
{"zero2", "2006.01.02.15.04.05.00", "2010.02.04.21.00.57.01", false, false, 1, 2},
+ // Month and day names only match when not followed by a lower-case letter.
+ {"Janet", "Hi Janet, the Month is January: Jan _2 15:04:05 2006", "Hi Janet, the Month is February: Feb 4 21:00:57 2010", false, true, 1, 0},
+
+ // GMT with offset.
+ {"GMT-8", UnixDate, "Fri Feb 5 05:00:57 GMT-8 2010", true, true, 1, 0},
// Accept any number of fractional second digits (including none) for .999...
// In Go 1, .999... was completely ignored in the format, meaning the first two
@@ -659,6 +666,38 @@ func TestFormatAndParse(t *testing.T) {
}
}
+type ParseTimeZoneTest struct {
+ value string
+ length int
+ ok bool
+}
+
+var parseTimeZoneTests = []ParseTimeZoneTest{
+ {"gmt hi there", 0, false},
+ {"GMT hi there", 3, true},
+ {"GMT+12 hi there", 6, true},
+ {"GMT+00 hi there", 3, true}, // 0 or 00 is not a legal offset.
+ {"GMT-5 hi there", 5, true},
+ {"GMT-51 hi there", 3, true},
+ {"ChST hi there", 4, true},
+ {"MSDx", 3, true},
+ {"MSDY", 0, false}, // four letters must end in T.
+ {"ESAST hi", 5, true},
+ {"ESASTT hi", 0, false}, // run of upper-case letters too long.
+ {"ESATY hi", 0, false}, // five letters must end in T.
+}
+
+func TestParseTimeZone(t *testing.T) {
+ for _, test := range parseTimeZoneTests {
+ length, ok := ParseTimeZone(test.value)
+ if ok != test.ok {
+ t.Errorf("expected %t for %q got %t", test.ok, test.value, ok)
+ } else if length != test.length {
+ t.Errorf("expected %d for %q got %d", test.length, test.value, length)
+ }
+ }
+}
+
type ParseErrorTest struct {
format string
value string
@@ -781,6 +820,44 @@ func TestMinutesInTimeZone(t *testing.T) {
}
}
+type SecondsTimeZoneOffsetTest struct {
+ format string
+ value string
+ expectedoffset int
+}
+
+var secondsTimeZoneOffsetTests = []SecondsTimeZoneOffsetTest{
+ {"2006-01-02T15:04:05-070000", "1871-01-01T05:33:02-003408", -(34*60 + 8)},
+ {"2006-01-02T15:04:05-07:00:00", "1871-01-01T05:33:02-00:34:08", -(34*60 + 8)},
+ {"2006-01-02T15:04:05-070000", "1871-01-01T05:33:02+003408", 34*60 + 8},
+ {"2006-01-02T15:04:05-07:00:00", "1871-01-01T05:33:02+00:34:08", 34*60 + 8},
+ {"2006-01-02T15:04:05Z070000", "1871-01-01T05:33:02-003408", -(34*60 + 8)},
+ {"2006-01-02T15:04:05Z07:00:00", "1871-01-01T05:33:02+00:34:08", 34*60 + 8},
+}
+
+func TestParseSecondsInTimeZone(t *testing.T) {
+ // should accept timezone offsets with seconds like: Zone America/New_York -4:56:02 - LMT 1883 Nov 18 12:03:58
+ for _, test := range secondsTimeZoneOffsetTests {
+ time, err := Parse(test.format, test.value)
+ if err != nil {
+ t.Fatal("error parsing date:", err)
+ }
+ _, offset := time.Zone()
+ if offset != test.expectedoffset {
+ t.Errorf("ZoneOffset = %d, want %d", offset, test.expectedoffset)
+ }
+ }
+}
+
+func TestFormatSecondsInTimeZone(t *testing.T) {
+ d := Date(1871, 9, 17, 20, 4, 26, 0, FixedZone("LMT", -(34*60+8)))
+ timestr := d.Format("2006-01-02T15:04:05Z070000")
+ expected := "1871-09-17T20:04:26-003408"
+ if timestr != expected {
+ t.Errorf("Got %s, want %s", timestr, expected)
+ }
+}
+
type ISOWeekTest struct {
year int // year
month, day int // month and day
@@ -1106,9 +1183,9 @@ var invalidEncodingTests = []struct {
bytes []byte
want string
}{
- {[]byte{}, "Time.GobDecode: no data"},
- {[]byte{0, 2, 3}, "Time.GobDecode: unsupported version"},
- {[]byte{1, 2, 3}, "Time.GobDecode: invalid length"},
+ {[]byte{}, "Time.UnmarshalBinary: no data"},
+ {[]byte{0, 2, 3}, "Time.UnmarshalBinary: unsupported version"},
+ {[]byte{1, 2, 3}, "Time.UnmarshalBinary: invalid length"},
}
func TestInvalidTimeGob(t *testing.T) {
@@ -1118,6 +1195,10 @@ func TestInvalidTimeGob(t *testing.T) {
if err == nil || err.Error() != tt.want {
t.Errorf("time.GobDecode(%#v) error = %v, want %v", tt.bytes, err, tt.want)
}
+ err = ignored.UnmarshalBinary(tt.bytes)
+ if err == nil || err.Error() != tt.want {
+ t.Errorf("time.UnmarshalBinary(%#v) error = %v, want %v", tt.bytes, err, tt.want)
+ }
}
}
@@ -1125,10 +1206,10 @@ var notEncodableTimes = []struct {
time Time
want string
}{
- {Date(0, 1, 2, 3, 4, 5, 6, FixedZone("", 1)), "Time.GobEncode: zone offset has fractional minute"},
- {Date(0, 1, 2, 3, 4, 5, 6, FixedZone("", -1*60)), "Time.GobEncode: unexpected zone offset"},
- {Date(0, 1, 2, 3, 4, 5, 6, FixedZone("", -32769*60)), "Time.GobEncode: unexpected zone offset"},
- {Date(0, 1, 2, 3, 4, 5, 6, FixedZone("", 32768*60)), "Time.GobEncode: unexpected zone offset"},
+ {Date(0, 1, 2, 3, 4, 5, 6, FixedZone("", 1)), "Time.MarshalBinary: zone offset has fractional minute"},
+ {Date(0, 1, 2, 3, 4, 5, 6, FixedZone("", -1*60)), "Time.MarshalBinary: unexpected zone offset"},
+ {Date(0, 1, 2, 3, 4, 5, 6, FixedZone("", -32769*60)), "Time.MarshalBinary: unexpected zone offset"},
+ {Date(0, 1, 2, 3, 4, 5, 6, FixedZone("", 32768*60)), "Time.MarshalBinary: unexpected zone offset"},
}
func TestNotGobEncodableTime(t *testing.T) {
@@ -1137,6 +1218,10 @@ func TestNotGobEncodableTime(t *testing.T) {
if err == nil || err.Error() != tt.want {
t.Errorf("%v GobEncode error = %v, want %v", tt.time, err, tt.want)
}
+ _, err = tt.time.MarshalBinary()
+ if err == nil || err.Error() != tt.want {
+ t.Errorf("%v MarshalBinary error = %v, want %v", tt.time, err, tt.want)
+ }
}
}
@@ -1233,6 +1318,8 @@ var parseDurationTests = []struct {
{"39h9m14.425s", true, 39*Hour + 9*Minute + 14*Second + 425*Millisecond},
// large value
{"52763797000ns", true, 52763797000 * Nanosecond},
+ // more than 9 digits after decimal point, see http://golang.org/issue/6617
+ {"0.3333333333333333333h", true, 20 * Minute},
// errors
{"", false, 0},
@@ -1300,6 +1387,9 @@ var mallocTest = []struct {
}
func TestCountMallocs(t *testing.T) {
+ if testing.Short() {
+ t.Skip("skipping malloc count in short mode")
+ }
if runtime.GOMAXPROCS(0) > 1 {
t.Skip("skipping; GOMAXPROCS>1")
}
@@ -1327,6 +1417,40 @@ func TestLoadFixed(t *testing.T) {
}
}
+const (
+ minDuration Duration = -1 << 63
+ maxDuration Duration = 1<<63 - 1
+)
+
+var subTests = []struct {
+ t Time
+ u Time
+ d Duration
+}{
+ {Time{}, Time{}, Duration(0)},
+ {Date(2009, 11, 23, 0, 0, 0, 1, UTC), Date(2009, 11, 23, 0, 0, 0, 0, UTC), Duration(1)},
+ {Date(2009, 11, 23, 0, 0, 0, 0, UTC), Date(2009, 11, 24, 0, 0, 0, 0, UTC), -24 * Hour},
+ {Date(2009, 11, 24, 0, 0, 0, 0, UTC), Date(2009, 11, 23, 0, 0, 0, 0, UTC), 24 * Hour},
+ {Date(-2009, 11, 24, 0, 0, 0, 0, UTC), Date(-2009, 11, 23, 0, 0, 0, 0, UTC), 24 * Hour},
+ {Time{}, Date(2109, 11, 23, 0, 0, 0, 0, UTC), Duration(minDuration)},
+ {Date(2109, 11, 23, 0, 0, 0, 0, UTC), Time{}, Duration(maxDuration)},
+ {Time{}, Date(-2109, 11, 23, 0, 0, 0, 0, UTC), Duration(maxDuration)},
+ {Date(-2109, 11, 23, 0, 0, 0, 0, UTC), Time{}, Duration(minDuration)},
+ {Date(2290, 1, 1, 0, 0, 0, 0, UTC), Date(2000, 1, 1, 0, 0, 0, 0, UTC), 290*365*24*Hour + 71*24*Hour},
+ {Date(2300, 1, 1, 0, 0, 0, 0, UTC), Date(2000, 1, 1, 0, 0, 0, 0, UTC), Duration(maxDuration)},
+ {Date(2000, 1, 1, 0, 0, 0, 0, UTC), Date(2290, 1, 1, 0, 0, 0, 0, UTC), -290*365*24*Hour - 71*24*Hour},
+ {Date(2000, 1, 1, 0, 0, 0, 0, UTC), Date(2300, 1, 1, 0, 0, 0, 0, UTC), Duration(minDuration)},
+}
+
+func TestSub(t *testing.T) {
+ for i, st := range subTests {
+ got := st.t.Sub(st.u)
+ if got != st.d {
+ t.Errorf("#%d: Sub(%v, %v): got %v; want %v", i, st.t, st.u, got, st.d)
+ }
+ }
+}
+
func BenchmarkNow(b *testing.B) {
for i := 0; i < b.N; i++ {
t = Now()
diff --git a/libgo/go/time/zoneinfo.go b/libgo/go/time/zoneinfo.go
index c44477f4743..1c6186258f9 100644
--- a/libgo/go/time/zoneinfo.go
+++ b/libgo/go/time/zoneinfo.go
@@ -178,19 +178,6 @@ func (l *Location) lookupName(name string, unix int64) (offset int, isDST bool,
return
}
-// lookupOffset returns information about the time zone with
-// the given offset (such as -5*60*60).
-func (l *Location) lookupOffset(offset int) (name string, isDST bool, ok bool) {
- l = l.get()
- for i := range l.zone {
- zone := &l.zone[i]
- if zone.offset == offset {
- return zone.name, zone.isDST, true
- }
- }
- return
-}
-
// NOTE(rsc): Eventually we will need to accept the POSIX TZ environment
// syntax too, but I don't feel like implementing it today.
diff --git a/libgo/go/time/zoneinfo_abbrs_windows.go b/libgo/go/time/zoneinfo_abbrs_windows.go
new file mode 100644
index 00000000000..80334371fe0
--- /dev/null
+++ b/libgo/go/time/zoneinfo_abbrs_windows.go
@@ -0,0 +1,115 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// generated by genzabbrs.go from
+// http://unicode.org/cldr/data/common/supplemental/windowsZones.xml
+
+package time
+
+type abbr struct {
+ std string
+ dst string
+}
+
+var abbrs = map[string]abbr{
+ "Egypt Standard Time": {"EET", "EET"}, // Africa/Cairo
+ "Morocco Standard Time": {"WET", "WEST"}, // Africa/Casablanca
+ "South Africa Standard Time": {"SAST", "SAST"}, // Africa/Johannesburg
+ "W. Central Africa Standard Time": {"WAT", "WAT"}, // Africa/Lagos
+ "E. Africa Standard Time": {"EAT", "EAT"}, // Africa/Nairobi
+ "Namibia Standard Time": {"WAT", "WAST"}, // Africa/Windhoek
+ "Alaskan Standard Time": {"AKST", "AKDT"}, // America/Anchorage
+ "Paraguay Standard Time": {"PYT", "PYST"}, // America/Asuncion
+ "Bahia Standard Time": {"BRT", "BRST"}, // America/Bahia
+ "SA Pacific Standard Time": {"COT", "COT"}, // America/Bogota
+ "Argentina Standard Time": {"ART", "ART"}, // America/Buenos_Aires
+ "Venezuela Standard Time": {"VET", "VET"}, // America/Caracas
+ "SA Eastern Standard Time": {"GFT", "GFT"}, // America/Cayenne
+ "Central Standard Time": {"CST", "CDT"}, // America/Chicago
+ "Mountain Standard Time (Mexico)": {"MST", "MDT"}, // America/Chihuahua
+ "Central Brazilian Standard Time": {"AMT", "AMST"}, // America/Cuiaba
+ "Mountain Standard Time": {"MST", "MDT"}, // America/Denver
+ "Greenland Standard Time": {"WGT", "WGST"}, // America/Godthab
+ "Central America Standard Time": {"CST", "CST"}, // America/Guatemala
+ "Atlantic Standard Time": {"AST", "ADT"}, // America/Halifax
+ "US Eastern Standard Time": {"EST", "EDT"}, // America/Indianapolis
+ "SA Western Standard Time": {"BOT", "BOT"}, // America/La_Paz
+ "Pacific Standard Time": {"PST", "PDT"}, // America/Los_Angeles
+ "Central Standard Time (Mexico)": {"CST", "CDT"}, // America/Mexico_City
+ "Montevideo Standard Time": {"UYT", "UYST"}, // America/Montevideo
+ "Eastern Standard Time": {"EST", "EDT"}, // America/New_York
+ "US Mountain Standard Time": {"MST", "MST"}, // America/Phoenix
+ "Canada Central Standard Time": {"CST", "CST"}, // America/Regina
+ "Pacific Standard Time (Mexico)": {"PST", "PDT"}, // America/Santa_Isabel
+ "Pacific SA Standard Time": {"CLT", "CLST"}, // America/Santiago
+ "E. South America Standard Time": {"BRT", "BRST"}, // America/Sao_Paulo
+ "Newfoundland Standard Time": {"NST", "NDT"}, // America/St_Johns
+ "Central Asia Standard Time": {"ALMT", "ALMT"}, // Asia/Almaty
+ "Jordan Standard Time": {"EET", "EEST"}, // Asia/Amman
+ "Arabic Standard Time": {"AST", "AST"}, // Asia/Baghdad
+ "Azerbaijan Standard Time": {"AZT", "AZST"}, // Asia/Baku
+ "SE Asia Standard Time": {"ICT", "ICT"}, // Asia/Bangkok
+ "Middle East Standard Time": {"EET", "EEST"}, // Asia/Beirut
+ "India Standard Time": {"IST", "IST"}, // Asia/Calcutta
+ "Sri Lanka Standard Time": {"IST", "IST"}, // Asia/Colombo
+ "Syria Standard Time": {"EET", "EEST"}, // Asia/Damascus
+ "Bangladesh Standard Time": {"BDT", "BDT"}, // Asia/Dhaka
+ "Arabian Standard Time": {"GST", "GST"}, // Asia/Dubai
+ "North Asia East Standard Time": {"IRKT", "IRKT"}, // Asia/Irkutsk
+ "Israel Standard Time": {"IST", "IDT"}, // Asia/Jerusalem
+ "Afghanistan Standard Time": {"AFT", "AFT"}, // Asia/Kabul
+ "Pakistan Standard Time": {"PKT", "PKT"}, // Asia/Karachi
+ "Nepal Standard Time": {"NPT", "NPT"}, // Asia/Katmandu
+ "North Asia Standard Time": {"KRAT", "KRAT"}, // Asia/Krasnoyarsk
+ "Magadan Standard Time": {"MAGT", "MAGT"}, // Asia/Magadan
+ "E. Europe Standard Time": {"EET", "EEST"}, // Asia/Nicosia
+ "N. Central Asia Standard Time": {"NOVT", "NOVT"}, // Asia/Novosibirsk
+ "Myanmar Standard Time": {"MMT", "MMT"}, // Asia/Rangoon
+ "Arab Standard Time": {"AST", "AST"}, // Asia/Riyadh
+ "Korea Standard Time": {"KST", "KST"}, // Asia/Seoul
+ "China Standard Time": {"CST", "CST"}, // Asia/Shanghai
+ "Singapore Standard Time": {"SGT", "SGT"}, // Asia/Singapore
+ "Taipei Standard Time": {"CST", "CST"}, // Asia/Taipei
+ "West Asia Standard Time": {"UZT", "UZT"}, // Asia/Tashkent
+ "Georgian Standard Time": {"GET", "GET"}, // Asia/Tbilisi
+ "Iran Standard Time": {"IRST", "IRDT"}, // Asia/Tehran
+ "Tokyo Standard Time": {"JST", "JST"}, // Asia/Tokyo
+ "Ulaanbaatar Standard Time": {"ULAT", "ULAT"}, // Asia/Ulaanbaatar
+ "Vladivostok Standard Time": {"VLAT", "VLAT"}, // Asia/Vladivostok
+ "Yakutsk Standard Time": {"YAKT", "YAKT"}, // Asia/Yakutsk
+ "Ekaterinburg Standard Time": {"YEKT", "YEKT"}, // Asia/Yekaterinburg
+ "Caucasus Standard Time": {"AMT", "AMT"}, // Asia/Yerevan
+ "Azores Standard Time": {"AZOT", "AZOST"}, // Atlantic/Azores
+ "Cape Verde Standard Time": {"CVT", "CVT"}, // Atlantic/Cape_Verde
+ "Greenwich Standard Time": {"GMT", "GMT"}, // Atlantic/Reykjavik
+ "Cen. Australia Standard Time": {"CST", "CST"}, // Australia/Adelaide
+ "E. Australia Standard Time": {"EST", "EST"}, // Australia/Brisbane
+ "AUS Central Standard Time": {"CST", "CST"}, // Australia/Darwin
+ "Tasmania Standard Time": {"EST", "EST"}, // Australia/Hobart
+ "W. Australia Standard Time": {"WST", "WST"}, // Australia/Perth
+ "AUS Eastern Standard Time": {"EST", "EST"}, // Australia/Sydney
+ "UTC": {"GMT", "GMT"}, // Etc/GMT
+ "UTC-11": {"GMT+11", "GMT+11"}, // Etc/GMT+11
+ "Dateline Standard Time": {"GMT+12", "GMT+12"}, // Etc/GMT+12
+ "UTC-02": {"GMT+2", "GMT+2"}, // Etc/GMT+2
+ "UTC+12": {"GMT-12", "GMT-12"}, // Etc/GMT-12
+ "W. Europe Standard Time": {"CET", "CEST"}, // Europe/Berlin
+ "GTB Standard Time": {"EET", "EEST"}, // Europe/Bucharest
+ "Central Europe Standard Time": {"CET", "CEST"}, // Europe/Budapest
+ "Turkey Standard Time": {"EET", "EEST"}, // Europe/Istanbul
+ "Kaliningrad Standard Time": {"FET", "FET"}, // Europe/Kaliningrad
+ "FLE Standard Time": {"EET", "EEST"}, // Europe/Kiev
+ "GMT Standard Time": {"GMT", "BST"}, // Europe/London
+ "Russian Standard Time": {"MSK", "MSK"}, // Europe/Moscow
+ "Romance Standard Time": {"CET", "CEST"}, // Europe/Paris
+ "Central European Standard Time": {"CET", "CEST"}, // Europe/Warsaw
+ "Mauritius Standard Time": {"MUT", "MUT"}, // Indian/Mauritius
+ "Samoa Standard Time": {"WST", "WST"}, // Pacific/Apia
+ "New Zealand Standard Time": {"NZST", "NZDT"}, // Pacific/Auckland
+ "Fiji Standard Time": {"FJT", "FJT"}, // Pacific/Fiji
+ "Central Pacific Standard Time": {"SBT", "SBT"}, // Pacific/Guadalcanal
+ "Hawaiian Standard Time": {"HST", "HST"}, // Pacific/Honolulu
+ "West Pacific Standard Time": {"PGT", "PGT"}, // Pacific/Port_Moresby
+ "Tonga Standard Time": {"TOT", "TOT"}, // Pacific/Tongatapu
+}
diff --git a/libgo/go/time/zoneinfo_read.go b/libgo/go/time/zoneinfo_read.go
index 4519c996234..7714aa9f583 100644
--- a/libgo/go/time/zoneinfo_read.go
+++ b/libgo/go/time/zoneinfo_read.go
@@ -11,10 +11,6 @@ package time
import "errors"
-const (
- headerSize = 4 + 16 + 4*7
-)
-
// Simple I/O interface to binary blob of data.
type data struct {
p []byte
diff --git a/libgo/go/time/zoneinfo_unix.go b/libgo/go/time/zoneinfo_unix.go
index 1bf1f11e24f..72070253a78 100644
--- a/libgo/go/time/zoneinfo_unix.go
+++ b/libgo/go/time/zoneinfo_unix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd linux netbsd openbsd
+// +build darwin dragonfly freebsd linux netbsd openbsd
// Parse "zoneinfo" time zone file.
// This is a fairly standard file format used on OS X, Linux, BSD, Sun, and others.
diff --git a/libgo/go/time/zoneinfo_windows.go b/libgo/go/time/zoneinfo_windows.go
index a8d3dcbfeb1..1e18ad295df 100644
--- a/libgo/go/time/zoneinfo_windows.go
+++ b/libgo/go/time/zoneinfo_windows.go
@@ -8,6 +8,7 @@ import (
"errors"
"runtime"
"syscall"
+ "unsafe"
)
// TODO(rsc): Fall back to copy of zoneinfo files.
@@ -16,21 +17,83 @@ import (
// time zone information.
// The implementation assumes that this year's rules for daylight savings
// time apply to all previous and future years as well.
-// Also, time zone abbreviations are unavailable. The implementation constructs
-// them using the capital letters from a longer time zone description.
-
-// abbrev returns the abbreviation to use for the given zone name.
-func abbrev(name []uint16) string {
- // name is 'Pacific Standard Time' but we want 'PST'.
- // Extract just capital letters. It's not perfect but the
- // information we need is not available from the kernel.
- // Because time zone abbreviations are not unique,
- // Windows refuses to expose them.
- //
- // http://social.msdn.microsoft.com/Forums/eu/vclanguage/thread/a87e1d25-fb71-4fe0-ae9c-a9578c9753eb
- // http://stackoverflow.com/questions/4195948/windows-time-zone-abbreviations-in-asp-net
+
+// getKeyValue retrieves the string value kname associated with the open registry key kh.
+func getKeyValue(kh syscall.Handle, kname string) (string, error) {
+ var buf [50]uint16 // buf needs to be large enough to fit zone descriptions
+ var typ uint32
+ n := uint32(len(buf) * 2) // RegQueryValueEx's signature expects array of bytes, not uint16
+ p, _ := syscall.UTF16PtrFromString(kname)
+ if err := syscall.RegQueryValueEx(kh, p, nil, &typ, (*byte)(unsafe.Pointer(&buf[0])), &n); err != nil {
+ return "", err
+ }
+ if typ != syscall.REG_SZ { // null terminated strings only
+ return "", errors.New("Key is not string")
+ }
+ return syscall.UTF16ToString(buf[:]), nil
+}
+
+// matchZoneKey checks if stdname and dstname match the corresponding "Std"
+// and "Dlt" key values in the kname key stored under the open registry key zones.
+func matchZoneKey(zones syscall.Handle, kname string, stdname, dstname string) (matched bool, err2 error) {
+ var h syscall.Handle
+ p, _ := syscall.UTF16PtrFromString(kname)
+ if err := syscall.RegOpenKeyEx(zones, p, 0, syscall.KEY_READ, &h); err != nil {
+ return false, err
+ }
+ defer syscall.RegCloseKey(h)
+
+ s, err := getKeyValue(h, "Std")
+ if err != nil {
+ return false, err
+ }
+ if s != stdname {
+ return false, nil
+ }
+ s, err = getKeyValue(h, "Dlt")
+ if err != nil {
+ return false, err
+ }
+ if s != dstname {
+ return false, nil
+ }
+ return true, nil
+}
+
+// toEnglishName searches the registry for an English name of a time zone
+// whose zone names are stdname and dstname and returns the English name.
+func toEnglishName(stdname, dstname string) (string, error) {
+ var zones syscall.Handle
+ p, _ := syscall.UTF16PtrFromString(`SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones`)
+ if err := syscall.RegOpenKeyEx(syscall.HKEY_LOCAL_MACHINE, p, 0, syscall.KEY_READ, &zones); err != nil {
+ return "", err
+ }
+ defer syscall.RegCloseKey(zones)
+
+ var count uint32
+ if err := syscall.RegQueryInfoKey(zones, nil, nil, nil, &count, nil, nil, nil, nil, nil, nil, nil); err != nil {
+ return "", err
+ }
+
+ var buf [50]uint16 // buf needs to be large enough to fit zone descriptions
+ for i := uint32(0); i < count; i++ {
+ n := uint32(len(buf))
+ if syscall.RegEnumKeyEx(zones, i, &buf[0], &n, nil, nil, nil, nil) != nil {
+ continue
+ }
+ kname := syscall.UTF16ToString(buf[:])
+ matched, err := matchZoneKey(zones, kname, stdname, dstname)
+ if err == nil && matched {
+ return kname, nil
+ }
+ }
+ return "", errors.New(`English name for time zone "` + stdname + `" not found in registry`)
+}
+
+// extractCAPS exracts capital letters from description desc.
+func extractCAPS(desc string) string {
var short []rune
- for _, c := range name {
+ for _, c := range desc {
if 'A' <= c && c <= 'Z' {
short = append(short, rune(c))
}
@@ -38,6 +101,26 @@ func abbrev(name []uint16) string {
return string(short)
}
+// abbrev returns the abbreviations to use for the given zone z.
+func abbrev(z *syscall.Timezoneinformation) (std, dst string) {
+ stdName := syscall.UTF16ToString(z.StandardName[:])
+ a, ok := abbrs[stdName]
+ if !ok {
+ dstName := syscall.UTF16ToString(z.DaylightName[:])
+ // Perhaps stdName is not English. Try to convert it.
+ englishName, err := toEnglishName(stdName, dstName)
+ if err == nil {
+ a, ok = abbrs[englishName]
+ if ok {
+ return a.std, a.dst
+ }
+ }
+ // fallback to using capital letters
+ return extractCAPS(stdName), extractCAPS(dstName)
+ }
+ return a.std, a.dst
+}
+
// pseudoUnix returns the pseudo-Unix time (seconds since Jan 1 1970 *LOCAL TIME*)
// denoted by the system date+time d in the given year.
// It is up to the caller to convert this local time into a UTC-based time.
@@ -75,8 +158,10 @@ func initLocalFromTZI(i *syscall.Timezoneinformation) {
}
l.zone = make([]zone, nzone)
+ stdname, dstname := abbrev(i)
+
std := &l.zone[0]
- std.name = abbrev(i.StandardName[0:])
+ std.name = stdname
if nzone == 1 {
// No daylight savings.
std.offset = -int(i.Bias) * 60
@@ -95,7 +180,7 @@ func initLocalFromTZI(i *syscall.Timezoneinformation) {
std.offset = -int(i.Bias+i.StandardBias) * 60
dst := &l.zone[1]
- dst.name = abbrev(i.DaylightName[0:])
+ dst.name = dstname
dst.offset = -int(i.Bias+i.DaylightBias) * 60
dst.isDST = true
@@ -142,10 +227,27 @@ var usPacific = syscall.Timezoneinformation{
DaylightBias: -60,
}
+var aus = syscall.Timezoneinformation{
+ Bias: -10 * 60,
+ StandardName: [32]uint16{
+ 'A', 'U', 'S', ' ', 'E', 'a', 's', 't', 'e', 'r', 'n', ' ', 'S', 't', 'a', 'n', 'd', 'a', 'r', 'd', ' ', 'T', 'i', 'm', 'e',
+ },
+ StandardDate: syscall.Systemtime{Month: 4, Day: 1, Hour: 3},
+ DaylightName: [32]uint16{
+ 'A', 'U', 'S', ' ', 'E', 'a', 's', 't', 'e', 'r', 'n', ' ', 'D', 'a', 'y', 'l', 'i', 'g', 'h', 't', ' ', 'T', 'i', 'm', 'e',
+ },
+ DaylightDate: syscall.Systemtime{Month: 10, Day: 1, Hour: 2},
+ DaylightBias: -60,
+}
+
func initTestingZone() {
initLocalFromTZI(&usPacific)
}
+func initAusTestingZone() {
+ initLocalFromTZI(&aus)
+}
+
func initLocal() {
var i syscall.Timezoneinformation
if _, err := syscall.GetTimeZoneInformation(&i); err != nil {
diff --git a/libgo/go/unicode/graphic.go b/libgo/go/unicode/graphic.go
index 5b995fcd0df..ba90b4e5189 100644
--- a/libgo/go/unicode/graphic.go
+++ b/libgo/go/unicode/graphic.go
@@ -39,7 +39,7 @@ func IsGraphic(r rune) bool {
if uint32(r) <= MaxLatin1 {
return properties[uint8(r)]&pg != 0
}
- return IsOneOf(GraphicRanges, r)
+ return In(r, GraphicRanges...)
}
// IsPrint reports whether the rune is defined as printable by Go. Such
@@ -51,12 +51,23 @@ func IsPrint(r rune) bool {
if uint32(r) <= MaxLatin1 {
return properties[uint8(r)]&pp != 0
}
- return IsOneOf(PrintRanges, r)
+ return In(r, PrintRanges...)
}
// IsOneOf reports whether the rune is a member of one of the ranges.
-func IsOneOf(set []*RangeTable, r rune) bool {
- for _, inside := range set {
+// The function "In" provides a nicer signature and should be used in preference to IsOneOf.
+func IsOneOf(ranges []*RangeTable, r rune) bool {
+ for _, inside := range ranges {
+ if Is(inside, r) {
+ return true
+ }
+ }
+ return false
+}
+
+// In reports whether the rune is a member of one of the ranges.
+func In(r rune, ranges ...*RangeTable) bool {
+ for _, inside := range ranges {
if Is(inside, r) {
return true
}
diff --git a/libgo/go/unicode/graphic_test.go b/libgo/go/unicode/graphic_test.go
index 7b1f6209e80..c9f289c7f55 100644
--- a/libgo/go/unicode/graphic_test.go
+++ b/libgo/go/unicode/graphic_test.go
@@ -71,7 +71,7 @@ func TestNumberLatin1(t *testing.T) {
func TestIsPrintLatin1(t *testing.T) {
for i := rune(0); i <= MaxLatin1; i++ {
got := IsPrint(i)
- want := IsOneOf(PrintRanges, i)
+ want := In(i, PrintRanges...)
if i == ' ' {
want = true
}
@@ -84,7 +84,7 @@ func TestIsPrintLatin1(t *testing.T) {
func TestIsGraphicLatin1(t *testing.T) {
for i := rune(0); i <= MaxLatin1; i++ {
got := IsGraphic(i)
- want := IsOneOf(GraphicRanges, i)
+ want := In(i, GraphicRanges...)
if got != want {
t.Errorf("%U incorrect: got %t; want %t", i, got, want)
}
diff --git a/libgo/mksysinfo.sh b/libgo/mksysinfo.sh
index 11bcb257a94..025729ccad1 100755
--- a/libgo/mksysinfo.sh
+++ b/libgo/mksysinfo.sh
@@ -160,6 +160,9 @@ cat > sysinfo.c <<EOF
#if defined(HAVE_SYS_INOTIFY_H)
#include <sys/inotify.h>
#endif
+#if defined(HAVE_NETINET_ICMP6_H)
+#include <netinet/icmp6.h>
+#endif
/* Constants that may only be defined as expressions on some systems,
expressions too complex for -fdump-go-spec to handle. These are
@@ -217,6 +220,11 @@ if ! grep '^const O_CLOEXEC' ${OUT} >/dev/null 2>&1; then
echo "const O_CLOEXEC = 0" >> ${OUT}
fi
+# The os package requires F_DUPFD_CLOEXEC to be defined.
+if ! grep '^const F_DUPFD_CLOEXEC' ${OUT} >/dev/null 2>&1; then
+ echo "const F_DUPFD_CLOEXEC = 0" >> ${OUT}
+fi
+
# These flags can be lost on i386 GNU/Linux when using
# -D_FILE_OFFSET_BITS=64, because we see "#define F_SETLK F_SETLK64"
# before we see the definition of F_SETLK64.
@@ -709,6 +717,18 @@ if ! grep 'type IPMreqn ' ${OUT} >/dev/null 2>&1; then
echo 'type IPMreqn struct { Multiaddr [4]byte; Interface [4]byte; Ifindex int32 }' >> ${OUT}
fi
+# The icmp6_filter struct.
+grep '^type _icmp6_filter ' gen-sysinfo.go | \
+ sed -e 's/_icmp6_filter/ICMPv6Filter/' \
+ -e 's/data/Data/' \
+ -e 's/filt/Filt/' \
+ >> ${OUT}
+
+# We need ICMPv6Filter to compile the syscall package.
+if ! grep 'type ICMPv6Filter ' ${OUT} > /dev/null 2>&1; then
+ echo 'type ICMPv6Filter struct { Data [8]uint32 }' >> ${OUT}
+fi
+
# Try to guess the type to use for fd_set.
fd_set=`grep '^type _fd_set ' gen-sysinfo.go || true`
fds_bits_type="_C_long"
@@ -1035,6 +1055,10 @@ grep '^type _utimbuf ' gen-sysinfo.go | \
grep '^const _LOCK_' gen-sysinfo.go |
sed -e 's/^\(const \)_\(LOCK_[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+# The PRIO constants.
+grep '^const _PRIO_' gen-sysinfo.go | \
+ sed -e 's/^\(const \)_\(PRIO_[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+
# The GNU/Linux LINUX_REBOOT flags.
grep '^const _LINUX_REBOOT_' gen-sysinfo.go |
sed -e 's/^\(const \)_\(LINUX_REBOOT_[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
@@ -1117,7 +1141,8 @@ set cmsghdr Cmsghdr ip_mreq IPMreq ip_mreqn IPMreqn ipv6_mreq IPv6Mreq \
in6_pktinfo Inet6Pktinfo inotify_event InotifyEvent linger Linger \
msghdr Msghdr nlattr NlAttr nlmsgerr NlMsgerr nlmsghdr NlMsghdr \
rtattr RtAttr rtgenmsg RtGenmsg rtmsg RtMsg rtnexthop RtNexthop \
- sock_filter SockFilter sock_fprog SockFprog ucred Ucred
+ sock_filter SockFilter sock_fprog SockFprog ucred Ucred \
+ icmp6_filter ICMPv6Filter
while test $# != 0; do
nc=$1
ngo=$2
@@ -1139,5 +1164,8 @@ fi
if ! grep 'const SizeofIPMreqn ' ${OUT} >/dev/null 2>&1; then
echo 'const SizeofIPMreqn = 12' >> ${OUT}
fi
+if ! grep 'const SizeofICMPv6Filter ' ${OUT} >/dev/null 2>&1; then
+ echo 'const SizeofICMPv6Filter = 32' >> ${OUT}
+fi
exit $?
diff --git a/libgo/runtime/chan.c b/libgo/runtime/chan.c
index 6f52a1d5e31..1d9e6681d35 100644
--- a/libgo/runtime/chan.c
+++ b/libgo/runtime/chan.c
@@ -10,8 +10,6 @@
#define NOSELGEN 1
-static int32 debug = 0;
-
typedef struct WaitQ WaitQ;
typedef struct SudoG SudoG;
typedef struct Select Select;
@@ -42,8 +40,9 @@ struct Hchan
uintgo qcount; // total data in the q
uintgo dataqsiz; // size of the circular q
uint16 elemsize;
- bool closed;
uint8 elemalign;
+ uint8 pad; // ensures proper alignment of the buffer that follows Hchan in memory
+ bool closed;
uintgo sendx; // send index
uintgo recvx; // receive index
WaitQ recvq; // list of recv waiters
@@ -59,6 +58,8 @@ uint32 runtime_Hchansize = sizeof(Hchan);
enum
{
+ debug = 0,
+
// Scase.kind
CaseRecv,
CaseSend,
@@ -105,17 +106,17 @@ runtime_makechan_c(ChanType *t, int64 hint)
runtime_panicstring("makechan: size out of range");
n = sizeof(*c);
+ n = ROUND(n, elem->__align);
// allocate memory in one call
- c = (Hchan*)runtime_mal(n + hint*elem->__size);
+ c = (Hchan*)runtime_mallocgc(n + hint*elem->__size, (uintptr)t | TypeInfo_Chan, 0);
c->elemsize = elem->__size;
c->elemalign = elem->__align;
c->dataqsiz = hint;
- runtime_settype(c, (uintptr)t | TypeInfo_Chan);
if(debug)
- runtime_printf("makechan: chan=%p; elemsize=%D; elemalign=%d; dataqsiz=%D\n",
- c, (int64)elem->__size, elem->__align, (int64)c->dataqsiz);
+ runtime_printf("makechan: chan=%p; elemsize=%D; dataqsiz=%D\n",
+ c, (int64)elem->__size, (int64)c->dataqsiz);
return c;
}
@@ -185,7 +186,7 @@ runtime_chansend(ChanType *t, Hchan *c, byte *ep, bool *pres, void *pc)
return; // not reached
}
- if(runtime_gcwaiting)
+ if(runtime_gcwaiting())
runtime_gosched();
if(debug) {
@@ -200,7 +201,6 @@ runtime_chansend(ChanType *t, Hchan *c, byte *ep, bool *pres, void *pc)
}
runtime_lock(c);
- // TODO(dvyukov): add similar instrumentation to select.
if(raceenabled)
runtime_racereadpc(c, pc, runtime_chansend);
if(c->closed)
@@ -311,7 +311,7 @@ runtime_chanrecv(ChanType *t, Hchan* c, byte *ep, bool *selected, bool *received
int64 t0;
G *g;
- if(runtime_gcwaiting)
+ if(runtime_gcwaiting())
runtime_gosched();
if(debug)
@@ -927,6 +927,7 @@ selectgo(Select **selp)
{
Select *sel;
uint32 o, i, j, k;
+ int64 t0;
Scase *cas, *dfl;
Hchan *c;
SudoG *sg;
@@ -935,7 +936,7 @@ selectgo(Select **selp)
G *g;
sel = *selp;
- if(runtime_gcwaiting)
+ if(runtime_gcwaiting())
runtime_gosched();
if(debug)
@@ -943,6 +944,13 @@ selectgo(Select **selp)
g = runtime_g();
+ t0 = 0;
+ if(runtime_blockprofilerate > 0) {
+ t0 = runtime_cputicks();
+ for(i=0; i<sel->ncase; i++)
+ sel->scase[i].sg.releasetime = -1;
+ }
+
// The compiler rewrites selects that statically have
// only 0 or 1 cases plus default into simpler constructs.
// The only way we can end up with such small sel->ncase
@@ -1023,6 +1031,8 @@ loop:
break;
case CaseSend:
+ if(raceenabled)
+ runtime_racereadpc(c, runtime_selectgo, runtime_chansend);
if(c->closed)
goto sclose;
if(c->dataqsiz > 0) {
@@ -1124,6 +1134,8 @@ asyncrecv:
if(sg != nil) {
gp = sg->g;
selunlock(sel);
+ if(sg->releasetime)
+ sg->releasetime = runtime_cputicks();
runtime_ready(gp);
} else {
selunlock(sel);
@@ -1142,6 +1154,8 @@ asyncsend:
if(sg != nil) {
gp = sg->g;
selunlock(sel);
+ if(sg->releasetime)
+ sg->releasetime = runtime_cputicks();
runtime_ready(gp);
} else {
selunlock(sel);
@@ -1161,6 +1175,8 @@ syncrecv:
runtime_memmove(cas->sg.elem, sg->elem, c->elemsize);
gp = sg->g;
gp->param = sg;
+ if(sg->releasetime)
+ sg->releasetime = runtime_cputicks();
runtime_ready(gp);
goto retc;
@@ -1186,11 +1202,15 @@ syncsend:
runtime_memmove(sg->elem, cas->sg.elem, c->elemsize);
gp = sg->g;
gp->param = sg;
+ if(sg->releasetime)
+ sg->releasetime = runtime_cputicks();
runtime_ready(gp);
retc:
// return index corresponding to chosen case
index = cas->index;
+ if(cas->sg.releasetime > 0)
+ runtime_blockevent(cas->sg.releasetime - t0, 2);
runtime_free(sel);
return index;
@@ -1297,17 +1317,36 @@ reflect_rselect(Slice cases)
return ret;
}
+static void closechan(Hchan *c, void *pc);
+
// closechan(sel *byte);
void
runtime_closechan(Hchan *c)
{
+ closechan(c, runtime_getcallerpc(&c));
+}
+
+// For reflect
+// func chanclose(c chan)
+
+void reflect_chanclose(uintptr) __asm__ (GOSYM_PREFIX "reflect.chanclose");
+
+void
+reflect_chanclose(uintptr c)
+{
+ closechan((Hchan*)c, runtime_getcallerpc(&c));
+}
+
+static void
+closechan(Hchan *c, void *pc)
+{
SudoG *sg;
G* gp;
if(c == nil)
runtime_panicstring("close of nil channel");
- if(runtime_gcwaiting)
+ if(runtime_gcwaiting())
runtime_gosched();
runtime_lock(c);
@@ -1317,7 +1356,7 @@ runtime_closechan(Hchan *c)
}
if(raceenabled) {
- runtime_racewritepc(c, runtime_getcallerpc(&c), runtime_closechan);
+ runtime_racewritepc(c, pc, runtime_closechan);
runtime_racerelease(c);
}
@@ -1330,6 +1369,8 @@ runtime_closechan(Hchan *c)
break;
gp = sg->g;
gp->param = nil;
+ if(sg->releasetime)
+ sg->releasetime = runtime_cputicks();
runtime_ready(gp);
}
@@ -1340,6 +1381,8 @@ runtime_closechan(Hchan *c)
break;
gp = sg->g;
gp->param = nil;
+ if(sg->releasetime)
+ sg->releasetime = runtime_cputicks();
runtime_ready(gp);
}
@@ -1353,17 +1396,6 @@ __go_builtin_close(Hchan *c)
}
// For reflect
-// func chanclose(c chan)
-
-void reflect_chanclose(uintptr) __asm__ (GOSYM_PREFIX "reflect.chanclose");
-
-void
-reflect_chanclose(uintptr c)
-{
- runtime_closechan((Hchan*)c);
-}
-
-// For reflect
// func chanlen(c chan) (len int)
intgo reflect_chanlen(uintptr) __asm__ (GOSYM_PREFIX "reflect.chanlen");
diff --git a/libgo/runtime/cpuprof.c b/libgo/runtime/cpuprof.c
index 516387396ea..a2a1a05ce3d 100644
--- a/libgo/runtime/cpuprof.c
+++ b/libgo/runtime/cpuprof.c
@@ -146,7 +146,7 @@ runtime_SetCPUProfileRate(intgo hz)
runtime_lock(&lk);
if(hz > 0) {
if(prof == nil) {
- prof = runtime_SysAlloc(sizeof *prof);
+ prof = runtime_SysAlloc(sizeof *prof, &mstats.other_sys);
if(prof == nil) {
runtime_printf("runtime: cpu profiling cannot allocate memory\n");
runtime_unlock(&lk);
@@ -340,7 +340,7 @@ getprofile(Profile *p)
if(p->wholding) {
// Release previous log to signal handling side.
- // Loop because we are racing against setprofile(off).
+ // Loop because we are racing against SetCPUProfileRate(0).
for(;;) {
n = p->handoff;
if(n == 0) {
@@ -367,9 +367,7 @@ getprofile(Profile *p)
return ret;
// Wait for new log.
- runtime_entersyscallblock();
- runtime_notesleep(&p->wait);
- runtime_exitsyscall();
+ runtime_notetsleepg(&p->wait, -1);
runtime_noteclear(&p->wait);
n = p->handoff;
diff --git a/libgo/runtime/env_posix.c b/libgo/runtime/env_posix.c
index 7f3fa0d8e0f..3219550af99 100644
--- a/libgo/runtime/env_posix.c
+++ b/libgo/runtime/env_posix.c
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd linux netbsd openbsd windows
+// +build darwin dragonfly freebsd linux netbsd openbsd windows
#include "runtime.h"
#include "array.h"
@@ -12,7 +12,8 @@ extern Slice syscall_Envs __asm__ (GOSYM_PREFIX "syscall.Envs");
const byte*
runtime_getenv(const char *s)
{
- int32 i, j, len;
+ int32 i, j;
+ intgo len;
const byte *v, *bs;
String* envv;
int32 envc;
diff --git a/libgo/runtime/go-append.c b/libgo/runtime/go-append.c
index 12fe876cb95..8d5dee21616 100644
--- a/libgo/runtime/go-append.c
+++ b/libgo/runtime/go-append.c
@@ -24,24 +24,24 @@ __go_append (struct __go_open_array a, void *bvalues, uintptr_t bcount,
uintptr_t element_size)
{
uintptr_t ucount;
- int count;
+ intgo count;
if (bvalues == NULL || bcount == 0)
return a;
ucount = (uintptr_t) a.__count + bcount;
- count = (int) ucount;
+ count = (intgo) ucount;
if ((uintptr_t) count != ucount || count <= a.__count)
runtime_panicstring ("append: slice overflow");
if (count > a.__capacity)
{
- int m;
+ intgo m;
void *n;
m = a.__capacity;
- if (m == 0)
- m = (int) bcount;
+ if (m + m < count)
+ m = count;
else
{
do
@@ -54,7 +54,7 @@ __go_append (struct __go_open_array a, void *bvalues, uintptr_t bcount,
while (m < count);
}
- if ((uintptr) m > MaxMem / element_size)
+ if (element_size > 0 && (uintptr) m > MaxMem / element_size)
runtime_panicstring ("growslice: cap out of range");
n = __go_alloc (m * element_size);
diff --git a/libgo/runtime/go-byte-array-to-string.c b/libgo/runtime/go-byte-array-to-string.c
index 0cd63c76d8d..088b78690fe 100644
--- a/libgo/runtime/go-byte-array-to-string.c
+++ b/libgo/runtime/go-byte-array-to-string.c
@@ -16,7 +16,7 @@ __go_byte_array_to_string (const void* p, intgo len)
String ret;
bytes = (const unsigned char *) p;
- retdata = runtime_mallocgc ((uintptr) len, FlagNoPointers, 1, 0);
+ retdata = runtime_mallocgc ((uintptr) len, 0, FlagNoScan);
__builtin_memcpy (retdata, bytes, len);
ret.str = retdata;
ret.len = len;
diff --git a/libgo/runtime/go-caller.c b/libgo/runtime/go-caller.c
index d84580fa594..8ca3c7efcd7 100644
--- a/libgo/runtime/go-caller.c
+++ b/libgo/runtime/go-caller.c
@@ -228,3 +228,23 @@ runtime_funcline_go (Func *f __attribute__((unused)), uintptr targetpc)
runtime_memclr (&ret, sizeof ret);
return ret;
}
+
+/* Return the name of a function. */
+String runtime_funcname_go (Func *f)
+ __asm__ (GOSYM_PREFIX "runtime.funcname_go");
+
+String
+runtime_funcname_go (Func *f)
+{
+ return f->name;
+}
+
+/* Return the entry point of a function. */
+uintptr runtime_funcentry_go(Func *f)
+ __asm__ (GOSYM_PREFIX "runtime.funcentry_go");
+
+uintptr
+runtime_funcentry_go (Func *f)
+{
+ return f->entry;
+}
diff --git a/libgo/runtime/go-callers.c b/libgo/runtime/go-callers.c
index dd1cf7909b6..291dfd0d666 100644
--- a/libgo/runtime/go-callers.c
+++ b/libgo/runtime/go-callers.c
@@ -53,6 +53,21 @@ callback (void *data, uintptr_t pc, const char *filename, int lineno,
return 0;
}
+ /* Skip thunks and recover functions. There is no equivalent to
+ these functions in the gc toolchain, so returning them here means
+ significantly different results for runtime.Caller(N). */
+ if (function != NULL)
+ {
+ const char *p;
+
+ p = __builtin_strchr (function, '.');
+ if (p != NULL && __builtin_strncmp (p + 1, "$thunk", 6) == 0)
+ return 0;
+ p = __builtin_strrchr (function, '$');
+ if (p != NULL && __builtin_strcmp(p, "$recover") == 0)
+ return 0;
+ }
+
if (arg->skip > 0)
{
--arg->skip;
diff --git a/libgo/runtime/go-cdiv.c b/libgo/runtime/go-cdiv.c
new file mode 100644
index 00000000000..0a81e458c84
--- /dev/null
+++ b/libgo/runtime/go-cdiv.c
@@ -0,0 +1,46 @@
+/* go-cdiv.c -- complex division routines
+
+ Copyright 2013 The Go Authors. All rights reserved.
+ Use of this source code is governed by a BSD-style
+ license that can be found in the LICENSE file. */
+
+/* Calls to these functions are generated by the Go frontend for
+ division of complex64 or complex128. We use these because Go's
+ complex division expects slightly different results from the GCC
+ default. When dividing NaN+1.0i / 0+0i, Go expects NaN+NaNi but
+ GCC generates NaN+Infi. NaN+Infi seems wrong seems the rules of
+ C99 Annex G specify that if either side of a complex number is Inf,
+ the the whole number is Inf, but an operation involving NaN ought
+ to result in NaN, not Inf. */
+
+__complex float
+__go_complex64_div (__complex float a, __complex float b)
+{
+ if (__builtin_expect (b == 0+0i, 0))
+ {
+ if (!__builtin_isinff (__real__ a)
+ && !__builtin_isinff (__imag__ a)
+ && (__builtin_isnanf (__real__ a) || __builtin_isnanf (__imag__ a)))
+ {
+ /* Pass "1" to nanf to match math/bits.go. */
+ return __builtin_nanf("1") + __builtin_nanf("1")*1i;
+ }
+ }
+ return a / b;
+}
+
+__complex double
+__go_complex128_div (__complex double a, __complex double b)
+{
+ if (__builtin_expect (b == 0+0i, 0))
+ {
+ if (!__builtin_isinf (__real__ a)
+ && !__builtin_isinf (__imag__ a)
+ && (__builtin_isnan (__real__ a) || __builtin_isnan (__imag__ a)))
+ {
+ /* Pass "1" to nan to match math/bits.go. */
+ return __builtin_nan("1") + __builtin_nan("1")*1i;
+ }
+ }
+ return a / b;
+}
diff --git a/libgo/runtime/go-int-array-to-string.c b/libgo/runtime/go-int-array-to-string.c
index 6cae2fd8ccb..d93fe651d95 100644
--- a/libgo/runtime/go-int-array-to-string.c
+++ b/libgo/runtime/go-int-array-to-string.c
@@ -41,7 +41,7 @@ __go_int_array_to_string (const void* p, intgo len)
slen += 4;
}
- retdata = runtime_mallocgc ((uintptr) slen, FlagNoPointers, 1, 0);
+ retdata = runtime_mallocgc ((uintptr) slen, 0, FlagNoScan);
ret.str = retdata;
ret.len = slen;
diff --git a/libgo/runtime/go-int-to-string.c b/libgo/runtime/go-int-to-string.c
index eb441674b6c..d90b1ddfed1 100644
--- a/libgo/runtime/go-int-to-string.c
+++ b/libgo/runtime/go-int-to-string.c
@@ -60,7 +60,7 @@ __go_int_to_string (intgo v)
}
}
- retdata = runtime_mallocgc (len, FlagNoPointers, 1, 0);
+ retdata = runtime_mallocgc (len, 0, FlagNoScan);
__builtin_memcpy (retdata, buf, len);
ret.str = retdata;
ret.len = len;
diff --git a/libgo/runtime/go-make-slice.c b/libgo/runtime/go-make-slice.c
index 591ab37e0c6..855bb17ce59 100644
--- a/libgo/runtime/go-make-slice.c
+++ b/libgo/runtime/go-make-slice.c
@@ -34,7 +34,10 @@ __go_make_slice2 (const struct __go_type_descriptor *td, uintptr_t len,
std = (const struct __go_slice_type *) td;
ilen = (intgo) len;
- if (ilen < 0 || (uintptr_t) ilen != len)
+ if (ilen < 0
+ || (uintptr_t) ilen != len
+ || (std->__element_type->__size > 0
+ && len > MaxMem / std->__element_type->__size))
runtime_panicstring ("makeslice: len out of range");
icap = (intgo) cap;
@@ -52,15 +55,15 @@ __go_make_slice2 (const struct __go_type_descriptor *td, uintptr_t len,
if (size == 0)
ret.__values = &runtime_zerobase;
else if ((std->__element_type->__code & GO_NO_POINTERS) != 0)
- ret.__values = runtime_mallocgc (size, FlagNoPointers, 1, 1);
+ ret.__values =
+ runtime_mallocgc (size,
+ (uintptr) std->__element_type | TypeInfo_Array,
+ FlagNoScan);
else
- {
- ret.__values = runtime_mallocgc (size, 0, 1, 1);
-
- if (UseSpanType)
- runtime_settype (ret.__values,
- (uintptr) std->__element_type | TypeInfo_Array);
- }
+ ret.__values =
+ runtime_mallocgc (size,
+ (uintptr) std->__element_type | TypeInfo_Array,
+ 0);
return ret;
}
diff --git a/libgo/runtime/go-new.c b/libgo/runtime/go-new.c
index b1af5f22473..9d46706eaa4 100644
--- a/libgo/runtime/go-new.c
+++ b/libgo/runtime/go-new.c
@@ -12,11 +12,11 @@
void *
__go_new (uintptr_t size)
{
- return runtime_mallocgc (size, 0, 1, 1);
+ return runtime_mallocgc (size, 0, 0);
}
void *
__go_new_nopointers (uintptr_t size)
{
- return runtime_mallocgc (size, FlagNoPointers, 1, 1);
+ return runtime_mallocgc (size, 0, FlagNoScan);
}
diff --git a/libgo/runtime/go-nosys.c b/libgo/runtime/go-nosys.c
index 3ab5ea235f2..0a94de0523e 100644
--- a/libgo/runtime/go-nosys.c
+++ b/libgo/runtime/go-nosys.c
@@ -43,6 +43,17 @@ accept4 (int sockfd __attribute__ ((unused)),
}
#endif
+#ifndef HAVE_DUP3
+int
+dup3 (int oldfd __attribute__ ((unused)),
+ int newfd __attribute__ ((unused)),
+ int flags __attribute__ ((unused)))
+{
+ errno = ENOSYS;
+ return -1;
+}
+#endif
+
#ifndef HAVE_EPOLL_CREATE1
int
epoll_create1 (int flags __attribute__ ((unused)))
@@ -112,6 +123,18 @@ futimesat (int dirfd __attribute__ ((unused)),
}
#endif
+#ifndef HAVE_GETXATTR
+ssize_t
+getxattr (const char *path __attribute__ ((unused)),
+ const char *name __attribute__ ((unused)),
+ void *value __attribute__ ((unused)),
+ size_t size __attribute__ ((unused)))
+{
+ errno = ENOSYS;
+ return -1;
+}
+#endif
+
#ifndef HAVE_INOTIFY_ADD_WATCH
int
inotify_add_watch (int fd __attribute__ ((unused)),
@@ -151,6 +174,17 @@ inotify_rm_watch (int fd __attribute__ ((unused)),
}
#endif
+#ifndef HAVE_LISTXATTR
+ssize_t
+listxattr (const char *path __attribute__ ((unused)),
+ char *list __attribute__ ((unused)),
+ size_t size __attribute__ ((unused)))
+{
+ errno = ENOSYS;
+ return -1;
+}
+#endif
+
#ifndef HAVE_MKDIRAT
int
mkdirat (int dirfd __attribute__ ((unused)),
@@ -196,6 +230,16 @@ pipe2 (int pipefd[2] __attribute__ ((unused)),
}
#endif
+#ifndef HAVE_REMOVEXATTR
+int
+removexattr (const char *path __attribute__ ((unused)),
+ const char *name __attribute__ ((unused)))
+{
+ errno = ENOSYS;
+ return -1;
+}
+#endif
+
#ifndef HAVE_RENAMEAT
int
renameat (int olddirfd __attribute__ ((unused)),
@@ -208,6 +252,19 @@ renameat (int olddirfd __attribute__ ((unused)),
}
#endif
+#ifndef HAVE_SETXATTR
+int
+setxattr (const char *path __attribute__ ((unused)),
+ const char *name __attribute__ ((unused)),
+ const void *value __attribute__ ((unused)),
+ size_t size __attribute__ ((unused)),
+ int flags __attribute__ ((unused)))
+{
+ errno = ENOSYS;
+ return -1;
+}
+#endif
+
#ifndef HAVE_SPLICE
int
splice (int fd __attribute__ ((unused)),
diff --git a/libgo/runtime/go-reflect-call.c b/libgo/runtime/go-reflect-call.c
index 5cf370798bf..0fed68a50e7 100644
--- a/libgo/runtime/go-reflect-call.c
+++ b/libgo/runtime/go-reflect-call.c
@@ -271,7 +271,21 @@ go_func_return_ffi (const struct __go_func_type *func)
types = (const struct __go_type_descriptor **) func->__out.__values;
if (count == 1)
- return go_type_to_ffi (types[0]);
+ {
+
+#if defined (__i386__) && !defined (__x86_64__)
+ /* FFI does not support complex types. On 32-bit x86, a
+ complex64 will be returned in %eax/%edx. We normally tell
+ FFI that a complex64 is a struct of two floats. On 32-bit
+ x86 a struct of two floats is returned via a hidden first
+ pointer parameter. Fortunately we can make everything work
+ by pretending that complex64 is int64. */
+ if ((types[0]->__code & GO_CODE_MASK) == GO_COMPLEX64)
+ return &ffi_type_sint64;
+#endif
+
+ return go_type_to_ffi (types[0]);
+ }
ret = (ffi_type *) __go_alloc (sizeof (ffi_type));
ret->type = FFI_TYPE_STRUCT;
diff --git a/libgo/runtime/go-signal.c b/libgo/runtime/go-signal.c
index 9771b71cfcf..4f0dcc78c17 100644
--- a/libgo/runtime/go-signal.c
+++ b/libgo/runtime/go-signal.c
@@ -139,22 +139,6 @@ SigTab runtime_sigtab[] = {
#undef P
#undef D
-
-static int8 badsignal[] = "runtime: signal received on thread not created by Go.\n";
-
-static void
-runtime_badsignal(int32 sig)
-{
- // Avoid -D_FORTIFY_SOURCE problems.
- int rv __attribute__((unused));
-
- if (sig == SIGPROF) {
- return; // Ignore SIGPROFs intended for a non-Go thread.
- }
- rv = runtime_write(2, badsignal, sizeof badsignal - 1);
- runtime_exit(1);
-}
-
/* Handle a signal, for cases where we don't panic. We can split the
stack here. */
@@ -399,6 +383,9 @@ sig_tramp_info (int sig, Siginfo *info, void *context)
{
G *gp;
M *mp;
+#ifdef USING_SPLIT_STACK
+ void *stack_context[10];
+#endif
/* We are now running on the stack registered via sigaltstack.
(Actually there is a small span of time between runtime_siginit
@@ -409,7 +396,7 @@ sig_tramp_info (int sig, Siginfo *info, void *context)
if (gp != NULL)
{
#ifdef USING_SPLIT_STACK
- __splitstack_getcontext (&gp->stack_context[0]);
+ __splitstack_getcontext (&stack_context[0]);
#endif
}
@@ -432,7 +419,7 @@ sig_tramp_info (int sig, Siginfo *info, void *context)
if (gp != NULL)
{
#ifdef USING_SPLIT_STACK
- __splitstack_setcontext (&gp->stack_context[0]);
+ __splitstack_setcontext (&stack_context[0]);
#endif
}
}
diff --git a/libgo/runtime/go-string-to-byte-array.c b/libgo/runtime/go-string-to-byte-array.c
index 75fac1dbfe6..5e030330f29 100644
--- a/libgo/runtime/go-string-to-byte-array.c
+++ b/libgo/runtime/go-string-to-byte-array.c
@@ -15,7 +15,8 @@ __go_string_to_byte_array (String str)
unsigned char *data;
struct __go_open_array ret;
- data = (unsigned char *) runtime_mallocgc (str.len, FlagNoPointers, 1, 0);
+ data = (unsigned char *) runtime_mallocgc (str.len, 0,
+ FlagNoScan | FlagNoZero);
__builtin_memcpy (data, str.str, str.len);
ret.__values = (void *) data;
ret.__count = str.len;
diff --git a/libgo/runtime/go-string-to-int-array.c b/libgo/runtime/go-string-to-int-array.c
index 16970bdd042..d91c9e2df82 100644
--- a/libgo/runtime/go-string-to-int-array.c
+++ b/libgo/runtime/go-string-to-int-array.c
@@ -32,8 +32,8 @@ __go_string_to_int_array (String str)
p += __go_get_rune (p, pend - p, &rune);
}
- data = (uint32_t *) runtime_mallocgc (c * sizeof (uint32_t), FlagNoPointers,
- 1, 0);
+ data = (uint32_t *) runtime_mallocgc (c * sizeof (uint32_t), 0,
+ FlagNoScan | FlagNoZero);
p = str.str;
pd = data;
while (p < pend)
diff --git a/libgo/runtime/go-strplus.c b/libgo/runtime/go-strplus.c
index d6e6df67fce..13915e3e673 100644
--- a/libgo/runtime/go-strplus.c
+++ b/libgo/runtime/go-strplus.c
@@ -21,7 +21,7 @@ __go_string_plus (String s1, String s2)
return s1;
len = s1.len + s2.len;
- retdata = runtime_mallocgc (len, FlagNoPointers, 1, 0);
+ retdata = runtime_mallocgc (len, 0, FlagNoScan | FlagNoZero);
__builtin_memcpy (retdata, s1.str, s1.len);
__builtin_memcpy (retdata + s1.len, s2.str, s2.len);
ret.str = retdata;
diff --git a/libgo/runtime/lfstack.c b/libgo/runtime/lfstack.c
index 230ed87c43f..132783c3644 100644
--- a/libgo/runtime/lfstack.c
+++ b/libgo/runtime/lfstack.c
@@ -41,10 +41,10 @@ runtime_lfstackpush(uint64 *head, LFNode *node)
node->pushcnt++;
new = (uint64)(uintptr)node|(((uint64)node->pushcnt&CNT_MASK)<<PTR_BITS);
- old = runtime_atomicload64(head);
for(;;) {
+ old = runtime_atomicload64(head);
node->next = (LFNode*)(uintptr)(old&PTR_MASK);
- if(runtime_cas64(head, &old, new))
+ if(runtime_cas64(head, old, new))
break;
}
}
@@ -55,8 +55,8 @@ runtime_lfstackpop(uint64 *head)
LFNode *node, *node2;
uint64 old, new;
- old = runtime_atomicload64(head);
for(;;) {
+ old = runtime_atomicload64(head);
if(old == 0)
return nil;
node = (LFNode*)(uintptr)(old&PTR_MASK);
@@ -64,7 +64,7 @@ runtime_lfstackpop(uint64 *head)
new = 0;
if(node2 != nil)
new = (uint64)(uintptr)node2|(((uint64)node2->pushcnt&CNT_MASK)<<PTR_BITS);
- if(runtime_cas64(head, &old, new))
+ if(runtime_cas64(head, old, new))
return node;
}
}
diff --git a/libgo/runtime/lock_futex.c b/libgo/runtime/lock_futex.c
index 4b9651a75de..fa270132895 100644
--- a/libgo/runtime/lock_futex.c
+++ b/libgo/runtime/lock_futex.c
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build freebsd linux
+// +build dragonfly freebsd linux
#include "runtime.h"
@@ -91,14 +91,14 @@ runtime_unlock(Lock *l)
{
uint32 v;
- if(--runtime_m()->locks < 0)
- runtime_throw("runtime_unlock: lock count");
-
v = runtime_xchg((uint32*)&l->key, MUTEX_UNLOCKED);
if(v == MUTEX_UNLOCKED)
runtime_throw("unlock of unlocked lock");
if(v == MUTEX_SLEEPING)
runtime_futexwakeup((uint32*)&l->key, 1);
+
+ if(--runtime_m()->locks < 0)
+ runtime_throw("runtime_unlock: lock count");
}
// One-time notifications.
@@ -111,37 +111,45 @@ runtime_noteclear(Note *n)
void
runtime_notewakeup(Note *n)
{
- if(runtime_xchg((uint32*)&n->key, 1))
+ uint32 old;
+
+ old = runtime_xchg((uint32*)&n->key, 1);
+ if(old != 0) {
+ runtime_printf("notewakeup - double wakeup (%d)\n", old);
runtime_throw("notewakeup - double wakeup");
+ }
runtime_futexwakeup((uint32*)&n->key, 1);
}
void
runtime_notesleep(Note *n)
{
- if(runtime_m()->profilehz > 0)
- runtime_setprof(false);
+ /* For gccgo it's OK to sleep in non-g0, and it happens in
+ stoptheworld because we have not implemented preemption.
+
+ if(runtime_g() != runtime_m()->g0)
+ runtime_throw("notesleep not on g0");
+ */
while(runtime_atomicload((uint32*)&n->key) == 0)
runtime_futexsleep((uint32*)&n->key, 0, -1);
- if(runtime_m()->profilehz > 0)
- runtime_setprof(true);
}
-void
-runtime_notetsleep(Note *n, int64 ns)
+static bool
+notetsleep(Note *n, int64 ns, int64 deadline, int64 now)
{
- int64 deadline, now;
+ // Conceptually, deadline and now are local variables.
+ // They are passed as arguments so that the space for them
+ // does not count against our nosplit stack sequence.
if(ns < 0) {
- runtime_notesleep(n);
- return;
+ while(runtime_atomicload((uint32*)&n->key) == 0)
+ runtime_futexsleep((uint32*)&n->key, 0, -1);
+ return true;
}
if(runtime_atomicload((uint32*)&n->key) != 0)
- return;
+ return true;
- if(runtime_m()->profilehz > 0)
- runtime_setprof(false);
deadline = runtime_nanotime() + ns;
for(;;) {
runtime_futexsleep((uint32*)&n->key, 0, ns);
@@ -152,6 +160,33 @@ runtime_notetsleep(Note *n, int64 ns)
break;
ns = deadline - now;
}
- if(runtime_m()->profilehz > 0)
- runtime_setprof(true);
+ return runtime_atomicload((uint32*)&n->key) != 0;
+}
+
+bool
+runtime_notetsleep(Note *n, int64 ns)
+{
+ bool res;
+
+ if(runtime_g() != runtime_m()->g0 && !runtime_m()->gcing)
+ runtime_throw("notetsleep not on g0");
+
+ res = notetsleep(n, ns, 0, 0);
+ return res;
+}
+
+// same as runtime_notetsleep, but called on user g (not g0)
+// calls only nosplit functions between entersyscallblock/exitsyscall
+bool
+runtime_notetsleepg(Note *n, int64 ns)
+{
+ bool res;
+
+ if(runtime_g() == runtime_m()->g0)
+ runtime_throw("notetsleepg on g0");
+
+ runtime_entersyscallblock();
+ res = notetsleep(n, ns, 0, 0);
+ runtime_exitsyscall();
+ return res;
}
diff --git a/libgo/runtime/lock_sema.c b/libgo/runtime/lock_sema.c
index 2663c5463de..ce435119323 100644
--- a/libgo/runtime/lock_sema.c
+++ b/libgo/runtime/lock_sema.c
@@ -95,9 +95,6 @@ runtime_unlock(Lock *l)
uintptr v;
M *mp;
- if(--runtime_m()->locks < 0)
- runtime_throw("runtime_unlock: lock count");
-
for(;;) {
v = (uintptr)runtime_atomicloadp((void**)&l->key);
if(v == LOCKED) {
@@ -114,6 +111,9 @@ runtime_unlock(Lock *l)
}
}
}
+
+ if(--runtime_m()->locks < 0)
+ runtime_throw("runtime_unlock: lock count");
}
// One-time notifications.
@@ -151,6 +151,10 @@ runtime_notesleep(Note *n)
M *m;
m = runtime_m();
+
+ if(runtime_g() != m->g0)
+ runtime_throw("notesleep not on g0");
+
if(m->waitsema == 0)
m->waitsema = runtime_semacreate();
if(!runtime_casp((void**)&n->key, nil, m)) { // must be LOCKED (got wakeup)
@@ -159,61 +163,49 @@ runtime_notesleep(Note *n)
return;
}
// Queued. Sleep.
- if(m->profilehz > 0)
- runtime_setprof(false);
runtime_semasleep(-1);
- if(m->profilehz > 0)
- runtime_setprof(true);
}
-void
-runtime_notetsleep(Note *n, int64 ns)
+static bool
+notetsleep(Note *n, int64 ns, int64 deadline, M *mp)
{
M *m;
- M *mp;
- int64 deadline, now;
-
- if(ns < 0) {
- runtime_notesleep(n);
- return;
- }
m = runtime_m();
- if(m->waitsema == 0)
- m->waitsema = runtime_semacreate();
+
+ // Conceptually, deadline and mp are local variables.
+ // They are passed as arguments so that the space for them
+ // does not count against our nosplit stack sequence.
// Register for wakeup on n->waitm.
if(!runtime_casp((void**)&n->key, nil, m)) { // must be LOCKED (got wakeup already)
if(n->key != LOCKED)
runtime_throw("notetsleep - waitm out of sync");
- return;
+ return true;
+ }
+
+ if(ns < 0) {
+ // Queued. Sleep.
+ runtime_semasleep(-1);
+ return true;
}
- if(m->profilehz > 0)
- runtime_setprof(false);
deadline = runtime_nanotime() + ns;
for(;;) {
// Registered. Sleep.
if(runtime_semasleep(ns) >= 0) {
// Acquired semaphore, semawakeup unregistered us.
// Done.
- if(m->profilehz > 0)
- runtime_setprof(true);
- return;
+ return true;
}
// Interrupted or timed out. Still registered. Semaphore not acquired.
- now = runtime_nanotime();
- if(now >= deadline)
+ ns = deadline - runtime_nanotime();
+ if(ns <= 0)
break;
-
// Deadline hasn't arrived. Keep sleeping.
- ns = deadline - now;
}
- if(m->profilehz > 0)
- runtime_setprof(true);
-
// Deadline arrived. Still registered. Semaphore not acquired.
// Want to give up and return, but have to unregister first,
// so that any notewakeup racing with the return does not
@@ -223,15 +215,54 @@ runtime_notetsleep(Note *n, int64 ns)
if(mp == m) {
// No wakeup yet; unregister if possible.
if(runtime_casp((void**)&n->key, mp, nil))
- return;
+ return false;
} else if(mp == (M*)LOCKED) {
// Wakeup happened so semaphore is available.
// Grab it to avoid getting out of sync.
if(runtime_semasleep(-1) < 0)
runtime_throw("runtime: unable to acquire - semaphore out of sync");
- return;
- } else {
+ return true;
+ } else
runtime_throw("runtime: unexpected waitm - semaphore out of sync");
- }
}
}
+
+bool
+runtime_notetsleep(Note *n, int64 ns)
+{
+ M *m;
+ bool res;
+
+ m = runtime_m();
+
+ if(runtime_g() != m->g0 && !m->gcing)
+ runtime_throw("notetsleep not on g0");
+
+ if(m->waitsema == 0)
+ m->waitsema = runtime_semacreate();
+
+ res = notetsleep(n, ns, 0, nil);
+ return res;
+}
+
+// same as runtime_notetsleep, but called on user g (not g0)
+// calls only nosplit functions between entersyscallblock/exitsyscall
+bool
+runtime_notetsleepg(Note *n, int64 ns)
+{
+ M *m;
+ bool res;
+
+ m = runtime_m();
+
+ if(runtime_g() == m->g0)
+ runtime_throw("notetsleepg on g0");
+
+ if(m->waitsema == 0)
+ m->waitsema = runtime_semacreate();
+
+ runtime_entersyscallblock();
+ res = notetsleep(n, ns, 0, nil);
+ runtime_exitsyscall();
+ return res;
+}
diff --git a/libgo/runtime/malloc.goc b/libgo/runtime/malloc.goc
index 8ccaa6b888c..72470730471 100644
--- a/libgo/runtime/malloc.goc
+++ b/libgo/runtime/malloc.goc
@@ -18,7 +18,17 @@ package runtime
#include "go-type.h"
#include "race.h"
-MHeap *runtime_mheap;
+// Map gccgo field names to gc field names.
+// Eface aka __go_empty_interface.
+#define type __type_descriptor
+// Type aka __go_type_descriptor
+#define kind __code
+#define string __reflection
+#define KindPtr GO_PTR
+#define KindNoPointers GO_NO_POINTERS
+
+// Mark mheap as 'no pointers', it does not contain interesting pointers but occupies ~45K.
+MHeap runtime_mheap;
int32 runtime_checking;
@@ -30,19 +40,28 @@ extern volatile intgo runtime_MemProfileRate
// Allocate an object of at least size bytes.
// Small objects are allocated from the per-thread cache's free lists.
// Large objects (> 32 kB) are allocated straight from the heap.
+// If the block will be freed with runtime_free(), typ must be 0.
void*
-runtime_mallocgc(uintptr size, uint32 flag, int32 dogc, int32 zeroed)
+runtime_mallocgc(uintptr size, uintptr typ, uint32 flag)
{
M *m;
G *g;
int32 sizeclass;
intgo rate;
MCache *c;
+ MCacheList *l;
uintptr npages;
MSpan *s;
- void *v;
+ MLink *v;
bool incallback;
+ if(size == 0) {
+ // All 0-length allocations use this pointer.
+ // The language does not require the allocations to
+ // have distinct values.
+ return &runtime_zerobase;
+ }
+
m = runtime_m();
g = runtime_g();
@@ -56,34 +75,45 @@ runtime_mallocgc(uintptr size, uint32 flag, int32 dogc, int32 zeroed)
runtime_exitsyscall();
m = runtime_m();
incallback = true;
- dogc = false;
+ flag |= FlagNoGC;
}
- if(runtime_gcwaiting && g != m->g0 && m->locks == 0 && dogc) {
+ if(runtime_gcwaiting() && g != m->g0 && m->locks == 0 && !(flag & FlagNoInvokeGC)) {
runtime_gosched();
m = runtime_m();
}
if(m->mallocing)
runtime_throw("malloc/free - deadlock");
+ // Disable preemption during settype_flush.
+ // We can not use m->mallocing for this, because settype_flush calls mallocgc.
+ m->locks++;
m->mallocing = 1;
- if(size == 0)
- size = 1;
if(DebugTypeAtBlockEnd)
size += sizeof(uintptr);
c = m->mcache;
- c->local_nmalloc++;
if(size <= MaxSmallSize) {
// Allocate from mcache free lists.
- sizeclass = runtime_SizeToClass(size);
+ // Inlined version of SizeToClass().
+ if(size <= 1024-8)
+ sizeclass = runtime_size_to_class8[(size+7)>>3];
+ else
+ sizeclass = runtime_size_to_class128[(size-1024+127) >> 7];
size = runtime_class_to_size[sizeclass];
- v = runtime_MCache_Alloc(c, sizeclass, size, zeroed);
- if(v == nil)
- runtime_throw("out of memory");
- c->local_alloc += size;
- c->local_total_alloc += size;
- c->local_by_size[sizeclass].nmalloc++;
+ l = &c->list[sizeclass];
+ if(l->list == nil)
+ runtime_MCache_Refill(c, sizeclass);
+ v = l->list;
+ l->list = v->next;
+ l->nlist--;
+ if(!(flag & FlagNoZero)) {
+ v->next = nil;
+ // block is zeroed iff second word is zero ...
+ if(size > sizeof(uintptr) && ((uintptr*)v)[1] != 0)
+ runtime_memclr((byte*)v, size);
+ }
+ c->local_cachealloc += size;
} else {
// TODO(rsc): Report tracebacks for very large allocations.
@@ -91,32 +121,39 @@ runtime_mallocgc(uintptr size, uint32 flag, int32 dogc, int32 zeroed)
npages = size >> PageShift;
if((size & PageMask) != 0)
npages++;
- s = runtime_MHeap_Alloc(runtime_mheap, npages, 0, 1, zeroed);
+ s = runtime_MHeap_Alloc(&runtime_mheap, npages, 0, 1, !(flag & FlagNoZero));
if(s == nil)
runtime_throw("out of memory");
+ s->limit = (byte*)(s->start<<PageShift) + size;
size = npages<<PageShift;
- c->local_alloc += size;
- c->local_total_alloc += size;
v = (void*)(s->start << PageShift);
// setup for mark sweep
runtime_markspan(v, 0, 0, true);
}
- if (sizeof(void*) == 4 && c->local_total_alloc >= (1<<30)) {
- // purge cache stats to prevent overflow
- runtime_lock(runtime_mheap);
- runtime_purgecachedstats(c);
- runtime_unlock(runtime_mheap);
- }
-
if(!(flag & FlagNoGC))
- runtime_markallocated(v, size, (flag&FlagNoPointers) != 0);
+ runtime_markallocated(v, size, (flag&FlagNoScan) != 0);
if(DebugTypeAtBlockEnd)
- *(uintptr*)((uintptr)v+size-sizeof(uintptr)) = 0;
+ *(uintptr*)((uintptr)v+size-sizeof(uintptr)) = typ;
+
+ // TODO: save type even if FlagNoScan? Potentially expensive but might help
+ // heap profiling/tracing.
+ if(UseSpanType && !(flag & FlagNoScan) && typ != 0) {
+ uintptr *buf, i;
+
+ buf = m->settype_buf;
+ i = m->settype_bufsize;
+ buf[i++] = (uintptr)v;
+ buf[i++] = typ;
+ m->settype_bufsize = i;
+ }
m->mallocing = 0;
+ if(UseSpanType && !(flag & FlagNoScan) && typ != 0 && m->settype_bufsize == nelem(m->settype_buf))
+ runtime_settype_flush(m);
+ m->locks--;
if(!(flag & FlagNoProfiling) && (rate = runtime_MemProfileRate) > 0) {
if(size >= (uint32) rate)
@@ -135,13 +172,11 @@ runtime_mallocgc(uintptr size, uint32 flag, int32 dogc, int32 zeroed)
}
}
- if(dogc && mstats.heap_alloc >= mstats.next_gc)
+ if(!(flag & FlagNoInvokeGC) && mstats.heap_alloc >= mstats.next_gc)
runtime_gc(0);
- if(raceenabled) {
- runtime_racemalloc(v, size, m->racepc);
- m->racepc = nil;
- }
+ if(raceenabled)
+ runtime_racemalloc(v, size);
if(incallback)
runtime_entersyscall();
@@ -152,7 +187,7 @@ runtime_mallocgc(uintptr size, uint32 flag, int32 dogc, int32 zeroed)
void*
__go_alloc(uintptr size)
{
- return runtime_mallocgc(size, 0, 0, 1);
+ return runtime_mallocgc(size, 0, FlagNoInvokeGC);
}
// Free the object whose base pointer is v.
@@ -197,7 +232,9 @@ __go_free(void *v)
// they might coalesce v into other spans and change the bitmap further.
runtime_markfreed(v, size);
runtime_unmarkspan(v, 1<<PageShift);
- runtime_MHeap_Free(runtime_mheap, s, 1);
+ runtime_MHeap_Free(&runtime_mheap, s, 1);
+ c->local_nlargefree++;
+ c->local_largefree += size;
} else {
// Small object.
size = runtime_class_to_size[sizeclass];
@@ -207,11 +244,9 @@ __go_free(void *v)
// it might coalesce v and other blocks into a bigger span
// and change the bitmap further.
runtime_markfreed(v, size);
- c->local_by_size[sizeclass].nfree++;
+ c->local_nsmallfree[sizeclass]++;
runtime_MCache_Free(c, v, sizeclass, size);
}
- c->local_nfree++;
- c->local_alloc -= size;
if(prof)
runtime_MProf_Free(v, size);
m->mallocing = 0;
@@ -230,12 +265,12 @@ runtime_mlookup(void *v, byte **base, uintptr *size, MSpan **sp)
m->mcache->local_nlookup++;
if (sizeof(void*) == 4 && m->mcache->local_nlookup >= (1<<30)) {
// purge cache stats to prevent overflow
- runtime_lock(runtime_mheap);
+ runtime_lock(&runtime_mheap);
runtime_purgecachedstats(m->mcache);
- runtime_unlock(runtime_mheap);
+ runtime_unlock(&runtime_mheap);
}
- s = runtime_MHeap_LookupMaybe(runtime_mheap, v);
+ s = runtime_MHeap_LookupMaybe(&runtime_mheap, v);
if(sp)
*sp = s;
if(s == nil) {
@@ -257,11 +292,6 @@ runtime_mlookup(void *v, byte **base, uintptr *size, MSpan **sp)
return 1;
}
- if((byte*)v >= (byte*)s->limit) {
- // pointers past the last block do not count as pointers.
- return 0;
- }
-
n = s->elemsize;
if(base) {
i = ((byte*)v - p)/n;
@@ -279,11 +309,9 @@ runtime_allocmcache(void)
intgo rate;
MCache *c;
- runtime_lock(runtime_mheap);
- c = runtime_FixAlloc_Alloc(&runtime_mheap->cachealloc);
- mstats.mcache_inuse = runtime_mheap->cachealloc.inuse;
- mstats.mcache_sys = runtime_mheap->cachealloc.sys;
- runtime_unlock(runtime_mheap);
+ runtime_lock(&runtime_mheap);
+ c = runtime_FixAlloc_Alloc(&runtime_mheap.cachealloc);
+ runtime_unlock(&runtime_mheap);
runtime_memclr((byte*)c, sizeof(*c));
// Set first allocation sample size.
@@ -300,30 +328,32 @@ void
runtime_freemcache(MCache *c)
{
runtime_MCache_ReleaseAll(c);
- runtime_lock(runtime_mheap);
+ runtime_lock(&runtime_mheap);
runtime_purgecachedstats(c);
- runtime_FixAlloc_Free(&runtime_mheap->cachealloc, c);
- runtime_unlock(runtime_mheap);
+ runtime_FixAlloc_Free(&runtime_mheap.cachealloc, c);
+ runtime_unlock(&runtime_mheap);
}
void
runtime_purgecachedstats(MCache *c)
{
+ MHeap *h;
+ int32 i;
+
// Protected by either heap or GC lock.
+ h = &runtime_mheap;
mstats.heap_alloc += c->local_cachealloc;
c->local_cachealloc = 0;
- mstats.heap_objects += c->local_objects;
- c->local_objects = 0;
- mstats.nmalloc += c->local_nmalloc;
- c->local_nmalloc = 0;
- mstats.nfree += c->local_nfree;
- c->local_nfree = 0;
mstats.nlookup += c->local_nlookup;
c->local_nlookup = 0;
- mstats.alloc += c->local_alloc;
- c->local_alloc= 0;
- mstats.total_alloc += c->local_total_alloc;
- c->local_total_alloc= 0;
+ h->largefree += c->local_largefree;
+ c->local_largefree = 0;
+ h->nlargefree += c->local_nlargefree;
+ c->local_nlargefree = 0;
+ for(i=0; i<(int32)nelem(c->local_nsmallfree); i++) {
+ h->nsmallfree[i] += c->local_nsmallfree[i];
+ c->local_nsmallfree[i] = 0;
+ }
}
extern uintptr runtime_sizeof_C_MStats
@@ -335,24 +365,24 @@ void
runtime_mallocinit(void)
{
byte *p;
- uintptr arena_size, bitmap_size;
+ uintptr arena_size, bitmap_size, spans_size;
extern byte _end[];
byte *want;
uintptr limit;
+ uint64 i;
runtime_sizeof_C_MStats = sizeof(MStats);
p = nil;
arena_size = 0;
bitmap_size = 0;
-
+ spans_size = 0;
+
// for 64-bit build
USED(p);
USED(arena_size);
USED(bitmap_size);
-
- if((runtime_mheap = runtime_SysAlloc(sizeof(*runtime_mheap))) == nil)
- runtime_throw("runtime: cannot allocate heap metadata");
+ USED(spans_size);
runtime_InitSizes();
@@ -369,15 +399,17 @@ runtime_mallocinit(void)
// 128 GB (MaxMem) should be big enough for now.
//
// The code will work with the reservation at any address, but ask
- // SysReserve to use 0x000000c000000000 if possible.
+ // SysReserve to use 0x0000XXc000000000 if possible (XX=00...7f).
// Allocating a 128 GB region takes away 37 bits, and the amd64
// doesn't let us choose the top 17 bits, so that leaves the 11 bits
// in the middle of 0x00c0 for us to choose. Choosing 0x00c0 means
- // that the valid memory addresses will begin 0x00c0, 0x00c1, ..., 0x0x00df.
+ // that the valid memory addresses will begin 0x00c0, 0x00c1, ..., 0x00df.
// In little-endian, that's c0 00, c1 00, ..., df 00. None of those are valid
// UTF-8 sequences, and they are otherwise as far away from
- // ff (likely a common byte) as possible. An earlier attempt to use 0x11f8
- // caused out of memory errors on OS X during thread allocations.
+ // ff (likely a common byte) as possible. If that fails, we try other 0xXXc0
+ // addresses. An earlier attempt to use 0x11f8 caused out of memory errors
+ // on OS X during thread allocations. 0x00c0 causes conflicts with
+ // AddressSanitizer which reserves all memory up to 0x0100.
// These choices are both for debuggability and to reduce the
// odds of the conservative garbage collector not collecting memory
// because some non-pointer block of memory had a bit pattern
@@ -389,7 +421,14 @@ runtime_mallocinit(void)
// If this fails we fall back to the 32 bit memory mechanism
arena_size = MaxMem;
bitmap_size = arena_size / (sizeof(void*)*8/4);
- p = runtime_SysReserve((void*)(0x00c0ULL<<32), bitmap_size + arena_size);
+ spans_size = arena_size / PageSize * sizeof(runtime_mheap.spans[0]);
+ spans_size = ROUND(spans_size, PageSize);
+ for(i = 0; i <= 0x7f; i++) {
+ p = (void*)(uintptr)(i<<40 | 0x00c0ULL<<32);
+ p = runtime_SysReserve(p, bitmap_size + spans_size + arena_size);
+ if(p != nil)
+ break;
+ }
}
if (p == nil) {
// On a 32-bit machine, we can't typically get away
@@ -411,11 +450,14 @@ runtime_mallocinit(void)
// of address space, which is probably too much in a 32-bit world.
bitmap_size = MaxArena32 / (sizeof(void*)*8/4);
arena_size = 512<<20;
- if(limit > 0 && arena_size+bitmap_size > limit) {
+ spans_size = MaxArena32 / PageSize * sizeof(runtime_mheap.spans[0]);
+ if(limit > 0 && arena_size+bitmap_size+spans_size > limit) {
bitmap_size = (limit / 9) & ~((1<<PageShift) - 1);
arena_size = bitmap_size * 8;
+ spans_size = arena_size / PageSize * sizeof(runtime_mheap.spans[0]);
}
-
+ spans_size = ROUND(spans_size, PageSize);
+
// SysReserve treats the address we ask for, end, as a hint,
// not as an absolute requirement. If we ask for the end
// of the data segment but the operating system requires
@@ -425,25 +467,27 @@ runtime_mallocinit(void)
// So adjust it upward a little bit ourselves: 1/4 MB to get
// away from the running binary image and then round up
// to a MB boundary.
- want = (byte*)(((uintptr)_end + (1<<18) + (1<<20) - 1)&~((1<<20)-1));
- if(0xffffffff - (uintptr)want <= bitmap_size + arena_size)
+ want = (byte*)ROUND((uintptr)_end + (1<<18), 1<<20);
+ if(0xffffffff - (uintptr)want <= bitmap_size + spans_size + arena_size)
want = 0;
- p = runtime_SysReserve(want, bitmap_size + arena_size);
+ p = runtime_SysReserve(want, bitmap_size + spans_size + arena_size);
if(p == nil)
runtime_throw("runtime: cannot reserve arena virtual address space");
if((uintptr)p & (((uintptr)1<<PageShift)-1))
- runtime_printf("runtime: SysReserve returned unaligned address %p; asked for %p", p, bitmap_size+arena_size);
+ runtime_printf("runtime: SysReserve returned unaligned address %p; asked for %p", p,
+ bitmap_size+spans_size+arena_size);
}
if((uintptr)p & (((uintptr)1<<PageShift)-1))
runtime_throw("runtime: SysReserve returned unaligned address");
- runtime_mheap->bitmap = p;
- runtime_mheap->arena_start = p + bitmap_size;
- runtime_mheap->arena_used = runtime_mheap->arena_start;
- runtime_mheap->arena_end = runtime_mheap->arena_start + arena_size;
+ runtime_mheap.spans = (MSpan**)p;
+ runtime_mheap.bitmap = p + spans_size;
+ runtime_mheap.arena_start = p + spans_size + bitmap_size;
+ runtime_mheap.arena_used = runtime_mheap.arena_start;
+ runtime_mheap.arena_end = runtime_mheap.arena_start + arena_size;
// Initialize the rest of the allocator.
- runtime_MHeap_Init(runtime_mheap, runtime_SysAlloc);
+ runtime_MHeap_Init(&runtime_mheap);
runtime_m()->mcache = runtime_allocmcache();
// See if it works.
@@ -463,8 +507,7 @@ runtime_MHeap_SysAlloc(MHeap *h, uintptr n)
uintptr needed;
needed = (uintptr)h->arena_used + n - (uintptr)h->arena_end;
- // Round wanted arena size to a multiple of 256MB.
- needed = (needed + (256<<20) - 1) & ~((256<<20)-1);
+ needed = ROUND(needed, 256<<20);
new_end = h->arena_end + needed;
if(new_end <= h->arena_start + MaxArena32) {
p = runtime_SysReserve(h->arena_end, new_end - h->arena_end);
@@ -475,9 +518,10 @@ runtime_MHeap_SysAlloc(MHeap *h, uintptr n)
if(n <= (uintptr)(h->arena_end - h->arena_used)) {
// Keep taking from our reservation.
p = h->arena_used;
- runtime_SysMap(p, n);
+ runtime_SysMap(p, n, &mstats.heap_sys);
h->arena_used += n;
runtime_MHeap_MapBits(h);
+ runtime_MHeap_MapSpans(h);
if(raceenabled)
runtime_racemapshadow(p, n);
return p;
@@ -490,14 +534,14 @@ runtime_MHeap_SysAlloc(MHeap *h, uintptr n)
// On 32-bit, once the reservation is gone we can
// try to get memory at a location chosen by the OS
// and hope that it is in the range we allocated bitmap for.
- p = runtime_SysAlloc(n);
+ p = runtime_SysAlloc(n, &mstats.heap_sys);
if(p == nil)
return nil;
if(p < h->arena_start || (uintptr)(p+n - h->arena_start) >= MaxArena32) {
runtime_printf("runtime: memory allocated by OS (%p) not in usable range [%p,%p)\n",
p, h->arena_start, h->arena_start+MaxArena32);
- runtime_SysFree(p, n);
+ runtime_SysFree(p, n, &mstats.heap_sys);
return nil;
}
@@ -506,6 +550,7 @@ runtime_MHeap_SysAlloc(MHeap *h, uintptr n)
if(h->arena_used > h->arena_end)
h->arena_end = h->arena_used;
runtime_MHeap_MapBits(h);
+ runtime_MHeap_MapSpans(h);
if(raceenabled)
runtime_racemapshadow(p, n);
}
@@ -513,17 +558,68 @@ runtime_MHeap_SysAlloc(MHeap *h, uintptr n)
return p;
}
+static struct
+{
+ Lock;
+ byte* pos;
+ byte* end;
+} persistent;
+
+enum
+{
+ PersistentAllocChunk = 256<<10,
+ PersistentAllocMaxBlock = 64<<10, // VM reservation granularity is 64K on windows
+};
+
+// Wrapper around SysAlloc that can allocate small chunks.
+// There is no associated free operation.
+// Intended for things like function/type/debug-related persistent data.
+// If align is 0, uses default align (currently 8).
+void*
+runtime_persistentalloc(uintptr size, uintptr align, uint64 *stat)
+{
+ byte *p;
+
+ if(align != 0) {
+ if(align&(align-1))
+ runtime_throw("persistentalloc: align is now a power of 2");
+ if(align > PageSize)
+ runtime_throw("persistentalloc: align is too large");
+ } else
+ align = 8;
+ if(size >= PersistentAllocMaxBlock)
+ return runtime_SysAlloc(size, stat);
+ runtime_lock(&persistent);
+ persistent.pos = (byte*)ROUND((uintptr)persistent.pos, align);
+ if(persistent.pos + size > persistent.end) {
+ persistent.pos = runtime_SysAlloc(PersistentAllocChunk, &mstats.other_sys);
+ if(persistent.pos == nil) {
+ runtime_unlock(&persistent);
+ runtime_throw("runtime: cannot allocate memory");
+ }
+ persistent.end = persistent.pos + PersistentAllocChunk;
+ }
+ p = persistent.pos;
+ persistent.pos += size;
+ runtime_unlock(&persistent);
+ if(stat != &mstats.other_sys) {
+ // reaccount the allocation against provided stat
+ runtime_xadd64(stat, size);
+ runtime_xadd64(&mstats.other_sys, -(uint64)size);
+ }
+ return p;
+}
+
static Lock settype_lock;
void
-runtime_settype_flush(M *mp, bool sysalloc)
+runtime_settype_flush(M *mp)
{
uintptr *buf, *endbuf;
uintptr size, ofs, j, t;
uintptr ntypes, nbytes2, nbytes3;
uintptr *data2;
byte *data3;
- bool sysalloc3;
void *v;
uintptr typ, p;
MSpan *s;
@@ -542,8 +638,8 @@ runtime_settype_flush(M *mp, bool sysalloc)
// (Manually inlined copy of runtime_MHeap_Lookup)
p = (uintptr)v>>PageShift;
if(sizeof(void*) == 8)
- p -= (uintptr)runtime_mheap->arena_start >> PageShift;
- s = runtime_mheap->map[p];
+ p -= (uintptr)runtime_mheap.arena_start >> PageShift;
+ s = runtime_mheap.spans[p];
if(s->sizeclass == 0) {
s->types.compression = MTypes_Single;
@@ -558,20 +654,9 @@ runtime_settype_flush(M *mp, bool sysalloc)
case MTypes_Empty:
ntypes = (s->npages << PageShift) / size;
nbytes3 = 8*sizeof(uintptr) + 1*ntypes;
-
- if(!sysalloc) {
- data3 = runtime_mallocgc(nbytes3, FlagNoProfiling|FlagNoPointers, 0, 1);
- } else {
- data3 = runtime_SysAlloc(nbytes3);
- if(data3 == nil)
- runtime_throw("runtime: cannot allocate memory");
- if(0) runtime_printf("settype(0->3): SysAlloc(%x) --> %p\n", (uint32)nbytes3, data3);
- }
-
+ data3 = runtime_mallocgc(nbytes3, 0, FlagNoProfiling|FlagNoScan|FlagNoInvokeGC);
s->types.compression = MTypes_Bytes;
- s->types.sysalloc = sysalloc;
s->types.data = (uintptr)data3;
-
((uintptr*)data3)[1] = typ;
data3[8*sizeof(uintptr) + ofs] = 1;
break;
@@ -596,20 +681,8 @@ runtime_settype_flush(M *mp, bool sysalloc)
} else {
ntypes = (s->npages << PageShift) / size;
nbytes2 = ntypes * sizeof(uintptr);
-
- if(!sysalloc) {
- data2 = runtime_mallocgc(nbytes2, FlagNoProfiling|FlagNoPointers, 0, 1);
- } else {
- data2 = runtime_SysAlloc(nbytes2);
- if(data2 == nil)
- runtime_throw("runtime: cannot allocate memory");
- if(0) runtime_printf("settype.(3->2): SysAlloc(%x) --> %p\n", (uint32)nbytes2, data2);
- }
-
- sysalloc3 = s->types.sysalloc;
-
+ data2 = runtime_mallocgc(nbytes2, 0, FlagNoProfiling|FlagNoScan|FlagNoInvokeGC);
s->types.compression = MTypes_Words;
- s->types.sysalloc = sysalloc;
s->types.data = (uintptr)data2;
// Move the contents of data3 to data2. Then deallocate data3.
@@ -618,12 +691,6 @@ runtime_settype_flush(M *mp, bool sysalloc)
t = ((uintptr*)data3)[t];
data2[j] = t;
}
- if(sysalloc3) {
- nbytes3 = 8*sizeof(uintptr) + 1*ntypes;
- if(0) runtime_printf("settype.(3->2): SysFree(%p,%x)\n", data3, (uint32)nbytes3);
- runtime_SysFree(data3, nbytes3);
- }
-
data2[ofs] = typ;
}
break;
@@ -634,64 +701,6 @@ runtime_settype_flush(M *mp, bool sysalloc)
mp->settype_bufsize = 0;
}
-// It is forbidden to use this function if it is possible that
-// explicit deallocation via calling runtime_free(v) may happen.
-void
-runtime_settype(void *v, uintptr t)
-{
- M *mp;
- uintptr *buf;
- uintptr i;
- MSpan *s;
-
- if(t == 0)
- runtime_throw("settype: zero type");
-
- mp = runtime_m();
- buf = mp->settype_buf;
- i = mp->settype_bufsize;
- buf[i+0] = (uintptr)v;
- buf[i+1] = t;
- i += 2;
- mp->settype_bufsize = i;
-
- if(i == nelem(mp->settype_buf)) {
- runtime_settype_flush(mp, false);
- }
-
- if(DebugTypeAtBlockEnd) {
- s = runtime_MHeap_Lookup(runtime_mheap, v);
- *(uintptr*)((uintptr)v+s->elemsize-sizeof(uintptr)) = t;
- }
-}
-
-void
-runtime_settype_sysfree(MSpan *s)
-{
- uintptr ntypes, nbytes;
-
- if(!s->types.sysalloc)
- return;
-
- nbytes = (uintptr)-1;
-
- switch (s->types.compression) {
- case MTypes_Words:
- ntypes = (s->npages << PageShift) / s->elemsize;
- nbytes = ntypes * sizeof(uintptr);
- break;
- case MTypes_Bytes:
- ntypes = (s->npages << PageShift) / s->elemsize;
- nbytes = 8*sizeof(uintptr) + 1*ntypes;
- break;
- }
-
- if(nbytes != (uintptr)-1) {
- if(0) runtime_printf("settype: SysFree(%p,%x)\n", (void*)s->types.data, (uint32)nbytes);
- runtime_SysFree((void*)s->types.data, nbytes);
- }
-}
-
uintptr
runtime_gettype(void *v)
{
@@ -699,7 +708,7 @@ runtime_gettype(void *v)
uintptr t, ofs;
byte *data;
- s = runtime_MHeap_LookupMaybe(runtime_mheap, v);
+ s = runtime_MHeap_LookupMaybe(&runtime_mheap, v);
if(s != nil) {
t = 0;
switch(s->types.compression) {
@@ -736,61 +745,23 @@ runtime_gettype(void *v)
void*
runtime_mal(uintptr n)
{
- return runtime_mallocgc(n, 0, 1, 1);
+ return runtime_mallocgc(n, 0, 0);
}
void *
runtime_new(const Type *typ)
{
- void *ret;
- uint32 flag;
-
- if(raceenabled)
- runtime_m()->racepc = runtime_getcallerpc(&typ);
-
- if(typ->__size == 0) {
- // All 0-length allocations use this pointer.
- // The language does not require the allocations to
- // have distinct values.
- ret = (uint8*)&runtime_zerobase;
- } else {
- flag = typ->__code&GO_NO_POINTERS ? FlagNoPointers : 0;
- ret = runtime_mallocgc(typ->__size, flag, 1, 1);
-
- if(UseSpanType && !flag) {
- if(false)
- runtime_printf("new %S: %p\n", *typ->__reflection, ret);
- runtime_settype(ret, (uintptr)typ | TypeInfo_SingleObject);
- }
- }
-
- return ret;
+ return runtime_mallocgc(typ->__size, (uintptr)typ | TypeInfo_SingleObject, typ->kind&KindNoPointers ? FlagNoScan : 0);
}
static void*
cnew(const Type *typ, intgo n, int32 objtyp)
{
- uint32 flag;
- void *ret;
-
if((objtyp&(PtrSize-1)) != objtyp)
runtime_throw("runtime: invalid objtyp");
if(n < 0 || (typ->__size > 0 && (uintptr)n > (MaxMem/typ->__size)))
runtime_panicstring("runtime: allocation size out of range");
- if(typ->__size == 0 || n == 0) {
- // All 0-length allocations use this pointer.
- // The language does not require the allocations to
- // have distinct values.
- return &runtime_zerobase;
- }
- flag = typ->__code&GO_NO_POINTERS ? FlagNoPointers : 0;
- ret = runtime_mallocgc(typ->__size*n, flag, 1, 1);
- if(UseSpanType && !flag) {
- if(false)
- runtime_printf("cnew [%D]%S: %p\n", (int64)n, *typ->__reflection, ret);
- runtime_settype(ret, (uintptr)typ | TypeInfo_SingleObject);
- }
- return ret;
+ return runtime_mallocgc(typ->__size*n, (uintptr)typ | objtyp, typ->kind&KindNoPointers ? FlagNoScan : 0);
}
// same as runtime_new, but callable from C
@@ -814,6 +785,8 @@ func SetFinalizer(obj Eface, finalizer Eface) {
byte *base;
uintptr size;
const FuncType *ft;
+ const Type *fint;
+ const PtrType *ot;
if(obj.__type_descriptor == nil) {
runtime_printf("runtime.SetFinalizer: first argument is nil interface\n");
@@ -828,22 +801,36 @@ func SetFinalizer(obj Eface, finalizer Eface) {
goto throw;
}
ft = nil;
+ ot = (const PtrType*)obj.__type_descriptor;
+ fint = nil;
if(finalizer.__type_descriptor != nil) {
if(finalizer.__type_descriptor->__code != GO_FUNC)
goto badfunc;
ft = (const FuncType*)finalizer.__type_descriptor;
- if(ft->__dotdotdot || ft->__in.__count != 1 || !__go_type_descriptors_equal(*(Type**)ft->__in.__values, obj.__type_descriptor))
+ if(ft->__dotdotdot || ft->__in.__count != 1)
+ goto badfunc;
+ fint = *(Type**)ft->__in.__values;
+ if(__go_type_descriptors_equal(fint, obj.__type_descriptor)) {
+ // ok - same type
+ } else if(fint->__code == GO_PTR && (fint->__uncommon == nil || fint->__uncommon->__name == nil || obj.type->__uncommon == nil || obj.type->__uncommon->__name == nil) && __go_type_descriptors_equal(((const PtrType*)fint)->__element_type, ((const PtrType*)obj.type)->__element_type)) {
+ // ok - not same type, but both pointers,
+ // one or the other is unnamed, and same element type, so assignable.
+ } else if(fint->kind == GO_INTERFACE && ((const InterfaceType*)fint)->__methods.__count == 0) {
+ // ok - satisfies empty interface
+ } else if(fint->kind == GO_INTERFACE && __go_convert_interface_2(fint, obj.__type_descriptor, 1) != nil) {
+ // ok - satisfies non-empty interface
+ } else
goto badfunc;
}
- if(!runtime_addfinalizer(obj.__object, finalizer.__type_descriptor != nil ? *(void**)finalizer.__object : nil, ft)) {
+ if(!runtime_addfinalizer(obj.__object, finalizer.__type_descriptor != nil ? *(void**)finalizer.__object : nil, ft, ot)) {
runtime_printf("runtime.SetFinalizer: finalizer already set\n");
goto throw;
}
return;
badfunc:
- runtime_printf("runtime.SetFinalizer: second argument is %S, not func(%S)\n", *finalizer.__type_descriptor->__reflection, *obj.__type_descriptor->__reflection);
+ runtime_printf("runtime.SetFinalizer: cannot pass %S to finalizer %S\n", *obj.__type_descriptor->__reflection, *finalizer.__type_descriptor->__reflection);
throw:
runtime_throw("runtime.SetFinalizer");
}
diff --git a/libgo/runtime/malloc.h b/libgo/runtime/malloc.h
index ebea34eb32c..45c4c09c147 100644
--- a/libgo/runtime/malloc.h
+++ b/libgo/runtime/malloc.h
@@ -108,9 +108,7 @@ enum
// Tunable constants.
MaxSmallSize = 32<<10,
- FixAllocChunk = 128<<10, // Chunk size for FixAlloc
- MaxMCacheListLen = 256, // Maximum objects on MCacheList
- MaxMCacheSize = 2<<20, // Maximum bytes in one MCache
+ FixAllocChunk = 16<<10, // Chunk size for FixAlloc
MaxMHeapList = 1<<(20 - PageShift), // Maximum page length for fixed-size list in MHeap.
HeapAllocChunk = 1<<20, // Chunk size for heap growth
@@ -155,13 +153,13 @@ struct MLink
// SysAlloc obtains a large chunk of zeroed memory from the
// operating system, typically on the order of a hundred kilobytes
-// or a megabyte. If the pointer argument is non-nil, the caller
-// wants a mapping there or nowhere.
+// or a megabyte.
//
// SysUnused notifies the operating system that the contents
// of the memory region are no longer needed and can be reused
-// for other purposes. The program reserves the right to start
-// accessing those pages in the future.
+// for other purposes.
+// SysUsed notifies the operating system that the contents
+// of the memory region are needed again.
//
// SysFree returns it unconditionally; this is only used if
// an out-of-memory error has been detected midway through
@@ -174,10 +172,11 @@ struct MLink
//
// SysMap maps previously reserved address space for use.
-void* runtime_SysAlloc(uintptr nbytes);
-void runtime_SysFree(void *v, uintptr nbytes);
+void* runtime_SysAlloc(uintptr nbytes, uint64 *stat);
+void runtime_SysFree(void *v, uintptr nbytes, uint64 *stat);
void runtime_SysUnused(void *v, uintptr nbytes);
-void runtime_SysMap(void *v, uintptr nbytes);
+void runtime_SysUsed(void *v, uintptr nbytes);
+void runtime_SysMap(void *v, uintptr nbytes, uint64 *stat);
void* runtime_SysReserve(void *v, uintptr nbytes);
// FixAlloc is a simple free-list allocator for fixed size objects.
@@ -190,18 +189,17 @@ void* runtime_SysReserve(void *v, uintptr nbytes);
// smashed by freeing and reallocating.
struct FixAlloc
{
- uintptr size;
- void *(*alloc)(uintptr);
- void (*first)(void *arg, byte *p); // called first time p is returned
- void *arg;
- MLink *list;
- byte *chunk;
- uint32 nchunk;
- uintptr inuse; // in-use bytes now
- uintptr sys; // bytes obtained from system
+ uintptr size;
+ void (*first)(void *arg, byte *p); // called first time p is returned
+ void* arg;
+ MLink* list;
+ byte* chunk;
+ uint32 nchunk;
+ uintptr inuse; // in-use bytes now
+ uint64* stat;
};
-void runtime_FixAlloc_Init(FixAlloc *f, uintptr size, void *(*alloc)(uintptr), void (*first)(void*, byte*), void *arg);
+void runtime_FixAlloc_Init(FixAlloc *f, uintptr size, void (*first)(void*, byte*), void *arg, uint64 *stat);
void* runtime_FixAlloc_Alloc(FixAlloc *f);
void runtime_FixAlloc_Free(FixAlloc *f, void *p);
@@ -236,6 +234,8 @@ struct MStats
uint64 mcache_inuse; // MCache structures
uint64 mcache_sys;
uint64 buckhash_sys; // profiling bucket hash table
+ uint64 gc_sys;
+ uint64 other_sys;
// Statistics about garbage collector.
// Protected by mheap or stopping the world during GC.
@@ -267,14 +267,12 @@ extern MStats mstats
// class_to_size[i] = largest size in class i
// class_to_allocnpages[i] = number of pages to allocate when
// making new objects in class i
-// class_to_transfercount[i] = number of objects to move when
-// taking a bunch of objects out of the central lists
-// and putting them in the thread free list.
int32 runtime_SizeToClass(int32);
extern int32 runtime_class_to_size[NumSizeClasses];
extern int32 runtime_class_to_allocnpages[NumSizeClasses];
-extern int32 runtime_class_to_transfercount[NumSizeClasses];
+extern int8 runtime_size_to_class8[1024/8 + 1];
+extern int8 runtime_size_to_class128[(MaxSmallSize-1024)/128 + 1];
extern void runtime_InitSizes(void);
@@ -285,30 +283,24 @@ struct MCacheList
{
MLink *list;
uint32 nlist;
- uint32 nlistmin;
};
struct MCache
{
- MCacheList list[NumSizeClasses];
- uintptr size;
+ // The following members are accessed on every malloc,
+ // so they are grouped here for better caching.
+ int32 next_sample; // trigger heap sample after allocating this many bytes
intptr local_cachealloc; // bytes allocated (or freed) from cache since last lock of heap
- intptr local_objects; // objects allocated (or freed) from cache since last lock of heap
- intptr local_alloc; // bytes allocated (or freed) since last lock of heap
- uintptr local_total_alloc; // bytes allocated (even if freed) since last lock of heap
- uintptr local_nmalloc; // number of mallocs since last lock of heap
- uintptr local_nfree; // number of frees since last lock of heap
- uintptr local_nlookup; // number of pointer lookups since last lock of heap
- int32 next_sample; // trigger heap sample after allocating this many bytes
- // Statistics about allocation size classes since last lock of heap
- struct {
- uintptr nmalloc;
- uintptr nfree;
- } local_by_size[NumSizeClasses];
-
+ // The rest is not accessed on every malloc.
+ MCacheList list[NumSizeClasses];
+ // Local allocator stats, flushed during GC.
+ uintptr local_nlookup; // number of pointer lookups
+ uintptr local_largefree; // bytes freed for large objects (>MaxSmallSize)
+ uintptr local_nlargefree; // number of frees for large objects (>MaxSmallSize)
+ uintptr local_nsmallfree[NumSizeClasses]; // number of frees for small objects (<=MaxSmallSize)
};
-void* runtime_MCache_Alloc(MCache *c, int32 sizeclass, uintptr size, int32 zeroed);
+void runtime_MCache_Refill(MCache *c, int32 sizeclass);
void runtime_MCache_Free(MCache *c, void *p, int32 sizeclass, uintptr size);
void runtime_MCache_ReleaseAll(MCache *c);
@@ -346,7 +338,6 @@ enum
struct MTypes
{
byte compression; // one of MTypes_*
- bool sysalloc; // whether (void*)data is from runtime_SysAlloc
uintptr data;
};
@@ -397,8 +388,8 @@ struct MCentral
};
void runtime_MCentral_Init(MCentral *c, int32 sizeclass);
-int32 runtime_MCentral_AllocList(MCentral *c, int32 n, MLink **first);
-void runtime_MCentral_FreeList(MCentral *c, int32 n, MLink *first);
+int32 runtime_MCentral_AllocList(MCentral *c, MLink **first);
+void runtime_MCentral_FreeList(MCentral *c, MLink *first);
void runtime_MCentral_FreeSpan(MCentral *c, MSpan *s, int32 n, MLink *start, MLink *end);
// Main malloc heap.
@@ -414,7 +405,8 @@ struct MHeap
uint32 nspancap;
// span lookup
- MSpan *map[1<<MHeapMap_Bits];
+ MSpan** spans;
+ uintptr spans_mapped;
// range of addresses we might see in the heap
byte *bitmap;
@@ -434,10 +426,15 @@ struct MHeap
FixAlloc spanalloc; // allocator for Span*
FixAlloc cachealloc; // allocator for MCache*
+
+ // Malloc stats.
+ uint64 largefree; // bytes freed for large objects (>MaxSmallSize)
+ uint64 nlargefree; // number of frees for large objects (>MaxSmallSize)
+ uint64 nsmallfree[NumSizeClasses]; // number of frees for small objects (<=MaxSmallSize)
};
-extern MHeap *runtime_mheap;
+extern MHeap runtime_mheap;
-void runtime_MHeap_Init(MHeap *h, void *(*allocator)(uintptr));
+void runtime_MHeap_Init(MHeap *h);
MSpan* runtime_MHeap_Alloc(MHeap *h, uintptr npage, int32 sizeclass, int32 acct, int32 zeroed);
void runtime_MHeap_Free(MHeap *h, MSpan *s, int32 acct);
MSpan* runtime_MHeap_Lookup(MHeap *h, void *v);
@@ -445,9 +442,11 @@ MSpan* runtime_MHeap_LookupMaybe(MHeap *h, void *v);
void runtime_MGetSizeClassInfo(int32 sizeclass, uintptr *size, int32 *npages, int32 *nobj);
void* runtime_MHeap_SysAlloc(MHeap *h, uintptr n);
void runtime_MHeap_MapBits(MHeap *h);
+void runtime_MHeap_MapSpans(MHeap *h);
void runtime_MHeap_Scavenger(void*);
-void* runtime_mallocgc(uintptr size, uint32 flag, int32 dogc, int32 zeroed);
+void* runtime_mallocgc(uintptr size, uintptr typ, uint32 flag);
+void* runtime_persistentalloc(uintptr size, uintptr align, uint64 *stat);
int32 runtime_mlookup(void *v, byte **base, uintptr *size, MSpan **s);
void runtime_gc(int32 force);
void runtime_markallocated(void *v, uintptr n, bool noptr);
@@ -463,17 +462,18 @@ void runtime_purgecachedstats(MCache*);
void* runtime_cnew(const Type*);
void* runtime_cnewarray(const Type*, intgo);
-void runtime_settype(void*, uintptr);
-void runtime_settype_flush(M*, bool);
+void runtime_settype_flush(M*);
void runtime_settype_sysfree(MSpan*);
uintptr runtime_gettype(void*);
enum
{
// flags to malloc
- FlagNoPointers = 1<<0, // no pointers here
- FlagNoProfiling = 1<<1, // must not profile
- FlagNoGC = 1<<2, // must not free or scan for pointers
+ FlagNoScan = 1<<0, // GC doesn't have to scan object
+ FlagNoProfiling = 1<<1, // must not profile
+ FlagNoGC = 1<<2, // must not free or scan for pointers
+ FlagNoZero = 1<<3, // don't zero memory
+ FlagNoInvokeGC = 1<<4, // don't invoke GC
};
typedef struct Obj Obj;
@@ -493,15 +493,15 @@ void runtime_helpgc(int32 nproc);
void runtime_gchelper(void);
struct __go_func_type;
-bool runtime_getfinalizer(void *p, bool del, FuncVal **fn, const struct __go_func_type **ft);
+struct __go_ptr_type;
+bool runtime_getfinalizer(void *p, bool del, FuncVal **fn, const struct __go_func_type **ft, const struct __go_ptr_type **ot);
void runtime_walkfintab(void (*fn)(void*), void (*scan)(Obj));
enum
{
TypeInfo_SingleObject = 0,
TypeInfo_Array = 1,
- TypeInfo_Map = 2,
- TypeInfo_Chan = 3,
+ TypeInfo_Chan = 2,
// Enables type information at the end of blocks allocated from heap
DebugTypeAtBlockEnd = 0,
diff --git a/libgo/runtime/mcache.c b/libgo/runtime/mcache.c
index 45bac4ffbce..38f824a139b 100644
--- a/libgo/runtime/mcache.c
+++ b/libgo/runtime/mcache.c
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Per-thread (in Go, per-M) malloc cache for small objects.
+// Per-P malloc cache for small objects.
//
// See malloc.h for an overview.
@@ -10,48 +10,23 @@
#include "arch.h"
#include "malloc.h"
-void*
-runtime_MCache_Alloc(MCache *c, int32 sizeclass, uintptr size, int32 zeroed)
+void
+runtime_MCache_Refill(MCache *c, int32 sizeclass)
{
MCacheList *l;
- MLink *first, *v;
- int32 n;
- // Allocate from list.
+ // Replenish using central lists.
l = &c->list[sizeclass];
- if(l->list == nil) {
- // Replenish using central lists.
- n = runtime_MCentral_AllocList(&runtime_mheap->central[sizeclass],
- runtime_class_to_transfercount[sizeclass], &first);
- if(n == 0)
- runtime_throw("out of memory");
- l->list = first;
- l->nlist = n;
- c->size += n*size;
- }
- v = l->list;
- l->list = v->next;
- l->nlist--;
- if(l->nlist < l->nlistmin)
- l->nlistmin = l->nlist;
- c->size -= size;
-
- // v is zeroed except for the link pointer
- // that we used above; zero that.
- v->next = nil;
- if(zeroed) {
- // block is zeroed iff second word is zero ...
- if(size > sizeof(uintptr) && ((uintptr*)v)[1] != 0)
- runtime_memclr((byte*)v, size);
- }
- c->local_cachealloc += size;
- c->local_objects++;
- return v;
+ if(l->list)
+ runtime_throw("MCache_Refill: the list is not empty");
+ l->nlist = runtime_MCentral_AllocList(&runtime_mheap.central[sizeclass], &l->list);
+ if(l->list == nil)
+ runtime_throw("out of memory");
}
// Take n elements off l and return them to the central free list.
static void
-ReleaseN(MCache *c, MCacheList *l, int32 n, int32 sizeclass)
+ReleaseN(MCacheList *l, int32 n, int32 sizeclass)
{
MLink *first, **lp;
int32 i;
@@ -64,18 +39,14 @@ ReleaseN(MCache *c, MCacheList *l, int32 n, int32 sizeclass)
l->list = *lp;
*lp = nil;
l->nlist -= n;
- if(l->nlist < l->nlistmin)
- l->nlistmin = l->nlist;
- c->size -= n*runtime_class_to_size[sizeclass];
// Return them to central free list.
- runtime_MCentral_FreeList(&runtime_mheap->central[sizeclass], n, first);
+ runtime_MCentral_FreeList(&runtime_mheap.central[sizeclass], first);
}
void
runtime_MCache_Free(MCache *c, void *v, int32 sizeclass, uintptr size)
{
- int32 i, n;
MCacheList *l;
MLink *p;
@@ -85,34 +56,12 @@ runtime_MCache_Free(MCache *c, void *v, int32 sizeclass, uintptr size)
p->next = l->list;
l->list = p;
l->nlist++;
- c->size += size;
c->local_cachealloc -= size;
- c->local_objects--;
-
- if(l->nlist >= MaxMCacheListLen) {
- // Release a chunk back.
- ReleaseN(c, l, runtime_class_to_transfercount[sizeclass], sizeclass);
- }
-
- if(c->size >= MaxMCacheSize) {
- // Scavenge.
- for(i=0; i<NumSizeClasses; i++) {
- l = &c->list[i];
- n = l->nlistmin;
- // n is the minimum number of elements we've seen on
- // the list since the last scavenge. If n > 0, it means that
- // we could have gotten by with n fewer elements
- // without needing to consult the central free list.
- // Move toward that situation by releasing n/2 of them.
- if(n > 0) {
- if(n > 1)
- n /= 2;
- ReleaseN(c, l, n, i);
- }
- l->nlistmin = l->nlist;
- }
- }
+ // We transfer span at a time from MCentral to MCache,
+ // if we have 2 times more than that, release a half back.
+ if(l->nlist >= 2*(runtime_class_to_allocnpages[sizeclass]<<PageShift)/size)
+ ReleaseN(l, l->nlist/2, sizeclass);
}
void
@@ -123,7 +72,10 @@ runtime_MCache_ReleaseAll(MCache *c)
for(i=0; i<NumSizeClasses; i++) {
l = &c->list[i];
- ReleaseN(c, l, l->nlist, i);
- l->nlistmin = 0;
+ if(l->list) {
+ runtime_MCentral_FreeList(&runtime_mheap.central[i], l->list);
+ l->list = nil;
+ l->nlist = 0;
+ }
}
}
diff --git a/libgo/runtime/mcentral.c b/libgo/runtime/mcentral.c
index b3108a1c061..81916101e46 100644
--- a/libgo/runtime/mcentral.c
+++ b/libgo/runtime/mcentral.c
@@ -30,16 +30,15 @@ runtime_MCentral_Init(MCentral *c, int32 sizeclass)
runtime_MSpanList_Init(&c->empty);
}
-// Allocate up to n objects from the central free list.
+// Allocate a list of objects from the central free list.
// Return the number of objects allocated.
// The objects are linked together by their first words.
-// On return, *pstart points at the first object.
+// On return, *pfirst points at the first object.
int32
-runtime_MCentral_AllocList(MCentral *c, int32 n, MLink **pfirst)
+runtime_MCentral_AllocList(MCentral *c, MLink **pfirst)
{
MSpan *s;
- MLink *first, *last;
- int32 cap, avail, i;
+ int32 cap, n;
runtime_lock(c);
// Replenish central list if empty.
@@ -52,49 +51,27 @@ runtime_MCentral_AllocList(MCentral *c, int32 n, MLink **pfirst)
}
s = c->nonempty.next;
cap = (s->npages << PageShift) / s->elemsize;
- avail = cap - s->ref;
- if(avail < n)
- n = avail;
-
- // First one is guaranteed to work, because we just grew the list.
- first = s->freelist;
- last = first;
- for(i=1; i<n; i++) {
- last = last->next;
- }
- s->freelist = last->next;
- last->next = nil;
+ n = cap - s->ref;
+ *pfirst = s->freelist;
+ s->freelist = nil;
s->ref += n;
c->nfree -= n;
-
- if(n == avail) {
- if(s->freelist != nil || s->ref != (uint32)cap) {
- runtime_throw("invalid freelist");
- }
- runtime_MSpanList_Remove(s);
- runtime_MSpanList_Insert(&c->empty, s);
- }
-
+ runtime_MSpanList_Remove(s);
+ runtime_MSpanList_Insert(&c->empty, s);
runtime_unlock(c);
- *pfirst = first;
return n;
}
-// Free n objects back into the central free list.
+// Free the list of objects back into the central free list.
void
-runtime_MCentral_FreeList(MCentral *c, int32 n, MLink *start)
+runtime_MCentral_FreeList(MCentral *c, MLink *start)
{
- MLink *v, *next;
-
- // Assume next == nil marks end of list.
- // n and end would be useful if we implemented
- // the transfer cache optimization in the TODO above.
- USED(n);
+ MLink *next;
runtime_lock(c);
- for(v=start; v; v=next) {
- next = v->next;
- MCentral_Free(c, v);
+ for(; start != nil; start = next) {
+ next = start->next;
+ MCentral_Free(c, start);
}
runtime_unlock(c);
}
@@ -108,7 +85,7 @@ MCentral_Free(MCentral *c, void *v)
int32 size;
// Find span for v.
- s = runtime_MHeap_Lookup(runtime_mheap, v);
+ s = runtime_MHeap_Lookup(&runtime_mheap, v);
if(s == nil || s->ref == 0)
runtime_throw("invalid free");
@@ -133,7 +110,7 @@ MCentral_Free(MCentral *c, void *v)
s->freelist = nil;
c->nfree -= (s->npages << PageShift) / size;
runtime_unlock(c);
- runtime_MHeap_Free(runtime_mheap, s, 0);
+ runtime_MHeap_Free(&runtime_mheap, s, 0);
runtime_lock(c);
}
}
@@ -168,7 +145,7 @@ runtime_MCentral_FreeSpan(MCentral *c, MSpan *s, int32 n, MLink *start, MLink *e
c->nfree -= (s->npages << PageShift) / size;
runtime_unlock(c);
runtime_unmarkspan((byte*)(s->start<<PageShift), s->npages<<PageShift);
- runtime_MHeap_Free(runtime_mheap, s, 0);
+ runtime_MHeap_Free(&runtime_mheap, s, 0);
} else {
runtime_unlock(c);
}
@@ -200,7 +177,7 @@ MCentral_Grow(MCentral *c)
runtime_unlock(c);
runtime_MGetSizeClassInfo(c->sizeclass, &size, &npages, &n);
- s = runtime_MHeap_Alloc(runtime_mheap, npages, c->sizeclass, 0, 1);
+ s = runtime_MHeap_Alloc(&runtime_mheap, npages, c->sizeclass, 0, 1);
if(s == nil) {
// TODO(rsc): Log out of memory
runtime_lock(c);
diff --git a/libgo/runtime/mem.c b/libgo/runtime/mem.c
index 8481e950750..78f7c51faf2 100644
--- a/libgo/runtime/mem.c
+++ b/libgo/runtime/mem.c
@@ -60,13 +60,11 @@ mmap_fixed(byte *v, uintptr n, int32 prot, int32 flags, int32 fd, uint32 offset)
}
void*
-runtime_SysAlloc(uintptr n)
+runtime_SysAlloc(uintptr n, uint64 *stat)
{
void *p;
int fd = -1;
- mstats.sys += n;
-
#ifdef USE_DEV_ZERO
if (dev_zero == -1) {
dev_zero = open("/dev/zero", O_RDONLY);
@@ -91,6 +89,7 @@ runtime_SysAlloc(uintptr n)
}
return nil;
}
+ runtime_xadd64(stat, n);
return p;
}
@@ -103,9 +102,16 @@ runtime_SysUnused(void *v __attribute__ ((unused)), uintptr n __attribute__ ((un
}
void
-runtime_SysFree(void *v, uintptr n)
+runtime_SysUsed(void *v, uintptr n)
+{
+ USED(v);
+ USED(n);
+}
+
+void
+runtime_SysFree(void *v, uintptr n, uint64 *stat)
{
- mstats.sys -= n;
+ runtime_xadd64(stat, -(uint64)n);
runtime_munmap(v, n);
}
@@ -132,8 +138,10 @@ runtime_SysReserve(void *v, uintptr n)
// Only user-mode Linux (UML) rejects these requests.
if(sizeof(void*) == 8 && (uintptr)v >= 0xffffffffU) {
p = mmap_fixed(v, 64<<10, PROT_NONE, MAP_ANON|MAP_PRIVATE, fd, 0);
- if (p != v)
+ if (p != v) {
+ runtime_munmap(p, 64<<10);
return nil;
+ }
runtime_munmap(p, 64<<10);
return v;
}
@@ -149,12 +157,12 @@ runtime_SysReserve(void *v, uintptr n)
}
void
-runtime_SysMap(void *v, uintptr n)
+runtime_SysMap(void *v, uintptr n, uint64 *stat)
{
void *p;
int fd = -1;
- mstats.sys += n;
+ runtime_xadd64(stat, n);
#ifdef USE_DEV_ZERO
if (dev_zero == -1) {
diff --git a/libgo/runtime/mfinal.c b/libgo/runtime/mfinal.c
index 407092bf392..625af528e1e 100644
--- a/libgo/runtime/mfinal.c
+++ b/libgo/runtime/mfinal.c
@@ -5,6 +5,7 @@
#include "runtime.h"
#include "arch.h"
#include "malloc.h"
+#include "go-type.h"
enum { debug = 0 };
@@ -13,6 +14,7 @@ struct Fin
{
FuncVal *fn;
const struct __go_func_type *ft;
+ const struct __go_ptr_type *ot;
};
// Finalizer hash table. Direct hash, linear scan, at most 3/4 full.
@@ -42,7 +44,7 @@ static struct {
} fintab[TABSZ];
static void
-addfintab(Fintab *t, void *k, FuncVal *fn, const struct __go_func_type *ft)
+addfintab(Fintab *t, void *k, FuncVal *fn, const struct __go_func_type *ft, const struct __go_ptr_type *ot)
{
int32 i, j;
@@ -67,6 +69,7 @@ ret:
t->fkey[i] = k;
t->val[i].fn = fn;
t->val[i].ft = ft;
+ t->val[i].ot = ot;
}
static bool
@@ -87,6 +90,7 @@ lookfintab(Fintab *t, void *k, bool del, Fin *f)
t->fkey[i] = (void*)-1;
t->val[i].fn = nil;
t->val[i].ft = nil;
+ t->val[i].ot = nil;
t->ndead++;
}
return true;
@@ -117,13 +121,13 @@ resizefintab(Fintab *tab)
newtab.max *= 3;
}
- newtab.fkey = runtime_mallocgc(newtab.max*sizeof newtab.fkey[0], FlagNoPointers, 0, 1);
- newtab.val = runtime_mallocgc(newtab.max*sizeof newtab.val[0], 0, 0, 1);
+ newtab.fkey = runtime_mallocgc(newtab.max*sizeof newtab.fkey[0], 0, FlagNoInvokeGC|FlagNoScan);
+ newtab.val = runtime_mallocgc(newtab.max*sizeof newtab.val[0], 0, FlagNoInvokeGC);
for(i=0; i<tab->max; i++) {
k = tab->fkey[i];
if(k != nil && k != (void*)-1)
- addfintab(&newtab, k, tab->val[i].fn, tab->val[i].ft);
+ addfintab(&newtab, k, tab->val[i].fn, tab->val[i].ft, tab->val[i].ot);
}
runtime_free(tab->fkey);
@@ -137,7 +141,7 @@ resizefintab(Fintab *tab)
}
bool
-runtime_addfinalizer(void *p, FuncVal *f, const struct __go_func_type *ft)
+runtime_addfinalizer(void *p, FuncVal *f, const struct __go_func_type *ft, const struct __go_ptr_type *ot)
{
Fintab *tab;
byte *base;
@@ -166,7 +170,7 @@ runtime_addfinalizer(void *p, FuncVal *f, const struct __go_func_type *ft)
resizefintab(tab);
}
- addfintab(tab, p, f, ft);
+ addfintab(tab, p, f, ft, ot);
runtime_setblockspecial(p, true);
runtime_unlock(tab);
return true;
@@ -175,7 +179,7 @@ runtime_addfinalizer(void *p, FuncVal *f, const struct __go_func_type *ft)
// get finalizer; if del, delete finalizer.
// caller is responsible for updating RefHasFinalizer (special) bit.
bool
-runtime_getfinalizer(void *p, bool del, FuncVal **fn, const struct __go_func_type **ft)
+runtime_getfinalizer(void *p, bool del, FuncVal **fn, const struct __go_func_type **ft, const struct __go_ptr_type **ot)
{
Fintab *tab;
bool res;
@@ -189,6 +193,7 @@ runtime_getfinalizer(void *p, bool del, FuncVal **fn, const struct __go_func_typ
return false;
*fn = f.fn;
*ft = f.ft;
+ *ot = f.ot;
return true;
}
diff --git a/libgo/runtime/mfixalloc.c b/libgo/runtime/mfixalloc.c
index 6e4f0c6e607..9d0b3bbda7e 100644
--- a/libgo/runtime/mfixalloc.c
+++ b/libgo/runtime/mfixalloc.c
@@ -13,17 +13,16 @@
// Initialize f to allocate objects of the given size,
// using the allocator to obtain chunks of memory.
void
-runtime_FixAlloc_Init(FixAlloc *f, uintptr size, void *(*alloc)(uintptr), void (*first)(void*, byte*), void *arg)
+runtime_FixAlloc_Init(FixAlloc *f, uintptr size, void (*first)(void*, byte*), void *arg, uint64 *stat)
{
f->size = size;
- f->alloc = alloc;
f->first = first;
f->arg = arg;
f->list = nil;
f->chunk = nil;
f->nchunk = 0;
f->inuse = 0;
- f->sys = 0;
+ f->stat = stat;
}
void*
@@ -43,10 +42,7 @@ runtime_FixAlloc_Alloc(FixAlloc *f)
return v;
}
if(f->nchunk < f->size) {
- f->sys += FixAllocChunk;
- f->chunk = f->alloc(FixAllocChunk);
- if(f->chunk == nil)
- runtime_throw("out of memory (FixAlloc)");
+ f->chunk = runtime_persistentalloc(FixAllocChunk, 0, f->stat);
f->nchunk = FixAllocChunk;
}
v = f->chunk;
diff --git a/libgo/runtime/mgc0.c b/libgo/runtime/mgc0.c
index c3b32111ca0..3edcee9c397 100644
--- a/libgo/runtime/mgc0.c
+++ b/libgo/runtime/mgc0.c
@@ -59,6 +59,13 @@ enum {
PRECISE = 1,
LOOP = 2,
PC_BITS = PRECISE | LOOP,
+
+ // Pointer map
+ BitsPerPointer = 2,
+ BitsNoPointer = 0,
+ BitsPointer = 1,
+ BitsIface = 2,
+ BitsEface = 3,
};
// Bits in per-word bitmap.
@@ -70,7 +77,7 @@ enum {
// The bits in the word are packed together by type first, then by
// heap location, so each 64-bit bitmap word consists of, from top to bottom,
// the 16 bitSpecial bits for the corresponding heap words, then the 16 bitMarked bits,
-// then the 16 bitNoPointers/bitBlockBoundary bits, then the 16 bitAllocated bits.
+// then the 16 bitNoScan/bitBlockBoundary bits, then the 16 bitAllocated bits.
// This layout makes it easier to iterate over the bits of a given type.
//
// The bitmap starts at mheap.arena_start and extends *backward* from
@@ -87,7 +94,7 @@ enum {
// /* then test bits & bitAllocated, bits & bitMarked, etc. */
//
#define bitAllocated ((uintptr)1<<(bitShift*0))
-#define bitNoPointers ((uintptr)1<<(bitShift*1)) /* when bitAllocated is set */
+#define bitNoScan ((uintptr)1<<(bitShift*1)) /* when bitAllocated is set */
#define bitMarked ((uintptr)1<<(bitShift*2)) /* when bitAllocated is set */
#define bitSpecial ((uintptr)1<<(bitShift*3)) /* when bitAllocated is set - has finalizer or being profiled */
#define bitBlockBoundary ((uintptr)1<<(bitShift*1)) /* when bitAllocated is NOT set */
@@ -109,8 +116,6 @@ enum {
//
uint32 runtime_worldsema = 1;
-static int32 gctrace;
-
// The size of Workbuf is N*PageSize.
typedef struct Workbuf Workbuf;
struct Workbuf
@@ -129,6 +134,7 @@ struct Finalizer
FuncVal *fn;
void *arg;
const struct __go_func_type *ft;
+ const struct __go_ptr_type *ot;
};
typedef struct FinBlock FinBlock;
@@ -178,7 +184,6 @@ static struct {
enum {
GC_DEFAULT_PTR = GC_NUM_INSTR,
- GC_MAP_NEXT,
GC_CHAN,
GC_NUM_INSTR2
@@ -201,6 +206,16 @@ static struct {
uint64 instr[GC_NUM_INSTR2];
uint64 putempty;
uint64 getfull;
+ struct {
+ uint64 foundbit;
+ uint64 foundword;
+ uint64 foundspan;
+ } flushptrbuf;
+ struct {
+ uint64 foundbit;
+ uint64 foundword;
+ uint64 foundspan;
+ } markonly;
} gcstats;
// markonly marks an object. It returns true if the object
@@ -210,12 +225,12 @@ static bool
markonly(void *obj)
{
byte *p;
- uintptr *bitp, bits, shift, x, xbits, off;
+ uintptr *bitp, bits, shift, x, xbits, off, j;
MSpan *s;
PageID k;
// Words outside the arena cannot be pointers.
- if((byte*)obj < runtime_mheap->arena_start || (byte*)obj >= runtime_mheap->arena_used)
+ if((byte*)obj < runtime_mheap.arena_start || (byte*)obj >= runtime_mheap.arena_used)
return false;
// obj may be a pointer to a live object.
@@ -225,42 +240,57 @@ markonly(void *obj)
obj = (void*)((uintptr)obj & ~((uintptr)PtrSize-1));
// Find bits for this word.
- off = (uintptr*)obj - (uintptr*)runtime_mheap->arena_start;
- bitp = (uintptr*)runtime_mheap->arena_start - off/wordsPerBitmapWord - 1;
+ off = (uintptr*)obj - (uintptr*)runtime_mheap.arena_start;
+ bitp = (uintptr*)runtime_mheap.arena_start - off/wordsPerBitmapWord - 1;
shift = off % wordsPerBitmapWord;
xbits = *bitp;
bits = xbits >> shift;
// Pointing at the beginning of a block?
- if((bits & (bitAllocated|bitBlockBoundary)) != 0)
+ if((bits & (bitAllocated|bitBlockBoundary)) != 0) {
+ if(CollectStats)
+ runtime_xadd64(&gcstats.markonly.foundbit, 1);
goto found;
+ }
+
+ // Pointing just past the beginning?
+ // Scan backward a little to find a block boundary.
+ for(j=shift; j-->0; ) {
+ if(((xbits>>j) & (bitAllocated|bitBlockBoundary)) != 0) {
+ shift = j;
+ bits = xbits>>shift;
+ if(CollectStats)
+ runtime_xadd64(&gcstats.markonly.foundword, 1);
+ goto found;
+ }
+ }
// Otherwise consult span table to find beginning.
// (Manually inlined copy of MHeap_LookupMaybe.)
k = (uintptr)obj>>PageShift;
x = k;
if(sizeof(void*) == 8)
- x -= (uintptr)runtime_mheap->arena_start>>PageShift;
- s = runtime_mheap->map[x];
- if(s == nil || k < s->start || k - s->start >= s->npages || s->state != MSpanInUse)
+ x -= (uintptr)runtime_mheap.arena_start>>PageShift;
+ s = runtime_mheap.spans[x];
+ if(s == nil || k < s->start || (byte*)obj >= s->limit || s->state != MSpanInUse)
return false;
p = (byte*)((uintptr)s->start<<PageShift);
if(s->sizeclass == 0) {
obj = p;
} else {
- if((byte*)obj >= (byte*)s->limit)
- return false;
uintptr size = s->elemsize;
int32 i = ((byte*)obj - p)/size;
obj = p+i*size;
}
// Now that we know the object header, reload bits.
- off = (uintptr*)obj - (uintptr*)runtime_mheap->arena_start;
- bitp = (uintptr*)runtime_mheap->arena_start - off/wordsPerBitmapWord - 1;
+ off = (uintptr*)obj - (uintptr*)runtime_mheap.arena_start;
+ bitp = (uintptr*)runtime_mheap.arena_start - off/wordsPerBitmapWord - 1;
shift = off % wordsPerBitmapWord;
xbits = *bitp;
bits = xbits >> shift;
+ if(CollectStats)
+ runtime_xadd64(&gcstats.markonly.foundspan, 1);
found:
// Now we have bits, bitp, and shift correct for
@@ -338,7 +368,7 @@ flushptrbuf(PtrTarget *ptrbuf, PtrTarget **ptrbufpos, Obj **_wp, Workbuf **_wbuf
Workbuf *wbuf;
PtrTarget *ptrbuf_end;
- arena_start = runtime_mheap->arena_start;
+ arena_start = runtime_mheap.arena_start;
wp = *_wp;
wbuf = *_wbuf;
@@ -377,7 +407,7 @@ flushptrbuf(PtrTarget *ptrbuf, PtrTarget **ptrbufpos, Obj **_wp, Workbuf **_wbuf
// obj belongs to interval [mheap.arena_start, mheap.arena_used).
if(Debug > 1) {
- if(obj < runtime_mheap->arena_start || obj >= runtime_mheap->arena_used)
+ if(obj < runtime_mheap.arena_start || obj >= runtime_mheap.arena_used)
runtime_throw("object is outside of mheap");
}
@@ -398,8 +428,11 @@ flushptrbuf(PtrTarget *ptrbuf, PtrTarget **ptrbufpos, Obj **_wp, Workbuf **_wbuf
bits = xbits >> shift;
// Pointing at the beginning of a block?
- if((bits & (bitAllocated|bitBlockBoundary)) != 0)
+ if((bits & (bitAllocated|bitBlockBoundary)) != 0) {
+ if(CollectStats)
+ runtime_xadd64(&gcstats.flushptrbuf.foundbit, 1);
goto found;
+ }
ti = 0;
@@ -410,6 +443,8 @@ flushptrbuf(PtrTarget *ptrbuf, PtrTarget **ptrbufpos, Obj **_wp, Workbuf **_wbuf
obj = (byte*)obj - (shift-j)*PtrSize;
shift = j;
bits = xbits>>shift;
+ if(CollectStats)
+ runtime_xadd64(&gcstats.flushptrbuf.foundword, 1);
goto found;
}
}
@@ -420,15 +455,13 @@ flushptrbuf(PtrTarget *ptrbuf, PtrTarget **ptrbufpos, Obj **_wp, Workbuf **_wbuf
x = k;
if(sizeof(void*) == 8)
x -= (uintptr)arena_start>>PageShift;
- s = runtime_mheap->map[x];
- if(s == nil || k < s->start || k - s->start >= s->npages || s->state != MSpanInUse)
+ s = runtime_mheap.spans[x];
+ if(s == nil || k < s->start || obj >= s->limit || s->state != MSpanInUse)
continue;
p = (byte*)((uintptr)s->start<<PageShift);
if(s->sizeclass == 0) {
obj = p;
} else {
- if((byte*)obj >= (byte*)s->limit)
- continue;
size = s->elemsize;
int32 i = ((byte*)obj - p)/size;
obj = p+i*size;
@@ -440,6 +473,8 @@ flushptrbuf(PtrTarget *ptrbuf, PtrTarget **ptrbufpos, Obj **_wp, Workbuf **_wbuf
shift = off % wordsPerBitmapWord;
xbits = *bitp;
bits = xbits >> shift;
+ if(CollectStats)
+ runtime_xadd64(&gcstats.flushptrbuf.foundspan, 1);
found:
// Now we have bits, bitp, and shift correct for
@@ -460,7 +495,7 @@ flushptrbuf(PtrTarget *ptrbuf, PtrTarget **ptrbufpos, Obj **_wp, Workbuf **_wbuf
}
// If object has no pointers, don't need to scan further.
- if((bits & bitNoPointers) != 0)
+ if((bits & bitNoScan) != 0)
continue;
// Ask span about size class.
@@ -468,7 +503,7 @@ flushptrbuf(PtrTarget *ptrbuf, PtrTarget **ptrbufpos, Obj **_wp, Workbuf **_wbuf
x = (uintptr)obj >> PageShift;
if(sizeof(void*) == 8)
x -= (uintptr)arena_start>>PageShift;
- s = runtime_mheap->map[x];
+ s = runtime_mheap.spans[x];
PREFETCH(obj);
@@ -552,9 +587,6 @@ flushobjbuf(Obj *objbuf, Obj **objbufpos, Obj **_wp, Workbuf **_wbuf, uintptr *_
static uintptr defaultProg[2] = {PtrSize, GC_DEFAULT_PTR};
#if 0
-// Hashmap iterator program
-static uintptr mapProg[2] = {0, GC_MAP_NEXT};
-
// Hchan program
static uintptr chanProg[2] = {0, GC_CHAN};
#endif
@@ -578,7 +610,7 @@ checkptr(void *obj, uintptr objti)
if(!Debug)
runtime_throw("checkptr is debug only");
- if((byte*)obj < runtime_mheap->arena_start || (byte*)obj >= runtime_mheap->arena_used)
+ if((byte*)obj < runtime_mheap.arena_start || (byte*)obj >= runtime_mheap.arena_used)
return;
type = runtime_gettype(obj);
t = (Type*)(type & ~(uintptr)(PtrSize-1));
@@ -586,8 +618,8 @@ checkptr(void *obj, uintptr objti)
return;
x = (uintptr)obj >> PageShift;
if(sizeof(void*) == 8)
- x -= (uintptr)(runtime_mheap->arena_start)>>PageShift;
- s = runtime_mheap->map[x];
+ x -= (uintptr)(runtime_mheap.arena_start)>>PageShift;
+ s = runtime_mheap.spans[x];
objstart = (byte*)((uintptr)s->start<<PageShift);
if(s->sizeclass != 0) {
i = ((byte*)obj - objstart)/s->elemsize;
@@ -595,8 +627,11 @@ checkptr(void *obj, uintptr objti)
}
tisize = *(uintptr*)objti;
// Sanity check for object size: it should fit into the memory block.
- if((byte*)obj + tisize > objstart + s->elemsize)
+ if((byte*)obj + tisize > objstart + s->elemsize) {
+ runtime_printf("object of type '%S' at %p/%p does not fit in block %p/%p\n",
+ *t->string, obj, tisize, objstart, s->elemsize);
runtime_throw("invalid gc type info");
+ }
if(obj != objstart)
return;
// If obj points to the beginning of the memory block,
@@ -613,7 +648,7 @@ checkptr(void *obj, uintptr objti)
for(j = 1; pc1[j] != GC_END && pc2[j] != GC_END; j++) {
if(pc1[j] != pc2[j]) {
runtime_printf("invalid gc type info for '%s' at %p, type info %p, block info %p\n",
- t->string ? (const int8*)t->string->str : (const int8*)"?", j, pc1[j], pc2[j]);
+ t->string ? (const int8*)t->string->str : (const int8*)"?", j, pc1[j], pc2[j]);
runtime_throw("invalid gc type info");
}
}
@@ -638,7 +673,7 @@ scanblock(Workbuf *wbuf, Obj *wp, uintptr nobj, bool keepworking)
uintptr n, i, end_b, elemsize, size, ti, objti, count /* , type */;
uintptr *pc, precise_type, nominal_size;
#if 0
- uintptr *map_ret, mapkey_size, mapval_size, mapkey_ti, mapval_ti, *chan_ret, chancap;
+ uintptr *chan_ret, chancap;
#endif
void *obj;
const Type *t;
@@ -650,11 +685,6 @@ scanblock(Workbuf *wbuf, Obj *wp, uintptr nobj, bool keepworking)
Eface *eface;
Iface *iface;
#if 0
- Hmap *hmap;
- MapType *maptype;
- bool mapkey_kind, mapval_kind;
- struct hash_gciter map_iter;
- struct hash_gciter_data d;
Hchan *chan;
ChanType *chantype;
#endif
@@ -663,8 +693,8 @@ scanblock(Workbuf *wbuf, Obj *wp, uintptr nobj, bool keepworking)
runtime_throw("scanblock: size of Workbuf is suboptimal");
// Memory arena parameters.
- arena_start = runtime_mheap->arena_start;
- arena_used = runtime_mheap->arena_used;
+ arena_start = runtime_mheap.arena_start;
+ arena_used = runtime_mheap.arena_used;
stack_ptr = stack+nelem(stack)-1;
@@ -685,10 +715,6 @@ scanblock(Workbuf *wbuf, Obj *wp, uintptr nobj, bool keepworking)
// (Silence the compiler)
#if 0
- map_ret = nil;
- mapkey_size = mapval_size = 0;
- mapkey_kind = mapval_kind = false;
- mapkey_ti = mapval_ti = 0;
chan = nil;
chantype = nil;
chan_ret = nil;
@@ -759,23 +785,6 @@ scanblock(Workbuf *wbuf, Obj *wp, uintptr nobj, bool keepworking)
stack_top.elemsize = pc[0];
stack_top.loop_or_ret = pc+1;
break;
- case TypeInfo_Map:
- hmap = (Hmap*)b;
- maptype = (MapType*)t;
- if(hash_gciter_init(hmap, &map_iter)) {
- mapkey_size = maptype->key->size;
- mapkey_kind = maptype->key->kind;
- mapkey_ti = (uintptr)maptype->key->gc | PRECISE;
- mapval_size = maptype->elem->size;
- mapval_kind = maptype->elem->kind;
- mapval_ti = (uintptr)maptype->elem->gc | PRECISE;
-
- map_ret = nil;
- pc = mapProg;
- } else {
- goto next_block;
- }
- break;
case TypeInfo_Chan:
chan = (Hchan*)b;
chantype = (ChanType*)t;
@@ -985,79 +994,6 @@ scanblock(Workbuf *wbuf, Obj *wp, uintptr nobj, bool keepworking)
pc = (uintptr*)((byte*)pc + *(int32*)(pc+2)); // target of the CALL instruction
continue;
-#if 0
- case GC_MAP_PTR:
- hmap = *(Hmap**)(stack_top.b + pc[1]);
- if(hmap == nil) {
- pc += 3;
- continue;
- }
- if(markonly(hmap)) {
- maptype = (MapType*)pc[2];
- if(hash_gciter_init(hmap, &map_iter)) {
- mapkey_size = maptype->key->size;
- mapkey_kind = maptype->key->kind;
- mapkey_ti = (uintptr)maptype->key->gc | PRECISE;
- mapval_size = maptype->elem->size;
- mapval_kind = maptype->elem->kind;
- mapval_ti = (uintptr)maptype->elem->gc | PRECISE;
-
- // Start mapProg.
- map_ret = pc+3;
- pc = mapProg+1;
- } else {
- pc += 3;
- }
- } else {
- pc += 3;
- }
- continue;
-
- case GC_MAP_NEXT:
- // Add all keys and values to buffers, mark all subtables.
- while(hash_gciter_next(&map_iter, &d)) {
- // buffers: reserve space for 2 objects.
- if(ptrbufpos+2 >= ptrbuf_end)
- flushptrbuf(ptrbuf, &ptrbufpos, &wp, &wbuf, &nobj);
- if(objbufpos+2 >= objbuf_end)
- flushobjbuf(objbuf, &objbufpos, &wp, &wbuf, &nobj);
-
- if(d.st != nil)
- markonly(d.st);
-
- if(d.key_data != nil) {
- if(!(mapkey_kind & KindNoPointers) || d.indirectkey) {
- if(!d.indirectkey)
- *objbufpos++ = (Obj){d.key_data, mapkey_size, mapkey_ti};
- else {
- if(Debug) {
- obj = *(void**)d.key_data;
- if(!(arena_start <= obj && obj < arena_used))
- runtime_throw("scanblock: inconsistent hashmap");
- }
- *ptrbufpos++ = (struct PtrTarget){*(void**)d.key_data, mapkey_ti};
- }
- }
- if(!(mapval_kind & KindNoPointers) || d.indirectval) {
- if(!d.indirectval)
- *objbufpos++ = (Obj){d.val_data, mapval_size, mapval_ti};
- else {
- if(Debug) {
- obj = *(void**)d.val_data;
- if(!(arena_start <= obj && obj < arena_used))
- runtime_throw("scanblock: inconsistent hashmap");
- }
- *ptrbufpos++ = (struct PtrTarget){*(void**)d.val_data, mapval_ti};
- }
- }
- }
- }
- if(map_ret == nil)
- goto next_block;
- pc = map_ret;
- continue;
-#endif
-
case GC_REGION:
obj = (void*)(stack_top.b + pc[1]);
size = pc[2];
@@ -1071,7 +1007,6 @@ scanblock(Workbuf *wbuf, Obj *wp, uintptr nobj, bool keepworking)
#if 0
case GC_CHAN_PTR:
- // Similar to GC_MAP_PTR
chan = *(Hchan**)(stack_top.b + pc[1]);
if(chan == nil) {
pc += 3;
@@ -1191,14 +1126,14 @@ debug_scanblock(byte *b, uintptr n)
obj = (byte*)vp[i];
// Words outside the arena cannot be pointers.
- if((byte*)obj < runtime_mheap->arena_start || (byte*)obj >= runtime_mheap->arena_used)
+ if((byte*)obj < runtime_mheap.arena_start || (byte*)obj >= runtime_mheap.arena_used)
continue;
// Round down to word boundary.
obj = (void*)((uintptr)obj & ~((uintptr)PtrSize-1));
// Consult span table to find beginning.
- s = runtime_MHeap_LookupMaybe(runtime_mheap, obj);
+ s = runtime_MHeap_LookupMaybe(&runtime_mheap, obj);
if(s == nil)
continue;
@@ -1207,15 +1142,13 @@ debug_scanblock(byte *b, uintptr n)
if(s->sizeclass == 0) {
obj = p;
} else {
- if((byte*)obj >= (byte*)s->limit)
- continue;
int32 i = ((byte*)obj - p)/size;
obj = p+i*size;
}
// Now that we know the object header, reload bits.
- off = (uintptr*)obj - (uintptr*)runtime_mheap->arena_start;
- bitp = (uintptr*)runtime_mheap->arena_start - off/wordsPerBitmapWord - 1;
+ off = (uintptr*)obj - (uintptr*)runtime_mheap.arena_start;
+ bitp = (uintptr*)runtime_mheap.arena_start - off/wordsPerBitmapWord - 1;
shift = off % wordsPerBitmapWord;
xbits = *bitp;
bits = xbits >> shift;
@@ -1230,7 +1163,7 @@ debug_scanblock(byte *b, uintptr n)
runtime_printf("found unmarked block %p in %p\n", obj, vp+i);
// If object has no pointers, don't need to scan further.
- if((bits & bitNoPointers) != 0)
+ if((bits & bitNoScan) != 0)
continue;
debug_scanblock(obj, size);
@@ -1320,7 +1253,7 @@ getempty(Workbuf *b)
runtime_lock(&work);
if(work.nchunk < sizeof *b) {
work.nchunk = 1<<20;
- work.chunk = runtime_SysAlloc(work.nchunk);
+ work.chunk = runtime_SysAlloc(work.nchunk, &mstats.gc_sys);
if(work.chunk == nil)
runtime_throw("runtime: cannot allocate memory");
}
@@ -1416,12 +1349,12 @@ addroot(Obj obj)
cap = PageSize/sizeof(Obj);
if(cap < 2*work.rootcap)
cap = 2*work.rootcap;
- new = (Obj*)runtime_SysAlloc(cap*sizeof(Obj));
+ new = (Obj*)runtime_SysAlloc(cap*sizeof(Obj), &mstats.gc_sys);
if(new == nil)
runtime_throw("runtime: cannot allocate memory");
if(work.roots != nil) {
runtime_memmove(new, work.roots, work.rootcap*sizeof(Obj));
- runtime_SysFree(work.roots, work.rootcap*sizeof(Obj));
+ runtime_SysFree(work.roots, work.rootcap*sizeof(Obj), &mstats.gc_sys);
}
work.roots = new;
work.rootcap = cap;
@@ -1560,8 +1493,8 @@ addroots(void)
runtime_time_scan(addroot);
// MSpan.types
- allspans = runtime_mheap->allspans;
- for(spanidx=0; spanidx<runtime_mheap->nspan; spanidx++) {
+ allspans = runtime_mheap.allspans;
+ for(spanidx=0; spanidx<runtime_mheap.nspan; spanidx++) {
s = allspans[spanidx];
if(s->state == MSpanInUse) {
// The garbage collector ignores type pointers stored in MSpan.types:
@@ -1589,10 +1522,7 @@ addroots(void)
case Gdead:
break;
case Grunning:
- if(gp != runtime_g())
- runtime_throw("mark - world not stopped");
- addstackroots(gp);
- break;
+ runtime_throw("mark - world not stopped");
case Grunnable:
case Gsyscall:
case Gwaiting:
@@ -1614,10 +1544,11 @@ handlespecial(byte *p, uintptr size)
{
FuncVal *fn;
const struct __go_func_type *ft;
+ const struct __go_ptr_type *ot;
FinBlock *block;
Finalizer *f;
- if(!runtime_getfinalizer(p, true, &fn, &ft)) {
+ if(!runtime_getfinalizer(p, true, &fn, &ft, &ot)) {
runtime_setblockspecial(p, false);
runtime_MProf_Free(p, size);
return false;
@@ -1626,9 +1557,7 @@ handlespecial(byte *p, uintptr size)
runtime_lock(&finlock);
if(finq == nil || finq->cnt == finq->cap) {
if(finc == nil) {
- finc = runtime_SysAlloc(PageSize);
- if(finc == nil)
- runtime_throw("runtime: cannot allocate memory");
+ finc = runtime_persistentalloc(PageSize, 0, &mstats.gc_sys);
finc->cap = (PageSize - sizeof(FinBlock)) / sizeof(Finalizer) + 1;
finc->alllink = allfin;
allfin = finc;
@@ -1642,6 +1571,7 @@ handlespecial(byte *p, uintptr size)
finq->cnt++;
f->fn = fn;
f->ft = ft;
+ f->ot = ot;
f->arg = p;
runtime_unlock(&finlock);
return true;
@@ -1668,10 +1598,10 @@ sweepspan(ParFor *desc, uint32 idx)
m = runtime_m();
USED(&desc);
- s = runtime_mheap->allspans[idx];
+ s = runtime_mheap.allspans[idx];
if(s->state != MSpanInUse)
return;
- arena_start = runtime_mheap->arena_start;
+ arena_start = runtime_mheap.arena_start;
p = (byte*)(s->start << PageShift);
cl = s->sizeclass;
size = s->elemsize;
@@ -1735,9 +1665,9 @@ sweepspan(ParFor *desc, uint32 idx)
// Free large span.
runtime_unmarkspan(p, 1<<PageShift);
*(uintptr*)p = (uintptr)0xdeaddeaddeaddeadll; // needs zeroing
- runtime_MHeap_Free(runtime_mheap, s, 1);
- c->local_alloc -= size;
- c->local_nfree++;
+ runtime_MHeap_Free(&runtime_mheap, s, 1);
+ c->local_nlargefree++;
+ c->local_largefree += size;
} else {
// Free small object.
switch(compression) {
@@ -1758,12 +1688,9 @@ sweepspan(ParFor *desc, uint32 idx)
}
if(nfree) {
- c->local_by_size[cl].nfree += nfree;
- c->local_alloc -= size * nfree;
- c->local_nfree += nfree;
+ c->local_nsmallfree[cl] += nfree;
c->local_cachealloc -= nfree * size;
- c->local_objects -= nfree;
- runtime_MCentral_FreeSpan(&runtime_mheap->central[cl], s, nfree, head.next, end);
+ runtime_MCentral_FreeSpan(&runtime_mheap.central[cl], s, nfree, head.next, end);
}
}
@@ -1777,10 +1704,10 @@ dumpspan(uint32 idx)
MSpan *s;
bool allocated, special;
- s = runtime_mheap->allspans[idx];
+ s = runtime_mheap.allspans[idx];
if(s->state != MSpanInUse)
return;
- arena_start = runtime_mheap->arena_start;
+ arena_start = runtime_mheap.arena_start;
p = (byte*)(s->start << PageShift);
sizeclass = s->sizeclass;
size = s->elemsize;
@@ -1838,7 +1765,7 @@ runtime_memorydump(void)
{
uint32 spanidx;
- for(spanidx=0; spanidx<runtime_mheap->nspan; spanidx++) {
+ for(spanidx=0; spanidx<runtime_mheap.nspan; spanidx++) {
dumpspan(spanidx);
}
}
@@ -1880,13 +1807,28 @@ runtime_gchelper(void)
static int32 gcpercent = GcpercentUnknown;
static void
-cachestats(GCStats *stats)
+cachestats(void)
+{
+ MCache *c;
+ P *p, **pp;
+
+ for(pp=runtime_allp; (p=*pp) != nil; pp++) {
+ c = p->mcache;
+ if(c==nil)
+ continue;
+ runtime_purgecachedstats(c);
+ }
+}
+
+static void
+updatememstats(GCStats *stats)
{
M *mp;
+ MSpan *s;
MCache *c;
P *p, **pp;
uint32 i;
- uint64 stacks_inuse;
+ uint64 stacks_inuse, smallfree;
uint64 *src, *dst;
if(stats)
@@ -1902,29 +1844,80 @@ cachestats(GCStats *stats)
runtime_memclr((byte*)&mp->gcstats, sizeof(mp->gcstats));
}
}
+ mstats.stacks_inuse = stacks_inuse;
+ mstats.mcache_inuse = runtime_mheap.cachealloc.inuse;
+ mstats.mspan_inuse = runtime_mheap.spanalloc.inuse;
+ mstats.sys = mstats.heap_sys + mstats.stacks_sys + mstats.mspan_sys +
+ mstats.mcache_sys + mstats.buckhash_sys + mstats.gc_sys + mstats.other_sys;
+
+ // Calculate memory allocator stats.
+ // During program execution we only count number of frees and amount of freed memory.
+ // Current number of alive object in the heap and amount of alive heap memory
+ // are calculated by scanning all spans.
+ // Total number of mallocs is calculated as number of frees plus number of alive objects.
+ // Similarly, total amount of allocated memory is calculated as amount of freed memory
+ // plus amount of alive heap memory.
+ mstats.alloc = 0;
+ mstats.total_alloc = 0;
+ mstats.nmalloc = 0;
+ mstats.nfree = 0;
+ for(i = 0; i < nelem(mstats.by_size); i++) {
+ mstats.by_size[i].nmalloc = 0;
+ mstats.by_size[i].nfree = 0;
+ }
+
+ // Flush MCache's to MCentral.
for(pp=runtime_allp; (p=*pp) != nil; pp++) {
c = p->mcache;
if(c==nil)
continue;
- runtime_purgecachedstats(c);
- for(i=0; i<nelem(c->local_by_size); i++) {
- mstats.by_size[i].nmalloc += c->local_by_size[i].nmalloc;
- c->local_by_size[i].nmalloc = 0;
- mstats.by_size[i].nfree += c->local_by_size[i].nfree;
- c->local_by_size[i].nfree = 0;
+ runtime_MCache_ReleaseAll(c);
+ }
+
+ // Aggregate local stats.
+ cachestats();
+
+ // Scan all spans and count number of alive objects.
+ for(i = 0; i < runtime_mheap.nspan; i++) {
+ s = runtime_mheap.allspans[i];
+ if(s->state != MSpanInUse)
+ continue;
+ if(s->sizeclass == 0) {
+ mstats.nmalloc++;
+ mstats.alloc += s->elemsize;
+ } else {
+ mstats.nmalloc += s->ref;
+ mstats.by_size[s->sizeclass].nmalloc += s->ref;
+ mstats.alloc += s->ref*s->elemsize;
}
}
- mstats.stacks_inuse = stacks_inuse;
+
+ // Aggregate by size class.
+ smallfree = 0;
+ mstats.nfree = runtime_mheap.nlargefree;
+ for(i = 0; i < nelem(mstats.by_size); i++) {
+ mstats.nfree += runtime_mheap.nsmallfree[i];
+ mstats.by_size[i].nfree = runtime_mheap.nsmallfree[i];
+ mstats.by_size[i].nmalloc += runtime_mheap.nsmallfree[i];
+ smallfree += runtime_mheap.nsmallfree[i] * runtime_class_to_size[i];
+ }
+ mstats.nmalloc += mstats.nfree;
+
+ // Calculate derived stats.
+ mstats.total_alloc = mstats.alloc + runtime_mheap.largefree + smallfree;
+ mstats.heap_alloc = mstats.alloc;
+ mstats.heap_objects = mstats.nmalloc - mstats.nfree;
}
// Structure of arguments passed to function gc().
-// This allows the arguments to be passed via reflect_call.
+// This allows the arguments to be passed via runtime_mcall.
struct gc_args
{
- int32 force;
+ int64 start_time; // start time of GC in ns (just before stoptheworld)
};
static void gc(struct gc_args *args);
+static void mgc(G *gp);
static int32
readgogc(void)
@@ -1943,8 +1936,9 @@ void
runtime_gc(int32 force)
{
M *m;
- const byte *p;
- struct gc_args a, *ap;
+ G *g;
+ struct gc_args a;
+ int32 i;
// The atomic operations are not atomic if the uint64s
// are not aligned on uint64 boundaries. This has been
@@ -1967,30 +1961,77 @@ runtime_gc(int32 force)
// while holding a lock. The next mallocgc
// without a lock will do the gc instead.
m = runtime_m();
- if(!mstats.enablegc || m->locks > 0 || runtime_panicking)
+ if(!mstats.enablegc || runtime_g() == m->g0 || m->locks > 0 || runtime_panicking)
return;
if(gcpercent == GcpercentUnknown) { // first time through
- gcpercent = readgogc();
-
- p = runtime_getenv("GOGCTRACE");
- if(p != nil)
- gctrace = runtime_atoi(p);
+ runtime_lock(&runtime_mheap);
+ if(gcpercent == GcpercentUnknown)
+ gcpercent = readgogc();
+ runtime_unlock(&runtime_mheap);
}
if(gcpercent < 0)
return;
- // Run gc on a bigger stack to eliminate
- // a potentially large number of calls to runtime_morestack.
- // But not when using gccgo.
- a.force = force;
- ap = &a;
- gc(ap);
+ runtime_semacquire(&runtime_worldsema, false);
+ if(!force && mstats.heap_alloc < mstats.next_gc) {
+ // typically threads which lost the race to grab
+ // worldsema exit here when gc is done.
+ runtime_semrelease(&runtime_worldsema);
+ return;
+ }
- if(gctrace > 1 && !force) {
- a.force = 1;
- gc(&a);
+ // Ok, we're doing it! Stop everybody else
+ a.start_time = runtime_nanotime();
+ m->gcing = 1;
+ runtime_stoptheworld();
+
+ // Run gc on the g0 stack. We do this so that the g stack
+ // we're currently running on will no longer change. Cuts
+ // the root set down a bit (g0 stacks are not scanned, and
+ // we don't need to scan gc's internal state). Also an
+ // enabler for copyable stacks.
+ for(i = 0; i < (runtime_debug.gctrace > 1 ? 2 : 1); i++) {
+ // switch to g0, call gc(&a), then switch back
+ g = runtime_g();
+ g->param = &a;
+ g->status = Gwaiting;
+ g->waitreason = "garbage collection";
+ runtime_mcall(mgc);
+ // record a new start time in case we're going around again
+ a.start_time = runtime_nanotime();
}
+
+ // all done
+ m->gcing = 0;
+ m->locks++;
+ runtime_semrelease(&runtime_worldsema);
+ runtime_starttheworld();
+ m->locks--;
+
+ // now that gc is done, kick off finalizer thread if needed
+ if(finq != nil) {
+ runtime_lock(&finlock);
+ // kick off or wake up goroutine to run queued finalizers
+ if(fing == nil)
+ fing = __go_go(runfinq, nil);
+ else if(fingwait) {
+ fingwait = 0;
+ runtime_ready(fing);
+ }
+ runtime_unlock(&finlock);
+ }
+ // give the queued finalizers, if any, a chance to run
+ runtime_gosched();
+}
+
+static void
+mgc(G *gp)
+{
+ gc(gp->param);
+ gp->param = nil;
+ gp->status = Grunning;
+ runtime_gogo(gp);
}
static void
@@ -2004,29 +2045,20 @@ gc(struct gc_args *args)
uint32 i;
// Eface eface;
- runtime_semacquire(&runtime_worldsema);
- if(!args->force && mstats.heap_alloc < mstats.next_gc) {
- runtime_semrelease(&runtime_worldsema);
- return;
- }
-
m = runtime_m();
- t0 = runtime_nanotime();
-
- m->gcing = 1;
- runtime_stoptheworld();
+ t0 = args->start_time;
if(CollectStats)
runtime_memclr((byte*)&gcstats, sizeof(gcstats));
for(mp=runtime_allm; mp; mp=mp->alllink)
- runtime_settype_flush(mp, false);
+ runtime_settype_flush(mp);
heap0 = 0;
obj0 = 0;
- if(gctrace) {
- cachestats(nil);
+ if(runtime_debug.gctrace) {
+ updatememstats(nil);
heap0 = mstats.heap_alloc;
obj0 = mstats.nmalloc - mstats.nfree;
}
@@ -2050,7 +2082,7 @@ gc(struct gc_args *args)
work.nproc = runtime_gcprocs();
addroots();
runtime_parforsetup(work.markfor, work.nproc, work.nroot, nil, false, markroot);
- runtime_parforsetup(work.sweepfor, work.nproc, runtime_mheap->nspan, nil, true, sweepspan);
+ runtime_parforsetup(work.sweepfor, work.nproc, runtime_mheap.nspan, nil, true, sweepspan);
if(work.nproc > 1) {
runtime_noteclear(&work.alldone);
runtime_helpgc(work.nproc);
@@ -2076,29 +2108,8 @@ gc(struct gc_args *args)
if(work.nproc > 1)
runtime_notesleep(&work.alldone);
- cachestats(&stats);
-
- stats.nprocyield += work.sweepfor->nprocyield;
- stats.nosyield += work.sweepfor->nosyield;
- stats.nsleep += work.sweepfor->nsleep;
-
- mstats.next_gc = mstats.heap_alloc+(mstats.heap_alloc-runtime_stacks_sys)*gcpercent/100;
- m->gcing = 0;
-
- if(finq != nil) {
- m->locks++; // disable gc during the mallocs in newproc
- // kick off or wake up goroutine to run queued finalizers
- if(fing == nil)
- fing = __go_go(runfinq, nil);
- else if(fingwait) {
- fingwait = 0;
- runtime_ready(fing);
- }
- m->locks--;
- }
-
- heap1 = mstats.heap_alloc;
- obj1 = mstats.nmalloc - mstats.nfree;
+ cachestats();
+ mstats.next_gc = mstats.heap_alloc+mstats.heap_alloc*gcpercent/100;
t4 = runtime_nanotime();
mstats.last_gc = t4;
@@ -2108,7 +2119,15 @@ gc(struct gc_args *args)
if(mstats.debuggc)
runtime_printf("pause %D\n", t4-t0);
- if(gctrace) {
+ if(runtime_debug.gctrace) {
+ updatememstats(&stats);
+ heap1 = mstats.heap_alloc;
+ obj1 = mstats.nmalloc - mstats.nfree;
+
+ stats.nprocyield += work.sweepfor->nprocyield;
+ stats.nosyield += work.sweepfor->nosyield;
+ stats.nsleep += work.sweepfor->nsleep;
+
runtime_printf("gc%d(%d): %D+%D+%D ms, %D -> %D MB %D -> %D (%D-%D) objects,"
" %D(%D) handoff, %D(%D) steal, %D/%D/%D yields\n",
mstats.numgc, work.nproc, (t2-t1)/1000000, (t3-t2)/1000000, (t1-t0+t4-t3)/1000000,
@@ -2137,16 +2156,13 @@ gc(struct gc_args *args)
runtime_printf("\ttotal:\t%D\n", ninstr);
runtime_printf("putempty: %D, getfull: %D\n", gcstats.putempty, gcstats.getfull);
+
+ runtime_printf("markonly base lookup: bit %D word %D span %D\n", gcstats.markonly.foundbit, gcstats.markonly.foundword, gcstats.markonly.foundspan);
+ runtime_printf("flushptrbuf base lookup: bit %D word %D span %D\n", gcstats.flushptrbuf.foundbit, gcstats.flushptrbuf.foundword, gcstats.flushptrbuf.foundspan);
}
}
runtime_MProf_GC();
- runtime_semrelease(&runtime_worldsema);
- runtime_starttheworld();
-
- // give the queued finalizers, if any, a chance to run
- if(finq != nil)
- runtime_gosched();
}
void runtime_ReadMemStats(MStats *)
@@ -2161,15 +2177,17 @@ runtime_ReadMemStats(MStats *stats)
// because stoptheworld can only be used by
// one goroutine at a time, and there might be
// a pending garbage collection already calling it.
- runtime_semacquire(&runtime_worldsema);
+ runtime_semacquire(&runtime_worldsema, false);
m = runtime_m();
m->gcing = 1;
runtime_stoptheworld();
- cachestats(nil);
+ updatememstats(nil);
*stats = mstats;
m->gcing = 0;
+ m->locks++;
runtime_semrelease(&runtime_worldsema);
runtime_starttheworld();
+ m->locks--;
}
void runtime_debug_readGCStats(Slice*)
@@ -2187,7 +2205,7 @@ runtime_debug_readGCStats(Slice *pauses)
// Pass back: pauses, last gc (absolute time), number of gc, total pause ns.
p = (uint64*)pauses->array;
- runtime_lock(runtime_mheap);
+ runtime_lock(&runtime_mheap);
n = mstats.numgc;
if(n > nelem(mstats.pause_ns))
n = nelem(mstats.pause_ns);
@@ -2202,7 +2220,7 @@ runtime_debug_readGCStats(Slice *pauses)
p[n] = mstats.last_gc;
p[n+1] = mstats.numgc;
p[n+2] = mstats.pause_total_ns;
- runtime_unlock(runtime_mheap);
+ runtime_unlock(&runtime_mheap);
pauses->__count = n+3;
}
@@ -2214,14 +2232,14 @@ runtime_debug_setGCPercent(intgo in)
{
intgo out;
- runtime_lock(runtime_mheap);
+ runtime_lock(&runtime_mheap);
if(gcpercent == GcpercentUnknown)
gcpercent = readgogc();
out = gcpercent;
if(in < 0)
in = -1;
gcpercent = in;
- runtime_unlock(runtime_mheap);
+ runtime_unlock(&runtime_mheap);
return out;
}
@@ -2235,6 +2253,8 @@ gchelperstart(void)
runtime_throw("gchelperstart: bad m->helpgc");
if(runtime_xchg(&bufferList[m->helpgc].busy, 1))
runtime_throw("gchelperstart: already busy");
+ if(runtime_g() != m->g0)
+ runtime_throw("gchelper not running on g0 stack");
}
static void
@@ -2243,33 +2263,51 @@ runfinq(void* dummy __attribute__ ((unused)))
Finalizer *f;
FinBlock *fb, *next;
uint32 i;
+ Eface ef;
+ Iface iface;
for(;;) {
- // There's no need for a lock in this section
- // because it only conflicts with the garbage
- // collector, and the garbage collector only
- // runs when everyone else is stopped, and
- // runfinq only stops at the gosched() or
- // during the calls in the for loop.
+ runtime_lock(&finlock);
fb = finq;
finq = nil;
if(fb == nil) {
fingwait = 1;
- runtime_park(nil, nil, "finalizer wait");
+ runtime_park(runtime_unlock, &finlock, "finalizer wait");
continue;
}
+ runtime_unlock(&finlock);
if(raceenabled)
runtime_racefingo();
for(; fb; fb=next) {
next = fb->next;
for(i=0; i<(uint32)fb->cnt; i++) {
+ const Type *fint;
void *param;
f = &fb->fin[i];
- param = &f->arg;
+ fint = ((const Type**)f->ft->__in.array)[0];
+ if(fint->kind == KindPtr) {
+ // direct use of pointer
+ param = &f->arg;
+ } else if(((const InterfaceType*)fint)->__methods.__count == 0) {
+ // convert to empty interface
+ ef.type = (const Type*)f->ot;
+ ef.__object = f->arg;
+ param = &ef;
+ } else {
+ // convert to interface with methods
+ iface.__methods = __go_convert_interface_2((const Type*)fint,
+ (const Type*)f->ot,
+ 1);
+ iface.__object = f->arg;
+ if(iface.__methods == nil)
+ runtime_throw("invalid type conversion in runfinq");
+ param = &iface;
+ }
reflect_call(f->ft, f->fn, 0, 0, &param, nil);
f->fn = nil;
f->arg = nil;
+ f->ot = nil;
}
fb->cnt = 0;
fb->next = finc;
@@ -2280,28 +2318,28 @@ runfinq(void* dummy __attribute__ ((unused)))
}
// mark the block at v of size n as allocated.
-// If noptr is true, mark it as having no pointers.
+// If noscan is true, mark it as not needing scanning.
void
-runtime_markallocated(void *v, uintptr n, bool noptr)
+runtime_markallocated(void *v, uintptr n, bool noscan)
{
uintptr *b, obits, bits, off, shift;
if(0)
runtime_printf("markallocated %p+%p\n", v, n);
- if((byte*)v+n > (byte*)runtime_mheap->arena_used || (byte*)v < runtime_mheap->arena_start)
+ if((byte*)v+n > (byte*)runtime_mheap.arena_used || (byte*)v < runtime_mheap.arena_start)
runtime_throw("markallocated: bad pointer");
- off = (uintptr*)v - (uintptr*)runtime_mheap->arena_start; // word offset
- b = (uintptr*)runtime_mheap->arena_start - off/wordsPerBitmapWord - 1;
+ off = (uintptr*)v - (uintptr*)runtime_mheap.arena_start; // word offset
+ b = (uintptr*)runtime_mheap.arena_start - off/wordsPerBitmapWord - 1;
shift = off % wordsPerBitmapWord;
for(;;) {
obits = *b;
bits = (obits & ~(bitMask<<shift)) | (bitAllocated<<shift);
- if(noptr)
- bits |= bitNoPointers<<shift;
- if(runtime_singleproc) {
+ if(noscan)
+ bits |= bitNoScan<<shift;
+ if(runtime_gomaxprocs == 1) {
*b = bits;
break;
} else {
@@ -2319,19 +2357,19 @@ runtime_markfreed(void *v, uintptr n)
uintptr *b, obits, bits, off, shift;
if(0)
- runtime_printf("markallocated %p+%p\n", v, n);
+ runtime_printf("markfreed %p+%p\n", v, n);
- if((byte*)v+n > (byte*)runtime_mheap->arena_used || (byte*)v < runtime_mheap->arena_start)
- runtime_throw("markallocated: bad pointer");
+ if((byte*)v+n > (byte*)runtime_mheap.arena_used || (byte*)v < runtime_mheap.arena_start)
+ runtime_throw("markfreed: bad pointer");
- off = (uintptr*)v - (uintptr*)runtime_mheap->arena_start; // word offset
- b = (uintptr*)runtime_mheap->arena_start - off/wordsPerBitmapWord - 1;
+ off = (uintptr*)v - (uintptr*)runtime_mheap.arena_start; // word offset
+ b = (uintptr*)runtime_mheap.arena_start - off/wordsPerBitmapWord - 1;
shift = off % wordsPerBitmapWord;
for(;;) {
obits = *b;
bits = (obits & ~(bitMask<<shift)) | (bitBlockBoundary<<shift);
- if(runtime_singleproc) {
+ if(runtime_gomaxprocs == 1) {
*b = bits;
break;
} else {
@@ -2351,11 +2389,11 @@ runtime_checkfreed(void *v, uintptr n)
if(!runtime_checking)
return;
- if((byte*)v+n > (byte*)runtime_mheap->arena_used || (byte*)v < runtime_mheap->arena_start)
+ if((byte*)v+n > (byte*)runtime_mheap.arena_used || (byte*)v < runtime_mheap.arena_start)
return; // not allocated, so okay
- off = (uintptr*)v - (uintptr*)runtime_mheap->arena_start; // word offset
- b = (uintptr*)runtime_mheap->arena_start - off/wordsPerBitmapWord - 1;
+ off = (uintptr*)v - (uintptr*)runtime_mheap.arena_start; // word offset
+ b = (uintptr*)runtime_mheap.arena_start - off/wordsPerBitmapWord - 1;
shift = off % wordsPerBitmapWord;
bits = *b>>shift;
@@ -2374,7 +2412,7 @@ runtime_markspan(void *v, uintptr size, uintptr n, bool leftover)
uintptr *b, off, shift;
byte *p;
- if((byte*)v+size*n > (byte*)runtime_mheap->arena_used || (byte*)v < runtime_mheap->arena_start)
+ if((byte*)v+size*n > (byte*)runtime_mheap.arena_used || (byte*)v < runtime_mheap.arena_start)
runtime_throw("markspan: bad pointer");
p = v;
@@ -2385,8 +2423,8 @@ runtime_markspan(void *v, uintptr size, uintptr n, bool leftover)
// the entire span, and each bitmap word has bits for only
// one span, so no other goroutines are changing these
// bitmap words.
- off = (uintptr*)p - (uintptr*)runtime_mheap->arena_start; // word offset
- b = (uintptr*)runtime_mheap->arena_start - off/wordsPerBitmapWord - 1;
+ off = (uintptr*)p - (uintptr*)runtime_mheap.arena_start; // word offset
+ b = (uintptr*)runtime_mheap.arena_start - off/wordsPerBitmapWord - 1;
shift = off % wordsPerBitmapWord;
*b = (*b & ~(bitMask<<shift)) | (bitBlockBoundary<<shift);
}
@@ -2398,14 +2436,14 @@ runtime_unmarkspan(void *v, uintptr n)
{
uintptr *p, *b, off;
- if((byte*)v+n > (byte*)runtime_mheap->arena_used || (byte*)v < runtime_mheap->arena_start)
+ if((byte*)v+n > (byte*)runtime_mheap.arena_used || (byte*)v < runtime_mheap.arena_start)
runtime_throw("markspan: bad pointer");
p = v;
- off = p - (uintptr*)runtime_mheap->arena_start; // word offset
+ off = p - (uintptr*)runtime_mheap.arena_start; // word offset
if(off % wordsPerBitmapWord != 0)
runtime_throw("markspan: unaligned pointer");
- b = (uintptr*)runtime_mheap->arena_start - off/wordsPerBitmapWord - 1;
+ b = (uintptr*)runtime_mheap.arena_start - off/wordsPerBitmapWord - 1;
n /= PtrSize;
if(n%wordsPerBitmapWord != 0)
runtime_throw("unmarkspan: unaligned length");
@@ -2426,8 +2464,8 @@ runtime_blockspecial(void *v)
if(DebugMark)
return true;
- off = (uintptr*)v - (uintptr*)runtime_mheap->arena_start;
- b = (uintptr*)runtime_mheap->arena_start - off/wordsPerBitmapWord - 1;
+ off = (uintptr*)v - (uintptr*)runtime_mheap.arena_start;
+ b = (uintptr*)runtime_mheap.arena_start - off/wordsPerBitmapWord - 1;
shift = off % wordsPerBitmapWord;
return (*b & (bitSpecial<<shift)) != 0;
@@ -2441,8 +2479,8 @@ runtime_setblockspecial(void *v, bool s)
if(DebugMark)
return;
- off = (uintptr*)v - (uintptr*)runtime_mheap->arena_start;
- b = (uintptr*)runtime_mheap->arena_start - off/wordsPerBitmapWord - 1;
+ off = (uintptr*)v - (uintptr*)runtime_mheap.arena_start;
+ b = (uintptr*)runtime_mheap.arena_start - off/wordsPerBitmapWord - 1;
shift = off % wordsPerBitmapWord;
for(;;) {
@@ -2451,7 +2489,7 @@ runtime_setblockspecial(void *v, bool s)
bits = obits | (bitSpecial<<shift);
else
bits = obits & ~(bitSpecial<<shift);
- if(runtime_singleproc) {
+ if(runtime_gomaxprocs == 1) {
*b = bits;
break;
} else {
@@ -2476,13 +2514,13 @@ runtime_MHeap_MapBits(MHeap *h)
uintptr n;
n = (h->arena_used - h->arena_start) / wordsPerBitmapWord;
- n = (n+bitmapChunk-1) & ~(bitmapChunk-1);
+ n = ROUND(n, bitmapChunk);
if(h->bitmap_mapped >= n)
return;
page_size = getpagesize();
n = (n+page_size-1) & ~(page_size-1);
- runtime_SysMap(h->arena_start - n, n - h->bitmap_mapped);
+ runtime_SysMap(h->arena_start - n, n - h->bitmap_mapped, &mstats.gc_sys);
h->bitmap_mapped = n;
}
diff --git a/libgo/runtime/mgc0.h b/libgo/runtime/mgc0.h
index d14fb37c209..f8abe6c9c1c 100644
--- a/libgo/runtime/mgc0.h
+++ b/libgo/runtime/mgc0.h
@@ -26,7 +26,6 @@ enum {
GC_ARRAY_START, // Start an array with a fixed length. Args: (off, len, elemsize)
GC_ARRAY_NEXT, // The next element of an array. Args: none
GC_CALL, // Call a subroutine. Args: (off, objgcrel)
- GC_MAP_PTR, // Go map. Args: (off, MapType*)
GC_CHAN_PTR, // Go channel. Args: (off, ChanType*)
GC_STRING, // Go string. Args: (off)
GC_EFACE, // interface{}. Args: (off)
diff --git a/libgo/runtime/mheap.c b/libgo/runtime/mheap.c
index b4d94b68559..62070f37943 100644
--- a/libgo/runtime/mheap.c
+++ b/libgo/runtime/mheap.c
@@ -36,12 +36,12 @@ RecordSpan(void *vh, byte *p)
cap = 64*1024/sizeof(all[0]);
if(cap < h->nspancap*3/2)
cap = h->nspancap*3/2;
- all = (MSpan**)runtime_SysAlloc(cap*sizeof(all[0]));
+ all = (MSpan**)runtime_SysAlloc(cap*sizeof(all[0]), &mstats.other_sys);
if(all == nil)
runtime_throw("runtime: cannot allocate memory");
if(h->allspans) {
runtime_memmove(all, h->allspans, h->nspancap*sizeof(all[0]));
- runtime_SysFree(h->allspans, h->nspancap*sizeof(all[0]));
+ runtime_SysFree(h->allspans, h->nspancap*sizeof(all[0]), &mstats.other_sys);
}
h->allspans = all;
h->nspancap = cap;
@@ -51,12 +51,12 @@ RecordSpan(void *vh, byte *p)
// Initialize the heap; fetch memory using alloc.
void
-runtime_MHeap_Init(MHeap *h, void *(*alloc)(uintptr))
+runtime_MHeap_Init(MHeap *h)
{
uint32 i;
- runtime_FixAlloc_Init(&h->spanalloc, sizeof(MSpan), alloc, RecordSpan, h);
- runtime_FixAlloc_Init(&h->cachealloc, sizeof(MCache), alloc, nil, nil);
+ runtime_FixAlloc_Init(&h->spanalloc, sizeof(MSpan), RecordSpan, h, &mstats.mspan_sys);
+ runtime_FixAlloc_Init(&h->cachealloc, sizeof(MCache), nil, nil, &mstats.mcache_sys);
// h->mapcache needs no init
for(i=0; i<nelem(h->free); i++)
runtime_MSpanList_Init(&h->free[i]);
@@ -65,6 +65,26 @@ runtime_MHeap_Init(MHeap *h, void *(*alloc)(uintptr))
runtime_MCentral_Init(&h->central[i], i);
}
+void
+runtime_MHeap_MapSpans(MHeap *h)
+{
+ uintptr pagesize;
+ uintptr n;
+
+ // Map spans array, PageSize at a time.
+ n = (uintptr)h->arena_used;
+ if(sizeof(void*) == 8)
+ n -= (uintptr)h->arena_start;
+ n = n / PageSize * sizeof(h->spans[0]);
+ n = ROUND(n, PageSize);
+ pagesize = getpagesize();
+ n = ROUND(n, pagesize);
+ if(h->spans_mapped >= n)
+ return;
+ runtime_SysMap((byte*)h->spans + h->spans_mapped, n - h->spans_mapped, &mstats.other_sys);
+ h->spans_mapped = n;
+}
+
// Allocate a new span of npage pages from the heap
// and record its size class in the HeapMap and HeapMapCache.
MSpan*
@@ -73,7 +93,8 @@ runtime_MHeap_Alloc(MHeap *h, uintptr npage, int32 sizeclass, int32 acct, int32
MSpan *s;
runtime_lock(h);
- runtime_purgecachedstats(runtime_m()->mcache);
+ mstats.heap_alloc += runtime_m()->mcache->local_cachealloc;
+ runtime_m()->mcache->local_cachealloc = 0;
s = MHeap_AllocLocked(h, npage, sizeclass);
if(s != nil) {
mstats.heap_inuse += npage<<PageShift;
@@ -138,6 +159,7 @@ HaveSpan:
// is just a unique constant not seen elsewhere in the
// runtime, as a clue in case it turns up unexpectedly in
// memory or in a stack trace.
+ runtime_SysUsed((void*)(s->start<<PageShift), s->npages<<PageShift);
*(uintptr*)(s->start<<PageShift) = (uintptr)0xbeadbeadbeadbeadULL;
}
s->npreleased = 0;
@@ -145,17 +167,15 @@ HaveSpan:
if(s->npages > npage) {
// Trim extra and put it back in the heap.
t = runtime_FixAlloc_Alloc(&h->spanalloc);
- mstats.mspan_inuse = h->spanalloc.inuse;
- mstats.mspan_sys = h->spanalloc.sys;
runtime_MSpan_Init(t, s->start + npage, s->npages - npage);
s->npages = npage;
p = t->start;
if(sizeof(void*) == 8)
p -= ((uintptr)h->arena_start>>PageShift);
if(p > 0)
- h->map[p-1] = s;
- h->map[p] = t;
- h->map[p+t->npages-1] = t;
+ h->spans[p-1] = s;
+ h->spans[p] = t;
+ h->spans[p+t->npages-1] = t;
*(uintptr*)(t->start<<PageShift) = *(uintptr*)(s->start<<PageShift); // copy "needs zeroing" mark
t->state = MSpanInUse;
MHeap_FreeLocked(h, t);
@@ -172,7 +192,7 @@ HaveSpan:
if(sizeof(void*) == 8)
p -= ((uintptr)h->arena_start>>PageShift);
for(n=0; n<npage; n++)
- h->map[p+n] = s;
+ h->spans[p+n] = s;
return s;
}
@@ -232,19 +252,16 @@ MHeap_Grow(MHeap *h, uintptr npage)
return false;
}
}
- mstats.heap_sys += ask;
// Create a fake "in use" span and free it, so that the
// right coalescing happens.
s = runtime_FixAlloc_Alloc(&h->spanalloc);
- mstats.mspan_inuse = h->spanalloc.inuse;
- mstats.mspan_sys = h->spanalloc.sys;
runtime_MSpan_Init(s, (uintptr)v>>PageShift, ask>>PageShift);
p = s->start;
if(sizeof(void*) == 8)
p -= ((uintptr)h->arena_start>>PageShift);
- h->map[p] = s;
- h->map[p + s->npages - 1] = s;
+ h->spans[p] = s;
+ h->spans[p + s->npages - 1] = s;
s->state = MSpanInUse;
MHeap_FreeLocked(h, s);
return true;
@@ -261,7 +278,7 @@ runtime_MHeap_Lookup(MHeap *h, void *v)
p = (uintptr)v;
if(sizeof(void*) == 8)
p -= (uintptr)h->arena_start;
- return h->map[p >> PageShift];
+ return h->spans[p >> PageShift];
}
// Look up the span at the given address.
@@ -283,10 +300,8 @@ runtime_MHeap_LookupMaybe(MHeap *h, void *v)
q = p;
if(sizeof(void*) == 8)
q -= (uintptr)h->arena_start >> PageShift;
- s = h->map[q];
- if(s == nil || p < s->start || p - s->start >= s->npages)
- return nil;
- if(s->state != MSpanInUse)
+ s = h->spans[q];
+ if(s == nil || p < s->start || (byte*)v >= s->limit || s->state != MSpanInUse)
return nil;
return s;
}
@@ -296,7 +311,8 @@ void
runtime_MHeap_Free(MHeap *h, MSpan *s, int32 acct)
{
runtime_lock(h);
- runtime_purgecachedstats(runtime_m()->mcache);
+ mstats.heap_alloc += runtime_m()->mcache->local_cachealloc;
+ runtime_m()->mcache->local_cachealloc = 0;
mstats.heap_inuse -= s->npages<<PageShift;
if(acct) {
mstats.heap_alloc -= s->npages<<PageShift;
@@ -313,8 +329,6 @@ MHeap_FreeLocked(MHeap *h, MSpan *s)
MSpan *t;
PageID p;
- if(s->types.sysalloc)
- runtime_settype_sysfree(s);
s->types.compression = MTypes_Empty;
if(s->state != MSpanInUse || s->ref != 0) {
@@ -334,31 +348,31 @@ MHeap_FreeLocked(MHeap *h, MSpan *s)
p = s->start;
if(sizeof(void*) == 8)
p -= (uintptr)h->arena_start >> PageShift;
- if(p > 0 && (t = h->map[p-1]) != nil && t->state != MSpanInUse) {
- tp = (uintptr*)(t->start<<PageShift);
- *tp |= *sp; // propagate "needs zeroing" mark
+ if(p > 0 && (t = h->spans[p-1]) != nil && t->state != MSpanInUse) {
+ if(t->npreleased == 0) { // cant't touch this otherwise
+ tp = (uintptr*)(t->start<<PageShift);
+ *tp |= *sp; // propagate "needs zeroing" mark
+ }
s->start = t->start;
s->npages += t->npages;
s->npreleased = t->npreleased; // absorb released pages
p -= t->npages;
- h->map[p] = s;
+ h->spans[p] = s;
runtime_MSpanList_Remove(t);
t->state = MSpanDead;
runtime_FixAlloc_Free(&h->spanalloc, t);
- mstats.mspan_inuse = h->spanalloc.inuse;
- mstats.mspan_sys = h->spanalloc.sys;
}
- if(p+s->npages < nelem(h->map) && (t = h->map[p+s->npages]) != nil && t->state != MSpanInUse) {
- tp = (uintptr*)(t->start<<PageShift);
- *sp |= *tp; // propagate "needs zeroing" mark
+ if((p+s->npages)*sizeof(h->spans[0]) < h->spans_mapped && (t = h->spans[p+s->npages]) != nil && t->state != MSpanInUse) {
+ if(t->npreleased == 0) { // cant't touch this otherwise
+ tp = (uintptr*)(t->start<<PageShift);
+ *sp |= *tp; // propagate "needs zeroing" mark
+ }
s->npages += t->npages;
s->npreleased += t->npreleased;
- h->map[p + s->npages - 1] = s;
+ h->spans[p + s->npages - 1] = s;
runtime_MSpanList_Remove(t);
t->state = MSpanDead;
runtime_FixAlloc_Free(&h->spanalloc, t);
- mstats.mspan_inuse = h->spanalloc.inuse;
- mstats.mspan_sys = h->spanalloc.sys;
}
// Insert s into appropriate list.
@@ -388,7 +402,7 @@ scavengelist(MSpan *list, uint64 now, uint64 limit)
sumreleased = 0;
for(s=list->next; s != list; s=s->next) {
- if((now - s->unusedsince) > limit) {
+ if((now - s->unusedsince) > limit && s->npreleased != s->npages) {
released = (s->npages - s->npreleased) << PageShift;
mstats.heap_released += released;
sumreleased += released;
@@ -399,19 +413,26 @@ scavengelist(MSpan *list, uint64 now, uint64 limit)
return sumreleased;
}
-static uintptr
-scavenge(uint64 now, uint64 limit)
+static void
+scavenge(int32 k, uint64 now, uint64 limit)
{
uint32 i;
uintptr sumreleased;
MHeap *h;
- h = runtime_mheap;
+ h = &runtime_mheap;
sumreleased = 0;
for(i=0; i < nelem(h->free); i++)
sumreleased += scavengelist(&h->free[i], now, limit);
sumreleased += scavengelist(&h->large, now, limit);
- return sumreleased;
+
+ if(runtime_debug.gctrace > 0) {
+ if(sumreleased > 0)
+ runtime_printf("scvg%d: %D MB released\n", k, (uint64)sumreleased>>20);
+ runtime_printf("scvg%d: inuse: %D, idle: %D, sys: %D, released: %D, consumed: %D (MB)\n",
+ k, mstats.heap_inuse>>20, mstats.heap_idle>>20, mstats.heap_sys>>20,
+ mstats.heap_released>>20, (mstats.heap_sys - mstats.heap_released)>>20);
+ }
}
// Release (part of) unused memory to OS.
@@ -424,9 +445,6 @@ runtime_MHeap_Scavenger(void* dummy)
MHeap *h;
uint64 tick, now, forcegc, limit;
uint32 k;
- uintptr sumreleased;
- const byte *env;
- bool trace;
Note note, *notep;
USED(dummy);
@@ -446,17 +464,10 @@ runtime_MHeap_Scavenger(void* dummy)
else
tick = limit/2;
- trace = false;
- env = runtime_getenv("GOGCTRACE");
- if(env != nil)
- trace = runtime_atoi(env) > 0;
-
- h = runtime_mheap;
+ h = &runtime_mheap;
for(k=0;; k++) {
runtime_noteclear(&note);
- runtime_entersyscallblock();
- runtime_notetsleep(&note, tick);
- runtime_exitsyscall();
+ runtime_notetsleepg(&note, tick);
runtime_lock(h);
now = runtime_nanotime();
@@ -468,24 +479,14 @@ runtime_MHeap_Scavenger(void* dummy)
runtime_noteclear(&note);
notep = &note;
__go_go(forcegchelper, (void*)notep);
- runtime_entersyscallblock();
- runtime_notesleep(&note);
- runtime_exitsyscall();
- if(trace)
+ runtime_notetsleepg(&note, -1);
+ if(runtime_debug.gctrace > 0)
runtime_printf("scvg%d: GC forced\n", k);
runtime_lock(h);
now = runtime_nanotime();
}
- sumreleased = scavenge(now, limit);
+ scavenge(k, now, limit);
runtime_unlock(h);
-
- if(trace) {
- if(sumreleased > 0)
- runtime_printf("scvg%d: %p MB released\n", k, sumreleased>>20);
- runtime_printf("scvg%d: inuse: %D, idle: %D, sys: %D, released: %D, consumed: %D (MB)\n",
- k, mstats.heap_inuse>>20, mstats.heap_idle>>20, mstats.heap_sys>>20,
- mstats.heap_released>>20, (mstats.heap_sys - mstats.heap_released)>>20);
- }
}
}
@@ -495,9 +496,9 @@ void
runtime_debug_freeOSMemory(void)
{
runtime_gc(1);
- runtime_lock(runtime_mheap);
- scavenge(~(uintptr)0, 0);
- runtime_unlock(runtime_mheap);
+ runtime_lock(&runtime_mheap);
+ scavenge(-1, ~(uintptr)0, 0);
+ runtime_unlock(&runtime_mheap);
}
// Initialize a new span with the given start and npages.
diff --git a/libgo/runtime/mprof.goc b/libgo/runtime/mprof.goc
index 73d937908c6..7507dfc9173 100644
--- a/libgo/runtime/mprof.goc
+++ b/libgo/runtime/mprof.goc
@@ -14,44 +14,11 @@ package runtime
#include "go-string.h"
// NOTE(rsc): Everything here could use cas if contention became an issue.
-static Lock proflock, alloclock;
+static Lock proflock;
// All memory allocations are local and do not escape outside of the profiler.
// The profiler is forbidden from referring to garbage-collected memory.
-static byte *pool; // memory allocation pool
-static uintptr poolfree; // number of bytes left in the pool
-enum {
- Chunk = 32*PageSize, // initial size of the pool
-};
-
-// Memory allocation local to this file.
-// There is no way to return the allocated memory back to the OS.
-static void*
-allocate(uintptr size)
-{
- void *v;
-
- if(size == 0)
- return nil;
-
- if(size >= Chunk/2)
- return runtime_SysAlloc(size);
-
- runtime_lock(&alloclock);
- if(size > poolfree) {
- pool = runtime_SysAlloc(Chunk);
- if(pool == nil)
- runtime_throw("runtime: cannot allocate memory");
- poolfree = Chunk;
- }
- v = pool;
- pool += size;
- poolfree -= size;
- runtime_unlock(&alloclock);
- return v;
-}
-
enum { MProf, BProf }; // profile types
// Per-call-stack profiling information.
@@ -104,10 +71,9 @@ stkbucket(int32 typ, Location *stk, int32 nstk, bool alloc)
Bucket *b;
if(buckhash == nil) {
- buckhash = runtime_SysAlloc(BuckHashSize*sizeof buckhash[0]);
+ buckhash = runtime_SysAlloc(BuckHashSize*sizeof buckhash[0], &mstats.buckhash_sys);
if(buckhash == nil)
runtime_throw("runtime: cannot allocate memory");
- mstats.buckhash_sys += BuckHashSize*sizeof buckhash[0];
}
// Hash stack.
@@ -137,9 +103,7 @@ stkbucket(int32 typ, Location *stk, int32 nstk, bool alloc)
if(!alloc)
return nil;
- b = allocate(sizeof *b + nstk*sizeof stk[0]);
- if(b == nil)
- runtime_throw("runtime: cannot allocate memory");
+ b = runtime_persistentalloc(sizeof *b + nstk*sizeof stk[0], 0, &mstats.buckhash_sys);
bucketmem += sizeof *b + nstk*sizeof stk[0];
runtime_memmove(b->stk, stk, nstk*sizeof stk[0]);
b->typ = typ;
@@ -241,7 +205,7 @@ setaddrbucket(uintptr addr, Bucket *b)
if(ah->addr == (addr>>AddrHashShift))
goto found;
- ah = allocate(sizeof *ah);
+ ah = runtime_persistentalloc(sizeof *ah, 0, &mstats.buckhash_sys);
addrmem += sizeof *ah;
ah->next = addrhash[h];
ah->addr = addr>>AddrHashShift;
@@ -249,7 +213,7 @@ setaddrbucket(uintptr addr, Bucket *b)
found:
if((e = addrfree) == nil) {
- e = allocate(64*sizeof *e);
+ e = runtime_persistentalloc(64*sizeof *e, 0, &mstats.buckhash_sys);
addrmem += 64*sizeof *e;
for(i=0; i+1<64; i++)
e[i].next = &e[i+1];
@@ -296,16 +260,10 @@ found:
void
runtime_MProf_Malloc(void *p, uintptr size)
{
- M *m;
int32 nstk;
Location stk[32];
Bucket *b;
- m = runtime_m();
- if(m->nomemprof > 0)
- return;
-
- m->nomemprof++;
nstk = runtime_callers(1, stk, 32);
runtime_lock(&proflock);
b = stkbucket(MProf, stk, nstk, true);
@@ -313,22 +271,14 @@ runtime_MProf_Malloc(void *p, uintptr size)
b->recent_alloc_bytes += size;
setaddrbucket((uintptr)p, b);
runtime_unlock(&proflock);
- m = runtime_m();
- m->nomemprof--;
}
// Called when freeing a profiled block.
void
runtime_MProf_Free(void *p, uintptr size)
{
- M *m;
Bucket *b;
- m = runtime_m();
- if(m->nomemprof > 0)
- return;
-
- m->nomemprof++;
runtime_lock(&proflock);
b = getaddrbucket((uintptr)p);
if(b != nil) {
@@ -336,8 +286,6 @@ runtime_MProf_Free(void *p, uintptr size)
b->recent_free_bytes += size;
}
runtime_unlock(&proflock);
- m = runtime_m();
- m->nomemprof--;
}
int64 runtime_blockprofilerate; // in CPU ticks
@@ -347,7 +295,17 @@ void runtime_SetBlockProfileRate(intgo) __asm__ (GOSYM_PREFIX "runtime.SetBlockP
void
runtime_SetBlockProfileRate(intgo rate)
{
- runtime_atomicstore64((uint64*)&runtime_blockprofilerate, rate * runtime_tickspersecond() / (1000*1000*1000));
+ int64 r;
+
+ if(rate <= 0)
+ r = 0; // disable profiling
+ else {
+ // convert ns to cycles, use float64 to prevent overflow during multiplication
+ r = (float64)rate*runtime_tickspersecond()/(1000*1000*1000);
+ if(r == 0)
+ r = 1;
+ }
+ runtime_atomicstore64((uint64*)&runtime_blockprofilerate, r);
}
void
@@ -510,10 +468,10 @@ func Stack(b Slice, all bool) (n int) {
bool enablegc;
sp = runtime_getcallersp(&b);
- pc = runtime_getcallerpc(&b);
+ pc = (byte*)(uintptr)runtime_getcallerpc(&b);
if(all) {
- runtime_semacquire(&runtime_worldsema);
+ runtime_semacquire(&runtime_worldsema, false);
runtime_m()->gcing = 1;
runtime_stoptheworld();
enablegc = mstats.enablegc;
@@ -530,7 +488,7 @@ func Stack(b Slice, all bool) (n int) {
USED(sp);
runtime_goroutineheader(g);
runtime_traceback();
- runtime_goroutinetrailer(g);
+ runtime_printcreatedby(g);
if(all)
runtime_tracebackothers(g);
n = b.__count - g->writenbuf;
@@ -572,7 +530,7 @@ func GoroutineProfile(b Slice) (n int, ok bool) {
ok = false;
n = runtime_gcount();
if(n <= b.__count) {
- runtime_semacquire(&runtime_worldsema);
+ runtime_semacquire(&runtime_worldsema, false);
runtime_m()->gcing = 1;
runtime_stoptheworld();
@@ -598,5 +556,5 @@ func GoroutineProfile(b Slice) (n int, ok bool) {
void
runtime_mprofinit(void)
{
- addrhash = allocate((1<<AddrHashBits)*sizeof *addrhash);
+ addrhash = runtime_persistentalloc((1<<AddrHashBits)*sizeof *addrhash, 0, &mstats.buckhash_sys);
}
diff --git a/libgo/runtime/msize.c b/libgo/runtime/msize.c
index 3b5591c1b17..745a76958c8 100644
--- a/libgo/runtime/msize.c
+++ b/libgo/runtime/msize.c
@@ -31,7 +31,6 @@
int32 runtime_class_to_size[NumSizeClasses];
int32 runtime_class_to_allocnpages[NumSizeClasses];
-int32 runtime_class_to_transfercount[NumSizeClasses];
// The SizeToClass lookup is implemented using two arrays,
// one mapping sizes <= 1024 to their class and one mapping
@@ -42,17 +41,17 @@ int32 runtime_class_to_transfercount[NumSizeClasses];
// size divided by 128 (rounded up). The arrays are filled in
// by InitSizes.
-static int32 size_to_class8[1024/8 + 1];
-static int32 size_to_class128[(MaxSmallSize-1024)/128 + 1];
+int8 runtime_size_to_class8[1024/8 + 1];
+int8 runtime_size_to_class128[(MaxSmallSize-1024)/128 + 1];
-int32
-runtime_SizeToClass(int32 size)
+static int32
+SizeToClass(int32 size)
{
if(size > MaxSmallSize)
runtime_throw("SizeToClass - invalid size");
if(size > 1024-8)
- return size_to_class128[(size-1024+127) >> 7];
- return size_to_class8[(size+7)>>3];
+ return runtime_size_to_class128[(size-1024+127) >> 7];
+ return runtime_size_to_class8[(size+7)>>3];
}
void
@@ -111,16 +110,16 @@ runtime_InitSizes(void)
nextsize = 0;
for (sizeclass = 1; sizeclass < NumSizeClasses; sizeclass++) {
for(; nextsize < 1024 && nextsize <= runtime_class_to_size[sizeclass]; nextsize+=8)
- size_to_class8[nextsize/8] = sizeclass;
+ runtime_size_to_class8[nextsize/8] = sizeclass;
if(nextsize >= 1024)
for(; nextsize <= runtime_class_to_size[sizeclass]; nextsize += 128)
- size_to_class128[(nextsize-1024)/128] = sizeclass;
+ runtime_size_to_class128[(nextsize-1024)/128] = sizeclass;
}
// Double-check SizeToClass.
if(0) {
for(n=0; n < MaxSmallSize; n++) {
- sizeclass = runtime_SizeToClass(n);
+ sizeclass = SizeToClass(n);
if(sizeclass < 1 || sizeclass >= NumSizeClasses || runtime_class_to_size[sizeclass] < n) {
runtime_printf("size=%d sizeclass=%d runtime_class_to_size=%d\n", n, sizeclass, runtime_class_to_size[sizeclass]);
runtime_printf("incorrect SizeToClass");
@@ -137,16 +136,6 @@ runtime_InitSizes(void)
// Copy out for statistics table.
for(i=0; i<nelem(runtime_class_to_size); i++)
mstats.by_size[i].size = runtime_class_to_size[i];
-
- // Initialize the runtime_class_to_transfercount table.
- for(sizeclass = 1; sizeclass < NumSizeClasses; sizeclass++) {
- n = 64*1024 / runtime_class_to_size[sizeclass];
- if(n < 2)
- n = 2;
- if(n > 32)
- n = 32;
- runtime_class_to_transfercount[sizeclass] = n;
- }
return;
dump:
@@ -157,12 +146,14 @@ dump:
runtime_printf(" %d", runtime_class_to_size[sizeclass]);
runtime_printf("\n\n");
runtime_printf("size_to_class8:");
- for(i=0; i<nelem(size_to_class8); i++)
- runtime_printf(" %d=>%d(%d)\n", i*8, size_to_class8[i], runtime_class_to_size[size_to_class8[i]]);
+ for(i=0; i<nelem(runtime_size_to_class8); i++)
+ runtime_printf(" %d=>%d(%d)\n", i*8, runtime_size_to_class8[i],
+ runtime_class_to_size[runtime_size_to_class8[i]]);
runtime_printf("\n");
runtime_printf("size_to_class128:");
- for(i=0; i<nelem(size_to_class128); i++)
- runtime_printf(" %d=>%d(%d)\n", i*128, size_to_class128[i], runtime_class_to_size[size_to_class128[i]]);
+ for(i=0; i<nelem(runtime_size_to_class128); i++)
+ runtime_printf(" %d=>%d(%d)\n", i*128, runtime_size_to_class128[i],
+ runtime_class_to_size[runtime_size_to_class128[i]]);
runtime_printf("\n");
}
runtime_throw("InitSizes failed");
diff --git a/libgo/runtime/netpoll.goc b/libgo/runtime/netpoll.goc
index a0bd735f85c..02705734dd8 100644
--- a/libgo/runtime/netpoll.goc
+++ b/libgo/runtime/netpoll.goc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin linux
+// +build darwin dragonfly freebsd linux netbsd openbsd windows
package net
@@ -19,7 +19,7 @@ package net
// Integrated network poller (platform-independent part).
// A particular implementation (epoll/kqueue) must define the following functions:
// void runtime_netpollinit(void); // to initialize the poller
-// int32 runtime_netpollopen(int32 fd, PollDesc *pd); // to arm edge-triggered notifications
+// int32 runtime_netpollopen(uintptr fd, PollDesc *pd); // to arm edge-triggered notifications
// and associate fd with pd.
// An implementation must call the following function to denote that the pd is ready.
// void runtime_netpollready(G **gpp, PollDesc *pd, int32 mode);
@@ -30,7 +30,7 @@ struct PollDesc
{
PollDesc* link; // in pollcache, protected by pollcache.Lock
Lock; // protectes the following fields
- int32 fd;
+ uintptr fd;
bool closing;
uintptr seq; // protects from stale timers and ready notifications
G* rg; // G waiting for read or READY (binary semaphore)
@@ -52,8 +52,8 @@ static struct
// seq is incremented when deadlines are changed or descriptor is reused.
} pollcache;
-static void netpollblock(PollDesc*, int32);
-static G* netpollunblock(PollDesc*, int32);
+static bool netpollblock(PollDesc*, int32);
+static G* netpollunblock(PollDesc*, int32, bool);
static void deadline(int64, Eface);
static void readDeadline(int64, Eface);
static void writeDeadline(int64, Eface);
@@ -68,7 +68,7 @@ func runtime_pollServerInit() {
runtime_netpollinit();
}
-func runtime_pollOpen(fd int) (pd *PollDesc, errno int) {
+func runtime_pollOpen(fd uintptr) (pd *PollDesc, errno int) {
pd = allocPollDesc();
runtime_lock(pd);
if(pd->wg != nil && pd->wg != READY)
@@ -117,18 +117,35 @@ ret:
func runtime_pollWait(pd *PollDesc, mode int) (err int) {
runtime_lock(pd);
err = checkerr(pd, mode);
- if(err)
- goto ret;
- netpollblock(pd, mode);
- err = checkerr(pd, mode);
-ret:
+ if(err == 0) {
+ while(!netpollblock(pd, mode)) {
+ err = checkerr(pd, mode);
+ if(err != 0)
+ break;
+ // Can happen if timeout has fired and unblocked us,
+ // but before we had a chance to run, timeout has been reset.
+ // Pretend it has not happened and retry.
+ }
+ }
+ runtime_unlock(pd);
+}
+
+func runtime_pollWaitCanceled(pd *PollDesc, mode int) {
+ runtime_lock(pd);
+ // wait for ioready, ignore closing or timeouts.
+ while(!netpollblock(pd, mode))
+ ;
runtime_unlock(pd);
}
func runtime_pollSetDeadline(pd *PollDesc, d int64, mode int) {
+ G *rg, *wg;
+
runtime_lock(pd);
- if(pd->closing)
- goto ret;
+ if(pd->closing) {
+ runtime_unlock(pd);
+ return;
+ }
pd->seq++; // invalidate current timers
// Reset current timers.
if(pd->rt.fv) {
@@ -140,9 +157,8 @@ func runtime_pollSetDeadline(pd *PollDesc, d int64, mode int) {
pd->wt.fv = nil;
}
// Setup new timers.
- if(d != 0 && d <= runtime_nanotime()) {
+ if(d != 0 && d <= runtime_nanotime())
d = -1;
- }
if(mode == 'r' || mode == 'r'+'w')
pd->rd = d;
if(mode == 'w' || mode == 'r'+'w')
@@ -172,8 +188,18 @@ func runtime_pollSetDeadline(pd *PollDesc, d int64, mode int) {
runtime_addtimer(&pd->wt);
}
}
-ret:
+ // If we set the new deadline in the past, unblock currently pending IO if any.
+ rg = nil;
+ wg = nil;
+ if(pd->rd < 0)
+ rg = netpollunblock(pd, 'r', false);
+ if(pd->wd < 0)
+ wg = netpollunblock(pd, 'w', false);
runtime_unlock(pd);
+ if(rg)
+ runtime_ready(rg);
+ if(wg)
+ runtime_ready(wg);
}
func runtime_pollUnblock(pd *PollDesc) {
@@ -184,8 +210,8 @@ func runtime_pollUnblock(pd *PollDesc) {
runtime_throw("runtime_pollUnblock: already closing");
pd->closing = true;
pd->seq++;
- rg = netpollunblock(pd, 'r');
- wg = netpollunblock(pd, 'w');
+ rg = netpollunblock(pd, 'r', false);
+ wg = netpollunblock(pd, 'w', false);
if(pd->rt.fv) {
runtime_deltimer(&pd->rt);
pd->rt.fv = nil;
@@ -201,6 +227,12 @@ func runtime_pollUnblock(pd *PollDesc) {
runtime_ready(wg);
}
+uintptr
+runtime_netpollfd(PollDesc *pd)
+{
+ return pd->fd;
+}
+
// make pd ready, newly runnable goroutines (if any) are enqueued info gpp list
void
runtime_netpollready(G **gpp, PollDesc *pd, int32 mode)
@@ -210,9 +242,9 @@ runtime_netpollready(G **gpp, PollDesc *pd, int32 mode)
rg = wg = nil;
runtime_lock(pd);
if(mode == 'r' || mode == 'r'+'w')
- rg = netpollunblock(pd, 'r');
+ rg = netpollunblock(pd, 'r', true);
if(mode == 'w' || mode == 'r'+'w')
- wg = netpollunblock(pd, 'w');
+ wg = netpollunblock(pd, 'w', true);
runtime_unlock(pd);
if(rg) {
rg->schedlink = *gpp;
@@ -234,7 +266,8 @@ checkerr(PollDesc *pd, int32 mode)
return 0;
}
-static void
+// returns true if IO is ready, or false if timedout or closed
+static bool
netpollblock(PollDesc *pd, int32 mode)
{
G **gpp;
@@ -244,17 +277,20 @@ netpollblock(PollDesc *pd, int32 mode)
gpp = &pd->wg;
if(*gpp == READY) {
*gpp = nil;
- return;
+ return true;
}
if(*gpp != nil)
- runtime_throw("epoll: double wait");
+ runtime_throw("netpollblock: double wait");
*gpp = runtime_g();
runtime_park(runtime_unlock, &pd->Lock, "IO wait");
runtime_lock(pd);
+ if(runtime_g()->param)
+ return true;
+ return false;
}
static G*
-netpollunblock(PollDesc *pd, int32 mode)
+netpollunblock(PollDesc *pd, int32 mode, bool ioready)
{
G **gpp, *old;
@@ -264,10 +300,15 @@ netpollunblock(PollDesc *pd, int32 mode)
if(*gpp == READY)
return nil;
if(*gpp == nil) {
- *gpp = READY;
+ // Only set READY for ioready. runtime_pollWait
+ // will check for timeout/cancel before waiting.
+ if(ioready)
+ *gpp = READY;
return nil;
}
old = *gpp;
+ // pass unblock reason onto blocked g
+ old->param = (void*)(uintptr)ioready;
*gpp = nil;
return old;
}
@@ -296,14 +337,14 @@ deadlineimpl(int64 now, Eface arg, bool read, bool write)
runtime_throw("deadlineimpl: inconsistent read deadline");
pd->rd = -1;
pd->rt.fv = nil;
- rg = netpollunblock(pd, 'r');
+ rg = netpollunblock(pd, 'r', false);
}
if(write) {
if(pd->wd <= 0 || (pd->wt.fv == nil && !read))
runtime_throw("deadlineimpl: inconsistent write deadline");
pd->wd = -1;
pd->wt.fv = nil;
- wg = netpollunblock(pd, 'w');
+ wg = netpollunblock(pd, 'w', false);
}
runtime_unlock(pd);
if(rg)
@@ -343,7 +384,7 @@ allocPollDesc(void)
n = 1;
// Must be in non-GC memory because can be referenced
// only from epoll/kqueue internals.
- pd = runtime_SysAlloc(n*sizeof(*pd));
+ pd = runtime_persistentalloc(n*sizeof(*pd), 0, &mstats.other_sys);
for(i = 0; i < n; i++) {
pd[i].link = pollcache.first;
pollcache.first = &pd[i];
diff --git a/libgo/runtime/netpoll_epoll.c b/libgo/runtime/netpoll_epoll.c
index 98c5cbeb587..b98aa818c89 100644
--- a/libgo/runtime/netpoll_epoll.c
+++ b/libgo/runtime/netpoll_epoll.c
@@ -94,24 +94,24 @@ runtime_netpollinit(void)
}
int32
-runtime_netpollopen(int32 fd, PollDesc *pd)
+runtime_netpollopen(uintptr fd, PollDesc *pd)
{
EpollEvent ev;
int32 res;
ev.events = EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLET;
ev.data.ptr = (void*)pd;
- res = runtime_epollctl(epfd, EPOLL_CTL_ADD, fd, &ev);
+ res = runtime_epollctl(epfd, EPOLL_CTL_ADD, (int32)fd, &ev);
return -res;
}
int32
-runtime_netpollclose(int32 fd)
+runtime_netpollclose(uintptr fd)
{
EpollEvent ev;
int32 res;
- res = runtime_epollctl(epfd, EPOLL_CTL_DEL, fd, &ev);
+ res = runtime_epollctl(epfd, EPOLL_CTL_DEL, (int32)fd, &ev);
return -res;
}
diff --git a/libgo/runtime/netpoll_kqueue.c b/libgo/runtime/netpoll_kqueue.c
index 9b79b2020df..78901611884 100644
--- a/libgo/runtime/netpoll_kqueue.c
+++ b/libgo/runtime/netpoll_kqueue.c
@@ -2,10 +2,11 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin
+// +build darwin dragonfly freebsd netbsd openbsd
#include "runtime.h"
#include "defs_GOOS_GOARCH.h"
+#include "os_GOOS.h"
// Integrated network poller (kqueue-based implementation).
@@ -27,7 +28,7 @@ runtime_netpollinit(void)
}
int32
-runtime_netpollopen(int32 fd, PollDesc *pd)
+runtime_netpollopen(uintptr fd, PollDesc *pd)
{
Kevent ev[2];
int32 n;
@@ -35,30 +36,22 @@ runtime_netpollopen(int32 fd, PollDesc *pd)
// Arm both EVFILT_READ and EVFILT_WRITE in edge-triggered mode (EV_CLEAR)
// for the whole fd lifetime. The notifications are automatically unregistered
// when fd is closed.
- ev[0].ident = fd;
+ ev[0].ident = (uint32)fd;
ev[0].filter = EVFILT_READ;
- ev[0].flags = EV_ADD|EV_RECEIPT|EV_CLEAR;
+ ev[0].flags = EV_ADD|EV_CLEAR;
ev[0].fflags = 0;
ev[0].data = 0;
- ev[0].udata = (byte*)pd;
+ ev[0].udata = (kevent_udata)pd;
ev[1] = ev[0];
ev[1].filter = EVFILT_WRITE;
- n = runtime_kevent(kq, ev, 2, ev, 2, nil);
+ n = runtime_kevent(kq, ev, 2, nil, 0, nil);
if(n < 0)
return -n;
- if(n != 2 ||
- (ev[0].flags&EV_ERROR) == 0 || ev[0].ident != fd || ev[0].filter != EVFILT_READ ||
- (ev[1].flags&EV_ERROR) == 0 || ev[1].ident != fd || ev[1].filter != EVFILT_WRITE)
- return EFAULT; // just to mark out from other errors
- if(ev[0].data != 0)
- return ev[0].data;
- if(ev[1].data != 0)
- return ev[1].data;
return 0;
}
int32
-runtime_netpollclose(int32 fd)
+runtime_netpollclose(uintptr fd)
{
// Don't need to unregister because calling close()
// on fd will remove any kevents that reference the descriptor.
@@ -74,7 +67,7 @@ runtime_netpoll(bool block)
static int32 lasterr;
Kevent events[64], *ev;
Timespec ts, *tp;
- int32 n, i;
+ int32 n, i, mode;
G *gp;
if(kq == -1)
@@ -97,10 +90,13 @@ retry:
}
for(i = 0; i < n; i++) {
ev = &events[i];
+ mode = 0;
if(ev->filter == EVFILT_READ)
- runtime_netpollready(&gp, (PollDesc*)ev->udata, 'r');
+ mode += 'r';
if(ev->filter == EVFILT_WRITE)
- runtime_netpollready(&gp, (PollDesc*)ev->udata, 'w');
+ mode += 'w';
+ if(mode)
+ runtime_netpollready(&gp, (PollDesc*)ev->udata, mode);
}
if(block && gp == nil)
goto retry;
diff --git a/libgo/runtime/netpoll_stub.c b/libgo/runtime/netpoll_stub.c
index e28e38e2643..84eef754c8d 100644
--- a/libgo/runtime/netpoll_stub.c
+++ b/libgo/runtime/netpoll_stub.c
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build freebsd netbsd openbsd plan9 windows
+// +build plan9
#include "runtime.h"
diff --git a/libgo/runtime/panic.c b/libgo/runtime/panic.c
index 7d79256cf41..7a8d95b1ade 100644
--- a/libgo/runtime/panic.c
+++ b/libgo/runtime/panic.c
@@ -38,7 +38,7 @@ runtime_startpanic(void)
M *m;
m = runtime_m();
- if(runtime_mheap == 0 || runtime_mheap->cachealloc.size == 0) { // very early
+ if(runtime_mheap.cachealloc.size == 0) { // very early
runtime_printf("runtime: panic before malloc heap initialized\n");
m->mallocing = 1; // tell rest of panic not to try to malloc
} else if(m->mcache == nil) // can happen if called from signal handler or throw
@@ -48,8 +48,13 @@ runtime_startpanic(void)
runtime_exit(3);
}
m->dying = 1;
+ if(runtime_g() != nil)
+ runtime_g()->writebuf = nil;
runtime_xadd(&runtime_panicking, 1);
runtime_lock(&paniclk);
+ if(runtime_debug.schedtrace > 0 || runtime_debug.scheddetail > 0)
+ runtime_schedtrace(true);
+ runtime_freezetheworld();
}
void
@@ -58,18 +63,22 @@ runtime_dopanic(int32 unused __attribute__ ((unused)))
G *g;
static bool didothers;
bool crash;
+ int32 t;
g = runtime_g();
if(g->sig != 0)
runtime_printf("[signal %x code=%p addr=%p]\n",
g->sig, (void*)g->sigcode0, (void*)g->sigcode1);
- if(runtime_gotraceback(&crash)){
+ if((t = runtime_gotraceback(&crash)) > 0){
if(g != runtime_m()->g0) {
runtime_printf("\n");
runtime_goroutineheader(g);
runtime_traceback();
- runtime_goroutinetrailer(g);
+ runtime_printcreatedby(g);
+ } else if(t >= 2 || runtime_m()->throwing > 0) {
+ runtime_printf("\nruntime stack:\n");
+ runtime_traceback();
}
if(!didothers) {
didothers = true;
@@ -113,11 +122,15 @@ runtime_panicstring(const char *s)
{
Eface err;
+ if(runtime_m()->mallocing) {
+ runtime_printf("panic: %s\n", s);
+ runtime_throw("panic during malloc");
+ }
if(runtime_m()->gcing) {
runtime_printf("panic: %s\n", s);
runtime_throw("panic during gc");
}
- runtime_newErrorString(runtime_gostringnocopy((const byte*)s), &err);
+ runtime_newErrorCString(s, &err);
runtime_panic(err);
}
diff --git a/libgo/runtime/parfor.c b/libgo/runtime/parfor.c
index c0e40f5081b..9489d8dc2ec 100644
--- a/libgo/runtime/parfor.c
+++ b/libgo/runtime/parfor.c
@@ -151,9 +151,9 @@ runtime_parfordo(ParFor *desc)
if(victim >= tid)
victim++;
victimpos = &desc->thr[victim].pos;
- pos = runtime_atomicload64(victimpos);
for(;;) {
// See if it has any work.
+ pos = runtime_atomicload64(victimpos);
begin = (uint32)pos;
end = (uint32)(pos>>32);
if(begin+1 >= end) {
@@ -166,7 +166,7 @@ runtime_parfordo(ParFor *desc)
}
begin2 = begin + (end-begin)/2;
newpos = (uint64)begin | (uint64)begin2<<32;
- if(runtime_cas64(victimpos, &pos, newpos)) {
+ if(runtime_cas64(victimpos, pos, newpos)) {
begin = begin2;
break;
}
diff --git a/libgo/runtime/print.c b/libgo/runtime/print.c
index f5c6e82840e..766ddbdc499 100644
--- a/libgo/runtime/print.c
+++ b/libgo/runtime/print.c
@@ -5,6 +5,7 @@
#include <stdarg.h>
#include "runtime.h"
#include "array.h"
+#include "go-type.h"
//static Lock debuglock;
@@ -13,7 +14,7 @@ static void go_vprintf(const char*, va_list);
// write to goroutine-local buffer if diverting output,
// or else standard error.
static void
-gwrite(const void *v, int32 n)
+gwrite(const void *v, intgo n)
{
G* g = runtime_g();
@@ -301,8 +302,6 @@ runtime_printpointer(void *p)
void
runtime_printstring(String v)
{
- // extern uint32 runtime_maxstring;
-
// if(v.len > runtime_maxstring) {
// gwrite("[string too long]", 17);
// return;
diff --git a/libgo/runtime/proc.c b/libgo/runtime/proc.c
index 0e77a3e0603..7011f14f8a5 100644
--- a/libgo/runtime/proc.c
+++ b/libgo/runtime/proc.c
@@ -231,8 +231,8 @@ kickoff(void)
}
// Switch context to a different goroutine. This is like longjmp.
-static void runtime_gogo(G*) __attribute__ ((noinline));
-static void
+void runtime_gogo(G*) __attribute__ ((noinline));
+void
runtime_gogo(G* newg)
{
#ifdef USING_SPLIT_STACK
@@ -249,8 +249,8 @@ runtime_gogo(G* newg)
// setjmp. Because getcontext always returns 0, unlike setjmp, we use
// g->fromgogo as a code. It will be true if we got here via
// setcontext. g == nil the first time this is called in a new m.
-static void runtime_mcall(void (*)(G*)) __attribute__ ((noinline));
-static void
+void runtime_mcall(void (*)(G*)) __attribute__ ((noinline));
+void
runtime_mcall(void (*pfn)(G*))
{
M *mp;
@@ -365,8 +365,9 @@ struct Sched {
uint64 goidgen;
M* midle; // idle m's waiting for work
int32 nmidle; // number of idle m's waiting for work
- int32 mlocked; // number of locked m's waiting for work
+ int32 nmidlelocked; // number of locked m's waiting for work
int32 mcount; // number of m's that have been created
+ int32 maxmcount; // maximum number of m's allowed (or die)
P* pidle; // idle P's
uint32 npidle;
@@ -381,6 +382,7 @@ struct Sched {
Lock gflock;
G* gfree;
+ uint32 gcwaiting; // gc is waiting to run
int32 stopwait;
Note stopnote;
uint32 sysmonwait;
@@ -396,10 +398,8 @@ enum { MaxGomaxprocs = 1<<8 };
Sched runtime_sched;
int32 runtime_gomaxprocs;
-bool runtime_singleproc;
-bool runtime_iscgo = true;
uint32 runtime_needextram = 1;
-uint32 runtime_gcwaiting;
+bool runtime_iscgo = true;
M runtime_m0;
G runtime_g0; // idle goroutine for m0
G* runtime_allg;
@@ -409,6 +409,7 @@ P** runtime_allp;
M* runtime_extram;
int8* runtime_goos;
int32 runtime_ncpu;
+bool runtime_precisestack;
static int32 newprocs;
void* runtime_mstart(void*);
@@ -431,21 +432,22 @@ static void wakep(void);
static void stoplockedm(void);
static void startlockedm(G*);
static void sysmon(void);
-static uint32 retake(uint32*);
-static void inclocked(int32);
+static uint32 retake(int64);
+static void incidlelocked(int32);
static void checkdead(void);
static void exitsyscall0(G*);
static void park0(G*);
-static void gosched0(G*);
static void goexit0(G*);
static void gfput(P*, G*);
static G* gfget(P*);
static void gfpurge(P*);
static void globrunqput(G*);
-static G* globrunqget(P*);
+static G* globrunqget(P*, int32);
static P* pidleget(void);
static void pidleput(P*);
static void injectglist(G*);
+static bool preemptall(void);
+static bool exitsyscallfast(void);
// The bootstrap sequence is:
//
@@ -460,6 +462,7 @@ runtime_schedinit(void)
{
int32 n, procs;
const byte *p;
+ Eface i;
m = &runtime_m0;
g = &runtime_g0;
@@ -470,18 +473,22 @@ runtime_schedinit(void)
initcontext();
inittlssize();
- m->nomemprof++;
+ runtime_sched.maxmcount = 10000;
+ runtime_precisestack = 0;
+
runtime_mprofinit();
runtime_mallocinit();
mcommoninit(m);
+
+ // Initialize the itable value for newErrorCString,
+ // so that the next time it gets called, possibly
+ // in a fault during a garbage collection, it will not
+ // need to allocated memory.
+ runtime_newErrorCString(0, &i);
runtime_goargs();
runtime_goenvs();
-
- // For debugging:
- // Allocate internal symbol table representation now,
- // so that we don't need to call malloc when we crash.
- // runtime_findfunc(0);
+ runtime_parsedebugvars();
runtime_sched.lastpoll = runtime_nanotime();
procs = 1;
@@ -496,16 +503,26 @@ runtime_schedinit(void)
// Can not enable GC until all roots are registered.
// mstats.enablegc = 1;
- m->nomemprof--;
+
+ // if(raceenabled)
+ // g->racectx = runtime_raceinit();
}
extern void main_init(void) __asm__ (GOSYM_PREFIX "__go_init_main");
extern void main_main(void) __asm__ (GOSYM_PREFIX "main.main");
+static void
+initDone(void *arg __attribute__ ((unused))) {
+ runtime_unlockOSThread();
+};
+
// The main goroutine.
void
runtime_main(void* dummy __attribute__((unused)))
{
+ Defer d;
+ _Bool frame;
+
newm(sysmon, nil);
// Lock the main goroutine onto this, the main OS thread,
@@ -515,10 +532,24 @@ runtime_main(void* dummy __attribute__((unused)))
// by calling runtime.LockOSThread during initialization
// to preserve the lock.
runtime_lockOSThread();
+
+ // Defer unlock so that runtime.Goexit during init does the unlock too.
+ d.__pfn = initDone;
+ d.__next = g->defer;
+ d.__arg = (void*)-1;
+ d.__panic = g->panic;
+ d.__retaddr = nil;
+ d.__frame = &frame;
+ g->defer = &d;
+
if(m != &runtime_m0)
runtime_throw("runtime_main not on m0");
__go_go(runtime_MHeap_Scavenger, nil);
main_init();
+
+ if(g->defer != &d || d.__pfn != initDone)
+ runtime_throw("runtime: bad defer entry after init");
+ g->defer = d.__next;
runtime_unlockOSThread();
// For gccgo we have to wait until after main is initialized
@@ -574,7 +605,7 @@ runtime_goroutineheader(G *gp)
}
void
-runtime_goroutinetrailer(G *g)
+runtime_printcreatedby(G *g)
{
if(g != nil && g->gopc != 0 && g->goid != 1) {
String fn;
@@ -604,8 +635,28 @@ runtime_tracebackothers(G * volatile me)
tb.gp = me;
traceback = runtime_gotraceback(nil);
+
+ // Show the current goroutine first, if we haven't already.
+ if((gp = m->curg) != nil && gp != me) {
+ runtime_printf("\n");
+ runtime_goroutineheader(gp);
+ gp->traceback = &tb;
+
+#ifdef USING_SPLIT_STACK
+ __splitstack_getcontext(&me->stack_context[0]);
+#endif
+ getcontext(&me->context);
+
+ if(gp->traceback != nil) {
+ runtime_gogo(gp);
+ }
+
+ runtime_printtrace(tb.locbuf, tb.c, false);
+ runtime_printcreatedby(gp);
+ }
+
for(gp = runtime_allg; gp != nil; gp = gp->alllink) {
- if(gp == me || gp->status == Gdead)
+ if(gp == me || gp == m->curg || gp->status == Gdead)
continue;
if(gp->issystem && traceback < 2)
continue;
@@ -620,25 +671,38 @@ runtime_tracebackothers(G * volatile me)
// This means that if g is running or in a syscall, we
// can't reliably print a stack trace. FIXME.
- if(gp->status == Gsyscall || gp->status == Grunning) {
- runtime_printf("no stack trace available\n");
- runtime_goroutinetrailer(gp);
- continue;
- }
- gp->traceback = &tb;
+ if(gp->status == Grunning) {
+ runtime_printf("\tgoroutine running on other thread; stack unavailable\n");
+ runtime_printcreatedby(gp);
+ } else if(gp->status == Gsyscall) {
+ runtime_printf("\tgoroutine in C code; stack unavailable\n");
+ runtime_printcreatedby(gp);
+ } else {
+ gp->traceback = &tb;
#ifdef USING_SPLIT_STACK
- __splitstack_getcontext(&me->stack_context[0]);
+ __splitstack_getcontext(&me->stack_context[0]);
#endif
- getcontext(&me->context);
+ getcontext(&me->context);
- if(gp->traceback != nil) {
- runtime_gogo(gp);
+ if(gp->traceback != nil) {
+ runtime_gogo(gp);
+ }
+
+ runtime_printtrace(tb.locbuf, tb.c, false);
+ runtime_printcreatedby(gp);
}
+ }
+}
- runtime_printtrace(tb.locbuf, tb.c, false);
- runtime_goroutinetrailer(gp);
+static void
+checkmcount(void)
+{
+ // sched lock is held
+ if(runtime_sched.mcount > runtime_sched.maxmcount) {
+ runtime_printf("runtime: program exceeds %d-thread limit\n", runtime_sched.maxmcount);
+ runtime_throw("thread exhaustion");
}
}
@@ -669,7 +733,7 @@ mcommoninit(M *mp)
runtime_lock(&runtime_sched);
mp->id = runtime_sched.mcount++;
-
+ checkmcount();
runtime_mpreinit(mp);
// Add to runtime_allm so garbage collector doesn't free m
@@ -686,6 +750,7 @@ void
runtime_ready(G *gp)
{
// Mark runnable.
+ m->locks++; // disable preemption because it can be holding p in a local var
if(gp->status != Gwaiting) {
runtime_printf("goroutine %D has status %d\n", gp->goid, gp->status);
runtime_throw("bad g->status in ready");
@@ -694,6 +759,7 @@ runtime_ready(G *gp)
runqput(m->p, gp);
if(runtime_atomicload(&runtime_sched.npidle) != 0 && runtime_atomicload(&runtime_sched.nmspinning) == 0) // TODO: fast atomic
wakep();
+ m->locks--;
}
int32
@@ -753,6 +819,34 @@ runtime_helpgc(int32 nproc)
runtime_unlock(&runtime_sched);
}
+// Similar to stoptheworld but best-effort and can be called several times.
+// There is no reverse operation, used during crashing.
+// This function must not lock any mutexes.
+void
+runtime_freezetheworld(void)
+{
+ int32 i;
+
+ if(runtime_gomaxprocs == 1)
+ return;
+ // stopwait and preemption requests can be lost
+ // due to races with concurrently executing threads,
+ // so try several times
+ for(i = 0; i < 5; i++) {
+ // this should tell the scheduler to not start any new goroutines
+ runtime_sched.stopwait = 0x7fffffff;
+ runtime_atomicstore((uint32*)&runtime_sched.gcwaiting, 1);
+ // this should stop running goroutines
+ if(!preemptall())
+ break; // no running goroutines
+ runtime_usleep(1000);
+ }
+ // to be sure
+ runtime_usleep(1000);
+ preemptall();
+ runtime_usleep(1000);
+}
+
void
runtime_stoptheworld(void)
{
@@ -763,7 +857,8 @@ runtime_stoptheworld(void)
runtime_lock(&runtime_sched);
runtime_sched.stopwait = runtime_gomaxprocs;
- runtime_atomicstore((uint32*)&runtime_gcwaiting, 1);
+ runtime_atomicstore((uint32*)&runtime_sched.gcwaiting, 1);
+ preemptall();
// stop current P
m->p->status = Pgcstop;
runtime_sched.stopwait--;
@@ -782,7 +877,7 @@ runtime_stoptheworld(void)
wait = runtime_sched.stopwait > 0;
runtime_unlock(&runtime_sched);
- // wait for remaining P's to stop voluntary
+ // wait for remaining P's to stop voluntarily
if(wait) {
runtime_notesleep(&runtime_sched.stopnote);
runtime_noteclear(&runtime_sched.stopnote);
@@ -810,6 +905,7 @@ runtime_starttheworld(void)
G *gp;
bool add;
+ m->locks++; // disable preemption because it can be holding p in a local var
gp = runtime_netpoll(false); // non-blocking
injectglist(gp);
add = needaddgcproc();
@@ -819,7 +915,7 @@ runtime_starttheworld(void)
newprocs = 0;
} else
procresize(runtime_gomaxprocs);
- runtime_gcwaiting = 0;
+ runtime_sched.gcwaiting = 0;
p1 = nil;
while((p = pidleget()) != nil) {
@@ -829,16 +925,9 @@ runtime_starttheworld(void)
pidleput(p);
break;
}
- mp = mget();
- if(mp == nil) {
- p->link = p1;
- p1 = p;
- continue;
- }
- if(mp->nextp)
- runtime_throw("starttheworld: inconsistent mp->nextp");
- mp->nextp = p;
- runtime_notewakeup(&mp->park);
+ p->m = mget();
+ p->link = p1;
+ p1 = p;
}
if(runtime_sched.sysmonwait) {
runtime_sched.sysmonwait = false;
@@ -849,8 +938,18 @@ runtime_starttheworld(void)
while(p1) {
p = p1;
p1 = p1->link;
- add = false;
- newm(nil, p);
+ if(p->m) {
+ mp = p->m;
+ p->m = nil;
+ if(mp->nextp)
+ runtime_throw("starttheworld: inconsistent mp->nextp");
+ mp->nextp = p;
+ runtime_notewakeup(&mp->park);
+ } else {
+ // Start M to run P. Do not start another M below.
+ newm(nil, p);
+ add = false;
+ }
}
if(add) {
@@ -863,6 +962,7 @@ runtime_starttheworld(void)
// the maximum number of procs.
newm(mhelpgc, nil);
}
+ m->locks--;
}
// Called to start an M.
@@ -909,11 +1009,8 @@ runtime_mstart(void* mp)
// Install signal handlers; after minit so that minit can
// prepare the thread to be able to handle the signals.
- if(m == &runtime_m0) {
+ if(m == &runtime_m0)
runtime_initsig();
- if(runtime_iscgo)
- runtime_newextram();
- }
if(m->mstartfn)
m->mstartfn();
@@ -1015,6 +1112,14 @@ runtime_needm(void)
{
M *mp;
+ if(runtime_needextram) {
+ // Can happen if C/C++ code calls Go from a global ctor.
+ // Can not throw, because scheduler is not initialized yet.
+ runtime_write(2, "fatal error: cgo callback before cgo call\n",
+ sizeof("fatal error: cgo callback before cgo call\n")-1);
+ runtime_exit(1);
+ }
+
// Lock extra list, take head, unlock popped list.
// nilokay=false is safe here because of the invariant above,
// that the extra list always contains or will soon contain
@@ -1090,6 +1195,7 @@ runtime_newextram(void)
mp->locked = LockInternal;
mp->lockedg = gp;
gp->lockedm = mp;
+ gp->goid = runtime_xadd64(&runtime_sched.goidgen, 1);
// put on allg for garbage collector
runtime_lock(&runtime_sched);
if(runtime_lastg == nil)
@@ -1325,7 +1431,7 @@ handoffp(P *p)
return;
}
runtime_lock(&runtime_sched);
- if(runtime_gcwaiting) {
+ if(runtime_sched.gcwaiting) {
p->status = Pgcstop;
if(--runtime_sched.stopwait == 0)
runtime_notewakeup(&runtime_sched.stopnote);
@@ -1373,7 +1479,7 @@ stoplockedm(void)
p = releasep();
handoffp(p);
}
- inclocked(1);
+ incidlelocked(1);
// Wait until another thread schedules lockedg again.
runtime_notesleep(&m->park);
runtime_noteclear(&m->park);
@@ -1396,7 +1502,7 @@ startlockedm(G *gp)
if(mp->nextp)
runtime_throw("startlockedm: m has p");
// directly handoff current P to the locked m
- inclocked(-1);
+ incidlelocked(-1);
p = releasep();
mp->nextp = p;
runtime_notewakeup(&mp->park);
@@ -1410,7 +1516,7 @@ gcstopm(void)
{
P *p;
- if(!runtime_gcwaiting)
+ if(!runtime_sched.gcwaiting)
runtime_throw("gcstopm: not waiting for gc");
if(m->spinning) {
m->spinning = false;
@@ -1437,7 +1543,7 @@ execute(G *gp)
runtime_throw("execute: bad g status");
}
gp->status = Grunning;
- m->p->tick++;
+ m->p->schedtick++;
m->curg = gp;
gp->m = m;
@@ -1459,7 +1565,7 @@ findrunnable(void)
int32 i;
top:
- if(runtime_gcwaiting) {
+ if(runtime_sched.gcwaiting) {
gcstopm();
goto top;
}
@@ -1470,7 +1576,7 @@ top:
// global runq
if(runtime_sched.runqsize) {
runtime_lock(&runtime_sched);
- gp = globrunqget(m->p);
+ gp = globrunqget(m->p, 0);
runtime_unlock(&runtime_sched);
if(gp)
return gp;
@@ -1493,7 +1599,7 @@ top:
}
// random steal from other P's
for(i = 0; i < 2*runtime_gomaxprocs; i++) {
- if(runtime_gcwaiting)
+ if(runtime_sched.gcwaiting)
goto top;
p = runtime_allp[runtime_fastrand1()%runtime_gomaxprocs];
if(p == m->p)
@@ -1506,12 +1612,12 @@ top:
stop:
// return P and block
runtime_lock(&runtime_sched);
- if(runtime_gcwaiting) {
+ if(runtime_sched.gcwaiting) {
runtime_unlock(&runtime_sched);
goto top;
}
if(runtime_sched.runqsize) {
- gp = globrunqget(m->p);
+ gp = globrunqget(m->p, 0);
runtime_unlock(&runtime_sched);
return gp;
}
@@ -1561,6 +1667,25 @@ stop:
goto top;
}
+static void
+resetspinning(void)
+{
+ int32 nmspinning;
+
+ if(m->spinning) {
+ m->spinning = false;
+ nmspinning = runtime_xadd(&runtime_sched.nmspinning, -1);
+ if(nmspinning < 0)
+ runtime_throw("findrunnable: negative nmspinning");
+ } else
+ nmspinning = runtime_atomicload(&runtime_sched.nmspinning);
+
+ // M wakeup policy is deliberately somewhat conservative (see nmspinning handling),
+ // so see if we need to wakeup another P here.
+ if (nmspinning == 0 && runtime_atomicload(&runtime_sched.npidle) > 0)
+ wakep();
+}
+
// Injects the list of runnable G's into the scheduler.
// Can run concurrently with GC.
static void
@@ -1590,33 +1715,44 @@ static void
schedule(void)
{
G *gp;
+ uint32 tick;
if(m->locks)
runtime_throw("schedule: holding locks");
top:
- if(runtime_gcwaiting) {
+ if(runtime_sched.gcwaiting) {
gcstopm();
goto top;
}
- gp = runqget(m->p);
- if(gp == nil)
- gp = findrunnable();
-
- if(m->spinning) {
- m->spinning = false;
- runtime_xadd(&runtime_sched.nmspinning, -1);
+ gp = nil;
+ // Check the global runnable queue once in a while to ensure fairness.
+ // Otherwise two goroutines can completely occupy the local runqueue
+ // by constantly respawning each other.
+ tick = m->p->schedtick;
+ // This is a fancy way to say tick%61==0,
+ // it uses 2 MUL instructions instead of a single DIV and so is faster on modern processors.
+ if(tick - (((uint64)tick*0x4325c53fu)>>36)*61 == 0 && runtime_sched.runqsize > 0) {
+ runtime_lock(&runtime_sched);
+ gp = globrunqget(m->p, 1);
+ runtime_unlock(&runtime_sched);
+ if(gp)
+ resetspinning();
+ }
+ if(gp == nil) {
+ gp = runqget(m->p);
+ if(gp && m->spinning)
+ runtime_throw("schedule: spinning with local work");
+ }
+ if(gp == nil) {
+ gp = findrunnable(); // blocks until work is available
+ resetspinning();
}
-
- // M wakeup policy is deliberately somewhat conservative (see nmspinning handling),
- // so see if we need to wakeup another M here.
- if (m->p->runqhead != m->p->runqtail &&
- runtime_atomicload(&runtime_sched.nmspinning) == 0 &&
- runtime_atomicload(&runtime_sched.npidle) > 0) // TODO: fast atomic
- wakep();
if(gp->lockedm) {
+ // Hands off own p to the locked m,
+ // then blocks waiting for a new p.
startlockedm(gp);
goto top;
}
@@ -1658,12 +1794,12 @@ park0(G *gp)
void
runtime_gosched(void)
{
- runtime_mcall(gosched0);
+ runtime_mcall(runtime_gosched0);
}
// runtime_gosched continuation on g0.
-static void
-gosched0(G *gp)
+void
+runtime_gosched0(G *gp)
{
gp->status = Grunnable;
gp->m = nil;
@@ -1679,6 +1815,9 @@ gosched0(G *gp)
}
// Finishes execution of the current goroutine.
+// Need to mark it as nosplit, because it runs with sp > stackbase (as runtime_lessstack).
+// Since it does not return it does not matter. But if it is preempted
+// at the split stack check, GC will complain about inconsistent sp.
void
runtime_goexit(void)
{
@@ -1698,7 +1837,7 @@ goexit0(G *gp)
m->curg = nil;
m->lockedg = nil;
if(m->locked & ~LockExternal) {
- runtime_printf("invalid m->locked = %d", m->locked);
+ runtime_printf("invalid m->locked = %d\n", m->locked);
runtime_throw("internal lockOSThread error");
}
m->locked = 0;
@@ -1720,10 +1859,11 @@ void runtime_entersyscall(void) __attribute__ ((no_split_stack));
void
runtime_entersyscall()
{
- if(m->profilehz > 0)
- runtime_setprof(false);
+ // Disable preemption because during this function g is in Gsyscall status,
+ // but can have inconsistent g->sched, do not let GC observe it.
+ m->locks++;
- // Leave SP around for gc and traceback.
+ // Leave SP around for GC and traceback.
#ifdef USING_SPLIT_STACK
g->gcstack = __splitstack_find(nil, nil, &g->gcstack_size,
&g->gcnext_segment, &g->gcnext_sp,
@@ -1752,10 +1892,9 @@ runtime_entersyscall()
}
m->mcache = nil;
- m->p->tick++;
m->p->m = nil;
runtime_atomicstore(&m->p->status, Psyscall);
- if(runtime_gcwaiting) {
+ if(runtime_sched.gcwaiting) {
runtime_lock(&runtime_sched);
if (runtime_sched.stopwait > 0 && runtime_cas(&m->p->status, Psyscall, Pgcstop)) {
if(--runtime_sched.stopwait == 0)
@@ -1763,6 +1902,8 @@ runtime_entersyscall()
}
runtime_unlock(&runtime_sched);
}
+
+ m->locks--;
}
// The same as runtime_entersyscall(), but with a hint that the syscall is blocking.
@@ -1771,10 +1912,9 @@ runtime_entersyscallblock(void)
{
P *p;
- if(m->profilehz > 0)
- runtime_setprof(false);
+ m->locks++; // see comment in entersyscall
- // Leave SP around for gc and traceback.
+ // Leave SP around for GC and traceback.
#ifdef USING_SPLIT_STACK
g->gcstack = __splitstack_find(nil, nil, &g->gcstack_size,
&g->gcnext_segment, &g->gcnext_sp,
@@ -1792,7 +1932,9 @@ runtime_entersyscallblock(void)
p = releasep();
handoffp(p);
if(g->isbackground) // do not consider blocked scavenger for deadlock detection
- inclocked(1);
+ incidlelocked(1);
+
+ m->locks--;
}
// The goroutine g exited its system call.
@@ -1803,19 +1945,16 @@ void
runtime_exitsyscall(void)
{
G *gp;
- P *p;
- // Check whether the profiler needs to be turned on.
- if(m->profilehz > 0)
- runtime_setprof(true);
+ m->locks++; // see comment in entersyscall
gp = g;
- // Try to re-acquire the last P.
- if(m->p && m->p->status == Psyscall && runtime_cas(&m->p->status, Psyscall, Prunning)) {
+ if(gp->isbackground) // do not consider blocked scavenger for deadlock detection
+ incidlelocked(-1);
+
+ if(exitsyscallfast()) {
// There's a cpu for us, so we can run.
- m->mcache = m->p->mcache;
- m->p->m = m;
- m->p->tick++;
+ m->p->syscalltick++;
gp->status = Grunning;
// Garbage collector isn't running (since we are),
// so okay to clear gcstack and gcsp.
@@ -1824,27 +1963,11 @@ runtime_exitsyscall(void)
#endif
gp->gcnext_sp = nil;
runtime_memclr(&gp->gcregs, sizeof gp->gcregs);
+ m->locks--;
return;
}
- if(gp->isbackground) // do not consider blocked scavenger for deadlock detection
- inclocked(-1);
- // Try to get any other idle P.
- m->p = nil;
- if(runtime_sched.pidle) {
- runtime_lock(&runtime_sched);
- p = pidleget();
- runtime_unlock(&runtime_sched);
- if(p) {
- acquirep(p);
-#ifdef USING_SPLIT_STACK
- gp->gcstack = nil;
-#endif
- gp->gcnext_sp = nil;
- runtime_memclr(&gp->gcregs, sizeof gp->gcregs);
- return;
- }
- }
+ m->locks--;
// Call the scheduler.
runtime_mcall(exitsyscall0);
@@ -1860,6 +1983,43 @@ runtime_exitsyscall(void)
#endif
gp->gcnext_sp = nil;
runtime_memclr(&gp->gcregs, sizeof gp->gcregs);
+ m->p->syscalltick++;
+}
+
+static bool
+exitsyscallfast(void)
+{
+ P *p;
+
+ // Freezetheworld sets stopwait but does not retake P's.
+ if(runtime_sched.stopwait) {
+ m->p = nil;
+ return false;
+ }
+
+ // Try to re-acquire the last P.
+ if(m->p && m->p->status == Psyscall && runtime_cas(&m->p->status, Psyscall, Prunning)) {
+ // There's a cpu for us, so we can run.
+ m->mcache = m->p->mcache;
+ m->p->m = m;
+ return true;
+ }
+ // Try to get any other idle P.
+ m->p = nil;
+ if(runtime_sched.pidle) {
+ runtime_lock(&runtime_sched);
+ p = pidleget();
+ if(p && runtime_atomicload(&runtime_sched.sysmonwait)) {
+ runtime_atomicstore(&runtime_sched.sysmonwait, 0);
+ runtime_notewakeup(&runtime_sched.sysmonnote);
+ }
+ runtime_unlock(&runtime_sched);
+ if(p) {
+ acquirep(p);
+ return true;
+ }
+ }
+ return false;
}
// runtime_exitsyscall slow path on g0.
@@ -1876,6 +2036,10 @@ exitsyscall0(G *gp)
p = pidleget();
if(p == nil)
globrunqput(gp);
+ else if(runtime_atomicload(&runtime_sched.sysmonwait)) {
+ runtime_atomicstore(&runtime_sched.sysmonwait, 0);
+ runtime_notewakeup(&runtime_sched.sysmonnote);
+ }
runtime_unlock(&runtime_sched);
if(p) {
acquirep(p);
@@ -1890,6 +2054,33 @@ exitsyscall0(G *gp)
schedule(); // Never returns.
}
+// Called from syscall package before fork.
+void syscall_runtime_BeforeFork(void)
+ __asm__(GOSYM_PREFIX "syscall.runtime_BeforeFork");
+void
+syscall_runtime_BeforeFork(void)
+{
+ // Fork can hang if preempted with signals frequently enough (see issue 5517).
+ // Ensure that we stay on the same M where we disable profiling.
+ m->locks++;
+ if(m->profilehz != 0)
+ runtime_resetcpuprofiler(0);
+}
+
+// Called from syscall package after fork in parent.
+void syscall_runtime_AfterFork(void)
+ __asm__(GOSYM_PREFIX "syscall.runtime_AfterFork");
+void
+syscall_runtime_AfterFork(void)
+{
+ int32 hz;
+
+ hz = runtime_sched.profilehz;
+ if(hz != 0)
+ runtime_resetcpuprofiler(hz);
+ m->locks--;
+}
+
// Allocate a new g, with a stack big enough for stacksize bytes.
G*
runtime_malg(int32 stacksize, byte** ret_stack, size_t* ret_stacksize)
@@ -1907,7 +2098,7 @@ runtime_malg(int32 stacksize, byte** ret_stack, size_t* ret_stacksize)
__splitstack_block_signals_context(&newg->stack_context[0],
&dont_block_signals, nil);
#else
- *ret_stack = runtime_mallocgc(stacksize, FlagNoProfiling|FlagNoGC, 0, 0);
+ *ret_stack = runtime_mallocgc(stacksize, 0, FlagNoProfiling|FlagNoGC);
*ret_stacksize = stacksize;
newg->gcinitial_sp = *ret_stack;
newg->gcstack_size = stacksize;
@@ -1919,9 +2110,16 @@ runtime_malg(int32 stacksize, byte** ret_stack, size_t* ret_stacksize)
/* For runtime package testing. */
+
+// Create a new g running fn with siz bytes of arguments.
+// Put it on the queue of g's waiting to run.
+// The compiler turns a go statement into a call to this.
+// Cannot split the stack because it assumes that the arguments
+// are available sequentially after &fn; they would not be
+// copied if a stack split occurred. It's OK for this to call
+// functions that split the stack.
void runtime_testing_entersyscall(void)
__asm__ (GOSYM_PREFIX "runtime.entersyscall");
-
void
runtime_testing_entersyscall()
{
@@ -1944,6 +2142,7 @@ __go_go(void (*fn)(void*), void* arg)
size_t spsize;
G *newg;
+//runtime_printf("newproc1 %p %p narg=%d nret=%d\n", fn->fn, argp, narg, nret);
m->locks++; // disable preemption because it can be holding p in a local var
if((newg = gfget(m->p)) != nil) {
@@ -2099,7 +2298,7 @@ runtime_gomaxprocsfunc(int32 n)
}
runtime_unlock(&runtime_sched);
- runtime_semacquire(&runtime_worldsema);
+ runtime_semacquire(&runtime_worldsema, false);
m->gcing = 1;
runtime_stoptheworld();
newprocs = n;
@@ -2110,8 +2309,11 @@ runtime_gomaxprocsfunc(int32 n)
return ret;
}
+// lockOSThread is called by runtime.LockOSThread and runtime.lockOSThread below
+// after they modify m->locked. Do not allow preemption during this call,
+// or else the m might be different in this function than in the caller.
static void
-LockOSThread(void)
+lockOSThread(void)
{
m->lockedg = g;
g->lockedm = m;
@@ -2122,18 +2324,22 @@ void
runtime_LockOSThread(void)
{
m->locked |= LockExternal;
- LockOSThread();
+ lockOSThread();
}
void
runtime_lockOSThread(void)
{
m->locked += LockInternal;
- LockOSThread();
+ lockOSThread();
}
+
+// unlockOSThread is called by runtime.UnlockOSThread and runtime.unlockOSThread below
+// after they update m->locked. Do not allow preemption during this call,
+// or else the m might be in different in this function than in the caller.
static void
-UnlockOSThread(void)
+unlockOSThread(void)
{
if(m->locked != 0)
return;
@@ -2147,7 +2353,7 @@ void
runtime_UnlockOSThread(void)
{
m->locked &= ~LockExternal;
- UnlockOSThread();
+ unlockOSThread();
}
void
@@ -2156,7 +2362,7 @@ runtime_unlockOSThread(void)
if(m->locked < LockInternal)
runtime_throw("runtime: internal error: misuse of lockOSThread/unlockOSThread");
m->locked -= LockInternal;
- UnlockOSThread();
+ unlockOSThread();
}
bool
@@ -2176,13 +2382,6 @@ runtime_golockedOSThread(void)
return runtime_lockedOSThread();
}
-// for testing of wire, unwire
-uint32
-runtime_mid()
-{
- return m->id;
-}
-
intgo runtime_NumGoroutine (void)
__asm__ (GOSYM_PREFIX "runtime.NumGoroutine");
@@ -2227,28 +2426,42 @@ static struct {
Location locbuf[100];
} prof;
+static void
+System(void)
+{
+}
+
// Called if we receive a SIGPROF signal.
void
runtime_sigprof()
{
int32 n, i;
+ bool traceback;
- // Windows does profiling in a dedicated thread w/o m.
- if(!Windows && (m == nil || m->mcache == nil))
- return;
if(prof.fn == nil || prof.hz == 0)
return;
-
+ traceback = true;
+ // Windows does profiling in a dedicated thread w/o m.
+ if(!Windows && (m == nil || m->mcache == nil))
+ traceback = false;
+
runtime_lock(&prof);
if(prof.fn == nil) {
runtime_unlock(&prof);
return;
}
- n = runtime_callers(0, prof.locbuf, nelem(prof.locbuf));
- for(i = 0; i < n; i++)
- prof.pcbuf[i] = prof.locbuf[i].pc;
- if(n > 0)
- prof.fn(prof.pcbuf, n);
+ n = 0;
+ if(traceback) {
+ n = runtime_callers(0, prof.locbuf, nelem(prof.locbuf));
+ for(i = 0; i < n; i++)
+ prof.pcbuf[i] = prof.locbuf[i].pc;
+ }
+ if (!traceback || n <= 0) {
+ n = 2;
+ prof.pcbuf[0] = (uintptr)runtime_getcallerpc(&n);
+ prof.pcbuf[1] = (uintptr)System + 1;
+ }
+ prof.fn(prof.pcbuf, n);
runtime_unlock(&prof);
}
@@ -2264,7 +2477,11 @@ runtime_setcpuprofilerate(void (*fn)(uintptr*, int32), int32 hz)
if(fn == nil)
hz = 0;
- // Stop profiler on this cpu so that it is safe to lock prof.
+ // Disable preemption, otherwise we can be rescheduled to another thread
+ // that has profiling enabled.
+ m->locks++;
+
+ // Stop profiler on this thread so that it is safe to lock prof.
// if a profiling signal came in while we had prof locked,
// it would deadlock.
runtime_resetcpuprofiler(0);
@@ -2279,6 +2496,8 @@ runtime_setcpuprofilerate(void (*fn)(uintptr*, int32), int32 hz)
if(hz != 0)
runtime_resetcpuprofiler(hz);
+
+ m->locks--;
}
// Change number of processors. The world is stopped, sched is locked.
@@ -2296,7 +2515,8 @@ procresize(int32 new)
for(i = 0; i < new; i++) {
p = runtime_allp[i];
if(p == nil) {
- p = (P*)runtime_mallocgc(sizeof(*p), 0, 0, 1);
+ p = (P*)runtime_mallocgc(sizeof(*p), 0, FlagNoInvokeGC);
+ p->id = i;
p->status = Pgcstop;
runtime_atomicstorep(&runtime_allp[i], p);
}
@@ -2308,7 +2528,7 @@ procresize(int32 new)
}
if(p->runq == nil) {
p->runqsize = 128;
- p->runq = (G**)runtime_mallocgc(p->runqsize*sizeof(G*), 0, 0, 1);
+ p->runq = (G**)runtime_mallocgc(p->runqsize*sizeof(G*), 0, FlagNoInvokeGC);
}
}
@@ -2351,7 +2571,6 @@ procresize(int32 new)
p->status = Pidle;
pidleput(p);
}
- runtime_singleproc = new == 1;
runtime_atomicstore((uint32*)&runtime_gomaxprocs, new);
}
@@ -2393,10 +2612,10 @@ releasep(void)
}
static void
-inclocked(int32 v)
+incidlelocked(int32 v)
{
runtime_lock(&runtime_sched);
- runtime_sched.mlocked += v;
+ runtime_sched.nmidlelocked += v;
if(v > 0)
checkdead();
runtime_unlock(&runtime_sched);
@@ -2411,12 +2630,12 @@ checkdead(void)
int32 run, grunning, s;
// -1 for sysmon
- run = runtime_sched.mcount - runtime_sched.nmidle - runtime_sched.mlocked - 1 - countextra();
+ run = runtime_sched.mcount - runtime_sched.nmidle - runtime_sched.nmidlelocked - 1 - countextra();
if(run > 0)
return;
if(run < 0) {
- runtime_printf("checkdead: nmidle=%d mlocked=%d mcount=%d\n",
- runtime_sched.nmidle, runtime_sched.mlocked, runtime_sched.mcount);
+ runtime_printf("checkdead: nmidle=%d nmidlelocked=%d mcount=%d\n",
+ runtime_sched.nmidle, runtime_sched.nmidlelocked, runtime_sched.mcount);
runtime_throw("checkdead: inconsistent counts");
}
grunning = 0;
@@ -2441,10 +2660,10 @@ static void
sysmon(void)
{
uint32 idle, delay;
- int64 now, lastpoll;
+ int64 now, lastpoll, lasttrace;
G *gp;
- uint32 ticks[MaxGomaxprocs];
+ lasttrace = 0;
idle = 0; // how many cycles in succession we had not wokeup somebody
delay = 0;
for(;;) {
@@ -2455,9 +2674,10 @@ sysmon(void)
if(delay > 10*1000) // up to 10ms
delay = 10*1000;
runtime_usleep(delay);
- if(runtime_gcwaiting || runtime_atomicload(&runtime_sched.npidle) == (uint32)runtime_gomaxprocs) { // TODO: fast atomic
+ if(runtime_debug.schedtrace <= 0 &&
+ (runtime_sched.gcwaiting || runtime_atomicload(&runtime_sched.npidle) == (uint32)runtime_gomaxprocs)) { // TODO: fast atomic
runtime_lock(&runtime_sched);
- if(runtime_atomicload(&runtime_gcwaiting) || runtime_atomicload(&runtime_sched.npidle) == (uint32)runtime_gomaxprocs) {
+ if(runtime_atomicload(&runtime_sched.gcwaiting) || runtime_atomicload(&runtime_sched.npidle) == (uint32)runtime_gomaxprocs) {
runtime_atomicstore(&runtime_sched.sysmonwait, 1);
runtime_unlock(&runtime_sched);
runtime_notesleep(&runtime_sched.sysmonnote);
@@ -2470,53 +2690,198 @@ sysmon(void)
// poll network if not polled for more than 10ms
lastpoll = runtime_atomicload64(&runtime_sched.lastpoll);
now = runtime_nanotime();
- if(lastpoll != 0 && lastpoll + 10*1000*1000 > now) {
+ if(lastpoll != 0 && lastpoll + 10*1000*1000 < now) {
+ runtime_cas64(&runtime_sched.lastpoll, lastpoll, now);
gp = runtime_netpoll(false); // non-blocking
- injectglist(gp);
+ if(gp) {
+ // Need to decrement number of idle locked M's
+ // (pretending that one more is running) before injectglist.
+ // Otherwise it can lead to the following situation:
+ // injectglist grabs all P's but before it starts M's to run the P's,
+ // another M returns from syscall, finishes running its G,
+ // observes that there is no work to do and no other running M's
+ // and reports deadlock.
+ incidlelocked(-1);
+ injectglist(gp);
+ incidlelocked(1);
+ }
}
// retake P's blocked in syscalls
- if(retake(ticks))
+ // and preempt long running G's
+ if(retake(now))
idle = 0;
else
idle++;
+
+ if(runtime_debug.schedtrace > 0 && lasttrace + runtime_debug.schedtrace*1000000ll <= now) {
+ lasttrace = now;
+ runtime_schedtrace(runtime_debug.scheddetail);
+ }
}
}
+typedef struct Pdesc Pdesc;
+struct Pdesc
+{
+ uint32 schedtick;
+ int64 schedwhen;
+ uint32 syscalltick;
+ int64 syscallwhen;
+};
+static Pdesc pdesc[MaxGomaxprocs];
+
static uint32
-retake(uint32 *ticks)
+retake(int64 now)
{
uint32 i, s, n;
int64 t;
P *p;
+ Pdesc *pd;
n = 0;
for(i = 0; i < (uint32)runtime_gomaxprocs; i++) {
p = runtime_allp[i];
if(p==nil)
continue;
- t = p->tick;
- if(ticks[i] != t) {
- ticks[i] = t;
- continue;
- }
+ pd = &pdesc[i];
s = p->status;
- if(s != Psyscall)
- continue;
- if(p->runqhead == p->runqtail && runtime_atomicload(&runtime_sched.nmspinning) + runtime_atomicload(&runtime_sched.npidle) > 0) // TODO: fast atomic
- continue;
- // Need to increment number of locked M's before the CAS.
- // Otherwise the M from which we retake can exit the syscall,
- // increment nmidle and report deadlock.
- inclocked(-1);
- if(runtime_cas(&p->status, s, Pidle)) {
- n++;
- handoffp(p);
+ if(s == Psyscall) {
+ // Retake P from syscall if it's there for more than 1 sysmon tick (20us).
+ // But only if there is other work to do.
+ t = p->syscalltick;
+ if(pd->syscalltick != t) {
+ pd->syscalltick = t;
+ pd->syscallwhen = now;
+ continue;
+ }
+ if(p->runqhead == p->runqtail &&
+ runtime_atomicload(&runtime_sched.nmspinning) + runtime_atomicload(&runtime_sched.npidle) > 0)
+ continue;
+ // Need to decrement number of idle locked M's
+ // (pretending that one more is running) before the CAS.
+ // Otherwise the M from which we retake can exit the syscall,
+ // increment nmidle and report deadlock.
+ incidlelocked(-1);
+ if(runtime_cas(&p->status, s, Pidle)) {
+ n++;
+ handoffp(p);
+ }
+ incidlelocked(1);
+ } else if(s == Prunning) {
+ // Preempt G if it's running for more than 10ms.
+ t = p->schedtick;
+ if(pd->schedtick != t) {
+ pd->schedtick = t;
+ pd->schedwhen = now;
+ continue;
+ }
+ if(pd->schedwhen + 10*1000*1000 > now)
+ continue;
+ // preemptone(p);
}
- inclocked(1);
}
return n;
}
+// Tell all goroutines that they have been preempted and they should stop.
+// This function is purely best-effort. It can fail to inform a goroutine if a
+// processor just started running it.
+// No locks need to be held.
+// Returns true if preemption request was issued to at least one goroutine.
+static bool
+preemptall(void)
+{
+ return false;
+}
+
+void
+runtime_schedtrace(bool detailed)
+{
+ static int64 starttime;
+ int64 now;
+ int64 id1, id2, id3;
+ int32 i, q, t, h, s;
+ const char *fmt;
+ M *mp, *lockedm;
+ G *gp, *lockedg;
+ P *p;
+
+ now = runtime_nanotime();
+ if(starttime == 0)
+ starttime = now;
+
+ runtime_lock(&runtime_sched);
+ runtime_printf("SCHED %Dms: gomaxprocs=%d idleprocs=%d threads=%d idlethreads=%d runqueue=%d",
+ (now-starttime)/1000000, runtime_gomaxprocs, runtime_sched.npidle, runtime_sched.mcount,
+ runtime_sched.nmidle, runtime_sched.runqsize);
+ if(detailed) {
+ runtime_printf(" gcwaiting=%d nmidlelocked=%d nmspinning=%d stopwait=%d sysmonwait=%d\n",
+ runtime_sched.gcwaiting, runtime_sched.nmidlelocked, runtime_sched.nmspinning,
+ runtime_sched.stopwait, runtime_sched.sysmonwait);
+ }
+ // We must be careful while reading data from P's, M's and G's.
+ // Even if we hold schedlock, most data can be changed concurrently.
+ // E.g. (p->m ? p->m->id : -1) can crash if p->m changes from non-nil to nil.
+ for(i = 0; i < runtime_gomaxprocs; i++) {
+ p = runtime_allp[i];
+ if(p == nil)
+ continue;
+ mp = p->m;
+ t = p->runqtail;
+ h = p->runqhead;
+ s = p->runqsize;
+ q = t - h;
+ if(q < 0)
+ q += s;
+ if(detailed)
+ runtime_printf(" P%d: status=%d schedtick=%d syscalltick=%d m=%d runqsize=%d/%d gfreecnt=%d\n",
+ i, p->status, p->schedtick, p->syscalltick, mp ? mp->id : -1, q, s, p->gfreecnt);
+ else {
+ // In non-detailed mode format lengths of per-P run queues as:
+ // [len1 len2 len3 len4]
+ fmt = " %d";
+ if(runtime_gomaxprocs == 1)
+ fmt = " [%d]\n";
+ else if(i == 0)
+ fmt = " [%d";
+ else if(i == runtime_gomaxprocs-1)
+ fmt = " %d]\n";
+ runtime_printf(fmt, q);
+ }
+ }
+ if(!detailed) {
+ runtime_unlock(&runtime_sched);
+ return;
+ }
+ for(mp = runtime_allm; mp; mp = mp->alllink) {
+ p = mp->p;
+ gp = mp->curg;
+ lockedg = mp->lockedg;
+ id1 = -1;
+ if(p)
+ id1 = p->id;
+ id2 = -1;
+ if(gp)
+ id2 = gp->goid;
+ id3 = -1;
+ if(lockedg)
+ id3 = lockedg->goid;
+ runtime_printf(" M%d: p=%D curg=%D mallocing=%d throwing=%d gcing=%d"
+ " locks=%d dying=%d helpgc=%d spinning=%d lockedg=%D\n",
+ mp->id, id1, id2,
+ mp->mallocing, mp->throwing, mp->gcing, mp->locks, mp->dying, mp->helpgc,
+ mp->spinning, id3);
+ }
+ for(gp = runtime_allg; gp; gp = gp->alllink) {
+ mp = gp->m;
+ lockedm = gp->lockedm;
+ runtime_printf(" G%D: status=%d(%s) m=%d lockedm=%d\n",
+ gp->goid, gp->status, gp->waitreason, mp ? mp->id : -1,
+ lockedm ? lockedm->id : -1);
+ }
+ runtime_unlock(&runtime_sched);
+}
+
// Put mp on midle list.
// Sched must be locked.
static void
@@ -2559,7 +2924,7 @@ globrunqput(G *gp)
// Try get a batch of G's from the global runnable queue.
// Sched must be locked.
static G*
-globrunqget(P *p)
+globrunqget(P *p, int32 max)
{
G *gp, *gp1;
int32 n;
@@ -2569,6 +2934,8 @@ globrunqget(P *p)
n = runtime_sched.runqsize/runtime_gomaxprocs+1;
if(n > runtime_sched.runqsize)
n = runtime_sched.runqsize;
+ if(max > 0 && n > max)
+ n = max;
runtime_sched.runqsize -= n;
if(runtime_sched.runqsize == 0)
runtime_sched.runqtail = nil;
@@ -2827,6 +3194,22 @@ runtime_testSchedLocalQueueSteal(void)
}
}
+intgo runtime_debug_setMaxThreads(intgo)
+ __asm__(GOSYM_PREFIX "runtime_debug.setMaxThreads");
+
+intgo
+runtime_debug_setMaxThreads(intgo in)
+{
+ intgo out;
+
+ runtime_lock(&runtime_sched);
+ out = runtime_sched.maxmcount;
+ runtime_sched.maxmcount = in;
+ checkmcount();
+ runtime_unlock(&runtime_sched);
+ return out;
+}
+
void
runtime_proc_scan(void (*addroot)(Obj))
{
@@ -2852,3 +3235,11 @@ __go_get_closure(void)
{
return g->closure;
}
+
+// Return whether we are waiting for a GC. This gc toolchain uses
+// preemption instead.
+bool
+runtime_gcwaiting(void)
+{
+ return runtime_sched.gcwaiting;
+}
diff --git a/libgo/runtime/race.h b/libgo/runtime/race.h
index 3357bed312d..884245cedad 100644
--- a/libgo/runtime/race.h
+++ b/libgo/runtime/race.h
@@ -16,14 +16,14 @@ uintptr runtime_raceinit(void);
void runtime_racefini(void);
void runtime_racemapshadow(void *addr, uintptr size);
-void runtime_racemalloc(void *p, uintptr sz, void *pc);
+void runtime_racemalloc(void *p, uintptr sz);
void runtime_racefree(void *p);
uintptr runtime_racegostart(void *pc);
void runtime_racegoend(void);
void runtime_racewritepc(void *addr, void *callpc, void *pc);
void runtime_racereadpc(void *addr, void *callpc, void *pc);
-void runtime_racewriterangepc(void *addr, uintptr sz, uintptr step, void *callpc, void *pc);
-void runtime_racereadrangepc(void *addr, uintptr sz, uintptr step, void *callpc, void *pc);
+void runtime_racewriterangepc(void *addr, uintptr sz, void *callpc, void *pc);
+void runtime_racereadrangepc(void *addr, uintptr sz, void *callpc, void *pc);
void runtime_racefingo(void);
void runtime_raceacquire(void *addr);
void runtime_raceacquireg(G *gp, void *addr);
diff --git a/libgo/runtime/runtime.c b/libgo/runtime/runtime.c
index 1ff6d00e299..56fc045eac8 100644
--- a/libgo/runtime/runtime.c
+++ b/libgo/runtime/runtime.c
@@ -124,11 +124,12 @@ TestAtomic64(void)
z64 = 42;
x64 = 0;
PREFETCH(&z64);
- if(runtime_cas64(&z64, &x64, 1))
+ if(runtime_cas64(&z64, x64, 1))
runtime_throw("cas64 failed");
- if(x64 != 42)
+ if(x64 != 0)
runtime_throw("cas64 failed");
- if(!runtime_cas64(&z64, &x64, 1))
+ x64 = 42;
+ if(!runtime_cas64(&z64, x64, 1))
runtime_throw("cas64 failed");
if(x64 != 42 || z64 != 1)
runtime_throw("cas64 failed");
@@ -279,3 +280,79 @@ runtime_signalstack(byte *p, int32 n)
if(sigaltstack(&st, nil) < 0)
*(int *)0xf1 = 0xf1;
}
+
+DebugVars runtime_debug;
+
+static struct {
+ const char* name;
+ int32* value;
+} dbgvar[] = {
+ {"gctrace", &runtime_debug.gctrace},
+ {"schedtrace", &runtime_debug.schedtrace},
+ {"scheddetail", &runtime_debug.scheddetail},
+};
+
+void
+runtime_parsedebugvars(void)
+{
+ const byte *p;
+ intgo i, n;
+
+ p = runtime_getenv("GODEBUG");
+ if(p == nil)
+ return;
+ for(;;) {
+ for(i=0; i<(intgo)nelem(dbgvar); i++) {
+ n = runtime_findnull((const byte*)dbgvar[i].name);
+ if(runtime_mcmp(p, dbgvar[i].name, n) == 0 && p[n] == '=')
+ *dbgvar[i].value = runtime_atoi(p+n+1);
+ }
+ p = (const byte *)runtime_strstr((const char *)p, ",");
+ if(p == nil)
+ break;
+ p++;
+ }
+}
+
+// Poor mans 64-bit division.
+// This is a very special function, do not use it if you are not sure what you are doing.
+// int64 division is lowered into _divv() call on 386, which does not fit into nosplit functions.
+// Handles overflow in a time-specific manner.
+int32
+runtime_timediv(int64 v, int32 div, int32 *rem)
+{
+ int32 res, bit;
+
+ if(v >= (int64)div*0x7fffffffLL) {
+ if(rem != nil)
+ *rem = 0;
+ return 0x7fffffff;
+ }
+ res = 0;
+ for(bit = 30; bit >= 0; bit--) {
+ if(v >= ((int64)div<<bit)) {
+ v = v - ((int64)div<<bit);
+ res += 1<<bit;
+ }
+ }
+ if(rem != nil)
+ *rem = v;
+ return res;
+}
+
+// Setting the max stack size doesn't really do anything for gccgo.
+
+uintptr runtime_maxstacksize = 1<<20; // enough until runtime.main sets it for real
+
+intgo runtime_debug_setMaxStack(intgo)
+ __asm__ (GOSYM_PREFIX "runtime_debug.setMaxStack");
+
+intgo
+runtime_debug_setMaxStack(intgo in)
+{
+ intgo out;
+
+ out = runtime_maxstacksize;
+ runtime_maxstacksize = in;
+ return out;
+}
diff --git a/libgo/runtime/runtime.h b/libgo/runtime/runtime.h
index d2e7d4c11bc..e82e83231e6 100644
--- a/libgo/runtime/runtime.h
+++ b/libgo/runtime/runtime.h
@@ -72,6 +72,7 @@ typedef struct ParFor ParFor;
typedef struct ParForThread ParForThread;
typedef struct CgoMal CgoMal;
typedef struct PollDesc PollDesc;
+typedef struct DebugVars DebugVars;
typedef struct __go_open_array Slice;
typedef struct __go_interface Iface;
@@ -82,6 +83,7 @@ typedef struct __go_panic_stack Panic;
typedef struct __go_ptr_type PtrType;
typedef struct __go_func_type FuncType;
+typedef struct __go_interface_type InterfaceType;
typedef struct __go_map_type MapType;
typedef struct __go_channel_type ChanType;
@@ -206,21 +208,20 @@ struct G
void* param; // passed parameter on wakeup
bool fromgogo; // reached from gogo
int16 status;
- int64 goid;
uint32 selgen; // valid sudog pointer
+ int64 goid;
const char* waitreason; // if status==Gwaiting
G* schedlink;
bool ispanic;
bool issystem; // do not output in stack dump
bool isbackground; // ignore in deadlock detector
- bool blockingsyscall; // hint that the next syscall will block
M* m; // for debuggers, but offset not hard-coded
M* lockedm;
int32 sig;
int32 writenbuf;
byte* writebuf;
- // DeferChunk *dchunk;
- // DeferChunk *dchunknext;
+ // DeferChunk* dchunk;
+ // DeferChunk* dchunknext;
uintptr sigcode0;
uintptr sigcode1;
// uintptr sigpc;
@@ -243,6 +244,7 @@ struct M
size_t gsignalstacksize;
void (*mstartfn)(void);
G* curg; // current running goroutine
+ G* caughtsig; // goroutine running during fatal signal
P* p; // attached P for executing Go code (nil if not executing Go code)
P* nextp;
int32 id;
@@ -250,11 +252,9 @@ struct M
int32 throwing;
int32 gcing;
int32 locks;
- int32 nomemprof;
int32 dying;
int32 profilehz;
int32 helpgc;
- bool blockingsyscall;
bool spinning;
uint32 fastrand;
uint64 ncgocall; // number of cgo calls in total
@@ -289,10 +289,12 @@ struct P
{
Lock;
- uint32 status; // one of Pidle/Prunning/...
+ int32 id;
+ uint32 status; // one of Pidle/Prunning/...
P* link;
- uint32 tick; // incremented on every scheduler or system call
- M* m; // back-link to associated M (nil if idle)
+ uint32 schedtick; // incremented on every scheduler call
+ uint32 syscalltick; // incremented on every system call
+ M* m; // back-link to associated M (nil if idle)
MCache* mcache;
// Queue of runnable goroutines.
@@ -308,9 +310,13 @@ struct P
byte pad[64];
};
-// The m->locked word holds a single bit saying whether
-// external calls to LockOSThread are in effect, and then a counter
-// of the internal nesting depth of lockOSThread / unlockOSThread.
+// The m->locked word holds two pieces of state counting active calls to LockOSThread/lockOSThread.
+// The low bit (LockExternal) is a boolean reporting whether any LockOSThread call is active.
+// External locks are not recursive; a second lock is silently ignored.
+// The upper bits of m->lockedcount record the nesting depth of calls to lockOSThread
+// (counting up by LockInternal), popped by unlockOSThread (counting down by LockInternal).
+// Internal locks can be recursive. For instance, a lock for cgo can occur while the main
+// goroutine is holding the lock during the initialization phase.
enum
{
LockExternal = 1,
@@ -333,19 +339,16 @@ enum
SigIgnored = 1<<6, // the signal was ignored before we registered for it
};
-#ifndef NSIG
-#define NSIG 32
-#endif
-
-// NOTE(rsc): keep in sync with extern.go:/type.Func.
-// Eventually, the loaded symbol table should be closer to this form.
+// Layout of in-memory per-function information prepared by linker
+// See http://golang.org/s/go12symtab.
+// Keep in sync with linker and with ../../libmach/sym.c
+// and with package debug/gosym.
struct Func
{
String name;
uintptr entry; // entry pc
};
-
#ifdef GOOS_windows
enum {
Windows = 1
@@ -372,7 +375,7 @@ struct Timers
// If this struct changes, adjust ../time/sleep.go:/runtimeTimer.
struct Timer
{
- int32 i; // heap index
+ int32 i; // heap index
// Timer wakes up at when, and then at when+period, ... (period > 0 only)
// each time calling f(now, arg) in the timer goroutine, so f must be
@@ -420,6 +423,16 @@ struct CgoMal
void *alloc;
};
+// Holds variables parsed from GODEBUG env var.
+struct DebugVars
+{
+ int32 gctrace;
+ int32 schedtrace;
+ int32 scheddetail;
+};
+
+extern bool runtime_precisestack;
+
/*
* defined macros
* you need super-gopher-guru privilege
@@ -453,12 +466,11 @@ extern M* runtime_allm;
extern P** runtime_allp;
extern int32 runtime_gomaxprocs;
extern uint32 runtime_needextram;
-extern bool runtime_singleproc;
extern uint32 runtime_panicking;
-extern uint32 runtime_gcwaiting; // gc is waiting to run
extern int8* runtime_goos;
extern int32 runtime_ncpu;
extern void (*runtime_sysargs)(int32, uint8**);
+extern DebugVars runtime_debug;
/*
* common functions and data
@@ -466,11 +478,13 @@ extern void (*runtime_sysargs)(int32, uint8**);
#define runtime_strcmp(s1, s2) __builtin_strcmp((s1), (s2))
#define runtime_strstr(s1, s2) __builtin_strstr((s1), (s2))
intgo runtime_findnull(const byte*);
+intgo runtime_findnullw(const uint16*);
void runtime_dump(byte*, int32);
/*
* very low level c-called
*/
+void runtime_gogo(G*);
struct __go_func_type;
void runtime_args(int32, byte**);
void runtime_osinit();
@@ -492,14 +506,13 @@ void runtime_sigenable(uint32 sig);
void runtime_sigdisable(uint32 sig);
int32 runtime_gotraceback(bool *crash);
void runtime_goroutineheader(G*);
-void runtime_goroutinetrailer(G*);
void runtime_printtrace(Location*, int32, bool);
#define runtime_open(p, f, m) open((p), (f), (m))
#define runtime_read(d, v, n) read((d), (v), (n))
#define runtime_write(d, v, n) write((d), (v), (n))
#define runtime_close(d) close(d)
#define runtime_cas(pval, old, new) __sync_bool_compare_and_swap (pval, old, new)
-#define runtime_cas64(pval, pold, new) __atomic_compare_exchange_n (pval, pold, new, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
+#define runtime_cas64(pval, old, new) __sync_bool_compare_and_swap (pval, old, new)
#define runtime_casp(pval, old, new) __sync_bool_compare_and_swap (pval, old, new)
// Don't confuse with XADD x86 instruction,
// this one is actually 'addx', that is, add-and-fetch.
@@ -530,17 +543,21 @@ void runtime_mallocinit(void);
void runtime_mprofinit(void);
#define runtime_malloc(s) __go_alloc(s)
#define runtime_free(p) __go_free(p)
-bool runtime_addfinalizer(void*, FuncVal *fn, const struct __go_func_type *);
+bool runtime_addfinalizer(void*, FuncVal *fn, const struct __go_func_type *, const struct __go_ptr_type *);
#define runtime_getcallersp(p) __builtin_frame_address(1)
int32 runtime_mcount(void);
int32 runtime_gcount(void);
+void runtime_mcall(void(*)(G*));
uint32 runtime_fastrand1(void);
+int32 runtime_timediv(int64, int32, int32*);
void runtime_setmg(M*, G*);
void runtime_newextram(void);
#define runtime_exit(s) exit(s)
#define runtime_breakpoint() __builtin_trap()
void runtime_gosched(void);
+void runtime_gosched0(G*);
+void runtime_schedtrace(bool);
void runtime_park(void(*)(Lock*), Lock*, const char*);
void runtime_tsleep(int64, const char*);
M* runtime_newm(void);
@@ -555,6 +572,8 @@ int32 runtime_callers(int32, Location*, int32);
int64 runtime_nanotime(void);
void runtime_dopanic(int32) __attribute__ ((noreturn));
void runtime_startpanic(void);
+void runtime_freezetheworld(void);
+void runtime_unwindstack(G*, byte*);
void runtime_sigprof();
void runtime_resetcpuprofiler(int32);
void runtime_setcpuprofilerate(void(*)(uintptr*, int32), int32);
@@ -567,10 +586,14 @@ void runtime_addtimer(Timer*);
bool runtime_deltimer(Timer*);
G* runtime_netpoll(bool);
void runtime_netpollinit(void);
-int32 runtime_netpollopen(int32, PollDesc*);
-int32 runtime_netpollclose(int32);
+int32 runtime_netpollopen(uintptr, PollDesc*);
+int32 runtime_netpollclose(uintptr);
void runtime_netpollready(G**, PollDesc*, int32);
+uintptr runtime_netpollfd(PollDesc*);
void runtime_crash(void);
+void runtime_parsedebugvars(void);
+void _rt0_go(void);
+void* runtime_funcdata(Func*, int32);
void runtime_stoptheworld(void);
void runtime_starttheworld(void);
@@ -603,11 +626,15 @@ void runtime_unlock(Lock*);
* wake up early, it must wait to call noteclear until it
* can be sure that no other goroutine is calling
* notewakeup.
+ *
+ * notesleep/notetsleep are generally called on g0,
+ * notetsleepg is similar to notetsleep but is called on user g.
*/
void runtime_noteclear(Note*);
void runtime_notesleep(Note*);
void runtime_notewakeup(Note*);
-void runtime_notetsleep(Note*, int64);
+bool runtime_notetsleep(Note*, int64); // false - timeout
+bool runtime_notetsleepg(Note*, int64); // false - timeout
/*
* low-level synchronization for implementing the above
@@ -698,11 +725,13 @@ void runtime_newTypeAssertionError(const String*, const String*, const String*,
__asm__ (GOSYM_PREFIX "runtime.NewTypeAssertionError");
void runtime_newErrorString(String, Eface*)
__asm__ (GOSYM_PREFIX "runtime.NewErrorString");
+void runtime_newErrorCString(const char*, Eface*)
+ __asm__ (GOSYM_PREFIX "runtime.NewErrorCString");
/*
* wrapped for go users
*/
-void runtime_semacquire(uint32 volatile *);
+void runtime_semacquire(uint32 volatile *, bool);
void runtime_semrelease(uint32 volatile *);
int32 runtime_gomaxprocsfunc(int32 n);
void runtime_procyield(uint32);
@@ -711,19 +740,10 @@ void runtime_lockOSThread(void);
void runtime_unlockOSThread(void);
bool runtime_showframe(String, bool);
+void runtime_printcreatedby(G*);
uintptr runtime_memlimit(void);
-// If appropriate, ask the operating system to control whether this
-// thread should receive profiling signals. This is only necessary on OS X.
-// An operating system should not deliver a profiling signal to a
-// thread that is not actually executing (what good is that?), but that's
-// what OS X prefers to do. When profiling is turned on, we mask
-// away the profiling signal when threads go to sleep, so that OS X
-// is forced to deliver the signal to a thread that's actually running.
-// This is a no-op on other systems.
-void runtime_setprof(bool);
-
#define ISNAN(f) __builtin_isnan(f)
enum
@@ -763,3 +783,6 @@ int32 getproccount(void);
void __go_set_closure(void*);
void* __go_get_closure(void);
+
+bool runtime_gcwaiting(void);
+void runtime_badsignal(int);
diff --git a/libgo/runtime/sema.goc b/libgo/runtime/sema.goc
index be971bd1265..f5d5bc89e3d 100644
--- a/libgo/runtime/sema.goc
+++ b/libgo/runtime/sema.goc
@@ -21,22 +21,23 @@ package sync
#include "runtime.h"
#include "arch.h"
-typedef struct Sema Sema;
-struct Sema
+typedef struct SemaWaiter SemaWaiter;
+struct SemaWaiter
{
uint32 volatile* addr;
G* g;
int64 releasetime;
- Sema* prev;
- Sema* next;
+ int32 nrelease; // -1 for acquire
+ SemaWaiter* prev;
+ SemaWaiter* next;
};
typedef struct SemaRoot SemaRoot;
struct SemaRoot
{
Lock;
- Sema* head;
- Sema* tail;
+ SemaWaiter* head;
+ SemaWaiter* tail;
// Number of waiters. Read w/o the lock.
uint32 volatile nwait;
};
@@ -58,7 +59,7 @@ semroot(uint32 volatile *addr)
}
static void
-semqueue(SemaRoot *root, uint32 volatile *addr, Sema *s)
+semqueue(SemaRoot *root, uint32 volatile *addr, SemaWaiter *s)
{
s->g = runtime_g();
s->addr = addr;
@@ -72,7 +73,7 @@ semqueue(SemaRoot *root, uint32 volatile *addr, Sema *s)
}
static void
-semdequeue(SemaRoot *root, Sema *s)
+semdequeue(SemaRoot *root, SemaWaiter *s)
{
if(s->next)
s->next->prev = s->prev;
@@ -97,10 +98,10 @@ cansemacquire(uint32 volatile *addr)
return 0;
}
-static void
-semacquireimpl(uint32 volatile *addr, int32 profile)
+void
+runtime_semacquire(uint32 volatile *addr, bool profile)
{
- Sema s; // Needs to be allocated on stack, otherwise garbage collector could deallocate it
+ SemaWaiter s; // Needs to be allocated on stack, otherwise garbage collector could deallocate it
SemaRoot *root;
int64 t0;
@@ -145,15 +146,9 @@ semacquireimpl(uint32 volatile *addr, int32 profile)
}
void
-runtime_semacquire(uint32 volatile *addr)
-{
- semacquireimpl(addr, 0);
-}
-
-void
runtime_semrelease(uint32 volatile *addr)
{
- Sema *s;
+ SemaWaiter *s;
SemaRoot *root;
root = semroot(addr);
@@ -188,10 +183,117 @@ runtime_semrelease(uint32 volatile *addr)
}
}
+// TODO(dvyukov): move to netpoll.goc once it's used by all OSes.
+void net_runtime_Semacquire(uint32 *addr)
+ __asm__ (GOSYM_PREFIX "net.runtime_Semacquire");
+
+void net_runtime_Semacquire(uint32 *addr)
+{
+ runtime_semacquire(addr, true);
+}
+
+void net_runtime_Semrelease(uint32 *addr)
+ __asm__ (GOSYM_PREFIX "net.runtime_Semrelease");
+
+void net_runtime_Semrelease(uint32 *addr)
+{
+ runtime_semrelease(addr);
+}
+
func runtime_Semacquire(addr *uint32) {
- semacquireimpl(addr, 1);
+ runtime_semacquire(addr, true);
}
func runtime_Semrelease(addr *uint32) {
runtime_semrelease(addr);
}
+
+typedef struct SyncSema SyncSema;
+struct SyncSema
+{
+ Lock;
+ SemaWaiter* head;
+ SemaWaiter* tail;
+};
+
+func runtime_Syncsemcheck(size uintptr) {
+ if(size != sizeof(SyncSema)) {
+ runtime_printf("bad SyncSema size: sync:%D runtime:%D\n", (int64)size, (int64)sizeof(SyncSema));
+ runtime_throw("bad SyncSema size");
+ }
+}
+
+// Syncsemacquire waits for a pairing Syncsemrelease on the same semaphore s.
+func runtime_Syncsemacquire(s *SyncSema) {
+ SemaWaiter w, *wake;
+ int64 t0;
+
+ w.g = runtime_g();
+ w.nrelease = -1;
+ w.next = nil;
+ w.releasetime = 0;
+ t0 = 0;
+ if(runtime_blockprofilerate > 0) {
+ t0 = runtime_cputicks();
+ w.releasetime = -1;
+ }
+
+ runtime_lock(s);
+ if(s->head && s->head->nrelease > 0) {
+ // have pending release, consume it
+ wake = nil;
+ s->head->nrelease--;
+ if(s->head->nrelease == 0) {
+ wake = s->head;
+ s->head = wake->next;
+ if(s->head == nil)
+ s->tail = nil;
+ }
+ runtime_unlock(s);
+ if(wake)
+ runtime_ready(wake->g);
+ } else {
+ // enqueue itself
+ if(s->tail == nil)
+ s->head = &w;
+ else
+ s->tail->next = &w;
+ s->tail = &w;
+ runtime_park(runtime_unlock, s, "semacquire");
+ if(t0)
+ runtime_blockevent(w.releasetime - t0, 2);
+ }
+}
+
+// Syncsemrelease waits for n pairing Syncsemacquire on the same semaphore s.
+func runtime_Syncsemrelease(s *SyncSema, n uint32) {
+ SemaWaiter w, *wake;
+
+ w.g = runtime_g();
+ w.nrelease = (int32)n;
+ w.next = nil;
+ w.releasetime = 0;
+
+ runtime_lock(s);
+ while(w.nrelease > 0 && s->head && s->head->nrelease < 0) {
+ // have pending acquire, satisfy it
+ wake = s->head;
+ s->head = wake->next;
+ if(s->head == nil)
+ s->tail = nil;
+ if(wake->releasetime)
+ wake->releasetime = runtime_cputicks();
+ runtime_ready(wake->g);
+ w.nrelease--;
+ }
+ if(w.nrelease > 0) {
+ // enqueue itself
+ if(s->tail == nil)
+ s->head = &w;
+ else
+ s->tail->next = &w;
+ s->tail = &w;
+ runtime_park(runtime_unlock, s, "semarelease");
+ } else
+ runtime_unlock(s);
+}
diff --git a/libgo/runtime/signal_unix.c b/libgo/runtime/signal_unix.c
index 5a506c8af3d..ea0a58f2ea2 100644
--- a/libgo/runtime/signal_unix.c
+++ b/libgo/runtime/signal_unix.c
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin freebsd linux openbsd netbsd
+// +build darwin dragonfly freebsd linux openbsd netbsd
#include <sys/time.h>
@@ -100,13 +100,11 @@ runtime_resetcpuprofiler(int32 hz)
runtime_memclr((byte*)&it, sizeof it);
if(hz == 0) {
runtime_setitimer(ITIMER_PROF, &it, nil);
- runtime_setprof(false);
} else {
it.it_interval.tv_sec = 0;
it.it_interval.tv_usec = 1000000 / hz;
it.it_value = it.it_interval;
runtime_setitimer(ITIMER_PROF, &it, nil);
- runtime_setprof(true);
}
runtime_m()->profilehz = hz;
}
diff --git a/libgo/runtime/sigqueue.goc b/libgo/runtime/sigqueue.goc
index 8657216d3f4..6769b239dc3 100644
--- a/libgo/runtime/sigqueue.goc
+++ b/libgo/runtime/sigqueue.goc
@@ -107,9 +107,7 @@ func signal_recv() (m uint32) {
new = HASWAITER;
if(runtime_cas(&sig.state, old, new)) {
if (new == HASWAITER) {
- runtime_entersyscallblock();
- runtime_notesleep(&sig);
- runtime_exitsyscall();
+ runtime_notetsleepg(&sig, -1);
runtime_noteclear(&sig);
}
break;
@@ -157,3 +155,10 @@ func signal_disable(s uint32) {
sig.wanted[s/32] &= ~(1U<<(s&31));
runtime_sigdisable(s);
}
+
+// This runs on a foreign stack, without an m or a g. No stack split.
+void
+runtime_badsignal(int sig)
+{
+ __go_sigsend(sig);
+}
diff --git a/libgo/runtime/string.goc b/libgo/runtime/string.goc
index 64ed4f6ebaa..a7446e93c45 100644
--- a/libgo/runtime/string.goc
+++ b/libgo/runtime/string.goc
@@ -21,6 +21,18 @@ runtime_findnull(const byte *s)
return __builtin_strlen((const char*) s);
}
+intgo
+runtime_findnullw(const uint16 *s)
+{
+ intgo l;
+
+ if(s == nil)
+ return 0;
+ for(l=0; s[l]!=0; l++)
+ ;
+ return l;
+}
+
static String
gostringsize(intgo l, byte** pmem)
{
@@ -32,7 +44,7 @@ gostringsize(intgo l, byte** pmem)
return runtime_emptystring;
}
// leave room for NUL for C runtime (e.g., callers of getenv)
- mem = runtime_mallocgc(l+1, FlagNoPointers, 1, 0);
+ mem = runtime_mallocgc(l+1, 0, FlagNoScan|FlagNoZero);
s.str = mem;
s.len = l;
mem[l] = 0;
@@ -63,6 +75,15 @@ runtime_gostringnocopy(const byte *str)
return s;
}
+String runtime_cstringToGo(byte*)
+ __asm__ (GOSYM_PREFIX "runtime.cstringToGo");
+
+String
+runtime_cstringToGo(byte *str)
+{
+ return runtime_gostringnocopy(str);
+}
+
enum
{
Runeself = 0x80,
diff --git a/libgo/runtime/thread-linux.c b/libgo/runtime/thread-linux.c
index 13d23c47b07..ae56261e6f5 100644
--- a/libgo/runtime/thread-linux.c
+++ b/libgo/runtime/thread-linux.c
@@ -4,6 +4,7 @@
#include "runtime.h"
#include "defs.h"
+#include "signal_unix.h"
// Linux futex.
//
@@ -33,25 +34,22 @@ typedef struct timespec Timespec;
void
runtime_futexsleep(uint32 *addr, uint32 val, int64 ns)
{
- Timespec ts, *tsp;
-
- if(ns < 0)
- tsp = nil;
- else {
- ts.tv_sec = ns/1000000000LL;
- ts.tv_nsec = ns%1000000000LL;
- // Avoid overflow
- if(ts.tv_sec > 1<<30)
- ts.tv_sec = 1<<30;
- tsp = &ts;
- }
+ Timespec ts;
+ int32 nsec;
// Some Linux kernels have a bug where futex of
// FUTEX_WAIT returns an internal error code
// as an errno. Libpthread ignores the return value
// here, and so can we: as it says a few lines up,
// spurious wakeups are allowed.
- syscall(__NR_futex, addr, FUTEX_WAIT, val, tsp, nil, 0);
+
+ if(ns < 0) {
+ syscall(__NR_futex, addr, FUTEX_WAIT, val, nil, nil, 0);
+ return;
+ }
+ ts.tv_sec = runtime_timediv(ns, 1000000000LL, &nsec);
+ ts.tv_nsec = nsec;
+ syscall(__NR_futex, addr, FUTEX_WAIT, val, &ts, nil, 0);
}
// If any procs are sleeping on addr, wake up at most cnt.
diff --git a/libgo/runtime/time.goc b/libgo/runtime/time.goc
index 8d12fe01080..e4e35ec0846 100644
--- a/libgo/runtime/time.goc
+++ b/libgo/runtime/time.goc
@@ -12,8 +12,13 @@ package time
#include "malloc.h"
#include "race.h"
+enum {
+ debug = 0,
+};
+
static Timers timers;
static void addtimer(Timer*);
+static void dumptimers(const char*);
// Package time APIs.
// Godoc uses the comments in package time, not these.
@@ -92,6 +97,11 @@ addtimer(Timer *t)
int32 n;
Timer **nt;
+ // when must never be negative; otherwise timerproc will overflow
+ // during its delta calculation and never expire other timers.
+ if(t->when < 0)
+ t->when = (int64)((1ULL<<63)-1);
+
if(timers.len >= timers.cap) {
// Grow slice.
n = 16;
@@ -121,8 +131,13 @@ addtimer(Timer *t)
timers.timerproc = __go_go(timerproc, nil);
timers.timerproc->issystem = true;
}
+ if(debug)
+ dumptimers("addtimer");
}
+// Used to force a dereference before the lock is acquired.
+static int32 gi;
+
// Delete timer t from the heap.
// Do not need to update the timerproc:
// if it wakes up early, no big deal.
@@ -131,6 +146,11 @@ runtime_deltimer(Timer *t)
{
int32 i;
+ // Dereference t so that any panic happens before the lock is held.
+ // Discard result, because t might be moving in the heap.
+ i = t->i;
+ gi = i;
+
runtime_lock(&timers);
// t may not be registered anymore and may have
@@ -152,6 +172,8 @@ runtime_deltimer(Timer *t)
siftup(i);
siftdown(i);
}
+ if(debug)
+ dumptimers("deltimer");
runtime_unlock(&timers);
return true;
}
@@ -170,6 +192,7 @@ timerproc(void* dummy __attribute__ ((unused)))
for(;;) {
runtime_lock(&timers);
+ timers.sleeping = false;
now = runtime_nanotime();
for(;;) {
if(timers.len == 0) {
@@ -210,9 +233,7 @@ timerproc(void* dummy __attribute__ ((unused)))
timers.sleeping = true;
runtime_noteclear(&timers.waitnote);
runtime_unlock(&timers);
- runtime_entersyscallblock();
- runtime_notetsleep(&timers.waitnote, delta);
- runtime_exitsyscall();
+ runtime_notetsleepg(&timers.waitnote, delta);
}
}
@@ -222,18 +243,20 @@ static void
siftup(int32 i)
{
int32 p;
+ int64 when;
Timer **t, *tmp;
t = timers.t;
+ when = t[i]->when;
+ tmp = t[i];
while(i > 0) {
- p = (i-1)/2; // parent
- if(t[i]->when >= t[p]->when)
+ p = (i-1)/4; // parent
+ if(when >= t[p]->when)
break;
- tmp = t[i];
t[i] = t[p];
- t[p] = tmp;
t[i]->i = i;
- t[p]->i = p;
+ t[p] = tmp;
+ tmp->i = p;
i = p;
}
}
@@ -241,29 +264,61 @@ siftup(int32 i)
static void
siftdown(int32 i)
{
- int32 c, len;
+ int32 c, c3, len;
+ int64 when, w, w3;
Timer **t, *tmp;
t = timers.t;
len = timers.len;
+ when = t[i]->when;
+ tmp = t[i];
for(;;) {
- c = i*2 + 1; // left child
+ c = i*4 + 1; // left child
+ c3 = c + 2; // mid child
if(c >= len) {
break;
}
- if(c+1 < len && t[c+1]->when < t[c]->when)
+ w = t[c]->when;
+ if(c+1 < len && t[c+1]->when < w) {
+ w = t[c+1]->when;
c++;
- if(t[c]->when >= t[i]->when)
+ }
+ if(c3 < len) {
+ w3 = t[c3]->when;
+ if(c3+1 < len && t[c3+1]->when < w3) {
+ w3 = t[c3+1]->when;
+ c3++;
+ }
+ if(w3 < w) {
+ w = w3;
+ c = c3;
+ }
+ }
+ if(w >= when)
break;
- tmp = t[i];
t[i] = t[c];
- t[c] = tmp;
t[i]->i = i;
- t[c]->i = c;
+ t[c] = tmp;
+ tmp->i = c;
i = c;
}
}
+static void
+dumptimers(const char *msg)
+{
+ Timer *t;
+ int32 i;
+
+ runtime_printf("timers: %s\n", msg);
+ for(i = 0; i < timers.len; i++) {
+ t = timers.t[i];
+ runtime_printf("\t%d\t%p:\ti %d when %D period %D fn %p\n",
+ i, t, t->i, t->when, t->period, t->fv->fn);
+ }
+ runtime_printf("\n");
+}
+
void
runtime_time_scan(void (*addroot)(Obj))
{
diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog
index 67ce62795b0..00b4ce1ba89 100644
--- a/libgomp/ChangeLog
+++ b/libgomp/ChangeLog
@@ -1,3 +1,463 @@
+2013-11-07 Thomas Schwinge <thomas@codesourcery.com>
+
+ * testsuite/lib/libgomp.exp (libgomp_init): Don't add -fopenmp to
+ ALWAYS_CFLAGS.
+ * testsuite/libgomp.c++/c++.exp (ALWAYS_CFLAGS): Add -fopenmp.
+ * testsuite/libgomp.c/c.exp (ALWAYS_CFLAGS): Likewise.
+ * testsuite/libgomp.fortran/fortran.exp (ALWAYS_CFLAGS): Likewise.
+ * testsuite/libgomp.graphite/graphite.exp (ALWAYS_CFLAGS):
+ Likewise.
+
+ * libgomp_g.h: Include <stddef.h> for size_t.
+
+ * libgomp.spec.in: Update comment about libgomp's dependencies.
+ * configure.ac: Likewise.
+ * configure: Regenerate.
+
+2013-10-16 Tobias Burnus <burnus@net-b.de>
+
+ * libgomp.texi: (Runtime Library Routines): Update references for
+ OpenMP 4.0. Add omp_get_cancellation, omp_get_default_device,
+ omp_get_num_devices, omp_get_num_teams, omp_get_proc_bind,
+ omp_get_team_num, omp_is_initial_device, omp_set_default_device.
+ (Environment Variables): Update references for OpenMP 4.0. Add
+ OMP_CANCELLATION, OMP_DEFAULT_DEVICE, OMP_PLACES.
+ Move OMP_DISPLAY_ENV and OMP_PROC_BIND up to be in alphabetical
+ order.
+
+2013-10-14 Jakub Jelinek <jakub@redhat.com>
+
+ * env.c (parse_bind_var): Initialize value to avoid
+ (false positive) warning.
+
+2013-10-12 Jakub Jelinek <jakub@redhat.com>
+
+ PR libgomp/58691
+ * config/linux/proc.c (gomp_cpuset_popcount): Add unused attribute
+ to check variable.
+ (gomp_init_num_threads): Move i variable declaration into
+ #ifdef CPU_ALLOC_SIZE block.
+ * config/linux/affinity.c (gomp_affinity_init_level): Test
+ gomp_places_list_len == 0 rather than gomp_places_list == 0
+ when checking for topology reading error.
+ * team.c (gomp_team_start): Don't handle bind == omp_proc_bind_false.
+ * env.c (parse_affinity): Add ignore argument, if true, don't populate
+ gomp_places_list, only parse env var and always return false.
+ (parse_places_var): Likewise. Don't check gomp_global_icv.bind_var.
+ (initialize_env): Always parse OMP_PLACES and GOMP_CPU_AFFINITY env
+ vars, default to OMP_PROC_BIND=true if OMP_PROC_BIND wasn't specified
+ and either of these variables were parsed correctly into a places
+ list.
+
+2013-10-11 Thomas Schwinge <thomas@codesourcery.com>
+ Jakub Jelinek <jakub@redhat.com>
+
+ * testsuite/libgomp.graphite/force-parallel-1.c: Expect 4 instead
+ of 5 loopfn matches.
+ * testsuite/libgomp.graphite/force-parallel-2.c: Likewise.
+ * testsuite/libgomp.graphite/force-parallel-3.c: Likewise.
+ * testsuite/libgomp.graphite/force-parallel-4.c: Likewise.
+ * testsuite/libgomp.graphite/force-parallel-5.c: Likewise.
+ * testsuite/libgomp.graphite/force-parallel-6.c: Likewise.
+ * testsuite/libgomp.graphite/force-parallel-7.c: Likewise.
+ * testsuite/libgomp.graphite/force-parallel-8.c: Likewise.
+ * testsuite/libgomp.graphite/force-parallel-9.c: Likewise.
+
+2013-10-11 Thomas Schwinge <thomas@codesourcery.com>
+
+ * Makefile.am (omp_lib.mod): Streamline rule.
+ * Makefile.in: Regenerate.
+
+ * libgomp.texi (Runtime Library Routines): C linkage, don't throw
+ exceptions.
+
+ * testsuite/libgomp.c/lib-1.c (main): Add missing error check.
+ * testsuite/libgomp.fortran/lib1.f90: Likewise.
+ * testsuite/libgomp.fortran/lib2.f: Likewise.
+ * testsuite/libgomp.fortran/lib3.f: Likewise.
+
+ * configure.ac: Typo fix.
+ * configure: Regenerate.
+
+ * testsuite/libgomp.fortran/openmp_version-1.f: New file.
+ * testsuite/libgomp.fortran/openmp_version-2.f90: Likewise.
+
+ * omp.h.in: Don't touch the user's namespace.
+
+2013-10-11 Jakub Jelinek <jakub@redhat.com>
+ Tobias Burnus <burnus@net-b.de>
+ Richard Henderson <rth@redhat.com>
+
+ * target.c: New file.
+ * Makefile.am (libgomp_la_SOURCES): Add target.c.
+ * Makefile.in: Regenerated.
+ * libgomp_g.h (GOMP_task): Add depend argument.
+ (GOMP_barrier_cancel, GOMP_loop_end_cancel,
+ GOMP_sections_end_cancel, GOMP_target, GOMP_target_data,
+ GOMP_target_end_data, GOMP_target_update, GOMP_teams,
+ GOMP_parallel_loop_static, GOMP_parallel_loop_dynamic,
+ GOMP_parallel_loop_guided, GOMP_parallel_loop_runtime,
+ GOMP_parallel, GOMP_cancel, GOMP_cancellation_point,
+ GOMP_taskgroup_start, GOMP_taskgroup_end,
+ GOMP_parallel_sections): New prototypes.
+ * fortran.c (omp_is_initial_device): Add ialias_redirect.
+ (omp_is_initial_device_): New function.
+ (ULP, STR1, STR2, ialias_redirect): Removed.
+ (omp_get_cancellation_, omp_get_proc_bind_, omp_set_default_device_,
+ omp_set_default_device_8_, omp_get_default_device_,
+ omp_get_num_devices_, omp_get_num_teams_, omp_get_team_num_): New
+ functions.
+ * libgomp.map (GOMP_barrier_cancel, GOMP_loop_end_cancel,
+ GOMP_sections_end_cancel, GOMP_target, GOMP_target_data,
+ GOMP_target_end_data, GOMP_target_update, GOMP_teams): Export
+ @@GOMP_4.0.
+ (omp_is_initial_device, omp_is_initial_device_, omp_get_cancellation,
+ omp_get_cancellation_, omp_get_proc_bind, omp_get_proc_bind_,
+ omp_set_default_device, omp_set_default_device_,
+ omp_set_default_device_8_, omp_get_default_device,
+ omp_get_default_device_, omp_get_num_devices, omp_get_num_devices_,
+ omp_get_num_teams, omp_get_num_teams_, omp_get_team_num,
+ omp_get_team_num_): Export @@OMP_4.0.
+ * team.c (struct gomp_thread_start_data): Add place field.
+ (gomp_thread_start): Clear thr->thread_pool and
+ thr->task before returning. Use gomp_team_barrier_wait_final
+ instead of gomp_team_barrier_wait. Initialize thr->place.
+ (gomp_new_team): Initialize work_shares_to_free, work_share_cancelled,
+ team_cancelled and task_queued_count fields.
+ (gomp_free_pool_helper): Clear thr->thread_pool and thr->task
+ before calling pthread_exit.
+ (gomp_free_thread): No longer static. Use
+ gomp_managed_threads_lock instead of gomp_remaining_threads_lock.
+ (gomp_team_start): Add flags argument. Set
+ thr->thread_pool->threads_busy to nthreads immediately after creating
+ new pool. Use gomp_managed_threads_lock instead of
+ gomp_remaining_threads_lock. Handle OpenMP 4.0 affinity.
+ (gomp_team_end): Use gomp_managed_threads_lock instead of
+ gomp_remaining_threads_lock. Use gomp_team_barrier_wait_final instead
+ of gomp_team_barrier_wait. If team->team_cancelled, call
+ gomp_fini_worshare on ws chain starting at team->work_shares_to_free
+ rather than thr->ts.work_share.
+ (initialize_team): Don't call gomp_sem_init here.
+ * sections.c (GOMP_parallel_sections_start): Adjust gomp_team_start
+ caller.
+ (GOMP_parallel_sections, GOMP_sections_end_cancel): New functions.
+ * env.c (gomp_global_icv): Add default_device_var, target_data and
+ bind_var initializers.
+ (gomp_cpu_affinity, gomp_cpu_affinity_len): Remove.
+ (gomp_bind_var_list, gomp_bind_var_list_len, gomp_places_list,
+ gomp_places_list_len): New variables.
+ (parse_bind_var, parse_one_place, parse_places_var): New functions.
+ (parse_affinity): Rewritten to construct OMP_PLACES list with unit
+ sized places.
+ (gomp_cancel_var): New global variable.
+ (parse_int): New function.
+ (handle_omp_display_env): New function.
+ (initialize_env): Use it. Initialize default_device_var.
+ Parse OMP_CANCELLATION env var. Use parse_bind_var to parse
+ OMP_PROC_BIND instead of parse_boolean. Use parse_places_var for
+ OMP_PLACES parsing. Don't call parse_affinity if OMP_PLACES has
+ been successfully parsed (and call gomp_init_affinity in that case).
+ (omp_get_cancellation, omp_get_proc_bind, omp_set_default_device,
+ omp_get_default_device, omp_get_num_devices, omp_get_num_teams,
+ omp_get_team_num, omp_is_initial_device): New functions.
+ * libgomp.h: Include stdlib.h.
+ (ialias_ulp, ialias_str1, ialias_str2, ialias_redirect, ialias_call):
+ Define.
+ (struct target_mem_desc): Forward declare.
+ (struct gomp_task_icv): Add default_device_var, target_data, bind_var
+ and thread_limit_var fields.
+ (gomp_get_num_devices): New prototype.
+ (gomp_cancel_var): New extern decl.
+ (struct gomp_team): Add work_shares_to_free, work_share_cancelled,
+ team_cancelled and task_queued_count fields. Add comments about
+ task_{,queued_,running_}count.
+ (gomp_cancel_kind): New enum.
+ (gomp_work_share_end_cancel): New prototype.
+ (struct gomp_task): Add next_taskgroup, prev_taskgroup, taskgroup,
+ copy_ctors_done, dependers, depend_hash, depend_count, num_dependees
+ and depend fields.
+ (struct gomp_taskgroup): New type.
+ (struct gomp_task_depend_entry,
+ struct gomp_dependers_vec): New types.
+ (gomp_finish_task): Free depend_hash if non-NULL.
+ (struct gomp_team_state): Add place_partition_off
+ and place_partition_len fields.
+ (gomp_bind_var_list, gomp_bind_var_list_len, gomp_places_list,
+ gomp_places_list_len): New extern decls.
+ (struct gomp_thread): Add place field.
+ (gomp_cpu_affinity, gomp_cpu_affinity_len): Remove.
+ (gomp_init_thread_affinity): Add place argument.
+ (gomp_affinity_alloc, gomp_affinity_init_place, gomp_affinity_add_cpus,
+ gomp_affinity_remove_cpu, gomp_affinity_copy_place,
+ gomp_affinity_same_place, gomp_affinity_finalize_place_list,
+ gomp_affinity_init_level, gomp_affinity_print_place): New
+ prototypes.
+ (gomp_team_start): Add flags argument.
+ (gomp_thread_limit_var, gomp_remaining_threads_count,
+ gomp_remaining_threads_lock): Remove.
+ (gomp_managed_threads_lock): New variable.
+ (struct gomp_thread_pool): Add threads_busy field.
+ (gomp_free_thread): New prototype.
+ * task.c: Include hashtab.h.
+ (hash_entry_type): New typedef.
+ (htab_alloc, htab_free, htab_hash, htab_eq): New inlines.
+ (gomp_init_task): Clear dependers, depend_hash, depend_count,
+ copy_ctors_done and taskgroup fields.
+ (GOMP_task): Add depend argument, handle depend clauses. If
+ gomp_team_barrier_cancelled or if it's taskgroup has been
+ cancelled, don't queue or start new tasks. Set copy_ctors_done
+ field if needed. Initialize taskgroup field. If copy_ctors_done
+ and already cancelled, don't discard the task. If taskgroup is
+ non-NULL, enqueue the task into taskgroup queue. Increment
+ num_children field in taskgroup. Increment task_queued_count.
+ (gomp_task_run_pre, gomp_task_run_post_remove_parent,
+ gomp_task_run_post_remove_taskgroup): New inline functions.
+ (gomp_task_run_post_handle_depend_hash,
+ gomp_task_run_post_handle_dependers,
+ gomp_task_run_post_handle_depend): New functions.
+ (GOMP_taskwait): Use them. If more than one new tasks
+ have been queued, wake other threads if needed.
+ (gomp_barrier_handle_tasks): Likewise. If
+ gomp_team_barrier_cancelled, don't start any new tasks, just free
+ all tasks.
+ (GOMP_taskgroup_start, GOMP_taskgroup_end): New functions.
+ * omp_lib.f90.in
+ (omp_proc_bind_kind, omp_proc_bind_false,
+ omp_proc_bind_true, omp_proc_bind_master, omp_proc_bind_close,
+ omp_proc_bind_spread): New params.
+ (omp_get_cancellation, omp_get_proc_bind, omp_set_default_device,
+ omp_get_default_device, omp_get_num_devices, omp_get_num_teams,
+ omp_get_team_num, omp_is_initial_device): New interfaces.
+ (omp_get_dynamic, omp_get_nested, omp_in_parallel,
+ omp_get_max_threads, omp_get_num_procs, omp_get_num_threads,
+ omp_get_thread_num, omp_get_thread_limit, omp_set_max_active_levels,
+ omp_get_max_active_levels, omp_get_level, omp_get_ancestor_thread_num,
+ omp_get_team_size, omp_get_active_level, omp_in_final): Remove
+ useless use omp_lib_kinds.
+ * omp.h.in (omp_proc_bind_t): New typedef.
+ (omp_get_cancellation, omp_get_proc_bind, omp_set_default_device,
+ omp_get_default_device, omp_get_num_devices, omp_get_num_teams,
+ omp_get_team_num, omp_is_initial_device): New prototypes.
+ * loop.c (gomp_parallel_loop_start): Add flags argument, pass it
+ through to gomp_team_start.
+ (GOMP_parallel_loop_static_start, GOMP_parallel_loop_dynamic_start,
+ GOMP_parallel_loop_guided_start, GOMP_parallel_loop_runtime_start):
+ Adjust gomp_parallel_loop_start callers.
+ (GOMP_parallel_loop_static, GOMP_parallel_loop_dynamic,
+ GOMP_parallel_loop_guided, GOMP_parallel_loop_runtime,
+ GOMP_loop_end_cancel): New functions.
+ (GOMP_parallel_end): Add ialias_redirect.
+ * hashtab.h: New file.
+ * libgomp.texi (Environment Variables): Minor cleanup,
+ update section refs to OpenMP 4.0rc2.
+ (OMP_DISPLAY_ENV, GOMP_SPINCOUNT): Document these
+ environment variables.
+ * work.c (gomp_work_share_end, gomp_work_share_end_nowait): Set
+ team->work_shares_to_free to thr->ts.work_share before calling
+ free_work_share.
+ (gomp_work_share_end_cancel): New function.
+ * config/linux/proc.c: Include errno.h.
+ (gomp_get_cpuset_size, gomp_cpuset_size, gomp_cpusetp): New variables.
+ (gomp_cpuset_popcount): Add cpusetsize argument, use it instead of
+ sizeof (cpu_set_t) to determine number of iterations. Fix up check
+ extern decl. Use CPU_COUNT_S if available, or CPU_COUNT if
+ gomp_cpuset_size is sizeof (cpu_set_t).
+ (gomp_init_num_threads): Initialize gomp_cpuset_size,
+ gomp_get_cpuset_size and gomp_cpusetp here, use gomp_cpusetp instead
+ of &cpuset and pass gomp_cpuset_size instead of sizeof (cpu_set_t)
+ to pthread_getaffinity_np. Free and clear gomp_cpusetp if it didn't
+ contain any logical CPUs.
+ (get_num_procs): Don't call pthread_getaffinity_np if gomp_cpusetp
+ is NULL. Use gomp_cpusetp instead of &cpuset and pass
+ gomp_get_cpuset_size instead of sizeof (cpu_set_t) to
+ pthread_getaffinity_np. Check gomp_places_list instead of
+ gomp_cpu_affinity. Adjust gomp_cpuset_popcount caller.
+ * config/linux/bar.c (gomp_barrier_wait_end,
+ gomp_barrier_wait_last): Use BAR_* defines.
+ (gomp_team_barrier_wait_end): Likewise. Clear BAR_CANCELLED
+ from state where needed. Set work_share_cancelled to 0 on last
+ thread.
+ (gomp_team_barrier_wait_final, gomp_team_barrier_wait_cancel_end,
+ gomp_team_barrier_wait_cancel, gomp_team_barrier_cancel): New
+ functions.
+ * config/linux/proc.h (gomp_cpuset_popcount): Add attribute_hidden.
+ Add cpusetsize argument.
+ (gomp_cpuset_size, gomp_cpusetp): Declare.
+ * config/linux/affinity.c: Include errno.h, stdio.h and string.h.
+ (affinity_counter): Remove.
+ (CPU_ISSET_S, CPU_ZERO_S, CPU_SET_S, CPU_CLR_S): Define
+ if CPU_ALLOC_SIZE isn't defined.
+ (gomp_init_affinity): Rewritten, if gomp_places_list is NULL, try
+ silently create OMP_PLACES=threads, if it is non-NULL afterwards,
+ bind current thread to the first place.
+ (gomp_init_thread_affinity): Rewritten. Add place argument, just
+ pthread_setaffinity_np to gomp_places_list[place].
+ (gomp_affinity_alloc, gomp_affinity_init_place, gomp_affinity_add_cpus,
+ gomp_affinity_remove_cpu, gomp_affinity_copy_place,
+ gomp_affinity_same_place, gomp_affinity_finalize_place_list,
+ gomp_affinity_init_level, gomp_affinity_print_place): New functions.
+ * config/linux/bar.h (BAR_TASK_PENDING, BAR_WAS_LAST,
+ BAR_WAITING_FOR_TASK, BAR_INCR, BAR_CANCELLED): Define.
+ (gomp_barrier_t): Add awaited_final field.
+ (gomp_barrier_init): Initialize awaited_final field.
+ (gomp_team_barrier_wait_final, gomp_team_barrier_wait_cancel,
+ gomp_team_barrier_wait_cancel_end, gomp_team_barrier_cancel): New
+ prototypes.
+ (gomp_barrier_wait_start): Preserve BAR_CANCELLED bit. Use BAR_*
+ defines.
+ (gomp_barrier_wait_cancel_start, gomp_team_barrier_wait_final_start,
+ gomp_team_barrier_cancelled): New inline functions.
+ (gomp_barrier_last_thread,
+ gomp_team_barrier_set_task_pending,
+ gomp_team_barrier_clear_task_pending,
+ gomp_team_barrier_set_waiting_for_tasks,
+ gomp_team_barrier_waiting_for_tasks,
+ gomp_team_barrier_done): Use BAR_* defines.
+ * config/posix/bar.c (gomp_barrier_init): Clear cancellable field.
+ (gomp_barrier_wait_end): Use BAR_* defines.
+ (gomp_team_barrier_wait_end): Clear BAR_CANCELLED from state.
+ Set work_share_cancelled to 0 on last thread, use __atomic_load_n.
+ Use BAR_* defines.
+ (gomp_team_barrier_wait_cancel_end, gomp_team_barrier_wait_cancel,
+ gomp_team_barrier_cancel): New functions.
+ * config/posix/affinity.c (gomp_init_thread_affinity): Add place
+ argument.
+ (gomp_affinity_alloc, gomp_affinity_init_place, gomp_affinity_add_cpus,
+ gomp_affinity_remove_cpu, gomp_affinity_copy_place,
+ gomp_affinity_same_place, gomp_affinity_finalize_place_list,
+ gomp_affinity_init_level, gomp_affinity_print_place): New stubs.
+ * config/posix/bar.h (BAR_TASK_PENDING, BAR_WAS_LAST,
+ BAR_WAITING_FOR_TASK, BAR_INCR, BAR_CANCELLED): Define.
+ (gomp_barrier_t): Add cancellable field.
+ (gomp_team_barrier_wait_cancel, gomp_team_barrier_wait_cancel_end,
+ gomp_team_barrier_cancel): New prototypes.
+ (gomp_barrier_wait_start): Preserve BAR_CANCELLED bit.
+ (gomp_barrier_wait_cancel_start, gomp_team_barrier_wait_final,
+ gomp_team_barrier_cancelled): New inline functions.
+ (gomp_barrier_wait_start, gomp_barrier_last_thread,
+ gomp_team_barrier_set_task_pending,
+ gomp_team_barrier_clear_task_pending,
+ gomp_team_barrier_set_waiting_for_tasks,
+ gomp_team_barrier_waiting_for_tasks,
+ gomp_team_barrier_done): Use BAR_* defines.
+ * barrier.c (GOMP_barrier_cancel): New function.
+ * omp_lib.h.in (omp_proc_bind_kind, omp_proc_bind_false,
+ omp_proc_bind_true, omp_proc_bind_master, omp_proc_bind_close,
+ omp_proc_bind_spread): New params.
+ (omp_get_cancellation, omp_get_proc_bind, omp_set_default_device,
+ omp_get_default_device, omp_get_num_devices, omp_get_num_teams,
+ omp_get_team_num, omp_is_initial_device): New externals.
+ * parallel.c (GOMP_parallel, GOMP_cancel, GOMP_cancellation_point):
+ New functions.
+ (gomp_resolve_num_threads): Adjust for thread_limit now being in
+ icv->thread_limit_var. Use UINT_MAX instead of ULONG_MAX as
+ infinity. If not nested, just return minimum of max_num_threads
+ and icv->thread_limit_var and if thr->thread_pool, set threads_busy
+ to the returned value. Otherwise, don't update atomically
+ gomp_remaining_threads_count, but instead thr->thread_pool->threads_busy.
+ (GOMP_parallel_end): Adjust for thread_limit now being in
+ icv->thread_limit_var. Use UINT_MAX instead of ULONG_MAX as
+ infinity. Adjust threads_busy in the pool rather than
+ gomp_remaining_threads_count. Remember team->nthreads and call
+ gomp_team_end before adjusting threads_busy, if not nested
+ afterwards, just set it to 1 non-atomically. Add ialias.
+ (GOMP_parallel_start): Adjust gomp_team_start caller.
+ * testsuite/libgomp.c/atomic-14.c: Add parens to make it valid.
+ * testsuite/libgomp.c/affinity-1.c: New test.
+ * testsuite/libgomp.c/atomic-15.c: New test.
+ * testsuite/libgomp.c/atomic-16.c: New test.
+ * testsuite/libgomp.c/atomic-17.c: New test.
+ * testsuite/libgomp.c/cancel-for-1.c: New test.
+ * testsuite/libgomp.c/cancel-for-2.c: New test.
+ * testsuite/libgomp.c/cancel-parallel-1.c: New test.
+ * testsuite/libgomp.c/cancel-parallel-2.c: New test.
+ * testsuite/libgomp.c/cancel-parallel-3.c: New test.
+ * testsuite/libgomp.c/cancel-sections-1.c: New test.
+ * testsuite/libgomp.c/cancel-taskgroup-1.c: New test.
+ * testsuite/libgomp.c/cancel-taskgroup-2.c: New test.
+ * testsuite/libgomp.c/depend-1.c: New test.
+ * testsuite/libgomp.c/depend-2.c: New test.
+ * testsuite/libgomp.c/depend-3.c: New test.
+ * testsuite/libgomp.c/depend-4.c: New test.
+ * testsuite/libgomp.c/for-1.c: New test.
+ * testsuite/libgomp.c/for-1.h: New file.
+ * testsuite/libgomp.c/for-2.c: New test.
+ * testsuite/libgomp.c/for-2.h: New file.
+ * testsuite/libgomp.c/for-3.c: New test.
+ * testsuite/libgomp.c/pr58392.c: New test.
+ * testsuite/libgomp.c/simd-1.c: New test.
+ * testsuite/libgomp.c/simd-2.c: New test.
+ * testsuite/libgomp.c/simd-3.c: New test.
+ * testsuite/libgomp.c/simd-4.c: New test.
+ * testsuite/libgomp.c/simd-5.c: New test.
+ * testsuite/libgomp.c/simd-6.c: New test.
+ * testsuite/libgomp.c/target-1.c: New test.
+ * testsuite/libgomp.c/target-2.c: New test.
+ * testsuite/libgomp.c/target-3.c: New test.
+ * testsuite/libgomp.c/target-4.c: New test.
+ * testsuite/libgomp.c/target-5.c: New test.
+ * testsuite/libgomp.c/target-6.c: New test.
+ * testsuite/libgomp.c/target-7.c: New test.
+ * testsuite/libgomp.c/taskgroup-1.c: New test.
+ * testsuite/libgomp.c/thread-limit-1.c: New test.
+ * testsuite/libgomp.c/thread-limit-2.c: New test.
+ * testsuite/libgomp.c/thread-limit-3.c: New test.
+ * testsuite/libgomp.c/udr-1.c: New test.
+ * testsuite/libgomp.c/udr-2.c: New test.
+ * testsuite/libgomp.c/udr-3.c: New test.
+ * testsuite/libgomp.c++/affinity-1.C: New test.
+ * testsuite/libgomp.c++/atomic-10.C: New test.
+ * testsuite/libgomp.c++/atomic-11.C: New test.
+ * testsuite/libgomp.c++/atomic-12.C: New test.
+ * testsuite/libgomp.c++/atomic-13.C: New test.
+ * testsuite/libgomp.c++/atomic-14.C: New test.
+ * testsuite/libgomp.c++/atomic-15.C: New test.
+ * testsuite/libgomp.c++/cancel-for-1.C: New test.
+ * testsuite/libgomp.c++/cancel-for-2.C: New test.
+ * testsuite/libgomp.c++/cancel-parallel-1.C: New test.
+ * testsuite/libgomp.c++/cancel-parallel-2.C: New test.
+ * testsuite/libgomp.c++/cancel-parallel-3.C: New test.
+ * testsuite/libgomp.c++/cancel-sections-1.C: New test.
+ * testsuite/libgomp.c++/cancel-taskgroup-1.C: New test.
+ * testsuite/libgomp.c++/cancel-taskgroup-2.C: New test.
+ * testsuite/libgomp.c++/cancel-taskgroup-3.C: New test.
+ * testsuite/libgomp.c++/cancel-test.h: New file.
+ * testsuite/libgomp.c++/for-9.C: New test.
+ * testsuite/libgomp.c++/for-10.C: New test.
+ * testsuite/libgomp.c++/for-11.C: New test.
+ * testsuite/libgomp.c++/simd-1.C: New test.
+ * testsuite/libgomp.c++/simd-2.C: New test.
+ * testsuite/libgomp.c++/simd-3.C: New test.
+ * testsuite/libgomp.c++/simd-4.C: New test.
+ * testsuite/libgomp.c++/simd-5.C: New test.
+ * testsuite/libgomp.c++/simd-6.C: New test.
+ * testsuite/libgomp.c++/simd-7.C: New test.
+ * testsuite/libgomp.c++/simd-8.C: New test.
+ * testsuite/libgomp.c++/target-1.C: New test.
+ * testsuite/libgomp.c++/target-2.C: New test.
+ * testsuite/libgomp.c++/target-2-aux.cc: New file.
+ * testsuite/libgomp.c++/target-3.C: New test.
+ * testsuite/libgomp.c++/taskgroup-1.C: New test.
+ * testsuite/libgomp.c++/udr-1.C: New test.
+ * testsuite/libgomp.c++/udr-2.C: New test.
+ * testsuite/libgomp.c++/udr-3.C: New test.
+ * testsuite/libgomp.c++/udr-4.C: New test.
+ * testsuite/libgomp.c++/udr-5.C: New test.
+ * testsuite/libgomp.c++/udr-6.C: New test.
+ * testsuite/libgomp.c++/udr-7.C: New test.
+ * testsuite/libgomp.c++/udr-8.C: New test.
+ * testsuite/libgomp.c++/udr-9.C: New test.
+
+2013-09-20 Jakub Jelinek <jakub@redhat.com>
+
+ PR testsuite/57605
+ * testsuite/lib/libgomp.exp: Add -fdiagnostics-color=never to
+ ALWAYS_CFLAGS.
+
+2013-09-20 Alan Modra <amodra@gmail.com>
+
+ * configure: Regenerate.
+
2013-09-19 Jakub Jelinek <jakub@redhat.com>
* testsuite/libgomp.c/sections-2.c: New test.
diff --git a/libgomp/Makefile.am b/libgomp/Makefile.am
index 2bc4986ad18..427415ee084 100644
--- a/libgomp/Makefile.am
+++ b/libgomp/Makefile.am
@@ -60,7 +60,7 @@ libgomp_la_LINK = $(LINK) $(libgomp_la_LDFLAGS)
libgomp_la_SOURCES = alloc.c barrier.c critical.c env.c error.c iter.c \
iter_ull.c loop.c loop_ull.c ordered.c parallel.c sections.c single.c \
task.c team.c work.c lock.c mutex.c proc.c sem.c bar.c ptrlock.c \
- time.c fortran.c affinity.c
+ time.c fortran.c affinity.c target.c
nodist_noinst_HEADERS = libgomp_f.h
nodist_libsubinclude_HEADERS = omp.h
@@ -76,7 +76,7 @@ LINK = $(LIBTOOL) --tag CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \
omp_lib_kinds.mod: omp_lib.mod
:
omp_lib.mod: omp_lib.f90
- $(FC) $(FCFLAGS) -fsyntax-only omp_lib.f90
+ $(FC) $(FCFLAGS) -fsyntax-only $<
fortran.lo: libgomp_f.h
fortran.o: libgomp_f.h
env.lo: libgomp_f.h
diff --git a/libgomp/Makefile.in b/libgomp/Makefile.in
index 3b8feced59e..52b313612b4 100644
--- a/libgomp/Makefile.in
+++ b/libgomp/Makefile.in
@@ -119,7 +119,7 @@ am_libgomp_la_OBJECTS = alloc.lo barrier.lo critical.lo env.lo \
error.lo iter.lo iter_ull.lo loop.lo loop_ull.lo ordered.lo \
parallel.lo sections.lo single.lo task.lo team.lo work.lo \
lock.lo mutex.lo proc.lo sem.lo bar.lo ptrlock.lo time.lo \
- fortran.lo affinity.lo
+ fortran.lo affinity.lo target.lo
libgomp_la_OBJECTS = $(am_libgomp_la_OBJECTS)
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/../depcomp
@@ -345,7 +345,7 @@ libgomp_la_LINK = $(LINK) $(libgomp_la_LDFLAGS)
libgomp_la_SOURCES = alloc.c barrier.c critical.c env.c error.c iter.c \
iter_ull.c loop.c loop_ull.c ordered.c parallel.c sections.c single.c \
task.c team.c work.c lock.c mutex.c proc.c sem.c bar.c ptrlock.c \
- time.c fortran.c affinity.c
+ time.c fortran.c affinity.c target.c
nodist_noinst_HEADERS = libgomp_f.h
nodist_libsubinclude_HEADERS = omp.h
@@ -501,6 +501,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sections.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sem.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/single.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/target.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/task.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/team.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/time.Plo@am__quote@
@@ -1133,7 +1134,7 @@ vpath % $(strip $(search_path))
omp_lib_kinds.mod: omp_lib.mod
:
omp_lib.mod: omp_lib.f90
- $(FC) $(FCFLAGS) -fsyntax-only omp_lib.f90
+ $(FC) $(FCFLAGS) -fsyntax-only $<
fortran.lo: libgomp_f.h
fortran.o: libgomp_f.h
env.lo: libgomp_f.h
diff --git a/libgomp/barrier.c b/libgomp/barrier.c
index dfd0bd49f50..2a9fe8f8b88 100644
--- a/libgomp/barrier.c
+++ b/libgomp/barrier.c
@@ -39,3 +39,15 @@ GOMP_barrier (void)
gomp_team_barrier_wait (&team->barrier);
}
+
+bool
+GOMP_barrier_cancel (void)
+{
+ struct gomp_thread *thr = gomp_thread ();
+ struct gomp_team *team = thr->ts.team;
+
+ /* The compiler transforms to barrier_cancel when it sees that the
+ barrier is within a construct that can cancel. Thus we should
+ never have an orphaned cancellable barrier. */
+ return gomp_team_barrier_wait_cancel (&team->barrier);
+}
diff --git a/libgomp/config/linux/affinity.c b/libgomp/config/linux/affinity.c
index dc6c7e5ed3b..bc5c9fcb656 100644
--- a/libgomp/config/linux/affinity.c
+++ b/libgomp/config/linux/affinity.c
@@ -29,90 +29,327 @@
#endif
#include "libgomp.h"
#include "proc.h"
+#include <errno.h>
#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
#include <unistd.h>
#ifdef HAVE_PTHREAD_AFFINITY_NP
-static unsigned int affinity_counter;
+#ifndef CPU_ALLOC_SIZE
+#define CPU_ISSET_S(idx, size, set) CPU_ISSET(idx, set)
+#define CPU_ZERO_S(size, set) CPU_ZERO(set)
+#define CPU_SET_S(idx, size, set) CPU_SET(idx, set)
+#define CPU_CLR_S(idx, size, set) CPU_CLR(idx, set)
+#endif
void
gomp_init_affinity (void)
{
- cpu_set_t cpuset, cpusetnew;
- size_t idx, widx;
- unsigned long cpus = 0;
+ if (gomp_places_list == NULL)
+ {
+ if (!gomp_affinity_init_level (1, ULONG_MAX, true))
+ return;
+ }
+
+ struct gomp_thread *thr = gomp_thread ();
+ pthread_setaffinity_np (pthread_self (), gomp_cpuset_size,
+ (cpu_set_t *) gomp_places_list[0]);
+ thr->place = 1;
+ thr->ts.place_partition_off = 0;
+ thr->ts.place_partition_len = gomp_places_list_len;
+}
+
+void
+gomp_init_thread_affinity (pthread_attr_t *attr, unsigned int place)
+{
+ pthread_attr_setaffinity_np (attr, gomp_cpuset_size,
+ (cpu_set_t *) gomp_places_list[place]);
+}
+
+void **
+gomp_affinity_alloc (unsigned long count, bool quiet)
+{
+ unsigned long i;
+ void **ret;
+ char *p;
+
+ if (gomp_cpusetp == NULL)
+ {
+ if (!quiet)
+ gomp_error ("Could not get CPU affinity set");
+ return NULL;
+ }
- if (pthread_getaffinity_np (pthread_self (), sizeof (cpuset), &cpuset))
+ ret = malloc (count * sizeof (void *) + count * gomp_cpuset_size);
+ if (ret == NULL)
{
- gomp_error ("could not get CPU affinity set");
- free (gomp_cpu_affinity);
- gomp_cpu_affinity = NULL;
- gomp_cpu_affinity_len = 0;
- return;
+ if (!quiet)
+ gomp_error ("Out of memory trying to allocate places list");
+ return NULL;
}
- CPU_ZERO (&cpusetnew);
- if (gomp_cpu_affinity_len == 0)
+ p = (char *) (ret + count);
+ for (i = 0; i < count; i++, p += gomp_cpuset_size)
+ ret[i] = p;
+ return ret;
+}
+
+void
+gomp_affinity_init_place (void *p)
+{
+ cpu_set_t *cpusetp = (cpu_set_t *) p;
+ CPU_ZERO_S (gomp_cpuset_size, cpusetp);
+}
+
+bool
+gomp_affinity_add_cpus (void *p, unsigned long num,
+ unsigned long len, long stride, bool quiet)
+{
+ cpu_set_t *cpusetp = (cpu_set_t *) p;
+ unsigned long max = 8 * gomp_cpuset_size;
+ for (;;)
{
- unsigned long count = gomp_cpuset_popcount (&cpuset);
- if (count >= 65536)
- count = 65536;
- gomp_cpu_affinity = malloc (count * sizeof (unsigned short));
- if (gomp_cpu_affinity == NULL)
+ if (num >= max)
+ {
+ if (!quiet)
+ gomp_error ("Logical CPU number %lu out of range", num);
+ return false;
+ }
+ CPU_SET_S (num, gomp_cpuset_size, cpusetp);
+ if (--len == 0)
+ return true;
+ if ((stride < 0 && num + stride > num)
+ || (stride > 0 && num + stride < num))
{
- gomp_error ("not enough memory to store CPU affinity list");
- return;
+ if (!quiet)
+ gomp_error ("Logical CPU number %lu+%ld out of range",
+ num, stride);
+ return false;
}
- for (widx = idx = 0; widx < count && idx < 65536; idx++)
- if (CPU_ISSET (idx, &cpuset))
+ num += stride;
+ }
+}
+
+bool
+gomp_affinity_remove_cpu (void *p, unsigned long num)
+{
+ cpu_set_t *cpusetp = (cpu_set_t *) p;
+ if (num >= 8 * gomp_cpuset_size)
+ {
+ gomp_error ("Logical CPU number %lu out of range", num);
+ return false;
+ }
+ if (!CPU_ISSET_S (num, gomp_cpuset_size, cpusetp))
+ {
+ gomp_error ("Logical CPU %lu to be removed is not in the set", num);
+ return false;
+ }
+ CPU_CLR_S (num, gomp_cpuset_size, cpusetp);
+ return true;
+}
+
+bool
+gomp_affinity_copy_place (void *p, void *q, long stride)
+{
+ unsigned long i, max = 8 * gomp_cpuset_size;
+ cpu_set_t *destp = (cpu_set_t *) p;
+ cpu_set_t *srcp = (cpu_set_t *) q;
+
+ CPU_ZERO_S (gomp_cpuset_size, destp);
+ for (i = 0; i < max; i++)
+ if (CPU_ISSET_S (i, gomp_cpuset_size, srcp))
+ {
+ if ((stride < 0 && i + stride > i)
+ || (stride > 0 && (i + stride < i || i + stride >= max)))
+ {
+ gomp_error ("Logical CPU number %lu+%ld out of range", i, stride);
+ return false;
+ }
+ CPU_SET_S (i + stride, gomp_cpuset_size, destp);
+ }
+ return true;
+}
+
+bool
+gomp_affinity_same_place (void *p, void *q)
+{
+#ifdef CPU_EQUAL_S
+ return CPU_EQUAL_S (gomp_cpuset_size, (cpu_set_t *) p, (cpu_set_t *) q);
+#else
+ return memcmp (p, q, gomp_cpuset_size) == 0;
+#endif
+}
+
+bool
+gomp_affinity_finalize_place_list (bool quiet)
+{
+ unsigned long i, j;
+
+ for (i = 0, j = 0; i < gomp_places_list_len; i++)
+ {
+ cpu_set_t *cpusetp = (cpu_set_t *) gomp_places_list[i];
+ bool nonempty = false;
+#ifdef CPU_AND_S
+ CPU_AND_S (gomp_cpuset_size, cpusetp, cpusetp, gomp_cpusetp);
+ nonempty = gomp_cpuset_popcount (gomp_cpuset_size, cpusetp) != 0;
+#else
+ unsigned long k, max = gomp_cpuset_size / sizeof (cpusetp->__bits[0]);
+ for (k = 0; k < max; k++)
+ if ((cpusetp->__bits[k] &= gomp_cpusetp->__bits[k]) != 0)
+ nonempty = true;
+#endif
+ if (nonempty)
+ gomp_places_list[j++] = gomp_places_list[i];
+ }
+
+ if (j == 0)
+ {
+ if (!quiet)
+ gomp_error ("None of the places contain usable logical CPUs");
+ return false;
+ }
+ else if (j < gomp_places_list_len)
+ {
+ if (!quiet)
+ gomp_error ("Number of places reduced from %ld to %ld because some "
+ "places didn't contain any usable logical CPUs",
+ gomp_places_list_len, j);
+ gomp_places_list_len = j;
+ }
+ return true;
+}
+
+bool
+gomp_affinity_init_level (int level, unsigned long count, bool quiet)
+{
+ unsigned long i, max = 8 * gomp_cpuset_size;
+
+ if (gomp_cpusetp)
+ {
+ unsigned long maxcount
+ = gomp_cpuset_popcount (gomp_cpuset_size, gomp_cpusetp);
+ if (count > maxcount)
+ count = maxcount;
+ }
+ gomp_places_list = gomp_affinity_alloc (count, quiet);
+ gomp_places_list_len = 0;
+ if (gomp_places_list == NULL)
+ return false;
+ /* SMT (threads). */
+ if (level == 1)
+ {
+ for (i = 0; i < max && gomp_places_list_len < count; i++)
+ if (CPU_ISSET_S (i, gomp_cpuset_size, gomp_cpusetp))
{
- cpus++;
- gomp_cpu_affinity[widx++] = idx;
+ gomp_affinity_init_place (gomp_places_list[gomp_places_list_len]);
+ gomp_affinity_add_cpus (gomp_places_list[gomp_places_list_len],
+ i, 1, 0, true);
+ ++gomp_places_list_len;
}
+ return true;
}
else
- for (widx = idx = 0; idx < gomp_cpu_affinity_len; idx++)
- if (gomp_cpu_affinity[idx] < CPU_SETSIZE
- && CPU_ISSET (gomp_cpu_affinity[idx], &cpuset))
+ {
+ char name[sizeof ("/sys/devices/system/cpu/cpu/topology/"
+ "thread_siblings_list") + 3 * sizeof (unsigned long)];
+ size_t prefix_len = sizeof ("/sys/devices/system/cpu/cpu") - 1;
+ cpu_set_t *copy = gomp_alloca (gomp_cpuset_size);
+ FILE *f;
+ char *line = NULL;
+ size_t linelen = 0;
+
+ memcpy (name, "/sys/devices/system/cpu/cpu", prefix_len);
+ memcpy (copy, gomp_cpusetp, gomp_cpuset_size);
+ for (i = 0; i < max && gomp_places_list_len < count; i++)
+ if (CPU_ISSET_S (i, gomp_cpuset_size, copy))
+ {
+ sprintf (name + prefix_len, "%lu/topology/%s_siblings_list",
+ i, level == 2 ? "thread" : "core");
+ f = fopen (name, "r");
+ if (f != NULL)
+ {
+ if (getline (&line, &linelen, f) > 0)
+ {
+ char *p = line;
+ bool seen_i = false;
+ void *pl = gomp_places_list[gomp_places_list_len];
+ gomp_affinity_init_place (pl);
+ while (*p && *p != '\n')
+ {
+ unsigned long first, last;
+ errno = 0;
+ first = strtoul (p, &p, 10);
+ if (errno)
+ break;
+ last = first;
+ if (*p == '-')
+ {
+ errno = 0;
+ last = strtoul (p + 1, &p, 10);
+ if (errno || last < first)
+ break;
+ }
+ for (; first <= last; first++)
+ if (CPU_ISSET_S (first, gomp_cpuset_size, copy)
+ && gomp_affinity_add_cpus (pl, first, 1, 0,
+ true))
+ {
+ CPU_CLR_S (first, gomp_cpuset_size, copy);
+ if (first == i)
+ seen_i = true;
+ }
+ if (*p == ',')
+ ++p;
+ }
+ if (seen_i)
+ gomp_places_list_len++;
+ }
+ fclose (f);
+ }
+ }
+ if (gomp_places_list_len == 0)
{
- if (! CPU_ISSET (gomp_cpu_affinity[idx], &cpusetnew))
- {
- cpus++;
- CPU_SET (gomp_cpu_affinity[idx], &cpusetnew);
- }
- gomp_cpu_affinity[widx++] = gomp_cpu_affinity[idx];
+ if (!quiet)
+ gomp_error ("Error reading %s topology",
+ level == 2 ? "core" : "socket");
+ free (gomp_places_list);
+ gomp_places_list = NULL;
+ return false;
}
-
- if (widx == 0)
- {
- gomp_error ("no CPUs left for affinity setting");
- free (gomp_cpu_affinity);
- gomp_cpu_affinity = NULL;
- gomp_cpu_affinity_len = 0;
- return;
+ return true;
}
-
- gomp_cpu_affinity_len = widx;
- if (cpus < gomp_available_cpus)
- gomp_available_cpus = cpus;
- CPU_ZERO (&cpuset);
- CPU_SET (gomp_cpu_affinity[0], &cpuset);
- pthread_setaffinity_np (pthread_self (), sizeof (cpuset), &cpuset);
- affinity_counter = 1;
+ return false;
}
void
-gomp_init_thread_affinity (pthread_attr_t *attr)
+gomp_affinity_print_place (void *p)
{
- unsigned int cpu;
- cpu_set_t cpuset;
-
- cpu = __atomic_fetch_add (&affinity_counter, 1, MEMMODEL_RELAXED);
- cpu %= gomp_cpu_affinity_len;
- CPU_ZERO (&cpuset);
- CPU_SET (gomp_cpu_affinity[cpu], &cpuset);
- pthread_attr_setaffinity_np (attr, sizeof (cpu_set_t), &cpuset);
+ unsigned long i, max = 8 * gomp_cpuset_size, len;
+ cpu_set_t *cpusetp = (cpu_set_t *) p;
+ bool notfirst = false;
+
+ for (i = 0, len = 0; i < max; i++)
+ if (CPU_ISSET_S (i, gomp_cpuset_size, cpusetp))
+ {
+ if (len == 0)
+ {
+ if (notfirst)
+ fputc (',', stderr);
+ notfirst = true;
+ fprintf (stderr, "%lu", i);
+ }
+ ++len;
+ }
+ else
+ {
+ if (len > 1)
+ fprintf (stderr, ":%lu", len);
+ len = 0;
+ }
+ if (len > 1)
+ fprintf (stderr, ":%lu", len);
}
#else
diff --git a/libgomp/config/linux/bar.c b/libgomp/config/linux/bar.c
index 35baa886ab4..6b591e5a6c5 100644
--- a/libgomp/config/linux/bar.c
+++ b/libgomp/config/linux/bar.c
@@ -33,11 +33,11 @@
void
gomp_barrier_wait_end (gomp_barrier_t *bar, gomp_barrier_state_t state)
{
- if (__builtin_expect ((state & 1) != 0, 0))
+ if (__builtin_expect (state & BAR_WAS_LAST, 0))
{
/* Next time we'll be awaiting TOTAL threads again. */
bar->awaited = bar->total;
- __atomic_store_n (&bar->generation, bar->generation + 4,
+ __atomic_store_n (&bar->generation, bar->generation + BAR_INCR,
MEMMODEL_RELEASE);
futex_wake ((int *) &bar->generation, INT_MAX);
}
@@ -66,7 +66,7 @@ void
gomp_barrier_wait_last (gomp_barrier_t *bar)
{
gomp_barrier_state_t state = gomp_barrier_wait_start (bar);
- if (state & 1)
+ if (state & BAR_WAS_LAST)
gomp_barrier_wait_end (bar, state);
}
@@ -81,40 +81,43 @@ gomp_team_barrier_wait_end (gomp_barrier_t *bar, gomp_barrier_state_t state)
{
unsigned int generation, gen;
- if (__builtin_expect ((state & 1) != 0, 0))
+ if (__builtin_expect (state & BAR_WAS_LAST, 0))
{
/* Next time we'll be awaiting TOTAL threads again. */
struct gomp_thread *thr = gomp_thread ();
struct gomp_team *team = thr->ts.team;
bar->awaited = bar->total;
+ team->work_share_cancelled = 0;
if (__builtin_expect (team->task_count, 0))
{
gomp_barrier_handle_tasks (state);
- state &= ~1;
+ state &= ~BAR_WAS_LAST;
}
else
{
- __atomic_store_n (&bar->generation, state + 3, MEMMODEL_RELEASE);
+ state &= ~BAR_CANCELLED;
+ state += BAR_INCR - BAR_WAS_LAST;
+ __atomic_store_n (&bar->generation, state, MEMMODEL_RELEASE);
futex_wake ((int *) &bar->generation, INT_MAX);
return;
}
}
generation = state;
+ state &= ~BAR_CANCELLED;
do
{
do_wait ((int *) &bar->generation, generation);
gen = __atomic_load_n (&bar->generation, MEMMODEL_ACQUIRE);
- if (__builtin_expect (gen & 1, 0))
+ if (__builtin_expect (gen & BAR_TASK_PENDING, 0))
{
gomp_barrier_handle_tasks (state);
gen = __atomic_load_n (&bar->generation, MEMMODEL_ACQUIRE);
}
- if ((gen & 2) != 0)
- generation |= 2;
+ generation |= gen & BAR_WAITING_FOR_TASK;
}
- while (gen != state + 4);
+ while (gen != state + BAR_INCR);
}
void
@@ -122,3 +125,86 @@ gomp_team_barrier_wait (gomp_barrier_t *bar)
{
gomp_team_barrier_wait_end (bar, gomp_barrier_wait_start (bar));
}
+
+void
+gomp_team_barrier_wait_final (gomp_barrier_t *bar)
+{
+ gomp_barrier_state_t state = gomp_barrier_wait_final_start (bar);
+ if (__builtin_expect (state & BAR_WAS_LAST, 0))
+ bar->awaited_final = bar->total;
+ gomp_team_barrier_wait_end (bar, state);
+}
+
+bool
+gomp_team_barrier_wait_cancel_end (gomp_barrier_t *bar,
+ gomp_barrier_state_t state)
+{
+ unsigned int generation, gen;
+
+ if (__builtin_expect (state & BAR_WAS_LAST, 0))
+ {
+ /* Next time we'll be awaiting TOTAL threads again. */
+ /* BAR_CANCELLED should never be set in state here, because
+ cancellation means that at least one of the threads has been
+ cancelled, thus on a cancellable barrier we should never see
+ all threads to arrive. */
+ struct gomp_thread *thr = gomp_thread ();
+ struct gomp_team *team = thr->ts.team;
+
+ bar->awaited = bar->total;
+ team->work_share_cancelled = 0;
+ if (__builtin_expect (team->task_count, 0))
+ {
+ gomp_barrier_handle_tasks (state);
+ state &= ~BAR_WAS_LAST;
+ }
+ else
+ {
+ state += BAR_INCR - BAR_WAS_LAST;
+ __atomic_store_n (&bar->generation, state, MEMMODEL_RELEASE);
+ futex_wake ((int *) &bar->generation, INT_MAX);
+ return false;
+ }
+ }
+
+ if (__builtin_expect (state & BAR_CANCELLED, 0))
+ return true;
+
+ generation = state;
+ do
+ {
+ do_wait ((int *) &bar->generation, generation);
+ gen = __atomic_load_n (&bar->generation, MEMMODEL_ACQUIRE);
+ if (__builtin_expect (gen & BAR_CANCELLED, 0))
+ return true;
+ if (__builtin_expect (gen & BAR_TASK_PENDING, 0))
+ {
+ gomp_barrier_handle_tasks (state);
+ gen = __atomic_load_n (&bar->generation, MEMMODEL_ACQUIRE);
+ }
+ generation |= gen & BAR_WAITING_FOR_TASK;
+ }
+ while (gen != state + BAR_INCR);
+
+ return false;
+}
+
+bool
+gomp_team_barrier_wait_cancel (gomp_barrier_t *bar)
+{
+ return gomp_team_barrier_wait_cancel_end (bar, gomp_barrier_wait_start (bar));
+}
+
+void
+gomp_team_barrier_cancel (struct gomp_team *team)
+{
+ gomp_mutex_lock (&team->task_lock);
+ if (team->barrier.generation & BAR_CANCELLED)
+ {
+ gomp_mutex_unlock (&team->task_lock);
+ return;
+ }
+ team->barrier.generation |= BAR_CANCELLED;
+ gomp_mutex_unlock (&team->task_lock);
+ futex_wake ((int *) &team->barrier.generation, INT_MAX);
+}
diff --git a/libgomp/config/linux/bar.h b/libgomp/config/linux/bar.h
index 69b97069647..914c86778e5 100644
--- a/libgomp/config/linux/bar.h
+++ b/libgomp/config/linux/bar.h
@@ -38,13 +38,25 @@ typedef struct
unsigned total __attribute__((aligned (64)));
unsigned generation;
unsigned awaited __attribute__((aligned (64)));
+ unsigned awaited_final;
} gomp_barrier_t;
+
typedef unsigned int gomp_barrier_state_t;
+/* The generation field contains a counter in the high bits, with a few
+ low bits dedicated to flags. Note that TASK_PENDING and WAS_LAST can
+ share space because WAS_LAST is never stored back to generation. */
+#define BAR_TASK_PENDING 1
+#define BAR_WAS_LAST 1
+#define BAR_WAITING_FOR_TASK 2
+#define BAR_CANCELLED 4
+#define BAR_INCR 8
+
static inline void gomp_barrier_init (gomp_barrier_t *bar, unsigned count)
{
bar->total = count;
bar->awaited = count;
+ bar->awaited_final = count;
bar->generation = 0;
}
@@ -62,27 +74,55 @@ extern void gomp_barrier_wait (gomp_barrier_t *);
extern void gomp_barrier_wait_last (gomp_barrier_t *);
extern void gomp_barrier_wait_end (gomp_barrier_t *, gomp_barrier_state_t);
extern void gomp_team_barrier_wait (gomp_barrier_t *);
+extern void gomp_team_barrier_wait_final (gomp_barrier_t *);
extern void gomp_team_barrier_wait_end (gomp_barrier_t *,
gomp_barrier_state_t);
+extern bool gomp_team_barrier_wait_cancel (gomp_barrier_t *);
+extern bool gomp_team_barrier_wait_cancel_end (gomp_barrier_t *,
+ gomp_barrier_state_t);
extern void gomp_team_barrier_wake (gomp_barrier_t *, int);
+struct gomp_team;
+extern void gomp_team_barrier_cancel (struct gomp_team *);
static inline gomp_barrier_state_t
gomp_barrier_wait_start (gomp_barrier_t *bar)
{
- unsigned int ret = __atomic_load_n (&bar->generation, MEMMODEL_ACQUIRE) & ~3;
+ unsigned int ret = __atomic_load_n (&bar->generation, MEMMODEL_ACQUIRE);
+ ret &= -BAR_INCR | BAR_CANCELLED;
/* A memory barrier is needed before exiting from the various forms
of gomp_barrier_wait, to satisfy OpenMP API version 3.1 section
2.8.6 flush Construct, which says there is an implicit flush during
a barrier region. This is a convenient place to add the barrier,
so we use MEMMODEL_ACQ_REL here rather than MEMMODEL_ACQUIRE. */
- ret += __atomic_add_fetch (&bar->awaited, -1, MEMMODEL_ACQ_REL) == 0;
+ if (__atomic_add_fetch (&bar->awaited, -1, MEMMODEL_ACQ_REL) == 0)
+ ret |= BAR_WAS_LAST;
+ return ret;
+}
+
+static inline gomp_barrier_state_t
+gomp_barrier_wait_cancel_start (gomp_barrier_t *bar)
+{
+ return gomp_barrier_wait_start (bar);
+}
+
+/* This is like gomp_barrier_wait_start, except it decrements
+ bar->awaited_final rather than bar->awaited and should be used
+ for the gomp_team_end barrier only. */
+static inline gomp_barrier_state_t
+gomp_barrier_wait_final_start (gomp_barrier_t *bar)
+{
+ unsigned int ret = __atomic_load_n (&bar->generation, MEMMODEL_ACQUIRE);
+ ret &= -BAR_INCR | BAR_CANCELLED;
+ /* See above gomp_barrier_wait_start comment. */
+ if (__atomic_add_fetch (&bar->awaited_final, -1, MEMMODEL_ACQ_REL) == 0)
+ ret |= BAR_WAS_LAST;
return ret;
}
static inline bool
gomp_barrier_last_thread (gomp_barrier_state_t state)
{
- return state & 1;
+ return state & BAR_WAS_LAST;
}
/* All the inlines below must be called with team->task_lock
@@ -91,31 +131,37 @@ gomp_barrier_last_thread (gomp_barrier_state_t state)
static inline void
gomp_team_barrier_set_task_pending (gomp_barrier_t *bar)
{
- bar->generation |= 1;
+ bar->generation |= BAR_TASK_PENDING;
}
static inline void
gomp_team_barrier_clear_task_pending (gomp_barrier_t *bar)
{
- bar->generation &= ~1;
+ bar->generation &= ~BAR_TASK_PENDING;
}
static inline void
gomp_team_barrier_set_waiting_for_tasks (gomp_barrier_t *bar)
{
- bar->generation |= 2;
+ bar->generation |= BAR_WAITING_FOR_TASK;
}
static inline bool
gomp_team_barrier_waiting_for_tasks (gomp_barrier_t *bar)
{
- return (bar->generation & 2) != 0;
+ return (bar->generation & BAR_WAITING_FOR_TASK) != 0;
+}
+
+static inline bool
+gomp_team_barrier_cancelled (gomp_barrier_t *bar)
+{
+ return __builtin_expect ((bar->generation & BAR_CANCELLED) != 0, 0);
}
static inline void
gomp_team_barrier_done (gomp_barrier_t *bar, gomp_barrier_state_t state)
{
- bar->generation = (state & ~3) + 4;
+ bar->generation = (state & -BAR_INCR) + BAR_INCR;
}
#endif /* GOMP_BARRIER_H */
diff --git a/libgomp/config/linux/proc.c b/libgomp/config/linux/proc.c
index cbb773e6e90..76616dd37a0 100644
--- a/libgomp/config/linux/proc.c
+++ b/libgomp/config/linux/proc.c
@@ -30,6 +30,7 @@
#endif
#include "libgomp.h"
#include "proc.h"
+#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#ifdef HAVE_GETLOADAVG
@@ -39,19 +40,28 @@
#endif
#ifdef HAVE_PTHREAD_AFFINITY_NP
+unsigned long gomp_cpuset_size;
+static unsigned long gomp_get_cpuset_size;
+cpu_set_t *gomp_cpusetp;
+
unsigned long
-gomp_cpuset_popcount (cpu_set_t *cpusetp)
+gomp_cpuset_popcount (unsigned long cpusetsize, cpu_set_t *cpusetp)
{
-#ifdef CPU_COUNT
- /* glibc 2.6 and above provide a macro for this. */
- return CPU_COUNT (cpusetp);
+#ifdef CPU_COUNT_S
+ /* glibc 2.7 and above provide a macro for this. */
+ return CPU_COUNT_S (cpusetsize, cpusetp);
#else
+#ifdef CPU_COUNT
+ if (cpusetsize == sizeof (cpu_set_t))
+ /* glibc 2.6 and above provide a macro for this. */
+ return CPU_COUNT (cpusetp);
+#endif
size_t i;
unsigned long ret = 0;
- extern int check[sizeof (cpusetp->__bits[0]) == sizeof (unsigned long int)];
+ extern int check[sizeof (cpusetp->__bits[0]) == sizeof (unsigned long int)
+ ? 1 : -1] __attribute__((unused));
- (void) check;
- for (i = 0; i < sizeof (*cpusetp) / sizeof (cpusetp->__bits[0]); i++)
+ for (i = 0; i < cpusetsize / sizeof (cpusetp->__bits[0]); i++)
{
unsigned long int mask = cpusetp->__bits[i];
if (mask == 0)
@@ -70,16 +80,63 @@ void
gomp_init_num_threads (void)
{
#ifdef HAVE_PTHREAD_AFFINITY_NP
- cpu_set_t cpuset;
+#if defined (_SC_NPROCESSORS_CONF) && defined (CPU_ALLOC_SIZE)
+ gomp_cpuset_size = sysconf (_SC_NPROCESSORS_CONF);
+ gomp_cpuset_size = CPU_ALLOC_SIZE (gomp_cpuset_size);
+#else
+ gomp_cpuset_size = sizeof (cpu_set_t);
+#endif
- if (pthread_getaffinity_np (pthread_self (), sizeof (cpuset), &cpuset) == 0)
+ gomp_cpusetp = (cpu_set_t *) gomp_malloc (gomp_cpuset_size);
+ do
{
- /* Count only the CPUs this process can use. */
- gomp_global_icv.nthreads_var = gomp_cpuset_popcount (&cpuset);
- if (gomp_global_icv.nthreads_var == 0)
- gomp_global_icv.nthreads_var = 1;
- return;
+ int ret = pthread_getaffinity_np (pthread_self (), gomp_cpuset_size,
+ gomp_cpusetp);
+ if (ret == 0)
+ {
+ /* Count only the CPUs this process can use. */
+ gomp_global_icv.nthreads_var
+ = gomp_cpuset_popcount (gomp_cpuset_size, gomp_cpusetp);
+ if (gomp_global_icv.nthreads_var == 0)
+ break;
+ gomp_get_cpuset_size = gomp_cpuset_size;
+#ifdef CPU_ALLOC_SIZE
+ unsigned long i;
+ for (i = gomp_cpuset_size * 8; i; i--)
+ if (CPU_ISSET_S (i - 1, gomp_cpuset_size, gomp_cpusetp))
+ break;
+ gomp_cpuset_size = CPU_ALLOC_SIZE (i);
+#endif
+ return;
+ }
+ if (ret != EINVAL)
+ break;
+#ifdef CPU_ALLOC_SIZE
+ if (gomp_cpuset_size < sizeof (cpu_set_t))
+ gomp_cpuset_size = sizeof (cpu_set_t);
+ else
+ gomp_cpuset_size = gomp_cpuset_size * 2;
+ if (gomp_cpuset_size < 8 * sizeof (cpu_set_t))
+ gomp_cpusetp
+ = (cpu_set_t *) gomp_realloc (gomp_cpusetp, gomp_cpuset_size);
+ else
+ {
+ /* Avoid gomp_fatal if too large memory allocation would be
+ requested, e.g. kernel returning EINVAL all the time. */
+ void *p = realloc (gomp_cpusetp, gomp_cpuset_size);
+ if (p == NULL)
+ break;
+ gomp_cpusetp = (cpu_set_t *) p;
+ }
+#else
+ break;
+#endif
}
+ while (1);
+ gomp_cpuset_size = 0;
+ gomp_global_icv.nthreads_var = 1;
+ free (gomp_cpusetp);
+ gomp_cpusetp = NULL;
#endif
#ifdef _SC_NPROCESSORS_ONLN
gomp_global_icv.nthreads_var = sysconf (_SC_NPROCESSORS_ONLN);
@@ -90,15 +147,14 @@ static int
get_num_procs (void)
{
#ifdef HAVE_PTHREAD_AFFINITY_NP
- cpu_set_t cpuset;
-
- if (gomp_cpu_affinity == NULL)
+ if (gomp_places_list == NULL)
{
/* Count only the CPUs this process can use. */
- if (pthread_getaffinity_np (pthread_self (), sizeof (cpuset),
- &cpuset) == 0)
+ if (gomp_cpusetp
+ && pthread_getaffinity_np (pthread_self (), gomp_get_cpuset_size,
+ gomp_cpusetp) == 0)
{
- int ret = gomp_cpuset_popcount (&cpuset);
+ int ret = gomp_cpuset_popcount (gomp_get_cpuset_size, gomp_cpusetp);
return ret != 0 ? ret : 1;
}
}
diff --git a/libgomp/config/linux/proc.h b/libgomp/config/linux/proc.h
index cba7f4a09e6..bdc85dba99e 100644
--- a/libgomp/config/linux/proc.h
+++ b/libgomp/config/linux/proc.h
@@ -28,7 +28,10 @@
#include <sched.h>
#ifdef HAVE_PTHREAD_AFFINITY_NP
-extern unsigned long gomp_cpuset_popcount (cpu_set_t *);
+extern unsigned long gomp_cpuset_size attribute_hidden;
+extern cpu_set_t *gomp_cpusetp attribute_hidden;
+extern unsigned long gomp_cpuset_popcount (unsigned long, cpu_set_t *)
+ attribute_hidden;
#endif
#endif /* GOMP_PROC_H */
diff --git a/libgomp/config/posix/affinity.c b/libgomp/config/posix/affinity.c
index ac3d14e830c..e7f97ab08d6 100644
--- a/libgomp/config/posix/affinity.c
+++ b/libgomp/config/posix/affinity.c
@@ -32,7 +32,84 @@ gomp_init_affinity (void)
}
void
-gomp_init_thread_affinity (pthread_attr_t *attr)
+gomp_init_thread_affinity (pthread_attr_t *attr, unsigned int place)
{
(void) attr;
+ (void) place;
+}
+
+void **
+gomp_affinity_alloc (unsigned long count, bool quiet)
+{
+ (void) count;
+ if (!quiet)
+ gomp_error ("Affinity not supported on this configuration");
+ return NULL;
+}
+
+void
+gomp_affinity_init_place (void *p)
+{
+ (void) p;
+}
+
+bool
+gomp_affinity_add_cpus (void *p, unsigned long num,
+ unsigned long len, long stride, bool quiet)
+{
+ (void) p;
+ (void) num;
+ (void) len;
+ (void) stride;
+ (void) quiet;
+ return false;
+}
+
+bool
+gomp_affinity_remove_cpu (void *p, unsigned long num)
+{
+ (void) p;
+ (void) num;
+ return false;
+}
+
+bool
+gomp_affinity_copy_place (void *p, void *q, long stride)
+{
+ (void) p;
+ (void) q;
+ (void) stride;
+ return false;
+}
+
+bool
+gomp_affinity_same_place (void *p, void *q)
+{
+ (void) p;
+ (void) q;
+ return false;
+}
+
+bool
+gomp_affinity_finalize_place_list (bool quiet)
+{
+ (void) quiet;
+ return false;
+}
+
+bool
+gomp_affinity_init_level (int level, unsigned long count, bool quiet)
+{
+ (void) level;
+ (void) count;
+ (void) quiet;
+ if (!quiet)
+ gomp_error ("Affinity not supported on this configuration");
+ return NULL;
+}
+
+void
+gomp_affinity_print_place (void *p)
+{
+ (void) p;
}
diff --git a/libgomp/config/posix/bar.c b/libgomp/config/posix/bar.c
index 06a3185c286..bdf3978caee 100644
--- a/libgomp/config/posix/bar.c
+++ b/libgomp/config/posix/bar.c
@@ -42,6 +42,7 @@ gomp_barrier_init (gomp_barrier_t *bar, unsigned count)
bar->total = count;
bar->arrived = 0;
bar->generation = 0;
+ bar->cancellable = false;
}
void
@@ -72,7 +73,7 @@ gomp_barrier_wait_end (gomp_barrier_t *bar, gomp_barrier_state_t state)
{
unsigned int n;
- if (state & 1)
+ if (state & BAR_WAS_LAST)
{
n = --bar->arrived;
if (n > 0)
@@ -113,12 +114,14 @@ gomp_team_barrier_wait_end (gomp_barrier_t *bar, gomp_barrier_state_t state)
{
unsigned int n;
- if (state & 1)
+ state &= ~BAR_CANCELLED;
+ if (state & BAR_WAS_LAST)
{
n = --bar->arrived;
struct gomp_thread *thr = gomp_thread ();
struct gomp_team *team = thr->ts.team;
+ team->work_share_cancelled = 0;
if (team->task_count)
{
gomp_barrier_handle_tasks (state);
@@ -128,7 +131,7 @@ gomp_team_barrier_wait_end (gomp_barrier_t *bar, gomp_barrier_state_t state)
return;
}
- bar->generation = state + 3;
+ bar->generation = state + BAR_INCR - BAR_WAS_LAST;
if (n > 0)
{
do
@@ -141,13 +144,18 @@ gomp_team_barrier_wait_end (gomp_barrier_t *bar, gomp_barrier_state_t state)
else
{
gomp_mutex_unlock (&bar->mutex1);
+ int gen;
do
{
gomp_sem_wait (&bar->sem1);
- if (bar->generation & 1)
- gomp_barrier_handle_tasks (state);
+ gen = __atomic_load_n (&bar->generation, MEMMODEL_ACQUIRE);
+ if (gen & BAR_TASK_PENDING)
+ {
+ gomp_barrier_handle_tasks (state);
+ gen = __atomic_load_n (&bar->generation, MEMMODEL_ACQUIRE);
+ }
}
- while (bar->generation != state + 4);
+ while (gen != state + BAR_INCR);
#ifdef HAVE_SYNC_BUILTINS
n = __sync_add_and_fetch (&bar->arrived, -1);
@@ -162,6 +170,81 @@ gomp_team_barrier_wait_end (gomp_barrier_t *bar, gomp_barrier_state_t state)
}
}
+bool
+gomp_team_barrier_wait_cancel_end (gomp_barrier_t *bar,
+ gomp_barrier_state_t state)
+{
+ unsigned int n;
+
+ if (state & BAR_WAS_LAST)
+ {
+ bar->cancellable = false;
+ n = --bar->arrived;
+ struct gomp_thread *thr = gomp_thread ();
+ struct gomp_team *team = thr->ts.team;
+
+ team->work_share_cancelled = 0;
+ if (team->task_count)
+ {
+ gomp_barrier_handle_tasks (state);
+ if (n > 0)
+ gomp_sem_wait (&bar->sem2);
+ gomp_mutex_unlock (&bar->mutex1);
+ return false;
+ }
+
+ bar->generation = state + BAR_INCR - BAR_WAS_LAST;
+ if (n > 0)
+ {
+ do
+ gomp_sem_post (&bar->sem1);
+ while (--n != 0);
+ gomp_sem_wait (&bar->sem2);
+ }
+ gomp_mutex_unlock (&bar->mutex1);
+ }
+ else
+ {
+ if (state & BAR_CANCELLED)
+ {
+ gomp_mutex_unlock (&bar->mutex1);
+ return true;
+ }
+ bar->cancellable = true;
+ gomp_mutex_unlock (&bar->mutex1);
+ int gen;
+ do
+ {
+ gomp_sem_wait (&bar->sem1);
+ gen = __atomic_load_n (&bar->generation, MEMMODEL_ACQUIRE);
+ if (gen & BAR_CANCELLED)
+ break;
+ if (gen & BAR_TASK_PENDING)
+ {
+ gomp_barrier_handle_tasks (state);
+ gen = __atomic_load_n (&bar->generation, MEMMODEL_ACQUIRE);
+ if (gen & BAR_CANCELLED)
+ break;
+ }
+ }
+ while (gen != state + BAR_INCR);
+
+#ifdef HAVE_SYNC_BUILTINS
+ n = __sync_add_and_fetch (&bar->arrived, -1);
+#else
+ gomp_mutex_lock (&bar->mutex2);
+ n = --bar->arrived;
+ gomp_mutex_unlock (&bar->mutex2);
+#endif
+
+ if (n == 0)
+ gomp_sem_post (&bar->sem2);
+ if (gen & BAR_CANCELLED)
+ return true;
+ }
+ return false;
+}
+
void
gomp_team_barrier_wait (gomp_barrier_t *barrier)
{
@@ -176,3 +259,40 @@ gomp_team_barrier_wake (gomp_barrier_t *bar, int count)
while (count-- > 0)
gomp_sem_post (&bar->sem1);
}
+
+bool
+gomp_team_barrier_wait_cancel (gomp_barrier_t *bar)
+{
+ gomp_barrier_state_t state = gomp_barrier_wait_cancel_start (bar);
+ return gomp_team_barrier_wait_cancel_end (bar, state);
+}
+
+void
+gomp_team_barrier_cancel (struct gomp_team *team)
+{
+ if (team->barrier.generation & BAR_CANCELLED)
+ return;
+ gomp_mutex_lock (&team->barrier.mutex1);
+ gomp_mutex_lock (&team->task_lock);
+ if (team->barrier.generation & BAR_CANCELLED)
+ {
+ gomp_mutex_unlock (&team->task_lock);
+ gomp_mutex_unlock (&team->barrier.mutex1);
+ return;
+ }
+ team->barrier.generation |= BAR_CANCELLED;
+ gomp_mutex_unlock (&team->task_lock);
+ if (team->barrier.cancellable)
+ {
+ int n = team->barrier.arrived;
+ if (n > 0)
+ {
+ do
+ gomp_sem_post (&team->barrier.sem1);
+ while (--n != 0);
+ gomp_sem_wait (&team->barrier.sem2);
+ }
+ team->barrier.cancellable = false;
+ }
+ gomp_mutex_unlock (&team->barrier.mutex1);
+}
diff --git a/libgomp/config/posix/bar.h b/libgomp/config/posix/bar.h
index 1a16ca86bba..9fcd4da6723 100644
--- a/libgomp/config/posix/bar.h
+++ b/libgomp/config/posix/bar.h
@@ -43,9 +43,20 @@ typedef struct
unsigned total;
unsigned arrived;
unsigned generation;
+ bool cancellable;
} gomp_barrier_t;
+
typedef unsigned int gomp_barrier_state_t;
+/* The generation field contains a counter in the high bits, with a few
+ low bits dedicated to flags. Note that TASK_PENDING and WAS_LAST can
+ share space because WAS_LAST is never stored back to generation. */
+#define BAR_TASK_PENDING 1
+#define BAR_WAS_LAST 1
+#define BAR_WAITING_FOR_TASK 2
+#define BAR_CANCELLED 4
+#define BAR_INCR 8
+
extern void gomp_barrier_init (gomp_barrier_t *, unsigned);
extern void gomp_barrier_reinit (gomp_barrier_t *, unsigned);
extern void gomp_barrier_destroy (gomp_barrier_t *);
@@ -55,22 +66,47 @@ extern void gomp_barrier_wait_end (gomp_barrier_t *, gomp_barrier_state_t);
extern void gomp_team_barrier_wait (gomp_barrier_t *);
extern void gomp_team_barrier_wait_end (gomp_barrier_t *,
gomp_barrier_state_t);
+extern bool gomp_team_barrier_wait_cancel (gomp_barrier_t *);
+extern bool gomp_team_barrier_wait_cancel_end (gomp_barrier_t *,
+ gomp_barrier_state_t);
extern void gomp_team_barrier_wake (gomp_barrier_t *, int);
+struct gomp_team;
+extern void gomp_team_barrier_cancel (struct gomp_team *);
static inline gomp_barrier_state_t
gomp_barrier_wait_start (gomp_barrier_t *bar)
{
unsigned int ret;
gomp_mutex_lock (&bar->mutex1);
- ret = bar->generation & ~3;
- ret += ++bar->arrived == bar->total;
+ ret = bar->generation & (-BAR_INCR | BAR_CANCELLED);
+ if (++bar->arrived == bar->total)
+ ret |= BAR_WAS_LAST;
+ return ret;
+}
+
+static inline gomp_barrier_state_t
+gomp_barrier_wait_cancel_start (gomp_barrier_t *bar)
+{
+ unsigned int ret;
+ gomp_mutex_lock (&bar->mutex1);
+ ret = bar->generation & (-BAR_INCR | BAR_CANCELLED);
+ if (ret & BAR_CANCELLED)
+ return ret;
+ if (++bar->arrived == bar->total)
+ ret |= BAR_WAS_LAST;
return ret;
}
+static inline void
+gomp_team_barrier_wait_final (gomp_barrier_t *bar)
+{
+ gomp_team_barrier_wait (bar);
+}
+
static inline bool
gomp_barrier_last_thread (gomp_barrier_state_t state)
{
- return state & 1;
+ return state & BAR_WAS_LAST;
}
static inline void
@@ -85,31 +121,37 @@ gomp_barrier_wait_last (gomp_barrier_t *bar)
static inline void
gomp_team_barrier_set_task_pending (gomp_barrier_t *bar)
{
- bar->generation |= 1;
+ bar->generation |= BAR_TASK_PENDING;
}
static inline void
gomp_team_barrier_clear_task_pending (gomp_barrier_t *bar)
{
- bar->generation &= ~1;
+ bar->generation &= ~BAR_TASK_PENDING;
}
static inline void
gomp_team_barrier_set_waiting_for_tasks (gomp_barrier_t *bar)
{
- bar->generation |= 2;
+ bar->generation |= BAR_WAITING_FOR_TASK;
}
static inline bool
gomp_team_barrier_waiting_for_tasks (gomp_barrier_t *bar)
{
- return (bar->generation & 2) != 0;
+ return (bar->generation & BAR_WAITING_FOR_TASK) != 0;
+}
+
+static inline bool
+gomp_team_barrier_cancelled (gomp_barrier_t *bar)
+{
+ return __builtin_expect ((bar->generation & BAR_CANCELLED) != 0, 0);
}
static inline void
gomp_team_barrier_done (gomp_barrier_t *bar, gomp_barrier_state_t state)
{
- bar->generation = (state & ~3) + 4;
+ bar->generation = (state & -BAR_INCR) + BAR_INCR;
}
#endif /* GOMP_BARRIER_H */
diff --git a/libgomp/configure b/libgomp/configure
index 311cccb31ad..766eb098089 100755
--- a/libgomp/configure
+++ b/libgomp/configure
@@ -662,7 +662,6 @@ AR
am__fastdepCC_FALSE
am__fastdepCC_TRUE
CCDEPMODE
-am__nodep
AMDEPBACKSLASH
AMDEP_FALSE
AMDEP_TRUE
@@ -3232,11 +3231,11 @@ MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
# We need awk for the "check" target. The system "awk" is bad on
# some platforms.
-# Always define AMTAR for backward compatibility. Yes, it's still used
-# in the wild :-( We should find a proper way to deprecate it ...
-AMTAR='$${TAR-tar}'
+# Always define AMTAR for backward compatibility.
-am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'
+AMTAR=${AMTAR-"${am_missing_run}tar"}
+
+am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'
@@ -4134,7 +4133,6 @@ fi
if test "x$enable_dependency_tracking" != xno; then
am_depcomp="$ac_aux_dir/depcomp"
AMDEPBACKSLASH='\'
- am__nodep='_no'
fi
if test "x$enable_dependency_tracking" != xno; then
AMDEP_TRUE=
@@ -4159,7 +4157,6 @@ else
# 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'.
- rm -rf conftest.dir
mkdir conftest.dir
# Copy depcomp to subdir because otherwise we won't find it if we're
# using a relative directory.
@@ -4219,7 +4216,7 @@ else
break
fi
;;
- msvc7 | msvc7msys | msvisualcpp | msvcmsys)
+ msvisualcpp | msvcmsys)
# This compiler won't grok `-c -o', but also, the minuso test has
# not run yet. These depmodes are late enough in the game, and
# so weak that their functioning should not be impacted.
@@ -6583,7 +6580,7 @@ ia64-*-hpux*)
rm -rf conftest*
;;
-x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \
+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
@@ -6608,7 +6605,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
;;
esac
;;
- ppc64-*linux*|powerpc64-*linux*)
+ powerpc64le-*linux*)
+ LD="${LD-ld} -m elf32lppclinux"
+ ;;
+ powerpc64-*linux*)
LD="${LD-ld} -m elf32ppclinux"
;;
s390x-*linux*)
@@ -6627,7 +6627,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
x86_64-*linux*)
LD="${LD-ld} -m elf_x86_64"
;;
- ppc*-*linux*|powerpc*-*linux*)
+ powerpcle-*linux*)
+ LD="${LD-ld} -m elf64lppc"
+ ;;
+ powerpc-*linux*)
LD="${LD-ld} -m elf64ppc"
;;
s390*-*linux*|s390*-*tpf*)
@@ -11091,7 +11094,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11094 "configure"
+#line 11097 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -11197,7 +11200,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11200 "configure"
+#line 11203 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -15455,7 +15458,7 @@ $as_echo "#define HAVE_TLS 1" >>confdefs.h
fi
-# See what sort of export controls are availible.
+# See what sort of export controls are available.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the target supports hidden visibility" >&5
$as_echo_n "checking whether the target supports hidden visibility... " >&6; }
@@ -16151,7 +16154,7 @@ else
fi
# Set up the set of libraries that we need to link against for libgomp.
-# Note that the GOMP_SELF_SPEC in gcc.c will force -pthread for -fopenmp,
+# Note that the GOMP_SELF_SPEC in gcc.c may force -pthread,
# which will force linkage against -lpthread (or equivalent for the system).
# That's not 100% ideal, but about the best we can do easily.
if test $enable_shared = yes; then
diff --git a/libgomp/configure.ac b/libgomp/configure.ac
index d87ed2932dc..84d250f0b19 100644
--- a/libgomp/configure.ac
+++ b/libgomp/configure.ac
@@ -238,7 +238,7 @@ fi
# See if we support thread-local storage.
GCC_CHECK_TLS
-# See what sort of export controls are availible.
+# See what sort of export controls are available.
LIBGOMP_CHECK_ATTRIBUTE_VISIBILITY
LIBGOMP_CHECK_ATTRIBUTE_DLLEXPORT
LIBGOMP_CHECK_ATTRIBUTE_ALIAS
@@ -274,7 +274,7 @@ else
fi
# Set up the set of libraries that we need to link against for libgomp.
-# Note that the GOMP_SELF_SPEC in gcc.c will force -pthread for -fopenmp,
+# Note that the GOMP_SELF_SPEC in gcc.c may force -pthread,
# which will force linkage against -lpthread (or equivalent for the system).
# That's not 100% ideal, but about the best we can do easily.
if test $enable_shared = yes; then
diff --git a/libgomp/env.c b/libgomp/env.c
index 65cbba83e6c..afd03f020d0 100644
--- a/libgomp/env.c
+++ b/libgomp/env.c
@@ -29,6 +29,10 @@
#include "libgomp_f.h"
#include <ctype.h>
#include <stdlib.h>
+#include <stdio.h>
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h> /* For PRIu64. */
+#endif
#ifdef STRING_WITH_STRINGS
# include <string.h>
# include <strings.h>
@@ -50,23 +54,28 @@
struct gomp_task_icv gomp_global_icv = {
.nthreads_var = 1,
+ .thread_limit_var = UINT_MAX,
.run_sched_var = GFS_DYNAMIC,
.run_sched_modifier = 1,
+ .default_device_var = 0,
.dyn_var = false,
- .nest_var = false
+ .nest_var = false,
+ .bind_var = omp_proc_bind_false,
+ .target_data = NULL
};
-unsigned short *gomp_cpu_affinity;
-size_t gomp_cpu_affinity_len;
unsigned long gomp_max_active_levels_var = INT_MAX;
-unsigned long gomp_thread_limit_var = ULONG_MAX;
-unsigned long gomp_remaining_threads_count;
+bool gomp_cancel_var = false;
#ifndef HAVE_SYNC_BUILTINS
-gomp_mutex_t gomp_remaining_threads_lock;
+gomp_mutex_t gomp_managed_threads_lock;
#endif
unsigned long gomp_available_cpus = 1, gomp_managed_threads = 1;
unsigned long long gomp_spin_count_var, gomp_throttled_spin_count_var;
unsigned long *gomp_nthreads_var_list, gomp_nthreads_var_list_len;
+char *gomp_bind_var_list;
+unsigned long gomp_bind_var_list_len;
+void **gomp_places_list;
+unsigned long gomp_places_list_len;
/* Parse the OMP_SCHEDULE environment variable. */
@@ -184,6 +193,24 @@ parse_unsigned_long (const char *name, unsigned long *pvalue, bool allow_zero)
return false;
}
+/* Parse a positive int environment variable. Return true if one was
+ present and it was successfully parsed. */
+
+static bool
+parse_int (const char *name, int *pvalue, bool allow_zero)
+{
+ unsigned long value;
+ if (!parse_unsigned_long (name, &value, allow_zero))
+ return false;
+ if (value > INT_MAX)
+ {
+ gomp_error ("Invalid value for environment variable %s", name);
+ return false;
+ }
+ *pvalue = (int) value;
+ return true;
+}
+
/* Parse an unsigned long list environment variable. Return true if one was
present and it was successfully parsed. */
@@ -273,6 +300,416 @@ parse_unsigned_long_list (const char *name, unsigned long *p1stvalue,
return false;
}
+/* Parse environment variable set to a boolean or list of omp_proc_bind_t
+ enum values. Return true if one was present and it was successfully
+ parsed. */
+
+static bool
+parse_bind_var (const char *name, char *p1stvalue,
+ char **pvalues, unsigned long *pnvalues)
+{
+ char *env;
+ char value = omp_proc_bind_false, *values = NULL;
+ int i;
+ static struct proc_bind_kinds
+ {
+ const char name[7];
+ const char len;
+ omp_proc_bind_t kind;
+ } kinds[] =
+ {
+ { "false", 5, omp_proc_bind_false },
+ { "true", 4, omp_proc_bind_true },
+ { "master", 6, omp_proc_bind_master },
+ { "close", 5, omp_proc_bind_close },
+ { "spread", 6, omp_proc_bind_spread }
+ };
+
+ env = getenv (name);
+ if (env == NULL)
+ return false;
+
+ while (isspace ((unsigned char) *env))
+ ++env;
+ if (*env == '\0')
+ goto invalid;
+
+ for (i = 0; i < 5; i++)
+ if (strncasecmp (env, kinds[i].name, kinds[i].len) == 0)
+ {
+ value = kinds[i].kind;
+ env += kinds[i].len;
+ break;
+ }
+ if (i == 5)
+ goto invalid;
+
+ while (isspace ((unsigned char) *env))
+ ++env;
+ if (*env != '\0')
+ {
+ if (*env == ',')
+ {
+ unsigned long nvalues = 0, nalloced = 0;
+
+ if (value == omp_proc_bind_false
+ || value == omp_proc_bind_true)
+ goto invalid;
+
+ do
+ {
+ env++;
+ if (nvalues == nalloced)
+ {
+ char *n;
+ nalloced = nalloced ? nalloced * 2 : 16;
+ n = realloc (values, nalloced);
+ if (n == NULL)
+ {
+ free (values);
+ gomp_error ("Out of memory while trying to parse"
+ " environment variable %s", name);
+ return false;
+ }
+ values = n;
+ if (nvalues == 0)
+ values[nvalues++] = value;
+ }
+
+ while (isspace ((unsigned char) *env))
+ ++env;
+ if (*env == '\0')
+ goto invalid;
+
+ for (i = 2; i < 5; i++)
+ if (strncasecmp (env, kinds[i].name, kinds[i].len) == 0)
+ {
+ value = kinds[i].kind;
+ env += kinds[i].len;
+ break;
+ }
+ if (i == 5)
+ goto invalid;
+
+ values[nvalues++] = value;
+ while (isspace ((unsigned char) *env))
+ ++env;
+ if (*env == '\0')
+ break;
+ if (*env != ',')
+ goto invalid;
+ }
+ while (1);
+ *p1stvalue = values[0];
+ *pvalues = values;
+ *pnvalues = nvalues;
+ return true;
+ }
+ goto invalid;
+ }
+
+ *p1stvalue = value;
+ return true;
+
+ invalid:
+ free (values);
+ gomp_error ("Invalid value for environment variable %s", name);
+ return false;
+}
+
+static bool
+parse_one_place (char **envp, bool *negatep, unsigned long *lenp,
+ long *stridep)
+{
+ char *env = *envp, *start;
+ void *p = gomp_places_list ? gomp_places_list[gomp_places_list_len] : NULL;
+ unsigned long len = 1;
+ long stride = 1;
+ int pass;
+ bool any_negate = false;
+ *negatep = false;
+ while (isspace ((unsigned char) *env))
+ ++env;
+ if (*env == '!')
+ {
+ *negatep = true;
+ ++env;
+ while (isspace ((unsigned char) *env))
+ ++env;
+ }
+ if (*env != '{')
+ return false;
+ ++env;
+ while (isspace ((unsigned char) *env))
+ ++env;
+ start = env;
+ for (pass = 0; pass < (any_negate ? 2 : 1); pass++)
+ {
+ env = start;
+ do
+ {
+ unsigned long this_num, this_len = 1;
+ long this_stride = 1;
+ bool this_negate = (*env == '!');
+ if (this_negate)
+ {
+ if (gomp_places_list)
+ any_negate = true;
+ ++env;
+ while (isspace ((unsigned char) *env))
+ ++env;
+ }
+
+ errno = 0;
+ this_num = strtoul (env, &env, 10);
+ if (errno)
+ return false;
+ while (isspace ((unsigned char) *env))
+ ++env;
+ if (*env == ':')
+ {
+ ++env;
+ while (isspace ((unsigned char) *env))
+ ++env;
+ errno = 0;
+ this_len = strtoul (env, &env, 10);
+ if (errno || this_len == 0)
+ return false;
+ while (isspace ((unsigned char) *env))
+ ++env;
+ if (*env == ':')
+ {
+ ++env;
+ while (isspace ((unsigned char) *env))
+ ++env;
+ errno = 0;
+ this_stride = strtol (env, &env, 10);
+ if (errno)
+ return false;
+ while (isspace ((unsigned char) *env))
+ ++env;
+ }
+ }
+ if (this_negate && this_len != 1)
+ return false;
+ if (gomp_places_list && pass == this_negate)
+ {
+ if (this_negate)
+ {
+ if (!gomp_affinity_remove_cpu (p, this_num))
+ return false;
+ }
+ else if (!gomp_affinity_add_cpus (p, this_num, this_len,
+ this_stride, false))
+ return false;
+ }
+ if (*env == '}')
+ break;
+ if (*env != ',')
+ return false;
+ ++env;
+ }
+ while (1);
+ }
+
+ ++env;
+ while (isspace ((unsigned char) *env))
+ ++env;
+ if (*env == ':')
+ {
+ ++env;
+ while (isspace ((unsigned char) *env))
+ ++env;
+ errno = 0;
+ len = strtoul (env, &env, 10);
+ if (errno || len == 0 || len >= 65536)
+ return false;
+ while (isspace ((unsigned char) *env))
+ ++env;
+ if (*env == ':')
+ {
+ ++env;
+ while (isspace ((unsigned char) *env))
+ ++env;
+ errno = 0;
+ stride = strtol (env, &env, 10);
+ if (errno)
+ return false;
+ while (isspace ((unsigned char) *env))
+ ++env;
+ }
+ }
+ if (*negatep && len != 1)
+ return false;
+ *envp = env;
+ *lenp = len;
+ *stridep = stride;
+ return true;
+}
+
+static bool
+parse_places_var (const char *name, bool ignore)
+{
+ char *env = getenv (name), *end;
+ bool any_negate = false;
+ int level = 0;
+ unsigned long count = 0;
+ if (env == NULL)
+ return false;
+
+ while (isspace ((unsigned char) *env))
+ ++env;
+ if (*env == '\0')
+ goto invalid;
+
+ if (strncasecmp (env, "threads", 7) == 0)
+ {
+ env += 7;
+ level = 1;
+ }
+ else if (strncasecmp (env, "cores", 5) == 0)
+ {
+ env += 5;
+ level = 2;
+ }
+ else if (strncasecmp (env, "sockets", 7) == 0)
+ {
+ env += 7;
+ level = 3;
+ }
+ if (level)
+ {
+ count = ULONG_MAX;
+ while (isspace ((unsigned char) *env))
+ ++env;
+ if (*env != '\0')
+ {
+ if (*env++ != '(')
+ goto invalid;
+ while (isspace ((unsigned char) *env))
+ ++env;
+
+ errno = 0;
+ count = strtoul (env, &end, 10);
+ if (errno)
+ goto invalid;
+ env = end;
+ while (isspace ((unsigned char) *env))
+ ++env;
+ if (*env != ')')
+ goto invalid;
+ ++env;
+ while (isspace ((unsigned char) *env))
+ ++env;
+ if (*env != '\0')
+ goto invalid;
+ }
+
+ if (ignore)
+ return false;
+
+ return gomp_affinity_init_level (level, count, false);
+ }
+
+ count = 0;
+ end = env;
+ do
+ {
+ bool negate;
+ unsigned long len;
+ long stride;
+ if (!parse_one_place (&end, &negate, &len, &stride))
+ goto invalid;
+ if (negate)
+ {
+ if (!any_negate)
+ count++;
+ any_negate = true;
+ }
+ else
+ count += len;
+ if (count > 65536)
+ goto invalid;
+ if (*end == '\0')
+ break;
+ if (*end != ',')
+ goto invalid;
+ end++;
+ }
+ while (1);
+
+ if (ignore)
+ return false;
+
+ gomp_places_list_len = 0;
+ gomp_places_list = gomp_affinity_alloc (count, false);
+ if (gomp_places_list == NULL)
+ return false;
+
+ do
+ {
+ bool negate;
+ unsigned long len;
+ long stride;
+ gomp_affinity_init_place (gomp_places_list[gomp_places_list_len]);
+ if (!parse_one_place (&env, &negate, &len, &stride))
+ goto invalid;
+ if (negate)
+ {
+ void *p;
+ for (count = 0; count < gomp_places_list_len; count++)
+ if (gomp_affinity_same_place
+ (gomp_places_list[count],
+ gomp_places_list[gomp_places_list_len]))
+ break;
+ if (count == gomp_places_list_len)
+ {
+ gomp_error ("Trying to remove a non-existing place from list "
+ "of places");
+ goto invalid;
+ }
+ p = gomp_places_list[count];
+ memmove (&gomp_places_list[count],
+ &gomp_places_list[count + 1],
+ (gomp_places_list_len - count - 1) * sizeof (void *));
+ --gomp_places_list_len;
+ gomp_places_list[gomp_places_list_len] = p;
+ }
+ else if (len == 1)
+ ++gomp_places_list_len;
+ else
+ {
+ for (count = 0; count < len - 1; count++)
+ if (!gomp_affinity_copy_place
+ (gomp_places_list[gomp_places_list_len + count + 1],
+ gomp_places_list[gomp_places_list_len + count],
+ stride))
+ goto invalid;
+ gomp_places_list_len += len;
+ }
+ if (*env == '\0')
+ break;
+ env++;
+ }
+ while (1);
+
+ if (gomp_places_list_len == 0)
+ {
+ gomp_error ("All places have been removed");
+ goto invalid;
+ }
+ if (!gomp_affinity_finalize_place_list (false))
+ goto invalid;
+ return true;
+
+ invalid:
+ free (gomp_places_list);
+ gomp_places_list = NULL;
+ gomp_places_list_len = 0;
+ gomp_error ("Invalid value for environment variable %s", name);
+ return false;
+}
+
/* Parse the OMP_STACKSIZE environment varible. Return true if one was
present and it was successfully parsed. */
@@ -478,86 +915,95 @@ parse_wait_policy (void)
present and it was successfully parsed. */
static bool
-parse_affinity (void)
+parse_affinity (bool ignore)
{
- char *env, *end;
+ char *env, *end, *start;
+ int pass;
unsigned long cpu_beg, cpu_end, cpu_stride;
- unsigned short *cpus = NULL;
- size_t allocated = 0, used = 0, needed;
+ size_t count = 0, needed;
env = getenv ("GOMP_CPU_AFFINITY");
if (env == NULL)
return false;
- do
+ start = env;
+ for (pass = 0; pass < 2; pass++)
{
- while (*env == ' ' || *env == '\t')
- env++;
-
- cpu_beg = strtoul (env, &end, 0);
- cpu_end = cpu_beg;
- cpu_stride = 1;
- if (env == end || cpu_beg >= 65536)
- goto invalid;
+ env = start;
+ if (pass == 1)
+ {
+ if (ignore)
+ return false;
- env = end;
- if (*env == '-')
+ gomp_places_list_len = 0;
+ gomp_places_list = gomp_affinity_alloc (count, true);
+ if (gomp_places_list == NULL)
+ return false;
+ }
+ do
{
- cpu_end = strtoul (++env, &end, 0);
- if (env == end || cpu_end >= 65536 || cpu_end < cpu_beg)
+ while (isspace ((unsigned char) *env))
+ ++env;
+
+ errno = 0;
+ cpu_beg = strtoul (env, &end, 0);
+ if (errno || cpu_beg >= 65536)
goto invalid;
+ cpu_end = cpu_beg;
+ cpu_stride = 1;
env = end;
- if (*env == ':')
+ if (*env == '-')
{
- cpu_stride = strtoul (++env, &end, 0);
- if (env == end || cpu_stride == 0 || cpu_stride >= 65536)
+ errno = 0;
+ cpu_end = strtoul (++env, &end, 0);
+ if (errno || cpu_end >= 65536 || cpu_end < cpu_beg)
goto invalid;
env = end;
- }
- }
+ if (*env == ':')
+ {
+ errno = 0;
+ cpu_stride = strtoul (++env, &end, 0);
+ if (errno || cpu_stride == 0 || cpu_stride >= 65536)
+ goto invalid;
- needed = (cpu_end - cpu_beg) / cpu_stride + 1;
- if (used + needed >= allocated)
- {
- unsigned short *new_cpus;
+ env = end;
+ }
+ }
- if (allocated < 64)
- allocated = 64;
- if (allocated > needed)
- allocated <<= 1;
+ needed = (cpu_end - cpu_beg) / cpu_stride + 1;
+ if (pass == 0)
+ count += needed;
else
- allocated += 2 * needed;
- new_cpus = realloc (cpus, allocated * sizeof (unsigned short));
- if (new_cpus == NULL)
{
- free (cpus);
- gomp_error ("not enough memory to store GOMP_CPU_AFFINITY list");
- return false;
+ while (needed--)
+ {
+ void *p = gomp_places_list[gomp_places_list_len];
+ gomp_affinity_init_place (p);
+ if (gomp_affinity_add_cpus (p, cpu_beg, 1, 0, true))
+ ++gomp_places_list_len;
+ cpu_beg += cpu_stride;
+ }
}
- cpus = new_cpus;
- }
+ while (isspace ((unsigned char) *env))
+ ++env;
- while (needed--)
- {
- cpus[used++] = cpu_beg;
- cpu_beg += cpu_stride;
+ if (*env == ',')
+ env++;
+ else if (*env == '\0')
+ break;
}
-
- while (*env == ' ' || *env == '\t')
- env++;
-
- if (*env == ',')
- env++;
- else if (*env == '\0')
- break;
+ while (1);
}
- while (1);
- gomp_cpu_affinity = cpus;
- gomp_cpu_affinity_len = used;
+ if (gomp_places_list_len == 0)
+ {
+ free (gomp_places_list);
+ gomp_places_list = NULL;
+ return false;
+ }
return true;
invalid:
@@ -565,12 +1011,160 @@ parse_affinity (void)
return false;
}
+
+static void
+handle_omp_display_env (unsigned long stacksize, int wait_policy)
+{
+ const char *env;
+ bool display = false;
+ bool verbose = false;
+ int i;
+
+ env = getenv ("OMP_DISPLAY_ENV");
+ if (env == NULL)
+ return;
+
+ while (isspace ((unsigned char) *env))
+ ++env;
+ if (strncasecmp (env, "true", 4) == 0)
+ {
+ display = true;
+ env += 4;
+ }
+ else if (strncasecmp (env, "false", 5) == 0)
+ {
+ display = false;
+ env += 5;
+ }
+ else if (strncasecmp (env, "verbose", 7) == 0)
+ {
+ display = true;
+ verbose = true;
+ env += 7;
+ }
+ else
+ env = "X";
+ while (isspace ((unsigned char) *env))
+ ++env;
+ if (*env != '\0')
+ gomp_error ("Invalid value for environment variable OMP_DISPLAY_ENV");
+
+ if (!display)
+ return;
+
+ fputs ("\nOPENMP DISPLAY ENVIRONMENT BEGIN\n", stderr);
+
+ fputs (" _OPENMP = '201307'\n", stderr);
+ fprintf (stderr, " OMP_DYNAMIC = '%s'\n",
+ gomp_global_icv.dyn_var ? "TRUE" : "FALSE");
+ fprintf (stderr, " OMP_NESTED = '%s'\n",
+ gomp_global_icv.nest_var ? "TRUE" : "FALSE");
+
+ fprintf (stderr, " OMP_NUM_THREADS = '%lu", gomp_global_icv.nthreads_var);
+ for (i = 1; i < gomp_nthreads_var_list_len; i++)
+ fprintf (stderr, ",%lu", gomp_nthreads_var_list[i]);
+ fputs ("'\n", stderr);
+
+ fprintf (stderr, " OMP_SCHEDULE = '");
+ switch (gomp_global_icv.run_sched_var)
+ {
+ case GFS_RUNTIME:
+ fputs ("RUNTIME", stderr);
+ break;
+ case GFS_STATIC:
+ fputs ("STATIC", stderr);
+ break;
+ case GFS_DYNAMIC:
+ fputs ("DYNAMIC", stderr);
+ break;
+ case GFS_GUIDED:
+ fputs ("GUIDED", stderr);
+ break;
+ case GFS_AUTO:
+ fputs ("AUTO", stderr);
+ break;
+ }
+ fputs ("'\n", stderr);
+
+ fputs (" OMP_PROC_BIND = '", stderr);
+ switch (gomp_global_icv.bind_var)
+ {
+ case omp_proc_bind_false:
+ fputs ("FALSE", stderr);
+ break;
+ case omp_proc_bind_true:
+ fputs ("TRUE", stderr);
+ break;
+ case omp_proc_bind_master:
+ fputs ("MASTER", stderr);
+ break;
+ case omp_proc_bind_close:
+ fputs ("CLOSE", stderr);
+ break;
+ case omp_proc_bind_spread:
+ fputs ("SPREAD", stderr);
+ break;
+ }
+ for (i = 1; i < gomp_bind_var_list_len; i++)
+ switch (gomp_bind_var_list[i])
+ {
+ case omp_proc_bind_master:
+ fputs (",MASTER", stderr);
+ break;
+ case omp_proc_bind_close:
+ fputs (",CLOSE", stderr);
+ break;
+ case omp_proc_bind_spread:
+ fputs (",SPREAD", stderr);
+ break;
+ }
+ fputs ("'\n", stderr);
+ fputs (" OMP_PLACES = '", stderr);
+ for (i = 0; i < gomp_places_list_len; i++)
+ {
+ fputs ("{", stderr);
+ gomp_affinity_print_place (gomp_places_list[i]);
+ fputs (i + 1 == gomp_places_list_len ? "}" : "},", stderr);
+ }
+ fputs ("'\n", stderr);
+
+ fprintf (stderr, " OMP_STACKSIZE = '%lu'\n", stacksize);
+
+ /* GOMP's default value is actually neither active nor passive. */
+ fprintf (stderr, " OMP_WAIT_POLICY = '%s'\n",
+ wait_policy > 0 ? "ACTIVE" : "PASSIVE");
+ fprintf (stderr, " OMP_THREAD_LIMIT = '%u'\n",
+ gomp_global_icv.thread_limit_var);
+ fprintf (stderr, " OMP_MAX_ACTIVE_LEVELS = '%lu'\n",
+ gomp_max_active_levels_var);
+
+ fprintf (stderr, " OMP_CANCELLATION = '%s'\n",
+ gomp_cancel_var ? "TRUE" : "FALSE");
+ fprintf (stderr, " OMP_DEFAULT_DEVICE = '%d'\n",
+ gomp_global_icv.default_device_var);
+
+ if (verbose)
+ {
+ fputs (" GOMP_CPU_AFFINITY = ''\n", stderr);
+ fprintf (stderr, " GOMP_STACKSIZE = '%lu'\n", stacksize);
+#ifdef HAVE_INTTYPES_H
+ fprintf (stderr, " GOMP_SPINCOUNT = '%"PRIu64"'\n",
+ (uint64_t) gomp_spin_count_var);
+#else
+ fprintf (stderr, " GOMP_SPINCOUNT = '%lu'\n",
+ (unsigned long) gomp_spin_count_var);
+#endif
+ }
+
+ fputs ("OPENMP DISPLAY ENVIRONMENT END\n", stderr);
+}
+
+
static void __attribute__((constructor))
initialize_env (void)
{
- unsigned long stacksize;
+ unsigned long thread_limit_var, stacksize;
int wait_policy;
- bool bind_var = false;
/* Do a compile time check that mkomp_h.pl did good job. */
omp_check_defines ();
@@ -578,14 +1172,17 @@ initialize_env (void)
parse_schedule ();
parse_boolean ("OMP_DYNAMIC", &gomp_global_icv.dyn_var);
parse_boolean ("OMP_NESTED", &gomp_global_icv.nest_var);
- parse_boolean ("OMP_PROC_BIND", &bind_var);
+ parse_boolean ("OMP_CANCELLATION", &gomp_cancel_var);
+ parse_int ("OMP_DEFAULT_DEVICE", &gomp_global_icv.default_device_var, true);
parse_unsigned_long ("OMP_MAX_ACTIVE_LEVELS", &gomp_max_active_levels_var,
true);
- parse_unsigned_long ("OMP_THREAD_LIMIT", &gomp_thread_limit_var, false);
- if (gomp_thread_limit_var != ULONG_MAX)
- gomp_remaining_threads_count = gomp_thread_limit_var - 1;
+ if (parse_unsigned_long ("OMP_THREAD_LIMIT", &thread_limit_var, false))
+ {
+ gomp_global_icv.thread_limit_var
+ = thread_limit_var > INT_MAX ? UINT_MAX : thread_limit_var;
+ }
#ifndef HAVE_SYNC_BUILTINS
- gomp_mutex_init (&gomp_remaining_threads_lock);
+ gomp_mutex_init (&gomp_managed_threads_lock);
#endif
gomp_init_num_threads ();
gomp_available_cpus = gomp_global_icv.nthreads_var;
@@ -594,7 +1191,34 @@ initialize_env (void)
&gomp_nthreads_var_list,
&gomp_nthreads_var_list_len))
gomp_global_icv.nthreads_var = gomp_available_cpus;
- if (parse_affinity () || bind_var)
+ bool ignore = false;
+ if (parse_bind_var ("OMP_PROC_BIND",
+ &gomp_global_icv.bind_var,
+ &gomp_bind_var_list,
+ &gomp_bind_var_list_len)
+ && gomp_global_icv.bind_var == omp_proc_bind_false)
+ ignore = true;
+ /* Make sure OMP_PLACES and GOMP_CPU_AFFINITY env vars are always
+ parsed if present in the environment. If OMP_PROC_BIND was set
+ explictly to false, don't populate places list though. If places
+ list was successfully set from OMP_PLACES, only parse but don't process
+ GOMP_CPU_AFFINITY. If OMP_PROC_BIND was not set in the environment,
+ default to OMP_PROC_BIND=true if OMP_PLACES or GOMP_CPU_AFFINITY
+ was successfully parsed into a places list, otherwise to
+ OMP_PROC_BIND=false. */
+ if (parse_places_var ("OMP_PLACES", ignore))
+ {
+ if (gomp_global_icv.bind_var == omp_proc_bind_false)
+ gomp_global_icv.bind_var = true;
+ ignore = true;
+ }
+ if (parse_affinity (ignore))
+ {
+ if (gomp_global_icv.bind_var == omp_proc_bind_false)
+ gomp_global_icv.bind_var = true;
+ ignore = true;
+ }
+ if (gomp_global_icv.bind_var != omp_proc_bind_false)
gomp_init_affinity ();
wait_policy = parse_wait_policy ();
if (!parse_spincount ("GOMP_SPINCOUNT", &gomp_spin_count_var))
@@ -645,6 +1269,8 @@ initialize_env (void)
if (err != 0)
gomp_error ("Stack size change failed: %s", strerror (err));
}
+
+ handle_omp_display_env (stacksize, wait_policy);
}
@@ -728,7 +1354,8 @@ omp_get_max_threads (void)
int
omp_get_thread_limit (void)
{
- return gomp_thread_limit_var > INT_MAX ? INT_MAX : gomp_thread_limit_var;
+ struct gomp_task_icv *icv = gomp_icv (false);
+ return icv->thread_limit_var > INT_MAX ? INT_MAX : icv->thread_limit_var;
}
void
@@ -744,6 +1371,60 @@ omp_get_max_active_levels (void)
return gomp_max_active_levels_var;
}
+int
+omp_get_cancellation (void)
+{
+ return gomp_cancel_var;
+}
+
+omp_proc_bind_t
+omp_get_proc_bind (void)
+{
+ struct gomp_task_icv *icv = gomp_icv (false);
+ return icv->bind_var;
+}
+
+void
+omp_set_default_device (int device_num)
+{
+ struct gomp_task_icv *icv = gomp_icv (true);
+ icv->default_device_var = device_num >= 0 ? device_num : 0;
+}
+
+int
+omp_get_default_device (void)
+{
+ struct gomp_task_icv *icv = gomp_icv (false);
+ return icv->default_device_var;
+}
+
+int
+omp_get_num_devices (void)
+{
+ return gomp_get_num_devices ();
+}
+
+int
+omp_get_num_teams (void)
+{
+ /* Hardcoded to 1 on host, MIC, HSAIL? Maybe variable on PTX. */
+ return 1;
+}
+
+int
+omp_get_team_num (void)
+{
+ /* Hardcoded to 0 on host, MIC, HSAIL? Maybe variable on PTX. */
+ return 0;
+}
+
+int
+omp_is_initial_device (void)
+{
+ /* Hardcoded to 1 on host, should be 0 on MIC, HSAIL, PTX. */
+ return 1;
+}
+
ialias (omp_set_dynamic)
ialias (omp_set_nested)
ialias (omp_set_num_threads)
@@ -755,3 +1436,11 @@ ialias (omp_get_max_threads)
ialias (omp_get_thread_limit)
ialias (omp_set_max_active_levels)
ialias (omp_get_max_active_levels)
+ialias (omp_get_cancellation)
+ialias (omp_get_proc_bind)
+ialias (omp_set_default_device)
+ialias (omp_get_default_device)
+ialias (omp_get_num_devices)
+ialias (omp_get_num_teams)
+ialias (omp_get_team_num)
+ialias (omp_is_initial_device)
diff --git a/libgomp/fortran.c b/libgomp/fortran.c
index 3a4a42a4c61..38b968a8d39 100644
--- a/libgomp/fortran.c
+++ b/libgomp/fortran.c
@@ -31,11 +31,6 @@
#ifdef HAVE_ATTRIBUTE_ALIAS
/* Use internal aliases if possible. */
-# define ULP STR1(__USER_LABEL_PREFIX__)
-# define STR1(x) STR2(x)
-# define STR2(x) #x
-# define ialias_redirect(fn) \
- extern __typeof (fn) fn __asm__ (ULP "gomp_ialias_" #fn) attribute_hidden;
# ifndef LIBGOMP_GNU_SYMBOL_VERSIONING
ialias_redirect (omp_init_lock)
ialias_redirect (omp_init_nest_lock)
@@ -70,6 +65,14 @@ ialias_redirect (omp_get_ancestor_thread_num)
ialias_redirect (omp_get_team_size)
ialias_redirect (omp_get_active_level)
ialias_redirect (omp_in_final)
+ialias_redirect (omp_get_cancellation)
+ialias_redirect (omp_get_proc_bind)
+ialias_redirect (omp_set_default_device)
+ialias_redirect (omp_get_default_device)
+ialias_redirect (omp_get_num_devices)
+ialias_redirect (omp_get_num_teams)
+ialias_redirect (omp_get_team_num)
+ialias_redirect (omp_is_initial_device)
#endif
#ifndef LIBGOMP_GNU_SYMBOL_VERSIONING
@@ -435,3 +438,57 @@ omp_in_final_ (void)
{
return omp_in_final ();
}
+
+int32_t
+omp_get_cancellation_ (void)
+{
+ return omp_get_cancellation ();
+}
+
+int32_t
+omp_get_proc_bind_ (void)
+{
+ return omp_get_proc_bind ();
+}
+
+void
+omp_set_default_device_ (const int32_t *device_num)
+{
+ return omp_set_default_device (*device_num);
+}
+
+void
+omp_set_default_device_8_ (const int64_t *device_num)
+{
+ return omp_set_default_device (TO_INT (*device_num));
+}
+
+int32_t
+omp_get_default_device_ (void)
+{
+ return omp_get_default_device ();
+}
+
+int32_t
+omp_get_num_devices_ (void)
+{
+ return omp_get_num_devices ();
+}
+
+int32_t
+omp_get_num_teams_ (void)
+{
+ return omp_get_num_teams ();
+}
+
+int32_t
+omp_get_team_num_ (void)
+{
+ return omp_get_team_num ();
+}
+
+int32_t
+omp_is_initial_device_ (void)
+{
+ return omp_is_initial_device ();
+}
diff --git a/libgomp/hashtab.h b/libgomp/hashtab.h
new file mode 100644
index 00000000000..7f1dad69524
--- /dev/null
+++ b/libgomp/hashtab.h
@@ -0,0 +1,443 @@
+/* An expandable hash tables datatype.
+ Copyright (C) 1999-2013
+ Free Software Foundation, Inc.
+ Contributed by Vladimir Makarov <vmakarov@cygnus.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 2 of the License, 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. */
+
+/* The hash table code copied from include/hashtab.[hc] and adjusted,
+ so that the hash table entries are in the flexible array at the end
+ of the control structure, no callbacks are used and the elements in the
+ table are of the hash_entry_type type.
+ Before including this file, define hash_entry_type type and
+ htab_alloc and htab_free functions. After including it, define
+ htab_hash and htab_eq inline functions. */
+
+/* This package implements basic hash table functionality. It is possible
+ to search for an entry, create an entry and destroy an entry.
+
+ Elements in the table are generic pointers.
+
+ The size of the table is not fixed; if the occupancy of the table
+ grows too high the hash table will be expanded.
+
+ The abstract data implementation is based on generalized Algorithm D
+ from Knuth's book "The art of computer programming". Hash table is
+ expanded by creation of new hash table and transferring elements from
+ the old table to the new table. */
+
+/* The type for a hash code. */
+typedef unsigned int hashval_t;
+
+static inline hashval_t htab_hash (hash_entry_type);
+static inline bool htab_eq (hash_entry_type, hash_entry_type);
+
+/* This macro defines reserved value for empty table entry. */
+
+#define HTAB_EMPTY_ENTRY ((hash_entry_type) 0)
+
+/* This macro defines reserved value for table entry which contained
+ a deleted element. */
+
+#define HTAB_DELETED_ENTRY ((hash_entry_type) 1)
+
+/* Hash tables are of the following type. The structure
+ (implementation) of this type is not needed for using the hash
+ tables. All work with hash table should be executed only through
+ functions mentioned below. The size of this structure is subject to
+ change. */
+
+struct htab {
+ /* Current size (in entries) of the hash table. */
+ size_t size;
+
+ /* Current number of elements including also deleted elements. */
+ size_t n_elements;
+
+ /* Current number of deleted elements in the table. */
+ size_t n_deleted;
+
+ /* Current size (in entries) of the hash table, as an index into the
+ table of primes. */
+ unsigned int size_prime_index;
+
+ /* Table itself. */
+ hash_entry_type entries[];
+};
+
+typedef struct htab *htab_t;
+
+/* An enum saying whether we insert into the hash table or not. */
+enum insert_option {NO_INSERT, INSERT};
+
+/* 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, the function that computed the table is in
+ libiberty/hashtab.c. */
+
+struct prime_ent
+{
+ hashval_t prime;
+ hashval_t inv;
+ hashval_t inv_m2; /* inverse of prime-2 */
+ hashval_t shift;
+};
+
+static 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 }
+};
+
+/* The following function returns an index into the above table of the
+ nearest prime number which is greater than N, and near a power of two. */
+
+static unsigned int
+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. */
+ if (n > prime_tab[low].prime)
+ abort ();
+
+ return low;
+}
+
+/* Return the current size of given hash table. */
+
+static inline size_t
+htab_size (htab_t htab)
+{
+ return htab->size;
+}
+
+/* Return the current number of elements in given hash table. */
+
+static inline size_t
+htab_elements (htab_t htab)
+{
+ return htab->n_elements - htab->n_deleted;
+}
+
+/* Return X % Y. */
+
+static inline hashval_t
+htab_mod_1 (hashval_t x, hashval_t y, hashval_t inv, int shift)
+{
+ /* The multiplicative inverses computed above are for 32-bit types, and
+ requires that we be able to compute a highpart multiply. */
+ if (sizeof (hashval_t) * __CHAR_BIT__ <= 32)
+ {
+ hashval_t t1, t2, t3, t4, q, r;
+
+ t1 = ((unsigned long long)x * inv) >> 32;
+ t2 = x - t1;
+ t3 = t2 >> 1;
+ t4 = t1 + t3;
+ q = t4 >> shift;
+ r = x - (q * y);
+
+ return r;
+ }
+
+ /* Otherwise just use the native division routines. */
+ return x % y;
+}
+
+/* Compute the primary hash for HASH given HTAB's current size. */
+
+static inline hashval_t
+htab_mod (hashval_t hash, htab_t htab)
+{
+ const struct prime_ent *p = &prime_tab[htab->size_prime_index];
+ return htab_mod_1 (hash, p->prime, p->inv, p->shift);
+}
+
+/* Compute the secondary hash for HASH given HTAB's current size. */
+
+static inline hashval_t
+htab_mod_m2 (hashval_t hash, htab_t htab)
+{
+ const struct prime_ent *p = &prime_tab[htab->size_prime_index];
+ return 1 + htab_mod_1 (hash, p->prime - 2, p->inv_m2, p->shift);
+}
+
+/* Create hash table of size SIZE. */
+
+static htab_t
+htab_create (size_t size)
+{
+ htab_t result;
+ unsigned int size_prime_index;
+
+ size_prime_index = higher_prime_index (size);
+ size = prime_tab[size_prime_index].prime;
+
+ result = (htab_t) htab_alloc (sizeof (struct htab)
+ + size * sizeof (hash_entry_type));
+ result->size = size;
+ result->n_elements = 0;
+ result->n_deleted = 0;
+ result->size_prime_index = size_prime_index;
+ memset (result->entries, 0, size * sizeof (hash_entry_type));
+ return result;
+}
+
+/* Similar to htab_find_slot, but without several unwanted side effects:
+ - Does not call htab_eq when it finds an existing entry.
+ - Does not change the count of elements 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. */
+
+static hash_entry_type *
+find_empty_slot_for_expand (htab_t htab, hashval_t hash)
+{
+ hashval_t index = htab_mod (hash, htab);
+ size_t size = htab_size (htab);
+ hash_entry_type *slot = htab->entries + index;
+ hashval_t hash2;
+
+ if (*slot == HTAB_EMPTY_ENTRY)
+ return slot;
+ else if (*slot == HTAB_DELETED_ENTRY)
+ abort ();
+
+ hash2 = htab_mod_m2 (hash, htab);
+ for (;;)
+ {
+ index += hash2;
+ if (index >= size)
+ index -= size;
+
+ slot = htab->entries + index;
+ if (*slot == HTAB_EMPTY_ENTRY)
+ return slot;
+ else if (*slot == HTAB_DELETED_ENTRY)
+ abort ();
+ }
+}
+
+/* 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. */
+
+static htab_t
+htab_expand (htab_t htab)
+{
+ htab_t nhtab;
+ hash_entry_type *olimit;
+ hash_entry_type *p;
+ size_t osize, elts;
+
+ osize = htab->size;
+ olimit = htab->entries + osize;
+ elts = htab_elements (htab);
+
+ /* Resize only when table after removal of unused elements is either
+ too full or too empty. */
+ if (elts * 2 > osize || (elts * 8 < osize && osize > 32))
+ nhtab = htab_create (elts * 2);
+ else
+ nhtab = htab_create (osize - 1);
+ nhtab->n_elements = htab->n_elements - htab->n_deleted;
+
+ p = htab->entries;
+ do
+ {
+ hash_entry_type x = *p;
+
+ if (x != HTAB_EMPTY_ENTRY && x != HTAB_DELETED_ENTRY)
+ *find_empty_slot_for_expand (nhtab, htab_hash (x)) = x;
+
+ p++;
+ }
+ while (p < olimit);
+
+ htab_free (htab);
+ return nhtab;
+}
+
+/* This function searches for a hash table entry equal to the given
+ element. It cannot be used to insert or delete an element. */
+
+static hash_entry_type
+htab_find (htab_t htab, const hash_entry_type element)
+{
+ hashval_t index, hash2, hash = htab_hash (element);
+ size_t size;
+ hash_entry_type entry;
+
+ size = htab_size (htab);
+ index = htab_mod (hash, htab);
+
+ entry = htab->entries[index];
+ if (entry == HTAB_EMPTY_ENTRY
+ || (entry != HTAB_DELETED_ENTRY && htab_eq (entry, element)))
+ return entry;
+
+ hash2 = htab_mod_m2 (hash, htab);
+ for (;;)
+ {
+ index += hash2;
+ if (index >= size)
+ index -= size;
+
+ entry = htab->entries[index];
+ if (entry == HTAB_EMPTY_ENTRY
+ || (entry != HTAB_DELETED_ENTRY && htab_eq (entry, element)))
+ return entry;
+ }
+}
+
+/* This function searches for a hash table slot containing an entry
+ equal to the given element. To delete an entry, call this with
+ insert=NO_INSERT, then call htab_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. */
+
+static hash_entry_type *
+htab_find_slot (htab_t *htabp, const hash_entry_type element,
+ enum insert_option insert)
+{
+ hash_entry_type *first_deleted_slot;
+ hashval_t index, hash2, hash = htab_hash (element);
+ size_t size;
+ hash_entry_type entry;
+ htab_t htab = *htabp;
+
+ size = htab_size (htab);
+ if (insert == INSERT && size * 3 <= htab->n_elements * 4)
+ {
+ htab = *htabp = htab_expand (htab);
+ size = htab_size (htab);
+ }
+
+ index = htab_mod (hash, htab);
+
+ first_deleted_slot = NULL;
+
+ entry = htab->entries[index];
+ if (entry == HTAB_EMPTY_ENTRY)
+ goto empty_entry;
+ else if (entry == HTAB_DELETED_ENTRY)
+ first_deleted_slot = &htab->entries[index];
+ else if (htab_eq (entry, element))
+ return &htab->entries[index];
+
+ hash2 = htab_mod_m2 (hash, htab);
+ for (;;)
+ {
+ index += hash2;
+ if (index >= size)
+ index -= size;
+
+ entry = htab->entries[index];
+ if (entry == HTAB_EMPTY_ENTRY)
+ goto empty_entry;
+ else if (entry == HTAB_DELETED_ENTRY)
+ {
+ if (!first_deleted_slot)
+ first_deleted_slot = &htab->entries[index];
+ }
+ else if (htab_eq (entry, element))
+ return &htab->entries[index];
+ }
+
+ empty_entry:
+ if (insert == NO_INSERT)
+ return NULL;
+
+ if (first_deleted_slot)
+ {
+ htab->n_deleted--;
+ *first_deleted_slot = HTAB_EMPTY_ENTRY;
+ return first_deleted_slot;
+ }
+
+ htab->n_elements++;
+ return &htab->entries[index];
+}
+
+/* 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. */
+
+static inline void
+htab_clear_slot (htab_t htab, hash_entry_type *slot)
+{
+ if (slot < htab->entries || slot >= htab->entries + htab_size (htab)
+ || *slot == HTAB_EMPTY_ENTRY || *slot == HTAB_DELETED_ENTRY)
+ abort ();
+
+ *slot = HTAB_DELETED_ENTRY;
+ htab->n_deleted++;
+}
+
+/* Returns a hash code for pointer P. Simplified version of evahash */
+
+static inline hashval_t
+hash_pointer (const void *p)
+{
+ uintptr_t v = (uintptr_t) p;
+ if (sizeof (v) > sizeof (hashval_t))
+ v ^= v >> (sizeof (uintptr_t) / 2 * __CHAR_BIT__);
+ return v;
+}
diff --git a/libgomp/libgomp.h b/libgomp/libgomp.h
index 322a43520ee..bdc0486ad12 100644
--- a/libgomp/libgomp.h
+++ b/libgomp/libgomp.h
@@ -39,6 +39,7 @@
#include <pthread.h>
#include <stdbool.h>
+#include <stdlib.h>
#ifdef HAVE_ATTRIBUTE_VISIBILITY
# pragma GCC visibility push(hidden)
@@ -201,6 +202,10 @@ struct gomp_team_state
/* Active nesting level. Only active parallel regions are counted. */
unsigned active_level;
+ /* Place-partition-var, offset and length into gomp_places_list array. */
+ unsigned place_partition_off;
+ unsigned place_partition_len;
+
#ifdef HAVE_SYNC_BUILTINS
/* Number of single stmts encountered. */
unsigned long single_count;
@@ -214,30 +219,40 @@ struct gomp_team_state
unsigned long static_trip;
};
-/* These are the OpenMP 3.0 Internal Control Variables described in
+struct target_mem_desc;
+
+/* These are the OpenMP 4.0 Internal Control Variables described in
section 2.3.1. Those described as having one copy per task are
stored within the structure; those described as having one copy
for the whole program are (naturally) global variables. */
-
+
struct gomp_task_icv
{
unsigned long nthreads_var;
enum gomp_schedule_type run_sched_var;
int run_sched_modifier;
+ int default_device_var;
+ unsigned int thread_limit_var;
bool dyn_var;
bool nest_var;
+ char bind_var;
+ /* Internal ICV. */
+ struct target_mem_desc *target_data;
};
extern struct gomp_task_icv gomp_global_icv;
-extern unsigned long gomp_thread_limit_var;
-extern unsigned long gomp_remaining_threads_count;
#ifndef HAVE_SYNC_BUILTINS
-extern gomp_mutex_t gomp_remaining_threads_lock;
+extern gomp_mutex_t gomp_managed_threads_lock;
#endif
extern unsigned long gomp_max_active_levels_var;
+extern bool gomp_cancel_var;
extern unsigned long long gomp_spin_count_var, gomp_throttled_spin_count_var;
extern unsigned long gomp_available_cpus, gomp_managed_threads;
extern unsigned long *gomp_nthreads_var_list, gomp_nthreads_var_list_len;
+extern char *gomp_bind_var_list;
+extern unsigned long gomp_bind_var_list_len;
+extern void **gomp_places_list;
+extern unsigned long gomp_places_list_len;
enum gomp_task_kind
{
@@ -247,6 +262,27 @@ enum gomp_task_kind
GOMP_TASK_TIED
};
+struct gomp_task;
+struct gomp_taskgroup;
+struct htab;
+
+struct gomp_task_depend_entry
+{
+ void *addr;
+ struct gomp_task_depend_entry *next;
+ struct gomp_task_depend_entry *prev;
+ struct gomp_task *task;
+ bool is_in;
+ bool redundant;
+};
+
+struct gomp_dependers_vec
+{
+ size_t n_elem;
+ size_t allocated;
+ struct gomp_task *elem[];
+};
+
/* This structure describes a "task" to be run by a thread. */
struct gomp_task
@@ -257,6 +293,13 @@ struct gomp_task
struct gomp_task *prev_child;
struct gomp_task *next_queue;
struct gomp_task *prev_queue;
+ struct gomp_task *next_taskgroup;
+ struct gomp_task *prev_taskgroup;
+ struct gomp_taskgroup *taskgroup;
+ struct gomp_dependers_vec *dependers;
+ struct htab *depend_hash;
+ size_t depend_count;
+ size_t num_dependees;
struct gomp_task_icv icv;
void (*fn) (void *);
void *fn_data;
@@ -264,7 +307,19 @@ struct gomp_task
bool in_taskwait;
bool in_tied_task;
bool final_task;
+ bool copy_ctors_done;
gomp_sem_t taskwait_sem;
+ struct gomp_task_depend_entry depend[];
+};
+
+struct gomp_taskgroup
+{
+ struct gomp_taskgroup *prev;
+ struct gomp_task *children;
+ bool in_taskgroup_wait;
+ bool cancelled;
+ gomp_sem_t taskgroup_sem;
+ size_t num_children;
};
/* This structure describes a "team" of threads. These are the threads
@@ -293,6 +348,12 @@ struct gomp_team
of the threads in the team. */
gomp_sem_t **ordered_release;
+ /* List of work shares on which gomp_fini_work_share hasn't been
+ called yet. If the team hasn't been cancelled, this should be
+ equal to each thr->ts.work_share, but otherwise it can be a possibly
+ long list of workshares. */
+ struct gomp_work_share *work_shares_to_free;
+
/* List of gomp_work_share structs chained through next_free fields.
This is populated and taken off only by the first thread in the
team encountering a new work sharing construct, in a critical
@@ -324,8 +385,20 @@ struct gomp_team
gomp_mutex_t task_lock;
struct gomp_task *task_queue;
- int task_count;
- int task_running_count;
+ /* Number of all GOMP_TASK_{WAITING,TIED} tasks in the team. */
+ unsigned int task_count;
+ /* Number of GOMP_TASK_WAITING tasks currently waiting to be scheduled. */
+ unsigned int task_queued_count;
+ /* Number of GOMP_TASK_{WAITING,TIED} tasks currently running
+ directly in gomp_barrier_handle_tasks; tasks spawned
+ from e.g. GOMP_taskwait or GOMP_taskgroup_end don't count, even when
+ that is called from a task run from gomp_barrier_handle_tasks.
+ task_running_count should be always <= team->nthreads,
+ and if current task isn't in_tied_task, then it will be
+ even < team->nthreads. */
+ unsigned int task_running_count;
+ int work_share_cancelled;
+ int team_cancelled;
/* This array contains structures for implicit tasks. */
struct gomp_task implicit_task[];
@@ -350,7 +423,11 @@ struct gomp_thread
/* This semaphore is used for ordered loops. */
gomp_sem_t release;
- /* user pthread thread pool */
+ /* Place this thread is bound to plus one, or zero if not bound
+ to any place. */
+ unsigned int place;
+
+ /* User pthread thread pool */
struct gomp_thread_pool *thread_pool;
};
@@ -363,11 +440,23 @@ struct gomp_thread_pool
unsigned threads_size;
unsigned threads_used;
struct gomp_team *last_team;
+ /* Number of threads running in this contention group. */
+ unsigned long threads_busy;
/* This barrier holds and releases threads waiting in threads. */
gomp_barrier_t threads_dock;
};
+enum gomp_cancel_kind
+{
+ GOMP_CANCEL_PARALLEL = 1,
+ GOMP_CANCEL_LOOP = 2,
+ GOMP_CANCEL_FOR = GOMP_CANCEL_LOOP,
+ GOMP_CANCEL_DO = GOMP_CANCEL_LOOP,
+ GOMP_CANCEL_SECTIONS = 4,
+ GOMP_CANCEL_TASKGROUP = 8
+};
+
/* ... and here is that TLS data. */
#ifdef HAVE_TLS
@@ -402,17 +491,22 @@ static inline struct gomp_task_icv *gomp_icv (bool write)
/* The attributes to be used during thread creation. */
extern pthread_attr_t gomp_thread_attr;
-/* Other variables. */
-
-extern unsigned short *gomp_cpu_affinity;
-extern size_t gomp_cpu_affinity_len;
-
/* Function prototypes. */
/* affinity.c */
extern void gomp_init_affinity (void);
-extern void gomp_init_thread_affinity (pthread_attr_t *);
+extern void gomp_init_thread_affinity (pthread_attr_t *, unsigned int);
+extern void **gomp_affinity_alloc (unsigned long, bool);
+extern void gomp_affinity_init_place (void *);
+extern bool gomp_affinity_add_cpus (void *, unsigned long, unsigned long,
+ long, bool);
+extern bool gomp_affinity_remove_cpu (void *, unsigned long);
+extern bool gomp_affinity_copy_place (void *, void *, long);
+extern bool gomp_affinity_same_place (void *, void *);
+extern bool gomp_affinity_finalize_place_list (bool);
+extern bool gomp_affinity_init_level (int, unsigned long, bool);
+extern void gomp_affinity_print_place (void *);
/* alloc.c */
@@ -486,6 +580,8 @@ extern void gomp_barrier_handle_tasks (gomp_barrier_state_t);
static void inline
gomp_finish_task (struct gomp_task *task)
{
+ if (__builtin_expect (task->depend_hash != NULL, 0))
+ free (task->depend_hash);
gomp_sem_destroy (&task->taskwait_sem);
}
@@ -493,8 +589,13 @@ gomp_finish_task (struct gomp_task *task)
extern struct gomp_team *gomp_new_team (unsigned);
extern void gomp_team_start (void (*) (void *), void *, unsigned,
- struct gomp_team *);
+ unsigned, struct gomp_team *);
extern void gomp_team_end (void);
+extern void gomp_free_thread (void *);
+
+/* target.c */
+
+extern int gomp_get_num_devices (void);
/* work.c */
@@ -502,6 +603,7 @@ extern void gomp_init_work_share (struct gomp_work_share *, bool, unsigned);
extern void gomp_fini_work_share (struct gomp_work_share *);
extern bool gomp_work_share_start (bool);
extern void gomp_work_share_end (void);
+extern bool gomp_work_share_end_cancel (void);
extern void gomp_work_share_end_nowait (void);
static inline void
@@ -580,11 +682,19 @@ extern int gomp_test_nest_lock_25 (omp_nest_lock_25_t *) __GOMP_NOTHROW;
#endif
#ifdef HAVE_ATTRIBUTE_ALIAS
+# define ialias_ulp ialias_str1(__USER_LABEL_PREFIX__)
+# define ialias_str1(x) ialias_str2(x)
+# define ialias_str2(x) #x
# define ialias(fn) \
extern __typeof (fn) gomp_ialias_##fn \
__attribute__ ((alias (#fn))) attribute_hidden;
+# define ialias_redirect(fn) \
+ extern __typeof (fn) fn __asm__ (ialias_ulp "gomp_ialias_" #fn) attribute_hidden;
+# define ialias_call(fn) gomp_ialias_ ## fn
#else
# define ialias(fn)
+# define ialias_redirect(fn)
+# define ialias_call(fn) fn
#endif
#endif /* LIBGOMP_H */
diff --git a/libgomp/libgomp.map b/libgomp/libgomp.map
index 7b051f96aab..b102fd88357 100644
--- a/libgomp/libgomp.map
+++ b/libgomp/libgomp.map
@@ -113,6 +113,27 @@ OMP_3.1 {
omp_in_final_;
} OMP_3.0;
+OMP_4.0 {
+ global:
+ omp_get_cancellation;
+ omp_get_cancellation_;
+ omp_get_proc_bind;
+ omp_get_proc_bind_;
+ omp_set_default_device;
+ omp_set_default_device_;
+ omp_set_default_device_8_;
+ omp_get_default_device;
+ omp_get_default_device_;
+ omp_get_num_devices;
+ omp_get_num_devices_;
+ omp_get_num_teams;
+ omp_get_num_teams_;
+ omp_get_team_num;
+ omp_get_team_num_;
+ omp_is_initial_device;
+ omp_is_initial_device_;
+} OMP_3.1;
+
GOMP_1.0 {
global:
GOMP_atomic_end;
@@ -184,3 +205,25 @@ GOMP_3.0 {
global:
GOMP_taskyield;
} GOMP_2.0;
+
+GOMP_4.0 {
+ global:
+ GOMP_barrier_cancel;
+ GOMP_cancel;
+ GOMP_cancellation_point;
+ GOMP_loop_end_cancel;
+ GOMP_parallel_loop_dynamic;
+ GOMP_parallel_loop_guided;
+ GOMP_parallel_loop_runtime;
+ GOMP_parallel_loop_static;
+ GOMP_parallel_sections;
+ GOMP_parallel;
+ GOMP_sections_end_cancel;
+ GOMP_taskgroup_start;
+ GOMP_taskgroup_end;
+ GOMP_target;
+ GOMP_target_data;
+ GOMP_target_end_data;
+ GOMP_target_update;
+ GOMP_teams;
+} GOMP_3.0;
diff --git a/libgomp/libgomp.spec.in b/libgomp/libgomp.spec.in
index b7319f33a53..5651603f487 100644
--- a/libgomp/libgomp.spec.in
+++ b/libgomp/libgomp.spec.in
@@ -1,3 +1,3 @@
# This spec file is read by gcc when linking. It is used to specify the
-# standard libraries we need in order to link with -fopenmp.
+# standard libraries we need in order to link with libgomp.
*link_gomp: @link_gomp@
diff --git a/libgomp/libgomp.texi b/libgomp/libgomp.texi
index 2985128f8ac..ba430fc9fd7 100644
--- a/libgomp/libgomp.texi
+++ b/libgomp/libgomp.texi
@@ -106,17 +106,17 @@ for multi-platform shared-memory parallel programming in C/C++ and Fortran.
@chapter Enabling OpenMP
To activate the OpenMP extensions for C/C++ and Fortran, the compile-time
-flag @command{-fopenmp} must be specified. This enables the OpenMP directive
+flag @command{-fopenmp} must be specified. This enables the OpenMP directive
@code{#pragma omp} in C/C++ and @code{!$omp} directives in free form,
@code{c$omp}, @code{*$omp} and @code{!$omp} directives in fixed form,
@code{!$} conditional compilation sentinels in free form and @code{c$},
-@code{*$} and @code{!$} sentinels in fixed form, for Fortran. The flag also
+@code{*$} and @code{!$} sentinels in fixed form, for Fortran. The flag also
arranges for automatic linking of the OpenMP runtime library
(@ref{Runtime Library Routines}).
A complete description of all OpenMP directives accepted may be found in
the @uref{http://www.openmp.org, OpenMP Application Program Interface} manual,
-version 3.1.
+version 4.0.
@c ---------------------------------------------------------------------
@@ -126,28 +126,37 @@ version 3.1.
@node Runtime Library Routines
@chapter Runtime Library Routines
-The runtime routines described here are defined by section 3 of the OpenMP
-specifications in version 3.1. The routines are structured in following
+The runtime routines described here are defined by Section 3 of the OpenMP
+specification in version 4.0. The routines are structured in following
three parts:
-Control threads, processors and the parallel environment.
+Control threads, processors and the parallel environment. They have C
+linkage, and do not throw exceptions.
@menu
* omp_get_active_level:: Number of active parallel regions
* omp_get_ancestor_thread_num:: Ancestor thread ID
+* omp_get_cancellation:: Whether cancellation support is enabled
+* omp_get_default_device:: Get the default device for target regions
* omp_get_dynamic:: Dynamic teams setting
* omp_get_level:: Number of parallel regions
* omp_get_max_active_levels:: Maximum number of active regions
* omp_get_max_threads:: Maximum number of threads of parallel region
* omp_get_nested:: Nested parallel regions
+* omp_get_num_devices:: Number of target devices
* omp_get_num_procs:: Number of processors online
+* omp_get_num_teams:: Number of teams
* omp_get_num_threads:: Size of the active team
+* omp_get_proc_bind:: Whether theads may be moved between CPUs
* omp_get_schedule:: Obtain the runtime scheduling method
+* omp_get_team_num:: Get team number
* omp_get_team_size:: Number of threads in a team
* omp_get_thread_limit:: Maximum number of threads
* omp_get_thread_num:: Current thread ID
* omp_in_parallel:: Whether a parallel region is active
* omp_in_final:: Whether in final or included task region
+* omp_is_initial_device:: Whether executing on the host device
+* omp_set_default_device:: Set the default device for target regions
* omp_set_dynamic:: Enable/disable dynamic teams
* omp_set_max_active_levels:: Limits the number of active parallel regions
* omp_set_nested:: Enable/disable nested parallel regions
@@ -200,7 +209,7 @@ which enclose the calling call.
@ref{omp_get_level}, @ref{omp_get_max_active_levels}, @ref{omp_set_max_active_levels}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.19.
+@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 3.2.20.
@end table
@@ -210,7 +219,7 @@ which enclose the calling call.
@table @asis
@item @emph{Description}:
This function returns the thread identification number for the given
-nesting level of the current thread. For values of @var{level} outside
+nesting level of the current thread. For values of @var{level} outside
zero to @code{omp_get_level} -1 is returned; if @var{level} is
@code{omp_get_level} the result is identical to @code{omp_get_thread_num}.
@@ -229,7 +238,60 @@ zero to @code{omp_get_level} -1 is returned; if @var{level} is
@ref{omp_get_level}, @ref{omp_get_thread_num}, @ref{omp_get_team_size}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.17.
+@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 3.2.18.
+@end table
+
+
+
+@node omp_get_cancellation
+@section @code{omp_get_cancellation} -- Whether cancellation support is enabled
+@table @asis
+@item @emph{Description}:
+This function returns @code{true} if cancellation is activated, @code{false}
+otherwise. Here, @code{true} and @code{false} represent their language-specific
+counterparts. Unless @env{OMP_CANCELLATION} is set true, cancellations are
+deactivated.
+
+@item @emph{C/C++}:
+@multitable @columnfractions .20 .80
+@item @emph{Prototype}: @tab @code{int omp_get_cancellation(void);}
+@end multitable
+
+@item @emph{Fortran}:
+@multitable @columnfractions .20 .80
+@item @emph{Interface}: @tab @code{logical function omp_get_cancellation()}
+@end multitable
+
+@item @emph{See also}:
+@ref{OMP_CANCELLATION}
+
+@item @emph{Reference}:
+@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 3.2.9.
+@end table
+
+
+
+@node omp_get_default_device
+@section @code{omp_get_default_device} -- Get the default device for target regions
+@table @asis
+@item @emph{Description}:
+Get the default device for target regions without device clause.
+
+@item @emph{C/C++}:
+@multitable @columnfractions .20 .80
+@item @emph{Prototype}: @tab @code{int omp_get_default_device(void);}
+@end multitable
+
+@item @emph{Fortran}:
+@multitable @columnfractions .20 .80
+@item @emph{Interface}: @tab @code{integer function omp_get_default_device()}
+@end multitable
+
+@item @emph{See also}:
+@ref{OMP_DEFAULT_DEVICE}, @ref{omp_set_default_device}
+
+@item @emph{Reference}:
+@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 3.2.24.
@end table
@@ -243,8 +305,8 @@ Here, @code{true} and @code{false} represent their language-specific
counterparts.
The dynamic team setting may be initialized at startup by the
-@code{OMP_DYNAMIC} environment variable or at runtime using
-@code{omp_set_dynamic}. If undefined, dynamic adjustment is
+@env{OMP_DYNAMIC} environment variable or at runtime using
+@code{omp_set_dynamic}. If undefined, dynamic adjustment is
disabled by default.
@item @emph{C/C++}:
@@ -261,7 +323,7 @@ disabled by default.
@ref{omp_set_dynamic}, @ref{OMP_DYNAMIC}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.8.
+@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 3.2.8.
@end table
@@ -287,7 +349,7 @@ which enclose the calling call.
@ref{omp_get_active_level}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.16.
+@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 3.2.17.
@end table
@@ -312,7 +374,7 @@ This function obtains the maximum allowed number of nested, active parallel regi
@ref{omp_set_max_active_levels}, @ref{omp_get_active_level}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.15.
+@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 3.2.16.
@end table
@@ -338,7 +400,7 @@ that does not use the clause @code{num_threads}.
@ref{omp_set_num_threads}, @ref{omp_set_dynamic}, @ref{omp_get_thread_limit}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.3.
+@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 3.2.3.
@end table
@@ -348,12 +410,12 @@ that does not use the clause @code{num_threads}.
@table @asis
@item @emph{Description}:
This function returns @code{true} if nested parallel regions are
-enabled, @code{false} otherwise. Here, @code{true} and @code{false}
+enabled, @code{false} otherwise. Here, @code{true} and @code{false}
represent their language-specific counterparts.
Nested parallel regions may be initialized at startup by the
-@code{OMP_NESTED} environment variable or at runtime using
-@code{omp_set_nested}. If undefined, nested parallel regions are
+@env{OMP_NESTED} environment variable or at runtime using
+@code{omp_set_nested}. If undefined, nested parallel regions are
disabled by default.
@item @emph{C/C++}:
@@ -370,7 +432,29 @@ disabled by default.
@ref{omp_set_nested}, @ref{OMP_NESTED}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.10.
+@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 3.2.11.
+@end table
+
+
+
+@node omp_get_num_devices
+@section @code{omp_get_num_devices} -- Number of target devices
+@table @asis
+@item @emph{Description}:
+Returns the number of target devices.
+
+@item @emph{C/C++}:
+@multitable @columnfractions .20 .80
+@item @emph{Prototype}: @tab @code{int omp_get_num_devices(void);}
+@end multitable
+
+@item @emph{Fortran}:
+@multitable @columnfractions .20 .80
+@item @emph{Interface}: @tab @code{integer function omp_get_num_devices()}
+@end multitable
+
+@item @emph{Reference}:
+@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 3.2.25.
@end table
@@ -379,7 +463,7 @@ disabled by default.
@section @code{omp_get_num_procs} -- Number of processors online
@table @asis
@item @emph{Description}:
-Returns the number of processors online.
+Returns the number of processors online on that device.
@item @emph{C/C++}:
@multitable @columnfractions .20 .80
@@ -392,7 +476,29 @@ Returns the number of processors online.
@end multitable
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.5.
+@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 3.2.5.
+@end table
+
+
+
+@node omp_get_num_teams
+@section @code{omp_get_num_teams} -- Number of teams
+@table @asis
+@item @emph{Description}:
+Returns the number of teams in the current team region.
+
+@item @emph{C/C++}:
+@multitable @columnfractions .20 .80
+@item @emph{Prototype}: @tab @code{int omp_get_num_teams(void);}
+@end multitable
+
+@item @emph{Fortran}:
+@multitable @columnfractions .20 .80
+@item @emph{Interface}: @tab @code{integer function omp_get_num_teams()}
+@end multitable
+
+@item @emph{Reference}:
+@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 3.2.26.
@end table
@@ -401,14 +507,14 @@ Returns the number of processors online.
@section @code{omp_get_num_threads} -- Size of the active team
@table @asis
@item @emph{Description}:
-Returns the number of threads in the current team. In a sequential section of
+Returns the number of threads in the current team. In a sequential section of
the program @code{omp_get_num_threads} returns 1.
The default team size may be initialized at startup by the
-@code{OMP_NUM_THREADS} environment variable. At runtime, the size
+@env{OMP_NUM_THREADS} environment variable. At runtime, the size
of the current team may be set either by the @code{NUM_THREADS}
-clause or by @code{omp_set_num_threads}. If none of the above were
-used to define a specific value and @code{OMP_DYNAMIC} is disabled,
+clause or by @code{omp_set_num_threads}. If none of the above were
+used to define a specific value and @env{OMP_DYNAMIC} is disabled,
one thread per CPU online is used.
@item @emph{C/C++}:
@@ -425,7 +531,35 @@ one thread per CPU online is used.
@ref{omp_get_max_threads}, @ref{omp_set_num_threads}, @ref{OMP_NUM_THREADS}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.2.
+@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 3.2.2.
+@end table
+
+
+
+@node omp_get_proc_bind
+@section @code{omp_get_proc_bind} -- Whether theads may be moved between CPUs
+@table @asis
+@item @emph{Description}:
+This functions returns the currently active thread affinity policy, which is
+set via @env{OMP_PROC_BIND}. Possible values are @code{omp_proc_bind_false},
+@code{omp_proc_bind_true}, @code{omp_proc_bind_master},
+@code{omp_proc_bind_close} and @code{omp_proc_bind_spread}.
+
+@item @emph{C/C++}:
+@multitable @columnfractions .20 .80
+@item @emph{Prototype}: @tab @code{omp_proc_bind_t omp_get_proc_bind(void);}
+@end multitable
+
+@item @emph{Fortran}:
+@multitable @columnfractions .20 .80
+@item @emph{Interface}: @tab @code{integer(kind=omp_proc_bind_kind) function omp_get_proc_bind()}
+@end multitable
+
+@item @emph{See also}:
+@ref{OMP_PROC_BIND}, @ref{OMP_PLACES}, @ref{GOMP_CPU_AFFINITY},
+
+@item @emph{Reference}:
+@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 3.2.22.
@end table
@@ -434,19 +568,19 @@ one thread per CPU online is used.
@section @code{omp_get_schedule} -- Obtain the runtime scheduling method
@table @asis
@item @emph{Description}:
-Obtain the runtime scheduling method. The @var{kind} argument will be
+Obtain the runtime scheduling method. The @var{kind} argument will be
set to the value @code{omp_sched_static}, @code{omp_sched_dynamic},
-@code{omp_sched_guided} or @code{omp_sched_auto}. The second argument,
+@code{omp_sched_guided} or @code{omp_sched_auto}. The second argument,
@var{modifier}, is set to the chunk size.
@item @emph{C/C++}
@multitable @columnfractions .20 .80
-@item @emph{Prototype}: @tab @code{void omp_schedule(omp_sched_t *kind, int *modifier);}
+@item @emph{Prototype}: @tab @code{void omp_get_schedule(omp_sched_t *kind, int *modifier);}
@end multitable
@item @emph{Fortran}:
@multitable @columnfractions .20 .80
-@item @emph{Interface}: @tab @code{subroutine omp_schedule(kind, modifier)}
+@item @emph{Interface}: @tab @code{subroutine omp_get_schedule(kind, modifier)}
@item @tab @code{integer(kind=omp_sched_kind) kind}
@item @tab @code{integer modifier}
@end multitable
@@ -455,7 +589,29 @@ set to the value @code{omp_sched_static}, @code{omp_sched_dynamic},
@ref{omp_set_schedule}, @ref{OMP_SCHEDULE}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.12.
+@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 3.2.13.
+@end table
+
+
+
+@node omp_get_team_num
+@section @code{omp_get_team_num} -- Get team number
+@table @asis
+@item @emph{Description}:
+Returns the team number of the calling thread.
+
+@item @emph{C/C++}:
+@multitable @columnfractions .20 .80
+@item @emph{Prototype}: @tab @code{int omp_get_team_num(void);}
+@end multitable
+
+@item @emph{Fortran}:
+@multitable @columnfractions .20 .80
+@item @emph{Interface}: @tab @code{integer function omp_get_team_num()}
+@end multitable
+
+@item @emph{Reference}:
+@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 3.2.27.
@end table
@@ -465,7 +621,7 @@ set to the value @code{omp_sched_static}, @code{omp_sched_dynamic},
@table @asis
@item @emph{Description}:
This function returns the number of threads in a thread team to which
-either the current thread or its ancestor belongs. For values of @var{level}
+either the current thread or its ancestor belongs. For values of @var{level}
outside zero to @code{omp_get_level}, -1 is returned; if @var{level} is zero,
1 is returned, and for @code{omp_get_level}, the result is identical
to @code{omp_get_num_threads}.
@@ -485,7 +641,7 @@ to @code{omp_get_num_threads}.
@ref{omp_get_num_threads}, @ref{omp_get_level}, @ref{omp_get_ancestor_thread_num}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.18.
+@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 3.2.19.
@end table
@@ -510,19 +666,19 @@ Return the maximum number of threads of the program.
@ref{omp_get_max_threads}, @ref{OMP_THREAD_LIMIT}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.13.
+@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 3.2.14.
@end table
-@node omp_get_thread_num
+@node omp_get_thread_num
@section @code{omp_get_thread_num} -- Current thread ID
@table @asis
@item @emph{Description}:
Returns a unique thread identification number within the current team.
In a sequential parts of the program, @code{omp_get_thread_num}
-always returns 0. In parallel regions the return value varies
-from 0 to @code{omp_get_num_threads}-1 inclusive. The return
+always returns 0. In parallel regions the return value varies
+from 0 to @code{omp_get_num_threads}-1 inclusive. The return
value of the master thread of a team is always 0.
@item @emph{C/C++}:
@@ -539,7 +695,7 @@ value of the master thread of a team is always 0.
@ref{omp_get_num_threads}, @ref{omp_get_ancestor_thread_num}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.4.
+@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 3.2.4.
@end table
@@ -548,8 +704,8 @@ value of the master thread of a team is always 0.
@section @code{omp_in_parallel} -- Whether a parallel region is active
@table @asis
@item @emph{Description}:
-This function returns @code{true} if currently running in parallel,
-@code{false} otherwise. Here, @code{true} and @code{false} represent
+This function returns @code{true} if currently running in parallel,
+@code{false} otherwise. Here, @code{true} and @code{false} represent
their language-specific counterparts.
@item @emph{C/C++}:
@@ -563,7 +719,7 @@ their language-specific counterparts.
@end multitable
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.6.
+@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 3.2.6.
@end table
@@ -572,7 +728,7 @@ their language-specific counterparts.
@table @asis
@item @emph{Description}:
This function returns @code{true} if currently running in a final
-or included task region, @code{false} otherwise. Here, @code{true}
+or included task region, @code{false} otherwise. Here, @code{true}
and @code{false} represent their language-specific counterparts.
@item @emph{C/C++}:
@@ -586,16 +742,68 @@ and @code{false} represent their language-specific counterparts.
@end multitable
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.20.
+@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 3.2.21.
+@end table
+
+
+
+@node omp_is_initial_device
+@section @code{omp_is_initial_device} -- Whether executing on the host device
+@table @asis
+@item @emph{Description}:
+This function returns @code{true} if currently running on the host device,
+@code{false} otherwise. Here, @code{true} and @code{false} represent
+their language-specific counterparts.
+
+@item @emph{C/C++}:
+@multitable @columnfractions .20 .80
+@item @emph{Prototype}: @tab @code{int omp_is_initial_device(void);}
+@end multitable
+
+@item @emph{Fortran}:
+@multitable @columnfractions .20 .80
+@item @emph{Interface}: @tab @code{logical function omp_is_initial_device()}
+@end multitable
+
+@item @emph{Reference}:
+@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 3.2.28.
+@end table
+
+
+
+@node omp_set_default_device
+@section @code{omp_set_default_device} -- Set the default device for target regions
+@table @asis
+@item @emph{Description}:
+Set the default device for target regions without device clause. The argument
+shall be a nonnegative device number.
+
+@item @emph{C/C++}:
+@multitable @columnfractions .20 .80
+@item @emph{Prototype}: @tab @code{void omp_set_default_device(int device_num);}
+@end multitable
+
+@item @emph{Fortran}:
+@multitable @columnfractions .20 .80
+@item @emph{Interface}: @tab @code{subroutine omp_set_default_device(device_num)}
+@item @tab @code{integer device_num}
+@end multitable
+
+@item @emph{See also}:
+@ref{OMP_DEFAULT_DEVICE}, @ref{omp_get_default_device}
+
+@item @emph{Reference}:
+@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 3.2.23.
@end table
+
@node omp_set_dynamic
@section @code{omp_set_dynamic} -- Enable/disable dynamic teams
@table @asis
@item @emph{Description}:
Enable or disable the dynamic adjustment of the number of threads
-within a team. The function takes the language-specific equivalent
+within a team. The function takes the language-specific equivalent
of @code{true} and @code{false}, where @code{true} enables dynamic
adjustment of team sizes and @code{false} disables it.
@@ -614,7 +822,7 @@ adjustment of team sizes and @code{false} disables it.
@ref{OMP_DYNAMIC}, @ref{omp_get_dynamic}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.7.
+@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 3.2.7.
@end table
@@ -641,7 +849,7 @@ parallel regions.
@ref{omp_get_max_active_levels}, @ref{omp_get_active_level}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.14.
+@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 3.2.15.
@end table
@@ -651,7 +859,7 @@ parallel regions.
@table @asis
@item @emph{Description}:
Enable or disable nested parallel regions, i.e., whether team members
-are allowed to create new teams. The function takes the language-specific
+are allowed to create new teams. The function takes the language-specific
equivalent of @code{true} and @code{false}, where @code{true} enables
dynamic adjustment of team sizes and @code{false} disables it.
@@ -670,7 +878,7 @@ dynamic adjustment of team sizes and @code{false} disables it.
@ref{OMP_NESTED}, @ref{omp_get_nested}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.9.
+@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 3.2.10.
@end table
@@ -680,8 +888,8 @@ dynamic adjustment of team sizes and @code{false} disables it.
@table @asis
@item @emph{Description}:
Specifies the number of threads used by default in subsequent parallel
-sections, if those do not specify a @code{num_threads} clause. The
-argument of @code{omp_set_num_threads} shall be a positive integer.
+sections, if those do not specify a @code{num_threads} clause. The
+argument of @code{omp_set_num_threads} shall be a positive integer.
@item @emph{C/C++}:
@multitable @columnfractions .20 .80
@@ -698,7 +906,7 @@ argument of @code{omp_set_num_threads} shall be a positive integer.
@ref{OMP_NUM_THREADS}, @ref{omp_get_num_threads}, @ref{omp_get_max_threads}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.1.
+@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 3.2.1.
@end table
@@ -707,16 +915,16 @@ argument of @code{omp_set_num_threads} shall be a positive integer.
@section @code{omp_set_schedule} -- Set the runtime scheduling method
@table @asis
@item @emph{Description}:
-Sets the runtime scheduling method. The @var{kind} argument can have the
+Sets the runtime scheduling method. The @var{kind} argument can have the
value @code{omp_sched_static}, @code{omp_sched_dynamic},
-@code{omp_sched_guided} or @code{omp_sched_auto}. Except for
+@code{omp_sched_guided} or @code{omp_sched_auto}. Except for
@code{omp_sched_auto}, the chunk size is set to the value of
@var{modifier} if positive, or to the default value if zero or negative.
For @code{omp_sched_auto} the @var{modifier} argument is ignored.
@item @emph{C/C++}
@multitable @columnfractions .20 .80
-@item @emph{Prototype}: @tab @code{void omp_set_schedule(omp_sched_t *kind, int *modifier);}
+@item @emph{Prototype}: @tab @code{void omp_set_schedule(omp_sched_t kind, int modifier);}
@end multitable
@item @emph{Fortran}:
@@ -731,7 +939,7 @@ For @code{omp_sched_auto} the @var{modifier} argument is ignored.
@ref{OMP_SCHEDULE}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.2.11.
+@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 3.2.12.
@end table
@@ -740,7 +948,7 @@ For @code{omp_sched_auto} the @var{modifier} argument is ignored.
@section @code{omp_init_lock} -- Initialize simple lock
@table @asis
@item @emph{Description}:
-Initialize a simple lock. After initialization, the lock is in
+Initialize a simple lock. After initialization, the lock is in
an unlocked state.
@item @emph{C/C++}:
@@ -758,7 +966,7 @@ an unlocked state.
@ref{omp_destroy_lock}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.3.1.
+@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 3.3.1.
@end table
@@ -768,8 +976,8 @@ an unlocked state.
@table @asis
@item @emph{Description}:
Before setting a simple lock, the lock variable must be initialized by
-@code{omp_init_lock}. The calling thread is blocked until the lock
-is available. If the lock is already held by the current thread,
+@code{omp_init_lock}. The calling thread is blocked until the lock
+is available. If the lock is already held by the current thread,
a deadlock occurs.
@item @emph{C/C++}:
@@ -787,7 +995,7 @@ a deadlock occurs.
@ref{omp_init_lock}, @ref{omp_test_lock}, @ref{omp_unset_lock}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.3.3.
+@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 3.3.3.
@end table
@@ -797,9 +1005,9 @@ a deadlock occurs.
@table @asis
@item @emph{Description}:
Before setting a simple lock, the lock variable must be initialized by
-@code{omp_init_lock}. Contrary to @code{omp_set_lock}, @code{omp_test_lock}
-does not block if the lock is not available. This function returns
-@code{true} upon success, @code{false} otherwise. Here, @code{true} and
+@code{omp_init_lock}. Contrary to @code{omp_set_lock}, @code{omp_test_lock}
+does not block if the lock is not available. This function returns
+@code{true} upon success, @code{false} otherwise. Here, @code{true} and
@code{false} represent their language-specific counterparts.
@item @emph{C/C++}:
@@ -817,7 +1025,7 @@ does not block if the lock is not available. This function returns
@ref{omp_init_lock}, @ref{omp_set_lock}, @ref{omp_set_lock}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.3.5.
+@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 3.3.5.
@end table
@@ -827,9 +1035,9 @@ does not block if the lock is not available. This function returns
@table @asis
@item @emph{Description}:
A simple lock about to be unset must have been locked by @code{omp_set_lock}
-or @code{omp_test_lock} before. In addition, the lock must be held by the
-thread calling @code{omp_unset_lock}. Then, the lock becomes unlocked. If one
-or more threads attempted to set the lock before, one of them is chosen to,
+or @code{omp_test_lock} before. In addition, the lock must be held by the
+thread calling @code{omp_unset_lock}. Then, the lock becomes unlocked. If one
+or more threads attempted to set the lock before, one of them is chosen to,
again, set the lock to itself.
@item @emph{C/C++}:
@@ -847,7 +1055,7 @@ again, set the lock to itself.
@ref{omp_set_lock}, @ref{omp_test_lock}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.3.4.
+@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 3.3.4.
@end table
@@ -856,7 +1064,7 @@ again, set the lock to itself.
@section @code{omp_destroy_lock} -- Destroy simple lock
@table @asis
@item @emph{Description}:
-Destroy a simple lock. In order to be destroyed, a simple lock must be
+Destroy a simple lock. In order to be destroyed, a simple lock must be
in the unlocked state.
@item @emph{C/C++}:
@@ -874,7 +1082,7 @@ in the unlocked state.
@ref{omp_init_lock}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.3.2.
+@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 3.3.2.
@end table
@@ -883,7 +1091,7 @@ in the unlocked state.
@section @code{omp_init_nest_lock} -- Initialize nested lock
@table @asis
@item @emph{Description}:
-Initialize a nested lock. After initialization, the lock is in
+Initialize a nested lock. After initialization, the lock is in
an unlocked state and the nesting count is set to zero.
@item @emph{C/C++}:
@@ -901,7 +1109,7 @@ an unlocked state and the nesting count is set to zero.
@ref{omp_destroy_nest_lock}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.3.1.
+@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 3.3.1.
@end table
@@ -910,8 +1118,8 @@ an unlocked state and the nesting count is set to zero.
@table @asis
@item @emph{Description}:
Before setting a nested lock, the lock variable must be initialized by
-@code{omp_init_nest_lock}. The calling thread is blocked until the lock
-is available. If the lock is already held by the current thread, the
+@code{omp_init_nest_lock}. The calling thread is blocked until the lock
+is available. If the lock is already held by the current thread, the
nesting count for the lock is incremented.
@item @emph{C/C++}:
@@ -929,7 +1137,7 @@ nesting count for the lock is incremented.
@ref{omp_init_nest_lock}, @ref{omp_unset_nest_lock}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.3.3.
+@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 3.3.3.
@end table
@@ -939,10 +1147,10 @@ nesting count for the lock is incremented.
@table @asis
@item @emph{Description}:
Before setting a nested lock, the lock variable must be initialized by
-@code{omp_init_nest_lock}. Contrary to @code{omp_set_nest_lock},
+@code{omp_init_nest_lock}. Contrary to @code{omp_set_nest_lock},
@code{omp_test_nest_lock} does not block if the lock is not available.
If the lock is already held by the current thread, the new nesting count
-is returned. Otherwise, the return value equals zero.
+is returned. Otherwise, the return value equals zero.
@item @emph{C/C++}:
@multitable @columnfractions .20 .80
@@ -960,7 +1168,7 @@ is returned. Otherwise, the return value equals zero.
@ref{omp_init_lock}, @ref{omp_set_lock}, @ref{omp_set_lock}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.3.5.
+@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 3.3.5.
@end table
@@ -970,9 +1178,9 @@ is returned. Otherwise, the return value equals zero.
@table @asis
@item @emph{Description}:
A nested lock about to be unset must have been locked by @code{omp_set_nested_lock}
-or @code{omp_test_nested_lock} before. In addition, the lock must be held by the
-thread calling @code{omp_unset_nested_lock}. If the nesting count drops to zero, the
-lock becomes unlocked. If one ore more threads attempted to set the lock before,
+or @code{omp_test_nested_lock} before. In addition, the lock must be held by the
+thread calling @code{omp_unset_nested_lock}. If the nesting count drops to zero, the
+lock becomes unlocked. If one ore more threads attempted to set the lock before,
one of them is chosen to, again, set the lock to itself.
@item @emph{C/C++}:
@@ -990,7 +1198,7 @@ one of them is chosen to, again, set the lock to itself.
@ref{omp_set_nest_lock}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.3.4.
+@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 3.3.4.
@end table
@@ -999,7 +1207,7 @@ one of them is chosen to, again, set the lock to itself.
@section @code{omp_destroy_nest_lock} -- Destroy nested lock
@table @asis
@item @emph{Description}:
-Destroy a nested lock. In order to be destroyed, a nested lock must be
+Destroy a nested lock. In order to be destroyed, a nested lock must be
in the unlocked state and its nesting count must equal zero.
@item @emph{C/C++}:
@@ -1017,7 +1225,7 @@ in the unlocked state and its nesting count must equal zero.
@ref{omp_init_lock}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.3.2.
+@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 3.3.2.
@end table
@@ -1043,7 +1251,7 @@ successive clock ticks.
@ref{omp_get_wtime}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.4.2.
+@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 3.4.2.
@end table
@@ -1052,7 +1260,7 @@ successive clock ticks.
@section @code{omp_get_wtime} -- Elapsed wall clock time
@table @asis
@item @emph{Description}:
-Elapsed wall clock time in seconds. The time is measured per thread, no
+Elapsed wall clock time in seconds. The time is measured per thread, no
guarantee can be made that two distinct threads measure the same time.
Time is measured from some "time in the past", which is an arbitrary time
guaranteed not to change during the execution of the program.
@@ -1071,7 +1279,7 @@ guaranteed not to change during the execution of the program.
@ref{omp_get_wtick}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 3.4.1.
+@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 3.4.1.
@end table
@@ -1083,43 +1291,101 @@ guaranteed not to change during the execution of the program.
@node Environment Variables
@chapter Environment Variables
-The variables @env{OMP_DYNAMIC}, @env{OMP_MAX_ACTIVE_LEVELS},
-@env{OMP_NESTED}, @env{OMP_NUM_THREADS}, @env{OMP_SCHEDULE},
-@env{OMP_STACKSIZE},@env{OMP_THREAD_LIMIT} and @env{OMP_WAIT_POLICY}
-are defined by section 4 of the OpenMP specifications in version 3.1,
-while @env{GOMP_CPU_AFFINITY} and @env{GOMP_STACKSIZE} are GNU
-extensions.
+The environment variables which beginning with @env{OMP_} are defined by
+section 4 of the OpenMP specification in version 4.0, while those
+beginning with @env{GOMP_} are GNU extensions.
@menu
+* OMP_CANCELLATION:: Set whether cancellation is activated
+* OMP_DISPLAY_ENV:: Show OpenMP version and environment variables
+* OMP_DEFAULT_DEVICE:: Set the device used in target regions
* OMP_DYNAMIC:: Dynamic adjustment of threads
* OMP_MAX_ACTIVE_LEVELS:: Set the maximum number of nested parallel regions
* OMP_NESTED:: Nested parallel regions
* OMP_NUM_THREADS:: Specifies the number of threads to use
+* OMP_PROC_BIND:: Whether theads may be moved between CPUs
+* OMP_PLACES:: Specifies on which CPUs the theads should be placed
* OMP_STACKSIZE:: Set default thread stack size
* OMP_SCHEDULE:: How threads are scheduled
* OMP_THREAD_LIMIT:: Set the maximum number of threads
* OMP_WAIT_POLICY:: How waiting threads are handled
-* OMP_PROC_BIND:: Whether theads may be moved between CPUs
* GOMP_CPU_AFFINITY:: Bind threads to specific CPUs
* GOMP_STACKSIZE:: Set default thread stack size
+* GOMP_SPINCOUNT:: Set the busy-wait spin count
@end menu
+@node OMP_CANCELLATION
+@section @env{OMP_CANCELLATION} -- Set whether cancellation is activated
+@cindex Environment Variable
+@table @asis
+@item @emph{Description}:
+If set to @code{TRUE}, the cancellation is activated. If set to @code{FALSE} or
+if unset, cancellation is disabled and the @code{cancel} construct is ignored.
+
+@item @emph{See also}:
+@ref{omp_get_cancellation}
+
+@item @emph{Reference}:
+@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 4.11
+@end table
+
+
+
+@node OMP_DISPLAY_ENV
+@section @env{OMP_DISPLAY_ENV} -- Show OpenMP version and environment variables
+@cindex Environment Variable
+@table @asis
+@item @emph{Description}:
+If set to @code{TRUE}, the OpenMP version number and the values
+associated with the OpenMP environment variables are printed to @code{stderr}.
+If set to @code{VERBOSE}, it additionally shows the value of the environment
+variables which are GNU extensions. If undefined or set to @code{FALSE},
+this information will not be shown.
+
+
+@item @emph{Reference}:
+@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 4.12
+@end table
+
+
+
+@node OMP_DEFAULT_DEVICE
+@section @env{OMP_DEFAULT_DEVICE} -- Set the device used in target regions
+@cindex Environment Variable
+@table @asis
+@item @emph{Description}:
+Set to choose the device which is used in a @code{target} region, unless the
+value is overridden by @code{omp_set_default_device} or by a @code{device}
+clause. The value shall be the nonnegative device number. If no device with
+the given device number exists, the code is executed on the host. If unset,
+device number 0 will be used.
+
+
+@item @emph{See also}:
+@ref{omp_get_default_device}, @ref{omp_set_default_device},
+
+@item @emph{Reference}:
+@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 4.11
+@end table
+
+
+
@node OMP_DYNAMIC
@section @env{OMP_DYNAMIC} -- Dynamic adjustment of threads
@cindex Environment Variable
@table @asis
@item @emph{Description}:
Enable or disable the dynamic adjustment of the number of threads
-within a team. The value of this environment variable shall be
-@code{TRUE} or @code{FALSE}. If undefined, dynamic adjustment is
+within a team. The value of this environment variable shall be
+@code{TRUE} or @code{FALSE}. If undefined, dynamic adjustment is
disabled by default.
@item @emph{See also}:
@ref{omp_set_dynamic}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 4.3
+@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 4.3
@end table
@@ -1130,14 +1396,14 @@ disabled by default.
@table @asis
@item @emph{Description}:
Specifies the initial value for the maximum number of nested parallel
-regions. The value of this variable shall be a positive integer.
+regions. The value of this variable shall be a positive integer.
If undefined, the number of active levels is unlimited.
@item @emph{See also}:
@ref{omp_set_max_active_levels}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 4.8
+@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 4.9
@end table
@@ -1149,15 +1415,15 @@ If undefined, the number of active levels is unlimited.
@table @asis
@item @emph{Description}:
Enable or disable nested parallel regions, i.e., whether team members
-are allowed to create new teams. The value of this environment variable
-shall be @code{TRUE} or @code{FALSE}. If undefined, nested parallel
+are allowed to create new teams. The value of this environment variable
+shall be @code{TRUE} or @code{FALSE}. If undefined, nested parallel
regions are disabled by default.
@item @emph{See also}:
@ref{omp_set_nested}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 4.5
+@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 4.6
@end table
@@ -1168,16 +1434,85 @@ regions are disabled by default.
@cindex Implementation specific setting
@table @asis
@item @emph{Description}:
-Specifies the default number of threads to use in parallel regions. The
+Specifies the default number of threads to use in parallel regions. The
value of this variable shall be a comma-separated list of positive integers;
the value specified the number of threads to use for the corresponding nested
-level. If undefined one thread per CPU is used.
+level. If undefined one thread per CPU is used.
@item @emph{See also}:
@ref{omp_set_num_threads}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 4.2
+@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 4.2
+@end table
+
+
+
+@node OMP_PLACES
+@section @env{OMP_PLACES} -- Specifies on which CPUs the theads should be placed
+@cindex Environment Variable
+@table @asis
+@item @emph{Description}:
+The thread placement can be either specified using an abstract name or by an
+explicit list of the places. The abstract names @code{threads}, @code{cores}
+and @code{sockets} can be optionally followed by a positive number in
+parentheses, which denotes the how many places shall be created. With
+@code{threads} each place corresponds to a single hardware thread; @code{cores}
+to a single core with the corresponding number of hardware threads; and with
+@code{sockets} the place corresponds to a single socket. The resulting
+placement can be shown by setting the @env{OMP_DISPLAY_ENV} environment
+variable.
+
+Alternatively, the placement can be specified explicitly as comma-separated
+list of places. A place is specified by set of nonnegative numbers in curly
+braces, denoting the denoting the hardware threads. The hardware threads
+belonging to a place can either be specified as comma-separated list of
+nonnegative thread numbers or using an interval. Multiple places can also be
+either specified by a comma-separated list of places or by an interval. To
+specify an interval, a colon followed by the count is placed after after
+the hardware thread number or the place. Optionally, the length can be
+followed by a colon and the stride number -- otherwise a unit stride is
+assumed. For instance, the following specifies the same places list:
+@code{"@{0,1,2@}, @{3,4,6@}, @{7,8,9@}, @{10,11,12@}"};
+@code{"@{0:3@}, @{3:3@}, @{7:3@}, @{10:3@}"}; and @code{"@{0:2@}:4:3"}.
+
+If @env{OMP_PLACES} and @env{GOMP_CPU_AFFINITY} are unset and
+@env{OMP_PROC_BIND} is either unset or @code{false}, threads may be moved
+between CPUs following no placement policy.
+
+@item @emph{See also}:
+@ref{OMP_PROC_BIND}, @ref{GOMP_CPU_AFFINITY}, @ref{omp_get_proc_bind},
+@ref{OMP_DISPLAY_ENV}
+
+@item @emph{Reference}:
+@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 4.5
+@end table
+
+
+
+@node OMP_PROC_BIND
+@section @env{OMP_PROC_BIND} -- Whether theads may be moved between CPUs
+@cindex Environment Variable
+@table @asis
+@item @emph{Description}:
+Specifies whether threads may be moved between processors. If set to
+@code{TRUE}, OpenMP theads should not be moved; if set to @code{FALSE}
+they may be moved. Alternatively, a comma separated list with the
+values @code{MASTER}, @code{CLOSE} and @code{SPREAD} can be used to specify
+the thread affinity policy for the corresponding nesting level. With
+@code{MASTER} the worker threads are in the same place partition as the
+master thread. With @code{CLOSE} those are kept close to the master thread
+in contiguous place partitions. And with @code{SPREAD} a sparse distribution
+across the place partitions is used.
+
+When undefined, @env{OMP_PROC_BIND} defaults to @code{TRUE} when
+@env{OMP_PLACES} or @env{GOMP_CPU_AFFINITY} is set and @code{FALSE} otherwise.
+
+@item @emph{See also}:
+@ref{OMP_PLACES}, @ref{GOMP_CPU_AFFINITY}, @ref{omp_get_proc_bind}
+
+@item @emph{Reference}:
+@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 4.4
@end table
@@ -1191,14 +1526,14 @@ level. If undefined one thread per CPU is used.
Allows to specify @code{schedule type} and @code{chunk size}.
The value of the variable shall have the form: @code{type[,chunk]} where
@code{type} is one of @code{static}, @code{dynamic}, @code{guided} or @code{auto}
-The optional @code{chunk} size shall be a positive integer. If undefined,
+The optional @code{chunk} size shall be a positive integer. If undefined,
dynamic scheduling and a chunk size of 1 is used.
@item @emph{See also}:
@ref{omp_set_schedule}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.1}, sections 2.5.1 and 4.1
+@uref{http://www.openmp.org/, OpenMP specification v4.0}, Sections 2.7.1 and 4.1
@end table
@@ -1211,14 +1546,14 @@ dynamic scheduling and a chunk size of 1 is used.
Set the default thread stack size in kilobytes, unless the number
is suffixed by @code{B}, @code{K}, @code{M} or @code{G}, in which
case the size is, respectively, in bytes, kilobytes, megabytes
-or gigabytes. This is different from @code{pthread_attr_setstacksize}
-which gets the number of bytes as an argument. If the stack size cannot
+or gigabytes. This is different from @code{pthread_attr_setstacksize}
+which gets the number of bytes as an argument. If the stack size cannot
be set due to system constraints, an error is reported and the initial
-stack size is left unchanged. If undefined, the stack size is system
+stack size is left unchanged. If undefined, the stack size is system
dependent.
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.1}, sections 4.6
+@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 4.7
@end table
@@ -1228,16 +1563,15 @@ dependent.
@cindex Environment Variable
@table @asis
@item @emph{Description}:
-Specifies the number of threads to use for the whole program. The
-value of this variable shall be a positive integer. If undefined,
+Specifies the number of threads to use for the whole program. The
+value of this variable shall be a positive integer. If undefined,
the number of threads is not limited.
@item @emph{See also}:
-@ref{OMP_NUM_THREADS}
-@ref{omp_get_thread_limit}
+@ref{OMP_NUM_THREADS}, @ref{omp_get_thread_limit}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.1}, section 4.9
+@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 4.10
@end table
@@ -1247,31 +1581,17 @@ the number of threads is not limited.
@cindex Environment Variable
@table @asis
@item @emph{Description}:
-Specifies whether waiting threads should be active or passive. If
+Specifies whether waiting threads should be active or passive. If
the value is @code{PASSIVE}, waiting threads should not consume CPU
power while waiting; while the value is @code{ACTIVE} specifies that
-they should.
-
-@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.1}, sections 4.7
-@end table
-
-
-
-@node OMP_PROC_BIND
-@section @env{OMP_PROC_BIND} -- Whether theads may be moved between CPUs
-@cindex Environment Variable
-@table @asis
-@item @emph{Description}:
-Specifies whether threads may be moved between processors. If set to
-@code{true}, OpenMP theads should not be moved, if set to @code{false}
-they may be moved.
+they should. If undefined, threads wait actively for a short time
+before waiting passively.
@item @emph{See also}:
-@ref{GOMP_CPU_AFFINITY}
+@ref{GOMP_SPINCOUNT}
@item @emph{Reference}:
-@uref{http://www.openmp.org/, OpenMP specifications v3.1}, sections 4.4
+@uref{http://www.openmp.org/, OpenMP specification v4.0}, Section 4.8
@end table
@@ -1281,10 +1601,10 @@ they may be moved.
@cindex Environment Variable
@table @asis
@item @emph{Description}:
-Binds threads to specific CPUs. The variable should contain a space-separated
-or comma-separated list of CPUs. This list may contain different kinds of
+Binds threads to specific CPUs. The variable should contain a space-separated
+or comma-separated list of CPUs. This list may contain different kinds of
entries: either single CPU numbers in any order, a range of CPUs (M-N)
-or a range with some stride (M-N:S). CPU numbers are zero based. For example,
+or a range with some stride (M-N:S). CPU numbers are zero based. For example,
@code{GOMP_CPU_AFFINITY="0 3 1-2 4-15:2"} will bind the initial thread
to CPU 0, the second to CPU 3, the third to CPU 1, the fourth to
CPU 2, the fifth to CPU 4, the sixth through tenth to CPUs 6, 8, 10, 12,
@@ -1292,17 +1612,19 @@ and 14 respectively and then start assigning back from the beginning of
the list. @code{GOMP_CPU_AFFINITY=0} binds all threads to CPU 0.
There is no GNU OpenMP library routine to determine whether a CPU affinity
-specification is in effect. As a workaround, language-specific library
+specification is in effect. As a workaround, language-specific library
functions, e.g., @code{getenv} in C or @code{GET_ENVIRONMENT_VARIABLE} in
Fortran, may be used to query the setting of the @code{GOMP_CPU_AFFINITY}
-environment variable. A defined CPU affinity on startup cannot be changed
+environment variable. A defined CPU affinity on startup cannot be changed
or disabled during the runtime of the application.
-If this environment variable is omitted, the host system will handle the
-assignment of threads to CPUs.
+If both @env{GOMP_CPU_AFFINITY} and @env{OMP_PROC_BIND} are set,
+@env{OMP_PROC_BIND} has a higher precedence. If neither has been set and
+@env{OMP_PROC_BIND} is unset, or when @env{OMP_PROC_BIND} is set to
+@code{FALSE}, the host system will handle the assignment of threads to CPUs.
@item @emph{See also}:
-@ref{OMP_PROC_BIND}
+@ref{OMP_PLACES}, @ref{OMP_PROC_BIND}
@end table
@@ -1313,10 +1635,10 @@ assignment of threads to CPUs.
@cindex Implementation specific setting
@table @asis
@item @emph{Description}:
-Set the default thread stack size in kilobytes. This is different from
+Set the default thread stack size in kilobytes. This is different from
@code{pthread_attr_setstacksize} which gets the number of bytes as an
-argument. If the stack size cannot be set due to system constraints, an
-error is reported and the initial stack size is left unchanged. If undefined,
+argument. If the stack size cannot be set due to system constraints, an
+error is reported and the initial stack size is left unchanged. If undefined,
the stack size is system dependent.
@item @emph{See also}:
@@ -1331,6 +1653,33 @@ GCC Patches Mailinglist}
+@node GOMP_SPINCOUNT
+@section @env{GOMP_SPINCOUNT} -- Set the busy-wait spin count
+@cindex Environment Variable
+@cindex Implementation specific setting
+@table @asis
+@item @emph{Description}:
+Determines how long a threads waits actively with consuming CPU power
+before waiting passively without consuming CPU power. The value may be
+either @code{INFINITE}, @code{INFINITY} to always wait actively or an
+integer which gives the number of spins of the busy-wait loop. The
+integer may optionally be followed by the following suffixes acting
+as multiplication factors: @code{k} (kilo, thousand), @code{M} (mega,
+million), @code{G} (giga, billion), or @code{T} (tera, trillion).
+If undefined, 0 is used when @env{OMP_WAIT_POLICY} is @code{PASSIVE},
+300,000 is used when @env{OMP_WAIT_POLICY} is undefined and
+30 billion is used when @env{OMP_WAIT_POLICY} is @code{ACTIVE}.
+If there are more OpenMP threads than available CPUs, 1000 and 100
+spins are used for @env{OMP_WAIT_POLICY} being @code{ACTIVE} or
+undefined, respectively; unless the @env{GOMP_SPINCOUNT} is lower
+or @env{OMP_WAIT_POLICY} is @code{PASSIVE}.
+
+@item @emph{See also}:
+@ref{OMP_WAIT_POLICY}
+@end table
+
+
+
@c ---------------------------------------------------------------------
@c The libgomp ABI
@c ---------------------------------------------------------------------
@@ -1728,7 +2077,7 @@ becomes
@chapter Reporting Bugs
Bugs in the GNU OpenMP implementation should be reported via
-@uref{http://gcc.gnu.org/bugzilla/, bugzilla}. For all cases, please add
+@uref{http://gcc.gnu.org/bugzilla/, Bugzilla}. For all cases, please add
"openmp" to the keywords field in the bug report.
diff --git a/libgomp/libgomp_g.h b/libgomp/libgomp_g.h
index a31e3458c1b..577956a50dc 100644
--- a/libgomp/libgomp_g.h
+++ b/libgomp/libgomp_g.h
@@ -29,10 +29,12 @@
#define LIBGOMP_G_H 1
#include <stdbool.h>
+#include <stddef.h>
/* barrier.c */
extern void GOMP_barrier (void);
+extern bool GOMP_barrier_cancel (void);
/* critical.c */
@@ -76,9 +78,22 @@ extern void GOMP_parallel_loop_guided_start (void (*)(void *), void *,
unsigned, long, long, long, long);
extern void GOMP_parallel_loop_runtime_start (void (*)(void *), void *,
unsigned, long, long, long);
+extern void GOMP_parallel_loop_static (void (*)(void *), void *,
+ unsigned, long, long, long, long,
+ unsigned);
+extern void GOMP_parallel_loop_dynamic (void (*)(void *), void *,
+ unsigned, long, long, long, long,
+ unsigned);
+extern void GOMP_parallel_loop_guided (void (*)(void *), void *,
+ unsigned, long, long, long, long,
+ unsigned);
+extern void GOMP_parallel_loop_runtime (void (*)(void *), void *,
+ unsigned, long, long, long,
+ unsigned);
extern void GOMP_loop_end (void);
extern void GOMP_loop_end_nowait (void);
+extern bool GOMP_loop_end_cancel (void);
/* loop_ull.c */
@@ -157,13 +172,18 @@ extern void GOMP_ordered_end (void);
extern void GOMP_parallel_start (void (*) (void *), void *, unsigned);
extern void GOMP_parallel_end (void);
+extern void GOMP_parallel (void (*) (void *), void *, unsigned, unsigned);
+extern bool GOMP_cancel (int, bool);
+extern bool GOMP_cancellation_point (int);
/* task.c */
extern void GOMP_task (void (*) (void *), void *, void (*) (void *, void *),
- long, long, bool, unsigned);
+ long, long, bool, unsigned, void **);
extern void GOMP_taskwait (void);
extern void GOMP_taskyield (void);
+extern void GOMP_taskgroup_start (void);
+extern void GOMP_taskgroup_end (void);
/* sections.c */
@@ -171,8 +191,11 @@ extern unsigned GOMP_sections_start (unsigned);
extern unsigned GOMP_sections_next (void);
extern void GOMP_parallel_sections_start (void (*) (void *), void *,
unsigned, unsigned);
+extern void GOMP_parallel_sections (void (*) (void *), void *,
+ unsigned, unsigned, unsigned);
extern void GOMP_sections_end (void);
extern void GOMP_sections_end_nowait (void);
+extern bool GOMP_sections_end_cancel (void);
/* single.c */
@@ -180,4 +203,15 @@ extern bool GOMP_single_start (void);
extern void *GOMP_single_copy_start (void);
extern void GOMP_single_copy_end (void *);
+/* target.c */
+
+extern void GOMP_target (int, void (*) (void *), const void *,
+ size_t, void **, size_t *, unsigned char *);
+extern void GOMP_target_data (int, const void *,
+ size_t, void **, size_t *, unsigned char *);
+extern void GOMP_target_end_data (void);
+extern void GOMP_target_update (int, const void *,
+ size_t, void **, size_t *, unsigned char *);
+extern void GOMP_teams (unsigned int, unsigned int);
+
#endif /* LIBGOMP_G_H */
diff --git a/libgomp/loop.c b/libgomp/loop.c
index 12c818b0110..f5b33a06658 100644
--- a/libgomp/loop.c
+++ b/libgomp/loop.c
@@ -439,14 +439,14 @@ static void
gomp_parallel_loop_start (void (*fn) (void *), void *data,
unsigned num_threads, long start, long end,
long incr, enum gomp_schedule_type sched,
- long chunk_size)
+ long chunk_size, unsigned int flags)
{
struct gomp_team *team;
num_threads = gomp_resolve_num_threads (num_threads, 0);
team = gomp_new_team (num_threads);
gomp_loop_init (&team->work_shares[0], start, end, incr, sched, chunk_size);
- gomp_team_start (fn, data, num_threads, team);
+ gomp_team_start (fn, data, num_threads, flags, team);
}
void
@@ -455,7 +455,7 @@ GOMP_parallel_loop_static_start (void (*fn) (void *), void *data,
long incr, long chunk_size)
{
gomp_parallel_loop_start (fn, data, num_threads, start, end, incr,
- GFS_STATIC, chunk_size);
+ GFS_STATIC, chunk_size, 0);
}
void
@@ -464,7 +464,7 @@ GOMP_parallel_loop_dynamic_start (void (*fn) (void *), void *data,
long incr, long chunk_size)
{
gomp_parallel_loop_start (fn, data, num_threads, start, end, incr,
- GFS_DYNAMIC, chunk_size);
+ GFS_DYNAMIC, chunk_size, 0);
}
void
@@ -473,7 +473,7 @@ GOMP_parallel_loop_guided_start (void (*fn) (void *), void *data,
long incr, long chunk_size)
{
gomp_parallel_loop_start (fn, data, num_threads, start, end, incr,
- GFS_GUIDED, chunk_size);
+ GFS_GUIDED, chunk_size, 0);
}
void
@@ -483,11 +483,59 @@ GOMP_parallel_loop_runtime_start (void (*fn) (void *), void *data,
{
struct gomp_task_icv *icv = gomp_icv (false);
gomp_parallel_loop_start (fn, data, num_threads, start, end, incr,
- icv->run_sched_var, icv->run_sched_modifier);
+ icv->run_sched_var, icv->run_sched_modifier, 0);
+}
+
+ialias_redirect (GOMP_parallel_end)
+
+void
+GOMP_parallel_loop_static (void (*fn) (void *), void *data,
+ unsigned num_threads, long start, long end,
+ long incr, long chunk_size, unsigned flags)
+{
+ gomp_parallel_loop_start (fn, data, num_threads, start, end, incr,
+ GFS_STATIC, chunk_size, flags);
+ fn (data);
+ GOMP_parallel_end ();
+}
+
+void
+GOMP_parallel_loop_dynamic (void (*fn) (void *), void *data,
+ unsigned num_threads, long start, long end,
+ long incr, long chunk_size, unsigned flags)
+{
+ gomp_parallel_loop_start (fn, data, num_threads, start, end, incr,
+ GFS_DYNAMIC, chunk_size, flags);
+ fn (data);
+ GOMP_parallel_end ();
+}
+
+void
+GOMP_parallel_loop_guided (void (*fn) (void *), void *data,
+ unsigned num_threads, long start, long end,
+ long incr, long chunk_size, unsigned flags)
+{
+ gomp_parallel_loop_start (fn, data, num_threads, start, end, incr,
+ GFS_GUIDED, chunk_size, flags);
+ fn (data);
+ GOMP_parallel_end ();
+}
+
+void
+GOMP_parallel_loop_runtime (void (*fn) (void *), void *data,
+ unsigned num_threads, long start, long end,
+ long incr, unsigned flags)
+{
+ struct gomp_task_icv *icv = gomp_icv (false);
+ gomp_parallel_loop_start (fn, data, num_threads, start, end, incr,
+ icv->run_sched_var, icv->run_sched_modifier,
+ flags);
+ fn (data);
+ GOMP_parallel_end ();
}
/* The GOMP_loop_end* routines are called after the thread is told that
- all loop iterations are complete. This first version synchronizes
+ all loop iterations are complete. The first two versions synchronize
all threads; the nowait version does not. */
void
@@ -496,6 +544,12 @@ GOMP_loop_end (void)
gomp_work_share_end ();
}
+bool
+GOMP_loop_end_cancel (void)
+{
+ return gomp_work_share_end_cancel ();
+}
+
void
GOMP_loop_end_nowait (void)
{
diff --git a/libgomp/omp.h.in b/libgomp/omp.h.in
index 5db440785db..1db5d6ba522 100644
--- a/libgomp/omp.h.in
+++ b/libgomp/omp.h.in
@@ -22,8 +22,8 @@
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
-#ifndef OMP_H
-#define OMP_H 1
+#ifndef _OMP_H
+#define _OMP_H 1
#ifndef _LIBGOMP_OMP_LOCK_DEFINED
#define _LIBGOMP_OMP_LOCK_DEFINED 1
@@ -52,6 +52,15 @@ typedef enum omp_sched_t
omp_sched_auto = 4
} omp_sched_t;
+typedef enum omp_proc_bind_t
+{
+ omp_proc_bind_false = 0,
+ omp_proc_bind_true = 1,
+ omp_proc_bind_master = 2,
+ omp_proc_bind_close = 3,
+ omp_proc_bind_spread = 4
+} omp_proc_bind_t;
+
#ifdef __cplusplus
extern "C" {
# define __GOMP_NOTHROW throw ()
@@ -88,20 +97,31 @@ extern int omp_test_nest_lock (omp_nest_lock_t *) __GOMP_NOTHROW;
extern double omp_get_wtime (void) __GOMP_NOTHROW;
extern double omp_get_wtick (void) __GOMP_NOTHROW;
-void omp_set_schedule (omp_sched_t, int) __GOMP_NOTHROW;
-void omp_get_schedule (omp_sched_t *, int *) __GOMP_NOTHROW;
-int omp_get_thread_limit (void) __GOMP_NOTHROW;
-void omp_set_max_active_levels (int) __GOMP_NOTHROW;
-int omp_get_max_active_levels (void) __GOMP_NOTHROW;
-int omp_get_level (void) __GOMP_NOTHROW;
-int omp_get_ancestor_thread_num (int) __GOMP_NOTHROW;
-int omp_get_team_size (int) __GOMP_NOTHROW;
-int omp_get_active_level (void) __GOMP_NOTHROW;
+extern void omp_set_schedule (omp_sched_t, int) __GOMP_NOTHROW;
+extern void omp_get_schedule (omp_sched_t *, int *) __GOMP_NOTHROW;
+extern int omp_get_thread_limit (void) __GOMP_NOTHROW;
+extern void omp_set_max_active_levels (int) __GOMP_NOTHROW;
+extern int omp_get_max_active_levels (void) __GOMP_NOTHROW;
+extern int omp_get_level (void) __GOMP_NOTHROW;
+extern int omp_get_ancestor_thread_num (int) __GOMP_NOTHROW;
+extern int omp_get_team_size (int) __GOMP_NOTHROW;
+extern int omp_get_active_level (void) __GOMP_NOTHROW;
+
+extern int omp_in_final (void) __GOMP_NOTHROW;
+
+extern int omp_get_cancellation (void) __GOMP_NOTHROW;
+extern omp_proc_bind_t omp_get_proc_bind (void) __GOMP_NOTHROW;
+
+extern void omp_set_default_device (int) __GOMP_NOTHROW;
+extern int omp_get_default_device (void) __GOMP_NOTHROW;
+extern int omp_get_num_devices (void) __GOMP_NOTHROW;
+extern int omp_get_num_teams (void) __GOMP_NOTHROW;
+extern int omp_get_team_num (void) __GOMP_NOTHROW;
-int omp_in_final (void) __GOMP_NOTHROW;
+extern int omp_is_initial_device (void) __GOMP_NOTHROW;
#ifdef __cplusplus
}
#endif
-#endif /* OMP_H */
+#endif /* _OMP_H */
diff --git a/libgomp/omp_lib.f90.in b/libgomp/omp_lib.f90.in
index c9bc5fd003a..3c6deb6bbd5 100644
--- a/libgomp/omp_lib.f90.in
+++ b/libgomp/omp_lib.f90.in
@@ -27,16 +27,22 @@
integer, parameter :: omp_lock_kind = @OMP_LOCK_KIND@
integer, parameter :: omp_nest_lock_kind = @OMP_NEST_LOCK_KIND@
integer, parameter :: omp_sched_kind = 4
+ integer, parameter :: omp_proc_bind_kind = 4
+ integer (omp_sched_kind), parameter :: omp_sched_static = 1
+ integer (omp_sched_kind), parameter :: omp_sched_dynamic = 2
+ integer (omp_sched_kind), parameter :: omp_sched_guided = 3
+ integer (omp_sched_kind), parameter :: omp_sched_auto = 4
+ integer (omp_proc_bind_kind), parameter :: omp_proc_bind_false = 0
+ integer (omp_proc_bind_kind), parameter :: omp_proc_bind_true = 1
+ integer (omp_proc_bind_kind), parameter :: omp_proc_bind_master = 2
+ integer (omp_proc_bind_kind), parameter :: omp_proc_bind_close = 3
+ integer (omp_proc_bind_kind), parameter :: omp_proc_bind_spread = 4
end module
module omp_lib
use omp_lib_kinds
implicit none
integer, parameter :: openmp_version = 201107
- integer (omp_sched_kind), parameter :: omp_sched_static = 1
- integer (omp_sched_kind), parameter :: omp_sched_dynamic = 2
- integer (omp_sched_kind), parameter :: omp_sched_guided = 3
- integer (omp_sched_kind), parameter :: omp_sched_auto = 4
interface
subroutine omp_init_lock (svar)
@@ -123,21 +129,18 @@
interface
function omp_get_dynamic ()
- use omp_lib_kinds
logical (4) :: omp_get_dynamic
end function omp_get_dynamic
end interface
interface
function omp_get_nested ()
- use omp_lib_kinds
logical (4) :: omp_get_nested
end function omp_get_nested
end interface
interface
function omp_in_parallel ()
- use omp_lib_kinds
logical (4) :: omp_in_parallel
end function omp_in_parallel
end interface
@@ -152,28 +155,24 @@
interface
function omp_get_max_threads ()
- use omp_lib_kinds
integer (4) :: omp_get_max_threads
end function omp_get_max_threads
end interface
interface
function omp_get_num_procs ()
- use omp_lib_kinds
integer (4) :: omp_get_num_procs
end function omp_get_num_procs
end interface
interface
function omp_get_num_threads ()
- use omp_lib_kinds
integer (4) :: omp_get_num_threads
end function omp_get_num_threads
end interface
interface
function omp_get_thread_num ()
- use omp_lib_kinds
integer (4) :: omp_get_thread_num
end function omp_get_thread_num
end interface
@@ -226,44 +225,37 @@
interface
function omp_get_thread_limit ()
- use omp_lib_kinds
integer (4) :: omp_get_thread_limit
end function omp_get_thread_limit
end interface
interface omp_set_max_active_levels
subroutine omp_set_max_active_levels (max_levels)
- use omp_lib_kinds
integer (4), intent (in) :: max_levels
end subroutine omp_set_max_active_levels
subroutine omp_set_max_active_levels_8 (max_levels)
- use omp_lib_kinds
integer (8), intent (in) :: max_levels
end subroutine omp_set_max_active_levels_8
end interface
interface
function omp_get_max_active_levels ()
- use omp_lib_kinds
integer (4) :: omp_get_max_active_levels
end function omp_get_max_active_levels
end interface
interface
function omp_get_level ()
- use omp_lib_kinds
integer (4) :: omp_get_level
end function omp_get_level
end interface
interface omp_get_ancestor_thread_num
function omp_get_ancestor_thread_num (level)
- use omp_lib_kinds
integer (4), intent (in) :: level
integer (4) :: omp_get_ancestor_thread_num
end function omp_get_ancestor_thread_num
function omp_get_ancestor_thread_num_8 (level)
- use omp_lib_kinds
integer (8), intent (in) :: level
integer (4) :: omp_get_ancestor_thread_num_8
end function omp_get_ancestor_thread_num_8
@@ -271,12 +263,10 @@
interface omp_get_team_size
function omp_get_team_size (level)
- use omp_lib_kinds
integer (4), intent (in) :: level
integer (4) :: omp_get_team_size
end function omp_get_team_size
function omp_get_team_size_8 (level)
- use omp_lib_kinds
integer (8), intent (in) :: level
integer (4) :: omp_get_team_size_8
end function omp_get_team_size_8
@@ -284,16 +274,66 @@
interface
function omp_get_active_level ()
- use omp_lib_kinds
integer (4) :: omp_get_active_level
end function omp_get_active_level
end interface
interface
function omp_in_final ()
- use omp_lib_kinds
logical (4) :: omp_in_final
end function omp_in_final
end interface
+ interface
+ function omp_get_cancellation ()
+ logical (4) :: omp_get_cancellation
+ end function omp_get_cancellation
+ end interface
+
+ interface
+ function omp_get_proc_bind ()
+ use omp_lib_kinds
+ integer (omp_proc_bind_kind) :: omp_get_proc_bind
+ end function omp_get_proc_bind
+ end interface
+
+ interface omp_set_default_device
+ subroutine omp_set_default_device (device_num)
+ integer (4), intent (in) :: device_num
+ end subroutine omp_set_default_device
+ subroutine omp_set_default_device_8 (device_num)
+ integer (8), intent (in) :: device_num
+ end subroutine omp_set_default_device_8
+ end interface
+
+ interface
+ function omp_get_default_device ()
+ integer (4) :: omp_get_default_device
+ end function omp_get_default_device
+ end interface
+
+ interface
+ function omp_get_num_devices ()
+ integer (4) :: omp_get_num_devices
+ end function omp_get_num_devices
+ end interface
+
+ interface
+ function omp_get_num_teams ()
+ integer (4) :: omp_get_num_teams
+ end function omp_get_num_teams
+ end interface
+
+ interface
+ function omp_get_team_num ()
+ integer (4) :: omp_get_team_num
+ end function omp_get_team_num
+ end interface
+
+ interface
+ function omp_is_initial_device ()
+ logical (4) :: omp_is_initial_device
+ end function omp_is_initial_device
+ end interface
+
end module omp_lib
diff --git a/libgomp/omp_lib.h.in b/libgomp/omp_lib.h.in
index f188edcf661..804636df82f 100644
--- a/libgomp/omp_lib.h.in
+++ b/libgomp/omp_lib.h.in
@@ -33,6 +33,18 @@
parameter (omp_sched_dynamic = 2)
parameter (omp_sched_guided = 3)
parameter (omp_sched_auto = 4)
+ integer omp_proc_bind_kind
+ parameter (omp_proc_bind_kind = 4)
+ integer (omp_proc_bind_kind) omp_proc_bind_false
+ integer (omp_proc_bind_kind) omp_proc_bind_true
+ integer (omp_proc_bind_kind) omp_proc_bind_master
+ integer (omp_proc_bind_kind) omp_proc_bind_close
+ integer (omp_proc_bind_kind) omp_proc_bind_spread
+ parameter (omp_proc_bind_false = 0)
+ parameter (omp_proc_bind_true = 1)
+ parameter (omp_proc_bind_master = 2)
+ parameter (omp_proc_bind_close = 3)
+ parameter (omp_proc_bind_spread = 4)
parameter (openmp_version = 201107)
external omp_init_lock, omp_init_nest_lock
@@ -68,3 +80,18 @@
external omp_in_final
logical(4) omp_in_final
+
+ external omp_get_cancelllation
+ logical(4) omp_get_cancelllation
+
+ external omp_get_proc_bind
+ integer(omp_proc_bind_kind) omp_get_proc_bind
+
+ external omp_set_default_device, omp_get_default_device
+ external omp_get_num_devices, omp_get_num_teams
+ external omp_get_team_num
+ integer(4) omp_get_default_device, omp_get_num_devices
+ integer(4) omp_get_num_teams, omp_get_team_num
+
+ external omp_is_initial_device
+ logical(4) omp_is_initial_device
diff --git a/libgomp/parallel.c b/libgomp/parallel.c
index 45735119025..ccc0b6a6973 100644
--- a/libgomp/parallel.c
+++ b/libgomp/parallel.c
@@ -37,18 +37,19 @@
unsigned
gomp_resolve_num_threads (unsigned specified, unsigned count)
{
- struct gomp_thread *thread = gomp_thread();
+ struct gomp_thread *thr = gomp_thread ();
struct gomp_task_icv *icv;
unsigned threads_requested, max_num_threads, num_threads;
- unsigned long remaining;
+ unsigned long busy;
+ struct gomp_thread_pool *pool;
icv = gomp_icv (false);
if (specified == 1)
return 1;
- else if (thread->ts.active_level >= 1 && !icv->nest_var)
+ else if (thr->ts.active_level >= 1 && !icv->nest_var)
return 1;
- else if (thread->ts.active_level >= gomp_max_active_levels_var)
+ else if (thr->ts.active_level >= gomp_max_active_levels_var)
return 1;
/* If NUM_THREADS not specified, use nthreads_var. */
@@ -72,30 +73,46 @@ gomp_resolve_num_threads (unsigned specified, unsigned count)
max_num_threads = count;
}
- /* ULONG_MAX stands for infinity. */
- if (__builtin_expect (gomp_thread_limit_var == ULONG_MAX, 1)
+ /* UINT_MAX stands for infinity. */
+ if (__builtin_expect (icv->thread_limit_var == UINT_MAX, 1)
|| max_num_threads == 1)
return max_num_threads;
+ /* The threads_busy counter lives in thread_pool, if there
+ isn't a thread_pool yet, there must be just one thread
+ in the contention group. If thr->team is NULL, this isn't
+ nested parallel, so there is just one thread in the
+ contention group as well, no need to handle it atomically. */
+ pool = thr->thread_pool;
+ if (thr->ts.team == NULL)
+ {
+ num_threads = max_num_threads;
+ if (num_threads > icv->thread_limit_var)
+ num_threads = icv->thread_limit_var;
+ if (pool)
+ pool->threads_busy = num_threads;
+ return num_threads;
+ }
+
#ifdef HAVE_SYNC_BUILTINS
do
{
- remaining = gomp_remaining_threads_count;
+ busy = pool->threads_busy;
num_threads = max_num_threads;
- if (num_threads > remaining)
- num_threads = remaining + 1;
+ if (icv->thread_limit_var - busy + 1 < num_threads)
+ num_threads = icv->thread_limit_var - busy + 1;
}
- while (__sync_val_compare_and_swap (&gomp_remaining_threads_count,
- remaining, remaining - num_threads + 1)
- != remaining);
+ while (__sync_val_compare_and_swap (&pool->threads_busy,
+ busy, busy + num_threads - 1)
+ != busy);
#else
- gomp_mutex_lock (&gomp_remaining_threads_lock);
+ gomp_mutex_lock (&gomp_managed_threads_lock);
num_threads = max_num_threads;
- remaining = gomp_remaining_threads_count;
- if (num_threads > remaining)
- num_threads = remaining + 1;
- gomp_remaining_threads_count -= num_threads - 1;
- gomp_mutex_unlock (&gomp_remaining_threads_lock);
+ busy = pool->threads_busy;
+ if (icv->thread_limit_var - busy + 1 < num_threads)
+ num_threads = icv->thread_limit_var - busy + 1;
+ pool->threads_busy += num_threads - 1;
+ gomp_mutex_unlock (&gomp_managed_threads_lock);
#endif
return num_threads;
@@ -105,31 +122,113 @@ void
GOMP_parallel_start (void (*fn) (void *), void *data, unsigned num_threads)
{
num_threads = gomp_resolve_num_threads (num_threads, 0);
- gomp_team_start (fn, data, num_threads, gomp_new_team (num_threads));
+ gomp_team_start (fn, data, num_threads, 0, gomp_new_team (num_threads));
}
void
GOMP_parallel_end (void)
{
- if (__builtin_expect (gomp_thread_limit_var != ULONG_MAX, 0))
+ struct gomp_task_icv *icv = gomp_icv (false);
+ if (__builtin_expect (icv->thread_limit_var != UINT_MAX, 0))
{
struct gomp_thread *thr = gomp_thread ();
struct gomp_team *team = thr->ts.team;
- if (team && team->nthreads > 1)
+ unsigned int nthreads = team ? team->nthreads : 1;
+ gomp_team_end ();
+ if (nthreads > 1)
{
+ /* If not nested, there is just one thread in the
+ contention group left, no need for atomicity. */
+ if (thr->ts.team == NULL)
+ thr->thread_pool->threads_busy = 1;
+ else
+ {
#ifdef HAVE_SYNC_BUILTINS
- __sync_fetch_and_add (&gomp_remaining_threads_count,
- 1UL - team->nthreads);
+ __sync_fetch_and_add (&thr->thread_pool->threads_busy,
+ 1UL - nthreads);
#else
- gomp_mutex_lock (&gomp_remaining_threads_lock);
- gomp_remaining_threads_count -= team->nthreads - 1;
- gomp_mutex_unlock (&gomp_remaining_threads_lock);
+ gomp_mutex_lock (&gomp_managed_threads_lock);
+ thr->thread_pool->threads_busy -= nthreads - 1;
+ gomp_mutex_unlock (&gomp_managed_threads_lock);
#endif
+ }
}
}
- gomp_team_end ();
+ else
+ gomp_team_end ();
+}
+ialias (GOMP_parallel_end)
+
+void
+GOMP_parallel (void (*fn) (void *), void *data, unsigned num_threads, unsigned int flags)
+{
+ num_threads = gomp_resolve_num_threads (num_threads, 0);
+ gomp_team_start (fn, data, num_threads, flags, gomp_new_team (num_threads));
+ fn (data);
+ ialias_call (GOMP_parallel_end) ();
+}
+
+bool
+GOMP_cancellation_point (int which)
+{
+ if (!gomp_cancel_var)
+ return false;
+
+ struct gomp_thread *thr = gomp_thread ();
+ struct gomp_team *team = thr->ts.team;
+ if (which & (GOMP_CANCEL_LOOP | GOMP_CANCEL_SECTIONS))
+ {
+ if (team == NULL)
+ return false;
+ return team->work_share_cancelled != 0;
+ }
+ else if (which & GOMP_CANCEL_TASKGROUP)
+ {
+ if (thr->task->taskgroup && thr->task->taskgroup->cancelled)
+ return true;
+ /* FALLTHRU into the GOMP_CANCEL_PARALLEL case,
+ as #pragma omp cancel parallel also cancels all explicit
+ tasks. */
+ }
+ if (team)
+ return gomp_team_barrier_cancelled (&team->barrier);
+ return false;
}
+ialias (GOMP_cancellation_point)
+
+bool
+GOMP_cancel (int which, bool do_cancel)
+{
+ if (!gomp_cancel_var)
+ return false;
+
+ if (!do_cancel)
+ return ialias_call (GOMP_cancellation_point) (which);
+ struct gomp_thread *thr = gomp_thread ();
+ struct gomp_team *team = thr->ts.team;
+ if (which & (GOMP_CANCEL_LOOP | GOMP_CANCEL_SECTIONS))
+ {
+ /* In orphaned worksharing region, all we want to cancel
+ is current thread. */
+ if (team != NULL)
+ team->work_share_cancelled = 1;
+ return true;
+ }
+ else if (which & GOMP_CANCEL_TASKGROUP)
+ {
+ if (thr->task->taskgroup && !thr->task->taskgroup->cancelled)
+ {
+ gomp_mutex_lock (&team->task_lock);
+ thr->task->taskgroup->cancelled = true;
+ gomp_mutex_unlock (&team->task_lock);
+ }
+ return true;
+ }
+ team->team_cancelled = 1;
+ gomp_team_barrier_cancel (team);
+ return true;
+}
/* The public OpenMP API for thread and team related inquiries. */
diff --git a/libgomp/sections.c b/libgomp/sections.c
index 369f7a4426f..6fb117de0b1 100644
--- a/libgomp/sections.c
+++ b/libgomp/sections.c
@@ -139,11 +139,27 @@ GOMP_parallel_sections_start (void (*fn) (void *), void *data,
num_threads = gomp_resolve_num_threads (num_threads, count);
team = gomp_new_team (num_threads);
gomp_sections_init (&team->work_shares[0], count);
- gomp_team_start (fn, data, num_threads, team);
+ gomp_team_start (fn, data, num_threads, 0, team);
+}
+
+ialias_redirect (GOMP_parallel_end)
+
+void
+GOMP_parallel_sections (void (*fn) (void *), void *data,
+ unsigned num_threads, unsigned count, unsigned flags)
+{
+ struct gomp_team *team;
+
+ num_threads = gomp_resolve_num_threads (num_threads, count);
+ team = gomp_new_team (num_threads);
+ gomp_sections_init (&team->work_shares[0], count);
+ gomp_team_start (fn, data, num_threads, flags, team);
+ fn (data);
+ GOMP_parallel_end ();
}
/* The GOMP_section_end* routines are called after the thread is told
- that all sections are complete. This first version synchronizes
+ that all sections are complete. The first two versions synchronize
all threads; the nowait version does not. */
void
@@ -152,6 +168,12 @@ GOMP_sections_end (void)
gomp_work_share_end ();
}
+bool
+GOMP_sections_end_cancel (void)
+{
+ return gomp_work_share_end_cancel ();
+}
+
void
GOMP_sections_end_nowait (void)
{
diff --git a/libgomp/target.c b/libgomp/target.c
new file mode 100644
index 00000000000..2e9865f2ae3
--- /dev/null
+++ b/libgomp/target.c
@@ -0,0 +1,96 @@
+/* Copyright (C) 2013 Free Software Foundation, Inc.
+ Contributed by Jakub Jelinek <jakub@redhat.com>.
+
+ This file is part of the GNU OpenMP Library (libgomp).
+
+ Libgomp is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ Libgomp is distributed in the hope that it will be useful, but WITHOUT 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 handles the maintainence of threads in response to team
+ creation and termination. */
+
+#include "libgomp.h"
+#include <limits.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+
+attribute_hidden int
+gomp_get_num_devices (void)
+{
+ return 0;
+}
+
+/* Called when encountering a target directive. If DEVICE
+ is -1, it means use device-var ICV. If it is -2 (or any other value
+ larger than last available hw device, use host fallback.
+ FN is address of host code, OPENMP_TARGET contains value of the
+ __OPENMP_TARGET__ symbol in the shared library or binary that invokes
+ GOMP_target. HOSTADDRS, SIZES and KINDS are arrays
+ with MAPNUM entries, with addresses of the host objects,
+ sizes of the host objects (resp. for pointer kind pointer bias
+ and assumed sizeof (void *) size) and kinds. */
+
+void
+GOMP_target (int device, void (*fn) (void *), const void *openmp_target,
+ size_t mapnum, void **hostaddrs, size_t *sizes,
+ unsigned char *kinds)
+{
+ /* Host fallback. */
+ struct gomp_thread old_thr, *thr = gomp_thread ();
+ old_thr = *thr;
+ memset (thr, '\0', sizeof (*thr));
+ if (gomp_places_list)
+ {
+ thr->place = old_thr.place;
+ thr->ts.place_partition_len = gomp_places_list_len;
+ }
+ fn (hostaddrs);
+ gomp_free_thread (thr);
+ *thr = old_thr;
+}
+
+void
+GOMP_target_data (int device, const void *openmp_target, size_t mapnum,
+ void **hostaddrs, size_t *sizes, unsigned char *kinds)
+{
+}
+
+void
+GOMP_target_end_data (void)
+{
+}
+
+void
+GOMP_target_update (int device, const void *openmp_target, size_t mapnum,
+ void **hostaddrs, size_t *sizes, unsigned char *kinds)
+{
+}
+
+void
+GOMP_teams (unsigned int num_teams, unsigned int thread_limit)
+{
+ if (thread_limit)
+ {
+ struct gomp_task_icv *icv = gomp_icv (true);
+ icv->thread_limit_var
+ = thread_limit > INT_MAX ? UINT_MAX : thread_limit;
+ }
+ (void) num_teams;
+}
diff --git a/libgomp/task.c b/libgomp/task.c
index 7de650a43f1..a3d343fe126 100644
--- a/libgomp/task.c
+++ b/libgomp/task.c
@@ -29,6 +29,33 @@
#include <stdlib.h>
#include <string.h>
+typedef struct gomp_task_depend_entry *hash_entry_type;
+
+static inline void *
+htab_alloc (size_t size)
+{
+ return gomp_malloc (size);
+}
+
+static inline void
+htab_free (void *ptr)
+{
+ free (ptr);
+}
+
+#include "hashtab.h"
+
+static inline hashval_t
+htab_hash (hash_entry_type element)
+{
+ return hash_pointer (element->addr);
+}
+
+static inline bool
+htab_eq (hash_entry_type x, hash_entry_type y)
+{
+ return x->addr == y->addr;
+}
/* Create a new task data structure. */
@@ -42,7 +69,12 @@ gomp_init_task (struct gomp_task *task, struct gomp_task *parent_task,
task->in_taskwait = false;
task->in_tied_task = false;
task->final_task = false;
+ task->copy_ctors_done = false;
task->children = NULL;
+ task->taskgroup = NULL;
+ task->dependers = NULL;
+ task->depend_hash = NULL;
+ task->depend_count = 0;
gomp_sem_init (&task->taskwait_sem, 0);
}
@@ -78,7 +110,8 @@ gomp_clear_parent (struct gomp_task *children)
void
GOMP_task (void (*fn) (void *), void *data, void (*cpyfn) (void *, void *),
- long arg_size, long arg_align, bool if_clause, unsigned flags)
+ long arg_size, long arg_align, bool if_clause, unsigned flags,
+ void **depend)
{
struct gomp_thread *thr = gomp_thread ();
struct gomp_team *team = thr->ts.team;
@@ -94,17 +127,58 @@ GOMP_task (void (*fn) (void *), void *data, void (*cpyfn) (void *, void *),
flags &= ~1;
#endif
+ /* If parallel or taskgroup has been cancelled, don't start new tasks. */
+ if (team
+ && (gomp_team_barrier_cancelled (&team->barrier)
+ || (thr->task->taskgroup && thr->task->taskgroup->cancelled)))
+ return;
+
if (!if_clause || team == NULL
|| (thr->task && thr->task->final_task)
|| team->task_count > 64 * team->nthreads)
{
struct gomp_task task;
+ /* If there are depend clauses and earlier deferred sibling tasks
+ with depend clauses, check if there isn't a dependency. If there
+ is, fall through to the deferred task handling, as we can't
+ schedule such tasks right away. There is no need to handle
+ depend clauses for non-deferred tasks other than this, because
+ the parent task is suspended until the child task finishes and thus
+ it can't start further child tasks. */
+ if ((flags & 8) && thr->task && thr->task->depend_hash)
+ {
+ struct gomp_task *parent = thr->task;
+ struct gomp_task_depend_entry elem, *ent = NULL;
+ size_t ndepend = (uintptr_t) depend[0];
+ size_t nout = (uintptr_t) depend[1];
+ size_t i;
+ gomp_mutex_lock (&team->task_lock);
+ for (i = 0; i < ndepend; i++)
+ {
+ elem.addr = depend[i + 2];
+ ent = htab_find (parent->depend_hash, &elem);
+ for (; ent; ent = ent->next)
+ if (i >= nout && ent->is_in)
+ continue;
+ else
+ break;
+ if (ent)
+ break;
+ }
+ gomp_mutex_unlock (&team->task_lock);
+ if (ent)
+ goto defer;
+ }
+
gomp_init_task (&task, thr->task, gomp_icv (false));
task.kind = GOMP_TASK_IFFALSE;
task.final_task = (thr->task && thr->task->final_task) || (flags & 2);
if (thr->task)
- task.in_tied_task = thr->task->in_tied_task;
+ {
+ task.in_tied_task = thr->task->in_tied_task;
+ task.taskgroup = thr->task->taskgroup;
+ }
thr->task = &task;
if (__builtin_expect (cpyfn != NULL, 0))
{
@@ -135,29 +209,161 @@ GOMP_task (void (*fn) (void *), void *data, void (*cpyfn) (void *, void *),
}
else
{
+ defer:;
struct gomp_task *task;
struct gomp_task *parent = thr->task;
+ struct gomp_taskgroup *taskgroup = parent->taskgroup;
char *arg;
bool do_wake;
-
- task = gomp_malloc (sizeof (*task) + arg_size + arg_align - 1);
- arg = (char *) (((uintptr_t) (task + 1) + arg_align - 1)
+ size_t depend_size = 0;
+
+ if (flags & 8)
+ depend_size = ((uintptr_t) depend[0]
+ * sizeof (struct gomp_task_depend_entry));
+ task = gomp_malloc (sizeof (*task) + depend_size
+ + arg_size + arg_align - 1);
+ arg = (char *) (((uintptr_t) (task + 1) + depend_size + arg_align - 1)
& ~(uintptr_t) (arg_align - 1));
gomp_init_task (task, parent, gomp_icv (false));
task->kind = GOMP_TASK_IFFALSE;
task->in_tied_task = parent->in_tied_task;
+ task->taskgroup = taskgroup;
thr->task = task;
if (cpyfn)
- cpyfn (arg, data);
+ {
+ cpyfn (arg, data);
+ task->copy_ctors_done = true;
+ }
else
memcpy (arg, data, arg_size);
thr->task = parent;
task->kind = GOMP_TASK_WAITING;
task->fn = fn;
task->fn_data = arg;
- task->in_tied_task = true;
task->final_task = (flags & 2) >> 1;
gomp_mutex_lock (&team->task_lock);
+ /* If parallel or taskgroup has been cancelled, don't start new
+ tasks. */
+ if (__builtin_expect ((gomp_team_barrier_cancelled (&team->barrier)
+ || (taskgroup && taskgroup->cancelled))
+ && !task->copy_ctors_done, 0))
+ {
+ gomp_mutex_unlock (&team->task_lock);
+ gomp_finish_task (task);
+ free (task);
+ return;
+ }
+ if (taskgroup)
+ taskgroup->num_children++;
+ if (depend_size)
+ {
+ size_t ndepend = (uintptr_t) depend[0];
+ size_t nout = (uintptr_t) depend[1];
+ size_t i;
+ hash_entry_type ent;
+
+ task->depend_count = ndepend;
+ task->num_dependees = 0;
+ if (parent->depend_hash == NULL)
+ parent->depend_hash
+ = htab_create (2 * ndepend > 12 ? 2 * ndepend : 12);
+ for (i = 0; i < ndepend; i++)
+ {
+ task->depend[i].addr = depend[2 + i];
+ task->depend[i].next = NULL;
+ task->depend[i].prev = NULL;
+ task->depend[i].task = task;
+ task->depend[i].is_in = i >= nout;
+ task->depend[i].redundant = false;
+
+ hash_entry_type *slot
+ = htab_find_slot (&parent->depend_hash, &task->depend[i],
+ INSERT);
+ hash_entry_type out = NULL;
+ if (*slot)
+ {
+ /* If multiple depends on the same task are the
+ same, all but the first one are redundant.
+ As inout/out come first, if any of them is
+ inout/out, it will win, which is the right
+ semantics. */
+ if ((*slot)->task == task)
+ {
+ task->depend[i].redundant = true;
+ continue;
+ }
+ for (ent = *slot; ent; ent = ent->next)
+ {
+ /* depend(in:...) doesn't depend on earlier
+ depend(in:...). */
+ if (i >= nout && ent->is_in)
+ continue;
+
+ if (!ent->is_in)
+ out = ent;
+
+ struct gomp_task *tsk = ent->task;
+ if (tsk->dependers == NULL)
+ {
+ tsk->dependers
+ = gomp_malloc (sizeof (struct gomp_dependers_vec)
+ + 6 * sizeof (struct gomp_task *));
+ tsk->dependers->n_elem = 1;
+ tsk->dependers->allocated = 6;
+ tsk->dependers->elem[0] = task;
+ task->num_dependees++;
+ continue;
+ }
+ /* We already have some other dependency on tsk
+ from earlier depend clause. */
+ else if (tsk->dependers->n_elem
+ && (tsk->dependers->elem[tsk->dependers->n_elem
+ - 1]
+ == task))
+ continue;
+ else if (tsk->dependers->n_elem
+ == tsk->dependers->allocated)
+ {
+ tsk->dependers->allocated
+ = tsk->dependers->allocated * 2 + 2;
+ tsk->dependers
+ = gomp_realloc (tsk->dependers,
+ sizeof (struct gomp_dependers_vec)
+ + (tsk->dependers->allocated
+ * sizeof (struct gomp_task *)));
+ }
+ tsk->dependers->elem[tsk->dependers->n_elem++] = task;
+ task->num_dependees++;
+ }
+ task->depend[i].next = *slot;
+ (*slot)->prev = &task->depend[i];
+ }
+ *slot = &task->depend[i];
+
+ /* There is no need to store more than one depend({,in}out:)
+ task per address in the hash table chain, because each out
+ depends on all earlier outs, thus it is enough to record
+ just the last depend({,in}out:). For depend(in:), we need
+ to keep all of the previous ones not terminated yet, because
+ a later depend({,in}out:) might need to depend on all of
+ them. So, if the new task's clause is depend({,in}out:),
+ we know there is at most one other depend({,in}out:) clause
+ in the list (out) and to maintain the invariant we now
+ need to remove it from the list. */
+ if (!task->depend[i].is_in && out)
+ {
+ if (out->next)
+ out->next->prev = out->prev;
+ out->prev->next = out->next;
+ out->redundant = true;
+ }
+ }
+ if (task->num_dependees)
+ {
+ gomp_mutex_unlock (&team->task_lock);
+ return;
+ }
+ }
if (parent->children)
{
task->next_child = parent->children;
@@ -171,6 +377,22 @@ GOMP_task (void (*fn) (void *), void *data, void (*cpyfn) (void *, void *),
task->prev_child = task;
}
parent->children = task;
+ if (taskgroup)
+ {
+ if (taskgroup->children)
+ {
+ task->next_taskgroup = taskgroup->children;
+ task->prev_taskgroup = taskgroup->children->prev_taskgroup;
+ task->next_taskgroup->prev_taskgroup = task;
+ task->prev_taskgroup->next_taskgroup = task;
+ }
+ else
+ {
+ task->next_taskgroup = task;
+ task->prev_taskgroup = task;
+ }
+ taskgroup->children = task;
+ }
if (team->task_queue)
{
task->next_queue = team->task_queue;
@@ -185,6 +407,7 @@ GOMP_task (void (*fn) (void *), void *data, void (*cpyfn) (void *, void *),
team->task_queue = task;
}
++team->task_count;
+ ++team->task_queued_count;
gomp_team_barrier_set_task_pending (&team->barrier);
do_wake = team->task_running_count + !parent->in_tied_task
< team->nthreads;
@@ -194,6 +417,220 @@ GOMP_task (void (*fn) (void *), void *data, void (*cpyfn) (void *, void *),
}
}
+static inline bool
+gomp_task_run_pre (struct gomp_task *child_task, struct gomp_task *parent,
+ struct gomp_taskgroup *taskgroup, struct gomp_team *team)
+{
+ if (parent && parent->children == child_task)
+ parent->children = child_task->next_child;
+ if (taskgroup && taskgroup->children == child_task)
+ taskgroup->children = child_task->next_taskgroup;
+ child_task->prev_queue->next_queue = child_task->next_queue;
+ child_task->next_queue->prev_queue = child_task->prev_queue;
+ if (team->task_queue == child_task)
+ {
+ if (child_task->next_queue != child_task)
+ team->task_queue = child_task->next_queue;
+ else
+ team->task_queue = NULL;
+ }
+ child_task->kind = GOMP_TASK_TIED;
+ if (--team->task_queued_count == 0)
+ gomp_team_barrier_clear_task_pending (&team->barrier);
+ if ((gomp_team_barrier_cancelled (&team->barrier)
+ || (taskgroup && taskgroup->cancelled))
+ && !child_task->copy_ctors_done)
+ return true;
+ return false;
+}
+
+static void
+gomp_task_run_post_handle_depend_hash (struct gomp_task *child_task)
+{
+ struct gomp_task *parent = child_task->parent;
+ size_t i;
+
+ for (i = 0; i < child_task->depend_count; i++)
+ if (!child_task->depend[i].redundant)
+ {
+ if (child_task->depend[i].next)
+ child_task->depend[i].next->prev = child_task->depend[i].prev;
+ if (child_task->depend[i].prev)
+ child_task->depend[i].prev->next = child_task->depend[i].next;
+ else
+ {
+ hash_entry_type *slot
+ = htab_find_slot (&parent->depend_hash, &child_task->depend[i],
+ NO_INSERT);
+ if (*slot != &child_task->depend[i])
+ abort ();
+ if (child_task->depend[i].next)
+ *slot = child_task->depend[i].next;
+ else
+ htab_clear_slot (parent->depend_hash, slot);
+ }
+ }
+}
+
+static size_t
+gomp_task_run_post_handle_dependers (struct gomp_task *child_task,
+ struct gomp_team *team)
+{
+ struct gomp_task *parent = child_task->parent;
+ size_t i, count = child_task->dependers->n_elem, ret = 0;
+ for (i = 0; i < count; i++)
+ {
+ struct gomp_task *task = child_task->dependers->elem[i];
+ if (--task->num_dependees != 0)
+ continue;
+
+ struct gomp_taskgroup *taskgroup = task->taskgroup;
+ if (parent)
+ {
+ if (parent->children)
+ {
+ task->next_child = parent->children;
+ task->prev_child = parent->children->prev_child;
+ task->next_child->prev_child = task;
+ task->prev_child->next_child = task;
+ }
+ else
+ {
+ task->next_child = task;
+ task->prev_child = task;
+ }
+ parent->children = task;
+ if (parent->in_taskwait)
+ {
+ parent->in_taskwait = false;
+ gomp_sem_post (&parent->taskwait_sem);
+ }
+ }
+ if (taskgroup)
+ {
+ if (taskgroup->children)
+ {
+ task->next_taskgroup = taskgroup->children;
+ task->prev_taskgroup = taskgroup->children->prev_taskgroup;
+ task->next_taskgroup->prev_taskgroup = task;
+ task->prev_taskgroup->next_taskgroup = task;
+ }
+ else
+ {
+ task->next_taskgroup = task;
+ task->prev_taskgroup = task;
+ }
+ taskgroup->children = task;
+ if (taskgroup->in_taskgroup_wait)
+ {
+ taskgroup->in_taskgroup_wait = false;
+ gomp_sem_post (&taskgroup->taskgroup_sem);
+ }
+ }
+ if (team->task_queue)
+ {
+ task->next_queue = team->task_queue;
+ task->prev_queue = team->task_queue->prev_queue;
+ task->next_queue->prev_queue = task;
+ task->prev_queue->next_queue = task;
+ }
+ else
+ {
+ task->next_queue = task;
+ task->prev_queue = task;
+ team->task_queue = task;
+ }
+ ++team->task_count;
+ ++team->task_queued_count;
+ ++ret;
+ }
+ free (child_task->dependers);
+ child_task->dependers = NULL;
+ if (ret > 1)
+ gomp_team_barrier_set_task_pending (&team->barrier);
+ return ret;
+}
+
+static inline size_t
+gomp_task_run_post_handle_depend (struct gomp_task *child_task,
+ struct gomp_team *team)
+{
+ if (child_task->depend_count == 0)
+ return 0;
+
+ /* If parent is gone already, the hash table is freed and nothing
+ will use the hash table anymore, no need to remove anything from it. */
+ if (child_task->parent != NULL)
+ gomp_task_run_post_handle_depend_hash (child_task);
+
+ if (child_task->dependers == NULL)
+ return 0;
+
+ return gomp_task_run_post_handle_dependers (child_task, team);
+}
+
+static inline void
+gomp_task_run_post_remove_parent (struct gomp_task *child_task)
+{
+ struct gomp_task *parent = child_task->parent;
+ if (parent == NULL)
+ return;
+ child_task->prev_child->next_child = child_task->next_child;
+ child_task->next_child->prev_child = child_task->prev_child;
+ if (parent->children != child_task)
+ return;
+ if (child_task->next_child != child_task)
+ parent->children = child_task->next_child;
+ else
+ {
+ /* We access task->children in GOMP_taskwait
+ outside of the task lock mutex region, so
+ need a release barrier here to ensure memory
+ written by child_task->fn above is flushed
+ before the NULL is written. */
+ __atomic_store_n (&parent->children, NULL, MEMMODEL_RELEASE);
+ if (parent->in_taskwait)
+ {
+ parent->in_taskwait = false;
+ gomp_sem_post (&parent->taskwait_sem);
+ }
+ }
+}
+
+static inline void
+gomp_task_run_post_remove_taskgroup (struct gomp_task *child_task)
+{
+ struct gomp_taskgroup *taskgroup = child_task->taskgroup;
+ if (taskgroup == NULL)
+ return;
+ child_task->prev_taskgroup->next_taskgroup = child_task->next_taskgroup;
+ child_task->next_taskgroup->prev_taskgroup = child_task->prev_taskgroup;
+ if (taskgroup->num_children > 1)
+ --taskgroup->num_children;
+ else
+ {
+ /* We access taskgroup->num_children in GOMP_taskgroup_end
+ outside of the task lock mutex region, so
+ need a release barrier here to ensure memory
+ written by child_task->fn above is flushed
+ before the NULL is written. */
+ __atomic_store_n (&taskgroup->num_children, 0, MEMMODEL_RELEASE);
+ }
+ if (taskgroup->children != child_task)
+ return;
+ if (child_task->next_taskgroup != child_task)
+ taskgroup->children = child_task->next_taskgroup;
+ else
+ {
+ taskgroup->children = NULL;
+ if (taskgroup->in_taskgroup_wait)
+ {
+ taskgroup->in_taskgroup_wait = false;
+ gomp_sem_post (&taskgroup->taskgroup_sem);
+ }
+ }
+}
+
void
gomp_barrier_handle_tasks (gomp_barrier_state_t state)
{
@@ -202,6 +639,7 @@ gomp_barrier_handle_tasks (gomp_barrier_state_t state)
struct gomp_task *task = thr->task;
struct gomp_task *child_task = NULL;
struct gomp_task *to_free = NULL;
+ int do_wake = 0;
gomp_mutex_lock (&team->task_lock);
if (gomp_barrier_last_thread (state))
@@ -218,26 +656,31 @@ gomp_barrier_handle_tasks (gomp_barrier_state_t state)
while (1)
{
+ bool cancelled = false;
if (team->task_queue != NULL)
{
- struct gomp_task *parent;
-
child_task = team->task_queue;
- parent = child_task->parent;
- if (parent && parent->children == child_task)
- parent->children = child_task->next_child;
- child_task->prev_queue->next_queue = child_task->next_queue;
- child_task->next_queue->prev_queue = child_task->prev_queue;
- if (child_task->next_queue != child_task)
- team->task_queue = child_task->next_queue;
- else
- team->task_queue = NULL;
- child_task->kind = GOMP_TASK_TIED;
+ cancelled = gomp_task_run_pre (child_task, child_task->parent,
+ child_task->taskgroup, team);
+ if (__builtin_expect (cancelled, 0))
+ {
+ if (to_free)
+ {
+ gomp_finish_task (to_free);
+ free (to_free);
+ to_free = NULL;
+ }
+ goto finish_cancelled;
+ }
team->task_running_count++;
- if (team->task_count == team->task_running_count)
- gomp_team_barrier_clear_task_pending (&team->barrier);
+ child_task->in_tied_task = true;
}
gomp_mutex_unlock (&team->task_lock);
+ if (do_wake)
+ {
+ gomp_team_barrier_wake (&team->barrier, do_wake);
+ do_wake = 0;
+ }
if (to_free)
{
gomp_finish_task (to_free);
@@ -255,33 +698,22 @@ gomp_barrier_handle_tasks (gomp_barrier_state_t state)
gomp_mutex_lock (&team->task_lock);
if (child_task)
{
- struct gomp_task *parent = child_task->parent;
- if (parent)
- {
- child_task->prev_child->next_child = child_task->next_child;
- child_task->next_child->prev_child = child_task->prev_child;
- if (parent->children == child_task)
- {
- if (child_task->next_child != child_task)
- parent->children = child_task->next_child;
- else
- {
- /* We access task->children in GOMP_taskwait
- outside of the task lock mutex region, so
- need a release barrier here to ensure memory
- written by child_task->fn above is flushed
- before the NULL is written. */
- __atomic_store_n (&parent->children, NULL,
- MEMMODEL_RELEASE);
- if (parent->in_taskwait)
- gomp_sem_post (&parent->taskwait_sem);
- }
- }
- }
+ finish_cancelled:;
+ size_t new_tasks
+ = gomp_task_run_post_handle_depend (child_task, team);
+ gomp_task_run_post_remove_parent (child_task);
gomp_clear_parent (child_task->children);
+ gomp_task_run_post_remove_taskgroup (child_task);
to_free = child_task;
child_task = NULL;
- team->task_running_count--;
+ if (!cancelled)
+ team->task_running_count--;
+ if (new_tasks > 1)
+ {
+ do_wake = team->nthreads - team->task_running_count;
+ if (do_wake > new_tasks)
+ do_wake = new_tasks;
+ }
if (--team->task_count == 0
&& gomp_team_barrier_waiting_for_tasks (&team->barrier))
{
@@ -304,9 +736,10 @@ GOMP_taskwait (void)
struct gomp_task *task = thr->task;
struct gomp_task *child_task = NULL;
struct gomp_task *to_free = NULL;
+ int do_wake = 0;
/* The acquire barrier on load of task->children here synchronizes
- with the write of a NULL in gomp_barrier_handle_tasks. It is
+ with the write of a NULL in gomp_task_run_post_remove_parent. It is
not necessary that we synchronize with other non-NULL writes at
this point, but we must ensure that all writes to memory by a
child thread task work function are seen before we exit from
@@ -318,6 +751,7 @@ GOMP_taskwait (void)
gomp_mutex_lock (&team->task_lock);
while (1)
{
+ bool cancelled = false;
if (task->children == NULL)
{
gomp_mutex_unlock (&team->task_lock);
@@ -331,26 +765,30 @@ GOMP_taskwait (void)
if (task->children->kind == GOMP_TASK_WAITING)
{
child_task = task->children;
- task->children = child_task->next_child;
- child_task->prev_queue->next_queue = child_task->next_queue;
- child_task->next_queue->prev_queue = child_task->prev_queue;
- if (team->task_queue == child_task)
+ cancelled
+ = gomp_task_run_pre (child_task, task, child_task->taskgroup,
+ team);
+ if (__builtin_expect (cancelled, 0))
{
- if (child_task->next_queue != child_task)
- team->task_queue = child_task->next_queue;
- else
- team->task_queue = NULL;
+ if (to_free)
+ {
+ gomp_finish_task (to_free);
+ free (to_free);
+ to_free = NULL;
+ }
+ goto finish_cancelled;
}
- child_task->kind = GOMP_TASK_TIED;
- team->task_running_count++;
- if (team->task_count == team->task_running_count)
- gomp_team_barrier_clear_task_pending (&team->barrier);
}
else
/* All tasks we are waiting for are already running
in other threads. Wait for them. */
task->in_taskwait = true;
gomp_mutex_unlock (&team->task_lock);
+ if (do_wake)
+ {
+ gomp_team_barrier_wake (&team->barrier, do_wake);
+ do_wake = 0;
+ }
if (to_free)
{
gomp_finish_task (to_free);
@@ -364,14 +802,13 @@ GOMP_taskwait (void)
thr->task = task;
}
else
- {
- gomp_sem_wait (&task->taskwait_sem);
- task->in_taskwait = false;
- return;
- }
+ gomp_sem_wait (&task->taskwait_sem);
gomp_mutex_lock (&team->task_lock);
if (child_task)
{
+ finish_cancelled:;
+ size_t new_tasks
+ = gomp_task_run_post_handle_depend (child_task, team);
child_task->prev_child->next_child = child_task->next_child;
child_task->next_child->prev_child = child_task->prev_child;
if (task->children == child_task)
@@ -382,10 +819,17 @@ GOMP_taskwait (void)
task->children = NULL;
}
gomp_clear_parent (child_task->children);
+ gomp_task_run_post_remove_taskgroup (child_task);
to_free = child_task;
child_task = NULL;
team->task_count--;
- team->task_running_count--;
+ if (new_tasks > 1)
+ {
+ do_wake = team->nthreads - team->task_running_count
+ - !task->in_tied_task;
+ if (do_wake > new_tasks)
+ do_wake = new_tasks;
+ }
}
}
}
@@ -398,6 +842,153 @@ GOMP_taskyield (void)
/* Nothing at the moment. */
}
+void
+GOMP_taskgroup_start (void)
+{
+ struct gomp_thread *thr = gomp_thread ();
+ struct gomp_team *team = thr->ts.team;
+ struct gomp_task *task = thr->task;
+ struct gomp_taskgroup *taskgroup;
+
+ /* If team is NULL, all tasks are executed as
+ GOMP_TASK_IFFALSE tasks and thus all children tasks of
+ taskgroup and their descendant tasks will be finished
+ by the time GOMP_taskgroup_end is called. */
+ if (team == NULL)
+ return;
+ taskgroup = gomp_malloc (sizeof (struct gomp_taskgroup));
+ taskgroup->prev = task->taskgroup;
+ taskgroup->children = NULL;
+ taskgroup->in_taskgroup_wait = false;
+ taskgroup->cancelled = false;
+ taskgroup->num_children = 0;
+ gomp_sem_init (&taskgroup->taskgroup_sem, 0);
+ task->taskgroup = taskgroup;
+}
+
+void
+GOMP_taskgroup_end (void)
+{
+ struct gomp_thread *thr = gomp_thread ();
+ struct gomp_team *team = thr->ts.team;
+ struct gomp_task *task = thr->task;
+ struct gomp_taskgroup *taskgroup;
+ struct gomp_task *child_task = NULL;
+ struct gomp_task *to_free = NULL;
+ int do_wake = 0;
+
+ if (team == NULL)
+ return;
+ taskgroup = task->taskgroup;
+
+ /* The acquire barrier on load of taskgroup->num_children here
+ synchronizes with the write of 0 in gomp_task_run_post_remove_taskgroup.
+ It is not necessary that we synchronize with other non-0 writes at
+ this point, but we must ensure that all writes to memory by a
+ child thread task work function are seen before we exit from
+ GOMP_taskgroup_end. */
+ if (__atomic_load_n (&taskgroup->num_children, MEMMODEL_ACQUIRE) == 0)
+ goto finish;
+
+ gomp_mutex_lock (&team->task_lock);
+ while (1)
+ {
+ bool cancelled = false;
+ if (taskgroup->children == NULL)
+ {
+ if (taskgroup->num_children)
+ goto do_wait;
+ gomp_mutex_unlock (&team->task_lock);
+ if (to_free)
+ {
+ gomp_finish_task (to_free);
+ free (to_free);
+ }
+ goto finish;
+ }
+ if (taskgroup->children->kind == GOMP_TASK_WAITING)
+ {
+ child_task = taskgroup->children;
+ cancelled
+ = gomp_task_run_pre (child_task, child_task->parent, taskgroup,
+ team);
+ if (__builtin_expect (cancelled, 0))
+ {
+ if (to_free)
+ {
+ gomp_finish_task (to_free);
+ free (to_free);
+ to_free = NULL;
+ }
+ goto finish_cancelled;
+ }
+ }
+ else
+ {
+ do_wait:
+ /* All tasks we are waiting for are already running
+ in other threads. Wait for them. */
+ taskgroup->in_taskgroup_wait = true;
+ }
+ gomp_mutex_unlock (&team->task_lock);
+ if (do_wake)
+ {
+ gomp_team_barrier_wake (&team->barrier, do_wake);
+ do_wake = 0;
+ }
+ if (to_free)
+ {
+ gomp_finish_task (to_free);
+ free (to_free);
+ to_free = NULL;
+ }
+ if (child_task)
+ {
+ thr->task = child_task;
+ child_task->fn (child_task->fn_data);
+ thr->task = task;
+ }
+ else
+ gomp_sem_wait (&taskgroup->taskgroup_sem);
+ gomp_mutex_lock (&team->task_lock);
+ if (child_task)
+ {
+ finish_cancelled:;
+ size_t new_tasks
+ = gomp_task_run_post_handle_depend (child_task, team);
+ child_task->prev_taskgroup->next_taskgroup
+ = child_task->next_taskgroup;
+ child_task->next_taskgroup->prev_taskgroup
+ = child_task->prev_taskgroup;
+ --taskgroup->num_children;
+ if (taskgroup->children == child_task)
+ {
+ if (child_task->next_taskgroup != child_task)
+ taskgroup->children = child_task->next_taskgroup;
+ else
+ taskgroup->children = NULL;
+ }
+ gomp_task_run_post_remove_parent (child_task);
+ gomp_clear_parent (child_task->children);
+ to_free = child_task;
+ child_task = NULL;
+ team->task_count--;
+ if (new_tasks > 1)
+ {
+ do_wake = team->nthreads - team->task_running_count
+ - !task->in_tied_task;
+ if (do_wake > new_tasks)
+ do_wake = new_tasks;
+ }
+ }
+ }
+
+ finish:
+ task->taskgroup = taskgroup->prev;
+ gomp_sem_destroy (&taskgroup->taskgroup_sem);
+ free (taskgroup);
+}
+
int
omp_in_final (void)
{
diff --git a/libgomp/team.c b/libgomp/team.c
index 243aa9aa954..20f5f91750c 100644
--- a/libgomp/team.c
+++ b/libgomp/team.c
@@ -53,6 +53,7 @@ struct gomp_thread_start_data
struct gomp_team_state ts;
struct gomp_task *task;
struct gomp_thread_pool *thread_pool;
+ unsigned int place;
bool nested;
};
@@ -84,6 +85,7 @@ gomp_thread_start (void *xdata)
thr->thread_pool = data->thread_pool;
thr->ts = data->ts;
thr->task = data->task;
+ thr->place = data->place;
thr->ts.team->ordered_release[thr->ts.team_id] = &thr->release;
@@ -98,7 +100,7 @@ gomp_thread_start (void *xdata)
gomp_barrier_wait (&team->barrier);
local_fn (local_data);
- gomp_team_barrier_wait (&team->barrier);
+ gomp_team_barrier_wait_final (&team->barrier);
gomp_finish_task (task);
gomp_barrier_wait_last (&team->barrier);
}
@@ -113,7 +115,7 @@ gomp_thread_start (void *xdata)
struct gomp_task *task = thr->task;
local_fn (local_data);
- gomp_team_barrier_wait (&team->barrier);
+ gomp_team_barrier_wait_final (&team->barrier);
gomp_finish_task (task);
gomp_barrier_wait (&pool->threads_dock);
@@ -126,6 +128,8 @@ gomp_thread_start (void *xdata)
}
gomp_sem_destroy (&thr->release);
+ thr->thread_pool = NULL;
+ thr->task = NULL;
return NULL;
}
@@ -149,6 +153,7 @@ gomp_new_team (unsigned nthreads)
#else
gomp_mutex_init (&team->work_share_list_free_lock);
#endif
+ team->work_shares_to_free = &team->work_shares[0];
gomp_init_work_share (&team->work_shares[0], false, nthreads);
team->work_shares[0].next_alloc = NULL;
team->work_share_list_free = NULL;
@@ -167,7 +172,10 @@ gomp_new_team (unsigned nthreads)
gomp_mutex_init (&team->task_lock);
team->task_queue = NULL;
team->task_count = 0;
+ team->task_queued_count = 0;
team->task_running_count = 0;
+ team->work_share_cancelled = 0;
+ team->team_cancelled = 0;
return team;
}
@@ -199,16 +207,19 @@ static struct gomp_thread_pool *gomp_new_thread_pool (void)
static void
gomp_free_pool_helper (void *thread_pool)
{
+ struct gomp_thread *thr = gomp_thread ();
struct gomp_thread_pool *pool
= (struct gomp_thread_pool *) thread_pool;
gomp_barrier_wait_last (&pool->threads_dock);
- gomp_sem_destroy (&gomp_thread ()->release);
+ gomp_sem_destroy (&thr->release);
+ thr->thread_pool = NULL;
+ thr->task = NULL;
pthread_exit (NULL);
}
/* Free a thread pool and release its threads. */
-static void
+void
gomp_free_thread (void *arg __attribute__((unused)))
{
struct gomp_thread *thr = gomp_thread ();
@@ -236,9 +247,9 @@ gomp_free_thread (void *arg __attribute__((unused)))
__sync_fetch_and_add (&gomp_managed_threads,
1L - pool->threads_used);
#else
- gomp_mutex_lock (&gomp_remaining_threads_lock);
+ gomp_mutex_lock (&gomp_managed_threads_lock);
gomp_managed_threads -= pool->threads_used - 1L;
- gomp_mutex_unlock (&gomp_remaining_threads_lock);
+ gomp_mutex_unlock (&gomp_managed_threads_lock);
#endif
}
free (pool->threads);
@@ -259,7 +270,7 @@ gomp_free_thread (void *arg __attribute__((unused)))
void
gomp_team_start (void (*fn) (void *), void *data, unsigned nthreads,
- struct gomp_team *team)
+ unsigned flags, struct gomp_team *team)
{
struct gomp_thread_start_data *start_data;
struct gomp_thread *thr, *nthr;
@@ -270,17 +281,24 @@ gomp_team_start (void (*fn) (void *), void *data, unsigned nthreads,
unsigned i, n, old_threads_used = 0;
pthread_attr_t thread_attr, *attr;
unsigned long nthreads_var;
+ char bind, bind_var;
+ unsigned int s = 0, rest = 0, p = 0, k = 0;
+ unsigned int affinity_count = 0;
+ struct gomp_thread **affinity_thr = NULL;
thr = gomp_thread ();
nested = thr->ts.team != NULL;
if (__builtin_expect (thr->thread_pool == NULL, 0))
{
thr->thread_pool = gomp_new_thread_pool ();
+ thr->thread_pool->threads_busy = nthreads;
pthread_setspecific (gomp_thread_destructor, thr);
}
pool = thr->thread_pool;
task = thr->task;
icv = task ? &task->icv : &gomp_global_icv;
+ if (__builtin_expect (gomp_places_list != NULL, 0) && thr->place == 0)
+ gomp_init_affinity ();
/* Always save the previous state, even if this isn't a nested team.
In particular, we should save any work share state from an outer
@@ -303,14 +321,90 @@ gomp_team_start (void (*fn) (void *), void *data, unsigned nthreads,
if (__builtin_expect (gomp_nthreads_var_list != NULL, 0)
&& thr->ts.level < gomp_nthreads_var_list_len)
nthreads_var = gomp_nthreads_var_list[thr->ts.level];
+ bind_var = icv->bind_var;
+ if (bind_var != omp_proc_bind_false && (flags & 7) != omp_proc_bind_false)
+ bind_var = flags & 7;
+ bind = bind_var;
+ if (__builtin_expect (gomp_bind_var_list != NULL, 0)
+ && thr->ts.level < gomp_bind_var_list_len)
+ bind_var = gomp_bind_var_list[thr->ts.level];
gomp_init_task (thr->task, task, icv);
team->implicit_task[0].icv.nthreads_var = nthreads_var;
+ team->implicit_task[0].icv.bind_var = bind_var;
if (nthreads == 1)
return;
i = 1;
+ if (__builtin_expect (gomp_places_list != NULL, 0))
+ {
+ /* Depending on chosen proc_bind model, set subpartition
+ for the master thread and initialize helper variables
+ P and optionally S, K and/or REST used by later place
+ computation for each additional thread. */
+ p = thr->place - 1;
+ switch (bind)
+ {
+ case omp_proc_bind_true:
+ case omp_proc_bind_close:
+ if (nthreads > thr->ts.place_partition_len)
+ {
+ /* T > P. S threads will be placed in each place,
+ and the final REM threads placed one by one
+ into the already occupied places. */
+ s = nthreads / thr->ts.place_partition_len;
+ rest = nthreads % thr->ts.place_partition_len;
+ }
+ else
+ s = 1;
+ k = 1;
+ break;
+ case omp_proc_bind_master:
+ /* Each thread will be bound to master's place. */
+ break;
+ case omp_proc_bind_spread:
+ if (nthreads <= thr->ts.place_partition_len)
+ {
+ /* T <= P. Each subpartition will have in between s
+ and s+1 places (subpartitions starting at or
+ after rest will have s places, earlier s+1 places),
+ each thread will be bound to the first place in
+ its subpartition (except for the master thread
+ that can be bound to another place in its
+ subpartition). */
+ s = thr->ts.place_partition_len / nthreads;
+ rest = thr->ts.place_partition_len % nthreads;
+ rest = (s + 1) * rest + thr->ts.place_partition_off;
+ if (p < rest)
+ {
+ p -= (p - thr->ts.place_partition_off) % (s + 1);
+ thr->ts.place_partition_len = s + 1;
+ }
+ else
+ {
+ p -= (p - rest) % s;
+ thr->ts.place_partition_len = s;
+ }
+ thr->ts.place_partition_off = p;
+ }
+ else
+ {
+ /* T > P. Each subpartition will have just a single
+ place and we'll place between s and s+1
+ threads into each subpartition. */
+ s = nthreads / thr->ts.place_partition_len;
+ rest = nthreads % thr->ts.place_partition_len;
+ thr->ts.place_partition_off = p;
+ thr->ts.place_partition_len = 1;
+ k = 1;
+ }
+ break;
+ }
+ }
+ else
+ bind = omp_proc_bind_false;
+
/* We only allow the reuse of idle threads for non-nested PARALLEL
regions. This appears to be implied by the semantics of
threadprivate variables, but perhaps that's reading too much into
@@ -341,47 +435,244 @@ gomp_team_start (void (*fn) (void *), void *data, unsigned nthreads,
team will exit. */
pool->threads_used = nthreads;
+ /* If necessary, expand the size of the gomp_threads array. It is
+ expected that changes in the number of threads are rare, thus we
+ make no effort to expand gomp_threads_size geometrically. */
+ if (nthreads >= pool->threads_size)
+ {
+ pool->threads_size = nthreads + 1;
+ pool->threads
+ = gomp_realloc (pool->threads,
+ pool->threads_size
+ * sizeof (struct gomp_thread_data *));
+ }
+
/* Release existing idle threads. */
for (; i < n; ++i)
{
- nthr = pool->threads[i];
+ unsigned int place_partition_off = thr->ts.place_partition_off;
+ unsigned int place_partition_len = thr->ts.place_partition_len;
+ unsigned int place = 0;
+ if (__builtin_expect (gomp_places_list != NULL, 0))
+ {
+ switch (bind)
+ {
+ case omp_proc_bind_true:
+ case omp_proc_bind_close:
+ if (k == s)
+ {
+ ++p;
+ if (p == (team->prev_ts.place_partition_off
+ + team->prev_ts.place_partition_len))
+ p = team->prev_ts.place_partition_off;
+ k = 1;
+ if (i == nthreads - rest)
+ s = 1;
+ }
+ else
+ ++k;
+ break;
+ case omp_proc_bind_master:
+ break;
+ case omp_proc_bind_spread:
+ if (k == 0)
+ {
+ /* T <= P. */
+ if (p < rest)
+ p += s + 1;
+ else
+ p += s;
+ if (p == (team->prev_ts.place_partition_off
+ + team->prev_ts.place_partition_len))
+ p = team->prev_ts.place_partition_off;
+ place_partition_off = p;
+ if (p < rest)
+ place_partition_len = s + 1;
+ else
+ place_partition_len = s;
+ }
+ else
+ {
+ /* T > P. */
+ if (k == s)
+ {
+ ++p;
+ if (p == (team->prev_ts.place_partition_off
+ + team->prev_ts.place_partition_len))
+ p = team->prev_ts.place_partition_off;
+ k = 1;
+ if (i == nthreads - rest)
+ s = 1;
+ }
+ else
+ ++k;
+ place_partition_off = p;
+ place_partition_len = 1;
+ }
+ break;
+ }
+ if (affinity_thr != NULL
+ || (bind != omp_proc_bind_true
+ && pool->threads[i]->place != p + 1)
+ || pool->threads[i]->place <= place_partition_off
+ || pool->threads[i]->place > (place_partition_off
+ + place_partition_len))
+ {
+ unsigned int l;
+ if (affinity_thr == NULL)
+ {
+ unsigned int j;
+
+ if (team->prev_ts.place_partition_len > 64)
+ affinity_thr
+ = gomp_malloc (team->prev_ts.place_partition_len
+ * sizeof (struct gomp_thread *));
+ else
+ affinity_thr
+ = gomp_alloca (team->prev_ts.place_partition_len
+ * sizeof (struct gomp_thread *));
+ memset (affinity_thr, '\0',
+ team->prev_ts.place_partition_len
+ * sizeof (struct gomp_thread *));
+ for (j = i; j < old_threads_used; j++)
+ {
+ if (pool->threads[j]->place
+ > team->prev_ts.place_partition_off
+ && (pool->threads[j]->place
+ <= (team->prev_ts.place_partition_off
+ + team->prev_ts.place_partition_len)))
+ {
+ l = pool->threads[j]->place - 1
+ - team->prev_ts.place_partition_off;
+ pool->threads[j]->data = affinity_thr[l];
+ affinity_thr[l] = pool->threads[j];
+ }
+ pool->threads[j] = NULL;
+ }
+ if (nthreads > old_threads_used)
+ memset (&pool->threads[old_threads_used],
+ '\0', ((nthreads - old_threads_used)
+ * sizeof (struct gomp_thread *)));
+ n = nthreads;
+ affinity_count = old_threads_used - i;
+ }
+ if (affinity_count == 0)
+ break;
+ l = p;
+ if (affinity_thr[l - team->prev_ts.place_partition_off]
+ == NULL)
+ {
+ if (bind != omp_proc_bind_true)
+ continue;
+ for (l = place_partition_off;
+ l < place_partition_off + place_partition_len;
+ l++)
+ if (affinity_thr[l - team->prev_ts.place_partition_off]
+ != NULL)
+ break;
+ if (l == place_partition_off + place_partition_len)
+ continue;
+ }
+ nthr = affinity_thr[l - team->prev_ts.place_partition_off];
+ affinity_thr[l - team->prev_ts.place_partition_off]
+ = (struct gomp_thread *) nthr->data;
+ affinity_count--;
+ pool->threads[i] = nthr;
+ }
+ else
+ nthr = pool->threads[i];
+ place = p + 1;
+ }
+ else
+ nthr = pool->threads[i];
nthr->ts.team = team;
nthr->ts.work_share = &team->work_shares[0];
nthr->ts.last_work_share = NULL;
nthr->ts.team_id = i;
nthr->ts.level = team->prev_ts.level + 1;
nthr->ts.active_level = thr->ts.active_level;
+ nthr->ts.place_partition_off = place_partition_off;
+ nthr->ts.place_partition_len = place_partition_len;
#ifdef HAVE_SYNC_BUILTINS
nthr->ts.single_count = 0;
#endif
nthr->ts.static_trip = 0;
nthr->task = &team->implicit_task[i];
+ nthr->place = place;
gomp_init_task (nthr->task, task, icv);
team->implicit_task[i].icv.nthreads_var = nthreads_var;
+ team->implicit_task[i].icv.bind_var = bind_var;
nthr->fn = fn;
nthr->data = data;
team->ordered_release[i] = &nthr->release;
}
+ if (__builtin_expect (affinity_thr != NULL, 0))
+ {
+ /* If AFFINITY_THR is non-NULL just because we had to
+ permute some threads in the pool, but we've managed
+ to find exactly as many old threads as we'd find
+ without affinity, we don't need to handle this
+ specially anymore. */
+ if (nthreads <= old_threads_used
+ ? (affinity_count == old_threads_used - nthreads)
+ : (i == old_threads_used))
+ {
+ if (team->prev_ts.place_partition_len > 64)
+ free (affinity_thr);
+ affinity_thr = NULL;
+ affinity_count = 0;
+ }
+ else
+ {
+ i = 1;
+ /* We are going to compute the places/subpartitions
+ again from the beginning. So, we need to reinitialize
+ vars modified by the switch (bind) above inside
+ of the loop, to the state they had after the initial
+ switch (bind). */
+ switch (bind)
+ {
+ case omp_proc_bind_true:
+ case omp_proc_bind_close:
+ if (nthreads > thr->ts.place_partition_len)
+ /* T > P. S has been changed, so needs
+ to be recomputed. */
+ s = nthreads / thr->ts.place_partition_len;
+ k = 1;
+ p = thr->place - 1;
+ break;
+ case omp_proc_bind_master:
+ /* No vars have been changed. */
+ break;
+ case omp_proc_bind_spread:
+ p = thr->ts.place_partition_off;
+ if (k != 0)
+ {
+ /* T > P. */
+ s = nthreads / team->prev_ts.place_partition_len;
+ k = 1;
+ }
+ break;
+ }
+
+ /* Increase the barrier threshold to make sure all new
+ threads and all the threads we're going to let die
+ arrive before the team is released. */
+ if (affinity_count)
+ gomp_barrier_reinit (&pool->threads_dock,
+ nthreads + affinity_count);
+ }
+ }
+
if (i == nthreads)
goto do_release;
- /* If necessary, expand the size of the gomp_threads array. It is
- expected that changes in the number of threads are rare, thus we
- make no effort to expand gomp_threads_size geometrically. */
- if (nthreads >= pool->threads_size)
- {
- pool->threads_size = nthreads + 1;
- pool->threads
- = gomp_realloc (pool->threads,
- pool->threads_size
- * sizeof (struct gomp_thread_data *));
- }
}
- if (__builtin_expect (nthreads > old_threads_used, 0))
+ if (__builtin_expect (nthreads + affinity_count > old_threads_used, 0))
{
- long diff = (long) nthreads - (long) old_threads_used;
+ long diff = (long) (nthreads + affinity_count) - (long) old_threads_used;
if (old_threads_used == 0)
--diff;
@@ -389,14 +680,14 @@ gomp_team_start (void (*fn) (void *), void *data, unsigned nthreads,
#ifdef HAVE_SYNC_BUILTINS
__sync_fetch_and_add (&gomp_managed_threads, diff);
#else
- gomp_mutex_lock (&gomp_remaining_threads_lock);
+ gomp_mutex_lock (&gomp_managed_threads_lock);
gomp_managed_threads += diff;
- gomp_mutex_unlock (&gomp_remaining_threads_lock);
+ gomp_mutex_unlock (&gomp_managed_threads_lock);
#endif
}
attr = &gomp_thread_attr;
- if (__builtin_expect (gomp_cpu_affinity != NULL, 0))
+ if (__builtin_expect (gomp_places_list != NULL, 0))
{
size_t stacksize;
pthread_attr_init (&thread_attr);
@@ -410,11 +701,78 @@ gomp_team_start (void (*fn) (void *), void *data, unsigned nthreads,
* (nthreads-i));
/* Launch new threads. */
- for (; i < nthreads; ++i, ++start_data)
+ for (; i < nthreads; ++i)
{
pthread_t pt;
int err;
+ start_data->ts.place_partition_off = thr->ts.place_partition_off;
+ start_data->ts.place_partition_len = thr->ts.place_partition_len;
+ start_data->place = 0;
+ if (__builtin_expect (gomp_places_list != NULL, 0))
+ {
+ switch (bind)
+ {
+ case omp_proc_bind_true:
+ case omp_proc_bind_close:
+ if (k == s)
+ {
+ ++p;
+ if (p == (team->prev_ts.place_partition_off
+ + team->prev_ts.place_partition_len))
+ p = team->prev_ts.place_partition_off;
+ k = 1;
+ if (i == nthreads - rest)
+ s = 1;
+ }
+ else
+ ++k;
+ break;
+ case omp_proc_bind_master:
+ break;
+ case omp_proc_bind_spread:
+ if (k == 0)
+ {
+ /* T <= P. */
+ if (p < rest)
+ p += s + 1;
+ else
+ p += s;
+ if (p == (team->prev_ts.place_partition_off
+ + team->prev_ts.place_partition_len))
+ p = team->prev_ts.place_partition_off;
+ start_data->ts.place_partition_off = p;
+ if (p < rest)
+ start_data->ts.place_partition_len = s + 1;
+ else
+ start_data->ts.place_partition_len = s;
+ }
+ else
+ {
+ /* T > P. */
+ if (k == s)
+ {
+ ++p;
+ if (p == (team->prev_ts.place_partition_off
+ + team->prev_ts.place_partition_len))
+ p = team->prev_ts.place_partition_off;
+ k = 1;
+ if (i == nthreads - rest)
+ s = 1;
+ }
+ else
+ ++k;
+ start_data->ts.place_partition_off = p;
+ start_data->ts.place_partition_len = 1;
+ }
+ break;
+ }
+ start_data->place = p + 1;
+ if (affinity_thr != NULL && pool->threads[i] != NULL)
+ continue;
+ gomp_init_thread_affinity (attr, p);
+ }
+
start_data->fn = fn;
start_data->fn_data = data;
start_data->ts.team = team;
@@ -430,18 +788,16 @@ gomp_team_start (void (*fn) (void *), void *data, unsigned nthreads,
start_data->task = &team->implicit_task[i];
gomp_init_task (start_data->task, task, icv);
team->implicit_task[i].icv.nthreads_var = nthreads_var;
+ team->implicit_task[i].icv.bind_var = bind_var;
start_data->thread_pool = pool;
start_data->nested = nested;
- if (gomp_cpu_affinity != NULL)
- gomp_init_thread_affinity (attr);
-
- err = pthread_create (&pt, attr, gomp_thread_start, start_data);
+ err = pthread_create (&pt, attr, gomp_thread_start, start_data++);
if (err != 0)
gomp_fatal ("Thread creation failed: %s", strerror (err));
}
- if (__builtin_expect (gomp_cpu_affinity != NULL, 0))
+ if (__builtin_expect (gomp_places_list != NULL, 0))
pthread_attr_destroy (&thread_attr);
do_release:
@@ -450,21 +806,32 @@ gomp_team_start (void (*fn) (void *), void *data, unsigned nthreads,
/* Decrease the barrier threshold to match the number of threads
that should arrive back at the end of this team. The extra
threads should be exiting. Note that we arrange for this test
- to never be true for nested teams. */
- if (__builtin_expect (nthreads < old_threads_used, 0))
+ to never be true for nested teams. If AFFINITY_COUNT is non-zero,
+ the barrier as well as gomp_managed_threads was temporarily
+ set to NTHREADS + AFFINITY_COUNT. For NTHREADS < OLD_THREADS_COUNT,
+ AFFINITY_COUNT if non-zero will be always at least
+ OLD_THREADS_COUNT - NTHREADS. */
+ if (__builtin_expect (nthreads < old_threads_used, 0)
+ || __builtin_expect (affinity_count, 0))
{
long diff = (long) nthreads - (long) old_threads_used;
+ if (affinity_count)
+ diff = -affinity_count;
+
gomp_barrier_reinit (&pool->threads_dock, nthreads);
#ifdef HAVE_SYNC_BUILTINS
__sync_fetch_and_add (&gomp_managed_threads, diff);
#else
- gomp_mutex_lock (&gomp_remaining_threads_lock);
+ gomp_mutex_lock (&gomp_managed_threads_lock);
gomp_managed_threads += diff;
- gomp_mutex_unlock (&gomp_remaining_threads_lock);
+ gomp_mutex_unlock (&gomp_managed_threads_lock);
#endif
}
+ if (__builtin_expect (affinity_thr != NULL, 0)
+ && team->prev_ts.place_partition_len > 64)
+ free (affinity_thr);
}
@@ -477,9 +844,26 @@ gomp_team_end (void)
struct gomp_thread *thr = gomp_thread ();
struct gomp_team *team = thr->ts.team;
- /* This barrier handles all pending explicit threads. */
- gomp_team_barrier_wait (&team->barrier);
- gomp_fini_work_share (thr->ts.work_share);
+ /* This barrier handles all pending explicit threads.
+ As #pragma omp cancel parallel might get awaited count in
+ team->barrier in a inconsistent state, we need to use a different
+ counter here. */
+ gomp_team_barrier_wait_final (&team->barrier);
+ if (__builtin_expect (team->team_cancelled, 0))
+ {
+ struct gomp_work_share *ws = team->work_shares_to_free;
+ do
+ {
+ struct gomp_work_share *next_ws = gomp_ptrlock_get (&ws->next_ws);
+ if (next_ws == NULL)
+ gomp_ptrlock_set (&ws->next_ws, ws);
+ gomp_fini_work_share (ws);
+ ws = next_ws;
+ }
+ while (ws != NULL);
+ }
+ else
+ gomp_fini_work_share (thr->ts.work_share);
gomp_end_task ();
thr->ts = team->prev_ts;
@@ -489,9 +873,9 @@ gomp_team_end (void)
#ifdef HAVE_SYNC_BUILTINS
__sync_fetch_and_add (&gomp_managed_threads, 1L - team->nthreads);
#else
- gomp_mutex_lock (&gomp_remaining_threads_lock);
+ gomp_mutex_lock (&gomp_managed_threads_lock);
gomp_managed_threads -= team->nthreads - 1L;
- gomp_mutex_unlock (&gomp_remaining_threads_lock);
+ gomp_mutex_unlock (&gomp_managed_threads_lock);
#endif
/* This barrier has gomp_barrier_wait_last counterparts
and ensures the team can be safely destroyed. */
@@ -532,8 +916,6 @@ gomp_team_end (void)
static void __attribute__((constructor))
initialize_team (void)
{
- struct gomp_thread *thr;
-
#ifndef HAVE_TLS
static struct gomp_thread initial_thread_tls_data;
@@ -543,13 +925,6 @@ initialize_team (void)
if (pthread_key_create (&gomp_thread_destructor, gomp_free_thread) != 0)
gomp_fatal ("could not create thread pool destructor.");
-
-#ifdef HAVE_TLS
- thr = &gomp_tls_data;
-#else
- thr = &initial_thread_tls_data;
-#endif
- gomp_sem_init (&thr->release, 0);
}
static void __attribute__((destructor))
diff --git a/libgomp/testsuite/lib/libgomp.exp b/libgomp/testsuite/lib/libgomp.exp
index 72daa7e3a3e..c965147e4fd 100644
--- a/libgomp/testsuite/lib/libgomp.exp
+++ b/libgomp/testsuite/lib/libgomp.exp
@@ -167,8 +167,8 @@ proc libgomp_init { args } {
# Disable caret
lappend ALWAYS_CFLAGS "additional_flags=-fno-diagnostics-show-caret"
- # And, gee, turn on OpenMP.
- lappend ALWAYS_CFLAGS "additional_flags=-fopenmp"
+ # Disable color diagnostics
+ lappend ALWAYS_CFLAGS "additional_flags=-fdiagnostics-color=never"
}
#
diff --git a/libgomp/testsuite/libgomp.c++/affinity-1.C b/libgomp/testsuite/libgomp.c++/affinity-1.C
new file mode 100644
index 00000000000..d20b392baf6
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/affinity-1.C
@@ -0,0 +1,4 @@
+// { dg-do run }
+// { dg-set-target-env-var OMP_PROC_BIND "true" }
+
+#include "../libgomp.c/affinity-1.c"
diff --git a/libgomp/testsuite/libgomp.c++/atomic-10.C b/libgomp/testsuite/libgomp.c++/atomic-10.C
new file mode 100644
index 00000000000..2145f288233
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/atomic-10.C
@@ -0,0 +1,99 @@
+// { dg-do run }
+
+extern "C" void abort (void);
+int x = 6;
+
+int
+main ()
+{
+ int v, l = 2, s = 1;
+ #pragma omp atomic
+ x = -3 + x;
+ #pragma omp atomic read
+ v = x;
+ if (v != 3)
+ abort ();
+ #pragma omp atomic update
+ x = 3 * 2 * 1 + x;
+ #pragma omp atomic read
+ v = x;
+ if (v != 9)
+ abort ();
+ #pragma omp atomic capture
+ v = x = x | 16;
+ if (v != 25)
+ abort ();
+ #pragma omp atomic capture
+ v = x = x + 14 * 2 / 4;
+ if (v != 32)
+ abort ();
+ #pragma omp atomic capture
+ v = x = 5 | x;
+ if (v != 37)
+ abort ();
+ #pragma omp atomic capture
+ v = x = 40 + 12 - 2 - 7 - x;
+ if (v != 6)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != 6)
+ abort ();
+ #pragma omp atomic capture
+ { v = x; x = 3 + x; }
+ if (v != 6)
+ abort ();
+ #pragma omp atomic capture
+ { v = x; x = -1 * -1 * -1 * -1 - x; }
+ if (v != 9)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != -8)
+ abort ();
+ #pragma omp atomic capture
+ { x = 2 * 2 - x; v = x; }
+ if (v != 12)
+ abort ();
+ #pragma omp atomic capture
+ { x = 7 & x; v = x; }
+ if (v != 4)
+ abort ();
+ #pragma omp atomic capture
+ { v = x; x = 6; }
+ if (v != 4)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != 6)
+ abort ();
+ #pragma omp atomic capture
+ { v = x; x = 7 * 8 + 23; }
+ if (v != 6)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != 79)
+ abort ();
+ #pragma omp atomic capture
+ { v = x; x = 23 + 6 * 4; }
+ if (v != 79)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != 47)
+ abort ();
+ #pragma omp atomic capture
+ { v = x; x = l ? 17 : 12; }
+ if (v != 47)
+ abort ();
+ #pragma omp atomic capture
+ { v = x; x = l = s++ + 3; }
+ if (v != 17 || l != 4 || s != 2)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != 4)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/atomic-11.C b/libgomp/testsuite/libgomp.c++/atomic-11.C
new file mode 100644
index 00000000000..c7101e01408
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/atomic-11.C
@@ -0,0 +1,108 @@
+// { dg-do run }
+
+extern "C" void abort (void);
+
+template <typename T>
+void
+foo ()
+{
+ extern T x;
+ T v, l = 2, s = 1;
+ #pragma omp atomic
+ x = -3 + x;
+ #pragma omp atomic read
+ v = x;
+ if (v != 3)
+ abort ();
+ #pragma omp atomic update
+ x = 3 * 2 * 1 + x;
+ #pragma omp atomic read
+ v = x;
+ if (v != 9)
+ abort ();
+ #pragma omp atomic capture
+ v = x = x | 16;
+ if (v != 25)
+ abort ();
+ #pragma omp atomic capture
+ v = x = x + 14 * 2 / 4;
+ if (v != 32)
+ abort ();
+ #pragma omp atomic capture
+ v = x = 5 | x;
+ if (v != 37)
+ abort ();
+ #pragma omp atomic capture
+ v = x = 40 + 12 - 2 - 7 - x;
+ if (v != 6)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != 6)
+ abort ();
+ #pragma omp atomic capture
+ { v = x; x = 3 + x; }
+ if (v != 6)
+ abort ();
+ #pragma omp atomic capture
+ { v = x; x = -1 * -1 * -1 * -1 - x; }
+ if (v != 9)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != -8)
+ abort ();
+ #pragma omp atomic capture
+ { x = 2 * 2 - x; v = x; }
+ if (v != 12)
+ abort ();
+ #pragma omp atomic capture
+ { x = 7 & x; v = x; }
+ if (v != 4)
+ abort ();
+ #pragma omp atomic capture
+ { v = x; x = 6; }
+ if (v != 4)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != 6)
+ abort ();
+ #pragma omp atomic capture
+ { v = x; x = 7 * 8 + 23; }
+ if (v != 6)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != 79)
+ abort ();
+ #pragma omp atomic capture
+ { v = x; x = 23 + 6 * 4; }
+ if (v != 79)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != 47)
+ abort ();
+ #pragma omp atomic capture
+ { v = x; x = l ? 17 : 12; }
+ if (v != 47)
+ abort ();
+ #pragma omp atomic capture
+ { v = x; x = l = s++ + 3; }
+ if (v != 17 || l != 4 || s != 2)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != 4)
+ abort ();
+}
+
+int x = 6;
+
+int
+main ()
+{
+ foo <int> ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/atomic-12.C b/libgomp/testsuite/libgomp.c++/atomic-12.C
new file mode 100644
index 00000000000..d1ae9d8c88c
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/atomic-12.C
@@ -0,0 +1,58 @@
+// { dg-do run }
+
+extern "C" void abort ();
+int x = 6, cnt;
+
+int
+foo ()
+{
+ return cnt++;
+}
+
+int
+main ()
+{
+ int v, *p;
+ p = &x;
+ #pragma omp atomic update
+ p[foo (), 0] = 16 + 6 - p[foo (), 0];
+ #pragma omp atomic read
+ v = x;
+ if (cnt != 2 || v != 16)
+ abort ();
+ #pragma omp atomic capture
+ v = p[foo () + foo (), 0] = p[foo () + foo (), 0] + 3;
+ if (cnt != 6 || v != 19)
+ abort ();
+ #pragma omp atomic capture
+ v = p[foo (), 0] = 12 * 1 / 2 + (foo (), 0) + p[foo (), 0];
+ if (cnt != 9 || v != 25)
+ abort ();
+ #pragma omp atomic capture
+ {
+ v = p[foo () & 0]; p[foo () & 0] = (foo (), 1) * 9 - p[foo () & 0];
+ }
+ if (cnt != 13 || v != 25)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != -16)
+ abort ();
+ #pragma omp atomic capture
+ {
+ p[0 & foo ()] = 16 - 2 + 3 + p[0 & foo ()]; v = p[0 & foo ()];
+ }
+ if (cnt != 16 || v != 1)
+ abort ();
+ #pragma omp atomic capture
+ {
+ v = p[foo (), 0]; p[foo (), 0] = (foo (), 7) ? 13 : foo () + 6;
+ }
+ if (cnt != 19 || v != 1)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != 13)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/atomic-13.C b/libgomp/testsuite/libgomp.c++/atomic-13.C
new file mode 100644
index 00000000000..0569d1c6deb
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/atomic-13.C
@@ -0,0 +1,68 @@
+// { dg-do run }
+
+extern "C" void abort ();
+int cnt;
+
+int
+foo ()
+{
+ return cnt++;
+}
+
+template <typename T>
+void
+bar ()
+{
+ extern T x;
+ T v, *p;
+ p = &x;
+ #pragma omp atomic update
+ p[foo (), 0] = 16 + 6 - p[foo (), 0];
+ #pragma omp atomic read
+ v = x;
+ if (cnt != 2 || v != 16)
+ abort ();
+ #pragma omp atomic capture
+ v = p[foo () + foo (), 0] = p[foo () + foo (), 0] + 3;
+ if (cnt != 6 || v != 19)
+ abort ();
+ #pragma omp atomic capture
+ v = p[foo (), 0] = 12 * 1 / 2 + (foo (), 0) + p[foo (), 0];
+ if (cnt != 9 || v != 25)
+ abort ();
+ #pragma omp atomic capture
+ {
+ v = p[foo () & 0]; p[foo () & 0] = (foo (), 1) * 9 - p[foo () & 0];
+ }
+ if (cnt != 13 || v != 25)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != -16)
+ abort ();
+ #pragma omp atomic capture
+ {
+ p[0 & foo ()] = 16 - 2 + 3 + p[0 & foo ()]; v = p[0 & foo ()];
+ }
+ if (cnt != 16 || v != 1)
+ abort ();
+ #pragma omp atomic capture
+ {
+ v = p[foo (), 0]; p[foo (), 0] = (foo (), 7) ? 13 : foo () + 6;
+ }
+ if (cnt != 19 || v != 1)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != 13)
+ abort ();
+}
+
+int x = 6;
+
+int
+main ()
+{
+ bar <int> ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/atomic-14.C b/libgomp/testsuite/libgomp.c++/atomic-14.C
new file mode 100644
index 00000000000..4cd9df812d3
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/atomic-14.C
@@ -0,0 +1,99 @@
+// { dg-do run }
+
+extern "C" void abort (void);
+int x = 6;
+
+int
+main ()
+{
+ int v, l = 2, s = 1;
+ #pragma omp atomic seq_cst
+ x = -3 + x;
+ #pragma omp atomic read seq_cst
+ v = x;
+ if (v != 3)
+ abort ();
+ #pragma omp atomic update seq_cst
+ x = 3 * 2 * 1 + x;
+ #pragma omp atomic read seq_cst
+ v = x;
+ if (v != 9)
+ abort ();
+ #pragma omp atomic capture seq_cst
+ v = x = x | 16;
+ if (v != 25)
+ abort ();
+ #pragma omp atomic capture seq_cst
+ v = x = x + 14 * 2 / 4;
+ if (v != 32)
+ abort ();
+ #pragma omp atomic capture seq_cst
+ v = x = 5 | x;
+ if (v != 37)
+ abort ();
+ #pragma omp atomic capture seq_cst
+ v = x = 40 + 12 - 2 - 7 - x;
+ if (v != 6)
+ abort ();
+ #pragma omp atomic read seq_cst
+ v = x;
+ if (v != 6)
+ abort ();
+ #pragma omp atomic capture seq_cst
+ { v = x; x = 3 + x; }
+ if (v != 6)
+ abort ();
+ #pragma omp atomic capture seq_cst
+ { v = x; x = -1 * -1 * -1 * -1 - x; }
+ if (v != 9)
+ abort ();
+ #pragma omp atomic read seq_cst
+ v = x;
+ if (v != -8)
+ abort ();
+ #pragma omp atomic capture seq_cst
+ { x = 2 * 2 - x; v = x; }
+ if (v != 12)
+ abort ();
+ #pragma omp atomic capture seq_cst
+ { x = 7 & x; v = x; }
+ if (v != 4)
+ abort ();
+ #pragma omp atomic capture seq_cst
+ { v = x; x = 6; }
+ if (v != 4)
+ abort ();
+ #pragma omp atomic read seq_cst
+ v = x;
+ if (v != 6)
+ abort ();
+ #pragma omp atomic capture seq_cst
+ { v = x; x = 7 * 8 + 23; }
+ if (v != 6)
+ abort ();
+ #pragma omp atomic read seq_cst
+ v = x;
+ if (v != 79)
+ abort ();
+ #pragma omp atomic capture seq_cst
+ { v = x; x = 23 + 6 * 4; }
+ if (v != 79)
+ abort ();
+ #pragma omp atomic read seq_cst
+ v = x;
+ if (v != 47)
+ abort ();
+ #pragma omp atomic capture seq_cst
+ { v = x; x = l ? 17 : 12; }
+ if (v != 47)
+ abort ();
+ #pragma omp atomic capture seq_cst
+ { v = x; x = l = s++ + 3; }
+ if (v != 17 || l != 4 || s != 2)
+ abort ();
+ #pragma omp atomic read seq_cst
+ v = x;
+ if (v != 4)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/atomic-15.C b/libgomp/testsuite/libgomp.c++/atomic-15.C
new file mode 100644
index 00000000000..1eabce7dbd3
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/atomic-15.C
@@ -0,0 +1,108 @@
+// { dg-do run }
+
+extern "C" void abort (void);
+
+template <typename T>
+void
+foo ()
+{
+ extern T x;
+ T v, l = 2, s = 1;
+ #pragma omp atomic seq_cst
+ x = -3 + x;
+ #pragma omp atomic read seq_cst
+ v = x;
+ if (v != 3)
+ abort ();
+ #pragma omp atomic update seq_cst
+ x = 3 * 2 * 1 + x;
+ #pragma omp atomic read seq_cst
+ v = x;
+ if (v != 9)
+ abort ();
+ #pragma omp atomic capture seq_cst
+ v = x = x | 16;
+ if (v != 25)
+ abort ();
+ #pragma omp atomic capture seq_cst
+ v = x = x + 14 * 2 / 4;
+ if (v != 32)
+ abort ();
+ #pragma omp atomic capture seq_cst
+ v = x = 5 | x;
+ if (v != 37)
+ abort ();
+ #pragma omp atomic capture seq_cst
+ v = x = 40 + 12 - 2 - 7 - x;
+ if (v != 6)
+ abort ();
+ #pragma omp atomic read seq_cst
+ v = x;
+ if (v != 6)
+ abort ();
+ #pragma omp atomic capture seq_cst
+ { v = x; x = 3 + x; }
+ if (v != 6)
+ abort ();
+ #pragma omp atomic capture seq_cst
+ { v = x; x = -1 * -1 * -1 * -1 - x; }
+ if (v != 9)
+ abort ();
+ #pragma omp atomic read seq_cst
+ v = x;
+ if (v != -8)
+ abort ();
+ #pragma omp atomic capture seq_cst
+ { x = 2 * 2 - x; v = x; }
+ if (v != 12)
+ abort ();
+ #pragma omp atomic capture seq_cst
+ { x = 7 & x; v = x; }
+ if (v != 4)
+ abort ();
+ #pragma omp atomic capture seq_cst
+ { v = x; x = 6; }
+ if (v != 4)
+ abort ();
+ #pragma omp atomic read seq_cst
+ v = x;
+ if (v != 6)
+ abort ();
+ #pragma omp atomic capture seq_cst
+ { v = x; x = 7 * 8 + 23; }
+ if (v != 6)
+ abort ();
+ #pragma omp atomic read seq_cst
+ v = x;
+ if (v != 79)
+ abort ();
+ #pragma omp atomic capture seq_cst
+ { v = x; x = 23 + 6 * 4; }
+ if (v != 79)
+ abort ();
+ #pragma omp atomic read seq_cst
+ v = x;
+ if (v != 47)
+ abort ();
+ #pragma omp atomic capture seq_cst
+ { v = x; x = l ? 17 : 12; }
+ if (v != 47)
+ abort ();
+ #pragma omp atomic capture seq_cst
+ { v = x; x = l = s++ + 3; }
+ if (v != 17 || l != 4 || s != 2)
+ abort ();
+ #pragma omp atomic read seq_cst
+ v = x;
+ if (v != 4)
+ abort ();
+}
+
+int x = 6;
+
+int
+main ()
+{
+ foo <int> ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/c++.exp b/libgomp/testsuite/libgomp.c++/c++.exp
index b3363062ae8..88e017e4e29 100644
--- a/libgomp/testsuite/libgomp.c++/c++.exp
+++ b/libgomp/testsuite/libgomp.c++/c++.exp
@@ -11,6 +11,9 @@ set lang_library_path "../libstdc++-v3/src/.libs"
# Initialize dg.
dg-init
+# Turn on OpenMP.
+lappend ALWAYS_CFLAGS "additional_flags=-fopenmp"
+
set blddir [lookfor_file [get_multilibs] libgomp]
diff --git a/libgomp/testsuite/libgomp.c++/cancel-for-1.C b/libgomp/testsuite/libgomp.c++/cancel-for-1.C
new file mode 100644
index 00000000000..8183a2d06a1
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/cancel-for-1.C
@@ -0,0 +1,29 @@
+// { dg-do run }
+// { dg-set-target-env-var OMP_CANCELLATION "true" }
+
+#include <omp.h>
+#include "cancel-test.h"
+
+int
+main ()
+{
+ {
+ S c;
+ #pragma omp parallel num_threads (32)
+ {
+ S a, b;
+ int i;
+ #pragma omp for private (b) firstprivate (c)
+ for (i = 0; i < 1000; ++i)
+ {
+ S d;
+ #pragma omp cancel for
+ if (omp_get_cancellation ())
+ abort ();
+ b.bump ();
+ c.bump ();
+ }
+ }
+ }
+ S::verify ();
+}
diff --git a/libgomp/testsuite/libgomp.c++/cancel-for-2.C b/libgomp/testsuite/libgomp.c++/cancel-for-2.C
new file mode 100644
index 00000000000..1595a239cd0
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/cancel-for-2.C
@@ -0,0 +1,126 @@
+// { dg-do run }
+// { dg-set-target-env-var OMP_CANCELLATION "true" }
+
+#include <omp.h>
+#include "cancel-test.h"
+
+__attribute__((noinline, noclone)) int
+foo (int *x)
+{
+ S a, b, c, d, e;
+ int v = 0, w = 0;
+ #pragma omp parallel num_threads (32) shared (v, w) private (c, d) firstprivate (e)
+ {
+ S g;
+ int i;
+ c.bump ();
+ e.bump ();
+ #pragma omp for private (d, g) firstprivate (b)
+ for (i = 0; i < 1000; ++i)
+ {
+ b.bump ();
+ d.bump ();
+ g.bump ();
+ #pragma omp cancel for if (x[0])
+ abort ();
+ }
+ #pragma omp for private (d, g) firstprivate (b)
+ for (i = 0; i < 1000; ++i)
+ {
+ b.bump ();
+ d.bump ();
+ g.bump ();
+ #pragma omp cancel for if (x[1])
+ #pragma omp atomic
+ v++;
+ }
+ #pragma omp for private (d, g) firstprivate (b)
+ for (i = 0; i < 1000; ++i)
+ {
+ b.bump ();
+ d.bump ();
+ g.bump ();
+ #pragma omp cancel for if (x[2])
+ #pragma omp atomic
+ w += 8;
+ }
+ #pragma omp for private (d, g) firstprivate (b)
+ for (i = 0; i < 1000; ++i)
+ {
+ b.bump ();
+ d.bump ();
+ g.bump ();
+ #pragma omp cancel for if (x[3])
+ #pragma omp atomic
+ v += 2;
+ }
+ }
+ if (v != 3000 || w != 0)
+ abort ();
+ #pragma omp parallel num_threads (32) shared (v, w) private (c, d) firstprivate (e)
+ {
+ S g, h;
+ int i;
+ c.bump ();
+ e.bump ();
+ /* None of these cancel directives should actually cancel anything,
+ but the compiler shouldn't know that and thus should use cancellable
+ barriers at the end of all the workshares. */
+ #pragma omp cancel parallel if (omp_get_thread_num () == 1 && x[4])
+ #pragma omp for private (d, g) firstprivate (b)
+ for (i = 0; i < 1000; ++i)
+ {
+ b.bump ();
+ d.bump ();
+ g.bump ();
+ #pragma omp cancel for if (x[0])
+ abort ();
+ }
+ #pragma omp cancel parallel if (omp_get_thread_num () == 2 && x[4])
+ #pragma omp for private (d, g) firstprivate (b)
+ for (i = 0; i < 1000; ++i)
+ {
+ b.bump ();
+ d.bump ();
+ g.bump ();
+ #pragma omp cancel for if (x[1])
+ #pragma omp atomic
+ v++;
+ }
+ #pragma omp cancel parallel if (omp_get_thread_num () == 3 && x[4])
+ #pragma omp for private (d, g) firstprivate (b)
+ for (i = 0; i < 1000; ++i)
+ {
+ b.bump ();
+ d.bump ();
+ g.bump ();
+ #pragma omp cancel for if (x[2])
+ #pragma omp atomic
+ w += 8;
+ }
+ #pragma omp cancel parallel if (omp_get_thread_num () == 4 && x[4])
+ #pragma omp for private (d, g) firstprivate (b)
+ for (i = 0; i < 1000; ++i)
+ {
+ b.bump ();
+ d.bump ();
+ g.bump ();
+ #pragma omp cancel for if (x[3])
+ #pragma omp atomic
+ v += 2;
+ }
+ #pragma omp cancel parallel if (omp_get_thread_num () == 5 && x[4])
+ }
+ if (v != 6000 || w != 0)
+ abort ();
+ return 0;
+}
+
+int
+main ()
+{
+ int x[] = { 1, 0, 1, 0, 0 };
+ if (omp_get_cancellation ())
+ foo (x);
+ S::verify ();
+}
diff --git a/libgomp/testsuite/libgomp.c++/cancel-parallel-1.C b/libgomp/testsuite/libgomp.c++/cancel-parallel-1.C
new file mode 100644
index 00000000000..033d676b3b2
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/cancel-parallel-1.C
@@ -0,0 +1,18 @@
+// { dg-do run }
+// { dg-set-target-env-var OMP_CANCELLATION "true" }
+
+#include <omp.h>
+#include "cancel-test.h"
+
+int
+main ()
+{
+ #pragma omp parallel num_threads (32)
+ {
+ S a;
+ #pragma omp cancel parallel
+ if (omp_get_cancellation ())
+ abort ();
+ }
+ S::verify ();
+}
diff --git a/libgomp/testsuite/libgomp.c++/cancel-parallel-2.C b/libgomp/testsuite/libgomp.c++/cancel-parallel-2.C
new file mode 100644
index 00000000000..340423b5586
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/cancel-parallel-2.C
@@ -0,0 +1,57 @@
+// { dg-do run }
+// { dg-set-target-env-var OMP_CANCELLATION "true" }
+
+#include <unistd.h>
+#include <omp.h>
+#include "cancel-test.h"
+
+static void
+foo (int *x)
+{
+ S a, b, c;
+ #pragma omp parallel firstprivate(x, c) num_threads (32) private (b)
+ {
+ S d;
+ b.bump ();
+ c.bump ();
+ int thr = omp_get_thread_num ();
+ switch (x[thr])
+ {
+ case 4:
+ #pragma omp cancel parallel
+ break;
+ case 3:
+ #pragma omp task
+ usleep (1000);
+ #pragma omp task
+ usleep (2000);
+ #pragma omp task
+ usleep (4000);
+ break;
+ case 2:
+ usleep (1000);
+ /* FALLTHRU */
+ case 1:
+ #pragma omp cancellation point parallel
+ break;
+ }
+ #pragma omp barrier
+ if (omp_get_cancellation ())
+ abort ();
+ }
+}
+
+int
+main ()
+{
+ int i, j, x[32] = { 0, 1, 2, 4, 2, 2, 1, 0 };
+ foo (x);
+ for (i = 0; i < 32; i++)
+ {
+ for (j = 0; j < 32; j++)
+ x[j] = rand () & 3;
+ x[rand () & 31] = 4;
+ foo (x);
+ }
+ S::verify ();
+}
diff --git a/libgomp/testsuite/libgomp.c++/cancel-parallel-3.C b/libgomp/testsuite/libgomp.c++/cancel-parallel-3.C
new file mode 100644
index 00000000000..9db7a4f7b3e
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/cancel-parallel-3.C
@@ -0,0 +1,50 @@
+// { dg-do run }
+// { dg-set-target-env-var OMP_CANCELLATION "true" }
+
+#include <omp.h>
+#include <unistd.h>
+#include "cancel-test.h"
+
+static inline void
+do_some_work (void)
+{
+ asm volatile ("" : : : "memory");
+}
+
+void
+foo ()
+{
+ S a, b, c;
+ omp_set_dynamic (0);
+ omp_set_schedule (omp_sched_static, 1);
+ #pragma omp parallel num_threads (16) private (b) firstprivate (c)
+ {
+ S d;
+ int i, j;
+ b.bump ();
+ c.bump ();
+ do_some_work ();
+ #pragma omp barrier
+ if (omp_get_thread_num () == 1)
+ {
+ sleep (2);
+ #pragma omp cancellation point parallel
+ }
+ for (j = 3; j <= 16; j++)
+ #pragma omp for schedule (runtime) nowait
+ for (i = 0; i < j; i++)
+ do_some_work ();
+ if (omp_get_thread_num () == 0)
+ {
+ sleep (1);
+ #pragma omp cancel parallel
+ }
+ }
+}
+
+int
+main ()
+{
+ foo ();
+ S::verify ();
+}
diff --git a/libgomp/testsuite/libgomp.c++/cancel-sections-1.C b/libgomp/testsuite/libgomp.c++/cancel-sections-1.C
new file mode 100644
index 00000000000..81a9c352018
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/cancel-sections-1.C
@@ -0,0 +1,43 @@
+// { dg-do run }
+// { dg-set-target-env-var OMP_CANCELLATION "true" }
+
+#include <omp.h>
+#include "cancel-test.h"
+
+int
+main ()
+{
+ if (!omp_get_cancellation ())
+ return 0;
+ #pragma omp parallel num_threads (32)
+ {
+ S a;
+ #pragma omp sections
+ {
+ {
+ S b;
+ #pragma omp cancel sections
+ abort ();
+ }
+ #pragma omp section
+ {
+ S c;
+ #pragma omp cancel sections
+ abort ();
+ }
+ #pragma omp section
+ {
+ S d;
+ #pragma omp cancel sections
+ abort ();
+ }
+ #pragma omp section
+ {
+ S e;
+ #pragma omp cancel sections
+ abort ();
+ }
+ }
+ }
+ S::verify ();
+}
diff --git a/libgomp/testsuite/libgomp.c++/cancel-taskgroup-1.C b/libgomp/testsuite/libgomp.c++/cancel-taskgroup-1.C
new file mode 100644
index 00000000000..4f66859d171
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/cancel-taskgroup-1.C
@@ -0,0 +1,4 @@
+// { dg-do run }
+// { dg-set-target-env-var OMP_CANCELLATION "true" }
+
+#include "../libgomp.c/cancel-taskgroup-1.c"
diff --git a/libgomp/testsuite/libgomp.c++/cancel-taskgroup-2.C b/libgomp/testsuite/libgomp.c++/cancel-taskgroup-2.C
new file mode 100644
index 00000000000..d4a02e91140
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/cancel-taskgroup-2.C
@@ -0,0 +1,4 @@
+// { dg-do run }
+// { dg-set-target-env-var OMP_CANCELLATION "true" }
+
+#include "../libgomp.c/cancel-taskgroup-2.c"
diff --git a/libgomp/testsuite/libgomp.c++/cancel-taskgroup-3.C b/libgomp/testsuite/libgomp.c++/cancel-taskgroup-3.C
new file mode 100644
index 00000000000..c897265ef8b
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/cancel-taskgroup-3.C
@@ -0,0 +1,58 @@
+// { dg-do run }
+// { dg-set-target-env-var OMP_CANCELLATION "true" }
+
+#include <unistd.h>
+#include <omp.h>
+#include "cancel-test.h"
+
+void
+foo ()
+{
+ S a, b, c, d, e, f;
+ #pragma omp parallel private (c, d) firstprivate (e, f)
+ #pragma omp taskgroup
+ {
+ c.bump ();
+ e.bump ();
+ #pragma omp task firstprivate (b, f) private (d)
+ {
+ S h;
+ b.bump ();
+ d.bump ();
+ f.bump ();
+ #pragma omp cancel taskgroup
+ if (omp_get_cancellation ())
+ abort ();
+ }
+ }
+ #pragma omp parallel private (c, d) firstprivate (e, f)
+ {
+ #pragma omp barrier
+ #pragma omp single
+ #pragma omp taskgroup
+ {
+ int i;
+ c.bump ();
+ e.bump ();
+ for (i = 0; i < 50; i++)
+ #pragma omp task firstprivate (b, f) private (d)
+ {
+ S h;
+ b.bump ();
+ d.bump ();
+ f.bump ();
+ #pragma omp cancellation point taskgroup
+ usleep (30);
+ #pragma omp cancel taskgroup if (i > 5)
+ }
+ }
+ usleep (10);
+ }
+}
+
+int
+main ()
+{
+ foo ();
+ S::verify ();
+}
diff --git a/libgomp/testsuite/libgomp.c++/cancel-test.h b/libgomp/testsuite/libgomp.c++/cancel-test.h
new file mode 100644
index 00000000000..776d6ee6321
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/cancel-test.h
@@ -0,0 +1,47 @@
+#include <stdlib.h>
+#include <omp.h>
+
+struct S
+{
+ static int s;
+ int v;
+ S ()
+ {
+ #pragma omp atomic
+ s++;
+ }
+
+ S (int x)
+ {
+ #pragma omp atomic
+ s++;
+ v = x;
+ }
+
+ ~S ()
+ {
+ #pragma omp atomic
+ s--;
+ }
+
+ S (const S &x)
+ {
+ #pragma omp atomic
+ s++;
+ v = x.v;
+ }
+
+ static void
+ verify ()
+ {
+ if (s) abort ();
+ }
+
+ void
+ bump ()
+ {
+ v++;
+ }
+};
+
+int S::s = 0;
diff --git a/libgomp/testsuite/libgomp.c++/for-10.C b/libgomp/testsuite/libgomp.c++/for-10.C
new file mode 100644
index 00000000000..fb1a3e952b1
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/for-10.C
@@ -0,0 +1,44 @@
+extern "C" void abort ();
+
+#define M(x, y, z) O(x, y, z)
+#define O(x, y, z) x ## _ ## y ## _ ## z
+
+#define F simd
+#define G simd
+#define S
+#define N(x) M(x, G, normal)
+#include "../libgomp.c/for-2.h"
+#undef S
+#undef N
+#undef F
+#undef G
+
+#define F parallel for simd
+#define G pf_simd
+#include "../libgomp.c/for-1.h"
+#undef F
+#undef G
+
+#define F for simd
+#define G f_simd
+#include "../libgomp.c/for-1.h"
+#undef F
+#undef G
+
+int
+main ()
+{
+ if (test_simd_normal ()
+ || test_pf_simd_static ()
+ || test_pf_simd_static32 ()
+ || test_pf_simd_auto ()
+ || test_pf_simd_guided32 ()
+ || test_pf_simd_runtime ()
+ || test_f_simd_static ()
+ || test_f_simd_static32 ()
+ || test_f_simd_auto ()
+ || test_f_simd_guided32 ()
+ || test_f_simd_runtime ())
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/for-11.C b/libgomp/testsuite/libgomp.c++/for-11.C
new file mode 100644
index 00000000000..0244e4de112
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/for-11.C
@@ -0,0 +1,108 @@
+extern "C" void abort ();
+
+#define M(x, y, z) O(x, y, z)
+#define O(x, y, z) x ## _ ## y ## _ ## z
+
+#pragma omp declare target
+
+#define F distribute
+#define G d
+#define S
+#define N(x) M(x, G, normal)
+#include "../libgomp.c/for-2.h"
+#undef S
+#undef N
+#undef F
+#undef G
+
+#define F distribute
+#define G d_ds128
+#define S dist_schedule(static, 128)
+#define N(x) M(x, G, normal)
+#include "../libgomp.c/for-2.h"
+#undef S
+#undef N
+#undef F
+#undef G
+
+#define F distribute simd
+#define G ds
+#define S
+#define N(x) M(x, G, normal)
+#include "../libgomp.c/for-2.h"
+#undef S
+#undef N
+#undef F
+#undef G
+
+#define F distribute simd
+#define G ds_ds128
+#define S dist_schedule(static, 128)
+#define N(x) M(x, G, normal)
+#include "../libgomp.c/for-2.h"
+#undef S
+#undef N
+#undef F
+#undef G
+
+#define F distribute parallel for
+#define G dpf
+#include "../libgomp.c/for-1.h"
+#undef F
+#undef G
+
+#define F distribute parallel for dist_schedule(static, 128)
+#define G dpf_ds128
+#include "../libgomp.c/for-1.h"
+#undef F
+#undef G
+
+#define F distribute parallel for simd
+#define G dpfs
+#include "../libgomp.c/for-1.h"
+#undef F
+#undef G
+
+#define F distribute parallel for simd dist_schedule(static, 128)
+#define G dpfs_ds128
+#include "../libgomp.c/for-1.h"
+#undef F
+#undef G
+
+#pragma omp end declare target
+
+int
+main ()
+{
+ int err = 0;
+ #pragma omp target teams reduction(|:err)
+ {
+ err |= test_d_normal ();
+ err |= test_d_ds128_normal ();
+ err |= test_ds_normal ();
+ err |= test_ds_ds128_normal ();
+ err |= test_dpf_static ();
+ err |= test_dpf_static32 ();
+ err |= test_dpf_auto ();
+ err |= test_dpf_guided32 ();
+ err |= test_dpf_runtime ();
+ err |= test_dpf_ds128_static ();
+ err |= test_dpf_ds128_static32 ();
+ err |= test_dpf_ds128_auto ();
+ err |= test_dpf_ds128_guided32 ();
+ err |= test_dpf_ds128_runtime ();
+ err |= test_dpfs_static ();
+ err |= test_dpfs_static32 ();
+ err |= test_dpfs_auto ();
+ err |= test_dpfs_guided32 ();
+ err |= test_dpfs_runtime ();
+ err |= test_dpfs_ds128_static ();
+ err |= test_dpfs_ds128_static32 ();
+ err |= test_dpfs_ds128_auto ();
+ err |= test_dpfs_ds128_guided32 ();
+ err |= test_dpfs_ds128_runtime ();
+ }
+ if (err)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/for-9.C b/libgomp/testsuite/libgomp.c++/for-9.C
new file mode 100644
index 00000000000..86b9d9318cb
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/for-9.C
@@ -0,0 +1,33 @@
+extern "C" void abort ();
+
+#define M(x, y, z) O(x, y, z)
+#define O(x, y, z) x ## _ ## y ## _ ## z
+
+#define F parallel for
+#define G pf
+#include "../libgomp.c/for-1.h"
+#undef F
+#undef G
+
+#define F for
+#define G f
+#include "../libgomp.c/for-1.h"
+#undef F
+#undef G
+
+int
+main ()
+{
+ if (test_pf_static ()
+ || test_pf_static32 ()
+ || test_pf_auto ()
+ || test_pf_guided32 ()
+ || test_pf_runtime ()
+ || test_f_static ()
+ || test_f_static32 ()
+ || test_f_auto ()
+ || test_f_guided32 ()
+ || test_f_runtime ())
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/simd-1.C b/libgomp/testsuite/libgomp.c++/simd-1.C
new file mode 100644
index 00000000000..16ef159b827
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/simd-1.C
@@ -0,0 +1,79 @@
+// { dg-do run }
+// { dg-options "-O2" }
+// { dg-additional-options "-msse2" { target sse2_runtime } }
+// { dg-additional-options "-mavx" { target avx_runtime } }
+
+extern "C" void abort ();
+int a[1024] __attribute__((aligned (32))) = { 1 };
+int b[1024] __attribute__((aligned (32))) = { 1 };
+int k, m;
+struct U { U (); ~U (); int u; };
+struct V
+{
+ V () : v (8) {}
+ ~V ()
+ {
+ if (v > 38 + 4 + 3 * 1024 + 1)
+ abort ();
+ }
+ V &operator= (const V &x) { v = x.v + 1; return *this; }
+ int v;
+};
+
+__attribute__((noinline, noclone))
+U::U () : u (6)
+{
+}
+
+__attribute__((noinline, noclone))
+U::~U ()
+{
+ if (u > 38 + 4 + 3 * 1023)
+ abort ();
+}
+
+__attribute__((noinline, noclone)) int
+foo (int *p)
+{
+ int i, s = 0;
+ U u;
+ V v;
+ #pragma omp simd aligned(a, p : 32) linear(k: m + 1) \
+ reduction(+:s) lastprivate(u, v)
+ for (i = 0; i < 1024; i++)
+ {
+ a[i] *= p[i];
+ u.u = p[i] + k;
+ k += m + 1;
+ v.v = p[i] + k;
+ s += p[i] + k;
+ }
+ if (u.u != 36 + 4 + 3 * 1023 || v.v != 36 + 4 + 3 * 1024 + 1)
+ abort ();
+ return s;
+}
+
+int
+main ()
+{
+#if __SIZEOF_INT__ >= 4
+ int i;
+ k = 4;
+ m = 2;
+ for (i = 0; i < 1024; i++)
+ {
+ a[i] = i - 512;
+ b[i] = (i - 51) % 39;
+ }
+ int s = foo (b);
+ for (i = 0; i < 1024; i++)
+ {
+ if (b[i] != (i - 51) % 39
+ || a[i] != (i - 512) * b[i])
+ abort ();
+ }
+ if (k != 4 + 3 * 1024 || s != 1596127)
+ abort ();
+#endif
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/simd-2.C b/libgomp/testsuite/libgomp.c++/simd-2.C
new file mode 100644
index 00000000000..6b12415bdce
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/simd-2.C
@@ -0,0 +1,36 @@
+// { dg-do run }
+// { dg-options "-O2" }
+// { dg-additional-options "-msse2" { target sse2_runtime } }
+// { dg-additional-options "-mavx" { target avx_runtime } }
+
+extern "C" void abort ();
+__UINTPTR_TYPE__ arr[1027];
+
+__attribute__((noinline, noclone)) void
+foo ()
+{
+ int i, v;
+ #pragma omp simd private (v) safelen(16)
+ for (i = 0; i < 1027; i++)
+ arr[i] = (__UINTPTR_TYPE__) &v;
+}
+
+int
+main ()
+{
+ int i, j, cnt = 0;
+ __UINTPTR_TYPE__ arr2[16];
+ foo ();
+ for (i = 0; i < 1027; i++)
+ {
+ for (j = 0; j < cnt; j++)
+ if (arr[i] == arr2[j])
+ break;
+ if (j != cnt)
+ continue;
+ if (cnt == 16)
+ abort ();
+ arr2[cnt++] = arr[i];
+ }
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/simd-3.C b/libgomp/testsuite/libgomp.c++/simd-3.C
new file mode 100644
index 00000000000..1c6d8e01af9
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/simd-3.C
@@ -0,0 +1,131 @@
+// { dg-do run }
+// { dg-options "-O2" }
+// { dg-additional-options "-msse2" { target sse2_runtime } }
+// { dg-additional-options "-mavx" { target avx_runtime } }
+
+extern "C" void abort ();
+int a[1024] __attribute__((aligned (32))) = { 1 };
+int b[1024] __attribute__((aligned (32))) = { 1 };
+unsigned char c[1024] __attribute__((aligned (32))) = { 1 };
+int k, m;
+__UINTPTR_TYPE__ u, u2, u3;
+
+__attribute__((noinline, noclone)) int
+foo (int *p)
+{
+ int i, s = 0, s2 = 0, t, t2;
+ #pragma omp simd aligned(a, b, p : 32) linear(k: m + 1) reduction(+:s) \
+ lastprivate (t2)
+ for (i = 0; i < 512; i++)
+ {
+ a[i] *= p[i];
+ t2 = k + p[i];
+ k += m + 1;
+ s += p[i] + k;
+ c[i]++;
+ }
+ #pragma omp simd aligned(a, b, p : 32) linear(k: m + 1) reduction(+:s2) \
+ lastprivate (t, u, u2, u3)
+ for (i = 512; i < 1024; i++)
+ {
+ a[i] *= p[i];
+ k += m + 1;
+ t = k + p[i];
+ u = (__UINTPTR_TYPE__) &k;
+ u2 = (__UINTPTR_TYPE__) &s2;
+ u3 = (__UINTPTR_TYPE__) &t;
+ s2 += t;
+ c[i]++;
+ }
+ return s + s2 + t + t2;
+}
+
+__attribute__((noinline, noclone)) long int
+bar (int *p, long int n, long int o)
+{
+ long int i, s = 0, s2 = 0, t, t2;
+ #pragma omp simd aligned(a, b, p : 32) linear(k: m + 1) reduction(+:s) \
+ lastprivate (t2)
+ for (i = 0; i < n; i++)
+ {
+ a[i] *= p[i];
+ t2 = k + p[i];
+ k += m + 1;
+ s += p[i] + k;
+ c[i]++;
+ }
+ #pragma omp simd aligned(a, b, p : 32) linear(k: m + 1) reduction(+:s2) \
+ lastprivate (t, u, u2, u3)
+ for (i = n; i < o; i++)
+ {
+ a[i] *= p[i];
+ k += m + 1;
+ t = k + p[i];
+ u = (__UINTPTR_TYPE__) &k;
+ u2 = (__UINTPTR_TYPE__) &s2;
+ u3 = (__UINTPTR_TYPE__) &t;
+ s2 += t;
+ c[i]++;
+ }
+ return s + s2 + t + t2;
+}
+
+int
+main ()
+{
+#if __SIZEOF_INT__ >= 4
+ int i;
+ k = 4;
+ m = 2;
+ for (i = 0; i < 1024; i++)
+ {
+ a[i] = i - 512;
+ b[i] = (i - 51) % 39;
+ c[i] = (unsigned char) i;
+ }
+ int s = foo (b);
+ for (i = 0; i < 1024; i++)
+ {
+ if (b[i] != (i - 51) % 39
+ || a[i] != (i - 512) * b[i]
+ || c[i] != (unsigned char) (i + 1))
+ abort ();
+ a[i] = i - 512;
+ }
+ if (k != 4 + 3 * 1024
+ || s != 1596127 + (4 + 3 * 511 + b[511]) + (4 + 3 * 1024 + b[1023]))
+ abort ();
+ k = 4;
+ s = bar (b, 512, 1024);
+ for (i = 0; i < 1024; i++)
+ {
+ if (b[i] != (i - 51) % 39
+ || a[i] != (i - 512) * b[i]
+ || c[i] != (unsigned char) (i + 2))
+ abort ();
+ a[i] = i - 512;
+ }
+ if (k != 4 + 3 * 1024
+ || s != 1596127 + (4 + 3 * 511 + b[511]) + (4 + 3 * 1024 + b[1023]))
+ abort ();
+ k = 4;
+ s = bar (b, 511, 1021);
+ for (i = 0; i < 1021; i++)
+ {
+ if (b[i] != (i - 51) % 39
+ || a[i] != (i - 512) * b[i]
+ || c[i] != (unsigned char) (i + 3))
+ abort ();
+ a[i] = i - 512;
+ }
+ for (i = 1021; i < 1024; i++)
+ if (b[i] != (i - 51) % 39
+ || a[i] != i - 512
+ || c[i] != (unsigned char) (i + 2))
+ abort ();
+ if (k != 4 + 3 * 1021
+ || s != 1586803 + (4 + 3 * 510 + b[510]) + (4 + 3 * 1021 + b[1020]))
+ abort ();
+#endif
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/simd-4.C b/libgomp/testsuite/libgomp.c++/simd-4.C
new file mode 100644
index 00000000000..bdfacc65264
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/simd-4.C
@@ -0,0 +1,45 @@
+// { dg-do run }
+// { dg-options "-O2" }
+// { dg-additional-options "-msse2" { target sse2_runtime } }
+// { dg-additional-options "-mavx" { target avx_runtime } }
+
+extern "C" void abort ();
+int a[1024] __attribute__((aligned (32))) = { 1 };
+struct S
+{
+ int s;
+ S () : s (0) {}
+ ~S () {}
+};
+#pragma omp declare reduction (+:S:omp_out.s += omp_in.s)
+#pragma omp declare reduction (foo:S:omp_out.s += omp_in.s)
+#pragma omp declare reduction (foo:int:omp_out += omp_in)
+
+__attribute__((noinline, noclone)) int
+foo ()
+{
+ int i, u = 0;
+ S s, t;
+ #pragma omp simd aligned(a : 32) reduction(+:s) reduction(foo:t, u)
+ for (i = 0; i < 1024; i++)
+ {
+ int x = a[i];
+ s.s += x;
+ t.s += x;
+ u += x;
+ }
+ if (t.s != s.s || u != s.s)
+ abort ();
+ return s.s;
+}
+
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 1024; i++)
+ a[i] = (i & 31) + (i / 128);
+ int s = foo ();
+ if (s != 19456)
+ abort ();
+}
diff --git a/libgomp/testsuite/libgomp.c++/simd-5.C b/libgomp/testsuite/libgomp.c++/simd-5.C
new file mode 100644
index 00000000000..6c4627e210a
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/simd-5.C
@@ -0,0 +1,47 @@
+// { dg-do run }
+// { dg-options "-O2" }
+// { dg-additional-options "-msse2" { target sse2_runtime } }
+// { dg-additional-options "-mavx" { target avx_runtime } }
+
+extern "C" void abort ();
+int a[1024] __attribute__((aligned (32))) = { 1 };
+struct S
+{
+ int s;
+ S () : s (0) {}
+ ~S () {}
+};
+#pragma omp declare reduction (+:S:omp_out.s += omp_in.s)
+#pragma omp declare reduction (foo:S:omp_out.s += omp_in.s)
+#pragma omp declare reduction (foo:int:omp_out += omp_in)
+
+__attribute__((noinline, noclone)) int
+foo ()
+{
+ int i, u = 0, q = 0;
+ S s, t;
+ #pragma omp simd aligned(a : 32) reduction(+:s, q) reduction(foo:t, u) \
+ safelen(1)
+ for (i = 0; i < 1024; i++)
+ {
+ int x = a[i];
+ s.s += x;
+ t.s += x;
+ u += x;
+ q++;
+ }
+ if (t.s != s.s || u != s.s || q != 1024)
+ abort ();
+ return s.s;
+}
+
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 1024; i++)
+ a[i] = (i & 31) + (i / 128);
+ int s = foo ();
+ if (s != 19456)
+ abort ();
+}
diff --git a/libgomp/testsuite/libgomp.c++/simd-6.C b/libgomp/testsuite/libgomp.c++/simd-6.C
new file mode 100644
index 00000000000..cfc13d0a0f9
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/simd-6.C
@@ -0,0 +1,70 @@
+// { dg-do run }
+// { dg-options "-O2" }
+// { dg-additional-options "-msse2" { target sse2_runtime } }
+// { dg-additional-options "-mavx" { target avx_runtime } }
+
+extern "C" void abort ();
+int a[1024] __attribute__((aligned (32))) = { 1 };
+struct S
+{
+ int s;
+ S () : s (0) {}
+ S (int x) : s (x) {}
+ ~S () {}
+};
+#pragma omp declare reduction (+:S:omp_out.s += omp_in.s) \
+ initializer (omp_priv (0))
+#pragma omp declare reduction (foo:S:omp_out.s += omp_in.s) \
+ initializer (omp_priv (0))
+#pragma omp declare reduction (foo:int:omp_out += omp_in) \
+ initializer (omp_priv = 0)
+
+__attribute__((noinline, noclone)) S
+foo (S s)
+{
+ int i, v = 0, &u = v;
+ S t;
+ #pragma omp simd aligned(a : 32) reduction(+:s) reduction(foo:t, u)
+ for (i = 0; i < 1024; i++)
+ {
+ int x = a[i];
+ s.s += x;
+ t.s += x;
+ u += x;
+ }
+ if (t.s != s.s || u != s.s)
+ abort ();
+ return t;
+}
+
+__attribute__((noinline, noclone)) int
+bar (S &s, S &t)
+{
+ int i, v = 0, &u = v;
+ #pragma omp simd aligned(a : 32) reduction(+:s) reduction(foo:t, u)
+ for (i = 0; i < 1024; i++)
+ {
+ int x = a[i];
+ s.s += x;
+ t.s += x;
+ u += x;
+ }
+ if (t.s != s.s || u != s.s)
+ abort ();
+ return s.s;
+}
+
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 1024; i++)
+ a[i] = (i & 31) + (i / 128);
+ S q;
+ int s = foo (q).s;
+ if (s != 19456)
+ abort ();
+ S r, v;
+ if (bar (r, v) != s)
+ abort ();
+}
diff --git a/libgomp/testsuite/libgomp.c++/simd-7.C b/libgomp/testsuite/libgomp.c++/simd-7.C
new file mode 100644
index 00000000000..5a6f4cef7c1
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/simd-7.C
@@ -0,0 +1,72 @@
+// { dg-do run }
+// { dg-options "-O2" }
+// { dg-additional-options "-msse2" { target sse2_runtime } }
+// { dg-additional-options "-mavx" { target avx_runtime } }
+
+extern "C" void abort ();
+int a[1024] __attribute__((aligned (32))) = { 1 };
+struct S
+{
+ int s;
+ S () : s (0) {}
+ S (int x) : s (x) {}
+ ~S () {}
+};
+#pragma omp declare reduction (+:S:omp_out.s += omp_in.s) \
+ initializer (omp_priv (0))
+#pragma omp declare reduction (foo:S:omp_out.s += omp_in.s) \
+ initializer (omp_priv (0))
+#pragma omp declare reduction (foo:int:omp_out += omp_in) \
+ initializer (omp_priv = 0)
+
+__attribute__((noinline, noclone)) S
+foo (S s)
+{
+ int i, v = 0, &u = v;
+ S t;
+ #pragma omp simd aligned(a : 32) reduction(+:s) reduction(foo:t, u) \
+ safelen(1)
+ for (i = 0; i < 1024; i++)
+ {
+ int x = a[i];
+ s.s += x;
+ t.s += x;
+ u += x;
+ }
+ if (t.s != s.s || u != s.s)
+ abort ();
+ return t;
+}
+
+__attribute__((noinline, noclone)) int
+bar (S &s, S &t)
+{
+ int i, v = 0, &u = v;
+ #pragma omp simd aligned(a : 32) reduction(+:s) reduction(foo:t, u) \
+ safelen(1)
+ for (i = 0; i < 1024; i++)
+ {
+ int x = a[i];
+ s.s += x;
+ t.s += x;
+ u += x;
+ }
+ if (t.s != s.s || u != s.s)
+ abort ();
+ return s.s;
+}
+
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 1024; i++)
+ a[i] = (i & 31) + (i / 128);
+ S q;
+ int s = foo (q).s;
+ if (s != 19456)
+ abort ();
+ S r, v;
+ if (bar (r, v) != s)
+ abort ();
+}
diff --git a/libgomp/testsuite/libgomp.c++/simd-8.C b/libgomp/testsuite/libgomp.c++/simd-8.C
new file mode 100644
index 00000000000..7c758328529
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/simd-8.C
@@ -0,0 +1,47 @@
+// PR libgomp/58482
+// { dg-do run }
+// { dg-options "-O2" }
+// { dg-additional-options "-msse2" { target sse2_runtime } }
+// { dg-additional-options "-mavx" { target avx_runtime } }
+
+extern "C" void abort ();
+int a[1024] __attribute__((aligned (32))) = { 1 };
+struct S
+{
+ int s;
+ S () : s (0) {}
+ ~S () {}
+};
+#pragma omp declare reduction (+:S:omp_out.s += omp_in.s)
+#pragma omp declare reduction (foo:S:omp_out.s += omp_in.s)
+#pragma omp declare reduction (foo:int:omp_out += omp_in)
+
+__attribute__((noinline, noclone)) int
+foo ()
+{
+ int i, u = 0;
+ S s, t;
+ #pragma omp parallel for simd aligned(a : 32) reduction(+:s) \
+ reduction(foo:t, u)
+ for (i = 0; i < 1024; i++)
+ {
+ int x = a[i];
+ s.s += x;
+ t.s += x;
+ u += x;
+ }
+ if (t.s != s.s || u != s.s)
+ abort ();
+ return s.s;
+}
+
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 1024; i++)
+ a[i] = (i & 31) + (i / 128);
+ int s = foo ();
+ if (s != 19456)
+ abort ();
+}
diff --git a/libgomp/testsuite/libgomp.c++/target-1.C b/libgomp/testsuite/libgomp.c++/target-1.C
new file mode 100644
index 00000000000..3cf01d9975d
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/target-1.C
@@ -0,0 +1 @@
+#include "../libgomp.c/target-1.c"
diff --git a/libgomp/testsuite/libgomp.c++/target-2-aux.cc b/libgomp/testsuite/libgomp.c++/target-2-aux.cc
new file mode 100644
index 00000000000..b405404e6dc
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/target-2-aux.cc
@@ -0,0 +1,5 @@
+double f[1024];
+double (&fr) [1024] = f;
+double gbuf[1024];
+double *g = gbuf;
+double *&gr = g;
diff --git a/libgomp/testsuite/libgomp.c++/target-2.C b/libgomp/testsuite/libgomp.c++/target-2.C
new file mode 100644
index 00000000000..83207cd51cd
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/target-2.C
@@ -0,0 +1,58 @@
+// { dg-options "-O2 -fopenmp" }
+// { dg-additional-sources "target-2-aux.cc" }
+
+extern "C" void abort (void);
+
+void
+fn1 (double *x, double *y, int z)
+{
+ int i;
+ for (i = 0; i < z; i++)
+ {
+ x[i] = i & 31;
+ y[i] = (i & 63) - 30;
+ }
+}
+
+double b[1024];
+double (&br) [1024] = b;
+double cbuf[1024];
+double *c = cbuf;
+double *&cr = c;
+extern double (&fr) [1024];
+extern double *&gr;
+
+double
+fn2 (int x, double (&dr) [1024], double *&er)
+{
+ double s = 0;
+ double h[1024];
+ double (&hr) [1024] = h;
+ double ibuf[1024];
+ double *i = ibuf;
+ double *&ir = i;
+ int j;
+ fn1 (hr + 2 * x, ir + 2 * x, x);
+ #pragma omp target map(to: br[:x], cr[0:x], dr[x:x], er[x:x]) \
+ map(to: fr[0:x], gr[0:x], hr[2 * x:x], ir[2 * x:x])
+ #pragma omp parallel for reduction(+:s)
+ for (j = 0; j < x; j++)
+ s += br[j] * cr[j] + dr[x + j] + er[x + j]
+ + fr[j] + gr[j] + hr[2 * x + j] + ir[2 * x + j];
+ return s;
+}
+
+int
+main ()
+{
+ double d[1024];
+ double ebuf[1024];
+ double *e = ebuf;
+ fn1 (br, cr, 128);
+ fn1 (d + 128, e + 128, 128);
+ fn1 (fr, gr, 128);
+ double h = fn2 (128, d, e);
+ if (h != 20416.0)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/target-3.C b/libgomp/testsuite/libgomp.c++/target-3.C
new file mode 100644
index 00000000000..2e4586feca0
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/target-3.C
@@ -0,0 +1 @@
+#include "../libgomp.c/target-2.c"
diff --git a/libgomp/testsuite/libgomp.c++/taskgroup-1.C b/libgomp/testsuite/libgomp.c++/taskgroup-1.C
new file mode 100644
index 00000000000..5129896613d
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/taskgroup-1.C
@@ -0,0 +1 @@
+#include "../libgomp.c/taskgroup-1.c"
diff --git a/libgomp/testsuite/libgomp.c++/udr-1.C b/libgomp/testsuite/libgomp.c++/udr-1.C
new file mode 100644
index 00000000000..c3ddd859ea4
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/udr-1.C
@@ -0,0 +1,82 @@
+// { dg-do run }
+
+extern "C" void abort ();
+
+struct S
+{
+ int s;
+ void foo (S &x) { s += x.s; }
+ void foo (S &x, bool y) { s += x.s; if (y) abort (); }
+ S (const S &x) { s = x.s + 1; }
+ S (const S &x, bool y) { s = x.s + 2; if (y) abort (); }
+ S () { s = 6; }
+ ~S ();
+};
+
+S::~S ()
+{
+ if (s < 6) abort ();
+ s = -1;
+ /* Ensure the above store is not DSEd. */
+ asm volatile ("" : : "r" (&s) : "memory");
+}
+
+void
+bar (S &x)
+{
+ if (x.s != 6) abort ();
+ x.s = 15;
+}
+
+#pragma omp declare reduction (foo: S: omp_out.foo (omp_in)) \
+ initializer (omp_priv (omp_orig, false))
+#pragma omp declare reduction (foo: char, int, short: omp_out += omp_in - 4) \
+ initializer (omp_priv (4))
+#pragma omp declare reduction (+: S: omp_out.foo (omp_in, false)) \
+ initializer (omp_priv (omp_orig))
+
+namespace N
+{
+ #pragma omp declare reduction (foo: S: omp_out.foo (omp_in)) \
+ initializer (::bar (omp_priv))
+ namespace M {}
+}
+
+int
+main ()
+{
+ S a, b, c, s, t, u;
+ if (a.s != 6 || b.s != 6 || c.s != 6
+ || s.s != 6 || t.s != 6 || u.s != 6) abort ();
+ s.s = 9; t.s = 10; u.s = 11;
+ int d = 0, e = 0, f = 0, g = 0, h = 30, v = 2, q = 0;
+ #pragma omp declare reduction (foo: S: omp_out.foo (omp_in, true)) \
+ initializer (omp_priv = omp_orig)
+ {
+ #pragma omp declare reduction (foo: S: omp_out.foo (omp_in, false)) \
+ initializer (omp_priv = omp_orig)
+ #pragma omp parallel num_threads (4) reduction (N::operator +: q) \
+ reduction (operator +: a, d) reduction (::operator +: b, e) \
+ reduction (+: c, f) reduction (::N::M::operator +: g) \
+ reduction (::N::min: h) reduction (foo: s) reduction (N::foo: t) \
+ reduction (::foo: u) reduction (::foo: v)
+ {
+ if (a.s != 7 || b.s != 7 || c.s != 7
+ || s.s != 10 || t.s != 15 || u.s != 13
+ || v != 4 || d || e || f || g || h != __INT_MAX__) abort ();
+ asm volatile ("" : "+m" (a.s), "+m" (b.s));
+ asm volatile ("" : "+m" (c.s), "+r" (d));
+ asm volatile ("" : "+r" (e), "+r" (f));
+ asm volatile ("" : "+r" (g), "+r" (h));
+ asm volatile ("" : "+m" (s.s), "+m" (t.s));
+ asm volatile ("" : "+m" (u.s), "+r" (v));
+ a.s++; b.s++; c.s++; d++; e++; f++; g++; h = t.s;
+ s.s++; t.s++; u.s++; v++; q++;
+ }
+ }
+ if (a.s != 6 + q * 8 || b.s != 6 + q * 8 || c.s != 6 + q * 8
+ || d != q || e != q || f != q || g != q || h != 15
+ || s.s != 9 + q * 11 || t.s != 10 + q * 16 || u.s != 11 + q * 14
+ || v != 2 + q)
+ abort ();
+}
diff --git a/libgomp/testsuite/libgomp.c++/udr-2.C b/libgomp/testsuite/libgomp.c++/udr-2.C
new file mode 100644
index 00000000000..5408be146bd
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/udr-2.C
@@ -0,0 +1,88 @@
+// { dg-do run }
+
+extern "C" void abort ();
+
+namespace NS
+{
+ struct U
+ {
+ void foo (U &, bool);
+ U ();
+ };
+ struct S
+ {
+ int s;
+ #pragma omp declare reduction (foo : U, S : omp_out.foo (omp_in, false))
+ #pragma omp declare reduction (foo : int : omp_out += omp_in) \
+ initializer (omp_priv = int ())
+ void baz (int v)
+ {
+ S s;
+ int q = 0;
+ if (s.s != 6 || v != 0) abort ();
+ s.s = 20;
+ #pragma omp parallel num_threads (4) reduction (foo : s, v) \
+ reduction (::NS::U::operator + : q)
+ {
+ if (s.s != 6 || q != 0 || v != 0) abort ();
+ asm volatile ("" : "+m" (s.s), "+r" (q), "+r" (v));
+ s.s++; q++; v++;
+ }
+ if (s.s != 20 + q * 7 || q != v) abort ();
+ }
+ void foo (S &x) { s += x.s; }
+ void foo (S &x, bool y) { s += x.s; if (y) abort (); }
+ S (const S &x) { s = x.s + 1; }
+ S (const S &x, bool y) { s = x.s + 2; if (y) abort (); }
+ S () { s = 6; }
+ S (int x) { s = x; }
+ ~S ();
+ };
+ #pragma omp declare reduction (bar : S : omp_out.foo (omp_in)) \
+ initializer (omp_priv (8))
+}
+
+NS::S::~S ()
+{
+ if (s < 6) abort ();
+ s = -1;
+ /* Ensure the above store is not DSEd. */
+ asm volatile ("" : : "r" (&s) : "memory");
+}
+
+struct T : public NS::S
+{
+ void baz ()
+ {
+ S s;
+ int q = 0;
+ if (s.s != 6) abort ();
+ #pragma omp parallel num_threads (4) reduction (foo:s) \
+ reduction (+: q)
+ {
+ if (s.s != 6 || q != 0) abort ();
+ asm volatile ("" : "+m" (s.s), "+r" (q));
+ s.s += 2; q++;
+ }
+ if (s.s != 6 + q * 8) abort ();
+ }
+};
+
+int
+main ()
+{
+ NS::S s;
+ s.baz (0);
+ T t;
+ t.baz ();
+ int q = 0;
+ if (s.s != 6) abort ();
+ // Test ADL
+ #pragma omp parallel num_threads (4) reduction (bar:s) reduction (+:q)
+ {
+ if (s.s != 8 || q != 0) abort ();
+ asm volatile ("" : "+m" (s.s), "+r" (q));
+ s.s += 4; q++;
+ }
+ if (s.s != 6 + q * 12) abort ();
+}
diff --git a/libgomp/testsuite/libgomp.c++/udr-3.C b/libgomp/testsuite/libgomp.c++/udr-3.C
new file mode 100644
index 00000000000..74a01389c7b
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/udr-3.C
@@ -0,0 +1,149 @@
+// { dg-do run }
+
+extern "C" void abort ();
+
+void
+dblinit (double *p)
+{
+ *p = 2.0;
+}
+
+namespace NS
+{
+ template <int N>
+ struct U
+ {
+ void foo (U &, bool);
+ U ();
+ };
+ template <int N>
+ struct S
+ {
+ int s;
+ #pragma omp declare reduction (foo : U<0>, S : omp_out.foo (omp_in, false))
+ #pragma omp declare reduction (foo : int : omp_out += omp_in) \
+ initializer (omp_priv = N + 2)
+ #pragma omp declare reduction (foo : double : omp_out += omp_in) \
+ initializer (dblinit (&omp_priv))
+ void baz (int v)
+ {
+ S s;
+ int q = 0;
+ if (s.s != 6 || v != 0) abort ();
+ s.s = 20;
+ double d = 4.0;
+ #pragma omp parallel num_threads (4) reduction (foo : s, v, d) \
+ reduction (::NS::U<N>::operator + : q)
+ {
+ if (s.s != 6 || q != 0 || v != N + 2 || d != 2.0) abort ();
+ asm volatile ("" : "+m" (s.s), "+r" (q), "+r" (v));
+ s.s++; q++; v++;
+ }
+ if (s.s != 20 + q * 7 || (N + 3) * q != v || d != 4.0 + 2.0 * q)
+ abort ();
+ }
+ void foo (S &x) { s += x.s; }
+ void foo (S &x, bool y) { s += x.s; if (y) abort (); }
+ S (const S &x) { s = x.s + 1; }
+ S (const S &x, bool y) { s = x.s + 2; if (y) abort (); }
+ S () { s = 6; }
+ S (int x) { s = x; }
+ ~S ();
+ };
+ #pragma omp declare reduction (bar : S<1> : omp_out.foo (omp_in)) \
+ initializer (omp_priv (8))
+}
+
+template <int N>
+NS::S<N>::~S ()
+{
+ if (s < 6) abort ();
+ s = -1;
+ /* Ensure the above store is not DSEd. */
+ asm volatile ("" : : "r" (&s) : "memory");
+}
+
+template <int N>
+struct T : public NS::S<N>
+{
+ void baz ()
+ {
+ NS::S<N> s;
+ int q = 0;
+ if (s.s != 6) abort ();
+ #pragma omp parallel num_threads (4) reduction (foo:s) \
+ reduction (+: q)
+ {
+ if (s.s != 6 || q != 0) abort ();
+ asm volatile ("" : "+m" (s.s), "+r" (q));
+ s.s += 2; q++;
+ }
+ if (s.s != 6 + q * 8) abort ();
+ }
+};
+
+struct W
+{
+ int v;
+ W () : v (6) {}
+ ~W () {}
+};
+
+template <typename T, typename D>
+struct V
+{
+ #pragma omp declare reduction (baz: T: omp_out.s += omp_in.s) \
+ initializer (omp_priv (11))
+ #pragma omp declare reduction (baz: D: omp_out += omp_in) \
+ initializer (dblinit (&omp_priv))
+ static void dblinit (D *x) { *x = 3.0; }
+ void baz ()
+ {
+ T t;
+ V v;
+ int q = 0;
+ D d = 4.0;
+ if (t.s != 6 || v.v != 4) abort ();
+ #pragma omp declare reduction (+ : V, W : omp_out.v -= omp_in.v) \
+ initializer (omp_priv (12))
+ {
+ #pragma omp declare reduction (+ : W, V : omp_out.v += omp_in.v) \
+ initializer (omp_priv (9))
+ #pragma omp parallel num_threads (4) reduction (+: v, q) \
+ reduction (baz: t, d)
+ {
+ if (t.s != 11 || v.v != 9 || q != 0 || d != 3.0) abort ();
+ asm volatile ("" : "+m" (t.s), "+m" (v.v), "+r" (q));
+ t.s += 2; v.v += 3; q++;
+ }
+ if (t.s != 6 + 13 * q || v.v != 4 + 12 * q || d != 4.0 + 3.0 * q)
+ abort ();
+ }
+ }
+ int v;
+ V () : v (4) {}
+ V (int x) : v (x) {}
+ ~V () {}
+};
+
+int
+main ()
+{
+ NS::S<0> u;
+ u.baz (0);
+ T<2> t;
+ t.baz ();
+ NS::S<1> s;
+ int q = 0;
+ if (s.s != 6) abort ();
+ // Test ADL
+ #pragma omp parallel num_threads (4) reduction (bar:s) reduction (+:q)
+ {
+ if (s.s != 8 || q != 0) abort ();
+ asm volatile ("" : "+m" (s.s), "+r" (q));
+ s.s += 4; q++;
+ }
+ if (s.s != 6 + q * 12) abort ();
+ V <NS::S <0>, double> v;
+ v.baz ();
+}
diff --git a/libgomp/testsuite/libgomp.c++/udr-4.C b/libgomp/testsuite/libgomp.c++/udr-4.C
new file mode 100644
index 00000000000..3e717467a0e
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/udr-4.C
@@ -0,0 +1,32 @@
+// { dg-do run }
+
+extern "C" void abort ();
+
+struct S
+{
+ int s;
+ S () : s (0) {}
+ ~S () {}
+};
+
+#pragma omp declare reduction (+:S:omp_out.s += omp_in.s)
+#pragma omp declare reduction (foo:S:omp_out.s += omp_in.s)
+#pragma omp declare reduction (foo:int:omp_out += omp_in)
+
+int
+main ()
+{
+ int i, u = 0, q = 0;
+ S s, t;
+ if (s.s != 0 || t.s != 0) abort ();
+ #pragma omp parallel reduction(+:s, q) reduction(foo:t, u)
+ {
+ if (s.s != 0 || t.s != 0 || u != 0 || q != 0) abort ();
+ s.s = 6;
+ t.s = 8;
+ u = 9;
+ q++;
+ }
+ if (s.s != 6 * q || t.s != 8 * q || u != 9 * q) abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/udr-5.C b/libgomp/testsuite/libgomp.c++/udr-5.C
new file mode 100644
index 00000000000..91ae2f697c3
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/udr-5.C
@@ -0,0 +1,49 @@
+// { dg-do run }
+
+extern "C" void abort ();
+
+struct S
+{
+ void foo ()
+ {
+ S s;
+ int j = 0;
+ #pragma omp declare reduction (bar : int : omp_out += omp_in)
+ #pragma omp parallel reduction (bar : s) reduction(S::operator+ : j)
+ s.a = 4, j = 1;
+ if (s.a != 4 * j) abort ();
+ }
+ #pragma omp declare reduction (bar : S : baz (omp_out, omp_in))
+ static void baz (S &x, S &y) { x.a += y.a; }
+ S () : a (0) {}
+ int a;
+};
+
+template <int N>
+struct T
+{
+ void foo ()
+ {
+ S s;
+ T t;
+ int j = 0;
+ #pragma omp declare reduction (bar : int : omp_out += omp_in)
+ #pragma omp parallel reduction (bar : t) reduction (S::bar : s) \
+ reduction(T<N>::operator+ : j)
+ s.a = 4, t.a = 5, j = 1;
+ if (s.a != 4 * j || t.a != 5 * j) abort ();
+ }
+ #pragma omp declare reduction (bar : T<N> : baz (omp_out, omp_in))
+ static void baz (T &x, T &y) { x.a += y.a; }
+ T () : a (N) {}
+ int a;
+};
+
+int
+main ()
+{
+ S s;
+ s.foo ();
+ T<0> t;
+ t.foo ();
+}
diff --git a/libgomp/testsuite/libgomp.c++/udr-6.C b/libgomp/testsuite/libgomp.c++/udr-6.C
new file mode 100644
index 00000000000..4be821ed0db
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/udr-6.C
@@ -0,0 +1,68 @@
+// { dg-do run }
+
+extern "C" void abort ();
+
+struct A { int a; A () : a (6) {} };
+struct B { int b; B () : b (5) {} };
+struct C { int c; C () : c (4) {} };
+struct D { int d; D () : d (3) {} };
+struct E : A, B {};
+struct F : C, D {};
+struct G : E, F {};
+void foo (B &);
+void foo (F &);
+#pragma omp declare reduction (+:B:omp_out.b += omp_in.b) \
+ initializer(foo (omp_priv))
+
+void
+foo (B &x)
+{
+ if (x.b != 5)
+ abort ();
+ x.b = 9;
+}
+
+template <typename T>
+void bar (T &x, T &y, int z)
+{
+ if (z)
+ abort ();
+ x.a += y.a;
+}
+
+namespace N1
+{
+ struct A { int a; A () : a (0) {} };
+ #pragma omp declare reduction (+:A:bar (omp_out, omp_in, 0))
+};
+namespace N2
+{
+ struct B : N1::A { };
+ #pragma omp declare reduction (+:N1::A:bar (omp_out, omp_in, 1))
+};
+
+int
+main ()
+{
+ G g;
+ int i = 0;
+ #pragma omp parallel reduction(+:g, i)
+ {
+ if (g.a != 6 || g.b != 9 || g.c != 4 || g.d != 3)
+ abort ();
+ g.a = 1, g.b = 2, g.c = 3, g.d = 4, i = 1;
+ }
+ if (g.a != 6 || g.b != 5 + 2 * i || g.c != 4 || g.d != 3)
+ abort ();
+ N2::B b;
+ i = 0;
+ #pragma omp parallel reduction (+:b, i)
+ {
+ if (b.a != 0)
+ abort ();
+ b.a = 4;
+ i = 1;
+ }
+ if (b.a != 4 * i)
+ abort ();
+}
diff --git a/libgomp/testsuite/libgomp.c++/udr-7.C b/libgomp/testsuite/libgomp.c++/udr-7.C
new file mode 100644
index 00000000000..6f661895a37
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/udr-7.C
@@ -0,0 +1,72 @@
+// { dg-do run }
+
+extern "C" void abort ();
+
+struct S
+{
+ int s;
+ void foo (S &x) { s += x.s; }
+ S (const S &x) { s = x.s + 1; }
+ S () { s = 6; }
+ ~S () {}
+};
+
+void
+bar (S &x, S &y)
+{
+ if (x.s != 6 || y.s != 6)
+ abort ();
+ x.s = 8;
+}
+
+#pragma omp declare reduction (foo: S: omp_out.foo (omp_in)) \
+ initializer (omp_priv (omp_orig))
+#pragma omp declare reduction (bar : S: omp_out.foo (omp_in)) \
+ initializer (bar (omp_priv, omp_orig))
+
+S
+baz (S x)
+{
+ S r;
+ int i = 0;
+ if (x.s != 7 || r.s != 6)
+ abort ();
+ #pragma omp parallel reduction (foo: x) reduction (bar: r) \
+ reduction (+: i)
+ {
+ if (x.s != 8 || r.s != 8)
+ abort ();
+ x.s = 12;
+ r.s = 14;
+ i = 1;
+ }
+ if (x.s != 7 + 12 * i || r.s != 6 + 14 * i)
+ abort ();
+ return r;
+}
+
+void
+baz (S &x, S &y)
+{
+ int i = 0, &j = i;
+ #pragma omp parallel reduction (foo: x) reduction (bar: y) \
+ reduction (+: i)
+ {
+ if (x.s != 7 || y.s != 8)
+ abort ();
+ x.s = 12;
+ y.s = 14;
+ i = 1;
+ }
+ if (x.s != 6 + 12 * j || y.s != 6 + 14 * j)
+ abort ();
+}
+
+int
+main ()
+{
+ S s;
+ baz (s);
+ S t, u;
+ baz (t, u);
+}
diff --git a/libgomp/testsuite/libgomp.c++/udr-8.C b/libgomp/testsuite/libgomp.c++/udr-8.C
new file mode 100644
index 00000000000..81c4beb8b6e
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/udr-8.C
@@ -0,0 +1,39 @@
+// { dg-do run }
+
+extern "C" void abort ();
+
+struct S;
+void foo (S *, S *);
+void bar (S &, S &);
+#pragma omp declare reduction (+:S:foo (&omp_out, &omp_in))
+#pragma omp declare reduction (*:S:bar (omp_out, omp_in))
+struct S { int s; S () : s (0) {} };
+
+void
+foo (S *x, S *y)
+{
+ x->s += y->s;
+}
+
+void
+bar (S &x, S &y)
+{
+ x.s += y.s;
+}
+
+int
+main ()
+{
+ S s, t;
+ int i = 0;
+ #pragma omp parallel reduction (+:s, i) reduction (*:t)
+ {
+ if (s.s != 0 || t.s != 0)
+ abort ();
+ s.s = 2;
+ t.s = 3;
+ i = 1;
+ }
+ if (s.s != 2 * i || t.s != 3 * i)
+ abort ();
+}
diff --git a/libgomp/testsuite/libgomp.c++/udr-9.C b/libgomp/testsuite/libgomp.c++/udr-9.C
new file mode 100644
index 00000000000..58fea18a4ce
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/udr-9.C
@@ -0,0 +1,3 @@
+// { dg-do run }
+
+#include "../libgomp.c/udr-1.c"
diff --git a/libgomp/testsuite/libgomp.c/affinity-1.c b/libgomp/testsuite/libgomp.c/affinity-1.c
new file mode 100644
index 00000000000..5d3e45d1df9
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/affinity-1.c
@@ -0,0 +1,1146 @@
+/* Affinity tests.
+ Copyright (C) 2013 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/>. */
+
+/* { dg-do run } */
+/* { dg-set-target-env-var OMP_PROC_BIND "false" } */
+/* { dg-additional-options "-DINTERPOSE_GETAFFINITY -DDO_FORK -ldl" { target *-*-linux* } } */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#include "config.h"
+#include <alloca.h>
+#include <omp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifdef DO_FORK
+#include <signal.h>
+#endif
+#ifdef HAVE_PTHREAD_AFFINITY_NP
+#include <sched.h>
+#include <pthread.h>
+#ifdef INTERPOSE_GETAFFINITY
+#include <dlfcn.h>
+#endif
+#endif
+
+struct place
+{
+ int start, len;
+};
+struct places
+{
+ char name[40];
+ int count;
+ struct place places[8];
+} places_array[] = {
+ { "", 1, { { -1, -1 } } },
+ { "{0}:8", 8,
+ { { 0, 1 }, { 1, 1 }, { 2, 1 }, { 3, 1 },
+ { 4, 1 }, { 5, 1 }, { 6, 1 }, { 7, 1 } } },
+ { "{7,6}:2:-3", 2, { { 6, 2 }, { 3, 2 } } },
+ { "{6,7}:4:-2,!{2,3}", 3, { { 6, 2 }, { 4, 2 }, { 0, 2 } } },
+ { "{1}:7:1", 7,
+ { { 1, 1 }, { 2, 1 }, { 3, 1 },
+ { 4, 1 }, { 5, 1 }, { 6, 1 }, { 7, 1 } } },
+ { "{0,1},{3,2,4},{6,5,!6},{6},{7:2:-1,!6}", 5,
+ { { 0, 2 }, { 2, 3 }, { 5, 1 }, { 6, 1 }, { 7, 1 } } }
+};
+
+unsigned long contig_cpucount;
+unsigned long min_cpusetsize;
+
+#if defined (HAVE_PTHREAD_AFFINITY_NP) && defined (_SC_NPROCESSORS_CONF) \
+ && defined (CPU_ALLOC_SIZE)
+
+#if defined (RTLD_NEXT) && defined (INTERPOSE_GETAFFINITY)
+int (*orig_getaffinity_np) (pthread_t, size_t, cpu_set_t *);
+
+int
+pthread_getaffinity_np (pthread_t thread, size_t cpusetsize, cpu_set_t *cpuset)
+{
+ int ret;
+ unsigned long i, max;
+ if (orig_getaffinity_np == NULL)
+ {
+ orig_getaffinity_np = (int (*) (pthread_t, size_t, cpu_set_t *))
+ dlsym (RTLD_NEXT, "pthread_getaffinity_np");
+ if (orig_getaffinity_np == NULL)
+ exit (0);
+ }
+ ret = orig_getaffinity_np (thread, cpusetsize, cpuset);
+ if (ret != 0)
+ return ret;
+ if (contig_cpucount == 0)
+ {
+ max = 8 * cpusetsize;
+ for (i = 0; i < max; i++)
+ if (!CPU_ISSET_S (i, cpusetsize, cpuset))
+ break;
+ contig_cpucount = i;
+ min_cpusetsize = cpusetsize;
+ }
+ return ret;
+}
+#endif
+
+void
+print_affinity (struct place p)
+{
+ static unsigned long size;
+ if (size == 0)
+ {
+ if (min_cpusetsize)
+ size = min_cpusetsize;
+ else
+ {
+ size = sysconf (_SC_NPROCESSORS_CONF);
+ size = CPU_ALLOC_SIZE (size);
+ if (size < sizeof (cpu_set_t))
+ size = sizeof (cpu_set_t);
+ }
+ }
+ cpu_set_t *cpusetp = (cpu_set_t *) alloca (size);
+ if (pthread_getaffinity_np (pthread_self (), size, cpusetp) == 0)
+ {
+ unsigned long i, len, max = 8 * size;
+ int notfirst = 0, unexpected = 1;
+
+ printf (" bound to {");
+ for (i = 0, len = 0; i < max; i++)
+ if (CPU_ISSET_S (i, size, cpusetp))
+ {
+ if (len == 0)
+ {
+ if (notfirst)
+ {
+ unexpected = 1;
+ printf (",");
+ }
+ else if (i == (unsigned long) p.start)
+ unexpected = 0;
+ notfirst = 1;
+ printf ("%lu", i);
+ }
+ ++len;
+ }
+ else
+ {
+ if (len && len != (unsigned long) p.len)
+ unexpected = 1;
+ if (len > 1)
+ printf (":%lu", len);
+ len = 0;
+ }
+ if (len && len != (unsigned long) p.len)
+ unexpected = 1;
+ if (len > 1)
+ printf (":%lu", len);
+ printf ("}");
+ if (p.start != -1 && unexpected)
+ {
+ printf (", expected {%d", p.start);
+ if (p.len != 1)
+ printf (":%d", p.len);
+ printf ("} instead");
+ }
+ else if (p.start != -1)
+ printf (", verified");
+ }
+}
+#else
+void
+print_affinity (struct place p)
+{
+ (void) p.start;
+ (void) p.len;
+}
+#endif
+
+
+int
+main ()
+{
+ char *env_proc_bind = getenv ("OMP_PROC_BIND");
+ int test_false = env_proc_bind && strcmp (env_proc_bind, "false") == 0;
+ int test_true = env_proc_bind && strcmp (env_proc_bind, "true") == 0;
+ int test_spread_master_close
+ = env_proc_bind && strcmp (env_proc_bind, "spread,master,close") == 0;
+ char *env_places = getenv ("OMP_PLACES");
+ int test_places = 0;
+
+#ifdef DO_FORK
+ if (env_places == NULL && contig_cpucount >= 8 && test_false
+ && getenv ("GOMP_AFFINITY") == NULL)
+ {
+ int i, j, status;
+ pid_t pid;
+ for (j = 0; j < 2; j++)
+ {
+ if (setenv ("OMP_PROC_BIND", j ? "spread,master,close" : "true", 1)
+ < 0)
+ break;
+ for (i = sizeof (places_array) / sizeof (places_array[0]) - 1;
+ i; --i)
+ {
+ if (setenv ("OMP_PLACES", places_array[i].name, 1) < 0)
+ break;
+ pid = fork ();
+ if (pid == -1)
+ break;
+ if (pid == 0)
+ {
+ execl ("/proc/self/exe", "affinity-1.exe", NULL);
+ _exit (1);
+ }
+ if (waitpid (pid, &status, 0) < 0)
+ break;
+ if (WIFSIGNALED (status) && WTERMSIG (status) == SIGABRT)
+ abort ();
+ else if (!WIFEXITED (status) || WEXITSTATUS (status) != 0)
+ break;
+ }
+ if (i)
+ break;
+ }
+ }
+#endif
+
+ int first = 1;
+ if (env_proc_bind)
+ {
+ printf ("OMP_PROC_BIND='%s'", env_proc_bind);
+ first = 0;
+ }
+ if (env_places)
+ printf ("%sOMP_PLACES='%s'", first ? "" : " ", env_places);
+ printf ("\n");
+
+ if (env_places && contig_cpucount >= 8
+ && (test_true || test_spread_master_close))
+ {
+ for (test_places = sizeof (places_array) / sizeof (places_array[0]) - 1;
+ test_places; --test_places)
+ if (strcmp (env_places, places_array[test_places].name) == 0)
+ break;
+ }
+
+#define verify(if_true, if_s_m_c) \
+ if (test_false && omp_get_proc_bind () != omp_proc_bind_false) \
+ abort (); \
+ if (test_true && omp_get_proc_bind () != if_true) \
+ abort (); \
+ if (test_spread_master_close && omp_get_proc_bind () != if_s_m_c) \
+ abort ();
+
+ verify (omp_proc_bind_true, omp_proc_bind_spread);
+
+ printf ("Initial thread");
+ print_affinity (places_array[test_places].places[0]);
+ printf ("\n");
+ omp_set_nested (1);
+ omp_set_dynamic (0);
+
+ #pragma omp parallel if (0)
+ {
+ verify (omp_proc_bind_true, omp_proc_bind_master);
+ #pragma omp parallel if (0)
+ {
+ verify (omp_proc_bind_true, omp_proc_bind_close);
+ #pragma omp parallel if (0)
+ {
+ verify (omp_proc_bind_true, omp_proc_bind_close);
+ }
+ #pragma omp parallel if (0) proc_bind (spread)
+ {
+ verify (omp_proc_bind_spread, omp_proc_bind_spread);
+ }
+ }
+ #pragma omp parallel if (0) proc_bind (master)
+ {
+ verify (omp_proc_bind_master, omp_proc_bind_close);
+ #pragma omp parallel if (0)
+ {
+ verify (omp_proc_bind_master, omp_proc_bind_close);
+ }
+ #pragma omp parallel if (0) proc_bind (spread)
+ {
+ verify (omp_proc_bind_spread, omp_proc_bind_spread);
+ }
+ }
+ }
+
+ /* True/spread */
+ #pragma omp parallel num_threads (4)
+ {
+ verify (omp_proc_bind_true, omp_proc_bind_master);
+ #pragma omp critical
+ {
+ struct place p = places_array[0].places[0];
+ int thr = omp_get_thread_num ();
+ printf ("#1 thread %d", thr);
+ if (omp_get_num_threads () == 4 && test_spread_master_close)
+ switch (places_array[test_places].count)
+ {
+ case 8:
+ /* T = 4, P = 8, each subpartition has 2 places. */
+ case 7:
+ /* T = 4, P = 7, each subpartition has 2 places, but
+ last partition, which has just one place. */
+ p = places_array[test_places].places[2 * thr];
+ break;
+ case 5:
+ /* T = 4, P = 5, first subpartition has 2 places, the
+ rest just one. */
+ p = places_array[test_places].places[thr ? 1 + thr : 0];
+ break;
+ case 3:
+ /* T = 4, P = 3, unit sized subpartitions, first gets
+ thr0 and thr3, second thr1, third thr2. */
+ p = places_array[test_places].places[thr == 3 ? 0 : thr];
+ break;
+ case 2:
+ /* T = 4, P = 2, unit sized subpartitions, each with
+ 2 threads. */
+ p = places_array[test_places].places[thr / 2];
+ break;
+ }
+ print_affinity (p);
+ printf ("\n");
+ }
+ #pragma omp barrier
+ if (omp_get_thread_num () == 3)
+ {
+ /* True/spread, true/master. */
+ #pragma omp parallel num_threads (3)
+ {
+ verify (omp_proc_bind_true, omp_proc_bind_close);
+ #pragma omp critical
+ {
+ struct place p = places_array[0].places[0];
+ int thr = omp_get_thread_num ();
+ printf ("#1,#1 thread 3,%d", thr);
+ if (omp_get_num_threads () == 3 && test_spread_master_close)
+ /* Outer is spread, inner master, so just bind to the
+ place or the master thread, which is thr 3 above. */
+ switch (places_array[test_places].count)
+ {
+ case 8:
+ case 7:
+ p = places_array[test_places].places[6];
+ break;
+ case 5:
+ p = places_array[test_places].places[4];
+ break;
+ case 3:
+ p = places_array[test_places].places[0];
+ break;
+ case 2:
+ p = places_array[test_places].places[1];
+ break;
+ }
+ print_affinity (p);
+ printf ("\n");
+ }
+ }
+ /* True/spread, spread. */
+ #pragma omp parallel num_threads (5) proc_bind (spread)
+ {
+ verify (omp_proc_bind_spread, omp_proc_bind_close);
+ #pragma omp critical
+ {
+ struct place p = places_array[0].places[0];
+ int thr = omp_get_thread_num ();
+ printf ("#1,#2 thread 3,%d", thr);
+ if (omp_get_num_threads () == 5 && test_spread_master_close)
+ /* Outer is spread, inner spread. */
+ switch (places_array[test_places].count)
+ {
+ case 8:
+ /* T = 5, P = 2, unit sized subpartitions. */
+ p = places_array[test_places].places[thr == 4 ? 6
+ : 6 + thr / 2];
+ break;
+ /* The rest are T = 5, P = 1. */
+ case 7:
+ p = places_array[test_places].places[6];
+ break;
+ case 5:
+ p = places_array[test_places].places[4];
+ break;
+ case 3:
+ p = places_array[test_places].places[0];
+ break;
+ case 2:
+ p = places_array[test_places].places[1];
+ break;
+ }
+ print_affinity (p);
+ printf ("\n");
+ }
+ #pragma omp barrier
+ if (omp_get_thread_num () == 3)
+ {
+ /* True/spread, spread, close. */
+ #pragma omp parallel num_threads (5) proc_bind (close)
+ {
+ verify (omp_proc_bind_close, omp_proc_bind_close);
+ #pragma omp critical
+ {
+ struct place p = places_array[0].places[0];
+ int thr = omp_get_thread_num ();
+ printf ("#1,#2,#1 thread 3,3,%d", thr);
+ if (omp_get_num_threads () == 5 && test_spread_master_close)
+ /* Outer is spread, inner spread, innermost close. */
+ switch (places_array[test_places].count)
+ {
+ /* All are T = 5, P = 1. */
+ case 8:
+ p = places_array[test_places].places[7];
+ break;
+ case 7:
+ p = places_array[test_places].places[6];
+ break;
+ case 5:
+ p = places_array[test_places].places[4];
+ break;
+ case 3:
+ p = places_array[test_places].places[0];
+ break;
+ case 2:
+ p = places_array[test_places].places[1];
+ break;
+ }
+ print_affinity (p);
+ printf ("\n");
+ }
+ }
+ }
+ }
+ /* True/spread, master. */
+ #pragma omp parallel num_threads (4) proc_bind(master)
+ {
+ verify (omp_proc_bind_master, omp_proc_bind_close);
+ #pragma omp critical
+ {
+ struct place p = places_array[0].places[0];
+ int thr = omp_get_thread_num ();
+ printf ("#1,#3 thread 3,%d", thr);
+ if (omp_get_num_threads () == 4 && test_spread_master_close)
+ /* Outer is spread, inner master, so just bind to the
+ place or the master thread, which is thr 3 above. */
+ switch (places_array[test_places].count)
+ {
+ case 8:
+ case 7:
+ p = places_array[test_places].places[6];
+ break;
+ case 5:
+ p = places_array[test_places].places[4];
+ break;
+ case 3:
+ p = places_array[test_places].places[0];
+ break;
+ case 2:
+ p = places_array[test_places].places[1];
+ break;
+ }
+ print_affinity (p);
+ printf ("\n");
+ }
+ }
+ /* True/spread, close. */
+ #pragma omp parallel num_threads (6) proc_bind (close)
+ {
+ verify (omp_proc_bind_close, omp_proc_bind_close);
+ #pragma omp critical
+ {
+ struct place p = places_array[0].places[0];
+ int thr = omp_get_thread_num ();
+ printf ("#1,#4 thread 3,%d", thr);
+ if (omp_get_num_threads () == 6 && test_spread_master_close)
+ /* Outer is spread, inner close. */
+ switch (places_array[test_places].count)
+ {
+ case 8:
+ /* T = 6, P = 2, unit sized subpartitions. */
+ p = places_array[test_places].places[6 + thr / 3];
+ break;
+ /* The rest are T = 6, P = 1. */
+ case 7:
+ p = places_array[test_places].places[6];
+ break;
+ case 5:
+ p = places_array[test_places].places[4];
+ break;
+ case 3:
+ p = places_array[test_places].places[0];
+ break;
+ case 2:
+ p = places_array[test_places].places[1];
+ break;
+ }
+ print_affinity (p);
+ printf ("\n");
+ }
+ }
+ }
+ }
+
+ /* Spread. */
+ #pragma omp parallel num_threads (5) proc_bind(spread)
+ {
+ verify (omp_proc_bind_spread, omp_proc_bind_master);
+ #pragma omp critical
+ {
+ struct place p = places_array[0].places[0];
+ int thr = omp_get_thread_num ();
+ printf ("#2 thread %d", thr);
+ if (omp_get_num_threads () == 5
+ && (test_spread_master_close || test_true))
+ switch (places_array[test_places].count)
+ {
+ case 8:
+ /* T = 5, P = 8, first 3 subpartitions have 2 places, last
+ 2 one place. */
+ p = places_array[test_places].places[thr < 3 ? 2 * thr : 3 + thr];
+ break;
+ case 7:
+ /* T = 5, P = 7, first 2 subpartitions have 2 places, last
+ 3 one place. */
+ p = places_array[test_places].places[thr < 2 ? 2 * thr : 2 + thr];
+ break;
+ case 5:
+ /* T = 5, P = 5, unit sized subpartitions, each one with one
+ thread. */
+ p = places_array[test_places].places[thr];
+ break;
+ case 3:
+ /* T = 5, P = 3, unit sized subpartitions, first gets
+ thr0 and thr3, second thr1 and thr4, third thr2. */
+ p = places_array[test_places].places[thr >= 3 ? thr - 3 : thr];
+ break;
+ case 2:
+ /* T = 5, P = 2, unit sized subpartitions, first with
+ thr{0,1,4} and second with thr{2,3}. */
+ p = places_array[test_places].places[thr == 4 ? 0 : thr / 2];
+ break;
+ }
+ print_affinity (p);
+ printf ("\n");
+ }
+ #pragma omp barrier
+ if (omp_get_thread_num () == 3)
+ {
+ int pp = 0;
+ switch (places_array[test_places].count)
+ {
+ case 8: pp = 6; break;
+ case 7: pp = 5; break;
+ case 5: pp = 3; break;
+ case 2: pp = 1; break;
+ }
+ /* Spread, spread/master. */
+ #pragma omp parallel num_threads (3) firstprivate (pp)
+ {
+ verify (omp_proc_bind_spread, omp_proc_bind_close);
+ #pragma omp critical
+ {
+ struct place p = places_array[0].places[0];
+ int thr = omp_get_thread_num ();
+ printf ("#2,#1 thread 3,%d", thr);
+ if (test_spread_master_close || test_true)
+ /* Outer is spread, inner spread resp. master, bit we have
+ just unit sized partitions. */
+ p = places_array[test_places].places[pp];
+ print_affinity (p);
+ printf ("\n");
+ }
+ }
+ /* Spread, spread. */
+ #pragma omp parallel num_threads (5) proc_bind (spread) \
+ firstprivate (pp)
+ {
+ verify (omp_proc_bind_spread, omp_proc_bind_close);
+ #pragma omp critical
+ {
+ struct place p = places_array[0].places[0];
+ int thr = omp_get_thread_num ();
+ printf ("#2,#2 thread 3,%d", thr);
+ if (test_spread_master_close || test_true)
+ /* Outer is spread, inner spread, bit we have
+ just unit sized partitions. */
+ p = places_array[test_places].places[pp];
+ print_affinity (p);
+ printf ("\n");
+ }
+ }
+ /* Spread, master. */
+ #pragma omp parallel num_threads (4) proc_bind(master) \
+ firstprivate(pp)
+ {
+ verify (omp_proc_bind_master, omp_proc_bind_close);
+ #pragma omp critical
+ {
+ struct place p = places_array[0].places[0];
+ int thr = omp_get_thread_num ();
+ printf ("#2,#3 thread 3,%d", thr);
+ if (test_spread_master_close || test_true)
+ /* Outer is spread, inner master, bit we have
+ just unit sized partitions. */
+ p = places_array[test_places].places[pp];
+ print_affinity (p);
+ printf ("\n");
+ }
+ }
+ /* Spread, close. */
+ #pragma omp parallel num_threads (6) proc_bind (close) \
+ firstprivate (pp)
+ {
+ verify (omp_proc_bind_close, omp_proc_bind_close);
+ #pragma omp critical
+ {
+ struct place p = places_array[0].places[0];
+ int thr = omp_get_thread_num ();
+ printf ("#2,#4 thread 3,%d", thr);
+ if (test_spread_master_close || test_true)
+ /* Outer is spread, inner close, bit we have
+ just unit sized partitions. */
+ p = places_array[test_places].places[pp];
+ print_affinity (p);
+ printf ("\n");
+ }
+ }
+ }
+ }
+
+ /* Master. */
+ #pragma omp parallel num_threads (3) proc_bind(master)
+ {
+ verify (omp_proc_bind_master, omp_proc_bind_master);
+ #pragma omp critical
+ {
+ struct place p = places_array[0].places[0];
+ int thr = omp_get_thread_num ();
+ printf ("#3 thread %d", thr);
+ if (test_spread_master_close || test_true)
+ p = places_array[test_places].places[0];
+ print_affinity (p);
+ printf ("\n");
+ }
+ #pragma omp barrier
+ if (omp_get_thread_num () == 2)
+ {
+ /* Master, master. */
+ #pragma omp parallel num_threads (4)
+ {
+ verify (omp_proc_bind_master, omp_proc_bind_close);
+ #pragma omp critical
+ {
+ struct place p = places_array[0].places[0];
+ int thr = omp_get_thread_num ();
+ printf ("#3,#1 thread 2,%d", thr);
+ if (test_spread_master_close || test_true)
+ /* Outer is master, inner is master. */
+ p = places_array[test_places].places[0];
+ print_affinity (p);
+ printf ("\n");
+ }
+ }
+ /* Master, spread. */
+ #pragma omp parallel num_threads (4) proc_bind (spread)
+ {
+ verify (omp_proc_bind_spread, omp_proc_bind_close);
+ #pragma omp critical
+ {
+ struct place p = places_array[0].places[0];
+ int thr = omp_get_thread_num ();
+ printf ("#3,#2 thread 2,%d", thr);
+ if (omp_get_num_threads () == 4
+ && (test_spread_master_close || test_true))
+ /* Outer is master, inner is spread. */
+ switch (places_array[test_places].count)
+ {
+ case 8:
+ /* T = 4, P = 8, each subpartition has 2 places. */
+ case 7:
+ /* T = 4, P = 7, each subpartition has 2 places, but
+ last partition, which has just one place. */
+ p = places_array[test_places].places[2 * thr];
+ break;
+ case 5:
+ /* T = 4, P = 5, first subpartition has 2 places, the
+ rest just one. */
+ p = places_array[test_places].places[thr ? 1 + thr : 0];
+ break;
+ case 3:
+ /* T = 4, P = 3, unit sized subpartitions, first gets
+ thr0 and thr3, second thr1, third thr2. */
+ p = places_array[test_places].places[thr == 3 ? 0 : thr];
+ break;
+ case 2:
+ /* T = 4, P = 2, unit sized subpartitions, each with
+ 2 threads. */
+ p = places_array[test_places].places[thr / 2];
+ break;
+ }
+ print_affinity (p);
+ printf ("\n");
+ }
+ #pragma omp barrier
+ if (omp_get_thread_num () == 0)
+ {
+ /* Master, spread, close. */
+ #pragma omp parallel num_threads (5) proc_bind (close)
+ {
+ verify (omp_proc_bind_close, omp_proc_bind_close);
+ #pragma omp critical
+ {
+ struct place p = places_array[0].places[0];
+ int thr = omp_get_thread_num ();
+ printf ("#3,#2,#1 thread 2,0,%d", thr);
+ if (omp_get_num_threads () == 5
+ && (test_spread_master_close || test_true))
+ /* Outer is master, inner spread, innermost close. */
+ switch (places_array[test_places].count)
+ {
+ /* First 3 are T = 5, P = 2. */
+ case 8:
+ case 7:
+ case 5:
+ p = places_array[test_places].places[(thr & 2) / 2];
+ break;
+ /* All the rest are T = 5, P = 1. */
+ case 3:
+ case 2:
+ p = places_array[test_places].places[0];
+ break;
+ }
+ print_affinity (p);
+ printf ("\n");
+ }
+ }
+ }
+ #pragma omp barrier
+ if (omp_get_thread_num () == 3)
+ {
+ /* Master, spread, close. */
+ #pragma omp parallel num_threads (5) proc_bind (close)
+ {
+ verify (omp_proc_bind_close, omp_proc_bind_close);
+ #pragma omp critical
+ {
+ struct place p = places_array[0].places[0];
+ int thr = omp_get_thread_num ();
+ printf ("#3,#2,#2 thread 2,3,%d", thr);
+ if (omp_get_num_threads () == 5
+ && (test_spread_master_close || test_true))
+ /* Outer is master, inner spread, innermost close. */
+ switch (places_array[test_places].count)
+ {
+ case 8:
+ /* T = 5, P = 2. */
+ p = places_array[test_places].places[6
+ + (thr & 2) / 2];
+ break;
+ /* All the rest are T = 5, P = 1. */
+ case 7:
+ p = places_array[test_places].places[6];
+ break;
+ case 5:
+ p = places_array[test_places].places[4];
+ break;
+ case 3:
+ p = places_array[test_places].places[0];
+ break;
+ case 2:
+ p = places_array[test_places].places[1];
+ break;
+ }
+ print_affinity (p);
+ printf ("\n");
+ }
+ }
+ }
+ }
+ /* Master, master. */
+ #pragma omp parallel num_threads (4) proc_bind(master)
+ {
+ verify (omp_proc_bind_master, omp_proc_bind_close);
+ #pragma omp critical
+ {
+ struct place p = places_array[0].places[0];
+ int thr = omp_get_thread_num ();
+ printf ("#3,#3 thread 2,%d", thr);
+ if (test_spread_master_close || test_true)
+ /* Outer is master, inner master. */
+ p = places_array[test_places].places[0];
+ print_affinity (p);
+ printf ("\n");
+ }
+ }
+ /* Master, close. */
+ #pragma omp parallel num_threads (6) proc_bind (close)
+ {
+ verify (omp_proc_bind_close, omp_proc_bind_close);
+ #pragma omp critical
+ {
+ struct place p = places_array[0].places[0];
+ int thr = omp_get_thread_num ();
+ printf ("#3,#4 thread 2,%d", thr);
+ if (omp_get_num_threads () == 6
+ && (test_spread_master_close || test_true))
+ switch (places_array[test_places].count)
+ {
+ case 8:
+ /* T = 6, P = 8. */
+ case 7:
+ /* T = 6, P = 7. */
+ p = places_array[test_places].places[thr];
+ break;
+ case 5:
+ /* T = 6, P = 5. thr{0,5} go into the first place. */
+ p = places_array[test_places].places[thr == 5 ? 0 : thr];
+ break;
+ case 3:
+ /* T = 6, P = 3, two threads into each place. */
+ p = places_array[test_places].places[thr / 2];
+ break;
+ case 2:
+ /* T = 6, P = 2, 3 threads into each place. */
+ p = places_array[test_places].places[thr / 3];
+ break;
+ }
+ print_affinity (p);
+ printf ("\n");
+ }
+ }
+ }
+ }
+
+ #pragma omp parallel num_threads (5) proc_bind(close)
+ {
+ verify (omp_proc_bind_close, omp_proc_bind_master);
+ #pragma omp critical
+ {
+ struct place p = places_array[0].places[0];
+ int thr = omp_get_thread_num ();
+ printf ("#4 thread %d", thr);
+ if (omp_get_num_threads () == 5
+ && (test_spread_master_close || test_true))
+ switch (places_array[test_places].count)
+ {
+ case 8:
+ /* T = 5, P = 8. */
+ case 7:
+ /* T = 5, P = 7. */
+ case 5:
+ /* T = 5, P = 5. */
+ p = places_array[test_places].places[thr];
+ break;
+ case 3:
+ /* T = 5, P = 3, thr{0,3} in first place, thr{1,4} in second,
+ thr2 in third. */
+ p = places_array[test_places].places[thr >= 3 ? thr - 3 : thr];
+ break;
+ case 2:
+ /* T = 5, P = 2, thr{0,1,4} in first place, thr{2,3} in second. */
+ p = places_array[test_places].places[thr == 4 ? 0 : thr / 2];
+ break;
+ }
+ print_affinity (p);
+ printf ("\n");
+ }
+ #pragma omp barrier
+ if (omp_get_thread_num () == 2)
+ {
+ int pp = 0;
+ switch (places_array[test_places].count)
+ {
+ case 8:
+ case 7:
+ case 5:
+ case 3:
+ pp = 2;
+ break;
+ case 2:
+ pp = 1;
+ break;
+ }
+ /* Close, close/master. */
+ #pragma omp parallel num_threads (4) firstprivate (pp)
+ {
+ verify (omp_proc_bind_close, omp_proc_bind_close);
+ #pragma omp critical
+ {
+ struct place p = places_array[0].places[0];
+ int thr = omp_get_thread_num ();
+ printf ("#4,#1 thread 2,%d", thr);
+ if (test_spread_master_close)
+ /* Outer is close, inner is master. */
+ p = places_array[test_places].places[pp];
+ else if (omp_get_num_threads () == 4 && test_true)
+ /* Outer is close, inner is close. */
+ switch (places_array[test_places].count)
+ {
+ case 8:
+ /* T = 4, P = 8. */
+ case 7:
+ /* T = 4, P = 7. */
+ p = places_array[test_places].places[2 + thr];
+ break;
+ case 5:
+ /* T = 4, P = 5. There is wrap-around for thr3. */
+ p = places_array[test_places].places[thr == 3 ? 0 : 2 + thr];
+ break;
+ case 3:
+ /* T = 4, P = 3, thr{0,3} go into p2, thr1 into p0, thr2
+ into p1. */
+ p = places_array[test_places].places[(2 + thr) % 3];
+ break;
+ case 2:
+ /* T = 4, P = 2, 2 threads into each place. */
+ p = places_array[test_places].places[1 - thr / 2];
+ break;
+ }
+
+ print_affinity (p);
+ printf ("\n");
+ }
+ }
+ /* Close, spread. */
+ #pragma omp parallel num_threads (4) proc_bind (spread)
+ {
+ verify (omp_proc_bind_spread, omp_proc_bind_close);
+ #pragma omp critical
+ {
+ struct place p = places_array[0].places[0];
+ int thr = omp_get_thread_num ();
+ printf ("#4,#2 thread 2,%d", thr);
+ if (omp_get_num_threads () == 4
+ && (test_spread_master_close || test_true))
+ /* Outer is close, inner is spread. */
+ switch (places_array[test_places].count)
+ {
+ case 8:
+ /* T = 4, P = 8, each subpartition has 2 places. */
+ case 7:
+ /* T = 4, P = 7, each subpartition has 2 places, but
+ last partition, which has just one place. */
+ p = places_array[test_places].places[thr == 3 ? 0
+ : 2 + 2 * thr];
+ break;
+ case 5:
+ /* T = 4, P = 5, first subpartition has 2 places, the
+ rest just one. */
+ p = places_array[test_places].places[thr == 3 ? 0
+ : 2 + thr];
+ break;
+ case 3:
+ /* T = 4, P = 3, unit sized subpartitions, third gets
+ thr0 and thr3, first thr1, second thr2. */
+ p = places_array[test_places].places[thr == 0 ? 2 : thr - 1];
+ break;
+ case 2:
+ /* T = 4, P = 2, unit sized subpartitions, each with
+ 2 threads. */
+ p = places_array[test_places].places[1 - thr / 2];
+ break;
+ }
+ print_affinity (p);
+ printf ("\n");
+ }
+ #pragma omp barrier
+ if (omp_get_thread_num () == 0)
+ {
+ /* Close, spread, close. */
+ #pragma omp parallel num_threads (5) proc_bind (close)
+ {
+ verify (omp_proc_bind_close, omp_proc_bind_close);
+ #pragma omp critical
+ {
+ struct place p = places_array[0].places[0];
+ int thr = omp_get_thread_num ();
+ printf ("#4,#2,#1 thread 2,0,%d", thr);
+ if (omp_get_num_threads () == 5
+ && (test_spread_master_close || test_true))
+ /* Outer is close, inner spread, innermost close. */
+ switch (places_array[test_places].count)
+ {
+ case 8:
+ case 7:
+ /* T = 5, P = 2. */
+ p = places_array[test_places].places[2
+ + (thr & 2) / 2];
+ break;
+ /* All the rest are T = 5, P = 1. */
+ case 5:
+ case 3:
+ p = places_array[test_places].places[2];
+ break;
+ case 2:
+ p = places_array[test_places].places[1];
+ break;
+ }
+ print_affinity (p);
+ printf ("\n");
+ }
+ }
+ }
+ #pragma omp barrier
+ if (omp_get_thread_num () == 2)
+ {
+ /* Close, spread, close. */
+ #pragma omp parallel num_threads (5) proc_bind (close)
+ {
+ verify (omp_proc_bind_close, omp_proc_bind_close);
+ #pragma omp critical
+ {
+ struct place p = places_array[0].places[0];
+ int thr = omp_get_thread_num ();
+ printf ("#4,#2,#2 thread 2,2,%d", thr);
+ if (omp_get_num_threads () == 5
+ && (test_spread_master_close || test_true))
+ /* Outer is close, inner spread, innermost close. */
+ switch (places_array[test_places].count)
+ {
+ case 8:
+ /* T = 5, P = 2. */
+ p = places_array[test_places].places[6
+ + (thr & 2) / 2];
+ break;
+ /* All the rest are T = 5, P = 1. */
+ case 7:
+ p = places_array[test_places].places[6];
+ break;
+ case 5:
+ p = places_array[test_places].places[4];
+ break;
+ case 3:
+ p = places_array[test_places].places[1];
+ break;
+ case 2:
+ p = places_array[test_places].places[0];
+ break;
+ }
+ print_affinity (p);
+ printf ("\n");
+ }
+ }
+ }
+ #pragma omp barrier
+ if (omp_get_thread_num () == 3)
+ {
+ /* Close, spread, close. */
+ #pragma omp parallel num_threads (5) proc_bind (close)
+ {
+ verify (omp_proc_bind_close, omp_proc_bind_close);
+ #pragma omp critical
+ {
+ struct place p = places_array[0].places[0];
+ int thr = omp_get_thread_num ();
+ printf ("#4,#2,#3 thread 2,3,%d", thr);
+ if (omp_get_num_threads () == 5
+ && (test_spread_master_close || test_true))
+ /* Outer is close, inner spread, innermost close. */
+ switch (places_array[test_places].count)
+ {
+ case 8:
+ case 7:
+ case 5:
+ /* T = 5, P = 2. */
+ p = places_array[test_places].places[(thr & 2) / 2];
+ break;
+ /* All the rest are T = 5, P = 1. */
+ case 3:
+ p = places_array[test_places].places[2];
+ break;
+ case 2:
+ p = places_array[test_places].places[0];
+ break;
+ }
+ print_affinity (p);
+ printf ("\n");
+ }
+ }
+ }
+ }
+ /* Close, master. */
+ #pragma omp parallel num_threads (4) proc_bind(master) \
+ firstprivate (pp)
+ {
+ verify (omp_proc_bind_master, omp_proc_bind_close);
+ #pragma omp critical
+ {
+ struct place p = places_array[0].places[0];
+ int thr = omp_get_thread_num ();
+ printf ("#4,#3 thread 2,%d", thr);
+ if (test_spread_master_close || test_true)
+ /* Outer is close, inner master. */
+ p = places_array[test_places].places[pp];
+ print_affinity (p);
+ printf ("\n");
+ }
+ }
+ /* Close, close. */
+ #pragma omp parallel num_threads (6) proc_bind (close)
+ {
+ verify (omp_proc_bind_close, omp_proc_bind_close);
+ #pragma omp critical
+ {
+ struct place p = places_array[0].places[0];
+ int thr = omp_get_thread_num ();
+ printf ("#4,#4 thread 2,%d", thr);
+ if (omp_get_num_threads () == 6
+ && (test_spread_master_close || test_true))
+ switch (places_array[test_places].count)
+ {
+ case 8:
+ /* T = 6, P = 8. */
+ p = places_array[test_places].places[2 + thr];
+ break;
+ case 7:
+ /* T = 6, P = 7. */
+ p = places_array[test_places].places[thr == 5 ? 0 : 2 + thr];
+ break;
+ case 5:
+ /* T = 6, P = 5. thr{0,5} go into the third place. */
+ p = places_array[test_places].places[thr >= 3 ? thr - 3
+ : 2 + thr];
+ break;
+ case 3:
+ /* T = 6, P = 3, two threads into each place. */
+ p = places_array[test_places].places[thr < 2 ? 2
+ : thr / 2 - 1];
+ break;
+ case 2:
+ /* T = 6, P = 2, 3 threads into each place. */
+ p = places_array[test_places].places[1 - thr / 3];
+ break;
+ }
+ print_affinity (p);
+ printf ("\n");
+ }
+ }
+ }
+ }
+
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/atomic-14.c b/libgomp/testsuite/libgomp.c/atomic-14.c
index 593665046c5..9046d80220d 100644
--- a/libgomp/testsuite/libgomp.c/atomic-14.c
+++ b/libgomp/testsuite/libgomp.c/atomic-14.c
@@ -16,7 +16,7 @@ main ()
#pragma omp atomic update
x = x + 7;
#pragma omp atomic
- x = x + 7 + 6;
+ x = x + (7 + 6);
#pragma omp atomic update
x = x + 2 * 3;
#pragma omp atomic
@@ -65,7 +65,7 @@ main ()
if (v != -8)
abort ();
#pragma omp atomic
- x = x * -4 / 2;
+ x = x * (-4 / 2);
#pragma omp atomic read
v = x;
if (v != 16)
diff --git a/libgomp/testsuite/libgomp.c/atomic-15.c b/libgomp/testsuite/libgomp.c/atomic-15.c
new file mode 100644
index 00000000000..58331f4a90b
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/atomic-15.c
@@ -0,0 +1,99 @@
+// { dg-do run }
+
+extern void abort (void);
+int x = 6;
+
+int
+main ()
+{
+ int v, l = 2, s = 1;
+ #pragma omp atomic
+ x = -3 + x;
+ #pragma omp atomic read
+ v = x;
+ if (v != 3)
+ abort ();
+ #pragma omp atomic update
+ x = 3 * 2 * 1 + x;
+ #pragma omp atomic read
+ v = x;
+ if (v != 9)
+ abort ();
+ #pragma omp atomic capture
+ v = x = x | 16;
+ if (v != 25)
+ abort ();
+ #pragma omp atomic capture
+ v = x = x + 14 * 2 / 4;
+ if (v != 32)
+ abort ();
+ #pragma omp atomic capture
+ v = x = 5 | x;
+ if (v != 37)
+ abort ();
+ #pragma omp atomic capture
+ v = x = 40 + 12 - 2 - 7 - x;
+ if (v != 6)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != 6)
+ abort ();
+ #pragma omp atomic capture
+ { v = x; x = 3 + x; }
+ if (v != 6)
+ abort ();
+ #pragma omp atomic capture
+ { v = x; x = -1 * -1 * -1 * -1 - x; }
+ if (v != 9)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != -8)
+ abort ();
+ #pragma omp atomic capture
+ { x = 2 * 2 - x; v = x; }
+ if (v != 12)
+ abort ();
+ #pragma omp atomic capture
+ { x = 7 & x; v = x; }
+ if (v != 4)
+ abort ();
+ #pragma omp atomic capture
+ { v = x; x = 6; }
+ if (v != 4)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != 6)
+ abort ();
+ #pragma omp atomic capture
+ { v = x; x = 7 * 8 + 23; }
+ if (v != 6)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != 79)
+ abort ();
+ #pragma omp atomic capture
+ { v = x; x = 23 + 6 * 4; }
+ if (v != 79)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != 47)
+ abort ();
+ #pragma omp atomic capture
+ { v = x; x = l ? 17 : 12; }
+ if (v != 47)
+ abort ();
+ #pragma omp atomic capture
+ { v = x; x = l = s++ + 3; }
+ if (v != 17 || l != 4 || s != 2)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != 4)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/atomic-16.c b/libgomp/testsuite/libgomp.c/atomic-16.c
new file mode 100644
index 00000000000..d33f670ec1f
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/atomic-16.c
@@ -0,0 +1,58 @@
+// { dg-do run }
+
+extern void abort (void);
+int x = 6, cnt;
+
+int
+foo (void)
+{
+ return cnt++;
+}
+
+int
+main ()
+{
+ int v, *p;
+ p = &x;
+ #pragma omp atomic update
+ p[foo (), 0] = 16 + 6 - p[foo (), 0];
+ #pragma omp atomic read
+ v = x;
+ if (cnt != 2 || v != 16)
+ abort ();
+ #pragma omp atomic capture
+ v = p[foo () + foo (), 0] = p[foo () + foo (), 0] + 3;
+ if (cnt != 6 || v != 19)
+ abort ();
+ #pragma omp atomic capture
+ v = p[foo (), 0] = 12 * 1 / 2 + (foo (), 0) + p[foo (), 0];
+ if (cnt != 9 || v != 25)
+ abort ();
+ #pragma omp atomic capture
+ {
+ v = p[foo () & 0]; p[foo () & 0] = (foo (), 1) * 9 - p[foo () & 0];
+ }
+ if (cnt != 13 || v != 25)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != -16)
+ abort ();
+ #pragma omp atomic capture
+ {
+ p[0 & foo ()] = 16 - 2 + 3 + p[0 & foo ()]; v = p[0 & foo ()];
+ }
+ if (cnt != 16 || v != 1)
+ abort ();
+ #pragma omp atomic capture
+ {
+ v = p[foo (), 0]; p[foo (), 0] = (foo (), 7) ? 13 : foo () + 6;
+ }
+ if (cnt != 19 || v != 1)
+ abort ();
+ #pragma omp atomic read
+ v = x;
+ if (v != 13)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/atomic-17.c b/libgomp/testsuite/libgomp.c/atomic-17.c
new file mode 100644
index 00000000000..2bd0e9b44dc
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/atomic-17.c
@@ -0,0 +1,99 @@
+// { dg-do run }
+
+extern void abort (void);
+int x = 6;
+
+int
+main ()
+{
+ int v, l = 2, s = 1;
+ #pragma omp atomic seq_cst
+ x = -3 + x;
+ #pragma omp atomic read seq_cst
+ v = x;
+ if (v != 3)
+ abort ();
+ #pragma omp atomic update seq_cst
+ x = 3 * 2 * 1 + x;
+ #pragma omp atomic read seq_cst
+ v = x;
+ if (v != 9)
+ abort ();
+ #pragma omp atomic capture seq_cst
+ v = x = x | 16;
+ if (v != 25)
+ abort ();
+ #pragma omp atomic capture seq_cst
+ v = x = x + 14 * 2 / 4;
+ if (v != 32)
+ abort ();
+ #pragma omp atomic capture seq_cst
+ v = x = 5 | x;
+ if (v != 37)
+ abort ();
+ #pragma omp atomic capture seq_cst
+ v = x = 40 + 12 - 2 - 7 - x;
+ if (v != 6)
+ abort ();
+ #pragma omp atomic read seq_cst
+ v = x;
+ if (v != 6)
+ abort ();
+ #pragma omp atomic capture seq_cst
+ { v = x; x = 3 + x; }
+ if (v != 6)
+ abort ();
+ #pragma omp atomic capture seq_cst
+ { v = x; x = -1 * -1 * -1 * -1 - x; }
+ if (v != 9)
+ abort ();
+ #pragma omp atomic read seq_cst
+ v = x;
+ if (v != -8)
+ abort ();
+ #pragma omp atomic capture seq_cst
+ { x = 2 * 2 - x; v = x; }
+ if (v != 12)
+ abort ();
+ #pragma omp atomic capture seq_cst
+ { x = 7 & x; v = x; }
+ if (v != 4)
+ abort ();
+ #pragma omp atomic capture seq_cst
+ { v = x; x = 6; }
+ if (v != 4)
+ abort ();
+ #pragma omp atomic read seq_cst
+ v = x;
+ if (v != 6)
+ abort ();
+ #pragma omp atomic capture seq_cst
+ { v = x; x = 7 * 8 + 23; }
+ if (v != 6)
+ abort ();
+ #pragma omp atomic read seq_cst
+ v = x;
+ if (v != 79)
+ abort ();
+ #pragma omp atomic capture seq_cst
+ { v = x; x = 23 + 6 * 4; }
+ if (v != 79)
+ abort ();
+ #pragma omp atomic read seq_cst
+ v = x;
+ if (v != 47)
+ abort ();
+ #pragma omp atomic capture seq_cst
+ { v = x; x = l ? 17 : 12; }
+ if (v != 47)
+ abort ();
+ #pragma omp atomic capture seq_cst
+ { v = x; x = l = s++ + 3; }
+ if (v != 17 || l != 4 || s != 2)
+ abort ();
+ #pragma omp atomic read seq_cst
+ v = x;
+ if (v != 4)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/c.exp b/libgomp/testsuite/libgomp.c/c.exp
index 7dfdf8bde78..8e902d4c131 100644
--- a/libgomp/testsuite/libgomp.c/c.exp
+++ b/libgomp/testsuite/libgomp.c/c.exp
@@ -17,6 +17,9 @@ if ![info exists DEFAULT_CFLAGS] then {
# Initialize dg.
dg-init
+# Turn on OpenMP.
+lappend ALWAYS_CFLAGS "additional_flags=-fopenmp"
+
# Gather a list of all tests.
set tests [lsort [find $srcdir/$subdir *.c]]
diff --git a/libgomp/testsuite/libgomp.c/cancel-for-1.c b/libgomp/testsuite/libgomp.c/cancel-for-1.c
new file mode 100644
index 00000000000..f805f13642f
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/cancel-for-1.c
@@ -0,0 +1,22 @@
+/* { dg-do run } */
+/* { dg-set-target-env-var OMP_CANCELLATION "true" } */
+
+#include <stdlib.h>
+#include <omp.h>
+
+int
+main ()
+{
+ #pragma omp parallel num_threads (32)
+ {
+ int i;
+ #pragma omp for
+ for (i = 0; i < 1000; ++i)
+ {
+ #pragma omp cancel for
+ if (omp_get_cancellation ())
+ abort ();
+ }
+ }
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/cancel-for-2.c b/libgomp/testsuite/libgomp.c/cancel-for-2.c
new file mode 100644
index 00000000000..30cfbb1c502
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/cancel-for-2.c
@@ -0,0 +1,95 @@
+/* { dg-do run } */
+/* { dg-set-target-env-var OMP_CANCELLATION "true" } */
+
+#include <stdlib.h>
+#include <omp.h>
+
+__attribute__((noinline, noclone)) int
+foo (int *x)
+{
+ int v = 0, w = 0;
+ #pragma omp parallel num_threads (32) shared (v, w)
+ {
+ int i;
+ #pragma omp for
+ for (i = 0; i < 1000; ++i)
+ {
+ #pragma omp cancel for if (x[0])
+ abort ();
+ }
+ #pragma omp for
+ for (i = 0; i < 1000; ++i)
+ {
+ #pragma omp cancel for if (x[1])
+ #pragma omp atomic
+ v++;
+ }
+ #pragma omp for
+ for (i = 0; i < 1000; ++i)
+ {
+ #pragma omp cancel for if (x[2])
+ #pragma omp atomic
+ w += 8;
+ }
+ #pragma omp for
+ for (i = 0; i < 1000; ++i)
+ {
+ #pragma omp cancel for if (x[3])
+ #pragma omp atomic
+ v += 2;
+ }
+ }
+ if (v != 3000 || w != 0)
+ abort ();
+ #pragma omp parallel num_threads (32) shared (v, w)
+ {
+ int i;
+ /* None of these cancel directives should actually cancel anything,
+ but the compiler shouldn't know that and thus should use cancellable
+ barriers at the end of all the workshares. */
+ #pragma omp cancel parallel if (omp_get_thread_num () == 1 && x[4])
+ #pragma omp for
+ for (i = 0; i < 1000; ++i)
+ {
+ #pragma omp cancel for if (x[0])
+ abort ();
+ }
+ #pragma omp cancel parallel if (omp_get_thread_num () == 2 && x[4])
+ #pragma omp for
+ for (i = 0; i < 1000; ++i)
+ {
+ #pragma omp cancel for if (x[1])
+ #pragma omp atomic
+ v++;
+ }
+ #pragma omp cancel parallel if (omp_get_thread_num () == 3 && x[4])
+ #pragma omp for
+ for (i = 0; i < 1000; ++i)
+ {
+ #pragma omp cancel for if (x[2])
+ #pragma omp atomic
+ w += 8;
+ }
+ #pragma omp cancel parallel if (omp_get_thread_num () == 4 && x[4])
+ #pragma omp for
+ for (i = 0; i < 1000; ++i)
+ {
+ #pragma omp cancel for if (x[3])
+ #pragma omp atomic
+ v += 2;
+ }
+ #pragma omp cancel parallel if (omp_get_thread_num () == 5 && x[4])
+ }
+ if (v != 6000 || w != 0)
+ abort ();
+ return 0;
+}
+
+int
+main ()
+{
+ int x[] = { 1, 0, 1, 0, 0 };
+ if (omp_get_cancellation ())
+ foo (x);
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/cancel-parallel-1.c b/libgomp/testsuite/libgomp.c/cancel-parallel-1.c
new file mode 100644
index 00000000000..614eb50f0d6
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/cancel-parallel-1.c
@@ -0,0 +1,17 @@
+/* { dg-do run } */
+/* { dg-set-target-env-var OMP_CANCELLATION "true" } */
+
+#include <stdlib.h>
+#include <omp.h>
+
+int
+main ()
+{
+ #pragma omp parallel num_threads (32)
+ {
+ #pragma omp cancel parallel
+ if (omp_get_cancellation ())
+ abort ();
+ }
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/cancel-parallel-2.c b/libgomp/testsuite/libgomp.c/cancel-parallel-2.c
new file mode 100644
index 00000000000..cae0aa45c0f
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/cancel-parallel-2.c
@@ -0,0 +1,53 @@
+/* { dg-do run } */
+/* { dg-set-target-env-var OMP_CANCELLATION "true" } */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <omp.h>
+
+static void
+foo (int *x)
+{
+ #pragma omp parallel firstprivate(x) num_threads (32)
+ {
+ int thr = omp_get_thread_num ();
+ switch (x[thr])
+ {
+ case 4:
+ #pragma omp cancel parallel
+ break;
+ case 3:
+ #pragma omp task
+ usleep (1000);
+ #pragma omp task
+ usleep (2000);
+ #pragma omp task
+ usleep (4000);
+ break;
+ case 2:
+ usleep (1000);
+ /* FALLTHRU */
+ case 1:
+ #pragma omp cancellation point parallel
+ break;
+ }
+ #pragma omp barrier
+ if (omp_get_cancellation ())
+ abort ();
+ }
+}
+
+int
+main ()
+{
+ int i, j, x[32] = { 0, 1, 2, 4, 2, 2, 1, 0 };
+ foo (x);
+ for (i = 0; i < 32; i++)
+ {
+ for (j = 0; j < 32; j++)
+ x[j] = rand () & 3;
+ x[rand () & 31] = 4;
+ foo (x);
+ }
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/cancel-parallel-3.c b/libgomp/testsuite/libgomp.c/cancel-parallel-3.c
new file mode 100644
index 00000000000..7ceaed18467
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/cancel-parallel-3.c
@@ -0,0 +1,39 @@
+/* { dg-do run } */
+/* { dg-set-target-env-var OMP_CANCELLATION "true" } */
+
+#include <omp.h>
+#include <unistd.h>
+
+static inline void
+do_some_work (void)
+{
+ asm volatile ("" : : : "memory");
+}
+
+int
+main ()
+{
+ omp_set_dynamic (0);
+ omp_set_schedule (omp_sched_static, 1);
+ #pragma omp parallel num_threads (16)
+ {
+ int i, j;
+ do_some_work ();
+ #pragma omp barrier
+ if (omp_get_thread_num () == 1)
+ {
+ sleep (2);
+ #pragma omp cancellation point parallel
+ }
+ for (j = 3; j <= 16; j++)
+ #pragma omp for schedule (runtime) nowait
+ for (i = 0; i < j; i++)
+ do_some_work ();
+ if (omp_get_thread_num () == 0)
+ {
+ sleep (1);
+ #pragma omp cancel parallel
+ }
+ }
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/cancel-sections-1.c b/libgomp/testsuite/libgomp.c/cancel-sections-1.c
new file mode 100644
index 00000000000..e0cef0b6ea7
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/cancel-sections-1.c
@@ -0,0 +1,38 @@
+/* { dg-do run } */
+/* { dg-set-target-env-var OMP_CANCELLATION "true" } */
+
+#include <stdlib.h>
+#include <omp.h>
+
+int
+main ()
+{
+ if (!omp_get_cancellation ())
+ return 0;
+ #pragma omp parallel num_threads (32)
+ {
+ #pragma omp sections
+ {
+ {
+ #pragma omp cancel sections
+ abort ();
+ }
+ #pragma omp section
+ {
+ #pragma omp cancel sections
+ abort ();
+ }
+ #pragma omp section
+ {
+ #pragma omp cancel sections
+ abort ();
+ }
+ #pragma omp section
+ {
+ #pragma omp cancel sections
+ abort ();
+ }
+ }
+ }
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/cancel-taskgroup-1.c b/libgomp/testsuite/libgomp.c/cancel-taskgroup-1.c
new file mode 100644
index 00000000000..5a808113fb0
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/cancel-taskgroup-1.c
@@ -0,0 +1,70 @@
+/* { dg-do run } */
+/* { dg-set-target-env-var OMP_CANCELLATION "true" } */
+
+#include <stdlib.h>
+#include <omp.h>
+
+struct T { struct T *children[2]; int val; };
+
+struct T *
+search (struct T *tree, int val, int lvl)
+{
+ if (tree == NULL || tree->val == val)
+ return tree;
+ struct T *ret = NULL;
+ int i;
+ for (i = 0; i < 2; i++)
+ #pragma omp task shared(ret) if(lvl < 10)
+ {
+ struct T *r = search (tree->children[i], val, lvl + 1);
+ if (r)
+ {
+ #pragma omp atomic write
+ ret = r;
+ #pragma omp cancel taskgroup
+ }
+ }
+ #pragma omp taskwait
+ return ret;
+}
+
+struct T *
+searchp (struct T *tree, int val)
+{
+ struct T *ret;
+ #pragma omp parallel shared(ret) firstprivate (tree, val)
+ #pragma omp single
+ #pragma omp taskgroup
+ ret = search (tree, val, 0);
+ return ret;
+}
+
+int
+main ()
+{
+ /* Must be power of two minus 1. */
+ int size = 0x7ffff;
+ struct T *trees = (struct T *) malloc (size * sizeof (struct T));
+ if (trees == NULL)
+ return 0;
+ int i, l = 1, b = 0;
+ for (i = 0; i < size; i++)
+ {
+ if (i == l)
+ {
+ b = l;
+ l = l * 2 + 1;
+ }
+ trees[i].val = i;
+ trees[i].children[0] = l == size ? NULL : &trees[l + (i - b) * 2];
+ trees[i].children[1] = l == size ? NULL : &trees[l + (i - b) * 2 + 1];
+ }
+ for (i = 0; i < 50; i++)
+ {
+ int v = random () & size;
+ if (searchp (&trees[0], v) != &trees[v])
+ abort ();
+ }
+ free (trees);
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/cancel-taskgroup-2.c b/libgomp/testsuite/libgomp.c/cancel-taskgroup-2.c
new file mode 100644
index 00000000000..c7b8bf75623
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/cancel-taskgroup-2.c
@@ -0,0 +1,37 @@
+/* { dg-do run } */
+/* { dg-set-target-env-var OMP_CANCELLATION "true" } */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <omp.h>
+
+int
+main ()
+{
+ #pragma omp parallel
+ #pragma omp taskgroup
+ #pragma omp task
+ {
+ #pragma omp cancel taskgroup
+ if (omp_get_cancellation ())
+ abort ();
+ }
+ #pragma omp parallel
+ {
+ #pragma omp barrier
+ #pragma omp single
+ #pragma omp taskgroup
+ {
+ int i;
+ for (i = 0; i < 50; i++)
+ #pragma omp task
+ {
+ #pragma omp cancellation point taskgroup
+ usleep (30);
+ #pragma omp cancel taskgroup if (i > 5)
+ }
+ }
+ usleep (10);
+ }
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/depend-1.c b/libgomp/testsuite/libgomp.c/depend-1.c
new file mode 100644
index 00000000000..2db1205c12a
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/depend-1.c
@@ -0,0 +1,215 @@
+#include <stdlib.h>
+
+void
+dep (void)
+{
+ int x = 1;
+ #pragma omp parallel
+ #pragma omp single
+ {
+ #pragma omp task shared (x) depend(out: x)
+ x = 2;
+ #pragma omp task shared (x) depend(in: x)
+ if (x != 2)
+ abort ();
+ }
+}
+
+void
+dep2 (void)
+{
+ #pragma omp parallel
+ #pragma omp single
+ {
+ int x = 1;
+ #pragma omp task shared (x) depend(out: x)
+ x = 2;
+ #pragma omp task shared (x) depend(in: x)
+ if (x != 2)
+ abort ();
+ #pragma omp taskwait
+ }
+}
+
+void
+dep3 (void)
+{
+ #pragma omp parallel
+ {
+ int x = 1;
+ #pragma omp single
+ {
+ #pragma omp task shared (x) depend(out: x)
+ x = 2;
+ #pragma omp task shared (x) depend(in: x)
+ if (x != 2)
+ abort ();
+ }
+ }
+}
+
+void
+firstpriv (void)
+{
+ #pragma omp parallel
+ #pragma omp single
+ {
+ int x = 1;
+ #pragma omp task depend(out: x)
+ x = 2;
+ #pragma omp task depend(in: x)
+ if (x != 1)
+ abort ();
+ }
+}
+
+void
+antidep (void)
+{
+ int x = 1;
+ #pragma omp parallel
+ #pragma omp single
+ {
+ #pragma omp task shared(x) depend(in: x)
+ if (x != 1)
+ abort ();
+ #pragma omp task shared(x) depend(out: x)
+ x = 2;
+ }
+}
+
+void
+antidep2 (void)
+{
+ #pragma omp parallel
+ #pragma omp single
+ {
+ int x = 1;
+ #pragma omp taskgroup
+ {
+ #pragma omp task shared(x) depend(in: x)
+ if (x != 1)
+ abort ();
+ #pragma omp task shared(x) depend(out: x)
+ x = 2;
+ }
+ }
+}
+
+void
+antidep3 (void)
+{
+ #pragma omp parallel
+ {
+ int x = 1;
+ #pragma omp single
+ {
+ #pragma omp task shared(x) depend(in: x)
+ if (x != 1)
+ abort ();
+ #pragma omp task shared(x) depend(out: x)
+ x = 2;
+ }
+ }
+}
+
+
+void
+outdep (void)
+{
+ #pragma omp parallel
+ #pragma omp single
+ {
+ int x = 0;
+ #pragma omp task shared(x) depend(out: x)
+ x = 1;
+ #pragma omp task shared(x) depend(out: x)
+ x = 2;
+ #pragma omp taskwait
+ if (x != 2)
+ abort ();
+ }
+}
+
+void
+concurrent (void)
+{
+ int x = 1;
+ #pragma omp parallel
+ #pragma omp single
+ {
+ #pragma omp task shared (x) depend(out: x)
+ x = 2;
+ #pragma omp task shared (x) depend(in: x)
+ if (x != 2)
+ abort ();
+ #pragma omp task shared (x) depend(in: x)
+ if (x != 2)
+ abort ();
+ #pragma omp task shared (x) depend(in: x)
+ if (x != 2)
+ abort ();
+ }
+}
+
+void
+concurrent2 (void)
+{
+ #pragma omp parallel
+ #pragma omp single
+ {
+ int x = 1;
+ #pragma omp task shared (x) depend(out: x)
+ x = 2;
+ #pragma omp task shared (x) depend(in: x)
+ if (x != 2)
+ abort ();
+ #pragma omp task shared (x) depend(in: x)
+ if (x != 2)
+ abort ();
+ #pragma omp task shared (x) depend(in: x)
+ if (x != 2)
+ abort ();
+ #pragma omp taskwait
+ }
+}
+
+void
+concurrent3 (void)
+{
+ #pragma omp parallel
+ {
+ int x = 1;
+ #pragma omp single
+ {
+ #pragma omp task shared (x) depend(out: x)
+ x = 2;
+ #pragma omp task shared (x) depend(in: x)
+ if (x != 2)
+ abort ();
+ #pragma omp task shared (x) depend(in: x)
+ if (x != 2)
+ abort ();
+ #pragma omp task shared (x) depend(in: x)
+ if (x != 2)
+ abort ();
+ }
+ }
+}
+
+int
+main ()
+{
+ dep ();
+ dep2 ();
+ dep3 ();
+ firstpriv ();
+ antidep ();
+ antidep2 ();
+ antidep3 ();
+ outdep ();
+ concurrent ();
+ concurrent2 ();
+ concurrent3 ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/depend-2.c b/libgomp/testsuite/libgomp.c/depend-2.c
new file mode 100644
index 00000000000..2772309e4b8
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/depend-2.c
@@ -0,0 +1,71 @@
+#include <stdlib.h>
+#include <unistd.h>
+
+void
+foo (int do_sleep)
+{
+ int a[64], i, *p = a + 4, x = 0;
+ asm volatile ("" : "+r" (p));
+ for (i = 0; i < 64; i++)
+ a[i] = i + 8;
+ #pragma omp parallel private (i)
+ {
+ #pragma omp single nowait
+ {
+ for (i = 0; i < 8; i++)
+ {
+ #pragma omp task depend(out: a[i * 8 : 4])
+ a[i * 8] += (i + 2) * 9;
+ #pragma omp task depend(out: p[i * 8 : 2])
+ p[i * 8] += (i + 3) * 10;
+ #pragma omp task depend(out: x)
+ x = 1;
+ }
+ for (i = 0; i < 8; i++)
+ #pragma omp task depend(in: a[i * 8 : 4]) \
+ depend(inout: a[i * 8 + 4 : 2]) \
+ depend(in: a[0 : 4]) depend(in: x)
+ {
+ if (a[0] != 8 + 2 * 9 || x != 1)
+ abort ();
+ if (a[i * 8] != i * 8 + 8 + (i + 2) * 9)
+ abort ();
+ if (a[4 + i * 8] != 4 + i * 8 + 8 + (i + 3) * 10)
+ abort ();
+ p[i * 8] += a[i * 8];
+ }
+ for (i = 0; i < 8; i++)
+ #pragma omp task depend(inout: a[i * 8 : 4]) \
+ depend(in: p[i * 8 : 2]) \
+ depend(in: p[0 : 2], x)
+ {
+ if (p[0] != 4 + 8 + 3 * 10 + 0 + 8 + 2 * 9 || x != 1)
+ abort ();
+ if (a[i * 8] != i * 8 + 8 + (i + 2) * 9)
+ abort ();
+ if (a[4 + i * 8] != (4 + i * 8 + 8 + (i + 3) * 10
+ + i * 8 + 8 + (i + 2) * 9))
+ abort ();
+ a[i * 8] += 2;
+ }
+ for (i = 0; i < 4; i++)
+ #pragma omp task depend(in: a[i * 16 : 4], a[i * 16 + 8 : 4], x)
+ {
+ if (a[i * 16] != i * 16 + 8 + (2 * i + 2) * 9 + 2 || x != 1)
+ abort ();
+ if (p[i * 16 + 4] != i * 16 + 8 + 8 + (2 * i + 1 + 2) * 9 + 2)
+ abort ();
+ }
+ }
+ if (do_sleep)
+ sleep (1);
+ }
+}
+
+int
+main ()
+{
+ foo (1);
+ foo (0);
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/depend-3.c b/libgomp/testsuite/libgomp.c/depend-3.c
new file mode 100644
index 00000000000..d565d6e4619
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/depend-3.c
@@ -0,0 +1,51 @@
+#include <stdlib.h>
+#include <unistd.h>
+
+int
+main ()
+{
+ #pragma omp parallel
+ #pragma omp single
+ {
+ int x = 1, y = 2;
+ #pragma omp taskgroup
+ {
+ #pragma omp task shared (x) depend(in: x)
+ {
+ usleep (10000);
+ if (x != 1)
+ abort ();
+ }
+ #pragma omp taskgroup
+ {
+ #pragma omp task shared (x) depend(in: x)
+ {
+ usleep (15000);
+ if (x != 1)
+ abort ();
+ }
+ #pragma omp task shared (y) depend(inout: y)
+ {
+ if (y != 2)
+ abort ();
+ y = 3;
+ }
+ #pragma omp taskgroup
+ {
+ #pragma omp task shared (x) depend(in: x)
+ {
+ usleep (13000);
+ if (x != 1)
+ abort ();
+ }
+ #pragma omp taskgroup
+ {
+ #pragma omp task shared (x) depend(out: x)
+ x = 2;
+ }
+ }
+ }
+ }
+ }
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/depend-4.c b/libgomp/testsuite/libgomp.c/depend-4.c
new file mode 100644
index 00000000000..a4395ea6fc0
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/depend-4.c
@@ -0,0 +1,56 @@
+#include <stdlib.h>
+#include <unistd.h>
+
+int
+main ()
+{
+ #pragma omp parallel
+ #pragma omp single
+ {
+ int x = 1, y = 2, z = 3;
+ #pragma omp taskgroup
+ {
+ #pragma omp task shared (x, y, z) depend(inout: x, y) \
+ depend (in: z) if (x > 10)
+ {
+ if (x != 1 || y != 2 || z != 3)
+ abort ();
+ x = 4;
+ y = 5;
+ }
+ /* The above task has depend clauses, but no dependencies
+ on earlier tasks, and is if (0), so must be scheduled
+ immediately. */
+ if (x != 4 || y != 5)
+ abort ();
+ }
+ #pragma omp taskgroup
+ {
+ #pragma omp task shared (x, y) depend(in: x, y)
+ {
+ usleep (10000);
+ if (x != 4 || y != 5 || z != 3)
+ abort ();
+ }
+ #pragma omp task shared (x, y) depend(in: x, y)
+ {
+ usleep (10000);
+ if (x != 4 || y != 5 || z != 3)
+ abort ();
+ }
+ #pragma omp task shared (x, y, z) depend(inout: x, y) \
+ depend (in: z) if (x > 10)
+ {
+ if (x != 4 || y != 5 || z != 3)
+ abort ();
+ x = 6;
+ y = 7;
+ }
+ /* The above task has depend clauses, and may have dependencies
+ on earlier tasks, while it is if (0), it can be deferred. */
+ }
+ if (x != 6 || y != 7)
+ abort ();
+ }
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/for-1.c b/libgomp/testsuite/libgomp.c/for-1.c
new file mode 100644
index 00000000000..e702453fb1a
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/for-1.c
@@ -0,0 +1,35 @@
+/* { dg-options "-std=gnu99 -fopenmp" } */
+
+extern void abort (void);
+
+#define M(x, y, z) O(x, y, z)
+#define O(x, y, z) x ## _ ## y ## _ ## z
+
+#define F parallel for
+#define G pf
+#include "for-1.h"
+#undef F
+#undef G
+
+#define F for
+#define G f
+#include "for-1.h"
+#undef F
+#undef G
+
+int
+main ()
+{
+ if (test_pf_static ()
+ || test_pf_static32 ()
+ || test_pf_auto ()
+ || test_pf_guided32 ()
+ || test_pf_runtime ()
+ || test_f_static ()
+ || test_f_static32 ()
+ || test_f_auto ()
+ || test_f_guided32 ()
+ || test_f_runtime ())
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/for-1.h b/libgomp/testsuite/libgomp.c/for-1.h
new file mode 100644
index 00000000000..fa82c5b20d7
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/for-1.h
@@ -0,0 +1,25 @@
+#define S
+#define N(x) M(x, G, static)
+#include "for-2.h"
+#undef S
+#undef N
+#define S schedule(static, 32)
+#define N(x) M(x, G, static32)
+#include "for-2.h"
+#undef S
+#undef N
+#define S schedule(auto)
+#define N(x) M(x, G, auto)
+#include "for-2.h"
+#undef S
+#undef N
+#define S schedule(guided, 32)
+#define N(x) M(x, G, guided32)
+#include "for-2.h"
+#undef S
+#undef N
+#define S schedule(runtime)
+#define N(x) M(x, G, runtime)
+#include "for-2.h"
+#undef S
+#undef N
diff --git a/libgomp/testsuite/libgomp.c/for-2.c b/libgomp/testsuite/libgomp.c/for-2.c
new file mode 100644
index 00000000000..f5a01ab05ec
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/for-2.c
@@ -0,0 +1,46 @@
+/* { dg-options "-std=gnu99 -fopenmp" } */
+
+extern void abort (void);
+
+#define M(x, y, z) O(x, y, z)
+#define O(x, y, z) x ## _ ## y ## _ ## z
+
+#define F simd
+#define G simd
+#define S
+#define N(x) M(x, G, normal)
+#include "for-2.h"
+#undef S
+#undef N
+#undef F
+#undef G
+
+#define F parallel for simd
+#define G pf_simd
+#include "for-1.h"
+#undef F
+#undef G
+
+#define F for simd
+#define G f_simd
+#include "for-1.h"
+#undef F
+#undef G
+
+int
+main ()
+{
+ if (test_simd_normal ()
+ || test_pf_simd_static ()
+ || test_pf_simd_static32 ()
+ || test_pf_simd_auto ()
+ || test_pf_simd_guided32 ()
+ || test_pf_simd_runtime ()
+ || test_f_simd_static ()
+ || test_f_simd_static32 ()
+ || test_f_simd_auto ()
+ || test_f_simd_guided32 ()
+ || test_f_simd_runtime ())
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/for-2.h b/libgomp/testsuite/libgomp.c/for-2.h
new file mode 100644
index 00000000000..57c385ec876
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/for-2.h
@@ -0,0 +1,269 @@
+#ifndef VARS
+#define VARS
+int a[1500];
+float b[10][15][10];
+__attribute__((noreturn)) void
+noreturn (void)
+{
+ for (;;);
+}
+#endif
+
+__attribute__((noinline, noclone)) void
+N(f0) (void)
+{
+ int i;
+#pragma omp F S
+ for (i = 0; i < 1500; i++)
+ a[i] += 2;
+}
+
+__attribute__((noinline, noclone)) void
+N(f1) (void)
+{
+#pragma omp F S
+ for (unsigned int i = __INT_MAX__; i < 3000U + __INT_MAX__; i += 2)
+ a[(i - __INT_MAX__) >> 1] -= 2;
+}
+
+__attribute__((noinline, noclone)) void
+N(f2) (void)
+{
+ unsigned long long i;
+#pragma omp F S
+ for (i = __LONG_LONG_MAX__ + 4500ULL - 27;
+ i > __LONG_LONG_MAX__ - 27ULL; i -= 3)
+ a[(i + 26LL - __LONG_LONG_MAX__) / 3] -= 4;
+}
+
+__attribute__((noinline, noclone)) void
+N(f3) (long long n1, long long n2, long long s3)
+{
+#pragma omp F S
+ for (long long i = n1 + 23; i > n2 - 25; i -= s3)
+ a[i + 48] += 7;
+}
+
+__attribute__((noinline, noclone)) void
+N(f4) (void)
+{
+ unsigned int i;
+#pragma omp F S
+ for (i = 30; i < 20; i += 2)
+ a[i] += 10;
+}
+
+__attribute__((noinline, noclone)) void
+N(f5) (int n11, int n12, int n21, int n22, int n31, int n32,
+ int s1, int s2, int s3)
+{
+ int v1, v2, v3;
+#pragma omp F S collapse(3)
+ for (v1 = n11; v1 < n12; v1 += s1)
+ for (v2 = n21; v2 < n22; v2 += s2)
+ for (v3 = n31; v3 < n32; v3 += s3)
+ b[v1][v2][v3] += 2.5;
+}
+
+__attribute__((noinline, noclone)) void
+N(f6) (int n11, int n12, int n21, int n22, long long n31, long long n32,
+ int s1, int s2, long long int s3)
+{
+ int v1, v2;
+ long long v3;
+#pragma omp F S collapse(3)
+ for (v1 = n11; v1 > n12; v1 += s1)
+ for (v2 = n21; v2 > n22; v2 += s2)
+ for (v3 = n31; v3 > n32; v3 += s3)
+ b[v1][v2 / 2][v3] -= 4.5;
+}
+
+__attribute__((noinline, noclone)) void
+N(f7) (void)
+{
+ unsigned int v1, v3;
+ unsigned long long v2;
+#pragma omp F S collapse(3)
+ for (v1 = 0; v1 < 20; v1 += 2)
+ for (v2 = __LONG_LONG_MAX__ + 16ULL;
+ v2 > __LONG_LONG_MAX__ - 29ULL; v2 -= 3)
+ for (v3 = 10; v3 > 0; v3--)
+ b[v1 >> 1][(v2 - __LONG_LONG_MAX__ + 64) / 3 - 12][v3 - 1] += 5.5;
+}
+
+__attribute__((noinline, noclone)) void
+N(f8) (void)
+{
+ long long v1, v2, v3;
+#pragma omp F S collapse(3)
+ for (v1 = 0; v1 < 20; v1 += 2)
+ for (v2 = 30; v2 < 20; v2++)
+ for (v3 = 10; v3 < 0; v3--)
+ b[v1][v2][v3] += 5.5;
+}
+
+__attribute__((noinline, noclone)) void
+N(f9) (void)
+{
+ int i;
+#pragma omp F S
+ for (i = 20; i < 10; i++)
+ {
+ a[i] += 2;
+ noreturn ();
+ a[i] -= 4;
+ }
+}
+
+__attribute__((noinline, noclone)) void
+N(f10) (void)
+{
+ int i;
+#pragma omp F S collapse(3)
+ for (i = 0; i < 10; i++)
+ for (int j = 10; j < 8; j++)
+ for (long k = -10; k < 10; k++)
+ {
+ b[i][j][k] += 4;
+ noreturn ();
+ b[i][j][k] -= 8;
+ }
+}
+
+__attribute__((noinline, noclone)) void
+N(f11) (int n)
+{
+ int i;
+#pragma omp F S
+ for (i = 20; i < n; i++)
+ {
+ a[i] += 8;
+ noreturn ();
+ a[i] -= 16;
+ }
+}
+
+__attribute__((noinline, noclone)) void
+N(f12) (int n)
+{
+ int i;
+#pragma omp F S collapse(3)
+ for (i = 0; i < 10; i++)
+ for (int j = n; j < 8; j++)
+ for (long k = -10; k < 10; k++)
+ {
+ b[i][j][k] += 16;
+ noreturn ();
+ b[i][j][k] -= 32;
+ }
+}
+
+__attribute__((noinline, noclone)) void
+N(f13) (void)
+{
+ int *i;
+#pragma omp F S
+ for (i = a; i < &a[1500]; i++)
+ i[0] += 2;
+}
+
+__attribute__((noinline, noclone)) void
+N(f14) (void)
+{
+ float *i;
+#pragma omp F S collapse(3)
+ for (i = &b[0][0][0]; i < &b[0][0][10]; i++)
+ for (float *j = &b[0][15][0]; j > &b[0][0][0]; j -= 10)
+ for (float *k = &b[0][0][10]; k > &b[0][0][0]; --k)
+ b[i - &b[0][0][0]][(j - &b[0][0][0]) / 10 - 1][(k - &b[0][0][0]) - 1]
+ -= 3.5;
+}
+
+__attribute__((noinline, noclone)) int
+N(test) (void)
+{
+ int i, j, k;
+ for (i = 0; i < 1500; i++)
+ a[i] = i - 25;
+ N(f0) ();
+ for (i = 0; i < 1500; i++)
+ if (a[i] != i - 23)
+ return 1;
+ N(f1) ();
+ for (i = 0; i < 1500; i++)
+ if (a[i] != i - 25)
+ return 1;
+ N(f2) ();
+ for (i = 0; i < 1500; i++)
+ if (a[i] != i - 29)
+ return 1;
+ N(f3) (1500LL - 1 - 23 - 48, -1LL + 25 - 48, 1LL);
+ for (i = 0; i < 1500; i++)
+ if (a[i] != i - 22)
+ return 1;
+ N(f3) (1500LL - 1 - 23 - 48, 1500LL - 1, 7LL);
+ for (i = 0; i < 1500; i++)
+ if (a[i] != i - 22)
+ return 1;
+ N(f4) ();
+ for (i = 0; i < 1500; i++)
+ if (a[i] != i - 22)
+ return 1;
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 15; j++)
+ for (k = 0; k < 10; k++)
+ b[i][j][k] = i - 2.5 + 1.5 * j - 1.5 * k;
+ N(f5) (0, 10, 0, 15, 0, 10, 1, 1, 1);
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 15; j++)
+ for (k = 0; k < 10; k++)
+ if (b[i][j][k] != i + 1.5 * j - 1.5 * k)
+ return 1;
+ N(f5) (0, 10, 30, 15, 0, 10, 4, 5, 6);
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 15; j++)
+ for (k = 0; k < 10; k++)
+ if (b[i][j][k] != i + 1.5 * j - 1.5 * k)
+ return 1;
+ N(f6) (9, -1, 29, 0, 9, -1, -1, -2, -1);
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 15; j++)
+ for (k = 0; k < 10; k++)
+ if (b[i][j][k] != i - 4.5 + 1.5 * j - 1.5 * k)
+ return 1;
+ N(f7) ();
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 15; j++)
+ for (k = 0; k < 10; k++)
+ if (b[i][j][k] != i + 1.0 + 1.5 * j - 1.5 * k)
+ return 1;
+ N(f8) ();
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 15; j++)
+ for (k = 0; k < 10; k++)
+ if (b[i][j][k] != i + 1.0 + 1.5 * j - 1.5 * k)
+ return 1;
+ N(f9) ();
+ N(f10) ();
+ N(f11) (10);
+ N(f12) (12);
+ for (i = 0; i < 1500; i++)
+ if (a[i] != i - 22)
+ return 1;
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 15; j++)
+ for (k = 0; k < 10; k++)
+ if (b[i][j][k] != i + 1.0 + 1.5 * j - 1.5 * k)
+ return 1;
+ N(f13) ();
+ N(f14) ();
+ for (i = 0; i < 1500; i++)
+ if (a[i] != i - 20)
+ return 1;
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 15; j++)
+ for (k = 0; k < 10; k++)
+ if (b[i][j][k] != i - 2.5 + 1.5 * j - 1.5 * k)
+ return 1;
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/for-3.c b/libgomp/testsuite/libgomp.c/for-3.c
new file mode 100644
index 00000000000..06cbf4f9de1
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/for-3.c
@@ -0,0 +1,110 @@
+/* { dg-options "-std=gnu99 -fopenmp" } */
+
+extern void abort ();
+
+#define M(x, y, z) O(x, y, z)
+#define O(x, y, z) x ## _ ## y ## _ ## z
+
+#pragma omp declare target
+
+#define F distribute
+#define G d
+#define S
+#define N(x) M(x, G, normal)
+#include "for-2.h"
+#undef S
+#undef N
+#undef F
+#undef G
+
+#define F distribute
+#define G d_ds128
+#define S dist_schedule(static, 128)
+#define N(x) M(x, G, normal)
+#include "for-2.h"
+#undef S
+#undef N
+#undef F
+#undef G
+
+#define F distribute simd
+#define G ds
+#define S
+#define N(x) M(x, G, normal)
+#include "for-2.h"
+#undef S
+#undef N
+#undef F
+#undef G
+
+#define F distribute simd
+#define G ds_ds128
+#define S dist_schedule(static, 128)
+#define N(x) M(x, G, normal)
+#include "for-2.h"
+#undef S
+#undef N
+#undef F
+#undef G
+
+#define F distribute parallel for
+#define G dpf
+#include "for-1.h"
+#undef F
+#undef G
+
+#define F distribute parallel for dist_schedule(static, 128)
+#define G dpf_ds128
+#include "for-1.h"
+#undef F
+#undef G
+
+#define F distribute parallel for simd
+#define G dpfs
+#include "for-1.h"
+#undef F
+#undef G
+
+#define F distribute parallel for simd dist_schedule(static, 128)
+#define G dpfs_ds128
+#include "for-1.h"
+#undef F
+#undef G
+
+#pragma omp end declare target
+
+int
+main ()
+{
+ int err = 0;
+ #pragma omp target teams reduction(|:err)
+ {
+ err |= test_d_normal ();
+ err |= test_d_ds128_normal ();
+ err |= test_ds_normal ();
+ err |= test_ds_ds128_normal ();
+ err |= test_dpf_static ();
+ err |= test_dpf_static32 ();
+ err |= test_dpf_auto ();
+ err |= test_dpf_guided32 ();
+ err |= test_dpf_runtime ();
+ err |= test_dpf_ds128_static ();
+ err |= test_dpf_ds128_static32 ();
+ err |= test_dpf_ds128_auto ();
+ err |= test_dpf_ds128_guided32 ();
+ err |= test_dpf_ds128_runtime ();
+ err |= test_dpfs_static ();
+ err |= test_dpfs_static32 ();
+ err |= test_dpfs_auto ();
+ err |= test_dpfs_guided32 ();
+ err |= test_dpfs_runtime ();
+ err |= test_dpfs_ds128_static ();
+ err |= test_dpfs_ds128_static32 ();
+ err |= test_dpfs_ds128_auto ();
+ err |= test_dpfs_ds128_guided32 ();
+ err |= test_dpfs_ds128_runtime ();
+ }
+ if (err)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/lib-1.c b/libgomp/testsuite/libgomp.c/lib-1.c
index 4839cf936f2..086036d0a69 100644
--- a/libgomp/testsuite/libgomp.c/lib-1.c
+++ b/libgomp/testsuite/libgomp.c/lib-1.c
@@ -85,6 +85,8 @@ main (void)
l = ! omp_in_parallel ();
#pragma omp parallel reduction (|:l) if (1)
l = ! omp_in_parallel ();
+ if (l)
+ abort ();
e = omp_get_wtime ();
if (d > e)
diff --git a/libgomp/testsuite/libgomp.c/pr58392.c b/libgomp/testsuite/libgomp.c/pr58392.c
new file mode 100644
index 00000000000..6ca97adc2d3
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/pr58392.c
@@ -0,0 +1,58 @@
+/* PR tree-optimization/58392 */
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+/* { dg-additional-options "-msse2" { target sse2_runtime } } */
+/* { dg-additional-options "-mavx" { target avx_runtime } } */
+
+extern void abort (void);
+int d[32 * 32];
+
+__attribute__((noinline, noclone)) int
+foo (int a, int b)
+{
+ int j, c = 0;
+ #pragma omp parallel for reduction(+: c)
+ for (j = 0; j < a; j += 32)
+ {
+ int l;
+ #pragma omp simd reduction(+: c)
+ for (l = 0; l < b; ++l)
+ c += d[j + l];
+ }
+ return c;
+}
+
+__attribute__((noinline, noclone)) int
+bar (int a)
+{
+ int j, c = 0;
+ #pragma omp parallel for simd reduction(+: c)
+ for (j = 0; j < a; ++j)
+ c += d[j];
+ return c;
+}
+
+__attribute__((noinline)) static int
+baz (int a)
+{
+ int j, c = 0;
+ #pragma omp simd reduction(+: c)
+ for (j = 0; j < a; ++j)
+ c += d[j];
+ return c;
+}
+
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 32 * 32; i++)
+ d[i] = (i & 31);
+ if (foo (32 * 32, 32) != (31 * 32 / 2) * 32)
+ abort ();
+ if (bar (32 * 32) != (31 * 32 / 2) * 32)
+ abort ();
+ if (baz (32 * 32) != (31 * 32 / 2) * 32)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/simd-1.c b/libgomp/testsuite/libgomp.c/simd-1.c
new file mode 100644
index 00000000000..352b3b7ddd4
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/simd-1.c
@@ -0,0 +1,57 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+/* { dg-additional-options "-msse2" { target sse2_runtime } } */
+/* { dg-additional-options "-mavx" { target avx_runtime } } */
+
+extern void abort ();
+int a[1024] __attribute__((aligned (32))) = { 1 };
+int b[1024] __attribute__((aligned (32))) = { 1 };
+int k, m;
+struct U { int u; };
+struct V { int v; };
+
+__attribute__((noinline, noclone)) int
+foo (int *p)
+{
+ int i, s = 0;
+ struct U u;
+ struct V v;
+ #pragma omp simd aligned(a, p : 32) linear(k: m + 1) \
+ reduction(+:s) lastprivate(u, v)
+ for (i = 0; i < 1024; i++)
+ {
+ a[i] *= p[i];
+ u.u = p[i] + k;
+ k += m + 1;
+ v.v = p[i] + k;
+ s += p[i] + k;
+ }
+ if (u.u != 36 + 4 + 3 * 1023 || v.v != 36 + 4 + 3 * 1024)
+ abort ();
+ return s;
+}
+
+int
+main ()
+{
+#if __SIZEOF_INT__ >= 4
+ int i;
+ k = 4;
+ m = 2;
+ for (i = 0; i < 1024; i++)
+ {
+ a[i] = i - 512;
+ b[i] = (i - 51) % 39;
+ }
+ int s = foo (b);
+ for (i = 0; i < 1024; i++)
+ {
+ if (b[i] != (i - 51) % 39
+ || a[i] != (i - 512) * b[i])
+ abort ();
+ }
+ if (k != 4 + 3 * 1024 || s != 1596127)
+ abort ();
+#endif
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/simd-2.c b/libgomp/testsuite/libgomp.c/simd-2.c
new file mode 100644
index 00000000000..b485fcb6f6f
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/simd-2.c
@@ -0,0 +1,36 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+/* { dg-additional-options "-msse2" { target sse2_runtime } } */
+/* { dg-additional-options "-mavx" { target avx_runtime } } */
+
+extern void abort ();
+__UINTPTR_TYPE__ arr[1027];
+
+__attribute__((noinline, noclone)) void
+foo ()
+{
+ int i, v;
+ #pragma omp simd private (v) safelen(16)
+ for (i = 0; i < 1027; i++)
+ arr[i] = (__UINTPTR_TYPE__) &v;
+}
+
+int
+main ()
+{
+ int i, j, cnt = 0;
+ __UINTPTR_TYPE__ arr2[16];
+ foo ();
+ for (i = 0; i < 1027; i++)
+ {
+ for (j = 0; j < cnt; j++)
+ if (arr[i] == arr2[j])
+ break;
+ if (j != cnt)
+ continue;
+ if (cnt == 16)
+ abort ();
+ arr2[cnt++] = arr[i];
+ }
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/simd-3.c b/libgomp/testsuite/libgomp.c/simd-3.c
new file mode 100644
index 00000000000..34a38830143
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/simd-3.c
@@ -0,0 +1,131 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+/* { dg-additional-options "-msse2" { target sse2_runtime } } */
+/* { dg-additional-options "-mavx" { target avx_runtime } } */
+
+extern void abort ();
+int a[1024] __attribute__((aligned (32))) = { 1 };
+int b[1024] __attribute__((aligned (32))) = { 1 };
+unsigned char c[1024] __attribute__((aligned (32))) = { 1 };
+int k, m;
+__UINTPTR_TYPE__ u, u2, u3;
+
+__attribute__((noinline, noclone)) int
+foo (int *p)
+{
+ int i, s = 0, s2 = 0, t, t2;
+ #pragma omp simd aligned(a, b, p : 32) linear(k: m + 1) reduction(+:s) \
+ lastprivate (t2)
+ for (i = 0; i < 512; i++)
+ {
+ a[i] *= p[i];
+ t2 = k + p[i];
+ k += m + 1;
+ s += p[i] + k;
+ c[i]++;
+ }
+ #pragma omp simd aligned(a, b, p : 32) linear(k: m + 1) reduction(+:s2) \
+ lastprivate (t, u, u2, u3)
+ for (i = 512; i < 1024; i++)
+ {
+ a[i] *= p[i];
+ k += m + 1;
+ t = k + p[i];
+ u = (__UINTPTR_TYPE__) &k;
+ u2 = (__UINTPTR_TYPE__) &s2;
+ u3 = (__UINTPTR_TYPE__) &t;
+ s2 += t;
+ c[i]++;
+ }
+ return s + s2 + t + t2;
+}
+
+__attribute__((noinline, noclone)) long int
+bar (int *p, long int n, long int o)
+{
+ long int i, s = 0, s2 = 0, t, t2;
+ #pragma omp simd aligned(a, b, p : 32) linear(k: m + 1) reduction(+:s) \
+ lastprivate (t2)
+ for (i = 0; i < n; i++)
+ {
+ a[i] *= p[i];
+ t2 = k + p[i];
+ k += m + 1;
+ s += p[i] + k;
+ c[i]++;
+ }
+ #pragma omp simd aligned(a, b, p : 32) linear(k: m + 1) reduction(+:s2) \
+ lastprivate (t, u, u2, u3)
+ for (i = n; i < o; i++)
+ {
+ a[i] *= p[i];
+ k += m + 1;
+ t = k + p[i];
+ u = (__UINTPTR_TYPE__) &k;
+ u2 = (__UINTPTR_TYPE__) &s2;
+ u3 = (__UINTPTR_TYPE__) &t;
+ s2 += t;
+ c[i]++;
+ }
+ return s + s2 + t + t2;
+}
+
+int
+main ()
+{
+#if __SIZEOF_INT__ >= 4
+ int i;
+ k = 4;
+ m = 2;
+ for (i = 0; i < 1024; i++)
+ {
+ a[i] = i - 512;
+ b[i] = (i - 51) % 39;
+ c[i] = (unsigned char) i;
+ }
+ int s = foo (b);
+ for (i = 0; i < 1024; i++)
+ {
+ if (b[i] != (i - 51) % 39
+ || a[i] != (i - 512) * b[i]
+ || c[i] != (unsigned char) (i + 1))
+ abort ();
+ a[i] = i - 512;
+ }
+ if (k != 4 + 3 * 1024
+ || s != 1596127 + (4 + 3 * 511 + b[511]) + (4 + 3 * 1024 + b[1023]))
+ abort ();
+ k = 4;
+ s = bar (b, 512, 1024);
+ for (i = 0; i < 1024; i++)
+ {
+ if (b[i] != (i - 51) % 39
+ || a[i] != (i - 512) * b[i]
+ || c[i] != (unsigned char) (i + 2))
+ abort ();
+ a[i] = i - 512;
+ }
+ if (k != 4 + 3 * 1024
+ || s != 1596127 + (4 + 3 * 511 + b[511]) + (4 + 3 * 1024 + b[1023]))
+ abort ();
+ k = 4;
+ s = bar (b, 511, 1021);
+ for (i = 0; i < 1021; i++)
+ {
+ if (b[i] != (i - 51) % 39
+ || a[i] != (i - 512) * b[i]
+ || c[i] != (unsigned char) (i + 3))
+ abort ();
+ a[i] = i - 512;
+ }
+ for (i = 1021; i < 1024; i++)
+ if (b[i] != (i - 51) % 39
+ || a[i] != i - 512
+ || c[i] != (unsigned char) (i + 2))
+ abort ();
+ if (k != 4 + 3 * 1021
+ || s != 1586803 + (4 + 3 * 510 + b[510]) + (4 + 3 * 1021 + b[1020]))
+ abort ();
+#endif
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/simd-4.c b/libgomp/testsuite/libgomp.c/simd-4.c
new file mode 100644
index 00000000000..fd87c7e1fa7
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/simd-4.c
@@ -0,0 +1,42 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+/* { dg-additional-options "-msse2" { target sse2_runtime } } */
+/* { dg-additional-options "-mavx" { target avx_runtime } } */
+
+extern void abort ();
+int a[1024] __attribute__((aligned (32))) = { 1 };
+struct S { int s; };
+#pragma omp declare reduction (+:struct S:omp_out.s += omp_in.s)
+#pragma omp declare reduction (foo:struct S:omp_out.s += omp_in.s)
+#pragma omp declare reduction (foo:int:omp_out += omp_in)
+
+__attribute__((noinline, noclone)) int
+foo (void)
+{
+ int i, u = 0;
+ struct S s, t;
+ s.s = 0; t.s = 0;
+ #pragma omp simd aligned(a : 32) reduction(+:s) reduction(foo:t, u)
+ for (i = 0; i < 1024; i++)
+ {
+ int x = a[i];
+ s.s += x;
+ t.s += x;
+ u += x;
+ }
+ if (t.s != s.s || u != s.s)
+ abort ();
+ return s.s;
+}
+
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 1024; i++)
+ a[i] = (i & 31) + (i / 128);
+ int s = foo ();
+ if (s != 19456)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/simd-5.c b/libgomp/testsuite/libgomp.c/simd-5.c
new file mode 100644
index 00000000000..0b6d41e6356
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/simd-5.c
@@ -0,0 +1,44 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+/* { dg-additional-options "-msse2" { target sse2_runtime } } */
+/* { dg-additional-options "-mavx" { target avx_runtime } } */
+
+extern void abort ();
+int a[1024] __attribute__((aligned (32))) = { 1 };
+struct S { int s; };
+#pragma omp declare reduction (+:struct S:omp_out.s += omp_in.s)
+#pragma omp declare reduction (foo:struct S:omp_out.s += omp_in.s)
+#pragma omp declare reduction (foo:int:omp_out += omp_in)
+
+__attribute__((noinline, noclone)) int
+foo (void)
+{
+ int i, u = 0, q = 0;
+ struct S s, t;
+ s.s = 0; t.s = 0;
+ #pragma omp simd aligned(a : 32) reduction(+:s, q) reduction(foo:t, u) \
+ safelen(1)
+ for (i = 0; i < 1024; i++)
+ {
+ int x = a[i];
+ s.s += x;
+ t.s += x;
+ u += x;
+ q++;
+ }
+ if (t.s != s.s || u != s.s || q != 1024)
+ abort ();
+ return s.s;
+}
+
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 1024; i++)
+ a[i] = (i & 31) + (i / 128);
+ int s = foo ();
+ if (s != 19456)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/simd-6.c b/libgomp/testsuite/libgomp.c/simd-6.c
new file mode 100644
index 00000000000..896f34784f2
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/simd-6.c
@@ -0,0 +1,44 @@
+/* PR libgomp/58482 */
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+/* { dg-additional-options "-msse2" { target sse2_runtime } } */
+/* { dg-additional-options "-mavx" { target avx_runtime } } */
+
+extern void abort ();
+int a[1024] __attribute__((aligned (32))) = { 1 };
+struct S { int s; };
+#pragma omp declare reduction (+:struct S:omp_out.s += omp_in.s)
+#pragma omp declare reduction (foo:struct S:omp_out.s += omp_in.s)
+#pragma omp declare reduction (foo:int:omp_out += omp_in)
+
+__attribute__((noinline, noclone)) int
+foo (void)
+{
+ int i, u = 0;
+ struct S s, t;
+ s.s = 0; t.s = 0;
+ #pragma omp parallel for simd aligned(a : 32) reduction(+:s) \
+ reduction(foo:t, u)
+ for (i = 0; i < 1024; i++)
+ {
+ int x = a[i];
+ s.s += x;
+ t.s += x;
+ u += x;
+ }
+ if (t.s != s.s || u != s.s)
+ abort ();
+ return s.s;
+}
+
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 1024; i++)
+ a[i] = (i & 31) + (i / 128);
+ int s = foo ();
+ if (s != 19456)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/target-1.c b/libgomp/testsuite/libgomp.c/target-1.c
new file mode 100644
index 00000000000..f734d3c279d
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/target-1.c
@@ -0,0 +1,90 @@
+extern
+#ifdef __cplusplus
+"C"
+#endif
+void abort (void);
+
+void
+fn1 (double *x, double *y, int z)
+{
+ int i;
+ for (i = 0; i < z; i++)
+ {
+ x[i] = i & 31;
+ y[i] = (i & 63) - 30;
+ }
+}
+
+#pragma omp declare target
+int tgtv = 6;
+int
+tgt (void)
+{
+ #pragma omp atomic update
+ tgtv++;
+ return 0;
+}
+#pragma omp end declare target
+
+double
+fn2 (int x, int y, int z)
+{
+ double b[1024], c[1024], s = 0;
+ int i, j;
+ fn1 (b, c, x);
+ #pragma omp target data map(to: b)
+ {
+ #pragma omp target map(tofrom: c)
+ #pragma omp teams num_teams(y) thread_limit(z) reduction(+:s) firstprivate(x)
+ #pragma omp distribute dist_schedule(static, 4) collapse(1)
+ for (j=0; j < x; j += y)
+ #pragma omp parallel for reduction(+:s)
+ for (i = j; i < j + y; i++)
+ tgt (), s += b[i] * c[i];
+ #pragma omp target update from(b, tgtv)
+ }
+ return s;
+}
+
+double
+fn3 (int x)
+{
+ double b[1024], c[1024], s = 0;
+ int i;
+ fn1 (b, c, x);
+ #pragma omp target map(to: b, c)
+ #pragma omp parallel for reduction(+:s)
+ for (i = 0; i < x; i++)
+ tgt (), s += b[i] * c[i];
+ return s;
+}
+
+double
+fn4 (int x, double *p)
+{
+ double b[1024], c[1024], d[1024], s = 0;
+ int i;
+ fn1 (b, c, x);
+ fn1 (d + x, p + x, x);
+ #pragma omp target map(to: b, c[0:x], d[x:x]) map(to:p[x:64 + (x & 31)])
+ #pragma omp parallel for reduction(+:s)
+ for (i = 0; i < x; i++)
+ s += b[i] * c[i] + d[x + i] + p[x + i];
+ return s;
+}
+
+int
+main ()
+{
+ double a = fn2 (128, 4, 6);
+ int b = tgtv;
+ double c = fn3 (61);
+ #pragma omp target update from(tgtv)
+ int d = tgtv;
+ double e[1024];
+ double f = fn4 (64, e);
+ if (a != 13888.0 || b != 6 + 128 || c != 4062.0 || d != 6 + 128 + 61
+ || f != 8032.0)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/target-2.c b/libgomp/testsuite/libgomp.c/target-2.c
new file mode 100644
index 00000000000..ada8dad81ad
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/target-2.c
@@ -0,0 +1,88 @@
+extern
+#ifdef __cplusplus
+"C"
+#endif
+void abort (void);
+
+void
+fn1 (double *x, double *y, int z)
+{
+ int i;
+ for (i = 0; i < z; i++)
+ {
+ x[i] = i & 31;
+ y[i] = (i & 63) - 30;
+ }
+}
+
+double
+fn2 (int x)
+{
+ double s = 0;
+ double b[3 * x], c[3 * x], d[3 * x], e[3 * x];
+ int i;
+ fn1 (b, c, x);
+ fn1 (e, d + x, x);
+ #pragma omp target map(to: b, c[:x], d[x:x], e)
+ #pragma omp parallel for reduction(+:s)
+ for (i = 0; i < x; i++)
+ s += b[i] * c[i] + d[x + i] + sizeof (b) - sizeof (c);
+ return s;
+}
+
+double
+fn3 (int x)
+{
+ double s = 0;
+ double b[3 * x], c[3 * x], d[3 * x], e[3 * x];
+ int i;
+ fn1 (b, c, x);
+ fn1 (e, d, x);
+ #pragma omp target
+ #pragma omp parallel for reduction(+:s)
+ for (i = 0; i < x; i++)
+ s += b[i] * c[i] + d[i];
+ return s;
+}
+
+double
+fn4 (int x)
+{
+ double s = 0;
+ double b[3 * x], c[3 * x], d[3 * x], e[3 * x];
+ int i;
+ fn1 (b, c, x);
+ fn1 (e, d + x, x);
+ #pragma omp target data map(from: b, c[:x], d[x:x], e)
+ {
+ #pragma omp target update to(b, c[:x], d[x:x], e)
+ #pragma omp target map(c[:x], d[x:x])
+ #pragma omp parallel for reduction(+:s)
+ for (i = 0; i < x; i++)
+ {
+ s += b[i] * c[i] + d[x + i] + sizeof (b) - sizeof (c);
+ b[i] = i + 0.5;
+ c[i] = 0.5 - i;
+ d[x + i] = 0.5 * i;
+ }
+ }
+ for (i = 0; i < x; i++)
+ if (b[i] != i + 0.5 || c[i] != 0.5 - i || d[x + i] != 0.5 * i)
+ abort ();
+ return s;
+}
+
+int
+main ()
+{
+ double a = fn2 (128);
+ if (a != 14080.0)
+ abort ();
+ double b = fn3 (128);
+ if (a != b)
+ abort ();
+ double c = fn4 (256);
+ if (c != 28160.0)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/target-3.c b/libgomp/testsuite/libgomp.c/target-3.c
new file mode 100644
index 00000000000..7002cf287f9
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/target-3.c
@@ -0,0 +1,17 @@
+#include <omp.h>
+#include <stdlib.h>
+
+int
+main ()
+{
+ if (omp_get_level ())
+ abort ();
+ #pragma omp target if (0)
+ if (omp_get_level ())
+ abort ();
+ #pragma omp target if (0)
+ #pragma omp teams
+ if (omp_get_level ())
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/target-4.c b/libgomp/testsuite/libgomp.c/target-4.c
new file mode 100644
index 00000000000..26e935b3673
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/target-4.c
@@ -0,0 +1,14 @@
+#include <omp.h>
+#include <stdlib.h>
+
+int
+main ()
+{
+ omp_set_dynamic (0);
+ #pragma omp parallel num_threads (4)
+ #pragma omp target if (0)
+ #pragma omp single
+ if (omp_get_num_threads () != 1)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/target-5.c b/libgomp/testsuite/libgomp.c/target-5.c
new file mode 100644
index 00000000000..436744359ca
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/target-5.c
@@ -0,0 +1,83 @@
+#include <omp.h>
+#include <stdlib.h>
+
+int
+main ()
+{
+ int d_o = omp_get_dynamic ();
+ int n_o = omp_get_nested ();
+ omp_sched_t s_o;
+ int c_o;
+ omp_get_schedule (&s_o, &c_o);
+ int m_o = omp_get_max_threads ();
+ omp_set_dynamic (1);
+ omp_set_nested (1);
+ omp_set_schedule (omp_sched_static, 2);
+ omp_set_num_threads (4);
+ int d = omp_get_dynamic ();
+ int n = omp_get_nested ();
+ omp_sched_t s;
+ int c;
+ omp_get_schedule (&s, &c);
+ int m = omp_get_max_threads ();
+ if (!omp_is_initial_device ())
+ abort ();
+ #pragma omp target if (0)
+ {
+ omp_sched_t s_c;
+ int c_c;
+ omp_get_schedule (&s_c, &c_c);
+ if (d_o != omp_get_dynamic ()
+ || n_o != omp_get_nested ()
+ || s_o != s_c
+ || c_o != c_c
+ || m_o != omp_get_max_threads ())
+ abort ();
+ omp_set_dynamic (0);
+ omp_set_nested (0);
+ omp_set_schedule (omp_sched_dynamic, 4);
+ omp_set_num_threads (2);
+ if (!omp_is_initial_device ())
+ abort ();
+ }
+ if (!omp_is_initial_device ())
+ abort ();
+ omp_sched_t s_c;
+ int c_c;
+ omp_get_schedule (&s_c, &c_c);
+ if (d != omp_get_dynamic ()
+ || n != omp_get_nested ()
+ || s != s_c
+ || c != c_c
+ || m != omp_get_max_threads ())
+ abort ();
+ #pragma omp target if (0)
+ #pragma omp teams
+ {
+ omp_sched_t s_c;
+ int c_c;
+ omp_get_schedule (&s_c, &c_c);
+ if (d_o != omp_get_dynamic ()
+ || n_o != omp_get_nested ()
+ || s_o != s_c
+ || c_o != c_c
+ || m_o != omp_get_max_threads ())
+ abort ();
+ omp_set_dynamic (0);
+ omp_set_nested (0);
+ omp_set_schedule (omp_sched_dynamic, 4);
+ omp_set_num_threads (2);
+ if (!omp_is_initial_device ())
+ abort ();
+ }
+ if (!omp_is_initial_device ())
+ abort ();
+ omp_get_schedule (&s_c, &c_c);
+ if (d != omp_get_dynamic ()
+ || n != omp_get_nested ()
+ || s != s_c
+ || c != c_c
+ || m != omp_get_max_threads ())
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/target-6.c b/libgomp/testsuite/libgomp.c/target-6.c
new file mode 100644
index 00000000000..ea35aa465f5
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/target-6.c
@@ -0,0 +1,68 @@
+#include <omp.h>
+#include <stdlib.h>
+
+int
+main ()
+{
+ omp_set_dynamic (0);
+ omp_set_nested (1);
+ if (omp_in_parallel ())
+ abort ();
+ #pragma omp parallel num_threads (3)
+ if (omp_get_thread_num () == 2)
+ {
+ if (!omp_in_parallel ())
+ abort ();
+ #pragma omp parallel num_threads (3)
+ if (omp_get_thread_num () == 1)
+ {
+ if (!omp_in_parallel ()
+ || omp_get_level () != 2
+ || omp_get_ancestor_thread_num (0) != 0
+ || omp_get_ancestor_thread_num (1) != 2
+ || omp_get_ancestor_thread_num (2) != 1
+ || omp_get_ancestor_thread_num (3) != -1)
+ abort ();
+ #pragma omp target if (0)
+ {
+ if (omp_in_parallel ()
+ || omp_get_level () != 0
+ || omp_get_ancestor_thread_num (0) != 0
+ || omp_get_ancestor_thread_num (1) != -1)
+ abort ();
+ #pragma omp parallel num_threads (2)
+ {
+ if (!omp_in_parallel ()
+ || omp_get_level () != 1
+ || omp_get_ancestor_thread_num (0) != 0
+ || omp_get_ancestor_thread_num (1)
+ != omp_get_thread_num ()
+ || omp_get_ancestor_thread_num (2) != -1)
+ abort ();
+ }
+ }
+ #pragma omp target if (0)
+ {
+ #pragma omp teams thread_limit (2)
+ {
+ if (omp_in_parallel ()
+ || omp_get_level () != 0
+ || omp_get_ancestor_thread_num (0) != 0
+ || omp_get_ancestor_thread_num (1) != -1)
+ abort ();
+ #pragma omp parallel num_threads (2)
+ {
+ if (!omp_in_parallel ()
+ || omp_get_level () != 1
+ || omp_get_ancestor_thread_num (0) != 0
+ || omp_get_ancestor_thread_num (1)
+ != omp_get_thread_num ()
+ || omp_get_ancestor_thread_num (2) != -1)
+ abort ();
+ }
+ }
+ }
+ }
+ }
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/target-7.c b/libgomp/testsuite/libgomp.c/target-7.c
new file mode 100644
index 00000000000..90de6c52311
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/target-7.c
@@ -0,0 +1,111 @@
+#include <omp.h>
+#include <stdlib.h>
+
+volatile int v;
+
+void
+foo (int f)
+{
+ int d = f ? omp_get_num_devices () : omp_get_default_device ();
+ int h = 5;
+ #pragma omp target device (d)
+ if (omp_get_level () != 0)
+ abort ();
+ #pragma omp target if (v > 1)
+ if (omp_get_level () != 0 || !omp_is_initial_device ())
+ abort ();
+ #pragma omp target device (d) if (v > 1)
+ if (omp_get_level () != 0 || !omp_is_initial_device ())
+ abort ();
+ #pragma omp target if (v <= 1)
+ if (omp_get_level () != 0 || (f && !omp_is_initial_device ()))
+ abort ();
+ #pragma omp target device (d) if (v <= 1)
+ if (omp_get_level () != 0 || (f && !omp_is_initial_device ()))
+ abort ();
+ #pragma omp target if (0)
+ if (omp_get_level () != 0 || !omp_is_initial_device ())
+ abort ();
+ #pragma omp target device (d) if (0)
+ if (omp_get_level () != 0 || !omp_is_initial_device ())
+ abort ();
+ #pragma omp target if (1)
+ if (omp_get_level () != 0 || (f && !omp_is_initial_device ()))
+ abort ();
+ #pragma omp target device (d) if (1)
+ if (omp_get_level () != 0 || (f && !omp_is_initial_device ()))
+ abort ();
+ #pragma omp target data device (d) map (to: h)
+ {
+ #pragma omp target device (d)
+ if (omp_get_level () != 0 || (f && !omp_is_initial_device ()) || h++ != 5)
+ abort ();
+ #pragma omp target update device (d) from (h)
+ }
+ #pragma omp target data if (v > 1) map (to: h)
+ {
+ #pragma omp target if (v > 1)
+ if (omp_get_level () != 0 || !omp_is_initial_device () || h++ != 6)
+ abort ();
+ #pragma omp target update if (v > 1) from (h)
+ }
+ #pragma omp target data device (d) if (v > 1) map (to: h)
+ {
+ #pragma omp target device (d) if (v > 1)
+ if (omp_get_level () != 0 || !omp_is_initial_device () || h++ != 7)
+ abort ();
+ #pragma omp target update device (d) if (v > 1) from (h)
+ }
+ #pragma omp target data if (v <= 1) map (to: h)
+ {
+ #pragma omp target if (v <= 1)
+ if (omp_get_level () != 0 || (f && !omp_is_initial_device ()) || h++ != 8)
+ abort ();
+ #pragma omp target update if (v <= 1) from (h)
+ }
+ #pragma omp target data device (d) if (v <= 1) map (to: h)
+ {
+ #pragma omp target device (d) if (v <= 1)
+ if (omp_get_level () != 0 || (f && !omp_is_initial_device ()) || h++ != 9)
+ abort ();
+ #pragma omp target update device (d) if (v <= 1) from (h)
+ }
+ #pragma omp target data if (0) map (to: h)
+ {
+ #pragma omp target if (0)
+ if (omp_get_level () != 0 || !omp_is_initial_device () || h++ != 10)
+ abort ();
+ #pragma omp target update if (0) from (h)
+ }
+ #pragma omp target data device (d) if (0) map (to: h)
+ {
+ #pragma omp target device (d) if (0)
+ if (omp_get_level () != 0 || !omp_is_initial_device () || h++ != 11)
+ abort ();
+ #pragma omp target update device (d) if (0) from (h)
+ }
+ #pragma omp target data if (1) map (to: h)
+ {
+ #pragma omp target if (1)
+ if (omp_get_level () != 0 || (f && !omp_is_initial_device ()) || h++ != 12)
+ abort ();
+ #pragma omp target update if (1) from (h)
+ }
+ #pragma omp target data device (d) if (1) map (to: h)
+ {
+ #pragma omp target device (d) if (1)
+ if (omp_get_level () != 0 || (f && !omp_is_initial_device ()) || h++ != 13)
+ abort ();
+ #pragma omp target update device (d) if (1) from (h)
+ }
+ if (h != 14)
+ abort ();
+}
+
+int
+main ()
+{
+ foo (0);
+ foo (1);
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/taskgroup-1.c b/libgomp/testsuite/libgomp.c/taskgroup-1.c
new file mode 100644
index 00000000000..641a3bc0f2c
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/taskgroup-1.c
@@ -0,0 +1,83 @@
+extern
+#ifdef __cplusplus
+"C"
+#endif
+void abort (void);
+int v[16] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
+
+int
+main ()
+{
+ #pragma omp parallel num_threads (4)
+ #pragma omp single
+ {
+ int i;
+ #pragma omp taskgroup
+ {
+ for (i = 0; i < 16; i += 2)
+ #pragma omp task
+ {
+ #pragma omp task
+ v[i]++;
+ #pragma omp task
+ v[i + 1]++;
+ }
+ }
+ for (i = 0; i < 16; i++)
+ if (v[i] != i + 2)
+ abort ();
+ #pragma omp taskgroup
+ {
+ for (i = 0; i < 16; i += 2)
+ #pragma omp task
+ {
+ #pragma omp task
+ v[i]++;
+ #pragma omp task
+ v[i + 1]++;
+ #pragma omp taskwait
+ }
+ }
+ for (i = 0; i < 16; i++)
+ if (v[i] != i + 3)
+ abort ();
+ #pragma omp taskgroup
+ {
+ for (i = 0; i < 16; i += 2)
+ #pragma omp task
+ {
+ #pragma omp task
+ v[i]++;
+ v[i + 1]++;
+ }
+ #pragma omp taskwait
+ for (i = 0; i < 16; i += 2)
+ #pragma omp task
+ v[i + 1]++;
+ }
+ for (i = 0; i < 16; i++)
+ if (v[i] != i + 4 + (i & 1))
+ abort ();
+ #pragma omp taskgroup
+ {
+ for (i = 0; i < 16; i += 2)
+ {
+ #pragma omp taskgroup
+ {
+ #pragma omp task
+ v[i]++;
+ #pragma omp task
+ v[i + 1]++;
+ }
+ if (v[i] != i + 5 || v[i + 1] != i + 7)
+ abort ();
+ #pragma omp task
+ v[i]++;
+ }
+ }
+ for (i = 0; i < 16; i++)
+ if (v[i] != i + 6)
+ abort ();
+ }
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/thread-limit-1.c b/libgomp/testsuite/libgomp.c/thread-limit-1.c
new file mode 100644
index 00000000000..6cc716bee89
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/thread-limit-1.c
@@ -0,0 +1,41 @@
+/* { dg-do run } */
+/* { dg-set-target-env-var OMP_THREAD_LIMIT "6" } */
+
+#include <stdlib.h>
+#include <unistd.h>
+
+int
+main ()
+{
+ if (omp_get_thread_limit () != 6)
+ return 0;
+ omp_set_dynamic (0);
+ omp_set_nested (1);
+ #pragma omp parallel num_threads (3)
+ if (omp_get_num_threads () != 3)
+ abort ();
+ #pragma omp parallel num_threads (3)
+ if (omp_get_num_threads () != 3)
+ abort ();
+ #pragma omp parallel num_threads (8)
+ if (omp_get_num_threads () > 6)
+ abort ();
+ #pragma omp parallel num_threads (6)
+ if (omp_get_num_threads () != 6)
+ abort ();
+ int cnt = 0;
+ #pragma omp parallel num_threads (5)
+ #pragma omp parallel num_threads (5)
+ #pragma omp parallel num_threads (2)
+ {
+ int v;
+ #pragma omp atomic capture
+ v = ++cnt;
+ if (v > 6)
+ abort ();
+ usleep (10000);
+ #pragma omp atomic
+ --cnt;
+ }
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/thread-limit-2.c b/libgomp/testsuite/libgomp.c/thread-limit-2.c
new file mode 100644
index 00000000000..0fc9dae0fd1
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/thread-limit-2.c
@@ -0,0 +1,57 @@
+/* { dg-do run } */
+/* { dg-set-target-env-var OMP_THREAD_LIMIT "9" } */
+
+#include <stdlib.h>
+#include <unistd.h>
+
+int
+main ()
+{
+ if (omp_get_thread_limit () != 9)
+ return 0;
+ omp_set_dynamic (0);
+ #pragma omp parallel num_threads (8)
+ if (omp_get_num_threads () != 8)
+ abort ();
+ #pragma omp parallel num_threads (16)
+ if (omp_get_num_threads () > 9)
+ abort ();
+ #pragma omp target if (0)
+ #pragma omp teams thread_limit (6)
+ {
+ if (omp_get_thread_limit () > 6)
+ abort ();
+ if (omp_get_thread_limit () == 6)
+ {
+ omp_set_dynamic (0);
+ omp_set_nested (1);
+ #pragma omp parallel num_threads (3)
+ if (omp_get_num_threads () != 3)
+ abort ();
+ #pragma omp parallel num_threads (3)
+ if (omp_get_num_threads () != 3)
+ abort ();
+ #pragma omp parallel num_threads (8)
+ if (omp_get_num_threads () > 6)
+ abort ();
+ #pragma omp parallel num_threads (6)
+ if (omp_get_num_threads () != 6)
+ abort ();
+ int cnt = 0;
+ #pragma omp parallel num_threads (5)
+ #pragma omp parallel num_threads (5)
+ #pragma omp parallel num_threads (2)
+ {
+ int v;
+ #pragma omp atomic capture
+ v = ++cnt;
+ if (v > 6)
+ abort ();
+ usleep (10000);
+ #pragma omp atomic
+ --cnt;
+ }
+ }
+ }
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/thread-limit-3.c b/libgomp/testsuite/libgomp.c/thread-limit-3.c
new file mode 100644
index 00000000000..af9bd7887ab
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/thread-limit-3.c
@@ -0,0 +1,12 @@
+#include <stdlib.h>
+#include <omp.h>
+
+int
+main ()
+{
+ #pragma omp target if (0)
+ #pragma omp teams thread_limit (1)
+ if (omp_get_thread_limit () != 1)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/udr-1.c b/libgomp/testsuite/libgomp.c/udr-1.c
new file mode 100644
index 00000000000..ea9da72526e
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/udr-1.c
@@ -0,0 +1,81 @@
+/* { dg-do run } */
+
+extern
+#ifdef __cplusplus
+"C"
+#endif
+void abort ();
+
+struct S { int s; struct S *t; };
+
+void
+foo (struct S *out, struct S *in)
+{
+ out->s += in->s;
+}
+
+void
+bar (struct S *x)
+{
+ if (x->s != 6) abort ();
+ x->s = 15;
+}
+
+void
+baz (struct S *x, struct S *y)
+{
+ x->s = 6;
+ x->t = x;
+ (void) y;
+}
+
+#pragma omp declare reduction (foo: struct S: foo (&omp_out, &omp_in)) \
+ initializer (omp_priv = { 8, &omp_priv })
+#pragma omp declare reduction (foo: char, int, short: omp_out += omp_in - 4) \
+ initializer (omp_priv = 4)
+#pragma omp declare reduction (+: struct S: foo (&omp_out, &omp_in)) \
+ initializer (baz (&omp_priv, &omp_orig))
+
+void
+test (struct S s, struct S t)
+{
+ int q = 0;
+ #pragma omp parallel num_threads (4) reduction (+: s, q) reduction (foo: t)
+ {
+ if (s.s != 6 || s.t != &s || t.s != 8 || t.t != &t)
+ abort ();
+ s.s = 2;
+ t.s = 3;
+ q = 1;
+ }
+ if (s.s != 12 + 2 * q || t.s != 14 + 3 * q)
+ abort ();
+}
+
+int
+main ()
+{
+ struct S s, t;
+ s.s = 9; t.s = 10;
+ int h = 30, v = 2, q = 0;
+ #pragma omp declare reduction (foo: struct S: omp_out.s *= omp_in.s) \
+ initializer (omp_priv = omp_orig)
+ {
+ #pragma omp declare reduction (foo: struct S: omp_out.s += omp_in.s) \
+ initializer (omp_priv = omp_orig)
+ #pragma omp parallel num_threads (4) reduction (+: t, q) \
+ reduction (min: h) reduction (foo: s, v)
+ {
+ if (s.s != 9 || t.s != 6 || v != 4 || h != __INT_MAX__) abort ();
+ asm volatile ("" : "+m" (s.s), "+m" (t.s));
+ asm volatile ("" : "+r" (h), "+r" (v));
+ h = t.s; s.s++; t.s++; v++; q++;
+ }
+ }
+ if (h != 6 || s.s != 9 + q * 10 || t.s != 10 + q * 7 || v != 2 + q)
+ abort ();
+ s.s = 12;
+ t.s = 14;
+ test (s, t);
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/udr-2.c b/libgomp/testsuite/libgomp.c/udr-2.c
new file mode 100644
index 00000000000..b58b5c781ab
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/udr-2.c
@@ -0,0 +1,27 @@
+/* { dg-do run } */
+
+extern void abort ();
+
+struct S { int s; };
+
+#pragma omp declare reduction (+:struct S:omp_out.s += omp_in.s)
+#pragma omp declare reduction (foo:struct S:omp_out.s += omp_in.s)
+#pragma omp declare reduction (foo:int:omp_out += omp_in)
+
+int
+main ()
+{
+ int u = 0, q = 0;
+ struct S s, t;
+ s.s = 0; t.s = 0;
+ #pragma omp parallel reduction(+:s, q) reduction(foo:t, u)
+ {
+ if (s.s != 0 || t.s != 0 || u != 0 || q != 0) abort ();
+ s.s = 6;
+ t.s = 8;
+ u = 9;
+ q++;
+ }
+ if (s.s != 6 * q || t.s != 8 * q || u != 9 * q) abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/udr-3.c b/libgomp/testsuite/libgomp.c/udr-3.c
new file mode 100644
index 00000000000..e0a5b8764df
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/udr-3.c
@@ -0,0 +1,32 @@
+/* { dg-do run } */
+
+extern void abort ();
+
+struct S;
+void foo (struct S *, struct S *);
+#pragma omp declare reduction (+:struct S:foo (&omp_out, &omp_in))
+struct S { int s; };
+
+void
+foo (struct S *x, struct S *y)
+{
+ x->s += y->s;
+}
+
+int
+main ()
+{
+ struct S s;
+ int i = 0;
+ s.s = 0;
+ #pragma omp parallel reduction (+:s, i)
+ {
+ if (s.s != 0)
+ abort ();
+ s.s = 2;
+ i = 1;
+ }
+ if (s.s != 2 * i)
+ abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.fortran/fortran.exp b/libgomp/testsuite/libgomp.fortran/fortran.exp
index b7fef293a22..e0bffe390b7 100644
--- a/libgomp/testsuite/libgomp.fortran/fortran.exp
+++ b/libgomp/testsuite/libgomp.fortran/fortran.exp
@@ -15,6 +15,9 @@ set quadmath_library_path "../libquadmath/.libs"
# Initialize dg.
dg-init
+# Turn on OpenMP.
+lappend ALWAYS_CFLAGS "additional_flags=-fopenmp"
+
if { $blddir != "" } {
lappend ALWAYS_CFLAGS "additional_flags=-fintrinsic-modules-path=${blddir}"
# Look for a static libgfortran first.
diff --git a/libgomp/testsuite/libgomp.fortran/lib1.f90 b/libgomp/testsuite/libgomp.fortran/lib1.f90
index 8840018674a..e7e1c748a31 100644
--- a/libgomp/testsuite/libgomp.fortran/lib1.f90
+++ b/libgomp/testsuite/libgomp.fortran/lib1.f90
@@ -66,6 +66,7 @@
!$omp parallel reduction (.or.:l) if (.true.)
l = .not. omp_in_parallel ()
!$omp end parallel
+ if (l) call abort
e = omp_get_wtime ()
if (d .gt. e) call abort
diff --git a/libgomp/testsuite/libgomp.fortran/lib2.f b/libgomp/testsuite/libgomp.fortran/lib2.f
index 75510827043..20db04a1c5f 100644
--- a/libgomp/testsuite/libgomp.fortran/lib2.f
+++ b/libgomp/testsuite/libgomp.fortran/lib2.f
@@ -66,6 +66,7 @@ C$OMP END PARALLEL
C$OMP PARALLEL REDUCTION (.OR.:L) IF (.TRUE.)
L = .NOT. OMP_IN_PARALLEL ()
C$OMP END PARALLEL
+ IF (L) CALL ABORT
E = OMP_GET_WTIME ()
IF (D .GT. E) CALL ABORT
diff --git a/libgomp/testsuite/libgomp.fortran/lib3.f b/libgomp/testsuite/libgomp.fortran/lib3.f
index fa7b227c0ef..264a377e5dd 100644
--- a/libgomp/testsuite/libgomp.fortran/lib3.f
+++ b/libgomp/testsuite/libgomp.fortran/lib3.f
@@ -66,6 +66,7 @@ C$OMP END PARALLEL
C$OMP PARALLEL REDUCTION (.OR.:L) IF (.TRUE.)
L = .NOT. OMP_IN_PARALLEL ()
C$OMP END PARALLEL
+ IF (L) CALL ABORT
E = OMP_GET_WTIME ()
IF (D .GT. E) CALL ABORT
diff --git a/libgomp/testsuite/libgomp.fortran/openmp_version-1.f b/libgomp/testsuite/libgomp.fortran/openmp_version-1.f
new file mode 100644
index 00000000000..aaa888189b1
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/openmp_version-1.f
@@ -0,0 +1,9 @@
+! { dg-do run }
+
+ program main
+ implicit none
+ include "omp_lib.h"
+
+ if (openmp_version .ne. 201107) call abort;
+
+ end program main
diff --git a/libgomp/testsuite/libgomp.fortran/openmp_version-2.f90 b/libgomp/testsuite/libgomp.fortran/openmp_version-2.f90
new file mode 100644
index 00000000000..b2d1d261f27
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/openmp_version-2.f90
@@ -0,0 +1,9 @@
+! { dg-do run }
+
+program main
+ use omp_lib
+ implicit none
+
+ if (openmp_version .ne. 201107) call abort;
+
+end program main
diff --git a/libgomp/testsuite/libgomp.graphite/force-parallel-1.c b/libgomp/testsuite/libgomp.graphite/force-parallel-1.c
index 8c40e34dfc0..008c9d76f0f 100644
--- a/libgomp/testsuite/libgomp.graphite/force-parallel-1.c
+++ b/libgomp/testsuite/libgomp.graphite/force-parallel-1.c
@@ -26,6 +26,6 @@ int main(void)
/* Check that parallel code generation part make the right answer. */
/* { dg-final { scan-tree-dump-times "1 loops carried no dependency" 1 "graphite" } } */
/* { dg-final { cleanup-tree-dump "graphite" } } */
-/* { dg-final { scan-tree-dump-times "loopfn" 5 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "loopfn" 4 "optimized" } } */
/* { dg-final { cleanup-tree-dump "parloops" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/libgomp/testsuite/libgomp.graphite/force-parallel-2.c b/libgomp/testsuite/libgomp.graphite/force-parallel-2.c
index 1ce0feb2506..f80401b6a7b 100644
--- a/libgomp/testsuite/libgomp.graphite/force-parallel-2.c
+++ b/libgomp/testsuite/libgomp.graphite/force-parallel-2.c
@@ -25,6 +25,6 @@ int main(void)
/* Check that parallel code generation part make the right answer. */
/* { dg-final { scan-tree-dump-times "2 loops carried no dependency" 1 "graphite" } } */
/* { dg-final { cleanup-tree-dump "graphite" } } */
-/* { dg-final { scan-tree-dump-times "loopfn" 5 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "loopfn" 4 "optimized" } } */
/* { dg-final { cleanup-tree-dump "parloops" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/libgomp/testsuite/libgomp.graphite/force-parallel-3.c b/libgomp/testsuite/libgomp.graphite/force-parallel-3.c
index ff8680bf03c..4a2d323e7b1 100644
--- a/libgomp/testsuite/libgomp.graphite/force-parallel-3.c
+++ b/libgomp/testsuite/libgomp.graphite/force-parallel-3.c
@@ -32,7 +32,7 @@ int main(void)
/* Check that parallel code generation part make the right answer. */
/* { dg-final { scan-tree-dump-times "4 loops carried no dependency" 1 "graphite" } } */
/* { dg-final { cleanup-tree-dump "graphite" } } */
-/* { dg-final { scan-tree-dump-times "loopfn.0" 5 "optimized" } } */
-/* { dg-final { scan-tree-dump-times "loopfn.1" 5 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "loopfn.0" 4 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "loopfn.1" 4 "optimized" } } */
/* { dg-final { cleanup-tree-dump "parloops" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/libgomp/testsuite/libgomp.graphite/force-parallel-4.c b/libgomp/testsuite/libgomp.graphite/force-parallel-4.c
index 825bda5c439..0bfb0d010ef 100644
--- a/libgomp/testsuite/libgomp.graphite/force-parallel-4.c
+++ b/libgomp/testsuite/libgomp.graphite/force-parallel-4.c
@@ -50,7 +50,7 @@ int main(void)
/* { dg-final { scan-tree-dump-times "1 loops carried no dependency" 1 "graphite" } } */
/* { dg-final { scan-tree-dump-times "2 loops carried no dependency" 1 "graphite" } } */
/* { dg-final { cleanup-tree-dump "graphite" } } */
-/* { dg-final { scan-tree-dump-times "loopfn.0" 5 "optimized" } } */
-/* { dg-final { scan-tree-dump-times "loopfn.1" 5 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "loopfn.0" 4 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "loopfn.1" 4 "optimized" } } */
/* { dg-final { cleanup-tree-dump "parloops" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/libgomp/testsuite/libgomp.graphite/force-parallel-5.c b/libgomp/testsuite/libgomp.graphite/force-parallel-5.c
index 5c944dcee61..4912d4743b8 100644
--- a/libgomp/testsuite/libgomp.graphite/force-parallel-5.c
+++ b/libgomp/testsuite/libgomp.graphite/force-parallel-5.c
@@ -33,7 +33,7 @@ int main(void)
/* Check that parallel code generation part make the right answer. */
/* { dg-final { scan-tree-dump-times "1 loops carried no dependency" 1 "graphite" } } */
/* { dg-final { cleanup-tree-dump "graphite" } } */
-/* { dg-final { scan-tree-dump-times "loopfn.0" 5 "optimized" } } */
-/* { dg-final { scan-tree-dump-times "loopfn.1" 5 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "loopfn.0" 4 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "loopfn.1" 4 "optimized" } } */
/* { dg-final { cleanup-tree-dump "parloops" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/libgomp/testsuite/libgomp.graphite/force-parallel-6.c b/libgomp/testsuite/libgomp.graphite/force-parallel-6.c
index d04c120324b..50716303eaf 100644
--- a/libgomp/testsuite/libgomp.graphite/force-parallel-6.c
+++ b/libgomp/testsuite/libgomp.graphite/force-parallel-6.c
@@ -34,6 +34,6 @@ int main(void)
/* Check that parallel code generation part make the right answer. */
/* { dg-final { scan-tree-dump-times "1 loops carried no dependency" 1 "graphite" } } */
/* { dg-final { cleanup-tree-dump "graphite" } } */
-/* { dg-final { scan-tree-dump-times "loopfn.0" 5 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "loopfn.0" 4 "optimized" } } */
/* { dg-final { cleanup-tree-dump "parloops" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/libgomp/testsuite/libgomp.graphite/force-parallel-7.c b/libgomp/testsuite/libgomp.graphite/force-parallel-7.c
index 2fbe10a4e5c..04dd01d174b 100644
--- a/libgomp/testsuite/libgomp.graphite/force-parallel-7.c
+++ b/libgomp/testsuite/libgomp.graphite/force-parallel-7.c
@@ -33,6 +33,6 @@ int main (void)
/* Check that parallel code generation part make the right answer. */
/* { dg-final { scan-tree-dump-times "3 loops carried no dependency" 1 "graphite" } } */
/* { dg-final { cleanup-tree-dump "graphite" } } */
-/* { dg-final { scan-tree-dump-times "loopfn.0" 5 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "loopfn.0" 4 "optimized" } } */
/* { dg-final { cleanup-tree-dump "parloops" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/libgomp/testsuite/libgomp.graphite/force-parallel-8.c b/libgomp/testsuite/libgomp.graphite/force-parallel-8.c
index f9ce9686fef..e2ed0ecb868 100644
--- a/libgomp/testsuite/libgomp.graphite/force-parallel-8.c
+++ b/libgomp/testsuite/libgomp.graphite/force-parallel-8.c
@@ -47,7 +47,7 @@ int main(void)
/* { dg-final { scan-tree-dump-times "3 loops carried no dependency" 1 "graphite" } } */
/* { dg-final { scan-tree-dump-times "5 loops carried no dependency" 1 "graphite" } } */
/* { dg-final { cleanup-tree-dump "graphite" } } */
-/* { dg-final { scan-tree-dump-times "loopfn.0" 5 "optimized" } } */
-/* { dg-final { scan-tree-dump-times "loopfn.1" 5 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "loopfn.0" 4 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "loopfn.1" 4 "optimized" } } */
/* { dg-final { cleanup-tree-dump "parloops" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/libgomp/testsuite/libgomp.graphite/force-parallel-9.c b/libgomp/testsuite/libgomp.graphite/force-parallel-9.c
index 1de43c36740..e0008801acc 100644
--- a/libgomp/testsuite/libgomp.graphite/force-parallel-9.c
+++ b/libgomp/testsuite/libgomp.graphite/force-parallel-9.c
@@ -31,7 +31,7 @@ int main(void)
/* Check that parallel code generation part make the right answer. */
/* { dg-final { scan-tree-dump-times "4 loops carried no dependency" 1 "graphite" } } */
/* { dg-final { cleanup-tree-dump "graphite" } } */
-/* { dg-final { scan-tree-dump-times "loopfn.0" 5 "optimized" } } */
-/* { dg-final { scan-tree-dump-times "loopfn.1" 5 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "loopfn.0" 4 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "loopfn.1" 4 "optimized" } } */
/* { dg-final { cleanup-tree-dump "parloops" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/libgomp/testsuite/libgomp.graphite/graphite.exp b/libgomp/testsuite/libgomp.graphite/graphite.exp
index 08aa5095cf9..9129964eb19 100644
--- a/libgomp/testsuite/libgomp.graphite/graphite.exp
+++ b/libgomp/testsuite/libgomp.graphite/graphite.exp
@@ -42,6 +42,9 @@ set PARALLEL_CFLAGS "-ansi -pedantic-errors -O2 \
# Initialize `dg'.
dg-init
+# Turn on OpenMP.
+lappend ALWAYS_CFLAGS "additional_flags=-fopenmp"
+
# Gather a list of all tests.
set tests [lsort [find $srcdir/$subdir *.c]]
diff --git a/libgomp/work.c b/libgomp/work.c
index 591242740af..9c5a327263b 100644
--- a/libgomp/work.c
+++ b/libgomp/work.c
@@ -221,7 +221,10 @@ gomp_work_share_end (void)
if (gomp_barrier_last_thread (bstate))
{
if (__builtin_expect (thr->ts.last_work_share != NULL, 1))
- free_work_share (team, thr->ts.last_work_share);
+ {
+ team->work_shares_to_free = thr->ts.work_share;
+ free_work_share (team, thr->ts.last_work_share);
+ }
}
gomp_team_barrier_wait_end (&team->barrier, bstate);
@@ -229,6 +232,32 @@ gomp_work_share_end (void)
}
/* The current thread is done with its current work sharing construct.
+ This version implies a cancellable barrier at the end of the work-share. */
+
+bool
+gomp_work_share_end_cancel (void)
+{
+ struct gomp_thread *thr = gomp_thread ();
+ struct gomp_team *team = thr->ts.team;
+ gomp_barrier_state_t bstate;
+
+ /* Cancellable work sharing constructs cannot be orphaned. */
+ bstate = gomp_barrier_wait_cancel_start (&team->barrier);
+
+ if (gomp_barrier_last_thread (bstate))
+ {
+ if (__builtin_expect (thr->ts.last_work_share != NULL, 1))
+ {
+ team->work_shares_to_free = thr->ts.work_share;
+ free_work_share (team, thr->ts.last_work_share);
+ }
+ }
+ thr->ts.last_work_share = NULL;
+
+ return gomp_team_barrier_wait_cancel_end (&team->barrier, bstate);
+}
+
+/* The current thread is done with its current work sharing construct.
This version does NOT imply a barrier at the end of the work-share. */
void
@@ -259,6 +288,9 @@ gomp_work_share_end_nowait (void)
#endif
if (completed == team->nthreads)
- free_work_share (team, thr->ts.last_work_share);
+ {
+ team->work_shares_to_free = thr->ts.work_share;
+ free_work_share (team, thr->ts.last_work_share);
+ }
thr->ts.last_work_share = NULL;
}
diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog
index 89e108a8da6..cda181e1066 100644
--- a/libiberty/ChangeLog
+++ b/libiberty/ChangeLog
@@ -1,3 +1,43 @@
+2013-10-29 Marc Glisse <marc.glisse@inria.fr>
+
+ PR tree-optimization/58689
+ * concat.c: Remove note about xmalloc.
+
+2013-10-27 Gerald Pfeifer <gerald@pfeifer.com>
+
+ * testsuite/test-demangle.c: Include unistd.h.
+
+2013-10-25 Gary Benson <gbenson@redhat.com>
+
+ * cp-demangle.c (struct d_saved_scope): New structure.
+ (struct d_print_info): New fields saved_scopes and
+ num_saved_scopes.
+ (d_print_init): Initialize the above.
+ (d_print_free): New function.
+ (cplus_demangle_print_callback): Call the above.
+ (d_copy_templates): New function.
+ (d_print_comp): New variables saved_templates and
+ need_template_restore.
+ [DEMANGLE_COMPONENT_REFERENCE,
+ DEMANGLE_COMPONENT_RVALUE_REFERENCE]: Capture scope the first
+ time the component is traversed, and use the captured scope for
+ subsequent traversals.
+ * testsuite/demangle-expected: Add regression test.
+
+2013-10-23 Gerald Pfeifer <gerald@pfeifer.com>
+
+ * testsuite/test-expandargv.c: Include unistd.h.
+
+2013-10-15 David Malcolm <dmalcolm@redhat.com>
+
+ * configure.ac: If --enable-host-shared, use -fPIC.
+ * configure: Regenerate.
+
+2013-10-11 Paul Pluzhnikov <ppluzhnikov@google.com>
+
+ * cp-demangle.c (d_name): Demangle local-source-names.
+ * testsuite/demangle-expected: New test.
+
2013-09-10 Paolo Carlini <paolo.carlini@oracle.com>
PR bootstrap/58386
@@ -73,7 +113,7 @@
* hashtab.c (hash_pointer): Remove conditional and avoid
unexecuted shift equal to wordsize.
-2013-04-22 Andi Kleen <ak@linux.intel.com>
+2013-04-22 Andi Kleen <ak@linux.intel.com>
* hashtab.c (hash_pointer): Move to end of file and reimplement.
@@ -647,12 +687,12 @@
* aclocal.m4 (AC_LANG_FUNC_LINK_TRY(C)): Delete.
* configure: Regenerate.
-2010-10-07 Andi Kleen <ak@linux.intel.com>
+2010-10-07 Andi Kleen <ak@linux.intel.com>
* configure: Regenerate.
* configure.ac: Turn PR_SET_NAME check into link check.
-2010-10-06 Andi Kleen <ak@linux.intel.com>
+2010-10-06 Andi Kleen <ak@linux.intel.com>
* Makefile.in (CFILES): Add setproctitle.
(CONFIGURED_OFILES): Add setproctitle.
diff --git a/libiberty/concat.c b/libiberty/concat.c
index 9779d5663b6..4144d8305cc 100644
--- a/libiberty/concat.c
+++ b/libiberty/concat.c
@@ -25,23 +25,11 @@ Boston, MA 02110-1301, USA. */
@dots{}, @code{NULL})
Concatenate zero or more of strings and return the result in freshly
-@code{xmalloc}ed memory. Returns @code{NULL} if insufficient memory is
-available. The argument list is terminated by the first @code{NULL}
-pointer encountered. Pointers to empty strings are ignored.
+@code{xmalloc}ed memory. The argument list is terminated by the first
+@code{NULL} pointer encountered. Pointers to empty strings are ignored.
@end deftypefn
-NOTES
-
- This function uses xmalloc() which is expected to be a front end
- function to malloc() that deals with low memory situations. In
- typical use, if malloc() returns NULL then xmalloc() diverts to an
- error handler routine which never returns, and thus xmalloc will
- never return a NULL pointer. If the client application wishes to
- deal with low memory situations itself, it should supply an xmalloc
- that just directly invokes malloc and blindly returns whatever
- malloc returns.
-
*/
diff --git a/libiberty/configure b/libiberty/configure
index e601ccd99f4..b71141a98b0 100755
--- a/libiberty/configure
+++ b/libiberty/configure
@@ -4963,6 +4963,12 @@ case "${enable_shared}" in
"") shared=no ;;
*) shared=yes ;;
esac
+
+# ...unless --enable-host-shared was passed from top-level config:
+if [ "${enable_host_shared}" = "yes" ]; then
+ shared=yes
+fi
+
if [ "${shared}" != "yes" ]; then
PICFLAG=
fi
diff --git a/libiberty/configure.ac b/libiberty/configure.ac
index fcea46f6c7b..4ad88a984d7 100644
--- a/libiberty/configure.ac
+++ b/libiberty/configure.ac
@@ -225,6 +225,12 @@ case "${enable_shared}" in
"") shared=no ;;
*) shared=yes ;;
esac
+
+# ...unless --enable-host-shared was passed from top-level config:
+if [[ "${enable_host_shared}" = "yes" ]]; then
+ shared=yes
+fi
+
if [[ "${shared}" != "yes" ]]; then
PICFLAG=
fi
diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c
index 70f54389c89..7be98048565 100644
--- a/libiberty/cp-demangle.c
+++ b/libiberty/cp-demangle.c
@@ -275,6 +275,18 @@ struct d_growable_string
int allocation_failure;
};
+/* A demangle component and some scope captured when it was first
+ traversed. */
+
+struct d_saved_scope
+{
+ /* The component whose scope this is. */
+ const struct demangle_component *container;
+ /* The list of templates, if any, that was current when this
+ scope was captured. */
+ struct d_print_template *templates;
+};
+
enum { D_PRINT_BUFFER_LENGTH = 256 };
struct d_print_info
{
@@ -302,6 +314,10 @@ struct d_print_info
int pack_index;
/* Number of d_print_flush calls so far. */
unsigned long int flush_count;
+ /* Array of saved scopes for evaluating substitutions. */
+ struct d_saved_scope *saved_scopes;
+ /* Number of saved scopes in the above array. */
+ int num_saved_scopes;
};
#ifdef CP_DEMANGLE_DEBUG
@@ -1276,7 +1292,6 @@ d_name (struct d_info *di)
case 'Z':
return d_local_name (di);
- case 'L':
case 'U':
return d_unqualified_name (di);
@@ -1323,6 +1338,7 @@ d_name (struct d_info *di)
return dc;
}
+ case 'L':
default:
dc = d_unqualified_name (di);
if (d_peek_char (di) == 'I')
@@ -3665,6 +3681,30 @@ d_print_init (struct d_print_info *dpi, demangle_callbackref callback,
dpi->opaque = opaque;
dpi->demangle_failure = 0;
+
+ dpi->saved_scopes = NULL;
+ dpi->num_saved_scopes = 0;
+}
+
+/* Free a print information structure. */
+
+static void
+d_print_free (struct d_print_info *dpi)
+{
+ int i;
+
+ for (i = 0; i < dpi->num_saved_scopes; i++)
+ {
+ struct d_print_template *ts, *tn;
+
+ for (ts = dpi->saved_scopes[i].templates; ts != NULL; ts = tn)
+ {
+ tn = ts->next;
+ free (ts);
+ }
+ }
+
+ free (dpi->saved_scopes);
}
/* Indicate that an error occurred during printing, and test for error. */
@@ -3749,6 +3789,7 @@ cplus_demangle_print_callback (int options,
demangle_callbackref callback, void *opaque)
{
struct d_print_info dpi;
+ int success;
d_print_init (&dpi, callback, opaque);
@@ -3756,7 +3797,9 @@ cplus_demangle_print_callback (int options,
d_print_flush (&dpi);
- return ! d_print_saw_error (&dpi);
+ success = ! d_print_saw_error (&dpi);
+ d_print_free (&dpi);
+ return success;
}
/* Turn components into a human readable string. OPTIONS is the
@@ -3913,6 +3956,36 @@ d_print_subexpr (struct d_print_info *dpi, int options,
d_append_char (dpi, ')');
}
+/* Return a shallow copy of the current list of templates.
+ On error d_print_error is called and a partial list may
+ be returned. Whatever is returned must be freed. */
+
+static struct d_print_template *
+d_copy_templates (struct d_print_info *dpi)
+{
+ struct d_print_template *src, *result, **link = &result;
+
+ for (src = dpi->templates; src != NULL; src = src->next)
+ {
+ struct d_print_template *dst =
+ malloc (sizeof (struct d_print_template));
+
+ if (dst == NULL)
+ {
+ d_print_error (dpi);
+ break;
+ }
+
+ dst->template_decl = src->template_decl;
+ *link = dst;
+ link = &dst->next;
+ }
+
+ *link = NULL;
+
+ return result;
+}
+
/* Subroutine to handle components. */
static void
@@ -3923,6 +3996,13 @@ d_print_comp (struct d_print_info *dpi, int options,
without needing to modify *dc. */
const struct demangle_component *mod_inner = NULL;
+ /* Variable used to store the current templates while a previously
+ captured scope is used. */
+ struct d_print_template *saved_templates;
+
+ /* Nonzero if templates have been stored in the above variable. */
+ int need_template_restore = 0;
+
if (dc == NULL)
{
d_print_error (dpi);
@@ -4291,12 +4371,56 @@ d_print_comp (struct d_print_info *dpi, int options,
const struct demangle_component *sub = d_left (dc);
if (sub->type == DEMANGLE_COMPONENT_TEMPLATE_PARAM)
{
- struct demangle_component *a = d_lookup_template_argument (dpi, sub);
+ struct demangle_component *a;
+ struct d_saved_scope *scope = NULL, *scopes;
+ int i;
+
+ for (i = 0; i < dpi->num_saved_scopes; i++)
+ if (dpi->saved_scopes[i].container == sub)
+ scope = &dpi->saved_scopes[i];
+
+ if (scope == NULL)
+ {
+ /* This is the first time SUB has been traversed.
+ We need to capture the current templates so
+ they can be restored if SUB is reentered as a
+ substitution. */
+ ++dpi->num_saved_scopes;
+ scopes = realloc (dpi->saved_scopes,
+ sizeof (struct d_saved_scope)
+ * dpi->num_saved_scopes);
+ if (scopes == NULL)
+ {
+ d_print_error (dpi);
+ return;
+ }
+
+ dpi->saved_scopes = scopes;
+ scope = dpi->saved_scopes + (dpi->num_saved_scopes - 1);
+
+ scope->container = sub;
+ scope->templates = d_copy_templates (dpi);
+ if (d_print_saw_error (dpi))
+ return;
+ }
+ else
+ {
+ /* This traversal is reentering SUB as a substition.
+ Restore the original templates temporarily. */
+ saved_templates = dpi->templates;
+ dpi->templates = scope->templates;
+ need_template_restore = 1;
+ }
+
+ a = d_lookup_template_argument (dpi, sub);
if (a && a->type == DEMANGLE_COMPONENT_TEMPLATE_ARGLIST)
a = d_index_template_argument (a, dpi->pack_index);
if (a == NULL)
{
+ if (need_template_restore)
+ dpi->templates = saved_templates;
+
d_print_error (dpi);
return;
}
@@ -4344,6 +4468,9 @@ d_print_comp (struct d_print_info *dpi, int options,
dpi->modifiers = dpm.next;
+ if (need_template_restore)
+ dpi->templates = saved_templates;
+
return;
}
diff --git a/libiberty/testsuite/demangle-expected b/libiberty/testsuite/demangle-expected
index 1259e4a9f49..ae872078d91 100644
--- a/libiberty/testsuite/demangle-expected
+++ b/libiberty/testsuite/demangle-expected
@@ -4291,3 +4291,9 @@ void m<void () &&>(void (A::*)() &&)
--format=gnu-v3
_Z1nIM1AKFvvREEvT_
void n<void (A::*)() const &>(void (A::*)() const &)
+--format=gnu-v3
+_ZL1fIiEvv
+void f<int>()
+--format=gnu-v3
+_ZSt7forwardIRN1x14refobjiteratorINS0_3refINS0_4mime30multipart_section_processorObjIZ15get_body_parserIZZN14mime_processor21make_section_iteratorERKNS2_INS3_10sectionObjENS0_10ptrrefBaseEEEbENKUlvE_clEvEUlSB_bE_ZZNS6_21make_section_iteratorESB_bENKSC_clEvEUlSB_E0_ENS1_INS2_INS0_20outputrefiteratorObjIiEES8_EEEERKSsSB_OT_OT0_EUlmE_NS3_32make_multipart_default_discarderISP_EEEES8_EEEEEOT_RNSt16remove_referenceISW_E4typeE
+x::refobjiterator<x::ref<x::mime::multipart_section_processorObj<x::refobjiterator<x::ref<x::outputrefiteratorObj<int>, x::ptrrefBase> > get_body_parser<mime_processor::make_section_iterator(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)#1}, mime_processor::make_section_iterator(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> const&)#2}>(std::string const&, x::ref<x::mime::sectionObj, x::ptrrefBase> const&, mime_processor::make_section_iterator(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)#1}&&, mime_processor::make_section_iterator(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> const&)#2}&&)::{lambda(unsigned long)#1}, x::mime::make_multipart_default_discarder<mime_processor::make_section_iterator(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)#1}&&> >, x::ptrrefBase> >& std::forward<x::refobjiterator<x::ref<x::mime::multipart_section_processorObj<x::refobjiterator<x::ref<x::outputrefiteratorObj<int>, x::ptrrefBase> > get_body_parser<mime_processor::make_section_iterator(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)#1}, mime_processor::make_section_iterator(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> const&)#2}>(std::string const&, x::ref<x::mime::sectionObj, x::ptrrefBase> const&, mime_processor::make_section_iterator(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)#1}&&, mime_processor::make_section_iterator(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> const&)#2}&&)::{lambda(unsigned long)#1}, x::mime::make_multipart_default_discarder<mime_processor::make_section_iterator(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)#1}&&> >, x::ptrrefBase> >&>(std::remove_reference<x::mime::multipart_section_processorObj<x::refobjiterator<x::ref<x::outputrefiteratorObj<int>, x::ptrrefBase> > get_body_parser<mime_processor::make_section_iterator(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)#1}, mime_processor::make_section_iterator(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> const&)#2}>(std::string const&, x::ref<x::mime::sectionObj, x::ptrrefBase> const&, mime_processor::make_section_iterator(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)#1}&&, mime_processor::make_section_iterator(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> const&)#2}&&)::{lambda(unsigned long)#1}, x::mime::make_multipart_default_discarder<mime_processor::make_section_iterator(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)#1}&&> > >::type&)
diff --git a/libiberty/testsuite/test-demangle.c b/libiberty/testsuite/test-demangle.c
index 11d9729999b..44062478c09 100644
--- a/libiberty/testsuite/test-demangle.c
+++ b/libiberty/testsuite/test-demangle.c
@@ -32,6 +32,9 @@
#if HAVE_STDLIB_H
# include <stdlib.h>
#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
struct line
{
diff --git a/libiberty/testsuite/test-expandargv.c b/libiberty/testsuite/test-expandargv.c
index dff20d41daf..0edd751722b 100644
--- a/libiberty/testsuite/test-expandargv.c
+++ b/libiberty/testsuite/test-expandargv.c
@@ -40,6 +40,9 @@
#ifdef HAVE_STRING_H
#include <string.h>
#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
#ifndef EXIT_SUCCESS
#define EXIT_SUCCESS 0
diff --git a/libitm/ChangeLog b/libitm/ChangeLog
index adf42308ef3..28f8a227f20 100644
--- a/libitm/ChangeLog
+++ b/libitm/ChangeLog
@@ -1,3 +1,7 @@
+2013-09-20 Alan Modra <amodra@gmail.com>
+
+ * configure: Regenerate.
+
2013-08-30 Torvald Riegel <triegel@redhat.com>
* config/posix/rwlock.cc: Fix initialization order.
diff --git a/libitm/configure b/libitm/configure
index fc77641242b..031c19ce337 100644
--- a/libitm/configure
+++ b/libitm/configure
@@ -667,7 +667,6 @@ CXX
am__fastdepCC_FALSE
am__fastdepCC_TRUE
CCDEPMODE
-am__nodep
AMDEPBACKSLASH
AMDEP_FALSE
AMDEP_TRUE
@@ -3319,11 +3318,11 @@ MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
# We need awk for the "check" target. The system "awk" is bad on
# some platforms.
-# Always define AMTAR for backward compatibility. Yes, it's still used
-# in the wild :-( We should find a proper way to deprecate it ...
-AMTAR='$${TAR-tar}'
+# Always define AMTAR for backward compatibility.
-am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'
+AMTAR=${AMTAR-"${am_missing_run}tar"}
+
+am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'
@@ -4221,7 +4220,6 @@ fi
if test "x$enable_dependency_tracking" != xno; then
am_depcomp="$ac_aux_dir/depcomp"
AMDEPBACKSLASH='\'
- am__nodep='_no'
fi
if test "x$enable_dependency_tracking" != xno; then
AMDEP_TRUE=
@@ -4246,7 +4244,6 @@ else
# 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'.
- rm -rf conftest.dir
mkdir conftest.dir
# Copy depcomp to subdir because otherwise we won't find it if we're
# using a relative directory.
@@ -4306,7 +4303,7 @@ else
break
fi
;;
- msvc7 | msvc7msys | msvisualcpp | msvcmsys)
+ msvisualcpp | msvcmsys)
# This compiler won't grok `-c -o', but also, the minuso test has
# not run yet. These depmodes are late enough in the game, and
# so weak that their functioning should not be impacted.
@@ -4631,7 +4628,6 @@ else
# 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'.
- rm -rf conftest.dir
mkdir conftest.dir
# Copy depcomp to subdir because otherwise we won't find it if we're
# using a relative directory.
@@ -4691,7 +4687,7 @@ else
break
fi
;;
- msvc7 | msvc7msys | msvisualcpp | msvcmsys)
+ msvisualcpp | msvcmsys)
# This compiler won't grok `-c -o', but also, the minuso test has
# not run yet. These depmodes are late enough in the game, and
# so weak that their functioning should not be impacted.
@@ -4766,7 +4762,6 @@ else
# 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'.
- rm -rf conftest.dir
mkdir conftest.dir
# Copy depcomp to subdir because otherwise we won't find it if we're
# using a relative directory.
@@ -4824,7 +4819,7 @@ else
break
fi
;;
- msvc7 | msvc7msys | msvisualcpp | msvcmsys)
+ msvisualcpp | msvcmsys)
# This compiler won't grok `-c -o', but also, the minuso test has
# not run yet. These depmodes are late enough in the game, and
# so weak that their functioning should not be impacted.
@@ -7275,7 +7270,7 @@ ia64-*-hpux*)
rm -rf conftest*
;;
-x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \
+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
@@ -7300,7 +7295,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
;;
esac
;;
- ppc64-*linux*|powerpc64-*linux*)
+ powerpc64le-*linux*)
+ LD="${LD-ld} -m elf32lppclinux"
+ ;;
+ powerpc64-*linux*)
LD="${LD-ld} -m elf32ppclinux"
;;
s390x-*linux*)
@@ -7319,7 +7317,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
x86_64-*linux*)
LD="${LD-ld} -m elf_x86_64"
;;
- ppc*-*linux*|powerpc*-*linux*)
+ powerpcle-*linux*)
+ LD="${LD-ld} -m elf64lppc"
+ ;;
+ powerpc-*linux*)
LD="${LD-ld} -m elf64ppc"
;;
s390*-*linux*|s390*-*tpf*)
@@ -11784,7 +11785,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11787 "configure"
+#line 11788 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -11890,7 +11891,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11893 "configure"
+#line 11894 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
diff --git a/libjava/ChangeLog b/libjava/ChangeLog
index 23a6accf5df..cda2ed09fd9 100644
--- a/libjava/ChangeLog
+++ b/libjava/ChangeLog
@@ -1,3 +1,7 @@
+2013-09-20 Alan Modra <amodra@gmail.com>
+
+ * configure: Regenerate.
+
2013-06-20 Roland Lutz <rlutz@hedmen.org>
* contrib/aot-compile.in: Fix typo in option list.
diff --git a/libjava/classpath/ChangeLog b/libjava/classpath/ChangeLog
index 49815367045..4d9f1a6e49c 100644
--- a/libjava/classpath/ChangeLog
+++ b/libjava/classpath/ChangeLog
@@ -1,3 +1,7 @@
+2013-09-20 Alan Modra <amodra@gmail.com>
+
+ * configure: Regenerate.
+
2013-05-22 Mark Mitchell <mark@codesourcery.com>
Sandra Loosemore <sandra@codesourcery.com>
diff --git a/libjava/classpath/configure b/libjava/classpath/configure
index 6def45cf7e8..bcb5bff1c18 100755
--- a/libjava/classpath/configure
+++ b/libjava/classpath/configure
@@ -7630,7 +7630,7 @@ ia64-*-hpux*)
rm -rf conftest*
;;
-x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \
+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
@@ -7655,7 +7655,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
;;
esac
;;
- ppc64-*linux*|powerpc64-*linux*)
+ powerpc64le-*linux*)
+ LD="${LD-ld} -m elf32lppclinux"
+ ;;
+ powerpc64-*linux*)
LD="${LD-ld} -m elf32ppclinux"
;;
s390x-*linux*)
@@ -7674,7 +7677,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
x86_64-*linux*)
LD="${LD-ld} -m elf_x86_64"
;;
- ppc*-*linux*|powerpc*-*linux*)
+ powerpcle-*linux*)
+ LD="${LD-ld} -m elf64lppc"
+ ;;
+ powerpc-*linux*)
LD="${LD-ld} -m elf64ppc"
;;
s390*-*linux*|s390*-*tpf*)
@@ -11873,7 +11879,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11876 "configure"
+#line 11882 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -11979,7 +11985,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11982 "configure"
+#line 11988 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -25353,7 +25359,7 @@ else
JAVA_TEST=Object.java
CLASS_TEST=Object.class
cat << \EOF > $JAVA_TEST
-/* #line 25356 "configure" */
+/* #line 25362 "configure" */
package java.lang;
public class Object
@@ -25446,7 +25452,7 @@ EOF
if uudecode$EXEEXT Test.uue; then
ac_cv_prog_uudecode_base64=yes
else
- echo "configure: 25449: uudecode had trouble decoding base 64 file 'Test.uue'" >&5
+ echo "configure: 25455: uudecode had trouble decoding base 64 file 'Test.uue'" >&5
echo "configure: failed file was:" >&5
cat Test.uue >&5
ac_cv_prog_uudecode_base64=no
@@ -25474,7 +25480,7 @@ JAVA_TEST=Test.java
CLASS_TEST=Test.class
TEST=Test
cat << \EOF > $JAVA_TEST
-/* [#]line 25477 "configure" */
+/* [#]line 25483 "configure" */
public class Test {
public static void main (String args[]) {
System.exit (0);
@@ -25682,7 +25688,7 @@ if test "x${use_glibj_zip}" = xfalse || \
JAVA_TEST=Test.java
CLASS_TEST=Test.class
cat << \EOF > $JAVA_TEST
- /* #line 25685 "configure" */
+ /* #line 25691 "configure" */
public class Test
{
public static void main(String args)
diff --git a/libjava/configure b/libjava/configure
index 6eb11bd2b96..55443608c0c 100755
--- a/libjava/configure
+++ b/libjava/configure
@@ -8842,7 +8842,7 @@ ia64-*-hpux*)
rm -rf conftest*
;;
-x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \
+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
@@ -8867,7 +8867,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
;;
esac
;;
- ppc64-*linux*|powerpc64-*linux*)
+ powerpc64le-*linux*)
+ LD="${LD-ld} -m elf32lppclinux"
+ ;;
+ powerpc64-*linux*)
LD="${LD-ld} -m elf32ppclinux"
;;
s390x-*linux*)
@@ -8886,7 +8889,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
x86_64-*linux*)
LD="${LD-ld} -m elf_x86_64"
;;
- ppc*-*linux*|powerpc*-*linux*)
+ powerpcle-*linux*)
+ LD="${LD-ld} -m elf64lppc"
+ ;;
+ powerpc-*linux*)
LD="${LD-ld} -m elf64ppc"
;;
s390*-*linux*|s390*-*tpf*)
@@ -13382,7 +13388,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 13385 "configure"
+#line 13391 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -13488,7 +13494,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 13491 "configure"
+#line 13497 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -19483,7 +19489,7 @@ if test "${enable_sjlj_exceptions+set}" = set; then :
enableval=$enable_sjlj_exceptions; :
else
cat > conftest.$ac_ext << EOF
-#line 19486 "configure"
+#line 19492 "configure"
struct S { ~S(); };
void bar();
void foo()
diff --git a/libjava/libltdl/ChangeLog b/libjava/libltdl/ChangeLog
index df5ce43462d..c00e5192e3e 100644
--- a/libjava/libltdl/ChangeLog
+++ b/libjava/libltdl/ChangeLog
@@ -1,3 +1,9 @@
+2013-09-20 Alan Modra <amodra@gmail.com>
+
+ * acinclude.m4 (_LT_ENABLE_LOCK <ld -m flags>): Remove non-canonical
+ ppc host match. Support little-endian powerpc linux hosts.
+ * configure: Regenerate.
+
2011-11-21 Andreas Tobler <andreast@fgznet.ch>
* acinclude.m4: Additional FreeBSD 10 fixes.
diff --git a/libjava/libltdl/acinclude.m4 b/libjava/libltdl/acinclude.m4
index d77a1a3990d..f08911950fd 100644
--- a/libjava/libltdl/acinclude.m4
+++ b/libjava/libltdl/acinclude.m4
@@ -519,7 +519,7 @@ ia64-*-hpux*)
rm -rf conftest*
;;
-x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*)
+x86_64-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*)
# Find out which ABI we are using.
echo 'int i;' > conftest.$ac_ext
if AC_TRY_EVAL(ac_compile); then
@@ -529,7 +529,10 @@ x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*)
x86_64-*linux*)
LD="${LD-ld} -m elf_i386"
;;
- ppc64-*linux*|powerpc64-*linux*)
+ powerpc64le-*linux*)
+ LD="${LD-ld} -m elf32lppclinux"
+ ;;
+ powerpc64-*linux*)
LD="${LD-ld} -m elf32ppclinux"
;;
s390x-*linux*)
@@ -545,7 +548,10 @@ x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*)
x86_64-*linux*)
LD="${LD-ld} -m elf_x86_64"
;;
- ppc*-*linux*|powerpc*-*linux*)
+ powerpcle-*linux*)
+ LD="${LD-ld} -m elf64lppc"
+ ;;
+ powerpc-*linux*)
LD="${LD-ld} -m elf64ppc"
;;
s390*-*linux*)
diff --git a/libjava/libltdl/configure b/libjava/libltdl/configure
index 35b89dc5551..146ca43299e 100755
--- a/libjava/libltdl/configure
+++ b/libjava/libltdl/configure
@@ -4806,7 +4806,7 @@ ia64-*-hpux*)
rm -rf conftest*
;;
-x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*)
+x86_64-*linux*|powerpc*-*linux*|s390*-*linux*|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
@@ -4820,7 +4820,10 @@ x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*)
x86_64-*linux*)
LD="${LD-ld} -m elf_i386"
;;
- ppc64-*linux*|powerpc64-*linux*)
+ powerpc64le-*linux*)
+ LD="${LD-ld} -m elf32lppclinux"
+ ;;
+ powerpc64-*linux*)
LD="${LD-ld} -m elf32ppclinux"
;;
s390x-*linux*)
@@ -4836,7 +4839,10 @@ x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*)
x86_64-*linux*)
LD="${LD-ld} -m elf_x86_64"
;;
- ppc*-*linux*|powerpc*-*linux*)
+ powerpcle-*linux*)
+ LD="${LD-ld} -m elf64lppc"
+ ;;
+ powerpc-*linux*)
LD="${LD-ld} -m elf64ppc"
;;
s390*-*linux*)
@@ -6456,11 +6462,11 @@ else
-e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:6459: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:6465: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:6463: \$? = $ac_status" >&5
+ echo "$as_me:6469: \$? = $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.
@@ -6718,11 +6724,11 @@ else
-e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:6721: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:6727: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:6725: \$? = $ac_status" >&5
+ echo "$as_me:6731: \$? = $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.
@@ -6780,11 +6786,11 @@ else
-e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:6783: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:6789: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:6787: \$? = $ac_status" >&5
+ echo "$as_me:6793: \$? = $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
@@ -8099,7 +8105,7 @@ linux*)
libsuff=
case "$host_cpu" in
x86_64*|s390x*|powerpc64*)
- echo '#line 8102 "configure"' > conftest.$ac_ext
+ echo '#line 8108 "configure"' > conftest.$ac_ext
if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
(eval $ac_compile) 2>&5
ac_status=$?
@@ -8652,7 +8658,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
-#line 8655 "configure"
+#line 8661 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -8750,7 +8756,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
-#line 8753 "configure"
+#line 8759 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -10591,7 +10597,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
-#line 10594 "configure"
+#line 10600 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
diff --git a/libmudflap/ChangeLog b/libmudflap/ChangeLog
deleted file mode 100644
index 6e0d65c2fb7..00000000000
--- a/libmudflap/ChangeLog
+++ /dev/null
@@ -1,2054 +0,0 @@
-2013-03-14 Jakub Jelinek <jakub@redhat.com>
-
- PR tree-optimization/53265
- * testsuite/libmudflap.c/fail37-frag.c: Add optimization barrier.
-
-2013-02-03 Richard Sandiford <rdsandiford@googlemail.com>
-
- Update copyright years.
-
-2013-01-03 Jakub Jelinek <jakub@redhat.com>
-
- * mf-runtime.c (__mf_usage): Update copyright notice dates.
-
-2012-12-15 Alexandre Oliva <aoliva@redhat.com>
-
- * mf-hooks1.c (free): Return on NULL before any logging.
-
-2012-09-14 David Edelsohn <dje.gcc@gmail.com>
-
- * configure: Regenerated.
-
-2012-07-13 Richard Guenther <rguenther@suse.de>
-
- * testsuite/libmudflap.c++/ctors.exp: Explicitely specify -O0.
- * testsuite/libmudflap.c++/c++frags.exp: Likewise.
- * testsuite/libmudflap.cth/cthfrags.exp: Likewise.
- * testsuite/libmudflap.c/cfrags.exp: Likewise.
- * testsuite/libmudflap.c/externs.exp: Likewise.
-
-2012-07-13 Richard Guenther <rguenther@suse.de>
-
- * testsuite/libmudflap.c/fail11-frag.c: Adjust to not look like memset.
- * testsuite/libmudflap.c/fail12-frag.c: Likewise.
-
-2012-05-29 Joseph Myers <joseph@codesourcery.com>
-
- * mf-impl.h: Fix typo.
-
-2012-05-16 H.J. Lu <hongjiu.lu@intel.com>
-
- * configure: Regenerated.
-
-2012-04-11 Manuel López-Ibáñez <manu@gcc.gnu.org>
-
- PR 24985
- * testsuite/lib/libmudflap.exp: Handle caret.
-
-2012-01-19 Jakub Jelinek <jakub@redhat.com>
-
- PR libmudflap/40778
- * testsuite/libmudflap.c/fail68-frag.c: New test.
-
-2012-01-01 Jakub Jelinek <jakub@redhat.com>
-
- * mf-runtime.c (__mf_usage): Update copyright notice dates.
-
-2011-11-21 Andreas Tobler <andreast@fgznet.ch>
-
- * configure: Regenerate.
-
-2011-07-31 Tom de Vries <tom@codesourcery.com>
-
- PR middle-end/43513
- * testsuite/libmudflap.c/fail31-frag.c: Adapt testcase to prevent
- folding of alloca.
-
-2011-07-25 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
-
- Revert:
- 2011-07-15 Jakub Jelinek <jakub@redhat.com>
-
- PR testsuite/49753
- PR tree-optimization/49309
- * testsuite/libmudflap.c++/pass68-frag.cxx: New test.
-
-2011-07-15 Jakub Jelinek <jakub@redhat.com>
-
- PR testsuite/49753
- PR tree-optimization/49309
- * testsuite/libmudflap.c++/pass68-frag.cxx: New test.
-
-2011-07-13 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
-
- * configure.ac: Don't create pth.
- Check for library containing sched_yield.
- * configure: Regenerate.
- * config.h.in: Regenerate.
-
- * testsuite/lib/libmudflap.exp (libmudflap-init): Use
- mfconfig_libs in -static check.
-
-2011-07-07 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
-
- PR libmudflap/49550
- * mf-runtime.c (__wrap_main) [__sun__ && __svr4__]: Don't register
- stdin, stdout, stderr.
- Register __ctype, __ctype_mask.
-
- * configure.ac: Check for mmap64.
- Check for rawmemchr, stpcpy, mempcpy.
- * configure: Regenerate.
- * config.h.in: Regenerate.
- * mf-hooks1.c [HAVE_MMAP64] (__mf_0fn_mmap64): New function.
- (mmap64): New wrapper function.
- * mf-impl.h (__mf_dynamic_index) [HAVE_MMAP64]: Add dyn_mmap64.
- * mf-runtime.c (__mf_dynamic) [HAVE_MMAP64]: Handle mmap64.
-
- * mf-hooks2.c [HAVE_GETMNTENT && HAVE_SYS_MNTTAB_H]: Implement
- getmntent wrapper.
-
- * mf-hooks3.c (_REENTRANT): Define.
-
- * testsuite/libmudflap.c/heap-scalestress.c (SCALE): Reduce to 10000.
-
- * testsuite/libmudflap.c/pass-stratcliff.c: Include ../config.h.
- (MIN): Define.
- Use HAVE_RAWMEMCHR, HAVE_STPCPY, HAVE_MEMPCPY as guards.
-
- * testsuite/libmudflap.c/pass47-frag.c: Expect __ctype warning on
- *-*-solaris2.*.
-
-2011-07-01 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
-
- PR libmudflap/49549
- * testsuite/lib/libmudflap.exp (load_gcc_lib): Load
- target-supports.exp.
- * testsuite/libmudflap.cth/cthfrags.exp: Only pass
- --noinhibit-exec to GNU ld.
-
-2011-06-27 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
-
- PR libmudflap/38738
- * configure.ac: Check for sys/mnttab.h.
- Check for library containing connect.
- * configure: Regenerate.
- * config.h.in: Regenerate.
- * mf-hooks2.c [HAVE_SYS_MNTTAB_H]: Include <sys/mnttab.h>.
- * testsuite/libmudflap.c/pass-stratcliff.c (main) [__sun__ &&
- __svr4__]: Disable rawmemchr, stpcpy, mempcpy tests.
-
-2011-02-13 Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
-
- * configure: Regenerate.
-
-2011-01-03 Jakub Jelinek <jakub@redhat.com>
-
- * mf-runtime.c (__mf_usage): Update copyright notice dates.
-
-2010-10-31 Jason Merrill <jason@redhat.com>
-
- PR testsuite/20003
- * testsuite/libmudflap.cth/pass40-frag.c: Increase timeout to 30.
-
-2010-08-20 Uros Bizjak <ubizjak@gmail.com>
-
- * testsuite/libmudflap.c++/pass41-frag.cxx (dg-prune-output):
- New dg directive.
-
-2010-06-09 Iain Sandoe <iains@gcc.gnu.org>
-
- PR bootstrap/43170
- * configure: Regenerate.
-
-2010-05-16 Uros Bizjak <ubizjak@gmail.com>
-
- * testsuite/libmudflap.c/pass46-frag.c (dg-options): Remove -Wall.
-
-2010-05-15 Uros Bizjak <ubizjak@gmail.com>
-
- * testsuite/lib/mfdg.exp (additional_prunes): New global.
- (dg-test): Clear additional_prunes before test is run.
- (dg-prune-output): New procedure.
- * testsuite/lib/libmudflap.exp (libmudflap-dg-test): Do not call
- prune_gcc_output.
- (libmudflap-dg-prune): New procedure.
- * testsuite/libmudflap.c++/pass57-frag.cxx (dg-prune-output):
- New dg directive.
-
-2010-05-04 Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
-
- PR other/43620
- * configure.ac (AM_INIT_AUTOMAKE): Add no-dist.
- * Makefile.in: Regenerate.
- * testsuite/Makefile.in: Regenerate.
-
-2010-04-02 Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
-
- * Makefile.in: Regenerate.
- * aclocal.m4: Regenerate.
- * testsuite/Makefile.in: Regenerate.
-
-2010-03-15 David S. Miller <davem@davemloft.net>
-
- * testsuite/libmudflap.c/pass54-frag.c: Add explicit return from
- main.
-
-2010-01-09 Jakub Jelinek <jakub@redhat.com>
-
- * mf-runtime.c (__mf_usage): Update copyright notice dates.
-
-2009-12-05 Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
-
- * Makefile.in: Regenerate.
- * configure: Regenerate.
- * testsuite/Makefile.in: Regenerate.
-
-2009-09-22 Frank Ch. Eigler <fche@redhat.com>
-
- PR libmudflap/41433
- * mf-runtime.c (__mf_init): Ignore $MUDFLAP_OPTIONS if
- running setuid or setgid.
-
-2009-09-01 Loren J. Rittle <ljrittle@acm.org>
-
- * mf-runtime.c (__mf_init): Support FreeBSD.
- Prime mutex which calls calloc upon first lock to avoid deadlock.
- * mf-hooks1.c (__mf_0fn_mmap): Support FreeBSD.
- Ignore red zone allocation request for initial thread's stack.
-
-2009-09-01 Loren J. Rittle <ljrittle@acm.org>
- Andreas Schwab <schwab@linux-m68k.org>
-
- * testsuite/libmudflap.c/pass51-frag.c (MAP_FAILED): Define,
- if not in system header; use it. On FreeBSD, must pass fd==-1
- with MAP_ANON flag. Correct mmap error check.
- * testsuite/libmudflap.c/fail40-frag.c: Ditto.
-
-2009-08-24 Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
-
- * configure.ac (AC_PREREQ): Bump to 2.64.
-
-2009-08-22 Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
-
- * Makefile.am (install-html, install-pdf): Remove.
- * Makefile.in: Regenerate.
-
- * Makefile.in: Regenerate.
- * aclocal.m4: Regenerate.
- * config.h.in: Regenerate.
- * configure: Regenerate.
- * testsuite/Makefile.in: Regenerate.
-
-2009-07-30 Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
-
- * configure.ac (_AC_ARG_VAR_PRECIOUS): Use m4_rename_force.
-
-2009-07-16 Joseph Myers <joseph@codesourcery.com>
-
- * configure: Regenerate.
-
-2009-07-11 Richard Sandiford <rdsandiford@googlemail.com>
-
- PR testsuite/40699
- PR testsuite/40707
- PR testsuite/40709
- * testsuite/lib/libmudflap.exp: Revert 2009-06-30 commit.
-
-2009-07-01 Richard Guenther <rguenther@suse.de>
-
- PR tree-optimization/19831
- * testsuite/libmudflap.c/fail11-frag.c: Make allocated memory
- escape.
- * testsuite/libmudflap.c/fail12-frag.c: Likewise.
- * testsuite/libmudflap.c/fail16-frag.c: Likewise.
- * testsuite/libmudflap.c/fail31-frag.c: Likewise.
-
-2009-06-30 Richard Sandiford <r.sandiford@uk.ibm.com>
-
- * testsuite/lib/libmudflap.exp (libmudflap-init): Don't add "."
- to ld_library_path. Use add_path. Add just find_libgcc_s to
- ld_library_path, not every libgcc multilib directory.
-
-2009-04-09 Nick Clifton <nickc@redhat.com>
-
- * mf-hooks1.c: Change copyright header to refer to version 3
- of the GNU General Public License with version 3.1 of the GCC
- Runtime Library Exception and to point readers at the COPYING3
- and COPYING3.RUNTIME files and the FSF's license web page.
- * mf-heuristics.c: Likewise.
- * mf-hooks2.c: Likewise.
- * mf-hooks3.c: Likewise.
- * mf-impl.h: Likewise.
- * mf-runtime.c: Likewise.
- * mf-runtime.h: Likewise.
-
-2009-04-09 Jakub Jelinek <jakub@redhat.com>
-
- * testsuite/lib/mfdg.exp: Change copyright header to refer to
- version 3 of the GNU General Public License and to point readers
- at the COPYING3 file and the FSF's license web page.
- * testsuite/lib/libmudflap.exp: Likewise.
-
-2009-03-31 Ben Elliston <bje@au.ibm.com>
-
- PR libmudflap/38462
- * testsuite/libmudflap.c/fail27-frag.c: Match `mudflap dead
- object', not `mudflap object'.
-
-2009-03-01 Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
-
- * configure: Regenerate.
-
-2009-02-03 Jakub Jelinek <jakub@redhat.com>
-
- * mf-runtime.c (__mf_usage): Update copyright notice dates.
-
-2009-01-23 Jie Zhang <jie.zhang@analog.com>
-
- * mf-impl.h (__mf_get_state, __mf_set_state): Don't use
- __thread when TLS support is emulated.
- * mf-hooks3.c (__mf_get_state, __mf_set_state): Likewise.
- * mf-runtime.c (__mf_state_1): Likewise.
- * configure.ac: Use GCC_CHECK_EMUTLS.
- * configure: Regenerate.
- * config.h.in: Regenerate.
-
-2008-12-18 Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
-
- * configure: Regenerate.
-
-2008-11-26 Janis Johnson <janis187@us.ibm.com>
-
- PR testsuite/28870
- * testsuite/lib/mfdg.exp (dg-test): Use new timeout support.
- (dg-timeout): Remove.
- (standard-wait): Remove.
- * testsuite/lib/libmudflap.exp: Include new timeout library files.
- (libmudflap_target_compile): Set timeout value from new proc.
-
-2008-11-10 Jakub Jelinek <jakub@redhat.com>
-
- PR middle-end/35314
- * testsuite/libmudflap.c/pass67-frag.c: New test.
-
-2008-10-09 Jakub Jelinek <jakub@redhat.com>
-
- PR c++/37568
- * testsuite/libmudflap.c++/pass66-frag.cxx: New test.
-
-2008-09-26 Peter O'Gorman <pogma@thewrittenword.com>
- Steve Ellcey <sje@cup.hp.com>
-
- * configure: Regenerate for new libtool.
- * Makefile.in: Ditto.
- * testsuite/Makefile.in: Ditto.
-
-2008-09-15 Jakub Jelinek <jakub@redhat.com>
-
- PR libmudflap/36397
- * testsuite/libmudflap.c/pass64-frag.c: New test.
-
-2008-06-17 Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
-
- * Makefile.in: Regenerate.
- * config.h.in: Regenerate.
- * configure: Regenerate.
- * testsuite/Makefile.in: Regenerate.
-
-2008-04-18 Paolo Bonzini <bonzini@gnu.org>
-
- PR bootstrap/35457
- * aclocal.m4: Regenerate.
- * configure: Regenerate.
-
-2008-03-20 Volker Reichelt <v.reichelt@netcologne.de>
-
- * testsuite/libmudflap.c/pass63-frag.c: New test.
-
-2008-03-16 Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
-
- * aclocal.m4: Regenerate.
- * configure: Likewise.
- * Makefile.in: Likewise.
- * testsuite/Makefile.in: Likewise.
-
-2008-03-02 Jakub Jelinek <jakub@redhat.com>
-
- * mf-runtime.c (__mf_usage): Update copyright notice dates.
-
-2008-02-21 Uros Bizjak <ubizjak@gmail.com>
-
- * testsuite/libmudflap.c/fail8-frag.c: Adjust scan pattern for
- mudflap dead object.
- * testsuite/libmudflap.c/fail9-frag.c: Ditto.
-
-2008-01-24 David Edelsohn <edelsohn@gnu.org>
-
- * configure: Regenerate.
-
-2008-01-05 Jakub Jelinek <jakub@redhat.com>
-
- PR tree-optimization/34618
- * testsuite/libmudflap.c/pass62-frag.c: New test.
-
-2008-01-03 Jakub Jelinek <jakub@redhat.com>
-
- PR c++/34619
- * testsuite/libmudflap.c++/pass61-frag.cxx: New test.
-
-2008-01-01 Volker Reichelt <v.reichelt@netcologne.de>
-
- PR libmudflap/26442
- * testsuite/libmudflap.c++/pass60-frag.cxx: New test.
-
-2007-10-15 Maciej W. Rozycki <macro@linux-mips.org>
-
- * configure: Regenerate following changes to ../config/tls.m4.
-
-2007-07-26 Tom Tromey <tromey@redhat.com>
-
- * Makefile.in: Rebuilt.
- * Makefile.am (clean-local): Removed.
- (pth/mf-runtime.lo, pth/mf-heuristics.lo, pth/mf-hooks1.lo,
- pth/mf-hooks2.lo, pth/mf-hooks3.lo): Likewise.
- (libmudflapth_la_SOURCES): List sources.
- (libmudflapth_la_LIBADD): Clear.
- (libmudflapth_la_CFLAGS): New variable.
-
-2007-07-05 H.J. Lu <hongjiu.lu@intel.com>
-
- * aclocal.m4: Regenerated.
-
-2007-06-02 Paolo Bonzini <bonzini@gnu.org>
-
- * configure: Regenerate.
-
-2007-05-31 Frank Ch. Eigler <fche@redhat.com>
-
- From Andi Kleen <ak@suse.de>:
- * mf-runtime.c (options): Rename structure for compatibility with
- glibc getopt_long.
-
-2007-05-23 Steve Ellcey <sje@cup.hp.com>
-
- * Makefile.in: Regenerate.
- * configure: Regenerate.
- * aclocal.m4: Regenerate.
- * testsuite/Makefile.in: Regenerate.
-
-2007-03-14 Uros Bizjak <ubizjak@gmail.com>
-
- * testsuite/libmudflap.cth/pass59-frag.c (main): Fix casting of arg.
-
-2007-03-01 Brooks Moses <brooks.moses@codesourcery.com>
-
- * Makefile.am: Add dummy install-pdf target.
- * Makefile.in: Regenerate
-
-2007-02-07 Jakub Jelinek <jakub@redhat.com>
-
- PR libgomp/28468
- * configure: Regenerate.
-
-2006-12-04 Eric Botcazou <ebotcazou@libertysurf.fr>
-
- * configure: Regenerate.
-
-2006-11-13 Daniel Jacobowitz <dan@codesourcery.com>
-
- * configure: Regenerated.
-
-2006-11-10 Frank Ch. Eigler <fche@redhat.com>
-
- PR libmudflap/28578
- * mf-hooks1.c (__mf_0fn_malloc): Make the bootstrap buffers
- static but not function scope static.
- (free): Skip deallocation attempts for objects placed into
- bootstrap buffers.
- * testsuite/libmudflap.cth/pass59-frag.c: New test.
-
-2006-11-06 Frank Ch. Eigler <fche@redhat.com>
-
- From Herman ten Brugge <hermantenbrugge@home.nl>:
- * mf-runtime.c (__mf_uncache_object): Optimize the code so that
- small and large objects are handled a lot faster.
-
-2006-11-06 Frank Ch. Eigler <fche@redhat.com>
-
- * configure.ac (__libc_freeres): Look for it.
- * mf-impl.h (call_libc_freeres): New configuration flag.
- * mf-runtime.c (__mf_set_default_options): Set it by default.
- (__mfu_report): Call it if needed.
- (__mfu_unregister): Remove "unaccessed registered object" warning.
- * configure, config.h.in: Regenerated.
-
-2006-09-18 Tom Tromey <tromey@redhat.com>
-
- * configure: Rebuilt.
-
-2006-06-21 Frank Ch. Eigler <fche@redhat.com>
-
- PR 21274
- mf-runtime.h installation based on ssp patch for PR 26473 from
- Mark Mitchell <mark@codesourcery.com>.
- * configure.ac (ACX_NONCANONICAL_TARGET): Use it.
- * Makefile.am (target_noncanonical): Define.
- (libsubincludedir): New variable.
- (nobase_libsubinclude_HEADERS): Add mf-runtime.h.
- (include_HEADERS): Remove.
- * configure, aclocal.m4, config.h.in: Regenerated.
- * Makefile.in, testsuite/Makefile.in: Likewise.
- * mf-runtime.h: Add #ifndef protection for conflicting _REENTRANT
- and _THREAD_SAFE redefinition values.
-
-2006-05-23 Carlos O'Donell <carlos@codesourcery.com>
-
- * Makefile.am: Add install-html target. Add install-html to .PHONY
- * Makefile.in: Regenerate.
-
-2006-04-19 Volker Reichelt <reichelt@igpm.rwth-aachen.de>
-
- PR mudflap/26789
- * testsuite/libmudflap.c++/error1-frag.cxx: New test.
-
- PR mudflap/26790
- * testsuite/libmudflap.c++/error2-frag.cxx: New test.
-
-2006-04-10 Matthias Klose <doko@debian.org>
-
- * testsuite/lib/libmudflap.exp (libmudflap-init): Recognize multilib
- directory names containing underscores.
-
-2005-11-22 Janis Johnson <janis187@us.ibm.com>
-
- * testsuite/lib/libmudflap.exp (libmudflap-init): Remove -static from
- MUDFLAP_FLAGS if static library not supported.
- * testsuite/libmudflap.c/cfrags.exp (MUDFLAP_FLAGS): new.
- * testsuite/libmudflap.c/externs.exp: Ditto.
- * testsuite/libmudflap.c++/ctors.exp: Ditto.
- * testsuite/libmudflap.c++/c++frags.exp: Ditto.
- * testsuite/libmudflap.cth/cthfrags.exp: Ditto.
-
-2005-10-04 James E Wilson <wilson@specifix.com>
-
- * configure.ac (mudflap_cv_entry_point): Use quadrigraphs to declare
- $name as array of characters with unknown bound. Also store into the
- array.
- * configure: Regenerate.
-
-2005-09-30 James E. Wilson <wilson@specifix.com>
-
- * configure.ac (pthread.h): Use AC_CHECK_HEADERS instead of
- AC_CHECK_HEADER.
- (target_thread_file): New. Set from sed'ed gcc output.
- (posix_threads): New. Set from target_thread_file. Use instead of
- ac_have_pthread_h.
- (pthread_create_version): Move initialization before code using it.
- * configure: Regenerate.
-
- * mf-heuristics.c (_end, ENTRY_POINT): Make them arrays with unknown
- bounds.
-
-2005-09-29 James E. Wilson <wilson@specifix.com>
-
- * mf-hooks1.c (__mf_0fn_mmap, mmap, __mf_0fn_munmap, munmap): Protect
- with HAVE_MMAP ifdef.
-
-2005-09-23 Frank Ch. Eigler <fche@elastic.org>
-
- PR 23084.
- * mf-hooks2.c (accept): Tolerate NULL sockaddr* parameter.
-
-2005-09-23 Frank Ch. Eigler <fche@elastic.org>
-
- * testsuite/libmudflap.c++/pass58-frag.cxx: New test for heisenbug 19319.
-
-2005-09-23 Tom Tromey <tromey@redhat.com>
-
- * aclocal.m4, configure: Rebuilt.
- * configure.ac: Use GCC_CHECK_TLS.
- * acinclude.m4 (LIBMUDFLAP_CHECK_TLS, LIBMUDFLAP_ENABLE): Moved
- to ../config.
-
-2005-08-22 Jim Wilson <wilson@specifix.com>
-
- * mf-hooks2.c (MF_REGISTER_fopen): Define to __MF_TYPE_STATIC when
- __FreeBSD__ is defined.
-
-2005-08-17 Jim Wilson <wilson@specifix.com>
-
- * mf-hooks1.c (malloc, calloc, realloc, free,
- __mf_wrap_alloca_indirect): Call BEGIN_MALLOC_PROTECT before calling
- the real routines, and END_MALLOC_PROTECT afterwards.
- * mf-impl.h (enum __mf_state_enum): Expand comment. Add in_malloc.
- (BEGIN_PROTECT): Handle in_malloc state.
- (BEGIN_MALLOC_PROTECT, END_MALLOC_PROTECT): New.
- * testsuite/libmudflap.c/hook2-allocstuff.c: New.
-
-2005-08-17 Kelley Cook <kcook@gcc.gnu.org>
-
- * All files: Update FSF address.
-
-2005-08-15 Ulrich Weigand <weigand@informatik.uni-erlangen.de>
-
- * mf-hooks3.c (main_seen_p): Remove.
- (__mf_get_state): Remove attempt to recognize the main thread.
-
-2005-08-15 Maciej W. Rozycki <macro@linux-mips.org>
-
- * configure.ac: Test for the name of the symbol used for the entry
- point; define ENTRY_POINT to the result.
- * configure: Regenerate.
- * config.h.in: Regenerate.
- * mf-heuristics.c: Replace _start with ENTRY_POINT throughout.
-
-2005-08-14 Ulrich Weigand <weigand@informatik.uni-erlangen.de>
-
- * mf-runtime.c (__mf_state_1): Initialize to reentrant.
- (__mf_init): Set thread state active.
- * mf-hooks3.c (__mf_pthread_spawner): Always set thread
- state active.
- (pthread_create wrapper): Always use thread spawner.
-
- * testsuite/libmudflap.cth/pass37-frag.c: Increase timeout.
- * testsuite/libmudflap.cth/pass39-frag.c: Likewise.
-
-2005-07-16 Richard Henderson <rth@redhat.com>
-
- * acinclude.m4: New file.
- * configure.ac: Invoke LIBMUDFLAP_CHECK_TLS.
- * configure, config.h.in, Makefile.in, testsuite/Makefile.in: Rebuild.
- * mf-hooks1.c (__mf_0fn_malloc): Move body from ...
- (__mf_0fn_calloc): ... here.
- * mf-hooks3.c (struct pthread_info): Remove.
- (__mf_pthread_info, __mf_pthread_info_idx): Remove.
- (LIBMUDFLAPTH_THREADS_MAX): Set to 1021.
- (struct mf_thread_data): New.
- (mf_thread_data, mf_thread_data_lock): New.
- (__mf_allocate_blank_threadinfo): Remove.
- (__mf_find_threadinfo): Rewrite and simplify. Only use if TLS is
- not available.
- (__mf_state_perthread): Remove.
- (__mf_get_state, __mf_set_state): New.
- (__mf_pthread_cleanup): Use &errno, rather than saved pointer.
- Update mf_thread_data killing procedure.
- (__mf_pthread_spawner): Similarly.
- (__mf_0fn_pthread_create): Only use wrapper if necessary. Remove
- code to allocate thread stack space.
- (__mf_0fn_pthread_join, pthread_join): Remove.
- (__mf_0fn_pthread_exit, pthread_exit): Remove.
- * mf-impl.h (dyn_pthread_join, dyn_pthread_exit): Remove.
- (__mf_state_1): Rename from __mf_state; use TLS when available.
- (__mf_get_state, __mf_set_state): New. Update all users.
- * mf-runtime.c (begin_recursion_protect1): New.
- (BEGIN_RECURSION_PROTECT): Use it.
- (__mf_state_1): Rename from __mf_state; use TLS when available.
- (threads_active_p): Remove.
- (__mf_usage): Compute it directly.
-
-2005-06-19 Ulrich Weigand <uweigand@de.ibm.com>
-
- * testsuite/libmudflap.c/externs-1.c (main): Add return statement.
-
-2005-06-15 Frank Ch. Eigler <fche@redhat.com>
-
- Fix for uncaching bug reported by Herman ten Brugge.
- * mf-runtime.c (__mf_uncache_object): Search whole cache.
- * testsuite/libmudflap.c/fail40-frag.c: New test.
-
-2005-05-23 Alfred M. Szmidt <ams@gnu.org>
-
- PR libmudflap/21724
- * Makefile.am (AM_MAKEFLAGS): Pass includedir.
- * Makefile.in: Amend.
-
-2005-06-14 Frank Ch. Eigler <fche@redhat.com>
-
- PR mudflap/21023
- * testsuite/libmudflap.c/externs.exp, externs-{1,2}.c: New test files.
- * testsuite/libmudflap.c/cfrags.exp: Bypass new sources.
-
-2005-06-14 Frank Ch. Eigler <fche@redhat.com>
-
- PR libmudflap/21094
- * testsuite/libmudflap.c++/*.exp: Assert build tree g++.
-
-2005-06-14 Frank Ch. Eigler <fche@redhat.com>
-
- PR mudflap/22064
- * mf-impl.h (mudflap_mode, violation_mode): Make these ordinary
- unsigned vars with #defines instead of enums.
-
-2005-05-09 Mike Stump <mrs@apple.com>
-
- * configure: Regenerate.
-
-2005-04-12 Mike Stump <mrs@apple.com>
-
- * configure: Regenerate.
-
-2005-04-12 Frank Ch. Eigler <fche@redhat.com>
-
- PR mudflap/19266
- * testsuite/libmudflap.c++/c++frags.exp: Also test -O permutation.
- * testsuite/libmudflap.c++/pass57-frag.cxx: New test.
-
-2005-04-04 Alan Modra <amodra@bigpond.net.au>
-
- * mf-runtime.c (__mfu_unregister): Warning fix for char unsigned.
-
-2005-03-31 Mike Stump <mrs@apple.com>
-
- * mf-runtime.h: Add libmudflap copyright clause.
-
-2005-03-21 Mike Stump <mrs@apple.com>
-
- * mf-heuristics.c: Fix whitespace at end of line.
- * mf-hooks1.c: Likewise.
- * mf-hooks2.c: Likewise.
- * mf-hooks3.c: Likewise.
- * mf-impl.h: Likewise.
- * mf-runtime.c: Likewise.
- * mf-runtime.h: Likewise.
-
-2005-03-21 Zack Weinberg <zack@codesourcery.com>
-
- * configure.ac: Do not invoke TL_AC_GCC_VERSION.
- In all substitutions, expand gcc_version in Makefile.
- * aclocal.m4, configure: Regenerate.
- * Makefile.am: Set gcc_version.
- * Makefile.in, testsuite/Makefile.in: Regenerate.
-
-2005-03-17 Frank Ch. Eigler <fche@redhat.com>
-
- * mf-runtime.c (__mfu_check): Respect ignore_reads configuration.
- * testsuite/libmudflap.c/{pass56,fail39}-frag.c: New tests.
-
-2005-02-13 Frank Ch. Eigler <fche@redhat.com>
-
- PR mudflap/19319
- * testsuite/libmudflap.c++/pass55-frag.c: New test.
-
-2005-01-05 Richard Henderson <rth@redhat.com>
-
- * testsuite/libmudflap.c/pass32-frag.c: Fix typo.
-
-2005-01-02 Greg McGary <greg@mcgary.org>
-
- * mf-impl.h (uintptr_t): Get typedef via stdint.h or define explicitly.
- * mf-runtime.h: New file, replaces mf-runtime.h.in.
- * configure.ac (AC_CONFIG_FILES): mf-runtime.h is no longer generated.
- * Makefile.in: Ditto.
- * testsuite/lib/libmudflap.exp: Add -I${srcdir}/.. to get mf-runtime.h
- * testsuite/libmudflap.c/pass32-frag.c: s/uintptr_t/__mf_uintptr_t/
- * testsuite/libmudflap.c/fail36-frag.c: New test.
- * testsuite/libmudflap.c/fail37-frag.c: New test.
- * testsuite/libmudflap.c/fail38-frag.c: New test.
-
-2004-12-08 Kelley Cook <kcook@gcc.gnu.org>
-
- * Makefile.am: Add ../config to ACLOCAL_AMFLAGS.
- * aclocal.m4, Makefile.in, testsuite/Makefile.in: Regenerate.
-
-2004-12-02 Richard Sandiford <rsandifo@redhat.com>
-
- * configure.ac: Use TL_AC_GCC_VERSION to set gcc_version.
- * aclocal.m4: Include ../config/gcc-version.m4.
- * configure, Makefile.in, testsuite/Makefile.in: Regenerate.
-
-2004-11-29 Kelley Cook <kcook@gcc.gnu.org>
-
- * Makefile.am: Define ACLOCAL_AMFLAGS.
- * acinclude.m4: Remove.
- * stamp-h.in: Remove superfluous stamp file.
- * aclocal.m4, configure, Makefile.in: Regenerate.
- * testsuite/Makefile.in: Likewise.
-
-2004-11-24 Kelley Cook <kcook@gcc.gnu.org>
-
- * Makefile.am: Revert previous.
- * acinclude.m4: Restore.
- * aclocal.m4, configure, Makefile.in: Regenerate.
- * testsuite/Makefile.in: Likewise.
-
-2004-11-24 Kelley Cook <kcook@gcc.gnu.org>
-
- * Makefile.am: Define ACLOCAL_AMFLAGS.
- * acinclude.m4: Remove.
- * aclocal.m4, configure, Makefile.in: Regenerate.
- * testsuite/Makefile.in: Likewise.
-
-2004-11-23 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
-
- * testsuite/lib/libmudflap.exp: Use new procs in target-libpath.exp.
-
-2004-11-23 Kelley Cook <kcook@gcc.gnu.org>
-
- * Makefile.in, configure, aclocal.m4: Regenerate with automake 1.9.3.
- * testsuite/Makefile.in: Likewise.
-
-2004-11-01 Andreas Schwab <schwab@suse.de>
-
- * configure.ac: (target_alias): Default to $host_alias, not
- $target.
- * configure: Regenerated.
-
-2004-10-28 Frank Ch. Eigler <fche@redhat.com>
-
- * testsuite/libmudflap.c/fail35-,pass53-,pass54-frag.c: New tests.
- * testsuite/libmudflap.c/pass35-frag.c: Correct embedded warning
- message.
-
-2004-10-25 Eric Botcazou <ebotcazou@libertysurf.fr>
-
- PR other/18138
- * testsuite/lib/libmudflap.exp: Accept more than one multilib libgcc.
-
-2004-10-12 Frank Ch. Eigler <fche@redhat.com>
-
- * configure.ac: Check for more headers, functions.
- * mf-hooks2.c (mkbuffer, unmkbuffer): New helper functions for
- tracking overridden FILE buffers.
- (fopen, setvbuf): New/revised hook functions for buffer overriding.
- (setbuf,setlinebuf,fdopen,freopen,fopen64,freopen64,fclose): Ditto.
- (fflush): Accept given NULL stream (means "all streams").
- * mf-runtime.h.in:
- * mf-runtime.c (__mfu_check): Accept accesses that span adjacent
- HEAP/GUESS objects.
- (LOOKUP_CACHE_SIZE_MAX): Raise to 64K entries tentatively.
- (__mf_adapt_cache): Use them all.
- * testsuite/libmudflap.c/pass35-frag.c: Update warning message.
- * testsuite/libmudflap.c++/ctors.exp: Ditto.
- * testsuite/libmudflap.c/{pass51,pass52}-frag.c: New tests.
- * configure, config.h.in: Regenerated.
-
-2004-10-05 Frank Ch. Eigler <fche@redhat.com>
-
- * configure.ac: Checking for sys/socket.h once is enough.
- * configure: Regenerated.
-
-2004-10-04 Frank Ch. Eigler <fche@redhat.com>
-
- * configure.ac: Look for more headers & functions.
- * mf-hooks2.c (getmntent, inet_ntoa, getproto*): New wrapper functions.
- * mf-runtime.h.in: Add new "#pragma redefine_extname"s for them.
- * mf-runtime.c (options): Clean up integer signedness warnings.
- (main): Add a declaration to fix a warning.
- * mf-hooks3.c (pthread_exit): Add not-reached exit() to wrapper.
- * configure, config.h.in: Regenerated.
-
-2004-10-02 Frank Ch. Eigler <fche@redhat.com>
-
- * testsuite/libmudflap.c/pass50-frag.c, fail33-frag.c, fail34-frag.c:
- New tests for proper base/limit checking for aggregates.
-
-2004-09-15 Joseph S. Myers <jsm@polyomino.org.uk>
-
- * testsuite/libmudflap.c/pass35-frag.c: Update expected message.
-
-2004-09-07 Frank Ch. Eigler <fche@redhat.com>
-
- * configure.ac: Look for pwd.h, grp.h, netdb.h headers and functions.
- * mf-hooks2.c (strerror): Unregister previous string returned by
- previous strerror.
- (getlogin,cuserid,getpwnam,getpwuid,getgrnam,getgrgid): New wrappers.
- (getservent,getservbyname,getservbyport,gai_strerror): Ditto.
- * mf-runtime.h.in: Add redefine_extname pragmas for them all.
- * mf-runtime.c (__mf_describe_object): Clarify object life status.
- * testsuite/libmudflap.c/pass48-frag.c, pass49-frag.c, fail32-frag.c:
- New tests.
- * configure, config.h.in: Regenerated.
-
-2004-08-03 Dale Johannesen <dalej@apple.com>
-
- * mf-runtime.c: Conditionalize POSIX_SOURCE for Darwin.
-
-2004-08-03 Frank Ch. Eigler <fche@redhat.com>
-
- * mf-runtime.c (compare_uintptr_t): Remove function. Inline
- simplified contents in all former callers.
-
-2004-07-27 Ulrich Weigand <weigand@informatik.uni-erlangen.de>
-
- * mf-runtime.c (__mf_fini): Set mudflap_mode to mode_nop in
- the statically linked case.
-
-2004-07-27 Frank Ch. Eigler <fche@redhat.com>
-
- * splay-tree.[ch]: Remove. Merge contents into ...
- * mf-runtime.c: ... here, renaming symbols and making all functions
- static. Remove unused min/max functions.
- * Makefile.am: Forget about splay-tree.[ch].
- * Makefile.in, testsuite/Makefile.in: Regenerated.
-
-2004-07-21 Frank Ch. Eigler <fche@redhat.com>
-
- * mf-runtime.c (__mfu_check): Remove mistaken mode-nop handling.
- (__mfu_usage): Include (C) 2004.
- * mf-hooks3.c (__mf_find_threadinfo): Don't call tracing functions
- here. Include a comment explaining why.
-
-2004-07-20 Frank Ch. Eigler <fche@redhat.com>
-
- * mf-impl.h (__mf_options): Add ignore_reads and timestamps fields.
- * mf-runtime.c (options): Give them a name.
- (__mf_set_default_options): Set them.
- (__mf_insert_new_object, __mfu_unregister): Optionalize timestamps.
- (__mf_violation): Warning cleanup.
- * mf-impl.h (MF_VALIDATE_EXTENT): Support ignore_reads option.
- * splay-tree.c (splay_tree_delete_helper): Remove obsolete decl.
-
-2004-07-15 Frank Ch. Eigler <fche@redhat.com>
-
- g++/15861
- * mf-runtime.c (__mf_init): Make it non-static. Tolerate
- repeated invocation.
-
-2004-07-09 Frank Ch. Eigler <fche@redhat.com>
-
- Test case for g++/15861
- * testsuite/libmudflap.c++/ctors-[12].cxx: New test case halves.
- * testsuite/libmudflap.c++/ctors.exp: Driver.
- * testsuite/libmudflap.c++/c++frags.exp: Elide redundant default.
- Look only for *frag* test cases.
-
-2004-07-08 Frank Ch. Eigler <fche@redhat.com>
-
- ANSI C conversion, libmudflap specialization, recursion limiting.
- * splay-tree.h (splay_tree_{de,}allocate_fn): Remove allocation_data
- argument and indirection function pointers, update callers.
- (splay_tree_s): Add statistics and recursion control fields
- num_keys, max_depth, depth, rebalance_p.
- * splay-tree.c (splay_tree_splay_helper): Track recursion depth.
- Back out of search if it exceeds limit.
- (splay_tree_splay): Manage recursion limiting with rebalancing as
- needed.
- (splay_tree_new): More initialization.
- (splay_tree_rebalance): New function.
- (splay_tree_foreach): Rewrite using nonrecursive logic.
- (splay_tree_xmalloc_allocate, splay_tree_xmalloc_deallocate):
- Remove. Point indirect calls to mf-runtime.c's routines.
- (splay_tree_compare_ints, splay_tree_compare_pointers): Remove unused
- functions.
- (splay_tree_delete, splay_tree_delete_helper): Ditto.
- * testsuite/heap-scalestress.c: New test based on one from
- Eyal Lebedinsky <eyal@eyal.emu.id.au>:
-
-2004-07-05 Matthias Klose <doko@debian.org>
-
- * libtool-version: New.
- * Makefile.am (libmudflap_la_LDFLAGS, libmudflapth_la_LDFLAGS):
- Use -version-info for soname.
- * Makefile.in: Regenerate.
- * configure.ac: Remove libtool_VERSION macro
- * configure: Regenerate
-
-2004-07-05 Zack Weinberg <zack@codesourcery.com>
-
- * mf-runtime.h.in: Wrap declarations of struct __mf_cache,
- __mf_lookup_cache, __mf_lc_mask, or __mf_lc_shift in
- #ifndef _MUDFLAP.
-
-2004-06-29 Frank Ch. Eigler <fche@redhat.com>
-
- Splay tree implementation fork.
- * splay-tree.c, splay-tree.h: Copied & modified from libiberty.
- Use hard-coded comparison function for uintptr_t. Remove key/value
- deallocation logic. Cache last splayed key for consecutive lookups.
- * Makefile.am, Makefile.in: Use them, don't link to them.
- * mf-runtime.c (__mf_object_tree): Adapt to simpler splay_tree_new.
- (__mf_find_objects2): Flip successor/predecessor search sequence.
- * ansidecl.h, libiberty.h: Removed dummy files.
-
-2004-06-29 Nick Clifton <nickc@redhat.com>
-
- * configure.ac (AC_CHECK_HEADERS): Add dirent.h
- * configure: Regenerate.
- * mf-hooks2.c: Surround uses of dirent.h with #ifdef
- HAVE_DIRENT_H.
- Remove spurious inclusion of <strings.h>.
-
-2004-06-29 Nick Clifton <nickc@redhat.com>
-
- * mf-runtime.c (pthread_join): Only apply the weak pragma if the
- function actually exists.
-
-2004-06-25 Frank Ch. Eigler <fche@redhat.com>
-
- * ansidecl.h, libiberty.h: New dummy files for building splay-tree.
- * config.h.in: Regenerated.
-
-2004-06-24 Frank Ch. Eigler <fche@redhat.com>
-
- Adopt splay trees for object database.
- * Makefile.am: Copy splay-tree.* from libiberty.
- * Makefile.in, testsuite/Makefile.in: Regenerated.
- * mf-runtime.h.in (__mf_unregister): Add third parameter (type).
- * mf-hooks[123].c (*): Add new third parameter to mf_unregister.
- * mf-impl.h (BEGIN_PROTECT): Remove some trace text.
- * mf-runtime.c: Rewrite code dealing with object database to use
- libiberty splay trees. Remove tree liveness aging option.
- * testsuite/libmudflap.c/fail18-frag.c: Add volatile flag.
-
-2004-06-15 Paolo Bonzini <bonzini@gnu.org>
-
- * configure.ac: New name of configure.in. Update
- AC_INIT, AC_CONFIG_SRCDIR, AC_CONFIG_HEADERS, AC_CONFIG_FILES,
- AC_OUTPUT, AM_INIT_AUTOMAKE to the preferred style for
- Autoconf 2.5x and Automake 1.7 or later.
- * configure.in: Remove.
- * configure: Regenerate.
-
- * Makefile.am: Remove useless multilib rules.
- * Makefile.in: Regenerate.
-
-2004-06-15 Paolo Bonzini <bonzini@gnu.org>
-
- * .cvsignore: New file.
-
-2004-06-10 Stephen Crowley <stephen.crowley@sbcglobal.net>
-
- PR libmudflap/13505
- * mf-hooks2.c (semctl): Add cygwin porting hack.
-
-2004-06-09 Frank Ch. Eigler <fche@redhat.com>
-
- ctype support.
- * configure.in: Look for ctype header and glibc implementation.
- * mf-hooks2.c (__ctype_{b,toupper,tolower}_loc): Sample ctype
- array hooks for glibc 2.3.
- * mf-runtime.h.in: Wrap them.
- * mf-runtime.c (__mf_init): Leave marker regarding other ctype
- implementations.
- * testsuite/libmudflap.c/pass47-frag.c: New test.
- * configure, config.h.in: Regenerated.
-
-2004-06-04 Frank Ch. Eigler <fche@redhat.com>
-
- Portability improvements, e.g., libmudflap/15293.
- * configure.in: Look for glibc extension functions. Look for
- support of -f{function,data}-sections. Look for more headers.
- Create testsuite/mfconfig.exp. Correct more "test x.." thinkos.
- * Makefile.am: Use $(SECTION_FLAGS). Collapse piecemeal-compiled
- mf-hooks* into usual single object per source.
- * mf-hooks*.c: Remove all #if WRAP_foo conditionals.
- * mf-hooks2.c: #include a bunch more system headers. Define strnlen
- if system doesn't provide one.
- * mf-hooks3.c (struct pthread_info): Add stack_*_alloc fields.
- (pthread_create): Use it to properly GC dead thread stacks.
- * mf-runtime.c (__mf_violation): Correct snprintf type warning.
- * testsuite/Makefile.am: Stop generating site.exp.
- * testsuite/mfconfig.exp.in: New file.
- * testsuite/config/default.exp: Load new mfconfig.exp.
- * testsuite/lib/libmudflap.exp (libmudflap-init): Add extra libraries.
- (prune_gcc_output): Add glibc static linking warnings.
- * testsuite/libmudflap.*/*frags.exp: Enumerate needed -lmudflap* libs.
- * testsuite/libmudflap.c/pass46-frag.c: Ditto.
- * configure, Makefile, aclocal.m4, config.h.in, testsuite/Makefile.in:
- Regenerated with autoconf 2.57 and automake 1.7.
-
-2004-06-04 Per Bothner <per@bothner.com>
-
- * configure.in (LIBMUDFLAPTH): Fix thinko.
-
- * configure.in: Check for more headers.
- * mf-hooks2.c: Conditionalize on HAVE_SYS_SOCKET_H etc.
-
- * mf-runtime.c: In two places conditionalize on SIUSR1 rather than
- HAVE_SIGNAL as mingw has signal.h but not SIUSR1.
-
-2004-06-01 Andreas Jaeger <aj@suse.de>
-
- * configure.in: Handle multilibs, support
- --enable-version-specific-runtime-libs.
- * Makefile.am (lib_LTLIBRARIES): Rename to ...
- (toolexeclib_LTLIBRARIES): this for multilib support.
- * Makefile.in: Regenerated.
- * configure: Regenerated.
- * aclocal.m4: Regenerated.
- * config.h.in: Regenerated.
- * testsuite/Makefile.in: Regenerated.
-
-2004-06-01 Andreas Jaeger <aj@suse.de>
-
- * testsuite/lib/libmudflap.exp (libmudflap-init): Handle
- multilibs, using multilib directory instead of hardcoded path.
- Set LD_RUN_PATH.
-
-2004-05-21 Frank Ch. Eigler <fche@redhat.com>
-
- * Makefile.am (AM_MAKEFLAGS): Pass RUNTESTFLAGS.
- * Makefile.in: Ditto.
-
-2004-05-18 Kaz Kojima <kkojima@gcc.gnu.org>
-
- * acinclude.m4 (lt_cv_deplibs_check_method): Use pass_all on sh*.
- * aclocal.m4, configure: Rebuilt.
-
-2004-05-17 Frank Ch. Eigler <fche@redhat.com>
-
- * lib/libmudflap.exp (libmudflap-init): For C++ test cases only,
- import some build settings from libstdc++-v3 testsuite_flags.
- * .../cfrags.exp, .../c++frags.exp, .../cthfrags.exp: Corresponding
- changes to pass test language.
-
- * mf-runtime.c (__mfu_check): Poison the cache with antidote for
- quicker mode-nop handling.
-
-2004-03-25 Frank Ch. Eigler <fche@redhat.com>
-
- * mf-impl.h: Added libgcc license header.
-
-2004-03-20 Frank Ch. Eigler <fche@redhat.com>
-
- * mf-hooks[123].c, mf-runtime.c, mf-heuristics.c:
- Added libgcc license header.
- * mf-hooks3.c (__mf_0fn_pthread_create): Correct arg constness.
- (pthread_create): Simplify stack allocation syntax.
-
-2004-03-08 Loren J. Rittle <ljrittle@acm.org>
-
- * mf-hooks2.c: Support FreeBSD.
- (WRAP_gets): Avoid gets().
- * testsuite/libmudflap.c/pass-stratcliff.c: Do not
- test unimplemented mem/str calls on FreeBSD.
- * testsuite/libmudflap.c/pass21-frag.c: Do not include
- <alloca.h> on FreeBSD.
-
-2004-01-30 Frank Ch. Eigler <fche@redhat.com>
-
- * testsuite/libmudflap.c/pass36-frag.c: Add missing free() call.
- * testsuite/libmudflap.c/pass46-frag.c: New test for -fmudflapir.
- * testsuite/libmudflap.cth/cthfrags.exp: Add -DSTATIC to compiler
- flags for static linking permutation.
- * testsuite/libmudflap.cth/pass40-frag.c: When -DSTATIC, avoid
- some pthreads code that croaks on linux glibc tls.
-
-2004-01-27 Frank Ch. Eigler <fche@redhat.com>
-
- * testsuite/libmudflap.c/fail31-frag.c, pass45-frag.c: New tests.
-
-2004-01-15 Frank Ch. Eigler <fche@redhat.com>
-
- * testsuite/libmudflap.c/pass44-frag.c: New test.
-
-2004-01-12 Frank Ch. Eigler <fche@redhat.com>
-
- * testsuite/libmudflap.c/fail{28,29,30}-frag.c: New tests.
-
-2004-01-08 Frank Ch. Eigler <fche@redhat.com>
-
- * testsuite/libmudflap.c/pass43-frag.c: Added missing program rc.
-
-2003-12-11 Frank Ch. Eigler <fche@redhat.com>
-
- * testsuite/libmudflap.c/pass42-frag.c, pass43-frag.c: New tests.
-
-2003-12-08 Andrew Pinski <pinskia@physics.uc.edu>
-
- PR libmudflap/12670
- * configure.in: Add check for see if
- socklen_t typedef is in sys/socket.h.
- * mf-hooks1.c: Add define if socklen_t
- is not typedef.
- * mf-hooks2.c: Likewise.
- * mf-hooks3.c: Likewise.
- * config.h.in: Regen.
- * configure: Regen.
-
-2003-12-08 Frank Ch. Eigler <fche@redhat.com>
-
- * mf-runtime.c (__mf_watch_or_not): Tweak tracing message.
- * testsuite/libmudflap.c/fail21-frag.c: Defeat aliasing
- optimizations.
- * testsuite/libmudflap.c/pass25-frag.c: Ditto.
- * testsuite/libmudflap.c/pass26-frag.c: Tolerate non-overlapping
- (unoptimized) allocation of stack space.
-
-2003-12-07 Richard Henderson <rth@redhat.com>
-
- * testsuite/libmudflap.c/fail23-frag.c (main): Adjust addend to 11.
- * testsuite/libmudflap.c/fail27-frag.c (foo): Mark noinline.
-
-2003-12-06 Andrew Pinski <apinski@apple.com>
-
- partial PR libmudflap/12670
- * mf-hooks1.c: Respect Darwin checks. Conditionalize POSIX_SOURCE.
- * mf-hooks2.c: Likewise.
- * mf-hooks3.c: Likewise.
-
-2003-11-19 Frank Ch. Eigler <fche@redhat.com>
-
- libstdc++/11696
- * mf-runtime.h.in: Switch to #pragma redefine_extname for
- symbols interposed at compile time.
- * testsuite/libmudflap.c++/pass41-frag.cxx: New test.
-
- libmudflap/12939
- * mf-hooks2.c (semctl): Tolerate FreeBSD.
-
- * configure.in: Reorganize check for <pthread.h>.
- * configure: Regenerated.
-
-2003-11-04 David Edelsohn <edelsohn@gnu.org>
-
- * mf-runtime.c (_ALL_SOURCE): Define for AIX.
- (_LARGE_FILE_API): Define for AIX.
- * mf-hooks[123]: Same.
- (_XOPEN_SOURCE_EXTENDED): Define to 1 for AIX.
-
-2003-10-21 David Edelsohn <edelsohn@gnu.org>
-
- * mf-runtime.c (_XOPEN_SOURCE_EXTENDED): Define to 1 for AIX.
-
-2003-07-29 Frank Ch. Eigler <fche@redhat.com>
-
- 2003-07-29 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
-
- * configure.in: Update check for union semun.
-
-2003-07-29 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
-
- PR other/11673
- * mf-hooks2.c [WRAP_semctl]: Fix check for HAVE_UNION_SEMUN.
-
-2003-07-29 Frank Ch. Eigler <fche@redhat.com>
-
- PR other/11673
- * configure.in: Add checks for 64-bit LFS functions, struct semun
- definition, for BSD compatibility.
- * mf-hooks1.c: Respect BSD checks. Conditionalize POSIX_SOURCE.
- * mf-hooks2.c: Ditto. Include <strings.h> for bcmp* decls.
- * mf-hooks3.c: Ditto.
- (pthread_create): Try MAP_ANON on platforms without the MAP_ANONYMOUS
- mmap flag.
- * configure, config.h.in: Regenerated.
-
-2003-07-23 Frank Ch. Eigler <fche@redhat.com>
-
- Multithreading fixes:
- * mf-runtime.c (__mf_object): Store allocating/deallocating
- thread id.
- (options): Support new "-thread-stack" option.
- Rename "-heur-argv-environ" option to "-heur-stdlib".
- Disable "-lc-mask" and "-lc-shift" options.
- (__mf_dynamic): Add function pointers for pthread_join/_exit.
- (__assert_fail): New self-contained function for glibc.
- * mf-hooks3.c: Essentially rewritten, particularly related to
- use of __mf_pthread_info array.
- (pthread_join, _exit): New hook functions.
- * mf-impl.h (BEGIN_PROTECT): Handle starting_p case.
- * testsuite/libmudflap.cth/pass40-frag.c: New test.
-
- Warning cleanups:
- * mf-heuristics.c: Add type casts for tracing, sub calls.
- * mf-impl.h (BEGIN_PROTECT): Redefine to omit result type.
- Update all callers to declare explicit result holder.
- (END_PROTECT): Removed.
- * testsuite/*/*frags.exp: Clean up default MUDFLAP_OPTIONS.
-
-2003-07-15 Diego Novillo <dnovillo@redhat.com>
-
- * testsuite/libmudflap.c/fail21-frag.c: Add volatile modifiers.
- * testsuite/libmudflap.c/fail15-frag.c: Likewise.
- * testsuite/libmudflap.c/fail13-frag.c: Likewise.
-
-2003-07-04 Frank Ch. Eigler <fche@redhat.com>
-
- * mf-hooks1.c, 2.c, 3.c: New file, splits up content from old ...
- * mf-hooks: Removed.
- * mf-impl.h (MF_VALIDATE_EXTENT, BEGIN_PROTECT, END_PROTECT):
- Move these macros from old mf-hooks.c here.
- * Makefile.am: Adapt to split-up hook sources for faster builds.
- * Makefile.in: Regenerated.
-
- * mf-heuristics.c: Remove #if-0 block.
-
- * mf-impl.h (__mf_state): Reorganize declaration and implementation.
- (__mf_starting_p): New state only for use while dlsym bootstrapping.
- (CALL_REAL, __mf_init): Corresponding changes.
- (TRACE, VERBOSE_TRACE): Include thread id and "mf:" prefix. Update
- all callers to remove redundant "mf:" prefix.
- * mf-runtime.h.in: #define a few reentrancy macros for libmudflapth.
- * mf-hooks3.c: Rewrite chunks to support per-thread __mf_state value.
- (__mf_pthread_info): Become a hash table.
-
- * testsuite/lib/mfdg.exp: Support new "dg-timeout" and
- "dg-repetitions" directives to control test case execution.
- * testsuite/libmudflap.cth/pass37-frag.c: Add timeout and repeat
- options.
- * testsuite/libmudflap.cth/pass39-frag.c: Ditto for this new test.
-
-2003-06-25 Frank Ch. Eigler <fche@redhat.com>
-
- * mf-hooks.c (alloca): Separate into stub.
- (__mf_wrap_alloca_indirect): New function. Use CALL_REAL
- malloc/free for alloca blocks.
- (pthread_create): Tolerate failing pthread_attr_get* calls.
- * mf-runtime.c (__mf_fini): Call __mf_wrap_alloca_indirect.
- * mf-impl.h (CALL_WRAP): Remove macro.
- * testsuite/libmudflap.c/pass21-frag.c: Include <alloca.h>.
- * testsuite/libmudflap.c/pass23-frag.c: Include more struct
- padding for ia64 BIT_FIELD_REF constructs.
-
-2003-06-19 Frank Ch. Eigler <fche@redhat.com>
-
- * mf-hooks.c (struct pthread_info): Add "thread_errno" field.
- (__mf_pthread_spawner, __mf_pthread_cleanup): Use it with GUESS
- libmudflap object type.
- * mf-runtime.c (__mfu_unregister): Correct cemetary logic to avoid
- crashes on unregistering STATIC objects.
-
-2003-06-17 Frank Ch. Eigler <fche@redhat.com>
-
- Based on patch from Eyal Lebedinsky <eyal@eyal.emu.id.au>:
- * mf-hooks.c (__mf_pthread_spawner): Register thread errno.
- (time, strerror, fopen, fopen64, fclose, fread): New hooks.
- (fwrite, fgetc, fgets, getc, gets, ungetc, fputc): New hooks.
- (fputs, putc, puts, clearerr, feof, ferror, fileno): New hooks.
- (printf, fprintf, sprintf, snprintf, vprintf, vfprintf): New hooks.
- (vsprintf, vsnprintf, access, remove, fflush, fseek): New hooks.
- (fseeko64, ftell, ftello64, rewind, fgetpos, fsetpos): New hooks.
- (stat, stat64, fstat, lstat, mkfifo, setvbuf, setbuf): New hooks.
- (setvbuf, opendir, closedir, readdir, recv, recvfrom): New hooks.
- (recvmsg, send, sendto, sendmsg, setsockopt, getsockopt): New hooks.
- (accept, bind, connect, gethostname, sethostname): New hooks.
- (gethostbyname, wait, waitpid, popen, pclose, execve): New hooks.
- (execv, execvp, system, dlopen, dlclose, dlerror, dlsym): New hooks.
- (semop, semctl, shmctl, shmat, shmdt): New hooks.
- * mf-runtime.h.in: Corresponding changes.
- * mf-runtime.c (__mf_ini): Register stdio objects. Use STATIC type.
- (opts) Rename heur_argv_environ to heur_std_data.
- (__mf_wrap_main): Use STATIC type for argv/environ strings.
- * Makefile.am: Corresponding changes.
- * Makefile.in: Regenerated.
-
-2003-06-11 Frank Ch. Eigler <fche@redhat.com>
-
- * mf-heuristics.c (__mf_heuristic_check): Disable stack_bounds
- heuristic for threaded case, and for non-x86-linux targets.
- * mf-hooks.c (__mf_0fn_calloc): Provide a working dummy implementation
- for use during pre-main() program startup.
- (__mf_0fn_*): Make these functions non-static.
- * mf-impl.h (DECLARE, CALL_REAL): Support calls to 0fn backup hook
- functions.
- * mf-runtime.c (__mf_state): Set initial state to "starting".
- (__mf_resolve_single_dynamic): Tolerate repeated calls for same symbol.
- (__wrap_main): New function to register argv[] and environ[] strings.
- (__mf_ini): Call it.
- (*): In all trace functions, use "%p" as formatter for uintptr_t.
-
- * testsuite/libmudflap.c/pass38-frag.c: New test case.
- * testsuite/libmudflap.cth/pass37-frag.c: Improved test.
-
- * acinclude.m4: Add comments with aoliva's concerns about x86_64
- pass_all.
- * aclocal.m4, configure: Regenerated.
-
-2003-06-04 Frank Ch. Eigler <fche@redhat.com>
-
- * acinclude.m4: Correct typo in AC_MSG_CHECKING.
- * aclocal.m4, configure: Regenerated.
-
-2003-06-03 Frank Ch. Eigler <fche@redhat.com>
-
- * acinclude.m4: Force "pass_all" deplibs_check_method for libtool
- for x86_64 target. Disable caching for this value.
- * aclocal.m4, configure: Regenerated.
-
-2003-06-02 Frank Ch. Eigler <fche@redhat.com>
-
- * testsuite/libmudflap.c/pass38-frag.c: Deleted. -fwritable-strings
- is about to become deprecated, and its present handling bugs are
- unworthy of fixing.
-
-2003-05-30 Frank Ch. Eigler <fche@redhat.com>
-
- * testsuite/libmudflap.c/pass38-frag.c: New test for
- -fwritable-strings.
-
-2003-05-23 Frank Ch. Eigler <fche@redhat.com>
-
- * mf-runtime.c (__mf_sigusr1_handle): Call unlocked variant of
- __mf_report, asserting reentrant calling context.
-
-2003-05-23 Frank Ch. Eigler <fche@redhat.com>
-
- * mf-hooks.c (realloc): Correct reentrancy logic.
- * testsuite/libmudflap.c/hook-allocstuff.c: New test case.
-
-2003-05-20 Frank Ch. Eigler <fche@redhat.com>
-
- * mf-hooks.c (LIBMUDFLAPTH_THREADS_MAX): New macro, replaces
- PTHREAD_THREADS_MAX. Update users.
- * mf-runtime.c (__mf_usage): Print [active] instead of [default]
- for active options.
- * testsuite/Makefile.am (all-local): Prime dejagnu site.exp file
- with libmudflapth presence indicator.
- * testsuite/Makefile.in: Regenerated.
-
-2003-05-16 Frank Ch. Eigler <fche@redhat.com>
-
- * Makefile.am (AM_CFLAGS): Remove "-ansi".
- * configure.in: Remove silly no-pthreads => no-shared logic.
- * Makefile.in, configure: Regenerated.
- * mf-heuristics.c (__mf_heuristic_check): Remove reentrancy hacks.
- * mf-hooks.c (BEGIN_PROTECT, END_PROTECT): Reorganize reentrancy
- code. Count reentrancy events.
- (all hook functions): Don't directly manipulate __mf_state variable.
- Add TRACE calls to hook functions without them.
- * mf-impl.h (LOCKTH): Try to count lock contention events.
- (VERBOSE_TRACE, TRACE): Remove reentrancy hacks.
- * mf-runtime.c (BEGIN_RECURSION_PROTECT, END_RECURSION_PROTECT):
- Reorganize reentrancy code.
- (external __mf_ entry points): Use RECURSION_PROTECT mechanism to
- identify reentrancy with mutex holding times.
- (internal __mfu_ entry points): Remove internal reentrancy code.
- (__mf_init): Use ordinary locked calls.
- (__mfu_report): Print the two new counts.
- * testsuite/lib/libmudflap.exp: Filter out junk ld/pthreads messages.
- * testsuite/libmudfap.cth/cthfrags.exp: New test driver.
- * testsuite/libmudflap.cth/pass37-frag.c: New pthreads test.
- * testsuite/libmudfap.cth/cfrags.exp: Adapt to new libmudflap
- option defaults.
-
-2003-05-09 Frank Ch. Eigler <fche@redhat.com>
-
- * configure.in: Add pthread support, plus glibc and porting hacks.
- * Makefile.am (LIBMUDFLAPTH): New conditional, to build -lmudflapth
- from objects built into ./pth/.
- * mf-runtime.c (__mfu_watch,register,...): Fork new unlocked
- functions for internal entry points. Update callers to pick
- locked vs. unlocked variants.
- (__mf_resolve_single_dynamic): Extend to support symbol versioning
- info coming in from a static data structure.
- (*): Reorder miscellaneous declarations to group data vs functions.
- (__mf_set_default_options): Simplify.
- (__mf_usage): Mention threading status of host executable.
- * mf-impl.h: Move max/min decls here. Reorganize __mf_dynamic
- decls to match above.
- (LOCKTH, UNLOCKTH): New macros for Big Libmudflap Lock management.
- * mf-heuristics.c: Choose between locked/unlocked calls. Add
- some lock/unlock markers. Remove some unused code.
- * mf-hooks: Ditto.
- (pthread_create): New hook function.
- (__mf_pthread_cleanup, _spawner): New helper functions.
- * configure. aclocal.m4, config.h.in, Makefile.in: Regenerated.
-
-2003-05-02 Frank Ch. Eigler <fche@redhat.com>
-
- * testsuite/libmudflap.c/fail27-frag.c: Add more volatile flags.
-
-2002-04-28 Frank Ch. Eigler <fche@redhat.com>
-
- * Makefile.am (HOOKOBJS): Add *time related hooks.
- * configure.in: Look for pthreads.h header.
- * mf-hooks.c (asctime, ctime, gmtime, localtime): New wrappers.
- * mf-runtime.c: Begin sketching some pthreads support.
- (__mf_usage): Check for -lpthread presence.
- (__mf_unregister): Confirm matching unregistration base.
- (__mf_find_objects_rec): Reduce unnecessary recursion.
- * mf-runtime.h.in: Add "nothrow" attribute to functions. Add
- #defines for new hook functions.
- * mf-impl.h: Corresponding changes.
- * config.h.in, configure, Makefile.in: Regenerated.
-
-2002-04-27 Diego Novillo <dnovillo@redhat.com>
-
- * testsuite/libmudflap.c/fail1-frag.c: Add volatile
- modifiers to prevent being optimized away.
- * testsuite/libmudflap.c/fail10-frag.c: Likewise.
- * testsuite/libmudflap.c/fail13-frag.c: Likewise.
- * testsuite/libmudflap.c/fail14-frag.c: Likewise.
- * testsuite/libmudflap.c/fail15-frag.c: Likewise.
- * testsuite/libmudflap.c/fail2-frag.c: Likewise.
- * testsuite/libmudflap.c/fail20-frag.c: Likewise.
- * testsuite/libmudflap.c/fail3-frag.c: Likewise.
-
-2003-04-15 Frank Ch. Eigler <fche@redhat.com>
-
- * Makefile.am (libmudflap_la_LIBADD): Remove -ldl.
- * configure.in: Look for uintptr_t and -ldl on target.
- * mf-runtime.h.in: Adjust uintptr_t declaration logic.
- * Makefile.in, aclocal.m4, configure, config.h.in: Regenerated.
- * testsuite/Makefile.in: Regenerated.
- * mf-runtime.c (__mf_sigusr1_respond): Tweak declaration and calls
- for better C compliance.
-
-2003-04-15 Frank Ch. Eigler <fche@redhat.com>
-
- * mf-hooks.c (MF_VALIDATE_EXTENT): Remove unnecessary reentrancy
- prevention code.
- * mf-runtime.c (__mf_set_default_options): Turn off
- check-initialization.
- (__mf_describe_object): Shorten description.
- * testsuite/libmudflap.c/fail25-frag.c: Turn on check-initialization.
-
-2003-04-07 Frank Ch. Eigler <fche@redhat.com>
-
- * mf-hooks.c (__mf_0fn_mmap): Correct return value, as per <rth>.
-
-2003-04-02 Frank Ch. Eigler <fche@redhat.com>
-
- * mf-hooks.c (BEGIN_PROTECT): Handle startup-time reentrant
- calls specially.
- (__mf_0fn_malloc ... _munmap): New dummy backup calls.
- * mf-impl.h (CALL_BACKUP): New macros.
- * mf-runtime.c (__mf_init): Tweak __mf_state during startup.
-
-2003-03-31 Frank Ch. Eigler <fche@redhat.com>
-
- * Makefile.am (AM_CFLAGS): Remove optimization flags.
- (HOOKOBJS): Remove dlopen hook.
- (libmudflap_la_LIBADD): Add -ldl.
- * mf-hooks.c (dlopen): Remove hook.
- * mf-impl.h (__mf_dynamic): Ditto.
- * mf-runtime.c (__mf_resolve_dynamics): Ditto.
- * Makefile.in: Regenerated.
-
-2003-03-28 Frank Ch. Eigler <fche@redhat.com>
-
- * configure.in: Check for target gettimeofday, signal, some headers.
- * mf-impl.h (__mf_opts): Add new "sigusr1_report" field. Comment
- out inop multi_threaded field.
- * mf-runtime.c (options): Handle new "-sigusr1-report" option.
- (__mf_set_options): Correct handling of "-help".
- (__mf_sigusr1_respond): New function to manage SIGUSR1 response.
- (__mf_check, __mf_register, __mf_unregister): Call it.
- (__mf_insert_new_object, __mf_unregister): Respect HAVE_GETTIMEOFDAY.
- (__mf_report_leaks): Make callable
- (__mf_tree_analyze): Traverse in-order. Accumulate address bit
- distribution statistics.
- (__mf_adapt_cache): Rewrite shift guessing logic based on address
- bit distributions.
- * config.h.in, configure: Regenerated.
- * testsuite/libmudflap.c/fail27-frag.c: New test.
- * testsuite/libmudflap.c/pass36-frag.c: New test.
-
-2003-03-11 Frank Ch. Eigler <fche@redhat.com>
-
- * mf-runtime.h.in: Tweak.
- * Makefile.am, configure.in: Tweak mf-runtime.h generation some more.
- Don't use intermediate files nor AC_OUTPUT-time postprocessing.
- * Makefile.in, testsuite/Makefile.in, configure: Regenerated.
-
-2003-03-10 Frank Ch. Eigler <fche@redhat.com>
-
- * configure.in: Tweak generation of mf-runtime.h some more. It
- needs to work from both config.status and configure.
- * configure: Regenerated.
-
-2003-03-10 Frank Ch. Eigler <fche@redhat.com>
-
- * Makefile.am: Reorganize hook file building. Add auto dependencies.
- * configure.in: Tweak generation of mf-runtime.h.
- * mf-runtime.h.in: Add new __MF_TYPE_HEAP_I.
- * mf-hooks.c (*): Adapt to initialized-heap object type.
- * mf-impl.h: Tweak cemetary boundaries.
- * mf-runtime.c (__mf_check): Adapt to new initialized-heap object
- type.
- (__mf_insert_new_object, __mf_register, __mf_unregister): Ditto.
- (__mf_describe_object, __mf_report_leaks, __mf_violation): Ditto.
- * testsuite/lib/libmudflap.exp (includes): Include build tree.
- * testsuite/libmudflap.c/pass{26,5}: Further adapt to initialization
- checking.
- * testsuite/.../fail{25,26}-frag.c: New tests.
- * testsuite/.../pass{32,33,34,35}-frag.c: New tests.
- * Makefile.in, configure: Regenerated.
-
-2003-03-05 Frank Ch. Eigler <fche@redhat.com>
-
- * mf-runtime.c (__mf_set_default_options): Turn on initialization
- checking by default.
- (__mf_insert_new_object): As a temporary hack, assume that new
- objects registered on the stack start out initialized.
- * testsuite/libmudflap.c/fail9,pass23,pass[6789]-*: Initialize
- heap objects by hand.
-
-2003-03-05 Frank Ch. Eigler <fche@redhat.com>
-
- Switch to macro-style hooks for str*/mem*/b* functions.
- * mf-runtime.h.in (__MF_TYPE_*): Moved some internal values out.
- (mem*, str*, b*): Added macro-style hooks for _MUDFLAP case.
- * mf-runtime.c: #include config.h to enable glibc backtraces again.
- (__mf_set_default_options): Turn off heur_proc_map.
- (*): Adapt to to macro-style hook functions.
- (__mf_object_dead_head, __mf_object_cemetary): Correct bounds.
- (__mf_check, __mf_register, __mf_unregister): Tweak tracing message.
- (__mf_violation): Handle __MF_VIOL_WATCH.
- * mf-impl.h (__MF_TYPE_*): Moved these internal values here.
- (__mf_dynamic): Removed mem*/str*/b* functions.
- (TRACE, VERBOSE_TRACE): Add reentrancy locking.
- (WRAPPER2): New macro for macro-style hooks.
- * mf-hooks.c: Convert mem*/str*/b* functions to simpler
- macro-style hooks.
- (BEGIN_PROTECT): Tweak tracing vs reentrancy-lock ordering.
- * mf-heuristics.c: Adapt to macro-style hook functions.
- Correct some comments.
- * testsuite/lib/mfdg.exp (dg-test): Simplify result string for
- output pattern tests.
- * testsuite/libmudflap.c/fail[89]-frag.c: Elaborate output test.
- * testsuite/libmudflap.c++/c++frags.exp: Enable non-static tests.
-
-2003-02-28 Frank Ch. Eigler <fche@redhat.com>
-
- * testsuite/libmudflap.c/fail23-frag.c, pass30-frag.c: New tests
- for global array registration.
- * testsuite/libmudflap.c++/fail24-frag.cxx, pass31-frag.cxx: Ditto.
- * testsuite/libmudflap.c++/c++frags.exp: Tweak -static multilib hack.
-
-2003-02-27 Frank Ch. Eigler <fche@redhat.com>
-
- * Makefile.am: Add gross make bug workarounds. Tweaked
- SUBDIRS and AM_CFLAGS.
- * Makefile.in: Regenerated.
-
-2003-02-26 Frank Ch. Eigler <fche@redhat.com>
-
- Switch to dejagnu.
- * configure.in (AC_PROG_CXX): Don't look for C++ any more.
- * Makefile.am (TESTS): Remove simple automake testing.
- * configure, Makefile.in: Regenerated.
- (SUBDIRS): Include new testsuite/ directory.
- * tests/*: Removed all files; moved bulk under:
- * testsuite/*: New subdirectory tree.
- * testsuite/libmudflap.c/cfrags.exp: New file, C test driver.
- * testsuite/libmudflap.c++/c++frags.exp: New file, C++ test driver.
- * testsuite/lib/libmudflap.exp: New file, derived from libstdc++.
- * testsuite/lib/mfdg.exp: New file, derived from dejagnu.
- * testsuite/config/default.exp: New file.
- * testsuite/Makefile.am, Makefile.in: New files.
-
-2003-01-29 Frank Ch. Eigler <fche@redhat.com>
-
- * Makefile.am (TESTS_ENVIRONMENT): Remove redundant "-mode-check".
- (TESTS): Add fail22 and pass29 tests.
- * mf-runtime.h.in: Change API to take void*/size_t region parameters.
- Add new access-type parameter for __mf_check. Move __MF_VIOL* out.
- * mf-impl.h: Corresponding changes. Update CLAMP* macros for void*
- values. Move __MF_VIOL* here.
- * mf-runtime.c (*): Adapt to void*/size_t API in mf-runtime.h.
- (check_initialization): New field in __mf_opts. Default off.
- (read_count,write_count): New fields in __mf_object.
- (__mf_check): Implement basic initialization checking.
- (__mf_insert_new_object): Assume STATIC|GUESS regions are initialized.
- (__mf_describe_object): Print new fields.
- (__mf_violation): Identify check/read vs. check/write in messages.
- * test/pass29-frag.c, test/fail22-frag.c: Basic tests for new
- "-check-initialized" mudflap option.
- * test/pass25-frag.c, test/fail21-frag.c: Adapt to API changes.
- * mf-hooks.c (MF_VALIDATE_EXTENT): Add new access-type parameter.
- Drop __FILE__/__LINE__ hack. Update callers.
- (*): Adapt to new mf-runtime.h API.
- * Makefile.in: regenerated.
-
-2003-01-24 Frank Ch. Eigler <fche@redhat.com>
-
- * configure.in: Build mf-runtime.h a more proper way.
- * mf-hooks.c (strdup, strndup): Correct reentrancy logic.
- * mf-runtime.c (verbose_violations): Turn on by default.
- * mf-runtime.h.in: Remove some miscellaneous stuff ...
- * mf-impl.h: ... and move it here.
- * configure: Regenerated.
-
-2003-01-22 Frank Ch. Eigler <fche@redhat.com>
-
- * configure.in: Look for C++ compiler.
- * test/*-frag.c, mf-driver.c: Reformatted with GNU indent and
- fixed type warnings when built with C++.
- * test/pass27-frag.cxx, pass28-frag.cxx: New C++ tests.
- * Makefile.am (TESTS): Run them.
- (*) Add new rules for building and running C++ tests.
- (TESTFLAGS): Set new default to avoid libstdc++-v3 shlib issues.
- * mf-runtime.h.in: Protect with extern "C".
- * Makefile, configure: Regenerated.
-
-2003-01-06 Frank Ch. Eigler <fche@redhat.com>
-
- Portability improvements.
- * configure.in: Look for glibc backtrace headers/functions.
- * mf-hooks.c: Don't include <execinfo.h> any more.
- * mf-runtime.c (__mf_set_options): Call more stdlib functions
- via CALL_REAL.
- (__mf_backtrace): Provide alternate baby implementation in
- absence of glibc.
- * test/mf-driver.c: Portability tweaks.
- * acinclude.m4: New file, containing top level libtool.m4.
- * aclocal.m4, configure, Makefile.in, config.h.in: Regenerated.
-
-2002-12-19 Frank Ch. Eigler <fche@redhat.com>
-
- * mf-runtime.h.in (HAVE_UINTPTR_T): Define unconditionally.
-
-2002-11-08 Frank Ch. Eigler <fche@redhat.com>
-
- * mf-runtime.c (options): Add new "wipe-heap", "wipe-stack"
- options.
- (__mf_unregister): Implement stack/heap object wiping.
- (__mf_set_options): Renamed from __mf_process_opts.
- (__mf_uncache_object): Change arg type, correct callers.
- * mf-impl.h: Corresponding changes.
- * mf-hooks.c (realloc): Save/restore heap-wiping flag.
- * mf-runtime.h.in (__mf_set_options): Extend public API.
- * test/pass26-frag.c: New test for stack wiping.
- * Makefile.am (TESTS): Run it.
- * Makefile.in: Regenerated.
-
-2002-11-07 Frank Ch. Eigler <fche@redhat.com>
-
- * mf-runtime.h.in (__mf_watch, __mf_unwatch): Extend public API.
- * mf-runtime.c (__mf_object_t): Add watching_p field.
- (__mf_watch_or_not): New function to implement
- object watch flagging.
- (__mf_watch, __mf_unwatch): New wrappers for above.
- (__mf_check, __mf_describe_object): Handle objects with watching_p.
- (__mf_count_violation): Enlarge array.
- (__mf_uncache_object): Renamed from __mf_remove_old_object. Don't
- unlink object. Clear cache properly.
- (__mf_unregister): Unlink object explicitly before uncaching.
- * test/fail21-frag.c, pass25-frag.c: New tests.
- * Makefile.in, aclocal.m4: Regenerated.
-
-2002-11-05 Frank Ch. Eigler <fche@redhat.com>
-
- * test/fail20-frag.c: New test for NULL pointer dereferencing.
- * Makefile.am (TESTS): Add it.
- * test/pass-stratcliff.c: Add decls of stpcpy.
- * configure.in: Test for <stdint.h>. Generate mf-runtime.h in
- build tree from config.h and new file mf-runtime.h.in.
- * mf-runtime.h.in: Renamed from mf-runtime.h. Tweak uintptr_t decl.
- * Makefile.in, configure, config.h.in: Regenerated.
- * mf-hooks.c: Add #undef for wrapped glibc str*/mem* macros.
- * mf-runtime.c (options, __mf_set_default_options): Support new
- default "abbreviate" option.
- (__mf_object.description_epoch): New field.
- (__mf_describe_object): Conditionally abbreviate objects already
- displayed in current epoch. Accept NULL input to increment epoch.
- (__mf_fini, __mf_ini): Reset description epoch.
- (__mf_register, __mf_unregister, __mf_adapt_cache, __mf_init): Ensure
- that NULL pointer slot in lookup cache is invalidated. Register a
- NOACCESS region around NULL.
- * mf-impl.h: Corresponding changes.
-
-2002-10-16 Frank Ch. Eigler <fche@redhat.com>
-
- * test/fail19-frag.c, pass24-frag.c, pass-stratcliff.c: New tests.
- * Makefile.am: Run them. Install mf-runtime.h.
- * Makefile.in: Regenerated.
- * mf-hooks.c: Add some markers for more missing functions.
- * mf-runtime.c (__mf_adapt_cache): Experiment with a utilization-based
- statistic to tune tune cache size (mask).
-
-2002-10-01 Frank Ch. Eigler <fche@redhat.com>
-
- * test/pass23-frag.c: New test for bit_field_ref expressions.
- * Makefile.am, Makefile.in: Add new test.
- * mf-hooks.c (mmap, munmap): Rewrite to track individual pages.
- (MF_VALIDATE_EXTENT): Accept zero-size mem/str operations.
- * mf-runtime.c (__mf_init): Register errno global.
- (__mf_find_object): Removed function.
- (__mf_check): Rewrite logic to support accesses across some
- contiguous but distinctly registered objects.
- (__mf_remove_old_object): Tolerate cache entries that span
- contiguous objects.
-
-2002-09-30 Frank Ch. Eigler <fche@redhat.com>
-
- * test/pass21-frag.c, pass22-frag.c: New tests: alloca, bitfields.
- * Makefile.am, Makefile.in: Run new tests.
- * mf-hooks.c (alloca): Correct stack direction logic.
-
-2002-09-26 Frank Ch. Eigler <fche@redhat.com>
-
- * mf-impl.h (adapt_cache): New option.
- * mf-runtime.c (__mf_set_default_options): Set its default value.
- Tweak the tree_aging parameter down.
- (__mf_check): Maintain separate counter for cache-adaptation.
- (__mf_tree_analyze): New function to collect object tree stats.
- (__mf_adapt_cache): New function to automate cache parameters.
-
-2002-09-24 Frank Ch. Eigler <fche@redhat.com>
-
- * mf-heuristics.c (__init_misc, __mf_heuristic_check): Add
- hypothetical #if-0'd argv/envp region registration.
- * mf-runtime.c (__mf_init): Add kludged form of above.
- (*) Add "heur_argv_environ" flag, default on, to govern this.
- * mf-impl.h: Corresponding changes.
-
-2002-09-20 Frank Ch. Eigler <fche@redhat.com>
-
- * test/fail18-frag.c: New test file for NOACCESS regions.
- * Makefile.am (TESTS): Add new test.
- * Makefile.in: Regenerated.
-
- * mf-heuristics.c (__mf_heuristics_check): Correct deja_vu logic.
- * mf-impl.h (tree_aging): Add new mudflap_option, default 1000000.
- (optimize_object_tree): Remove unused mudflap_option.
- * mf-runtime.h (__MF_TYPE_NOACCESS): New region type. Add printing
- support throughout. Use .._MAX_CEM for cemetary upper bound.
- * mf-runtime.c (__mf_init): Register __mf_* globals as NOACCESS
- regions.
- (__mf_object): Add new liveness field for use by tree aging.
- (__mf_check): Trigger tree aging when needed.
- (__mf_age_tree): New function to decay liveness field.
- (__mf_find_objects_rec): Use liveness field to rotate tree.
- (__mf_insert_new_object): Only provide backtrace for HEAP objects.
- (__mf_unregister): Ditto.
- (__mf_register): Tweak duplicate-static message.
- (__mf_violation: Tweak nearby-object counter printing.
-
-2002-09-16 Frank Ch. Eigler <fche@redhat.com>
-
- * test/pass20-frag.c: New test file.
- * Makefile.am (TESTS): Reorganize. Add pass20 test.
- * Makefile.in: Regenerated.
-
- * mf-impl.h (TRACE_IN, TRACE_OUT): Remove macros. Update callers.
- * mf-hooks.c (BEGIN_PROTECT): Add hook tracing here.
- * mf-heuristic.c (__mf_heuristic_check): Track seen /proc/self/map
- entries to avoid repeat registration.
- * mf-runtime.c (__mf_object_cemetary): Don't bother bury GUESS regions.
- (__mf_register, __mf_unregister): Rewrite GUESS handling logic.
-
-2002-09-09 Frank Ch. Eigler <fche@redhat.com>
-
- * Makefile.am: Create test sources with #include, not cat>>.
- * Makefile.in: Regenerated.
- * test/buildtest.sh: Removed.
- * test/driver.c (abort_handler, main): Be quiet.
-
-2002-09-06 Frank Ch. Eigler <fche@redhat.com>
-
- * test/pass18-frag.c, pass19-frag.c: New tests.
- * Makefile.am (check): Run them. Rebuild test programs each time.
- * Makefile.in: Regenerated.
-
-2002-09-06 Frank Ch. Eigler <fche@redhat.com>
-
- * mf-runtime.c (__mf_register): Correct SEGV-inducing error in
- overlapping object search.
- (__mf_violation): Likewise for nearby objects.
- Improve nearby-object listing.
-
- cleanup:
- * mf-runtime.c, mf-hooks.c: Remove "{{{"/"}}}" folding marks.
- * mf-heuristics.c (__mf_heuristic_check): Tweak message.
-
-2002-09-03 Frank Ch. Eigler <fche@redhat.com>
-
- alloca support:
- * Makefile.am (AM_CFLAGS): New definition of needed settings.
- (HOOKOBJS): Add alloca-hook.o.
- * mf-hooks.c (alloca): New function to implement alloca in libiberty
- style.
- * mf-runtime.c (__mf_report): Call alloca(0) to flush remaining blocks.
- (__mf_backtrace): Reimplement without using alloca.
- * Makefile.in: Regenerated.
-
- cleanup:
- * mf-hooks.c: Use VERBOSE_TRACE throughout instead of fprintf(stderr).
- Correct signedness bugs in length-tracking variables.
- * mf-impl.h: Make options unsigned.
- (CALL_WRAP): New macro to parallel CALL_REAL().
- (DECLARE): Remove erroneous ";" at end.
- * mf-runtime.c, mf-hooks.c, mf-heuristics.c: Replace remaining %p
- formatting specs with %08lx. Correct several compiler warnings.
-
-2002-08-28 Frank Ch. Eigler <fche@redhat.com>
-
- * mf-runtime.c (__mf_violation): Try harder to locate nearby objects.
-
-2002-08-27 Frank Ch. Eigler <fche@redhat.com>
-
- libmudflap hook breakup:
- * Makefile.am (TESTS_ENVIRONMENT): Add ../../gcc to LD_LIBRARY_PATH
- for libgcc_s.
- (TESTS): Make dependent on libmudflap.
- (HOOKOBJS): Break up mf-hooks.o into many little hook objects,
- compiled from segments of mf-hooks.c.
- * mf-hooks.c: Corresponding changes: wrap each function in
- #ifdef/#endif.
- * Makefile.in: Regenerated.
-
- Heuristics reorganization:
- * mf-heuristics.c (__mf_register_ro_sections, __mf_init_heuristics):
- Remove these functions. Update callers.
- (__mf_heuristic_check): Incorporate all the various heuristics.
- Encode cacheability/retry judgement into trinary return value.
- Separate start-end logic into a separate fallback heuristic. Only
- register relevant /proc/self/map segments.
- * mf-impl.h: Corresponding changes.
- * mf-runtime.c (__mf_check): Reorganize heuristics fallback logic.
- (__mf_init): Don't call __mf_init_heuristics.
-
- Tracing cleanup:
- * mf-heuristics.c, mf-runtime.c: Use new MUDFLAP_OPTION
- "-verbose-trace" to emit all tracing messages other than those of
- basic public api. Eliminate some duplicate/excessive messages.
- * mf-runtime.h: Corresponding changes.
-
-2002-08-27 Graydon Hoare <graydon@redhat.com>
-
- * mf-impl.h (WRAPPER): Change to create linker aliases for __wrap
- and __real when compiled with -DPIC.
- * mf-hooks.c (WRAPPER): Change all uses of WRAPPER macro slightly.
- * Makefile.am (AUTOMAKE_OPTIONS): Fix LD_LIBRARY_PATH for tests.
- * Makefile.in: Regenerate.
-
-2002-08-26 Graydon Hoare <graydon@redhat.com>
-
- * mf-impl.h: New file, private implementation header.
- * mf-runtime.h: Reorganize a bit.
- (CLAMPSZ): Fix arithmetic.
- (__MF_CACHE_MISS_P): Fix arithmetic.
- * mf-runtime.c: Reorganize a bit.
- (__mf_dynamic): New structure.
- (resolve_single_dynamic): New function.
- (__mf_resolve_dynamics): New function.
- (__mf_init): Initialize dynamic wrappers.
- * mf-hooks.c: Macro-ize __real calls.
- Clamp various bits of arithmetic.
- Add explicit __mf_check call contexts.
- * Makefile.am: Add dependencies on mf-impl.h
- * Makefile.in: Regenerate.
- * configure.in: Comment out shared override.
- * configure: Regenerate.
-
-2002-08-22 Graydon Hoare <graydon@redhat.com>
-
- * mf-runtime.c (__mf_process_opts): Sanity-check free_queue_length.
- (__mf_check): Re-inialize and check heuristics before violation.
- (__mf_register): Permit updating pure-guess regions.
- * mf-hooks.c (__wrap_free): Correct some free queue logic.
- (__wrap_dlopen): New wrapper function.
- (__wrap_mmap): New wrapper function.
- (__wrap_munmap): New wrapper function.
- * mf-heuristics.c (__mf_register_ro_sections): Register *all* regions
- which are not stack addresses.
- (is_stack_address): New function.
- (__mf_init_heuristics): Save and restore state, always initialize with
- "starting" state.
-
-2002-08-21 Frank Ch. Eigler <fche@redhat.com>
-
- * mf-hooks.c (MF_VALIDATE_EXTENT): Rewrite to correct off-by-one
- error. Pass location string.
- (wrap_strcpy, wrap_strncpy): Remove extra %s in trace strings.
- * mf-runtime.c (options): Add lc-mask, lc-shift options.
- (__mf_process_opts): Apply some sanity checking for lc-mask.
- (__mf_check, __mf_violation): Take new location-string argument.
- Update callers to pass NULL if necessary.
- (__mf_backtrace): New smart backtracer function. Calls replace
- several ad-hoc blocks elsewhere.
- (__mf_describe_object): Remove bad reentrancy test. Improve
- tracing message.
- * mf-runtime.h: Corresponding changes. Public/private markup.
- (__MF_CACHE_MISS_P): New macro.
-
-2002-08-20 Graydon Hoare <graydon@redhat.com>
-
- * mf-runtime.h: New option: stack_bound (heuristic).
- Move some macros out of implementation files.
- * mf-runtime.c: New option string: -stack-bound.
- Unify recursion protection with hooks.
- Add more logging.
- (__mf_check): Call __mf_heuristic_check.
- (__mf_process_opts): Fix "no-" processing.
- * mf-heuristics.c (__mf_heuristic_check): New function.
- * mf-hooks.c: Much off-by-one fixing, recursion protection.
-
-2002-08-20 Frank Ch. Eigler <fche@redhat.com>
-
- Option parsing improvements, region splitting bug fixes:
- * mf-heuristics.c (__mf_register_ro_sections): Add warned casts.
- * mf-runtime.h (heur_proc_map): New libmudflap option.
- * mf-runtime.c (__mf_set_default_options): Set it.
- (__mf_usage): Print default values/status.
- (__mf_process_opts): Support general "no-" option string prefix.
- (__mf_init): Print __mf_usage on unknown-option error.
- (__mf_register): Print trace message up front.
- Correct region splitting logic for case where a subregion disappears.
- Correct memory leak.
- (__mf_violation): Make even basic message conditional on option.
-
- Build cleanup:
- * Makefile.am (TESTS_ENVIRONMENT): Add -no-heur-proc-map.
- (clean-local): New target.
- (test/*x rules): Add -g CFLAGS.
- (CFLAGS): Add -freorder-blocks.
- (MFCONFIG_CFLAGS, INCLUDE): Remove unneeded settings.
- * Makefile.in: Regenerated.
- * Makefile, mf-config.h: Removed files.
-
-2002-08-16 Graydon Hoare <graydon@redhat.com>
-
- * mf-runtime.c (__mf_insert_new_object): Factor out of
- __mf_register.
- (__mf_remove_old_object): Factor out of __mf_unregister.
- (__mf_register): Handle guessed regions, splitting
- guesses when new registrations arrive.
- (__mf_unregister): Do not unregister guesses.
- * mf-runtime.h: Move convenience macros around,
- declare new option fields. Add __MF_TYPE_GUESS.
- * mf-hooks.c (__wrap_*alloc): Use crumple zones.
- (__wrap_free): Call __real_free for deferred frees.
- * Makefile.am: Add more tests, fix dependency.
- * Makefile.in: Regenerate.
- * test/pass[13..17]-frag.c: New testcases.
- * test/fail[13..17]-frag.c: New testcases.
-
-2002-08-15 Graydon Hoare <graydon@redhat.com>
-
- * mf-heuristics.c: New file.
- * mf-runtime.c (options): Add -trace-calls option.
- (__mf_init): Call __mf_init_heuristics.
-
-2002-08-14 Graydon Hoare <graydon@redhat.com>
-
- * Makefile.am (TESTS): Add testsuite support.
- * Makefile.in: Regenerate.
- * test/mf-driver.c: New file.
- * test/buildtest.sh: New file.
- * test/passNN-frag.c: New testcases.
- * test/failNN-frag.c: New testcases.
-
-2002-08-14 Graydon Hoare <graydon@redhat.com>
-
- * mf-hooks.c: Change __real_strlen() to __real_strlen()+1 when
- verifying non-size-limited string extents.
-
-2002-08-14 Frank Ch. Eigler <fche@redhat.com>
-
- * mf-hooks.c: Make __wrap string* functions use __real_str[n]len
- instead of plain str[n]len for internal checks.
- * mf-runtime.c (__mf_violation): Print optional stack traceback.
-
-2002-08-14 Frank Ch. Eigler <fche@redhat.com>
-
- * mf-hooks.c: Remove #if-0 around hooks that are now ld-wrapped.
-
-2002-08-13 Graydon Hoare <graydon@redhat.com>
-
- * mf-runtime.c: Rework configuration to operate on
- environment variable options rather than #defines
- (__mf_violation): Add simple fork-a-gdb violaiton mode.
- (__mf_init): Set static __mf_active_p flag on startup,
- to inhibit mudflap wrap-based checking during crt0.s.
- * mf-runtime.h: Declare options structure.
- * mf-hooks.c: New wrappings for mem*, b*, str*
- libc functions (temporarily #if 0-ed out).
-
-2002-08-12 Frank Ch. Eigler <fche@redhat.com>
-
- * Makefile.am, configure.in: New files.
- * Makefile.in, Makefile, configure, config.h.in: New generated files.
- * stamp-h.in, aclocal.m4: Ditto.
-
-2002-08-08 Frank Ch. Eigler <fche@redhat.com>
-
- * Makefile: New file.
- * mf-config.h: New file: runtime configuration.
- * mf-hooks.c: New file: interposed libc functions.
- * mf-runtime.c: New file: bulk of runtime.
- * mf-runtime.h: New file: public functions.
diff --git a/libmudflap/Makefile.am b/libmudflap/Makefile.am
deleted file mode 100644
index 40a70aead9b..00000000000
--- a/libmudflap/Makefile.am
+++ /dev/null
@@ -1,97 +0,0 @@
-## Makefile for the toplevel directory of the mudflap library.
-##
-## Copyright (C) 2002-2013 Free Software Foundation, Inc.
-##
-
-AUTOMAKE_OPTIONS = 1.8 foreign
-ACLOCAL_AMFLAGS = -I .. -I ../config
-MAINT_CHARSET = latin1
-SUBDIRS = testsuite
-
-# May be used by various substitution variables.
-gcc_version := $(shell cat $(top_srcdir)/../gcc/BASE-VER)
-
-SECTION_FLAGS = @SECTION_FLAGS@
-AM_CFLAGS = -Wall $(SECTION_FLAGS)
-
-if LIBMUDFLAPTH
-libmudflapth = libmudflapth.la
-else
-libmudflapth =
-endif
-
-toolexeclib_LTLIBRARIES = libmudflap.la $(libmudflapth)
-target_noncanonical = @target_noncanonical@
-libsubincludedir = $(libdir)/gcc/$(target_noncanonical)/$(gcc_version)/include
-nobase_libsubinclude_HEADERS = mf-runtime.h
-
-
-libmudflap_la_SOURCES = \
- mf-runtime.c \
- mf-heuristics.c \
- mf-hooks1.c \
- mf-hooks2.c
-libmudflap_la_LIBADD =
-libmudflap_la_DEPENDENCIES = $(libmudflap_la_LIBADD)
-libmudflap_la_LDFLAGS = -version-info `grep -v '^\#' $(srcdir)/libtool-version`
-
-
-libmudflapth_la_SOURCES = \
- mf-runtime.c \
- mf-heuristics.c \
- mf-hooks1.c \
- mf-hooks2.c \
- mf-hooks3.c
-libmudflapth_la_CFLAGS = -DLIBMUDFLAPTH
-libmudflapth_la_LIBADD =
-libmudflapth_la_DEPENDENCIES = $(libmudflapth_la_LIBADD)
-libmudflapth_la_LDFLAGS = -version-info `grep -v '^\#' $(srcdir)/libtool-version`
-
-
-# XXX hack alert
-# From libffi/Makefile.am
-
-# Work around what appears to be a GNU make bug handling MAKEFLAGS
-# values defined in terms of make variables, as is the case for CC and
-# friends when we are called from the top level Makefile.
-AM_MAKEFLAGS = \
- "AR_FLAGS=$(AR_FLAGS)" \
- "CC_FOR_BUILD=$(CC_FOR_BUILD)" \
- "CFLAGS=$(CFLAGS)" \
- "CXXFLAGS=$(CXXFLAGS)" \
- "CFLAGS_FOR_BUILD=$(CFLAGS_FOR_BUILD)" \
- "CFLAGS_FOR_TARGET=$(CFLAGS_FOR_TARGET)" \
- "INSTALL=$(INSTALL)" \
- "INSTALL_DATA=$(INSTALL_DATA)" \
- "INSTALL_PROGRAM=$(INSTALL_PROGRAM)" \
- "INSTALL_SCRIPT=$(INSTALL_SCRIPT)" \
- "JC1FLAGS=$(JC1FLAGS)" \
- "LDFLAGS=$(LDFLAGS)" \
- "LIBCFLAGS=$(LIBCFLAGS)" \
- "LIBCFLAGS_FOR_TARGET=$(LIBCFLAGS_FOR_TARGET)" \
- "MAKE=$(MAKE)" \
- "MAKEINFO=$(MAKEINFO) $(MAKEINFOFLAGS)" \
- "PICFLAG=$(PICFLAG)" \
- "PICFLAG_FOR_TARGET=$(PICFLAG_FOR_TARGET)" \
- "SHELL=$(SHELL)" \
- "RUNTESTFLAGS=$(RUNTESTFLAGS)" \
- "exec_prefix=$(exec_prefix)" \
- "infodir=$(infodir)" \
- "libdir=$(libdir)" \
- "prefix=$(prefix)" \
- "includedir=$(includedir)" \
- "AR=$(AR)" \
- "AS=$(AS)" \
- "CC=$(CC)" \
- "CXX=$(CXX)" \
- "LD=$(LD)" \
- "LIBCFLAGS=$(LIBCFLAGS)" \
- "NM=$(NM)" \
- "PICFLAG=$(PICFLAG)" \
- "RANLIB=$(RANLIB)" \
- "DESTDIR=$(DESTDIR)"
-
-MAKEOVERRIDES=
-
-## ################################################################
-
diff --git a/libmudflap/Makefile.in b/libmudflap/Makefile.in
deleted file mode 100644
index 416bd32371b..00000000000
--- a/libmudflap/Makefile.in
+++ /dev/null
@@ -1,855 +0,0 @@
-# Makefile.in generated by automake 1.11.6 from Makefile.am.
-# @configure_input@
-
-# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
-# Foundation, Inc.
-# This Makefile.in 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.
-
-@SET_MAKE@
-
-
-VPATH = @srcdir@
-am__make_dryrun = \
- { \
- am__dry=no; \
- case $$MAKEFLAGS in \
- *\\[\ \ ]*) \
- echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
- | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
- *) \
- for am__flg in $$MAKEFLAGS; do \
- case $$am__flg in \
- *=*|--*) ;; \
- *n*) am__dry=yes; break;; \
- esac; \
- done;; \
- esac; \
- test $$am__dry = yes; \
- }
-pkgdatadir = $(datadir)/@PACKAGE@
-pkgincludedir = $(includedir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
-pkglibexecdir = $(libexecdir)/@PACKAGE@
-am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
-install_sh_DATA = $(install_sh) -c -m 644
-install_sh_PROGRAM = $(install_sh) -c
-install_sh_SCRIPT = $(install_sh) -c
-INSTALL_HEADER = $(INSTALL_DATA)
-transform = $(program_transform_name)
-NORMAL_INSTALL = :
-PRE_INSTALL = :
-POST_INSTALL = :
-NORMAL_UNINSTALL = :
-PRE_UNINSTALL = :
-POST_UNINSTALL = :
-build_triplet = @build@
-host_triplet = @host@
-target_triplet = @target@
-subdir = .
-DIST_COMMON = ChangeLog $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
- $(top_srcdir)/configure $(am__configure_deps) \
- $(srcdir)/config.h.in $(srcdir)/../mkinstalldirs \
- $(srcdir)/../depcomp $(nobase_libsubinclude_HEADERS)
-ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \
- $(top_srcdir)/../config/depstand.m4 \
- $(top_srcdir)/../config/enable.m4 \
- $(top_srcdir)/../config/lead-dot.m4 \
- $(top_srcdir)/../config/multi.m4 \
- $(top_srcdir)/../config/override.m4 \
- $(top_srcdir)/../config/tls.m4 $(top_srcdir)/../ltoptions.m4 \
- $(top_srcdir)/../ltsugar.m4 $(top_srcdir)/../ltversion.m4 \
- $(top_srcdir)/../lt~obsolete.m4 $(top_srcdir)/acinclude.m4 \
- $(top_srcdir)/../libtool.m4 $(top_srcdir)/configure.ac
-am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
- $(ACLOCAL_M4)
-am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
- configure.lineno config.status.lineno
-mkinstalldirs = $(SHELL) $(top_srcdir)/../mkinstalldirs
-CONFIG_HEADER = config.h
-CONFIG_CLEAN_FILES =
-CONFIG_CLEAN_VPATH_FILES =
-am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
-am__vpath_adj = case $$p in \
- $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
- *) f=$$p;; \
- esac;
-am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
-am__install_max = 40
-am__nobase_strip_setup = \
- srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
-am__nobase_strip = \
- for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
-am__nobase_list = $(am__nobase_strip_setup); \
- for p in $$list; do echo "$$p $$p"; done | \
- sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
- $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
- if (++n[$$2] == $(am__install_max)) \
- { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
- END { for (dir in files) print dir, files[dir] }'
-am__base_list = \
- sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
- sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
-am__uninstall_files_from_dir = { \
- test -z "$$files" \
- || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
- || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
- $(am__cd) "$$dir" && rm -f $$files; }; \
- }
-am__installdirs = "$(DESTDIR)$(toolexeclibdir)" \
- "$(DESTDIR)$(libsubincludedir)"
-LTLIBRARIES = $(toolexeclib_LTLIBRARIES)
-am_libmudflap_la_OBJECTS = mf-runtime.lo mf-heuristics.lo mf-hooks1.lo \
- mf-hooks2.lo
-libmudflap_la_OBJECTS = $(am_libmudflap_la_OBJECTS)
-libmudflap_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
- $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
- $(libmudflap_la_LDFLAGS) $(LDFLAGS) -o $@
-am_libmudflapth_la_OBJECTS = libmudflapth_la-mf-runtime.lo \
- libmudflapth_la-mf-heuristics.lo libmudflapth_la-mf-hooks1.lo \
- libmudflapth_la-mf-hooks2.lo libmudflapth_la-mf-hooks3.lo
-libmudflapth_la_OBJECTS = $(am_libmudflapth_la_OBJECTS)
-libmudflapth_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
- $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libmudflapth_la_CFLAGS) \
- $(CFLAGS) $(libmudflapth_la_LDFLAGS) $(LDFLAGS) -o $@
-@LIBMUDFLAPTH_TRUE@am_libmudflapth_la_rpath = -rpath $(toolexeclibdir)
-DEFAULT_INCLUDES = -I.@am__isrc@
-depcomp = $(SHELL) $(top_srcdir)/../depcomp
-am__depfiles_maybe = depfiles
-am__mv = mv -f
-COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
- $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
- --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
- $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-CCLD = $(CC)
-LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
- --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
- $(LDFLAGS) -o $@
-SOURCES = $(libmudflap_la_SOURCES) $(libmudflapth_la_SOURCES)
-MULTISRCTOP =
-MULTIBUILDTOP =
-MULTIDIRS =
-MULTISUBDIR =
-MULTIDO = true
-MULTICLEAN = true
-RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
- html-recursive info-recursive install-data-recursive \
- install-dvi-recursive install-exec-recursive \
- install-html-recursive install-info-recursive \
- install-pdf-recursive install-ps-recursive install-recursive \
- installcheck-recursive installdirs-recursive pdf-recursive \
- ps-recursive uninstall-recursive
-am__can_run_installinfo = \
- case $$AM_UPDATE_INFO_DIR in \
- n|no|NO) false;; \
- *) (install-info --version) >/dev/null 2>&1;; \
- esac
-HEADERS = $(nobase_libsubinclude_HEADERS)
-RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
- distclean-recursive maintainer-clean-recursive
-AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
- $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS
-ETAGS = etags
-CTAGS = ctags
-DIST_SUBDIRS = $(SUBDIRS)
-ACLOCAL = @ACLOCAL@
-AMTAR = @AMTAR@
-AR = @AR@
-AUTOCONF = @AUTOCONF@
-AUTOHEADER = @AUTOHEADER@
-AUTOMAKE = @AUTOMAKE@
-AWK = @AWK@
-CC = @CC@
-CCDEPMODE = @CCDEPMODE@
-CFLAGS = @CFLAGS@
-CPP = @CPP@
-CPPFLAGS = @CPPFLAGS@
-CYGPATH_W = @CYGPATH_W@
-DEFS = @DEFS@
-DEPDIR = @DEPDIR@
-DSYMUTIL = @DSYMUTIL@
-DUMPBIN = @DUMPBIN@
-ECHO_C = @ECHO_C@
-ECHO_N = @ECHO_N@
-ECHO_T = @ECHO_T@
-EGREP = @EGREP@
-EXEEXT = @EXEEXT@
-FGREP = @FGREP@
-GREP = @GREP@
-INSTALL = @INSTALL@
-INSTALL_DATA = @INSTALL_DATA@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_SCRIPT = @INSTALL_SCRIPT@
-INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
-LD = @LD@
-LDFLAGS = @LDFLAGS@
-LIBOBJS = @LIBOBJS@
-LIBS = @LIBS@
-LIBTOOL = @LIBTOOL@
-LIPO = @LIPO@
-LN_S = @LN_S@
-LTLIBOBJS = @LTLIBOBJS@
-MAINT = @MAINT@
-MAKEINFO = @MAKEINFO@
-MF_HAVE_STDINT_H = @MF_HAVE_STDINT_H@
-MF_HAVE_UINTPTR_T = @MF_HAVE_UINTPTR_T@
-MKDIR_P = @MKDIR_P@
-NM = @NM@
-NMEDIT = @NMEDIT@
-OBJDUMP = @OBJDUMP@
-OBJEXT = @OBJEXT@
-OTOOL = @OTOOL@
-OTOOL64 = @OTOOL64@
-PACKAGE = @PACKAGE@
-PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
-PACKAGE_NAME = @PACKAGE_NAME@
-PACKAGE_STRING = @PACKAGE_STRING@
-PACKAGE_TARNAME = @PACKAGE_TARNAME@
-PACKAGE_URL = @PACKAGE_URL@
-PACKAGE_VERSION = @PACKAGE_VERSION@
-PATH_SEPARATOR = @PATH_SEPARATOR@
-RANLIB = @RANLIB@
-SECTION_FLAGS = @SECTION_FLAGS@
-SED = @SED@
-SET_MAKE = @SET_MAKE@
-SHELL = @SHELL@
-STRIP = @STRIP@
-VERSION = @VERSION@
-abs_builddir = @abs_builddir@
-abs_srcdir = @abs_srcdir@
-abs_top_builddir = @abs_top_builddir@
-abs_top_srcdir = @abs_top_srcdir@
-ac_ct_CC = @ac_ct_CC@
-ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
-am__include = @am__include@
-am__leading_dot = @am__leading_dot@
-am__quote = @am__quote@
-am__tar = @am__tar@
-am__untar = @am__untar@
-bindir = @bindir@
-build = @build@
-build_alias = @build_alias@
-build_cpu = @build_cpu@
-build_libmudflapth = @build_libmudflapth@
-build_os = @build_os@
-build_vendor = @build_vendor@
-builddir = @builddir@
-datadir = @datadir@
-datarootdir = @datarootdir@
-docdir = @docdir@
-dvidir = @dvidir@
-enable_shared = @enable_shared@
-enable_static = @enable_static@
-exec_prefix = @exec_prefix@
-host = @host@
-host_alias = @host_alias@
-host_cpu = @host_cpu@
-host_os = @host_os@
-host_vendor = @host_vendor@
-htmldir = @htmldir@
-includedir = @includedir@
-infodir = @infodir@
-install_sh = @install_sh@
-libdir = @libdir@
-libexecdir = @libexecdir@
-localedir = @localedir@
-localstatedir = @localstatedir@
-mandir = @mandir@
-mkdir_p = @mkdir_p@
-multi_basedir = @multi_basedir@
-oldincludedir = @oldincludedir@
-pdfdir = @pdfdir@
-prefix = @prefix@
-program_transform_name = @program_transform_name@
-psdir = @psdir@
-sbindir = @sbindir@
-sharedstatedir = @sharedstatedir@
-srcdir = @srcdir@
-sysconfdir = @sysconfdir@
-target = @target@
-target_alias = @target_alias@
-target_cpu = @target_cpu@
-target_noncanonical = @target_noncanonical@
-target_os = @target_os@
-target_vendor = @target_vendor@
-toolexecdir = @toolexecdir@
-toolexeclibdir = @toolexeclibdir@
-top_build_prefix = @top_build_prefix@
-top_builddir = @top_builddir@
-top_srcdir = @top_srcdir@
-AUTOMAKE_OPTIONS = 1.8 foreign
-ACLOCAL_AMFLAGS = -I .. -I ../config
-MAINT_CHARSET = latin1
-SUBDIRS = testsuite
-
-# May be used by various substitution variables.
-gcc_version := $(shell cat $(top_srcdir)/../gcc/BASE-VER)
-AM_CFLAGS = -Wall $(SECTION_FLAGS)
-@LIBMUDFLAPTH_FALSE@libmudflapth =
-@LIBMUDFLAPTH_TRUE@libmudflapth = libmudflapth.la
-toolexeclib_LTLIBRARIES = libmudflap.la $(libmudflapth)
-libsubincludedir = $(libdir)/gcc/$(target_noncanonical)/$(gcc_version)/include
-nobase_libsubinclude_HEADERS = mf-runtime.h
-libmudflap_la_SOURCES = \
- mf-runtime.c \
- mf-heuristics.c \
- mf-hooks1.c \
- mf-hooks2.c
-
-libmudflap_la_LIBADD =
-libmudflap_la_DEPENDENCIES = $(libmudflap_la_LIBADD)
-libmudflap_la_LDFLAGS = -version-info `grep -v '^\#' $(srcdir)/libtool-version`
-libmudflapth_la_SOURCES = \
- mf-runtime.c \
- mf-heuristics.c \
- mf-hooks1.c \
- mf-hooks2.c \
- mf-hooks3.c
-
-libmudflapth_la_CFLAGS = -DLIBMUDFLAPTH
-libmudflapth_la_LIBADD =
-libmudflapth_la_DEPENDENCIES = $(libmudflapth_la_LIBADD)
-libmudflapth_la_LDFLAGS = -version-info `grep -v '^\#' $(srcdir)/libtool-version`
-
-# XXX hack alert
-# From libffi/Makefile.am
-
-# Work around what appears to be a GNU make bug handling MAKEFLAGS
-# values defined in terms of make variables, as is the case for CC and
-# friends when we are called from the top level Makefile.
-AM_MAKEFLAGS = \
- "AR_FLAGS=$(AR_FLAGS)" \
- "CC_FOR_BUILD=$(CC_FOR_BUILD)" \
- "CFLAGS=$(CFLAGS)" \
- "CXXFLAGS=$(CXXFLAGS)" \
- "CFLAGS_FOR_BUILD=$(CFLAGS_FOR_BUILD)" \
- "CFLAGS_FOR_TARGET=$(CFLAGS_FOR_TARGET)" \
- "INSTALL=$(INSTALL)" \
- "INSTALL_DATA=$(INSTALL_DATA)" \
- "INSTALL_PROGRAM=$(INSTALL_PROGRAM)" \
- "INSTALL_SCRIPT=$(INSTALL_SCRIPT)" \
- "JC1FLAGS=$(JC1FLAGS)" \
- "LDFLAGS=$(LDFLAGS)" \
- "LIBCFLAGS=$(LIBCFLAGS)" \
- "LIBCFLAGS_FOR_TARGET=$(LIBCFLAGS_FOR_TARGET)" \
- "MAKE=$(MAKE)" \
- "MAKEINFO=$(MAKEINFO) $(MAKEINFOFLAGS)" \
- "PICFLAG=$(PICFLAG)" \
- "PICFLAG_FOR_TARGET=$(PICFLAG_FOR_TARGET)" \
- "SHELL=$(SHELL)" \
- "RUNTESTFLAGS=$(RUNTESTFLAGS)" \
- "exec_prefix=$(exec_prefix)" \
- "infodir=$(infodir)" \
- "libdir=$(libdir)" \
- "prefix=$(prefix)" \
- "includedir=$(includedir)" \
- "AR=$(AR)" \
- "AS=$(AS)" \
- "CC=$(CC)" \
- "CXX=$(CXX)" \
- "LD=$(LD)" \
- "LIBCFLAGS=$(LIBCFLAGS)" \
- "NM=$(NM)" \
- "PICFLAG=$(PICFLAG)" \
- "RANLIB=$(RANLIB)" \
- "DESTDIR=$(DESTDIR)"
-
-MAKEOVERRIDES =
-all: config.h
- $(MAKE) $(AM_MAKEFLAGS) all-recursive
-
-.SUFFIXES:
-.SUFFIXES: .c .lo .o .obj
-am--refresh: Makefile
- @:
-$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
- @for dep in $?; do \
- case '$(am__configure_deps)' in \
- *$$dep*) \
- echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \
- $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \
- && exit 0; \
- exit 1;; \
- esac; \
- done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \
- $(am__cd) $(top_srcdir) && \
- $(AUTOMAKE) --foreign Makefile
-.PRECIOUS: Makefile
-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
- @case '$?' in \
- *config.status*) \
- echo ' $(SHELL) ./config.status'; \
- $(SHELL) ./config.status;; \
- *) \
- echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
- cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
- esac;
-
-$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
- $(SHELL) ./config.status --recheck
-
-$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
- $(am__cd) $(srcdir) && $(AUTOCONF)
-$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
- $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
-$(am__aclocal_m4_deps):
-
-config.h: stamp-h1
- @if test ! -f $@; then rm -f stamp-h1; else :; fi
- @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) stamp-h1; else :; fi
-
-stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
- @rm -f stamp-h1
- cd $(top_builddir) && $(SHELL) ./config.status config.h
-$(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
- ($(am__cd) $(top_srcdir) && $(AUTOHEADER))
- rm -f stamp-h1
- touch $@
-
-distclean-hdr:
- -rm -f config.h stamp-h1
-install-toolexeclibLTLIBRARIES: $(toolexeclib_LTLIBRARIES)
- @$(NORMAL_INSTALL)
- @list='$(toolexeclib_LTLIBRARIES)'; test -n "$(toolexeclibdir)" || list=; \
- list2=; for p in $$list; do \
- if test -f $$p; then \
- list2="$$list2 $$p"; \
- else :; fi; \
- done; \
- test -z "$$list2" || { \
- echo " $(MKDIR_P) '$(DESTDIR)$(toolexeclibdir)'"; \
- $(MKDIR_P) "$(DESTDIR)$(toolexeclibdir)" || exit 1; \
- echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(toolexeclibdir)'"; \
- $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(toolexeclibdir)"; \
- }
-
-uninstall-toolexeclibLTLIBRARIES:
- @$(NORMAL_UNINSTALL)
- @list='$(toolexeclib_LTLIBRARIES)'; test -n "$(toolexeclibdir)" || list=; \
- for p in $$list; do \
- $(am__strip_dir) \
- echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(toolexeclibdir)/$$f'"; \
- $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(toolexeclibdir)/$$f"; \
- done
-
-clean-toolexeclibLTLIBRARIES:
- -test -z "$(toolexeclib_LTLIBRARIES)" || rm -f $(toolexeclib_LTLIBRARIES)
- @list='$(toolexeclib_LTLIBRARIES)'; for p in $$list; do \
- dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
- test "$$dir" != "$$p" || dir=.; \
- echo "rm -f \"$${dir}/so_locations\""; \
- rm -f "$${dir}/so_locations"; \
- done
-libmudflap.la: $(libmudflap_la_OBJECTS) $(libmudflap_la_DEPENDENCIES) $(EXTRA_libmudflap_la_DEPENDENCIES)
- $(libmudflap_la_LINK) -rpath $(toolexeclibdir) $(libmudflap_la_OBJECTS) $(libmudflap_la_LIBADD) $(LIBS)
-libmudflapth.la: $(libmudflapth_la_OBJECTS) $(libmudflapth_la_DEPENDENCIES) $(EXTRA_libmudflapth_la_DEPENDENCIES)
- $(libmudflapth_la_LINK) $(am_libmudflapth_la_rpath) $(libmudflapth_la_OBJECTS) $(libmudflapth_la_LIBADD) $(LIBS)
-
-mostlyclean-compile:
- -rm -f *.$(OBJEXT)
-
-distclean-compile:
- -rm -f *.tab.c
-
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmudflapth_la-mf-heuristics.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmudflapth_la-mf-hooks1.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmudflapth_la-mf-hooks2.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmudflapth_la-mf-hooks3.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmudflapth_la-mf-runtime.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mf-heuristics.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mf-hooks1.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mf-hooks2.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mf-runtime.Plo@am__quote@
-
-.c.o:
-@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(COMPILE) -c $<
-
-.c.obj:
-@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
-
-.c.lo:
-@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
-
-libmudflapth_la-mf-runtime.lo: mf-runtime.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmudflapth_la_CFLAGS) $(CFLAGS) -MT libmudflapth_la-mf-runtime.lo -MD -MP -MF $(DEPDIR)/libmudflapth_la-mf-runtime.Tpo -c -o libmudflapth_la-mf-runtime.lo `test -f 'mf-runtime.c' || echo '$(srcdir)/'`mf-runtime.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libmudflapth_la-mf-runtime.Tpo $(DEPDIR)/libmudflapth_la-mf-runtime.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='mf-runtime.c' object='libmudflapth_la-mf-runtime.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmudflapth_la_CFLAGS) $(CFLAGS) -c -o libmudflapth_la-mf-runtime.lo `test -f 'mf-runtime.c' || echo '$(srcdir)/'`mf-runtime.c
-
-libmudflapth_la-mf-heuristics.lo: mf-heuristics.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmudflapth_la_CFLAGS) $(CFLAGS) -MT libmudflapth_la-mf-heuristics.lo -MD -MP -MF $(DEPDIR)/libmudflapth_la-mf-heuristics.Tpo -c -o libmudflapth_la-mf-heuristics.lo `test -f 'mf-heuristics.c' || echo '$(srcdir)/'`mf-heuristics.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libmudflapth_la-mf-heuristics.Tpo $(DEPDIR)/libmudflapth_la-mf-heuristics.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='mf-heuristics.c' object='libmudflapth_la-mf-heuristics.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmudflapth_la_CFLAGS) $(CFLAGS) -c -o libmudflapth_la-mf-heuristics.lo `test -f 'mf-heuristics.c' || echo '$(srcdir)/'`mf-heuristics.c
-
-libmudflapth_la-mf-hooks1.lo: mf-hooks1.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmudflapth_la_CFLAGS) $(CFLAGS) -MT libmudflapth_la-mf-hooks1.lo -MD -MP -MF $(DEPDIR)/libmudflapth_la-mf-hooks1.Tpo -c -o libmudflapth_la-mf-hooks1.lo `test -f 'mf-hooks1.c' || echo '$(srcdir)/'`mf-hooks1.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libmudflapth_la-mf-hooks1.Tpo $(DEPDIR)/libmudflapth_la-mf-hooks1.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='mf-hooks1.c' object='libmudflapth_la-mf-hooks1.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmudflapth_la_CFLAGS) $(CFLAGS) -c -o libmudflapth_la-mf-hooks1.lo `test -f 'mf-hooks1.c' || echo '$(srcdir)/'`mf-hooks1.c
-
-libmudflapth_la-mf-hooks2.lo: mf-hooks2.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmudflapth_la_CFLAGS) $(CFLAGS) -MT libmudflapth_la-mf-hooks2.lo -MD -MP -MF $(DEPDIR)/libmudflapth_la-mf-hooks2.Tpo -c -o libmudflapth_la-mf-hooks2.lo `test -f 'mf-hooks2.c' || echo '$(srcdir)/'`mf-hooks2.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libmudflapth_la-mf-hooks2.Tpo $(DEPDIR)/libmudflapth_la-mf-hooks2.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='mf-hooks2.c' object='libmudflapth_la-mf-hooks2.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmudflapth_la_CFLAGS) $(CFLAGS) -c -o libmudflapth_la-mf-hooks2.lo `test -f 'mf-hooks2.c' || echo '$(srcdir)/'`mf-hooks2.c
-
-libmudflapth_la-mf-hooks3.lo: mf-hooks3.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmudflapth_la_CFLAGS) $(CFLAGS) -MT libmudflapth_la-mf-hooks3.lo -MD -MP -MF $(DEPDIR)/libmudflapth_la-mf-hooks3.Tpo -c -o libmudflapth_la-mf-hooks3.lo `test -f 'mf-hooks3.c' || echo '$(srcdir)/'`mf-hooks3.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libmudflapth_la-mf-hooks3.Tpo $(DEPDIR)/libmudflapth_la-mf-hooks3.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='mf-hooks3.c' object='libmudflapth_la-mf-hooks3.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmudflapth_la_CFLAGS) $(CFLAGS) -c -o libmudflapth_la-mf-hooks3.lo `test -f 'mf-hooks3.c' || echo '$(srcdir)/'`mf-hooks3.c
-
-mostlyclean-libtool:
- -rm -f *.lo
-
-clean-libtool:
- -rm -rf .libs _libs
-
-distclean-libtool:
- -rm -f libtool config.lt
-
-# GNU Make needs to see an explicit $(MAKE) variable in the command it
-# runs to enable its job server during parallel builds. Hence the
-# comments below.
-all-multi:
- $(MULTIDO) $(AM_MAKEFLAGS) DO=all multi-do # $(MAKE)
-install-multi:
- $(MULTIDO) $(AM_MAKEFLAGS) DO=install multi-do # $(MAKE)
-
-mostlyclean-multi:
- $(MULTICLEAN) $(AM_MAKEFLAGS) DO=mostlyclean multi-clean # $(MAKE)
-clean-multi:
- $(MULTICLEAN) $(AM_MAKEFLAGS) DO=clean multi-clean # $(MAKE)
-distclean-multi:
- $(MULTICLEAN) $(AM_MAKEFLAGS) DO=distclean multi-clean # $(MAKE)
-maintainer-clean-multi:
- $(MULTICLEAN) $(AM_MAKEFLAGS) DO=maintainer-clean multi-clean # $(MAKE)
-install-nobase_libsubincludeHEADERS: $(nobase_libsubinclude_HEADERS)
- @$(NORMAL_INSTALL)
- @list='$(nobase_libsubinclude_HEADERS)'; test -n "$(libsubincludedir)" || list=; \
- if test -n "$$list"; then \
- echo " $(MKDIR_P) '$(DESTDIR)$(libsubincludedir)'"; \
- $(MKDIR_P) "$(DESTDIR)$(libsubincludedir)" || exit 1; \
- fi; \
- $(am__nobase_list) | while read dir files; do \
- xfiles=; for file in $$files; do \
- if test -f "$$file"; then xfiles="$$xfiles $$file"; \
- else xfiles="$$xfiles $(srcdir)/$$file"; fi; done; \
- test -z "$$xfiles" || { \
- test "x$$dir" = x. || { \
- echo " $(MKDIR_P) '$(DESTDIR)$(libsubincludedir)/$$dir'"; \
- $(MKDIR_P) "$(DESTDIR)$(libsubincludedir)/$$dir"; }; \
- echo " $(INSTALL_HEADER) $$xfiles '$(DESTDIR)$(libsubincludedir)/$$dir'"; \
- $(INSTALL_HEADER) $$xfiles "$(DESTDIR)$(libsubincludedir)/$$dir" || exit $$?; }; \
- done
-
-uninstall-nobase_libsubincludeHEADERS:
- @$(NORMAL_UNINSTALL)
- @list='$(nobase_libsubinclude_HEADERS)'; test -n "$(libsubincludedir)" || list=; \
- $(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \
- dir='$(DESTDIR)$(libsubincludedir)'; $(am__uninstall_files_from_dir)
-
-# This directory's subdirectories are mostly independent; you can cd
-# into them and run `make' without going through this Makefile.
-# To change the values of `make' variables: instead of editing Makefiles,
-# (1) if the variable is set in `config.status', edit `config.status'
-# (which will cause the Makefiles to be regenerated when you run `make');
-# (2) otherwise, pass the desired values on the `make' command line.
-$(RECURSIVE_TARGETS):
- @fail= failcom='exit 1'; \
- for f in x $$MAKEFLAGS; do \
- case $$f in \
- *=* | --[!k]*);; \
- *k*) failcom='fail=yes';; \
- esac; \
- done; \
- dot_seen=no; \
- target=`echo $@ | sed s/-recursive//`; \
- list='$(SUBDIRS)'; for subdir in $$list; do \
- echo "Making $$target in $$subdir"; \
- if test "$$subdir" = "."; then \
- dot_seen=yes; \
- local_target="$$target-am"; \
- else \
- local_target="$$target"; \
- fi; \
- ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
- || eval $$failcom; \
- done; \
- if test "$$dot_seen" = "no"; then \
- $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
- fi; test -z "$$fail"
-
-$(RECURSIVE_CLEAN_TARGETS):
- @fail= failcom='exit 1'; \
- for f in x $$MAKEFLAGS; do \
- case $$f in \
- *=* | --[!k]*);; \
- *k*) failcom='fail=yes';; \
- esac; \
- done; \
- dot_seen=no; \
- case "$@" in \
- distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
- *) list='$(SUBDIRS)' ;; \
- esac; \
- rev=''; for subdir in $$list; do \
- if test "$$subdir" = "."; then :; else \
- rev="$$subdir $$rev"; \
- fi; \
- done; \
- rev="$$rev ."; \
- target=`echo $@ | sed s/-recursive//`; \
- for subdir in $$rev; do \
- echo "Making $$target in $$subdir"; \
- if test "$$subdir" = "."; then \
- local_target="$$target-am"; \
- else \
- local_target="$$target"; \
- fi; \
- ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
- || eval $$failcom; \
- done && test -z "$$fail"
-tags-recursive:
- list='$(SUBDIRS)'; for subdir in $$list; do \
- test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
- done
-ctags-recursive:
- list='$(SUBDIRS)'; for subdir in $$list; do \
- test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
- done
-
-ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
- unique=`for i in $$list; do \
- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
- done | \
- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
- END { if (nonempty) { for (i in files) print i; }; }'`; \
- mkid -fID $$unique
-tags: TAGS
-
-TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
- $(TAGS_FILES) $(LISP)
- set x; \
- here=`pwd`; \
- if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
- include_option=--etags-include; \
- empty_fix=.; \
- else \
- include_option=--include; \
- empty_fix=; \
- fi; \
- list='$(SUBDIRS)'; for subdir in $$list; do \
- if test "$$subdir" = .; then :; else \
- test ! -f $$subdir/TAGS || \
- set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
- fi; \
- done; \
- list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
- unique=`for i in $$list; do \
- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
- done | \
- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
- END { if (nonempty) { for (i in files) print i; }; }'`; \
- shift; \
- if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
- test -n "$$unique" || unique=$$empty_fix; \
- if test $$# -gt 0; then \
- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
- "$$@" $$unique; \
- else \
- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
- $$unique; \
- fi; \
- fi
-ctags: CTAGS
-CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
- $(TAGS_FILES) $(LISP)
- list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
- unique=`for i in $$list; do \
- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
- done | \
- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
- END { if (nonempty) { for (i in files) print i; }; }'`; \
- test -z "$(CTAGS_ARGS)$$unique" \
- || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
- $$unique
-
-GTAGS:
- here=`$(am__cd) $(top_builddir) && pwd` \
- && $(am__cd) $(top_srcdir) \
- && gtags -i $(GTAGS_ARGS) "$$here"
-
-distclean-tags:
- -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
-check-am: all-am
-check: check-recursive
-all-am: Makefile $(LTLIBRARIES) all-multi $(HEADERS) config.h
-installdirs: installdirs-recursive
-installdirs-am:
- for dir in "$(DESTDIR)$(toolexeclibdir)" "$(DESTDIR)$(libsubincludedir)"; do \
- test -z "$$dir" || $(MKDIR_P) "$$dir"; \
- done
-install: install-recursive
-install-exec: install-exec-recursive
-install-data: install-data-recursive
-uninstall: uninstall-recursive
-
-install-am: all-am
- @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
-
-installcheck: installcheck-recursive
-install-strip:
- if test -z '$(STRIP)'; then \
- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
- install; \
- else \
- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
- "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
- fi
-mostlyclean-generic:
-
-clean-generic:
-
-distclean-generic:
- -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
- -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
-
-maintainer-clean-generic:
- @echo "This command is intended for maintainers to use"
- @echo "it deletes files that may require special tools to rebuild."
-clean: clean-multi clean-recursive
-
-clean-am: clean-generic clean-libtool clean-toolexeclibLTLIBRARIES \
- mostlyclean-am
-
-distclean: distclean-multi distclean-recursive
- -rm -f $(am__CONFIG_DISTCLEAN_FILES)
- -rm -rf ./$(DEPDIR)
- -rm -f Makefile
-distclean-am: clean-am distclean-compile distclean-generic \
- distclean-hdr distclean-libtool distclean-tags
-
-dvi: dvi-recursive
-
-dvi-am:
-
-html: html-recursive
-
-html-am:
-
-info: info-recursive
-
-info-am:
-
-install-data-am: install-nobase_libsubincludeHEADERS
-
-install-dvi: install-dvi-recursive
-
-install-dvi-am:
-
-install-exec-am: install-multi install-toolexeclibLTLIBRARIES
-
-install-html: install-html-recursive
-
-install-html-am:
-
-install-info: install-info-recursive
-
-install-info-am:
-
-install-man:
-
-install-pdf: install-pdf-recursive
-
-install-pdf-am:
-
-install-ps: install-ps-recursive
-
-install-ps-am:
-
-installcheck-am:
-
-maintainer-clean: maintainer-clean-multi maintainer-clean-recursive
- -rm -f $(am__CONFIG_DISTCLEAN_FILES)
- -rm -rf $(top_srcdir)/autom4te.cache
- -rm -rf ./$(DEPDIR)
- -rm -f Makefile
-maintainer-clean-am: distclean-am maintainer-clean-generic
-
-mostlyclean: mostlyclean-multi mostlyclean-recursive
-
-mostlyclean-am: mostlyclean-compile mostlyclean-generic \
- mostlyclean-libtool
-
-pdf: pdf-recursive
-
-pdf-am:
-
-ps: ps-recursive
-
-ps-am:
-
-uninstall-am: uninstall-nobase_libsubincludeHEADERS \
- uninstall-toolexeclibLTLIBRARIES
-
-.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) all all-multi \
- clean-multi ctags-recursive distclean-multi install-am \
- install-multi install-strip maintainer-clean-multi \
- mostlyclean-multi tags-recursive
-
-.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
- all all-am all-multi am--refresh check check-am clean \
- clean-generic clean-libtool clean-multi \
- clean-toolexeclibLTLIBRARIES ctags ctags-recursive distclean \
- distclean-compile distclean-generic distclean-hdr \
- distclean-libtool distclean-multi distclean-tags dvi dvi-am \
- html html-am info info-am install install-am install-data \
- install-data-am install-dvi install-dvi-am install-exec \
- install-exec-am install-html install-html-am install-info \
- install-info-am install-man install-multi \
- install-nobase_libsubincludeHEADERS install-pdf install-pdf-am \
- install-ps install-ps-am install-strip \
- install-toolexeclibLTLIBRARIES installcheck installcheck-am \
- installdirs installdirs-am maintainer-clean \
- maintainer-clean-generic maintainer-clean-multi mostlyclean \
- mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
- mostlyclean-multi pdf pdf-am ps ps-am tags tags-recursive \
- uninstall uninstall-am uninstall-nobase_libsubincludeHEADERS \
- uninstall-toolexeclibLTLIBRARIES
-
-
-# Tell versions [3.59,3.63) of GNU make to not export all variables.
-# Otherwise a system limit (for SysV at least) may be exceeded.
-.NOEXPORT:
diff --git a/libmudflap/acinclude.m4 b/libmudflap/acinclude.m4
deleted file mode 100644
index 38e0808ad93..00000000000
--- a/libmudflap/acinclude.m4
+++ /dev/null
@@ -1,12 +0,0 @@
-dnl ----------------------------------------------------------------------
-dnl This whole bit snagged from libgfortran.
-
-sinclude(../libtool.m4)
-dnl The lines below arrange for aclocal not to bring an installed
-dnl libtool.m4 into aclocal.m4, while still arranging for automake to
-dnl add a definition of LIBTOOL to Makefile.in.
-ifelse(,,,[AC_SUBST(LIBTOOL)
-AC_DEFUN([AM_PROG_LIBTOOL])
-AC_DEFUN([AC_LIBTOOL_DLOPEN])
-AC_DEFUN([AC_PROG_LD])
-])
diff --git a/libmudflap/aclocal.m4 b/libmudflap/aclocal.m4
deleted file mode 100644
index fb5a1ededac..00000000000
--- a/libmudflap/aclocal.m4
+++ /dev/null
@@ -1,1002 +0,0 @@
-# generated automatically by aclocal 1.11.6 -*- Autoconf -*-
-
-# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-# 2005, 2006, 2007, 2008, 2009, 2010, 2011 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_AUTOCONF_VERSION],
- [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
-m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.64],,
-[m4_warning([this file was generated for autoconf 2.64.
-You have another version of autoconf. It may work, but is not guaranteed to.
-If you have problems, you may need to regenerate the build system entirely.
-To do so, use the procedure documented by the package, typically `autoreconf'.])])
-
-# Copyright (C) 2002, 2003, 2005, 2006, 2007, 2008, 2011 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.
-
-# serial 1
-
-# AM_AUTOMAKE_VERSION(VERSION)
-# ----------------------------
-# Automake X.Y traces this macro to ensure aclocal.m4 has been
-# generated from the m4 files accompanying Automake X.Y.
-# (This private macro should not be called outside this file.)
-AC_DEFUN([AM_AUTOMAKE_VERSION],
-[am__api_version='1.11'
-dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
-dnl require some minimum version. Point them to the right macro.
-m4_if([$1], [1.11.6], [],
- [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
-])
-
-# _AM_AUTOCONF_VERSION(VERSION)
-# -----------------------------
-# aclocal traces this macro to find the Autoconf version.
-# This is a private macro too. Using m4_define simplifies
-# the logic in aclocal, which can simply ignore this definition.
-m4_define([_AM_AUTOCONF_VERSION], [])
-
-# AM_SET_CURRENT_AUTOMAKE_VERSION
-# -------------------------------
-# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
-# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
-AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
-[AM_AUTOMAKE_VERSION([1.11.6])dnl
-m4_ifndef([AC_AUTOCONF_VERSION],
- [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
-_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
-
-# AM_AUX_DIR_EXPAND -*- Autoconf -*-
-
-# Copyright (C) 2001, 2003, 2005, 2011 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.
-
-# serial 1
-
-# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
-# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to
-# `$srcdir', `$srcdir/..', or `$srcdir/../..'.
-#
-# Of course, Automake must honor this variable whenever it calls a
-# tool from the auxiliary directory. The problem is that $srcdir (and
-# therefore $ac_aux_dir as well) can be either absolute or relative,
-# depending on how configure is run. This is pretty annoying, since
-# it makes $ac_aux_dir quite unusable in subdirectories: in the top
-# source directory, any form will work fine, but in subdirectories a
-# relative path needs to be adjusted first.
-#
-# $ac_aux_dir/missing
-# fails when called from a subdirectory if $ac_aux_dir is relative
-# $top_srcdir/$ac_aux_dir/missing
-# fails if $ac_aux_dir is absolute,
-# fails when called from a subdirectory in a VPATH build with
-# a relative $ac_aux_dir
-#
-# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
-# are both prefixed by $srcdir. In an in-source build this is usually
-# harmless because $srcdir is `.', but things will broke when you
-# start a VPATH build or use an absolute $srcdir.
-#
-# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
-# iff we strip the leading $srcdir from $ac_aux_dir. That would be:
-# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
-# and then we would define $MISSING as
-# MISSING="\${SHELL} $am_aux_dir/missing"
-# This will work as long as MISSING is not called from configure, because
-# unfortunately $(top_srcdir) has no meaning in configure.
-# However there are other variables, like CC, which are often used in
-# configure, and could therefore not use this "fixed" $ac_aux_dir.
-#
-# Another solution, used here, is to always expand $ac_aux_dir to an
-# absolute PATH. The drawback is that using absolute paths prevent a
-# configured tree to be moved without reconfiguration.
-
-AC_DEFUN([AM_AUX_DIR_EXPAND],
-[dnl Rely on autoconf to set up CDPATH properly.
-AC_PREREQ([2.50])dnl
-# expand $ac_aux_dir to an absolute path
-am_aux_dir=`cd $ac_aux_dir && pwd`
-])
-
-# AM_CONDITIONAL -*- Autoconf -*-
-
-# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006, 2008
-# 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.
-
-# serial 9
-
-# AM_CONDITIONAL(NAME, SHELL-CONDITION)
-# -------------------------------------
-# Define a conditional.
-AC_DEFUN([AM_CONDITIONAL],
-[AC_PREREQ(2.52)dnl
- ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])],
- [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
-AC_SUBST([$1_TRUE])dnl
-AC_SUBST([$1_FALSE])dnl
-_AM_SUBST_NOTMAKE([$1_TRUE])dnl
-_AM_SUBST_NOTMAKE([$1_FALSE])dnl
-m4_define([_AM_COND_VALUE_$1], [$2])dnl
-if $2; then
- $1_TRUE=
- $1_FALSE='#'
-else
- $1_TRUE='#'
- $1_FALSE=
-fi
-AC_CONFIG_COMMANDS_PRE(
-[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
- AC_MSG_ERROR([[conditional "$1" was never defined.
-Usually this means the macro was only invoked conditionally.]])
-fi])])
-
-# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009,
-# 2010, 2011 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.
-
-# serial 12
-
-# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be
-# written in clear, in which case automake, when reading aclocal.m4,
-# will think it sees a *use*, and therefore will trigger all it's
-# C support machinery. Also note that it means that autoscan, seeing
-# CC etc. in the Makefile, will ask for an AC_PROG_CC use...
-
-
-# _AM_DEPENDENCIES(NAME)
-# ----------------------
-# See how the compiler implements dependency checking.
-# NAME is "CC", "CXX", "GCJ", or "OBJC".
-# We try a few techniques and use that to set a single cache variable.
-#
-# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was
-# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular
-# dependency, and given that the user is not expected to run this macro,
-# just rely on AC_PROG_CC.
-AC_DEFUN([_AM_DEPENDENCIES],
-[AC_REQUIRE([AM_SET_DEPDIR])dnl
-AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl
-AC_REQUIRE([AM_MAKE_INCLUDE])dnl
-AC_REQUIRE([AM_DEP_TRACK])dnl
-
-ifelse([$1], CC, [depcc="$CC" am_compiler_list=],
- [$1], CXX, [depcc="$CXX" am_compiler_list=],
- [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'],
- [$1], UPC, [depcc="$UPC" am_compiler_list=],
- [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'],
- [depcc="$$1" am_compiler_list=])
-
-AC_CACHE_CHECK([dependency style of $depcc],
- [am_cv_$1_dependencies_compiler_type],
-[if test -z "$AMDEP_TRUE" && 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'.
- rm -rf conftest.dir
- 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_$1_dependencies_compiler_type=none
- if test "$am_compiler_list" = ""; then
- am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp`
- fi
- am__universal=false
- m4_case([$1], [CC],
- [case " $depcc " in #(
- *\ -arch\ *\ -arch\ *) am__universal=true ;;
- esac],
- [CXX],
- [case " $depcc " in #(
- *\ -arch\ *\ -arch\ *) am__universal=true ;;
- esac])
-
- for depmode in $am_compiler_list; do
- # 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 "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > 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. Also, some Intel
- # versions had trouble with output in subdirs
- am__obj=sub/conftest.${OBJEXT-o}
- am__minus_obj="-o $am__obj"
- case $depmode in
- gcc)
- # This depmode causes a compiler race in universal mode.
- test "$am__universal" = false || continue
- ;;
- nosideeffect)
- # after this tag, mechanisms are not by side-effect, so they'll
- # only be used when explicitly requested
- if test "x$enable_dependency_tracking" = xyes; then
- continue
- else
- break
- fi
- ;;
- msvc7 | msvc7msys | msvisualcpp | msvcmsys)
- # This compiler won't grok `-c -o', but also, the minuso test has
- # not run yet. These depmodes are late enough in the game, and
- # so weak that their functioning should not be impacted.
- am__obj=conftest.${OBJEXT-o}
- am__minus_obj=
- ;;
- none) break ;;
- esac
- if depmode=$depmode \
- source=sub/conftest.c object=$am__obj \
- depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
- $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
- >/dev/null 2>conftest.err &&
- grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
- grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
- grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
- ${MAKE-make} -s -f confmf > /dev/null 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_$1_dependencies_compiler_type=$depmode
- break
- fi
- fi
- done
-
- cd ..
- rm -rf conftest.dir
-else
- am_cv_$1_dependencies_compiler_type=none
-fi
-])
-AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type])
-AM_CONDITIONAL([am__fastdep$1], [
- test "x$enable_dependency_tracking" != xno \
- && test "$am_cv_$1_dependencies_compiler_type" = gcc3])
-])
-
-
-# AM_SET_DEPDIR
-# -------------
-# Choose a directory name for dependency files.
-# This macro is AC_REQUIREd in _AM_DEPENDENCIES
-AC_DEFUN([AM_SET_DEPDIR],
-[AC_REQUIRE([AM_SET_LEADING_DOT])dnl
-AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl
-])
-
-
-# AM_DEP_TRACK
-# ------------
-AC_DEFUN([AM_DEP_TRACK],
-[AC_ARG_ENABLE(dependency-tracking,
-[ --disable-dependency-tracking speeds up one-time build
- --enable-dependency-tracking do not reject slow dependency extractors])
-if test "x$enable_dependency_tracking" != xno; then
- am_depcomp="$ac_aux_dir/depcomp"
- AMDEPBACKSLASH='\'
- am__nodep='_no'
-fi
-AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
-AC_SUBST([AMDEPBACKSLASH])dnl
-_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl
-AC_SUBST([am__nodep])dnl
-_AM_SUBST_NOTMAKE([am__nodep])dnl
-])
-
-# Generate code to set up dependency tracking. -*- Autoconf -*-
-
-# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008
-# 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.
-
-#serial 5
-
-# _AM_OUTPUT_DEPENDENCY_COMMANDS
-# ------------------------------
-AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
-[{
- # Autoconf 2.62 quotes --file arguments for eval, but not when files
- # are listed without --file. Let's play safe and only enable the eval
- # if we detect the quoting.
- case $CONFIG_FILES in
- *\'*) eval set x "$CONFIG_FILES" ;;
- *) set x $CONFIG_FILES ;;
- esac
- shift
- for mf
- do
- # Strip MF so we end up with the name of the file.
- mf=`echo "$mf" | sed -e 's/:.*$//'`
- # Check whether this is an Automake generated Makefile or not.
- # We used to match only the files named `Makefile.in', but
- # some people rename them; so instead we look at the file content.
- # Grep'ing the first line is not enough: some people post-process
- # each Makefile.in and add a new line on top of each file to say so.
- # Grep'ing the whole file is not good either: AIX grep has a line
- # limit of 2048, but all sed's we know have understand at least 4000.
- if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
- dirpart=`AS_DIRNAME("$mf")`
- else
- continue
- fi
- # Extract the definition of DEPDIR, am__include, and am__quote
- # from the Makefile without running `make'.
- DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
- test -z "$DEPDIR" && continue
- am__include=`sed -n 's/^am__include = //p' < "$mf"`
- test -z "am__include" && continue
- am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
- # When using ansi2knr, U may be empty or an underscore; expand it
- U=`sed -n 's/^U = //p' < "$mf"`
- # Find all dependency output files, they are included files with
- # $(DEPDIR) in their names. We invoke sed twice because it is the
- # simplest approach to changing $(DEPDIR) to its actual value in the
- # expansion.
- for file in `sed -n "
- s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
- sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
- # Make sure the directory exists.
- test -f "$dirpart/$file" && continue
- fdir=`AS_DIRNAME(["$file"])`
- AS_MKDIR_P([$dirpart/$fdir])
- # echo "creating $dirpart/$file"
- echo '# dummy' > "$dirpart/$file"
- done
- done
-}
-])# _AM_OUTPUT_DEPENDENCY_COMMANDS
-
-
-# AM_OUTPUT_DEPENDENCY_COMMANDS
-# -----------------------------
-# This macro should only be invoked once -- use via AC_REQUIRE.
-#
-# This code is only required when automatic dependency tracking
-# is enabled. FIXME. This creates each `.P' file that we will
-# need in order to bootstrap the dependency handling code.
-AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
-[AC_CONFIG_COMMANDS([depfiles],
- [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS],
- [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"])
-])
-
-# Do all the work for Automake. -*- Autoconf -*-
-
-# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-# 2005, 2006, 2008, 2009 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.
-
-# serial 16
-
-# This macro actually does too much. Some checks are only needed if
-# your package does certain things. But this isn't really a big deal.
-
-# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
-# AM_INIT_AUTOMAKE([OPTIONS])
-# -----------------------------------------------
-# The call with PACKAGE and VERSION arguments is the old style
-# call (pre autoconf-2.50), which is being phased out. PACKAGE
-# and VERSION should now be passed to AC_INIT and removed from
-# the call to AM_INIT_AUTOMAKE.
-# We support both call styles for the transition. After
-# the next Automake release, Autoconf can make the AC_INIT
-# arguments mandatory, and then we can depend on a new Autoconf
-# release and drop the old call support.
-AC_DEFUN([AM_INIT_AUTOMAKE],
-[AC_PREREQ([2.62])dnl
-dnl Autoconf wants to disallow AM_ names. We explicitly allow
-dnl the ones we care about.
-m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
-AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
-AC_REQUIRE([AC_PROG_INSTALL])dnl
-if test "`cd $srcdir && pwd`" != "`pwd`"; then
- # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
- # is not polluted with repeated "-I."
- AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl
- # test to see if srcdir already configured
- if test -f $srcdir/config.status; then
- AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
- fi
-fi
-
-# test whether we have cygpath
-if test -z "$CYGPATH_W"; then
- if (cygpath --version) >/dev/null 2>/dev/null; then
- CYGPATH_W='cygpath -w'
- else
- CYGPATH_W=echo
- fi
-fi
-AC_SUBST([CYGPATH_W])
-
-# Define the identity of the package.
-dnl Distinguish between old-style and new-style calls.
-m4_ifval([$2],
-[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
- AC_SUBST([PACKAGE], [$1])dnl
- AC_SUBST([VERSION], [$2])],
-[_AM_SET_OPTIONS([$1])dnl
-dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
-m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,,
- [m4_fatal([AC_INIT should be called with package and version arguments])])dnl
- AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
- AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
-
-_AM_IF_OPTION([no-define],,
-[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
- AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl
-
-# Some tools Automake needs.
-AC_REQUIRE([AM_SANITY_CHECK])dnl
-AC_REQUIRE([AC_ARG_PROGRAM])dnl
-AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version})
-AM_MISSING_PROG(AUTOCONF, autoconf)
-AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version})
-AM_MISSING_PROG(AUTOHEADER, autoheader)
-AM_MISSING_PROG(MAKEINFO, makeinfo)
-AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
-AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl
-AC_REQUIRE([AM_PROG_MKDIR_P])dnl
-# We need awk for the "check" target. The system "awk" is bad on
-# some platforms.
-AC_REQUIRE([AC_PROG_AWK])dnl
-AC_REQUIRE([AC_PROG_MAKE_SET])dnl
-AC_REQUIRE([AM_SET_LEADING_DOT])dnl
-_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
- [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
- [_AM_PROG_TAR([v7])])])
-_AM_IF_OPTION([no-dependencies],,
-[AC_PROVIDE_IFELSE([AC_PROG_CC],
- [_AM_DEPENDENCIES(CC)],
- [define([AC_PROG_CC],
- defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl
-AC_PROVIDE_IFELSE([AC_PROG_CXX],
- [_AM_DEPENDENCIES(CXX)],
- [define([AC_PROG_CXX],
- defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl
-AC_PROVIDE_IFELSE([AC_PROG_OBJC],
- [_AM_DEPENDENCIES(OBJC)],
- [define([AC_PROG_OBJC],
- defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl
-])
-_AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl
-dnl The `parallel-tests' driver may need to know about EXEEXT, so add the
-dnl `am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This macro
-dnl is hooked onto _AC_COMPILER_EXEEXT early, see below.
-AC_CONFIG_COMMANDS_PRE(dnl
-[m4_provide_if([_AM_COMPILER_EXEEXT],
- [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl
-])
-
-dnl Hook into `_AC_COMPILER_EXEEXT' early to learn its expansion. Do not
-dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further
-dnl mangled by Autoconf and run in a shell conditional statement.
-m4_define([_AC_COMPILER_EXEEXT],
-m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])])
-
-
-# When config.status generates a header, we must update the stamp-h file.
-# This file resides in the same directory as the config header
-# that is generated. The stamp files are numbered to have different names.
-
-# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
-# loop where config.status creates the headers, so we can generate
-# our stamp files there.
-AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
-[# Compute $1's index in $config_headers.
-_am_arg=$1
-_am_stamp_count=1
-for _am_header in $config_headers :; do
- case $_am_header in
- $_am_arg | $_am_arg:* )
- break ;;
- * )
- _am_stamp_count=`expr $_am_stamp_count + 1` ;;
- esac
-done
-echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
-
-# Copyright (C) 2001, 2003, 2005, 2008, 2011 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.
-
-# serial 1
-
-# AM_PROG_INSTALL_SH
-# ------------------
-# Define $install_sh.
-AC_DEFUN([AM_PROG_INSTALL_SH],
-[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
-if test x"${install_sh}" != xset; then
- case $am_aux_dir in
- *\ * | *\ *)
- install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
- *)
- install_sh="\${SHELL} $am_aux_dir/install-sh"
- esac
-fi
-AC_SUBST(install_sh)])
-
-# Add --enable-maintainer-mode option to configure. -*- Autoconf -*-
-# From Jim Meyering
-
-# Copyright (C) 1996, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2008,
-# 2011 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.
-
-# serial 5
-
-# AM_MAINTAINER_MODE([DEFAULT-MODE])
-# ----------------------------------
-# Control maintainer-specific portions of Makefiles.
-# Default is to disable them, unless `enable' is passed literally.
-# For symmetry, `disable' may be passed as well. Anyway, the user
-# can override the default with the --enable/--disable switch.
-AC_DEFUN([AM_MAINTAINER_MODE],
-[m4_case(m4_default([$1], [disable]),
- [enable], [m4_define([am_maintainer_other], [disable])],
- [disable], [m4_define([am_maintainer_other], [enable])],
- [m4_define([am_maintainer_other], [enable])
- m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])])
-AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
- dnl maintainer-mode's default is 'disable' unless 'enable' is passed
- AC_ARG_ENABLE([maintainer-mode],
-[ --][am_maintainer_other][-maintainer-mode am_maintainer_other make rules and dependencies not useful
- (and sometimes confusing) to the casual installer],
- [USE_MAINTAINER_MODE=$enableval],
- [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes]))
- AC_MSG_RESULT([$USE_MAINTAINER_MODE])
- AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes])
- MAINT=$MAINTAINER_MODE_TRUE
- AC_SUBST([MAINT])dnl
-]
-)
-
-AU_DEFUN([jm_MAINTAINER_MODE], [AM_MAINTAINER_MODE])
-
-# Check to see how 'make' treats includes. -*- Autoconf -*-
-
-# Copyright (C) 2001, 2002, 2003, 2005, 2009 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.
-
-# serial 4
-
-# AM_MAKE_INCLUDE()
-# -----------------
-# Check to see how make treats includes.
-AC_DEFUN([AM_MAKE_INCLUDE],
-[am_make=${MAKE-make}
-cat > confinc << 'END'
-am__doit:
- @echo this is the am__doit target
-.PHONY: am__doit
-END
-# If we don't find an include directive, just comment out the code.
-AC_MSG_CHECKING([for style of include used by $am_make])
-am__include="#"
-am__quote=
-_am_result=none
-# First try GNU make style include.
-echo "include confinc" > confmf
-# Ignore all kinds of additional output from `make'.
-case `$am_make -s -f confmf 2> /dev/null` in #(
-*the\ am__doit\ target*)
- am__include=include
- am__quote=
- _am_result=GNU
- ;;
-esac
-# Now try BSD make style include.
-if test "$am__include" = "#"; then
- echo '.include "confinc"' > confmf
- case `$am_make -s -f confmf 2> /dev/null` in #(
- *the\ am__doit\ target*)
- am__include=.include
- am__quote="\""
- _am_result=BSD
- ;;
- esac
-fi
-AC_SUBST([am__include])
-AC_SUBST([am__quote])
-AC_MSG_RESULT([$_am_result])
-rm -f confinc confmf
-])
-
-# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
-
-# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005, 2008
-# 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.
-
-# serial 6
-
-# AM_MISSING_PROG(NAME, PROGRAM)
-# ------------------------------
-AC_DEFUN([AM_MISSING_PROG],
-[AC_REQUIRE([AM_MISSING_HAS_RUN])
-$1=${$1-"${am_missing_run}$2"}
-AC_SUBST($1)])
-
-
-# AM_MISSING_HAS_RUN
-# ------------------
-# Define MISSING if not defined so far and test if it supports --run.
-# If it does, set am_missing_run to use it, otherwise, to nothing.
-AC_DEFUN([AM_MISSING_HAS_RUN],
-[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
-AC_REQUIRE_AUX_FILE([missing])dnl
-if test x"${MISSING+set}" != xset; then
- case $am_aux_dir in
- *\ * | *\ *)
- MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
- *)
- MISSING="\${SHELL} $am_aux_dir/missing" ;;
- esac
-fi
-# Use eval to expand $SHELL
-if eval "$MISSING --run true"; then
- am_missing_run="$MISSING --run "
-else
- am_missing_run=
- AC_MSG_WARN([`missing' script is too old or missing])
-fi
-])
-
-# Copyright (C) 2003, 2004, 2005, 2006, 2011 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.
-
-# serial 1
-
-# AM_PROG_MKDIR_P
-# ---------------
-# Check for `mkdir -p'.
-AC_DEFUN([AM_PROG_MKDIR_P],
-[AC_PREREQ([2.60])dnl
-AC_REQUIRE([AC_PROG_MKDIR_P])dnl
-dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P,
-dnl while keeping a definition of mkdir_p for backward compatibility.
-dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile.
-dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of
-dnl Makefile.ins that do not define MKDIR_P, so we do our own
-dnl adjustment using top_builddir (which is defined more often than
-dnl MKDIR_P).
-AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl
-case $mkdir_p in
- [[\\/$]]* | ?:[[\\/]]*) ;;
- */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;;
-esac
-])
-
-# Helper functions for option handling. -*- Autoconf -*-
-
-# Copyright (C) 2001, 2002, 2003, 2005, 2008, 2010 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.
-
-# serial 5
-
-# _AM_MANGLE_OPTION(NAME)
-# -----------------------
-AC_DEFUN([_AM_MANGLE_OPTION],
-[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
-
-# _AM_SET_OPTION(NAME)
-# --------------------
-# Set option NAME. Presently that only means defining a flag for this option.
-AC_DEFUN([_AM_SET_OPTION],
-[m4_define(_AM_MANGLE_OPTION([$1]), 1)])
-
-# _AM_SET_OPTIONS(OPTIONS)
-# ------------------------
-# OPTIONS is a space-separated list of Automake options.
-AC_DEFUN([_AM_SET_OPTIONS],
-[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
-
-# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
-# -------------------------------------------
-# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
-AC_DEFUN([_AM_IF_OPTION],
-[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
-
-# Check to make sure that the build environment is sane. -*- Autoconf -*-
-
-# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005, 2008
-# 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.
-
-# serial 5
-
-# AM_SANITY_CHECK
-# ---------------
-AC_DEFUN([AM_SANITY_CHECK],
-[AC_MSG_CHECKING([whether build environment is sane])
-# Just in case
-sleep 1
-echo timestamp > conftest.file
-# Reject unsafe characters in $srcdir or the absolute working directory
-# name. Accept space and tab only in the latter.
-am_lf='
-'
-case `pwd` in
- *[[\\\"\#\$\&\'\`$am_lf]]*)
- AC_MSG_ERROR([unsafe absolute working directory name]);;
-esac
-case $srcdir in
- *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*)
- AC_MSG_ERROR([unsafe srcdir value: `$srcdir']);;
-esac
-
-# Do `set' in a subshell so we don't clobber the current shell's
-# arguments. Must try -L first in case configure is actually a
-# symlink; some systems play weird games with the mod time of symlinks
-# (eg FreeBSD returns the mod time of the symlink's containing
-# directory).
-if (
- set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
- if test "$[*]" = "X"; then
- # -L didn't work.
- set X `ls -t "$srcdir/configure" conftest.file`
- fi
- rm -f conftest.file
- if test "$[*]" != "X $srcdir/configure conftest.file" \
- && test "$[*]" != "X conftest.file $srcdir/configure"; then
-
- # If neither matched, then we have a broken ls. This can happen
- # if, for instance, CONFIG_SHELL is bash and it inherits a
- # broken ls alias from the environment. This has actually
- # happened. Such a system could not be considered "sane".
- AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken
-alias in your environment])
- fi
-
- test "$[2]" = conftest.file
- )
-then
- # Ok.
- :
-else
- AC_MSG_ERROR([newly created file is older than distributed files!
-Check your system clock])
-fi
-AC_MSG_RESULT(yes)])
-
-# Copyright (C) 2001, 2003, 2005, 2011 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.
-
-# serial 1
-
-# AM_PROG_INSTALL_STRIP
-# ---------------------
-# One issue with vendor `install' (even GNU) is that you can't
-# specify the program used to strip binaries. This is especially
-# annoying in cross-compiling environments, where the build's strip
-# is unlikely to handle the host's binaries.
-# Fortunately install-sh will honor a STRIPPROG variable, so we
-# always use install-sh in `make install-strip', and initialize
-# STRIPPROG with the value of the STRIP variable (set by the user).
-AC_DEFUN([AM_PROG_INSTALL_STRIP],
-[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
-# Installed binaries are usually stripped using `strip' when the user
-# run `make install-strip'. However `strip' might not be the right
-# tool to use in cross-compilation environments, therefore Automake
-# will honor the `STRIP' environment variable to overrule this program.
-dnl Don't test for $cross_compiling = yes, because it might be `maybe'.
-if test "$cross_compiling" != no; then
- AC_CHECK_TOOL([STRIP], [strip], :)
-fi
-INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
-AC_SUBST([INSTALL_STRIP_PROGRAM])])
-
-# Copyright (C) 2006, 2008, 2010 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.
-
-# serial 3
-
-# _AM_SUBST_NOTMAKE(VARIABLE)
-# ---------------------------
-# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in.
-# This macro is traced by Automake.
-AC_DEFUN([_AM_SUBST_NOTMAKE])
-
-# AM_SUBST_NOTMAKE(VARIABLE)
-# --------------------------
-# Public sister of _AM_SUBST_NOTMAKE.
-AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
-
-# Check how to create a tarball. -*- Autoconf -*-
-
-# Copyright (C) 2004, 2005, 2012 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.
-
-# serial 2
-
-# _AM_PROG_TAR(FORMAT)
-# --------------------
-# Check how to create a tarball in format FORMAT.
-# FORMAT should be one of `v7', `ustar', or `pax'.
-#
-# Substitute a variable $(am__tar) that is a command
-# writing to stdout a FORMAT-tarball containing the directory
-# $tardir.
-# tardir=directory && $(am__tar) > result.tar
-#
-# Substitute a variable $(am__untar) that extract such
-# a tarball read from stdin.
-# $(am__untar) < result.tar
-AC_DEFUN([_AM_PROG_TAR],
-[# Always define AMTAR for backward compatibility. Yes, it's still used
-# in the wild :-( We should find a proper way to deprecate it ...
-AC_SUBST([AMTAR], ['$${TAR-tar}'])
-m4_if([$1], [v7],
- [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'],
- [m4_case([$1], [ustar],, [pax],,
- [m4_fatal([Unknown tar format])])
-AC_MSG_CHECKING([how to create a $1 tar archive])
-# Loop over all known methods to create a tar archive until one works.
-_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
-_am_tools=${am_cv_prog_tar_$1-$_am_tools}
-# Do not fold the above two line into one, because Tru64 sh and
-# Solaris sh will not grok spaces in the rhs of `-'.
-for _am_tool in $_am_tools
-do
- case $_am_tool in
- gnutar)
- for _am_tar in tar gnutar gtar;
- do
- AM_RUN_LOG([$_am_tar --version]) && break
- done
- am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
- am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
- am__untar="$_am_tar -xf -"
- ;;
- plaintar)
- # Must skip GNU tar: if it does not support --format= it doesn't create
- # ustar tarball either.
- (tar --version) >/dev/null 2>&1 && continue
- am__tar='tar chf - "$$tardir"'
- am__tar_='tar chf - "$tardir"'
- am__untar='tar xf -'
- ;;
- pax)
- am__tar='pax -L -x $1 -w "$$tardir"'
- am__tar_='pax -L -x $1 -w "$tardir"'
- am__untar='pax -r'
- ;;
- cpio)
- am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
- am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
- am__untar='cpio -i -H $1 -d'
- ;;
- none)
- am__tar=false
- am__tar_=false
- am__untar=false
- ;;
- esac
-
- # If the value was cached, stop now. We just wanted to have am__tar
- # and am__untar set.
- test -n "${am_cv_prog_tar_$1}" && break
-
- # tar/untar a dummy directory, and stop if the command works
- rm -rf conftest.dir
- mkdir conftest.dir
- echo GrepMe > conftest.dir/file
- AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
- rm -rf conftest.dir
- if test -s conftest.tar; then
- AM_RUN_LOG([$am__untar <conftest.tar])
- grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
- fi
-done
-rm -rf conftest.dir
-
-AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
-AC_MSG_RESULT([$am_cv_prog_tar_$1])])
-AC_SUBST([am__tar])
-AC_SUBST([am__untar])
-]) # _AM_PROG_TAR
-
-m4_include([../config/acx.m4])
-m4_include([../config/depstand.m4])
-m4_include([../config/enable.m4])
-m4_include([../config/lead-dot.m4])
-m4_include([../config/multi.m4])
-m4_include([../config/override.m4])
-m4_include([../config/tls.m4])
-m4_include([../ltoptions.m4])
-m4_include([../ltsugar.m4])
-m4_include([../ltversion.m4])
-m4_include([../lt~obsolete.m4])
-m4_include([acinclude.m4])
diff --git a/libmudflap/config.h.in b/libmudflap/config.h.in
deleted file mode 100644
index ffdd6721c01..00000000000
--- a/libmudflap/config.h.in
+++ /dev/null
@@ -1,308 +0,0 @@
-/* config.h.in. Generated from configure.ac by autoheader. */
-
-/* Define to the name of the symbol used for the entry point. */
-#undef ENTRY_POINT
-
-/* Define to 1 if you have the `addmntent' function. */
-#undef HAVE_ADDMNTENT
-
-/* Define to 1 if you have the <arpa/inet.h> header file. */
-#undef HAVE_ARPA_INET_H
-
-/* Define to 1 if you have the `backtrace' function. */
-#undef HAVE_BACKTRACE
-
-/* Define to 1 if you have the `backtrace_symbols' function. */
-#undef HAVE_BACKTRACE_SYMBOLS
-
-/* Define to 1 if the target assembler supports thread-local storage. */
-#undef HAVE_CC_TLS
-
-/* Define to 1 if you have the <ctype.h> header file. */
-#undef HAVE_CTYPE_H
-
-/* Define to 1 if you have the `cuserid' function. */
-#undef HAVE_CUSERID
-
-/* Define to 1 if you have the <dirent.h> header file. */
-#undef HAVE_DIRENT_H
-
-/* Define to 1 if you have the <dlfcn.h> header file. */
-#undef HAVE_DLFCN_H
-
-/* Define to 1 if you have the `dlvsym' function. */
-#undef HAVE_DLVSYM
-
-/* Define to 1 if you have the <execinfo.h> header file. */
-#undef HAVE_EXECINFO_H
-
-/* Define to 1 if you have the `fopen64' function. */
-#undef HAVE_FOPEN64
-
-/* Define to 1 if you have the `freopen64' function. */
-#undef HAVE_FREOPEN64
-
-/* Define to 1 if you have the `fseeko64' function. */
-#undef HAVE_FSEEKO64
-
-/* Define to 1 if you have the `ftello64' function. */
-#undef HAVE_FTELLO64
-
-/* Define to 1 if you have the `gai_strerror' function. */
-#undef HAVE_GAI_STRERROR
-
-/* Define to 1 if you have the `getaddrinfo' function. */
-#undef HAVE_GETADDRINFO
-
-/* Define to 1 if you have the `getgrent' function. */
-#undef HAVE_GETGRENT
-
-/* Define to 1 if you have the `getgrgid' function. */
-#undef HAVE_GETGRGID
-
-/* Define to 1 if you have the `getgrgid_r' function. */
-#undef HAVE_GETGRGID_R
-
-/* Define to 1 if you have the `getgrnam' function. */
-#undef HAVE_GETGRNAM
-
-/* Define to 1 if you have the `getgrnam_r' function. */
-#undef HAVE_GETGRNAM_R
-
-/* Define to 1 if you have the `getlogin' function. */
-#undef HAVE_GETLOGIN
-
-/* Define to 1 if you have the `getlogin_r' function. */
-#undef HAVE_GETLOGIN_R
-
-/* Define to 1 if you have the `getmntent' function. */
-#undef HAVE_GETMNTENT
-
-/* Define to 1 if you have the `getprotobyname' function. */
-#undef HAVE_GETPROTOBYNAME
-
-/* Define to 1 if you have the `getprotobynumber' function. */
-#undef HAVE_GETPROTOBYNUMBER
-
-/* Define to 1 if you have the `getprotoent' function. */
-#undef HAVE_GETPROTOENT
-
-/* Define to 1 if you have the `getpwent' function. */
-#undef HAVE_GETPWENT
-
-/* Define to 1 if you have the `getpwnam' function. */
-#undef HAVE_GETPWNAM
-
-/* Define to 1 if you have the `getpwnam_r' function. */
-#undef HAVE_GETPWNAM_R
-
-/* Define to 1 if you have the `getpwuid' function. */
-#undef HAVE_GETPWUID
-
-/* Define to 1 if you have the `getpwuid_r' function. */
-#undef HAVE_GETPWUID_R
-
-/* Define to 1 if you have the `getservbyname' function. */
-#undef HAVE_GETSERVBYNAME
-
-/* Define to 1 if you have the `getservbyport' function. */
-#undef HAVE_GETSERVBYPORT
-
-/* Define to 1 if you have the `getservent' function. */
-#undef HAVE_GETSERVENT
-
-/* Define to 1 if you have the `gettimeofday' function. */
-#undef HAVE_GETTIMEOFDAY
-
-/* Define to 1 if you have the <grp.h> header file. */
-#undef HAVE_GRP_H
-
-/* Define to 1 if you have the `inet_ntoa' function. */
-#undef HAVE_INET_NTOA
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-#undef HAVE_INTTYPES_H
-
-/* Define to 1 if you have the `dl' library (-ldl). */
-#undef HAVE_LIBDL
-
-/* Define to 1 if you have the `rt' library (-lrt). */
-#undef HAVE_LIBRT
-
-/* Define to 1 if you have the `socket' library (-lsocket). */
-#undef HAVE_LIBSOCKET
-
-/* Define to 1 if you have the `memmem' function. */
-#undef HAVE_MEMMEM
-
-/* Define to 1 if you have the <memory.h> header file. */
-#undef HAVE_MEMORY_H
-
-/* Define to 1 if you have the `mempcpy' function. */
-#undef HAVE_MEMPCPY
-
-/* Define to 1 if you have the `memrchr' function. */
-#undef HAVE_MEMRCHR
-
-/* Define to 1 if you have the `mmap' function. */
-#undef HAVE_MMAP
-
-/* Define to 1 if you have the `mmap64' function. */
-#undef HAVE_MMAP64
-
-/* Define to 1 if you have the <mntent.h> header file. */
-#undef HAVE_MNTENT_H
-
-/* Define to 1 if you have the `munmap' function. */
-#undef HAVE_MUNMAP
-
-/* Define to 1 if you have the <netdb.h> header file. */
-#undef HAVE_NETDB_H
-
-/* Define to 1 if you have the <netinet/in.h> header file. */
-#undef HAVE_NETINET_IN_H
-
-/* Define to 1 if you have the <pthread.h> header file. */
-#undef HAVE_PTHREAD_H
-
-/* Define to 1 if you have the <pwd.h> header file. */
-#undef HAVE_PWD_H
-
-/* Define to 1 if you have the `rawmemchr' function. */
-#undef HAVE_RAWMEMCHR
-
-/* Define to 1 if you have the `setbuf' function. */
-#undef HAVE_SETBUF
-
-/* Define to 1 if you have the `setbuffer' function. */
-#undef HAVE_SETBUFFER
-
-/* Define to 1 if you have the `sethostname' function. */
-#undef HAVE_SETHOSTNAME
-
-/* Define to 1 if you have the `setlinebuf' function. */
-#undef HAVE_SETLINEBUF
-
-/* Define to 1 if you have the `setmntent' function. */
-#undef HAVE_SETMNTENT
-
-/* Define to 1 if you have the `setvbuf' function. */
-#undef HAVE_SETVBUF
-
-/* Define to 1 if you have the `signal' function. */
-#undef HAVE_SIGNAL
-
-/* Define to 1 if you have the <signal.h> header file. */
-#undef HAVE_SIGNAL_H
-
-/* Define it socklen_t typedef is in sys/socket.h. */
-#undef HAVE_SOCKLEN_T
-
-/* Define to 1 if you have the `stat64' function. */
-#undef HAVE_STAT64
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#undef HAVE_STDINT_H
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#undef HAVE_STDLIB_H
-
-/* Define to 1 if you have the `stpcpy' function. */
-#undef HAVE_STPCPY
-
-/* Define to 1 if you have the <strings.h> header file. */
-#undef HAVE_STRINGS_H
-
-/* Define to 1 if you have the <string.h> header file. */
-#undef HAVE_STRING_H
-
-/* Define to 1 if you have the `strncpy' function. */
-#undef HAVE_STRNCPY
-
-/* Define to 1 if you have the `strnlen' function. */
-#undef HAVE_STRNLEN
-
-/* Define to 1 if you have the <sys/ipc.h> header file. */
-#undef HAVE_SYS_IPC_H
-
-/* Define to 1 if you have the <sys/mman.h> header file. */
-#undef HAVE_SYS_MMAN_H
-
-/* Define to 1 if you have the <sys/mnttab.h> header file. */
-#undef HAVE_SYS_MNTTAB_H
-
-/* Define to 1 if you have the <sys/sem.h> header file. */
-#undef HAVE_SYS_SEM_H
-
-/* Define to 1 if you have the <sys/shm.h> header file. */
-#undef HAVE_SYS_SHM_H
-
-/* Define to 1 if you have the <sys/socket.h> header file. */
-#undef HAVE_SYS_SOCKET_H
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#undef HAVE_SYS_STAT_H
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#undef HAVE_SYS_TYPES_H
-
-/* Define to 1 if you have the <sys/wait.h> header file. */
-#undef HAVE_SYS_WAIT_H
-
-/* Define to 1 if the target supports thread-local storage. */
-#undef HAVE_TLS
-
-/* union semun defined in sys/ipc.h or sys/sem.h */
-#undef HAVE_UNION_SEMUN
-
-/* Define to 1 if you have the <unistd.h> header file. */
-#undef HAVE_UNISTD_H
-
-/* Define to 1 if you have the `__ctype_b_loc' function. */
-#undef HAVE___CTYPE_B_LOC
-
-/* Define to 1 if you have the `__ctype_tolower_loc' function. */
-#undef HAVE___CTYPE_TOLOWER_LOC
-
-/* Define to 1 if you have the `__ctype_toupper_loc' function. */
-#undef HAVE___CTYPE_TOUPPER_LOC
-
-/* Define to 1 if you have the `__libc_freeres' function. */
-#undef HAVE___LIBC_FREERES
-
-/* Define to the sub-directory in which libtool stores uninstalled libraries.
- */
-#undef LT_OBJDIR
-
-/* Name of package */
-#undef PACKAGE
-
-/* Define to the address where bug reports for this package should be sent. */
-#undef PACKAGE_BUGREPORT
-
-/* Define to the full name of this package. */
-#undef PACKAGE_NAME
-
-/* Define to the full name and version of this package. */
-#undef PACKAGE_STRING
-
-/* Define to the one symbol short name of this package. */
-#undef PACKAGE_TARNAME
-
-/* Define to the home page for this package. */
-#undef PACKAGE_URL
-
-/* Define to the version of this package. */
-#undef PACKAGE_VERSION
-
-/* pthread_create symbol version */
-#undef PTHREAD_CREATE_VERSION
-
-/* Define to 1 if you have the ANSI C header files. */
-#undef STDC_HEADERS
-
-/* Define to 1 if the target use emutls for thread-local storage. */
-#undef USE_EMUTLS
-
-/* Version number of package */
-#undef VERSION
diff --git a/libmudflap/configure b/libmudflap/configure
deleted file mode 100755
index 076ad63095e..00000000000
--- a/libmudflap/configure
+++ /dev/null
@@ -1,14047 +0,0 @@
-#! /bin/sh
-# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.64 for libmudflap 1.0.
-#
-# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
-# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 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.
-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
-
-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"
- 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 :
- # 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.
- BASH_ENV=/dev/null
- ENV=/dev/null
- (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
- export CONFIG_SHELL
- exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"}
-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_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 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=$?; test $as_status -eq 0 && as_status=1
- if test "$3"; then
- as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3
- fi
- $as_echo "$as_me: error: $1" >&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; }
-
- # 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 -p'.
- ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
- as_ln_s='cp -p'
- elif ln conf$$.file conf$$ 2>/dev/null; then
- as_ln_s=ln
- else
- as_ln_s='cp -p'
- fi
-else
- as_ln_s='cp -p'
-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
-
-if test -x / >/dev/null 2>&1; then
- as_test_x='test -x'
-else
- if ls -dL / >/dev/null 2>&1; then
- as_ls_L_option=L
- else
- as_ls_L_option=
- fi
- as_test_x='
- eval sh -c '\''
- if test -d "$1"; then
- test -d "$1/.";
- else
- case $1 in #(
- -*)set "./$1";;
- esac;
- case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
- ???[sx]*):;;*)false;;esac;fi
- '\'' sh
- '
-fi
-as_executable_p=$as_test_x
-
-# 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}
-
-
-exec 7<&0 </dev/null 6>&1
-
-# Name of the host.
-# hostname on some systems (SVR3.2, 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='libmudflap'
-PACKAGE_TARNAME='libmudflap'
-PACKAGE_VERSION='1.0'
-PACKAGE_STRING='libmudflap 1.0'
-PACKAGE_BUGREPORT=''
-PACKAGE_URL=''
-
-ac_unique_file="mf-runtime.c"
-# 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='am__EXEEXT_FALSE
-am__EXEEXT_TRUE
-LTLIBOBJS
-LIBOBJS
-SECTION_FLAGS
-toolexeclibdir
-toolexecdir
-build_libmudflapth
-LIBMUDFLAPTH_FALSE
-LIBMUDFLAPTH_TRUE
-MF_HAVE_UINTPTR_T
-MF_HAVE_STDINT_H
-enable_static
-enable_shared
-OTOOL64
-OTOOL
-LIPO
-NMEDIT
-DSYMUTIL
-RANLIB
-AR
-OBJDUMP
-LN_S
-NM
-ac_ct_DUMPBIN
-DUMPBIN
-LD
-FGREP
-SED
-LIBTOOL
-EGREP
-GREP
-CPP
-am__fastdepCC_FALSE
-am__fastdepCC_TRUE
-CCDEPMODE
-am__nodep
-AMDEPBACKSLASH
-AMDEP_FALSE
-AMDEP_TRUE
-am__quote
-am__include
-DEPDIR
-OBJEXT
-EXEEXT
-ac_ct_CC
-CPPFLAGS
-LDFLAGS
-CFLAGS
-CC
-multi_basedir
-MAINT
-MAINTAINER_MODE_FALSE
-MAINTAINER_MODE_TRUE
-am__untar
-am__tar
-AMTAR
-am__leading_dot
-SET_MAKE
-AWK
-mkdir_p
-MKDIR_P
-INSTALL_STRIP_PROGRAM
-STRIP
-install_sh
-MAKEINFO
-AUTOHEADER
-AUTOMAKE
-AUTOCONF
-ACLOCAL
-VERSION
-PACKAGE
-CYGPATH_W
-am__isrc
-INSTALL_DATA
-INSTALL_SCRIPT
-INSTALL_PROGRAM
-target_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=''
-ac_user_opts='
-enable_option_checking
-enable_version_specific_runtime_libs
-enable_maintainer_mode
-enable_multilib
-enable_dependency_tracking
-enable_shared
-enable_static
-with_pic
-enable_fast_install
-with_gnu_ld
-enable_libtool_lock
-enable_tls
-'
- ac_precious_vars='build_alias
-host_alias
-target_alias
-CPP
-CPPFLAGS'
-
-
-# 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_TARNAME}'
-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=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
- $as_echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
- If a cross compiler is detected then cross compile mode will be used." >&2
- 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 libmudflap 1.0 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/libmudflap]
- --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
- case $ac_init_help in
- short | recursive ) echo "Configuration of libmudflap 1.0:";;
- esac
- 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-version-specific-runtime-libs Specify that runtime libraries should be installed in a compiler-specific directory
- --enable-maintainer-mode enable make rules and dependencies not useful
- (and sometimes confusing) to the casual installer
- --enable-multilib build many library versions (default)
- --disable-dependency-tracking speeds up one-time build
- --enable-dependency-tracking do not reject slow dependency extractors
- --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-tls Use thread-local storage [default=yes]
-
-Optional Packages:
- --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
- --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
- --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]
-
-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 C/C++/Objective C preprocessor flags, e.g. -I<include dir> if
- you have headers in a nonstandard directory <include dir>
- CPP C preprocessor
-
-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
-libmudflap configure 1.0
-generated by GNU Autoconf 2.64
-
-Copyright (C) 2009 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; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
- return $ac_retval
-
-} # ac_fn_c_try_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; } >/dev/null && {
- 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; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
- return $ac_retval
-
-} # ac_fn_c_try_cpp
-
-# ac_fn_c_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_c_check_header_mongrel ()
-{
- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; 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_c_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_c_try_cpp "$LINENO"; then :
- ac_header_preproc=yes
-else
- ac_header_preproc=no
-fi
-rm -f conftest.err 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_c_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 { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; 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; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
-
-} # ac_fn_c_check_header_mongrel
-
-# ac_fn_c_try_run LINENO
-# ----------------------
-# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
-# that executables *can* be run.
-ac_fn_c_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; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
- return $ac_retval
-
-} # ac_fn_c_try_run
-
-# ac_fn_c_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_c_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 { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-$4
-#include <$2>
-_ACEOF
-if ac_fn_c_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; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
-
-} # ac_fn_c_check_header_compile
-
-# 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 ||
- $as_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; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
- return $ac_retval
-
-} # ac_fn_c_try_link
-
-# 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 { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; 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; test "x$as_lineno_stack" = x && { as_lineno=; 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 libmudflap $as_me 1.0, which was
-generated by GNU Autoconf 2.64. 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
-
- cat <<\_ASBOX
-## ---------------- ##
-## Cache variables. ##
-## ---------------- ##
-_ASBOX
- 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
-
- cat <<\_ASBOX
-## ----------------- ##
-## Output variables. ##
-## ----------------- ##
-_ASBOX
- 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
- cat <<\_ASBOX
-## ------------------- ##
-## File substitutions. ##
-## ------------------- ##
-_ASBOX
- 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
- cat <<\_ASBOX
-## ----------- ##
-## confdefs.h. ##
-## ----------- ##
-_ASBOX
- 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
- ac_site_file1=$CONFIG_SITE
-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 -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"
- 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.
- if 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_aux_dir=
-for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
- for ac_t in install-sh install.sh shtool; do
- if test -f "$ac_dir/$ac_t"; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/$ac_t -c"
- break 2
- fi
- done
-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 test "${ac_cv_build+set}" = set; 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 test "${ac_cv_host+set}" = set; 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 test "${ac_cv_target+set}" = set; 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}-
-
- 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
-
- case ${target_alias} in
- "") target_noncanonical=${host_noncanonical} ;;
- *) target_noncanonical=${target_alias} ;;
-esac
-
-
-
-
-am__api_version='1.11'
-
-# 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
-# AmigaOS /C/install, which installs bootblocks on floppy discs
-# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
-# AFS /usr/afsws/bin/install, which mishandles nonexistent args
-# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
-# OS/2's system install, which has a completely different semantic
-# ./install, which can be erroneously created by make from ./install.sh.
-# Reject install programs that cannot install multiple files.
-{ $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 test "${ac_cv_path_install+set}" = set; then :
- $as_echo_n "(cached) " >&6
-else
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- # Account for people who put trailing slashes in PATH elements.
-case $as_dir/ in #((
- ./ | .// | /[cC]/* | \
- /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
- ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
- /usr/ucb/* ) ;;
- *)
- # OSF1 and SCO ODT 3.0 have their own names for install.
- # Don't use installbsd from OSF since it installs stuff as root
- # by default.
- for ac_prog in ginstall scoinst install; do
- for ac_exec_ext in '' $ac_executable_extensions; do
- if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
- if test $ac_prog = install &&
- grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
- # AIX install. It has an incompatible calling convention.
- :
- elif test $ac_prog = install &&
- grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
- # program-specific install script used by HP pwplus--don't use.
- :
- else
- rm -rf conftest.one conftest.two conftest.dir
- echo one > conftest.one
- echo two > conftest.two
- mkdir conftest.dir
- if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" &&
- test -s conftest.one && test -s conftest.two &&
- test -s conftest.dir/conftest.one &&
- test -s conftest.dir/conftest.two
- then
- ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
- break 3
- fi
- fi
- fi
- done
- done
- ;;
-esac
-
- done
-IFS=$as_save_IFS
-
-rm -rf conftest.one conftest.two conftest.dir
-
-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. Don't cache a
- # value for INSTALL within a source directory, because that will
- # break other packages using the cache if that directory is
- # removed, or if the value is a relative name.
- 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_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
-
-test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5
-$as_echo_n "checking whether build environment is sane... " >&6; }
-# Just in case
-sleep 1
-echo timestamp > conftest.file
-# Reject unsafe characters in $srcdir or the absolute working directory
-# name. Accept space and tab only in the latter.
-am_lf='
-'
-case `pwd` in
- *[\\\"\#\$\&\'\`$am_lf]*)
- as_fn_error "unsafe absolute working directory name" "$LINENO" 5;;
-esac
-case $srcdir in
- *[\\\"\#\$\&\'\`$am_lf\ \ ]*)
- as_fn_error "unsafe srcdir value: \`$srcdir'" "$LINENO" 5;;
-esac
-
-# Do `set' in a subshell so we don't clobber the current shell's
-# arguments. Must try -L first in case configure is actually a
-# symlink; some systems play weird games with the mod time of symlinks
-# (eg FreeBSD returns the mod time of the symlink's containing
-# directory).
-if (
- set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
- if test "$*" = "X"; then
- # -L didn't work.
- set X `ls -t "$srcdir/configure" conftest.file`
- fi
- rm -f conftest.file
- if test "$*" != "X $srcdir/configure conftest.file" \
- && test "$*" != "X conftest.file $srcdir/configure"; then
-
- # If neither matched, then we have a broken ls. This can happen
- # if, for instance, CONFIG_SHELL is bash and it inherits a
- # broken ls alias from the environment. This has actually
- # happened. Such a system could not be considered "sane".
- as_fn_error "ls -t appears to fail. Make sure there is not a broken
-alias in your environment" "$LINENO" 5
- fi
-
- test "$2" = conftest.file
- )
-then
- # Ok.
- :
-else
- as_fn_error "newly created file is older than distributed files!
-Check your system clock" "$LINENO" 5
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-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"`
-
-# expand $ac_aux_dir to an absolute path
-am_aux_dir=`cd $ac_aux_dir && pwd`
-
-if test x"${MISSING+set}" != xset; then
- case $am_aux_dir in
- *\ * | *\ *)
- MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
- *)
- MISSING="\${SHELL} $am_aux_dir/missing" ;;
- esac
-fi
-# Use eval to expand $SHELL
-if eval "$MISSING --run true"; then
- am_missing_run="$MISSING --run "
-else
- am_missing_run=
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`missing' script is too old or missing" >&5
-$as_echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;}
-fi
-
-if test x"${install_sh}" != xset; then
- case $am_aux_dir in
- *\ * | *\ *)
- install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
- *)
- install_sh="\${SHELL} $am_aux_dir/install-sh"
- esac
-fi
-
-# Installed binaries are usually stripped using `strip' when the user
-# run `make install-strip'. However `strip' might not be the right
-# tool to use in cross-compilation environments, therefore Automake
-# will honor the `STRIP' environment variable to overrule this program.
-if test "$cross_compiling" != no; then
- 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 test "${ac_cv_prog_STRIP+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_ac_ct_STRIP+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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
-
-fi
-INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5
-$as_echo_n "checking for a thread-safe mkdir -p... " >&6; }
-if test -z "$MKDIR_P"; then
- if test "${ac_cv_path_mkdir+set}" = set; then :
- $as_echo_n "(cached) " >&6
-else
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_prog in mkdir gmkdir; do
- for ac_exec_ext in '' $ac_executable_extensions; do
- { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; } || continue
- case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #(
- 'mkdir (GNU coreutils) '* | \
- 'mkdir (coreutils) '* | \
- 'mkdir (fileutils) '4.1*)
- ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext
- break 3;;
- esac
- done
- done
- done
-IFS=$as_save_IFS
-
-fi
-
- if test "${ac_cv_path_mkdir+set}" = set; then
- MKDIR_P="$ac_cv_path_mkdir -p"
- else
- # As a last resort, use the slow shell script. Don't cache a
- # value for MKDIR_P within a source directory, because that will
- # break other packages using the cache if that directory is
- # removed, or if the value is a relative name.
- test -d ./--version && rmdir ./--version
- MKDIR_P="$ac_install_sh -d"
- fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5
-$as_echo "$MKDIR_P" >&6; }
-
-mkdir_p="$MKDIR_P"
-case $mkdir_p in
- [\\/$]* | ?:[\\/]*) ;;
- */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;;
-esac
-
-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 test "${ac_cv_prog_AWK+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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
-
-{ $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 { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; 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
-
-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
-
-if test "`cd $srcdir && pwd`" != "`pwd`"; then
- # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
- # is not polluted with repeated "-I."
- am__isrc=' -I$(srcdir)'
- # test to see if srcdir already configured
- if test -f $srcdir/config.status; then
- as_fn_error "source directory already configured; run \"make distclean\" there first" "$LINENO" 5
- fi
-fi
-
-# test whether we have cygpath
-if test -z "$CYGPATH_W"; then
- if (cygpath --version) >/dev/null 2>/dev/null; then
- CYGPATH_W='cygpath -w'
- else
- CYGPATH_W=echo
- fi
-fi
-
-
-# Define the identity of the package.
- PACKAGE='libmudflap'
- VERSION='1.0'
-
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE "$PACKAGE"
-_ACEOF
-
-
-cat >>confdefs.h <<_ACEOF
-#define VERSION "$VERSION"
-_ACEOF
-
-# Some tools Automake needs.
-
-ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"}
-
-
-AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"}
-
-
-AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"}
-
-
-AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"}
-
-
-MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
-
-# We need awk for the "check" target. The system "awk" is bad on
-# some platforms.
-# Always define AMTAR for backward compatibility. Yes, it's still used
-# in the wild :-( We should find a proper way to deprecate it ...
-AMTAR='$${TAR-tar}'
-
-am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'
-
-
-
-
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for --enable-version-specific-runtime-libs" >&5
-$as_echo_n "checking for --enable-version-specific-runtime-libs... " >&6; }
-# 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; case "$enableval" in
- yes) version_specific_libs=yes ;;
- no) version_specific_libs=no ;;
- *) as_fn_error "Unknown argument to enable/disable version-specific libs" "$LINENO" 5;;
- esac
-else
- version_specific_libs=no
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $version_specific_libs" >&5
-$as_echo "$version_specific_libs" >&6; }
-
-
-{ $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; USE_MAINTAINER_MODE=$enableval
-else
- USE_MAINTAINER_MODE=no
-fi
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5
-$as_echo "$USE_MAINTAINER_MODE" >&6; }
- if test $USE_MAINTAINER_MODE = yes; then
- MAINTAINER_MODE_TRUE=
- MAINTAINER_MODE_FALSE='#'
-else
- MAINTAINER_MODE_TRUE='#'
- MAINTAINER_MODE_FALSE=
-fi
-
- MAINT=$MAINTAINER_MODE_TRUE
-
-
-
-
-# Default to --enable-multilib
-# Check whether --enable-multilib was given.
-if test "${enable_multilib+set}" = set; then :
- enableval=$enable_multilib; case "$enableval" in
- yes) multilib=yes ;;
- no) multilib=no ;;
- *) as_fn_error "bad value $enableval for multilib option" "$LINENO" 5 ;;
- esac
-else
- multilib=yes
-fi
-
-
-# We may get other options which we leave undocumented:
-# --with-target-subdir, --with-multisrctop, --with-multisubdir
-# See config-ml.in if you want the gory details.
-
-if test "$srcdir" = "."; then
- if test "$with_target_subdir" != "."; then
- multi_basedir="$srcdir/$with_multisrctop../.."
- else
- multi_basedir="$srcdir/$with_multisrctop.."
- fi
-else
- multi_basedir="$srcdir/.."
-fi
-
-
-# Even if the default multilib is not a cross compilation,
-# it may be that some of the other multilibs are.
-if test $cross_compiling = no && test $multilib = yes \
- && test "x${with_multisubdir}" != x ; then
- cross_compiling=maybe
-fi
-
-ac_config_commands="$ac_config_commands default-1"
-
-
-target_alias=${target_alias-$host_alias}
-
-
-ac_config_headers="$ac_config_headers config.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
-
-# The same as in boehm-gc and libstdc++. Have to borrow it from there.
-# We must force CC to /not/ be precious variables; otherwise
-# the wrong, non-multilib-adjusted value will be used in multilibs.
-# As a side effect, we have to subst CFLAGS ourselves.
-
-
-
-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 test "${ac_cv_prog_CC+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_ac_ct_CC+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_CC+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_CC+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_CC+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_ac_ct_CC+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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
- rm -f conftest.er1 conftest.err
- fi
- $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 conftest.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 for C compiler default output file name" >&5
-$as_echo_n "checking for C compiler default output file name... " >&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
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
-$as_echo "$ac_file" >&6; }
-if test -z "$ac_file"; then :
- $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_set_status 77
-as_fn_error "C compiler cannot create executables
-See \`config.log' for more details." "$LINENO" 5; }; }
-fi
-ac_exeext=$ac_cv_exeext
-
-# 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 the C compiler works" >&5
-$as_echo_n "checking whether the C compiler works... " >&6; }
-# If not cross compiling, check that we can run a simple program.
-if test "$cross_compiling" != yes; then
- if { ac_try='./$ac_file'
- { { 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: yes" >&5
-$as_echo "yes" >&6; }
-
-rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out conftest.out
-ac_clean_files=$ac_clean_files_save
-# 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; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
-$as_echo "$cross_compiling" >&6; }
-
-{ $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$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
-{ $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 test "${ac_cv_objext+set}" = set; 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 test "${ac_cv_c_compiler_gnu+set}" = set; 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 test "${ac_cv_prog_cc_g+set}" = set; 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 test "${ac_cv_prog_cc_c89+set}" = set; 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>
-#include <sys/types.h>
-#include <sys/stat.h>
-/* 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
-DEPDIR="${am__leading_dot}deps"
-
-ac_config_commands="$ac_config_commands depfiles"
-
-
-am_make=${MAKE-make}
-cat > confinc << 'END'
-am__doit:
- @echo this is the am__doit target
-.PHONY: am__doit
-END
-# If we don't find an include directive, just comment out the code.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5
-$as_echo_n "checking for style of include used by $am_make... " >&6; }
-am__include="#"
-am__quote=
-_am_result=none
-# First try GNU make style include.
-echo "include confinc" > confmf
-# Ignore all kinds of additional output from `make'.
-case `$am_make -s -f confmf 2> /dev/null` in #(
-*the\ am__doit\ target*)
- am__include=include
- am__quote=
- _am_result=GNU
- ;;
-esac
-# Now try BSD make style include.
-if test "$am__include" = "#"; then
- echo '.include "confinc"' > confmf
- case `$am_make -s -f confmf 2> /dev/null` in #(
- *the\ am__doit\ target*)
- am__include=.include
- am__quote="\""
- _am_result=BSD
- ;;
- esac
-fi
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5
-$as_echo "$_am_result" >&6; }
-rm -f confinc confmf
-
-# Check whether --enable-dependency-tracking was given.
-if test "${enable_dependency_tracking+set}" = set; then :
- enableval=$enable_dependency_tracking;
-fi
-
-if test "x$enable_dependency_tracking" != xno; then
- am_depcomp="$ac_aux_dir/depcomp"
- AMDEPBACKSLASH='\'
- am__nodep='_no'
-fi
- if test "x$enable_dependency_tracking" != xno; then
- AMDEP_TRUE=
- AMDEP_FALSE='#'
-else
- AMDEP_TRUE='#'
- AMDEP_FALSE=
-fi
-
-
-
-depcc="$CC" am_compiler_list=
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
-$as_echo_n "checking dependency style of $depcc... " >&6; }
-if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then :
- $as_echo_n "(cached) " >&6
-else
- if test -z "$AMDEP_TRUE" && 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'.
- rm -rf conftest.dir
- 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_CC_dependencies_compiler_type=none
- if test "$am_compiler_list" = ""; then
- am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
- fi
- am__universal=false
- case " $depcc " in #(
- *\ -arch\ *\ -arch\ *) am__universal=true ;;
- esac
-
- for depmode in $am_compiler_list; do
- # 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 "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > 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. Also, some Intel
- # versions had trouble with output in subdirs
- am__obj=sub/conftest.${OBJEXT-o}
- am__minus_obj="-o $am__obj"
- case $depmode in
- gcc)
- # This depmode causes a compiler race in universal mode.
- test "$am__universal" = false || continue
- ;;
- nosideeffect)
- # after this tag, mechanisms are not by side-effect, so they'll
- # only be used when explicitly requested
- if test "x$enable_dependency_tracking" = xyes; then
- continue
- else
- break
- fi
- ;;
- msvc7 | msvc7msys | msvisualcpp | msvcmsys)
- # This compiler won't grok `-c -o', but also, the minuso test has
- # not run yet. These depmodes are late enough in the game, and
- # so weak that their functioning should not be impacted.
- am__obj=conftest.${OBJEXT-o}
- am__minus_obj=
- ;;
- none) break ;;
- esac
- if depmode=$depmode \
- source=sub/conftest.c object=$am__obj \
- depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
- $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
- >/dev/null 2>conftest.err &&
- grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
- grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
- grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
- ${MAKE-make} -s -f confmf > /dev/null 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_CC_dependencies_compiler_type=$depmode
- break
- fi
- fi
- done
-
- cd ..
- rm -rf conftest.dir
-else
- am_cv_CC_dependencies_compiler_type=none
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5
-$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; }
-CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
-
- if
- test "x$enable_dependency_tracking" != xno \
- && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then
- am__fastdepCC_TRUE=
- am__fastdepCC_FALSE='#'
-else
- am__fastdepCC_TRUE='#'
- am__fastdepCC_FALSE=
-fi
-
-
-
-
-
-
-if test "x$GCC" != "xyes"; then
- as_fn_error "libmudflap must be built with GCC" "$LINENO" 5
-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
-{ $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 test "${ac_cv_prog_CPP+set}" = set; 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.$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.$ac_ext
-
-done
-# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f 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.$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.$ac_ext
-
-done
-# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f 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=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
-
-
-# Some hosts don't have dlsym(RTLD_NEXT, "symbol") for use in
-# symbol interposition. We disable shared libraries for these.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether dlsym(RTLD_NEXT,...) is available" >&5
-$as_echo_n "checking whether dlsym(RTLD_NEXT,...) is available... " >&6; }
-
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-#define _GNU_SOURCE
-#include <dlfcn.h>
-
-int
-main ()
-{
-void *foo = dlsym (RTLD_NEXT, "exit");
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; 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" >&5
-$as_echo "no" >&6; }
-enable_shared=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-
-{ $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 test "${ac_cv_path_GREP+set}" = set; 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"
- { test -f "$ac_path_GREP" && $as_test_x "$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 test "${ac_cv_path_EGREP+set}" = set; 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"
- { test -f "$ac_path_EGREP" && $as_test_x "$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 test "${ac_cv_header_stdc+set}" = set; 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_c_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_c_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_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
-"
-eval as_val=\$$as_ac_Header
- if test "x$as_val" = x""yes; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-
-done
-
-
-for ac_header in stdint.h execinfo.h signal.h dlfcn.h dirent.h pwd.h grp.h \
- netdb.h sys/ipc.h sys/sem.h sys/shm.h sys/wait.h ctype.h mntent.h \
- sys/mnttab.h sys/socket.h netinet/in.h arpa/inet.h dlfcn.h sys/mman.h
-do :
- as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
-ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
-eval as_val=\$$as_ac_Header
- if test "x$as_val" = x""yes; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-
-done
-
-
-for ac_func in backtrace backtrace_symbols gettimeofday signal
-do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-eval as_val=\$$as_ac_var
- if test "x$as_val" = x""yes; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
-for ac_func in fopen64 fseeko64 ftello64 stat64 freopen64
-do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-eval as_val=\$$as_ac_var
- if test "x$as_val" = x""yes; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
-for ac_func in setbuf setbuffer setlinebuf setvbuf
-do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-eval as_val=\$$as_ac_var
- if test "x$as_val" = x""yes; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
-for ac_func in strnlen memrchr strncpy memmem sethostname
-do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-eval as_val=\$$as_ac_var
- if test "x$as_val" = x""yes; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
-for ac_func in __ctype_b_loc __ctype_tolower_loc __ctype_toupper_loc
-do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-eval as_val=\$$as_ac_var
- if test "x$as_val" = x""yes; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
-for ac_func in getlogin cuserid getpwnam getpwuid getpwent getgrnam getgrgid getgrent
-do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-eval as_val=\$$as_ac_var
- if test "x$as_val" = x""yes; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
-for ac_func in getlogin_r getpwnam_r getpwuid_r getgrnam_r getgrgid_r
-do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-eval as_val=\$$as_ac_var
- if test "x$as_val" = x""yes; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
-for ac_func in getservent getservbyname getservbyport getaddrinfo gai_strerror
-do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-eval as_val=\$$as_ac_var
- if test "x$as_val" = x""yes; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
-for ac_func in getprotoent getprotobyname getprotobynumber
-do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-eval as_val=\$$as_ac_var
- if test "x$as_val" = x""yes; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
-for ac_func in getmntent setmntent addmntent
-do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-eval as_val=\$$as_ac_var
- if test "x$as_val" = x""yes; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
-for ac_func in inet_ntoa mmap munmap
-do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-eval as_val=\$$as_ac_var
- if test "x$as_val" = x""yes; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
-for ac_func in mmap64
-do :
- ac_fn_c_check_func "$LINENO" "mmap64" "ac_cv_func_mmap64"
-if test "x$ac_cv_func_mmap64" = x""yes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_MMAP64 1
-_ACEOF
-
-fi
-done
-
-for ac_func in __libc_freeres
-do :
- ac_fn_c_check_func "$LINENO" "__libc_freeres" "ac_cv_func___libc_freeres"
-if test "x$ac_cv_func___libc_freeres" = x""yes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE___LIBC_FREERES 1
-_ACEOF
-
-fi
-done
-
-for ac_func in rawmemchr stpcpy mempcpy
-do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-eval as_val=\$$as_ac_var
- if test "x$as_val" = x""yes; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
-
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <sys/types.h>
-#include <sys/ipc.h>
-#include <sys/sem.h>
-int
-main ()
-{
-union semun foo;
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- mf_have_semun=1
-else
- mf_have_semun=0
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-if test $mf_have_semun = 1
-then
-
-$as_echo "#define HAVE_UNION_SEMUN 1" >>confdefs.h
-
-fi
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for socklen_t in sys/socket.h" >&5
-$as_echo_n "checking for socklen_t in sys/socket.h... " >&6; }
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#define _POSIX_PII_SOCKET
-#include <sys/types.h>
-#include <sys/socket.h>
-int
-main ()
-{
-socklen_t x = 5;
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-
-$as_echo "#define HAVE_SOCKLEN_T 1" >>confdefs.h
-
- { $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
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-enable_dlopen=yes
-
-
-
-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 test "${ac_cv_path_SED+set}" = set; 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"
- { test -f "$ac_path_SED" && $as_test_x "$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 test "${ac_cv_path_FGREP+set}" = set; 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"
- { test -f "$ac_path_FGREP" && $as_test_x "$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 test "${lt_cv_path_LD+set}" = set; 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 test "${lt_cv_prog_gnu_ld+set}" = set; 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 test "${lt_cv_path_NM+set}" = set; 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 test "${ac_cv_prog_DUMPBIN+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_ac_ct_DUMPBIN+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${lt_cv_nm_interface+set}" = set; 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 test "${lt_cv_sys_max_cmd_len+set}" = set; 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 test "${lt_cv_ld_reload_flag+set}" = set; 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 test "${ac_cv_prog_OBJDUMP+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_ac_ct_OBJDUMP+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${lt_cv_deplibs_check_method+set}" = set; 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)
- 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 test "${ac_cv_prog_AR+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_ac_ct_AR+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_STRIP+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_ac_ct_STRIP+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_RANLIB+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${lt_cv_sys_global_symbol_pipe+set}" = set; 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*|ppc*-*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
- ;;
- ppc64-*linux*|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"
- ;;
- ppc*-*linux*|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 test "${lt_cv_cc_needs_belf+set}" = set; 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 test "${ac_cv_prog_DSYMUTIL+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_ac_ct_DSYMUTIL+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_NMEDIT+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_ac_ct_NMEDIT+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_LIPO+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_ac_ct_LIPO+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_OTOOL+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_ac_ct_OTOOL+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_OTOOL64+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_ac_ct_OTOOL64+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${lt_cv_apple_cc_single_mod+set}" = set; 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 test "${lt_cv_ld_exported_symbols_list+set}" = set; 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 test "${lt_cv_ld_force_load+set}" = set; 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; }
- case $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 on
- # if running on 10.5 or later, the deployment target defaults
- # to the OS version, if on x86, and 10.4, the deployment
- # target defaults to 10.4. Don't you love it?
- case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
- 10.0,*86*-darwin8*|10.0,*-darwin[91]*)
- _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
- 10.[012]*)
- _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
- 10.*)
- _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
- 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_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default
-"
-if test "x$ac_cv_header_dlfcn_h" = x""yes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_DLFCN_H 1
-_ACEOF
-
-fi
-
-done
-
-
-
-
-
-# Set options
-
-
-
-
- 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 test "${lt_cv_objdir+set}" = set; 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 test "${lt_cv_path_MAGIC_CMD+set}" = set; 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 test "${lt_cv_path_MAGIC_CMD+set}" = set; 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 test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; 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 test "${lt_cv_prog_compiler_pic_works+set}" = set; 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 test "${lt_cv_prog_compiler_static_works+set}" = set; 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 test "${lt_cv_prog_compiler_c_o+set}" = set; 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 test "${lt_cv_prog_compiler_c_o+set}" = set; 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)
- 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=
- 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")) && (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 -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 -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 test "${lt_cv_prog_compiler__b+set}" = set; 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 test "${lt_cv_archive_cmds_need_lc+set}" = set; 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
- ;;
-
-gnu*)
- 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
- hardcode_into_libs=yes
- ;;
-
-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.
-linux* | k*bsd*-gnu | kopensolaris*-gnu)
- 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 test "${lt_cv_shlibpath_overrides_runpath+set}" = set; 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 test "${ac_cv_lib_dl_dlopen+set}" = set; 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" = x""yes; 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" = x""yes; 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 test "${ac_cv_lib_dld_shl_load+set}" = set; 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" = x""yes; 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" = x""yes; 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 test "${ac_cv_lib_dl_dlopen+set}" = set; 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" = x""yes; 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 test "${ac_cv_lib_svld_dlopen+set}" = set; 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" = x""yes; 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 test "${ac_cv_lib_dld_dld_link+set}" = set; 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" = x""yes; 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 test "${lt_cv_dlopen_self+set}" = set; 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 10621 "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 test "${lt_cv_dlopen_self_static+set}" = set; 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 10727 "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=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
-
-CC="$lt_save_CC"
-
-
-
-
-
-
-
-
-
-
-
-
-
- ac_config_commands="$ac_config_commands libtool"
-
-
-
-
-# Only expand once:
-
-
-
-
-
-ac_fn_c_check_header_mongrel "$LINENO" "stdint.h" "ac_cv_header_stdint_h" "$ac_includes_default"
-if test "x$ac_cv_header_stdint_h" = x""yes; then :
- MF_HAVE_STDINT_H=1
-else
- MF_HAVE_STDINT_H=0
-fi
-
-
-
-if test $MF_HAVE_STDINT_H = 1
-then
- MF_HAVE_UINTPTR_T=1
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <sys/types.h>
-int
-main ()
-{
-uintptr_t k = 0;
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- MF_HAVE_UINTPTR_T=1
-else
- MF_HAVE_UINTPTR_T=0
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-
-
-for ac_header in pthread.h
-do :
- ac_fn_c_check_header_mongrel "$LINENO" "pthread.h" "ac_cv_header_pthread_h" "$ac_includes_default"
-if test "x$ac_cv_header_pthread_h" = x""yes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_PTHREAD_H 1
-_ACEOF
-
-fi
-
-done
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for thread model used by GCC" >&5
-$as_echo_n "checking for thread model used by GCC... " >&6; }
-target_thread_file=`$CC -v 2>&1 | sed -n 's/^Thread model: //p'`
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $target_thread_file" >&5
-$as_echo "$target_thread_file" >&6; }
-
-# We only support posix threads, or no threads at all.
-posix_threads=
-case ${target_thread_file} in
- posix)
- posix_threads=yes
- ;;
- single)
- ;;
- *)
- echo "${target_thread_file} is an unsupported thread package" 1>&2
- exit 1
- ;;
-esac
-
- if test "x$posix_threads" != "x"; then
- LIBMUDFLAPTH_TRUE=
- LIBMUDFLAPTH_FALSE='#'
-else
- LIBMUDFLAPTH_TRUE='#'
- LIBMUDFLAPTH_FALSE=
-fi
-
-if test "x$posix_threads" != "x"
-then
- build_libmudflapth=1
-else
- build_libmudflapth=0
-fi
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlsym in -ldl" >&5
-$as_echo_n "checking for dlsym in -ldl... " >&6; }
-if test "${ac_cv_lib_dl_dlsym+set}" = set; 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 dlsym ();
-int
-main ()
-{
-return dlsym ();
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_lib_dl_dlsym=yes
-else
- ac_cv_lib_dl_dlsym=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_dlsym" >&5
-$as_echo "$ac_cv_lib_dl_dlsym" >&6; }
-if test "x$ac_cv_lib_dl_dlsym" = x""yes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBDL 1
-_ACEOF
-
- LIBS="-ldl $LIBS"
-
-fi
-
-
-ac_fn_c_check_func "$LINENO" "connect" "ac_cv_func_connect"
-if test "x$ac_cv_func_connect" = x""yes; then :
-
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for connect in -lsocket" >&5
-$as_echo_n "checking for connect in -lsocket... " >&6; }
-if test "${ac_cv_lib_socket_connect+set}" = set; then :
- $as_echo_n "(cached) " >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lsocket $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 connect ();
-int
-main ()
-{
-return connect ();
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_lib_socket_connect=yes
-else
- ac_cv_lib_socket_connect=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_connect" >&5
-$as_echo "$ac_cv_lib_socket_connect" >&6; }
-if test "x$ac_cv_lib_socket_connect" = x""yes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBSOCKET 1
-_ACEOF
-
- LIBS="-lsocket $LIBS"
-
-fi
-
-fi
-
-ac_fn_c_check_func "$LINENO" "sched_yield" "ac_cv_func_sched_yield"
-if test "x$ac_cv_func_sched_yield" = x""yes; then :
-
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sched_yield in -lrt" >&5
-$as_echo_n "checking for sched_yield in -lrt... " >&6; }
-if test "${ac_cv_lib_rt_sched_yield+set}" = set; then :
- $as_echo_n "(cached) " >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lrt $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 sched_yield ();
-int
-main ()
-{
-return sched_yield ();
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_lib_rt_sched_yield=yes
-else
- ac_cv_lib_rt_sched_yield=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_rt_sched_yield" >&5
-$as_echo "$ac_cv_lib_rt_sched_yield" >&6; }
-if test "x$ac_cv_lib_rt_sched_yield" = x""yes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBRT 1
-_ACEOF
-
- LIBS="-lrt $LIBS"
-
-fi
-
-fi
-
-
-# Calculate toolexeclibdir
-# Also toolexecdir, though it's only used in toolexeclibdir
-case ${version_specific_libs} in
- yes)
- # Need the gcc compiler version to know where to install libraries
- # and header files if --enable-version-specific-runtime-libs option
- # is selected.
- toolexecdir='$(libdir)/gcc/$(target_alias)'
- toolexeclibdir='$(toolexecdir)/$(gcc_version)$(MULTISUBDIR)'
- ;;
- no)
- if test -n "$with_cross_host" &&
- test x"$with_cross_host" != x"no"; then
- # Install a library built with a cross compiler in tooldir, not libdir.
- toolexecdir='$(exec_prefix)/$(target_alias)'
- toolexeclibdir='$(toolexecdir)/lib'
- else
- toolexecdir='$(libdir)/gcc-lib/$(target_alias)'
- toolexeclibdir='$(libdir)'
- fi
- multi_os_directory=`$CC -print-multi-os-directory`
- case $multi_os_directory in
- .) ;; # Avoid trailing /.
- *) toolexeclibdir=$toolexeclibdir/$multi_os_directory ;;
- esac
- ;;
-esac
-
-
-
-includedir=${toolexecdir}/include
-
-
-pthread_create_version='""'
-if test "x$enable_shared" = "xyes" && test "x$posix_threads" != "x"; then
- # NB: don't check for -lpthread here, because then it would be
- # added to LIBS. For the thread-unaware libmudflap.la, we don't
- # want it there.
-
- # glibc-related hacks. dlsym() may pick the wrong version of
- # interposed functions like pthread_create on modern glibc.
- # We need to find the proper symbol version string, and use
- # the nonstandard dlvsym().
- for ac_func in dlvsym
-do :
- ac_fn_c_check_func "$LINENO" "dlvsym" "ac_cv_func_dlvsym"
-if test "x$ac_cv_func_dlvsym" = x""yes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_DLVSYM 1
-_ACEOF
-
-fi
-done
-
- if test -n "$ac_tool_prefix"; then
- # Extract the first word of "${ac_tool_prefix}nm", so it can be a program name with args.
-set dummy ${ac_tool_prefix}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 test "${ac_cv_prog_NM+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_prog_NM="${ac_tool_prefix}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
-
-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
-if test -z "$ac_cv_prog_NM"; then
- ac_ct_NM=$NM
- # 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 test "${ac_cv_prog_ac_ct_NM+set}" = set; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$ac_ct_NM"; then
- ac_cv_prog_ac_ct_NM="$ac_ct_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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
- ac_cv_prog_ac_ct_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
-
-fi
-fi
-ac_ct_NM=$ac_cv_prog_ac_ct_NM
-if test -n "$ac_ct_NM"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NM" >&5
-$as_echo "$ac_ct_NM" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
- if test "x$ac_ct_NM" = x; then
- NM=""
- 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
- NM=$ac_ct_NM
- fi
-else
- NM="$ac_cv_prog_NM"
-fi
-
- if test "x$ac_cv_have_dlvsym" != "x"; then
- # Try compiling a simple pthreads program. Find the shared libraries it
- # ends up with. Then use "nm" on those libraries to extract the
- # default symbol versioning suffix ("@@"), if any. But that's tricky.
- # Rather, run nm on the resulting executable. Unfortunately, autoconf
- # doesn't appear to have a macro that builds a test executable for
- # subsequent analysis ... so we do it by hand here.
- cat >> conftest.c << EOF
-#include <pthread.h>
-int main () { void *p = (void *) & pthread_create; return (int) p; }
-EOF
- oldLIBS="$LIBS"
- LIBS="$LIBS -lpthread"
- pthread_create_version="\"\""
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking pthread_create symbol version" >&5
-$as_echo_n "checking pthread_create symbol version... " >&6; }
- if eval $ac_link 2>&5 && test -s conftest${ac_exeext}; then
- version=`$NM conftest${ac_exeect} | grep 'pthread_create@@' | sed -e 's/^.*@@//'`
- if test "x$version" != "x"; then
- pthread_create_version="\"$version\""
- fi
- fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $pthread_create_version" >&5
-$as_echo "$pthread_create_version" >&6; }
- LIBS="$oldLIBS"
- fi
-fi
-
-cat >>confdefs.h <<_ACEOF
-#define PTHREAD_CREATE_VERSION $pthread_create_version
-_ACEOF
-
-
-
-# Figure out whether the compiler supports "-ffunction-sections -fdata-sections",
-# similarly to how libstdc++ does it
-ac_test_CFLAGS="${CFLAGS+set}"
-ac_save_CFLAGS="$CFLAGS"
-
-# Check for -ffunction-sections -fdata-sections
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gcc that supports -ffunction-sections -fdata-sections" >&5
-$as_echo_n "checking for gcc that supports -ffunction-sections -fdata-sections... " >&6; }
-CFLAGS='-Werror -ffunction-sections -fdata-sections'
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-int
-main ()
-{
-int foo;
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_fdsections=yes
-else
- ac_fdsections=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-if test "$ac_test_CFLAGS" = set; then
- CFLAGS="$ac_save_CFLAGS"
-else
- # this is the suspicious part
- CFLAGS=""
-fi
-if test x"$ac_fdsections" = x"yes"; then
- SECTION_FLAGS='-ffunction-sections -fdata-sections'
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_fdsections" >&5
-$as_echo "$ac_fdsections" >&6; }
-
-
-
-# Check for the name of the symbol used for the entry point.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for the name of the symbol used for the entry point" >&5
-$as_echo_n "checking for the name of the symbol used for the entry point... " >&6; }
-if test "${mudflap_cv_entry_point+set}" = set; then :
- $as_echo_n "(cached) " >&6
-else
-
-for name in _start __start unknown; do
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-extern char $name[];
-int
-main ()
-{
-$name[0] = 0;
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- break
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-done
-mudflap_cv_entry_point="$name"
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $mudflap_cv_entry_point" >&5
-$as_echo "$mudflap_cv_entry_point" >&6; }
-if test "$mudflap_cv_entry_point" = unknown; then
- as_fn_error "none of the known symbol names works" "$LINENO" 5
-fi
-
-cat >>confdefs.h <<_ACEOF
-#define ENTRY_POINT $mudflap_cv_entry_point
-_ACEOF
-
-
-
-if test ${multilib} = yes; then
- multilib_arg="--enable-multilib"
-else
- multilib_arg=
-fi
-
-# See if we support thread-local storage.
-
-
- # Check whether --enable-tls was given.
-if test "${enable_tls+set}" = set; then :
- enableval=$enable_tls;
- case "$enableval" in
- yes|no) ;;
- *) as_fn_error "Argument to enable/disable tls must be yes or no" "$LINENO" 5 ;;
- esac
-
-else
- enable_tls=yes
-fi
-
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the target supports thread-local storage" >&5
-$as_echo_n "checking whether the target supports thread-local storage... " >&6; }
-if test "${gcc_cv_have_tls+set}" = set; then :
- $as_echo_n "(cached) " >&6
-else
-
- if test "$cross_compiling" = yes; then :
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-__thread int a; int b; int main() { return a = b; }
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- chktls_save_LDFLAGS="$LDFLAGS"
- case $host in
- *-*-linux*)
- LDFLAGS="-shared -Wl,--no-undefined $LDFLAGS"
- ;;
- esac
- chktls_save_CFLAGS="$CFLAGS"
- CFLAGS="-fPIC $CFLAGS"
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-int f() { return 0; }
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-__thread int a; int b; int f() { return a = b; }
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- gcc_cv_have_tls=yes
-else
- gcc_cv_have_tls=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-else
- gcc_cv_have_tls=yes
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
- CFLAGS="$chktls_save_CFLAGS"
- LDFLAGS="$chktls_save_LDFLAGS"
-else
- gcc_cv_have_tls=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-
-
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-__thread int a; int b; int main() { return a = b; }
-_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
- chktls_save_LDFLAGS="$LDFLAGS"
- LDFLAGS="-static $LDFLAGS"
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-int main() { return 0; }
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; 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. */
-__thread int a; int b; int main() { return a = b; }
-_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
- gcc_cv_have_tls=yes
-else
- gcc_cv_have_tls=no
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
- conftest.$ac_objext conftest.beam conftest.$ac_ext
-fi
-
-else
- gcc_cv_have_tls=yes
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
- LDFLAGS="$chktls_save_LDFLAGS"
- if test $gcc_cv_have_tls = yes; then
- chktls_save_CFLAGS="$CFLAGS"
- thread_CFLAGS=failed
- for flag in '' '-pthread' '-lpthread'; do
- CFLAGS="$flag $chktls_save_CFLAGS"
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <pthread.h>
- void *g(void *d) { return NULL; }
-int
-main ()
-{
-pthread_t t; pthread_create(&t,NULL,g,NULL);
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- thread_CFLAGS="$flag"
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
- if test "X$thread_CFLAGS" != Xfailed; then
- break
- fi
- done
- CFLAGS="$chktls_save_CFLAGS"
- if test "X$thread_CFLAGS" != Xfailed; then
- CFLAGS="$thread_CFLAGS $chktls_save_CFLAGS"
- 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. */
-#include <pthread.h>
- __thread int a;
- static int *volatile a_in_other_thread;
- static void *
- thread_func (void *arg)
- {
- a_in_other_thread = &a;
- return (void *)0;
- }
-int
-main ()
-{
-pthread_t thread;
- void *thread_retval;
- int *volatile a_in_main_thread;
- a_in_main_thread = &a;
- if (pthread_create (&thread, (pthread_attr_t *)0,
- thread_func, (void *)0))
- return 0;
- if (pthread_join (thread, &thread_retval))
- return 0;
- return (a_in_other_thread == a_in_main_thread);
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
- gcc_cv_have_tls=yes
-else
- gcc_cv_have_tls=no
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
- conftest.$ac_objext conftest.beam conftest.$ac_ext
-fi
-
- CFLAGS="$chktls_save_CFLAGS"
- fi
- fi
-else
- gcc_cv_have_tls=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_have_tls" >&5
-$as_echo "$gcc_cv_have_tls" >&6; }
- if test "$enable_tls $gcc_cv_have_tls" = "yes yes"; then
-
-$as_echo "#define HAVE_TLS 1" >>confdefs.h
-
- fi
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the thread-local storage support is from emutls" >&5
-$as_echo_n "checking whether the thread-local storage support is from emutls... " >&6; }
-if test "${gcc_cv_use_emutls+set}" = set; then :
- $as_echo_n "(cached) " >&6
-else
-
- gcc_cv_use_emutls=no
- echo '__thread int a; int b; int main() { return a = b; }' > conftest.c
- if { ac_try='${CC-cc} -Werror -S -o conftest.s conftest.c 1>&5'
- { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; }; then
- if grep __emutls_get_address conftest.s > /dev/null; then
- gcc_cv_use_emutls=yes
- fi
- fi
- rm -f conftest.*
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_use_emutls" >&5
-$as_echo "$gcc_cv_use_emutls" >&6; }
- if test "$gcc_cv_use_emutls" = "yes" ; then
-
-$as_echo "#define USE_EMUTLS 1" >>confdefs.h
-
- fi
-
-ac_config_files="$ac_config_files Makefile testsuite/Makefile testsuite/mfconfig.exp"
-
-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
- test "x$cache_file" != "x/dev/null" &&
- { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
-$as_echo "$as_me: updating cache $cache_file" >&6;}
- cat confcache >$cache_file
- 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=
-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
-
-
- if test -n "$EXEEXT"; then
- am__EXEEXT_TRUE=
- am__EXEEXT_FALSE='#'
-else
- am__EXEEXT_TRUE='#'
- am__EXEEXT_FALSE=
-fi
-
-if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then
- as_fn_error "conditional \"MAINTAINER_MODE\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then
- as_fn_error "conditional \"AMDEP\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
- as_fn_error "conditional \"am__fastdepCC\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${LIBMUDFLAPTH_TRUE}" && test -z "${LIBMUDFLAPTH_FALSE}"; then
- as_fn_error "conditional \"LIBMUDFLAPTH\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-
-: ${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.
-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 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=$?; test $as_status -eq 0 && as_status=1
- if test "$3"; then
- as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3
- fi
- $as_echo "$as_me: error: $1" >&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 -p'.
- ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
- as_ln_s='cp -p'
- elif ln conf$$.file conf$$ 2>/dev/null; then
- as_ln_s=ln
- else
- as_ln_s='cp -p'
- fi
-else
- as_ln_s='cp -p'
-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
-
-if test -x / >/dev/null 2>&1; then
- as_test_x='test -x'
-else
- if ls -dL / >/dev/null 2>&1; then
- as_ls_L_option=L
- else
- as_ls_L_option=
- fi
- as_test_x='
- eval sh -c '\''
- if test -d "$1"; then
- test -d "$1/.";
- else
- case $1 in #(
- -*)set "./$1";;
- esac;
- case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
- ???[sx]*):;;*)false;;esac;fi
- '\'' sh
- '
-fi
-as_executable_p=$as_test_x
-
-# 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 libmudflap $as_me 1.0, which was
-generated by GNU Autoconf 2.64. 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_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
- -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 commands:
-$config_commands
-
-Report bugs to the package provider."
-
-_ACEOF
-cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
-ac_cs_version="\\
-libmudflap config.status 1.0
-configured by $0, generated by GNU Autoconf 2.64,
- with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
-
-Copyright (C) 2009 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'
-INSTALL='$INSTALL'
-MKDIR_P='$MKDIR_P'
-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=$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 ;;
- --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"` ;;
- 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
-#
-
-srcdir="$srcdir"
-host="$host"
-target="$target"
-with_multisubdir="$with_multisubdir"
-with_multisrctop="$with_multisrctop"
-with_target_subdir="$with_target_subdir"
-ac_configure_args="${multilib_arg} ${ac_configure_args}"
-multi_basedir="$multi_basedir"
-CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
-CC="$CC"
-CXX="$CXX"
-GFORTRAN="$GFORTRAN"
-GCJ="$GCJ"
-AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"
-
-
-# The HP-UX ksh and POSIX shell print the target directory to stdout
-# if CDPATH is set.
-(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
-
-sed_quote_subst='$sed_quote_subst'
-double_quote_subst='$double_quote_subst'
-delay_variable_subst='$delay_variable_subst'
-macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`'
-macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`'
-enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`'
-enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`'
-pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`'
-enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`'
-SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`'
-ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`'
-host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`'
-host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`'
-host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`'
-build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`'
-build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`'
-build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`'
-SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`'
-Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`'
-GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`'
-EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`'
-FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`'
-LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`'
-NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`'
-LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`'
-max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`'
-ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`'
-exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`'
-lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`'
-lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`'
-lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`'
-reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`'
-reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`'
-OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`'
-deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`'
-file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`'
-AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`'
-AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`'
-STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`'
-RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`'
-old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`'
-old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`'
-old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`'
-lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`'
-CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`'
-CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`'
-compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`'
-GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`'
-lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`'
-lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`'
-lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`'
-lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`'
-objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`'
-MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`'
-lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`'
-lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`'
-lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`'
-lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`'
-lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`'
-need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`'
-DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`'
-NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`'
-LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`'
-OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`'
-OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`'
-libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`'
-shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`'
-extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`'
-archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`'
-enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`'
-export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`'
-whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`'
-compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`'
-old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`'
-old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`'
-archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`'
-archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`'
-module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`'
-module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`'
-with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`'
-allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`'
-no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`'
-hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`'
-hardcode_libdir_flag_spec_ld='`$ECHO "$hardcode_libdir_flag_spec_ld" | $SED "$delay_single_quote_subst"`'
-hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`'
-hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`'
-hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`'
-hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`'
-hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`'
-hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`'
-inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`'
-link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`'
-fix_srcfile_path='`$ECHO "$fix_srcfile_path" | $SED "$delay_single_quote_subst"`'
-always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`'
-export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`'
-exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`'
-include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`'
-prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`'
-file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`'
-variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`'
-need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`'
-need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`'
-version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`'
-runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`'
-shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`'
-shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`'
-libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`'
-library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`'
-soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`'
-install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`'
-postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`'
-postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`'
-finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`'
-finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`'
-hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`'
-sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`'
-sys_lib_dlsearch_path_spec='`$ECHO "$sys_lib_dlsearch_path_spec" | $SED "$delay_single_quote_subst"`'
-hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`'
-enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`'
-enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`'
-enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`'
-old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`'
-striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`'
-
-LTCC='$LTCC'
-LTCFLAGS='$LTCFLAGS'
-compiler='$compiler_DEFAULT'
-
-# A function that is used when there is no print builtin or printf.
-func_fallback_echo ()
-{
- eval 'cat <<_LTECHO_EOF
-\$1
-_LTECHO_EOF'
-}
-
-# Quote evaled strings.
-for var in SHELL \
-ECHO \
-SED \
-GREP \
-EGREP \
-FGREP \
-LD \
-NM \
-LN_S \
-lt_SP2NL \
-lt_NL2SP \
-reload_flag \
-OBJDUMP \
-deplibs_check_method \
-file_magic_cmd \
-AR \
-AR_FLAGS \
-STRIP \
-RANLIB \
-CC \
-CFLAGS \
-compiler \
-lt_cv_sys_global_symbol_pipe \
-lt_cv_sys_global_symbol_to_cdecl \
-lt_cv_sys_global_symbol_to_c_name_address \
-lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \
-lt_prog_compiler_no_builtin_flag \
-lt_prog_compiler_wl \
-lt_prog_compiler_pic \
-lt_prog_compiler_static \
-lt_cv_prog_compiler_c_o \
-need_locks \
-DSYMUTIL \
-NMEDIT \
-LIPO \
-OTOOL \
-OTOOL64 \
-shrext_cmds \
-export_dynamic_flag_spec \
-whole_archive_flag_spec \
-compiler_needs_object \
-with_gnu_ld \
-allow_undefined_flag \
-no_undefined_flag \
-hardcode_libdir_flag_spec \
-hardcode_libdir_flag_spec_ld \
-hardcode_libdir_separator \
-fix_srcfile_path \
-exclude_expsyms \
-include_expsyms \
-file_list_spec \
-variables_saved_for_relink \
-libname_spec \
-library_names_spec \
-soname_spec \
-install_override_mode \
-finish_eval \
-old_striplib \
-striplib; do
- case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
- *[\\\\\\\`\\"\\\$]*)
- eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\""
- ;;
- *)
- eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
- ;;
- esac
-done
-
-# Double-quote double-evaled strings.
-for var in reload_cmds \
-old_postinstall_cmds \
-old_postuninstall_cmds \
-old_archive_cmds \
-extract_expsyms_cmds \
-old_archive_from_new_cmds \
-old_archive_from_expsyms_cmds \
-archive_cmds \
-archive_expsym_cmds \
-module_cmds \
-module_expsym_cmds \
-export_symbols_cmds \
-prelink_cmds \
-postinstall_cmds \
-postuninstall_cmds \
-finish_cmds \
-sys_lib_search_path_spec \
-sys_lib_dlsearch_path_spec; do
- case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
- *[\\\\\\\`\\"\\\$]*)
- eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\""
- ;;
- *)
- eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
- ;;
- esac
-done
-
-ac_aux_dir='$ac_aux_dir'
-xsi_shell='$xsi_shell'
-lt_shell_append='$lt_shell_append'
-
-# See if we are running on zsh, and set the options which allow our
-# commands through without removal of \ escapes INIT.
-if test -n "\${ZSH_VERSION+set}" ; then
- setopt NO_GLOB_SUBST
-fi
-
-
- PACKAGE='$PACKAGE'
- VERSION='$VERSION'
- TIMESTAMP='$TIMESTAMP'
- RM='$RM'
- ofile='$ofile'
-
-
-
-
-_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
- "default-1") CONFIG_COMMANDS="$CONFIG_COMMANDS default-1" ;;
- "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
- "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
- "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;;
- "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
- "testsuite/Makefile") CONFIG_FILES="$CONFIG_FILES testsuite/Makefile" ;;
- "testsuite/mfconfig.exp") CONFIG_FILES="$CONFIG_FILES testsuite/mfconfig.exp" ;;
-
- *) 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_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=
- trap 'exit_status=$?
- { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$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 -n "$tmp" && test -d "$tmp"
-} ||
-{
- tmp=./conf$$-$RANDOM
- (umask 077 && mkdir "$tmp")
-} || as_fn_error "cannot create a temporary directory in ." "$LINENO" 5
-
-# 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
-
-
-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 {' >"$tmp/subs1.awk" &&
-_ACEOF
-
-
-{
- 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 >>"\$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 >>"\$tmp/subs1.awk" <<_ACAWK &&
- for (key in S) S_is_set[key] = 1
- FS = ""
-
-}
-{
- 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
- }
-
- print line
-}
-
-_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 < "$tmp/subs1.awk" > "$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 $(srcdir),
-# ${srcdir} and @srcdir@ 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[ ]*=/{
-s/:*\$(srcdir):*/:/
-s/:*\${srcdir}:*/:/
-s/:*@srcdir@:*/:/
-s/^\([^=]*=[ ]*\):*/\1/
-s/:*$//
-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 >"$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_t=`sed -n "/$ac_delim/p" confdefs.h`
- if test -z "$ac_t"; 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 :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="$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 "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 >"$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
- #
-
- case $INSTALL in
- [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
- *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
- esac
- ac_MKDIR_P=$MKDIR_P
- case $MKDIR_P in
- [\\/$]* | ?:[\\/]* ) ;;
- */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;;
- esac
-_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
-s&@INSTALL@&$ac_INSTALL&;t t
-s&@MKDIR_P@&$ac_MKDIR_P&;t t
-$ac_datarootdir_hack
-"
-eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$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' "$tmp/out"`; test -n "$ac_out"; } &&
- { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$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 "$tmp/stdin"
- case $ac_file in
- -) cat "$tmp/out" && rm -f "$tmp/out";;
- *) rm -f "$ac_file" && mv "$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 "$tmp/defines.awk"' "$ac_file_inputs"
- } >"$tmp/config.h" \
- || as_fn_error "could not create $ac_file" "$LINENO" 5
- if diff "$ac_file" "$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 "$tmp/config.h" "$ac_file" \
- || as_fn_error "could not create $ac_file" "$LINENO" 5
- fi
- else
- $as_echo "/* $configure_input */" \
- && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" \
- || as_fn_error "could not create -" "$LINENO" 5
- fi
-# Compute "$ac_file"'s index in $config_headers.
-_am_arg="$ac_file"
-_am_stamp_count=1
-for _am_header in $config_headers :; do
- case $_am_header in
- $_am_arg | $_am_arg:* )
- break ;;
- * )
- _am_stamp_count=`expr $_am_stamp_count + 1` ;;
- esac
-done
-echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" ||
-$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
- X"$_am_arg" : 'X\(//\)[^/]' \| \
- X"$_am_arg" : 'X\(//\)$' \| \
- X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$_am_arg" |
- sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
- s//\1/
- q
- }
- /^X\(\/\/\)[^/].*/{
- s//\1/
- q
- }
- /^X\(\/\/\)$/{
- s//\1/
- q
- }
- /^X\(\/\).*/{
- s//\1/
- q
- }
- s/.*/./; q'`/stamp-h$_am_stamp_count
- ;;
-
- :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
- "default-1":C)
-# Only add multilib support code if we just rebuilt the top-level
-# Makefile.
-case " $CONFIG_FILES " in
- *" Makefile "*)
- ac_file=Makefile . ${multi_basedir}/config-ml.in
- ;;
-esac ;;
- "depfiles":C) test x"$AMDEP_TRUE" != x"" || {
- # Autoconf 2.62 quotes --file arguments for eval, but not when files
- # are listed without --file. Let's play safe and only enable the eval
- # if we detect the quoting.
- case $CONFIG_FILES in
- *\'*) eval set x "$CONFIG_FILES" ;;
- *) set x $CONFIG_FILES ;;
- esac
- shift
- for mf
- do
- # Strip MF so we end up with the name of the file.
- mf=`echo "$mf" | sed -e 's/:.*$//'`
- # Check whether this is an Automake generated Makefile or not.
- # We used to match only the files named `Makefile.in', but
- # some people rename them; so instead we look at the file content.
- # Grep'ing the first line is not enough: some people post-process
- # each Makefile.in and add a new line on top of each file to say so.
- # Grep'ing the whole file is not good either: AIX grep has a line
- # limit of 2048, but all sed's we know have understand at least 4000.
- if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
- dirpart=`$as_dirname -- "$mf" ||
-$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
- X"$mf" : 'X\(//\)[^/]' \| \
- X"$mf" : 'X\(//\)$' \| \
- X"$mf" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$mf" |
- sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
- s//\1/
- q
- }
- /^X\(\/\/\)[^/].*/{
- s//\1/
- q
- }
- /^X\(\/\/\)$/{
- s//\1/
- q
- }
- /^X\(\/\).*/{
- s//\1/
- q
- }
- s/.*/./; q'`
- else
- continue
- fi
- # Extract the definition of DEPDIR, am__include, and am__quote
- # from the Makefile without running `make'.
- DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
- test -z "$DEPDIR" && continue
- am__include=`sed -n 's/^am__include = //p' < "$mf"`
- test -z "am__include" && continue
- am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
- # When using ansi2knr, U may be empty or an underscore; expand it
- U=`sed -n 's/^U = //p' < "$mf"`
- # Find all dependency output files, they are included files with
- # $(DEPDIR) in their names. We invoke sed twice because it is the
- # simplest approach to changing $(DEPDIR) to its actual value in the
- # expansion.
- for file in `sed -n "
- s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
- sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
- # Make sure the directory exists.
- test -f "$dirpart/$file" && continue
- fdir=`$as_dirname -- "$file" ||
-$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
- X"$file" : 'X\(//\)[^/]' \| \
- X"$file" : 'X\(//\)$' \| \
- X"$file" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$file" |
- sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
- s//\1/
- q
- }
- /^X\(\/\/\)[^/].*/{
- s//\1/
- q
- }
- /^X\(\/\/\)$/{
- s//\1/
- q
- }
- /^X\(\/\).*/{
- s//\1/
- q
- }
- s/.*/./; q'`
- as_dir=$dirpart/$fdir; as_fn_mkdir_p
- # echo "creating $dirpart/$file"
- echo '# dummy' > "$dirpart/$file"
- done
- done
-}
- ;;
- "libtool":C)
-
- # See if we are running on zsh, and set the options which allow our
- # commands through without removal of \ escapes.
- if test -n "${ZSH_VERSION+set}" ; then
- setopt NO_GLOB_SUBST
- fi
-
- cfgfile="${ofile}T"
- trap "$RM \"$cfgfile\"; exit 1" 1 2 15
- $RM "$cfgfile"
-
- cat <<_LT_EOF >> "$cfgfile"
-#! $SHELL
-
-# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
-# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION
-# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
-# NOTE: Changes made to this file will be lost: look at ltmain.sh.
-#
-# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
-# 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
-# Written by Gordon Matzigkeit, 1996
-#
-# This file is part of GNU Libtool.
-#
-# GNU Libtool is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License as
-# published by the Free Software Foundation; either version 2 of
-# the License, or (at your option) any later version.
-#
-# As a special exception to the GNU General Public License,
-# if you distribute this file as part of a program or library that
-# is built using GNU Libtool, you may include this file under the
-# same distribution terms that you use for the rest of that program.
-#
-# GNU Libtool is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with GNU Libtool; see the file COPYING. If not, a copy
-# can be downloaded from http://www.gnu.org/licenses/gpl.html, or
-# obtained by writing to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-
-# The names of the tagged configurations supported by this script.
-available_tags=""
-
-# ### BEGIN LIBTOOL CONFIG
-
-# Which release of libtool.m4 was used?
-macro_version=$macro_version
-macro_revision=$macro_revision
-
-# Whether or not to build shared libraries.
-build_libtool_libs=$enable_shared
-
-# Whether or not to build static libraries.
-build_old_libs=$enable_static
-
-# What type of objects to build.
-pic_mode=$pic_mode
-
-# Whether or not to optimize for fast installation.
-fast_install=$enable_fast_install
-
-# Shell to use when invoking shell scripts.
-SHELL=$lt_SHELL
-
-# An echo program that protects backslashes.
-ECHO=$lt_ECHO
-
-# The host system.
-host_alias=$host_alias
-host=$host
-host_os=$host_os
-
-# The build system.
-build_alias=$build_alias
-build=$build
-build_os=$build_os
-
-# A sed program that does not truncate output.
-SED=$lt_SED
-
-# Sed that helps us avoid accidentally triggering echo(1) options like -n.
-Xsed="\$SED -e 1s/^X//"
-
-# A grep program that handles long lines.
-GREP=$lt_GREP
-
-# An ERE matcher.
-EGREP=$lt_EGREP
-
-# A literal string matcher.
-FGREP=$lt_FGREP
-
-# A BSD- or MS-compatible name lister.
-NM=$lt_NM
-
-# Whether we need soft or hard links.
-LN_S=$lt_LN_S
-
-# What is the maximum length of a command?
-max_cmd_len=$max_cmd_len
-
-# Object file suffix (normally "o").
-objext=$ac_objext
-
-# Executable file suffix (normally "").
-exeext=$exeext
-
-# whether the shell understands "unset".
-lt_unset=$lt_unset
-
-# turn spaces into newlines.
-SP2NL=$lt_lt_SP2NL
-
-# turn newlines into spaces.
-NL2SP=$lt_lt_NL2SP
-
-# An object symbol dumper.
-OBJDUMP=$lt_OBJDUMP
-
-# Method to check whether dependent libraries are shared objects.
-deplibs_check_method=$lt_deplibs_check_method
-
-# Command to use when deplibs_check_method == "file_magic".
-file_magic_cmd=$lt_file_magic_cmd
-
-# The archiver.
-AR=$lt_AR
-AR_FLAGS=$lt_AR_FLAGS
-
-# A symbol stripping program.
-STRIP=$lt_STRIP
-
-# Commands used to install an old-style archive.
-RANLIB=$lt_RANLIB
-old_postinstall_cmds=$lt_old_postinstall_cmds
-old_postuninstall_cmds=$lt_old_postuninstall_cmds
-
-# Whether to use a lock for old archive extraction.
-lock_old_archive_extraction=$lock_old_archive_extraction
-
-# A C compiler.
-LTCC=$lt_CC
-
-# LTCC compiler flags.
-LTCFLAGS=$lt_CFLAGS
-
-# Take the output of nm and produce a listing of raw symbols and C names.
-global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
-
-# Transform the output of nm in a proper C declaration.
-global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
-
-# Transform the output of nm in a C name address pair.
-global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
-
-# Transform the output of nm in a C name address pair when lib prefix is needed.
-global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix
-
-# The name of the directory that contains temporary libtool files.
-objdir=$objdir
-
-# Used to examine libraries when file_magic_cmd begins with "file".
-MAGIC_CMD=$MAGIC_CMD
-
-# Must we lock files when doing compilation?
-need_locks=$lt_need_locks
-
-# Tool to manipulate archived DWARF debug symbol files on Mac OS X.
-DSYMUTIL=$lt_DSYMUTIL
-
-# Tool to change global to local symbols on Mac OS X.
-NMEDIT=$lt_NMEDIT
-
-# Tool to manipulate fat objects and archives on Mac OS X.
-LIPO=$lt_LIPO
-
-# ldd/readelf like tool for Mach-O binaries on Mac OS X.
-OTOOL=$lt_OTOOL
-
-# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4.
-OTOOL64=$lt_OTOOL64
-
-# Old archive suffix (normally "a").
-libext=$libext
-
-# Shared library suffix (normally ".so").
-shrext_cmds=$lt_shrext_cmds
-
-# The commands to extract the exported symbol list from a shared archive.
-extract_expsyms_cmds=$lt_extract_expsyms_cmds
-
-# Variables whose values should be saved in libtool wrapper scripts and
-# restored at link time.
-variables_saved_for_relink=$lt_variables_saved_for_relink
-
-# Do we need the "lib" prefix for modules?
-need_lib_prefix=$need_lib_prefix
-
-# Do we need a version for libraries?
-need_version=$need_version
-
-# Library versioning type.
-version_type=$version_type
-
-# Shared library runtime path variable.
-runpath_var=$runpath_var
-
-# Shared library path variable.
-shlibpath_var=$shlibpath_var
-
-# Is shlibpath searched before the hard-coded library search path?
-shlibpath_overrides_runpath=$shlibpath_overrides_runpath
-
-# Format of library name prefix.
-libname_spec=$lt_libname_spec
-
-# List of archive names. First name is the real one, the rest are links.
-# The last name is the one that the linker finds with -lNAME
-library_names_spec=$lt_library_names_spec
-
-# The coded name of the library, if different from the real name.
-soname_spec=$lt_soname_spec
-
-# Permission mode override for installation of shared libraries.
-install_override_mode=$lt_install_override_mode
-
-# Command to use after installation of a shared archive.
-postinstall_cmds=$lt_postinstall_cmds
-
-# Command to use after uninstallation of a shared archive.
-postuninstall_cmds=$lt_postuninstall_cmds
-
-# Commands used to finish a libtool library installation in a directory.
-finish_cmds=$lt_finish_cmds
-
-# As "finish_cmds", except a single script fragment to be evaled but
-# not shown.
-finish_eval=$lt_finish_eval
-
-# Whether we should hardcode library paths into libraries.
-hardcode_into_libs=$hardcode_into_libs
-
-# Compile-time system search path for libraries.
-sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
-
-# Run-time system search path for libraries.
-sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
-
-# Whether dlopen is supported.
-dlopen_support=$enable_dlopen
-
-# Whether dlopen of programs is supported.
-dlopen_self=$enable_dlopen_self
-
-# Whether dlopen of statically linked programs is supported.
-dlopen_self_static=$enable_dlopen_self_static
-
-# Commands to strip libraries.
-old_striplib=$lt_old_striplib
-striplib=$lt_striplib
-
-
-# The linker used to build libraries.
-LD=$lt_LD
-
-# How to create reloadable object files.
-reload_flag=$lt_reload_flag
-reload_cmds=$lt_reload_cmds
-
-# Commands used to build an old-style archive.
-old_archive_cmds=$lt_old_archive_cmds
-
-# A language specific compiler.
-CC=$lt_compiler
-
-# Is the compiler the GNU compiler?
-with_gcc=$GCC
-
-# Compiler flag to turn off builtin functions.
-no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag
-
-# How to pass a linker flag through the compiler.
-wl=$lt_lt_prog_compiler_wl
-
-# Additional compiler flags for building library objects.
-pic_flag=$lt_lt_prog_compiler_pic
-
-# Compiler flag to prevent dynamic linking.
-link_static_flag=$lt_lt_prog_compiler_static
-
-# Does compiler simultaneously support -c and -o options?
-compiler_c_o=$lt_lt_cv_prog_compiler_c_o
-
-# Whether or not to add -lc for building shared libraries.
-build_libtool_need_lc=$archive_cmds_need_lc
-
-# Whether or not to disallow shared libs when runtime libs are static.
-allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes
-
-# Compiler flag to allow reflexive dlopens.
-export_dynamic_flag_spec=$lt_export_dynamic_flag_spec
-
-# Compiler flag to generate shared objects directly from archives.
-whole_archive_flag_spec=$lt_whole_archive_flag_spec
-
-# Whether the compiler copes with passing no objects directly.
-compiler_needs_object=$lt_compiler_needs_object
-
-# Create an old-style archive from a shared archive.
-old_archive_from_new_cmds=$lt_old_archive_from_new_cmds
-
-# Create a temporary old-style archive to link instead of a shared archive.
-old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds
-
-# Commands used to build a shared archive.
-archive_cmds=$lt_archive_cmds
-archive_expsym_cmds=$lt_archive_expsym_cmds
-
-# Commands used to build a loadable module if different from building
-# a shared archive.
-module_cmds=$lt_module_cmds
-module_expsym_cmds=$lt_module_expsym_cmds
-
-# Whether we are building with GNU ld or not.
-with_gnu_ld=$lt_with_gnu_ld
-
-# Flag that allows shared libraries with undefined symbols to be built.
-allow_undefined_flag=$lt_allow_undefined_flag
-
-# Flag that enforces no undefined symbols.
-no_undefined_flag=$lt_no_undefined_flag
-
-# Flag to hardcode \$libdir into a binary during linking.
-# This must work even if \$libdir does not exist
-hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec
-
-# If ld is used when linking, flag to hardcode \$libdir into a binary
-# during linking. This must work even if \$libdir does not exist.
-hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld
-
-# Whether we need a single "-rpath" flag with a separated argument.
-hardcode_libdir_separator=$lt_hardcode_libdir_separator
-
-# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes
-# DIR into the resulting binary.
-hardcode_direct=$hardcode_direct
-
-# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes
-# DIR into the resulting binary and the resulting library dependency is
-# "absolute",i.e impossible to change by setting \${shlibpath_var} if the
-# library is relocated.
-hardcode_direct_absolute=$hardcode_direct_absolute
-
-# Set to "yes" if using the -LDIR flag during linking hardcodes DIR
-# into the resulting binary.
-hardcode_minus_L=$hardcode_minus_L
-
-# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
-# into the resulting binary.
-hardcode_shlibpath_var=$hardcode_shlibpath_var
-
-# Set to "yes" if building a shared library automatically hardcodes DIR
-# into the library and all subsequent libraries and executables linked
-# against it.
-hardcode_automatic=$hardcode_automatic
-
-# Set to yes if linker adds runtime paths of dependent libraries
-# to runtime path list.
-inherit_rpath=$inherit_rpath
-
-# Whether libtool must link a program against all its dependency libraries.
-link_all_deplibs=$link_all_deplibs
-
-# Fix the shell variable \$srcfile for the compiler.
-fix_srcfile_path=$lt_fix_srcfile_path
-
-# Set to "yes" if exported symbols are required.
-always_export_symbols=$always_export_symbols
-
-# The commands to list exported symbols.
-export_symbols_cmds=$lt_export_symbols_cmds
-
-# Symbols that should not be listed in the preloaded symbols.
-exclude_expsyms=$lt_exclude_expsyms
-
-# Symbols that must always be exported.
-include_expsyms=$lt_include_expsyms
-
-# Commands necessary for linking programs (against libraries) with templates.
-prelink_cmds=$lt_prelink_cmds
-
-# Specify filename containing input files.
-file_list_spec=$lt_file_list_spec
-
-# How to hardcode a shared library path into an executable.
-hardcode_action=$hardcode_action
-
-# ### END LIBTOOL CONFIG
-
-_LT_EOF
-
- case $host_os in
- aix3*)
- cat <<\_LT_EOF >> "$cfgfile"
-# 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
-_LT_EOF
- ;;
- esac
-
-
-ltmain="$ac_aux_dir/ltmain.sh"
-
-
- # We use sed instead of cat because bash on DJGPP gets confused if
- # if finds mixed CR/LF and LF-only lines. Since sed operates in
- # text mode, it properly converts lines to CR/LF. This bash problem
- # is reportedly fixed, but why not run on old versions too?
- sed '/^# Generated shell functions inserted here/q' "$ltmain" >> "$cfgfile" \
- || (rm -f "$cfgfile"; exit 1)
-
- case $xsi_shell in
- yes)
- cat << \_LT_EOF >> "$cfgfile"
-
-# func_dirname file append nondir_replacement
-# Compute the dirname of FILE. If nonempty, add APPEND to the result,
-# otherwise set result to NONDIR_REPLACEMENT.
-func_dirname ()
-{
- case ${1} in
- */*) func_dirname_result="${1%/*}${2}" ;;
- * ) func_dirname_result="${3}" ;;
- esac
-}
-
-# func_basename file
-func_basename ()
-{
- func_basename_result="${1##*/}"
-}
-
-# func_dirname_and_basename file append nondir_replacement
-# perform func_basename and func_dirname in a single function
-# call:
-# dirname: Compute the dirname of FILE. If nonempty,
-# add APPEND to the result, otherwise set result
-# to NONDIR_REPLACEMENT.
-# value returned in "$func_dirname_result"
-# basename: Compute filename of FILE.
-# value retuned in "$func_basename_result"
-# Implementation must be kept synchronized with func_dirname
-# and func_basename. For efficiency, we do not delegate to
-# those functions but instead duplicate the functionality here.
-func_dirname_and_basename ()
-{
- case ${1} in
- */*) func_dirname_result="${1%/*}${2}" ;;
- * ) func_dirname_result="${3}" ;;
- esac
- func_basename_result="${1##*/}"
-}
-
-# func_stripname prefix suffix name
-# strip PREFIX and SUFFIX off of NAME.
-# PREFIX and SUFFIX must not contain globbing or regex special
-# characters, hashes, percent signs, but SUFFIX may contain a leading
-# dot (in which case that matches only a dot).
-func_stripname ()
-{
- # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are
- # positional parameters, so assign one to ordinary parameter first.
- func_stripname_result=${3}
- func_stripname_result=${func_stripname_result#"${1}"}
- func_stripname_result=${func_stripname_result%"${2}"}
-}
-
-# func_opt_split
-func_opt_split ()
-{
- func_opt_split_opt=${1%%=*}
- func_opt_split_arg=${1#*=}
-}
-
-# func_lo2o object
-func_lo2o ()
-{
- case ${1} in
- *.lo) func_lo2o_result=${1%.lo}.${objext} ;;
- *) func_lo2o_result=${1} ;;
- esac
-}
-
-# func_xform libobj-or-source
-func_xform ()
-{
- func_xform_result=${1%.*}.lo
-}
-
-# func_arith arithmetic-term...
-func_arith ()
-{
- func_arith_result=$(( $* ))
-}
-
-# func_len string
-# STRING may not start with a hyphen.
-func_len ()
-{
- func_len_result=${#1}
-}
-
-_LT_EOF
- ;;
- *) # Bourne compatible functions.
- cat << \_LT_EOF >> "$cfgfile"
-
-# func_dirname file append nondir_replacement
-# Compute the dirname of FILE. If nonempty, add APPEND to the result,
-# otherwise set result to NONDIR_REPLACEMENT.
-func_dirname ()
-{
- # Extract subdirectory from the argument.
- func_dirname_result=`$ECHO "${1}" | $SED "$dirname"`
- if test "X$func_dirname_result" = "X${1}"; then
- func_dirname_result="${3}"
- else
- func_dirname_result="$func_dirname_result${2}"
- fi
-}
-
-# func_basename file
-func_basename ()
-{
- func_basename_result=`$ECHO "${1}" | $SED "$basename"`
-}
-
-
-# func_stripname prefix suffix name
-# strip PREFIX and SUFFIX off of NAME.
-# PREFIX and SUFFIX must not contain globbing or regex special
-# characters, hashes, percent signs, but SUFFIX may contain a leading
-# dot (in which case that matches only a dot).
-# func_strip_suffix prefix name
-func_stripname ()
-{
- case ${2} in
- .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;;
- *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;;
- esac
-}
-
-# sed scripts:
-my_sed_long_opt='1s/^\(-[^=]*\)=.*/\1/;q'
-my_sed_long_arg='1s/^-[^=]*=//'
-
-# func_opt_split
-func_opt_split ()
-{
- func_opt_split_opt=`$ECHO "${1}" | $SED "$my_sed_long_opt"`
- func_opt_split_arg=`$ECHO "${1}" | $SED "$my_sed_long_arg"`
-}
-
-# func_lo2o object
-func_lo2o ()
-{
- func_lo2o_result=`$ECHO "${1}" | $SED "$lo2o"`
-}
-
-# func_xform libobj-or-source
-func_xform ()
-{
- func_xform_result=`$ECHO "${1}" | $SED 's/\.[^.]*$/.lo/'`
-}
-
-# func_arith arithmetic-term...
-func_arith ()
-{
- func_arith_result=`expr "$@"`
-}
-
-# func_len string
-# STRING may not start with a hyphen.
-func_len ()
-{
- func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len`
-}
-
-_LT_EOF
-esac
-
-case $lt_shell_append in
- yes)
- cat << \_LT_EOF >> "$cfgfile"
-
-# func_append var value
-# Append VALUE to the end of shell variable VAR.
-func_append ()
-{
- eval "$1+=\$2"
-}
-_LT_EOF
- ;;
- *)
- cat << \_LT_EOF >> "$cfgfile"
-
-# func_append var value
-# Append VALUE to the end of shell variable VAR.
-func_append ()
-{
- eval "$1=\$$1\$2"
-}
-
-_LT_EOF
- ;;
- esac
-
-
- sed -n '/^# Generated shell functions inserted here/,$p' "$ltmain" >> "$cfgfile" \
- || (rm -f "$cfgfile"; exit 1)
-
- mv -f "$cfgfile" "$ofile" ||
- (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
- chmod +x "$ofile"
-
- ;;
-
- 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 $?
-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/libmudflap/configure.ac b/libmudflap/configure.ac
deleted file mode 100644
index 83aba5a5ba8..00000000000
--- a/libmudflap/configure.ac
+++ /dev/null
@@ -1,270 +0,0 @@
-# Process this file with autoconf to produce a configure script, like so:
-# aclocal -I .. -I ../config && autoconf && autoheader && automake
-
-AC_PREREQ(2.64)
-AC_INIT(libmudflap, 1.0)
-AC_CONFIG_SRCDIR(mf-runtime.c)
-AC_CANONICAL_SYSTEM
-ACX_NONCANONICAL_TARGET
-
-AM_INIT_AUTOMAKE([no-dist])
-
-AC_MSG_CHECKING([for --enable-version-specific-runtime-libs])
-AC_ARG_ENABLE(version-specific-runtime-libs,
-[ --enable-version-specific-runtime-libs Specify that runtime libraries should be installed in a compiler-specific directory ],
-[case "$enableval" in
- yes) version_specific_libs=yes ;;
- no) version_specific_libs=no ;;
- *) AC_MSG_ERROR([Unknown argument to enable/disable version-specific libs]);;
- esac],
-[version_specific_libs=no])
-AC_MSG_RESULT($version_specific_libs)
-
-AM_MAINTAINER_MODE
-AC_EXEEXT
-
-AM_ENABLE_MULTILIB(, ..)
-
-target_alias=${target_alias-$host_alias}
-AC_SUBST(target_alias)
-
-AC_CONFIG_HEADERS(config.h)
-
-AC_LANG_C
-# The same as in boehm-gc and libstdc++. Have to borrow it from there.
-# We must force CC to /not/ be precious variables; otherwise
-# the wrong, non-multilib-adjusted value will be used in multilibs.
-# As a side effect, we have to subst CFLAGS ourselves.
-
-m4_rename([_AC_ARG_VAR_PRECIOUS],[real_PRECIOUS])
-m4_define([_AC_ARG_VAR_PRECIOUS],[])
-AC_PROG_CC
-m4_rename_force([real_PRECIOUS],[_AC_ARG_VAR_PRECIOUS])
-
-AC_SUBST(CFLAGS)
-
-if test "x$GCC" != "xyes"; then
- AC_MSG_ERROR([libmudflap must be built with GCC])
-fi
-AC_PROG_CPP
-
-# Some hosts don't have dlsym(RTLD_NEXT, "symbol") for use in
-# symbol interposition. We disable shared libraries for these.
-AC_MSG_CHECKING([whether dlsym(RTLD_NEXT,...) is available])
-AC_TRY_COMPILE([
-#define _GNU_SOURCE
-#include <dlfcn.h>
-],
-[void *foo = dlsym (RTLD_NEXT, "exit");],
-[AC_MSG_RESULT(yes)],
-[AC_MSG_RESULT(no)
-enable_shared=no])
-
-AC_CHECK_HEADERS(stdint.h execinfo.h signal.h dlfcn.h dirent.h pwd.h grp.h \
- netdb.h sys/ipc.h sys/sem.h sys/shm.h sys/wait.h ctype.h mntent.h \
- sys/mnttab.h sys/socket.h netinet/in.h arpa/inet.h dlfcn.h sys/mman.h)
-
-AC_CHECK_FUNCS(backtrace backtrace_symbols gettimeofday signal)
-AC_CHECK_FUNCS(fopen64 fseeko64 ftello64 stat64 freopen64)
-AC_CHECK_FUNCS(setbuf setbuffer setlinebuf setvbuf)
-AC_CHECK_FUNCS(strnlen memrchr strncpy memmem sethostname)
-AC_CHECK_FUNCS(__ctype_b_loc __ctype_tolower_loc __ctype_toupper_loc)
-AC_CHECK_FUNCS(getlogin cuserid getpwnam getpwuid getpwent getgrnam getgrgid getgrent)
-AC_CHECK_FUNCS(getlogin_r getpwnam_r getpwuid_r getgrnam_r getgrgid_r)
-AC_CHECK_FUNCS(getservent getservbyname getservbyport getaddrinfo gai_strerror)
-AC_CHECK_FUNCS(getprotoent getprotobyname getprotobynumber)
-AC_CHECK_FUNCS(getmntent setmntent addmntent)
-AC_CHECK_FUNCS(inet_ntoa mmap munmap)
-AC_CHECK_FUNCS(mmap64)
-AC_CHECK_FUNCS(__libc_freeres)
-AC_CHECK_FUNCS(rawmemchr stpcpy mempcpy)
-
-AC_TRY_COMPILE([#include <sys/types.h>
-#include <sys/ipc.h>
-#include <sys/sem.h>],[union semun foo;], [mf_have_semun=1], [mf_have_semun=0])
-if test $mf_have_semun = 1
-then
- AC_DEFINE(HAVE_UNION_SEMUN, 1, [union semun defined in sys/ipc.h or sys/sem.h])
-fi
-
-
-AC_MSG_CHECKING([for socklen_t in sys/socket.h])
-AC_TRY_COMPILE([#define _POSIX_PII_SOCKET
-#include <sys/types.h>
-#include <sys/socket.h>], [socklen_t x = 5;],
- [AC_DEFINE(HAVE_SOCKLEN_T, 1, [Define it socklen_t typedef is in sys/socket.h.])
- AC_MSG_RESULT(yes)],
- [AC_MSG_RESULT(no)])
-
-AC_LIBTOOL_DLOPEN
-AM_PROG_LIBTOOL
-AC_SUBST(enable_shared)
-AC_SUBST(enable_static)
-
-AC_CHECK_HEADER(stdint.h, [MF_HAVE_STDINT_H=1], [MF_HAVE_STDINT_H=0])
-AC_SUBST(MF_HAVE_STDINT_H)
-if test $MF_HAVE_STDINT_H = 1
-then
- MF_HAVE_UINTPTR_T=1
-else
- AC_TRY_COMPILE([#include <sys/types.h>], [uintptr_t k = 0;],
- [MF_HAVE_UINTPTR_T=1], [MF_HAVE_UINTPTR_T=0])
-fi
-AC_SUBST(MF_HAVE_UINTPTR_T)
-
-AC_CHECK_HEADERS(pthread.h)
-
-AC_MSG_CHECKING([for thread model used by GCC])
-target_thread_file=`$CC -v 2>&1 | sed -n 's/^Thread model: //p'`
-AC_MSG_RESULT([$target_thread_file])
-
-# We only support posix threads, or no threads at all.
-posix_threads=
-case ${target_thread_file} in
- posix)
- posix_threads=yes
- ;;
- single)
- ;;
- *)
- echo "${target_thread_file} is an unsupported thread package" 1>&2
- exit 1
- ;;
-esac
-
-AM_CONDITIONAL(LIBMUDFLAPTH, [test "x$posix_threads" != "x"])
-if test "x$posix_threads" != "x"
-then
- build_libmudflapth=1
-else
- build_libmudflapth=0
-fi
-AC_SUBST(build_libmudflapth)
-
-AC_CHECK_LIB(dl, dlsym)
-
-AC_CHECK_FUNC(connect,, AC_CHECK_LIB(socket, connect))
-AC_CHECK_FUNC(sched_yield,, AC_CHECK_LIB(rt, sched_yield))
-
-# Calculate toolexeclibdir
-# Also toolexecdir, though it's only used in toolexeclibdir
-case ${version_specific_libs} in
- yes)
- # Need the gcc compiler version to know where to install libraries
- # and header files if --enable-version-specific-runtime-libs option
- # is selected.
- toolexecdir='$(libdir)/gcc/$(target_alias)'
- toolexeclibdir='$(toolexecdir)/$(gcc_version)$(MULTISUBDIR)'
- ;;
- no)
- if test -n "$with_cross_host" &&
- test x"$with_cross_host" != x"no"; then
- # Install a library built with a cross compiler in tooldir, not libdir.
- toolexecdir='$(exec_prefix)/$(target_alias)'
- toolexeclibdir='$(toolexecdir)/lib'
- else
- toolexecdir='$(libdir)/gcc-lib/$(target_alias)'
- toolexeclibdir='$(libdir)'
- fi
- multi_os_directory=`$CC -print-multi-os-directory`
- case $multi_os_directory in
- .) ;; # Avoid trailing /.
- *) toolexeclibdir=$toolexeclibdir/$multi_os_directory ;;
- esac
- ;;
-esac
-AC_SUBST(toolexecdir)
-AC_SUBST(toolexeclibdir)
-
-includedir=${toolexecdir}/include
-AC_SUBST(includedir)
-
-pthread_create_version='""'
-if test "x$enable_shared" = "xyes" && test "x$posix_threads" != "x"; then
- # NB: don't check for -lpthread here, because then it would be
- # added to LIBS. For the thread-unaware libmudflap.la, we don't
- # want it there.
-
- # glibc-related hacks. dlsym() may pick the wrong version of
- # interposed functions like pthread_create on modern glibc.
- # We need to find the proper symbol version string, and use
- # the nonstandard dlvsym().
- AC_CHECK_FUNCS(dlvsym)
- AC_CHECK_TOOL(NM, nm)
- if test "x$ac_cv_have_dlvsym" != "x"; then
- # Try compiling a simple pthreads program. Find the shared libraries it
- # ends up with. Then use "nm" on those libraries to extract the
- # default symbol versioning suffix ("@@"), if any. But that's tricky.
- # Rather, run nm on the resulting executable. Unfortunately, autoconf
- # doesn't appear to have a macro that builds a test executable for
- # subsequent analysis ... so we do it by hand here.
- cat >> conftest.c << EOF
-#include <pthread.h>
-int main () { void *p = (void *) & pthread_create; return (int) p; }
-EOF
- oldLIBS="$LIBS"
- LIBS="$LIBS -lpthread"
- pthread_create_version="\"\""
- AC_MSG_CHECKING(pthread_create symbol version)
- if eval $ac_link 2>&5 && test -s conftest${ac_exeext}; then
- version=`$NM conftest${ac_exeect} | grep 'pthread_create@@' | sed -e 's/^.*@@//'`
- if test "x$version" != "x"; then
- pthread_create_version="\"$version\""
- fi
- fi
- AC_MSG_RESULT($pthread_create_version)
- LIBS="$oldLIBS"
- fi
-fi
-AC_DEFINE_UNQUOTED(PTHREAD_CREATE_VERSION, $pthread_create_version, [pthread_create symbol version])
-
-
-# Figure out whether the compiler supports "-ffunction-sections -fdata-sections",
-# similarly to how libstdc++ does it
-ac_test_CFLAGS="${CFLAGS+set}"
-ac_save_CFLAGS="$CFLAGS"
-
-# Check for -ffunction-sections -fdata-sections
-AC_MSG_CHECKING([for gcc that supports -ffunction-sections -fdata-sections])
-CFLAGS='-Werror -ffunction-sections -fdata-sections'
-AC_TRY_COMPILE(, [int foo;], [ac_fdsections=yes], [ac_fdsections=no])
-if test "$ac_test_CFLAGS" = set; then
- CFLAGS="$ac_save_CFLAGS"
-else
- # this is the suspicious part
- CFLAGS=""
-fi
-if test x"$ac_fdsections" = x"yes"; then
- SECTION_FLAGS='-ffunction-sections -fdata-sections'
-fi
-AC_MSG_RESULT($ac_fdsections)
-AC_SUBST(SECTION_FLAGS)
-
-
-# Check for the name of the symbol used for the entry point.
-AC_CACHE_CHECK([for the name of the symbol used for the entry point],
- [mudflap_cv_entry_point], [
-for name in _start __start unknown; do
- AC_LINK_IFELSE([AC_LANG_PROGRAM([extern char $name@<:@@:>@;], [$name@<:@0@:>@ = 0;])],
- [break])
-done
-mudflap_cv_entry_point="$name"])
-if test "$mudflap_cv_entry_point" = unknown; then
- AC_MSG_ERROR([none of the known symbol names works])
-fi
-AC_DEFINE_UNQUOTED([ENTRY_POINT], [$mudflap_cv_entry_point],
- [Define to the name of the symbol used for the entry point.])
-
-
-if test ${multilib} = yes; then
- multilib_arg="--enable-multilib"
-else
- multilib_arg=
-fi
-
-# See if we support thread-local storage.
-GCC_CHECK_TLS
-GCC_CHECK_EMUTLS
-
-AC_CONFIG_FILES([Makefile testsuite/Makefile testsuite/mfconfig.exp])
-AC_OUTPUT
diff --git a/libmudflap/mf-heuristics.c b/libmudflap/mf-heuristics.c
deleted file mode 100644
index fa2dacb6abd..00000000000
--- a/libmudflap/mf-heuristics.c
+++ /dev/null
@@ -1,169 +0,0 @@
-/* Mudflap: narrow-pointer bounds-checking by tree rewriting.
- Copyright (C) 2002-2013 Free Software Foundation, Inc.
- Contributed by Frank Ch. Eigler <fche@redhat.com>
- and Graydon Hoare <graydon@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.
-
-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/>. */
-
-#include "config.h"
-
-#include <stdio.h>
-
-#include "mf-runtime.h"
-#include "mf-impl.h"
-
-#ifdef _MUDFLAP
-#error "Do not compile this file with -fmudflap!"
-#endif
-
-
-extern char _end[];
-extern char ENTRY_POINT[];
-
-
-/* Run some quick validation of the given region.
- Return -1 / 0 / 1 if the access known-invalid, possibly-valid, or known-valid.
-*/
-int
-__mf_heuristic_check (uintptr_t ptr, uintptr_t ptr_high)
-{
- VERBOSE_TRACE ("mf: heuristic check\n");
-
- /* XXX: Disable the stack bounding check for libmudflapth. We do
- actually have enough information to track stack bounds (see
- __mf_pthread_info in mf-hooks.c), so with a bit of future work,
- this heuristic can be turned on. */
-#ifndef LIBMUDFLAPTH
-
- /* The first heuristic is to check stack bounds. This is a
- transient condition and quick to check. */
- if (__mf_opts.heur_stack_bound)
- {
- uintptr_t stack_top_guess = (uintptr_t)__builtin_frame_address(0);
-#if defined(__i386__) && defined (__linux__)
- uintptr_t stack_segment_base = 0xC0000000; /* XXX: Bad assumption. */
-#else
- /* Cause tests to fail. */
- uintptr_t stack_segment_base = 0;
-#endif
-
- VERBOSE_TRACE ("mf: stack estimated as %p-%p\n",
- (void *) stack_top_guess, (void *) stack_segment_base);
-
- if (ptr_high <= stack_segment_base &&
- ptr >= stack_top_guess &&
- ptr_high >= ptr)
- {
- return 1;
- }
- }
-#endif
-
-
- /* The second heuristic is to scan the range of memory regions
- listed in /proc/self/maps, a special file provided by the Linux
- kernel. Its results may be cached, and in fact, a GUESS object
- may as well be recorded for interesting matching sections. */
- if (__mf_opts.heur_proc_map)
- {
- /* Keep a record of seen records from /proc/self/map. */
- enum { max_entries = 500 };
- struct proc_self_map_entry
- {
- uintptr_t low;
- uintptr_t high;
- };
- static struct proc_self_map_entry entry [max_entries];
- static unsigned entry_used [max_entries];
-
- /* Look for a known proc_self_map entry that may cover this
- region. If one exists, then this heuristic has already run,
- and should not be run again. The check should be allowed to
- fail. */
- unsigned i;
- unsigned deja_vu = 0;
- for (i=0; i<max_entries; i++)
- {
- if (entry_used[i] &&
- (entry[i].low <= ptr) &&
- (entry[i].high >= ptr_high))
- deja_vu = 1;
- }
-
- if (! deja_vu)
- {
- /* Time to run the heuristic. Rescan /proc/self/maps; update the
- entry[] array; XXX: remove expired entries, add new ones.
- XXX: Consider entries that have grown (e.g., stack). */
- char buf[512];
- char flags[4];
- void *low, *high;
- FILE *fp;
-
- fp = fopen ("/proc/self/maps", "r");
- if (fp)
- {
- while (fgets (buf, sizeof(buf), fp))
- {
- if (sscanf (buf, "%p-%p %4c", &low, &high, flags) == 3)
- {
- if ((uintptr_t) low <= ptr &&
- (uintptr_t) high >= ptr_high)
- {
- for (i=0; i<max_entries; i++)
- {
- if (! entry_used[i])
- {
- entry[i].low = (uintptr_t) low;
- entry[i].high = (uintptr_t) high;
- entry_used[i] = 1;
- break;
- }
- }
-
- VERBOSE_TRACE ("mf: registering region #%d "
- "%p-%p given %s",
- i, (void *) low, (void *) high, buf);
-
- __mfu_register ((void *) low, (size_t) (high-low),
- __MF_TYPE_GUESS,
- "/proc/self/maps segment");
-
- return 0; /* undecided (tending to cachable) */
- }
- }
- }
- fclose (fp);
- }
- }
- }
-
-
- /* The third heuristic is to approve all accesses between _start (or its
- equivalent for the given target) and _end, which should include all
- text and initialized data. */
- if (__mf_opts.heur_start_end)
- if (ptr >= (uintptr_t) & ENTRY_POINT && ptr_high <= (uintptr_t) & _end)
- return 1; /* uncacheable */
-
- return 0; /* unknown */
-}
diff --git a/libmudflap/mf-hooks1.c b/libmudflap/mf-hooks1.c
deleted file mode 100644
index 474c8356577..00000000000
--- a/libmudflap/mf-hooks1.c
+++ /dev/null
@@ -1,555 +0,0 @@
-/* Mudflap: narrow-pointer bounds-checking by tree rewriting.
- Copyright (C) 2002-2013 Free Software Foundation, Inc.
- Contributed by Frank Ch. Eigler <fche@redhat.com>
- and Graydon Hoare <graydon@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.
-
-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/>. */
-
-#include "config.h"
-
-#ifndef HAVE_SOCKLEN_T
-#define socklen_t int
-#endif
-
-
-/* These attempt to coax various unix flavours to declare all our
- needed tidbits in the system headers. */
-#if !defined(__FreeBSD__) && !defined(__APPLE__)
-#define _POSIX_SOURCE
-#endif /* Some BSDs break <sys/socket.h> if this is defined. */
-#define _GNU_SOURCE
-#define _XOPEN_SOURCE
-#define _BSD_TYPES
-#define __EXTENSIONS__
-#define _ALL_SOURCE
-#define _LARGE_FILE_API
-#define _XOPEN_SOURCE_EXTENDED 1
-
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <assert.h>
-#include <errno.h>
-#include <limits.h>
-#include <time.h>
-
-#include "mf-runtime.h"
-#include "mf-impl.h"
-
-#ifdef _MUDFLAP
-#error "Do not compile this file with -fmudflap!"
-#endif
-
-
-/* Memory allocation related hook functions. Some of these are
- intercepted via linker wrapping or symbol interposition. Others
- use plain macros in mf-runtime.h. */
-
-
-#if PIC
-
-enum { BS = 4096, NB=10 };
-static char __mf_0fn_bufs[NB][BS];
-static unsigned __mf_0fn_bufs_used[NB];
-
-
-/* A special bootstrap variant. */
-void *
-__mf_0fn_malloc (size_t c)
-{
- unsigned i;
-
- for (i=0; i<NB; i++)
- {
- if (! __mf_0fn_bufs_used[i] && c < BS)
- {
- __mf_0fn_bufs_used[i] = 1;
- return & __mf_0fn_bufs[i][0];
- }
- }
- return NULL;
-}
-#endif
-
-
-#undef malloc
-WRAPPER(void *, malloc, size_t c)
-{
- size_t size_with_crumple_zones;
- DECLARE(void *, malloc, size_t c);
- void *result;
- BEGIN_PROTECT (malloc, c);
-
- size_with_crumple_zones =
- CLAMPADD(c,CLAMPADD(__mf_opts.crumple_zone,
- __mf_opts.crumple_zone));
- BEGIN_MALLOC_PROTECT ();
- result = (char *) CALL_REAL (malloc, size_with_crumple_zones);
- END_MALLOC_PROTECT ();
-
- if (LIKELY(result))
- {
- result += __mf_opts.crumple_zone;
- __mf_register (result, c, __MF_TYPE_HEAP, "malloc region");
- /* XXX: register __MF_TYPE_NOACCESS for crumple zones. */
- }
-
- return result;
-}
-
-
-#ifdef PIC
-/* A special bootstrap variant. */
-void *
-__mf_0fn_calloc (size_t c, size_t n)
-{
- return __mf_0fn_malloc (c * n);
-}
-#endif
-
-
-#undef calloc
-WRAPPER(void *, calloc, size_t c, size_t n)
-{
- size_t size_with_crumple_zones;
- DECLARE(void *, calloc, size_t, size_t);
- DECLARE(void *, malloc, size_t);
- DECLARE(void *, memset, void *, int, size_t);
- char *result;
- BEGIN_PROTECT (calloc, c, n);
-
- size_with_crumple_zones =
- CLAMPADD((c * n), /* XXX: CLAMPMUL */
- CLAMPADD(__mf_opts.crumple_zone,
- __mf_opts.crumple_zone));
- BEGIN_MALLOC_PROTECT ();
- result = (char *) CALL_REAL (malloc, size_with_crumple_zones);
- END_MALLOC_PROTECT ();
-
- if (LIKELY(result))
- memset (result, 0, size_with_crumple_zones);
-
- if (LIKELY(result))
- {
- result += __mf_opts.crumple_zone;
- __mf_register (result, c*n /* XXX: clamp */, __MF_TYPE_HEAP_I, "calloc region");
- /* XXX: register __MF_TYPE_NOACCESS for crumple zones. */
- }
-
- return result;
-}
-
-
-#if PIC
-/* A special bootstrap variant. */
-void *
-__mf_0fn_realloc (void *buf, size_t c)
-{
- return NULL;
-}
-#endif
-
-
-#undef realloc
-WRAPPER(void *, realloc, void *buf, size_t c)
-{
- DECLARE(void * , realloc, void *, size_t);
- size_t size_with_crumple_zones;
- char *base = buf;
- unsigned saved_wipe_heap;
- char *result;
- BEGIN_PROTECT (realloc, buf, c);
-
- if (LIKELY(buf))
- base -= __mf_opts.crumple_zone;
-
- size_with_crumple_zones =
- CLAMPADD(c, CLAMPADD(__mf_opts.crumple_zone,
- __mf_opts.crumple_zone));
- BEGIN_MALLOC_PROTECT ();
- result = (char *) CALL_REAL (realloc, base, size_with_crumple_zones);
- END_MALLOC_PROTECT ();
-
- /* Ensure heap wiping doesn't occur during this peculiar
- unregister/reregister pair. */
- LOCKTH ();
- __mf_set_state (reentrant);
- saved_wipe_heap = __mf_opts.wipe_heap;
- __mf_opts.wipe_heap = 0;
-
- if (LIKELY(buf))
- __mfu_unregister (buf, 0, __MF_TYPE_HEAP_I);
- /* NB: underlying region may have been __MF_TYPE_HEAP. */
-
- if (LIKELY(result))
- {
- result += __mf_opts.crumple_zone;
- __mfu_register (result, c, __MF_TYPE_HEAP_I, "realloc region");
- /* XXX: register __MF_TYPE_NOACCESS for crumple zones. */
- }
-
- /* Restore previous setting. */
- __mf_opts.wipe_heap = saved_wipe_heap;
-
- __mf_set_state (active);
- UNLOCKTH ();
-
- return result;
-}
-
-
-#if PIC
-/* A special bootstrap variant. */
-void
-__mf_0fn_free (void *buf)
-{
- return;
-}
-#endif
-
-#undef free
-WRAPPER(void, free, void *buf)
-{
- /* Use a circular queue to delay some number (__mf_opts.free_queue_length) of free()s. */
- static void *free_queue [__MF_FREEQ_MAX];
- static unsigned free_ptr = 0;
- static int freeq_initialized = 0;
- DECLARE(void, free, void *);
-
- if (UNLIKELY(buf == NULL))
- return;
-
- BEGIN_PROTECT (free, buf);
-
-#if PIC
- /* Check whether the given buffer might have come from a
- __mf_0fn_malloc/calloc call that for whatever reason was not
- redirected back to __mf_0fn_free. If so, we just ignore the
- call. */
- if (UNLIKELY((uintptr_t) buf >= (uintptr_t) __mf_0fn_bufs &&
- (uintptr_t) buf < ((uintptr_t) __mf_0fn_bufs + sizeof(__mf_0fn_bufs))))
- {
- VERBOSE_TRACE ("skipping free of boot (0fn) alloc buffer %p\n", buf);
- return;
- }
-#endif
-
- LOCKTH ();
- if (UNLIKELY(!freeq_initialized))
- {
- memset (free_queue, 0,
- __MF_FREEQ_MAX * sizeof (void *));
- freeq_initialized = 1;
- }
- UNLOCKTH ();
-
- __mf_unregister (buf, 0, __MF_TYPE_HEAP_I);
- /* NB: underlying region may have been __MF_TYPE_HEAP. */
-
- if (UNLIKELY(__mf_opts.free_queue_length > 0))
- {
- char *freeme = NULL;
- LOCKTH ();
- if (free_queue [free_ptr] != NULL)
- {
- freeme = free_queue [free_ptr];
- freeme -= __mf_opts.crumple_zone;
- }
- free_queue [free_ptr] = buf;
- free_ptr = (free_ptr == (__mf_opts.free_queue_length-1) ? 0 : free_ptr + 1);
- UNLOCKTH ();
- if (freeme)
- {
- if (__mf_opts.trace_mf_calls)
- {
- VERBOSE_TRACE ("freeing deferred pointer %p (crumple %u)\n",
- (void *) freeme,
- __mf_opts.crumple_zone);
- }
- BEGIN_MALLOC_PROTECT ();
- CALL_REAL (free, freeme);
- END_MALLOC_PROTECT ();
- }
- }
- else
- {
- /* back pointer up a bit to the beginning of crumple zone */
- char *base = (char *)buf;
- base -= __mf_opts.crumple_zone;
- if (__mf_opts.trace_mf_calls)
- {
- VERBOSE_TRACE ("freeing pointer %p = %p - %u\n",
- (void *) base,
- (void *) buf,
- __mf_opts.crumple_zone);
- }
- BEGIN_MALLOC_PROTECT ();
- CALL_REAL (free, base);
- END_MALLOC_PROTECT ();
- }
-}
-
-
-/* We can only wrap mmap if the target supports it. Likewise for munmap.
- We assume we have both if we have mmap. */
-#ifdef HAVE_MMAP
-
-#if PIC
-/* A special bootstrap variant. */
-void *
-__mf_0fn_mmap (void *start, size_t l, int prot, int f, int fd, off_t off)
-{
-#if defined(__FreeBSD__)
- if (f == 0x1000 && fd == -1 && prot == 0 && off == 0)
- return 0;
-#endif /* Ignore red zone allocation request for initial thread's stack. */
-
- return (void *) -1;
-}
-#endif
-
-
-#undef mmap
-WRAPPER(void *, mmap,
- void *start, size_t length, int prot,
- int flags, int fd, off_t offset)
-{
- DECLARE(void *, mmap, void *, size_t, int,
- int, int, off_t);
- void *result;
- BEGIN_PROTECT (mmap, start, length, prot, flags, fd, offset);
-
- result = CALL_REAL (mmap, start, length, prot,
- flags, fd, offset);
-
- /*
- VERBOSE_TRACE ("mmap (%08lx, %08lx, ...) => %08lx\n",
- (uintptr_t) start, (uintptr_t) length,
- (uintptr_t) result);
- */
-
- if (result != (void *)-1)
- {
- /* Register each page as a heap object. Why not register it all
- as a single segment? That's so that a later munmap() call
- can unmap individual pages. XXX: would __MF_TYPE_GUESS make
- this more automatic? */
- size_t ps = getpagesize ();
- uintptr_t base = (uintptr_t) result;
- uintptr_t offset;
-
- for (offset=0; offset<length; offset+=ps)
- {
- /* XXX: We could map PROT_NONE to __MF_TYPE_NOACCESS. */
- /* XXX: Unaccessed HEAP pages are reported as leaks. Is this
- appropriate for unaccessed mmap pages? */
- __mf_register ((void *) CLAMPADD (base, offset), ps,
- __MF_TYPE_HEAP_I, "mmap page");
- }
- }
-
- return result;
-}
-
-
-#if PIC
-/* A special bootstrap variant. */
-int
-__mf_0fn_munmap (void *start, size_t length)
-{
- return -1;
-}
-#endif
-
-
-#undef munmap
-WRAPPER(int , munmap, void *start, size_t length)
-{
- DECLARE(int, munmap, void *, size_t);
- int result;
- BEGIN_PROTECT (munmap, start, length);
-
- result = CALL_REAL (munmap, start, length);
-
- /*
- VERBOSE_TRACE ("munmap (%08lx, %08lx, ...) => %08lx\n",
- (uintptr_t) start, (uintptr_t) length,
- (uintptr_t) result);
- */
-
- if (result == 0)
- {
- /* Unregister each page as a heap object. */
- size_t ps = getpagesize ();
- uintptr_t base = (uintptr_t) start & (~ (ps - 1)); /* page align */
- uintptr_t offset;
-
- for (offset=0; offset<length; offset+=ps)
- __mf_unregister ((void *) CLAMPADD (base, offset), ps, __MF_TYPE_HEAP_I);
- }
- return result;
-}
-#endif /* HAVE_MMAP */
-
-
-#ifdef HAVE_MMAP64
-#if PIC
-/* A special bootstrap variant. */
-void *
-__mf_0fn_mmap64 (void *start, size_t l, int prot, int f, int fd, off64_t off)
-{
- return (void *) -1;
-}
-#endif
-
-
-#undef mmap
-WRAPPER(void *, mmap64,
- void *start, size_t length, int prot,
- int flags, int fd, off64_t offset)
-{
- DECLARE(void *, mmap64, void *, size_t, int,
- int, int, off64_t);
- void *result;
- BEGIN_PROTECT (mmap64, start, length, prot, flags, fd, offset);
-
- result = CALL_REAL (mmap64, start, length, prot,
- flags, fd, offset);
-
- /*
- VERBOSE_TRACE ("mmap64 (%08lx, %08lx, ...) => %08lx\n",
- (uintptr_t) start, (uintptr_t) length,
- (uintptr_t) result);
- */
-
- if (result != (void *)-1)
- {
- /* Register each page as a heap object. Why not register it all
- as a single segment? That's so that a later munmap() call
- can unmap individual pages. XXX: would __MF_TYPE_GUESS make
- this more automatic? */
- size_t ps = getpagesize ();
- uintptr_t base = (uintptr_t) result;
- uintptr_t offset;
-
- for (offset=0; offset<length; offset+=ps)
- {
- /* XXX: We could map PROT_NONE to __MF_TYPE_NOACCESS. */
- /* XXX: Unaccessed HEAP pages are reported as leaks. Is this
- appropriate for unaccessed mmap pages? */
- __mf_register ((void *) CLAMPADD (base, offset), ps,
- __MF_TYPE_HEAP_I, "mmap64 page");
- }
- }
-
- return result;
-}
-#endif /* HAVE_MMAP64 */
-
-
-/* This wrapper is a little different, as it's called indirectly from
- __mf_fini also to clean up pending allocations. */
-void *
-__mf_wrap_alloca_indirect (size_t c)
-{
- DECLARE (void *, malloc, size_t);
- DECLARE (void, free, void *);
-
- /* This struct, a linked list, tracks alloca'd objects. The newest
- object is at the head of the list. If we detect that we've
- popped a few levels of stack, then the listed objects are freed
- as needed. NB: The tracking struct is allocated with
- real_malloc; the user data with wrap_malloc.
- */
- struct alloca_tracking { void *ptr; void *stack; struct alloca_tracking* next; };
- static struct alloca_tracking *alloca_history = NULL;
-
- void *stack = __builtin_frame_address (0);
- void *result;
- struct alloca_tracking *track;
-
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- VERBOSE_TRACE ("alloca stack level %p\n", (void *) stack);
-
- /* XXX: thread locking! */
-
- /* Free any previously alloca'd blocks that belong to deeper-nested functions,
- which must therefore have exited by now. */
-
-#define DEEPER_THAN < /* XXX: for x86; steal find_stack_direction() from libiberty/alloca.c */
-
- while (alloca_history &&
- ((uintptr_t) alloca_history->stack DEEPER_THAN (uintptr_t) stack))
- {
- struct alloca_tracking *next = alloca_history->next;
- __mf_unregister (alloca_history->ptr, 0, __MF_TYPE_HEAP);
- BEGIN_MALLOC_PROTECT ();
- CALL_REAL (free, alloca_history->ptr);
- CALL_REAL (free, alloca_history);
- END_MALLOC_PROTECT ();
- alloca_history = next;
- }
-
- /* Allocate new block. */
- result = NULL;
- if (LIKELY (c > 0)) /* alloca(0) causes no allocation. */
- {
- BEGIN_MALLOC_PROTECT ();
- track = (struct alloca_tracking *) CALL_REAL (malloc,
- sizeof (struct alloca_tracking));
- END_MALLOC_PROTECT ();
- if (LIKELY (track != NULL))
- {
- BEGIN_MALLOC_PROTECT ();
- result = CALL_REAL (malloc, c);
- END_MALLOC_PROTECT ();
- if (UNLIKELY (result == NULL))
- {
- BEGIN_MALLOC_PROTECT ();
- CALL_REAL (free, track);
- END_MALLOC_PROTECT ();
- /* Too bad. XXX: What about errno? */
- }
- else
- {
- __mf_register (result, c, __MF_TYPE_HEAP, "alloca region");
- track->ptr = result;
- track->stack = stack;
- track->next = alloca_history;
- alloca_history = track;
- }
- }
- }
-
- return result;
-}
-
-
-#undef alloca
-WRAPPER(void *, alloca, size_t c)
-{
- return __mf_wrap_alloca_indirect (c);
-}
-
diff --git a/libmudflap/mf-hooks2.c b/libmudflap/mf-hooks2.c
deleted file mode 100644
index 4af17df2214..00000000000
--- a/libmudflap/mf-hooks2.c
+++ /dev/null
@@ -1,2198 +0,0 @@
-/* Mudflap: narrow-pointer bounds-checking by tree rewriting.
- Copyright (C) 2002-2013 Free Software Foundation, Inc.
- Contributed by Frank Ch. Eigler <fche@redhat.com>
- and Graydon Hoare <graydon@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.
-
-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/>. */
-
-#include "config.h"
-
-#ifndef HAVE_SOCKLEN_T
-#define socklen_t int
-#endif
-
-/* These attempt to coax various unix flavours to declare all our
- needed tidbits in the system headers. */
-#if !defined(__FreeBSD__) && !defined(__APPLE__)
-#define _POSIX_SOURCE
-#endif /* Some BSDs break <sys/socket.h> if this is defined. */
-#define _GNU_SOURCE
-#define _XOPEN_SOURCE
-#define _BSD_TYPES
-#define __EXTENSIONS__
-#define _ALL_SOURCE
-#define _LARGE_FILE_API
-#define _LARGEFILE64_SOURCE
-#define _XOPEN_SOURCE_EXTENDED 1
-
-#include <string.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <assert.h>
-#include <errno.h>
-#include <limits.h>
-#include <time.h>
-#include <ctype.h>
-#ifdef HAVE_DLFCN_H
-#include <dlfcn.h>
-#endif
-#ifdef HAVE_DIRENT_H
-#include <dirent.h>
-#endif
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-#ifdef HAVE_NETDB_H
-#include <netdb.h>
-#endif
-#ifdef HAVE_SYS_WAIT_H
-#include <sys/wait.h>
-#endif
-#ifdef HAVE_SYS_IPC_H
-#include <sys/ipc.h>
-#endif
-#ifdef HAVE_SYS_SEM_H
-#include <sys/sem.h>
-#endif
-#ifdef HAVE_SYS_SHM_H
-#include <sys/shm.h>
-#endif
-#ifdef HAVE_PWD_H
-#include <pwd.h>
-#endif
-#ifdef HAVE_GRP_H
-#include <grp.h>
-#endif
-#ifdef HAVE_MNTENT_H
-#include <mntent.h>
-#endif
-#ifdef HAVE_SYS_MNTTAB_H
-#include <sys/mnttab.h>
-#endif
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-#ifdef HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
-#ifdef HAVE_ARPA_INET_H
-#include <arpa/inet.h>
-#endif
-
-#include "mf-runtime.h"
-#include "mf-impl.h"
-
-#ifdef _MUDFLAP
-#error "Do not compile this file with -fmudflap!"
-#endif
-
-
-/* A bunch of independent stdlib/unistd hook functions, all
- intercepted by mf-runtime.h macros. */
-
-#ifndef HAVE_STRNLEN
-static inline size_t (strnlen) (const char* str, size_t n)
-{
- const char *s;
-
- for (s = str; n && *s; ++s, --n)
- ;
- return (s - str);
-}
-#endif
-
-
-/* str*,mem*,b* */
-
-WRAPPER2(void *, memcpy, void *dest, const void *src, size_t n)
-{
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT(src, n, __MF_CHECK_READ, "memcpy source");
- MF_VALIDATE_EXTENT(dest, n, __MF_CHECK_WRITE, "memcpy dest");
- return memcpy (dest, src, n);
-}
-
-
-WRAPPER2(void *, memmove, void *dest, const void *src, size_t n)
-{
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT(src, n, __MF_CHECK_READ, "memmove src");
- MF_VALIDATE_EXTENT(dest, n, __MF_CHECK_WRITE, "memmove dest");
- return memmove (dest, src, n);
-}
-
-
-WRAPPER2(void *, memset, void *s, int c, size_t n)
-{
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT(s, n, __MF_CHECK_WRITE, "memset dest");
- return memset (s, c, n);
-}
-
-
-WRAPPER2(int, memcmp, const void *s1, const void *s2, size_t n)
-{
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT(s1, n, __MF_CHECK_READ, "memcmp 1st arg");
- MF_VALIDATE_EXTENT(s2, n, __MF_CHECK_READ, "memcmp 2nd arg");
- return memcmp (s1, s2, n);
-}
-
-
-WRAPPER2(void *, memchr, const void *s, int c, size_t n)
-{
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT(s, n, __MF_CHECK_READ, "memchr region");
- return memchr (s, c, n);
-}
-
-
-#ifdef HAVE_MEMRCHR
-WRAPPER2(void *, memrchr, const void *s, int c, size_t n)
-{
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT(s, n, __MF_CHECK_READ, "memrchr region");
- return memrchr (s, c, n);
-}
-#endif
-
-
-WRAPPER2(char *, strcpy, char *dest, const char *src)
-{
- /* nb: just because strlen(src) == n doesn't mean (src + n) or (src + n +
- 1) are valid pointers. the allocated object might have size < n.
- check anyways. */
-
- size_t n = strlen (src);
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT(src, CLAMPADD(n, 1), __MF_CHECK_READ, "strcpy src");
- MF_VALIDATE_EXTENT(dest, CLAMPADD(n, 1), __MF_CHECK_WRITE, "strcpy dest");
- return strcpy (dest, src);
-}
-
-
-#ifdef HAVE_STRNCPY
-WRAPPER2(char *, strncpy, char *dest, const char *src, size_t n)
-{
- size_t len = strnlen (src, n);
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT(src, len, __MF_CHECK_READ, "strncpy src");
- MF_VALIDATE_EXTENT(dest, len, __MF_CHECK_WRITE, "strncpy dest"); /* nb: strNcpy */
- return strncpy (dest, src, n);
-}
-#endif
-
-
-WRAPPER2(char *, strcat, char *dest, const char *src)
-{
- size_t dest_sz;
- size_t src_sz;
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- dest_sz = strlen (dest);
- src_sz = strlen (src);
- MF_VALIDATE_EXTENT(src, CLAMPADD(src_sz, 1), __MF_CHECK_READ, "strcat src");
- MF_VALIDATE_EXTENT(dest, CLAMPADD(dest_sz, CLAMPADD(src_sz, 1)),
- __MF_CHECK_WRITE, "strcat dest");
- return strcat (dest, src);
-}
-
-
-WRAPPER2(char *, strncat, char *dest, const char *src, size_t n)
-{
-
- /* nb: validating the extents (s,n) might be a mistake for two reasons.
-
- (1) the string s might be shorter than n chars, and n is just a
- poor choice by the programmer. this is not a "true" error in the
- sense that the call to strncat would still be ok.
-
- (2) we could try to compensate for case (1) by calling strlen(s) and
- using that as a bound for the extent to verify, but strlen might fall off
- the end of a non-terminated string, leading to a false positive.
-
- so we will call strnlen(s,n) and use that as a bound.
-
- if strnlen returns a length beyond the end of the registered extent
- associated with s, there is an error: the programmer's estimate for n is
- too large _AND_ the string s is unterminated, in which case they'd be
- about to touch memory they don't own while calling strncat.
-
- this same logic applies to further uses of strnlen later down in this
- file. */
-
- size_t src_sz;
- size_t dest_sz;
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- src_sz = strnlen (src, n);
- dest_sz = strnlen (dest, n);
- MF_VALIDATE_EXTENT(src, src_sz, __MF_CHECK_READ, "strncat src");
- MF_VALIDATE_EXTENT(dest, (CLAMPADD(dest_sz, CLAMPADD(src_sz, 1))),
- __MF_CHECK_WRITE, "strncat dest");
- return strncat (dest, src, n);
-}
-
-
-WRAPPER2(int, strcmp, const char *s1, const char *s2)
-{
- size_t s1_sz;
- size_t s2_sz;
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- s1_sz = strlen (s1);
- s2_sz = strlen (s2);
- MF_VALIDATE_EXTENT(s1, CLAMPADD(s1_sz, 1), __MF_CHECK_READ, "strcmp 1st arg");
- MF_VALIDATE_EXTENT(s2, CLAMPADD(s2_sz, 1), __MF_CHECK_WRITE, "strcmp 2nd arg");
- return strcmp (s1, s2);
-}
-
-
-WRAPPER2(int, strcasecmp, const char *s1, const char *s2)
-{
- size_t s1_sz;
- size_t s2_sz;
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- s1_sz = strlen (s1);
- s2_sz = strlen (s2);
- MF_VALIDATE_EXTENT(s1, CLAMPADD(s1_sz, 1), __MF_CHECK_READ, "strcasecmp 1st arg");
- MF_VALIDATE_EXTENT(s2, CLAMPADD(s2_sz, 1), __MF_CHECK_READ, "strcasecmp 2nd arg");
- return strcasecmp (s1, s2);
-}
-
-
-WRAPPER2(int, strncmp, const char *s1, const char *s2, size_t n)
-{
- size_t s1_sz;
- size_t s2_sz;
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- s1_sz = strnlen (s1, n);
- s2_sz = strnlen (s2, n);
- MF_VALIDATE_EXTENT(s1, s1_sz, __MF_CHECK_READ, "strncmp 1st arg");
- MF_VALIDATE_EXTENT(s2, s2_sz, __MF_CHECK_READ, "strncmp 2nd arg");
- return strncmp (s1, s2, n);
-}
-
-
-WRAPPER2(int, strncasecmp, const char *s1, const char *s2, size_t n)
-{
- size_t s1_sz;
- size_t s2_sz;
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- s1_sz = strnlen (s1, n);
- s2_sz = strnlen (s2, n);
- MF_VALIDATE_EXTENT(s1, s1_sz, __MF_CHECK_READ, "strncasecmp 1st arg");
- MF_VALIDATE_EXTENT(s2, s2_sz, __MF_CHECK_READ, "strncasecmp 2nd arg");
- return strncasecmp (s1, s2, n);
-}
-
-
-WRAPPER2(char *, strdup, const char *s)
-{
- DECLARE(void *, malloc, size_t sz);
- char *result;
- size_t n = strlen (s);
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT(s, CLAMPADD(n,1), __MF_CHECK_READ, "strdup region");
- result = (char *)CALL_REAL(malloc,
- CLAMPADD(CLAMPADD(n,1),
- CLAMPADD(__mf_opts.crumple_zone,
- __mf_opts.crumple_zone)));
-
- if (UNLIKELY(! result)) return result;
-
- result += __mf_opts.crumple_zone;
- memcpy (result, s, n);
- result[n] = '\0';
-
- __mf_register (result, CLAMPADD(n,1), __MF_TYPE_HEAP_I, "strdup region");
- return result;
-}
-
-
-WRAPPER2(char *, strndup, const char *s, size_t n)
-{
- DECLARE(void *, malloc, size_t sz);
- char *result;
- size_t sz = strnlen (s, n);
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT(s, sz, __MF_CHECK_READ, "strndup region"); /* nb: strNdup */
-
- /* note: strndup still adds a \0, even with the N limit! */
- result = (char *)CALL_REAL(malloc,
- CLAMPADD(CLAMPADD(n,1),
- CLAMPADD(__mf_opts.crumple_zone,
- __mf_opts.crumple_zone)));
-
- if (UNLIKELY(! result)) return result;
-
- result += __mf_opts.crumple_zone;
- memcpy (result, s, n);
- result[n] = '\0';
-
- __mf_register (result, CLAMPADD(n,1), __MF_TYPE_HEAP_I, "strndup region");
- return result;
-}
-
-
-WRAPPER2(char *, strchr, const char *s, int c)
-{
- size_t n;
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- n = strlen (s);
- MF_VALIDATE_EXTENT(s, CLAMPADD(n,1), __MF_CHECK_READ, "strchr region");
- return strchr (s, c);
-}
-
-
-WRAPPER2(char *, strrchr, const char *s, int c)
-{
- size_t n;
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- n = strlen (s);
- MF_VALIDATE_EXTENT(s, CLAMPADD(n,1), __MF_CHECK_READ, "strrchr region");
- return strrchr (s, c);
-}
-
-
-WRAPPER2(char *, strstr, const char *haystack, const char *needle)
-{
- size_t haystack_sz;
- size_t needle_sz;
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- haystack_sz = strlen (haystack);
- needle_sz = strlen (needle);
- MF_VALIDATE_EXTENT(haystack, CLAMPADD(haystack_sz, 1), __MF_CHECK_READ, "strstr haystack");
- MF_VALIDATE_EXTENT(needle, CLAMPADD(needle_sz, 1), __MF_CHECK_READ, "strstr needle");
- return strstr (haystack, needle);
-}
-
-
-#ifdef HAVE_MEMMEM
-WRAPPER2(void *, memmem,
- const void *haystack, size_t haystacklen,
- const void *needle, size_t needlelen)
-{
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT(haystack, haystacklen, __MF_CHECK_READ, "memmem haystack");
- MF_VALIDATE_EXTENT(needle, needlelen, __MF_CHECK_READ, "memmem needle");
- return memmem (haystack, haystacklen, needle, needlelen);
-}
-#endif
-
-
-WRAPPER2(size_t, strlen, const char *s)
-{
- size_t result = strlen (s);
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT(s, CLAMPADD(result, 1), __MF_CHECK_READ, "strlen region");
- return result;
-}
-
-
-WRAPPER2(size_t, strnlen, const char *s, size_t n)
-{
- size_t result = strnlen (s, n);
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT(s, result, __MF_CHECK_READ, "strnlen region");
- return result;
-}
-
-
-WRAPPER2(void, bzero, void *s, size_t n)
-{
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT(s, n, __MF_CHECK_WRITE, "bzero region");
- bzero (s, n);
-}
-
-
-#undef bcopy
-WRAPPER2(void, bcopy, const void *src, void *dest, size_t n)
-{
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT(src, n, __MF_CHECK_READ, "bcopy src");
- MF_VALIDATE_EXTENT(dest, n, __MF_CHECK_WRITE, "bcopy dest");
- bcopy (src, dest, n);
-}
-
-
-#undef bcmp
-WRAPPER2(int, bcmp, const void *s1, const void *s2, size_t n)
-{
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT(s1, n, __MF_CHECK_READ, "bcmp 1st arg");
- MF_VALIDATE_EXTENT(s2, n, __MF_CHECK_READ, "bcmp 2nd arg");
- return bcmp (s1, s2, n);
-}
-
-
-WRAPPER2(char *, index, const char *s, int c)
-{
- size_t n = strlen (s);
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT(s, CLAMPADD(n, 1), __MF_CHECK_READ, "index region");
- return index (s, c);
-}
-
-
-WRAPPER2(char *, rindex, const char *s, int c)
-{
- size_t n = strlen (s);
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT(s, CLAMPADD(n, 1), __MF_CHECK_READ, "rindex region");
- return rindex (s, c);
-}
-
-/* XXX: stpcpy, memccpy */
-
-/* XXX: *printf,*scanf */
-
-/* XXX: setjmp, longjmp */
-
-WRAPPER2(char *, asctime, struct tm *tm)
-{
- static char *reg_result = NULL;
- char *result;
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT(tm, sizeof (struct tm), __MF_CHECK_READ, "asctime tm");
- result = asctime (tm);
- if (reg_result == NULL)
- {
- __mf_register (result, strlen (result)+1, __MF_TYPE_STATIC, "asctime string");
- reg_result = result;
- }
- return result;
-}
-
-
-WRAPPER2(char *, ctime, const time_t *timep)
-{
- static char *reg_result = NULL;
- char *result;
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT(timep, sizeof (time_t), __MF_CHECK_READ, "ctime time");
- result = ctime (timep);
- if (reg_result == NULL)
- {
- /* XXX: what if asctime and ctime return the same static ptr? */
- __mf_register (result, strlen (result)+1, __MF_TYPE_STATIC, "ctime string");
- reg_result = result;
- }
- return result;
-}
-
-
-WRAPPER2(struct tm*, localtime, const time_t *timep)
-{
- static struct tm *reg_result = NULL;
- struct tm *result;
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT(timep, sizeof (time_t), __MF_CHECK_READ, "localtime time");
- result = localtime (timep);
- if (reg_result == NULL)
- {
- __mf_register (result, sizeof (struct tm), __MF_TYPE_STATIC, "localtime tm");
- reg_result = result;
- }
- return result;
-}
-
-
-WRAPPER2(struct tm*, gmtime, const time_t *timep)
-{
- static struct tm *reg_result = NULL;
- struct tm *result;
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT(timep, sizeof (time_t), __MF_CHECK_READ, "gmtime time");
- result = gmtime (timep);
- if (reg_result == NULL)
- {
- __mf_register (result, sizeof (struct tm), __MF_TYPE_STATIC, "gmtime tm");
- reg_result = result;
- }
- return result;
-}
-
-
-/* EL start */
-
-/* The following indicate if the result of the corresponding function
- * should be explicitly un/registered by the wrapper
-*/
-
-#ifdef __FreeBSD__
-#define MF_REGISTER_fopen __MF_TYPE_STATIC
-#else
-#undef MF_REGISTER_fopen
-#endif
-#define MF_RESULT_SIZE_fopen (sizeof (FILE))
-
-#undef MF_REGISTER_opendir
-#define MF_RESULT_SIZE_opendir 0 /* (sizeof (DIR)) */
-#undef MF_REGISTER_readdir
-#define MF_REGISTER_gethostbyname __MF_TYPE_STATIC
-#undef MF_REGISTER_gethostbyname_items
-#undef MF_REGISTER_dlopen
-#undef MF_REGISTER_dlerror
-#undef MF_REGISTER_dlsym
-#define MF_REGISTER_shmat __MF_TYPE_GUESS
-
-
-#include <time.h>
-WRAPPER2(time_t, time, time_t *timep)
-{
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- if (NULL != timep)
- MF_VALIDATE_EXTENT (timep, sizeof (*timep), __MF_CHECK_WRITE,
- "time timep");
- return time (timep);
-}
-
-
-WRAPPER2(char *, strerror, int errnum)
-{
- char *p;
- static char * last_strerror = NULL;
-
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- p = strerror (errnum);
- if (last_strerror != NULL)
- __mf_unregister (last_strerror, 0, __MF_TYPE_STATIC);
- if (NULL != p)
- __mf_register (p, strlen (p) + 1, __MF_TYPE_STATIC, "strerror result");
- last_strerror = p;
- return p;
-}
-
-
-
-/* An auxiliary data structure for tracking the hand-made stdio
- buffers we generate during the fopen/fopen64 hooks. In a civilized
- language, this would be a simple dynamically sized FILE*->char*
- lookup table, but this is C and we get to do it by hand. */
-struct mf_filebuffer
-{
- FILE *file;
- char *buffer;
- struct mf_filebuffer *next;
-};
-static struct mf_filebuffer *mf_filebuffers = NULL;
-
-static void
-mkbuffer (FILE *f)
-{
- /* Reset any buffer automatically provided by libc, since this may
- have been done via mechanisms that libmudflap couldn't
- intercept. */
- int rc;
- size_t bufsize = BUFSIZ;
- int bufmode;
- char *buffer = malloc (bufsize);
- struct mf_filebuffer *b = malloc (sizeof (struct mf_filebuffer));
- assert ((buffer != NULL) && (b != NULL));
-
- /* Link it into list. */
- b->file = f;
- b->buffer = buffer;
- b->next = mf_filebuffers;
- mf_filebuffers = b;
-
- /* Determine how the file is supposed to be buffered at the moment. */
- bufmode = fileno (f) == 2 ? _IONBF : (isatty (fileno (f)) ? _IOLBF : _IOFBF);
-
- rc = setvbuf (f, buffer, bufmode, bufsize);
- assert (rc == 0);
-}
-
-static void
-unmkbuffer (FILE *f)
-{
- struct mf_filebuffer *b = mf_filebuffers;
- struct mf_filebuffer **pb = & mf_filebuffers;
- while (b != NULL)
- {
- if (b->file == f)
- {
- *pb = b->next;
- free (b->buffer);
- free (b);
- return;
- }
- pb = & b->next;
- b = b->next;
- }
-}
-
-
-
-WRAPPER2(FILE *, fopen, const char *path, const char *mode)
-{
- size_t n;
- FILE *p;
- TRACE ("%s\n", __PRETTY_FUNCTION__);
-
- n = strlen (path);
- MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "fopen path");
-
- n = strlen (mode);
- MF_VALIDATE_EXTENT (mode, CLAMPADD(n, 1), __MF_CHECK_READ, "fopen mode");
-
- p = fopen (path, mode);
- if (NULL != p) {
-#ifdef MF_REGISTER_fopen
- __mf_register (p, sizeof (*p), MF_REGISTER_fopen, "fopen result");
-#endif
- MF_VALIDATE_EXTENT (p, sizeof (*p), __MF_CHECK_WRITE, "fopen result");
-
- mkbuffer (p);
- }
-
- return p;
-}
-
-
-WRAPPER2(int, setvbuf, FILE *stream, char *buf, int mode, size_t size)
-{
- int rc = 0;
- TRACE ("%s\n", __PRETTY_FUNCTION__);
-
- MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE, "setvbuf stream");
-
- unmkbuffer (stream);
-
- if (buf != NULL)
- MF_VALIDATE_EXTENT (buf, size, __MF_CHECK_WRITE, "setvbuf buffer");
-
- /* Override the user only if it's an auto-allocated buffer request. Otherwise
- assume that the supplied buffer is already known to libmudflap. */
- if ((buf == NULL) && ((mode == _IOFBF) || (mode == _IOLBF)))
- mkbuffer (stream);
- else
- rc = setvbuf (stream, buf, mode, size);
-
- return rc;
-}
-
-
-#ifdef HAVE_SETBUF
-WRAPPER2(int, setbuf, FILE* stream, char *buf)
-{
- return __mfwrap_setvbuf (stream, buf, buf ? _IOFBF : _IONBF, BUFSIZ);
-}
-#endif
-
-#ifdef HAVE_SETBUFFER
-WRAPPER2(int, setbuffer, FILE* stream, char *buf, size_t sz)
-{
- return __mfwrap_setvbuf (stream, buf, buf ? _IOFBF : _IONBF, sz);
-}
-#endif
-
-#ifdef HAVE_SETLINEBUF
-WRAPPER2(int, setlinebuf, FILE* stream)
-{
- return __mfwrap_setvbuf(stream, NULL, _IOLBF, 0);
-}
-#endif
-
-
-
-WRAPPER2(FILE *, fdopen, int fd, const char *mode)
-{
- size_t n;
- FILE *p;
- TRACE ("%s\n", __PRETTY_FUNCTION__);
-
- n = strlen (mode);
- MF_VALIDATE_EXTENT (mode, CLAMPADD(n, 1), __MF_CHECK_READ, "fdopen mode");
-
- p = fdopen (fd, mode);
- if (NULL != p) {
-#ifdef MF_REGISTER_fopen
- __mf_register (p, sizeof (*p), MF_REGISTER_fopen, "fdopen result");
-#endif
- MF_VALIDATE_EXTENT (p, sizeof (*p), __MF_CHECK_WRITE, "fdopen result");
-
- mkbuffer (p);
- }
-
- return p;
-}
-
-
-WRAPPER2(FILE *, freopen, const char *path, const char *mode, FILE *s)
-{
- size_t n;
- FILE *p;
- TRACE ("%s\n", __PRETTY_FUNCTION__);
-
- n = strlen (path);
- MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "freopen path");
-
- MF_VALIDATE_EXTENT (s, (sizeof (*s)), __MF_CHECK_WRITE, "freopen stream");
- unmkbuffer (s);
-
- n = strlen (mode);
- MF_VALIDATE_EXTENT (mode, CLAMPADD(n, 1), __MF_CHECK_READ, "freopen mode");
-
- p = freopen (path, mode, s);
- if (NULL != p) {
-#ifdef MF_REGISTER_fopen
- __mf_register (p, sizeof (*p), MF_REGISTER_fopen, "freopen result");
-#endif
- MF_VALIDATE_EXTENT (p, sizeof (*p), __MF_CHECK_WRITE, "freopen result");
-
- mkbuffer (p);
- }
-
- return p;
-}
-
-
-#ifdef HAVE_FOPEN64
-WRAPPER2(FILE *, fopen64, const char *path, const char *mode)
-{
- size_t n;
- FILE *p;
- TRACE ("%s\n", __PRETTY_FUNCTION__);
-
- n = strlen (path);
- MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "fopen64 path");
-
- n = strlen (mode);
- MF_VALIDATE_EXTENT (mode, CLAMPADD(n, 1), __MF_CHECK_READ, "fopen64 mode");
-
- p = fopen64 (path, mode);
- if (NULL != p) {
-#ifdef MF_REGISTER_fopen
- __mf_register (p, sizeof (*p), MF_REGISTER_fopen, "fopen64 result");
-#endif
- MF_VALIDATE_EXTENT (p, sizeof (*p), __MF_CHECK_WRITE, "fopen64 result");
-
- mkbuffer (p);
- }
-
- return p;
-}
-#endif
-
-
-#ifdef HAVE_FREOPEN64
-WRAPPER2(FILE *, freopen64, const char *path, const char *mode, FILE *s)
-{
- size_t n;
- FILE *p;
- TRACE ("%s\n", __PRETTY_FUNCTION__);
-
- n = strlen (path);
- MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "freopen64 path");
-
- MF_VALIDATE_EXTENT (s, (sizeof (*s)), __MF_CHECK_WRITE, "freopen64 stream");
- unmkbuffer (s);
-
- n = strlen (mode);
- MF_VALIDATE_EXTENT (mode, CLAMPADD(n, 1), __MF_CHECK_READ, "freopen64 mode");
-
- p = freopen (path, mode, s);
- if (NULL != p) {
-#ifdef MF_REGISTER_fopen
- __mf_register (p, sizeof (*p), MF_REGISTER_fopen, "freopen64 result");
-#endif
- MF_VALIDATE_EXTENT (p, sizeof (*p), __MF_CHECK_WRITE, "freopen64 result");
-
- mkbuffer (p);
- }
-
- return p;
-}
-#endif
-
-
-WRAPPER2(int, fclose, FILE *stream)
-{
- int resp;
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
- "fclose stream");
- resp = fclose (stream);
-#ifdef MF_REGISTER_fopen
- __mf_unregister (stream, sizeof (*stream), MF_REGISTER_fopen);
-#endif
- unmkbuffer (stream);
-
- return resp;
-}
-
-
-WRAPPER2(size_t, fread, void *ptr, size_t size, size_t nmemb, FILE *stream)
-{
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
- "fread stream");
- MF_VALIDATE_EXTENT (ptr, size * nmemb, __MF_CHECK_WRITE, "fread buffer");
- return fread (ptr, size, nmemb, stream);
-}
-
-
-WRAPPER2(size_t, fwrite, const void *ptr, size_t size, size_t nmemb,
- FILE *stream)
-{
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
- "fwrite stream");
- MF_VALIDATE_EXTENT (ptr, size * nmemb, __MF_CHECK_READ, "fwrite buffer");
- return fwrite (ptr, size, nmemb, stream);
-}
-
-
-WRAPPER2(int, fgetc, FILE *stream)
-{
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
- "fgetc stream");
- return fgetc (stream);
-}
-
-
-WRAPPER2(char *, fgets, char *s, int size, FILE *stream)
-{
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
- "fgets stream");
- MF_VALIDATE_EXTENT (s, size, __MF_CHECK_WRITE, "fgets buffer");
- return fgets (s, size, stream);
-}
-
-
-WRAPPER2(int, getc, FILE *stream)
-{
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
- "getc stream");
- return getc (stream);
-}
-
-
-WRAPPER2(char *, gets, char *s)
-{
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT (s, 1, __MF_CHECK_WRITE, "gets buffer");
- /* Avoid link-time warning... */
- s = fgets (s, INT_MAX, stdin);
- if (NULL != s) { /* better late than never */
- size_t n = strlen (s);
- MF_VALIDATE_EXTENT (s, CLAMPADD(n, 1), __MF_CHECK_WRITE, "gets buffer");
- }
- return s;
-}
-
-
-WRAPPER2(int, ungetc, int c, FILE *stream)
-{
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
- "ungetc stream");
- return ungetc (c, stream);
-}
-
-
-WRAPPER2(int, fputc, int c, FILE *stream)
-{
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
- "fputc stream");
- return fputc (c, stream);
-}
-
-
-WRAPPER2(int, fputs, const char *s, FILE *stream)
-{
- size_t n;
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- n = strlen (s);
- MF_VALIDATE_EXTENT (s, CLAMPADD(n, 1), __MF_CHECK_READ, "fputs buffer");
- MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
- "fputs stream");
- return fputs (s, stream);
-}
-
-
-WRAPPER2(int, putc, int c, FILE *stream)
-{
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
- "putc stream");
- return putc (c, stream);
-}
-
-
-WRAPPER2(int, puts, const char *s)
-{
- size_t n;
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- n = strlen (s);
- MF_VALIDATE_EXTENT (s, CLAMPADD(n, 1), __MF_CHECK_READ, "puts buffer");
- return puts (s);
-}
-
-
-WRAPPER2(void, clearerr, FILE *stream)
-{
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
- "clearerr stream");
- clearerr (stream);
-}
-
-
-WRAPPER2(int, feof, FILE *stream)
-{
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
- "feof stream");
- return feof (stream);
-}
-
-
-WRAPPER2(int, ferror, FILE *stream)
-{
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
- "ferror stream");
- return ferror (stream);
-}
-
-
-WRAPPER2(int, fileno, FILE *stream)
-{
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
- "fileno stream");
- return fileno (stream);
-}
-
-
-WRAPPER2(int, printf, const char *format, ...)
-{
- size_t n;
- va_list ap;
- int result;
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- n = strlen (format);
- MF_VALIDATE_EXTENT (format, CLAMPADD(n, 1), __MF_CHECK_READ,
- "printf format");
- va_start (ap, format);
- result = vprintf (format, ap);
- va_end (ap);
- return result;
-}
-
-
-WRAPPER2(int, fprintf, FILE *stream, const char *format, ...)
-{
- size_t n;
- va_list ap;
- int result;
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
- "fprintf stream");
- n = strlen (format);
- MF_VALIDATE_EXTENT (format, CLAMPADD(n, 1), __MF_CHECK_READ,
- "fprintf format");
- va_start (ap, format);
- result = vfprintf (stream, format, ap);
- va_end (ap);
- return result;
-}
-
-
-WRAPPER2(int, sprintf, char *str, const char *format, ...)
-{
- size_t n;
- va_list ap;
- int result;
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT (str, 1, __MF_CHECK_WRITE, "sprintf str");
- n = strlen (format);
- MF_VALIDATE_EXTENT (format, CLAMPADD(n, 1), __MF_CHECK_READ,
- "sprintf format");
- va_start (ap, format);
- result = vsprintf (str, format, ap);
- va_end (ap);
- n = strlen (str);
- MF_VALIDATE_EXTENT (str, CLAMPADD(n, 1), __MF_CHECK_WRITE, "sprintf str");
- return result;
-}
-
-
-WRAPPER2(int, snprintf, char *str, size_t size, const char *format, ...)
-{
- size_t n;
- va_list ap;
- int result;
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT (str, size, __MF_CHECK_WRITE, "snprintf str");
- n = strlen (format);
- MF_VALIDATE_EXTENT (format, CLAMPADD(n, 1), __MF_CHECK_READ,
- "snprintf format");
- va_start (ap, format);
- result = vsnprintf (str, size, format, ap);
- va_end (ap);
- return result;
-}
-
-
-WRAPPER2(int, vprintf, const char *format, va_list ap)
-{
- size_t n;
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- n = strlen (format);
- MF_VALIDATE_EXTENT (format, CLAMPADD(n, 1), __MF_CHECK_READ,
- "vprintf format");
- return vprintf (format, ap);
-}
-
-
-WRAPPER2(int, vfprintf, FILE *stream, const char *format, va_list ap)
-{
- size_t n;
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
- "vfprintf stream");
- n = strlen (format);
- MF_VALIDATE_EXTENT (format, CLAMPADD(n, 1), __MF_CHECK_READ,
- "vfprintf format");
- return vfprintf (stream, format, ap);
-}
-
-
-WRAPPER2(int, vsprintf, char *str, const char *format, va_list ap)
-{
- size_t n;
- int result;
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT (str, 1, __MF_CHECK_WRITE, "vsprintf str");
- n = strlen (format);
- MF_VALIDATE_EXTENT (format, CLAMPADD(n, 1), __MF_CHECK_READ,
- "vsprintf format");
- result = vsprintf (str, format, ap);
- n = strlen (str);
- MF_VALIDATE_EXTENT (str, CLAMPADD(n, 1), __MF_CHECK_WRITE, "vsprintf str");
- return result;
-}
-
-
-WRAPPER2(int, vsnprintf, char *str, size_t size, const char *format,
- va_list ap)
-{
- size_t n;
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT (str, size, __MF_CHECK_WRITE, "vsnprintf str");
- n = strlen (format);
- MF_VALIDATE_EXTENT (format, CLAMPADD(n, 1), __MF_CHECK_READ,
- "vsnprintf format");
- return vsnprintf (str, size, format, ap);
-}
-
-
-WRAPPER2(int , access, const char *path, int mode)
-{
- size_t n;
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- n = strlen (path);
- MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "access path");
- return access (path, mode);
-}
-
-
-WRAPPER2(int , remove, const char *path)
-{
- size_t n;
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- n = strlen (path);
- MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "remove path");
- return remove (path);
-}
-
-
-WRAPPER2(int, fflush, FILE *stream)
-{
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- if (stream != NULL)
- MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
- "fflush stream");
- return fflush (stream);
-}
-
-
-WRAPPER2(int, fseek, FILE *stream, long offset, int whence)
-{
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
- "fseek stream");
- return fseek (stream, offset, whence);
-}
-
-
-#ifdef HAVE_FSEEKO64
-WRAPPER2(int, fseeko64, FILE *stream, off64_t offset, int whence)
-{
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
- "fseeko64 stream");
- return fseeko64 (stream, offset, whence);
-}
-#endif
-
-
-WRAPPER2(long, ftell, FILE *stream)
-{
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
- "ftell stream");
- return ftell (stream);
-}
-
-
-#ifdef HAVE_FTELLO64
-WRAPPER2(off64_t, ftello64, FILE *stream)
-{
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
- "ftello64 stream");
- return ftello64 (stream);
-}
-#endif
-
-
-WRAPPER2(void, rewind, FILE *stream)
-{
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
- "rewind stream");
- rewind (stream);
-}
-
-
-WRAPPER2(int, fgetpos, FILE *stream, fpos_t *pos)
-{
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
- "fgetpos stream");
- MF_VALIDATE_EXTENT (pos, sizeof (*pos), __MF_CHECK_WRITE, "fgetpos pos");
- return fgetpos (stream, pos);
-}
-
-
-WRAPPER2(int, fsetpos, FILE *stream, fpos_t *pos)
-{
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
- "fsetpos stream");
- MF_VALIDATE_EXTENT (pos, sizeof (*pos), __MF_CHECK_READ, "fsetpos pos");
- return fsetpos (stream, pos);
-}
-
-
-WRAPPER2(int , stat, const char *path, struct stat *buf)
-{
- size_t n;
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- n = strlen (path);
- MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "stat path");
- MF_VALIDATE_EXTENT (buf, sizeof (*buf), __MF_CHECK_READ, "stat buf");
- return stat (path, buf);
-}
-
-
-#ifdef HAVE_STAT64
-WRAPPER2(int , stat64, const char *path, struct stat64 *buf)
-{
- size_t n;
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- n = strlen (path);
- MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "stat64 path");
- MF_VALIDATE_EXTENT (buf, sizeof (*buf), __MF_CHECK_READ, "stat64 buf");
- return stat64 (path, buf);
-}
-#endif
-
-
-WRAPPER2(int , fstat, int filedes, struct stat *buf)
-{
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT (buf, sizeof (*buf), __MF_CHECK_READ, "fstat buf");
- return fstat (filedes, buf);
-}
-
-
-WRAPPER2(int , lstat, const char *path, struct stat *buf)
-{
- size_t n;
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- n = strlen (path);
- MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "lstat path");
- MF_VALIDATE_EXTENT (buf, sizeof (*buf), __MF_CHECK_READ, "lstat buf");
- return lstat (path, buf);
-}
-
-
-WRAPPER2(int , mkfifo, const char *path, mode_t mode)
-{
- size_t n;
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- n = strlen (path);
- MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "mkfifo path");
- return mkfifo (path, mode);
-}
-
-
-#ifdef HAVE_DIRENT_H
-WRAPPER2(DIR *, opendir, const char *path)
-{
- DIR *p;
- size_t n;
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- n = strlen (path);
- MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "opendir path");
-
- p = opendir (path);
- if (NULL != p) {
-#ifdef MF_REGISTER_opendir
- __mf_register (p, MF_RESULT_SIZE_opendir, MF_REGISTER_opendir,
- "opendir result");
-#endif
- MF_VALIDATE_EXTENT (p, MF_RESULT_SIZE_opendir, __MF_CHECK_WRITE,
- "opendir result");
- }
- return p;
-}
-
-
-WRAPPER2(int, closedir, DIR *dir)
-{
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT (dir, 0, __MF_CHECK_WRITE, "closedir dir");
-#ifdef MF_REGISTER_opendir
- __mf_unregister (dir, MF_RESULT_SIZE_opendir, MF_REGISTER_opendir);
-#endif
- return closedir (dir);
-}
-
-
-WRAPPER2(struct dirent *, readdir, DIR *dir)
-{
- struct dirent *p;
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT (dir, 0, __MF_CHECK_READ, "readdir dir");
- p = readdir (dir);
- if (NULL != p) {
-#ifdef MF_REGISTER_readdir
- __mf_register (p, sizeof (*p), MF_REGISTER_readdir, "readdir result");
-#endif
- MF_VALIDATE_EXTENT (p, sizeof (*p), __MF_CHECK_WRITE, "readdir result");
- }
- return p;
-}
-#endif
-
-
-#ifdef HAVE_SYS_SOCKET_H
-
-WRAPPER2(int, recv, int s, void *buf, size_t len, int flags)
-{
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT (buf, len, __MF_CHECK_WRITE, "recv buf");
- return recv (s, buf, len, flags);
-}
-
-
-WRAPPER2(int, recvfrom, int s, void *buf, size_t len, int flags,
- struct sockaddr *from, socklen_t *fromlen)
-{
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT (buf, len, __MF_CHECK_WRITE, "recvfrom buf");
- MF_VALIDATE_EXTENT (from, (size_t)*fromlen, __MF_CHECK_WRITE,
- "recvfrom from");
- return recvfrom (s, buf, len, flags, from, fromlen);
-}
-
-
-WRAPPER2(int, recvmsg, int s, struct msghdr *msg, int flags)
-{
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT (msg, sizeof (*msg), __MF_CHECK_WRITE, "recvmsg msg");
- return recvmsg (s, msg, flags);
-}
-
-
-WRAPPER2(int, send, int s, const void *msg, size_t len, int flags)
-{
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT (msg, len, __MF_CHECK_READ, "send msg");
- return send (s, msg, len, flags);
-}
-
-
-WRAPPER2(int, sendto, int s, const void *msg, size_t len, int flags,
- const struct sockaddr *to, socklen_t tolen)
-{
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT (msg, len, __MF_CHECK_READ, "sendto msg");
- MF_VALIDATE_EXTENT (to, (size_t)tolen, __MF_CHECK_WRITE, "sendto to");
- return sendto (s, msg, len, flags, to, tolen);
-}
-
-
-WRAPPER2(int, sendmsg, int s, const void *msg, int flags)
-{
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT (msg, sizeof (*msg), __MF_CHECK_READ, "sendmsg msg");
- return sendmsg (s, msg, flags);
-}
-
-
-WRAPPER2(int, setsockopt, int s, int level, int optname, const void *optval,
- socklen_t optlen)
-{
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT (optval, (size_t)optlen, __MF_CHECK_READ,
- "setsockopt optval");
- return setsockopt (s, level, optname, optval, optlen);
-}
-
-
-WRAPPER2(int, getsockopt, int s, int level, int optname, void *optval,
- socklen_t *optlen)
-{
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT (optval, (size_t)*optlen, __MF_CHECK_WRITE,
- "getsockopt optval");
- return getsockopt (s, level, optname, optval, optlen);
-}
-
-
-WRAPPER2(int, accept, int s, struct sockaddr *addr, socklen_t *addrlen)
-{
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- if (addr != NULL)
- MF_VALIDATE_EXTENT (addr, (size_t)*addrlen, __MF_CHECK_WRITE, "accept addr");
- return accept (s, addr, addrlen);
-}
-
-
-WRAPPER2(int, bind, int sockfd, struct sockaddr *addr, socklen_t addrlen)
-{
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT (addr, (size_t)addrlen, __MF_CHECK_WRITE, "bind addr");
- return bind (sockfd, addr, addrlen);
-}
-
-
-WRAPPER2(int, connect, int sockfd, const struct sockaddr *addr,
- socklen_t addrlen)
-{
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT (addr, (size_t)addrlen, __MF_CHECK_READ,
- "connect addr");
- return connect (sockfd, addr, addrlen);
-}
-
-#endif /* HAVE_SYS_SOCKET_H */
-
-
-WRAPPER2(int, gethostname, char *name, size_t len)
-{
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT (name, len, __MF_CHECK_WRITE, "gethostname name");
- return gethostname (name, len);
-}
-
-
-#ifdef HAVE_SETHOSTNAME
-WRAPPER2(int, sethostname, const char *name, size_t len)
-{
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT (name, len, __MF_CHECK_READ, "sethostname name");
- return sethostname (name, len);
-}
-#endif
-
-
-#ifdef HAVE_NETDB_H
-
-WRAPPER2(struct hostent *, gethostbyname, const char *name)
-{
- struct hostent *p;
- char **ss;
- char *s;
- size_t n;
- int nreg;
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- n = strlen (name);
- MF_VALIDATE_EXTENT (name, CLAMPADD(n, 1), __MF_CHECK_READ,
- "gethostbyname name");
- p = gethostbyname (name);
- if (NULL != p) {
-#ifdef MF_REGISTER_gethostbyname
- __mf_register (p, sizeof (*p), MF_REGISTER_gethostbyname,
- "gethostbyname result");
-#endif
- MF_VALIDATE_EXTENT (p, sizeof (*p), __MF_CHECK_WRITE,
- "gethostbyname result");
- if (NULL != (s = p->h_name)) {
- n = strlen (s);
- n = CLAMPADD(n, 1);
-#ifdef MF_REGISTER_gethostbyname_items
- __mf_register (s, n, MF_REGISTER_gethostbyname_items,
- "gethostbyname result->h_name");
-#endif
- MF_VALIDATE_EXTENT (s, n, __MF_CHECK_WRITE,
- "gethostbyname result->h_name");
- }
-
- if (NULL != (ss = p->h_aliases)) {
- for (nreg = 1;; ++nreg) {
- s = *ss++;
- if (NULL == s)
- break;
- n = strlen (s);
- n = CLAMPADD(n, 1);
-#ifdef MF_REGISTER_gethostbyname_items
- __mf_register (s, n, MF_REGISTER_gethostbyname_items,
- "gethostbyname result->h_aliases[]");
-#endif
- MF_VALIDATE_EXTENT (s, n, __MF_CHECK_WRITE,
- "gethostbyname result->h_aliases[]");
- }
- nreg *= sizeof (*p->h_aliases);
-#ifdef MF_REGISTER_gethostbyname_items
- __mf_register (p->h_aliases, nreg, MF_REGISTER_gethostbyname_items,
- "gethostbyname result->h_aliases");
-#endif
- MF_VALIDATE_EXTENT (p->h_aliases, nreg, __MF_CHECK_WRITE,
- "gethostbyname result->h_aliases");
- }
-
- if (NULL != (ss = p->h_addr_list)) {
- for (nreg = 1;; ++nreg) {
- s = *ss++;
- if (NULL == s)
- break;
-#ifdef MF_REGISTER_gethostbyname_items
- __mf_register (s, p->h_length, MF_REGISTER_gethostbyname_items,
- "gethostbyname result->h_addr_list[]");
-#endif
- MF_VALIDATE_EXTENT (s, p->h_length, __MF_CHECK_WRITE,
- "gethostbyname result->h_addr_list[]");
- }
- nreg *= sizeof (*p->h_addr_list);
-#ifdef MF_REGISTER_gethostbyname_items
- __mf_register (p->h_addr_list, nreg, MF_REGISTER_gethostbyname_items,
- "gethostbyname result->h_addr_list");
-#endif
- MF_VALIDATE_EXTENT (p->h_addr_list, nreg, __MF_CHECK_WRITE,
- "gethostbyname result->h_addr_list");
- }
- }
- return p;
-}
-
-#endif /* HAVE_NETDB_H */
-
-
-#ifdef HAVE_SYS_WAIT_H
-
-WRAPPER2(pid_t, wait, int *status)
-{
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- if (NULL != status)
- MF_VALIDATE_EXTENT (status, sizeof (*status), __MF_CHECK_WRITE,
- "wait status");
- return wait (status);
-}
-
-
-WRAPPER2(pid_t, waitpid, pid_t pid, int *status, int options)
-{
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- if (NULL != status)
- MF_VALIDATE_EXTENT (status, sizeof (*status), __MF_CHECK_WRITE,
- "waitpid status");
- return waitpid (pid, status, options);
-}
-
-#endif /* HAVE_SYS_WAIT_H */
-
-
-WRAPPER2(FILE *, popen, const char *command, const char *mode)
-{
- size_t n;
- FILE *p;
- TRACE ("%s\n", __PRETTY_FUNCTION__);
-
- n = strlen (command);
- MF_VALIDATE_EXTENT (command, CLAMPADD(n, 1), __MF_CHECK_READ, "popen path");
-
- n = strlen (mode);
- MF_VALIDATE_EXTENT (mode, CLAMPADD(n, 1), __MF_CHECK_READ, "popen mode");
-
- p = popen (command, mode);
- if (NULL != p) {
-#ifdef MF_REGISTER_fopen
- __mf_register (p, sizeof (*p), MF_REGISTER_fopen, "popen result");
-#endif
- MF_VALIDATE_EXTENT (p, sizeof (*p), __MF_CHECK_WRITE, "popen result");
- }
- return p;
-}
-
-
-WRAPPER2(int, pclose, FILE *stream)
-{
- int resp;
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT (stream, sizeof (*stream), __MF_CHECK_WRITE,
- "pclose stream");
- resp = pclose (stream);
-#ifdef MF_REGISTER_fopen
- __mf_unregister (stream, sizeof (*stream), MF_REGISTER_fopen);
-#endif
- return resp;
-}
-
-
-WRAPPER2(int, execve, const char *path, char *const argv [],
- char *const envp[])
-{
- size_t n;
- char *const *p;
- const char *s;
- TRACE ("%s\n", __PRETTY_FUNCTION__);
-
- n = strlen (path);
- MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "execve path");
-
- for (p = argv;;) {
- MF_VALIDATE_EXTENT (p, sizeof (*p), __MF_CHECK_READ, "execve *argv");
- s = *p++;
- if (NULL == s)
- break;
- n = strlen (s);
- MF_VALIDATE_EXTENT (s, CLAMPADD(n, 1), __MF_CHECK_READ, "execve **argv");
- }
-
- for (p = envp;;) {
- MF_VALIDATE_EXTENT (p, sizeof (*p), __MF_CHECK_READ, "execve *envp");
- s = *p++;
- if (NULL == s)
- break;
- n = strlen (s);
- MF_VALIDATE_EXTENT (s, CLAMPADD(n, 1), __MF_CHECK_READ, "execve **envp");
- }
- return execve (path, argv, envp);
-}
-
-
-WRAPPER2(int, execv, const char *path, char *const argv [])
-{
- size_t n;
- char *const *p;
- const char *s;
- TRACE ("%s\n", __PRETTY_FUNCTION__);
-
- n = strlen (path);
- MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "execv path");
-
- for (p = argv;;) {
- MF_VALIDATE_EXTENT (p, sizeof (*p), __MF_CHECK_READ, "execv *argv");
- s = *p++;
- if (NULL == s)
- break;
- n = strlen (s);
- MF_VALIDATE_EXTENT (s, CLAMPADD(n, 1), __MF_CHECK_READ, "execv **argv");
- }
- return execv (path, argv);
-}
-
-
-WRAPPER2(int, execvp, const char *path, char *const argv [])
-{
- size_t n;
- char *const *p;
- const char *s;
- TRACE ("%s\n", __PRETTY_FUNCTION__);
-
- n = strlen (path);
- MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "execvp path");
-
- for (p = argv;;) {
- MF_VALIDATE_EXTENT (p, sizeof (*p), __MF_CHECK_READ, "execvp *argv");
- s = *p++;
- if (NULL == s)
- break;
- n = strlen (s);
- MF_VALIDATE_EXTENT (s, CLAMPADD(n, 1), __MF_CHECK_READ, "execvp **argv");
- }
- return execvp (path, argv);
-}
-
-
-WRAPPER2(int, system, const char *string)
-{
- size_t n;
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- n = strlen (string);
- MF_VALIDATE_EXTENT (string, CLAMPADD(n, 1), __MF_CHECK_READ,
- "system string");
- return system (string);
-}
-
-
-WRAPPER2(void *, dlopen, const char *path, int flags)
-{
- void *p;
- size_t n;
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- n = strlen (path);
- MF_VALIDATE_EXTENT (path, CLAMPADD(n, 1), __MF_CHECK_READ, "dlopen path");
- p = dlopen (path, flags);
- if (NULL != p) {
-#ifdef MF_REGISTER_dlopen
- __mf_register (p, 0, MF_REGISTER_dlopen, "dlopen result");
-#endif
- MF_VALIDATE_EXTENT (p, 0, __MF_CHECK_WRITE, "dlopen result");
- }
- return p;
-}
-
-
-WRAPPER2(int, dlclose, void *handle)
-{
- int resp;
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT (handle, 0, __MF_CHECK_READ, "dlclose handle");
- resp = dlclose (handle);
-#ifdef MF_REGISTER_dlopen
- __mf_unregister (handle, 0, MF_REGISTER_dlopen);
-#endif
- return resp;
-}
-
-
-WRAPPER2(char *, dlerror)
-{
- char *p;
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- p = dlerror ();
- if (NULL != p) {
- size_t n;
- n = strlen (p);
- n = CLAMPADD(n, 1);
-#ifdef MF_REGISTER_dlerror
- __mf_register (p, n, MF_REGISTER_dlerror, "dlerror result");
-#endif
- MF_VALIDATE_EXTENT (p, n, __MF_CHECK_WRITE, "dlerror result");
- }
- return p;
-}
-
-
-WRAPPER2(void *, dlsym, void *handle, char *symbol)
-{
- size_t n;
- void *p;
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT (handle, 0, __MF_CHECK_READ, "dlsym handle");
- n = strlen (symbol);
- MF_VALIDATE_EXTENT (symbol, CLAMPADD(n, 1), __MF_CHECK_READ, "dlsym symbol");
- p = dlsym (handle, symbol);
- if (NULL != p) {
-#ifdef MF_REGISTER_dlsym
- __mf_register (p, 0, MF_REGISTER_dlsym, "dlsym result");
-#endif
- MF_VALIDATE_EXTENT (p, 0, __MF_CHECK_WRITE, "dlsym result");
- }
- return p;
-}
-
-
-#if defined (HAVE_SYS_IPC_H) && defined (HAVE_SYS_SEM_H) && defined (HAVE_SYS_SHM_H)
-
-WRAPPER2(int, semop, int semid, struct sembuf *sops, unsigned nsops)
-{
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- MF_VALIDATE_EXTENT (sops, sizeof (*sops) * nsops, __MF_CHECK_READ,
- "semop sops");
- return semop (semid, sops, nsops);
-}
-
-
-#ifndef HAVE_UNION_SEMUN
-union semun {
- int val; /* value for SETVAL */
- struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */
- unsigned short int *array; /* array for GETALL, SETALL */
- struct seminfo *__buf; /* buffer for IPC_INFO */
-};
-#endif
-WRAPPER2(int, semctl, int semid, int semnum, int cmd, union semun arg)
-{
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- switch (cmd) {
- case IPC_STAT:
- MF_VALIDATE_EXTENT (arg.buf, sizeof (*arg.buf), __MF_CHECK_WRITE,
- "semctl buf");
- break;
- case IPC_SET:
- MF_VALIDATE_EXTENT (arg.buf, sizeof (*arg.buf), __MF_CHECK_READ,
- "semctl buf");
- break;
- case GETALL:
- MF_VALIDATE_EXTENT (arg.array, sizeof (*arg.array), __MF_CHECK_WRITE,
- "semctl array");
- case SETALL:
- MF_VALIDATE_EXTENT (arg.array, sizeof (*arg.array), __MF_CHECK_READ,
- "semctl array");
- break;
-#ifdef IPC_INFO
- /* FreeBSD 5.1 And Cygwin headers include IPC_INFO but not the __buf field. */
-#if !defined(__FreeBSD__) && !defined(__CYGWIN__)
- case IPC_INFO:
- MF_VALIDATE_EXTENT (arg.__buf, sizeof (*arg.__buf), __MF_CHECK_WRITE,
- "semctl __buf");
- break;
-#endif
-#endif
- default:
- break;
- }
- return semctl (semid, semnum, cmd, arg);
-}
-
-
-WRAPPER2(int, shmctl, int shmid, int cmd, struct shmid_ds *buf)
-{
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- switch (cmd) {
- case IPC_STAT:
- MF_VALIDATE_EXTENT (buf, sizeof (*buf), __MF_CHECK_WRITE,
- "shmctl buf");
- break;
- case IPC_SET:
- MF_VALIDATE_EXTENT (buf, sizeof (*buf), __MF_CHECK_READ,
- "shmctl buf");
- break;
- default:
- break;
- }
- return shmctl (shmid, cmd, buf);
-}
-
-
-WRAPPER2(void *, shmat, int shmid, const void *shmaddr, int shmflg)
-{
- void *p;
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- p = shmat (shmid, shmaddr, shmflg);
-#ifdef MF_REGISTER_shmat
- if (NULL != p) {
- struct shmid_ds buf;
- __mf_register (p, shmctl (shmid, IPC_STAT, &buf) ? 0 : buf.shm_segsz,
- MF_REGISTER_shmat, "shmat result");
- }
-#endif
- return p;
-}
-
-
-WRAPPER2(int, shmdt, const void *shmaddr)
-{
- int resp;
- TRACE ("%s\n", __PRETTY_FUNCTION__);
- resp = shmdt (shmaddr);
-#ifdef MF_REGISTER_shmat
- __mf_unregister ((void *)shmaddr, 0, MF_REGISTER_shmat);
-#endif
- return resp;
-}
-
-
-#endif /* HAVE_SYS_IPC/SEM/SHM_H */
-
-
-
-/* ctype stuff. This is host-specific by necessity, as the arrays
- that is used by most is*()/to*() macros are implementation-defined. */
-
-/* GLIBC 2.3 */
-#ifdef HAVE___CTYPE_B_LOC
-WRAPPER2(unsigned short **, __ctype_b_loc, void)
-{
- static unsigned short * last_buf = (void *) 0;
- static unsigned short ** last_ptr = (void *) 0;
- unsigned short ** ptr = (unsigned short **) __ctype_b_loc ();
- unsigned short * buf = * ptr;
- if (ptr != last_ptr)
- {
- /* XXX: unregister last_ptr? */
- last_ptr = ptr;
- __mf_register (last_ptr, sizeof(last_ptr), __MF_TYPE_STATIC, "ctype_b_loc **");
- }
- if (buf != last_buf)
- {
- last_buf = buf;
- __mf_register ((void *) (last_buf - 128), 384 * sizeof(unsigned short), __MF_TYPE_STATIC,
- "ctype_b_loc []");
- }
- return ptr;
-}
-#endif
-
-#ifdef HAVE___CTYPE_TOUPPER_LOC
-WRAPPER2(int **, __ctype_toupper_loc, void)
-{
- static int * last_buf = (void *) 0;
- static int ** last_ptr = (void *) 0;
- int ** ptr = (int **) __ctype_toupper_loc ();
- int * buf = * ptr;
- if (ptr != last_ptr)
- {
- /* XXX: unregister last_ptr? */
- last_ptr = ptr;
- __mf_register (last_ptr, sizeof(last_ptr), __MF_TYPE_STATIC, "ctype_toupper_loc **");
- }
- if (buf != last_buf)
- {
- last_buf = buf;
- __mf_register ((void *) (last_buf - 128), 384 * sizeof(int), __MF_TYPE_STATIC,
- "ctype_toupper_loc []");
- }
- return ptr;
-}
-#endif
-
-#ifdef HAVE___CTYPE_TOLOWER_LOC
-WRAPPER2(int **, __ctype_tolower_loc, void)
-{
- static int * last_buf = (void *) 0;
- static int ** last_ptr = (void *) 0;
- int ** ptr = (int **) __ctype_tolower_loc ();
- int * buf = * ptr;
- if (ptr != last_ptr)
- {
- /* XXX: unregister last_ptr? */
- last_ptr = ptr;
- __mf_register (last_ptr, sizeof(last_ptr), __MF_TYPE_STATIC, "ctype_tolower_loc **");
- }
- if (buf != last_buf)
- {
- last_buf = buf;
- __mf_register ((void *) (last_buf - 128), 384 * sizeof(int), __MF_TYPE_STATIC,
- "ctype_tolower_loc []");
- }
- return ptr;
-}
-#endif
-
-
-/* passwd/group related functions. These register every (static) pointer value returned,
- and rely on libmudflap's quiet toleration of duplicate static registrations. */
-
-#ifdef HAVE_GETLOGIN
-WRAPPER2(char *, getlogin, void)
-{
- char *buf = getlogin ();
- if (buf != NULL)
- __mf_register (buf, sizeof(*buf), __MF_TYPE_STATIC,
- "getlogin() return");
- return buf;
-}
-#endif
-
-
-#ifdef HAVE_CUSERID
-WRAPPER2(char *, cuserid, char * buf)
-{
- if (buf != NULL)
- {
- MF_VALIDATE_EXTENT(buf, L_cuserid, __MF_CHECK_WRITE,
- "cuserid destination");
- return cuserid (buf);
- }
- buf = cuserid (NULL);
- if (buf != NULL)
- __mf_register (buf, sizeof(*buf), __MF_TYPE_STATIC,
- "getcuserid() return");
- return buf;
-}
-#endif
-
-
-#ifdef HAVE_GETPWNAM
-WRAPPER2(struct passwd *, getpwnam, const char *name)
-{
- struct passwd *buf;
- MF_VALIDATE_EXTENT(name, strlen(name)+1, __MF_CHECK_READ,
- "getpwnam name");
- buf = getpwnam (name);
- if (buf != NULL)
- __mf_register (buf, sizeof(*buf), __MF_TYPE_STATIC,
- "getpw*() return");
- return buf;
-}
-#endif
-
-
-#ifdef HAVE_GETPWUID
-WRAPPER2(struct passwd *, getpwuid, uid_t uid)
-{
- struct passwd *buf;
- buf = getpwuid (uid);
- if (buf != NULL)
- __mf_register (buf, sizeof(*buf), __MF_TYPE_STATIC,
- "getpw*() return");
- return buf;
-}
-#endif
-
-
-#ifdef HAVE_GETGRNAM
-WRAPPER2(struct group *, getgrnam, const char *name)
-{
- struct group *buf;
- MF_VALIDATE_EXTENT(name, strlen(name)+1, __MF_CHECK_READ,
- "getgrnam name");
- buf = getgrnam (name);
- if (buf != NULL)
- __mf_register (buf, sizeof(*buf), __MF_TYPE_STATIC,
- "getgr*() return");
- return buf;
-}
-#endif
-
-
-#ifdef HAVE_GETGRGID
-WRAPPER2(struct group *, getgrgid, uid_t uid)
-{
- struct group *buf;
- buf = getgrgid (uid);
- if (buf != NULL)
- __mf_register (buf, sizeof(*buf), __MF_TYPE_STATIC,
- "getgr*() return");
- return buf;
-}
-#endif
-
-
-#ifdef HAVE_GETSERVENT
-WRAPPER2(struct servent *, getservent, void)
-{
- struct servent *buf;
- buf = getservent ();
- if (buf != NULL)
- __mf_register (buf, sizeof(*buf), __MF_TYPE_STATIC,
- "getserv*() return");
- return buf;
-}
-#endif
-
-
-#ifdef HAVE_GETSERVBYNAME
-WRAPPER2(struct servent *, getservbyname, const char *name, const char *proto)
-{
- struct servent *buf;
- MF_VALIDATE_EXTENT(name, strlen(name)+1, __MF_CHECK_READ,
- "getservbyname name");
- MF_VALIDATE_EXTENT(proto, strlen(proto)+1, __MF_CHECK_READ,
- "getservbyname proto");
- buf = getservbyname (name, proto);
- if (buf != NULL)
- __mf_register (buf, sizeof(*buf), __MF_TYPE_STATIC,
- "getserv*() return");
- return buf;
-}
-#endif
-
-
-#ifdef HAVE_GETSERVBYPORT
-WRAPPER2(struct servent *, getservbyport, int port, const char *proto)
-{
- struct servent *buf;
- MF_VALIDATE_EXTENT(proto, strlen(proto)+1, __MF_CHECK_READ,
- "getservbyport proto");
- buf = getservbyport (port, proto);
- if (buf != NULL)
- __mf_register (buf, sizeof(*buf), __MF_TYPE_STATIC,
- "getserv*() return");
- return buf;
-}
-#endif
-
-
-#ifdef HAVE_GAI_STRERROR
-WRAPPER2(const char *, gai_strerror, int errcode)
-{
- const char *buf;
- buf = gai_strerror (errcode);
- if (buf != NULL)
- __mf_register ((void *) buf, strlen(buf)+1, __MF_TYPE_STATIC,
- "gai_strerror() return");
- return buf;
-}
-#endif
-
-
-#ifdef HAVE_GETMNTENT
-#ifdef HAVE_MNTENT_H
-WRAPPER2(struct mntent *, getmntent, FILE *filep)
-{
- struct mntent *m;
- static struct mntent *last = NULL;
-
- MF_VALIDATE_EXTENT (filep, sizeof (*filep), __MF_CHECK_WRITE,
- "getmntent stream");
-#define UR(field) __mf_unregister(last->field, strlen (last->field)+1, __MF_TYPE_STATIC)
- if (last)
- {
- UR (mnt_fsname);
- UR (mnt_dir);
- UR (mnt_type);
- UR (mnt_opts);
- __mf_unregister (last, sizeof (*last), __MF_TYPE_STATIC);
- }
-#undef UR
-
- m = getmntent (filep);
- last = m;
-
-#define R(field) __mf_register(last->field, strlen (last->field)+1, __MF_TYPE_STATIC, "mntent " #field)
- if (m)
- {
- R (mnt_fsname);
- R (mnt_dir);
- R (mnt_type);
- R (mnt_opts);
- __mf_register (last, sizeof (*last), __MF_TYPE_STATIC, "getmntent result");
- }
-#undef R
-
- return m;
-}
-#elif defined HAVE_SYS_MNTTAB_H
-WRAPPER2(int, getmntent, FILE *filep, struct mnttab *mp)
-{
- static struct mnttab *last = NULL;
- int res;
-
- MF_VALIDATE_EXTENT (filep, sizeof (*filep), __MF_CHECK_WRITE,
- "getmntent stream");
-#define UR(field) __mf_unregister(last->field, strlen (last->field)+1, __MF_TYPE_STATIC)
- if (last)
- {
- UR (mnt_special);
- UR (mnt_mountp);
- UR (mnt_fstype);
- UR (mnt_mntopts);
- UR (mnt_time);
- __mf_unregister (last, sizeof (*last), __MF_TYPE_STATIC);
- }
-#undef UR
-
- res = getmntent (filep, mp);
- last = mp;
-
-#define R(field) __mf_register(last->field, strlen (last->field)+1, __MF_TYPE_STATIC, "mntent " #field)
- if (mp)
- {
- R (mnt_special);
- R (mnt_mountp);
- R (mnt_fstype);
- R (mnt_mntopts);
- R (mnt_time);
- __mf_register (last, sizeof (*last), __MF_TYPE_STATIC, "getmntent result");
- }
-#undef R
-
- return res;
-}
-#endif
-#endif
-
-
-#ifdef HAVE_INET_NTOA
-WRAPPER2(char *, inet_ntoa, struct in_addr in)
-{
- static char *last_buf = NULL;
- char *buf;
- if (last_buf)
- __mf_unregister (last_buf, strlen (last_buf)+1, __MF_TYPE_STATIC);
- buf = inet_ntoa (in);
- last_buf = buf;
- if (buf)
- __mf_register (last_buf, strlen (last_buf)+1, __MF_TYPE_STATIC, "inet_ntoa result");
- return buf;
-}
-#endif
-
-
-#ifdef HAVE_GETPROTOENT
-WRAPPER2(struct protoent *, getprotoent, void)
-{
- struct protoent *buf;
- buf = getprotoent ();
- if (buf != NULL)
- __mf_register (buf, sizeof(*buf), __MF_TYPE_STATIC, "getproto*() return");
- return buf;
-}
-#endif
-
-
-#ifdef HAVE_GETPROTOBYNAME
-WRAPPER2(struct protoent *, getprotobyname, const char *name)
-{
- struct protoent *buf;
- MF_VALIDATE_EXTENT(name, strlen(name)+1, __MF_CHECK_READ,
- "getprotobyname name");
- buf = getprotobyname (name);
- if (buf != NULL)
- __mf_register (buf, sizeof(*buf), __MF_TYPE_STATIC,
- "getproto*() return");
- return buf;
-}
-#endif
-
-
-#ifdef HAVE_GETPROTOBYNUMBER
-WRAPPER2(struct protoent *, getprotobynumber, int port)
-{
- struct protoent *buf;
- buf = getprotobynumber (port);
- if (buf != NULL)
- __mf_register (buf, sizeof(*buf), __MF_TYPE_STATIC,
- "getproto*() return");
- return buf;
-}
-#endif
diff --git a/libmudflap/mf-hooks3.c b/libmudflap/mf-hooks3.c
deleted file mode 100644
index 552cbb598d8..00000000000
--- a/libmudflap/mf-hooks3.c
+++ /dev/null
@@ -1,284 +0,0 @@
-/* Mudflap: narrow-pointer bounds-checking by tree rewriting.
- Copyright (C) 2002-2013 Free Software Foundation, Inc.
- Contributed by Frank Ch. Eigler <fche@redhat.com>
- and Graydon Hoare <graydon@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.
-
-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/>. */
-
-
-#include "config.h"
-
-#ifndef HAVE_SOCKLEN_T
-#define socklen_t int
-#endif
-
-/* These attempt to coax various unix flavours to declare all our
- needed tidbits in the system headers. */
-#if !defined(__FreeBSD__) && !defined(__APPLE__)
-#define _POSIX_SOURCE
-#endif /* Some BSDs break <sys/socket.h> if this is defined. */
-#define _GNU_SOURCE
-#define _XOPEN_SOURCE
-#define _BSD_TYPES
-#define __EXTENSIONS__
-#define _ALL_SOURCE
-#define _LARGE_FILE_API
-#define _XOPEN_SOURCE_EXTENDED 1
-#define _REENTRANT
-
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <assert.h>
-#include <errno.h>
-#include <stdbool.h>
-
-#include "mf-runtime.h"
-#include "mf-impl.h"
-
-#ifdef _MUDFLAP
-#error "Do not compile this file with -fmudflap!"
-#endif
-
-#ifndef LIBMUDFLAPTH
-#error "pthreadstuff is to be included only in libmudflapth"
-#endif
-
-/* ??? Why isn't this done once in the header files. */
-DECLARE(void *, malloc, size_t sz);
-DECLARE(void, free, void *ptr);
-DECLARE(int, pthread_create, pthread_t *thr, const pthread_attr_t *attr,
- void * (*start) (void *), void *arg);
-
-
-/* Multithreading support hooks. */
-
-
-#if !defined(HAVE_TLS) || defined(USE_EMUTLS)
-/* We don't have TLS. Ordinarily we could use pthread keys, but since we're
- commandeering malloc/free that presents a few problems. The first is that
- we'll recurse from __mf_get_state to pthread_setspecific to malloc back to
- __mf_get_state during thread startup. This can be solved with clever uses
- of a mutex. The second problem is that thread shutdown is indistinguishable
- from thread startup, since libpthread is deallocating our state variable.
- I've no good solution for this.
-
- Which leaves us to handle this mess by totally by hand. */
-
-/* Yes, we want this prime. If pthread_t is a pointer, it's almost always
- page aligned, and if we use a smaller power of 2, this results in "%N"
- being the worst possible hash -- all threads hash to zero. */
-#define LIBMUDFLAPTH_THREADS_MAX 1021
-
-struct mf_thread_data
-{
- pthread_t self;
- unsigned char used_p;
- unsigned char state;
-};
-
-static struct mf_thread_data mf_thread_data[LIBMUDFLAPTH_THREADS_MAX];
-static pthread_mutex_t mf_thread_data_lock = PTHREAD_MUTEX_INITIALIZER;
-
-#define PTHREAD_HASH(p) ((unsigned long) (p) % LIBMUDFLAPTH_THREADS_MAX)
-
-static struct mf_thread_data *
-__mf_find_threadinfo (int alloc)
-{
- pthread_t self = pthread_self ();
- unsigned long hash = PTHREAD_HASH (self);
- unsigned long rehash;
-
-#ifdef __alpha__
- /* Alpha has the loosest memory ordering rules of all. We need a memory
- barrier to flush the reorder buffer before considering a *read* of a
- shared variable. Since we're not always taking a lock, we have to do
- this by hand. */
- __sync_synchronize ();
-#endif
-
- rehash = hash;
- while (1)
- {
- if (mf_thread_data[rehash].used_p && mf_thread_data[rehash].self == self)
- return &mf_thread_data[rehash];
-
- rehash += 7;
- if (rehash >= LIBMUDFLAPTH_THREADS_MAX)
- rehash -= LIBMUDFLAPTH_THREADS_MAX;
- if (rehash == hash)
- break;
- }
-
- if (alloc)
- {
- pthread_mutex_lock (&mf_thread_data_lock);
-
- rehash = hash;
- while (1)
- {
- if (!mf_thread_data[rehash].used_p)
- {
- mf_thread_data[rehash].self = self;
- __sync_synchronize ();
- mf_thread_data[rehash].used_p = 1;
-
- pthread_mutex_unlock (&mf_thread_data_lock);
- return &mf_thread_data[rehash];
- }
-
- rehash += 7;
- if (rehash >= LIBMUDFLAPTH_THREADS_MAX)
- rehash -= LIBMUDFLAPTH_THREADS_MAX;
- if (rehash == hash)
- break;
- }
-
- pthread_mutex_unlock (&mf_thread_data_lock);
- }
-
- return NULL;
-}
-
-enum __mf_state_enum
-__mf_get_state (void)
-{
- struct mf_thread_data *data = __mf_find_threadinfo (0);
- if (data)
- return data->state;
-
- /* If we've never seen this thread before, consider it to be in the
- reentrant state. The state gets reset to active for the main thread
- in __mf_init, and for child threads in __mf_pthread_spawner.
-
- The trickiest bit here is that the LinuxThreads pthread_manager thread
- should *always* be considered to be reentrant, so that none of our
- hooks actually do anything. Why? Because that thread isn't a real
- thread from the point of view of the thread library, and so lots of
- stuff isn't initialized, leading to SEGV very quickly. Even calling
- pthread_self is a bit suspect, but it happens to work. */
-
- return reentrant;
-}
-
-void
-__mf_set_state (enum __mf_state_enum new_state)
-{
- struct mf_thread_data *data = __mf_find_threadinfo (1);
- data->state = new_state;
-}
-#endif
-
-/* The following two functions are used only with __mf_opts.heur_std_data.
- We're interested in recording the location of the thread-local errno
- variable.
-
- Note that this doesn't handle TLS references in general; we have no
- visibility into __tls_get_data for when that memory is allocated at
- runtime. Hopefully we get to see the malloc or mmap operation that
- eventually allocates the backing store. */
-
-/* Describe the startup information for a new user thread. */
-struct mf_thread_start_info
-{
- /* The user's thread entry point and argument. */
- void * (*user_fn)(void *);
- void *user_arg;
-};
-
-
-static void
-__mf_pthread_cleanup (void *arg)
-{
- if (__mf_opts.heur_std_data)
- __mf_unregister (&errno, sizeof (errno), __MF_TYPE_GUESS);
-
-#if !defined(HAVE_TLS) || defined(USE_EMUTLS)
- struct mf_thread_data *data = __mf_find_threadinfo (0);
- if (data)
- data->used_p = 0;
-#endif
-}
-
-
-static void *
-__mf_pthread_spawner (void *arg)
-{
- void *result = NULL;
-
- __mf_set_state (active);
-
- /* NB: We could use __MF_TYPE_STATIC here, but we guess that the thread
- errno is coming out of some dynamically allocated pool that we already
- know of as __MF_TYPE_HEAP. */
- if (__mf_opts.heur_std_data)
- __mf_register (&errno, sizeof (errno), __MF_TYPE_GUESS,
- "errno area (thread)");
-
- /* We considered using pthread_key_t objects instead of these
- cleanup stacks, but they were less cooperative with the
- interposed malloc hooks in libmudflap. */
- /* ??? The pthread_key_t problem is solved above... */
- pthread_cleanup_push (__mf_pthread_cleanup, NULL);
-
- /* Extract given entry point and argument. */
- struct mf_thread_start_info *psi = arg;
- void * (*user_fn)(void *) = psi->user_fn;
- void *user_arg = psi->user_arg;
- CALL_REAL (free, arg);
-
- result = (*user_fn)(user_arg);
-
- pthread_cleanup_pop (1 /* execute */);
-
- return result;
-}
-
-
-#if PIC
-/* A special bootstrap variant. */
-int
-__mf_0fn_pthread_create (pthread_t *thr, const pthread_attr_t *attr,
- void * (*start) (void *), void *arg)
-{
- return -1;
-}
-#endif
-
-
-#undef pthread_create
-WRAPPER(int, pthread_create, pthread_t *thr, const pthread_attr_t *attr,
- void * (*start) (void *), void *arg)
-{
- struct mf_thread_start_info *si;
-
- TRACE ("pthread_create\n");
-
- /* Fill in startup-control fields. */
- si = CALL_REAL (malloc, sizeof (*si));
- si->user_fn = start;
- si->user_arg = arg;
-
- /* Actually create the thread. */
- return CALL_REAL (pthread_create, thr, attr, __mf_pthread_spawner, si);
-}
diff --git a/libmudflap/mf-impl.h b/libmudflap/mf-impl.h
deleted file mode 100644
index 107ed40f664..00000000000
--- a/libmudflap/mf-impl.h
+++ /dev/null
@@ -1,419 +0,0 @@
-/* Implementation header for mudflap runtime library.
- Mudflap: narrow-pointer bounds-checking by tree rewriting.
- Copyright (C) 2002-2013 Free Software Foundation, Inc.
- Contributed by Frank Ch. Eigler <fche@redhat.com>
- and Graydon Hoare <graydon@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.
-
-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 __MF_IMPL_H
-#define __MF_IMPL_H
-
-#ifdef _MUDFLAP
-#error "Do not compile this file with -fmudflap!"
-#endif
-
-#if HAVE_PTHREAD_H
-#include <pthread.h>
-#elif LIBMUDFLAPTH
-#error "Cannot build libmudflapth without pthread.h."
-#endif
-
-#if HAVE_STDINT_H
-#include <stdint.h>
-#else
-typedef __mf_uintptr_t uintptr_t;
-#endif
-
-/* Private definitions related to mf-runtime.h */
-
-#define __MF_TYPE_MAX_CEM __MF_TYPE_STACK /* largest type# for the cemetery */
-#define __MF_TYPE_MAX __MF_TYPE_GUESS
-
-
-#ifndef max
-#define max(a,b) ((a) > (b) ? (a) : (b))
-#endif
-
-#ifndef min
-#define min(a,b) ((a) < (b) ? (a) : (b))
-#endif
-
-/* Address calculation macros. */
-
-#define MINPTR ((uintptr_t) 0)
-#define MAXPTR (~ (uintptr_t) 0)
-
-/* Clamp the addition/subtraction of uintptr_t's to [MINPTR,MAXPTR] */
-#define CLAMPSUB(ptr,offset) (((uintptr_t) ptr) >= (offset) ? ((uintptr_t) ptr)-((uintptr_t) offset) : MINPTR)
-#define CLAMPADD(ptr,offset) (((uintptr_t) ptr) <= MAXPTR-(offset) ? ((uintptr_t) ptr)+((uintptr_t) offset) : MAXPTR)
-#define CLAMPSZ(ptr,size) ((size) ? (((uintptr_t) ptr) <= MAXPTR-(size)+1 ? ((uintptr_t) ptr)+((uintptr_t) size) - 1 : MAXPTR) : ((uintptr_t) ptr))
-
-#define __MF_CACHE_INDEX(ptr) ((((uintptr_t) (ptr)) >> __mf_lc_shift) & __mf_lc_mask)
-#define __MF_CACHE_MISS_P(ptr,sz) ({ \
- struct __mf_cache *elem = & __mf_lookup_cache[__MF_CACHE_INDEX((ptr))]; \
- ((elem->low > (uintptr_t) (ptr)) || \
- (elem->high < (CLAMPADD((uintptr_t) (ptr), (uintptr_t) CLAMPSUB(sz,1) )))); })
-/* XXX: the above should use CLAMPSZ () */
-
-
-
-/* Private functions. */
-
-extern void __mf_violation (void *ptr, size_t sz,
- uintptr_t pc, const char *location,
- int type);
-extern size_t __mf_backtrace (char ***, void *, unsigned);
-extern int __mf_heuristic_check (uintptr_t, uintptr_t);
-
-/* ------------------------------------------------------------------------ */
-/* Type definitions. */
-/* ------------------------------------------------------------------------ */
-
-/* The mf_state type codes describe recursion and initialization order.
-
- reentrant means we are inside a mf-runtime support routine, such as
- __mf_register, and thus there should be no calls to any wrapped functions,
- such as the wrapped malloc. This indicates a bug if it occurs.
- in_malloc means we are inside a real malloc call inside a wrapped malloc
- call, and thus there should be no calls to any wrapped functions like the
- wrapped mmap. This happens on some systems due to how the system libraries
- are constructed. */
-
-enum __mf_state_enum { active, reentrant, in_malloc };
-
-/* The __mf_options structure records optional or tunable aspects of the
- mudflap library's behavior. There is a single global instance of this
- structure which is populated from user input (in an environment variable)
- when the library initializes. */
-
-struct __mf_options
-{
- /* Emit a trace message for each call. */
- unsigned trace_mf_calls;
-
- /* Collect and emit statistics. */
- unsigned collect_stats;
-
- /* Set up a SIGUSR1 -> __mf_report handler. */
- unsigned sigusr1_report;
-
- /* Execute internal checking code. */
- unsigned internal_checking;
-
- /* Age object liveness periodically. */
- unsigned tree_aging;
-
- /* Adapt the lookup cache to working set. */
- unsigned adapt_cache;
-
- /* Print list of leaked heap objects on shutdown. */
- unsigned print_leaks;
-
-#ifdef HAVE___LIBC_FREERES
- /* Call __libc_freeres before leak analysis. */
- unsigned call_libc_freeres;
-#endif
-
- /* Detect reads of uninitialized objects. */
- unsigned check_initialization;
-
- /* Print verbose description of violations. */
- unsigned verbose_violations;
-
- /* Abbreviate duplicate object descriptions. */
- unsigned abbreviate;
-
- /* Emit internal tracing message. */
- unsigned verbose_trace;
-
- /* Wipe stack/heap objects upon unwind. */
- unsigned wipe_stack;
- unsigned wipe_heap;
-
- /* Maintain a queue of this many deferred free()s,
- to trap use of freed memory. */
- unsigned free_queue_length;
-
- /* Maintain a history of this many past unregistered objects. */
- unsigned persistent_count;
-
- /* Pad allocated extents by this many bytes on either side. */
- unsigned crumple_zone;
-
- /* Maintain this many stack frames for contexts. */
- unsigned backtrace;
-
- /* Ignore read operations even if mode_check is in effect. */
- unsigned ignore_reads;
-
- /* Collect register/unregister timestamps. */
- unsigned timestamps;
-
-#ifdef LIBMUDFLAPTH
- /* Thread stack size. */
- unsigned thread_stack;
-#endif
-
- /* Major operation mode */
-#define mode_nop 0 /* Do nothing. */
-#define mode_populate 1 /* Populate tree but do not check for violations. */
-#define mode_check 2 /* Populate and check for violations (normal). */
-#define mode_violate 3 /* Trigger a violation on every call (diagnostic). */
- unsigned mudflap_mode;
-
- /* How to handle a violation. */
-#define viol_nop 0 /* Return control to application. */
-#define viol_segv 1 /* Signal self with segv. */
-#define viol_abort 2 /* Call abort (). */
-#define viol_gdb 3 /* Fork a debugger on self */
- unsigned violation_mode;
-
- /* Violation heuristics selection. */
- unsigned heur_stack_bound; /* allow current stack region */
- unsigned heur_proc_map; /* allow & cache /proc/self/map regions. */
- unsigned heur_start_end; /* allow _start .. _end */
- unsigned heur_std_data; /* allow & cache stdlib data */
-};
-
-
-#ifdef PIC
-
-/* This is a table of dynamically resolved function pointers. */
-
-struct __mf_dynamic_entry
-{
- void *pointer;
- char *name;
- char *version;
-};
-
-/* The definition of the array (mf-runtime.c) must match the enums! */
-extern struct __mf_dynamic_entry __mf_dynamic[];
-enum __mf_dynamic_index
-{
- dyn_calloc, dyn_free, dyn_malloc, dyn_mmap,
-#ifdef HAVE_MMAP64
- dyn_mmap64,
-#endif
- dyn_munmap, dyn_realloc,
- dyn_INITRESOLVE, /* Marker for last init-time resolution. */
-#ifdef LIBMUDFLAPTH
- dyn_pthread_create
-#endif
-};
-
-#endif /* PIC */
-
-/* ------------------------------------------------------------------------ */
-/* Private global variables. */
-/* ------------------------------------------------------------------------ */
-
-#ifdef LIBMUDFLAPTH
-extern pthread_mutex_t __mf_biglock;
-#define LOCKTH() do { extern unsigned long __mf_lock_contention; \
- int rc = pthread_mutex_trylock (& __mf_biglock); \
- if (rc) { __mf_lock_contention ++; \
- rc = pthread_mutex_lock (& __mf_biglock); } \
- assert (rc==0); } while (0)
-#define UNLOCKTH() do { int rc = pthread_mutex_unlock (& __mf_biglock); \
- assert (rc==0); } while (0)
-#else
-#define LOCKTH() do {} while (0)
-#define UNLOCKTH() do {} while (0)
-#endif
-
-#if defined(LIBMUDFLAPTH) && (!defined(HAVE_TLS) || defined(USE_EMUTLS))
-extern enum __mf_state_enum __mf_get_state (void);
-extern void __mf_set_state (enum __mf_state_enum);
-#else
-# ifdef LIBMUDFLAPTH
-extern __thread enum __mf_state_enum __mf_state_1;
-# else
-extern enum __mf_state_enum __mf_state_1;
-# endif
-static inline enum __mf_state_enum __mf_get_state (void)
-{
- return __mf_state_1;
-}
-static inline void __mf_set_state (enum __mf_state_enum s)
-{
- __mf_state_1 = s;
-}
-#endif
-
-extern int __mf_starting_p;
-extern struct __mf_options __mf_opts;
-
-/* ------------------------------------------------------------------------ */
-/* Utility macros. */
-/* ------------------------------------------------------------------------ */
-
-#define UNLIKELY(e) (__builtin_expect (!!(e), 0))
-#define LIKELY(e) (__builtin_expect (!!(e), 1))
-#define STRINGIFY2(e) #e
-#define STRINGIFY(e) STRINGIFY2(e)
-
-#ifdef LIBMUDFLAPTH
-#define VERBOSE_TRACE(...) \
- do { if (UNLIKELY (__mf_opts.verbose_trace)) { \
- fprintf (stderr, "mf(%u): ", (unsigned) pthread_self ()); \
- fprintf (stderr, __VA_ARGS__); \
- } } while (0)
-#define TRACE(...) \
- do { if (UNLIKELY (__mf_opts.trace_mf_calls)) { \
- fprintf (stderr, "mf(%u): ", (unsigned) pthread_self ()); \
- fprintf (stderr, __VA_ARGS__); \
- } } while (0)
-#else
-#define VERBOSE_TRACE(...) \
- do { if (UNLIKELY (__mf_opts.verbose_trace)) { \
- fprintf (stderr, "mf: "); \
- fprintf (stderr, __VA_ARGS__); \
- } } while (0)
-#define TRACE(...) \
- do { if (UNLIKELY (__mf_opts.trace_mf_calls)) { \
- fprintf (stderr, "mf: "); \
- fprintf (stderr, __VA_ARGS__); \
- } } while (0)
-#endif
-
-
-#define __MF_PERSIST_MAX 256
-#define __MF_FREEQ_MAX 256
-
-/*
- Wrapping and redirection:
-
- Mudflap redirects a number of libc functions into itself, for "cheap"
- verification (eg. strcpy, bzero, memcpy) and also to register /
- unregister regions of memory as they are manipulated by the program
- (eg. malloc/free, mmap/munmap).
-
- There are two methods of wrapping.
-
- (1) The static method involves a list of -wrap=foo flags being passed to
- the linker, which then links references to "foo" to the symbol
- "__wrap_foo", and links references to "__real_foo" to the symbol "foo".
- When compiled without -DPIC, libmudflap.a contains such __wrap_foo
- functions which delegate to __real_foo functions in libc to get their
- work done.
-
- (2) The dynamic method involves providing a definition of symbol foo in
- libmudflap.so and linking it earlier in the compiler command line,
- before libc.so. The function "foo" in libmudflap must then call
- dlsym(RTLD_NEXT, "foo") to acquire a pointer to the "real" libc foo, or
- at least the "next" foo in the dynamic link resolution order.
-
- We switch between these two techniques by the presence of the -DPIC
- #define passed in by libtool when building libmudflap.
-*/
-
-
-#ifdef PIC
-
-extern void __mf_resolve_single_dynamic (struct __mf_dynamic_entry *);
-
-#define _GNU_SOURCE
-#include <dlfcn.h>
-
-#define WRAPPER(ret, fname, ...) \
-ret __wrap_ ## fname (__VA_ARGS__) \
- __attribute__ (( alias (#fname) )); \
-ret __real_ ## fname (__VA_ARGS__) \
- __attribute__ (( alias (#fname) )); \
-ret fname (__VA_ARGS__)
-#define DECLARE(ty, fname, ...) \
- typedef ty (*__mf_fn_ ## fname) (__VA_ARGS__); \
- extern ty __mf_0fn_ ## fname (__VA_ARGS__);
-#define CALL_REAL(fname, ...) \
- ({__mf_starting_p \
- ? __mf_0fn_ ## fname (__VA_ARGS__) \
- : (__mf_resolve_single_dynamic (& __mf_dynamic[dyn_ ## fname]), \
- (((__mf_fn_ ## fname)(__mf_dynamic[dyn_ ## fname].pointer)) (__VA_ARGS__)));})
-#define CALL_BACKUP(fname, ...) \
- __mf_0fn_ ## fname(__VA_ARGS__)
-
-#else /* not PIC --> static library */
-
-#define WRAPPER(ret, fname, ...) \
-ret __wrap_ ## fname (__VA_ARGS__)
-#define DECLARE(ty, fname, ...) \
- extern ty __real_ ## fname (__VA_ARGS__)
-#define CALL_REAL(fname, ...) \
- __real_ ## fname (__VA_ARGS__)
-#define CALL_BACKUP(fname, ...) \
- __real_ ## fname(__VA_ARGS__)
-
-#endif /* PIC */
-
-/* WRAPPER2 is for functions intercepted via macros at compile time. */
-#define WRAPPER2(ret, fname, ...) \
-ret __mfwrap_ ## fname (__VA_ARGS__)
-
-
-/* Utility macros for mf-hooks*.c */
-
-#define MF_VALIDATE_EXTENT(value,size,acc,context) \
- do { \
- if (UNLIKELY (size > 0 && __MF_CACHE_MISS_P (value, size))) \
- if (acc == __MF_CHECK_WRITE || ! __mf_opts.ignore_reads) \
- __mf_check ((void *) (value), (size), acc, "(" context ")"); \
- } while (0)
-#define BEGIN_PROTECT(fname, ...) \
- if (UNLIKELY (__mf_starting_p)) \
- { \
- return CALL_BACKUP(fname, __VA_ARGS__); \
- } \
- else if (UNLIKELY (__mf_get_state () == reentrant)) \
- { \
- extern unsigned long __mf_reentrancy; \
- __mf_reentrancy ++; \
- return CALL_REAL(fname, __VA_ARGS__); \
- } \
- else if (UNLIKELY (__mf_get_state () == in_malloc)) \
- { \
- return CALL_REAL(fname, __VA_ARGS__); \
- } \
- else \
- { \
- TRACE ("%s\n", __PRETTY_FUNCTION__); \
- }
-
-/* There is an assumption here that these will only be called in routines
- that call BEGIN_PROTECT at the start, and hence the state must always
- be active when BEGIN_MALLOC_PROTECT is called. */
-#define BEGIN_MALLOC_PROTECT() \
- __mf_set_state (in_malloc)
-
-#define END_MALLOC_PROTECT() \
- __mf_set_state (active)
-
-/* Unlocked variants of main entry points from mf-runtime.h. */
-extern void __mfu_check (void *ptr, size_t sz, int type, const char *location);
-extern void __mfu_register (void *ptr, size_t sz, int type, const char *name);
-extern void __mfu_unregister (void *ptr, size_t sz, int type);
-extern void __mfu_report ();
-extern int __mfu_set_options (const char *opts);
-
-
-#endif /* __MF_IMPL_H */
diff --git a/libmudflap/mf-runtime.c b/libmudflap/mf-runtime.c
deleted file mode 100644
index 96a396ef319..00000000000
--- a/libmudflap/mf-runtime.c
+++ /dev/null
@@ -1,2886 +0,0 @@
-/* Mudflap: narrow-pointer bounds-checking by tree rewriting.
- Copyright (C) 2002-2013 Free Software Foundation, Inc.
- Contributed by Frank Ch. Eigler <fche@redhat.com>
- and Graydon Hoare <graydon@redhat.com>
- Splay Tree code originally by Mark Mitchell <mark@markmitchell.com>,
- adapted from libiberty.
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 3, or (at your option) any later
-version.
-
-GCC is distributed in the hope that it will be useful, but WITHOUT 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/>. */
-
-#include "config.h"
-
-/* These attempt to coax various unix flavours to declare all our
- needed tidbits in the system headers. */
-#if !defined(__FreeBSD__) && !defined(__APPLE__)
-#define _POSIX_SOURCE
-#endif /* Some BSDs break <sys/socket.h> if this is defined. */
-#define _GNU_SOURCE
-#define _XOPEN_SOURCE
-#define _BSD_TYPES
-#define __EXTENSIONS__
-#define _ALL_SOURCE
-#define _LARGE_FILE_API
-#define _XOPEN_SOURCE_EXTENDED 1
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <time.h>
-#include <unistd.h>
-#ifdef HAVE_EXECINFO_H
-#include <execinfo.h>
-#endif
-#ifdef HAVE_SIGNAL_H
-#include <signal.h>
-#endif
-#include <assert.h>
-
-#include <string.h>
-#include <limits.h>
-#include <sys/types.h>
-#include <signal.h>
-#include <errno.h>
-#include <ctype.h>
-
-#include "mf-runtime.h"
-#include "mf-impl.h"
-
-
-/* ------------------------------------------------------------------------ */
-/* Splay-tree implementation. */
-
-typedef uintptr_t mfsplay_tree_key;
-typedef void *mfsplay_tree_value;
-
-/* Forward declaration for a node in the tree. */
-typedef struct mfsplay_tree_node_s *mfsplay_tree_node;
-
-/* The type of a function used to iterate over the tree. */
-typedef int (*mfsplay_tree_foreach_fn) (mfsplay_tree_node, void *);
-
-/* The nodes in the splay tree. */
-struct mfsplay_tree_node_s
-{
- /* Data. */
- mfsplay_tree_key key;
- mfsplay_tree_value value;
- /* Children. */
- mfsplay_tree_node left;
- mfsplay_tree_node right;
- /* XXX: The addition of a parent pointer may eliminate some recursion. */
-};
-
-/* The splay tree itself. */
-struct mfsplay_tree_s
-{
- /* The root of the tree. */
- mfsplay_tree_node root;
-
- /* The last key value for which the tree has been splayed, but not
- since modified. */
- mfsplay_tree_key last_splayed_key;
- int last_splayed_key_p;
-
- /* Statistics. */
- unsigned num_keys;
-
- /* Traversal recursion control flags. */
- unsigned max_depth;
- unsigned depth;
- unsigned rebalance_p;
-};
-typedef struct mfsplay_tree_s *mfsplay_tree;
-
-static mfsplay_tree mfsplay_tree_new (void);
-static mfsplay_tree_node mfsplay_tree_insert (mfsplay_tree, mfsplay_tree_key, mfsplay_tree_value);
-static void mfsplay_tree_remove (mfsplay_tree, mfsplay_tree_key);
-static mfsplay_tree_node mfsplay_tree_lookup (mfsplay_tree, mfsplay_tree_key);
-static mfsplay_tree_node mfsplay_tree_predecessor (mfsplay_tree, mfsplay_tree_key);
-static mfsplay_tree_node mfsplay_tree_successor (mfsplay_tree, mfsplay_tree_key);
-static int mfsplay_tree_foreach (mfsplay_tree, mfsplay_tree_foreach_fn, void *);
-static void mfsplay_tree_rebalance (mfsplay_tree sp);
-
-/* ------------------------------------------------------------------------ */
-/* Utility macros */
-
-#define CTOR __attribute__ ((constructor))
-#define DTOR __attribute__ ((destructor))
-
-
-/* Codes to describe the context in which a violation occurs. */
-#define __MF_VIOL_UNKNOWN 0
-#define __MF_VIOL_READ 1
-#define __MF_VIOL_WRITE 2
-#define __MF_VIOL_REGISTER 3
-#define __MF_VIOL_UNREGISTER 4
-#define __MF_VIOL_WATCH 5
-
-/* Protect against recursive calls. */
-
-static void
-begin_recursion_protect1 (const char *pf)
-{
- if (__mf_get_state () == reentrant)
- {
- write (2, "mf: erroneous reentrancy detected in `", 38);
- write (2, pf, strlen(pf));
- write (2, "'\n", 2); \
- abort ();
- }
- __mf_set_state (reentrant);
-}
-
-#define BEGIN_RECURSION_PROTECT() \
- begin_recursion_protect1 (__PRETTY_FUNCTION__)
-
-#define END_RECURSION_PROTECT() \
- __mf_set_state (active)
-
-/* ------------------------------------------------------------------------ */
-/* Required globals. */
-
-#define LOOKUP_CACHE_MASK_DFL 1023
-#define LOOKUP_CACHE_SIZE_MAX 65536 /* Allows max CACHE_MASK 0xFFFF */
-#define LOOKUP_CACHE_SHIFT_DFL 2
-
-struct __mf_cache __mf_lookup_cache [LOOKUP_CACHE_SIZE_MAX];
-uintptr_t __mf_lc_mask = LOOKUP_CACHE_MASK_DFL;
-unsigned char __mf_lc_shift = LOOKUP_CACHE_SHIFT_DFL;
-#define LOOKUP_CACHE_SIZE (__mf_lc_mask + 1)
-
-struct __mf_options __mf_opts;
-int __mf_starting_p = 1;
-
-#ifdef LIBMUDFLAPTH
-#if defined(HAVE_TLS) && !defined(USE_EMUTLS)
-__thread enum __mf_state_enum __mf_state_1 = reentrant;
-#endif
-#else
-enum __mf_state_enum __mf_state_1 = reentrant;
-#endif
-
-#ifdef LIBMUDFLAPTH
-pthread_mutex_t __mf_biglock =
-#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
- PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
-#else
- PTHREAD_MUTEX_INITIALIZER;
-#endif
-#endif
-
-/* Use HAVE_PTHREAD_H here instead of LIBMUDFLAPTH, so that even
- the libmudflap.la (no threading support) can diagnose whether
- the application is linked with -lpthread. See __mf_usage() below. */
-#if HAVE_PTHREAD_H
-#ifdef _POSIX_THREADS
-#pragma weak pthread_join
-#else
-#define pthread_join NULL
-#endif
-#endif
-
-
-/* ------------------------------------------------------------------------ */
-/* stats-related globals. */
-
-static unsigned long __mf_count_check;
-static unsigned long __mf_lookup_cache_reusecount [LOOKUP_CACHE_SIZE_MAX];
-static unsigned long __mf_count_register;
-static unsigned long __mf_total_register_size [__MF_TYPE_MAX+1];
-static unsigned long __mf_count_unregister;
-static unsigned long __mf_total_unregister_size;
-static unsigned long __mf_count_violation [__MF_VIOL_WATCH+1];
-static unsigned long __mf_sigusr1_received;
-static unsigned long __mf_sigusr1_handled;
-/* not static */ unsigned long __mf_reentrancy;
-#ifdef LIBMUDFLAPTH
-/* not static */ unsigned long __mf_lock_contention;
-#endif
-
-
-/* ------------------------------------------------------------------------ */
-/* mode-check-related globals. */
-
-typedef struct __mf_object
-{
- uintptr_t low, high; /* __mf_register parameters */
- const char *name;
- char type; /* __MF_TYPE_something */
- char watching_p; /* Trigger a VIOL_WATCH on access? */
- unsigned read_count; /* Number of times __mf_check/read was called on this object. */
- unsigned write_count; /* Likewise for __mf_check/write. */
- unsigned liveness; /* A measure of recent checking activity. */
- unsigned description_epoch; /* Last epoch __mf_describe_object printed this. */
-
- uintptr_t alloc_pc;
- struct timeval alloc_time;
- char **alloc_backtrace;
- size_t alloc_backtrace_size;
-#ifdef LIBMUDFLAPTH
- pthread_t alloc_thread;
-#endif
-
- int deallocated_p;
- uintptr_t dealloc_pc;
- struct timeval dealloc_time;
- char **dealloc_backtrace;
- size_t dealloc_backtrace_size;
-#ifdef LIBMUDFLAPTH
- pthread_t dealloc_thread;
-#endif
-} __mf_object_t;
-
-/* Live objects: splay trees, separated by type, ordered on .low (base address). */
-/* Actually stored as static vars within lookup function below. */
-
-/* Dead objects: circular arrays; _MIN_CEM .. _MAX_CEM only */
-static unsigned __mf_object_dead_head[__MF_TYPE_MAX_CEM+1]; /* next empty spot */
-static __mf_object_t *__mf_object_cemetary[__MF_TYPE_MAX_CEM+1][__MF_PERSIST_MAX];
-
-
-/* ------------------------------------------------------------------------ */
-/* Forward function declarations */
-
-void __mf_init () CTOR;
-static void __mf_sigusr1_respond ();
-static unsigned __mf_find_objects (uintptr_t ptr_low, uintptr_t ptr_high,
- __mf_object_t **objs, unsigned max_objs);
-static unsigned __mf_find_objects2 (uintptr_t ptr_low, uintptr_t ptr_high,
- __mf_object_t **objs, unsigned max_objs, int type);
-static unsigned __mf_find_dead_objects (uintptr_t ptr_low, uintptr_t ptr_high,
- __mf_object_t **objs, unsigned max_objs);
-static void __mf_adapt_cache ();
-static void __mf_describe_object (__mf_object_t *obj);
-static unsigned __mf_watch_or_not (void *ptr, size_t sz, char flag);
-static mfsplay_tree __mf_object_tree (int type);
-static void __mf_link_object (__mf_object_t *node);
-static void __mf_unlink_object (__mf_object_t *node);
-
-
-/* ------------------------------------------------------------------------ */
-/* Configuration engine */
-
-static void
-__mf_set_default_options ()
-{
- memset (& __mf_opts, 0, sizeof (__mf_opts));
-
- __mf_opts.adapt_cache = 1000003;
- __mf_opts.abbreviate = 1;
- __mf_opts.verbose_violations = 1;
- __mf_opts.free_queue_length = 4;
- __mf_opts.persistent_count = 100;
- __mf_opts.crumple_zone = 32;
- __mf_opts.backtrace = 4;
- __mf_opts.timestamps = 1;
- __mf_opts.mudflap_mode = mode_check;
- __mf_opts.violation_mode = viol_nop;
-#ifdef HAVE___LIBC_FREERES
- __mf_opts.call_libc_freeres = 1;
-#endif
- __mf_opts.heur_std_data = 1;
-#ifdef LIBMUDFLAPTH
- __mf_opts.thread_stack = 0;
-#endif
-
- /* PR41443: Beware that the above flags will be applied to
- setuid/setgid binaries, and cannot be overriden with
- $MUDFLAP_OPTIONS. So the defaults must be non-exploitable.
-
- Should we consider making the default violation_mode something
- harsher than viol_nop? OTOH, glibc's MALLOC_CHECK_ is disabled
- by default for these same programs. */
-}
-
-static struct mudoption
-{
- char *name;
- char *description;
- enum
- {
- set_option,
- read_integer_option,
- } type;
- unsigned value;
- unsigned *target;
-}
-options [] =
- {
- {"mode-nop",
- "mudflaps do nothing",
- set_option, (unsigned)mode_nop, (unsigned *)&__mf_opts.mudflap_mode},
- {"mode-populate",
- "mudflaps populate object tree",
- set_option, (unsigned)mode_populate, (unsigned *)&__mf_opts.mudflap_mode},
- {"mode-check",
- "mudflaps check for memory violations",
- set_option, (unsigned)mode_check, (unsigned *)&__mf_opts.mudflap_mode},
- {"mode-violate",
- "mudflaps always cause violations (diagnostic)",
- set_option, (unsigned)mode_violate, (unsigned *)&__mf_opts.mudflap_mode},
-
- {"viol-nop",
- "violations do not change program execution",
- set_option, (unsigned)viol_nop, (unsigned *)&__mf_opts.violation_mode},
- {"viol-abort",
- "violations cause a call to abort()",
- set_option, (unsigned)viol_abort, (unsigned *)&__mf_opts.violation_mode},
- {"viol-segv",
- "violations are promoted to SIGSEGV signals",
- set_option, (unsigned)viol_segv, (unsigned *)&__mf_opts.violation_mode},
- {"viol-gdb",
- "violations fork a gdb process attached to current program",
- set_option, (unsigned)viol_gdb, (unsigned *)&__mf_opts.violation_mode},
- {"trace-calls",
- "trace calls to mudflap runtime library",
- set_option, 1, &__mf_opts.trace_mf_calls},
- {"verbose-trace",
- "trace internal events within mudflap runtime library",
- set_option, 1, &__mf_opts.verbose_trace},
- {"collect-stats",
- "collect statistics on mudflap's operation",
- set_option, 1, &__mf_opts.collect_stats},
-#ifdef SIGUSR1
- {"sigusr1-report",
- "print report upon SIGUSR1",
- set_option, 1, &__mf_opts.sigusr1_report},
-#endif
- {"internal-checking",
- "perform more expensive internal checking",
- set_option, 1, &__mf_opts.internal_checking},
- {"print-leaks",
- "print any memory leaks at program shutdown",
- set_option, 1, &__mf_opts.print_leaks},
-#ifdef HAVE___LIBC_FREERES
- {"libc-freeres",
- "call glibc __libc_freeres at shutdown for better leak data",
- set_option, 1, &__mf_opts.call_libc_freeres},
-#endif
- {"check-initialization",
- "detect uninitialized object reads",
- set_option, 1, &__mf_opts.check_initialization},
- {"verbose-violations",
- "print verbose messages when memory violations occur",
- set_option, 1, &__mf_opts.verbose_violations},
- {"abbreviate",
- "abbreviate repetitive listings",
- set_option, 1, &__mf_opts.abbreviate},
- {"timestamps",
- "track object lifetime timestamps",
- set_option, 1, &__mf_opts.timestamps},
- {"ignore-reads",
- "ignore read accesses - assume okay",
- set_option, 1, &__mf_opts.ignore_reads},
- {"wipe-stack",
- "wipe stack objects at unwind",
- set_option, 1, &__mf_opts.wipe_stack},
- {"wipe-heap",
- "wipe heap objects at free",
- set_option, 1, &__mf_opts.wipe_heap},
- {"heur-proc-map",
- "support /proc/self/map heuristics",
- set_option, 1, &__mf_opts.heur_proc_map},
- {"heur-stack-bound",
- "enable a simple upper stack bound heuristic",
- set_option, 1, &__mf_opts.heur_stack_bound},
- {"heur-start-end",
- "support _start.._end heuristics",
- set_option, 1, &__mf_opts.heur_start_end},
- {"heur-stdlib",
- "register standard library data (argv, errno, stdin, ...)",
- set_option, 1, &__mf_opts.heur_std_data},
- {"free-queue-length",
- "queue N deferred free() calls before performing them",
- read_integer_option, 0, &__mf_opts.free_queue_length},
- {"persistent-count",
- "keep a history of N unregistered regions",
- read_integer_option, 0, &__mf_opts.persistent_count},
- {"crumple-zone",
- "surround allocations with crumple zones of N bytes",
- read_integer_option, 0, &__mf_opts.crumple_zone},
- /* XXX: not type-safe.
- {"lc-mask",
- "set lookup cache size mask to N (2**M - 1)",
- read_integer_option, 0, (int *)(&__mf_lc_mask)},
- {"lc-shift",
- "set lookup cache pointer shift",
- read_integer_option, 0, (int *)(&__mf_lc_shift)},
- */
- {"lc-adapt",
- "adapt mask/shift parameters after N cache misses",
- read_integer_option, 1, &__mf_opts.adapt_cache},
- {"backtrace",
- "keep an N-level stack trace of each call context",
- read_integer_option, 0, &__mf_opts.backtrace},
-#ifdef LIBMUDFLAPTH
- {"thread-stack",
- "override thread stacks allocation: N kB",
- read_integer_option, 0, &__mf_opts.thread_stack},
-#endif
- {0, 0, set_option, 0, NULL}
- };
-
-static void
-__mf_usage ()
-{
- struct mudoption *opt;
-
- fprintf (stderr,
- "This is a %s%sGCC \"mudflap\" memory-checked binary.\n"
- "Mudflap is Copyright (C) 2002-2013 Free Software Foundation, Inc.\n"
- "\n"
- "Unless setuid, a program's mudflap options be set by an environment variable:\n"
- "\n"
- "$ export MUDFLAP_OPTIONS='<options>'\n"
- "$ <mudflapped_program>\n"
- "\n"
- "where <options> is a space-separated list of \n"
- "any of the following options. Use `-no-OPTION' to disable options.\n"
- "\n",
-#if HAVE_PTHREAD_H
- (pthread_join ? "multi-threaded " : "single-threaded "),
-#else
- "",
-#endif
-#if LIBMUDFLAPTH
- "thread-aware "
-#else
- "thread-unaware "
-#endif
- );
- /* XXX: The multi-threaded thread-unaware combination is bad. */
-
- for (opt = options; opt->name; opt++)
- {
- int default_p = (opt->value == * opt->target);
-
- switch (opt->type)
- {
- char buf[128];
- case set_option:
- fprintf (stderr, "-%-23.23s %s", opt->name, opt->description);
- if (default_p)
- fprintf (stderr, " [active]\n");
- else
- fprintf (stderr, "\n");
- break;
- case read_integer_option:
- strncpy (buf, opt->name, 128);
- strncpy (buf + strlen (opt->name), "=N", 2);
- fprintf (stderr, "-%-23.23s %s", buf, opt->description);
- fprintf (stderr, " [%d]\n", * opt->target);
- break;
- default: abort();
- }
- }
-
- fprintf (stderr, "\n");
-}
-
-
-int
-__mf_set_options (const char *optstr)
-{
- int rc;
- LOCKTH ();
- BEGIN_RECURSION_PROTECT ();
- rc = __mfu_set_options (optstr);
- /* XXX: It's not really that easy. A change to a bunch of parameters
- can require updating auxiliary state or risk crashing:
- free_queue_length, crumple_zone ... */
- END_RECURSION_PROTECT ();
- UNLOCKTH ();
- return rc;
-}
-
-
-int
-__mfu_set_options (const char *optstr)
-{
- struct mudoption *opts = 0;
- char *nxt = 0;
- long tmp = 0;
- int rc = 0;
- const char *saved_optstr = optstr;
-
- /* XXX: bounds-check for optstr! */
-
- while (*optstr)
- {
- switch (*optstr) {
- case ' ':
- case '\t':
- case '\n':
- optstr++;
- break;
-
- case '-':
- if (*optstr+1)
- {
- int negate = 0;
- optstr++;
-
- if (*optstr == '?' ||
- strncmp (optstr, "help", 4) == 0)
- {
- /* Caller will print help and exit. */
- return -1;
- }
-
- if (strncmp (optstr, "no-", 3) == 0)
- {
- negate = 1;
- optstr = & optstr[3];
- }
-
- for (opts = options; opts->name; opts++)
- {
- if (strncmp (optstr, opts->name, strlen (opts->name)) == 0)
- {
- optstr += strlen (opts->name);
- assert (opts->target);
- switch (opts->type)
- {
- case set_option:
- if (negate)
- *(opts->target) = 0;
- else
- *(opts->target) = opts->value;
- break;
- case read_integer_option:
- if (! negate && (*optstr == '=' && *(optstr+1)))
- {
- optstr++;
- tmp = strtol (optstr, &nxt, 10);
- if ((optstr != nxt) && (tmp != LONG_MAX))
- {
- optstr = nxt;
- *(opts->target) = (int)tmp;
- }
- }
- else if (negate)
- * opts->target = 0;
- break;
- }
- }
- }
- }
- break;
-
- default:
- fprintf (stderr,
- "warning: unrecognized string '%s' in mudflap options\n",
- optstr);
- optstr += strlen (optstr);
- rc = -1;
- break;
- }
- }
-
- /* Special post-processing: bound __mf_lc_mask and free_queue_length for security. */
- __mf_lc_mask &= (LOOKUP_CACHE_SIZE_MAX - 1);
- __mf_opts.free_queue_length &= (__MF_FREEQ_MAX - 1);
-
- /* Clear the lookup cache, in case the parameters got changed. */
- /* XXX: race */
- memset (__mf_lookup_cache, 0, sizeof(__mf_lookup_cache));
- /* void slot 0 */
- __mf_lookup_cache[0].low = MAXPTR;
-
- TRACE ("set options from `%s'\n", saved_optstr);
-
- /* Call this unconditionally, in case -sigusr1-report was toggled. */
- __mf_sigusr1_respond ();
-
- return rc;
-}
-
-
-#ifdef PIC
-
-void
-__mf_resolve_single_dynamic (struct __mf_dynamic_entry *e)
-{
- char *err;
-
- assert (e);
- if (e->pointer) return;
-
-#if HAVE_DLVSYM
- if (e->version != NULL && e->version[0] != '\0') /* non-null/empty */
- e->pointer = dlvsym (RTLD_NEXT, e->name, e->version);
- else
-#endif
- e->pointer = dlsym (RTLD_NEXT, e->name);
-
- err = dlerror ();
-
- if (err)
- {
- fprintf (stderr, "mf: error in dlsym(\"%s\"): %s\n",
- e->name, err);
- abort ();
- }
- if (! e->pointer)
- {
- fprintf (stderr, "mf: dlsym(\"%s\") = NULL\n", e->name);
- abort ();
- }
-}
-
-
-static void
-__mf_resolve_dynamics ()
-{
- int i;
- for (i = 0; i < dyn_INITRESOLVE; i++)
- __mf_resolve_single_dynamic (& __mf_dynamic[i]);
-}
-
-
-/* NB: order must match enums in mf-impl.h */
-struct __mf_dynamic_entry __mf_dynamic [] =
-{
- {NULL, "calloc", NULL},
- {NULL, "free", NULL},
- {NULL, "malloc", NULL},
- {NULL, "mmap", NULL},
-#ifdef HAVE_MMAP64
- {NULL, "mmap64", NULL},
-#endif
- {NULL, "munmap", NULL},
- {NULL, "realloc", NULL},
- {NULL, "DUMMY", NULL}, /* dyn_INITRESOLVE */
-#ifdef LIBMUDFLAPTH
- {NULL, "pthread_create", PTHREAD_CREATE_VERSION},
- {NULL, "pthread_join", NULL},
- {NULL, "pthread_exit", NULL}
-#endif
-};
-
-#endif /* PIC */
-
-
-
-/* ------------------------------------------------------------------------ */
-
-/* Lookup & manage automatic initialization of the five or so splay trees. */
-static mfsplay_tree
-__mf_object_tree (int type)
-{
- static mfsplay_tree trees [__MF_TYPE_MAX+1];
- assert (type >= 0 && type <= __MF_TYPE_MAX);
- if (UNLIKELY (trees[type] == NULL))
- trees[type] = mfsplay_tree_new ();
- return trees[type];
-}
-
-
-/* not static */void
-__mf_init ()
-{
- char *ov = 0;
-
- /* Return if initialization has already been done. */
- if (LIKELY (__mf_starting_p == 0))
- return;
-
-#if defined(__FreeBSD__) && defined(LIBMUDFLAPTH)
- pthread_self();
- LOCKTH ();
- UNLOCKTH ();
-#endif /* Prime mutex which calls calloc upon first lock to avoid deadlock. */
-
- /* This initial bootstrap phase requires that __mf_starting_p = 1. */
-#ifdef PIC
- __mf_resolve_dynamics ();
-#endif
- __mf_starting_p = 0;
-
- __mf_set_state (active);
-
- __mf_set_default_options ();
-
- if (getuid () == geteuid () && getgid () == getegid ()) /* PR41433, not setuid */
- ov = getenv ("MUDFLAP_OPTIONS");
- if (ov)
- {
- int rc = __mfu_set_options (ov);
- if (rc < 0)
- {
- __mf_usage ();
- exit (1);
- }
- }
-
- /* Initialize to a non-zero description epoch. */
- __mf_describe_object (NULL);
-
-#define REG_RESERVED(obj) \
- __mf_register (& obj, sizeof(obj), __MF_TYPE_NOACCESS, # obj)
-
- REG_RESERVED (__mf_lookup_cache);
- REG_RESERVED (__mf_lc_mask);
- REG_RESERVED (__mf_lc_shift);
- /* XXX: others of our statics? */
-
- /* Prevent access to *NULL. */
- __mf_register (MINPTR, 1, __MF_TYPE_NOACCESS, "NULL");
- __mf_lookup_cache[0].low = (uintptr_t) -1;
-}
-
-
-
-int
-__wrap_main (int argc, char* argv[])
-{
- extern char **environ;
- extern int main ();
- extern int __real_main ();
- static int been_here = 0;
-
- if (__mf_opts.heur_std_data && ! been_here)
- {
- unsigned i;
-
- been_here = 1;
- __mf_register (argv, sizeof(char *)*(argc+1), __MF_TYPE_STATIC, "argv[]");
- for (i=0; i<argc; i++)
- {
- unsigned j = strlen (argv[i]);
- __mf_register (argv[i], j+1, __MF_TYPE_STATIC, "argv element");
- }
-
- for (i=0; ; i++)
- {
- char *e = environ[i];
- unsigned j;
- if (e == NULL) break;
- j = strlen (environ[i]);
- __mf_register (environ[i], j+1, __MF_TYPE_STATIC, "environ element");
- }
- __mf_register (environ, sizeof(char *)*(i+1), __MF_TYPE_STATIC, "environ[]");
-
- __mf_register (& errno, sizeof (errno), __MF_TYPE_STATIC, "errno area");
-
-#if !(defined(__sun__) && defined(__svr4__))
- /* Conflicts with the automatic registration of __iob[]. */
- __mf_register (stdin, sizeof (*stdin), __MF_TYPE_STATIC, "stdin");
- __mf_register (stdout, sizeof (*stdout), __MF_TYPE_STATIC, "stdout");
- __mf_register (stderr, sizeof (*stderr), __MF_TYPE_STATIC, "stderr");
-#endif
-
- /* Make some effort to register ctype.h static arrays. */
-#if defined(__sun__) && defined(__svr4__)
- /* __ctype[] is declared without size, but MB_CUR_MAX is the last
- member. There seems to be no proper way to determine the size. */
- __mf_register (__ctype, &MB_CUR_MAX - &__ctype[0] + 1, __MF_TYPE_STATIC, "__ctype");
- /* __ctype_mask points at _C_masks[1]. The size can only determined
- using nm on libc.so.1. */
- __mf_register (__ctype_mask - 1, 1028, __MF_TYPE_STATIC, "_C_masks");
-#endif
- /* On modern Linux GLIBC, these are thread-specific and changeable, and are dealt
- with in mf-hooks2.c. */
- }
-
-#ifdef PIC
- return main (argc, argv, environ);
-#else
- return __real_main (argc, argv, environ);
-#endif
-}
-
-
-
-extern void __mf_fini () DTOR;
-void __mf_fini ()
-{
- TRACE ("__mf_fini\n");
- __mfu_report ();
-
-#ifndef PIC
-/* Since we didn't populate the tree for allocations in constructors
- before __mf_init, we cannot check destructors after __mf_fini. */
- __mf_opts.mudflap_mode = mode_nop;
-#endif
-}
-
-
-
-/* ------------------------------------------------------------------------ */
-/* __mf_check */
-
-void __mf_check (void *ptr, size_t sz, int type, const char *location)
-{
- LOCKTH ();
- BEGIN_RECURSION_PROTECT ();
- __mfu_check (ptr, sz, type, location);
- END_RECURSION_PROTECT ();
- UNLOCKTH ();
-}
-
-
-void __mfu_check (void *ptr, size_t sz, int type, const char *location)
-{
- unsigned entry_idx = __MF_CACHE_INDEX (ptr);
- struct __mf_cache *entry = & __mf_lookup_cache [entry_idx];
- int judgement = 0; /* 0=undecided; <0=violation; >0=okay */
- uintptr_t ptr_low = (uintptr_t) ptr;
- uintptr_t ptr_high = CLAMPSZ (ptr, sz);
- struct __mf_cache old_entry = *entry;
-
- if (UNLIKELY (__mf_opts.sigusr1_report))
- __mf_sigusr1_respond ();
- if (UNLIKELY (__mf_opts.ignore_reads && type == 0))
- return;
-
- TRACE ("check ptr=%p b=%u size=%lu %s location=`%s'\n",
- ptr, entry_idx, (unsigned long)sz,
- (type == 0 ? "read" : "write"), location);
-
- switch (__mf_opts.mudflap_mode)
- {
- case mode_nop:
- /* It is tempting to poison the cache here similarly to
- mode_populate. However that eliminates a valuable
- distinction between these two modes. mode_nop is useful to
- let a user count & trace every single check / registration
- call. mode_populate is useful to let a program run fast
- while unchecked.
- */
- judgement = 1;
- break;
-
- case mode_populate:
- entry->low = ptr_low;
- entry->high = ptr_high;
- judgement = 1;
- break;
-
- case mode_check:
- {
- unsigned heuristics = 0;
-
- /* Advance aging/adaptation counters. */
- static unsigned adapt_count;
- adapt_count ++;
- if (UNLIKELY (__mf_opts.adapt_cache > 0 &&
- adapt_count > __mf_opts.adapt_cache))
- {
- adapt_count = 0;
- __mf_adapt_cache ();
- }
-
- /* Looping only occurs if heuristics were triggered. */
- while (judgement == 0)
- {
- DECLARE (void, free, void *p);
- __mf_object_t* ovr_obj[1];
- unsigned obj_count;
- __mf_object_t** all_ovr_obj = NULL;
- __mf_object_t** dealloc_me = NULL;
- unsigned i;
-
- /* Find all overlapping objects. Be optimistic that there is just one. */
- obj_count = __mf_find_objects (ptr_low, ptr_high, ovr_obj, 1);
- if (UNLIKELY (obj_count > 1))
- {
- /* Allocate a real buffer and do the search again. */
- DECLARE (void *, malloc, size_t c);
- unsigned n;
- all_ovr_obj = CALL_REAL (malloc, (sizeof (__mf_object_t *) *
- obj_count));
- if (all_ovr_obj == NULL) abort ();
- n = __mf_find_objects (ptr_low, ptr_high, all_ovr_obj, obj_count);
- assert (n == obj_count);
- dealloc_me = all_ovr_obj;
- }
- else
- {
- all_ovr_obj = ovr_obj;
- dealloc_me = NULL;
- }
-
- /* Update object statistics. */
- for (i = 0; i < obj_count; i++)
- {
- __mf_object_t *obj = all_ovr_obj[i];
- assert (obj != NULL);
- if (type == __MF_CHECK_READ)
- obj->read_count ++;
- else
- obj->write_count ++;
- obj->liveness ++;
- }
-
- /* Iterate over the various objects. There are a number of special cases. */
- for (i = 0; i < obj_count; i++)
- {
- __mf_object_t *obj = all_ovr_obj[i];
-
- /* Any __MF_TYPE_NOACCESS hit is bad. */
- if (UNLIKELY (obj->type == __MF_TYPE_NOACCESS))
- judgement = -1;
-
- /* Any object with a watch flag is bad. */
- if (UNLIKELY (obj->watching_p))
- judgement = -2; /* trigger VIOL_WATCH */
-
- /* A read from an uninitialized object is bad. */
- if (UNLIKELY (__mf_opts.check_initialization
- /* reading */
- && type == __MF_CHECK_READ
- /* not written */
- && obj->write_count == 0
- /* uninitialized (heap) */
- && obj->type == __MF_TYPE_HEAP))
- judgement = -1;
- }
-
- /* We now know that the access spans no invalid objects. */
- if (LIKELY (judgement >= 0))
- for (i = 0; i < obj_count; i++)
- {
- __mf_object_t *obj = all_ovr_obj[i];
-
- /* Is this access entirely contained within this object? */
- if (LIKELY (ptr_low >= obj->low && ptr_high <= obj->high))
- {
- /* Valid access. */
- entry->low = obj->low;
- entry->high = obj->high;
- judgement = 1;
- }
- }
-
- /* This access runs off the end of one valid object. That
- could be okay, if other valid objects fill in all the
- holes. We allow this only for HEAP and GUESS type
- objects. Accesses to STATIC and STACK variables
- should not be allowed to span. */
- if (UNLIKELY ((judgement == 0) && (obj_count > 1)))
- {
- unsigned uncovered = 0;
- for (i = 0; i < obj_count; i++)
- {
- __mf_object_t *obj = all_ovr_obj[i];
- int j, uncovered_low_p, uncovered_high_p;
- uintptr_t ptr_lower, ptr_higher;
-
- uncovered_low_p = ptr_low < obj->low;
- ptr_lower = CLAMPSUB (obj->low, 1);
- uncovered_high_p = ptr_high > obj->high;
- ptr_higher = CLAMPADD (obj->high, 1);
-
- for (j = 0; j < obj_count; j++)
- {
- __mf_object_t *obj2 = all_ovr_obj[j];
-
- if (i == j) continue;
-
- /* Filter out objects that cannot be spanned across. */
- if (obj2->type == __MF_TYPE_STACK
- || obj2->type == __MF_TYPE_STATIC)
- continue;
-
- /* Consider a side "covered" if obj2 includes
- the next byte on that side. */
- if (uncovered_low_p
- && (ptr_lower >= obj2->low && ptr_lower <= obj2->high))
- uncovered_low_p = 0;
- if (uncovered_high_p
- && (ptr_high >= obj2->low && ptr_higher <= obj2->high))
- uncovered_high_p = 0;
- }
-
- if (uncovered_low_p || uncovered_high_p)
- uncovered ++;
- }
-
- /* Success if no overlapping objects are uncovered. */
- if (uncovered == 0)
- judgement = 1;
- }
-
-
- if (dealloc_me != NULL)
- CALL_REAL (free, dealloc_me);
-
- /* If the judgment is still unknown at this stage, loop
- around at most one more time. */
- if (judgement == 0)
- {
- if (heuristics++ < 2) /* XXX parametrize this number? */
- judgement = __mf_heuristic_check (ptr_low, ptr_high);
- else
- judgement = -1;
- }
- }
-
- }
- break;
-
- case mode_violate:
- judgement = -1;
- break;
- }
-
- if (__mf_opts.collect_stats)
- {
- __mf_count_check ++;
-
- if (LIKELY (old_entry.low != entry->low || old_entry.high != entry->high))
- /* && (old_entry.low != 0) && (old_entry.high != 0)) */
- __mf_lookup_cache_reusecount [entry_idx] ++;
- }
-
- if (UNLIKELY (judgement < 0))
- __mf_violation (ptr, sz,
- (uintptr_t) __builtin_return_address (0), location,
- ((judgement == -1) ?
- (type == __MF_CHECK_READ ? __MF_VIOL_READ : __MF_VIOL_WRITE) :
- __MF_VIOL_WATCH));
-}
-
-
-static __mf_object_t *
-__mf_insert_new_object (uintptr_t low, uintptr_t high, int type,
- const char *name, uintptr_t pc)
-{
- DECLARE (void *, calloc, size_t c, size_t n);
-
- __mf_object_t *new_obj;
- new_obj = CALL_REAL (calloc, 1, sizeof(__mf_object_t));
- new_obj->low = low;
- new_obj->high = high;
- new_obj->type = type;
- new_obj->name = name;
- new_obj->alloc_pc = pc;
-#if HAVE_GETTIMEOFDAY
- if (__mf_opts.timestamps)
- gettimeofday (& new_obj->alloc_time, NULL);
-#endif
-#if LIBMUDFLAPTH
- new_obj->alloc_thread = pthread_self ();
-#endif
-
- if (__mf_opts.backtrace > 0 && (type == __MF_TYPE_HEAP || type == __MF_TYPE_HEAP_I))
- new_obj->alloc_backtrace_size =
- __mf_backtrace (& new_obj->alloc_backtrace,
- (void *) pc, 2);
-
- __mf_link_object (new_obj);
- return new_obj;
-}
-
-
-static void
-__mf_uncache_object (__mf_object_t *old_obj)
-{
- /* Remove any low/high pointers for this object from the lookup cache. */
-
- /* Can it possibly exist in the cache? */
- if (LIKELY (old_obj->read_count + old_obj->write_count))
- {
- uintptr_t low = old_obj->low;
- uintptr_t high = old_obj->high;
- struct __mf_cache *entry;
- unsigned i;
- if ((high - low) >= (__mf_lc_mask << __mf_lc_shift))
- {
- /* For large objects (>= cache size - 1) check the whole cache. */
- entry = & __mf_lookup_cache [0];
- for (i = 0; i <= __mf_lc_mask; i++, entry++)
- {
- /* NB: the "||" in the following test permits this code to
- tolerate the situation introduced by __mf_check over
- contiguous objects, where a cache entry spans several
- objects. */
- if (entry->low == low || entry->high == high)
- {
- entry->low = MAXPTR;
- entry->high = MINPTR;
- }
- }
- }
- else
- {
- /* Object is now smaller then cache size. */
- unsigned entry_low_idx = __MF_CACHE_INDEX (low);
- unsigned entry_high_idx = __MF_CACHE_INDEX (high);
- if (entry_low_idx <= entry_high_idx)
- {
- entry = & __mf_lookup_cache [entry_low_idx];
- for (i = entry_low_idx; i <= entry_high_idx; i++, entry++)
- {
- /* NB: the "||" in the following test permits this code to
- tolerate the situation introduced by __mf_check over
- contiguous objects, where a cache entry spans several
- objects. */
- if (entry->low == low || entry->high == high)
- {
- entry->low = MAXPTR;
- entry->high = MINPTR;
- }
- }
- }
- else
- {
- /* Object wrapped around the end of the cache. First search
- from low to end of cache and then from 0 to high. */
- entry = & __mf_lookup_cache [entry_low_idx];
- for (i = entry_low_idx; i <= __mf_lc_mask; i++, entry++)
- {
- /* NB: the "||" in the following test permits this code to
- tolerate the situation introduced by __mf_check over
- contiguous objects, where a cache entry spans several
- objects. */
- if (entry->low == low || entry->high == high)
- {
- entry->low = MAXPTR;
- entry->high = MINPTR;
- }
- }
- entry = & __mf_lookup_cache [0];
- for (i = 0; i <= entry_high_idx; i++, entry++)
- {
- /* NB: the "||" in the following test permits this code to
- tolerate the situation introduced by __mf_check over
- contiguous objects, where a cache entry spans several
- objects. */
- if (entry->low == low || entry->high == high)
- {
- entry->low = MAXPTR;
- entry->high = MINPTR;
- }
- }
- }
- }
- }
-}
-
-
-void
-__mf_register (void *ptr, size_t sz, int type, const char *name)
-{
- LOCKTH ();
- BEGIN_RECURSION_PROTECT ();
- __mfu_register (ptr, sz, type, name);
- END_RECURSION_PROTECT ();
- UNLOCKTH ();
-}
-
-
-void
-__mfu_register (void *ptr, size_t sz, int type, const char *name)
-{
- TRACE ("register ptr=%p size=%lu type=%x name='%s'\n",
- ptr, (unsigned long) sz, type, name ? name : "");
-
- if (__mf_opts.collect_stats)
- {
- __mf_count_register ++;
- __mf_total_register_size [(type < 0) ? 0 :
- (type > __MF_TYPE_MAX) ? 0 :
- type] += sz;
- }
-
- if (UNLIKELY (__mf_opts.sigusr1_report))
- __mf_sigusr1_respond ();
-
- switch (__mf_opts.mudflap_mode)
- {
- case mode_nop:
- break;
-
- case mode_violate:
- __mf_violation (ptr, sz, (uintptr_t) __builtin_return_address (0), NULL,
- __MF_VIOL_REGISTER);
- break;
-
- case mode_populate:
- /* Clear the cache. */
- /* XXX: why the entire cache? */
- /* XXX: race */
- memset (__mf_lookup_cache, 0, sizeof(__mf_lookup_cache));
- /* void slot 0 */
- __mf_lookup_cache[0].low = MAXPTR;
- break;
-
- case mode_check:
- {
- __mf_object_t *ovr_objs [1];
- unsigned num_overlapping_objs;
- uintptr_t low = (uintptr_t) ptr;
- uintptr_t high = CLAMPSZ (ptr, sz);
- uintptr_t pc = (uintptr_t) __builtin_return_address (0);
-
- /* Treat unknown size indication as 1. */
- if (UNLIKELY (sz == 0)) sz = 1;
-
- /* Look for objects only of the same type. This will e.g. permit a registration
- of a STATIC overlapping with a GUESS, and a HEAP with a NOACCESS. At
- __mf_check time however harmful overlaps will be detected. */
- num_overlapping_objs = __mf_find_objects2 (low, high, ovr_objs, 1, type);
-
- /* Handle overlaps. */
- if (UNLIKELY (num_overlapping_objs > 0))
- {
- __mf_object_t *ovr_obj = ovr_objs[0];
-
- /* Accept certain specific duplication pairs. */
- if (((type == __MF_TYPE_STATIC) || (type == __MF_TYPE_GUESS))
- && ovr_obj->low == low
- && ovr_obj->high == high
- && ovr_obj->type == type)
- {
- /* Duplicate registration for static objects may come
- from distinct compilation units. */
- VERBOSE_TRACE ("harmless duplicate reg %p-%p `%s'\n",
- (void *) low, (void *) high,
- (ovr_obj->name ? ovr_obj->name : ""));
- break;
- }
-
- /* Alas, a genuine violation. */
- else
- {
- /* Two or more *real* mappings here. */
- __mf_violation ((void *) ptr, sz,
- (uintptr_t) __builtin_return_address (0), NULL,
- __MF_VIOL_REGISTER);
- }
- }
- else /* No overlapping objects: AOK. */
- __mf_insert_new_object (low, high, type, name, pc);
-
- /* We could conceivably call __mf_check() here to prime the cache,
- but then the read_count/write_count field is not reliable. */
- break;
- }
- } /* end switch (__mf_opts.mudflap_mode) */
-}
-
-
-void
-__mf_unregister (void *ptr, size_t sz, int type)
-{
- LOCKTH ();
- BEGIN_RECURSION_PROTECT ();
- __mfu_unregister (ptr, sz, type);
- END_RECURSION_PROTECT ();
- UNLOCKTH ();
-}
-
-
-void
-__mfu_unregister (void *ptr, size_t sz, int type)
-{
- DECLARE (void, free, void *ptr);
-
- if (UNLIKELY (__mf_opts.sigusr1_report))
- __mf_sigusr1_respond ();
-
- TRACE ("unregister ptr=%p size=%lu type=%x\n", ptr, (unsigned long) sz, type);
-
- switch (__mf_opts.mudflap_mode)
- {
- case mode_nop:
- break;
-
- case mode_violate:
- __mf_violation (ptr, sz,
- (uintptr_t) __builtin_return_address (0), NULL,
- __MF_VIOL_UNREGISTER);
- break;
-
- case mode_populate:
- /* Clear the cache. */
- /* XXX: race */
- memset (__mf_lookup_cache, 0, sizeof(__mf_lookup_cache));
- /* void slot 0 */
- __mf_lookup_cache[0].low = MAXPTR;
- break;
-
- case mode_check:
- {
- __mf_object_t *old_obj = NULL;
- __mf_object_t *del_obj = NULL; /* Object to actually delete. */
- __mf_object_t *objs[1] = {NULL};
- unsigned num_overlapping_objs;
-
- num_overlapping_objs = __mf_find_objects2 ((uintptr_t) ptr,
- CLAMPSZ (ptr, sz), objs, 1, type);
-
- /* Special case for HEAP_I - see free & realloc hook. They don't
- know whether the input region was HEAP or HEAP_I before
- unmapping it. Here we give HEAP a try in case HEAP_I
- failed. */
- if ((type == __MF_TYPE_HEAP_I) && (num_overlapping_objs == 0))
- {
- num_overlapping_objs = __mf_find_objects2 ((uintptr_t) ptr,
- CLAMPSZ (ptr, sz), objs, 1, __MF_TYPE_HEAP);
- }
-
- old_obj = objs[0];
- if (UNLIKELY ((num_overlapping_objs != 1) /* more than one overlap */
- || ((sz == 0) ? 0 : (sz != (old_obj->high - old_obj->low + 1))) /* size mismatch */
- || ((uintptr_t) ptr != old_obj->low))) /* base mismatch */
- {
- __mf_violation (ptr, sz,
- (uintptr_t) __builtin_return_address (0), NULL,
- __MF_VIOL_UNREGISTER);
- break;
- }
-
- __mf_unlink_object (old_obj);
- __mf_uncache_object (old_obj);
-
- /* Wipe buffer contents if desired. */
- if ((__mf_opts.wipe_stack && old_obj->type == __MF_TYPE_STACK)
- || (__mf_opts.wipe_heap && (old_obj->type == __MF_TYPE_HEAP
- || old_obj->type == __MF_TYPE_HEAP_I)))
- {
- memset ((void *) old_obj->low,
- 0,
- (size_t) (old_obj->high - old_obj->low + 1));
- }
-
- /* Manage the object cemetary. */
- if (__mf_opts.persistent_count > 0
- && (unsigned) old_obj->type <= __MF_TYPE_MAX_CEM)
- {
- old_obj->deallocated_p = 1;
- old_obj->dealloc_pc = (uintptr_t) __builtin_return_address (0);
-#if HAVE_GETTIMEOFDAY
- if (__mf_opts.timestamps)
- gettimeofday (& old_obj->dealloc_time, NULL);
-#endif
-#ifdef LIBMUDFLAPTH
- old_obj->dealloc_thread = pthread_self ();
-#endif
-
- if (__mf_opts.backtrace > 0 && old_obj->type == __MF_TYPE_HEAP)
- old_obj->dealloc_backtrace_size =
- __mf_backtrace (& old_obj->dealloc_backtrace,
- NULL, 2);
-
- /* Encourage this object to be displayed again in current epoch. */
- old_obj->description_epoch --;
-
- /* Put this object into the cemetary. This may require this plot to
- be recycled, and the previous resident to be designated del_obj. */
- {
- unsigned row = old_obj->type;
- unsigned plot = __mf_object_dead_head [row];
-
- del_obj = __mf_object_cemetary [row][plot];
- __mf_object_cemetary [row][plot] = old_obj;
- plot ++;
- if (plot == __mf_opts.persistent_count) plot = 0;
- __mf_object_dead_head [row] = plot;
- }
- }
- else
- del_obj = old_obj;
-
- if (__mf_opts.print_leaks)
- {
- if ((old_obj->read_count + old_obj->write_count) == 0 &&
- (old_obj->type == __MF_TYPE_HEAP
- || old_obj->type == __MF_TYPE_HEAP_I))
- {
- /* The problem with a warning message here is that we may not
- be privy to accesses to such objects that occur within
- uninstrumented libraries. */
-#if 0
- fprintf (stderr,
- "*******\n"
- "mudflap warning: unaccessed registered object:\n");
- __mf_describe_object (old_obj);
-#endif
- }
- }
-
- if (del_obj != NULL) /* May or may not equal old_obj. */
- {
- if (__mf_opts.backtrace > 0)
- {
- CALL_REAL(free, del_obj->alloc_backtrace);
- if (__mf_opts.persistent_count > 0)
- {
- CALL_REAL(free, del_obj->dealloc_backtrace);
- }
- }
- CALL_REAL(free, del_obj);
- }
-
- break;
- }
- } /* end switch (__mf_opts.mudflap_mode) */
-
-
- if (__mf_opts.collect_stats)
- {
- __mf_count_unregister ++;
- __mf_total_unregister_size += sz;
- }
-}
-
-
-
-struct tree_stats
-{
- unsigned obj_count;
- unsigned long total_size;
- unsigned live_obj_count;
- double total_weight;
- double weighted_size;
- unsigned long weighted_address_bits [sizeof (uintptr_t) * 8][2];
-};
-
-
-
-static int
-__mf_adapt_cache_fn (mfsplay_tree_node n, void *param)
-{
- __mf_object_t *obj = (__mf_object_t *) n->value;
- struct tree_stats *s = (struct tree_stats *) param;
-
- assert (obj != NULL && s != NULL);
-
- /* Exclude never-accessed objects. */
- if (obj->read_count + obj->write_count)
- {
- s->obj_count ++;
- s->total_size += (obj->high - obj->low + 1);
-
- if (obj->liveness)
- {
- unsigned i;
- uintptr_t addr;
-
- /* VERBOSE_TRACE ("analyze low=%p live=%u name=`%s'\n",
- (void *) obj->low, obj->liveness, obj->name); */
-
- s->live_obj_count ++;
- s->total_weight += (double) obj->liveness;
- s->weighted_size +=
- (double) (obj->high - obj->low + 1) *
- (double) obj->liveness;
-
- addr = obj->low;
- for (i=0; i<sizeof(uintptr_t) * 8; i++)
- {
- unsigned bit = addr & 1;
- s->weighted_address_bits[i][bit] += obj->liveness;
- addr = addr >> 1;
- }
-
- /* Age the liveness value. */
- obj->liveness >>= 1;
- }
- }
-
- return 0;
-}
-
-
-static void
-__mf_adapt_cache ()
-{
- struct tree_stats s;
- uintptr_t new_mask = 0;
- unsigned char new_shift;
- float cache_utilization;
- float max_value;
- static float smoothed_new_shift = -1.0;
- unsigned i;
-
- memset (&s, 0, sizeof (s));
-
- mfsplay_tree_foreach (__mf_object_tree (__MF_TYPE_HEAP), __mf_adapt_cache_fn, (void *) & s);
- mfsplay_tree_foreach (__mf_object_tree (__MF_TYPE_HEAP_I), __mf_adapt_cache_fn, (void *) & s);
- mfsplay_tree_foreach (__mf_object_tree (__MF_TYPE_STACK), __mf_adapt_cache_fn, (void *) & s);
- mfsplay_tree_foreach (__mf_object_tree (__MF_TYPE_STATIC), __mf_adapt_cache_fn, (void *) & s);
- mfsplay_tree_foreach (__mf_object_tree (__MF_TYPE_GUESS), __mf_adapt_cache_fn, (void *) & s);
-
- /* Maybe we're dealing with funny aging/adaptation parameters, or an
- empty tree. Just leave the cache alone in such cases, rather
- than risk dying by division-by-zero. */
- if (! (s.obj_count > 0) && (s.live_obj_count > 0) && (s.total_weight > 0.0))
- return;
-
- /* Guess a good value for the shift parameter by finding an address bit that is a
- good discriminant of lively objects. */
- max_value = 0.0;
- for (i=0; i<sizeof (uintptr_t)*8; i++)
- {
- float value = (float) s.weighted_address_bits[i][0] * (float) s.weighted_address_bits[i][1];
- if (max_value < value) max_value = value;
- }
- for (i=0; i<sizeof (uintptr_t)*8; i++)
- {
- float shoulder_factor = 0.7; /* Include slightly less popular bits too. */
- float value = (float) s.weighted_address_bits[i][0] * (float) s.weighted_address_bits[i][1];
- if (value >= max_value * shoulder_factor)
- break;
- }
- if (smoothed_new_shift < 0) smoothed_new_shift = __mf_lc_shift;
- /* Converge toward this slowly to reduce flapping. */
- smoothed_new_shift = 0.9*smoothed_new_shift + 0.1*i;
- new_shift = (unsigned) (smoothed_new_shift + 0.5);
- assert (new_shift < sizeof (uintptr_t)*8);
-
- /* Count number of used buckets. */
- cache_utilization = 0.0;
- for (i = 0; i < (1 + __mf_lc_mask); i++)
- if (__mf_lookup_cache[i].low != 0 || __mf_lookup_cache[i].high != 0)
- cache_utilization += 1.0;
- cache_utilization /= (1 + __mf_lc_mask);
-
- new_mask |= 0xffff; /* XXX: force a large cache. */
- new_mask &= (LOOKUP_CACHE_SIZE_MAX - 1);
-
- VERBOSE_TRACE ("adapt cache obj=%u/%u sizes=%lu/%.0f/%.0f => "
- "util=%u%% m=%p s=%u\n",
- s.obj_count, s.live_obj_count, s.total_size, s.total_weight, s.weighted_size,
- (unsigned)(cache_utilization*100.0), (void *) new_mask, new_shift);
-
- /* We should reinitialize cache if its parameters have changed. */
- if (new_mask != __mf_lc_mask ||
- new_shift != __mf_lc_shift)
- {
- __mf_lc_mask = new_mask;
- __mf_lc_shift = new_shift;
- /* XXX: race */
- memset (__mf_lookup_cache, 0, sizeof(__mf_lookup_cache));
- /* void slot 0 */
- __mf_lookup_cache[0].low = MAXPTR;
- }
-}
-
-
-
-/* __mf_find_object[s] */
-
-/* Find overlapping live objecs between [low,high]. Return up to
- max_objs of their pointers in objs[]. Return total count of
- overlaps (may exceed max_objs). */
-
-unsigned
-__mf_find_objects2 (uintptr_t ptr_low, uintptr_t ptr_high,
- __mf_object_t **objs, unsigned max_objs, int type)
-{
- unsigned count = 0;
- mfsplay_tree t = __mf_object_tree (type);
- mfsplay_tree_key k = (mfsplay_tree_key) ptr_low;
- int direction;
-
- mfsplay_tree_node n = mfsplay_tree_lookup (t, k);
- /* An exact match for base address implies a hit. */
- if (n != NULL)
- {
- if (count < max_objs)
- objs[count] = (__mf_object_t *) n->value;
- count ++;
- }
-
- /* Iterate left then right near this key value to find all overlapping objects. */
- for (direction = 0; direction < 2; direction ++)
- {
- /* Reset search origin. */
- k = (mfsplay_tree_key) ptr_low;
-
- while (1)
- {
- __mf_object_t *obj;
-
- n = (direction == 0 ? mfsplay_tree_successor (t, k) : mfsplay_tree_predecessor (t, k));
- if (n == NULL) break;
- obj = (__mf_object_t *) n->value;
-
- if (! (obj->low <= ptr_high && obj->high >= ptr_low)) /* No overlap? */
- break;
-
- if (count < max_objs)
- objs[count] = (__mf_object_t *) n->value;
- count ++;
-
- k = (mfsplay_tree_key) obj->low;
- }
- }
-
- return count;
-}
-
-
-unsigned
-__mf_find_objects (uintptr_t ptr_low, uintptr_t ptr_high,
- __mf_object_t **objs, unsigned max_objs)
-{
- int type;
- unsigned count = 0;
-
- /* Search each splay tree for overlaps. */
- for (type = __MF_TYPE_NOACCESS; type <= __MF_TYPE_GUESS; type++)
- {
- unsigned c = __mf_find_objects2 (ptr_low, ptr_high, objs, max_objs, type);
- if (c > max_objs)
- {
- max_objs = 0;
- objs = NULL;
- }
- else /* NB: C may equal 0 */
- {
- max_objs -= c;
- objs += c;
- }
- count += c;
- }
-
- return count;
-}
-
-
-
-/* __mf_link_object */
-
-static void
-__mf_link_object (__mf_object_t *node)
-{
- mfsplay_tree t = __mf_object_tree (node->type);
- mfsplay_tree_insert (t, (mfsplay_tree_key) node->low, (mfsplay_tree_value) node);
-}
-
-/* __mf_unlink_object */
-
-static void
-__mf_unlink_object (__mf_object_t *node)
-{
- mfsplay_tree t = __mf_object_tree (node->type);
- mfsplay_tree_remove (t, (mfsplay_tree_key) node->low);
-}
-
-/* __mf_find_dead_objects */
-
-/* Find overlapping dead objecs between [low,high]. Return up to
- max_objs of their pointers in objs[]. Return total count of
- overlaps (may exceed max_objs). */
-
-static unsigned
-__mf_find_dead_objects (uintptr_t low, uintptr_t high,
- __mf_object_t **objs, unsigned max_objs)
-{
- if (__mf_opts.persistent_count > 0)
- {
- unsigned count = 0;
- unsigned recollection = 0;
- unsigned row = 0;
-
- assert (low <= high);
- assert (max_objs == 0 || objs != NULL);
-
- /* Widen the search from the most recent plots in each row, looking
- backward in time. */
- recollection = 0;
- while (recollection < __mf_opts.persistent_count)
- {
- count = 0;
-
- for (row = 0; row <= __MF_TYPE_MAX_CEM; row ++)
- {
- unsigned plot;
- unsigned i;
-
- plot = __mf_object_dead_head [row];
- for (i = 0; i <= recollection; i ++)
- {
- __mf_object_t *obj;
-
- /* Look backward through row: it's a circular buffer. */
- if (plot > 0) plot --;
- else plot = __mf_opts.persistent_count - 1;
-
- obj = __mf_object_cemetary [row][plot];
- if (obj && obj->low <= high && obj->high >= low)
- {
- /* Found an overlapping dead object! */
- if (count < max_objs)
- objs [count] = obj;
- count ++;
- }
- }
- }
-
- if (count)
- break;
-
- /* Look farther back in time. */
- recollection = (recollection * 2) + 1;
- }
-
- return count;
- } else {
- return 0;
- }
-}
-
-/* __mf_describe_object */
-
-static void
-__mf_describe_object (__mf_object_t *obj)
-{
- static unsigned epoch = 0;
- if (obj == NULL)
- {
- epoch ++;
- return;
- }
-
- if (__mf_opts.abbreviate && obj->description_epoch == epoch)
- {
- fprintf (stderr,
- "mudflap %sobject %p: name=`%s'\n",
- (obj->deallocated_p ? "dead " : ""),
- (void *) obj, (obj->name ? obj->name : ""));
- return;
- }
- else
- obj->description_epoch = epoch;
-
- fprintf (stderr,
- "mudflap %sobject %p: name=`%s'\n"
- "bounds=[%p,%p] size=%lu area=%s check=%ur/%uw liveness=%u%s\n"
- "alloc time=%lu.%06lu pc=%p"
-#ifdef LIBMUDFLAPTH
- " thread=%u"
-#endif
- "\n",
- (obj->deallocated_p ? "dead " : ""),
- (void *) obj, (obj->name ? obj->name : ""),
- (void *) obj->low, (void *) obj->high,
- (unsigned long) (obj->high - obj->low + 1),
- (obj->type == __MF_TYPE_NOACCESS ? "no-access" :
- obj->type == __MF_TYPE_HEAP ? "heap" :
- obj->type == __MF_TYPE_HEAP_I ? "heap-init" :
- obj->type == __MF_TYPE_STACK ? "stack" :
- obj->type == __MF_TYPE_STATIC ? "static" :
- obj->type == __MF_TYPE_GUESS ? "guess" :
- "unknown"),
- obj->read_count, obj->write_count, obj->liveness,
- obj->watching_p ? " watching" : "",
- obj->alloc_time.tv_sec, obj->alloc_time.tv_usec,
- (void *) obj->alloc_pc
-#ifdef LIBMUDFLAPTH
- , (unsigned) obj->alloc_thread
-#endif
- );
-
- if (__mf_opts.backtrace > 0)
- {
- unsigned i;
- for (i=0; i<obj->alloc_backtrace_size; i++)
- fprintf (stderr, " %s\n", obj->alloc_backtrace[i]);
- }
-
- if (__mf_opts.persistent_count > 0)
- {
- if (obj->deallocated_p)
- {
- fprintf (stderr, "dealloc time=%lu.%06lu pc=%p"
-#ifdef LIBMUDFLAPTH
- " thread=%u"
-#endif
- "\n",
- obj->dealloc_time.tv_sec, obj->dealloc_time.tv_usec,
- (void *) obj->dealloc_pc
-#ifdef LIBMUDFLAPTH
- , (unsigned) obj->dealloc_thread
-#endif
- );
-
-
- if (__mf_opts.backtrace > 0)
- {
- unsigned i;
- for (i=0; i<obj->dealloc_backtrace_size; i++)
- fprintf (stderr, " %s\n", obj->dealloc_backtrace[i]);
- }
- }
- }
-}
-
-
-static int
-__mf_report_leaks_fn (mfsplay_tree_node n, void *param)
-{
- __mf_object_t *node = (__mf_object_t *) n->value;
- unsigned *count = (unsigned *) param;
-
- if (count != NULL)
- (*count) ++;
-
- fprintf (stderr, "Leaked object %u:\n", (*count));
- __mf_describe_object (node);
-
- return 0;
-}
-
-
-static unsigned
-__mf_report_leaks ()
-{
- unsigned count = 0;
-
- (void) mfsplay_tree_foreach (__mf_object_tree (__MF_TYPE_HEAP),
- __mf_report_leaks_fn, & count);
- (void) mfsplay_tree_foreach (__mf_object_tree (__MF_TYPE_HEAP_I),
- __mf_report_leaks_fn, & count);
-
- return count;
-}
-
-/* ------------------------------------------------------------------------ */
-/* __mf_report */
-
-void
-__mf_report ()
-{
- LOCKTH ();
- BEGIN_RECURSION_PROTECT ();
- __mfu_report ();
- END_RECURSION_PROTECT ();
- UNLOCKTH ();
-}
-
-void
-__mfu_report ()
-{
- if (__mf_opts.collect_stats)
- {
- fprintf (stderr,
- "*******\n"
- "mudflap stats:\n"
- "calls to __mf_check: %lu\n"
- " __mf_register: %lu [%luB, %luB, %luB, %luB, %luB]\n"
- " __mf_unregister: %lu [%luB]\n"
- " __mf_violation: [%lu, %lu, %lu, %lu, %lu]\n",
- __mf_count_check,
- __mf_count_register,
- __mf_total_register_size[0], __mf_total_register_size[1],
- __mf_total_register_size[2], __mf_total_register_size[3],
- __mf_total_register_size[4], /* XXX */
- __mf_count_unregister, __mf_total_unregister_size,
- __mf_count_violation[0], __mf_count_violation[1],
- __mf_count_violation[2], __mf_count_violation[3],
- __mf_count_violation[4]);
-
- fprintf (stderr,
- "calls with reentrancy: %lu\n", __mf_reentrancy);
-#ifdef LIBMUDFLAPTH
- fprintf (stderr,
- " lock contention: %lu\n", __mf_lock_contention);
-#endif
-
- /* Lookup cache stats. */
- {
- unsigned i;
- unsigned max_reuse = 0;
- unsigned num_used = 0;
- unsigned num_unused = 0;
-
- for (i = 0; i < LOOKUP_CACHE_SIZE; i++)
- {
- if (__mf_lookup_cache_reusecount[i])
- num_used ++;
- else
- num_unused ++;
- if (max_reuse < __mf_lookup_cache_reusecount[i])
- max_reuse = __mf_lookup_cache_reusecount[i];
- }
- fprintf (stderr, "lookup cache slots used: %u unused: %u peak-reuse: %u\n",
- num_used, num_unused, max_reuse);
- }
-
- {
- unsigned live_count;
- live_count = __mf_find_objects (MINPTR, MAXPTR, NULL, 0);
- fprintf (stderr, "number of live objects: %u\n", live_count);
- }
-
- if (__mf_opts.persistent_count > 0)
- {
- unsigned dead_count = 0;
- unsigned row, plot;
- for (row = 0; row <= __MF_TYPE_MAX_CEM; row ++)
- for (plot = 0 ; plot < __mf_opts.persistent_count; plot ++)
- if (__mf_object_cemetary [row][plot] != 0)
- dead_count ++;
- fprintf (stderr, " zombie objects: %u\n", dead_count);
- }
- }
- if (__mf_opts.print_leaks && (__mf_opts.mudflap_mode == mode_check))
- {
- unsigned l;
- extern void * __mf_wrap_alloca_indirect (size_t c);
-
- /* Free up any remaining alloca()'d blocks. */
- __mf_wrap_alloca_indirect (0);
-#ifdef HAVE___LIBC_FREERES
- if (__mf_opts.call_libc_freeres)
- {
- extern void __libc_freeres (void);
- __libc_freeres ();
- }
-#endif
-
- __mf_describe_object (NULL); /* Reset description epoch. */
- l = __mf_report_leaks ();
- fprintf (stderr, "number of leaked objects: %u\n", l);
- }
-}
-
-/* __mf_backtrace */
-
-size_t
-__mf_backtrace (char ***symbols, void *guess_pc, unsigned guess_omit_levels)
-{
- void ** pc_array;
- unsigned pc_array_size = __mf_opts.backtrace + guess_omit_levels;
- unsigned remaining_size;
- unsigned omitted_size = 0;
- unsigned i;
- DECLARE (void, free, void *ptr);
- DECLARE (void *, calloc, size_t c, size_t n);
- DECLARE (void *, malloc, size_t n);
-
- pc_array = CALL_REAL (calloc, pc_array_size, sizeof (void *) );
-#ifdef HAVE_BACKTRACE
- pc_array_size = backtrace (pc_array, pc_array_size);
-#else
-#define FETCH(n) do { if (pc_array_size >= n) { \
- pc_array[n] = __builtin_return_address(n); \
- if (pc_array[n] == 0) pc_array_size = n; } } while (0)
-
- /* Unroll some calls __builtin_return_address because this function
- only takes a literal integer parameter. */
- FETCH (0);
-#if 0
- /* XXX: __builtin_return_address sometimes crashes (!) on >0 arguments,
- rather than simply returning 0. :-( */
- FETCH (1);
- FETCH (2);
- FETCH (3);
- FETCH (4);
- FETCH (5);
- FETCH (6);
- FETCH (7);
- FETCH (8);
- if (pc_array_size > 8) pc_array_size = 9;
-#else
- if (pc_array_size > 0) pc_array_size = 1;
-#endif
-
-#undef FETCH
-#endif
-
- /* We want to trim the first few levels of the stack traceback,
- since they contain libmudflap wrappers and junk. If pc_array[]
- ends up containing a non-NULL guess_pc, then trim everything
- before that. Otherwise, omit the first guess_omit_levels
- entries. */
-
- if (guess_pc != NULL)
- for (i=0; i<pc_array_size; i++)
- if (pc_array [i] == guess_pc)
- omitted_size = i;
-
- if (omitted_size == 0) /* No match? */
- if (pc_array_size > guess_omit_levels)
- omitted_size = guess_omit_levels;
-
- remaining_size = pc_array_size - omitted_size;
-
-#ifdef HAVE_BACKTRACE_SYMBOLS
- *symbols = backtrace_symbols (pc_array + omitted_size, remaining_size);
-#else
- {
- /* Let's construct a buffer by hand. It will have <remaining_size>
- char*'s at the front, pointing at individual strings immediately
- afterwards. */
- void *buffer;
- char *chars;
- char **pointers;
- enum { perline = 30 };
- buffer = CALL_REAL (malloc, remaining_size * (perline + sizeof(char *)));
- pointers = (char **) buffer;
- chars = (char *)buffer + (remaining_size * sizeof (char *));
- for (i = 0; i < remaining_size; i++)
- {
- pointers[i] = chars;
- sprintf (chars, "[0x%p]", pc_array [omitted_size + i]);
- chars = chars + perline;
- }
- *symbols = pointers;
- }
-#endif
- CALL_REAL (free, pc_array);
-
- return remaining_size;
-}
-
-/* ------------------------------------------------------------------------ */
-/* __mf_violation */
-
-void
-__mf_violation (void *ptr, size_t sz, uintptr_t pc,
- const char *location, int type)
-{
- char buf [128];
- static unsigned violation_number;
- DECLARE(void, free, void *ptr);
-
- TRACE ("violation pc=%p location=%s type=%d ptr=%p size=%lu\n",
- (void *) pc,
- (location != NULL ? location : ""), type, ptr, (unsigned long) sz);
-
- if (__mf_opts.collect_stats)
- __mf_count_violation [(type < 0) ? 0 :
- (type > __MF_VIOL_WATCH) ? 0 :
- type] ++;
-
- /* Print out a basic warning message. */
- if (__mf_opts.verbose_violations)
- {
- unsigned dead_p;
- unsigned num_helpful = 0;
- struct timeval now = { 0, 0 };
-#if HAVE_GETTIMEOFDAY
- gettimeofday (& now, NULL);
-#endif
-
- violation_number ++;
- fprintf (stderr,
- "*******\n"
- "mudflap violation %u (%s): time=%lu.%06lu "
- "ptr=%p size=%lu\npc=%p%s%s%s\n",
- violation_number,
- ((type == __MF_VIOL_READ) ? "check/read" :
- (type == __MF_VIOL_WRITE) ? "check/write" :
- (type == __MF_VIOL_REGISTER) ? "register" :
- (type == __MF_VIOL_UNREGISTER) ? "unregister" :
- (type == __MF_VIOL_WATCH) ? "watch" : "unknown"),
- now.tv_sec, now.tv_usec,
- (void *) ptr, (unsigned long)sz, (void *) pc,
- (location != NULL ? " location=`" : ""),
- (location != NULL ? location : ""),
- (location != NULL ? "'" : ""));
-
- if (__mf_opts.backtrace > 0)
- {
- char ** symbols;
- unsigned i, num;
-
- num = __mf_backtrace (& symbols, (void *) pc, 2);
- /* Note: backtrace_symbols calls malloc(). But since we're in
- __mf_violation and presumably __mf_check, it'll detect
- recursion, and not put the new string into the database. */
-
- for (i=0; i<num; i++)
- fprintf (stderr, " %s\n", symbols[i]);
-
- /* Calling free() here would trigger a violation. */
- CALL_REAL(free, symbols);
- }
-
-
- /* Look for nearby objects. For this, we start with s_low/s_high
- pointing to the given area, looking for overlapping objects.
- If none show up, widen the search area and keep looking. */
-
- if (sz == 0) sz = 1;
-
- for (dead_p = 0; dead_p <= 1; dead_p ++) /* for dead_p in 0 1 */
- {
- enum {max_objs = 3}; /* magic */
- __mf_object_t *objs[max_objs];
- unsigned num_objs = 0;
- uintptr_t s_low, s_high;
- unsigned tries = 0;
- unsigned i;
-
- s_low = (uintptr_t) ptr;
- s_high = CLAMPSZ (ptr, sz);
-
- while (tries < 16) /* magic */
- {
- if (dead_p)
- num_objs = __mf_find_dead_objects (s_low, s_high, objs, max_objs);
- else
- num_objs = __mf_find_objects (s_low, s_high, objs, max_objs);
-
- if (num_objs) /* good enough */
- break;
-
- tries ++;
-
- /* XXX: tune this search strategy. It's too dependent on
- sz, which can vary from 1 to very big (when array index
- checking) numbers. */
- s_low = CLAMPSUB (s_low, (sz * tries * tries));
- s_high = CLAMPADD (s_high, (sz * tries * tries));
- }
-
- for (i = 0; i < min (num_objs, max_objs); i++)
- {
- __mf_object_t *obj = objs[i];
- uintptr_t low = (uintptr_t) ptr;
- uintptr_t high = CLAMPSZ (ptr, sz);
- unsigned before1 = (low < obj->low) ? obj->low - low : 0;
- unsigned after1 = (low > obj->high) ? low - obj->high : 0;
- unsigned into1 = (high >= obj->low && low <= obj->high) ? low - obj->low : 0;
- unsigned before2 = (high < obj->low) ? obj->low - high : 0;
- unsigned after2 = (high > obj->high) ? high - obj->high : 0;
- unsigned into2 = (high >= obj->low && low <= obj->high) ? high - obj->low : 0;
-
- fprintf (stderr, "Nearby object %u: checked region begins %uB %s and ends %uB %s\n",
- num_helpful + i + 1,
- (before1 ? before1 : after1 ? after1 : into1),
- (before1 ? "before" : after1 ? "after" : "into"),
- (before2 ? before2 : after2 ? after2 : into2),
- (before2 ? "before" : after2 ? "after" : "into"));
- __mf_describe_object (obj);
- }
- num_helpful += num_objs;
- }
-
- fprintf (stderr, "number of nearby objects: %u\n", num_helpful);
- }
-
- /* How to finally handle this violation? */
- switch (__mf_opts.violation_mode)
- {
- case viol_nop:
- break;
- case viol_segv:
- kill (getpid(), SIGSEGV);
- break;
- case viol_abort:
- abort ();
- break;
- case viol_gdb:
-
- snprintf (buf, 128, "gdb --pid=%u", (unsigned) getpid ());
- system (buf);
- /* XXX: should probably fork() && sleep(GDB_WAIT_PARAMETER)
- instead, and let the forked child execlp() gdb. That way, this
- subject process can be resumed under the supervision of gdb.
- This can't happen now, since system() only returns when gdb
- dies. In that case, we need to beware of starting a second
- concurrent gdb child upon the next violation. (But if the first
- gdb dies, then starting a new one is appropriate.) */
- break;
- }
-}
-
-/* ------------------------------------------------------------------------ */
-
-
-unsigned __mf_watch (void *ptr, size_t sz)
-{
- unsigned rc;
- LOCKTH ();
- BEGIN_RECURSION_PROTECT ();
- rc = __mf_watch_or_not (ptr, sz, 1);
- END_RECURSION_PROTECT ();
- UNLOCKTH ();
- return rc;
-}
-
-unsigned __mf_unwatch (void *ptr, size_t sz)
-{
- unsigned rc;
- LOCKTH ();
- rc = __mf_watch_or_not (ptr, sz, 0);
- UNLOCKTH ();
- return rc;
-}
-
-
-static unsigned
-__mf_watch_or_not (void *ptr, size_t sz, char flag)
-{
- uintptr_t ptr_high = CLAMPSZ (ptr, sz);
- uintptr_t ptr_low = (uintptr_t) ptr;
- unsigned count = 0;
-
- TRACE ("%s ptr=%p size=%lu\n",
- (flag ? "watch" : "unwatch"), ptr, (unsigned long) sz);
-
- switch (__mf_opts.mudflap_mode)
- {
- case mode_nop:
- case mode_populate:
- case mode_violate:
- count = 0;
- break;
-
- case mode_check:
- {
- __mf_object_t **all_ovr_objs;
- unsigned obj_count;
- unsigned n;
- DECLARE (void *, malloc, size_t c);
- DECLARE (void, free, void *p);
-
- obj_count = __mf_find_objects (ptr_low, ptr_high, NULL, 0);
- VERBOSE_TRACE (" %u:", obj_count);
-
- all_ovr_objs = CALL_REAL (malloc, (sizeof (__mf_object_t *) * obj_count));
- if (all_ovr_objs == NULL) abort ();
- n = __mf_find_objects (ptr_low, ptr_high, all_ovr_objs, obj_count);
- assert (n == obj_count);
-
- for (n = 0; n < obj_count; n ++)
- {
- __mf_object_t *obj = all_ovr_objs[n];
-
- VERBOSE_TRACE (" [%p]", (void *) obj);
- if (obj->watching_p != flag)
- {
- obj->watching_p = flag;
- count ++;
-
- /* Remove object from cache, to ensure next access
- goes through __mf_check(). */
- if (flag)
- __mf_uncache_object (obj);
- }
- }
- CALL_REAL (free, all_ovr_objs);
- }
- break;
- }
-
- return count;
-}
-
-
-void
-__mf_sigusr1_handler (int num)
-{
- __mf_sigusr1_received ++;
-}
-
-/* Install or remove SIGUSR1 handler as necessary.
- Also, respond to a received pending SIGUSR1. */
-void
-__mf_sigusr1_respond ()
-{
- static int handler_installed;
-
-#ifdef SIGUSR1
- /* Manage handler */
- if (__mf_opts.sigusr1_report && ! handler_installed)
- {
- signal (SIGUSR1, __mf_sigusr1_handler);
- handler_installed = 1;
- }
- else if(! __mf_opts.sigusr1_report && handler_installed)
- {
- signal (SIGUSR1, SIG_DFL);
- handler_installed = 0;
- }
-#endif
-
- /* Manage enqueued signals */
- if (__mf_sigusr1_received > __mf_sigusr1_handled)
- {
- __mf_sigusr1_handled ++;
- assert (__mf_get_state () == reentrant);
- __mfu_report ();
- handler_installed = 0; /* We may need to re-enable signal; this might be a SysV library. */
- }
-}
-
-
-/* XXX: provide an alternative __assert_fail function that cannot
- fail due to libmudflap infinite recursion. */
-#ifndef NDEBUG
-
-static void
-write_itoa (int fd, unsigned n)
-{
- enum x { bufsize = sizeof(n)*4 };
- char buf [bufsize];
- unsigned i;
-
- for (i=0; i<bufsize-1; i++)
- {
- unsigned digit = n % 10;
- buf[bufsize-2-i] = digit + '0';
- n /= 10;
- if (n == 0)
- {
- char *m = & buf [bufsize-2-i];
- buf[bufsize-1] = '\0';
- write (fd, m, strlen(m));
- break;
- }
- }
-}
-
-
-void
-__assert_fail (const char *msg, const char *file, unsigned line, const char *func)
-{
-#define write2(string) write (2, (string), strlen ((string)));
- write2("mf");
-#ifdef LIBMUDFLAPTH
- write2("(");
- write_itoa (2, (unsigned) pthread_self ());
- write2(")");
-#endif
- write2(": assertion failure: `");
- write (2, msg, strlen (msg));
- write2("' in ");
- write (2, func, strlen (func));
- write2(" at ");
- write (2, file, strlen (file));
- write2(":");
- write_itoa (2, line);
- write2("\n");
-#undef write2
- abort ();
-}
-
-
-#endif
-
-
-
-/* Adapted splay tree code, originally from libiberty. It has been
- specialized for libmudflap as requested by RMS. */
-
-static void
-mfsplay_tree_free (void *p)
-{
- DECLARE (void, free, void *p);
- CALL_REAL (free, p);
-}
-
-static void *
-mfsplay_tree_xmalloc (size_t s)
-{
- DECLARE (void *, malloc, size_t s);
- return CALL_REAL (malloc, s);
-}
-
-
-static void mfsplay_tree_splay (mfsplay_tree, mfsplay_tree_key);
-static mfsplay_tree_node mfsplay_tree_splay_helper (mfsplay_tree,
- mfsplay_tree_key,
- mfsplay_tree_node *,
- mfsplay_tree_node *,
- mfsplay_tree_node *);
-
-
-/* Help splay SP around KEY. PARENT and GRANDPARENT are the parent
- and grandparent, respectively, of NODE. */
-
-static mfsplay_tree_node
-mfsplay_tree_splay_helper (mfsplay_tree sp,
- mfsplay_tree_key key,
- mfsplay_tree_node * node,
- mfsplay_tree_node * parent,
- mfsplay_tree_node * grandparent)
-{
- mfsplay_tree_node *next;
- mfsplay_tree_node n;
- int comparison;
-
- n = *node;
-
- if (!n)
- return *parent;
-
- comparison = ((key > n->key) ? 1 : ((key < n->key) ? -1 : 0));
-
- if (comparison == 0)
- /* We've found the target. */
- next = 0;
- else if (comparison < 0)
- /* The target is to the left. */
- next = &n->left;
- else
- /* The target is to the right. */
- next = &n->right;
-
- if (next)
- {
- /* Check whether our recursion depth is too high. Abort this search,
- and signal that a rebalance is required to continue. */
- if (sp->depth > sp->max_depth)
- {
- sp->rebalance_p = 1;
- return n;
- }
-
- /* Continue down the tree. */
- sp->depth ++;
- n = mfsplay_tree_splay_helper (sp, key, next, node, parent);
- sp->depth --;
-
- /* The recursive call will change the place to which NODE
- points. */
- if (*node != n || sp->rebalance_p)
- return n;
- }
-
- if (!parent)
- /* NODE is the root. We are done. */
- return n;
-
- /* First, handle the case where there is no grandparent (i.e.,
- *PARENT is the root of the tree.) */
- if (!grandparent)
- {
- if (n == (*parent)->left)
- {
- *node = n->right;
- n->right = *parent;
- }
- else
- {
- *node = n->left;
- n->left = *parent;
- }
- *parent = n;
- return n;
- }
-
- /* Next handle the cases where both N and *PARENT are left children,
- or where both are right children. */
- if (n == (*parent)->left && *parent == (*grandparent)->left)
- {
- mfsplay_tree_node p = *parent;
-
- (*grandparent)->left = p->right;
- p->right = *grandparent;
- p->left = n->right;
- n->right = p;
- *grandparent = n;
- return n;
- }
- else if (n == (*parent)->right && *parent == (*grandparent)->right)
- {
- mfsplay_tree_node p = *parent;
-
- (*grandparent)->right = p->left;
- p->left = *grandparent;
- p->right = n->left;
- n->left = p;
- *grandparent = n;
- return n;
- }
-
- /* Finally, deal with the case where N is a left child, but *PARENT
- is a right child, or vice versa. */
- if (n == (*parent)->left)
- {
- (*parent)->left = n->right;
- n->right = *parent;
- (*grandparent)->right = n->left;
- n->left = *grandparent;
- *grandparent = n;
- return n;
- }
- else
- {
- (*parent)->right = n->left;
- n->left = *parent;
- (*grandparent)->left = n->right;
- n->right = *grandparent;
- *grandparent = n;
- return n;
- }
-}
-
-
-
-static int
-mfsplay_tree_rebalance_helper1 (mfsplay_tree_node n, void *array_ptr)
-{
- mfsplay_tree_node **p = array_ptr;
- *(*p) = n;
- (*p)++;
- return 0;
-}
-
-
-static mfsplay_tree_node
-mfsplay_tree_rebalance_helper2 (mfsplay_tree_node * array, unsigned low,
- unsigned high)
-{
- unsigned middle = low + (high - low) / 2;
- mfsplay_tree_node n = array[middle];
-
- /* Note that since we're producing a balanced binary tree, it is not a problem
- that this function is recursive. */
- if (low + 1 <= middle)
- n->left = mfsplay_tree_rebalance_helper2 (array, low, middle - 1);
- else
- n->left = NULL;
-
- if (middle + 1 <= high)
- n->right = mfsplay_tree_rebalance_helper2 (array, middle + 1, high);
- else
- n->right = NULL;
-
- return n;
-}
-
-
-/* Rebalance the entire tree. Do this by copying all the node
- pointers into an array, then cleverly re-linking them. */
-static void
-mfsplay_tree_rebalance (mfsplay_tree sp)
-{
- mfsplay_tree_node *all_nodes, *all_nodes_1;
-
- if (sp->num_keys <= 2)
- return;
-
- all_nodes = mfsplay_tree_xmalloc (sizeof (mfsplay_tree_node) * sp->num_keys);
-
- /* Traverse all nodes to copy their addresses into this array. */
- all_nodes_1 = all_nodes;
- mfsplay_tree_foreach (sp, mfsplay_tree_rebalance_helper1,
- (void *) &all_nodes_1);
-
- /* Relink all the nodes. */
- sp->root = mfsplay_tree_rebalance_helper2 (all_nodes, 0, sp->num_keys - 1);
-
- mfsplay_tree_free (all_nodes);
-}
-
-
-/* Splay SP around KEY. */
-static void
-mfsplay_tree_splay (mfsplay_tree sp, mfsplay_tree_key key)
-{
- if (sp->root == 0)
- return;
-
- /* If we just splayed the tree with the same key, do nothing. */
- if (sp->last_splayed_key_p &&
- (sp->last_splayed_key == key))
- return;
-
- /* Compute a maximum recursion depth for a splay tree with NUM nodes.
- The idea is to limit excessive stack usage if we're facing
- degenerate access patterns. Unfortunately such patterns can occur
- e.g. during static initialization, where many static objects might
- be registered in increasing address sequence, or during a case where
- large tree-like heap data structures are allocated quickly.
-
- On x86, this corresponds to roughly 200K of stack usage.
- XXX: For libmudflapth, this could be a function of __mf_opts.thread_stack. */
- sp->max_depth = 2500;
- sp->rebalance_p = sp->depth = 0;
-
- mfsplay_tree_splay_helper (sp, key, &sp->root, NULL, NULL);
- if (sp->rebalance_p)
- {
- mfsplay_tree_rebalance (sp);
-
- sp->rebalance_p = sp->depth = 0;
- mfsplay_tree_splay_helper (sp, key, &sp->root, NULL, NULL);
-
- if (sp->rebalance_p)
- abort ();
- }
-
-
- /* Cache this splay key. */
- sp->last_splayed_key = key;
- sp->last_splayed_key_p = 1;
-}
-
-
-
-/* Allocate a new splay tree. */
-static mfsplay_tree
-mfsplay_tree_new ()
-{
- mfsplay_tree sp = mfsplay_tree_xmalloc (sizeof (struct mfsplay_tree_s));
- sp->root = NULL;
- sp->last_splayed_key_p = 0;
- sp->num_keys = 0;
-
- return sp;
-}
-
-
-
-/* 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. */
-static mfsplay_tree_node
-mfsplay_tree_insert (mfsplay_tree sp, mfsplay_tree_key key, mfsplay_tree_value value)
-{
- int comparison = 0;
-
- mfsplay_tree_splay (sp, key);
-
- if (sp->root)
- comparison = ((sp->root->key > key) ? 1 :
- ((sp->root->key < key) ? -1 : 0));
-
- if (sp->root && comparison == 0)
- {
- /* If the root of the tree already has the indicated KEY, just
- replace the value with VALUE. */
- sp->root->value = value;
- }
- else
- {
- /* Create a new node, and insert it at the root. */
- mfsplay_tree_node node;
-
- node = mfsplay_tree_xmalloc (sizeof (struct mfsplay_tree_node_s));
- node->key = key;
- node->value = value;
- sp->num_keys++;
- if (!sp->root)
- node->left = node->right = 0;
- else if (comparison < 0)
- {
- node->left = sp->root;
- node->right = node->left->right;
- node->left->right = 0;
- }
- else
- {
- node->right = sp->root;
- node->left = node->right->left;
- node->right->left = 0;
- }
-
- sp->root = node;
- sp->last_splayed_key_p = 0;
- }
-
- return sp->root;
-}
-
-/* Remove KEY from SP. It is not an error if it did not exist. */
-
-static void
-mfsplay_tree_remove (mfsplay_tree sp, mfsplay_tree_key key)
-{
- mfsplay_tree_splay (sp, key);
- sp->last_splayed_key_p = 0;
- if (sp->root && (sp->root->key == key))
- {
- mfsplay_tree_node left, right;
- left = sp->root->left;
- right = sp->root->right;
- /* Delete the root node itself. */
- mfsplay_tree_free (sp->root);
- sp->num_keys--;
- /* 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)
- {
- sp->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
- sp->root = right;
- }
-}
-
-/* Lookup KEY in SP, returning VALUE if present, and NULL
- otherwise. */
-
-static mfsplay_tree_node
-mfsplay_tree_lookup (mfsplay_tree sp, mfsplay_tree_key key)
-{
- mfsplay_tree_splay (sp, key);
- if (sp->root && (sp->root->key == key))
- return sp->root;
- else
- return 0;
-}
-
-
-/* Return the immediate predecessor KEY, or NULL if there is no
- predecessor. KEY need not be present in the tree. */
-
-static mfsplay_tree_node
-mfsplay_tree_predecessor (mfsplay_tree sp, mfsplay_tree_key key)
-{
- int comparison;
- mfsplay_tree_node node;
- /* If the tree is empty, there is certainly no predecessor. */
- if (!sp->root)
- return NULL;
- /* Splay the tree around KEY. That will leave either the KEY
- itself, its predecessor, or its successor at the root. */
- mfsplay_tree_splay (sp, key);
- comparison = ((sp->root->key > key) ? 1 :
- ((sp->root->key < key) ? -1 : 0));
-
- /* If the predecessor is at the root, just return it. */
- if (comparison < 0)
- return sp->root;
- /* Otherwise, find the rightmost element of the left subtree. */
- node = sp->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. */
-
-static mfsplay_tree_node
-mfsplay_tree_successor (mfsplay_tree sp, mfsplay_tree_key key)
-{
- int comparison;
- mfsplay_tree_node node;
- /* If the tree is empty, there is certainly no successor. */
- if (!sp->root)
- return NULL;
- /* Splay the tree around KEY. That will leave either the KEY
- itself, its predecessor, or its successor at the root. */
- mfsplay_tree_splay (sp, key);
- comparison = ((sp->root->key > key) ? 1 :
- ((sp->root->key < key) ? -1 : 0));
- /* If the successor is at the root, just return it. */
- if (comparison > 0)
- return sp->root;
- /* Otherwise, find the leftmost element of the right subtree. */
- node = sp->root->right;
- if (node)
- while (node->left)
- node = node->left;
- return node;
-}
-
-/* Call FN, passing it the DATA, for every node in 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.
-
- This function simulates recursion using dynamically allocated
- arrays, since it may be called from mfsplay_tree_rebalance(), which
- in turn means that the tree is already uncomfortably deep for stack
- space limits. */
-static int
-mfsplay_tree_foreach (mfsplay_tree st, mfsplay_tree_foreach_fn fn, void *data)
-{
- mfsplay_tree_node *stack1;
- char *stack2;
- unsigned sp;
- int val = 0;
- enum s { s_left, s_here, s_right, s_up };
-
- if (st->root == NULL) /* => num_keys == 0 */
- return 0;
-
- stack1 = mfsplay_tree_xmalloc (sizeof (mfsplay_tree_node) * st->num_keys);
- stack2 = mfsplay_tree_xmalloc (sizeof (char) * st->num_keys);
-
- sp = 0;
- stack1 [sp] = st->root;
- stack2 [sp] = s_left;
-
- while (1)
- {
- mfsplay_tree_node n;
- enum s s;
-
- n = stack1 [sp];
- s = stack2 [sp];
-
- /* Handle each of the four possible states separately. */
-
- /* 1: We're here to traverse the left subtree (if any). */
- if (s == s_left)
- {
- stack2 [sp] = s_here;
- if (n->left != NULL)
- {
- sp ++;
- stack1 [sp] = n->left;
- stack2 [sp] = s_left;
- }
- }
-
- /* 2: We're here to traverse this node. */
- else if (s == s_here)
- {
- stack2 [sp] = s_right;
- val = (*fn) (n, data);
- if (val) break;
- }
-
- /* 3: We're here to traverse the right subtree (if any). */
- else if (s == s_right)
- {
- stack2 [sp] = s_up;
- if (n->right != NULL)
- {
- sp ++;
- stack1 [sp] = n->right;
- stack2 [sp] = s_left;
- }
- }
-
- /* 4: We're here after both subtrees (if any) have been traversed. */
- else if (s == s_up)
- {
- /* Pop the stack. */
- if (sp == 0) break; /* Popping off the root note: we're finished! */
- sp --;
- }
-
- else
- abort ();
- }
-
- mfsplay_tree_free (stack1);
- mfsplay_tree_free (stack2);
- return val;
-}
diff --git a/libmudflap/mf-runtime.h b/libmudflap/mf-runtime.h
deleted file mode 100644
index cea01df098b..00000000000
--- a/libmudflap/mf-runtime.h
+++ /dev/null
@@ -1,244 +0,0 @@
-/* Implementation header for mudflap runtime library.
- Mudflap: narrow-pointer bounds-checking by tree rewriting.
- Copyright (C) 2002-2013 Free Software Foundation, Inc.
- Contributed by Frank Ch. Eigler <fche@redhat.com>
- and Graydon Hoare <graydon@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.
-
-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/>. */
-
-/* Public libmudflap declarations -*- C -*- */
-
-#ifndef MF_RUNTIME_H
-#define MF_RUNTIME_H
-
-typedef void *__mf_ptr_t;
-typedef unsigned int __mf_uintptr_t __attribute__ ((__mode__ (__pointer__)));
-typedef __SIZE_TYPE__ __mf_size_t;
-
-/* Global declarations used by instrumentation. When _MUDFLAP is
- defined, these have been auto-declared by the compiler and we
- should not declare them again (ideally we *would* declare them
- again, to verify that the compiler's declarations match the
- library's, but the C++ front end has no mechanism for allowing
- the re-definition of a structure type). */
-#ifndef _MUDFLAP
-struct __mf_cache { __mf_uintptr_t low; __mf_uintptr_t high; };
-extern struct __mf_cache __mf_lookup_cache [];
-extern __mf_uintptr_t __mf_lc_mask;
-extern unsigned char __mf_lc_shift;
-#endif
-
-/* Multithreading support. */
-#ifdef _MUDFLAPTH
-/* extern pthread_mutex_t __mf_biglock; */
-#ifndef _REENTRANT
-#define _REENTRANT
-#endif
-#ifndef _THREAD_SAFE
-#define _THREAD_SAFE
-#endif
-#endif
-
-/* Codes to describe the type of access to check: __mf_check arg 3 */
-
-#define __MF_CHECK_READ 0
-#define __MF_CHECK_WRITE 1
-
-
-/* Codes to describe a region of memory being registered: __mf_*register arg 3 */
-
-#define __MF_TYPE_NOACCESS 0
-#define __MF_TYPE_HEAP 1
-#define __MF_TYPE_HEAP_I 2
-#define __MF_TYPE_STACK 3
-#define __MF_TYPE_STATIC 4
-#define __MF_TYPE_GUESS 5
-
-
-/* The public mudflap API */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern void __mf_check (void *ptr, __mf_size_t sz, int type, const char *location)
- __attribute((nothrow));
-extern void __mf_register (void *ptr, __mf_size_t sz, int type, const char *name)
- __attribute((nothrow));
-extern void __mf_unregister (void *ptr, __mf_size_t sz, int type)
- __attribute((nothrow));
-extern unsigned __mf_watch (void *ptr, __mf_size_t sz);
-extern unsigned __mf_unwatch (void *ptr, __mf_size_t sz);
-extern void __mf_report ();
-extern int __mf_set_options (const char *opts);
-
-
-/* Redirect some standard library functions to libmudflap. These are
- done by simple #define rather than linker wrapping, since only
- instrumented modules are meant to be affected. */
-
-#ifdef _MUDFLAP
-#pragma redefine_extname memcpy __mfwrap_memcpy
-#pragma redefine_extname memmove __mfwrap_memmove
-#pragma redefine_extname memset __mfwrap_memset
-#pragma redefine_extname memcmp __mfwrap_memcmp
-#pragma redefine_extname memchr __mfwrap_memchr
-#pragma redefine_extname memrchr __mfwrap_memrchr
-#pragma redefine_extname strcpy __mfwrap_strcpy
-#pragma redefine_extname strncpy __mfwrap_strncpy
-#pragma redefine_extname strcat __mfwrap_strcat
-#pragma redefine_extname strncat __mfwrap_strncat
-#pragma redefine_extname strcmp __mfwrap_strcmp
-#pragma redefine_extname strcasecmp __mfwrap_strcasecmp
-#pragma redefine_extname strncmp __mfwrap_strncmp
-#pragma redefine_extname strncasecmp __mfwrap_strncasecmp
-#pragma redefine_extname strdup __mfwrap_strdup
-#pragma redefine_extname strndup __mfwrap_strndup
-#pragma redefine_extname strchr __mfwrap_strchr
-#pragma redefine_extname strrchr __mfwrap_strrchr
-#pragma redefine_extname strstr __mfwrap_strstr
-#pragma redefine_extname memmem __mfwrap_memmem
-#pragma redefine_extname strlen __mfwrap_strlen
-#pragma redefine_extname strnlen __mfwrap_strnlen
-#pragma redefine_extname bzero __mfwrap_bzero
-#pragma redefine_extname bcopy __mfwrap_bcopy
-#pragma redefine_extname bcmp __mfwrap_bcmp
-#pragma redefine_extname index __mfwrap_index
-#pragma redefine_extname rindex __mfwrap_rindex
-#pragma redefine_extname asctime __mfwrap_asctime
-#pragma redefine_extname ctime __mfwrap_ctime
-#pragma redefine_extname gmtime __mfwrap_gmtime
-#pragma redefine_extname localtime __mfwrap_localtime
-#pragma redefine_extname time __mfwrap_time
-#pragma redefine_extname strerror __mfwrap_strerror
-#pragma redefine_extname fopen __mfwrap_fopen
-#pragma redefine_extname fdopen __mfwrap_fdopen
-#pragma redefine_extname freopen __mfwrap_freopen
-#pragma redefine_extname fclose __mfwrap_fclose
-#pragma redefine_extname fread __mfwrap_fread
-#pragma redefine_extname fwrite __mfwrap_fwrite
-#pragma redefine_extname fgetc __mfwrap_fgetc
-#pragma redefine_extname fgets __mfwrap_fgets
-#pragma redefine_extname getc __mfwrap_getc
-#pragma redefine_extname gets __mfwrap_gets
-#pragma redefine_extname ungetc __mfwrap_ungetc
-#pragma redefine_extname fputc __mfwrap_fputc
-#pragma redefine_extname fputs __mfwrap_fputs
-#pragma redefine_extname putc __mfwrap_putc
-#pragma redefine_extname puts __mfwrap_puts
-#pragma redefine_extname clearerr __mfwrap_clearerr
-#pragma redefine_extname feof __mfwrap_feof
-#pragma redefine_extname ferror __mfwrap_ferror
-#pragma redefine_extname fileno __mfwrap_fileno
-#pragma redefine_extname printf __mfwrap_printf
-#pragma redefine_extname fprintf __mfwrap_fprintf
-#pragma redefine_extname sprintf __mfwrap_sprintf
-#pragma redefine_extname snprintf __mfwrap_snprintf
-#pragma redefine_extname vprintf __mfwrap_vprintf
-#pragma redefine_extname vfprintf __mfwrap_vfprintf
-#pragma redefine_extname vsprintf __mfwrap_vsprintf
-#pragma redefine_extname vsnprintf __mfwrap_vsnprintf
-#pragma redefine_extname access __mfwrap_access
-#pragma redefine_extname remove __mfwrap_remove
-#pragma redefine_extname fflush __mfwrap_fflush
-#pragma redefine_extname fseek __mfwrap_fseek
-#pragma redefine_extname ftell __mfwrap_ftell
-#pragma redefine_extname rewind __mfwrap_rewind
-#pragma redefine_extname fgetpos __mfwrap_fgetpos
-#pragma redefine_extname fsetpos __mfwrap_fsetpos
-#pragma redefine_extname stat __mfwrap_stat
-#pragma redefine_extname fstat __mfwrap_fstat
-#pragma redefine_extname lstat __mfwrap_lstat
-#pragma redefine_extname mkfifo __mfwrap_mkfifo
-#pragma redefine_extname setvbuf __mfwrap_setvbuf
-#pragma redefine_extname setbuf __mfwrap_setbuf
-#pragma redefine_extname setbuffer __mfwrap_setbuffer
-#pragma redefine_extname setlinebuf __mfwrap_setlinebuf
-#pragma redefine_extname opendir __mfwrap_opendir
-#pragma redefine_extname closedir __mfwrap_closedir
-#pragma redefine_extname readdir __mfwrap_readdir
-#pragma redefine_extname recv __mfwrap_recv
-#pragma redefine_extname recvfrom __mfwrap_recvfrom
-#pragma redefine_extname recvmsg __mfwrap_recvmsg
-#pragma redefine_extname send __mfwrap_send
-#pragma redefine_extname sendto __mfwrap_sendto
-#pragma redefine_extname sendmsg __mfwrap_sendmsg
-#pragma redefine_extname setsockopt __mfwrap_setsockopt
-#pragma redefine_extname getsockopt __mfwrap_getsockopt
-#pragma redefine_extname accept __mfwrap_accept
-#pragma redefine_extname bind __mfwrap_bind
-#pragma redefine_extname connect __mfwrap_connect
-#pragma redefine_extname gethostname __mfwrap_gethostname
-#pragma redefine_extname sethostname __mfwrap_sethostname
-#pragma redefine_extname gethostbyname __mfwrap_gethostbyname
-#pragma redefine_extname wait __mfwrap_wait
-#pragma redefine_extname waitpid __mfwrap_waitpid
-#pragma redefine_extname popen __mfwrap_popen
-#pragma redefine_extname pclose __mfwrap_pclose
-#pragma redefine_extname execve __mfwrap_execve
-#pragma redefine_extname execv __mfwrap_execv
-#pragma redefine_extname execvp __mfwrap_execvp
-#pragma redefine_extname system __mfwrap_system
-#pragma redefine_extname dlopen __mfwrap_dlopen
-#pragma redefine_extname dlerror __mfwrap_dlerror
-#pragma redefine_extname dlsym __mfwrap_dlsym
-#pragma redefine_extname dlclose __mfwrap_dlclose
-#pragma redefine_extname fopen64 __mfwrap_fopen64
-#pragma redefine_extname freopen64 __mfwrap_freopen64
-#pragma redefine_extname stat64 __mfwrap_stat64
-#pragma redefine_extname fseeko64 __mfwrap_fseeko64
-#pragma redefine_extname ftello64 __mfwrap_ftello64
-#pragma redefine_extname semop __mfwrap_semop
-#pragma redefine_extname semctl __mfwrap_semctl
-#pragma redefine_extname shmctl __mfwrap_shmctl
-#pragma redefine_extname shmat __mfwrap_shmat
-#pragma redefine_extname shmdt __mfwrap_shmdt
-#pragma redefine_extname __ctype_b_loc __mfwrap___ctype_b_loc
-#pragma redefine_extname __ctype_toupper_loc __mfwrap___ctype_toupper_loc
-#pragma redefine_extname __ctype_tolower_loc __mfwrap___ctype_tolower_loc
-#pragma redefine_extname getlogin __mfwrap_getlogin
-#pragma redefine_extname cuserid __mfwrap_cuserid
-#pragma redefine_extname getpwnam __mfwrap_getpwnam
-#pragma redefine_extname getpwuid __mfwrap_getpwuid
-#pragma redefine_extname getgrnam __mfwrap_getgrnam
-#pragma redefine_extname getgrgid __mfwrap_getgrgid
-#pragma redefine_extname getservent __mfwrap_getservent
-#pragma redefine_extname getservbyname __mfwrap_getservbyname
-#pragma redefine_extname getservbyport __mfwrap_getservbyport
-#pragma redefine_extname gai_strerror __mfwrap_gai_strerror
-#pragma redefine_extname getmntent __mfwrap_getmntent
-#pragma redefine_extname inet_ntoa __mfwrap_inet_ntoa
-#pragma redefine_extname getprotoent __mfwrap_getprotoent
-#pragma redefine_extname getprotobyname __mfwrap_getprotobyname
-#pragma redefine_extname getprotobynumber __mfwrap_getprotobynumber
-
-/* Disable glibc macros. */
-#define __NO_STRING_INLINES
-
-#endif /* _MUDFLAP */
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* MF_RUNTIME_H */
diff --git a/libmudflap/testsuite/Makefile.am b/libmudflap/testsuite/Makefile.am
deleted file mode 100644
index a2c1e9f4ea3..00000000000
--- a/libmudflap/testsuite/Makefile.am
+++ /dev/null
@@ -1,11 +0,0 @@
-## Process this with automake to create Makefile.in
-
-AUTOMAKE_OPTIONS = foreign dejagnu
-
-EXPECT = `if [ -f ../../expect/expect ] ; then \
- echo ../../expect/expect ; \
- else echo expect ; fi`
-
-RUNTEST = `if [ -f ${srcdir}/../../dejagnu/runtest ] ; then \
- echo ${srcdir}/../../dejagnu/runtest ; \
- else echo runtest ; fi`
diff --git a/libmudflap/testsuite/Makefile.in b/libmudflap/testsuite/Makefile.in
deleted file mode 100644
index 7993ba85408..00000000000
--- a/libmudflap/testsuite/Makefile.in
+++ /dev/null
@@ -1,426 +0,0 @@
-# Makefile.in generated by automake 1.11.6 from Makefile.am.
-# @configure_input@
-
-# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
-# Foundation, Inc.
-# This Makefile.in 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.
-
-@SET_MAKE@
-VPATH = @srcdir@
-am__make_dryrun = \
- { \
- am__dry=no; \
- case $$MAKEFLAGS in \
- *\\[\ \ ]*) \
- echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
- | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
- *) \
- for am__flg in $$MAKEFLAGS; do \
- case $$am__flg in \
- *=*|--*) ;; \
- *n*) am__dry=yes; break;; \
- esac; \
- done;; \
- esac; \
- test $$am__dry = yes; \
- }
-pkgdatadir = $(datadir)/@PACKAGE@
-pkgincludedir = $(includedir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
-pkglibexecdir = $(libexecdir)/@PACKAGE@
-am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
-install_sh_DATA = $(install_sh) -c -m 644
-install_sh_PROGRAM = $(install_sh) -c
-install_sh_SCRIPT = $(install_sh) -c
-INSTALL_HEADER = $(INSTALL_DATA)
-transform = $(program_transform_name)
-NORMAL_INSTALL = :
-PRE_INSTALL = :
-POST_INSTALL = :
-NORMAL_UNINSTALL = :
-PRE_UNINSTALL = :
-POST_UNINSTALL = :
-build_triplet = @build@
-host_triplet = @host@
-target_triplet = @target@
-subdir = testsuite
-DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
- $(srcdir)/mfconfig.exp.in
-ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \
- $(top_srcdir)/../config/depstand.m4 \
- $(top_srcdir)/../config/enable.m4 \
- $(top_srcdir)/../config/lead-dot.m4 \
- $(top_srcdir)/../config/multi.m4 \
- $(top_srcdir)/../config/override.m4 \
- $(top_srcdir)/../config/tls.m4 $(top_srcdir)/../ltoptions.m4 \
- $(top_srcdir)/../ltsugar.m4 $(top_srcdir)/../ltversion.m4 \
- $(top_srcdir)/../lt~obsolete.m4 $(top_srcdir)/acinclude.m4 \
- $(top_srcdir)/../libtool.m4 $(top_srcdir)/configure.ac
-am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
- $(ACLOCAL_M4)
-mkinstalldirs = $(SHELL) $(top_srcdir)/../mkinstalldirs
-CONFIG_HEADER = $(top_builddir)/config.h
-CONFIG_CLEAN_FILES = mfconfig.exp
-CONFIG_CLEAN_VPATH_FILES =
-SOURCES =
-am__can_run_installinfo = \
- case $$AM_UPDATE_INFO_DIR in \
- n|no|NO) false;; \
- *) (install-info --version) >/dev/null 2>&1;; \
- esac
-DEJATOOL = $(PACKAGE)
-RUNTESTDEFAULTFLAGS = --tool $$tool --srcdir $$srcdir
-ACLOCAL = @ACLOCAL@
-AMTAR = @AMTAR@
-AR = @AR@
-AUTOCONF = @AUTOCONF@
-AUTOHEADER = @AUTOHEADER@
-AUTOMAKE = @AUTOMAKE@
-AWK = @AWK@
-CC = @CC@
-CCDEPMODE = @CCDEPMODE@
-CFLAGS = @CFLAGS@
-CPP = @CPP@
-CPPFLAGS = @CPPFLAGS@
-CYGPATH_W = @CYGPATH_W@
-DEFS = @DEFS@
-DEPDIR = @DEPDIR@
-DSYMUTIL = @DSYMUTIL@
-DUMPBIN = @DUMPBIN@
-ECHO_C = @ECHO_C@
-ECHO_N = @ECHO_N@
-ECHO_T = @ECHO_T@
-EGREP = @EGREP@
-EXEEXT = @EXEEXT@
-FGREP = @FGREP@
-GREP = @GREP@
-INSTALL = @INSTALL@
-INSTALL_DATA = @INSTALL_DATA@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_SCRIPT = @INSTALL_SCRIPT@
-INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
-LD = @LD@
-LDFLAGS = @LDFLAGS@
-LIBOBJS = @LIBOBJS@
-LIBS = @LIBS@
-LIBTOOL = @LIBTOOL@
-LIPO = @LIPO@
-LN_S = @LN_S@
-LTLIBOBJS = @LTLIBOBJS@
-MAINT = @MAINT@
-MAKEINFO = @MAKEINFO@
-MF_HAVE_STDINT_H = @MF_HAVE_STDINT_H@
-MF_HAVE_UINTPTR_T = @MF_HAVE_UINTPTR_T@
-MKDIR_P = @MKDIR_P@
-NM = @NM@
-NMEDIT = @NMEDIT@
-OBJDUMP = @OBJDUMP@
-OBJEXT = @OBJEXT@
-OTOOL = @OTOOL@
-OTOOL64 = @OTOOL64@
-PACKAGE = @PACKAGE@
-PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
-PACKAGE_NAME = @PACKAGE_NAME@
-PACKAGE_STRING = @PACKAGE_STRING@
-PACKAGE_TARNAME = @PACKAGE_TARNAME@
-PACKAGE_URL = @PACKAGE_URL@
-PACKAGE_VERSION = @PACKAGE_VERSION@
-PATH_SEPARATOR = @PATH_SEPARATOR@
-RANLIB = @RANLIB@
-SECTION_FLAGS = @SECTION_FLAGS@
-SED = @SED@
-SET_MAKE = @SET_MAKE@
-SHELL = @SHELL@
-STRIP = @STRIP@
-VERSION = @VERSION@
-abs_builddir = @abs_builddir@
-abs_srcdir = @abs_srcdir@
-abs_top_builddir = @abs_top_builddir@
-abs_top_srcdir = @abs_top_srcdir@
-ac_ct_CC = @ac_ct_CC@
-ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
-am__include = @am__include@
-am__leading_dot = @am__leading_dot@
-am__quote = @am__quote@
-am__tar = @am__tar@
-am__untar = @am__untar@
-bindir = @bindir@
-build = @build@
-build_alias = @build_alias@
-build_cpu = @build_cpu@
-build_libmudflapth = @build_libmudflapth@
-build_os = @build_os@
-build_vendor = @build_vendor@
-builddir = @builddir@
-datadir = @datadir@
-datarootdir = @datarootdir@
-docdir = @docdir@
-dvidir = @dvidir@
-enable_shared = @enable_shared@
-enable_static = @enable_static@
-exec_prefix = @exec_prefix@
-host = @host@
-host_alias = @host_alias@
-host_cpu = @host_cpu@
-host_os = @host_os@
-host_vendor = @host_vendor@
-htmldir = @htmldir@
-includedir = @includedir@
-infodir = @infodir@
-install_sh = @install_sh@
-libdir = @libdir@
-libexecdir = @libexecdir@
-localedir = @localedir@
-localstatedir = @localstatedir@
-mandir = @mandir@
-mkdir_p = @mkdir_p@
-multi_basedir = @multi_basedir@
-oldincludedir = @oldincludedir@
-pdfdir = @pdfdir@
-prefix = @prefix@
-program_transform_name = @program_transform_name@
-psdir = @psdir@
-sbindir = @sbindir@
-sharedstatedir = @sharedstatedir@
-srcdir = @srcdir@
-sysconfdir = @sysconfdir@
-target = @target@
-target_alias = @target_alias@
-target_cpu = @target_cpu@
-target_noncanonical = @target_noncanonical@
-target_os = @target_os@
-target_vendor = @target_vendor@
-toolexecdir = @toolexecdir@
-toolexeclibdir = @toolexeclibdir@
-top_build_prefix = @top_build_prefix@
-top_builddir = @top_builddir@
-top_srcdir = @top_srcdir@
-AUTOMAKE_OPTIONS = foreign dejagnu
-EXPECT = `if [ -f ../../expect/expect ] ; then \
- echo ../../expect/expect ; \
- else echo expect ; fi`
-
-RUNTEST = `if [ -f ${srcdir}/../../dejagnu/runtest ] ; then \
- echo ${srcdir}/../../dejagnu/runtest ; \
- else echo runtest ; fi`
-
-all: all-am
-
-.SUFFIXES:
-$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
- @for dep in $?; do \
- case '$(am__configure_deps)' in \
- *$$dep*) \
- ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
- && { if test -f $@; then exit 0; else break; fi; }; \
- exit 1;; \
- esac; \
- done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign testsuite/Makefile'; \
- $(am__cd) $(top_srcdir) && \
- $(AUTOMAKE) --foreign testsuite/Makefile
-.PRECIOUS: Makefile
-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
- @case '$?' in \
- *config.status*) \
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
- *) \
- echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
- cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
- esac;
-
-$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-
-$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(am__aclocal_m4_deps):
-mfconfig.exp: $(top_builddir)/config.status $(srcdir)/mfconfig.exp.in
- cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
-
-mostlyclean-libtool:
- -rm -f *.lo
-
-clean-libtool:
- -rm -rf .libs _libs
-tags: TAGS
-TAGS:
-
-ctags: CTAGS
-CTAGS:
-
-
-check-DEJAGNU: site.exp
- srcdir='$(srcdir)'; export srcdir; \
- EXPECT=$(EXPECT); export EXPECT; \
- runtest=$(RUNTEST); \
- if $(SHELL) -c "$$runtest --version" > /dev/null 2>&1; then \
- exit_status=0; l='$(DEJATOOL)'; for tool in $$l; do \
- if $$runtest $(AM_RUNTESTFLAGS) $(RUNTESTDEFAULTFLAGS) $(RUNTESTFLAGS); \
- then :; else exit_status=1; fi; \
- done; \
- else echo "WARNING: could not find \`runtest'" 1>&2; :;\
- fi; \
- exit $$exit_status
-site.exp: Makefile $(EXTRA_DEJAGNU_SITE_CONFIG)
- @echo 'Making a new site.exp file...'
- @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 '# edit the last section' >>site.tmp
- @echo 'set srcdir "$(srcdir)"' >>site.tmp
- @echo "set objdir `pwd`" >>site.tmp
- @echo 'set build_alias "$(build_alias)"' >>site.tmp
- @echo 'set build_triplet $(build_triplet)' >>site.tmp
- @echo 'set host_alias "$(host_alias)"' >>site.tmp
- @echo 'set host_triplet $(host_triplet)' >>site.tmp
- @echo 'set target_alias "$(target_alias)"' >>site.tmp
- @echo 'set target_triplet $(target_triplet)' >>site.tmp
- @list='$(EXTRA_DEJAGNU_SITE_CONFIG)'; for f in $$list; do \
- echo "## Begin content included from file $$f. Do not modify. ##" \
- && cat `test -f "$$f" || echo '$(srcdir)/'`$$f \
- && echo "## End content included from file $$f. ##" \
- || exit 1; \
- done >> site.tmp
- @echo "## End of auto-generated content; you can edit from here. ##" >> site.tmp
- @if test -f site.exp; then \
- sed -e '1,/^## End of auto-generated content.*##/d' site.exp >> site.tmp; \
- fi
- @-rm -f site.bak
- @test ! -f site.exp || mv site.exp site.bak
- @mv site.tmp site.exp
-
-distclean-DEJAGNU:
- -rm -f site.exp site.bak
- -l='$(DEJATOOL)'; for tool in $$l; do \
- rm -f $$tool.sum $$tool.log; \
- done
-check-am: all-am
- $(MAKE) $(AM_MAKEFLAGS) check-DEJAGNU
-check: check-am
-all-am: Makefile
-installdirs:
-install: install-am
-install-exec: install-exec-am
-install-data: install-data-am
-uninstall: uninstall-am
-
-install-am: all-am
- @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
-
-installcheck: installcheck-am
-install-strip:
- if test -z '$(STRIP)'; then \
- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
- install; \
- else \
- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
- "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
- fi
-mostlyclean-generic:
-
-clean-generic:
-
-distclean-generic:
- -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
- -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
-
-maintainer-clean-generic:
- @echo "This command is intended for maintainers to use"
- @echo "it deletes files that may require special tools to rebuild."
-clean: clean-am
-
-clean-am: clean-generic clean-libtool mostlyclean-am
-
-distclean: distclean-am
- -rm -f Makefile
-distclean-am: clean-am distclean-DEJAGNU distclean-generic
-
-dvi: dvi-am
-
-dvi-am:
-
-html: html-am
-
-html-am:
-
-info: info-am
-
-info-am:
-
-install-data-am:
-
-install-dvi: install-dvi-am
-
-install-dvi-am:
-
-install-exec-am:
-
-install-html: install-html-am
-
-install-html-am:
-
-install-info: install-info-am
-
-install-info-am:
-
-install-man:
-
-install-pdf: install-pdf-am
-
-install-pdf-am:
-
-install-ps: install-ps-am
-
-install-ps-am:
-
-installcheck-am:
-
-maintainer-clean: maintainer-clean-am
- -rm -f Makefile
-maintainer-clean-am: distclean-am maintainer-clean-generic
-
-mostlyclean: mostlyclean-am
-
-mostlyclean-am: mostlyclean-generic mostlyclean-libtool
-
-pdf: pdf-am
-
-pdf-am:
-
-ps: ps-am
-
-ps-am:
-
-uninstall-am:
-
-.MAKE: check-am install-am install-strip
-
-.PHONY: all all-am check check-DEJAGNU check-am clean clean-generic \
- clean-libtool distclean distclean-DEJAGNU distclean-generic \
- distclean-libtool dvi dvi-am html html-am info info-am install \
- install-am install-data install-data-am install-dvi \
- install-dvi-am install-exec install-exec-am install-html \
- install-html-am install-info install-info-am install-man \
- install-pdf install-pdf-am install-ps install-ps-am \
- install-strip installcheck installcheck-am installdirs \
- maintainer-clean maintainer-clean-generic mostlyclean \
- mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
- uninstall uninstall-am
-
-
-# Tell versions [3.59,3.63) of GNU make to not export all variables.
-# Otherwise a system limit (for SysV at least) may be exceeded.
-.NOEXPORT:
diff --git a/libmudflap/testsuite/config/default.exp b/libmudflap/testsuite/config/default.exp
deleted file mode 100644
index 0dafaa123d3..00000000000
--- a/libmudflap/testsuite/config/default.exp
+++ /dev/null
@@ -1,3 +0,0 @@
-load_lib standard.exp
-load_lib libmudflap.exp
-load_lib mfconfig.exp
diff --git a/libmudflap/testsuite/lib/libmudflap.exp b/libmudflap/testsuite/lib/libmudflap.exp
deleted file mode 100644
index 48166e1d0f3..00000000000
--- a/libmudflap/testsuite/lib/libmudflap.exp
+++ /dev/null
@@ -1,311 +0,0 @@
-# Copyright (C) 2001-2013 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 of the License, 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/>.
-
-# Define libmudflap callbacks for dg.exp.
-# This file is a copy of libstdc++-v3's dejagnu driver, with minor changes.
-
-# Useful hook: if ${hostname}_init exists, it will be called, almost
-# the last thing before testing begins. This can be defined in, e.g.,
-# ~/.dejagnurc or $DEJAGNU.
-
-proc load_gcc_lib { filename } {
- global srcdir
- load_file $srcdir/../../gcc/testsuite/lib/$filename
-}
-
-load_lib mfdg.exp
-load_lib libgloss.exp
-load_gcc_lib target-libpath.exp
-load_gcc_lib target-supports.exp
-load_gcc_lib timeout.exp
-load_gcc_lib timeout-dg.exp
-
-proc libmudflap-init { language } {
- global env
- global srcdir outdir blddir objdir tool_root_dir
- global cxx cxxflags
- global includes
- global libs
- global gluefile wrap_flags
- global ld_library_path
-
- switch $language {
- "c" { set cxx [find_gcc] }
- "c++" { set cxx [find_g++] }
- default { error "bad language code $language"; return }
- }
-
- verbose -log "libmudflap-init $cxx"
-
- set blddir [lookfor_file [get_multilibs] libmudflap]
- set cxxblddir [lookfor_file [get_multilibs] libstdc++-v3]
- set cxxflags_file "${cxxblddir}/scripts/testsuite_flags"
-
- # By default, we assume we want to run program images.
- global dg-do-what-default
- set dg-do-what-default run
-
- # set LD_LIBRARY_PATH so that libgcc_s, libstdc++ binaries can be found.
- # locate libgcc.a so we don't need to account for different values of
- # SHLIB_EXT on different platforms
- set gccdir [lookfor_file $tool_root_dir gcc/libgcc.a]
- if {$gccdir != ""} {
- set gccdir [file dirname $gccdir]
- }
-
- set ld_library_path "."
- append ld_library_path ":${gccdir}"
- append ld_library_path ":${cxxblddir}/src/.libs"
- if {[is_remote host] == 0} {
- foreach i "[exec ${gccdir}/xgcc --print-multi-lib]" {
- set mldir ""
- regexp -- "\[a-z0-9=_/\.-\]*;" $i mldir
- set mldir [string trimright $mldir "\;@"]
- if { "$mldir" == "." } {
- continue
- }
- if { [llength [glob -nocomplain ${gccdir}/${mldir}/libgcc_s*.so.*]] >= 1 } {
- append ld_library_path ":${gccdir}/${mldir}"
- }
- }
- }
- append ld_library_path ":${blddir}/.libs"
-
- set libs "-L${blddir}/.libs"
- set cxxflags "-ggdb3 -DDEBUG_ASSERT"
- set includes "-I${srcdir} -I${srcdir}/.. -I.."
-
- if {$language == "c++"} {
- if {[file exists $cxxflags_file]} then {
- set includes "${includes} [exec sh $cxxflags_file --build-includes]"
- set cxxflags "${cxxflags} [exec sh $cxxflags_file --cxxflags]"
- # c++ libs are included by --build-cxx below
- set cxx "[exec sh $cxxflags_file --build-cxx]"
- } else {
- lappend libs "-L${cxxblddir}src/.libs"
- lappend includes "-I../../libstdc++-v3/include"
- }
- }
-
- global mfconfig_libs
- global add_flags
- append add_flags " $mfconfig_libs"
-
- set_ld_library_path_env_vars
- if [info exists env(LD_LIBRARY_PATH)] {
- verbose -log "LD_LIBRARY_PATH = $env(LD_LIBRARY_PATH)"
- }
-
- if { [target_info needs_status_wrapper]!=""} {
- file delete ${objdir}/testglue.o;
- set gluefile ${objdir}/testglue.o;
- set result [build_wrapper $gluefile];
- if { $result != "" } {
- set gluefile [lindex $result 0];
- set wrap_flags [lindex $result 1];
- } else {
- unset gluefile
- }
- }
-
- # If there is no static library then don't run tests with -static.
- global tool
- global mfconfig_libs
- set opts "additional_flags=-static"
- lappend opts "additional_flags=-fmudflap"
- lappend opts "additional_flags=-lmudflap"
- lappend opts "libs=$mfconfig_libs"
- set src stlm[pid].c
- set exe stlm[pid].x
-
- set f [open $src "w"]
- puts $f "int main () { }"
- close $f
- set lines [${tool}_target_compile $src $exe executable "$opts"]
- file delete $src
- remote_file build delete $exe
-
- if { ![string match "" $lines] } {
- # Compilation failed; assume static library is not available.
- global MUDFLAP_FLAGS
- set i [lsearch $MUDFLAP_FLAGS "*static*"]
- set MUDFLAP_FLAGS [lreplace $MUDFLAP_FLAGS $i $i]
- }
-}
-
-proc libmudflap-dg-test { prog do_what extra_tool_flags } {
- # Set up the compiler flags, based on what we're going to do.
-
- switch $do_what {
- "preprocess" {
- set compile_type "preprocess"
- set output_file "[file rootname [file tail $prog]].i"
- }
- "compile" {
- set compile_type "assembly"
- set output_file "[file rootname [file tail $prog]].s"
- }
- "assemble" {
- set compile_type "object"
- set output_file "[file rootname [file tail $prog]].o"
- }
- "link" {
- set compile_type "executable"
- set output_file "./[file rootname [file tail $prog]].exe"
- }
- "run" {
- set compile_type "executable"
- # FIXME: "./" is to cope with "." not being in $PATH.
- # Should this be handled elsewhere?
- # YES.
- set output_file "./[file rootname [file tail $prog]].exe"
- # This is the only place where we care if an executable was
- # created or not. If it was, dg.exp will try to run it.
- remote_file build delete $output_file;
- }
- default {
- perror "$do_what: not a valid dg-do keyword"
- return ""
- }
- }
- set options ""
- if { $extra_tool_flags != "" } {
- lappend options "additional_flags=$extra_tool_flags"
- }
-
- global mfconfig_libs
- lappend options "libs=$mfconfig_libs"
-
- set comp_output [libmudflap_target_compile "$prog" "$output_file" "$compile_type" $options];
-
- return [list $comp_output $output_file]
-}
-
-
-proc libmudflap_target_compile { source dest type options } {
- global gluefile
- global wrap_flags
- global cxx
- global cxxflags
- global includes
- global libs
- global blddir
-
- if { [target_info needs_status_wrapper] != "" && [info exists gluefile] } {
- lappend options "libs=${gluefile}"
- lappend options "ldflags=${wrap_flags}"
- }
-
- set cxx_final $cxx
- set cxxlibglossflags [libgloss_link_flags]
- set cxx_final [concat $cxx_final $cxxlibglossflags]
- set cxx_final [concat $cxx_final $cxxflags]
- set cxx_final [concat $cxx_final $includes]
- set cxx_final [concat $cxx_final $libs]
-
- lappend options "compiler=$cxx_final"
- lappend options "timeout=[timeout_value]"
-
- # Picks up the freshly-built testsuite library corresponding to the
- # multilib under test.
- lappend options "ldflags=-L${blddir}/testsuite"
-
- return [target_compile $source $dest $type $options]
-}
-
-
-# A bit sloppy... Returns a list of source files (full pathnames) to
-# compile. We mimic the mkcheck script in that the first time this is run,
-# all existing files are listed in "testsuite_files" in the output
-# directory. Subsequent runs pull the list from that file, allowing users
-# to trim the list down to problematic tests.
-### This is supposed to be done via RUNTESTFLAGS, but that doesn't work.
-proc libmudflap-list-sourcefiles { } {
- global srcdir
- global outdir
-
- set files_file "${outdir}/testsuite_files"
- set sfiles ""
- if { [file exists $files_file] } {
- set f [open $files_file]
- while { ! [eof $f] } {
- set t [gets $f]
- if { [string length "$t"] != 0 } {
- lappend sfiles ${srcdir}/${t}
- }
- }
- } else {
- set f [open $files_file "w"]
- set where_we_were [pwd]
- cd $srcdir
- foreach s [lsort [glob -nocomplain "*/*.cc" "*/*/*.cc" "{,*/}*/*/*/*.cc" ]] {
- lappend sfiles ${srcdir}/${s}
- puts $f $s
- }
- cd $where_we_were
- }
- close $f
-
- # Disable wchar_t tests if library not configured to support
- # wchar_t testing.
- set wchar_file "${outdir}/testsuite_wchar_t"
- if { [file exists $wchar_file] } {
- return $sfiles
- } else {
- # Remove wchar_t tests files from list.
- set res {}
- foreach w $sfiles {
- if [regexp "wchar_t" $w] {
- verbose -log "element out list is $w"
- } else {
- verbose -log "element in list is $w"
- lappend res $w
- }
- }
- return $res
- }
-}
-
-
-proc libmudflap-dg-prune { system text } {
- global additional_prunes
-
- set text [prune_gcc_output $text]
-
- foreach p $additional_prunes {
- if { [string length $p] > 0 } {
- # Following regexp matches a complete line containing $p.
- regsub -all "(^|\n)\[^\n\]*$p\[^\n\]*" $text "" text
- }
- }
-
- return $text
-}
-
-
-proc prune_gcc_output { text } {
- # Ignore caret diagnostics. Unfortunately dejaGNU trims leading
- # spaces, so one cannot rely on them being present.
- regsub -all "(^|\n)\[^\n\]+\n *\\^\n" $text "\n" text
- regsub -all {(^|\n)[^\n]*ld: warning: libgcc_s[^\n]*not found[^\n]*try using[^\n]*} $text "" text
- regsub -all {(^|\n)[^\n]*In function.*pthread_create[^\n]*} $text "" text
- regsub -all {(^|\n)[^\n]*the use of .pthread.*is deprecated[^\n]*} $text "" text
- regsub -all {(^|\n)[^\n]*Dwarf Error:.*FORM value: 14[^\n]*} $text "" text
- regsub -all {(^|\n)[^\n]*In function[^\n]*} $text "" text
- regsub -all {(^|\n)[^\n]*Using.*in statically linked applications requires[^\n]*} $text "" text
-
- return $text
-}
diff --git a/libmudflap/testsuite/lib/mfdg.exp b/libmudflap/testsuite/lib/mfdg.exp
deleted file mode 100644
index 0b9875cd6ec..00000000000
--- a/libmudflap/testsuite/lib/mfdg.exp
+++ /dev/null
@@ -1,365 +0,0 @@
-# `mfdg' - overrides parts of general purpose testcase driver.
-# Copyright (C) 1994-2013 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 of the License, 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 is a modified excerpt of dejagnu/lib/dg.exp.
-
-load_lib dg.exp
-
-
-# dg-test -- runs a new style DejaGnu test
-#
-# Syntax: dg-test [-keep-output] prog tool_flags default_extra_tool_flags
-#
-# PROG is the full path name of the file to pass to the tool (eg: compiler).
-# TOOL_FLAGS is a set of options to always pass.
-# DEFAULT_EXTRA_TOOL_FLAGS are additional options if the testcase has none.
-
-#proc dg-test { prog tool_flags default_extra_tool_flags } {
-proc dg-test { args } {
- global dg-do-what-default dg-interpreter-batch-mode dg-linenum-format
- global errorCode errorInfo
- global additional_prunes
- global tool
- global srcdir ;# eg: /calvin/dje/build/gcc/./testsuite/
- global host_triplet target_triplet
-
- set keep 0
- set i 0
- set dg-repetitions 1 ;# may be overridden by { dg-repetitions N }
- unset_timeout_vars
-
- if { [string index [lindex $args 0] 0] == "-" } {
- for { set i 0 } { $i < [llength $args] } { incr i } {
- if { [lindex $args $i] == "--" } {
- incr i
- break
- } elseif { [lindex $args $i] == "-keep-output" } {
- set keep 1
- } elseif { [string index [lindex $args $i] 0] == "-" } {
- clone_output "ERROR: dg-test: illegal argument: [lindex $args $i]"
- return
- } else {
- break
- }
- }
- }
-
- if { $i + 3 != [llength $args] } {
- clone_output "ERROR: dg-test: missing arguments in call"
- return
- }
- set prog [lindex $args $i]
- set tool_flags [lindex $args [expr $i + 1]]
- set default_extra_tool_flags [lindex $args [expr $i + 2]]
-
- set text "\[- A-Za-z0-9\.\;\"\_\:\'\`\(\)\!\#\=\+\?\&\*]*"
-
- set name [dg-trim-dirname $srcdir $prog]
- # If we couldn't rip $srcdir out of `prog' then just do the best we can.
- # The point is to reduce the unnecessary noise in the logs. Don't strip
- # out too much because different testcases with the same name can confuse
- # `test-tool'.
- if [string match "/*" $name] {
- set name "[file tail [file dirname $prog]]/[file tail $prog]"
- }
-
- if {$tool_flags != ""} {
- append name " ($tool_flags)"
- }
-
- # Process any embedded dg options in the testcase.
-
- # Use "" for the second element of dg-do-what so we can tell if it's been
- # explicitly set to "S".
- set dg-do-what [list ${dg-do-what-default} "" P]
- set dg-excess-errors-flag 0
- set dg-messages ""
- set dg-extra-tool-flags $default_extra_tool_flags
- set dg-final-code ""
-
- set additional_prunes ""
-
- # `dg-output-text' is a list of two elements: pass/fail and text.
- # Leave second element off for now (indicates "don't perform test")
- set dg-output-text "P"
-
- # Define our own "special function" `unknown' so we catch spelling errors.
- # But first rename the existing one so we can restore it afterwards.
- catch {rename dg-save-unknown ""}
- rename unknown dg-save-unknown
- proc unknown { args } {
- return -code error "unknown dg option: $args"
- }
-
- set tmp [dg-get-options $prog]
- foreach op $tmp {
- verbose "Processing option: $op" 3
- set status [catch "$op" errmsg]
- if { $status != 0 } {
- if { 0 && [info exists errorInfo] } {
- # This also prints a backtrace which will just confuse
- # testcase writers, so it's disabled.
- perror "$name: $errorInfo\n"
- } else {
- perror "$name: $errmsg for \"$op\"\n"
- }
- # ??? The call to unresolved here is necessary to clear `errcnt'.
- # What we really need is a proc like perror that doesn't set errcnt.
- # It should also set exit_status to 1.
- unresolved "$name: $errmsg for \"$op\""
- return
- }
- }
-
- # Restore normal error handling.
- rename unknown ""
- rename dg-save-unknown unknown
-
- # If we're not supposed to try this test on this target, we're done.
- if { [lindex ${dg-do-what} 1] == "N" } {
- unsupported "$name"
- verbose "$name not supported on this target, skipping it" 3
- return
- }
-
- # Run the tool and analyze the results.
- # The result of ${tool}-dg-test is in a bit of flux.
- # Currently it is the name of the output file (or "" if none).
- # If we need more than this it will grow into a list of things.
- # No intention is made (at this point) to preserve upward compatibility
- # (though at some point we'll have to).
-
- set results [${tool}-dg-test $prog [lindex ${dg-do-what} 0] "$tool_flags ${dg-extra-tool-flags}"];
-
- set comp_output [lindex $results 0];
- set output_file [lindex $results 1];
-
- #send_user "\nold_dejagnu.exp: comp_output1 = :$comp_output:\n\n"
- #send_user "\nold_dejagnu.exp: message = :$message:\n\n"
- #send_user "\nold_dejagnu.exp: message length = [llength $message]\n\n"
-
- foreach i ${dg-messages} {
- verbose "Scanning for message: $i" 4
-
- # Remove all error messages for the line [lindex $i 0]
- # in the source file. If we find any, success!
- set line [lindex $i 0]
- set pattern [lindex $i 2]
- set comment [lindex $i 3]
- #send_user "Before:\n$comp_output\n"
- if [regsub -all "(^|\n)(\[^\n\]+$line\[^\n\]*($pattern)\[^\n\]*\n?)+" $comp_output "\n" comp_output] {
- set comp_output [string trimleft $comp_output]
- set ok pass
- set uhoh fail
- } else {
- set ok fail
- set uhoh pass
- }
- #send_user "After:\n$comp_output\n"
-
- # $line will either be a formatted line number or a number all by
- # itself. Delete the formatting.
- scan $line ${dg-linenum-format} line
- switch [lindex $i 1] {
- "ERROR" {
- $ok "$name $comment (test for errors, line $line)"
- }
- "XERROR" {
- x$ok "$name $comment (test for errors, line $line)"
- }
- "WARNING" {
- $ok "$name $comment (test for warnings, line $line)"
- }
- "XWARNING" {
- x$ok "$name $comment (test for warnings, line $line)"
- }
- "BOGUS" {
- $uhoh "$name $comment (test for bogus messages, line $line)"
- }
- "XBOGUS" {
- x$uhoh "$name $comment (test for bogus messages, line $line)"
- }
- "BUILD" {
- $uhoh "$name $comment (test for build failure, line $line)"
- }
- "XBUILD" {
- x$uhoh "$name $comment (test for build failure, line $line)"
- }
- "EXEC" { }
- "XEXEC" { }
- }
- #send_user "\nold_dejagnu.exp: comp_output2= :$comp_output:\n\n"
- }
- #send_user "\nold_dejagnu.exp: comp_output3 = :$comp_output:\n\n"
-
- # Remove messages from the tool that we can ignore.
- #send_user "comp_output: $comp_output\n"
- set comp_output [prune_warnings $comp_output]
-
- if { [info proc ${tool}-dg-prune] != "" } {
- set comp_output [${tool}-dg-prune $target_triplet $comp_output]
- switch -glob $comp_output {
- "::untested::*" {
- regsub "::untested::" $comp_output "" message
- untested "$name: $message"
- return
- }
- "::unresolved::*" {
- regsub "::unresolved::" $comp_output "" message
- unresolved "$name: $message"
- return
- }
- "::unsupported::*" {
- regsub "::unsupported::" $comp_output "" message
- unsupported "$name: $message"
- return
- }
- }
- }
-
- # See if someone forgot to delete the extra lines.
- regsub -all "\n+" $comp_output "\n" comp_output
- regsub "^\n+" $comp_output "" comp_output
- #send_user "comp_output: $comp_output\n"
-
- # Don't do this if we're testing an interpreter.
- # FIXME: why?
- if { ${dg-interpreter-batch-mode} == 0 } {
- # Catch excess errors (new bugs or incomplete testcases).
- if ${dg-excess-errors-flag} {
- setup_xfail "*-*-*"
- }
- if ![string match "" $comp_output] {
- fail "$name (test for excess errors)"
- send_log "Excess errors:\n$comp_output\n"
- } else {
- pass "$name (test for excess errors)"
- }
- }
-
- # Run the executable image if asked to do so.
- # FIXME: This is the only place where we assume a standard meaning to
- # the `keyword' argument of dg-do. This could be cleaned up.
- if { [lindex ${dg-do-what} 0] == "run" } {
- if ![file exists $output_file] {
- warning "$name compilation failed to produce executable"
- } else {
- set testname $name
- for {set rep 0} {$rep < ${dg-repetitions}} {incr rep} {
- # include repetition number in test name
- if {$rep > 0} { set name "$testname (rerun $rep)" }
-
- set status -1
- set result [${tool}_load $output_file]
- set status [lindex $result 0];
- set output [lindex $result 1];
- #send_user "After exec, status: $status\n"
-
- if { "$status" == "pass" } {
- verbose "Exec succeeded." 3
- } elseif { "$status" == "fail" } {
- # It would be nice to get some info out of errorCode.
- if [info exists errorCode] {
- verbose "Exec failed, errorCode: $errorCode" 3
- } else {
- verbose "Exec failed, errorCode not defined!" 3
- }
- }
-
- if { [lindex ${dg-do-what} 2] == "F" } {
- # Instead of modelling this as an xfail (via setup_xfail),
- # treat an expected crash as a success.
- if { $status == "pass" } then { set status fail } else { set status pass }
- set testtype "crash"
- } else { set testtype "execution" }
-
- $status "$name $testtype test"
-
- if { [llength ${dg-output-text}] > 1 } {
- #send_user "${dg-output-text}\n"
- if { [lindex ${dg-output-text} 0] == "F" } {
- setup_xfail "*-*-*"
- }
- set texttmp [lindex ${dg-output-text} 1]
- if { ![regexp $texttmp ${output}] } {
- fail "$name output pattern test"
- } else {
- pass "$name output pattern test"
- }
- verbose -log "Output pattern $texttmp"
- unset texttmp
- }
- }
- }
- }
-
- # Are there any further tests to perform?
- # Note that if the program has special run-time requirements, running
- # of the program can be delayed until here. Ditto for other situations.
- # It would be a bit cumbersome though.
-
- if ![string match ${dg-final-code} ""] {
- regsub -all "\\\\(\[{}\])" ${dg-final-code} "\\1" dg-final-code
- # Note that the use of `args' here makes this a varargs proc.
- proc dg-final-proc { args } ${dg-final-code}
- verbose "Running dg-final tests." 3
- verbose "dg-final-proc:\n[info body dg-final-proc]" 4
- if [catch "dg-final-proc $prog" errmsg] {
- perror "$name: error executing dg-final: $errmsg"
- # ??? The call to unresolved here is necessary to clear `errcnt'.
- # What we really need is a proc like perror that doesn't set errcnt.
- # It should also set exit_status to 1.
- unresolved "$name: error executing dg-final: $errmsg"
- }
- }
-
- # Do some final clean up.
- # When testing an interpreter, we don't compile something and leave an
- # output file.
- if { ! ${keep} && ${dg-interpreter-batch-mode} == 0 } {
- catch "exec rm -f $output_file"
- }
-}
-
-
-#
-# Indicate that this test case is to be rerun several times. This
-# is useful if it is nondeterministic. This applies to rerunning the
-# test program only, not rebuilding it.
-# The embedded format is "{ dg-repetitions N }", where N is the number
-# of repetitions. It better be greater than zero.
-#
-proc dg-repetitions { line value } {
- upvar dg-repetitions repetitions
- set repetitions $value
-}
-
-
-# Prune any messages matching ARGS[1] (a regexp) from test output.
-proc dg-prune-output { args } {
- global additional_prunes
-
- if { [llength $args] != 2 } {
- error "[lindex $args 1]: need one argument"
- return
- }
-
- lappend additional_prunes [lindex $args 1]
-}
-
-set additional_prunes ""
diff --git a/libmudflap/testsuite/libmudflap.c++/c++frags.exp b/libmudflap/testsuite/libmudflap.c++/c++frags.exp
deleted file mode 100644
index 4e3d244fd1a..00000000000
--- a/libmudflap/testsuite/libmudflap.c++/c++frags.exp
+++ /dev/null
@@ -1,22 +0,0 @@
-global MUDFLAP_FLAGS
-set MUDFLAP_FLAGS [list {-O0} {-static} { -O} {-O2} {-O3}]
-
-libmudflap-init c++
-if {$cxx == "g++"} then {
- unsupported "g++ not found"
- return
-}
-
-dg-init
-
-global srcdir
-
-foreach flags $MUDFLAP_FLAGS {
- foreach srcfile [lsort [glob -nocomplain ${srcdir}/libmudflap.c++/*frag.cxx]] {
- set bsrc [file tail $srcfile]
- setenv MUDFLAP_OPTIONS "-viol-segv"
- dg-runtest $srcfile $flags "-fmudflap -lmudflap"
- }
-}
-
-dg-finish
diff --git a/libmudflap/testsuite/libmudflap.c++/ctors-1.cxx b/libmudflap/testsuite/libmudflap.c++/ctors-1.cxx
deleted file mode 100644
index 7717c805ca5..00000000000
--- a/libmudflap/testsuite/libmudflap.c++/ctors-1.cxx
+++ /dev/null
@@ -1,20 +0,0 @@
-#include <iostream>
-
-
-extern char k [];
-
-class foo
-{
- public:
- foo (char *m) { m [40] = 20; }
-};
-
-
-foo f1 (k);
-foo f2 (k);
-foo f3 (k);
-
-int main ()
-{
- return 0;
-}
diff --git a/libmudflap/testsuite/libmudflap.c++/ctors-2.cxx b/libmudflap/testsuite/libmudflap.c++/ctors-2.cxx
deleted file mode 100644
index c1a501979bf..00000000000
--- a/libmudflap/testsuite/libmudflap.c++/ctors-2.cxx
+++ /dev/null
@@ -1 +0,0 @@
-char k [500];
diff --git a/libmudflap/testsuite/libmudflap.c++/ctors.exp b/libmudflap/testsuite/libmudflap.c++/ctors.exp
deleted file mode 100644
index df7293dc91c..00000000000
--- a/libmudflap/testsuite/libmudflap.c++/ctors.exp
+++ /dev/null
@@ -1,48 +0,0 @@
-global MUDFLAP_FLAGS
-set MUDFLAP_FLAGS [list {-O0} {-static} {-O2} {-O3}]
-
-libmudflap-init c++
-if {$cxx == "g++"} then {
- unsupported "g++ not found"
- return
-}
-
-dg-init
-
-global srcdir subdir
-
-foreach flags $MUDFLAP_FLAGS {
- set l1 [libmudflap_target_compile "$srcdir/$subdir/ctors-1.cxx" "ctors-1.o" object {additional_flags=-fmudflap}]
- set test "ctors-1 compilation ${flags}"
- if [string match "*mudflap cannot track unknown size extern *k*" $l1] { pass $test } { fail $test }
-
- set l2 [libmudflap_target_compile "$srcdir/$subdir/ctors-2.cxx" "ctors-2.o" object {additional_flags=-fmudflap}]
- set test "ctors-2 compilation ${flags}"
- if [string match "" $l2] { pass $test } { fail $test }
-
- set l3 [libmudflap_target_compile "ctors-1.o ctors-2.o" "ctors-12.exe" executable {additional_flags=-fmudflap additional_flags=-lmudflap additional_flags=-lstdc++}]
- set test "ctors-12 linkage ${flags}"
- if [string match "" $l3] { pass $test } { fail $test }
-
- set l4 [libmudflap_target_compile "ctors-2.o ctors-1.o" "ctors-21.exe" executable {additional_flags=-fmudflap additional_flags=-lmudflap additional_flags=-lstdc++}]
- set test "ctors-21 linkage ${flags}"
- if [string match "" $l3] { pass $test } { fail $test }
-
- setenv MUDFLAP_OPTIONS "-viol-segv"
-
- remote_spawn host "./ctors-12.exe"
- set l5 [remote_wait host 10]
- set test "ctors-12 execution ${flags}"
- if {[lindex $l5 0] == 0} { pass $test } { fail $test }
-
- remote_spawn host "./ctors-21.exe"
- set l6 [remote_wait host 10]
- set test "ctors-21 execution ${flags}"
- if {[lindex $l6 0] == 0} { pass $test } { fail $test }
-
- foreach f [glob -nocomplain "ctors-*"] {
- remote_file build delete $f
- }
-}
-
-dg-finish
diff --git a/libmudflap/testsuite/libmudflap.c++/error1-frag.cxx b/libmudflap/testsuite/libmudflap.c++/error1-frag.cxx
deleted file mode 100644
index 8bfe8532830..00000000000
--- a/libmudflap/testsuite/libmudflap.c++/error1-frag.cxx
+++ /dev/null
@@ -1,5 +0,0 @@
-// PR 26789
-// { dg-do compile }
-
-struct A;
-A a; // { dg-error "incomplete" }
diff --git a/libmudflap/testsuite/libmudflap.c++/error2-frag.cxx b/libmudflap/testsuite/libmudflap.c++/error2-frag.cxx
deleted file mode 100644
index 0e89e117fbf..00000000000
--- a/libmudflap/testsuite/libmudflap.c++/error2-frag.cxx
+++ /dev/null
@@ -1,10 +0,0 @@
-// PR 26790
-// { dg-do compile }
-
-struct A;
-
-A foo() // { dg-error "incomplete" }
-{
- A a; // { dg-error "incomplete" }
- return a;
-}
diff --git a/libmudflap/testsuite/libmudflap.c++/fail24-frag.cxx b/libmudflap/testsuite/libmudflap.c++/fail24-frag.cxx
deleted file mode 100644
index e3467ddaf1a..00000000000
--- a/libmudflap/testsuite/libmudflap.c++/fail24-frag.cxx
+++ /dev/null
@@ -1,16 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-char zoo [10];
-
-int main ()
-{
-int i = strlen ("twelve") + strlen ("zero") + strlen ("seventeen");
-zoo[i] = 'a';
-return 0;
-}
-/* { dg-output "mudflap violation 1.*" } */
-/* { dg-output "Nearby object.*" } */
-/* { dg-output "mudflap object.*zoo.*static.*" } */
-/* { dg-do run { xfail *-*-* } } */
diff --git a/libmudflap/testsuite/libmudflap.c++/pass27-frag.cxx b/libmudflap/testsuite/libmudflap.c++/pass27-frag.cxx
deleted file mode 100644
index aca2ea3a3b6..00000000000
--- a/libmudflap/testsuite/libmudflap.c++/pass27-frag.cxx
+++ /dev/null
@@ -1,12 +0,0 @@
-class foo {
- char z [10];
-public:
- char *get_z () { return & this->z[0]; }
-};
-
-int main ()
-{
-foo x;
-x.get_z()[9] = 'a';
-return 0;
-}
diff --git a/libmudflap/testsuite/libmudflap.c++/pass28-frag.cxx b/libmudflap/testsuite/libmudflap.c++/pass28-frag.cxx
deleted file mode 100644
index 75e14ba1460..00000000000
--- a/libmudflap/testsuite/libmudflap.c++/pass28-frag.cxx
+++ /dev/null
@@ -1,20 +0,0 @@
-class foo {
- char z [10];
-public:
- virtual char *get_z () { return & this->z[0]; }
-};
-
-class bar: public foo {
- char q [20];
-public:
- char *get_z () { return & this->q[0]; }
-};
-
-int main () {
-foo *x = new bar ();
-
-x->get_z()[9] = 'a';
-
-delete x;
-return 0;
-}
diff --git a/libmudflap/testsuite/libmudflap.c++/pass31-frag.cxx b/libmudflap/testsuite/libmudflap.c++/pass31-frag.cxx
deleted file mode 100644
index 6c4b9f9a7f8..00000000000
--- a/libmudflap/testsuite/libmudflap.c++/pass31-frag.cxx
+++ /dev/null
@@ -1,12 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-char zoo [10];
-
-int main ()
-{
-int i = strlen ("eight") + strlen ("one");
-zoo[i] = 'a';
-return 0;
-}
diff --git a/libmudflap/testsuite/libmudflap.c++/pass41-frag.cxx b/libmudflap/testsuite/libmudflap.c++/pass41-frag.cxx
deleted file mode 100644
index 06896c7f6e7..00000000000
--- a/libmudflap/testsuite/libmudflap.c++/pass41-frag.cxx
+++ /dev/null
@@ -1,13 +0,0 @@
-#include <string>
-#include <iostream>
-
-int
-main (int argc, char *argv[])
-{
- std::string myStr = "Hello, World!";
- std::cout << myStr << std::endl;
- return 0;
-}
-
-/* Ignore a warning that is irrelevant to the purpose of this test. */
-/* { dg-prune-output ".*mudflap cannot track unknown size extern.*" } */
diff --git a/libmudflap/testsuite/libmudflap.c++/pass55-frag.cxx b/libmudflap/testsuite/libmudflap.c++/pass55-frag.cxx
deleted file mode 100644
index e83c12461e2..00000000000
--- a/libmudflap/testsuite/libmudflap.c++/pass55-frag.cxx
+++ /dev/null
@@ -1,7 +0,0 @@
-#include <vector>
-
-int main() {
- std::vector<int> v;
- v.push_back(1);
- return 0;
-}
diff --git a/libmudflap/testsuite/libmudflap.c++/pass57-frag.cxx b/libmudflap/testsuite/libmudflap.c++/pass57-frag.cxx
deleted file mode 100644
index 8be1a2d1113..00000000000
--- a/libmudflap/testsuite/libmudflap.c++/pass57-frag.cxx
+++ /dev/null
@@ -1,28 +0,0 @@
-#include <vector>
-#include <string>
-
-class fitscolumn
- {
- private:
- std::string name_, unit_;
- int i, t;
- public:
- fitscolumn (const std::string &nm, const std::string &un,int i1,int t1)
- : name_(nm), unit_(un), i(i1), t(t1){}
- };
-
-void init_bintab(std::vector<fitscolumn> & columns_)
-{
- char ttype[81], tunit[81], tform[81];
- long repc;
- int typecode;
- columns_.push_back (fitscolumn (ttype,tunit,1,typecode));
-}
-
-int main ()
-{
- return 0;
-}
-
-/* Ignore a warning that is irrelevant to the purpose of this test. */
-/* { dg-prune-output ".*mudflap cannot track unknown size extern.*" } */
diff --git a/libmudflap/testsuite/libmudflap.c++/pass58-frag.cxx b/libmudflap/testsuite/libmudflap.c++/pass58-frag.cxx
deleted file mode 100644
index 96da05fca07..00000000000
--- a/libmudflap/testsuite/libmudflap.c++/pass58-frag.cxx
+++ /dev/null
@@ -1,12 +0,0 @@
-// PR 19319
-struct k {
- int data;
- k(int j): data(j) {}
-};
-k make_k () { return k(1); }
-
-int main ()
-{
- k foo = make_k ();
- return 0;
-}
diff --git a/libmudflap/testsuite/libmudflap.c++/pass60-frag.cxx b/libmudflap/testsuite/libmudflap.c++/pass60-frag.cxx
deleted file mode 100644
index 35989d122b1..00000000000
--- a/libmudflap/testsuite/libmudflap.c++/pass60-frag.cxx
+++ /dev/null
@@ -1,13 +0,0 @@
-// PR 26442
-
-struct A
-{
- A();
-};
-
-int main()
-{
- if (0)
- A();
- return 0;
-}
diff --git a/libmudflap/testsuite/libmudflap.c++/pass61-frag.cxx b/libmudflap/testsuite/libmudflap.c++/pass61-frag.cxx
deleted file mode 100644
index 03046112c46..00000000000
--- a/libmudflap/testsuite/libmudflap.c++/pass61-frag.cxx
+++ /dev/null
@@ -1,20 +0,0 @@
-// PR c++/34619
-// { dg-do compile }
-
-template <typename> struct A
-{
- typedef int X;
- static const int N = 1;
-};
-
-template <typename T> struct B
-{
- typedef typename A <int [A <T>::N]>::X Y;
- template <typename U> B (Y, U) {}
-};
-
-int main ()
-{
-}
-
-B <int>b (0, 0);
diff --git a/libmudflap/testsuite/libmudflap.c++/pass66-frag.cxx b/libmudflap/testsuite/libmudflap.c++/pass66-frag.cxx
deleted file mode 100644
index 989c7ca6f1c..00000000000
--- a/libmudflap/testsuite/libmudflap.c++/pass66-frag.cxx
+++ /dev/null
@@ -1,17 +0,0 @@
-// PR c++/37568
-// { dg-do compile }
-// { dg-options "-fmudflap -O" }
-
-struct A
-{
- int i;
-};
-
-A
-foo ()
-{
- A a = { 1 };
- return a;
-}
-
-A a = foo ();
diff --git a/libmudflap/testsuite/libmudflap.c/cfrags.exp b/libmudflap/testsuite/libmudflap.c/cfrags.exp
deleted file mode 100644
index ebd67c4ff72..00000000000
--- a/libmudflap/testsuite/libmudflap.c/cfrags.exp
+++ /dev/null
@@ -1,21 +0,0 @@
-global MUDFLAP_FLAGS
-set MUDFLAP_FLAGS [list {-O0} {-static} {-O2} {-O3}]
-
-libmudflap-init c
-
-dg-init
-
-global srcdir
-foreach flags $MUDFLAP_FLAGS {
- foreach srcfile [lsort [glob -nocomplain \
- ${srcdir}/libmudflap.c/*frag.c \
- ${srcdir}/libmudflap.c/heap*.c \
- ${srcdir}/libmudflap.c/hook*.c \
- ${srcdir}/libmudflap.c/pass*.c]] {
- set bsrc [file tail $srcfile]
- setenv MUDFLAP_OPTIONS "-viol-segv"
- dg-runtest $srcfile $flags "-fmudflap -lmudflap"
- }
-}
-
-dg-finish
diff --git a/libmudflap/testsuite/libmudflap.c/externs-1.c b/libmudflap/testsuite/libmudflap.c/externs-1.c
deleted file mode 100644
index 028f5eb5a48..00000000000
--- a/libmudflap/testsuite/libmudflap.c/externs-1.c
+++ /dev/null
@@ -1,16 +0,0 @@
-typedef struct { char *name; } dummy;
-extern dummy d[];
-
-int
-main (void)
-{
- dummy *pd = d;
-
- while (pd->name)
- {
- printf ("%s\n", pd->name);
- pd++;
- }
-
- return 0;
-}
diff --git a/libmudflap/testsuite/libmudflap.c/externs-2.c b/libmudflap/testsuite/libmudflap.c/externs-2.c
deleted file mode 100644
index cecf6253a6a..00000000000
--- a/libmudflap/testsuite/libmudflap.c/externs-2.c
+++ /dev/null
@@ -1,2 +0,0 @@
-typedef struct { char *name; } dummy;
-dummy d[] = { {"a"}, {0} };
diff --git a/libmudflap/testsuite/libmudflap.c/externs.exp b/libmudflap/testsuite/libmudflap.c/externs.exp
deleted file mode 100644
index 5a0297f2ed4..00000000000
--- a/libmudflap/testsuite/libmudflap.c/externs.exp
+++ /dev/null
@@ -1,43 +0,0 @@
-global MUDFLAP_FLAGS
-set MUDFLAP_FLAGS [list {-O0} {-static} {-O2} {-O3}]
-
-libmudflap-init c
-dg-init
-
-global srcdir subdir
-
-foreach flags $MUDFLAP_FLAGS {
- set l1 [libmudflap_target_compile "$srcdir/$subdir/externs-1.c" "externs-1.o" object {additional_flags=-fmudflap}]
- set test "externs-1 compilation ${flags}"
- if [string match "*mudflap cannot track unknown size extern *d*" $l1] { pass $test } { fail $test }
-
- set l2 [libmudflap_target_compile "$srcdir/$subdir/externs-2.c" "externs-2.o" object {additional_flags=-fmudflap}]
- set test "externs-2 compilation ${flags}"
- if [string match "" $l2] { pass $test } { fail $test }
-
- set l3 [libmudflap_target_compile "externs-1.o externs-2.o" "externs-12.exe" executable {additional_flags=-fmudflap additional_flags=-lmudflap}]
- set test "externs-12 linkage ${flags}"
- if [string match "" $l3] { pass $test } { fail $test }
-
- set l4 [libmudflap_target_compile "externs-2.o externs-1.o" "externs-21.exe" executable {additional_flags=-fmudflap additional_flags=-lmudflap}]
- set test "externs-21 linkage ${flags}"
- if [string match "" $l3] { pass $test } { fail $test }
-
- setenv MUDFLAP_OPTIONS "-viol-segv"
-
- remote_spawn host "./externs-12.exe"
- set l5 [remote_wait host 10]
- set test "externs-12 execution ${flags}"
- if {[lindex $l5 0] == 0} { pass $test } { fail $test }
-
- remote_spawn host "./externs-21.exe"
- set l6 [remote_wait host 10]
- set test "externs-21 execution ${flags}"
- if {[lindex $l6 0] == 0} { pass $test } { fail $test }
-
- foreach f [glob -nocomplain "externs-*"] {
- remote_file build delete $f
- }
-}
-
-dg-finish
diff --git a/libmudflap/testsuite/libmudflap.c/fail1-frag.c b/libmudflap/testsuite/libmudflap.c/fail1-frag.c
deleted file mode 100644
index 1e48fff8771..00000000000
--- a/libmudflap/testsuite/libmudflap.c/fail1-frag.c
+++ /dev/null
@@ -1,13 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-int main ()
-{
-volatile int foo [10];
-foo[10] = 0;
-return 0;
-}
-/* { dg-output "mudflap violation 1.*" } */
-/* { dg-output "Nearby object 1.*" } */
-/* { dg-output "mudflap object.*.main. foo.*" } */
-/* { dg-do run { xfail *-*-* } } */
diff --git a/libmudflap/testsuite/libmudflap.c/fail10-frag.c b/libmudflap/testsuite/libmudflap.c/fail10-frag.c
deleted file mode 100644
index db135d5c451..00000000000
--- a/libmudflap/testsuite/libmudflap.c/fail10-frag.c
+++ /dev/null
@@ -1,16 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-int main ()
-{
-volatile int foo[10];
-int sz = sizeof (int);
-
-volatile char *bar = (char *)foo;
-bar [sz * 10] = 0;
-return 0;
-}
-/* { dg-output "mudflap violation 1.*" } */
-/* { dg-output "Nearby object 1.*" } */
-/* { dg-output "mudflap object.*.main. foo.*" } */
-/* { dg-do run { xfail *-*-* } } */
diff --git a/libmudflap/testsuite/libmudflap.c/fail11-frag.c b/libmudflap/testsuite/libmudflap.c/fail11-frag.c
deleted file mode 100644
index 8cd4a5329de..00000000000
--- a/libmudflap/testsuite/libmudflap.c/fail11-frag.c
+++ /dev/null
@@ -1,20 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-char *y;
-int main ()
-{
-int i = 10;
-char *x = (char *) malloc (i * sizeof (char));
-y = x;
-while (i--)
-{
- ++x;
- *x = i;
-}
-return 0;
-}
-/* { dg-output "mudflap violation 1.*" } */
-/* { dg-output "Nearby object 1.*" } */
-/* { dg-output "mudflap object.*malloc region.*" } */
-/* { dg-do run { xfail *-*-* } } */
diff --git a/libmudflap/testsuite/libmudflap.c/fail12-frag.c b/libmudflap/testsuite/libmudflap.c/fail12-frag.c
deleted file mode 100644
index 7491fed7c1f..00000000000
--- a/libmudflap/testsuite/libmudflap.c/fail12-frag.c
+++ /dev/null
@@ -1,20 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-int *y;
-int main ()
-{
-int i = 10;
-int *x = (int *) malloc (i * sizeof (int));
-y = x;
-while (i--)
-{
- ++x;
- *x = i;
-}
-return 0;
-}
-/* { dg-output "mudflap violation 1.*" } */
-/* { dg-output "Nearby object 1.*" } */
-/* { dg-output "mudflap object.*malloc region.*" } */
-/* { dg-do run { xfail *-*-* } } */
diff --git a/libmudflap/testsuite/libmudflap.c/fail13-frag.c b/libmudflap/testsuite/libmudflap.c/fail13-frag.c
deleted file mode 100644
index 9fd3e255712..00000000000
--- a/libmudflap/testsuite/libmudflap.c/fail13-frag.c
+++ /dev/null
@@ -1,26 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-int main ()
-{
-struct a {
- int x;
- int y;
- char z;
-};
-
-struct b {
- int x;
- int y;
-};
-
-struct b k;
-
-(*((volatile struct a *) &k)).z = 'q';
-
-return 0;
-}
-/* { dg-output "mudflap violation 1..check/write.*" } */
-/* { dg-output "Nearby object 1.*" } */
-/* { dg-output "mudflap object.*.main. k.*" } */
-/* { dg-do run { xfail *-*-* } } */
diff --git a/libmudflap/testsuite/libmudflap.c/fail14-frag.c b/libmudflap/testsuite/libmudflap.c/fail14-frag.c
deleted file mode 100644
index e66cc94c49b..00000000000
--- a/libmudflap/testsuite/libmudflap.c/fail14-frag.c
+++ /dev/null
@@ -1,29 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-int main ()
-{
-struct a {
- int x;
- int y;
- char z;
-};
-
-struct b {
- int x;
- int y;
-};
-
-volatile struct b k;
-volatile struct a *p;
-
-p = (struct a*) &k;
-
-p->z = 'q';
-
-return 0;
-}
-/* { dg-output "mudflap violation 1.*" } */
-/* { dg-output "Nearby object 1.*" } */
-/* { dg-output "mudflap object.*.main. k.*" } */
-/* { dg-do run { xfail *-*-* } } */
diff --git a/libmudflap/testsuite/libmudflap.c/fail15-frag.c b/libmudflap/testsuite/libmudflap.c/fail15-frag.c
deleted file mode 100644
index 5d7ae744973..00000000000
--- a/libmudflap/testsuite/libmudflap.c/fail15-frag.c
+++ /dev/null
@@ -1,27 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-int main ()
-{
-struct base {
- int basic;
-};
-
-struct derived {
- struct base common;
- char extra;
-};
-
-volatile struct base b;
-volatile struct base *bp;
-
-bp = (struct base *)&b;
-
-bp->basic = 10;
-((struct derived volatile *)bp)->extra = 'x';
-return 0;
-}
-/* { dg-output "mudflap violation 1.*" } */
-/* { dg-output "Nearby object 1.*" } */
-/* { dg-output "mudflap object.*.main. b.*" } */
-/* { dg-do run { xfail *-*-* } } */
diff --git a/libmudflap/testsuite/libmudflap.c/fail16-frag.c b/libmudflap/testsuite/libmudflap.c/fail16-frag.c
deleted file mode 100644
index 6ac6187e2ad..00000000000
--- a/libmudflap/testsuite/libmudflap.c/fail16-frag.c
+++ /dev/null
@@ -1,27 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-void *p;
-int main ()
-{
-struct base {
- int basic;
-};
-
-struct derived {
- struct base common;
- char extra;
-};
-
-struct base *bp;
-
-bp = (struct base *) malloc (sizeof (struct base));;
-p = bp;
-bp->basic = 10;
-((struct derived *)bp)->extra = 'x';
-return 0;
-}
-/* { dg-output "mudflap violation 1.*" } */
-/* { dg-output "Nearby object 1.*" } */
-/* { dg-output "mudflap object.*.malloc region.*" } */
-/* { dg-do run { xfail *-*-* } } */
diff --git a/libmudflap/testsuite/libmudflap.c/fail17-frag.c b/libmudflap/testsuite/libmudflap.c/fail17-frag.c
deleted file mode 100644
index 5af67f13858..00000000000
--- a/libmudflap/testsuite/libmudflap.c/fail17-frag.c
+++ /dev/null
@@ -1,18 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-int main ()
-{
-
-char * x;
-int foo;
-x = (char *) malloc (10);
-strcpy (x, "123456789");
-foo = strlen (x+10);
-x [foo] = 1; /* we just just use foo to force execution of strlen */
-return 0;
-}
-/* { dg-output "mudflap violation 1.*" } */
-/* { dg-output "Nearby object 1.*" } */
-/* { dg-output "mudflap object.*.malloc region.*" } */
-/* { dg-do run { xfail *-*-* } } */
diff --git a/libmudflap/testsuite/libmudflap.c/fail18-frag.c b/libmudflap/testsuite/libmudflap.c/fail18-frag.c
deleted file mode 100644
index a7b62ddb7c7..00000000000
--- a/libmudflap/testsuite/libmudflap.c/fail18-frag.c
+++ /dev/null
@@ -1,16 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-int main ()
-{
-/* One cannot redeclare __mf_lc_mask in proper C from instrumented
- code, because of the way the instrumentation code emits its decls. */
-extern unsigned foo __asm__ ("__mf_lc_mask");
-unsigned * volatile bar = &foo;
-*bar = 4;
-return 0;
-}
-/* { dg-output "mudflap violation 1.*" } */
-/* { dg-output "Nearby object 1.*" } */
-/* { dg-output "mudflap object.*.__mf_lc_mask.*no-access.*" } */
-/* { dg-do run { xfail *-*-* } } */
diff --git a/libmudflap/testsuite/libmudflap.c/fail19-frag.c b/libmudflap/testsuite/libmudflap.c/fail19-frag.c
deleted file mode 100644
index 7e446b40503..00000000000
--- a/libmudflap/testsuite/libmudflap.c/fail19-frag.c
+++ /dev/null
@@ -1,18 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-int main ()
-{
-struct foo {
- int bar [10];
-};
-
-struct foo *k = (struct foo *) malloc (2 * sizeof(int));
-k->bar[5] = 9;
-free (k);
-return 0;
-}
-/* { dg-output "mudflap violation 1.*" } */
-/* { dg-output "Nearby object 1.*" } */
-/* { dg-output "mudflap object.*.malloc region.*" } */
-/* { dg-do run { xfail *-*-* } } */
diff --git a/libmudflap/testsuite/libmudflap.c/fail2-frag.c b/libmudflap/testsuite/libmudflap.c/fail2-frag.c
deleted file mode 100644
index 7672e60c602..00000000000
--- a/libmudflap/testsuite/libmudflap.c/fail2-frag.c
+++ /dev/null
@@ -1,13 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-int main ()
-{
-volatile int foo [10][10];
-foo[10][0] = 0;
-return 0;
-}
-/* { dg-output "mudflap violation 1.*" } */
-/* { dg-output "Nearby object 1.*" } */
-/* { dg-output "mudflap object.*.main. foo.*" } */
-/* { dg-do run { xfail *-*-* } } */
diff --git a/libmudflap/testsuite/libmudflap.c/fail20-frag.c b/libmudflap/testsuite/libmudflap.c/fail20-frag.c
deleted file mode 100644
index 0dd8bb7f983..00000000000
--- a/libmudflap/testsuite/libmudflap.c/fail20-frag.c
+++ /dev/null
@@ -1,13 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-int main ()
-{
-volatile char *p = (char *) 0;
-*p = 5;
-return 0;
-}
-/* { dg-output "mudflap violation 1.*" } */
-/* { dg-output "Nearby object 1.*" } */
-/* { dg-output "mudflap object.*.NULL.*" } */
-/* { dg-do run { xfail *-*-* } } */
diff --git a/libmudflap/testsuite/libmudflap.c/fail21-frag.c b/libmudflap/testsuite/libmudflap.c/fail21-frag.c
deleted file mode 100644
index 4ab4a09f3b0..00000000000
--- a/libmudflap/testsuite/libmudflap.c/fail21-frag.c
+++ /dev/null
@@ -1,18 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-int main ()
-{
- int *bar = (int *) malloc (sizeof (int));
-/* Make an access here to get &foo into the lookup cache. */
-*bar = 5;
-__mf_watch (bar, sizeof(int));
-/* This access should trigger the watch violation. */
-*bar = 10;
-/* NOTREACHED */
-return 0;
-}
-/* { dg-output "mudflap violation 1.*watch.*" } */
-/* { dg-output "Nearby object 1.*" } */
-/* { dg-output "mudflap object.*malloc region.*" } */
-/* { dg-do run { xfail *-*-* } } */
diff --git a/libmudflap/testsuite/libmudflap.c/fail22-frag.c b/libmudflap/testsuite/libmudflap.c/fail22-frag.c
deleted file mode 100644
index 7dd7103d359..00000000000
--- a/libmudflap/testsuite/libmudflap.c/fail22-frag.c
+++ /dev/null
@@ -1,17 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-int main ()
-{
-struct boo { int a; };
-int c;
-struct boo *b = malloc (sizeof (struct boo));
-__mf_set_options ("-check-initialization");
-c = b->a;
-(void) malloc (c); /* some dummy use of c */
-return 0;
-}
-/* { dg-output "mudflap violation 1.*" } */
-/* { dg-output "Nearby object 1.*" } */
-/* { dg-output "mudflap object.*.malloc region.*1r/0w.*" } */
-/* { dg-do run { xfail *-*-* } } */
diff --git a/libmudflap/testsuite/libmudflap.c/fail23-frag.c b/libmudflap/testsuite/libmudflap.c/fail23-frag.c
deleted file mode 100644
index bb1b52ec7e0..00000000000
--- a/libmudflap/testsuite/libmudflap.c/fail23-frag.c
+++ /dev/null
@@ -1,16 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-char zoo [10];
-
-int main ()
-{
-int i = strlen ("012345") + strlen ("6789") + strlen ("01"); /* 11 */
-zoo[i] = 'a';
-return 0;
-}
-/* { dg-output "mudflap violation 1.*" } */
-/* { dg-output "Nearby object.*" } */
-/* { dg-output "mudflap object.*zoo.*static.*" } */
-/* { dg-do run { xfail *-*-* } } */
diff --git a/libmudflap/testsuite/libmudflap.c/fail25-frag.c b/libmudflap/testsuite/libmudflap.c/fail25-frag.c
deleted file mode 100644
index acac5236b42..00000000000
--- a/libmudflap/testsuite/libmudflap.c/fail25-frag.c
+++ /dev/null
@@ -1,18 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-int main ()
-{
-char *foo;
-char *bar;
-__mf_set_options ("-check-initialization");
-foo = (char *)malloc (10);
-bar = (char *)malloc (10);
-/* bar[2] = 'z'; */ /* don't touch memcpy source */
-memcpy(foo+1, bar+1, 9);
-return 0;
-}
-/* { dg-output "mudflap violation 1.*check.read.*memcpy source.*" } */
-/* { dg-output "Nearby object.*" } */
-/* { dg-output "mudflap object.*malloc region.*alloc time.*" } */
-/* { dg-do run { xfail *-*-* } } */
diff --git a/libmudflap/testsuite/libmudflap.c/fail26-frag.c b/libmudflap/testsuite/libmudflap.c/fail26-frag.c
deleted file mode 100644
index 88484d6adc4..00000000000
--- a/libmudflap/testsuite/libmudflap.c/fail26-frag.c
+++ /dev/null
@@ -1,24 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-int main ()
-{
-char *foo;
-
-__mf_set_options ("-check-initialization");
-foo = (char *)malloc (1);
-
-/* These two operations each expand to a read-modify-write.
- * Even though the end result is that every bit of foo[0] is
- * eventually written to deterministically, the first read
- * triggers an uninit error. Ideally, it shouldn't, so this
- * should be treated more like a regular XFAIL. */
-foo[0] &= 0xfe;
-foo[0] |= 0x01;
-
-return foo[0];
-}
-/* { dg-output "mudflap violation 1.*" } */
-/* { dg-output "Nearby object.*" } */
-/* { dg-output "mudflap object.*malloc region.*1r/0w.*" } */
-/* { dg-do run { xfail *-*-* } } */
diff --git a/libmudflap/testsuite/libmudflap.c/fail27-frag.c b/libmudflap/testsuite/libmudflap.c/fail27-frag.c
deleted file mode 100644
index 547c5e7a6ad..00000000000
--- a/libmudflap/testsuite/libmudflap.c/fail27-frag.c
+++ /dev/null
@@ -1,24 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-char volatile *
-__attribute__((noinline))
-foo (unsigned i)
-{
- char volatile buffer[10];
- char volatile *k = i ? & buffer[i] : NULL; /* defeat addr-of-local-returned warning */
- return k;
-}
-
-int main ()
-{
-char volatile *f = foo (5);
-f[0] = 'b';
-
-return 0;
-}
-/* { dg-output "mudflap violation 1.*" } */
-/* { dg-output "Nearby object.*" } */
-/* { dg-output "mudflap dead object.*buffer.*alloc.*dealloc" } */
-/* { dg-do run { xfail *-*-* } } */
diff --git a/libmudflap/testsuite/libmudflap.c/fail28-frag.c b/libmudflap/testsuite/libmudflap.c/fail28-frag.c
deleted file mode 100644
index 7d61c57f34b..00000000000
--- a/libmudflap/testsuite/libmudflap.c/fail28-frag.c
+++ /dev/null
@@ -1,18 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-int foo (int *u, int i)
-{
- return u[i]; /* this dereference should be instrumented */
-}
-
-int main ()
-{
-int *k = malloc (6);
-return foo (k, 8);
-}
-/* { dg-output "mudflap violation 1.*" } */
-/* { dg-output "Nearby object.*" } */
-/* { dg-output "mudflap object.*malloc region.*alloc" } */
-/* { dg-do run { xfail *-*-* } } */
diff --git a/libmudflap/testsuite/libmudflap.c/fail29-frag.c b/libmudflap/testsuite/libmudflap.c/fail29-frag.c
deleted file mode 100644
index 2024064dc73..00000000000
--- a/libmudflap/testsuite/libmudflap.c/fail29-frag.c
+++ /dev/null
@@ -1,17 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-
-int foo (int u[10])
-{
- return u[8]; /* this dereference should be instrumented */
-}
-
-int main ()
-{
-int *k = malloc (6);
-return foo (k);
-}
-/* { dg-output "mudflap violation 1.*" } */
-/* { dg-output "Nearby object.*" } */
-/* { dg-output "mudflap object.*malloc region.*alloc" } */
-/* { dg-do run { xfail *-*-* } } */
diff --git a/libmudflap/testsuite/libmudflap.c/fail3-frag.c b/libmudflap/testsuite/libmudflap.c/fail3-frag.c
deleted file mode 100644
index 98c1dbae165..00000000000
--- a/libmudflap/testsuite/libmudflap.c/fail3-frag.c
+++ /dev/null
@@ -1,13 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-int main ()
-{
-volatile int foo [10][10][10];
-foo[9][10][0] = 0;
-return 0;
-}
-/* { dg-output "mudflap violation 1.*" } */
-/* { dg-output "Nearby object 1.*" } */
-/* { dg-output "mudflap object.*.main. foo.*" } */
-/* { dg-do run { xfail *-*-* } } */
diff --git a/libmudflap/testsuite/libmudflap.c/fail30-frag.c b/libmudflap/testsuite/libmudflap.c/fail30-frag.c
deleted file mode 100644
index 8bfea61cbb2..00000000000
--- a/libmudflap/testsuite/libmudflap.c/fail30-frag.c
+++ /dev/null
@@ -1,18 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-
-int foo (int u)
-{
- return u*u;
-}
-
-int main ()
-{
-int *k = malloc(5);
-int j = foo (k[8]); /* this call argument should be instrumented */
-return j;
-}
-/* { dg-output "mudflap violation 1.*" } */
-/* { dg-output "Nearby object.*" } */
-/* { dg-output "mudflap object.*malloc region.*alloc" } */
-/* { dg-do run { xfail *-*-* } } */
diff --git a/libmudflap/testsuite/libmudflap.c/fail31-frag.c b/libmudflap/testsuite/libmudflap.c/fail31-frag.c
deleted file mode 100644
index 138c8ccba1c..00000000000
--- a/libmudflap/testsuite/libmudflap.c/fail31-frag.c
+++ /dev/null
@@ -1,24 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-
-extern int h (int i, int j);
-
-int main ()
-{
- int z = h (4, 10);
- return 0;
-}
-int *p;
-__attribute__((noinline))
-int h (int i, int j)
-{
- int k[i];
- k[j] = i;
- p = k;
- return j;
-}
-
-/* { dg-output "mudflap violation 1.*" } */
-/* { dg-output "Nearby object.*" } */
-/* { dg-output "mudflap object.*\(h\).*k" } */
-/* { dg-do run { xfail *-*-* } } */
diff --git a/libmudflap/testsuite/libmudflap.c/fail32-frag.c b/libmudflap/testsuite/libmudflap.c/fail32-frag.c
deleted file mode 100644
index 2a38237b678..00000000000
--- a/libmudflap/testsuite/libmudflap.c/fail32-frag.c
+++ /dev/null
@@ -1,16 +0,0 @@
-void foo (int k)
-{
- volatile int *b = & k;
- b++;
- *b = 5;
-}
-
-int main ()
-{
- foo (5);
- return 0;
-}
-/* { dg-output "mudflap violation 1.*" } */
-/* { dg-output "Nearby object.*" } */
-/* { dg-output "mudflap object.*k" } */
-/* { dg-do run { xfail *-*-* } } */
diff --git a/libmudflap/testsuite/libmudflap.c/fail33-frag.c b/libmudflap/testsuite/libmudflap.c/fail33-frag.c
deleted file mode 100644
index ac7c617a4eb..00000000000
--- a/libmudflap/testsuite/libmudflap.c/fail33-frag.c
+++ /dev/null
@@ -1,25 +0,0 @@
-#include <stdlib.h>
-
-#define SIZE 16
-
-char b[SIZE];
-char a[SIZE];
-
-int main ()
-{
- int i, j=0, k;
- int a_before_b = (& a[0] < & b[0]);
- /* Rather than iterating linearly, which would allow loop unrolling
- and mapping to pointer manipulation, we traverse the "joined"
- arrays in some random order. */
- for (i=0; i<SIZE*2; i++)
- {
- k = rand() % (SIZE*2);
- j += (a_before_b ? a[k] : b[k]);
- }
- return j;
-}
-/* { dg-output "mudflap violation 1.*" } */
-/* { dg-output "Nearby object.*" } */
-/* { dg-output "mudflap object.*\[ab\]" } */
-/* { dg-do run { xfail *-*-* } } */
diff --git a/libmudflap/testsuite/libmudflap.c/fail34-frag.c b/libmudflap/testsuite/libmudflap.c/fail34-frag.c
deleted file mode 100644
index f6572b019a4..00000000000
--- a/libmudflap/testsuite/libmudflap.c/fail34-frag.c
+++ /dev/null
@@ -1,22 +0,0 @@
-#include <stdlib.h>
-
-struct s
-{
- int a1[4];
-};
-
-struct s a, b;
-int idx = 7; /* should pass to the next object */
-
-int
-main ()
-{
- int i, j=0;
- int a_before_b = (& a < & b);
- j = (a_before_b ? a.a1[idx] : b.a1[idx]);
- return j;
-}
-/* { dg-output "mudflap violation 1.*" } */
-/* { dg-output "Nearby object.*" } */
-/* { dg-output "mudflap object.*\[ab\]" } */
-/* { dg-do run { xfail *-*-* } } */
diff --git a/libmudflap/testsuite/libmudflap.c/fail35-frag.c b/libmudflap/testsuite/libmudflap.c/fail35-frag.c
deleted file mode 100644
index 101fe293b2b..00000000000
--- a/libmudflap/testsuite/libmudflap.c/fail35-frag.c
+++ /dev/null
@@ -1,23 +0,0 @@
-#include <stdlib.h>
-
-struct k
-{
- int p;
- struct {
- int m;
- } q;
-};
-
-int
-main ()
-{
- volatile struct k *l = malloc (sizeof (int)); /* make it only big enough for k.p */
- /* Confirm that we instrument this nested construct
- COMPONENT_REF(COMPONENT_REF(INDIRECT_REF)). */
- l->q.m = 5;
- return 0;
-}
-/* { dg-output "mudflap violation 1.*" } */
-/* { dg-output "Nearby object.*" } */
-/* { dg-output "mudflap object.*" } */
-/* { dg-do run { xfail *-*-* } } */
diff --git a/libmudflap/testsuite/libmudflap.c/fail36-frag.c b/libmudflap/testsuite/libmudflap.c/fail36-frag.c
deleted file mode 100644
index af6851c1d23..00000000000
--- a/libmudflap/testsuite/libmudflap.c/fail36-frag.c
+++ /dev/null
@@ -1,23 +0,0 @@
-#include <stdlib.h>
-
-struct k
-{
- int p;
- struct {
- int m : 31;
- } q;
-};
-
-int
-main ()
-{
- volatile struct k *l = malloc (sizeof (int)); /* make it only big enough for k.p */
- /* Confirm that we instrument this nested construct
- BIT_FIELD_REF(COMPONENT_REF(INDIRECT_REF)). */
- l->q.m = 5;
- return 0;
-}
-/* { dg-output "mudflap violation 1.*" } */
-/* { dg-output "Nearby object.*" } */
-/* { dg-output "mudflap object.*" } */
-/* { dg-do run { xfail *-*-* } } */
diff --git a/libmudflap/testsuite/libmudflap.c/fail37-frag.c b/libmudflap/testsuite/libmudflap.c/fail37-frag.c
deleted file mode 100644
index 38dbde56a81..00000000000
--- a/libmudflap/testsuite/libmudflap.c/fail37-frag.c
+++ /dev/null
@@ -1,26 +0,0 @@
-typedef struct
-{
- short f : 3;
-} small;
-
-struct
-{
- int i;
- small s[4];
-} x;
-
-main ()
-{
- int i;
- for (i = 0; i < 5; i++)
- {
- /* Optimization barrier. Prevent gcc from seeing the undefined behavior. */
- __asm ("" : "+r" (i));
- x.s[i].f = 0;
- }
- exit (0);
-}
-/* { dg-output "mudflap violation 1.*" } */
-/* { dg-output "Nearby object.*" } */
-/* { dg-output "mudflap object.* x.*" } */
-/* { dg-do run { xfail *-*-* } } */
diff --git a/libmudflap/testsuite/libmudflap.c/fail38-frag.c b/libmudflap/testsuite/libmudflap.c/fail38-frag.c
deleted file mode 100644
index 9667e213418..00000000000
--- a/libmudflap/testsuite/libmudflap.c/fail38-frag.c
+++ /dev/null
@@ -1,29 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-int main ()
-{
-struct a {
- int x;
- int y;
- int z : 10;
-};
-
-struct b {
- int x;
- int y;
-};
-
-volatile struct b k;
-volatile struct a *p;
-
-p = (struct a*) &k;
-
-p->z = 'q';
-
-return 0;
-}
-/* { dg-output "mudflap violation 1.*" } */
-/* { dg-output "Nearby object 1.*" } */
-/* { dg-output "mudflap object.*.main. k.*" } */
-/* { dg-do run { xfail *-*-* } } */
diff --git a/libmudflap/testsuite/libmudflap.c/fail39-frag.c b/libmudflap/testsuite/libmudflap.c/fail39-frag.c
deleted file mode 100644
index 4e74ea5cd5e..00000000000
--- a/libmudflap/testsuite/libmudflap.c/fail39-frag.c
+++ /dev/null
@@ -1,20 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-
-int main ()
-{
- volatile int *k = (int *) malloc (sizeof (int));
- volatile int l;
- if (k == NULL) abort ();
- *k = 5;
- free ((void *) k);
- __mf_set_options ("-ignore-reads");
- l = *k; /* Should not trip, even though memory region just freed. */
- __mf_set_options ("-no-ignore-reads");
- l = *k; /* Should trip now. */
- return 0;
-}
-/* { dg-output "mudflap violation 1.*check/read.*" } */
-/* { dg-output "Nearby object 1.*" } */
-/* { dg-output "mudflap dead object.*malloc region.*" } */
-/* { dg-do run { xfail *-*-* } } */
diff --git a/libmudflap/testsuite/libmudflap.c/fail4-frag.c b/libmudflap/testsuite/libmudflap.c/fail4-frag.c
deleted file mode 100644
index a3423e6c36b..00000000000
--- a/libmudflap/testsuite/libmudflap.c/fail4-frag.c
+++ /dev/null
@@ -1,13 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-int main ()
-{
-char foo [10];
-strcpy(foo, "1234567890");
-return 0;
-}
-/* { dg-output "mudflap violation 1.*" } */
-/* { dg-output "Nearby object 1.*" } */
-/* { dg-output "mudflap object.*.main. foo.*" } */
-/* { dg-do run { xfail *-*-* } } */
diff --git a/libmudflap/testsuite/libmudflap.c/fail40-frag.c b/libmudflap/testsuite/libmudflap.c/fail40-frag.c
deleted file mode 100644
index fbeb6fd21d3..00000000000
--- a/libmudflap/testsuite/libmudflap.c/fail40-frag.c
+++ /dev/null
@@ -1,59 +0,0 @@
-/* Test proper lookup-uncaching of large objects */
-#include "../config.h"
-
-#include <unistd.h>
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-#ifdef HAVE_SYS_MMAN_H
-#include <sys/mman.h>
-#endif
-
-int main ()
-{
-#ifndef MAP_ANONYMOUS
-#define MAP_ANONYMOUS MAP_ANON
-#endif
-#ifndef MAP_FAILED
-#define MAP_FAILED ((void *)-1)
-#endif
-#ifdef HAVE_MMAP
- volatile unsigned char *p;
- unsigned num = getpagesize ();
- unsigned i;
- int rc;
-
- /* Get a bit of usable address space. We really want an 2**N+1-sized object,
- so the low/high addresses wrap when hashed into the lookup cache. So we
- will manually unregister the entire mmap, then re-register a slice. */
- p = mmap (NULL, num, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
- if (p == MAP_FAILED)
- return 1;
- /* Now unregister it, as if munmap was called. But don't actually munmap, so
- we can write into the memory. */
- __mf_unregister ((void *) p, num, __MF_TYPE_HEAP_I);
-
- /* Now register it under a slightly inflated, 2**N+1 size. */
- __mf_register ((void *) p, num+1, __MF_TYPE_HEAP_I, "fake mmap registration");
-
- /* Traverse array to ensure that entire lookup cache is made to point at it. */
- for (i=0; i<num; i++)
- p[i] = 0;
-
- /* Unregister it. This should clear the entire lookup cache, even though
- hash(low) == hash (high) (and probably == 0) */
- __mf_unregister ((void *) p, num+1, __MF_TYPE_HEAP_I);
-
- /* Now touch the middle portion of the ex-array. If the lookup cache was
- well and truly cleaned, then this access should trap. */
- p[num/2] = 1;
-
- return 0;
-#else
- return 1;
-#endif
-}
-/* { dg-output "mudflap violation 1.*check/write.*" } */
-/* { dg-output "Nearby object 1.*" } */
-/* { dg-output "mudflap dead object.*fake mmap registration.*" } */
-/* { dg-do run { xfail *-*-* } } */
diff --git a/libmudflap/testsuite/libmudflap.c/fail5-frag.c b/libmudflap/testsuite/libmudflap.c/fail5-frag.c
deleted file mode 100644
index a08569fe773..00000000000
--- a/libmudflap/testsuite/libmudflap.c/fail5-frag.c
+++ /dev/null
@@ -1,14 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-int main ()
-{
-char foo [15];
-char bar [10];
-memcpy(foo, bar, 11);
-return 0;
-}
-/* { dg-output "mudflap violation 1.*" } */
-/* { dg-output "Nearby object 1.*" } */
-/* { dg-output "mudflap object.*.main. bar.*" } */
-/* { dg-do run { xfail *-*-* } } */
diff --git a/libmudflap/testsuite/libmudflap.c/fail6-frag.c b/libmudflap/testsuite/libmudflap.c/fail6-frag.c
deleted file mode 100644
index 1904a88711a..00000000000
--- a/libmudflap/testsuite/libmudflap.c/fail6-frag.c
+++ /dev/null
@@ -1,17 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-int main ()
-{
-char *foo;
-char *bar;
-foo = (char *)malloc (10);
-bar = (char *)malloc (15);
-
-memcpy(foo, bar, 11);
-return 0;
-}
-/* { dg-output "mudflap violation 1.*" } */
-/* { dg-output "Nearby object 1.*" } */
-/* { dg-output "mudflap object.*malloc region.*" } */
-/* { dg-do run { xfail *-*-* } } */
diff --git a/libmudflap/testsuite/libmudflap.c/fail68-frag.c b/libmudflap/testsuite/libmudflap.c/fail68-frag.c
deleted file mode 100644
index 7b2f8cf2cb0..00000000000
--- a/libmudflap/testsuite/libmudflap.c/fail68-frag.c
+++ /dev/null
@@ -1,27 +0,0 @@
-/* PR libmudflap/40778 */
-
-char p[32];
-static int j;
-
-__attribute__((noinline))
-static void foo (int i)
-{
- if (j++ == 0)
- p[i + 4] = 12;
- else
- p[i - 4] = 13;
-}
-
-int
-main ()
-{
- foo (30);
- foo (30);
- foo (30);
- return 0;
-}
-
-/* { dg-output "mudflap violation 1.*" } */
-/* { dg-output "Nearby object 1.*" } */
-/* { dg-output "mudflap object.*name.*p" } */
-/* { dg-do run { xfail *-*-* } } */
diff --git a/libmudflap/testsuite/libmudflap.c/fail7-frag.c b/libmudflap/testsuite/libmudflap.c/fail7-frag.c
deleted file mode 100644
index 580d045386d..00000000000
--- a/libmudflap/testsuite/libmudflap.c/fail7-frag.c
+++ /dev/null
@@ -1,17 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-int main ()
-{
-char *foo;
-char *bar;
-foo = (char *)malloc (12);
-bar = (char *)malloc (10);
-
-memcpy(foo+1, bar+1, 10);
-return 0;
-}
-/* { dg-output "mudflap violation 1.*" } */
-/* { dg-output "Nearby object 1.*" } */
-/* { dg-output "mudflap object.*malloc region.*" } */
-/* { dg-do run { xfail *-*-* } } */
diff --git a/libmudflap/testsuite/libmudflap.c/fail8-frag.c b/libmudflap/testsuite/libmudflap.c/fail8-frag.c
deleted file mode 100644
index 8309068df47..00000000000
--- a/libmudflap/testsuite/libmudflap.c/fail8-frag.c
+++ /dev/null
@@ -1,19 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-int main ()
-{
-char *foo;
-char *bar;
-foo = (char *)malloc (10);
-bar = (char *)malloc (10);
-
-free(bar);
-
-memcpy(foo, bar, 10);
-return 0;
-}
-/* { dg-output "mudflap violation 1.*memcpy source.*" } */
-/* { dg-output "Nearby object.*" } */
-/* { dg-output "mudflap dead object.*malloc region.*alloc time.*dealloc time.*" } */
-/* { dg-do run { xfail *-*-* } } */
diff --git a/libmudflap/testsuite/libmudflap.c/fail9-frag.c b/libmudflap/testsuite/libmudflap.c/fail9-frag.c
deleted file mode 100644
index 9bbd860a898..00000000000
--- a/libmudflap/testsuite/libmudflap.c/fail9-frag.c
+++ /dev/null
@@ -1,21 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-int main ()
-{
-char *foo;
-char *bar;
-foo = (char *)malloc (10);
-bar = (char *)malloc (10);
-
-free(foo);
-
-bar[4] = 'a'; /* touch source buffer */
-memcpy(foo, bar, 10);
-return 0;
-}
-
-/* { dg-output "mudflap violation 1.*memcpy dest.*" } */
-/* { dg-output "Nearby object.*" } */
-/* { dg-output "mudflap dead object.*malloc region.*alloc time.*dealloc time.*" } */
-/* { dg-do run { xfail *-*-* } } */
diff --git a/libmudflap/testsuite/libmudflap.c/heap-scalestress.c b/libmudflap/testsuite/libmudflap.c/heap-scalestress.c
deleted file mode 100644
index 6e7813ba2ac..00000000000
--- a/libmudflap/testsuite/libmudflap.c/heap-scalestress.c
+++ /dev/null
@@ -1,79 +0,0 @@
-/* zz30
- *
- * demonstrate a splay-tree depth problem
-*/
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-
-#ifndef SCALE
-#define SCALE 10000
-#endif
-
-
-struct list
-{
- struct list *next;
-};
-
-
-int
-main ()
-{
- struct list *head = NULL;
- struct list *tail = NULL;
- struct list *p;
- long n;
- int direction;
-
- for (direction = 0; direction < 2; direction++)
- {
- fprintf (stdout, "allocating\n");
- fflush (stdout);
-
- for (n = 0; n < SCALE; ++n)
- {
- p = malloc (sizeof *p);
- if (NULL == p)
- {
- fprintf (stdout, "malloc failed\n");
- break;
- }
- if (direction == 0)
- { /* add at tail */
- p->next = NULL;
- if (NULL != tail)
- tail->next = p;
- else
- head = p;
- tail = p;
- }
- else
- { /* add at head */
- p->next = head;
- if (NULL == tail)
- tail = p;
- head = p;
- }
- }
-
- fprintf (stdout, "freeing\n");
- fflush (stdout);
-
- while (NULL != head)
- {
- p = head;
- head = head->next;
- free (p);
- }
-
- }
-
- fprintf (stdout, "done\n");
- fflush (stdout);
-
- return (0);
-}
-
-/* { dg-output "allocating.*freeing.*allocating.*freeing.*done" } */
diff --git a/libmudflap/testsuite/libmudflap.c/hook-allocstuff.c b/libmudflap/testsuite/libmudflap.c/hook-allocstuff.c
deleted file mode 100644
index dc25375488d..00000000000
--- a/libmudflap/testsuite/libmudflap.c/hook-allocstuff.c
+++ /dev/null
@@ -1,16 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-
-int main ()
-{
- char *foo = (char *) malloc (10);
- strcpy (foo, "hello");
- foo = (char *) realloc (foo, 20);
- printf ("%s", foo);
- if (strcmp (foo, "hello"))
- abort ();
- free (foo);
- printf (" world\n");
- return 0;
-}
-/* { dg-output "hello world" } */
diff --git a/libmudflap/testsuite/libmudflap.c/hook2-allocstuff.c b/libmudflap/testsuite/libmudflap.c/hook2-allocstuff.c
deleted file mode 100644
index d8fbec4676d..00000000000
--- a/libmudflap/testsuite/libmudflap.c/hook2-allocstuff.c
+++ /dev/null
@@ -1,9 +0,0 @@
-/* Generates recursive malloc call on i386-freebsd4.10 with -fmudflap. */
-#include <stdlib.h>
-
-int
-main (void)
-{
- char *p = malloc (1<<24);
- return 0;
-}
diff --git a/libmudflap/testsuite/libmudflap.c/pass-stratcliff.c b/libmudflap/testsuite/libmudflap.c/pass-stratcliff.c
deleted file mode 100644
index cf5430657ff..00000000000
--- a/libmudflap/testsuite/libmudflap.c/pass-stratcliff.c
+++ /dev/null
@@ -1,326 +0,0 @@
-/* Test for string function add boundaries of usable memory.
- Copyright (C) 1996, 1997, 1999, 2000, 2001, 2002, 2011
- Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301 USA. */
-
-#define _GNU_SOURCE 1
-#define __USE_GNU
-
-/* Make sure we don't test the optimized inline functions if we want to
- test the real implementation. */
-#undef __USE_STRING_INLINES
-
-#include "../config.h"
-
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/mman.h>
-#include <sys/param.h>
-
-#ifndef MAX
-#define MAX(a, b) ((a) > (b) ? (a) : (b))
-#endif
-
-#ifndef MIN
-#define MIN(a, b) ((a) < (b) ? (a) : (b))
-#endif
-
-int
-main (int argc, char *argv[])
-{
- int size = sysconf (_SC_PAGESIZE);
- char *adr, *dest;
- int result = 0;
-
- adr = (char *) mmap (NULL, 3 * size, PROT_READ | PROT_WRITE,
- MAP_PRIVATE | MAP_ANON, -1, 0);
- dest = (char *) mmap (NULL, 3 * size, PROT_READ | PROT_WRITE,
- MAP_PRIVATE | MAP_ANON, -1, 0);
- if (adr == MAP_FAILED || dest == MAP_FAILED)
- {
- if (errno == ENOSYS)
- puts ("No test, mmap not available.");
- else
- {
- printf ("mmap failed: %m");
- result = 1;
- }
- }
- else
- {
- int inner, middle, outer;
-
- mprotect(adr, size, PROT_NONE);
- mprotect(adr + 2 * size, size, PROT_NONE);
- adr += size;
-
- mprotect(dest, size, PROT_NONE);
- mprotect(dest + 2 * size, size, PROT_NONE);
- dest += size;
-
- memset (adr, 'T', size);
-
- /* strlen test */
- for (outer = size - 1; outer >= MAX (0, size - 128); --outer)
- {
- for (inner = MAX (outer, size - 64); inner < size; ++inner)
- {
- adr[inner] = '\0';
-
- if (strlen (&adr[outer]) != (size_t) (inner - outer))
- {
- printf ("strlen flunked for outer = %d, inner = %d\n",
- outer, inner);
- result = 1;
- }
-
- adr[inner] = 'T';
- }
- }
-
- /* strchr test */
- for (outer = size - 1; outer >= MAX (0, size - 128); --outer)
- {
- for (middle = MAX (outer, size - 64); middle < size; ++middle)
- {
- for (inner = middle; inner < size; ++inner)
- {
- char *cp;
- adr[middle] = 'V';
- adr[inner] = '\0';
-
- cp = strchr (&adr[outer], 'V');
-
- if ((inner == middle && cp != NULL)
- || (inner != middle
- && (cp - &adr[outer]) != middle - outer))
- {
- printf ("strchr flunked for outer = %d, middle = %d, "
- "inner = %d\n", outer, middle, inner);
- result = 1;
- }
-
- adr[inner] = 'T';
- adr[middle] = 'T';
- }
- }
- }
-
- /* Special test. */
- adr[size - 1] = '\0';
- if (strchr (&adr[size - 1], '\n') != NULL)
- {
- puts ("strchr flunked for test of empty string at end of page");
- result = 1;
- }
-
- /* strrchr test */
- for (outer = size - 1; outer >= MAX (0, size - 128); --outer)
- {
- for (middle = MAX (outer, size - 64); middle < size; ++middle)
- {
- for (inner = middle; inner < size; ++inner)
- {
- char *cp;
- adr[middle] = 'V';
- adr[inner] = '\0';
-
- cp = strrchr (&adr[outer], 'V');
-
- if ((inner == middle && cp != NULL)
- || (inner != middle
- && (cp - &adr[outer]) != middle - outer))
- {
- printf ("strrchr flunked for outer = %d, middle = %d, "
- "inner = %d\n", outer, middle, inner);
- result = 1;
- }
-
- adr[inner] = 'T';
- adr[middle] = 'T';
- }
- }
- }
-
-#ifdef HAVE_RAWMEMCHR
- /* rawmemchr test */
- for (outer = size - 1; outer >= MAX (0, size - 128); --outer)
- {
- for (middle = MAX (outer, size - 64); middle < size; ++middle)
- {
- char *cp;
- adr[middle] = 'V';
-
- cp = (char *) rawmemchr (&adr[outer], 'V');
-
- if (cp - &adr[outer] != middle - outer)
- {
- printf ("rawmemchr flunked for outer = %d, middle = %d\n",
- outer, middle);
- result = 1;
- }
-
- adr[middle] = 'T';
- }
- }
-#endif
-
- /* strcpy test */
- for (outer = size - 1; outer >= MAX (0, size - 128); --outer)
- {
- for (inner = MAX (outer, size - 64); inner < size; ++inner)
- {
- adr[inner] = '\0';
-
- if (strcpy (dest, &adr[outer]) != dest
- || strlen (dest) != (size_t) (inner - outer))
- {
- printf ("strcpy flunked for outer = %d, inner = %d\n",
- outer, inner);
- result = 1;
- }
-
- adr[inner] = 'T';
- }
- }
-
- /* strncpy tests */
- adr[size-1] = 'T';
- for (outer = size - 1; outer >= MAX (0, size - 128); --outer)
- {
- size_t len;
-
- for (len = 0; len < size - outer; ++len)
- {
- if (strncpy (dest, &adr[outer], len) != dest
- || memcmp (dest, &adr[outer], len) != 0)
- {
- printf ("outer strncpy flunked for outer = %d, len = %Zd\n",
- outer, len);
- result = 1;
- }
- }
- }
- adr[size-1] = '\0';
-
- for (outer = size - 1; outer >= MAX (0, size - 128); --outer)
- {
- for (inner = MAX (outer, size - 64); inner < size; ++inner)
- {
- size_t len;
-
- adr[inner] = '\0';
-
- for (len = 0; len < size - outer + 64; ++len)
- {
- if (strncpy (dest, &adr[outer], len) != dest
- || memcmp (dest, &adr[outer],
- MIN (inner - outer, len)) != 0
- || (inner - outer < len
- && strlen (dest) != (inner - outer)))
- {
- printf ("strncpy flunked for outer = %d, inner = %d, len = %Zd\n",
- outer, inner, len);
- result = 1;
- }
- if (strncpy (dest + 1, &adr[outer], len) != dest + 1
- || memcmp (dest + 1, &adr[outer],
- MIN (inner - outer, len)) != 0
- || (inner - outer < len
- && strlen (dest + 1) != (inner - outer)))
- {
- printf ("strncpy+1 flunked for outer = %d, inner = %d, len = %Zd\n",
- outer, inner, len);
- result = 1;
- }
- }
-
- adr[inner] = 'T';
- }
- }
-
-#ifdef HAVE_STPCPY
- /* stpcpy test */
- for (outer = size - 1; outer >= MAX (0, size - 128); --outer)
- {
- for (inner = MAX (outer, size - 64); inner < size; ++inner)
- {
- adr[inner] = '\0';
-
- if ((stpcpy (dest, &adr[outer]) - dest) != inner - outer)
- {
- printf ("stpcpy flunked for outer = %d, inner = %d\n",
- outer, inner);
- result = 1;
- }
-
- adr[inner] = 'T';
- }
- }
-
- /* stpncpy test */
- for (outer = size - 1; outer >= MAX (0, size - 128); --outer)
- {
- for (middle = MAX (outer, size - 64); middle < size; ++middle)
- {
- adr[middle] = '\0';
-
- for (inner = 0; inner < size - outer; ++ inner)
- {
- if ((stpncpy (dest, &adr[outer], inner) - dest)
- != MIN (inner, middle - outer))
- {
- printf ("stpncpy flunked for outer = %d, middle = %d, "
- "inner = %d\n", outer, middle, inner);
- result = 1;
- }
- }
-
- adr[middle] = 'T';
- }
- }
-#endif
-
- /* memcpy test */
- for (outer = size - 1; outer >= MAX (0, size - 128); --outer)
- for (inner = 0; inner < size - outer; ++inner)
- if (memcpy (dest, &adr[outer], inner) != dest)
- {
- printf ("memcpy flunked for outer = %d, inner = %d\n",
- outer, inner);
- result = 1;
- }
-
-#ifdef HAVE_MEMPCPY
- /* mempcpy test */
- for (outer = size - 1; outer >= MAX (0, size - 128); --outer)
- for (inner = 0; inner < size - outer; ++inner)
- if (mempcpy (dest, &adr[outer], inner) != dest + inner)
- {
- printf ("mempcpy flunked for outer = %d, inner = %d\n",
- outer, inner);
- result = 1;
- }
-#endif
- }
-
- return result;
-}
diff --git a/libmudflap/testsuite/libmudflap.c/pass1-frag.c b/libmudflap/testsuite/libmudflap.c/pass1-frag.c
deleted file mode 100644
index 40f629b56da..00000000000
--- a/libmudflap/testsuite/libmudflap.c/pass1-frag.c
+++ /dev/null
@@ -1,9 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-int main ()
-{
-int foo [10];
-foo[9] = 0;
-return 0;
-}
diff --git a/libmudflap/testsuite/libmudflap.c/pass10-frag.c b/libmudflap/testsuite/libmudflap.c/pass10-frag.c
deleted file mode 100644
index f05650da515..00000000000
--- a/libmudflap/testsuite/libmudflap.c/pass10-frag.c
+++ /dev/null
@@ -1,12 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-int main ()
-{
-int foo[10];
-int sz = sizeof (int);
-
-char *bar = (char *)foo;
-bar [sz * 9] = 0;
-return 0;
-}
diff --git a/libmudflap/testsuite/libmudflap.c/pass11-frag.c b/libmudflap/testsuite/libmudflap.c/pass11-frag.c
deleted file mode 100644
index ab7ee38c4f8..00000000000
--- a/libmudflap/testsuite/libmudflap.c/pass11-frag.c
+++ /dev/null
@@ -1,15 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-int main ()
-{
-int i = 10;
-char *x = (char *) malloc (i * sizeof (char));
-
-while (--i)
-{
- ++x;
- *x = 0;
-}
-return 0;
-}
diff --git a/libmudflap/testsuite/libmudflap.c/pass12-frag.c b/libmudflap/testsuite/libmudflap.c/pass12-frag.c
deleted file mode 100644
index 53630d9971d..00000000000
--- a/libmudflap/testsuite/libmudflap.c/pass12-frag.c
+++ /dev/null
@@ -1,15 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-int main ()
-{
-int i = 10;
-int *x = (int *) malloc (i * sizeof (int));
-
-while (--i)
-{
- ++x;
- *x = 0;
-}
-return 0;
-}
diff --git a/libmudflap/testsuite/libmudflap.c/pass13-frag.c b/libmudflap/testsuite/libmudflap.c/pass13-frag.c
deleted file mode 100644
index c2b820d0f43..00000000000
--- a/libmudflap/testsuite/libmudflap.c/pass13-frag.c
+++ /dev/null
@@ -1,17 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-int main ()
-{
-struct a {
- int x;
- int y;
- char z;
-};
-
-struct a k;
-
-k.z = 'q';
-
-return 0;
-}
diff --git a/libmudflap/testsuite/libmudflap.c/pass14-frag.c b/libmudflap/testsuite/libmudflap.c/pass14-frag.c
deleted file mode 100644
index 26456432979..00000000000
--- a/libmudflap/testsuite/libmudflap.c/pass14-frag.c
+++ /dev/null
@@ -1,20 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-int main ()
-{
-struct a {
- int x;
- int y;
- char z;
-};
-
-struct a k;
-struct a *p;
-
-p = &k;
-
-p->z = 'q';
-
-return 0;
-}
diff --git a/libmudflap/testsuite/libmudflap.c/pass15-frag.c b/libmudflap/testsuite/libmudflap.c/pass15-frag.c
deleted file mode 100644
index 5e1fee8eb9c..00000000000
--- a/libmudflap/testsuite/libmudflap.c/pass15-frag.c
+++ /dev/null
@@ -1,23 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-int main ()
-{
-struct base {
- int basic;
-};
-
-struct derived {
- struct base common;
- char extra;
-};
-
-struct derived d;
-struct base *bp;
-
-bp = (struct base *)&d;
-
-bp->basic = 10;
-((struct derived *)bp)->extra = 'x';
-return 0;
-}
diff --git a/libmudflap/testsuite/libmudflap.c/pass16-frag.c b/libmudflap/testsuite/libmudflap.c/pass16-frag.c
deleted file mode 100644
index 99ede3f2138..00000000000
--- a/libmudflap/testsuite/libmudflap.c/pass16-frag.c
+++ /dev/null
@@ -1,22 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-int main ()
-{
-struct base {
- int basic;
-};
-
-struct derived {
- struct base common;
- char extra;
-};
-
-struct base *bp;
-
-bp = (struct base *) malloc (sizeof (struct derived));
-
-bp->basic = 10;
-((struct derived *)bp)->extra = 'x';
-return 0;
-}
diff --git a/libmudflap/testsuite/libmudflap.c/pass17-frag.c b/libmudflap/testsuite/libmudflap.c/pass17-frag.c
deleted file mode 100644
index b840dc98746..00000000000
--- a/libmudflap/testsuite/libmudflap.c/pass17-frag.c
+++ /dev/null
@@ -1,9 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-int main ()
-{
-
-strlen("123456789");
-return 0;
-}
diff --git a/libmudflap/testsuite/libmudflap.c/pass18-frag.c b/libmudflap/testsuite/libmudflap.c/pass18-frag.c
deleted file mode 100644
index c5d5af0fe12..00000000000
--- a/libmudflap/testsuite/libmudflap.c/pass18-frag.c
+++ /dev/null
@@ -1,27 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-int main ()
-{
-int t;
-char foo[3] = { 'b', 'c', 'd' };
-int bar[3] = {1, 2, 0};
-t = 1;
-
-/* These tests check expression evaluation rules, such as
- ensuring that side-effect expression (++) get executed the
- right number of times; that array lookup checks nest correctly. */
-foo[t++] = 'a';
-if (foo[0] != 'b' || foo[1] != 'a' || foo[2] != 'd' || t != 2) abort ();
-if (bar[0] != 1 || bar[1] != 2 || bar[2] != 0) abort();
-
-foo[bar[t--]] = 'e';
-if (foo[0] != 'e' || foo[1] != 'a' || foo[2] != 'd' || t != 1) abort ();
-if (bar[0] != 1 || bar[1] != 2 || bar[2] != 0) abort();
-
-foo[bar[++t]--] = 'g';
-if (foo[0] != 'g' || foo[1] != 'a' || foo[2] != 'd' || t != 2) abort ();
-if (bar[0] != 1 || bar[1] != 2 || bar[2] != -1) abort();
-
-return 0;
-}
diff --git a/libmudflap/testsuite/libmudflap.c/pass19-frag.c b/libmudflap/testsuite/libmudflap.c/pass19-frag.c
deleted file mode 100644
index 0b00845d412..00000000000
--- a/libmudflap/testsuite/libmudflap.c/pass19-frag.c
+++ /dev/null
@@ -1,11 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-int main ()
-{
-struct foo {int base; char variable[1]; }; /* a common idiom for variable-size structs */
-
-struct foo * b = (struct foo *) malloc (sizeof (int)); /* enough for base */
-b->base = 4;
-return 0;
-}
diff --git a/libmudflap/testsuite/libmudflap.c/pass2-frag.c b/libmudflap/testsuite/libmudflap.c/pass2-frag.c
deleted file mode 100644
index 7e71e0cd7b5..00000000000
--- a/libmudflap/testsuite/libmudflap.c/pass2-frag.c
+++ /dev/null
@@ -1,9 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-int main ()
-{
-int foo [10][10];
-foo[9][0] = 0;
-return 0;
-}
diff --git a/libmudflap/testsuite/libmudflap.c/pass20-frag.c b/libmudflap/testsuite/libmudflap.c/pass20-frag.c
deleted file mode 100644
index 98431168548..00000000000
--- a/libmudflap/testsuite/libmudflap.c/pass20-frag.c
+++ /dev/null
@@ -1,13 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-int main ()
-{
-struct bar {int stuff; int array[10]; };
-
-struct bar *foo = (struct bar *) malloc (sizeof (struct bar));
-foo->array[5] = 4;
-free (foo);
-
-return 0;
-}
diff --git a/libmudflap/testsuite/libmudflap.c/pass21-frag.c b/libmudflap/testsuite/libmudflap.c/pass21-frag.c
deleted file mode 100644
index 231055a236f..00000000000
--- a/libmudflap/testsuite/libmudflap.c/pass21-frag.c
+++ /dev/null
@@ -1,15 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#ifndef __FreeBSD__
-#include <alloca.h>
-#endif
-int main ()
-{
-char *boo, *foo;
-boo = (char *) alloca (100);
-boo[99] = 'a';
-foo = (char *) __builtin_alloca (200);
-foo[44] = 'b';
-return 0;
-}
diff --git a/libmudflap/testsuite/libmudflap.c/pass22-frag.c b/libmudflap/testsuite/libmudflap.c/pass22-frag.c
deleted file mode 100644
index b092ea0b277..00000000000
--- a/libmudflap/testsuite/libmudflap.c/pass22-frag.c
+++ /dev/null
@@ -1,23 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-int main ()
-{
-struct foo {
- unsigned base:8;
- unsigned flag1:1;
- unsigned flag2:3;
- unsigned flag3:4;
- char nothing[0];
-};
-
-#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *) 0)->MEMBER)
-
-struct foo* f = (struct foo *) malloc (offsetof (struct foo, nothing));
-f->base = 1;
-f->flag1 = 1;
-free (f);
-
-
-return 0;
-}
diff --git a/libmudflap/testsuite/libmudflap.c/pass23-frag.c b/libmudflap/testsuite/libmudflap.c/pass23-frag.c
deleted file mode 100644
index f27c223614b..00000000000
--- a/libmudflap/testsuite/libmudflap.c/pass23-frag.c
+++ /dev/null
@@ -1,29 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-int main ()
-{
-struct foo {
- int part1: 8;
- int nothing : 1;
- int part2 : 5;
- int lots_more_nothing : 3;
- int some_padding; /* for 64-bit hosts */
- float some_more_nothing;
- double yet_more_nothing;
-};
-
-#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *) 0)->MEMBER)
-
-struct foo* q = (struct foo *) malloc (offsetof (struct foo, some_more_nothing));
-q->nothing = 1; /* touch q */
-/* The RHS of the following expression is meant to trigger a
- fold-const.c mapping the expression to a BIT_FIELD_REF. It glues
- together the accesses to the two non-neighbouring bitfields into a
- single bigger boolean test. */
-q->lots_more_nothing = (q->part1 == 13 && q->part2 == 7);
-free (q);
-
-
-return 0;
-}
diff --git a/libmudflap/testsuite/libmudflap.c/pass24-frag.c b/libmudflap/testsuite/libmudflap.c/pass24-frag.c
deleted file mode 100644
index 00385822130..00000000000
--- a/libmudflap/testsuite/libmudflap.c/pass24-frag.c
+++ /dev/null
@@ -1,18 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-int main ()
-{
-struct foo {
- int zoo;
- int bar [10];
- float baz;
-};
-
-#define offsetof(S,F) ((size_t) & (((S *) 0)->F))
-
-struct foo *k = (struct foo *) malloc (offsetof (struct foo, bar[4]));
-k->bar[1] = 9;
-free (k);
-return 0;
-}
diff --git a/libmudflap/testsuite/libmudflap.c/pass25-frag.c b/libmudflap/testsuite/libmudflap.c/pass25-frag.c
deleted file mode 100644
index c5a75e3338e..00000000000
--- a/libmudflap/testsuite/libmudflap.c/pass25-frag.c
+++ /dev/null
@@ -1,15 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-int main ()
-{
-int *foo = malloc (10 * sizeof(int));
-int *bar = & foo[3];
-/* Watching occurs at the object granularity, which is in this case
- the entire array. */
-__mf_watch (& foo[1], sizeof(foo[1]));
-__mf_unwatch (& foo[6], sizeof(foo[6]));
-*bar = 10;
-free (foo);
-return 0;
-}
diff --git a/libmudflap/testsuite/libmudflap.c/pass26-frag.c b/libmudflap/testsuite/libmudflap.c/pass26-frag.c
deleted file mode 100644
index 5a72f5b790c..00000000000
--- a/libmudflap/testsuite/libmudflap.c/pass26-frag.c
+++ /dev/null
@@ -1,52 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-int main ()
-{
-volatile int *p;
-
-__mf_set_options ("-wipe-stack -no-check-initialization");
-
-{
- volatile int array [10];
- p = & array[0];
-
- array[0] = 2;
- array[9] = 5;
-
- /* Array[] should be wiped clean at this point. */
-}
-
-__mf_set_options ("-no-wipe-stack");
-
-{
- volatile int array2[10];
-
- /* hope that this is allocated on top of old array[] */
- if (p != & array2[0])
- exit (0); /* Test is not applicable. */
-
- array2[5] = 6;
-
- /* Old values shouldn't still be around; the new one should. */
- if (p[0] == 2 || p[9] == 5 || p[5] != 6)
- abort() ;
-
- /* array2[] should not be wiped at this point! */
-}
-
-{
- volatile int array3[10];
-
- /* hope that this is allocated on top of old array[] and array2[]*/
- if (p != & array3[0])
- exit (0); /* Test is not applicable. */
-
- array3[1] = 2;
-
- /* Check that old assignment is still around. */
- if (p[5] != 6 || p[1] != 2)
- abort() ;
-}
-return 0;
-}
diff --git a/libmudflap/testsuite/libmudflap.c/pass29-frag.c b/libmudflap/testsuite/libmudflap.c/pass29-frag.c
deleted file mode 100644
index 97bed6eb373..00000000000
--- a/libmudflap/testsuite/libmudflap.c/pass29-frag.c
+++ /dev/null
@@ -1,15 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-int main ()
-{
-struct boo { int a; };
-int c;
-struct boo *b = malloc (sizeof (struct boo));
-__mf_set_options ("-check-initialization");
-b->a = 0;
-/* That __mf_set_options call could be here instead. */
-c = b->a;
-(void) malloc (c); /* some dummy use of c */
-return 0;
-}
diff --git a/libmudflap/testsuite/libmudflap.c/pass3-frag.c b/libmudflap/testsuite/libmudflap.c/pass3-frag.c
deleted file mode 100644
index 4e950a2c5d8..00000000000
--- a/libmudflap/testsuite/libmudflap.c/pass3-frag.c
+++ /dev/null
@@ -1,9 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-int main ()
-{
-int foo [10][10][10];
-foo[9][9][0] = 0;
-return 0;
-}
diff --git a/libmudflap/testsuite/libmudflap.c/pass30-frag.c b/libmudflap/testsuite/libmudflap.c/pass30-frag.c
deleted file mode 100644
index 6c4b9f9a7f8..00000000000
--- a/libmudflap/testsuite/libmudflap.c/pass30-frag.c
+++ /dev/null
@@ -1,12 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-char zoo [10];
-
-int main ()
-{
-int i = strlen ("eight") + strlen ("one");
-zoo[i] = 'a';
-return 0;
-}
diff --git a/libmudflap/testsuite/libmudflap.c/pass32-frag.c b/libmudflap/testsuite/libmudflap.c/pass32-frag.c
deleted file mode 100644
index d7f22327976..00000000000
--- a/libmudflap/testsuite/libmudflap.c/pass32-frag.c
+++ /dev/null
@@ -1,18 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-struct foo { char z[10]; };
-
-char * get_z (struct foo *this)
-{
- return & this->z[0] /* the `this' pointer is not dereferenced! */;
-}
-
-int main ()
-{
-struct foo k;
-char *n = get_z (& k);
-srand ((int)(__mf_uintptr_t) n); /* use the pointer value */
-return 0;
-}
diff --git a/libmudflap/testsuite/libmudflap.c/pass33-frag.c b/libmudflap/testsuite/libmudflap.c/pass33-frag.c
deleted file mode 100644
index 95d762cc1aa..00000000000
--- a/libmudflap/testsuite/libmudflap.c/pass33-frag.c
+++ /dev/null
@@ -1,17 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-void test (int *k)
-{
- if (*k > 5) { *k --; }
-}
-
-int main ()
-{
-int z;
-/* z is initialized, but not via a pointer, so not instrumented */
-z = rand ();
-test (& z);
-return 0;
-}
diff --git a/libmudflap/testsuite/libmudflap.c/pass34-frag.c b/libmudflap/testsuite/libmudflap.c/pass34-frag.c
deleted file mode 100644
index 2dfd0ca2113..00000000000
--- a/libmudflap/testsuite/libmudflap.c/pass34-frag.c
+++ /dev/null
@@ -1,18 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-void test (int *k)
-{
- if (*k > 5) { *k --; }
-}
-
-int z;
-
-int main ()
-{
-/* z is initialized, but not via a pointer, so not instrumented */
-z = rand ();
-test (& z);
-return 0;
-}
diff --git a/libmudflap/testsuite/libmudflap.c/pass35-frag.c b/libmudflap/testsuite/libmudflap.c/pass35-frag.c
deleted file mode 100644
index 14d2c94a9bb..00000000000
--- a/libmudflap/testsuite/libmudflap.c/pass35-frag.c
+++ /dev/null
@@ -1,14 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-extern char end []; /* Any old symbol we're sure will be defined. */
-/* { dg-warning "cannot track unknown size extern" "cannot track unknown size extern" { target *-*-* } 0 } */
-
-int main ()
-{
-/* dummy register */
-__mf_register ((void *) end, 1, __MF_TYPE_GUESS, "end");
-char z = end[0];
-return z & 0;
-}
diff --git a/libmudflap/testsuite/libmudflap.c/pass36-frag.c b/libmudflap/testsuite/libmudflap.c/pass36-frag.c
deleted file mode 100644
index 68d1a7f8080..00000000000
--- a/libmudflap/testsuite/libmudflap.c/pass36-frag.c
+++ /dev/null
@@ -1,15 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <signal.h>
-
-int main ()
-{
-char *k;
-__mf_set_options ("-sigusr1-report -print-leaks");
-k = (char *) malloc (100);
-raise (SIGUSR1);
-free (k);
-return 0;
-}
-/* { dg-output "Leaked object.*name=.malloc region.*objects: 1" } */
diff --git a/libmudflap/testsuite/libmudflap.c/pass38-frag.c b/libmudflap/testsuite/libmudflap.c/pass38-frag.c
deleted file mode 100644
index a250234da8a..00000000000
--- a/libmudflap/testsuite/libmudflap.c/pass38-frag.c
+++ /dev/null
@@ -1,9 +0,0 @@
-/* Test an odd construct for compilability. */
-static void *fwd;
-void *bwd = &fwd;
-static void *fwd = &bwd;
-
-int main ()
-{
- return 0;
-}
diff --git a/libmudflap/testsuite/libmudflap.c/pass4-frag.c b/libmudflap/testsuite/libmudflap.c/pass4-frag.c
deleted file mode 100644
index 0a40d1c425a..00000000000
--- a/libmudflap/testsuite/libmudflap.c/pass4-frag.c
+++ /dev/null
@@ -1,9 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-int main ()
-{
-char foo[10];
-strcpy (foo, "123456789");
-return 0;
-}
diff --git a/libmudflap/testsuite/libmudflap.c/pass42-frag.c b/libmudflap/testsuite/libmudflap.c/pass42-frag.c
deleted file mode 100644
index 1045c47c37a..00000000000
--- a/libmudflap/testsuite/libmudflap.c/pass42-frag.c
+++ /dev/null
@@ -1,17 +0,0 @@
-#include <stdio.h>
-
-void
-foo ()
-{
- putc ('h', stdout);
- putc ('i', stdout);
- putc ('\n', stdout);
-}
-
-int
-main (int argc, char *argv[])
-{
- foo ();
- return 0;
-}
-/* { dg-output "hi" } */
diff --git a/libmudflap/testsuite/libmudflap.c/pass43-frag.c b/libmudflap/testsuite/libmudflap.c/pass43-frag.c
deleted file mode 100644
index 4fec3306eb1..00000000000
--- a/libmudflap/testsuite/libmudflap.c/pass43-frag.c
+++ /dev/null
@@ -1,11 +0,0 @@
-void
-foo ()
-{
-}
-
-int
-main (int argc, char *argv[])
-{
- foo ();
- return 0;
-}
diff --git a/libmudflap/testsuite/libmudflap.c/pass44-frag.c b/libmudflap/testsuite/libmudflap.c/pass44-frag.c
deleted file mode 100644
index 338d6da63bf..00000000000
--- a/libmudflap/testsuite/libmudflap.c/pass44-frag.c
+++ /dev/null
@@ -1,14 +0,0 @@
-#include <stdio.h>
-
-void
-foo ()
-{
- return; /* accept value-less return statement */
-}
-
-int
-main (int argc, char *argv[])
-{
- foo ();
- return 0;
-}
diff --git a/libmudflap/testsuite/libmudflap.c/pass45-frag.c b/libmudflap/testsuite/libmudflap.c/pass45-frag.c
deleted file mode 100644
index c6bfeb5048c..00000000000
--- a/libmudflap/testsuite/libmudflap.c/pass45-frag.c
+++ /dev/null
@@ -1,31 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-extern void h (const char *p, const char *f);
-int
-main (void)
-{
- h (0, "foo");
- return 0;
-}
-
-void
-h (const char *p, const char *f)
-{
- size_t pl = p == NULL ? 0 : strlen (p);
- size_t fl = strlen (f) + 1;
- char a[pl + 1 + fl];
- char *cp = a;
- char b[pl + 5 + fl * 2];
- char *cccp = b;
- if (p != NULL)
- {
- cp = memcpy (cp, p, pl);
- *cp++ = ':';
- }
- memcpy (cp, f, fl);
- strcpy (b, a);
- puts (a);
-}
-/* { dg-output "foo" } */
diff --git a/libmudflap/testsuite/libmudflap.c/pass46-frag.c b/libmudflap/testsuite/libmudflap.c/pass46-frag.c
deleted file mode 100644
index 904868af0d1..00000000000
--- a/libmudflap/testsuite/libmudflap.c/pass46-frag.c
+++ /dev/null
@@ -1,18 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-int foo (int *u, int i)
-{
- return u[i]; /* this dereference should not be instrumented */
-}
-
-int main ()
-{
- int *k = malloc (6);
- int l = foo (k, 8);
- int boo [8];
- int m = boo [l % 2 + 12]; /* should not be instrumented */
- return m & strlen (""); /* a fancy way of saying "0" */
-}
-/* { dg-options "-fmudflap -fmudflapir -lmudflap" } */
diff --git a/libmudflap/testsuite/libmudflap.c/pass47-frag.c b/libmudflap/testsuite/libmudflap.c/pass47-frag.c
deleted file mode 100644
index 71175827209..00000000000
--- a/libmudflap/testsuite/libmudflap.c/pass47-frag.c
+++ /dev/null
@@ -1,12 +0,0 @@
-#include <stdlib.h>
-#include <ctype.h>
-
-int main ()
-{
- char* buf = "hello";
- return ! ((toupper (buf[0]) == 'H' && toupper ('z') == 'Z' &&
- tolower (buf[4]) == 'o' && tolower ('X') == 'x' &&
- isdigit (buf[3])) == 0 && isalnum ('4'));
-}
-
-/* { dg-warning "cannot track unknown size extern .__ctype." "Solaris __ctype declared without size" { target *-*-solaris2.* } 0 } */
diff --git a/libmudflap/testsuite/libmudflap.c/pass48-frag.c b/libmudflap/testsuite/libmudflap.c/pass48-frag.c
deleted file mode 100644
index 3059762a82c..00000000000
--- a/libmudflap/testsuite/libmudflap.c/pass48-frag.c
+++ /dev/null
@@ -1,11 +0,0 @@
-void foo (int k)
-{
- volatile int *b = & k;
- *b = 5;
-}
-
-int main ()
-{
- foo (5);
- return 0;
-}
diff --git a/libmudflap/testsuite/libmudflap.c/pass49-frag.c b/libmudflap/testsuite/libmudflap.c/pass49-frag.c
deleted file mode 100644
index db7453079a0..00000000000
--- a/libmudflap/testsuite/libmudflap.c/pass49-frag.c
+++ /dev/null
@@ -1,35 +0,0 @@
-#include <stdlib.h>
-#include <ctype.h>
-#include <stdarg.h>
-
-int foo (int a, ...)
-{
- va_list args;
- char *a1;
- int a2;
- int k;
-
- va_start (args, a);
- for (k = 0; k < a; k++)
- {
- if ((k % 2) == 0)
- {
- char *b = va_arg (args, char *);
- printf ("%s", b);
- }
- else
- {
- int b = va_arg (args, int);
- printf ("%d", b);
- }
- }
- va_end (args);
- return a;
-}
-
-int main ()
-{
- foo (7, "hello ", 5, " ", 3, " world ", 9, "\n");
- return 0;
-}
-/* { dg-output "hello 5 3 world 9" } */
diff --git a/libmudflap/testsuite/libmudflap.c/pass5-frag.c b/libmudflap/testsuite/libmudflap.c/pass5-frag.c
deleted file mode 100644
index 6d3408a4e52..00000000000
--- a/libmudflap/testsuite/libmudflap.c/pass5-frag.c
+++ /dev/null
@@ -1,11 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-int main ()
-{
-char foo [10];
-char bar [10];
-bar[4] = 'k'; /* touch memcpy source */
-memcpy(foo, bar, 10);
-return 0;
-}
diff --git a/libmudflap/testsuite/libmudflap.c/pass50-frag.c b/libmudflap/testsuite/libmudflap.c/pass50-frag.c
deleted file mode 100644
index ac9ee090950..00000000000
--- a/libmudflap/testsuite/libmudflap.c/pass50-frag.c
+++ /dev/null
@@ -1,29 +0,0 @@
-#include <stdlib.h>
-
-struct a
-{
- int a1[5];
- union
- {
- int b1[5];
- struct
- {
- int c1;
- int c2;
- } b2[4];
- } a2[8];
-};
-
-int i1 = 5;
-int i2 = 2;
-int i3 = 6;
-int i4 = 0;
-
-int
-main ()
-{
- volatile struct a *k = calloc (1, sizeof (struct a));
- k->a2[i1].b1[i2] = k->a2[i3].b2[i4].c2;
- free ((void *) k);
- return 0;
-}
diff --git a/libmudflap/testsuite/libmudflap.c/pass51-frag.c b/libmudflap/testsuite/libmudflap.c/pass51-frag.c
deleted file mode 100644
index 2780ffd72a0..00000000000
--- a/libmudflap/testsuite/libmudflap.c/pass51-frag.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/* Test object-spanning accesses. This is most conveniently done with
- mmap, thus the config.h specificity here. */
-#include "../config.h"
-
-#include <unistd.h>
-#include <string.h>
-#ifdef HAVE_SYS_MMAN_H
-#include <sys/mman.h>
-#endif
-
-int main ()
-{
-#ifndef MAP_ANONYMOUS
-#define MAP_ANONYMOUS MAP_ANON
-#endif
-#ifndef MAP_FAILED
-#define MAP_FAILED ((void *)-1)
-#endif
-#ifdef HAVE_MMAP
- void *p;
- unsigned pg = getpagesize ();
- int rc;
-
- p = mmap (NULL, 4 * pg, PROT_READ|PROT_WRITE,
- MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
- if (p == MAP_FAILED)
- return 1;
-
- memset (p, 0, 4*pg);
- rc = munmap (p, pg);
- if (rc < 0) return 1;
- memset (p+pg, 0, 3*pg);
- rc = munmap (p+pg, pg);
- if (rc < 0) return 1;
- memset (p+2*pg, 0, 2*pg);
- rc = munmap (p+2*pg, pg);
- if (rc < 0) return 1;
- memset (p+3*pg, 0, pg);
- rc = munmap (p+3*pg, pg);
- if (rc < 0) return 1;
-#endif
-
- return 0;
-}
diff --git a/libmudflap/testsuite/libmudflap.c/pass52-frag.c b/libmudflap/testsuite/libmudflap.c/pass52-frag.c
deleted file mode 100644
index 7ff9d577ba7..00000000000
--- a/libmudflap/testsuite/libmudflap.c/pass52-frag.c
+++ /dev/null
@@ -1,36 +0,0 @@
-#include <stdio.h>
-
-
-void writestuff (FILE *f)
-{
- fprintf (f, "hello world\n");
- fputc ('y', f);
- putc ('e', f);
-}
-
-void readstuff (FILE *f)
-{
- int c, d;
- char stuff[100], *s;
- c = fgetc (f);
- ungetc (c, f);
- d = fgetc (f);
- s = fgets (stuff, sizeof(stuff), f);
-}
-
-int main ()
-{
- FILE *f;
- writestuff (stdout);
- writestuff (stderr);
- f = fopen ("/dev/null", "w");
- writestuff (f);
- fclose (f);
- f = fopen ("/dev/zero", "r");
- readstuff (f);
- f = freopen ("/dev/null", "w", f);
- writestuff (f);
- fclose (f);
-
- return 0;
-}
diff --git a/libmudflap/testsuite/libmudflap.c/pass53-frag.c b/libmudflap/testsuite/libmudflap.c/pass53-frag.c
deleted file mode 100644
index 6afb2931e34..00000000000
--- a/libmudflap/testsuite/libmudflap.c/pass53-frag.c
+++ /dev/null
@@ -1,41 +0,0 @@
-int foo1 ()
-{
- union { int l; char c[sizeof (int)]; } k1;
- char *m;
- k1.l = 0;
- /* This test variant triggers ADDR_EXPR of k explicitly in order to
- ensure it's registered with the runtime. */
- m = k1.c;
- k1.c [sizeof (int)-1] = m[sizeof (int)-2];
-}
-
-int foo2 ()
-{
- union { int l; char c[sizeof (int)]; } k2;
- k2.l = 0;
- /* Since this access is known-in-range, k need not be registered
- with the runtime, but then this access better not be instrumented
- either. */
- k2.c [sizeof (int)-1] ++;
- return k2.l;
-}
-
-int foo3idx = sizeof (int)-1;
-
-int foo3 ()
-{
- union { int l; char c[sizeof (int)]; } k3;
- k3.l = 0;
- /* NB this test uses foo3idx, an extern variable, to defeat mudflap
- known-in-range-index optimizations. */
- k3.c [foo3idx] ++;
- return k3.l;
-}
-
-int main ()
-{
- foo1 ();
- foo2 ();
- foo3 ();
- return 0;
-}
diff --git a/libmudflap/testsuite/libmudflap.c/pass54-frag.c b/libmudflap/testsuite/libmudflap.c/pass54-frag.c
deleted file mode 100644
index 5eebb4515fc..00000000000
--- a/libmudflap/testsuite/libmudflap.c/pass54-frag.c
+++ /dev/null
@@ -1,34 +0,0 @@
-struct k
-{
- struct {
- int b;
- int c;
- } a;
-};
-
-static struct k l;
-static struct k m;
-
-void foo ()
-{
- /* This should not be instrumented. */
- l.a.b = 5;
-}
-
-void bar ()
-{
- /* This should not be instrumented. */
- m.a.b = 5;
-}
-
-int main ()
-{
- /* Force TREE_ADDRESSABLE on "l" only. */
- volatile int *k = & l.a.c;
- *k = 8;
- __mf_set_options ("-mode-violate");
- foo ();
- bar ();
- __mf_set_options ("-mode-check");
- return 0;
-}
diff --git a/libmudflap/testsuite/libmudflap.c/pass56-frag.c b/libmudflap/testsuite/libmudflap.c/pass56-frag.c
deleted file mode 100644
index e22fc8dbfd6..00000000000
--- a/libmudflap/testsuite/libmudflap.c/pass56-frag.c
+++ /dev/null
@@ -1,14 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-
-int main ()
-{
- volatile int *k = (int *) malloc (sizeof (int));
- volatile int l;
- if (k == NULL) abort ();
- *k = 5;
- free ((void *) k);
- __mf_set_options ("-ignore-reads");
- l = *k; /* Should not trip, even though memory region just freed. */
- return 0;
-}
diff --git a/libmudflap/testsuite/libmudflap.c/pass6-frag.c b/libmudflap/testsuite/libmudflap.c/pass6-frag.c
deleted file mode 100644
index 9b07fe2de22..00000000000
--- a/libmudflap/testsuite/libmudflap.c/pass6-frag.c
+++ /dev/null
@@ -1,14 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-int main ()
-{
-char *foo;
-char *bar;
-
-foo = (char *)malloc (10);
-bar = (char *)malloc (10);
-bar[2] = 'z'; /* touch memcpy source */
-memcpy(foo, bar, 10);
-return 0;
-}
diff --git a/libmudflap/testsuite/libmudflap.c/pass62-frag.c b/libmudflap/testsuite/libmudflap.c/pass62-frag.c
deleted file mode 100644
index 8e64b2b0e43..00000000000
--- a/libmudflap/testsuite/libmudflap.c/pass62-frag.c
+++ /dev/null
@@ -1,13 +0,0 @@
-/* PR tree-optimization/34618 */
-/* { dg-do compile } */
-/* { dg-options "-O3 -fmudflap" } */
-
-int a[16];
-
-void
-foo ()
-{
- int i;
- for (i = 0; i < 16; i++)
- a[i] = i;
-}
diff --git a/libmudflap/testsuite/libmudflap.c/pass63-frag.c b/libmudflap/testsuite/libmudflap.c/pass63-frag.c
deleted file mode 100644
index a5ad8f26b08..00000000000
--- a/libmudflap/testsuite/libmudflap.c/pass63-frag.c
+++ /dev/null
@@ -1,6 +0,0 @@
-/* Check -Wno-mudflap flag */
-/* { dg-do compile } */
-/* { dg-options "-fmudflap -Wno-mudflap" } */
-
-extern char x[];
-int main() { return x[3]; } /* { dg-bogus "mudflap cannot track" } */
diff --git a/libmudflap/testsuite/libmudflap.c/pass64-frag.c b/libmudflap/testsuite/libmudflap.c/pass64-frag.c
deleted file mode 100644
index 856eec0fa7e..00000000000
--- a/libmudflap/testsuite/libmudflap.c/pass64-frag.c
+++ /dev/null
@@ -1,38 +0,0 @@
-/* PR libmudflap/36397 */
-/* { dg-do run } */
-/* { dg-options "-O -fmudflap -fno-strict-aliasing -lmudflap" } */
-
-struct A
-{
- int a[2];
-};
-
-long long int x;
-
-int __attribute__ ((noinline))
-baz (long long int *x)
-{
- return *x;
-}
-
-int __attribute__ ((noinline))
-foo (int i)
-{
- if (i > 10)
- return baz (&x);
- return ((struct A *) &x)->a[i];
-}
-
-int
-main (void)
-{
- if (sizeof (long long) == 2 * sizeof (int)
- && sizeof (long long) == sizeof (struct A))
- {
- struct A a = { .a[0] = 10, .a[1] = 20 };
- __builtin_memcpy (&x, &a, sizeof (x));
- if (foo (0) != 10 || foo (1) != 20)
- __builtin_abort ();
- }
- return 0;
-}
diff --git a/libmudflap/testsuite/libmudflap.c/pass67-frag.c b/libmudflap/testsuite/libmudflap.c/pass67-frag.c
deleted file mode 100644
index 0c2f81a1705..00000000000
--- a/libmudflap/testsuite/libmudflap.c/pass67-frag.c
+++ /dev/null
@@ -1,14 +0,0 @@
-/* PR middle-end/35314 */
-/* { dg-do compile } */
-/* { dg-options "-fmudflap" } */
-
-#include <setjmp.h>
-
-jmp_buf buf;
-
-void
-foo (volatile char *p)
-{
- if (__builtin_setjmp (buf))
- *p;
-}
diff --git a/libmudflap/testsuite/libmudflap.c/pass7-frag.c b/libmudflap/testsuite/libmudflap.c/pass7-frag.c
deleted file mode 100644
index 36197339e88..00000000000
--- a/libmudflap/testsuite/libmudflap.c/pass7-frag.c
+++ /dev/null
@@ -1,13 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-int main ()
-{
-char *foo;
-char *bar;
-foo = (char *)malloc (10);
-bar = (char *)malloc (10);
-bar[2] = 'z'; /* touch memcpy source */
-memcpy(foo+1, bar+1, 9);
-return 0;
-}
diff --git a/libmudflap/testsuite/libmudflap.c/pass8-frag.c b/libmudflap/testsuite/libmudflap.c/pass8-frag.c
deleted file mode 100644
index 6be4e93f000..00000000000
--- a/libmudflap/testsuite/libmudflap.c/pass8-frag.c
+++ /dev/null
@@ -1,16 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-int main ()
-{
-char *foo;
-char *bar;
-foo = (char *)malloc (10);
-bar = (char *)malloc (10);
-
-free(bar);
-bar = (char *)malloc (10);
-bar[6] = 'k'; /* touch memcpy source */
-memcpy(foo, bar, 10);
-return 0;
-}
diff --git a/libmudflap/testsuite/libmudflap.c/pass9-frag.c b/libmudflap/testsuite/libmudflap.c/pass9-frag.c
deleted file mode 100644
index 9186e062ff8..00000000000
--- a/libmudflap/testsuite/libmudflap.c/pass9-frag.c
+++ /dev/null
@@ -1,16 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-int main ()
-{
-char *foo;
-char *bar;
-foo = (char *)malloc (10);
-bar = (char *)malloc (10);
-
-free(foo);
-foo = (char *)malloc (10);
-bar[3] = 'w'; /* touch memcpy source */
-memcpy(foo, bar, 10);
-return 0;
-}
diff --git a/libmudflap/testsuite/libmudflap.cth/cthfrags.exp b/libmudflap/testsuite/libmudflap.cth/cthfrags.exp
deleted file mode 100644
index 75d44476838..00000000000
--- a/libmudflap/testsuite/libmudflap.cth/cthfrags.exp
+++ /dev/null
@@ -1,30 +0,0 @@
-global MUDFLAP_FLAGS
-set MUDFLAP_FLAGS [list {-O0} {-static -DSTATIC} {-O2} {-O3}]
-
-libmudflap-init c
-
-dg-init
-
-global srcdir
-foreach flags $MUDFLAP_FLAGS {
- foreach srcfile [lsort [glob -nocomplain ${srcdir}/libmudflap.cth/*.c]] {
- set bsrc [file tail $srcfile]
- setenv MUDFLAP_OPTIONS "-viol-segv"
- if {$libmudflapth} then {
- if [check_effective_target_gld] {
- # --noinhibit-exec works around a ld problem that causes
- # "Dwarf Error: Invalid or unhandled FORM value: 14"
- # to fail builds unnecessarily.
- set noie_option " -Wl,--noinhibit-exec"
- } else {
- set noie_option ""
- }
- dg-runtest $srcfile $flags "-fmudflapth -lmudflapth -lpthread $noie_option"
- } else {
- if {$flags != ""} {set f " ($flags)"} {set f ""}
- untested "libmudflap.cth/$bsrc$f"
- }
- }
-}
-
-dg-finish
diff --git a/libmudflap/testsuite/libmudflap.cth/pass37-frag.c b/libmudflap/testsuite/libmudflap.cth/pass37-frag.c
deleted file mode 100644
index 877803c1ea0..00000000000
--- a/libmudflap/testsuite/libmudflap.cth/pass37-frag.c
+++ /dev/null
@@ -1,58 +0,0 @@
-#include <stdlib.h>
-#include <stdio.h>
-#include <pthread.h>
-#include <sched.h>
-
-static void *
-func (void *p)
-{
- int *counter = (int *) p;
- unsigned i;
-
- for (i=0; i<100; i++)
- {
- (*counter) ++;
- {
- int array[17];
- unsigned x = i % (sizeof(array)/sizeof(array[0]));
- /* VRP could prove that x is within [0,16], but until then, the
- following access will ensure that array[] is registered to
- libmudflap. */
- array[x] = i;
- }
- sched_yield (); /* sleep (1); */
- }
-
- return (NULL);
-}
-
-
-int main ()
-{
- int rc;
- unsigned i;
- enum foo { NT=10 };
- pthread_t threads[NT];
- int counts[NT];
-
-
- for (i=0; i<NT; i++)
- {
- counts[i] = 0;
- rc = pthread_create (& threads[i], NULL, func, (void *) & counts[i]);
- if (rc) abort();
- }
-
- for (i=0; i<NT; i++)
- {
- rc = pthread_join (threads[i], NULL);
- if (rc) abort();
- printf ("%d%s", counts[i], (i==NT-1) ? "\n" : " ");
- }
-
- return 0;
-}
-
-/* { dg-output "100 100 100 100 100 100 100 100 100 100" } */
-/* { dg-repetitions 20 } */
-/* { dg-timeout 10 } */
diff --git a/libmudflap/testsuite/libmudflap.cth/pass39-frag.c b/libmudflap/testsuite/libmudflap.cth/pass39-frag.c
deleted file mode 100644
index cd3eb5abdaf..00000000000
--- a/libmudflap/testsuite/libmudflap.cth/pass39-frag.c
+++ /dev/null
@@ -1,57 +0,0 @@
-#include <stdlib.h>
-#include <stdio.h>
-#include <pthread.h>
-#include <sched.h>
-#include <assert.h>
-
-static void *
-func (void *p)
-{
- int *counter = (int *) p;
- unsigned i;
- enum { numarrays = 100, numels = 17 };
- char *arrays [numarrays];
-
- for (i=0; i<numarrays; i++)
- {
- (*counter) ++;
- unsigned x = i % numels;
- arrays[i] = calloc (numels, sizeof(arrays[i][0]));
- assert (arrays[i] != NULL);
- arrays[i][x] = i;
- free (arrays[i]);
- sched_yield (); /* sleep (1); */
- }
-
- return (NULL);
-}
-
-
-int main ()
-{
- int rc;
- unsigned i;
- enum foo { NT=10 };
- pthread_t threads[NT];
- int counts[NT];
-
-
- for (i=0; i<NT; i++)
- {
- counts[i] = 0;
- rc = pthread_create (& threads[i], NULL, func, (void *) & counts[i]);
- if (rc) abort();
- }
-
- for (i=0; i<NT; i++)
- {
- rc = pthread_join (threads[i], NULL);
- if (rc) abort();
- printf ("%d%s", counts[i], (i==NT-1) ? "\n" : " ");
- }
-
- return 0;
-}
-/* { dg-output "100 100 100 100 100 100 100 100 100 100" } */
-/* { dg-repetitions 20 } */
-/* { dg-timeout 10 } */
diff --git a/libmudflap/testsuite/libmudflap.cth/pass40-frag.c b/libmudflap/testsuite/libmudflap.cth/pass40-frag.c
deleted file mode 100644
index 007cb1607de..00000000000
--- a/libmudflap/testsuite/libmudflap.cth/pass40-frag.c
+++ /dev/null
@@ -1,59 +0,0 @@
-#include <stdlib.h>
-#include <stdio.h>
-#include <pthread.h>
-
-static void *
-func (void *p)
-{
- return (NULL);
-}
-
-static void
-test (void)
-{
- int rc;
- pthread_attr_t my_pthread_attr;
- pthread_t h;
- long i;
-
- rc = pthread_attr_init (&my_pthread_attr);
-
- for (i = 1; i <= 10000; ++i) {
- if (i%100 == 0) fprintf (stderr, "%i ", i);
- if (i%1000 == 0) fprintf (stderr, "\n");
-#ifndef STATIC
- /* Some glibc versions don't like static multithreaded programs doing this. */
- if (i==5000) __mf_set_options ("-thread-stack=192");
-#endif
- rc = pthread_create (&h, &my_pthread_attr,
- func, NULL);
- if (rc)
- break;
-
- rc = pthread_join (h, NULL);
- if (rc)
- break;
- }
-
- rc = pthread_attr_destroy (&my_pthread_attr);
-}
-
-int main ()
-{
- test ();
-
- return (0);
-}
-
-/* { dg-timeout 30 } */
-/* { dg-output "100 200 300 400 500 600 700 800 900 1000 \n" } */
-/* { dg-output "1100 1200 1300 1400 1500 1600 1700 1800 1900 2000 \n" } */
-/* { dg-output "2100 2200 2300 2400 2500 2600 2700 2800 2900 3000 \n" } */
-/* { dg-output "3100 3200 3300 3400 3500 3600 3700 3800 3900 4000 \n" } */
-/* { dg-output "4100 4200 4300 4400 4500 4600 4700 4800 4900 5000 \n" } */
-/* { dg-output "5100 5200 5300 5400 5500 5600 5700 5800 5900 6000 \n" } */
-/* { dg-output "6100 6200 6300 6400 6500 6600 6700 6800 6900 7000 \n" } */
-/* { dg-output "7100 7200 7300 7400 7500 7600 7700 7800 7900 8000 \n" } */
-/* { dg-output "8100 8200 8300 8400 8500 8600 8700 8800 8900 9000 \n" } */
-/* { dg-output "9100 9200 9300 9400 9500 9600 9700 9800 9900 10000 \n" } */
-
diff --git a/libmudflap/testsuite/libmudflap.cth/pass59-frag.c b/libmudflap/testsuite/libmudflap.cth/pass59-frag.c
deleted file mode 100644
index 49013067705..00000000000
--- a/libmudflap/testsuite/libmudflap.cth/pass59-frag.c
+++ /dev/null
@@ -1,39 +0,0 @@
-#include <stdio.h>
-#include <pthread.h>
-
-/* PR 28578 */
-
-void* test_thread(void* arg)
-{
- printf("Hello from thread!\n");
- pthread_exit(NULL);
- return 0;
-}
-
-int main()
-{
- pthread_t thread;
- void *arg = NULL;
- pthread_create(&thread, NULL, test_thread, arg);
- pthread_join(thread, NULL);
- pthread_exit(NULL);
- return 0;
-}
-
-/* { dg-output "Hello from thread!\n" } */
-
-#if 0
-
-/* Even this test case replicates the problem. However, when built in
- static mode, it blows up during __mf_init (?!?!?!) with a
- pthread_mutex_lock deadlock error. */
-
-#include <stdio.h>
-#include <pthread.h>
-
-int main ()
-{
- pthread_exit(NULL);
- return 0;
-}
-#endif
diff --git a/libmudflap/testsuite/mfconfig.exp.in b/libmudflap/testsuite/mfconfig.exp.in
deleted file mode 100644
index bed16542cad..00000000000
--- a/libmudflap/testsuite/mfconfig.exp.in
+++ /dev/null
@@ -1,4 +0,0 @@
-global mfconfig_libs
-set mfconfig_libs "@LIBS@"
-global libmudflapth
-set libmudflapth "@build_libmudflapth@"
diff --git a/libobjc/ChangeLog b/libobjc/ChangeLog
index c2e1a2887b5..85b864abe01 100644
--- a/libobjc/ChangeLog
+++ b/libobjc/ChangeLog
@@ -1,3 +1,7 @@
+2013-09-20 Alan Modra <amodra@gmail.com>
+
+ * configure: Regenerate.
+
2013-07-21 Ondřej Bílka <neleai@seznam.cz>
* class.c: Fix typos.
diff --git a/libobjc/configure b/libobjc/configure
index a220b155893..dd39d7ec8b4 100755
--- a/libobjc/configure
+++ b/libobjc/configure
@@ -6056,7 +6056,7 @@ ia64-*-hpux*)
rm -rf conftest*
;;
-x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \
+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
@@ -6081,7 +6081,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
;;
esac
;;
- ppc64-*linux*|powerpc64-*linux*)
+ powerpc64le-*linux*)
+ LD="${LD-ld} -m elf32lppclinux"
+ ;;
+ powerpc64-*linux*)
LD="${LD-ld} -m elf32ppclinux"
;;
s390x-*linux*)
@@ -6100,7 +6103,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
x86_64-*linux*)
LD="${LD-ld} -m elf_x86_64"
;;
- ppc*-*linux*|powerpc*-*linux*)
+ powerpcle-*linux*)
+ LD="${LD-ld} -m elf64lppc"
+ ;;
+ powerpc-*linux*)
LD="${LD-ld} -m elf64ppc"
;;
s390*-*linux*|s390*-*tpf*)
@@ -10595,7 +10601,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 10598 "configure"
+#line 10604 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -10701,7 +10707,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 10704 "configure"
+#line 10710 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -11472,7 +11478,7 @@ if test "${enable_sjlj_exceptions+set}" = set; then :
enableval=$enable_sjlj_exceptions; :
else
cat > conftest.$ac_ext << EOF
-#line 11475 "configure"
+#line 11481 "configure"
@interface Frob
@end
@implementation Frob
diff --git a/libquadmath/ChangeLog b/libquadmath/ChangeLog
index f04c70180b5..d3c17f67d5d 100644
--- a/libquadmath/ChangeLog
+++ b/libquadmath/ChangeLog
@@ -1,3 +1,7 @@
+2013-09-20 Alan Modra <amodra@gmail.com>
+
+ * configure: Regenerate.
+
2013-03-06 Shakthi Kannan <shakthimaan@gmail.com>
PR libquadmath/55473
diff --git a/libquadmath/configure b/libquadmath/configure
index 148e0e277dd..907e0cf05cd 100755
--- a/libquadmath/configure
+++ b/libquadmath/configure
@@ -646,7 +646,6 @@ CPP
am__fastdepCC_FALSE
am__fastdepCC_TRUE
CCDEPMODE
-am__nodep
AMDEPBACKSLASH
AMDEP_FALSE
AMDEP_TRUE
@@ -2842,11 +2841,11 @@ MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
# We need awk for the "check" target. The system "awk" is bad on
# some platforms.
-# Always define AMTAR for backward compatibility. Yes, it's still used
-# in the wild :-( We should find a proper way to deprecate it ...
-AMTAR='$${TAR-tar}'
+# Always define AMTAR for backward compatibility.
-am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'
+AMTAR=${AMTAR-"${am_missing_run}tar"}
+
+am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'
@@ -2923,7 +2922,6 @@ fi
if test "x$enable_dependency_tracking" != xno; then
am_depcomp="$ac_aux_dir/depcomp"
AMDEPBACKSLASH='\'
- am__nodep='_no'
fi
if test "x$enable_dependency_tracking" != xno; then
AMDEP_TRUE=
@@ -3741,7 +3739,6 @@ else
# 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'.
- rm -rf conftest.dir
mkdir conftest.dir
# Copy depcomp to subdir because otherwise we won't find it if we're
# using a relative directory.
@@ -3801,7 +3798,7 @@ else
break
fi
;;
- msvc7 | msvc7msys | msvisualcpp | msvcmsys)
+ msvisualcpp | msvcmsys)
# This compiler won't grok `-c -o', but also, the minuso test has
# not run yet. These depmodes are late enough in the game, and
# so weak that their functioning should not be impacted.
@@ -6251,7 +6248,7 @@ ia64-*-hpux*)
rm -rf conftest*
;;
-x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \
+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
@@ -6276,7 +6273,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
;;
esac
;;
- ppc64-*linux*|powerpc64-*linux*)
+ powerpc64le-*linux*)
+ LD="${LD-ld} -m elf32lppclinux"
+ ;;
+ powerpc64-*linux*)
LD="${LD-ld} -m elf32ppclinux"
;;
s390x-*linux*)
@@ -6295,7 +6295,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
x86_64-*linux*)
LD="${LD-ld} -m elf_x86_64"
;;
- ppc*-*linux*|powerpc*-*linux*)
+ powerpcle-*linux*)
+ LD="${LD-ld} -m elf64lppc"
+ ;;
+ powerpc-*linux*)
LD="${LD-ld} -m elf64ppc"
;;
s390*-*linux*|s390*-*tpf*)
@@ -10524,7 +10527,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 10527 "configure"
+#line 10530 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -10630,7 +10633,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 10633 "configure"
+#line 10636 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -11519,7 +11522,6 @@ else
# 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'.
- rm -rf conftest.dir
mkdir conftest.dir
# Copy depcomp to subdir because otherwise we won't find it if we're
# using a relative directory.
@@ -11579,7 +11581,7 @@ else
break
fi
;;
- msvc7 | msvc7msys | msvisualcpp | msvcmsys)
+ msvisualcpp | msvcmsys)
# This compiler won't grok `-c -o', but also, the minuso test has
# not run yet. These depmodes are late enough in the game, and
# so weak that their functioning should not be impacted.
diff --git a/libsanitizer/ChangeLog b/libsanitizer/ChangeLog
index f5162c90250..3d790fe75d7 100644
--- a/libsanitizer/ChangeLog
+++ b/libsanitizer/ChangeLog
@@ -1,3 +1,62 @@
+2013-11-05 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR sanitizer/59018
+ * sanitizer_common/sanitizer_platform_limits_posix.cc
+ (struct_user_fpxregs_struct_sz): Initialize to 0 if __x86_64__ is
+ defined.
+
+2013-11-05 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR sanitizer/59018
+ * sanitizer_common/sanitizer_platform_limits_linux.cc
+ (struct_kernel_stat64_sz): Initialize to 0 if __x86_64__ is
+ defined.
+ * sanitizer_common/sanitizer_platform_limits_posix.h
+ (__sanitizer_dirent): Use 64-bit d_ino/d_off if __x86_64__ is
+ defined.
+ (__sanitizer___kernel_uid_t): Typedef as unsigned if __x86_64__
+ is defined.
+ (__sanitizer___kernel_gid_t): Likewise.
+ (__sanitizer___kernel_off_t): Typedef as long long if __x86_64__
+ is defined.
+
+2013-11-05 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR sanitizer/59018
+ * sanitizer_common/sanitizer_linux.cc (internal_clone): Allocate
+ 2 64-bit integers to save and restore fn and arg. Properly load
+ newtls/child_tidptr into r8/r10.
+
+2013-11-05 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR sanitizer/59018
+ * sanitizer_common/sanitizer_linux.cc (internal_mmap,
+ internal_munmap, internal_open, internal_read, internal_write,
+ internal_stat, internal_lstat, internal_fstat, internal_readlink,
+ internal_unlink, internal_execve, NanoTime, BlockingMutex::Lock,
+ BlockingMutex::Unlock, internal_ptrace, internal_getdents,
+ internal_sigaltstack): Cast pointers to uptr for 64-bit syscalls.
+
+2013-11-04 Kostya Serebryany <kcc@google.com>
+
+ * All source files: Merge from upstream r191666.
+ * merge.sh: Added lsan.
+ * configure.ac (AC_CONFIG_FILES): Added lsan.
+ * Makefile.am (SUBDIRS): Added lsan.
+ * sanitizer_common/Makefile.am (sanitizer_common_files): Added new fles.
+ * asan/Makefile.am (asan_files): Added new files.
+ (libasan_la_LIBADD): Added a dependency on lsan.
+ * lsan/Makefile.am: New file.
+ * asan/Makefile.in: Regenerate.
+ * lsan/Makefile.in: Regenerate.
+ * Makefile.in: Regenerate.
+ * configure: Regenerate.
+ * sanitizer_common/Makefile.in: Regenerate.
+
+2013-09-20 Alan Modra <amodra@gmail.com>
+
+ * configure: Regenerate.
+
2013-09-01 Iain Sandoe <iain@codesourcery.com>
* ubsan/Makefile.am (libubsan_la_LIBADD): Revise to omit
@@ -49,7 +108,7 @@
* asan/asan_preinit.cc: New file, synced from upstream.
* asan/asan_rtl.cc: Remove preinit stuff, synced from upstream.
-2013-02-21 Jack Howarth <howarth@bromo.med.uc.edu>
+2013-02-21 Jack Howarth <howarth@bromo.med.uc.edu>
* asan/Makefile.am (libasan_la_SOURCES): Remove deprecated
dynamic/asan_interceptors_dynamic.cc.
@@ -205,7 +264,7 @@
* configure.tgt: Enable build on powerpc*-linux.
-2012-12-06 Jack Howarth <howarth@bromo.med.uc.edu>
+2012-12-06 Jack Howarth <howarth@bromo.med.uc.edu>
PR 55599/sanitizer
* configure.ac: Set enable_static=no on darwin.
@@ -220,7 +279,7 @@
* All files: Merge from upstream r169371.
2012-12-04 Kostya Serebryany <kcc@google.com>
- Jack Howarth <howarth@bromo.med.uc.edu>
+ Jack Howarth <howarth@bromo.med.uc.edu>
PR 55521/sanitizer
* configure.ac: Define USING_MAC_INTERPOSE when on darwin.
@@ -286,7 +345,7 @@
* All files: Merge from upstream r168699.
2012-11-24 Kostya Serebryany <kcc@google.com>
- Jack Howarth <howarth@bromo.med.uc.edu>
+ Jack Howarth <howarth@bromo.med.uc.edu>
* interception/mach_override/mach_override.c: Migrate from llvm.
* interception/mach_override/mach_override.h: Likewise.
diff --git a/libsanitizer/MERGE b/libsanitizer/MERGE
index 28d1e49ab77..0431b147a16 100644
--- a/libsanitizer/MERGE
+++ b/libsanitizer/MERGE
@@ -1,4 +1,4 @@
-175733
+191666
The first line of this file holds the svn revision number of the
last merge done from the master library sources.
diff --git a/libsanitizer/Makefile.am b/libsanitizer/Makefile.am
index 739c33babbe..15c11ecb2d7 100644
--- a/libsanitizer/Makefile.am
+++ b/libsanitizer/Makefile.am
@@ -1,13 +1,13 @@
ACLOCAL_AMFLAGS = -I .. -I ../config
if TSAN_SUPPORTED
-SUBDIRS = interception sanitizer_common asan tsan ubsan
+SUBDIRS = interception sanitizer_common lsan asan tsan ubsan
else
-SUBDIRS = interception sanitizer_common asan ubsan
+SUBDIRS = interception sanitizer_common lsan asan ubsan
endif
if USING_MAC_INTERPOSE
-SUBDIRS = sanitizer_common asan ubsan
+SUBDIRS = sanitizer_common lsan asan ubsan
endif
# Work around what appears to be a GNU make bug handling MAKEFLAGS
diff --git a/libsanitizer/Makefile.in b/libsanitizer/Makefile.in
index fca1c4e0dc3..cdd6fb202bd 100644
--- a/libsanitizer/Makefile.in
+++ b/libsanitizer/Makefile.in
@@ -98,7 +98,7 @@ AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
$(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS
ETAGS = etags
CTAGS = ctags
-DIST_SUBDIRS = interception sanitizer_common asan ubsan tsan
+DIST_SUBDIRS = interception sanitizer_common lsan asan ubsan tsan
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AR = @AR@
@@ -231,9 +231,9 @@ top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
ACLOCAL_AMFLAGS = -I .. -I ../config
-@TSAN_SUPPORTED_FALSE@SUBDIRS = interception sanitizer_common asan ubsan
-@TSAN_SUPPORTED_TRUE@SUBDIRS = interception sanitizer_common asan tsan ubsan
-@USING_MAC_INTERPOSE_TRUE@SUBDIRS = sanitizer_common asan ubsan
+@TSAN_SUPPORTED_FALSE@SUBDIRS = interception sanitizer_common lsan asan ubsan
+@TSAN_SUPPORTED_TRUE@SUBDIRS = interception sanitizer_common lsan asan tsan ubsan
+@USING_MAC_INTERPOSE_TRUE@SUBDIRS = sanitizer_common lsan asan ubsan
# Work around what appears to be a GNU make bug handling MAKEFLAGS
# values defined in terms of make variables, as is the case for CC and
diff --git a/libsanitizer/asan/Makefile.am b/libsanitizer/asan/Makefile.am
index f7847db3647..8764007ca45 100644
--- a/libsanitizer/asan/Makefile.am
+++ b/libsanitizer/asan/Makefile.am
@@ -15,32 +15,31 @@ toolexeclib_LTLIBRARIES = libasan.la
nodist_toolexeclib_HEADERS = libasan_preinit.o
asan_files = \
- asan_allocator.cc \
asan_allocator2.cc \
- asan_interceptors.cc \
- asan_mac.cc \
- asan_malloc_mac.cc \
- asan_new_delete.cc \
- asan_posix.cc \
- asan_rtl.cc \
- asan_stats.cc \
- asan_thread_registry.cc \
+ asan_dll_thunk.cc \
asan_fake_stack.cc \
asan_globals.cc \
+ asan_interceptors.cc \
asan_linux.cc \
+ asan_mac.cc \
asan_malloc_linux.cc \
+ asan_malloc_mac.cc \
asan_malloc_win.cc \
+ asan_new_delete.cc \
asan_poisoning.cc \
+ asan_posix.cc \
asan_report.cc \
+ asan_rtl.cc \
asan_stack.cc \
+ asan_stats.cc \
asan_thread.cc \
asan_win.cc
libasan_la_SOURCES = $(asan_files)
if USING_MAC_INTERPOSE
-libasan_la_LIBADD = $(top_builddir)/sanitizer_common/libsanitizer_common.la
+libasan_la_LIBADD = $(top_builddir)/sanitizer_common/libsanitizer_common.la $(top_builddir)/lsan/libsanitizer_lsan.la
else
-libasan_la_LIBADD = $(top_builddir)/sanitizer_common/libsanitizer_common.la $(top_builddir)/interception/libinterception.la
+libasan_la_LIBADD = $(top_builddir)/sanitizer_common/libsanitizer_common.la $(top_builddir)/lsan/libsanitizer_lsan.la $(top_builddir)/interception/libinterception.la
endif
libasan_la_LIBADD += $(LIBSTDCXX_RAW_CXX_LDFLAGS)
diff --git a/libsanitizer/asan/Makefile.in b/libsanitizer/asan/Makefile.in
index 8bc0a3d0838..70d87676a55 100644
--- a/libsanitizer/asan/Makefile.in
+++ b/libsanitizer/asan/Makefile.in
@@ -104,17 +104,18 @@ am__installdirs = "$(DESTDIR)$(toolexeclibdir)" \
LTLIBRARIES = $(toolexeclib_LTLIBRARIES)
am__DEPENDENCIES_1 =
@USING_MAC_INTERPOSE_FALSE@libasan_la_DEPENDENCIES = $(top_builddir)/sanitizer_common/libsanitizer_common.la \
+@USING_MAC_INTERPOSE_FALSE@ $(top_builddir)/lsan/libsanitizer_lsan.la \
@USING_MAC_INTERPOSE_FALSE@ $(top_builddir)/interception/libinterception.la \
@USING_MAC_INTERPOSE_FALSE@ $(am__DEPENDENCIES_1)
@USING_MAC_INTERPOSE_TRUE@libasan_la_DEPENDENCIES = $(top_builddir)/sanitizer_common/libsanitizer_common.la \
+@USING_MAC_INTERPOSE_TRUE@ $(top_builddir)/lsan/libsanitizer_lsan.la \
@USING_MAC_INTERPOSE_TRUE@ $(am__DEPENDENCIES_1)
-am__objects_1 = asan_allocator.lo asan_allocator2.lo \
- asan_interceptors.lo asan_mac.lo asan_malloc_mac.lo \
- asan_new_delete.lo asan_posix.lo asan_rtl.lo asan_stats.lo \
- asan_thread_registry.lo asan_fake_stack.lo asan_globals.lo \
- asan_linux.lo asan_malloc_linux.lo asan_malloc_win.lo \
- asan_poisoning.lo asan_report.lo asan_stack.lo asan_thread.lo \
- asan_win.lo
+am__objects_1 = asan_allocator2.lo asan_dll_thunk.lo \
+ asan_fake_stack.lo asan_globals.lo asan_interceptors.lo \
+ asan_linux.lo asan_mac.lo asan_malloc_linux.lo \
+ asan_malloc_mac.lo asan_malloc_win.lo asan_new_delete.lo \
+ asan_poisoning.lo asan_posix.lo asan_report.lo asan_rtl.lo \
+ asan_stack.lo asan_stats.lo asan_thread.lo asan_win.lo
am_libasan_la_OBJECTS = $(am__objects_1)
libasan_la_OBJECTS = $(am_libasan_la_OBJECTS)
libasan_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
@@ -288,32 +289,33 @@ ACLOCAL_AMFLAGS = -I $(top_srcdir) -I $(top_srcdir)/config
toolexeclib_LTLIBRARIES = libasan.la
nodist_toolexeclib_HEADERS = libasan_preinit.o
asan_files = \
- asan_allocator.cc \
asan_allocator2.cc \
- asan_interceptors.cc \
- asan_mac.cc \
- asan_malloc_mac.cc \
- asan_new_delete.cc \
- asan_posix.cc \
- asan_rtl.cc \
- asan_stats.cc \
- asan_thread_registry.cc \
+ asan_dll_thunk.cc \
asan_fake_stack.cc \
asan_globals.cc \
+ asan_interceptors.cc \
asan_linux.cc \
+ asan_mac.cc \
asan_malloc_linux.cc \
+ asan_malloc_mac.cc \
asan_malloc_win.cc \
+ asan_new_delete.cc \
asan_poisoning.cc \
+ asan_posix.cc \
asan_report.cc \
+ asan_rtl.cc \
asan_stack.cc \
+ asan_stats.cc \
asan_thread.cc \
asan_win.cc
libasan_la_SOURCES = $(asan_files)
@USING_MAC_INTERPOSE_FALSE@libasan_la_LIBADD = $(top_builddir)/sanitizer_common/libsanitizer_common.la \
+@USING_MAC_INTERPOSE_FALSE@ $(top_builddir)/lsan/libsanitizer_lsan.la \
@USING_MAC_INTERPOSE_FALSE@ $(top_builddir)/interception/libinterception.la \
@USING_MAC_INTERPOSE_FALSE@ $(LIBSTDCXX_RAW_CXX_LDFLAGS)
@USING_MAC_INTERPOSE_TRUE@libasan_la_LIBADD = $(top_builddir)/sanitizer_common/libsanitizer_common.la \
+@USING_MAC_INTERPOSE_TRUE@ $(top_builddir)/lsan/libsanitizer_lsan.la \
@USING_MAC_INTERPOSE_TRUE@ $(LIBSTDCXX_RAW_CXX_LDFLAGS)
libasan_la_LDFLAGS = -version-info `grep -v '^\#' $(srcdir)/libtool-version` -lpthread -ldl
@@ -431,8 +433,8 @@ mostlyclean-compile:
distclean-compile:
-rm -f *.tab.c
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asan_allocator.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asan_allocator2.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asan_dll_thunk.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asan_fake_stack.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asan_globals.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asan_interceptors.Plo@am__quote@
@@ -449,7 +451,6 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asan_stack.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asan_stats.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asan_thread.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asan_thread_registry.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asan_win.Plo@am__quote@
.cc.o:
diff --git a/libsanitizer/asan/asan_allocator.cc b/libsanitizer/asan/asan_allocator.cc
deleted file mode 100644
index 4e97ff57530..00000000000
--- a/libsanitizer/asan/asan_allocator.cc
+++ /dev/null
@@ -1,811 +0,0 @@
-//===-- asan_allocator.cc -------------------------------------------------===//
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file is a part of AddressSanitizer, an address sanity checker.
-//
-// Implementation of ASan's memory allocator.
-// Evey piece of memory (AsanChunk) allocated by the allocator
-// has a left redzone of REDZONE bytes and
-// a right redzone such that the end of the chunk is aligned by REDZONE
-// (i.e. the right redzone is between 0 and REDZONE-1).
-// The left redzone is always poisoned.
-// The right redzone is poisoned on malloc, the body is poisoned on free.
-// Once freed, a chunk is moved to a quarantine (fifo list).
-// After quarantine, a chunk is returned to freelists.
-//
-// The left redzone contains ASan's internal data and the stack trace of
-// the malloc call.
-// Once freed, the body of the chunk contains the stack trace of the free call.
-//
-//===----------------------------------------------------------------------===//
-#include "asan_allocator.h"
-
-#if ASAN_ALLOCATOR_VERSION == 1
-#include "asan_interceptors.h"
-#include "asan_internal.h"
-#include "asan_mapping.h"
-#include "asan_stats.h"
-#include "asan_report.h"
-#include "asan_thread.h"
-#include "asan_thread_registry.h"
-#include "sanitizer_common/sanitizer_allocator.h"
-#include "sanitizer_common/sanitizer_atomic.h"
-#include "sanitizer_common/sanitizer_mutex.h"
-
-namespace __asan {
-
-#define REDZONE ((uptr)(flags()->redzone))
-static const uptr kMinAllocSize = REDZONE * 2;
-static const u64 kMaxAvailableRam = 128ULL << 30; // 128G
-static const uptr kMaxThreadLocalQuarantine = 1 << 20; // 1M
-
-static const uptr kMinMmapSize = (ASAN_LOW_MEMORY) ? 4UL << 17 : 4UL << 20;
-static const uptr kMaxSizeForThreadLocalFreeList =
- (ASAN_LOW_MEMORY) ? 1 << 15 : 1 << 17;
-
-// Size classes less than kMallocSizeClassStep are powers of two.
-// All other size classes are multiples of kMallocSizeClassStep.
-static const uptr kMallocSizeClassStepLog = 26;
-static const uptr kMallocSizeClassStep = 1UL << kMallocSizeClassStepLog;
-
-static const uptr kMaxAllowedMallocSize =
- (SANITIZER_WORDSIZE == 32) ? 3UL << 30 : 8UL << 30;
-
-static inline uptr SizeClassToSize(u8 size_class) {
- CHECK(size_class < kNumberOfSizeClasses);
- if (size_class <= kMallocSizeClassStepLog) {
- return 1UL << size_class;
- } else {
- return (size_class - kMallocSizeClassStepLog) * kMallocSizeClassStep;
- }
-}
-
-static inline u8 SizeToSizeClass(uptr size) {
- u8 res = 0;
- if (size <= kMallocSizeClassStep) {
- uptr rounded = RoundUpToPowerOfTwo(size);
- res = Log2(rounded);
- } else {
- res = ((size + kMallocSizeClassStep - 1) / kMallocSizeClassStep)
- + kMallocSizeClassStepLog;
- }
- CHECK(res < kNumberOfSizeClasses);
- CHECK(size <= SizeClassToSize(res));
- return res;
-}
-
-// Given REDZONE bytes, we need to mark first size bytes
-// as addressable and the rest REDZONE-size bytes as unaddressable.
-static void PoisonHeapPartialRightRedzone(uptr mem, uptr size) {
- CHECK(size <= REDZONE);
- CHECK(IsAligned(mem, REDZONE));
- CHECK(IsPowerOfTwo(SHADOW_GRANULARITY));
- CHECK(IsPowerOfTwo(REDZONE));
- CHECK(REDZONE >= SHADOW_GRANULARITY);
- PoisonShadowPartialRightRedzone(mem, size, REDZONE,
- kAsanHeapRightRedzoneMagic);
-}
-
-static u8 *MmapNewPagesAndPoisonShadow(uptr size) {
- CHECK(IsAligned(size, GetPageSizeCached()));
- u8 *res = (u8*)MmapOrDie(size, __FUNCTION__);
- PoisonShadow((uptr)res, size, kAsanHeapLeftRedzoneMagic);
- if (flags()->debug) {
- Printf("ASAN_MMAP: [%p, %p)\n", res, res + size);
- }
- return res;
-}
-
-// Every chunk of memory allocated by this allocator can be in one of 3 states:
-// CHUNK_AVAILABLE: the chunk is in the free list and ready to be allocated.
-// CHUNK_ALLOCATED: the chunk is allocated and not yet freed.
-// CHUNK_QUARANTINE: the chunk was freed and put into quarantine zone.
-//
-// The pseudo state CHUNK_MEMALIGN is used to mark that the address is not
-// the beginning of a AsanChunk (in which the actual chunk resides at
-// this - this->used_size).
-//
-// The magic numbers for the enum values are taken randomly.
-enum {
- CHUNK_AVAILABLE = 0x57,
- CHUNK_ALLOCATED = 0x32,
- CHUNK_QUARANTINE = 0x19,
- CHUNK_MEMALIGN = 0xDC
-};
-
-struct ChunkBase {
- // First 8 bytes.
- uptr chunk_state : 8;
- uptr alloc_tid : 24;
- uptr size_class : 8;
- uptr free_tid : 24;
-
- // Second 8 bytes.
- uptr alignment_log : 8;
- uptr alloc_type : 2;
- uptr used_size : FIRST_32_SECOND_64(32, 54); // Size requested by the user.
-
- // This field may overlap with the user area and thus should not
- // be used while the chunk is in CHUNK_ALLOCATED state.
- AsanChunk *next;
-
- // Typically the beginning of the user-accessible memory is 'this'+REDZONE
- // and is also aligned by REDZONE. However, if the memory is allocated
- // by memalign, the alignment might be higher and the user-accessible memory
- // starts at the first properly aligned address after 'this'.
- uptr Beg() { return RoundUpTo((uptr)this + 1, 1 << alignment_log); }
- uptr Size() { return SizeClassToSize(size_class); }
- u8 SizeClass() { return size_class; }
-};
-
-struct AsanChunk: public ChunkBase {
- u32 *compressed_alloc_stack() {
- return (u32*)((uptr)this + sizeof(ChunkBase));
- }
- u32 *compressed_free_stack() {
- return (u32*)((uptr)this + Max((uptr)REDZONE, (uptr)sizeof(ChunkBase)));
- }
-
- // The left redzone after the ChunkBase is given to the alloc stack trace.
- uptr compressed_alloc_stack_size() {
- if (REDZONE < sizeof(ChunkBase)) return 0;
- return (REDZONE - sizeof(ChunkBase)) / sizeof(u32);
- }
- uptr compressed_free_stack_size() {
- if (REDZONE < sizeof(ChunkBase)) return 0;
- return (REDZONE) / sizeof(u32);
- }
-};
-
-uptr AsanChunkView::Beg() { return chunk_->Beg(); }
-uptr AsanChunkView::End() { return Beg() + UsedSize(); }
-uptr AsanChunkView::UsedSize() { return chunk_->used_size; }
-uptr AsanChunkView::AllocTid() { return chunk_->alloc_tid; }
-uptr AsanChunkView::FreeTid() { return chunk_->free_tid; }
-
-void AsanChunkView::GetAllocStack(StackTrace *stack) {
- StackTrace::UncompressStack(stack, chunk_->compressed_alloc_stack(),
- chunk_->compressed_alloc_stack_size());
-}
-
-void AsanChunkView::GetFreeStack(StackTrace *stack) {
- StackTrace::UncompressStack(stack, chunk_->compressed_free_stack(),
- chunk_->compressed_free_stack_size());
-}
-
-static AsanChunk *PtrToChunk(uptr ptr) {
- AsanChunk *m = (AsanChunk*)(ptr - REDZONE);
- if (m->chunk_state == CHUNK_MEMALIGN) {
- m = (AsanChunk*)((uptr)m - m->used_size);
- }
- return m;
-}
-
-void AsanChunkFifoList::PushList(AsanChunkFifoList *q) {
- CHECK(q->size() > 0);
- size_ += q->size();
- append_back(q);
- q->clear();
-}
-
-void AsanChunkFifoList::Push(AsanChunk *n) {
- push_back(n);
- size_ += n->Size();
-}
-
-// Interesting performance observation: this function takes up to 15% of overal
-// allocator time. That's because *first_ has been evicted from cache long time
-// ago. Not sure if we can or want to do anything with this.
-AsanChunk *AsanChunkFifoList::Pop() {
- CHECK(first_);
- AsanChunk *res = front();
- size_ -= res->Size();
- pop_front();
- return res;
-}
-
-// All pages we ever allocated.
-struct PageGroup {
- uptr beg;
- uptr end;
- uptr size_of_chunk;
- uptr last_chunk;
- bool InRange(uptr addr) {
- return addr >= beg && addr < end;
- }
-};
-
-class MallocInfo {
- public:
- explicit MallocInfo(LinkerInitialized x) : mu_(x) { }
-
- AsanChunk *AllocateChunks(u8 size_class, uptr n_chunks) {
- AsanChunk *m = 0;
- AsanChunk **fl = &free_lists_[size_class];
- {
- BlockingMutexLock lock(&mu_);
- for (uptr i = 0; i < n_chunks; i++) {
- if (!(*fl)) {
- *fl = GetNewChunks(size_class);
- }
- AsanChunk *t = *fl;
- *fl = t->next;
- t->next = m;
- CHECK(t->chunk_state == CHUNK_AVAILABLE);
- m = t;
- }
- }
- return m;
- }
-
- void SwallowThreadLocalMallocStorage(AsanThreadLocalMallocStorage *x,
- bool eat_free_lists) {
- CHECK(flags()->quarantine_size > 0);
- BlockingMutexLock lock(&mu_);
- AsanChunkFifoList *q = &x->quarantine_;
- if (q->size() > 0) {
- quarantine_.PushList(q);
- while (quarantine_.size() > (uptr)flags()->quarantine_size) {
- QuarantinePop();
- }
- }
- if (eat_free_lists) {
- for (uptr size_class = 0; size_class < kNumberOfSizeClasses;
- size_class++) {
- AsanChunk *m = x->free_lists_[size_class];
- while (m) {
- AsanChunk *t = m->next;
- m->next = free_lists_[size_class];
- free_lists_[size_class] = m;
- m = t;
- }
- x->free_lists_[size_class] = 0;
- }
- }
- }
-
- void BypassThreadLocalQuarantine(AsanChunk *chunk) {
- BlockingMutexLock lock(&mu_);
- quarantine_.Push(chunk);
- }
-
- AsanChunk *FindChunkByAddr(uptr addr) {
- BlockingMutexLock lock(&mu_);
- return FindChunkByAddrUnlocked(addr);
- }
-
- uptr AllocationSize(uptr ptr) {
- if (!ptr) return 0;
- BlockingMutexLock lock(&mu_);
-
- // Make sure this is our chunk and |ptr| actually points to the beginning
- // of the allocated memory.
- AsanChunk *m = FindChunkByAddrUnlocked(ptr);
- if (!m || m->Beg() != ptr) return 0;
-
- if (m->chunk_state == CHUNK_ALLOCATED) {
- return m->used_size;
- } else {
- return 0;
- }
- }
-
- void ForceLock() {
- mu_.Lock();
- }
-
- void ForceUnlock() {
- mu_.Unlock();
- }
-
- void PrintStatus() {
- BlockingMutexLock lock(&mu_);
- uptr malloced = 0;
-
- Printf(" MallocInfo: in quarantine: %zu malloced: %zu; ",
- quarantine_.size() >> 20, malloced >> 20);
- for (uptr j = 1; j < kNumberOfSizeClasses; j++) {
- AsanChunk *i = free_lists_[j];
- if (!i) continue;
- uptr t = 0;
- for (; i; i = i->next) {
- t += i->Size();
- }
- Printf("%zu:%zu ", j, t >> 20);
- }
- Printf("\n");
- }
-
- PageGroup *FindPageGroup(uptr addr) {
- BlockingMutexLock lock(&mu_);
- return FindPageGroupUnlocked(addr);
- }
-
- private:
- PageGroup *FindPageGroupUnlocked(uptr addr) {
- int n = atomic_load(&n_page_groups_, memory_order_relaxed);
- // If the page groups are not sorted yet, sort them.
- if (n_sorted_page_groups_ < n) {
- SortArray((uptr*)page_groups_, n);
- n_sorted_page_groups_ = n;
- }
- // Binary search over the page groups.
- int beg = 0, end = n;
- while (beg < end) {
- int med = (beg + end) / 2;
- uptr g = (uptr)page_groups_[med];
- if (addr > g) {
- // 'g' points to the end of the group, so 'addr'
- // may not belong to page_groups_[med] or any previous group.
- beg = med + 1;
- } else {
- // 'addr' may belong to page_groups_[med] or a previous group.
- end = med;
- }
- }
- if (beg >= n)
- return 0;
- PageGroup *g = page_groups_[beg];
- CHECK(g);
- if (g->InRange(addr))
- return g;
- return 0;
- }
-
- // We have an address between two chunks, and we want to report just one.
- AsanChunk *ChooseChunk(uptr addr,
- AsanChunk *left_chunk, AsanChunk *right_chunk) {
- // Prefer an allocated chunk or a chunk from quarantine.
- if (left_chunk->chunk_state == CHUNK_AVAILABLE &&
- right_chunk->chunk_state != CHUNK_AVAILABLE)
- return right_chunk;
- if (right_chunk->chunk_state == CHUNK_AVAILABLE &&
- left_chunk->chunk_state != CHUNK_AVAILABLE)
- return left_chunk;
- // Choose based on offset.
- sptr l_offset = 0, r_offset = 0;
- CHECK(AsanChunkView(left_chunk).AddrIsAtRight(addr, 1, &l_offset));
- CHECK(AsanChunkView(right_chunk).AddrIsAtLeft(addr, 1, &r_offset));
- if (l_offset < r_offset)
- return left_chunk;
- return right_chunk;
- }
-
- AsanChunk *FindChunkByAddrUnlocked(uptr addr) {
- PageGroup *g = FindPageGroupUnlocked(addr);
- if (!g) return 0;
- CHECK(g->size_of_chunk);
- uptr offset_from_beg = addr - g->beg;
- uptr this_chunk_addr = g->beg +
- (offset_from_beg / g->size_of_chunk) * g->size_of_chunk;
- CHECK(g->InRange(this_chunk_addr));
- AsanChunk *m = (AsanChunk*)this_chunk_addr;
- CHECK(m->chunk_state == CHUNK_ALLOCATED ||
- m->chunk_state == CHUNK_AVAILABLE ||
- m->chunk_state == CHUNK_QUARANTINE);
- sptr offset = 0;
- AsanChunkView m_view(m);
- if (m_view.AddrIsInside(addr, 1, &offset))
- return m;
-
- if (m_view.AddrIsAtRight(addr, 1, &offset)) {
- if (this_chunk_addr == g->last_chunk) // rightmost chunk
- return m;
- uptr right_chunk_addr = this_chunk_addr + g->size_of_chunk;
- CHECK(g->InRange(right_chunk_addr));
- return ChooseChunk(addr, m, (AsanChunk*)right_chunk_addr);
- } else {
- CHECK(m_view.AddrIsAtLeft(addr, 1, &offset));
- if (this_chunk_addr == g->beg) // leftmost chunk
- return m;
- uptr left_chunk_addr = this_chunk_addr - g->size_of_chunk;
- CHECK(g->InRange(left_chunk_addr));
- return ChooseChunk(addr, (AsanChunk*)left_chunk_addr, m);
- }
- }
-
- void QuarantinePop() {
- CHECK(quarantine_.size() > 0);
- AsanChunk *m = quarantine_.Pop();
- CHECK(m);
- // if (F_v >= 2) Printf("MallocInfo::pop %p\n", m);
-
- CHECK(m->chunk_state == CHUNK_QUARANTINE);
- m->chunk_state = CHUNK_AVAILABLE;
- PoisonShadow((uptr)m, m->Size(), kAsanHeapLeftRedzoneMagic);
- CHECK(m->alloc_tid >= 0);
- CHECK(m->free_tid >= 0);
-
- uptr size_class = m->SizeClass();
- m->next = free_lists_[size_class];
- free_lists_[size_class] = m;
-
- // Statistics.
- AsanStats &thread_stats = asanThreadRegistry().GetCurrentThreadStats();
- thread_stats.real_frees++;
- thread_stats.really_freed += m->used_size;
- thread_stats.really_freed_redzones += m->Size() - m->used_size;
- thread_stats.really_freed_by_size[m->SizeClass()]++;
- }
-
- // Get a list of newly allocated chunks.
- AsanChunk *GetNewChunks(u8 size_class) {
- uptr size = SizeClassToSize(size_class);
- CHECK(IsPowerOfTwo(kMinMmapSize));
- CHECK(size < kMinMmapSize || (size % kMinMmapSize) == 0);
- uptr mmap_size = Max(size, kMinMmapSize);
- uptr n_chunks = mmap_size / size;
- CHECK(n_chunks * size == mmap_size);
- uptr PageSize = GetPageSizeCached();
- if (size < PageSize) {
- // Size is small, just poison the last chunk.
- n_chunks--;
- } else {
- // Size is large, allocate an extra page at right and poison it.
- mmap_size += PageSize;
- }
- CHECK(n_chunks > 0);
- u8 *mem = MmapNewPagesAndPoisonShadow(mmap_size);
-
- // Statistics.
- AsanStats &thread_stats = asanThreadRegistry().GetCurrentThreadStats();
- thread_stats.mmaps++;
- thread_stats.mmaped += mmap_size;
- thread_stats.mmaped_by_size[size_class] += n_chunks;
-
- AsanChunk *res = 0;
- for (uptr i = 0; i < n_chunks; i++) {
- AsanChunk *m = (AsanChunk*)(mem + i * size);
- m->chunk_state = CHUNK_AVAILABLE;
- m->size_class = size_class;
- m->next = res;
- res = m;
- }
- PageGroup *pg = (PageGroup*)(mem + n_chunks * size);
- // This memory is already poisoned, no need to poison it again.
- pg->beg = (uptr)mem;
- pg->end = pg->beg + mmap_size;
- pg->size_of_chunk = size;
- pg->last_chunk = (uptr)(mem + size * (n_chunks - 1));
- int idx = atomic_fetch_add(&n_page_groups_, 1, memory_order_relaxed);
- CHECK(idx < (int)ARRAY_SIZE(page_groups_));
- page_groups_[idx] = pg;
- return res;
- }
-
- AsanChunk *free_lists_[kNumberOfSizeClasses];
- AsanChunkFifoList quarantine_;
- BlockingMutex mu_;
-
- PageGroup *page_groups_[kMaxAvailableRam / kMinMmapSize];
- atomic_uint32_t n_page_groups_;
- int n_sorted_page_groups_;
-};
-
-static MallocInfo malloc_info(LINKER_INITIALIZED);
-
-void AsanThreadLocalMallocStorage::CommitBack() {
- malloc_info.SwallowThreadLocalMallocStorage(this, true);
-}
-
-AsanChunkView FindHeapChunkByAddress(uptr address) {
- return AsanChunkView(malloc_info.FindChunkByAddr(address));
-}
-
-static u8 *Allocate(uptr alignment, uptr size, StackTrace *stack,
- AllocType alloc_type) {
- __asan_init();
- CHECK(stack);
- if (size == 0) {
- size = 1; // TODO(kcc): do something smarter
- }
- CHECK(IsPowerOfTwo(alignment));
- uptr rounded_size = RoundUpTo(size, REDZONE);
- uptr needed_size = rounded_size + REDZONE;
- if (alignment > REDZONE) {
- needed_size += alignment;
- }
- CHECK(IsAligned(needed_size, REDZONE));
- if (size > kMaxAllowedMallocSize || needed_size > kMaxAllowedMallocSize) {
- Report("WARNING: AddressSanitizer failed to allocate %p bytes\n",
- (void*)size);
- return 0;
- }
-
- u8 size_class = SizeToSizeClass(needed_size);
- uptr size_to_allocate = SizeClassToSize(size_class);
- CHECK(size_to_allocate >= kMinAllocSize);
- CHECK(size_to_allocate >= needed_size);
- CHECK(IsAligned(size_to_allocate, REDZONE));
-
- if (flags()->verbosity >= 3) {
- Printf("Allocate align: %zu size: %zu class: %u real: %zu\n",
- alignment, size, size_class, size_to_allocate);
- }
-
- AsanThread *t = asanThreadRegistry().GetCurrent();
- AsanStats &thread_stats = asanThreadRegistry().GetCurrentThreadStats();
- // Statistics
- thread_stats.mallocs++;
- thread_stats.malloced += size;
- thread_stats.malloced_redzones += size_to_allocate - size;
- thread_stats.malloced_by_size[size_class]++;
-
- AsanChunk *m = 0;
- if (!t || size_to_allocate >= kMaxSizeForThreadLocalFreeList) {
- // get directly from global storage.
- m = malloc_info.AllocateChunks(size_class, 1);
- thread_stats.malloc_large++;
- } else {
- // get from the thread-local storage.
- AsanChunk **fl = &t->malloc_storage().free_lists_[size_class];
- if (!*fl) {
- uptr n_new_chunks = kMaxSizeForThreadLocalFreeList / size_to_allocate;
- *fl = malloc_info.AllocateChunks(size_class, n_new_chunks);
- thread_stats.malloc_small_slow++;
- }
- m = *fl;
- *fl = (*fl)->next;
- }
- CHECK(m);
- CHECK(m->chunk_state == CHUNK_AVAILABLE);
- m->chunk_state = CHUNK_ALLOCATED;
- m->alloc_type = alloc_type;
- m->next = 0;
- CHECK(m->Size() == size_to_allocate);
- uptr addr = (uptr)m + REDZONE;
- CHECK(addr <= (uptr)m->compressed_free_stack());
-
- if (alignment > REDZONE && (addr & (alignment - 1))) {
- addr = RoundUpTo(addr, alignment);
- CHECK((addr & (alignment - 1)) == 0);
- AsanChunk *p = (AsanChunk*)(addr - REDZONE);
- p->chunk_state = CHUNK_MEMALIGN;
- p->used_size = (uptr)p - (uptr)m;
- m->alignment_log = Log2(alignment);
- CHECK(m->Beg() == addr);
- } else {
- m->alignment_log = Log2(REDZONE);
- }
- CHECK(m == PtrToChunk(addr));
- m->used_size = size;
- CHECK(m->Beg() == addr);
- m->alloc_tid = t ? t->tid() : 0;
- m->free_tid = kInvalidTid;
- StackTrace::CompressStack(stack, m->compressed_alloc_stack(),
- m->compressed_alloc_stack_size());
- PoisonShadow(addr, rounded_size, 0);
- if (size < rounded_size) {
- PoisonHeapPartialRightRedzone(addr + rounded_size - REDZONE,
- size & (REDZONE - 1));
- }
- if (size <= (uptr)(flags()->max_malloc_fill_size)) {
- REAL(memset)((void*)addr, 0, rounded_size);
- }
- return (u8*)addr;
-}
-
-static void Deallocate(u8 *ptr, StackTrace *stack, AllocType alloc_type) {
- if (!ptr) return;
- CHECK(stack);
-
- if (flags()->debug) {
- CHECK(malloc_info.FindPageGroup((uptr)ptr));
- }
-
- // Printf("Deallocate %p\n", ptr);
- AsanChunk *m = PtrToChunk((uptr)ptr);
-
- // Flip the chunk_state atomically to avoid race on double-free.
- u8 old_chunk_state = atomic_exchange((atomic_uint8_t*)m, CHUNK_QUARANTINE,
- memory_order_acq_rel);
-
- if (old_chunk_state == CHUNK_QUARANTINE) {
- ReportDoubleFree((uptr)ptr, stack);
- } else if (old_chunk_state != CHUNK_ALLOCATED) {
- ReportFreeNotMalloced((uptr)ptr, stack);
- }
- CHECK(old_chunk_state == CHUNK_ALLOCATED);
- if (m->alloc_type != alloc_type && flags()->alloc_dealloc_mismatch)
- ReportAllocTypeMismatch((uptr)ptr, stack,
- (AllocType)m->alloc_type, (AllocType)alloc_type);
- // With REDZONE==16 m->next is in the user area, otherwise it should be 0.
- CHECK(REDZONE <= 16 || !m->next);
- CHECK(m->free_tid == kInvalidTid);
- CHECK(m->alloc_tid >= 0);
- AsanThread *t = asanThreadRegistry().GetCurrent();
- m->free_tid = t ? t->tid() : 0;
- StackTrace::CompressStack(stack, m->compressed_free_stack(),
- m->compressed_free_stack_size());
- uptr rounded_size = RoundUpTo(m->used_size, REDZONE);
- PoisonShadow((uptr)ptr, rounded_size, kAsanHeapFreeMagic);
-
- // Statistics.
- AsanStats &thread_stats = asanThreadRegistry().GetCurrentThreadStats();
- thread_stats.frees++;
- thread_stats.freed += m->used_size;
- thread_stats.freed_by_size[m->SizeClass()]++;
-
- CHECK(m->chunk_state == CHUNK_QUARANTINE);
-
- if (t) {
- AsanThreadLocalMallocStorage *ms = &t->malloc_storage();
- ms->quarantine_.Push(m);
-
- if (ms->quarantine_.size() > kMaxThreadLocalQuarantine) {
- malloc_info.SwallowThreadLocalMallocStorage(ms, false);
- }
- } else {
- malloc_info.BypassThreadLocalQuarantine(m);
- }
-}
-
-static u8 *Reallocate(u8 *old_ptr, uptr new_size,
- StackTrace *stack) {
- CHECK(old_ptr && new_size);
-
- // Statistics.
- AsanStats &thread_stats = asanThreadRegistry().GetCurrentThreadStats();
- thread_stats.reallocs++;
- thread_stats.realloced += new_size;
-
- AsanChunk *m = PtrToChunk((uptr)old_ptr);
- CHECK(m->chunk_state == CHUNK_ALLOCATED);
- uptr old_size = m->used_size;
- uptr memcpy_size = Min(new_size, old_size);
- u8 *new_ptr = Allocate(0, new_size, stack, FROM_MALLOC);
- if (new_ptr) {
- CHECK(REAL(memcpy) != 0);
- REAL(memcpy)(new_ptr, old_ptr, memcpy_size);
- Deallocate(old_ptr, stack, FROM_MALLOC);
- }
- return new_ptr;
-}
-
-} // namespace __asan
-
-#if !SANITIZER_SUPPORTS_WEAK_HOOKS
-// Provide default (no-op) implementation of malloc hooks.
-extern "C" {
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
-void __asan_malloc_hook(void *ptr, uptr size) {
- (void)ptr;
- (void)size;
-}
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
-void __asan_free_hook(void *ptr) {
- (void)ptr;
-}
-} // extern "C"
-#endif
-
-namespace __asan {
-
-void InitializeAllocator() { }
-
-void PrintInternalAllocatorStats() {
-}
-
-SANITIZER_INTERFACE_ATTRIBUTE
-void *asan_memalign(uptr alignment, uptr size, StackTrace *stack,
- AllocType alloc_type) {
- void *ptr = (void*)Allocate(alignment, size, stack, alloc_type);
- ASAN_MALLOC_HOOK(ptr, size);
- return ptr;
-}
-
-SANITIZER_INTERFACE_ATTRIBUTE
-void asan_free(void *ptr, StackTrace *stack, AllocType alloc_type) {
- ASAN_FREE_HOOK(ptr);
- Deallocate((u8*)ptr, stack, alloc_type);
-}
-
-SANITIZER_INTERFACE_ATTRIBUTE
-void *asan_malloc(uptr size, StackTrace *stack) {
- void *ptr = (void*)Allocate(0, size, stack, FROM_MALLOC);
- ASAN_MALLOC_HOOK(ptr, size);
- return ptr;
-}
-
-void *asan_calloc(uptr nmemb, uptr size, StackTrace *stack) {
- if (__sanitizer::CallocShouldReturnNullDueToOverflow(size, nmemb)) return 0;
- void *ptr = (void*)Allocate(0, nmemb * size, stack, FROM_MALLOC);
- if (ptr)
- REAL(memset)(ptr, 0, nmemb * size);
- ASAN_MALLOC_HOOK(ptr, size);
- return ptr;
-}
-
-void *asan_realloc(void *p, uptr size, StackTrace *stack) {
- if (p == 0) {
- void *ptr = (void*)Allocate(0, size, stack, FROM_MALLOC);
- ASAN_MALLOC_HOOK(ptr, size);
- return ptr;
- } else if (size == 0) {
- ASAN_FREE_HOOK(p);
- Deallocate((u8*)p, stack, FROM_MALLOC);
- return 0;
- }
- return Reallocate((u8*)p, size, stack);
-}
-
-void *asan_valloc(uptr size, StackTrace *stack) {
- void *ptr = (void*)Allocate(GetPageSizeCached(), size, stack, FROM_MALLOC);
- ASAN_MALLOC_HOOK(ptr, size);
- return ptr;
-}
-
-void *asan_pvalloc(uptr size, StackTrace *stack) {
- uptr PageSize = GetPageSizeCached();
- size = RoundUpTo(size, PageSize);
- if (size == 0) {
- // pvalloc(0) should allocate one page.
- size = PageSize;
- }
- void *ptr = (void*)Allocate(PageSize, size, stack, FROM_MALLOC);
- ASAN_MALLOC_HOOK(ptr, size);
- return ptr;
-}
-
-int asan_posix_memalign(void **memptr, uptr alignment, uptr size,
- StackTrace *stack) {
- void *ptr = Allocate(alignment, size, stack, FROM_MALLOC);
- CHECK(IsAligned((uptr)ptr, alignment));
- ASAN_MALLOC_HOOK(ptr, size);
- *memptr = ptr;
- return 0;
-}
-
-uptr asan_malloc_usable_size(void *ptr, StackTrace *stack) {
- CHECK(stack);
- if (ptr == 0) return 0;
- uptr usable_size = malloc_info.AllocationSize((uptr)ptr);
- if (flags()->check_malloc_usable_size && (usable_size == 0)) {
- ReportMallocUsableSizeNotOwned((uptr)ptr, stack);
- }
- return usable_size;
-}
-
-uptr asan_mz_size(const void *ptr) {
- return malloc_info.AllocationSize((uptr)ptr);
-}
-
-void asan_mz_force_lock() {
- malloc_info.ForceLock();
-}
-
-void asan_mz_force_unlock() {
- malloc_info.ForceUnlock();
-}
-
-} // namespace __asan
-
-// ---------------------- Interface ---------------- {{{1
-using namespace __asan; // NOLINT
-
-// ASan allocator doesn't reserve extra bytes, so normally we would
-// just return "size".
-uptr __asan_get_estimated_allocated_size(uptr size) {
- if (size == 0) return 1;
- return Min(size, kMaxAllowedMallocSize);
-}
-
-bool __asan_get_ownership(const void *p) {
- return malloc_info.AllocationSize((uptr)p) > 0;
-}
-
-uptr __asan_get_allocated_size(const void *p) {
- if (p == 0) return 0;
- uptr allocated_size = malloc_info.AllocationSize((uptr)p);
- // Die if p is not malloced or if it is already freed.
- if (allocated_size == 0) {
- GET_STACK_TRACE_FATAL_HERE;
- ReportAsanGetAllocatedSizeNotOwned((uptr)p, &stack);
- }
- return allocated_size;
-}
-#endif // ASAN_ALLOCATOR_VERSION
diff --git a/libsanitizer/asan/asan_allocator.h b/libsanitizer/asan/asan_allocator.h
index df2f520c41a..1f83dcd6780 100644
--- a/libsanitizer/asan/asan_allocator.h
+++ b/libsanitizer/asan/asan_allocator.h
@@ -7,7 +7,7 @@
//
// This file is a part of AddressSanitizer, an address sanity checker.
//
-// ASan-private header for asan_allocator.cc.
+// ASan-private header for asan_allocator2.cc.
//===----------------------------------------------------------------------===//
#ifndef ASAN_ALLOCATOR_H
@@ -17,18 +17,6 @@
#include "asan_interceptors.h"
#include "sanitizer_common/sanitizer_list.h"
-// We are in the process of transitioning from the old allocator (version 1)
-// to a new one (version 2). The change is quite intrusive so both allocators
-// will co-exist in the source base for a while. The actual allocator is chosen
-// at build time by redefining this macro.
-#ifndef ASAN_ALLOCATOR_VERSION
-# if (ASAN_LINUX && !ASAN_ANDROID) || ASAN_MAC || ASAN_WINDOWS
-# define ASAN_ALLOCATOR_VERSION 2
-# else
-# define ASAN_ALLOCATOR_VERSION 1
-# endif
-#endif // ASAN_ALLOCATOR_VERSION
-
namespace __asan {
enum AllocType {
@@ -101,109 +89,17 @@ class AsanChunkFifoList: public IntrusiveList<AsanChunk> {
struct AsanThreadLocalMallocStorage {
explicit AsanThreadLocalMallocStorage(LinkerInitialized x)
-#if ASAN_ALLOCATOR_VERSION == 1
- : quarantine_(x)
-#endif
{ }
AsanThreadLocalMallocStorage() {
CHECK(REAL(memset));
REAL(memset)(this, 0, sizeof(AsanThreadLocalMallocStorage));
}
-#if ASAN_ALLOCATOR_VERSION == 1
- AsanChunkFifoList quarantine_;
- AsanChunk *free_lists_[kNumberOfSizeClasses];
-#else
uptr quarantine_cache[16];
uptr allocator2_cache[96 * (512 * 8 + 16)]; // Opaque.
-#endif
void CommitBack();
};
-// Fake stack frame contains local variables of one function.
-// This struct should fit into a stack redzone (32 bytes).
-struct FakeFrame {
- uptr magic; // Modified by the instrumented code.
- uptr descr; // Modified by the instrumented code.
- FakeFrame *next;
- u64 real_stack : 48;
- u64 size_minus_one : 16;
-};
-
-struct FakeFrameFifo {
- public:
- void FifoPush(FakeFrame *node);
- FakeFrame *FifoPop();
- private:
- FakeFrame *first_, *last_;
-};
-
-class FakeFrameLifo {
- public:
- void LifoPush(FakeFrame *node) {
- node->next = top_;
- top_ = node;
- }
- void LifoPop() {
- CHECK(top_);
- top_ = top_->next;
- }
- FakeFrame *top() { return top_; }
- private:
- FakeFrame *top_;
-};
-
-// For each thread we create a fake stack and place stack objects on this fake
-// stack instead of the real stack. The fake stack is not really a stack but
-// a fast malloc-like allocator so that when a function exits the fake stack
-// is not poped but remains there for quite some time until gets used again.
-// So, we poison the objects on the fake stack when function returns.
-// It helps us find use-after-return bugs.
-// We can not rely on __asan_stack_free being called on every function exit,
-// so we maintain a lifo list of all current fake frames and update it on every
-// call to __asan_stack_malloc.
-class FakeStack {
- public:
- FakeStack();
- explicit FakeStack(LinkerInitialized) {}
- void Init(uptr stack_size);
- void StopUsingFakeStack() { alive_ = false; }
- void Cleanup();
- uptr AllocateStack(uptr size, uptr real_stack);
- static void OnFree(uptr ptr, uptr size, uptr real_stack);
- // Return the bottom of the maped region.
- uptr AddrIsInFakeStack(uptr addr);
- bool StackSize() { return stack_size_; }
-
- private:
- static const uptr kMinStackFrameSizeLog = 9; // Min frame is 512B.
- static const uptr kMaxStackFrameSizeLog = 16; // Max stack frame is 64K.
- static const uptr kMaxStackMallocSize = 1 << kMaxStackFrameSizeLog;
- static const uptr kNumberOfSizeClasses =
- kMaxStackFrameSizeLog - kMinStackFrameSizeLog + 1;
-
- bool AddrIsInSizeClass(uptr addr, uptr size_class);
-
- // Each size class should be large enough to hold all frames.
- uptr ClassMmapSize(uptr size_class);
-
- uptr ClassSize(uptr size_class) {
- return 1UL << (size_class + kMinStackFrameSizeLog);
- }
-
- void DeallocateFrame(FakeFrame *fake_frame);
-
- uptr ComputeSizeClass(uptr alloc_size);
- void AllocateOneSizeClass(uptr size_class);
-
- uptr stack_size_;
- bool alive_;
-
- uptr allocated_size_classes_[kNumberOfSizeClasses];
- FakeFrameFifo size_classes_[kNumberOfSizeClasses];
- FakeFrameLifo call_stack_;
-};
-
void *asan_memalign(uptr alignment, uptr size, StackTrace *stack,
AllocType alloc_type);
void asan_free(void *ptr, StackTrace *stack, AllocType alloc_type);
diff --git a/libsanitizer/asan/asan_allocator2.cc b/libsanitizer/asan/asan_allocator2.cc
index 1ff120e555c..34aad11ed75 100644
--- a/libsanitizer/asan/asan_allocator2.cc
+++ b/libsanitizer/asan/asan_allocator2.cc
@@ -11,20 +11,20 @@
// This variant uses the allocator from sanitizer_common, i.e. the one shared
// with ThreadSanitizer and MemorySanitizer.
//
-// Status: under development, not enabled by default yet.
//===----------------------------------------------------------------------===//
#include "asan_allocator.h"
-#if ASAN_ALLOCATOR_VERSION == 2
#include "asan_mapping.h"
+#include "asan_poisoning.h"
#include "asan_report.h"
#include "asan_thread.h"
-#include "asan_thread_registry.h"
#include "sanitizer_common/sanitizer_allocator.h"
+#include "sanitizer_common/sanitizer_flags.h"
#include "sanitizer_common/sanitizer_internal_defs.h"
#include "sanitizer_common/sanitizer_list.h"
#include "sanitizer_common/sanitizer_stackdepot.h"
#include "sanitizer_common/sanitizer_quarantine.h"
+#include "lsan/lsan_common.h"
namespace __asan {
@@ -32,7 +32,7 @@ struct AsanMapUnmapCallback {
void OnMap(uptr p, uptr size) const {
PoisonShadow(p, size, kAsanHeapLeftRedzoneMagic);
// Statistics.
- AsanStats &thread_stats = asanThreadRegistry().GetCurrentThreadStats();
+ AsanStats &thread_stats = GetCurrentThreadStats();
thread_stats.mmaps++;
thread_stats.mmaped += size;
}
@@ -47,7 +47,7 @@ struct AsanMapUnmapCallback {
uptr shadow_end = RoundDownTo(MemToShadow(p + size), page_size);
FlushUnneededShadowMemory(shadow_beg, shadow_end - shadow_beg);
// Statistics.
- AsanStats &thread_stats = asanThreadRegistry().GetCurrentThreadStats();
+ AsanStats &thread_stats = GetCurrentThreadStats();
thread_stats.munmaps++;
thread_stats.munmaped += size;
}
@@ -56,18 +56,23 @@ struct AsanMapUnmapCallback {
#if SANITIZER_WORDSIZE == 64
#if defined(__powerpc64__)
const uptr kAllocatorSpace = 0xa0000000000ULL;
+const uptr kAllocatorSize = 0x20000000000ULL; // 2T.
#else
const uptr kAllocatorSpace = 0x600000000000ULL;
+const uptr kAllocatorSize = 0x40000000000ULL; // 4T.
#endif
-const uptr kAllocatorSize = 0x10000000000ULL; // 1T.
typedef DefaultSizeClassMap SizeClassMap;
typedef SizeClassAllocator64<kAllocatorSpace, kAllocatorSize, 0 /*metadata*/,
SizeClassMap, AsanMapUnmapCallback> PrimaryAllocator;
#elif SANITIZER_WORDSIZE == 32
static const u64 kAddressSpaceSize = 1ULL << 32;
typedef CompactSizeClassMap SizeClassMap;
+static const uptr kRegionSizeLog = 20;
+static const uptr kFlatByteMapSize = kAddressSpaceSize >> kRegionSizeLog;
typedef SizeClassAllocator32<0, kAddressSpaceSize, 16,
- SizeClassMap, AsanMapUnmapCallback> PrimaryAllocator;
+ SizeClassMap, kRegionSizeLog,
+ FlatByteMap<kFlatByteMapSize>,
+ AsanMapUnmapCallback> PrimaryAllocator;
#endif
typedef SizeClassAllocatorLocalCache<PrimaryAllocator> AllocatorCache;
@@ -139,14 +144,15 @@ static uptr ComputeRZLog(uptr user_requested_size) {
// ChunkBase consists of ChunkHeader and other bytes that overlap with user
// memory.
-// If a memory chunk is allocated by memalign and we had to increase the
-// allocation size to achieve the proper alignment, then we store this magic
+// If the left redzone is greater than the ChunkHeader size we store a magic
// value in the first uptr word of the memory block and store the address of
// ChunkBase in the next uptr.
-// M B ? ? ? L L L L L L H H U U U U U U
-// M -- magic value kMemalignMagic
+// M B L L L L L L L L L H H U U U U U U
+// | ^
+// ---------------------|
+// M -- magic value kAllocBegMagic
// B -- address of ChunkHeader pointing to the first 'H'
-static const uptr kMemalignMagic = 0xCC6E96B9;
+static const uptr kAllocBegMagic = 0xCC6E96B9;
struct ChunkHeader {
// 1-st 8 bytes.
@@ -157,6 +163,7 @@ struct ChunkHeader {
u32 from_memalign : 1;
u32 alloc_type : 2;
u32 rz_log : 3;
+ u32 lsan_tag : 2;
// 2-nd 8 bytes
// This field is used for small sizes. For large sizes it is equal to
// SizeClassMap::kMaxSize and the actual size is stored in the
@@ -167,7 +174,6 @@ struct ChunkHeader {
struct ChunkBase : ChunkHeader {
// Header2, intersects with user memory.
- AsanChunk *next;
u32 free_context_id;
};
@@ -188,7 +194,8 @@ struct AsanChunk: ChunkBase {
return allocator.GetBlockBegin(reinterpret_cast<void *>(this));
return reinterpret_cast<void*>(Beg() - RZLog2Size(rz_log));
}
- // We store the alloc/free stack traces in the chunk itself.
+ // If we don't use stack depot, we store the alloc/free stack traces
+ // in the chunk itself.
u32 *AllocStackBeg() {
return (u32*)(Beg() - RZLog2Size(rz_log));
}
@@ -204,6 +211,9 @@ struct AsanChunk: ChunkBase {
uptr available = RoundUpTo(user_requested_size, SHADOW_GRANULARITY);
return (available - kChunkHeader2Size) / sizeof(u32);
}
+ bool AddrIsInside(uptr addr) {
+ return (addr >= Beg()) && (addr < Beg() + UsedSize());
+ }
};
uptr AsanChunkView::Beg() { return chunk_->Beg(); }
@@ -257,22 +267,25 @@ struct QuarantineCallback {
}
void Recycle(AsanChunk *m) {
- CHECK(m->chunk_state == CHUNK_QUARANTINE);
- m->chunk_state = CHUNK_AVAILABLE;
+ CHECK_EQ(m->chunk_state, CHUNK_QUARANTINE);
+ atomic_store((atomic_uint8_t*)m, CHUNK_AVAILABLE, memory_order_relaxed);
CHECK_NE(m->alloc_tid, kInvalidTid);
CHECK_NE(m->free_tid, kInvalidTid);
PoisonShadow(m->Beg(),
RoundUpTo(m->UsedSize(), SHADOW_GRANULARITY),
kAsanHeapLeftRedzoneMagic);
void *p = reinterpret_cast<void *>(m->AllocBeg());
- if (m->from_memalign) {
- uptr *memalign_magic = reinterpret_cast<uptr *>(p);
- CHECK_EQ(memalign_magic[0], kMemalignMagic);
- CHECK_EQ(memalign_magic[1], reinterpret_cast<uptr>(m));
+ if (p != m) {
+ uptr *alloc_magic = reinterpret_cast<uptr *>(p);
+ CHECK_EQ(alloc_magic[0], kAllocBegMagic);
+ // Clear the magic value, as allocator internals may overwrite the
+ // contents of deallocated chunk, confusing GetAsanChunk lookup.
+ alloc_magic[0] = 0;
+ CHECK_EQ(alloc_magic[1], reinterpret_cast<uptr>(m));
}
// Statistics.
- AsanStats &thread_stats = asanThreadRegistry().GetCurrentThreadStats();
+ AsanStats &thread_stats = GetCurrentThreadStats();
thread_stats.real_frees++;
thread_stats.really_freed += m->UsedSize();
@@ -296,9 +309,10 @@ void InitializeAllocator() {
}
static void *Allocate(uptr size, uptr alignment, StackTrace *stack,
- AllocType alloc_type) {
+ AllocType alloc_type, bool can_fill) {
if (!asan_inited)
__asan_init();
+ Flags &fl = *flags();
CHECK(stack);
const uptr min_alignment = SHADOW_GRANULARITY;
if (alignment < min_alignment)
@@ -314,9 +328,7 @@ static void *Allocate(uptr size, uptr alignment, StackTrace *stack,
CHECK(IsPowerOfTwo(alignment));
uptr rz_log = ComputeRZLog(size);
uptr rz_size = RZLog2Size(rz_log);
- uptr rounded_size = RoundUpTo(size, alignment);
- if (rounded_size < kChunkHeader2Size)
- rounded_size = kChunkHeader2Size;
+ uptr rounded_size = RoundUpTo(Max(size, kChunkHeader2Size), alignment);
uptr needed_size = rounded_size + rz_size;
if (alignment > min_alignment)
needed_size += alignment;
@@ -331,10 +343,10 @@ static void *Allocate(uptr size, uptr alignment, StackTrace *stack,
if (size > kMaxAllowedMallocSize || needed_size > kMaxAllowedMallocSize) {
Report("WARNING: AddressSanitizer failed to allocate %p bytes\n",
(void*)size);
- return 0;
+ return AllocatorReturnNull();
}
- AsanThread *t = asanThreadRegistry().GetCurrent();
+ AsanThread *t = GetCurrentThread();
void *allocated;
if (t) {
AllocatorCache *cache = GetAllocatorCache(&t->malloc_storage());
@@ -345,8 +357,6 @@ static void *Allocate(uptr size, uptr alignment, StackTrace *stack,
allocated = allocator.Allocate(cache, needed_size, 8, false);
}
uptr alloc_beg = reinterpret_cast<uptr>(allocated);
- // Clear the first allocated word (an old kMemalignMagic may still be there).
- reinterpret_cast<uptr *>(alloc_beg)[0] = 0;
uptr alloc_end = alloc_beg + needed_size;
uptr beg_plus_redzone = alloc_beg + rz_size;
uptr user_beg = beg_plus_redzone;
@@ -356,7 +366,6 @@ static void *Allocate(uptr size, uptr alignment, StackTrace *stack,
CHECK_LE(user_end, alloc_end);
uptr chunk_beg = user_beg - kChunkHeaderSize;
AsanChunk *m = reinterpret_cast<AsanChunk *>(chunk_beg);
- m->chunk_state = CHUNK_ALLOCATED;
m->alloc_type = alloc_type;
m->rz_log = rz_log;
u32 alloc_tid = t ? t->tid() : 0;
@@ -364,11 +373,10 @@ static void *Allocate(uptr size, uptr alignment, StackTrace *stack,
CHECK_EQ(alloc_tid, m->alloc_tid); // Does alloc_tid fit into the bitfield?
m->free_tid = kInvalidTid;
m->from_memalign = user_beg != beg_plus_redzone;
- if (m->from_memalign) {
- CHECK_LE(beg_plus_redzone + 2 * sizeof(uptr), user_beg);
- uptr *memalign_magic = reinterpret_cast<uptr *>(alloc_beg);
- memalign_magic[0] = kMemalignMagic;
- memalign_magic[1] = chunk_beg;
+ if (alloc_beg != chunk_beg) {
+ CHECK_LE(alloc_beg+ 2 * sizeof(uptr), chunk_beg);
+ reinterpret_cast<uptr *>(alloc_beg)[0] = kAllocBegMagic;
+ reinterpret_cast<uptr *>(alloc_beg)[1] = chunk_beg;
}
if (using_primary_allocator) {
CHECK(size);
@@ -382,7 +390,7 @@ static void *Allocate(uptr size, uptr alignment, StackTrace *stack,
meta[1] = chunk_beg;
}
- if (flags()->use_stack_depot) {
+ if (fl.use_stack_depot) {
m->alloc_context_id = StackDepotPut(stack->trace, stack->size);
} else {
m->alloc_context_id = 0;
@@ -394,12 +402,12 @@ static void *Allocate(uptr size, uptr alignment, StackTrace *stack,
if (size_rounded_down_to_granularity)
PoisonShadow(user_beg, size_rounded_down_to_granularity, 0);
// Deal with the end of the region if size is not aligned to granularity.
- if (size != size_rounded_down_to_granularity && flags()->poison_heap) {
+ if (size != size_rounded_down_to_granularity && fl.poison_heap) {
u8 *shadow = (u8*)MemToShadow(user_beg + size_rounded_down_to_granularity);
*shadow = size & (SHADOW_GRANULARITY - 1);
}
- AsanStats &thread_stats = asanThreadRegistry().GetCurrentThreadStats();
+ AsanStats &thread_stats = GetCurrentThreadStats();
thread_stats.mallocs++;
thread_stats.malloced += size;
thread_stats.malloced_redzones += needed_size - size;
@@ -409,26 +417,43 @@ static void *Allocate(uptr size, uptr alignment, StackTrace *stack,
thread_stats.malloc_large++;
void *res = reinterpret_cast<void *>(user_beg);
+ if (can_fill && fl.max_malloc_fill_size) {
+ uptr fill_size = Min(size, (uptr)fl.max_malloc_fill_size);
+ REAL(memset)(res, fl.malloc_fill_byte, fill_size);
+ }
+#if CAN_SANITIZE_LEAKS
+ m->lsan_tag = __lsan::DisabledInThisThread() ? __lsan::kIgnored
+ : __lsan::kDirectlyLeaked;
+#endif
+ // Must be the last mutation of metadata in this function.
+ atomic_store((atomic_uint8_t *)m, CHUNK_ALLOCATED, memory_order_release);
ASAN_MALLOC_HOOK(res, size);
return res;
}
-static void Deallocate(void *ptr, StackTrace *stack, AllocType alloc_type) {
- uptr p = reinterpret_cast<uptr>(ptr);
- if (p == 0) return;
- ASAN_FREE_HOOK(ptr);
- uptr chunk_beg = p - kChunkHeaderSize;
- AsanChunk *m = reinterpret_cast<AsanChunk *>(chunk_beg);
+static void ReportInvalidFree(void *ptr, u8 chunk_state, StackTrace *stack) {
+ if (chunk_state == CHUNK_QUARANTINE)
+ ReportDoubleFree((uptr)ptr, stack);
+ else
+ ReportFreeNotMalloced((uptr)ptr, stack);
+}
+static void AtomicallySetQuarantineFlag(AsanChunk *m,
+ void *ptr, StackTrace *stack) {
+ u8 old_chunk_state = CHUNK_ALLOCATED;
// Flip the chunk_state atomically to avoid race on double-free.
- u8 old_chunk_state = atomic_exchange((atomic_uint8_t*)m, CHUNK_QUARANTINE,
- memory_order_relaxed);
+ if (!atomic_compare_exchange_strong((atomic_uint8_t*)m, &old_chunk_state,
+ CHUNK_QUARANTINE, memory_order_acquire))
+ ReportInvalidFree(ptr, old_chunk_state, stack);
+ CHECK_EQ(CHUNK_ALLOCATED, old_chunk_state);
+}
+
+// Expects the chunk to already be marked as quarantined by using
+// AtomicallySetQuarantineFlag.
+static void QuarantineChunk(AsanChunk *m, void *ptr,
+ StackTrace *stack, AllocType alloc_type) {
+ CHECK_EQ(m->chunk_state, CHUNK_QUARANTINE);
- if (old_chunk_state == CHUNK_QUARANTINE)
- ReportDoubleFree((uptr)ptr, stack);
- else if (old_chunk_state != CHUNK_ALLOCATED)
- ReportFreeNotMalloced((uptr)ptr, stack);
- CHECK(old_chunk_state == CHUNK_ALLOCATED);
if (m->alloc_type != alloc_type && flags()->alloc_dealloc_mismatch)
ReportAllocTypeMismatch((uptr)ptr, stack,
(AllocType)m->alloc_type, (AllocType)alloc_type);
@@ -436,7 +461,7 @@ static void Deallocate(void *ptr, StackTrace *stack, AllocType alloc_type) {
CHECK_GE(m->alloc_tid, 0);
if (SANITIZER_WORDSIZE == 64) // On 32-bits this resides in user area.
CHECK_EQ(m->free_tid, kInvalidTid);
- AsanThread *t = asanThreadRegistry().GetCurrent();
+ AsanThread *t = GetCurrentThread();
m->free_tid = t ? t->tid() : 0;
if (flags()->use_stack_depot) {
m->free_context_id = StackDepotPut(stack->trace, stack->size);
@@ -444,13 +469,12 @@ static void Deallocate(void *ptr, StackTrace *stack, AllocType alloc_type) {
m->free_context_id = 0;
StackTrace::CompressStack(stack, m->FreeStackBeg(), m->FreeStackSize());
}
- CHECK(m->chunk_state == CHUNK_QUARANTINE);
// Poison the region.
PoisonShadow(m->Beg(),
RoundUpTo(m->UsedSize(), SHADOW_GRANULARITY),
kAsanHeapFreeMagic);
- AsanStats &thread_stats = asanThreadRegistry().GetCurrentThreadStats();
+ AsanStats &thread_stats = GetCurrentThreadStats();
thread_stats.frees++;
thread_stats.freed += m->UsedSize();
@@ -468,57 +492,67 @@ static void Deallocate(void *ptr, StackTrace *stack, AllocType alloc_type) {
}
}
+static void Deallocate(void *ptr, StackTrace *stack, AllocType alloc_type) {
+ uptr p = reinterpret_cast<uptr>(ptr);
+ if (p == 0) return;
+
+ uptr chunk_beg = p - kChunkHeaderSize;
+ AsanChunk *m = reinterpret_cast<AsanChunk *>(chunk_beg);
+ ASAN_FREE_HOOK(ptr);
+ // Must mark the chunk as quarantined before any changes to its metadata.
+ AtomicallySetQuarantineFlag(m, ptr, stack);
+ QuarantineChunk(m, ptr, stack, alloc_type);
+}
+
static void *Reallocate(void *old_ptr, uptr new_size, StackTrace *stack) {
CHECK(old_ptr && new_size);
uptr p = reinterpret_cast<uptr>(old_ptr);
uptr chunk_beg = p - kChunkHeaderSize;
AsanChunk *m = reinterpret_cast<AsanChunk *>(chunk_beg);
- AsanStats &thread_stats = asanThreadRegistry().GetCurrentThreadStats();
+ AsanStats &thread_stats = GetCurrentThreadStats();
thread_stats.reallocs++;
thread_stats.realloced += new_size;
- CHECK(m->chunk_state == CHUNK_ALLOCATED);
- uptr old_size = m->UsedSize();
- uptr memcpy_size = Min(new_size, old_size);
- void *new_ptr = Allocate(new_size, 8, stack, FROM_MALLOC);
+ void *new_ptr = Allocate(new_size, 8, stack, FROM_MALLOC, true);
if (new_ptr) {
- CHECK(REAL(memcpy) != 0);
+ u8 chunk_state = m->chunk_state;
+ if (chunk_state != CHUNK_ALLOCATED)
+ ReportInvalidFree(old_ptr, chunk_state, stack);
+ CHECK_NE(REAL(memcpy), (void*)0);
+ uptr memcpy_size = Min(new_size, m->UsedSize());
+ // If realloc() races with free(), we may start copying freed memory.
+ // However, we will report racy double-free later anyway.
REAL(memcpy)(new_ptr, old_ptr, memcpy_size);
Deallocate(old_ptr, stack, FROM_MALLOC);
}
return new_ptr;
}
-static AsanChunk *GetAsanChunkByAddr(uptr p) {
- void *ptr = reinterpret_cast<void *>(p);
- uptr alloc_beg = reinterpret_cast<uptr>(allocator.GetBlockBegin(ptr));
+// Assumes alloc_beg == allocator.GetBlockBegin(alloc_beg).
+static AsanChunk *GetAsanChunk(void *alloc_beg) {
if (!alloc_beg) return 0;
- uptr *memalign_magic = reinterpret_cast<uptr *>(alloc_beg);
- if (memalign_magic[0] == kMemalignMagic) {
- AsanChunk *m = reinterpret_cast<AsanChunk *>(memalign_magic[1]);
- CHECK(m->from_memalign);
- return m;
- }
- if (!allocator.FromPrimary(ptr)) {
- uptr *meta = reinterpret_cast<uptr *>(
- allocator.GetMetaData(reinterpret_cast<void *>(alloc_beg)));
+ if (!allocator.FromPrimary(alloc_beg)) {
+ uptr *meta = reinterpret_cast<uptr *>(allocator.GetMetaData(alloc_beg));
AsanChunk *m = reinterpret_cast<AsanChunk *>(meta[1]);
return m;
}
- uptr actual_size = allocator.GetActuallyAllocatedSize(ptr);
- CHECK_LE(actual_size, SizeClassMap::kMaxSize);
- // We know the actually allocted size, but we don't know the redzone size.
- // Just try all possible redzone sizes.
- for (u32 rz_log = 0; rz_log < 8; rz_log++) {
- u32 rz_size = RZLog2Size(rz_log);
- uptr max_possible_size = actual_size - rz_size;
- if (ComputeRZLog(max_possible_size) != rz_log)
- continue;
- return reinterpret_cast<AsanChunk *>(
- alloc_beg + rz_size - kChunkHeaderSize);
- }
- return 0;
+ uptr *alloc_magic = reinterpret_cast<uptr *>(alloc_beg);
+ if (alloc_magic[0] == kAllocBegMagic)
+ return reinterpret_cast<AsanChunk *>(alloc_magic[1]);
+ return reinterpret_cast<AsanChunk *>(alloc_beg);
+}
+
+static AsanChunk *GetAsanChunkByAddr(uptr p) {
+ void *alloc_beg = allocator.GetBlockBegin(reinterpret_cast<void *>(p));
+ return GetAsanChunk(alloc_beg);
+}
+
+// Allocator must be locked when this function is called.
+static AsanChunk *GetAsanChunkByAddrFastLocked(uptr p) {
+ void *alloc_beg =
+ allocator.GetBlockBeginFastLocked(reinterpret_cast<void *>(p));
+ return GetAsanChunk(alloc_beg);
}
static uptr AllocationSize(uptr p) {
@@ -583,33 +617,33 @@ void PrintInternalAllocatorStats() {
allocator.PrintStats();
}
-SANITIZER_INTERFACE_ATTRIBUTE
void *asan_memalign(uptr alignment, uptr size, StackTrace *stack,
AllocType alloc_type) {
- return Allocate(size, alignment, stack, alloc_type);
+ return Allocate(size, alignment, stack, alloc_type, true);
}
-SANITIZER_INTERFACE_ATTRIBUTE
void asan_free(void *ptr, StackTrace *stack, AllocType alloc_type) {
Deallocate(ptr, stack, alloc_type);
}
-SANITIZER_INTERFACE_ATTRIBUTE
void *asan_malloc(uptr size, StackTrace *stack) {
- return Allocate(size, 8, stack, FROM_MALLOC);
+ return Allocate(size, 8, stack, FROM_MALLOC, true);
}
void *asan_calloc(uptr nmemb, uptr size, StackTrace *stack) {
- if (CallocShouldReturnNullDueToOverflow(size, nmemb)) return 0;
- void *ptr = Allocate(nmemb * size, 8, stack, FROM_MALLOC);
- if (ptr)
+ if (CallocShouldReturnNullDueToOverflow(size, nmemb))
+ return AllocatorReturnNull();
+ void *ptr = Allocate(nmemb * size, 8, stack, FROM_MALLOC, false);
+ // If the memory comes from the secondary allocator no need to clear it
+ // as it comes directly from mmap.
+ if (ptr && allocator.FromPrimary(ptr))
REAL(memset)(ptr, 0, nmemb * size);
return ptr;
}
void *asan_realloc(void *p, uptr size, StackTrace *stack) {
if (p == 0)
- return Allocate(size, 8, stack, FROM_MALLOC);
+ return Allocate(size, 8, stack, FROM_MALLOC, true);
if (size == 0) {
Deallocate(p, stack, FROM_MALLOC);
return 0;
@@ -618,7 +652,7 @@ void *asan_realloc(void *p, uptr size, StackTrace *stack) {
}
void *asan_valloc(uptr size, StackTrace *stack) {
- return Allocate(size, GetPageSizeCached(), stack, FROM_MALLOC);
+ return Allocate(size, GetPageSizeCached(), stack, FROM_MALLOC, true);
}
void *asan_pvalloc(uptr size, StackTrace *stack) {
@@ -628,12 +662,12 @@ void *asan_pvalloc(uptr size, StackTrace *stack) {
// pvalloc(0) should allocate one page.
size = PageSize;
}
- return Allocate(size, PageSize, stack, FROM_MALLOC);
+ return Allocate(size, PageSize, stack, FROM_MALLOC, true);
}
int asan_posix_memalign(void **memptr, uptr alignment, uptr size,
StackTrace *stack) {
- void *ptr = Allocate(size, alignment, stack, FROM_MALLOC);
+ void *ptr = Allocate(size, alignment, stack, FROM_MALLOC, true);
CHECK(IsAligned((uptr)ptr, alignment));
*memptr = ptr;
return 0;
@@ -664,6 +698,86 @@ void asan_mz_force_unlock() {
} // namespace __asan
+// --- Implementation of LSan-specific functions --- {{{1
+namespace __lsan {
+void LockAllocator() {
+ __asan::allocator.ForceLock();
+}
+
+void UnlockAllocator() {
+ __asan::allocator.ForceUnlock();
+}
+
+void GetAllocatorGlobalRange(uptr *begin, uptr *end) {
+ *begin = (uptr)&__asan::allocator;
+ *end = *begin + sizeof(__asan::allocator);
+}
+
+uptr PointsIntoChunk(void* p) {
+ uptr addr = reinterpret_cast<uptr>(p);
+ __asan::AsanChunk *m = __asan::GetAsanChunkByAddrFastLocked(addr);
+ if (!m) return 0;
+ uptr chunk = m->Beg();
+ if ((m->chunk_state == __asan::CHUNK_ALLOCATED) && m->AddrIsInside(addr))
+ return chunk;
+ return 0;
+}
+
+uptr GetUserBegin(uptr chunk) {
+ __asan::AsanChunk *m =
+ __asan::GetAsanChunkByAddrFastLocked(chunk);
+ CHECK(m);
+ return m->Beg();
+}
+
+LsanMetadata::LsanMetadata(uptr chunk) {
+ metadata_ = reinterpret_cast<void *>(chunk - __asan::kChunkHeaderSize);
+}
+
+bool LsanMetadata::allocated() const {
+ __asan::AsanChunk *m = reinterpret_cast<__asan::AsanChunk *>(metadata_);
+ return m->chunk_state == __asan::CHUNK_ALLOCATED;
+}
+
+ChunkTag LsanMetadata::tag() const {
+ __asan::AsanChunk *m = reinterpret_cast<__asan::AsanChunk *>(metadata_);
+ return static_cast<ChunkTag>(m->lsan_tag);
+}
+
+void LsanMetadata::set_tag(ChunkTag value) {
+ __asan::AsanChunk *m = reinterpret_cast<__asan::AsanChunk *>(metadata_);
+ m->lsan_tag = value;
+}
+
+uptr LsanMetadata::requested_size() const {
+ __asan::AsanChunk *m = reinterpret_cast<__asan::AsanChunk *>(metadata_);
+ return m->UsedSize();
+}
+
+u32 LsanMetadata::stack_trace_id() const {
+ __asan::AsanChunk *m = reinterpret_cast<__asan::AsanChunk *>(metadata_);
+ return m->alloc_context_id;
+}
+
+void ForEachChunk(ForEachChunkCallback callback, void *arg) {
+ __asan::allocator.ForEachChunk(callback, arg);
+}
+
+IgnoreObjectResult IgnoreObjectLocked(const void *p) {
+ uptr addr = reinterpret_cast<uptr>(p);
+ __asan::AsanChunk *m = __asan::GetAsanChunkByAddr(addr);
+ if (!m) return kIgnoreObjectInvalid;
+ if ((m->chunk_state == __asan::CHUNK_ALLOCATED) && m->AddrIsInside(addr)) {
+ if (m->lsan_tag == kIgnored)
+ return kIgnoreObjectAlreadyIgnored;
+ m->lsan_tag = __lsan::kIgnored;
+ return kIgnoreObjectSuccess;
+ } else {
+ return kIgnoreObjectInvalid;
+ }
+}
+} // namespace __lsan
+
// ---------------------- Interface ---------------- {{{1
using namespace __asan; // NOLINT
@@ -693,17 +807,14 @@ uptr __asan_get_allocated_size(const void *p) {
#if !SANITIZER_SUPPORTS_WEAK_HOOKS
// Provide default (no-op) implementation of malloc hooks.
extern "C" {
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
void __asan_malloc_hook(void *ptr, uptr size) {
(void)ptr;
(void)size;
}
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
void __asan_free_hook(void *ptr) {
(void)ptr;
}
} // extern "C"
#endif
-
-
-#endif // ASAN_ALLOCATOR_VERSION
diff --git a/libsanitizer/asan/asan_dll_thunk.cc b/libsanitizer/asan/asan_dll_thunk.cc
new file mode 100644
index 00000000000..26e19441523
--- /dev/null
+++ b/libsanitizer/asan/asan_dll_thunk.cc
@@ -0,0 +1,194 @@
+//===-- asan_dll_thunk.cc -------------------------------------------------===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// This file defines a family of thunks that should be statically linked into
+// the DLLs that have ASan instrumentation in order to delegate the calls to the
+// shared runtime that lives in the main binary.
+// See https://code.google.com/p/address-sanitizer/issues/detail?id=209 for the
+// details.
+//===----------------------------------------------------------------------===//
+
+// Only compile this code when buidling asan_dll_thunk.lib
+// Using #ifdef rather than relying on Makefiles etc.
+// simplifies the build procedure.
+#ifdef ASAN_DLL_THUNK
+
+// ----------------- Helper functions and macros --------------------- {{{1
+extern "C" {
+void *__stdcall GetModuleHandleA(const char *module_name);
+void *__stdcall GetProcAddress(void *module, const char *proc_name);
+void abort();
+}
+
+static void *getRealProcAddressOrDie(const char *name) {
+ void *ret = GetProcAddress(GetModuleHandleA(0), name);
+ if (!ret)
+ abort();
+ return ret;
+}
+
+#define WRAP_V_V(name) \
+ extern "C" void name() { \
+ typedef void (*fntype)(); \
+ static fntype fn = (fntype)getRealProcAddressOrDie(#name); \
+ fn(); \
+ }
+
+#define WRAP_V_W(name) \
+ extern "C" void name(void *arg) { \
+ typedef void (*fntype)(void *arg); \
+ static fntype fn = (fntype)getRealProcAddressOrDie(#name); \
+ fn(arg); \
+ }
+
+#define WRAP_V_WW(name) \
+ extern "C" void name(void *arg1, void *arg2) { \
+ typedef void (*fntype)(void *, void *); \
+ static fntype fn = (fntype)getRealProcAddressOrDie(#name); \
+ fn(arg1, arg2); \
+ }
+
+#define WRAP_V_WWW(name) \
+ extern "C" void name(void *arg1, void *arg2, void *arg3) { \
+ typedef void *(*fntype)(void *, void *, void *); \
+ static fntype fn = (fntype)getRealProcAddressOrDie(#name); \
+ fn(arg1, arg2, arg3); \
+ }
+
+#define WRAP_W_V(name) \
+ extern "C" void *name() { \
+ typedef void *(*fntype)(); \
+ static fntype fn = (fntype)getRealProcAddressOrDie(#name); \
+ return fn(); \
+ }
+
+#define WRAP_W_W(name) \
+ extern "C" void *name(void *arg) { \
+ typedef void *(*fntype)(void *arg); \
+ static fntype fn = (fntype)getRealProcAddressOrDie(#name); \
+ return fn(arg); \
+ }
+
+#define WRAP_W_WW(name) \
+ extern "C" void *name(void *arg1, void *arg2) { \
+ typedef void *(*fntype)(void *, void *); \
+ static fntype fn = (fntype)getRealProcAddressOrDie(#name); \
+ return fn(arg1, arg2); \
+ }
+
+#define WRAP_W_WWW(name) \
+ extern "C" void *name(void *arg1, void *arg2, void *arg3) { \
+ typedef void *(*fntype)(void *, void *, void *); \
+ static fntype fn = (fntype)getRealProcAddressOrDie(#name); \
+ return fn(arg1, arg2, arg3); \
+ }
+
+#define WRAP_W_WWWW(name) \
+ extern "C" void *name(void *arg1, void *arg2, void *arg3, void *arg4) { \
+ typedef void *(*fntype)(void *, void *, void *, void *); \
+ static fntype fn = (fntype)getRealProcAddressOrDie(#name); \
+ return fn(arg1, arg2, arg3, arg4); \
+ }
+
+#define WRAP_W_WWWWW(name) \
+ extern "C" void *name(void *arg1, void *arg2, void *arg3, void *arg4, \
+ void *arg5) { \
+ typedef void *(*fntype)(void *, void *, void *, void *, void *); \
+ static fntype fn = (fntype)getRealProcAddressOrDie(#name); \
+ return fn(arg1, arg2, arg3, arg4, arg5); \
+ }
+
+#define WRAP_W_WWWWWW(name) \
+ extern "C" void *name(void *arg1, void *arg2, void *arg3, void *arg4, \
+ void *arg5, void *arg6) { \
+ typedef void *(*fntype)(void *, void *, void *, void *, void *, void *); \
+ static fntype fn = (fntype)getRealProcAddressOrDie(#name); \
+ return fn(arg1, arg2, arg3, arg4, arg5, arg6); \
+ }
+// }}}
+
+// ----------------- ASan own interface functions --------------------
+WRAP_W_V(__asan_should_detect_stack_use_after_return)
+
+extern "C" {
+ int __asan_option_detect_stack_use_after_return;
+
+ // Manually wrap __asan_init as we need to initialize
+ // __asan_option_detect_stack_use_after_return afterwards.
+ void __asan_init_v3() {
+ typedef void (*fntype)();
+ static fntype fn = (fntype)getRealProcAddressOrDie("__asan_init_v3");
+ fn();
+ __asan_option_detect_stack_use_after_return =
+ (__asan_should_detect_stack_use_after_return() != 0);
+ }
+}
+
+WRAP_V_W(__asan_report_store1)
+WRAP_V_W(__asan_report_store2)
+WRAP_V_W(__asan_report_store4)
+WRAP_V_W(__asan_report_store8)
+WRAP_V_W(__asan_report_store16)
+WRAP_V_WW(__asan_report_store_n)
+
+WRAP_V_W(__asan_report_load1)
+WRAP_V_W(__asan_report_load2)
+WRAP_V_W(__asan_report_load4)
+WRAP_V_W(__asan_report_load8)
+WRAP_V_W(__asan_report_load16)
+WRAP_V_WW(__asan_report_load_n)
+
+WRAP_V_WW(__asan_register_globals)
+WRAP_V_WW(__asan_unregister_globals)
+
+WRAP_W_WW(__asan_stack_malloc_0)
+WRAP_W_WW(__asan_stack_malloc_1)
+WRAP_W_WW(__asan_stack_malloc_2)
+WRAP_W_WW(__asan_stack_malloc_3)
+WRAP_W_WW(__asan_stack_malloc_4)
+WRAP_W_WW(__asan_stack_malloc_5)
+WRAP_W_WW(__asan_stack_malloc_6)
+WRAP_W_WW(__asan_stack_malloc_7)
+WRAP_W_WW(__asan_stack_malloc_8)
+WRAP_W_WW(__asan_stack_malloc_9)
+WRAP_W_WW(__asan_stack_malloc_10)
+
+WRAP_V_WWW(__asan_stack_free_0)
+WRAP_V_WWW(__asan_stack_free_1)
+WRAP_V_WWW(__asan_stack_free_2)
+WRAP_V_WWW(__asan_stack_free_4)
+WRAP_V_WWW(__asan_stack_free_5)
+WRAP_V_WWW(__asan_stack_free_6)
+WRAP_V_WWW(__asan_stack_free_7)
+WRAP_V_WWW(__asan_stack_free_8)
+WRAP_V_WWW(__asan_stack_free_9)
+WRAP_V_WWW(__asan_stack_free_10)
+
+// TODO(timurrrr): Add more interface functions on the as-needed basis.
+
+// ----------------- Memory allocation functions ---------------------
+WRAP_V_W(free)
+WRAP_V_WW(_free_dbg)
+
+WRAP_W_W(malloc)
+WRAP_W_WWWW(_malloc_dbg)
+
+WRAP_W_WW(calloc)
+WRAP_W_WWWWW(_calloc_dbg)
+WRAP_W_WWW(_calloc_impl)
+
+WRAP_W_WW(realloc)
+WRAP_W_WWW(_realloc_dbg)
+WRAP_W_WWW(_recalloc)
+
+WRAP_W_W(_msize)
+
+// TODO(timurrrr): Do we need to add _Crt* stuff here? (see asan_malloc_win.cc).
+
+#endif // ASAN_DLL_THUNK
diff --git a/libsanitizer/asan/asan_fake_stack.cc b/libsanitizer/asan/asan_fake_stack.cc
index 1fc0415750b..b9cce88f34f 100644
--- a/libsanitizer/asan/asan_fake_stack.cc
+++ b/libsanitizer/asan/asan_fake_stack.cc
@@ -10,170 +10,195 @@
// FakeStack is used to detect use-after-return bugs.
//===----------------------------------------------------------------------===//
#include "asan_allocator.h"
+#include "asan_poisoning.h"
#include "asan_thread.h"
-#include "asan_thread_registry.h"
namespace __asan {
-FakeStack::FakeStack() {
- CHECK(REAL(memset) != 0);
- REAL(memset)(this, 0, sizeof(*this));
+static const u64 kMagic1 = kAsanStackAfterReturnMagic;
+static const u64 kMagic2 = (kMagic1 << 8) | kMagic1;
+static const u64 kMagic4 = (kMagic2 << 16) | kMagic2;
+static const u64 kMagic8 = (kMagic4 << 32) | kMagic4;
+
+// For small size classes inline PoisonShadow for better performance.
+ALWAYS_INLINE void SetShadow(uptr ptr, uptr size, uptr class_id, u64 magic) {
+ CHECK_EQ(SHADOW_SCALE, 3); // This code expects SHADOW_SCALE=3.
+ u64 *shadow = reinterpret_cast<u64*>(MemToShadow(ptr));
+ if (class_id <= 6) {
+ for (uptr i = 0; i < (1U << class_id); i++)
+ shadow[i] = magic;
+ } else {
+ // The size class is too big, it's cheaper to poison only size bytes.
+ PoisonShadow(ptr, size, static_cast<u8>(magic));
+ }
}
-bool FakeStack::AddrIsInSizeClass(uptr addr, uptr size_class) {
- uptr mem = allocated_size_classes_[size_class];
- uptr size = ClassMmapSize(size_class);
- bool res = mem && addr >= mem && addr < mem + size;
+FakeStack *FakeStack::Create(uptr stack_size_log) {
+ static uptr kMinStackSizeLog = 16;
+ static uptr kMaxStackSizeLog = FIRST_32_SECOND_64(24, 28);
+ if (stack_size_log < kMinStackSizeLog)
+ stack_size_log = kMinStackSizeLog;
+ if (stack_size_log > kMaxStackSizeLog)
+ stack_size_log = kMaxStackSizeLog;
+ FakeStack *res = reinterpret_cast<FakeStack *>(
+ MmapOrDie(RequiredSize(stack_size_log), "FakeStack"));
+ res->stack_size_log_ = stack_size_log;
+ if (flags()->verbosity) {
+ u8 *p = reinterpret_cast<u8 *>(res);
+ Report("T%d: FakeStack created: %p -- %p stack_size_log: %zd \n",
+ GetCurrentTidOrInvalid(), p,
+ p + FakeStack::RequiredSize(stack_size_log), stack_size_log);
+ }
return res;
}
-uptr FakeStack::AddrIsInFakeStack(uptr addr) {
- for (uptr i = 0; i < kNumberOfSizeClasses; i++) {
- if (AddrIsInSizeClass(addr, i)) return allocated_size_classes_[i];
- }
- return 0;
+void FakeStack::Destroy() {
+ PoisonAll(0);
+ UnmapOrDie(this, RequiredSize(stack_size_log_));
}
-// We may want to compute this during compilation.
-inline uptr FakeStack::ComputeSizeClass(uptr alloc_size) {
- uptr rounded_size = RoundUpToPowerOfTwo(alloc_size);
- uptr log = Log2(rounded_size);
- CHECK(alloc_size <= (1UL << log));
- if (!(alloc_size > (1UL << (log-1)))) {
- Printf("alloc_size %zu log %zu\n", alloc_size, log);
- }
- CHECK(alloc_size > (1UL << (log-1)));
- uptr res = log < kMinStackFrameSizeLog ? 0 : log - kMinStackFrameSizeLog;
- CHECK(res < kNumberOfSizeClasses);
- CHECK(ClassSize(res) >= rounded_size);
- return res;
+void FakeStack::PoisonAll(u8 magic) {
+ PoisonShadow(reinterpret_cast<uptr>(this), RequiredSize(stack_size_log()),
+ magic);
}
-void FakeFrameFifo::FifoPush(FakeFrame *node) {
- CHECK(node);
- node->next = 0;
- if (first_ == 0 && last_ == 0) {
- first_ = last_ = node;
- } else {
- CHECK(first_);
- CHECK(last_);
- last_->next = node;
- last_ = node;
+ALWAYS_INLINE USED
+FakeFrame *FakeStack::Allocate(uptr stack_size_log, uptr class_id,
+ uptr real_stack) {
+ CHECK_LT(class_id, kNumberOfSizeClasses);
+ if (needs_gc_)
+ GC(real_stack);
+ uptr &hint_position = hint_position_[class_id];
+ const int num_iter = NumberOfFrames(stack_size_log, class_id);
+ u8 *flags = GetFlags(stack_size_log, class_id);
+ for (int i = 0; i < num_iter; i++) {
+ uptr pos = ModuloNumberOfFrames(stack_size_log, class_id, hint_position++);
+ // This part is tricky. On one hand, checking and setting flags[pos]
+ // should be atomic to ensure async-signal safety. But on the other hand,
+ // if the signal arrives between checking and setting flags[pos], the
+ // signal handler's fake stack will start from a different hint_position
+ // and so will not touch this particular byte. So, it is safe to do this
+ // with regular non-atimic load and store (at least I was not able to make
+ // this code crash).
+ if (flags[pos]) continue;
+ flags[pos] = 1;
+ FakeFrame *res = reinterpret_cast<FakeFrame *>(
+ GetFrame(stack_size_log, class_id, pos));
+ res->real_stack = real_stack;
+ *SavedFlagPtr(reinterpret_cast<uptr>(res), class_id) = &flags[pos];
+ return res;
}
+ return 0; // We are out of fake stack.
}
-FakeFrame *FakeFrameFifo::FifoPop() {
- CHECK(first_ && last_ && "Exhausted fake stack");
- FakeFrame *res = 0;
- if (first_ == last_) {
- res = first_;
- first_ = last_ = 0;
- } else {
- res = first_;
- first_ = first_->next;
- }
- return res;
+uptr FakeStack::AddrIsInFakeStack(uptr ptr) {
+ uptr stack_size_log = this->stack_size_log();
+ uptr beg = reinterpret_cast<uptr>(GetFrame(stack_size_log, 0, 0));
+ uptr end = reinterpret_cast<uptr>(this) + RequiredSize(stack_size_log);
+ if (ptr < beg || ptr >= end) return 0;
+ uptr class_id = (ptr - beg) >> stack_size_log;
+ uptr base = beg + (class_id << stack_size_log);
+ CHECK_LE(base, ptr);
+ CHECK_LT(ptr, base + (1UL << stack_size_log));
+ uptr pos = (ptr - base) >> (kMinStackFrameSizeLog + class_id);
+ return base + pos * BytesInSizeClass(class_id);
}
-void FakeStack::Init(uptr stack_size) {
- stack_size_ = stack_size;
- alive_ = true;
+void FakeStack::HandleNoReturn() {
+ needs_gc_ = true;
}
-void FakeStack::Cleanup() {
- alive_ = false;
- for (uptr i = 0; i < kNumberOfSizeClasses; i++) {
- uptr mem = allocated_size_classes_[i];
- if (mem) {
- PoisonShadow(mem, ClassMmapSize(i), 0);
- allocated_size_classes_[i] = 0;
- UnmapOrDie((void*)mem, ClassMmapSize(i));
+// When throw, longjmp or some such happens we don't call OnFree() and
+// as the result may leak one or more fake frames, but the good news is that
+// we are notified about all such events by HandleNoReturn().
+// If we recently had such no-return event we need to collect garbage frames.
+// We do it based on their 'real_stack' values -- everything that is lower
+// than the current real_stack is garbage.
+NOINLINE void FakeStack::GC(uptr real_stack) {
+ uptr collected = 0;
+ for (uptr class_id = 0; class_id < kNumberOfSizeClasses; class_id++) {
+ u8 *flags = GetFlags(stack_size_log(), class_id);
+ for (uptr i = 0, n = NumberOfFrames(stack_size_log(), class_id); i < n;
+ i++) {
+ if (flags[i] == 0) continue; // not allocated.
+ FakeFrame *ff = reinterpret_cast<FakeFrame *>(
+ GetFrame(stack_size_log(), class_id, i));
+ if (ff->real_stack < real_stack) {
+ flags[i] = 0;
+ collected++;
+ }
}
}
+ needs_gc_ = false;
}
-uptr FakeStack::ClassMmapSize(uptr size_class) {
- return RoundUpToPowerOfTwo(stack_size_);
-}
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
+static THREADLOCAL FakeStack *fake_stack_tls;
-void FakeStack::AllocateOneSizeClass(uptr size_class) {
- CHECK(ClassMmapSize(size_class) >= GetPageSizeCached());
- uptr new_mem = (uptr)MmapOrDie(
- ClassMmapSize(size_class), __FUNCTION__);
- // Printf("T%d new_mem[%zu]: %p-%p mmap %zu\n",
- // asanThreadRegistry().GetCurrent()->tid(),
- // size_class, new_mem, new_mem + ClassMmapSize(size_class),
- // ClassMmapSize(size_class));
- uptr i;
- for (i = 0; i < ClassMmapSize(size_class);
- i += ClassSize(size_class)) {
- size_classes_[size_class].FifoPush((FakeFrame*)(new_mem + i));
- }
- CHECK(i == ClassMmapSize(size_class));
- allocated_size_classes_[size_class] = new_mem;
+FakeStack *GetTLSFakeStack() {
+ return fake_stack_tls;
+}
+void SetTLSFakeStack(FakeStack *fs) {
+ fake_stack_tls = fs;
+}
+#else
+FakeStack *GetTLSFakeStack() { return 0; }
+void SetTLSFakeStack(FakeStack *fs) { }
+#endif // SANITIZER_LINUX && !SANITIZER_ANDROID
+
+static FakeStack *GetFakeStack() {
+ AsanThread *t = GetCurrentThread();
+ if (!t) return 0;
+ return t->fake_stack();
}
-uptr FakeStack::AllocateStack(uptr size, uptr real_stack) {
- if (!alive_) return real_stack;
- CHECK(size <= kMaxStackMallocSize && size > 1);
- uptr size_class = ComputeSizeClass(size);
- if (!allocated_size_classes_[size_class]) {
- AllocateOneSizeClass(size_class);
- }
- FakeFrame *fake_frame = size_classes_[size_class].FifoPop();
- CHECK(fake_frame);
- fake_frame->size_minus_one = size - 1;
- fake_frame->real_stack = real_stack;
- while (FakeFrame *top = call_stack_.top()) {
- if (top->real_stack > real_stack) break;
- call_stack_.LifoPop();
- DeallocateFrame(top);
- }
- call_stack_.LifoPush(fake_frame);
- uptr ptr = (uptr)fake_frame;
- PoisonShadow(ptr, size, 0);
- return ptr;
+static FakeStack *GetFakeStackFast() {
+ if (FakeStack *fs = GetTLSFakeStack())
+ return fs;
+ if (!__asan_option_detect_stack_use_after_return)
+ return 0;
+ return GetFakeStack();
}
-void FakeStack::DeallocateFrame(FakeFrame *fake_frame) {
- CHECK(alive_);
- uptr size = fake_frame->size_minus_one + 1;
- uptr size_class = ComputeSizeClass(size);
- CHECK(allocated_size_classes_[size_class]);
- uptr ptr = (uptr)fake_frame;
- CHECK(AddrIsInSizeClass(ptr, size_class));
- CHECK(AddrIsInSizeClass(ptr + size - 1, size_class));
- size_classes_[size_class].FifoPush(fake_frame);
+ALWAYS_INLINE uptr OnMalloc(uptr class_id, uptr size, uptr real_stack) {
+ FakeStack *fs = GetFakeStackFast();
+ if (!fs) return real_stack;
+ FakeFrame *ff = fs->Allocate(fs->stack_size_log(), class_id, real_stack);
+ if (!ff)
+ return real_stack; // Out of fake stack, return the real one.
+ uptr ptr = reinterpret_cast<uptr>(ff);
+ SetShadow(ptr, size, class_id, 0);
+ return ptr;
}
-void FakeStack::OnFree(uptr ptr, uptr size, uptr real_stack) {
- FakeFrame *fake_frame = (FakeFrame*)ptr;
- CHECK(fake_frame->magic = kRetiredStackFrameMagic);
- CHECK(fake_frame->descr != 0);
- CHECK(fake_frame->size_minus_one == size - 1);
- PoisonShadow(ptr, size, kAsanStackAfterReturnMagic);
+ALWAYS_INLINE void OnFree(uptr ptr, uptr class_id, uptr size, uptr real_stack) {
+ if (ptr == real_stack)
+ return;
+ FakeStack::Deallocate(ptr, class_id);
+ SetShadow(ptr, size, class_id, kMagic8);
}
} // namespace __asan
// ---------------------- Interface ---------------- {{{1
-using namespace __asan; // NOLINT
-
-uptr __asan_stack_malloc(uptr size, uptr real_stack) {
- if (!flags()->use_fake_stack) return real_stack;
- AsanThread *t = asanThreadRegistry().GetCurrent();
- if (!t) {
- // TSD is gone, use the real stack.
- return real_stack;
+#define DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(class_id) \
+ extern "C" SANITIZER_INTERFACE_ATTRIBUTE uptr \
+ __asan_stack_malloc_##class_id(uptr size, uptr real_stack) { \
+ return __asan::OnMalloc(class_id, size, real_stack); \
+ } \
+ extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __asan_stack_free_##class_id( \
+ uptr ptr, uptr size, uptr real_stack) { \
+ __asan::OnFree(ptr, class_id, size, real_stack); \
}
- uptr ptr = t->fake_stack().AllocateStack(size, real_stack);
- // Printf("__asan_stack_malloc %p %zu %p\n", ptr, size, real_stack);
- return ptr;
-}
-void __asan_stack_free(uptr ptr, uptr size, uptr real_stack) {
- if (!flags()->use_fake_stack) return;
- if (ptr != real_stack) {
- FakeStack::OnFree(ptr, size, real_stack);
- }
-}
+DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(0)
+DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(1)
+DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(2)
+DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(3)
+DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(4)
+DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(5)
+DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(6)
+DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(7)
+DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(8)
+DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(9)
+DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(10)
diff --git a/libsanitizer/asan/asan_fake_stack.h b/libsanitizer/asan/asan_fake_stack.h
new file mode 100644
index 00000000000..4287497fd5d
--- /dev/null
+++ b/libsanitizer/asan/asan_fake_stack.h
@@ -0,0 +1,167 @@
+//===-- asan_fake_stack.h ---------------------------------------*- C++ -*-===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// ASan-private header for asan_fake_stack.cc, implements FakeStack.
+//===----------------------------------------------------------------------===//
+
+#ifndef ASAN_FAKE_STACK_H
+#define ASAN_FAKE_STACK_H
+
+#include "sanitizer_common/sanitizer_common.h"
+
+namespace __asan {
+
+// Fake stack frame contains local variables of one function.
+struct FakeFrame {
+ uptr magic; // Modified by the instrumented code.
+ uptr descr; // Modified by the instrumented code.
+ uptr pc; // Modified by the instrumented code.
+ uptr real_stack;
+};
+
+// For each thread we create a fake stack and place stack objects on this fake
+// stack instead of the real stack. The fake stack is not really a stack but
+// a fast malloc-like allocator so that when a function exits the fake stack
+// is not popped but remains there for quite some time until gets used again.
+// So, we poison the objects on the fake stack when function returns.
+// It helps us find use-after-return bugs.
+//
+// The FakeStack objects is allocated by a single mmap call and has no other
+// pointers. The size of the fake stack depends on the actual thread stack size
+// and thus can not be a constant.
+// stack_size is a power of two greater or equal to the thread's stack size;
+// we store it as its logarithm (stack_size_log).
+// FakeStack has kNumberOfSizeClasses (11) size classes, each size class
+// is a power of two, starting from 64 bytes. Each size class occupies
+// stack_size bytes and thus can allocate
+// NumberOfFrames=(stack_size/BytesInSizeClass) fake frames (also a power of 2).
+// For each size class we have NumberOfFrames allocation flags,
+// each flag indicates whether the given frame is currently allocated.
+// All flags for size classes 0 .. 10 are stored in a single contiguous region
+// followed by another contiguous region which contains the actual memory for
+// size classes. The addresses are computed by GetFlags and GetFrame without
+// any memory accesses solely based on 'this' and stack_size_log.
+// Allocate() flips the appropriate allocation flag atomically, thus achieving
+// async-signal safety.
+// This allocator does not have quarantine per se, but it tries to allocate the
+// frames in round robin fasion to maximize the delay between a deallocation
+// and the next allocation.
+class FakeStack {
+ static const uptr kMinStackFrameSizeLog = 6; // Min frame is 64B.
+ static const uptr kMaxStackFrameSizeLog = 16; // Max stack frame is 64K.
+
+ public:
+ static const uptr kNumberOfSizeClasses =
+ kMaxStackFrameSizeLog - kMinStackFrameSizeLog + 1;
+
+ // CTOR: create the FakeStack as a single mmap-ed object.
+ static FakeStack *Create(uptr stack_size_log);
+
+ void Destroy();
+
+ // stack_size_log is at least 15 (stack_size >= 32K).
+ static uptr SizeRequiredForFlags(uptr stack_size_log) {
+ return 1UL << (stack_size_log + 1 - kMinStackFrameSizeLog);
+ }
+
+ // Each size class occupies stack_size bytes.
+ static uptr SizeRequiredForFrames(uptr stack_size_log) {
+ return (1ULL << stack_size_log) * kNumberOfSizeClasses;
+ }
+
+ // Number of bytes requires for the whole object.
+ static uptr RequiredSize(uptr stack_size_log) {
+ return kFlagsOffset + SizeRequiredForFlags(stack_size_log) +
+ SizeRequiredForFrames(stack_size_log);
+ }
+
+ // Offset of the given flag from the first flag.
+ // The flags for class 0 begin at offset 000000000
+ // The flags for class 1 begin at offset 100000000
+ // ....................2................ 110000000
+ // ....................3................ 111000000
+ // and so on.
+ static uptr FlagsOffset(uptr stack_size_log, uptr class_id) {
+ uptr t = kNumberOfSizeClasses - 1 - class_id;
+ const uptr all_ones = (1 << (kNumberOfSizeClasses - 1)) - 1;
+ return ((all_ones >> t) << t) << (stack_size_log - 15);
+ }
+
+ static uptr NumberOfFrames(uptr stack_size_log, uptr class_id) {
+ return 1UL << (stack_size_log - kMinStackFrameSizeLog - class_id);
+ }
+
+ // Divide n by the numbe of frames in size class.
+ static uptr ModuloNumberOfFrames(uptr stack_size_log, uptr class_id, uptr n) {
+ return n & (NumberOfFrames(stack_size_log, class_id) - 1);
+ }
+
+ // The the pointer to the flags of the given class_id.
+ u8 *GetFlags(uptr stack_size_log, uptr class_id) {
+ return reinterpret_cast<u8 *>(this) + kFlagsOffset +
+ FlagsOffset(stack_size_log, class_id);
+ }
+
+ // Get frame by class_id and pos.
+ u8 *GetFrame(uptr stack_size_log, uptr class_id, uptr pos) {
+ return reinterpret_cast<u8 *>(this) + kFlagsOffset +
+ SizeRequiredForFlags(stack_size_log) +
+ (1 << stack_size_log) * class_id + BytesInSizeClass(class_id) * pos;
+ }
+
+ // Allocate the fake frame.
+ FakeFrame *Allocate(uptr stack_size_log, uptr class_id, uptr real_stack);
+
+ // Deallocate the fake frame: read the saved flag address and write 0 there.
+ static void Deallocate(uptr x, uptr class_id) {
+ **SavedFlagPtr(x, class_id) = 0;
+ }
+
+ // Poison the entire FakeStack's shadow with the magic value.
+ void PoisonAll(u8 magic);
+
+ // Return the beginning of the FakeFrame or 0 if the address is not ours.
+ uptr AddrIsInFakeStack(uptr addr);
+
+ // Number of bytes in a fake frame of this size class.
+ static uptr BytesInSizeClass(uptr class_id) {
+ return 1UL << (class_id + kMinStackFrameSizeLog);
+ }
+
+ // The fake frame is guaranteed to have a right redzone.
+ // We use the last word of that redzone to store the address of the flag
+ // that corresponds to the current frame to make faster deallocation.
+ static u8 **SavedFlagPtr(uptr x, uptr class_id) {
+ return reinterpret_cast<u8 **>(x + BytesInSizeClass(class_id) - sizeof(x));
+ }
+
+ uptr stack_size_log() const { return stack_size_log_; }
+
+ void HandleNoReturn();
+ void GC(uptr real_stack);
+
+ private:
+ FakeStack() { }
+ static const uptr kFlagsOffset = 4096; // This is were the flags begin.
+ // Must match the number of uses of DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID
+ COMPILER_CHECK(kNumberOfSizeClasses == 11);
+ static const uptr kMaxStackMallocSize = 1 << kMaxStackFrameSizeLog;
+
+ uptr hint_position_[kNumberOfSizeClasses];
+ uptr stack_size_log_;
+ // a bit is set if something was allocated from the corresponding size class.
+ bool needs_gc_;
+};
+
+FakeStack *GetTLSFakeStack();
+void SetTLSFakeStack(FakeStack *fs);
+
+} // namespace __asan
+
+#endif // ASAN_FAKE_STACK_H
diff --git a/libsanitizer/asan/asan_flags.h b/libsanitizer/asan/asan_flags.h
index b880896c7a3..c115997ff29 100644
--- a/libsanitizer/asan/asan_flags.h
+++ b/libsanitizer/asan/asan_flags.h
@@ -30,8 +30,6 @@ struct Flags {
// Lower value may reduce memory usage but increase the chance of
// false negatives.
int quarantine_size;
- // If set, uses in-process symbolizer from common sanitizer runtime.
- bool symbolize;
// Verbosity level (0 - silent, 1 - a bit of output, 2+ - more output).
int verbosity;
// Size (in bytes) of redzones around heap objects.
@@ -45,8 +43,6 @@ struct Flags {
int report_globals;
// If set, attempts to catch initialization order issues.
bool check_initialization_order;
- // Max number of stack frames kept for each allocation/deallocation.
- int malloc_context_size;
// If set, uses custom wrappers and replacements for libc string functions
// to find more errors.
bool replace_str;
@@ -54,11 +50,13 @@ struct Flags {
bool replace_intrin;
// Used on Mac only.
bool mac_ignore_invalid_free;
- // ASan allocator flag. See asan_allocator.cc.
- bool use_fake_stack;
- // ASan allocator flag. Sets the maximal size of allocation request
- // that would return memory filled with zero bytes.
- int max_malloc_fill_size;
+ // Enables stack-use-after-return checking at run-time.
+ bool detect_stack_use_after_return;
+ // The minimal fake stack size log.
+ int uar_stack_size_log;
+ // ASan allocator flag. max_malloc_fill_size is the maximal amount of bytes
+ // that will be filled with malloc_fill_byte on malloc.
+ int max_malloc_fill_size, malloc_fill_byte;
// Override exit status if something was reported.
int exitcode;
// If set, user may manually mark memory regions as poisoned or unpoisoned.
@@ -69,6 +67,8 @@ struct Flags {
int sleep_before_dying;
// If set, registers ASan custom segv handler.
bool handle_segv;
+ // If set, allows user register segv handler even if ASan registers one.
+ bool allow_user_segv_handler;
// If set, uses alternate stack for signal handling.
bool use_sigaltstack;
// Allow the users to work around the bug in Nvidia drivers prior to 295.*.
@@ -89,18 +89,10 @@ struct Flags {
// Allow the tool to re-exec the program. This may interfere badly with the
// debugger.
bool allow_reexec;
- // Strips this prefix from file paths in error reports.
- const char *strip_path_prefix;
// If set, prints not only thread creation stacks for threads in error report,
// but also thread creation stacks for threads that created those threads,
// etc. up to main thread.
bool print_full_thread_history;
- // ASan will write logs to "log_path.pid" instead of stderr.
- const char *log_path;
- // Use fast (frame-pointer-based) unwinder on fatal errors (if available).
- bool fast_unwind_on_fatal;
- // Use fast (frame-pointer-based) unwinder on malloc/free (if available).
- bool fast_unwind_on_malloc;
// Poison (or not) the heap memory on [de]allocation. Zero value is useful
// for benchmarking the allocator or instrumentator.
bool poison_heap;
@@ -108,9 +100,18 @@ struct Flags {
bool alloc_dealloc_mismatch;
// Use stack depot instead of storing stacks in the redzones.
bool use_stack_depot;
+ // If true, assume that memcmp(p1, p2, n) always reads n bytes before
+ // comparing p1 and p2.
+ bool strict_memcmp;
+ // If true, assume that dynamic initializers can never access globals from
+ // other modules, even if the latter are already initialized.
+ bool strict_init_order;
};
-Flags *flags();
+extern Flags asan_flags_dont_use_directly;
+inline Flags *flags() {
+ return &asan_flags_dont_use_directly;
+}
void InitializeFlags(Flags *f, const char *env);
} // namespace __asan
diff --git a/libsanitizer/asan/asan_globals.cc b/libsanitizer/asan/asan_globals.cc
index 7093c445588..96985af71a9 100644
--- a/libsanitizer/asan/asan_globals.cc
+++ b/libsanitizer/asan/asan_globals.cc
@@ -12,11 +12,14 @@
#include "asan_interceptors.h"
#include "asan_internal.h"
#include "asan_mapping.h"
+#include "asan_poisoning.h"
#include "asan_report.h"
#include "asan_stack.h"
#include "asan_stats.h"
#include "asan_thread.h"
+#include "sanitizer_common/sanitizer_common.h"
#include "sanitizer_common/sanitizer_mutex.h"
+#include "sanitizer_common/sanitizer_placement_new.h"
namespace __asan {
@@ -30,15 +33,26 @@ struct ListOfGlobals {
static BlockingMutex mu_for_globals(LINKER_INITIALIZED);
static LowLevelAllocator allocator_for_globals;
static ListOfGlobals *list_of_all_globals;
-static ListOfGlobals *list_of_dynamic_init_globals;
-void PoisonRedZones(const Global &g) {
+static const int kDynamicInitGlobalsInitialCapacity = 512;
+struct DynInitGlobal {
+ Global g;
+ bool initialized;
+};
+typedef InternalMmapVector<DynInitGlobal> VectorOfGlobals;
+// Lazy-initialized and never deleted.
+static VectorOfGlobals *dynamic_init_globals;
+
+ALWAYS_INLINE void PoisonShadowForGlobal(const Global *g, u8 value) {
+ FastPoisonShadow(g->beg, g->size_with_redzone, value);
+}
+
+ALWAYS_INLINE void PoisonRedZones(const Global &g) {
uptr aligned_size = RoundUpTo(g.size, SHADOW_GRANULARITY);
- PoisonShadow(g.beg + aligned_size, g.size_with_redzone - aligned_size,
- kAsanGlobalRedzoneMagic);
+ FastPoisonShadow(g.beg + aligned_size, g.size_with_redzone - aligned_size,
+ kAsanGlobalRedzoneMagic);
if (g.size != aligned_size) {
- // partial right redzone
- PoisonShadowPartialRightRedzone(
+ FastPoisonShadowPartialRightRedzone(
g.beg + RoundDownTo(g.size, SHADOW_GRANULARITY),
g.size % SHADOW_GRANULARITY,
SHADOW_GRANULARITY,
@@ -46,6 +60,12 @@ void PoisonRedZones(const Global &g) {
}
}
+static void ReportGlobal(const Global &g, const char *prefix) {
+ Report("%s Global: beg=%p size=%zu/%zu name=%s module=%s dyn_init=%zu\n",
+ prefix, (void*)g.beg, g.size, g.size_with_redzone, g.name,
+ g.module_name, g.has_dynamic_init);
+}
+
bool DescribeAddressIfGlobal(uptr addr, uptr size) {
if (!flags()->report_globals) return false;
BlockingMutexLock lock(&mu_for_globals);
@@ -53,8 +73,7 @@ bool DescribeAddressIfGlobal(uptr addr, uptr size) {
for (ListOfGlobals *l = list_of_all_globals; l; l = l->next) {
const Global &g = *l->g;
if (flags()->report_globals >= 2)
- Report("Search Global: beg=%p size=%zu name=%s\n",
- (void*)g.beg, g.size, (char*)g.name);
+ ReportGlobal(g, "Search");
res |= DescribeAddressRelativeToGlobal(addr, size, g);
}
return res;
@@ -66,24 +85,26 @@ bool DescribeAddressIfGlobal(uptr addr, uptr size) {
static void RegisterGlobal(const Global *g) {
CHECK(asan_inited);
if (flags()->report_globals >= 2)
- Report("Added Global: beg=%p size=%zu/%zu name=%s dyn.init=%zu\n",
- (void*)g->beg, g->size, g->size_with_redzone, g->name,
- g->has_dynamic_init);
+ ReportGlobal(*g, "Added");
CHECK(flags()->report_globals);
CHECK(AddrIsInMem(g->beg));
CHECK(AddrIsAlignedByGranularity(g->beg));
CHECK(AddrIsAlignedByGranularity(g->size_with_redzone));
- PoisonRedZones(*g);
+ if (flags()->poison_heap)
+ PoisonRedZones(*g);
ListOfGlobals *l =
(ListOfGlobals*)allocator_for_globals.Allocate(sizeof(ListOfGlobals));
l->g = g;
l->next = list_of_all_globals;
list_of_all_globals = l;
if (g->has_dynamic_init) {
- l = (ListOfGlobals*)allocator_for_globals.Allocate(sizeof(ListOfGlobals));
- l->g = g;
- l->next = list_of_dynamic_init_globals;
- list_of_dynamic_init_globals = l;
+ if (dynamic_init_globals == 0) {
+ void *mem = allocator_for_globals.Allocate(sizeof(VectorOfGlobals));
+ dynamic_init_globals = new(mem)
+ VectorOfGlobals(kDynamicInitGlobalsInitialCapacity);
+ }
+ DynInitGlobal dyn_global = { *g, false };
+ dynamic_init_globals->push_back(dyn_global);
}
}
@@ -93,34 +114,26 @@ static void UnregisterGlobal(const Global *g) {
CHECK(AddrIsInMem(g->beg));
CHECK(AddrIsAlignedByGranularity(g->beg));
CHECK(AddrIsAlignedByGranularity(g->size_with_redzone));
- PoisonShadow(g->beg, g->size_with_redzone, 0);
+ if (flags()->poison_heap)
+ PoisonShadowForGlobal(g, 0);
// We unpoison the shadow memory for the global but we do not remove it from
// the list because that would require O(n^2) time with the current list
// implementation. It might not be worth doing anyway.
}
-// Poison all shadow memory for a single global.
-static void PoisonGlobalAndRedzones(const Global *g) {
- CHECK(asan_inited);
- CHECK(flags()->check_initialization_order);
- CHECK(AddrIsInMem(g->beg));
- CHECK(AddrIsAlignedByGranularity(g->beg));
- CHECK(AddrIsAlignedByGranularity(g->size_with_redzone));
- if (flags()->report_globals >= 3)
- Printf("DynInitPoison : %s\n", g->name);
- PoisonShadow(g->beg, g->size_with_redzone, kAsanInitializationOrderMagic);
-}
-
-static void UnpoisonGlobal(const Global *g) {
- CHECK(asan_inited);
- CHECK(flags()->check_initialization_order);
- CHECK(AddrIsInMem(g->beg));
- CHECK(AddrIsAlignedByGranularity(g->beg));
- CHECK(AddrIsAlignedByGranularity(g->size_with_redzone));
- if (flags()->report_globals >= 3)
- Printf("DynInitUnpoison: %s\n", g->name);
- PoisonShadow(g->beg, g->size_with_redzone, 0);
- PoisonRedZones(*g);
+void StopInitOrderChecking() {
+ BlockingMutexLock lock(&mu_for_globals);
+ if (!flags()->check_initialization_order || !dynamic_init_globals)
+ return;
+ flags()->check_initialization_order = false;
+ for (uptr i = 0, n = dynamic_init_globals->size(); i < n; ++i) {
+ DynInitGlobal &dyn_g = (*dynamic_init_globals)[i];
+ const Global *g = &dyn_g.g;
+ // Unpoison the whole global.
+ PoisonShadowForGlobal(g, 0);
+ // Poison redzones back.
+ PoisonRedZones(*g);
+ }
}
} // namespace __asan
@@ -151,31 +164,47 @@ void __asan_unregister_globals(__asan_global *globals, uptr n) {
// when all dynamically initialized globals are unpoisoned. This method
// poisons all global variables not defined in this TU, so that a dynamic
// initializer can only touch global variables in the same TU.
-void __asan_before_dynamic_init(uptr first_addr, uptr last_addr) {
- if (!flags()->check_initialization_order) return;
- CHECK(list_of_dynamic_init_globals);
+void __asan_before_dynamic_init(const char *module_name) {
+ if (!flags()->check_initialization_order ||
+ !flags()->poison_heap)
+ return;
+ bool strict_init_order = flags()->strict_init_order;
+ CHECK(dynamic_init_globals);
+ CHECK(module_name);
+ CHECK(asan_inited);
BlockingMutexLock lock(&mu_for_globals);
- bool from_current_tu = false;
- // The list looks like:
- // a => ... => b => last_addr => ... => first_addr => c => ...
- // The globals of the current TU reside between last_addr and first_addr.
- for (ListOfGlobals *l = list_of_dynamic_init_globals; l; l = l->next) {
- if (l->g->beg == last_addr)
- from_current_tu = true;
- if (!from_current_tu)
- PoisonGlobalAndRedzones(l->g);
- if (l->g->beg == first_addr)
- from_current_tu = false;
+ if (flags()->report_globals >= 3)
+ Printf("DynInitPoison module: %s\n", module_name);
+ for (uptr i = 0, n = dynamic_init_globals->size(); i < n; ++i) {
+ DynInitGlobal &dyn_g = (*dynamic_init_globals)[i];
+ const Global *g = &dyn_g.g;
+ if (dyn_g.initialized)
+ continue;
+ if (g->module_name != module_name)
+ PoisonShadowForGlobal(g, kAsanInitializationOrderMagic);
+ else if (!strict_init_order)
+ dyn_g.initialized = true;
}
- CHECK(!from_current_tu);
}
// This method runs immediately after dynamic initialization in each TU, when
// all dynamically initialized globals except for those defined in the current
// TU are poisoned. It simply unpoisons all dynamically initialized globals.
void __asan_after_dynamic_init() {
- if (!flags()->check_initialization_order) return;
+ if (!flags()->check_initialization_order ||
+ !flags()->poison_heap)
+ return;
+ CHECK(asan_inited);
BlockingMutexLock lock(&mu_for_globals);
- for (ListOfGlobals *l = list_of_dynamic_init_globals; l; l = l->next)
- UnpoisonGlobal(l->g);
+ // FIXME: Optionally report that we're unpoisoning globals from a module.
+ for (uptr i = 0, n = dynamic_init_globals->size(); i < n; ++i) {
+ DynInitGlobal &dyn_g = (*dynamic_init_globals)[i];
+ const Global *g = &dyn_g.g;
+ if (!dyn_g.initialized) {
+ // Unpoison the whole global.
+ PoisonShadowForGlobal(g, 0);
+ // Poison redzones back.
+ PoisonRedZones(*g);
+ }
+ }
}
diff --git a/libsanitizer/asan/asan_intercepted_functions.h b/libsanitizer/asan/asan_intercepted_functions.h
index ed75c428439..19b53363a5b 100644
--- a/libsanitizer/asan/asan_intercepted_functions.h
+++ b/libsanitizer/asan/asan_intercepted_functions.h
@@ -12,22 +12,14 @@
#ifndef ASAN_INTERCEPTED_FUNCTIONS_H
#define ASAN_INTERCEPTED_FUNCTIONS_H
-#include "asan_internal.h"
-#include "interception/interception.h"
#include "sanitizer_common/sanitizer_platform_interceptors.h"
-#include <stdarg.h>
-#include <stddef.h>
-
-using __sanitizer::uptr;
-
// Use macro to describe if specific function should be
// intercepted on a given platform.
-#if !defined(_WIN32)
+#if !SANITIZER_WINDOWS
# define ASAN_INTERCEPT_ATOLL_AND_STRTOLL 1
# define ASAN_INTERCEPT__LONGJMP 1
# define ASAN_INTERCEPT_STRDUP 1
-# define ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP 1
# define ASAN_INTERCEPT_INDEX 1
# define ASAN_INTERCEPT_PTHREAD_CREATE 1
# define ASAN_INTERCEPT_MLOCKX 1
@@ -35,290 +27,51 @@ using __sanitizer::uptr;
# define ASAN_INTERCEPT_ATOLL_AND_STRTOLL 0
# define ASAN_INTERCEPT__LONGJMP 0
# define ASAN_INTERCEPT_STRDUP 0
-# define ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP 0
# define ASAN_INTERCEPT_INDEX 0
# define ASAN_INTERCEPT_PTHREAD_CREATE 0
# define ASAN_INTERCEPT_MLOCKX 0
#endif
-#if defined(__linux__)
+#if SANITIZER_LINUX
# define ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX 1
#else
# define ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX 0
#endif
-#if !defined(__APPLE__)
+#if !SANITIZER_MAC
# define ASAN_INTERCEPT_STRNLEN 1
#else
# define ASAN_INTERCEPT_STRNLEN 0
#endif
-#if defined(__linux__) && !defined(ANDROID)
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
# define ASAN_INTERCEPT_SWAPCONTEXT 1
#else
# define ASAN_INTERCEPT_SWAPCONTEXT 0
#endif
-#if !defined(ANDROID) && !defined(_WIN32)
+#if !SANITIZER_ANDROID && !SANITIZER_WINDOWS
# define ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 1
#else
# define ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 0
#endif
-#if !defined(_WIN32)
+#if !SANITIZER_WINDOWS
# define ASAN_INTERCEPT_SIGLONGJMP 1
#else
# define ASAN_INTERCEPT_SIGLONGJMP 0
#endif
-#if ASAN_HAS_EXCEPTIONS && !defined(_WIN32)
+#if ASAN_HAS_EXCEPTIONS && !SANITIZER_WINDOWS
# define ASAN_INTERCEPT___CXA_THROW 1
#else
# define ASAN_INTERCEPT___CXA_THROW 0
#endif
-#define INTERPOSE_FUNCTION(function) \
- { reinterpret_cast<const uptr>(WRAP(function)), \
- reinterpret_cast<const uptr>(function) }
-
-#define INTERPOSE_FUNCTION_2(function, wrapper) \
- { reinterpret_cast<const uptr>(wrapper), \
- reinterpret_cast<const uptr>(function) }
-
-struct interpose_substitution {
- const uptr replacement;
- const uptr original;
-};
-
-#define INTERPOSER(func) __attribute__((used)) \
-const interpose_substitution substitution_##func[] \
- __attribute__((section("__DATA, __interpose"))) = { \
- INTERPOSE_FUNCTION(func), \
-}
-
-#define INTERPOSER_2(func, wrapper) __attribute__((used)) \
-const interpose_substitution substitution_##func[] \
- __attribute__((section("__DATA, __interpose"))) = { \
- INTERPOSE_FUNCTION_2(func, wrapper), \
-}
-
-
-#define DECLARE_FUNCTION_AND_WRAPPER(ret_type, func, ...) \
- ret_type func(__VA_ARGS__); \
- ret_type WRAP(func)(__VA_ARGS__); \
- INTERPOSER(func)
-
-// Use extern declarations of intercepted functions on Mac and Windows
-// to avoid including system headers.
-#if defined(__APPLE__) || (defined(_WIN32) && !defined(_DLL))
-extern "C" {
-// signal.h
-# if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
-struct sigaction;
-DECLARE_FUNCTION_AND_WRAPPER(int, sigaction, int sig,
- const struct sigaction *act,
- struct sigaction *oldact);
-DECLARE_FUNCTION_AND_WRAPPER(void*, signal, int signum, void *handler);
-# endif
-
-// setjmp.h
-DECLARE_FUNCTION_AND_WRAPPER(void, longjmp, void *env, int value);
-# if ASAN_INTERCEPT__LONGJMP
-DECLARE_FUNCTION_AND_WRAPPER(void, _longjmp, void *env, int value);
-# endif
-# if ASAN_INTERCEPT_SIGLONGJMP
-DECLARE_FUNCTION_AND_WRAPPER(void, siglongjmp, void *env, int value);
-# endif
-# if ASAN_INTERCEPT___CXA_THROW
-DECLARE_FUNCTION_AND_WRAPPER(void, __cxa_throw, void *a, void *b, void *c);
-# endif
-
-// string.h / strings.h
-DECLARE_FUNCTION_AND_WRAPPER(int, memcmp,
- const void *a1, const void *a2, uptr size);
-DECLARE_FUNCTION_AND_WRAPPER(void*, memmove,
- void *to, const void *from, uptr size);
-DECLARE_FUNCTION_AND_WRAPPER(void*, memcpy,
- void *to, const void *from, uptr size);
-DECLARE_FUNCTION_AND_WRAPPER(void*, memset, void *block, int c, uptr size);
-DECLARE_FUNCTION_AND_WRAPPER(char*, strchr, const char *str, int c);
-DECLARE_FUNCTION_AND_WRAPPER(char*, strcat, /* NOLINT */
- char *to, const char* from);
-DECLARE_FUNCTION_AND_WRAPPER(char*, strncat,
- char *to, const char* from, uptr size);
-DECLARE_FUNCTION_AND_WRAPPER(char*, strcpy, /* NOLINT */
- char *to, const char* from);
-DECLARE_FUNCTION_AND_WRAPPER(char*, strncpy,
- char *to, const char* from, uptr size);
-DECLARE_FUNCTION_AND_WRAPPER(int, strcmp, const char *s1, const char* s2);
-DECLARE_FUNCTION_AND_WRAPPER(int, strncmp,
- const char *s1, const char* s2, uptr size);
-DECLARE_FUNCTION_AND_WRAPPER(uptr, strlen, const char *s);
-# if ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP
-DECLARE_FUNCTION_AND_WRAPPER(int, strcasecmp, const char *s1, const char *s2);
-DECLARE_FUNCTION_AND_WRAPPER(int, strncasecmp,
- const char *s1, const char *s2, uptr n);
-# endif
-# if ASAN_INTERCEPT_STRDUP
-DECLARE_FUNCTION_AND_WRAPPER(char*, strdup, const char *s);
-# endif
-# if ASAN_INTERCEPT_STRNLEN
-DECLARE_FUNCTION_AND_WRAPPER(uptr, strnlen, const char *s, uptr maxlen);
-# endif
-# if ASAN_INTERCEPT_INDEX
-char* index(const char *string, int c);
-INTERPOSER_2(index, WRAP(strchr));
-# endif
-
-// stdlib.h
-DECLARE_FUNCTION_AND_WRAPPER(int, atoi, const char *nptr);
-DECLARE_FUNCTION_AND_WRAPPER(long, atol, const char *nptr); // NOLINT
-DECLARE_FUNCTION_AND_WRAPPER(long, strtol, const char *nptr, char **endptr, int base); // NOLINT
-# if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
-DECLARE_FUNCTION_AND_WRAPPER(long long, atoll, const char *nptr); // NOLINT
-DECLARE_FUNCTION_AND_WRAPPER(long long, strtoll, const char *nptr, char **endptr, int base); // NOLINT
-# endif
-
-// unistd.h
-# if SANITIZER_INTERCEPT_READ
-DECLARE_FUNCTION_AND_WRAPPER(SSIZE_T, read, int fd, void *buf, SIZE_T count);
-# endif
-# if SANITIZER_INTERCEPT_PREAD
-DECLARE_FUNCTION_AND_WRAPPER(SSIZE_T, pread, int fd, void *buf,
- SIZE_T count, OFF_T offset);
-# endif
-# if SANITIZER_INTERCEPT_PREAD64
-DECLARE_FUNCTION_AND_WRAPPER(SSIZE_T, pread64, int fd, void *buf,
- SIZE_T count, OFF64_T offset);
-# endif
-
-# if SANITIZER_INTERCEPT_WRITE
-DECLARE_FUNCTION_AND_WRAPPER(SSIZE_T, write, int fd, void *ptr, SIZE_T count);
-# endif
-# if SANITIZER_INTERCEPT_PWRITE
-DECLARE_FUNCTION_AND_WRAPPER(SSIZE_T, pwrite,
- int fd, void *ptr, SIZE_T count, OFF_T offset);
-# endif
-
-# if ASAN_INTERCEPT_MLOCKX
-// mlock/munlock
-DECLARE_FUNCTION_AND_WRAPPER(int, mlock, const void *addr, SIZE_T len);
-DECLARE_FUNCTION_AND_WRAPPER(int, munlock, const void *addr, SIZE_T len);
-DECLARE_FUNCTION_AND_WRAPPER(int, mlockall, int flags);
-DECLARE_FUNCTION_AND_WRAPPER(int, munlockall, void);
-# endif
-
-// Windows threads.
-# if defined(_WIN32)
-__declspec(dllimport)
-void* __stdcall CreateThread(void *sec, uptr st, void* start,
- void *arg, DWORD fl, DWORD *id);
-# endif
-// Posix threads.
-# if ASAN_INTERCEPT_PTHREAD_CREATE
-DECLARE_FUNCTION_AND_WRAPPER(int, pthread_create,
- void *thread, void *attr,
- void *(*start_routine)(void*), void *arg);
-# endif
-
-# if SANITIZER_INTERCEPT_LOCALTIME_AND_FRIENDS
-DECLARE_FUNCTION_AND_WRAPPER(void *, localtime, unsigned long *timep);
-DECLARE_FUNCTION_AND_WRAPPER(void *, localtime_r, unsigned long *timep,
- void *result);
-DECLARE_FUNCTION_AND_WRAPPER(void *, gmtime, unsigned long *timep);
-DECLARE_FUNCTION_AND_WRAPPER(void *, gmtime_r, unsigned long *timep,
- void *result);
-DECLARE_FUNCTION_AND_WRAPPER(char *, ctime, unsigned long *timep);
-DECLARE_FUNCTION_AND_WRAPPER(char *, ctime_r, unsigned long *timep,
- char *result);
-DECLARE_FUNCTION_AND_WRAPPER(char *, asctime, void *tm);
-DECLARE_FUNCTION_AND_WRAPPER(char *, asctime_r, void *tm, char *result);
-# endif
-
-// stdio.h
-# if SANITIZER_INTERCEPT_SCANF
-DECLARE_FUNCTION_AND_WRAPPER(int, vscanf, const char *format, va_list ap);
-DECLARE_FUNCTION_AND_WRAPPER(int, vsscanf, const char *str, const char *format,
- va_list ap);
-DECLARE_FUNCTION_AND_WRAPPER(int, vfscanf, void *stream, const char *format,
- va_list ap);
-DECLARE_FUNCTION_AND_WRAPPER(int, scanf, const char *format, ...);
-DECLARE_FUNCTION_AND_WRAPPER(int, fscanf,
- void* stream, const char *format, ...);
-DECLARE_FUNCTION_AND_WRAPPER(int, sscanf, // NOLINT
- const char *str, const char *format, ...);
-# endif
-
-# if defined(__APPLE__)
-typedef void* pthread_workqueue_t;
-typedef void* pthread_workitem_handle_t;
-
-typedef void* dispatch_group_t;
-typedef void* dispatch_queue_t;
-typedef void* dispatch_source_t;
-typedef u64 dispatch_time_t;
-typedef void (*dispatch_function_t)(void *block);
-typedef void* (*worker_t)(void *block);
-
-DECLARE_FUNCTION_AND_WRAPPER(void, dispatch_async_f,
- dispatch_queue_t dq,
- void *ctxt, dispatch_function_t func);
-DECLARE_FUNCTION_AND_WRAPPER(void, dispatch_sync_f,
- dispatch_queue_t dq,
- void *ctxt, dispatch_function_t func);
-DECLARE_FUNCTION_AND_WRAPPER(void, dispatch_after_f,
- dispatch_time_t when, dispatch_queue_t dq,
- void *ctxt, dispatch_function_t func);
-DECLARE_FUNCTION_AND_WRAPPER(void, dispatch_barrier_async_f,
- dispatch_queue_t dq,
- void *ctxt, dispatch_function_t func);
-DECLARE_FUNCTION_AND_WRAPPER(void, dispatch_group_async_f,
- dispatch_group_t group, dispatch_queue_t dq,
- void *ctxt, dispatch_function_t func);
-
-# if !defined(MISSING_BLOCKS_SUPPORT)
-DECLARE_FUNCTION_AND_WRAPPER(void, dispatch_group_async,
- dispatch_group_t dg,
- dispatch_queue_t dq, void (^work)(void));
-DECLARE_FUNCTION_AND_WRAPPER(void, dispatch_async,
- dispatch_queue_t dq, void (^work)(void));
-DECLARE_FUNCTION_AND_WRAPPER(void, dispatch_after,
- dispatch_queue_t dq, void (^work)(void));
-DECLARE_FUNCTION_AND_WRAPPER(void, dispatch_source_set_event_handler,
- dispatch_source_t ds, void (^work)(void));
-DECLARE_FUNCTION_AND_WRAPPER(void, dispatch_source_set_cancel_handler,
- dispatch_source_t ds, void (^work)(void));
-# endif // MISSING_BLOCKS_SUPPORT
-
-typedef void malloc_zone_t;
-typedef size_t vm_size_t;
-DECLARE_FUNCTION_AND_WRAPPER(malloc_zone_t *, malloc_create_zone,
- vm_size_t start_size, unsigned flags);
-DECLARE_FUNCTION_AND_WRAPPER(malloc_zone_t *, malloc_default_zone, void);
-DECLARE_FUNCTION_AND_WRAPPER(
- malloc_zone_t *, malloc_default_purgeable_zone, void);
-DECLARE_FUNCTION_AND_WRAPPER(void, malloc_make_purgeable, void *ptr);
-DECLARE_FUNCTION_AND_WRAPPER(int, malloc_make_nonpurgeable, void *ptr);
-DECLARE_FUNCTION_AND_WRAPPER(void, malloc_set_zone_name,
- malloc_zone_t *zone, const char *name);
-DECLARE_FUNCTION_AND_WRAPPER(void *, malloc, size_t size);
-DECLARE_FUNCTION_AND_WRAPPER(void, free, void *ptr);
-DECLARE_FUNCTION_AND_WRAPPER(void *, realloc, void *ptr, size_t size);
-DECLARE_FUNCTION_AND_WRAPPER(void *, calloc, size_t nmemb, size_t size);
-DECLARE_FUNCTION_AND_WRAPPER(void *, valloc, size_t size);
-DECLARE_FUNCTION_AND_WRAPPER(size_t, malloc_good_size, size_t size);
-DECLARE_FUNCTION_AND_WRAPPER(int, posix_memalign,
- void **memptr, size_t alignment, size_t size);
-#if 0
-DECLARE_FUNCTION_AND_WRAPPER(void, _malloc_fork_prepare, void);
-DECLARE_FUNCTION_AND_WRAPPER(void, _malloc_fork_parent, void);
-DECLARE_FUNCTION_AND_WRAPPER(void, _malloc_fork_child, void);
+#if !SANITIZER_WINDOWS
+# define ASAN_INTERCEPT___CXA_ATEXIT 1
+#else
+# define ASAN_INTERCEPT___CXA_ATEXIT 0
#endif
-
-
-# endif // __APPLE__
-} // extern "C"
-#endif // defined(__APPLE__) || (defined(_WIN32) && !defined(_DLL))
-
#endif // ASAN_INTERCEPTED_FUNCTIONS_H
diff --git a/libsanitizer/asan/asan_interceptors.cc b/libsanitizer/asan/asan_interceptors.cc
index 064fc6261b0..6fa968da0a3 100644
--- a/libsanitizer/asan/asan_interceptors.cc
+++ b/libsanitizer/asan/asan_interceptors.cc
@@ -15,10 +15,10 @@
#include "asan_intercepted_functions.h"
#include "asan_internal.h"
#include "asan_mapping.h"
+#include "asan_poisoning.h"
#include "asan_report.h"
#include "asan_stack.h"
#include "asan_stats.h"
-#include "asan_thread_registry.h"
#include "interception/interception.h"
#include "sanitizer_common/sanitizer_libc.h"
@@ -42,15 +42,16 @@ static inline bool QuickCheckForUnpoisonedRegion(uptr beg, uptr size) {
#define ACCESS_MEMORY_RANGE(offset, size, isWrite) do { \
uptr __offset = (uptr)(offset); \
uptr __size = (uptr)(size); \
+ uptr __bad = 0; \
if (!QuickCheckForUnpoisonedRegion(__offset, __size) && \
- __asan_region_is_poisoned(__offset, __size)) { \
+ (__bad = __asan_region_is_poisoned(__offset, __size))) { \
GET_CURRENT_PC_BP_SP; \
- __asan_report_error(pc, bp, sp, __offset, isWrite, __size); \
+ __asan_report_error(pc, bp, sp, __bad, isWrite, __size); \
} \
} while (0)
#define ASAN_READ_RANGE(offset, size) ACCESS_MEMORY_RANGE(offset, size, false)
-#define ASAN_WRITE_RANGE(offset, size) ACCESS_MEMORY_RANGE(offset, size, true);
+#define ASAN_WRITE_RANGE(offset, size) ACCESS_MEMORY_RANGE(offset, size, true)
// Behavior of functions like "memcpy" or "strcpy" is undefined
// if memory intervals overlap. We report error in this case.
@@ -86,9 +87,9 @@ static inline uptr MaybeRealStrnlen(const char *s, uptr maxlen) {
}
void SetThreadName(const char *name) {
- AsanThread *t = asanThreadRegistry().GetCurrent();
+ AsanThread *t = GetCurrentThread();
if (t)
- t->summary()->set_name(name);
+ asanThreadRegistry().SetThreadName(t->tid(), name);
}
} // namespace __asan
@@ -96,40 +97,76 @@ void SetThreadName(const char *name) {
// ---------------------- Wrappers ---------------- {{{1
using namespace __asan; // NOLINT
+DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr)
+DECLARE_REAL_AND_INTERCEPTOR(void, free, void *)
+
+#define COMMON_INTERCEPTOR_UNPOISON_PARAM(ctx, count) \
+ do { \
+ } while (false)
#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
ASAN_WRITE_RANGE(ptr, size)
#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) ASAN_READ_RANGE(ptr, size)
-#define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \
- do { \
- ctx = 0; \
- (void)ctx; \
- ENSURE_ASAN_INITED(); \
+#define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \
+ do { \
+ if (asan_init_is_running) return REAL(func)(__VA_ARGS__); \
+ ctx = 0; \
+ (void) ctx; \
+ ENSURE_ASAN_INITED(); \
+ } while (false)
+#define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
+ do { \
+ } while (false)
+#define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \
+ do { \
+ } while (false)
+#define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \
+ do { \
} while (false)
-#define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) do { } while (false)
-#define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) do { } while (false)
#define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) SetThreadName(name)
+#define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name)
#include "sanitizer_common/sanitizer_common_interceptors.inc"
+#define COMMON_SYSCALL_PRE_READ_RANGE(p, s) ASAN_READ_RANGE(p, s)
+#define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) ASAN_WRITE_RANGE(p, s)
+#define COMMON_SYSCALL_POST_READ_RANGE(p, s) \
+ do { \
+ } while (false)
+#define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) \
+ do { \
+ } while (false)
+#include "sanitizer_common/sanitizer_common_syscalls.inc"
+
static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) {
AsanThread *t = (AsanThread*)arg;
- asanThreadRegistry().SetCurrent(t);
- return t->ThreadStart();
+ SetCurrentThread(t);
+ return t->ThreadStart(GetTid());
}
#if ASAN_INTERCEPT_PTHREAD_CREATE
+extern "C" int pthread_attr_getdetachstate(void *attr, int *v);
+
INTERCEPTOR(int, pthread_create, void *thread,
void *attr, void *(*start_routine)(void*), void *arg) {
+ EnsureMainThreadIDIsCorrect();
+ // Strict init-order checking in thread-hostile.
+ if (flags()->strict_init_order)
+ StopInitOrderChecking();
GET_STACK_TRACE_THREAD;
- u32 current_tid = asanThreadRegistry().GetCurrentTidOrInvalid();
- AsanThread *t = AsanThread::Create(current_tid, start_routine, arg, &stack);
- asanThreadRegistry().RegisterThread(t);
+ int detached = 0;
+ if (attr != 0)
+ pthread_attr_getdetachstate(attr, &detached);
+
+ u32 current_tid = GetCurrentTidOrInvalid();
+ AsanThread *t = AsanThread::Create(start_routine, arg);
+ CreateThreadContextArgs args = { t, &stack };
+ asanThreadRegistry().CreateThread(*(uptr*)t, detached, current_tid, &args);
return REAL(pthread_create)(thread, attr, asan_thread_start, t);
}
#endif // ASAN_INTERCEPT_PTHREAD_CREATE
#if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
INTERCEPTOR(void*, signal, int signum, void *handler) {
- if (!AsanInterceptsSignal(signum)) {
+ if (!AsanInterceptsSignal(signum) || flags()->allow_user_segv_handler) {
return REAL(signal)(signum, handler);
}
return 0;
@@ -137,15 +174,15 @@ INTERCEPTOR(void*, signal, int signum, void *handler) {
INTERCEPTOR(int, sigaction, int signum, const struct sigaction *act,
struct sigaction *oldact) {
- if (!AsanInterceptsSignal(signum)) {
+ if (!AsanInterceptsSignal(signum) || flags()->allow_user_segv_handler) {
return REAL(sigaction)(signum, act, oldact);
}
return 0;
}
-#elif ASAN_POSIX
+#elif SANITIZER_POSIX
// We need to have defined REAL(sigaction) on posix systems.
DEFINE_REAL(int, sigaction, int signum, const struct sigaction *act,
- struct sigaction *oldact);
+ struct sigaction *oldact)
#endif // ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
#if ASAN_INTERCEPT_SWAPCONTEXT
@@ -215,13 +252,15 @@ INTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) {
// Since asan maps 16T of RAM, mlock is completely unfriendly to asan.
// All functions return 0 (success).
static void MlockIsUnsupported() {
- static bool printed = 0;
+ static bool printed = false;
if (printed) return;
printed = true;
- Printf("INFO: AddressSanitizer ignores mlock/mlockall/munlock/munlockall\n");
+ if (flags()->verbosity > 0) {
+ Printf("INFO: AddressSanitizer ignores "
+ "mlock/mlockall/munlock/munlockall\n");
+ }
}
-extern "C" {
INTERCEPTOR(int, mlock, const void *addr, uptr len) {
MlockIsUnsupported();
return 0;
@@ -241,36 +280,56 @@ INTERCEPTOR(int, munlockall, void) {
MlockIsUnsupported();
return 0;
}
-} // extern "C"
static inline int CharCmp(unsigned char c1, unsigned char c2) {
return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1;
}
-static inline int CharCaseCmp(unsigned char c1, unsigned char c2) {
- int c1_low = ToLower(c1);
- int c2_low = ToLower(c2);
- return c1_low - c2_low;
-}
-
INTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) {
if (!asan_inited) return internal_memcmp(a1, a2, size);
ENSURE_ASAN_INITED();
- unsigned char c1 = 0, c2 = 0;
- const unsigned char *s1 = (const unsigned char*)a1;
- const unsigned char *s2 = (const unsigned char*)a2;
- uptr i;
- for (i = 0; i < size; i++) {
- c1 = s1[i];
- c2 = s2[i];
- if (c1 != c2) break;
+ if (flags()->replace_intrin) {
+ if (flags()->strict_memcmp) {
+ // Check the entire regions even if the first bytes of the buffers are
+ // different.
+ ASAN_READ_RANGE(a1, size);
+ ASAN_READ_RANGE(a2, size);
+ // Fallthrough to REAL(memcmp) below.
+ } else {
+ unsigned char c1 = 0, c2 = 0;
+ const unsigned char *s1 = (const unsigned char*)a1;
+ const unsigned char *s2 = (const unsigned char*)a2;
+ uptr i;
+ for (i = 0; i < size; i++) {
+ c1 = s1[i];
+ c2 = s2[i];
+ if (c1 != c2) break;
+ }
+ ASAN_READ_RANGE(s1, Min(i + 1, size));
+ ASAN_READ_RANGE(s2, Min(i + 1, size));
+ return CharCmp(c1, c2);
+ }
}
- ASAN_READ_RANGE(s1, Min(i + 1, size));
- ASAN_READ_RANGE(s2, Min(i + 1, size));
- return CharCmp(c1, c2);
+ return REAL(memcmp(a1, a2, size));
}
+#define MEMMOVE_BODY { \
+ if (!asan_inited) return internal_memmove(to, from, size); \
+ if (asan_init_is_running) { \
+ return REAL(memmove)(to, from, size); \
+ } \
+ ENSURE_ASAN_INITED(); \
+ if (flags()->replace_intrin) { \
+ ASAN_READ_RANGE(from, size); \
+ ASAN_WRITE_RANGE(to, size); \
+ } \
+ return internal_memmove(to, from, size); \
+}
+
+INTERCEPTOR(void*, memmove, void *to, const void *from, uptr size) MEMMOVE_BODY
+
INTERCEPTOR(void*, memcpy, void *to, const void *from, uptr size) {
+#if !SANITIZER_MAC
if (!asan_inited) return internal_memcpy(to, from, size);
// memcpy is called during __asan_init() from the internals
// of printf(...).
@@ -287,24 +346,19 @@ INTERCEPTOR(void*, memcpy, void *to, const void *from, uptr size) {
ASAN_READ_RANGE(from, size);
ASAN_WRITE_RANGE(to, size);
}
- // Interposing of resolver functions is broken on Mac OS 10.7 and 10.8.
+ // Interposing of resolver functions is broken on Mac OS 10.7 and 10.8, so
+ // calling REAL(memcpy) here leads to infinite recursion.
// See also http://code.google.com/p/address-sanitizer/issues/detail?id=116.
return internal_memcpy(to, from, size);
-}
-
-INTERCEPTOR(void*, memmove, void *to, const void *from, uptr size) {
- if (!asan_inited) return internal_memmove(to, from, size);
- if (asan_init_is_running) {
- return REAL(memmove)(to, from, size);
- }
- ENSURE_ASAN_INITED();
- if (flags()->replace_intrin) {
- ASAN_READ_RANGE(from, size);
- ASAN_WRITE_RANGE(to, size);
- }
- // Interposing of resolver functions is broken on Mac OS 10.7 and 10.8.
- // See also http://code.google.com/p/address-sanitizer/issues/detail?id=116.
- return internal_memmove(to, from, size);
+#else
+ // At least on 10.7 and 10.8 both memcpy() and memmove() are being replaced
+ // with WRAP(memcpy). As a result, false positives are reported for memmove()
+ // calls. If we just disable error reporting with
+ // ASAN_OPTIONS=replace_intrin=0, memmove() is still replaced with
+ // internal_memcpy(), which may lead to crashes, see
+ // http://llvm.org/bugs/show_bug.cgi?id=16362.
+ MEMMOVE_BODY
+#endif // !SANITIZER_MAC
}
INTERCEPTOR(void*, memset, void *block, int c, uptr size) {
@@ -341,7 +395,12 @@ INTERCEPTOR(char*, strchr, const char *str, int c) {
INTERCEPTOR(char*, index, const char *string, int c)
ALIAS(WRAPPER_NAME(strchr));
# else
+# if SANITIZER_MAC
+DECLARE_REAL(char*, index, const char *string, int c)
+OVERRIDE_FUNCTION(index, strchr);
+# else
DEFINE_REAL(char*, index, const char *string, int c)
+# endif
# endif
#endif // ASAN_INTERCEPT_INDEX
@@ -383,26 +442,8 @@ INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) {
return REAL(strncat)(to, from, size);
}
-INTERCEPTOR(int, strcmp, const char *s1, const char *s2) {
- if (!asan_inited) return internal_strcmp(s1, s2);
- if (asan_init_is_running) {
- return REAL(strcmp)(s1, s2);
- }
- ENSURE_ASAN_INITED();
- unsigned char c1, c2;
- uptr i;
- for (i = 0; ; i++) {
- c1 = (unsigned char)s1[i];
- c2 = (unsigned char)s2[i];
- if (c1 != c2 || c1 == '\0') break;
- }
- ASAN_READ_RANGE(s1, i + 1);
- ASAN_READ_RANGE(s2, i + 1);
- return CharCmp(c1, c2);
-}
-
INTERCEPTOR(char*, strcpy, char *to, const char *from) { // NOLINT
-#if defined(__APPLE__)
+#if SANITIZER_MAC
if (!asan_inited) return REAL(strcpy)(to, from); // NOLINT
#endif
// strcpy is called from malloc_default_purgeable_zone()
@@ -422,21 +463,16 @@ INTERCEPTOR(char*, strcpy, char *to, const char *from) { // NOLINT
#if ASAN_INTERCEPT_STRDUP
INTERCEPTOR(char*, strdup, const char *s) {
-#if defined(__APPLE__)
- // FIXME: because internal_strdup() uses InternalAlloc(), which currently
- // just calls malloc() on Mac, we can't use internal_strdup() with the
- // dynamic runtime. We can remove the call to REAL(strdup) once InternalAlloc
- // starts using mmap() instead.
- // See also http://code.google.com/p/address-sanitizer/issues/detail?id=123.
- if (!asan_inited) return REAL(strdup)(s);
-#endif
if (!asan_inited) return internal_strdup(s);
ENSURE_ASAN_INITED();
+ uptr length = REAL(strlen)(s);
if (flags()->replace_str) {
- uptr length = REAL(strlen)(s);
ASAN_READ_RANGE(s, length + 1);
}
- return REAL(strdup)(s);
+ GET_STACK_TRACE_MALLOC;
+ void *new_mem = asan_malloc(length + 1, &stack);
+ REAL(memcpy)(new_mem, s, length + 1);
+ return reinterpret_cast<char*>(new_mem);
}
#endif
@@ -455,54 +491,13 @@ INTERCEPTOR(uptr, strlen, const char *s) {
return length;
}
-#if ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP
-INTERCEPTOR(int, strcasecmp, const char *s1, const char *s2) {
- ENSURE_ASAN_INITED();
- unsigned char c1, c2;
- uptr i;
- for (i = 0; ; i++) {
- c1 = (unsigned char)s1[i];
- c2 = (unsigned char)s2[i];
- if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break;
- }
- ASAN_READ_RANGE(s1, i + 1);
- ASAN_READ_RANGE(s2, i + 1);
- return CharCaseCmp(c1, c2);
-}
-
-INTERCEPTOR(int, strncasecmp, const char *s1, const char *s2, uptr n) {
- ENSURE_ASAN_INITED();
- unsigned char c1 = 0, c2 = 0;
- uptr i;
- for (i = 0; i < n; i++) {
- c1 = (unsigned char)s1[i];
- c2 = (unsigned char)s2[i];
- if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break;
- }
- ASAN_READ_RANGE(s1, Min(i + 1, n));
- ASAN_READ_RANGE(s2, Min(i + 1, n));
- return CharCaseCmp(c1, c2);
-}
-#endif // ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP
-
-INTERCEPTOR(int, strncmp, const char *s1, const char *s2, uptr size) {
- if (!asan_inited) return internal_strncmp(s1, s2, size);
- // strncmp is called from malloc_default_purgeable_zone()
- // in __asan::ReplaceSystemAlloc() on Mac.
- if (asan_init_is_running) {
- return REAL(strncmp)(s1, s2, size);
- }
- ENSURE_ASAN_INITED();
- unsigned char c1 = 0, c2 = 0;
- uptr i;
- for (i = 0; i < size; i++) {
- c1 = (unsigned char)s1[i];
- c2 = (unsigned char)s2[i];
- if (c1 != c2 || c1 == '\0') break;
+INTERCEPTOR(uptr, wcslen, const wchar_t *s) {
+ uptr length = REAL(wcslen)(s);
+ if (!asan_init_is_running) {
+ ENSURE_ASAN_INITED();
+ ASAN_READ_RANGE(s, (length + 1) * sizeof(wchar_t));
}
- ASAN_READ_RANGE(s1, Min(i + 1, size));
- ASAN_READ_RANGE(s2, Min(i + 1, size));
- return CharCmp(c1, c2);
+ return length;
}
INTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) {
@@ -532,7 +527,7 @@ static inline bool IsValidStrtolBase(int base) {
}
static inline void FixRealStrtolEndptr(const char *nptr, char **endptr) {
- CHECK(endptr != 0);
+ CHECK(endptr);
if (nptr == *endptr) {
// No digits were found at strtol call, we need to find out the last
// symbol accessed by strtoll on our own.
@@ -563,7 +558,7 @@ INTERCEPTOR(long, strtol, const char *nptr, // NOLINT
}
INTERCEPTOR(int, atoi, const char *nptr) {
-#if defined(__APPLE__)
+#if SANITIZER_MAC
if (!asan_inited) return REAL(atoi)(nptr);
#endif
ENSURE_ASAN_INITED();
@@ -582,7 +577,7 @@ INTERCEPTOR(int, atoi, const char *nptr) {
}
INTERCEPTOR(long, atol, const char *nptr) { // NOLINT
-#if defined(__APPLE__)
+#if SANITIZER_MAC
if (!asan_inited) return REAL(atol)(nptr);
#endif
ENSURE_ASAN_INITED();
@@ -631,22 +626,47 @@ INTERCEPTOR(long long, atoll, const char *nptr) { // NOLINT
}
#endif // ASAN_INTERCEPT_ATOLL_AND_STRTOLL
+static void AtCxaAtexit(void *unused) {
+ (void)unused;
+ StopInitOrderChecking();
+}
+
+#if ASAN_INTERCEPT___CXA_ATEXIT
+INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg,
+ void *dso_handle) {
+ ENSURE_ASAN_INITED();
+ int res = REAL(__cxa_atexit)(func, arg, dso_handle);
+ REAL(__cxa_atexit)(AtCxaAtexit, 0, 0);
+ return res;
+}
+#endif // ASAN_INTERCEPT___CXA_ATEXIT
+
+#if !SANITIZER_MAC
#define ASAN_INTERCEPT_FUNC(name) do { \
if (!INTERCEPT_FUNCTION(name) && flags()->verbosity > 0) \
Report("AddressSanitizer: failed to intercept '" #name "'\n"); \
} while (0)
+#else
+// OS X interceptors don't need to be initialized with INTERCEPT_FUNCTION.
+#define ASAN_INTERCEPT_FUNC(name)
+#endif // SANITIZER_MAC
-#if defined(_WIN32)
+#if SANITIZER_WINDOWS
INTERCEPTOR_WINAPI(DWORD, CreateThread,
void* security, uptr stack_size,
DWORD (__stdcall *start_routine)(void*), void* arg,
- DWORD flags, void* tid) {
+ DWORD thr_flags, void* tid) {
+ // Strict init-order checking in thread-hostile.
+ if (flags()->strict_init_order)
+ StopInitOrderChecking();
GET_STACK_TRACE_THREAD;
- u32 current_tid = asanThreadRegistry().GetCurrentTidOrInvalid();
- AsanThread *t = AsanThread::Create(current_tid, start_routine, arg, &stack);
- asanThreadRegistry().RegisterThread(t);
+ u32 current_tid = GetCurrentTidOrInvalid();
+ AsanThread *t = AsanThread::Create(start_routine, arg);
+ CreateThreadContextArgs args = { t, &stack };
+ bool detached = false; // FIXME: how can we determine it on Windows?
+ asanThreadRegistry().CreateThread(*(uptr*)t, detached, current_tid, &args);
return REAL(CreateThread)(security, stack_size,
- asan_thread_start, t, flags, tid);
+ asan_thread_start, t, thr_flags, tid);
}
namespace __asan {
@@ -663,9 +683,6 @@ void InitializeAsanInterceptors() {
static bool was_called_once;
CHECK(was_called_once == false);
was_called_once = true;
-#if defined(__APPLE__)
- return;
-#else
SANITIZER_COMMON_INTERCEPTORS_INIT;
// Intercept mem* functions.
@@ -679,16 +696,11 @@ void InitializeAsanInterceptors() {
// Intercept str* functions.
ASAN_INTERCEPT_FUNC(strcat); // NOLINT
ASAN_INTERCEPT_FUNC(strchr);
- ASAN_INTERCEPT_FUNC(strcmp);
ASAN_INTERCEPT_FUNC(strcpy); // NOLINT
ASAN_INTERCEPT_FUNC(strlen);
+ ASAN_INTERCEPT_FUNC(wcslen);
ASAN_INTERCEPT_FUNC(strncat);
- ASAN_INTERCEPT_FUNC(strncmp);
ASAN_INTERCEPT_FUNC(strncpy);
-#if ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP
- ASAN_INTERCEPT_FUNC(strcasecmp);
- ASAN_INTERCEPT_FUNC(strncasecmp);
-#endif
#if ASAN_INTERCEPT_STRDUP
ASAN_INTERCEPT_FUNC(strdup);
#endif
@@ -741,15 +753,19 @@ void InitializeAsanInterceptors() {
ASAN_INTERCEPT_FUNC(pthread_create);
#endif
+ // Intercept atexit function.
+#if ASAN_INTERCEPT___CXA_ATEXIT
+ ASAN_INTERCEPT_FUNC(__cxa_atexit);
+#endif
+
// Some Windows-specific interceptors.
-#if defined(_WIN32)
+#if SANITIZER_WINDOWS
InitializeWindowsInterceptors();
#endif
if (flags()->verbosity > 0) {
Report("AddressSanitizer: libc interceptors initialized\n");
}
-#endif // __APPLE__
}
} // namespace __asan
diff --git a/libsanitizer/asan/asan_interface_internal.h b/libsanitizer/asan/asan_interface_internal.h
index 2fd58b856bc..7deed9f4607 100644
--- a/libsanitizer/asan/asan_interface_internal.h
+++ b/libsanitizer/asan/asan_interface_internal.h
@@ -23,8 +23,13 @@ extern "C" {
// Everytime the asan ABI changes we also change the version number in this
// name. Objects build with incompatible asan ABI version
// will not link with run-time.
- void __asan_init_v1() SANITIZER_INTERFACE_ATTRIBUTE;
- #define __asan_init __asan_init_v1
+ // Changes between ABI versions:
+ // v1=>v2: added 'module_name' to __asan_global
+ // v2=>v3: stack frame description (created by the compiler)
+ // contains the function PC as the 3-rd field (see
+ // DescribeAddressIfStack).
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_init_v3();
+ #define __asan_init __asan_init_v3
// This structure describes an instrumented global variable.
struct __asan_global {
@@ -32,102 +37,92 @@ extern "C" {
uptr size; // The original size of the global.
uptr size_with_redzone; // The size with the redzone.
const char *name; // Name as a C string.
+ const char *module_name; // Module name as a C string. This pointer is a
+ // unique identifier of a module.
uptr has_dynamic_init; // Non-zero if the global has dynamic initializer.
};
// These two functions should be called by the instrumented code.
// 'globals' is an array of structures describing 'n' globals.
- void __asan_register_globals(__asan_global *globals, uptr n)
- SANITIZER_INTERFACE_ATTRIBUTE;
- void __asan_unregister_globals(__asan_global *globals, uptr n)
- SANITIZER_INTERFACE_ATTRIBUTE;
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void __asan_register_globals(__asan_global *globals, uptr n);
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void __asan_unregister_globals(__asan_global *globals, uptr n);
// These two functions should be called before and after dynamic initializers
- // run, respectively. They should be called with parameters describing all
- // dynamically initialized globals defined in the calling TU.
- void __asan_before_dynamic_init(uptr first_addr, uptr last_addr)
- SANITIZER_INTERFACE_ATTRIBUTE;
- void __asan_after_dynamic_init()
- SANITIZER_INTERFACE_ATTRIBUTE;
-
- // These two functions are used by the instrumented code in the
- // use-after-return mode. __asan_stack_malloc allocates size bytes of
- // fake stack and __asan_stack_free poisons it. real_stack is a pointer to
- // the real stack region.
- uptr __asan_stack_malloc(uptr size, uptr real_stack)
- SANITIZER_INTERFACE_ATTRIBUTE;
- void __asan_stack_free(uptr ptr, uptr size, uptr real_stack)
- SANITIZER_INTERFACE_ATTRIBUTE;
+ // of a single module run, respectively.
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void __asan_before_dynamic_init(const char *module_name);
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void __asan_after_dynamic_init();
// These two functions are used by instrumented code in the
// use-after-scope mode. They mark memory for local variables as
// unaddressable when they leave scope and addressable before the
// function exits.
- void __asan_poison_stack_memory(uptr addr, uptr size)
- SANITIZER_INTERFACE_ATTRIBUTE;
- void __asan_unpoison_stack_memory(uptr addr, uptr size)
- SANITIZER_INTERFACE_ATTRIBUTE;
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void __asan_poison_stack_memory(uptr addr, uptr size);
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void __asan_unpoison_stack_memory(uptr addr, uptr size);
// Performs cleanup before a NoReturn function. Must be called before things
// like _exit and execl to avoid false positives on stack.
- void __asan_handle_no_return() SANITIZER_INTERFACE_ATTRIBUTE;
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_handle_no_return();
- void __asan_poison_memory_region(void const volatile *addr, uptr size)
- SANITIZER_INTERFACE_ATTRIBUTE;
- void __asan_unpoison_memory_region(void const volatile *addr, uptr size)
- SANITIZER_INTERFACE_ATTRIBUTE;
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void __asan_poison_memory_region(void const volatile *addr, uptr size);
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void __asan_unpoison_memory_region(void const volatile *addr, uptr size);
- bool __asan_address_is_poisoned(void const volatile *addr)
- SANITIZER_INTERFACE_ATTRIBUTE;
+ SANITIZER_INTERFACE_ATTRIBUTE
+ bool __asan_address_is_poisoned(void const volatile *addr);
- uptr __asan_region_is_poisoned(uptr beg, uptr size)
- SANITIZER_INTERFACE_ATTRIBUTE;
+ SANITIZER_INTERFACE_ATTRIBUTE
+ uptr __asan_region_is_poisoned(uptr beg, uptr size);
- void __asan_describe_address(uptr addr)
- SANITIZER_INTERFACE_ATTRIBUTE;
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void __asan_describe_address(uptr addr);
+ SANITIZER_INTERFACE_ATTRIBUTE
void __asan_report_error(uptr pc, uptr bp, uptr sp,
- uptr addr, bool is_write, uptr access_size)
- SANITIZER_INTERFACE_ATTRIBUTE;
+ uptr addr, bool is_write, uptr access_size);
- int __asan_set_error_exit_code(int exit_code)
- SANITIZER_INTERFACE_ATTRIBUTE;
- void __asan_set_death_callback(void (*callback)(void))
- SANITIZER_INTERFACE_ATTRIBUTE;
- void __asan_set_error_report_callback(void (*callback)(const char*))
- SANITIZER_INTERFACE_ATTRIBUTE;
+ SANITIZER_INTERFACE_ATTRIBUTE
+ int __asan_set_error_exit_code(int exit_code);
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void __asan_set_death_callback(void (*callback)(void));
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void __asan_set_error_report_callback(void (*callback)(const char*));
- /* OPTIONAL */ void __asan_on_error()
- SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+ SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
+ /* OPTIONAL */ void __asan_on_error();
+ SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
/* OPTIONAL */ bool __asan_symbolize(const void *pc, char *out_buffer,
- int out_size)
- SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
-
- uptr __asan_get_estimated_allocated_size(uptr size)
- SANITIZER_INTERFACE_ATTRIBUTE;
- bool __asan_get_ownership(const void *p)
- SANITIZER_INTERFACE_ATTRIBUTE;
- uptr __asan_get_allocated_size(const void *p)
- SANITIZER_INTERFACE_ATTRIBUTE;
- uptr __asan_get_current_allocated_bytes()
- SANITIZER_INTERFACE_ATTRIBUTE;
- uptr __asan_get_heap_size()
- SANITIZER_INTERFACE_ATTRIBUTE;
- uptr __asan_get_free_bytes()
- SANITIZER_INTERFACE_ATTRIBUTE;
- uptr __asan_get_unmapped_bytes()
- SANITIZER_INTERFACE_ATTRIBUTE;
- void __asan_print_accumulated_stats()
- SANITIZER_INTERFACE_ATTRIBUTE;
-
- /* OPTIONAL */ const char* __asan_default_options()
- SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
-
- /* OPTIONAL */ void __asan_malloc_hook(void *ptr, uptr size)
- SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
- /* OPTIONAL */ void __asan_free_hook(void *ptr)
- SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+ int out_size);
+
+ SANITIZER_INTERFACE_ATTRIBUTE
+ uptr __asan_get_estimated_allocated_size(uptr size);
+
+ SANITIZER_INTERFACE_ATTRIBUTE bool __asan_get_ownership(const void *p);
+ SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_get_allocated_size(const void *p);
+ SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_get_current_allocated_bytes();
+ SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_get_heap_size();
+ SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_get_free_bytes();
+ SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_get_unmapped_bytes();
+ SANITIZER_INTERFACE_ATTRIBUTE void __asan_print_accumulated_stats();
+
+ SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
+ /* OPTIONAL */ const char* __asan_default_options();
+
+ SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
+ /* OPTIONAL */ void __asan_malloc_hook(void *ptr, uptr size);
+ SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
+ /* OPTIONAL */ void __asan_free_hook(void *ptr);
+
+ // Global flag, copy of ASAN_OPTIONS=detect_stack_use_after_return
+ SANITIZER_INTERFACE_ATTRIBUTE
+ extern int __asan_option_detect_stack_use_after_return;
} // extern "C"
#endif // ASAN_INTERFACE_INTERNAL_H
diff --git a/libsanitizer/asan/asan_internal.h b/libsanitizer/asan/asan_internal.h
index 1ccbf108647..b5b48708090 100644
--- a/libsanitizer/asan/asan_internal.h
+++ b/libsanitizer/asan/asan_internal.h
@@ -19,39 +19,8 @@
#include "sanitizer_common/sanitizer_stacktrace.h"
#include "sanitizer_common/sanitizer_libc.h"
-#if !defined(__linux__) && !defined(__APPLE__) && !defined(_WIN32)
-# error "This operating system is not supported by AddressSanitizer"
-#endif
-
#define ASAN_DEFAULT_FAILURE_EXITCODE 1
-#if defined(__linux__)
-# define ASAN_LINUX 1
-#else
-# define ASAN_LINUX 0
-#endif
-
-#if defined(__APPLE__)
-# define ASAN_MAC 1
-#else
-# define ASAN_MAC 0
-#endif
-
-#if defined(_WIN32)
-# define ASAN_WINDOWS 1
-#else
-# define ASAN_WINDOWS 0
-#endif
-
-#if defined(__ANDROID__) || defined(ANDROID)
-# define ASAN_ANDROID 1
-#else
-# define ASAN_ANDROID 0
-#endif
-
-
-#define ASAN_POSIX (ASAN_LINUX || ASAN_MAC)
-
#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
# error "The AddressSanitizer run-time should not be"
" instrumented by AddressSanitizer"
@@ -61,7 +30,7 @@
// If set, asan will install its own SEGV signal handler.
#ifndef ASAN_NEEDS_SEGV
-# if ASAN_ANDROID == 1
+# if SANITIZER_ANDROID == 1
# define ASAN_NEEDS_SEGV 0
# else
# define ASAN_NEEDS_SEGV 1
@@ -90,7 +59,7 @@
#endif
#ifndef ASAN_USE_PREINIT_ARRAY
-# define ASAN_USE_PREINIT_ARRAY (ASAN_LINUX && !ASAN_ANDROID)
+# define ASAN_USE_PREINIT_ARRAY (SANITIZER_LINUX && !SANITIZER_ANDROID)
#endif
// All internal functions in asan reside inside the __asan namespace
@@ -121,6 +90,7 @@ void UnsetAlternateSignalStack();
void InstallSignalHandlers();
void ReadContextStack(void *context, uptr *stack, uptr *ssize);
void AsanPlatformThreadInit();
+void StopInitOrderChecking();
// Wrapper for TLS/TSD.
void AsanTSDInit(void (*destructor)(void *tsd));
@@ -129,24 +99,14 @@ void AsanTSDSet(void *tsd);
void AppendToErrorMessageBuffer(const char *buffer);
-// asan_poisoning.cc
-// Poisons the shadow memory for "size" bytes starting from "addr".
-void PoisonShadow(uptr addr, uptr size, u8 value);
-// Poisons the shadow memory for "redzone_size" bytes starting from
-// "addr + size".
-void PoisonShadowPartialRightRedzone(uptr addr,
- uptr size,
- uptr redzone_size,
- u8 value);
-
// Platfrom-specific options.
-#ifdef __APPLE__
+#if SANITIZER_MAC
bool PlatformHasDifferentMemcpyAndMemmove();
# define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE \
(PlatformHasDifferentMemcpyAndMemmove())
#else
# define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE true
-#endif // __APPLE__
+#endif // SANITIZER_MAC
// Add convenient macro for interface functions that may be represented as
// weak hooks.
diff --git a/libsanitizer/asan/asan_linux.cc b/libsanitizer/asan/asan_linux.cc
index a030fcd3972..10c6175092b 100644
--- a/libsanitizer/asan/asan_linux.cc
+++ b/libsanitizer/asan/asan_linux.cc
@@ -9,12 +9,13 @@
//
// Linux-specific details.
//===----------------------------------------------------------------------===//
-#ifdef __linux__
+
+#include "sanitizer_common/sanitizer_platform.h"
+#if SANITIZER_LINUX
#include "asan_interceptors.h"
#include "asan_internal.h"
#include "asan_thread.h"
-#include "asan_thread_registry.h"
#include "sanitizer_common/sanitizer_libc.h"
#include "sanitizer_common/sanitizer_procmaps.h"
@@ -29,7 +30,7 @@
#include <unistd.h>
#include <unwind.h>
-#if !ASAN_ANDROID
+#if !SANITIZER_ANDROID
// FIXME: where to get ucontext on Android?
#include <sys/ucontext.h>
#endif
@@ -48,7 +49,7 @@ void *AsanDoesNotSupportStaticLinkage() {
}
void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
-#if ASAN_ANDROID
+#if SANITIZER_ANDROID
*pc = *sp = *bp = 0;
#elif defined(__arm__)
ucontext_t *ucontext = (ucontext_t*)context;
@@ -86,6 +87,11 @@ void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
stk_ptr = (uptr *) *sp;
*bp = stk_ptr[15];
# endif
+# elif defined(__mips__)
+ ucontext_t *ucontext = (ucontext_t*)context;
+ *pc = ucontext->uc_mcontext.gregs[31];
+ *bp = ucontext->uc_mcontext.gregs[30];
+ *sp = ucontext->uc_mcontext.gregs[29];
#else
# error "Unsupported arch"
#endif
@@ -99,25 +105,7 @@ void AsanPlatformThreadInit() {
// Nothing here for now.
}
-void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp, bool fast) {
-#if defined(__arm__) || \
- defined(__powerpc__) || defined(__powerpc64__) || \
- defined(__sparc__)
- fast = false;
-#endif
- if (!fast)
- return stack->SlowUnwindStack(pc, max_s);
- stack->size = 0;
- stack->trace[0] = pc;
- if (max_s > 1) {
- stack->max_size = max_s;
- if (!asan_inited) return;
- if (AsanThread *t = asanThreadRegistry().GetCurrent())
- stack->FastUnwindStack(pc, bp, t->stack_top(), t->stack_bottom());
- }
-}
-
-#if !ASAN_ANDROID
+#if !SANITIZER_ANDROID
void ReadContextStack(void *context, uptr *stack, uptr *ssize) {
ucontext_t *ucp = (ucontext_t*)context;
*stack = (uptr)ucp->uc_stack.ss_sp;
@@ -131,4 +119,4 @@ void ReadContextStack(void *context, uptr *stack, uptr *ssize) {
} // namespace __asan
-#endif // __linux__
+#endif // SANITIZER_LINUX
diff --git a/libsanitizer/asan/asan_mac.cc b/libsanitizer/asan/asan_mac.cc
index dd2657df1e2..4b28c1422cd 100644
--- a/libsanitizer/asan/asan_mac.cc
+++ b/libsanitizer/asan/asan_mac.cc
@@ -10,7 +10,8 @@
// Mac-specific details.
//===----------------------------------------------------------------------===//
-#ifdef __APPLE__
+#include "sanitizer_common/sanitizer_platform.h"
+#if SANITIZER_MAC
#include "asan_interceptors.h"
#include "asan_internal.h"
@@ -18,7 +19,7 @@
#include "asan_mapping.h"
#include "asan_stack.h"
#include "asan_thread.h"
-#include "asan_thread_registry.h"
+#include "sanitizer_common/sanitizer_atomic.h"
#include "sanitizer_common/sanitizer_libc.h"
#include <crt_externs.h> // for _NSGetArgv
@@ -50,15 +51,17 @@ void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
# endif // SANITIZER_WORDSIZE
}
-int GetMacosVersion() {
+MacosVersion cached_macos_version = MACOS_VERSION_UNINITIALIZED;
+
+MacosVersion GetMacosVersionInternal() {
int mib[2] = { CTL_KERN, KERN_OSRELEASE };
char version[100];
uptr len = 0, maxlen = sizeof(version) / sizeof(version[0]);
for (uptr i = 0; i < maxlen; i++) version[i] = '\0';
// Get the version length.
- CHECK(sysctl(mib, 2, 0, &len, 0, 0) != -1);
- CHECK(len < maxlen);
- CHECK(sysctl(mib, 2, version, &len, 0, 0) != -1);
+ CHECK_NE(sysctl(mib, 2, 0, &len, 0, 0), -1);
+ CHECK_LT(len, maxlen);
+ CHECK_NE(sysctl(mib, 2, version, &len, 0, 0), -1);
switch (version[0]) {
case '9': return MACOS_VERSION_LEOPARD;
case '1': {
@@ -66,6 +69,7 @@ int GetMacosVersion() {
case '0': return MACOS_VERSION_SNOW_LEOPARD;
case '1': return MACOS_VERSION_LION;
case '2': return MACOS_VERSION_MOUNTAIN_LION;
+ case '3': return MACOS_VERSION_MAVERICKS;
default: return MACOS_VERSION_UNKNOWN;
}
}
@@ -73,6 +77,18 @@ int GetMacosVersion() {
}
}
+MacosVersion GetMacosVersion() {
+ atomic_uint32_t *cache =
+ reinterpret_cast<atomic_uint32_t*>(&cached_macos_version);
+ MacosVersion result =
+ static_cast<MacosVersion>(atomic_load(cache, memory_order_acquire));
+ if (result == MACOS_VERSION_UNINITIALIZED) {
+ result = GetMacosVersionInternal();
+ atomic_store(cache, result, memory_order_release);
+ }
+ return result;
+}
+
bool PlatformHasDifferentMemcpyAndMemmove() {
// On OS X 10.7 memcpy() and memmove() are both resolved
// into memmove$VARIANT$sse42.
@@ -227,18 +243,6 @@ bool AsanInterceptsSignal(int signum) {
void AsanPlatformThreadInit() {
}
-void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp, bool fast) {
- (void)fast;
- stack->size = 0;
- stack->trace[0] = pc;
- if ((max_s) > 1) {
- stack->max_size = max_s;
- if (!asan_inited) return;
- if (AsanThread *t = asanThreadRegistry().GetCurrent())
- stack->FastUnwindStack(pc, bp, t->stack_top(), t->stack_bottom());
- }
-}
-
void ReadContextStack(void *context, uptr *stack, uptr *ssize) {
UNIMPLEMENTED();
}
@@ -286,32 +290,16 @@ typedef struct {
u32 parent_tid;
} asan_block_context_t;
-// We use extern declarations of libdispatch functions here instead
-// of including <dispatch/dispatch.h>. This header is not present on
-// Mac OS X Leopard and eariler, and although we don't expect ASan to
-// work on legacy systems, it's bad to break the build of
-// LLVM compiler-rt there.
-extern "C" {
-void dispatch_async_f(dispatch_queue_t dq, void *ctxt,
- dispatch_function_t func);
-void dispatch_sync_f(dispatch_queue_t dq, void *ctxt,
- dispatch_function_t func);
-void dispatch_after_f(dispatch_time_t when, dispatch_queue_t dq, void *ctxt,
- dispatch_function_t func);
-void dispatch_barrier_async_f(dispatch_queue_t dq, void *ctxt,
- dispatch_function_t func);
-void dispatch_group_async_f(dispatch_group_t group, dispatch_queue_t dq,
- void *ctxt, dispatch_function_t func);
-} // extern "C"
-
-static ALWAYS_INLINE
+ALWAYS_INLINE
void asan_register_worker_thread(int parent_tid, StackTrace *stack) {
- AsanThread *t = asanThreadRegistry().GetCurrent();
+ AsanThread *t = GetCurrentThread();
if (!t) {
- t = AsanThread::Create(parent_tid, 0, 0, stack);
- asanThreadRegistry().RegisterThread(t);
+ t = AsanThread::Create(0, 0);
+ CreateThreadContextArgs args = { t, stack };
+ asanThreadRegistry().CreateThread(*(uptr*)t, true, parent_tid, &args);
t->Init();
- asanThreadRegistry().SetCurrent(t);
+ asanThreadRegistry().StartThread(t->tid(), 0, 0);
+ SetCurrentThread(t);
}
}
@@ -345,7 +333,7 @@ asan_block_context_t *alloc_asan_context(void *ctxt, dispatch_function_t func,
(asan_block_context_t*) asan_malloc(sizeof(asan_block_context_t), stack);
asan_ctxt->block = ctxt;
asan_ctxt->func = func;
- asan_ctxt->parent_tid = asanThreadRegistry().GetCurrentTidOrInvalid();
+ asan_ctxt->parent_tid = GetCurrentTidOrInvalid();
return asan_ctxt;
}
@@ -411,7 +399,7 @@ void dispatch_source_set_event_handler(dispatch_source_t ds, void(^work)(void));
#define GET_ASAN_BLOCK(work) \
void (^asan_block)(void); \
- int parent_tid = asanThreadRegistry().GetCurrentTidOrInvalid(); \
+ int parent_tid = GetCurrentTidOrInvalid(); \
asan_block = ^(void) { \
GET_STACK_TRACE_THREAD; \
asan_register_worker_thread(parent_tid, &stack); \
@@ -449,4 +437,4 @@ INTERCEPTOR(void, dispatch_source_set_event_handler,
}
#endif
-#endif // __APPLE__
+#endif // SANITIZER_MAC
diff --git a/libsanitizer/asan/asan_mac.h b/libsanitizer/asan/asan_mac.h
index 2c162fb0c39..2d1d4b0bfb3 100644
--- a/libsanitizer/asan/asan_mac.h
+++ b/libsanitizer/asan/asan_mac.h
@@ -34,12 +34,14 @@ typedef struct __CFRuntimeBase {
#endif
} CFRuntimeBase;
-enum {
- MACOS_VERSION_UNKNOWN = 0,
+enum MacosVersion {
+ MACOS_VERSION_UNINITIALIZED = 0,
+ MACOS_VERSION_UNKNOWN,
MACOS_VERSION_LEOPARD,
MACOS_VERSION_SNOW_LEOPARD,
MACOS_VERSION_LION,
- MACOS_VERSION_MOUNTAIN_LION
+ MACOS_VERSION_MOUNTAIN_LION,
+ MACOS_VERSION_MAVERICKS
};
// Used by asan_malloc_mac.cc and asan_mac.cc
@@ -47,7 +49,7 @@ extern "C" void __CFInitialize();
namespace __asan {
-int GetMacosVersion();
+MacosVersion GetMacosVersion();
void MaybeReplaceCFAllocator();
} // namespace __asan
diff --git a/libsanitizer/asan/asan_malloc_linux.cc b/libsanitizer/asan/asan_malloc_linux.cc
index 18e6a3be865..97691fcd361 100644
--- a/libsanitizer/asan/asan_malloc_linux.cc
+++ b/libsanitizer/asan/asan_malloc_linux.cc
@@ -11,15 +11,16 @@
// We simply define functions like malloc, free, realloc, etc.
// They will replace the corresponding libc functions automagically.
//===----------------------------------------------------------------------===//
-#ifdef __linux__
+
+#include "sanitizer_common/sanitizer_platform.h"
+#if SANITIZER_LINUX
#include "asan_allocator.h"
#include "asan_interceptors.h"
#include "asan_internal.h"
#include "asan_stack.h"
-#include "asan_thread_registry.h"
-#if ASAN_ANDROID
+#if SANITIZER_ANDROID
DECLARE_REAL_AND_INTERCEPTOR(void*, malloc, uptr size)
DECLARE_REAL_AND_INTERCEPTOR(void, free, void *ptr)
DECLARE_REAL_AND_INTERCEPTOR(void*, calloc, uptr nmemb, uptr size)
@@ -144,4 +145,4 @@ INTERCEPTOR(void, malloc_stats, void) {
__asan_print_accumulated_stats();
}
-#endif // __linux__
+#endif // SANITIZER_LINUX
diff --git a/libsanitizer/asan/asan_malloc_mac.cc b/libsanitizer/asan/asan_malloc_mac.cc
index 3ae6c594650..342e806e3b6 100644
--- a/libsanitizer/asan/asan_malloc_mac.cc
+++ b/libsanitizer/asan/asan_malloc_mac.cc
@@ -10,12 +10,14 @@
// Mac-specific malloc interception.
//===----------------------------------------------------------------------===//
-#ifdef __APPLE__
+#include "sanitizer_common/sanitizer_platform.h"
+#if SANITIZER_MAC
#include <AvailabilityMacros.h>
#include <CoreFoundation/CFBase.h>
#include <dlfcn.h>
#include <malloc/malloc.h>
+#include <sys/mman.h>
#include "asan_allocator.h"
#include "asan_interceptors.h"
@@ -24,7 +26,6 @@
#include "asan_report.h"
#include "asan_stack.h"
#include "asan_stats.h"
-#include "asan_thread_registry.h"
// Similar code is used in Google Perftools,
// http://code.google.com/p/google-perftools.
@@ -40,10 +41,19 @@ INTERCEPTOR(malloc_zone_t *, malloc_create_zone,
vm_size_t start_size, unsigned zone_flags) {
if (!asan_inited) __asan_init();
GET_STACK_TRACE_MALLOC;
+ uptr page_size = GetPageSizeCached();
+ uptr allocated_size = RoundUpTo(sizeof(asan_zone), page_size);
malloc_zone_t *new_zone =
- (malloc_zone_t*)asan_malloc(sizeof(asan_zone), &stack);
+ (malloc_zone_t*)asan_memalign(page_size, allocated_size,
+ &stack, FROM_MALLOC);
internal_memcpy(new_zone, &asan_zone, sizeof(asan_zone));
new_zone->zone_name = NULL; // The name will be changed anyway.
+ if (GetMacosVersion() >= MACOS_VERSION_LION) {
+ // Prevent the client app from overwriting the zone contents.
+ // Library functions that need to modify the zone will set PROT_WRITE on it.
+ // This matches the behavior of malloc_create_zone() on OSX 10.7 and higher.
+ mprotect(new_zone, allocated_size, PROT_READ);
+ }
return new_zone;
}
@@ -282,7 +292,7 @@ void mi_force_unlock(malloc_zone_t *zone) {
void mi_statistics(malloc_zone_t *zone, malloc_statistics_t *stats) {
AsanMallocStats malloc_stats;
- asanThreadRegistry().FillMallocStatistics(&malloc_stats);
+ FillMallocStatistics(&malloc_stats);
CHECK(sizeof(malloc_statistics_t) == sizeof(AsanMallocStats));
internal_memcpy(stats, &malloc_stats, sizeof(malloc_statistics_t));
}
@@ -344,4 +354,4 @@ void ReplaceSystemMalloc() {
}
} // namespace __asan
-#endif // __APPLE__
+#endif // SANITIZER_MAC
diff --git a/libsanitizer/asan/asan_malloc_win.cc b/libsanitizer/asan/asan_malloc_win.cc
index 437079f5d1d..cabf8cd254c 100644
--- a/libsanitizer/asan/asan_malloc_win.cc
+++ b/libsanitizer/asan/asan_malloc_win.cc
@@ -9,7 +9,9 @@
//
// Windows-specific malloc interception.
//===----------------------------------------------------------------------===//
-#ifdef _WIN32
+
+#include "sanitizer_common/sanitizer_platform.h"
+#if SANITIZER_WINDOWS
#include "asan_allocator.h"
#include "asan_interceptors.h"
@@ -28,11 +30,13 @@ using namespace __asan; // NOLINT
// revisited in the future.
extern "C" {
+SANITIZER_INTERFACE_ATTRIBUTE
void free(void *ptr) {
GET_STACK_TRACE_FREE;
return asan_free(ptr, &stack, FROM_MALLOC);
}
+SANITIZER_INTERFACE_ATTRIBUTE
void _free_dbg(void* ptr, int) {
free(ptr);
}
@@ -41,38 +45,46 @@ void cfree(void *ptr) {
CHECK(!"cfree() should not be used on Windows?");
}
+SANITIZER_INTERFACE_ATTRIBUTE
void *malloc(size_t size) {
GET_STACK_TRACE_MALLOC;
return asan_malloc(size, &stack);
}
+SANITIZER_INTERFACE_ATTRIBUTE
void* _malloc_dbg(size_t size, int , const char*, int) {
return malloc(size);
}
+SANITIZER_INTERFACE_ATTRIBUTE
void *calloc(size_t nmemb, size_t size) {
GET_STACK_TRACE_MALLOC;
return asan_calloc(nmemb, size, &stack);
}
+SANITIZER_INTERFACE_ATTRIBUTE
void* _calloc_dbg(size_t n, size_t size, int, const char*, int) {
return calloc(n, size);
}
+SANITIZER_INTERFACE_ATTRIBUTE
void *_calloc_impl(size_t nmemb, size_t size, int *errno_tmp) {
return calloc(nmemb, size);
}
+SANITIZER_INTERFACE_ATTRIBUTE
void *realloc(void *ptr, size_t size) {
GET_STACK_TRACE_MALLOC;
return asan_realloc(ptr, size, &stack);
}
+SANITIZER_INTERFACE_ATTRIBUTE
void *_realloc_dbg(void *ptr, size_t size, int) {
CHECK(!"_realloc_dbg should not exist!");
return 0;
}
+SANITIZER_INTERFACE_ATTRIBUTE
void* _recalloc(void* p, size_t n, size_t elem_size) {
if (!p)
return calloc(n, elem_size);
@@ -82,6 +94,7 @@ void* _recalloc(void* p, size_t n, size_t elem_size) {
return realloc(p, size);
}
+SANITIZER_INTERFACE_ATTRIBUTE
size_t _msize(void *ptr) {
GET_STACK_TRACE_MALLOC;
return asan_malloc_usable_size(ptr, &stack);
diff --git a/libsanitizer/asan/asan_mapping.h b/libsanitizer/asan/asan_mapping.h
index 9b4dd35f1eb..fd5c2039bca 100644
--- a/libsanitizer/asan/asan_mapping.h
+++ b/libsanitizer/asan/asan_mapping.h
@@ -47,6 +47,20 @@
// || `[0x24000000, 0x27ffffff]` || ShadowGap ||
// || `[0x20000000, 0x23ffffff]` || LowShadow ||
// || `[0x00000000, 0x1fffffff]` || LowMem ||
+//
+// Default Linux/MIPS mapping:
+// || `[0x2aaa8000, 0xffffffff]` || HighMem ||
+// || `[0x0fffd000, 0x2aaa7fff]` || HighShadow ||
+// || `[0x0bffd000, 0x0fffcfff]` || ShadowGap ||
+// || `[0x0aaa8000, 0x0bffcfff]` || LowShadow ||
+// || `[0x00000000, 0x0aaa7fff]` || LowMem ||
+
+static const u64 kDefaultShadowScale = 3;
+static const u64 kDefaultShadowOffset32 = 1ULL << 29;
+static const u64 kDefaultShadowOffset64 = 1ULL << 44;
+static const u64 kDefaultShort64bitShadowOffset = 0x7FFF8000; // < 2G.
+static const u64 kPPC64_ShadowOffset64 = 1ULL << 41;
+static const u64 kMIPS32_ShadowOffset32 = 0x0aaa8000;
#if ASAN_FLEXIBLE_MAPPING_AND_OFFSET == 1
extern SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_mapping_scale;
@@ -54,22 +68,23 @@ extern SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_mapping_offset;
# define SHADOW_SCALE (__asan_mapping_scale)
# define SHADOW_OFFSET (__asan_mapping_offset)
#else
-# if ASAN_ANDROID
-# define SHADOW_SCALE (3)
+# define SHADOW_SCALE kDefaultShadowScale
+# if SANITIZER_ANDROID
# define SHADOW_OFFSET (0)
# else
-# define SHADOW_SCALE (3)
# if SANITIZER_WORDSIZE == 32
-# define SHADOW_OFFSET (1 << 29)
+# if defined(__mips__)
+# define SHADOW_OFFSET kMIPS32_ShadowOffset32
+# else
+# define SHADOW_OFFSET kDefaultShadowOffset32
+# endif
# else
# if defined(__powerpc64__)
-# define SHADOW_OFFSET (1ULL << 41)
+# define SHADOW_OFFSET kPPC64_ShadowOffset64
+# elif SANITIZER_MAC
+# define SHADOW_OFFSET kDefaultShadowOffset64
# else
-# if ASAN_MAC
-# define SHADOW_OFFSET (1ULL << 44)
-# else
-# define SHADOW_OFFSET 0x7fff8000ULL
-# endif
+# define SHADOW_OFFSET kDefaultShort64bitShadowOffset
# endif
# endif
# endif
@@ -131,7 +146,6 @@ static uptr kHighMemEnd = 0x7fffffffffffULL;
static uptr kMidMemBeg = 0x3000000000ULL;
static uptr kMidMemEnd = 0x4fffffffffULL;
#else
-SANITIZER_INTERFACE_ATTRIBUTE
extern uptr kHighMemEnd, kMidMemBeg, kMidMemEnd; // Initialized in __asan_init.
#endif
diff --git a/libsanitizer/asan/asan_new_delete.cc b/libsanitizer/asan/asan_new_delete.cc
index fd47eee4205..beac8cdbdd5 100644
--- a/libsanitizer/asan/asan_new_delete.cc
+++ b/libsanitizer/asan/asan_new_delete.cc
@@ -27,7 +27,7 @@ using namespace __asan; // NOLINT
// On Android new() goes through malloc interceptors.
// See also https://code.google.com/p/address-sanitizer/issues/detail?id=131.
-#if !ASAN_ANDROID
+#if !SANITIZER_ANDROID
// Fake std::nothrow_t to avoid including <new>.
namespace std {
@@ -38,6 +38,14 @@ struct nothrow_t {};
GET_STACK_TRACE_MALLOC;\
return asan_memalign(0, size, &stack, type);
+// On OS X it's not enough to just provide our own 'operator new' and
+// 'operator delete' implementations, because they're going to be in the
+// runtime dylib, and the main executable will depend on both the runtime
+// dylib and libstdc++, each of those'll have its implementation of new and
+// delete.
+// To make sure that C++ allocation/deallocation operators are overridden on
+// OS X we need to intercept them using their mangled names.
+#if !SANITIZER_MAC
INTERCEPTOR_ATTRIBUTE
void *operator new(size_t size) { OPERATOR_NEW_BODY(FROM_NEW); }
INTERCEPTOR_ATTRIBUTE
@@ -49,10 +57,26 @@ INTERCEPTOR_ATTRIBUTE
void *operator new[](size_t size, std::nothrow_t const&)
{ OPERATOR_NEW_BODY(FROM_NEW_BR); }
+#else // SANITIZER_MAC
+INTERCEPTOR(void *, _Znwm, size_t size) {
+ OPERATOR_NEW_BODY(FROM_NEW);
+}
+INTERCEPTOR(void *, _Znam, size_t size) {
+ OPERATOR_NEW_BODY(FROM_NEW_BR);
+}
+INTERCEPTOR(void *, _ZnwmRKSt9nothrow_t, size_t size, std::nothrow_t const&) {
+ OPERATOR_NEW_BODY(FROM_NEW);
+}
+INTERCEPTOR(void *, _ZnamRKSt9nothrow_t, size_t size, std::nothrow_t const&) {
+ OPERATOR_NEW_BODY(FROM_NEW_BR);
+}
+#endif
+
#define OPERATOR_DELETE_BODY(type) \
GET_STACK_TRACE_FREE;\
asan_free(ptr, &stack, type);
+#if !SANITIZER_MAC
INTERCEPTOR_ATTRIBUTE
void operator delete(void *ptr) { OPERATOR_DELETE_BODY(FROM_NEW); }
INTERCEPTOR_ATTRIBUTE
@@ -64,4 +88,19 @@ INTERCEPTOR_ATTRIBUTE
void operator delete[](void *ptr, std::nothrow_t const&)
{ OPERATOR_DELETE_BODY(FROM_NEW_BR); }
+#else // SANITIZER_MAC
+INTERCEPTOR(void, _ZdlPv, void *ptr) {
+ OPERATOR_DELETE_BODY(FROM_NEW);
+}
+INTERCEPTOR(void, _ZdaPv, void *ptr) {
+ OPERATOR_DELETE_BODY(FROM_NEW_BR);
+}
+INTERCEPTOR(void, _ZdlPvRKSt9nothrow_t, void *ptr, std::nothrow_t const&) {
+ OPERATOR_DELETE_BODY(FROM_NEW);
+}
+INTERCEPTOR(void, _ZdaPvRKSt9nothrow_t, void *ptr, std::nothrow_t const&) {
+ OPERATOR_DELETE_BODY(FROM_NEW_BR);
+}
+#endif
+
#endif
diff --git a/libsanitizer/asan/asan_poisoning.cc b/libsanitizer/asan/asan_poisoning.cc
index 7e930034bef..b967acded63 100644
--- a/libsanitizer/asan/asan_poisoning.cc
+++ b/libsanitizer/asan/asan_poisoning.cc
@@ -10,9 +10,7 @@
// Shadow memory poisoning by ASan RTL and by user application.
//===----------------------------------------------------------------------===//
-#include "asan_interceptors.h"
-#include "asan_internal.h"
-#include "asan_mapping.h"
+#include "asan_poisoning.h"
#include "sanitizer_common/sanitizer_libc.h"
namespace __asan {
@@ -20,11 +18,11 @@ namespace __asan {
void PoisonShadow(uptr addr, uptr size, u8 value) {
if (!flags()->poison_heap) return;
CHECK(AddrIsAlignedByGranularity(addr));
+ CHECK(AddrIsInMem(addr));
CHECK(AddrIsAlignedByGranularity(addr + size));
- uptr shadow_beg = MemToShadow(addr);
- uptr shadow_end = MemToShadow(addr + size - SHADOW_GRANULARITY) + 1;
- CHECK(REAL(memset) != 0);
- REAL(memset)((void*)shadow_beg, value, shadow_end - shadow_beg);
+ CHECK(AddrIsInMem(addr + size - SHADOW_GRANULARITY));
+ CHECK(REAL(memset));
+ FastPoisonShadow(addr, size, value);
}
void PoisonShadowPartialRightRedzone(uptr addr,
@@ -33,20 +31,10 @@ void PoisonShadowPartialRightRedzone(uptr addr,
u8 value) {
if (!flags()->poison_heap) return;
CHECK(AddrIsAlignedByGranularity(addr));
- u8 *shadow = (u8*)MemToShadow(addr);
- for (uptr i = 0; i < redzone_size;
- i += SHADOW_GRANULARITY, shadow++) {
- if (i + SHADOW_GRANULARITY <= size) {
- *shadow = 0; // fully addressable
- } else if (i >= size) {
- *shadow = (SHADOW_GRANULARITY == 128) ? 0xff : value; // unaddressable
- } else {
- *shadow = size - i; // first size-i bytes are addressable
- }
- }
+ CHECK(AddrIsInMem(addr));
+ FastPoisonShadowPartialRightRedzone(addr, size, redzone_size, value);
}
-
struct ShadowSegmentEndpoint {
u8 *chunk;
s8 offset; // in [0, SHADOW_GRANULARITY)
@@ -179,6 +167,55 @@ uptr __asan_region_is_poisoned(uptr beg, uptr size) {
return 0;
}
+#define CHECK_SMALL_REGION(p, size, isWrite) \
+ do { \
+ uptr __p = reinterpret_cast<uptr>(p); \
+ uptr __size = size; \
+ if (UNLIKELY(__asan::AddressIsPoisoned(__p) || \
+ __asan::AddressIsPoisoned(__p + __size - 1))) { \
+ GET_CURRENT_PC_BP_SP; \
+ uptr __bad = __asan_region_is_poisoned(__p, __size); \
+ __asan_report_error(pc, bp, sp, __bad, isWrite, __size);\
+ } \
+ } while (false); \
+
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE
+u16 __sanitizer_unaligned_load16(const uu16 *p) {
+ CHECK_SMALL_REGION(p, sizeof(*p), false);
+ return *p;
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE
+u32 __sanitizer_unaligned_load32(const uu32 *p) {
+ CHECK_SMALL_REGION(p, sizeof(*p), false);
+ return *p;
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE
+u64 __sanitizer_unaligned_load64(const uu64 *p) {
+ CHECK_SMALL_REGION(p, sizeof(*p), false);
+ return *p;
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_unaligned_store16(uu16 *p, u16 x) {
+ CHECK_SMALL_REGION(p, sizeof(*p), true);
+ *p = x;
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_unaligned_store32(uu32 *p, u32 x) {
+ CHECK_SMALL_REGION(p, sizeof(*p), true);
+ *p = x;
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_unaligned_store64(uu64 *p, u64 x) {
+ CHECK_SMALL_REGION(p, sizeof(*p), true);
+ *p = x;
+}
+
// This is a simplified version of __asan_(un)poison_memory_region, which
// assumes that left border of region to be poisoned is properly aligned.
static void PoisonAlignedStackMemory(uptr addr, uptr size, bool do_poison) {
diff --git a/libsanitizer/asan/asan_poisoning.h b/libsanitizer/asan/asan_poisoning.h
new file mode 100644
index 00000000000..866c0a57c7e
--- /dev/null
+++ b/libsanitizer/asan/asan_poisoning.h
@@ -0,0 +1,57 @@
+//===-- asan_poisoning.h ----------------------------------------*- C++ -*-===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Shadow memory poisoning by ASan RTL and by user application.
+//===----------------------------------------------------------------------===//
+
+#include "asan_interceptors.h"
+#include "asan_internal.h"
+#include "asan_mapping.h"
+
+namespace __asan {
+
+// Poisons the shadow memory for "size" bytes starting from "addr".
+void PoisonShadow(uptr addr, uptr size, u8 value);
+
+// Poisons the shadow memory for "redzone_size" bytes starting from
+// "addr + size".
+void PoisonShadowPartialRightRedzone(uptr addr,
+ uptr size,
+ uptr redzone_size,
+ u8 value);
+
+// Fast versions of PoisonShadow and PoisonShadowPartialRightRedzone that
+// assume that memory addresses are properly aligned. Use in
+// performance-critical code with care.
+ALWAYS_INLINE void FastPoisonShadow(uptr aligned_beg, uptr aligned_size,
+ u8 value) {
+ DCHECK(flags()->poison_heap);
+ uptr shadow_beg = MEM_TO_SHADOW(aligned_beg);
+ uptr shadow_end = MEM_TO_SHADOW(
+ aligned_beg + aligned_size - SHADOW_GRANULARITY) + 1;
+ REAL(memset)((void*)shadow_beg, value, shadow_end - shadow_beg);
+}
+
+ALWAYS_INLINE void FastPoisonShadowPartialRightRedzone(
+ uptr aligned_addr, uptr size, uptr redzone_size, u8 value) {
+ DCHECK(flags()->poison_heap);
+ u8 *shadow = (u8*)MEM_TO_SHADOW(aligned_addr);
+ for (uptr i = 0; i < redzone_size; i += SHADOW_GRANULARITY, shadow++) {
+ if (i + SHADOW_GRANULARITY <= size) {
+ *shadow = 0; // fully addressable
+ } else if (i >= size) {
+ *shadow = (SHADOW_GRANULARITY == 128) ? 0xff : value; // unaddressable
+ } else {
+ // first size-i bytes are addressable
+ *shadow = static_cast<u8>(size - i);
+ }
+ }
+}
+
+} // namespace __asan
diff --git a/libsanitizer/asan/asan_posix.cc b/libsanitizer/asan/asan_posix.cc
index 177b84ae67f..a210a810036 100644
--- a/libsanitizer/asan/asan_posix.cc
+++ b/libsanitizer/asan/asan_posix.cc
@@ -9,14 +9,15 @@
//
// Posix-specific details.
//===----------------------------------------------------------------------===//
-#if defined(__linux__) || defined(__APPLE__)
+
+#include "sanitizer_common/sanitizer_platform.h"
+#if SANITIZER_LINUX || SANITIZER_MAC
#include "asan_internal.h"
#include "asan_interceptors.h"
#include "asan_mapping.h"
#include "asan_report.h"
#include "asan_stack.h"
-#include "asan_thread_registry.h"
#include "sanitizer_common/sanitizer_libc.h"
#include "sanitizer_common/sanitizer_procmaps.h"
@@ -40,7 +41,7 @@ static void MaybeInstallSigaction(int signum,
sigact.sa_sigaction = handler;
sigact.sa_flags = SA_SIGINFO;
if (flags()->use_sigaltstack) sigact.sa_flags |= SA_ONSTACK;
- CHECK(0 == REAL(sigaction)(signum, &sigact, 0));
+ CHECK_EQ(0, REAL(sigaction)(signum, &sigact, 0));
if (flags()->verbosity >= 1) {
Report("Installed the sigaction for signal %d\n", signum);
}
@@ -57,7 +58,7 @@ static void ASAN_OnSIGSEGV(int, siginfo_t *siginfo, void *context) {
void SetAlternateSignalStack() {
stack_t altstack, oldstack;
- CHECK(0 == sigaltstack(0, &oldstack));
+ CHECK_EQ(0, sigaltstack(0, &oldstack));
// If the alternate stack is already in place, do nothing.
if ((oldstack.ss_flags & SS_DISABLE) == 0) return;
// TODO(glider): the mapped stack should have the MAP_STACK flag in the
@@ -67,10 +68,10 @@ void SetAlternateSignalStack() {
altstack.ss_sp = base;
altstack.ss_flags = 0;
altstack.ss_size = kAltStackSize;
- CHECK(0 == sigaltstack(&altstack, 0));
+ CHECK_EQ(0, sigaltstack(&altstack, 0));
if (flags()->verbosity > 0) {
Report("Alternative stack for T%d set: [%p,%p)\n",
- asanThreadRegistry().GetCurrentTidOrInvalid(),
+ GetCurrentTidOrInvalid(),
altstack.ss_sp, (char*)altstack.ss_sp + altstack.ss_size);
}
}
@@ -80,7 +81,7 @@ void UnsetAlternateSignalStack() {
altstack.ss_sp = 0;
altstack.ss_flags = SS_DISABLE;
altstack.ss_size = 0;
- CHECK(0 == sigaltstack(&altstack, &oldstack));
+ CHECK_EQ(0, sigaltstack(&altstack, &oldstack));
UnmapOrDie(oldstack.ss_sp, oldstack.ss_size);
}
@@ -100,7 +101,7 @@ static bool tsd_key_inited = false;
void AsanTSDInit(void (*destructor)(void *tsd)) {
CHECK(!tsd_key_inited);
tsd_key_inited = true;
- CHECK(0 == pthread_key_create(&tsd_key, destructor));
+ CHECK_EQ(0, pthread_key_create(&tsd_key, destructor));
}
void *AsanTSDGet() {
@@ -115,4 +116,4 @@ void AsanTSDSet(void *tsd) {
} // namespace __asan
-#endif // __linux__ || __APPLE_
+#endif // SANITIZER_LINUX || SANITIZER_MAC
diff --git a/libsanitizer/asan/asan_preinit.cc b/libsanitizer/asan/asan_preinit.cc
index 40309fa389d..31042401536 100644
--- a/libsanitizer/asan/asan_preinit.cc
+++ b/libsanitizer/asan/asan_preinit.cc
@@ -16,9 +16,11 @@
// On Linux, we force __asan_init to be called before anyone else
// by placing it into .preinit_array section.
// FIXME: do we have anything like this on Mac?
+ // The symbol is called __local_asan_preinit, because it's not intended to be
+ // exported.
__attribute__((section(".preinit_array"), used))
- void (*__asan_preinit)(void) =__asan_init;
-#elif defined(_WIN32) && defined(_DLL)
+ void (*__local_asan_preinit)(void) = __asan_init;
+#elif SANITIZER_WINDOWS && defined(_DLL)
// On Windows, when using dynamic CRT (/MD), we can put a pointer
// to __asan_init into the global list of C initializers.
// See crt0dat.c in the CRT sources for the details.
diff --git a/libsanitizer/asan/asan_report.cc b/libsanitizer/asan/asan_report.cc
index 13e94c421b5..8f11ff4eac3 100644
--- a/libsanitizer/asan/asan_report.cc
+++ b/libsanitizer/asan/asan_report.cc
@@ -15,8 +15,8 @@
#include "asan_report.h"
#include "asan_stack.h"
#include "asan_thread.h"
-#include "asan_thread_registry.h"
#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_flags.h"
#include "sanitizer_common/sanitizer_report_decorator.h"
#include "sanitizer_common/sanitizer_symbolizer.h"
@@ -42,15 +42,6 @@ void AppendToErrorMessageBuffer(const char *buffer) {
}
// ---------------------- Decorator ------------------------------ {{{1
-bool PrintsToTtyCached() {
- static int cached = 0;
- static bool prints_to_tty;
- if (!cached) { // Ok wrt threads since we are printing only from one thread.
- prints_to_tty = PrintsToTty();
- cached = 1;
- }
- return prints_to_tty;
-}
class Decorator: private __sanitizer::AnsiColorDecorator {
public:
Decorator() : __sanitizer::AnsiColorDecorator(PrintsToTtyCached()) { }
@@ -111,7 +102,7 @@ static void PrintShadowBytes(const char *before, u8 *bytes,
for (uptr i = 0; i < n; i++) {
u8 *p = bytes + i;
const char *before = p == guilty ? "[" :
- p - 1 == guilty ? "" : " ";
+ (p - 1 == guilty && i != 0) ? "" : " ";
const char *after = p == guilty ? "]" : "";
PrintShadowByte(before, *p, after);
}
@@ -123,12 +114,12 @@ static void PrintLegend() {
"application bytes):\n", (int)SHADOW_GRANULARITY);
PrintShadowByte(" Addressable: ", 0);
Printf(" Partially addressable: ");
- for (uptr i = 1; i < SHADOW_GRANULARITY; i++)
+ for (u8 i = 1; i < SHADOW_GRANULARITY; i++)
PrintShadowByte("", i, " ");
Printf("\n");
PrintShadowByte(" Heap left redzone: ", kAsanHeapLeftRedzoneMagic);
- PrintShadowByte(" Heap righ redzone: ", kAsanHeapRightRedzoneMagic);
- PrintShadowByte(" Freed Heap region: ", kAsanHeapFreeMagic);
+ PrintShadowByte(" Heap right redzone: ", kAsanHeapRightRedzoneMagic);
+ PrintShadowByte(" Freed heap region: ", kAsanHeapFreeMagic);
PrintShadowByte(" Stack left redzone: ", kAsanStackLeftRedzoneMagic);
PrintShadowByte(" Stack mid redzone: ", kAsanStackMidRedzoneMagic);
PrintShadowByte(" Stack right redzone: ", kAsanStackRightRedzoneMagic);
@@ -173,19 +164,34 @@ static void PrintZoneForPointer(uptr ptr, uptr zone_ptr,
}
}
+static void DescribeThread(AsanThread *t) {
+ if (t)
+ DescribeThread(t->context());
+}
+
// ---------------------- Address Descriptions ------------------- {{{1
static bool IsASCII(unsigned char c) {
return /*0x00 <= c &&*/ c <= 0x7F;
}
+static const char *MaybeDemangleGlobalName(const char *name) {
+ // We can spoil names of globals with C linkage, so use an heuristic
+ // approach to check if the name should be demangled.
+ return (name[0] == '_' && name[1] == 'Z' && &getSymbolizer)
+ ? getSymbolizer()->Demangle(name)
+ : name;
+}
+
// Check if the global is a zero-terminated ASCII string. If so, print it.
static void PrintGlobalNameIfASCII(const __asan_global &g) {
for (uptr p = g.beg; p < g.beg + g.size - 1; p++) {
- if (!IsASCII(*(unsigned char*)p)) return;
+ unsigned char c = *(unsigned char*)p;
+ if (c == '\0' || !IsASCII(c)) return;
}
- if (*(char*)(g.beg + g.size - 1) != 0) return;
- Printf(" '%s' is ascii string '%s'\n", g.name, (char*)g.beg);
+ if (*(char*)(g.beg + g.size - 1) != '\0') return;
+ Printf(" '%s' is ascii string '%s'\n",
+ MaybeDemangleGlobalName(g.name), (char*)g.beg);
}
bool DescribeAddressRelativeToGlobal(uptr addr, uptr size,
@@ -206,8 +212,8 @@ bool DescribeAddressRelativeToGlobal(uptr addr, uptr size,
// Can it happen?
Printf("%p is located %zd bytes inside", (void*)addr, addr - g.beg);
}
- Printf(" of global variable '%s' (0x%zx) of size %zu\n",
- g.name, g.beg, g.size);
+ Printf(" of global variable '%s' from '%s' (0x%zx) of size %zu\n",
+ MaybeDemangleGlobalName(g.name), g.module_name, g.beg, g.size);
Printf("%s", d.EndLocation());
PrintGlobalNameIfASCII(g);
return true;
@@ -234,57 +240,149 @@ bool DescribeAddressIfShadow(uptr addr) {
return false;
}
+// Return " (thread_name) " or an empty string if the name is empty.
+const char *ThreadNameWithParenthesis(AsanThreadContext *t, char buff[],
+ uptr buff_len) {
+ const char *name = t->name;
+ if (name[0] == '\0') return "";
+ buff[0] = 0;
+ internal_strncat(buff, " (", 3);
+ internal_strncat(buff, name, buff_len - 4);
+ internal_strncat(buff, ")", 2);
+ return buff;
+}
+
+const char *ThreadNameWithParenthesis(u32 tid, char buff[],
+ uptr buff_len) {
+ if (tid == kInvalidTid) return "";
+ asanThreadRegistry().CheckLocked();
+ AsanThreadContext *t = GetThreadContextByTidLocked(tid);
+ return ThreadNameWithParenthesis(t, buff, buff_len);
+}
+
+void PrintAccessAndVarIntersection(const char *var_name,
+ uptr var_beg, uptr var_size,
+ uptr addr, uptr access_size,
+ uptr prev_var_end, uptr next_var_beg) {
+ uptr var_end = var_beg + var_size;
+ uptr addr_end = addr + access_size;
+ const char *pos_descr = 0;
+ // If the variable [var_beg, var_end) is the nearest variable to the
+ // current memory access, indicate it in the log.
+ if (addr >= var_beg) {
+ if (addr_end <= var_end)
+ pos_descr = "is inside"; // May happen if this is a use-after-return.
+ else if (addr < var_end)
+ pos_descr = "partially overflows";
+ else if (addr_end <= next_var_beg &&
+ next_var_beg - addr_end >= addr - var_end)
+ pos_descr = "overflows";
+ } else {
+ if (addr_end > var_beg)
+ pos_descr = "partially underflows";
+ else if (addr >= prev_var_end &&
+ addr - prev_var_end >= var_beg - addr_end)
+ pos_descr = "underflows";
+ }
+ Printf(" [%zd, %zd) '%s'", var_beg, var_beg + var_size, var_name);
+ if (pos_descr) {
+ Decorator d;
+ // FIXME: we may want to also print the size of the access here,
+ // but in case of accesses generated by memset it may be confusing.
+ Printf("%s <== Memory access at offset %zd %s this variable%s\n",
+ d.Location(), addr, pos_descr, d.EndLocation());
+ } else {
+ Printf("\n");
+ }
+}
+
+struct StackVarDescr {
+ uptr beg;
+ uptr size;
+ const char *name_pos;
+ uptr name_len;
+};
+
bool DescribeAddressIfStack(uptr addr, uptr access_size) {
- AsanThread *t = asanThreadRegistry().FindThreadByStackAddress(addr);
+ AsanThread *t = FindThreadByStackAddress(addr);
if (!t) return false;
- const sptr kBufSize = 4095;
+ const uptr kBufSize = 4095;
char buf[kBufSize];
uptr offset = 0;
- const char *frame_descr = t->GetFrameNameByAddr(addr, &offset);
+ uptr frame_pc = 0;
+ char tname[128];
+ const char *frame_descr = t->GetFrameNameByAddr(addr, &offset, &frame_pc);
+
+#ifdef __powerpc64__
+ // On PowerPC64, the address of a function actually points to a
+ // three-doubleword data structure with the first field containing
+ // the address of the function's code.
+ frame_pc = *reinterpret_cast<uptr *>(frame_pc);
+#endif
+
// This string is created by the compiler and has the following form:
- // "FunctioName n alloc_1 alloc_2 ... alloc_n"
+ // "n alloc_1 alloc_2 ... alloc_n"
// where alloc_i looks like "offset size len ObjectName ".
CHECK(frame_descr);
- // Report the function name and the offset.
- const char *name_end = internal_strchr(frame_descr, ' ');
- CHECK(name_end);
- buf[0] = 0;
- internal_strncat(buf, frame_descr,
- Min(kBufSize,
- static_cast<sptr>(name_end - frame_descr)));
Decorator d;
Printf("%s", d.Location());
- Printf("Address %p is located at offset %zu "
- "in frame <%s> of T%d's stack:\n",
- (void*)addr, offset, Demangle(buf), t->tid());
+ Printf("Address %p is located in stack of thread T%d%s "
+ "at offset %zu in frame\n",
+ addr, t->tid(),
+ ThreadNameWithParenthesis(t->tid(), tname, sizeof(tname)),
+ offset);
+ // Now we print the frame where the alloca has happened.
+ // We print this frame as a stack trace with one element.
+ // The symbolizer may print more than one frame if inlining was involved.
+ // The frame numbers may be different than those in the stack trace printed
+ // previously. That's unfortunate, but I have no better solution,
+ // especially given that the alloca may be from entirely different place
+ // (e.g. use-after-scope, or different thread's stack).
+ StackTrace alloca_stack;
+ alloca_stack.trace[0] = frame_pc + 16;
+ alloca_stack.size = 1;
Printf("%s", d.EndLocation());
+ PrintStack(&alloca_stack);
// Report the number of stack objects.
char *p;
- uptr n_objects = internal_simple_strtoll(name_end, &p, 10);
- CHECK(n_objects > 0);
+ uptr n_objects = (uptr)internal_simple_strtoll(frame_descr, &p, 10);
+ CHECK_GT(n_objects, 0);
Printf(" This frame has %zu object(s):\n", n_objects);
+
// Report all objects in this frame.
+ InternalScopedBuffer<StackVarDescr> vars(n_objects);
for (uptr i = 0; i < n_objects; i++) {
uptr beg, size;
- sptr len;
- beg = internal_simple_strtoll(p, &p, 10);
- size = internal_simple_strtoll(p, &p, 10);
- len = internal_simple_strtoll(p, &p, 10);
- if (beg <= 0 || size <= 0 || len < 0 || *p != ' ') {
+ uptr len;
+ beg = (uptr)internal_simple_strtoll(p, &p, 10);
+ size = (uptr)internal_simple_strtoll(p, &p, 10);
+ len = (uptr)internal_simple_strtoll(p, &p, 10);
+ if (beg == 0 || size == 0 || *p != ' ') {
Printf("AddressSanitizer can't parse the stack frame "
"descriptor: |%s|\n", frame_descr);
break;
}
p++;
- buf[0] = 0;
- internal_strncat(buf, p, Min(kBufSize, len));
+ vars[i].beg = beg;
+ vars[i].size = size;
+ vars[i].name_pos = p;
+ vars[i].name_len = len;
p += len;
- Printf(" [%zu, %zu) '%s'\n", beg, beg + size, buf);
+ }
+ for (uptr i = 0; i < n_objects; i++) {
+ buf[0] = 0;
+ internal_strncat(buf, vars[i].name_pos,
+ static_cast<uptr>(Min(kBufSize, vars[i].name_len)));
+ uptr prev_var_end = i ? vars[i - 1].beg + vars[i - 1].size : 0;
+ uptr next_var_beg = i + 1 < n_objects ? vars[i + 1].beg : ~(0UL);
+ PrintAccessAndVarIntersection(buf, vars[i].beg, vars[i].size,
+ offset, access_size,
+ prev_var_end, next_var_beg);
}
Printf("HINT: this may be a false positive if your program uses "
"some custom stack unwind mechanism or swapcontext\n"
" (longjmp and C++ exceptions *are* supported)\n");
- DescribeThread(t->summary());
+ DescribeThread(t);
return true;
}
@@ -312,65 +410,43 @@ static void DescribeAccessToHeapChunk(AsanChunkView chunk, uptr addr,
Printf("%s", d.EndLocation());
}
-// Return " (thread_name) " or an empty string if the name is empty.
-const char *ThreadNameWithParenthesis(AsanThreadSummary *t, char buff[],
- uptr buff_len) {
- const char *name = t->name();
- if (*name == 0) return "";
- buff[0] = 0;
- internal_strncat(buff, " (", 3);
- internal_strncat(buff, name, buff_len - 4);
- internal_strncat(buff, ")", 2);
- return buff;
-}
-
-const char *ThreadNameWithParenthesis(u32 tid, char buff[],
- uptr buff_len) {
- if (tid == kInvalidTid) return "";
- AsanThreadSummary *t = asanThreadRegistry().FindByTid(tid);
- return ThreadNameWithParenthesis(t, buff, buff_len);
-}
-
void DescribeHeapAddress(uptr addr, uptr access_size) {
AsanChunkView chunk = FindHeapChunkByAddress(addr);
if (!chunk.IsValid()) return;
DescribeAccessToHeapChunk(chunk, addr, access_size);
CHECK(chunk.AllocTid() != kInvalidTid);
- AsanThreadSummary *alloc_thread =
- asanThreadRegistry().FindByTid(chunk.AllocTid());
+ asanThreadRegistry().CheckLocked();
+ AsanThreadContext *alloc_thread =
+ GetThreadContextByTidLocked(chunk.AllocTid());
StackTrace alloc_stack;
chunk.GetAllocStack(&alloc_stack);
- AsanThread *t = asanThreadRegistry().GetCurrent();
- CHECK(t);
char tname[128];
Decorator d;
+ AsanThreadContext *free_thread = 0;
if (chunk.FreeTid() != kInvalidTid) {
- AsanThreadSummary *free_thread =
- asanThreadRegistry().FindByTid(chunk.FreeTid());
+ free_thread = GetThreadContextByTidLocked(chunk.FreeTid());
Printf("%sfreed by thread T%d%s here:%s\n", d.Allocation(),
- free_thread->tid(),
+ free_thread->tid,
ThreadNameWithParenthesis(free_thread, tname, sizeof(tname)),
d.EndAllocation());
StackTrace free_stack;
chunk.GetFreeStack(&free_stack);
PrintStack(&free_stack);
Printf("%spreviously allocated by thread T%d%s here:%s\n",
- d.Allocation(), alloc_thread->tid(),
+ d.Allocation(), alloc_thread->tid,
ThreadNameWithParenthesis(alloc_thread, tname, sizeof(tname)),
d.EndAllocation());
- PrintStack(&alloc_stack);
- DescribeThread(t->summary());
- DescribeThread(free_thread);
- DescribeThread(alloc_thread);
} else {
Printf("%sallocated by thread T%d%s here:%s\n", d.Allocation(),
- alloc_thread->tid(),
+ alloc_thread->tid,
ThreadNameWithParenthesis(alloc_thread, tname, sizeof(tname)),
d.EndAllocation());
- PrintStack(&alloc_stack);
- DescribeThread(t->summary());
- DescribeThread(alloc_thread);
}
+ PrintStack(&alloc_stack);
+ DescribeThread(GetCurrentThread());
+ if (free_thread)
+ DescribeThread(free_thread);
+ DescribeThread(alloc_thread);
}
void DescribeAddress(uptr addr, uptr access_size) {
@@ -388,26 +464,27 @@ void DescribeAddress(uptr addr, uptr access_size) {
// ------------------- Thread description -------------------- {{{1
-void DescribeThread(AsanThreadSummary *summary) {
- CHECK(summary);
+void DescribeThread(AsanThreadContext *context) {
+ CHECK(context);
+ asanThreadRegistry().CheckLocked();
// No need to announce the main thread.
- if (summary->tid() == 0 || summary->announced()) {
+ if (context->tid == 0 || context->announced) {
return;
}
- summary->set_announced(true);
+ context->announced = true;
char tname[128];
- Printf("Thread T%d%s", summary->tid(),
- ThreadNameWithParenthesis(summary->tid(), tname, sizeof(tname)));
+ Printf("Thread T%d%s", context->tid,
+ ThreadNameWithParenthesis(context->tid, tname, sizeof(tname)));
Printf(" created by T%d%s here:\n",
- summary->parent_tid(),
- ThreadNameWithParenthesis(summary->parent_tid(),
+ context->parent_tid,
+ ThreadNameWithParenthesis(context->parent_tid,
tname, sizeof(tname)));
- PrintStack(summary->stack());
+ PrintStack(&context->stack);
// Recursively described parent thread if needed.
if (flags()->print_full_thread_history) {
- AsanThreadSummary *parent_summary =
- asanThreadRegistry().FindByTid(summary->parent_tid());
- DescribeThread(parent_summary);
+ AsanThreadContext *parent_context =
+ GetThreadContextByTidLocked(context->parent_tid);
+ DescribeThread(parent_context);
}
}
@@ -426,7 +503,7 @@ class ScopedInErrorReport {
// they are defined as no-return.
Report("AddressSanitizer: while reporting a bug found another one."
"Ignoring.\n");
- u32 current_tid = asanThreadRegistry().GetCurrentTidOrInvalid();
+ u32 current_tid = GetCurrentTidOrInvalid();
if (current_tid != reporting_thread_tid) {
// ASan found two bugs in different threads simultaneously. Sleep
// long enough to make sure that the thread which started to print
@@ -438,24 +515,20 @@ class ScopedInErrorReport {
internal__exit(flags()->exitcode);
}
ASAN_ON_ERROR();
- reporting_thread_tid = asanThreadRegistry().GetCurrentTidOrInvalid();
+ // Make sure the registry and sanitizer report mutexes are locked while
+ // we're printing an error report.
+ // We can lock them only here to avoid self-deadlock in case of
+ // recursive reports.
+ asanThreadRegistry().Lock();
+ CommonSanitizerReportMutex.Lock();
+ reporting_thread_tid = GetCurrentTidOrInvalid();
Printf("===================================================="
"=============\n");
- if (reporting_thread_tid != kInvalidTid) {
- // We started reporting an error message. Stop using the fake stack
- // in case we call an instrumented function from a symbolizer.
- AsanThread *curr_thread = asanThreadRegistry().GetCurrent();
- CHECK(curr_thread);
- curr_thread->fake_stack().StopUsingFakeStack();
- }
}
// Destructor is NORETURN, as functions that report errors are.
NORETURN ~ScopedInErrorReport() {
// Make sure the current thread is announced.
- AsanThread *curr_thread = asanThreadRegistry().GetCurrent();
- if (curr_thread) {
- DescribeThread(curr_thread->summary());
- }
+ DescribeThread(GetCurrentThread());
// Print memory stats.
if (flags()->print_stats)
__asan_print_accumulated_stats();
@@ -469,13 +542,15 @@ class ScopedInErrorReport {
static void ReportSummary(const char *error_type, StackTrace *stack) {
if (!stack->size) return;
- if (IsSymbolizerAvailable()) {
+ if (&getSymbolizer && getSymbolizer()->IsAvailable()) {
AddressInfo ai;
// Currently, we include the first stack frame into the report summary.
// Maybe sometimes we need to choose another frame (e.g. skip memcpy/etc).
- SymbolizeCode(stack->trace[0], &ai, 1);
+ uptr pc = StackTrace::GetPreviousInstructionPc(stack->trace[0]);
+ getSymbolizer()->SymbolizeCode(pc, &ai, 1);
ReportErrorSummary(error_type,
- StripPathPrefix(ai.file, flags()->strip_path_prefix),
+ StripPathPrefix(ai.file,
+ common_flags()->strip_path_prefix),
ai.line, ai.function);
}
// FIXME: do we need to print anything at all if there is no symbolizer?
@@ -488,7 +563,7 @@ void ReportSIGSEGV(uptr pc, uptr sp, uptr bp, uptr addr) {
Report("ERROR: AddressSanitizer: SEGV on unknown address %p"
" (pc %p sp %p bp %p T%d)\n",
(void*)addr, (void*)pc, (void*)sp, (void*)bp,
- asanThreadRegistry().GetCurrentTidOrInvalid());
+ GetCurrentTidOrInvalid());
Printf("%s", d.EndWarning());
Printf("AddressSanitizer can not provide additional info.\n");
GET_STACK_TRACE_FATAL(pc, bp);
@@ -500,7 +575,13 @@ void ReportDoubleFree(uptr addr, StackTrace *stack) {
ScopedInErrorReport in_report;
Decorator d;
Printf("%s", d.Warning());
- Report("ERROR: AddressSanitizer: attempting double-free on %p:\n", addr);
+ char tname[128];
+ u32 curr_tid = GetCurrentTidOrInvalid();
+ Report("ERROR: AddressSanitizer: attempting double-free on %p in "
+ "thread T%d%s:\n",
+ addr, curr_tid,
+ ThreadNameWithParenthesis(curr_tid, tname, sizeof(tname)));
+
Printf("%s", d.EndWarning());
PrintStack(stack);
DescribeHeapAddress(addr, 1);
@@ -511,8 +592,11 @@ void ReportFreeNotMalloced(uptr addr, StackTrace *stack) {
ScopedInErrorReport in_report;
Decorator d;
Printf("%s", d.Warning());
+ char tname[128];
+ u32 curr_tid = GetCurrentTidOrInvalid();
Report("ERROR: AddressSanitizer: attempting free on address "
- "which was not malloc()-ed: %p\n", addr);
+ "which was not malloc()-ed: %p in thread T%d%s\n", addr,
+ curr_tid, ThreadNameWithParenthesis(curr_tid, tname, sizeof(tname)));
Printf("%s", d.EndWarning());
PrintStack(stack);
DescribeHeapAddress(addr, 1);
@@ -678,7 +762,7 @@ void __asan_report_error(uptr pc, uptr bp, uptr sp,
bug_descr, (void*)addr, pc, bp, sp);
Printf("%s", d.EndWarning());
- u32 curr_tid = asanThreadRegistry().GetCurrentTidOrInvalid();
+ u32 curr_tid = GetCurrentTidOrInvalid();
char tname[128];
Printf("%s%s of size %zu at %p thread T%d%s%s\n",
d.Access(),
@@ -712,6 +796,6 @@ void __asan_describe_address(uptr addr) {
#if !SANITIZER_SUPPORTS_WEAK_HOOKS
// Provide default implementation of __asan_on_error that does nothing
// and may be overriden by user.
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE NOINLINE
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE NOINLINE
void __asan_on_error() {}
#endif
diff --git a/libsanitizer/asan/asan_report.h b/libsanitizer/asan/asan_report.h
index 13724dab9ee..afe7673304c 100644
--- a/libsanitizer/asan/asan_report.h
+++ b/libsanitizer/asan/asan_report.h
@@ -27,7 +27,7 @@ bool DescribeAddressIfStack(uptr addr, uptr access_size);
// Determines memory type on its own.
void DescribeAddress(uptr addr, uptr access_size);
-void DescribeThread(AsanThreadSummary *summary);
+void DescribeThread(AsanThreadContext *context);
// Different kinds of error reports.
void NORETURN ReportSIGSEGV(uptr pc, uptr sp, uptr bp, uptr addr);
diff --git a/libsanitizer/asan/asan_rtl.cc b/libsanitizer/asan/asan_rtl.cc
index 6ddb01329ad..67327611e84 100644
--- a/libsanitizer/asan/asan_rtl.cc
+++ b/libsanitizer/asan/asan_rtl.cc
@@ -11,17 +11,21 @@
//===----------------------------------------------------------------------===//
#include "asan_allocator.h"
#include "asan_interceptors.h"
+#include "asan_interface_internal.h"
#include "asan_internal.h"
#include "asan_mapping.h"
+#include "asan_poisoning.h"
#include "asan_report.h"
#include "asan_stack.h"
#include "asan_stats.h"
#include "asan_thread.h"
-#include "asan_thread_registry.h"
#include "sanitizer_common/sanitizer_atomic.h"
#include "sanitizer_common/sanitizer_flags.h"
#include "sanitizer_common/sanitizer_libc.h"
#include "sanitizer_common/sanitizer_symbolizer.h"
+#include "lsan/lsan_common.h"
+
+int __asan_option_detect_stack_use_after_return; // Global interface symbol.
namespace __asan {
@@ -62,13 +66,9 @@ static void AsanCheckFailed(const char *file, int line, const char *cond,
}
// -------------------------- Flags ------------------------- {{{1
-static const int kDeafultMallocContextSize = 30;
-
-static Flags asan_flags;
+static const int kDefaultMallocContextSize = 30;
-Flags *flags() {
- return &asan_flags;
-}
+Flags asan_flags_dont_use_directly; // use via flags().
static const char *MaybeCallAsanDefaultOptions() {
return (&__asan_default_options) ? __asan_default_options() : "";
@@ -86,28 +86,32 @@ static const char *MaybeUseAsanDefaultOptionsCompileDefiniton() {
}
static void ParseFlagsFromString(Flags *f, const char *str) {
+ ParseCommonFlagsFromString(str);
+ CHECK((uptr)common_flags()->malloc_context_size <= kStackTraceMax);
+
ParseFlag(str, &f->quarantine_size, "quarantine_size");
- ParseFlag(str, &f->symbolize, "symbolize");
ParseFlag(str, &f->verbosity, "verbosity");
ParseFlag(str, &f->redzone, "redzone");
- CHECK(f->redzone >= 16);
+ CHECK_GE(f->redzone, 16);
CHECK(IsPowerOfTwo(f->redzone));
ParseFlag(str, &f->debug, "debug");
ParseFlag(str, &f->report_globals, "report_globals");
- ParseFlag(str, &f->check_initialization_order, "initialization_order");
- ParseFlag(str, &f->malloc_context_size, "malloc_context_size");
- CHECK((uptr)f->malloc_context_size <= kStackTraceMax);
+ ParseFlag(str, &f->check_initialization_order, "check_initialization_order");
ParseFlag(str, &f->replace_str, "replace_str");
ParseFlag(str, &f->replace_intrin, "replace_intrin");
ParseFlag(str, &f->mac_ignore_invalid_free, "mac_ignore_invalid_free");
- ParseFlag(str, &f->use_fake_stack, "use_fake_stack");
+ ParseFlag(str, &f->detect_stack_use_after_return,
+ "detect_stack_use_after_return");
+ ParseFlag(str, &f->uar_stack_size_log, "uar_stack_size_log");
ParseFlag(str, &f->max_malloc_fill_size, "max_malloc_fill_size");
+ ParseFlag(str, &f->malloc_fill_byte, "malloc_fill_byte");
ParseFlag(str, &f->exitcode, "exitcode");
ParseFlag(str, &f->allow_user_poisoning, "allow_user_poisoning");
ParseFlag(str, &f->sleep_before_dying, "sleep_before_dying");
ParseFlag(str, &f->handle_segv, "handle_segv");
+ ParseFlag(str, &f->allow_user_segv_handler, "allow_user_segv_handler");
ParseFlag(str, &f->use_sigaltstack, "use_sigaltstack");
ParseFlag(str, &f->check_malloc_usable_size, "check_malloc_usable_size");
ParseFlag(str, &f->unmap_shadow_on_exit, "unmap_shadow_on_exit");
@@ -116,37 +120,47 @@ static void ParseFlagsFromString(Flags *f, const char *str) {
ParseFlag(str, &f->print_legend, "print_legend");
ParseFlag(str, &f->atexit, "atexit");
ParseFlag(str, &f->disable_core, "disable_core");
- ParseFlag(str, &f->strip_path_prefix, "strip_path_prefix");
ParseFlag(str, &f->allow_reexec, "allow_reexec");
ParseFlag(str, &f->print_full_thread_history, "print_full_thread_history");
- ParseFlag(str, &f->log_path, "log_path");
- ParseFlag(str, &f->fast_unwind_on_fatal, "fast_unwind_on_fatal");
- ParseFlag(str, &f->fast_unwind_on_malloc, "fast_unwind_on_malloc");
ParseFlag(str, &f->poison_heap, "poison_heap");
ParseFlag(str, &f->alloc_dealloc_mismatch, "alloc_dealloc_mismatch");
ParseFlag(str, &f->use_stack_depot, "use_stack_depot");
+ ParseFlag(str, &f->strict_memcmp, "strict_memcmp");
+ ParseFlag(str, &f->strict_init_order, "strict_init_order");
}
void InitializeFlags(Flags *f, const char *env) {
- internal_memset(f, 0, sizeof(*f));
+ CommonFlags *cf = common_flags();
+ cf->external_symbolizer_path = GetEnv("ASAN_SYMBOLIZER_PATH");
+ cf->symbolize = true;
+ cf->malloc_context_size = kDefaultMallocContextSize;
+ cf->fast_unwind_on_fatal = false;
+ cf->fast_unwind_on_malloc = true;
+ cf->strip_path_prefix = "";
+ cf->handle_ioctl = false;
+ cf->log_path = 0;
+ cf->detect_leaks = false;
+ cf->leak_check_at_exit = true;
+ internal_memset(f, 0, sizeof(*f));
f->quarantine_size = (ASAN_LOW_MEMORY) ? 1UL << 26 : 1UL << 28;
- f->symbolize = false;
f->verbosity = 0;
- f->redzone = ASAN_ALLOCATOR_VERSION == 2 ? 16 : (ASAN_LOW_MEMORY) ? 64 : 128;
+ f->redzone = 16;
f->debug = false;
f->report_globals = 1;
- f->check_initialization_order = true;
- f->malloc_context_size = kDeafultMallocContextSize;
+ f->check_initialization_order = false;
f->replace_str = true;
f->replace_intrin = true;
f->mac_ignore_invalid_free = false;
- f->use_fake_stack = true;
- f->max_malloc_fill_size = 0;
+ f->detect_stack_use_after_return = false; // Also needs the compiler flag.
+ f->uar_stack_size_log = 0;
+ f->max_malloc_fill_size = 0x1000; // By default, fill only the first 4K.
+ f->malloc_fill_byte = 0xbe;
f->exitcode = ASAN_DEFAULT_FAILURE_EXITCODE;
f->allow_user_poisoning = true;
f->sleep_before_dying = 0;
f->handle_segv = ASAN_NEEDS_SEGV;
+ f->allow_user_segv_handler = false;
f->use_sigaltstack = false;
f->check_malloc_usable_size = true;
f->unmap_shadow_on_exit = false;
@@ -155,15 +169,15 @@ void InitializeFlags(Flags *f, const char *env) {
f->print_legend = true;
f->atexit = false;
f->disable_core = (SANITIZER_WORDSIZE == 64);
- f->strip_path_prefix = "";
f->allow_reexec = true;
f->print_full_thread_history = true;
- f->log_path = 0;
- f->fast_unwind_on_fatal = false;
- f->fast_unwind_on_malloc = true;
f->poison_heap = true;
- f->alloc_dealloc_mismatch = true;
- f->use_stack_depot = true; // Only affects allocator2.
+ // Turn off alloc/dealloc mismatch checker on Mac and Windows for now.
+ // TODO(glider,timurrrr): Fix known issues and enable this back.
+ f->alloc_dealloc_mismatch = (SANITIZER_MAC == 0) && (SANITIZER_WINDOWS == 0);
+ f->use_stack_depot = true;
+ f->strict_memcmp = true;
+ f->strict_init_order = false;
// Override from compile definition.
ParseFlagsFromString(f, MaybeUseAsanDefaultOptionsCompileDefiniton());
@@ -177,6 +191,20 @@ void InitializeFlags(Flags *f, const char *env) {
// Override from command line.
ParseFlagsFromString(f, env);
+
+#if !CAN_SANITIZE_LEAKS
+ if (cf->detect_leaks) {
+ Report("%s: detect_leaks is not supported on this platform.\n",
+ SanitizerToolName);
+ cf->detect_leaks = false;
+ }
+#endif
+
+ if (cf->detect_leaks && !f->use_stack_depot) {
+ Report("%s: detect_leaks is ignored (requires use_stack_depot).\n",
+ SanitizerToolName);
+ cf->detect_leaks = false;
+ }
}
// -------------------------- Globals --------------------- {{{1
@@ -197,8 +225,8 @@ void ShowStatsAndAbort() {
// ---------------------- mmap -------------------- {{{1
// Reserve memory range [beg, end].
static void ReserveShadowMemoryRange(uptr beg, uptr end) {
- CHECK((beg % GetPageSizeCached()) == 0);
- CHECK(((end + 1) % GetPageSizeCached()) == 0);
+ CHECK_EQ((beg % GetPageSizeCached()), 0);
+ CHECK_EQ(((end + 1) % GetPageSizeCached()), 0);
uptr size = end - beg + 1;
void *res = MmapFixedNoReserve(beg, size);
if (res != (void*)beg) {
@@ -281,9 +309,7 @@ static NOINLINE void force_interface_symbols() {
case 25: __asan_poison_memory_region(0, 0); break;
case 26: __asan_unpoison_memory_region(0, 0); break;
case 27: __asan_set_error_exit_code(0); break;
- case 28: __asan_stack_free(0, 0, 0); break;
- case 29: __asan_stack_malloc(0, 0); break;
- case 30: __asan_before_dynamic_init(0, 0); break;
+ case 30: __asan_before_dynamic_init(0); break;
case 31: __asan_after_dynamic_init(); break;
case 32: __asan_poison_stack_memory(0, 0); break;
case 33: __asan_unpoison_stack_memory(0, 0); break;
@@ -304,22 +330,12 @@ static void asan_atexit() {
static void InitializeHighMemEnd() {
#if !ASAN_FIXED_MAPPING
-#if SANITIZER_WORDSIZE == 64
-# if defined(__powerpc64__)
- // FIXME:
- // On PowerPC64 we have two different address space layouts: 44- and 46-bit.
- // We somehow need to figure our which one we are using now and choose
- // one of 0x00000fffffffffffUL and 0x00003fffffffffffUL.
- // Note that with 'ulimit -s unlimited' the stack is moved away from the top
- // of the address space, so simply checking the stack address is not enough.
- kHighMemEnd = (1ULL << 44) - 1; // 0x00000fffffffffffUL
-# else
- kHighMemEnd = (1ULL << 47) - 1; // 0x00007fffffffffffUL;
-# endif
-#else // SANITIZER_WORDSIZE == 32
- kHighMemEnd = (1ULL << 32) - 1; // 0xffffffff;
-#endif // SANITIZER_WORDSIZE
+ kHighMemEnd = GetMaxVirtualAddress();
+ // Increase kHighMemEnd to make sure it's properly
+ // aligned together with kHighMemBeg:
+ kHighMemEnd |= SHADOW_GRANULARITY * GetPageSizeCached() - 1;
#endif // !ASAN_FIXED_MAPPING
+ CHECK_EQ((kHighMemBeg % GetPageSizeCached()), 0);
}
static void ProtectGap(uptr a, uptr size) {
@@ -361,7 +377,9 @@ static void PrintAddressSpaceLayout() {
}
Printf("\n");
Printf("red_zone=%zu\n", (uptr)flags()->redzone);
- Printf("malloc_context_size=%zu\n", (uptr)flags()->malloc_context_size);
+ Printf("quarantine_size=%zuM\n", (uptr)flags()->quarantine_size >> 20);
+ Printf("malloc_context_size=%zu\n",
+ (uptr)common_flags()->malloc_context_size);
Printf("SHADOW_SCALE: %zx\n", (uptr)SHADOW_SCALE);
Printf("SHADOW_GRANULARITY: %zx\n", (uptr)SHADOW_GRANULARITY);
@@ -380,7 +398,7 @@ using namespace __asan; // NOLINT
#if !SANITIZER_SUPPORTS_WEAK_HOOKS
extern "C" {
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
const char* __asan_default_options() { return ""; }
} // extern "C"
#endif
@@ -393,12 +411,28 @@ int NOINLINE __asan_set_error_exit_code(int exit_code) {
void NOINLINE __asan_handle_no_return() {
int local_stack;
- AsanThread *curr_thread = asanThreadRegistry().GetCurrent();
+ AsanThread *curr_thread = GetCurrentThread();
CHECK(curr_thread);
uptr PageSize = GetPageSizeCached();
uptr top = curr_thread->stack_top();
uptr bottom = ((uptr)&local_stack - PageSize) & ~(PageSize-1);
+ static const uptr kMaxExpectedCleanupSize = 64 << 20; // 64M
+ if (top - bottom > kMaxExpectedCleanupSize) {
+ static bool reported_warning = false;
+ if (reported_warning)
+ return;
+ reported_warning = true;
+ Report("WARNING: ASan is ignoring requested __asan_handle_no_return: "
+ "stack top: %p; bottom %p; size: %p (%zd)\n"
+ "False positive error reports may follow\n"
+ "For details see "
+ "http://code.google.com/p/address-sanitizer/issues/detail?id=189\n",
+ top, bottom, top - bottom, top - bottom);
+ return;
+ }
PoisonShadow(bottom, top - bottom, 0);
+ if (curr_thread->has_fake_stack())
+ curr_thread->fake_stack()->HandleNoReturn();
}
void NOINLINE __asan_set_death_callback(void (*callback)(void)) {
@@ -424,7 +458,9 @@ void __asan_init() {
// initialization steps look at flags().
const char *options = GetEnv("ASAN_OPTIONS");
InitializeFlags(flags(), options);
- __sanitizer_set_report_path(flags()->log_path);
+ __sanitizer_set_report_path(common_flags()->log_path);
+ __asan_option_detect_stack_use_after_return =
+ flags()->detect_stack_use_after_return;
if (flags()->verbosity && options) {
Report("Parsed ASAN_OPTIONS: %s\n", options);
@@ -447,12 +483,12 @@ void __asan_init() {
ReplaceOperatorsNewAndDelete();
uptr shadow_start = kLowShadowBeg;
- if (kLowShadowBeg) shadow_start -= GetMmapGranularity();
- uptr shadow_end = kHighShadowEnd;
+ if (kLowShadowBeg)
+ shadow_start -= GetMmapGranularity();
bool full_shadow_is_available =
- MemoryRangeIsAvailable(shadow_start, shadow_end);
+ MemoryRangeIsAvailable(shadow_start, kHighShadowEnd);
-#if ASAN_LINUX && defined(__x86_64__) && !ASAN_FIXED_MAPPING
+#if SANITIZER_LINUX && defined(__x86_64__) && !ASAN_FIXED_MAPPING
if (!full_shadow_is_available) {
kMidMemBeg = kLowMemEnd < 0x3000000000ULL ? 0x3000000000ULL : 0;
kMidMemEnd = kLowMemEnd < 0x3000000000ULL ? 0x4fffffffffULL : 0;
@@ -476,7 +512,7 @@ void __asan_init() {
ProtectGap(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1);
} else if (kMidMemBeg &&
MemoryRangeIsAvailable(shadow_start, kMidMemBeg - 1) &&
- MemoryRangeIsAvailable(kMidMemEnd + 1, shadow_end)) {
+ MemoryRangeIsAvailable(kMidMemEnd + 1, kHighShadowEnd)) {
CHECK(kLowShadowBeg != kLowShadowEnd);
// mmap the low shadow plus at least one page at the left.
ReserveShadowMemoryRange(shadow_start, kLowShadowEnd);
@@ -496,12 +532,16 @@ void __asan_init() {
}
InstallSignalHandlers();
+
+ AsanTSDInit(AsanThread::TSDDtor);
+ // Allocator should be initialized before starting external symbolizer, as
+ // fork() on Mac locks the allocator.
+ InitializeAllocator();
+
// Start symbolizer process if necessary.
- if (flags()->symbolize) {
- const char *external_symbolizer = GetEnv("ASAN_SYMBOLIZER_PATH");
- if (external_symbolizer) {
- InitializeExternalSymbolizer(external_symbolizer);
- }
+ if (common_flags()->symbolize && &getSymbolizer) {
+ getSymbolizer()
+ ->InitializeExternal(common_flags()->external_symbolizer_path);
}
// On Linux AsanThread::ThreadStart() calls malloc() that's why asan_inited
@@ -509,11 +549,24 @@ void __asan_init() {
asan_inited = 1;
asan_init_is_running = false;
- asanThreadRegistry().Init();
- asanThreadRegistry().GetMain()->ThreadStart();
+ InitTlsSize();
+
+ // Create main thread.
+ AsanThread *main_thread = AsanThread::Create(0, 0);
+ CreateThreadContextArgs create_main_args = { main_thread, 0 };
+ u32 main_tid = asanThreadRegistry().CreateThread(
+ 0, true, 0, &create_main_args);
+ CHECK_EQ(0, main_tid);
+ SetCurrentThread(main_thread);
+ main_thread->ThreadStart(internal_getpid());
force_interface_symbols(); // no-op.
- InitializeAllocator();
+#if CAN_SANITIZE_LEAKS
+ __lsan::InitCommonLsan();
+ if (common_flags()->detect_leaks && common_flags()->leak_check_at_exit) {
+ Atexit(__lsan::DoLeakCheck);
+ }
+#endif // CAN_SANITIZE_LEAKS
if (flags()->verbosity) {
Report("AddressSanitizer Init done\n");
diff --git a/libsanitizer/asan/asan_stack.cc b/libsanitizer/asan/asan_stack.cc
index 999cbfba757..74952518642 100644
--- a/libsanitizer/asan/asan_stack.cc
+++ b/libsanitizer/asan/asan_stack.cc
@@ -12,6 +12,7 @@
#include "asan_internal.h"
#include "asan_flags.h"
#include "asan_stack.h"
+#include "sanitizer_common/sanitizer_flags.h"
namespace __asan {
@@ -22,8 +23,8 @@ static bool MaybeCallAsanSymbolize(const void *pc, char *out_buffer,
}
void PrintStack(StackTrace *stack) {
- stack->PrintStack(stack->trace, stack->size, flags()->symbolize,
- flags()->strip_path_prefix, MaybeCallAsanSymbolize);
+ stack->PrintStack(stack->trace, stack->size, common_flags()->symbolize,
+ common_flags()->strip_path_prefix, MaybeCallAsanSymbolize);
}
} // namespace __asan
@@ -33,8 +34,8 @@ void PrintStack(StackTrace *stack) {
// Provide default implementation of __asan_symbolize that does nothing
// and may be overriden by user if he wants to use his own symbolization.
// ASan on Windows has its own implementation of this.
-#if !defined(_WIN32) && !SANITIZER_SUPPORTS_WEAK_HOOKS
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE NOINLINE
+#if !SANITIZER_WINDOWS && !SANITIZER_SUPPORTS_WEAK_HOOKS
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE NOINLINE
bool __asan_symbolize(const void *pc, char *out_buffer, int out_size) {
return false;
}
diff --git a/libsanitizer/asan/asan_stack.h b/libsanitizer/asan/asan_stack.h
index 6a5ffc934cc..3c0ac31f6c6 100644
--- a/libsanitizer/asan/asan_stack.h
+++ b/libsanitizer/asan/asan_stack.h
@@ -12,12 +12,13 @@
#ifndef ASAN_STACK_H
#define ASAN_STACK_H
-#include "sanitizer_common/sanitizer_stacktrace.h"
#include "asan_flags.h"
+#include "asan_thread.h"
+#include "sanitizer_common/sanitizer_flags.h"
+#include "sanitizer_common/sanitizer_stacktrace.h"
namespace __asan {
-void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp, bool fast);
void PrintStack(StackTrace *stack);
} // namespace __asan
@@ -25,10 +26,24 @@ void PrintStack(StackTrace *stack);
// Get the stack trace with the given pc and bp.
// The pc will be in the position 0 of the resulting stack trace.
// The bp may refer to the current frame or to the caller's frame.
-// fast_unwind is currently unused.
-#define GET_STACK_TRACE_WITH_PC_AND_BP(max_s, pc, bp, fast) \
- StackTrace stack; \
- GetStackTrace(&stack, max_s, pc, bp, fast)
+#if SANITIZER_WINDOWS
+#define GET_STACK_TRACE_WITH_PC_AND_BP(max_s, pc, bp, fast) \
+ StackTrace stack; \
+ GetStackTrace(&stack, max_s, pc, bp, 0, 0, fast)
+#else
+#define GET_STACK_TRACE_WITH_PC_AND_BP(max_s, pc, bp, fast) \
+ StackTrace stack; \
+ { \
+ AsanThread *t; \
+ stack.size = 0; \
+ if (asan_inited && (t = GetCurrentThread()) && !t->isUnwinding()) { \
+ uptr stack_top = t->stack_top(); \
+ uptr stack_bottom = t->stack_bottom(); \
+ ScopedUnwinding unwind_scope(t); \
+ GetStackTrace(&stack, max_s, pc, bp, stack_top, stack_bottom, fast); \
+ } \
+ }
+#endif // SANITIZER_WINDOWS
// NOTE: A Rule of thumb is to retrieve stack trace in the interceptors
// as early as possible (in functions exposed to the user), as we generally
@@ -40,24 +55,24 @@ void PrintStack(StackTrace *stack);
#define GET_STACK_TRACE_FATAL(pc, bp) \
GET_STACK_TRACE_WITH_PC_AND_BP(kStackTraceMax, pc, bp, \
- flags()->fast_unwind_on_fatal)
+ common_flags()->fast_unwind_on_fatal)
-#define GET_STACK_TRACE_FATAL_HERE \
- GET_STACK_TRACE(kStackTraceMax, flags()->fast_unwind_on_fatal)
+#define GET_STACK_TRACE_FATAL_HERE \
+ GET_STACK_TRACE(kStackTraceMax, common_flags()->fast_unwind_on_fatal)
-#define GET_STACK_TRACE_THREAD \
+#define GET_STACK_TRACE_THREAD \
GET_STACK_TRACE(kStackTraceMax, true)
-#define GET_STACK_TRACE_MALLOC \
- GET_STACK_TRACE(flags()->malloc_context_size, \
- flags()->fast_unwind_on_malloc)
+#define GET_STACK_TRACE_MALLOC \
+ GET_STACK_TRACE(common_flags()->malloc_context_size, \
+ common_flags()->fast_unwind_on_malloc)
#define GET_STACK_TRACE_FREE GET_STACK_TRACE_MALLOC
#define PRINT_CURRENT_STACK() \
{ \
GET_STACK_TRACE(kStackTraceMax, \
- flags()->fast_unwind_on_fatal); \
+ common_flags()->fast_unwind_on_fatal); \
PrintStack(&stack); \
}
diff --git a/libsanitizer/asan/asan_stats.cc b/libsanitizer/asan/asan_stats.cc
index 935b33e20ac..71c8582e81c 100644
--- a/libsanitizer/asan/asan_stats.cc
+++ b/libsanitizer/asan/asan_stats.cc
@@ -12,13 +12,18 @@
#include "asan_interceptors.h"
#include "asan_internal.h"
#include "asan_stats.h"
-#include "asan_thread_registry.h"
+#include "asan_thread.h"
+#include "sanitizer_common/sanitizer_mutex.h"
#include "sanitizer_common/sanitizer_stackdepot.h"
namespace __asan {
AsanStats::AsanStats() {
- CHECK(REAL(memset) != 0);
+ Clear();
+}
+
+void AsanStats::Clear() {
+ CHECK(REAL(memset));
REAL(memset)(this, 0, sizeof(AsanStats));
}
@@ -51,11 +56,73 @@ void AsanStats::Print() {
malloc_large, malloc_small_slow);
}
+void AsanStats::MergeFrom(const AsanStats *stats) {
+ uptr *dst_ptr = reinterpret_cast<uptr*>(this);
+ const uptr *src_ptr = reinterpret_cast<const uptr*>(stats);
+ uptr num_fields = sizeof(*this) / sizeof(uptr);
+ for (uptr i = 0; i < num_fields; i++)
+ dst_ptr[i] += src_ptr[i];
+}
+
static BlockingMutex print_lock(LINKER_INITIALIZED);
+static AsanStats unknown_thread_stats(LINKER_INITIALIZED);
+static AsanStats dead_threads_stats(LINKER_INITIALIZED);
+static BlockingMutex dead_threads_stats_lock(LINKER_INITIALIZED);
+// Required for malloc_zone_statistics() on OS X. This can't be stored in
+// per-thread AsanStats.
+static uptr max_malloced_memory;
+
+static void MergeThreadStats(ThreadContextBase *tctx_base, void *arg) {
+ AsanStats *accumulated_stats = reinterpret_cast<AsanStats*>(arg);
+ AsanThreadContext *tctx = static_cast<AsanThreadContext*>(tctx_base);
+ if (AsanThread *t = tctx->thread)
+ accumulated_stats->MergeFrom(&t->stats());
+}
+
+static void GetAccumulatedStats(AsanStats *stats) {
+ stats->Clear();
+ {
+ ThreadRegistryLock l(&asanThreadRegistry());
+ asanThreadRegistry()
+ .RunCallbackForEachThreadLocked(MergeThreadStats, stats);
+ }
+ stats->MergeFrom(&unknown_thread_stats);
+ {
+ BlockingMutexLock lock(&dead_threads_stats_lock);
+ stats->MergeFrom(&dead_threads_stats);
+ }
+ // This is not very accurate: we may miss allocation peaks that happen
+ // between two updates of accumulated_stats_. For more accurate bookkeeping
+ // the maximum should be updated on every malloc(), which is unacceptable.
+ if (max_malloced_memory < stats->malloced) {
+ max_malloced_memory = stats->malloced;
+ }
+}
+
+void FlushToDeadThreadStats(AsanStats *stats) {
+ BlockingMutexLock lock(&dead_threads_stats_lock);
+ dead_threads_stats.MergeFrom(stats);
+ stats->Clear();
+}
+
+void FillMallocStatistics(AsanMallocStats *malloc_stats) {
+ AsanStats stats;
+ GetAccumulatedStats(&stats);
+ malloc_stats->blocks_in_use = stats.mallocs;
+ malloc_stats->size_in_use = stats.malloced;
+ malloc_stats->max_size_in_use = max_malloced_memory;
+ malloc_stats->size_allocated = stats.mmaped;
+}
+
+AsanStats &GetCurrentThreadStats() {
+ AsanThread *t = GetCurrentThread();
+ return (t) ? t->stats() : unknown_thread_stats;
+}
+
static void PrintAccumulatedStats() {
AsanStats stats;
- asanThreadRegistry().GetAccumulatedStats(&stats);
+ GetAccumulatedStats(&stats);
// Use lock to keep reports from mixing up.
BlockingMutexLock lock(&print_lock);
stats.Print();
@@ -71,15 +138,33 @@ static void PrintAccumulatedStats() {
using namespace __asan; // NOLINT
uptr __asan_get_current_allocated_bytes() {
- return asanThreadRegistry().GetCurrentAllocatedBytes();
+ AsanStats stats;
+ GetAccumulatedStats(&stats);
+ uptr malloced = stats.malloced;
+ uptr freed = stats.freed;
+ // Return sane value if malloced < freed due to racy
+ // way we update accumulated stats.
+ return (malloced > freed) ? malloced - freed : 1;
}
uptr __asan_get_heap_size() {
- return asanThreadRegistry().GetHeapSize();
+ AsanStats stats;
+ GetAccumulatedStats(&stats);
+ return stats.mmaped - stats.munmaped;
}
uptr __asan_get_free_bytes() {
- return asanThreadRegistry().GetFreeBytes();
+ AsanStats stats;
+ GetAccumulatedStats(&stats);
+ uptr total_free = stats.mmaped
+ - stats.munmaped
+ + stats.really_freed
+ + stats.really_freed_redzones;
+ uptr total_used = stats.malloced
+ + stats.malloced_redzones;
+ // Return sane value if total_free < total_used due to racy
+ // way we update accumulated stats.
+ return (total_free > total_used) ? total_free - total_used : 1;
}
uptr __asan_get_unmapped_bytes() {
diff --git a/libsanitizer/asan/asan_stats.h b/libsanitizer/asan/asan_stats.h
index fd27451aef2..2f964f8d052 100644
--- a/libsanitizer/asan/asan_stats.h
+++ b/libsanitizer/asan/asan_stats.h
@@ -50,10 +50,17 @@ struct AsanStats {
// Default ctor for thread-local stats.
AsanStats();
- // Prints formatted stats to stderr.
- void Print();
+ void Print(); // Prints formatted stats to stderr.
+ void Clear();
+ void MergeFrom(const AsanStats *stats);
};
+// Returns stats for GetCurrentThread(), or stats for fake "unknown thread"
+// if GetCurrentThread() returns 0.
+AsanStats &GetCurrentThreadStats();
+// Flushes a given stats into accumulated stats of dead threads.
+void FlushToDeadThreadStats(AsanStats *stats);
+
// A cross-platform equivalent of malloc_statistics_t on Mac OS.
struct AsanMallocStats {
uptr blocks_in_use;
@@ -62,6 +69,8 @@ struct AsanMallocStats {
uptr size_allocated;
};
+void FillMallocStatistics(AsanMallocStats *malloc_stats);
+
} // namespace __asan
#endif // ASAN_STATS_H
diff --git a/libsanitizer/asan/asan_thread.cc b/libsanitizer/asan/asan_thread.cc
index 02f49dd59ef..1da714c6013 100644
--- a/libsanitizer/asan/asan_thread.cc
+++ b/libsanitizer/asan/asan_thread.cc
@@ -11,46 +11,82 @@
//===----------------------------------------------------------------------===//
#include "asan_allocator.h"
#include "asan_interceptors.h"
+#include "asan_poisoning.h"
#include "asan_stack.h"
#include "asan_thread.h"
-#include "asan_thread_registry.h"
#include "asan_mapping.h"
#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_placement_new.h"
+#include "lsan/lsan_common.h"
namespace __asan {
-AsanThread::AsanThread(LinkerInitialized x)
- : fake_stack_(x),
- malloc_storage_(x),
- stats_(x) { }
+// AsanThreadContext implementation.
-AsanThread *AsanThread::Create(u32 parent_tid, thread_callback_t start_routine,
- void *arg, StackTrace *stack) {
+void AsanThreadContext::OnCreated(void *arg) {
+ CreateThreadContextArgs *args = static_cast<CreateThreadContextArgs*>(arg);
+ if (args->stack) {
+ internal_memcpy(&stack, args->stack, sizeof(stack));
+ }
+ thread = args->thread;
+ thread->set_context(this);
+}
+
+void AsanThreadContext::OnFinished() {
+ // Drop the link to the AsanThread object.
+ thread = 0;
+}
+
+// MIPS requires aligned address
+static ALIGNED(16) char thread_registry_placeholder[sizeof(ThreadRegistry)];
+static ThreadRegistry *asan_thread_registry;
+
+static ThreadContextBase *GetAsanThreadContext(u32 tid) {
+ void *mem = MmapOrDie(sizeof(AsanThreadContext), "AsanThreadContext");
+ return new(mem) AsanThreadContext(tid);
+}
+
+ThreadRegistry &asanThreadRegistry() {
+ static bool initialized;
+ // Don't worry about thread_safety - this should be called when there is
+ // a single thread.
+ if (!initialized) {
+ // Never reuse ASan threads: we store pointer to AsanThreadContext
+ // in TSD and can't reliably tell when no more TSD destructors will
+ // be called. It would be wrong to reuse AsanThreadContext for another
+ // thread before all TSD destructors will be called for it.
+ asan_thread_registry = new(thread_registry_placeholder) ThreadRegistry(
+ GetAsanThreadContext, kMaxNumberOfThreads, kMaxNumberOfThreads);
+ initialized = true;
+ }
+ return *asan_thread_registry;
+}
+
+AsanThreadContext *GetThreadContextByTidLocked(u32 tid) {
+ return static_cast<AsanThreadContext *>(
+ asanThreadRegistry().GetThreadLocked(tid));
+}
+
+// AsanThread implementation.
+
+AsanThread *AsanThread::Create(thread_callback_t start_routine,
+ void *arg) {
uptr PageSize = GetPageSizeCached();
uptr size = RoundUpTo(sizeof(AsanThread), PageSize);
AsanThread *thread = (AsanThread*)MmapOrDie(size, __FUNCTION__);
thread->start_routine_ = start_routine;
thread->arg_ = arg;
-
- const uptr kSummaryAllocSize = PageSize;
- CHECK_LE(sizeof(AsanThreadSummary), kSummaryAllocSize);
- AsanThreadSummary *summary =
- (AsanThreadSummary*)MmapOrDie(PageSize, "AsanThreadSummary");
- summary->Init(parent_tid, stack);
- summary->set_thread(thread);
- thread->set_summary(summary);
+ thread->context_ = 0;
return thread;
}
-void AsanThreadSummary::TSDDtor(void *tsd) {
- AsanThreadSummary *summary = (AsanThreadSummary*)tsd;
- if (flags()->verbosity >= 1) {
- Report("T%d TSDDtor\n", summary->tid());
- }
- if (summary->thread()) {
- summary->thread()->Destroy();
- }
+void AsanThread::TSDDtor(void *tsd) {
+ AsanThreadContext *context = (AsanThreadContext*)tsd;
+ if (flags()->verbosity >= 1)
+ Report("T%d TSDDtor\n", context->tid);
+ if (context->thread)
+ context->thread->Destroy();
}
void AsanThread::Destroy() {
@@ -58,41 +94,68 @@ void AsanThread::Destroy() {
Report("T%d exited\n", tid());
}
- asanThreadRegistry().UnregisterThread(this);
- CHECK(summary()->thread() == 0);
+ asanThreadRegistry().FinishThread(tid());
+ FlushToDeadThreadStats(&stats_);
// We also clear the shadow on thread destruction because
// some code may still be executing in later TSD destructors
// and we don't want it to have any poisoned stack.
- ClearShadowForThreadStack();
- fake_stack().Cleanup();
+ ClearShadowForThreadStackAndTLS();
+ DeleteFakeStack();
uptr size = RoundUpTo(sizeof(AsanThread), GetPageSizeCached());
UnmapOrDie(this, size);
}
+// We want to create the FakeStack lazyly on the first use, but not eralier
+// than the stack size is known and the procedure has to be async-signal safe.
+FakeStack *AsanThread::AsyncSignalSafeLazyInitFakeStack() {
+ uptr stack_size = this->stack_size();
+ if (stack_size == 0) // stack_size is not yet available, don't use FakeStack.
+ return 0;
+ uptr old_val = 0;
+ // fake_stack_ has 3 states:
+ // 0 -- not initialized
+ // 1 -- being initialized
+ // ptr -- initialized
+ // This CAS checks if the state was 0 and if so changes it to state 1,
+ // if that was successfull, it initilizes the pointer.
+ if (atomic_compare_exchange_strong(
+ reinterpret_cast<atomic_uintptr_t *>(&fake_stack_), &old_val, 1UL,
+ memory_order_relaxed)) {
+ uptr stack_size_log = Log2(RoundUpToPowerOfTwo(stack_size));
+ if (flags()->uar_stack_size_log)
+ stack_size_log = static_cast<uptr>(flags()->uar_stack_size_log);
+ fake_stack_ = FakeStack::Create(stack_size_log);
+ SetTLSFakeStack(fake_stack_);
+ return fake_stack_;
+ }
+ return 0;
+}
+
void AsanThread::Init() {
- SetThreadStackTopAndBottom();
+ SetThreadStackAndTls();
CHECK(AddrIsInMem(stack_bottom_));
CHECK(AddrIsInMem(stack_top_ - 1));
- ClearShadowForThreadStack();
+ ClearShadowForThreadStackAndTLS();
if (flags()->verbosity >= 1) {
int local = 0;
Report("T%d: stack [%p,%p) size 0x%zx; local=%p\n",
tid(), (void*)stack_bottom_, (void*)stack_top_,
stack_top_ - stack_bottom_, &local);
}
- fake_stack_.Init(stack_size());
+ fake_stack_ = 0; // Will be initialized lazily if needed.
AsanPlatformThreadInit();
}
-thread_return_t AsanThread::ThreadStart() {
+thread_return_t AsanThread::ThreadStart(uptr os_id) {
Init();
+ asanThreadRegistry().StartThread(tid(), os_id, 0);
if (flags()->use_sigaltstack) SetAlternateSignalStack();
if (!start_routine_) {
// start_routine_ == 0 if we're on the main thread or on one of the
// OS X libdispatch worker threads. But nobody is supposed to call
// ThreadStart() for the worker threads.
- CHECK(tid() == 0);
+ CHECK_EQ(tid(), 0);
return 0;
}
@@ -105,24 +168,33 @@ thread_return_t AsanThread::ThreadStart() {
return res;
}
-void AsanThread::SetThreadStackTopAndBottom() {
- GetThreadStackTopAndBottom(tid() == 0, &stack_top_, &stack_bottom_);
+void AsanThread::SetThreadStackAndTls() {
+ uptr tls_size = 0;
+ GetThreadStackAndTls(tid() == 0, &stack_bottom_, &stack_size_, &tls_begin_,
+ &tls_size);
+ stack_top_ = stack_bottom_ + stack_size_;
+ tls_end_ = tls_begin_ + tls_size;
+
int local;
CHECK(AddrIsInStack((uptr)&local));
}
-void AsanThread::ClearShadowForThreadStack() {
+void AsanThread::ClearShadowForThreadStackAndTLS() {
PoisonShadow(stack_bottom_, stack_top_ - stack_bottom_, 0);
+ if (tls_begin_ != tls_end_)
+ PoisonShadow(tls_begin_, tls_end_ - tls_begin_, 0);
}
-const char *AsanThread::GetFrameNameByAddr(uptr addr, uptr *offset) {
+const char *AsanThread::GetFrameNameByAddr(uptr addr, uptr *offset,
+ uptr *frame_pc) {
uptr bottom = 0;
if (AddrIsInStack(addr)) {
bottom = stack_bottom();
- } else {
- bottom = fake_stack().AddrIsInFakeStack(addr);
+ } else if (has_fake_stack()) {
+ bottom = fake_stack()->AddrIsInFakeStack(addr);
CHECK(bottom);
*offset = addr - bottom;
+ *frame_pc = ((uptr*)bottom)[2];
return (const char *)((uptr*)bottom)[1];
}
uptr aligned_addr = addr & ~(SANITIZER_WORDSIZE/8 - 1); // align addr.
@@ -147,7 +219,104 @@ const char *AsanThread::GetFrameNameByAddr(uptr addr, uptr *offset) {
uptr* ptr = (uptr*)SHADOW_TO_MEM((uptr)(shadow_ptr + 1));
CHECK(ptr[0] == kCurrentStackFrameMagic);
*offset = addr - (uptr)ptr;
+ *frame_pc = ptr[2];
return (const char*)ptr[1];
}
+static bool ThreadStackContainsAddress(ThreadContextBase *tctx_base,
+ void *addr) {
+ AsanThreadContext *tctx = static_cast<AsanThreadContext*>(tctx_base);
+ AsanThread *t = tctx->thread;
+ if (!t) return false;
+ if (t->AddrIsInStack((uptr)addr)) return true;
+ if (t->has_fake_stack() && t->fake_stack()->AddrIsInFakeStack((uptr)addr))
+ return true;
+ return false;
+}
+
+AsanThread *GetCurrentThread() {
+ AsanThreadContext *context =
+ reinterpret_cast<AsanThreadContext *>(AsanTSDGet());
+ if (!context) {
+ if (SANITIZER_ANDROID) {
+ // On Android, libc constructor is called _after_ asan_init, and cleans up
+ // TSD. Try to figure out if this is still the main thread by the stack
+ // address. We are not entirely sure that we have correct main thread
+ // limits, so only do this magic on Android, and only if the found thread
+ // is the main thread.
+ AsanThreadContext *tctx = GetThreadContextByTidLocked(0);
+ if (ThreadStackContainsAddress(tctx, &context)) {
+ SetCurrentThread(tctx->thread);
+ return tctx->thread;
+ }
+ }
+ return 0;
+ }
+ return context->thread;
+}
+
+void SetCurrentThread(AsanThread *t) {
+ CHECK(t->context());
+ if (flags()->verbosity >= 2) {
+ Report("SetCurrentThread: %p for thread %p\n",
+ t->context(), (void*)GetThreadSelf());
+ }
+ // Make sure we do not reset the current AsanThread.
+ CHECK_EQ(0, AsanTSDGet());
+ AsanTSDSet(t->context());
+ CHECK_EQ(t->context(), AsanTSDGet());
+}
+
+u32 GetCurrentTidOrInvalid() {
+ AsanThread *t = GetCurrentThread();
+ return t ? t->tid() : kInvalidTid;
+}
+
+AsanThread *FindThreadByStackAddress(uptr addr) {
+ asanThreadRegistry().CheckLocked();
+ AsanThreadContext *tctx = static_cast<AsanThreadContext *>(
+ asanThreadRegistry().FindThreadContextLocked(ThreadStackContainsAddress,
+ (void *)addr));
+ return tctx ? tctx->thread : 0;
+}
+
+void EnsureMainThreadIDIsCorrect() {
+ AsanThreadContext *context =
+ reinterpret_cast<AsanThreadContext *>(AsanTSDGet());
+ if (context && (context->tid == 0))
+ context->os_id = GetTid();
+}
} // namespace __asan
+
+// --- Implementation of LSan-specific functions --- {{{1
+namespace __lsan {
+bool GetThreadRangesLocked(uptr os_id, uptr *stack_begin, uptr *stack_end,
+ uptr *tls_begin, uptr *tls_end,
+ uptr *cache_begin, uptr *cache_end) {
+ __asan::AsanThreadContext *context = static_cast<__asan::AsanThreadContext *>(
+ __asan::asanThreadRegistry().FindThreadContextByOsIDLocked(os_id));
+ if (!context) return false;
+ __asan::AsanThread *t = context->thread;
+ if (!t) return false;
+ *stack_begin = t->stack_bottom();
+ *stack_end = t->stack_top();
+ *tls_begin = t->tls_begin();
+ *tls_end = t->tls_end();
+ // ASan doesn't keep allocator caches in TLS, so these are unused.
+ *cache_begin = 0;
+ *cache_end = 0;
+ return true;
+}
+
+void LockThreadRegistry() {
+ __asan::asanThreadRegistry().Lock();
+}
+
+void UnlockThreadRegistry() {
+ __asan::asanThreadRegistry().Unlock();
+}
+
+void EnsureMainThreadIDIsCorrect() {
+ __asan::EnsureMainThreadIDIsCorrect();
+}
+} // namespace __lsan
diff --git a/libsanitizer/asan/asan_thread.h b/libsanitizer/asan/asan_thread.h
index f385ec35fcd..f21971ff430 100644
--- a/libsanitizer/asan/asan_thread.h
+++ b/libsanitizer/asan/asan_thread.h
@@ -14,99 +14,148 @@
#include "asan_allocator.h"
#include "asan_internal.h"
+#include "asan_fake_stack.h"
#include "asan_stack.h"
#include "asan_stats.h"
#include "sanitizer_common/sanitizer_libc.h"
+#include "sanitizer_common/sanitizer_thread_registry.h"
namespace __asan {
const u32 kInvalidTid = 0xffffff; // Must fit into 24 bits.
+const u32 kMaxNumberOfThreads = (1 << 22); // 4M
class AsanThread;
// These objects are created for every thread and are never deleted,
// so we can find them by tid even if the thread is long dead.
-class AsanThreadSummary {
+class AsanThreadContext : public ThreadContextBase {
public:
- explicit AsanThreadSummary(LinkerInitialized) { } // for T0.
- void Init(u32 parent_tid, StackTrace *stack) {
- parent_tid_ = parent_tid;
- announced_ = false;
- tid_ = kInvalidTid;
- if (stack) {
- internal_memcpy(&stack_, stack, sizeof(*stack));
- }
- thread_ = 0;
- name_[0] = 0;
+ explicit AsanThreadContext(int tid)
+ : ThreadContextBase(tid),
+ announced(false),
+ thread(0) {
+ internal_memset(&stack, 0, sizeof(stack));
}
- u32 tid() { return tid_; }
- void set_tid(u32 tid) { tid_ = tid; }
- u32 parent_tid() { return parent_tid_; }
- bool announced() { return announced_; }
- void set_announced(bool announced) { announced_ = announced; }
- StackTrace *stack() { return &stack_; }
- AsanThread *thread() { return thread_; }
- void set_thread(AsanThread *thread) { thread_ = thread; }
- static void TSDDtor(void *tsd);
- void set_name(const char *name) {
- internal_strncpy(name_, name, sizeof(name_) - 1);
- }
- const char *name() { return name_; }
+ bool announced;
+ StackTrace stack;
+ AsanThread *thread;
- private:
- u32 tid_;
- u32 parent_tid_;
- bool announced_;
- StackTrace stack_;
- AsanThread *thread_;
- char name_[128];
+ void OnCreated(void *arg);
+ void OnFinished();
};
-// AsanThreadSummary objects are never freed, so we need many of them.
-COMPILER_CHECK(sizeof(AsanThreadSummary) <= 4094);
+// AsanThreadContext objects are never freed, so we need many of them.
+COMPILER_CHECK(sizeof(AsanThreadContext) <= 4096);
// AsanThread are stored in TSD and destroyed when the thread dies.
class AsanThread {
public:
- explicit AsanThread(LinkerInitialized); // for T0.
- static AsanThread *Create(u32 parent_tid, thread_callback_t start_routine,
- void *arg, StackTrace *stack);
+ static AsanThread *Create(thread_callback_t start_routine, void *arg);
+ static void TSDDtor(void *tsd);
void Destroy();
void Init(); // Should be called from the thread itself.
- thread_return_t ThreadStart();
+ thread_return_t ThreadStart(uptr os_id);
uptr stack_top() { return stack_top_; }
uptr stack_bottom() { return stack_bottom_; }
- uptr stack_size() { return stack_top_ - stack_bottom_; }
- u32 tid() { return summary_->tid(); }
- AsanThreadSummary *summary() { return summary_; }
- void set_summary(AsanThreadSummary *summary) { summary_ = summary; }
+ uptr stack_size() { return stack_size_; }
+ uptr tls_begin() { return tls_begin_; }
+ uptr tls_end() { return tls_end_; }
+ u32 tid() { return context_->tid; }
+ AsanThreadContext *context() { return context_; }
+ void set_context(AsanThreadContext *context) { context_ = context; }
- const char *GetFrameNameByAddr(uptr addr, uptr *offset);
+ const char *GetFrameNameByAddr(uptr addr, uptr *offset, uptr *frame_pc);
bool AddrIsInStack(uptr addr) {
return addr >= stack_bottom_ && addr < stack_top_;
}
- FakeStack &fake_stack() { return fake_stack_; }
+ void DeleteFakeStack() {
+ if (!fake_stack_) return;
+ FakeStack *t = fake_stack_;
+ fake_stack_ = 0;
+ SetTLSFakeStack(0);
+ t->Destroy();
+ }
+
+ bool has_fake_stack() {
+ return (reinterpret_cast<uptr>(fake_stack_) > 1);
+ }
+
+ FakeStack *fake_stack() {
+ if (!__asan_option_detect_stack_use_after_return)
+ return 0;
+ if (!has_fake_stack())
+ return AsyncSignalSafeLazyInitFakeStack();
+ return fake_stack_;
+ }
+
+ // True is this thread is currently unwinding stack (i.e. collecting a stack
+ // trace). Used to prevent deadlocks on platforms where libc unwinder calls
+ // malloc internally. See PR17116 for more details.
+ bool isUnwinding() const { return unwinding; }
+ void setUnwinding(bool b) { unwinding = b; }
+
AsanThreadLocalMallocStorage &malloc_storage() { return malloc_storage_; }
AsanStats &stats() { return stats_; }
private:
- void SetThreadStackTopAndBottom();
- void ClearShadowForThreadStack();
- AsanThreadSummary *summary_;
+ AsanThread() : unwinding(false) {}
+ void SetThreadStackAndTls();
+ void ClearShadowForThreadStackAndTLS();
+ FakeStack *AsyncSignalSafeLazyInitFakeStack();
+
+ AsanThreadContext *context_;
thread_callback_t start_routine_;
void *arg_;
uptr stack_top_;
uptr stack_bottom_;
+ // stack_size_ == stack_top_ - stack_bottom_;
+ // It needs to be set in a async-signal-safe manner.
+ uptr stack_size_;
+ uptr tls_begin_;
+ uptr tls_end_;
- FakeStack fake_stack_;
+ FakeStack *fake_stack_;
AsanThreadLocalMallocStorage malloc_storage_;
AsanStats stats_;
+ bool unwinding;
};
+// ScopedUnwinding is a scope for stacktracing member of a context
+class ScopedUnwinding {
+ public:
+ explicit ScopedUnwinding(AsanThread *t) : thread(t) {
+ t->setUnwinding(true);
+ }
+ ~ScopedUnwinding() { thread->setUnwinding(false); }
+
+ private:
+ AsanThread *thread;
+};
+
+struct CreateThreadContextArgs {
+ AsanThread *thread;
+ StackTrace *stack;
+};
+
+// Returns a single instance of registry.
+ThreadRegistry &asanThreadRegistry();
+
+// Must be called under ThreadRegistryLock.
+AsanThreadContext *GetThreadContextByTidLocked(u32 tid);
+
+// Get the current thread. May return 0.
+AsanThread *GetCurrentThread();
+void SetCurrentThread(AsanThread *t);
+u32 GetCurrentTidOrInvalid();
+AsanThread *FindThreadByStackAddress(uptr addr);
+
+// Used to handle fork().
+void EnsureMainThreadIDIsCorrect();
} // namespace __asan
#endif // ASAN_THREAD_H
diff --git a/libsanitizer/asan/asan_thread_registry.cc b/libsanitizer/asan/asan_thread_registry.cc
deleted file mode 100644
index 8fda9b6ea0a..00000000000
--- a/libsanitizer/asan/asan_thread_registry.cc
+++ /dev/null
@@ -1,196 +0,0 @@
-//===-- asan_thread_registry.cc -------------------------------------------===//
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file is a part of AddressSanitizer, an address sanity checker.
-//
-// AsanThreadRegistry-related code. AsanThreadRegistry is a container
-// for summaries of all created threads.
-//===----------------------------------------------------------------------===//
-
-#include "asan_stack.h"
-#include "asan_thread.h"
-#include "asan_thread_registry.h"
-#include "sanitizer_common/sanitizer_common.h"
-
-namespace __asan {
-
-static AsanThreadRegistry asan_thread_registry(LINKER_INITIALIZED);
-
-AsanThreadRegistry &asanThreadRegistry() {
- return asan_thread_registry;
-}
-
-AsanThreadRegistry::AsanThreadRegistry(LinkerInitialized x)
- : main_thread_(x),
- main_thread_summary_(x),
- accumulated_stats_(x),
- max_malloced_memory_(x),
- mu_(x) { }
-
-void AsanThreadRegistry::Init() {
- AsanTSDInit(AsanThreadSummary::TSDDtor);
- main_thread_.set_summary(&main_thread_summary_);
- main_thread_summary_.set_thread(&main_thread_);
- RegisterThread(&main_thread_);
- SetCurrent(&main_thread_);
- // At this point only one thread exists.
- inited_ = true;
-}
-
-void AsanThreadRegistry::RegisterThread(AsanThread *thread) {
- BlockingMutexLock lock(&mu_);
- u32 tid = n_threads_;
- n_threads_++;
- CHECK(n_threads_ < kMaxNumberOfThreads);
-
- AsanThreadSummary *summary = thread->summary();
- CHECK(summary != 0);
- summary->set_tid(tid);
- thread_summaries_[tid] = summary;
-}
-
-void AsanThreadRegistry::UnregisterThread(AsanThread *thread) {
- BlockingMutexLock lock(&mu_);
- FlushToAccumulatedStatsUnlocked(&thread->stats());
- AsanThreadSummary *summary = thread->summary();
- CHECK(summary);
- summary->set_thread(0);
-}
-
-AsanThread *AsanThreadRegistry::GetMain() {
- return &main_thread_;
-}
-
-AsanThread *AsanThreadRegistry::GetCurrent() {
- AsanThreadSummary *summary = (AsanThreadSummary *)AsanTSDGet();
- if (!summary) {
-#if ASAN_ANDROID
- // On Android, libc constructor is called _after_ asan_init, and cleans up
- // TSD. Try to figure out if this is still the main thread by the stack
- // address. We are not entirely sure that we have correct main thread
- // limits, so only do this magic on Android, and only if the found thread is
- // the main thread.
- AsanThread* thread = FindThreadByStackAddress((uptr)&summary);
- if (thread && thread->tid() == 0) {
- SetCurrent(thread);
- return thread;
- }
-#endif
- return 0;
- }
- return summary->thread();
-}
-
-void AsanThreadRegistry::SetCurrent(AsanThread *t) {
- CHECK(t->summary());
- if (flags()->verbosity >= 2) {
- Report("SetCurrent: %p for thread %p\n",
- t->summary(), (void*)GetThreadSelf());
- }
- // Make sure we do not reset the current AsanThread.
- CHECK(AsanTSDGet() == 0);
- AsanTSDSet(t->summary());
- CHECK(AsanTSDGet() == t->summary());
-}
-
-AsanStats &AsanThreadRegistry::GetCurrentThreadStats() {
- AsanThread *t = GetCurrent();
- return (t) ? t->stats() : main_thread_.stats();
-}
-
-void AsanThreadRegistry::GetAccumulatedStats(AsanStats *stats) {
- BlockingMutexLock lock(&mu_);
- UpdateAccumulatedStatsUnlocked();
- internal_memcpy(stats, &accumulated_stats_, sizeof(accumulated_stats_));
-}
-
-uptr AsanThreadRegistry::GetCurrentAllocatedBytes() {
- BlockingMutexLock lock(&mu_);
- UpdateAccumulatedStatsUnlocked();
- uptr malloced = accumulated_stats_.malloced;
- uptr freed = accumulated_stats_.freed;
- // Return sane value if malloced < freed due to racy
- // way we update accumulated stats.
- return (malloced > freed) ? malloced - freed : 1;
-}
-
-uptr AsanThreadRegistry::GetHeapSize() {
- BlockingMutexLock lock(&mu_);
- UpdateAccumulatedStatsUnlocked();
- return accumulated_stats_.mmaped - accumulated_stats_.munmaped;
-}
-
-uptr AsanThreadRegistry::GetFreeBytes() {
- BlockingMutexLock lock(&mu_);
- UpdateAccumulatedStatsUnlocked();
- uptr total_free = accumulated_stats_.mmaped
- - accumulated_stats_.munmaped
- + accumulated_stats_.really_freed
- + accumulated_stats_.really_freed_redzones;
- uptr total_used = accumulated_stats_.malloced
- + accumulated_stats_.malloced_redzones;
- // Return sane value if total_free < total_used due to racy
- // way we update accumulated stats.
- return (total_free > total_used) ? total_free - total_used : 1;
-}
-
-// Return several stats counters with a single call to
-// UpdateAccumulatedStatsUnlocked().
-void AsanThreadRegistry::FillMallocStatistics(AsanMallocStats *malloc_stats) {
- BlockingMutexLock lock(&mu_);
- UpdateAccumulatedStatsUnlocked();
- malloc_stats->blocks_in_use = accumulated_stats_.mallocs;
- malloc_stats->size_in_use = accumulated_stats_.malloced;
- malloc_stats->max_size_in_use = max_malloced_memory_;
- malloc_stats->size_allocated = accumulated_stats_.mmaped;
-}
-
-AsanThreadSummary *AsanThreadRegistry::FindByTid(u32 tid) {
- CHECK(tid < n_threads_);
- CHECK(thread_summaries_[tid]);
- return thread_summaries_[tid];
-}
-
-AsanThread *AsanThreadRegistry::FindThreadByStackAddress(uptr addr) {
- BlockingMutexLock lock(&mu_);
- for (u32 tid = 0; tid < n_threads_; tid++) {
- AsanThread *t = thread_summaries_[tid]->thread();
- if (!t || !(t->fake_stack().StackSize())) continue;
- if (t->fake_stack().AddrIsInFakeStack(addr) || t->AddrIsInStack(addr)) {
- return t;
- }
- }
- return 0;
-}
-
-void AsanThreadRegistry::UpdateAccumulatedStatsUnlocked() {
- for (u32 tid = 0; tid < n_threads_; tid++) {
- AsanThread *t = thread_summaries_[tid]->thread();
- if (t != 0) {
- FlushToAccumulatedStatsUnlocked(&t->stats());
- }
- }
- // This is not very accurate: we may miss allocation peaks that happen
- // between two updates of accumulated_stats_. For more accurate bookkeeping
- // the maximum should be updated on every malloc(), which is unacceptable.
- if (max_malloced_memory_ < accumulated_stats_.malloced) {
- max_malloced_memory_ = accumulated_stats_.malloced;
- }
-}
-
-void AsanThreadRegistry::FlushToAccumulatedStatsUnlocked(AsanStats *stats) {
- // AsanStats consists of variables of type uptr only.
- uptr *dst = (uptr*)&accumulated_stats_;
- uptr *src = (uptr*)stats;
- uptr num_fields = sizeof(AsanStats) / sizeof(uptr);
- for (uptr i = 0; i < num_fields; i++) {
- dst[i] += src[i];
- src[i] = 0;
- }
-}
-
-} // namespace __asan
diff --git a/libsanitizer/asan/asan_thread_registry.h b/libsanitizer/asan/asan_thread_registry.h
deleted file mode 100644
index 8c3d0c886e0..00000000000
--- a/libsanitizer/asan/asan_thread_registry.h
+++ /dev/null
@@ -1,83 +0,0 @@
-//===-- asan_thread_registry.h ----------------------------------*- C++ -*-===//
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file is a part of AddressSanitizer, an address sanity checker.
-//
-// ASan-private header for asan_thread_registry.cc
-//===----------------------------------------------------------------------===//
-
-#ifndef ASAN_THREAD_REGISTRY_H
-#define ASAN_THREAD_REGISTRY_H
-
-#include "asan_stack.h"
-#include "asan_stats.h"
-#include "asan_thread.h"
-#include "sanitizer_common/sanitizer_mutex.h"
-
-namespace __asan {
-
-// Stores summaries of all created threads, returns current thread,
-// thread by tid, thread by stack address. There is a single instance
-// of AsanThreadRegistry for the whole program.
-// AsanThreadRegistry is thread-safe.
-class AsanThreadRegistry {
- public:
- explicit AsanThreadRegistry(LinkerInitialized);
- void Init();
- void RegisterThread(AsanThread *thread);
- void UnregisterThread(AsanThread *thread);
-
- AsanThread *GetMain();
- // Get the current thread. May return 0.
- AsanThread *GetCurrent();
- void SetCurrent(AsanThread *t);
-
- u32 GetCurrentTidOrInvalid() {
- if (!inited_) return 0;
- AsanThread *t = GetCurrent();
- return t ? t->tid() : kInvalidTid;
- }
-
- // Returns stats for GetCurrent(), or stats for
- // T0 if GetCurrent() returns 0.
- AsanStats &GetCurrentThreadStats();
- // Flushes all thread-local stats to accumulated stats, and makes
- // a copy of accumulated stats.
- void GetAccumulatedStats(AsanStats *stats);
- uptr GetCurrentAllocatedBytes();
- uptr GetHeapSize();
- uptr GetFreeBytes();
- void FillMallocStatistics(AsanMallocStats *malloc_stats);
-
- AsanThreadSummary *FindByTid(u32 tid);
- AsanThread *FindThreadByStackAddress(uptr addr);
-
- private:
- void UpdateAccumulatedStatsUnlocked();
- // Adds values of all counters in "stats" to accumulated stats,
- // and fills "stats" with zeroes.
- void FlushToAccumulatedStatsUnlocked(AsanStats *stats);
-
- static const u32 kMaxNumberOfThreads = (1 << 22); // 4M
- AsanThreadSummary *thread_summaries_[kMaxNumberOfThreads];
- AsanThread main_thread_;
- AsanThreadSummary main_thread_summary_;
- AsanStats accumulated_stats_;
- // Required for malloc_zone_statistics() on OS X. This can't be stored in
- // per-thread AsanStats.
- uptr max_malloced_memory_;
- u32 n_threads_;
- BlockingMutex mu_;
- bool inited_;
-};
-
-// Returns a single instance of registry.
-AsanThreadRegistry &asanThreadRegistry();
-
-} // namespace __asan
-
-#endif // ASAN_THREAD_REGISTRY_H
diff --git a/libsanitizer/asan/asan_win.cc b/libsanitizer/asan/asan_win.cc
index 6acfeebc8bf..ed785b69281 100644
--- a/libsanitizer/asan/asan_win.cc
+++ b/libsanitizer/asan/asan_win.cc
@@ -9,7 +9,9 @@
//
// Windows-specific details.
//===----------------------------------------------------------------------===//
-#ifdef _WIN32
+
+#include "sanitizer_common/sanitizer_platform.h"
+#if SANITIZER_WINDOWS
#include <windows.h>
#include <dbghelp.h>
@@ -21,6 +23,14 @@
#include "sanitizer_common/sanitizer_libc.h"
#include "sanitizer_common/sanitizer_mutex.h"
+extern "C" {
+ SANITIZER_INTERFACE_ATTRIBUTE
+ int __asan_should_detect_stack_use_after_return() {
+ __asan_init();
+ return __asan_option_detect_stack_use_after_return;
+ }
+}
+
namespace __asan {
// ---------------------- Stacktraces, symbols, etc. ---------------- {{{1
@@ -28,30 +38,6 @@ static BlockingMutex dbghelp_lock(LINKER_INITIALIZED);
static bool dbghelp_initialized = false;
#pragma comment(lib, "dbghelp.lib")
-void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp, bool fast) {
- (void)fast;
- stack->max_size = max_s;
- void *tmp[kStackTraceMax];
-
- // FIXME: CaptureStackBackTrace might be too slow for us.
- // FIXME: Compare with StackWalk64.
- // FIXME: Look at LLVMUnhandledExceptionFilter in Signals.inc
- uptr cs_ret = CaptureStackBackTrace(1, stack->max_size, tmp, 0);
- uptr offset = 0;
- // Skip the RTL frames by searching for the PC in the stacktrace.
- // FIXME: this doesn't work well for the malloc/free stacks yet.
- for (uptr i = 0; i < cs_ret; i++) {
- if (pc != (uptr)tmp[i])
- continue;
- offset = i;
- break;
- }
-
- stack->size = cs_ret - offset;
- for (uptr i = 0; i < stack->size; i++)
- stack->trace[i] = (uptr)tmp[i + offset];
-}
-
// ---------------------- TSD ---------------- {{{1
static bool tsd_key_inited = false;
diff --git a/libsanitizer/asan/libtool-version b/libsanitizer/asan/libtool-version
index 204fdd2d8e5..9a16cf57844 100644
--- a/libsanitizer/asan/libtool-version
+++ b/libsanitizer/asan/libtool-version
@@ -1,6 +1,6 @@
-# This file is used to maintain libtool version info for libmudflap. See
+# This file is used to maintain libtool version info for libasan. See
# the libtool manual to understand the meaning of the fields. This is
# a separate file so that version updates don't involve re-running
# automake.
# CURRENT:REVISION:AGE
-0:0:0
+1:0:0
diff --git a/libsanitizer/configure b/libsanitizer/configure
index 4080d7a1c95..5e425d1d9e3 100755
--- a/libsanitizer/configure
+++ b/libsanitizer/configure
@@ -644,7 +644,6 @@ CXX
am__fastdepCC_FALSE
am__fastdepCC_TRUE
CCDEPMODE
-am__nodep
AMDEPBACKSLASH
AMDEP_FALSE
AMDEP_TRUE
@@ -3069,11 +3068,11 @@ MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
# We need awk for the "check" target. The system "awk" is bad on
# some platforms.
-# Always define AMTAR for backward compatibility. Yes, it's still used
-# in the wild :-( We should find a proper way to deprecate it ...
-AMTAR='$${TAR-tar}'
+# Always define AMTAR for backward compatibility.
-am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'
+AMTAR=${AMTAR-"${am_missing_run}tar"}
+
+am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'
@@ -3987,7 +3986,6 @@ fi
if test "x$enable_dependency_tracking" != xno; then
am_depcomp="$ac_aux_dir/depcomp"
AMDEPBACKSLASH='\'
- am__nodep='_no'
fi
if test "x$enable_dependency_tracking" != xno; then
AMDEP_TRUE=
@@ -4012,7 +4010,6 @@ else
# 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'.
- rm -rf conftest.dir
mkdir conftest.dir
# Copy depcomp to subdir because otherwise we won't find it if we're
# using a relative directory.
@@ -4072,7 +4069,7 @@ else
break
fi
;;
- msvc7 | msvc7msys | msvisualcpp | msvcmsys)
+ msvisualcpp | msvcmsys)
# This compiler won't grok `-c -o', but also, the minuso test has
# not run yet. These depmodes are late enough in the game, and
# so weak that their functioning should not be impacted.
@@ -4397,7 +4394,6 @@ else
# 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'.
- rm -rf conftest.dir
mkdir conftest.dir
# Copy depcomp to subdir because otherwise we won't find it if we're
# using a relative directory.
@@ -4457,7 +4453,7 @@ else
break
fi
;;
- msvc7 | msvc7msys | msvisualcpp | msvcmsys)
+ msvisualcpp | msvcmsys)
# This compiler won't grok `-c -o', but also, the minuso test has
# not run yet. These depmodes are late enough in the game, and
# so weak that their functioning should not be impacted.
@@ -4532,7 +4528,6 @@ else
# 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'.
- rm -rf conftest.dir
mkdir conftest.dir
# Copy depcomp to subdir because otherwise we won't find it if we're
# using a relative directory.
@@ -4590,7 +4585,7 @@ else
break
fi
;;
- msvc7 | msvc7msys | msvisualcpp | msvcmsys)
+ msvisualcpp | msvcmsys)
# This compiler won't grok `-c -o', but also, the minuso test has
# not run yet. These depmodes are late enough in the game, and
# so weak that their functioning should not be impacted.
@@ -6609,7 +6604,7 @@ ia64-*-hpux*)
rm -rf conftest*
;;
-x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \
+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
@@ -6634,7 +6629,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
;;
esac
;;
- ppc64-*linux*|powerpc64-*linux*)
+ powerpc64le-*linux*)
+ LD="${LD-ld} -m elf32lppclinux"
+ ;;
+ powerpc64-*linux*)
LD="${LD-ld} -m elf32ppclinux"
;;
s390x-*linux*)
@@ -6653,7 +6651,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
x86_64-*linux*)
LD="${LD-ld} -m elf_x86_64"
;;
- ppc*-*linux*|powerpc*-*linux*)
+ powerpcle-*linux*)
+ LD="${LD-ld} -m elf64lppc"
+ ;;
+ powerpc-*linux*)
LD="${LD-ld} -m elf64ppc"
;;
s390*-*linux*|s390*-*tpf*)
@@ -11116,7 +11117,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11119 "configure"
+#line 11120 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -11222,7 +11223,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11225 "configure"
+#line 11226 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -14548,7 +14549,7 @@ fi
ac_config_files="$ac_config_files Makefile"
-ac_config_files="$ac_config_files interception/Makefile sanitizer_common/Makefile asan/Makefile ubsan/Makefile"
+ac_config_files="$ac_config_files interception/Makefile sanitizer_common/Makefile lsan/Makefile asan/Makefile ubsan/Makefile"
if test "x$TSAN_SUPPORTED" = "xyes"; then
@@ -15678,6 +15679,7 @@ do
"Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
"interception/Makefile") CONFIG_FILES="$CONFIG_FILES interception/Makefile" ;;
"sanitizer_common/Makefile") CONFIG_FILES="$CONFIG_FILES sanitizer_common/Makefile" ;;
+ "lsan/Makefile") CONFIG_FILES="$CONFIG_FILES lsan/Makefile" ;;
"asan/Makefile") CONFIG_FILES="$CONFIG_FILES asan/Makefile" ;;
"ubsan/Makefile") CONFIG_FILES="$CONFIG_FILES ubsan/Makefile" ;;
"tsan/Makefile") CONFIG_FILES="$CONFIG_FILES tsan/Makefile" ;;
@@ -17034,6 +17036,17 @@ _EOF
. ${multi_basedir}/config-ml.in
{ ml_norecursion=; unset ml_norecursion;}
;;
+ "lsan/Makefile":F) cat > vpsed$$ << \_EOF
+s!`test -f '$<' || echo '$(srcdir)/'`!!
+_EOF
+ sed -f vpsed$$ $ac_file > tmp$$
+ mv tmp$$ $ac_file
+ rm vpsed$$
+ echo 'MULTISUBDIR =' >> $ac_file
+ ml_norecursion=yes
+ . ${multi_basedir}/config-ml.in
+ { ml_norecursion=; unset ml_norecursion;}
+ ;;
"asan/Makefile":F) cat > vpsed$$ << \_EOF
s!`test -f '$<' || echo '$(srcdir)/'`!!
_EOF
diff --git a/libsanitizer/configure.ac b/libsanitizer/configure.ac
index 5919da61304..0b2d8132fb6 100644
--- a/libsanitizer/configure.ac
+++ b/libsanitizer/configure.ac
@@ -89,7 +89,7 @@ AM_CONDITIONAL(USING_MAC_INTERPOSE, $MAC_INTERPOSE)
AC_CONFIG_FILES([Makefile])
-AC_CONFIG_FILES(AC_FOREACH([DIR], [interception sanitizer_common asan ubsan], [DIR/Makefile ]),
+AC_CONFIG_FILES(AC_FOREACH([DIR], [interception sanitizer_common lsan asan ubsan], [DIR/Makefile ]),
[cat > vpsed$$ << \_EOF
s!`test -f '$<' || echo '$(srcdir)/'`!!
_EOF
diff --git a/libsanitizer/include/sanitizer/common_interface_defs.h b/libsanitizer/include/sanitizer/common_interface_defs.h
index c218b5b5654..a7db2ff1c12 100644
--- a/libsanitizer/include/sanitizer/common_interface_defs.h
+++ b/libsanitizer/include/sanitizer/common_interface_defs.h
@@ -39,6 +39,16 @@ extern "C" {
// the error message. This function can be overridden by the client.
void __sanitizer_report_error_summary(const char *error_summary);
+ // Some of the sanitizers (e.g. asan/tsan) may miss bugs that happen
+ // in unaligned loads/stores. In order to find such bugs reliably one needs
+ // to replace plain unaligned loads/stores with these calls.
+ uint16_t __sanitizer_unaligned_load16(const void *p);
+ uint32_t __sanitizer_unaligned_load32(const void *p);
+ uint64_t __sanitizer_unaligned_load64(const void *p);
+ void __sanitizer_unaligned_store16(void *p, uint16_t x);
+ void __sanitizer_unaligned_store32(void *p, uint32_t x);
+ void __sanitizer_unaligned_store64(void *p, uint64_t x);
+
#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/libsanitizer/include/sanitizer/dfsan_interface.h b/libsanitizer/include/sanitizer/dfsan_interface.h
new file mode 100644
index 00000000000..dd938483d18
--- /dev/null
+++ b/libsanitizer/include/sanitizer/dfsan_interface.h
@@ -0,0 +1,85 @@
+//===-- dfsan_interface.h -------------------------------------------------===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of DataFlowSanitizer.
+//
+// Public interface header.
+//===----------------------------------------------------------------------===//
+#ifndef DFSAN_INTERFACE_H
+#define DFSAN_INTERFACE_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include <sanitizer/common_interface_defs.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef uint16_t dfsan_label;
+
+/// Stores information associated with a specific label identifier. A label
+/// may be a base label created using dfsan_create_label, with associated
+/// text description and user data, or an automatically created union label,
+/// which represents the union of two label identifiers (which may themselves
+/// be base or union labels).
+struct dfsan_label_info {
+ // Fields for union labels, set to 0 for base labels.
+ dfsan_label l1;
+ dfsan_label l2;
+
+ // Fields for base labels.
+ const char *desc;
+ void *userdata;
+};
+
+/// Computes the union of \c l1 and \c l2, possibly creating a union label in
+/// the process.
+dfsan_label dfsan_union(dfsan_label l1, dfsan_label l2);
+
+/// Creates and returns a base label with the given description and user data.
+dfsan_label dfsan_create_label(const char *desc, void *userdata);
+
+/// Sets the label for each address in [addr,addr+size) to \c label.
+void dfsan_set_label(dfsan_label label, void *addr, size_t size);
+
+/// Sets the label for each address in [addr,addr+size) to the union of the
+/// current label for that address and \c label.
+void dfsan_add_label(dfsan_label label, void *addr, size_t size);
+
+/// Retrieves the label associated with the given data.
+///
+/// The type of 'data' is arbitrary. The function accepts a value of any type,
+/// which can be truncated or extended (implicitly or explicitly) as necessary.
+/// The truncation/extension operations will preserve the label of the original
+/// value.
+dfsan_label dfsan_get_label(long data);
+
+/// Retrieves the label associated with the data at the given address.
+dfsan_label dfsan_read_label(const void *addr, size_t size);
+
+/// Retrieves a pointer to the dfsan_label_info struct for the given label.
+const struct dfsan_label_info *dfsan_get_label_info(dfsan_label label);
+
+/// Returns whether the given label label contains the label elem.
+int dfsan_has_label(dfsan_label label, dfsan_label elem);
+
+/// If the given label label contains a label with the description desc, returns
+/// that label, else returns 0.
+dfsan_label dfsan_has_label_with_desc(dfsan_label label, const char *desc);
+
+#ifdef __cplusplus
+} // extern "C"
+
+template <typename T>
+void dfsan_set_label(dfsan_label label, T &data) { // NOLINT
+ dfsan_set_label(label, (void *)&data, sizeof(T));
+}
+
+#endif
+
+#endif // DFSAN_INTERFACE_H
diff --git a/libsanitizer/include/sanitizer/linux_syscall_hooks.h b/libsanitizer/include/sanitizer/linux_syscall_hooks.h
new file mode 100644
index 00000000000..6cd7d7626b8
--- /dev/null
+++ b/libsanitizer/include/sanitizer/linux_syscall_hooks.h
@@ -0,0 +1,3067 @@
+//===-- linux_syscall_hooks.h ---------------------------------------------===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of public sanitizer interface.
+//
+// System call handlers.
+//
+// Interface methods declared in this header implement pre- and post- syscall
+// actions for the active sanitizer.
+// Usage:
+// __sanitizer_syscall_pre_getfoo(...args...);
+// long res = syscall(__NR_getfoo, ...args...);
+// __sanitizer_syscall_post_getfoo(res, ...args...);
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_LINUX_SYSCALL_HOOKS_H
+#define SANITIZER_LINUX_SYSCALL_HOOKS_H
+
+#define __sanitizer_syscall_pre_time(tloc) \
+ __sanitizer_syscall_pre_impl_time((long)(tloc))
+#define __sanitizer_syscall_post_time(res, tloc) \
+ __sanitizer_syscall_post_impl_time(res, (long)(tloc))
+#define __sanitizer_syscall_pre_stime(tptr) \
+ __sanitizer_syscall_pre_impl_stime((long)(tptr))
+#define __sanitizer_syscall_post_stime(res, tptr) \
+ __sanitizer_syscall_post_impl_stime(res, (long)(tptr))
+#define __sanitizer_syscall_pre_gettimeofday(tv, tz) \
+ __sanitizer_syscall_pre_impl_gettimeofday((long)(tv), (long)(tz))
+#define __sanitizer_syscall_post_gettimeofday(res, tv, tz) \
+ __sanitizer_syscall_post_impl_gettimeofday(res, (long)(tv), (long)(tz))
+#define __sanitizer_syscall_pre_settimeofday(tv, tz) \
+ __sanitizer_syscall_pre_impl_settimeofday((long)(tv), (long)(tz))
+#define __sanitizer_syscall_post_settimeofday(res, tv, tz) \
+ __sanitizer_syscall_post_impl_settimeofday(res, (long)(tv), (long)(tz))
+#define __sanitizer_syscall_pre_adjtimex(txc_p) \
+ __sanitizer_syscall_pre_impl_adjtimex((long)(txc_p))
+#define __sanitizer_syscall_post_adjtimex(res, txc_p) \
+ __sanitizer_syscall_post_impl_adjtimex(res, (long)(txc_p))
+#define __sanitizer_syscall_pre_times(tbuf) \
+ __sanitizer_syscall_pre_impl_times((long)(tbuf))
+#define __sanitizer_syscall_post_times(res, tbuf) \
+ __sanitizer_syscall_post_impl_times(res, (long)(tbuf))
+#define __sanitizer_syscall_pre_gettid() __sanitizer_syscall_pre_impl_gettid()
+#define __sanitizer_syscall_post_gettid(res) \
+ __sanitizer_syscall_post_impl_gettid(res)
+#define __sanitizer_syscall_pre_nanosleep(rqtp, rmtp) \
+ __sanitizer_syscall_pre_impl_nanosleep((long)(rqtp), (long)(rmtp))
+#define __sanitizer_syscall_post_nanosleep(res, rqtp, rmtp) \
+ __sanitizer_syscall_post_impl_nanosleep(res, (long)(rqtp), (long)(rmtp))
+#define __sanitizer_syscall_pre_alarm(seconds) \
+ __sanitizer_syscall_pre_impl_alarm((long)(seconds))
+#define __sanitizer_syscall_post_alarm(res, seconds) \
+ __sanitizer_syscall_post_impl_alarm(res, (long)(seconds))
+#define __sanitizer_syscall_pre_getpid() __sanitizer_syscall_pre_impl_getpid()
+#define __sanitizer_syscall_post_getpid(res) \
+ __sanitizer_syscall_post_impl_getpid(res)
+#define __sanitizer_syscall_pre_getppid() __sanitizer_syscall_pre_impl_getppid()
+#define __sanitizer_syscall_post_getppid(res) \
+ __sanitizer_syscall_post_impl_getppid(res)
+#define __sanitizer_syscall_pre_getuid() __sanitizer_syscall_pre_impl_getuid()
+#define __sanitizer_syscall_post_getuid(res) \
+ __sanitizer_syscall_post_impl_getuid(res)
+#define __sanitizer_syscall_pre_geteuid() __sanitizer_syscall_pre_impl_geteuid()
+#define __sanitizer_syscall_post_geteuid(res) \
+ __sanitizer_syscall_post_impl_geteuid(res)
+#define __sanitizer_syscall_pre_getgid() __sanitizer_syscall_pre_impl_getgid()
+#define __sanitizer_syscall_post_getgid(res) \
+ __sanitizer_syscall_post_impl_getgid(res)
+#define __sanitizer_syscall_pre_getegid() __sanitizer_syscall_pre_impl_getegid()
+#define __sanitizer_syscall_post_getegid(res) \
+ __sanitizer_syscall_post_impl_getegid(res)
+#define __sanitizer_syscall_pre_getresuid(ruid, euid, suid) \
+ __sanitizer_syscall_pre_impl_getresuid((long)(ruid), (long)(euid), \
+ (long)(suid))
+#define __sanitizer_syscall_post_getresuid(res, ruid, euid, suid) \
+ __sanitizer_syscall_post_impl_getresuid(res, (long)(ruid), (long)(euid), \
+ (long)(suid))
+#define __sanitizer_syscall_pre_getresgid(rgid, egid, sgid) \
+ __sanitizer_syscall_pre_impl_getresgid((long)(rgid), (long)(egid), \
+ (long)(sgid))
+#define __sanitizer_syscall_post_getresgid(res, rgid, egid, sgid) \
+ __sanitizer_syscall_post_impl_getresgid(res, (long)(rgid), (long)(egid), \
+ (long)(sgid))
+#define __sanitizer_syscall_pre_getpgid(pid) \
+ __sanitizer_syscall_pre_impl_getpgid((long)(pid))
+#define __sanitizer_syscall_post_getpgid(res, pid) \
+ __sanitizer_syscall_post_impl_getpgid(res, (long)(pid))
+#define __sanitizer_syscall_pre_getpgrp() __sanitizer_syscall_pre_impl_getpgrp()
+#define __sanitizer_syscall_post_getpgrp(res) \
+ __sanitizer_syscall_post_impl_getpgrp(res)
+#define __sanitizer_syscall_pre_getsid(pid) \
+ __sanitizer_syscall_pre_impl_getsid((long)(pid))
+#define __sanitizer_syscall_post_getsid(res, pid) \
+ __sanitizer_syscall_post_impl_getsid(res, (long)(pid))
+#define __sanitizer_syscall_pre_getgroups(gidsetsize, grouplist) \
+ __sanitizer_syscall_pre_impl_getgroups((long)(gidsetsize), (long)(grouplist))
+#define __sanitizer_syscall_post_getgroups(res, gidsetsize, grouplist) \
+ __sanitizer_syscall_post_impl_getgroups(res, (long)(gidsetsize), \
+ (long)(grouplist))
+#define __sanitizer_syscall_pre_setregid(rgid, egid) \
+ __sanitizer_syscall_pre_impl_setregid((long)(rgid), (long)(egid))
+#define __sanitizer_syscall_post_setregid(res, rgid, egid) \
+ __sanitizer_syscall_post_impl_setregid(res, (long)(rgid), (long)(egid))
+#define __sanitizer_syscall_pre_setgid(gid) \
+ __sanitizer_syscall_pre_impl_setgid((long)(gid))
+#define __sanitizer_syscall_post_setgid(res, gid) \
+ __sanitizer_syscall_post_impl_setgid(res, (long)(gid))
+#define __sanitizer_syscall_pre_setreuid(ruid, euid) \
+ __sanitizer_syscall_pre_impl_setreuid((long)(ruid), (long)(euid))
+#define __sanitizer_syscall_post_setreuid(res, ruid, euid) \
+ __sanitizer_syscall_post_impl_setreuid(res, (long)(ruid), (long)(euid))
+#define __sanitizer_syscall_pre_setuid(uid) \
+ __sanitizer_syscall_pre_impl_setuid((long)(uid))
+#define __sanitizer_syscall_post_setuid(res, uid) \
+ __sanitizer_syscall_post_impl_setuid(res, (long)(uid))
+#define __sanitizer_syscall_pre_setresuid(ruid, euid, suid) \
+ __sanitizer_syscall_pre_impl_setresuid((long)(ruid), (long)(euid), \
+ (long)(suid))
+#define __sanitizer_syscall_post_setresuid(res, ruid, euid, suid) \
+ __sanitizer_syscall_post_impl_setresuid(res, (long)(ruid), (long)(euid), \
+ (long)(suid))
+#define __sanitizer_syscall_pre_setresgid(rgid, egid, sgid) \
+ __sanitizer_syscall_pre_impl_setresgid((long)(rgid), (long)(egid), \
+ (long)(sgid))
+#define __sanitizer_syscall_post_setresgid(res, rgid, egid, sgid) \
+ __sanitizer_syscall_post_impl_setresgid(res, (long)(rgid), (long)(egid), \
+ (long)(sgid))
+#define __sanitizer_syscall_pre_setfsuid(uid) \
+ __sanitizer_syscall_pre_impl_setfsuid((long)(uid))
+#define __sanitizer_syscall_post_setfsuid(res, uid) \
+ __sanitizer_syscall_post_impl_setfsuid(res, (long)(uid))
+#define __sanitizer_syscall_pre_setfsgid(gid) \
+ __sanitizer_syscall_pre_impl_setfsgid((long)(gid))
+#define __sanitizer_syscall_post_setfsgid(res, gid) \
+ __sanitizer_syscall_post_impl_setfsgid(res, (long)(gid))
+#define __sanitizer_syscall_pre_setpgid(pid, pgid) \
+ __sanitizer_syscall_pre_impl_setpgid((long)(pid), (long)(pgid))
+#define __sanitizer_syscall_post_setpgid(res, pid, pgid) \
+ __sanitizer_syscall_post_impl_setpgid(res, (long)(pid), (long)(pgid))
+#define __sanitizer_syscall_pre_setsid() __sanitizer_syscall_pre_impl_setsid()
+#define __sanitizer_syscall_post_setsid(res) \
+ __sanitizer_syscall_post_impl_setsid(res)
+#define __sanitizer_syscall_pre_setgroups(gidsetsize, grouplist) \
+ __sanitizer_syscall_pre_impl_setgroups((long)(gidsetsize), (long)(grouplist))
+#define __sanitizer_syscall_post_setgroups(res, gidsetsize, grouplist) \
+ __sanitizer_syscall_post_impl_setgroups(res, (long)(gidsetsize), \
+ (long)(grouplist))
+#define __sanitizer_syscall_pre_acct(name) \
+ __sanitizer_syscall_pre_impl_acct((long)(name))
+#define __sanitizer_syscall_post_acct(res, name) \
+ __sanitizer_syscall_post_impl_acct(res, (long)(name))
+#define __sanitizer_syscall_pre_capget(header, dataptr) \
+ __sanitizer_syscall_pre_impl_capget((long)(header), (long)(dataptr))
+#define __sanitizer_syscall_post_capget(res, header, dataptr) \
+ __sanitizer_syscall_post_impl_capget(res, (long)(header), (long)(dataptr))
+#define __sanitizer_syscall_pre_capset(header, data) \
+ __sanitizer_syscall_pre_impl_capset((long)(header), (long)(data))
+#define __sanitizer_syscall_post_capset(res, header, data) \
+ __sanitizer_syscall_post_impl_capset(res, (long)(header), (long)(data))
+#define __sanitizer_syscall_pre_personality(personality) \
+ __sanitizer_syscall_pre_impl_personality((long)(personality))
+#define __sanitizer_syscall_post_personality(res, personality) \
+ __sanitizer_syscall_post_impl_personality(res, (long)(personality))
+#define __sanitizer_syscall_pre_sigpending(set) \
+ __sanitizer_syscall_pre_impl_sigpending((long)(set))
+#define __sanitizer_syscall_post_sigpending(res, set) \
+ __sanitizer_syscall_post_impl_sigpending(res, (long)(set))
+#define __sanitizer_syscall_pre_sigprocmask(how, set, oset) \
+ __sanitizer_syscall_pre_impl_sigprocmask((long)(how), (long)(set), \
+ (long)(oset))
+#define __sanitizer_syscall_post_sigprocmask(res, how, set, oset) \
+ __sanitizer_syscall_post_impl_sigprocmask(res, (long)(how), (long)(set), \
+ (long)(oset))
+#define __sanitizer_syscall_pre_getitimer(which, value) \
+ __sanitizer_syscall_pre_impl_getitimer((long)(which), (long)(value))
+#define __sanitizer_syscall_post_getitimer(res, which, value) \
+ __sanitizer_syscall_post_impl_getitimer(res, (long)(which), (long)(value))
+#define __sanitizer_syscall_pre_setitimer(which, value, ovalue) \
+ __sanitizer_syscall_pre_impl_setitimer((long)(which), (long)(value), \
+ (long)(ovalue))
+#define __sanitizer_syscall_post_setitimer(res, which, value, ovalue) \
+ __sanitizer_syscall_post_impl_setitimer(res, (long)(which), (long)(value), \
+ (long)(ovalue))
+#define __sanitizer_syscall_pre_timer_create(which_clock, timer_event_spec, \
+ created_timer_id) \
+ __sanitizer_syscall_pre_impl_timer_create( \
+ (long)(which_clock), (long)(timer_event_spec), (long)(created_timer_id))
+#define __sanitizer_syscall_post_timer_create( \
+ res, which_clock, timer_event_spec, created_timer_id) \
+ __sanitizer_syscall_post_impl_timer_create(res, (long)(which_clock), \
+ (long)(timer_event_spec), \
+ (long)(created_timer_id))
+#define __sanitizer_syscall_pre_timer_gettime(timer_id, setting) \
+ __sanitizer_syscall_pre_impl_timer_gettime((long)(timer_id), (long)(setting))
+#define __sanitizer_syscall_post_timer_gettime(res, timer_id, setting) \
+ __sanitizer_syscall_post_impl_timer_gettime(res, (long)(timer_id), \
+ (long)(setting))
+#define __sanitizer_syscall_pre_timer_getoverrun(timer_id) \
+ __sanitizer_syscall_pre_impl_timer_getoverrun((long)(timer_id))
+#define __sanitizer_syscall_post_timer_getoverrun(res, timer_id) \
+ __sanitizer_syscall_post_impl_timer_getoverrun(res, (long)(timer_id))
+#define __sanitizer_syscall_pre_timer_settime(timer_id, flags, new_setting, \
+ old_setting) \
+ __sanitizer_syscall_pre_impl_timer_settime((long)(timer_id), (long)(flags), \
+ (long)(new_setting), \
+ (long)(old_setting))
+#define __sanitizer_syscall_post_timer_settime(res, timer_id, flags, \
+ new_setting, old_setting) \
+ __sanitizer_syscall_post_impl_timer_settime( \
+ res, (long)(timer_id), (long)(flags), (long)(new_setting), \
+ (long)(old_setting))
+#define __sanitizer_syscall_pre_timer_delete(timer_id) \
+ __sanitizer_syscall_pre_impl_timer_delete((long)(timer_id))
+#define __sanitizer_syscall_post_timer_delete(res, timer_id) \
+ __sanitizer_syscall_post_impl_timer_delete(res, (long)(timer_id))
+#define __sanitizer_syscall_pre_clock_settime(which_clock, tp) \
+ __sanitizer_syscall_pre_impl_clock_settime((long)(which_clock), (long)(tp))
+#define __sanitizer_syscall_post_clock_settime(res, which_clock, tp) \
+ __sanitizer_syscall_post_impl_clock_settime(res, (long)(which_clock), \
+ (long)(tp))
+#define __sanitizer_syscall_pre_clock_gettime(which_clock, tp) \
+ __sanitizer_syscall_pre_impl_clock_gettime((long)(which_clock), (long)(tp))
+#define __sanitizer_syscall_post_clock_gettime(res, which_clock, tp) \
+ __sanitizer_syscall_post_impl_clock_gettime(res, (long)(which_clock), \
+ (long)(tp))
+#define __sanitizer_syscall_pre_clock_adjtime(which_clock, tx) \
+ __sanitizer_syscall_pre_impl_clock_adjtime((long)(which_clock), (long)(tx))
+#define __sanitizer_syscall_post_clock_adjtime(res, which_clock, tx) \
+ __sanitizer_syscall_post_impl_clock_adjtime(res, (long)(which_clock), \
+ (long)(tx))
+#define __sanitizer_syscall_pre_clock_getres(which_clock, tp) \
+ __sanitizer_syscall_pre_impl_clock_getres((long)(which_clock), (long)(tp))
+#define __sanitizer_syscall_post_clock_getres(res, which_clock, tp) \
+ __sanitizer_syscall_post_impl_clock_getres(res, (long)(which_clock), \
+ (long)(tp))
+#define __sanitizer_syscall_pre_clock_nanosleep(which_clock, flags, rqtp, \
+ rmtp) \
+ __sanitizer_syscall_pre_impl_clock_nanosleep( \
+ (long)(which_clock), (long)(flags), (long)(rqtp), (long)(rmtp))
+#define __sanitizer_syscall_post_clock_nanosleep(res, which_clock, flags, \
+ rqtp, rmtp) \
+ __sanitizer_syscall_post_impl_clock_nanosleep( \
+ res, (long)(which_clock), (long)(flags), (long)(rqtp), (long)(rmtp))
+#define __sanitizer_syscall_pre_nice(increment) \
+ __sanitizer_syscall_pre_impl_nice((long)(increment))
+#define __sanitizer_syscall_post_nice(res, increment) \
+ __sanitizer_syscall_post_impl_nice(res, (long)(increment))
+#define __sanitizer_syscall_pre_sched_setscheduler(pid, policy, param) \
+ __sanitizer_syscall_pre_impl_sched_setscheduler((long)(pid), (long)(policy), \
+ (long)(param))
+#define __sanitizer_syscall_post_sched_setscheduler(res, pid, policy, param) \
+ __sanitizer_syscall_post_impl_sched_setscheduler( \
+ res, (long)(pid), (long)(policy), (long)(param))
+#define __sanitizer_syscall_pre_sched_setparam(pid, param) \
+ __sanitizer_syscall_pre_impl_sched_setparam((long)(pid), (long)(param))
+#define __sanitizer_syscall_post_sched_setparam(res, pid, param) \
+ __sanitizer_syscall_post_impl_sched_setparam(res, (long)(pid), (long)(param))
+#define __sanitizer_syscall_pre_sched_getscheduler(pid) \
+ __sanitizer_syscall_pre_impl_sched_getscheduler((long)(pid))
+#define __sanitizer_syscall_post_sched_getscheduler(res, pid) \
+ __sanitizer_syscall_post_impl_sched_getscheduler(res, (long)(pid))
+#define __sanitizer_syscall_pre_sched_getparam(pid, param) \
+ __sanitizer_syscall_pre_impl_sched_getparam((long)(pid), (long)(param))
+#define __sanitizer_syscall_post_sched_getparam(res, pid, param) \
+ __sanitizer_syscall_post_impl_sched_getparam(res, (long)(pid), (long)(param))
+#define __sanitizer_syscall_pre_sched_setaffinity(pid, len, user_mask_ptr) \
+ __sanitizer_syscall_pre_impl_sched_setaffinity((long)(pid), (long)(len), \
+ (long)(user_mask_ptr))
+#define __sanitizer_syscall_post_sched_setaffinity(res, pid, len, \
+ user_mask_ptr) \
+ __sanitizer_syscall_post_impl_sched_setaffinity( \
+ res, (long)(pid), (long)(len), (long)(user_mask_ptr))
+#define __sanitizer_syscall_pre_sched_getaffinity(pid, len, user_mask_ptr) \
+ __sanitizer_syscall_pre_impl_sched_getaffinity((long)(pid), (long)(len), \
+ (long)(user_mask_ptr))
+#define __sanitizer_syscall_post_sched_getaffinity(res, pid, len, \
+ user_mask_ptr) \
+ __sanitizer_syscall_post_impl_sched_getaffinity( \
+ res, (long)(pid), (long)(len), (long)(user_mask_ptr))
+#define __sanitizer_syscall_pre_sched_yield() \
+ __sanitizer_syscall_pre_impl_sched_yield()
+#define __sanitizer_syscall_post_sched_yield(res) \
+ __sanitizer_syscall_post_impl_sched_yield(res)
+#define __sanitizer_syscall_pre_sched_get_priority_max(policy) \
+ __sanitizer_syscall_pre_impl_sched_get_priority_max((long)(policy))
+#define __sanitizer_syscall_post_sched_get_priority_max(res, policy) \
+ __sanitizer_syscall_post_impl_sched_get_priority_max(res, (long)(policy))
+#define __sanitizer_syscall_pre_sched_get_priority_min(policy) \
+ __sanitizer_syscall_pre_impl_sched_get_priority_min((long)(policy))
+#define __sanitizer_syscall_post_sched_get_priority_min(res, policy) \
+ __sanitizer_syscall_post_impl_sched_get_priority_min(res, (long)(policy))
+#define __sanitizer_syscall_pre_sched_rr_get_interval(pid, interval) \
+ __sanitizer_syscall_pre_impl_sched_rr_get_interval((long)(pid), \
+ (long)(interval))
+#define __sanitizer_syscall_post_sched_rr_get_interval(res, pid, interval) \
+ __sanitizer_syscall_post_impl_sched_rr_get_interval(res, (long)(pid), \
+ (long)(interval))
+#define __sanitizer_syscall_pre_setpriority(which, who, niceval) \
+ __sanitizer_syscall_pre_impl_setpriority((long)(which), (long)(who), \
+ (long)(niceval))
+#define __sanitizer_syscall_post_setpriority(res, which, who, niceval) \
+ __sanitizer_syscall_post_impl_setpriority(res, (long)(which), (long)(who), \
+ (long)(niceval))
+#define __sanitizer_syscall_pre_getpriority(which, who) \
+ __sanitizer_syscall_pre_impl_getpriority((long)(which), (long)(who))
+#define __sanitizer_syscall_post_getpriority(res, which, who) \
+ __sanitizer_syscall_post_impl_getpriority(res, (long)(which), (long)(who))
+#define __sanitizer_syscall_pre_shutdown(arg0, arg1) \
+ __sanitizer_syscall_pre_impl_shutdown((long)(arg0), (long)(arg1))
+#define __sanitizer_syscall_post_shutdown(res, arg0, arg1) \
+ __sanitizer_syscall_post_impl_shutdown(res, (long)(arg0), (long)(arg1))
+#define __sanitizer_syscall_pre_reboot(magic1, magic2, cmd, arg) \
+ __sanitizer_syscall_pre_impl_reboot((long)(magic1), (long)(magic2), \
+ (long)(cmd), (long)(arg))
+#define __sanitizer_syscall_post_reboot(res, magic1, magic2, cmd, arg) \
+ __sanitizer_syscall_post_impl_reboot(res, (long)(magic1), (long)(magic2), \
+ (long)(cmd), (long)(arg))
+#define __sanitizer_syscall_pre_restart_syscall() \
+ __sanitizer_syscall_pre_impl_restart_syscall()
+#define __sanitizer_syscall_post_restart_syscall(res) \
+ __sanitizer_syscall_post_impl_restart_syscall(res)
+#define __sanitizer_syscall_pre_kexec_load(entry, nr_segments, segments, \
+ flags) \
+ __sanitizer_syscall_pre_impl_kexec_load((long)(entry), (long)(nr_segments), \
+ (long)(segments), (long)(flags))
+#define __sanitizer_syscall_post_kexec_load(res, entry, nr_segments, segments, \
+ flags) \
+ __sanitizer_syscall_post_impl_kexec_load(res, (long)(entry), \
+ (long)(nr_segments), \
+ (long)(segments), (long)(flags))
+#define __sanitizer_syscall_pre_exit(error_code) \
+ __sanitizer_syscall_pre_impl_exit((long)(error_code))
+#define __sanitizer_syscall_post_exit(res, error_code) \
+ __sanitizer_syscall_post_impl_exit(res, (long)(error_code))
+#define __sanitizer_syscall_pre_exit_group(error_code) \
+ __sanitizer_syscall_pre_impl_exit_group((long)(error_code))
+#define __sanitizer_syscall_post_exit_group(res, error_code) \
+ __sanitizer_syscall_post_impl_exit_group(res, (long)(error_code))
+#define __sanitizer_syscall_pre_wait4(pid, stat_addr, options, ru) \
+ __sanitizer_syscall_pre_impl_wait4((long)(pid), (long)(stat_addr), \
+ (long)(options), (long)(ru))
+#define __sanitizer_syscall_post_wait4(res, pid, stat_addr, options, ru) \
+ __sanitizer_syscall_post_impl_wait4(res, (long)(pid), (long)(stat_addr), \
+ (long)(options), (long)(ru))
+#define __sanitizer_syscall_pre_waitid(which, pid, infop, options, ru) \
+ __sanitizer_syscall_pre_impl_waitid( \
+ (long)(which), (long)(pid), (long)(infop), (long)(options), (long)(ru))
+#define __sanitizer_syscall_post_waitid(res, which, pid, infop, options, ru) \
+ __sanitizer_syscall_post_impl_waitid(res, (long)(which), (long)(pid), \
+ (long)(infop), (long)(options), \
+ (long)(ru))
+#define __sanitizer_syscall_pre_waitpid(pid, stat_addr, options) \
+ __sanitizer_syscall_pre_impl_waitpid((long)(pid), (long)(stat_addr), \
+ (long)(options))
+#define __sanitizer_syscall_post_waitpid(res, pid, stat_addr, options) \
+ __sanitizer_syscall_post_impl_waitpid(res, (long)(pid), (long)(stat_addr), \
+ (long)(options))
+#define __sanitizer_syscall_pre_set_tid_address(tidptr) \
+ __sanitizer_syscall_pre_impl_set_tid_address((long)(tidptr))
+#define __sanitizer_syscall_post_set_tid_address(res, tidptr) \
+ __sanitizer_syscall_post_impl_set_tid_address(res, (long)(tidptr))
+#define __sanitizer_syscall_pre_init_module(umod, len, uargs) \
+ __sanitizer_syscall_pre_impl_init_module((long)(umod), (long)(len), \
+ (long)(uargs))
+#define __sanitizer_syscall_post_init_module(res, umod, len, uargs) \
+ __sanitizer_syscall_post_impl_init_module(res, (long)(umod), (long)(len), \
+ (long)(uargs))
+#define __sanitizer_syscall_pre_delete_module(name_user, flags) \
+ __sanitizer_syscall_pre_impl_delete_module((long)(name_user), (long)(flags))
+#define __sanitizer_syscall_post_delete_module(res, name_user, flags) \
+ __sanitizer_syscall_post_impl_delete_module(res, (long)(name_user), \
+ (long)(flags))
+#define __sanitizer_syscall_pre_rt_sigprocmask(how, set, oset, sigsetsize) \
+ __sanitizer_syscall_pre_impl_rt_sigprocmask( \
+ (long)(how), (long)(set), (long)(oset), (long)(sigsetsize))
+#define __sanitizer_syscall_post_rt_sigprocmask(res, how, set, oset, \
+ sigsetsize) \
+ __sanitizer_syscall_post_impl_rt_sigprocmask( \
+ res, (long)(how), (long)(set), (long)(oset), (long)(sigsetsize))
+#define __sanitizer_syscall_pre_rt_sigpending(set, sigsetsize) \
+ __sanitizer_syscall_pre_impl_rt_sigpending((long)(set), (long)(sigsetsize))
+#define __sanitizer_syscall_post_rt_sigpending(res, set, sigsetsize) \
+ __sanitizer_syscall_post_impl_rt_sigpending(res, (long)(set), \
+ (long)(sigsetsize))
+#define __sanitizer_syscall_pre_rt_sigtimedwait(uthese, uinfo, uts, \
+ sigsetsize) \
+ __sanitizer_syscall_pre_impl_rt_sigtimedwait( \
+ (long)(uthese), (long)(uinfo), (long)(uts), (long)(sigsetsize))
+#define __sanitizer_syscall_post_rt_sigtimedwait(res, uthese, uinfo, uts, \
+ sigsetsize) \
+ __sanitizer_syscall_post_impl_rt_sigtimedwait( \
+ res, (long)(uthese), (long)(uinfo), (long)(uts), (long)(sigsetsize))
+#define __sanitizer_syscall_pre_rt_tgsigqueueinfo(tgid, pid, sig, uinfo) \
+ __sanitizer_syscall_pre_impl_rt_tgsigqueueinfo((long)(tgid), (long)(pid), \
+ (long)(sig), (long)(uinfo))
+#define __sanitizer_syscall_post_rt_tgsigqueueinfo(res, tgid, pid, sig, uinfo) \
+ __sanitizer_syscall_post_impl_rt_tgsigqueueinfo( \
+ res, (long)(tgid), (long)(pid), (long)(sig), (long)(uinfo))
+#define __sanitizer_syscall_pre_kill(pid, sig) \
+ __sanitizer_syscall_pre_impl_kill((long)(pid), (long)(sig))
+#define __sanitizer_syscall_post_kill(res, pid, sig) \
+ __sanitizer_syscall_post_impl_kill(res, (long)(pid), (long)(sig))
+#define __sanitizer_syscall_pre_tgkill(tgid, pid, sig) \
+ __sanitizer_syscall_pre_impl_tgkill((long)(tgid), (long)(pid), (long)(sig))
+#define __sanitizer_syscall_post_tgkill(res, tgid, pid, sig) \
+ __sanitizer_syscall_post_impl_tgkill(res, (long)(tgid), (long)(pid), \
+ (long)(sig))
+#define __sanitizer_syscall_pre_tkill(pid, sig) \
+ __sanitizer_syscall_pre_impl_tkill((long)(pid), (long)(sig))
+#define __sanitizer_syscall_post_tkill(res, pid, sig) \
+ __sanitizer_syscall_post_impl_tkill(res, (long)(pid), (long)(sig))
+#define __sanitizer_syscall_pre_rt_sigqueueinfo(pid, sig, uinfo) \
+ __sanitizer_syscall_pre_impl_rt_sigqueueinfo((long)(pid), (long)(sig), \
+ (long)(uinfo))
+#define __sanitizer_syscall_post_rt_sigqueueinfo(res, pid, sig, uinfo) \
+ __sanitizer_syscall_post_impl_rt_sigqueueinfo(res, (long)(pid), (long)(sig), \
+ (long)(uinfo))
+#define __sanitizer_syscall_pre_sgetmask() \
+ __sanitizer_syscall_pre_impl_sgetmask()
+#define __sanitizer_syscall_post_sgetmask(res) \
+ __sanitizer_syscall_post_impl_sgetmask(res)
+#define __sanitizer_syscall_pre_ssetmask(newmask) \
+ __sanitizer_syscall_pre_impl_ssetmask((long)(newmask))
+#define __sanitizer_syscall_post_ssetmask(res, newmask) \
+ __sanitizer_syscall_post_impl_ssetmask(res, (long)(newmask))
+#define __sanitizer_syscall_pre_signal(sig, handler) \
+ __sanitizer_syscall_pre_impl_signal((long)(sig), (long)(handler))
+#define __sanitizer_syscall_post_signal(res, sig, handler) \
+ __sanitizer_syscall_post_impl_signal(res, (long)(sig), (long)(handler))
+#define __sanitizer_syscall_pre_pause() __sanitizer_syscall_pre_impl_pause()
+#define __sanitizer_syscall_post_pause(res) \
+ __sanitizer_syscall_post_impl_pause(res)
+#define __sanitizer_syscall_pre_sync() __sanitizer_syscall_pre_impl_sync()
+#define __sanitizer_syscall_post_sync(res) \
+ __sanitizer_syscall_post_impl_sync(res)
+#define __sanitizer_syscall_pre_fsync(fd) \
+ __sanitizer_syscall_pre_impl_fsync((long)(fd))
+#define __sanitizer_syscall_post_fsync(res, fd) \
+ __sanitizer_syscall_post_impl_fsync(res, (long)(fd))
+#define __sanitizer_syscall_pre_fdatasync(fd) \
+ __sanitizer_syscall_pre_impl_fdatasync((long)(fd))
+#define __sanitizer_syscall_post_fdatasync(res, fd) \
+ __sanitizer_syscall_post_impl_fdatasync(res, (long)(fd))
+#define __sanitizer_syscall_pre_bdflush(func, data) \
+ __sanitizer_syscall_pre_impl_bdflush((long)(func), (long)(data))
+#define __sanitizer_syscall_post_bdflush(res, func, data) \
+ __sanitizer_syscall_post_impl_bdflush(res, (long)(func), (long)(data))
+#define __sanitizer_syscall_pre_mount(dev_name, dir_name, type, flags, data) \
+ __sanitizer_syscall_pre_impl_mount((long)(dev_name), (long)(dir_name), \
+ (long)(type), (long)(flags), \
+ (long)(data))
+#define __sanitizer_syscall_post_mount(res, dev_name, dir_name, type, flags, \
+ data) \
+ __sanitizer_syscall_post_impl_mount(res, (long)(dev_name), (long)(dir_name), \
+ (long)(type), (long)(flags), \
+ (long)(data))
+#define __sanitizer_syscall_pre_umount(name, flags) \
+ __sanitizer_syscall_pre_impl_umount((long)(name), (long)(flags))
+#define __sanitizer_syscall_post_umount(res, name, flags) \
+ __sanitizer_syscall_post_impl_umount(res, (long)(name), (long)(flags))
+#define __sanitizer_syscall_pre_oldumount(name) \
+ __sanitizer_syscall_pre_impl_oldumount((long)(name))
+#define __sanitizer_syscall_post_oldumount(res, name) \
+ __sanitizer_syscall_post_impl_oldumount(res, (long)(name))
+#define __sanitizer_syscall_pre_truncate(path, length) \
+ __sanitizer_syscall_pre_impl_truncate((long)(path), (long)(length))
+#define __sanitizer_syscall_post_truncate(res, path, length) \
+ __sanitizer_syscall_post_impl_truncate(res, (long)(path), (long)(length))
+#define __sanitizer_syscall_pre_ftruncate(fd, length) \
+ __sanitizer_syscall_pre_impl_ftruncate((long)(fd), (long)(length))
+#define __sanitizer_syscall_post_ftruncate(res, fd, length) \
+ __sanitizer_syscall_post_impl_ftruncate(res, (long)(fd), (long)(length))
+#define __sanitizer_syscall_pre_stat(filename, statbuf) \
+ __sanitizer_syscall_pre_impl_stat((long)(filename), (long)(statbuf))
+#define __sanitizer_syscall_post_stat(res, filename, statbuf) \
+ __sanitizer_syscall_post_impl_stat(res, (long)(filename), (long)(statbuf))
+#define __sanitizer_syscall_pre_statfs(path, buf) \
+ __sanitizer_syscall_pre_impl_statfs((long)(path), (long)(buf))
+#define __sanitizer_syscall_post_statfs(res, path, buf) \
+ __sanitizer_syscall_post_impl_statfs(res, (long)(path), (long)(buf))
+#define __sanitizer_syscall_pre_statfs64(path, sz, buf) \
+ __sanitizer_syscall_pre_impl_statfs64((long)(path), (long)(sz), (long)(buf))
+#define __sanitizer_syscall_post_statfs64(res, path, sz, buf) \
+ __sanitizer_syscall_post_impl_statfs64(res, (long)(path), (long)(sz), \
+ (long)(buf))
+#define __sanitizer_syscall_pre_fstatfs(fd, buf) \
+ __sanitizer_syscall_pre_impl_fstatfs((long)(fd), (long)(buf))
+#define __sanitizer_syscall_post_fstatfs(res, fd, buf) \
+ __sanitizer_syscall_post_impl_fstatfs(res, (long)(fd), (long)(buf))
+#define __sanitizer_syscall_pre_fstatfs64(fd, sz, buf) \
+ __sanitizer_syscall_pre_impl_fstatfs64((long)(fd), (long)(sz), (long)(buf))
+#define __sanitizer_syscall_post_fstatfs64(res, fd, sz, buf) \
+ __sanitizer_syscall_post_impl_fstatfs64(res, (long)(fd), (long)(sz), \
+ (long)(buf))
+#define __sanitizer_syscall_pre_lstat(filename, statbuf) \
+ __sanitizer_syscall_pre_impl_lstat((long)(filename), (long)(statbuf))
+#define __sanitizer_syscall_post_lstat(res, filename, statbuf) \
+ __sanitizer_syscall_post_impl_lstat(res, (long)(filename), (long)(statbuf))
+#define __sanitizer_syscall_pre_fstat(fd, statbuf) \
+ __sanitizer_syscall_pre_impl_fstat((long)(fd), (long)(statbuf))
+#define __sanitizer_syscall_post_fstat(res, fd, statbuf) \
+ __sanitizer_syscall_post_impl_fstat(res, (long)(fd), (long)(statbuf))
+#define __sanitizer_syscall_pre_newstat(filename, statbuf) \
+ __sanitizer_syscall_pre_impl_newstat((long)(filename), (long)(statbuf))
+#define __sanitizer_syscall_post_newstat(res, filename, statbuf) \
+ __sanitizer_syscall_post_impl_newstat(res, (long)(filename), (long)(statbuf))
+#define __sanitizer_syscall_pre_newlstat(filename, statbuf) \
+ __sanitizer_syscall_pre_impl_newlstat((long)(filename), (long)(statbuf))
+#define __sanitizer_syscall_post_newlstat(res, filename, statbuf) \
+ __sanitizer_syscall_post_impl_newlstat(res, (long)(filename), (long)(statbuf))
+#define __sanitizer_syscall_pre_newfstat(fd, statbuf) \
+ __sanitizer_syscall_pre_impl_newfstat((long)(fd), (long)(statbuf))
+#define __sanitizer_syscall_post_newfstat(res, fd, statbuf) \
+ __sanitizer_syscall_post_impl_newfstat(res, (long)(fd), (long)(statbuf))
+#define __sanitizer_syscall_pre_ustat(dev, ubuf) \
+ __sanitizer_syscall_pre_impl_ustat((long)(dev), (long)(ubuf))
+#define __sanitizer_syscall_post_ustat(res, dev, ubuf) \
+ __sanitizer_syscall_post_impl_ustat(res, (long)(dev), (long)(ubuf))
+#define __sanitizer_syscall_pre_stat64(filename, statbuf) \
+ __sanitizer_syscall_pre_impl_stat64((long)(filename), (long)(statbuf))
+#define __sanitizer_syscall_post_stat64(res, filename, statbuf) \
+ __sanitizer_syscall_post_impl_stat64(res, (long)(filename), (long)(statbuf))
+#define __sanitizer_syscall_pre_fstat64(fd, statbuf) \
+ __sanitizer_syscall_pre_impl_fstat64((long)(fd), (long)(statbuf))
+#define __sanitizer_syscall_post_fstat64(res, fd, statbuf) \
+ __sanitizer_syscall_post_impl_fstat64(res, (long)(fd), (long)(statbuf))
+#define __sanitizer_syscall_pre_lstat64(filename, statbuf) \
+ __sanitizer_syscall_pre_impl_lstat64((long)(filename), (long)(statbuf))
+#define __sanitizer_syscall_post_lstat64(res, filename, statbuf) \
+ __sanitizer_syscall_post_impl_lstat64(res, (long)(filename), (long)(statbuf))
+#define __sanitizer_syscall_pre_setxattr(path, name, value, size, flags) \
+ __sanitizer_syscall_pre_impl_setxattr( \
+ (long)(path), (long)(name), (long)(value), (long)(size), (long)(flags))
+#define __sanitizer_syscall_post_setxattr(res, path, name, value, size, flags) \
+ __sanitizer_syscall_post_impl_setxattr(res, (long)(path), (long)(name), \
+ (long)(value), (long)(size), \
+ (long)(flags))
+#define __sanitizer_syscall_pre_lsetxattr(path, name, value, size, flags) \
+ __sanitizer_syscall_pre_impl_lsetxattr( \
+ (long)(path), (long)(name), (long)(value), (long)(size), (long)(flags))
+#define __sanitizer_syscall_post_lsetxattr(res, path, name, value, size, \
+ flags) \
+ __sanitizer_syscall_post_impl_lsetxattr(res, (long)(path), (long)(name), \
+ (long)(value), (long)(size), \
+ (long)(flags))
+#define __sanitizer_syscall_pre_fsetxattr(fd, name, value, size, flags) \
+ __sanitizer_syscall_pre_impl_fsetxattr( \
+ (long)(fd), (long)(name), (long)(value), (long)(size), (long)(flags))
+#define __sanitizer_syscall_post_fsetxattr(res, fd, name, value, size, flags) \
+ __sanitizer_syscall_post_impl_fsetxattr(res, (long)(fd), (long)(name), \
+ (long)(value), (long)(size), \
+ (long)(flags))
+#define __sanitizer_syscall_pre_getxattr(path, name, value, size) \
+ __sanitizer_syscall_pre_impl_getxattr((long)(path), (long)(name), \
+ (long)(value), (long)(size))
+#define __sanitizer_syscall_post_getxattr(res, path, name, value, size) \
+ __sanitizer_syscall_post_impl_getxattr(res, (long)(path), (long)(name), \
+ (long)(value), (long)(size))
+#define __sanitizer_syscall_pre_lgetxattr(path, name, value, size) \
+ __sanitizer_syscall_pre_impl_lgetxattr((long)(path), (long)(name), \
+ (long)(value), (long)(size))
+#define __sanitizer_syscall_post_lgetxattr(res, path, name, value, size) \
+ __sanitizer_syscall_post_impl_lgetxattr(res, (long)(path), (long)(name), \
+ (long)(value), (long)(size))
+#define __sanitizer_syscall_pre_fgetxattr(fd, name, value, size) \
+ __sanitizer_syscall_pre_impl_fgetxattr((long)(fd), (long)(name), \
+ (long)(value), (long)(size))
+#define __sanitizer_syscall_post_fgetxattr(res, fd, name, value, size) \
+ __sanitizer_syscall_post_impl_fgetxattr(res, (long)(fd), (long)(name), \
+ (long)(value), (long)(size))
+#define __sanitizer_syscall_pre_listxattr(path, list, size) \
+ __sanitizer_syscall_pre_impl_listxattr((long)(path), (long)(list), \
+ (long)(size))
+#define __sanitizer_syscall_post_listxattr(res, path, list, size) \
+ __sanitizer_syscall_post_impl_listxattr(res, (long)(path), (long)(list), \
+ (long)(size))
+#define __sanitizer_syscall_pre_llistxattr(path, list, size) \
+ __sanitizer_syscall_pre_impl_llistxattr((long)(path), (long)(list), \
+ (long)(size))
+#define __sanitizer_syscall_post_llistxattr(res, path, list, size) \
+ __sanitizer_syscall_post_impl_llistxattr(res, (long)(path), (long)(list), \
+ (long)(size))
+#define __sanitizer_syscall_pre_flistxattr(fd, list, size) \
+ __sanitizer_syscall_pre_impl_flistxattr((long)(fd), (long)(list), \
+ (long)(size))
+#define __sanitizer_syscall_post_flistxattr(res, fd, list, size) \
+ __sanitizer_syscall_post_impl_flistxattr(res, (long)(fd), (long)(list), \
+ (long)(size))
+#define __sanitizer_syscall_pre_removexattr(path, name) \
+ __sanitizer_syscall_pre_impl_removexattr((long)(path), (long)(name))
+#define __sanitizer_syscall_post_removexattr(res, path, name) \
+ __sanitizer_syscall_post_impl_removexattr(res, (long)(path), (long)(name))
+#define __sanitizer_syscall_pre_lremovexattr(path, name) \
+ __sanitizer_syscall_pre_impl_lremovexattr((long)(path), (long)(name))
+#define __sanitizer_syscall_post_lremovexattr(res, path, name) \
+ __sanitizer_syscall_post_impl_lremovexattr(res, (long)(path), (long)(name))
+#define __sanitizer_syscall_pre_fremovexattr(fd, name) \
+ __sanitizer_syscall_pre_impl_fremovexattr((long)(fd), (long)(name))
+#define __sanitizer_syscall_post_fremovexattr(res, fd, name) \
+ __sanitizer_syscall_post_impl_fremovexattr(res, (long)(fd), (long)(name))
+#define __sanitizer_syscall_pre_brk(brk) \
+ __sanitizer_syscall_pre_impl_brk((long)(brk))
+#define __sanitizer_syscall_post_brk(res, brk) \
+ __sanitizer_syscall_post_impl_brk(res, (long)(brk))
+#define __sanitizer_syscall_pre_mprotect(start, len, prot) \
+ __sanitizer_syscall_pre_impl_mprotect((long)(start), (long)(len), \
+ (long)(prot))
+#define __sanitizer_syscall_post_mprotect(res, start, len, prot) \
+ __sanitizer_syscall_post_impl_mprotect(res, (long)(start), (long)(len), \
+ (long)(prot))
+#define __sanitizer_syscall_pre_mremap(addr, old_len, new_len, flags, \
+ new_addr) \
+ __sanitizer_syscall_pre_impl_mremap((long)(addr), (long)(old_len), \
+ (long)(new_len), (long)(flags), \
+ (long)(new_addr))
+#define __sanitizer_syscall_post_mremap(res, addr, old_len, new_len, flags, \
+ new_addr) \
+ __sanitizer_syscall_post_impl_mremap(res, (long)(addr), (long)(old_len), \
+ (long)(new_len), (long)(flags), \
+ (long)(new_addr))
+#define __sanitizer_syscall_pre_remap_file_pages(start, size, prot, pgoff, \
+ flags) \
+ __sanitizer_syscall_pre_impl_remap_file_pages( \
+ (long)(start), (long)(size), (long)(prot), (long)(pgoff), (long)(flags))
+#define __sanitizer_syscall_post_remap_file_pages(res, start, size, prot, \
+ pgoff, flags) \
+ __sanitizer_syscall_post_impl_remap_file_pages(res, (long)(start), \
+ (long)(size), (long)(prot), \
+ (long)(pgoff), (long)(flags))
+#define __sanitizer_syscall_pre_msync(start, len, flags) \
+ __sanitizer_syscall_pre_impl_msync((long)(start), (long)(len), (long)(flags))
+#define __sanitizer_syscall_post_msync(res, start, len, flags) \
+ __sanitizer_syscall_post_impl_msync(res, (long)(start), (long)(len), \
+ (long)(flags))
+#define __sanitizer_syscall_pre_munmap(addr, len) \
+ __sanitizer_syscall_pre_impl_munmap((long)(addr), (long)(len))
+#define __sanitizer_syscall_post_munmap(res, addr, len) \
+ __sanitizer_syscall_post_impl_munmap(res, (long)(addr), (long)(len))
+#define __sanitizer_syscall_pre_mlock(start, len) \
+ __sanitizer_syscall_pre_impl_mlock((long)(start), (long)(len))
+#define __sanitizer_syscall_post_mlock(res, start, len) \
+ __sanitizer_syscall_post_impl_mlock(res, (long)(start), (long)(len))
+#define __sanitizer_syscall_pre_munlock(start, len) \
+ __sanitizer_syscall_pre_impl_munlock((long)(start), (long)(len))
+#define __sanitizer_syscall_post_munlock(res, start, len) \
+ __sanitizer_syscall_post_impl_munlock(res, (long)(start), (long)(len))
+#define __sanitizer_syscall_pre_mlockall(flags) \
+ __sanitizer_syscall_pre_impl_mlockall((long)(flags))
+#define __sanitizer_syscall_post_mlockall(res, flags) \
+ __sanitizer_syscall_post_impl_mlockall(res, (long)(flags))
+#define __sanitizer_syscall_pre_munlockall() \
+ __sanitizer_syscall_pre_impl_munlockall()
+#define __sanitizer_syscall_post_munlockall(res) \
+ __sanitizer_syscall_post_impl_munlockall(res)
+#define __sanitizer_syscall_pre_madvise(start, len, behavior) \
+ __sanitizer_syscall_pre_impl_madvise((long)(start), (long)(len), \
+ (long)(behavior))
+#define __sanitizer_syscall_post_madvise(res, start, len, behavior) \
+ __sanitizer_syscall_post_impl_madvise(res, (long)(start), (long)(len), \
+ (long)(behavior))
+#define __sanitizer_syscall_pre_mincore(start, len, vec) \
+ __sanitizer_syscall_pre_impl_mincore((long)(start), (long)(len), (long)(vec))
+#define __sanitizer_syscall_post_mincore(res, start, len, vec) \
+ __sanitizer_syscall_post_impl_mincore(res, (long)(start), (long)(len), \
+ (long)(vec))
+#define __sanitizer_syscall_pre_pivot_root(new_root, put_old) \
+ __sanitizer_syscall_pre_impl_pivot_root((long)(new_root), (long)(put_old))
+#define __sanitizer_syscall_post_pivot_root(res, new_root, put_old) \
+ __sanitizer_syscall_post_impl_pivot_root(res, (long)(new_root), \
+ (long)(put_old))
+#define __sanitizer_syscall_pre_chroot(filename) \
+ __sanitizer_syscall_pre_impl_chroot((long)(filename))
+#define __sanitizer_syscall_post_chroot(res, filename) \
+ __sanitizer_syscall_post_impl_chroot(res, (long)(filename))
+#define __sanitizer_syscall_pre_mknod(filename, mode, dev) \
+ __sanitizer_syscall_pre_impl_mknod((long)(filename), (long)(mode), \
+ (long)(dev))
+#define __sanitizer_syscall_post_mknod(res, filename, mode, dev) \
+ __sanitizer_syscall_post_impl_mknod(res, (long)(filename), (long)(mode), \
+ (long)(dev))
+#define __sanitizer_syscall_pre_link(oldname, newname) \
+ __sanitizer_syscall_pre_impl_link((long)(oldname), (long)(newname))
+#define __sanitizer_syscall_post_link(res, oldname, newname) \
+ __sanitizer_syscall_post_impl_link(res, (long)(oldname), (long)(newname))
+#define __sanitizer_syscall_pre_symlink(old, new_) \
+ __sanitizer_syscall_pre_impl_symlink((long)(old), (long)(new_))
+#define __sanitizer_syscall_post_symlink(res, old, new_) \
+ __sanitizer_syscall_post_impl_symlink(res, (long)(old), (long)(new_))
+#define __sanitizer_syscall_pre_unlink(pathname) \
+ __sanitizer_syscall_pre_impl_unlink((long)(pathname))
+#define __sanitizer_syscall_post_unlink(res, pathname) \
+ __sanitizer_syscall_post_impl_unlink(res, (long)(pathname))
+#define __sanitizer_syscall_pre_rename(oldname, newname) \
+ __sanitizer_syscall_pre_impl_rename((long)(oldname), (long)(newname))
+#define __sanitizer_syscall_post_rename(res, oldname, newname) \
+ __sanitizer_syscall_post_impl_rename(res, (long)(oldname), (long)(newname))
+#define __sanitizer_syscall_pre_chmod(filename, mode) \
+ __sanitizer_syscall_pre_impl_chmod((long)(filename), (long)(mode))
+#define __sanitizer_syscall_post_chmod(res, filename, mode) \
+ __sanitizer_syscall_post_impl_chmod(res, (long)(filename), (long)(mode))
+#define __sanitizer_syscall_pre_fchmod(fd, mode) \
+ __sanitizer_syscall_pre_impl_fchmod((long)(fd), (long)(mode))
+#define __sanitizer_syscall_post_fchmod(res, fd, mode) \
+ __sanitizer_syscall_post_impl_fchmod(res, (long)(fd), (long)(mode))
+#define __sanitizer_syscall_pre_fcntl(fd, cmd, arg) \
+ __sanitizer_syscall_pre_impl_fcntl((long)(fd), (long)(cmd), (long)(arg))
+#define __sanitizer_syscall_post_fcntl(res, fd, cmd, arg) \
+ __sanitizer_syscall_post_impl_fcntl(res, (long)(fd), (long)(cmd), (long)(arg))
+#define __sanitizer_syscall_pre_fcntl64(fd, cmd, arg) \
+ __sanitizer_syscall_pre_impl_fcntl64((long)(fd), (long)(cmd), (long)(arg))
+#define __sanitizer_syscall_post_fcntl64(res, fd, cmd, arg) \
+ __sanitizer_syscall_post_impl_fcntl64(res, (long)(fd), (long)(cmd), \
+ (long)(arg))
+#define __sanitizer_syscall_pre_pipe(fildes) \
+ __sanitizer_syscall_pre_impl_pipe((long)(fildes))
+#define __sanitizer_syscall_post_pipe(res, fildes) \
+ __sanitizer_syscall_post_impl_pipe(res, (long)(fildes))
+#define __sanitizer_syscall_pre_pipe2(fildes, flags) \
+ __sanitizer_syscall_pre_impl_pipe2((long)(fildes), (long)(flags))
+#define __sanitizer_syscall_post_pipe2(res, fildes, flags) \
+ __sanitizer_syscall_post_impl_pipe2(res, (long)(fildes), (long)(flags))
+#define __sanitizer_syscall_pre_dup(fildes) \
+ __sanitizer_syscall_pre_impl_dup((long)(fildes))
+#define __sanitizer_syscall_post_dup(res, fildes) \
+ __sanitizer_syscall_post_impl_dup(res, (long)(fildes))
+#define __sanitizer_syscall_pre_dup2(oldfd, newfd) \
+ __sanitizer_syscall_pre_impl_dup2((long)(oldfd), (long)(newfd))
+#define __sanitizer_syscall_post_dup2(res, oldfd, newfd) \
+ __sanitizer_syscall_post_impl_dup2(res, (long)(oldfd), (long)(newfd))
+#define __sanitizer_syscall_pre_dup3(oldfd, newfd, flags) \
+ __sanitizer_syscall_pre_impl_dup3((long)(oldfd), (long)(newfd), (long)(flags))
+#define __sanitizer_syscall_post_dup3(res, oldfd, newfd, flags) \
+ __sanitizer_syscall_post_impl_dup3(res, (long)(oldfd), (long)(newfd), \
+ (long)(flags))
+#define __sanitizer_syscall_pre_ioperm(from, num, on) \
+ __sanitizer_syscall_pre_impl_ioperm((long)(from), (long)(num), (long)(on))
+#define __sanitizer_syscall_post_ioperm(res, from, num, on) \
+ __sanitizer_syscall_post_impl_ioperm(res, (long)(from), (long)(num), \
+ (long)(on))
+#define __sanitizer_syscall_pre_ioctl(fd, cmd, arg) \
+ __sanitizer_syscall_pre_impl_ioctl((long)(fd), (long)(cmd), (long)(arg))
+#define __sanitizer_syscall_post_ioctl(res, fd, cmd, arg) \
+ __sanitizer_syscall_post_impl_ioctl(res, (long)(fd), (long)(cmd), (long)(arg))
+#define __sanitizer_syscall_pre_flock(fd, cmd) \
+ __sanitizer_syscall_pre_impl_flock((long)(fd), (long)(cmd))
+#define __sanitizer_syscall_post_flock(res, fd, cmd) \
+ __sanitizer_syscall_post_impl_flock(res, (long)(fd), (long)(cmd))
+#define __sanitizer_syscall_pre_io_setup(nr_reqs, ctx) \
+ __sanitizer_syscall_pre_impl_io_setup((long)(nr_reqs), (long)(ctx))
+#define __sanitizer_syscall_post_io_setup(res, nr_reqs, ctx) \
+ __sanitizer_syscall_post_impl_io_setup(res, (long)(nr_reqs), (long)(ctx))
+#define __sanitizer_syscall_pre_io_destroy(ctx) \
+ __sanitizer_syscall_pre_impl_io_destroy((long)(ctx))
+#define __sanitizer_syscall_post_io_destroy(res, ctx) \
+ __sanitizer_syscall_post_impl_io_destroy(res, (long)(ctx))
+#define __sanitizer_syscall_pre_io_getevents(ctx_id, min_nr, nr, events, \
+ timeout) \
+ __sanitizer_syscall_pre_impl_io_getevents((long)(ctx_id), (long)(min_nr), \
+ (long)(nr), (long)(events), \
+ (long)(timeout))
+#define __sanitizer_syscall_post_io_getevents(res, ctx_id, min_nr, nr, events, \
+ timeout) \
+ __sanitizer_syscall_post_impl_io_getevents(res, (long)(ctx_id), \
+ (long)(min_nr), (long)(nr), \
+ (long)(events), (long)(timeout))
+#define __sanitizer_syscall_pre_io_submit(ctx_id, arg1, arg2) \
+ __sanitizer_syscall_pre_impl_io_submit((long)(ctx_id), (long)(arg1), \
+ (long)(arg2))
+#define __sanitizer_syscall_post_io_submit(res, ctx_id, arg1, arg2) \
+ __sanitizer_syscall_post_impl_io_submit(res, (long)(ctx_id), (long)(arg1), \
+ (long)(arg2))
+#define __sanitizer_syscall_pre_io_cancel(ctx_id, iocb, result) \
+ __sanitizer_syscall_pre_impl_io_cancel((long)(ctx_id), (long)(iocb), \
+ (long)(result))
+#define __sanitizer_syscall_post_io_cancel(res, ctx_id, iocb, result) \
+ __sanitizer_syscall_post_impl_io_cancel(res, (long)(ctx_id), (long)(iocb), \
+ (long)(result))
+#define __sanitizer_syscall_pre_sendfile(out_fd, in_fd, offset, count) \
+ __sanitizer_syscall_pre_impl_sendfile((long)(out_fd), (long)(in_fd), \
+ (long)(offset), (long)(count))
+#define __sanitizer_syscall_post_sendfile(res, out_fd, in_fd, offset, count) \
+ __sanitizer_syscall_post_impl_sendfile(res, (long)(out_fd), (long)(in_fd), \
+ (long)(offset), (long)(count))
+#define __sanitizer_syscall_pre_sendfile64(out_fd, in_fd, offset, count) \
+ __sanitizer_syscall_pre_impl_sendfile64((long)(out_fd), (long)(in_fd), \
+ (long)(offset), (long)(count))
+#define __sanitizer_syscall_post_sendfile64(res, out_fd, in_fd, offset, count) \
+ __sanitizer_syscall_post_impl_sendfile64(res, (long)(out_fd), (long)(in_fd), \
+ (long)(offset), (long)(count))
+#define __sanitizer_syscall_pre_readlink(path, buf, bufsiz) \
+ __sanitizer_syscall_pre_impl_readlink((long)(path), (long)(buf), \
+ (long)(bufsiz))
+#define __sanitizer_syscall_post_readlink(res, path, buf, bufsiz) \
+ __sanitizer_syscall_post_impl_readlink(res, (long)(path), (long)(buf), \
+ (long)(bufsiz))
+#define __sanitizer_syscall_pre_creat(pathname, mode) \
+ __sanitizer_syscall_pre_impl_creat((long)(pathname), (long)(mode))
+#define __sanitizer_syscall_post_creat(res, pathname, mode) \
+ __sanitizer_syscall_post_impl_creat(res, (long)(pathname), (long)(mode))
+#define __sanitizer_syscall_pre_open(filename, flags, mode) \
+ __sanitizer_syscall_pre_impl_open((long)(filename), (long)(flags), \
+ (long)(mode))
+#define __sanitizer_syscall_post_open(res, filename, flags, mode) \
+ __sanitizer_syscall_post_impl_open(res, (long)(filename), (long)(flags), \
+ (long)(mode))
+#define __sanitizer_syscall_pre_close(fd) \
+ __sanitizer_syscall_pre_impl_close((long)(fd))
+#define __sanitizer_syscall_post_close(res, fd) \
+ __sanitizer_syscall_post_impl_close(res, (long)(fd))
+#define __sanitizer_syscall_pre_access(filename, mode) \
+ __sanitizer_syscall_pre_impl_access((long)(filename), (long)(mode))
+#define __sanitizer_syscall_post_access(res, filename, mode) \
+ __sanitizer_syscall_post_impl_access(res, (long)(filename), (long)(mode))
+#define __sanitizer_syscall_pre_vhangup() __sanitizer_syscall_pre_impl_vhangup()
+#define __sanitizer_syscall_post_vhangup(res) \
+ __sanitizer_syscall_post_impl_vhangup(res)
+#define __sanitizer_syscall_pre_chown(filename, user, group) \
+ __sanitizer_syscall_pre_impl_chown((long)(filename), (long)(user), \
+ (long)(group))
+#define __sanitizer_syscall_post_chown(res, filename, user, group) \
+ __sanitizer_syscall_post_impl_chown(res, (long)(filename), (long)(user), \
+ (long)(group))
+#define __sanitizer_syscall_pre_lchown(filename, user, group) \
+ __sanitizer_syscall_pre_impl_lchown((long)(filename), (long)(user), \
+ (long)(group))
+#define __sanitizer_syscall_post_lchown(res, filename, user, group) \
+ __sanitizer_syscall_post_impl_lchown(res, (long)(filename), (long)(user), \
+ (long)(group))
+#define __sanitizer_syscall_pre_fchown(fd, user, group) \
+ __sanitizer_syscall_pre_impl_fchown((long)(fd), (long)(user), (long)(group))
+#define __sanitizer_syscall_post_fchown(res, fd, user, group) \
+ __sanitizer_syscall_post_impl_fchown(res, (long)(fd), (long)(user), \
+ (long)(group))
+#define __sanitizer_syscall_pre_chown16(filename, user, group) \
+ __sanitizer_syscall_pre_impl_chown16((long)(filename), (long)user, \
+ (long)group)
+#define __sanitizer_syscall_post_chown16(res, filename, user, group) \
+ __sanitizer_syscall_post_impl_chown16(res, (long)(filename), (long)user, \
+ (long)group)
+#define __sanitizer_syscall_pre_lchown16(filename, user, group) \
+ __sanitizer_syscall_pre_impl_lchown16((long)(filename), (long)user, \
+ (long)group)
+#define __sanitizer_syscall_post_lchown16(res, filename, user, group) \
+ __sanitizer_syscall_post_impl_lchown16(res, (long)(filename), (long)user, \
+ (long)group)
+#define __sanitizer_syscall_pre_fchown16(fd, user, group) \
+ __sanitizer_syscall_pre_impl_fchown16((long)(fd), (long)user, (long)group)
+#define __sanitizer_syscall_post_fchown16(res, fd, user, group) \
+ __sanitizer_syscall_post_impl_fchown16(res, (long)(fd), (long)user, \
+ (long)group)
+#define __sanitizer_syscall_pre_setregid16(rgid, egid) \
+ __sanitizer_syscall_pre_impl_setregid16((long)rgid, (long)egid)
+#define __sanitizer_syscall_post_setregid16(res, rgid, egid) \
+ __sanitizer_syscall_post_impl_setregid16(res, (long)rgid, (long)egid)
+#define __sanitizer_syscall_pre_setgid16(gid) \
+ __sanitizer_syscall_pre_impl_setgid16((long)gid)
+#define __sanitizer_syscall_post_setgid16(res, gid) \
+ __sanitizer_syscall_post_impl_setgid16(res, (long)gid)
+#define __sanitizer_syscall_pre_setreuid16(ruid, euid) \
+ __sanitizer_syscall_pre_impl_setreuid16((long)ruid, (long)euid)
+#define __sanitizer_syscall_post_setreuid16(res, ruid, euid) \
+ __sanitizer_syscall_post_impl_setreuid16(res, (long)ruid, (long)euid)
+#define __sanitizer_syscall_pre_setuid16(uid) \
+ __sanitizer_syscall_pre_impl_setuid16((long)uid)
+#define __sanitizer_syscall_post_setuid16(res, uid) \
+ __sanitizer_syscall_post_impl_setuid16(res, (long)uid)
+#define __sanitizer_syscall_pre_setresuid16(ruid, euid, suid) \
+ __sanitizer_syscall_pre_impl_setresuid16((long)ruid, (long)euid, (long)suid)
+#define __sanitizer_syscall_post_setresuid16(res, ruid, euid, suid) \
+ __sanitizer_syscall_post_impl_setresuid16(res, (long)ruid, (long)euid, \
+ (long)suid)
+#define __sanitizer_syscall_pre_getresuid16(ruid, euid, suid) \
+ __sanitizer_syscall_pre_impl_getresuid16((long)(ruid), (long)(euid), \
+ (long)(suid))
+#define __sanitizer_syscall_post_getresuid16(res, ruid, euid, suid) \
+ __sanitizer_syscall_post_impl_getresuid16(res, (long)(ruid), (long)(euid), \
+ (long)(suid))
+#define __sanitizer_syscall_pre_setresgid16(rgid, egid, sgid) \
+ __sanitizer_syscall_pre_impl_setresgid16((long)rgid, (long)egid, (long)sgid)
+#define __sanitizer_syscall_post_setresgid16(res, rgid, egid, sgid) \
+ __sanitizer_syscall_post_impl_setresgid16(res, (long)rgid, (long)egid, \
+ (long)sgid)
+#define __sanitizer_syscall_pre_getresgid16(rgid, egid, sgid) \
+ __sanitizer_syscall_pre_impl_getresgid16((long)(rgid), (long)(egid), \
+ (long)(sgid))
+#define __sanitizer_syscall_post_getresgid16(res, rgid, egid, sgid) \
+ __sanitizer_syscall_post_impl_getresgid16(res, (long)(rgid), (long)(egid), \
+ (long)(sgid))
+#define __sanitizer_syscall_pre_setfsuid16(uid) \
+ __sanitizer_syscall_pre_impl_setfsuid16((long)uid)
+#define __sanitizer_syscall_post_setfsuid16(res, uid) \
+ __sanitizer_syscall_post_impl_setfsuid16(res, (long)uid)
+#define __sanitizer_syscall_pre_setfsgid16(gid) \
+ __sanitizer_syscall_pre_impl_setfsgid16((long)gid)
+#define __sanitizer_syscall_post_setfsgid16(res, gid) \
+ __sanitizer_syscall_post_impl_setfsgid16(res, (long)gid)
+#define __sanitizer_syscall_pre_getgroups16(gidsetsize, grouplist) \
+ __sanitizer_syscall_pre_impl_getgroups16((long)(gidsetsize), \
+ (long)(grouplist))
+#define __sanitizer_syscall_post_getgroups16(res, gidsetsize, grouplist) \
+ __sanitizer_syscall_post_impl_getgroups16(res, (long)(gidsetsize), \
+ (long)(grouplist))
+#define __sanitizer_syscall_pre_setgroups16(gidsetsize, grouplist) \
+ __sanitizer_syscall_pre_impl_setgroups16((long)(gidsetsize), \
+ (long)(grouplist))
+#define __sanitizer_syscall_post_setgroups16(res, gidsetsize, grouplist) \
+ __sanitizer_syscall_post_impl_setgroups16(res, (long)(gidsetsize), \
+ (long)(grouplist))
+#define __sanitizer_syscall_pre_getuid16() \
+ __sanitizer_syscall_pre_impl_getuid16()
+#define __sanitizer_syscall_post_getuid16(res) \
+ __sanitizer_syscall_post_impl_getuid16(res)
+#define __sanitizer_syscall_pre_geteuid16() \
+ __sanitizer_syscall_pre_impl_geteuid16()
+#define __sanitizer_syscall_post_geteuid16(res) \
+ __sanitizer_syscall_post_impl_geteuid16(res)
+#define __sanitizer_syscall_pre_getgid16() \
+ __sanitizer_syscall_pre_impl_getgid16()
+#define __sanitizer_syscall_post_getgid16(res) \
+ __sanitizer_syscall_post_impl_getgid16(res)
+#define __sanitizer_syscall_pre_getegid16() \
+ __sanitizer_syscall_pre_impl_getegid16()
+#define __sanitizer_syscall_post_getegid16(res) \
+ __sanitizer_syscall_post_impl_getegid16(res)
+#define __sanitizer_syscall_pre_utime(filename, times) \
+ __sanitizer_syscall_pre_impl_utime((long)(filename), (long)(times))
+#define __sanitizer_syscall_post_utime(res, filename, times) \
+ __sanitizer_syscall_post_impl_utime(res, (long)(filename), (long)(times))
+#define __sanitizer_syscall_pre_utimes(filename, utimes) \
+ __sanitizer_syscall_pre_impl_utimes((long)(filename), (long)(utimes))
+#define __sanitizer_syscall_post_utimes(res, filename, utimes) \
+ __sanitizer_syscall_post_impl_utimes(res, (long)(filename), (long)(utimes))
+#define __sanitizer_syscall_pre_lseek(fd, offset, origin) \
+ __sanitizer_syscall_pre_impl_lseek((long)(fd), (long)(offset), (long)(origin))
+#define __sanitizer_syscall_post_lseek(res, fd, offset, origin) \
+ __sanitizer_syscall_post_impl_lseek(res, (long)(fd), (long)(offset), \
+ (long)(origin))
+#define __sanitizer_syscall_pre_llseek(fd, offset_high, offset_low, result, \
+ origin) \
+ __sanitizer_syscall_pre_impl_llseek((long)(fd), (long)(offset_high), \
+ (long)(offset_low), (long)(result), \
+ (long)(origin))
+#define __sanitizer_syscall_post_llseek(res, fd, offset_high, offset_low, \
+ result, origin) \
+ __sanitizer_syscall_post_impl_llseek(res, (long)(fd), (long)(offset_high), \
+ (long)(offset_low), (long)(result), \
+ (long)(origin))
+#define __sanitizer_syscall_pre_read(fd, buf, count) \
+ __sanitizer_syscall_pre_impl_read((long)(fd), (long)(buf), (long)(count))
+#define __sanitizer_syscall_post_read(res, fd, buf, count) \
+ __sanitizer_syscall_post_impl_read(res, (long)(fd), (long)(buf), \
+ (long)(count))
+#define __sanitizer_syscall_pre_readv(fd, vec, vlen) \
+ __sanitizer_syscall_pre_impl_readv((long)(fd), (long)(vec), (long)(vlen))
+#define __sanitizer_syscall_post_readv(res, fd, vec, vlen) \
+ __sanitizer_syscall_post_impl_readv(res, (long)(fd), (long)(vec), \
+ (long)(vlen))
+#define __sanitizer_syscall_pre_write(fd, buf, count) \
+ __sanitizer_syscall_pre_impl_write((long)(fd), (long)(buf), (long)(count))
+#define __sanitizer_syscall_post_write(res, fd, buf, count) \
+ __sanitizer_syscall_post_impl_write(res, (long)(fd), (long)(buf), \
+ (long)(count))
+#define __sanitizer_syscall_pre_writev(fd, vec, vlen) \
+ __sanitizer_syscall_pre_impl_writev((long)(fd), (long)(vec), (long)(vlen))
+#define __sanitizer_syscall_post_writev(res, fd, vec, vlen) \
+ __sanitizer_syscall_post_impl_writev(res, (long)(fd), (long)(vec), \
+ (long)(vlen))
+
+#ifdef _LP64
+#define __sanitizer_syscall_pre_pread64(fd, buf, count, pos) \
+ __sanitizer_syscall_pre_impl_pread64((long)(fd), (long)(buf), (long)(count), \
+ (long)(pos))
+#define __sanitizer_syscall_post_pread64(res, fd, buf, count, pos) \
+ __sanitizer_syscall_post_impl_pread64(res, (long)(fd), (long)(buf), \
+ (long)(count), (long)(pos))
+#define __sanitizer_syscall_pre_pwrite64(fd, buf, count, pos) \
+ __sanitizer_syscall_pre_impl_pwrite64((long)(fd), (long)(buf), \
+ (long)(count), (long)(pos))
+#define __sanitizer_syscall_post_pwrite64(res, fd, buf, count, pos) \
+ __sanitizer_syscall_post_impl_pwrite64(res, (long)(fd), (long)(buf), \
+ (long)(count), (long)(pos))
+#else
+#define __sanitizer_syscall_pre_pread64(fd, buf, count, pos0, pos1) \
+ __sanitizer_syscall_pre_impl_pread64((long)(fd), (long)(buf), (long)(count), \
+ (long)(pos))
+#define __sanitizer_syscall_post_pread64(res, fd, buf, count, pos0, pos1) \
+ __sanitizer_syscall_post_impl_pread64(res, (long)(fd), (long)(buf), \
+ (long)(count), (long)(pos))
+#define __sanitizer_syscall_pre_pwrite64(fd, buf, count, pos0, pos1) \
+ __sanitizer_syscall_pre_impl_pwrite64( \
+ (long)(fd), (long)(buf), (long)(count), (long)(pos0), (long)(pos1))
+#define __sanitizer_syscall_post_pwrite64(res, fd, buf, count, pos0, pos1) \
+ __sanitizer_syscall_post_impl_pwrite64( \
+ res, (long)(fd), (long)(buf), (long)(count), (long)(pos0), (long)(pos1))
+#endif
+
+#define __sanitizer_syscall_pre_preadv(fd, vec, vlen, pos_l, pos_h) \
+ __sanitizer_syscall_pre_impl_preadv((long)(fd), (long)(vec), (long)(vlen), \
+ (long)(pos_l), (long)(pos_h))
+#define __sanitizer_syscall_post_preadv(res, fd, vec, vlen, pos_l, pos_h) \
+ __sanitizer_syscall_post_impl_preadv(res, (long)(fd), (long)(vec), \
+ (long)(vlen), (long)(pos_l), \
+ (long)(pos_h))
+#define __sanitizer_syscall_pre_pwritev(fd, vec, vlen, pos_l, pos_h) \
+ __sanitizer_syscall_pre_impl_pwritev((long)(fd), (long)(vec), (long)(vlen), \
+ (long)(pos_l), (long)(pos_h))
+#define __sanitizer_syscall_post_pwritev(res, fd, vec, vlen, pos_l, pos_h) \
+ __sanitizer_syscall_post_impl_pwritev(res, (long)(fd), (long)(vec), \
+ (long)(vlen), (long)(pos_l), \
+ (long)(pos_h))
+#define __sanitizer_syscall_pre_getcwd(buf, size) \
+ __sanitizer_syscall_pre_impl_getcwd((long)(buf), (long)(size))
+#define __sanitizer_syscall_post_getcwd(res, buf, size) \
+ __sanitizer_syscall_post_impl_getcwd(res, (long)(buf), (long)(size))
+#define __sanitizer_syscall_pre_mkdir(pathname, mode) \
+ __sanitizer_syscall_pre_impl_mkdir((long)(pathname), (long)(mode))
+#define __sanitizer_syscall_post_mkdir(res, pathname, mode) \
+ __sanitizer_syscall_post_impl_mkdir(res, (long)(pathname), (long)(mode))
+#define __sanitizer_syscall_pre_chdir(filename) \
+ __sanitizer_syscall_pre_impl_chdir((long)(filename))
+#define __sanitizer_syscall_post_chdir(res, filename) \
+ __sanitizer_syscall_post_impl_chdir(res, (long)(filename))
+#define __sanitizer_syscall_pre_fchdir(fd) \
+ __sanitizer_syscall_pre_impl_fchdir((long)(fd))
+#define __sanitizer_syscall_post_fchdir(res, fd) \
+ __sanitizer_syscall_post_impl_fchdir(res, (long)(fd))
+#define __sanitizer_syscall_pre_rmdir(pathname) \
+ __sanitizer_syscall_pre_impl_rmdir((long)(pathname))
+#define __sanitizer_syscall_post_rmdir(res, pathname) \
+ __sanitizer_syscall_post_impl_rmdir(res, (long)(pathname))
+#define __sanitizer_syscall_pre_lookup_dcookie(cookie64, buf, len) \
+ __sanitizer_syscall_pre_impl_lookup_dcookie((long)(cookie64), (long)(buf), \
+ (long)(len))
+#define __sanitizer_syscall_post_lookup_dcookie(res, cookie64, buf, len) \
+ __sanitizer_syscall_post_impl_lookup_dcookie(res, (long)(cookie64), \
+ (long)(buf), (long)(len))
+#define __sanitizer_syscall_pre_quotactl(cmd, special, id, addr) \
+ __sanitizer_syscall_pre_impl_quotactl((long)(cmd), (long)(special), \
+ (long)(id), (long)(addr))
+#define __sanitizer_syscall_post_quotactl(res, cmd, special, id, addr) \
+ __sanitizer_syscall_post_impl_quotactl(res, (long)(cmd), (long)(special), \
+ (long)(id), (long)(addr))
+#define __sanitizer_syscall_pre_getdents(fd, dirent, count) \
+ __sanitizer_syscall_pre_impl_getdents((long)(fd), (long)(dirent), \
+ (long)(count))
+#define __sanitizer_syscall_post_getdents(res, fd, dirent, count) \
+ __sanitizer_syscall_post_impl_getdents(res, (long)(fd), (long)(dirent), \
+ (long)(count))
+#define __sanitizer_syscall_pre_getdents64(fd, dirent, count) \
+ __sanitizer_syscall_pre_impl_getdents64((long)(fd), (long)(dirent), \
+ (long)(count))
+#define __sanitizer_syscall_post_getdents64(res, fd, dirent, count) \
+ __sanitizer_syscall_post_impl_getdents64(res, (long)(fd), (long)(dirent), \
+ (long)(count))
+#define __sanitizer_syscall_pre_setsockopt(fd, level, optname, optval, optlen) \
+ __sanitizer_syscall_pre_impl_setsockopt((long)(fd), (long)(level), \
+ (long)(optname), (long)(optval), \
+ (long)(optlen))
+#define __sanitizer_syscall_post_setsockopt(res, fd, level, optname, optval, \
+ optlen) \
+ __sanitizer_syscall_post_impl_setsockopt(res, (long)(fd), (long)(level), \
+ (long)(optname), (long)(optval), \
+ (long)(optlen))
+#define __sanitizer_syscall_pre_getsockopt(fd, level, optname, optval, optlen) \
+ __sanitizer_syscall_pre_impl_getsockopt((long)(fd), (long)(level), \
+ (long)(optname), (long)(optval), \
+ (long)(optlen))
+#define __sanitizer_syscall_post_getsockopt(res, fd, level, optname, optval, \
+ optlen) \
+ __sanitizer_syscall_post_impl_getsockopt(res, (long)(fd), (long)(level), \
+ (long)(optname), (long)(optval), \
+ (long)(optlen))
+#define __sanitizer_syscall_pre_bind(arg0, arg1, arg2) \
+ __sanitizer_syscall_pre_impl_bind((long)(arg0), (long)(arg1), (long)(arg2))
+#define __sanitizer_syscall_post_bind(res, arg0, arg1, arg2) \
+ __sanitizer_syscall_post_impl_bind(res, (long)(arg0), (long)(arg1), \
+ (long)(arg2))
+#define __sanitizer_syscall_pre_connect(arg0, arg1, arg2) \
+ __sanitizer_syscall_pre_impl_connect((long)(arg0), (long)(arg1), (long)(arg2))
+#define __sanitizer_syscall_post_connect(res, arg0, arg1, arg2) \
+ __sanitizer_syscall_post_impl_connect(res, (long)(arg0), (long)(arg1), \
+ (long)(arg2))
+#define __sanitizer_syscall_pre_accept(arg0, arg1, arg2) \
+ __sanitizer_syscall_pre_impl_accept((long)(arg0), (long)(arg1), (long)(arg2))
+#define __sanitizer_syscall_post_accept(res, arg0, arg1, arg2) \
+ __sanitizer_syscall_post_impl_accept(res, (long)(arg0), (long)(arg1), \
+ (long)(arg2))
+#define __sanitizer_syscall_pre_accept4(arg0, arg1, arg2, arg3) \
+ __sanitizer_syscall_pre_impl_accept4((long)(arg0), (long)(arg1), \
+ (long)(arg2), (long)(arg3))
+#define __sanitizer_syscall_post_accept4(res, arg0, arg1, arg2, arg3) \
+ __sanitizer_syscall_post_impl_accept4(res, (long)(arg0), (long)(arg1), \
+ (long)(arg2), (long)(arg3))
+#define __sanitizer_syscall_pre_getsockname(arg0, arg1, arg2) \
+ __sanitizer_syscall_pre_impl_getsockname((long)(arg0), (long)(arg1), \
+ (long)(arg2))
+#define __sanitizer_syscall_post_getsockname(res, arg0, arg1, arg2) \
+ __sanitizer_syscall_post_impl_getsockname(res, (long)(arg0), (long)(arg1), \
+ (long)(arg2))
+#define __sanitizer_syscall_pre_getpeername(arg0, arg1, arg2) \
+ __sanitizer_syscall_pre_impl_getpeername((long)(arg0), (long)(arg1), \
+ (long)(arg2))
+#define __sanitizer_syscall_post_getpeername(res, arg0, arg1, arg2) \
+ __sanitizer_syscall_post_impl_getpeername(res, (long)(arg0), (long)(arg1), \
+ (long)(arg2))
+#define __sanitizer_syscall_pre_send(arg0, arg1, arg2, arg3) \
+ __sanitizer_syscall_pre_impl_send((long)(arg0), (long)(arg1), (long)(arg2), \
+ (long)(arg3))
+#define __sanitizer_syscall_post_send(res, arg0, arg1, arg2, arg3) \
+ __sanitizer_syscall_post_impl_send(res, (long)(arg0), (long)(arg1), \
+ (long)(arg2), (long)(arg3))
+#define __sanitizer_syscall_pre_sendto(arg0, arg1, arg2, arg3, arg4, arg5) \
+ __sanitizer_syscall_pre_impl_sendto((long)(arg0), (long)(arg1), \
+ (long)(arg2), (long)(arg3), \
+ (long)(arg4), (long)(arg5))
+#define __sanitizer_syscall_post_sendto(res, arg0, arg1, arg2, arg3, arg4, \
+ arg5) \
+ __sanitizer_syscall_post_impl_sendto(res, (long)(arg0), (long)(arg1), \
+ (long)(arg2), (long)(arg3), \
+ (long)(arg4), (long)(arg5))
+#define __sanitizer_syscall_pre_sendmsg(fd, msg, flags) \
+ __sanitizer_syscall_pre_impl_sendmsg((long)(fd), (long)(msg), (long)(flags))
+#define __sanitizer_syscall_post_sendmsg(res, fd, msg, flags) \
+ __sanitizer_syscall_post_impl_sendmsg(res, (long)(fd), (long)(msg), \
+ (long)(flags))
+#define __sanitizer_syscall_pre_sendmmsg(fd, msg, vlen, flags) \
+ __sanitizer_syscall_pre_impl_sendmmsg((long)(fd), (long)(msg), (long)(vlen), \
+ (long)(flags))
+#define __sanitizer_syscall_post_sendmmsg(res, fd, msg, vlen, flags) \
+ __sanitizer_syscall_post_impl_sendmmsg(res, (long)(fd), (long)(msg), \
+ (long)(vlen), (long)(flags))
+#define __sanitizer_syscall_pre_recv(arg0, arg1, arg2, arg3) \
+ __sanitizer_syscall_pre_impl_recv((long)(arg0), (long)(arg1), (long)(arg2), \
+ (long)(arg3))
+#define __sanitizer_syscall_post_recv(res, arg0, arg1, arg2, arg3) \
+ __sanitizer_syscall_post_impl_recv(res, (long)(arg0), (long)(arg1), \
+ (long)(arg2), (long)(arg3))
+#define __sanitizer_syscall_pre_recvfrom(arg0, arg1, arg2, arg3, arg4, arg5) \
+ __sanitizer_syscall_pre_impl_recvfrom((long)(arg0), (long)(arg1), \
+ (long)(arg2), (long)(arg3), \
+ (long)(arg4), (long)(arg5))
+#define __sanitizer_syscall_post_recvfrom(res, arg0, arg1, arg2, arg3, arg4, \
+ arg5) \
+ __sanitizer_syscall_post_impl_recvfrom(res, (long)(arg0), (long)(arg1), \
+ (long)(arg2), (long)(arg3), \
+ (long)(arg4), (long)(arg5))
+#define __sanitizer_syscall_pre_recvmsg(fd, msg, flags) \
+ __sanitizer_syscall_pre_impl_recvmsg((long)(fd), (long)(msg), (long)(flags))
+#define __sanitizer_syscall_post_recvmsg(res, fd, msg, flags) \
+ __sanitizer_syscall_post_impl_recvmsg(res, (long)(fd), (long)(msg), \
+ (long)(flags))
+#define __sanitizer_syscall_pre_recvmmsg(fd, msg, vlen, flags, timeout) \
+ __sanitizer_syscall_pre_impl_recvmmsg((long)(fd), (long)(msg), (long)(vlen), \
+ (long)(flags), (long)(timeout))
+#define __sanitizer_syscall_post_recvmmsg(res, fd, msg, vlen, flags, timeout) \
+ __sanitizer_syscall_post_impl_recvmmsg(res, (long)(fd), (long)(msg), \
+ (long)(vlen), (long)(flags), \
+ (long)(timeout))
+#define __sanitizer_syscall_pre_socket(arg0, arg1, arg2) \
+ __sanitizer_syscall_pre_impl_socket((long)(arg0), (long)(arg1), (long)(arg2))
+#define __sanitizer_syscall_post_socket(res, arg0, arg1, arg2) \
+ __sanitizer_syscall_post_impl_socket(res, (long)(arg0), (long)(arg1), \
+ (long)(arg2))
+#define __sanitizer_syscall_pre_socketpair(arg0, arg1, arg2, arg3) \
+ __sanitizer_syscall_pre_impl_socketpair((long)(arg0), (long)(arg1), \
+ (long)(arg2), (long)(arg3))
+#define __sanitizer_syscall_post_socketpair(res, arg0, arg1, arg2, arg3) \
+ __sanitizer_syscall_post_impl_socketpair(res, (long)(arg0), (long)(arg1), \
+ (long)(arg2), (long)(arg3))
+#define __sanitizer_syscall_pre_socketcall(call, args) \
+ __sanitizer_syscall_pre_impl_socketcall((long)(call), (long)(args))
+#define __sanitizer_syscall_post_socketcall(res, call, args) \
+ __sanitizer_syscall_post_impl_socketcall(res, (long)(call), (long)(args))
+#define __sanitizer_syscall_pre_listen(arg0, arg1) \
+ __sanitizer_syscall_pre_impl_listen((long)(arg0), (long)(arg1))
+#define __sanitizer_syscall_post_listen(res, arg0, arg1) \
+ __sanitizer_syscall_post_impl_listen(res, (long)(arg0), (long)(arg1))
+#define __sanitizer_syscall_pre_poll(ufds, nfds, timeout) \
+ __sanitizer_syscall_pre_impl_poll((long)(ufds), (long)(nfds), (long)(timeout))
+#define __sanitizer_syscall_post_poll(res, ufds, nfds, timeout) \
+ __sanitizer_syscall_post_impl_poll(res, (long)(ufds), (long)(nfds), \
+ (long)(timeout))
+#define __sanitizer_syscall_pre_select(n, inp, outp, exp, tvp) \
+ __sanitizer_syscall_pre_impl_select((long)(n), (long)(inp), (long)(outp), \
+ (long)(exp), (long)(tvp))
+#define __sanitizer_syscall_post_select(res, n, inp, outp, exp, tvp) \
+ __sanitizer_syscall_post_impl_select(res, (long)(n), (long)(inp), \
+ (long)(outp), (long)(exp), (long)(tvp))
+#define __sanitizer_syscall_pre_old_select(arg) \
+ __sanitizer_syscall_pre_impl_old_select((long)(arg))
+#define __sanitizer_syscall_post_old_select(res, arg) \
+ __sanitizer_syscall_post_impl_old_select(res, (long)(arg))
+#define __sanitizer_syscall_pre_epoll_create(size) \
+ __sanitizer_syscall_pre_impl_epoll_create((long)(size))
+#define __sanitizer_syscall_post_epoll_create(res, size) \
+ __sanitizer_syscall_post_impl_epoll_create(res, (long)(size))
+#define __sanitizer_syscall_pre_epoll_create1(flags) \
+ __sanitizer_syscall_pre_impl_epoll_create1((long)(flags))
+#define __sanitizer_syscall_post_epoll_create1(res, flags) \
+ __sanitizer_syscall_post_impl_epoll_create1(res, (long)(flags))
+#define __sanitizer_syscall_pre_epoll_ctl(epfd, op, fd, event) \
+ __sanitizer_syscall_pre_impl_epoll_ctl((long)(epfd), (long)(op), (long)(fd), \
+ (long)(event))
+#define __sanitizer_syscall_post_epoll_ctl(res, epfd, op, fd, event) \
+ __sanitizer_syscall_post_impl_epoll_ctl(res, (long)(epfd), (long)(op), \
+ (long)(fd), (long)(event))
+#define __sanitizer_syscall_pre_epoll_wait(epfd, events, maxevents, timeout) \
+ __sanitizer_syscall_pre_impl_epoll_wait((long)(epfd), (long)(events), \
+ (long)(maxevents), (long)(timeout))
+#define __sanitizer_syscall_post_epoll_wait(res, epfd, events, maxevents, \
+ timeout) \
+ __sanitizer_syscall_post_impl_epoll_wait(res, (long)(epfd), (long)(events), \
+ (long)(maxevents), (long)(timeout))
+#define __sanitizer_syscall_pre_epoll_pwait(epfd, events, maxevents, timeout, \
+ sigmask, sigsetsize) \
+ __sanitizer_syscall_pre_impl_epoll_pwait( \
+ (long)(epfd), (long)(events), (long)(maxevents), (long)(timeout), \
+ (long)(sigmask), (long)(sigsetsize))
+#define __sanitizer_syscall_post_epoll_pwait(res, epfd, events, maxevents, \
+ timeout, sigmask, sigsetsize) \
+ __sanitizer_syscall_post_impl_epoll_pwait( \
+ res, (long)(epfd), (long)(events), (long)(maxevents), (long)(timeout), \
+ (long)(sigmask), (long)(sigsetsize))
+#define __sanitizer_syscall_pre_gethostname(name, len) \
+ __sanitizer_syscall_pre_impl_gethostname((long)(name), (long)(len))
+#define __sanitizer_syscall_post_gethostname(res, name, len) \
+ __sanitizer_syscall_post_impl_gethostname(res, (long)(name), (long)(len))
+#define __sanitizer_syscall_pre_sethostname(name, len) \
+ __sanitizer_syscall_pre_impl_sethostname((long)(name), (long)(len))
+#define __sanitizer_syscall_post_sethostname(res, name, len) \
+ __sanitizer_syscall_post_impl_sethostname(res, (long)(name), (long)(len))
+#define __sanitizer_syscall_pre_setdomainname(name, len) \
+ __sanitizer_syscall_pre_impl_setdomainname((long)(name), (long)(len))
+#define __sanitizer_syscall_post_setdomainname(res, name, len) \
+ __sanitizer_syscall_post_impl_setdomainname(res, (long)(name), (long)(len))
+#define __sanitizer_syscall_pre_newuname(name) \
+ __sanitizer_syscall_pre_impl_newuname((long)(name))
+#define __sanitizer_syscall_post_newuname(res, name) \
+ __sanitizer_syscall_post_impl_newuname(res, (long)(name))
+#define __sanitizer_syscall_pre_uname(arg0) \
+ __sanitizer_syscall_pre_impl_uname((long)(arg0))
+#define __sanitizer_syscall_post_uname(res, arg0) \
+ __sanitizer_syscall_post_impl_uname(res, (long)(arg0))
+#define __sanitizer_syscall_pre_olduname(arg0) \
+ __sanitizer_syscall_pre_impl_olduname((long)(arg0))
+#define __sanitizer_syscall_post_olduname(res, arg0) \
+ __sanitizer_syscall_post_impl_olduname(res, (long)(arg0))
+#define __sanitizer_syscall_pre_getrlimit(resource, rlim) \
+ __sanitizer_syscall_pre_impl_getrlimit((long)(resource), (long)(rlim))
+#define __sanitizer_syscall_post_getrlimit(res, resource, rlim) \
+ __sanitizer_syscall_post_impl_getrlimit(res, (long)(resource), (long)(rlim))
+#define __sanitizer_syscall_pre_old_getrlimit(resource, rlim) \
+ __sanitizer_syscall_pre_impl_old_getrlimit((long)(resource), (long)(rlim))
+#define __sanitizer_syscall_post_old_getrlimit(res, resource, rlim) \
+ __sanitizer_syscall_post_impl_old_getrlimit(res, (long)(resource), \
+ (long)(rlim))
+#define __sanitizer_syscall_pre_setrlimit(resource, rlim) \
+ __sanitizer_syscall_pre_impl_setrlimit((long)(resource), (long)(rlim))
+#define __sanitizer_syscall_post_setrlimit(res, resource, rlim) \
+ __sanitizer_syscall_post_impl_setrlimit(res, (long)(resource), (long)(rlim))
+#define __sanitizer_syscall_pre_prlimit64(pid, resource, new_rlim, old_rlim) \
+ __sanitizer_syscall_pre_impl_prlimit64((long)(pid), (long)(resource), \
+ (long)(new_rlim), (long)(old_rlim))
+#define __sanitizer_syscall_post_prlimit64(res, pid, resource, new_rlim, \
+ old_rlim) \
+ __sanitizer_syscall_post_impl_prlimit64(res, (long)(pid), (long)(resource), \
+ (long)(new_rlim), (long)(old_rlim))
+#define __sanitizer_syscall_pre_getrusage(who, ru) \
+ __sanitizer_syscall_pre_impl_getrusage((long)(who), (long)(ru))
+#define __sanitizer_syscall_post_getrusage(res, who, ru) \
+ __sanitizer_syscall_post_impl_getrusage(res, (long)(who), (long)(ru))
+#define __sanitizer_syscall_pre_umask(mask) \
+ __sanitizer_syscall_pre_impl_umask((long)(mask))
+#define __sanitizer_syscall_post_umask(res, mask) \
+ __sanitizer_syscall_post_impl_umask(res, (long)(mask))
+#define __sanitizer_syscall_pre_msgget(key, msgflg) \
+ __sanitizer_syscall_pre_impl_msgget((long)(key), (long)(msgflg))
+#define __sanitizer_syscall_post_msgget(res, key, msgflg) \
+ __sanitizer_syscall_post_impl_msgget(res, (long)(key), (long)(msgflg))
+#define __sanitizer_syscall_pre_msgsnd(msqid, msgp, msgsz, msgflg) \
+ __sanitizer_syscall_pre_impl_msgsnd((long)(msqid), (long)(msgp), \
+ (long)(msgsz), (long)(msgflg))
+#define __sanitizer_syscall_post_msgsnd(res, msqid, msgp, msgsz, msgflg) \
+ __sanitizer_syscall_post_impl_msgsnd(res, (long)(msqid), (long)(msgp), \
+ (long)(msgsz), (long)(msgflg))
+#define __sanitizer_syscall_pre_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg) \
+ __sanitizer_syscall_pre_impl_msgrcv((long)(msqid), (long)(msgp), \
+ (long)(msgsz), (long)(msgtyp), \
+ (long)(msgflg))
+#define __sanitizer_syscall_post_msgrcv(res, msqid, msgp, msgsz, msgtyp, \
+ msgflg) \
+ __sanitizer_syscall_post_impl_msgrcv(res, (long)(msqid), (long)(msgp), \
+ (long)(msgsz), (long)(msgtyp), \
+ (long)(msgflg))
+#define __sanitizer_syscall_pre_msgctl(msqid, cmd, buf) \
+ __sanitizer_syscall_pre_impl_msgctl((long)(msqid), (long)(cmd), (long)(buf))
+#define __sanitizer_syscall_post_msgctl(res, msqid, cmd, buf) \
+ __sanitizer_syscall_post_impl_msgctl(res, (long)(msqid), (long)(cmd), \
+ (long)(buf))
+#define __sanitizer_syscall_pre_semget(key, nsems, semflg) \
+ __sanitizer_syscall_pre_impl_semget((long)(key), (long)(nsems), \
+ (long)(semflg))
+#define __sanitizer_syscall_post_semget(res, key, nsems, semflg) \
+ __sanitizer_syscall_post_impl_semget(res, (long)(key), (long)(nsems), \
+ (long)(semflg))
+#define __sanitizer_syscall_pre_semop(semid, sops, nsops) \
+ __sanitizer_syscall_pre_impl_semop((long)(semid), (long)(sops), (long)(nsops))
+#define __sanitizer_syscall_post_semop(res, semid, sops, nsops) \
+ __sanitizer_syscall_post_impl_semop(res, (long)(semid), (long)(sops), \
+ (long)(nsops))
+#define __sanitizer_syscall_pre_semctl(semid, semnum, cmd, arg) \
+ __sanitizer_syscall_pre_impl_semctl((long)(semid), (long)(semnum), \
+ (long)(cmd), (long)(arg))
+#define __sanitizer_syscall_post_semctl(res, semid, semnum, cmd, arg) \
+ __sanitizer_syscall_post_impl_semctl(res, (long)(semid), (long)(semnum), \
+ (long)(cmd), (long)(arg))
+#define __sanitizer_syscall_pre_semtimedop(semid, sops, nsops, timeout) \
+ __sanitizer_syscall_pre_impl_semtimedop((long)(semid), (long)(sops), \
+ (long)(nsops), (long)(timeout))
+#define __sanitizer_syscall_post_semtimedop(res, semid, sops, nsops, timeout) \
+ __sanitizer_syscall_post_impl_semtimedop(res, (long)(semid), (long)(sops), \
+ (long)(nsops), (long)(timeout))
+#define __sanitizer_syscall_pre_shmat(shmid, shmaddr, shmflg) \
+ __sanitizer_syscall_pre_impl_shmat((long)(shmid), (long)(shmaddr), \
+ (long)(shmflg))
+#define __sanitizer_syscall_post_shmat(res, shmid, shmaddr, shmflg) \
+ __sanitizer_syscall_post_impl_shmat(res, (long)(shmid), (long)(shmaddr), \
+ (long)(shmflg))
+#define __sanitizer_syscall_pre_shmget(key, size, flag) \
+ __sanitizer_syscall_pre_impl_shmget((long)(key), (long)(size), (long)(flag))
+#define __sanitizer_syscall_post_shmget(res, key, size, flag) \
+ __sanitizer_syscall_post_impl_shmget(res, (long)(key), (long)(size), \
+ (long)(flag))
+#define __sanitizer_syscall_pre_shmdt(shmaddr) \
+ __sanitizer_syscall_pre_impl_shmdt((long)(shmaddr))
+#define __sanitizer_syscall_post_shmdt(res, shmaddr) \
+ __sanitizer_syscall_post_impl_shmdt(res, (long)(shmaddr))
+#define __sanitizer_syscall_pre_shmctl(shmid, cmd, buf) \
+ __sanitizer_syscall_pre_impl_shmctl((long)(shmid), (long)(cmd), (long)(buf))
+#define __sanitizer_syscall_post_shmctl(res, shmid, cmd, buf) \
+ __sanitizer_syscall_post_impl_shmctl(res, (long)(shmid), (long)(cmd), \
+ (long)(buf))
+#define __sanitizer_syscall_pre_ipc(call, first, second, third, ptr, fifth) \
+ __sanitizer_syscall_pre_impl_ipc((long)(call), (long)(first), \
+ (long)(second), (long)(third), (long)(ptr), \
+ (long)(fifth))
+#define __sanitizer_syscall_post_ipc(res, call, first, second, third, ptr, \
+ fifth) \
+ __sanitizer_syscall_post_impl_ipc(res, (long)(call), (long)(first), \
+ (long)(second), (long)(third), \
+ (long)(ptr), (long)(fifth))
+#define __sanitizer_syscall_pre_mq_open(name, oflag, mode, attr) \
+ __sanitizer_syscall_pre_impl_mq_open((long)(name), (long)(oflag), \
+ (long)(mode), (long)(attr))
+#define __sanitizer_syscall_post_mq_open(res, name, oflag, mode, attr) \
+ __sanitizer_syscall_post_impl_mq_open(res, (long)(name), (long)(oflag), \
+ (long)(mode), (long)(attr))
+#define __sanitizer_syscall_pre_mq_unlink(name) \
+ __sanitizer_syscall_pre_impl_mq_unlink((long)(name))
+#define __sanitizer_syscall_post_mq_unlink(res, name) \
+ __sanitizer_syscall_post_impl_mq_unlink(res, (long)(name))
+#define __sanitizer_syscall_pre_mq_timedsend(mqdes, msg_ptr, msg_len, \
+ msg_prio, abs_timeout) \
+ __sanitizer_syscall_pre_impl_mq_timedsend((long)(mqdes), (long)(msg_ptr), \
+ (long)(msg_len), (long)(msg_prio), \
+ (long)(abs_timeout))
+#define __sanitizer_syscall_post_mq_timedsend(res, mqdes, msg_ptr, msg_len, \
+ msg_prio, abs_timeout) \
+ __sanitizer_syscall_post_impl_mq_timedsend( \
+ res, (long)(mqdes), (long)(msg_ptr), (long)(msg_len), (long)(msg_prio), \
+ (long)(abs_timeout))
+#define __sanitizer_syscall_pre_mq_timedreceive(mqdes, msg_ptr, msg_len, \
+ msg_prio, abs_timeout) \
+ __sanitizer_syscall_pre_impl_mq_timedreceive( \
+ (long)(mqdes), (long)(msg_ptr), (long)(msg_len), (long)(msg_prio), \
+ (long)(abs_timeout))
+#define __sanitizer_syscall_post_mq_timedreceive(res, mqdes, msg_ptr, msg_len, \
+ msg_prio, abs_timeout) \
+ __sanitizer_syscall_post_impl_mq_timedreceive( \
+ res, (long)(mqdes), (long)(msg_ptr), (long)(msg_len), (long)(msg_prio), \
+ (long)(abs_timeout))
+#define __sanitizer_syscall_pre_mq_notify(mqdes, notification) \
+ __sanitizer_syscall_pre_impl_mq_notify((long)(mqdes), (long)(notification))
+#define __sanitizer_syscall_post_mq_notify(res, mqdes, notification) \
+ __sanitizer_syscall_post_impl_mq_notify(res, (long)(mqdes), \
+ (long)(notification))
+#define __sanitizer_syscall_pre_mq_getsetattr(mqdes, mqstat, omqstat) \
+ __sanitizer_syscall_pre_impl_mq_getsetattr((long)(mqdes), (long)(mqstat), \
+ (long)(omqstat))
+#define __sanitizer_syscall_post_mq_getsetattr(res, mqdes, mqstat, omqstat) \
+ __sanitizer_syscall_post_impl_mq_getsetattr(res, (long)(mqdes), \
+ (long)(mqstat), (long)(omqstat))
+#define __sanitizer_syscall_pre_pciconfig_iobase(which, bus, devfn) \
+ __sanitizer_syscall_pre_impl_pciconfig_iobase((long)(which), (long)(bus), \
+ (long)(devfn))
+#define __sanitizer_syscall_post_pciconfig_iobase(res, which, bus, devfn) \
+ __sanitizer_syscall_post_impl_pciconfig_iobase(res, (long)(which), \
+ (long)(bus), (long)(devfn))
+#define __sanitizer_syscall_pre_pciconfig_read(bus, dfn, off, len, buf) \
+ __sanitizer_syscall_pre_impl_pciconfig_read( \
+ (long)(bus), (long)(dfn), (long)(off), (long)(len), (long)(buf))
+#define __sanitizer_syscall_post_pciconfig_read(res, bus, dfn, off, len, buf) \
+ __sanitizer_syscall_post_impl_pciconfig_read( \
+ res, (long)(bus), (long)(dfn), (long)(off), (long)(len), (long)(buf))
+#define __sanitizer_syscall_pre_pciconfig_write(bus, dfn, off, len, buf) \
+ __sanitizer_syscall_pre_impl_pciconfig_write( \
+ (long)(bus), (long)(dfn), (long)(off), (long)(len), (long)(buf))
+#define __sanitizer_syscall_post_pciconfig_write(res, bus, dfn, off, len, buf) \
+ __sanitizer_syscall_post_impl_pciconfig_write( \
+ res, (long)(bus), (long)(dfn), (long)(off), (long)(len), (long)(buf))
+#define __sanitizer_syscall_pre_swapon(specialfile, swap_flags) \
+ __sanitizer_syscall_pre_impl_swapon((long)(specialfile), (long)(swap_flags))
+#define __sanitizer_syscall_post_swapon(res, specialfile, swap_flags) \
+ __sanitizer_syscall_post_impl_swapon(res, (long)(specialfile), \
+ (long)(swap_flags))
+#define __sanitizer_syscall_pre_swapoff(specialfile) \
+ __sanitizer_syscall_pre_impl_swapoff((long)(specialfile))
+#define __sanitizer_syscall_post_swapoff(res, specialfile) \
+ __sanitizer_syscall_post_impl_swapoff(res, (long)(specialfile))
+#define __sanitizer_syscall_pre_sysctl(args) \
+ __sanitizer_syscall_pre_impl_sysctl((long)(args))
+#define __sanitizer_syscall_post_sysctl(res, args) \
+ __sanitizer_syscall_post_impl_sysctl(res, (long)(args))
+#define __sanitizer_syscall_pre_sysinfo(info) \
+ __sanitizer_syscall_pre_impl_sysinfo((long)(info))
+#define __sanitizer_syscall_post_sysinfo(res, info) \
+ __sanitizer_syscall_post_impl_sysinfo(res, (long)(info))
+#define __sanitizer_syscall_pre_sysfs(option, arg1, arg2) \
+ __sanitizer_syscall_pre_impl_sysfs((long)(option), (long)(arg1), (long)(arg2))
+#define __sanitizer_syscall_post_sysfs(res, option, arg1, arg2) \
+ __sanitizer_syscall_post_impl_sysfs(res, (long)(option), (long)(arg1), \
+ (long)(arg2))
+#define __sanitizer_syscall_pre_syslog(type, buf, len) \
+ __sanitizer_syscall_pre_impl_syslog((long)(type), (long)(buf), (long)(len))
+#define __sanitizer_syscall_post_syslog(res, type, buf, len) \
+ __sanitizer_syscall_post_impl_syslog(res, (long)(type), (long)(buf), \
+ (long)(len))
+#define __sanitizer_syscall_pre_uselib(library) \
+ __sanitizer_syscall_pre_impl_uselib((long)(library))
+#define __sanitizer_syscall_post_uselib(res, library) \
+ __sanitizer_syscall_post_impl_uselib(res, (long)(library))
+#define __sanitizer_syscall_pre_ni_syscall() \
+ __sanitizer_syscall_pre_impl_ni_syscall()
+#define __sanitizer_syscall_post_ni_syscall(res) \
+ __sanitizer_syscall_post_impl_ni_syscall(res)
+#define __sanitizer_syscall_pre_ptrace(request, pid, addr, data) \
+ __sanitizer_syscall_pre_impl_ptrace((long)(request), (long)(pid), \
+ (long)(addr), (long)(data))
+#define __sanitizer_syscall_post_ptrace(res, request, pid, addr, data) \
+ __sanitizer_syscall_post_impl_ptrace(res, (long)(request), (long)(pid), \
+ (long)(addr), (long)(data))
+#define __sanitizer_syscall_pre_add_key(_type, _description, _payload, plen, \
+ destringid) \
+ __sanitizer_syscall_pre_impl_add_key((long)(_type), (long)(_description), \
+ (long)(_payload), (long)(plen), \
+ (long)(destringid))
+#define __sanitizer_syscall_post_add_key(res, _type, _description, _payload, \
+ plen, destringid) \
+ __sanitizer_syscall_post_impl_add_key( \
+ res, (long)(_type), (long)(_description), (long)(_payload), \
+ (long)(plen), (long)(destringid))
+#define __sanitizer_syscall_pre_request_key(_type, _description, \
+ _callout_info, destringid) \
+ __sanitizer_syscall_pre_impl_request_key( \
+ (long)(_type), (long)(_description), (long)(_callout_info), \
+ (long)(destringid))
+#define __sanitizer_syscall_post_request_key(res, _type, _description, \
+ _callout_info, destringid) \
+ __sanitizer_syscall_post_impl_request_key( \
+ res, (long)(_type), (long)(_description), (long)(_callout_info), \
+ (long)(destringid))
+#define __sanitizer_syscall_pre_keyctl(cmd, arg2, arg3, arg4, arg5) \
+ __sanitizer_syscall_pre_impl_keyctl((long)(cmd), (long)(arg2), (long)(arg3), \
+ (long)(arg4), (long)(arg5))
+#define __sanitizer_syscall_post_keyctl(res, cmd, arg2, arg3, arg4, arg5) \
+ __sanitizer_syscall_post_impl_keyctl(res, (long)(cmd), (long)(arg2), \
+ (long)(arg3), (long)(arg4), \
+ (long)(arg5))
+#define __sanitizer_syscall_pre_ioprio_set(which, who, ioprio) \
+ __sanitizer_syscall_pre_impl_ioprio_set((long)(which), (long)(who), \
+ (long)(ioprio))
+#define __sanitizer_syscall_post_ioprio_set(res, which, who, ioprio) \
+ __sanitizer_syscall_post_impl_ioprio_set(res, (long)(which), (long)(who), \
+ (long)(ioprio))
+#define __sanitizer_syscall_pre_ioprio_get(which, who) \
+ __sanitizer_syscall_pre_impl_ioprio_get((long)(which), (long)(who))
+#define __sanitizer_syscall_post_ioprio_get(res, which, who) \
+ __sanitizer_syscall_post_impl_ioprio_get(res, (long)(which), (long)(who))
+#define __sanitizer_syscall_pre_set_mempolicy(mode, nmask, maxnode) \
+ __sanitizer_syscall_pre_impl_set_mempolicy((long)(mode), (long)(nmask), \
+ (long)(maxnode))
+#define __sanitizer_syscall_post_set_mempolicy(res, mode, nmask, maxnode) \
+ __sanitizer_syscall_post_impl_set_mempolicy(res, (long)(mode), \
+ (long)(nmask), (long)(maxnode))
+#define __sanitizer_syscall_pre_migrate_pages(pid, maxnode, from, to) \
+ __sanitizer_syscall_pre_impl_migrate_pages((long)(pid), (long)(maxnode), \
+ (long)(from), (long)(to))
+#define __sanitizer_syscall_post_migrate_pages(res, pid, maxnode, from, to) \
+ __sanitizer_syscall_post_impl_migrate_pages( \
+ res, (long)(pid), (long)(maxnode), (long)(from), (long)(to))
+#define __sanitizer_syscall_pre_move_pages(pid, nr_pages, pages, nodes, \
+ status, flags) \
+ __sanitizer_syscall_pre_impl_move_pages((long)(pid), (long)(nr_pages), \
+ (long)(pages), (long)(nodes), \
+ (long)(status), (long)(flags))
+#define __sanitizer_syscall_post_move_pages(res, pid, nr_pages, pages, nodes, \
+ status, flags) \
+ __sanitizer_syscall_post_impl_move_pages(res, (long)(pid), (long)(nr_pages), \
+ (long)(pages), (long)(nodes), \
+ (long)(status), (long)(flags))
+#define __sanitizer_syscall_pre_mbind(start, len, mode, nmask, maxnode, flags) \
+ __sanitizer_syscall_pre_impl_mbind((long)(start), (long)(len), (long)(mode), \
+ (long)(nmask), (long)(maxnode), \
+ (long)(flags))
+#define __sanitizer_syscall_post_mbind(res, start, len, mode, nmask, maxnode, \
+ flags) \
+ __sanitizer_syscall_post_impl_mbind(res, (long)(start), (long)(len), \
+ (long)(mode), (long)(nmask), \
+ (long)(maxnode), (long)(flags))
+#define __sanitizer_syscall_pre_get_mempolicy(policy, nmask, maxnode, addr, \
+ flags) \
+ __sanitizer_syscall_pre_impl_get_mempolicy((long)(policy), (long)(nmask), \
+ (long)(maxnode), (long)(addr), \
+ (long)(flags))
+#define __sanitizer_syscall_post_get_mempolicy(res, policy, nmask, maxnode, \
+ addr, flags) \
+ __sanitizer_syscall_post_impl_get_mempolicy(res, (long)(policy), \
+ (long)(nmask), (long)(maxnode), \
+ (long)(addr), (long)(flags))
+#define __sanitizer_syscall_pre_inotify_init() \
+ __sanitizer_syscall_pre_impl_inotify_init()
+#define __sanitizer_syscall_post_inotify_init(res) \
+ __sanitizer_syscall_post_impl_inotify_init(res)
+#define __sanitizer_syscall_pre_inotify_init1(flags) \
+ __sanitizer_syscall_pre_impl_inotify_init1((long)(flags))
+#define __sanitizer_syscall_post_inotify_init1(res, flags) \
+ __sanitizer_syscall_post_impl_inotify_init1(res, (long)(flags))
+#define __sanitizer_syscall_pre_inotify_add_watch(fd, path, mask) \
+ __sanitizer_syscall_pre_impl_inotify_add_watch((long)(fd), (long)(path), \
+ (long)(mask))
+#define __sanitizer_syscall_post_inotify_add_watch(res, fd, path, mask) \
+ __sanitizer_syscall_post_impl_inotify_add_watch(res, (long)(fd), \
+ (long)(path), (long)(mask))
+#define __sanitizer_syscall_pre_inotify_rm_watch(fd, wd) \
+ __sanitizer_syscall_pre_impl_inotify_rm_watch((long)(fd), (long)(wd))
+#define __sanitizer_syscall_post_inotify_rm_watch(res, fd, wd) \
+ __sanitizer_syscall_post_impl_inotify_rm_watch(res, (long)(fd), (long)(wd))
+#define __sanitizer_syscall_pre_spu_run(fd, unpc, ustatus) \
+ __sanitizer_syscall_pre_impl_spu_run((long)(fd), (long)(unpc), \
+ (long)(ustatus))
+#define __sanitizer_syscall_post_spu_run(res, fd, unpc, ustatus) \
+ __sanitizer_syscall_post_impl_spu_run(res, (long)(fd), (long)(unpc), \
+ (long)(ustatus))
+#define __sanitizer_syscall_pre_spu_create(name, flags, mode, fd) \
+ __sanitizer_syscall_pre_impl_spu_create((long)(name), (long)(flags), \
+ (long)(mode), (long)(fd))
+#define __sanitizer_syscall_post_spu_create(res, name, flags, mode, fd) \
+ __sanitizer_syscall_post_impl_spu_create(res, (long)(name), (long)(flags), \
+ (long)(mode), (long)(fd))
+#define __sanitizer_syscall_pre_mknodat(dfd, filename, mode, dev) \
+ __sanitizer_syscall_pre_impl_mknodat((long)(dfd), (long)(filename), \
+ (long)(mode), (long)(dev))
+#define __sanitizer_syscall_post_mknodat(res, dfd, filename, mode, dev) \
+ __sanitizer_syscall_post_impl_mknodat(res, (long)(dfd), (long)(filename), \
+ (long)(mode), (long)(dev))
+#define __sanitizer_syscall_pre_mkdirat(dfd, pathname, mode) \
+ __sanitizer_syscall_pre_impl_mkdirat((long)(dfd), (long)(pathname), \
+ (long)(mode))
+#define __sanitizer_syscall_post_mkdirat(res, dfd, pathname, mode) \
+ __sanitizer_syscall_post_impl_mkdirat(res, (long)(dfd), (long)(pathname), \
+ (long)(mode))
+#define __sanitizer_syscall_pre_unlinkat(dfd, pathname, flag) \
+ __sanitizer_syscall_pre_impl_unlinkat((long)(dfd), (long)(pathname), \
+ (long)(flag))
+#define __sanitizer_syscall_post_unlinkat(res, dfd, pathname, flag) \
+ __sanitizer_syscall_post_impl_unlinkat(res, (long)(dfd), (long)(pathname), \
+ (long)(flag))
+#define __sanitizer_syscall_pre_symlinkat(oldname, newdfd, newname) \
+ __sanitizer_syscall_pre_impl_symlinkat((long)(oldname), (long)(newdfd), \
+ (long)(newname))
+#define __sanitizer_syscall_post_symlinkat(res, oldname, newdfd, newname) \
+ __sanitizer_syscall_post_impl_symlinkat(res, (long)(oldname), \
+ (long)(newdfd), (long)(newname))
+#define __sanitizer_syscall_pre_linkat(olddfd, oldname, newdfd, newname, \
+ flags) \
+ __sanitizer_syscall_pre_impl_linkat((long)(olddfd), (long)(oldname), \
+ (long)(newdfd), (long)(newname), \
+ (long)(flags))
+#define __sanitizer_syscall_post_linkat(res, olddfd, oldname, newdfd, newname, \
+ flags) \
+ __sanitizer_syscall_post_impl_linkat(res, (long)(olddfd), (long)(oldname), \
+ (long)(newdfd), (long)(newname), \
+ (long)(flags))
+#define __sanitizer_syscall_pre_renameat(olddfd, oldname, newdfd, newname) \
+ __sanitizer_syscall_pre_impl_renameat((long)(olddfd), (long)(oldname), \
+ (long)(newdfd), (long)(newname))
+#define __sanitizer_syscall_post_renameat(res, olddfd, oldname, newdfd, \
+ newname) \
+ __sanitizer_syscall_post_impl_renameat(res, (long)(olddfd), (long)(oldname), \
+ (long)(newdfd), (long)(newname))
+#define __sanitizer_syscall_pre_futimesat(dfd, filename, utimes) \
+ __sanitizer_syscall_pre_impl_futimesat((long)(dfd), (long)(filename), \
+ (long)(utimes))
+#define __sanitizer_syscall_post_futimesat(res, dfd, filename, utimes) \
+ __sanitizer_syscall_post_impl_futimesat(res, (long)(dfd), (long)(filename), \
+ (long)(utimes))
+#define __sanitizer_syscall_pre_faccessat(dfd, filename, mode) \
+ __sanitizer_syscall_pre_impl_faccessat((long)(dfd), (long)(filename), \
+ (long)(mode))
+#define __sanitizer_syscall_post_faccessat(res, dfd, filename, mode) \
+ __sanitizer_syscall_post_impl_faccessat(res, (long)(dfd), (long)(filename), \
+ (long)(mode))
+#define __sanitizer_syscall_pre_fchmodat(dfd, filename, mode) \
+ __sanitizer_syscall_pre_impl_fchmodat((long)(dfd), (long)(filename), \
+ (long)(mode))
+#define __sanitizer_syscall_post_fchmodat(res, dfd, filename, mode) \
+ __sanitizer_syscall_post_impl_fchmodat(res, (long)(dfd), (long)(filename), \
+ (long)(mode))
+#define __sanitizer_syscall_pre_fchownat(dfd, filename, user, group, flag) \
+ __sanitizer_syscall_pre_impl_fchownat((long)(dfd), (long)(filename), \
+ (long)(user), (long)(group), \
+ (long)(flag))
+#define __sanitizer_syscall_post_fchownat(res, dfd, filename, user, group, \
+ flag) \
+ __sanitizer_syscall_post_impl_fchownat(res, (long)(dfd), (long)(filename), \
+ (long)(user), (long)(group), \
+ (long)(flag))
+#define __sanitizer_syscall_pre_openat(dfd, filename, flags, mode) \
+ __sanitizer_syscall_pre_impl_openat((long)(dfd), (long)(filename), \
+ (long)(flags), (long)(mode))
+#define __sanitizer_syscall_post_openat(res, dfd, filename, flags, mode) \
+ __sanitizer_syscall_post_impl_openat(res, (long)(dfd), (long)(filename), \
+ (long)(flags), (long)(mode))
+#define __sanitizer_syscall_pre_newfstatat(dfd, filename, statbuf, flag) \
+ __sanitizer_syscall_pre_impl_newfstatat((long)(dfd), (long)(filename), \
+ (long)(statbuf), (long)(flag))
+#define __sanitizer_syscall_post_newfstatat(res, dfd, filename, statbuf, flag) \
+ __sanitizer_syscall_post_impl_newfstatat(res, (long)(dfd), (long)(filename), \
+ (long)(statbuf), (long)(flag))
+#define __sanitizer_syscall_pre_fstatat64(dfd, filename, statbuf, flag) \
+ __sanitizer_syscall_pre_impl_fstatat64((long)(dfd), (long)(filename), \
+ (long)(statbuf), (long)(flag))
+#define __sanitizer_syscall_post_fstatat64(res, dfd, filename, statbuf, flag) \
+ __sanitizer_syscall_post_impl_fstatat64(res, (long)(dfd), (long)(filename), \
+ (long)(statbuf), (long)(flag))
+#define __sanitizer_syscall_pre_readlinkat(dfd, path, buf, bufsiz) \
+ __sanitizer_syscall_pre_impl_readlinkat((long)(dfd), (long)(path), \
+ (long)(buf), (long)(bufsiz))
+#define __sanitizer_syscall_post_readlinkat(res, dfd, path, buf, bufsiz) \
+ __sanitizer_syscall_post_impl_readlinkat(res, (long)(dfd), (long)(path), \
+ (long)(buf), (long)(bufsiz))
+#define __sanitizer_syscall_pre_utimensat(dfd, filename, utimes, flags) \
+ __sanitizer_syscall_pre_impl_utimensat((long)(dfd), (long)(filename), \
+ (long)(utimes), (long)(flags))
+#define __sanitizer_syscall_post_utimensat(res, dfd, filename, utimes, flags) \
+ __sanitizer_syscall_post_impl_utimensat(res, (long)(dfd), (long)(filename), \
+ (long)(utimes), (long)(flags))
+#define __sanitizer_syscall_pre_unshare(unshare_flags) \
+ __sanitizer_syscall_pre_impl_unshare((long)(unshare_flags))
+#define __sanitizer_syscall_post_unshare(res, unshare_flags) \
+ __sanitizer_syscall_post_impl_unshare(res, (long)(unshare_flags))
+#define __sanitizer_syscall_pre_splice(fd_in, off_in, fd_out, off_out, len, \
+ flags) \
+ __sanitizer_syscall_pre_impl_splice((long)(fd_in), (long)(off_in), \
+ (long)(fd_out), (long)(off_out), \
+ (long)(len), (long)(flags))
+#define __sanitizer_syscall_post_splice(res, fd_in, off_in, fd_out, off_out, \
+ len, flags) \
+ __sanitizer_syscall_post_impl_splice(res, (long)(fd_in), (long)(off_in), \
+ (long)(fd_out), (long)(off_out), \
+ (long)(len), (long)(flags))
+#define __sanitizer_syscall_pre_vmsplice(fd, iov, nr_segs, flags) \
+ __sanitizer_syscall_pre_impl_vmsplice((long)(fd), (long)(iov), \
+ (long)(nr_segs), (long)(flags))
+#define __sanitizer_syscall_post_vmsplice(res, fd, iov, nr_segs, flags) \
+ __sanitizer_syscall_post_impl_vmsplice(res, (long)(fd), (long)(iov), \
+ (long)(nr_segs), (long)(flags))
+#define __sanitizer_syscall_pre_tee(fdin, fdout, len, flags) \
+ __sanitizer_syscall_pre_impl_tee((long)(fdin), (long)(fdout), (long)(len), \
+ (long)(flags))
+#define __sanitizer_syscall_post_tee(res, fdin, fdout, len, flags) \
+ __sanitizer_syscall_post_impl_tee(res, (long)(fdin), (long)(fdout), \
+ (long)(len), (long)(flags))
+#define __sanitizer_syscall_pre_get_robust_list(pid, head_ptr, len_ptr) \
+ __sanitizer_syscall_pre_impl_get_robust_list((long)(pid), (long)(head_ptr), \
+ (long)(len_ptr))
+#define __sanitizer_syscall_post_get_robust_list(res, pid, head_ptr, len_ptr) \
+ __sanitizer_syscall_post_impl_get_robust_list( \
+ res, (long)(pid), (long)(head_ptr), (long)(len_ptr))
+#define __sanitizer_syscall_pre_set_robust_list(head, len) \
+ __sanitizer_syscall_pre_impl_set_robust_list((long)(head), (long)(len))
+#define __sanitizer_syscall_post_set_robust_list(res, head, len) \
+ __sanitizer_syscall_post_impl_set_robust_list(res, (long)(head), (long)(len))
+#define __sanitizer_syscall_pre_getcpu(cpu, node, cache) \
+ __sanitizer_syscall_pre_impl_getcpu((long)(cpu), (long)(node), (long)(cache))
+#define __sanitizer_syscall_post_getcpu(res, cpu, node, cache) \
+ __sanitizer_syscall_post_impl_getcpu(res, (long)(cpu), (long)(node), \
+ (long)(cache))
+#define __sanitizer_syscall_pre_signalfd(ufd, user_mask, sizemask) \
+ __sanitizer_syscall_pre_impl_signalfd((long)(ufd), (long)(user_mask), \
+ (long)(sizemask))
+#define __sanitizer_syscall_post_signalfd(res, ufd, user_mask, sizemask) \
+ __sanitizer_syscall_post_impl_signalfd(res, (long)(ufd), (long)(user_mask), \
+ (long)(sizemask))
+#define __sanitizer_syscall_pre_signalfd4(ufd, user_mask, sizemask, flags) \
+ __sanitizer_syscall_pre_impl_signalfd4((long)(ufd), (long)(user_mask), \
+ (long)(sizemask), (long)(flags))
+#define __sanitizer_syscall_post_signalfd4(res, ufd, user_mask, sizemask, \
+ flags) \
+ __sanitizer_syscall_post_impl_signalfd4(res, (long)(ufd), (long)(user_mask), \
+ (long)(sizemask), (long)(flags))
+#define __sanitizer_syscall_pre_timerfd_create(clockid, flags) \
+ __sanitizer_syscall_pre_impl_timerfd_create((long)(clockid), (long)(flags))
+#define __sanitizer_syscall_post_timerfd_create(res, clockid, flags) \
+ __sanitizer_syscall_post_impl_timerfd_create(res, (long)(clockid), \
+ (long)(flags))
+#define __sanitizer_syscall_pre_timerfd_settime(ufd, flags, utmr, otmr) \
+ __sanitizer_syscall_pre_impl_timerfd_settime((long)(ufd), (long)(flags), \
+ (long)(utmr), (long)(otmr))
+#define __sanitizer_syscall_post_timerfd_settime(res, ufd, flags, utmr, otmr) \
+ __sanitizer_syscall_post_impl_timerfd_settime( \
+ res, (long)(ufd), (long)(flags), (long)(utmr), (long)(otmr))
+#define __sanitizer_syscall_pre_timerfd_gettime(ufd, otmr) \
+ __sanitizer_syscall_pre_impl_timerfd_gettime((long)(ufd), (long)(otmr))
+#define __sanitizer_syscall_post_timerfd_gettime(res, ufd, otmr) \
+ __sanitizer_syscall_post_impl_timerfd_gettime(res, (long)(ufd), (long)(otmr))
+#define __sanitizer_syscall_pre_eventfd(count) \
+ __sanitizer_syscall_pre_impl_eventfd((long)(count))
+#define __sanitizer_syscall_post_eventfd(res, count) \
+ __sanitizer_syscall_post_impl_eventfd(res, (long)(count))
+#define __sanitizer_syscall_pre_eventfd2(count, flags) \
+ __sanitizer_syscall_pre_impl_eventfd2((long)(count), (long)(flags))
+#define __sanitizer_syscall_post_eventfd2(res, count, flags) \
+ __sanitizer_syscall_post_impl_eventfd2(res, (long)(count), (long)(flags))
+#define __sanitizer_syscall_pre_old_readdir(arg0, arg1, arg2) \
+ __sanitizer_syscall_pre_impl_old_readdir((long)(arg0), (long)(arg1), \
+ (long)(arg2))
+#define __sanitizer_syscall_post_old_readdir(res, arg0, arg1, arg2) \
+ __sanitizer_syscall_post_impl_old_readdir(res, (long)(arg0), (long)(arg1), \
+ (long)(arg2))
+#define __sanitizer_syscall_pre_pselect6(arg0, arg1, arg2, arg3, arg4, arg5) \
+ __sanitizer_syscall_pre_impl_pselect6((long)(arg0), (long)(arg1), \
+ (long)(arg2), (long)(arg3), \
+ (long)(arg4), (long)(arg5))
+#define __sanitizer_syscall_post_pselect6(res, arg0, arg1, arg2, arg3, arg4, \
+ arg5) \
+ __sanitizer_syscall_post_impl_pselect6(res, (long)(arg0), (long)(arg1), \
+ (long)(arg2), (long)(arg3), \
+ (long)(arg4), (long)(arg5))
+#define __sanitizer_syscall_pre_ppoll(arg0, arg1, arg2, arg3, arg4) \
+ __sanitizer_syscall_pre_impl_ppoll((long)(arg0), (long)(arg1), (long)(arg2), \
+ (long)(arg3), (long)(arg4))
+#define __sanitizer_syscall_post_ppoll(res, arg0, arg1, arg2, arg3, arg4) \
+ __sanitizer_syscall_post_impl_ppoll(res, (long)(arg0), (long)(arg1), \
+ (long)(arg2), (long)(arg3), \
+ (long)(arg4))
+#define __sanitizer_syscall_pre_syncfs(fd) \
+ __sanitizer_syscall_pre_impl_syncfs((long)(fd))
+#define __sanitizer_syscall_post_syncfs(res, fd) \
+ __sanitizer_syscall_post_impl_syncfs(res, (long)(fd))
+#define __sanitizer_syscall_pre_perf_event_open(attr_uptr, pid, cpu, group_fd, \
+ flags) \
+ __sanitizer_syscall_pre_impl_perf_event_open((long)(attr_uptr), (long)(pid), \
+ (long)(cpu), (long)(group_fd), \
+ (long)(flags))
+#define __sanitizer_syscall_post_perf_event_open(res, attr_uptr, pid, cpu, \
+ group_fd, flags) \
+ __sanitizer_syscall_post_impl_perf_event_open( \
+ res, (long)(attr_uptr), (long)(pid), (long)(cpu), (long)(group_fd), \
+ (long)(flags))
+#define __sanitizer_syscall_pre_mmap_pgoff(addr, len, prot, flags, fd, pgoff) \
+ __sanitizer_syscall_pre_impl_mmap_pgoff((long)(addr), (long)(len), \
+ (long)(prot), (long)(flags), \
+ (long)(fd), (long)(pgoff))
+#define __sanitizer_syscall_post_mmap_pgoff(res, addr, len, prot, flags, fd, \
+ pgoff) \
+ __sanitizer_syscall_post_impl_mmap_pgoff(res, (long)(addr), (long)(len), \
+ (long)(prot), (long)(flags), \
+ (long)(fd), (long)(pgoff))
+#define __sanitizer_syscall_pre_old_mmap(arg) \
+ __sanitizer_syscall_pre_impl_old_mmap((long)(arg))
+#define __sanitizer_syscall_post_old_mmap(res, arg) \
+ __sanitizer_syscall_post_impl_old_mmap(res, (long)(arg))
+#define __sanitizer_syscall_pre_name_to_handle_at(dfd, name, handle, mnt_id, \
+ flag) \
+ __sanitizer_syscall_pre_impl_name_to_handle_at( \
+ (long)(dfd), (long)(name), (long)(handle), (long)(mnt_id), (long)(flag))
+#define __sanitizer_syscall_post_name_to_handle_at(res, dfd, name, handle, \
+ mnt_id, flag) \
+ __sanitizer_syscall_post_impl_name_to_handle_at( \
+ res, (long)(dfd), (long)(name), (long)(handle), (long)(mnt_id), \
+ (long)(flag))
+#define __sanitizer_syscall_pre_open_by_handle_at(mountdirfd, handle, flags) \
+ __sanitizer_syscall_pre_impl_open_by_handle_at( \
+ (long)(mountdirfd), (long)(handle), (long)(flags))
+#define __sanitizer_syscall_post_open_by_handle_at(res, mountdirfd, handle, \
+ flags) \
+ __sanitizer_syscall_post_impl_open_by_handle_at( \
+ res, (long)(mountdirfd), (long)(handle), (long)(flags))
+#define __sanitizer_syscall_pre_setns(fd, nstype) \
+ __sanitizer_syscall_pre_impl_setns((long)(fd), (long)(nstype))
+#define __sanitizer_syscall_post_setns(res, fd, nstype) \
+ __sanitizer_syscall_post_impl_setns(res, (long)(fd), (long)(nstype))
+#define __sanitizer_syscall_pre_process_vm_readv(pid, lvec, liovcnt, rvec, \
+ riovcnt, flags) \
+ __sanitizer_syscall_pre_impl_process_vm_readv( \
+ (long)(pid), (long)(lvec), (long)(liovcnt), (long)(rvec), \
+ (long)(riovcnt), (long)(flags))
+#define __sanitizer_syscall_post_process_vm_readv(res, pid, lvec, liovcnt, \
+ rvec, riovcnt, flags) \
+ __sanitizer_syscall_post_impl_process_vm_readv( \
+ res, (long)(pid), (long)(lvec), (long)(liovcnt), (long)(rvec), \
+ (long)(riovcnt), (long)(flags))
+#define __sanitizer_syscall_pre_process_vm_writev(pid, lvec, liovcnt, rvec, \
+ riovcnt, flags) \
+ __sanitizer_syscall_pre_impl_process_vm_writev( \
+ (long)(pid), (long)(lvec), (long)(liovcnt), (long)(rvec), \
+ (long)(riovcnt), (long)(flags))
+#define __sanitizer_syscall_post_process_vm_writev(res, pid, lvec, liovcnt, \
+ rvec, riovcnt, flags) \
+ __sanitizer_syscall_post_impl_process_vm_writev( \
+ res, (long)(pid), (long)(lvec), (long)(liovcnt), (long)(rvec), \
+ (long)(riovcnt), (long)(flags))
+#define __sanitizer_syscall_pre_fork() \
+ __sanitizer_syscall_pre_impl_fork()
+#define __sanitizer_syscall_post_fork(res) \
+ __sanitizer_syscall_post_impl_fork(res)
+#define __sanitizer_syscall_pre_vfork() \
+ __sanitizer_syscall_pre_impl_vfork()
+#define __sanitizer_syscall_post_vfork(res) \
+ __sanitizer_syscall_post_impl_vfork(res)
+
+// And now a few syscalls we don't handle yet.
+#define __sanitizer_syscall_pre_afs_syscall(...)
+#define __sanitizer_syscall_pre_arch_prctl(...)
+#define __sanitizer_syscall_pre_break(...)
+#define __sanitizer_syscall_pre_chown32(...)
+#define __sanitizer_syscall_pre_clone(...)
+#define __sanitizer_syscall_pre_create_module(...)
+#define __sanitizer_syscall_pre_epoll_ctl_old(...)
+#define __sanitizer_syscall_pre_epoll_wait_old(...)
+#define __sanitizer_syscall_pre_execve(...)
+#define __sanitizer_syscall_pre_fadvise64(...)
+#define __sanitizer_syscall_pre_fadvise64_64(...)
+#define __sanitizer_syscall_pre_fallocate(...)
+#define __sanitizer_syscall_pre_fanotify_init(...)
+#define __sanitizer_syscall_pre_fanotify_mark(...)
+#define __sanitizer_syscall_pre_fchown32(...)
+#define __sanitizer_syscall_pre_ftime(...)
+#define __sanitizer_syscall_pre_ftruncate64(...)
+#define __sanitizer_syscall_pre_futex(...)
+#define __sanitizer_syscall_pre_getegid32(...)
+#define __sanitizer_syscall_pre_geteuid32(...)
+#define __sanitizer_syscall_pre_getgid32(...)
+#define __sanitizer_syscall_pre_getgroups32(...)
+#define __sanitizer_syscall_pre_get_kernel_syms(...)
+#define __sanitizer_syscall_pre_getpmsg(...)
+#define __sanitizer_syscall_pre_getresgid32(...)
+#define __sanitizer_syscall_pre_getresuid32(...)
+#define __sanitizer_syscall_pre_get_thread_area(...)
+#define __sanitizer_syscall_pre_getuid32(...)
+#define __sanitizer_syscall_pre_gtty(...)
+#define __sanitizer_syscall_pre_idle(...)
+#define __sanitizer_syscall_pre_iopl(...)
+#define __sanitizer_syscall_pre_lchown32(...)
+#define __sanitizer_syscall_pre__llseek(...)
+#define __sanitizer_syscall_pre_lock(...)
+#define __sanitizer_syscall_pre_madvise1(...)
+#define __sanitizer_syscall_pre_mmap(...)
+#define __sanitizer_syscall_pre_mmap2(...)
+#define __sanitizer_syscall_pre_modify_ldt(...)
+#define __sanitizer_syscall_pre_mpx(...)
+#define __sanitizer_syscall_pre__newselect(...)
+#define __sanitizer_syscall_pre_nfsservctl(...)
+#define __sanitizer_syscall_pre_oldfstat(...)
+#define __sanitizer_syscall_pre_oldlstat(...)
+#define __sanitizer_syscall_pre_oldolduname(...)
+#define __sanitizer_syscall_pre_oldstat(...)
+#define __sanitizer_syscall_pre_prctl(...)
+#define __sanitizer_syscall_pre_prof(...)
+#define __sanitizer_syscall_pre_profil(...)
+#define __sanitizer_syscall_pre_putpmsg(...)
+#define __sanitizer_syscall_pre_query_module(...)
+#define __sanitizer_syscall_pre_readahead(...)
+#define __sanitizer_syscall_pre_readdir(...)
+#define __sanitizer_syscall_pre_rt_sigaction(...)
+#define __sanitizer_syscall_pre_rt_sigreturn(...)
+#define __sanitizer_syscall_pre_rt_sigsuspend(...)
+#define __sanitizer_syscall_pre_security(...)
+#define __sanitizer_syscall_pre_setfsgid32(...)
+#define __sanitizer_syscall_pre_setfsuid32(...)
+#define __sanitizer_syscall_pre_setgid32(...)
+#define __sanitizer_syscall_pre_setgroups32(...)
+#define __sanitizer_syscall_pre_setregid32(...)
+#define __sanitizer_syscall_pre_setresgid32(...)
+#define __sanitizer_syscall_pre_setresuid32(...)
+#define __sanitizer_syscall_pre_setreuid32(...)
+#define __sanitizer_syscall_pre_set_thread_area(...)
+#define __sanitizer_syscall_pre_setuid32(...)
+#define __sanitizer_syscall_pre_sigaction(...)
+#define __sanitizer_syscall_pre_sigaltstack(...)
+#define __sanitizer_syscall_pre_sigreturn(...)
+#define __sanitizer_syscall_pre_sigsuspend(...)
+#define __sanitizer_syscall_pre_stty(...)
+#define __sanitizer_syscall_pre_sync_file_range(...)
+#define __sanitizer_syscall_pre__sysctl(...)
+#define __sanitizer_syscall_pre_truncate64(...)
+#define __sanitizer_syscall_pre_tuxcall(...)
+#define __sanitizer_syscall_pre_ugetrlimit(...)
+#define __sanitizer_syscall_pre_ulimit(...)
+#define __sanitizer_syscall_pre_umount2(...)
+#define __sanitizer_syscall_pre_vm86(...)
+#define __sanitizer_syscall_pre_vm86old(...)
+#define __sanitizer_syscall_pre_vserver(...)
+
+#define __sanitizer_syscall_post_afs_syscall(res, ...)
+#define __sanitizer_syscall_post_arch_prctl(res, ...)
+#define __sanitizer_syscall_post_break(res, ...)
+#define __sanitizer_syscall_post_chown32(res, ...)
+#define __sanitizer_syscall_post_clone(res, ...)
+#define __sanitizer_syscall_post_create_module(res, ...)
+#define __sanitizer_syscall_post_epoll_ctl_old(res, ...)
+#define __sanitizer_syscall_post_epoll_wait_old(res, ...)
+#define __sanitizer_syscall_post_execve(res, ...)
+#define __sanitizer_syscall_post_fadvise64(res, ...)
+#define __sanitizer_syscall_post_fadvise64_64(res, ...)
+#define __sanitizer_syscall_post_fallocate(res, ...)
+#define __sanitizer_syscall_post_fanotify_init(res, ...)
+#define __sanitizer_syscall_post_fanotify_mark(res, ...)
+#define __sanitizer_syscall_post_fchown32(res, ...)
+#define __sanitizer_syscall_post_ftime(res, ...)
+#define __sanitizer_syscall_post_ftruncate64(res, ...)
+#define __sanitizer_syscall_post_futex(res, ...)
+#define __sanitizer_syscall_post_getegid32(res, ...)
+#define __sanitizer_syscall_post_geteuid32(res, ...)
+#define __sanitizer_syscall_post_getgid32(res, ...)
+#define __sanitizer_syscall_post_getgroups32(res, ...)
+#define __sanitizer_syscall_post_get_kernel_syms(res, ...)
+#define __sanitizer_syscall_post_getpmsg(res, ...)
+#define __sanitizer_syscall_post_getresgid32(res, ...)
+#define __sanitizer_syscall_post_getresuid32(res, ...)
+#define __sanitizer_syscall_post_get_thread_area(res, ...)
+#define __sanitizer_syscall_post_getuid32(res, ...)
+#define __sanitizer_syscall_post_gtty(res, ...)
+#define __sanitizer_syscall_post_idle(res, ...)
+#define __sanitizer_syscall_post_iopl(res, ...)
+#define __sanitizer_syscall_post_lchown32(res, ...)
+#define __sanitizer_syscall_post__llseek(res, ...)
+#define __sanitizer_syscall_post_lock(res, ...)
+#define __sanitizer_syscall_post_madvise1(res, ...)
+#define __sanitizer_syscall_post_mmap2(res, ...)
+#define __sanitizer_syscall_post_mmap(res, ...)
+#define __sanitizer_syscall_post_modify_ldt(res, ...)
+#define __sanitizer_syscall_post_mpx(res, ...)
+#define __sanitizer_syscall_post__newselect(res, ...)
+#define __sanitizer_syscall_post_nfsservctl(res, ...)
+#define __sanitizer_syscall_post_oldfstat(res, ...)
+#define __sanitizer_syscall_post_oldlstat(res, ...)
+#define __sanitizer_syscall_post_oldolduname(res, ...)
+#define __sanitizer_syscall_post_oldstat(res, ...)
+#define __sanitizer_syscall_post_prctl(res, ...)
+#define __sanitizer_syscall_post_profil(res, ...)
+#define __sanitizer_syscall_post_prof(res, ...)
+#define __sanitizer_syscall_post_putpmsg(res, ...)
+#define __sanitizer_syscall_post_query_module(res, ...)
+#define __sanitizer_syscall_post_readahead(res, ...)
+#define __sanitizer_syscall_post_readdir(res, ...)
+#define __sanitizer_syscall_post_rt_sigaction(res, ...)
+#define __sanitizer_syscall_post_rt_sigreturn(res, ...)
+#define __sanitizer_syscall_post_rt_sigsuspend(res, ...)
+#define __sanitizer_syscall_post_security(res, ...)
+#define __sanitizer_syscall_post_setfsgid32(res, ...)
+#define __sanitizer_syscall_post_setfsuid32(res, ...)
+#define __sanitizer_syscall_post_setgid32(res, ...)
+#define __sanitizer_syscall_post_setgroups32(res, ...)
+#define __sanitizer_syscall_post_setregid32(res, ...)
+#define __sanitizer_syscall_post_setresgid32(res, ...)
+#define __sanitizer_syscall_post_setresuid32(res, ...)
+#define __sanitizer_syscall_post_setreuid32(res, ...)
+#define __sanitizer_syscall_post_set_thread_area(res, ...)
+#define __sanitizer_syscall_post_setuid32(res, ...)
+#define __sanitizer_syscall_post_sigaction(res, ...)
+#define __sanitizer_syscall_post_sigaltstack(res, ...)
+#define __sanitizer_syscall_post_sigreturn(res, ...)
+#define __sanitizer_syscall_post_sigsuspend(res, ...)
+#define __sanitizer_syscall_post_stty(res, ...)
+#define __sanitizer_syscall_post_sync_file_range(res, ...)
+#define __sanitizer_syscall_post__sysctl(res, ...)
+#define __sanitizer_syscall_post_truncate64(res, ...)
+#define __sanitizer_syscall_post_tuxcall(res, ...)
+#define __sanitizer_syscall_post_ugetrlimit(res, ...)
+#define __sanitizer_syscall_post_ulimit(res, ...)
+#define __sanitizer_syscall_post_umount2(res, ...)
+#define __sanitizer_syscall_post_vm86old(res, ...)
+#define __sanitizer_syscall_post_vm86(res, ...)
+#define __sanitizer_syscall_post_vserver(res, ...)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Private declarations. Do not call directly from user code. Use macros above.
+void __sanitizer_syscall_pre_impl_time(long tloc);
+void __sanitizer_syscall_post_impl_time(long res, long tloc);
+void __sanitizer_syscall_pre_impl_stime(long tptr);
+void __sanitizer_syscall_post_impl_stime(long res, long tptr);
+void __sanitizer_syscall_pre_impl_gettimeofday(long tv, long tz);
+void __sanitizer_syscall_post_impl_gettimeofday(long res, long tv, long tz);
+void __sanitizer_syscall_pre_impl_settimeofday(long tv, long tz);
+void __sanitizer_syscall_post_impl_settimeofday(long res, long tv, long tz);
+void __sanitizer_syscall_pre_impl_adjtimex(long txc_p);
+void __sanitizer_syscall_post_impl_adjtimex(long res, long txc_p);
+void __sanitizer_syscall_pre_impl_times(long tbuf);
+void __sanitizer_syscall_post_impl_times(long res, long tbuf);
+void __sanitizer_syscall_pre_impl_gettid();
+void __sanitizer_syscall_post_impl_gettid(long res);
+void __sanitizer_syscall_pre_impl_nanosleep(long rqtp, long rmtp);
+void __sanitizer_syscall_post_impl_nanosleep(long res, long rqtp, long rmtp);
+void __sanitizer_syscall_pre_impl_alarm(long seconds);
+void __sanitizer_syscall_post_impl_alarm(long res, long seconds);
+void __sanitizer_syscall_pre_impl_getpid();
+void __sanitizer_syscall_post_impl_getpid(long res);
+void __sanitizer_syscall_pre_impl_getppid();
+void __sanitizer_syscall_post_impl_getppid(long res);
+void __sanitizer_syscall_pre_impl_getuid();
+void __sanitizer_syscall_post_impl_getuid(long res);
+void __sanitizer_syscall_pre_impl_geteuid();
+void __sanitizer_syscall_post_impl_geteuid(long res);
+void __sanitizer_syscall_pre_impl_getgid();
+void __sanitizer_syscall_post_impl_getgid(long res);
+void __sanitizer_syscall_pre_impl_getegid();
+void __sanitizer_syscall_post_impl_getegid(long res);
+void __sanitizer_syscall_pre_impl_getresuid(long ruid, long euid, long suid);
+void __sanitizer_syscall_post_impl_getresuid(long res, long ruid, long euid,
+ long suid);
+void __sanitizer_syscall_pre_impl_getresgid(long rgid, long egid, long sgid);
+void __sanitizer_syscall_post_impl_getresgid(long res, long rgid, long egid,
+ long sgid);
+void __sanitizer_syscall_pre_impl_getpgid(long pid);
+void __sanitizer_syscall_post_impl_getpgid(long res, long pid);
+void __sanitizer_syscall_pre_impl_getpgrp();
+void __sanitizer_syscall_post_impl_getpgrp(long res);
+void __sanitizer_syscall_pre_impl_getsid(long pid);
+void __sanitizer_syscall_post_impl_getsid(long res, long pid);
+void __sanitizer_syscall_pre_impl_getgroups(long gidsetsize, long grouplist);
+void __sanitizer_syscall_post_impl_getgroups(long res, long gidsetsize,
+ long grouplist);
+void __sanitizer_syscall_pre_impl_setregid(long rgid, long egid);
+void __sanitizer_syscall_post_impl_setregid(long res, long rgid, long egid);
+void __sanitizer_syscall_pre_impl_setgid(long gid);
+void __sanitizer_syscall_post_impl_setgid(long res, long gid);
+void __sanitizer_syscall_pre_impl_setreuid(long ruid, long euid);
+void __sanitizer_syscall_post_impl_setreuid(long res, long ruid, long euid);
+void __sanitizer_syscall_pre_impl_setuid(long uid);
+void __sanitizer_syscall_post_impl_setuid(long res, long uid);
+void __sanitizer_syscall_pre_impl_setresuid(long ruid, long euid, long suid);
+void __sanitizer_syscall_post_impl_setresuid(long res, long ruid, long euid,
+ long suid);
+void __sanitizer_syscall_pre_impl_setresgid(long rgid, long egid, long sgid);
+void __sanitizer_syscall_post_impl_setresgid(long res, long rgid, long egid,
+ long sgid);
+void __sanitizer_syscall_pre_impl_setfsuid(long uid);
+void __sanitizer_syscall_post_impl_setfsuid(long res, long uid);
+void __sanitizer_syscall_pre_impl_setfsgid(long gid);
+void __sanitizer_syscall_post_impl_setfsgid(long res, long gid);
+void __sanitizer_syscall_pre_impl_setpgid(long pid, long pgid);
+void __sanitizer_syscall_post_impl_setpgid(long res, long pid, long pgid);
+void __sanitizer_syscall_pre_impl_setsid();
+void __sanitizer_syscall_post_impl_setsid(long res);
+void __sanitizer_syscall_pre_impl_setgroups(long gidsetsize, long grouplist);
+void __sanitizer_syscall_post_impl_setgroups(long res, long gidsetsize,
+ long grouplist);
+void __sanitizer_syscall_pre_impl_acct(long name);
+void __sanitizer_syscall_post_impl_acct(long res, long name);
+void __sanitizer_syscall_pre_impl_capget(long header, long dataptr);
+void __sanitizer_syscall_post_impl_capget(long res, long header, long dataptr);
+void __sanitizer_syscall_pre_impl_capset(long header, long data);
+void __sanitizer_syscall_post_impl_capset(long res, long header, long data);
+void __sanitizer_syscall_pre_impl_personality(long personality);
+void __sanitizer_syscall_post_impl_personality(long res, long personality);
+void __sanitizer_syscall_pre_impl_sigpending(long set);
+void __sanitizer_syscall_post_impl_sigpending(long res, long set);
+void __sanitizer_syscall_pre_impl_sigprocmask(long how, long set, long oset);
+void __sanitizer_syscall_post_impl_sigprocmask(long res, long how, long set,
+ long oset);
+void __sanitizer_syscall_pre_impl_getitimer(long which, long value);
+void __sanitizer_syscall_post_impl_getitimer(long res, long which, long value);
+void __sanitizer_syscall_pre_impl_setitimer(long which, long value,
+ long ovalue);
+void __sanitizer_syscall_post_impl_setitimer(long res, long which, long value,
+ long ovalue);
+void __sanitizer_syscall_pre_impl_timer_create(long which_clock,
+ long timer_event_spec,
+ long created_timer_id);
+void __sanitizer_syscall_post_impl_timer_create(long res, long which_clock,
+ long timer_event_spec,
+ long created_timer_id);
+void __sanitizer_syscall_pre_impl_timer_gettime(long timer_id, long setting);
+void __sanitizer_syscall_post_impl_timer_gettime(long res, long timer_id,
+ long setting);
+void __sanitizer_syscall_pre_impl_timer_getoverrun(long timer_id);
+void __sanitizer_syscall_post_impl_timer_getoverrun(long res, long timer_id);
+void __sanitizer_syscall_pre_impl_timer_settime(long timer_id, long flags,
+ long new_setting,
+ long old_setting);
+void __sanitizer_syscall_post_impl_timer_settime(long res, long timer_id,
+ long flags, long new_setting,
+ long old_setting);
+void __sanitizer_syscall_pre_impl_timer_delete(long timer_id);
+void __sanitizer_syscall_post_impl_timer_delete(long res, long timer_id);
+void __sanitizer_syscall_pre_impl_clock_settime(long which_clock, long tp);
+void __sanitizer_syscall_post_impl_clock_settime(long res, long which_clock,
+ long tp);
+void __sanitizer_syscall_pre_impl_clock_gettime(long which_clock, long tp);
+void __sanitizer_syscall_post_impl_clock_gettime(long res, long which_clock,
+ long tp);
+void __sanitizer_syscall_pre_impl_clock_adjtime(long which_clock, long tx);
+void __sanitizer_syscall_post_impl_clock_adjtime(long res, long which_clock,
+ long tx);
+void __sanitizer_syscall_pre_impl_clock_getres(long which_clock, long tp);
+void __sanitizer_syscall_post_impl_clock_getres(long res, long which_clock,
+ long tp);
+void __sanitizer_syscall_pre_impl_clock_nanosleep(long which_clock, long flags,
+ long rqtp, long rmtp);
+void __sanitizer_syscall_post_impl_clock_nanosleep(long res, long which_clock,
+ long flags, long rqtp,
+ long rmtp);
+void __sanitizer_syscall_pre_impl_nice(long increment);
+void __sanitizer_syscall_post_impl_nice(long res, long increment);
+void __sanitizer_syscall_pre_impl_sched_setscheduler(long pid, long policy,
+ long param);
+void __sanitizer_syscall_post_impl_sched_setscheduler(long res, long pid,
+ long policy, long param);
+void __sanitizer_syscall_pre_impl_sched_setparam(long pid, long param);
+void __sanitizer_syscall_post_impl_sched_setparam(long res, long pid,
+ long param);
+void __sanitizer_syscall_pre_impl_sched_getscheduler(long pid);
+void __sanitizer_syscall_post_impl_sched_getscheduler(long res, long pid);
+void __sanitizer_syscall_pre_impl_sched_getparam(long pid, long param);
+void __sanitizer_syscall_post_impl_sched_getparam(long res, long pid,
+ long param);
+void __sanitizer_syscall_pre_impl_sched_setaffinity(long pid, long len,
+ long user_mask_ptr);
+void __sanitizer_syscall_post_impl_sched_setaffinity(long res, long pid,
+ long len,
+ long user_mask_ptr);
+void __sanitizer_syscall_pre_impl_sched_getaffinity(long pid, long len,
+ long user_mask_ptr);
+void __sanitizer_syscall_post_impl_sched_getaffinity(long res, long pid,
+ long len,
+ long user_mask_ptr);
+void __sanitizer_syscall_pre_impl_sched_yield();
+void __sanitizer_syscall_post_impl_sched_yield(long res);
+void __sanitizer_syscall_pre_impl_sched_get_priority_max(long policy);
+void __sanitizer_syscall_post_impl_sched_get_priority_max(long res,
+ long policy);
+void __sanitizer_syscall_pre_impl_sched_get_priority_min(long policy);
+void __sanitizer_syscall_post_impl_sched_get_priority_min(long res,
+ long policy);
+void __sanitizer_syscall_pre_impl_sched_rr_get_interval(long pid,
+ long interval);
+void __sanitizer_syscall_post_impl_sched_rr_get_interval(long res, long pid,
+ long interval);
+void __sanitizer_syscall_pre_impl_setpriority(long which, long who,
+ long niceval);
+void __sanitizer_syscall_post_impl_setpriority(long res, long which, long who,
+ long niceval);
+void __sanitizer_syscall_pre_impl_getpriority(long which, long who);
+void __sanitizer_syscall_post_impl_getpriority(long res, long which, long who);
+void __sanitizer_syscall_pre_impl_shutdown(long arg0, long arg1);
+void __sanitizer_syscall_post_impl_shutdown(long res, long arg0, long arg1);
+void __sanitizer_syscall_pre_impl_reboot(long magic1, long magic2, long cmd,
+ long arg);
+void __sanitizer_syscall_post_impl_reboot(long res, long magic1, long magic2,
+ long cmd, long arg);
+void __sanitizer_syscall_pre_impl_restart_syscall();
+void __sanitizer_syscall_post_impl_restart_syscall(long res);
+void __sanitizer_syscall_pre_impl_kexec_load(long entry, long nr_segments,
+ long segments, long flags);
+void __sanitizer_syscall_post_impl_kexec_load(long res, long entry,
+ long nr_segments, long segments,
+ long flags);
+void __sanitizer_syscall_pre_impl_exit(long error_code);
+void __sanitizer_syscall_post_impl_exit(long res, long error_code);
+void __sanitizer_syscall_pre_impl_exit_group(long error_code);
+void __sanitizer_syscall_post_impl_exit_group(long res, long error_code);
+void __sanitizer_syscall_pre_impl_wait4(long pid, long stat_addr, long options,
+ long ru);
+void __sanitizer_syscall_post_impl_wait4(long res, long pid, long stat_addr,
+ long options, long ru);
+void __sanitizer_syscall_pre_impl_waitid(long which, long pid, long infop,
+ long options, long ru);
+void __sanitizer_syscall_post_impl_waitid(long res, long which, long pid,
+ long infop, long options, long ru);
+void __sanitizer_syscall_pre_impl_waitpid(long pid, long stat_addr,
+ long options);
+void __sanitizer_syscall_post_impl_waitpid(long res, long pid, long stat_addr,
+ long options);
+void __sanitizer_syscall_pre_impl_set_tid_address(long tidptr);
+void __sanitizer_syscall_post_impl_set_tid_address(long res, long tidptr);
+void __sanitizer_syscall_pre_impl_init_module(long umod, long len, long uargs);
+void __sanitizer_syscall_post_impl_init_module(long res, long umod, long len,
+ long uargs);
+void __sanitizer_syscall_pre_impl_delete_module(long name_user, long flags);
+void __sanitizer_syscall_post_impl_delete_module(long res, long name_user,
+ long flags);
+void __sanitizer_syscall_pre_impl_rt_sigprocmask(long how, long set, long oset,
+ long sigsetsize);
+void __sanitizer_syscall_post_impl_rt_sigprocmask(long res, long how, long set,
+ long oset, long sigsetsize);
+void __sanitizer_syscall_pre_impl_rt_sigpending(long set, long sigsetsize);
+void __sanitizer_syscall_post_impl_rt_sigpending(long res, long set,
+ long sigsetsize);
+void __sanitizer_syscall_pre_impl_rt_sigtimedwait(long uthese, long uinfo,
+ long uts, long sigsetsize);
+void __sanitizer_syscall_post_impl_rt_sigtimedwait(long res, long uthese,
+ long uinfo, long uts,
+ long sigsetsize);
+void __sanitizer_syscall_pre_impl_rt_tgsigqueueinfo(long tgid, long pid,
+ long sig, long uinfo);
+void __sanitizer_syscall_post_impl_rt_tgsigqueueinfo(long res, long tgid,
+ long pid, long sig,
+ long uinfo);
+void __sanitizer_syscall_pre_impl_kill(long pid, long sig);
+void __sanitizer_syscall_post_impl_kill(long res, long pid, long sig);
+void __sanitizer_syscall_pre_impl_tgkill(long tgid, long pid, long sig);
+void __sanitizer_syscall_post_impl_tgkill(long res, long tgid, long pid,
+ long sig);
+void __sanitizer_syscall_pre_impl_tkill(long pid, long sig);
+void __sanitizer_syscall_post_impl_tkill(long res, long pid, long sig);
+void __sanitizer_syscall_pre_impl_rt_sigqueueinfo(long pid, long sig,
+ long uinfo);
+void __sanitizer_syscall_post_impl_rt_sigqueueinfo(long res, long pid, long sig,
+ long uinfo);
+void __sanitizer_syscall_pre_impl_sgetmask();
+void __sanitizer_syscall_post_impl_sgetmask(long res);
+void __sanitizer_syscall_pre_impl_ssetmask(long newmask);
+void __sanitizer_syscall_post_impl_ssetmask(long res, long newmask);
+void __sanitizer_syscall_pre_impl_signal(long sig, long handler);
+void __sanitizer_syscall_post_impl_signal(long res, long sig, long handler);
+void __sanitizer_syscall_pre_impl_pause();
+void __sanitizer_syscall_post_impl_pause(long res);
+void __sanitizer_syscall_pre_impl_sync();
+void __sanitizer_syscall_post_impl_sync(long res);
+void __sanitizer_syscall_pre_impl_fsync(long fd);
+void __sanitizer_syscall_post_impl_fsync(long res, long fd);
+void __sanitizer_syscall_pre_impl_fdatasync(long fd);
+void __sanitizer_syscall_post_impl_fdatasync(long res, long fd);
+void __sanitizer_syscall_pre_impl_bdflush(long func, long data);
+void __sanitizer_syscall_post_impl_bdflush(long res, long func, long data);
+void __sanitizer_syscall_pre_impl_mount(long dev_name, long dir_name, long type,
+ long flags, long data);
+void __sanitizer_syscall_post_impl_mount(long res, long dev_name, long dir_name,
+ long type, long flags, long data);
+void __sanitizer_syscall_pre_impl_umount(long name, long flags);
+void __sanitizer_syscall_post_impl_umount(long res, long name, long flags);
+void __sanitizer_syscall_pre_impl_oldumount(long name);
+void __sanitizer_syscall_post_impl_oldumount(long res, long name);
+void __sanitizer_syscall_pre_impl_truncate(long path, long length);
+void __sanitizer_syscall_post_impl_truncate(long res, long path, long length);
+void __sanitizer_syscall_pre_impl_ftruncate(long fd, long length);
+void __sanitizer_syscall_post_impl_ftruncate(long res, long fd, long length);
+void __sanitizer_syscall_pre_impl_stat(long filename, long statbuf);
+void __sanitizer_syscall_post_impl_stat(long res, long filename, long statbuf);
+void __sanitizer_syscall_pre_impl_statfs(long path, long buf);
+void __sanitizer_syscall_post_impl_statfs(long res, long path, long buf);
+void __sanitizer_syscall_pre_impl_statfs64(long path, long sz, long buf);
+void __sanitizer_syscall_post_impl_statfs64(long res, long path, long sz,
+ long buf);
+void __sanitizer_syscall_pre_impl_fstatfs(long fd, long buf);
+void __sanitizer_syscall_post_impl_fstatfs(long res, long fd, long buf);
+void __sanitizer_syscall_pre_impl_fstatfs64(long fd, long sz, long buf);
+void __sanitizer_syscall_post_impl_fstatfs64(long res, long fd, long sz,
+ long buf);
+void __sanitizer_syscall_pre_impl_lstat(long filename, long statbuf);
+void __sanitizer_syscall_post_impl_lstat(long res, long filename, long statbuf);
+void __sanitizer_syscall_pre_impl_fstat(long fd, long statbuf);
+void __sanitizer_syscall_post_impl_fstat(long res, long fd, long statbuf);
+void __sanitizer_syscall_pre_impl_newstat(long filename, long statbuf);
+void __sanitizer_syscall_post_impl_newstat(long res, long filename,
+ long statbuf);
+void __sanitizer_syscall_pre_impl_newlstat(long filename, long statbuf);
+void __sanitizer_syscall_post_impl_newlstat(long res, long filename,
+ long statbuf);
+void __sanitizer_syscall_pre_impl_newfstat(long fd, long statbuf);
+void __sanitizer_syscall_post_impl_newfstat(long res, long fd, long statbuf);
+void __sanitizer_syscall_pre_impl_ustat(long dev, long ubuf);
+void __sanitizer_syscall_post_impl_ustat(long res, long dev, long ubuf);
+void __sanitizer_syscall_pre_impl_stat64(long filename, long statbuf);
+void __sanitizer_syscall_post_impl_stat64(long res, long filename,
+ long statbuf);
+void __sanitizer_syscall_pre_impl_fstat64(long fd, long statbuf);
+void __sanitizer_syscall_post_impl_fstat64(long res, long fd, long statbuf);
+void __sanitizer_syscall_pre_impl_lstat64(long filename, long statbuf);
+void __sanitizer_syscall_post_impl_lstat64(long res, long filename,
+ long statbuf);
+void __sanitizer_syscall_pre_impl_setxattr(long path, long name, long value,
+ long size, long flags);
+void __sanitizer_syscall_post_impl_setxattr(long res, long path, long name,
+ long value, long size, long flags);
+void __sanitizer_syscall_pre_impl_lsetxattr(long path, long name, long value,
+ long size, long flags);
+void __sanitizer_syscall_post_impl_lsetxattr(long res, long path, long name,
+ long value, long size, long flags);
+void __sanitizer_syscall_pre_impl_fsetxattr(long fd, long name, long value,
+ long size, long flags);
+void __sanitizer_syscall_post_impl_fsetxattr(long res, long fd, long name,
+ long value, long size, long flags);
+void __sanitizer_syscall_pre_impl_getxattr(long path, long name, long value,
+ long size);
+void __sanitizer_syscall_post_impl_getxattr(long res, long path, long name,
+ long value, long size);
+void __sanitizer_syscall_pre_impl_lgetxattr(long path, long name, long value,
+ long size);
+void __sanitizer_syscall_post_impl_lgetxattr(long res, long path, long name,
+ long value, long size);
+void __sanitizer_syscall_pre_impl_fgetxattr(long fd, long name, long value,
+ long size);
+void __sanitizer_syscall_post_impl_fgetxattr(long res, long fd, long name,
+ long value, long size);
+void __sanitizer_syscall_pre_impl_listxattr(long path, long list, long size);
+void __sanitizer_syscall_post_impl_listxattr(long res, long path, long list,
+ long size);
+void __sanitizer_syscall_pre_impl_llistxattr(long path, long list, long size);
+void __sanitizer_syscall_post_impl_llistxattr(long res, long path, long list,
+ long size);
+void __sanitizer_syscall_pre_impl_flistxattr(long fd, long list, long size);
+void __sanitizer_syscall_post_impl_flistxattr(long res, long fd, long list,
+ long size);
+void __sanitizer_syscall_pre_impl_removexattr(long path, long name);
+void __sanitizer_syscall_post_impl_removexattr(long res, long path, long name);
+void __sanitizer_syscall_pre_impl_lremovexattr(long path, long name);
+void __sanitizer_syscall_post_impl_lremovexattr(long res, long path, long name);
+void __sanitizer_syscall_pre_impl_fremovexattr(long fd, long name);
+void __sanitizer_syscall_post_impl_fremovexattr(long res, long fd, long name);
+void __sanitizer_syscall_pre_impl_brk(long brk);
+void __sanitizer_syscall_post_impl_brk(long res, long brk);
+void __sanitizer_syscall_pre_impl_mprotect(long start, long len, long prot);
+void __sanitizer_syscall_post_impl_mprotect(long res, long start, long len,
+ long prot);
+void __sanitizer_syscall_pre_impl_mremap(long addr, long old_len, long new_len,
+ long flags, long new_addr);
+void __sanitizer_syscall_post_impl_mremap(long res, long addr, long old_len,
+ long new_len, long flags,
+ long new_addr);
+void __sanitizer_syscall_pre_impl_remap_file_pages(long start, long size,
+ long prot, long pgoff,
+ long flags);
+void __sanitizer_syscall_post_impl_remap_file_pages(long res, long start,
+ long size, long prot,
+ long pgoff, long flags);
+void __sanitizer_syscall_pre_impl_msync(long start, long len, long flags);
+void __sanitizer_syscall_post_impl_msync(long res, long start, long len,
+ long flags);
+void __sanitizer_syscall_pre_impl_munmap(long addr, long len);
+void __sanitizer_syscall_post_impl_munmap(long res, long addr, long len);
+void __sanitizer_syscall_pre_impl_mlock(long start, long len);
+void __sanitizer_syscall_post_impl_mlock(long res, long start, long len);
+void __sanitizer_syscall_pre_impl_munlock(long start, long len);
+void __sanitizer_syscall_post_impl_munlock(long res, long start, long len);
+void __sanitizer_syscall_pre_impl_mlockall(long flags);
+void __sanitizer_syscall_post_impl_mlockall(long res, long flags);
+void __sanitizer_syscall_pre_impl_munlockall();
+void __sanitizer_syscall_post_impl_munlockall(long res);
+void __sanitizer_syscall_pre_impl_madvise(long start, long len, long behavior);
+void __sanitizer_syscall_post_impl_madvise(long res, long start, long len,
+ long behavior);
+void __sanitizer_syscall_pre_impl_mincore(long start, long len, long vec);
+void __sanitizer_syscall_post_impl_mincore(long res, long start, long len,
+ long vec);
+void __sanitizer_syscall_pre_impl_pivot_root(long new_root, long put_old);
+void __sanitizer_syscall_post_impl_pivot_root(long res, long new_root,
+ long put_old);
+void __sanitizer_syscall_pre_impl_chroot(long filename);
+void __sanitizer_syscall_post_impl_chroot(long res, long filename);
+void __sanitizer_syscall_pre_impl_mknod(long filename, long mode, long dev);
+void __sanitizer_syscall_post_impl_mknod(long res, long filename, long mode,
+ long dev);
+void __sanitizer_syscall_pre_impl_link(long oldname, long newname);
+void __sanitizer_syscall_post_impl_link(long res, long oldname, long newname);
+void __sanitizer_syscall_pre_impl_symlink(long old, long new_);
+void __sanitizer_syscall_post_impl_symlink(long res, long old, long new_);
+void __sanitizer_syscall_pre_impl_unlink(long pathname);
+void __sanitizer_syscall_post_impl_unlink(long res, long pathname);
+void __sanitizer_syscall_pre_impl_rename(long oldname, long newname);
+void __sanitizer_syscall_post_impl_rename(long res, long oldname, long newname);
+void __sanitizer_syscall_pre_impl_chmod(long filename, long mode);
+void __sanitizer_syscall_post_impl_chmod(long res, long filename, long mode);
+void __sanitizer_syscall_pre_impl_fchmod(long fd, long mode);
+void __sanitizer_syscall_post_impl_fchmod(long res, long fd, long mode);
+void __sanitizer_syscall_pre_impl_fcntl(long fd, long cmd, long arg);
+void __sanitizer_syscall_post_impl_fcntl(long res, long fd, long cmd, long arg);
+void __sanitizer_syscall_pre_impl_fcntl64(long fd, long cmd, long arg);
+void __sanitizer_syscall_post_impl_fcntl64(long res, long fd, long cmd,
+ long arg);
+void __sanitizer_syscall_pre_impl_pipe(long fildes);
+void __sanitizer_syscall_post_impl_pipe(long res, long fildes);
+void __sanitizer_syscall_pre_impl_pipe2(long fildes, long flags);
+void __sanitizer_syscall_post_impl_pipe2(long res, long fildes, long flags);
+void __sanitizer_syscall_pre_impl_dup(long fildes);
+void __sanitizer_syscall_post_impl_dup(long res, long fildes);
+void __sanitizer_syscall_pre_impl_dup2(long oldfd, long newfd);
+void __sanitizer_syscall_post_impl_dup2(long res, long oldfd, long newfd);
+void __sanitizer_syscall_pre_impl_dup3(long oldfd, long newfd, long flags);
+void __sanitizer_syscall_post_impl_dup3(long res, long oldfd, long newfd,
+ long flags);
+void __sanitizer_syscall_pre_impl_ioperm(long from, long num, long on);
+void __sanitizer_syscall_post_impl_ioperm(long res, long from, long num,
+ long on);
+void __sanitizer_syscall_pre_impl_ioctl(long fd, long cmd, long arg);
+void __sanitizer_syscall_post_impl_ioctl(long res, long fd, long cmd, long arg);
+void __sanitizer_syscall_pre_impl_flock(long fd, long cmd);
+void __sanitizer_syscall_post_impl_flock(long res, long fd, long cmd);
+void __sanitizer_syscall_pre_impl_io_setup(long nr_reqs, long ctx);
+void __sanitizer_syscall_post_impl_io_setup(long res, long nr_reqs, long ctx);
+void __sanitizer_syscall_pre_impl_io_destroy(long ctx);
+void __sanitizer_syscall_post_impl_io_destroy(long res, long ctx);
+void __sanitizer_syscall_pre_impl_io_getevents(long ctx_id, long min_nr,
+ long nr, long events,
+ long timeout);
+void __sanitizer_syscall_post_impl_io_getevents(long res, long ctx_id,
+ long min_nr, long nr,
+ long events, long timeout);
+void __sanitizer_syscall_pre_impl_io_submit(long ctx_id, long arg1, long arg2);
+void __sanitizer_syscall_post_impl_io_submit(long res, long ctx_id, long arg1,
+ long arg2);
+void __sanitizer_syscall_pre_impl_io_cancel(long ctx_id, long iocb,
+ long result);
+void __sanitizer_syscall_post_impl_io_cancel(long res, long ctx_id, long iocb,
+ long result);
+void __sanitizer_syscall_pre_impl_sendfile(long out_fd, long in_fd, long offset,
+ long count);
+void __sanitizer_syscall_post_impl_sendfile(long res, long out_fd, long in_fd,
+ long offset, long count);
+void __sanitizer_syscall_pre_impl_sendfile64(long out_fd, long in_fd,
+ long offset, long count);
+void __sanitizer_syscall_post_impl_sendfile64(long res, long out_fd, long in_fd,
+ long offset, long count);
+void __sanitizer_syscall_pre_impl_readlink(long path, long buf, long bufsiz);
+void __sanitizer_syscall_post_impl_readlink(long res, long path, long buf,
+ long bufsiz);
+void __sanitizer_syscall_pre_impl_creat(long pathname, long mode);
+void __sanitizer_syscall_post_impl_creat(long res, long pathname, long mode);
+void __sanitizer_syscall_pre_impl_open(long filename, long flags, long mode);
+void __sanitizer_syscall_post_impl_open(long res, long filename, long flags,
+ long mode);
+void __sanitizer_syscall_pre_impl_close(long fd);
+void __sanitizer_syscall_post_impl_close(long res, long fd);
+void __sanitizer_syscall_pre_impl_access(long filename, long mode);
+void __sanitizer_syscall_post_impl_access(long res, long filename, long mode);
+void __sanitizer_syscall_pre_impl_vhangup();
+void __sanitizer_syscall_post_impl_vhangup(long res);
+void __sanitizer_syscall_pre_impl_chown(long filename, long user, long group);
+void __sanitizer_syscall_post_impl_chown(long res, long filename, long user,
+ long group);
+void __sanitizer_syscall_pre_impl_lchown(long filename, long user, long group);
+void __sanitizer_syscall_post_impl_lchown(long res, long filename, long user,
+ long group);
+void __sanitizer_syscall_pre_impl_fchown(long fd, long user, long group);
+void __sanitizer_syscall_post_impl_fchown(long res, long fd, long user,
+ long group);
+void __sanitizer_syscall_pre_impl_chown16(long filename, long user, long group);
+void __sanitizer_syscall_post_impl_chown16(long res, long filename, long user,
+ long group);
+void __sanitizer_syscall_pre_impl_lchown16(long filename, long user,
+ long group);
+void __sanitizer_syscall_post_impl_lchown16(long res, long filename, long user,
+ long group);
+void __sanitizer_syscall_pre_impl_fchown16(long fd, long user, long group);
+void __sanitizer_syscall_post_impl_fchown16(long res, long fd, long user,
+ long group);
+void __sanitizer_syscall_pre_impl_setregid16(long rgid, long egid);
+void __sanitizer_syscall_post_impl_setregid16(long res, long rgid, long egid);
+void __sanitizer_syscall_pre_impl_setgid16(long gid);
+void __sanitizer_syscall_post_impl_setgid16(long res, long gid);
+void __sanitizer_syscall_pre_impl_setreuid16(long ruid, long euid);
+void __sanitizer_syscall_post_impl_setreuid16(long res, long ruid, long euid);
+void __sanitizer_syscall_pre_impl_setuid16(long uid);
+void __sanitizer_syscall_post_impl_setuid16(long res, long uid);
+void __sanitizer_syscall_pre_impl_setresuid16(long ruid, long euid, long suid);
+void __sanitizer_syscall_post_impl_setresuid16(long res, long ruid, long euid,
+ long suid);
+void __sanitizer_syscall_pre_impl_getresuid16(long ruid, long euid, long suid);
+void __sanitizer_syscall_post_impl_getresuid16(long res, long ruid, long euid,
+ long suid);
+void __sanitizer_syscall_pre_impl_setresgid16(long rgid, long egid, long sgid);
+void __sanitizer_syscall_post_impl_setresgid16(long res, long rgid, long egid,
+ long sgid);
+void __sanitizer_syscall_pre_impl_getresgid16(long rgid, long egid, long sgid);
+void __sanitizer_syscall_post_impl_getresgid16(long res, long rgid, long egid,
+ long sgid);
+void __sanitizer_syscall_pre_impl_setfsuid16(long uid);
+void __sanitizer_syscall_post_impl_setfsuid16(long res, long uid);
+void __sanitizer_syscall_pre_impl_setfsgid16(long gid);
+void __sanitizer_syscall_post_impl_setfsgid16(long res, long gid);
+void __sanitizer_syscall_pre_impl_getgroups16(long gidsetsize, long grouplist);
+void __sanitizer_syscall_post_impl_getgroups16(long res, long gidsetsize,
+ long grouplist);
+void __sanitizer_syscall_pre_impl_setgroups16(long gidsetsize, long grouplist);
+void __sanitizer_syscall_post_impl_setgroups16(long res, long gidsetsize,
+ long grouplist);
+void __sanitizer_syscall_pre_impl_getuid16();
+void __sanitizer_syscall_post_impl_getuid16(long res);
+void __sanitizer_syscall_pre_impl_geteuid16();
+void __sanitizer_syscall_post_impl_geteuid16(long res);
+void __sanitizer_syscall_pre_impl_getgid16();
+void __sanitizer_syscall_post_impl_getgid16(long res);
+void __sanitizer_syscall_pre_impl_getegid16();
+void __sanitizer_syscall_post_impl_getegid16(long res);
+void __sanitizer_syscall_pre_impl_utime(long filename, long times);
+void __sanitizer_syscall_post_impl_utime(long res, long filename, long times);
+void __sanitizer_syscall_pre_impl_utimes(long filename, long utimes);
+void __sanitizer_syscall_post_impl_utimes(long res, long filename, long utimes);
+void __sanitizer_syscall_pre_impl_lseek(long fd, long offset, long origin);
+void __sanitizer_syscall_post_impl_lseek(long res, long fd, long offset,
+ long origin);
+void __sanitizer_syscall_pre_impl_llseek(long fd, long offset_high,
+ long offset_low, long result,
+ long origin);
+void __sanitizer_syscall_post_impl_llseek(long res, long fd, long offset_high,
+ long offset_low, long result,
+ long origin);
+void __sanitizer_syscall_pre_impl_read(long fd, long buf, long count);
+void __sanitizer_syscall_post_impl_read(long res, long fd, long buf,
+ long count);
+void __sanitizer_syscall_pre_impl_readv(long fd, long vec, long vlen);
+void __sanitizer_syscall_post_impl_readv(long res, long fd, long vec,
+ long vlen);
+void __sanitizer_syscall_pre_impl_write(long fd, long buf, long count);
+void __sanitizer_syscall_post_impl_write(long res, long fd, long buf,
+ long count);
+void __sanitizer_syscall_pre_impl_writev(long fd, long vec, long vlen);
+void __sanitizer_syscall_post_impl_writev(long res, long fd, long vec,
+ long vlen);
+
+#ifdef _LP64
+void __sanitizer_syscall_pre_impl_pread64(long fd, long buf, long count,
+ long pos);
+void __sanitizer_syscall_post_impl_pread64(long res, long fd, long buf,
+ long count, long pos);
+void __sanitizer_syscall_pre_impl_pwrite64(long fd, long buf, long count,
+ long pos);
+void __sanitizer_syscall_post_impl_pwrite64(long res, long fd, long buf,
+ long count, long pos);
+#else
+void __sanitizer_syscall_pre_impl_pread64(long fd, long buf, long count,
+ long pos0, long pos1);
+void __sanitizer_syscall_post_impl_pread64(long res, long fd, long buf,
+ long count, long pos0, long pos1);
+void __sanitizer_syscall_pre_impl_pwrite64(long fd, long buf, long count,
+ long pos0, long pos1);
+void __sanitizer_syscall_post_impl_pwrite64(long res, long fd, long buf,
+ long count, long pos0, long pos1);
+#endif
+
+void __sanitizer_syscall_pre_impl_preadv(long fd, long vec, long vlen,
+ long pos_l, long pos_h);
+void __sanitizer_syscall_post_impl_preadv(long res, long fd, long vec,
+ long vlen, long pos_l, long pos_h);
+void __sanitizer_syscall_pre_impl_pwritev(long fd, long vec, long vlen,
+ long pos_l, long pos_h);
+void __sanitizer_syscall_post_impl_pwritev(long res, long fd, long vec,
+ long vlen, long pos_l, long pos_h);
+void __sanitizer_syscall_pre_impl_getcwd(long buf, long size);
+void __sanitizer_syscall_post_impl_getcwd(long res, long buf, long size);
+void __sanitizer_syscall_pre_impl_mkdir(long pathname, long mode);
+void __sanitizer_syscall_post_impl_mkdir(long res, long pathname, long mode);
+void __sanitizer_syscall_pre_impl_chdir(long filename);
+void __sanitizer_syscall_post_impl_chdir(long res, long filename);
+void __sanitizer_syscall_pre_impl_fchdir(long fd);
+void __sanitizer_syscall_post_impl_fchdir(long res, long fd);
+void __sanitizer_syscall_pre_impl_rmdir(long pathname);
+void __sanitizer_syscall_post_impl_rmdir(long res, long pathname);
+void __sanitizer_syscall_pre_impl_lookup_dcookie(long cookie64, long buf,
+ long len);
+void __sanitizer_syscall_post_impl_lookup_dcookie(long res, long cookie64,
+ long buf, long len);
+void __sanitizer_syscall_pre_impl_quotactl(long cmd, long special, long id,
+ long addr);
+void __sanitizer_syscall_post_impl_quotactl(long res, long cmd, long special,
+ long id, long addr);
+void __sanitizer_syscall_pre_impl_getdents(long fd, long dirent, long count);
+void __sanitizer_syscall_post_impl_getdents(long res, long fd, long dirent,
+ long count);
+void __sanitizer_syscall_pre_impl_getdents64(long fd, long dirent, long count);
+void __sanitizer_syscall_post_impl_getdents64(long res, long fd, long dirent,
+ long count);
+void __sanitizer_syscall_pre_impl_setsockopt(long fd, long level, long optname,
+ long optval, long optlen);
+void __sanitizer_syscall_post_impl_setsockopt(long res, long fd, long level,
+ long optname, long optval,
+ long optlen);
+void __sanitizer_syscall_pre_impl_getsockopt(long fd, long level, long optname,
+ long optval, long optlen);
+void __sanitizer_syscall_post_impl_getsockopt(long res, long fd, long level,
+ long optname, long optval,
+ long optlen);
+void __sanitizer_syscall_pre_impl_bind(long arg0, long arg1, long arg2);
+void __sanitizer_syscall_post_impl_bind(long res, long arg0, long arg1,
+ long arg2);
+void __sanitizer_syscall_pre_impl_connect(long arg0, long arg1, long arg2);
+void __sanitizer_syscall_post_impl_connect(long res, long arg0, long arg1,
+ long arg2);
+void __sanitizer_syscall_pre_impl_accept(long arg0, long arg1, long arg2);
+void __sanitizer_syscall_post_impl_accept(long res, long arg0, long arg1,
+ long arg2);
+void __sanitizer_syscall_pre_impl_accept4(long arg0, long arg1, long arg2,
+ long arg3);
+void __sanitizer_syscall_post_impl_accept4(long res, long arg0, long arg1,
+ long arg2, long arg3);
+void __sanitizer_syscall_pre_impl_getsockname(long arg0, long arg1, long arg2);
+void __sanitizer_syscall_post_impl_getsockname(long res, long arg0, long arg1,
+ long arg2);
+void __sanitizer_syscall_pre_impl_getpeername(long arg0, long arg1, long arg2);
+void __sanitizer_syscall_post_impl_getpeername(long res, long arg0, long arg1,
+ long arg2);
+void __sanitizer_syscall_pre_impl_send(long arg0, long arg1, long arg2,
+ long arg3);
+void __sanitizer_syscall_post_impl_send(long res, long arg0, long arg1,
+ long arg2, long arg3);
+void __sanitizer_syscall_pre_impl_sendto(long arg0, long arg1, long arg2,
+ long arg3, long arg4, long arg5);
+void __sanitizer_syscall_post_impl_sendto(long res, long arg0, long arg1,
+ long arg2, long arg3, long arg4,
+ long arg5);
+void __sanitizer_syscall_pre_impl_sendmsg(long fd, long msg, long flags);
+void __sanitizer_syscall_post_impl_sendmsg(long res, long fd, long msg,
+ long flags);
+void __sanitizer_syscall_pre_impl_sendmmsg(long fd, long msg, long vlen,
+ long flags);
+void __sanitizer_syscall_post_impl_sendmmsg(long res, long fd, long msg,
+ long vlen, long flags);
+void __sanitizer_syscall_pre_impl_recv(long arg0, long arg1, long arg2,
+ long arg3);
+void __sanitizer_syscall_post_impl_recv(long res, long arg0, long arg1,
+ long arg2, long arg3);
+void __sanitizer_syscall_pre_impl_recvfrom(long arg0, long arg1, long arg2,
+ long arg3, long arg4, long arg5);
+void __sanitizer_syscall_post_impl_recvfrom(long res, long arg0, long arg1,
+ long arg2, long arg3, long arg4,
+ long arg5);
+void __sanitizer_syscall_pre_impl_recvmsg(long fd, long msg, long flags);
+void __sanitizer_syscall_post_impl_recvmsg(long res, long fd, long msg,
+ long flags);
+void __sanitizer_syscall_pre_impl_recvmmsg(long fd, long msg, long vlen,
+ long flags, long timeout);
+void __sanitizer_syscall_post_impl_recvmmsg(long res, long fd, long msg,
+ long vlen, long flags,
+ long timeout);
+void __sanitizer_syscall_pre_impl_socket(long arg0, long arg1, long arg2);
+void __sanitizer_syscall_post_impl_socket(long res, long arg0, long arg1,
+ long arg2);
+void __sanitizer_syscall_pre_impl_socketpair(long arg0, long arg1, long arg2,
+ long arg3);
+void __sanitizer_syscall_post_impl_socketpair(long res, long arg0, long arg1,
+ long arg2, long arg3);
+void __sanitizer_syscall_pre_impl_socketcall(long call, long args);
+void __sanitizer_syscall_post_impl_socketcall(long res, long call, long args);
+void __sanitizer_syscall_pre_impl_listen(long arg0, long arg1);
+void __sanitizer_syscall_post_impl_listen(long res, long arg0, long arg1);
+void __sanitizer_syscall_pre_impl_poll(long ufds, long nfds, long timeout);
+void __sanitizer_syscall_post_impl_poll(long res, long ufds, long nfds,
+ long timeout);
+void __sanitizer_syscall_pre_impl_select(long n, long inp, long outp, long exp,
+ long tvp);
+void __sanitizer_syscall_post_impl_select(long res, long n, long inp, long outp,
+ long exp, long tvp);
+void __sanitizer_syscall_pre_impl_old_select(long arg);
+void __sanitizer_syscall_post_impl_old_select(long res, long arg);
+void __sanitizer_syscall_pre_impl_epoll_create(long size);
+void __sanitizer_syscall_post_impl_epoll_create(long res, long size);
+void __sanitizer_syscall_pre_impl_epoll_create1(long flags);
+void __sanitizer_syscall_post_impl_epoll_create1(long res, long flags);
+void __sanitizer_syscall_pre_impl_epoll_ctl(long epfd, long op, long fd,
+ long event);
+void __sanitizer_syscall_post_impl_epoll_ctl(long res, long epfd, long op,
+ long fd, long event);
+void __sanitizer_syscall_pre_impl_epoll_wait(long epfd, long events,
+ long maxevents, long timeout);
+void __sanitizer_syscall_post_impl_epoll_wait(long res, long epfd, long events,
+ long maxevents, long timeout);
+void __sanitizer_syscall_pre_impl_epoll_pwait(long epfd, long events,
+ long maxevents, long timeout,
+ long sigmask, long sigsetsize);
+void __sanitizer_syscall_post_impl_epoll_pwait(long res, long epfd, long events,
+ long maxevents, long timeout,
+ long sigmask, long sigsetsize);
+void __sanitizer_syscall_pre_impl_gethostname(long name, long len);
+void __sanitizer_syscall_post_impl_gethostname(long res, long name, long len);
+void __sanitizer_syscall_pre_impl_sethostname(long name, long len);
+void __sanitizer_syscall_post_impl_sethostname(long res, long name, long len);
+void __sanitizer_syscall_pre_impl_setdomainname(long name, long len);
+void __sanitizer_syscall_post_impl_setdomainname(long res, long name, long len);
+void __sanitizer_syscall_pre_impl_newuname(long name);
+void __sanitizer_syscall_post_impl_newuname(long res, long name);
+void __sanitizer_syscall_pre_impl_uname(long arg0);
+void __sanitizer_syscall_post_impl_uname(long res, long arg0);
+void __sanitizer_syscall_pre_impl_olduname(long arg0);
+void __sanitizer_syscall_post_impl_olduname(long res, long arg0);
+void __sanitizer_syscall_pre_impl_getrlimit(long resource, long rlim);
+void __sanitizer_syscall_post_impl_getrlimit(long res, long resource,
+ long rlim);
+void __sanitizer_syscall_pre_impl_old_getrlimit(long resource, long rlim);
+void __sanitizer_syscall_post_impl_old_getrlimit(long res, long resource,
+ long rlim);
+void __sanitizer_syscall_pre_impl_setrlimit(long resource, long rlim);
+void __sanitizer_syscall_post_impl_setrlimit(long res, long resource,
+ long rlim);
+void __sanitizer_syscall_pre_impl_prlimit64(long pid, long resource,
+ long new_rlim, long old_rlim);
+void __sanitizer_syscall_post_impl_prlimit64(long res, long pid, long resource,
+ long new_rlim, long old_rlim);
+void __sanitizer_syscall_pre_impl_getrusage(long who, long ru);
+void __sanitizer_syscall_post_impl_getrusage(long res, long who, long ru);
+void __sanitizer_syscall_pre_impl_umask(long mask);
+void __sanitizer_syscall_post_impl_umask(long res, long mask);
+void __sanitizer_syscall_pre_impl_msgget(long key, long msgflg);
+void __sanitizer_syscall_post_impl_msgget(long res, long key, long msgflg);
+void __sanitizer_syscall_pre_impl_msgsnd(long msqid, long msgp, long msgsz,
+ long msgflg);
+void __sanitizer_syscall_post_impl_msgsnd(long res, long msqid, long msgp,
+ long msgsz, long msgflg);
+void __sanitizer_syscall_pre_impl_msgrcv(long msqid, long msgp, long msgsz,
+ long msgtyp, long msgflg);
+void __sanitizer_syscall_post_impl_msgrcv(long res, long msqid, long msgp,
+ long msgsz, long msgtyp, long msgflg);
+void __sanitizer_syscall_pre_impl_msgctl(long msqid, long cmd, long buf);
+void __sanitizer_syscall_post_impl_msgctl(long res, long msqid, long cmd,
+ long buf);
+void __sanitizer_syscall_pre_impl_semget(long key, long nsems, long semflg);
+void __sanitizer_syscall_post_impl_semget(long res, long key, long nsems,
+ long semflg);
+void __sanitizer_syscall_pre_impl_semop(long semid, long sops, long nsops);
+void __sanitizer_syscall_post_impl_semop(long res, long semid, long sops,
+ long nsops);
+void __sanitizer_syscall_pre_impl_semctl(long semid, long semnum, long cmd,
+ long arg);
+void __sanitizer_syscall_post_impl_semctl(long res, long semid, long semnum,
+ long cmd, long arg);
+void __sanitizer_syscall_pre_impl_semtimedop(long semid, long sops, long nsops,
+ long timeout);
+void __sanitizer_syscall_post_impl_semtimedop(long res, long semid, long sops,
+ long nsops, long timeout);
+void __sanitizer_syscall_pre_impl_shmat(long shmid, long shmaddr, long shmflg);
+void __sanitizer_syscall_post_impl_shmat(long res, long shmid, long shmaddr,
+ long shmflg);
+void __sanitizer_syscall_pre_impl_shmget(long key, long size, long flag);
+void __sanitizer_syscall_post_impl_shmget(long res, long key, long size,
+ long flag);
+void __sanitizer_syscall_pre_impl_shmdt(long shmaddr);
+void __sanitizer_syscall_post_impl_shmdt(long res, long shmaddr);
+void __sanitizer_syscall_pre_impl_shmctl(long shmid, long cmd, long buf);
+void __sanitizer_syscall_post_impl_shmctl(long res, long shmid, long cmd,
+ long buf);
+void __sanitizer_syscall_pre_impl_ipc(long call, long first, long second,
+ long third, long ptr, long fifth);
+void __sanitizer_syscall_post_impl_ipc(long res, long call, long first,
+ long second, long third, long ptr,
+ long fifth);
+void __sanitizer_syscall_pre_impl_mq_open(long name, long oflag, long mode,
+ long attr);
+void __sanitizer_syscall_post_impl_mq_open(long res, long name, long oflag,
+ long mode, long attr);
+void __sanitizer_syscall_pre_impl_mq_unlink(long name);
+void __sanitizer_syscall_post_impl_mq_unlink(long res, long name);
+void __sanitizer_syscall_pre_impl_mq_timedsend(long mqdes, long msg_ptr,
+ long msg_len, long msg_prio,
+ long abs_timeout);
+void __sanitizer_syscall_post_impl_mq_timedsend(long res, long mqdes,
+ long msg_ptr, long msg_len,
+ long msg_prio,
+ long abs_timeout);
+void __sanitizer_syscall_pre_impl_mq_timedreceive(long mqdes, long msg_ptr,
+ long msg_len, long msg_prio,
+ long abs_timeout);
+void __sanitizer_syscall_post_impl_mq_timedreceive(long res, long mqdes,
+ long msg_ptr, long msg_len,
+ long msg_prio,
+ long abs_timeout);
+void __sanitizer_syscall_pre_impl_mq_notify(long mqdes, long notification);
+void __sanitizer_syscall_post_impl_mq_notify(long res, long mqdes,
+ long notification);
+void __sanitizer_syscall_pre_impl_mq_getsetattr(long mqdes, long mqstat,
+ long omqstat);
+void __sanitizer_syscall_post_impl_mq_getsetattr(long res, long mqdes,
+ long mqstat, long omqstat);
+void __sanitizer_syscall_pre_impl_pciconfig_iobase(long which, long bus,
+ long devfn);
+void __sanitizer_syscall_post_impl_pciconfig_iobase(long res, long which,
+ long bus, long devfn);
+void __sanitizer_syscall_pre_impl_pciconfig_read(long bus, long dfn, long off,
+ long len, long buf);
+void __sanitizer_syscall_post_impl_pciconfig_read(long res, long bus, long dfn,
+ long off, long len, long buf);
+void __sanitizer_syscall_pre_impl_pciconfig_write(long bus, long dfn, long off,
+ long len, long buf);
+void __sanitizer_syscall_post_impl_pciconfig_write(long res, long bus, long dfn,
+ long off, long len,
+ long buf);
+void __sanitizer_syscall_pre_impl_swapon(long specialfile, long swap_flags);
+void __sanitizer_syscall_post_impl_swapon(long res, long specialfile,
+ long swap_flags);
+void __sanitizer_syscall_pre_impl_swapoff(long specialfile);
+void __sanitizer_syscall_post_impl_swapoff(long res, long specialfile);
+void __sanitizer_syscall_pre_impl_sysctl(long args);
+void __sanitizer_syscall_post_impl_sysctl(long res, long args);
+void __sanitizer_syscall_pre_impl_sysinfo(long info);
+void __sanitizer_syscall_post_impl_sysinfo(long res, long info);
+void __sanitizer_syscall_pre_impl_sysfs(long option, long arg1, long arg2);
+void __sanitizer_syscall_post_impl_sysfs(long res, long option, long arg1,
+ long arg2);
+void __sanitizer_syscall_pre_impl_syslog(long type, long buf, long len);
+void __sanitizer_syscall_post_impl_syslog(long res, long type, long buf,
+ long len);
+void __sanitizer_syscall_pre_impl_uselib(long library);
+void __sanitizer_syscall_post_impl_uselib(long res, long library);
+void __sanitizer_syscall_pre_impl_ni_syscall();
+void __sanitizer_syscall_post_impl_ni_syscall(long res);
+void __sanitizer_syscall_pre_impl_ptrace(long request, long pid, long addr,
+ long data);
+void __sanitizer_syscall_post_impl_ptrace(long res, long request, long pid,
+ long addr, long data);
+void __sanitizer_syscall_pre_impl_add_key(long _type, long _description,
+ long _payload, long plen,
+ long destringid);
+void __sanitizer_syscall_post_impl_add_key(long res, long _type,
+ long _description, long _payload,
+ long plen, long destringid);
+void __sanitizer_syscall_pre_impl_request_key(long _type, long _description,
+ long _callout_info,
+ long destringid);
+void __sanitizer_syscall_post_impl_request_key(long res, long _type,
+ long _description,
+ long _callout_info,
+ long destringid);
+void __sanitizer_syscall_pre_impl_keyctl(long cmd, long arg2, long arg3,
+ long arg4, long arg5);
+void __sanitizer_syscall_post_impl_keyctl(long res, long cmd, long arg2,
+ long arg3, long arg4, long arg5);
+void __sanitizer_syscall_pre_impl_ioprio_set(long which, long who, long ioprio);
+void __sanitizer_syscall_post_impl_ioprio_set(long res, long which, long who,
+ long ioprio);
+void __sanitizer_syscall_pre_impl_ioprio_get(long which, long who);
+void __sanitizer_syscall_post_impl_ioprio_get(long res, long which, long who);
+void __sanitizer_syscall_pre_impl_set_mempolicy(long mode, long nmask,
+ long maxnode);
+void __sanitizer_syscall_post_impl_set_mempolicy(long res, long mode,
+ long nmask, long maxnode);
+void __sanitizer_syscall_pre_impl_migrate_pages(long pid, long maxnode,
+ long from, long to);
+void __sanitizer_syscall_post_impl_migrate_pages(long res, long pid,
+ long maxnode, long from,
+ long to);
+void __sanitizer_syscall_pre_impl_move_pages(long pid, long nr_pages,
+ long pages, long nodes,
+ long status, long flags);
+void __sanitizer_syscall_post_impl_move_pages(long res, long pid, long nr_pages,
+ long pages, long nodes,
+ long status, long flags);
+void __sanitizer_syscall_pre_impl_mbind(long start, long len, long mode,
+ long nmask, long maxnode, long flags);
+void __sanitizer_syscall_post_impl_mbind(long res, long start, long len,
+ long mode, long nmask, long maxnode,
+ long flags);
+void __sanitizer_syscall_pre_impl_get_mempolicy(long policy, long nmask,
+ long maxnode, long addr,
+ long flags);
+void __sanitizer_syscall_post_impl_get_mempolicy(long res, long policy,
+ long nmask, long maxnode,
+ long addr, long flags);
+void __sanitizer_syscall_pre_impl_inotify_init();
+void __sanitizer_syscall_post_impl_inotify_init(long res);
+void __sanitizer_syscall_pre_impl_inotify_init1(long flags);
+void __sanitizer_syscall_post_impl_inotify_init1(long res, long flags);
+void __sanitizer_syscall_pre_impl_inotify_add_watch(long fd, long path,
+ long mask);
+void __sanitizer_syscall_post_impl_inotify_add_watch(long res, long fd,
+ long path, long mask);
+void __sanitizer_syscall_pre_impl_inotify_rm_watch(long fd, long wd);
+void __sanitizer_syscall_post_impl_inotify_rm_watch(long res, long fd, long wd);
+void __sanitizer_syscall_pre_impl_spu_run(long fd, long unpc, long ustatus);
+void __sanitizer_syscall_post_impl_spu_run(long res, long fd, long unpc,
+ long ustatus);
+void __sanitizer_syscall_pre_impl_spu_create(long name, long flags, long mode,
+ long fd);
+void __sanitizer_syscall_post_impl_spu_create(long res, long name, long flags,
+ long mode, long fd);
+void __sanitizer_syscall_pre_impl_mknodat(long dfd, long filename, long mode,
+ long dev);
+void __sanitizer_syscall_post_impl_mknodat(long res, long dfd, long filename,
+ long mode, long dev);
+void __sanitizer_syscall_pre_impl_mkdirat(long dfd, long pathname, long mode);
+void __sanitizer_syscall_post_impl_mkdirat(long res, long dfd, long pathname,
+ long mode);
+void __sanitizer_syscall_pre_impl_unlinkat(long dfd, long pathname, long flag);
+void __sanitizer_syscall_post_impl_unlinkat(long res, long dfd, long pathname,
+ long flag);
+void __sanitizer_syscall_pre_impl_symlinkat(long oldname, long newdfd,
+ long newname);
+void __sanitizer_syscall_post_impl_symlinkat(long res, long oldname,
+ long newdfd, long newname);
+void __sanitizer_syscall_pre_impl_linkat(long olddfd, long oldname, long newdfd,
+ long newname, long flags);
+void __sanitizer_syscall_post_impl_linkat(long res, long olddfd, long oldname,
+ long newdfd, long newname,
+ long flags);
+void __sanitizer_syscall_pre_impl_renameat(long olddfd, long oldname,
+ long newdfd, long newname);
+void __sanitizer_syscall_post_impl_renameat(long res, long olddfd, long oldname,
+ long newdfd, long newname);
+void __sanitizer_syscall_pre_impl_futimesat(long dfd, long filename,
+ long utimes);
+void __sanitizer_syscall_post_impl_futimesat(long res, long dfd, long filename,
+ long utimes);
+void __sanitizer_syscall_pre_impl_faccessat(long dfd, long filename, long mode);
+void __sanitizer_syscall_post_impl_faccessat(long res, long dfd, long filename,
+ long mode);
+void __sanitizer_syscall_pre_impl_fchmodat(long dfd, long filename, long mode);
+void __sanitizer_syscall_post_impl_fchmodat(long res, long dfd, long filename,
+ long mode);
+void __sanitizer_syscall_pre_impl_fchownat(long dfd, long filename, long user,
+ long group, long flag);
+void __sanitizer_syscall_post_impl_fchownat(long res, long dfd, long filename,
+ long user, long group, long flag);
+void __sanitizer_syscall_pre_impl_openat(long dfd, long filename, long flags,
+ long mode);
+void __sanitizer_syscall_post_impl_openat(long res, long dfd, long filename,
+ long flags, long mode);
+void __sanitizer_syscall_pre_impl_newfstatat(long dfd, long filename,
+ long statbuf, long flag);
+void __sanitizer_syscall_post_impl_newfstatat(long res, long dfd, long filename,
+ long statbuf, long flag);
+void __sanitizer_syscall_pre_impl_fstatat64(long dfd, long filename,
+ long statbuf, long flag);
+void __sanitizer_syscall_post_impl_fstatat64(long res, long dfd, long filename,
+ long statbuf, long flag);
+void __sanitizer_syscall_pre_impl_readlinkat(long dfd, long path, long buf,
+ long bufsiz);
+void __sanitizer_syscall_post_impl_readlinkat(long res, long dfd, long path,
+ long buf, long bufsiz);
+void __sanitizer_syscall_pre_impl_utimensat(long dfd, long filename,
+ long utimes, long flags);
+void __sanitizer_syscall_post_impl_utimensat(long res, long dfd, long filename,
+ long utimes, long flags);
+void __sanitizer_syscall_pre_impl_unshare(long unshare_flags);
+void __sanitizer_syscall_post_impl_unshare(long res, long unshare_flags);
+void __sanitizer_syscall_pre_impl_splice(long fd_in, long off_in, long fd_out,
+ long off_out, long len, long flags);
+void __sanitizer_syscall_post_impl_splice(long res, long fd_in, long off_in,
+ long fd_out, long off_out, long len,
+ long flags);
+void __sanitizer_syscall_pre_impl_vmsplice(long fd, long iov, long nr_segs,
+ long flags);
+void __sanitizer_syscall_post_impl_vmsplice(long res, long fd, long iov,
+ long nr_segs, long flags);
+void __sanitizer_syscall_pre_impl_tee(long fdin, long fdout, long len,
+ long flags);
+void __sanitizer_syscall_post_impl_tee(long res, long fdin, long fdout,
+ long len, long flags);
+void __sanitizer_syscall_pre_impl_get_robust_list(long pid, long head_ptr,
+ long len_ptr);
+void __sanitizer_syscall_post_impl_get_robust_list(long res, long pid,
+ long head_ptr, long len_ptr);
+void __sanitizer_syscall_pre_impl_set_robust_list(long head, long len);
+void __sanitizer_syscall_post_impl_set_robust_list(long res, long head,
+ long len);
+void __sanitizer_syscall_pre_impl_getcpu(long cpu, long node, long cache);
+void __sanitizer_syscall_post_impl_getcpu(long res, long cpu, long node,
+ long cache);
+void __sanitizer_syscall_pre_impl_signalfd(long ufd, long user_mask,
+ long sizemask);
+void __sanitizer_syscall_post_impl_signalfd(long res, long ufd, long user_mask,
+ long sizemask);
+void __sanitizer_syscall_pre_impl_signalfd4(long ufd, long user_mask,
+ long sizemask, long flags);
+void __sanitizer_syscall_post_impl_signalfd4(long res, long ufd, long user_mask,
+ long sizemask, long flags);
+void __sanitizer_syscall_pre_impl_timerfd_create(long clockid, long flags);
+void __sanitizer_syscall_post_impl_timerfd_create(long res, long clockid,
+ long flags);
+void __sanitizer_syscall_pre_impl_timerfd_settime(long ufd, long flags,
+ long utmr, long otmr);
+void __sanitizer_syscall_post_impl_timerfd_settime(long res, long ufd,
+ long flags, long utmr,
+ long otmr);
+void __sanitizer_syscall_pre_impl_timerfd_gettime(long ufd, long otmr);
+void __sanitizer_syscall_post_impl_timerfd_gettime(long res, long ufd,
+ long otmr);
+void __sanitizer_syscall_pre_impl_eventfd(long count);
+void __sanitizer_syscall_post_impl_eventfd(long res, long count);
+void __sanitizer_syscall_pre_impl_eventfd2(long count, long flags);
+void __sanitizer_syscall_post_impl_eventfd2(long res, long count, long flags);
+void __sanitizer_syscall_pre_impl_old_readdir(long arg0, long arg1, long arg2);
+void __sanitizer_syscall_post_impl_old_readdir(long res, long arg0, long arg1,
+ long arg2);
+void __sanitizer_syscall_pre_impl_pselect6(long arg0, long arg1, long arg2,
+ long arg3, long arg4, long arg5);
+void __sanitizer_syscall_post_impl_pselect6(long res, long arg0, long arg1,
+ long arg2, long arg3, long arg4,
+ long arg5);
+void __sanitizer_syscall_pre_impl_ppoll(long arg0, long arg1, long arg2,
+ long arg3, long arg4);
+void __sanitizer_syscall_post_impl_ppoll(long res, long arg0, long arg1,
+ long arg2, long arg3, long arg4);
+void __sanitizer_syscall_pre_impl_fanotify_init(long flags, long event_f_flags);
+void __sanitizer_syscall_post_impl_fanotify_init(long res, long flags,
+ long event_f_flags);
+void __sanitizer_syscall_pre_impl_fanotify_mark(long fanotify_fd, long flags,
+ long mask, long fd,
+ long pathname);
+void __sanitizer_syscall_post_impl_fanotify_mark(long res, long fanotify_fd,
+ long flags, long mask, long fd,
+ long pathname);
+void __sanitizer_syscall_pre_impl_syncfs(long fd);
+void __sanitizer_syscall_post_impl_syncfs(long res, long fd);
+void __sanitizer_syscall_pre_impl_perf_event_open(long attr_uptr, long pid,
+ long cpu, long group_fd,
+ long flags);
+void __sanitizer_syscall_post_impl_perf_event_open(long res, long attr_uptr,
+ long pid, long cpu,
+ long group_fd, long flags);
+void __sanitizer_syscall_pre_impl_mmap_pgoff(long addr, long len, long prot,
+ long flags, long fd, long pgoff);
+void __sanitizer_syscall_post_impl_mmap_pgoff(long res, long addr, long len,
+ long prot, long flags, long fd,
+ long pgoff);
+void __sanitizer_syscall_pre_impl_old_mmap(long arg);
+void __sanitizer_syscall_post_impl_old_mmap(long res, long arg);
+void __sanitizer_syscall_pre_impl_name_to_handle_at(long dfd, long name,
+ long handle, long mnt_id,
+ long flag);
+void __sanitizer_syscall_post_impl_name_to_handle_at(long res, long dfd,
+ long name, long handle,
+ long mnt_id, long flag);
+void __sanitizer_syscall_pre_impl_open_by_handle_at(long mountdirfd,
+ long handle, long flags);
+void __sanitizer_syscall_post_impl_open_by_handle_at(long res, long mountdirfd,
+ long handle, long flags);
+void __sanitizer_syscall_pre_impl_setns(long fd, long nstype);
+void __sanitizer_syscall_post_impl_setns(long res, long fd, long nstype);
+void __sanitizer_syscall_pre_impl_process_vm_readv(long pid, long lvec,
+ long liovcnt, long rvec,
+ long riovcnt, long flags);
+void __sanitizer_syscall_post_impl_process_vm_readv(long res, long pid,
+ long lvec, long liovcnt,
+ long rvec, long riovcnt,
+ long flags);
+void __sanitizer_syscall_pre_impl_process_vm_writev(long pid, long lvec,
+ long liovcnt, long rvec,
+ long riovcnt, long flags);
+void __sanitizer_syscall_post_impl_process_vm_writev(long res, long pid,
+ long lvec, long liovcnt,
+ long rvec, long riovcnt,
+ long flags);
+void __sanitizer_syscall_pre_impl_fork();
+void __sanitizer_syscall_post_impl_fork(long res);
+void __sanitizer_syscall_pre_impl_vfork();
+void __sanitizer_syscall_post_impl_vfork(long res);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // SANITIZER_LINUX_SYSCALL_HOOKS_H
diff --git a/libsanitizer/include/sanitizer/lsan_interface.h b/libsanitizer/include/sanitizer/lsan_interface.h
new file mode 100644
index 00000000000..ec9c730eee3
--- /dev/null
+++ b/libsanitizer/include/sanitizer/lsan_interface.h
@@ -0,0 +1,50 @@
+//===-- sanitizer/lsan_interface.h ------------------------------*- C++ -*-===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of LeakSanitizer.
+//
+// Public interface header.
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_LSAN_INTERFACE_H
+#define SANITIZER_LSAN_INTERFACE_H
+
+#include <sanitizer/common_interface_defs.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ // Allocations made between calls to __lsan_disable() and __lsan_enable() will
+ // be treated as non-leaks. Disable/enable pairs may be nested.
+ void __lsan_disable();
+ void __lsan_enable();
+ // The heap object into which p points will be treated as a non-leak.
+ void __lsan_ignore_object(const void *p);
+ // The user may optionally provide this function to disallow leak checking
+ // for the program it is linked into (if the return value is non-zero). This
+ // function must be defined as returning a constant value; any behavior beyond
+ // that is unsupported.
+ int __lsan_is_turned_off();
+ // Calling this function makes LSan enter the leak checking phase immediately.
+ // Use this if normal end-of-process leak checking happens too late (e.g. if
+ // you have intentional memory leaks in your shutdown code). Calling this
+ // function overrides end-of-process leak checking; it must be called at
+ // most once per process. This function will terminate the process if there
+ // are memory leaks and the exit_code flag is non-zero.
+ void __lsan_do_leak_check();
+#ifdef __cplusplus
+} // extern "C"
+
+namespace __lsan {
+class ScopedDisabler {
+ public:
+ ScopedDisabler() { __lsan_disable(); }
+ ~ScopedDisabler() { __lsan_enable(); }
+};
+} // namespace __lsan
+#endif
+
+#endif // SANITIZER_LSAN_INTERFACE_H
diff --git a/libsanitizer/include/sanitizer/msan_interface.h b/libsanitizer/include/sanitizer/msan_interface.h
new file mode 100644
index 00000000000..f531cf347c9
--- /dev/null
+++ b/libsanitizer/include/sanitizer/msan_interface.h
@@ -0,0 +1,160 @@
+//===-- msan_interface.h --------------------------------------------------===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of MemorySanitizer.
+//
+// Public interface header.
+//===----------------------------------------------------------------------===//
+#ifndef MSAN_INTERFACE_H
+#define MSAN_INTERFACE_H
+
+#include <sanitizer/common_interface_defs.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if __has_feature(memory_sanitizer)
+ /* Returns a string describing a stack origin.
+ Return NULL if the origin is invalid, or is not a stack origin. */
+ const char *__msan_get_origin_descr_if_stack(uint32_t id);
+
+
+ /* Set raw origin for the memory range. */
+ void __msan_set_origin(const volatile void *a, size_t size, uint32_t origin);
+
+ /* Get raw origin for an address. */
+ uint32_t __msan_get_origin(const volatile void *a);
+
+ /* Returns non-zero if tracking origins. */
+ int __msan_get_track_origins();
+
+ /* Returns the origin id of the latest UMR in the calling thread. */
+ uint32_t __msan_get_umr_origin();
+
+ /* Make memory region fully initialized (without changing its contents). */
+ void __msan_unpoison(const volatile void *a, size_t size);
+
+ /* Make memory region fully uninitialized (without changing its contents). */
+ void __msan_poison(const volatile void *a, size_t size);
+
+ /* Make memory region partially uninitialized (without changing its contents).
+ */
+ void __msan_partial_poison(const volatile void *data, void *shadow,
+ size_t size);
+
+ /* Returns the offset of the first (at least partially) poisoned byte in the
+ memory range, or -1 if the whole range is good. */
+ intptr_t __msan_test_shadow(const volatile void *x, size_t size);
+
+ /* Set exit code when error(s) were detected.
+ Value of 0 means don't change the program exit code. */
+ void __msan_set_exit_code(int exit_code);
+
+ /* For testing:
+ __msan_set_expect_umr(1);
+ ... some buggy code ...
+ __msan_set_expect_umr(0);
+ The last line will verify that a UMR happened. */
+ void __msan_set_expect_umr(int expect_umr);
+
+ /* Change the value of keep_going flag. Non-zero value means don't terminate
+ program execution when an error is detected. This will not affect error in
+ modules that were compiled without the corresponding compiler flag. */
+ void __msan_set_keep_going(int keep_going);
+
+ /* Print shadow and origin for the memory range to stdout in a human-readable
+ format. */
+ void __msan_print_shadow(const volatile void *x, size_t size);
+
+ /* Print current function arguments shadow and origin to stdout in a
+ human-readable format. */
+ void __msan_print_param_shadow();
+
+ /* Returns true if running under a dynamic tool (DynamoRio-based). */
+ int __msan_has_dynamic_component();
+
+ /* Tell MSan about newly allocated memory (ex.: custom allocator).
+ Memory will be marked uninitialized, with origin at the call site. */
+ void __msan_allocated_memory(const volatile void* data, size_t size);
+
+ /* This function may be optionally provided by user and should return
+ a string containing Msan runtime options. See msan_flags.h for details. */
+ const char* __msan_default_options();
+
+
+ /***********************************/
+ /* Allocator statistics interface. */
+
+ /* Returns the estimated number of bytes that will be reserved by allocator
+ for request of "size" bytes. If Msan allocator can't allocate that much
+ memory, returns the maximal possible allocation size, otherwise returns
+ "size". */
+ size_t __msan_get_estimated_allocated_size(size_t size);
+
+ /* Returns true if p was returned by the Msan allocator and
+ is not yet freed. */
+ int __msan_get_ownership(const volatile void *p);
+
+ /* Returns the number of bytes reserved for the pointer p.
+ Requires (get_ownership(p) == true) or (p == 0). */
+ size_t __msan_get_allocated_size(const volatile void *p);
+
+ /* Number of bytes, allocated and not yet freed by the application. */
+ size_t __msan_get_current_allocated_bytes();
+
+ /* Number of bytes, mmaped by msan allocator to fulfill allocation requests.
+ Generally, for request of X bytes, allocator can reserve and add to free
+ lists a large number of chunks of size X to use them for future requests.
+ All these chunks count toward the heap size. Currently, allocator never
+ releases memory to OS (instead, it just puts freed chunks to free
+ lists). */
+ size_t __msan_get_heap_size();
+
+ /* Number of bytes, mmaped by msan allocator, which can be used to fulfill
+ allocation requests. When a user program frees memory chunk, it can first
+ fall into quarantine and will count toward __msan_get_free_bytes()
+ later. */
+ size_t __msan_get_free_bytes();
+
+ /* Number of bytes in unmapped pages, that are released to OS. Currently,
+ always returns 0. */
+ size_t __msan_get_unmapped_bytes();
+
+ /* Malloc hooks that may be optionally provided by user.
+ __msan_malloc_hook(ptr, size) is called immediately after
+ allocation of "size" bytes, which returned "ptr".
+ __msan_free_hook(ptr) is called immediately before
+ deallocation of "ptr". */
+ void __msan_malloc_hook(const volatile void *ptr, size_t size);
+ void __msan_free_hook(const volatile void *ptr);
+
+#else // __has_feature(memory_sanitizer)
+
+#define __msan_get_origin_descr_if_stack(id) ((const char*)0)
+#define __msan_set_origin(a, size, origin)
+#define __msan_get_origin(a) ((uint32_t)-1)
+#define __msan_get_track_origins() (0)
+#define __msan_get_umr_origin() ((uint32_t)-1)
+#define __msan_unpoison(a, size)
+#define __msan_poison(a, size)
+#define __msan_partial_poison(data, shadow, size)
+#define __msan_test_shadow(x, size) ((intptr_t)-1)
+#define __msan_set_exit_code(exit_code)
+#define __msan_set_expect_umr(expect_umr)
+#define __msan_print_shadow(x, size)
+#define __msan_print_param_shadow()
+#define __msan_has_dynamic_component() (0)
+#define __msan_allocated_memory(data, size)
+
+#endif // __has_feature(memory_sanitizer)
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif
diff --git a/libsanitizer/interception/interception.h b/libsanitizer/interception/interception.h
index c4c5026c7ed..71740c5c403 100644
--- a/libsanitizer/interception/interception.h
+++ b/libsanitizer/interception/interception.h
@@ -21,27 +21,20 @@
// These typedefs should be used only in the interceptor definitions to replace
// the standard system types (e.g. SSIZE_T instead of ssize_t)
-typedef __sanitizer::uptr SIZE_T;
-typedef __sanitizer::sptr SSIZE_T;
-typedef __sanitizer::sptr PTRDIFF_T;
-typedef __sanitizer::s64 INTMAX_T;
-// WARNING: OFF_T may be different from OS type off_t, depending on the value of
-// _FILE_OFFSET_BITS. This definition of OFF_T matches the ABI of system calls
-// like pread and mmap, as opposed to pread64 and mmap64.
-// Mac and Linux/x86-64 are special.
-#if defined(__APPLE__) || (defined(__linux__) && defined(__x86_64__))
-typedef __sanitizer::u64 OFF_T;
-#else
-typedef __sanitizer::uptr OFF_T;
-#endif
-typedef __sanitizer::u64 OFF64_T;
+typedef __sanitizer::uptr SIZE_T;
+typedef __sanitizer::sptr SSIZE_T;
+typedef __sanitizer::sptr PTRDIFF_T;
+typedef __sanitizer::s64 INTMAX_T;
+typedef __sanitizer::OFF_T OFF_T;
+typedef __sanitizer::OFF64_T OFF64_T;
// How to add an interceptor:
// Suppose you need to wrap/replace system function (generally, from libc):
// int foo(const char *bar, double baz);
// You'll need to:
// 1) define INTERCEPTOR(int, foo, const char *bar, double baz) { ... } in
-// your source file.
+// your source file. See the notes below for cases when
+// INTERCEPTOR_WITH_SUFFIX(...) should be used instead.
// 2) Call "INTERCEPT_FUNCTION(foo)" prior to the first call of "foo".
// INTERCEPT_FUNCTION(foo) evaluates to "true" iff the function was
// intercepted successfully.
@@ -55,15 +48,20 @@ typedef __sanitizer::u64 OFF64_T;
// 3b) add DECLARE_REAL_AND_INTERCEPTOR(int, foo, const char*, double)
// to a header file.
-// Notes: 1. Things may not work properly if macro INTERCEPT(...) {...} or
+// Notes: 1. Things may not work properly if macro INTERCEPTOR(...) {...} or
// DECLARE_REAL(...) are located inside namespaces.
-// 2. On Mac you can also use: "OVERRIDE_FUNCTION(foo, zoo);" to
+// 2. On Mac you can also use: "OVERRIDE_FUNCTION(foo, zoo)" to
// effectively redirect calls from "foo" to "zoo". In this case
// you aren't required to implement
// INTERCEPTOR(int, foo, const char *bar, double baz) {...}
// but instead you'll have to add
-// DEFINE_REAL(int, foo, const char *bar, double baz) in your
+// DECLARE_REAL(int, foo, const char *bar, double baz) in your
// source file (to define a pointer to overriden function).
+// 3. Some Mac functions have symbol variants discriminated by
+// additional suffixes, e.g. _$UNIX2003 (see
+// https://developer.apple.com/library/mac/#releasenotes/Darwin/SymbolVariantsRelNotes/index.html
+// for more details). To intercept such functions you need to use the
+// INTERCEPTOR_WITH_SUFFIX(...) macro.
// How it works:
// To replace system functions on Linux we just need to declare functions
@@ -73,6 +71,7 @@ typedef __sanitizer::u64 OFF64_T;
// we intercept. To resolve this we declare our interceptors with __interceptor_
// prefix, and then make actual interceptors weak aliases to __interceptor_
// functions.
+//
// This is not so on Mac OS, where the two-level namespace makes
// our replacement functions invisible to other libraries. This may be overcomed
// using the DYLD_FORCE_FLAT_NAMESPACE, but some errors loading the shared
@@ -82,12 +81,43 @@ typedef __sanitizer::u64 OFF64_T;
// preloaded before an executable using DYLD_INSERT_LIBRARIES, it routes all
// the calls to interposed functions done through stubs to the wrapper
// functions.
+// As it's decided at compile time which functions are to be intercepted on Mac,
+// INTERCEPT_FUNCTION() is effectively a no-op on this system.
#if defined(__APPLE__)
+#include <sys/cdefs.h> // For __DARWIN_ALIAS_C().
+
+// Just a pair of pointers.
+struct interpose_substitution {
+ const uptr replacement;
+ const uptr original;
+};
+
+// For a function foo() create a global pair of pointers { wrap_foo, foo } in
+// the __DATA,__interpose section.
+// As a result all the calls to foo() will be routed to wrap_foo() at runtime.
+#define INTERPOSER(func_name) __attribute__((used)) \
+const interpose_substitution substitution_##func_name[] \
+ __attribute__((section("__DATA, __interpose"))) = { \
+ { reinterpret_cast<const uptr>(WRAP(func_name)), \
+ reinterpret_cast<const uptr>(func_name) } \
+}
+
+// For a function foo() and a wrapper function bar() create a global pair
+// of pointers { bar, foo } in the __DATA,__interpose section.
+// As a result all the calls to foo() will be routed to bar() at runtime.
+#define INTERPOSER_2(func_name, wrapper_name) __attribute__((used)) \
+const interpose_substitution substitution_##func_name[] \
+ __attribute__((section("__DATA, __interpose"))) = { \
+ { reinterpret_cast<const uptr>(wrapper_name), \
+ reinterpret_cast<const uptr>(func_name) } \
+}
+
# define WRAP(x) wrap_##x
# define WRAPPER_NAME(x) "wrap_"#x
# define INTERCEPTOR_ATTRIBUTE
# define DECLARE_WRAPPER(ret_type, func, ...)
+
#elif defined(_WIN32)
# if defined(_DLL) // DLL CRT
# define WRAP(x) x
@@ -98,7 +128,10 @@ typedef __sanitizer::u64 OFF64_T;
# define WRAPPER_NAME(x) "wrap_"#x
# define INTERCEPTOR_ATTRIBUTE
# endif
-# define DECLARE_WRAPPER(ret_type, func, ...)
+# define DECLARE_WRAPPER(ret_type, func, ...) \
+ extern "C" ret_type func(__VA_ARGS__);
+# define DECLARE_WRAPPER_WINAPI(ret_type, func, ...) \
+ extern "C" __declspec(dllimport) ret_type __stdcall func(__VA_ARGS__);
#else
# define WRAP(x) __interceptor_ ## x
# define WRAPPER_NAME(x) "__interceptor_" #x
@@ -142,6 +175,7 @@ typedef __sanitizer::u64 OFF64_T;
# define DEFINE_REAL(ret_type, func, ...)
#endif
+#if !defined(__APPLE__)
#define INTERCEPTOR(ret_type, func, ...) \
DEFINE_REAL(ret_type, func, __VA_ARGS__) \
DECLARE_WRAPPER(ret_type, func, __VA_ARGS__) \
@@ -149,13 +183,36 @@ typedef __sanitizer::u64 OFF64_T;
INTERCEPTOR_ATTRIBUTE \
ret_type WRAP(func)(__VA_ARGS__)
+// We don't need INTERCEPTOR_WITH_SUFFIX on non-Darwin for now.
+#define INTERCEPTOR_WITH_SUFFIX(ret_type, func, ...) \
+ INTERCEPTOR(ret_type, func, __VA_ARGS__)
+
+#else // __APPLE__
+
+#define INTERCEPTOR_ZZZ(suffix, ret_type, func, ...) \
+ extern "C" ret_type func(__VA_ARGS__) suffix; \
+ extern "C" ret_type WRAP(func)(__VA_ARGS__); \
+ INTERPOSER(func); \
+ extern "C" INTERCEPTOR_ATTRIBUTE ret_type WRAP(func)(__VA_ARGS__)
+
+#define INTERCEPTOR(ret_type, func, ...) \
+ INTERCEPTOR_ZZZ(/*no symbol variants*/, ret_type, func, __VA_ARGS__)
+
+#define INTERCEPTOR_WITH_SUFFIX(ret_type, func, ...) \
+ INTERCEPTOR_ZZZ(__DARWIN_ALIAS_C(func), ret_type, func, __VA_ARGS__)
+
+// Override |overridee| with |overrider|.
+#define OVERRIDE_FUNCTION(overridee, overrider) \
+ INTERPOSER_2(overridee, WRAP(overrider))
+#endif
+
#if defined(_WIN32)
# define INTERCEPTOR_WINAPI(ret_type, func, ...) \
typedef ret_type (__stdcall *FUNC_TYPE(func))(__VA_ARGS__); \
namespace __interception { \
FUNC_TYPE(func) PTR_TO_REAL(func); \
} \
- DECLARE_WRAPPER(ret_type, func, __VA_ARGS__) \
+ DECLARE_WRAPPER_WINAPI(ret_type, func, __VA_ARGS__) \
extern "C" \
INTERCEPTOR_ATTRIBUTE \
ret_type __stdcall WRAP(func)(__VA_ARGS__)
@@ -181,8 +238,6 @@ typedef unsigned long uptr; // NOLINT
# define INTERCEPT_FUNCTION(func) INTERCEPT_FUNCTION_LINUX(func)
#elif defined(__APPLE__)
# include "interception_mac.h"
-# define OVERRIDE_FUNCTION(old_func, new_func) \
- OVERRIDE_FUNCTION_MAC(old_func, new_func)
# define INTERCEPT_FUNCTION(func) INTERCEPT_FUNCTION_MAC(func)
#else // defined(_WIN32)
# include "interception_win.h"
diff --git a/libsanitizer/interception/interception_linux.cc b/libsanitizer/interception/interception_linux.cc
index 4929a7fce49..0a8df474ab4 100644
--- a/libsanitizer/interception/interception_linux.cc
+++ b/libsanitizer/interception/interception_linux.cc
@@ -13,7 +13,6 @@
#ifdef __linux__
#include "interception.h"
-#include <stddef.h> // for NULL
#include <dlfcn.h> // for dlsym
namespace __interception {
@@ -22,6 +21,13 @@ bool GetRealFunctionAddress(const char *func_name, uptr *func_addr,
*func_addr = (uptr)dlsym(RTLD_NEXT, func_name);
return real == wrapper;
}
+
+#if !defined(__ANDROID__) // android does not have dlvsym
+void *GetFuncAddrVer(const char *func_name, const char *ver) {
+ return dlvsym(RTLD_NEXT, func_name, ver);
+}
+#endif // !defined(__ANDROID__)
+
} // namespace __interception
diff --git a/libsanitizer/interception/interception_linux.h b/libsanitizer/interception/interception_linux.h
index 7940ef257c8..fbbfecbe037 100644
--- a/libsanitizer/interception/interception_linux.h
+++ b/libsanitizer/interception/interception_linux.h
@@ -23,6 +23,7 @@ namespace __interception {
// returns true if a function with the given name was found.
bool GetRealFunctionAddress(const char *func_name, uptr *func_addr,
uptr real, uptr wrapper);
+void *GetFuncAddrVer(const char *func_name, const char *ver);
} // namespace __interception
#define INTERCEPT_FUNCTION_LINUX(func) \
@@ -31,5 +32,11 @@ bool GetRealFunctionAddress(const char *func_name, uptr *func_addr,
(::__interception::uptr)&(func), \
(::__interception::uptr)&WRAP(func))
+#if !defined(__ANDROID__) // android does not have dlvsym
+#define INTERCEPT_FUNCTION_VER(func, symver) \
+ ::__interception::real_##func = (func##_f)(unsigned long) \
+ ::__interception::GetFuncAddrVer(#func, #symver)
+#endif // !defined(__ANDROID__)
+
#endif // INTERCEPTION_LINUX_H
#endif // __linux__
diff --git a/libsanitizer/lsan/Makefile.am b/libsanitizer/lsan/Makefile.am
new file mode 100644
index 00000000000..5c8726fb35b
--- /dev/null
+++ b/libsanitizer/lsan/Makefile.am
@@ -0,0 +1,60 @@
+AM_CPPFLAGS = -I $(top_srcdir)/include -I $(top_srcdir)
+
+# May be used by toolexeclibdir.
+gcc_version := $(shell cat $(top_srcdir)/../gcc/BASE-VER)
+
+DEFS = -D_GNU_SOURCE -D_DEBUG -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS
+AM_CXXFLAGS = -Wall -W -Wno-unused-parameter -Wwrite-strings -pedantic -Wno-long-long -fPIC -fno-builtin -fno-exceptions -fomit-frame-pointer -funwind-tables -fvisibility=hidden -Wno-variadic-macros
+AM_CXXFLAGS += $(LIBSTDCXX_RAW_CXX_CXXFLAGS)
+ACLOCAL_AMFLAGS = -I m4
+
+noinst_LTLIBRARIES = libsanitizer_lsan.la
+
+sanitizer_lsan_files = \
+ lsan_common.cc \
+ lsan_common_linux.cc
+
+libsanitizer_lsan_la_SOURCES = $(sanitizer_lsan_files)
+
+# Work around what appears to be a GNU make bug handling MAKEFLAGS
+# values defined in terms of make variables, as is the case for CC and
+# friends when we are called from the top level Makefile.
+AM_MAKEFLAGS = \
+ "AR_FLAGS=$(AR_FLAGS)" \
+ "CC_FOR_BUILD=$(CC_FOR_BUILD)" \
+ "CFLAGS=$(CFLAGS)" \
+ "CXXFLAGS=$(CXXFLAGS)" \
+ "CFLAGS_FOR_BUILD=$(CFLAGS_FOR_BUILD)" \
+ "CFLAGS_FOR_TARGET=$(CFLAGS_FOR_TARGET)" \
+ "INSTALL=$(INSTALL)" \
+ "INSTALL_DATA=$(INSTALL_DATA)" \
+ "INSTALL_PROGRAM=$(INSTALL_PROGRAM)" \
+ "INSTALL_SCRIPT=$(INSTALL_SCRIPT)" \
+ "JC1FLAGS=$(JC1FLAGS)" \
+ "LDFLAGS=$(LDFLAGS)" \
+ "LIBCFLAGS=$(LIBCFLAGS)" \
+ "LIBCFLAGS_FOR_TARGET=$(LIBCFLAGS_FOR_TARGET)" \
+ "MAKE=$(MAKE)" \
+ "MAKEINFO=$(MAKEINFO) $(MAKEINFOFLAGS)" \
+ "PICFLAG=$(PICFLAG)" \
+ "PICFLAG_FOR_TARGET=$(PICFLAG_FOR_TARGET)" \
+ "SHELL=$(SHELL)" \
+ "RUNTESTFLAGS=$(RUNTESTFLAGS)" \
+ "exec_prefix=$(exec_prefix)" \
+ "infodir=$(infodir)" \
+ "libdir=$(libdir)" \
+ "prefix=$(prefix)" \
+ "includedir=$(includedir)" \
+ "AR=$(AR)" \
+ "AS=$(AS)" \
+ "LD=$(LD)" \
+ "LIBCFLAGS=$(LIBCFLAGS)" \
+ "NM=$(NM)" \
+ "PICFLAG=$(PICFLAG)" \
+ "RANLIB=$(RANLIB)" \
+ "DESTDIR=$(DESTDIR)"
+
+MAKEOVERRIDES=
+
+## ################################################################
+
diff --git a/libsanitizer/lsan/Makefile.in b/libsanitizer/lsan/Makefile.in
new file mode 100644
index 00000000000..e01f65b8663
--- /dev/null
+++ b/libsanitizer/lsan/Makefile.in
@@ -0,0 +1,514 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in 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.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = lsan
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \
+ $(top_srcdir)/../config/depstand.m4 \
+ $(top_srcdir)/../config/lead-dot.m4 \
+ $(top_srcdir)/../config/libstdc++-raw-cxx.m4 \
+ $(top_srcdir)/../config/multi.m4 \
+ $(top_srcdir)/../config/override.m4 \
+ $(top_srcdir)/../ltoptions.m4 $(top_srcdir)/../ltsugar.m4 \
+ $(top_srcdir)/../ltversion.m4 $(top_srcdir)/../lt~obsolete.m4 \
+ $(top_srcdir)/acinclude.m4 $(top_srcdir)/../libtool.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/../mkinstalldirs
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+libsanitizer_lsan_la_LIBADD =
+am__objects_1 = lsan_common.lo lsan_common_linux.lo
+am_libsanitizer_lsan_la_OBJECTS = $(am__objects_1)
+libsanitizer_lsan_la_OBJECTS = $(am_libsanitizer_lsan_la_OBJECTS)
+DEFAULT_INCLUDES = -I.@am__isrc@
+depcomp = $(SHELL) $(top_srcdir)/../depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libsanitizer_lsan_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCAS = @CCAS@
+CCASDEPMODE = @CCASDEPMODE@
+CCASFLAGS = @CCASFLAGS@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = -D_GNU_SOURCE -D_DEBUG -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS
+DEPDIR = @DEPDIR@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBSTDCXX_RAW_CXX_CXXFLAGS = @LIBSTDCXX_RAW_CXX_CXXFLAGS@
+LIBSTDCXX_RAW_CXX_LDFLAGS = @LIBSTDCXX_RAW_CXX_LDFLAGS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+enable_shared = @enable_shared@
+enable_static = @enable_static@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+multi_basedir = @multi_basedir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_noncanonical = @target_noncanonical@
+target_os = @target_os@
+target_vendor = @target_vendor@
+toolexecdir = @toolexecdir@
+toolexeclibdir = @toolexeclibdir@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AM_CPPFLAGS = -I $(top_srcdir)/include -I $(top_srcdir)
+
+# May be used by toolexeclibdir.
+gcc_version := $(shell cat $(top_srcdir)/../gcc/BASE-VER)
+AM_CXXFLAGS = -Wall -W -Wno-unused-parameter -Wwrite-strings -pedantic \
+ -Wno-long-long -fPIC -fno-builtin -fno-exceptions \
+ -fomit-frame-pointer -funwind-tables -fvisibility=hidden \
+ -Wno-variadic-macros $(LIBSTDCXX_RAW_CXX_CXXFLAGS)
+ACLOCAL_AMFLAGS = -I m4
+noinst_LTLIBRARIES = libsanitizer_lsan.la
+sanitizer_lsan_files = \
+ lsan_common.cc \
+ lsan_common_linux.cc
+
+libsanitizer_lsan_la_SOURCES = $(sanitizer_lsan_files)
+
+# Work around what appears to be a GNU make bug handling MAKEFLAGS
+# values defined in terms of make variables, as is the case for CC and
+# friends when we are called from the top level Makefile.
+AM_MAKEFLAGS = \
+ "AR_FLAGS=$(AR_FLAGS)" \
+ "CC_FOR_BUILD=$(CC_FOR_BUILD)" \
+ "CFLAGS=$(CFLAGS)" \
+ "CXXFLAGS=$(CXXFLAGS)" \
+ "CFLAGS_FOR_BUILD=$(CFLAGS_FOR_BUILD)" \
+ "CFLAGS_FOR_TARGET=$(CFLAGS_FOR_TARGET)" \
+ "INSTALL=$(INSTALL)" \
+ "INSTALL_DATA=$(INSTALL_DATA)" \
+ "INSTALL_PROGRAM=$(INSTALL_PROGRAM)" \
+ "INSTALL_SCRIPT=$(INSTALL_SCRIPT)" \
+ "JC1FLAGS=$(JC1FLAGS)" \
+ "LDFLAGS=$(LDFLAGS)" \
+ "LIBCFLAGS=$(LIBCFLAGS)" \
+ "LIBCFLAGS_FOR_TARGET=$(LIBCFLAGS_FOR_TARGET)" \
+ "MAKE=$(MAKE)" \
+ "MAKEINFO=$(MAKEINFO) $(MAKEINFOFLAGS)" \
+ "PICFLAG=$(PICFLAG)" \
+ "PICFLAG_FOR_TARGET=$(PICFLAG_FOR_TARGET)" \
+ "SHELL=$(SHELL)" \
+ "RUNTESTFLAGS=$(RUNTESTFLAGS)" \
+ "exec_prefix=$(exec_prefix)" \
+ "infodir=$(infodir)" \
+ "libdir=$(libdir)" \
+ "prefix=$(prefix)" \
+ "includedir=$(includedir)" \
+ "AR=$(AR)" \
+ "AS=$(AS)" \
+ "LD=$(LD)" \
+ "LIBCFLAGS=$(LIBCFLAGS)" \
+ "NM=$(NM)" \
+ "PICFLAG=$(PICFLAG)" \
+ "RANLIB=$(RANLIB)" \
+ "DESTDIR=$(DESTDIR)"
+
+MAKEOVERRIDES =
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .cc .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lsan/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign lsan/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libsanitizer_lsan.la: $(libsanitizer_lsan_la_OBJECTS) $(libsanitizer_lsan_la_DEPENDENCIES)
+ $(CXXLINK) $(libsanitizer_lsan_la_OBJECTS) $(libsanitizer_lsan_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lsan_common.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lsan_common_linux.Plo@am__quote@
+
+.cc.o:
+@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
+
+.cc.obj:
+@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cc.lo:
+@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags dvi dvi-am html html-am info info-am install \
+ install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/libmudflap/libtool-version b/libsanitizer/lsan/libtool-version
index 204fdd2d8e5..204fdd2d8e5 100644
--- a/libmudflap/libtool-version
+++ b/libsanitizer/lsan/libtool-version
diff --git a/libsanitizer/lsan/lsan.cc b/libsanitizer/lsan/lsan.cc
new file mode 100644
index 00000000000..500da50622c
--- /dev/null
+++ b/libsanitizer/lsan/lsan.cc
@@ -0,0 +1,63 @@
+//=-- lsan.cc -------------------------------------------------------------===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of LeakSanitizer.
+// Standalone LSan RTL.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lsan.h"
+
+#include "sanitizer_common/sanitizer_flags.h"
+#include "sanitizer_common/sanitizer_stacktrace.h"
+#include "lsan_allocator.h"
+#include "lsan_common.h"
+#include "lsan_thread.h"
+
+namespace __lsan {
+
+static void InitializeCommonFlags() {
+ CommonFlags *cf = common_flags();
+ cf->external_symbolizer_path = GetEnv("LSAN_SYMBOLIZER_PATH");
+ cf->symbolize = true;
+ cf->strip_path_prefix = "";
+ cf->fast_unwind_on_malloc = true;
+ cf->malloc_context_size = 30;
+ cf->detect_leaks = true;
+ cf->leak_check_at_exit = true;
+
+ ParseCommonFlagsFromString(GetEnv("LSAN_OPTIONS"));
+}
+
+void Init() {
+ static bool inited;
+ if (inited)
+ return;
+ inited = true;
+ SanitizerToolName = "LeakSanitizer";
+ InitializeCommonFlags();
+ InitializeAllocator();
+ InitTlsSize();
+ InitializeInterceptors();
+ InitializeThreadRegistry();
+ u32 tid = ThreadCreate(0, 0, true);
+ CHECK_EQ(tid, 0);
+ ThreadStart(tid, GetTid());
+ SetCurrentThread(tid);
+
+ // Start symbolizer process if necessary.
+ if (common_flags()->symbolize) {
+ getSymbolizer()
+ ->InitializeExternal(common_flags()->external_symbolizer_path);
+ }
+
+ InitCommonLsan();
+ if (common_flags()->detect_leaks && common_flags()->leak_check_at_exit)
+ Atexit(DoLeakCheck);
+}
+
+} // namespace __lsan
diff --git a/libsanitizer/lsan/lsan.h b/libsanitizer/lsan/lsan.h
new file mode 100644
index 00000000000..18ff5da6281
--- /dev/null
+++ b/libsanitizer/lsan/lsan.h
@@ -0,0 +1,21 @@
+//=-- lsan.h --------------------------------------------------------------===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of LeakSanitizer.
+// Private header for standalone LSan RTL.
+//
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_flags.h"
+#include "sanitizer_common/sanitizer_stacktrace.h"
+
+namespace __lsan {
+
+void Init();
+void InitializeInterceptors();
+
+} // namespace __lsan
diff --git a/libsanitizer/lsan/lsan_allocator.cc b/libsanitizer/lsan/lsan_allocator.cc
new file mode 100644
index 00000000000..66af603e656
--- /dev/null
+++ b/libsanitizer/lsan/lsan_allocator.cc
@@ -0,0 +1,191 @@
+//=-- lsan_allocator.cc ---------------------------------------------------===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of LeakSanitizer.
+// See lsan_allocator.h for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lsan_allocator.h"
+
+#include "sanitizer_common/sanitizer_allocator.h"
+#include "sanitizer_common/sanitizer_internal_defs.h"
+#include "sanitizer_common/sanitizer_stackdepot.h"
+#include "sanitizer_common/sanitizer_stacktrace.h"
+#include "lsan_common.h"
+
+namespace __lsan {
+
+static const uptr kMaxAllowedMallocSize = 8UL << 30;
+static const uptr kAllocatorSpace = 0x600000000000ULL;
+static const uptr kAllocatorSize = 0x40000000000ULL; // 4T.
+
+struct ChunkMetadata {
+ bool allocated : 8; // Must be first.
+ ChunkTag tag : 2;
+ uptr requested_size : 54;
+ u32 stack_trace_id;
+};
+
+typedef SizeClassAllocator64<kAllocatorSpace, kAllocatorSize,
+ sizeof(ChunkMetadata), CompactSizeClassMap> PrimaryAllocator;
+typedef SizeClassAllocatorLocalCache<PrimaryAllocator> AllocatorCache;
+typedef LargeMmapAllocator<> SecondaryAllocator;
+typedef CombinedAllocator<PrimaryAllocator, AllocatorCache,
+ SecondaryAllocator> Allocator;
+
+static Allocator allocator;
+static THREADLOCAL AllocatorCache cache;
+
+void InitializeAllocator() {
+ allocator.Init();
+}
+
+void AllocatorThreadFinish() {
+ allocator.SwallowCache(&cache);
+}
+
+static ChunkMetadata *Metadata(void *p) {
+ return reinterpret_cast<ChunkMetadata *>(allocator.GetMetaData(p));
+}
+
+static void RegisterAllocation(const StackTrace &stack, void *p, uptr size) {
+ if (!p) return;
+ ChunkMetadata *m = Metadata(p);
+ CHECK(m);
+ m->tag = DisabledInThisThread() ? kIgnored : kDirectlyLeaked;
+ m->stack_trace_id = StackDepotPut(stack.trace, stack.size);
+ m->requested_size = size;
+ atomic_store(reinterpret_cast<atomic_uint8_t *>(m), 1, memory_order_relaxed);
+}
+
+static void RegisterDeallocation(void *p) {
+ if (!p) return;
+ ChunkMetadata *m = Metadata(p);
+ CHECK(m);
+ atomic_store(reinterpret_cast<atomic_uint8_t *>(m), 0, memory_order_relaxed);
+}
+
+void *Allocate(const StackTrace &stack, uptr size, uptr alignment,
+ bool cleared) {
+ if (size == 0)
+ size = 1;
+ if (size > kMaxAllowedMallocSize) {
+ Report("WARNING: LeakSanitizer failed to allocate %zu bytes\n", size);
+ return 0;
+ }
+ void *p = allocator.Allocate(&cache, size, alignment, cleared);
+ RegisterAllocation(stack, p, size);
+ return p;
+}
+
+void Deallocate(void *p) {
+ RegisterDeallocation(p);
+ allocator.Deallocate(&cache, p);
+}
+
+void *Reallocate(const StackTrace &stack, void *p, uptr new_size,
+ uptr alignment) {
+ RegisterDeallocation(p);
+ if (new_size > kMaxAllowedMallocSize) {
+ Report("WARNING: LeakSanitizer failed to allocate %zu bytes\n", new_size);
+ allocator.Deallocate(&cache, p);
+ return 0;
+ }
+ p = allocator.Reallocate(&cache, p, new_size, alignment);
+ RegisterAllocation(stack, p, new_size);
+ return p;
+}
+
+void GetAllocatorCacheRange(uptr *begin, uptr *end) {
+ *begin = (uptr)&cache;
+ *end = *begin + sizeof(cache);
+}
+
+uptr GetMallocUsableSize(void *p) {
+ ChunkMetadata *m = Metadata(p);
+ if (!m) return 0;
+ return m->requested_size;
+}
+
+///// Interface to the common LSan module. /////
+
+void LockAllocator() {
+ allocator.ForceLock();
+}
+
+void UnlockAllocator() {
+ allocator.ForceUnlock();
+}
+
+void GetAllocatorGlobalRange(uptr *begin, uptr *end) {
+ *begin = (uptr)&allocator;
+ *end = *begin + sizeof(allocator);
+}
+
+uptr PointsIntoChunk(void* p) {
+ uptr addr = reinterpret_cast<uptr>(p);
+ uptr chunk = reinterpret_cast<uptr>(allocator.GetBlockBeginFastLocked(p));
+ if (!chunk) return 0;
+ // LargeMmapAllocator considers pointers to the meta-region of a chunk to be
+ // valid, but we don't want that.
+ if (addr < chunk) return 0;
+ ChunkMetadata *m = Metadata(reinterpret_cast<void *>(chunk));
+ CHECK(m);
+ if (m->allocated && addr < chunk + m->requested_size)
+ return chunk;
+ return 0;
+}
+
+uptr GetUserBegin(uptr chunk) {
+ return chunk;
+}
+
+LsanMetadata::LsanMetadata(uptr chunk) {
+ metadata_ = Metadata(reinterpret_cast<void *>(chunk));
+ CHECK(metadata_);
+}
+
+bool LsanMetadata::allocated() const {
+ return reinterpret_cast<ChunkMetadata *>(metadata_)->allocated;
+}
+
+ChunkTag LsanMetadata::tag() const {
+ return reinterpret_cast<ChunkMetadata *>(metadata_)->tag;
+}
+
+void LsanMetadata::set_tag(ChunkTag value) {
+ reinterpret_cast<ChunkMetadata *>(metadata_)->tag = value;
+}
+
+uptr LsanMetadata::requested_size() const {
+ return reinterpret_cast<ChunkMetadata *>(metadata_)->requested_size;
+}
+
+u32 LsanMetadata::stack_trace_id() const {
+ return reinterpret_cast<ChunkMetadata *>(metadata_)->stack_trace_id;
+}
+
+void ForEachChunk(ForEachChunkCallback callback, void *arg) {
+ allocator.ForEachChunk(callback, arg);
+}
+
+IgnoreObjectResult IgnoreObjectLocked(const void *p) {
+ void *chunk = allocator.GetBlockBegin(p);
+ if (!chunk || p < chunk) return kIgnoreObjectInvalid;
+ ChunkMetadata *m = Metadata(chunk);
+ CHECK(m);
+ if (m->allocated && (uptr)p < (uptr)chunk + m->requested_size) {
+ if (m->tag == kIgnored)
+ return kIgnoreObjectAlreadyIgnored;
+ m->tag = kIgnored;
+ return kIgnoreObjectSuccess;
+ } else {
+ return kIgnoreObjectInvalid;
+ }
+}
+} // namespace __lsan
diff --git a/libsanitizer/lsan/lsan_allocator.h b/libsanitizer/lsan/lsan_allocator.h
new file mode 100644
index 00000000000..61ea86572ef
--- /dev/null
+++ b/libsanitizer/lsan/lsan_allocator.h
@@ -0,0 +1,37 @@
+//=-- lsan_allocator.h ----------------------------------------------------===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of LeakSanitizer.
+// Allocator for standalone LSan.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LSAN_ALLOCATOR_H
+#define LSAN_ALLOCATOR_H
+
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_internal_defs.h"
+
+namespace __lsan {
+
+void *Allocate(const StackTrace &stack, uptr size, uptr alignment,
+ bool cleared);
+void Deallocate(void *p);
+void *Reallocate(const StackTrace &stack, void *p, uptr new_size,
+ uptr alignment);
+uptr GetMallocUsableSize(void *p);
+
+template<typename Callable>
+void ForEachChunk(const Callable &callback);
+
+void GetAllocatorCacheRange(uptr *begin, uptr *end);
+void AllocatorThreadFinish();
+void InitializeAllocator();
+
+} // namespace __lsan
+
+#endif // LSAN_ALLOCATOR_H
diff --git a/libsanitizer/lsan/lsan_common.cc b/libsanitizer/lsan/lsan_common.cc
new file mode 100644
index 00000000000..ce82430f48b
--- /dev/null
+++ b/libsanitizer/lsan/lsan_common.cc
@@ -0,0 +1,577 @@
+//=-- lsan_common.cc ------------------------------------------------------===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of LeakSanitizer.
+// Implementation of common leak checking functionality.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lsan_common.h"
+
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_flags.h"
+#include "sanitizer_common/sanitizer_placement_new.h"
+#include "sanitizer_common/sanitizer_stackdepot.h"
+#include "sanitizer_common/sanitizer_stacktrace.h"
+#include "sanitizer_common/sanitizer_stoptheworld.h"
+#include "sanitizer_common/sanitizer_suppressions.h"
+#include "sanitizer_common/sanitizer_report_decorator.h"
+
+#if CAN_SANITIZE_LEAKS
+namespace __lsan {
+
+// This mutex is used to prevent races between DoLeakCheck and IgnoreObject.
+BlockingMutex global_mutex(LINKER_INITIALIZED);
+
+THREADLOCAL int disable_counter;
+bool DisabledInThisThread() { return disable_counter > 0; }
+
+Flags lsan_flags;
+
+static void InitializeFlags() {
+ Flags *f = flags();
+ // Default values.
+ f->report_objects = false;
+ f->resolution = 0;
+ f->max_leaks = 0;
+ f->exitcode = 23;
+ f->suppressions="";
+ f->use_registers = true;
+ f->use_globals = true;
+ f->use_stacks = true;
+ f->use_tls = true;
+ f->use_unaligned = false;
+ f->verbosity = 0;
+ f->log_pointers = false;
+ f->log_threads = false;
+
+ const char *options = GetEnv("LSAN_OPTIONS");
+ if (options) {
+ ParseFlag(options, &f->use_registers, "use_registers");
+ ParseFlag(options, &f->use_globals, "use_globals");
+ ParseFlag(options, &f->use_stacks, "use_stacks");
+ ParseFlag(options, &f->use_tls, "use_tls");
+ ParseFlag(options, &f->use_unaligned, "use_unaligned");
+ ParseFlag(options, &f->report_objects, "report_objects");
+ ParseFlag(options, &f->resolution, "resolution");
+ CHECK_GE(&f->resolution, 0);
+ ParseFlag(options, &f->max_leaks, "max_leaks");
+ CHECK_GE(&f->max_leaks, 0);
+ ParseFlag(options, &f->verbosity, "verbosity");
+ ParseFlag(options, &f->log_pointers, "log_pointers");
+ ParseFlag(options, &f->log_threads, "log_threads");
+ ParseFlag(options, &f->exitcode, "exitcode");
+ ParseFlag(options, &f->suppressions, "suppressions");
+ }
+}
+
+SuppressionContext *suppression_ctx;
+
+void InitializeSuppressions() {
+ CHECK(!suppression_ctx);
+ ALIGNED(64) static char placeholder_[sizeof(SuppressionContext)];
+ suppression_ctx = new(placeholder_) SuppressionContext;
+ char *suppressions_from_file;
+ uptr buffer_size;
+ if (ReadFileToBuffer(flags()->suppressions, &suppressions_from_file,
+ &buffer_size, 1 << 26 /* max_len */))
+ suppression_ctx->Parse(suppressions_from_file);
+ if (flags()->suppressions[0] && !buffer_size) {
+ Printf("LeakSanitizer: failed to read suppressions file '%s'\n",
+ flags()->suppressions);
+ Die();
+ }
+ if (&__lsan_default_suppressions)
+ suppression_ctx->Parse(__lsan_default_suppressions());
+}
+
+void InitCommonLsan() {
+ InitializeFlags();
+ InitializeSuppressions();
+ InitializePlatformSpecificModules();
+}
+
+class Decorator: private __sanitizer::AnsiColorDecorator {
+ public:
+ Decorator() : __sanitizer::AnsiColorDecorator(PrintsToTtyCached()) { }
+ const char *Error() { return Red(); }
+ const char *Leak() { return Blue(); }
+ const char *End() { return Default(); }
+};
+
+static inline bool CanBeAHeapPointer(uptr p) {
+ // Since our heap is located in mmap-ed memory, we can assume a sensible lower
+ // bound on heap addresses.
+ const uptr kMinAddress = 4 * 4096;
+ if (p < kMinAddress) return false;
+#ifdef __x86_64__
+ // Accept only canonical form user-space addresses.
+ return ((p >> 47) == 0);
+#else
+ return true;
+#endif
+}
+
+// Scans the memory range, looking for byte patterns that point into allocator
+// chunks. Marks those chunks with |tag| and adds them to |frontier|.
+// There are two usage modes for this function: finding reachable or ignored
+// chunks (|tag| = kReachable or kIgnored) and finding indirectly leaked chunks
+// (|tag| = kIndirectlyLeaked). In the second case, there's no flood fill,
+// so |frontier| = 0.
+void ScanRangeForPointers(uptr begin, uptr end,
+ Frontier *frontier,
+ const char *region_type, ChunkTag tag) {
+ const uptr alignment = flags()->pointer_alignment();
+ if (flags()->log_pointers)
+ Report("Scanning %s range %p-%p.\n", region_type, begin, end);
+ uptr pp = begin;
+ if (pp % alignment)
+ pp = pp + alignment - pp % alignment;
+ for (; pp + sizeof(void *) <= end; pp += alignment) { // NOLINT
+ void *p = *reinterpret_cast<void **>(pp);
+ if (!CanBeAHeapPointer(reinterpret_cast<uptr>(p))) continue;
+ uptr chunk = PointsIntoChunk(p);
+ if (!chunk) continue;
+ LsanMetadata m(chunk);
+ // Reachable beats ignored beats leaked.
+ if (m.tag() == kReachable) continue;
+ if (m.tag() == kIgnored && tag != kReachable) continue;
+ m.set_tag(tag);
+ if (flags()->log_pointers)
+ Report("%p: found %p pointing into chunk %p-%p of size %zu.\n", pp, p,
+ chunk, chunk + m.requested_size(), m.requested_size());
+ if (frontier)
+ frontier->push_back(chunk);
+ }
+}
+
+// Scans thread data (stacks and TLS) for heap pointers.
+static void ProcessThreads(SuspendedThreadsList const &suspended_threads,
+ Frontier *frontier) {
+ InternalScopedBuffer<uptr> registers(SuspendedThreadsList::RegisterCount());
+ uptr registers_begin = reinterpret_cast<uptr>(registers.data());
+ uptr registers_end = registers_begin + registers.size();
+ for (uptr i = 0; i < suspended_threads.thread_count(); i++) {
+ uptr os_id = static_cast<uptr>(suspended_threads.GetThreadID(i));
+ if (flags()->log_threads) Report("Processing thread %d.\n", os_id);
+ uptr stack_begin, stack_end, tls_begin, tls_end, cache_begin, cache_end;
+ bool thread_found = GetThreadRangesLocked(os_id, &stack_begin, &stack_end,
+ &tls_begin, &tls_end,
+ &cache_begin, &cache_end);
+ if (!thread_found) {
+ // If a thread can't be found in the thread registry, it's probably in the
+ // process of destruction. Log this event and move on.
+ if (flags()->log_threads)
+ Report("Thread %d not found in registry.\n", os_id);
+ continue;
+ }
+ uptr sp;
+ bool have_registers =
+ (suspended_threads.GetRegistersAndSP(i, registers.data(), &sp) == 0);
+ if (!have_registers) {
+ Report("Unable to get registers from thread %d.\n");
+ // If unable to get SP, consider the entire stack to be reachable.
+ sp = stack_begin;
+ }
+
+ if (flags()->use_registers && have_registers)
+ ScanRangeForPointers(registers_begin, registers_end, frontier,
+ "REGISTERS", kReachable);
+
+ if (flags()->use_stacks) {
+ if (flags()->log_threads)
+ Report("Stack at %p-%p, SP = %p.\n", stack_begin, stack_end, sp);
+ if (sp < stack_begin || sp >= stack_end) {
+ // SP is outside the recorded stack range (e.g. the thread is running a
+ // signal handler on alternate stack). Again, consider the entire stack
+ // range to be reachable.
+ if (flags()->log_threads)
+ Report("WARNING: stack pointer not in stack range.\n");
+ } else {
+ // Shrink the stack range to ignore out-of-scope values.
+ stack_begin = sp;
+ }
+ ScanRangeForPointers(stack_begin, stack_end, frontier, "STACK",
+ kReachable);
+ }
+
+ if (flags()->use_tls) {
+ if (flags()->log_threads) Report("TLS at %p-%p.\n", tls_begin, tls_end);
+ if (cache_begin == cache_end) {
+ ScanRangeForPointers(tls_begin, tls_end, frontier, "TLS", kReachable);
+ } else {
+ // Because LSan should not be loaded with dlopen(), we can assume
+ // that allocator cache will be part of static TLS image.
+ CHECK_LE(tls_begin, cache_begin);
+ CHECK_GE(tls_end, cache_end);
+ if (tls_begin < cache_begin)
+ ScanRangeForPointers(tls_begin, cache_begin, frontier, "TLS",
+ kReachable);
+ if (tls_end > cache_end)
+ ScanRangeForPointers(cache_end, tls_end, frontier, "TLS", kReachable);
+ }
+ }
+ }
+}
+
+static void FloodFillTag(Frontier *frontier, ChunkTag tag) {
+ while (frontier->size()) {
+ uptr next_chunk = frontier->back();
+ frontier->pop_back();
+ LsanMetadata m(next_chunk);
+ ScanRangeForPointers(next_chunk, next_chunk + m.requested_size(), frontier,
+ "HEAP", tag);
+ }
+}
+
+// ForEachChunk callback. If the chunk is marked as leaked, marks all chunks
+// which are reachable from it as indirectly leaked.
+static void MarkIndirectlyLeakedCb(uptr chunk, void *arg) {
+ chunk = GetUserBegin(chunk);
+ LsanMetadata m(chunk);
+ if (m.allocated() && m.tag() != kReachable) {
+ ScanRangeForPointers(chunk, chunk + m.requested_size(),
+ /* frontier */ 0, "HEAP", kIndirectlyLeaked);
+ }
+}
+
+// ForEachChunk callback. If chunk is marked as ignored, adds its address to
+// frontier.
+static void CollectIgnoredCb(uptr chunk, void *arg) {
+ CHECK(arg);
+ chunk = GetUserBegin(chunk);
+ LsanMetadata m(chunk);
+ if (m.allocated() && m.tag() == kIgnored)
+ reinterpret_cast<Frontier *>(arg)->push_back(chunk);
+}
+
+// Sets the appropriate tag on each chunk.
+static void ClassifyAllChunks(SuspendedThreadsList const &suspended_threads) {
+ // Holds the flood fill frontier.
+ Frontier frontier(GetPageSizeCached());
+
+ if (flags()->use_globals)
+ ProcessGlobalRegions(&frontier);
+ ProcessThreads(suspended_threads, &frontier);
+ FloodFillTag(&frontier, kReachable);
+ // The check here is relatively expensive, so we do this in a separate flood
+ // fill. That way we can skip the check for chunks that are reachable
+ // otherwise.
+ ProcessPlatformSpecificAllocations(&frontier);
+ FloodFillTag(&frontier, kReachable);
+
+ if (flags()->log_pointers)
+ Report("Scanning ignored chunks.\n");
+ CHECK_EQ(0, frontier.size());
+ ForEachChunk(CollectIgnoredCb, &frontier);
+ FloodFillTag(&frontier, kIgnored);
+
+ // Iterate over leaked chunks and mark those that are reachable from other
+ // leaked chunks.
+ if (flags()->log_pointers)
+ Report("Scanning leaked chunks.\n");
+ ForEachChunk(MarkIndirectlyLeakedCb, 0 /* arg */);
+}
+
+static void PrintStackTraceById(u32 stack_trace_id) {
+ CHECK(stack_trace_id);
+ uptr size = 0;
+ const uptr *trace = StackDepotGet(stack_trace_id, &size);
+ StackTrace::PrintStack(trace, size, common_flags()->symbolize,
+ common_flags()->strip_path_prefix, 0);
+}
+
+// ForEachChunk callback. Aggregates unreachable chunks into a LeakReport.
+static void CollectLeaksCb(uptr chunk, void *arg) {
+ CHECK(arg);
+ LeakReport *leak_report = reinterpret_cast<LeakReport *>(arg);
+ chunk = GetUserBegin(chunk);
+ LsanMetadata m(chunk);
+ if (!m.allocated()) return;
+ if (m.tag() == kDirectlyLeaked || m.tag() == kIndirectlyLeaked) {
+ uptr resolution = flags()->resolution;
+ if (resolution > 0) {
+ uptr size = 0;
+ const uptr *trace = StackDepotGet(m.stack_trace_id(), &size);
+ size = Min(size, resolution);
+ leak_report->Add(StackDepotPut(trace, size), m.requested_size(), m.tag());
+ } else {
+ leak_report->Add(m.stack_trace_id(), m.requested_size(), m.tag());
+ }
+ }
+}
+
+// ForEachChunkCallback. Prints addresses of unreachable chunks.
+static void PrintLeakedCb(uptr chunk, void *arg) {
+ chunk = GetUserBegin(chunk);
+ LsanMetadata m(chunk);
+ if (!m.allocated()) return;
+ if (m.tag() == kDirectlyLeaked || m.tag() == kIndirectlyLeaked) {
+ Printf("%s leaked %zu byte object at %p.\n",
+ m.tag() == kDirectlyLeaked ? "Directly" : "Indirectly",
+ m.requested_size(), chunk);
+ }
+}
+
+static void PrintMatchedSuppressions() {
+ InternalMmapVector<Suppression *> matched(1);
+ suppression_ctx->GetMatched(&matched);
+ if (!matched.size())
+ return;
+ const char *line = "-----------------------------------------------------";
+ Printf("%s\n", line);
+ Printf("Suppressions used:\n");
+ Printf(" count bytes template\n");
+ for (uptr i = 0; i < matched.size(); i++)
+ Printf("%7zu %10zu %s\n", static_cast<uptr>(matched[i]->hit_count),
+ matched[i]->weight, matched[i]->templ);
+ Printf("%s\n\n", line);
+}
+
+static void PrintLeaked() {
+ Printf("\n");
+ Printf("Reporting individual objects:\n");
+ ForEachChunk(PrintLeakedCb, 0 /* arg */);
+}
+
+struct DoLeakCheckParam {
+ bool success;
+ LeakReport leak_report;
+};
+
+static void DoLeakCheckCallback(const SuspendedThreadsList &suspended_threads,
+ void *arg) {
+ DoLeakCheckParam *param = reinterpret_cast<DoLeakCheckParam *>(arg);
+ CHECK(param);
+ CHECK(!param->success);
+ CHECK(param->leak_report.IsEmpty());
+ ClassifyAllChunks(suspended_threads);
+ ForEachChunk(CollectLeaksCb, &param->leak_report);
+ if (!param->leak_report.IsEmpty() && flags()->report_objects)
+ PrintLeaked();
+ param->success = true;
+}
+
+void DoLeakCheck() {
+ EnsureMainThreadIDIsCorrect();
+ BlockingMutexLock l(&global_mutex);
+ static bool already_done;
+ if (already_done) return;
+ already_done = true;
+ if (&__lsan_is_turned_off && __lsan_is_turned_off())
+ return;
+
+ DoLeakCheckParam param;
+ param.success = false;
+ LockThreadRegistry();
+ LockAllocator();
+ StopTheWorld(DoLeakCheckCallback, &param);
+ UnlockAllocator();
+ UnlockThreadRegistry();
+
+ if (!param.success) {
+ Report("LeakSanitizer has encountered a fatal error.\n");
+ Die();
+ }
+ uptr have_unsuppressed = param.leak_report.ApplySuppressions();
+ if (have_unsuppressed) {
+ Decorator d;
+ Printf("\n"
+ "================================================================="
+ "\n");
+ Printf("%s", d.Error());
+ Report("ERROR: LeakSanitizer: detected memory leaks\n");
+ Printf("%s", d.End());
+ param.leak_report.PrintLargest(flags()->max_leaks);
+ }
+ if (have_unsuppressed || (flags()->verbosity >= 1)) {
+ PrintMatchedSuppressions();
+ param.leak_report.PrintSummary();
+ }
+ if (have_unsuppressed && flags()->exitcode)
+ internal__exit(flags()->exitcode);
+}
+
+static Suppression *GetSuppressionForAddr(uptr addr) {
+ static const uptr kMaxAddrFrames = 16;
+ InternalScopedBuffer<AddressInfo> addr_frames(kMaxAddrFrames);
+ for (uptr i = 0; i < kMaxAddrFrames; i++) new (&addr_frames[i]) AddressInfo();
+ uptr addr_frames_num =
+ getSymbolizer()->SymbolizeCode(addr, addr_frames.data(), kMaxAddrFrames);
+ for (uptr i = 0; i < addr_frames_num; i++) {
+ Suppression* s;
+ if (suppression_ctx->Match(addr_frames[i].function, SuppressionLeak, &s) ||
+ suppression_ctx->Match(addr_frames[i].file, SuppressionLeak, &s) ||
+ suppression_ctx->Match(addr_frames[i].module, SuppressionLeak, &s))
+ return s;
+ }
+ return 0;
+}
+
+static Suppression *GetSuppressionForStack(u32 stack_trace_id) {
+ uptr size = 0;
+ const uptr *trace = StackDepotGet(stack_trace_id, &size);
+ for (uptr i = 0; i < size; i++) {
+ Suppression *s =
+ GetSuppressionForAddr(StackTrace::GetPreviousInstructionPc(trace[i]));
+ if (s) return s;
+ }
+ return 0;
+}
+
+///// LeakReport implementation. /////
+
+// A hard limit on the number of distinct leaks, to avoid quadratic complexity
+// in LeakReport::Add(). We don't expect to ever see this many leaks in
+// real-world applications.
+// FIXME: Get rid of this limit by changing the implementation of LeakReport to
+// use a hash table.
+const uptr kMaxLeaksConsidered = 5000;
+
+void LeakReport::Add(u32 stack_trace_id, uptr leaked_size, ChunkTag tag) {
+ CHECK(tag == kDirectlyLeaked || tag == kIndirectlyLeaked);
+ bool is_directly_leaked = (tag == kDirectlyLeaked);
+ for (uptr i = 0; i < leaks_.size(); i++)
+ if (leaks_[i].stack_trace_id == stack_trace_id &&
+ leaks_[i].is_directly_leaked == is_directly_leaked) {
+ leaks_[i].hit_count++;
+ leaks_[i].total_size += leaked_size;
+ return;
+ }
+ if (leaks_.size() == kMaxLeaksConsidered) return;
+ Leak leak = { /* hit_count */ 1, leaked_size, stack_trace_id,
+ is_directly_leaked, /* is_suppressed */ false };
+ leaks_.push_back(leak);
+}
+
+static bool LeakComparator(const Leak &leak1, const Leak &leak2) {
+ if (leak1.is_directly_leaked == leak2.is_directly_leaked)
+ return leak1.total_size > leak2.total_size;
+ else
+ return leak1.is_directly_leaked;
+}
+
+void LeakReport::PrintLargest(uptr num_leaks_to_print) {
+ CHECK(leaks_.size() <= kMaxLeaksConsidered);
+ Printf("\n");
+ if (leaks_.size() == kMaxLeaksConsidered)
+ Printf("Too many leaks! Only the first %zu leaks encountered will be "
+ "reported.\n",
+ kMaxLeaksConsidered);
+
+ uptr unsuppressed_count = 0;
+ for (uptr i = 0; i < leaks_.size(); i++)
+ if (!leaks_[i].is_suppressed) unsuppressed_count++;
+ if (num_leaks_to_print > 0 && num_leaks_to_print < unsuppressed_count)
+ Printf("The %zu largest leak(s):\n", num_leaks_to_print);
+ InternalSort(&leaks_, leaks_.size(), LeakComparator);
+ uptr leaks_printed = 0;
+ Decorator d;
+ for (uptr i = 0; i < leaks_.size(); i++) {
+ if (leaks_[i].is_suppressed) continue;
+ Printf("%s", d.Leak());
+ Printf("%s leak of %zu byte(s) in %zu object(s) allocated from:\n",
+ leaks_[i].is_directly_leaked ? "Direct" : "Indirect",
+ leaks_[i].total_size, leaks_[i].hit_count);
+ Printf("%s", d.End());
+ PrintStackTraceById(leaks_[i].stack_trace_id);
+ Printf("\n");
+ leaks_printed++;
+ if (leaks_printed == num_leaks_to_print) break;
+ }
+ if (leaks_printed < unsuppressed_count) {
+ uptr remaining = unsuppressed_count - leaks_printed;
+ Printf("Omitting %zu more leak(s).\n", remaining);
+ }
+}
+
+void LeakReport::PrintSummary() {
+ CHECK(leaks_.size() <= kMaxLeaksConsidered);
+ uptr bytes = 0, allocations = 0;
+ for (uptr i = 0; i < leaks_.size(); i++) {
+ if (leaks_[i].is_suppressed) continue;
+ bytes += leaks_[i].total_size;
+ allocations += leaks_[i].hit_count;
+ }
+ const int kMaxSummaryLength = 128;
+ InternalScopedBuffer<char> summary(kMaxSummaryLength);
+ internal_snprintf(summary.data(), kMaxSummaryLength,
+ "LeakSanitizer: %zu byte(s) leaked in %zu allocation(s).",
+ bytes, allocations);
+ __sanitizer_report_error_summary(summary.data());
+}
+
+uptr LeakReport::ApplySuppressions() {
+ uptr unsuppressed_count = 0;
+ for (uptr i = 0; i < leaks_.size(); i++) {
+ Suppression *s = GetSuppressionForStack(leaks_[i].stack_trace_id);
+ if (s) {
+ s->weight += leaks_[i].total_size;
+ s->hit_count += leaks_[i].hit_count;
+ leaks_[i].is_suppressed = true;
+ } else {
+ unsuppressed_count++;
+ }
+ }
+ return unsuppressed_count;
+}
+} // namespace __lsan
+#endif // CAN_SANITIZE_LEAKS
+
+using namespace __lsan; // NOLINT
+
+extern "C" {
+SANITIZER_INTERFACE_ATTRIBUTE
+void __lsan_ignore_object(const void *p) {
+#if CAN_SANITIZE_LEAKS
+ // Cannot use PointsIntoChunk or LsanMetadata here, since the allocator is not
+ // locked.
+ BlockingMutexLock l(&global_mutex);
+ IgnoreObjectResult res = IgnoreObjectLocked(p);
+ if (res == kIgnoreObjectInvalid && flags()->verbosity >= 2)
+ Report("__lsan_ignore_object(): no heap object found at %p", p);
+ if (res == kIgnoreObjectAlreadyIgnored && flags()->verbosity >= 2)
+ Report("__lsan_ignore_object(): "
+ "heap object at %p is already being ignored\n", p);
+ if (res == kIgnoreObjectSuccess && flags()->verbosity >= 3)
+ Report("__lsan_ignore_object(): ignoring heap object at %p\n", p);
+#endif // CAN_SANITIZE_LEAKS
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __lsan_disable() {
+#if CAN_SANITIZE_LEAKS
+ __lsan::disable_counter++;
+#endif
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __lsan_enable() {
+#if CAN_SANITIZE_LEAKS
+ if (!__lsan::disable_counter) {
+ Report("Unmatched call to __lsan_enable().\n");
+ Die();
+ }
+ __lsan::disable_counter--;
+#endif
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __lsan_do_leak_check() {
+#if CAN_SANITIZE_LEAKS
+ if (common_flags()->detect_leaks)
+ __lsan::DoLeakCheck();
+#endif // CAN_SANITIZE_LEAKS
+}
+
+#if !SANITIZER_SUPPORTS_WEAK_HOOKS
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
+int __lsan_is_turned_off() {
+ return 0;
+}
+#endif
+} // extern "C"
diff --git a/libsanitizer/lsan/lsan_common.h b/libsanitizer/lsan/lsan_common.h
new file mode 100644
index 00000000000..7906ecb9177
--- /dev/null
+++ b/libsanitizer/lsan/lsan_common.h
@@ -0,0 +1,174 @@
+//=-- lsan_common.h -------------------------------------------------------===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of LeakSanitizer.
+// Private LSan header.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LSAN_COMMON_H
+#define LSAN_COMMON_H
+
+#include "sanitizer_common/sanitizer_allocator.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_internal_defs.h"
+#include "sanitizer_common/sanitizer_platform.h"
+#include "sanitizer_common/sanitizer_symbolizer.h"
+
+#if SANITIZER_LINUX && defined(__x86_64__)
+#define CAN_SANITIZE_LEAKS 1
+#else
+#define CAN_SANITIZE_LEAKS 0
+#endif
+
+namespace __lsan {
+
+// Chunk tags.
+enum ChunkTag {
+ kDirectlyLeaked = 0, // default
+ kIndirectlyLeaked = 1,
+ kReachable = 2,
+ kIgnored = 3
+};
+
+struct Flags {
+ uptr pointer_alignment() const {
+ return use_unaligned ? 1 : sizeof(uptr);
+ }
+
+ // Print addresses of leaked objects after main leak report.
+ bool report_objects;
+ // Aggregate two objects into one leak if this many stack frames match. If
+ // zero, the entire stack trace must match.
+ int resolution;
+ // The number of leaks reported.
+ int max_leaks;
+ // If nonzero kill the process with this exit code upon finding leaks.
+ int exitcode;
+ // Suppressions file name.
+ const char* suppressions;
+
+ // Flags controlling the root set of reachable memory.
+ // Global variables (.data and .bss).
+ bool use_globals;
+ // Thread stacks.
+ bool use_stacks;
+ // Thread registers.
+ bool use_registers;
+ // TLS and thread-specific storage.
+ bool use_tls;
+
+ // Consider unaligned pointers valid.
+ bool use_unaligned;
+
+ // User-visible verbosity.
+ int verbosity;
+
+ // Debug logging.
+ bool log_pointers;
+ bool log_threads;
+};
+
+extern Flags lsan_flags;
+inline Flags *flags() { return &lsan_flags; }
+
+struct Leak {
+ uptr hit_count;
+ uptr total_size;
+ u32 stack_trace_id;
+ bool is_directly_leaked;
+ bool is_suppressed;
+};
+
+// Aggregates leaks by stack trace prefix.
+class LeakReport {
+ public:
+ LeakReport() : leaks_(1) {}
+ void Add(u32 stack_trace_id, uptr leaked_size, ChunkTag tag);
+ void PrintLargest(uptr max_leaks);
+ void PrintSummary();
+ bool IsEmpty() { return leaks_.size() == 0; }
+ uptr ApplySuppressions();
+ private:
+ InternalMmapVector<Leak> leaks_;
+};
+
+typedef InternalMmapVector<uptr> Frontier;
+
+// Platform-specific functions.
+void InitializePlatformSpecificModules();
+void ProcessGlobalRegions(Frontier *frontier);
+void ProcessPlatformSpecificAllocations(Frontier *frontier);
+
+void ScanRangeForPointers(uptr begin, uptr end,
+ Frontier *frontier,
+ const char *region_type, ChunkTag tag);
+
+enum IgnoreObjectResult {
+ kIgnoreObjectSuccess,
+ kIgnoreObjectAlreadyIgnored,
+ kIgnoreObjectInvalid
+};
+
+// Functions called from the parent tool.
+void InitCommonLsan();
+void DoLeakCheck();
+bool DisabledInThisThread();
+
+// The following must be implemented in the parent tool.
+
+void ForEachChunk(ForEachChunkCallback callback, void *arg);
+// Returns the address range occupied by the global allocator object.
+void GetAllocatorGlobalRange(uptr *begin, uptr *end);
+// Wrappers for allocator's ForceLock()/ForceUnlock().
+void LockAllocator();
+void UnlockAllocator();
+// Wrappers for ThreadRegistry access.
+void LockThreadRegistry();
+void UnlockThreadRegistry();
+bool GetThreadRangesLocked(uptr os_id, uptr *stack_begin, uptr *stack_end,
+ uptr *tls_begin, uptr *tls_end,
+ uptr *cache_begin, uptr *cache_end);
+// If called from the main thread, updates the main thread's TID in the thread
+// registry. We need this to handle processes that fork() without a subsequent
+// exec(), which invalidates the recorded TID. To update it, we must call
+// gettid() from the main thread. Our solution is to call this function before
+// leak checking and also before every call to pthread_create() (to handle cases
+// where leak checking is initiated from a non-main thread).
+void EnsureMainThreadIDIsCorrect();
+// If p points into a chunk that has been allocated to the user, returns its
+// user-visible address. Otherwise, returns 0.
+uptr PointsIntoChunk(void *p);
+// Returns address of user-visible chunk contained in this allocator chunk.
+uptr GetUserBegin(uptr chunk);
+// Helper for __lsan_ignore_object().
+IgnoreObjectResult IgnoreObjectLocked(const void *p);
+// Wrapper for chunk metadata operations.
+class LsanMetadata {
+ public:
+ // Constructor accepts address of user-visible chunk.
+ explicit LsanMetadata(uptr chunk);
+ bool allocated() const;
+ ChunkTag tag() const;
+ void set_tag(ChunkTag value);
+ uptr requested_size() const;
+ u32 stack_trace_id() const;
+ private:
+ void *metadata_;
+};
+
+} // namespace __lsan
+
+extern "C" {
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
+int __lsan_is_turned_off();
+
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
+const char *__lsan_default_suppressions();
+} // extern "C"
+
+#endif // LSAN_COMMON_H
diff --git a/libsanitizer/lsan/lsan_common_linux.cc b/libsanitizer/lsan/lsan_common_linux.cc
new file mode 100644
index 00000000000..80d2459a9ad
--- /dev/null
+++ b/libsanitizer/lsan/lsan_common_linux.cc
@@ -0,0 +1,139 @@
+//=-- lsan_common_linux.cc ------------------------------------------------===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of LeakSanitizer.
+// Implementation of common leak checking functionality. Linux-specific code.
+//
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_platform.h"
+#include "lsan_common.h"
+
+#if CAN_SANITIZE_LEAKS && SANITIZER_LINUX
+#include <link.h>
+
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_linux.h"
+#include "sanitizer_common/sanitizer_stackdepot.h"
+
+namespace __lsan {
+
+static const char kLinkerName[] = "ld";
+// We request 2 modules matching "ld", so we can print a warning if there's more
+// than one match. But only the first one is actually used.
+static char linker_placeholder[2 * sizeof(LoadedModule)] ALIGNED(64);
+static LoadedModule *linker = 0;
+
+static bool IsLinker(const char* full_name) {
+ return LibraryNameIs(full_name, kLinkerName);
+}
+
+void InitializePlatformSpecificModules() {
+ internal_memset(linker_placeholder, 0, sizeof(linker_placeholder));
+ uptr num_matches = GetListOfModules(
+ reinterpret_cast<LoadedModule *>(linker_placeholder), 2, IsLinker);
+ if (num_matches == 1) {
+ linker = reinterpret_cast<LoadedModule *>(linker_placeholder);
+ return;
+ }
+ if (num_matches == 0)
+ Report("LeakSanitizer: Dynamic linker not found. "
+ "TLS will not be handled correctly.\n");
+ else if (num_matches > 1)
+ Report("LeakSanitizer: Multiple modules match \"%s\". "
+ "TLS will not be handled correctly.\n", kLinkerName);
+ linker = 0;
+}
+
+static int ProcessGlobalRegionsCallback(struct dl_phdr_info *info, size_t size,
+ void *data) {
+ Frontier *frontier = reinterpret_cast<Frontier *>(data);
+ for (uptr j = 0; j < info->dlpi_phnum; j++) {
+ const ElfW(Phdr) *phdr = &(info->dlpi_phdr[j]);
+ // We're looking for .data and .bss sections, which reside in writeable,
+ // loadable segments.
+ if (!(phdr->p_flags & PF_W) || (phdr->p_type != PT_LOAD) ||
+ (phdr->p_memsz == 0))
+ continue;
+ uptr begin = info->dlpi_addr + phdr->p_vaddr;
+ uptr end = begin + phdr->p_memsz;
+ uptr allocator_begin = 0, allocator_end = 0;
+ GetAllocatorGlobalRange(&allocator_begin, &allocator_end);
+ if (begin <= allocator_begin && allocator_begin < end) {
+ CHECK_LE(allocator_begin, allocator_end);
+ CHECK_LT(allocator_end, end);
+ if (begin < allocator_begin)
+ ScanRangeForPointers(begin, allocator_begin, frontier, "GLOBAL",
+ kReachable);
+ if (allocator_end < end)
+ ScanRangeForPointers(allocator_end, end, frontier, "GLOBAL",
+ kReachable);
+ } else {
+ ScanRangeForPointers(begin, end, frontier, "GLOBAL", kReachable);
+ }
+ }
+ return 0;
+}
+
+// Scans global variables for heap pointers.
+void ProcessGlobalRegions(Frontier *frontier) {
+ // FIXME: dl_iterate_phdr acquires a linker lock, so we run a risk of
+ // deadlocking by running this under StopTheWorld. However, the lock is
+ // reentrant, so we should be able to fix this by acquiring the lock before
+ // suspending threads.
+ dl_iterate_phdr(ProcessGlobalRegionsCallback, frontier);
+}
+
+static uptr GetCallerPC(u32 stack_id, StackDepotReverseMap *map) {
+ CHECK(stack_id);
+ uptr size = 0;
+ const uptr *trace = map->Get(stack_id, &size);
+ // The top frame is our malloc/calloc/etc. The next frame is the caller.
+ if (size >= 2)
+ return trace[1];
+ return 0;
+}
+
+struct ProcessPlatformAllocParam {
+ Frontier *frontier;
+ StackDepotReverseMap *stack_depot_reverse_map;
+};
+
+// ForEachChunk callback. Identifies unreachable chunks which must be treated as
+// reachable. Marks them as reachable and adds them to the frontier.
+static void ProcessPlatformSpecificAllocationsCb(uptr chunk, void *arg) {
+ CHECK(arg);
+ ProcessPlatformAllocParam *param =
+ reinterpret_cast<ProcessPlatformAllocParam *>(arg);
+ chunk = GetUserBegin(chunk);
+ LsanMetadata m(chunk);
+ if (m.allocated() && m.tag() != kReachable) {
+ u32 stack_id = m.stack_trace_id();
+ uptr caller_pc = 0;
+ if (stack_id > 0)
+ caller_pc = GetCallerPC(stack_id, param->stack_depot_reverse_map);
+ // If caller_pc is unknown, this chunk may be allocated in a coroutine. Mark
+ // it as reachable, as we can't properly report its allocation stack anyway.
+ if (caller_pc == 0 || linker->containsAddress(caller_pc)) {
+ m.set_tag(kReachable);
+ param->frontier->push_back(chunk);
+ }
+ }
+}
+
+// Handles dynamically allocated TLS blocks by treating all chunks allocated
+// from ld-linux.so as reachable.
+void ProcessPlatformSpecificAllocations(Frontier *frontier) {
+ if (!flags()->use_tls) return;
+ if (!linker) return;
+ StackDepotReverseMap stack_depot_reverse_map;
+ ProcessPlatformAllocParam arg = {frontier, &stack_depot_reverse_map};
+ ForEachChunk(ProcessPlatformSpecificAllocationsCb, &arg);
+}
+
+} // namespace __lsan
+#endif // CAN_SANITIZE_LEAKS && SANITIZER_LINUX
diff --git a/libsanitizer/lsan/lsan_interceptors.cc b/libsanitizer/lsan/lsan_interceptors.cc
new file mode 100644
index 00000000000..40ddc7773e2
--- /dev/null
+++ b/libsanitizer/lsan/lsan_interceptors.cc
@@ -0,0 +1,279 @@
+//=-- lsan_interceptors.cc ------------------------------------------------===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of LeakSanitizer.
+// Interceptors for standalone LSan.
+//
+//===----------------------------------------------------------------------===//
+
+#include "interception/interception.h"
+#include "sanitizer_common/sanitizer_allocator.h"
+#include "sanitizer_common/sanitizer_atomic.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_flags.h"
+#include "sanitizer_common/sanitizer_internal_defs.h"
+#include "sanitizer_common/sanitizer_linux.h"
+#include "sanitizer_common/sanitizer_platform_limits_posix.h"
+#include "lsan.h"
+#include "lsan_allocator.h"
+#include "lsan_thread.h"
+
+using namespace __lsan;
+
+extern "C" {
+int pthread_attr_init(void *attr);
+int pthread_attr_destroy(void *attr);
+int pthread_attr_getdetachstate(void *attr, int *v);
+int pthread_key_create(unsigned *key, void (*destructor)(void* v));
+int pthread_setspecific(unsigned key, const void *v);
+}
+
+#define GET_STACK_TRACE \
+ StackTrace stack; \
+ { \
+ uptr stack_top = 0, stack_bottom = 0; \
+ ThreadContext *t; \
+ bool fast = common_flags()->fast_unwind_on_malloc; \
+ if (fast && (t = CurrentThreadContext())) { \
+ stack_top = t->stack_end(); \
+ stack_bottom = t->stack_begin(); \
+ } \
+ GetStackTrace(&stack, __sanitizer::common_flags()->malloc_context_size, \
+ StackTrace::GetCurrentPc(), \
+ GET_CURRENT_FRAME(), stack_top, stack_bottom, fast); \
+ }
+
+///// Malloc/free interceptors. /////
+
+const bool kAlwaysClearMemory = true;
+
+namespace std {
+ struct nothrow_t;
+}
+
+INTERCEPTOR(void*, malloc, uptr size) {
+ Init();
+ GET_STACK_TRACE;
+ return Allocate(stack, size, 1, kAlwaysClearMemory);
+}
+
+INTERCEPTOR(void, free, void *p) {
+ Init();
+ Deallocate(p);
+}
+
+INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) {
+ if (CallocShouldReturnNullDueToOverflow(size, nmemb)) return 0;
+ Init();
+ GET_STACK_TRACE;
+ size *= nmemb;
+ return Allocate(stack, size, 1, true);
+}
+
+INTERCEPTOR(void*, realloc, void *q, uptr size) {
+ Init();
+ GET_STACK_TRACE;
+ return Reallocate(stack, q, size, 1);
+}
+
+INTERCEPTOR(void*, memalign, uptr alignment, uptr size) {
+ Init();
+ GET_STACK_TRACE;
+ return Allocate(stack, size, alignment, kAlwaysClearMemory);
+}
+
+INTERCEPTOR(int, posix_memalign, void **memptr, uptr alignment, uptr size) {
+ Init();
+ GET_STACK_TRACE;
+ *memptr = Allocate(stack, size, alignment, kAlwaysClearMemory);
+ // FIXME: Return ENOMEM if user requested more than max alloc size.
+ return 0;
+}
+
+INTERCEPTOR(void*, valloc, uptr size) {
+ Init();
+ GET_STACK_TRACE;
+ if (size == 0)
+ size = GetPageSizeCached();
+ return Allocate(stack, size, GetPageSizeCached(), kAlwaysClearMemory);
+}
+
+INTERCEPTOR(uptr, malloc_usable_size, void *ptr) {
+ Init();
+ return GetMallocUsableSize(ptr);
+}
+
+struct fake_mallinfo {
+ int x[10];
+};
+
+INTERCEPTOR(struct fake_mallinfo, mallinfo, void) {
+ struct fake_mallinfo res;
+ internal_memset(&res, 0, sizeof(res));
+ return res;
+}
+
+INTERCEPTOR(int, mallopt, int cmd, int value) {
+ return -1;
+}
+
+INTERCEPTOR(void*, pvalloc, uptr size) {
+ Init();
+ GET_STACK_TRACE;
+ uptr PageSize = GetPageSizeCached();
+ size = RoundUpTo(size, PageSize);
+ if (size == 0) {
+ // pvalloc(0) should allocate one page.
+ size = PageSize;
+ }
+ return Allocate(stack, size, GetPageSizeCached(), kAlwaysClearMemory);
+}
+
+INTERCEPTOR(void, cfree, void *p) ALIAS("free");
+
+#define OPERATOR_NEW_BODY \
+ Init(); \
+ GET_STACK_TRACE; \
+ return Allocate(stack, size, 1, kAlwaysClearMemory);
+
+INTERCEPTOR_ATTRIBUTE
+void *operator new(uptr size) { OPERATOR_NEW_BODY; }
+INTERCEPTOR_ATTRIBUTE
+void *operator new[](uptr size) { OPERATOR_NEW_BODY; }
+INTERCEPTOR_ATTRIBUTE
+void *operator new(uptr size, std::nothrow_t const&) { OPERATOR_NEW_BODY; }
+INTERCEPTOR_ATTRIBUTE
+void *operator new[](uptr size, std::nothrow_t const&) { OPERATOR_NEW_BODY; }
+
+#define OPERATOR_DELETE_BODY \
+ Init(); \
+ Deallocate(ptr);
+
+INTERCEPTOR_ATTRIBUTE
+void operator delete(void *ptr) { OPERATOR_DELETE_BODY; }
+INTERCEPTOR_ATTRIBUTE
+void operator delete[](void *ptr) { OPERATOR_DELETE_BODY; }
+INTERCEPTOR_ATTRIBUTE
+void operator delete(void *ptr, std::nothrow_t const&) { OPERATOR_DELETE_BODY; }
+INTERCEPTOR_ATTRIBUTE
+void operator delete[](void *ptr, std::nothrow_t const &) {
+ OPERATOR_DELETE_BODY;
+}
+
+// We need this to intercept the __libc_memalign calls that are used to
+// allocate dynamic TLS space in ld-linux.so.
+INTERCEPTOR(void *, __libc_memalign, uptr align, uptr s) ALIAS("memalign");
+
+///// Thread initialization and finalization. /////
+
+static unsigned g_thread_finalize_key;
+
+static void thread_finalize(void *v) {
+ uptr iter = (uptr)v;
+ if (iter > 1) {
+ if (pthread_setspecific(g_thread_finalize_key, (void*)(iter - 1))) {
+ Report("LeakSanitizer: failed to set thread key.\n");
+ Die();
+ }
+ return;
+ }
+ ThreadFinish();
+}
+
+struct ThreadParam {
+ void *(*callback)(void *arg);
+ void *param;
+ atomic_uintptr_t tid;
+};
+
+// PTHREAD_DESTRUCTOR_ITERATIONS from glibc.
+const uptr kPthreadDestructorIterations = 4;
+
+extern "C" void *__lsan_thread_start_func(void *arg) {
+ ThreadParam *p = (ThreadParam*)arg;
+ void* (*callback)(void *arg) = p->callback;
+ void *param = p->param;
+ // Wait until the last iteration to maximize the chance that we are the last
+ // destructor to run.
+ if (pthread_setspecific(g_thread_finalize_key,
+ (void*)kPthreadDestructorIterations)) {
+ Report("LeakSanitizer: failed to set thread key.\n");
+ Die();
+ }
+ int tid = 0;
+ while ((tid = atomic_load(&p->tid, memory_order_acquire)) == 0)
+ internal_sched_yield();
+ atomic_store(&p->tid, 0, memory_order_release);
+ SetCurrentThread(tid);
+ ThreadStart(tid, GetTid());
+ return callback(param);
+}
+
+INTERCEPTOR(int, pthread_create, void *th, void *attr,
+ void *(*callback)(void *), void *param) {
+ Init();
+ EnsureMainThreadIDIsCorrect();
+ __sanitizer_pthread_attr_t myattr;
+ if (attr == 0) {
+ pthread_attr_init(&myattr);
+ attr = &myattr;
+ }
+ AdjustStackSizeLinux(attr, 0);
+ int detached = 0;
+ pthread_attr_getdetachstate(attr, &detached);
+ ThreadParam p;
+ p.callback = callback;
+ p.param = param;
+ atomic_store(&p.tid, 0, memory_order_relaxed);
+ int res = REAL(pthread_create)(th, attr, __lsan_thread_start_func, &p);
+ if (res == 0) {
+ int tid = ThreadCreate(GetCurrentThread(), *(uptr *)th, detached);
+ CHECK_NE(tid, 0);
+ atomic_store(&p.tid, tid, memory_order_release);
+ while (atomic_load(&p.tid, memory_order_acquire) != 0)
+ internal_sched_yield();
+ }
+ if (attr == &myattr)
+ pthread_attr_destroy(&myattr);
+ return res;
+}
+
+INTERCEPTOR(int, pthread_join, void *th, void **ret) {
+ Init();
+ int tid = ThreadTid((uptr)th);
+ int res = REAL(pthread_join)(th, ret);
+ if (res == 0)
+ ThreadJoin(tid);
+ return res;
+}
+
+namespace __lsan {
+
+void InitializeInterceptors() {
+ INTERCEPT_FUNCTION(malloc);
+ INTERCEPT_FUNCTION(free);
+ INTERCEPT_FUNCTION(cfree);
+ INTERCEPT_FUNCTION(calloc);
+ INTERCEPT_FUNCTION(realloc);
+ INTERCEPT_FUNCTION(memalign);
+ INTERCEPT_FUNCTION(posix_memalign);
+ INTERCEPT_FUNCTION(__libc_memalign);
+ INTERCEPT_FUNCTION(valloc);
+ INTERCEPT_FUNCTION(pvalloc);
+ INTERCEPT_FUNCTION(malloc_usable_size);
+ INTERCEPT_FUNCTION(mallinfo);
+ INTERCEPT_FUNCTION(mallopt);
+ INTERCEPT_FUNCTION(pthread_create);
+ INTERCEPT_FUNCTION(pthread_join);
+
+ if (pthread_key_create(&g_thread_finalize_key, &thread_finalize)) {
+ Report("LeakSanitizer: failed to create thread key.\n");
+ Die();
+ }
+}
+
+} // namespace __lsan
diff --git a/libsanitizer/lsan/lsan_thread.cc b/libsanitizer/lsan/lsan_thread.cc
new file mode 100644
index 00000000000..c260972cb47
--- /dev/null
+++ b/libsanitizer/lsan/lsan_thread.cc
@@ -0,0 +1,154 @@
+//=-- lsan_thread.cc ------------------------------------------------------===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of LeakSanitizer.
+// See lsan_thread.h for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lsan_thread.h"
+
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_placement_new.h"
+#include "sanitizer_common/sanitizer_thread_registry.h"
+#include "lsan_allocator.h"
+
+namespace __lsan {
+
+const u32 kInvalidTid = (u32) -1;
+
+static ThreadRegistry *thread_registry;
+static THREADLOCAL u32 current_thread_tid = kInvalidTid;
+
+static ThreadContextBase *CreateThreadContext(u32 tid) {
+ void *mem = MmapOrDie(sizeof(ThreadContext), "ThreadContext");
+ return new(mem) ThreadContext(tid);
+}
+
+static const uptr kMaxThreads = 1 << 13;
+static const uptr kThreadQuarantineSize = 64;
+
+void InitializeThreadRegistry() {
+ static char thread_registry_placeholder[sizeof(ThreadRegistry)] ALIGNED(64);
+ thread_registry = new(thread_registry_placeholder)
+ ThreadRegistry(CreateThreadContext, kMaxThreads, kThreadQuarantineSize);
+}
+
+u32 GetCurrentThread() {
+ return current_thread_tid;
+}
+
+void SetCurrentThread(u32 tid) {
+ current_thread_tid = tid;
+}
+
+ThreadContext::ThreadContext(int tid)
+ : ThreadContextBase(tid),
+ stack_begin_(0),
+ stack_end_(0),
+ cache_begin_(0),
+ cache_end_(0),
+ tls_begin_(0),
+ tls_end_(0) {}
+
+struct OnStartedArgs {
+ uptr stack_begin, stack_end,
+ cache_begin, cache_end,
+ tls_begin, tls_end;
+};
+
+void ThreadContext::OnStarted(void *arg) {
+ OnStartedArgs *args = reinterpret_cast<OnStartedArgs *>(arg);
+ stack_begin_ = args->stack_begin;
+ stack_end_ = args->stack_end;
+ tls_begin_ = args->tls_begin;
+ tls_end_ = args->tls_end;
+ cache_begin_ = args->cache_begin;
+ cache_end_ = args->cache_end;
+}
+
+void ThreadContext::OnFinished() {
+ AllocatorThreadFinish();
+}
+
+u32 ThreadCreate(u32 parent_tid, uptr user_id, bool detached) {
+ return thread_registry->CreateThread(user_id, detached, parent_tid,
+ /* arg */ 0);
+}
+
+void ThreadStart(u32 tid, uptr os_id) {
+ OnStartedArgs args;
+ uptr stack_size = 0;
+ uptr tls_size = 0;
+ GetThreadStackAndTls(tid == 0, &args.stack_begin, &stack_size,
+ &args.tls_begin, &tls_size);
+ args.stack_end = args.stack_begin + stack_size;
+ args.tls_end = args.tls_begin + tls_size;
+ GetAllocatorCacheRange(&args.cache_begin, &args.cache_end);
+ thread_registry->StartThread(tid, os_id, &args);
+}
+
+void ThreadFinish() {
+ thread_registry->FinishThread(GetCurrentThread());
+}
+
+ThreadContext *CurrentThreadContext() {
+ if (!thread_registry) return 0;
+ if (GetCurrentThread() == kInvalidTid)
+ return 0;
+ // No lock needed when getting current thread.
+ return (ThreadContext *)thread_registry->GetThreadLocked(GetCurrentThread());
+}
+
+static bool FindThreadByUid(ThreadContextBase *tctx, void *arg) {
+ uptr uid = (uptr)arg;
+ if (tctx->user_id == uid && tctx->status != ThreadStatusInvalid) {
+ return true;
+ }
+ return false;
+}
+
+u32 ThreadTid(uptr uid) {
+ return thread_registry->FindThread(FindThreadByUid, (void*)uid);
+}
+
+void ThreadJoin(u32 tid) {
+ CHECK_NE(tid, kInvalidTid);
+ thread_registry->JoinThread(tid, /* arg */0);
+}
+
+void EnsureMainThreadIDIsCorrect() {
+ if (GetCurrentThread() == 0)
+ CurrentThreadContext()->os_id = GetTid();
+}
+
+///// Interface to the common LSan module. /////
+
+bool GetThreadRangesLocked(uptr os_id, uptr *stack_begin, uptr *stack_end,
+ uptr *tls_begin, uptr *tls_end,
+ uptr *cache_begin, uptr *cache_end) {
+ ThreadContext *context = static_cast<ThreadContext *>(
+ thread_registry->FindThreadContextByOsIDLocked(os_id));
+ if (!context) return false;
+ *stack_begin = context->stack_begin();
+ *stack_end = context->stack_end();
+ *tls_begin = context->tls_begin();
+ *tls_end = context->tls_end();
+ *cache_begin = context->cache_begin();
+ *cache_end = context->cache_end();
+ return true;
+}
+
+void LockThreadRegistry() {
+ thread_registry->Lock();
+}
+
+void UnlockThreadRegistry() {
+ thread_registry->Unlock();
+}
+
+} // namespace __lsan
diff --git a/libsanitizer/lsan/lsan_thread.h b/libsanitizer/lsan/lsan_thread.h
new file mode 100644
index 00000000000..cd13fdb5c52
--- /dev/null
+++ b/libsanitizer/lsan/lsan_thread.h
@@ -0,0 +1,51 @@
+//=-- lsan_thread.h -------------------------------------------------------===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of LeakSanitizer.
+// Thread registry for standalone LSan.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LSAN_THREAD_H
+#define LSAN_THREAD_H
+
+#include "sanitizer_common/sanitizer_thread_registry.h"
+
+namespace __lsan {
+
+class ThreadContext : public ThreadContextBase {
+ public:
+ explicit ThreadContext(int tid);
+ void OnStarted(void *arg);
+ void OnFinished();
+ uptr stack_begin() { return stack_begin_; }
+ uptr stack_end() { return stack_end_; }
+ uptr tls_begin() { return tls_begin_; }
+ uptr tls_end() { return tls_end_; }
+ uptr cache_begin() { return cache_begin_; }
+ uptr cache_end() { return cache_end_; }
+ private:
+ uptr stack_begin_, stack_end_,
+ cache_begin_, cache_end_,
+ tls_begin_, tls_end_;
+};
+
+void InitializeThreadRegistry();
+
+void ThreadStart(u32 tid, uptr os_id);
+void ThreadFinish();
+u32 ThreadCreate(u32 tid, uptr uid, bool detached);
+void ThreadJoin(u32 tid);
+u32 ThreadTid(uptr uid);
+
+u32 GetCurrentThread();
+void SetCurrentThread(u32 tid);
+ThreadContext *CurrentThreadContext();
+void EnsureMainThreadIDIsCorrect();
+} // namespace __lsan
+
+#endif // LSAN_THREAD_H
diff --git a/libsanitizer/merge.sh b/libsanitizer/merge.sh
index 23748a701bb..aae8eb41f7d 100755
--- a/libsanitizer/merge.sh
+++ b/libsanitizer/merge.sh
@@ -66,6 +66,7 @@ CUR_REV=$(get_current_rev)
echo Current upstream revision: $CUR_REV
merge include/sanitizer include/sanitizer
merge lib/asan asan
+merge lib/lsan lsan
merge lib/tsan/rtl tsan
merge lib/sanitizer_common sanitizer_common
merge lib/interception interception
diff --git a/libsanitizer/sanitizer_common/Makefile.am b/libsanitizer/sanitizer_common/Makefile.am
index c53a3c6bfc5..6cd51187ccb 100644
--- a/libsanitizer/sanitizer_common/Makefile.am
+++ b/libsanitizer/sanitizer_common/Makefile.am
@@ -11,23 +11,27 @@ ACLOCAL_AMFLAGS = -I m4
noinst_LTLIBRARIES = libsanitizer_common.la
sanitizer_common_files = \
- sanitizer_allocator.cc \
- sanitizer_common.cc \
- sanitizer_flags.cc \
- sanitizer_libc.cc \
- sanitizer_linux.cc \
- sanitizer_mac.cc \
+ sanitizer_allocator.cc \
+ sanitizer_common.cc \
+ sanitizer_common_libcdep.cc \
+ sanitizer_flags.cc \
+ sanitizer_libc.cc \
+ sanitizer_linux.cc \
+ sanitizer_linux_libcdep.cc \
+ sanitizer_mac.cc \
+ sanitizer_platform_limits_linux.cc \
sanitizer_platform_limits_posix.cc \
- sanitizer_posix.cc \
- sanitizer_printf.cc \
- sanitizer_stackdepot.cc \
- sanitizer_stacktrace.cc \
- sanitizer_symbolizer.cc \
- sanitizer_symbolizer_itanium.cc \
- sanitizer_symbolizer_linux.cc \
- sanitizer_symbolizer_mac.cc \
- sanitizer_symbolizer_win.cc \
- sanitizer_win.cc
+ sanitizer_posix.cc \
+ sanitizer_posix_libcdep.cc \
+ sanitizer_printf.cc \
+ sanitizer_stackdepot.cc \
+ sanitizer_stacktrace.cc \
+ sanitizer_stoptheworld_linux_libcdep.cc \
+ sanitizer_suppressions.cc \
+ sanitizer_symbolizer_posix_libcdep.cc \
+ sanitizer_symbolizer_win.cc \
+ sanitizer_thread_registry.cc \
+ sanitizer_win.cc
libsanitizer_common_la_SOURCES = $(sanitizer_common_files)
diff --git a/libsanitizer/sanitizer_common/Makefile.in b/libsanitizer/sanitizer_common/Makefile.in
index b49fe4212cf..4679dead3a9 100644
--- a/libsanitizer/sanitizer_common/Makefile.in
+++ b/libsanitizer/sanitizer_common/Makefile.in
@@ -73,12 +73,17 @@ CONFIG_CLEAN_VPATH_FILES =
LTLIBRARIES = $(noinst_LTLIBRARIES)
libsanitizer_common_la_LIBADD =
am__objects_1 = sanitizer_allocator.lo sanitizer_common.lo \
- sanitizer_flags.lo sanitizer_libc.lo sanitizer_linux.lo \
- sanitizer_mac.lo sanitizer_platform_limits_posix.lo \
- sanitizer_posix.lo sanitizer_printf.lo sanitizer_stackdepot.lo \
- sanitizer_stacktrace.lo sanitizer_symbolizer.lo \
- sanitizer_symbolizer_itanium.lo sanitizer_symbolizer_linux.lo \
- sanitizer_symbolizer_mac.lo sanitizer_symbolizer_win.lo \
+ sanitizer_common_libcdep.lo sanitizer_flags.lo \
+ sanitizer_libc.lo sanitizer_linux.lo \
+ sanitizer_linux_libcdep.lo sanitizer_mac.lo \
+ sanitizer_platform_limits_linux.lo \
+ sanitizer_platform_limits_posix.lo sanitizer_posix.lo \
+ sanitizer_posix_libcdep.lo sanitizer_printf.lo \
+ sanitizer_stackdepot.lo sanitizer_stacktrace.lo \
+ sanitizer_stoptheworld_linux_libcdep.lo \
+ sanitizer_suppressions.lo \
+ sanitizer_symbolizer_posix_libcdep.lo \
+ sanitizer_symbolizer_win.lo sanitizer_thread_registry.lo \
sanitizer_win.lo
am_libsanitizer_common_la_OBJECTS = $(am__objects_1)
libsanitizer_common_la_OBJECTS = $(am_libsanitizer_common_la_OBJECTS)
@@ -245,23 +250,27 @@ AM_CXXFLAGS = -Wall -W -Wno-unused-parameter -Wwrite-strings -pedantic \
ACLOCAL_AMFLAGS = -I m4
noinst_LTLIBRARIES = libsanitizer_common.la
sanitizer_common_files = \
- sanitizer_allocator.cc \
- sanitizer_common.cc \
- sanitizer_flags.cc \
- sanitizer_libc.cc \
- sanitizer_linux.cc \
- sanitizer_mac.cc \
+ sanitizer_allocator.cc \
+ sanitizer_common.cc \
+ sanitizer_common_libcdep.cc \
+ sanitizer_flags.cc \
+ sanitizer_libc.cc \
+ sanitizer_linux.cc \
+ sanitizer_linux_libcdep.cc \
+ sanitizer_mac.cc \
+ sanitizer_platform_limits_linux.cc \
sanitizer_platform_limits_posix.cc \
- sanitizer_posix.cc \
- sanitizer_printf.cc \
- sanitizer_stackdepot.cc \
- sanitizer_stacktrace.cc \
- sanitizer_symbolizer.cc \
- sanitizer_symbolizer_itanium.cc \
- sanitizer_symbolizer_linux.cc \
- sanitizer_symbolizer_mac.cc \
- sanitizer_symbolizer_win.cc \
- sanitizer_win.cc
+ sanitizer_posix.cc \
+ sanitizer_posix_libcdep.cc \
+ sanitizer_printf.cc \
+ sanitizer_stackdepot.cc \
+ sanitizer_stacktrace.cc \
+ sanitizer_stoptheworld_linux_libcdep.cc \
+ sanitizer_suppressions.cc \
+ sanitizer_symbolizer_posix_libcdep.cc \
+ sanitizer_symbolizer_win.cc \
+ sanitizer_thread_registry.cc \
+ sanitizer_win.cc
libsanitizer_common_la_SOURCES = $(sanitizer_common_files)
@@ -358,20 +367,24 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_allocator.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_common.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_common_libcdep.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_flags.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_libc.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_linux.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_linux_libcdep.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_mac.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_platform_limits_linux.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_platform_limits_posix.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_posix.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_posix_libcdep.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_printf.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_stackdepot.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_stacktrace.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_symbolizer.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_symbolizer_itanium.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_symbolizer_linux.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_symbolizer_mac.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_stoptheworld_linux_libcdep.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_suppressions.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_symbolizer_posix_libcdep.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_symbolizer_win.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_thread_registry.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_win.Plo@am__quote@
.cc.o:
diff --git a/libsanitizer/sanitizer_common/sanitizer_allocator.cc b/libsanitizer/sanitizer_common/sanitizer_allocator.cc
index a54de9d6f9a..9d38e9429ac 100644
--- a/libsanitizer/sanitizer_common/sanitizer_allocator.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_allocator.cc
@@ -7,44 +7,103 @@
//
// This file is shared between AddressSanitizer and ThreadSanitizer
// run-time libraries.
-// This allocator that is used inside run-times.
+// This allocator is used inside run-times.
//===----------------------------------------------------------------------===//
+#include "sanitizer_allocator.h"
+#include "sanitizer_allocator_internal.h"
#include "sanitizer_common.h"
+#include "sanitizer_flags.h"
-// FIXME: We should probably use more low-level allocator that would
-// mmap some pages and split them into chunks to fulfill requests.
-#if defined(__linux__) && !defined(__ANDROID__)
-extern "C" void *__libc_malloc(__sanitizer::uptr size);
+namespace __sanitizer {
+
+// ThreadSanitizer for Go uses libc malloc/free.
+#if defined(SANITIZER_GO)
+# if SANITIZER_LINUX && !SANITIZER_ANDROID
+extern "C" void *__libc_malloc(uptr size);
extern "C" void __libc_free(void *ptr);
-# define LIBC_MALLOC __libc_malloc
-# define LIBC_FREE __libc_free
-#else // __linux__ && !ANDROID
-# include <stdlib.h>
-# define LIBC_MALLOC malloc
-# define LIBC_FREE free
-#endif // __linux__ && !ANDROID
+# define LIBC_MALLOC __libc_malloc
+# define LIBC_FREE __libc_free
+# else
+# include <stdlib.h>
+# define LIBC_MALLOC malloc
+# define LIBC_FREE free
+# endif
-namespace __sanitizer {
+static void *RawInternalAlloc(uptr size, InternalAllocatorCache *cache) {
+ (void)cache;
+ return LIBC_MALLOC(size);
+}
+
+static void RawInternalFree(void *ptr, InternalAllocatorCache *cache) {
+ (void)cache;
+ LIBC_FREE(ptr);
+}
+
+InternalAllocator *internal_allocator() {
+ return 0;
+}
+
+#else // SANITIZER_GO
+
+static ALIGNED(64) char internal_alloc_placeholder[sizeof(InternalAllocator)];
+static atomic_uint8_t internal_allocator_initialized;
+static StaticSpinMutex internal_alloc_init_mu;
+
+static InternalAllocatorCache internal_allocator_cache;
+static StaticSpinMutex internal_allocator_cache_mu;
+
+InternalAllocator *internal_allocator() {
+ InternalAllocator *internal_allocator_instance =
+ reinterpret_cast<InternalAllocator *>(&internal_alloc_placeholder);
+ if (atomic_load(&internal_allocator_initialized, memory_order_acquire) == 0) {
+ SpinMutexLock l(&internal_alloc_init_mu);
+ if (atomic_load(&internal_allocator_initialized, memory_order_relaxed) ==
+ 0) {
+ internal_allocator_instance->Init();
+ atomic_store(&internal_allocator_initialized, 1, memory_order_release);
+ }
+ }
+ return internal_allocator_instance;
+}
+
+static void *RawInternalAlloc(uptr size, InternalAllocatorCache *cache) {
+ if (cache == 0) {
+ SpinMutexLock l(&internal_allocator_cache_mu);
+ return internal_allocator()->Allocate(&internal_allocator_cache, size, 8,
+ false);
+ }
+ return internal_allocator()->Allocate(cache, size, 8, false);
+}
+
+static void RawInternalFree(void *ptr, InternalAllocatorCache *cache) {
+ if (cache == 0) {
+ SpinMutexLock l(&internal_allocator_cache_mu);
+ return internal_allocator()->Deallocate(&internal_allocator_cache, ptr);
+ }
+ internal_allocator()->Deallocate(cache, ptr);
+}
+
+#endif // SANITIZER_GO
const u64 kBlockMagic = 0x6A6CB03ABCEBC041ull;
-void *InternalAlloc(uptr size) {
+void *InternalAlloc(uptr size, InternalAllocatorCache *cache) {
if (size + sizeof(u64) < size)
return 0;
- void *p = LIBC_MALLOC(size + sizeof(u64));
+ void *p = RawInternalAlloc(size + sizeof(u64), cache);
if (p == 0)
return 0;
((u64*)p)[0] = kBlockMagic;
return (char*)p + sizeof(u64);
}
-void InternalFree(void *addr) {
+void InternalFree(void *addr, InternalAllocatorCache *cache) {
if (addr == 0)
return;
addr = (char*)addr - sizeof(u64);
- CHECK_EQ(((u64*)addr)[0], kBlockMagic);
+ CHECK_EQ(kBlockMagic, ((u64*)addr)[0]);
((u64*)addr)[0] = 0;
- LIBC_FREE(addr);
+ RawInternalFree(addr, cache);
}
// LowLevelAllocator
@@ -79,4 +138,14 @@ bool CallocShouldReturnNullDueToOverflow(uptr size, uptr n) {
return (max / size) < n;
}
+void *AllocatorReturnNull() {
+ if (common_flags()->allocator_may_return_null)
+ return 0;
+ Report("%s's allocator is terminating the process instead of returning 0\n",
+ SanitizerToolName);
+ Report("If you don't like this behavior set allocator_may_return_null=1\n");
+ CHECK(0);
+ return 0;
+}
+
} // namespace __sanitizer
diff --git a/libsanitizer/sanitizer_common/sanitizer_allocator.h b/libsanitizer/sanitizer_common/sanitizer_allocator.h
index 889281216fc..505fa5b8837 100644
--- a/libsanitizer/sanitizer_common/sanitizer_allocator.h
+++ b/libsanitizer/sanitizer_common/sanitizer_allocator.h
@@ -21,18 +21,21 @@
namespace __sanitizer {
+// Depending on allocator_may_return_null either return 0 or crash.
+void *AllocatorReturnNull();
+
// SizeClassMap maps allocation sizes into size classes and back.
// Class 0 corresponds to size 0.
// Classes 1 - 16 correspond to sizes 16 to 256 (size = class_id * 16).
-// Next 8 classes: 256 + i * 32 (i = 1 to 8).
-// Next 8 classes: 512 + i * 64 (i = 1 to 8).
+// Next 4 classes: 256 + i * 64 (i = 1 to 4).
+// Next 4 classes: 512 + i * 128 (i = 1 to 4).
// ...
-// Next 8 classes: 2^k + i * 2^(k-3) (i = 1 to 8).
+// Next 4 classes: 2^k + i * 2^(k-2) (i = 1 to 4).
// Last class corresponds to kMaxSize = 1 << kMaxSizeLog.
//
// This structure of the size class map gives us:
// - Efficient table-free class-to-size and size-to-class functions.
-// - Difference between two consequent size classes is betweed 12% and 6%
+// - Difference between two consequent size classes is betweed 14% and 25%
//
// This class also gives a hint to a thread-caching allocator about the amount
// of chunks that need to be cached per-thread:
@@ -59,46 +62,51 @@ namespace __sanitizer {
// c15 => s: 240 diff: +16 07% l 7 cached: 256 61440; id 15
//
// c16 => s: 256 diff: +16 06% l 8 cached: 256 65536; id 16
-// c17 => s: 288 diff: +32 12% l 8 cached: 227 65376; id 17
-// c18 => s: 320 diff: +32 11% l 8 cached: 204 65280; id 18
-// c19 => s: 352 diff: +32 10% l 8 cached: 186 65472; id 19
-// c20 => s: 384 diff: +32 09% l 8 cached: 170 65280; id 20
-// c21 => s: 416 diff: +32 08% l 8 cached: 157 65312; id 21
-// c22 => s: 448 diff: +32 07% l 8 cached: 146 65408; id 22
-// c23 => s: 480 diff: +32 07% l 8 cached: 136 65280; id 23
+// c17 => s: 320 diff: +64 25% l 8 cached: 204 65280; id 17
+// c18 => s: 384 diff: +64 20% l 8 cached: 170 65280; id 18
+// c19 => s: 448 diff: +64 16% l 8 cached: 146 65408; id 19
+//
+// c20 => s: 512 diff: +64 14% l 9 cached: 128 65536; id 20
+// c21 => s: 640 diff: +128 25% l 9 cached: 102 65280; id 21
+// c22 => s: 768 diff: +128 20% l 9 cached: 85 65280; id 22
+// c23 => s: 896 diff: +128 16% l 9 cached: 73 65408; id 23
+//
+// c24 => s: 1024 diff: +128 14% l 10 cached: 64 65536; id 24
+// c25 => s: 1280 diff: +256 25% l 10 cached: 51 65280; id 25
+// c26 => s: 1536 diff: +256 20% l 10 cached: 42 64512; id 26
+// c27 => s: 1792 diff: +256 16% l 10 cached: 36 64512; id 27
+//
+// ...
//
-// c24 => s: 512 diff: +32 06% l 9 cached: 128 65536; id 24
-// c25 => s: 576 diff: +64 12% l 9 cached: 113 65088; id 25
-// c26 => s: 640 diff: +64 11% l 9 cached: 102 65280; id 26
-// c27 => s: 704 diff: +64 10% l 9 cached: 93 65472; id 27
-// c28 => s: 768 diff: +64 09% l 9 cached: 85 65280; id 28
-// c29 => s: 832 diff: +64 08% l 9 cached: 78 64896; id 29
-// c30 => s: 896 diff: +64 07% l 9 cached: 73 65408; id 30
-// c31 => s: 960 diff: +64 07% l 9 cached: 68 65280; id 31
+// c48 => s: 65536 diff: +8192 14% l 16 cached: 1 65536; id 48
+// c49 => s: 81920 diff: +16384 25% l 16 cached: 1 81920; id 49
+// c50 => s: 98304 diff: +16384 20% l 16 cached: 1 98304; id 50
+// c51 => s: 114688 diff: +16384 16% l 16 cached: 1 114688; id 51
//
-// c32 => s: 1024 diff: +64 06% l 10 cached: 64 65536; id 32
+// c52 => s: 131072 diff: +16384 14% l 17 cached: 1 131072; id 52
-template <uptr kMaxSizeLog, uptr kMaxNumCachedT, uptr kMaxBytesCachedLog,
- uptr kMinBatchClassT>
+template <uptr kMaxSizeLog, uptr kMaxNumCachedT, uptr kMaxBytesCachedLog>
class SizeClassMap {
static const uptr kMinSizeLog = 4;
static const uptr kMidSizeLog = kMinSizeLog + 4;
static const uptr kMinSize = 1 << kMinSizeLog;
static const uptr kMidSize = 1 << kMidSizeLog;
static const uptr kMidClass = kMidSize / kMinSize;
- static const uptr S = 3;
+ static const uptr S = 2;
static const uptr M = (1 << S) - 1;
public:
static const uptr kMaxNumCached = kMaxNumCachedT;
+ // We transfer chunks between central and thread-local free lists in batches.
+ // For small size classes we allocate batches separately.
+ // For large size classes we use one of the chunks to store the batch.
struct TransferBatch {
TransferBatch *next;
uptr count;
void *batch[kMaxNumCached];
};
- static const uptr kMinBatchClass = kMinBatchClassT;
- static const uptr kMaxSize = 1 << kMaxSizeLog;
+ static const uptr kMaxSize = 1UL << kMaxSizeLog;
static const uptr kNumClasses =
kMidClass + ((kMaxSizeLog - kMidSizeLog) << S) + 1;
COMPILER_CHECK(kNumClasses >= 32 && kNumClasses <= 256);
@@ -141,7 +149,7 @@ class SizeClassMap {
Printf("\n");
uptr d = s - prev_s;
uptr p = prev_s ? (d * 100 / prev_s) : 0;
- uptr l = MostSignificantSetBitIndex(s);
+ uptr l = s ? MostSignificantSetBitIndex(s) : 0;
uptr cached = MaxCached(i) * s;
Printf("c%02zd => s: %zd diff: +%zd %02zd%% l %zd "
"cached: %zd %zd; id %zd\n",
@@ -152,10 +160,16 @@ class SizeClassMap {
Printf("Total cached: %zd\n", total_cached);
}
+ static bool SizeClassRequiresSeparateTransferBatch(uptr class_id) {
+ return Size(class_id) < sizeof(TransferBatch) -
+ sizeof(uptr) * (kMaxNumCached - MaxCached(class_id));
+ }
+
static void Validate() {
for (uptr c = 1; c < kNumClasses; c++) {
// Printf("Validate: c%zd\n", c);
uptr s = Size(c);
+ CHECK_NE(s, 0U);
CHECK_EQ(ClassID(s), c);
if (c != kNumClasses - 1)
CHECK_EQ(ClassID(s + 1), c + 1);
@@ -173,24 +187,11 @@ class SizeClassMap {
if (c > 0)
CHECK_LT(Size(c-1), s);
}
-
- // TransferBatch for kMinBatchClass must fit into the block itself.
- const uptr batch_size = sizeof(TransferBatch)
- - sizeof(void*) // NOLINT
- * (kMaxNumCached - MaxCached(kMinBatchClass));
- CHECK_LE(batch_size, Size(kMinBatchClass));
- // TransferBatch for kMinBatchClass-1 must not fit into the block itself.
- const uptr batch_size1 = sizeof(TransferBatch)
- - sizeof(void*) // NOLINT
- * (kMaxNumCached - MaxCached(kMinBatchClass - 1));
- CHECK_GT(batch_size1, Size(kMinBatchClass - 1));
}
};
-typedef SizeClassMap<17, 256, 16, FIRST_32_SECOND_64(25, 28)>
- DefaultSizeClassMap;
-typedef SizeClassMap<17, 64, 14, FIRST_32_SECOND_64(17, 20)>
- CompactSizeClassMap;
+typedef SizeClassMap<17, 128, 16> DefaultSizeClassMap;
+typedef SizeClassMap<17, 64, 14> CompactSizeClassMap;
template<class SizeClassAllocator> struct SizeClassAllocatorLocalCache;
// Memory allocator statistics
@@ -279,6 +280,9 @@ struct NoOpMapUnmapCallback {
void OnUnmap(uptr p, uptr size) const { }
};
+// Callback type for iterating over chunks.
+typedef void (*ForEachChunkCallback)(uptr chunk, void *arg);
+
// SizeClassAllocator64 -- allocator for 64-bit address space.
//
// Space: a portion of address space of kSpaceSize bytes starting at
@@ -339,25 +343,28 @@ class SizeClassAllocator64 {
NOINLINE void DeallocateBatch(AllocatorStats *stat, uptr class_id, Batch *b) {
RegionInfo *region = GetRegionInfo(class_id);
+ CHECK_GT(b->count, 0);
region->free_list.Push(b);
region->n_freed += b->count;
}
- static bool PointerIsMine(void *p) {
+ static bool PointerIsMine(const void *p) {
return reinterpret_cast<uptr>(p) / kSpaceSize == kSpaceBeg / kSpaceSize;
}
- static uptr GetSizeClass(void *p) {
+ static uptr GetSizeClass(const void *p) {
return (reinterpret_cast<uptr>(p) / kRegionSize) % kNumClassesRounded;
}
- void *GetBlockBegin(void *p) {
+ void *GetBlockBegin(const void *p) {
uptr class_id = GetSizeClass(p);
uptr size = SizeClassMap::Size(class_id);
+ if (!size) return 0;
uptr chunk_idx = GetChunkIdx((uptr)p, size);
uptr reg_beg = (uptr)p & ~(kRegionSize - 1);
uptr beg = chunk_idx * size;
uptr next_beg = beg + size;
+ if (class_id >= kNumClasses) return 0;
RegionInfo *region = GetRegionInfo(class_id);
if (region->mapped_user >= next_beg)
return reinterpret_cast<void*>(reg_beg + beg);
@@ -371,7 +378,7 @@ class SizeClassAllocator64 {
uptr ClassID(uptr size) { return SizeClassMap::ClassID(size); }
- void *GetMetaData(void *p) {
+ void *GetMetaData(const void *p) {
uptr class_id = GetSizeClass(p);
uptr size = SizeClassMap::Size(class_id);
uptr chunk_idx = GetChunkIdx(reinterpret_cast<uptr>(p), size);
@@ -430,6 +437,22 @@ class SizeClassAllocator64 {
}
}
+ // Iterate over all existing chunks.
+ // The allocator must be locked when calling this function.
+ void ForEachChunk(ForEachChunkCallback callback, void *arg) {
+ for (uptr class_id = 1; class_id < kNumClasses; class_id++) {
+ RegionInfo *region = GetRegionInfo(class_id);
+ uptr chunk_size = SizeClassMap::Size(class_id);
+ uptr region_beg = kSpaceBeg + class_id * kRegionSize;
+ for (uptr chunk = region_beg;
+ chunk < region_beg + region->allocated_user;
+ chunk += chunk_size) {
+ // Too slow: CHECK_EQ((void *)chunk, GetBlockBegin((void *)chunk));
+ callback(chunk, arg);
+ }
+ }
+ }
+
typedef SizeClassMap SizeClassMapT;
static const uptr kNumClasses = SizeClassMap::kNumClasses;
static const uptr kNumClassesRounded = SizeClassMap::kNumClassesRounded;
@@ -471,11 +494,12 @@ class SizeClassAllocator64 {
}
static uptr GetChunkIdx(uptr chunk, uptr size) {
- u32 offset = chunk % kRegionSize;
+ uptr offset = chunk % kRegionSize;
// Here we divide by a non-constant. This is costly.
- // We require that kRegionSize is at least 2^32 so that offset is 32-bit.
- // We save 2x by using 32-bit div, but may need to use a 256-way switch.
- return offset / (u32)size;
+ // size always fits into 32-bits. If the offset fits too, use 32-bit div.
+ if (offset >> (SANITIZER_WORDSIZE / 2))
+ return offset / size;
+ return (u32)offset / (u32)size;
}
NOINLINE Batch* PopulateFreeList(AllocatorStats *stat, AllocatorCache *c,
@@ -513,14 +537,14 @@ class SizeClassAllocator64 {
region->mapped_meta += map_size;
}
CHECK_LE(region->allocated_meta, region->mapped_meta);
- if (region->allocated_user + region->allocated_meta > kRegionSize) {
- Printf("Out of memory. Dying.\n");
+ if (region->mapped_user + region->mapped_meta > kRegionSize) {
+ Printf("%s: Out of memory. Dying. ", SanitizerToolName);
Printf("The process has exhausted %zuMB for size class %zu.\n",
kRegionSize / 1024 / 1024, size);
Die();
}
for (;;) {
- if (class_id < SizeClassMap::kMinBatchClass)
+ if (SizeClassMap::SizeClassRequiresSeparateTransferBatch(class_id))
b = (Batch*)c->Allocate(this, SizeClassMap::ClassID(sizeof(Batch)));
else
b = (Batch*)(region_beg + beg_idx);
@@ -532,12 +556,37 @@ class SizeClassAllocator64 {
beg_idx += count * size;
if (beg_idx + count * size + size > region->mapped_user)
break;
+ CHECK_GT(b->count, 0);
region->free_list.Push(b);
}
return b;
}
};
+// Maps integers in rage [0, kSize) to u8 values.
+template<u64 kSize>
+class FlatByteMap {
+ public:
+ void TestOnlyInit() {
+ internal_memset(map_, 0, sizeof(map_));
+ }
+
+ void set(uptr idx, u8 val) {
+ CHECK_LT(idx, kSize);
+ CHECK_EQ(0U, map_[idx]);
+ map_[idx] = val;
+ }
+ u8 operator[] (uptr idx) {
+ CHECK_LT(idx, kSize);
+ // FIXME: CHECK may be too expensive here.
+ return map_[idx];
+ }
+ private:
+ u8 map_[kSize];
+};
+
+// FIXME: Also implement TwoLevelByteMap.
+
// SizeClassAllocator32 -- allocator for 32-bit address space.
// This allocator can theoretically be used on 64-bit arch, but there it is less
// efficient than SizeClassAllocator64.
@@ -549,7 +598,7 @@ class SizeClassAllocator64 {
// a result of a single call to MmapAlignedOrDie(kRegionSize, kRegionSize).
// Since the regions are aligned by kRegionSize, there are exactly
// kNumPossibleRegions possible regions in the address space and so we keep
-// an u8 array possible_regions[kNumPossibleRegions] to store the size classes.
+// a ByteMap possible_regions to store the size classes of each Region.
// 0 size class means the region is not used by the allocator.
//
// One Region is used to allocate chunks of a single size class.
@@ -560,16 +609,19 @@ class SizeClassAllocator64 {
// chache-line aligned.
template <const uptr kSpaceBeg, const u64 kSpaceSize,
const uptr kMetadataSize, class SizeClassMap,
+ const uptr kRegionSizeLog,
+ class ByteMap,
class MapUnmapCallback = NoOpMapUnmapCallback>
class SizeClassAllocator32 {
public:
typedef typename SizeClassMap::TransferBatch Batch;
typedef SizeClassAllocator32<kSpaceBeg, kSpaceSize, kMetadataSize,
- SizeClassMap, MapUnmapCallback> ThisT;
+ SizeClassMap, kRegionSizeLog, ByteMap, MapUnmapCallback> ThisT;
typedef SizeClassAllocatorLocalCache<ThisT> AllocatorCache;
void Init() {
- state_ = reinterpret_cast<State *>(MapWithCallback(sizeof(State)));
+ possible_regions.TestOnlyInit();
+ internal_memset(size_class_info_array, 0, sizeof(size_class_info_array));
}
void *MapWithCallback(uptr size) {
@@ -589,7 +641,7 @@ class SizeClassAllocator32 {
alignment <= SizeClassMap::kMaxSize;
}
- void *GetMetaData(void *p) {
+ void *GetMetaData(const void *p) {
CHECK(PointerIsMine(p));
uptr mem = reinterpret_cast<uptr>(p);
uptr beg = ComputeRegionBeg(mem);
@@ -617,18 +669,19 @@ class SizeClassAllocator32 {
CHECK_LT(class_id, kNumClasses);
SizeClassInfo *sci = GetSizeClassInfo(class_id);
SpinMutexLock l(&sci->mutex);
+ CHECK_GT(b->count, 0);
sci->free_list.push_front(b);
}
- bool PointerIsMine(void *p) {
+ bool PointerIsMine(const void *p) {
return GetSizeClass(p) != 0;
}
- uptr GetSizeClass(void *p) {
- return state_->possible_regions[ComputeRegionId(reinterpret_cast<uptr>(p))];
+ uptr GetSizeClass(const void *p) {
+ return possible_regions[ComputeRegionId(reinterpret_cast<uptr>(p))];
}
- void *GetBlockBegin(void *p) {
+ void *GetBlockBegin(const void *p) {
CHECK(PointerIsMine(p));
uptr mem = reinterpret_cast<uptr>(p);
uptr beg = ComputeRegionBeg(mem);
@@ -650,16 +703,15 @@ class SizeClassAllocator32 {
// No need to lock here.
uptr res = 0;
for (uptr i = 0; i < kNumPossibleRegions; i++)
- if (state_->possible_regions[i])
+ if (possible_regions[i])
res += kRegionSize;
return res;
}
void TestOnlyUnmap() {
for (uptr i = 0; i < kNumPossibleRegions; i++)
- if (state_->possible_regions[i])
+ if (possible_regions[i])
UnmapWithCallback((i * kRegionSize), kRegionSize);
- UnmapWithCallback(reinterpret_cast<uptr>(state_), sizeof(State));
}
// ForceLock() and ForceUnlock() are needed to implement Darwin malloc zone
@@ -676,6 +728,23 @@ class SizeClassAllocator32 {
}
}
+ // Iterate over all existing chunks.
+ // The allocator must be locked when calling this function.
+ void ForEachChunk(ForEachChunkCallback callback, void *arg) {
+ for (uptr region = 0; region < kNumPossibleRegions; region++)
+ if (possible_regions[region]) {
+ uptr chunk_size = SizeClassMap::Size(possible_regions[region]);
+ uptr max_chunks_in_region = kRegionSize / (chunk_size + kMetadataSize);
+ uptr region_beg = region * kRegionSize;
+ for (uptr chunk = region_beg;
+ chunk < region_beg + max_chunks_in_region * chunk_size;
+ chunk += chunk_size) {
+ // Too slow: CHECK_EQ((void *)chunk, GetBlockBegin((void *)chunk));
+ callback(chunk, arg);
+ }
+ }
+ }
+
void PrintStats() {
}
@@ -683,7 +752,6 @@ class SizeClassAllocator32 {
static const uptr kNumClasses = SizeClassMap::kNumClasses;
private:
- static const uptr kRegionSizeLog = SANITIZER_WORDSIZE == 64 ? 24 : 20;
static const uptr kRegionSize = 1 << kRegionSizeLog;
static const uptr kNumPossibleRegions = kSpaceSize / kRegionSize;
@@ -711,14 +779,13 @@ class SizeClassAllocator32 {
MapUnmapCallback().OnMap(res, kRegionSize);
stat->Add(AllocatorStatMmapped, kRegionSize);
CHECK_EQ(0U, (res & (kRegionSize - 1)));
- CHECK_EQ(0U, state_->possible_regions[ComputeRegionId(res)]);
- state_->possible_regions[ComputeRegionId(res)] = class_id;
+ possible_regions.set(ComputeRegionId(res), static_cast<u8>(class_id));
return res;
}
SizeClassInfo *GetSizeClassInfo(uptr class_id) {
CHECK_LT(class_id, kNumClasses);
- return &state_->size_class_info_array[class_id];
+ return &size_class_info_array[class_id];
}
void PopulateFreeList(AllocatorStats *stat, AllocatorCache *c,
@@ -730,7 +797,7 @@ class SizeClassAllocator32 {
Batch *b = 0;
for (uptr i = reg; i < reg + n_chunks * size; i += size) {
if (b == 0) {
- if (class_id < SizeClassMap::kMinBatchClass)
+ if (SizeClassMap::SizeClassRequiresSeparateTransferBatch(class_id))
b = (Batch*)c->Allocate(this, SizeClassMap::ClassID(sizeof(Batch)));
else
b = (Batch*)i;
@@ -738,19 +805,19 @@ class SizeClassAllocator32 {
}
b->batch[b->count++] = (void*)i;
if (b->count == max_count) {
+ CHECK_GT(b->count, 0);
sci->free_list.push_back(b);
b = 0;
}
}
- if (b)
+ if (b) {
+ CHECK_GT(b->count, 0);
sci->free_list.push_back(b);
+ }
}
- struct State {
- u8 possible_regions[kNumPossibleRegions];
- SizeClassInfo size_class_info_array[kNumClasses];
- };
- State *state_;
+ ByteMap possible_regions;
+ SizeClassInfo size_class_info_array[kNumClasses];
};
// Objects of this type should be used as local caches for SizeClassAllocator64
@@ -788,8 +855,12 @@ struct SizeClassAllocatorLocalCache {
void Deallocate(SizeClassAllocator *allocator, uptr class_id, void *p) {
CHECK_NE(class_id, 0UL);
CHECK_LT(class_id, kNumClasses);
+ // If the first allocator call on a new thread is a deallocation, then
+ // max_count will be zero, leading to check failure.
+ InitCache();
stats_.Add(AllocatorStatFreed, SizeClassMap::Size(class_id));
PerClass *c = &per_class_[class_id];
+ CHECK_NE(c->max_count, 0UL);
if (UNLIKELY(c->count == c->max_count))
Drain(allocator, class_id);
c->batch[c->count++] = p;
@@ -815,7 +886,7 @@ struct SizeClassAllocatorLocalCache {
AllocatorStats stats_;
void InitCache() {
- if (per_class_[0].max_count)
+ if (per_class_[1].max_count)
return;
for (uptr i = 0; i < kNumClasses; i++) {
PerClass *c = &per_class_[i];
@@ -831,7 +902,7 @@ struct SizeClassAllocatorLocalCache {
for (uptr i = 0; i < b->count; i++)
c->batch[i] = b->batch[i];
c->count = b->count;
- if (class_id < SizeClassMap::kMinBatchClass)
+ if (SizeClassMap::SizeClassRequiresSeparateTransferBatch(class_id))
Deallocate(allocator, SizeClassMap::ClassID(sizeof(Batch)), b);
}
@@ -839,7 +910,7 @@ struct SizeClassAllocatorLocalCache {
InitCache();
PerClass *c = &per_class_[class_id];
Batch *b;
- if (class_id < SizeClassMap::kMinBatchClass)
+ if (SizeClassMap::SizeClassRequiresSeparateTransferBatch(class_id))
b = (Batch*)Allocate(allocator, SizeClassMap::ClassID(sizeof(Batch)));
else
b = (Batch*)c->batch[0];
@@ -850,6 +921,7 @@ struct SizeClassAllocatorLocalCache {
}
b->count = cnt;
c->count -= cnt;
+ CHECK_GT(b->count, 0);
allocator->DeallocateBatch(&stats_, class_id, b);
}
};
@@ -870,7 +942,7 @@ class LargeMmapAllocator {
uptr map_size = RoundUpMapSize(size);
if (alignment > page_size_)
map_size += alignment;
- if (map_size < size) return 0; // Overflow.
+ if (map_size < size) return AllocatorReturnNull(); // Overflow.
uptr map_beg = reinterpret_cast<uptr>(
MmapOrDie(map_size, "LargeMmapAllocator"));
MapUnmapCallback().OnMap(map_beg, map_size);
@@ -889,6 +961,7 @@ class LargeMmapAllocator {
{
SpinMutexLock l(&mutex_);
uptr idx = n_chunks_++;
+ chunks_sorted_ = false;
CHECK_LT(idx, kMaxNumChunks);
h->chunk_idx = idx;
chunks_[idx] = h;
@@ -912,6 +985,7 @@ class LargeMmapAllocator {
chunks_[idx] = chunks_[n_chunks_ - 1];
chunks_[idx]->chunk_idx = idx;
n_chunks_--;
+ chunks_sorted_ = false;
stats.n_frees++;
stats.currently_allocated -= h->map_size;
stat->Add(AllocatorStatFreed, h->map_size);
@@ -932,7 +1006,7 @@ class LargeMmapAllocator {
return res;
}
- bool PointerIsMine(void *p) {
+ bool PointerIsMine(const void *p) {
return GetBlockBegin(p) != 0;
}
@@ -941,13 +1015,16 @@ class LargeMmapAllocator {
}
// At least page_size_/2 metadata bytes is available.
- void *GetMetaData(void *p) {
+ void *GetMetaData(const void *p) {
// Too slow: CHECK_EQ(p, GetBlockBegin(p));
- CHECK(IsAligned(reinterpret_cast<uptr>(p), page_size_));
+ if (!IsAligned(reinterpret_cast<uptr>(p), page_size_)) {
+ Printf("%s: bad pointer %p\n", SanitizerToolName, p);
+ CHECK(IsAligned(reinterpret_cast<uptr>(p), page_size_));
+ }
return GetHeader(p) + 1;
}
- void *GetBlockBegin(void *ptr) {
+ void *GetBlockBegin(const void *ptr) {
uptr p = reinterpret_cast<uptr>(ptr);
SpinMutexLock l(&mutex_);
uptr nearest_chunk = 0;
@@ -964,7 +1041,49 @@ class LargeMmapAllocator {
CHECK_GE(nearest_chunk, h->map_beg);
CHECK_LT(nearest_chunk, h->map_beg + h->map_size);
CHECK_LE(nearest_chunk, p);
- if (h->map_beg + h->map_size < p)
+ if (h->map_beg + h->map_size <= p)
+ return 0;
+ return GetUser(h);
+ }
+
+ // This function does the same as GetBlockBegin, but is much faster.
+ // Must be called with the allocator locked.
+ void *GetBlockBeginFastLocked(void *ptr) {
+ uptr p = reinterpret_cast<uptr>(ptr);
+ uptr n = n_chunks_;
+ if (!n) return 0;
+ if (!chunks_sorted_) {
+ // Do one-time sort. chunks_sorted_ is reset in Allocate/Deallocate.
+ SortArray(reinterpret_cast<uptr*>(chunks_), n);
+ for (uptr i = 0; i < n; i++)
+ chunks_[i]->chunk_idx = i;
+ chunks_sorted_ = true;
+ min_mmap_ = reinterpret_cast<uptr>(chunks_[0]);
+ max_mmap_ = reinterpret_cast<uptr>(chunks_[n - 1]) +
+ chunks_[n - 1]->map_size;
+ }
+ if (p < min_mmap_ || p >= max_mmap_)
+ return 0;
+ uptr beg = 0, end = n - 1;
+ // This loop is a log(n) lower_bound. It does not check for the exact match
+ // to avoid expensive cache-thrashing loads.
+ while (end - beg >= 2) {
+ uptr mid = (beg + end) / 2; // Invariant: mid >= beg + 1
+ if (p < reinterpret_cast<uptr>(chunks_[mid]))
+ end = mid - 1; // We are not interested in chunks_[mid].
+ else
+ beg = mid; // chunks_[mid] may still be what we want.
+ }
+
+ if (beg < end) {
+ CHECK_EQ(beg + 1, end);
+ // There are 2 chunks left, choose one.
+ if (p >= reinterpret_cast<uptr>(chunks_[end]))
+ beg = end;
+ }
+
+ Header *h = chunks_[beg];
+ if (h->map_beg + h->map_size <= p || p < h->map_beg)
return 0;
return GetUser(h);
}
@@ -992,6 +1111,13 @@ class LargeMmapAllocator {
mutex_.Unlock();
}
+ // Iterate over all existing chunks.
+ // The allocator must be locked when calling this function.
+ void ForEachChunk(ForEachChunkCallback callback, void *arg) {
+ for (uptr i = 0; i < n_chunks_; i++)
+ callback(reinterpret_cast<uptr>(GetUser(chunks_[i])), arg);
+ }
+
private:
static const int kMaxNumChunks = 1 << FIRST_32_SECOND_64(15, 18);
struct Header {
@@ -1002,13 +1128,15 @@ class LargeMmapAllocator {
};
Header *GetHeader(uptr p) {
- CHECK_EQ(p % page_size_, 0);
+ CHECK(IsAligned(p, page_size_));
return reinterpret_cast<Header*>(p - page_size_);
}
- Header *GetHeader(void *p) { return GetHeader(reinterpret_cast<uptr>(p)); }
+ Header *GetHeader(const void *p) {
+ return GetHeader(reinterpret_cast<uptr>(p));
+ }
void *GetUser(Header *h) {
- CHECK_EQ((uptr)h % page_size_, 0);
+ CHECK(IsAligned((uptr)h, page_size_));
return reinterpret_cast<void*>(reinterpret_cast<uptr>(h) + page_size_);
}
@@ -1019,6 +1147,8 @@ class LargeMmapAllocator {
uptr page_size_;
Header *chunks_[kMaxNumChunks];
uptr n_chunks_;
+ uptr min_mmap_, max_mmap_;
+ bool chunks_sorted_;
struct Stats {
uptr n_allocs, n_frees, currently_allocated, max_allocated, by_size_log[64];
} stats;
@@ -1047,7 +1177,7 @@ class CombinedAllocator {
if (size == 0)
size = 1;
if (size + alignment < size)
- return 0;
+ return AllocatorReturnNull();
if (alignment > 8)
size = RoundUpTo(size, alignment);
void *res;
@@ -1098,18 +1228,26 @@ class CombinedAllocator {
return primary_.PointerIsMine(p);
}
- void *GetMetaData(void *p) {
+ void *GetMetaData(const void *p) {
if (primary_.PointerIsMine(p))
return primary_.GetMetaData(p);
return secondary_.GetMetaData(p);
}
- void *GetBlockBegin(void *p) {
+ void *GetBlockBegin(const void *p) {
if (primary_.PointerIsMine(p))
return primary_.GetBlockBegin(p);
return secondary_.GetBlockBegin(p);
}
+ // This function does the same as GetBlockBegin, but is much faster.
+ // Must be called with the allocator locked.
+ void *GetBlockBeginFastLocked(void *p) {
+ if (primary_.PointerIsMine(p))
+ return primary_.GetBlockBegin(p);
+ return secondary_.GetBlockBeginFastLocked(p);
+ }
+
uptr GetActuallyAllocatedSize(void *p) {
if (primary_.PointerIsMine(p))
return primary_.GetActuallyAllocatedSize(p);
@@ -1155,6 +1293,13 @@ class CombinedAllocator {
primary_.ForceUnlock();
}
+ // Iterate over all existing chunks.
+ // The allocator must be locked when calling this function.
+ void ForEachChunk(ForEachChunkCallback callback, void *arg) {
+ primary_.ForEachChunk(callback, arg);
+ secondary_.ForEachChunk(callback, arg);
+ }
+
private:
PrimaryAllocator primary_;
SecondaryAllocator secondary_;
diff --git a/libsanitizer/sanitizer_common/sanitizer_allocator_internal.h b/libsanitizer/sanitizer_common/sanitizer_allocator_internal.h
new file mode 100644
index 00000000000..c033b96e4dd
--- /dev/null
+++ b/libsanitizer/sanitizer_common/sanitizer_allocator_internal.h
@@ -0,0 +1,62 @@
+//===-- sanitizer_allocator_internal.h -------------------------- C++ -----===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This allocator is used inside run-times.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_ALLOCATOR_INTERNAL_H
+#define SANITIZER_ALLOCATOR_INTERNAL_H
+
+#include "sanitizer_allocator.h"
+#include "sanitizer_internal_defs.h"
+
+namespace __sanitizer {
+
+// FIXME: Check if we may use even more compact size class map for internal
+// purposes.
+typedef CompactSizeClassMap InternalSizeClassMap;
+
+static const uptr kInternalAllocatorSpace = 0;
+#if SANITIZER_WORDSIZE == 32
+static const u64 kInternalAllocatorSize = (1ULL << 32);
+static const uptr kInternalAllocatorRegionSizeLog = 20;
+#else
+static const u64 kInternalAllocatorSize = (1ULL << 47);
+static const uptr kInternalAllocatorRegionSizeLog = 24;
+#endif
+static const uptr kInternalAllocatorFlatByteMapSize =
+ kInternalAllocatorSize >> kInternalAllocatorRegionSizeLog;
+typedef SizeClassAllocator32<
+ kInternalAllocatorSpace, kInternalAllocatorSize, 16, InternalSizeClassMap,
+ kInternalAllocatorRegionSizeLog,
+ FlatByteMap<kInternalAllocatorFlatByteMapSize> > PrimaryInternalAllocator;
+
+typedef SizeClassAllocatorLocalCache<PrimaryInternalAllocator>
+ InternalAllocatorCache;
+
+// We don't want our internal allocator to do any map/unmap operations.
+struct CrashOnMapUnmap {
+ void OnMap(uptr p, uptr size) const {
+ RAW_CHECK_MSG(0, "Unexpected mmap in InternalAllocator!");
+ }
+ void OnUnmap(uptr p, uptr size) const {
+ RAW_CHECK_MSG(0, "Unexpected munmap in InternalAllocator!");
+ }
+};
+
+typedef CombinedAllocator<PrimaryInternalAllocator, InternalAllocatorCache,
+ LargeMmapAllocator<CrashOnMapUnmap> >
+ InternalAllocator;
+
+void *InternalAlloc(uptr size, InternalAllocatorCache *cache = 0);
+void InternalFree(void *p, InternalAllocatorCache *cache = 0);
+InternalAllocator *internal_allocator();
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_ALLOCATOR_INTERNAL_H
diff --git a/libsanitizer/sanitizer_common/sanitizer_atomic_clang.h b/libsanitizer/sanitizer_common/sanitizer_atomic_clang.h
index bb4611d51e6..88819e32a73 100644
--- a/libsanitizer/sanitizer_common/sanitizer_atomic_clang.h
+++ b/libsanitizer/sanitizer_common/sanitizer_atomic_clang.h
@@ -39,7 +39,17 @@ INLINE typename T::Type atomic_load(
| memory_order_acquire | memory_order_seq_cst));
DCHECK(!((uptr)a % sizeof(*a)));
typename T::Type v;
- // FIXME(dvyukov): 64-bit load is not atomic on 32-bits.
+ // FIXME:
+ // 64-bit atomic operations are not atomic on 32-bit platforms.
+ // The implementation lacks necessary memory fences on ARM/PPC.
+ // We would like to use compiler builtin atomic operations,
+ // but they are mostly broken:
+ // - they lead to vastly inefficient code generation
+ // (http://llvm.org/bugs/show_bug.cgi?id=17281)
+ // - 64-bit atomic operations are not implemented on x86_32
+ // (http://llvm.org/bugs/show_bug.cgi?id=15034)
+ // - they are not implemented on ARM
+ // error: undefined reference to '__atomic_load_4'
if (mo == memory_order_relaxed) {
v = a->val_dont_use;
} else {
@@ -55,7 +65,6 @@ INLINE void atomic_store(volatile T *a, typename T::Type v, memory_order mo) {
DCHECK(mo & (memory_order_relaxed | memory_order_release
| memory_order_seq_cst));
DCHECK(!((uptr)a % sizeof(*a)));
- // FIXME(dvyukov): 64-bit store is not atomic on 32-bits.
if (mo == memory_order_relaxed) {
a->val_dont_use = v;
} else {
@@ -111,12 +120,14 @@ INLINE bool atomic_compare_exchange_strong(volatile T *a,
template<typename T>
INLINE bool atomic_compare_exchange_weak(volatile T *a,
- typename T::Type *cmp,
- typename T::Type xchg,
- memory_order mo) {
+ typename T::Type *cmp,
+ typename T::Type xchg,
+ memory_order mo) {
return atomic_compare_exchange_strong(a, cmp, xchg, mo);
}
} // namespace __sanitizer
+#undef ATOMIC_ORDER
+
#endif // SANITIZER_ATOMIC_CLANG_H
diff --git a/libsanitizer/sanitizer_common/sanitizer_atomic_msvc.h b/libsanitizer/sanitizer_common/sanitizer_atomic_msvc.h
index 919e24f3b11..dac7c19199b 100644
--- a/libsanitizer/sanitizer_common/sanitizer_atomic_msvc.h
+++ b/libsanitizer/sanitizer_common/sanitizer_atomic_msvc.h
@@ -132,6 +132,27 @@ INLINE u16 atomic_exchange(volatile atomic_uint16_t *a,
return v;
}
+INLINE bool atomic_compare_exchange_strong(volatile atomic_uint8_t *a,
+ u8 *cmp,
+ u8 xchgv,
+ memory_order mo) {
+ (void)mo;
+ DCHECK(!((uptr)a % sizeof(*a)));
+ u8 cmpv = *cmp;
+ u8 prev;
+ __asm {
+ mov al, cmpv
+ mov ecx, a
+ mov dl, xchgv
+ lock cmpxchg [ecx], dl
+ mov prev, al
+ }
+ if (prev == cmpv)
+ return true;
+ *cmp = prev;
+ return false;
+}
+
INLINE bool atomic_compare_exchange_strong(volatile atomic_uintptr_t *a,
uptr *cmp,
uptr xchg,
@@ -147,9 +168,9 @@ INLINE bool atomic_compare_exchange_strong(volatile atomic_uintptr_t *a,
template<typename T>
INLINE bool atomic_compare_exchange_weak(volatile T *a,
- typename T::Type *cmp,
- typename T::Type xchg,
- memory_order mo) {
+ typename T::Type *cmp,
+ typename T::Type xchg,
+ memory_order mo) {
return atomic_compare_exchange_strong(a, cmp, xchg, mo);
}
diff --git a/libsanitizer/sanitizer_common/sanitizer_common.cc b/libsanitizer/sanitizer_common/sanitizer_common.cc
index f8d2d0e3fe5..f689df421aa 100644
--- a/libsanitizer/sanitizer_common/sanitizer_common.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_common.cc
@@ -15,6 +15,7 @@
namespace __sanitizer {
const char *SanitizerToolName = "SanitizerTool";
+uptr SanitizerVerbosity = 0;
uptr GetPageSizeCached() {
static uptr PageSize;
@@ -23,22 +24,29 @@ uptr GetPageSizeCached() {
return PageSize;
}
-static bool log_to_file = false; // Set to true by __sanitizer_set_report_path
// By default, dump to stderr. If |log_to_file| is true and |report_fd_pid|
// isn't equal to the current PID, try to obtain file descriptor by opening
// file "report_path_prefix.<PID>".
-static fd_t report_fd = kStderrFd;
-static char report_path_prefix[4096]; // Set via __sanitizer_set_report_path.
+fd_t report_fd = kStderrFd;
+
+// Set via __sanitizer_set_report_path.
+bool log_to_file = false;
+char report_path_prefix[sizeof(report_path_prefix)];
+
// PID of process that opened |report_fd|. If a fork() occurs, the PID of the
// child thread will be different from |report_fd_pid|.
-static int report_fd_pid = 0;
+uptr report_fd_pid = 0;
-static void (*DieCallback)(void);
-void SetDieCallback(void (*callback)(void)) {
+static DieCallbackType DieCallback;
+void SetDieCallback(DieCallbackType callback) {
DieCallback = callback;
}
+DieCallbackType GetDieCallback() {
+ return DieCallback;
+}
+
void NORETURN Die() {
if (DieCallback) {
DieCallback();
@@ -61,41 +69,6 @@ void NORETURN CheckFailed(const char *file, int line, const char *cond,
Die();
}
-static void MaybeOpenReportFile() {
- if (!log_to_file || (report_fd_pid == GetPid())) return;
- InternalScopedBuffer<char> report_path_full(4096);
- internal_snprintf(report_path_full.data(), report_path_full.size(),
- "%s.%d", report_path_prefix, GetPid());
- fd_t fd = OpenFile(report_path_full.data(), true);
- if (fd == kInvalidFd) {
- report_fd = kStderrFd;
- log_to_file = false;
- Report("ERROR: Can't open file: %s\n", report_path_full.data());
- Die();
- }
- if (report_fd != kInvalidFd) {
- // We're in the child. Close the parent's log.
- internal_close(report_fd);
- }
- report_fd = fd;
- report_fd_pid = GetPid();
-}
-
-bool PrintsToTty() {
- MaybeOpenReportFile();
- return internal_isatty(report_fd);
-}
-
-void RawWrite(const char *buffer) {
- static const char *kRawWriteError = "RawWrite can't output requested buffer!";
- uptr length = (uptr)internal_strlen(buffer);
- MaybeOpenReportFile();
- if (length != internal_write(report_fd, buffer, length)) {
- internal_write(report_fd, kRawWriteError, internal_strlen(kRawWriteError));
- Die();
- }
-}
-
uptr ReadFileToBuffer(const char *file_name, char **buff,
uptr *buff_size, uptr max_len) {
uptr PageSize = GetPageSizeCached();
@@ -105,8 +78,9 @@ uptr ReadFileToBuffer(const char *file_name, char **buff,
*buff_size = 0;
// The files we usually open are not seekable, so try different buffer sizes.
for (uptr size = kMinFileLen; size <= max_len; size *= 2) {
- fd_t fd = OpenFile(file_name, /*write*/ false);
- if (fd == kInvalidFd) return 0;
+ uptr openrv = OpenFile(file_name, /*write*/ false);
+ if (internal_iserror(openrv)) return 0;
+ fd_t fd = openrv;
UnmapOrDie(*buff, *buff_size);
*buff = (char*)MmapOrDie(size, __FUNCTION__);
*buff_size = size;
@@ -128,45 +102,15 @@ uptr ReadFileToBuffer(const char *file_name, char **buff,
return read_len;
}
-// We don't want to use std::sort to avoid including <algorithm>, as
-// we may end up with two implementation of std::sort - one in instrumented
-// code, and the other in runtime.
-// qsort() from stdlib won't work as it calls malloc(), which results
-// in deadlock in ASan allocator.
-// We re-implement in-place sorting w/o recursion as straightforward heapsort.
+typedef bool UptrComparisonFunction(const uptr &a, const uptr &b);
+
+template<class T>
+static inline bool CompareLess(const T &a, const T &b) {
+ return a < b;
+}
+
void SortArray(uptr *array, uptr size) {
- if (size < 2)
- return;
- // Stage 1: insert elements to the heap.
- for (uptr i = 1; i < size; i++) {
- uptr j, p;
- for (j = i; j > 0; j = p) {
- p = (j - 1) / 2;
- if (array[j] > array[p])
- Swap(array[j], array[p]);
- else
- break;
- }
- }
- // Stage 2: swap largest element with the last one,
- // and sink the new top.
- for (uptr i = size - 1; i > 0; i--) {
- Swap(array[0], array[i]);
- uptr j, max_ind;
- for (j = 0; j < i; j = max_ind) {
- uptr left = 2 * j + 1;
- uptr right = 2 * j + 2;
- max_ind = j;
- if (left < i && array[left] > array[max_ind])
- max_ind = left;
- if (right < i && array[right] > array[max_ind])
- max_ind = right;
- if (max_ind != j)
- Swap(array[j], array[max_ind]);
- else
- break;
- }
- }
+ InternalSort<uptr*, UptrComparisonFunction>(&array, size, CompareLess);
}
// We want to map a chunk of address space aligned to 'alignment'.
@@ -200,6 +144,27 @@ void ReportErrorSummary(const char *error_type, const char *file,
__sanitizer_report_error_summary(buff.data());
}
+LoadedModule::LoadedModule(const char *module_name, uptr base_address) {
+ full_name_ = internal_strdup(module_name);
+ base_address_ = base_address;
+ n_ranges_ = 0;
+}
+
+void LoadedModule::addAddressRange(uptr beg, uptr end) {
+ CHECK_LT(n_ranges_, kMaxNumberOfAddressRanges);
+ ranges_[n_ranges_].beg = beg;
+ ranges_[n_ranges_].end = end;
+ n_ranges_++;
+}
+
+bool LoadedModule::containsAddress(uptr address) const {
+ for (uptr i = 0; i < n_ranges_; i++) {
+ if (ranges_[i].beg <= address && address < ranges_[i].end)
+ return true;
+ }
+ return false;
+}
+
} // namespace __sanitizer
using namespace __sanitizer; // NOLINT
diff --git a/libsanitizer/sanitizer_common/sanitizer_common.h b/libsanitizer/sanitizer_common/sanitizer_common.h
index d2782b6c9dc..417f71f987c 100644
--- a/libsanitizer/sanitizer_common/sanitizer_common.h
+++ b/libsanitizer/sanitizer_common/sanitizer_common.h
@@ -15,6 +15,7 @@
#define SANITIZER_COMMON_H
#include "sanitizer_internal_defs.h"
+#include "sanitizer_libc.h"
#include "sanitizer_mutex.h"
namespace __sanitizer {
@@ -30,17 +31,22 @@ const uptr kCacheLineSize = 128;
const uptr kCacheLineSize = 64;
#endif
+const uptr kMaxPathLength = 512;
+
extern const char *SanitizerToolName; // Can be changed by the tool.
+extern uptr SanitizerVerbosity;
uptr GetPageSize();
uptr GetPageSizeCached();
uptr GetMmapGranularity();
+uptr GetMaxVirtualAddress();
// Threads
-int GetPid();
uptr GetTid();
uptr GetThreadSelf();
void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
uptr *stack_bottom);
+void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
+ uptr *tls_addr, uptr *tls_size);
// Memory management
void *MmapOrDie(uptr size, const char *mem_type);
@@ -54,10 +60,6 @@ void *MmapAlignedOrDie(uptr size, uptr alignment, const char *mem_type);
bool MemoryRangeIsAvailable(uptr range_start, uptr range_end);
void FlushUnneededShadowMemory(uptr addr, uptr size);
-// Internal allocator
-void *InternalAlloc(uptr size);
-void InternalFree(void *p);
-
// InternalScopedBuffer can be used instead of large stack arrays to
// keep frame size low.
// FIXME: use InternalAlloc instead of MmapOrDie once
@@ -103,13 +105,20 @@ void SetLowLevelAllocateCallback(LowLevelAllocateCallback callback);
// IO
void RawWrite(const char *buffer);
bool PrintsToTty();
+// Caching version of PrintsToTty(). Not thread-safe.
+bool PrintsToTtyCached();
void Printf(const char *format, ...);
void Report(const char *format, ...);
void SetPrintfAndReportCallback(void (*callback)(const char *));
// Can be used to prevent mixing error reports from different sanitizers.
extern StaticSpinMutex CommonSanitizerReportMutex;
+void MaybeOpenReportFile();
+extern fd_t report_fd;
+extern bool log_to_file;
+extern char report_path_prefix[4096];
+extern uptr report_fd_pid;
-fd_t OpenFile(const char *filename, bool write);
+uptr OpenFile(const char *filename, bool write);
// Opens the file 'file_name" and reads up to 'max_len' bytes.
// The resulting buffer is mmaped and stored in '*buff'.
// The size of the mmaped region is stored in '*buff_size',
@@ -126,23 +135,29 @@ void DisableCoreDumper();
void DumpProcessMap();
bool FileExists(const char *filename);
const char *GetEnv(const char *name);
+bool SetEnv(const char *name, const char *value);
const char *GetPwd();
+char *FindPathToBinary(const char *name);
u32 GetUid();
void ReExec();
bool StackSizeIsUnlimited();
void SetStackSizeLimitInBytes(uptr limit);
void PrepareForSandboxing();
+void InitTlsSize();
+uptr GetTlsSize();
+
// Other
void SleepForSeconds(int seconds);
void SleepForMillis(int millis);
+u64 NanoTime();
int Atexit(void (*function)(void));
void SortArray(uptr *array, uptr size);
// Exit
void NORETURN Abort();
void NORETURN Die();
-void NORETURN SANITIZER_INTERFACE_ATTRIBUTE
+void NORETURN
CheckFailed(const char *file, int line, const char *cond, u64 v1, u64 v2);
// Set the name of the current thread to 'name', return true on succees.
@@ -154,7 +169,9 @@ bool SanitizerGetThreadName(char *name, int max_len);
// Specific tools may override behavior of "Die" and "CheckFailed" functions
// to do tool-specific job.
-void SetDieCallback(void (*callback)(void));
+typedef void (*DieCallbackType)(void);
+void SetDieCallback(DieCallbackType);
+DieCallbackType GetDieCallback();
typedef void (*CheckFailedCallbackType)(const char *, int, const char *,
u64, u64);
void SetCheckFailedCallback(CheckFailedCallbackType callback);
@@ -166,7 +183,7 @@ void ReportErrorSummary(const char *error_type, const char *file,
int line, const char *function);
// Math
-#if defined(_WIN32) && !defined(__clang__)
+#if SANITIZER_WINDOWS && !defined(__clang__) && !defined(__GNUC__)
extern "C" {
unsigned char _BitScanForward(unsigned long *index, unsigned long mask); // NOLINT
unsigned char _BitScanReverse(unsigned long *index, unsigned long mask); // NOLINT
@@ -178,9 +195,9 @@ unsigned char _BitScanReverse64(unsigned long *index, unsigned __int64 mask); /
#endif
INLINE uptr MostSignificantSetBitIndex(uptr x) {
- CHECK(x != 0);
+ CHECK_NE(x, 0U);
unsigned long up; // NOLINT
-#if !defined(_WIN32) || defined(__clang__)
+#if !SANITIZER_WINDOWS || defined(__clang__) || defined(__GNUC__)
up = SANITIZER_WORDSIZE - 1 - __builtin_clzl(x);
#elif defined(_WIN64)
_BitScanReverse64(&up, x);
@@ -219,7 +236,7 @@ INLINE bool IsAligned(uptr a, uptr alignment) {
INLINE uptr Log2(uptr x) {
CHECK(IsPowerOfTwo(x));
-#if !defined(_WIN32) || defined(__clang__)
+#if !SANITIZER_WINDOWS || defined(__clang__) || defined(__GNUC__)
return __builtin_ctzl(x);
#elif defined(_WIN64)
unsigned long ret; // NOLINT
@@ -260,6 +277,160 @@ INLINE int ToLower(int c) {
# define FIRST_32_SECOND_64(a, b) (a)
#endif
+// A low-level vector based on mmap. May incur a significant memory overhead for
+// small vectors.
+// WARNING: The current implementation supports only POD types.
+template<typename T>
+class InternalMmapVector {
+ public:
+ explicit InternalMmapVector(uptr initial_capacity) {
+ CHECK_GT(initial_capacity, 0);
+ capacity_ = initial_capacity;
+ size_ = 0;
+ data_ = (T *)MmapOrDie(capacity_ * sizeof(T), "InternalMmapVector");
+ }
+ ~InternalMmapVector() {
+ UnmapOrDie(data_, capacity_ * sizeof(T));
+ }
+ T &operator[](uptr i) {
+ CHECK_LT(i, size_);
+ return data_[i];
+ }
+ const T &operator[](uptr i) const {
+ CHECK_LT(i, size_);
+ return data_[i];
+ }
+ void push_back(const T &element) {
+ CHECK_LE(size_, capacity_);
+ if (size_ == capacity_) {
+ uptr new_capacity = RoundUpToPowerOfTwo(size_ + 1);
+ Resize(new_capacity);
+ }
+ data_[size_++] = element;
+ }
+ T &back() {
+ CHECK_GT(size_, 0);
+ return data_[size_ - 1];
+ }
+ void pop_back() {
+ CHECK_GT(size_, 0);
+ size_--;
+ }
+ uptr size() const {
+ return size_;
+ }
+ const T *data() const {
+ return data_;
+ }
+ uptr capacity() const {
+ return capacity_;
+ }
+
+ private:
+ void Resize(uptr new_capacity) {
+ CHECK_GT(new_capacity, 0);
+ CHECK_LE(size_, new_capacity);
+ T *new_data = (T *)MmapOrDie(new_capacity * sizeof(T),
+ "InternalMmapVector");
+ internal_memcpy(new_data, data_, size_ * sizeof(T));
+ T *old_data = data_;
+ data_ = new_data;
+ UnmapOrDie(old_data, capacity_ * sizeof(T));
+ capacity_ = new_capacity;
+ }
+ // Disallow evil constructors.
+ InternalMmapVector(const InternalMmapVector&);
+ void operator=(const InternalMmapVector&);
+
+ T *data_;
+ uptr capacity_;
+ uptr size_;
+};
+
+// HeapSort for arrays and InternalMmapVector.
+template<class Container, class Compare>
+void InternalSort(Container *v, uptr size, Compare comp) {
+ if (size < 2)
+ return;
+ // Stage 1: insert elements to the heap.
+ for (uptr i = 1; i < size; i++) {
+ uptr j, p;
+ for (j = i; j > 0; j = p) {
+ p = (j - 1) / 2;
+ if (comp((*v)[p], (*v)[j]))
+ Swap((*v)[j], (*v)[p]);
+ else
+ break;
+ }
+ }
+ // Stage 2: swap largest element with the last one,
+ // and sink the new top.
+ for (uptr i = size - 1; i > 0; i--) {
+ Swap((*v)[0], (*v)[i]);
+ uptr j, max_ind;
+ for (j = 0; j < i; j = max_ind) {
+ uptr left = 2 * j + 1;
+ uptr right = 2 * j + 2;
+ max_ind = j;
+ if (left < i && comp((*v)[max_ind], (*v)[left]))
+ max_ind = left;
+ if (right < i && comp((*v)[max_ind], (*v)[right]))
+ max_ind = right;
+ if (max_ind != j)
+ Swap((*v)[j], (*v)[max_ind]);
+ else
+ break;
+ }
+ }
+}
+
+template<class Container, class Value, class Compare>
+uptr InternalBinarySearch(const Container &v, uptr first, uptr last,
+ const Value &val, Compare comp) {
+ uptr not_found = last + 1;
+ while (last >= first) {
+ uptr mid = (first + last) / 2;
+ if (comp(v[mid], val))
+ first = mid + 1;
+ else if (comp(val, v[mid]))
+ last = mid - 1;
+ else
+ return mid;
+ }
+ return not_found;
+}
+
+// Represents a binary loaded into virtual memory (e.g. this can be an
+// executable or a shared object).
+class LoadedModule {
+ public:
+ LoadedModule(const char *module_name, uptr base_address);
+ void addAddressRange(uptr beg, uptr end);
+ bool containsAddress(uptr address) const;
+
+ const char *full_name() const { return full_name_; }
+ uptr base_address() const { return base_address_; }
+
+ private:
+ struct AddressRange {
+ uptr beg;
+ uptr end;
+ };
+ char *full_name_;
+ uptr base_address_;
+ static const uptr kMaxNumberOfAddressRanges = 6;
+ AddressRange ranges_[kMaxNumberOfAddressRanges];
+ uptr n_ranges_;
+};
+
+// OS-dependent function that fills array with descriptions of at most
+// "max_modules" currently loaded modules. Returns the number of
+// initialized modules. If filter is nonzero, ignores modules for which
+// filter(full_name) is false.
+typedef bool (*string_predicate_t)(const char *);
+uptr GetListOfModules(LoadedModule *modules, uptr max_modules,
+ string_predicate_t filter);
+
} // namespace __sanitizer
#endif // SANITIZER_COMMON_H
diff --git a/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc b/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc
index af27603ebdd..17ef72e0c98 100644
--- a/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc
+++ b/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc
@@ -22,10 +22,157 @@
#include <stdarg.h>
-#ifdef _WIN32
+#if SANITIZER_WINDOWS
#define va_copy(dst, src) ((dst) = (src))
#endif // _WIN32
+#if SANITIZER_INTERCEPT_STRCMP
+static inline int CharCmpX(unsigned char c1, unsigned char c2) {
+ return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1;
+}
+
+INTERCEPTOR(int, strcmp, const char *s1, const char *s2) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, strcmp, s1, s2);
+ unsigned char c1, c2;
+ uptr i;
+ for (i = 0; ; i++) {
+ c1 = (unsigned char)s1[i];
+ c2 = (unsigned char)s2[i];
+ if (c1 != c2 || c1 == '\0') break;
+ }
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, s1, i + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, i + 1);
+ return CharCmpX(c1, c2);
+}
+
+INTERCEPTOR(int, strncmp, const char *s1, const char *s2, uptr size) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, strncmp, s1, s2, size);
+ unsigned char c1 = 0, c2 = 0;
+ uptr i;
+ for (i = 0; i < size; i++) {
+ c1 = (unsigned char)s1[i];
+ c2 = (unsigned char)s2[i];
+ if (c1 != c2 || c1 == '\0') break;
+ }
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, s1, Min(i + 1, size));
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, Min(i + 1, size));
+ return CharCmpX(c1, c2);
+}
+
+#define INIT_STRCMP INTERCEPT_FUNCTION(strcmp)
+#define INIT_STRNCMP INTERCEPT_FUNCTION(strncmp)
+#else
+#define INIT_STRCMP
+#define INIT_STRNCMP
+#endif
+
+#if SANITIZER_INTERCEPT_STRCASECMP
+static inline int CharCaseCmp(unsigned char c1, unsigned char c2) {
+ int c1_low = ToLower(c1);
+ int c2_low = ToLower(c2);
+ return c1_low - c2_low;
+}
+
+INTERCEPTOR(int, strcasecmp, const char *s1, const char *s2) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, strcasecmp, s1, s2);
+ unsigned char c1 = 0, c2 = 0;
+ uptr i;
+ for (i = 0; ; i++) {
+ c1 = (unsigned char)s1[i];
+ c2 = (unsigned char)s2[i];
+ if (CharCaseCmp(c1, c2) != 0 || c1 == '\0')
+ break;
+ }
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, s1, i + 1);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, i + 1);
+ return CharCaseCmp(c1, c2);
+}
+
+INTERCEPTOR(int, strncasecmp, const char *s1, const char *s2, SIZE_T n) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, strncasecmp, s1, s2, n);
+ unsigned char c1 = 0, c2 = 0;
+ uptr i;
+ for (i = 0; i < n; i++) {
+ c1 = (unsigned char)s1[i];
+ c2 = (unsigned char)s2[i];
+ if (CharCaseCmp(c1, c2) != 0 || c1 == '\0')
+ break;
+ }
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, s1, Min(i + 1, n));
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, Min(i + 1, n));
+ return CharCaseCmp(c1, c2);
+}
+
+#define INIT_STRCASECMP INTERCEPT_FUNCTION(strcasecmp)
+#define INIT_STRNCASECMP INTERCEPT_FUNCTION(strncasecmp)
+#else
+#define INIT_STRCASECMP
+#define INIT_STRNCASECMP
+#endif
+
+#if SANITIZER_INTERCEPT_FREXP
+INTERCEPTOR(double, frexp, double x, int *exp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, frexp, x, exp);
+ double res = REAL(frexp)(x, exp);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, exp, sizeof(*exp));
+ return res;
+}
+
+#define INIT_FREXP INTERCEPT_FUNCTION(frexp);
+#else
+#define INIT_FREXP
+#endif // SANITIZER_INTERCEPT_FREXP
+
+#if SANITIZER_INTERCEPT_FREXPF_FREXPL
+INTERCEPTOR(float, frexpf, float x, int *exp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, frexpf, x, exp);
+ float res = REAL(frexpf)(x, exp);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, exp, sizeof(*exp));
+ return res;
+}
+
+INTERCEPTOR(long double, frexpl, long double x, int *exp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, frexpl, x, exp);
+ long double res = REAL(frexpl)(x, exp);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, exp, sizeof(*exp));
+ return res;
+}
+
+#define INIT_FREXPF_FREXPL \
+ INTERCEPT_FUNCTION(frexpf); \
+ INTERCEPT_FUNCTION(frexpl)
+#else
+#define INIT_FREXPF_FREXPL
+#endif // SANITIZER_INTERCEPT_FREXPF_FREXPL
+
+#if SI_NOT_WINDOWS
+static void write_iovec(void *ctx, struct __sanitizer_iovec *iovec,
+ SIZE_T iovlen, SIZE_T maxlen) {
+ for (SIZE_T i = 0; i < iovlen && maxlen; ++i) {
+ SSIZE_T sz = Min(iovec[i].iov_len, maxlen);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iovec[i].iov_base, sz);
+ maxlen -= sz;
+ }
+}
+
+static void read_iovec(void *ctx, struct __sanitizer_iovec *iovec,
+ SIZE_T iovlen, SIZE_T maxlen) {
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, iovec, sizeof(*iovec) * iovlen);
+ for (SIZE_T i = 0; i < iovlen && maxlen; ++i) {
+ SSIZE_T sz = Min(iovec[i].iov_len, maxlen);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, iovec[i].iov_base, sz);
+ maxlen -= sz;
+ }
+}
+#endif
+
#if SANITIZER_INTERCEPT_READ
INTERCEPTOR(SSIZE_T, read, int fd, void *ptr, SIZE_T count) {
void *ctx;
@@ -74,6 +221,51 @@ INTERCEPTOR(SSIZE_T, pread64, int fd, void *ptr, SIZE_T count, OFF64_T offset) {
#define INIT_PREAD64
#endif
+#if SANITIZER_INTERCEPT_READV
+INTERCEPTOR_WITH_SUFFIX(SSIZE_T, readv, int fd, __sanitizer_iovec *iov,
+ int iovcnt) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, readv, fd, iov, iovcnt);
+ SSIZE_T res = REAL(readv)(fd, iov, iovcnt);
+ if (res > 0) write_iovec(ctx, iov, iovcnt, res);
+ if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
+ return res;
+}
+#define INIT_READV INTERCEPT_FUNCTION(readv)
+#else
+#define INIT_READV
+#endif
+
+#if SANITIZER_INTERCEPT_PREADV
+INTERCEPTOR(SSIZE_T, preadv, int fd, __sanitizer_iovec *iov, int iovcnt,
+ OFF_T offset) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, preadv, fd, iov, iovcnt, offset);
+ SSIZE_T res = REAL(preadv)(fd, iov, iovcnt, offset);
+ if (res > 0) write_iovec(ctx, iov, iovcnt, res);
+ if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
+ return res;
+}
+#define INIT_PREADV INTERCEPT_FUNCTION(preadv)
+#else
+#define INIT_PREADV
+#endif
+
+#if SANITIZER_INTERCEPT_PREADV64
+INTERCEPTOR(SSIZE_T, preadv64, int fd, __sanitizer_iovec *iov, int iovcnt,
+ OFF64_T offset) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, preadv64, fd, iov, iovcnt, offset);
+ SSIZE_T res = REAL(preadv64)(fd, iov, iovcnt, offset);
+ if (res > 0) write_iovec(ctx, iov, iovcnt, res);
+ if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
+ return res;
+}
+#define INIT_PREADV64 INTERCEPT_FUNCTION(preadv64)
+#else
+#define INIT_PREADV64
+#endif
+
#if SANITIZER_INTERCEPT_WRITE
INTERCEPTOR(SSIZE_T, write, int fd, void *ptr, SIZE_T count) {
void *ctx;
@@ -81,6 +273,7 @@ INTERCEPTOR(SSIZE_T, write, int fd, void *ptr, SIZE_T count) {
if (fd >= 0)
COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
SSIZE_T res = REAL(write)(fd, ptr, count);
+ // FIXME: this check should be _before_ the call to REAL(write), not after
if (res > 0)
COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res);
return res;
@@ -123,6 +316,51 @@ INTERCEPTOR(SSIZE_T, pwrite64, int fd, void *ptr, OFF64_T count,
#define INIT_PWRITE64
#endif
+#if SANITIZER_INTERCEPT_WRITEV
+INTERCEPTOR_WITH_SUFFIX(SSIZE_T, writev, int fd, __sanitizer_iovec *iov,
+ int iovcnt) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, writev, fd, iov, iovcnt);
+ if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
+ SSIZE_T res = REAL(writev)(fd, iov, iovcnt);
+ if (res > 0) read_iovec(ctx, iov, iovcnt, res);
+ return res;
+}
+#define INIT_WRITEV INTERCEPT_FUNCTION(writev)
+#else
+#define INIT_WRITEV
+#endif
+
+#if SANITIZER_INTERCEPT_PWRITEV
+INTERCEPTOR(SSIZE_T, pwritev, int fd, __sanitizer_iovec *iov, int iovcnt,
+ OFF_T offset) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, pwritev, fd, iov, iovcnt, offset);
+ if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
+ SSIZE_T res = REAL(pwritev)(fd, iov, iovcnt, offset);
+ if (res > 0) read_iovec(ctx, iov, iovcnt, res);
+ return res;
+}
+#define INIT_PWRITEV INTERCEPT_FUNCTION(pwritev)
+#else
+#define INIT_PWRITEV
+#endif
+
+#if SANITIZER_INTERCEPT_PWRITEV64
+INTERCEPTOR(SSIZE_T, pwritev64, int fd, __sanitizer_iovec *iov, int iovcnt,
+ OFF64_T offset) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, pwritev64, fd, iov, iovcnt, offset);
+ if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
+ SSIZE_T res = REAL(pwritev64)(fd, iov, iovcnt, offset);
+ if (res > 0) read_iovec(ctx, iov, iovcnt, res);
+ return res;
+}
+#define INIT_PWRITEV64 INTERCEPT_FUNCTION(pwritev64)
+#else
+#define INIT_PWRITEV64
+#endif
+
#if SANITIZER_INTERCEPT_PRCTL
INTERCEPTOR(int, prctl, int option,
unsigned long arg2, unsigned long arg3, // NOLINT
@@ -144,6 +382,24 @@ INTERCEPTOR(int, prctl, int option,
#define INIT_PRCTL
#endif // SANITIZER_INTERCEPT_PRCTL
+
+#if SANITIZER_INTERCEPT_TIME
+INTERCEPTOR(unsigned long, time, unsigned long *t) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, time, t);
+ unsigned long res = REAL(time)(t);
+ if (t && res != (unsigned long)-1) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, t, sizeof(*t));
+ }
+ return res;
+}
+#define INIT_TIME \
+ INTERCEPT_FUNCTION(time);
+#else
+#define INIT_TIME
+#endif // SANITIZER_INTERCEPT_TIME
+
+
#if SANITIZER_INTERCEPT_LOCALTIME_AND_FRIENDS
INTERCEPTOR(void *, localtime, unsigned long *timep) {
void *ctx;
@@ -279,9 +535,9 @@ VSCANF_INTERCEPTOR_IMPL(__isoc99_vfscanf, false, stream, format, ap)
#define SCANF_INTERCEPTOR_IMPL(name, vname, ...) \
{ \
void *ctx; \
- COMMON_INTERCEPTOR_ENTER(ctx, name, __VA_ARGS__); \
va_list ap; \
va_start(ap, format); \
+ COMMON_INTERCEPTOR_ENTER(ctx, vname, __VA_ARGS__, ap); \
int res = vname(__VA_ARGS__, ap); \
va_end(ap); \
return res; \
@@ -307,31 +563,1659 @@ INTERCEPTOR(int, __isoc99_sscanf, const char *str, const char *format, ...)
SCANF_INTERCEPTOR_IMPL(__isoc99_sscanf, __isoc99_vsscanf, str, format)
#endif
-#define INIT_SCANF \
- INTERCEPT_FUNCTION(scanf); \
- INTERCEPT_FUNCTION(sscanf); \
- INTERCEPT_FUNCTION(fscanf); \
- INTERCEPT_FUNCTION(vscanf); \
- INTERCEPT_FUNCTION(vsscanf); \
- INTERCEPT_FUNCTION(vfscanf); \
- INTERCEPT_FUNCTION(__isoc99_scanf); \
- INTERCEPT_FUNCTION(__isoc99_sscanf); \
- INTERCEPT_FUNCTION(__isoc99_fscanf); \
- INTERCEPT_FUNCTION(__isoc99_vscanf); \
- INTERCEPT_FUNCTION(__isoc99_vsscanf); \
- INTERCEPT_FUNCTION(__isoc99_vfscanf);
+#endif
+#if SANITIZER_INTERCEPT_SCANF
+#define INIT_SCANF \
+ INTERCEPT_FUNCTION(scanf); \
+ INTERCEPT_FUNCTION(sscanf); \
+ INTERCEPT_FUNCTION(fscanf); \
+ INTERCEPT_FUNCTION(vscanf); \
+ INTERCEPT_FUNCTION(vsscanf); \
+ INTERCEPT_FUNCTION(vfscanf);
#else
#define INIT_SCANF
#endif
-#define SANITIZER_COMMON_INTERCEPTORS_INIT \
- INIT_READ; \
- INIT_PREAD; \
- INIT_PREAD64; \
- INIT_PRCTL; \
- INIT_WRITE; \
- INIT_PWRITE; \
- INIT_PWRITE64; \
- INIT_LOCALTIME_AND_FRIENDS; \
- INIT_SCANF;
+#if SANITIZER_INTERCEPT_ISOC99_SCANF
+#define INIT_ISOC99_SCANF \
+ INTERCEPT_FUNCTION(__isoc99_scanf); \
+ INTERCEPT_FUNCTION(__isoc99_sscanf); \
+ INTERCEPT_FUNCTION(__isoc99_fscanf); \
+ INTERCEPT_FUNCTION(__isoc99_vscanf); \
+ INTERCEPT_FUNCTION(__isoc99_vsscanf); \
+ INTERCEPT_FUNCTION(__isoc99_vfscanf);
+#else
+#define INIT_ISOC99_SCANF
+#endif
+
+#if SANITIZER_INTERCEPT_IOCTL
+#include "sanitizer_common_interceptors_ioctl.inc"
+INTERCEPTOR(int, ioctl, int d, unsigned request, void *arg) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, ioctl, d, request, arg);
+
+ CHECK(ioctl_initialized);
+
+ // Note: TSan does not use common flags, and they are zero-initialized.
+ // This effectively disables ioctl handling in TSan.
+ if (!common_flags()->handle_ioctl)
+ return REAL(ioctl)(d, request, arg);
+
+ const ioctl_desc *desc = ioctl_lookup(request);
+ if (!desc)
+ Printf("WARNING: unknown ioctl %x\n", request);
+
+ if (desc)
+ ioctl_common_pre(ctx, desc, d, request, arg);
+ int res = REAL(ioctl)(d, request, arg);
+ // FIXME: some ioctls have different return values for success and failure.
+ if (desc && res != -1)
+ ioctl_common_post(ctx, desc, res, d, request, arg);
+ return res;
+}
+#define INIT_IOCTL \
+ ioctl_init(); \
+ INTERCEPT_FUNCTION(ioctl);
+#else
+#define INIT_IOCTL
+#endif
+
+
+#if SANITIZER_INTERCEPT_GETPWNAM_AND_FRIENDS
+INTERCEPTOR(void *, getpwnam, const char *name) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getpwnam, name);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
+ void *res = REAL(getpwnam)(name);
+ if (res != 0)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_passwd_sz);
+ return res;
+}
+INTERCEPTOR(void *, getpwuid, u32 uid) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getpwuid, uid);
+ void *res = REAL(getpwuid)(uid);
+ if (res != 0)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_passwd_sz);
+ return res;
+}
+INTERCEPTOR(void *, getgrnam, const char *name) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getgrnam, name);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
+ void *res = REAL(getgrnam)(name);
+ if (res != 0)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_group_sz);
+ return res;
+}
+INTERCEPTOR(void *, getgrgid, u32 gid) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getgrgid, gid);
+ void *res = REAL(getgrgid)(gid);
+ if (res != 0)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_group_sz);
+ return res;
+}
+#define INIT_GETPWNAM_AND_FRIENDS \
+ INTERCEPT_FUNCTION(getpwnam); \
+ INTERCEPT_FUNCTION(getpwuid); \
+ INTERCEPT_FUNCTION(getgrnam); \
+ INTERCEPT_FUNCTION(getgrgid);
+#else
+#define INIT_GETPWNAM_AND_FRIENDS
+#endif
+
+
+#if SANITIZER_INTERCEPT_GETPWNAM_R_AND_FRIENDS
+INTERCEPTOR(int, getpwnam_r, const char *name, void *pwd,
+ char *buf, SIZE_T buflen, void **result) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getpwnam_r, name, pwd, buf, buflen, result);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
+ int res = REAL(getpwnam_r)(name, pwd, buf, buflen, result);
+ if (!res) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd, struct_passwd_sz);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
+ }
+ return res;
+}
+INTERCEPTOR(int, getpwuid_r, u32 uid, void *pwd,
+ char *buf, SIZE_T buflen, void **result) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getpwuid_r, uid, pwd, buf, buflen, result);
+ int res = REAL(getpwuid_r)(uid, pwd, buf, buflen, result);
+ if (!res) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd, struct_passwd_sz);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
+ }
+ return res;
+}
+INTERCEPTOR(int, getgrnam_r, const char *name, void *grp,
+ char *buf, SIZE_T buflen, void **result) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getgrnam_r, name, grp, buf, buflen, result);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
+ int res = REAL(getgrnam_r)(name, grp, buf, buflen, result);
+ if (!res) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, grp, struct_group_sz);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
+ }
+ return res;
+}
+INTERCEPTOR(int, getgrgid_r, u32 gid, void *grp,
+ char *buf, SIZE_T buflen, void **result) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getgrgid_r, gid, grp, buf, buflen, result);
+ int res = REAL(getgrgid_r)(gid, grp, buf, buflen, result);
+ if (!res) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, grp, struct_group_sz);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
+ }
+ return res;
+}
+#define INIT_GETPWNAM_R_AND_FRIENDS \
+ INTERCEPT_FUNCTION(getpwnam_r); \
+ INTERCEPT_FUNCTION(getpwuid_r); \
+ INTERCEPT_FUNCTION(getgrnam_r); \
+ INTERCEPT_FUNCTION(getgrgid_r);
+#else
+#define INIT_GETPWNAM_R_AND_FRIENDS
+#endif
+
+
+#if SANITIZER_INTERCEPT_CLOCK_GETTIME
+INTERCEPTOR(int, clock_getres, u32 clk_id, void *tp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, clock_getres, clk_id, tp);
+ int res = REAL(clock_getres)(clk_id, tp);
+ if (!res && tp) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tp, struct_timespec_sz);
+ }
+ return res;
+}
+INTERCEPTOR(int, clock_gettime, u32 clk_id, void *tp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, clock_gettime, clk_id, tp);
+ int res = REAL(clock_gettime)(clk_id, tp);
+ if (!res) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tp, struct_timespec_sz);
+ }
+ return res;
+}
+INTERCEPTOR(int, clock_settime, u32 clk_id, const void *tp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, clock_settime, clk_id, tp);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, tp, struct_timespec_sz);
+ return REAL(clock_settime)(clk_id, tp);
+}
+#define INIT_CLOCK_GETTIME \
+ INTERCEPT_FUNCTION(clock_getres); \
+ INTERCEPT_FUNCTION(clock_gettime); \
+ INTERCEPT_FUNCTION(clock_settime);
+#else
+#define INIT_CLOCK_GETTIME
+#endif
+
+
+#if SANITIZER_INTERCEPT_GETITIMER
+INTERCEPTOR(int, getitimer, int which, void *curr_value) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getitimer, which, curr_value);
+ int res = REAL(getitimer)(which, curr_value);
+ if (!res && curr_value) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, curr_value, struct_itimerval_sz);
+ }
+ return res;
+}
+INTERCEPTOR(int, setitimer, int which, const void *new_value, void *old_value) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, setitimer, which, new_value, old_value);
+ if (new_value)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, new_value, struct_itimerval_sz);
+ int res = REAL(setitimer)(which, new_value, old_value);
+ if (!res && old_value) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, old_value, struct_itimerval_sz);
+ }
+ return res;
+}
+#define INIT_GETITIMER \
+ INTERCEPT_FUNCTION(getitimer); \
+ INTERCEPT_FUNCTION(setitimer);
+#else
+#define INIT_GETITIMER
+#endif
+
+#if SANITIZER_INTERCEPT_GLOB
+static void unpoison_glob_t(void *ctx, __sanitizer_glob_t *pglob) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pglob, sizeof(*pglob));
+ // +1 for NULL pointer at the end.
+ if (pglob->gl_pathv)
+ COMMON_INTERCEPTOR_WRITE_RANGE(
+ ctx, pglob->gl_pathv, (pglob->gl_pathc + 1) * sizeof(*pglob->gl_pathv));
+ for (SIZE_T i = 0; i < pglob->gl_pathc; ++i) {
+ char *p = pglob->gl_pathv[i];
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, REAL(strlen)(p) + 1);
+ }
+}
+
+static THREADLOCAL __sanitizer_glob_t* pglob_copy;
+static THREADLOCAL void* glob_ctx;
+
+static void wrapped_gl_closedir(void *dir) {
+ COMMON_INTERCEPTOR_UNPOISON_PARAM(glob_ctx, 1);
+ pglob_copy->gl_closedir(dir);
+}
+
+static void *wrapped_gl_readdir(void *dir) {
+ COMMON_INTERCEPTOR_UNPOISON_PARAM(glob_ctx, 1);
+ return pglob_copy->gl_readdir(dir);
+}
+
+static void *wrapped_gl_opendir(const char *s) {
+ COMMON_INTERCEPTOR_UNPOISON_PARAM(glob_ctx, 1);
+ COMMON_INTERCEPTOR_WRITE_RANGE(glob_ctx, s, REAL(strlen)(s) + 1);
+ return pglob_copy->gl_opendir(s);
+}
+
+static int wrapped_gl_lstat(const char *s, void *st) {
+ COMMON_INTERCEPTOR_UNPOISON_PARAM(glob_ctx, 2);
+ COMMON_INTERCEPTOR_WRITE_RANGE(glob_ctx, s, REAL(strlen)(s) + 1);
+ return pglob_copy->gl_lstat(s, st);
+}
+
+static int wrapped_gl_stat(const char *s, void *st) {
+ COMMON_INTERCEPTOR_UNPOISON_PARAM(glob_ctx, 2);
+ COMMON_INTERCEPTOR_WRITE_RANGE(glob_ctx, s, REAL(strlen)(s) + 1);
+ return pglob_copy->gl_stat(s, st);
+}
+
+INTERCEPTOR(int, glob, const char *pattern, int flags,
+ int (*errfunc)(const char *epath, int eerrno),
+ __sanitizer_glob_t *pglob) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, glob, pattern, flags, errfunc, pglob);
+ __sanitizer_glob_t glob_copy = {0, 0, 0, 0, wrapped_gl_closedir,
+ wrapped_gl_readdir, wrapped_gl_opendir,
+ wrapped_gl_lstat, wrapped_gl_stat};
+ if (flags & glob_altdirfunc) {
+ Swap(pglob->gl_closedir, glob_copy.gl_closedir);
+ Swap(pglob->gl_readdir, glob_copy.gl_readdir);
+ Swap(pglob->gl_opendir, glob_copy.gl_opendir);
+ Swap(pglob->gl_lstat, glob_copy.gl_lstat);
+ Swap(pglob->gl_stat, glob_copy.gl_stat);
+ pglob_copy = &glob_copy;
+ glob_ctx = ctx;
+ }
+ int res = REAL(glob)(pattern, flags, errfunc, pglob);
+ if (flags & glob_altdirfunc) {
+ Swap(pglob->gl_closedir, glob_copy.gl_closedir);
+ Swap(pglob->gl_readdir, glob_copy.gl_readdir);
+ Swap(pglob->gl_opendir, glob_copy.gl_opendir);
+ Swap(pglob->gl_lstat, glob_copy.gl_lstat);
+ Swap(pglob->gl_stat, glob_copy.gl_stat);
+ }
+ pglob_copy = 0;
+ glob_ctx = 0;
+ if ((!res || res == glob_nomatch) && pglob) unpoison_glob_t(ctx, pglob);
+ return res;
+}
+
+INTERCEPTOR(int, glob64, const char *pattern, int flags,
+ int (*errfunc)(const char *epath, int eerrno),
+ __sanitizer_glob_t *pglob) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, glob64, pattern, flags, errfunc, pglob);
+ __sanitizer_glob_t glob_copy = {0, 0, 0, 0, wrapped_gl_closedir,
+ wrapped_gl_readdir, wrapped_gl_opendir,
+ wrapped_gl_lstat, wrapped_gl_stat};
+ if (flags & glob_altdirfunc) {
+ Swap(pglob->gl_closedir, glob_copy.gl_closedir);
+ Swap(pglob->gl_readdir, glob_copy.gl_readdir);
+ Swap(pglob->gl_opendir, glob_copy.gl_opendir);
+ Swap(pglob->gl_lstat, glob_copy.gl_lstat);
+ Swap(pglob->gl_stat, glob_copy.gl_stat);
+ pglob_copy = &glob_copy;
+ glob_ctx = ctx;
+ }
+ int res = REAL(glob64)(pattern, flags, errfunc, pglob);
+ if (flags & glob_altdirfunc) {
+ Swap(pglob->gl_closedir, glob_copy.gl_closedir);
+ Swap(pglob->gl_readdir, glob_copy.gl_readdir);
+ Swap(pglob->gl_opendir, glob_copy.gl_opendir);
+ Swap(pglob->gl_lstat, glob_copy.gl_lstat);
+ Swap(pglob->gl_stat, glob_copy.gl_stat);
+ }
+ pglob_copy = 0;
+ glob_ctx = 0;
+ if ((!res || res == glob_nomatch) && pglob) unpoison_glob_t(ctx, pglob);
+ return res;
+}
+#define INIT_GLOB \
+ INTERCEPT_FUNCTION(glob); \
+ INTERCEPT_FUNCTION(glob64);
+#else // SANITIZER_INTERCEPT_GLOB
+#define INIT_GLOB
+#endif // SANITIZER_INTERCEPT_GLOB
+
+#if SANITIZER_INTERCEPT_WAIT
+// According to sys/wait.h, wait(), waitid(), waitpid() may have symbol version
+// suffixes on Darwin. See the declaration of INTERCEPTOR_WITH_SUFFIX for
+// details.
+INTERCEPTOR_WITH_SUFFIX(int, wait, int *status) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, wait, status);
+ int res = REAL(wait)(status);
+ if (res != -1 && status)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
+ return res;
+}
+INTERCEPTOR_WITH_SUFFIX(int, waitid, int idtype, int id, void *infop,
+ int options) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, waitid, idtype, id, infop, options);
+ int res = REAL(waitid)(idtype, id, infop, options);
+ if (res != -1 && infop)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, infop, siginfo_t_sz);
+ return res;
+}
+INTERCEPTOR_WITH_SUFFIX(int, waitpid, int pid, int *status, int options) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, waitpid, pid, status, options);
+ int res = REAL(waitpid)(pid, status, options);
+ if (res != -1 && status)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
+ return res;
+}
+INTERCEPTOR(int, wait3, int *status, int options, void *rusage) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, wait3, status, options, rusage);
+ int res = REAL(wait3)(status, options, rusage);
+ if (res != -1) {
+ if (status)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
+ if (rusage)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rusage, struct_rusage_sz);
+ }
+ return res;
+}
+INTERCEPTOR(int, wait4, int pid, int *status, int options, void *rusage) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, wait4, pid, status, options, rusage);
+ int res = REAL(wait4)(pid, status, options, rusage);
+ if (res != -1) {
+ if (status)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
+ if (rusage)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rusage, struct_rusage_sz);
+ }
+ return res;
+}
+#define INIT_WAIT \
+ INTERCEPT_FUNCTION(wait); \
+ INTERCEPT_FUNCTION(waitid); \
+ INTERCEPT_FUNCTION(waitpid); \
+ INTERCEPT_FUNCTION(wait3); \
+ INTERCEPT_FUNCTION(wait4);
+#else
+#define INIT_WAIT
+#endif
+
+#if SANITIZER_INTERCEPT_INET
+INTERCEPTOR(char *, inet_ntop, int af, const void *src, char *dst, u32 size) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, inet_ntop, af, src, dst, size);
+ uptr sz = __sanitizer_in_addr_sz(af);
+ if (sz) COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sz);
+ // FIXME: figure out read size based on the address family.
+ char *res = REAL(inet_ntop)(af, src, dst, size);
+ if (res)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
+ return res;
+}
+INTERCEPTOR(int, inet_pton, int af, const char *src, void *dst) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, inet_pton, af, src, dst);
+ // FIXME: figure out read size based on the address family.
+ int res = REAL(inet_pton)(af, src, dst);
+ if (res == 1) {
+ uptr sz = __sanitizer_in_addr_sz(af);
+ if (sz) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sz);
+ }
+ return res;
+}
+#define INIT_INET \
+ INTERCEPT_FUNCTION(inet_ntop); \
+ INTERCEPT_FUNCTION(inet_pton);
+#else
+#define INIT_INET
+#endif
+
+#if SANITIZER_INTERCEPT_INET
+INTERCEPTOR(int, inet_aton, const char *cp, void *dst) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, inet_aton, cp, dst);
+ if (cp) COMMON_INTERCEPTOR_READ_RANGE(ctx, cp, REAL(strlen)(cp) + 1);
+ int res = REAL(inet_aton)(cp, dst);
+ if (res != 0) {
+ uptr sz = __sanitizer_in_addr_sz(af_inet);
+ if (sz) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sz);
+ }
+ return res;
+}
+#define INIT_INET_ATON INTERCEPT_FUNCTION(inet_aton);
+#else
+#define INIT_INET_ATON
+#endif
+
+#if SANITIZER_INTERCEPT_PTHREAD_GETSCHEDPARAM
+INTERCEPTOR(int, pthread_getschedparam, uptr thread, int *policy, int *param) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, pthread_getschedparam, thread, policy, param);
+ int res = REAL(pthread_getschedparam)(thread, policy, param);
+ if (res == 0) {
+ if (policy) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, policy, sizeof(*policy));
+ if (param) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, param, sizeof(*param));
+ }
+ return res;
+}
+#define INIT_PTHREAD_GETSCHEDPARAM INTERCEPT_FUNCTION(pthread_getschedparam);
+#else
+#define INIT_PTHREAD_GETSCHEDPARAM
+#endif
+
+#if SANITIZER_INTERCEPT_GETADDRINFO
+INTERCEPTOR(int, getaddrinfo, char *node, char *service,
+ struct __sanitizer_addrinfo *hints,
+ struct __sanitizer_addrinfo **out) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getaddrinfo, node, service, hints, out);
+ if (node) COMMON_INTERCEPTOR_READ_RANGE(ctx, node, REAL(strlen)(node) + 1);
+ if (service)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, service, REAL(strlen)(service) + 1);
+ if (hints)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, hints, sizeof(__sanitizer_addrinfo));
+ int res = REAL(getaddrinfo)(node, service, hints, out);
+ if (res == 0 && out) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, out, sizeof(*out));
+ struct __sanitizer_addrinfo *p = *out;
+ while (p) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));
+ if (p->ai_addr)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ai_addr, p->ai_addrlen);
+ if (p->ai_canonname)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ai_canonname,
+ REAL(strlen)(p->ai_canonname) + 1);
+ p = p->ai_next;
+ }
+ }
+ return res;
+}
+#define INIT_GETADDRINFO INTERCEPT_FUNCTION(getaddrinfo);
+#else
+#define INIT_GETADDRINFO
+#endif
+
+#if SANITIZER_INTERCEPT_GETNAMEINFO
+INTERCEPTOR(int, getnameinfo, void *sockaddr, unsigned salen, char *host,
+ unsigned hostlen, char *serv, unsigned servlen, int flags) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getnameinfo, sockaddr, salen, host, hostlen,
+ serv, servlen, flags);
+ // FIXME: consider adding READ_RANGE(sockaddr, salen)
+ // There is padding in in_addr that may make this too noisy
+ int res =
+ REAL(getnameinfo)(sockaddr, salen, host, hostlen, serv, servlen, flags);
+ if (res == 0) {
+ if (host && hostlen)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, host, REAL(strlen)(host) + 1);
+ if (serv && servlen)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, serv, REAL(strlen)(serv) + 1);
+ }
+ return res;
+}
+#define INIT_GETNAMEINFO INTERCEPT_FUNCTION(getnameinfo);
+#else
+#define INIT_GETNAMEINFO
+#endif
+
+#if SANITIZER_INTERCEPT_GETSOCKNAME
+INTERCEPTOR(int, getsockname, int sock_fd, void *addr, int *addrlen) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getsockname, sock_fd, addr, addrlen);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
+ int addrlen_in = *addrlen;
+ int res = REAL(getsockname)(sock_fd, addr, addrlen);
+ if (res == 0) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(addrlen_in, *addrlen));
+ }
+ return res;
+}
+#define INIT_GETSOCKNAME INTERCEPT_FUNCTION(getsockname);
+#else
+#define INIT_GETSOCKNAME
+#endif
+
+#if SANITIZER_INTERCEPT_GETHOSTBYNAME || SANITIZER_INTERCEPT_GETHOSTBYNAME_R
+static void write_hostent(void *ctx, struct __sanitizer_hostent *h) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h, sizeof(__sanitizer_hostent));
+ if (h->h_name)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h->h_name, REAL(strlen)(h->h_name) + 1);
+ char **p = h->h_aliases;
+ while (*p) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, REAL(strlen)(*p) + 1);
+ ++p;
+ }
+ COMMON_INTERCEPTOR_WRITE_RANGE(
+ ctx, h->h_aliases, (p - h->h_aliases + 1) * sizeof(*h->h_aliases));
+ p = h->h_addr_list;
+ while (*p) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, h->h_length);
+ ++p;
+ }
+ COMMON_INTERCEPTOR_WRITE_RANGE(
+ ctx, h->h_addr_list, (p - h->h_addr_list + 1) * sizeof(*h->h_addr_list));
+}
+#endif
+
+#if SANITIZER_INTERCEPT_GETHOSTBYNAME
+INTERCEPTOR(struct __sanitizer_hostent *, gethostbyname, char *name) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname, name);
+ struct __sanitizer_hostent *res = REAL(gethostbyname)(name);
+ if (res) write_hostent(ctx, res);
+ return res;
+}
+
+INTERCEPTOR(struct __sanitizer_hostent *, gethostbyaddr, void *addr, int len,
+ int type) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, gethostbyaddr, addr, len, type);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, len);
+ struct __sanitizer_hostent *res = REAL(gethostbyaddr)(addr, len, type);
+ if (res) write_hostent(ctx, res);
+ return res;
+}
+
+INTERCEPTOR(struct __sanitizer_hostent *, gethostent) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, gethostent);
+ struct __sanitizer_hostent *res = REAL(gethostent)();
+ if (res) write_hostent(ctx, res);
+ return res;
+}
+
+INTERCEPTOR(struct __sanitizer_hostent *, gethostbyname2, char *name, int af) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname2, name, af);
+ struct __sanitizer_hostent *res = REAL(gethostbyname2)(name, af);
+ if (res) write_hostent(ctx, res);
+ return res;
+}
+#define INIT_GETHOSTBYNAME \
+ INTERCEPT_FUNCTION(gethostent); \
+ INTERCEPT_FUNCTION(gethostbyaddr); \
+ INTERCEPT_FUNCTION(gethostbyname); \
+ INTERCEPT_FUNCTION(gethostbyname2);
+#else
+#define INIT_GETHOSTBYNAME
+#endif
+
+#if SANITIZER_INTERCEPT_GETHOSTBYNAME_R
+INTERCEPTOR(int, gethostent_r, struct __sanitizer_hostent *ret, char *buf,
+ SIZE_T buflen, __sanitizer_hostent **result, int *h_errnop) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, gethostent_r, ret, buf, buflen, result,
+ h_errnop);
+ int res = REAL(gethostent_r)(ret, buf, buflen, result, h_errnop);
+ if (res == 0) {
+ if (result) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
+ if (*result) write_hostent(ctx, *result);
+ }
+ if (h_errnop)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
+ }
+ return res;
+}
+
+INTERCEPTOR(int, gethostbyaddr_r, void *addr, int len, int type,
+ struct __sanitizer_hostent *ret, char *buf, SIZE_T buflen,
+ __sanitizer_hostent **result, int *h_errnop) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, gethostbyaddr_r, addr, len, type, ret, buf,
+ buflen, result, h_errnop);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, len);
+ int res = REAL(gethostbyaddr_r)(addr, len, type, ret, buf, buflen, result,
+ h_errnop);
+ if (res == 0) {
+ if (result) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
+ if (*result) write_hostent(ctx, *result);
+ }
+ if (h_errnop)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
+ }
+ return res;
+}
+
+INTERCEPTOR(int, gethostbyname_r, char *name, struct __sanitizer_hostent *ret,
+ char *buf, SIZE_T buflen, __sanitizer_hostent **result,
+ int *h_errnop) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname_r, name, ret, buf, buflen, result,
+ h_errnop);
+ int res = REAL(gethostbyname_r)(name, ret, buf, buflen, result, h_errnop);
+ if (res == 0) {
+ if (result) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
+ if (*result) write_hostent(ctx, *result);
+ }
+ if (h_errnop)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
+ }
+ return res;
+}
+
+INTERCEPTOR(int, gethostbyname2_r, char *name, int af,
+ struct __sanitizer_hostent *ret, char *buf, SIZE_T buflen,
+ __sanitizer_hostent **result, int *h_errnop) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname2_r, name, af, ret, buf, buflen,
+ result, h_errnop);
+ int res =
+ REAL(gethostbyname2_r)(name, af, ret, buf, buflen, result, h_errnop);
+ if (res == 0) {
+ if (result) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
+ if (*result) write_hostent(ctx, *result);
+ }
+ if (h_errnop)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
+ }
+ return res;
+}
+#define INIT_GETHOSTBYNAME_R \
+ INTERCEPT_FUNCTION(gethostent_r); \
+ INTERCEPT_FUNCTION(gethostbyaddr_r); \
+ INTERCEPT_FUNCTION(gethostbyname_r); \
+ INTERCEPT_FUNCTION(gethostbyname2_r);
+#else
+#define INIT_GETHOSTBYNAME_R
+#endif
+
+#if SANITIZER_INTERCEPT_GETSOCKOPT
+INTERCEPTOR(int, getsockopt, int sockfd, int level, int optname, void *optval,
+ int *optlen) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getsockopt, sockfd, level, optname, optval,
+ optlen);
+ if (optlen) COMMON_INTERCEPTOR_READ_RANGE(ctx, optlen, sizeof(*optlen));
+ int res = REAL(getsockopt)(sockfd, level, optname, optval, optlen);
+ if (res == 0)
+ if (optval && optlen) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, optval, *optlen);
+ return res;
+}
+#define INIT_GETSOCKOPT INTERCEPT_FUNCTION(getsockopt);
+#else
+#define INIT_GETSOCKOPT
+#endif
+
+#if SANITIZER_INTERCEPT_ACCEPT
+INTERCEPTOR(int, accept, int fd, void *addr, unsigned *addrlen) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, accept, fd, addr, addrlen);
+ unsigned addrlen0;
+ if (addrlen) {
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
+ addrlen0 = *addrlen;
+ }
+ int fd2 = REAL(accept)(fd, addr, addrlen);
+ if (fd2 >= 0) {
+ if (fd >= 0)
+ COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, fd2);
+ if (addr && addrlen)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(*addrlen, addrlen0));
+ }
+ return fd2;
+}
+#define INIT_ACCEPT INTERCEPT_FUNCTION(accept);
+#else
+#define INIT_ACCEPT
+#endif
+
+#if SANITIZER_INTERCEPT_ACCEPT4
+INTERCEPTOR(int, accept4, int fd, void *addr, unsigned *addrlen, int f) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, accept4, fd, addr, addrlen, f);
+ unsigned addrlen0;
+ if (addrlen) {
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
+ addrlen0 = *addrlen;
+ }
+ int fd2 = REAL(accept4)(fd, addr, addrlen, f);
+ if (fd2 >= 0) {
+ if (fd >= 0)
+ COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, fd2);
+ if (addr && addrlen)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(*addrlen, addrlen0));
+ }
+ return fd2;
+}
+#define INIT_ACCEPT4 INTERCEPT_FUNCTION(accept4);
+#else
+#define INIT_ACCEPT4
+#endif
+
+#if SANITIZER_INTERCEPT_MODF
+INTERCEPTOR(double, modf, double x, double *iptr) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, modf, x, iptr);
+ double res = REAL(modf)(x, iptr);
+ if (iptr) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iptr, sizeof(*iptr));
+ }
+ return res;
+}
+INTERCEPTOR(float, modff, float x, float *iptr) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, modff, x, iptr);
+ float res = REAL(modff)(x, iptr);
+ if (iptr) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iptr, sizeof(*iptr));
+ }
+ return res;
+}
+INTERCEPTOR(long double, modfl, long double x, long double *iptr) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, modfl, x, iptr);
+ long double res = REAL(modfl)(x, iptr);
+ if (iptr) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iptr, sizeof(*iptr));
+ }
+ return res;
+}
+#define INIT_MODF \
+ INTERCEPT_FUNCTION(modf); \
+ INTERCEPT_FUNCTION(modff); \
+ INTERCEPT_FUNCTION(modfl);
+#else
+#define INIT_MODF
+#endif
+
+#if SANITIZER_INTERCEPT_RECVMSG
+static void write_msghdr(void *ctx, struct __sanitizer_msghdr *msg,
+ SSIZE_T maxlen) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg, sizeof(*msg));
+ if (msg->msg_name)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg->msg_name,
+ REAL(strlen)((char *)msg->msg_name) + 1);
+ if (msg->msg_iov)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg->msg_iov,
+ sizeof(*msg->msg_iov) * msg->msg_iovlen);
+ write_iovec(ctx, msg->msg_iov, msg->msg_iovlen, maxlen);
+ if (msg->msg_control)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg->msg_control, msg->msg_controllen);
+}
+
+INTERCEPTOR(SSIZE_T, recvmsg, int fd, struct __sanitizer_msghdr *msg,
+ int flags) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, recvmsg, fd, msg, flags);
+ SSIZE_T res = REAL(recvmsg)(fd, msg, flags);
+ if (res >= 0) {
+ if (fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
+ if (msg) write_msghdr(ctx, msg, res);
+ }
+ return res;
+}
+#define INIT_RECVMSG INTERCEPT_FUNCTION(recvmsg);
+#else
+#define INIT_RECVMSG
+#endif
+
+#if SANITIZER_INTERCEPT_GETPEERNAME
+INTERCEPTOR(int, getpeername, int sockfd, void *addr, unsigned *addrlen) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getpeername, sockfd, addr, addrlen);
+ unsigned addr_sz;
+ if (addrlen) addr_sz = *addrlen;
+ int res = REAL(getpeername)(sockfd, addr, addrlen);
+ if (!res && addr && addrlen)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(addr_sz, *addrlen));
+ return res;
+}
+#define INIT_GETPEERNAME INTERCEPT_FUNCTION(getpeername);
+#else
+#define INIT_GETPEERNAME
+#endif
+
+#if SANITIZER_INTERCEPT_SYSINFO
+INTERCEPTOR(int, sysinfo, void *info) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, sysinfo, info);
+ int res = REAL(sysinfo)(info);
+ if (!res && info)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, info, struct_sysinfo_sz);
+ return res;
+}
+#define INIT_SYSINFO INTERCEPT_FUNCTION(sysinfo);
+#else
+#define INIT_SYSINFO
+#endif
+
+#if SANITIZER_INTERCEPT_READDIR
+INTERCEPTOR(__sanitizer_dirent *, readdir, void *dirp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, readdir, dirp);
+ __sanitizer_dirent *res = REAL(readdir)(dirp);
+ if (res)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, res->d_reclen);
+ return res;
+}
+
+INTERCEPTOR(int, readdir_r, void *dirp, __sanitizer_dirent *entry,
+ __sanitizer_dirent **result) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, readdir_r, dirp, entry, result);
+ int res = REAL(readdir_r)(dirp, entry, result);
+ if (!res) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
+ if (*result)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *result, (*result)->d_reclen);
+ }
+ return res;
+}
+
+#define INIT_READDIR \
+ INTERCEPT_FUNCTION(readdir); \
+ INTERCEPT_FUNCTION(readdir_r);
+#else
+#define INIT_READDIR
+#endif
+
+#if SANITIZER_INTERCEPT_READDIR64
+INTERCEPTOR(__sanitizer_dirent64 *, readdir64, void *dirp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, readdir64, dirp);
+ __sanitizer_dirent64 *res = REAL(readdir64)(dirp);
+ if (res)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, res->d_reclen);
+ return res;
+}
+
+INTERCEPTOR(int, readdir64_r, void *dirp, __sanitizer_dirent64 *entry,
+ __sanitizer_dirent64 **result) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, readdir64_r, dirp, entry, result);
+ int res = REAL(readdir64_r)(dirp, entry, result);
+ if (!res) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
+ if (*result)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *result, (*result)->d_reclen);
+ }
+ return res;
+}
+#define INIT_READDIR64 \
+ INTERCEPT_FUNCTION(readdir64); \
+ INTERCEPT_FUNCTION(readdir64_r);
+#else
+#define INIT_READDIR64
+#endif
+
+#if SANITIZER_INTERCEPT_PTRACE
+INTERCEPTOR(uptr, ptrace, int request, int pid, void *addr, void *data) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, ptrace, request, pid, addr, data);
+
+ if (data) {
+ if (request == ptrace_setregs)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_regs_struct_sz);
+ else if (request == ptrace_setfpregs)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_fpregs_struct_sz);
+ else if (request == ptrace_setfpxregs)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_fpxregs_struct_sz);
+ else if (request == ptrace_setsiginfo)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, data, siginfo_t_sz);
+ else if (request == ptrace_setregset) {
+ __sanitizer_iovec *iov = (__sanitizer_iovec *)data;
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, iov->iov_base, iov->iov_len);
+ }
+ }
+
+ uptr res = REAL(ptrace)(request, pid, addr, data);
+
+ if (!res && data) {
+ // Note that PEEK* requests assing different meaning to the return value.
+ // This function does not handle them (nor does it need to).
+ if (request == ptrace_getregs)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_regs_struct_sz);
+ else if (request == ptrace_getfpregs)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_fpregs_struct_sz);
+ else if (request == ptrace_getfpxregs)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_fpxregs_struct_sz);
+ else if (request == ptrace_getsiginfo)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, siginfo_t_sz);
+ else if (request == ptrace_getregset) {
+ __sanitizer_iovec *iov = (__sanitizer_iovec *)data;
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iov->iov_base, iov->iov_len);
+ }
+ }
+ return res;
+}
+
+#define INIT_PTRACE \
+ INTERCEPT_FUNCTION(ptrace);
+#else
+#define INIT_PTRACE
+#endif
+
+#if SANITIZER_INTERCEPT_SETLOCALE
+INTERCEPTOR(char *, setlocale, int category, char *locale) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, setlocale, category, locale);
+ if (locale)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, locale, REAL(strlen)(locale) + 1);
+ char *res = REAL(setlocale)(category, locale);
+ if (res)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
+ return res;
+}
+
+#define INIT_SETLOCALE \
+ INTERCEPT_FUNCTION(setlocale);
+#else
+#define INIT_SETLOCALE
+#endif
+
+#if SANITIZER_INTERCEPT_GETCWD
+INTERCEPTOR(char *, getcwd, char *buf, SIZE_T size) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getcwd, buf, size);
+ char *res = REAL(getcwd)(buf, size);
+ if (res)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
+ return res;
+}
+#define INIT_GETCWD \
+ INTERCEPT_FUNCTION(getcwd);
+#else
+#define INIT_GETCWD
+#endif
+
+#if SANITIZER_INTERCEPT_GET_CURRENT_DIR_NAME
+INTERCEPTOR(char *, get_current_dir_name) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, get_current_dir_name);
+ char *res = REAL(get_current_dir_name)();
+ if (res)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
+ return res;
+}
+
+#define INIT_GET_CURRENT_DIR_NAME \
+ INTERCEPT_FUNCTION(get_current_dir_name);
+#else
+#define INIT_GET_CURRENT_DIR_NAME
+#endif
+
+#if SANITIZER_INTERCEPT_STRTOIMAX
+INTERCEPTOR(INTMAX_T, strtoimax, const char *nptr, char **endptr, int base) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, strtoimax, nptr, endptr, base);
+ INTMAX_T res = REAL(strtoimax)(nptr, endptr, base);
+ if (endptr) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, endptr, sizeof(*endptr));
+ return res;
+}
+
+INTERCEPTOR(INTMAX_T, strtoumax, const char *nptr, char **endptr, int base) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, strtoumax, nptr, endptr, base);
+ INTMAX_T res = REAL(strtoumax)(nptr, endptr, base);
+ if (endptr) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, endptr, sizeof(*endptr));
+ return res;
+}
+
+#define INIT_STRTOIMAX \
+ INTERCEPT_FUNCTION(strtoimax); \
+ INTERCEPT_FUNCTION(strtoumax);
+#else
+#define INIT_STRTOIMAX
+#endif
+
+#if SANITIZER_INTERCEPT_MBSTOWCS
+INTERCEPTOR(SIZE_T, mbstowcs, wchar_t *dest, const char *src, SIZE_T len) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, mbstowcs, dest, src, len);
+ SIZE_T res = REAL(mbstowcs)(dest, src, len);
+ if (res != (SIZE_T) - 1 && dest) {
+ SIZE_T write_cnt = res + (res < len);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt * sizeof(wchar_t));
+ }
+ return res;
+}
+
+INTERCEPTOR(SIZE_T, mbsrtowcs, wchar_t *dest, const char **src, SIZE_T len,
+ void *ps) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, mbsrtowcs, dest, src, len, ps);
+ if (src) COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
+ if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
+ SIZE_T res = REAL(mbsrtowcs)(dest, src, len, ps);
+ if (res != (SIZE_T)(-1) && dest && src) {
+ // This function, and several others, may or may not write the terminating
+ // \0 character. They write it iff they clear *src.
+ SIZE_T write_cnt = res + !*src;
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt * sizeof(wchar_t));
+ }
+ return res;
+}
+
+#define INIT_MBSTOWCS \
+ INTERCEPT_FUNCTION(mbstowcs); \
+ INTERCEPT_FUNCTION(mbsrtowcs);
+#else
+#define INIT_MBSTOWCS
+#endif
+
+#if SANITIZER_INTERCEPT_MBSNRTOWCS
+INTERCEPTOR(SIZE_T, mbsnrtowcs, wchar_t *dest, const char **src, SIZE_T nms,
+ SIZE_T len, void *ps) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, mbsnrtowcs, dest, src, nms, len, ps);
+ if (src) {
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
+ if (nms) COMMON_INTERCEPTOR_READ_RANGE(ctx, *src, nms);
+ }
+ if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
+ SIZE_T res = REAL(mbsnrtowcs)(dest, src, nms, len, ps);
+ if (res != (SIZE_T)(-1) && dest && src) {
+ SIZE_T write_cnt = res + !*src;
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt * sizeof(wchar_t));
+ }
+ return res;
+}
+
+#define INIT_MBSNRTOWCS INTERCEPT_FUNCTION(mbsnrtowcs);
+#else
+#define INIT_MBSNRTOWCS
+#endif
+
+#if SANITIZER_INTERCEPT_WCSTOMBS
+INTERCEPTOR(SIZE_T, wcstombs, char *dest, const wchar_t *src, SIZE_T len) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, wcstombs, dest, src, len);
+ SIZE_T res = REAL(wcstombs)(dest, src, len);
+ if (res != (SIZE_T) - 1 && dest) {
+ SIZE_T write_cnt = res + (res < len);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt);
+ }
+ return res;
+}
+
+INTERCEPTOR(SIZE_T, wcsrtombs, char *dest, const wchar_t **src, SIZE_T len,
+ void *ps) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, wcsrtombs, dest, src, len, ps);
+ if (src) COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
+ if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
+ SIZE_T res = REAL(wcsrtombs)(dest, src, len, ps);
+ if (res != (SIZE_T) - 1 && dest && src) {
+ SIZE_T write_cnt = res + !*src;
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt);
+ }
+ return res;
+}
+
+#define INIT_WCSTOMBS \
+ INTERCEPT_FUNCTION(wcstombs); \
+ INTERCEPT_FUNCTION(wcsrtombs);
+#else
+#define INIT_WCSTOMBS
+#endif
+
+#if SANITIZER_INTERCEPT_WCSNRTOMBS
+INTERCEPTOR(SIZE_T, wcsnrtombs, char *dest, const wchar_t **src, SIZE_T nms,
+ SIZE_T len, void *ps) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, wcsnrtombs, dest, src, nms, len, ps);
+ if (src) {
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
+ if (nms) COMMON_INTERCEPTOR_READ_RANGE(ctx, *src, nms);
+ }
+ if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
+ SIZE_T res = REAL(wcsnrtombs)(dest, src, nms, len, ps);
+ if (res != (SIZE_T) - 1 && dest && src) {
+ SIZE_T write_cnt = res + !*src;
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt);
+ }
+ return res;
+}
+
+#define INIT_WCSNRTOMBS INTERCEPT_FUNCTION(wcsnrtombs);
+#else
+#define INIT_WCSNRTOMBS
+#endif
+
+
+#if SANITIZER_INTERCEPT_TCGETATTR
+INTERCEPTOR(int, tcgetattr, int fd, void *termios_p) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, tcgetattr, fd, termios_p);
+ int res = REAL(tcgetattr)(fd, termios_p);
+ if (!res && termios_p)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, termios_p, struct_termios_sz);
+ return res;
+}
+
+#define INIT_TCGETATTR INTERCEPT_FUNCTION(tcgetattr);
+#else
+#define INIT_TCGETATTR
+#endif
+
+
+#if SANITIZER_INTERCEPT_REALPATH
+INTERCEPTOR(char *, realpath, const char *path, char *resolved_path) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, realpath, path, resolved_path);
+ if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
+
+ // Workaround a bug in glibc where dlsym(RTLD_NEXT, ...) returns the oldest
+ // version of a versioned symbol. For realpath(), this gives us something
+ // (called __old_realpath) that does not handle NULL in the second argument.
+ // Handle it as part of the interceptor.
+ char *allocated_path = 0;
+ if (!resolved_path)
+ allocated_path = resolved_path = (char *)WRAP(malloc)(path_max + 1);
+
+ char *res = REAL(realpath)(path, resolved_path);
+ if (allocated_path && !res)
+ WRAP(free)(allocated_path);
+ if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
+ return res;
+}
+#define INIT_REALPATH INTERCEPT_FUNCTION(realpath);
+#else
+#define INIT_REALPATH
+#endif
+
+#if SANITIZER_INTERCEPT_CANONICALIZE_FILE_NAME
+INTERCEPTOR(char *, canonicalize_file_name, const char *path) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, canonicalize_file_name, path);
+ if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
+ char *res = REAL(canonicalize_file_name)(path);
+ if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
+ return res;
+}
+#define INIT_CANONICALIZE_FILE_NAME INTERCEPT_FUNCTION(canonicalize_file_name);
+#else
+#define INIT_CANONICALIZE_FILE_NAME
+#endif
+
+#if SANITIZER_INTERCEPT_CONFSTR
+INTERCEPTOR(SIZE_T, confstr, int name, char *buf, SIZE_T len) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, confstr, name, buf, len);
+ SIZE_T res = REAL(confstr)(name, buf, len);
+ if (buf && res)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, res < len ? res : len);
+ return res;
+}
+#define INIT_CONFSTR INTERCEPT_FUNCTION(confstr);
+#else
+#define INIT_CONFSTR
+#endif
+
+#if SANITIZER_INTERCEPT_SCHED_GETAFFINITY
+INTERCEPTOR(int, sched_getaffinity, int pid, SIZE_T cpusetsize, void *mask) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, sched_getaffinity, pid, cpusetsize, mask);
+ int res = REAL(sched_getaffinity)(pid, cpusetsize, mask);
+ if (mask && !res)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mask, cpusetsize);
+ return res;
+}
+#define INIT_SCHED_GETAFFINITY INTERCEPT_FUNCTION(sched_getaffinity);
+#else
+#define INIT_SCHED_GETAFFINITY
+#endif
+
+#if SANITIZER_INTERCEPT_STRERROR
+INTERCEPTOR(char *, strerror, int errnum) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, strerror, errnum);
+ char *res = REAL(strerror)(errnum);
+ if (res)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
+ return res;
+}
+#define INIT_STRERROR INTERCEPT_FUNCTION(strerror);
+#else
+#define INIT_STRERROR
+#endif
+
+#if SANITIZER_INTERCEPT_STRERROR_R
+INTERCEPTOR(char *, strerror_r, int errnum, char *buf, SIZE_T buflen) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, strerror_r, errnum, buf, buflen);
+ char *res = REAL(strerror_r)(errnum, buf, buflen);
+ // There are 2 versions of strerror_r:
+ // * POSIX version returns 0 on success, negative error code on failure,
+ // writes message to buf.
+ // * GNU version returns message pointer, which points to either buf or some
+ // static storage.
+ SIZE_T posix_res = (SIZE_T)res;
+ if (posix_res < 1024 || posix_res > (SIZE_T) - 1024) {
+ // POSIX version. Spec is not clear on whether buf is NULL-terminated.
+ // At least on OSX, buf contents are valid even when the call fails.
+ SIZE_T sz = internal_strnlen(buf, buflen);
+ if (sz < buflen) ++sz;
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, sz);
+ } else {
+ // GNU version.
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
+ }
+ return res;
+}
+#define INIT_STRERROR_R INTERCEPT_FUNCTION(strerror_r);
+#else
+#define INIT_STRERROR_R
+#endif
+
+#if SANITIZER_INTERCEPT_SCANDIR
+typedef int (*scandir_filter_f)(const struct __sanitizer_dirent *);
+typedef int (*scandir_compar_f)(const struct __sanitizer_dirent **,
+ const struct __sanitizer_dirent **);
+
+static THREADLOCAL void *scandir_ctx;
+static THREADLOCAL scandir_filter_f scandir_filter;
+static THREADLOCAL scandir_compar_f scandir_compar;
+
+static int wrapped_scandir_filter(const struct __sanitizer_dirent *dir) {
+ COMMON_INTERCEPTOR_UNPOISON_PARAM(scandir_ctx, 1);
+ COMMON_INTERCEPTOR_WRITE_RANGE(scandir_ctx, dir, dir->d_reclen);
+ return scandir_filter(dir);
+}
+
+static int wrapped_scandir_compar(const struct __sanitizer_dirent **a,
+ const struct __sanitizer_dirent **b) {
+ COMMON_INTERCEPTOR_UNPOISON_PARAM(scandir_ctx, 2);
+ COMMON_INTERCEPTOR_WRITE_RANGE(scandir_ctx, a, sizeof(*a));
+ COMMON_INTERCEPTOR_WRITE_RANGE(scandir_ctx, *a, (*a)->d_reclen);
+ COMMON_INTERCEPTOR_WRITE_RANGE(scandir_ctx, b, sizeof(*b));
+ COMMON_INTERCEPTOR_WRITE_RANGE(scandir_ctx, *b, (*b)->d_reclen);
+ return scandir_compar(a, b);
+}
+
+INTERCEPTOR(int, scandir, char *dirp, __sanitizer_dirent ***namelist,
+ scandir_filter_f filter, scandir_compar_f compar) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, scandir, dirp, namelist, filter, compar);
+ if (dirp) COMMON_INTERCEPTOR_READ_RANGE(ctx, dirp, REAL(strlen)(dirp) + 1);
+ CHECK_EQ(0, scandir_ctx);
+ scandir_ctx = ctx;
+ scandir_filter = filter;
+ scandir_compar = compar;
+ int res = REAL(scandir)(dirp, namelist, filter ? wrapped_scandir_filter : 0,
+ compar ? wrapped_scandir_compar : 0);
+ scandir_ctx = 0;
+ scandir_filter = 0;
+ scandir_compar = 0;
+ if (namelist && res > 0) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, namelist, sizeof(*namelist));
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *namelist, sizeof(**namelist) * res);
+ for (int i = 0; i < res; ++i)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, (*namelist)[i],
+ (*namelist)[i]->d_reclen);
+ }
+ return res;
+}
+#define INIT_SCANDIR INTERCEPT_FUNCTION(scandir);
+#else
+#define INIT_SCANDIR
+#endif
+
+#if SANITIZER_INTERCEPT_SCANDIR64
+typedef int (*scandir64_filter_f)(const struct __sanitizer_dirent64 *);
+typedef int (*scandir64_compar_f)(const struct __sanitizer_dirent64 **,
+ const struct __sanitizer_dirent64 **);
+
+static THREADLOCAL void *scandir64_ctx;
+static THREADLOCAL scandir64_filter_f scandir64_filter;
+static THREADLOCAL scandir64_compar_f scandir64_compar;
+
+static int wrapped_scandir64_filter(const struct __sanitizer_dirent64 *dir) {
+ COMMON_INTERCEPTOR_UNPOISON_PARAM(scandir64_ctx, 1);
+ COMMON_INTERCEPTOR_WRITE_RANGE(scandir64_ctx, dir, dir->d_reclen);
+ return scandir64_filter(dir);
+}
+
+static int wrapped_scandir64_compar(const struct __sanitizer_dirent64 **a,
+ const struct __sanitizer_dirent64 **b) {
+ COMMON_INTERCEPTOR_UNPOISON_PARAM(scandir64_ctx, 2);
+ COMMON_INTERCEPTOR_WRITE_RANGE(scandir64_ctx, a, sizeof(*a));
+ COMMON_INTERCEPTOR_WRITE_RANGE(scandir64_ctx, *a, (*a)->d_reclen);
+ COMMON_INTERCEPTOR_WRITE_RANGE(scandir64_ctx, b, sizeof(*b));
+ COMMON_INTERCEPTOR_WRITE_RANGE(scandir64_ctx, *b, (*b)->d_reclen);
+ return scandir64_compar(a, b);
+}
+
+INTERCEPTOR(int, scandir64, char *dirp, __sanitizer_dirent64 ***namelist,
+ scandir64_filter_f filter, scandir64_compar_f compar) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, scandir64, dirp, namelist, filter, compar);
+ if (dirp) COMMON_INTERCEPTOR_READ_RANGE(ctx, dirp, REAL(strlen)(dirp) + 1);
+ CHECK_EQ(0, scandir64_ctx);
+ scandir64_ctx = ctx;
+ scandir64_filter = filter;
+ scandir64_compar = compar;
+ int res =
+ REAL(scandir64)(dirp, namelist, filter ? wrapped_scandir64_filter : 0,
+ compar ? wrapped_scandir64_compar : 0);
+ scandir64_ctx = 0;
+ scandir64_filter = 0;
+ scandir64_compar = 0;
+ if (namelist && res > 0) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, namelist, sizeof(*namelist));
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *namelist, sizeof(**namelist) * res);
+ for (int i = 0; i < res; ++i)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, (*namelist)[i],
+ (*namelist)[i]->d_reclen);
+ }
+ return res;
+}
+#define INIT_SCANDIR64 INTERCEPT_FUNCTION(scandir64);
+#else
+#define INIT_SCANDIR64
+#endif
+
+#if SANITIZER_INTERCEPT_GETGROUPS
+INTERCEPTOR(int, getgroups, int size, u32 *lst) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getgroups, size, lst);
+ int res = REAL(getgroups)(size, lst);
+ if (res && lst)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, lst, res * sizeof(*lst));
+ return res;
+}
+#define INIT_GETGROUPS INTERCEPT_FUNCTION(getgroups);
+#else
+#define INIT_GETGROUPS
+#endif
+
+#if SANITIZER_INTERCEPT_POLL
+static void read_pollfd(void *ctx, __sanitizer_pollfd *fds,
+ __sanitizer_nfds_t nfds) {
+ for (unsigned i = 0; i < nfds; ++i) {
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, &fds[i].fd, sizeof(fds[i].fd));
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, &fds[i].events, sizeof(fds[i].events));
+ }
+}
+
+static void write_pollfd(void *ctx, __sanitizer_pollfd *fds,
+ __sanitizer_nfds_t nfds) {
+ for (unsigned i = 0; i < nfds; ++i)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &fds[i].revents,
+ sizeof(fds[i].revents));
+}
+
+INTERCEPTOR(int, poll, __sanitizer_pollfd *fds, __sanitizer_nfds_t nfds,
+ int timeout) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, poll, fds, nfds, timeout);
+ if (fds && nfds) read_pollfd(ctx, fds, nfds);
+ int res = COMMON_INTERCEPTOR_BLOCK_REAL(poll)(fds, nfds, timeout);
+ if (fds && nfds) write_pollfd(ctx, fds, nfds);
+ return res;
+}
+#define INIT_POLL INTERCEPT_FUNCTION(poll);
+#else
+#define INIT_POLL
+#endif
+
+#if SANITIZER_INTERCEPT_PPOLL
+INTERCEPTOR(int, ppoll, __sanitizer_pollfd *fds, __sanitizer_nfds_t nfds,
+ void *timeout_ts, __sanitizer_sigset_t *sigmask) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, ppoll, fds, nfds, timeout_ts, sigmask);
+ if (fds && nfds) read_pollfd(ctx, fds, nfds);
+ if (timeout_ts)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, timeout_ts, struct_timespec_sz);
+ // FIXME: read sigmask when all of sigemptyset, etc are intercepted.
+ int res =
+ COMMON_INTERCEPTOR_BLOCK_REAL(ppoll)(fds, nfds, timeout_ts, sigmask);
+ if (fds && nfds) write_pollfd(ctx, fds, nfds);
+ return res;
+}
+#define INIT_PPOLL INTERCEPT_FUNCTION(ppoll);
+#else
+#define INIT_PPOLL
+#endif
+
+#if SANITIZER_INTERCEPT_WORDEXP
+INTERCEPTOR(int, wordexp, char *s, __sanitizer_wordexp_t *p, int flags) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, wordexp, s, p, flags);
+ if (s) COMMON_INTERCEPTOR_READ_RANGE(ctx, s, REAL(strlen)(s) + 1);
+ int res = REAL(wordexp)(s, p, flags);
+ if (!res && p) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));
+ if (p->we_wordc)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->we_wordv,
+ sizeof(*p->we_wordv) * p->we_wordc);
+ for (uptr i = 0; i < p->we_wordc; ++i) {
+ char *w = p->we_wordv[i];
+ if (w) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, w, REAL(strlen)(w) + 1);
+ }
+ }
+ return res;
+}
+#define INIT_WORDEXP INTERCEPT_FUNCTION(wordexp);
+#else
+#define INIT_WORDEXP
+#endif
+
+#if SANITIZER_INTERCEPT_SIGWAIT
+INTERCEPTOR(int, sigwait, __sanitizer_sigset_t *set, int *sig) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, sigwait, set, sig);
+ // FIXME: read sigset_t when all of sigemptyset, etc are intercepted
+ int res = REAL(sigwait)(set, sig);
+ if (!res && sig) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sig, sizeof(*sig));
+ return res;
+}
+#define INIT_SIGWAIT INTERCEPT_FUNCTION(sigwait);
+#else
+#define INIT_SIGWAIT
+#endif
+
+#if SANITIZER_INTERCEPT_SIGWAITINFO
+INTERCEPTOR(int, sigwaitinfo, __sanitizer_sigset_t *set, void *info) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, sigwaitinfo, set, info);
+ // FIXME: read sigset_t when all of sigemptyset, etc are intercepted
+ int res = REAL(sigwaitinfo)(set, info);
+ if (res > 0 && info) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, info, siginfo_t_sz);
+ return res;
+}
+#define INIT_SIGWAITINFO INTERCEPT_FUNCTION(sigwaitinfo);
+#else
+#define INIT_SIGWAITINFO
+#endif
+
+#if SANITIZER_INTERCEPT_SIGTIMEDWAIT
+INTERCEPTOR(int, sigtimedwait, __sanitizer_sigset_t *set, void *info,
+ void *timeout) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, sigtimedwait, set, info, timeout);
+ if (timeout) COMMON_INTERCEPTOR_READ_RANGE(ctx, timeout, struct_timespec_sz);
+ // FIXME: read sigset_t when all of sigemptyset, etc are intercepted
+ int res = REAL(sigtimedwait)(set, info, timeout);
+ if (res > 0 && info) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, info, siginfo_t_sz);
+ return res;
+}
+#define INIT_SIGTIMEDWAIT INTERCEPT_FUNCTION(sigtimedwait);
+#else
+#define INIT_SIGTIMEDWAIT
+#endif
+
+#if SANITIZER_INTERCEPT_SIGSETOPS
+INTERCEPTOR(int, sigemptyset, __sanitizer_sigset_t *set) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, sigemptyset, set);
+ int res = REAL(sigemptyset)(set);
+ if (!res && set) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, set, sizeof(*set));
+ return res;
+}
+
+INTERCEPTOR(int, sigfillset, __sanitizer_sigset_t *set) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, sigfillset, set);
+ int res = REAL(sigfillset)(set);
+ if (!res && set) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, set, sizeof(*set));
+ return res;
+}
+#define INIT_SIGSETOPS \
+ INTERCEPT_FUNCTION(sigemptyset); \
+ INTERCEPT_FUNCTION(sigfillset);
+#else
+#define INIT_SIGSETOPS
+#endif
+
+#if SANITIZER_INTERCEPT_SIGPENDING
+INTERCEPTOR(int, sigpending, __sanitizer_sigset_t *set) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, sigpending, set);
+ int res = REAL(sigpending)(set);
+ if (!res && set) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, set, sizeof(*set));
+ return res;
+}
+#define INIT_SIGPENDING INTERCEPT_FUNCTION(sigpending);
+#else
+#define INIT_SIGPENDING
+#endif
+
+#if SANITIZER_INTERCEPT_SIGPROCMASK
+INTERCEPTOR(int, sigprocmask, int how, __sanitizer_sigset_t *set,
+ __sanitizer_sigset_t *oldset) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, sigprocmask, how, set, oldset);
+ // FIXME: read sigset_t when all of sigemptyset, etc are intercepted
+ int res = REAL(sigprocmask)(how, set, oldset);
+ if (!res && oldset)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldset, sizeof(*oldset));
+ return res;
+}
+#define INIT_SIGPROCMASK INTERCEPT_FUNCTION(sigprocmask);
+#else
+#define INIT_SIGPROCMASK
+#endif
+
+#if SANITIZER_INTERCEPT_BACKTRACE
+INTERCEPTOR(int, backtrace, void **buffer, int size) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, backtrace, buffer, size);
+ int res = REAL(backtrace)(buffer, size);
+ if (res && buffer)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buffer, res * sizeof(*buffer));
+ return res;
+}
+
+INTERCEPTOR(char **, backtrace_symbols, void **buffer, int size) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, backtrace_symbols, buffer, size);
+ if (buffer && size)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, buffer, size * sizeof(*buffer));
+ char ** res = REAL(backtrace_symbols)(buffer, size);
+ if (res && size) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, size * sizeof(*res));
+ for (int i = 0; i < size; ++i)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res[i], REAL(strlen(res[i])) + 1);
+ }
+ return res;
+}
+#define INIT_BACKTRACE \
+ INTERCEPT_FUNCTION(backtrace); \
+ INTERCEPT_FUNCTION(backtrace_symbols);
+#else
+#define INIT_BACKTRACE
+#endif
+
+#define SANITIZER_COMMON_INTERCEPTORS_INIT \
+ INIT_STRCMP; \
+ INIT_STRNCMP; \
+ INIT_STRCASECMP; \
+ INIT_STRNCASECMP; \
+ INIT_READ; \
+ INIT_PREAD; \
+ INIT_PREAD64; \
+ INIT_READV; \
+ INIT_PREADV; \
+ INIT_PREADV64; \
+ INIT_WRITE; \
+ INIT_PWRITE; \
+ INIT_PWRITE64; \
+ INIT_WRITEV; \
+ INIT_PWRITEV; \
+ INIT_PWRITEV64; \
+ INIT_PRCTL; \
+ INIT_LOCALTIME_AND_FRIENDS; \
+ INIT_SCANF; \
+ INIT_ISOC99_SCANF; \
+ INIT_FREXP; \
+ INIT_FREXPF_FREXPL; \
+ INIT_GETPWNAM_AND_FRIENDS; \
+ INIT_GETPWNAM_R_AND_FRIENDS; \
+ INIT_CLOCK_GETTIME; \
+ INIT_GETITIMER; \
+ INIT_TIME; \
+ INIT_GLOB; \
+ INIT_WAIT; \
+ INIT_INET; \
+ INIT_PTHREAD_GETSCHEDPARAM; \
+ INIT_GETADDRINFO; \
+ INIT_GETNAMEINFO; \
+ INIT_GETSOCKNAME; \
+ INIT_GETHOSTBYNAME; \
+ INIT_GETHOSTBYNAME_R; \
+ INIT_GETSOCKOPT; \
+ INIT_ACCEPT; \
+ INIT_ACCEPT4; \
+ INIT_MODF; \
+ INIT_RECVMSG; \
+ INIT_GETPEERNAME; \
+ INIT_IOCTL; \
+ INIT_INET_ATON; \
+ INIT_SYSINFO; \
+ INIT_READDIR; \
+ INIT_READDIR64; \
+ INIT_PTRACE; \
+ INIT_SETLOCALE; \
+ INIT_GETCWD; \
+ INIT_GET_CURRENT_DIR_NAME; \
+ INIT_STRTOIMAX; \
+ INIT_MBSTOWCS; \
+ INIT_MBSNRTOWCS; \
+ INIT_WCSTOMBS; \
+ INIT_WCSNRTOMBS; \
+ INIT_TCGETATTR; \
+ INIT_REALPATH; \
+ INIT_CANONICALIZE_FILE_NAME; \
+ INIT_CONFSTR; \
+ INIT_SCHED_GETAFFINITY; \
+ INIT_STRERROR; \
+ INIT_STRERROR_R; \
+ INIT_SCANDIR; \
+ INIT_SCANDIR64; \
+ INIT_GETGROUPS; \
+ INIT_POLL; \
+ INIT_PPOLL; \
+ INIT_WORDEXP; \
+ INIT_SIGWAIT; \
+ INIT_SIGWAITINFO; \
+ INIT_SIGTIMEDWAIT; \
+ INIT_SIGSETOPS; \
+ INIT_SIGPENDING; \
+ INIT_SIGPROCMASK; \
+ INIT_BACKTRACE;
diff --git a/libsanitizer/sanitizer_common/sanitizer_common_interceptors_ioctl.inc b/libsanitizer/sanitizer_common/sanitizer_common_interceptors_ioctl.inc
new file mode 100755
index 00000000000..50db0d71d89
--- /dev/null
+++ b/libsanitizer/sanitizer_common/sanitizer_common_interceptors_ioctl.inc
@@ -0,0 +1,566 @@
+//===-- sanitizer_common_interceptors_ioctl.inc -----------------*- C++ -*-===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Ioctl handling in common sanitizer interceptors.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_flags.h"
+
+struct ioctl_desc {
+ unsigned req;
+ // FIXME: support read+write arguments. Those are currently marked as WRITE.
+ enum {
+ NONE,
+ READ,
+ WRITE,
+ CUSTOM
+ } type : 2;
+ unsigned size : 30;
+ const char* name;
+};
+
+const unsigned ioctl_table_max = 500;
+static ioctl_desc ioctl_table[ioctl_table_max];
+static unsigned ioctl_table_size = 0;
+
+// This can not be declared as a global, because references to struct_*_sz
+// require a global initializer. And this table must be available before global
+// initializers are run.
+static void ioctl_table_fill() {
+#define _(rq, tp, sz) \
+ if (IOCTL_##rq != IOCTL_NOT_PRESENT) { \
+ CHECK(ioctl_table_size < ioctl_table_max); \
+ ioctl_table[ioctl_table_size].req = IOCTL_##rq; \
+ ioctl_table[ioctl_table_size].type = ioctl_desc::tp; \
+ ioctl_table[ioctl_table_size].size = sz; \
+ ioctl_table[ioctl_table_size].name = #rq; \
+ ++ioctl_table_size; \
+ }
+
+ _(FIOASYNC, READ, sizeof(int));
+ _(FIOCLEX, NONE, 0);
+ _(FIOGETOWN, WRITE, sizeof(int));
+ _(FIONBIO, READ, sizeof(int));
+ _(FIONCLEX, NONE, 0);
+ _(FIOSETOWN, READ, sizeof(int));
+ _(SIOCADDMULTI, READ, struct_ifreq_sz);
+ _(SIOCATMARK, WRITE, sizeof(int));
+ _(SIOCDELMULTI, READ, struct_ifreq_sz);
+ _(SIOCGIFADDR, WRITE, struct_ifreq_sz);
+ _(SIOCGIFBRDADDR, WRITE, struct_ifreq_sz);
+ _(SIOCGIFCONF, CUSTOM, 0);
+ _(SIOCGIFDSTADDR, WRITE, struct_ifreq_sz);
+ _(SIOCGIFFLAGS, WRITE, struct_ifreq_sz);
+ _(SIOCGIFMETRIC, WRITE, struct_ifreq_sz);
+ _(SIOCGIFMTU, WRITE, struct_ifreq_sz);
+ _(SIOCGIFNETMASK, WRITE, struct_ifreq_sz);
+ _(SIOCGPGRP, WRITE, sizeof(int));
+ _(SIOCSIFADDR, READ, struct_ifreq_sz);
+ _(SIOCSIFBRDADDR, READ, struct_ifreq_sz);
+ _(SIOCSIFDSTADDR, READ, struct_ifreq_sz);
+ _(SIOCSIFFLAGS, READ, struct_ifreq_sz);
+ _(SIOCSIFMETRIC, READ, struct_ifreq_sz);
+ _(SIOCSIFMTU, READ, struct_ifreq_sz);
+ _(SIOCSIFNETMASK, READ, struct_ifreq_sz);
+ _(SIOCSPGRP, READ, sizeof(int));
+ _(TIOCCONS, NONE, 0);
+ _(TIOCEXCL, NONE, 0);
+ _(TIOCGETD, WRITE, sizeof(int));
+ _(TIOCGPGRP, WRITE, pid_t_sz);
+ _(TIOCGWINSZ, WRITE, struct_winsize_sz);
+ _(TIOCMBIC, READ, sizeof(int));
+ _(TIOCMBIS, READ, sizeof(int));
+ _(TIOCMGET, WRITE, sizeof(int));
+ _(TIOCMSET, READ, sizeof(int));
+ _(TIOCNOTTY, NONE, 0);
+ _(TIOCNXCL, NONE, 0);
+ _(TIOCOUTQ, WRITE, sizeof(int));
+ _(TIOCPKT, READ, sizeof(int));
+ _(TIOCSCTTY, NONE, 0);
+ _(TIOCSETD, READ, sizeof(int));
+ _(TIOCSPGRP, READ, pid_t_sz);
+ _(TIOCSTI, READ, sizeof(char));
+ _(TIOCSWINSZ, READ, struct_winsize_sz);
+
+#if (SANITIZER_LINUX && !SANITIZER_ANDROID) || SANITIZER_MAC
+ _(SIOCGETSGCNT, WRITE, struct_sioc_sg_req_sz);
+ _(SIOCGETVIFCNT, WRITE, struct_sioc_vif_req_sz);
+#endif
+
+#if SANITIZER_LINUX
+ // Conflicting request ids.
+ // _(CDROMAUDIOBUFSIZ, NONE, 0);
+ // _(SNDCTL_TMR_CONTINUE, NONE, 0);
+ // _(SNDCTL_TMR_START, NONE, 0);
+ // _(SNDCTL_TMR_STOP, NONE, 0);
+ // _(SOUND_MIXER_READ_LOUD, WRITE, sizeof(int)); // same as ...READ_ENHANCE
+ // _(SOUND_MIXER_READ_MUTE, WRITE, sizeof(int)); // same as ...READ_ENHANCE
+ // _(SOUND_MIXER_WRITE_LOUD, WRITE, sizeof(int)); // same as ...WRITE_ENHANCE
+ // _(SOUND_MIXER_WRITE_MUTE, WRITE, sizeof(int)); // same as ...WRITE_ENHANCE
+ _(BLKFLSBUF, NONE, 0);
+ _(BLKGETSIZE, WRITE, sizeof(uptr));
+ _(BLKRAGET, WRITE, sizeof(int));
+ _(BLKRASET, NONE, 0);
+ _(BLKROGET, WRITE, sizeof(int));
+ _(BLKROSET, READ, sizeof(int));
+ _(BLKRRPART, NONE, 0);
+ _(CDROMEJECT, NONE, 0);
+ _(CDROMEJECT_SW, NONE, 0);
+ _(CDROMMULTISESSION, WRITE, struct_cdrom_multisession_sz);
+ _(CDROMPAUSE, NONE, 0);
+ _(CDROMPLAYMSF, READ, struct_cdrom_msf_sz);
+ _(CDROMPLAYTRKIND, READ, struct_cdrom_ti_sz);
+ _(CDROMREADAUDIO, READ, struct_cdrom_read_audio_sz);
+ _(CDROMREADCOOKED, READ, struct_cdrom_msf_sz);
+ _(CDROMREADMODE1, READ, struct_cdrom_msf_sz);
+ _(CDROMREADMODE2, READ, struct_cdrom_msf_sz);
+ _(CDROMREADRAW, READ, struct_cdrom_msf_sz);
+ _(CDROMREADTOCENTRY, WRITE, struct_cdrom_tocentry_sz);
+ _(CDROMREADTOCHDR, WRITE, struct_cdrom_tochdr_sz);
+ _(CDROMRESET, NONE, 0);
+ _(CDROMRESUME, NONE, 0);
+ _(CDROMSEEK, READ, struct_cdrom_msf_sz);
+ _(CDROMSTART, NONE, 0);
+ _(CDROMSTOP, NONE, 0);
+ _(CDROMSUBCHNL, WRITE, struct_cdrom_subchnl_sz);
+ _(CDROMVOLCTRL, READ, struct_cdrom_volctrl_sz);
+ _(CDROMVOLREAD, WRITE, struct_cdrom_volctrl_sz);
+ _(CDROM_GET_UPC, WRITE, 8);
+ _(EVIOCGABS, WRITE, struct_input_absinfo_sz); // fixup
+ _(EVIOCGBIT, WRITE, struct_input_id_sz); // fixup
+ _(EVIOCGEFFECTS, WRITE, sizeof(int));
+ _(EVIOCGID, WRITE, struct_input_id_sz);
+ _(EVIOCGKEY, WRITE, 0);
+ _(EVIOCGKEYCODE, WRITE, sizeof(int) * 2);
+ _(EVIOCGLED, WRITE, 0);
+ _(EVIOCGNAME, WRITE, 0);
+ _(EVIOCGPHYS, WRITE, 0);
+ _(EVIOCGRAB, READ, sizeof(int));
+ _(EVIOCGREP, WRITE, sizeof(int) * 2);
+ _(EVIOCGSND, WRITE, 0);
+ _(EVIOCGSW, WRITE, 0);
+ _(EVIOCGUNIQ, WRITE, 0);
+ _(EVIOCGVERSION, WRITE, sizeof(int));
+ _(EVIOCRMFF, READ, sizeof(int));
+ _(EVIOCSABS, READ, struct_input_absinfo_sz); // fixup
+ _(EVIOCSFF, READ, struct_ff_effect_sz);
+ _(EVIOCSKEYCODE, READ, sizeof(int) * 2);
+ _(EVIOCSREP, READ, sizeof(int) * 2);
+ _(FDCLRPRM, NONE, 0);
+ _(FDDEFPRM, READ, struct_floppy_struct_sz);
+ _(FDFLUSH, NONE, 0);
+ _(FDFMTBEG, NONE, 0);
+ _(FDFMTEND, NONE, 0);
+ _(FDFMTTRK, READ, struct_format_descr_sz);
+ _(FDGETDRVPRM, WRITE, struct_floppy_drive_params_sz);
+ _(FDGETDRVSTAT, WRITE, struct_floppy_drive_struct_sz);
+ _(FDGETDRVTYP, WRITE, 16);
+ _(FDGETFDCSTAT, WRITE, struct_floppy_fdc_state_sz);
+ _(FDGETMAXERRS, WRITE, struct_floppy_max_errors_sz);
+ _(FDGETPRM, WRITE, struct_floppy_struct_sz);
+ _(FDMSGOFF, NONE, 0);
+ _(FDMSGON, NONE, 0);
+ _(FDPOLLDRVSTAT, WRITE, struct_floppy_drive_struct_sz);
+ _(FDRAWCMD, WRITE, struct_floppy_raw_cmd_sz);
+ _(FDRESET, NONE, 0);
+ _(FDSETDRVPRM, READ, struct_floppy_drive_params_sz);
+ _(FDSETEMSGTRESH, NONE, 0);
+ _(FDSETMAXERRS, READ, struct_floppy_max_errors_sz);
+ _(FDSETPRM, READ, struct_floppy_struct_sz);
+ _(FDTWADDLE, NONE, 0);
+ _(FDWERRORCLR, NONE, 0);
+ _(FDWERRORGET, WRITE, struct_floppy_write_errors_sz);
+ _(HDIO_DRIVE_CMD, WRITE, sizeof(int));
+ _(HDIO_GETGEO, WRITE, struct_hd_geometry_sz);
+ _(HDIO_GET_32BIT, WRITE, sizeof(int));
+ _(HDIO_GET_DMA, WRITE, sizeof(int));
+ _(HDIO_GET_IDENTITY, WRITE, struct_hd_driveid_sz);
+ _(HDIO_GET_KEEPSETTINGS, WRITE, sizeof(int));
+ _(HDIO_GET_MULTCOUNT, WRITE, sizeof(int));
+ _(HDIO_GET_NOWERR, WRITE, sizeof(int));
+ _(HDIO_GET_UNMASKINTR, WRITE, sizeof(int));
+ _(HDIO_SET_32BIT, NONE, 0);
+ _(HDIO_SET_DMA, NONE, 0);
+ _(HDIO_SET_KEEPSETTINGS, NONE, 0);
+ _(HDIO_SET_MULTCOUNT, NONE, 0);
+ _(HDIO_SET_NOWERR, NONE, 0);
+ _(HDIO_SET_UNMASKINTR, NONE, 0);
+ _(MTIOCGET, WRITE, struct_mtget_sz);
+ _(MTIOCPOS, WRITE, struct_mtpos_sz);
+ _(MTIOCTOP, READ, struct_mtop_sz);
+ _(PPPIOCGASYNCMAP, WRITE, sizeof(int));
+ _(PPPIOCGDEBUG, WRITE, sizeof(int));
+ _(PPPIOCGFLAGS, WRITE, sizeof(int));
+ _(PPPIOCGUNIT, WRITE, sizeof(int));
+ _(PPPIOCGXASYNCMAP, WRITE, sizeof(int) * 8);
+ _(PPPIOCSASYNCMAP, READ, sizeof(int));
+ _(PPPIOCSDEBUG, READ, sizeof(int));
+ _(PPPIOCSFLAGS, READ, sizeof(int));
+ _(PPPIOCSMAXCID, READ, sizeof(int));
+ _(PPPIOCSMRU, READ, sizeof(int));
+ _(PPPIOCSXASYNCMAP, READ, sizeof(int) * 8);
+ _(SIOCADDRT, READ, struct_rtentry_sz);
+ _(SIOCDARP, READ, struct_arpreq_sz);
+ _(SIOCDELRT, READ, struct_rtentry_sz);
+ _(SIOCDRARP, READ, struct_arpreq_sz);
+ _(SIOCGARP, WRITE, struct_arpreq_sz);
+ _(SIOCGIFENCAP, WRITE, sizeof(int));
+ _(SIOCGIFHWADDR, WRITE, struct_ifreq_sz);
+ _(SIOCGIFMAP, WRITE, struct_ifreq_sz);
+ _(SIOCGIFMEM, WRITE, struct_ifreq_sz);
+ _(SIOCGIFNAME, NONE, 0);
+ _(SIOCGIFSLAVE, NONE, 0);
+ _(SIOCGRARP, WRITE, struct_arpreq_sz);
+ _(SIOCGSTAMP, WRITE, timeval_sz);
+ _(SIOCSARP, READ, struct_arpreq_sz);
+ _(SIOCSIFENCAP, READ, sizeof(int));
+ _(SIOCSIFHWADDR, READ, struct_ifreq_sz);
+ _(SIOCSIFLINK, NONE, 0);
+ _(SIOCSIFMAP, READ, struct_ifreq_sz);
+ _(SIOCSIFMEM, READ, struct_ifreq_sz);
+ _(SIOCSIFSLAVE, NONE, 0);
+ _(SIOCSRARP, READ, struct_arpreq_sz);
+ _(SNDCTL_COPR_HALT, WRITE, struct_copr_debug_buf_sz);
+ _(SNDCTL_COPR_LOAD, READ, struct_copr_buffer_sz);
+ _(SNDCTL_COPR_RCODE, WRITE, struct_copr_debug_buf_sz);
+ _(SNDCTL_COPR_RCVMSG, WRITE, struct_copr_msg_sz);
+ _(SNDCTL_COPR_RDATA, WRITE, struct_copr_debug_buf_sz);
+ _(SNDCTL_COPR_RESET, NONE, 0);
+ _(SNDCTL_COPR_RUN, WRITE, struct_copr_debug_buf_sz);
+ _(SNDCTL_COPR_SENDMSG, READ, struct_copr_msg_sz);
+ _(SNDCTL_COPR_WCODE, READ, struct_copr_debug_buf_sz);
+ _(SNDCTL_COPR_WDATA, READ, struct_copr_debug_buf_sz);
+ _(SNDCTL_DSP_GETBLKSIZE, WRITE, sizeof(int));
+ _(SNDCTL_DSP_GETFMTS, WRITE, sizeof(int));
+ _(SNDCTL_DSP_NONBLOCK, NONE, 0);
+ _(SNDCTL_DSP_POST, NONE, 0);
+ _(SNDCTL_DSP_RESET, NONE, 0);
+ _(SNDCTL_DSP_SETFMT, WRITE, sizeof(int));
+ _(SNDCTL_DSP_SETFRAGMENT, WRITE, sizeof(int));
+ _(SNDCTL_DSP_SPEED, WRITE, sizeof(int));
+ _(SNDCTL_DSP_STEREO, WRITE, sizeof(int));
+ _(SNDCTL_DSP_SUBDIVIDE, WRITE, sizeof(int));
+ _(SNDCTL_DSP_SYNC, NONE, 0);
+ _(SNDCTL_FM_4OP_ENABLE, READ, sizeof(int));
+ _(SNDCTL_FM_LOAD_INSTR, READ, struct_sbi_instrument_sz);
+ _(SNDCTL_MIDI_INFO, WRITE, struct_midi_info_sz);
+ _(SNDCTL_MIDI_PRETIME, WRITE, sizeof(int));
+ _(SNDCTL_SEQ_CTRLRATE, WRITE, sizeof(int));
+ _(SNDCTL_SEQ_GETINCOUNT, WRITE, sizeof(int));
+ _(SNDCTL_SEQ_GETOUTCOUNT, WRITE, sizeof(int));
+ _(SNDCTL_SEQ_NRMIDIS, WRITE, sizeof(int));
+ _(SNDCTL_SEQ_NRSYNTHS, WRITE, sizeof(int));
+ _(SNDCTL_SEQ_OUTOFBAND, READ, struct_seq_event_rec_sz);
+ _(SNDCTL_SEQ_PANIC, NONE, 0);
+ _(SNDCTL_SEQ_PERCMODE, NONE, 0);
+ _(SNDCTL_SEQ_RESET, NONE, 0);
+ _(SNDCTL_SEQ_RESETSAMPLES, READ, sizeof(int));
+ _(SNDCTL_SEQ_SYNC, NONE, 0);
+ _(SNDCTL_SEQ_TESTMIDI, READ, sizeof(int));
+ _(SNDCTL_SEQ_THRESHOLD, READ, sizeof(int));
+ _(SNDCTL_SYNTH_INFO, WRITE, struct_synth_info_sz);
+ _(SNDCTL_SYNTH_MEMAVL, WRITE, sizeof(int));
+ _(SNDCTL_TMR_METRONOME, READ, sizeof(int));
+ _(SNDCTL_TMR_SELECT, WRITE, sizeof(int));
+ _(SNDCTL_TMR_SOURCE, WRITE, sizeof(int));
+ _(SNDCTL_TMR_TEMPO, WRITE, sizeof(int));
+ _(SNDCTL_TMR_TIMEBASE, WRITE, sizeof(int));
+ _(SOUND_MIXER_READ_ALTPCM, WRITE, sizeof(int));
+ _(SOUND_MIXER_READ_BASS, WRITE, sizeof(int));
+ _(SOUND_MIXER_READ_CAPS, WRITE, sizeof(int));
+ _(SOUND_MIXER_READ_CD, WRITE, sizeof(int));
+ _(SOUND_MIXER_READ_DEVMASK, WRITE, sizeof(int));
+ _(SOUND_MIXER_READ_ENHANCE, WRITE, sizeof(int));
+ _(SOUND_MIXER_READ_IGAIN, WRITE, sizeof(int));
+ _(SOUND_MIXER_READ_IMIX, WRITE, sizeof(int));
+ _(SOUND_MIXER_READ_LINE, WRITE, sizeof(int));
+ _(SOUND_MIXER_READ_LINE1, WRITE, sizeof(int));
+ _(SOUND_MIXER_READ_LINE2, WRITE, sizeof(int));
+ _(SOUND_MIXER_READ_LINE3, WRITE, sizeof(int));
+ _(SOUND_MIXER_READ_MIC, WRITE, sizeof(int));
+ _(SOUND_MIXER_READ_OGAIN, WRITE, sizeof(int));
+ _(SOUND_MIXER_READ_PCM, WRITE, sizeof(int));
+ _(SOUND_MIXER_READ_RECLEV, WRITE, sizeof(int));
+ _(SOUND_MIXER_READ_RECMASK, WRITE, sizeof(int));
+ _(SOUND_MIXER_READ_RECSRC, WRITE, sizeof(int));
+ _(SOUND_MIXER_READ_SPEAKER, WRITE, sizeof(int));
+ _(SOUND_MIXER_READ_STEREODEVS, WRITE, sizeof(int));
+ _(SOUND_MIXER_READ_SYNTH, WRITE, sizeof(int));
+ _(SOUND_MIXER_READ_TREBLE, WRITE, sizeof(int));
+ _(SOUND_MIXER_READ_VOLUME, WRITE, sizeof(int));
+ _(SOUND_MIXER_WRITE_ALTPCM, WRITE, sizeof(int));
+ _(SOUND_MIXER_WRITE_BASS, WRITE, sizeof(int));
+ _(SOUND_MIXER_WRITE_CD, WRITE, sizeof(int));
+ _(SOUND_MIXER_WRITE_ENHANCE, WRITE, sizeof(int));
+ _(SOUND_MIXER_WRITE_IGAIN, WRITE, sizeof(int));
+ _(SOUND_MIXER_WRITE_IMIX, WRITE, sizeof(int));
+ _(SOUND_MIXER_WRITE_LINE, WRITE, sizeof(int));
+ _(SOUND_MIXER_WRITE_LINE1, WRITE, sizeof(int));
+ _(SOUND_MIXER_WRITE_LINE2, WRITE, sizeof(int));
+ _(SOUND_MIXER_WRITE_LINE3, WRITE, sizeof(int));
+ _(SOUND_MIXER_WRITE_MIC, WRITE, sizeof(int));
+ _(SOUND_MIXER_WRITE_OGAIN, WRITE, sizeof(int));
+ _(SOUND_MIXER_WRITE_PCM, WRITE, sizeof(int));
+ _(SOUND_MIXER_WRITE_RECLEV, WRITE, sizeof(int));
+ _(SOUND_MIXER_WRITE_RECSRC, WRITE, sizeof(int));
+ _(SOUND_MIXER_WRITE_SPEAKER, WRITE, sizeof(int));
+ _(SOUND_MIXER_WRITE_SYNTH, WRITE, sizeof(int));
+ _(SOUND_MIXER_WRITE_TREBLE, WRITE, sizeof(int));
+ _(SOUND_MIXER_WRITE_VOLUME, WRITE, sizeof(int));
+ _(SOUND_PCM_READ_BITS, WRITE, sizeof(int));
+ _(SOUND_PCM_READ_CHANNELS, WRITE, sizeof(int));
+ _(SOUND_PCM_READ_FILTER, WRITE, sizeof(int));
+ _(SOUND_PCM_READ_RATE, WRITE, sizeof(int));
+ _(SOUND_PCM_WRITE_CHANNELS, WRITE, sizeof(int));
+ _(SOUND_PCM_WRITE_FILTER, WRITE, sizeof(int));
+ _(TCFLSH, NONE, 0);
+ _(TCGETA, WRITE, struct_termio_sz);
+ _(TCGETS, WRITE, struct_termios_sz);
+ _(TCSBRK, NONE, 0);
+ _(TCSBRKP, NONE, 0);
+ _(TCSETA, READ, struct_termio_sz);
+ _(TCSETAF, READ, struct_termio_sz);
+ _(TCSETAW, READ, struct_termio_sz);
+ _(TCSETS, READ, struct_termios_sz);
+ _(TCSETSF, READ, struct_termios_sz);
+ _(TCSETSW, READ, struct_termios_sz);
+ _(TCXONC, NONE, 0);
+ _(TIOCGLCKTRMIOS, WRITE, struct_termios_sz);
+ _(TIOCGSOFTCAR, WRITE, sizeof(int));
+ _(TIOCINQ, WRITE, sizeof(int));
+ _(TIOCLINUX, READ, sizeof(char));
+ _(TIOCSERCONFIG, NONE, 0);
+ _(TIOCSERGETLSR, WRITE, sizeof(int));
+ _(TIOCSERGWILD, WRITE, sizeof(int));
+ _(TIOCSERSWILD, READ, sizeof(int));
+ _(TIOCSLCKTRMIOS, READ, struct_termios_sz);
+ _(TIOCSSOFTCAR, READ, sizeof(int));
+ _(VT_ACTIVATE, NONE, 0);
+ _(VT_DISALLOCATE, NONE, 0);
+ _(VT_GETMODE, WRITE, struct_vt_mode_sz);
+ _(VT_GETSTATE, WRITE, struct_vt_stat_sz);
+ _(VT_OPENQRY, WRITE, sizeof(int));
+ _(VT_RELDISP, NONE, 0);
+ _(VT_RESIZE, READ, struct_vt_sizes_sz);
+ _(VT_RESIZEX, READ, struct_vt_consize_sz);
+ _(VT_SENDSIG, NONE, 0);
+ _(VT_SETMODE, READ, struct_vt_mode_sz);
+ _(VT_WAITACTIVE, NONE, 0);
+#endif
+
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
+ // _(SIOCDEVPLIP, WRITE, struct_ifreq_sz); // the same as EQL_ENSLAVE
+ _(CYGETDEFTHRESH, WRITE, sizeof(int));
+ _(CYGETDEFTIMEOUT, WRITE, sizeof(int));
+ _(CYGETMON, WRITE, struct_cyclades_monitor_sz);
+ _(CYGETTHRESH, WRITE, sizeof(int));
+ _(CYGETTIMEOUT, WRITE, sizeof(int));
+ _(CYSETDEFTHRESH, NONE, 0);
+ _(CYSETDEFTIMEOUT, NONE, 0);
+ _(CYSETTHRESH, NONE, 0);
+ _(CYSETTIMEOUT, NONE, 0);
+ _(EQL_EMANCIPATE, WRITE, struct_ifreq_sz);
+ _(EQL_ENSLAVE, WRITE, struct_ifreq_sz);
+ _(EQL_GETMASTRCFG, WRITE, struct_ifreq_sz);
+ _(EQL_GETSLAVECFG, WRITE, struct_ifreq_sz);
+ _(EQL_SETMASTRCFG, WRITE, struct_ifreq_sz);
+ _(EQL_SETSLAVECFG, WRITE, struct_ifreq_sz);
+ _(EVIOCGKEYCODE_V2, WRITE, struct_input_keymap_entry_sz);
+ _(EVIOCGPROP, WRITE, 0);
+ _(EVIOCSKEYCODE_V2, READ, struct_input_keymap_entry_sz);
+ _(FS_IOC_GETFLAGS, WRITE, sizeof(int));
+ _(FS_IOC_GETVERSION, WRITE, sizeof(int));
+ _(FS_IOC_SETFLAGS, READ, sizeof(int));
+ _(FS_IOC_SETVERSION, READ, sizeof(int));
+ _(GIO_CMAP, WRITE, 48);
+ _(GIO_FONT, WRITE, 8192);
+ _(GIO_SCRNMAP, WRITE, e_tabsz);
+ _(GIO_UNIMAP, WRITE, struct_unimapdesc_sz);
+ _(GIO_UNISCRNMAP, WRITE, sizeof(short) * e_tabsz);
+ _(KDADDIO, NONE, 0);
+ _(KDDELIO, NONE, 0);
+ _(KDDISABIO, NONE, 0);
+ _(KDENABIO, NONE, 0);
+ _(KDGETKEYCODE, WRITE, struct_kbkeycode_sz);
+ _(KDGETLED, WRITE, 1);
+ _(KDGETMODE, WRITE, sizeof(int));
+ _(KDGKBDIACR, WRITE, struct_kbdiacrs_sz);
+ _(KDGKBENT, WRITE, struct_kbentry_sz);
+ _(KDGKBLED, WRITE, sizeof(int));
+ _(KDGKBMETA, WRITE, sizeof(int));
+ _(KDGKBMODE, WRITE, sizeof(int));
+ _(KDGKBSENT, WRITE, struct_kbsentry_sz);
+ _(KDGKBTYPE, WRITE, 1);
+ _(KDMAPDISP, NONE, 0);
+ _(KDMKTONE, NONE, 0);
+ _(KDSETKEYCODE, READ, struct_kbkeycode_sz);
+ _(KDSETLED, NONE, 0);
+ _(KDSETMODE, NONE, 0);
+ _(KDSIGACCEPT, NONE, 0);
+ _(KDSKBDIACR, READ, struct_kbdiacrs_sz);
+ _(KDSKBENT, READ, struct_kbentry_sz);
+ _(KDSKBLED, NONE, 0);
+ _(KDSKBMETA, NONE, 0);
+ _(KDSKBMODE, NONE, 0);
+ _(KDSKBSENT, READ, struct_kbsentry_sz);
+ _(KDUNMAPDISP, NONE, 0);
+ _(KIOCSOUND, NONE, 0);
+ _(LPABORT, NONE, 0);
+ _(LPABORTOPEN, NONE, 0);
+ _(LPCAREFUL, NONE, 0);
+ _(LPCHAR, NONE, 0);
+ _(LPGETIRQ, WRITE, sizeof(int));
+ _(LPGETSTATUS, WRITE, sizeof(int));
+ _(LPRESET, NONE, 0);
+ _(LPSETIRQ, NONE, 0);
+ _(LPTIME, NONE, 0);
+ _(LPWAIT, NONE, 0);
+ _(MTIOCGETCONFIG, WRITE, struct_mtconfiginfo_sz);
+ _(MTIOCSETCONFIG, READ, struct_mtconfiginfo_sz);
+ _(PIO_CMAP, NONE, 0);
+ _(PIO_FONT, READ, 8192);
+ _(PIO_SCRNMAP, READ, e_tabsz);
+ _(PIO_UNIMAP, READ, struct_unimapdesc_sz);
+ _(PIO_UNIMAPCLR, READ, struct_unimapinit_sz);
+ _(PIO_UNISCRNMAP, READ, sizeof(short) * e_tabsz);
+ _(SCSI_IOCTL_PROBE_HOST, READ, sizeof(int));
+ _(SCSI_IOCTL_TAGGED_DISABLE, NONE, 0);
+ _(SCSI_IOCTL_TAGGED_ENABLE, NONE, 0);
+ _(SNDCTL_DSP_GETISPACE, WRITE, struct_audio_buf_info_sz);
+ _(SNDCTL_DSP_GETOSPACE, WRITE, struct_audio_buf_info_sz);
+ _(TIOCGSERIAL, WRITE, struct_serial_struct_sz);
+ _(TIOCSERGETMULTI, WRITE, struct_serial_multiport_struct_sz);
+ _(TIOCSERSETMULTI, READ, struct_serial_multiport_struct_sz);
+ _(TIOCSSERIAL, READ, struct_serial_struct_sz);
+
+ // The following ioctl requests are shared between AX25, IPX, netrom and
+ // mrouted.
+ // _(SIOCAIPXITFCRT, READ, sizeof(char));
+ // _(SIOCAX25GETUID, READ, struct_sockaddr_ax25_sz);
+ // _(SIOCNRGETPARMS, WRITE, struct_nr_parms_struct_sz);
+ // _(SIOCAIPXPRISLT, READ, sizeof(char));
+ // _(SIOCNRSETPARMS, READ, struct_nr_parms_struct_sz);
+ // _(SIOCAX25ADDUID, READ, struct_sockaddr_ax25_sz);
+ // _(SIOCNRDECOBS, NONE, 0);
+ // _(SIOCAX25DELUID, READ, struct_sockaddr_ax25_sz);
+ // _(SIOCIPXCFGDATA, WRITE, struct_ipx_config_data_sz);
+ // _(SIOCAX25NOUID, READ, sizeof(int));
+ // _(SIOCNRRTCTL, READ, sizeof(int));
+ // _(SIOCAX25DIGCTL, READ, sizeof(int));
+ // _(SIOCAX25GETPARMS, WRITE, struct_ax25_parms_struct_sz);
+ // _(SIOCAX25SETPARMS, READ, struct_ax25_parms_struct_sz);
+#endif
+#undef _
+}
+
+static bool ioctl_initialized = false;
+
+struct ioctl_desc_compare {
+ bool operator()(const ioctl_desc& left, const ioctl_desc& right) const {
+ return left.req < right.req;
+ }
+};
+
+static void ioctl_init() {
+ ioctl_table_fill();
+ InternalSort(&ioctl_table, ioctl_table_size, ioctl_desc_compare());
+
+ bool bad = false;
+ for (unsigned i = 0; i < ioctl_table_size - 1; ++i) {
+ if (ioctl_table[i].req >= ioctl_table[i + 1].req) {
+ Printf("Duplicate or unsorted ioctl request id %x >= %x (%s vs %s)\n",
+ ioctl_table[i].req, ioctl_table[i + 1].req, ioctl_table[i].name,
+ ioctl_table[i + 1].name);
+ bad = true;
+ }
+ }
+
+ if (bad) Die();
+
+ ioctl_initialized = true;
+}
+
+// Handle the most evil ioctls that encode argument value as part of request id.
+static unsigned ioctl_request_fixup(unsigned req) {
+#if SANITIZER_LINUX
+ if ((req & ~0x3fff001fU) == IOCTL_EVIOCGBIT)
+ return IOCTL_EVIOCGBIT;
+ if ((req & ~0x3fU) == IOCTL_EVIOCGABS)
+ return IOCTL_EVIOCGABS;
+ if ((req & ~0x3fU) == IOCTL_EVIOCSABS)
+ return IOCTL_EVIOCSABS;
+#endif
+ return req;
+}
+
+static const ioctl_desc *ioctl_table_lookup(unsigned req) {
+ int left = 0;
+ int right = ioctl_table_size;
+ while (left < right) {
+ int mid = (left + right) / 2;
+ if (ioctl_table[mid].req < req)
+ left = mid + 1;
+ else
+ right = mid;
+ }
+ if (left == right && ioctl_table[left].req == req)
+ return ioctl_table + left;
+ else
+ return 0;
+}
+
+static const ioctl_desc *ioctl_lookup(unsigned req) {
+ req = ioctl_request_fixup(req);
+ const ioctl_desc *desc = ioctl_table_lookup(req);
+ if (desc) return desc;
+
+ // Try stripping access size from the request id.
+ desc = ioctl_table_lookup(req & ~0x3fff0000U);
+ // Sanity check: requests that encode access size are either read or write and
+ // have size of 0 in the table.
+ if (desc && desc->size == 0 &&
+ (desc->type == ioctl_desc::WRITE || desc->type == ioctl_desc::READ))
+ return desc;
+ return 0;
+}
+
+static void ioctl_common_pre(void *ctx, const ioctl_desc *desc, int d,
+ unsigned request, void *arg) {
+ if (desc->type == ioctl_desc::READ) {
+ unsigned size = desc->size ? desc->size : IOC_SIZE(request);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, arg, size);
+ }
+ if (desc->type != ioctl_desc::CUSTOM)
+ return;
+ switch (request) {
+ case 0x00008912: { // SIOCGIFCONF
+ struct __sanitizer_ifconf *ifc = (__sanitizer_ifconf *)arg;
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, &ifc->ifc_len, sizeof(ifc->ifc_len));
+ break;
+ }
+ }
+ return;
+}
+
+static void ioctl_common_post(void *ctx, const ioctl_desc *desc, int res, int d,
+ unsigned request, void *arg) {
+ if (desc->type == ioctl_desc::WRITE) {
+ // FIXME: add verbose output
+ unsigned size = desc->size ? desc->size : IOC_SIZE(request);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, arg, size);
+ }
+ if (desc->type != ioctl_desc::CUSTOM)
+ return;
+ switch (request) {
+ case 0x00008912: { // SIOCGIFCONF
+ struct __sanitizer_ifconf *ifc = (__sanitizer_ifconf *)arg;
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ifc->ifc_ifcu.ifcu_req, ifc->ifc_len);
+ break;
+ }
+ }
+ return;
+}
diff --git a/libsanitizer/sanitizer_common/sanitizer_common_interceptors_scanf.inc b/libsanitizer/sanitizer_common/sanitizer_common_interceptors_scanf.inc
index 5b761382d3e..2660dada2be 100644
--- a/libsanitizer/sanitizer_common/sanitizer_common_interceptors_scanf.inc
+++ b/libsanitizer/sanitizer_common/sanitizer_common_interceptors_scanf.inc
@@ -276,7 +276,7 @@ static void scanf_common(void *ctx, int n_inputs, bool allowGnuMalloc,
CHECK_GT(n_inputs, 0);
const char *p = format;
- while (*p && n_inputs) {
+ while (*p) {
ScanfDirective dir;
p = scanf_parse_next(p, allowGnuMalloc, &dir);
if (!p)
@@ -299,6 +299,8 @@ static void scanf_common(void *ctx, int n_inputs, bool allowGnuMalloc,
void *argp = va_arg(aq, void *);
if (dir.convSpecifier != 'n')
--n_inputs;
+ if (n_inputs < 0)
+ break;
if (size == SSS_STRLEN) {
size = internal_strlen((const char *)argp) + 1;
}
diff --git a/libsanitizer/sanitizer_common/sanitizer_common_libcdep.cc b/libsanitizer/sanitizer_common/sanitizer_common_libcdep.cc
new file mode 100644
index 00000000000..215a61deab6
--- /dev/null
+++ b/libsanitizer/sanitizer_common/sanitizer_common_libcdep.cc
@@ -0,0 +1,35 @@
+//===-- sanitizer_common_libcdep.cc ---------------------------------------===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between AddressSanitizer and ThreadSanitizer
+// run-time libraries.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common.h"
+
+namespace __sanitizer {
+
+bool PrintsToTty() {
+ MaybeOpenReportFile();
+ return internal_isatty(report_fd) != 0;
+}
+
+bool PrintsToTtyCached() {
+ // FIXME: Add proper Windows support to AnsiColorDecorator and re-enable color
+ // printing on Windows.
+ if (SANITIZER_WINDOWS)
+ return 0;
+
+ static int cached = 0;
+ static bool prints_to_tty;
+ if (!cached) { // Not thread-safe.
+ prints_to_tty = PrintsToTty();
+ cached = 1;
+ }
+ return prints_to_tty;
+}
+} // namespace __sanitizer
diff --git a/libsanitizer/sanitizer_common/sanitizer_common_syscalls.inc b/libsanitizer/sanitizer_common/sanitizer_common_syscalls.inc
new file mode 100644
index 00000000000..bc097c847d4
--- /dev/null
+++ b/libsanitizer/sanitizer_common/sanitizer_common_syscalls.inc
@@ -0,0 +1,2732 @@
+//===-- sanitizer_common_syscalls.inc ---------------------------*- C++ -*-===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Common syscalls handlers for tools like AddressSanitizer,
+// ThreadSanitizer, MemorySanitizer, etc.
+//
+// This file should be included into the tool's interceptor file,
+// which has to define it's own macros:
+// COMMON_SYSCALL_PRE_READ_RANGE
+// Called in prehook for regions that will be read by the kernel and
+// must be initialized.
+// COMMON_SYSCALL_PRE_WRITE_RANGE
+// Called in prehook for regions that will be written to by the kernel
+// and must be addressable. The actual write range may be smaller than
+// reported in the prehook. See POST_WRITE_RANGE.
+// COMMON_SYSCALL_POST_READ_RANGE
+// Called in posthook for regions that were read by the kernel. Does
+// not make much sense.
+// COMMON_SYSCALL_POST_WRITE_RANGE
+// Called in posthook for regions that were written to by the kernel
+// and are now initialized.
+// COMMON_SYSCALL_FD_CLOSE(fd)
+// Called before closing file descriptor fd.
+// COMMON_SYSCALL_PRE_FORK()
+// Called before fork syscall.
+// COMMON_SYSCALL_POST_FORK(long res)
+// Called after fork syscall.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_platform.h"
+#if SANITIZER_LINUX
+
+#include "sanitizer_libc.h"
+
+#define PRE_SYSCALL(name) \
+ SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_syscall_pre_impl_##name
+#define PRE_READ(p, s) COMMON_SYSCALL_PRE_READ_RANGE(p, s)
+#define PRE_WRITE(p, s) COMMON_SYSCALL_PRE_WRITE_RANGE(p, s)
+
+#define POST_SYSCALL(name) \
+ SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_syscall_post_impl_##name
+#define POST_READ(p, s) COMMON_SYSCALL_POST_READ_RANGE(p, s)
+#define POST_WRITE(p, s) COMMON_SYSCALL_POST_WRITE_RANGE(p, s)
+
+#ifndef COMMON_SYSCALL_FD_CLOSE
+# define COMMON_SYSCALL_FD_CLOSE(fd)
+#endif
+
+#ifndef COMMON_SYSCALL_PRE_FORK
+# define COMMON_SYSCALL_PRE_FORK()
+#endif
+
+#ifndef COMMON_SYSCALL_POST_FORK
+# define COMMON_SYSCALL_POST_FORK(res)
+#endif
+
+// FIXME: do some kind of PRE_READ for all syscall arguments (int(s) and such).
+
+extern "C" {
+struct sanitizer_kernel_iovec {
+ void *iov_base;
+ unsigned long iov_len;
+};
+
+struct sanitizer_kernel_msghdr {
+ void *msg_name;
+ int msg_namelen;
+ struct sanitizer_kernel_iovec *msg_iov;
+ unsigned long msg_iovlen;
+ void *msg_control;
+ unsigned long msg_controllen;
+ unsigned msg_flags;
+};
+
+struct sanitizer_kernel_mmsghdr {
+ struct sanitizer_kernel_msghdr msg_hdr;
+ unsigned msg_len;
+};
+
+struct sanitizer_kernel_timespec {
+ long tv_sec;
+ long tv_nsec;
+};
+
+struct sanitizer_kernel_timeval {
+ long tv_sec;
+ long tv_usec;
+};
+
+struct sanitizer_kernel_rusage {
+ struct sanitizer_kernel_timeval ru_timeval[2];
+ long ru_long[14];
+};
+
+struct sanitizer_kernel_sockaddr {
+ unsigned short sa_family;
+ char sa_data[14];
+};
+
+// Real sigset size is always passed as a syscall argument.
+// Declare it "void" to catch sizeof(kernel_sigset_t).
+typedef void kernel_sigset_t;
+
+static void kernel_write_iovec(const __sanitizer_iovec *iovec,
+ SIZE_T iovlen, SIZE_T maxlen) {
+ for (SIZE_T i = 0; i < iovlen && maxlen; ++i) {
+ SSIZE_T sz = Min(iovec[i].iov_len, maxlen);
+ POST_WRITE(iovec[i].iov_base, sz);
+ maxlen -= sz;
+ }
+}
+
+// This functions uses POST_READ, because it needs to run after syscall to know
+// the real read range.
+static void kernel_read_iovec(const __sanitizer_iovec *iovec,
+ SIZE_T iovlen, SIZE_T maxlen) {
+ POST_READ(iovec, sizeof(*iovec) * iovlen);
+ for (SIZE_T i = 0; i < iovlen && maxlen; ++i) {
+ SSIZE_T sz = Min(iovec[i].iov_len, maxlen);
+ POST_READ(iovec[i].iov_base, sz);
+ maxlen -= sz;
+ }
+}
+
+PRE_SYSCALL(recvmsg)(long sockfd, sanitizer_kernel_msghdr *msg, long flags) {
+ PRE_READ(msg, sizeof(*msg));
+}
+
+POST_SYSCALL(recvmsg)(long res, long sockfd, sanitizer_kernel_msghdr *msg,
+ long flags) {
+ if (res >= 0) {
+ if (msg) {
+ for (unsigned long i = 0; i < msg->msg_iovlen; ++i) {
+ POST_WRITE(msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len);
+ }
+ POST_WRITE(msg->msg_control, msg->msg_controllen);
+ }
+ }
+}
+
+PRE_SYSCALL(recvmmsg)(long fd, sanitizer_kernel_mmsghdr *msg, long vlen,
+ long flags, void *timeout) {
+ PRE_READ(msg, vlen * sizeof(*msg));
+}
+
+POST_SYSCALL(recvmmsg)(long res, long fd, sanitizer_kernel_mmsghdr *msg,
+ long vlen, long flags, void *timeout) {
+ if (res >= 0) {
+ if (msg) {
+ for (unsigned long i = 0; i < msg->msg_hdr.msg_iovlen; ++i) {
+ POST_WRITE(msg->msg_hdr.msg_iov[i].iov_base,
+ msg->msg_hdr.msg_iov[i].iov_len);
+ }
+ POST_WRITE(msg->msg_hdr.msg_control, msg->msg_hdr.msg_controllen);
+ POST_WRITE(&msg->msg_len, sizeof(msg->msg_len));
+ }
+ if (timeout) POST_WRITE(timeout, struct_timespec_sz);
+ }
+}
+
+PRE_SYSCALL(read)(long fd, void *buf, uptr count) {
+ if (buf) {
+ PRE_WRITE(buf, count);
+ }
+}
+
+POST_SYSCALL(read)(long res, long fd, void *buf, uptr count) {
+ if (res > 0 && buf) {
+ POST_WRITE(buf, res);
+ }
+}
+
+PRE_SYSCALL(time)(void *tloc) {}
+
+POST_SYSCALL(time)(long res, void *tloc) {
+ if (res >= 0) {
+ if (tloc) POST_WRITE(tloc, sizeof(long));
+ }
+}
+
+PRE_SYSCALL(stime)(void *tptr) {}
+
+POST_SYSCALL(stime)(long res, void *tptr) {
+ if (res >= 0) {
+ if (tptr) POST_WRITE(tptr, sizeof(long));
+ }
+}
+
+PRE_SYSCALL(gettimeofday)(void *tv, void *tz) {}
+
+POST_SYSCALL(gettimeofday)(long res, void *tv, void *tz) {
+ if (res >= 0) {
+ if (tv) POST_WRITE(tv, timeval_sz);
+ if (tz) POST_WRITE(tz, struct_timezone_sz);
+ }
+}
+
+PRE_SYSCALL(settimeofday)(void *tv, void *tz) {}
+
+POST_SYSCALL(settimeofday)(long res, void *tv, void *tz) {
+ if (res >= 0) {
+ if (tv) POST_WRITE(tv, timeval_sz);
+ if (tz) POST_WRITE(tz, struct_timezone_sz);
+ }
+}
+
+PRE_SYSCALL(adjtimex)(void *txc_p) {}
+
+POST_SYSCALL(adjtimex)(long res, void *txc_p) {
+ if (res >= 0) {
+ if (txc_p) POST_WRITE(txc_p, struct_timex_sz);
+ }
+}
+
+PRE_SYSCALL(times)(void *tbuf) {}
+
+POST_SYSCALL(times)(long res, void *tbuf) {
+ if (res >= 0) {
+ if (tbuf) POST_WRITE(tbuf, struct_tms_sz);
+ }
+}
+
+PRE_SYSCALL(gettid)() {}
+
+POST_SYSCALL(gettid)(long res) {}
+
+PRE_SYSCALL(nanosleep)(void *rqtp, void *rmtp) {}
+
+POST_SYSCALL(nanosleep)(long res, void *rqtp, void *rmtp) {
+ if (res >= 0) {
+ if (rqtp) POST_WRITE(rqtp, struct_timespec_sz);
+ if (rmtp) POST_WRITE(rmtp, struct_timespec_sz);
+ }
+}
+
+PRE_SYSCALL(alarm)(long seconds) {}
+
+POST_SYSCALL(alarm)(long res, long seconds) {}
+
+PRE_SYSCALL(getpid)() {}
+
+POST_SYSCALL(getpid)(long res) {}
+
+PRE_SYSCALL(getppid)() {}
+
+POST_SYSCALL(getppid)(long res) {}
+
+PRE_SYSCALL(getuid)() {}
+
+POST_SYSCALL(getuid)(long res) {}
+
+PRE_SYSCALL(geteuid)() {}
+
+POST_SYSCALL(geteuid)(long res) {}
+
+PRE_SYSCALL(getgid)() {}
+
+POST_SYSCALL(getgid)(long res) {}
+
+PRE_SYSCALL(getegid)() {}
+
+POST_SYSCALL(getegid)(long res) {}
+
+PRE_SYSCALL(getresuid)(void *ruid, void *euid, void *suid) {}
+
+POST_SYSCALL(getresuid)(long res, void *ruid, void *euid, void *suid) {
+ if (res >= 0) {
+ if (ruid) POST_WRITE(ruid, sizeof(unsigned));
+ if (euid) POST_WRITE(euid, sizeof(unsigned));
+ if (suid) POST_WRITE(suid, sizeof(unsigned));
+ }
+}
+
+PRE_SYSCALL(getresgid)(void *rgid, void *egid, void *sgid) {}
+
+POST_SYSCALL(getresgid)(long res, void *rgid, void *egid, void *sgid) {
+ if (res >= 0) {
+ if (rgid) POST_WRITE(rgid, sizeof(unsigned));
+ if (egid) POST_WRITE(egid, sizeof(unsigned));
+ if (sgid) POST_WRITE(sgid, sizeof(unsigned));
+ }
+}
+
+PRE_SYSCALL(getpgid)(long pid) {}
+
+POST_SYSCALL(getpgid)(long res, long pid) {}
+
+PRE_SYSCALL(getpgrp)() {}
+
+POST_SYSCALL(getpgrp)(long res) {}
+
+PRE_SYSCALL(getsid)(long pid) {}
+
+POST_SYSCALL(getsid)(long res, long pid) {}
+
+PRE_SYSCALL(getgroups)(long gidsetsize, void *grouplist) {}
+
+POST_SYSCALL(getgroups)(long res, long gidsetsize,
+ __sanitizer___kernel_gid_t *grouplist) {
+ if (res >= 0) {
+ if (grouplist) POST_WRITE(grouplist, res * sizeof(*grouplist));
+ }
+}
+
+PRE_SYSCALL(setregid)(long rgid, long egid) {}
+
+POST_SYSCALL(setregid)(long res, long rgid, long egid) {}
+
+PRE_SYSCALL(setgid)(long gid) {}
+
+POST_SYSCALL(setgid)(long res, long gid) {}
+
+PRE_SYSCALL(setreuid)(long ruid, long euid) {}
+
+POST_SYSCALL(setreuid)(long res, long ruid, long euid) {}
+
+PRE_SYSCALL(setuid)(long uid) {}
+
+POST_SYSCALL(setuid)(long res, long uid) {}
+
+PRE_SYSCALL(setresuid)(long ruid, long euid, long suid) {}
+
+POST_SYSCALL(setresuid)(long res, long ruid, long euid, long suid) {}
+
+PRE_SYSCALL(setresgid)(long rgid, long egid, long sgid) {}
+
+POST_SYSCALL(setresgid)(long res, long rgid, long egid, long sgid) {}
+
+PRE_SYSCALL(setfsuid)(long uid) {}
+
+POST_SYSCALL(setfsuid)(long res, long uid) {}
+
+PRE_SYSCALL(setfsgid)(long gid) {}
+
+POST_SYSCALL(setfsgid)(long res, long gid) {}
+
+PRE_SYSCALL(setpgid)(long pid, long pgid) {}
+
+POST_SYSCALL(setpgid)(long res, long pid, long pgid) {}
+
+PRE_SYSCALL(setsid)() {}
+
+POST_SYSCALL(setsid)(long res) {}
+
+PRE_SYSCALL(setgroups)(long gidsetsize, __sanitizer___kernel_gid_t *grouplist) {
+ if (grouplist) POST_WRITE(grouplist, gidsetsize * sizeof(*grouplist));
+}
+
+POST_SYSCALL(setgroups)(long res, long gidsetsize,
+ __sanitizer___kernel_gid_t *grouplist) {}
+
+PRE_SYSCALL(acct)(const void *name) {
+ if (name)
+ PRE_READ(name, __sanitizer::internal_strlen((const char *)name) + 1);
+}
+
+POST_SYSCALL(acct)(long res, const void *name) {}
+
+PRE_SYSCALL(capget)(void *header, void *dataptr) {}
+
+POST_SYSCALL(capget)(long res, void *header, void *dataptr) {
+ if (res >= 0) {
+ if (header) POST_WRITE(header, __user_cap_header_struct_sz);
+ if (dataptr) POST_WRITE(dataptr, __user_cap_data_struct_sz);
+ }
+}
+
+PRE_SYSCALL(capset)(void *header, const void *data) {
+ if (data) PRE_READ(data, __user_cap_data_struct_sz);
+}
+
+POST_SYSCALL(capset)(long res, void *header, const void *data) {
+ if (res >= 0) {
+ if (header) POST_WRITE(header, __user_cap_header_struct_sz);
+ }
+}
+
+PRE_SYSCALL(personality)(long personality) {}
+
+POST_SYSCALL(personality)(long res, long personality) {}
+
+PRE_SYSCALL(sigpending)(void *set) {}
+
+POST_SYSCALL(sigpending)(long res, void *set) {
+ if (res >= 0) {
+ if (set) POST_WRITE(set, old_sigset_t_sz);
+ }
+}
+
+PRE_SYSCALL(sigprocmask)(long how, void *set, void *oset) {}
+
+POST_SYSCALL(sigprocmask)(long res, long how, void *set, void *oset) {
+ if (res >= 0) {
+ if (set) POST_WRITE(set, old_sigset_t_sz);
+ if (oset) POST_WRITE(oset, old_sigset_t_sz);
+ }
+}
+
+PRE_SYSCALL(getitimer)(long which, void *value) {}
+
+POST_SYSCALL(getitimer)(long res, long which, void *value) {
+ if (res >= 0) {
+ if (value) POST_WRITE(value, struct_itimerval_sz);
+ }
+}
+
+PRE_SYSCALL(setitimer)(long which, void *value, void *ovalue) {}
+
+POST_SYSCALL(setitimer)(long res, long which, void *value, void *ovalue) {
+ if (res >= 0) {
+ if (value) POST_WRITE(value, struct_itimerval_sz);
+ if (ovalue) POST_WRITE(ovalue, struct_itimerval_sz);
+ }
+}
+
+PRE_SYSCALL(timer_create)(long which_clock, void *timer_event_spec,
+ void *created_timer_id) {}
+
+POST_SYSCALL(timer_create)(long res, long which_clock, void *timer_event_spec,
+ void *created_timer_id) {
+ if (res >= 0) {
+ if (timer_event_spec) POST_WRITE(timer_event_spec, struct_sigevent_sz);
+ if (created_timer_id) POST_WRITE(created_timer_id, sizeof(long));
+ }
+}
+
+PRE_SYSCALL(timer_gettime)(long timer_id, void *setting) {}
+
+POST_SYSCALL(timer_gettime)(long res, long timer_id, void *setting) {
+ if (res >= 0) {
+ if (setting) POST_WRITE(setting, struct_itimerspec_sz);
+ }
+}
+
+PRE_SYSCALL(timer_getoverrun)(long timer_id) {}
+
+POST_SYSCALL(timer_getoverrun)(long res, long timer_id) {}
+
+PRE_SYSCALL(timer_settime)(long timer_id, long flags, const void *new_setting,
+ void *old_setting) {
+ if (new_setting) PRE_READ(new_setting, struct_itimerspec_sz);
+}
+
+POST_SYSCALL(timer_settime)(long res, long timer_id, long flags,
+ const void *new_setting, void *old_setting) {
+ if (res >= 0) {
+ if (old_setting) POST_WRITE(old_setting, struct_itimerspec_sz);
+ }
+}
+
+PRE_SYSCALL(timer_delete)(long timer_id) {}
+
+POST_SYSCALL(timer_delete)(long res, long timer_id) {}
+
+PRE_SYSCALL(clock_settime)(long which_clock, const void *tp) {
+ if (tp) PRE_READ(tp, struct_timespec_sz);
+}
+
+POST_SYSCALL(clock_settime)(long res, long which_clock, const void *tp) {}
+
+PRE_SYSCALL(clock_gettime)(long which_clock, void *tp) {}
+
+POST_SYSCALL(clock_gettime)(long res, long which_clock, void *tp) {
+ if (res >= 0) {
+ if (tp) POST_WRITE(tp, struct_timespec_sz);
+ }
+}
+
+PRE_SYSCALL(clock_adjtime)(long which_clock, void *tx) {}
+
+POST_SYSCALL(clock_adjtime)(long res, long which_clock, void *tx) {
+ if (res >= 0) {
+ if (tx) POST_WRITE(tx, struct_timex_sz);
+ }
+}
+
+PRE_SYSCALL(clock_getres)(long which_clock, void *tp) {}
+
+POST_SYSCALL(clock_getres)(long res, long which_clock, void *tp) {
+ if (res >= 0) {
+ if (tp) POST_WRITE(tp, struct_timespec_sz);
+ }
+}
+
+PRE_SYSCALL(clock_nanosleep)(long which_clock, long flags, const void *rqtp,
+ void *rmtp) {
+ if (rqtp) PRE_READ(rqtp, struct_timespec_sz);
+}
+
+POST_SYSCALL(clock_nanosleep)(long res, long which_clock, long flags,
+ const void *rqtp, void *rmtp) {
+ if (res >= 0) {
+ if (rmtp) POST_WRITE(rmtp, struct_timespec_sz);
+ }
+}
+
+PRE_SYSCALL(nice)(long increment) {}
+
+POST_SYSCALL(nice)(long res, long increment) {}
+
+PRE_SYSCALL(sched_setscheduler)(long pid, long policy, void *param) {}
+
+POST_SYSCALL(sched_setscheduler)(long res, long pid, long policy, void *param) {
+ if (res >= 0) {
+ if (param) POST_WRITE(param, struct_sched_param_sz);
+ }
+}
+
+PRE_SYSCALL(sched_setparam)(long pid, void *param) {
+ if (param) PRE_READ(param, struct_sched_param_sz);
+}
+
+POST_SYSCALL(sched_setparam)(long res, long pid, void *param) {}
+
+PRE_SYSCALL(sched_getscheduler)(long pid) {}
+
+POST_SYSCALL(sched_getscheduler)(long res, long pid) {}
+
+PRE_SYSCALL(sched_getparam)(long pid, void *param) {}
+
+POST_SYSCALL(sched_getparam)(long res, long pid, void *param) {
+ if (res >= 0) {
+ if (param) POST_WRITE(param, struct_sched_param_sz);
+ }
+}
+
+PRE_SYSCALL(sched_setaffinity)(long pid, long len, void *user_mask_ptr) {
+ if (user_mask_ptr) PRE_READ(user_mask_ptr, len);
+}
+
+POST_SYSCALL(sched_setaffinity)(long res, long pid, long len,
+ void *user_mask_ptr) {}
+
+PRE_SYSCALL(sched_getaffinity)(long pid, long len, void *user_mask_ptr) {}
+
+POST_SYSCALL(sched_getaffinity)(long res, long pid, long len,
+ void *user_mask_ptr) {
+ if (res >= 0) {
+ if (user_mask_ptr) POST_WRITE(user_mask_ptr, len);
+ }
+}
+
+PRE_SYSCALL(sched_yield)() {}
+
+POST_SYSCALL(sched_yield)(long res) {}
+
+PRE_SYSCALL(sched_get_priority_max)(long policy) {}
+
+POST_SYSCALL(sched_get_priority_max)(long res, long policy) {}
+
+PRE_SYSCALL(sched_get_priority_min)(long policy) {}
+
+POST_SYSCALL(sched_get_priority_min)(long res, long policy) {}
+
+PRE_SYSCALL(sched_rr_get_interval)(long pid, void *interval) {}
+
+POST_SYSCALL(sched_rr_get_interval)(long res, long pid, void *interval) {
+ if (res >= 0) {
+ if (interval) POST_WRITE(interval, struct_timespec_sz);
+ }
+}
+
+PRE_SYSCALL(setpriority)(long which, long who, long niceval) {}
+
+POST_SYSCALL(setpriority)(long res, long which, long who, long niceval) {}
+
+PRE_SYSCALL(getpriority)(long which, long who) {}
+
+POST_SYSCALL(getpriority)(long res, long which, long who) {}
+
+PRE_SYSCALL(shutdown)(long arg0, long arg1) {}
+
+POST_SYSCALL(shutdown)(long res, long arg0, long arg1) {}
+
+PRE_SYSCALL(reboot)(long magic1, long magic2, long cmd, void *arg) {}
+
+POST_SYSCALL(reboot)(long res, long magic1, long magic2, long cmd, void *arg) {}
+
+PRE_SYSCALL(restart_syscall)() {}
+
+POST_SYSCALL(restart_syscall)(long res) {}
+
+PRE_SYSCALL(kexec_load)(long entry, long nr_segments, void *segments,
+ long flags) {}
+
+POST_SYSCALL(kexec_load)(long res, long entry, long nr_segments, void *segments,
+ long flags) {
+ if (res >= 0) {
+ if (segments) POST_WRITE(segments, struct_kexec_segment_sz);
+ }
+}
+
+PRE_SYSCALL(exit)(long error_code) {}
+
+POST_SYSCALL(exit)(long res, long error_code) {}
+
+PRE_SYSCALL(exit_group)(long error_code) {}
+
+POST_SYSCALL(exit_group)(long res, long error_code) {}
+
+PRE_SYSCALL(wait4)(long pid, void *stat_addr, long options, void *ru) {}
+
+POST_SYSCALL(wait4)(long res, long pid, void *stat_addr, long options,
+ void *ru) {
+ if (res >= 0) {
+ if (stat_addr) POST_WRITE(stat_addr, sizeof(int));
+ if (ru) POST_WRITE(ru, struct_rusage_sz);
+ }
+}
+
+PRE_SYSCALL(waitid)(long which, long pid, void *infop, long options, void *ru) {
+}
+
+POST_SYSCALL(waitid)(long res, long which, long pid, void *infop, long options,
+ void *ru) {
+ if (res >= 0) {
+ if (infop) POST_WRITE(infop, siginfo_t_sz);
+ if (ru) POST_WRITE(ru, struct_rusage_sz);
+ }
+}
+
+PRE_SYSCALL(waitpid)(long pid, void *stat_addr, long options) {}
+
+POST_SYSCALL(waitpid)(long res, long pid, void *stat_addr, long options) {
+ if (res >= 0) {
+ if (stat_addr) POST_WRITE(stat_addr, sizeof(int));
+ }
+}
+
+PRE_SYSCALL(set_tid_address)(void *tidptr) {}
+
+POST_SYSCALL(set_tid_address)(long res, void *tidptr) {
+ if (res >= 0) {
+ if (tidptr) POST_WRITE(tidptr, sizeof(int));
+ }
+}
+
+PRE_SYSCALL(init_module)(void *umod, long len, const void *uargs) {
+ if (uargs)
+ PRE_READ(uargs, __sanitizer::internal_strlen((const char *)uargs) + 1);
+}
+
+POST_SYSCALL(init_module)(long res, void *umod, long len, const void *uargs) {}
+
+PRE_SYSCALL(delete_module)(const void *name_user, long flags) {
+ if (name_user)
+ PRE_READ(name_user,
+ __sanitizer::internal_strlen((const char *)name_user) + 1);
+}
+
+POST_SYSCALL(delete_module)(long res, const void *name_user, long flags) {}
+
+PRE_SYSCALL(rt_sigprocmask)(long how, void *set, void *oset, long sigsetsize) {}
+
+POST_SYSCALL(rt_sigprocmask)(long res, long how, kernel_sigset_t *set,
+ kernel_sigset_t *oset, long sigsetsize) {
+ if (res >= 0) {
+ if (set) POST_WRITE(set, sigsetsize);
+ if (oset) POST_WRITE(oset, sigsetsize);
+ }
+}
+
+PRE_SYSCALL(rt_sigpending)(void *set, long sigsetsize) {}
+
+POST_SYSCALL(rt_sigpending)(long res, kernel_sigset_t *set, long sigsetsize) {
+ if (res >= 0) {
+ if (set) POST_WRITE(set, sigsetsize);
+ }
+}
+
+PRE_SYSCALL(rt_sigtimedwait)(const kernel_sigset_t *uthese, void *uinfo,
+ const void *uts, long sigsetsize) {
+ if (uthese) PRE_READ(uthese, sigsetsize);
+ if (uts) PRE_READ(uts, struct_timespec_sz);
+}
+
+POST_SYSCALL(rt_sigtimedwait)(long res, const void *uthese, void *uinfo,
+ const void *uts, long sigsetsize) {
+ if (res >= 0) {
+ if (uinfo) POST_WRITE(uinfo, siginfo_t_sz);
+ }
+}
+
+PRE_SYSCALL(rt_tgsigqueueinfo)(long tgid, long pid, long sig, void *uinfo) {}
+
+POST_SYSCALL(rt_tgsigqueueinfo)(long res, long tgid, long pid, long sig,
+ void *uinfo) {
+ if (res >= 0) {
+ if (uinfo) POST_WRITE(uinfo, siginfo_t_sz);
+ }
+}
+
+PRE_SYSCALL(kill)(long pid, long sig) {}
+
+POST_SYSCALL(kill)(long res, long pid, long sig) {}
+
+PRE_SYSCALL(tgkill)(long tgid, long pid, long sig) {}
+
+POST_SYSCALL(tgkill)(long res, long tgid, long pid, long sig) {}
+
+PRE_SYSCALL(tkill)(long pid, long sig) {}
+
+POST_SYSCALL(tkill)(long res, long pid, long sig) {}
+
+PRE_SYSCALL(rt_sigqueueinfo)(long pid, long sig, void *uinfo) {}
+
+POST_SYSCALL(rt_sigqueueinfo)(long res, long pid, long sig, void *uinfo) {
+ if (res >= 0) {
+ if (uinfo) POST_WRITE(uinfo, siginfo_t_sz);
+ }
+}
+
+PRE_SYSCALL(sgetmask)() {}
+
+POST_SYSCALL(sgetmask)(long res) {}
+
+PRE_SYSCALL(ssetmask)(long newmask) {}
+
+POST_SYSCALL(ssetmask)(long res, long newmask) {}
+
+PRE_SYSCALL(signal)(long sig, long handler) {}
+
+POST_SYSCALL(signal)(long res, long sig, long handler) {}
+
+PRE_SYSCALL(pause)() {}
+
+POST_SYSCALL(pause)(long res) {}
+
+PRE_SYSCALL(sync)() {}
+
+POST_SYSCALL(sync)(long res) {}
+
+PRE_SYSCALL(fsync)(long fd) {}
+
+POST_SYSCALL(fsync)(long res, long fd) {}
+
+PRE_SYSCALL(fdatasync)(long fd) {}
+
+POST_SYSCALL(fdatasync)(long res, long fd) {}
+
+PRE_SYSCALL(bdflush)(long func, long data) {}
+
+POST_SYSCALL(bdflush)(long res, long func, long data) {}
+
+PRE_SYSCALL(mount)(void *dev_name, void *dir_name, void *type, long flags,
+ void *data) {}
+
+POST_SYSCALL(mount)(long res, void *dev_name, void *dir_name, void *type,
+ long flags, void *data) {
+ if (res >= 0) {
+ if (dev_name)
+ POST_WRITE(dev_name,
+ __sanitizer::internal_strlen((const char *)dev_name) + 1);
+ if (dir_name)
+ POST_WRITE(dir_name,
+ __sanitizer::internal_strlen((const char *)dir_name) + 1);
+ if (type)
+ POST_WRITE(type, __sanitizer::internal_strlen((const char *)type) + 1);
+ }
+}
+
+PRE_SYSCALL(umount)(void *name, long flags) {}
+
+POST_SYSCALL(umount)(long res, void *name, long flags) {
+ if (res >= 0) {
+ if (name)
+ POST_WRITE(name, __sanitizer::internal_strlen((const char *)name) + 1);
+ }
+}
+
+PRE_SYSCALL(oldumount)(void *name) {}
+
+POST_SYSCALL(oldumount)(long res, void *name) {
+ if (res >= 0) {
+ if (name)
+ POST_WRITE(name, __sanitizer::internal_strlen((const char *)name) + 1);
+ }
+}
+
+PRE_SYSCALL(truncate)(const void *path, long length) {
+ if (path)
+ PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
+}
+
+POST_SYSCALL(truncate)(long res, const void *path, long length) {}
+
+PRE_SYSCALL(ftruncate)(long fd, long length) {}
+
+POST_SYSCALL(ftruncate)(long res, long fd, long length) {}
+
+PRE_SYSCALL(stat)(const void *filename, void *statbuf) {
+ if (filename)
+ PRE_READ(filename,
+ __sanitizer::internal_strlen((const char *)filename) + 1);
+}
+
+POST_SYSCALL(stat)(long res, const void *filename, void *statbuf) {
+ if (res >= 0) {
+ if (statbuf) POST_WRITE(statbuf, struct___old_kernel_stat_sz);
+ }
+}
+
+PRE_SYSCALL(statfs)(const void *path, void *buf) {
+ if (path)
+ PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
+}
+
+POST_SYSCALL(statfs)(long res, const void *path, void *buf) {
+ if (res >= 0) {
+ if (buf) POST_WRITE(buf, struct_statfs_sz);
+ }
+}
+
+PRE_SYSCALL(statfs64)(const void *path, long sz, void *buf) {
+ if (path)
+ PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
+}
+
+POST_SYSCALL(statfs64)(long res, const void *path, long sz, void *buf) {
+ if (res >= 0) {
+ if (buf) POST_WRITE(buf, struct_statfs64_sz);
+ }
+}
+
+PRE_SYSCALL(fstatfs)(long fd, void *buf) {}
+
+POST_SYSCALL(fstatfs)(long res, long fd, void *buf) {
+ if (res >= 0) {
+ if (buf) POST_WRITE(buf, struct_statfs_sz);
+ }
+}
+
+PRE_SYSCALL(fstatfs64)(long fd, long sz, void *buf) {}
+
+POST_SYSCALL(fstatfs64)(long res, long fd, long sz, void *buf) {
+ if (res >= 0) {
+ if (buf) POST_WRITE(buf, struct_statfs64_sz);
+ }
+}
+
+PRE_SYSCALL(lstat)(const void *filename, void *statbuf) {
+ if (filename)
+ PRE_READ(filename,
+ __sanitizer::internal_strlen((const char *)filename) + 1);
+}
+
+POST_SYSCALL(lstat)(long res, const void *filename, void *statbuf) {
+ if (res >= 0) {
+ if (statbuf) POST_WRITE(statbuf, struct___old_kernel_stat_sz);
+ }
+}
+
+PRE_SYSCALL(fstat)(long fd, void *statbuf) {}
+
+POST_SYSCALL(fstat)(long res, long fd, void *statbuf) {
+ if (res >= 0) {
+ if (statbuf) POST_WRITE(statbuf, struct___old_kernel_stat_sz);
+ }
+}
+
+PRE_SYSCALL(newstat)(const void *filename, void *statbuf) {
+ if (filename)
+ PRE_READ(filename,
+ __sanitizer::internal_strlen((const char *)filename) + 1);
+}
+
+POST_SYSCALL(newstat)(long res, const void *filename, void *statbuf) {
+ if (res >= 0) {
+ if (statbuf) POST_WRITE(statbuf, struct_kernel_stat_sz);
+ }
+}
+
+PRE_SYSCALL(newlstat)(const void *filename, void *statbuf) {
+ if (filename)
+ PRE_READ(filename,
+ __sanitizer::internal_strlen((const char *)filename) + 1);
+}
+
+POST_SYSCALL(newlstat)(long res, const void *filename, void *statbuf) {
+ if (res >= 0) {
+ if (statbuf) POST_WRITE(statbuf, struct_kernel_stat_sz);
+ }
+}
+
+PRE_SYSCALL(newfstat)(long fd, void *statbuf) {}
+
+POST_SYSCALL(newfstat)(long res, long fd, void *statbuf) {
+ if (res >= 0) {
+ if (statbuf) POST_WRITE(statbuf, struct_kernel_stat_sz);
+ }
+}
+
+PRE_SYSCALL(ustat)(long dev, void *ubuf) {}
+
+POST_SYSCALL(ustat)(long res, long dev, void *ubuf) {
+ if (res >= 0) {
+ if (ubuf) POST_WRITE(ubuf, struct_ustat_sz);
+ }
+}
+
+PRE_SYSCALL(stat64)(const void *filename, void *statbuf) {
+ if (filename)
+ PRE_READ(filename,
+ __sanitizer::internal_strlen((const char *)filename) + 1);
+}
+
+POST_SYSCALL(stat64)(long res, const void *filename, void *statbuf) {
+ if (res >= 0) {
+ if (statbuf) POST_WRITE(statbuf, struct_kernel_stat64_sz);
+ }
+}
+
+PRE_SYSCALL(fstat64)(long fd, void *statbuf) {}
+
+POST_SYSCALL(fstat64)(long res, long fd, void *statbuf) {
+ if (res >= 0) {
+ if (statbuf) POST_WRITE(statbuf, struct_kernel_stat64_sz);
+ }
+}
+
+PRE_SYSCALL(lstat64)(const void *filename, void *statbuf) {
+ if (filename)
+ PRE_READ(filename,
+ __sanitizer::internal_strlen((const char *)filename) + 1);
+}
+
+POST_SYSCALL(lstat64)(long res, const void *filename, void *statbuf) {
+ if (res >= 0) {
+ if (statbuf) POST_WRITE(statbuf, struct_kernel_stat64_sz);
+ }
+}
+
+PRE_SYSCALL(setxattr)(const void *path, const void *name, const void *value,
+ long size, long flags) {
+ if (path)
+ PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
+ if (name)
+ PRE_READ(name, __sanitizer::internal_strlen((const char *)name) + 1);
+ if (value) PRE_READ(value, size);
+}
+
+POST_SYSCALL(setxattr)(long res, const void *path, const void *name,
+ const void *value, long size, long flags) {}
+
+PRE_SYSCALL(lsetxattr)(const void *path, const void *name, const void *value,
+ long size, long flags) {
+ if (path)
+ PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
+ if (name)
+ PRE_READ(name, __sanitizer::internal_strlen((const char *)name) + 1);
+ if (value) PRE_READ(value, size);
+}
+
+POST_SYSCALL(lsetxattr)(long res, const void *path, const void *name,
+ const void *value, long size, long flags) {}
+
+PRE_SYSCALL(fsetxattr)(long fd, const void *name, const void *value, long size,
+ long flags) {
+ if (name)
+ PRE_READ(name, __sanitizer::internal_strlen((const char *)name) + 1);
+ if (value) PRE_READ(value, size);
+}
+
+POST_SYSCALL(fsetxattr)(long res, long fd, const void *name, const void *value,
+ long size, long flags) {}
+
+PRE_SYSCALL(getxattr)(const void *path, const void *name, void *value,
+ long size) {
+ if (path)
+ PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
+ if (name)
+ PRE_READ(name, __sanitizer::internal_strlen((const char *)name) + 1);
+}
+
+POST_SYSCALL(getxattr)(long res, const void *path, const void *name,
+ void *value, long size) {
+ if (res >= 0) {
+ if (value) POST_WRITE(value, size);
+ }
+}
+
+PRE_SYSCALL(lgetxattr)(const void *path, const void *name, void *value,
+ long size) {
+ if (path)
+ PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
+ if (name)
+ PRE_READ(name, __sanitizer::internal_strlen((const char *)name) + 1);
+}
+
+POST_SYSCALL(lgetxattr)(long res, const void *path, const void *name,
+ void *value, long size) {
+ if (res >= 0) {
+ if (value) POST_WRITE(value, size);
+ }
+}
+
+PRE_SYSCALL(fgetxattr)(long fd, const void *name, void *value, long size) {
+ if (name)
+ PRE_READ(name, __sanitizer::internal_strlen((const char *)name) + 1);
+}
+
+POST_SYSCALL(fgetxattr)(long res, long fd, const void *name, void *value,
+ long size) {
+ if (res >= 0) {
+ if (value) POST_WRITE(value, size);
+ }
+}
+
+PRE_SYSCALL(listxattr)(const void *path, void *list, long size) {
+ if (path)
+ PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
+}
+
+POST_SYSCALL(listxattr)(long res, const void *path, void *list, long size) {
+ if (res >= 0) {
+ if (list) POST_WRITE(list, size);
+ }
+}
+
+PRE_SYSCALL(llistxattr)(const void *path, void *list, long size) {
+ if (path)
+ PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
+}
+
+POST_SYSCALL(llistxattr)(long res, const void *path, void *list, long size) {
+ if (res >= 0) {
+ if (list) POST_WRITE(list, size);
+ }
+}
+
+PRE_SYSCALL(flistxattr)(long fd, void *list, long size) {}
+
+POST_SYSCALL(flistxattr)(long res, long fd, void *list, long size) {
+ if (res >= 0) {
+ if (list) POST_WRITE(list, size);
+ }
+}
+
+PRE_SYSCALL(removexattr)(const void *path, const void *name) {
+ if (path)
+ PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
+ if (name)
+ PRE_READ(name, __sanitizer::internal_strlen((const char *)name) + 1);
+}
+
+POST_SYSCALL(removexattr)(long res, const void *path, const void *name) {}
+
+PRE_SYSCALL(lremovexattr)(const void *path, const void *name) {
+ if (path)
+ PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
+ if (name)
+ PRE_READ(name, __sanitizer::internal_strlen((const char *)name) + 1);
+}
+
+POST_SYSCALL(lremovexattr)(long res, const void *path, const void *name) {}
+
+PRE_SYSCALL(fremovexattr)(long fd, const void *name) {
+ if (name)
+ PRE_READ(name, __sanitizer::internal_strlen((const char *)name) + 1);
+}
+
+POST_SYSCALL(fremovexattr)(long res, long fd, const void *name) {}
+
+PRE_SYSCALL(brk)(long brk) {}
+
+POST_SYSCALL(brk)(long res, long brk) {}
+
+PRE_SYSCALL(mprotect)(long start, long len, long prot) {}
+
+POST_SYSCALL(mprotect)(long res, long start, long len, long prot) {}
+
+PRE_SYSCALL(mremap)(long addr, long old_len, long new_len, long flags,
+ long new_addr) {}
+
+POST_SYSCALL(mremap)(long res, long addr, long old_len, long new_len,
+ long flags, long new_addr) {}
+
+PRE_SYSCALL(remap_file_pages)(long start, long size, long prot, long pgoff,
+ long flags) {}
+
+POST_SYSCALL(remap_file_pages)(long res, long start, long size, long prot,
+ long pgoff, long flags) {}
+
+PRE_SYSCALL(msync)(long start, long len, long flags) {}
+
+POST_SYSCALL(msync)(long res, long start, long len, long flags) {}
+
+PRE_SYSCALL(munmap)(long addr, long len) {}
+
+POST_SYSCALL(munmap)(long res, long addr, long len) {}
+
+PRE_SYSCALL(mlock)(long start, long len) {}
+
+POST_SYSCALL(mlock)(long res, long start, long len) {}
+
+PRE_SYSCALL(munlock)(long start, long len) {}
+
+POST_SYSCALL(munlock)(long res, long start, long len) {}
+
+PRE_SYSCALL(mlockall)(long flags) {}
+
+POST_SYSCALL(mlockall)(long res, long flags) {}
+
+PRE_SYSCALL(munlockall)() {}
+
+POST_SYSCALL(munlockall)(long res) {}
+
+PRE_SYSCALL(madvise)(long start, long len, long behavior) {}
+
+POST_SYSCALL(madvise)(long res, long start, long len, long behavior) {}
+
+PRE_SYSCALL(mincore)(long start, long len, void *vec) {}
+
+POST_SYSCALL(mincore)(long res, long start, long len, void *vec) {
+ if (res >= 0) {
+ if (vec) {
+ POST_WRITE(vec, (len + GetPageSizeCached() - 1) / GetPageSizeCached());
+ }
+ }
+}
+
+PRE_SYSCALL(pivot_root)(const void *new_root, const void *put_old) {
+ if (new_root)
+ PRE_READ(new_root,
+ __sanitizer::internal_strlen((const char *)new_root) + 1);
+ if (put_old)
+ PRE_READ(put_old, __sanitizer::internal_strlen((const char *)put_old) + 1);
+}
+
+POST_SYSCALL(pivot_root)(long res, const void *new_root, const void *put_old) {}
+
+PRE_SYSCALL(chroot)(const void *filename) {
+ if (filename)
+ PRE_READ(filename,
+ __sanitizer::internal_strlen((const char *)filename) + 1);
+}
+
+POST_SYSCALL(chroot)(long res, const void *filename) {}
+
+PRE_SYSCALL(mknod)(const void *filename, long mode, long dev) {
+ if (filename)
+ PRE_READ(filename,
+ __sanitizer::internal_strlen((const char *)filename) + 1);
+}
+
+POST_SYSCALL(mknod)(long res, const void *filename, long mode, long dev) {}
+
+PRE_SYSCALL(link)(const void *oldname, const void *newname) {
+ if (oldname)
+ PRE_READ(oldname, __sanitizer::internal_strlen((const char *)oldname) + 1);
+ if (newname)
+ PRE_READ(newname, __sanitizer::internal_strlen((const char *)newname) + 1);
+}
+
+POST_SYSCALL(link)(long res, const void *oldname, const void *newname) {}
+
+PRE_SYSCALL(symlink)(const void *old, const void *new_) {
+ if (old) PRE_READ(old, __sanitizer::internal_strlen((const char *)old) + 1);
+ if (new_)
+ PRE_READ(new_, __sanitizer::internal_strlen((const char *)new_) + 1);
+}
+
+POST_SYSCALL(symlink)(long res, const void *old, const void *new_) {}
+
+PRE_SYSCALL(unlink)(const void *pathname) {
+ if (pathname)
+ PRE_READ(pathname,
+ __sanitizer::internal_strlen((const char *)pathname) + 1);
+}
+
+POST_SYSCALL(unlink)(long res, const void *pathname) {}
+
+PRE_SYSCALL(rename)(const void *oldname, const void *newname) {
+ if (oldname)
+ PRE_READ(oldname, __sanitizer::internal_strlen((const char *)oldname) + 1);
+ if (newname)
+ PRE_READ(newname, __sanitizer::internal_strlen((const char *)newname) + 1);
+}
+
+POST_SYSCALL(rename)(long res, const void *oldname, const void *newname) {}
+
+PRE_SYSCALL(chmod)(const void *filename, long mode) {
+ if (filename)
+ PRE_READ(filename,
+ __sanitizer::internal_strlen((const char *)filename) + 1);
+}
+
+POST_SYSCALL(chmod)(long res, const void *filename, long mode) {}
+
+PRE_SYSCALL(fchmod)(long fd, long mode) {}
+
+POST_SYSCALL(fchmod)(long res, long fd, long mode) {}
+
+PRE_SYSCALL(fcntl)(long fd, long cmd, long arg) {}
+
+POST_SYSCALL(fcntl)(long res, long fd, long cmd, long arg) {}
+
+PRE_SYSCALL(fcntl64)(long fd, long cmd, long arg) {}
+
+POST_SYSCALL(fcntl64)(long res, long fd, long cmd, long arg) {}
+
+PRE_SYSCALL(pipe)(void *fildes) {}
+
+POST_SYSCALL(pipe)(long res, void *fildes) {
+ if (res >= 0) {
+ if (fildes) POST_WRITE(fildes, sizeof(int));
+ }
+}
+
+PRE_SYSCALL(pipe2)(void *fildes, long flags) {}
+
+POST_SYSCALL(pipe2)(long res, void *fildes, long flags) {
+ if (res >= 0) {
+ if (fildes) POST_WRITE(fildes, sizeof(int));
+ }
+}
+
+PRE_SYSCALL(dup)(long fildes) {}
+
+POST_SYSCALL(dup)(long res, long fildes) {}
+
+PRE_SYSCALL(dup2)(long oldfd, long newfd) {}
+
+POST_SYSCALL(dup2)(long res, long oldfd, long newfd) {}
+
+PRE_SYSCALL(dup3)(long oldfd, long newfd, long flags) {}
+
+POST_SYSCALL(dup3)(long res, long oldfd, long newfd, long flags) {}
+
+PRE_SYSCALL(ioperm)(long from, long num, long on) {}
+
+POST_SYSCALL(ioperm)(long res, long from, long num, long on) {}
+
+PRE_SYSCALL(ioctl)(long fd, long cmd, long arg) {}
+
+POST_SYSCALL(ioctl)(long res, long fd, long cmd, long arg) {}
+
+PRE_SYSCALL(flock)(long fd, long cmd) {}
+
+POST_SYSCALL(flock)(long res, long fd, long cmd) {}
+
+PRE_SYSCALL(io_setup)(long nr_reqs, void *ctx) {}
+
+POST_SYSCALL(io_setup)(long res, long nr_reqs, void *ctx) {
+ if (res >= 0) {
+ if (ctx) POST_WRITE(ctx, sizeof(long));
+ }
+}
+
+PRE_SYSCALL(io_destroy)(long ctx) {}
+
+POST_SYSCALL(io_destroy)(long res, long ctx) {}
+
+PRE_SYSCALL(io_getevents)(long ctx_id, long min_nr, long nr, void *events,
+ void *timeout) {
+ if (timeout) PRE_READ(timeout, struct_timespec_sz);
+}
+
+POST_SYSCALL(io_getevents)(long res, long ctx_id, long min_nr, long nr,
+ void *events, void *timeout) {
+ if (res >= 0) {
+ if (events) POST_WRITE(events, res * struct_io_event_sz);
+ if (timeout) POST_WRITE(timeout, struct_timespec_sz);
+ }
+}
+
+PRE_SYSCALL(io_submit)(long, long arg1, void *arg2) {}
+
+POST_SYSCALL(io_submit)(long res, long, long arg1, void *arg2) {}
+
+PRE_SYSCALL(io_cancel)(long ctx_id, void *iocb, void *result) {}
+
+POST_SYSCALL(io_cancel)(long res, long ctx_id, void *iocb, void *result) {
+ if (res >= 0) {
+ if (iocb) POST_WRITE(iocb, struct_iocb_sz);
+ if (result) POST_WRITE(result, struct_io_event_sz);
+ }
+}
+
+PRE_SYSCALL(sendfile)(long out_fd, long in_fd, void *offset, long count) {}
+
+POST_SYSCALL(sendfile)(long res, long out_fd, long in_fd,
+ __sanitizer___kernel_off_t *offset, long count) {
+ if (res >= 0) {
+ if (offset) POST_WRITE(offset, sizeof(*offset));
+ }
+}
+
+PRE_SYSCALL(sendfile64)(long out_fd, long in_fd, void *offset, long count) {}
+
+POST_SYSCALL(sendfile64)(long res, long out_fd, long in_fd,
+ __sanitizer___kernel_loff_t *offset, long count) {
+ if (res >= 0) {
+ if (offset) POST_WRITE(offset, sizeof(*offset));
+ }
+}
+
+PRE_SYSCALL(readlink)(const void *path, void *buf, long bufsiz) {
+ if (path)
+ PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
+}
+
+POST_SYSCALL(readlink)(long res, const void *path, void *buf, long bufsiz) {
+ if (res >= 0) {
+ if (buf)
+ POST_WRITE(buf, __sanitizer::internal_strlen((const char *)buf) + 1);
+ }
+}
+
+PRE_SYSCALL(creat)(const void *pathname, long mode) {
+ if (pathname)
+ PRE_READ(pathname,
+ __sanitizer::internal_strlen((const char *)pathname) + 1);
+}
+
+POST_SYSCALL(creat)(long res, const void *pathname, long mode) {}
+
+PRE_SYSCALL(open)(const void *filename, long flags, long mode) {
+ if (filename)
+ PRE_READ(filename,
+ __sanitizer::internal_strlen((const char *)filename) + 1);
+}
+
+POST_SYSCALL(open)(long res, const void *filename, long flags, long mode) {}
+
+PRE_SYSCALL(close)(long fd) {
+ COMMON_SYSCALL_FD_CLOSE((int)fd);
+}
+
+POST_SYSCALL(close)(long res, long fd) {}
+
+PRE_SYSCALL(access)(const void *filename, long mode) {
+ if (filename)
+ PRE_READ(filename,
+ __sanitizer::internal_strlen((const char *)filename) + 1);
+}
+
+POST_SYSCALL(access)(long res, const void *filename, long mode) {}
+
+PRE_SYSCALL(vhangup)() {}
+
+POST_SYSCALL(vhangup)(long res) {}
+
+PRE_SYSCALL(chown)(const void *filename, long user, long group) {
+ if (filename)
+ PRE_READ(filename,
+ __sanitizer::internal_strlen((const char *)filename) + 1);
+}
+
+POST_SYSCALL(chown)(long res, const void *filename, long user, long group) {}
+
+PRE_SYSCALL(lchown)(const void *filename, long user, long group) {
+ if (filename)
+ PRE_READ(filename,
+ __sanitizer::internal_strlen((const char *)filename) + 1);
+}
+
+POST_SYSCALL(lchown)(long res, const void *filename, long user, long group) {}
+
+PRE_SYSCALL(fchown)(long fd, long user, long group) {}
+
+POST_SYSCALL(fchown)(long res, long fd, long user, long group) {}
+
+PRE_SYSCALL(chown16)(const void *filename, long user, long group) {
+ if (filename)
+ PRE_READ(filename,
+ __sanitizer::internal_strlen((const char *)filename) + 1);
+}
+
+POST_SYSCALL(chown16)(long res, const void *filename, long user, long group) {}
+
+PRE_SYSCALL(lchown16)(const void *filename, long user, long group) {
+ if (filename)
+ PRE_READ(filename,
+ __sanitizer::internal_strlen((const char *)filename) + 1);
+}
+
+POST_SYSCALL(lchown16)(long res, const void *filename, long user, long group) {}
+
+PRE_SYSCALL(fchown16)(long fd, long user, long group) {}
+
+POST_SYSCALL(fchown16)(long res, long fd, long user, long group) {}
+
+PRE_SYSCALL(setregid16)(long rgid, long egid) {}
+
+POST_SYSCALL(setregid16)(long res, long rgid, long egid) {}
+
+PRE_SYSCALL(setgid16)(long gid) {}
+
+POST_SYSCALL(setgid16)(long res, long gid) {}
+
+PRE_SYSCALL(setreuid16)(long ruid, long euid) {}
+
+POST_SYSCALL(setreuid16)(long res, long ruid, long euid) {}
+
+PRE_SYSCALL(setuid16)(long uid) {}
+
+POST_SYSCALL(setuid16)(long res, long uid) {}
+
+PRE_SYSCALL(setresuid16)(long ruid, long euid, long suid) {}
+
+POST_SYSCALL(setresuid16)(long res, long ruid, long euid, long suid) {}
+
+PRE_SYSCALL(getresuid16)(void *ruid, void *euid, void *suid) {}
+
+POST_SYSCALL(getresuid16)(long res, __sanitizer___kernel_old_uid_t *ruid,
+ __sanitizer___kernel_old_uid_t *euid,
+ __sanitizer___kernel_old_uid_t *suid) {
+ if (res >= 0) {
+ if (ruid) POST_WRITE(ruid, sizeof(*ruid));
+ if (euid) POST_WRITE(euid, sizeof(*euid));
+ if (suid) POST_WRITE(suid, sizeof(*suid));
+ }
+}
+
+PRE_SYSCALL(setresgid16)(long rgid, long egid, long sgid) {}
+
+POST_SYSCALL(setresgid16)(long res, long rgid, long egid, long sgid) {}
+
+PRE_SYSCALL(getresgid16)(void *rgid, void *egid, void *sgid) {}
+
+POST_SYSCALL(getresgid16)(long res, __sanitizer___kernel_old_gid_t *rgid,
+ __sanitizer___kernel_old_gid_t *egid,
+ __sanitizer___kernel_old_gid_t *sgid) {
+ if (res >= 0) {
+ if (rgid) POST_WRITE(rgid, sizeof(*rgid));
+ if (egid) POST_WRITE(egid, sizeof(*egid));
+ if (sgid) POST_WRITE(sgid, sizeof(*sgid));
+ }
+}
+
+PRE_SYSCALL(setfsuid16)(long uid) {}
+
+POST_SYSCALL(setfsuid16)(long res, long uid) {}
+
+PRE_SYSCALL(setfsgid16)(long gid) {}
+
+POST_SYSCALL(setfsgid16)(long res, long gid) {}
+
+PRE_SYSCALL(getgroups16)(long gidsetsize,
+ __sanitizer___kernel_old_gid_t *grouplist) {}
+
+POST_SYSCALL(getgroups16)(long res, long gidsetsize,
+ __sanitizer___kernel_old_gid_t *grouplist) {
+ if (res >= 0) {
+ if (grouplist) POST_WRITE(grouplist, res * sizeof(*grouplist));
+ }
+}
+
+PRE_SYSCALL(setgroups16)(long gidsetsize,
+ __sanitizer___kernel_old_gid_t *grouplist) {
+ if (grouplist) POST_WRITE(grouplist, gidsetsize * sizeof(*grouplist));
+}
+
+POST_SYSCALL(setgroups16)(long res, long gidsetsize,
+ __sanitizer___kernel_old_gid_t *grouplist) {}
+
+PRE_SYSCALL(getuid16)() {}
+
+POST_SYSCALL(getuid16)(long res) {}
+
+PRE_SYSCALL(geteuid16)() {}
+
+POST_SYSCALL(geteuid16)(long res) {}
+
+PRE_SYSCALL(getgid16)() {}
+
+POST_SYSCALL(getgid16)(long res) {}
+
+PRE_SYSCALL(getegid16)() {}
+
+POST_SYSCALL(getegid16)(long res) {}
+
+PRE_SYSCALL(utime)(void *filename, void *times) {}
+
+POST_SYSCALL(utime)(long res, void *filename, void *times) {
+ if (res >= 0) {
+ if (filename)
+ POST_WRITE(filename,
+ __sanitizer::internal_strlen((const char *)filename) + 1);
+ if (times) POST_WRITE(times, struct_utimbuf_sz);
+ }
+}
+
+PRE_SYSCALL(utimes)(void *filename, void *utimes) {}
+
+POST_SYSCALL(utimes)(long res, void *filename, void *utimes) {
+ if (res >= 0) {
+ if (filename)
+ POST_WRITE(filename,
+ __sanitizer::internal_strlen((const char *)filename) + 1);
+ if (utimes) POST_WRITE(utimes, timeval_sz);
+ }
+}
+
+PRE_SYSCALL(lseek)(long fd, long offset, long origin) {}
+
+POST_SYSCALL(lseek)(long res, long fd, long offset, long origin) {}
+
+PRE_SYSCALL(llseek)(long fd, long offset_high, long offset_low, void *result,
+ long origin) {}
+
+POST_SYSCALL(llseek)(long res, long fd, long offset_high, long offset_low,
+ void *result, long origin) {
+ if (res >= 0) {
+ if (result) POST_WRITE(result, sizeof(long long));
+ }
+}
+
+PRE_SYSCALL(readv)(long fd, const __sanitizer_iovec *vec, long vlen) {}
+
+POST_SYSCALL(readv)(long res, long fd, const __sanitizer_iovec *vec,
+ long vlen) {
+ if (res >= 0) {
+ if (vec) kernel_write_iovec(vec, vlen, res);
+ }
+}
+
+PRE_SYSCALL(write)(long fd, const void *buf, long count) {
+ if (buf) PRE_READ(buf, count);
+}
+
+POST_SYSCALL(write)(long res, long fd, const void *buf, long count) {}
+
+PRE_SYSCALL(writev)(long fd, const __sanitizer_iovec *vec, long vlen) {}
+
+POST_SYSCALL(writev)(long res, long fd, const __sanitizer_iovec *vec,
+ long vlen) {
+ if (res >= 0) {
+ if (vec) kernel_read_iovec(vec, vlen, res);
+ }
+}
+
+#ifdef _LP64
+PRE_SYSCALL(pread64)(long fd, void *buf, long count, long pos) {}
+
+POST_SYSCALL(pread64)(long res, long fd, void *buf, long count, long pos) {
+ if (res >= 0) {
+ if (buf) POST_WRITE(buf, res);
+ }
+}
+
+PRE_SYSCALL(pwrite64)(long fd, const void *buf, long count, long pos) {
+ if (buf) PRE_READ(buf, count);
+}
+
+POST_SYSCALL(pwrite64)(long res, long fd, const void *buf, long count,
+ long pos) {}
+#else
+PRE_SYSCALL(pread64)(long fd, void *buf, long count, long pos0, long pos1) {}
+
+POST_SYSCALL(pread64)(long res, long fd, void *buf, long count, long pos0,
+ long pos1) {
+ if (res >= 0) {
+ if (buf) POST_WRITE(buf, res);
+ }
+}
+
+PRE_SYSCALL(pwrite64)(long fd, const void *buf, long count, long pos0,
+ long pos1) {
+ if (buf) PRE_READ(buf, count);
+}
+
+POST_SYSCALL(pwrite64)(long res, long fd, const void *buf, long count,
+ long pos0, long pos1) {}
+#endif
+
+PRE_SYSCALL(preadv)(long fd, const __sanitizer_iovec *vec, long vlen,
+ long pos_l, long pos_h) {}
+
+POST_SYSCALL(preadv)(long res, long fd, const __sanitizer_iovec *vec, long vlen,
+ long pos_l, long pos_h) {
+ if (res >= 0) {
+ if (vec) kernel_write_iovec(vec, vlen, res);
+ }
+}
+
+PRE_SYSCALL(pwritev)(long fd, const __sanitizer_iovec *vec, long vlen,
+ long pos_l, long pos_h) {}
+
+POST_SYSCALL(pwritev)(long res, long fd, const __sanitizer_iovec *vec,
+ long vlen, long pos_l, long pos_h) {
+ if (res >= 0) {
+ if (vec) kernel_read_iovec(vec, vlen, res);
+ }
+}
+
+PRE_SYSCALL(getcwd)(void *buf, long size) {}
+
+POST_SYSCALL(getcwd)(long res, void *buf, long size) {
+ if (res >= 0) {
+ if (buf)
+ POST_WRITE(buf, __sanitizer::internal_strlen((const char *)buf) + 1);
+ }
+}
+
+PRE_SYSCALL(mkdir)(const void *pathname, long mode) {
+ if (pathname)
+ PRE_READ(pathname,
+ __sanitizer::internal_strlen((const char *)pathname) + 1);
+}
+
+POST_SYSCALL(mkdir)(long res, const void *pathname, long mode) {}
+
+PRE_SYSCALL(chdir)(const void *filename) {
+ if (filename)
+ PRE_READ(filename,
+ __sanitizer::internal_strlen((const char *)filename) + 1);
+}
+
+POST_SYSCALL(chdir)(long res, const void *filename) {}
+
+PRE_SYSCALL(fchdir)(long fd) {}
+
+POST_SYSCALL(fchdir)(long res, long fd) {}
+
+PRE_SYSCALL(rmdir)(const void *pathname) {
+ if (pathname)
+ PRE_READ(pathname,
+ __sanitizer::internal_strlen((const char *)pathname) + 1);
+}
+
+POST_SYSCALL(rmdir)(long res, const void *pathname) {}
+
+PRE_SYSCALL(lookup_dcookie)(u64 cookie64, void *buf, long len) {}
+
+POST_SYSCALL(lookup_dcookie)(long res, u64 cookie64, void *buf, long len) {
+ if (res >= 0) {
+ if (buf)
+ POST_WRITE(buf, __sanitizer::internal_strlen((const char *)buf) + 1);
+ }
+}
+
+PRE_SYSCALL(quotactl)(long cmd, const void *special, long id, void *addr) {
+ if (special)
+ PRE_READ(special, __sanitizer::internal_strlen((const char *)special) + 1);
+}
+
+POST_SYSCALL(quotactl)(long res, long cmd, const void *special, long id,
+ void *addr) {}
+
+PRE_SYSCALL(getdents)(long fd, void *dirent, long count) {}
+
+POST_SYSCALL(getdents)(long res, long fd, void *dirent, long count) {
+ if (res >= 0) {
+ if (dirent) POST_WRITE(dirent, res);
+ }
+}
+
+PRE_SYSCALL(getdents64)(long fd, void *dirent, long count) {}
+
+POST_SYSCALL(getdents64)(long res, long fd, void *dirent, long count) {
+ if (res >= 0) {
+ if (dirent) POST_WRITE(dirent, res);
+ }
+}
+
+PRE_SYSCALL(setsockopt)(long fd, long level, long optname, void *optval,
+ long optlen) {}
+
+POST_SYSCALL(setsockopt)(long res, long fd, long level, long optname,
+ void *optval, long optlen) {
+ if (res >= 0) {
+ if (optval)
+ POST_WRITE(optval,
+ __sanitizer::internal_strlen((const char *)optval) + 1);
+ }
+}
+
+PRE_SYSCALL(getsockopt)(long fd, long level, long optname, void *optval,
+ void *optlen) {}
+
+POST_SYSCALL(getsockopt)(long res, long fd, long level, long optname,
+ void *optval, void *optlen) {
+ if (res >= 0) {
+ if (optval)
+ POST_WRITE(optval,
+ __sanitizer::internal_strlen((const char *)optval) + 1);
+ if (optlen) POST_WRITE(optlen, sizeof(int));
+ }
+}
+
+PRE_SYSCALL(bind)(long arg0, sanitizer_kernel_sockaddr *arg1, long arg2) {}
+
+POST_SYSCALL(bind)(long res, long arg0, sanitizer_kernel_sockaddr *arg1,
+ long arg2) {
+ if (res >= 0) {
+ if (arg1) POST_WRITE(arg1, sizeof(*arg1));
+ }
+}
+
+PRE_SYSCALL(connect)(long arg0, sanitizer_kernel_sockaddr *arg1, long arg2) {}
+
+POST_SYSCALL(connect)(long res, long arg0, sanitizer_kernel_sockaddr *arg1,
+ long arg2) {
+ if (res >= 0) {
+ if (arg1) POST_WRITE(arg1, sizeof(*arg1));
+ }
+}
+
+PRE_SYSCALL(accept)(long arg0, sanitizer_kernel_sockaddr *arg1, void *arg2) {}
+
+POST_SYSCALL(accept)(long res, long arg0, sanitizer_kernel_sockaddr *arg1,
+ void *arg2) {
+ if (res >= 0) {
+ if (arg1) POST_WRITE(arg1, sizeof(*arg1));
+ if (arg2) POST_WRITE(arg2, sizeof(unsigned));
+ }
+}
+
+PRE_SYSCALL(accept4)(long arg0, sanitizer_kernel_sockaddr *arg1, void *arg2,
+ long arg3) {}
+
+POST_SYSCALL(accept4)(long res, long arg0, sanitizer_kernel_sockaddr *arg1,
+ void *arg2, long arg3) {
+ if (res >= 0) {
+ if (arg1) POST_WRITE(arg1, sizeof(*arg1));
+ if (arg2) POST_WRITE(arg2, sizeof(unsigned));
+ }
+}
+
+PRE_SYSCALL(getsockname)(long arg0, sanitizer_kernel_sockaddr *arg1,
+ void *arg2) {}
+
+POST_SYSCALL(getsockname)(long res, long arg0, sanitizer_kernel_sockaddr *arg1,
+ void *arg2) {
+ if (res >= 0) {
+ if (arg1) POST_WRITE(arg1, sizeof(*arg1));
+ if (arg2) POST_WRITE(arg2, sizeof(unsigned));
+ }
+}
+
+PRE_SYSCALL(getpeername)(long arg0, sanitizer_kernel_sockaddr *arg1,
+ void *arg2) {}
+
+POST_SYSCALL(getpeername)(long res, long arg0, sanitizer_kernel_sockaddr *arg1,
+ void *arg2) {
+ if (res >= 0) {
+ if (arg1) POST_WRITE(arg1, sizeof(*arg1));
+ if (arg2) POST_WRITE(arg2, sizeof(unsigned));
+ }
+}
+
+PRE_SYSCALL(send)(long arg0, void *arg1, long arg2, long arg3) {}
+
+POST_SYSCALL(send)(long res, long arg0, void *arg1, long arg2, long arg3) {
+ if (res) {
+ if (arg1) POST_READ(arg1, res);
+ }
+}
+
+PRE_SYSCALL(sendto)(long arg0, void *arg1, long arg2, long arg3,
+ sanitizer_kernel_sockaddr *arg4, long arg5) {}
+
+POST_SYSCALL(sendto)(long res, long arg0, void *arg1, long arg2, long arg3,
+ sanitizer_kernel_sockaddr *arg4, long arg5) {
+ if (res >= 0) {
+ if (arg1) POST_READ(arg1, res);
+ if (arg4) POST_WRITE(arg4, sizeof(*arg4));
+ }
+}
+
+PRE_SYSCALL(sendmsg)(long fd, void *msg, long flags) {}
+
+POST_SYSCALL(sendmsg)(long res, long fd, void *msg, long flags) {
+ // FIXME: POST_READ
+}
+
+PRE_SYSCALL(sendmmsg)(long fd, void *msg, long vlen, long flags) {}
+
+POST_SYSCALL(sendmmsg)(long res, long fd, void *msg, long vlen, long flags) {
+ // FIXME: POST_READ
+}
+
+PRE_SYSCALL(recv)(long arg0, void *buf, long len, long flags) {}
+
+POST_SYSCALL(recv)(long res, void *buf, long len, long flags) {
+ if (res >= 0) {
+ if (buf) POST_WRITE(buf, res);
+ }
+}
+
+PRE_SYSCALL(recvfrom)(long arg0, void *buf, long len, long flags,
+ sanitizer_kernel_sockaddr *arg4, void *arg5) {}
+
+POST_SYSCALL(recvfrom)(long res, long arg0, void *buf, long len, long flags,
+ sanitizer_kernel_sockaddr *arg4, void *arg5) {
+ if (res >= 0) {
+ if (buf) POST_WRITE(buf, res);
+ if (arg4) POST_WRITE(arg4, sizeof(*arg4));
+ if (arg5) POST_WRITE(arg5, sizeof(int));
+ }
+}
+
+PRE_SYSCALL(socket)(long arg0, long arg1, long arg2) {}
+
+POST_SYSCALL(socket)(long res, long arg0, long arg1, long arg2) {}
+
+PRE_SYSCALL(socketpair)(long arg0, long arg1, long arg2, void *arg3) {}
+
+POST_SYSCALL(socketpair)(long res, long arg0, long arg1, long arg2,
+ void *arg3) {
+ if (res >= 0) {
+ if (arg3) POST_WRITE(arg3, sizeof(int));
+ }
+}
+
+PRE_SYSCALL(socketcall)(long call, void *args) {}
+
+POST_SYSCALL(socketcall)(long res, long call, void *args) {
+ if (res >= 0) {
+ if (args) POST_WRITE(args, sizeof(long));
+ }
+}
+
+PRE_SYSCALL(listen)(long arg0, long arg1) {}
+
+POST_SYSCALL(listen)(long res, long arg0, long arg1) {}
+
+PRE_SYSCALL(poll)(void *ufds, long nfds, long timeout) {}
+
+POST_SYSCALL(poll)(long res, __sanitizer_pollfd *ufds, long nfds,
+ long timeout) {
+ if (res >= 0) {
+ if (ufds) POST_WRITE(ufds, nfds * sizeof(*ufds));
+ }
+}
+
+PRE_SYSCALL(select)(long n, __sanitizer___kernel_fd_set *inp,
+ __sanitizer___kernel_fd_set *outp,
+ __sanitizer___kernel_fd_set *exp, void *tvp) {}
+
+POST_SYSCALL(select)(long res, long n, __sanitizer___kernel_fd_set *inp,
+ __sanitizer___kernel_fd_set *outp,
+ __sanitizer___kernel_fd_set *exp, void *tvp) {
+ if (res >= 0) {
+ if (inp) POST_WRITE(inp, sizeof(*inp));
+ if (outp) POST_WRITE(outp, sizeof(*outp));
+ if (exp) POST_WRITE(exp, sizeof(*exp));
+ if (tvp) POST_WRITE(tvp, timeval_sz);
+ }
+}
+
+PRE_SYSCALL(old_select)(void *arg) {}
+
+POST_SYSCALL(old_select)(long res, void *arg) {}
+
+PRE_SYSCALL(epoll_create)(long size) {}
+
+POST_SYSCALL(epoll_create)(long res, long size) {}
+
+PRE_SYSCALL(epoll_create1)(long flags) {}
+
+POST_SYSCALL(epoll_create1)(long res, long flags) {}
+
+PRE_SYSCALL(epoll_ctl)(long epfd, long op, long fd, void *event) {}
+
+POST_SYSCALL(epoll_ctl)(long res, long epfd, long op, long fd, void *event) {
+ if (res >= 0) {
+ if (event) POST_WRITE(event, struct_epoll_event_sz);
+ }
+}
+
+PRE_SYSCALL(epoll_wait)(long epfd, void *events, long maxevents, long timeout) {
+}
+
+POST_SYSCALL(epoll_wait)(long res, long epfd, void *events, long maxevents,
+ long timeout) {
+ if (res >= 0) {
+ if (events) POST_WRITE(events, struct_epoll_event_sz);
+ }
+}
+
+PRE_SYSCALL(epoll_pwait)(long epfd, void *events, long maxevents, long timeout,
+ const kernel_sigset_t *sigmask, long sigsetsize) {
+ if (sigmask) PRE_READ(sigmask, sigsetsize);
+}
+
+POST_SYSCALL(epoll_pwait)(long res, long epfd, void *events, long maxevents,
+ long timeout, const void *sigmask, long sigsetsize) {
+ if (res >= 0) {
+ if (events) POST_WRITE(events, struct_epoll_event_sz);
+ }
+}
+
+PRE_SYSCALL(gethostname)(void *name, long len) {}
+
+POST_SYSCALL(gethostname)(long res, void *name, long len) {
+ if (res >= 0) {
+ if (name)
+ POST_WRITE(name, __sanitizer::internal_strlen((const char *)name) + 1);
+ }
+}
+
+PRE_SYSCALL(sethostname)(void *name, long len) {}
+
+POST_SYSCALL(sethostname)(long res, void *name, long len) {
+ if (res >= 0) {
+ if (name)
+ POST_WRITE(name, __sanitizer::internal_strlen((const char *)name) + 1);
+ }
+}
+
+PRE_SYSCALL(setdomainname)(void *name, long len) {}
+
+POST_SYSCALL(setdomainname)(long res, void *name, long len) {
+ if (res >= 0) {
+ if (name)
+ POST_WRITE(name, __sanitizer::internal_strlen((const char *)name) + 1);
+ }
+}
+
+PRE_SYSCALL(newuname)(void *name) {}
+
+POST_SYSCALL(newuname)(long res, void *name) {
+ if (res >= 0) {
+ if (name) POST_WRITE(name, struct_new_utsname_sz);
+ }
+}
+
+PRE_SYSCALL(uname)(void *arg0) {}
+
+POST_SYSCALL(uname)(long res, void *arg0) {
+ if (res >= 0) {
+ if (arg0) POST_WRITE(arg0, struct_old_utsname_sz);
+ }
+}
+
+PRE_SYSCALL(olduname)(void *arg0) {}
+
+POST_SYSCALL(olduname)(long res, void *arg0) {
+ if (res >= 0) {
+ if (arg0) POST_WRITE(arg0, struct_oldold_utsname_sz);
+ }
+}
+
+PRE_SYSCALL(getrlimit)(long resource, void *rlim) {}
+
+POST_SYSCALL(getrlimit)(long res, long resource, void *rlim) {
+ if (res >= 0) {
+ if (rlim) POST_WRITE(rlim, struct_rlimit_sz);
+ }
+}
+
+PRE_SYSCALL(old_getrlimit)(long resource, void *rlim) {}
+
+POST_SYSCALL(old_getrlimit)(long res, long resource, void *rlim) {
+ if (res >= 0) {
+ if (rlim) POST_WRITE(rlim, struct_rlimit_sz);
+ }
+}
+
+PRE_SYSCALL(setrlimit)(long resource, void *rlim) {}
+
+POST_SYSCALL(setrlimit)(long res, long resource, void *rlim) {
+ if (res >= 0) {
+ if (rlim) POST_WRITE(rlim, struct_rlimit_sz);
+ }
+}
+
+#if !SANITIZER_ANDROID
+PRE_SYSCALL(prlimit64)(long pid, long resource, const void *new_rlim,
+ void *old_rlim) {
+ if (new_rlim) PRE_READ(new_rlim, struct_rlimit64_sz);
+}
+
+POST_SYSCALL(prlimit64)(long res, long pid, long resource, const void *new_rlim,
+ void *old_rlim) {
+ if (res >= 0) {
+ if (old_rlim) POST_WRITE(old_rlim, struct_rlimit64_sz);
+ }
+}
+#endif
+
+PRE_SYSCALL(getrusage)(long who, void *ru) {}
+
+POST_SYSCALL(getrusage)(long res, long who, void *ru) {
+ if (res >= 0) {
+ if (ru) POST_WRITE(ru, struct_rusage_sz);
+ }
+}
+
+PRE_SYSCALL(umask)(long mask) {}
+
+POST_SYSCALL(umask)(long res, long mask) {}
+
+PRE_SYSCALL(msgget)(long key, long msgflg) {}
+
+POST_SYSCALL(msgget)(long res, long key, long msgflg) {}
+
+PRE_SYSCALL(msgsnd)(long msqid, void *msgp, long msgsz, long msgflg) {
+ if (msgp) PRE_READ(msgp, msgsz);
+}
+
+POST_SYSCALL(msgsnd)(long res, long msqid, void *msgp, long msgsz,
+ long msgflg) {}
+
+PRE_SYSCALL(msgrcv)(long msqid, void *msgp, long msgsz, long msgtyp,
+ long msgflg) {}
+
+POST_SYSCALL(msgrcv)(long res, long msqid, void *msgp, long msgsz, long msgtyp,
+ long msgflg) {
+ if (res >= 0) {
+ if (msgp) POST_WRITE(msgp, res);
+ }
+}
+
+PRE_SYSCALL(msgctl)(long msqid, long cmd, void *buf) {}
+
+POST_SYSCALL(msgctl)(long res, long msqid, long cmd, void *buf) {
+ if (res >= 0) {
+ if (buf) POST_WRITE(buf, struct_msqid_ds_sz);
+ }
+}
+
+PRE_SYSCALL(semget)(long key, long nsems, long semflg) {}
+
+POST_SYSCALL(semget)(long res, long key, long nsems, long semflg) {}
+
+PRE_SYSCALL(semop)(long semid, void *sops, long nsops) {}
+
+POST_SYSCALL(semop)(long res, long semid, void *sops, long nsops) {}
+
+PRE_SYSCALL(semctl)(long semid, long semnum, long cmd, void *arg) {}
+
+POST_SYSCALL(semctl)(long res, long semid, long semnum, long cmd, void *arg) {}
+
+PRE_SYSCALL(semtimedop)(long semid, void *sops, long nsops,
+ const void *timeout) {
+ if (timeout) PRE_READ(timeout, struct_timespec_sz);
+}
+
+POST_SYSCALL(semtimedop)(long res, long semid, void *sops, long nsops,
+ const void *timeout) {}
+
+PRE_SYSCALL(shmat)(long shmid, void *shmaddr, long shmflg) {}
+
+POST_SYSCALL(shmat)(long res, long shmid, void *shmaddr, long shmflg) {
+ if (res >= 0) {
+ if (shmaddr)
+ POST_WRITE(shmaddr,
+ __sanitizer::internal_strlen((const char *)shmaddr) + 1);
+ }
+}
+
+PRE_SYSCALL(shmget)(long key, long size, long flag) {}
+
+POST_SYSCALL(shmget)(long res, long key, long size, long flag) {}
+
+PRE_SYSCALL(shmdt)(void *shmaddr) {}
+
+POST_SYSCALL(shmdt)(long res, void *shmaddr) {
+ if (res >= 0) {
+ if (shmaddr)
+ POST_WRITE(shmaddr,
+ __sanitizer::internal_strlen((const char *)shmaddr) + 1);
+ }
+}
+
+PRE_SYSCALL(shmctl)(long shmid, long cmd, void *buf) {}
+
+POST_SYSCALL(shmctl)(long res, long shmid, long cmd, void *buf) {
+ if (res >= 0) {
+ if (buf) POST_WRITE(buf, struct_shmid_ds_sz);
+ }
+}
+
+PRE_SYSCALL(ipc)(long call, long first, long second, long third, void *ptr,
+ long fifth) {}
+
+POST_SYSCALL(ipc)(long res, long call, long first, long second, long third,
+ void *ptr, long fifth) {}
+
+#if !SANITIZER_ANDROID
+PRE_SYSCALL(mq_open)(const void *name, long oflag, long mode, void *attr) {
+ if (name)
+ PRE_READ(name, __sanitizer::internal_strlen((const char *)name) + 1);
+}
+
+POST_SYSCALL(mq_open)(long res, const void *name, long oflag, long mode,
+ void *attr) {
+ if (res >= 0) {
+ if (attr) POST_WRITE(attr, struct_mq_attr_sz);
+ }
+}
+
+PRE_SYSCALL(mq_unlink)(const void *name) {
+ if (name)
+ PRE_READ(name, __sanitizer::internal_strlen((const char *)name) + 1);
+}
+
+POST_SYSCALL(mq_unlink)(long res, const void *name) {}
+
+PRE_SYSCALL(mq_timedsend)(long mqdes, const void *msg_ptr, long msg_len,
+ long msg_prio, const void *abs_timeout) {
+ if (msg_ptr) PRE_READ(msg_ptr, msg_len);
+ if (abs_timeout) PRE_READ(abs_timeout, struct_timespec_sz);
+}
+
+POST_SYSCALL(mq_timedsend)(long res, long mqdes, const void *msg_ptr,
+ long msg_len, long msg_prio,
+ const void *abs_timeout) {}
+
+PRE_SYSCALL(mq_timedreceive)(long mqdes, void *msg_ptr, long msg_len,
+ void *msg_prio, const void *abs_timeout) {
+ if (abs_timeout) PRE_READ(abs_timeout, struct_timespec_sz);
+}
+
+POST_SYSCALL(mq_timedreceive)(long res, long mqdes, void *msg_ptr, long msg_len,
+ int *msg_prio, const void *abs_timeout) {
+ if (res >= 0) {
+ if (msg_ptr) POST_WRITE(msg_ptr, res);
+ if (msg_prio) POST_WRITE(msg_prio, sizeof(*msg_prio));
+ }
+}
+
+PRE_SYSCALL(mq_notify)(long mqdes, const void *notification) {
+ if (notification) PRE_READ(notification, struct_sigevent_sz);
+}
+
+POST_SYSCALL(mq_notify)(long res, long mqdes, const void *notification) {}
+
+PRE_SYSCALL(mq_getsetattr)(long mqdes, const void *mqstat, void *omqstat) {
+ if (mqstat) PRE_READ(mqstat, struct_mq_attr_sz);
+}
+
+POST_SYSCALL(mq_getsetattr)(long res, long mqdes, const void *mqstat,
+ void *omqstat) {
+ if (res >= 0) {
+ if (omqstat) POST_WRITE(omqstat, struct_mq_attr_sz);
+ }
+}
+#endif // SANITIZER_ANDROID
+
+PRE_SYSCALL(pciconfig_iobase)(long which, long bus, long devfn) {}
+
+POST_SYSCALL(pciconfig_iobase)(long res, long which, long bus, long devfn) {}
+
+PRE_SYSCALL(pciconfig_read)(long bus, long dfn, long off, long len, void *buf) {
+}
+
+POST_SYSCALL(pciconfig_read)(long res, long bus, long dfn, long off, long len,
+ void *buf) {}
+
+PRE_SYSCALL(pciconfig_write)(long bus, long dfn, long off, long len,
+ void *buf) {}
+
+POST_SYSCALL(pciconfig_write)(long res, long bus, long dfn, long off, long len,
+ void *buf) {}
+
+PRE_SYSCALL(swapon)(const void *specialfile, long swap_flags) {
+ if (specialfile)
+ PRE_READ(specialfile,
+ __sanitizer::internal_strlen((const char *)specialfile) + 1);
+}
+
+POST_SYSCALL(swapon)(long res, const void *specialfile, long swap_flags) {}
+
+PRE_SYSCALL(swapoff)(const void *specialfile) {
+ if (specialfile)
+ PRE_READ(specialfile,
+ __sanitizer::internal_strlen((const char *)specialfile) + 1);
+}
+
+POST_SYSCALL(swapoff)(long res, const void *specialfile) {}
+
+PRE_SYSCALL(sysctl)(__sanitizer___sysctl_args *args) {
+ if (args) {
+ if (args->name) PRE_READ(args->name, args->nlen * sizeof(*args->name));
+ if (args->newval) PRE_READ(args->name, args->newlen);
+ }
+}
+
+POST_SYSCALL(sysctl)(long res, __sanitizer___sysctl_args *args) {
+ if (res >= 0) {
+ if (args && args->oldval && args->oldlenp) {
+ POST_WRITE(args->oldlenp, sizeof(*args->oldlenp));
+ POST_WRITE(args->oldval, *args->oldlenp);
+ }
+ }
+}
+
+PRE_SYSCALL(sysinfo)(void *info) {}
+
+POST_SYSCALL(sysinfo)(long res, void *info) {
+ if (res >= 0) {
+ if (info) POST_WRITE(info, struct_sysinfo_sz);
+ }
+}
+
+PRE_SYSCALL(sysfs)(long option, long arg1, long arg2) {}
+
+POST_SYSCALL(sysfs)(long res, long option, long arg1, long arg2) {}
+
+PRE_SYSCALL(syslog)(long type, void *buf, long len) {}
+
+POST_SYSCALL(syslog)(long res, long type, void *buf, long len) {
+ if (res >= 0) {
+ if (buf)
+ POST_WRITE(buf, __sanitizer::internal_strlen((const char *)buf) + 1);
+ }
+}
+
+PRE_SYSCALL(uselib)(const void *library) {
+ if (library)
+ PRE_READ(library, __sanitizer::internal_strlen((const char *)library) + 1);
+}
+
+POST_SYSCALL(uselib)(long res, const void *library) {}
+
+PRE_SYSCALL(ni_syscall)() {}
+
+POST_SYSCALL(ni_syscall)(long res) {}
+
+PRE_SYSCALL(ptrace)(long request, long pid, long addr, long data) {}
+
+POST_SYSCALL(ptrace)(long res, long request, long pid, long addr, long data) {}
+
+PRE_SYSCALL(add_key)(const void *_type, const void *_description,
+ const void *_payload, long plen, long destringid) {
+ if (_type)
+ PRE_READ(_type, __sanitizer::internal_strlen((const char *)_type) + 1);
+ if (_description)
+ PRE_READ(_description,
+ __sanitizer::internal_strlen((const char *)_description) + 1);
+}
+
+POST_SYSCALL(add_key)(long res, const void *_type, const void *_description,
+ const void *_payload, long plen, long destringid) {}
+
+PRE_SYSCALL(request_key)(const void *_type, const void *_description,
+ const void *_callout_info, long destringid) {
+ if (_type)
+ PRE_READ(_type, __sanitizer::internal_strlen((const char *)_type) + 1);
+ if (_description)
+ PRE_READ(_description,
+ __sanitizer::internal_strlen((const char *)_description) + 1);
+ if (_callout_info)
+ PRE_READ(_callout_info,
+ __sanitizer::internal_strlen((const char *)_callout_info) + 1);
+}
+
+POST_SYSCALL(request_key)(long res, const void *_type, const void *_description,
+ const void *_callout_info, long destringid) {}
+
+PRE_SYSCALL(keyctl)(long cmd, long arg2, long arg3, long arg4, long arg5) {}
+
+POST_SYSCALL(keyctl)(long res, long cmd, long arg2, long arg3, long arg4,
+ long arg5) {}
+
+PRE_SYSCALL(ioprio_set)(long which, long who, long ioprio) {}
+
+POST_SYSCALL(ioprio_set)(long res, long which, long who, long ioprio) {}
+
+PRE_SYSCALL(ioprio_get)(long which, long who) {}
+
+POST_SYSCALL(ioprio_get)(long res, long which, long who) {}
+
+PRE_SYSCALL(set_mempolicy)(long mode, void *nmask, long maxnode) {}
+
+POST_SYSCALL(set_mempolicy)(long res, long mode, void *nmask, long maxnode) {
+ if (res >= 0) {
+ if (nmask) POST_WRITE(nmask, sizeof(long));
+ }
+}
+
+PRE_SYSCALL(migrate_pages)(long pid, long maxnode, const void *from,
+ const void *to) {
+ if (from) PRE_READ(from, sizeof(long));
+ if (to) PRE_READ(to, sizeof(long));
+}
+
+POST_SYSCALL(migrate_pages)(long res, long pid, long maxnode, const void *from,
+ const void *to) {}
+
+PRE_SYSCALL(move_pages)(long pid, long nr_pages, const void **pages,
+ const int *nodes, int *status, long flags) {
+ if (pages) PRE_READ(pages, nr_pages * sizeof(*pages));
+ if (nodes) PRE_READ(nodes, nr_pages * sizeof(*nodes));
+}
+
+POST_SYSCALL(move_pages)(long res, long pid, long nr_pages, const void **pages,
+ const int *nodes, int *status, long flags) {
+ if (res >= 0) {
+ if (status) POST_WRITE(status, nr_pages * sizeof(*status));
+ }
+}
+
+PRE_SYSCALL(mbind)(long start, long len, long mode, void *nmask, long maxnode,
+ long flags) {}
+
+POST_SYSCALL(mbind)(long res, long start, long len, long mode, void *nmask,
+ long maxnode, long flags) {
+ if (res >= 0) {
+ if (nmask) POST_WRITE(nmask, sizeof(long));
+ }
+}
+
+PRE_SYSCALL(get_mempolicy)(void *policy, void *nmask, long maxnode, long addr,
+ long flags) {}
+
+POST_SYSCALL(get_mempolicy)(long res, void *policy, void *nmask, long maxnode,
+ long addr, long flags) {
+ if (res >= 0) {
+ if (policy) POST_WRITE(policy, sizeof(int));
+ if (nmask) POST_WRITE(nmask, sizeof(long));
+ }
+}
+
+PRE_SYSCALL(inotify_init)() {}
+
+POST_SYSCALL(inotify_init)(long res) {}
+
+PRE_SYSCALL(inotify_init1)(long flags) {}
+
+POST_SYSCALL(inotify_init1)(long res, long flags) {}
+
+PRE_SYSCALL(inotify_add_watch)(long fd, const void *path, long mask) {
+ if (path)
+ PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
+}
+
+POST_SYSCALL(inotify_add_watch)(long res, long fd, const void *path,
+ long mask) {}
+
+PRE_SYSCALL(inotify_rm_watch)(long fd, long wd) {}
+
+POST_SYSCALL(inotify_rm_watch)(long res, long fd, long wd) {}
+
+PRE_SYSCALL(spu_run)(long fd, void *unpc, void *ustatus) {}
+
+POST_SYSCALL(spu_run)(long res, long fd, unsigned *unpc, unsigned *ustatus) {
+ if (res >= 0) {
+ if (unpc) POST_WRITE(unpc, sizeof(*unpc));
+ if (ustatus) POST_WRITE(ustatus, sizeof(*ustatus));
+ }
+}
+
+PRE_SYSCALL(spu_create)(const void *name, long flags, long mode, long fd) {
+ if (name)
+ PRE_READ(name, __sanitizer::internal_strlen((const char *)name) + 1);
+}
+
+POST_SYSCALL(spu_create)(long res, const void *name, long flags, long mode,
+ long fd) {}
+
+PRE_SYSCALL(mknodat)(long dfd, const void *filename, long mode, long dev) {
+ if (filename)
+ PRE_READ(filename,
+ __sanitizer::internal_strlen((const char *)filename) + 1);
+}
+
+POST_SYSCALL(mknodat)(long res, long dfd, const void *filename, long mode,
+ long dev) {}
+
+PRE_SYSCALL(mkdirat)(long dfd, const void *pathname, long mode) {
+ if (pathname)
+ PRE_READ(pathname,
+ __sanitizer::internal_strlen((const char *)pathname) + 1);
+}
+
+POST_SYSCALL(mkdirat)(long res, long dfd, const void *pathname, long mode) {}
+
+PRE_SYSCALL(unlinkat)(long dfd, const void *pathname, long flag) {
+ if (pathname)
+ PRE_READ(pathname,
+ __sanitizer::internal_strlen((const char *)pathname) + 1);
+}
+
+POST_SYSCALL(unlinkat)(long res, long dfd, const void *pathname, long flag) {}
+
+PRE_SYSCALL(symlinkat)(const void *oldname, long newdfd, const void *newname) {
+ if (oldname)
+ PRE_READ(oldname, __sanitizer::internal_strlen((const char *)oldname) + 1);
+ if (newname)
+ PRE_READ(newname, __sanitizer::internal_strlen((const char *)newname) + 1);
+}
+
+POST_SYSCALL(symlinkat)(long res, const void *oldname, long newdfd,
+ const void *newname) {}
+
+PRE_SYSCALL(linkat)(long olddfd, const void *oldname, long newdfd,
+ const void *newname, long flags) {
+ if (oldname)
+ PRE_READ(oldname, __sanitizer::internal_strlen((const char *)oldname) + 1);
+ if (newname)
+ PRE_READ(newname, __sanitizer::internal_strlen((const char *)newname) + 1);
+}
+
+POST_SYSCALL(linkat)(long res, long olddfd, const void *oldname, long newdfd,
+ const void *newname, long flags) {}
+
+PRE_SYSCALL(renameat)(long olddfd, const void *oldname, long newdfd,
+ const void *newname) {
+ if (oldname)
+ PRE_READ(oldname, __sanitizer::internal_strlen((const char *)oldname) + 1);
+ if (newname)
+ PRE_READ(newname, __sanitizer::internal_strlen((const char *)newname) + 1);
+}
+
+POST_SYSCALL(renameat)(long res, long olddfd, const void *oldname, long newdfd,
+ const void *newname) {}
+
+PRE_SYSCALL(futimesat)(long dfd, const void *filename, void *utimes) {
+ if (filename)
+ PRE_READ(filename,
+ __sanitizer::internal_strlen((const char *)filename) + 1);
+}
+
+POST_SYSCALL(futimesat)(long res, long dfd, const void *filename,
+ void *utimes) {
+ if (res >= 0) {
+ if (utimes) POST_WRITE(utimes, timeval_sz);
+ }
+}
+
+PRE_SYSCALL(faccessat)(long dfd, const void *filename, long mode) {
+ if (filename)
+ PRE_READ(filename,
+ __sanitizer::internal_strlen((const char *)filename) + 1);
+}
+
+POST_SYSCALL(faccessat)(long res, long dfd, const void *filename, long mode) {}
+
+PRE_SYSCALL(fchmodat)(long dfd, const void *filename, long mode) {
+ if (filename)
+ PRE_READ(filename,
+ __sanitizer::internal_strlen((const char *)filename) + 1);
+}
+
+POST_SYSCALL(fchmodat)(long res, long dfd, const void *filename, long mode) {}
+
+PRE_SYSCALL(fchownat)(long dfd, const void *filename, long user, long group,
+ long flag) {
+ if (filename)
+ PRE_READ(filename,
+ __sanitizer::internal_strlen((const char *)filename) + 1);
+}
+
+POST_SYSCALL(fchownat)(long res, long dfd, const void *filename, long user,
+ long group, long flag) {}
+
+PRE_SYSCALL(openat)(long dfd, const void *filename, long flags, long mode) {
+ if (filename)
+ PRE_READ(filename,
+ __sanitizer::internal_strlen((const char *)filename) + 1);
+}
+
+POST_SYSCALL(openat)(long res, long dfd, const void *filename, long flags,
+ long mode) {}
+
+PRE_SYSCALL(newfstatat)(long dfd, const void *filename, void *statbuf,
+ long flag) {
+ if (filename)
+ PRE_READ(filename,
+ __sanitizer::internal_strlen((const char *)filename) + 1);
+}
+
+POST_SYSCALL(newfstatat)(long res, long dfd, const void *filename,
+ void *statbuf, long flag) {
+ if (res >= 0) {
+ if (statbuf) POST_WRITE(statbuf, struct_kernel_stat_sz);
+ }
+}
+
+PRE_SYSCALL(fstatat64)(long dfd, const void *filename, void *statbuf,
+ long flag) {
+ if (filename)
+ PRE_READ(filename,
+ __sanitizer::internal_strlen((const char *)filename) + 1);
+}
+
+POST_SYSCALL(fstatat64)(long res, long dfd, const void *filename, void *statbuf,
+ long flag) {
+ if (res >= 0) {
+ if (statbuf) POST_WRITE(statbuf, struct_kernel_stat64_sz);
+ }
+}
+
+PRE_SYSCALL(readlinkat)(long dfd, const void *path, void *buf, long bufsiz) {
+ if (path)
+ PRE_READ(path, __sanitizer::internal_strlen((const char *)path) + 1);
+}
+
+POST_SYSCALL(readlinkat)(long res, long dfd, const void *path, void *buf,
+ long bufsiz) {
+ if (res >= 0) {
+ if (buf)
+ POST_WRITE(buf, __sanitizer::internal_strlen((const char *)buf) + 1);
+ }
+}
+
+PRE_SYSCALL(utimensat)(long dfd, const void *filename, void *utimes,
+ long flags) {
+ if (filename)
+ PRE_READ(filename,
+ __sanitizer::internal_strlen((const char *)filename) + 1);
+}
+
+POST_SYSCALL(utimensat)(long res, long dfd, const void *filename, void *utimes,
+ long flags) {
+ if (res >= 0) {
+ if (utimes) POST_WRITE(utimes, struct_timespec_sz);
+ }
+}
+
+PRE_SYSCALL(unshare)(long unshare_flags) {}
+
+POST_SYSCALL(unshare)(long res, long unshare_flags) {}
+
+PRE_SYSCALL(splice)(long fd_in, void *off_in, long fd_out, void *off_out,
+ long len, long flags) {}
+
+POST_SYSCALL(splice)(long res, long fd_in, void *off_in, long fd_out,
+ void *off_out, long len, long flags) {
+ if (res >= 0) {
+ if (off_in) POST_WRITE(off_in, sizeof(long long));
+ if (off_out) POST_WRITE(off_out, sizeof(long long));
+ }
+}
+
+PRE_SYSCALL(vmsplice)(long fd, const __sanitizer_iovec *iov, long nr_segs,
+ long flags) {}
+
+POST_SYSCALL(vmsplice)(long res, long fd, const __sanitizer_iovec *iov,
+ long nr_segs, long flags) {
+ if (res >= 0) {
+ if (iov) kernel_read_iovec(iov, nr_segs, res);
+ }
+}
+
+PRE_SYSCALL(tee)(long fdin, long fdout, long len, long flags) {}
+
+POST_SYSCALL(tee)(long res, long fdin, long fdout, long len, long flags) {}
+
+PRE_SYSCALL(get_robust_list)(long pid, void *head_ptr, void *len_ptr) {}
+
+POST_SYSCALL(get_robust_list)(long res, long pid, void *head_ptr,
+ void *len_ptr) {}
+
+PRE_SYSCALL(set_robust_list)(void *head, long len) {}
+
+POST_SYSCALL(set_robust_list)(long res, void *head, long len) {}
+
+PRE_SYSCALL(getcpu)(void *cpu, void *node, void *cache) {}
+
+POST_SYSCALL(getcpu)(long res, void *cpu, void *node, void *cache) {
+ if (res >= 0) {
+ if (cpu) POST_WRITE(cpu, sizeof(unsigned));
+ if (node) POST_WRITE(node, sizeof(unsigned));
+ // The third argument to this system call is nowadays unused.
+ }
+}
+
+PRE_SYSCALL(signalfd)(long ufd, void *user_mask, long sizemask) {}
+
+POST_SYSCALL(signalfd)(long res, long ufd, kernel_sigset_t *user_mask,
+ long sizemask) {
+ if (res >= 0) {
+ if (user_mask) POST_WRITE(user_mask, sizemask);
+ }
+}
+
+PRE_SYSCALL(signalfd4)(long ufd, void *user_mask, long sizemask, long flags) {}
+
+POST_SYSCALL(signalfd4)(long res, long ufd, kernel_sigset_t *user_mask,
+ long sizemask, long flags) {
+ if (res >= 0) {
+ if (user_mask) POST_WRITE(user_mask, sizemask);
+ }
+}
+
+PRE_SYSCALL(timerfd_create)(long clockid, long flags) {}
+
+POST_SYSCALL(timerfd_create)(long res, long clockid, long flags) {}
+
+PRE_SYSCALL(timerfd_settime)(long ufd, long flags, const void *utmr,
+ void *otmr) {
+ if (utmr) PRE_READ(utmr, struct_itimerspec_sz);
+}
+
+POST_SYSCALL(timerfd_settime)(long res, long ufd, long flags, const void *utmr,
+ void *otmr) {
+ if (res >= 0) {
+ if (otmr) POST_WRITE(otmr, struct_itimerspec_sz);
+ }
+}
+
+PRE_SYSCALL(timerfd_gettime)(long ufd, void *otmr) {}
+
+POST_SYSCALL(timerfd_gettime)(long res, long ufd, void *otmr) {
+ if (res >= 0) {
+ if (otmr) POST_WRITE(otmr, struct_itimerspec_sz);
+ }
+}
+
+PRE_SYSCALL(eventfd)(long count) {}
+
+POST_SYSCALL(eventfd)(long res, long count) {}
+
+PRE_SYSCALL(eventfd2)(long count, long flags) {}
+
+POST_SYSCALL(eventfd2)(long res, long count, long flags) {}
+
+PRE_SYSCALL(old_readdir)(long arg0, void *arg1, long arg2) {}
+
+POST_SYSCALL(old_readdir)(long res, long arg0, void *arg1, long arg2) {
+ // Missing definition of 'struct old_linux_dirent'.
+}
+
+PRE_SYSCALL(pselect6)(long arg0, __sanitizer___kernel_fd_set *arg1,
+ __sanitizer___kernel_fd_set *arg2,
+ __sanitizer___kernel_fd_set *arg3, void *arg4,
+ void *arg5) {}
+
+POST_SYSCALL(pselect6)(long res, long arg0, __sanitizer___kernel_fd_set *arg1,
+ __sanitizer___kernel_fd_set *arg2,
+ __sanitizer___kernel_fd_set *arg3, void *arg4,
+ void *arg5) {
+ if (res >= 0) {
+ if (arg1) POST_WRITE(arg1, sizeof(*arg1));
+ if (arg2) POST_WRITE(arg2, sizeof(*arg2));
+ if (arg3) POST_WRITE(arg3, sizeof(*arg3));
+ if (arg4) POST_WRITE(arg4, struct_timespec_sz);
+ }
+}
+
+PRE_SYSCALL(ppoll)(__sanitizer_pollfd *arg0, long arg1, void *arg2,
+ const kernel_sigset_t *arg3, long arg4) {
+ if (arg3) PRE_READ(arg3, arg4);
+}
+
+POST_SYSCALL(ppoll)(long res, __sanitizer_pollfd *arg0, long arg1, void *arg2,
+ const void *arg3, long arg4) {
+ if (res >= 0) {
+ if (arg0) POST_WRITE(arg0, sizeof(*arg0));
+ if (arg2) POST_WRITE(arg2, struct_timespec_sz);
+ }
+}
+
+PRE_SYSCALL(syncfs)(long fd) {}
+
+POST_SYSCALL(syncfs)(long res, long fd) {}
+
+PRE_SYSCALL(perf_event_open)(void *attr_uptr, long pid, long cpu, long group_fd,
+ long flags) {}
+
+POST_SYSCALL(perf_event_open)(long res, void *attr_uptr, long pid, long cpu,
+ long group_fd, long flags) {
+ if (res >= 0) {
+ if (attr_uptr) POST_WRITE(attr_uptr, struct_perf_event_attr_sz);
+ }
+}
+
+PRE_SYSCALL(mmap_pgoff)(long addr, long len, long prot, long flags, long fd,
+ long pgoff) {}
+
+POST_SYSCALL(mmap_pgoff)(long res, long addr, long len, long prot, long flags,
+ long fd, long pgoff) {}
+
+PRE_SYSCALL(old_mmap)(void *arg) {}
+
+POST_SYSCALL(old_mmap)(long res, void *arg) {}
+
+PRE_SYSCALL(name_to_handle_at)(long dfd, const void *name, void *handle,
+ void *mnt_id, long flag) {}
+
+POST_SYSCALL(name_to_handle_at)(long res, long dfd, const void *name,
+ void *handle, void *mnt_id, long flag) {}
+
+PRE_SYSCALL(open_by_handle_at)(long mountdirfd, void *handle, long flags) {}
+
+POST_SYSCALL(open_by_handle_at)(long res, long mountdirfd, void *handle,
+ long flags) {}
+
+PRE_SYSCALL(setns)(long fd, long nstype) {}
+
+POST_SYSCALL(setns)(long res, long fd, long nstype) {}
+
+PRE_SYSCALL(process_vm_readv)(long pid, const __sanitizer_iovec *lvec,
+ long liovcnt, const void *rvec, long riovcnt,
+ long flags) {}
+
+POST_SYSCALL(process_vm_readv)(long res, long pid,
+ const __sanitizer_iovec *lvec, long liovcnt,
+ const void *rvec, long riovcnt, long flags) {
+ if (res >= 0) {
+ if (lvec) kernel_write_iovec(lvec, liovcnt, res);
+ }
+}
+
+PRE_SYSCALL(process_vm_writev)(long pid, const __sanitizer_iovec *lvec,
+ long liovcnt, const void *rvec, long riovcnt,
+ long flags) {}
+
+POST_SYSCALL(process_vm_writev)(long res, long pid,
+ const __sanitizer_iovec *lvec, long liovcnt,
+ const void *rvec, long riovcnt, long flags) {
+ if (res >= 0) {
+ if (lvec) kernel_read_iovec(lvec, liovcnt, res);
+ }
+}
+
+PRE_SYSCALL(fork)() {
+ COMMON_SYSCALL_PRE_FORK();
+}
+
+POST_SYSCALL(fork)(long res) {
+ COMMON_SYSCALL_POST_FORK(res);
+}
+
+PRE_SYSCALL(vfork)() {
+ COMMON_SYSCALL_PRE_FORK();
+}
+
+POST_SYSCALL(vfork)(long res) {
+ COMMON_SYSCALL_POST_FORK(res);
+}
+} // extern "C"
+
+#undef PRE_SYSCALL
+#undef PRE_READ
+#undef PRE_WRITE
+#undef POST_SYSCALL
+#undef POST_READ
+#undef POST_WRITE
+
+#endif // SANITIZER_LINUX
diff --git a/libsanitizer/sanitizer_common/sanitizer_flags.cc b/libsanitizer/sanitizer_common/sanitizer_flags.cc
index 2152c7bdff4..06ac5435b9d 100644
--- a/libsanitizer/sanitizer_common/sanitizer_flags.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_flags.cc
@@ -16,15 +16,40 @@
namespace __sanitizer {
+CommonFlags common_flags_dont_use_directly;
+
+void ParseCommonFlagsFromString(const char *str) {
+ CommonFlags *f = common_flags();
+ ParseFlag(str, &f->malloc_context_size, "malloc_context_size");
+ ParseFlag(str, &f->strip_path_prefix, "strip_path_prefix");
+ ParseFlag(str, &f->fast_unwind_on_fatal, "fast_unwind_on_fatal");
+ ParseFlag(str, &f->fast_unwind_on_malloc, "fast_unwind_on_malloc");
+ ParseFlag(str, &f->symbolize, "symbolize");
+ ParseFlag(str, &f->handle_ioctl, "handle_ioctl");
+ ParseFlag(str, &f->log_path, "log_path");
+ ParseFlag(str, &f->detect_leaks, "detect_leaks");
+ ParseFlag(str, &f->leak_check_at_exit, "leak_check_at_exit");
+ ParseFlag(str, &f->allocator_may_return_null, "allocator_may_return_null");
+}
+
static bool GetFlagValue(const char *env, const char *name,
const char **value, int *value_length) {
if (env == 0)
return false;
- const char *pos = internal_strstr(env, name);
- const char *end;
- if (pos == 0)
- return false;
+ const char *pos = 0;
+ for (;;) {
+ pos = internal_strstr(env, name);
+ if (pos == 0)
+ return false;
+ if (pos != env && ((pos[-1] >= 'a' && pos[-1] <= 'z') || pos[-1] == '_')) {
+ // Seems to be middle of another flag name or value.
+ env = pos + 1;
+ continue;
+ }
+ break;
+ }
pos += internal_strlen(name);
+ const char *end;
if (pos[0] != '=') {
end = pos;
} else {
@@ -75,7 +100,7 @@ void ParseFlag(const char *env, int *flag, const char *name) {
int value_length;
if (!GetFlagValue(env, name, &value, &value_length))
return;
- *flag = internal_atoll(value);
+ *flag = static_cast<int>(internal_atoll(value));
}
static LowLevelAllocator allocator_for_flags;
diff --git a/libsanitizer/sanitizer_common/sanitizer_flags.h b/libsanitizer/sanitizer_common/sanitizer_flags.h
index 1b9bf5bffdb..62aa96bbb69 100644
--- a/libsanitizer/sanitizer_common/sanitizer_flags.h
+++ b/libsanitizer/sanitizer_common/sanitizer_flags.h
@@ -20,6 +20,41 @@ void ParseFlag(const char *env, bool *flag, const char *name);
void ParseFlag(const char *env, int *flag, const char *name);
void ParseFlag(const char *env, const char **flag, const char *name);
+struct CommonFlags {
+ // If set, use the online symbolizer from common sanitizer runtime.
+ bool symbolize;
+ // Path to external symbolizer.
+ const char *external_symbolizer_path;
+ // Strips this prefix from file paths in error reports.
+ const char *strip_path_prefix;
+ // Use fast (frame-pointer-based) unwinder on fatal errors (if available).
+ bool fast_unwind_on_fatal;
+ // Use fast (frame-pointer-based) unwinder on malloc/free (if available).
+ bool fast_unwind_on_malloc;
+ // Intercept and handle ioctl requests.
+ bool handle_ioctl;
+ // Max number of stack frames kept for each allocation/deallocation.
+ int malloc_context_size;
+ // Write logs to "log_path.pid" instead of stderr.
+ const char *log_path;
+ // Enable memory leak detection.
+ bool detect_leaks;
+ // Invoke leak checking in an atexit handler. Has no effect if
+ // detect_leaks=false, or if __lsan_do_leak_check() is called before the
+ // handler has a chance to run.
+ bool leak_check_at_exit;
+ // If false, the allocator will crash instead of returning 0 on out-of-memory.
+ bool allocator_may_return_null;
+};
+
+extern CommonFlags common_flags_dont_use_directly;
+
+inline CommonFlags *common_flags() {
+ return &common_flags_dont_use_directly;
+}
+
+void ParseCommonFlagsFromString(const char *str);
+
} // namespace __sanitizer
#endif // SANITIZER_FLAGS_H
diff --git a/libsanitizer/sanitizer_common/sanitizer_internal_defs.h b/libsanitizer/sanitizer_common/sanitizer_internal_defs.h
index 577c9a9c17f..cc9233cad5f 100644
--- a/libsanitizer/sanitizer_common/sanitizer_internal_defs.h
+++ b/libsanitizer/sanitizer_common/sanitizer_internal_defs.h
@@ -11,9 +11,12 @@
#ifndef SANITIZER_DEFS_H
#define SANITIZER_DEFS_H
-#if defined(_WIN32)
-// FIXME find out what we need on Windows. __declspec(dllexport) ?
-# define SANITIZER_INTERFACE_ATTRIBUTE
+#include "sanitizer_platform.h"
+
+// Only use SANITIZER_*ATTRIBUTE* before the function return type!
+#if SANITIZER_WINDOWS
+# define SANITIZER_INTERFACE_ATTRIBUTE __declspec(dllexport)
+// FIXME find out what we need on Windows, if anything.
# define SANITIZER_WEAK_ATTRIBUTE
#elif defined(SANITIZER_GO)
# define SANITIZER_INTERFACE_ATTRIBUTE
@@ -23,7 +26,7 @@
# define SANITIZER_WEAK_ATTRIBUTE __attribute__((weak))
#endif
-#ifdef __linux__
+#if SANITIZER_LINUX && !defined(SANITIZER_GO)
# define SANITIZER_SUPPORTS_WEAK_HOOKS 1
#else
# define SANITIZER_SUPPORTS_WEAK_HOOKS 0
@@ -64,29 +67,39 @@ typedef signed int s32;
typedef signed long long s64; // NOLINT
typedef int fd_t;
+// WARNING: OFF_T may be different from OS type off_t, depending on the value of
+// _FILE_OFFSET_BITS. This definition of OFF_T matches the ABI of system calls
+// like pread and mmap, as opposed to pread64 and mmap64.
+// Mac and Linux/x86-64 are special.
+#if SANITIZER_MAC || (SANITIZER_LINUX && defined(__x86_64__))
+typedef u64 OFF_T;
+#else
+typedef uptr OFF_T;
+#endif
+typedef u64 OFF64_T;
} // namespace __sanitizer
extern "C" {
// Tell the tools to write their reports to "path.<pid>" instead of stderr.
- void __sanitizer_set_report_path(const char *path)
- SANITIZER_INTERFACE_ATTRIBUTE;
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void __sanitizer_set_report_path(const char *path);
// Tell the tools to write their reports to given file descriptor instead of
// stderr.
- void __sanitizer_set_report_fd(int fd)
- SANITIZER_INTERFACE_ATTRIBUTE;
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void __sanitizer_set_report_fd(int fd);
// Notify the tools that the sandbox is going to be turned on. The reserved
// parameter will be used in the future to hold a structure with functions
// that the tools may call to bypass the sandbox.
- void __sanitizer_sandbox_on_notify(void *reserved)
- SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+ SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
+ void __sanitizer_sandbox_on_notify(void *reserved);
// This function is called by the tool when it has just finished reporting
// an error. 'error_summary' is a one-line string that summarizes
// the error message. This function can be overridden by the client.
- void __sanitizer_report_error_summary(const char *error_summary)
- SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE;
+ SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
+ void __sanitizer_report_error_summary(const char *error_summary);
} // extern "C"
@@ -95,13 +108,13 @@ using namespace __sanitizer; // NOLINT
// This header should NOT include any other headers to avoid portability issues.
// Common defs.
-#define INLINE static inline
+#define INLINE inline
#define INTERFACE_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
#define WEAK SANITIZER_WEAK_ATTRIBUTE
// Platform-specific defs.
#if defined(_MSC_VER)
-# define ALWAYS_INLINE __declspec(forceinline)
+# define ALWAYS_INLINE __forceinline
// FIXME(timurrrr): do we need this on Windows?
# define ALIAS(x)
# define ALIGNED(x) __declspec(align(x))
@@ -116,8 +129,10 @@ using namespace __sanitizer; // NOLINT
# define USED
# define PREFETCH(x) /* _mm_prefetch(x, _MM_HINT_NTA) */
#else // _MSC_VER
-# define ALWAYS_INLINE __attribute__((always_inline))
+# define ALWAYS_INLINE inline __attribute__((always_inline))
# define ALIAS(x) __attribute__((alias(x)))
+// Please only use the ALIGNED macro before the type.
+// Using ALIGNED after the variable declaration is not portable!
# define ALIGNED(x) __attribute__((aligned(x)))
# define FORMAT(f, a) __attribute__((format(printf, f, a)))
# define NOINLINE __attribute__((noinline))
@@ -136,7 +151,15 @@ using namespace __sanitizer; // NOLINT
# endif
#endif // _MSC_VER
-#if defined(_WIN32)
+// Unaligned versions of basic types.
+typedef ALIGNED(1) u16 uu16;
+typedef ALIGNED(1) u32 uu32;
+typedef ALIGNED(1) u64 uu64;
+typedef ALIGNED(1) s16 us16;
+typedef ALIGNED(1) s32 us32;
+typedef ALIGNED(1) s64 us64;
+
+#if SANITIZER_WINDOWS
typedef unsigned long DWORD; // NOLINT
typedef DWORD thread_return_t;
# define THREAD_CALLING_CONV __stdcall
@@ -155,6 +178,9 @@ typedef thread_return_t (THREAD_CALLING_CONV *thread_callback_t)(void* arg);
// NOTE: Functions below must be defined in each run-time.
namespace __sanitizer {
void NORETURN Die();
+
+// FIXME: No, this shouldn't be in the sanitizer interface.
+SANITIZER_INTERFACE_ATTRIBUTE
void NORETURN CheckFailed(const char *file, int line, const char *cond,
u64 v1, u64 v2);
} // namespace __sanitizer
@@ -259,10 +285,12 @@ extern "C" void* _ReturnAddress(void);
# define GET_CURRENT_FRAME() (uptr)0xDEADBEEF
#endif
-#define HANDLE_EINTR(res, f) { \
- do { \
- res = (f); \
- } while (res == -1 && errno == EINTR); \
+#define HANDLE_EINTR(res, f) \
+ { \
+ int rverrno; \
+ do { \
+ res = (f); \
+ } while (internal_iserror(res, &rverrno) && rverrno == EINTR); \
}
#endif // SANITIZER_DEFS_H
diff --git a/libsanitizer/sanitizer_common/sanitizer_libc.cc b/libsanitizer/sanitizer_common/sanitizer_libc.cc
index c57128a54cb..2a75e431b31 100644
--- a/libsanitizer/sanitizer_common/sanitizer_libc.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_libc.cc
@@ -8,6 +8,7 @@
// This file is shared between AddressSanitizer and ThreadSanitizer
// run-time libraries. See sanitizer_libc.h for details.
//===----------------------------------------------------------------------===//
+#include "sanitizer_allocator_internal.h"
#include "sanitizer_common.h"
#include "sanitizer_libc.h"
@@ -122,6 +123,13 @@ char* internal_strchr(const char *s, int c) {
}
}
+char *internal_strchrnul(const char *s, int c) {
+ char *res = internal_strchr(s, c);
+ if (!res)
+ res = (char*)s + internal_strlen(s);
+ return res;
+}
+
char *internal_strrchr(const char *s, int c) {
const char *res = 0;
for (uptr i = 0; s[i]; i++) {
@@ -149,8 +157,7 @@ char *internal_strncpy(char *dst, const char *src, uptr n) {
uptr i;
for (i = 0; i < n && src[i]; i++)
dst[i] = src[i];
- for (; i < n; i++)
- dst[i] = '\0';
+ internal_memset(dst + i, '\0', n - i);
return dst;
}
diff --git a/libsanitizer/sanitizer_common/sanitizer_libc.h b/libsanitizer/sanitizer_common/sanitizer_libc.h
index 16239413356..f90ffcc679a 100644
--- a/libsanitizer/sanitizer_common/sanitizer_libc.h
+++ b/libsanitizer/sanitizer_common/sanitizer_libc.h
@@ -30,6 +30,7 @@ void *internal_memmove(void *dest, const void *src, uptr n);
// Should not be used in performance-critical places.
void *internal_memset(void *s, int c, uptr n);
char* internal_strchr(const char *s, int c);
+char *internal_strchrnul(const char *s, int c);
int internal_strcmp(const char *s1, const char *s2);
uptr internal_strcspn(const char *s, const char *reject);
char *internal_strdup(const char *s);
@@ -51,36 +52,46 @@ bool mem_is_zero(const char *mem, uptr size);
// Memory
-void *internal_mmap(void *addr, uptr length, int prot, int flags,
- int fd, u64 offset);
-int internal_munmap(void *addr, uptr length);
+uptr internal_mmap(void *addr, uptr length, int prot, int flags,
+ int fd, u64 offset);
+uptr internal_munmap(void *addr, uptr length);
// I/O
const fd_t kInvalidFd = -1;
const fd_t kStdinFd = 0;
const fd_t kStdoutFd = 1;
const fd_t kStderrFd = 2;
-int internal_close(fd_t fd);
+uptr internal_close(fd_t fd);
int internal_isatty(fd_t fd);
// Use __sanitizer::OpenFile() instead.
-fd_t internal_open(const char *filename, int flags);
-fd_t internal_open(const char *filename, int flags, u32 mode);
+uptr internal_open(const char *filename, int flags);
+uptr internal_open(const char *filename, int flags, u32 mode);
uptr internal_read(fd_t fd, void *buf, uptr count);
uptr internal_write(fd_t fd, const void *buf, uptr count);
// OS
uptr internal_filesize(fd_t fd); // -1 on error.
-int internal_stat(const char *path, void *buf);
-int internal_lstat(const char *path, void *buf);
-int internal_fstat(fd_t fd, void *buf);
-int internal_dup2(int oldfd, int newfd);
+uptr internal_stat(const char *path, void *buf);
+uptr internal_lstat(const char *path, void *buf);
+uptr internal_fstat(fd_t fd, void *buf);
+uptr internal_dup2(int oldfd, int newfd);
uptr internal_readlink(const char *path, char *buf, uptr bufsize);
+uptr internal_unlink(const char *path);
void NORETURN internal__exit(int exitcode);
+uptr internal_lseek(fd_t fd, OFF_T offset, int whence);
+
+uptr internal_ptrace(int request, int pid, void *addr, void *data);
+uptr internal_waitpid(int pid, int *status, int options);
+uptr internal_getpid();
+uptr internal_getppid();
// Threading
-int internal_sched_yield();
+uptr internal_sched_yield();
+
+// Error handling
+bool internal_iserror(uptr retval, int *rverrno = 0);
} // namespace __sanitizer
diff --git a/libsanitizer/sanitizer_common/sanitizer_linux.cc b/libsanitizer/sanitizer_common/sanitizer_linux.cc
index 1ab6f780fa3..2763313015a 100644
--- a/libsanitizer/sanitizer_common/sanitizer_linux.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_linux.cc
@@ -9,29 +9,48 @@
// run-time libraries and implements linux-specific functions from
// sanitizer_libc.h.
//===----------------------------------------------------------------------===//
-#ifdef __linux__
+
+#include "sanitizer_platform.h"
+#if SANITIZER_LINUX
#include "sanitizer_common.h"
#include "sanitizer_internal_defs.h"
#include "sanitizer_libc.h"
+#include "sanitizer_linux.h"
#include "sanitizer_mutex.h"
#include "sanitizer_placement_new.h"
#include "sanitizer_procmaps.h"
#include "sanitizer_stacktrace.h"
+#include "sanitizer_symbolizer.h"
+#include <asm/param.h>
+#include <dlfcn.h>
+#include <errno.h>
#include <fcntl.h>
+#if !SANITIZER_ANDROID
+#include <link.h>
+#endif
#include <pthread.h>
#include <sched.h>
#include <sys/mman.h>
+#include <sys/ptrace.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/time.h>
#include <sys/types.h>
-#include <sys/prctl.h>
#include <unistd.h>
#include <unwind.h>
-#include <errno.h>
+
+#if !SANITIZER_ANDROID
+#include <sys/signal.h>
+#endif
+
+// <linux/time.h>
+struct kernel_timeval {
+ long tv_sec;
+ long tv_usec;
+};
// <linux/futex.h> is broken on some linux distributions.
const int FUTEX_WAIT = 0;
@@ -48,165 +67,158 @@ const int FUTEX_WAKE = 1;
namespace __sanitizer {
+#ifdef __x86_64__
+#include "sanitizer_syscall_linux_x86_64.inc"
+#else
+#include "sanitizer_syscall_generic.inc"
+#endif
+
// --------------- sanitizer_libc.h
-void *internal_mmap(void *addr, uptr length, int prot, int flags,
+uptr internal_mmap(void *addr, uptr length, int prot, int flags,
int fd, u64 offset) {
#if SANITIZER_LINUX_USES_64BIT_SYSCALLS
- return (void *)syscall(__NR_mmap, addr, length, prot, flags, fd, offset);
+ return internal_syscall(__NR_mmap, (uptr)addr, length, prot, flags, fd, offset);
#else
- return (void *)syscall(__NR_mmap2, addr, length, prot, flags, fd, offset);
+ return internal_syscall(__NR_mmap2, addr, length, prot, flags, fd, offset);
#endif
}
-int internal_munmap(void *addr, uptr length) {
- return syscall(__NR_munmap, addr, length);
+uptr internal_munmap(void *addr, uptr length) {
+ return internal_syscall(__NR_munmap, (uptr)addr, length);
}
-int internal_close(fd_t fd) {
- return syscall(__NR_close, fd);
+uptr internal_close(fd_t fd) {
+ return internal_syscall(__NR_close, fd);
}
-fd_t internal_open(const char *filename, int flags) {
- return syscall(__NR_open, filename, flags);
+uptr internal_open(const char *filename, int flags) {
+ return internal_syscall(__NR_open, (uptr)filename, flags);
}
-fd_t internal_open(const char *filename, int flags, u32 mode) {
- return syscall(__NR_open, filename, flags, mode);
+uptr internal_open(const char *filename, int flags, u32 mode) {
+ return internal_syscall(__NR_open, (uptr)filename, flags, mode);
}
-fd_t OpenFile(const char *filename, bool write) {
+uptr OpenFile(const char *filename, bool write) {
return internal_open(filename,
write ? O_WRONLY | O_CREAT /*| O_CLOEXEC*/ : O_RDONLY, 0660);
}
uptr internal_read(fd_t fd, void *buf, uptr count) {
sptr res;
- HANDLE_EINTR(res, (sptr)syscall(__NR_read, fd, buf, count));
+ HANDLE_EINTR(res, (sptr)internal_syscall(__NR_read, fd, (uptr)buf, count));
return res;
}
uptr internal_write(fd_t fd, const void *buf, uptr count) {
sptr res;
- HANDLE_EINTR(res, (sptr)syscall(__NR_write, fd, buf, count));
+ HANDLE_EINTR(res, (sptr)internal_syscall(__NR_write, fd, (uptr)buf, count));
return res;
}
-int internal_stat(const char *path, void *buf) {
+#if !SANITIZER_LINUX_USES_64BIT_SYSCALLS
+static void stat64_to_stat(struct stat64 *in, struct stat *out) {
+ internal_memset(out, 0, sizeof(*out));
+ out->st_dev = in->st_dev;
+ out->st_ino = in->st_ino;
+ out->st_mode = in->st_mode;
+ out->st_nlink = in->st_nlink;
+ out->st_uid = in->st_uid;
+ out->st_gid = in->st_gid;
+ out->st_rdev = in->st_rdev;
+ out->st_size = in->st_size;
+ out->st_blksize = in->st_blksize;
+ out->st_blocks = in->st_blocks;
+ out->st_atime = in->st_atime;
+ out->st_mtime = in->st_mtime;
+ out->st_ctime = in->st_ctime;
+ out->st_ino = in->st_ino;
+}
+#endif
+
+uptr internal_stat(const char *path, void *buf) {
#if SANITIZER_LINUX_USES_64BIT_SYSCALLS
- return syscall(__NR_stat, path, buf);
+ return internal_syscall(__NR_stat, (uptr)path, (uptr)buf);
#else
- return syscall(__NR_stat64, path, buf);
+ struct stat64 buf64;
+ int res = internal_syscall(__NR_stat64, path, &buf64);
+ stat64_to_stat(&buf64, (struct stat *)buf);
+ return res;
#endif
}
-int internal_lstat(const char *path, void *buf) {
+uptr internal_lstat(const char *path, void *buf) {
#if SANITIZER_LINUX_USES_64BIT_SYSCALLS
- return syscall(__NR_lstat, path, buf);
+ return internal_syscall(__NR_lstat, (uptr)path, (uptr)buf);
#else
- return syscall(__NR_lstat64, path, buf);
+ struct stat64 buf64;
+ int res = internal_syscall(__NR_lstat64, path, &buf64);
+ stat64_to_stat(&buf64, (struct stat *)buf);
+ return res;
#endif
}
-int internal_fstat(fd_t fd, void *buf) {
+uptr internal_fstat(fd_t fd, void *buf) {
#if SANITIZER_LINUX_USES_64BIT_SYSCALLS
- return syscall(__NR_fstat, fd, buf);
+ return internal_syscall(__NR_fstat, fd, (uptr)buf);
#else
- return syscall(__NR_fstat64, fd, buf);
+ struct stat64 buf64;
+ int res = internal_syscall(__NR_fstat64, fd, &buf64);
+ stat64_to_stat(&buf64, (struct stat *)buf);
+ return res;
#endif
}
uptr internal_filesize(fd_t fd) {
-#if SANITIZER_LINUX_USES_64BIT_SYSCALLS
struct stat st;
-#else
- struct stat64 st;
-#endif
if (internal_fstat(fd, &st))
return -1;
return (uptr)st.st_size;
}
-int internal_dup2(int oldfd, int newfd) {
- return syscall(__NR_dup2, oldfd, newfd);
+uptr internal_dup2(int oldfd, int newfd) {
+ return internal_syscall(__NR_dup2, oldfd, newfd);
}
uptr internal_readlink(const char *path, char *buf, uptr bufsize) {
- return (uptr)syscall(__NR_readlink, path, buf, bufsize);
+ return internal_syscall(__NR_readlink, (uptr)path, (uptr)buf, bufsize);
+}
+
+uptr internal_unlink(const char *path) {
+ return internal_syscall(__NR_unlink, (uptr)path);
}
-int internal_sched_yield() {
- return syscall(__NR_sched_yield);
+uptr internal_sched_yield() {
+ return internal_syscall(__NR_sched_yield);
}
void internal__exit(int exitcode) {
- syscall(__NR_exit_group, exitcode);
+ internal_syscall(__NR_exit_group, exitcode);
Die(); // Unreachable.
}
+uptr internal_execve(const char *filename, char *const argv[],
+ char *const envp[]) {
+ return internal_syscall(__NR_execve, (uptr)filename, (uptr)argv, (uptr)envp);
+}
+
// ----------------- sanitizer_common.h
bool FileExists(const char *filename) {
-#if SANITIZER_LINUX_USES_64BIT_SYSCALLS
struct stat st;
- if (syscall(__NR_stat, filename, &st))
+ if (internal_stat(filename, &st))
return false;
-#else
- struct stat64 st;
- if (syscall(__NR_stat64, filename, &st))
- return false;
-#endif
// Sanity check: filename is a regular file.
return S_ISREG(st.st_mode);
}
uptr GetTid() {
- return syscall(__NR_gettid);
-}
-
-void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
- uptr *stack_bottom) {
- static const uptr kMaxThreadStackSize = 256 * (1 << 20); // 256M
- CHECK(stack_top);
- CHECK(stack_bottom);
- if (at_initialization) {
- // This is the main thread. Libpthread may not be initialized yet.
- struct rlimit rl;
- CHECK_EQ(getrlimit(RLIMIT_STACK, &rl), 0);
-
- // Find the mapping that contains a stack variable.
- MemoryMappingLayout proc_maps;
- uptr start, end, offset;
- uptr prev_end = 0;
- while (proc_maps.Next(&start, &end, &offset, 0, 0)) {
- if ((uptr)&rl < end)
- break;
- prev_end = end;
- }
- CHECK((uptr)&rl >= start && (uptr)&rl < end);
-
- // Get stacksize from rlimit, but clip it so that it does not overlap
- // with other mappings.
- uptr stacksize = rl.rlim_cur;
- if (stacksize > end - prev_end)
- stacksize = end - prev_end;
- // When running with unlimited stack size, we still want to set some limit.
- // The unlimited stack size is caused by 'ulimit -s unlimited'.
- // Also, for some reason, GNU make spawns subprocesses with unlimited stack.
- if (stacksize > kMaxThreadStackSize)
- stacksize = kMaxThreadStackSize;
- *stack_top = end;
- *stack_bottom = end - stacksize;
- return;
- }
- pthread_attr_t attr;
- CHECK_EQ(pthread_getattr_np(pthread_self(), &attr), 0);
- uptr stacksize = 0;
- void *stackaddr = 0;
- pthread_attr_getstack(&attr, &stackaddr, (size_t*)&stacksize);
- pthread_attr_destroy(&attr);
+ return internal_syscall(__NR_gettid);
+}
- *stack_top = (uptr)stackaddr + stacksize;
- *stack_bottom = (uptr)stackaddr;
- CHECK(stacksize < kMaxThreadStackSize); // Sanity check.
+u64 NanoTime() {
+ kernel_timeval tv = {};
+ internal_syscall(__NR_gettimeofday, (uptr)&tv, 0);
+ return (u64)tv.tv_sec * 1000*1000*1000 + tv.tv_usec * 1000;
}
// Like getenv, but reads env directly from /proc and does not use libc.
@@ -237,21 +249,11 @@ const char *GetEnv(const char *name) {
return 0; // Not found.
}
-#ifdef __GLIBC__
-
extern "C" {
- extern void *__libc_stack_end;
-}
-
-static void GetArgsAndEnv(char ***argv, char ***envp) {
- uptr *stack_end = (uptr *)__libc_stack_end;
- int argc = *stack_end;
- *argv = (char**)(stack_end + 1);
- *envp = (char**)(stack_end + argc + 2);
+ SANITIZER_WEAK_ATTRIBUTE extern void *__libc_stack_end;
}
-#else // __GLIBC__
-
+#if !SANITIZER_GO
static void ReadNullSepFileToArray(const char *path, char ***arr,
int arr_size) {
char *buff;
@@ -270,20 +272,32 @@ static void ReadNullSepFileToArray(const char *path, char ***arr,
}
(*arr)[count] = 0;
}
+#endif
-static void GetArgsAndEnv(char ***argv, char ***envp) {
- static const int kMaxArgv = 2000, kMaxEnvp = 2000;
- ReadNullSepFileToArray("/proc/self/cmdline", argv, kMaxArgv);
- ReadNullSepFileToArray("/proc/self/environ", envp, kMaxEnvp);
+static void GetArgsAndEnv(char*** argv, char*** envp) {
+#if !SANITIZER_GO
+ if (&__libc_stack_end) {
+#endif
+ uptr* stack_end = (uptr*)__libc_stack_end;
+ int argc = *stack_end;
+ *argv = (char**)(stack_end + 1);
+ *envp = (char**)(stack_end + argc + 2);
+#if !SANITIZER_GO
+ } else {
+ static const int kMaxArgv = 2000, kMaxEnvp = 2000;
+ ReadNullSepFileToArray("/proc/self/cmdline", argv, kMaxArgv);
+ ReadNullSepFileToArray("/proc/self/environ", envp, kMaxEnvp);
+ }
+#endif
}
-#endif // __GLIBC__
-
void ReExec() {
char **argv, **envp;
GetArgsAndEnv(&argv, &envp);
- execve("/proc/self/exe", argv, envp);
- Printf("execve failed, errno %d\n", errno);
+ uptr rv = internal_execve("/proc/self/exe", argv, envp);
+ int rverrno;
+ CHECK_EQ(internal_iserror(rv, &rverrno), true);
+ Printf("execve failed, errno %d\n", rverrno);
Die();
}
@@ -293,6 +307,10 @@ void PrepareForSandboxing() {
// process will be able to load additional libraries, so it's fine to use the
// cached mappings.
MemoryMappingLayout::CacheMemoryMappings();
+ // Same for /proc/self/exe in the symbolizer.
+#if !SANITIZER_GO
+ getSymbolizer()->PrepareForSandboxing();
+#endif
}
// ----------------- sanitizer_procmaps.h
@@ -300,18 +318,22 @@ void PrepareForSandboxing() {
ProcSelfMapsBuff MemoryMappingLayout::cached_proc_self_maps_;
StaticSpinMutex MemoryMappingLayout::cache_lock_; // Linker initialized.
-MemoryMappingLayout::MemoryMappingLayout() {
+MemoryMappingLayout::MemoryMappingLayout(bool cache_enabled) {
proc_self_maps_.len =
ReadFileToBuffer("/proc/self/maps", &proc_self_maps_.data,
&proc_self_maps_.mmaped_size, 1 << 26);
- if (proc_self_maps_.mmaped_size == 0) {
- LoadFromCache();
- CHECK_GT(proc_self_maps_.len, 0);
+ if (cache_enabled) {
+ if (proc_self_maps_.mmaped_size == 0) {
+ LoadFromCache();
+ CHECK_GT(proc_self_maps_.len, 0);
+ }
+ } else {
+ CHECK_GT(proc_self_maps_.mmaped_size, 0);
}
- // internal_write(2, proc_self_maps_.data, proc_self_maps_.len);
Reset();
// FIXME: in the future we may want to cache the mappings on demand only.
- CacheMemoryMappings();
+ if (cache_enabled)
+ CacheMemoryMappings();
}
MemoryMappingLayout::~MemoryMappingLayout() {
@@ -373,7 +395,7 @@ static uptr ParseHex(char **str) {
return x;
}
-static bool IsOnOf(char c, char c1, char c2) {
+static bool IsOneOf(char c, char c1, char c2) {
return c == c1 || c == c2;
}
@@ -381,8 +403,33 @@ static bool IsDecimal(char c) {
return c >= '0' && c <= '9';
}
+static bool IsHex(char c) {
+ return (c >= '0' && c <= '9')
+ || (c >= 'a' && c <= 'f');
+}
+
+static uptr ReadHex(const char *p) {
+ uptr v = 0;
+ for (; IsHex(p[0]); p++) {
+ if (p[0] >= '0' && p[0] <= '9')
+ v = v * 16 + p[0] - '0';
+ else
+ v = v * 16 + p[0] - 'a' + 10;
+ }
+ return v;
+}
+
+static uptr ReadDecimal(const char *p) {
+ uptr v = 0;
+ for (; IsDecimal(p[0]); p++)
+ v = v * 10 + p[0] - '0';
+ return v;
+}
+
+
bool MemoryMappingLayout::Next(uptr *start, uptr *end, uptr *offset,
- char filename[], uptr filename_size) {
+ char filename[], uptr filename_size,
+ uptr *protection) {
char *last = proc_self_maps_.data + proc_self_maps_.len;
if (current_ >= last) return false;
uptr dummy;
@@ -397,10 +444,22 @@ bool MemoryMappingLayout::Next(uptr *start, uptr *end, uptr *offset,
CHECK_EQ(*current_++, '-');
*end = ParseHex(&current_);
CHECK_EQ(*current_++, ' ');
- CHECK(IsOnOf(*current_++, '-', 'r'));
- CHECK(IsOnOf(*current_++, '-', 'w'));
- CHECK(IsOnOf(*current_++, '-', 'x'));
- CHECK(IsOnOf(*current_++, 's', 'p'));
+ uptr local_protection = 0;
+ CHECK(IsOneOf(*current_, '-', 'r'));
+ if (*current_++ == 'r')
+ local_protection |= kProtectionRead;
+ CHECK(IsOneOf(*current_, '-', 'w'));
+ if (*current_++ == 'w')
+ local_protection |= kProtectionWrite;
+ CHECK(IsOneOf(*current_, '-', 'x'));
+ if (*current_++ == 'x')
+ local_protection |= kProtectionExecute;
+ CHECK(IsOneOf(*current_, 's', 'p'));
+ if (*current_++ == 's')
+ local_protection |= kProtectionShared;
+ if (protection) {
+ *protection = local_protection;
+ }
CHECK_EQ(*current_++, ' ');
*offset = ParseHex(&current_);
CHECK_EQ(*current_++, ' ');
@@ -432,87 +491,35 @@ bool MemoryMappingLayout::Next(uptr *start, uptr *end, uptr *offset,
// Gets the object name and the offset by walking MemoryMappingLayout.
bool MemoryMappingLayout::GetObjectNameAndOffset(uptr addr, uptr *offset,
char filename[],
- uptr filename_size) {
- return IterateForObjectNameAndOffset(addr, offset, filename, filename_size);
-}
-
-bool SanitizerSetThreadName(const char *name) {
-#ifdef PR_SET_NAME
- return 0 == prctl(PR_SET_NAME, (unsigned long)name, 0, 0, 0); // NOLINT
-#else
- return false;
-#endif
-}
-
-bool SanitizerGetThreadName(char *name, int max_len) {
-#ifdef PR_GET_NAME
- char buff[17];
- if (prctl(PR_GET_NAME, (unsigned long)buff, 0, 0, 0)) // NOLINT
- return false;
- internal_strncpy(name, buff, max_len);
- name[max_len] = 0;
- return true;
-#else
- return false;
-#endif
-}
-
-#ifndef SANITIZER_GO
-//------------------------- SlowUnwindStack -----------------------------------
-#ifdef __arm__
-#define UNWIND_STOP _URC_END_OF_STACK
-#define UNWIND_CONTINUE _URC_NO_REASON
-#else
-#define UNWIND_STOP _URC_NORMAL_STOP
-#define UNWIND_CONTINUE _URC_NO_REASON
-#endif
-
-uptr Unwind_GetIP(struct _Unwind_Context *ctx) {
-#ifdef __arm__
- uptr val;
- _Unwind_VRS_Result res = _Unwind_VRS_Get(ctx, _UVRSC_CORE,
- 15 /* r15 = PC */, _UVRSD_UINT32, &val);
- CHECK(res == _UVRSR_OK && "_Unwind_VRS_Get failed");
- // Clear the Thumb bit.
- return val & ~(uptr)1;
-#else
- return _Unwind_GetIP(ctx);
-#endif
-}
-
-_Unwind_Reason_Code Unwind_Trace(struct _Unwind_Context *ctx, void *param) {
- StackTrace *b = (StackTrace*)param;
- CHECK(b->size < b->max_size);
- uptr pc = Unwind_GetIP(ctx);
- b->trace[b->size++] = pc;
- if (b->size == b->max_size) return UNWIND_STOP;
- return UNWIND_CONTINUE;
-}
-
-static bool MatchPc(uptr cur_pc, uptr trace_pc) {
- return cur_pc - trace_pc <= 64 || trace_pc - cur_pc <= 64;
-}
-
-void StackTrace::SlowUnwindStack(uptr pc, uptr max_depth) {
- this->size = 0;
- this->max_size = max_depth;
- if (max_depth > 1) {
- _Unwind_Backtrace(Unwind_Trace, this);
- // We need to pop a few frames so that pc is on top.
- // trace[0] belongs to the current function so we always pop it.
- int to_pop = 1;
- /**/ if (size > 1 && MatchPc(pc, trace[1])) to_pop = 1;
- else if (size > 2 && MatchPc(pc, trace[2])) to_pop = 2;
- else if (size > 3 && MatchPc(pc, trace[3])) to_pop = 3;
- else if (size > 4 && MatchPc(pc, trace[4])) to_pop = 4;
- else if (size > 5 && MatchPc(pc, trace[5])) to_pop = 5;
- this->PopStackFrames(to_pop);
+ uptr filename_size,
+ uptr *protection) {
+ return IterateForObjectNameAndOffset(addr, offset, filename, filename_size,
+ protection);
+}
+
+void GetMemoryProfile(fill_profile_f cb, uptr *stats, uptr stats_size) {
+ char *smaps = 0;
+ uptr smaps_cap = 0;
+ uptr smaps_len = ReadFileToBuffer("/proc/self/smaps",
+ &smaps, &smaps_cap, 64<<20);
+ uptr start = 0;
+ bool file = false;
+ const char *pos = smaps;
+ while (pos < smaps + smaps_len) {
+ if (IsHex(pos[0])) {
+ start = ReadHex(pos);
+ for (; *pos != '/' && *pos > '\n'; pos++) {}
+ file = *pos == '/';
+ } else if (internal_strncmp(pos, "Rss:", 4) == 0) {
+ for (; *pos < '0' || *pos > '9'; pos++) {}
+ uptr rss = ReadDecimal(pos) * 1024;
+ cb(start, rss, file, stats, stats_size);
+ }
+ while (*pos++ != '\n') {}
}
- this->trace[0] = pc;
+ UnmapOrDie(smaps, smaps_cap);
}
-#endif // #ifndef SANITIZER_GO
-
enum MutexState {
MtxUnlocked = 0,
MtxLocked = 1,
@@ -523,12 +530,16 @@ BlockingMutex::BlockingMutex(LinkerInitialized) {
CHECK_EQ(owner_, 0);
}
+BlockingMutex::BlockingMutex() {
+ internal_memset(this, 0, sizeof(*this));
+}
+
void BlockingMutex::Lock() {
atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
if (atomic_exchange(m, MtxLocked, memory_order_acquire) == MtxUnlocked)
return;
while (atomic_exchange(m, MtxSleeping, memory_order_acquire) != MtxUnlocked)
- syscall(__NR_futex, m, FUTEX_WAIT, MtxSleeping, 0, 0, 0);
+ internal_syscall(__NR_futex, (uptr)m, FUTEX_WAIT, MtxSleeping, 0, 0, 0);
}
void BlockingMutex::Unlock() {
@@ -536,9 +547,281 @@ void BlockingMutex::Unlock() {
u32 v = atomic_exchange(m, MtxUnlocked, memory_order_relaxed);
CHECK_NE(v, MtxUnlocked);
if (v == MtxSleeping)
- syscall(__NR_futex, m, FUTEX_WAKE, 1, 0, 0, 0);
+ internal_syscall(__NR_futex, (uptr)m, FUTEX_WAKE, 1, 0, 0, 0);
+}
+
+void BlockingMutex::CheckLocked() {
+ atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
+ CHECK_NE(MtxUnlocked, atomic_load(m, memory_order_relaxed));
+}
+
+// ----------------- sanitizer_linux.h
+// The actual size of this structure is specified by d_reclen.
+// Note that getdents64 uses a different structure format. We only provide the
+// 32-bit syscall here.
+struct linux_dirent {
+ unsigned long d_ino;
+ unsigned long d_off;
+ unsigned short d_reclen;
+ char d_name[256];
+};
+
+// Syscall wrappers.
+uptr internal_ptrace(int request, int pid, void *addr, void *data) {
+ return internal_syscall(__NR_ptrace, request, pid, (uptr)addr, (uptr)data);
+}
+
+uptr internal_waitpid(int pid, int *status, int options) {
+ return internal_syscall(__NR_wait4, pid, (uptr)status, options, 0 /* rusage */);
+}
+
+uptr internal_getpid() {
+ return internal_syscall(__NR_getpid);
+}
+
+uptr internal_getppid() {
+ return internal_syscall(__NR_getppid);
+}
+
+uptr internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count) {
+ return internal_syscall(__NR_getdents, fd, (uptr)dirp, count);
+}
+
+uptr internal_lseek(fd_t fd, OFF_T offset, int whence) {
+ return internal_syscall(__NR_lseek, fd, offset, whence);
+}
+
+uptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5) {
+ return internal_syscall(__NR_prctl, option, arg2, arg3, arg4, arg5);
+}
+
+uptr internal_sigaltstack(const struct sigaltstack *ss,
+ struct sigaltstack *oss) {
+ return internal_syscall(__NR_sigaltstack, (uptr)ss, (uptr)oss);
+}
+
+// ThreadLister implementation.
+ThreadLister::ThreadLister(int pid)
+ : pid_(pid),
+ descriptor_(-1),
+ buffer_(4096),
+ error_(true),
+ entry_((struct linux_dirent *)buffer_.data()),
+ bytes_read_(0) {
+ char task_directory_path[80];
+ internal_snprintf(task_directory_path, sizeof(task_directory_path),
+ "/proc/%d/task/", pid);
+ uptr openrv = internal_open(task_directory_path, O_RDONLY | O_DIRECTORY);
+ if (internal_iserror(openrv)) {
+ error_ = true;
+ Report("Can't open /proc/%d/task for reading.\n", pid);
+ } else {
+ error_ = false;
+ descriptor_ = openrv;
+ }
+}
+
+int ThreadLister::GetNextTID() {
+ int tid = -1;
+ do {
+ if (error_)
+ return -1;
+ if ((char *)entry_ >= &buffer_[bytes_read_] && !GetDirectoryEntries())
+ return -1;
+ if (entry_->d_ino != 0 && entry_->d_name[0] >= '0' &&
+ entry_->d_name[0] <= '9') {
+ // Found a valid tid.
+ tid = (int)internal_atoll(entry_->d_name);
+ }
+ entry_ = (struct linux_dirent *)(((char *)entry_) + entry_->d_reclen);
+ } while (tid < 0);
+ return tid;
+}
+
+void ThreadLister::Reset() {
+ if (error_ || descriptor_ < 0)
+ return;
+ internal_lseek(descriptor_, 0, SEEK_SET);
+}
+
+ThreadLister::~ThreadLister() {
+ if (descriptor_ >= 0)
+ internal_close(descriptor_);
+}
+
+bool ThreadLister::error() { return error_; }
+
+bool ThreadLister::GetDirectoryEntries() {
+ CHECK_GE(descriptor_, 0);
+ CHECK_NE(error_, true);
+ bytes_read_ = internal_getdents(descriptor_,
+ (struct linux_dirent *)buffer_.data(),
+ buffer_.size());
+ if (internal_iserror(bytes_read_)) {
+ Report("Can't read directory entries from /proc/%d/task.\n", pid_);
+ error_ = true;
+ return false;
+ } else if (bytes_read_ == 0) {
+ return false;
+ }
+ entry_ = (struct linux_dirent *)buffer_.data();
+ return true;
+}
+
+uptr GetPageSize() {
+#if defined(__x86_64__) || defined(__i386__)
+ return EXEC_PAGESIZE;
+#else
+ return sysconf(_SC_PAGESIZE); // EXEC_PAGESIZE may not be trustworthy.
+#endif
+}
+
+static char proc_self_exe_cache_str[kMaxPathLength];
+static uptr proc_self_exe_cache_len = 0;
+
+uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) {
+ uptr module_name_len = internal_readlink(
+ "/proc/self/exe", buf, buf_len);
+ int readlink_error;
+ if (internal_iserror(module_name_len, &readlink_error)) {
+ if (proc_self_exe_cache_len) {
+ // If available, use the cached module name.
+ CHECK_LE(proc_self_exe_cache_len, buf_len);
+ internal_strncpy(buf, proc_self_exe_cache_str, buf_len);
+ module_name_len = internal_strlen(proc_self_exe_cache_str);
+ } else {
+ // We can't read /proc/self/exe for some reason, assume the name of the
+ // binary is unknown.
+ Report("WARNING: readlink(\"/proc/self/exe\") failed with errno %d, "
+ "some stack frames may not be symbolized\n", readlink_error);
+ module_name_len = internal_snprintf(buf, buf_len, "/proc/self/exe");
+ }
+ CHECK_LT(module_name_len, buf_len);
+ buf[module_name_len] = '\0';
+ }
+ return module_name_len;
}
+void CacheBinaryName() {
+ if (!proc_self_exe_cache_len) {
+ proc_self_exe_cache_len =
+ ReadBinaryName(proc_self_exe_cache_str, kMaxPathLength);
+ }
+}
+
+// Match full names of the form /path/to/base_name{-,.}*
+bool LibraryNameIs(const char *full_name, const char *base_name) {
+ const char *name = full_name;
+ // Strip path.
+ while (*name != '\0') name++;
+ while (name > full_name && *name != '/') name--;
+ if (*name == '/') name++;
+ uptr base_name_length = internal_strlen(base_name);
+ if (internal_strncmp(name, base_name, base_name_length)) return false;
+ return (name[base_name_length] == '-' || name[base_name_length] == '.');
+}
+
+#if !SANITIZER_ANDROID
+// Call cb for each region mapped by map.
+void ForEachMappedRegion(link_map *map, void (*cb)(const void *, uptr)) {
+ typedef ElfW(Phdr) Elf_Phdr;
+ typedef ElfW(Ehdr) Elf_Ehdr;
+ char *base = (char *)map->l_addr;
+ Elf_Ehdr *ehdr = (Elf_Ehdr *)base;
+ char *phdrs = base + ehdr->e_phoff;
+ char *phdrs_end = phdrs + ehdr->e_phnum * ehdr->e_phentsize;
+
+ // Find the segment with the minimum base so we can "relocate" the p_vaddr
+ // fields. Typically ET_DYN objects (DSOs) have base of zero and ET_EXEC
+ // objects have a non-zero base.
+ uptr preferred_base = (uptr)-1;
+ for (char *iter = phdrs; iter != phdrs_end; iter += ehdr->e_phentsize) {
+ Elf_Phdr *phdr = (Elf_Phdr *)iter;
+ if (phdr->p_type == PT_LOAD && preferred_base > (uptr)phdr->p_vaddr)
+ preferred_base = (uptr)phdr->p_vaddr;
+ }
+
+ // Compute the delta from the real base to get a relocation delta.
+ sptr delta = (uptr)base - preferred_base;
+ // Now we can figure out what the loader really mapped.
+ for (char *iter = phdrs; iter != phdrs_end; iter += ehdr->e_phentsize) {
+ Elf_Phdr *phdr = (Elf_Phdr *)iter;
+ if (phdr->p_type == PT_LOAD) {
+ uptr seg_start = phdr->p_vaddr + delta;
+ uptr seg_end = seg_start + phdr->p_memsz;
+ // None of these values are aligned. We consider the ragged edges of the
+ // load command as defined, since they are mapped from the file.
+ seg_start = RoundDownTo(seg_start, GetPageSizeCached());
+ seg_end = RoundUpTo(seg_end, GetPageSizeCached());
+ cb((void *)seg_start, seg_end - seg_start);
+ }
+ }
+}
+#endif
+
+#if defined(__x86_64__)
+// We cannot use glibc's clone wrapper, because it messes with the child
+// task's TLS. It writes the PID and TID of the child task to its thread
+// descriptor, but in our case the child task shares the thread descriptor with
+// the parent (because we don't know how to allocate a new thread
+// descriptor to keep glibc happy). So the stock version of clone(), when
+// used with CLONE_VM, would end up corrupting the parent's thread descriptor.
+uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
+ int *parent_tidptr, void *newtls, int *child_tidptr) {
+ long long res;
+ if (!fn || !child_stack)
+ return -EINVAL;
+ CHECK_EQ(0, (uptr)child_stack % 16);
+ child_stack = (char *)child_stack - 2 * sizeof(unsigned long long);
+ ((unsigned long long *)child_stack)[0] = (uptr)fn;
+ ((unsigned long long *)child_stack)[1] = (uptr)arg;
+ register void *r8 __asm__ ("r8") = newtls;
+ register int *r10 __asm__ ("r10") = child_tidptr;
+ __asm__ __volatile__(
+ /* %rax = syscall(%rax = __NR_clone,
+ * %rdi = flags,
+ * %rsi = child_stack,
+ * %rdx = parent_tidptr,
+ * %r8 = new_tls,
+ * %r10 = child_tidptr)
+ */
+ ".cfi_endproc\n"
+ "syscall\n"
+
+ /* if (%rax != 0)
+ * return;
+ */
+ "testq %%rax,%%rax\n"
+ "jnz 1f\n"
+
+ /* In the child. Terminate unwind chain. */
+ ".cfi_startproc\n"
+ ".cfi_undefined %%rip;\n"
+ "xorq %%rbp,%%rbp\n"
+
+ /* Call "fn(arg)". */
+ "popq %%rax\n"
+ "popq %%rdi\n"
+ "call *%%rax\n"
+
+ /* Call _exit(%rax). */
+ "movq %%rax,%%rdi\n"
+ "movq %2,%%rax\n"
+ "syscall\n"
+
+ /* Return to parent. */
+ "1:\n"
+ : "=a" (res)
+ : "a"(__NR_clone), "i"(__NR_exit),
+ "S"(child_stack),
+ "D"(flags),
+ "d"(parent_tidptr),
+ "r"(r8),
+ "r"(r10)
+ : "rsp", "memory", "r11", "rcx");
+ return res;
+}
+#endif // defined(__x86_64__)
} // namespace __sanitizer
-#endif // __linux__
+#endif // SANITIZER_LINUX
diff --git a/libsanitizer/sanitizer_common/sanitizer_linux.h b/libsanitizer/sanitizer_common/sanitizer_linux.h
new file mode 100644
index 00000000000..5bbf47904d8
--- /dev/null
+++ b/libsanitizer/sanitizer_common/sanitizer_linux.h
@@ -0,0 +1,81 @@
+//===-- sanitizer_linux.h ---------------------------------------*- C++ -*-===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Linux-specific syscall wrappers and classes.
+//
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_LINUX_H
+#define SANITIZER_LINUX_H
+
+#include "sanitizer_platform.h"
+#if SANITIZER_LINUX
+#include "sanitizer_common.h"
+#include "sanitizer_internal_defs.h"
+
+struct link_map; // Opaque type returned by dlopen().
+struct sigaltstack;
+
+namespace __sanitizer {
+// Dirent structure for getdents(). Note that this structure is different from
+// the one in <dirent.h>, which is used by readdir().
+struct linux_dirent;
+
+// Syscall wrappers.
+uptr internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count);
+uptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5);
+uptr internal_sigaltstack(const struct sigaltstack* ss,
+ struct sigaltstack* oss);
+#ifdef __x86_64__
+uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
+ int *parent_tidptr, void *newtls, int *child_tidptr);
+#endif
+
+// This class reads thread IDs from /proc/<pid>/task using only syscalls.
+class ThreadLister {
+ public:
+ explicit ThreadLister(int pid);
+ ~ThreadLister();
+ // GetNextTID returns -1 if the list of threads is exhausted, or if there has
+ // been an error.
+ int GetNextTID();
+ void Reset();
+ bool error();
+
+ private:
+ bool GetDirectoryEntries();
+
+ int pid_;
+ int descriptor_;
+ InternalScopedBuffer<char> buffer_;
+ bool error_;
+ struct linux_dirent* entry_;
+ int bytes_read_;
+};
+
+void AdjustStackSizeLinux(void *attr, int verbosity);
+
+// Exposed for testing.
+uptr ThreadDescriptorSize();
+uptr ThreadSelf();
+uptr ThreadSelfOffset();
+
+// Matches a library's file name against a base name (stripping path and version
+// information).
+bool LibraryNameIs(const char *full_name, const char *base_name);
+
+// Read the name of the current binary from /proc/self/exe.
+uptr ReadBinaryName(/*out*/char *buf, uptr buf_len);
+// Cache the value of /proc/self/exe.
+void CacheBinaryName();
+
+// Call cb for each region mapped by map.
+void ForEachMappedRegion(link_map *map, void (*cb)(const void *, uptr));
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_LINUX
+#endif // SANITIZER_LINUX_H
diff --git a/libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cc b/libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cc
new file mode 100644
index 00000000000..7d6c63918de
--- /dev/null
+++ b/libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cc
@@ -0,0 +1,351 @@
+//===-- sanitizer_linux_libcdep.cc ----------------------------------------===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between AddressSanitizer and ThreadSanitizer
+// run-time libraries and implements linux-specific functions from
+// sanitizer_libc.h.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_platform.h"
+#if SANITIZER_LINUX
+
+#include "sanitizer_common.h"
+#include "sanitizer_linux.h"
+#include "sanitizer_placement_new.h"
+#include "sanitizer_procmaps.h"
+#include "sanitizer_stacktrace.h"
+
+#include <dlfcn.h>
+#include <pthread.h>
+#include <sys/prctl.h>
+#include <sys/resource.h>
+#include <unwind.h>
+
+#if !SANITIZER_ANDROID
+#include <elf.h>
+#include <link.h>
+#endif
+
+namespace __sanitizer {
+
+void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
+ uptr *stack_bottom) {
+ static const uptr kMaxThreadStackSize = 1 << 30; // 1Gb
+ CHECK(stack_top);
+ CHECK(stack_bottom);
+ if (at_initialization) {
+ // This is the main thread. Libpthread may not be initialized yet.
+ struct rlimit rl;
+ CHECK_EQ(getrlimit(RLIMIT_STACK, &rl), 0);
+
+ // Find the mapping that contains a stack variable.
+ MemoryMappingLayout proc_maps(/*cache_enabled*/true);
+ uptr start, end, offset;
+ uptr prev_end = 0;
+ while (proc_maps.Next(&start, &end, &offset, 0, 0, /* protection */0)) {
+ if ((uptr)&rl < end)
+ break;
+ prev_end = end;
+ }
+ CHECK((uptr)&rl >= start && (uptr)&rl < end);
+
+ // Get stacksize from rlimit, but clip it so that it does not overlap
+ // with other mappings.
+ uptr stacksize = rl.rlim_cur;
+ if (stacksize > end - prev_end)
+ stacksize = end - prev_end;
+ // When running with unlimited stack size, we still want to set some limit.
+ // The unlimited stack size is caused by 'ulimit -s unlimited'.
+ // Also, for some reason, GNU make spawns subprocesses with unlimited stack.
+ if (stacksize > kMaxThreadStackSize)
+ stacksize = kMaxThreadStackSize;
+ *stack_top = end;
+ *stack_bottom = end - stacksize;
+ return;
+ }
+ pthread_attr_t attr;
+ CHECK_EQ(pthread_getattr_np(pthread_self(), &attr), 0);
+ uptr stacksize = 0;
+ void *stackaddr = 0;
+ pthread_attr_getstack(&attr, &stackaddr, (size_t*)&stacksize);
+ pthread_attr_destroy(&attr);
+
+ CHECK_LE(stacksize, kMaxThreadStackSize); // Sanity check.
+ *stack_top = (uptr)stackaddr + stacksize;
+ *stack_bottom = (uptr)stackaddr;
+}
+
+// Does not compile for Go because dlsym() requires -ldl
+#ifndef SANITIZER_GO
+bool SetEnv(const char *name, const char *value) {
+ void *f = dlsym(RTLD_NEXT, "setenv");
+ if (f == 0)
+ return false;
+ typedef int(*setenv_ft)(const char *name, const char *value, int overwrite);
+ setenv_ft setenv_f;
+ CHECK_EQ(sizeof(setenv_f), sizeof(f));
+ internal_memcpy(&setenv_f, &f, sizeof(f));
+ return setenv_f(name, value, 1) == 0;
+}
+#endif
+
+bool SanitizerSetThreadName(const char *name) {
+#ifdef PR_SET_NAME
+ return 0 == prctl(PR_SET_NAME, (unsigned long)name, 0, 0, 0); // NOLINT
+#else
+ return false;
+#endif
+}
+
+bool SanitizerGetThreadName(char *name, int max_len) {
+#ifdef PR_GET_NAME
+ char buff[17];
+ if (prctl(PR_GET_NAME, (unsigned long)buff, 0, 0, 0)) // NOLINT
+ return false;
+ internal_strncpy(name, buff, max_len);
+ name[max_len] = 0;
+ return true;
+#else
+ return false;
+#endif
+}
+
+#ifndef SANITIZER_GO
+//------------------------- SlowUnwindStack -----------------------------------
+#ifdef __arm__
+#define UNWIND_STOP _URC_END_OF_STACK
+#define UNWIND_CONTINUE _URC_NO_REASON
+#else
+#define UNWIND_STOP _URC_NORMAL_STOP
+#define UNWIND_CONTINUE _URC_NO_REASON
+#endif
+
+uptr Unwind_GetIP(struct _Unwind_Context *ctx) {
+#ifdef __arm__
+ uptr val;
+ _Unwind_VRS_Result res = _Unwind_VRS_Get(ctx, _UVRSC_CORE,
+ 15 /* r15 = PC */, _UVRSD_UINT32, &val);
+ CHECK(res == _UVRSR_OK && "_Unwind_VRS_Get failed");
+ // Clear the Thumb bit.
+ return val & ~(uptr)1;
+#else
+ return _Unwind_GetIP(ctx);
+#endif
+}
+
+_Unwind_Reason_Code Unwind_Trace(struct _Unwind_Context *ctx, void *param) {
+ StackTrace *b = (StackTrace*)param;
+ CHECK(b->size < b->max_size);
+ uptr pc = Unwind_GetIP(ctx);
+ b->trace[b->size++] = pc;
+ if (b->size == b->max_size) return UNWIND_STOP;
+ return UNWIND_CONTINUE;
+}
+
+static bool MatchPc(uptr cur_pc, uptr trace_pc) {
+ return cur_pc - trace_pc <= 64 || trace_pc - cur_pc <= 64;
+}
+
+void StackTrace::SlowUnwindStack(uptr pc, uptr max_depth) {
+ this->size = 0;
+ this->max_size = max_depth;
+ if (max_depth > 1) {
+ _Unwind_Backtrace(Unwind_Trace, this);
+ // We need to pop a few frames so that pc is on top.
+ // trace[0] belongs to the current function so we always pop it.
+ int to_pop = 1;
+ /**/ if (size > 1 && MatchPc(pc, trace[1])) to_pop = 1;
+ else if (size > 2 && MatchPc(pc, trace[2])) to_pop = 2;
+ else if (size > 3 && MatchPc(pc, trace[3])) to_pop = 3;
+ else if (size > 4 && MatchPc(pc, trace[4])) to_pop = 4;
+ else if (size > 5 && MatchPc(pc, trace[5])) to_pop = 5;
+ this->PopStackFrames(to_pop);
+ }
+ this->trace[0] = pc;
+}
+
+#endif // !SANITIZER_GO
+
+static uptr g_tls_size;
+
+#ifdef __i386__
+# define DL_INTERNAL_FUNCTION __attribute__((regparm(3), stdcall))
+#else
+# define DL_INTERNAL_FUNCTION
+#endif
+
+void InitTlsSize() {
+#if !defined(SANITIZER_GO) && !SANITIZER_ANDROID
+ typedef void (*get_tls_func)(size_t*, size_t*) DL_INTERNAL_FUNCTION;
+ get_tls_func get_tls;
+ void *get_tls_static_info_ptr = dlsym(RTLD_NEXT, "_dl_get_tls_static_info");
+ CHECK_EQ(sizeof(get_tls), sizeof(get_tls_static_info_ptr));
+ internal_memcpy(&get_tls, &get_tls_static_info_ptr,
+ sizeof(get_tls_static_info_ptr));
+ CHECK_NE(get_tls, 0);
+ size_t tls_size = 0;
+ size_t tls_align = 0;
+ get_tls(&tls_size, &tls_align);
+ g_tls_size = tls_size;
+#endif
+}
+
+uptr GetTlsSize() {
+ return g_tls_size;
+}
+
+#if defined(__x86_64__) || defined(__i386__)
+// sizeof(struct thread) from glibc.
+// There has been a report of this being different on glibc 2.11 and 2.13. We
+// don't know when this change happened, so 2.14 is a conservative estimate.
+#if __GLIBC_PREREQ(2, 14)
+const uptr kThreadDescriptorSize = FIRST_32_SECOND_64(1216, 2304);
+#else
+const uptr kThreadDescriptorSize = FIRST_32_SECOND_64(1168, 2304);
+#endif
+
+uptr ThreadDescriptorSize() {
+ return kThreadDescriptorSize;
+}
+
+// The offset at which pointer to self is located in the thread descriptor.
+const uptr kThreadSelfOffset = FIRST_32_SECOND_64(8, 16);
+
+uptr ThreadSelfOffset() {
+ return kThreadSelfOffset;
+}
+
+uptr ThreadSelf() {
+ uptr descr_addr;
+#ifdef __i386__
+ asm("mov %%gs:%c1,%0" : "=r"(descr_addr) : "i"(kThreadSelfOffset));
+#else
+ asm("mov %%fs:%c1,%0" : "=r"(descr_addr) : "i"(kThreadSelfOffset));
+#endif
+ return descr_addr;
+}
+#endif // defined(__x86_64__) || defined(__i386__)
+
+void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
+ uptr *tls_addr, uptr *tls_size) {
+#ifndef SANITIZER_GO
+#if defined(__x86_64__) || defined(__i386__)
+ *tls_addr = ThreadSelf();
+ *tls_size = GetTlsSize();
+ *tls_addr -= *tls_size;
+ *tls_addr += kThreadDescriptorSize;
+#else
+ *tls_addr = 0;
+ *tls_size = 0;
+#endif
+
+ uptr stack_top, stack_bottom;
+ GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom);
+ *stk_addr = stack_bottom;
+ *stk_size = stack_top - stack_bottom;
+
+ if (!main) {
+ // If stack and tls intersect, make them non-intersecting.
+ if (*tls_addr > *stk_addr && *tls_addr < *stk_addr + *stk_size) {
+ CHECK_GT(*tls_addr + *tls_size, *stk_addr);
+ CHECK_LE(*tls_addr + *tls_size, *stk_addr + *stk_size);
+ *stk_size -= *tls_size;
+ *tls_addr = *stk_addr + *stk_size;
+ }
+ }
+#else // SANITIZER_GO
+ *stk_addr = 0;
+ *stk_size = 0;
+ *tls_addr = 0;
+ *tls_size = 0;
+#endif // SANITIZER_GO
+}
+
+void AdjustStackSizeLinux(void *attr_, int verbosity) {
+ pthread_attr_t *attr = (pthread_attr_t *)attr_;
+ uptr stackaddr = 0;
+ size_t stacksize = 0;
+ pthread_attr_getstack(attr, (void**)&stackaddr, &stacksize);
+ // GLibC will return (0 - stacksize) as the stack address in the case when
+ // stacksize is set, but stackaddr is not.
+ bool stack_set = (stackaddr != 0) && (stackaddr + stacksize != 0);
+ // We place a lot of tool data into TLS, account for that.
+ const uptr minstacksize = GetTlsSize() + 128*1024;
+ if (stacksize < minstacksize) {
+ if (!stack_set) {
+ if (verbosity && stacksize != 0)
+ Printf("Sanitizer: increasing stacksize %zu->%zu\n", stacksize,
+ minstacksize);
+ pthread_attr_setstacksize(attr, minstacksize);
+ } else {
+ Printf("Sanitizer: pre-allocated stack size is insufficient: "
+ "%zu < %zu\n", stacksize, minstacksize);
+ Printf("Sanitizer: pthread_create is likely to fail.\n");
+ }
+ }
+}
+
+#if SANITIZER_ANDROID
+uptr GetListOfModules(LoadedModule *modules, uptr max_modules,
+ string_predicate_t filter) {
+ return 0;
+}
+#else // SANITIZER_ANDROID
+typedef ElfW(Phdr) Elf_Phdr;
+
+struct DlIteratePhdrData {
+ LoadedModule *modules;
+ uptr current_n;
+ bool first;
+ uptr max_n;
+ string_predicate_t filter;
+};
+
+static int dl_iterate_phdr_cb(dl_phdr_info *info, size_t size, void *arg) {
+ DlIteratePhdrData *data = (DlIteratePhdrData*)arg;
+ if (data->current_n == data->max_n)
+ return 0;
+ InternalScopedBuffer<char> module_name(kMaxPathLength);
+ module_name.data()[0] = '\0';
+ if (data->first) {
+ data->first = false;
+ // First module is the binary itself.
+ ReadBinaryName(module_name.data(), module_name.size());
+ } else if (info->dlpi_name) {
+ internal_strncpy(module_name.data(), info->dlpi_name, module_name.size());
+ }
+ if (module_name.data()[0] == '\0')
+ return 0;
+ if (data->filter && !data->filter(module_name.data()))
+ return 0;
+ void *mem = &data->modules[data->current_n];
+ LoadedModule *cur_module = new(mem) LoadedModule(module_name.data(),
+ info->dlpi_addr);
+ data->current_n++;
+ for (int i = 0; i < info->dlpi_phnum; i++) {
+ const Elf_Phdr *phdr = &info->dlpi_phdr[i];
+ if (phdr->p_type == PT_LOAD) {
+ uptr cur_beg = info->dlpi_addr + phdr->p_vaddr;
+ uptr cur_end = cur_beg + phdr->p_memsz;
+ cur_module->addAddressRange(cur_beg, cur_end);
+ }
+ }
+ return 0;
+}
+
+uptr GetListOfModules(LoadedModule *modules, uptr max_modules,
+ string_predicate_t filter) {
+ CHECK(modules);
+ DlIteratePhdrData data = {modules, 0, true, max_modules, filter};
+ dl_iterate_phdr(dl_iterate_phdr_cb, &data);
+ return data.current_n;
+}
+#endif // SANITIZER_ANDROID
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_LINUX
diff --git a/libsanitizer/sanitizer_common/sanitizer_mac.cc b/libsanitizer/sanitizer_common/sanitizer_mac.cc
index d7885bb3509..fa146b5b4e8 100644
--- a/libsanitizer/sanitizer_common/sanitizer_mac.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_mac.cc
@@ -10,7 +10,9 @@
// sanitizer_libc.h.
//===----------------------------------------------------------------------===//
-#ifdef __APPLE__
+#include "sanitizer_platform.h"
+#if SANITIZER_MAC
+
// Use 64-bit inodes in file operations. ASan does not support OS X 10.5, so
// the clients will most certainly use 64-bit ones as well.
#ifndef _DARWIN_USE_64_BIT_INODE
@@ -21,6 +23,7 @@
#include "sanitizer_common.h"
#include "sanitizer_internal_defs.h"
#include "sanitizer_libc.h"
+#include "sanitizer_placement_new.h"
#include "sanitizer_procmaps.h"
#include <crt_externs.h> // for _NSGetEnviron
@@ -35,32 +38,35 @@
#include <sys/types.h>
#include <unistd.h>
#include <libkern/OSAtomic.h>
+#include <errno.h>
namespace __sanitizer {
+#include "sanitizer_syscall_generic.inc"
+
// ---------------------- sanitizer_libc.h
-void *internal_mmap(void *addr, size_t length, int prot, int flags,
- int fd, u64 offset) {
- return mmap(addr, length, prot, flags, fd, offset);
+uptr internal_mmap(void *addr, size_t length, int prot, int flags,
+ int fd, u64 offset) {
+ return (uptr)mmap(addr, length, prot, flags, fd, offset);
}
-int internal_munmap(void *addr, uptr length) {
+uptr internal_munmap(void *addr, uptr length) {
return munmap(addr, length);
}
-int internal_close(fd_t fd) {
+uptr internal_close(fd_t fd) {
return close(fd);
}
-fd_t internal_open(const char *filename, int flags) {
+uptr internal_open(const char *filename, int flags) {
return open(filename, flags);
}
-fd_t internal_open(const char *filename, int flags, u32 mode) {
+uptr internal_open(const char *filename, int flags, u32 mode) {
return open(filename, flags, mode);
}
-fd_t OpenFile(const char *filename, bool write) {
+uptr OpenFile(const char *filename, bool write) {
return internal_open(filename,
write ? O_WRONLY | O_CREAT : O_RDONLY, 0660);
}
@@ -73,15 +79,15 @@ uptr internal_write(fd_t fd, const void *buf, uptr count) {
return write(fd, buf, count);
}
-int internal_stat(const char *path, void *buf) {
+uptr internal_stat(const char *path, void *buf) {
return stat(path, (struct stat *)buf);
}
-int internal_lstat(const char *path, void *buf) {
+uptr internal_lstat(const char *path, void *buf) {
return lstat(path, (struct stat *)buf);
}
-int internal_fstat(fd_t fd, void *buf) {
+uptr internal_fstat(fd_t fd, void *buf) {
return fstat(fd, (struct stat *)buf);
}
@@ -92,7 +98,7 @@ uptr internal_filesize(fd_t fd) {
return (uptr)st.st_size;
}
-int internal_dup2(int oldfd, int newfd) {
+uptr internal_dup2(int oldfd, int newfd) {
return dup2(oldfd, newfd);
}
@@ -100,7 +106,7 @@ uptr internal_readlink(const char *path, char *buf, uptr bufsize) {
return readlink(path, buf, bufsize);
}
-int internal_sched_yield() {
+uptr internal_sched_yield() {
return sched_yield();
}
@@ -108,6 +114,10 @@ void internal__exit(int exitcode) {
_exit(exitcode);
}
+uptr internal_getpid() {
+ return getpid();
+}
+
// ----------------- sanitizer_common.h
bool FileExists(const char *filename) {
struct stat st;
@@ -159,9 +169,13 @@ void PrepareForSandboxing() {
// Nothing here for now.
}
+uptr GetPageSize() {
+ return sysconf(_SC_PAGESIZE);
+}
+
// ----------------- sanitizer_procmaps.h
-MemoryMappingLayout::MemoryMappingLayout() {
+MemoryMappingLayout::MemoryMappingLayout(bool cache_enabled) {
Reset();
}
@@ -214,7 +228,9 @@ void MemoryMappingLayout::LoadFromCache() {
template<u32 kLCSegment, typename SegmentCommand>
bool MemoryMappingLayout::NextSegmentLoad(
uptr *start, uptr *end, uptr *offset,
- char filename[], uptr filename_size) {
+ char filename[], uptr filename_size, uptr *protection) {
+ if (protection)
+ UNIMPLEMENTED();
const char* lc = current_load_cmd_addr_;
current_load_cmd_addr_ += ((const load_command *)lc)->cmdsize;
if (((const load_command *)lc)->cmd == kLCSegment) {
@@ -239,7 +255,8 @@ bool MemoryMappingLayout::NextSegmentLoad(
}
bool MemoryMappingLayout::Next(uptr *start, uptr *end, uptr *offset,
- char filename[], uptr filename_size) {
+ char filename[], uptr filename_size,
+ uptr *protection) {
for (; current_image_ >= 0; current_image_--) {
const mach_header* hdr = _dyld_get_image_header(current_image_);
if (!hdr) continue;
@@ -271,14 +288,14 @@ bool MemoryMappingLayout::Next(uptr *start, uptr *end, uptr *offset,
#ifdef MH_MAGIC_64
case MH_MAGIC_64: {
if (NextSegmentLoad<LC_SEGMENT_64, struct segment_command_64>(
- start, end, offset, filename, filename_size))
+ start, end, offset, filename, filename_size, protection))
return true;
break;
}
#endif
case MH_MAGIC: {
if (NextSegmentLoad<LC_SEGMENT, struct segment_command>(
- start, end, offset, filename, filename_size))
+ start, end, offset, filename, filename_size, protection))
return true;
break;
}
@@ -292,18 +309,24 @@ bool MemoryMappingLayout::Next(uptr *start, uptr *end, uptr *offset,
bool MemoryMappingLayout::GetObjectNameAndOffset(uptr addr, uptr *offset,
char filename[],
- uptr filename_size) {
- return IterateForObjectNameAndOffset(addr, offset, filename, filename_size);
+ uptr filename_size,
+ uptr *protection) {
+ return IterateForObjectNameAndOffset(addr, offset, filename, filename_size,
+ protection);
}
BlockingMutex::BlockingMutex(LinkerInitialized) {
// We assume that OS_SPINLOCK_INIT is zero
}
+BlockingMutex::BlockingMutex() {
+ internal_memset(this, 0, sizeof(*this));
+}
+
void BlockingMutex::Lock() {
CHECK(sizeof(OSSpinLock) <= sizeof(opaque_storage_));
- CHECK(OS_SPINLOCK_INIT == 0);
- CHECK(owner_ != (uptr)pthread_self());
+ CHECK_EQ(OS_SPINLOCK_INIT, 0);
+ CHECK_NE(owner_, (uptr)pthread_self());
OSSpinLockLock((OSSpinLock*)&opaque_storage_);
CHECK(!owner_);
owner_ = (uptr)pthread_self();
@@ -315,6 +338,69 @@ void BlockingMutex::Unlock() {
OSSpinLockUnlock((OSSpinLock*)&opaque_storage_);
}
+void BlockingMutex::CheckLocked() {
+ CHECK_EQ((uptr)pthread_self(), owner_);
+}
+
+u64 NanoTime() {
+ return 0;
+}
+
+uptr GetTlsSize() {
+ return 0;
+}
+
+void InitTlsSize() {
+}
+
+void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
+ uptr *tls_addr, uptr *tls_size) {
+#ifndef SANITIZER_GO
+ uptr stack_top, stack_bottom;
+ GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom);
+ *stk_addr = stack_bottom;
+ *stk_size = stack_top - stack_bottom;
+ *tls_addr = 0;
+ *tls_size = 0;
+#else
+ *stk_addr = 0;
+ *stk_size = 0;
+ *tls_addr = 0;
+ *tls_size = 0;
+#endif
+}
+
+uptr GetListOfModules(LoadedModule *modules, uptr max_modules,
+ string_predicate_t filter) {
+ MemoryMappingLayout memory_mapping(false);
+ memory_mapping.Reset();
+ uptr cur_beg, cur_end, cur_offset;
+ InternalScopedBuffer<char> module_name(kMaxPathLength);
+ uptr n_modules = 0;
+ for (uptr i = 0;
+ n_modules < max_modules &&
+ memory_mapping.Next(&cur_beg, &cur_end, &cur_offset,
+ module_name.data(), module_name.size(), 0);
+ i++) {
+ const char *cur_name = module_name.data();
+ if (cur_name[0] == '\0')
+ continue;
+ if (filter && !filter(cur_name))
+ continue;
+ LoadedModule *cur_module = 0;
+ if (n_modules > 0 &&
+ 0 == internal_strcmp(cur_name, modules[n_modules - 1].full_name())) {
+ cur_module = &modules[n_modules - 1];
+ } else {
+ void *mem = &modules[n_modules];
+ cur_module = new(mem) LoadedModule(cur_name, cur_beg);
+ n_modules++;
+ }
+ cur_module->addAddressRange(cur_beg, cur_end);
+ }
+ return n_modules;
+}
+
} // namespace __sanitizer
-#endif // __APPLE__
+#endif // SANITIZER_MAC
diff --git a/libsanitizer/sanitizer_common/sanitizer_mutex.h b/libsanitizer/sanitizer_common/sanitizer_mutex.h
index 27009118e62..b3501146279 100644
--- a/libsanitizer/sanitizer_common/sanitizer_mutex.h
+++ b/libsanitizer/sanitizer_common/sanitizer_mutex.h
@@ -68,8 +68,10 @@ class SpinMutex : public StaticSpinMutex {
class BlockingMutex {
public:
explicit BlockingMutex(LinkerInitialized);
+ BlockingMutex();
void Lock();
void Unlock();
+ void CheckLocked();
private:
uptr opaque_storage_[10];
uptr owner_; // for debugging
diff --git a/libsanitizer/sanitizer_common/sanitizer_placement_new.h b/libsanitizer/sanitizer_common/sanitizer_placement_new.h
index e32d65702df..310327fd8f0 100644
--- a/libsanitizer/sanitizer_common/sanitizer_placement_new.h
+++ b/libsanitizer/sanitizer_common/sanitizer_placement_new.h
@@ -17,7 +17,7 @@
#include "sanitizer_internal_defs.h"
namespace __sanitizer {
-#if (SANITIZER_WORDSIZE == 64) || defined(__APPLE__)
+#if (SANITIZER_WORDSIZE == 64) || SANITIZER_MAC
typedef uptr operator_new_ptr_type;
#else
typedef u32 operator_new_ptr_type;
diff --git a/libsanitizer/sanitizer_common/sanitizer_platform.h b/libsanitizer/sanitizer_common/sanitizer_platform.h
new file mode 100644
index 00000000000..2270709449b
--- /dev/null
+++ b/libsanitizer/sanitizer_common/sanitizer_platform.h
@@ -0,0 +1,44 @@
+//===-- sanitizer_platform.h ------------------------------------*- C++ -*-===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Common platform macros.
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_PLATFORM_H
+#define SANITIZER_PLATFORM_H
+
+#if !defined(__linux__) && !defined(__APPLE__) && !defined(_WIN32)
+# error "This operating system is not supported"
+#endif
+
+#if defined(__linux__)
+# define SANITIZER_LINUX 1
+#else
+# define SANITIZER_LINUX 0
+#endif
+
+#if defined(__APPLE__)
+# define SANITIZER_MAC 1
+#else
+# define SANITIZER_MAC 0
+#endif
+
+#if defined(_WIN32)
+# define SANITIZER_WINDOWS 1
+#else
+# define SANITIZER_WINDOWS 0
+#endif
+
+#if defined(__ANDROID__) || defined(ANDROID)
+# define SANITIZER_ANDROID 1
+#else
+# define SANITIZER_ANDROID 0
+#endif
+
+#define SANITIZER_POSIX (SANITIZER_LINUX || SANITIZER_MAC)
+
+#endif // SANITIZER_PLATFORM_H
diff --git a/libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h b/libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h
index 9b40c0cc523..e0199482f10 100644
--- a/libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h
+++ b/libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h
@@ -9,38 +9,120 @@
// given library functions on a given platform.
//
//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_PLATFORM_INTERCEPTORS_H
+#define SANITIZER_PLATFORM_INTERCEPTORS_H
#include "sanitizer_internal_defs.h"
-#if !defined(_WIN32)
+#if !SANITIZER_WINDOWS
# define SI_NOT_WINDOWS 1
# include "sanitizer_platform_limits_posix.h"
#else
# define SI_NOT_WINDOWS 0
#endif
-#if defined(__linux__) && !defined(ANDROID)
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
# define SI_LINUX_NOT_ANDROID 1
#else
# define SI_LINUX_NOT_ANDROID 0
#endif
-#if defined(__linux__)
+#if SANITIZER_LINUX
# define SI_LINUX 1
#else
# define SI_LINUX 0
#endif
+#if SANITIZER_MAC
+# define SI_MAC 1
+#else
+# define SI_MAC 0
+#endif
+
+# define SANITIZER_INTERCEPT_STRCMP 1
+# define SANITIZER_INTERCEPT_STRCASECMP SI_NOT_WINDOWS
+
# define SANITIZER_INTERCEPT_READ SI_NOT_WINDOWS
# define SANITIZER_INTERCEPT_PREAD SI_NOT_WINDOWS
# define SANITIZER_INTERCEPT_WRITE SI_NOT_WINDOWS
# define SANITIZER_INTERCEPT_PWRITE SI_NOT_WINDOWS
-# define SANITIZER_INTERCEPT_PREAD64 SI_LINUX_NOT_ANDROID
-# define SANITIZER_INTERCEPT_PWRITE64 SI_LINUX_NOT_ANDROID
-# define SANITIZER_INTERCEPT_PRCTL SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_PREAD64 SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_PWRITE64 SI_LINUX_NOT_ANDROID
+
+#define SANITIZER_INTERCEPT_READV SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_WRITEV SI_NOT_WINDOWS
+
+#define SANITIZER_INTERCEPT_PREADV SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_PWRITEV SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_PREADV64 SI_LINUX_NOT_ANDROID
+#define SANITIZER_INTERCEPT_PWRITEV64 SI_LINUX_NOT_ANDROID
+
+# define SANITIZER_INTERCEPT_PRCTL SI_LINUX
# define SANITIZER_INTERCEPT_LOCALTIME_AND_FRIENDS SI_NOT_WINDOWS
# define SANITIZER_INTERCEPT_SCANF SI_NOT_WINDOWS
# define SANITIZER_INTERCEPT_ISOC99_SCANF SI_LINUX
+
+# define SANITIZER_INTERCEPT_FREXP 1
+# define SANITIZER_INTERCEPT_FREXPF_FREXPL SI_NOT_WINDOWS
+
+# define SANITIZER_INTERCEPT_GETPWNAM_AND_FRIENDS SI_NOT_WINDOWS
+# define SANITIZER_INTERCEPT_GETPWNAM_R_AND_FRIENDS \
+ SI_MAC || SI_LINUX_NOT_ANDROID
+# define SANITIZER_INTERCEPT_CLOCK_GETTIME SI_LINUX
+# define SANITIZER_INTERCEPT_GETITIMER SI_NOT_WINDOWS
+# define SANITIZER_INTERCEPT_TIME SI_NOT_WINDOWS
+# define SANITIZER_INTERCEPT_GLOB SI_LINUX_NOT_ANDROID
+# define SANITIZER_INTERCEPT_WAIT SI_NOT_WINDOWS
+# define SANITIZER_INTERCEPT_INET SI_NOT_WINDOWS
+# define SANITIZER_INTERCEPT_PTHREAD_GETSCHEDPARAM SI_NOT_WINDOWS
+# define SANITIZER_INTERCEPT_GETADDRINFO SI_NOT_WINDOWS
+# define SANITIZER_INTERCEPT_GETNAMEINFO SI_NOT_WINDOWS
+# define SANITIZER_INTERCEPT_GETSOCKNAME SI_NOT_WINDOWS
+# define SANITIZER_INTERCEPT_GETHOSTBYNAME SI_NOT_WINDOWS
+# define SANITIZER_INTERCEPT_GETHOSTBYNAME_R SI_LINUX
+# define SANITIZER_INTERCEPT_GETSOCKOPT SI_NOT_WINDOWS
+# define SANITIZER_INTERCEPT_ACCEPT SI_NOT_WINDOWS
+# define SANITIZER_INTERCEPT_ACCEPT4 SI_LINUX
+# define SANITIZER_INTERCEPT_MODF SI_NOT_WINDOWS
+# define SANITIZER_INTERCEPT_RECVMSG SI_NOT_WINDOWS
+# define SANITIZER_INTERCEPT_GETPEERNAME SI_NOT_WINDOWS
+# define SANITIZER_INTERCEPT_IOCTL SI_NOT_WINDOWS
+# define SANITIZER_INTERCEPT_INET_ATON SI_NOT_WINDOWS
+# define SANITIZER_INTERCEPT_SYSINFO SI_LINUX
+# define SANITIZER_INTERCEPT_READDIR SI_NOT_WINDOWS
+# define SANITIZER_INTERCEPT_READDIR64 SI_LINUX_NOT_ANDROID
+# define SANITIZER_INTERCEPT_PTRACE SI_LINUX_NOT_ANDROID && \
+ (defined(__i386) || defined (__x86_64)) // NOLINT
+# define SANITIZER_INTERCEPT_SETLOCALE SI_NOT_WINDOWS
+# define SANITIZER_INTERCEPT_GETCWD SI_NOT_WINDOWS
+# define SANITIZER_INTERCEPT_GET_CURRENT_DIR_NAME SI_LINUX
+# define SANITIZER_INTERCEPT_STRTOIMAX SI_NOT_WINDOWS
+# define SANITIZER_INTERCEPT_MBSTOWCS SI_NOT_WINDOWS
+# define SANITIZER_INTERCEPT_MBSNRTOWCS SI_MAC || SI_LINUX_NOT_ANDROID
+# define SANITIZER_INTERCEPT_WCSTOMBS SI_NOT_WINDOWS
+# define SANITIZER_INTERCEPT_WCSNRTOMBS SI_MAC || SI_LINUX_NOT_ANDROID
+# define SANITIZER_INTERCEPT_TCGETATTR SI_LINUX
+# define SANITIZER_INTERCEPT_REALPATH SI_NOT_WINDOWS
+# define SANITIZER_INTERCEPT_CANONICALIZE_FILE_NAME SI_LINUX_NOT_ANDROID
+# define SANITIZER_INTERCEPT_CONFSTR SI_MAC || SI_LINUX_NOT_ANDROID
+# define SANITIZER_INTERCEPT_SCHED_GETAFFINITY SI_LINUX_NOT_ANDROID
+# define SANITIZER_INTERCEPT_STRERROR SI_NOT_WINDOWS
+# define SANITIZER_INTERCEPT_STRERROR_R SI_NOT_WINDOWS
+# define SANITIZER_INTERCEPT_SCANDIR SI_LINUX_NOT_ANDROID
+# define SANITIZER_INTERCEPT_SCANDIR64 SI_LINUX_NOT_ANDROID
+# define SANITIZER_INTERCEPT_GETGROUPS SI_NOT_WINDOWS
+# define SANITIZER_INTERCEPT_POLL SI_NOT_WINDOWS
+# define SANITIZER_INTERCEPT_PPOLL SI_LINUX_NOT_ANDROID
+# define SANITIZER_INTERCEPT_WORDEXP SI_MAC || SI_LINUX_NOT_ANDROID
+# define SANITIZER_INTERCEPT_SIGWAIT SI_NOT_WINDOWS
+# define SANITIZER_INTERCEPT_SIGWAITINFO SI_LINUX_NOT_ANDROID
+# define SANITIZER_INTERCEPT_SIGTIMEDWAIT SI_LINUX_NOT_ANDROID
+# define SANITIZER_INTERCEPT_SIGSETOPS SI_NOT_WINDOWS
+# define SANITIZER_INTERCEPT_SIGPENDING SI_NOT_WINDOWS
+# define SANITIZER_INTERCEPT_SIGPROCMASK SI_NOT_WINDOWS
+# define SANITIZER_INTERCEPT_BACKTRACE SI_LINUX_NOT_ANDROID
+
+#endif // #ifndef SANITIZER_PLATFORM_INTERCEPTORS_H
diff --git a/libsanitizer/sanitizer_common/sanitizer_platform_limits_linux.cc b/libsanitizer/sanitizer_common/sanitizer_platform_limits_linux.cc
new file mode 100644
index 00000000000..98702436c4f
--- /dev/null
+++ b/libsanitizer/sanitizer_common/sanitizer_platform_limits_linux.cc
@@ -0,0 +1,45 @@
+//===-- sanitizer_platform_limits_linux.cc --------------------------------===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of Sanitizer common code.
+//
+// Sizes and layouts of linux kernel data structures.
+//===----------------------------------------------------------------------===//
+
+// This is a separate compilation unit for linux headers that conflict with
+// userspace headers.
+// Most "normal" includes go in sanitizer_platform_limits_posix.cc
+
+#include "sanitizer_platform.h"
+#if SANITIZER_LINUX
+
+// This header seems to contain the definitions of _kernel_ stat* structs.
+#include <asm/stat.h>
+#include <linux/aio_abi.h>
+
+#if !SANITIZER_ANDROID
+#include <linux/perf_event.h>
+#endif
+
+namespace __sanitizer {
+ unsigned struct___old_kernel_stat_sz = sizeof(struct __old_kernel_stat);
+ unsigned struct_kernel_stat_sz = sizeof(struct stat);
+ unsigned struct_io_event_sz = sizeof(struct io_event);
+ unsigned struct_iocb_sz = sizeof(struct iocb);
+
+#if !defined(_LP64) && !defined(__x86_64__)
+ unsigned struct_kernel_stat64_sz = sizeof(struct stat64);
+#else
+ unsigned struct_kernel_stat64_sz = 0;
+#endif
+
+#if !SANITIZER_ANDROID
+ unsigned struct_perf_event_attr_sz = sizeof(struct perf_event_attr);
+#endif
+} // namespace __sanitizer
+
+#endif // SANITIZER_LINUX
diff --git a/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cc b/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cc
index c4be1aa42da..b771583d064 100644
--- a/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cc
@@ -10,24 +10,105 @@
// Sizes and layouts of platform-specific POSIX data structures.
//===----------------------------------------------------------------------===//
-#if defined(__linux__) || defined(__APPLE__)
+
+#include "sanitizer_platform.h"
+#if SANITIZER_LINUX || SANITIZER_MAC
#include "sanitizer_internal_defs.h"
#include "sanitizer_platform_limits_posix.h"
+#include <arpa/inet.h>
#include <dirent.h>
-#include <sys/utsname.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/time.h>
+#include <grp.h>
+#include <limits.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/route.h>
+#include <netdb.h>
+#include <poll.h>
+#include <pthread.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stddef.h>
#include <sys/resource.h>
#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/times.h>
+#include <sys/types.h>
+#include <sys/utsname.h>
+#include <termios.h>
#include <time.h>
+#include <wchar.h>
+
+#if SANITIZER_LINUX
+#include <utime.h>
+#include <sys/mount.h>
+#include <sys/ptrace.h>
+#include <sys/sysinfo.h>
+#include <sys/vt.h>
+#include <linux/cdrom.h>
+#include <linux/fd.h>
+#include <linux/fs.h>
+#include <linux/hdreg.h>
+#include <linux/input.h>
+#include <linux/ioctl.h>
+#include <linux/soundcard.h>
+#include <linux/sysctl.h>
+#include <linux/utsname.h>
+#include <linux/posix_types.h>
+#endif
+
+#if !SANITIZER_ANDROID
+#include <sys/ucontext.h>
+#include <wordexp.h>
+#endif
+
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
+#include <glob.h>
+#include <mqueue.h>
+#include <net/if_ppp.h>
+#include <netax25/ax25.h>
+#include <netipx/ipx.h>
+#include <netrom/netrom.h>
+#include <scsi/scsi.h>
+#include <sys/mtio.h>
+#include <sys/kd.h>
+#include <sys/shm.h>
+#include <sys/timex.h>
+#include <sys/user.h>
+#include <sys/ustat.h>
+#include <linux/cyclades.h>
+#include <linux/if_eql.h>
+#include <linux/if_plip.h>
+#include <linux/lp.h>
+#include <linux/mroute.h>
+#include <linux/mroute6.h>
+#include <linux/scc.h>
+#include <linux/serial.h>
+#include <sys/msg.h>
+#endif // SANITIZER_LINUX && !SANITIZER_ANDROID
+
+#if SANITIZER_ANDROID
+#include <linux/kd.h>
+#include <linux/mtio.h>
+#include <linux/ppp_defs.h>
+#include <linux/if_ppp.h>
+#endif
-#if defined(__linux__)
+#if SANITIZER_LINUX
+#include <link.h>
#include <sys/vfs.h>
#include <sys/epoll.h>
-#endif // __linux__
+// #include <asm/stat.h>
+#include <linux/capability.h>
+#endif // SANITIZER_LINUX
+
+#if SANITIZER_MAC
+#include <netinet/ip_mroute.h>
+#include <sys/filio.h>
+#include <sys/sockio.h>
+#endif
namespace __sanitizer {
unsigned struct_utsname_sz = sizeof(struct utsname);
@@ -35,34 +116,768 @@ namespace __sanitizer {
unsigned struct_stat64_sz = sizeof(struct stat64);
unsigned struct_rusage_sz = sizeof(struct rusage);
unsigned struct_tm_sz = sizeof(struct tm);
+ unsigned struct_passwd_sz = sizeof(struct passwd);
+ unsigned struct_group_sz = sizeof(struct group);
+ unsigned siginfo_t_sz = sizeof(siginfo_t);
+ unsigned struct_sigaction_sz = sizeof(struct sigaction);
+ unsigned struct_itimerval_sz = sizeof(struct itimerval);
+ unsigned pthread_t_sz = sizeof(pthread_t);
+ unsigned pid_t_sz = sizeof(pid_t);
+ unsigned timeval_sz = sizeof(timeval);
+ unsigned uid_t_sz = sizeof(uid_t);
+ unsigned mbstate_t_sz = sizeof(mbstate_t);
+ unsigned sigset_t_sz = sizeof(sigset_t);
+ unsigned struct_timezone_sz = sizeof(struct timezone);
+ unsigned struct_tms_sz = sizeof(struct tms);
+ unsigned struct_sigevent_sz = sizeof(struct sigevent);
+ unsigned struct_sched_param_sz = sizeof(struct sched_param);
+
+#if !SANITIZER_ANDROID
+ unsigned ucontext_t_sz = sizeof(ucontext_t);
+#endif // !SANITIZER_ANDROID
-#if defined(__linux__)
+#if SANITIZER_LINUX
unsigned struct_rlimit_sz = sizeof(struct rlimit);
- unsigned struct_dirent_sz = sizeof(struct dirent);
unsigned struct_statfs_sz = sizeof(struct statfs);
unsigned struct_epoll_event_sz = sizeof(struct epoll_event);
-#endif // __linux__
+ unsigned struct_sysinfo_sz = sizeof(struct sysinfo);
+ unsigned struct_timespec_sz = sizeof(struct timespec);
+ unsigned __user_cap_header_struct_sz =
+ sizeof(struct __user_cap_header_struct);
+ unsigned __user_cap_data_struct_sz = sizeof(struct __user_cap_data_struct);
+ unsigned struct_utimbuf_sz = sizeof(struct utimbuf);
+ unsigned struct_new_utsname_sz = sizeof(struct new_utsname);
+ unsigned struct_old_utsname_sz = sizeof(struct old_utsname);
+ unsigned struct_oldold_utsname_sz = sizeof(struct oldold_utsname);
+ unsigned struct_itimerspec_sz = sizeof(struct itimerspec);
+ unsigned struct_ustat_sz = sizeof(struct ustat);
+#endif // SANITIZER_LINUX
-#if defined(__linux__) && !defined(__ANDROID__)
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
unsigned struct_rlimit64_sz = sizeof(struct rlimit64);
unsigned struct_statfs64_sz = sizeof(struct statfs64);
-#endif // __linux__ && !__ANDROID__
+ unsigned struct_timex_sz = sizeof(struct timex);
+ unsigned struct_msqid_ds_sz = sizeof(struct msqid_ds);
+ unsigned struct_shmid_ds_sz = sizeof(struct shmid_ds);
+ unsigned struct_mq_attr_sz = sizeof(struct mq_attr);
+#endif // SANITIZER_LINUX && !SANITIZER_ANDROID
- void* __sanitizer_get_msghdr_iov_iov_base(void* msg, int idx) {
- return ((struct msghdr *)msg)->msg_iov[idx].iov_base;
- }
+ uptr sig_ign = (uptr)SIG_IGN;
+ uptr sig_dfl = (uptr)SIG_DFL;
+ uptr sa_siginfo = (uptr)SA_SIGINFO;
- uptr __sanitizer_get_msghdr_iov_iov_len(void* msg, int idx) {
- return ((struct msghdr *)msg)->msg_iov[idx].iov_len;
- }
+#if SANITIZER_LINUX
+ int e_tabsz = (int)E_TABSZ;
+#endif
- uptr __sanitizer_get_msghdr_iovlen(void* msg) {
- return ((struct msghdr *)msg)->msg_iovlen;
- }
+ int af_inet = (int)AF_INET;
+ int af_inet6 = (int)AF_INET6;
- uptr __sanitizer_get_socklen_t(void* socklen_ptr) {
- return *(socklen_t*)socklen_ptr;
+ uptr __sanitizer_in_addr_sz(int af) {
+ if (af == AF_INET)
+ return sizeof(struct in_addr);
+ else if (af == AF_INET6)
+ return sizeof(struct in6_addr);
+ else
+ return 0;
}
+
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
+ int glob_nomatch = GLOB_NOMATCH;
+ int glob_altdirfunc = GLOB_ALTDIRFUNC;
+#endif
+
+#if SANITIZER_LINUX && !SANITIZER_ANDROID && \
+ (defined(__i386) || defined (__x86_64)) // NOLINT
+ unsigned struct_user_regs_struct_sz = sizeof(struct user_regs_struct);
+ unsigned struct_user_fpregs_struct_sz = sizeof(struct user_fpregs_struct);
+#ifdef __x86_64
+ unsigned struct_user_fpxregs_struct_sz = 0;
+#else
+ unsigned struct_user_fpxregs_struct_sz = sizeof(struct user_fpxregs_struct);
+#endif
+
+ int ptrace_getregs = PTRACE_GETREGS;
+ int ptrace_setregs = PTRACE_SETREGS;
+ int ptrace_getfpregs = PTRACE_GETFPREGS;
+ int ptrace_setfpregs = PTRACE_SETFPREGS;
+ int ptrace_getfpxregs = PTRACE_GETFPXREGS;
+ int ptrace_setfpxregs = PTRACE_SETFPXREGS;
+ int ptrace_getsiginfo = PTRACE_GETSIGINFO;
+ int ptrace_setsiginfo = PTRACE_SETSIGINFO;
+#if defined(PTRACE_GETREGSET) && defined(PTRACE_SETREGSET)
+ int ptrace_getregset = PTRACE_GETREGSET;
+ int ptrace_setregset = PTRACE_SETREGSET;
+#else
+ int ptrace_getregset = -1;
+ int ptrace_setregset = -1;
+#endif
+#endif
+
+ unsigned path_max = PATH_MAX;
+
+ // ioctl arguments
+ unsigned struct_arpreq_sz = sizeof(struct arpreq);
+ unsigned struct_ifreq_sz = sizeof(struct ifreq);
+ unsigned struct_termios_sz = sizeof(struct termios);
+ unsigned struct_winsize_sz = sizeof(struct winsize);
+
+#if SANITIZER_LINUX
+ unsigned struct_cdrom_msf_sz = sizeof(struct cdrom_msf);
+ unsigned struct_cdrom_multisession_sz = sizeof(struct cdrom_multisession);
+ unsigned struct_cdrom_read_audio_sz = sizeof(struct cdrom_read_audio);
+ unsigned struct_cdrom_subchnl_sz = sizeof(struct cdrom_subchnl);
+ unsigned struct_cdrom_ti_sz = sizeof(struct cdrom_ti);
+ unsigned struct_cdrom_tocentry_sz = sizeof(struct cdrom_tocentry);
+ unsigned struct_cdrom_tochdr_sz = sizeof(struct cdrom_tochdr);
+ unsigned struct_cdrom_volctrl_sz = sizeof(struct cdrom_volctrl);
+#if SOUND_VERSION >= 0x040000
+ unsigned struct_copr_buffer_sz = 0;
+ unsigned struct_copr_debug_buf_sz = 0;
+ unsigned struct_copr_msg_sz = 0;
+#else
+ unsigned struct_copr_buffer_sz = sizeof(struct copr_buffer);
+ unsigned struct_copr_debug_buf_sz = sizeof(struct copr_debug_buf);
+ unsigned struct_copr_msg_sz = sizeof(struct copr_msg);
+#endif
+ unsigned struct_ff_effect_sz = sizeof(struct ff_effect);
+ unsigned struct_floppy_drive_params_sz = sizeof(struct floppy_drive_params);
+ unsigned struct_floppy_drive_struct_sz = sizeof(struct floppy_drive_struct);
+ unsigned struct_floppy_fdc_state_sz = sizeof(struct floppy_fdc_state);
+ unsigned struct_floppy_max_errors_sz = sizeof(struct floppy_max_errors);
+ unsigned struct_floppy_raw_cmd_sz = sizeof(struct floppy_raw_cmd);
+ unsigned struct_floppy_struct_sz = sizeof(struct floppy_struct);
+ unsigned struct_floppy_write_errors_sz = sizeof(struct floppy_write_errors);
+ unsigned struct_format_descr_sz = sizeof(struct format_descr);
+ unsigned struct_hd_driveid_sz = sizeof(struct hd_driveid);
+ unsigned struct_hd_geometry_sz = sizeof(struct hd_geometry);
+ unsigned struct_input_absinfo_sz = sizeof(struct input_absinfo);
+ unsigned struct_input_id_sz = sizeof(struct input_id);
+ unsigned struct_midi_info_sz = sizeof(struct midi_info);
+ unsigned struct_mtget_sz = sizeof(struct mtget);
+ unsigned struct_mtop_sz = sizeof(struct mtop);
+ unsigned struct_mtpos_sz = sizeof(struct mtpos);
+ unsigned struct_rtentry_sz = sizeof(struct rtentry);
+ unsigned struct_sbi_instrument_sz = sizeof(struct sbi_instrument);
+ unsigned struct_seq_event_rec_sz = sizeof(struct seq_event_rec);
+ unsigned struct_synth_info_sz = sizeof(struct synth_info);
+ unsigned struct_termio_sz = sizeof(struct termio);
+ unsigned struct_vt_consize_sz = sizeof(struct vt_consize);
+ unsigned struct_vt_mode_sz = sizeof(struct vt_mode);
+ unsigned struct_vt_sizes_sz = sizeof(struct vt_sizes);
+ unsigned struct_vt_stat_sz = sizeof(struct vt_stat);
+#endif
+
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
+ unsigned struct_audio_buf_info_sz = sizeof(struct audio_buf_info);
+ unsigned struct_ax25_parms_struct_sz = sizeof(struct ax25_parms_struct);
+ unsigned struct_cyclades_monitor_sz = sizeof(struct cyclades_monitor);
+#if EV_VERSION > (0x010000)
+ unsigned struct_input_keymap_entry_sz = sizeof(struct input_keymap_entry);
+#else
+ unsigned struct_input_keymap_entry_sz = 0;
+#endif
+ unsigned struct_ipx_config_data_sz = sizeof(struct ipx_config_data);
+ unsigned struct_kbdiacrs_sz = sizeof(struct kbdiacrs);
+ unsigned struct_kbentry_sz = sizeof(struct kbentry);
+ unsigned struct_kbkeycode_sz = sizeof(struct kbkeycode);
+ unsigned struct_kbsentry_sz = sizeof(struct kbsentry);
+ unsigned struct_mtconfiginfo_sz = sizeof(struct mtconfiginfo);
+ unsigned struct_nr_parms_struct_sz = sizeof(struct nr_parms_struct);
+ unsigned struct_ppp_stats_sz = sizeof(struct ppp_stats);
+ unsigned struct_scc_modem_sz = sizeof(struct scc_modem);
+ unsigned struct_scc_stat_sz = sizeof(struct scc_stat);
+ unsigned struct_serial_multiport_struct_sz
+ = sizeof(struct serial_multiport_struct);
+ unsigned struct_serial_struct_sz = sizeof(struct serial_struct);
+ unsigned struct_sockaddr_ax25_sz = sizeof(struct sockaddr_ax25);
+ unsigned struct_unimapdesc_sz = sizeof(struct unimapdesc);
+ unsigned struct_unimapinit_sz = sizeof(struct unimapinit);
+#endif
+
+#if !SANITIZER_ANDROID
+ unsigned struct_sioc_sg_req_sz = sizeof(struct sioc_sg_req);
+ unsigned struct_sioc_vif_req_sz = sizeof(struct sioc_vif_req);
+#endif
+
+ unsigned IOCTL_NOT_PRESENT = 0;
+
+ unsigned IOCTL_FIOASYNC = FIOASYNC;
+ unsigned IOCTL_FIOCLEX = FIOCLEX;
+ unsigned IOCTL_FIOGETOWN = FIOGETOWN;
+ unsigned IOCTL_FIONBIO = FIONBIO;
+ unsigned IOCTL_FIONCLEX = FIONCLEX;
+ unsigned IOCTL_FIOSETOWN = FIOSETOWN;
+ unsigned IOCTL_SIOCADDMULTI = SIOCADDMULTI;
+ unsigned IOCTL_SIOCATMARK = SIOCATMARK;
+ unsigned IOCTL_SIOCDELMULTI = SIOCDELMULTI;
+ unsigned IOCTL_SIOCGIFADDR = SIOCGIFADDR;
+ unsigned IOCTL_SIOCGIFBRDADDR = SIOCGIFBRDADDR;
+ unsigned IOCTL_SIOCGIFCONF = SIOCGIFCONF;
+ unsigned IOCTL_SIOCGIFDSTADDR = SIOCGIFDSTADDR;
+ unsigned IOCTL_SIOCGIFFLAGS = SIOCGIFFLAGS;
+ unsigned IOCTL_SIOCGIFMETRIC = SIOCGIFMETRIC;
+ unsigned IOCTL_SIOCGIFMTU = SIOCGIFMTU;
+ unsigned IOCTL_SIOCGIFNETMASK = SIOCGIFNETMASK;
+ unsigned IOCTL_SIOCGPGRP = SIOCGPGRP;
+ unsigned IOCTL_SIOCSIFADDR = SIOCSIFADDR;
+ unsigned IOCTL_SIOCSIFBRDADDR = SIOCSIFBRDADDR;
+ unsigned IOCTL_SIOCSIFDSTADDR = SIOCSIFDSTADDR;
+ unsigned IOCTL_SIOCSIFFLAGS = SIOCSIFFLAGS;
+ unsigned IOCTL_SIOCSIFMETRIC = SIOCSIFMETRIC;
+ unsigned IOCTL_SIOCSIFMTU = SIOCSIFMTU;
+ unsigned IOCTL_SIOCSIFNETMASK = SIOCSIFNETMASK;
+ unsigned IOCTL_SIOCSPGRP = SIOCSPGRP;
+ unsigned IOCTL_TIOCCONS = TIOCCONS;
+ unsigned IOCTL_TIOCEXCL = TIOCEXCL;
+ unsigned IOCTL_TIOCGETD = TIOCGETD;
+ unsigned IOCTL_TIOCGPGRP = TIOCGPGRP;
+ unsigned IOCTL_TIOCGWINSZ = TIOCGWINSZ;
+ unsigned IOCTL_TIOCMBIC = TIOCMBIC;
+ unsigned IOCTL_TIOCMBIS = TIOCMBIS;
+ unsigned IOCTL_TIOCMGET = TIOCMGET;
+ unsigned IOCTL_TIOCMSET = TIOCMSET;
+ unsigned IOCTL_TIOCNOTTY = TIOCNOTTY;
+ unsigned IOCTL_TIOCNXCL = TIOCNXCL;
+ unsigned IOCTL_TIOCOUTQ = TIOCOUTQ;
+ unsigned IOCTL_TIOCPKT = TIOCPKT;
+ unsigned IOCTL_TIOCSCTTY = TIOCSCTTY;
+ unsigned IOCTL_TIOCSETD = TIOCSETD;
+ unsigned IOCTL_TIOCSPGRP = TIOCSPGRP;
+ unsigned IOCTL_TIOCSTI = TIOCSTI;
+ unsigned IOCTL_TIOCSWINSZ = TIOCSWINSZ;
+#if (SANITIZER_LINUX && !SANITIZER_ANDROID) || SANITIZER_MAC
+ unsigned IOCTL_SIOCGETSGCNT = SIOCGETSGCNT;
+ unsigned IOCTL_SIOCGETVIFCNT = SIOCGETVIFCNT;
+#endif
+#if SANITIZER_LINUX
+ unsigned IOCTL_EVIOCGABS = EVIOCGABS(0);
+ unsigned IOCTL_EVIOCGBIT = EVIOCGBIT(0, 0);
+ unsigned IOCTL_EVIOCGEFFECTS = EVIOCGEFFECTS;
+ unsigned IOCTL_EVIOCGID = EVIOCGID;
+ unsigned IOCTL_EVIOCGKEY = EVIOCGKEY(0);
+ unsigned IOCTL_EVIOCGKEYCODE = EVIOCGKEYCODE;
+ unsigned IOCTL_EVIOCGLED = EVIOCGLED(0);
+ unsigned IOCTL_EVIOCGNAME = EVIOCGNAME(0);
+ unsigned IOCTL_EVIOCGPHYS = EVIOCGPHYS(0);
+ unsigned IOCTL_EVIOCGRAB = EVIOCGRAB;
+ unsigned IOCTL_EVIOCGREP = EVIOCGREP;
+ unsigned IOCTL_EVIOCGSND = EVIOCGSND(0);
+ unsigned IOCTL_EVIOCGSW = EVIOCGSW(0);
+ unsigned IOCTL_EVIOCGUNIQ = EVIOCGUNIQ(0);
+ unsigned IOCTL_EVIOCGVERSION = EVIOCGVERSION;
+ unsigned IOCTL_EVIOCRMFF = EVIOCRMFF;
+ unsigned IOCTL_EVIOCSABS = EVIOCSABS(0);
+ unsigned IOCTL_EVIOCSFF = EVIOCSFF;
+ unsigned IOCTL_EVIOCSKEYCODE = EVIOCSKEYCODE;
+ unsigned IOCTL_EVIOCSREP = EVIOCSREP;
+ unsigned IOCTL_BLKFLSBUF = BLKFLSBUF;
+ unsigned IOCTL_BLKGETSIZE = BLKGETSIZE;
+ unsigned IOCTL_BLKRAGET = BLKRAGET;
+ unsigned IOCTL_BLKRASET = BLKRASET;
+ unsigned IOCTL_BLKROGET = BLKROGET;
+ unsigned IOCTL_BLKROSET = BLKROSET;
+ unsigned IOCTL_BLKRRPART = BLKRRPART;
+ unsigned IOCTL_CDROMAUDIOBUFSIZ = CDROMAUDIOBUFSIZ;
+ unsigned IOCTL_CDROMEJECT = CDROMEJECT;
+ unsigned IOCTL_CDROMEJECT_SW = CDROMEJECT_SW;
+ unsigned IOCTL_CDROMMULTISESSION = CDROMMULTISESSION;
+ unsigned IOCTL_CDROMPAUSE = CDROMPAUSE;
+ unsigned IOCTL_CDROMPLAYMSF = CDROMPLAYMSF;
+ unsigned IOCTL_CDROMPLAYTRKIND = CDROMPLAYTRKIND;
+ unsigned IOCTL_CDROMREADAUDIO = CDROMREADAUDIO;
+ unsigned IOCTL_CDROMREADCOOKED = CDROMREADCOOKED;
+ unsigned IOCTL_CDROMREADMODE1 = CDROMREADMODE1;
+ unsigned IOCTL_CDROMREADMODE2 = CDROMREADMODE2;
+ unsigned IOCTL_CDROMREADRAW = CDROMREADRAW;
+ unsigned IOCTL_CDROMREADTOCENTRY = CDROMREADTOCENTRY;
+ unsigned IOCTL_CDROMREADTOCHDR = CDROMREADTOCHDR;
+ unsigned IOCTL_CDROMRESET = CDROMRESET;
+ unsigned IOCTL_CDROMRESUME = CDROMRESUME;
+ unsigned IOCTL_CDROMSEEK = CDROMSEEK;
+ unsigned IOCTL_CDROMSTART = CDROMSTART;
+ unsigned IOCTL_CDROMSTOP = CDROMSTOP;
+ unsigned IOCTL_CDROMSUBCHNL = CDROMSUBCHNL;
+ unsigned IOCTL_CDROMVOLCTRL = CDROMVOLCTRL;
+ unsigned IOCTL_CDROMVOLREAD = CDROMVOLREAD;
+ unsigned IOCTL_CDROM_GET_UPC = CDROM_GET_UPC;
+ unsigned IOCTL_FDCLRPRM = FDCLRPRM;
+ unsigned IOCTL_FDDEFPRM = FDDEFPRM;
+ unsigned IOCTL_FDFLUSH = FDFLUSH;
+ unsigned IOCTL_FDFMTBEG = FDFMTBEG;
+ unsigned IOCTL_FDFMTEND = FDFMTEND;
+ unsigned IOCTL_FDFMTTRK = FDFMTTRK;
+ unsigned IOCTL_FDGETDRVPRM = FDGETDRVPRM;
+ unsigned IOCTL_FDGETDRVSTAT = FDGETDRVSTAT;
+ unsigned IOCTL_FDGETDRVTYP = FDGETDRVTYP;
+ unsigned IOCTL_FDGETFDCSTAT = FDGETFDCSTAT;
+ unsigned IOCTL_FDGETMAXERRS = FDGETMAXERRS;
+ unsigned IOCTL_FDGETPRM = FDGETPRM;
+ unsigned IOCTL_FDMSGOFF = FDMSGOFF;
+ unsigned IOCTL_FDMSGON = FDMSGON;
+ unsigned IOCTL_FDPOLLDRVSTAT = FDPOLLDRVSTAT;
+ unsigned IOCTL_FDRAWCMD = FDRAWCMD;
+ unsigned IOCTL_FDRESET = FDRESET;
+ unsigned IOCTL_FDSETDRVPRM = FDSETDRVPRM;
+ unsigned IOCTL_FDSETEMSGTRESH = FDSETEMSGTRESH;
+ unsigned IOCTL_FDSETMAXERRS = FDSETMAXERRS;
+ unsigned IOCTL_FDSETPRM = FDSETPRM;
+ unsigned IOCTL_FDTWADDLE = FDTWADDLE;
+ unsigned IOCTL_FDWERRORCLR = FDWERRORCLR;
+ unsigned IOCTL_FDWERRORGET = FDWERRORGET;
+ unsigned IOCTL_HDIO_DRIVE_CMD = HDIO_DRIVE_CMD;
+ unsigned IOCTL_HDIO_GETGEO = HDIO_GETGEO;
+ unsigned IOCTL_HDIO_GET_32BIT = HDIO_GET_32BIT;
+ unsigned IOCTL_HDIO_GET_DMA = HDIO_GET_DMA;
+ unsigned IOCTL_HDIO_GET_IDENTITY = HDIO_GET_IDENTITY;
+ unsigned IOCTL_HDIO_GET_KEEPSETTINGS = HDIO_GET_KEEPSETTINGS;
+ unsigned IOCTL_HDIO_GET_MULTCOUNT = HDIO_GET_MULTCOUNT;
+ unsigned IOCTL_HDIO_GET_NOWERR = HDIO_GET_NOWERR;
+ unsigned IOCTL_HDIO_GET_UNMASKINTR = HDIO_GET_UNMASKINTR;
+ unsigned IOCTL_HDIO_SET_32BIT = HDIO_SET_32BIT;
+ unsigned IOCTL_HDIO_SET_DMA = HDIO_SET_DMA;
+ unsigned IOCTL_HDIO_SET_KEEPSETTINGS = HDIO_SET_KEEPSETTINGS;
+ unsigned IOCTL_HDIO_SET_MULTCOUNT = HDIO_SET_MULTCOUNT;
+ unsigned IOCTL_HDIO_SET_NOWERR = HDIO_SET_NOWERR;
+ unsigned IOCTL_HDIO_SET_UNMASKINTR = HDIO_SET_UNMASKINTR;
+ unsigned IOCTL_MTIOCGET = MTIOCGET;
+ unsigned IOCTL_MTIOCPOS = MTIOCPOS;
+ unsigned IOCTL_MTIOCTOP = MTIOCTOP;
+ unsigned IOCTL_PPPIOCGASYNCMAP = PPPIOCGASYNCMAP;
+ unsigned IOCTL_PPPIOCGDEBUG = PPPIOCGDEBUG;
+ unsigned IOCTL_PPPIOCGFLAGS = PPPIOCGFLAGS;
+ unsigned IOCTL_PPPIOCGUNIT = PPPIOCGUNIT;
+ unsigned IOCTL_PPPIOCGXASYNCMAP = PPPIOCGXASYNCMAP;
+ unsigned IOCTL_PPPIOCSASYNCMAP = PPPIOCSASYNCMAP;
+ unsigned IOCTL_PPPIOCSDEBUG = PPPIOCSDEBUG;
+ unsigned IOCTL_PPPIOCSFLAGS = PPPIOCSFLAGS;
+ unsigned IOCTL_PPPIOCSMAXCID = PPPIOCSMAXCID;
+ unsigned IOCTL_PPPIOCSMRU = PPPIOCSMRU;
+ unsigned IOCTL_PPPIOCSXASYNCMAP = PPPIOCSXASYNCMAP;
+ unsigned IOCTL_SIOCADDRT = SIOCADDRT;
+ unsigned IOCTL_SIOCDARP = SIOCDARP;
+ unsigned IOCTL_SIOCDELRT = SIOCDELRT;
+ unsigned IOCTL_SIOCDRARP = SIOCDRARP;
+ unsigned IOCTL_SIOCGARP = SIOCGARP;
+ unsigned IOCTL_SIOCGIFENCAP = SIOCGIFENCAP;
+ unsigned IOCTL_SIOCGIFHWADDR = SIOCGIFHWADDR;
+ unsigned IOCTL_SIOCGIFMAP = SIOCGIFMAP;
+ unsigned IOCTL_SIOCGIFMEM = SIOCGIFMEM;
+ unsigned IOCTL_SIOCGIFNAME = SIOCGIFNAME;
+ unsigned IOCTL_SIOCGIFSLAVE = SIOCGIFSLAVE;
+ unsigned IOCTL_SIOCGRARP = SIOCGRARP;
+ unsigned IOCTL_SIOCGSTAMP = SIOCGSTAMP;
+ unsigned IOCTL_SIOCSARP = SIOCSARP;
+ unsigned IOCTL_SIOCSIFENCAP = SIOCSIFENCAP;
+ unsigned IOCTL_SIOCSIFHWADDR = SIOCSIFHWADDR;
+ unsigned IOCTL_SIOCSIFLINK = SIOCSIFLINK;
+ unsigned IOCTL_SIOCSIFMAP = SIOCSIFMAP;
+ unsigned IOCTL_SIOCSIFMEM = SIOCSIFMEM;
+ unsigned IOCTL_SIOCSIFSLAVE = SIOCSIFSLAVE;
+ unsigned IOCTL_SIOCSRARP = SIOCSRARP;
+#if SOUND_VERSION >= 0x040000
+ unsigned IOCTL_SNDCTL_COPR_HALT = IOCTL_NOT_PRESENT;
+ unsigned IOCTL_SNDCTL_COPR_LOAD = IOCTL_NOT_PRESENT;
+ unsigned IOCTL_SNDCTL_COPR_RCODE = IOCTL_NOT_PRESENT;
+ unsigned IOCTL_SNDCTL_COPR_RCVMSG = IOCTL_NOT_PRESENT;
+ unsigned IOCTL_SNDCTL_COPR_RDATA = IOCTL_NOT_PRESENT;
+ unsigned IOCTL_SNDCTL_COPR_RESET = IOCTL_NOT_PRESENT;
+ unsigned IOCTL_SNDCTL_COPR_RUN = IOCTL_NOT_PRESENT;
+ unsigned IOCTL_SNDCTL_COPR_SENDMSG = IOCTL_NOT_PRESENT;
+ unsigned IOCTL_SNDCTL_COPR_WCODE = IOCTL_NOT_PRESENT;
+ unsigned IOCTL_SNDCTL_COPR_WDATA = IOCTL_NOT_PRESENT;
+ unsigned IOCTL_SOUND_PCM_READ_BITS = IOCTL_NOT_PRESENT;
+ unsigned IOCTL_SOUND_PCM_READ_CHANNELS = IOCTL_NOT_PRESENT;
+ unsigned IOCTL_SOUND_PCM_READ_FILTER = IOCTL_NOT_PRESENT;
+ unsigned IOCTL_SOUND_PCM_READ_RATE = IOCTL_NOT_PRESENT;
+ unsigned IOCTL_SOUND_PCM_WRITE_CHANNELS = IOCTL_NOT_PRESENT;
+ unsigned IOCTL_SOUND_PCM_WRITE_FILTER = IOCTL_NOT_PRESENT;
+#else
+ unsigned IOCTL_SNDCTL_COPR_HALT = SNDCTL_COPR_HALT;
+ unsigned IOCTL_SNDCTL_COPR_LOAD = SNDCTL_COPR_LOAD;
+ unsigned IOCTL_SNDCTL_COPR_RCODE = SNDCTL_COPR_RCODE;
+ unsigned IOCTL_SNDCTL_COPR_RCVMSG = SNDCTL_COPR_RCVMSG;
+ unsigned IOCTL_SNDCTL_COPR_RDATA = SNDCTL_COPR_RDATA;
+ unsigned IOCTL_SNDCTL_COPR_RESET = SNDCTL_COPR_RESET;
+ unsigned IOCTL_SNDCTL_COPR_RUN = SNDCTL_COPR_RUN;
+ unsigned IOCTL_SNDCTL_COPR_SENDMSG = SNDCTL_COPR_SENDMSG;
+ unsigned IOCTL_SNDCTL_COPR_WCODE = SNDCTL_COPR_WCODE;
+ unsigned IOCTL_SNDCTL_COPR_WDATA = SNDCTL_COPR_WDATA;
+ unsigned IOCTL_SOUND_PCM_READ_BITS = SOUND_PCM_READ_BITS;
+ unsigned IOCTL_SOUND_PCM_READ_CHANNELS = SOUND_PCM_READ_CHANNELS;
+ unsigned IOCTL_SOUND_PCM_READ_FILTER = SOUND_PCM_READ_FILTER;
+ unsigned IOCTL_SOUND_PCM_READ_RATE = SOUND_PCM_READ_RATE;
+ unsigned IOCTL_SOUND_PCM_WRITE_CHANNELS = SOUND_PCM_WRITE_CHANNELS;
+ unsigned IOCTL_SOUND_PCM_WRITE_FILTER = SOUND_PCM_WRITE_FILTER;
+#endif
+ unsigned IOCTL_SNDCTL_DSP_GETBLKSIZE = SNDCTL_DSP_GETBLKSIZE;
+ unsigned IOCTL_SNDCTL_DSP_GETFMTS = SNDCTL_DSP_GETFMTS;
+ unsigned IOCTL_SNDCTL_DSP_NONBLOCK = SNDCTL_DSP_NONBLOCK;
+ unsigned IOCTL_SNDCTL_DSP_POST = SNDCTL_DSP_POST;
+ unsigned IOCTL_SNDCTL_DSP_RESET = SNDCTL_DSP_RESET;
+ unsigned IOCTL_SNDCTL_DSP_SETFMT = SNDCTL_DSP_SETFMT;
+ unsigned IOCTL_SNDCTL_DSP_SETFRAGMENT = SNDCTL_DSP_SETFRAGMENT;
+ unsigned IOCTL_SNDCTL_DSP_SPEED = SNDCTL_DSP_SPEED;
+ unsigned IOCTL_SNDCTL_DSP_STEREO = SNDCTL_DSP_STEREO;
+ unsigned IOCTL_SNDCTL_DSP_SUBDIVIDE = SNDCTL_DSP_SUBDIVIDE;
+ unsigned IOCTL_SNDCTL_DSP_SYNC = SNDCTL_DSP_SYNC;
+ unsigned IOCTL_SNDCTL_FM_4OP_ENABLE = SNDCTL_FM_4OP_ENABLE;
+ unsigned IOCTL_SNDCTL_FM_LOAD_INSTR = SNDCTL_FM_LOAD_INSTR;
+ unsigned IOCTL_SNDCTL_MIDI_INFO = SNDCTL_MIDI_INFO;
+ unsigned IOCTL_SNDCTL_MIDI_PRETIME = SNDCTL_MIDI_PRETIME;
+ unsigned IOCTL_SNDCTL_SEQ_CTRLRATE = SNDCTL_SEQ_CTRLRATE;
+ unsigned IOCTL_SNDCTL_SEQ_GETINCOUNT = SNDCTL_SEQ_GETINCOUNT;
+ unsigned IOCTL_SNDCTL_SEQ_GETOUTCOUNT = SNDCTL_SEQ_GETOUTCOUNT;
+ unsigned IOCTL_SNDCTL_SEQ_NRMIDIS = SNDCTL_SEQ_NRMIDIS;
+ unsigned IOCTL_SNDCTL_SEQ_NRSYNTHS = SNDCTL_SEQ_NRSYNTHS;
+ unsigned IOCTL_SNDCTL_SEQ_OUTOFBAND = SNDCTL_SEQ_OUTOFBAND;
+ unsigned IOCTL_SNDCTL_SEQ_PANIC = SNDCTL_SEQ_PANIC;
+ unsigned IOCTL_SNDCTL_SEQ_PERCMODE = SNDCTL_SEQ_PERCMODE;
+ unsigned IOCTL_SNDCTL_SEQ_RESET = SNDCTL_SEQ_RESET;
+ unsigned IOCTL_SNDCTL_SEQ_RESETSAMPLES = SNDCTL_SEQ_RESETSAMPLES;
+ unsigned IOCTL_SNDCTL_SEQ_SYNC = SNDCTL_SEQ_SYNC;
+ unsigned IOCTL_SNDCTL_SEQ_TESTMIDI = SNDCTL_SEQ_TESTMIDI;
+ unsigned IOCTL_SNDCTL_SEQ_THRESHOLD = SNDCTL_SEQ_THRESHOLD;
+ unsigned IOCTL_SNDCTL_SYNTH_INFO = SNDCTL_SYNTH_INFO;
+ unsigned IOCTL_SNDCTL_SYNTH_MEMAVL = SNDCTL_SYNTH_MEMAVL;
+ unsigned IOCTL_SNDCTL_TMR_CONTINUE = SNDCTL_TMR_CONTINUE;
+ unsigned IOCTL_SNDCTL_TMR_METRONOME = SNDCTL_TMR_METRONOME;
+ unsigned IOCTL_SNDCTL_TMR_SELECT = SNDCTL_TMR_SELECT;
+ unsigned IOCTL_SNDCTL_TMR_SOURCE = SNDCTL_TMR_SOURCE;
+ unsigned IOCTL_SNDCTL_TMR_START = SNDCTL_TMR_START;
+ unsigned IOCTL_SNDCTL_TMR_STOP = SNDCTL_TMR_STOP;
+ unsigned IOCTL_SNDCTL_TMR_TEMPO = SNDCTL_TMR_TEMPO;
+ unsigned IOCTL_SNDCTL_TMR_TIMEBASE = SNDCTL_TMR_TIMEBASE;
+ unsigned IOCTL_SOUND_MIXER_READ_ALTPCM = SOUND_MIXER_READ_ALTPCM;
+ unsigned IOCTL_SOUND_MIXER_READ_BASS = SOUND_MIXER_READ_BASS;
+ unsigned IOCTL_SOUND_MIXER_READ_CAPS = SOUND_MIXER_READ_CAPS;
+ unsigned IOCTL_SOUND_MIXER_READ_CD = SOUND_MIXER_READ_CD;
+ unsigned IOCTL_SOUND_MIXER_READ_DEVMASK = SOUND_MIXER_READ_DEVMASK;
+ unsigned IOCTL_SOUND_MIXER_READ_ENHANCE = SOUND_MIXER_READ_ENHANCE;
+ unsigned IOCTL_SOUND_MIXER_READ_IGAIN = SOUND_MIXER_READ_IGAIN;
+ unsigned IOCTL_SOUND_MIXER_READ_IMIX = SOUND_MIXER_READ_IMIX;
+ unsigned IOCTL_SOUND_MIXER_READ_LINE = SOUND_MIXER_READ_LINE;
+ unsigned IOCTL_SOUND_MIXER_READ_LINE1 = SOUND_MIXER_READ_LINE1;
+ unsigned IOCTL_SOUND_MIXER_READ_LINE2 = SOUND_MIXER_READ_LINE2;
+ unsigned IOCTL_SOUND_MIXER_READ_LINE3 = SOUND_MIXER_READ_LINE3;
+ unsigned IOCTL_SOUND_MIXER_READ_LOUD = SOUND_MIXER_READ_LOUD;
+ unsigned IOCTL_SOUND_MIXER_READ_MIC = SOUND_MIXER_READ_MIC;
+ unsigned IOCTL_SOUND_MIXER_READ_MUTE = SOUND_MIXER_READ_MUTE;
+ unsigned IOCTL_SOUND_MIXER_READ_OGAIN = SOUND_MIXER_READ_OGAIN;
+ unsigned IOCTL_SOUND_MIXER_READ_PCM = SOUND_MIXER_READ_PCM;
+ unsigned IOCTL_SOUND_MIXER_READ_RECLEV = SOUND_MIXER_READ_RECLEV;
+ unsigned IOCTL_SOUND_MIXER_READ_RECMASK = SOUND_MIXER_READ_RECMASK;
+ unsigned IOCTL_SOUND_MIXER_READ_RECSRC = SOUND_MIXER_READ_RECSRC;
+ unsigned IOCTL_SOUND_MIXER_READ_SPEAKER = SOUND_MIXER_READ_SPEAKER;
+ unsigned IOCTL_SOUND_MIXER_READ_STEREODEVS = SOUND_MIXER_READ_STEREODEVS;
+ unsigned IOCTL_SOUND_MIXER_READ_SYNTH = SOUND_MIXER_READ_SYNTH;
+ unsigned IOCTL_SOUND_MIXER_READ_TREBLE = SOUND_MIXER_READ_TREBLE;
+ unsigned IOCTL_SOUND_MIXER_READ_VOLUME = SOUND_MIXER_READ_VOLUME;
+ unsigned IOCTL_SOUND_MIXER_WRITE_ALTPCM = SOUND_MIXER_WRITE_ALTPCM;
+ unsigned IOCTL_SOUND_MIXER_WRITE_BASS = SOUND_MIXER_WRITE_BASS;
+ unsigned IOCTL_SOUND_MIXER_WRITE_CD = SOUND_MIXER_WRITE_CD;
+ unsigned IOCTL_SOUND_MIXER_WRITE_ENHANCE = SOUND_MIXER_WRITE_ENHANCE;
+ unsigned IOCTL_SOUND_MIXER_WRITE_IGAIN = SOUND_MIXER_WRITE_IGAIN;
+ unsigned IOCTL_SOUND_MIXER_WRITE_IMIX = SOUND_MIXER_WRITE_IMIX;
+ unsigned IOCTL_SOUND_MIXER_WRITE_LINE = SOUND_MIXER_WRITE_LINE;
+ unsigned IOCTL_SOUND_MIXER_WRITE_LINE1 = SOUND_MIXER_WRITE_LINE1;
+ unsigned IOCTL_SOUND_MIXER_WRITE_LINE2 = SOUND_MIXER_WRITE_LINE2;
+ unsigned IOCTL_SOUND_MIXER_WRITE_LINE3 = SOUND_MIXER_WRITE_LINE3;
+ unsigned IOCTL_SOUND_MIXER_WRITE_LOUD = SOUND_MIXER_WRITE_LOUD;
+ unsigned IOCTL_SOUND_MIXER_WRITE_MIC = SOUND_MIXER_WRITE_MIC;
+ unsigned IOCTL_SOUND_MIXER_WRITE_MUTE = SOUND_MIXER_WRITE_MUTE;
+ unsigned IOCTL_SOUND_MIXER_WRITE_OGAIN = SOUND_MIXER_WRITE_OGAIN;
+ unsigned IOCTL_SOUND_MIXER_WRITE_PCM = SOUND_MIXER_WRITE_PCM;
+ unsigned IOCTL_SOUND_MIXER_WRITE_RECLEV = SOUND_MIXER_WRITE_RECLEV;
+ unsigned IOCTL_SOUND_MIXER_WRITE_RECSRC = SOUND_MIXER_WRITE_RECSRC;
+ unsigned IOCTL_SOUND_MIXER_WRITE_SPEAKER = SOUND_MIXER_WRITE_SPEAKER;
+ unsigned IOCTL_SOUND_MIXER_WRITE_SYNTH = SOUND_MIXER_WRITE_SYNTH;
+ unsigned IOCTL_SOUND_MIXER_WRITE_TREBLE = SOUND_MIXER_WRITE_TREBLE;
+ unsigned IOCTL_SOUND_MIXER_WRITE_VOLUME = SOUND_MIXER_WRITE_VOLUME;
+ unsigned IOCTL_TCFLSH = TCFLSH;
+ unsigned IOCTL_TCGETA = TCGETA;
+ unsigned IOCTL_TCGETS = TCGETS;
+ unsigned IOCTL_TCSBRK = TCSBRK;
+ unsigned IOCTL_TCSBRKP = TCSBRKP;
+ unsigned IOCTL_TCSETA = TCSETA;
+ unsigned IOCTL_TCSETAF = TCSETAF;
+ unsigned IOCTL_TCSETAW = TCSETAW;
+ unsigned IOCTL_TCSETS = TCSETS;
+ unsigned IOCTL_TCSETSF = TCSETSF;
+ unsigned IOCTL_TCSETSW = TCSETSW;
+ unsigned IOCTL_TCXONC = TCXONC;
+ unsigned IOCTL_TIOCGLCKTRMIOS = TIOCGLCKTRMIOS;
+ unsigned IOCTL_TIOCGSOFTCAR = TIOCGSOFTCAR;
+ unsigned IOCTL_TIOCINQ = TIOCINQ;
+ unsigned IOCTL_TIOCLINUX = TIOCLINUX;
+ unsigned IOCTL_TIOCSERCONFIG = TIOCSERCONFIG;
+ unsigned IOCTL_TIOCSERGETLSR = TIOCSERGETLSR;
+ unsigned IOCTL_TIOCSERGWILD = TIOCSERGWILD;
+ unsigned IOCTL_TIOCSERSWILD = TIOCSERSWILD;
+ unsigned IOCTL_TIOCSLCKTRMIOS = TIOCSLCKTRMIOS;
+ unsigned IOCTL_TIOCSSOFTCAR = TIOCSSOFTCAR;
+ unsigned IOCTL_VT_ACTIVATE = VT_ACTIVATE;
+ unsigned IOCTL_VT_DISALLOCATE = VT_DISALLOCATE;
+ unsigned IOCTL_VT_GETMODE = VT_GETMODE;
+ unsigned IOCTL_VT_GETSTATE = VT_GETSTATE;
+ unsigned IOCTL_VT_OPENQRY = VT_OPENQRY;
+ unsigned IOCTL_VT_RELDISP = VT_RELDISP;
+ unsigned IOCTL_VT_RESIZE = VT_RESIZE;
+ unsigned IOCTL_VT_RESIZEX = VT_RESIZEX;
+ unsigned IOCTL_VT_SENDSIG = VT_SENDSIG;
+ unsigned IOCTL_VT_SETMODE = VT_SETMODE;
+ unsigned IOCTL_VT_WAITACTIVE = VT_WAITACTIVE;
+#endif
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
+ unsigned IOCTL_CYGETDEFTHRESH = CYGETDEFTHRESH;
+ unsigned IOCTL_CYGETDEFTIMEOUT = CYGETDEFTIMEOUT;
+ unsigned IOCTL_CYGETMON = CYGETMON;
+ unsigned IOCTL_CYGETTHRESH = CYGETTHRESH;
+ unsigned IOCTL_CYGETTIMEOUT = CYGETTIMEOUT;
+ unsigned IOCTL_CYSETDEFTHRESH = CYSETDEFTHRESH;
+ unsigned IOCTL_CYSETDEFTIMEOUT = CYSETDEFTIMEOUT;
+ unsigned IOCTL_CYSETTHRESH = CYSETTHRESH;
+ unsigned IOCTL_CYSETTIMEOUT = CYSETTIMEOUT;
+ unsigned IOCTL_EQL_EMANCIPATE = EQL_EMANCIPATE;
+ unsigned IOCTL_EQL_ENSLAVE = EQL_ENSLAVE;
+ unsigned IOCTL_EQL_GETMASTRCFG = EQL_GETMASTRCFG;
+ unsigned IOCTL_EQL_GETSLAVECFG = EQL_GETSLAVECFG;
+ unsigned IOCTL_EQL_SETMASTRCFG = EQL_SETMASTRCFG;
+ unsigned IOCTL_EQL_SETSLAVECFG = EQL_SETSLAVECFG;
+#if EV_VERSION > (0x010000)
+ unsigned IOCTL_EVIOCGKEYCODE_V2 = EVIOCGKEYCODE_V2;
+ unsigned IOCTL_EVIOCGPROP = EVIOCGPROP(0);
+ unsigned IOCTL_EVIOCSKEYCODE_V2 = EVIOCSKEYCODE_V2;
+#else
+ unsigned IOCTL_EVIOCGKEYCODE_V2 = IOCTL_NOT_PRESENT;
+ unsigned IOCTL_EVIOCGPROP = IOCTL_NOT_PRESENT;
+ unsigned IOCTL_EVIOCSKEYCODE_V2 = IOCTL_NOT_PRESENT;
+#endif
+ unsigned IOCTL_FS_IOC_GETFLAGS = FS_IOC_GETFLAGS;
+ unsigned IOCTL_FS_IOC_GETVERSION = FS_IOC_GETVERSION;
+ unsigned IOCTL_FS_IOC_SETFLAGS = FS_IOC_SETFLAGS;
+ unsigned IOCTL_FS_IOC_SETVERSION = FS_IOC_SETVERSION;
+ unsigned IOCTL_GIO_CMAP = GIO_CMAP;
+ unsigned IOCTL_GIO_FONT = GIO_FONT;
+ unsigned IOCTL_GIO_SCRNMAP = GIO_SCRNMAP;
+ unsigned IOCTL_GIO_UNIMAP = GIO_UNIMAP;
+ unsigned IOCTL_GIO_UNISCRNMAP = GIO_UNISCRNMAP;
+ unsigned IOCTL_KDADDIO = KDADDIO;
+ unsigned IOCTL_KDDELIO = KDDELIO;
+ unsigned IOCTL_KDDISABIO = KDDISABIO;
+ unsigned IOCTL_KDENABIO = KDENABIO;
+ unsigned IOCTL_KDGETKEYCODE = KDGETKEYCODE;
+ unsigned IOCTL_KDGETLED = KDGETLED;
+ unsigned IOCTL_KDGETMODE = KDGETMODE;
+ unsigned IOCTL_KDGKBDIACR = KDGKBDIACR;
+ unsigned IOCTL_KDGKBENT = KDGKBENT;
+ unsigned IOCTL_KDGKBLED = KDGKBLED;
+ unsigned IOCTL_KDGKBMETA = KDGKBMETA;
+ unsigned IOCTL_KDGKBMODE = KDGKBMODE;
+ unsigned IOCTL_KDGKBSENT = KDGKBSENT;
+ unsigned IOCTL_KDGKBTYPE = KDGKBTYPE;
+ unsigned IOCTL_KDMAPDISP = KDMAPDISP;
+ unsigned IOCTL_KDMKTONE = KDMKTONE;
+ unsigned IOCTL_KDSETKEYCODE = KDSETKEYCODE;
+ unsigned IOCTL_KDSETLED = KDSETLED;
+ unsigned IOCTL_KDSETMODE = KDSETMODE;
+ unsigned IOCTL_KDSIGACCEPT = KDSIGACCEPT;
+ unsigned IOCTL_KDSKBDIACR = KDSKBDIACR;
+ unsigned IOCTL_KDSKBENT = KDSKBENT;
+ unsigned IOCTL_KDSKBLED = KDSKBLED;
+ unsigned IOCTL_KDSKBMETA = KDSKBMETA;
+ unsigned IOCTL_KDSKBMODE = KDSKBMODE;
+ unsigned IOCTL_KDSKBSENT = KDSKBSENT;
+ unsigned IOCTL_KDUNMAPDISP = KDUNMAPDISP;
+ unsigned IOCTL_KIOCSOUND = KIOCSOUND;
+ unsigned IOCTL_LPABORT = LPABORT;
+ unsigned IOCTL_LPABORTOPEN = LPABORTOPEN;
+ unsigned IOCTL_LPCAREFUL = LPCAREFUL;
+ unsigned IOCTL_LPCHAR = LPCHAR;
+ unsigned IOCTL_LPGETIRQ = LPGETIRQ;
+ unsigned IOCTL_LPGETSTATUS = LPGETSTATUS;
+ unsigned IOCTL_LPRESET = LPRESET;
+ unsigned IOCTL_LPSETIRQ = LPSETIRQ;
+ unsigned IOCTL_LPTIME = LPTIME;
+ unsigned IOCTL_LPWAIT = LPWAIT;
+ unsigned IOCTL_MTIOCGETCONFIG = MTIOCGETCONFIG;
+ unsigned IOCTL_MTIOCSETCONFIG = MTIOCSETCONFIG;
+ unsigned IOCTL_PIO_CMAP = PIO_CMAP;
+ unsigned IOCTL_PIO_FONT = PIO_FONT;
+ unsigned IOCTL_PIO_SCRNMAP = PIO_SCRNMAP;
+ unsigned IOCTL_PIO_UNIMAP = PIO_UNIMAP;
+ unsigned IOCTL_PIO_UNIMAPCLR = PIO_UNIMAPCLR;
+ unsigned IOCTL_PIO_UNISCRNMAP = PIO_UNISCRNMAP;
+ unsigned IOCTL_SCSI_IOCTL_GET_IDLUN = SCSI_IOCTL_GET_IDLUN;
+ unsigned IOCTL_SCSI_IOCTL_PROBE_HOST = SCSI_IOCTL_PROBE_HOST;
+ unsigned IOCTL_SCSI_IOCTL_TAGGED_DISABLE = SCSI_IOCTL_TAGGED_DISABLE;
+ unsigned IOCTL_SCSI_IOCTL_TAGGED_ENABLE = SCSI_IOCTL_TAGGED_ENABLE;
+ unsigned IOCTL_SIOCAIPXITFCRT = SIOCAIPXITFCRT;
+ unsigned IOCTL_SIOCAIPXPRISLT = SIOCAIPXPRISLT;
+ unsigned IOCTL_SIOCAX25ADDUID = SIOCAX25ADDUID;
+ unsigned IOCTL_SIOCAX25DELUID = SIOCAX25DELUID;
+ unsigned IOCTL_SIOCAX25GETPARMS = SIOCAX25GETPARMS;
+ unsigned IOCTL_SIOCAX25GETUID = SIOCAX25GETUID;
+ unsigned IOCTL_SIOCAX25NOUID = SIOCAX25NOUID;
+ unsigned IOCTL_SIOCAX25SETPARMS = SIOCAX25SETPARMS;
+ unsigned IOCTL_SIOCDEVPLIP = SIOCDEVPLIP;
+ unsigned IOCTL_SIOCIPXCFGDATA = SIOCIPXCFGDATA;
+ unsigned IOCTL_SIOCNRDECOBS = SIOCNRDECOBS;
+ unsigned IOCTL_SIOCNRGETPARMS = SIOCNRGETPARMS;
+ unsigned IOCTL_SIOCNRRTCTL = SIOCNRRTCTL;
+ unsigned IOCTL_SIOCNRSETPARMS = SIOCNRSETPARMS;
+ unsigned IOCTL_SNDCTL_DSP_GETISPACE = SNDCTL_DSP_GETISPACE;
+ unsigned IOCTL_SNDCTL_DSP_GETOSPACE = SNDCTL_DSP_GETOSPACE;
+ unsigned IOCTL_TIOCGSERIAL = TIOCGSERIAL;
+ unsigned IOCTL_TIOCSERGETMULTI = TIOCSERGETMULTI;
+ unsigned IOCTL_TIOCSERSETMULTI = TIOCSERSETMULTI;
+ unsigned IOCTL_TIOCSSERIAL = TIOCSSERIAL;
+#endif
} // namespace __sanitizer
-#endif // __linux__ || __APPLE__
+#define CHECK_TYPE_SIZE(TYPE) \
+ COMPILER_CHECK(sizeof(__sanitizer_##TYPE) == sizeof(TYPE))
+
+#define CHECK_SIZE_AND_OFFSET(CLASS, MEMBER) \
+ COMPILER_CHECK(sizeof(((__sanitizer_##CLASS *) NULL)->MEMBER) == \
+ sizeof(((CLASS *) NULL)->MEMBER)); \
+ COMPILER_CHECK(offsetof(__sanitizer_##CLASS, MEMBER) == \
+ offsetof(CLASS, MEMBER))
+
+// For sigaction, which is a function and struct at the same time,
+// and thus requires explicit "struct" in sizeof() expression.
+#define CHECK_STRUCT_SIZE_AND_OFFSET(CLASS, MEMBER) \
+ COMPILER_CHECK(sizeof(((struct __sanitizer_##CLASS *) NULL)->MEMBER) == \
+ sizeof(((struct CLASS *) NULL)->MEMBER)); \
+ COMPILER_CHECK(offsetof(struct __sanitizer_##CLASS, MEMBER) == \
+ offsetof(struct CLASS, MEMBER))
+
+COMPILER_CHECK(sizeof(__sanitizer_pthread_attr_t) >= sizeof(pthread_attr_t));
+
+COMPILER_CHECK(sizeof(socklen_t) == sizeof(unsigned));
+CHECK_TYPE_SIZE(pthread_key_t);
+
+#if SANITIZER_LINUX
+// There are more undocumented fields in dl_phdr_info that we are not interested
+// in.
+COMPILER_CHECK(sizeof(__sanitizer_dl_phdr_info) <= sizeof(dl_phdr_info));
+CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_addr);
+CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_name);
+CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_phdr);
+CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_phnum);
+
+COMPILER_CHECK(IOC_SIZE(0x12345678) == _IOC_SIZE(0x12345678));
+#endif
+
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
+CHECK_TYPE_SIZE(glob_t);
+CHECK_SIZE_AND_OFFSET(glob_t, gl_pathc);
+CHECK_SIZE_AND_OFFSET(glob_t, gl_pathv);
+CHECK_SIZE_AND_OFFSET(glob_t, gl_offs);
+CHECK_SIZE_AND_OFFSET(glob_t, gl_flags);
+CHECK_SIZE_AND_OFFSET(glob_t, gl_closedir);
+CHECK_SIZE_AND_OFFSET(glob_t, gl_readdir);
+CHECK_SIZE_AND_OFFSET(glob_t, gl_opendir);
+CHECK_SIZE_AND_OFFSET(glob_t, gl_lstat);
+CHECK_SIZE_AND_OFFSET(glob_t, gl_stat);
+#endif
+
+CHECK_TYPE_SIZE(addrinfo);
+CHECK_SIZE_AND_OFFSET(addrinfo, ai_flags);
+CHECK_SIZE_AND_OFFSET(addrinfo, ai_family);
+CHECK_SIZE_AND_OFFSET(addrinfo, ai_socktype);
+CHECK_SIZE_AND_OFFSET(addrinfo, ai_protocol);
+CHECK_SIZE_AND_OFFSET(addrinfo, ai_protocol);
+CHECK_SIZE_AND_OFFSET(addrinfo, ai_addrlen);
+CHECK_SIZE_AND_OFFSET(addrinfo, ai_canonname);
+CHECK_SIZE_AND_OFFSET(addrinfo, ai_addr);
+
+CHECK_TYPE_SIZE(hostent);
+CHECK_SIZE_AND_OFFSET(hostent, h_name);
+CHECK_SIZE_AND_OFFSET(hostent, h_aliases);
+CHECK_SIZE_AND_OFFSET(hostent, h_addrtype);
+CHECK_SIZE_AND_OFFSET(hostent, h_length);
+CHECK_SIZE_AND_OFFSET(hostent, h_addr_list);
+
+CHECK_TYPE_SIZE(iovec);
+CHECK_SIZE_AND_OFFSET(iovec, iov_base);
+CHECK_SIZE_AND_OFFSET(iovec, iov_len);
+
+CHECK_TYPE_SIZE(msghdr);
+CHECK_SIZE_AND_OFFSET(msghdr, msg_name);
+CHECK_SIZE_AND_OFFSET(msghdr, msg_namelen);
+CHECK_SIZE_AND_OFFSET(msghdr, msg_iov);
+CHECK_SIZE_AND_OFFSET(msghdr, msg_iovlen);
+CHECK_SIZE_AND_OFFSET(msghdr, msg_control);
+CHECK_SIZE_AND_OFFSET(msghdr, msg_controllen);
+CHECK_SIZE_AND_OFFSET(msghdr, msg_flags);
+
+CHECK_TYPE_SIZE(cmsghdr);
+CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_len);
+CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_level);
+CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_type);
+
+COMPILER_CHECK(sizeof(__sanitizer_dirent) <= sizeof(dirent));
+CHECK_SIZE_AND_OFFSET(dirent, d_ino);
+#if SANITIZER_MAC
+CHECK_SIZE_AND_OFFSET(dirent, d_seekoff);
+#else
+CHECK_SIZE_AND_OFFSET(dirent, d_off);
+#endif
+CHECK_SIZE_AND_OFFSET(dirent, d_reclen);
+
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
+COMPILER_CHECK(sizeof(__sanitizer_dirent64) <= sizeof(dirent64));
+CHECK_SIZE_AND_OFFSET(dirent64, d_ino);
+CHECK_SIZE_AND_OFFSET(dirent64, d_off);
+CHECK_SIZE_AND_OFFSET(dirent64, d_reclen);
+#endif
+
+CHECK_TYPE_SIZE(ifconf);
+CHECK_SIZE_AND_OFFSET(ifconf, ifc_len);
+CHECK_SIZE_AND_OFFSET(ifconf, ifc_ifcu);
+
+CHECK_TYPE_SIZE(pollfd);
+CHECK_SIZE_AND_OFFSET(pollfd, fd);
+CHECK_SIZE_AND_OFFSET(pollfd, events);
+CHECK_SIZE_AND_OFFSET(pollfd, revents);
+
+CHECK_TYPE_SIZE(nfds_t);
+
+CHECK_TYPE_SIZE(sigset_t);
+
+COMPILER_CHECK(sizeof(__sanitizer_sigaction) == sizeof(struct sigaction));
+// Can't write checks for sa_handler and sa_sigaction due to them being
+// preprocessor macros.
+CHECK_STRUCT_SIZE_AND_OFFSET(sigaction, sa_mask);
+CHECK_STRUCT_SIZE_AND_OFFSET(sigaction, sa_flags);
+#if SANITIZER_LINUX
+CHECK_STRUCT_SIZE_AND_OFFSET(sigaction, sa_restorer);
+#endif
+
+#if SANITIZER_LINUX
+CHECK_TYPE_SIZE(__sysctl_args);
+CHECK_SIZE_AND_OFFSET(__sysctl_args, name);
+CHECK_SIZE_AND_OFFSET(__sysctl_args, nlen);
+CHECK_SIZE_AND_OFFSET(__sysctl_args, oldval);
+CHECK_SIZE_AND_OFFSET(__sysctl_args, oldlenp);
+CHECK_SIZE_AND_OFFSET(__sysctl_args, newval);
+CHECK_SIZE_AND_OFFSET(__sysctl_args, newlen);
+
+CHECK_TYPE_SIZE(__kernel_uid_t);
+CHECK_TYPE_SIZE(__kernel_gid_t);
+CHECK_TYPE_SIZE(__kernel_old_uid_t);
+CHECK_TYPE_SIZE(__kernel_old_gid_t);
+CHECK_TYPE_SIZE(__kernel_off_t);
+CHECK_TYPE_SIZE(__kernel_loff_t);
+CHECK_TYPE_SIZE(__kernel_fd_set);
+#endif
+
+#if !SANITIZER_ANDROID
+CHECK_TYPE_SIZE(wordexp_t);
+CHECK_SIZE_AND_OFFSET(wordexp_t, we_wordc);
+CHECK_SIZE_AND_OFFSET(wordexp_t, we_wordv);
+CHECK_SIZE_AND_OFFSET(wordexp_t, we_offs);
+#endif
+
+#endif // SANITIZER_LINUX || SANITIZER_MAC
diff --git a/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h b/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h
index dd53da94be6..67c459caabb 100644
--- a/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h
+++ b/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h
@@ -13,29 +13,800 @@
#ifndef SANITIZER_PLATFORM_LIMITS_POSIX_H
#define SANITIZER_PLATFORM_LIMITS_POSIX_H
+#include "sanitizer_platform.h"
+
namespace __sanitizer {
extern unsigned struct_utsname_sz;
extern unsigned struct_stat_sz;
extern unsigned struct_stat64_sz;
extern unsigned struct_rusage_sz;
extern unsigned struct_tm_sz;
+ extern unsigned struct_passwd_sz;
+ extern unsigned struct_group_sz;
+ extern unsigned siginfo_t_sz;
+ extern unsigned struct_itimerval_sz;
+ extern unsigned pthread_t_sz;
+ extern unsigned pid_t_sz;
+ extern unsigned timeval_sz;
+ extern unsigned uid_t_sz;
+ extern unsigned mbstate_t_sz;
+ extern unsigned struct_timezone_sz;
+ extern unsigned struct_tms_sz;
+ extern unsigned struct_itimerspec_sz;
+ extern unsigned struct_sigevent_sz;
+ extern unsigned struct_sched_param_sz;
+
+#if !SANITIZER_ANDROID
+ extern unsigned ucontext_t_sz;
+#endif // !SANITIZER_ANDROID
+
+#if SANITIZER_LINUX
+ extern unsigned struct___old_kernel_stat_sz;
+ extern unsigned struct_kernel_stat_sz;
+ extern unsigned struct_kernel_stat64_sz;
+ extern unsigned struct_io_event_sz;
+ extern unsigned struct_iocb_sz;
+ extern unsigned struct_utimbuf_sz;
+ extern unsigned struct_new_utsname_sz;
+ extern unsigned struct_old_utsname_sz;
+ extern unsigned struct_oldold_utsname_sz;
+ extern unsigned struct_msqid_ds_sz;
+ extern unsigned struct_shmid_ds_sz;
+ extern unsigned struct_mq_attr_sz;
+ extern unsigned struct_perf_event_attr_sz;
+ extern unsigned struct_timex_sz;
+ extern unsigned struct_ustat_sz;
-#if defined(__linux__)
extern unsigned struct_rlimit_sz;
- extern unsigned struct_dirent_sz;
extern unsigned struct_statfs_sz;
extern unsigned struct_epoll_event_sz;
-#endif // __linux__
+ extern unsigned struct_sysinfo_sz;
+ extern unsigned struct_timespec_sz;
+ extern unsigned __user_cap_header_struct_sz;
+ extern unsigned __user_cap_data_struct_sz;
+ const unsigned old_sigset_t_sz = sizeof(unsigned long);
+ const unsigned struct_kexec_segment_sz = 4 * sizeof(unsigned long);
+
+ struct __sanitizer___sysctl_args {
+ int *name;
+ int nlen;
+ void *oldval;
+ uptr *oldlenp;
+ void *newval;
+ uptr newlen;
+ unsigned long ___unused[4];
+ };
+#endif // SANITIZER_LINUX
-#if defined(__linux__) && !defined(__ANDROID__)
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
extern unsigned struct_rlimit64_sz;
extern unsigned struct_statfs64_sz;
-#endif // __linux__ && !__ANDROID__
+#endif // SANITIZER_LINUX && !SANITIZER_ANDROID
+
+ struct __sanitizer_iovec {
+ void *iov_base;
+ uptr iov_len;
+ };
+
+#if SANITIZER_MAC
+ typedef unsigned long __sanitizer_pthread_key_t;
+#else
+ typedef unsigned __sanitizer_pthread_key_t;
+#endif
+
+#if SANITIZER_ANDROID || SANITIZER_MAC
+ struct __sanitizer_msghdr {
+ void *msg_name;
+ unsigned msg_namelen;
+ struct __sanitizer_iovec *msg_iov;
+ unsigned msg_iovlen;
+ void *msg_control;
+ unsigned msg_controllen;
+ int msg_flags;
+ };
+ struct __sanitizer_cmsghdr {
+ unsigned cmsg_len;
+ int cmsg_level;
+ int cmsg_type;
+ };
+#else
+ struct __sanitizer_msghdr {
+ void *msg_name;
+ unsigned msg_namelen;
+ struct __sanitizer_iovec *msg_iov;
+ uptr msg_iovlen;
+ void *msg_control;
+ uptr msg_controllen;
+ int msg_flags;
+ };
+ struct __sanitizer_cmsghdr {
+ uptr cmsg_len;
+ int cmsg_level;
+ int cmsg_type;
+ };
+#endif
+
+#if SANITIZER_MAC
+ struct __sanitizer_dirent {
+ unsigned long long d_ino;
+ unsigned long long d_seekoff;
+ unsigned short d_reclen;
+ // more fields that we don't care about
+ };
+#elif SANITIZER_ANDROID || defined(__x86_64__)
+ struct __sanitizer_dirent {
+ unsigned long long d_ino;
+ unsigned long long d_off;
+ unsigned short d_reclen;
+ // more fields that we don't care about
+ };
+#else
+ struct __sanitizer_dirent {
+ uptr d_ino;
+ uptr d_off;
+ unsigned short d_reclen;
+ // more fields that we don't care about
+ };
+#endif
+
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
+ struct __sanitizer_dirent64 {
+ unsigned long long d_ino;
+ unsigned long long d_off;
+ unsigned short d_reclen;
+ // more fields that we don't care about
+ };
+#endif
+
+#if SANITIZER_LINUX
+#if defined(_LP64) || defined(__x86_64__)
+ typedef unsigned __sanitizer___kernel_uid_t;
+ typedef unsigned __sanitizer___kernel_gid_t;
+ typedef long long __sanitizer___kernel_off_t;
+#else
+ typedef unsigned short __sanitizer___kernel_uid_t;
+ typedef unsigned short __sanitizer___kernel_gid_t;
+ typedef long __sanitizer___kernel_off_t;
+#endif
+ typedef unsigned short __sanitizer___kernel_old_uid_t;
+ typedef unsigned short __sanitizer___kernel_old_gid_t;
+ typedef long long __sanitizer___kernel_loff_t;
+ typedef struct {
+ unsigned long fds_bits[1024 / (8 * sizeof(long))];
+ } __sanitizer___kernel_fd_set;
+#endif
+
+ // This thing depends on the platform. We are only interested in the upper
+ // limit. Verified with a compiler assert in .cc.
+ const int pthread_attr_t_max_sz = 128;
+ union __sanitizer_pthread_attr_t {
+ char size[pthread_attr_t_max_sz]; // NOLINT
+ void *align;
+ };
+
+#if SANITIZER_ANDROID
+ typedef unsigned long __sanitizer_sigset_t;
+#elif SANITIZER_MAC
+ typedef unsigned __sanitizer_sigset_t;
+#elif SANITIZER_LINUX
+ struct __sanitizer_sigset_t {
+ // The size is determined by looking at sizeof of real sigset_t on linux.
+ uptr val[128 / sizeof(uptr)];
+ };
+#endif
+
+ struct __sanitizer_sigaction {
+ union {
+ void (*sa_handler)(int sig);
+ void (*sa_sigaction)(int sig, void *siginfo, void *uctx);
+ };
+ __sanitizer_sigset_t sa_mask;
+ int sa_flags;
+#if SANITIZER_LINUX
+ void (*sa_restorer)();
+#endif
+ };
+
+ extern uptr sig_ign;
+ extern uptr sig_dfl;
+ extern uptr sa_siginfo;
+
+#if SANITIZER_LINUX
+ extern int e_tabsz;
+#endif
+
+ extern int af_inet;
+ extern int af_inet6;
+ uptr __sanitizer_in_addr_sz(int af);
+
+#if SANITIZER_LINUX
+ struct __sanitizer_dl_phdr_info {
+ uptr dlpi_addr;
+ const char *dlpi_name;
+ const void *dlpi_phdr;
+ short dlpi_phnum;
+ };
+#endif
+
+ struct __sanitizer_addrinfo {
+ int ai_flags;
+ int ai_family;
+ int ai_socktype;
+ int ai_protocol;
+#if SANITIZER_ANDROID || SANITIZER_MAC
+ unsigned ai_addrlen;
+ char *ai_canonname;
+ void *ai_addr;
+#else // LINUX
+ unsigned ai_addrlen;
+ void *ai_addr;
+ char *ai_canonname;
+#endif
+ struct __sanitizer_addrinfo *ai_next;
+ };
- void* __sanitizer_get_msghdr_iov_iov_base(void* msg, int idx);
- uptr __sanitizer_get_msghdr_iov_iov_len(void* msg, int idx);
- uptr __sanitizer_get_msghdr_iovlen(void* msg);
- uptr __sanitizer_get_socklen_t(void* socklen_ptr);
+ struct __sanitizer_hostent {
+ char *h_name;
+ char **h_aliases;
+ int h_addrtype;
+ int h_length;
+ char **h_addr_list;
+ };
+
+ struct __sanitizer_pollfd {
+ int fd;
+ short events;
+ short revents;
+ };
+
+#if SANITIZER_ANDROID || SANITIZER_MAC
+ typedef unsigned __sanitizer_nfds_t;
+#else
+ typedef unsigned long __sanitizer_nfds_t;
+#endif
+
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
+ struct __sanitizer_glob_t {
+ uptr gl_pathc;
+ char **gl_pathv;
+ uptr gl_offs;
+ int gl_flags;
+
+ void (*gl_closedir)(void *dirp);
+ void *(*gl_readdir)(void *dirp);
+ void *(*gl_opendir)(const char *);
+ int (*gl_lstat)(const char *, void *);
+ int (*gl_stat)(const char *, void *);
+ };
+
+ extern int glob_nomatch;
+ extern int glob_altdirfunc;
+#endif
+
+ extern unsigned path_max;
+
+ struct __sanitizer_wordexp_t {
+ uptr we_wordc;
+ char **we_wordv;
+ uptr we_offs;
+ };
+
+#if SANITIZER_LINUX && !SANITIZER_ANDROID && \
+ (defined(__i386) || defined (__x86_64)) // NOLINT
+ extern unsigned struct_user_regs_struct_sz;
+ extern unsigned struct_user_fpregs_struct_sz;
+ extern unsigned struct_user_fpxregs_struct_sz;
+
+ extern int ptrace_getregs;
+ extern int ptrace_setregs;
+ extern int ptrace_getfpregs;
+ extern int ptrace_setfpregs;
+ extern int ptrace_getfpxregs;
+ extern int ptrace_setfpxregs;
+ extern int ptrace_getsiginfo;
+ extern int ptrace_setsiginfo;
+ extern int ptrace_getregset;
+ extern int ptrace_setregset;
+#endif
+
+ // ioctl arguments
+ struct __sanitizer_ifconf {
+ int ifc_len;
+ union {
+ void *ifcu_req;
+ } ifc_ifcu;
+#if SANITIZER_MAC
+ } __attribute__((packed));
+#else
+ };
+#endif
+
+#define IOC_SIZE(nr) (((nr) >> 16) & 0x3fff)
+
+ extern unsigned struct_arpreq_sz;
+ extern unsigned struct_ifreq_sz;
+ extern unsigned struct_termios_sz;
+ extern unsigned struct_winsize_sz;
+
+#if SANITIZER_LINUX
+ extern unsigned struct_cdrom_msf_sz;
+ extern unsigned struct_cdrom_multisession_sz;
+ extern unsigned struct_cdrom_read_audio_sz;
+ extern unsigned struct_cdrom_subchnl_sz;
+ extern unsigned struct_cdrom_ti_sz;
+ extern unsigned struct_cdrom_tocentry_sz;
+ extern unsigned struct_cdrom_tochdr_sz;
+ extern unsigned struct_cdrom_volctrl_sz;
+ extern unsigned struct_copr_buffer_sz;
+ extern unsigned struct_copr_debug_buf_sz;
+ extern unsigned struct_copr_msg_sz;
+ extern unsigned struct_ff_effect_sz;
+ extern unsigned struct_floppy_drive_params_sz;
+ extern unsigned struct_floppy_drive_struct_sz;
+ extern unsigned struct_floppy_fdc_state_sz;
+ extern unsigned struct_floppy_max_errors_sz;
+ extern unsigned struct_floppy_raw_cmd_sz;
+ extern unsigned struct_floppy_struct_sz;
+ extern unsigned struct_floppy_write_errors_sz;
+ extern unsigned struct_format_descr_sz;
+ extern unsigned struct_hd_driveid_sz;
+ extern unsigned struct_hd_geometry_sz;
+ extern unsigned struct_input_absinfo_sz;
+ extern unsigned struct_input_id_sz;
+ extern unsigned struct_midi_info_sz;
+ extern unsigned struct_mtget_sz;
+ extern unsigned struct_mtop_sz;
+ extern unsigned struct_mtpos_sz;
+ extern unsigned struct_rtentry_sz;
+ extern unsigned struct_sbi_instrument_sz;
+ extern unsigned struct_seq_event_rec_sz;
+ extern unsigned struct_synth_info_sz;
+ extern unsigned struct_termio_sz;
+ extern unsigned struct_vt_consize_sz;
+ extern unsigned struct_vt_mode_sz;
+ extern unsigned struct_vt_sizes_sz;
+ extern unsigned struct_vt_stat_sz;
+#endif
+
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
+ extern unsigned struct_audio_buf_info_sz;
+ extern unsigned struct_ax25_parms_struct_sz;
+ extern unsigned struct_cyclades_monitor_sz;
+ extern unsigned struct_input_keymap_entry_sz;
+ extern unsigned struct_ipx_config_data_sz;
+ extern unsigned struct_kbdiacrs_sz;
+ extern unsigned struct_kbentry_sz;
+ extern unsigned struct_kbkeycode_sz;
+ extern unsigned struct_kbsentry_sz;
+ extern unsigned struct_mtconfiginfo_sz;
+ extern unsigned struct_nr_parms_struct_sz;
+ extern unsigned struct_ppp_stats_sz;
+ extern unsigned struct_scc_modem_sz;
+ extern unsigned struct_scc_stat_sz;
+ extern unsigned struct_serial_multiport_struct_sz;
+ extern unsigned struct_serial_struct_sz;
+ extern unsigned struct_sockaddr_ax25_sz;
+ extern unsigned struct_unimapdesc_sz;
+ extern unsigned struct_unimapinit_sz;
+#endif
+
+#if !SANITIZER_ANDROID
+ extern unsigned struct_sioc_sg_req_sz;
+ extern unsigned struct_sioc_vif_req_sz;
+#endif
+
+ // ioctl request identifiers
+
+ // A special value to mark ioctls that are not present on the target platform,
+ // when it can not be determined without including any system headers.
+ extern unsigned IOCTL_NOT_PRESENT;
+
+ extern unsigned IOCTL_FIOASYNC;
+ extern unsigned IOCTL_FIOCLEX;
+ extern unsigned IOCTL_FIOGETOWN;
+ extern unsigned IOCTL_FIONBIO;
+ extern unsigned IOCTL_FIONCLEX;
+ extern unsigned IOCTL_FIOSETOWN;
+ extern unsigned IOCTL_SIOCADDMULTI;
+ extern unsigned IOCTL_SIOCATMARK;
+ extern unsigned IOCTL_SIOCDELMULTI;
+ extern unsigned IOCTL_SIOCGIFADDR;
+ extern unsigned IOCTL_SIOCGIFBRDADDR;
+ extern unsigned IOCTL_SIOCGIFCONF;
+ extern unsigned IOCTL_SIOCGIFDSTADDR;
+ extern unsigned IOCTL_SIOCGIFFLAGS;
+ extern unsigned IOCTL_SIOCGIFMETRIC;
+ extern unsigned IOCTL_SIOCGIFMTU;
+ extern unsigned IOCTL_SIOCGIFNETMASK;
+ extern unsigned IOCTL_SIOCGPGRP;
+ extern unsigned IOCTL_SIOCSIFADDR;
+ extern unsigned IOCTL_SIOCSIFBRDADDR;
+ extern unsigned IOCTL_SIOCSIFDSTADDR;
+ extern unsigned IOCTL_SIOCSIFFLAGS;
+ extern unsigned IOCTL_SIOCSIFMETRIC;
+ extern unsigned IOCTL_SIOCSIFMTU;
+ extern unsigned IOCTL_SIOCSIFNETMASK;
+ extern unsigned IOCTL_SIOCSPGRP;
+ extern unsigned IOCTL_TIOCCONS;
+ extern unsigned IOCTL_TIOCEXCL;
+ extern unsigned IOCTL_TIOCGETD;
+ extern unsigned IOCTL_TIOCGPGRP;
+ extern unsigned IOCTL_TIOCGWINSZ;
+ extern unsigned IOCTL_TIOCMBIC;
+ extern unsigned IOCTL_TIOCMBIS;
+ extern unsigned IOCTL_TIOCMGET;
+ extern unsigned IOCTL_TIOCMSET;
+ extern unsigned IOCTL_TIOCNOTTY;
+ extern unsigned IOCTL_TIOCNXCL;
+ extern unsigned IOCTL_TIOCOUTQ;
+ extern unsigned IOCTL_TIOCPKT;
+ extern unsigned IOCTL_TIOCSCTTY;
+ extern unsigned IOCTL_TIOCSETD;
+ extern unsigned IOCTL_TIOCSPGRP;
+ extern unsigned IOCTL_TIOCSTI;
+ extern unsigned IOCTL_TIOCSWINSZ;
+#if (SANITIZER_LINUX && !SANITIZER_ANDROID) || SANITIZER_MAC
+ extern unsigned IOCTL_SIOCGETSGCNT;
+ extern unsigned IOCTL_SIOCGETVIFCNT;
+#endif
+#if SANITIZER_LINUX
+ extern unsigned IOCTL_EVIOCGABS;
+ extern unsigned IOCTL_EVIOCGBIT;
+ extern unsigned IOCTL_EVIOCGEFFECTS;
+ extern unsigned IOCTL_EVIOCGID;
+ extern unsigned IOCTL_EVIOCGKEY;
+ extern unsigned IOCTL_EVIOCGKEYCODE;
+ extern unsigned IOCTL_EVIOCGLED;
+ extern unsigned IOCTL_EVIOCGNAME;
+ extern unsigned IOCTL_EVIOCGPHYS;
+ extern unsigned IOCTL_EVIOCGRAB;
+ extern unsigned IOCTL_EVIOCGREP;
+ extern unsigned IOCTL_EVIOCGSND;
+ extern unsigned IOCTL_EVIOCGSW;
+ extern unsigned IOCTL_EVIOCGUNIQ;
+ extern unsigned IOCTL_EVIOCGVERSION;
+ extern unsigned IOCTL_EVIOCRMFF;
+ extern unsigned IOCTL_EVIOCSABS;
+ extern unsigned IOCTL_EVIOCSFF;
+ extern unsigned IOCTL_EVIOCSKEYCODE;
+ extern unsigned IOCTL_EVIOCSREP;
+ extern unsigned IOCTL_BLKFLSBUF;
+ extern unsigned IOCTL_BLKGETSIZE;
+ extern unsigned IOCTL_BLKRAGET;
+ extern unsigned IOCTL_BLKRASET;
+ extern unsigned IOCTL_BLKROGET;
+ extern unsigned IOCTL_BLKROSET;
+ extern unsigned IOCTL_BLKRRPART;
+ extern unsigned IOCTL_CDROMAUDIOBUFSIZ;
+ extern unsigned IOCTL_CDROMEJECT;
+ extern unsigned IOCTL_CDROMEJECT_SW;
+ extern unsigned IOCTL_CDROMMULTISESSION;
+ extern unsigned IOCTL_CDROMPAUSE;
+ extern unsigned IOCTL_CDROMPLAYMSF;
+ extern unsigned IOCTL_CDROMPLAYTRKIND;
+ extern unsigned IOCTL_CDROMREADAUDIO;
+ extern unsigned IOCTL_CDROMREADCOOKED;
+ extern unsigned IOCTL_CDROMREADMODE1;
+ extern unsigned IOCTL_CDROMREADMODE2;
+ extern unsigned IOCTL_CDROMREADRAW;
+ extern unsigned IOCTL_CDROMREADTOCENTRY;
+ extern unsigned IOCTL_CDROMREADTOCHDR;
+ extern unsigned IOCTL_CDROMRESET;
+ extern unsigned IOCTL_CDROMRESUME;
+ extern unsigned IOCTL_CDROMSEEK;
+ extern unsigned IOCTL_CDROMSTART;
+ extern unsigned IOCTL_CDROMSTOP;
+ extern unsigned IOCTL_CDROMSUBCHNL;
+ extern unsigned IOCTL_CDROMVOLCTRL;
+ extern unsigned IOCTL_CDROMVOLREAD;
+ extern unsigned IOCTL_CDROM_GET_UPC;
+ extern unsigned IOCTL_FDCLRPRM;
+ extern unsigned IOCTL_FDDEFPRM;
+ extern unsigned IOCTL_FDFLUSH;
+ extern unsigned IOCTL_FDFMTBEG;
+ extern unsigned IOCTL_FDFMTEND;
+ extern unsigned IOCTL_FDFMTTRK;
+ extern unsigned IOCTL_FDGETDRVPRM;
+ extern unsigned IOCTL_FDGETDRVSTAT;
+ extern unsigned IOCTL_FDGETDRVTYP;
+ extern unsigned IOCTL_FDGETFDCSTAT;
+ extern unsigned IOCTL_FDGETMAXERRS;
+ extern unsigned IOCTL_FDGETPRM;
+ extern unsigned IOCTL_FDMSGOFF;
+ extern unsigned IOCTL_FDMSGON;
+ extern unsigned IOCTL_FDPOLLDRVSTAT;
+ extern unsigned IOCTL_FDRAWCMD;
+ extern unsigned IOCTL_FDRESET;
+ extern unsigned IOCTL_FDSETDRVPRM;
+ extern unsigned IOCTL_FDSETEMSGTRESH;
+ extern unsigned IOCTL_FDSETMAXERRS;
+ extern unsigned IOCTL_FDSETPRM;
+ extern unsigned IOCTL_FDTWADDLE;
+ extern unsigned IOCTL_FDWERRORCLR;
+ extern unsigned IOCTL_FDWERRORGET;
+ extern unsigned IOCTL_HDIO_DRIVE_CMD;
+ extern unsigned IOCTL_HDIO_GETGEO;
+ extern unsigned IOCTL_HDIO_GET_32BIT;
+ extern unsigned IOCTL_HDIO_GET_DMA;
+ extern unsigned IOCTL_HDIO_GET_IDENTITY;
+ extern unsigned IOCTL_HDIO_GET_KEEPSETTINGS;
+ extern unsigned IOCTL_HDIO_GET_MULTCOUNT;
+ extern unsigned IOCTL_HDIO_GET_NOWERR;
+ extern unsigned IOCTL_HDIO_GET_UNMASKINTR;
+ extern unsigned IOCTL_HDIO_SET_32BIT;
+ extern unsigned IOCTL_HDIO_SET_DMA;
+ extern unsigned IOCTL_HDIO_SET_KEEPSETTINGS;
+ extern unsigned IOCTL_HDIO_SET_MULTCOUNT;
+ extern unsigned IOCTL_HDIO_SET_NOWERR;
+ extern unsigned IOCTL_HDIO_SET_UNMASKINTR;
+ extern unsigned IOCTL_MTIOCGET;
+ extern unsigned IOCTL_MTIOCPOS;
+ extern unsigned IOCTL_MTIOCTOP;
+ extern unsigned IOCTL_PPPIOCGASYNCMAP;
+ extern unsigned IOCTL_PPPIOCGDEBUG;
+ extern unsigned IOCTL_PPPIOCGFLAGS;
+ extern unsigned IOCTL_PPPIOCGUNIT;
+ extern unsigned IOCTL_PPPIOCGXASYNCMAP;
+ extern unsigned IOCTL_PPPIOCSASYNCMAP;
+ extern unsigned IOCTL_PPPIOCSDEBUG;
+ extern unsigned IOCTL_PPPIOCSFLAGS;
+ extern unsigned IOCTL_PPPIOCSMAXCID;
+ extern unsigned IOCTL_PPPIOCSMRU;
+ extern unsigned IOCTL_PPPIOCSXASYNCMAP;
+ extern unsigned IOCTL_SIOCADDRT;
+ extern unsigned IOCTL_SIOCDARP;
+ extern unsigned IOCTL_SIOCDELRT;
+ extern unsigned IOCTL_SIOCDRARP;
+ extern unsigned IOCTL_SIOCGARP;
+ extern unsigned IOCTL_SIOCGIFENCAP;
+ extern unsigned IOCTL_SIOCGIFHWADDR;
+ extern unsigned IOCTL_SIOCGIFMAP;
+ extern unsigned IOCTL_SIOCGIFMEM;
+ extern unsigned IOCTL_SIOCGIFNAME;
+ extern unsigned IOCTL_SIOCGIFSLAVE;
+ extern unsigned IOCTL_SIOCGRARP;
+ extern unsigned IOCTL_SIOCGSTAMP;
+ extern unsigned IOCTL_SIOCSARP;
+ extern unsigned IOCTL_SIOCSIFENCAP;
+ extern unsigned IOCTL_SIOCSIFHWADDR;
+ extern unsigned IOCTL_SIOCSIFLINK;
+ extern unsigned IOCTL_SIOCSIFMAP;
+ extern unsigned IOCTL_SIOCSIFMEM;
+ extern unsigned IOCTL_SIOCSIFSLAVE;
+ extern unsigned IOCTL_SIOCSRARP;
+ extern unsigned IOCTL_SNDCTL_COPR_HALT;
+ extern unsigned IOCTL_SNDCTL_COPR_LOAD;
+ extern unsigned IOCTL_SNDCTL_COPR_RCODE;
+ extern unsigned IOCTL_SNDCTL_COPR_RCVMSG;
+ extern unsigned IOCTL_SNDCTL_COPR_RDATA;
+ extern unsigned IOCTL_SNDCTL_COPR_RESET;
+ extern unsigned IOCTL_SNDCTL_COPR_RUN;
+ extern unsigned IOCTL_SNDCTL_COPR_SENDMSG;
+ extern unsigned IOCTL_SNDCTL_COPR_WCODE;
+ extern unsigned IOCTL_SNDCTL_COPR_WDATA;
+ extern unsigned IOCTL_SNDCTL_DSP_GETBLKSIZE;
+ extern unsigned IOCTL_SNDCTL_DSP_GETFMTS;
+ extern unsigned IOCTL_SNDCTL_DSP_NONBLOCK;
+ extern unsigned IOCTL_SNDCTL_DSP_POST;
+ extern unsigned IOCTL_SNDCTL_DSP_RESET;
+ extern unsigned IOCTL_SNDCTL_DSP_SETFMT;
+ extern unsigned IOCTL_SNDCTL_DSP_SETFRAGMENT;
+ extern unsigned IOCTL_SNDCTL_DSP_SPEED;
+ extern unsigned IOCTL_SNDCTL_DSP_STEREO;
+ extern unsigned IOCTL_SNDCTL_DSP_SUBDIVIDE;
+ extern unsigned IOCTL_SNDCTL_DSP_SYNC;
+ extern unsigned IOCTL_SNDCTL_FM_4OP_ENABLE;
+ extern unsigned IOCTL_SNDCTL_FM_LOAD_INSTR;
+ extern unsigned IOCTL_SNDCTL_MIDI_INFO;
+ extern unsigned IOCTL_SNDCTL_MIDI_PRETIME;
+ extern unsigned IOCTL_SNDCTL_SEQ_CTRLRATE;
+ extern unsigned IOCTL_SNDCTL_SEQ_GETINCOUNT;
+ extern unsigned IOCTL_SNDCTL_SEQ_GETOUTCOUNT;
+ extern unsigned IOCTL_SNDCTL_SEQ_NRMIDIS;
+ extern unsigned IOCTL_SNDCTL_SEQ_NRSYNTHS;
+ extern unsigned IOCTL_SNDCTL_SEQ_OUTOFBAND;
+ extern unsigned IOCTL_SNDCTL_SEQ_PANIC;
+ extern unsigned IOCTL_SNDCTL_SEQ_PERCMODE;
+ extern unsigned IOCTL_SNDCTL_SEQ_RESET;
+ extern unsigned IOCTL_SNDCTL_SEQ_RESETSAMPLES;
+ extern unsigned IOCTL_SNDCTL_SEQ_SYNC;
+ extern unsigned IOCTL_SNDCTL_SEQ_TESTMIDI;
+ extern unsigned IOCTL_SNDCTL_SEQ_THRESHOLD;
+ extern unsigned IOCTL_SNDCTL_SYNTH_INFO;
+ extern unsigned IOCTL_SNDCTL_SYNTH_MEMAVL;
+ extern unsigned IOCTL_SNDCTL_TMR_CONTINUE;
+ extern unsigned IOCTL_SNDCTL_TMR_METRONOME;
+ extern unsigned IOCTL_SNDCTL_TMR_SELECT;
+ extern unsigned IOCTL_SNDCTL_TMR_SOURCE;
+ extern unsigned IOCTL_SNDCTL_TMR_START;
+ extern unsigned IOCTL_SNDCTL_TMR_STOP;
+ extern unsigned IOCTL_SNDCTL_TMR_TEMPO;
+ extern unsigned IOCTL_SNDCTL_TMR_TIMEBASE;
+ extern unsigned IOCTL_SOUND_MIXER_READ_ALTPCM;
+ extern unsigned IOCTL_SOUND_MIXER_READ_BASS;
+ extern unsigned IOCTL_SOUND_MIXER_READ_CAPS;
+ extern unsigned IOCTL_SOUND_MIXER_READ_CD;
+ extern unsigned IOCTL_SOUND_MIXER_READ_DEVMASK;
+ extern unsigned IOCTL_SOUND_MIXER_READ_ENHANCE;
+ extern unsigned IOCTL_SOUND_MIXER_READ_IGAIN;
+ extern unsigned IOCTL_SOUND_MIXER_READ_IMIX;
+ extern unsigned IOCTL_SOUND_MIXER_READ_LINE1;
+ extern unsigned IOCTL_SOUND_MIXER_READ_LINE2;
+ extern unsigned IOCTL_SOUND_MIXER_READ_LINE3;
+ extern unsigned IOCTL_SOUND_MIXER_READ_LINE;
+ extern unsigned IOCTL_SOUND_MIXER_READ_LOUD;
+ extern unsigned IOCTL_SOUND_MIXER_READ_MIC;
+ extern unsigned IOCTL_SOUND_MIXER_READ_MUTE;
+ extern unsigned IOCTL_SOUND_MIXER_READ_OGAIN;
+ extern unsigned IOCTL_SOUND_MIXER_READ_PCM;
+ extern unsigned IOCTL_SOUND_MIXER_READ_RECLEV;
+ extern unsigned IOCTL_SOUND_MIXER_READ_RECMASK;
+ extern unsigned IOCTL_SOUND_MIXER_READ_RECSRC;
+ extern unsigned IOCTL_SOUND_MIXER_READ_SPEAKER;
+ extern unsigned IOCTL_SOUND_MIXER_READ_STEREODEVS;
+ extern unsigned IOCTL_SOUND_MIXER_READ_SYNTH;
+ extern unsigned IOCTL_SOUND_MIXER_READ_TREBLE;
+ extern unsigned IOCTL_SOUND_MIXER_READ_VOLUME;
+ extern unsigned IOCTL_SOUND_MIXER_WRITE_ALTPCM;
+ extern unsigned IOCTL_SOUND_MIXER_WRITE_BASS;
+ extern unsigned IOCTL_SOUND_MIXER_WRITE_CD;
+ extern unsigned IOCTL_SOUND_MIXER_WRITE_ENHANCE;
+ extern unsigned IOCTL_SOUND_MIXER_WRITE_IGAIN;
+ extern unsigned IOCTL_SOUND_MIXER_WRITE_IMIX;
+ extern unsigned IOCTL_SOUND_MIXER_WRITE_LINE1;
+ extern unsigned IOCTL_SOUND_MIXER_WRITE_LINE2;
+ extern unsigned IOCTL_SOUND_MIXER_WRITE_LINE3;
+ extern unsigned IOCTL_SOUND_MIXER_WRITE_LINE;
+ extern unsigned IOCTL_SOUND_MIXER_WRITE_LOUD;
+ extern unsigned IOCTL_SOUND_MIXER_WRITE_MIC;
+ extern unsigned IOCTL_SOUND_MIXER_WRITE_MUTE;
+ extern unsigned IOCTL_SOUND_MIXER_WRITE_OGAIN;
+ extern unsigned IOCTL_SOUND_MIXER_WRITE_PCM;
+ extern unsigned IOCTL_SOUND_MIXER_WRITE_RECLEV;
+ extern unsigned IOCTL_SOUND_MIXER_WRITE_RECSRC;
+ extern unsigned IOCTL_SOUND_MIXER_WRITE_SPEAKER;
+ extern unsigned IOCTL_SOUND_MIXER_WRITE_SYNTH;
+ extern unsigned IOCTL_SOUND_MIXER_WRITE_TREBLE;
+ extern unsigned IOCTL_SOUND_MIXER_WRITE_VOLUME;
+ extern unsigned IOCTL_SOUND_PCM_READ_BITS;
+ extern unsigned IOCTL_SOUND_PCM_READ_CHANNELS;
+ extern unsigned IOCTL_SOUND_PCM_READ_FILTER;
+ extern unsigned IOCTL_SOUND_PCM_READ_RATE;
+ extern unsigned IOCTL_SOUND_PCM_WRITE_CHANNELS;
+ extern unsigned IOCTL_SOUND_PCM_WRITE_FILTER;
+ extern unsigned IOCTL_TCFLSH;
+ extern unsigned IOCTL_TCGETA;
+ extern unsigned IOCTL_TCGETS;
+ extern unsigned IOCTL_TCSBRK;
+ extern unsigned IOCTL_TCSBRKP;
+ extern unsigned IOCTL_TCSETA;
+ extern unsigned IOCTL_TCSETAF;
+ extern unsigned IOCTL_TCSETAW;
+ extern unsigned IOCTL_TCSETS;
+ extern unsigned IOCTL_TCSETSF;
+ extern unsigned IOCTL_TCSETSW;
+ extern unsigned IOCTL_TCXONC;
+ extern unsigned IOCTL_TIOCGLCKTRMIOS;
+ extern unsigned IOCTL_TIOCGSOFTCAR;
+ extern unsigned IOCTL_TIOCINQ;
+ extern unsigned IOCTL_TIOCLINUX;
+ extern unsigned IOCTL_TIOCSERCONFIG;
+ extern unsigned IOCTL_TIOCSERGETLSR;
+ extern unsigned IOCTL_TIOCSERGWILD;
+ extern unsigned IOCTL_TIOCSERSWILD;
+ extern unsigned IOCTL_TIOCSLCKTRMIOS;
+ extern unsigned IOCTL_TIOCSSOFTCAR;
+ extern unsigned IOCTL_VT_ACTIVATE;
+ extern unsigned IOCTL_VT_DISALLOCATE;
+ extern unsigned IOCTL_VT_GETMODE;
+ extern unsigned IOCTL_VT_GETSTATE;
+ extern unsigned IOCTL_VT_OPENQRY;
+ extern unsigned IOCTL_VT_RELDISP;
+ extern unsigned IOCTL_VT_RESIZE;
+ extern unsigned IOCTL_VT_RESIZEX;
+ extern unsigned IOCTL_VT_SENDSIG;
+ extern unsigned IOCTL_VT_SETMODE;
+ extern unsigned IOCTL_VT_WAITACTIVE;
+#endif
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
+ extern unsigned IOCTL_CYGETDEFTHRESH;
+ extern unsigned IOCTL_CYGETDEFTIMEOUT;
+ extern unsigned IOCTL_CYGETMON;
+ extern unsigned IOCTL_CYGETTHRESH;
+ extern unsigned IOCTL_CYGETTIMEOUT;
+ extern unsigned IOCTL_CYSETDEFTHRESH;
+ extern unsigned IOCTL_CYSETDEFTIMEOUT;
+ extern unsigned IOCTL_CYSETTHRESH;
+ extern unsigned IOCTL_CYSETTIMEOUT;
+ extern unsigned IOCTL_EQL_EMANCIPATE;
+ extern unsigned IOCTL_EQL_ENSLAVE;
+ extern unsigned IOCTL_EQL_GETMASTRCFG;
+ extern unsigned IOCTL_EQL_GETSLAVECFG;
+ extern unsigned IOCTL_EQL_SETMASTRCFG;
+ extern unsigned IOCTL_EQL_SETSLAVECFG;
+ extern unsigned IOCTL_EVIOCGKEYCODE_V2;
+ extern unsigned IOCTL_EVIOCGPROP;
+ extern unsigned IOCTL_EVIOCSKEYCODE_V2;
+ extern unsigned IOCTL_FS_IOC_GETFLAGS;
+ extern unsigned IOCTL_FS_IOC_GETVERSION;
+ extern unsigned IOCTL_FS_IOC_SETFLAGS;
+ extern unsigned IOCTL_FS_IOC_SETVERSION;
+ extern unsigned IOCTL_GIO_CMAP;
+ extern unsigned IOCTL_GIO_FONT;
+ extern unsigned IOCTL_GIO_SCRNMAP;
+ extern unsigned IOCTL_GIO_UNIMAP;
+ extern unsigned IOCTL_GIO_UNISCRNMAP;
+ extern unsigned IOCTL_KDADDIO;
+ extern unsigned IOCTL_KDDELIO;
+ extern unsigned IOCTL_KDDISABIO;
+ extern unsigned IOCTL_KDENABIO;
+ extern unsigned IOCTL_KDGETKEYCODE;
+ extern unsigned IOCTL_KDGETLED;
+ extern unsigned IOCTL_KDGETMODE;
+ extern unsigned IOCTL_KDGKBDIACR;
+ extern unsigned IOCTL_KDGKBENT;
+ extern unsigned IOCTL_KDGKBLED;
+ extern unsigned IOCTL_KDGKBMETA;
+ extern unsigned IOCTL_KDGKBMODE;
+ extern unsigned IOCTL_KDGKBSENT;
+ extern unsigned IOCTL_KDGKBTYPE;
+ extern unsigned IOCTL_KDMAPDISP;
+ extern unsigned IOCTL_KDMKTONE;
+ extern unsigned IOCTL_KDSETKEYCODE;
+ extern unsigned IOCTL_KDSETLED;
+ extern unsigned IOCTL_KDSETMODE;
+ extern unsigned IOCTL_KDSIGACCEPT;
+ extern unsigned IOCTL_KDSKBDIACR;
+ extern unsigned IOCTL_KDSKBENT;
+ extern unsigned IOCTL_KDSKBLED;
+ extern unsigned IOCTL_KDSKBMETA;
+ extern unsigned IOCTL_KDSKBMODE;
+ extern unsigned IOCTL_KDSKBSENT;
+ extern unsigned IOCTL_KDUNMAPDISP;
+ extern unsigned IOCTL_KIOCSOUND;
+ extern unsigned IOCTL_LPABORT;
+ extern unsigned IOCTL_LPABORTOPEN;
+ extern unsigned IOCTL_LPCAREFUL;
+ extern unsigned IOCTL_LPCHAR;
+ extern unsigned IOCTL_LPGETIRQ;
+ extern unsigned IOCTL_LPGETSTATUS;
+ extern unsigned IOCTL_LPRESET;
+ extern unsigned IOCTL_LPSETIRQ;
+ extern unsigned IOCTL_LPTIME;
+ extern unsigned IOCTL_LPWAIT;
+ extern unsigned IOCTL_MTIOCGETCONFIG;
+ extern unsigned IOCTL_MTIOCSETCONFIG;
+ extern unsigned IOCTL_PIO_CMAP;
+ extern unsigned IOCTL_PIO_FONT;
+ extern unsigned IOCTL_PIO_SCRNMAP;
+ extern unsigned IOCTL_PIO_UNIMAP;
+ extern unsigned IOCTL_PIO_UNIMAPCLR;
+ extern unsigned IOCTL_PIO_UNISCRNMAP;
+ extern unsigned IOCTL_SCSI_IOCTL_GET_IDLUN;
+ extern unsigned IOCTL_SCSI_IOCTL_PROBE_HOST;
+ extern unsigned IOCTL_SCSI_IOCTL_TAGGED_DISABLE;
+ extern unsigned IOCTL_SCSI_IOCTL_TAGGED_ENABLE;
+ extern unsigned IOCTL_SIOCAIPXITFCRT;
+ extern unsigned IOCTL_SIOCAIPXPRISLT;
+ extern unsigned IOCTL_SIOCAX25ADDUID;
+ extern unsigned IOCTL_SIOCAX25DELUID;
+ extern unsigned IOCTL_SIOCAX25GETPARMS;
+ extern unsigned IOCTL_SIOCAX25GETUID;
+ extern unsigned IOCTL_SIOCAX25NOUID;
+ extern unsigned IOCTL_SIOCAX25SETPARMS;
+ extern unsigned IOCTL_SIOCDEVPLIP;
+ extern unsigned IOCTL_SIOCIPXCFGDATA;
+ extern unsigned IOCTL_SIOCNRDECOBS;
+ extern unsigned IOCTL_SIOCNRGETPARMS;
+ extern unsigned IOCTL_SIOCNRRTCTL;
+ extern unsigned IOCTL_SIOCNRSETPARMS;
+ extern unsigned IOCTL_SNDCTL_DSP_GETISPACE;
+ extern unsigned IOCTL_SNDCTL_DSP_GETOSPACE;
+ extern unsigned IOCTL_TIOCGSERIAL;
+ extern unsigned IOCTL_TIOCSERGETMULTI;
+ extern unsigned IOCTL_TIOCSERSETMULTI;
+ extern unsigned IOCTL_TIOCSSERIAL;
+#endif
} // namespace __sanitizer
#endif
diff --git a/libsanitizer/sanitizer_common/sanitizer_posix.cc b/libsanitizer/sanitizer_common/sanitizer_posix.cc
index 1c6ff0a2ebb..6d999e91961 100644
--- a/libsanitizer/sanitizer_common/sanitizer_posix.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_posix.cc
@@ -9,53 +9,49 @@
// run-time libraries and implements POSIX-specific functions from
// sanitizer_libc.h.
//===----------------------------------------------------------------------===//
-#if defined(__linux__) || defined(__APPLE__)
+
+#include "sanitizer_platform.h"
+#if SANITIZER_LINUX || SANITIZER_MAC
#include "sanitizer_common.h"
#include "sanitizer_libc.h"
#include "sanitizer_procmaps.h"
+#include "sanitizer_stacktrace.h"
-#include <errno.h>
-#include <pthread.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
#include <sys/mman.h>
-#include <sys/resource.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <unistd.h>
namespace __sanitizer {
// ------------- sanitizer_common.h
-uptr GetPageSize() {
- return sysconf(_SC_PAGESIZE);
-}
-
uptr GetMmapGranularity() {
return GetPageSize();
}
-int GetPid() {
- return getpid();
-}
-
-u32 GetUid() {
- return getuid();
-}
-
-uptr GetThreadSelf() {
- return (uptr)pthread_self();
+uptr GetMaxVirtualAddress() {
+#if SANITIZER_WORDSIZE == 64
+# if defined(__powerpc64__)
+ // On PowerPC64 we have two different address space layouts: 44- and 46-bit.
+ // We somehow need to figure our which one we are using now and choose
+ // one of 0x00000fffffffffffUL and 0x00003fffffffffffUL.
+ // Note that with 'ulimit -s unlimited' the stack is moved away from the top
+ // of the address space, so simply checking the stack address is not enough.
+ return (1ULL << 44) - 1; // 0x00000fffffffffffUL
+# else
+ return (1ULL << 47) - 1; // 0x00007fffffffffffUL;
+# endif
+#else // SANITIZER_WORDSIZE == 32
+ // FIXME: We can probably lower this on Android?
+ return (1ULL << 32) - 1; // 0xffffffff;
+#endif // SANITIZER_WORDSIZE
}
void *MmapOrDie(uptr size, const char *mem_type) {
size = RoundUpTo(size, GetPageSizeCached());
- void *res = internal_mmap(0, size,
+ uptr res = internal_mmap(0, size,
PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANON, -1, 0);
- if (res == (void*)-1) {
+ int reserrno;
+ if (internal_iserror(res, &reserrno)) {
static int recursion_count;
if (recursion_count) {
// The Report() and CHECK calls below may call mmap recursively and fail.
@@ -64,18 +60,18 @@ void *MmapOrDie(uptr size, const char *mem_type) {
Die();
}
recursion_count++;
- Report("ERROR: %s failed to allocate 0x%zx (%zd) bytes of %s: %s\n",
- SanitizerToolName, size, size, mem_type, strerror(errno));
+ Report("ERROR: %s failed to allocate 0x%zx (%zd) bytes of %s: %d\n",
+ SanitizerToolName, size, size, mem_type, reserrno);
DumpProcessMap();
CHECK("unable to mmap" && 0);
}
- return res;
+ return (void *)res;
}
void UnmapOrDie(void *addr, uptr size) {
if (!addr || !size) return;
- int res = internal_munmap(addr, size);
- if (res != 0) {
+ uptr res = internal_munmap(addr, size);
+ if (internal_iserror(res)) {
Report("ERROR: %s failed to deallocate 0x%zx (%zd) bytes at address %p\n",
SanitizerToolName, size, size, addr);
CHECK("unable to unmap" && 0);
@@ -84,54 +80,53 @@ void UnmapOrDie(void *addr, uptr size) {
void *MmapFixedNoReserve(uptr fixed_addr, uptr size) {
uptr PageSize = GetPageSizeCached();
- void *p = internal_mmap((void*)(fixed_addr & ~(PageSize - 1)),
+ uptr p = internal_mmap((void*)(fixed_addr & ~(PageSize - 1)),
RoundUpTo(size, PageSize),
PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_NORESERVE,
-1, 0);
- if (p == (void*)-1)
+ int reserrno;
+ if (internal_iserror(p, &reserrno))
Report("ERROR: "
"%s failed to allocate 0x%zx (%zd) bytes at address %p (%d)\n",
- SanitizerToolName, size, size, fixed_addr, errno);
- return p;
+ SanitizerToolName, size, size, fixed_addr, reserrno);
+ return (void *)p;
}
void *MmapFixedOrDie(uptr fixed_addr, uptr size) {
uptr PageSize = GetPageSizeCached();
- void *p = internal_mmap((void*)(fixed_addr & ~(PageSize - 1)),
+ uptr p = internal_mmap((void*)(fixed_addr & ~(PageSize - 1)),
RoundUpTo(size, PageSize),
PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANON | MAP_FIXED,
-1, 0);
- if (p == (void*)-1) {
+ int reserrno;
+ if (internal_iserror(p, &reserrno)) {
Report("ERROR:"
" %s failed to allocate 0x%zx (%zd) bytes at address %p (%d)\n",
- SanitizerToolName, size, size, fixed_addr, errno);
+ SanitizerToolName, size, size, fixed_addr, reserrno);
CHECK("unable to mmap" && 0);
}
- return p;
+ return (void *)p;
}
void *Mprotect(uptr fixed_addr, uptr size) {
- return internal_mmap((void*)fixed_addr, size,
- PROT_NONE,
- MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_NORESERVE,
- -1, 0);
-}
-
-void FlushUnneededShadowMemory(uptr addr, uptr size) {
- madvise((void*)addr, size, MADV_DONTNEED);
+ return (void *)internal_mmap((void*)fixed_addr, size,
+ PROT_NONE,
+ MAP_PRIVATE | MAP_ANON | MAP_FIXED |
+ MAP_NORESERVE, -1, 0);
}
void *MapFileToMemory(const char *file_name, uptr *buff_size) {
- fd_t fd = OpenFile(file_name, false);
- CHECK_NE(fd, kInvalidFd);
+ uptr openrv = OpenFile(file_name, false);
+ CHECK(!internal_iserror(openrv));
+ fd_t fd = openrv;
uptr fsize = internal_filesize(fd);
CHECK_NE(fsize, (uptr)-1);
CHECK_GT(fsize, 0);
*buff_size = RoundUpTo(fsize, GetPageSizeCached());
- void *map = internal_mmap(0, *buff_size, PROT_READ, MAP_PRIVATE, fd, 0);
- return (map == MAP_FAILED) ? 0 : map;
+ uptr map = internal_mmap(0, *buff_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ return internal_iserror(map) ? 0 : (void *)map;
}
@@ -147,10 +142,11 @@ static inline bool IntervalsAreSeparate(uptr start1, uptr end1,
// several worker threads on Mac, which aren't expected to map big chunks of
// memory).
bool MemoryRangeIsAvailable(uptr range_start, uptr range_end) {
- MemoryMappingLayout procmaps;
+ MemoryMappingLayout proc_maps(/*cache_enabled*/true);
uptr start, end;
- while (procmaps.Next(&start, &end,
- /*offset*/0, /*filename*/0, /*filename_size*/0)) {
+ while (proc_maps.Next(&start, &end,
+ /*offset*/0, /*filename*/0, /*filename_size*/0,
+ /*protection*/0)) {
if (!IntervalsAreSeparate(start, end, range_start, range_end))
return false;
}
@@ -158,13 +154,13 @@ bool MemoryRangeIsAvailable(uptr range_start, uptr range_end) {
}
void DumpProcessMap() {
- MemoryMappingLayout proc_maps;
+ MemoryMappingLayout proc_maps(/*cache_enabled*/true);
uptr start, end;
const sptr kBufSize = 4095;
char *filename = (char*)MmapOrDie(kBufSize, __FUNCTION__);
Report("Process memory map follows:\n");
while (proc_maps.Next(&start, &end, /* file_offset */0,
- filename, kBufSize)) {
+ filename, kBufSize, /* protection */0)) {
Printf("\t%p-%p\t%s\n", (void*)start, (void*)end, filename);
}
Report("End of process memory map.\n");
@@ -175,54 +171,77 @@ const char *GetPwd() {
return GetEnv("PWD");
}
-void DisableCoreDumper() {
- struct rlimit nocore;
- nocore.rlim_cur = 0;
- nocore.rlim_max = 0;
- setrlimit(RLIMIT_CORE, &nocore);
-}
-
-bool StackSizeIsUnlimited() {
- struct rlimit rlim;
- CHECK_EQ(0, getrlimit(RLIMIT_STACK, &rlim));
- return (rlim.rlim_cur == (uptr)-1);
+char *FindPathToBinary(const char *name) {
+ const char *path = GetEnv("PATH");
+ if (!path)
+ return 0;
+ uptr name_len = internal_strlen(name);
+ InternalScopedBuffer<char> buffer(kMaxPathLength);
+ const char *beg = path;
+ while (true) {
+ const char *end = internal_strchrnul(beg, ':');
+ uptr prefix_len = end - beg;
+ if (prefix_len + name_len + 2 <= kMaxPathLength) {
+ internal_memcpy(buffer.data(), beg, prefix_len);
+ buffer[prefix_len] = '/';
+ internal_memcpy(&buffer[prefix_len + 1], name, name_len);
+ buffer[prefix_len + 1 + name_len] = '\0';
+ if (FileExists(buffer.data()))
+ return internal_strdup(buffer.data());
+ }
+ if (*end == '\0') break;
+ beg = end + 1;
+ }
+ return 0;
}
-void SetStackSizeLimitInBytes(uptr limit) {
- struct rlimit rlim;
- rlim.rlim_cur = limit;
- rlim.rlim_max = limit;
- if (setrlimit(RLIMIT_STACK, &rlim)) {
- Report("ERROR: %s setrlimit() failed %d\n", SanitizerToolName, errno);
+void MaybeOpenReportFile() {
+ if (!log_to_file || (report_fd_pid == internal_getpid())) return;
+ InternalScopedBuffer<char> report_path_full(4096);
+ internal_snprintf(report_path_full.data(), report_path_full.size(),
+ "%s.%d", report_path_prefix, internal_getpid());
+ uptr openrv = OpenFile(report_path_full.data(), true);
+ if (internal_iserror(openrv)) {
+ report_fd = kStderrFd;
+ log_to_file = false;
+ Report("ERROR: Can't open file: %s\n", report_path_full.data());
Die();
}
- CHECK(!StackSizeIsUnlimited());
-}
-
-void SleepForSeconds(int seconds) {
- sleep(seconds);
-}
-
-void SleepForMillis(int millis) {
- usleep(millis * 1000);
-}
-
-void Abort() {
- abort();
+ if (report_fd != kInvalidFd) {
+ // We're in the child. Close the parent's log.
+ internal_close(report_fd);
+ }
+ report_fd = openrv;
+ report_fd_pid = internal_getpid();
}
-int Atexit(void (*function)(void)) {
-#ifndef SANITIZER_GO
- return atexit(function);
-#else
- return 0;
-#endif
+void RawWrite(const char *buffer) {
+ static const char *kRawWriteError =
+ "RawWrite can't output requested buffer!\n";
+ uptr length = (uptr)internal_strlen(buffer);
+ MaybeOpenReportFile();
+ if (length != internal_write(report_fd, buffer, length)) {
+ internal_write(report_fd, kRawWriteError, internal_strlen(kRawWriteError));
+ Die();
+ }
}
-int internal_isatty(fd_t fd) {
- return isatty(fd);
+bool GetCodeRangeForFile(const char *module, uptr *start, uptr *end) {
+ uptr s, e, off, prot;
+ InternalMmapVector<char> fn(4096);
+ fn.push_back(0);
+ MemoryMappingLayout proc_maps(/*cache_enabled*/false);
+ while (proc_maps.Next(&s, &e, &off, &fn[0], fn.capacity(), &prot)) {
+ if ((prot & MemoryMappingLayout::kProtectionExecute) != 0
+ && internal_strcmp(module, &fn[0]) == 0) {
+ *start = s;
+ *end = e;
+ return true;
+ }
+ }
+ return false;
}
} // namespace __sanitizer
-#endif // __linux__ || __APPLE_
+#endif // SANITIZER_LINUX || SANITIZER_MAC
diff --git a/libsanitizer/sanitizer_common/sanitizer_posix_libcdep.cc b/libsanitizer/sanitizer_common/sanitizer_posix_libcdep.cc
new file mode 100644
index 00000000000..3d4f92db581
--- /dev/null
+++ b/libsanitizer/sanitizer_common/sanitizer_posix_libcdep.cc
@@ -0,0 +1,114 @@
+//===-- sanitizer_posix_libcdep.cc ----------------------------------------===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between AddressSanitizer and ThreadSanitizer
+// run-time libraries and implements libc-dependent POSIX-specific functions
+// from sanitizer_libc.h.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_platform.h"
+
+#if SANITIZER_LINUX || SANITIZER_MAC
+#include "sanitizer_common.h"
+#include "sanitizer_stacktrace.h"
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <sys/resource.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+namespace __sanitizer {
+
+u32 GetUid() {
+ return getuid();
+}
+
+uptr GetThreadSelf() {
+ return (uptr)pthread_self();
+}
+
+void FlushUnneededShadowMemory(uptr addr, uptr size) {
+ madvise((void*)addr, size, MADV_DONTNEED);
+}
+
+void DisableCoreDumper() {
+ struct rlimit nocore;
+ nocore.rlim_cur = 0;
+ nocore.rlim_max = 0;
+ setrlimit(RLIMIT_CORE, &nocore);
+}
+
+bool StackSizeIsUnlimited() {
+ struct rlimit rlim;
+ CHECK_EQ(0, getrlimit(RLIMIT_STACK, &rlim));
+ return (rlim.rlim_cur == (uptr)-1);
+}
+
+void SetStackSizeLimitInBytes(uptr limit) {
+ struct rlimit rlim;
+ rlim.rlim_cur = limit;
+ rlim.rlim_max = limit;
+ if (setrlimit(RLIMIT_STACK, &rlim)) {
+ Report("ERROR: %s setrlimit() failed %d\n", SanitizerToolName, errno);
+ Die();
+ }
+ CHECK(!StackSizeIsUnlimited());
+}
+
+void SleepForSeconds(int seconds) {
+ sleep(seconds);
+}
+
+void SleepForMillis(int millis) {
+ usleep(millis * 1000);
+}
+
+void Abort() {
+ abort();
+}
+
+int Atexit(void (*function)(void)) {
+#ifndef SANITIZER_GO
+ return atexit(function);
+#else
+ return 0;
+#endif
+}
+
+int internal_isatty(fd_t fd) {
+ return isatty(fd);
+}
+
+#ifndef SANITIZER_GO
+void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp,
+ uptr stack_top, uptr stack_bottom, bool fast) {
+#if !SANITIZER_CAN_FAST_UNWIND
+ fast = false;
+#endif
+#if SANITIZER_MAC
+ // Always unwind fast on Mac.
+ (void)fast;
+#else
+ if (!fast)
+ return stack->SlowUnwindStack(pc, max_s);
+#endif // SANITIZER_MAC
+ stack->size = 0;
+ stack->trace[0] = pc;
+ if (max_s > 1) {
+ stack->max_size = max_s;
+ stack->FastUnwindStack(pc, bp, stack_top, stack_bottom);
+ }
+}
+#endif // SANITIZER_GO
+
+} // namespace __sanitizer
+
+#endif
diff --git a/libsanitizer/sanitizer_common/sanitizer_printf.cc b/libsanitizer/sanitizer_common/sanitizer_printf.cc
index 8298f12bd7b..d7ce9736b24 100644
--- a/libsanitizer/sanitizer_common/sanitizer_printf.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_printf.cc
@@ -19,6 +19,10 @@
#include <stdio.h>
#include <stdarg.h>
+#if SANITIZER_WINDOWS && !defined(va_copy)
+# define va_copy(dst, src) ((dst) = (src))
+#endif
+
namespace __sanitizer {
StaticSpinMutex CommonSanitizerReportMutex;
@@ -32,45 +36,60 @@ static int AppendChar(char **buff, const char *buff_end, char c) {
}
// Appends number in a given base to buffer. If its length is less than
-// "minimal_num_length", it is padded with leading zeroes.
-static int AppendUnsigned(char **buff, const char *buff_end, u64 num,
- u8 base, u8 minimal_num_length) {
+// |minimal_num_length|, it is padded with leading zeroes or spaces, depending
+// on the value of |pad_with_zero|.
+static int AppendNumber(char **buff, const char *buff_end, u64 absolute_value,
+ u8 base, u8 minimal_num_length, bool pad_with_zero,
+ bool negative) {
uptr const kMaxLen = 30;
RAW_CHECK(base == 10 || base == 16);
+ RAW_CHECK(base == 10 || !negative);
+ RAW_CHECK(absolute_value || !negative);
RAW_CHECK(minimal_num_length < kMaxLen);
+ int result = 0;
+ if (negative && minimal_num_length)
+ --minimal_num_length;
+ if (negative && pad_with_zero)
+ result += AppendChar(buff, buff_end, '-');
uptr num_buffer[kMaxLen];
- uptr pos = 0;
+ int pos = 0;
do {
- RAW_CHECK_MSG(pos < kMaxLen, "appendNumber buffer overflow");
- num_buffer[pos++] = num % base;
- num /= base;
- } while (num > 0);
+ RAW_CHECK_MSG((uptr)pos < kMaxLen, "AppendNumber buffer overflow");
+ num_buffer[pos++] = absolute_value % base;
+ absolute_value /= base;
+ } while (absolute_value > 0);
if (pos < minimal_num_length) {
// Make sure compiler doesn't insert call to memset here.
internal_memset(&num_buffer[pos], 0,
sizeof(num_buffer[0]) * (minimal_num_length - pos));
pos = minimal_num_length;
}
- int result = 0;
- while (pos-- > 0) {
- uptr digit = num_buffer[pos];
+ RAW_CHECK(pos > 0);
+ pos--;
+ for (; pos >= 0 && num_buffer[pos] == 0; pos--) {
+ char c = (pad_with_zero || pos == 0) ? '0' : ' ';
+ result += AppendChar(buff, buff_end, c);
+ }
+ if (negative && !pad_with_zero) result += AppendChar(buff, buff_end, '-');
+ for (; pos >= 0; pos--) {
+ char digit = static_cast<char>(num_buffer[pos]);
result += AppendChar(buff, buff_end, (digit < 10) ? '0' + digit
: 'a' + digit - 10);
}
return result;
}
+static int AppendUnsigned(char **buff, const char *buff_end, u64 num, u8 base,
+ u8 minimal_num_length, bool pad_with_zero) {
+ return AppendNumber(buff, buff_end, num, base, minimal_num_length,
+ pad_with_zero, false /* negative */);
+}
+
static int AppendSignedDecimal(char **buff, const char *buff_end, s64 num,
- u8 minimal_num_length) {
- int result = 0;
- if (num < 0) {
- result += AppendChar(buff, buff_end, '-');
- num = -num;
- if (minimal_num_length)
- --minimal_num_length;
- }
- result += AppendUnsigned(buff, buff_end, (u64)num, 10, minimal_num_length);
- return result;
+ u8 minimal_num_length, bool pad_with_zero) {
+ bool negative = (num < 0);
+ return AppendNumber(buff, buff_end, (u64)(negative ? -num : num), 10,
+ minimal_num_length, pad_with_zero, negative);
}
static int AppendString(char **buff, const char *buff_end, const char *s) {
@@ -87,14 +106,14 @@ static int AppendPointer(char **buff, const char *buff_end, u64 ptr_value) {
int result = 0;
result += AppendString(buff, buff_end, "0x");
result += AppendUnsigned(buff, buff_end, ptr_value, 16,
- (SANITIZER_WORDSIZE == 64) ? 12 : 8);
+ (SANITIZER_WORDSIZE == 64) ? 12 : 8, true);
return result;
}
int VSNPrintf(char *buff, int buff_length,
const char *format, va_list args) {
static const char *kPrintfFormatsHelp =
- "Supported Printf formats: %(0[0-9]*)?(z|ll)?{d,u,x}; %p; %s; %c\n";
+ "Supported Printf formats: %([0-9]*)?(z|ll)?{d,u,x}; %p; %s; %c\n";
RAW_CHECK(format);
RAW_CHECK(buff_length > 0);
const char *buff_end = &buff[buff_length - 1];
@@ -106,11 +125,11 @@ int VSNPrintf(char *buff, int buff_length,
continue;
}
cur++;
- bool have_width = (*cur == '0');
+ bool have_width = (*cur >= '0' && *cur <= '9');
+ bool pad_with_zero = (*cur == '0');
int width = 0;
if (have_width) {
while (*cur >= '0' && *cur <= '9') {
- have_width = true;
width = width * 10 + *cur++ - '0';
}
}
@@ -126,7 +145,8 @@ int VSNPrintf(char *buff, int buff_length,
dval = have_ll ? va_arg(args, s64)
: have_z ? va_arg(args, sptr)
: va_arg(args, int);
- result += AppendSignedDecimal(&buff, buff_end, dval, width);
+ result += AppendSignedDecimal(&buff, buff_end, dval, width,
+ pad_with_zero);
break;
}
case 'u':
@@ -135,7 +155,7 @@ int VSNPrintf(char *buff, int buff_length,
: have_z ? va_arg(args, uptr)
: va_arg(args, unsigned);
result += AppendUnsigned(&buff, buff_end, uval,
- (*cur == 'u') ? 10 : 16, width);
+ (*cur == 'u') ? 10 : 16, width, pad_with_zero);
break;
}
case 'p': {
@@ -173,17 +193,86 @@ void SetPrintfAndReportCallback(void (*callback)(const char *)) {
PrintfAndReportCallback = callback;
}
-void Printf(const char *format, ...) {
+#if SANITIZER_SUPPORTS_WEAK_HOOKS
+// Can be overriden in frontend.
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
+void OnPrint(const char *str);
+#endif
+
+static void CallPrintfAndReportCallback(const char *str) {
+#if SANITIZER_SUPPORTS_WEAK_HOOKS
+ if (&OnPrint != NULL)
+ OnPrint(str);
+#endif
+ if (PrintfAndReportCallback)
+ PrintfAndReportCallback(str);
+}
+
+static void SharedPrintfCode(bool append_pid, const char *format,
+ va_list args) {
+ va_list args2;
+ va_copy(args2, args);
const int kLen = 16 * 1024;
- InternalScopedBuffer<char> buffer(kLen);
+ // |local_buffer| is small enough not to overflow the stack and/or violate
+ // the stack limit enforced by TSan (-Wframe-larger-than=512). On the other
+ // hand, the bigger the buffer is, the more the chance the error report will
+ // fit into it.
+ char local_buffer[400];
+ int needed_length;
+ char *buffer = local_buffer;
+ int buffer_size = ARRAY_SIZE(local_buffer);
+ // First try to print a message using a local buffer, and then fall back to
+ // mmaped buffer.
+ for (int use_mmap = 0; use_mmap < 2; use_mmap++) {
+ if (use_mmap) {
+ va_end(args);
+ va_copy(args, args2);
+ buffer = (char*)MmapOrDie(kLen, "Report");
+ buffer_size = kLen;
+ }
+ needed_length = 0;
+ if (append_pid) {
+ int pid = internal_getpid();
+ needed_length += internal_snprintf(buffer, buffer_size, "==%d==", pid);
+ if (needed_length >= buffer_size) {
+ // The pid doesn't fit into the current buffer.
+ if (!use_mmap)
+ continue;
+ RAW_CHECK_MSG(needed_length < kLen, "Buffer in Report is too short!\n");
+ }
+ }
+ needed_length += VSNPrintf(buffer + needed_length,
+ buffer_size - needed_length, format, args);
+ if (needed_length >= buffer_size) {
+ // The message doesn't fit into the current buffer.
+ if (!use_mmap)
+ continue;
+ RAW_CHECK_MSG(needed_length < kLen, "Buffer in Report is too short!\n");
+ }
+ // If the message fit into the buffer, print it and exit.
+ break;
+ }
+ RawWrite(buffer);
+ CallPrintfAndReportCallback(buffer);
+ // If we had mapped any memory, clean up.
+ if (buffer != local_buffer)
+ UnmapOrDie((void *)buffer, buffer_size);
+ va_end(args2);
+}
+
+void Printf(const char *format, ...) {
va_list args;
va_start(args, format);
- int needed_length = VSNPrintf(buffer.data(), kLen, format, args);
+ SharedPrintfCode(false, format, args);
+ va_end(args);
+}
+
+// Like Printf, but prints the current PID before the output string.
+void Report(const char *format, ...) {
+ va_list args;
+ va_start(args, format);
+ SharedPrintfCode(true, format, args);
va_end(args);
- RAW_CHECK_MSG(needed_length < kLen, "Buffer in Printf is too short!\n");
- RawWrite(buffer.data());
- if (PrintfAndReportCallback)
- PrintfAndReportCallback(buffer.data());
}
// Writes at most "length" symbols to "buffer" (including trailing '\0').
@@ -198,22 +287,4 @@ int internal_snprintf(char *buffer, uptr length, const char *format, ...) {
return needed_length;
}
-// Like Printf, but prints the current PID before the output string.
-void Report(const char *format, ...) {
- const int kLen = 16 * 1024;
- InternalScopedBuffer<char> buffer(kLen);
- int needed_length = internal_snprintf(buffer.data(),
- kLen, "==%d== ", GetPid());
- RAW_CHECK_MSG(needed_length < kLen, "Buffer in Report is too short!\n");
- va_list args;
- va_start(args, format);
- needed_length += VSNPrintf(buffer.data() + needed_length,
- kLen - needed_length, format, args);
- va_end(args);
- RAW_CHECK_MSG(needed_length < kLen, "Buffer in Report is too short!\n");
- RawWrite(buffer.data());
- if (PrintfAndReportCallback)
- PrintfAndReportCallback(buffer.data());
-}
-
} // namespace __sanitizer
diff --git a/libsanitizer/sanitizer_common/sanitizer_procmaps.h b/libsanitizer/sanitizer_common/sanitizer_procmaps.h
index 400fd7a8bc4..87887f6b74b 100644
--- a/libsanitizer/sanitizer_common/sanitizer_procmaps.h
+++ b/libsanitizer/sanitizer_common/sanitizer_procmaps.h
@@ -17,51 +17,63 @@
namespace __sanitizer {
-#ifdef _WIN32
+#if SANITIZER_WINDOWS
class MemoryMappingLayout {
public:
- MemoryMappingLayout() {}
+ explicit MemoryMappingLayout(bool cache_enabled) {
+ (void)cache_enabled;
+ }
bool GetObjectNameAndOffset(uptr addr, uptr *offset,
- char filename[], uptr filename_size) {
+ char filename[], uptr filename_size,
+ uptr *protection) {
UNIMPLEMENTED();
}
};
-#else // _WIN32
-#if defined(__linux__)
+#else // SANITIZER_WINDOWS
+#if SANITIZER_LINUX
struct ProcSelfMapsBuff {
char *data;
uptr mmaped_size;
uptr len;
};
-#endif // defined(__linux__)
+#endif // SANITIZER_LINUX
class MemoryMappingLayout {
public:
- MemoryMappingLayout();
+ explicit MemoryMappingLayout(bool cache_enabled);
bool Next(uptr *start, uptr *end, uptr *offset,
- char filename[], uptr filename_size);
+ char filename[], uptr filename_size, uptr *protection);
void Reset();
// Gets the object file name and the offset in that object for a given
// address 'addr'. Returns true on success.
bool GetObjectNameAndOffset(uptr addr, uptr *offset,
- char filename[], uptr filename_size);
+ char filename[], uptr filename_size,
+ uptr *protection);
// In some cases, e.g. when running under a sandbox on Linux, ASan is unable
// to obtain the memory mappings. It should fall back to pre-cached data
// instead of aborting.
static void CacheMemoryMappings();
~MemoryMappingLayout();
+ // Memory protection masks.
+ static const uptr kProtectionRead = 1;
+ static const uptr kProtectionWrite = 2;
+ static const uptr kProtectionExecute = 4;
+ static const uptr kProtectionShared = 8;
+
private:
void LoadFromCache();
// Default implementation of GetObjectNameAndOffset.
// Quite slow, because it iterates through the whole process map for each
// lookup.
bool IterateForObjectNameAndOffset(uptr addr, uptr *offset,
- char filename[], uptr filename_size) {
+ char filename[], uptr filename_size,
+ uptr *protection) {
Reset();
uptr start, end, file_offset;
- for (int i = 0; Next(&start, &end, &file_offset, filename, filename_size);
+ for (int i = 0; Next(&start, &end, &file_offset, filename, filename_size,
+ protection);
i++) {
if (addr >= start && addr < end) {
// Don't subtract 'start' for the first entry:
@@ -84,17 +96,18 @@ class MemoryMappingLayout {
return false;
}
-# if defined __linux__
+# if SANITIZER_LINUX
ProcSelfMapsBuff proc_self_maps_;
char *current_;
// Static mappings cache.
static ProcSelfMapsBuff cached_proc_self_maps_;
static StaticSpinMutex cache_lock_; // protects cached_proc_self_maps_.
-# elif defined __APPLE__
+# elif SANITIZER_MAC
template<u32 kLCSegment, typename SegmentCommand>
bool NextSegmentLoad(uptr *start, uptr *end, uptr *offset,
- char filename[], uptr filename_size);
+ char filename[], uptr filename_size,
+ uptr *protection);
int current_image_;
u32 current_magic_;
u32 current_filetype_;
@@ -103,7 +116,18 @@ class MemoryMappingLayout {
# endif
};
-#endif // _WIN32
+typedef void (*fill_profile_f)(uptr start, uptr rss, bool file,
+ /*out*/uptr *stats, uptr stats_size);
+
+// Parse the contents of /proc/self/smaps and generate a memory profile.
+// |cb| is a tool-specific callback that fills the |stats| array containing
+// |stats_size| elements.
+void GetMemoryProfile(fill_profile_f cb, uptr *stats, uptr stats_size);
+
+// Returns code range for the specified module.
+bool GetCodeRangeForFile(const char *module, uptr *start, uptr *end);
+
+#endif // SANITIZER_WINDOWS
} // namespace __sanitizer
diff --git a/libsanitizer/sanitizer_common/sanitizer_quarantine.h b/libsanitizer/sanitizer_common/sanitizer_quarantine.h
index f3ad91a9cc2..7f567f97d7c 100644
--- a/libsanitizer/sanitizer_common/sanitizer_quarantine.h
+++ b/libsanitizer/sanitizer_common/sanitizer_quarantine.h
@@ -145,7 +145,9 @@ class QuarantineCache {
return 0;
QuarantineBatch *b = list_.front();
list_.pop_front();
- SizeAdd(-b->size);
+ // FIXME: should probably add SizeSub method?
+ // See https://code.google.com/p/thread-sanitizer/issues/detail?id=20
+ SizeAdd(0 - b->size);
return b;
}
diff --git a/libsanitizer/sanitizer_common/sanitizer_report_decorator.h b/libsanitizer/sanitizer_common/sanitizer_report_decorator.h
index cabf08e6082..c6e79ad0c7c 100644
--- a/libsanitizer/sanitizer_common/sanitizer_report_decorator.h
+++ b/libsanitizer/sanitizer_common/sanitizer_report_decorator.h
@@ -17,6 +17,8 @@
namespace __sanitizer {
class AnsiColorDecorator {
+ // FIXME: This is not portable. It assumes the special strings are printed to
+ // stdout, which is not the case on Windows (see SetConsoleTextAttribute()).
public:
explicit AnsiColorDecorator(bool use_ansi_colors) : ansi_(use_ansi_colors) { }
const char *Bold() const { return ansi_ ? "\033[1m" : ""; }
diff --git a/libsanitizer/sanitizer_common/sanitizer_stackdepot.cc b/libsanitizer/sanitizer_common/sanitizer_stackdepot.cc
index 2e22155fa75..e8d9f01e7f9 100644
--- a/libsanitizer/sanitizer_common/sanitizer_stackdepot.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_stackdepot.cc
@@ -199,4 +199,38 @@ const uptr *StackDepotGet(u32 id, uptr *size) {
return 0;
}
+bool StackDepotReverseMap::IdDescPair::IdComparator(
+ const StackDepotReverseMap::IdDescPair &a,
+ const StackDepotReverseMap::IdDescPair &b) {
+ return a.id < b.id;
+}
+
+StackDepotReverseMap::StackDepotReverseMap()
+ : map_(StackDepotGetStats()->n_uniq_ids + 100) {
+ for (int idx = 0; idx < kTabSize; idx++) {
+ atomic_uintptr_t *p = &depot.tab[idx];
+ uptr v = atomic_load(p, memory_order_consume);
+ StackDesc *s = (StackDesc*)(v & ~1);
+ for (; s; s = s->link) {
+ IdDescPair pair = {s->id, s};
+ map_.push_back(pair);
+ }
+ }
+ InternalSort(&map_, map_.size(), IdDescPair::IdComparator);
+}
+
+const uptr *StackDepotReverseMap::Get(u32 id, uptr *size) {
+ if (!map_.size()) return 0;
+ IdDescPair pair = {id, 0};
+ uptr idx = InternalBinarySearch(map_, 0, map_.size(), pair,
+ IdDescPair::IdComparator);
+ if (idx > map_.size()) {
+ *size = 0;
+ return 0;
+ }
+ StackDesc *desc = map_[idx].desc;
+ *size = desc->size;
+ return desc->stack;
+}
+
} // namespace __sanitizer
diff --git a/libsanitizer/sanitizer_common/sanitizer_stackdepot.h b/libsanitizer/sanitizer_common/sanitizer_stackdepot.h
index bf73cf14aad..c2c04ef9d64 100644
--- a/libsanitizer/sanitizer_common/sanitizer_stackdepot.h
+++ b/libsanitizer/sanitizer_common/sanitizer_stackdepot.h
@@ -11,6 +11,7 @@
#ifndef SANITIZER_STACKDEPOT_H
#define SANITIZER_STACKDEPOT_H
+#include "sanitizer_common.h"
#include "sanitizer_internal_defs.h"
namespace __sanitizer {
@@ -29,6 +30,31 @@ struct StackDepotStats {
StackDepotStats *StackDepotGetStats();
+struct StackDesc;
+
+// Instantiating this class creates a snapshot of StackDepot which can be
+// efficiently queried with StackDepotGet(). You can use it concurrently with
+// StackDepot, but the snapshot is only guaranteed to contain those stack traces
+// which were stored before it was instantiated.
+class StackDepotReverseMap {
+ public:
+ StackDepotReverseMap();
+ const uptr *Get(u32 id, uptr *size);
+
+ private:
+ struct IdDescPair {
+ u32 id;
+ StackDesc *desc;
+
+ static bool IdComparator(const IdDescPair &a, const IdDescPair &b);
+ };
+
+ InternalMmapVector<IdDescPair> map_;
+
+ // Disallow evil constructors.
+ StackDepotReverseMap(const StackDepotReverseMap&);
+ void operator=(const StackDepotReverseMap&);
+};
} // namespace __sanitizer
#endif // SANITIZER_STACKDEPOT_H
diff --git a/libsanitizer/sanitizer_common/sanitizer_stacktrace.cc b/libsanitizer/sanitizer_common/sanitizer_stacktrace.cc
index e14ea447264..4e7972424dc 100644
--- a/libsanitizer/sanitizer_common/sanitizer_stacktrace.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_stacktrace.cc
@@ -18,8 +18,9 @@ namespace __sanitizer {
const char *StripPathPrefix(const char *filepath,
const char *strip_file_prefix) {
if (filepath == 0) return 0;
- if (filepath == internal_strstr(filepath, strip_file_prefix))
- return filepath + internal_strlen(strip_file_prefix);
+ const char *prefix_beg = internal_strstr(filepath, strip_file_prefix);
+ if (prefix_beg)
+ return prefix_beg + internal_strlen(strip_file_prefix);
return filepath;
}
@@ -62,7 +63,7 @@ static void PrintModuleAndOffset(const char *module, uptr offset,
void StackTrace::PrintStack(const uptr *addr, uptr size,
bool symbolize, const char *strip_file_prefix,
SymbolizeCallback symbolize_callback ) {
- MemoryMappingLayout proc_maps;
+ MemoryMappingLayout proc_maps(/*cache_enabled*/true);
InternalScopedBuffer<char> buff(GetPageSizeCached() * 2);
InternalScopedBuffer<AddressInfo> addr_frames(64);
uptr frame_num = 0;
@@ -83,10 +84,10 @@ void StackTrace::PrintStack(const uptr *addr, uptr size,
frame_num++;
}
}
- if (symbolize && addr_frames_num == 0) {
+ if (symbolize && addr_frames_num == 0 && &getSymbolizer) {
// Use our own (online) symbolizer, if necessary.
- addr_frames_num = SymbolizeCode(pc, addr_frames.data(),
- addr_frames.size());
+ addr_frames_num = getSymbolizer()->SymbolizeCode(
+ pc, addr_frames.data(), addr_frames.size());
for (uptr j = 0; j < addr_frames_num; j++) {
AddressInfo &info = addr_frames[j];
PrintStackFramePrefix(frame_num, pc);
@@ -111,7 +112,8 @@ void StackTrace::PrintStack(const uptr *addr, uptr size,
PrintStackFramePrefix(frame_num, pc);
uptr offset;
if (proc_maps.GetObjectNameAndOffset(pc, &offset,
- buff.data(), buff.size())) {
+ buff.data(), buff.size(),
+ /* protection */0)) {
PrintModuleAndOffset(buff.data(), offset, strip_file_prefix);
}
Printf("\n");
@@ -130,10 +132,12 @@ void StackTrace::FastUnwindStack(uptr pc, uptr bp,
size = 1;
uhwptr *frame = (uhwptr *)bp;
uhwptr *prev_frame = frame - 1;
+ if (stack_top < 4096) return; // Sanity check for stack top.
// Avoid infinite loop when frame == frame[0] by using frame > prev_frame.
while (frame > prev_frame &&
frame < (uhwptr *)stack_top - 2 &&
frame > (uhwptr *)stack_bottom &&
+ IsAligned((uptr)frame, sizeof(*frame)) &&
size < max_size) {
uhwptr pc1 = frame[1];
if (pc1 != pc) {
diff --git a/libsanitizer/sanitizer_common/sanitizer_stacktrace.h b/libsanitizer/sanitizer_common/sanitizer_stacktrace.h
index fd0c4671a61..1f05753d207 100644
--- a/libsanitizer/sanitizer_common/sanitizer_stacktrace.h
+++ b/libsanitizer/sanitizer_common/sanitizer_stacktrace.h
@@ -17,6 +17,15 @@ namespace __sanitizer {
static const uptr kStackTraceMax = 256;
+#if SANITIZER_LINUX && (defined(__arm__) || \
+ defined(__powerpc__) || defined(__powerpc64__) || \
+ defined(__sparc__) || \
+ defined(__mips__))
+#define SANITIZER_CAN_FAST_UNWIND 0
+#else
+#define SANITIZER_CAN_FAST_UNWIND 1
+#endif
+
struct StackTrace {
typedef bool (*SymbolizeCallback)(const void *pc, char *out_buffer,
int out_size);
@@ -49,8 +58,10 @@ struct StackTrace {
static uptr GetCurrentPc();
static uptr GetPreviousInstructionPc(uptr pc);
+ SANITIZER_INTERFACE_ATTRIBUTE
static uptr CompressStack(StackTrace *stack,
u32 *compressed, uptr size);
+ SANITIZER_INTERFACE_ATTRIBUTE
static void UncompressStack(StackTrace *stack,
u32 *compressed, uptr size);
};
@@ -59,6 +70,9 @@ struct StackTrace {
const char *StripPathPrefix(const char *filepath,
const char *strip_file_prefix);
+void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp,
+ uptr stack_top, uptr stack_bottom, bool fast);
+
} // namespace __sanitizer
// Use this macro if you want to print stack trace with the caller
diff --git a/libsanitizer/sanitizer_common/sanitizer_stoptheworld.h b/libsanitizer/sanitizer_common/sanitizer_stoptheworld.h
new file mode 100644
index 00000000000..b1241da1f73
--- /dev/null
+++ b/libsanitizer/sanitizer_common/sanitizer_stoptheworld.h
@@ -0,0 +1,66 @@
+//===-- sanitizer_stoptheworld.h --------------------------------*- C++ -*-===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines the StopTheWorld function which suspends the execution of the current
+// process and runs the user-supplied callback in the same address space.
+//
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_STOPTHEWORLD_H
+#define SANITIZER_STOPTHEWORLD_H
+
+#include "sanitizer_internal_defs.h"
+#include "sanitizer_common.h"
+
+namespace __sanitizer {
+typedef int SuspendedThreadID;
+
+// Holds the list of suspended threads and provides an interface to dump their
+// register contexts.
+class SuspendedThreadsList {
+ public:
+ SuspendedThreadsList()
+ : thread_ids_(1024) {}
+ SuspendedThreadID GetThreadID(uptr index) const {
+ CHECK_LT(index, thread_ids_.size());
+ return thread_ids_[index];
+ }
+ int GetRegistersAndSP(uptr index, uptr *buffer, uptr *sp) const;
+ // The buffer in GetRegistersAndSP should be at least this big.
+ static uptr RegisterCount();
+ uptr thread_count() const { return thread_ids_.size(); }
+ bool Contains(SuspendedThreadID thread_id) const {
+ for (uptr i = 0; i < thread_ids_.size(); i++) {
+ if (thread_ids_[i] == thread_id)
+ return true;
+ }
+ return false;
+ }
+ void Append(SuspendedThreadID thread_id) {
+ thread_ids_.push_back(thread_id);
+ }
+
+ private:
+ InternalMmapVector<SuspendedThreadID> thread_ids_;
+
+ // Prohibit copy and assign.
+ SuspendedThreadsList(const SuspendedThreadsList&);
+ void operator=(const SuspendedThreadsList&);
+};
+
+typedef void (*StopTheWorldCallback)(
+ const SuspendedThreadsList &suspended_threads_list,
+ void *argument);
+
+// Suspend all threads in the current process and run the callback on the list
+// of suspended threads. This function will resume the threads before returning.
+// The callback should not call any libc functions.
+// This function should NOT be called from multiple threads simultaneously.
+void StopTheWorld(StopTheWorldCallback callback, void *argument);
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_STOPTHEWORLD_H
diff --git a/libsanitizer/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc b/libsanitizer/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc
new file mode 100644
index 00000000000..4f44a036982
--- /dev/null
+++ b/libsanitizer/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc
@@ -0,0 +1,450 @@
+//===-- sanitizer_stoptheworld_linux_libcdep.cc ---------------------------===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// See sanitizer_stoptheworld.h for details.
+// This implementation was inspired by Markus Gutschke's linuxthreads.cc.
+//
+//===----------------------------------------------------------------------===//
+
+
+#include "sanitizer_platform.h"
+#if SANITIZER_LINUX && defined(__x86_64__)
+
+#include "sanitizer_stoptheworld.h"
+
+#include <errno.h>
+#include <sched.h> // for CLONE_* definitions
+#include <stddef.h>
+#include <sys/prctl.h> // for PR_* definitions
+#include <sys/ptrace.h> // for PTRACE_* definitions
+#include <sys/types.h> // for pid_t
+#if SANITIZER_ANDROID && defined(__arm__)
+# include <linux/user.h> // for pt_regs
+#else
+# include <sys/user.h> // for user_regs_struct
+#endif
+#include <sys/wait.h> // for signal-related stuff
+
+#include "sanitizer_common.h"
+#include "sanitizer_libc.h"
+#include "sanitizer_linux.h"
+#include "sanitizer_mutex.h"
+#include "sanitizer_placement_new.h"
+
+// This module works by spawning a Linux task which then attaches to every
+// thread in the caller process with ptrace. This suspends the threads, and
+// PTRACE_GETREGS can then be used to obtain their register state. The callback
+// supplied to StopTheWorld() is run in the tracer task while the threads are
+// suspended.
+// The tracer task must be placed in a different thread group for ptrace to
+// work, so it cannot be spawned as a pthread. Instead, we use the low-level
+// clone() interface (we want to share the address space with the caller
+// process, so we prefer clone() over fork()).
+//
+// We avoid the use of libc for two reasons:
+// 1. calling a library function while threads are suspended could cause a
+// deadlock, if one of the treads happens to be holding a libc lock;
+// 2. it's generally not safe to call libc functions from the tracer task,
+// because clone() does not set up a thread-local storage for it. Any
+// thread-local variables used by libc will be shared between the tracer task
+// and the thread which spawned it.
+//
+// We deal with this by replacing libc calls with calls to our own
+// implementations defined in sanitizer_libc.h and sanitizer_linux.h. However,
+// there are still some libc functions which are used here:
+//
+// * All of the system calls ultimately go through the libc syscall() function.
+// We're operating under the assumption that syscall()'s implementation does
+// not acquire any locks or use any thread-local data (except for the errno
+// variable, which we handle separately).
+//
+// * We lack custom implementations of sigfillset() and sigaction(), so we use
+// the libc versions instead. The same assumptions as above apply.
+//
+// * It is safe to call libc functions before the cloned thread is spawned or
+// after it has exited. The following functions are used in this manner:
+// sigdelset()
+// sigprocmask()
+
+COMPILER_CHECK(sizeof(SuspendedThreadID) == sizeof(pid_t));
+
+namespace __sanitizer {
+// This class handles thread suspending/unsuspending in the tracer thread.
+class ThreadSuspender {
+ public:
+ explicit ThreadSuspender(pid_t pid)
+ : pid_(pid) {
+ CHECK_GE(pid, 0);
+ }
+ bool SuspendAllThreads();
+ void ResumeAllThreads();
+ void KillAllThreads();
+ SuspendedThreadsList &suspended_threads_list() {
+ return suspended_threads_list_;
+ }
+ private:
+ SuspendedThreadsList suspended_threads_list_;
+ pid_t pid_;
+ bool SuspendThread(SuspendedThreadID thread_id);
+};
+
+bool ThreadSuspender::SuspendThread(SuspendedThreadID thread_id) {
+ // Are we already attached to this thread?
+ // Currently this check takes linear time, however the number of threads is
+ // usually small.
+ if (suspended_threads_list_.Contains(thread_id))
+ return false;
+ int pterrno;
+ if (internal_iserror(internal_ptrace(PTRACE_ATTACH, thread_id, NULL, NULL),
+ &pterrno)) {
+ // Either the thread is dead, or something prevented us from attaching.
+ // Log this event and move on.
+ Report("Could not attach to thread %d (errno %d).\n", thread_id, pterrno);
+ return false;
+ } else {
+ if (SanitizerVerbosity > 0)
+ Report("Attached to thread %d.\n", thread_id);
+ // The thread is not guaranteed to stop before ptrace returns, so we must
+ // wait on it.
+ uptr waitpid_status;
+ HANDLE_EINTR(waitpid_status, internal_waitpid(thread_id, NULL, __WALL));
+ int wperrno;
+ if (internal_iserror(waitpid_status, &wperrno)) {
+ // Got a ECHILD error. I don't think this situation is possible, but it
+ // doesn't hurt to report it.
+ Report("Waiting on thread %d failed, detaching (errno %d).\n", thread_id,
+ wperrno);
+ internal_ptrace(PTRACE_DETACH, thread_id, NULL, NULL);
+ return false;
+ }
+ suspended_threads_list_.Append(thread_id);
+ return true;
+ }
+}
+
+void ThreadSuspender::ResumeAllThreads() {
+ for (uptr i = 0; i < suspended_threads_list_.thread_count(); i++) {
+ pid_t tid = suspended_threads_list_.GetThreadID(i);
+ int pterrno;
+ if (!internal_iserror(internal_ptrace(PTRACE_DETACH, tid, NULL, NULL),
+ &pterrno)) {
+ if (SanitizerVerbosity > 0)
+ Report("Detached from thread %d.\n", tid);
+ } else {
+ // Either the thread is dead, or we are already detached.
+ // The latter case is possible, for instance, if this function was called
+ // from a signal handler.
+ Report("Could not detach from thread %d (errno %d).\n", tid, pterrno);
+ }
+ }
+}
+
+void ThreadSuspender::KillAllThreads() {
+ for (uptr i = 0; i < suspended_threads_list_.thread_count(); i++)
+ internal_ptrace(PTRACE_KILL, suspended_threads_list_.GetThreadID(i),
+ NULL, NULL);
+}
+
+bool ThreadSuspender::SuspendAllThreads() {
+ ThreadLister thread_lister(pid_);
+ bool added_threads;
+ do {
+ // Run through the directory entries once.
+ added_threads = false;
+ pid_t tid = thread_lister.GetNextTID();
+ while (tid >= 0) {
+ if (SuspendThread(tid))
+ added_threads = true;
+ tid = thread_lister.GetNextTID();
+ }
+ if (thread_lister.error()) {
+ // Detach threads and fail.
+ ResumeAllThreads();
+ return false;
+ }
+ thread_lister.Reset();
+ } while (added_threads);
+ return true;
+}
+
+// Pointer to the ThreadSuspender instance for use in signal handler.
+static ThreadSuspender *thread_suspender_instance = NULL;
+
+// Signals that should not be blocked (this is used in the parent thread as well
+// as the tracer thread).
+static const int kUnblockedSignals[] = { SIGABRT, SIGILL, SIGFPE, SIGSEGV,
+ SIGBUS, SIGXCPU, SIGXFSZ };
+
+// Structure for passing arguments into the tracer thread.
+struct TracerThreadArgument {
+ StopTheWorldCallback callback;
+ void *callback_argument;
+ // The tracer thread waits on this mutex while the parent finished its
+ // preparations.
+ BlockingMutex mutex;
+};
+
+static DieCallbackType old_die_callback;
+
+// Signal handler to wake up suspended threads when the tracer thread dies.
+void TracerThreadSignalHandler(int signum, siginfo_t *siginfo, void *) {
+ if (thread_suspender_instance != NULL) {
+ if (signum == SIGABRT)
+ thread_suspender_instance->KillAllThreads();
+ else
+ thread_suspender_instance->ResumeAllThreads();
+ }
+ internal__exit((signum == SIGABRT) ? 1 : 2);
+}
+
+static void TracerThreadDieCallback() {
+ // Generally a call to Die() in the tracer thread should be fatal to the
+ // parent process as well, because they share the address space.
+ // This really only works correctly if all the threads are suspended at this
+ // point. So we correctly handle calls to Die() from within the callback, but
+ // not those that happen before or after the callback. Hopefully there aren't
+ // a lot of opportunities for that to happen...
+ if (thread_suspender_instance)
+ thread_suspender_instance->KillAllThreads();
+ if (old_die_callback)
+ old_die_callback();
+}
+
+// Size of alternative stack for signal handlers in the tracer thread.
+static const int kHandlerStackSize = 4096;
+
+// This function will be run as a cloned task.
+static int TracerThread(void* argument) {
+ TracerThreadArgument *tracer_thread_argument =
+ (TracerThreadArgument *)argument;
+
+ // Wait for the parent thread to finish preparations.
+ tracer_thread_argument->mutex.Lock();
+ tracer_thread_argument->mutex.Unlock();
+
+ SetDieCallback(TracerThreadDieCallback);
+
+ ThreadSuspender thread_suspender(internal_getppid());
+ // Global pointer for the signal handler.
+ thread_suspender_instance = &thread_suspender;
+
+ // Alternate stack for signal handling.
+ InternalScopedBuffer<char> handler_stack_memory(kHandlerStackSize);
+ struct sigaltstack handler_stack;
+ internal_memset(&handler_stack, 0, sizeof(handler_stack));
+ handler_stack.ss_sp = handler_stack_memory.data();
+ handler_stack.ss_size = kHandlerStackSize;
+ internal_sigaltstack(&handler_stack, NULL);
+
+ // Install our handler for fatal signals. Other signals should be blocked by
+ // the mask we inherited from the caller thread.
+ for (uptr signal_index = 0; signal_index < ARRAY_SIZE(kUnblockedSignals);
+ signal_index++) {
+ struct sigaction new_sigaction;
+ internal_memset(&new_sigaction, 0, sizeof(new_sigaction));
+ new_sigaction.sa_sigaction = TracerThreadSignalHandler;
+ new_sigaction.sa_flags = SA_ONSTACK | SA_SIGINFO;
+ sigfillset(&new_sigaction.sa_mask);
+ sigaction(kUnblockedSignals[signal_index], &new_sigaction, NULL);
+ }
+
+ int exit_code = 0;
+ if (!thread_suspender.SuspendAllThreads()) {
+ Report("Failed suspending threads.\n");
+ exit_code = 3;
+ } else {
+ tracer_thread_argument->callback(thread_suspender.suspended_threads_list(),
+ tracer_thread_argument->callback_argument);
+ thread_suspender.ResumeAllThreads();
+ exit_code = 0;
+ }
+ thread_suspender_instance = NULL;
+ handler_stack.ss_flags = SS_DISABLE;
+ internal_sigaltstack(&handler_stack, NULL);
+ return exit_code;
+}
+
+class ScopedStackSpaceWithGuard {
+ public:
+ explicit ScopedStackSpaceWithGuard(uptr stack_size) {
+ stack_size_ = stack_size;
+ guard_size_ = GetPageSizeCached();
+ // FIXME: Omitting MAP_STACK here works in current kernels but might break
+ // in the future.
+ guard_start_ = (uptr)MmapOrDie(stack_size_ + guard_size_,
+ "ScopedStackWithGuard");
+ CHECK_EQ(guard_start_, (uptr)Mprotect((uptr)guard_start_, guard_size_));
+ }
+ ~ScopedStackSpaceWithGuard() {
+ UnmapOrDie((void *)guard_start_, stack_size_ + guard_size_);
+ }
+ void *Bottom() const {
+ return (void *)(guard_start_ + stack_size_ + guard_size_);
+ }
+
+ private:
+ uptr stack_size_;
+ uptr guard_size_;
+ uptr guard_start_;
+};
+
+NOINLINE static void WipeStack() {
+ char arr[256];
+ internal_memset(arr, 0, sizeof(arr));
+}
+
+// We have a limitation on the stack frame size, so some stuff had to be moved
+// into globals.
+static sigset_t blocked_sigset;
+static sigset_t old_sigset;
+static struct sigaction old_sigactions[ARRAY_SIZE(kUnblockedSignals)];
+
+class StopTheWorldScope {
+ public:
+ StopTheWorldScope() {
+ // Glibc's sigaction() has a side-effect where it copies garbage stack
+ // values into oldact, which can cause false negatives in LSan. As a quick
+ // workaround we zero some stack space here.
+ WipeStack();
+ // Block all signals that can be blocked safely, and install
+ // default handlers for the remaining signals.
+ // We cannot allow user-defined handlers to run while the ThreadSuspender
+ // thread is active, because they could conceivably call some libc functions
+ // which modify errno (which is shared between the two threads).
+ sigfillset(&blocked_sigset);
+ for (uptr signal_index = 0; signal_index < ARRAY_SIZE(kUnblockedSignals);
+ signal_index++) {
+ // Remove the signal from the set of blocked signals.
+ sigdelset(&blocked_sigset, kUnblockedSignals[signal_index]);
+ // Install the default handler.
+ struct sigaction new_sigaction;
+ internal_memset(&new_sigaction, 0, sizeof(new_sigaction));
+ new_sigaction.sa_handler = SIG_DFL;
+ sigfillset(&new_sigaction.sa_mask);
+ sigaction(kUnblockedSignals[signal_index], &new_sigaction,
+ &old_sigactions[signal_index]);
+ }
+ int sigprocmask_status =
+ sigprocmask(SIG_BLOCK, &blocked_sigset, &old_sigset);
+ CHECK_EQ(sigprocmask_status, 0); // sigprocmask should never fail
+ // Make this process dumpable. Processes that are not dumpable cannot be
+ // attached to.
+ process_was_dumpable_ = internal_prctl(PR_GET_DUMPABLE, 0, 0, 0, 0);
+ if (!process_was_dumpable_)
+ internal_prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
+ old_die_callback = GetDieCallback();
+ }
+
+ ~StopTheWorldScope() {
+ SetDieCallback(old_die_callback);
+ // Restore the dumpable flag.
+ if (!process_was_dumpable_)
+ internal_prctl(PR_SET_DUMPABLE, 0, 0, 0, 0);
+ // Restore the signal handlers.
+ for (uptr signal_index = 0; signal_index < ARRAY_SIZE(kUnblockedSignals);
+ signal_index++) {
+ sigaction(kUnblockedSignals[signal_index],
+ &old_sigactions[signal_index], NULL);
+ }
+ sigprocmask(SIG_SETMASK, &old_sigset, &old_sigset);
+ }
+
+ private:
+ int process_was_dumpable_;
+};
+
+void StopTheWorld(StopTheWorldCallback callback, void *argument) {
+ StopTheWorldScope in_stoptheworld;
+ // Prepare the arguments for TracerThread.
+ struct TracerThreadArgument tracer_thread_argument;
+ tracer_thread_argument.callback = callback;
+ tracer_thread_argument.callback_argument = argument;
+ const uptr kTracerStackSize = 2 * 1024 * 1024;
+ ScopedStackSpaceWithGuard tracer_stack(kTracerStackSize);
+ // Block the execution of TracerThread until after we have set ptrace
+ // permissions.
+ tracer_thread_argument.mutex.Lock();
+ uptr tracer_pid = internal_clone(
+ TracerThread, tracer_stack.Bottom(),
+ CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_UNTRACED,
+ &tracer_thread_argument, 0 /* parent_tidptr */, 0 /* newtls */, 0
+ /* child_tidptr */);
+ int local_errno = 0;
+ if (internal_iserror(tracer_pid, &local_errno)) {
+ Report("Failed spawning a tracer thread (errno %d).\n", local_errno);
+ tracer_thread_argument.mutex.Unlock();
+ } else {
+ // On some systems we have to explicitly declare that we want to be traced
+ // by the tracer thread.
+#ifdef PR_SET_PTRACER
+ internal_prctl(PR_SET_PTRACER, tracer_pid, 0, 0, 0);
+#endif
+ // Allow the tracer thread to start.
+ tracer_thread_argument.mutex.Unlock();
+ // Since errno is shared between this thread and the tracer thread, we
+ // must avoid using errno while the tracer thread is running.
+ // At this point, any signal will either be blocked or kill us, so waitpid
+ // should never return (and set errno) while the tracer thread is alive.
+ uptr waitpid_status = internal_waitpid(tracer_pid, NULL, __WALL);
+ if (internal_iserror(waitpid_status, &local_errno))
+ Report("Waiting on the tracer thread failed (errno %d).\n", local_errno);
+ }
+}
+
+// Platform-specific methods from SuspendedThreadsList.
+#if SANITIZER_ANDROID && defined(__arm__)
+typedef pt_regs regs_struct;
+#define REG_SP ARM_sp
+
+#elif SANITIZER_LINUX && defined(__arm__)
+typedef user_regs regs_struct;
+#define REG_SP uregs[13]
+
+#elif defined(__i386__) || defined(__x86_64__)
+typedef user_regs_struct regs_struct;
+#if defined(__i386__)
+#define REG_SP esp
+#else
+#define REG_SP rsp
+#endif
+
+#elif defined(__powerpc__) || defined(__powerpc64__)
+typedef pt_regs regs_struct;
+#define REG_SP gpr[PT_R1]
+
+#elif defined(__mips__)
+typedef struct user regs_struct;
+#define REG_SP regs[EF_REG29]
+
+#else
+#error "Unsupported architecture"
+#endif // SANITIZER_ANDROID && defined(__arm__)
+
+int SuspendedThreadsList::GetRegistersAndSP(uptr index,
+ uptr *buffer,
+ uptr *sp) const {
+ pid_t tid = GetThreadID(index);
+ regs_struct regs;
+ int pterrno;
+ if (internal_iserror(internal_ptrace(PTRACE_GETREGS, tid, NULL, &regs),
+ &pterrno)) {
+ Report("Could not get registers from thread %d (errno %d).\n",
+ tid, pterrno);
+ return -1;
+ }
+
+ *sp = regs.REG_SP;
+ internal_memcpy(buffer, &regs, sizeof(regs));
+ return 0;
+}
+
+uptr SuspendedThreadsList::RegisterCount() {
+ return sizeof(regs_struct) / sizeof(uptr);
+}
+} // namespace __sanitizer
+
+#endif // SANITIZER_LINUX && defined(__x86_64__)
diff --git a/libsanitizer/sanitizer_common/sanitizer_suppressions.cc b/libsanitizer/sanitizer_common/sanitizer_suppressions.cc
new file mode 100644
index 00000000000..d8e8976a4b2
--- /dev/null
+++ b/libsanitizer/sanitizer_common/sanitizer_suppressions.cc
@@ -0,0 +1,146 @@
+//===-- sanitizer_suppressions.cc -----------------------------------------===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Suppression parsing/matching code shared between TSan and LSan.
+//
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_suppressions.h"
+
+#include "sanitizer_allocator_internal.h"
+#include "sanitizer_common.h"
+#include "sanitizer_libc.h"
+
+namespace __sanitizer {
+
+static const char *const kTypeStrings[SuppressionTypeCount] = {
+ "none", "race", "mutex", "thread", "signal", "leak"
+};
+
+bool TemplateMatch(char *templ, const char *str) {
+ if (str == 0 || str[0] == 0)
+ return false;
+ bool start = false;
+ if (templ && templ[0] == '^') {
+ start = true;
+ templ++;
+ }
+ bool asterisk = false;
+ while (templ && templ[0]) {
+ if (templ[0] == '*') {
+ templ++;
+ start = false;
+ asterisk = true;
+ continue;
+ }
+ if (templ[0] == '$')
+ return str[0] == 0 || asterisk;
+ if (str[0] == 0)
+ return false;
+ char *tpos = (char*)internal_strchr(templ, '*');
+ char *tpos1 = (char*)internal_strchr(templ, '$');
+ if (tpos == 0 || (tpos1 && tpos1 < tpos))
+ tpos = tpos1;
+ if (tpos != 0)
+ tpos[0] = 0;
+ const char *str0 = str;
+ const char *spos = internal_strstr(str, templ);
+ str = spos + internal_strlen(templ);
+ templ = tpos;
+ if (tpos)
+ tpos[0] = tpos == tpos1 ? '$' : '*';
+ if (spos == 0)
+ return false;
+ if (start && spos != str0)
+ return false;
+ start = false;
+ asterisk = false;
+ }
+ return true;
+}
+
+bool SuppressionContext::Match(const char *str, SuppressionType type,
+ Suppression **s) {
+ can_parse_ = false;
+ uptr i;
+ for (i = 0; i < suppressions_.size(); i++)
+ if (type == suppressions_[i].type &&
+ TemplateMatch(suppressions_[i].templ, str))
+ break;
+ if (i == suppressions_.size()) return false;
+ *s = &suppressions_[i];
+ return true;
+}
+
+static const char *StripPrefix(const char *str, const char *prefix) {
+ while (str && *str == *prefix) {
+ str++;
+ prefix++;
+ }
+ if (!*prefix)
+ return str;
+ return 0;
+}
+
+void SuppressionContext::Parse(const char *str) {
+ // Context must not mutate once Match has been called.
+ CHECK(can_parse_);
+ const char *line = str;
+ while (line) {
+ while (line[0] == ' ' || line[0] == '\t')
+ line++;
+ const char *end = internal_strchr(line, '\n');
+ if (end == 0)
+ end = line + internal_strlen(line);
+ if (line != end && line[0] != '#') {
+ const char *end2 = end;
+ while (line != end2 && (end2[-1] == ' ' || end2[-1] == '\t'))
+ end2--;
+ int type;
+ for (type = 0; type < SuppressionTypeCount; type++) {
+ const char *next_char = StripPrefix(line, kTypeStrings[type]);
+ if (next_char && *next_char == ':') {
+ line = ++next_char;
+ break;
+ }
+ }
+ if (type == SuppressionTypeCount) {
+ Printf("%s: failed to parse suppressions\n", SanitizerToolName);
+ Die();
+ }
+ Suppression s;
+ s.type = static_cast<SuppressionType>(type);
+ s.templ = (char*)InternalAlloc(end2 - line + 1);
+ internal_memcpy(s.templ, line, end2 - line);
+ s.templ[end2 - line] = 0;
+ s.hit_count = 0;
+ s.weight = 0;
+ suppressions_.push_back(s);
+ }
+ if (end[0] == 0)
+ break;
+ line = end + 1;
+ }
+}
+
+uptr SuppressionContext::SuppressionCount() {
+ return suppressions_.size();
+}
+
+void SuppressionContext::GetMatched(
+ InternalMmapVector<Suppression *> *matched) {
+ for (uptr i = 0; i < suppressions_.size(); i++)
+ if (suppressions_[i].hit_count)
+ matched->push_back(&suppressions_[i]);
+}
+
+const char *SuppressionTypeString(SuppressionType t) {
+ CHECK(t < SuppressionTypeCount);
+ return kTypeStrings[t];
+}
+
+} // namespace __sanitizer
diff --git a/libsanitizer/sanitizer_common/sanitizer_suppressions.h b/libsanitizer/sanitizer_common/sanitizer_suppressions.h
new file mode 100644
index 00000000000..9a0d87b383e
--- /dev/null
+++ b/libsanitizer/sanitizer_common/sanitizer_suppressions.h
@@ -0,0 +1,58 @@
+//===-- sanitizer_suppressions.h --------------------------------*- C++ -*-===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Suppression parsing/matching code shared between TSan and LSan.
+//
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_SUPPRESSIONS_H
+#define SANITIZER_SUPPRESSIONS_H
+
+#include "sanitizer_common.h"
+#include "sanitizer_internal_defs.h"
+
+namespace __sanitizer {
+
+enum SuppressionType {
+ SuppressionNone,
+ SuppressionRace,
+ SuppressionMutex,
+ SuppressionThread,
+ SuppressionSignal,
+ SuppressionLeak,
+ SuppressionTypeCount
+};
+
+struct Suppression {
+ SuppressionType type;
+ char *templ;
+ unsigned hit_count;
+ uptr weight;
+};
+
+class SuppressionContext {
+ public:
+ SuppressionContext() : suppressions_(1), can_parse_(true) {}
+ void Parse(const char *str);
+ bool Match(const char* str, SuppressionType type, Suppression **s);
+ uptr SuppressionCount();
+ void GetMatched(InternalMmapVector<Suppression *> *matched);
+
+ private:
+ InternalMmapVector<Suppression> suppressions_;
+ bool can_parse_;
+
+ friend class SuppressionContextTest;
+};
+
+const char *SuppressionTypeString(SuppressionType t);
+
+// Exposed for testing.
+bool TemplateMatch(char *templ, const char *str);
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_SUPPRESSIONS_H
diff --git a/libsanitizer/sanitizer_common/sanitizer_symbolizer.cc b/libsanitizer/sanitizer_common/sanitizer_symbolizer.cc
deleted file mode 100644
index 2c9cb2b0a55..00000000000
--- a/libsanitizer/sanitizer_common/sanitizer_symbolizer.cc
+++ /dev/null
@@ -1,408 +0,0 @@
-//===-- sanitizer_symbolizer.cc -------------------------------------------===//
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file is shared between AddressSanitizer and ThreadSanitizer
-// run-time libraries. See sanitizer_symbolizer.h for details.
-//===----------------------------------------------------------------------===//
-
-#include "sanitizer_common.h"
-#include "sanitizer_placement_new.h"
-#include "sanitizer_procmaps.h"
-#include "sanitizer_symbolizer.h"
-
-namespace __sanitizer {
-
-void AddressInfo::Clear() {
- InternalFree(module);
- InternalFree(function);
- InternalFree(file);
- internal_memset(this, 0, sizeof(AddressInfo));
-}
-
-LoadedModule::LoadedModule(const char *module_name, uptr base_address) {
- full_name_ = internal_strdup(module_name);
- base_address_ = base_address;
- n_ranges_ = 0;
-}
-
-void LoadedModule::addAddressRange(uptr beg, uptr end) {
- CHECK_LT(n_ranges_, kMaxNumberOfAddressRanges);
- ranges_[n_ranges_].beg = beg;
- ranges_[n_ranges_].end = end;
- n_ranges_++;
-}
-
-bool LoadedModule::containsAddress(uptr address) const {
- for (uptr i = 0; i < n_ranges_; i++) {
- if (ranges_[i].beg <= address && address < ranges_[i].end)
- return true;
- }
- return false;
-}
-
-// Extracts the prefix of "str" that consists of any characters not
-// present in "delims" string, and copies this prefix to "result", allocating
-// space for it.
-// Returns a pointer to "str" after skipping extracted prefix and first
-// delimiter char.
-static const char *ExtractToken(const char *str, const char *delims,
- char **result) {
- uptr prefix_len = internal_strcspn(str, delims);
- *result = (char*)InternalAlloc(prefix_len + 1);
- internal_memcpy(*result, str, prefix_len);
- (*result)[prefix_len] = '\0';
- const char *prefix_end = str + prefix_len;
- if (*prefix_end != '\0') prefix_end++;
- return prefix_end;
-}
-
-// Same as ExtractToken, but converts extracted token to integer.
-static const char *ExtractInt(const char *str, const char *delims,
- int *result) {
- char *buff;
- const char *ret = ExtractToken(str, delims, &buff);
- if (buff != 0) {
- *result = (int)internal_atoll(buff);
- }
- InternalFree(buff);
- return ret;
-}
-
-static const char *ExtractUptr(const char *str, const char *delims,
- uptr *result) {
- char *buff;
- const char *ret = ExtractToken(str, delims, &buff);
- if (buff != 0) {
- *result = (uptr)internal_atoll(buff);
- }
- InternalFree(buff);
- return ret;
-}
-
-// ExternalSymbolizer encapsulates communication between the tool and
-// external symbolizer program, running in a different subprocess,
-// For now we assume the following protocol:
-// For each request of the form
-// <module_name> <module_offset>
-// passed to STDIN, external symbolizer prints to STDOUT response:
-// <function_name>
-// <file_name>:<line_number>:<column_number>
-// <function_name>
-// <file_name>:<line_number>:<column_number>
-// ...
-// <empty line>
-class ExternalSymbolizer {
- public:
- ExternalSymbolizer(const char *path, int input_fd, int output_fd)
- : path_(path),
- input_fd_(input_fd),
- output_fd_(output_fd),
- times_restarted_(0) {
- CHECK(path_);
- CHECK_NE(input_fd_, kInvalidFd);
- CHECK_NE(output_fd_, kInvalidFd);
- }
-
- char *SendCommand(bool is_data, const char *module_name, uptr module_offset) {
- CHECK(module_name);
- internal_snprintf(buffer_, kBufferSize, "%s%s 0x%zx\n",
- is_data ? "DATA " : "", module_name, module_offset);
- if (!writeToSymbolizer(buffer_, internal_strlen(buffer_)))
- return 0;
- if (!readFromSymbolizer(buffer_, kBufferSize))
- return 0;
- return buffer_;
- }
-
- bool Restart() {
- if (times_restarted_ >= kMaxTimesRestarted) return false;
- times_restarted_++;
- internal_close(input_fd_);
- internal_close(output_fd_);
- return StartSymbolizerSubprocess(path_, &input_fd_, &output_fd_);
- }
-
- private:
- bool readFromSymbolizer(char *buffer, uptr max_length) {
- if (max_length == 0)
- return true;
- uptr read_len = 0;
- while (true) {
- uptr just_read = internal_read(input_fd_, buffer + read_len,
- max_length - read_len);
- // We can't read 0 bytes, as we don't expect external symbolizer to close
- // its stdout.
- if (just_read == 0 || just_read == (uptr)-1) {
- Report("WARNING: Can't read from symbolizer at fd %d\n", input_fd_);
- return false;
- }
- read_len += just_read;
- // Empty line marks the end of symbolizer output.
- if (read_len >= 2 && buffer[read_len - 1] == '\n' &&
- buffer[read_len - 2] == '\n') {
- break;
- }
- }
- return true;
- }
-
- bool writeToSymbolizer(const char *buffer, uptr length) {
- if (length == 0)
- return true;
- uptr write_len = internal_write(output_fd_, buffer, length);
- if (write_len == 0 || write_len == (uptr)-1) {
- Report("WARNING: Can't write to symbolizer at fd %d\n", output_fd_);
- return false;
- }
- return true;
- }
-
- const char *path_;
- int input_fd_;
- int output_fd_;
-
- static const uptr kBufferSize = 16 * 1024;
- char buffer_[kBufferSize];
-
- static const uptr kMaxTimesRestarted = 5;
- uptr times_restarted_;
-};
-
-static LowLevelAllocator symbolizer_allocator; // Linker initialized.
-
-#if SANITIZER_SUPPORTS_WEAK_HOOKS
-extern "C" {
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
-bool __sanitizer_symbolize_code(const char *ModuleName, u64 ModuleOffset,
- char *Buffer, int MaxLength);
-SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
-bool __sanitizer_symbolize_data(const char *ModuleName, u64 ModuleOffset,
- char *Buffer, int MaxLength);
-} // extern "C"
-
-class InternalSymbolizer {
- public:
- typedef bool (*SanitizerSymbolizeFn)(const char*, u64, char*, int);
- static InternalSymbolizer *get() {
- if (__sanitizer_symbolize_code != 0 &&
- __sanitizer_symbolize_data != 0) {
- void *mem = symbolizer_allocator.Allocate(sizeof(InternalSymbolizer));
- return new(mem) InternalSymbolizer();
- }
- return 0;
- }
- char *SendCommand(bool is_data, const char *module_name, uptr module_offset) {
- SanitizerSymbolizeFn symbolize_fn = is_data ? __sanitizer_symbolize_data
- : __sanitizer_symbolize_code;
- if (symbolize_fn(module_name, module_offset, buffer_, kBufferSize))
- return buffer_;
- return 0;
- }
-
- private:
- InternalSymbolizer() { }
-
- static const int kBufferSize = 16 * 1024;
- char buffer_[kBufferSize];
-};
-#else // SANITIZER_SUPPORTS_WEAK_HOOKS
-
-class InternalSymbolizer {
- public:
- static InternalSymbolizer *get() { return 0; }
- char *SendCommand(bool is_data, const char *module_name, uptr module_offset) {
- return 0;
- }
-};
-
-#endif // SANITIZER_SUPPORTS_WEAK_HOOKS
-
-class Symbolizer {
- public:
- uptr SymbolizeCode(uptr addr, AddressInfo *frames, uptr max_frames) {
- if (max_frames == 0)
- return 0;
- LoadedModule *module = FindModuleForAddress(addr);
- if (module == 0)
- return 0;
- const char *module_name = module->full_name();
- uptr module_offset = addr - module->base_address();
- const char *str = SendCommand(false, module_name, module_offset);
- if (str == 0) {
- // External symbolizer was not initialized or failed. Fill only data
- // about module name and offset.
- AddressInfo *info = &frames[0];
- info->Clear();
- info->FillAddressAndModuleInfo(addr, module_name, module_offset);
- return 1;
- }
- uptr frame_id = 0;
- for (frame_id = 0; frame_id < max_frames; frame_id++) {
- AddressInfo *info = &frames[frame_id];
- char *function_name = 0;
- str = ExtractToken(str, "\n", &function_name);
- CHECK(function_name);
- if (function_name[0] == '\0') {
- // There are no more frames.
- break;
- }
- info->Clear();
- info->FillAddressAndModuleInfo(addr, module_name, module_offset);
- info->function = function_name;
- // Parse <file>:<line>:<column> buffer.
- char *file_line_info = 0;
- str = ExtractToken(str, "\n", &file_line_info);
- CHECK(file_line_info);
- const char *line_info = ExtractToken(file_line_info, ":", &info->file);
- line_info = ExtractInt(line_info, ":", &info->line);
- line_info = ExtractInt(line_info, "", &info->column);
- InternalFree(file_line_info);
-
- // Functions and filenames can be "??", in which case we write 0
- // to address info to mark that names are unknown.
- if (0 == internal_strcmp(info->function, "??")) {
- InternalFree(info->function);
- info->function = 0;
- }
- if (0 == internal_strcmp(info->file, "??")) {
- InternalFree(info->file);
- info->file = 0;
- }
- }
- if (frame_id == 0) {
- // Make sure we return at least one frame.
- AddressInfo *info = &frames[0];
- info->Clear();
- info->FillAddressAndModuleInfo(addr, module_name, module_offset);
- frame_id = 1;
- }
- return frame_id;
- }
-
- bool SymbolizeData(uptr addr, DataInfo *info) {
- LoadedModule *module = FindModuleForAddress(addr);
- if (module == 0)
- return false;
- const char *module_name = module->full_name();
- uptr module_offset = addr - module->base_address();
- internal_memset(info, 0, sizeof(*info));
- info->address = addr;
- info->module = internal_strdup(module_name);
- info->module_offset = module_offset;
- const char *str = SendCommand(true, module_name, module_offset);
- if (str == 0)
- return true;
- str = ExtractToken(str, "\n", &info->name);
- str = ExtractUptr(str, " ", &info->start);
- str = ExtractUptr(str, "\n", &info->size);
- info->start += module->base_address();
- return true;
- }
-
- bool InitializeExternalSymbolizer(const char *path_to_symbolizer) {
- int input_fd, output_fd;
- if (!StartSymbolizerSubprocess(path_to_symbolizer, &input_fd, &output_fd))
- return false;
- void *mem = symbolizer_allocator.Allocate(sizeof(ExternalSymbolizer));
- external_symbolizer_ = new(mem) ExternalSymbolizer(path_to_symbolizer,
- input_fd, output_fd);
- return true;
- }
-
- bool IsSymbolizerAvailable() {
- if (internal_symbolizer_ == 0)
- internal_symbolizer_ = InternalSymbolizer::get();
- return internal_symbolizer_ || external_symbolizer_;
- }
-
- private:
- char *SendCommand(bool is_data, const char *module_name, uptr module_offset) {
- // First, try to use internal symbolizer.
- if (internal_symbolizer_ == 0) {
- internal_symbolizer_ = InternalSymbolizer::get();
- }
- if (internal_symbolizer_) {
- return internal_symbolizer_->SendCommand(is_data, module_name,
- module_offset);
- }
- // Otherwise, fall back to external symbolizer.
- if (external_symbolizer_ == 0) {
- ReportExternalSymbolizerError(
- "WARNING: Trying to symbolize code, but external "
- "symbolizer is not initialized!\n");
- return 0;
- }
- for (;;) {
- char *reply = external_symbolizer_->SendCommand(is_data, module_name,
- module_offset);
- if (reply)
- return reply;
- // Try to restart symbolizer subprocess. If we don't succeed, forget
- // about it and don't try to use it later.
- if (!external_symbolizer_->Restart()) {
- ReportExternalSymbolizerError(
- "WARNING: Failed to use and restart external symbolizer!\n");
- external_symbolizer_ = 0;
- return 0;
- }
- }
- }
-
- LoadedModule *FindModuleForAddress(uptr address) {
- if (modules_ == 0) {
- modules_ = (LoadedModule*)(symbolizer_allocator.Allocate(
- kMaxNumberOfModuleContexts * sizeof(LoadedModule)));
- CHECK(modules_);
- n_modules_ = GetListOfModules(modules_, kMaxNumberOfModuleContexts);
- CHECK_GT(n_modules_, 0);
- CHECK_LT(n_modules_, kMaxNumberOfModuleContexts);
- }
- for (uptr i = 0; i < n_modules_; i++) {
- if (modules_[i].containsAddress(address)) {
- return &modules_[i];
- }
- }
- return 0;
- }
- void ReportExternalSymbolizerError(const char *msg) {
- // Don't use atomics here for now, as SymbolizeCode can't be called
- // from multiple threads anyway.
- static bool reported;
- if (!reported) {
- Report(msg);
- reported = true;
- }
- }
-
- // 16K loaded modules should be enough for everyone.
- static const uptr kMaxNumberOfModuleContexts = 1 << 14;
- LoadedModule *modules_; // Array of module descriptions is leaked.
- uptr n_modules_;
-
- ExternalSymbolizer *external_symbolizer_; // Leaked.
- InternalSymbolizer *internal_symbolizer_; // Leaked.
-};
-
-static Symbolizer symbolizer; // Linker initialized.
-
-uptr SymbolizeCode(uptr address, AddressInfo *frames, uptr max_frames) {
- return symbolizer.SymbolizeCode(address, frames, max_frames);
-}
-
-bool SymbolizeData(uptr address, DataInfo *info) {
- return symbolizer.SymbolizeData(address, info);
-}
-
-bool InitializeExternalSymbolizer(const char *path_to_symbolizer) {
- return symbolizer.InitializeExternalSymbolizer(path_to_symbolizer);
-}
-
-bool IsSymbolizerAvailable() {
- return symbolizer.IsSymbolizerAvailable();
-}
-
-} // namespace __sanitizer
diff --git a/libsanitizer/sanitizer_common/sanitizer_symbolizer.h b/libsanitizer/sanitizer_common/sanitizer_symbolizer.h
index 751806e8472..2c84773eebc 100644
--- a/libsanitizer/sanitizer_common/sanitizer_symbolizer.h
+++ b/libsanitizer/sanitizer_common/sanitizer_symbolizer.h
@@ -22,6 +22,7 @@
#ifndef SANITIZER_SYMBOLIZER_H
#define SANITIZER_SYMBOLIZER_H
+#include "sanitizer_allocator_internal.h"
#include "sanitizer_internal_defs.h"
#include "sanitizer_libc.h"
// WARNING: Do not include system headers here. See details above.
@@ -40,8 +41,14 @@ struct AddressInfo {
AddressInfo() {
internal_memset(this, 0, sizeof(AddressInfo));
}
+
// Deletes all strings and sets all fields to zero.
- void Clear();
+ void Clear() {
+ InternalFree(module);
+ InternalFree(function);
+ InternalFree(file);
+ internal_memset(this, 0, sizeof(AddressInfo));
+ }
void FillAddressAndModuleInfo(uptr addr, const char *mod_name,
uptr mod_offset) {
@@ -60,52 +67,39 @@ struct DataInfo {
uptr size;
};
-// Fills at most "max_frames" elements of "frames" with descriptions
-// for a given address (in all inlined functions). Returns the number
-// of descriptions actually filled.
-// This function should NOT be called from two threads simultaneously.
-uptr SymbolizeCode(uptr address, AddressInfo *frames, uptr max_frames);
-bool SymbolizeData(uptr address, DataInfo *info);
-
-bool IsSymbolizerAvailable();
-
-// Attempts to demangle the provided C++ mangled name.
-const char *Demangle(const char *Name);
-
-// Starts external symbolizer program in a subprocess. Sanitizer communicates
-// with external symbolizer via pipes.
-bool InitializeExternalSymbolizer(const char *path_to_symbolizer);
-
-class LoadedModule {
+class SymbolizerInterface {
public:
- LoadedModule(const char *module_name, uptr base_address);
- void addAddressRange(uptr beg, uptr end);
- bool containsAddress(uptr address) const;
-
- const char *full_name() const { return full_name_; }
- uptr base_address() const { return base_address_; }
-
- private:
- struct AddressRange {
- uptr beg;
- uptr end;
- };
- char *full_name_;
- uptr base_address_;
- static const uptr kMaxNumberOfAddressRanges = 6;
- AddressRange ranges_[kMaxNumberOfAddressRanges];
- uptr n_ranges_;
+ // Fills at most "max_frames" elements of "frames" with descriptions
+ // for a given address (in all inlined functions). Returns the number
+ // of descriptions actually filled.
+ virtual uptr SymbolizeCode(uptr address, AddressInfo *frames,
+ uptr max_frames) {
+ return 0;
+ }
+ virtual bool SymbolizeData(uptr address, DataInfo *info) {
+ return false;
+ }
+ virtual bool IsAvailable() {
+ return false;
+ }
+ // Release internal caches (if any).
+ virtual void Flush() {}
+ // Attempts to demangle the provided C++ mangled name.
+ virtual const char *Demangle(const char *name) {
+ return name;
+ }
+ virtual void PrepareForSandboxing() {}
+ // Starts external symbolizer program in a subprocess. Sanitizer communicates
+ // with external symbolizer via pipes. If path_to_symbolizer is NULL or empty,
+ // tries to look for llvm-symbolizer in PATH.
+ virtual bool InitializeExternal(const char *path_to_symbolizer) {
+ return false;
+ }
};
-// Creates external symbolizer connected via pipe, user should write
-// to output_fd and read from input_fd.
-bool StartSymbolizerSubprocess(const char *path_to_symbolizer,
- int *input_fd, int *output_fd);
-
-// OS-dependent function that fills array with descriptions of at most
-// "max_modules" currently loaded modules. Returns the number of
-// initialized modules.
-uptr GetListOfModules(LoadedModule *modules, uptr max_modules);
+// Returns platform-specific implementation of SymbolizerInterface. It can't be
+// used from multiple threads simultaneously.
+SANITIZER_WEAK_ATTRIBUTE SymbolizerInterface *getSymbolizer();
} // namespace __sanitizer
diff --git a/libsanitizer/sanitizer_common/sanitizer_symbolizer_itanium.cc b/libsanitizer/sanitizer_common/sanitizer_symbolizer_itanium.cc
deleted file mode 100644
index b356f9a09e3..00000000000
--- a/libsanitizer/sanitizer_common/sanitizer_symbolizer_itanium.cc
+++ /dev/null
@@ -1,40 +0,0 @@
-//===-- sanitizer_symbolizer_itanium.cc -----------------------------------===//
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file is shared between the sanitizer run-time libraries.
-// Itanium C++ ABI-specific implementation of symbolizer parts.
-//===----------------------------------------------------------------------===//
-#if defined(__APPLE__) || defined(__linux__)
-
-#include "sanitizer_symbolizer.h"
-
-#include <stdlib.h>
-
-// C++ demangling function, as required by Itanium C++ ABI. This is weak,
-// because we do not require a C++ ABI library to be linked to a program
-// using sanitizers; if it's not present, we'll just use the mangled name.
-namespace __cxxabiv1 {
- extern "C" char *__cxa_demangle(const char *mangled, char *buffer,
- size_t *length, int *status)
- SANITIZER_WEAK_ATTRIBUTE;
-}
-
-const char *__sanitizer::Demangle(const char *MangledName) {
- // FIXME: __cxa_demangle aggressively insists on allocating memory.
- // There's not much we can do about that, short of providing our
- // own demangler (libc++abi's implementation could be adapted so that
- // it does not allocate). For now, we just call it anyway, and we leak
- // the returned value.
- if (__cxxabiv1::__cxa_demangle)
- if (const char *Demangled =
- __cxxabiv1::__cxa_demangle(MangledName, 0, 0, 0))
- return Demangled;
-
- return MangledName;
-}
-
-#endif // __APPLE__ || __linux__
diff --git a/libsanitizer/sanitizer_common/sanitizer_symbolizer_linux.cc b/libsanitizer/sanitizer_common/sanitizer_symbolizer_linux.cc
deleted file mode 100644
index 01f1e4588da..00000000000
--- a/libsanitizer/sanitizer_common/sanitizer_symbolizer_linux.cc
+++ /dev/null
@@ -1,180 +0,0 @@
-//===-- sanitizer_symbolizer_linux.cc -------------------------------------===//
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file is shared between AddressSanitizer and ThreadSanitizer
-// run-time libraries.
-// Linux-specific implementation of symbolizer parts.
-//===----------------------------------------------------------------------===//
-#ifdef __linux__
-#include "sanitizer_common.h"
-#include "sanitizer_internal_defs.h"
-#include "sanitizer_libc.h"
-#include "sanitizer_placement_new.h"
-#include "sanitizer_symbolizer.h"
-
-#include <elf.h>
-#include <errno.h>
-#include <poll.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-#if !defined(__ANDROID__) && !defined(ANDROID)
-#include <link.h>
-#endif
-
-namespace __sanitizer {
-
-static const int kSymbolizerStartupTimeMillis = 10;
-
-bool StartSymbolizerSubprocess(const char *path_to_symbolizer,
- int *input_fd, int *output_fd) {
- if (!FileExists(path_to_symbolizer)) {
- Report("WARNING: invalid path to external symbolizer!\n");
- return false;
- }
-
- int *infd = NULL;
- int *outfd = NULL;
- // The client program may close its stdin and/or stdout and/or stderr
- // thus allowing socketpair to reuse file descriptors 0, 1 or 2.
- // In this case the communication between the forked processes may be
- // broken if either the parent or the child tries to close or duplicate
- // these descriptors. The loop below produces two pairs of file
- // descriptors, each greater than 2 (stderr).
- int sock_pair[5][2];
- for (int i = 0; i < 5; i++) {
- if (pipe(sock_pair[i]) == -1) {
- for (int j = 0; j < i; j++) {
- internal_close(sock_pair[j][0]);
- internal_close(sock_pair[j][1]);
- }
- Report("WARNING: Can't create a socket pair to start "
- "external symbolizer (errno: %d)\n", errno);
- return false;
- } else if (sock_pair[i][0] > 2 && sock_pair[i][1] > 2) {
- if (infd == NULL) {
- infd = sock_pair[i];
- } else {
- outfd = sock_pair[i];
- for (int j = 0; j < i; j++) {
- if (sock_pair[j] == infd) continue;
- internal_close(sock_pair[j][0]);
- internal_close(sock_pair[j][1]);
- }
- break;
- }
- }
- }
- CHECK(infd);
- CHECK(outfd);
-
- int pid = fork();
- if (pid == -1) {
- // Fork() failed.
- internal_close(infd[0]);
- internal_close(infd[1]);
- internal_close(outfd[0]);
- internal_close(outfd[1]);
- Report("WARNING: failed to fork external symbolizer "
- " (errno: %d)\n", errno);
- return false;
- } else if (pid == 0) {
- // Child subprocess.
- internal_close(STDOUT_FILENO);
- internal_close(STDIN_FILENO);
- internal_dup2(outfd[0], STDIN_FILENO);
- internal_dup2(infd[1], STDOUT_FILENO);
- internal_close(outfd[0]);
- internal_close(outfd[1]);
- internal_close(infd[0]);
- internal_close(infd[1]);
- for (int fd = getdtablesize(); fd > 2; fd--)
- internal_close(fd);
- execl(path_to_symbolizer, path_to_symbolizer, (char*)0);
- internal__exit(1);
- }
-
- // Continue execution in parent process.
- internal_close(outfd[0]);
- internal_close(infd[1]);
- *input_fd = infd[0];
- *output_fd = outfd[1];
-
- // Check that symbolizer subprocess started successfully.
- int pid_status;
- SleepForMillis(kSymbolizerStartupTimeMillis);
- int exited_pid = waitpid(pid, &pid_status, WNOHANG);
- if (exited_pid != 0) {
- // Either waitpid failed, or child has already exited.
- Report("WARNING: external symbolizer didn't start up correctly!\n");
- return false;
- }
-
- return true;
-}
-
-#if defined(__ANDROID__) || defined(ANDROID)
-uptr GetListOfModules(LoadedModule *modules, uptr max_modules) {
- UNIMPLEMENTED();
-}
-#else // ANDROID
-typedef ElfW(Phdr) Elf_Phdr;
-
-struct DlIteratePhdrData {
- LoadedModule *modules;
- uptr current_n;
- uptr max_n;
-};
-
-static const uptr kMaxPathLength = 512;
-
-static int dl_iterate_phdr_cb(dl_phdr_info *info, size_t size, void *arg) {
- DlIteratePhdrData *data = (DlIteratePhdrData*)arg;
- if (data->current_n == data->max_n)
- return 0;
- InternalScopedBuffer<char> module_name(kMaxPathLength);
- module_name.data()[0] = '\0';
- if (data->current_n == 0) {
- // First module is the binary itself.
- uptr module_name_len = internal_readlink(
- "/proc/self/exe", module_name.data(), module_name.size());
- CHECK_NE(module_name_len, (uptr)-1);
- CHECK_LT(module_name_len, module_name.size());
- module_name[module_name_len] = '\0';
- } else if (info->dlpi_name) {
- internal_strncpy(module_name.data(), info->dlpi_name, module_name.size());
- }
- if (module_name.data()[0] == '\0')
- return 0;
- void *mem = &data->modules[data->current_n];
- LoadedModule *cur_module = new(mem) LoadedModule(module_name.data(),
- info->dlpi_addr);
- data->current_n++;
- for (int i = 0; i < info->dlpi_phnum; i++) {
- const Elf_Phdr *phdr = &info->dlpi_phdr[i];
- if (phdr->p_type == PT_LOAD) {
- uptr cur_beg = info->dlpi_addr + phdr->p_vaddr;
- uptr cur_end = cur_beg + phdr->p_memsz;
- cur_module->addAddressRange(cur_beg, cur_end);
- }
- }
- return 0;
-}
-
-uptr GetListOfModules(LoadedModule *modules, uptr max_modules) {
- CHECK(modules);
- DlIteratePhdrData data = {modules, 0, max_modules};
- dl_iterate_phdr(dl_iterate_phdr_cb, &data);
- return data.current_n;
-}
-#endif // ANDROID
-
-} // namespace __sanitizer
-
-#endif // __linux__
diff --git a/libsanitizer/sanitizer_common/sanitizer_symbolizer_mac.cc b/libsanitizer/sanitizer_common/sanitizer_symbolizer_mac.cc
deleted file mode 100644
index a1b931b737e..00000000000
--- a/libsanitizer/sanitizer_common/sanitizer_symbolizer_mac.cc
+++ /dev/null
@@ -1,29 +0,0 @@
-//===-- sanitizer_symbolizer_mac.cc ---------------------------------------===//
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file is shared between AddressSanitizer and ThreadSanitizer
-// run-time libraries.
-// Mac-specific implementation of symbolizer parts.
-//===----------------------------------------------------------------------===//
-#ifdef __APPLE__
-#include "sanitizer_internal_defs.h"
-#include "sanitizer_symbolizer.h"
-
-namespace __sanitizer {
-
-bool StartSymbolizerSubprocess(const char *path_to_symbolizer,
- int *input_fd, int *output_fd) {
- UNIMPLEMENTED();
-}
-
-uptr GetListOfModules(LoadedModule *modules, uptr max_modules) {
- UNIMPLEMENTED();
-}
-
-} // namespace __sanitizer
-
-#endif // __APPLE__
diff --git a/libsanitizer/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc b/libsanitizer/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc
new file mode 100644
index 00000000000..34063081c77
--- /dev/null
+++ b/libsanitizer/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc
@@ -0,0 +1,595 @@
+//===-- sanitizer_symbolizer_posix_libcdep.cc -----------------------------===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between AddressSanitizer and ThreadSanitizer
+// run-time libraries.
+// POSIX-specific implementation of symbolizer parts.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_platform.h"
+#if SANITIZER_POSIX
+#include "sanitizer_allocator_internal.h"
+#include "sanitizer_common.h"
+#include "sanitizer_internal_defs.h"
+#include "sanitizer_linux.h"
+#include "sanitizer_placement_new.h"
+#include "sanitizer_procmaps.h"
+#include "sanitizer_symbolizer.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+// C++ demangling function, as required by Itanium C++ ABI. This is weak,
+// because we do not require a C++ ABI library to be linked to a program
+// using sanitizers; if it's not present, we'll just use the mangled name.
+namespace __cxxabiv1 {
+ extern "C" SANITIZER_WEAK_ATTRIBUTE
+ char *__cxa_demangle(const char *mangled, char *buffer,
+ size_t *length, int *status);
+}
+
+namespace __sanitizer {
+
+// Attempts to demangle the name via __cxa_demangle from __cxxabiv1.
+static const char *DemangleCXXABI(const char *name) {
+ // FIXME: __cxa_demangle aggressively insists on allocating memory.
+ // There's not much we can do about that, short of providing our
+ // own demangler (libc++abi's implementation could be adapted so that
+ // it does not allocate). For now, we just call it anyway, and we leak
+ // the returned value.
+ if (__cxxabiv1::__cxa_demangle)
+ if (const char *demangled_name =
+ __cxxabiv1::__cxa_demangle(name, 0, 0, 0))
+ return demangled_name;
+
+ return name;
+}
+
+#if defined(__x86_64__)
+static const char* const kSymbolizerArch = "--default-arch=x86_64";
+#elif defined(__i386__)
+static const char* const kSymbolizerArch = "--default-arch=i386";
+#elif defined(__powerpc64__)
+static const char* const kSymbolizerArch = "--default-arch=powerpc64";
+#else
+static const char* const kSymbolizerArch = "--default-arch=unknown";
+#endif
+
+static const int kSymbolizerStartupTimeMillis = 10;
+
+// Creates external symbolizer connected via pipe, user should write
+// to output_fd and read from input_fd.
+static bool StartSymbolizerSubprocess(const char *path_to_symbolizer,
+ int *input_fd, int *output_fd) {
+ if (!FileExists(path_to_symbolizer)) {
+ Report("WARNING: invalid path to external symbolizer!\n");
+ return false;
+ }
+
+ int *infd = NULL;
+ int *outfd = NULL;
+ // The client program may close its stdin and/or stdout and/or stderr
+ // thus allowing socketpair to reuse file descriptors 0, 1 or 2.
+ // In this case the communication between the forked processes may be
+ // broken if either the parent or the child tries to close or duplicate
+ // these descriptors. The loop below produces two pairs of file
+ // descriptors, each greater than 2 (stderr).
+ int sock_pair[5][2];
+ for (int i = 0; i < 5; i++) {
+ if (pipe(sock_pair[i]) == -1) {
+ for (int j = 0; j < i; j++) {
+ internal_close(sock_pair[j][0]);
+ internal_close(sock_pair[j][1]);
+ }
+ Report("WARNING: Can't create a socket pair to start "
+ "external symbolizer (errno: %d)\n", errno);
+ return false;
+ } else if (sock_pair[i][0] > 2 && sock_pair[i][1] > 2) {
+ if (infd == NULL) {
+ infd = sock_pair[i];
+ } else {
+ outfd = sock_pair[i];
+ for (int j = 0; j < i; j++) {
+ if (sock_pair[j] == infd) continue;
+ internal_close(sock_pair[j][0]);
+ internal_close(sock_pair[j][1]);
+ }
+ break;
+ }
+ }
+ }
+ CHECK(infd);
+ CHECK(outfd);
+
+ int pid = fork();
+ if (pid == -1) {
+ // Fork() failed.
+ internal_close(infd[0]);
+ internal_close(infd[1]);
+ internal_close(outfd[0]);
+ internal_close(outfd[1]);
+ Report("WARNING: failed to fork external symbolizer "
+ " (errno: %d)\n", errno);
+ return false;
+ } else if (pid == 0) {
+ // Child subprocess.
+ internal_close(STDOUT_FILENO);
+ internal_close(STDIN_FILENO);
+ internal_dup2(outfd[0], STDIN_FILENO);
+ internal_dup2(infd[1], STDOUT_FILENO);
+ internal_close(outfd[0]);
+ internal_close(outfd[1]);
+ internal_close(infd[0]);
+ internal_close(infd[1]);
+ for (int fd = getdtablesize(); fd > 2; fd--)
+ internal_close(fd);
+ execl(path_to_symbolizer, path_to_symbolizer, kSymbolizerArch, (char*)0);
+ internal__exit(1);
+ }
+
+ // Continue execution in parent process.
+ internal_close(outfd[0]);
+ internal_close(infd[1]);
+ *input_fd = infd[0];
+ *output_fd = outfd[1];
+
+ // Check that symbolizer subprocess started successfully.
+ int pid_status;
+ SleepForMillis(kSymbolizerStartupTimeMillis);
+ int exited_pid = waitpid(pid, &pid_status, WNOHANG);
+ if (exited_pid != 0) {
+ // Either waitpid failed, or child has already exited.
+ Report("WARNING: external symbolizer didn't start up correctly!\n");
+ return false;
+ }
+
+ return true;
+}
+
+// Extracts the prefix of "str" that consists of any characters not
+// present in "delims" string, and copies this prefix to "result", allocating
+// space for it.
+// Returns a pointer to "str" after skipping extracted prefix and first
+// delimiter char.
+static const char *ExtractToken(const char *str, const char *delims,
+ char **result) {
+ uptr prefix_len = internal_strcspn(str, delims);
+ *result = (char*)InternalAlloc(prefix_len + 1);
+ internal_memcpy(*result, str, prefix_len);
+ (*result)[prefix_len] = '\0';
+ const char *prefix_end = str + prefix_len;
+ if (*prefix_end != '\0') prefix_end++;
+ return prefix_end;
+}
+
+// Same as ExtractToken, but converts extracted token to integer.
+static const char *ExtractInt(const char *str, const char *delims,
+ int *result) {
+ char *buff;
+ const char *ret = ExtractToken(str, delims, &buff);
+ if (buff != 0) {
+ *result = (int)internal_atoll(buff);
+ }
+ InternalFree(buff);
+ return ret;
+}
+
+static const char *ExtractUptr(const char *str, const char *delims,
+ uptr *result) {
+ char *buff;
+ const char *ret = ExtractToken(str, delims, &buff);
+ if (buff != 0) {
+ *result = (uptr)internal_atoll(buff);
+ }
+ InternalFree(buff);
+ return ret;
+}
+
+// ExternalSymbolizer encapsulates communication between the tool and
+// external symbolizer program, running in a different subprocess,
+// For now we assume the following protocol:
+// For each request of the form
+// <module_name> <module_offset>
+// passed to STDIN, external symbolizer prints to STDOUT response:
+// <function_name>
+// <file_name>:<line_number>:<column_number>
+// <function_name>
+// <file_name>:<line_number>:<column_number>
+// ...
+// <empty line>
+class ExternalSymbolizer {
+ public:
+ ExternalSymbolizer(const char *path, int input_fd, int output_fd)
+ : path_(path),
+ input_fd_(input_fd),
+ output_fd_(output_fd),
+ times_restarted_(0) {
+ CHECK(path_);
+ CHECK_NE(input_fd_, kInvalidFd);
+ CHECK_NE(output_fd_, kInvalidFd);
+ }
+
+ char *SendCommand(bool is_data, const char *module_name, uptr module_offset) {
+ CHECK(module_name);
+ internal_snprintf(buffer_, kBufferSize, "%s\"%s\" 0x%zx\n",
+ is_data ? "DATA " : "", module_name, module_offset);
+ if (!writeToSymbolizer(buffer_, internal_strlen(buffer_)))
+ return 0;
+ if (!readFromSymbolizer(buffer_, kBufferSize))
+ return 0;
+ return buffer_;
+ }
+
+ bool Restart() {
+ if (times_restarted_ >= kMaxTimesRestarted) return false;
+ times_restarted_++;
+ internal_close(input_fd_);
+ internal_close(output_fd_);
+ return StartSymbolizerSubprocess(path_, &input_fd_, &output_fd_);
+ }
+
+ void Flush() {
+ }
+
+ private:
+ bool readFromSymbolizer(char *buffer, uptr max_length) {
+ if (max_length == 0)
+ return true;
+ uptr read_len = 0;
+ while (true) {
+ uptr just_read = internal_read(input_fd_, buffer + read_len,
+ max_length - read_len);
+ // We can't read 0 bytes, as we don't expect external symbolizer to close
+ // its stdout.
+ if (just_read == 0 || just_read == (uptr)-1) {
+ Report("WARNING: Can't read from symbolizer at fd %d\n", input_fd_);
+ return false;
+ }
+ read_len += just_read;
+ // Empty line marks the end of symbolizer output.
+ if (read_len >= 2 && buffer[read_len - 1] == '\n' &&
+ buffer[read_len - 2] == '\n') {
+ break;
+ }
+ }
+ return true;
+ }
+
+ bool writeToSymbolizer(const char *buffer, uptr length) {
+ if (length == 0)
+ return true;
+ uptr write_len = internal_write(output_fd_, buffer, length);
+ if (write_len == 0 || write_len == (uptr)-1) {
+ Report("WARNING: Can't write to symbolizer at fd %d\n", output_fd_);
+ return false;
+ }
+ return true;
+ }
+
+ const char *path_;
+ int input_fd_;
+ int output_fd_;
+
+ static const uptr kBufferSize = 16 * 1024;
+ char buffer_[kBufferSize];
+
+ static const uptr kMaxTimesRestarted = 5;
+ uptr times_restarted_;
+};
+
+static LowLevelAllocator symbolizer_allocator; // Linker initialized.
+
+#if SANITIZER_SUPPORTS_WEAK_HOOKS
+extern "C" {
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
+bool __sanitizer_symbolize_code(const char *ModuleName, u64 ModuleOffset,
+ char *Buffer, int MaxLength);
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
+bool __sanitizer_symbolize_data(const char *ModuleName, u64 ModuleOffset,
+ char *Buffer, int MaxLength);
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
+void __sanitizer_symbolize_flush();
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
+int __sanitizer_symbolize_demangle(const char *Name, char *Buffer,
+ int MaxLength);
+} // extern "C"
+
+class InternalSymbolizer {
+ public:
+ typedef bool (*SanitizerSymbolizeFn)(const char*, u64, char*, int);
+
+ static InternalSymbolizer *get() {
+ if (__sanitizer_symbolize_code != 0 &&
+ __sanitizer_symbolize_data != 0) {
+ void *mem = symbolizer_allocator.Allocate(sizeof(InternalSymbolizer));
+ return new(mem) InternalSymbolizer();
+ }
+ return 0;
+ }
+
+ char *SendCommand(bool is_data, const char *module_name, uptr module_offset) {
+ SanitizerSymbolizeFn symbolize_fn = is_data ? __sanitizer_symbolize_data
+ : __sanitizer_symbolize_code;
+ if (symbolize_fn(module_name, module_offset, buffer_, kBufferSize))
+ return buffer_;
+ return 0;
+ }
+
+ void Flush() {
+ if (__sanitizer_symbolize_flush)
+ __sanitizer_symbolize_flush();
+ }
+
+ const char *Demangle(const char *name) {
+ if (__sanitizer_symbolize_demangle) {
+ for (uptr res_length = 1024;
+ res_length <= InternalSizeClassMap::kMaxSize;) {
+ char *res_buff = static_cast<char*>(InternalAlloc(res_length));
+ uptr req_length =
+ __sanitizer_symbolize_demangle(name, res_buff, res_length);
+ if (req_length > res_length) {
+ res_length = req_length + 1;
+ InternalFree(res_buff);
+ continue;
+ }
+ return res_buff;
+ }
+ }
+ return name;
+ }
+
+ private:
+ InternalSymbolizer() { }
+
+ static const int kBufferSize = 16 * 1024;
+ static const int kMaxDemangledNameSize = 1024;
+ char buffer_[kBufferSize];
+};
+#else // SANITIZER_SUPPORTS_WEAK_HOOKS
+
+class InternalSymbolizer {
+ public:
+ static InternalSymbolizer *get() { return 0; }
+ char *SendCommand(bool is_data, const char *module_name, uptr module_offset) {
+ return 0;
+ }
+ void Flush() { }
+ const char *Demangle(const char *name) { return name; }
+};
+
+#endif // SANITIZER_SUPPORTS_WEAK_HOOKS
+
+class Symbolizer : public SymbolizerInterface {
+ // This class has no constructor, as global constructors are forbidden in
+ // sanitizer_common. It should be linker initialized instead.
+ public:
+ uptr SymbolizeCode(uptr addr, AddressInfo *frames, uptr max_frames) {
+ if (max_frames == 0)
+ return 0;
+ LoadedModule *module = FindModuleForAddress(addr);
+ if (module == 0)
+ return 0;
+ const char *module_name = module->full_name();
+ uptr module_offset = addr - module->base_address();
+ const char *str = SendCommand(false, module_name, module_offset);
+ if (str == 0) {
+ // External symbolizer was not initialized or failed. Fill only data
+ // about module name and offset.
+ AddressInfo *info = &frames[0];
+ info->Clear();
+ info->FillAddressAndModuleInfo(addr, module_name, module_offset);
+ return 1;
+ }
+ uptr frame_id = 0;
+ for (frame_id = 0; frame_id < max_frames; frame_id++) {
+ AddressInfo *info = &frames[frame_id];
+ char *function_name = 0;
+ str = ExtractToken(str, "\n", &function_name);
+ CHECK(function_name);
+ if (function_name[0] == '\0') {
+ // There are no more frames.
+ break;
+ }
+ info->Clear();
+ info->FillAddressAndModuleInfo(addr, module_name, module_offset);
+ info->function = function_name;
+ // Parse <file>:<line>:<column> buffer.
+ char *file_line_info = 0;
+ str = ExtractToken(str, "\n", &file_line_info);
+ CHECK(file_line_info);
+ const char *line_info = ExtractToken(file_line_info, ":", &info->file);
+ line_info = ExtractInt(line_info, ":", &info->line);
+ line_info = ExtractInt(line_info, "", &info->column);
+ InternalFree(file_line_info);
+
+ // Functions and filenames can be "??", in which case we write 0
+ // to address info to mark that names are unknown.
+ if (0 == internal_strcmp(info->function, "??")) {
+ InternalFree(info->function);
+ info->function = 0;
+ }
+ if (0 == internal_strcmp(info->file, "??")) {
+ InternalFree(info->file);
+ info->file = 0;
+ }
+ }
+ if (frame_id == 0) {
+ // Make sure we return at least one frame.
+ AddressInfo *info = &frames[0];
+ info->Clear();
+ info->FillAddressAndModuleInfo(addr, module_name, module_offset);
+ frame_id = 1;
+ }
+ return frame_id;
+ }
+
+ bool SymbolizeData(uptr addr, DataInfo *info) {
+ LoadedModule *module = FindModuleForAddress(addr);
+ if (module == 0)
+ return false;
+ const char *module_name = module->full_name();
+ uptr module_offset = addr - module->base_address();
+ internal_memset(info, 0, sizeof(*info));
+ info->address = addr;
+ info->module = internal_strdup(module_name);
+ info->module_offset = module_offset;
+ const char *str = SendCommand(true, module_name, module_offset);
+ if (str == 0)
+ return true;
+ str = ExtractToken(str, "\n", &info->name);
+ str = ExtractUptr(str, " ", &info->start);
+ str = ExtractUptr(str, "\n", &info->size);
+ info->start += module->base_address();
+ return true;
+ }
+
+ bool InitializeExternal(const char *path_to_symbolizer) {
+ if (!path_to_symbolizer || path_to_symbolizer[0] == '\0') {
+ path_to_symbolizer = FindPathToBinary("llvm-symbolizer");
+ if (!path_to_symbolizer)
+ return false;
+ }
+ int input_fd, output_fd;
+ if (!StartSymbolizerSubprocess(path_to_symbolizer, &input_fd, &output_fd))
+ return false;
+ void *mem = symbolizer_allocator.Allocate(sizeof(ExternalSymbolizer));
+ external_symbolizer_ = new(mem) ExternalSymbolizer(path_to_symbolizer,
+ input_fd, output_fd);
+ return true;
+ }
+
+ bool IsAvailable() {
+ if (internal_symbolizer_ == 0)
+ internal_symbolizer_ = InternalSymbolizer::get();
+ return internal_symbolizer_ || external_symbolizer_;
+ }
+
+ void Flush() {
+ if (internal_symbolizer_)
+ internal_symbolizer_->Flush();
+ if (external_symbolizer_)
+ external_symbolizer_->Flush();
+ }
+
+ const char *Demangle(const char *name) {
+ if (IsAvailable() && internal_symbolizer_ != 0)
+ return internal_symbolizer_->Demangle(name);
+ return DemangleCXXABI(name);
+ }
+
+ void PrepareForSandboxing() {
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
+ // Cache /proc/self/exe on Linux.
+ CacheBinaryName();
+#endif
+ }
+
+ private:
+ char *SendCommand(bool is_data, const char *module_name, uptr module_offset) {
+ // First, try to use internal symbolizer.
+ if (!IsAvailable()) {
+ return 0;
+ }
+ if (internal_symbolizer_) {
+ return internal_symbolizer_->SendCommand(is_data, module_name,
+ module_offset);
+ }
+ // Otherwise, fall back to external symbolizer.
+ if (external_symbolizer_ == 0) {
+ ReportExternalSymbolizerError(
+ "WARNING: Trying to symbolize code, but external "
+ "symbolizer is not initialized!\n");
+ return 0;
+ }
+ for (;;) {
+ char *reply = external_symbolizer_->SendCommand(is_data, module_name,
+ module_offset);
+ if (reply)
+ return reply;
+ // Try to restart symbolizer subprocess. If we don't succeed, forget
+ // about it and don't try to use it later.
+ if (!external_symbolizer_->Restart()) {
+ ReportExternalSymbolizerError(
+ "WARNING: Failed to use and restart external symbolizer!\n");
+ external_symbolizer_ = 0;
+ return 0;
+ }
+ }
+ }
+
+ LoadedModule *FindModuleForAddress(uptr address) {
+ bool modules_were_reloaded = false;
+ if (modules_ == 0 || !modules_fresh_) {
+ modules_ = (LoadedModule*)(symbolizer_allocator.Allocate(
+ kMaxNumberOfModuleContexts * sizeof(LoadedModule)));
+ CHECK(modules_);
+ n_modules_ = GetListOfModules(modules_, kMaxNumberOfModuleContexts,
+ /* filter */ 0);
+ // FIXME: Return this check when GetListOfModules is implemented on Mac.
+ // CHECK_GT(n_modules_, 0);
+ CHECK_LT(n_modules_, kMaxNumberOfModuleContexts);
+ modules_fresh_ = true;
+ modules_were_reloaded = true;
+ }
+ for (uptr i = 0; i < n_modules_; i++) {
+ if (modules_[i].containsAddress(address)) {
+ return &modules_[i];
+ }
+ }
+ // Reload the modules and look up again, if we haven't tried it yet.
+ if (!modules_were_reloaded) {
+ // FIXME: set modules_fresh_ from dlopen()/dlclose() interceptors.
+ // It's too aggressive to reload the list of modules each time we fail
+ // to find a module for a given address.
+ modules_fresh_ = false;
+ return FindModuleForAddress(address);
+ }
+ return 0;
+ }
+
+ void ReportExternalSymbolizerError(const char *msg) {
+ // Don't use atomics here for now, as SymbolizeCode can't be called
+ // from multiple threads anyway.
+ static bool reported;
+ if (!reported) {
+ Report(msg);
+ reported = true;
+ }
+ }
+
+ // 16K loaded modules should be enough for everyone.
+ static const uptr kMaxNumberOfModuleContexts = 1 << 14;
+ LoadedModule *modules_; // Array of module descriptions is leaked.
+ uptr n_modules_;
+ // If stale, need to reload the modules before looking up addresses.
+ bool modules_fresh_;
+
+ ExternalSymbolizer *external_symbolizer_; // Leaked.
+ InternalSymbolizer *internal_symbolizer_; // Leaked.
+};
+
+static ALIGNED(64) char symbolizer_placeholder[sizeof(Symbolizer)];
+static Symbolizer *symbolizer;
+
+SymbolizerInterface *getSymbolizer() {
+ static atomic_uint8_t initialized;
+ static StaticSpinMutex init_mu;
+ if (atomic_load(&initialized, memory_order_acquire) == 0) {
+ SpinMutexLock l(&init_mu);
+ if (atomic_load(&initialized, memory_order_relaxed) == 0) {
+ symbolizer = new(symbolizer_placeholder) Symbolizer();
+ atomic_store(&initialized, 1, memory_order_release);
+ }
+ }
+ return symbolizer;
+}
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_POSIX
diff --git a/libsanitizer/sanitizer_common/sanitizer_symbolizer_win.cc b/libsanitizer/sanitizer_common/sanitizer_symbolizer_win.cc
index ad0053234f0..44801f39b31 100644
--- a/libsanitizer/sanitizer_common/sanitizer_symbolizer_win.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_symbolizer_win.cc
@@ -9,25 +9,18 @@
// run-time libraries.
// Windows-specific implementation of symbolizer parts.
//===----------------------------------------------------------------------===//
-#ifdef _WIN32
-#include <windows.h>
+#include "sanitizer_platform.h"
+#if SANITIZER_WINDOWS
#include "sanitizer_internal_defs.h"
#include "sanitizer_symbolizer.h"
namespace __sanitizer {
-bool StartSymbolizerSubprocess(const char *path_to_symbolizer,
- int *input_fd, int *output_fd) {
- UNIMPLEMENTED();
-}
-
-uptr GetListOfModules(LoadedModule *modules, uptr max_modules) {
- UNIMPLEMENTED();
-};
+static SymbolizerInterface win_symbolizer; // Linker initialized.
-const char *Demangle(const char *MangledName) {
- return MangledName;
+SymbolizerInterface *getSymbolizer() {
+ return &win_symbolizer;
}
} // namespace __sanitizer
diff --git a/libsanitizer/sanitizer_common/sanitizer_syscall_generic.inc b/libsanitizer/sanitizer_common/sanitizer_syscall_generic.inc
new file mode 100644
index 00000000000..6b2c915a3bc
--- /dev/null
+++ b/libsanitizer/sanitizer_common/sanitizer_syscall_generic.inc
@@ -0,0 +1,22 @@
+//===-- sanitizer_syscall_generic.inc ---------------------------*- C++ -*-===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Generic implementations of internal_syscall and internal_iserror.
+//
+//===----------------------------------------------------------------------===//
+
+#define internal_syscall syscall
+
+bool internal_iserror(uptr retval, int *rverrno) {
+ if (retval == (uptr)-1) {
+ if (rverrno)
+ *rverrno = errno;
+ return true;
+ } else {
+ return false;
+ }
+}
diff --git a/libsanitizer/sanitizer_common/sanitizer_syscall_linux_x86_64.inc b/libsanitizer/sanitizer_common/sanitizer_syscall_linux_x86_64.inc
new file mode 100644
index 00000000000..4f405d92b05
--- /dev/null
+++ b/libsanitizer/sanitizer_common/sanitizer_syscall_linux_x86_64.inc
@@ -0,0 +1,85 @@
+//===-- sanitizer_syscall_linux_x86_64.inc ----------------------*- C++ -*-===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Implementations of internal_syscall and internal_iserror for Linux/x86_64.
+//
+//===----------------------------------------------------------------------===//
+
+static uptr internal_syscall(u64 nr) {
+ u64 retval;
+ asm volatile("syscall" : "=a"(retval) : "a"(nr) : "rcx", "r11");
+ return retval;
+}
+
+template <typename T1>
+static uptr internal_syscall(u64 nr, T1 arg1) {
+ u64 retval;
+ asm volatile("syscall" : "=a"(retval) : "a"(nr), "D"((u64)arg1) :
+ "rcx", "r11");
+ return retval;
+}
+
+template <typename T1, typename T2>
+static uptr internal_syscall(u64 nr, T1 arg1, T2 arg2) {
+ u64 retval;
+ asm volatile("syscall" : "=a"(retval) : "a"(nr), "D"((u64)arg1),
+ "S"((u64)arg2) : "rcx", "r11");
+ return retval;
+}
+
+template <typename T1, typename T2, typename T3>
+static uptr internal_syscall(u64 nr, T1 arg1, T2 arg2, T3 arg3) {
+ u64 retval;
+ asm volatile("syscall" : "=a"(retval) : "a"(nr), "D"((u64)arg1),
+ "S"((u64)arg2), "d"((u64)arg3) : "rcx", "r11");
+ return retval;
+}
+
+template <typename T1, typename T2, typename T3, typename T4>
+static uptr internal_syscall(u64 nr, T1 arg1, T2 arg2, T3 arg3, T4 arg4) {
+ u64 retval;
+ asm volatile("mov %5, %%r10;"
+ "syscall" : "=a"(retval) : "a"(nr), "D"((u64)arg1),
+ "S"((u64)arg2), "d"((u64)arg3), "r"((u64)arg4) :
+ "rcx", "r11", "r10");
+ return retval;
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+static uptr internal_syscall(u64 nr, T1 arg1, T2 arg2, T3 arg3, T4 arg4,
+ T5 arg5) {
+ u64 retval;
+ asm volatile("mov %5, %%r10;"
+ "mov %6, %%r8;"
+ "syscall" : "=a"(retval) : "a"(nr), "D"((u64)arg1),
+ "S"((u64)arg2), "d"((u64)arg3), "r"((u64)arg4), "r"((u64)arg5) :
+ "rcx", "r11", "r10", "r8");
+ return retval;
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6>
+static uptr internal_syscall(u64 nr, T1 arg1, T2 arg2, T3 arg3, T4 arg4,
+ T5 arg5, T6 arg6) {
+ u64 retval;
+ asm volatile("mov %5, %%r10;"
+ "mov %6, %%r8;"
+ "mov %7, %%r9;"
+ "syscall" : "=a"(retval) : "a"(nr), "D"((u64)arg1),
+ "S"((u64)arg2), "d"((u64)arg3), "r"((u64)arg4), "r"((u64)arg5),
+ "r"((u64)arg6) : "rcx", "r11", "r10", "r8", "r9");
+ return retval;
+}
+
+bool internal_iserror(uptr retval, int *rverrno) {
+ if (retval >= (uptr)-4095) {
+ if (rverrno)
+ *rverrno = -retval;
+ return true;
+ }
+ return false;
+}
diff --git a/libsanitizer/sanitizer_common/sanitizer_thread_registry.cc b/libsanitizer/sanitizer_common/sanitizer_thread_registry.cc
new file mode 100644
index 00000000000..e639430f73a
--- /dev/null
+++ b/libsanitizer/sanitizer_common/sanitizer_thread_registry.cc
@@ -0,0 +1,277 @@
+//===-- sanitizer_thread_registry.cc --------------------------------------===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between sanitizer tools.
+//
+// General thread bookkeeping functionality.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_thread_registry.h"
+
+namespace __sanitizer {
+
+ThreadContextBase::ThreadContextBase(u32 tid)
+ : tid(tid), unique_id(0), os_id(0), user_id(0), status(ThreadStatusInvalid),
+ detached(false), reuse_count(0), parent_tid(0), next(0) {
+ name[0] = '\0';
+}
+
+ThreadContextBase::~ThreadContextBase() {
+ // ThreadContextBase should never be deleted.
+ CHECK(0);
+}
+
+void ThreadContextBase::SetName(const char *new_name) {
+ name[0] = '\0';
+ if (new_name) {
+ internal_strncpy(name, new_name, sizeof(name));
+ name[sizeof(name) - 1] = '\0';
+ }
+}
+
+void ThreadContextBase::SetDead() {
+ CHECK(status == ThreadStatusRunning ||
+ status == ThreadStatusFinished);
+ status = ThreadStatusDead;
+ user_id = 0;
+ OnDead();
+}
+
+void ThreadContextBase::SetJoined(void *arg) {
+ // FIXME(dvyukov): print message and continue (it's user error).
+ CHECK_EQ(false, detached);
+ CHECK_EQ(ThreadStatusFinished, status);
+ status = ThreadStatusDead;
+ user_id = 0;
+ OnJoined(arg);
+}
+
+void ThreadContextBase::SetFinished() {
+ if (!detached)
+ status = ThreadStatusFinished;
+ OnFinished();
+}
+
+void ThreadContextBase::SetStarted(uptr _os_id, void *arg) {
+ status = ThreadStatusRunning;
+ os_id = _os_id;
+ OnStarted(arg);
+}
+
+void ThreadContextBase::SetCreated(uptr _user_id, u64 _unique_id,
+ bool _detached, u32 _parent_tid, void *arg) {
+ status = ThreadStatusCreated;
+ user_id = _user_id;
+ unique_id = _unique_id;
+ detached = _detached;
+ // Parent tid makes no sense for the main thread.
+ if (tid != 0)
+ parent_tid = _parent_tid;
+ OnCreated(arg);
+}
+
+void ThreadContextBase::Reset() {
+ status = ThreadStatusInvalid;
+ reuse_count++;
+ SetName(0);
+ OnReset();
+}
+
+// ThreadRegistry implementation.
+
+const u32 ThreadRegistry::kUnknownTid = ~0U;
+
+ThreadRegistry::ThreadRegistry(ThreadContextFactory factory, u32 max_threads,
+ u32 thread_quarantine_size)
+ : context_factory_(factory),
+ max_threads_(max_threads),
+ thread_quarantine_size_(thread_quarantine_size),
+ mtx_(),
+ n_contexts_(0),
+ total_threads_(0),
+ alive_threads_(0),
+ max_alive_threads_(0),
+ running_threads_(0) {
+ threads_ = (ThreadContextBase **)MmapOrDie(max_threads_ * sizeof(threads_[0]),
+ "ThreadRegistry");
+ dead_threads_.clear();
+ invalid_threads_.clear();
+}
+
+void ThreadRegistry::GetNumberOfThreads(uptr *total, uptr *running,
+ uptr *alive) {
+ BlockingMutexLock l(&mtx_);
+ if (total) *total = n_contexts_;
+ if (running) *running = running_threads_;
+ if (alive) *alive = alive_threads_;
+}
+
+uptr ThreadRegistry::GetMaxAliveThreads() {
+ BlockingMutexLock l(&mtx_);
+ return max_alive_threads_;
+}
+
+u32 ThreadRegistry::CreateThread(uptr user_id, bool detached, u32 parent_tid,
+ void *arg) {
+ BlockingMutexLock l(&mtx_);
+ u32 tid = kUnknownTid;
+ ThreadContextBase *tctx = QuarantinePop();
+ if (tctx) {
+ tid = tctx->tid;
+ } else if (n_contexts_ < max_threads_) {
+ // Allocate new thread context and tid.
+ tid = n_contexts_++;
+ tctx = context_factory_(tid);
+ threads_[tid] = tctx;
+ } else {
+ Report("%s: Thread limit (%u threads) exceeded. Dying.\n",
+ SanitizerToolName, max_threads_);
+ Die();
+ }
+ CHECK_NE(tctx, 0);
+ CHECK_NE(tid, kUnknownTid);
+ CHECK_LT(tid, max_threads_);
+ CHECK_EQ(tctx->status, ThreadStatusInvalid);
+ alive_threads_++;
+ if (max_alive_threads_ < alive_threads_) {
+ max_alive_threads_++;
+ CHECK_EQ(alive_threads_, max_alive_threads_);
+ }
+ tctx->SetCreated(user_id, total_threads_++, detached,
+ parent_tid, arg);
+ return tid;
+}
+
+void ThreadRegistry::RunCallbackForEachThreadLocked(ThreadCallback cb,
+ void *arg) {
+ CheckLocked();
+ for (u32 tid = 0; tid < n_contexts_; tid++) {
+ ThreadContextBase *tctx = threads_[tid];
+ if (tctx == 0)
+ continue;
+ cb(tctx, arg);
+ }
+}
+
+u32 ThreadRegistry::FindThread(FindThreadCallback cb, void *arg) {
+ BlockingMutexLock l(&mtx_);
+ for (u32 tid = 0; tid < n_contexts_; tid++) {
+ ThreadContextBase *tctx = threads_[tid];
+ if (tctx != 0 && cb(tctx, arg))
+ return tctx->tid;
+ }
+ return kUnknownTid;
+}
+
+ThreadContextBase *
+ThreadRegistry::FindThreadContextLocked(FindThreadCallback cb, void *arg) {
+ CheckLocked();
+ for (u32 tid = 0; tid < n_contexts_; tid++) {
+ ThreadContextBase *tctx = threads_[tid];
+ if (tctx != 0 && cb(tctx, arg))
+ return tctx;
+ }
+ return 0;
+}
+
+static bool FindThreadContextByOsIdCallback(ThreadContextBase *tctx,
+ void *arg) {
+ return (tctx->os_id == (uptr)arg && tctx->status != ThreadStatusInvalid &&
+ tctx->status != ThreadStatusDead);
+}
+
+ThreadContextBase *ThreadRegistry::FindThreadContextByOsIDLocked(uptr os_id) {
+ return FindThreadContextLocked(FindThreadContextByOsIdCallback,
+ (void *)os_id);
+}
+
+void ThreadRegistry::SetThreadName(u32 tid, const char *name) {
+ BlockingMutexLock l(&mtx_);
+ CHECK_LT(tid, n_contexts_);
+ ThreadContextBase *tctx = threads_[tid];
+ CHECK_NE(tctx, 0);
+ CHECK_EQ(ThreadStatusRunning, tctx->status);
+ tctx->SetName(name);
+}
+
+void ThreadRegistry::DetachThread(u32 tid) {
+ BlockingMutexLock l(&mtx_);
+ CHECK_LT(tid, n_contexts_);
+ ThreadContextBase *tctx = threads_[tid];
+ CHECK_NE(tctx, 0);
+ if (tctx->status == ThreadStatusInvalid) {
+ Report("%s: Detach of non-existent thread\n", SanitizerToolName);
+ return;
+ }
+ if (tctx->status == ThreadStatusFinished) {
+ tctx->SetDead();
+ QuarantinePush(tctx);
+ } else {
+ tctx->detached = true;
+ }
+}
+
+void ThreadRegistry::JoinThread(u32 tid, void *arg) {
+ BlockingMutexLock l(&mtx_);
+ CHECK_LT(tid, n_contexts_);
+ ThreadContextBase *tctx = threads_[tid];
+ CHECK_NE(tctx, 0);
+ if (tctx->status == ThreadStatusInvalid) {
+ Report("%s: Join of non-existent thread\n", SanitizerToolName);
+ return;
+ }
+ tctx->SetJoined(arg);
+ QuarantinePush(tctx);
+}
+
+void ThreadRegistry::FinishThread(u32 tid) {
+ BlockingMutexLock l(&mtx_);
+ CHECK_GT(alive_threads_, 0);
+ alive_threads_--;
+ CHECK_GT(running_threads_, 0);
+ running_threads_--;
+ CHECK_LT(tid, n_contexts_);
+ ThreadContextBase *tctx = threads_[tid];
+ CHECK_NE(tctx, 0);
+ CHECK_EQ(ThreadStatusRunning, tctx->status);
+ tctx->SetFinished();
+ if (tctx->detached) {
+ tctx->SetDead();
+ QuarantinePush(tctx);
+ }
+}
+
+void ThreadRegistry::StartThread(u32 tid, uptr os_id, void *arg) {
+ BlockingMutexLock l(&mtx_);
+ running_threads_++;
+ CHECK_LT(tid, n_contexts_);
+ ThreadContextBase *tctx = threads_[tid];
+ CHECK_NE(tctx, 0);
+ CHECK_EQ(ThreadStatusCreated, tctx->status);
+ tctx->SetStarted(os_id, arg);
+}
+
+void ThreadRegistry::QuarantinePush(ThreadContextBase *tctx) {
+ dead_threads_.push_back(tctx);
+ if (dead_threads_.size() <= thread_quarantine_size_)
+ return;
+ tctx = dead_threads_.front();
+ dead_threads_.pop_front();
+ CHECK_EQ(tctx->status, ThreadStatusDead);
+ tctx->Reset();
+ invalid_threads_.push_back(tctx);
+}
+
+ThreadContextBase *ThreadRegistry::QuarantinePop() {
+ if (invalid_threads_.size() == 0)
+ return 0;
+ ThreadContextBase *tctx = invalid_threads_.front();
+ invalid_threads_.pop_front();
+ return tctx;
+}
+
+} // namespace __sanitizer
diff --git a/libsanitizer/sanitizer_common/sanitizer_thread_registry.h b/libsanitizer/sanitizer_common/sanitizer_thread_registry.h
new file mode 100644
index 00000000000..1ae47b800ca
--- /dev/null
+++ b/libsanitizer/sanitizer_common/sanitizer_thread_registry.h
@@ -0,0 +1,142 @@
+//===-- sanitizer_thread_registry.h -----------------------------*- C++ -*-===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between sanitizer tools.
+//
+// General thread bookkeeping functionality.
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_THREAD_REGISTRY_H
+#define SANITIZER_THREAD_REGISTRY_H
+
+#include "sanitizer_common.h"
+#include "sanitizer_list.h"
+#include "sanitizer_mutex.h"
+
+namespace __sanitizer {
+
+enum ThreadStatus {
+ ThreadStatusInvalid, // Non-existent thread, data is invalid.
+ ThreadStatusCreated, // Created but not yet running.
+ ThreadStatusRunning, // The thread is currently running.
+ ThreadStatusFinished, // Joinable thread is finished but not yet joined.
+ ThreadStatusDead // Joined, but some info is still available.
+};
+
+// Generic thread context. Specific sanitizer tools may inherit from it.
+// If thread is dead, context may optionally be reused for a new thread.
+class ThreadContextBase {
+ public:
+ explicit ThreadContextBase(u32 tid);
+ ~ThreadContextBase(); // Should never be called.
+
+ const u32 tid; // Thread ID. Main thread should have tid = 0.
+ u64 unique_id; // Unique thread ID.
+ uptr os_id; // PID (used for reporting).
+ uptr user_id; // Some opaque user thread id (e.g. pthread_t).
+ char name[64]; // As annotated by user.
+
+ ThreadStatus status;
+ bool detached;
+ int reuse_count;
+
+ u32 parent_tid;
+ ThreadContextBase *next; // For storing thread contexts in a list.
+
+ void SetName(const char *new_name);
+
+ void SetDead();
+ void SetJoined(void *arg);
+ void SetFinished();
+ void SetStarted(uptr _os_id, void *arg);
+ void SetCreated(uptr _user_id, u64 _unique_id, bool _detached,
+ u32 _parent_tid, void *arg);
+ void Reset();
+
+ // The following methods may be overriden by subclasses.
+ // Some of them take opaque arg that may be optionally be used
+ // by subclasses.
+ virtual void OnDead() {}
+ virtual void OnJoined(void *arg) {}
+ virtual void OnFinished() {}
+ virtual void OnStarted(void *arg) {}
+ virtual void OnCreated(void *arg) {}
+ virtual void OnReset() {}
+};
+
+typedef ThreadContextBase* (*ThreadContextFactory)(u32 tid);
+
+class ThreadRegistry {
+ public:
+ static const u32 kUnknownTid;
+
+ ThreadRegistry(ThreadContextFactory factory, u32 max_threads,
+ u32 thread_quarantine_size);
+ void GetNumberOfThreads(uptr *total = 0, uptr *running = 0, uptr *alive = 0);
+ uptr GetMaxAliveThreads();
+
+ void Lock() { mtx_.Lock(); }
+ void CheckLocked() { mtx_.CheckLocked(); }
+ void Unlock() { mtx_.Unlock(); }
+
+ // Should be guarded by ThreadRegistryLock.
+ ThreadContextBase *GetThreadLocked(u32 tid) {
+ DCHECK_LT(tid, n_contexts_);
+ return threads_[tid];
+ }
+
+ u32 CreateThread(uptr user_id, bool detached, u32 parent_tid, void *arg);
+
+ typedef void (*ThreadCallback)(ThreadContextBase *tctx, void *arg);
+ // Invokes callback with a specified arg for each thread context.
+ // Should be guarded by ThreadRegistryLock.
+ void RunCallbackForEachThreadLocked(ThreadCallback cb, void *arg);
+
+ typedef bool (*FindThreadCallback)(ThreadContextBase *tctx, void *arg);
+ // Finds a thread using the provided callback. Returns kUnknownTid if no
+ // thread is found.
+ u32 FindThread(FindThreadCallback cb, void *arg);
+ // Should be guarded by ThreadRegistryLock. Return 0 if no thread
+ // is found.
+ ThreadContextBase *FindThreadContextLocked(FindThreadCallback cb,
+ void *arg);
+ ThreadContextBase *FindThreadContextByOsIDLocked(uptr os_id);
+
+ void SetThreadName(u32 tid, const char *name);
+ void DetachThread(u32 tid);
+ void JoinThread(u32 tid, void *arg);
+ void FinishThread(u32 tid);
+ void StartThread(u32 tid, uptr os_id, void *arg);
+
+ private:
+ const ThreadContextFactory context_factory_;
+ const u32 max_threads_;
+ const u32 thread_quarantine_size_;
+
+ BlockingMutex mtx_;
+
+ u32 n_contexts_; // Number of created thread contexts,
+ // at most max_threads_.
+ u64 total_threads_; // Total number of created threads. May be greater than
+ // max_threads_ if contexts were reused.
+ uptr alive_threads_; // Created or running.
+ uptr max_alive_threads_;
+ uptr running_threads_;
+
+ ThreadContextBase **threads_; // Array of thread contexts is leaked.
+ IntrusiveList<ThreadContextBase> dead_threads_;
+ IntrusiveList<ThreadContextBase> invalid_threads_;
+
+ void QuarantinePush(ThreadContextBase *tctx);
+ ThreadContextBase *QuarantinePop();
+};
+
+typedef GenericScopedLock<ThreadRegistry> ThreadRegistryLock;
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_THREAD_REGISTRY_H
diff --git a/libsanitizer/sanitizer_common/sanitizer_win.cc b/libsanitizer/sanitizer_common/sanitizer_win.cc
index 695265594b3..0a5fe81ae45 100644
--- a/libsanitizer/sanitizer_common/sanitizer_win.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_win.cc
@@ -9,7 +9,10 @@
// run-time libraries and implements windows-specific functions from
// sanitizer_libc.h.
//===----------------------------------------------------------------------===//
-#ifdef _WIN32
+
+#include "sanitizer_platform.h"
+#if SANITIZER_WINDOWS
+
#define WIN32_LEAN_AND_MEAN
#define NOGDI
#include <stdlib.h>
@@ -18,11 +21,14 @@
#include "sanitizer_common.h"
#include "sanitizer_libc.h"
-#include "sanitizer_placement_new.h"
#include "sanitizer_mutex.h"
+#include "sanitizer_placement_new.h"
+#include "sanitizer_stacktrace.h"
namespace __sanitizer {
+#include "sanitizer_syscall_generic.inc"
+
// --------------------- sanitizer_common.h
uptr GetPageSize() {
return 1U << 14; // FIXME: is this configurable?
@@ -32,18 +38,30 @@ uptr GetMmapGranularity() {
return 1U << 16; // FIXME: is this configurable?
}
+uptr GetMaxVirtualAddress() {
+ SYSTEM_INFO si;
+ GetSystemInfo(&si);
+ return (uptr)si.lpMaximumApplicationAddress;
+}
+
bool FileExists(const char *filename) {
UNIMPLEMENTED();
}
-int GetPid() {
+uptr internal_getpid() {
return GetProcessId(GetCurrentProcess());
}
-uptr GetThreadSelf() {
+// In contrast to POSIX, on Windows GetCurrentThreadId()
+// returns a system-unique identifier.
+uptr GetTid() {
return GetCurrentThreadId();
}
+uptr GetThreadSelf() {
+ return GetTid();
+}
+
void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
uptr *stack_bottom) {
CHECK(stack_top);
@@ -109,19 +127,38 @@ void *MapFileToMemory(const char *file_name, uptr *buff_size) {
UNIMPLEMENTED();
}
-const char *GetEnv(const char *name) {
- static char env_buffer[32767] = {};
+static const int kMaxEnvNameLength = 128;
+static const DWORD kMaxEnvValueLength = 32767;
- // Note: this implementation stores the result in a static buffer so we only
- // allow it to be called just once.
- static bool called_once = false;
- if (called_once)
- UNIMPLEMENTED();
- called_once = true;
+namespace {
+
+struct EnvVariable {
+ char name[kMaxEnvNameLength];
+ char value[kMaxEnvValueLength];
+};
- DWORD rv = GetEnvironmentVariableA(name, env_buffer, sizeof(env_buffer));
- if (rv > 0 && rv < sizeof(env_buffer))
- return env_buffer;
+} // namespace
+
+static const int kEnvVariables = 5;
+static EnvVariable env_vars[kEnvVariables];
+static int num_env_vars;
+
+const char *GetEnv(const char *name) {
+ // Note: this implementation caches the values of the environment variables
+ // and limits their quantity.
+ for (int i = 0; i < num_env_vars; i++) {
+ if (0 == internal_strcmp(name, env_vars[i].name))
+ return env_vars[i].value;
+ }
+ CHECK_LT(num_env_vars, kEnvVariables);
+ DWORD rv = GetEnvironmentVariableA(name, env_vars[num_env_vars].value,
+ kMaxEnvValueLength);
+ if (rv > 0 && rv < kMaxEnvValueLength) {
+ CHECK_LT(internal_strlen(name), kMaxEnvNameLength);
+ internal_strncpy(env_vars[num_env_vars].name, name, kMaxEnvNameLength);
+ num_env_vars++;
+ return env_vars[num_env_vars - 1].value;
+ }
return 0;
}
@@ -157,6 +194,11 @@ void SetStackSizeLimitInBytes(uptr limit) {
UNIMPLEMENTED();
}
+char *FindPathToBinary(const char *name) {
+ // Nothing here for now.
+ return 0;
+}
+
void SleepForSeconds(int seconds) {
Sleep(seconds * 1000);
}
@@ -165,11 +207,20 @@ void SleepForMillis(int millis) {
Sleep(millis);
}
+u64 NanoTime() {
+ return 0;
+}
+
void Abort() {
abort();
_exit(-1); // abort is not NORETURN on Windows.
}
+uptr GetListOfModules(LoadedModule *modules, uptr max_modules,
+ string_predicate_t filter) {
+ UNIMPLEMENTED();
+};
+
#ifndef SANITIZER_GO
int Atexit(void (*function)(void)) {
return atexit(function);
@@ -177,16 +228,16 @@ int Atexit(void (*function)(void)) {
#endif
// ------------------ sanitizer_libc.h
-void *internal_mmap(void *addr, uptr length, int prot, int flags,
- int fd, u64 offset) {
+uptr internal_mmap(void *addr, uptr length, int prot, int flags,
+ int fd, u64 offset) {
UNIMPLEMENTED();
}
-int internal_munmap(void *addr, uptr length) {
+uptr internal_munmap(void *addr, uptr length) {
UNIMPLEMENTED();
}
-int internal_close(fd_t fd) {
+uptr internal_close(fd_t fd) {
UNIMPLEMENTED();
}
@@ -194,15 +245,15 @@ int internal_isatty(fd_t fd) {
return _isatty(fd);
}
-fd_t internal_open(const char *filename, int flags) {
+uptr internal_open(const char *filename, int flags) {
UNIMPLEMENTED();
}
-fd_t internal_open(const char *filename, int flags, u32 mode) {
+uptr internal_open(const char *filename, int flags, u32 mode) {
UNIMPLEMENTED();
}
-fd_t OpenFile(const char *filename, bool write) {
+uptr OpenFile(const char *filename, bool write) {
UNIMPLEMENTED();
}
@@ -222,15 +273,15 @@ uptr internal_write(fd_t fd, const void *buf, uptr count) {
return ret;
}
-int internal_stat(const char *path, void *buf) {
+uptr internal_stat(const char *path, void *buf) {
UNIMPLEMENTED();
}
-int internal_lstat(const char *path, void *buf) {
+uptr internal_lstat(const char *path, void *buf) {
UNIMPLEMENTED();
}
-int internal_fstat(fd_t fd, void *buf) {
+uptr internal_fstat(fd_t fd, void *buf) {
UNIMPLEMENTED();
}
@@ -238,7 +289,7 @@ uptr internal_filesize(fd_t fd) {
UNIMPLEMENTED();
}
-int internal_dup2(int oldfd, int newfd) {
+uptr internal_dup2(int oldfd, int newfd) {
UNIMPLEMENTED();
}
@@ -246,7 +297,7 @@ uptr internal_readlink(const char *path, char *buf, uptr bufsize) {
UNIMPLEMENTED();
}
-int internal_sched_yield() {
+uptr internal_sched_yield() {
Sleep(0);
return 0;
}
@@ -268,6 +319,12 @@ BlockingMutex::BlockingMutex(LinkerInitialized li) {
owner_ = LOCK_READY;
}
+BlockingMutex::BlockingMutex() {
+ CHECK(sizeof(CRITICAL_SECTION) <= sizeof(opaque_storage_));
+ InitializeCriticalSection((LPCRITICAL_SECTION)opaque_storage_);
+ owner_ = LOCK_READY;
+}
+
void BlockingMutex::Lock() {
if (owner_ == LOCK_UNINITIALIZED) {
// FIXME: hm, global BlockingMutex objects are not initialized?!?
@@ -289,6 +346,79 @@ void BlockingMutex::Unlock() {
LeaveCriticalSection((LPCRITICAL_SECTION)opaque_storage_);
}
+void BlockingMutex::CheckLocked() {
+ CHECK_EQ(owner_, GetThreadSelf());
+}
+
+uptr GetTlsSize() {
+ return 0;
+}
+
+void InitTlsSize() {
+}
+
+void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
+ uptr *tls_addr, uptr *tls_size) {
+#ifdef SANITIZER_GO
+ *stk_addr = 0;
+ *stk_size = 0;
+ *tls_addr = 0;
+ *tls_size = 0;
+#else
+ uptr stack_top, stack_bottom;
+ GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom);
+ *stk_addr = stack_bottom;
+ *stk_size = stack_top - stack_bottom;
+ *tls_addr = 0;
+ *tls_size = 0;
+#endif
+}
+
+void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp,
+ uptr stack_top, uptr stack_bottom, bool fast) {
+ (void)fast;
+ (void)stack_top;
+ (void)stack_bottom;
+ stack->max_size = max_s;
+ void *tmp[kStackTraceMax];
+
+ // FIXME: CaptureStackBackTrace might be too slow for us.
+ // FIXME: Compare with StackWalk64.
+ // FIXME: Look at LLVMUnhandledExceptionFilter in Signals.inc
+ uptr cs_ret = CaptureStackBackTrace(1, stack->max_size, tmp, 0);
+ uptr offset = 0;
+ // Skip the RTL frames by searching for the PC in the stacktrace.
+ // FIXME: this doesn't work well for the malloc/free stacks yet.
+ for (uptr i = 0; i < cs_ret; i++) {
+ if (pc != (uptr)tmp[i])
+ continue;
+ offset = i;
+ break;
+ }
+
+ stack->size = cs_ret - offset;
+ for (uptr i = 0; i < stack->size; i++)
+ stack->trace[i] = (uptr)tmp[i + offset];
+}
+
+void MaybeOpenReportFile() {
+ // Windows doesn't have native fork, and we don't support Cygwin or other
+ // environments that try to fake it, so the initial report_fd will always be
+ // correct.
+}
+
+void RawWrite(const char *buffer) {
+ static const char *kRawWriteError =
+ "RawWrite can't output requested buffer!\n";
+ uptr length = (uptr)internal_strlen(buffer);
+ if (length != internal_write(report_fd, buffer, length)) {
+ // stderr may be closed, but we may be able to print to the debugger
+ // instead. This is the case when launching a program from Visual Studio,
+ // and the following routine should write to its console.
+ OutputDebugStringA(buffer);
+ }
+}
+
} // namespace __sanitizer
#endif // _WIN32
diff --git a/libsanitizer/tsan/tsan_defs.h b/libsanitizer/tsan/tsan_defs.h
index b2937a428f3..68936e02e4b 100644
--- a/libsanitizer/tsan/tsan_defs.h
+++ b/libsanitizer/tsan/tsan_defs.h
@@ -154,7 +154,6 @@ struct MD5Hash {
MD5Hash md5_hash(const void *data, uptr size);
struct ThreadState;
-struct ThreadContext;
struct Context;
struct ReportStack;
class ReportDesc;
diff --git a/libsanitizer/tsan/tsan_fd.cc b/libsanitizer/tsan/tsan_fd.cc
index a75d9bde08a..de852b185a6 100644
--- a/libsanitizer/tsan/tsan_fd.cc
+++ b/libsanitizer/tsan/tsan_fd.cc
@@ -72,13 +72,14 @@ static FdDesc *fddesc(ThreadState *thr, uptr pc, int fd) {
uptr l1 = atomic_load(pl1, memory_order_consume);
if (l1 == 0) {
uptr size = kTableSizeL2 * sizeof(FdDesc);
- void *p = internal_alloc(MBlockFD, size);
+ // We need this to reside in user memory to properly catch races on it.
+ void *p = user_alloc(thr, pc, size);
internal_memset(p, 0, size);
MemoryResetRange(thr, (uptr)&fddesc, (uptr)p, size);
if (atomic_compare_exchange_strong(pl1, &l1, (uptr)p, memory_order_acq_rel))
l1 = (uptr)p;
else
- internal_free(p);
+ user_free(thr, pc, p);
}
return &((FdDesc*)l1)[fd % kTableSizeL2]; // NOLINT
}
@@ -157,9 +158,9 @@ void FdRelease(ThreadState *thr, uptr pc, int fd) {
FdDesc *d = fddesc(thr, pc, fd);
FdSync *s = d->sync;
DPrintf("#%d: FdRelease(%d) -> %p\n", thr->tid, fd, s);
+ MemoryRead(thr, pc, (uptr)d, kSizeLog8);
if (s)
Release(thr, pc, (uptr)s);
- MemoryRead(thr, pc, (uptr)d, kSizeLog8);
}
void FdAccess(ThreadState *thr, uptr pc, int fd) {
diff --git a/libsanitizer/tsan/tsan_flags.cc b/libsanitizer/tsan/tsan_flags.cc
index ae748a13e15..dbde4212c59 100644
--- a/libsanitizer/tsan/tsan_flags.cc
+++ b/libsanitizer/tsan/tsan_flags.cc
@@ -47,17 +47,22 @@ void InitializeFlags(Flags *f, const char *env) {
f->force_seq_cst_atomics = false;
f->strip_path_prefix = "";
f->suppressions = "";
+ f->print_suppressions = false;
+ f->print_benign = false;
f->exitcode = 66;
+ f->halt_on_error = false;
f->log_path = "stderr";
f->atexit_sleep_ms = 1000;
f->verbosity = 0;
f->profile_memory = "";
f->flush_memory_ms = 0;
+ f->flush_symbolizer_ms = 5000;
f->stop_on_start = false;
f->running_on_valgrind = false;
f->external_symbolizer_path = "";
f->history_size = kGoMode ? 1 : 2; // There are a lot of goroutines in Go.
f->io_sync = 1;
+ f->allocator_may_return_null = false;
// Let a frontend override.
OverrideFlags(f);
@@ -75,16 +80,21 @@ void InitializeFlags(Flags *f, const char *env) {
ParseFlag(env, &f->force_seq_cst_atomics, "force_seq_cst_atomics");
ParseFlag(env, &f->strip_path_prefix, "strip_path_prefix");
ParseFlag(env, &f->suppressions, "suppressions");
+ ParseFlag(env, &f->print_suppressions, "print_suppressions");
+ ParseFlag(env, &f->print_benign, "print_benign");
ParseFlag(env, &f->exitcode, "exitcode");
+ ParseFlag(env, &f->halt_on_error, "halt_on_error");
ParseFlag(env, &f->log_path, "log_path");
ParseFlag(env, &f->atexit_sleep_ms, "atexit_sleep_ms");
ParseFlag(env, &f->verbosity, "verbosity");
ParseFlag(env, &f->profile_memory, "profile_memory");
ParseFlag(env, &f->flush_memory_ms, "flush_memory_ms");
+ ParseFlag(env, &f->flush_symbolizer_ms, "flush_symbolizer_ms");
ParseFlag(env, &f->stop_on_start, "stop_on_start");
ParseFlag(env, &f->external_symbolizer_path, "external_symbolizer_path");
ParseFlag(env, &f->history_size, "history_size");
ParseFlag(env, &f->io_sync, "io_sync");
+ ParseFlag(env, &f->allocator_may_return_null, "allocator_may_return_null");
if (!f->report_bugs) {
f->report_thread_leaks = false;
@@ -103,6 +113,8 @@ void InitializeFlags(Flags *f, const char *env) {
" (must be [0..2])\n");
Die();
}
+
+ common_flags()->allocator_may_return_null = f->allocator_may_return_null;
}
} // namespace __tsan
diff --git a/libsanitizer/tsan/tsan_flags.h b/libsanitizer/tsan/tsan_flags.h
index 480b41538f9..a7571c92b5e 100644
--- a/libsanitizer/tsan/tsan_flags.h
+++ b/libsanitizer/tsan/tsan_flags.h
@@ -50,8 +50,14 @@ struct Flags {
const char *strip_path_prefix;
// Suppressions filename.
const char *suppressions;
+ // Print matched suppressions at exit.
+ bool print_suppressions;
+ // Print matched "benign" races at exit.
+ bool print_benign;
// Override exit status if something was reported.
int exitcode;
+ // Exit after first reported error.
+ bool halt_on_error;
// Write logs to "log_path.pid".
// The special values are "stdout" and "stderr".
// The default is "stderr".
@@ -65,6 +71,8 @@ struct Flags {
const char *profile_memory;
// Flush shadow memory every X ms.
int flush_memory_ms;
+ // Flush symbolizer caches every X ms.
+ int flush_symbolizer_ms;
// Stops on start until __tsan_resume() is called (for debugging).
bool stop_on_start;
// Controls whether RunningOnValgrind() returns true or false.
@@ -82,6 +90,8 @@ struct Flags {
// 1 - reasonable level of synchronization (write->read)
// 2 - global synchronization of all IO operations
int io_sync;
+ // If false, the allocator will crash instead of returning 0 on out-of-memory.
+ bool allocator_may_return_null;
};
Flags *flags();
diff --git a/libsanitizer/tsan/tsan_interceptors.cc b/libsanitizer/tsan/tsan_interceptors.cc
index 8a54511b6e0..eaaf9e3ebf6 100644
--- a/libsanitizer/tsan/tsan_interceptors.cc
+++ b/libsanitizer/tsan/tsan_interceptors.cc
@@ -8,11 +8,13 @@
// This file is a part of ThreadSanitizer (TSan), a race detector.
//
// FIXME: move as many interceptors as possible into
-// sanitizer_common/sanitizer_common_interceptors.h
+// sanitizer_common/sanitizer_common_interceptors.inc
//===----------------------------------------------------------------------===//
#include "sanitizer_common/sanitizer_atomic.h"
#include "sanitizer_common/sanitizer_libc.h"
+#include "sanitizer_common/sanitizer_linux.h"
+#include "sanitizer_common/sanitizer_platform_limits_posix.h"
#include "sanitizer_common/sanitizer_placement_new.h"
#include "sanitizer_common/sanitizer_stacktrace.h"
#include "interception/interception.h"
@@ -24,18 +26,16 @@
using namespace __tsan; // NOLINT
-const int kSigCount = 128;
+const int kSigCount = 64;
struct my_siginfo_t {
- int opaque[128];
-};
-
-struct sigset_t {
- u64 val[1024 / 8 / sizeof(u64)];
+ // The size is determined by looking at sizeof of real siginfo_t on linux.
+ u64 opaque[128 / sizeof(u64)];
};
struct ucontext_t {
- uptr opaque[117];
+ // The size is determined by looking at sizeof of real ucontext_t on linux.
+ u64 opaque[936 / sizeof(u64) + 1];
};
extern "C" int pthread_attr_init(void *attr);
@@ -47,8 +47,10 @@ extern "C" int pthread_key_create(unsigned *key, void (*destructor)(void* v));
extern "C" int pthread_setspecific(unsigned key, const void *v);
extern "C" int pthread_mutexattr_gettype(void *a, int *type);
extern "C" int pthread_yield();
-extern "C" int pthread_sigmask(int how, const sigset_t *set, sigset_t *oldset);
-extern "C" int sigfillset(sigset_t *set);
+extern "C" int pthread_sigmask(int how, const __sanitizer_sigset_t *set,
+ __sanitizer_sigset_t *oldset);
+// REAL(sigfillset) defined in common interceptors.
+DECLARE_REAL(int, sigfillset, __sanitizer_sigset_t *set)
extern "C" void *pthread_self();
extern "C" void _exit(int status);
extern "C" int *__errno_location();
@@ -57,9 +59,9 @@ extern "C" void *__libc_malloc(uptr size);
extern "C" void *__libc_calloc(uptr size, uptr n);
extern "C" void *__libc_realloc(void *ptr, uptr size);
extern "C" void __libc_free(void *ptr);
+extern "C" int mallopt(int param, int value);
const int PTHREAD_MUTEX_RECURSIVE = 1;
const int PTHREAD_MUTEX_RECURSIVE_NP = 1;
-const int kPthreadAttrSize = 56;
const int EINVAL = 22;
const int EBUSY = 16;
const int EPOLL_CTL_ADD = 1;
@@ -69,6 +71,7 @@ const int SIGFPE = 8;
const int SIGSEGV = 11;
const int SIGPIPE = 13;
const int SIGBUS = 7;
+const int SIGSYS = 31;
void *const MAP_FAILED = (void*)-1;
const int PTHREAD_BARRIER_SERIAL_THREAD = -1;
const int MAP_FIXED = 0x10;
@@ -84,17 +87,12 @@ typedef void (*sighandler_t)(int sig);
#define errno (*__errno_location())
-union pthread_attr_t {
- char size[kPthreadAttrSize];
- void *align;
-};
-
struct sigaction_t {
union {
sighandler_t sa_handler;
void (*sa_sigaction)(int sig, my_siginfo_t *siginfo, void *uctx);
};
- sigset_t sa_mask;
+ __sanitizer_sigset_t sa_mask;
int sa_flags;
void (*sa_restorer)();
};
@@ -125,6 +123,21 @@ struct SignalContext {
int pending_signal_count;
SignalDesc pending_signals[kSigCount];
};
+
+// Used to ignore interceptors coming directly from libjvm.so.
+atomic_uintptr_t libjvm_begin;
+atomic_uintptr_t libjvm_end;
+
+static bool libjvm_check(uptr pc) {
+ uptr begin = atomic_load(&libjvm_begin, memory_order_relaxed);
+ if (begin != 0 && pc >= begin) {
+ uptr end = atomic_load(&libjvm_end, memory_order_relaxed);
+ if (end != 0 && pc < end)
+ return true;
+ }
+ return false;
+}
+
} // namespace __tsan
static SignalContext *SigCtx(ThreadState *thr) {
@@ -178,8 +191,7 @@ ScopedInterceptor::~ScopedInterceptor() {
StatInc(thr, StatInt_##func); \
const uptr caller_pc = GET_CALLER_PC(); \
ScopedInterceptor si(thr, #func, caller_pc); \
- const uptr pc = __sanitizer::StackTrace::GetPreviousInstructionPc( \
- __sanitizer::StackTrace::GetCurrentPc()); \
+ const uptr pc = __sanitizer::StackTrace::GetCurrentPc(); \
(void)pc; \
/**/
@@ -189,7 +201,7 @@ ScopedInterceptor::~ScopedInterceptor() {
Printf("FATAL: ThreadSanitizer: failed to intercept %s\n", #func); \
Die(); \
} \
- if (thr->in_rtl > 1) \
+ if (thr->in_rtl > 1 || libjvm_check(pc)) \
return REAL(func)(__VA_ARGS__); \
/**/
@@ -293,15 +305,6 @@ class AtExitContext {
static AtExitContext *atexit_ctx;
-static void finalize(void *arg) {
- ThreadState * thr = cur_thread();
- uptr pc = 0;
- atexit_ctx->exit(thr, pc);
- int status = Finalize(cur_thread());
- if (status)
- _exit(status);
-}
-
TSAN_INTERCEPTOR(int, atexit, void (*f)()) {
if (cur_thread()->in_symbolizer)
return 0;
@@ -320,25 +323,123 @@ TSAN_INTERCEPTOR(int, __cxa_atexit, void (*f)(void *a), void *arg, void *dso) {
if (cur_thread()->in_symbolizer)
return 0;
SCOPED_TSAN_INTERCEPTOR(__cxa_atexit, f, arg, dso);
- if (dso)
- return REAL(__cxa_atexit)(f, arg, dso);
+ if (dso) {
+ // Memory allocation in __cxa_atexit will race with free during exit,
+ // because we do not see synchronization around atexit callback list.
+ ThreadIgnoreBegin(thr);
+ int res = REAL(__cxa_atexit)(f, arg, dso);
+ ThreadIgnoreEnd(thr);
+ return res;
+ }
return atexit_ctx->atexit(thr, pc, false, (void(*)())f, arg);
}
-TSAN_INTERCEPTOR(void, longjmp, void *env, int val) {
- SCOPED_TSAN_INTERCEPTOR(longjmp, env, val);
- Printf("ThreadSanitizer: longjmp() is not supported\n");
- Die();
+// Cleanup old bufs.
+static void JmpBufGarbageCollect(ThreadState *thr, uptr sp) {
+ for (uptr i = 0; i < thr->jmp_bufs.Size(); i++) {
+ JmpBuf *buf = &thr->jmp_bufs[i];
+ if (buf->sp <= sp) {
+ uptr sz = thr->jmp_bufs.Size();
+ thr->jmp_bufs[i] = thr->jmp_bufs[sz - 1];
+ thr->jmp_bufs.PopBack();
+ i--;
+ }
+ }
}
-TSAN_INTERCEPTOR(void, siglongjmp, void *env, int val) {
- SCOPED_TSAN_INTERCEPTOR(siglongjmp, env, val);
- Printf("ThreadSanitizer: siglongjmp() is not supported\n");
- Die();
+static void SetJmp(ThreadState *thr, uptr sp, uptr mangled_sp) {
+ if (thr->shadow_stack_pos == 0) // called from libc guts during bootstrap
+ return;
+ // Cleanup old bufs.
+ JmpBufGarbageCollect(thr, sp);
+ // Remember the buf.
+ JmpBuf *buf = thr->jmp_bufs.PushBack();
+ buf->sp = sp;
+ buf->mangled_sp = mangled_sp;
+ buf->shadow_stack_pos = thr->shadow_stack_pos;
+}
+
+static void LongJmp(ThreadState *thr, uptr *env) {
+ uptr mangled_sp = env[6];
+ // Find the saved buf by mangled_sp.
+ for (uptr i = 0; i < thr->jmp_bufs.Size(); i++) {
+ JmpBuf *buf = &thr->jmp_bufs[i];
+ if (buf->mangled_sp == mangled_sp) {
+ CHECK_GE(thr->shadow_stack_pos, buf->shadow_stack_pos);
+ // Unwind the stack.
+ while (thr->shadow_stack_pos > buf->shadow_stack_pos)
+ FuncExit(thr);
+ JmpBufGarbageCollect(thr, buf->sp - 1); // do not collect buf->sp
+ return;
+ }
+ }
+ Printf("ThreadSanitizer: can't find longjmp buf\n");
+ CHECK(0);
+}
+
+// FIXME: put everything below into a common extern "C" block?
+extern "C" void __tsan_setjmp(uptr sp, uptr mangled_sp) {
+ ScopedInRtl in_rtl;
+ SetJmp(cur_thread(), sp, mangled_sp);
+}
+
+// Not called. Merely to satisfy TSAN_INTERCEPT().
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE
+int __interceptor_setjmp(void *env);
+extern "C" int __interceptor_setjmp(void *env) {
+ CHECK(0);
+ return 0;
+}
+
+// FIXME: any reason to have a separate declaration?
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE
+int __interceptor__setjmp(void *env);
+extern "C" int __interceptor__setjmp(void *env) {
+ CHECK(0);
+ return 0;
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE
+int __interceptor_sigsetjmp(void *env);
+extern "C" int __interceptor_sigsetjmp(void *env) {
+ CHECK(0);
+ return 0;
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE
+int __interceptor___sigsetjmp(void *env);
+extern "C" int __interceptor___sigsetjmp(void *env) {
+ CHECK(0);
+ return 0;
+}
+
+extern "C" int setjmp(void *env);
+extern "C" int _setjmp(void *env);
+extern "C" int sigsetjmp(void *env);
+extern "C" int __sigsetjmp(void *env);
+DEFINE_REAL(int, setjmp, void *env)
+DEFINE_REAL(int, _setjmp, void *env)
+DEFINE_REAL(int, sigsetjmp, void *env)
+DEFINE_REAL(int, __sigsetjmp, void *env)
+
+TSAN_INTERCEPTOR(void, longjmp, uptr *env, int val) {
+ {
+ SCOPED_TSAN_INTERCEPTOR(longjmp, env, val);
+ }
+ LongJmp(cur_thread(), env);
+ REAL(longjmp)(env, val);
+}
+
+TSAN_INTERCEPTOR(void, siglongjmp, uptr *env, int val) {
+ {
+ SCOPED_TSAN_INTERCEPTOR(siglongjmp, env, val);
+ }
+ LongJmp(cur_thread(), env);
+ REAL(siglongjmp)(env, val);
}
TSAN_INTERCEPTOR(void*, malloc, uptr size) {
- if (cur_thread()->in_symbolizer)
+ if (cur_thread()->in_symbolizer || libjvm_check(GET_CALLER_PC()))
return __libc_malloc(size);
void *p = 0;
{
@@ -355,21 +456,23 @@ TSAN_INTERCEPTOR(void*, __libc_memalign, uptr align, uptr sz) {
}
TSAN_INTERCEPTOR(void*, calloc, uptr size, uptr n) {
- if (cur_thread()->in_symbolizer)
+ if (cur_thread()->in_symbolizer || libjvm_check(GET_CALLER_PC()))
return __libc_calloc(size, n);
- if (__sanitizer::CallocShouldReturnNullDueToOverflow(size, n)) return 0;
+ if (__sanitizer::CallocShouldReturnNullDueToOverflow(size, n))
+ return AllocatorReturnNull();
void *p = 0;
{
SCOPED_INTERCEPTOR_RAW(calloc, size, n);
p = user_alloc(thr, pc, n * size);
- if (p) internal_memset(p, 0, n * size);
+ if (p)
+ internal_memset(p, 0, n * size);
}
invoke_malloc_hook(p, n * size);
return p;
}
TSAN_INTERCEPTOR(void*, realloc, void *p, uptr size) {
- if (cur_thread()->in_symbolizer)
+ if (cur_thread()->in_symbolizer || libjvm_check(GET_CALLER_PC()))
return __libc_realloc(p, size);
if (p)
invoke_free_hook(p);
@@ -384,7 +487,7 @@ TSAN_INTERCEPTOR(void*, realloc, void *p, uptr size) {
TSAN_INTERCEPTOR(void, free, void *p) {
if (p == 0)
return;
- if (cur_thread()->in_symbolizer)
+ if (cur_thread()->in_symbolizer || libjvm_check(GET_CALLER_PC()))
return __libc_free(p);
invoke_free_hook(p);
SCOPED_INTERCEPTOR_RAW(free, p);
@@ -394,15 +497,22 @@ TSAN_INTERCEPTOR(void, free, void *p) {
TSAN_INTERCEPTOR(void, cfree, void *p) {
if (p == 0)
return;
- if (cur_thread()->in_symbolizer)
+ if (cur_thread()->in_symbolizer || libjvm_check(GET_CALLER_PC()))
return __libc_free(p);
invoke_free_hook(p);
SCOPED_INTERCEPTOR_RAW(cfree, p);
user_free(thr, pc, p);
}
+TSAN_INTERCEPTOR(uptr, malloc_usable_size, void *p) {
+ SCOPED_INTERCEPTOR_RAW(malloc_usable_size, p);
+ if (libjvm_check(pc))
+ return malloc_usable_size(p);
+ return user_alloc_usable_size(thr, pc, p);
+}
+
#define OPERATOR_NEW_BODY(mangled_name) \
- if (cur_thread()->in_symbolizer) \
+ if (cur_thread()->in_symbolizer || libjvm_check(GET_CALLER_PC())) \
return __libc_malloc(size); \
void *p = 0; \
{ \
@@ -412,36 +522,58 @@ TSAN_INTERCEPTOR(void, cfree, void *p) {
invoke_malloc_hook(p, size); \
return p;
+SANITIZER_INTERFACE_ATTRIBUTE
+void *operator new(__sanitizer::uptr size);
void *operator new(__sanitizer::uptr size) {
OPERATOR_NEW_BODY(_Znwm);
}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void *operator new[](__sanitizer::uptr size);
void *operator new[](__sanitizer::uptr size) {
OPERATOR_NEW_BODY(_Znam);
}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void *operator new(__sanitizer::uptr size, std::nothrow_t const&);
void *operator new(__sanitizer::uptr size, std::nothrow_t const&) {
OPERATOR_NEW_BODY(_ZnwmRKSt9nothrow_t);
}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void *operator new[](__sanitizer::uptr size, std::nothrow_t const&);
void *operator new[](__sanitizer::uptr size, std::nothrow_t const&) {
OPERATOR_NEW_BODY(_ZnamRKSt9nothrow_t);
}
#define OPERATOR_DELETE_BODY(mangled_name) \
if (ptr == 0) return; \
- if (cur_thread()->in_symbolizer) \
+ if (cur_thread()->in_symbolizer || libjvm_check(GET_CALLER_PC())) \
return __libc_free(ptr); \
invoke_free_hook(ptr); \
SCOPED_INTERCEPTOR_RAW(mangled_name, ptr); \
user_free(thr, pc, ptr);
+SANITIZER_INTERFACE_ATTRIBUTE
+void operator delete(void *ptr);
void operator delete(void *ptr) {
OPERATOR_DELETE_BODY(_ZdlPv);
}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void operator delete[](void *ptr);
void operator delete[](void *ptr) {
OPERATOR_DELETE_BODY(_ZdlPvRKSt9nothrow_t);
}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void operator delete(void *ptr, std::nothrow_t const&);
void operator delete(void *ptr, std::nothrow_t const&) {
OPERATOR_DELETE_BODY(_ZdaPv);
}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void operator delete[](void *ptr, std::nothrow_t const&);
void operator delete[](void *ptr, std::nothrow_t const&) {
OPERATOR_DELETE_BODY(_ZdaPvRKSt9nothrow_t);
}
@@ -479,30 +611,6 @@ TSAN_INTERCEPTOR(int, memcmp, const void *s1, const void *s2, uptr n) {
return res;
}
-TSAN_INTERCEPTOR(int, strcmp, const char *s1, const char *s2) {
- SCOPED_TSAN_INTERCEPTOR(strcmp, s1, s2);
- uptr len = 0;
- for (; s1[len] && s2[len]; len++) {
- if (s1[len] != s2[len])
- break;
- }
- MemoryAccessRange(thr, pc, (uptr)s1, len + 1, false);
- MemoryAccessRange(thr, pc, (uptr)s2, len + 1, false);
- return s1[len] - s2[len];
-}
-
-TSAN_INTERCEPTOR(int, strncmp, const char *s1, const char *s2, uptr n) {
- SCOPED_TSAN_INTERCEPTOR(strncmp, s1, s2, n);
- uptr len = 0;
- for (; len < n && s1[len] && s2[len]; len++) {
- if (s1[len] != s2[len])
- break;
- }
- MemoryAccessRange(thr, pc, (uptr)s1, len < n ? len + 1 : n, false);
- MemoryAccessRange(thr, pc, (uptr)s2, len < n ? len + 1 : n, false);
- return len == n ? 0 : s1[len] - s2[len];
-}
-
TSAN_INTERCEPTOR(void*, memchr, void *s, int c, uptr n) {
SCOPED_TSAN_INTERCEPTOR(memchr, s, c, n);
void *res = REAL(memchr)(s, c, n);
@@ -572,6 +680,21 @@ TSAN_INTERCEPTOR(const char*, strstr, const char *s1, const char *s2) {
return res;
}
+TSAN_INTERCEPTOR(char*, strdup, const char *str) {
+ SCOPED_TSAN_INTERCEPTOR(strdup, str);
+ if (libjvm_check(pc)) {
+ // The memory must come from libc malloc,
+ // and we must not instrument accesses in this case.
+ uptr n = internal_strlen(str) + 1;
+ void *p = __libc_malloc(n);
+ if (p == 0)
+ return 0;
+ return (char*)internal_memcpy(p, str, n);
+ }
+ // strdup will call malloc, so no instrumentation is required here.
+ return REAL(strdup)(str);
+}
+
static bool fix_mmap_addr(void **addr, long_t sz, int flags) {
if (*addr) {
if (!IsAppMem((uptr)*addr) || !IsAppMem((uptr)*addr + sz - 1)) {
@@ -595,7 +718,7 @@ TSAN_INTERCEPTOR(void*, mmap, void *addr, long_t sz, int prot,
if (res != MAP_FAILED) {
if (fd > 0)
FdAccess(thr, pc, fd);
- MemoryResetRange(thr, pc, (uptr)res, sz);
+ MemoryRangeImitateWrite(thr, pc, (uptr)res, sz);
}
return res;
}
@@ -609,13 +732,14 @@ TSAN_INTERCEPTOR(void*, mmap64, void *addr, long_t sz, int prot,
if (res != MAP_FAILED) {
if (fd > 0)
FdAccess(thr, pc, fd);
- MemoryResetRange(thr, pc, (uptr)res, sz);
+ MemoryRangeImitateWrite(thr, pc, (uptr)res, sz);
}
return res;
}
TSAN_INTERCEPTOR(int, munmap, void *addr, long_t sz) {
SCOPED_TSAN_INTERCEPTOR(munmap, addr, sz);
+ DontNeedShadowFor((uptr)addr, sz);
int res = REAL(munmap)(addr, sz);
return res;
}
@@ -727,21 +851,21 @@ extern "C" void *__tsan_thread_start_func(void *arg) {
TSAN_INTERCEPTOR(int, pthread_create,
void *th, void *attr, void *(*callback)(void*), void * param) {
SCOPED_TSAN_INTERCEPTOR(pthread_create, th, attr, callback, param);
- pthread_attr_t myattr;
+ __sanitizer_pthread_attr_t myattr;
if (attr == 0) {
pthread_attr_init(&myattr);
attr = &myattr;
}
int detached = 0;
pthread_attr_getdetachstate(attr, &detached);
- uptr stacksize = 0;
- pthread_attr_getstacksize(attr, &stacksize);
- // We place the huge ThreadState object into TLS, account for that.
- const uptr minstacksize = GetTlsSize() + 128*1024;
- if (stacksize < minstacksize) {
- DPrintf("ThreadSanitizer: stacksize %zu->%zu\n", stacksize, minstacksize);
- pthread_attr_setstacksize(attr, minstacksize);
- }
+
+#if defined(TSAN_DEBUG_OUTPUT)
+ int verbosity = (TSAN_DEBUG_OUTPUT);
+#else
+ int verbosity = 0;
+#endif
+ AdjustStackSizeLinux(attr, verbosity);
+
ThreadParam p;
p.callback = callback;
p.param = param;
@@ -960,30 +1084,30 @@ TSAN_INTERCEPTOR(int, pthread_rwlock_unlock, void *m) {
return res;
}
-// libpthread.so contains several versions of pthread_cond_init symbol.
-// When we just dlsym() it, we get the wrong (old) version.
-/*
TSAN_INTERCEPTOR(int, pthread_cond_init, void *c, void *a) {
SCOPED_TSAN_INTERCEPTOR(pthread_cond_init, c, a);
+ MemoryWrite(thr, pc, (uptr)c, kSizeLog1);
int res = REAL(pthread_cond_init)(c, a);
return res;
}
-*/
TSAN_INTERCEPTOR(int, pthread_cond_destroy, void *c) {
SCOPED_TSAN_INTERCEPTOR(pthread_cond_destroy, c);
+ MemoryWrite(thr, pc, (uptr)c, kSizeLog1);
int res = REAL(pthread_cond_destroy)(c);
return res;
}
TSAN_INTERCEPTOR(int, pthread_cond_signal, void *c) {
SCOPED_TSAN_INTERCEPTOR(pthread_cond_signal, c);
+ MemoryRead(thr, pc, (uptr)c, kSizeLog1);
int res = REAL(pthread_cond_signal)(c);
return res;
}
TSAN_INTERCEPTOR(int, pthread_cond_broadcast, void *c) {
SCOPED_TSAN_INTERCEPTOR(pthread_cond_broadcast, c);
+ MemoryRead(thr, pc, (uptr)c, kSizeLog1);
int res = REAL(pthread_cond_broadcast)(c);
return res;
}
@@ -991,14 +1115,17 @@ TSAN_INTERCEPTOR(int, pthread_cond_broadcast, void *c) {
TSAN_INTERCEPTOR(int, pthread_cond_wait, void *c, void *m) {
SCOPED_TSAN_INTERCEPTOR(pthread_cond_wait, c, m);
MutexUnlock(thr, pc, (uptr)m);
+ MemoryRead(thr, pc, (uptr)c, kSizeLog1);
int res = REAL(pthread_cond_wait)(c, m);
MutexLock(thr, pc, (uptr)m);
return res;
}
-TSAN_INTERCEPTOR(int, pthread_cond_timedwait, void *c, void *m, void *abstime) {
+TSAN_INTERCEPTOR(int, pthread_cond_timedwait, void *c, void *m,
+ void *abstime) {
SCOPED_TSAN_INTERCEPTOR(pthread_cond_timedwait, c, m, abstime);
MutexUnlock(thr, pc, (uptr)m);
+ MemoryRead(thr, pc, (uptr)c, kSizeLog1);
int res = REAL(pthread_cond_timedwait)(c, m, abstime);
MutexLock(thr, pc, (uptr)m);
return res;
@@ -1309,22 +1436,6 @@ TSAN_INTERCEPTOR(int, listen, int fd, int backlog) {
return res;
}
-TSAN_INTERCEPTOR(int, accept, int fd, void *addr, unsigned *addrlen) {
- SCOPED_TSAN_INTERCEPTOR(accept, fd, addr, addrlen);
- int fd2 = REAL(accept)(fd, addr, addrlen);
- if (fd >= 0 && fd2 >= 0)
- FdSocketAccept(thr, pc, fd, fd2);
- return fd2;
-}
-
-TSAN_INTERCEPTOR(int, accept4, int fd, void *addr, unsigned *addrlen, int f) {
- SCOPED_TSAN_INTERCEPTOR(accept4, fd, addr, addrlen, f);
- int fd2 = REAL(accept4)(fd, addr, addrlen, f);
- if (fd >= 0 && fd2 >= 0)
- FdSocketAccept(thr, pc, fd, fd2);
- return fd2;
-}
-
TSAN_INTERCEPTOR(int, epoll_create, int size) {
SCOPED_TSAN_INTERCEPTOR(epoll_create, size);
int fd = REAL(epoll_create)(size);
@@ -1383,40 +1494,6 @@ TSAN_INTERCEPTOR(int, pipe2, int *pipefd, int flags) {
return res;
}
-TSAN_INTERCEPTOR(long_t, readv, int fd, void *vec, int cnt) {
- SCOPED_TSAN_INTERCEPTOR(readv, fd, vec, cnt);
- int res = REAL(readv)(fd, vec, cnt);
- if (res >= 0 && fd >= 0) {
- FdAcquire(thr, pc, fd);
- }
- return res;
-}
-
-TSAN_INTERCEPTOR(long_t, preadv64, int fd, void *vec, int cnt, u64 off) {
- SCOPED_TSAN_INTERCEPTOR(preadv64, fd, vec, cnt, off);
- int res = REAL(preadv64)(fd, vec, cnt, off);
- if (res >= 0 && fd >= 0) {
- FdAcquire(thr, pc, fd);
- }
- return res;
-}
-
-TSAN_INTERCEPTOR(long_t, writev, int fd, void *vec, int cnt) {
- SCOPED_TSAN_INTERCEPTOR(writev, fd, vec, cnt);
- if (fd >= 0)
- FdRelease(thr, pc, fd);
- int res = REAL(writev)(fd, vec, cnt);
- return res;
-}
-
-TSAN_INTERCEPTOR(long_t, pwritev64, int fd, void *vec, int cnt, u64 off) {
- SCOPED_TSAN_INTERCEPTOR(pwritev64, fd, vec, cnt, off);
- if (fd >= 0)
- FdRelease(thr, pc, fd);
- int res = REAL(pwritev64)(fd, vec, cnt, off);
- return res;
-}
-
TSAN_INTERCEPTOR(long_t, send, int fd, void *buf, long_t len, int flags) {
SCOPED_TSAN_INTERCEPTOR(send, fd, buf, len, flags);
if (fd >= 0)
@@ -1442,15 +1519,6 @@ TSAN_INTERCEPTOR(long_t, recv, int fd, void *buf, long_t len, int flags) {
return res;
}
-TSAN_INTERCEPTOR(long_t, recvmsg, int fd, void *msg, int flags) {
- SCOPED_TSAN_INTERCEPTOR(recvmsg, fd, msg, flags);
- int res = REAL(recvmsg)(fd, msg, flags);
- if (res >= 0 && fd >= 0) {
- FdAcquire(thr, pc, fd);
- }
- return res;
-}
-
TSAN_INTERCEPTOR(int, unlink, char *path) {
SCOPED_TSAN_INTERCEPTOR(unlink, path);
Release(thr, pc, File2addr(path));
@@ -1515,6 +1583,17 @@ TSAN_INTERCEPTOR(uptr, fwrite, const void *p, uptr size, uptr nmemb, void *f) {
return REAL(fwrite)(p, size, nmemb, f);
}
+TSAN_INTERCEPTOR(int, fflush, void *stream) {
+ SCOPED_TSAN_INTERCEPTOR(fflush, stream);
+ return REAL(fflush)(stream);
+}
+
+TSAN_INTERCEPTOR(void, abort, int fake) {
+ SCOPED_TSAN_INTERCEPTOR(abort, fake);
+ REAL(fflush)(0);
+ REAL(abort)(fake);
+}
+
TSAN_INTERCEPTOR(int, puts, const char *s) {
SCOPED_TSAN_INTERCEPTOR(puts, s);
MemoryAccessRange(thr, pc, (uptr)s, internal_strlen(s), false);
@@ -1556,26 +1635,19 @@ TSAN_INTERCEPTOR(int, epoll_wait, int epfd, void *ev, int cnt, int timeout) {
return res;
}
-TSAN_INTERCEPTOR(int, poll, void *fds, long_t nfds, int timeout) {
- SCOPED_TSAN_INTERCEPTOR(poll, fds, nfds, timeout);
- int res = BLOCK_REAL(poll)(fds, nfds, timeout);
- return res;
-}
-
-static void ALWAYS_INLINE rtl_generic_sighandler(bool sigact, int sig,
+void ALWAYS_INLINE rtl_generic_sighandler(bool sigact, int sig,
my_siginfo_t *info, void *ctx) {
ThreadState *thr = cur_thread();
SignalContext *sctx = SigCtx(thr);
// Don't mess with synchronous signals.
if (sig == SIGSEGV || sig == SIGBUS || sig == SIGILL ||
- sig == SIGABRT || sig == SIGFPE || sig == SIGPIPE ||
+ sig == SIGABRT || sig == SIGFPE || sig == SIGPIPE || sig == SIGSYS ||
// If we are sending signal to ourselves, we must process it now.
(sctx && sig == sctx->int_signal_send) ||
// If we are in blocking function, we can safely process it now
// (but check if we are in a recursive interceptor,
// i.e. pthread_join()->munmap()).
(sctx && sctx->in_blocking_func == 1 && thr->in_rtl == 1)) {
- CHECK(thr->in_rtl == 0 || thr->in_rtl == 1);
int in_rtl = thr->in_rtl;
thr->in_rtl = 0;
CHECK_EQ(thr->in_signal_handler, false);
@@ -1621,7 +1693,7 @@ TSAN_INTERCEPTOR(int, sigaction, int sig, sigaction_t *act, sigaction_t *old) {
internal_memcpy(&sigactions[sig], act, sizeof(*act));
sigaction_t newact;
internal_memcpy(&newact, act, sizeof(newact));
- sigfillset(&newact.sa_mask);
+ REAL(sigfillset)(&newact.sa_mask);
if (act->sa_handler != SIG_IGN && act->sa_handler != SIG_DFL) {
if (newact.sa_flags & SA_SIGINFO)
newact.sa_sigaction = rtl_sigaction;
@@ -1644,6 +1716,11 @@ TSAN_INTERCEPTOR(sighandler_t, signal, int sig, sighandler_t h) {
return old.sa_handler;
}
+TSAN_INTERCEPTOR(int, sigsuspend, const __sanitizer_sigset_t *mask) {
+ SCOPED_TSAN_INTERCEPTOR(sigsuspend, mask);
+ return REAL(sigsuspend)(mask);
+}
+
TSAN_INTERCEPTOR(int, raise, int sig) {
SCOPED_TSAN_INTERCEPTOR(raise, sig);
SignalContext *sctx = SigCtx(thr);
@@ -1661,11 +1738,11 @@ TSAN_INTERCEPTOR(int, kill, int pid, int sig) {
SignalContext *sctx = SigCtx(thr);
CHECK_NE(sctx, 0);
int prev = sctx->int_signal_send;
- if (pid == GetPid()) {
+ if (pid == (int)internal_getpid()) {
sctx->int_signal_send = sig;
}
int res = REAL(kill)(pid, sig);
- if (pid == GetPid()) {
+ if (pid == (int)internal_getpid()) {
CHECK_EQ(sctx->int_signal_send, sig);
sctx->int_signal_send = prev;
}
@@ -1694,13 +1771,30 @@ TSAN_INTERCEPTOR(int, gettimeofday, void *tv, void *tz) {
return REAL(gettimeofday)(tv, tz);
}
+TSAN_INTERCEPTOR(int, getaddrinfo, void *node, void *service,
+ void *hints, void *rv) {
+ SCOPED_TSAN_INTERCEPTOR(getaddrinfo, node, service, hints, rv);
+ // We miss atomic synchronization in getaddrinfo,
+ // and can report false race between malloc and free
+ // inside of getaddrinfo. So ignore memory accesses.
+ ThreadIgnoreBegin(thr);
+ // getaddrinfo calls fopen, which can be intercepted by user.
+ thr->in_rtl--;
+ CHECK_EQ(thr->in_rtl, 0);
+ int res = REAL(getaddrinfo)(node, service, hints, rv);
+ thr->in_rtl++;
+ ThreadIgnoreEnd(thr);
+ return res;
+}
+
// Linux kernel has a bug that leads to kernel deadlock if a process
// maps TBs of memory and then calls mlock().
static void MlockIsUnsupported() {
static atomic_uint8_t printed;
if (atomic_exchange(&printed, 1, memory_order_relaxed))
return;
- Printf("INFO: ThreadSanitizer ignores mlock/mlockall/munlock/munlockall\n");
+ if (flags()->verbosity > 0)
+ Printf("INFO: ThreadSanitizer ignores mlock/mlockall/munlock/munlockall\n");
}
TSAN_INTERCEPTOR(int, mlock, const void *addr, uptr len) {
@@ -1725,7 +1819,6 @@ TSAN_INTERCEPTOR(int, munlockall, void) {
TSAN_INTERCEPTOR(int, fork, int fake) {
SCOPED_TSAN_INTERCEPTOR(fork, fake);
- // It's intercepted merely to process pending signals.
int pid = REAL(fork)(fake);
if (pid == 0) {
// child
@@ -1742,27 +1835,106 @@ struct TsanInterceptorContext {
const uptr pc;
};
-#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
- MemoryAccessRange(((TsanInterceptorContext*)ctx)->thr, \
- ((TsanInterceptorContext*)ctx)->pc, \
- (uptr)ptr, size, true)
-#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \
- MemoryAccessRange(((TsanInterceptorContext*)ctx)->thr, \
- ((TsanInterceptorContext*)ctx)->pc, \
- (uptr)ptr, size, false)
-#define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \
- SCOPED_TSAN_INTERCEPTOR(func, __VA_ARGS__) \
- TsanInterceptorContext _ctx = {thr, caller_pc, pc}; \
- ctx = (void*)&_ctx; \
- (void)ctx;
+#include "sanitizer_common/sanitizer_platform_interceptors.h"
+// Causes interceptor recursion (getpwuid_r() calls fopen())
+#undef SANITIZER_INTERCEPT_GETPWNAM_AND_FRIENDS
+#undef SANITIZER_INTERCEPT_GETPWNAM_R_AND_FRIENDS
+// Causes interceptor recursion (getaddrinfo() and fopen())
+#undef SANITIZER_INTERCEPT_GETADDRINFO
+#undef SANITIZER_INTERCEPT_GETNAMEINFO
+// Causes interceptor recursion (glob64() calls lstat64())
+#undef SANITIZER_INTERCEPT_GLOB
+
+#define COMMON_INTERCEPTOR_UNPOISON_PARAM(ctx, count) \
+ do { \
+ } while (false)
+#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
+ MemoryAccessRange(((TsanInterceptorContext *)ctx)->thr, \
+ ((TsanInterceptorContext *)ctx)->pc, (uptr)ptr, size, \
+ true)
+#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \
+ MemoryAccessRange(((TsanInterceptorContext *) ctx)->thr, \
+ ((TsanInterceptorContext *) ctx)->pc, (uptr) ptr, size, \
+ false)
+#define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \
+ SCOPED_TSAN_INTERCEPTOR(func, __VA_ARGS__); \
+ TsanInterceptorContext _ctx = {thr, caller_pc, pc}; \
+ ctx = (void *)&_ctx; \
+ (void) ctx;
#define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
- FdAcquire(((TsanInterceptorContext*)ctx)->thr, pc, fd)
+ FdAcquire(((TsanInterceptorContext *) ctx)->thr, pc, fd)
#define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \
- FdRelease(((TsanInterceptorContext*)ctx)->thr, pc, fd)
+ FdRelease(((TsanInterceptorContext *) ctx)->thr, pc, fd)
+#define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \
+ FdSocketAccept(((TsanInterceptorContext *) ctx)->thr, pc, fd, newfd)
#define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) \
- ThreadSetName(((TsanInterceptorContext*)ctx)->thr, name)
+ ThreadSetName(((TsanInterceptorContext *) ctx)->thr, name)
+#define COMMON_INTERCEPTOR_BLOCK_REAL(name) BLOCK_REAL(name)
#include "sanitizer_common/sanitizer_common_interceptors.inc"
+#define TSAN_SYSCALL() \
+ ThreadState *thr = cur_thread(); \
+ ScopedSyscall scoped_syscall(thr) \
+/**/
+
+struct ScopedSyscall {
+ ThreadState *thr;
+
+ explicit ScopedSyscall(ThreadState *thr)
+ : thr(thr) {
+ if (thr->in_rtl == 0)
+ Initialize(thr);
+ thr->in_rtl++;
+ }
+
+ ~ScopedSyscall() {
+ thr->in_rtl--;
+ if (thr->in_rtl == 0)
+ ProcessPendingSignals(thr);
+ }
+};
+
+static void syscall_access_range(uptr pc, uptr p, uptr s, bool write) {
+ TSAN_SYSCALL();
+ MemoryAccessRange(thr, pc, p, s, write);
+}
+
+static void syscall_fd_close(uptr pc, int fd) {
+ TSAN_SYSCALL();
+ if (fd >= 0)
+ FdClose(thr, pc, fd);
+}
+
+static void syscall_pre_fork(uptr pc) {
+ TSAN_SYSCALL();
+}
+
+static void syscall_post_fork(uptr pc, int res) {
+ TSAN_SYSCALL();
+ if (res == 0) {
+ // child
+ FdOnFork(thr, pc);
+ } else if (res > 0) {
+ // parent
+ }
+}
+
+#define COMMON_SYSCALL_PRE_READ_RANGE(p, s) \
+ syscall_access_range(GET_CALLER_PC(), (uptr)(p), (uptr)(s), false)
+#define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) \
+ syscall_access_range(GET_CALLER_PC(), (uptr)(p), (uptr)(s), true)
+#define COMMON_SYSCALL_POST_READ_RANGE(p, s) \
+ do { } while (false)
+#define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) \
+ do { } while (false)
+#define COMMON_SYSCALL_FD_CLOSE(fd) \
+ syscall_fd_close(GET_CALLER_PC(), fd)
+#define COMMON_SYSCALL_PRE_FORK() \
+ syscall_pre_fork(GET_CALLER_PC())
+#define COMMON_SYSCALL_POST_FORK(res) \
+ syscall_post_fork(GET_CALLER_PC(), res)
+#include "sanitizer_common/sanitizer_common_syscalls.inc"
+
namespace __tsan {
void ProcessPendingSignals(ThreadState *thr) {
@@ -1774,8 +1946,8 @@ void ProcessPendingSignals(ThreadState *thr) {
thr->in_signal_handler = true;
sctx->pending_signal_count = 0;
// These are too big for stack.
- static THREADLOCAL sigset_t emptyset, oldset;
- sigfillset(&emptyset);
+ static THREADLOCAL __sanitizer_sigset_t emptyset, oldset;
+ REAL(sigfillset)(&emptyset);
pthread_sigmask(SIG_SETMASK, &emptyset, &oldset);
for (int sig = 0; sig < kSigCount; sig++) {
SignalDesc *signal = &sctx->pending_signals[sig];
@@ -1796,8 +1968,9 @@ void ProcessPendingSignals(ThreadState *thr) {
uptr pc = signal->sigaction ?
(uptr)sigactions[sig].sa_sigaction :
(uptr)sigactions[sig].sa_handler;
+ pc += 1; // return address is expected, OutputReport() will undo this
stack.Init(&pc, 1);
- Lock l(&ctx->thread_mtx);
+ ThreadRegistryLock l(ctx->thread_registry);
ScopedReport rep(ReportTypeErrnoInSignal);
if (!IsFiredSuppression(ctx, rep, stack)) {
rep.AddStack(&stack);
@@ -1813,6 +1986,16 @@ void ProcessPendingSignals(ThreadState *thr) {
thr->in_signal_handler = false;
}
+static void finalize(void *arg) {
+ ThreadState * thr = cur_thread();
+ uptr pc = 0;
+ atexit_ctx->exit(thr, pc);
+ int status = Finalize(cur_thread());
+ REAL(fflush)(0);
+ if (status)
+ _exit(status);
+}
+
static void unreachable() {
Printf("FATAL: ThreadSanitizer: unreachable called\n");
Die();
@@ -1826,8 +2009,16 @@ void InitializeInterceptors() {
REAL(memcpy) = internal_memcpy;
REAL(memcmp) = internal_memcmp;
+ // Instruct libc malloc to consume less memory.
+ mallopt(1, 0); // M_MXFAST
+ mallopt(-3, 32*1024); // M_MMAP_THRESHOLD
+
SANITIZER_COMMON_INTERCEPTORS_INIT;
+ TSAN_INTERCEPT(setjmp);
+ TSAN_INTERCEPT(_setjmp);
+ TSAN_INTERCEPT(sigsetjmp);
+ TSAN_INTERCEPT(__sigsetjmp);
TSAN_INTERCEPT(longjmp);
TSAN_INTERCEPT(siglongjmp);
@@ -1848,7 +2039,6 @@ void InitializeInterceptors() {
TSAN_INTERCEPT(strlen);
TSAN_INTERCEPT(memset);
TSAN_INTERCEPT(memcpy);
- TSAN_INTERCEPT(strcmp);
TSAN_INTERCEPT(memchr);
TSAN_INTERCEPT(memrchr);
TSAN_INTERCEPT(memmove);
@@ -1856,10 +2046,10 @@ void InitializeInterceptors() {
TSAN_INTERCEPT(strchr);
TSAN_INTERCEPT(strchrnul);
TSAN_INTERCEPT(strrchr);
- TSAN_INTERCEPT(strncmp);
TSAN_INTERCEPT(strcpy); // NOLINT
TSAN_INTERCEPT(strncpy);
TSAN_INTERCEPT(strstr);
+ TSAN_INTERCEPT(strdup);
TSAN_INTERCEPT(pthread_create);
TSAN_INTERCEPT(pthread_join);
@@ -1888,12 +2078,12 @@ void InitializeInterceptors() {
TSAN_INTERCEPT(pthread_rwlock_timedwrlock);
TSAN_INTERCEPT(pthread_rwlock_unlock);
- // TSAN_INTERCEPT(pthread_cond_init);
- TSAN_INTERCEPT(pthread_cond_destroy);
- TSAN_INTERCEPT(pthread_cond_signal);
- TSAN_INTERCEPT(pthread_cond_broadcast);
- TSAN_INTERCEPT(pthread_cond_wait);
- TSAN_INTERCEPT(pthread_cond_timedwait);
+ INTERCEPT_FUNCTION_VER(pthread_cond_init, GLIBC_2.3.2);
+ INTERCEPT_FUNCTION_VER(pthread_cond_destroy, GLIBC_2.3.2);
+ INTERCEPT_FUNCTION_VER(pthread_cond_signal, GLIBC_2.3.2);
+ INTERCEPT_FUNCTION_VER(pthread_cond_broadcast, GLIBC_2.3.2);
+ INTERCEPT_FUNCTION_VER(pthread_cond_wait, GLIBC_2.3.2);
+ INTERCEPT_FUNCTION_VER(pthread_cond_timedwait, GLIBC_2.3.2);
TSAN_INTERCEPT(pthread_barrier_init);
TSAN_INTERCEPT(pthread_barrier_destroy);
@@ -1937,8 +2127,6 @@ void InitializeInterceptors() {
TSAN_INTERCEPT(connect);
TSAN_INTERCEPT(bind);
TSAN_INTERCEPT(listen);
- TSAN_INTERCEPT(accept);
- TSAN_INTERCEPT(accept4);
TSAN_INTERCEPT(epoll_create);
TSAN_INTERCEPT(epoll_create1);
TSAN_INTERCEPT(close);
@@ -1947,14 +2135,9 @@ void InitializeInterceptors() {
TSAN_INTERCEPT(pipe);
TSAN_INTERCEPT(pipe2);
- TSAN_INTERCEPT(readv);
- TSAN_INTERCEPT(preadv64);
- TSAN_INTERCEPT(writev);
- TSAN_INTERCEPT(pwritev64);
TSAN_INTERCEPT(send);
TSAN_INTERCEPT(sendmsg);
TSAN_INTERCEPT(recv);
- TSAN_INTERCEPT(recvmsg);
TSAN_INTERCEPT(unlink);
TSAN_INTERCEPT(fopen);
@@ -1962,16 +2145,18 @@ void InitializeInterceptors() {
TSAN_INTERCEPT(fclose);
TSAN_INTERCEPT(fread);
TSAN_INTERCEPT(fwrite);
+ TSAN_INTERCEPT(fflush);
+ TSAN_INTERCEPT(abort);
TSAN_INTERCEPT(puts);
TSAN_INTERCEPT(rmdir);
TSAN_INTERCEPT(opendir);
TSAN_INTERCEPT(epoll_ctl);
TSAN_INTERCEPT(epoll_wait);
- TSAN_INTERCEPT(poll);
TSAN_INTERCEPT(sigaction);
TSAN_INTERCEPT(signal);
+ TSAN_INTERCEPT(sigsuspend);
TSAN_INTERCEPT(raise);
TSAN_INTERCEPT(kill);
TSAN_INTERCEPT(pthread_kill);
@@ -1979,6 +2164,7 @@ void InitializeInterceptors() {
TSAN_INTERCEPT(usleep);
TSAN_INTERCEPT(nanosleep);
TSAN_INTERCEPT(gettimeofday);
+ TSAN_INTERCEPT(getaddrinfo);
TSAN_INTERCEPT(mlock);
TSAN_INTERCEPT(munlock);
diff --git a/libsanitizer/tsan/tsan_interface.cc b/libsanitizer/tsan/tsan_interface.cc
index 992e3834aae..e056bd465bf 100644
--- a/libsanitizer/tsan/tsan_interface.cc
+++ b/libsanitizer/tsan/tsan_interface.cc
@@ -12,11 +12,16 @@
#include "tsan_interface.h"
#include "tsan_interface_ann.h"
#include "tsan_rtl.h"
+#include "sanitizer_common/sanitizer_internal_defs.h"
#define CALLERPC ((uptr)__builtin_return_address(0))
using namespace __tsan; // NOLINT
+typedef u16 uint16_t;
+typedef u32 uint32_t;
+typedef u64 uint64_t;
+
void __tsan_init() {
Initialize(cur_thread());
}
@@ -31,6 +36,57 @@ void __tsan_write16(void *addr) {
MemoryWrite(cur_thread(), CALLERPC, (uptr)addr + 8, kSizeLog8);
}
+u16 __tsan_unaligned_read2(const uu16 *addr) {
+ UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 2, false, false);
+ return *addr;
+}
+
+u32 __tsan_unaligned_read4(const uu32 *addr) {
+ UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 4, false, false);
+ return *addr;
+}
+
+u64 __tsan_unaligned_read8(const uu64 *addr) {
+ UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 8, false, false);
+ return *addr;
+}
+
+void __tsan_unaligned_write2(uu16 *addr, u16 v) {
+ UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 2, true, false);
+ *addr = v;
+}
+
+void __tsan_unaligned_write4(uu32 *addr, u32 v) {
+ UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 4, true, false);
+ *addr = v;
+}
+
+void __tsan_unaligned_write8(uu64 *addr, u64 v) {
+ UnalignedMemoryAccess(cur_thread(), CALLERPC, (uptr)addr, 8, true, false);
+ *addr = v;
+}
+
+extern "C" {
+SANITIZER_INTERFACE_ATTRIBUTE
+uint16_t __sanitizer_unaligned_load16(void *addr)
+ ALIAS("__tsan_unaligned_read2");
+SANITIZER_INTERFACE_ATTRIBUTE
+uint32_t __sanitizer_unaligned_load32(void *addr)
+ ALIAS("__tsan_unaligned_read4");
+SANITIZER_INTERFACE_ATTRIBUTE
+uint64_t __sanitizer_unaligned_load64(void *addr)
+ ALIAS("__tsan_unaligned_read8");
+SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_unaligned_store16(void *addr, uint16_t v)
+ ALIAS("__tsan_unaligned_write2");
+SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_unaligned_store32(void *addr, uint32_t v)
+ ALIAS("__tsan_unaligned_write4");
+SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_unaligned_store64(void *addr, uint64_t v)
+ ALIAS("__tsan_unaligned_write8");
+}
+
void __tsan_acquire(void *addr) {
Acquire(cur_thread(), CALLERPC, (uptr)addr);
}
diff --git a/libsanitizer/tsan/tsan_interface.h b/libsanitizer/tsan/tsan_interface.h
index 2cfd7684183..63de7b2ab5c 100644
--- a/libsanitizer/tsan/tsan_interface.h
+++ b/libsanitizer/tsan/tsan_interface.h
@@ -25,30 +25,38 @@ extern "C" {
// This function should be called at the very beginning of the process,
// before any instrumented code is executed and before any call to malloc.
-void __tsan_init() SANITIZER_INTERFACE_ATTRIBUTE;
-
-void __tsan_read1(void *addr) SANITIZER_INTERFACE_ATTRIBUTE;
-void __tsan_read2(void *addr) SANITIZER_INTERFACE_ATTRIBUTE;
-void __tsan_read4(void *addr) SANITIZER_INTERFACE_ATTRIBUTE;
-void __tsan_read8(void *addr) SANITIZER_INTERFACE_ATTRIBUTE;
-void __tsan_read16(void *addr) SANITIZER_INTERFACE_ATTRIBUTE;
-
-void __tsan_write1(void *addr) SANITIZER_INTERFACE_ATTRIBUTE;
-void __tsan_write2(void *addr) SANITIZER_INTERFACE_ATTRIBUTE;
-void __tsan_write4(void *addr) SANITIZER_INTERFACE_ATTRIBUTE;
-void __tsan_write8(void *addr) SANITIZER_INTERFACE_ATTRIBUTE;
-void __tsan_write16(void *addr) SANITIZER_INTERFACE_ATTRIBUTE;
-
-void __tsan_vptr_update(void **vptr_p, void *new_val)
- SANITIZER_INTERFACE_ATTRIBUTE;
-
-void __tsan_func_entry(void *call_pc) SANITIZER_INTERFACE_ATTRIBUTE;
-void __tsan_func_exit() SANITIZER_INTERFACE_ATTRIBUTE;
-
-void __tsan_read_range(void *addr, unsigned long size) // NOLINT
- SANITIZER_INTERFACE_ATTRIBUTE;
-void __tsan_write_range(void *addr, unsigned long size) // NOLINT
- SANITIZER_INTERFACE_ATTRIBUTE;
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_init();
+
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_read1(void *addr);
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_read2(void *addr);
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_read4(void *addr);
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_read8(void *addr);
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_read16(void *addr);
+
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_write1(void *addr);
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_write2(void *addr);
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_write4(void *addr);
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_write8(void *addr);
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_write16(void *addr);
+
+SANITIZER_INTERFACE_ATTRIBUTE u16 __tsan_unaligned_read2(const uu16 *addr);
+SANITIZER_INTERFACE_ATTRIBUTE u32 __tsan_unaligned_read4(const uu32 *addr);
+SANITIZER_INTERFACE_ATTRIBUTE u64 __tsan_unaligned_read8(const uu64 *addr);
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_unaligned_write2(uu16 *addr, u16 v);
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_unaligned_write4(uu32 *addr, u32 v);
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_unaligned_write8(uu64 *addr, u64 v);
+
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_vptr_read(void **vptr_p);
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_vptr_update(void **vptr_p, void *new_val);
+
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_func_entry(void *call_pc);
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_func_exit();
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_read_range(void *addr, unsigned long size); // NOLINT
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tsan_write_range(void *addr, unsigned long size); // NOLINT
#ifdef __cplusplus
} // extern "C"
diff --git a/libsanitizer/tsan/tsan_interface_ann.cc b/libsanitizer/tsan/tsan_interface_ann.cc
index 7e49fb8b059..46d9e3ec1af 100644
--- a/libsanitizer/tsan/tsan_interface_ann.cc
+++ b/libsanitizer/tsan/tsan_interface_ann.cc
@@ -11,6 +11,7 @@
#include "sanitizer_common/sanitizer_libc.h"
#include "sanitizer_common/sanitizer_internal_defs.h"
#include "sanitizer_common/sanitizer_placement_new.h"
+#include "sanitizer_common/sanitizer_stacktrace.h"
#include "tsan_interface_ann.h"
#include "tsan_mutex.h"
#include "tsan_report.h"
@@ -18,6 +19,7 @@
#include "tsan_mman.h"
#include "tsan_flags.h"
#include "tsan_platform.h"
+#include "tsan_vector.h"
#define CALLERPC ((uptr)__builtin_return_address(0))
@@ -65,6 +67,7 @@ struct ExpectRace {
ExpectRace *next;
ExpectRace *prev;
int hitcount;
+ int addcount;
uptr addr;
uptr size;
char *file;
@@ -89,16 +92,19 @@ static void AddExpectRace(ExpectRace *list,
char *f, int l, uptr addr, uptr size, char *desc) {
ExpectRace *race = list->next;
for (; race != list; race = race->next) {
- if (race->addr == addr && race->size == size)
+ if (race->addr == addr && race->size == size) {
+ race->addcount++;
return;
+ }
}
race = (ExpectRace*)internal_alloc(MBlockExpectRace, sizeof(ExpectRace));
- race->hitcount = 0;
race->addr = addr;
race->size = size;
race->file = f;
race->line = l;
race->desc[0] = 0;
+ race->hitcount = 0;
+ race->addcount = 1;
if (desc) {
int i = 0;
for (; i < kMaxDescLen - 1 && desc[i]; i++)
@@ -153,6 +159,68 @@ bool IsExpectedReport(uptr addr, uptr size) {
return false;
}
+static void CollectMatchedBenignRaces(Vector<ExpectRace> *matched,
+ int *unique_count, int *hit_count, int ExpectRace::*counter) {
+ ExpectRace *list = &dyn_ann_ctx->benign;
+ for (ExpectRace *race = list->next; race != list; race = race->next) {
+ (*unique_count)++;
+ if (race->*counter == 0)
+ continue;
+ (*hit_count) += race->*counter;
+ uptr i = 0;
+ for (; i < matched->Size(); i++) {
+ ExpectRace *race0 = &(*matched)[i];
+ if (race->line == race0->line
+ && internal_strcmp(race->file, race0->file) == 0
+ && internal_strcmp(race->desc, race0->desc) == 0) {
+ race0->*counter += race->*counter;
+ break;
+ }
+ }
+ if (i == matched->Size())
+ matched->PushBack(*race);
+ }
+}
+
+void PrintMatchedBenignRaces() {
+ Lock lock(&dyn_ann_ctx->mtx);
+ int unique_count = 0;
+ int hit_count = 0;
+ int add_count = 0;
+ Vector<ExpectRace> hit_matched(MBlockScopedBuf);
+ CollectMatchedBenignRaces(&hit_matched, &unique_count, &hit_count,
+ &ExpectRace::hitcount);
+ Vector<ExpectRace> add_matched(MBlockScopedBuf);
+ CollectMatchedBenignRaces(&add_matched, &unique_count, &add_count,
+ &ExpectRace::addcount);
+ if (hit_matched.Size()) {
+ Printf("ThreadSanitizer: Matched %d \"benign\" races (pid=%d):\n",
+ hit_count, (int)internal_getpid());
+ for (uptr i = 0; i < hit_matched.Size(); i++) {
+ Printf("%d %s:%d %s\n",
+ hit_matched[i].hitcount, hit_matched[i].file,
+ hit_matched[i].line, hit_matched[i].desc);
+ }
+ }
+ if (hit_matched.Size()) {
+ Printf("ThreadSanitizer: Annotated %d \"benign\" races, %d unique"
+ " (pid=%d):\n",
+ add_count, unique_count, (int)internal_getpid());
+ for (uptr i = 0; i < add_matched.Size(); i++) {
+ Printf("%d %s:%d %s\n",
+ add_matched[i].addcount, add_matched[i].file,
+ add_matched[i].line, add_matched[i].desc);
+ }
+ }
+}
+
+static void ReportMissedExpectedRace(ExpectRace *race) {
+ Printf("==================\n");
+ Printf("WARNING: ThreadSanitizer: missed expected data race\n");
+ Printf(" %s addr=%zx %s:%d\n",
+ race->desc, race->addr, race->file, race->line);
+ Printf("==================\n");
+}
} // namespace __tsan
using namespace __tsan; // NOLINT
@@ -160,12 +228,12 @@ using namespace __tsan; // NOLINT
extern "C" {
void INTERFACE_ATTRIBUTE AnnotateHappensBefore(char *f, int l, uptr addr) {
SCOPED_ANNOTATION(AnnotateHappensBefore);
- Release(cur_thread(), CALLERPC, addr);
+ Release(thr, pc, addr);
}
void INTERFACE_ATTRIBUTE AnnotateHappensAfter(char *f, int l, uptr addr) {
SCOPED_ANNOTATION(AnnotateHappensAfter);
- Acquire(cur_thread(), CALLERPC, addr);
+ Acquire(thr, pc, addr);
}
void INTERFACE_ATTRIBUTE AnnotateCondVarSignal(char *f, int l, uptr cv) {
@@ -235,14 +303,6 @@ void INTERFACE_ATTRIBUTE AnnotateNoOp(char *f, int l, uptr mem) {
SCOPED_ANNOTATION(AnnotateNoOp);
}
-static void ReportMissedExpectedRace(ExpectRace *race) {
- Printf("==================\n");
- Printf("WARNING: ThreadSanitizer: missed expected data race\n");
- Printf(" %s addr=%zx %s:%d\n",
- race->desc, race->addr, race->file, race->line);
- Printf("==================\n");
-}
-
void INTERFACE_ATTRIBUTE AnnotateFlushExpectedRaces(char *f, int l) {
SCOPED_ANNOTATION(AnnotateFlushExpectedRaces);
Lock lock(&dyn_ann_ctx->mtx);
@@ -321,22 +381,22 @@ void INTERFACE_ATTRIBUTE AnnotateBenignRace(
void INTERFACE_ATTRIBUTE AnnotateIgnoreReadsBegin(char *f, int l) {
SCOPED_ANNOTATION(AnnotateIgnoreReadsBegin);
- IgnoreCtl(cur_thread(), false, true);
+ ThreadIgnoreBegin(thr);
}
void INTERFACE_ATTRIBUTE AnnotateIgnoreReadsEnd(char *f, int l) {
SCOPED_ANNOTATION(AnnotateIgnoreReadsEnd);
- IgnoreCtl(cur_thread(), false, false);
+ ThreadIgnoreEnd(thr);
}
void INTERFACE_ATTRIBUTE AnnotateIgnoreWritesBegin(char *f, int l) {
SCOPED_ANNOTATION(AnnotateIgnoreWritesBegin);
- IgnoreCtl(cur_thread(), true, true);
+ ThreadIgnoreBegin(thr);
}
void INTERFACE_ATTRIBUTE AnnotateIgnoreWritesEnd(char *f, int l) {
SCOPED_ANNOTATION(AnnotateIgnoreWritesEnd);
- IgnoreCtl(thr, true, false);
+ ThreadIgnoreEnd(thr);
}
void INTERFACE_ATTRIBUTE AnnotatePublishMemoryRange(
@@ -355,6 +415,9 @@ void INTERFACE_ATTRIBUTE AnnotateThreadName(
ThreadSetName(thr, name);
}
+// We deliberately omit the implementation of WTFAnnotateHappensBefore() and
+// WTFAnnotateHappensAfter(). Those are being used by Webkit to annotate
+// atomic operations, which should be handled by ThreadSanitizer correctly.
void INTERFACE_ATTRIBUTE WTFAnnotateHappensBefore(char *f, int l, uptr addr) {
SCOPED_ANNOTATION(AnnotateHappensBefore);
}
@@ -366,6 +429,7 @@ void INTERFACE_ATTRIBUTE WTFAnnotateHappensAfter(char *f, int l, uptr addr) {
void INTERFACE_ATTRIBUTE WTFAnnotateBenignRaceSized(
char *f, int l, uptr mem, uptr sz, char *desc) {
SCOPED_ANNOTATION(AnnotateBenignRaceSized);
+ BenignRaceImpl(f, l, mem, 1, desc);
}
int INTERFACE_ATTRIBUTE RunningOnValgrind() {
@@ -382,4 +446,7 @@ const char INTERFACE_ATTRIBUTE* ThreadSanitizerQuery(const char *query) {
else
return "0";
}
+
+void INTERFACE_ATTRIBUTE
+AnnotateMemoryIsInitialized(char *f, int l, uptr mem, uptr sz) {}
} // extern "C"
diff --git a/libsanitizer/tsan/tsan_interface_ann.h b/libsanitizer/tsan/tsan_interface_ann.h
index b6500329428..45c18352e69 100644
--- a/libsanitizer/tsan/tsan_interface_ann.h
+++ b/libsanitizer/tsan/tsan_interface_ann.h
@@ -21,8 +21,8 @@
extern "C" {
#endif
-void __tsan_acquire(void *addr) SANITIZER_INTERFACE_ATTRIBUTE;
-void __tsan_release(void *addr) SANITIZER_INTERFACE_ATTRIBUTE;
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_acquire(void *addr);
+SANITIZER_INTERFACE_ATTRIBUTE void __tsan_release(void *addr);
#ifdef __cplusplus
} // extern "C"
diff --git a/libsanitizer/tsan/tsan_interface_atomic.cc b/libsanitizer/tsan/tsan_interface_atomic.cc
index 2c8b2ab049c..02ebb47e6af 100644
--- a/libsanitizer/tsan/tsan_interface_atomic.cc
+++ b/libsanitizer/tsan/tsan_interface_atomic.cc
@@ -28,23 +28,37 @@ using namespace __tsan; // NOLINT
#define SCOPED_ATOMIC(func, ...) \
const uptr callpc = (uptr)__builtin_return_address(0); \
uptr pc = __sanitizer::StackTrace::GetCurrentPc(); \
- pc = __sanitizer::StackTrace::GetPreviousInstructionPc(pc); \
mo = ConvertOrder(mo); \
mo = flags()->force_seq_cst_atomics ? (morder)mo_seq_cst : mo; \
ThreadState *const thr = cur_thread(); \
AtomicStatInc(thr, sizeof(*a), mo, StatAtomic##func); \
- ScopedAtomic sa(thr, callpc, __FUNCTION__); \
+ ScopedAtomic sa(thr, callpc, a, mo, __FUNCTION__); \
return Atomic##func(thr, pc, __VA_ARGS__); \
/**/
+// Some shortcuts.
+typedef __tsan_memory_order morder;
+typedef __tsan_atomic8 a8;
+typedef __tsan_atomic16 a16;
+typedef __tsan_atomic32 a32;
+typedef __tsan_atomic64 a64;
+typedef __tsan_atomic128 a128;
+const morder mo_relaxed = __tsan_memory_order_relaxed;
+const morder mo_consume = __tsan_memory_order_consume;
+const morder mo_acquire = __tsan_memory_order_acquire;
+const morder mo_release = __tsan_memory_order_release;
+const morder mo_acq_rel = __tsan_memory_order_acq_rel;
+const morder mo_seq_cst = __tsan_memory_order_seq_cst;
+
class ScopedAtomic {
public:
- ScopedAtomic(ThreadState *thr, uptr pc, const char *func)
+ ScopedAtomic(ThreadState *thr, uptr pc, const volatile void *a,
+ morder mo, const char *func)
: thr_(thr) {
CHECK_EQ(thr_->in_rtl, 0);
ProcessPendingSignals(thr);
FuncEntry(thr_, pc);
- DPrintf("#%d: %s\n", thr_->tid, func);
+ DPrintf("#%d: %s(%p, %d)\n", thr_->tid, func, a, mo);
thr_->in_rtl++;
}
~ScopedAtomic() {
@@ -56,20 +70,6 @@ class ScopedAtomic {
ThreadState *thr_;
};
-// Some shortcuts.
-typedef __tsan_memory_order morder;
-typedef __tsan_atomic8 a8;
-typedef __tsan_atomic16 a16;
-typedef __tsan_atomic32 a32;
-typedef __tsan_atomic64 a64;
-typedef __tsan_atomic128 a128;
-const morder mo_relaxed = __tsan_memory_order_relaxed;
-const morder mo_consume = __tsan_memory_order_consume;
-const morder mo_acquire = __tsan_memory_order_acquire;
-const morder mo_release = __tsan_memory_order_release;
-const morder mo_acq_rel = __tsan_memory_order_acq_rel;
-const morder mo_seq_cst = __tsan_memory_order_seq_cst;
-
static void AtomicStatInc(ThreadState *thr, uptr size, morder mo, StatType t) {
StatInc(thr, StatAtomic);
StatInc(thr, t);
@@ -288,16 +288,20 @@ static void AtomicStore(ThreadState *thr, uptr pc, volatile T *a, T v,
template<typename T, T (*F)(volatile T *v, T op)>
static T AtomicRMW(ThreadState *thr, uptr pc, volatile T *a, T v, morder mo) {
MemoryWriteAtomic(thr, pc, (uptr)a, SizeLog<T>());
- SyncVar *s = CTX()->synctab.GetOrCreateAndLock(thr, pc, (uptr)a, true);
- thr->clock.set(thr->tid, thr->fast_state.epoch());
- if (IsAcqRelOrder(mo))
- thr->clock.acq_rel(&s->clock);
- else if (IsReleaseOrder(mo))
- thr->clock.release(&s->clock);
- else if (IsAcquireOrder(mo))
- thr->clock.acquire(&s->clock);
+ SyncVar *s = 0;
+ if (mo != mo_relaxed) {
+ s = CTX()->synctab.GetOrCreateAndLock(thr, pc, (uptr)a, true);
+ thr->clock.set(thr->tid, thr->fast_state.epoch());
+ if (IsAcqRelOrder(mo))
+ thr->clock.acq_rel(&s->clock);
+ else if (IsReleaseOrder(mo))
+ thr->clock.release(&s->clock);
+ else if (IsAcquireOrder(mo))
+ thr->clock.acquire(&s->clock);
+ }
v = F(a, v);
- s->mtx.Unlock();
+ if (s)
+ s->mtx.Unlock();
return v;
}
@@ -348,17 +352,21 @@ static bool AtomicCAS(ThreadState *thr, uptr pc,
volatile T *a, T *c, T v, morder mo, morder fmo) {
(void)fmo; // Unused because llvm does not pass it yet.
MemoryWriteAtomic(thr, pc, (uptr)a, SizeLog<T>());
- SyncVar *s = CTX()->synctab.GetOrCreateAndLock(thr, pc, (uptr)a, true);
- thr->clock.set(thr->tid, thr->fast_state.epoch());
- if (IsAcqRelOrder(mo))
- thr->clock.acq_rel(&s->clock);
- else if (IsReleaseOrder(mo))
- thr->clock.release(&s->clock);
- else if (IsAcquireOrder(mo))
- thr->clock.acquire(&s->clock);
+ SyncVar *s = 0;
+ if (mo != mo_relaxed) {
+ s = CTX()->synctab.GetOrCreateAndLock(thr, pc, (uptr)a, true);
+ thr->clock.set(thr->tid, thr->fast_state.epoch());
+ if (IsAcqRelOrder(mo))
+ thr->clock.acq_rel(&s->clock);
+ else if (IsReleaseOrder(mo))
+ thr->clock.release(&s->clock);
+ else if (IsAcquireOrder(mo))
+ thr->clock.acquire(&s->clock);
+ }
T cc = *c;
T pr = func_cas(a, cc, v);
- s->mtx.Unlock();
+ if (s)
+ s->mtx.Unlock();
if (pr == cc)
return true;
*c = pr;
@@ -649,14 +657,14 @@ a64 __tsan_atomic64_compare_exchange_val(volatile a64 *a, a64 c, a64 v,
}
#if __TSAN_HAS_INT128
-a128 __tsan_atomic64_compare_exchange_val(volatile a128 *a, a128 c, a128 v,
+a128 __tsan_atomic128_compare_exchange_val(volatile a128 *a, a128 c, a128 v,
morder mo, morder fmo) {
SCOPED_ATOMIC(CAS, a, c, v, mo, fmo);
}
#endif
void __tsan_atomic_thread_fence(morder mo) {
- char* a;
+ char* a = 0;
SCOPED_ATOMIC(Fence, mo);
}
diff --git a/libsanitizer/tsan/tsan_interface_inl.h b/libsanitizer/tsan/tsan_interface_inl.h
index 92796d1178f..4d6e10bcf7b 100644
--- a/libsanitizer/tsan/tsan_interface_inl.h
+++ b/libsanitizer/tsan/tsan_interface_inl.h
@@ -50,8 +50,20 @@ void __tsan_write8(void *addr) {
void __tsan_vptr_update(void **vptr_p, void *new_val) {
CHECK_EQ(sizeof(vptr_p), 8);
- if (*vptr_p != new_val)
- MemoryWrite(cur_thread(), CALLERPC, (uptr)vptr_p, kSizeLog8);
+ if (*vptr_p != new_val) {
+ ThreadState *thr = cur_thread();
+ thr->is_vptr_access = true;
+ MemoryWrite(thr, CALLERPC, (uptr)vptr_p, kSizeLog8);
+ thr->is_vptr_access = false;
+ }
+}
+
+void __tsan_vptr_read(void **vptr_p) {
+ CHECK_EQ(sizeof(vptr_p), 8);
+ ThreadState *thr = cur_thread();
+ thr->is_vptr_access = true;
+ MemoryRead(thr, CALLERPC, (uptr)vptr_p, kSizeLog8);
+ thr->is_vptr_access = false;
}
void __tsan_func_entry(void *pc) {
diff --git a/libsanitizer/tsan/tsan_interface_java.cc b/libsanitizer/tsan/tsan_interface_java.cc
index f8c0b4eb635..7cc72577977 100644
--- a/libsanitizer/tsan/tsan_interface_java.cc
+++ b/libsanitizer/tsan/tsan_interface_java.cc
@@ -15,6 +15,8 @@
#include "sanitizer_common/sanitizer_internal_defs.h"
#include "sanitizer_common/sanitizer_common.h"
#include "sanitizer_common/sanitizer_placement_new.h"
+#include "sanitizer_common/sanitizer_stacktrace.h"
+#include "sanitizer_common/sanitizer_procmaps.h"
using namespace __tsan; // NOLINT
@@ -92,6 +94,8 @@ class ScopedJavaFunc {
static u64 jctx_buf[sizeof(JavaContext) / sizeof(u64) + 1];
static JavaContext *jctx;
+extern atomic_uintptr_t libjvm_begin;
+extern atomic_uintptr_t libjvm_end;
static BlockDesc *getblock(uptr addr) {
uptr i = (addr - jctx->heap_begin) / kHeapAlignment;
@@ -155,11 +159,22 @@ SyncVar* GetAndRemoveJavaSync(ThreadState *thr, uptr pc, uptr addr) {
#define SCOPED_JAVA_FUNC(func) \
ThreadState *thr = cur_thread(); \
const uptr caller_pc = GET_CALLER_PC(); \
- const uptr pc = (uptr)&func; \
+ const uptr pc = __sanitizer::StackTrace::GetCurrentPc(); \
(void)pc; \
ScopedJavaFunc scoped(thr, caller_pc); \
/**/
+void __tsan_java_preinit(const char *libjvm_path) {
+ SCOPED_JAVA_FUNC(__tsan_java_preinit);
+ if (libjvm_path) {
+ uptr begin, end;
+ if (GetCodeRangeForFile(libjvm_path, &begin, &end)) {
+ atomic_store(&libjvm_begin, begin, memory_order_relaxed);
+ atomic_store(&libjvm_end, end, memory_order_relaxed);
+ }
+ }
+}
+
void __tsan_java_init(jptr heap_begin, jptr heap_size) {
SCOPED_JAVA_FUNC(__tsan_java_init);
DPrintf("#%d: java_init(%p, %p)\n", thr->tid, heap_begin, heap_size);
@@ -269,6 +284,7 @@ void __tsan_java_mutex_lock(jptr addr) {
CHECK_GE(addr, jctx->heap_begin);
CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
+ MutexCreate(thr, pc, addr, true, true, true);
MutexLock(thr, pc, addr);
}
@@ -289,6 +305,7 @@ void __tsan_java_mutex_read_lock(jptr addr) {
CHECK_GE(addr, jctx->heap_begin);
CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
+ MutexCreate(thr, pc, addr, true, true, true);
MutexReadLock(thr, pc, addr);
}
@@ -301,3 +318,25 @@ void __tsan_java_mutex_read_unlock(jptr addr) {
MutexReadUnlock(thr, pc, addr);
}
+
+void __tsan_java_mutex_lock_rec(jptr addr, int rec) {
+ SCOPED_JAVA_FUNC(__tsan_java_mutex_lock_rec);
+ DPrintf("#%d: java_mutex_lock_rec(%p, %d)\n", thr->tid, addr, rec);
+ CHECK_NE(jctx, 0);
+ CHECK_GE(addr, jctx->heap_begin);
+ CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
+ CHECK_GT(rec, 0);
+
+ MutexCreate(thr, pc, addr, true, true, true);
+ MutexLock(thr, pc, addr, rec);
+}
+
+int __tsan_java_mutex_unlock_rec(jptr addr) {
+ SCOPED_JAVA_FUNC(__tsan_java_mutex_unlock_rec);
+ DPrintf("#%d: java_mutex_unlock_rec(%p)\n", thr->tid, addr);
+ CHECK_NE(jctx, 0);
+ CHECK_GE(addr, jctx->heap_begin);
+ CHECK_LT(addr, jctx->heap_begin + jctx->heap_size);
+
+ return MutexUnlock(thr, pc, addr, true);
+}
diff --git a/libsanitizer/tsan/tsan_interface_java.h b/libsanitizer/tsan/tsan_interface_java.h
index 01922bc9231..818c07b97d4 100644
--- a/libsanitizer/tsan/tsan_interface_java.h
+++ b/libsanitizer/tsan/tsan_interface_java.h
@@ -32,7 +32,11 @@ extern "C" {
typedef unsigned long jptr; // NOLINT
-// Must be called before any other callback from Java.
+// Must be called before any other callback from Java, right after dlopen
+// of JVM shared lib. If libjvm_path is specified, then all interceptors
+// coming directly from JVM will be ignored.
+void __tsan_java_preinit(const char *libjvm_path) INTERFACE_ATTRIBUTE;
+// Must be called after __tsan_java_preinit but before any other callback.
void __tsan_java_init(jptr heap_begin, jptr heap_size) INTERFACE_ATTRIBUTE;
// Must be called when the application exits.
// Not necessary the last callback (concurrently running threads are OK).
@@ -53,8 +57,7 @@ void __tsan_java_move(jptr src, jptr dst, jptr size) INTERFACE_ATTRIBUTE;
// Mutex lock.
// Addr is any unique address associated with the mutex.
-// Must not be called on recursive reentry.
-// Object.wait() is handled as a pair of unlock/lock.
+// Can be called on recursive reentry.
void __tsan_java_mutex_lock(jptr addr) INTERFACE_ATTRIBUTE;
// Mutex unlock.
void __tsan_java_mutex_unlock(jptr addr) INTERFACE_ATTRIBUTE;
@@ -62,6 +65,16 @@ void __tsan_java_mutex_unlock(jptr addr) INTERFACE_ATTRIBUTE;
void __tsan_java_mutex_read_lock(jptr addr) INTERFACE_ATTRIBUTE;
// Mutex read unlock.
void __tsan_java_mutex_read_unlock(jptr addr) INTERFACE_ATTRIBUTE;
+// Recursive mutex lock, intended for handling of Object.wait().
+// The 'rec' value must be obtained from the previous
+// __tsan_java_mutex_unlock_rec().
+void __tsan_java_mutex_lock_rec(jptr addr, int rec) INTERFACE_ATTRIBUTE;
+// Recursive mutex unlock, intended for handling of Object.wait().
+// The return value says how many times this thread called lock()
+// w/o a pairing unlock() (i.e. how many recursive levels it unlocked).
+// It must be passed back to __tsan_java_mutex_lock_rec() to restore
+// the same recursion level.
+int __tsan_java_mutex_unlock_rec(jptr addr) INTERFACE_ATTRIBUTE;
#ifdef __cplusplus
} // extern "C"
diff --git a/libsanitizer/tsan/tsan_mman.cc b/libsanitizer/tsan/tsan_mman.cc
index 23c73c50cc1..832374becf5 100644
--- a/libsanitizer/tsan/tsan_mman.cc
+++ b/libsanitizer/tsan/tsan_mman.cc
@@ -27,6 +27,41 @@ extern "C" void WEAK __tsan_free_hook(void *ptr) {
namespace __tsan {
+COMPILER_CHECK(sizeof(MBlock) == 16);
+
+void MBlock::Lock() {
+ atomic_uintptr_t *a = reinterpret_cast<atomic_uintptr_t*>(this);
+ uptr v = atomic_load(a, memory_order_relaxed);
+ for (int iter = 0;; iter++) {
+ if (v & 1) {
+ if (iter < 10)
+ proc_yield(20);
+ else
+ internal_sched_yield();
+ v = atomic_load(a, memory_order_relaxed);
+ continue;
+ }
+ if (atomic_compare_exchange_weak(a, &v, v | 1, memory_order_acquire))
+ break;
+ }
+}
+
+void MBlock::Unlock() {
+ atomic_uintptr_t *a = reinterpret_cast<atomic_uintptr_t*>(this);
+ uptr v = atomic_load(a, memory_order_relaxed);
+ DCHECK(v & 1);
+ atomic_store(a, v & ~1, memory_order_relaxed);
+}
+
+struct MapUnmapCallback {
+ void OnMap(uptr p, uptr size) const { }
+ void OnUnmap(uptr p, uptr size) const {
+ // We are about to unmap a chunk of user memory.
+ // Mark the corresponding shadow memory as not needed.
+ DontNeedShadowFor(p, size);
+ }
+};
+
static char allocator_placeholder[sizeof(Allocator)] ALIGNED(64);
Allocator *allocator() {
return reinterpret_cast<Allocator*>(&allocator_placeholder);
@@ -38,10 +73,12 @@ void InitializeAllocator() {
void AllocatorThreadStart(ThreadState *thr) {
allocator()->InitCache(&thr->alloc_cache);
+ internal_allocator()->InitCache(&thr->internal_alloc_cache);
}
void AllocatorThreadFinish(ThreadState *thr) {
allocator()->DestroyCache(&thr->alloc_cache);
+ internal_allocator()->DestroyCache(&thr->internal_alloc_cache);
}
void AllocatorPrintStats() {
@@ -54,7 +91,7 @@ static void SignalUnsafeCall(ThreadState *thr, uptr pc) {
Context *ctx = CTX();
StackTrace stack;
stack.ObtainCurrent(thr, pc);
- Lock l(&ctx->thread_mtx);
+ ThreadRegistryLock l(ctx->thread_registry);
ScopedReport rep(ReportTypeSignalUnsafe);
if (!IsFiredSuppression(ctx, rep, stack)) {
rep.AddStack(&stack);
@@ -64,16 +101,18 @@ static void SignalUnsafeCall(ThreadState *thr, uptr pc) {
void *user_alloc(ThreadState *thr, uptr pc, uptr sz, uptr align) {
CHECK_GT(thr->in_rtl, 0);
+ if ((sz >= (1ull << 40)) || (align >= (1ull << 40)))
+ return AllocatorReturnNull();
void *p = allocator()->Allocate(&thr->alloc_cache, sz, align);
if (p == 0)
return 0;
MBlock *b = new(allocator()->GetMetaData(p)) MBlock;
- b->size = sz;
- b->head = 0;
- b->alloc_tid = thr->unique_id;
- b->alloc_stack_id = CurrentStackId(thr, pc);
+ b->Init(sz, thr->tid, CurrentStackId(thr, pc));
if (CTX() && CTX()->initialized) {
- MemoryRangeImitateWrite(thr, pc, (uptr)p, sz);
+ if (thr->ignore_reads_and_writes == 0)
+ MemoryRangeImitateWrite(thr, pc, (uptr)p, sz);
+ else
+ MemoryResetRange(thr, pc, (uptr)p, sz);
}
DPrintf("#%d: alloc(%zu) = %p\n", thr->tid, sz, p);
SignalUnsafeCall(thr, pc);
@@ -85,9 +124,9 @@ void user_free(ThreadState *thr, uptr pc, void *p) {
CHECK_NE(p, (void*)0);
DPrintf("#%d: free(%p)\n", thr->tid, p);
MBlock *b = (MBlock*)allocator()->GetMetaData(p);
- if (b->head) {
- Lock l(&b->mtx);
- for (SyncVar *s = b->head; s;) {
+ if (b->ListHead()) {
+ MBlock::ScopedLock l(b);
+ for (SyncVar *s = b->ListHead(); s;) {
SyncVar *res = s;
s = s->next;
StatInc(thr, StatSyncDestroyed);
@@ -95,12 +134,12 @@ void user_free(ThreadState *thr, uptr pc, void *p) {
res->mtx.Unlock();
DestroyAndFree(res);
}
- b->head = 0;
+ b->ListReset();
}
if (CTX() && CTX()->initialized && thr->in_rtl == 1) {
- MemoryRangeFreed(thr, pc, (uptr)p, b->size);
+ if (thr->ignore_reads_and_writes == 0)
+ MemoryRangeFreed(thr, pc, (uptr)p, b->Size());
}
- b->~MBlock();
allocator()->Deallocate(&thr->alloc_cache, p);
SignalUnsafeCall(thr, pc);
}
@@ -116,20 +155,29 @@ void *user_realloc(ThreadState *thr, uptr pc, void *p, uptr sz) {
return 0;
if (p) {
MBlock *b = user_mblock(thr, p);
- internal_memcpy(p2, p, min(b->size, sz));
+ CHECK_NE(b, 0);
+ internal_memcpy(p2, p, min(b->Size(), sz));
}
}
- if (p) {
+ if (p)
user_free(thr, pc, p);
- }
return p2;
}
+uptr user_alloc_usable_size(ThreadState *thr, uptr pc, void *p) {
+ CHECK_GT(thr->in_rtl, 0);
+ if (p == 0)
+ return 0;
+ MBlock *b = (MBlock*)allocator()->GetMetaData(p);
+ return b ? b->Size() : 0;
+}
+
MBlock *user_mblock(ThreadState *thr, void *p) {
- CHECK_NE(p, (void*)0);
+ CHECK_NE(p, 0);
Allocator *a = allocator();
void *b = a->GetBlockBegin(p);
- CHECK_NE(b, 0);
+ if (b == 0)
+ return 0;
return (MBlock*)a->GetMetaData(b);
}
@@ -152,11 +200,12 @@ void invoke_free_hook(void *ptr) {
void *internal_alloc(MBlockType typ, uptr sz) {
ThreadState *thr = cur_thread();
CHECK_GT(thr->in_rtl, 0);
+ CHECK_LE(sz, InternalSizeClassMap::kMaxSize);
if (thr->nomalloc) {
thr->nomalloc = 0; // CHECK calls internal_malloc().
CHECK(0);
}
- return InternalAlloc(sz);
+ return InternalAlloc(sz, &thr->internal_alloc_cache);
}
void internal_free(void *p) {
@@ -166,7 +215,7 @@ void internal_free(void *p) {
thr->nomalloc = 0; // CHECK calls internal_malloc().
CHECK(0);
}
- InternalFree(p);
+ InternalFree(p, &thr->internal_alloc_cache);
}
} // namespace __tsan
@@ -213,6 +262,12 @@ uptr __tsan_get_allocated_size(void *p) {
if (p == 0)
return 0;
MBlock *b = (MBlock*)allocator()->GetMetaData(p);
- return b->size;
+ return b->Size();
+}
+
+void __tsan_on_thread_idle() {
+ ThreadState *thr = cur_thread();
+ allocator()->SwallowCache(&thr->alloc_cache);
+ internal_allocator()->SwallowCache(&thr->internal_alloc_cache);
}
} // extern "C"
diff --git a/libsanitizer/tsan/tsan_mman.h b/libsanitizer/tsan/tsan_mman.h
index 7a657e124bf..90faaffa1fc 100644
--- a/libsanitizer/tsan/tsan_mman.h
+++ b/libsanitizer/tsan/tsan_mman.h
@@ -29,6 +29,7 @@ void *user_alloc(ThreadState *thr, uptr pc, uptr sz,
void user_free(ThreadState *thr, uptr pc, void *p);
void *user_realloc(ThreadState *thr, uptr pc, void *p, uptr sz);
void *user_alloc_aligned(ThreadState *thr, uptr pc, uptr sz, uptr align);
+uptr user_alloc_usable_size(ThreadState *thr, uptr pc, void *p);
// Given the pointer p into a valid allocated block,
// returns the descriptor of the block.
MBlock *user_mblock(ThreadState *thr, void *p);
@@ -60,6 +61,7 @@ enum MBlockType {
MBlockExpectRace,
MBlockSignal,
MBlockFD,
+ MBlockJmpBuf,
// This must be the last.
MBlockTypeCount
diff --git a/libsanitizer/tsan/tsan_mutex.cc b/libsanitizer/tsan/tsan_mutex.cc
index 716722b0897..e7846c53e4a 100644
--- a/libsanitizer/tsan/tsan_mutex.cc
+++ b/libsanitizer/tsan/tsan_mutex.cc
@@ -29,8 +29,8 @@ static MutexType CanLockTab[MutexTypeCount][MutexTypeCount] = {
/*0 MutexTypeInvalid*/ {},
/*1 MutexTypeTrace*/ {MutexTypeLeaf},
/*2 MutexTypeThreads*/ {MutexTypeReport},
- /*3 MutexTypeReport*/ {MutexTypeSyncTab, MutexTypeMBlock,
- MutexTypeJavaMBlock},
+ /*3 MutexTypeReport*/ {MutexTypeSyncTab, MutexTypeSyncVar,
+ MutexTypeMBlock, MutexTypeJavaMBlock},
/*4 MutexTypeSyncVar*/ {},
/*5 MutexTypeSyncTab*/ {MutexTypeSyncVar},
/*6 MutexTypeSlab*/ {MutexTypeLeaf},
diff --git a/libsanitizer/tsan/tsan_mutexset.h b/libsanitizer/tsan/tsan_mutexset.h
index 6924eade4c6..ef60bd47db2 100644
--- a/libsanitizer/tsan/tsan_mutexset.h
+++ b/libsanitizer/tsan/tsan_mutexset.h
@@ -20,7 +20,7 @@ class MutexSet {
public:
// Holds limited number of mutexes.
// The oldest mutexes are discarded on overflow.
- static const uptr kMaxSize = 64;
+ static const uptr kMaxSize = 16;
struct Desc {
u64 id;
u64 epoch;
diff --git a/libsanitizer/tsan/tsan_platform.h b/libsanitizer/tsan/tsan_platform.h
index 78c1a7d8195..ac36c5ab67a 100644
--- a/libsanitizer/tsan/tsan_platform.h
+++ b/libsanitizer/tsan/tsan_platform.h
@@ -35,9 +35,9 @@ C++ COMPAT linux memory layout:
Go linux and darwin memory layout:
0000 0000 0000 - 0000 1000 0000: executable
0000 1000 0000 - 00f8 0000 0000: -
-00f8 0000 0000 - 0118 0000 0000: heap
-0118 0000 0000 - 1000 0000 0000: -
-1000 0000 0000 - 1460 0000 0000: shadow
+00c0 0000 0000 - 00e0 0000 0000: heap
+00e0 0000 0000 - 1000 0000 0000: -
+1000 0000 0000 - 1380 0000 0000: shadow
1460 0000 0000 - 6000 0000 0000: -
6000 0000 0000 - 6200 0000 0000: traces
6200 0000 0000 - 7fff ffff ffff: -
@@ -45,8 +45,8 @@ Go linux and darwin memory layout:
Go windows memory layout:
0000 0000 0000 - 0000 1000 0000: executable
0000 1000 0000 - 00f8 0000 0000: -
-00f8 0000 0000 - 0118 0000 0000: heap
-0118 0000 0000 - 0100 0000 0000: -
+00c0 0000 0000 - 00e0 0000 0000: heap
+00e0 0000 0000 - 0100 0000 0000: -
0100 0000 0000 - 0560 0000 0000: shadow
0560 0000 0000 - 0760 0000 0000: traces
0760 0000 0000 - 07ff ffff ffff: -
@@ -63,11 +63,11 @@ namespace __tsan {
#if defined(TSAN_GO)
static const uptr kLinuxAppMemBeg = 0x000000000000ULL;
-static const uptr kLinuxAppMemEnd = 0x00fcffffffffULL;
-# if defined(_WIN32)
+static const uptr kLinuxAppMemEnd = 0x04dfffffffffULL;
+# if SANITIZER_WINDOWS
static const uptr kLinuxShadowMsk = 0x010000000000ULL;
# else
-static const uptr kLinuxShadowMsk = 0x100000000000ULL;
+static const uptr kLinuxShadowMsk = 0x200000000000ULL;
# endif
// TSAN_COMPAT_SHADOW is intended for COMPAT virtual memory layout,
// when memory addresses are of the 0x2axxxxxxxxxx form.
@@ -82,7 +82,7 @@ static const uptr kLinuxAppMemEnd = 0x7fffffffffffULL;
static const uptr kLinuxAppMemMsk = 0x7c0000000000ULL;
-#if defined(_WIN32)
+#if SANITIZER_WINDOWS
const uptr kTraceMemBegin = 0x056000000000ULL;
#else
const uptr kTraceMemBegin = 0x600000000000ULL;
@@ -130,13 +130,19 @@ static inline uptr AlternativeAddress(uptr addr) {
#endif
}
-uptr GetShadowMemoryConsumption();
void FlushShadowMemory();
+void WriteMemoryProfile(char *buf, uptr buf_size);
const char *InitializePlatform();
void FinalizePlatform();
-uptr ALWAYS_INLINE INLINE GetThreadTrace(int tid) {
- uptr p = kTraceMemBegin + (uptr)tid * kTraceSize * sizeof(Event);
+uptr ALWAYS_INLINE GetThreadTrace(int tid) {
+ uptr p = kTraceMemBegin + (uptr)(tid * 2) * kTraceSize * sizeof(Event);
+ DCHECK_LT(p, kTraceMemBegin + kTraceMemSize);
+ return p;
+}
+
+uptr ALWAYS_INLINE GetThreadTraceHeader(int tid) {
+ uptr p = kTraceMemBegin + (uptr)(tid * 2 + 1) * kTraceSize * sizeof(Event);
DCHECK_LT(p, kTraceMemBegin + kTraceMemSize);
return p;
}
@@ -146,9 +152,6 @@ void internal_start_thread(void(*func)(void*), void *arg);
// Says whether the addr relates to a global var.
// Guesses with high probability, may yield both false positives and negatives.
bool IsGlobalVar(uptr addr);
-uptr GetTlsSize();
-void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
- uptr *tls_addr, uptr *tls_size);
int ExtractResolvFDs(void *state, int *fds, int nfd);
} // namespace __tsan
diff --git a/libsanitizer/tsan/tsan_platform_linux.cc b/libsanitizer/tsan/tsan_platform_linux.cc
index f7b05f2bf8f..f13e3c893b3 100644
--- a/libsanitizer/tsan/tsan_platform_linux.cc
+++ b/libsanitizer/tsan/tsan_platform_linux.cc
@@ -10,7 +10,9 @@
// Linux-specific code.
//===----------------------------------------------------------------------===//
-#ifdef __linux__
+
+#include "sanitizer_common/sanitizer_platform.h"
+#if SANITIZER_LINUX
#include "sanitizer_common/sanitizer_common.h"
#include "sanitizer_common/sanitizer_libc.h"
@@ -19,7 +21,6 @@
#include "tsan_rtl.h"
#include "tsan_flags.h"
-#include <asm/prctl.h>
#include <fcntl.h>
#include <pthread.h>
#include <signal.h>
@@ -40,11 +41,14 @@
#include <dlfcn.h>
#define __need_res_state
#include <resolv.h>
+#include <malloc.h>
-extern "C" int arch_prctl(int code, __sanitizer::uptr *addr);
+extern "C" struct mallinfo __libc_mallinfo();
namespace __tsan {
+const uptr kPageSize = 4096;
+
#ifndef TSAN_GO
ScopedInRtl::ScopedInRtl()
: thr_(cur_thread()) {
@@ -66,8 +70,38 @@ ScopedInRtl::~ScopedInRtl() {
}
#endif
-uptr GetShadowMemoryConsumption() {
- return 0;
+void FillProfileCallback(uptr start, uptr rss, bool file,
+ uptr *mem, uptr stats_size) {
+ CHECK_EQ(7, stats_size);
+ mem[6] += rss; // total
+ start >>= 40;
+ if (start < 0x10) // shadow
+ mem[0] += rss;
+ else if (start >= 0x20 && start < 0x30) // compat modules
+ mem[file ? 1 : 2] += rss;
+ else if (start >= 0x7e) // modules
+ mem[file ? 1 : 2] += rss;
+ else if (start >= 0x60 && start < 0x62) // traces
+ mem[3] += rss;
+ else if (start >= 0x7d && start < 0x7e) // heap
+ mem[4] += rss;
+ else // other
+ mem[5] += rss;
+}
+
+void WriteMemoryProfile(char *buf, uptr buf_size) {
+ uptr mem[7] = {};
+ __sanitizer::GetMemoryProfile(FillProfileCallback, mem, 7);
+ char *buf_pos = buf;
+ char *buf_end = buf + buf_size;
+ buf_pos += internal_snprintf(buf_pos, buf_end - buf_pos,
+ "RSS %zd MB: shadow:%zd file:%zd mmap:%zd trace:%zd heap:%zd other:%zd\n",
+ mem[6] >> 20, mem[0] >> 20, mem[1] >> 20, mem[2] >> 20,
+ mem[3] >> 20, mem[4] >> 20, mem[5] >> 20);
+ struct mallinfo mi = __libc_mallinfo();
+ buf_pos += internal_snprintf(buf_pos, buf_end - buf_pos,
+ "mallinfo: arena=%d mmap=%d fordblks=%d keepcost=%d\n",
+ mi.arena >> 20, mi.hblkhd >> 20, mi.fordblks >> 20, mi.keepcost >> 20);
}
void FlushShadowMemory() {
@@ -89,6 +123,63 @@ static void ProtectRange(uptr beg, uptr end) {
#endif
#ifndef TSAN_GO
+// Mark shadow for .rodata sections with the special kShadowRodata marker.
+// Accesses to .rodata can't race, so this saves time, memory and trace space.
+static void MapRodata() {
+ // First create temp file.
+ const char *tmpdir = GetEnv("TMPDIR");
+ if (tmpdir == 0)
+ tmpdir = GetEnv("TEST_TMPDIR");
+#ifdef P_tmpdir
+ if (tmpdir == 0)
+ tmpdir = P_tmpdir;
+#endif
+ if (tmpdir == 0)
+ return;
+ char filename[256];
+ internal_snprintf(filename, sizeof(filename), "%s/tsan.rodata.%d",
+ tmpdir, (int)internal_getpid());
+ uptr openrv = internal_open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
+ if (internal_iserror(openrv))
+ return;
+ fd_t fd = openrv;
+ // Fill the file with kShadowRodata.
+ const uptr kMarkerSize = 512 * 1024 / sizeof(u64);
+ InternalScopedBuffer<u64> marker(kMarkerSize);
+ for (u64 *p = marker.data(); p < marker.data() + kMarkerSize; p++)
+ *p = kShadowRodata;
+ internal_write(fd, marker.data(), marker.size());
+ // Map the file into memory.
+ uptr page = internal_mmap(0, kPageSize, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, fd, 0);
+ if (internal_iserror(page)) {
+ internal_close(fd);
+ internal_unlink(filename);
+ return;
+ }
+ // Map the file into shadow of .rodata sections.
+ MemoryMappingLayout proc_maps(/*cache_enabled*/true);
+ uptr start, end, offset, prot;
+ char name[128];
+ while (proc_maps.Next(&start, &end, &offset, name, ARRAY_SIZE(name), &prot)) {
+ if (name[0] != 0 && name[0] != '['
+ && (prot & MemoryMappingLayout::kProtectionRead)
+ && (prot & MemoryMappingLayout::kProtectionExecute)
+ && !(prot & MemoryMappingLayout::kProtectionWrite)
+ && IsAppMem(start)) {
+ // Assume it's .rodata
+ char *shadow_start = (char*)MemToShadow(start);
+ char *shadow_end = (char*)MemToShadow(end);
+ for (char *p = shadow_start; p < shadow_end; p += marker.size()) {
+ internal_mmap(p, Min<uptr>(marker.size(), shadow_end - p),
+ PROT_READ, MAP_PRIVATE | MAP_FIXED, fd, 0);
+ }
+ }
+ }
+ internal_close(fd);
+ internal_unlink(filename);
+}
+
void InitializeShadowMemory() {
uptr shadow = (uptr)MmapFixedNoReserve(kLinuxShadowBeg,
kLinuxShadowEnd - kLinuxShadowBeg);
@@ -115,6 +206,8 @@ void InitializeShadowMemory() {
kLinuxAppMemBeg, kLinuxAppMemEnd,
(kLinuxAppMemEnd - kLinuxAppMemBeg) >> 30);
DPrintf("stack %zx\n", (uptr)&shadow);
+
+ MapRodata();
}
#endif
@@ -124,10 +217,11 @@ static uptr g_data_end;
#ifndef TSAN_GO
static void CheckPIE() {
// Ensure that the binary is indeed compiled with -pie.
- MemoryMappingLayout proc_maps;
+ MemoryMappingLayout proc_maps(true);
uptr start, end;
if (proc_maps.Next(&start, &end,
- /*offset*/0, /*filename*/0, /*filename_size*/0)) {
+ /*offset*/0, /*filename*/0, /*filename_size*/0,
+ /*protection*/0)) {
if ((u64)start < kLinuxAppMemBeg) {
Printf("FATAL: ThreadSanitizer can not mmap the shadow memory ("
"something is mapped at 0x%zx < 0x%zx)\n",
@@ -140,11 +234,12 @@ static void CheckPIE() {
}
static void InitDataSeg() {
- MemoryMappingLayout proc_maps;
+ MemoryMappingLayout proc_maps(true);
uptr start, end, offset;
char name[128];
bool prev_is_data = false;
- while (proc_maps.Next(&start, &end, &offset, name, ARRAY_SIZE(name))) {
+ while (proc_maps.Next(&start, &end, &offset, name, ARRAY_SIZE(name),
+ /*protection*/ 0)) {
DPrintf("%p-%p %p %s\n", start, end, offset, name);
bool is_data = offset != 0 && name[0] != 0;
// BSS may get merged with [heap] in /proc/self/maps. This is not very
@@ -163,27 +258,6 @@ static void InitDataSeg() {
CHECK_LT((uptr)&g_data_start, g_data_end);
}
-static uptr g_tls_size;
-
-#ifdef __i386__
-# define INTERNAL_FUNCTION __attribute__((regparm(3), stdcall))
-#else
-# define INTERNAL_FUNCTION
-#endif
-
-static int InitTlsSize() {
- typedef void (*get_tls_func)(size_t*, size_t*) INTERNAL_FUNCTION;
- get_tls_func get_tls;
- void *get_tls_static_info_ptr = dlsym(RTLD_NEXT, "_dl_get_tls_static_info");
- CHECK_EQ(sizeof(get_tls), sizeof(get_tls_static_info_ptr));
- internal_memcpy(&get_tls, &get_tls_static_info_ptr,
- sizeof(get_tls_static_info_ptr));
- CHECK_NE(get_tls, 0);
- size_t tls_size = 0;
- size_t tls_align = 0;
- get_tls(&tls_size, &tls_align);
- return tls_size;
-}
#endif // #ifndef TSAN_GO
static rlim_t getlim(int res) {
@@ -238,53 +312,12 @@ const char *InitializePlatform() {
#ifndef TSAN_GO
CheckPIE();
- g_tls_size = (uptr)InitTlsSize();
+ InitTlsSize();
InitDataSeg();
#endif
return GetEnv(kTsanOptionsEnv);
}
-void FinalizePlatform() {
- fflush(0);
-}
-
-uptr GetTlsSize() {
-#ifndef TSAN_GO
- return g_tls_size;
-#else
- return 0;
-#endif
-}
-
-void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
- uptr *tls_addr, uptr *tls_size) {
-#ifndef TSAN_GO
- arch_prctl(ARCH_GET_FS, tls_addr);
- *tls_addr -= g_tls_size;
- *tls_size = g_tls_size;
-
- uptr stack_top, stack_bottom;
- GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom);
- *stk_addr = stack_bottom;
- *stk_size = stack_top - stack_bottom;
-
- if (!main) {
- // If stack and tls intersect, make them non-intersecting.
- if (*tls_addr > *stk_addr && *tls_addr < *stk_addr + *stk_size) {
- CHECK_GT(*tls_addr + *tls_size, *stk_addr);
- CHECK_LE(*tls_addr + *tls_size, *stk_addr + *stk_size);
- *stk_size -= *tls_size;
- *tls_addr = *stk_addr + *stk_size;
- }
- }
-#else
- *stk_addr = 0;
- *stk_size = 0;
- *tls_addr = 0;
- *tls_size = 0;
-#endif
-}
-
bool IsGlobalVar(uptr addr) {
return g_data_start && addr >= g_data_start && addr < g_data_end;
}
@@ -304,4 +337,4 @@ int ExtractResolvFDs(void *state, int *fds, int nfd) {
} // namespace __tsan
-#endif // #ifdef __linux__
+#endif // SANITIZER_LINUX
diff --git a/libsanitizer/tsan/tsan_platform_mac.cc b/libsanitizer/tsan/tsan_platform_mac.cc
index b247468c829..3dca611dc92 100644
--- a/libsanitizer/tsan/tsan_platform_mac.cc
+++ b/libsanitizer/tsan/tsan_platform_mac.cc
@@ -10,7 +10,8 @@
// Mac-specific code.
//===----------------------------------------------------------------------===//
-#ifdef __APPLE__
+#include "sanitizer_common/sanitizer_platform.h"
+#if SANITIZER_MAC
#include "sanitizer_common/sanitizer_common.h"
#include "sanitizer_common/sanitizer_libc.h"
@@ -87,18 +88,6 @@ void FinalizePlatform() {
fflush(0);
}
-uptr GetTlsSize() {
- return 0;
-}
-
-void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
- uptr *tls_addr, uptr *tls_size) {
- *stk_addr = 0;
- *stk_size = 0;
- *tls_addr = 0;
- *tls_size = 0;
-}
-
} // namespace __tsan
-#endif // #ifdef __APPLE__
+#endif // SANITIZER_MAC
diff --git a/libsanitizer/tsan/tsan_platform_windows.cc b/libsanitizer/tsan/tsan_platform_windows.cc
index 376dc08688b..6e49ef42f0c 100644
--- a/libsanitizer/tsan/tsan_platform_windows.cc
+++ b/libsanitizer/tsan/tsan_platform_windows.cc
@@ -10,7 +10,8 @@
// Windows-specific code.
//===----------------------------------------------------------------------===//
-#ifdef _WIN32
+#include "sanitizer_common/sanitizer_platform.h"
+#if SANITIZER_WINDOWS
#include "tsan_platform.h"
@@ -39,18 +40,6 @@ void FinalizePlatform() {
fflush(0);
}
-uptr GetTlsSize() {
- return 0;
-}
-
-void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
- uptr *tls_addr, uptr *tls_size) {
- *stk_addr = 0;
- *stk_size = 0;
- *tls_addr = 0;
- *tls_size = 0;
-}
-
} // namespace __tsan
-#endif // #ifdef _WIN32
+#endif // SANITIZER_WINDOWS
diff --git a/libsanitizer/tsan/tsan_report.cc b/libsanitizer/tsan/tsan_report.cc
index 098d8262ba1..15ab22b4ba7 100644
--- a/libsanitizer/tsan/tsan_report.cc
+++ b/libsanitizer/tsan/tsan_report.cc
@@ -11,16 +11,35 @@
#include "tsan_report.h"
#include "tsan_platform.h"
#include "tsan_rtl.h"
+#include "sanitizer_common/sanitizer_report_decorator.h"
namespace __tsan {
+class Decorator: private __sanitizer::AnsiColorDecorator {
+ public:
+ Decorator() : __sanitizer::AnsiColorDecorator(PrintsToTtyCached()) { }
+ const char *Warning() { return Red(); }
+ const char *EndWarning() { return Default(); }
+ const char *Access() { return Blue(); }
+ const char *EndAccess() { return Default(); }
+ const char *ThreadDescription() { return Cyan(); }
+ const char *EndThreadDescription() { return Default(); }
+ const char *Location() { return Green(); }
+ const char *EndLocation() { return Default(); }
+ const char *Sleep() { return Yellow(); }
+ const char *EndSleep() { return Default(); }
+ const char *Mutex() { return Magenta(); }
+ const char *EndMutex() { return Default(); }
+};
+
ReportDesc::ReportDesc()
: stacks(MBlockReportStack)
, mops(MBlockReportMop)
, locs(MBlockReportLoc)
, mutexes(MBlockReportMutex)
, threads(MBlockReportThread)
- , sleep() {
+ , sleep()
+ , count() {
}
ReportMop::ReportMop()
@@ -44,6 +63,8 @@ const char *thread_name(char *buf, int tid) {
static const char *ReportTypeString(ReportType typ) {
if (typ == ReportTypeRace)
return "data race";
+ if (typ == ReportTypeVptrRace)
+ return "data race on vptr (ctor/dtor vs virtual call)";
if (typ == ReportTypeUseAfterFree)
return "heap-use-after-free";
if (typ == ReportTypeThreadLeak)
@@ -92,18 +113,24 @@ static const char *MopDesc(bool first, bool write, bool atomic) {
}
static void PrintMop(const ReportMop *mop, bool first) {
+ Decorator d;
char thrbuf[kThreadBufSize];
+ Printf("%s", d.Access());
Printf(" %s of size %d at %p by %s",
MopDesc(first, mop->write, mop->atomic),
mop->size, (void*)mop->addr,
thread_name(thrbuf, mop->tid));
PrintMutexSet(mop->mset);
Printf(":\n");
+ Printf("%s", d.EndAccess());
PrintStack(mop->stack);
}
static void PrintLocation(const ReportLocation *loc) {
+ Decorator d;
char thrbuf[kThreadBufSize];
+ bool print_stack = false;
+ Printf("%s", d.Location());
if (loc->type == ReportLocationGlobal) {
Printf(" Location is global '%s' of size %zu at %zx (%s+%p)\n\n",
loc->name, loc->size, loc->addr, loc->module, loc->offset);
@@ -111,7 +138,7 @@ static void PrintLocation(const ReportLocation *loc) {
char thrbuf[kThreadBufSize];
Printf(" Location is heap block of size %zu at %p allocated by %s:\n",
loc->size, loc->addr, thread_name(thrbuf, loc->tid));
- PrintStack(loc->stack);
+ print_stack = true;
} else if (loc->type == ReportLocationStack) {
Printf(" Location is stack of %s.\n\n", thread_name(thrbuf, loc->tid));
} else if (loc->type == ReportLocationTLS) {
@@ -119,24 +146,34 @@ static void PrintLocation(const ReportLocation *loc) {
} else if (loc->type == ReportLocationFD) {
Printf(" Location is file descriptor %d created by %s at:\n",
loc->fd, thread_name(thrbuf, loc->tid));
- PrintStack(loc->stack);
+ print_stack = true;
}
+ Printf("%s", d.EndLocation());
+ if (print_stack)
+ PrintStack(loc->stack);
}
static void PrintMutex(const ReportMutex *rm) {
+ Decorator d;
if (rm->destroyed) {
+ Printf("%s", d.Mutex());
Printf(" Mutex M%llu is already destroyed.\n\n", rm->id);
+ Printf("%s", d.EndMutex());
} else {
+ Printf("%s", d.Mutex());
Printf(" Mutex M%llu created at:\n", rm->id);
+ Printf("%s", d.EndMutex());
PrintStack(rm->stack);
}
}
static void PrintThread(const ReportThread *rt) {
+ Decorator d;
if (rt->id == 0) // Little sense in describing the main thread.
return;
+ Printf("%s", d.ThreadDescription());
Printf(" Thread T%d", rt->id);
- if (rt->name)
+ if (rt->name && rt->name[0] != '\0')
Printf(" '%s'", rt->name);
char thrbuf[kThreadBufSize];
Printf(" (tid=%zu, %s) created by %s",
@@ -145,11 +182,15 @@ static void PrintThread(const ReportThread *rt) {
if (rt->stack)
Printf(" at:");
Printf("\n");
+ Printf("%s", d.EndThreadDescription());
PrintStack(rt->stack);
}
static void PrintSleep(const ReportStack *s) {
+ Decorator d;
+ Printf("%s", d.Sleep());
Printf(" As if synchronized via sleep:\n");
+ Printf("%s", d.EndSleep());
PrintStack(s);
}
@@ -172,9 +213,13 @@ ReportStack *SkipTsanInternalFrames(ReportStack *ent) {
}
void PrintReport(const ReportDesc *rep) {
+ Decorator d;
Printf("==================\n");
const char *rep_typ_str = ReportTypeString(rep->typ);
- Printf("WARNING: ThreadSanitizer: %s (pid=%d)\n", rep_typ_str, GetPid());
+ Printf("%s", d.Warning());
+ Printf("WARNING: ThreadSanitizer: %s (pid=%d)\n", rep_typ_str,
+ (int)internal_getpid());
+ Printf("%s", d.EndWarning());
for (uptr i = 0; i < rep->stacks.Size(); i++) {
if (i)
@@ -197,37 +242,46 @@ void PrintReport(const ReportDesc *rep) {
for (uptr i = 0; i < rep->threads.Size(); i++)
PrintThread(rep->threads[i]);
+ if (rep->typ == ReportTypeThreadLeak && rep->count > 1)
+ Printf(" And %d more similar thread leaks.\n\n", rep->count - 1);
+
if (ReportStack *ent = SkipTsanInternalFrames(ChooseSummaryStack(rep)))
ReportErrorSummary(rep_typ_str, ent->file, ent->line, ent->func);
Printf("==================\n");
}
-#else
+#else // #ifndef TSAN_GO
+
+const int kMainThreadId = 1;
void PrintStack(const ReportStack *ent) {
if (ent == 0) {
- Printf(" [failed to restore the stack]\n\n");
+ Printf(" [failed to restore the stack]\n");
return;
}
for (int i = 0; ent; ent = ent->next, i++) {
Printf(" %s()\n %s:%d +0x%zx\n",
ent->func, ent->file, ent->line, (void*)ent->offset);
}
- Printf("\n");
}
static void PrintMop(const ReportMop *mop, bool first) {
- Printf("%s by goroutine %d:\n",
+ Printf("\n");
+ Printf("%s by ",
(first ? (mop->write ? "Write" : "Read")
- : (mop->write ? "Previous write" : "Previous read")),
- mop->tid);
+ : (mop->write ? "Previous write" : "Previous read")));
+ if (mop->tid == kMainThreadId)
+ Printf("main goroutine:\n");
+ else
+ Printf("goroutine %d:\n", mop->tid);
PrintStack(mop->stack);
}
static void PrintThread(const ReportThread *rt) {
- if (rt->id == 0) // Little sense in describing the main thread.
+ if (rt->id == kMainThreadId)
return;
+ Printf("\n");
Printf("Goroutine %d (%s) created at:\n",
rt->id, rt->running ? "running" : "finished");
PrintStack(rt->stack);
@@ -235,7 +289,7 @@ static void PrintThread(const ReportThread *rt) {
void PrintReport(const ReportDesc *rep) {
Printf("==================\n");
- Printf("WARNING: DATA RACE\n");
+ Printf("WARNING: DATA RACE");
for (uptr i = 0; i < rep->mops.Size(); i++)
PrintMop(rep->mops[i], i == 0);
for (uptr i = 0; i < rep->threads.Size(); i++)
diff --git a/libsanitizer/tsan/tsan_report.h b/libsanitizer/tsan/tsan_report.h
index eae2b3c721f..c0eef9eb023 100644
--- a/libsanitizer/tsan/tsan_report.h
+++ b/libsanitizer/tsan/tsan_report.h
@@ -18,6 +18,7 @@ namespace __tsan {
enum ReportType {
ReportTypeRace,
+ ReportTypeVptrRace,
ReportTypeUseAfterFree,
ReportTypeThreadLeak,
ReportTypeMutexDestroyLocked,
@@ -99,6 +100,7 @@ class ReportDesc {
Vector<ReportMutex*> mutexes;
Vector<ReportThread*> threads;
ReportStack *sleep;
+ int count;
ReportDesc();
~ReportDesc();
diff --git a/libsanitizer/tsan/tsan_rtl.cc b/libsanitizer/tsan/tsan_rtl.cc
index 673a355f1dc..7f18064e957 100644
--- a/libsanitizer/tsan/tsan_rtl.cc
+++ b/libsanitizer/tsan/tsan_rtl.cc
@@ -21,6 +21,7 @@
#include "tsan_rtl.h"
#include "tsan_mman.h"
#include "tsan_suppressions.h"
+#include "tsan_symbolize.h"
volatile int __tsan_resumed = 0;
@@ -45,15 +46,33 @@ Context *CTX() {
return ctx;
}
+static char thread_registry_placeholder[sizeof(ThreadRegistry)];
+
+static ThreadContextBase *CreateThreadContext(u32 tid) {
+ // Map thread trace when context is created.
+ MapThreadTrace(GetThreadTrace(tid), TraceSize() * sizeof(Event));
+ MapThreadTrace(GetThreadTraceHeader(tid), sizeof(Trace));
+ new(ThreadTrace(tid)) Trace();
+ void *mem = internal_alloc(MBlockThreadContex, sizeof(ThreadContext));
+ return new(mem) ThreadContext(tid);
+}
+
+#ifndef TSAN_GO
+static const u32 kThreadQuarantineSize = 16;
+#else
+static const u32 kThreadQuarantineSize = 64;
+#endif
+
Context::Context()
: initialized()
, report_mtx(MutexTypeReport, StatMtxReport)
, nreported()
, nmissed_expected()
- , thread_mtx(MutexTypeThreads, StatMtxThreads)
+ , thread_registry(new(thread_registry_placeholder) ThreadRegistry(
+ CreateThreadContext, kMaxTid, kThreadQuarantineSize))
, racy_stacks(MBlockRacyStacks)
, racy_addresses(MBlockRacyAddresses)
- , fired_suppressions(MBlockRacyAddresses) {
+ , fired_suppressions(8) {
}
// The objects are allocated in TLS, so one may rely on zero-initialization.
@@ -63,10 +82,12 @@ ThreadState::ThreadState(Context *ctx, int tid, int unique_id, u64 epoch,
: fast_state(tid, epoch)
// Do not touch these, rely on zero initialization,
// they may be accessed before the ctor.
- // , fast_ignore_reads()
- // , fast_ignore_writes()
+ // , ignore_reads_and_writes()
// , in_rtl()
, shadow_stack_pos(&shadow_stack[0])
+#ifndef TSAN_GO
+ , jmp_bufs(MBlockJmpBuf)
+#endif
, tid(tid)
, unique_id(unique_id)
, stk_addr(stk_addr)
@@ -75,94 +96,74 @@ ThreadState::ThreadState(Context *ctx, int tid, int unique_id, u64 epoch,
, tls_size(tls_size) {
}
-ThreadContext::ThreadContext(int tid)
- : tid(tid)
- , unique_id()
- , os_id()
- , user_id()
- , thr()
- , status(ThreadStatusInvalid)
- , detached()
- , reuse_count()
- , epoch0()
- , epoch1()
- , dead_info()
- , dead_next()
- , name() {
-}
-
-static void WriteMemoryProfile(char *buf, uptr buf_size, int num) {
- uptr shadow = GetShadowMemoryConsumption();
-
- int nthread = 0;
- int nlivethread = 0;
- uptr threadmem = 0;
- {
- Lock l(&ctx->thread_mtx);
- for (unsigned i = 0; i < kMaxTid; i++) {
- ThreadContext *tctx = ctx->threads[i];
- if (tctx == 0)
- continue;
- nthread += 1;
- threadmem += sizeof(ThreadContext);
- if (tctx->status != ThreadStatusRunning)
- continue;
- nlivethread += 1;
- threadmem += sizeof(ThreadState);
- }
- }
-
- uptr nsync = 0;
- uptr syncmem = CTX()->synctab.GetMemoryConsumption(&nsync);
-
- internal_snprintf(buf, buf_size, "%d: shadow=%zuMB"
- " thread=%zuMB(total=%d/live=%d)"
- " sync=%zuMB(cnt=%zu)\n",
- num,
- shadow >> 20,
- threadmem >> 20, nthread, nlivethread,
- syncmem >> 20, nsync);
+static void MemoryProfiler(Context *ctx, fd_t fd, int i) {
+ uptr n_threads;
+ uptr n_running_threads;
+ ctx->thread_registry->GetNumberOfThreads(&n_threads, &n_running_threads);
+ InternalScopedBuffer<char> buf(4096);
+ internal_snprintf(buf.data(), buf.size(), "%d: nthr=%d nlive=%d\n",
+ i, n_threads, n_running_threads);
+ internal_write(fd, buf.data(), internal_strlen(buf.data()));
+ WriteMemoryProfile(buf.data(), buf.size());
+ internal_write(fd, buf.data(), internal_strlen(buf.data()));
}
-static void MemoryProfileThread(void *arg) {
+static void BackgroundThread(void *arg) {
ScopedInRtl in_rtl;
- fd_t fd = (fd_t)(uptr)arg;
+ Context *ctx = CTX();
+ const u64 kMs2Ns = 1000 * 1000;
+
+ fd_t mprof_fd = kInvalidFd;
+ if (flags()->profile_memory && flags()->profile_memory[0]) {
+ InternalScopedBuffer<char> filename(4096);
+ internal_snprintf(filename.data(), filename.size(), "%s.%d",
+ flags()->profile_memory, (int)internal_getpid());
+ uptr openrv = OpenFile(filename.data(), true);
+ if (internal_iserror(openrv)) {
+ Printf("ThreadSanitizer: failed to open memory profile file '%s'\n",
+ &filename[0]);
+ } else {
+ mprof_fd = openrv;
+ }
+ }
+
+ u64 last_flush = NanoTime();
for (int i = 0; ; i++) {
- InternalScopedBuffer<char> buf(4096);
- WriteMemoryProfile(buf.data(), buf.size(), i);
- internal_write(fd, buf.data(), internal_strlen(buf.data()));
SleepForSeconds(1);
- }
-}
+ u64 now = NanoTime();
+
+ // Flush memory if requested.
+ if (flags()->flush_memory_ms) {
+ if (last_flush + flags()->flush_memory_ms * kMs2Ns < now) {
+ FlushShadowMemory();
+ last_flush = NanoTime();
+ }
+ }
-static void InitializeMemoryProfile() {
- if (flags()->profile_memory == 0 || flags()->profile_memory[0] == 0)
- return;
- InternalScopedBuffer<char> filename(4096);
- internal_snprintf(filename.data(), filename.size(), "%s.%d",
- flags()->profile_memory, GetPid());
- fd_t fd = OpenFile(filename.data(), true);
- if (fd == kInvalidFd) {
- Printf("Failed to open memory profile file '%s'\n", &filename[0]);
- Die();
- }
- internal_start_thread(&MemoryProfileThread, (void*)(uptr)fd);
-}
+ // Write memory profile if requested.
+ if (mprof_fd != kInvalidFd)
+ MemoryProfiler(ctx, mprof_fd, i);
-static void MemoryFlushThread(void *arg) {
- ScopedInRtl in_rtl;
- for (int i = 0; ; i++) {
- SleepForMillis(flags()->flush_memory_ms);
- FlushShadowMemory();
+#ifndef TSAN_GO
+ // Flush symbolizer cache if requested.
+ if (flags()->flush_symbolizer_ms > 0) {
+ u64 last = atomic_load(&ctx->last_symbolize_time_ns,
+ memory_order_relaxed);
+ if (last != 0 && last + flags()->flush_symbolizer_ms * kMs2Ns < now) {
+ Lock l(&ctx->report_mtx);
+ SpinMutexLock l2(&CommonSanitizerReportMutex);
+ SymbolizeFlush();
+ atomic_store(&ctx->last_symbolize_time_ns, 0, memory_order_relaxed);
+ }
+ }
+#endif
}
}
-static void InitializeMemoryFlush() {
- if (flags()->flush_memory_ms == 0)
- return;
- if (flags()->flush_memory_ms < 100)
- flags()->flush_memory_ms = 100;
- internal_start_thread(&MemoryFlushThread, 0);
+void DontNeedShadowFor(uptr addr, uptr size) {
+ uptr shadow_beg = MemToShadow(addr);
+ uptr shadow_end = MemToShadow(addr + size);
+ FlushUnneededShadowMemory(shadow_beg, shadow_end - shadow_beg);
}
void MapShadow(uptr addr, uptr size) {
@@ -201,9 +202,6 @@ void Initialize(ThreadState *thr) {
#ifndef TSAN_GO
InitializeShadowMemory();
#endif
- ctx->dead_list_size = 0;
- ctx->dead_list_head = 0;
- ctx->dead_list_tail = 0;
InitializeFlags(&ctx->flags, env);
// Setup correct file descriptor for error reports.
if (internal_strcmp(flags()->log_path, "stdout") == 0)
@@ -217,32 +215,30 @@ void Initialize(ThreadState *thr) {
// Initialize external symbolizer before internal threads are started.
const char *external_symbolizer = flags()->external_symbolizer_path;
if (external_symbolizer != 0 && external_symbolizer[0] != '\0') {
- if (!InitializeExternalSymbolizer(external_symbolizer)) {
+ if (!getSymbolizer()->InitializeExternal(external_symbolizer)) {
Printf("Failed to start external symbolizer: '%s'\n",
external_symbolizer);
Die();
}
}
#endif
- InitializeMemoryProfile();
- InitializeMemoryFlush();
+ internal_start_thread(&BackgroundThread, 0);
if (ctx->flags.verbosity)
Printf("***** Running under ThreadSanitizer v2 (pid %d) *****\n",
- GetPid());
+ (int)internal_getpid());
// Initialize thread 0.
- ctx->thread_seq = 0;
int tid = ThreadCreate(thr, 0, 0, true);
CHECK_EQ(tid, 0);
- ThreadStart(thr, tid, GetPid());
+ ThreadStart(thr, tid, internal_getpid());
CHECK_EQ(thr->in_rtl, 1);
ctx->initialized = true;
if (flags()->stop_on_start) {
Printf("ThreadSanitizer is suspended at startup (pid %d)."
" Call __tsan_resume().\n",
- GetPid());
+ (int)internal_getpid());
while (__tsan_resumed == 0) {}
}
}
@@ -257,6 +253,8 @@ int Finalize(ThreadState *thr) {
// Wait for pending reports.
ctx->report_mtx.Lock();
+ CommonSanitizerReportMutex.Lock();
+ CommonSanitizerReportMutex.Unlock();
ctx->report_mtx.Unlock();
#ifndef TSAN_GO
@@ -281,6 +279,13 @@ int Finalize(ThreadState *thr) {
ctx->nmissed_expected);
}
+ if (flags()->print_suppressions)
+ PrintMatchedSuppressions();
+#ifndef TSAN_GO
+ if (flags()->print_benign)
+ PrintMatchedBenignRaces();
+#endif
+
failed = OnFinalize(failed);
StatAggregate(ctx->stat, thr->stat);
@@ -307,15 +312,20 @@ u32 CurrentStackId(ThreadState *thr, uptr pc) {
void TraceSwitch(ThreadState *thr) {
thr->nomalloc++;
ScopedInRtl in_rtl;
- Lock l(&thr->trace.mtx);
+ Trace *thr_trace = ThreadTrace(thr->tid);
+ Lock l(&thr_trace->mtx);
unsigned trace = (thr->fast_state.epoch() / kTracePartSize) % TraceParts();
- TraceHeader *hdr = &thr->trace.headers[trace];
+ TraceHeader *hdr = &thr_trace->headers[trace];
hdr->epoch0 = thr->fast_state.epoch();
hdr->stack0.ObtainCurrent(thr, 0);
hdr->mset0 = thr->mset;
thr->nomalloc--;
}
+Trace *ThreadTrace(int tid) {
+ return (Trace*)GetThreadTraceHeader(tid);
+}
+
uptr TraceTopPC(ThreadState *thr) {
Event *events = (Event*)GetThreadTrace(thr->tid);
uptr pc = events[thr->fast_state.GetTracePos()];
@@ -341,18 +351,18 @@ extern "C" void __tsan_report_race() {
#endif
ALWAYS_INLINE
-static Shadow LoadShadow(u64 *p) {
+Shadow LoadShadow(u64 *p) {
u64 raw = atomic_load((atomic_uint64_t*)p, memory_order_relaxed);
return Shadow(raw);
}
ALWAYS_INLINE
-static void StoreShadow(u64 *sp, u64 s) {
+void StoreShadow(u64 *sp, u64 s) {
atomic_store((atomic_uint64_t*)sp, s, memory_order_relaxed);
}
ALWAYS_INLINE
-static void StoreIfNotYetStored(u64 *sp, u64 *s) {
+void StoreIfNotYetStored(u64 *sp, u64 *s) {
StoreShadow(sp, *s);
*s = 0;
}
@@ -377,7 +387,7 @@ static inline bool HappensBefore(Shadow old, ThreadState *thr) {
return thr->clock.get(old.TidWithIgnore()) >= old.epoch();
}
-ALWAYS_INLINE
+ALWAYS_INLINE USED
void MemoryAccessImpl(ThreadState *thr, uptr addr,
int kAccessSizeLog, bool kAccessIsWrite, bool kIsAtomic,
u64 *shadow_mem, Shadow cur) {
@@ -451,7 +461,28 @@ void MemoryAccessImpl(ThreadState *thr, uptr addr,
return;
}
-ALWAYS_INLINE
+void UnalignedMemoryAccess(ThreadState *thr, uptr pc, uptr addr,
+ int size, bool kAccessIsWrite, bool kIsAtomic) {
+ while (size) {
+ int size1 = 1;
+ int kAccessSizeLog = kSizeLog1;
+ if (size >= 8 && (addr & ~7) == ((addr + 8) & ~7)) {
+ size1 = 8;
+ kAccessSizeLog = kSizeLog8;
+ } else if (size >= 4 && (addr & ~7) == ((addr + 4) & ~7)) {
+ size1 = 4;
+ kAccessSizeLog = kSizeLog4;
+ } else if (size >= 2 && (addr & ~7) == ((addr + 2) & ~7)) {
+ size1 = 2;
+ kAccessSizeLog = kSizeLog2;
+ }
+ MemoryAccess(thr, pc, addr, kAccessSizeLog, kAccessIsWrite, kIsAtomic);
+ addr += size1;
+ size -= size1;
+ }
+}
+
+ALWAYS_INLINE USED
void MemoryAccess(ThreadState *thr, uptr pc, uptr addr,
int kAccessSizeLog, bool kAccessIsWrite, bool kIsAtomic) {
u64 *shadow_mem = (u64*)MemToShadow(addr);
@@ -472,6 +503,16 @@ void MemoryAccess(ThreadState *thr, uptr pc, uptr addr,
}
#endif
+ if (*shadow_mem == kShadowRodata) {
+ // Access to .rodata section, no races here.
+ // Measurements show that it can be 10-20% of all memory accesses.
+ StatInc(thr, StatMop);
+ StatInc(thr, kAccessIsWrite ? StatMopWrite : StatMopRead);
+ StatInc(thr, (StatType)(StatMop1 + kAccessSizeLog));
+ StatInc(thr, StatMopRodata);
+ return;
+ }
+
FastState fast_state = thr->fast_state;
if (fast_state.GetIgnoreBit())
return;
@@ -492,6 +533,8 @@ void MemoryAccess(ThreadState *thr, uptr pc, uptr addr,
static void MemoryRangeSet(ThreadState *thr, uptr pc, uptr addr, uptr size,
u64 val) {
+ (void)thr;
+ (void)pc;
if (size == 0)
return;
// FIXME: fix me.
@@ -508,23 +551,44 @@ static void MemoryRangeSet(ThreadState *thr, uptr pc, uptr addr, uptr size,
// let it just crash as usual.
if (!IsAppMem(addr) || !IsAppMem(addr + size - 1))
return;
- (void)thr;
- (void)pc;
- // Some programs mmap like hundreds of GBs but actually used a small part.
- // So, it's better to report a false positive on the memory
- // then to hang here senselessly.
- const uptr kMaxResetSize = 4ull*1024*1024*1024;
- if (size > kMaxResetSize)
- size = kMaxResetSize;
+ // Don't want to touch lots of shadow memory.
+ // If a program maps 10MB stack, there is no need reset the whole range.
size = (size + (kShadowCell - 1)) & ~(kShadowCell - 1);
- u64 *p = (u64*)MemToShadow(addr);
- CHECK(IsShadowMem((uptr)p));
- CHECK(IsShadowMem((uptr)(p + size * kShadowCnt / kShadowCell - 1)));
- // FIXME: may overwrite a part outside the region
- for (uptr i = 0; i < size * kShadowCnt / kShadowCell;) {
- p[i++] = val;
- for (uptr j = 1; j < kShadowCnt; j++)
- p[i++] = 0;
+ // UnmapOrDie/MmapFixedNoReserve does not work on Windows,
+ // so we do it only for C/C++.
+ if (kGoMode || size < 64*1024) {
+ u64 *p = (u64*)MemToShadow(addr);
+ CHECK(IsShadowMem((uptr)p));
+ CHECK(IsShadowMem((uptr)(p + size * kShadowCnt / kShadowCell - 1)));
+ // FIXME: may overwrite a part outside the region
+ for (uptr i = 0; i < size / kShadowCell * kShadowCnt;) {
+ p[i++] = val;
+ for (uptr j = 1; j < kShadowCnt; j++)
+ p[i++] = 0;
+ }
+ } else {
+ // The region is big, reset only beginning and end.
+ const uptr kPageSize = 4096;
+ u64 *begin = (u64*)MemToShadow(addr);
+ u64 *end = begin + size / kShadowCell * kShadowCnt;
+ u64 *p = begin;
+ // Set at least first kPageSize/2 to page boundary.
+ while ((p < begin + kPageSize / kShadowSize / 2) || ((uptr)p % kPageSize)) {
+ *p++ = val;
+ for (uptr j = 1; j < kShadowCnt; j++)
+ *p++ = 0;
+ }
+ // Reset middle part.
+ u64 *p1 = p;
+ p = RoundDown(end, kPageSize);
+ UnmapOrDie((void*)p1, (uptr)p - (uptr)p1);
+ MmapFixedNoReserve((uptr)p1, (uptr)p - (uptr)p1);
+ // Set the ending.
+ while (p < end) {
+ *p++ = val;
+ for (uptr j = 1; j < kShadowCnt; j++)
+ *p++ = 0;
+ }
}
}
@@ -533,10 +597,17 @@ void MemoryResetRange(ThreadState *thr, uptr pc, uptr addr, uptr size) {
}
void MemoryRangeFreed(ThreadState *thr, uptr pc, uptr addr, uptr size) {
+ // Processing more than 1k (4k of shadow) is expensive,
+ // can cause excessive memory consumption (user does not necessary touch
+ // the whole range) and most likely unnecessary.
+ if (size > 1024)
+ size = 1024;
CHECK_EQ(thr->is_freeing, false);
thr->is_freeing = true;
MemoryAccessRange(thr, pc, addr, size, true);
thr->is_freeing = false;
+ thr->fast_state.IncrementEpoch();
+ TraceAddEvent(thr, thr->fast_state, EventTypeMop, pc);
Shadow s(thr->fast_state);
s.ClearIgnoreBit();
s.MarkAsFreed();
@@ -546,6 +617,8 @@ void MemoryRangeFreed(ThreadState *thr, uptr pc, uptr addr, uptr size) {
}
void MemoryRangeImitateWrite(ThreadState *thr, uptr pc, uptr addr, uptr size) {
+ thr->fast_state.IncrementEpoch();
+ TraceAddEvent(thr, thr->fast_state, EventTypeMop, pc);
Shadow s(thr->fast_state);
s.ClearIgnoreBit();
s.SetWrite(true);
@@ -553,7 +626,7 @@ void MemoryRangeImitateWrite(ThreadState *thr, uptr pc, uptr addr, uptr size) {
MemoryRangeSet(thr, pc, addr, size, s.raw());
}
-ALWAYS_INLINE
+ALWAYS_INLINE USED
void FuncEntry(ThreadState *thr, uptr pc) {
DCHECK_EQ(thr->in_rtl, 0);
StatInc(thr, StatFuncEnter);
@@ -583,7 +656,7 @@ void FuncEntry(ThreadState *thr, uptr pc) {
thr->shadow_stack_pos++;
}
-ALWAYS_INLINE
+ALWAYS_INLINE USED
void FuncExit(ThreadState *thr) {
DCHECK_EQ(thr->in_rtl, 0);
StatInc(thr, StatFuncExit);
@@ -598,13 +671,18 @@ void FuncExit(ThreadState *thr) {
thr->shadow_stack_pos--;
}
-void IgnoreCtl(ThreadState *thr, bool write, bool begin) {
- DPrintf("#%d: IgnoreCtl(%d, %d)\n", thr->tid, write, begin);
- thr->ignore_reads_and_writes += begin ? 1 : -1;
+void ThreadIgnoreBegin(ThreadState *thr) {
+ DPrintf("#%d: ThreadIgnoreBegin\n", thr->tid);
+ thr->ignore_reads_and_writes++;
CHECK_GE(thr->ignore_reads_and_writes, 0);
- if (thr->ignore_reads_and_writes)
- thr->fast_state.SetIgnoreBit();
- else
+ thr->fast_state.SetIgnoreBit();
+}
+
+void ThreadIgnoreEnd(ThreadState *thr) {
+ DPrintf("#%d: ThreadIgnoreEnd\n", thr->tid);
+ thr->ignore_reads_and_writes--;
+ CHECK_GE(thr->ignore_reads_and_writes, 0);
+ if (thr->ignore_reads_and_writes == 0)
thr->fast_state.ClearIgnoreBit();
}
diff --git a/libsanitizer/tsan/tsan_rtl.h b/libsanitizer/tsan/tsan_rtl.h
index e939921049a..2548f67b25c 100644
--- a/libsanitizer/tsan/tsan_rtl.h
+++ b/libsanitizer/tsan/tsan_rtl.h
@@ -24,8 +24,11 @@
#ifndef TSAN_RTL_H
#define TSAN_RTL_H
-#include "sanitizer_common/sanitizer_common.h"
#include "sanitizer_common/sanitizer_allocator.h"
+#include "sanitizer_common/sanitizer_allocator_internal.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_suppressions.h"
+#include "sanitizer_common/sanitizer_thread_registry.h"
#include "tsan_clock.h"
#include "tsan_defs.h"
#include "tsan_flags.h"
@@ -44,15 +47,73 @@ namespace __tsan {
// Descriptor of user's memory block.
struct MBlock {
- Mutex mtx;
- uptr size;
- u32 alloc_tid;
- u32 alloc_stack_id;
- SyncVar *head;
+ /*
+ u64 mtx : 1; // must be first
+ u64 lst : 44;
+ u64 stk : 31; // on word boundary
+ u64 tid : kTidBits;
+ u64 siz : 128 - 1 - 31 - 44 - kTidBits; // 39
+ */
+ u64 raw[2];
+
+ void Init(uptr siz, u32 tid, u32 stk) {
+ raw[0] = raw[1] = 0;
+ raw[1] |= (u64)siz << ((1 + 44 + 31 + kTidBits) % 64);
+ raw[1] |= (u64)tid << ((1 + 44 + 31) % 64);
+ raw[0] |= (u64)stk << (1 + 44);
+ raw[1] |= (u64)stk >> (64 - 44 - 1);
+ DCHECK_EQ(Size(), siz);
+ DCHECK_EQ(Tid(), tid);
+ DCHECK_EQ(StackId(), stk);
+ }
+
+ u32 Tid() const {
+ return GetLsb(raw[1] >> ((1 + 44 + 31) % 64), kTidBits);
+ }
+
+ uptr Size() const {
+ return raw[1] >> ((1 + 31 + 44 + kTidBits) % 64);
+ }
+
+ u32 StackId() const {
+ return (raw[0] >> (1 + 44)) | GetLsb(raw[1] << (64 - 44 - 1), 31);
+ }
- MBlock()
- : mtx(MutexTypeMBlock, StatMtxMBlock) {
+ SyncVar *ListHead() const {
+ return (SyncVar*)(GetLsb(raw[0] >> 1, 44) << 3);
}
+
+ void ListPush(SyncVar *v) {
+ SyncVar *lst = ListHead();
+ v->next = lst;
+ u64 x = (u64)v ^ (u64)lst;
+ x = (x >> 3) << 1;
+ raw[0] ^= x;
+ DCHECK_EQ(ListHead(), v);
+ }
+
+ SyncVar *ListPop() {
+ SyncVar *lst = ListHead();
+ SyncVar *nxt = lst->next;
+ lst->next = 0;
+ u64 x = (u64)lst ^ (u64)nxt;
+ x = (x >> 3) << 1;
+ raw[0] ^= x;
+ DCHECK_EQ(ListHead(), nxt);
+ return lst;
+ }
+
+ void ListReset() {
+ SyncVar *lst = ListHead();
+ u64 x = (u64)lst;
+ x = (x >> 3) << 1;
+ raw[0] ^= x;
+ DCHECK_EQ(ListHead(), 0);
+ }
+
+ void Lock();
+ void Unlock();
+ typedef GenericScopedLock<MBlock> ScopedLock;
};
#ifndef TSAN_GO
@@ -63,22 +124,11 @@ const uptr kAllocatorSpace = 0x7d0000000000ULL;
#endif
const uptr kAllocatorSize = 0x10000000000ULL; // 1T.
-struct TsanMapUnmapCallback {
- void OnMap(uptr p, uptr size) const { }
- void OnUnmap(uptr p, uptr size) const {
- // We are about to unmap a chunk of user memory.
- // Mark the corresponding shadow memory as not needed.
- uptr shadow_beg = MemToShadow(p);
- uptr shadow_end = MemToShadow(p + size);
- CHECK(IsAligned(shadow_end|shadow_beg, GetPageSizeCached()));
- FlushUnneededShadowMemory(shadow_beg, shadow_end - shadow_beg);
- }
-};
-
+struct MapUnmapCallback;
typedef SizeClassAllocator64<kAllocatorSpace, kAllocatorSize, sizeof(MBlock),
- DefaultSizeClassMap> PrimaryAllocator;
+ DefaultSizeClassMap, MapUnmapCallback> PrimaryAllocator;
typedef SizeClassAllocatorLocalCache<PrimaryAllocator> AllocatorCache;
-typedef LargeMmapAllocator<TsanMapUnmapCallback> SecondaryAllocator;
+typedef LargeMmapAllocator<MapUnmapCallback> SecondaryAllocator;
typedef CombinedAllocator<PrimaryAllocator, AllocatorCache,
SecondaryAllocator> Allocator;
Allocator *allocator();
@@ -87,6 +137,8 @@ Allocator *allocator();
void TsanCheckFailed(const char *file, int line, const char *cond,
u64 v1, u64 v2);
+const u64 kShadowRodata = (u64)-1; // .rodata shadow marker
+
// FastState (from most significant bit):
// ignore : 1
// tid : kTidBits
@@ -332,6 +384,12 @@ class Shadow : public FastState {
struct SignalContext;
+struct JmpBuf {
+ uptr sp;
+ uptr mangled_sp;
+ uptr *shadow_stack_pos;
+};
+
// This struct is stored in TLS.
struct ThreadState {
FastState fast_state;
@@ -354,7 +412,6 @@ struct ThreadState {
uptr *shadow_stack_pos;
u64 *racy_shadow_addr;
u64 racy_state[2];
- Trace trace;
#ifndef TSAN_GO
// C/C++ uses embed shadow stack of fixed size.
uptr shadow_stack[kShadowStackSize];
@@ -367,6 +424,8 @@ struct ThreadState {
ThreadClock clock;
#ifndef TSAN_GO
AllocatorCache alloc_cache;
+ InternalAllocatorCache internal_alloc_cache;
+ Vector<JmpBuf> jmp_bufs;
#endif
u64 stat[StatCnt];
const int tid;
@@ -375,6 +434,7 @@ struct ThreadState {
bool in_symbolizer;
bool is_alive;
bool is_freeing;
+ bool is_vptr_access;
const uptr stk_addr;
const uptr stk_size;
const uptr tls_addr;
@@ -408,41 +468,30 @@ INLINE ThreadState *cur_thread() {
}
#endif
-enum ThreadStatus {
- ThreadStatusInvalid, // Non-existent thread, data is invalid.
- ThreadStatusCreated, // Created but not yet running.
- ThreadStatusRunning, // The thread is currently running.
- ThreadStatusFinished, // Joinable thread is finished but not yet joined.
- ThreadStatusDead // Joined, but some info (trace) is still alive.
-};
-
-// An info about a thread that is hold for some time after its termination.
-struct ThreadDeadInfo {
- Trace trace;
-};
-
-struct ThreadContext {
- const int tid;
- int unique_id; // Non-rolling thread id.
- uptr os_id; // pid
- uptr user_id; // Some opaque user thread id (e.g. pthread_t).
+class ThreadContext : public ThreadContextBase {
+ public:
+ explicit ThreadContext(int tid);
+ ~ThreadContext();
ThreadState *thr;
- ThreadStatus status;
- bool detached;
- int reuse_count;
+#ifdef TSAN_GO
+ StackTrace creation_stack;
+#else
+ u32 creation_stack_id;
+#endif
SyncClock sync;
// Epoch at which the thread had started.
// If we see an event from the thread stamped by an older epoch,
// the event is from a dead thread that shared tid with this thread.
u64 epoch0;
u64 epoch1;
- StackTrace creation_stack;
- int creation_tid;
- ThreadDeadInfo *dead_info;
- ThreadContext *dead_next; // In dead thread list.
- char *name; // As annotated by user.
- explicit ThreadContext(int tid);
+ // Override superclass callbacks.
+ void OnDead();
+ void OnJoined(void *arg);
+ void OnFinished();
+ void OnStarted(void *arg);
+ void OnCreated(void *arg);
+ void OnReset();
};
struct RacyStacks {
@@ -464,6 +513,7 @@ struct RacyAddress {
struct FiredSuppression {
ReportType type;
uptr pc;
+ Suppression *supp;
};
struct Context {
@@ -476,20 +526,14 @@ struct Context {
Mutex report_mtx;
int nreported;
int nmissed_expected;
+ atomic_uint64_t last_symbolize_time_ns;
- Mutex thread_mtx;
- unsigned thread_seq;
- unsigned unique_thread_seq;
- int alive_threads;
- int max_alive_threads;
- ThreadContext *threads[kMaxTid];
- int dead_list_size;
- ThreadContext* dead_list_head;
- ThreadContext* dead_list_tail;
+ ThreadRegistry *thread_registry;
Vector<RacyStacks> racy_stacks;
Vector<RacyAddress> racy_addresses;
- Vector<FiredSuppression> fired_suppressions;
+ // Number of fired suppressions may be large enough.
+ InternalMmapVector<FiredSuppression> fired_suppressions;
Flags flags;
@@ -520,6 +564,7 @@ class ScopedReport {
void AddMutex(const SyncVar *s);
void AddLocation(uptr addr, uptr size);
void AddSleep(u32 stack_id);
+ void SetCount(int count);
const ReportDesc *GetReport() const;
@@ -537,13 +582,18 @@ void RestoreStack(int tid, const u64 epoch, StackTrace *stk, MutexSet *mset);
void StatAggregate(u64 *dst, u64 *src);
void StatOutput(u64 *stat);
-void ALWAYS_INLINE INLINE StatInc(ThreadState *thr, StatType typ, u64 n = 1) {
+void ALWAYS_INLINE StatInc(ThreadState *thr, StatType typ, u64 n = 1) {
if (kCollectStats)
thr->stat[typ] += n;
}
+void ALWAYS_INLINE StatSet(ThreadState *thr, StatType typ, u64 n) {
+ if (kCollectStats)
+ thr->stat[typ] = n;
+}
void MapShadow(uptr addr, uptr size);
void MapThreadTrace(uptr addr, uptr size);
+void DontNeedShadowFor(uptr addr, uptr size);
void InitializeShadowMemory();
void InitializeInterceptors();
void InitializeDynamicAnnotations();
@@ -552,11 +602,13 @@ void ReportRace(ThreadState *thr);
bool OutputReport(Context *ctx,
const ScopedReport &srep,
const ReportStack *suppress_stack1 = 0,
- const ReportStack *suppress_stack2 = 0);
+ const ReportStack *suppress_stack2 = 0,
+ const ReportLocation *suppress_loc = 0);
bool IsFiredSuppression(Context *ctx,
const ScopedReport &srep,
const StackTrace &trace);
bool IsExpectedReport(uptr addr, uptr size);
+void PrintMatchedBenignRaces();
bool FrameIsInternal(const ReportStack *frame);
ReportStack *SkipTsanInternalFrames(ReportStack *ent);
@@ -592,28 +644,30 @@ void MemoryAccessRange(ThreadState *thr, uptr pc, uptr addr,
uptr size, bool is_write);
void MemoryAccessRangeStep(ThreadState *thr, uptr pc, uptr addr,
uptr size, uptr step, bool is_write);
+void UnalignedMemoryAccess(ThreadState *thr, uptr pc, uptr addr,
+ int size, bool kAccessIsWrite, bool kIsAtomic);
const int kSizeLog1 = 0;
const int kSizeLog2 = 1;
const int kSizeLog4 = 2;
const int kSizeLog8 = 3;
-void ALWAYS_INLINE INLINE MemoryRead(ThreadState *thr, uptr pc,
+void ALWAYS_INLINE MemoryRead(ThreadState *thr, uptr pc,
uptr addr, int kAccessSizeLog) {
MemoryAccess(thr, pc, addr, kAccessSizeLog, false, false);
}
-void ALWAYS_INLINE INLINE MemoryWrite(ThreadState *thr, uptr pc,
+void ALWAYS_INLINE MemoryWrite(ThreadState *thr, uptr pc,
uptr addr, int kAccessSizeLog) {
MemoryAccess(thr, pc, addr, kAccessSizeLog, true, false);
}
-void ALWAYS_INLINE INLINE MemoryReadAtomic(ThreadState *thr, uptr pc,
+void ALWAYS_INLINE MemoryReadAtomic(ThreadState *thr, uptr pc,
uptr addr, int kAccessSizeLog) {
MemoryAccess(thr, pc, addr, kAccessSizeLog, false, true);
}
-void ALWAYS_INLINE INLINE MemoryWriteAtomic(ThreadState *thr, uptr pc,
+void ALWAYS_INLINE MemoryWriteAtomic(ThreadState *thr, uptr pc,
uptr addr, int kAccessSizeLog) {
MemoryAccess(thr, pc, addr, kAccessSizeLog, true, true);
}
@@ -621,7 +675,8 @@ void ALWAYS_INLINE INLINE MemoryWriteAtomic(ThreadState *thr, uptr pc,
void MemoryResetRange(ThreadState *thr, uptr pc, uptr addr, uptr size);
void MemoryRangeFreed(ThreadState *thr, uptr pc, uptr addr, uptr size);
void MemoryRangeImitateWrite(ThreadState *thr, uptr pc, uptr addr, uptr size);
-void IgnoreCtl(ThreadState *thr, bool write, bool begin);
+void ThreadIgnoreBegin(ThreadState *thr);
+void ThreadIgnoreEnd(ThreadState *thr);
void FuncEntry(ThreadState *thr, uptr pc);
void FuncExit(ThreadState *thr);
@@ -640,8 +695,8 @@ void ProcessPendingSignals(ThreadState *thr);
void MutexCreate(ThreadState *thr, uptr pc, uptr addr,
bool rw, bool recursive, bool linker_init);
void MutexDestroy(ThreadState *thr, uptr pc, uptr addr);
-void MutexLock(ThreadState *thr, uptr pc, uptr addr);
-void MutexUnlock(ThreadState *thr, uptr pc, uptr addr);
+void MutexLock(ThreadState *thr, uptr pc, uptr addr, int rec = 1);
+int MutexUnlock(ThreadState *thr, uptr pc, uptr addr, bool all = false);
void MutexReadLock(ThreadState *thr, uptr pc, uptr addr);
void MutexReadUnlock(ThreadState *thr, uptr pc, uptr addr);
void MutexReadOrWriteUnlock(ThreadState *thr, uptr pc, uptr addr);
@@ -677,9 +732,10 @@ void TraceSwitch(ThreadState *thr);
uptr TraceTopPC(ThreadState *thr);
uptr TraceSize();
uptr TraceParts();
+Trace *ThreadTrace(int tid);
extern "C" void __tsan_trace_switch();
-void ALWAYS_INLINE INLINE TraceAddEvent(ThreadState *thr, FastState fs,
+void ALWAYS_INLINE TraceAddEvent(ThreadState *thr, FastState fs,
EventType typ, u64 addr) {
DCHECK_GE((int)typ, 0);
DCHECK_LE((int)typ, 7);
diff --git a/libsanitizer/tsan/tsan_rtl_mutex.cc b/libsanitizer/tsan/tsan_rtl_mutex.cc
index 22a71503c5c..d274a7a8cc5 100644
--- a/libsanitizer/tsan/tsan_rtl_mutex.cc
+++ b/libsanitizer/tsan/tsan_rtl_mutex.cc
@@ -61,7 +61,7 @@ void MutexDestroy(ThreadState *thr, uptr pc, uptr addr) {
&& s->owner_tid != SyncVar::kInvalidTid
&& !s->is_broken) {
s->is_broken = true;
- Lock l(&ctx->thread_mtx);
+ ThreadRegistryLock l(ctx->thread_registry);
ScopedReport rep(ReportTypeMutexDestroyLocked);
rep.AddMutex(s);
StackTrace trace;
@@ -77,9 +77,10 @@ void MutexDestroy(ThreadState *thr, uptr pc, uptr addr) {
DestroyAndFree(s);
}
-void MutexLock(ThreadState *thr, uptr pc, uptr addr) {
+void MutexLock(ThreadState *thr, uptr pc, uptr addr, int rec) {
CHECK_GT(thr->in_rtl, 0);
- DPrintf("#%d: MutexLock %zx\n", thr->tid, addr);
+ DPrintf("#%d: MutexLock %zx rec=%d\n", thr->tid, addr, rec);
+ CHECK_GT(rec, 0);
if (IsAppMem(addr))
MemoryReadAtomic(thr, pc, addr, kSizeLog1);
SyncVar *s = CTX()->synctab.GetOrCreateAndLock(thr, pc, addr, true);
@@ -92,7 +93,7 @@ void MutexLock(ThreadState *thr, uptr pc, uptr addr) {
} else if (s->owner_tid == thr->tid) {
CHECK_GT(s->recursion, 0);
} else {
- Printf("ThreadSanitizer WARNING: double lock\n");
+ Printf("ThreadSanitizer WARNING: double lock of mutex %p\n", addr);
PrintCurrentStack(thr, pc);
}
if (s->recursion == 0) {
@@ -105,33 +106,36 @@ void MutexLock(ThreadState *thr, uptr pc, uptr addr) {
} else if (!s->is_recursive) {
StatInc(thr, StatMutexRecLock);
}
- s->recursion++;
+ s->recursion += rec;
thr->mset.Add(s->GetId(), true, thr->fast_state.epoch());
s->mtx.Unlock();
}
-void MutexUnlock(ThreadState *thr, uptr pc, uptr addr) {
+int MutexUnlock(ThreadState *thr, uptr pc, uptr addr, bool all) {
CHECK_GT(thr->in_rtl, 0);
- DPrintf("#%d: MutexUnlock %zx\n", thr->tid, addr);
+ DPrintf("#%d: MutexUnlock %zx all=%d\n", thr->tid, addr, all);
if (IsAppMem(addr))
MemoryReadAtomic(thr, pc, addr, kSizeLog1);
SyncVar *s = CTX()->synctab.GetOrCreateAndLock(thr, pc, addr, true);
thr->fast_state.IncrementEpoch();
TraceAddEvent(thr, thr->fast_state, EventTypeUnlock, s->GetId());
+ int rec = 0;
if (s->recursion == 0) {
if (!s->is_broken) {
s->is_broken = true;
- Printf("ThreadSanitizer WARNING: unlock of unlocked mutex\n");
+ Printf("ThreadSanitizer WARNING: unlock of unlocked mutex %p\n", addr);
PrintCurrentStack(thr, pc);
}
} else if (s->owner_tid != thr->tid) {
if (!s->is_broken) {
s->is_broken = true;
- Printf("ThreadSanitizer WARNING: mutex unlock by another thread\n");
+ Printf("ThreadSanitizer WARNING: mutex %p is unlocked by wrong thread\n",
+ addr);
PrintCurrentStack(thr, pc);
}
} else {
- s->recursion--;
+ rec = all ? s->recursion : 1;
+ s->recursion -= rec;
if (s->recursion == 0) {
StatInc(thr, StatMutexUnlock);
s->owner_tid = SyncVar::kInvalidTid;
@@ -145,6 +149,7 @@ void MutexUnlock(ThreadState *thr, uptr pc, uptr addr) {
}
thr->mset.Del(s->GetId(), true);
s->mtx.Unlock();
+ return rec;
}
void MutexReadLock(ThreadState *thr, uptr pc, uptr addr) {
@@ -157,7 +162,8 @@ void MutexReadLock(ThreadState *thr, uptr pc, uptr addr) {
thr->fast_state.IncrementEpoch();
TraceAddEvent(thr, thr->fast_state, EventTypeRLock, s->GetId());
if (s->owner_tid != SyncVar::kInvalidTid) {
- Printf("ThreadSanitizer WARNING: read lock of a write locked mutex\n");
+ Printf("ThreadSanitizer WARNING: read lock of a write locked mutex %p\n",
+ addr);
PrintCurrentStack(thr, pc);
}
thr->clock.set(thr->tid, thr->fast_state.epoch());
@@ -178,8 +184,8 @@ void MutexReadUnlock(ThreadState *thr, uptr pc, uptr addr) {
thr->fast_state.IncrementEpoch();
TraceAddEvent(thr, thr->fast_state, EventTypeRUnlock, s->GetId());
if (s->owner_tid != SyncVar::kInvalidTid) {
- Printf("ThreadSanitizer WARNING: read unlock of a write "
- "locked mutex\n");
+ Printf("ThreadSanitizer WARNING: read unlock of a write locked mutex %p\n",
+ addr);
PrintCurrentStack(thr, pc);
}
thr->clock.set(thr->tid, thr->fast_state.epoch());
@@ -229,7 +235,8 @@ void MutexReadOrWriteUnlock(ThreadState *thr, uptr pc, uptr addr) {
}
} else if (!s->is_broken) {
s->is_broken = true;
- Printf("ThreadSanitizer WARNING: mutex unlock by another thread\n");
+ Printf("ThreadSanitizer WARNING: mutex %p is unlock by wrong thread\n",
+ addr);
PrintCurrentStack(thr, pc);
}
thr->mset.Del(s->GetId(), write);
@@ -246,18 +253,19 @@ void Acquire(ThreadState *thr, uptr pc, uptr addr) {
s->mtx.ReadUnlock();
}
+static void UpdateClockCallback(ThreadContextBase *tctx_base, void *arg) {
+ ThreadState *thr = reinterpret_cast<ThreadState*>(arg);
+ ThreadContext *tctx = static_cast<ThreadContext*>(tctx_base);
+ if (tctx->status == ThreadStatusRunning)
+ thr->clock.set(tctx->tid, tctx->thr->fast_state.epoch());
+ else
+ thr->clock.set(tctx->tid, tctx->epoch1);
+}
+
void AcquireGlobal(ThreadState *thr, uptr pc) {
- Context *ctx = CTX();
- Lock l(&ctx->thread_mtx);
- for (unsigned i = 0; i < kMaxTid; i++) {
- ThreadContext *tctx = ctx->threads[i];
- if (tctx == 0)
- continue;
- if (tctx->status == ThreadStatusRunning)
- thr->clock.set(i, tctx->thr->fast_state.epoch());
- else
- thr->clock.set(i, tctx->epoch1);
- }
+ ThreadRegistryLock l(CTX()->thread_registry);
+ CTX()->thread_registry->RunCallbackForEachThreadLocked(
+ UpdateClockCallback, thr);
}
void Release(ThreadState *thr, uptr pc, uptr addr) {
@@ -281,19 +289,20 @@ void ReleaseStore(ThreadState *thr, uptr pc, uptr addr) {
}
#ifndef TSAN_GO
+static void UpdateSleepClockCallback(ThreadContextBase *tctx_base, void *arg) {
+ ThreadState *thr = reinterpret_cast<ThreadState*>(arg);
+ ThreadContext *tctx = static_cast<ThreadContext*>(tctx_base);
+ if (tctx->status == ThreadStatusRunning)
+ thr->last_sleep_clock.set(tctx->tid, tctx->thr->fast_state.epoch());
+ else
+ thr->last_sleep_clock.set(tctx->tid, tctx->epoch1);
+}
+
void AfterSleep(ThreadState *thr, uptr pc) {
- Context *ctx = CTX();
thr->last_sleep_stack_id = CurrentStackId(thr, pc);
- Lock l(&ctx->thread_mtx);
- for (unsigned i = 0; i < kMaxTid; i++) {
- ThreadContext *tctx = ctx->threads[i];
- if (tctx == 0)
- continue;
- if (tctx->status == ThreadStatusRunning)
- thr->last_sleep_clock.set(i, tctx->thr->fast_state.epoch());
- else
- thr->last_sleep_clock.set(i, tctx->epoch1);
- }
+ ThreadRegistryLock l(CTX()->thread_registry);
+ CTX()->thread_registry->RunCallbackForEachThreadLocked(
+ UpdateSleepClockCallback, thr);
}
#endif
diff --git a/libsanitizer/tsan/tsan_rtl_report.cc b/libsanitizer/tsan/tsan_rtl_report.cc
index ff1d43bc9e8..7c0a0280071 100644
--- a/libsanitizer/tsan/tsan_rtl_report.cc
+++ b/libsanitizer/tsan/tsan_rtl_report.cc
@@ -93,8 +93,9 @@ static void StackStripMain(ReportStack *stack) {
DPrintf("Bottom stack frame of stack %zx is missed\n", stack->pc);
}
#else
- if (last && 0 == internal_strcmp(last, "schedunlock"))
- last_frame2->next = 0;
+ // The last frame always point into runtime (gosched0, goexit0, runtime.main).
+ last_frame2->next = 0;
+ (void)last;
#endif
}
@@ -103,17 +104,25 @@ static ReportStack *SymbolizeStack(const StackTrace& trace) {
return 0;
ReportStack *stack = 0;
for (uptr si = 0; si < trace.Size(); si++) {
+ const uptr pc = trace.Get(si);
+#ifndef TSAN_GO
// We obtain the return address, that is, address of the next instruction,
// so offset it by 1 byte.
- bool is_last = (si == trace.Size() - 1);
- ReportStack *ent = SymbolizeCode(trace.Get(si) - !is_last);
+ const uptr pc1 = __sanitizer::StackTrace::GetPreviousInstructionPc(pc);
+#else
+ // FIXME(dvyukov): Go sometimes uses address of a function as top pc.
+ uptr pc1 = pc;
+ if (si != trace.Size() - 1)
+ pc1 -= 1;
+#endif
+ ReportStack *ent = SymbolizeCode(pc1);
CHECK_NE(ent, 0);
ReportStack *last = ent;
while (last->next) {
- last->pc += !is_last;
+ last->pc = pc; // restore original pc for report
last = last->next;
}
- last->pc += !is_last;
+ last->pc = pc; // restore original pc for report
last->next = stack;
stack = ent;
}
@@ -123,14 +132,16 @@ static ReportStack *SymbolizeStack(const StackTrace& trace) {
ScopedReport::ScopedReport(ReportType typ) {
ctx_ = CTX();
- ctx_->thread_mtx.CheckLocked();
+ ctx_->thread_registry->CheckLocked();
void *mem = internal_alloc(MBlockReport, sizeof(ReportDesc));
rep_ = new(mem) ReportDesc;
rep_->typ = typ;
ctx_->report_mtx.Lock();
+ CommonSanitizerReportMutex.Lock();
}
ScopedReport::~ScopedReport() {
+ CommonSanitizerReportMutex.Unlock();
ctx_->report_mtx.Unlock();
DestroyAndFree(rep_);
}
@@ -175,7 +186,7 @@ void ScopedReport::AddMemoryAccess(uptr addr, Shadow s,
void ScopedReport::AddThread(const ThreadContext *tctx) {
for (uptr i = 0; i < rep_->threads.Size(); i++) {
- if (rep_->threads[i]->id == tctx->tid)
+ if ((u32)rep_->threads[i]->id == tctx->tid)
return;
}
void *mem = internal_alloc(MBlockReportThread, sizeof(ReportThread));
@@ -185,42 +196,65 @@ void ScopedReport::AddThread(const ThreadContext *tctx) {
rt->pid = tctx->os_id;
rt->running = (tctx->status == ThreadStatusRunning);
rt->name = tctx->name ? internal_strdup(tctx->name) : 0;
- rt->parent_tid = tctx->creation_tid;
+ rt->parent_tid = tctx->parent_tid;
+ rt->stack = 0;
+#ifdef TSAN_GO
rt->stack = SymbolizeStack(tctx->creation_stack);
+#else
+ uptr ssz = 0;
+ const uptr *stack = StackDepotGet(tctx->creation_stack_id, &ssz);
+ if (stack) {
+ StackTrace trace;
+ trace.Init(stack, ssz);
+ rt->stack = SymbolizeStack(trace);
+ }
+#endif
}
#ifndef TSAN_GO
-static ThreadContext *FindThread(int unique_id) {
+static ThreadContext *FindThreadByUidLocked(int unique_id) {
Context *ctx = CTX();
- ctx->thread_mtx.CheckLocked();
+ ctx->thread_registry->CheckLocked();
for (unsigned i = 0; i < kMaxTid; i++) {
- ThreadContext *tctx = ctx->threads[i];
- if (tctx && tctx->unique_id == unique_id) {
+ ThreadContext *tctx = static_cast<ThreadContext*>(
+ ctx->thread_registry->GetThreadLocked(i));
+ if (tctx && tctx->unique_id == (u32)unique_id) {
return tctx;
}
}
return 0;
}
+static ThreadContext *FindThreadByTidLocked(int tid) {
+ Context *ctx = CTX();
+ ctx->thread_registry->CheckLocked();
+ return static_cast<ThreadContext*>(
+ ctx->thread_registry->GetThreadLocked(tid));
+}
+
+static bool IsInStackOrTls(ThreadContextBase *tctx_base, void *arg) {
+ uptr addr = (uptr)arg;
+ ThreadContext *tctx = static_cast<ThreadContext*>(tctx_base);
+ if (tctx->status != ThreadStatusRunning)
+ return false;
+ ThreadState *thr = tctx->thr;
+ CHECK(thr);
+ return ((addr >= thr->stk_addr && addr < thr->stk_addr + thr->stk_size) ||
+ (addr >= thr->tls_addr && addr < thr->tls_addr + thr->tls_size));
+}
+
ThreadContext *IsThreadStackOrTls(uptr addr, bool *is_stack) {
Context *ctx = CTX();
- ctx->thread_mtx.CheckLocked();
- for (unsigned i = 0; i < kMaxTid; i++) {
- ThreadContext *tctx = ctx->threads[i];
- if (tctx == 0 || tctx->status != ThreadStatusRunning)
- continue;
- ThreadState *thr = tctx->thr;
- CHECK(thr);
- if (addr >= thr->stk_addr && addr < thr->stk_addr + thr->stk_size) {
- *is_stack = true;
- return tctx;
- }
- if (addr >= thr->tls_addr && addr < thr->tls_addr + thr->tls_size) {
- *is_stack = false;
- return tctx;
- }
- }
- return 0;
+ ctx->thread_registry->CheckLocked();
+ ThreadContext *tctx = static_cast<ThreadContext*>(
+ ctx->thread_registry->FindThreadContextLocked(IsInStackOrTls,
+ (void*)addr));
+ if (!tctx)
+ return 0;
+ ThreadState *thr = tctx->thr;
+ CHECK(thr);
+ *is_stack = (addr >= thr->stk_addr && addr < thr->stk_addr + thr->stk_size);
+ return tctx;
}
#endif
@@ -234,7 +268,16 @@ void ScopedReport::AddMutex(const SyncVar *s) {
rep_->mutexes.PushBack(rm);
rm->id = s->uid;
rm->destroyed = false;
- rm->stack = SymbolizeStack(s->creation_stack);
+ rm->stack = 0;
+#ifndef TSAN_GO
+ uptr ssz = 0;
+ const uptr *stack = StackDepotGet(s->creation_stack_id, &ssz);
+ if (stack) {
+ StackTrace trace;
+ trace.Init(stack, ssz);
+ rm->stack = SymbolizeStack(trace);
+ }
+#endif
}
void ScopedReport::AddMutex(u64 id) {
@@ -272,27 +315,28 @@ void ScopedReport::AddLocation(uptr addr, uptr size) {
trace.Init(stack, ssz);
loc->stack = SymbolizeStack(trace);
}
- ThreadContext *tctx = FindThread(creat_tid);
+ ThreadContext *tctx = FindThreadByUidLocked(creat_tid);
if (tctx)
AddThread(tctx);
return;
}
- if (allocator()->PointerIsMine((void*)addr)) {
- MBlock *b = user_mblock(0, (void*)addr);
- ThreadContext *tctx = FindThread(b->alloc_tid);
+ MBlock *b = 0;
+ if (allocator()->PointerIsMine((void*)addr)
+ && (b = user_mblock(0, (void*)addr))) {
+ ThreadContext *tctx = FindThreadByTidLocked(b->Tid());
void *mem = internal_alloc(MBlockReportLoc, sizeof(ReportLocation));
ReportLocation *loc = new(mem) ReportLocation();
rep_->locs.PushBack(loc);
loc->type = ReportLocationHeap;
loc->addr = (uptr)allocator()->GetBlockBegin((void*)addr);
- loc->size = b->size;
- loc->tid = tctx ? tctx->tid : b->alloc_tid;
+ loc->size = b->Size();
+ loc->tid = tctx ? tctx->tid : b->Tid();
loc->name = 0;
loc->file = 0;
loc->line = 0;
loc->stack = 0;
uptr ssz = 0;
- const uptr *stack = StackDepotGet(b->alloc_stack_id, &ssz);
+ const uptr *stack = StackDepotGet(b->StackId(), &ssz);
if (stack) {
StackTrace trace;
trace.Init(stack, ssz);
@@ -331,6 +375,10 @@ void ScopedReport::AddSleep(u32 stack_id) {
}
#endif
+void ScopedReport::SetCount(int count) {
+ rep_->count = count;
+}
+
const ReportDesc *ScopedReport::GetReport() const {
return rep_;
}
@@ -339,21 +387,17 @@ void RestoreStack(int tid, const u64 epoch, StackTrace *stk, MutexSet *mset) {
// This function restores stack trace and mutex set for the thread/epoch.
// It does so by getting stack trace and mutex set at the beginning of
// trace part, and then replaying the trace till the given epoch.
- ThreadContext *tctx = CTX()->threads[tid];
+ Context *ctx = CTX();
+ ctx->thread_registry->CheckLocked();
+ ThreadContext *tctx = static_cast<ThreadContext*>(
+ ctx->thread_registry->GetThreadLocked(tid));
if (tctx == 0)
return;
- Trace* trace = 0;
- if (tctx->status == ThreadStatusRunning) {
- CHECK(tctx->thr);
- trace = &tctx->thr->trace;
- } else if (tctx->status == ThreadStatusFinished
- || tctx->status == ThreadStatusDead) {
- if (tctx->dead_info == 0)
- return;
- trace = &tctx->dead_info->trace;
- } else {
+ if (tctx->status != ThreadStatusRunning
+ && tctx->status != ThreadStatusFinished
+ && tctx->status != ThreadStatusDead)
return;
- }
+ Trace* trace = ThreadTrace(tctx->tid);
Lock l(&trace->mtx);
const int partidx = (epoch / kTracePartSize) % TraceParts();
TraceHeader* hdr = &trace->headers[partidx];
@@ -464,31 +508,58 @@ static void AddRacyStacks(ThreadState *thr, const StackTrace (&traces)[2],
bool OutputReport(Context *ctx,
const ScopedReport &srep,
const ReportStack *suppress_stack1,
- const ReportStack *suppress_stack2) {
+ const ReportStack *suppress_stack2,
+ const ReportLocation *suppress_loc) {
+ atomic_store(&ctx->last_symbolize_time_ns, NanoTime(), memory_order_relaxed);
const ReportDesc *rep = srep.GetReport();
- uptr suppress_pc = IsSuppressed(rep->typ, suppress_stack1);
+ Suppression *supp = 0;
+ uptr suppress_pc = IsSuppressed(rep->typ, suppress_stack1, &supp);
+ if (suppress_pc == 0)
+ suppress_pc = IsSuppressed(rep->typ, suppress_stack2, &supp);
if (suppress_pc == 0)
- suppress_pc = IsSuppressed(rep->typ, suppress_stack2);
+ suppress_pc = IsSuppressed(rep->typ, suppress_loc, &supp);
if (suppress_pc != 0) {
- FiredSuppression supp = {srep.GetReport()->typ, suppress_pc};
- ctx->fired_suppressions.PushBack(supp);
+ FiredSuppression s = {srep.GetReport()->typ, suppress_pc, supp};
+ ctx->fired_suppressions.push_back(s);
}
if (OnReport(rep, suppress_pc != 0))
return false;
PrintReport(rep);
- CTX()->nreported++;
+ ctx->nreported++;
+ if (flags()->halt_on_error)
+ internal__exit(flags()->exitcode);
return true;
}
bool IsFiredSuppression(Context *ctx,
const ScopedReport &srep,
const StackTrace &trace) {
- for (uptr k = 0; k < ctx->fired_suppressions.Size(); k++) {
+ for (uptr k = 0; k < ctx->fired_suppressions.size(); k++) {
if (ctx->fired_suppressions[k].type != srep.GetReport()->typ)
continue;
for (uptr j = 0; j < trace.Size(); j++) {
- if (trace.Get(j) == ctx->fired_suppressions[k].pc)
+ FiredSuppression *s = &ctx->fired_suppressions[k];
+ if (trace.Get(j) == s->pc) {
+ if (s->supp)
+ s->supp->hit_count++;
return true;
+ }
+ }
+ }
+ return false;
+}
+
+static bool IsFiredSuppression(Context *ctx,
+ const ScopedReport &srep,
+ uptr addr) {
+ for (uptr k = 0; k < ctx->fired_suppressions.size(); k++) {
+ if (ctx->fired_suppressions[k].type != srep.GetReport()->typ)
+ continue;
+ FiredSuppression *s = &ctx->fired_suppressions[k];
+ if (addr == s->pc) {
+ if (s->supp)
+ s->supp->hit_count++;
+ return true;
}
}
return false;
@@ -525,8 +596,8 @@ static bool IsJavaNonsense(const ReportDesc *rep) {
|| (frame->func == 0 && frame->file == 0 && frame->line == 0
&& frame->module == 0)) {
if (frame) {
- FiredSuppression supp = {rep->typ, frame->pc};
- CTX()->fired_suppressions.PushBack(supp);
+ FiredSuppression supp = {rep->typ, frame->pc, 0};
+ CTX()->fired_suppressions.push_back(supp);
}
return true;
}
@@ -557,10 +628,6 @@ void ReportRace(ThreadState *thr) {
if (!flags()->report_atomic_races && !RaceBetweenAtomicAndFree(thr))
return;
- if (thr->in_signal_handler)
- Printf("ThreadSanitizer: printing report from signal handler."
- " Can crash or hang.\n");
-
bool freed = false;
{
Shadow s(thr->racy_state[1]);
@@ -583,9 +650,16 @@ void ReportRace(ThreadState *thr) {
}
Context *ctx = CTX();
- Lock l0(&ctx->thread_mtx);
-
- ScopedReport rep(freed ? ReportTypeUseAfterFree : ReportTypeRace);
+ ThreadRegistryLock l0(ctx->thread_registry);
+
+ ReportType typ = ReportTypeRace;
+ if (thr->is_vptr_access)
+ typ = ReportTypeVptrRace;
+ else if (freed)
+ typ = ReportTypeUseAfterFree;
+ ScopedReport rep(typ);
+ if (IsFiredSuppression(ctx, rep, addr))
+ return;
const uptr kMop = 2;
StackTrace traces[kMop];
const uptr toppc = TraceTopPC(thr);
@@ -596,6 +670,8 @@ void ReportRace(ThreadState *thr) {
new(mset2.data()) MutexSet();
Shadow s2(thr->racy_state[1]);
RestoreStack(s2.tid(), s2.epoch(), &traces[1], mset2.data());
+ if (IsFiredSuppression(ctx, rep, traces[1]))
+ return;
if (HandleRacyStacks(thr, traces, addr_min, addr_max))
return;
@@ -611,7 +687,8 @@ void ReportRace(ThreadState *thr) {
for (uptr i = 0; i < kMop; i++) {
FastState s(thr->racy_state[i]);
- ThreadContext *tctx = ctx->threads[s.tid()];
+ ThreadContext *tctx = static_cast<ThreadContext*>(
+ ctx->thread_registry->GetThreadLocked(s.tid()));
if (s.epoch() < tctx->epoch0 || s.epoch() > tctx->epoch1)
continue;
rep.AddThread(tctx);
@@ -627,8 +704,11 @@ void ReportRace(ThreadState *thr) {
}
#endif
+ ReportLocation *suppress_loc = rep.GetReport()->locs.Size() ?
+ rep.GetReport()->locs[0] : 0;
if (!OutputReport(ctx, rep, rep.GetReport()->mops[0]->stack,
- rep.GetReport()->mops[1]->stack))
+ rep.GetReport()->mops[1]->stack,
+ suppress_loc))
return;
AddRacyStacks(thr, traces, addr_min, addr_max);
@@ -646,6 +726,11 @@ void PrintCurrentStackSlow() {
sizeof(__sanitizer::StackTrace))) __sanitizer::StackTrace;
ptrace->SlowUnwindStack(__sanitizer::StackTrace::GetCurrentPc(),
kStackTraceMax);
+ for (uptr i = 0; i < ptrace->size / 2; i++) {
+ uptr tmp = ptrace->trace[i];
+ ptrace->trace[i] = ptrace->trace[ptrace->size - i - 1];
+ ptrace->trace[ptrace->size - i - 1] = tmp;
+ }
StackTrace trace;
trace.Init(ptrace->trace, ptrace->size);
PrintStack(SymbolizeStack(trace));
diff --git a/libsanitizer/tsan/tsan_rtl_thread.cc b/libsanitizer/tsan/tsan_rtl_thread.cc
index e30916dc627..9811e1c015f 100644
--- a/libsanitizer/tsan/tsan_rtl_thread.cc
+++ b/libsanitizer/tsan/tsan_rtl_thread.cc
@@ -18,144 +18,193 @@
namespace __tsan {
+// ThreadContext implementation.
+
+ThreadContext::ThreadContext(int tid)
+ : ThreadContextBase(tid)
+ , thr()
+ , sync()
+ , epoch0()
+ , epoch1() {
+}
+
#ifndef TSAN_GO
-const int kThreadQuarantineSize = 16;
-#else
-const int kThreadQuarantineSize = 64;
+ThreadContext::~ThreadContext() {
+}
#endif
-static void MaybeReportThreadLeak(ThreadContext *tctx) {
- if (tctx->detached)
+void ThreadContext::OnDead() {
+ sync.Reset();
+}
+
+void ThreadContext::OnJoined(void *arg) {
+ ThreadState *caller_thr = static_cast<ThreadState *>(arg);
+ caller_thr->clock.acquire(&sync);
+ StatInc(caller_thr, StatSyncAcquire);
+ sync.Reset();
+}
+
+struct OnCreatedArgs {
+ ThreadState *thr;
+ uptr pc;
+};
+
+void ThreadContext::OnCreated(void *arg) {
+ thr = 0;
+ if (tid == 0)
return;
- if (tctx->status != ThreadStatusCreated
- && tctx->status != ThreadStatusRunning
- && tctx->status != ThreadStatusFinished)
+ OnCreatedArgs *args = static_cast<OnCreatedArgs *>(arg);
+ args->thr->fast_state.IncrementEpoch();
+ // Can't increment epoch w/o writing to the trace as well.
+ TraceAddEvent(args->thr, args->thr->fast_state, EventTypeMop, 0);
+ args->thr->clock.set(args->thr->tid, args->thr->fast_state.epoch());
+ args->thr->fast_synch_epoch = args->thr->fast_state.epoch();
+ args->thr->clock.release(&sync);
+ StatInc(args->thr, StatSyncRelease);
+#ifdef TSAN_GO
+ creation_stack.ObtainCurrent(args->thr, args->pc);
+#else
+ creation_stack_id = CurrentStackId(args->thr, args->pc);
+#endif
+ if (reuse_count == 0)
+ StatInc(args->thr, StatThreadMaxTid);
+}
+
+void ThreadContext::OnReset() {
+ sync.Reset();
+ FlushUnneededShadowMemory(GetThreadTrace(tid), TraceSize() * sizeof(Event));
+ //!!! FlushUnneededShadowMemory(GetThreadTraceHeader(tid), sizeof(Trace));
+}
+
+struct OnStartedArgs {
+ ThreadState *thr;
+ uptr stk_addr;
+ uptr stk_size;
+ uptr tls_addr;
+ uptr tls_size;
+};
+
+void ThreadContext::OnStarted(void *arg) {
+ OnStartedArgs *args = static_cast<OnStartedArgs*>(arg);
+ thr = args->thr;
+ // RoundUp so that one trace part does not contain events
+ // from different threads.
+ epoch0 = RoundUp(epoch1 + 1, kTracePartSize);
+ epoch1 = (u64)-1;
+ new(thr) ThreadState(CTX(), tid, unique_id,
+ epoch0, args->stk_addr, args->stk_size, args->tls_addr, args->tls_size);
+#ifdef TSAN_GO
+ // Setup dynamic shadow stack.
+ const int kInitStackSize = 8;
+ args->thr->shadow_stack = (uptr*)internal_alloc(MBlockShadowStack,
+ kInitStackSize * sizeof(uptr));
+ args->thr->shadow_stack_pos = thr->shadow_stack;
+ args->thr->shadow_stack_end = thr->shadow_stack + kInitStackSize;
+#endif
+#ifndef TSAN_GO
+ AllocatorThreadStart(args->thr);
+#endif
+ thr = args->thr;
+ thr->fast_synch_epoch = epoch0;
+ thr->clock.set(tid, epoch0);
+ thr->clock.acquire(&sync);
+ thr->fast_state.SetHistorySize(flags()->history_size);
+ const uptr trace = (epoch0 / kTracePartSize) % TraceParts();
+ Trace *thr_trace = ThreadTrace(thr->tid);
+ thr_trace->headers[trace].epoch0 = epoch0;
+ StatInc(thr, StatSyncAcquire);
+ sync.Reset();
+ DPrintf("#%d: ThreadStart epoch=%zu stk_addr=%zx stk_size=%zx "
+ "tls_addr=%zx tls_size=%zx\n",
+ tid, (uptr)epoch0, args->stk_addr, args->stk_size,
+ args->tls_addr, args->tls_size);
+ thr->is_alive = true;
+}
+
+void ThreadContext::OnFinished() {
+ if (!detached) {
+ thr->fast_state.IncrementEpoch();
+ // Can't increment epoch w/o writing to the trace as well.
+ TraceAddEvent(thr, thr->fast_state, EventTypeMop, 0);
+ thr->clock.set(thr->tid, thr->fast_state.epoch());
+ thr->fast_synch_epoch = thr->fast_state.epoch();
+ thr->clock.release(&sync);
+ StatInc(thr, StatSyncRelease);
+ }
+ epoch1 = thr->fast_state.epoch();
+
+#ifndef TSAN_GO
+ AllocatorThreadFinish(thr);
+#endif
+ thr->~ThreadState();
+ StatAggregate(CTX()->stat, thr->stat);
+ thr = 0;
+}
+
+#ifndef TSAN_GO
+struct ThreadLeak {
+ ThreadContext *tctx;
+ int count;
+};
+
+static void MaybeReportThreadLeak(ThreadContextBase *tctx_base, void *arg) {
+ Vector<ThreadLeak> &leaks = *(Vector<ThreadLeak>*)arg;
+ ThreadContext *tctx = static_cast<ThreadContext*>(tctx_base);
+ if (tctx->detached || tctx->status != ThreadStatusFinished)
return;
- ScopedReport rep(ReportTypeThreadLeak);
- rep.AddThread(tctx);
- OutputReport(CTX(), rep);
+ for (uptr i = 0; i < leaks.Size(); i++) {
+ if (leaks[i].tctx->creation_stack_id == tctx->creation_stack_id) {
+ leaks[i].count++;
+ return;
+ }
+ }
+ ThreadLeak leak = {tctx, 1};
+ leaks.PushBack(leak);
+}
+#endif
+
+static void ThreadCheckIgnore(ThreadState *thr) {
+ if (thr->ignore_reads_and_writes) {
+ Printf("ThreadSanitizer: thread T%d finished with ignores enabled.\n",
+ thr->tid);
+ }
}
void ThreadFinalize(ThreadState *thr) {
CHECK_GT(thr->in_rtl, 0);
+ ThreadCheckIgnore(thr);
+#ifndef TSAN_GO
if (!flags()->report_thread_leaks)
return;
- Context *ctx = CTX();
- Lock l(&ctx->thread_mtx);
- for (unsigned i = 0; i < kMaxTid; i++) {
- ThreadContext *tctx = ctx->threads[i];
- if (tctx == 0)
- continue;
- MaybeReportThreadLeak(tctx);
+ ThreadRegistryLock l(CTX()->thread_registry);
+ Vector<ThreadLeak> leaks(MBlockScopedBuf);
+ CTX()->thread_registry->RunCallbackForEachThreadLocked(
+ MaybeReportThreadLeak, &leaks);
+ for (uptr i = 0; i < leaks.Size(); i++) {
+ ScopedReport rep(ReportTypeThreadLeak);
+ rep.AddThread(leaks[i].tctx);
+ rep.SetCount(leaks[i].count);
+ OutputReport(CTX(), rep);
}
+#endif
}
int ThreadCount(ThreadState *thr) {
CHECK_GT(thr->in_rtl, 0);
Context *ctx = CTX();
- Lock l(&ctx->thread_mtx);
- int cnt = 0;
- for (unsigned i = 0; i < kMaxTid; i++) {
- ThreadContext *tctx = ctx->threads[i];
- if (tctx == 0)
- continue;
- if (tctx->status != ThreadStatusCreated
- && tctx->status != ThreadStatusRunning)
- continue;
- cnt++;
- }
- return cnt;
-}
-
-static void ThreadDead(ThreadState *thr, ThreadContext *tctx) {
- Context *ctx = CTX();
- CHECK_GT(thr->in_rtl, 0);
- CHECK(tctx->status == ThreadStatusRunning
- || tctx->status == ThreadStatusFinished);
- DPrintf("#%d: ThreadDead uid=%zu\n", thr->tid, tctx->user_id);
- tctx->status = ThreadStatusDead;
- tctx->user_id = 0;
- tctx->sync.Reset();
-
- // Put to dead list.
- tctx->dead_next = 0;
- if (ctx->dead_list_size == 0)
- ctx->dead_list_head = tctx;
- else
- ctx->dead_list_tail->dead_next = tctx;
- ctx->dead_list_tail = tctx;
- ctx->dead_list_size++;
+ uptr result;
+ ctx->thread_registry->GetNumberOfThreads(0, 0, &result);
+ return (int)result;
}
int ThreadCreate(ThreadState *thr, uptr pc, uptr uid, bool detached) {
CHECK_GT(thr->in_rtl, 0);
- Context *ctx = CTX();
- Lock l(&ctx->thread_mtx);
StatInc(thr, StatThreadCreate);
- int tid = -1;
- ThreadContext *tctx = 0;
- if (ctx->dead_list_size > kThreadQuarantineSize
- || ctx->thread_seq >= kMaxTid) {
- // Reusing old thread descriptor and tid.
- if (ctx->dead_list_size == 0) {
- Printf("ThreadSanitizer: %d thread limit exceeded. Dying.\n",
- kMaxTid);
- Die();
- }
- StatInc(thr, StatThreadReuse);
- tctx = ctx->dead_list_head;
- ctx->dead_list_head = tctx->dead_next;
- ctx->dead_list_size--;
- if (ctx->dead_list_size == 0) {
- CHECK_EQ(tctx->dead_next, 0);
- ctx->dead_list_head = 0;
- }
- CHECK_EQ(tctx->status, ThreadStatusDead);
- tctx->status = ThreadStatusInvalid;
- tctx->reuse_count++;
- tctx->sync.Reset();
- tid = tctx->tid;
- DestroyAndFree(tctx->dead_info);
- if (tctx->name) {
- internal_free(tctx->name);
- tctx->name = 0;
- }
- } else {
- // Allocating new thread descriptor and tid.
- StatInc(thr, StatThreadMaxTid);
- tid = ctx->thread_seq++;
- void *mem = internal_alloc(MBlockThreadContex, sizeof(ThreadContext));
- tctx = new(mem) ThreadContext(tid);
- ctx->threads[tid] = tctx;
- MapThreadTrace(GetThreadTrace(tid), TraceSize() * sizeof(Event));
- }
- CHECK_NE(tctx, 0);
- CHECK_GE(tid, 0);
- CHECK_LT(tid, kMaxTid);
+ Context *ctx = CTX();
+ OnCreatedArgs args = { thr, pc };
+ int tid = ctx->thread_registry->CreateThread(uid, detached, thr->tid, &args);
DPrintf("#%d: ThreadCreate tid=%d uid=%zu\n", thr->tid, tid, uid);
- CHECK_EQ(tctx->status, ThreadStatusInvalid);
- ctx->alive_threads++;
- if (ctx->max_alive_threads < ctx->alive_threads) {
- ctx->max_alive_threads++;
- CHECK_EQ(ctx->max_alive_threads, ctx->alive_threads);
- StatInc(thr, StatThreadMaxAlive);
- }
- tctx->status = ThreadStatusCreated;
- tctx->thr = 0;
- tctx->user_id = uid;
- tctx->unique_id = ctx->unique_thread_seq++;
- tctx->detached = detached;
- if (tid) {
- thr->fast_state.IncrementEpoch();
- // Can't increment epoch w/o writing to the trace as well.
- TraceAddEvent(thr, thr->fast_state, EventTypeMop, 0);
- thr->clock.set(thr->tid, thr->fast_state.epoch());
- thr->fast_synch_epoch = thr->fast_state.epoch();
- thr->clock.release(&tctx->sync);
- StatInc(thr, StatSyncRelease);
- tctx->creation_stack.ObtainCurrent(thr, pc);
- tctx->creation_tid = thr->tid;
- }
+ StatSet(thr, StatThreadMaxAlive, ctx->thread_registry->GetMaxAliveThreads());
return tid;
}
@@ -168,9 +217,8 @@ void ThreadStart(ThreadState *thr, int tid, uptr os_id) {
GetThreadStackAndTls(tid == 0, &stk_addr, &stk_size, &tls_addr, &tls_size);
if (tid) {
- if (stk_addr && stk_size) {
- MemoryResetRange(thr, /*pc=*/ 1, stk_addr, stk_size);
- }
+ if (stk_addr && stk_size)
+ MemoryRangeImitateWrite(thr, /*pc=*/ 1, stk_addr, stk_size);
if (tls_addr && tls_size) {
// Check that the thr object is in tls;
@@ -181,116 +229,42 @@ void ThreadStart(ThreadState *thr, int tid, uptr os_id) {
CHECK_GE(thr_end, tls_addr);
CHECK_LE(thr_end, tls_addr + tls_size);
// Since the thr object is huge, skip it.
- MemoryResetRange(thr, /*pc=*/ 2, tls_addr, thr_beg - tls_addr);
- MemoryResetRange(thr, /*pc=*/ 2, thr_end, tls_addr + tls_size - thr_end);
+ MemoryRangeImitateWrite(thr, /*pc=*/ 2, tls_addr, thr_beg - tls_addr);
+ MemoryRangeImitateWrite(thr, /*pc=*/ 2,
+ thr_end, tls_addr + tls_size - thr_end);
}
}
- Lock l(&CTX()->thread_mtx);
- ThreadContext *tctx = CTX()->threads[tid];
- CHECK_NE(tctx, 0);
- CHECK_EQ(tctx->status, ThreadStatusCreated);
- tctx->status = ThreadStatusRunning;
- tctx->os_id = os_id;
- // RoundUp so that one trace part does not contain events
- // from different threads.
- tctx->epoch0 = RoundUp(tctx->epoch1 + 1, kTracePartSize);
- tctx->epoch1 = (u64)-1;
- new(thr) ThreadState(CTX(), tid, tctx->unique_id,
- tctx->epoch0, stk_addr, stk_size,
- tls_addr, tls_size);
-#ifdef TSAN_GO
- // Setup dynamic shadow stack.
- const int kInitStackSize = 8;
- thr->shadow_stack = (uptr*)internal_alloc(MBlockShadowStack,
- kInitStackSize * sizeof(uptr));
- thr->shadow_stack_pos = thr->shadow_stack;
- thr->shadow_stack_end = thr->shadow_stack + kInitStackSize;
-#endif
-#ifndef TSAN_GO
- AllocatorThreadStart(thr);
-#endif
- tctx->thr = thr;
- thr->fast_synch_epoch = tctx->epoch0;
- thr->clock.set(tid, tctx->epoch0);
- thr->clock.acquire(&tctx->sync);
- thr->fast_state.SetHistorySize(flags()->history_size);
- const uptr trace = (tctx->epoch0 / kTracePartSize) % TraceParts();
- thr->trace.headers[trace].epoch0 = tctx->epoch0;
- StatInc(thr, StatSyncAcquire);
- DPrintf("#%d: ThreadStart epoch=%zu stk_addr=%zx stk_size=%zx "
- "tls_addr=%zx tls_size=%zx\n",
- tid, (uptr)tctx->epoch0, stk_addr, stk_size, tls_addr, tls_size);
- thr->is_alive = true;
+ OnStartedArgs args = { thr, stk_addr, stk_size, tls_addr, tls_size };
+ CTX()->thread_registry->StartThread(tid, os_id, &args);
}
void ThreadFinish(ThreadState *thr) {
CHECK_GT(thr->in_rtl, 0);
+ ThreadCheckIgnore(thr);
StatInc(thr, StatThreadFinish);
- // FIXME: Treat it as write.
if (thr->stk_addr && thr->stk_size)
- MemoryResetRange(thr, /*pc=*/ 3, thr->stk_addr, thr->stk_size);
- if (thr->tls_addr && thr->tls_size) {
- const uptr thr_beg = (uptr)thr;
- const uptr thr_end = (uptr)thr + sizeof(*thr);
- // Since the thr object is huge, skip it.
- MemoryResetRange(thr, /*pc=*/ 4, thr->tls_addr, thr_beg - thr->tls_addr);
- MemoryResetRange(thr, /*pc=*/ 5,
- thr_end, thr->tls_addr + thr->tls_size - thr_end);
- }
+ DontNeedShadowFor(thr->stk_addr, thr->stk_size);
+ if (thr->tls_addr && thr->tls_size)
+ DontNeedShadowFor(thr->tls_addr, thr->tls_size);
thr->is_alive = false;
Context *ctx = CTX();
- Lock l(&ctx->thread_mtx);
- ThreadContext *tctx = ctx->threads[thr->tid];
- CHECK_NE(tctx, 0);
- CHECK_EQ(tctx->status, ThreadStatusRunning);
- CHECK_GT(ctx->alive_threads, 0);
- ctx->alive_threads--;
- if (tctx->detached) {
- ThreadDead(thr, tctx);
- } else {
- thr->fast_state.IncrementEpoch();
- // Can't increment epoch w/o writing to the trace as well.
- TraceAddEvent(thr, thr->fast_state, EventTypeMop, 0);
- thr->clock.set(thr->tid, thr->fast_state.epoch());
- thr->fast_synch_epoch = thr->fast_state.epoch();
- thr->clock.release(&tctx->sync);
- StatInc(thr, StatSyncRelease);
- tctx->status = ThreadStatusFinished;
- }
+ ctx->thread_registry->FinishThread(thr->tid);
+}
- // Save from info about the thread.
- tctx->dead_info = new(internal_alloc(MBlockDeadInfo, sizeof(ThreadDeadInfo)))
- ThreadDeadInfo();
- for (uptr i = 0; i < TraceParts(); i++) {
- tctx->dead_info->trace.headers[i].epoch0 = thr->trace.headers[i].epoch0;
- tctx->dead_info->trace.headers[i].stack0.CopyFrom(
- thr->trace.headers[i].stack0);
+static bool FindThreadByUid(ThreadContextBase *tctx, void *arg) {
+ uptr uid = (uptr)arg;
+ if (tctx->user_id == uid && tctx->status != ThreadStatusInvalid) {
+ tctx->user_id = 0;
+ return true;
}
- tctx->epoch1 = thr->fast_state.epoch();
-
-#ifndef TSAN_GO
- AllocatorThreadFinish(thr);
-#endif
- thr->~ThreadState();
- StatAggregate(ctx->stat, thr->stat);
- tctx->thr = 0;
+ return false;
}
int ThreadTid(ThreadState *thr, uptr pc, uptr uid) {
CHECK_GT(thr->in_rtl, 0);
Context *ctx = CTX();
- Lock l(&ctx->thread_mtx);
- int res = -1;
- for (unsigned tid = 0; tid < kMaxTid; tid++) {
- ThreadContext *tctx = ctx->threads[tid];
- if (tctx != 0 && tctx->user_id == uid
- && tctx->status != ThreadStatusInvalid) {
- tctx->user_id = 0;
- res = tid;
- break;
- }
- }
+ int res = ctx->thread_registry->FindThread(FindThreadByUid, (void*)uid);
DPrintf("#%d: ThreadTid uid=%zu tid=%d\n", thr->tid, uid, res);
return res;
}
@@ -301,18 +275,7 @@ void ThreadJoin(ThreadState *thr, uptr pc, int tid) {
CHECK_LT(tid, kMaxTid);
DPrintf("#%d: ThreadJoin tid=%d\n", thr->tid, tid);
Context *ctx = CTX();
- Lock l(&ctx->thread_mtx);
- ThreadContext *tctx = ctx->threads[tid];
- if (tctx->status == ThreadStatusInvalid) {
- Printf("ThreadSanitizer: join of non-existent thread\n");
- return;
- }
- // FIXME(dvyukov): print message and continue (it's user error).
- CHECK_EQ(tctx->detached, false);
- CHECK_EQ(tctx->status, ThreadStatusFinished);
- thr->clock.acquire(&tctx->sync);
- StatInc(thr, StatSyncAcquire);
- ThreadDead(thr, tctx);
+ ctx->thread_registry->JoinThread(tid, thr);
}
void ThreadDetach(ThreadState *thr, uptr pc, int tid) {
@@ -320,31 +283,12 @@ void ThreadDetach(ThreadState *thr, uptr pc, int tid) {
CHECK_GT(tid, 0);
CHECK_LT(tid, kMaxTid);
Context *ctx = CTX();
- Lock l(&ctx->thread_mtx);
- ThreadContext *tctx = ctx->threads[tid];
- if (tctx->status == ThreadStatusInvalid) {
- Printf("ThreadSanitizer: detach of non-existent thread\n");
- return;
- }
- if (tctx->status == ThreadStatusFinished) {
- ThreadDead(thr, tctx);
- } else {
- tctx->detached = true;
- }
+ ctx->thread_registry->DetachThread(tid);
}
void ThreadSetName(ThreadState *thr, const char *name) {
- Context *ctx = CTX();
- Lock l(&ctx->thread_mtx);
- ThreadContext *tctx = ctx->threads[thr->tid];
- CHECK_NE(tctx, 0);
- CHECK_EQ(tctx->status, ThreadStatusRunning);
- if (tctx->name) {
- internal_free(tctx->name);
- tctx->name = 0;
- }
- if (name)
- tctx->name = internal_strdup(name);
+ CHECK_GT(thr->in_rtl, 0);
+ CTX()->thread_registry->SetThreadName(thr->tid, name);
}
void MemoryAccessRange(ThreadState *thr, uptr pc, uptr addr,
@@ -379,6 +323,13 @@ void MemoryAccessRange(ThreadState *thr, uptr pc, uptr addr,
StatInc(thr, StatMopRange);
+ if (*shadow_mem == kShadowRodata) {
+ // Access to .rodata section, no races here.
+ // Measurements show that it can be 10-20% of all memory accesses.
+ StatInc(thr, StatMopRangeRodata);
+ return;
+ }
+
FastState fast_state = thr->fast_state;
if (fast_state.GetIgnoreBit())
return;
@@ -421,25 +372,4 @@ void MemoryAccessRange(ThreadState *thr, uptr pc, uptr addr,
}
}
-void MemoryAccessRangeStep(ThreadState *thr, uptr pc, uptr addr,
- uptr size, uptr step, bool is_write) {
- if (size == 0)
- return;
- FastState fast_state = thr->fast_state;
- if (fast_state.GetIgnoreBit())
- return;
- StatInc(thr, StatMopRange);
- fast_state.IncrementEpoch();
- thr->fast_state = fast_state;
- TraceAddEvent(thr, fast_state, EventTypeMop, pc);
-
- for (uptr addr_end = addr + size; addr < addr_end; addr += step) {
- u64 *shadow_mem = (u64*)MemToShadow(addr);
- Shadow cur(fast_state);
- cur.SetWrite(is_write);
- cur.SetAddr0AndSizeLog(addr & (kShadowCell - 1), kSizeLog1);
- MemoryAccessImpl(thr, addr, kSizeLog1, is_write, false,
- shadow_mem, cur);
- }
-}
} // namespace __tsan
diff --git a/libsanitizer/tsan/tsan_stat.cc b/libsanitizer/tsan/tsan_stat.cc
index fbec4225d9c..3a3ac1172d8 100644
--- a/libsanitizer/tsan/tsan_stat.cc
+++ b/libsanitizer/tsan/tsan_stat.cc
@@ -36,6 +36,8 @@ void StatOutput(u64 *stat) {
name[StatMop8] = " size 8 ";
name[StatMopSame] = " Including same ";
name[StatMopRange] = " Including range ";
+ name[StatMopRodata] = " Including .rodata ";
+ name[StatMopRangeRodata] = " Including .rodata range ";
name[StatShadowProcessed] = "Shadow processed ";
name[StatShadowZero] = " Including empty ";
name[StatShadowNonZero] = " Including non empty ";
@@ -103,6 +105,7 @@ void StatOutput(u64 *stat) {
name[StatInt_realloc] = " realloc ";
name[StatInt_free] = " free ";
name[StatInt_cfree] = " cfree ";
+ name[StatInt_malloc_usable_size] = " malloc_usable_size ";
name[StatInt_mmap] = " mmap ";
name[StatInt_mmap64] = " mmap64 ";
name[StatInt_munmap] = " munmap ";
@@ -133,6 +136,9 @@ void StatOutput(u64 *stat) {
name[StatInt_strcpy] = " strcpy ";
name[StatInt_strncpy] = " strncpy ";
name[StatInt_strstr] = " strstr ";
+ name[StatInt_strdup] = " strdup ";
+ name[StatInt_strcasecmp] = " strcasecmp ";
+ name[StatInt_strncasecmp] = " strncasecmp ";
name[StatInt_atexit] = " atexit ";
name[StatInt___cxa_guard_acquire] = " __cxa_guard_acquire ";
name[StatInt___cxa_guard_release] = " __cxa_guard_release ";
@@ -172,6 +178,7 @@ void StatOutput(u64 *stat) {
name[StatInt_pthread_barrier_destroy] = " pthread_barrier_destroy ";
name[StatInt_pthread_barrier_wait] = " pthread_barrier_wait ";
name[StatInt_pthread_once] = " pthread_once ";
+ name[StatInt_pthread_getschedparam] = " pthread_getschedparam ";
name[StatInt_sem_init] = " sem_init ";
name[StatInt_sem_destroy] = " sem_destroy ";
name[StatInt_sem_wait] = " sem_wait ";
@@ -221,11 +228,13 @@ void StatOutput(u64 *stat) {
name[StatInt_pread] = " pread ";
name[StatInt_pread64] = " pread64 ";
name[StatInt_readv] = " readv ";
+ name[StatInt_preadv] = " preadv ";
name[StatInt_preadv64] = " preadv64 ";
name[StatInt_write] = " write ";
name[StatInt_pwrite] = " pwrite ";
name[StatInt_pwrite64] = " pwrite64 ";
name[StatInt_writev] = " writev ";
+ name[StatInt_pwritev] = " pwritev ";
name[StatInt_pwritev64] = " pwritev64 ";
name[StatInt_send] = " send ";
name[StatInt_sendmsg] = " sendmsg ";
@@ -237,13 +246,21 @@ void StatOutput(u64 *stat) {
name[StatInt_fclose] = " fclose ";
name[StatInt_fread] = " fread ";
name[StatInt_fwrite] = " fwrite ";
+ name[StatInt_fflush] = " fflush ";
+ name[StatInt_abort] = " abort ";
name[StatInt_puts] = " puts ";
name[StatInt_rmdir] = " rmdir ";
name[StatInt_opendir] = " opendir ";
name[StatInt_epoll_ctl] = " epoll_ctl ";
name[StatInt_epoll_wait] = " epoll_wait ";
name[StatInt_poll] = " poll ";
+ name[StatInt_ppoll] = " ppoll ";
name[StatInt_sigaction] = " sigaction ";
+ name[StatInt_signal] = " signal ";
+ name[StatInt_sigsuspend] = " sigsuspend ";
+ name[StatInt_raise] = " raise ";
+ name[StatInt_kill] = " kill ";
+ name[StatInt_pthread_kill] = " pthread_kill ";
name[StatInt_sleep] = " sleep ";
name[StatInt_usleep] = " usleep ";
name[StatInt_nanosleep] = " nanosleep ";
@@ -271,6 +288,87 @@ void StatOutput(u64 *stat) {
name[StatInt_ctime_r] = " ctime_r ";
name[StatInt_asctime] = " asctime ";
name[StatInt_asctime_r] = " asctime_r ";
+ name[StatInt_frexp] = " frexp ";
+ name[StatInt_frexpf] = " frexpf ";
+ name[StatInt_frexpl] = " frexpl ";
+ name[StatInt_getpwnam] = " getpwnam ";
+ name[StatInt_getpwuid] = " getpwuid ";
+ name[StatInt_getgrnam] = " getgrnam ";
+ name[StatInt_getgrgid] = " getgrgid ";
+ name[StatInt_getpwnam_r] = " getpwnam_r ";
+ name[StatInt_getpwuid_r] = " getpwuid_r ";
+ name[StatInt_getgrnam_r] = " getgrnam_r ";
+ name[StatInt_getgrgid_r] = " getgrgid_r ";
+ name[StatInt_clock_getres] = " clock_getres ";
+ name[StatInt_clock_gettime] = " clock_gettime ";
+ name[StatInt_clock_settime] = " clock_settime ";
+ name[StatInt_getitimer] = " getitimer ";
+ name[StatInt_setitimer] = " setitimer ";
+ name[StatInt_time] = " time ";
+ name[StatInt_glob] = " glob ";
+ name[StatInt_glob64] = " glob64 ";
+ name[StatInt_wait] = " wait ";
+ name[StatInt_waitid] = " waitid ";
+ name[StatInt_waitpid] = " waitpid ";
+ name[StatInt_wait3] = " wait3 ";
+ name[StatInt_wait4] = " wait4 ";
+ name[StatInt_inet_ntop] = " inet_ntop ";
+ name[StatInt_inet_pton] = " inet_pton ";
+ name[StatInt_inet_aton] = " inet_aton ";
+ name[StatInt_getaddrinfo] = " getaddrinfo ";
+ name[StatInt_getnameinfo] = " getnameinfo ";
+ name[StatInt_getsockname] = " getsockname ";
+ name[StatInt_gethostent] = " gethostent ";
+ name[StatInt_gethostbyname] = " gethostbyname ";
+ name[StatInt_gethostbyname2] = " gethostbyname2 ";
+ name[StatInt_gethostbyaddr] = " gethostbyaddr ";
+ name[StatInt_gethostent_r] = " gethostent_r ";
+ name[StatInt_gethostbyname_r] = " gethostbyname_r ";
+ name[StatInt_gethostbyname2_r] = " gethostbyname2_r ";
+ name[StatInt_gethostbyaddr_r] = " gethostbyaddr_r ";
+ name[StatInt_getsockopt] = " getsockopt ";
+ name[StatInt_modf] = " modf ";
+ name[StatInt_modff] = " modff ";
+ name[StatInt_modfl] = " modfl ";
+ name[StatInt_getpeername] = " getpeername ";
+ name[StatInt_ioctl] = " ioctl ";
+ name[StatInt_sysinfo] = " sysinfo ";
+ name[StatInt_readdir] = " readdir ";
+ name[StatInt_readdir64] = " readdir64 ";
+ name[StatInt_readdir_r] = " readdir_r ";
+ name[StatInt_readdir64_r] = " readdir64_r ";
+ name[StatInt_ptrace] = " ptrace ";
+ name[StatInt_setlocale] = " setlocale ";
+ name[StatInt_getcwd] = " getcwd ";
+ name[StatInt_get_current_dir_name] = " get_current_dir_name ";
+ name[StatInt_strtoimax] = " strtoimax ";
+ name[StatInt_strtoumax] = " strtoumax ";
+ name[StatInt_mbstowcs] = " mbstowcs ";
+ name[StatInt_mbsrtowcs] = " mbsrtowcs ";
+ name[StatInt_mbsnrtowcs] = " mbsnrtowcs ";
+ name[StatInt_wcstombs] = " wcstombs ";
+ name[StatInt_wcsrtombs] = " wcsrtombs ";
+ name[StatInt_wcsnrtombs] = " wcsnrtombs ";
+ name[StatInt_tcgetattr] = " tcgetattr ";
+ name[StatInt_realpath] = " realpath ";
+ name[StatInt_canonicalize_file_name] = " canonicalize_file_name ";
+ name[StatInt_confstr] = " confstr ";
+ name[StatInt_sched_getaffinity] = " sched_getaffinity ";
+ name[StatInt_strerror] = " strerror ";
+ name[StatInt_strerror_r] = " strerror_r ";
+ name[StatInt_scandir] = " scandir ";
+ name[StatInt_scandir64] = " scandir64 ";
+ name[StatInt_getgroups] = " getgroups ";
+ name[StatInt_wordexp] = " wordexp ";
+ name[StatInt_sigwait] = " sigwait ";
+ name[StatInt_sigwaitinfo] = " sigwaitinfo ";
+ name[StatInt_sigtimedwait] = " sigtimedwait ";
+ name[StatInt_sigemptyset] = " sigemptyset ";
+ name[StatInt_sigfillset] = " sigfillset ";
+ name[StatInt_sigpending] = " sigpending ";
+ name[StatInt_sigprocmask] = " sigprocmask ";
+ name[StatInt_backtrace] = " backtrace ";
+ name[StatInt_backtrace_symbols] = " backtrace_symbols ";
name[StatAnnotation] = "Dynamic annotations ";
name[StatAnnotateHappensBefore] = " HappensBefore ";
@@ -280,6 +378,7 @@ void StatOutput(u64 *stat) {
name[StatAnnotateMutexIsNotPHB] = " MutexIsNotPHB ";
name[StatAnnotateCondVarWait] = " CondVarWait ";
name[StatAnnotateRWLockCreate] = " RWLockCreate ";
+ name[StatAnnotateRWLockCreateStatic] = " StatAnnotateRWLockCreateStatic ";
name[StatAnnotateRWLockDestroy] = " RWLockDestroy ";
name[StatAnnotateRWLockAcquired] = " RWLockAcquired ";
name[StatAnnotateRWLockReleased] = " RWLockReleased ";
diff --git a/libsanitizer/tsan/tsan_stat.h b/libsanitizer/tsan/tsan_stat.h
index 8b08a024be2..e392ff62c63 100644
--- a/libsanitizer/tsan/tsan_stat.h
+++ b/libsanitizer/tsan/tsan_stat.h
@@ -25,6 +25,8 @@ enum StatType {
StatMop8,
StatMopSame,
StatMopRange,
+ StatMopRodata,
+ StatMopRangeRodata,
StatShadowProcessed,
StatShadowZero,
StatShadowNonZero, // Derived.
@@ -100,6 +102,7 @@ enum StatType {
StatInt_realloc,
StatInt_free,
StatInt_cfree,
+ StatInt_malloc_usable_size,
StatInt_mmap,
StatInt_mmap64,
StatInt_munmap,
@@ -129,7 +132,10 @@ enum StatType {
StatInt_strncmp,
StatInt_strcpy,
StatInt_strncpy,
+ StatInt_strcasecmp,
+ StatInt_strncasecmp,
StatInt_strstr,
+ StatInt_strdup,
StatInt_atexit,
StatInt___cxa_guard_acquire,
StatInt___cxa_guard_release,
@@ -167,6 +173,7 @@ enum StatType {
StatInt_pthread_barrier_destroy,
StatInt_pthread_barrier_wait,
StatInt_pthread_once,
+ StatInt_pthread_getschedparam,
StatInt_sem_init,
StatInt_sem_destroy,
StatInt_sem_wait,
@@ -216,11 +223,13 @@ enum StatType {
StatInt_pread,
StatInt_pread64,
StatInt_readv,
+ StatInt_preadv,
StatInt_preadv64,
StatInt_write,
StatInt_pwrite,
StatInt_pwrite64,
StatInt_writev,
+ StatInt_pwritev,
StatInt_pwritev64,
StatInt_send,
StatInt_sendmsg,
@@ -232,14 +241,18 @@ enum StatType {
StatInt_fclose,
StatInt_fread,
StatInt_fwrite,
+ StatInt_fflush,
+ StatInt_abort,
StatInt_puts,
StatInt_rmdir,
StatInt_opendir,
StatInt_epoll_ctl,
StatInt_epoll_wait,
StatInt_poll,
+ StatInt_ppoll,
StatInt_sigaction,
StatInt_signal,
+ StatInt_sigsuspend,
StatInt_raise,
StatInt_kill,
StatInt_pthread_kill,
@@ -270,6 +283,87 @@ enum StatType {
StatInt_ctime_r,
StatInt_asctime,
StatInt_asctime_r,
+ StatInt_frexp,
+ StatInt_frexpf,
+ StatInt_frexpl,
+ StatInt_getpwnam,
+ StatInt_getpwuid,
+ StatInt_getgrnam,
+ StatInt_getgrgid,
+ StatInt_getpwnam_r,
+ StatInt_getpwuid_r,
+ StatInt_getgrnam_r,
+ StatInt_getgrgid_r,
+ StatInt_clock_getres,
+ StatInt_clock_gettime,
+ StatInt_clock_settime,
+ StatInt_getitimer,
+ StatInt_setitimer,
+ StatInt_time,
+ StatInt_glob,
+ StatInt_glob64,
+ StatInt_wait,
+ StatInt_waitid,
+ StatInt_waitpid,
+ StatInt_wait3,
+ StatInt_wait4,
+ StatInt_inet_ntop,
+ StatInt_inet_pton,
+ StatInt_inet_aton,
+ StatInt_getaddrinfo,
+ StatInt_getnameinfo,
+ StatInt_getsockname,
+ StatInt_gethostent,
+ StatInt_gethostbyname,
+ StatInt_gethostbyname2,
+ StatInt_gethostbyaddr,
+ StatInt_gethostent_r,
+ StatInt_gethostbyname_r,
+ StatInt_gethostbyname2_r,
+ StatInt_gethostbyaddr_r,
+ StatInt_getsockopt,
+ StatInt_modf,
+ StatInt_modff,
+ StatInt_modfl,
+ StatInt_getpeername,
+ StatInt_ioctl,
+ StatInt_sysinfo,
+ StatInt_readdir,
+ StatInt_readdir64,
+ StatInt_readdir_r,
+ StatInt_readdir64_r,
+ StatInt_ptrace,
+ StatInt_setlocale,
+ StatInt_getcwd,
+ StatInt_get_current_dir_name,
+ StatInt_strtoimax,
+ StatInt_strtoumax,
+ StatInt_mbstowcs,
+ StatInt_mbsrtowcs,
+ StatInt_mbsnrtowcs,
+ StatInt_wcstombs,
+ StatInt_wcsrtombs,
+ StatInt_wcsnrtombs,
+ StatInt_tcgetattr,
+ StatInt_realpath,
+ StatInt_canonicalize_file_name,
+ StatInt_confstr,
+ StatInt_sched_getaffinity,
+ StatInt_strerror,
+ StatInt_strerror_r,
+ StatInt_scandir,
+ StatInt_scandir64,
+ StatInt_getgroups,
+ StatInt_wordexp,
+ StatInt_sigwait,
+ StatInt_sigwaitinfo,
+ StatInt_sigtimedwait,
+ StatInt_sigemptyset,
+ StatInt_sigfillset,
+ StatInt_sigpending,
+ StatInt_sigprocmask,
+ StatInt_backtrace,
+ StatInt_backtrace_symbols,
// Dynamic annotations.
StatAnnotation,
diff --git a/libsanitizer/tsan/tsan_suppressions.cc b/libsanitizer/tsan/tsan_suppressions.cc
index 8ee8de7c278..912b3834e87 100644
--- a/libsanitizer/tsan/tsan_suppressions.cc
+++ b/libsanitizer/tsan/tsan_suppressions.cc
@@ -11,12 +11,25 @@
#include "sanitizer_common/sanitizer_common.h"
#include "sanitizer_common/sanitizer_libc.h"
+#include "sanitizer_common/sanitizer_placement_new.h"
+#include "sanitizer_common/sanitizer_suppressions.h"
#include "tsan_suppressions.h"
#include "tsan_rtl.h"
#include "tsan_flags.h"
#include "tsan_mman.h"
#include "tsan_platform.h"
+// Suppressions for true/false positives in standard libraries.
+static const char *const std_suppressions =
+// Libstdc++ 4.4 has data races in std::string.
+// See http://crbug.com/181502 for an example.
+"race:^_M_rep$\n"
+"race:^_M_is_leaked$\n"
+// False positive when using std <thread>.
+// Happens because we miss atomic synchronization in libstdc++.
+// See http://llvm.org/bugs/show_bug.cgi?id=17066 for details.
+"race:std::_Sp_counted_ptr_inplace<std::thread::_Impl\n";
+
// Can be overriden in frontend.
#ifndef TSAN_GO
extern "C" const char *WEAK __tsan_default_suppressions() {
@@ -26,7 +39,7 @@ extern "C" const char *WEAK __tsan_default_suppressions() {
namespace __tsan {
-static Suppression *g_suppressions;
+static SuppressionContext* g_ctx;
static char *ReadFile(const char *filename) {
if (filename == 0 || filename[0] == 0)
@@ -36,12 +49,13 @@ static char *ReadFile(const char *filename) {
internal_snprintf(tmp.data(), tmp.size(), "%s", filename);
else
internal_snprintf(tmp.data(), tmp.size(), "%s/%s", GetPwd(), filename);
- fd_t fd = OpenFile(tmp.data(), false);
- if (fd == kInvalidFd) {
+ uptr openrv = OpenFile(tmp.data(), false);
+ if (internal_iserror(openrv)) {
Printf("ThreadSanitizer: failed to open suppressions file '%s'\n",
tmp.data());
Die();
}
+ fd_t fd = openrv;
const uptr fsize = internal_filesize(fd);
if (fsize == (uptr)-1) {
Printf("ThreadSanitizer: failed to stat suppressions file '%s'\n",
@@ -59,114 +73,91 @@ static char *ReadFile(const char *filename) {
return buf;
}
-bool SuppressionMatch(char *templ, const char *str) {
- if (str == 0 || str[0] == 0)
- return false;
- char *tpos;
- const char *spos;
- while (templ && templ[0]) {
- if (templ[0] == '*') {
- templ++;
- continue;
- }
- if (str[0] == 0)
- return false;
- tpos = (char*)internal_strchr(templ, '*');
- if (tpos != 0)
- tpos[0] = 0;
- spos = internal_strstr(str, templ);
- str = spos + internal_strlen(templ);
- templ = tpos;
- if (tpos)
- tpos[0] = '*';
- if (spos == 0)
- return false;
- }
- return true;
-}
-
-Suppression *SuppressionParse(Suppression *head, const char* supp) {
- const char *line = supp;
- while (line) {
- while (line[0] == ' ' || line[0] == '\t')
- line++;
- const char *end = internal_strchr(line, '\n');
- if (end == 0)
- end = line + internal_strlen(line);
- if (line != end && line[0] != '#') {
- const char *end2 = end;
- while (line != end2 && (end2[-1] == ' ' || end2[-1] == '\t'))
- end2--;
- SuppressionType stype;
- if (0 == internal_strncmp(line, "race:", sizeof("race:") - 1)) {
- stype = SuppressionRace;
- line += sizeof("race:") - 1;
- } else if (0 == internal_strncmp(line, "thread:",
- sizeof("thread:") - 1)) {
- stype = SuppressionThread;
- line += sizeof("thread:") - 1;
- } else if (0 == internal_strncmp(line, "mutex:",
- sizeof("mutex:") - 1)) {
- stype = SuppressionMutex;
- line += sizeof("mutex:") - 1;
- } else if (0 == internal_strncmp(line, "signal:",
- sizeof("signal:") - 1)) {
- stype = SuppressionSignal;
- line += sizeof("signal:") - 1;
- } else {
- Printf("ThreadSanitizer: failed to parse suppressions file\n");
- Die();
- }
- Suppression *s = (Suppression*)internal_alloc(MBlockSuppression,
- sizeof(Suppression));
- s->next = head;
- head = s;
- s->type = stype;
- s->templ = (char*)internal_alloc(MBlockSuppression, end2 - line + 1);
- internal_memcpy(s->templ, line, end2 - line);
- s->templ[end2 - line] = 0;
- }
- if (end[0] == 0)
- break;
- line = end + 1;
- }
- return head;
-}
-
void InitializeSuppressions() {
+ ALIGNED(64) static char placeholder_[sizeof(SuppressionContext)];
+ g_ctx = new(placeholder_) SuppressionContext;
const char *supp = ReadFile(flags()->suppressions);
- g_suppressions = SuppressionParse(0, supp);
+ g_ctx->Parse(supp);
#ifndef TSAN_GO
supp = __tsan_default_suppressions();
- g_suppressions = SuppressionParse(g_suppressions, supp);
+ g_ctx->Parse(supp);
+ g_ctx->Parse(std_suppressions);
#endif
}
-uptr IsSuppressed(ReportType typ, const ReportStack *stack) {
- if (g_suppressions == 0 || stack == 0)
- return 0;
- SuppressionType stype;
+SuppressionType conv(ReportType typ) {
if (typ == ReportTypeRace)
- stype = SuppressionRace;
+ return SuppressionRace;
+ else if (typ == ReportTypeVptrRace)
+ return SuppressionRace;
+ else if (typ == ReportTypeUseAfterFree)
+ return SuppressionRace;
else if (typ == ReportTypeThreadLeak)
- stype = SuppressionThread;
+ return SuppressionThread;
else if (typ == ReportTypeMutexDestroyLocked)
- stype = SuppressionMutex;
+ return SuppressionMutex;
else if (typ == ReportTypeSignalUnsafe)
- stype = SuppressionSignal;
- else
+ return SuppressionSignal;
+ else if (typ == ReportTypeErrnoInSignal)
+ return SuppressionNone;
+ Printf("ThreadSanitizer: unknown report type %d\n", typ),
+ Die();
+}
+
+uptr IsSuppressed(ReportType typ, const ReportStack *stack, Suppression **sp) {
+ CHECK(g_ctx);
+ if (!g_ctx->SuppressionCount() || stack == 0) return 0;
+ SuppressionType stype = conv(typ);
+ if (stype == SuppressionNone)
return 0;
+ Suppression *s;
for (const ReportStack *frame = stack; frame; frame = frame->next) {
- for (Suppression *supp = g_suppressions; supp; supp = supp->next) {
- if (stype == supp->type &&
- (SuppressionMatch(supp->templ, frame->func) ||
- SuppressionMatch(supp->templ, frame->file) ||
- SuppressionMatch(supp->templ, frame->module))) {
- DPrintf("ThreadSanitizer: matched suppression '%s'\n", supp->templ);
- return frame->pc;
- }
+ if (g_ctx->Match(frame->func, stype, &s) ||
+ g_ctx->Match(frame->file, stype, &s) ||
+ g_ctx->Match(frame->module, stype, &s)) {
+ DPrintf("ThreadSanitizer: matched suppression '%s'\n", s->templ);
+ s->hit_count++;
+ *sp = s;
+ return frame->pc;
}
}
return 0;
}
+
+uptr IsSuppressed(ReportType typ, const ReportLocation *loc, Suppression **sp) {
+ CHECK(g_ctx);
+ if (!g_ctx->SuppressionCount() || loc == 0 ||
+ loc->type != ReportLocationGlobal)
+ return 0;
+ SuppressionType stype = conv(typ);
+ if (stype == SuppressionNone)
+ return 0;
+ Suppression *s;
+ if (g_ctx->Match(loc->name, stype, &s) ||
+ g_ctx->Match(loc->file, stype, &s) ||
+ g_ctx->Match(loc->module, stype, &s)) {
+ DPrintf("ThreadSanitizer: matched suppression '%s'\n", s->templ);
+ s->hit_count++;
+ *sp = s;
+ return loc->addr;
+ }
+ return 0;
+}
+
+void PrintMatchedSuppressions() {
+ CHECK(g_ctx);
+ InternalMmapVector<Suppression *> matched(1);
+ g_ctx->GetMatched(&matched);
+ if (!matched.size())
+ return;
+ int hit_count = 0;
+ for (uptr i = 0; i < matched.size(); i++)
+ hit_count += matched[i]->hit_count;
+ Printf("ThreadSanitizer: Matched %d suppressions (pid=%d):\n", hit_count,
+ (int)internal_getpid());
+ for (uptr i = 0; i < matched.size(); i++) {
+ Printf("%d %s:%s\n", matched[i]->hit_count,
+ SuppressionTypeString(matched[i]->type), matched[i]->templ);
+ }
+}
} // namespace __tsan
diff --git a/libsanitizer/tsan/tsan_suppressions.h b/libsanitizer/tsan/tsan_suppressions.h
index d44d8dd3529..e38d81ece85 100644
--- a/libsanitizer/tsan/tsan_suppressions.h
+++ b/libsanitizer/tsan/tsan_suppressions.h
@@ -11,30 +11,15 @@
#ifndef TSAN_SUPPRESSIONS_H
#define TSAN_SUPPRESSIONS_H
+#include "sanitizer_common/sanitizer_suppressions.h"
#include "tsan_report.h"
namespace __tsan {
void InitializeSuppressions();
-void FinalizeSuppressions();
-uptr IsSuppressed(ReportType typ, const ReportStack *stack);
-
-// Exposed for testing.
-enum SuppressionType {
- SuppressionRace,
- SuppressionMutex,
- SuppressionThread,
- SuppressionSignal
-};
-
-struct Suppression {
- Suppression *next;
- SuppressionType type;
- char *templ;
-};
-
-Suppression *SuppressionParse(Suppression *head, const char* supp);
-bool SuppressionMatch(char *templ, const char *str);
+void PrintMatchedSuppressions();
+uptr IsSuppressed(ReportType typ, const ReportStack *stack, Suppression **sp);
+uptr IsSuppressed(ReportType typ, const ReportLocation *loc, Suppression **sp);
} // namespace __tsan
diff --git a/libsanitizer/tsan/tsan_symbolize.cc b/libsanitizer/tsan/tsan_symbolize.cc
index 65a994670b5..0c7efac7a26 100644
--- a/libsanitizer/tsan/tsan_symbolize.cc
+++ b/libsanitizer/tsan/tsan_symbolize.cc
@@ -67,16 +67,65 @@ static ReportStack *NewReportStackEntry(const AddressInfo &info) {
return ent;
}
+
+ ReportStack *next;
+ char *module;
+ uptr offset;
+ uptr pc;
+ char *func;
+ char *file;
+ int line;
+ int col;
+
+
+// Denotes fake PC values that come from JIT/JAVA/etc.
+// For such PC values __tsan_symbolize_external() will be called.
+const uptr kExternalPCBit = 1ULL << 60;
+
+// May be overriden by JIT/JAVA/etc,
+// whatever produces PCs marked with kExternalPCBit.
+extern "C" bool __tsan_symbolize_external(uptr pc,
+ char *func_buf, uptr func_siz,
+ char *file_buf, uptr file_siz,
+ int *line, int *col)
+ SANITIZER_WEAK_ATTRIBUTE;
+
+bool __tsan_symbolize_external(uptr pc,
+ char *func_buf, uptr func_siz,
+ char *file_buf, uptr file_siz,
+ int *line, int *col) {
+ return false;
+}
+
ReportStack *SymbolizeCode(uptr addr) {
- if (!IsSymbolizerAvailable())
+ // Check if PC comes from non-native land.
+ if (addr & kExternalPCBit) {
+ // Declare static to not consume too much stack space.
+ // We symbolize reports in a single thread, so this is fine.
+ static char func_buf[1024];
+ static char file_buf[1024];
+ int line, col;
+ if (!__tsan_symbolize_external(addr, func_buf, sizeof(func_buf),
+ file_buf, sizeof(file_buf), &line, &col))
+ return NewReportStackEntry(addr);
+ ReportStack *ent = NewReportStackEntry(addr);
+ ent->module = 0;
+ ent->offset = 0;
+ ent->func = internal_strdup(func_buf);
+ ent->file = internal_strdup(file_buf);
+ ent->line = line;
+ ent->col = col;
+ return ent;
+ }
+ if (!getSymbolizer()->IsAvailable())
return SymbolizeCodeAddr2Line(addr);
ScopedInSymbolizer in_symbolizer;
static const uptr kMaxAddrFrames = 16;
InternalScopedBuffer<AddressInfo> addr_frames(kMaxAddrFrames);
for (uptr i = 0; i < kMaxAddrFrames; i++)
new(&addr_frames[i]) AddressInfo();
- uptr addr_frames_num = __sanitizer::SymbolizeCode(addr, addr_frames.data(),
- kMaxAddrFrames);
+ uptr addr_frames_num =
+ getSymbolizer()->SymbolizeCode(addr, addr_frames.data(), kMaxAddrFrames);
if (addr_frames_num == 0)
return NewReportStackEntry(addr);
ReportStack *top = 0;
@@ -95,11 +144,11 @@ ReportStack *SymbolizeCode(uptr addr) {
}
ReportLocation *SymbolizeData(uptr addr) {
- if (!IsSymbolizerAvailable())
+ if (!getSymbolizer()->IsAvailable())
return 0;
ScopedInSymbolizer in_symbolizer;
DataInfo info;
- if (!__sanitizer::SymbolizeData(addr, &info))
+ if (!getSymbolizer()->SymbolizeData(addr, &info))
return 0;
ReportLocation *ent = (ReportLocation*)internal_alloc(MBlockReportStack,
sizeof(ReportLocation));
@@ -114,4 +163,11 @@ ReportLocation *SymbolizeData(uptr addr) {
return ent;
}
+void SymbolizeFlush() {
+ if (!getSymbolizer()->IsAvailable())
+ return;
+ ScopedInSymbolizer in_symbolizer;
+ getSymbolizer()->Flush();
+}
+
} // namespace __tsan
diff --git a/libsanitizer/tsan/tsan_symbolize.h b/libsanitizer/tsan/tsan_symbolize.h
index 5275936a293..c610d1f5492 100644
--- a/libsanitizer/tsan/tsan_symbolize.h
+++ b/libsanitizer/tsan/tsan_symbolize.h
@@ -18,6 +18,7 @@ namespace __tsan {
ReportStack *SymbolizeCode(uptr addr);
ReportLocation *SymbolizeData(uptr addr);
+void SymbolizeFlush();
ReportStack *SymbolizeCodeAddr2Line(uptr addr);
diff --git a/libsanitizer/tsan/tsan_symbolize_addr2line_linux.cc b/libsanitizer/tsan/tsan_symbolize_addr2line_linux.cc
index 9bdd1ffdc5e..da0c87d297e 100644
--- a/libsanitizer/tsan/tsan_symbolize_addr2line_linux.cc
+++ b/libsanitizer/tsan/tsan_symbolize_addr2line_linux.cc
@@ -85,7 +85,8 @@ static int dl_iterate_phdr_cb(dl_phdr_info *info, size_t size, void *arg) {
DlIteratePhdrCtx *ctx = (DlIteratePhdrCtx*)arg;
InternalScopedBuffer<char> tmp(128);
if (ctx->is_first) {
- internal_snprintf(tmp.data(), tmp.size(), "/proc/%d/exe", GetPid());
+ internal_snprintf(tmp.data(), tmp.size(), "/proc/%d/exe",
+ (int)internal_getpid());
info->dlpi_name = tmp.data();
}
ctx->is_first = false;
diff --git a/libsanitizer/tsan/tsan_sync.cc b/libsanitizer/tsan/tsan_sync.cc
index d392408fd88..04fef615531 100644
--- a/libsanitizer/tsan/tsan_sync.cc
+++ b/libsanitizer/tsan/tsan_sync.cc
@@ -61,7 +61,7 @@ SyncVar* SyncTab::Create(ThreadState *thr, uptr pc, uptr addr) {
const u64 uid = atomic_fetch_add(&uid_gen_, 1, memory_order_relaxed);
SyncVar *res = new(mem) SyncVar(addr, uid);
#ifndef TSAN_GO
- res->creation_stack.ObtainCurrent(thr, pc);
+ res->creation_stack_id = CurrentStackId(thr, pc);
#endif
return res;
}
@@ -80,9 +80,10 @@ SyncVar* SyncTab::GetAndLock(ThreadState *thr, uptr pc,
// the hashmap anyway.
if (PrimaryAllocator::PointerIsMine((void*)addr)) {
MBlock *b = user_mblock(thr, (void*)addr);
- Lock l(&b->mtx);
+ CHECK_NE(b, 0);
+ MBlock::ScopedLock l(b);
SyncVar *res = 0;
- for (res = b->head; res; res = res->next) {
+ for (res = b->ListHead(); res; res = res->next) {
if (res->addr == addr)
break;
}
@@ -90,8 +91,7 @@ SyncVar* SyncTab::GetAndLock(ThreadState *thr, uptr pc,
if (!create)
return 0;
res = Create(thr, pc, addr);
- res->next = b->head;
- b->head = res;
+ b->ListPush(res);
}
if (write_lock)
res->mtx.Lock();
@@ -145,27 +145,37 @@ SyncVar* SyncTab::GetAndRemove(ThreadState *thr, uptr pc, uptr addr) {
}
if (PrimaryAllocator::PointerIsMine((void*)addr)) {
MBlock *b = user_mblock(thr, (void*)addr);
+ CHECK_NE(b, 0);
SyncVar *res = 0;
{
- Lock l(&b->mtx);
- SyncVar **prev = &b->head;
- res = *prev;
- while (res) {
+ MBlock::ScopedLock l(b);
+ res = b->ListHead();
+ if (res) {
if (res->addr == addr) {
if (res->is_linker_init)
return 0;
- *prev = res->next;
- break;
+ b->ListPop();
+ } else {
+ SyncVar **prev = &res->next;
+ res = *prev;
+ while (res) {
+ if (res->addr == addr) {
+ if (res->is_linker_init)
+ return 0;
+ *prev = res->next;
+ break;
+ }
+ prev = &res->next;
+ res = *prev;
+ }
+ }
+ if (res) {
+ StatInc(thr, StatSyncDestroyed);
+ res->mtx.Lock();
+ res->mtx.Unlock();
}
- prev = &res->next;
- res = *prev;
}
}
- if (res) {
- StatInc(thr, StatSyncDestroyed);
- res->mtx.Lock();
- res->mtx.Unlock();
- }
return res;
}
#endif
@@ -195,26 +205,6 @@ SyncVar* SyncTab::GetAndRemove(ThreadState *thr, uptr pc, uptr addr) {
return res;
}
-uptr SyncVar::GetMemoryConsumption() {
- return sizeof(*this)
- + clock.size() * sizeof(u64)
- + read_clock.size() * sizeof(u64)
- + creation_stack.Size() * sizeof(uptr);
-}
-
-uptr SyncTab::GetMemoryConsumption(uptr *nsync) {
- uptr mem = 0;
- for (int i = 0; i < kPartCount; i++) {
- Part *p = &tab_[i];
- Lock l(&p->mtx);
- for (SyncVar *s = p->val; s; s = s->next) {
- *nsync += 1;
- mem += s->GetMemoryConsumption();
- }
- }
- return mem;
-}
-
int SyncTab::PartIdx(uptr addr) {
return (addr >> 3) % kPartCount;
}
diff --git a/libsanitizer/tsan/tsan_sync.h b/libsanitizer/tsan/tsan_sync.h
index 4dbb055a17e..2867a8ac79e 100644
--- a/libsanitizer/tsan/tsan_sync.h
+++ b/libsanitizer/tsan/tsan_sync.h
@@ -57,7 +57,7 @@ struct SyncVar {
const u64 uid; // Globally unique id.
SyncClock clock;
SyncClock read_clock; // Used for rw mutexes only.
- StackTrace creation_stack;
+ u32 creation_stack_id;
int owner_tid; // Set only by exclusive owners.
u64 last_lock;
int recursion;
diff --git a/libsanitizer/tsan/tsan_update_shadow_word_inl.h b/libsanitizer/tsan/tsan_update_shadow_word_inl.h
index b9aa51c7957..42caf80d349 100644
--- a/libsanitizer/tsan/tsan_update_shadow_word_inl.h
+++ b/libsanitizer/tsan/tsan_update_shadow_word_inl.h
@@ -55,8 +55,7 @@ do {
goto RACE;
}
// Do the memory access intersect?
- // In Go all memory accesses are 1 byte, so there can be no intersections.
- if (kCppMode && Shadow::TwoRangesIntersect(old, cur, kAccessSize)) {
+ if (Shadow::TwoRangesIntersect(old, cur, kAccessSize)) {
StatInc(thr, StatShadowIntersect);
if (Shadow::TidsAreEqual(old, cur)) {
StatInc(thr, StatShadowSameThread);
diff --git a/libsanitizer/tsan/tsan_vector.h b/libsanitizer/tsan/tsan_vector.h
index 99e9f792c20..4da8b83d5c3 100644
--- a/libsanitizer/tsan/tsan_vector.h
+++ b/libsanitizer/tsan/tsan_vector.h
@@ -62,6 +62,11 @@ class Vector {
return &end_[-1];
}
+ void PopBack() {
+ DCHECK_GT(end_, begin_);
+ end_--;
+ }
+
void Resize(uptr size) {
uptr old_size = Size();
EnsureSize(size);
diff --git a/libsanitizer/ubsan/ubsan_diag.cc b/libsanitizer/ubsan/ubsan_diag.cc
index d56ef849b6f..c7378fdbda2 100644
--- a/libsanitizer/ubsan/ubsan_diag.cc
+++ b/libsanitizer/ubsan/ubsan_diag.cc
@@ -26,7 +26,8 @@ Location __ubsan::getCallerLocation(uptr CallerLoc) {
uptr Loc = StackTrace::GetPreviousInstructionPc(CallerLoc);
AddressInfo Info;
- if (!SymbolizeCode(Loc, &Info, 1) || !Info.module || !*Info.module)
+ if (!getSymbolizer()->SymbolizeCode(Loc, &Info, 1) ||
+ !Info.module || !*Info.module)
return Location(Loc);
if (!Info.file)
@@ -107,7 +108,7 @@ static void renderText(const char *Message, const Diag::Arg *Args) {
Printf("%s", A.String);
break;
case Diag::AK_Mangled: {
- Printf("'%s'", Demangle(A.String));
+ Printf("'%s'", getSymbolizer()->Demangle(A.String));
break;
}
case Diag::AK_SInt:
diff --git a/libsanitizer/ubsan/ubsan_value.h b/libsanitizer/ubsan/ubsan_value.h
index 6ca0f56c99d..9b31eb7defb 100644
--- a/libsanitizer/ubsan/ubsan_value.h
+++ b/libsanitizer/ubsan/ubsan_value.h
@@ -23,8 +23,8 @@
// FIXME: Move this out to a config header.
#if __SIZEOF_INT128__
-__extension__ typedef __int128 s128;
-__extension__ typedef unsigned __int128 u128;
+typedef __int128 s128;
+typedef unsigned __int128 u128;
#define HAVE_INT128_T 1
#else
#define HAVE_INT128_T 0
diff --git a/libssp/ChangeLog b/libssp/ChangeLog
index eb020d9dcf8..c127fce7f3f 100644
--- a/libssp/ChangeLog
+++ b/libssp/ChangeLog
@@ -1,3 +1,7 @@
+2013-09-20 Alan Modra <amodra@gmail.com>
+
+ * configure: Regenerate.
+
2013-02-06 Richard Sandiford <rdsandiford@googlemail.com>
Revert previous patch.
diff --git a/libssp/configure b/libssp/configure
index 0bb40500973..b26c0b33524 100755
--- a/libssp/configure
+++ b/libssp/configure
@@ -636,7 +636,6 @@ CPP
am__fastdepCC_FALSE
am__fastdepCC_TRUE
CCDEPMODE
-am__nodep
AMDEPBACKSLASH
AMDEP_FALSE
AMDEP_TRUE
@@ -2803,11 +2802,11 @@ MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
# We need awk for the "check" target. The system "awk" is bad on
# some platforms.
-# Always define AMTAR for backward compatibility. Yes, it's still used
-# in the wild :-( We should find a proper way to deprecate it ...
-AMTAR='$${TAR-tar}'
+# Always define AMTAR for backward compatibility.
-am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'
+AMTAR=${AMTAR-"${am_missing_run}tar"}
+
+am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'
@@ -3758,7 +3757,6 @@ fi
if test "x$enable_dependency_tracking" != xno; then
am_depcomp="$ac_aux_dir/depcomp"
AMDEPBACKSLASH='\'
- am__nodep='_no'
fi
if test "x$enable_dependency_tracking" != xno; then
AMDEP_TRUE=
@@ -3783,7 +3781,6 @@ else
# 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'.
- rm -rf conftest.dir
mkdir conftest.dir
# Copy depcomp to subdir because otherwise we won't find it if we're
# using a relative directory.
@@ -3843,7 +3840,7 @@ else
break
fi
;;
- msvc7 | msvc7msys | msvisualcpp | msvcmsys)
+ msvisualcpp | msvcmsys)
# This compiler won't grok `-c -o', but also, the minuso test has
# not run yet. These depmodes are late enough in the game, and
# so weak that their functioning should not be impacted.
@@ -6388,7 +6385,7 @@ ia64-*-hpux*)
rm -rf conftest*
;;
-x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \
+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
@@ -6413,7 +6410,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
;;
esac
;;
- ppc64-*linux*|powerpc64-*linux*)
+ powerpc64le-*linux*)
+ LD="${LD-ld} -m elf32lppclinux"
+ ;;
+ powerpc64-*linux*)
LD="${LD-ld} -m elf32ppclinux"
;;
s390x-*linux*)
@@ -6432,7 +6432,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
x86_64-*linux*)
LD="${LD-ld} -m elf_x86_64"
;;
- ppc*-*linux*|powerpc*-*linux*)
+ powerpcle-*linux*)
+ LD="${LD-ld} -m elf64lppc"
+ ;;
+ powerpc-*linux*)
LD="${LD-ld} -m elf64ppc"
;;
s390*-*linux*|s390*-*tpf*)
@@ -10661,7 +10664,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 10664 "configure"
+#line 10667 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -10767,7 +10770,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 10770 "configure"
+#line 10773 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index e2c846f98e9..38c70c583e8 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,1022 @@
+2013-11-11 Jonathan Wakely <jwakely.gcc@gmail.com>
+
+ PR libstdc++/54562
+ * include/std/mutex (__timed_mutex_impl::__clock_t): Use
+ high_resolution_clock for absolute timeouts, because
+ pthread_mutex_timedlock uses CLOCK_REALTIME not CLOCK_MONOTONIC.
+ (__timed_mutex_impl::_M_try_lock_for): Use steady_clock for relative
+ timeouts as per [thread.req.timing].
+ (__timed_mutex_impl::_M_try_lock_until<Clock,Duration>): Convert to
+ __clock_t time point instead of using _M_try_lock_for.
+
+2013-11-09 Jonathan Wakely <jwakely.gcc@gmail.com>
+
+ PR libstdc++/58982
+ * include/bits/stl_algobase.h (__copy_move::__copy_m): Use assertion
+ to prevent using memmove() on non-assignable types.
+ (__copy_move_backward::__copy_move_b): Likewise.
+ * include/bits/stl_uninitialized.h (uninitialized_copy
+ uninitialized_copy_n, uninitialized_fill, uninitialized_fill_n,
+ __uninitialized_default, __uninitialized_default_n): Check for
+ assignable as well as trivial.
+ * testsuite/20_util/specialized_algorithms/uninitialized_copy/
+ 58982.cc: New.
+ * testsuite/20_util/specialized_algorithms/uninitialized_copy_n/
+ 58982.cc: New.
+ * testsuite/20_util/specialized_algorithms/uninitialized_fill/
+ 58982.cc: New.
+ * testsuite/20_util/specialized_algorithms/uninitialized_fill_n/
+ 58982.cc: New.
+ * testsuite/25_algorithms/copy/58982.cc: New.
+ * testsuite/25_algorithms/copy_n/58982.cc: New.
+
+2013-11-08 François Dumont <fdumont@gcc.gnu.org>
+
+ * include/debug/safe_iterator.h (_BeforeBeginHelper<>::_S_Is):
+ Take only a const safe iterator reference.
+ (_BeforeBeginHelper<>::_S_Is_beginnest): Likewise.
+ (__get_distance): Take only one type of iterator.
+ (_Safe_iterator<>::_M_valid_range<>): Not template anymore.
+ (_Safe_iterator<>::_M_get_sequence()): Return pointer to const
+ sequence from a const_iterator and a pointer to sequence from an
+ iterator.
+ * include/debug/safe_iterator.tcc: Adapt.
+ * include/debug/safe_local_iterator.h
+ (_Safe_local_iterator<>::_M_valid_range<>): Not template anymore.
+ (_Safe_local_iterator<>::_M_get_sequence()): Return pointer to
+ const sequence from a const_iterator and a pointer to sequence
+ from an iterator.
+ * include/debug/safe_local_iterator.tcc: Adapt.
+ * include/debug/forward_list
+ (_BeforeBeginHelper<std::__debug::forward_list<>>): Adapt.
+
+2013-11-08 Jonathan Wakely <jwakely.gcc@gmail.com>
+
+ * include/bits/regex_automaton.h (__detail::_State): Split
+ non-dependent parts into new _State_base.
+ (__detail::_NFA): Likewise for _NFA_base. Use std::move() to avoid
+ copies when inserting _MatcherT and _StateT objects.
+ * include/bits/regex_automaton.tcc: Move member definitions to base
+ class. Qualify dependent names.
+ * include/bits/regex_compiler.h (__detail::_Compiler::_M_get_nfa): Make
+ non-const and use std::move to avoid copying.
+ * include/bits/regex_compiler.tcc: Likewise.
+ * include/bits/regex_executor.h (__detail::_Executor::_M_is_word): Use
+ array, so past-the-end iterator is valid.
+
+ * include/bits/regex_automaton.h (__detail::_State, __detail::_NFA,
+ __detail::_StateSeq): Remove redundant _CharT template parameters.
+ * include/bits/regex_automaton.tcc: Likewise.
+ * include/bits/regex_compiler.h (__detail::_Compiler): Likewise.
+ (__compile_nfa): Add object generator for _Compiler.
+ * include/bits/regex_compiler.tcc: Remove _CharT template parameters.
+ * include/bits/regex_executor.h: Likewise.
+ * include/bits/regex_executor.tcc: Likewise.
+ * include/bits/regex.h (basic_regex): Assert char_type matches. Use
+ __compile_nfa object generator. Remove _CharT template parameter.
+
+ * include/bits/regex_compiler.h (__detail::_AnyMatcher,
+ __detail::_CharMatcher, __detail::_BracketMatcher): Remove redundant
+ _CharT template parameters.
+ * include/bits/regex_compiler.tcc: Likewise.
+
+ * include/bits/regex_compiler.h (__detail::__compile_nfa): Overload
+ so that std::basic_string<C> and std::vector<C> iterators dispatch to
+ the const C* compiler.
+
+ * include/bits/regex_compiler.h (__detail::__has_contiguous_iter):
+ vector<bool> storage is not contiguous.
+
+2013-11-06 Jonathan Wakely <jwakely.gcc@gmail.com>
+
+ * include/bits/regex_automaton.h (_S_opcode_word_boundry): Rename to
+ _S_opcode_word_boundary.
+ * include/bits/regex_automaton.tcc: Likewise.
+ * include/bits/regex_executor.h (__detail::_Executor::_M_word_boundry):
+ Rename to _M_word_boundary.
+ * include/bits/regex_executor.tcc: Likewise.
+
+2013-11-05 Jonathan Wakely <jwakely.gcc@gmail.com>
+
+ N3655 C++1y TransformationTraits Redux
+ * include/std/type_traits (remove_const_t, remove_volatile_t,
+ remove_cv_t, add_const_t, add_volatile_t, add_cv_t, remove_reference_t,
+ add_lvalue_reference_t, add_rvalue_reference_t, make_signed_t,
+ make_unsigned_t, remove_extent_t, remove_all_extents_t,
+ remove_pointer_t, add_pointer_t, aligned_storage_t, decay_t,
+ enable_if_t, conditional_t, common_type_t, underlying_type_t,
+ result_of_t): Define.
+ * doc/xml/manual/status_cxx2014.xml: Update.
+ * testsuite/20_util/add_lvalue_reference/requirements/typedefs-3.cc:
+ New.
+ * testsuite/20_util/add_rvalue_reference/requirements/typedefs-3.cc:
+ New.
+ * testsuite/20_util/common_type/requirements/typedefs-3.cc: New.
+ * testsuite/20_util/conditional/requirements/typedefs-2.cc: New.
+ * testsuite/20_util/decay/requirements/typedefs-2.cc: New.
+ * testsuite/20_util/enable_if/requirements/typedefs-2.cc: New.
+ * testsuite/20_util/make_signed/requirements/typedefs-3.cc: New.
+ * testsuite/20_util/make_unsigned/requirements/typedefs-3.cc: New.
+ * testsuite/20_util/remove_reference/requirements/typedefs.cc: New.
+ * testsuite/20_util/result_of/requirements/typedefs.cc: New.
+ * testsuite/20_util/underlying_type/requirements/typedefs-3.cc: New.
+ * testsuite/20_util/common_type/requirements/typedefs-2.cc: Change to
+ compile-only test.
+ * testsuite/20_util/decay/requirements/typedefs.cc: Likewise.
+ * testsuite/20_util/make_signed/requirements/typedefs-1.cc: Likewise.
+ * testsuite/20_util/declval/requirements/1_neg.cc: Adjust dg-error
+ line number.
+ * testsuite/20_util/make_signed/requirements/typedefs_neg.cc:
+ Likewise.
+ * testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc:
+ Likewise.
+
+2013-11-05 Jonathan Wakely <jwakely.gcc@gmail.com>
+
+ * doc/xml/manual/status_cxx2011.xml: Document aligned_union as
+ missing.
+
+2013-11-05 Jonathan Wakely <jwakely.gcc@gmail.com>
+ Paolo Carlini <paolo.carlini@oracle.com>
+
+ * include/experimental/optional: Use __and_<> and __not_<> in
+ conditions. Style fixes.
+ (__constexpr_addressof, swap): Make inline.
+ * testsuite/experimental/optional/cons/copy.cc: Adjust constants for
+ 32-bit targets.
+ * testsuite/experimental/optional/cons/move.cc: Likewise.
+ * testsuite/experimental/optional/cons/value.cc: Likewise.
+ * testsuite/experimental/optional/constexpr/cons/value.cc: Likewise.
+
+2013-11-01 Michael Brune <lucdanton@free.fr>
+
+ * include/bits/enable_special_members.h: New.
+ * include/experimental/optional: New.
+ * include/Makefile.am: Handle include/experimental.
+ * include/Makefile.in: Regenerate.
+ * testsuite/libstdc++-dg/conformance.exp: Run tests from
+ testsuite/experimental sub-directory.
+ * testsuite/experimental/optional/assignment/1.cc: New.
+ * testsuite/experimental/optional/assignment/2.cc: New.
+ * testsuite/experimental/optional/assignment/3.cc: New.
+ * testsuite/experimental/optional/assignment/4.cc: New.
+ * testsuite/experimental/optional/assignment/5.cc: New.
+ * testsuite/experimental/optional/assignment/6.cc: New.
+ * testsuite/experimental/optional/cons/copy.cc: New.
+ * testsuite/experimental/optional/cons/default.cc: New.
+ * testsuite/experimental/optional/cons/move.cc: New.
+ * testsuite/experimental/optional/cons/value.cc: New.
+ * testsuite/experimental/optional/constexpr/cons/default.cc: New.
+ * testsuite/experimental/optional/constexpr/cons/value.cc: New.
+ * testsuite/experimental/optional/constexpr/in_place.cc: New.
+ * testsuite/experimental/optional/constexpr/make_optional.cc: New.
+ * testsuite/experimental/optional/constexpr/nullopt.cc: New.
+ * testsuite/experimental/optional/constexpr/observers/1.cc: New.
+ * testsuite/experimental/optional/constexpr/observers/2.cc: New.
+ * testsuite/experimental/optional/constexpr/observers/3.cc: New.
+ * testsuite/experimental/optional/constexpr/observers/4.cc: New.
+ * testsuite/experimental/optional/constexpr/observers/5.cc: New.
+ * testsuite/experimental/optional/constexpr/relops/1.cc: New.
+ * testsuite/experimental/optional/constexpr/relops/2.cc: New.
+ * testsuite/experimental/optional/constexpr/relops/3.cc: New.
+ * testsuite/experimental/optional/constexpr/relops/4.cc: New.
+ * testsuite/experimental/optional/constexpr/relops/5.cc: New.
+ * testsuite/experimental/optional/constexpr/relops/6.cc: New.
+ * testsuite/experimental/optional/in_place.cc: New.
+ * testsuite/experimental/optional/make_optional.cc: New.
+ * testsuite/experimental/optional/nullopt.cc: New.
+ * testsuite/experimental/optional/observers/1.cc: New.
+ * testsuite/experimental/optional/observers/2.cc: New.
+ * testsuite/experimental/optional/observers/3.cc: New.
+ * testsuite/experimental/optional/observers/4.cc: New.
+ * testsuite/experimental/optional/observers/5.cc: New.
+ * testsuite/experimental/optional/relops/1.cc: New.
+ * testsuite/experimental/optional/relops/2.cc: New.
+ * testsuite/experimental/optional/relops/3.cc: New.
+ * testsuite/experimental/optional/relops/4.cc: New.
+ * testsuite/experimental/optional/relops/5.cc: New.
+ * testsuite/experimental/optional/relops/6.cc: New.
+ * testsuite/experimental/optional/requirements.cc: New.
+ * testsuite/experimental/optional/swap/1.cc: New.
+
+2013-11-01 Jonathan Wakely <jwakely.gcc@gmail.com>
+
+ * include/bits/stl_function.h (logical_not<void>): Add noexcept.
+
+2013-11-01 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR libstdc++/58952
+ * include/c_global/cstdio: Undef getchar.
+
+2013-11-01 Jonathan Wakely <jwakely.gcc@gmail.com>
+
+ N3421 C++1y Transparent functors
+ * include/bits/stl_function.h (plus<void>, minus<void>,
+ multiplies<void>, divides<void>, modulus<void>, negate<void>,
+ equal_to<void>, not_equal_to<void>, greater<void>, less<void>,
+ greater_equal<void>, less_equal<void>, logical_and<void>,
+ logical_or<void>, logical_not<void>, bit_and<void>, bit_or<void>,
+ bit_xor<void>, bit_not<void>): Define.
+ * doc/xml/manual/status_cxx2014.xml: Update.
+ * testsuite/20_util/function_objects/comparisons_void.cc: New.
+
+2013-10-31 Jonathan Wakely <jwakely.gcc@gmail.com>
+
+ * include/std/tuple (_Index_tuple, _Build_index_tuple): Move to
+ <utility>.
+ * include/std/utility (integer_sequence, make_integer_sequence,
+ index_sequence, make_index_sequence, index_sequence_for): Define.
+ * doc/xml/manual/status_cxx2014.xml: Update.
+ * testsuite/20_util/integer_sequence/intseq.cc: New.
+ * testsuite/20_util/integer_sequence/requirements/typedefs.cc: New.
+
+2013-10-31 Steve Ellcey <sellcey@mips.com>
+
+ * configure.ac: Add header checks for fenv.h and complex.h.
+ * configure: Regenerate.
+
+2013-10-31 Edward Smith-Rowland <3dw4rd@verizon.net>
+
+ Implement C++14 digit separators.
+ * include/include/bits/parse_numbers.h: Change struct _Digit<_Base, '`'>
+ to struct _Digit<_Base, '\''>.
+
+2013-10-31 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * testsuite/20_util/default_delete/48631_neg.cc: Tweak dg-prune.
+
+2013-10-30 Jonathan Wakely <jwakely.gcc@gmail.com>
+
+ * testsuite/29_atomics/atomic/operators/pointer_partial_void.cc: Fix
+ and enable VERIFY tests.
+
+2013-10-30 Jonathan Wakely <jwakely.gcc@gmail.com>
+
+ * include/bits/shared_ptr (__shared_ptr): Assert non-void pointer.
+ * include/bits/shared_ptr (default_delete): Likewise.
+ * testsuite/20_util/shared_ptr/cons/58839.cc: Do not use
+ default_delete<void>.
+ * testsuite/20_util/shared_ptr/cons/void_neg.cc: New.
+ * testsuite/20_util/default_delete/void_neg.cc: New.
+ * testsuite/20_util/shared_ptr/cons/43820_neg.cc: Adjust line numbers.
+ * testsuite/20_util/unique_ptr/assign/48635_neg.cc: Likewise.
+
+2013-10-29 Jonathan Wakely <jwakely.gcc@gmail.com>
+
+ PR libstdc++/58839
+ * include/bits/shared_ptr_base.h
+ (__shared_ptr<T>::__shared_ptr(unique_ptr<U,D>&&)): Only use addressof
+ when unique_ptr<U,D>::pointer is not a built-in pointer type.
+ * testsuite/20_util/shared_ptr/cons/58839.cc: New.
+ * testsuite/20_util/enable_shared_from_this/members/assign.cc: New.
+ * testsuite/20_util/enable_shared_from_this/members/unique_ptr.cc: New.
+
+2013-10-29 Jonathan Wakely <jwakely.gcc@gmail.com>
+
+ * include/bits/hashtable.cc (__access_protected_ctor): Define and use
+ new type instead of _Hashtable_ebo_helper.
+ * testsuite/23_containers/unordered_set/
+ not_default_constructible_hash_neg.cc: Adjust line number.
+
+2013-10-28 Tim Shen <timshen91@gmail.com>
+
+ * regex_executor.tcc: Add comments.
+
+2013-10-26 Tim Shen <timshen91@gmail.com>
+
+ * include/bits/regex.h: Remove unnecessary friends.
+ * include/bits/regex.tcc (__regex_algo_impl<>): Move __get_executor
+ to here.
+ * include/bits/regex_executor.h: Remove _DFSExecutor and _BFSExecutor;
+ they are merged into _Executor. Eliminate quantifier tracking part, so
+ it's faster.
+ * include/bits/regex_executor.tcc: Implement _Executor.
+ * testsuite/28_regex/algorithms/regex_match/ecma/char/ungreedy.cc: New.
+ * testsuite/28_regex/algorithms/regex_search/ecma/greedy.cc: Adjust
+ duplicate testcases.
+ * testsuite/performance/28_regex/split.h: New.
+ * testsuite/performance/28_regex/split_bfs.cc: New.
+ * testsuite/util/testsuite_regex.h: Adjust behavior of two-executors
+ agreement judger: do not compare match_results when executor return
+ false.
+
+2013-10-25 François Dumont <fdumont@gcc.gnu.org>
+
+ * include/debug/formatter.h (__check_singular): Add const on
+ iterator reference.
+ * include/debug/functions.h (__check_singular): Likewise.
+ (__check_singular(const _Safe_iterator<_Ite, _Seq>&)): Delete.
+ (__check_dereferenceable(const _Ite&)): Add const on iterator
+ reference.
+ (__check_dereferenceable(const _Safe_local_iterator<>&)): New.
+ * include/debug/safe_iterator.h (__check_singular_aux): Review
+ comment.
+ * testsuite/23_containers/vector/debug/debug_functions.cc: New.
+ * testsuite/23_containers/unordered_set/debug/debug_functions.cc:
+ New.
+
+2013-10-23 Chris Jefferson <chris@bubblescope.net>
+ Paolo Carlini <paolo.carlini@oracle.com>
+
+ * testsuite/util/testsuite_containergen.h: New.
+ * testsuite/util/testsuite_iterators.h (test_container<>::val): Add.
+ * testsuite/25_algorithms/nth_element/random_test.cc: New, use the
+ above.
+ * testsuite/25_algorithms/partial_sort/random_test.cc: Likewise.
+ * testsuite/25_algorithms/partial_sort_copy/random_test.cc: Likewise.
+ * testsuite/25_algorithms/sort/random_test.cc: Likewise.
+
+2013-10-23 Jason Merrill <jason@redhat.com>
+
+ * include/bits/hashtable.h (_Hashtable): Force EBO for _Hash_code_base.
+
+2013-10-23 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR libstdc++/58850
+ * include/std/chrono (minutes, hours): Change typedefs to uniformly
+ use int64_t.
+ * testsuite/20_util/duration/arithmetic/58850.cc: New.
+
+2013-10-23 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * testsuite/decimal/pr58815.cc: Fix thinko.
+
+2013-10-23 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR libstdc++/58815
+ * include/decimal/decimal (decimal32::operator long long(),
+ decimal64::operator long long(), decimal128::operator long long()):
+ Add in c++11 mode per n3407.
+ * testsuite/decimal/pr58815.cc: New.
+
+2013-10-22 Edward Smith-Rowland <3dw4rd@verizon.net>
+
+ * include/bits/basic_string.h (operator""s): Remove space between quotes
+ and literal identifier.
+ * include/std/chrono (operator""h, operator""min, operator""s,
+ operator""ms, operator""us, operator""ns): Ditto.
+
+2013-10-22 Ed Smith-Rowland <3dw4rd@verizon.net>
+
+ Implement N3779 - User-defined Literals for std::complex,
+ part 2 of UDL for Standard Library Types
+ * include/std/complex: Add complex literal operators.
+ * testsuite/26_numerics/complex/literals/types.cc: New.
+ * testsuite/26_numerics/complex/literals/values.cc: New.
+
+2013-10-21 Edward Smith-Rowland <3dw4rd@verizon.net>
+
+ PR libstdc++/58804
+ PR libstdc++/58729
+ * include/tr2/dynamic_bitset
+ (__dynamic_bitset_base<_WordT, _Alloc>::_M_are_all_aux,
+ __dynamic_bitset_base<_WordT, _Alloc>::_M_do_count):
+ Use __builtin_popcountll() instead of __builtin_popcountl().
+ * include/tr2/dynamic_bitset.tcc
+ (__dynamic_bitset_base<_WordT, _Alloc>::_M_do_find_first,
+ __dynamic_bitset_base<_WordT, _Alloc>::_M_do_find_next):
+ Use __builtin_ctzll() instead of __builtin_ctzl().
+
+2013-10-20 Tim Shen <timshen91@gmail.com>
+
+ * include/bits/regex.h: Remove virtual class _Automaton.
+ * include/bits/regex_automaton.h: Likewise.
+ * include/bits/regex.tcc: Adjust comment for policy changing.
+ * include/bits/regex_executor.h: Update comments of complexity.
+ * include/bits/regex_executor.tcc: Adjust executor choosing
+ policy. Now DFS executor is the default one.
+ * testsuite/util/testsuite_regex.h (regex_match_debug,
+ regex_search_debug): Adjust for policy changing.
+
+2013-10-20 Chris Jefferson <chris@bubblescope.net>
+ Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR libstdc++/58800
+ * include/bits/stl_algo.h (__unguarded_partition_pivot): Change
+ __last - 2 to __last - 1.
+ * testsuite/25_algorithms/nth_element/58800.cc: New
+
+2013-10-18 Edward Smith-Rowland <3dw4rd@verizon.net>
+
+ PR libstdc++/58729
+ * include/tr2/dynamic_bitset (_M_resize, resize): Use input value
+ to set bits; (_M_do_left_shift, _M_do_right_shift, _M_do_to_ulong,
+ _M_do_to_ullong, _M_do_find_first, _M_do_find_next, _M_copy_from_ptr,
+ operator>>): Move long methods outline to...
+ * include/tr2/dynamic_bitset.tcc: New.
+ * include/Makefile.am: Add dynamic_bitset.tcc.
+ * include/Makefile.in: Add dynamic_bitset.tcc.
+ * testsuite/tr2/dynamic_bitset/pr58729.cc: New.
+
+2013-10-18 Tim Shen <timshen91@gmail.com>
+
+ * include/bits/regex_scanner.tcc: (_Scanner<>::_M_scan_normal,
+ _Scanner<>::_M_eat_escape_ecma, _Scanner<>::_M_eat_escape_posix,
+ _Scanner<>::_M_eat_escape_awk): Narrow character before finding in maps.
+ * testsuite/28_regex/algorithms/regex_match/ecma/wchar_t/cjk_match.cc:
+ New.
+
+2013-10-17 Tim Shen <timshen91@gmail.com>
+
+ * include/bits/regex.h (regex_token_iterator<>::regex_token_iterator):
+ Fix initialization orders in initialization list and add explicit braces
+ for potentially ambiguous(actually not) `else` branch to eliminate
+ warnings.
+ * include/bits/regex_automaton.h (_NFA<>::_NFA): Likewise.
+ * include/bits/regex_compiler.h (_CharMatcher<>::_CharMatcher,
+ _BracketMatcher<>::_BracketMatcher): Likewise.
+ * include/bits/regex_compiler.tcc (_Compiler<>::_Compiler,
+ _Compiler<>::_M_atom): Likewise.
+ * include/bits/regex_executor.h (_Executor<>::_Executor): Likewise.
+ * include/bits/regex_executor.tcc (_DFSExecutor<>::_M_dfs,
+ _Executor<>::_M_word_boundry): Likewise.
+ * include/bits/regex_scanner.tcc (_Scanner<>::_Scanner,
+ _Scanner<>::_M_eat_class): Likewise.
+ * include/bits/regex.tcc (__regex_algo_impl<>,
+ regex_iterator<>::operator++): Likewise, and remove unused typedef.
+
+2013-10-16 Tim Shen <timshen91@gmail.com>
+
+ * include/bits/regex.h (regex_token_iterator<>::regex_token_iterator):
+ Add initialization for _M_has_m1.
+ * include/bits/regex.tcc (regex_token_iterator<>::operator=): Add return
+ statment.
+
+2013-10-15 Diego Novillo <dnovillo@google.com>
+
+ * testsuite/20_util/exchange/1.cc: Add missing function
+ bodies.
+
+2013-10-15 Tim Shen <timshen91@gmail.com>
+
+ PR libstdc++/58737
+ * include/bits/regex_automaton.h (_Automaton<>::~_Automaton): Fix memory
+ leak by adding it.
+ * include/bits/regex_executor.h (_Executor<>::~_Executor): Likewise.
+
+2013-10-11 H.J. Lu <hongjiu.lu@intel.com>
+
+ * config/abi/post/x86_64-linux-gnu/x32/baseline_symbols.txt: Update.
+
+2013-10-10 Marcus Shawcroft <marcus.shawcroft@arm.com>
+
+ * testsuite/29_atomics/atomic/cons/49445.cc
+ (dg-require-atomic-builtins): Add.
+
+2013-10-09 Jonathan Wakely <jwakely.gcc@gmail.com>
+
+ * testsuite/20_util/shared_ptr/cons/58659.cc: Use VERIFY instead of
+ aborting.
+
+2013-10-09 Marcus Shawcroft <marcus.shawcroft@arm.com>
+
+ * testsuite/20_util/shared_ptr/cons/58659.cc: Use __builtin_abort().
+
+2013-10-08 Jonathan Wakely <jwakely.gcc@gmail.com>
+
+ * testsuite/*: Remove stray semi-colons after function definitions.
+
+2013-10-08 Jonathan Wakely <jwakely.gcc@gmail.com>
+
+ PR libstdc++/58659
+ * include/bits/shared_ptr_base.h (__shared_count::__shared_count(P,D)):
+ Delegate to constructor taking allocator.
+ (__shared_count::_S_create_from_up): Inline into ...
+ (__shared_count::__shared_count(unique_ptr<Y,D>&&): Here. Use
+ std::conditional instead of constrained overloads. Allocate memory
+ using the allocator type that will be used for deallocation.
+ * testsuite/20_util/shared_ptr/cons/58659.cc: New.
+ * testsuite/20_util/shared_ptr/cons/43820_neg.cc: Adjust.
+
+2013-10-08 Tim Shen <timshen91@gmail.com>
+
+ * include/bits/regex_executor.h: Add _TodoList class.
+ * include/bits/regex_executor.tcc (_BFSExecutor<>::_M_main): Add
+ _M_match_stack and _M_stack to make everything faster. Break if
+ _M_stack is empty, to reduce unnecessary idling.
+ * testsuite/performance/28_regex/split.cc: New.
+
+2013-10-06 Tim Shen <timshen91@gmail.com>
+
+ * include/bits/regex.h: (regex_token_iterator<>::regex_token_iterator):
+ Fix compile error.
+ * include/bits/regex.tcc: (regex_replace<>): Remove default parameter.
+
+2013-10-06 Tim Shen <timshen91@gmail.com>
+
+ * include/bits/regex.h (__regex_algo_impl<>, regex_match<>,
+ regex_search<>): New abstract function for regex_match and regex_search.
+ * include/bits/regex.tcc (__regex_algo_impl<>): Implement.
+ * include/bits/regex_executor.h
+ (_Executor<>::_M_lookahead,
+ _DFSExecutor<>::_M_clone,
+ _BFSExecutor<>::_M_clone): Let _M_clone to choose which executor to
+ use.
+ * include/bits/regex_executor.tcc (__get_executor<>): Update the
+ definition to support __policy.
+ * testsuite/28_regex/algorithms/regex_match/awk/cstring_01.cc: Use
+ *_debug.
+ * testsuite/28_regex/algorithms/regex_match/basic/empty_range.cc: Same.
+ * testsuite/28_regex/algorithms/regex_match/basic/string_01.cc: Same.
+ * testsuite/28_regex/algorithms/regex_match/basic/string_range_00_03.cc:
+ Same.
+ * testsuite/28_regex/algorithms/regex_match/basic/string_range_01_03.cc:
+ Same.
+ * testsuite/28_regex/algorithms/regex_match/basic/string_range_02_03.cc:
+ Same.
+ * testsuite/28_regex/algorithms/regex_match/ecma/char/53622.cc: Same.
+ * testsuite/28_regex/algorithms/regex_match/ecma/char/57173.cc: Same.
+ * testsuite/28_regex/algorithms/regex_match/ecma/char/58576.cc: Same.
+ * testsuite/28_regex/algorithms/regex_match/ecma/char/anymatcher.cc:
+ Same.
+ * testsuite/28_regex/algorithms/regex_match/ecma/char/backref.cc: Same.
+ * testsuite/28_regex/algorithms/regex_match/ecma/char/empty_range.cc:
+ Same.
+ * testsuite/28_regex/algorithms/regex_match/ecma/char/emptygroup.cc:
+ Same.
+ * testsuite/28_regex/algorithms/regex_match/ecma/char/hex.cc: Same.
+ * testsuite/28_regex/algorithms/regex_match/ecma/char/quoted_char.cc:
+ Same.
+ * testsuite/28_regex/algorithms/regex_match/ecma/wchar_t/anymatcher.cc:
+ Same.
+ * testsuite/28_regex/algorithms/regex_match/ecma/wchar_t/hex.cc: Same.
+ * testsuite/28_regex/algorithms/regex_match/extended/
+ string_bracket_01.cc: Same.
+ * testsuite/28_regex/algorithms/regex_match/extended/cstring_plus.cc:
+ Same.
+ * testsuite/28_regex/algorithms/regex_match/extended/
+ string_questionmark.cc: Same.
+ * testsuite/28_regex/algorithms/regex_match/extended/cstring_range.cc:
+ Same.
+ * testsuite/28_regex/algorithms/regex_match/extended/string_any.cc:
+ Same.
+ * testsuite/28_regex/algorithms/regex_match/extended/
+ string_dispatch_01.cc: Same.
+ * testsuite/28_regex/algorithms/regex_match/extended/
+ string_range_00_03.cc: Same.
+ * testsuite/28_regex/algorithms/regex_match/extended/
+ string_range_01_03.cc: Same.
+ * testsuite/28_regex/algorithms/regex_match/extended/
+ string_range_02_03.cc: Same.
+ * testsuite/28_regex/algorithms/regex_match/extended/wstring_locale.cc:
+ Same.
+ * testsuite/28_regex/algorithms/regex_search/basic/string_01.cc: Same.
+ * testsuite/28_regex/algorithms/regex_search/ecma/assertion.cc: Same.
+ * testsuite/28_regex/algorithms/regex_search/ecma/flags.cc: Same.
+ * testsuite/28_regex/algorithms/regex_search/ecma/greedy.cc: Same.
+ * testsuite/28_regex/algorithms/regex_search/ecma/string_01.cc: Same.
+ * testsuite/28_regex/match_results/format.cc: Same.
+ * testsuite/util/testsuite_regex.h
+ (regex_match_debug<>, regex_search_debug<>): Implement.
+
+2013-10-06 Oleg Endo <olegendo@gcc.gnu.org>
+ Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR libstdc++/58625
+ * include/c_global/cmath (signbit): Use __builtin_signbitf and
+ __builtin_signbitl.
+
+2013-10-03 Tim Shen <timshen91@gmail.com>
+
+ * include/bits/regex_executor.tcc (_DFSExecutor<>::_M_dfs): Fix wrong
+ backup variable initialization.
+
+2013-10-03 John Woolverton <jdwoolverton@gmail.com>
+
+ PR libstdc++/58604
+ * include/std/vector: Fix garbled line in HP Copyright.
+
+2013-10-03 Marc Glisse <marc.glisse@inria.fr>
+
+ * libsupc++/del_op.cc (operator delete): Don't test for 0 before free.
+ * libsupc++/del_opnt.cc (free): Only declare if freestanding.
+ (operator delete): Qualify free with std::.
+
+2013-10-02 Jonathan Wakely <jwakely.gcc@gmail.com>
+ Daniel Krugler <daniel.kruegler@gmail.com>
+
+ PR libstdc++/58569
+ * include/std/functional (function::_CheckResult): Move to namespace
+ scope and rename to __check_func_return_type.
+ * testsuite/20_util/function/58569.cc: New.
+
+2013-10-02 Jonathan Wakely <jwakely.gcc@gmail.com>
+
+ PR libstdc++/58594
+ * include/bits/shared_ptr_base.h
+ (_Sp_counted_ptr_inplace::_M_get_deleter()): Cast away cv-quals.
+ * testsuite/20_util/shared_ptr/creation/58594.cc: New.
+
+2013-10-02 Tim Shen <timshen91@gmail.com>
+
+ * include/bits/regex_compiler.h
+ (_BracketMatcher<>::_M_add_equivalence_class): Implement it correctly.
+ * include/bits/regex_compiler.tcc (_BracketMatcher<>::operator()):
+ Add _M_equiv_set support.
+ * testsuite/28_regex/algorithms/regex_match/extended/
+ cstring_bracket_01.cc: Add new "[[=a=]]" testcase.
+
+2013-10-01 Tim Shen <timshen91@gmail.com>
+
+ * doc/xml/manual/status_cxx2011.xml: Change "is not implemented" to
+ "is not correctly implemented".
+
+2013-10-01 Tim Shen <timshen91@gmail.com>
+
+ * doc/xml/manual/status_cxx2011.xml: Update regex status.
+ * include/bits/regex.h (match_results<>::begin,
+ match_results<>::cbegin, match_results<>::end, match_results<>::cend):
+ [28.10.3.13], [28.10.3.14] Always iterate the range [0, size()-2).
+
+2013-10-01 François Dumont <fdumont@gcc.gnu.org>
+
+ * include/parallel/algobase.h (mismatch, equal): Provide parallel
+ version for N3671 overloads.
+
+2013-10-01 Paul Pluzhnikov <ppluzhnikov@google.com>
+
+ * src/c++11/snprintf_lite.cc: Add missing
+ _GLIBCXX_{BEGIN,END}_NAMESPACE_VERSION
+
+2013-10-01 Joern Rennecke <joern.rennecke@embecosm.com>
+
+ * acinclude.m4 (GLIBCXX_ENABLE_SJLJ_EXCEPTIONS): Also check for
+ _Unwind_SjLj_Register when deciding if to set enable_sjlj_exceptions.
+ * configure: Regenerate.
+
+2013-10-01 Tim Shen <timshen91@gmail.com>
+
+ PR libstdc++/58576
+ * include/bits/regex_automaton.tcc (_NFA<>::_M_eliminate_dummy)
+ (_StateSeq<>::_M_clone): Add _S_opcode_subexpr_lookahead branch.
+ * testsuite/28_regex/algorithms/regex_match/ecma/char/58576.cc: New.
+
+2013-09-30 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * include/parallel/algo.h (__find_switch): Use __binder2nd.
+
+2013-09-30 Chris Jefferson <chris@bubblescope.net>
+
+ PR libstdc++/58437
+ * include/bits/stl_algo.h (__move_median_first): Rename to
+ __move_median_to_first, change to take an addition argument.
+ (__unguarded_partition_pivot): Adjust.
+ * testsuite/performance/25_algorithms/sort.cc: New.
+ * testsuite/performance/25_algorithms/sort_heap.cc: Likewise.
+ * testsuite/performance/25_algorithms/stable_sort.cc: Likewise.
+
+2013-09-28 François Dumont <fdumont@gcc.gnu.org>
+
+ * include/bits/stl_algo.h (remove_copy, remove_copy_if): Declare
+ inline.
+ (rotate_copy, stable_partition, partial_sort_copy): Likewise.
+ (lower_bound, upper_bound, equal_range, inplace_merge): Likewise.
+ (includes, next_permutation, prev_permutation): Likewise.
+ (replace_copy, replace_copy_if, is_sorted_until): Likewise.
+ (minmax_element, is_permutation, adjacent_find): Likewise.
+ (count, count_if, search, search_n, merge): Likewise.
+ (set_intersection, set_difference): Likewise.
+ (set_symmetric_difference, min_element, max_element): Likewise.
+ * include/bits/stl_algobase.h (lower_bound): Likewise.
+ (lexicographical_compare, mismatch): Likewise.
+
+2013-09-28 Tim Shen <timshen91@gmail.com>
+
+ * include/bits/regex_scanner.tcc (_Scanner<>::_M_eat_escape_posix):
+ Let ordinary char escaping in POSIX be valid.
+ * testsuite/28_regex/basic_regex/ctors/basic/raw_string.cc: Test this
+ change.
+
+2013-09-27 François Dumont <fdumont@gcc.gnu.org>
+
+ * include/bits/predefined_ops.h: New.
+ * include/bits/stl_heap.h: Include <bits/predefined_ops.h>.
+ (__is_heap_until, __push_heap, __adjust_heap, __pop_heap): Remove
+ algo duplication.
+ (__is_heap): Adapt.
+ (__make_heap): New.
+ (make_heap): Adapt to use latter.
+ (__sort_heap): New.
+ (sort_heap): Adapt to use latter.
+ * include/bits/algobase.h: Include <bits/predefined_ops.h>.
+ (__lexicographical_compare_impl): New.
+ (__lexicographical_compare<false>::__lc): Adapt to use latter.
+ (lexicographical_compare): Likewise.
+ (__lower_bound): New.
+ (lower_bound): Adapt to use latter.
+ (equal): Use _GLIBCXX_STD_A::equal in N3671 overloads.
+ (__mismatch): New.
+ (mismatch): Use latter.
+ * include/bits/algo.h: Include <bits/predefined_ops.h>. Remove
+ <functional> include.
+ (__move_median_first, __find, __find_if, __find_if_not): Remove
+ algo duplication.
+ (__find_end): Likewise.
+ (__search_n): Rename into ...
+ (__search_n_aux): ... this.
+ (__search_n): Renew, use latter.
+ (search_n): Use latter.
+ (__search): New.
+ (search): Use latter.
+ (__find_end): Likewise.
+ (__remove_copy_if): New.
+ (remove_copy): Use latter.
+ (__adjacent_find): New.
+ (adjacent_find): Use latter.
+ (__unique): New.
+ (unique): Use latter.
+ (__unique_copy): Remove algo duplication.
+ (__stable_partition): New.
+ (stable_partition): Use latter.
+ (__heap_select): Remove algo duplication, use __make_heap.
+ (__partial_sort): New, use latter.
+ (partial_sort): Use latter.
+ (__partial_sort_copy): New.
+ (partial_sort_copy): Use latter.
+ (__unguarded_linear_insert, __insertion_sort): Remove algo
+ duplication.
+ (__unguarded_insertion_sort, __final_insertion_sort): Likewise.
+ (__unguarded_partition, __unguarded_partition_pivot): Likewise.
+ (__partial_sort): New.
+ (partial_sort): Use latter.
+ (__sort): New.
+ (sort): Use latter.
+ (lower_bound): Use __lower_bound.
+ (__upper_bound): New.
+ (upper_bound): Use latter.
+ (__equal_range): New.
+ (equal_range): Use latter.
+ (__move_merge_adaptive, __move_merge_adaptive_backward): Remove
+ algo duplication.
+ (__merge_adaptive, __merge_without_buffer): Likewise.
+ (__inplace_merge): New.
+ (inplace_merge): Use latter.
+ (__move_merge, __merge_sort_loop, __chunk_insertion_sort): Remove
+ algo duplication.
+ (__merge_sort_with_buffer, __stable_sort_adaptive): Likewise.
+ (__inplace_stable_sort): Likewise.
+ (__include): New.
+ (includes): Use latter.
+ (__next_permutation): New.
+ (next_permutation): Use latter.
+ (__prev_permutation): New.
+ (prev_permutation): Use latter.
+ (__replace_copy_if): New.
+ (replace_copy): Use latter.
+ (__is_sorted_until): New.
+ (is_sorted_unitl): Use latter.
+ (__minmax_element): New.
+ (minmax_element): Use latter.
+ (__is_permutation): New.
+ (is_permutation): Use latter.
+ (__adjacent_find): New.
+ (adjacent_find): Use latter.
+ (__count_if): New.
+ (count): Use latter.
+ (count_if): Likewise.
+ (__merge): New.
+ (merge): Use latter.
+ (__stable_sort): New.
+ (stable_sort): Use latter.
+ (__set_union): New.
+ (set_union): Use latter.
+ (__set_intersection): New.
+ (set_intersection): Use latter.
+ (__set_difference): New.
+ (set_difference): Use latter.
+ (__set_symmetric_difference): New.
+ (set_symmetric_difference): Use latter.
+ (__min_element): New.
+ (min_element): Use latter.
+ (__max_element): New.
+ (max_element): Use latter.
+ * include/Makefile.am: Add predefined_ops.h.
+ * include/Makefile.in: Regenerate.
+ * include/parallel/algobase.h (equal, mismatch): Add overloads
+ from N3671.
+ * testsuite/25_algorithms/is_permutation/vectorbool.cc: New.
+ * testsuite/25_algorithms/adjacent_find/vectorbool.cc: Likewise.
+ * testsuite/25_algorithms/find/vectorbool.cc: Likewise.
+ * testsuite/25_algorithms/find_if/vectorbool.cc: Likewise.
+ * testsuite/25_algorithms/find_first_of/vectorbool.cc: Likewise.
+ * testsuite/25_algorithms/heap/vectorbool.cc: Likewise.
+ * testsuite/25_algorithms/find_end/vectorbool.cc: Likewise.
+ * testsuite/25_algorithms/find_if_not/vectorbool.cc: Likewise.
+
+2013-09-27 Jonathan Wakely <jwakely.gcc@gmail.com>
+
+ PR libstdc++/57465
+ * include/std/functional
+ (_Function_base::_Base_manager::_M_not_empty_function): Fix overload
+ for pointers.
+ * testsuite/20_util/function/cons/57465.cc: New.
+
+2013-09-26 Tim Shen <timshen91@gmail.com>
+
+ * regex_error.h: Remove _S_error_last to follow the standard.
+ * regex_scanner.tcc:
+ (_Scanner<_FwdIter>::_M_scan_in_brace): Change error_brace to
+ error_badbrace.
+ (_Scanner<>::_M_eat_escape_posix): Extended doesn't support
+ back-reference.
+ * testsuite/28_regex/algorithms/regex_match/ecma/char/53622.cc:
+ Move here from ../../extended.
+ * testsuite/28_regex/algorithms/regex_match/ecma/char/57173.cc:
+ Likewise.
+
+2013-09-25 Marc Glisse <marc.glisse@inria.fr>
+
+ PR libstdc++/58338
+ * include/bits/forward_list.h (_Fwd_list_node_base::_M_transfer_after):
+ Mark as noexcept.
+ (_Fwd_list_iterator) [_Fwd_list_iterator, operator*, operator->,
+ operator++, operator==, operator!=, _M_next]: Likewise.
+ (_Fwd_list_const_iterator) [_Fwd_list_const_iterator, operator*,
+ operator->, operator++, operator==, operator!=, _M_next]: Likewise.
+ (operator==(const _Fwd_list_iterator&, const _Fwd_list_const_iterator&),
+ operator!=(const _Fwd_list_iterator&, const _Fwd_list_const_iterator&)):
+ Likewise.
+ * include/bits/hashtable_policy.h (_Hash_node_base::_Hash_node_base,
+ _Hash_node::_M_next, _Node_iterator_base::_Node_iterator_base,
+ _Node_iterator_base::_M_incr, operator==(const _Node_iterator_base&,
+ const _Node_iterator_base&), operator!=(const _Node_iterator_base&,
+ const _Node_iterator_base&)): Likewise.
+ (_Node_iterator) [_Node_iterator, operator*, operator->, operator++]:
+ Likewise.
+ (_Node_const_iterator) [_Node_const_iterator, operator*, operator->,
+ operator++]: Likewise.
+ * include/debug/safe_iterator.h (_Safe_iterator) [_Safe_iterator,
+ operator=, operator*, operator->, operator++, operator--, operator[],
+ operator+=, operator+, operator-=, operator-, base, operator _Iterator]:
+ Likewise.
+ (operator==(const _Safe_iterator&, const _Safe_iterator&),
+ operator!=(const _Safe_iterator&, const _Safe_iterator&),
+ operator<(const _Safe_iterator&, const _Safe_iterator&),
+ operator<=(const _Safe_iterator&, const _Safe_iterator&),
+ operator>(const _Safe_iterator&, const _Safe_iterator&),
+ operator>=(const _Safe_iterator&, const _Safe_iterator&),
+ operator-(const _Safe_iterator&, const _Safe_iterator&),
+ operator+(difference_type, const _Safe_iterator&)): Likewise.
+ * include/profile/iterator_tracker.h (__iterator_tracker)
+ [__iterator_tracker, base, operator _Iterator, operator->, operator++,
+ operator--, operator=, operator*, operator[], operator+=, operator+,
+ operator-=, operator-]: Likewise.
+ (operator==(const __iterator_tracker&, const __iterator_tracker&),
+ operator!=(const __iterator_tracker&, const __iterator_tracker&),
+ operator<(const __iterator_tracker&, const __iterator_tracker&),
+ operator<=(const __iterator_tracker&, const __iterator_tracker&),
+ operator>(const __iterator_tracker&, const __iterator_tracker&),
+ operator>=(const __iterator_tracker&, const __iterator_tracker&),
+ operator-(const __iterator_tracker&, const __iterator_tracker&),
+ operator+(difference_type, const __iterator_tracker&)): Likewise.
+
+2013-09-24 Marc Glisse <marc.glisse@inria.fr>
+
+ PR libstdc++/58338
+ PR libstdc++/56166
+ * include/bits/basic_string.h (basic_string)
+ [basic_string(basic_string&&)]: Make the noexcept conditional.
+ [operator=(basic_string&&), assign(basic_string&&)]: Link to PR 58265.
+ [begin(), end(), rbegin(), rend(), clear]: Remove noexcept.
+ [pop_back]: Comment on the lack of noexcept.
+ * include/debug/string (basic_string) [basic_string(const _Allocator&),
+ basic_string(basic_string&&), begin(), end(), rbegin(), rend(), clear,
+ operator[](size_type), pop_back]: Comment out noexcept, until vstring
+ replaces basic_string.
+
+2013-09-24 Tim Shen <timshen91@gmail.com>
+
+ * include/Makefile.am: Add regex.tcc.
+ * include/Makefile.in: Regenerate.
+ * include/bits/regex.h: Remove definitions to regex.tcc.
+ * include/bits/regex.tcc: New.
+ (match_results::format, regex_replace): Implement;
+ * include/bits/regex_compiler.h: Move _M_flags to the top of class
+ member list, because other members' initialization depend on it.
+ * include/bits/regex_compiler.tcc
+ (_Compiler<>::_Compiler): Adjust member initializations.
+ (_Compiler<>::_M_quantifier): Fix ungreedy interval quantifier.
+ * include/bits/regex_executor.h: Remove _RegexT from _*Executor classes.
+ In the future, all regex classes may refactor to *Impl style.
+ * include/bits/regex_executor.tcc (_Executor::_M_set_results):
+ Merge identical code from _*Executor classes.
+ * testsuite/28_regex/algorithms/regex_match/extended/
+ string_dispatch_01.cc (fake_match<>): Adjust the hacking-style testcase
+ caller for new __get_executors interface.
+ * testsuite/28_regex/algorithms/regex_replace/char/basic_replace.cc:
+ New.
+ * testsuite/28_regex/match_results/format.cc: New.
+ * testsuite/28_regex/traits/char/lookup_collatename.cc: Remove digraph
+ testcase.
+ * testsuite/28_regex/traits/wchar_t/lookup_collatename.cc: Likewise.
+
+2013-09-23 Paul Pluzhnikov <ppluzhnikov@google.com>
+
+ * src/c++11/snprintf_lite.cc (__concat_size_t): Use
+ unsigned long long conditionally.
+
+2013-09-23 Paul Pluzhnikov <ppluzhnikov@google.com>
+
+ * src/c++11/snprintf_lite.cc (__concat_size_t): Use only
+ std::__int_to_char<unsigned long long>()
+
+2013-09-21 Paul Pluzhnikov <ppluzhnikov@google.com>
+
+ * include/bits/functexcept.h (__throw_out_of_range_fmt): New.
+ * src/c++11/functexcept.cc (__throw_out_of_range_fmt): New.
+ * src/c++11/snprintf_lite.cc: New.
+ * src/c++11/Makefile.am: Add snprintf_lite.cc.
+ * src/c++11/Makefile.in: Regenerate.
+ * config/abi/pre/gnu.ver: Add _ZSt24__throw_out_of_range_fmtPKcz.
+ * include/std/array (at): Use __throw_out_of_range_fmt.
+ * include/debug/array (at): Likewise.
+ * include/profile/array (at): Likewise.
+ * include/std/bitset (_M_check_initial_position, _M_check): New.
+ (bitset::bitset): Use _M_check_initial_position.
+ (set, reset, flip, test): Use _M_check.
+ * include/ext/vstring.h (_M_check, at): Use __throw_out_of_range_fmt.
+ * include/bits/stl_vector.h (_M_range_check): Likewise.
+ * include/bits/stl_bvector.h (_M_range_check): Likewise.
+ * include/bits/stl_deque.h (_M_range_check): Likewise.
+ * include/bits/basic_string.h (_M_check, at): Likewise.
+ * testsuite/23_containers/vector/requirements/dr438/assign_neg.cc: Adjust.
+ * testsuite/23_containers/vector/requirements/dr438/insert_neg.cc: Likewise.
+ * testsuite/23_containers/vector/requirements/dr438/constructor_1_neg.cc:
+ Likewise.
+ * testsuite/23_containers/vector/requirements/dr438/constructor_2_neg.cc:
+ Likewise.
+ * testsuite/23_containers/deque/requirements/dr438/assign_neg.cc: Likewise.
+ * testsuite/23_containers/deque/requirements/dr438/insert_neg.cc: Likewise.
+ * testsuite/23_containers/deque/requirements/dr438/constructor_1_neg.cc:
+ Likewise.
+ * testsuite/23_containers/deque/requirements/dr438/constructor_2_neg.cc:
+ Likewise.
+ * testsuite/23_containers/array/tuple_interface/tuple_element_neg.cc: Likewise.
+ * testsuite/23_containers/array/tuple_interface/tuple_element_debug_neg.cc:
+ Likewise.
+ * testsuite/23_containers/array/tuple_interface/get_neg.cc: Likewise.
+ * testsuite/23_containers/array/tuple_interface/get_debug_neg.cc: Likewise.
+ * testsuite/util/exception/safety.h (generate): Use __throw_out_of_range_fmt.
+
+2013-09-20 Jakub Jelinek <jakub@redhat.com>
+
+ PR testsuite/57605
+ * testsuite/lib/libstdc++.exp (libstdc++_init): Prepend
+ -fdiagnostics-color=never to cxxflags.
+
+2013-09-20 Marc Glisse <marc.glisse@inria.fr>
+
+ PR libstdc++/58338
+ * include/bits/allocator.h (__alloc_swap::_S_do_it,
+ __shrink_to_fit_aux::_S_do_it): Mark as noexcept.
+ * include/bits/basic_string.h (basic_string::_Rep) [_S_empty_rep,
+ _M_is_leaked, _M_is_shared, _M_set_leaked, _M_set_sharable,
+ _M_set_length_and_sharable, _M_dispose]: Likewise.
+ (basic_string::_Alloc_hider::_Alloc_hider): Likewise.
+ (basic_string) [_M_data, _M_rep, _M_ibegin, _M_iend, _M_limit,
+ _M_disjunct, _M_copy, _M_move, _M_assign, _S_copy_chars, _S_compare,
+ _S_empty_rep, shrink_to_fit, operator[] const, front const, back const]:
+ Likewise.
+ [clear]: Link to PR 56166.
+ [swap]: Link to PR 58265.
+ * include/bits/stl_deque.h (_Deque_iterator) [_S_buffer_size,
+ _Deque_iterator, _M_const_cast, operator*, operator->, operator++,
+ operator--, operator+=, operator+, operator-=, operator-, operator[],
+ _M_set_node]: Mark as noexcept.
+ (operator==(const _Deque_iterator&, const _Deque_iterator&),
+ operator!=(const _Deque_iterator&, const _Deque_iterator&),
+ operator<(const _Deque_iterator&, const _Deque_iterator&),
+ operator>(const _Deque_iterator&, const _Deque_iterator&),
+ operator<=(const _Deque_iterator&, const _Deque_iterator&),
+ operator>=(const _Deque_iterator&, const _Deque_iterator&),
+ operator-(const _Deque_iterator&, const _Deque_iterator&),
+ operator+(ptrdiff_t, const _Deque_iterator&)): Likewise.
+ (_Deque_base) [_Deque_base(const allocator_type&)]: Add missing call to
+ _M_initialize_map.
+ [~_Deque_base, _M_deallocate_node, _M_deallocate_map, _M_destroy_nodes]:
+ Mark as noexcept.
+ (_Deque_base::_Deque_impl) [_Deque_impl(const _Tp_alloc_type&),
+ _Deque_impl(_Tp_alloc_type&&)]: Likewise.
+ (deque) [_S_buffer_size, operator=(deque&&), shrink_to_fit, operator[],
+ front, back, pop_front, pop_back, swap]: Likewise.
+ [deque(), deque(const allocator_type&)]: Merge.
+ * include/debug/deque (deque) [operator=(deque&&), shrink_to_fit,
+ operator[], front, back, pop_front, pop_back, swap]: Mark as noexcept.
+ * include/profile/deque (deque) [operator=(deque&&), operator[], front,
+ back, pop_front, pop_back, swap]: Likewise.
+ * testsuite/23_containers/deque/requirements/dr438/assign_neg.cc:
+ Adjust line number.
+ * testsuite/23_containers/deque/requirements/dr438/constructor_1_neg.cc:
+ Likewise.
+ * testsuite/23_containers/deque/requirements/dr438/constructor_2_neg.cc:
+ Likewise.
+ * testsuite/23_containers/deque/requirements/dr438/insert_neg.cc:
+ Likewise.
+
+2013-09-20 Alan Modra <amodra@gmail.com>
+
+ * configure: Regenerate.
+
2013-09-19 Marc Glisse <marc.glisse@inria.fr>
PR libstdc++/58338
@@ -255,23 +1274,23 @@
* regex_automaton.h: Rearrange _NFA's layout.
* include/bits/regex_compiler.h: Add _AnyMatcher and _CharMatcher.
- Rearrange _BracketMatcher's layout.
- (_BracketMatcher<>::_M_add_char): Use set instead of vector for
- _M_char_set.
- (_BracketMatcher<>::_M_add_collating_element): Likewise.
- (_BracketMatcher<>::_M_make_range): Likewise.
+ Rearrange _BracketMatcher's layout.
+ (_BracketMatcher<>::_M_add_char): Use set instead of vector for
+ _M_char_set.
+ (_BracketMatcher<>::_M_add_collating_element): Likewise.
+ (_BracketMatcher<>::_M_make_range): Likewise.
* include/bits/regex_compiler.tcc (_Compiler<>::_M_atom): Use
- apropriate constructors of matchers above.
+ appropriate constructors of matchers above.
* testsuite/28_regex/algorithms/regex_match/ecma/char/anymatcher.cc:
- New.
+ New.
* testsuite/28_regex/algorithms/regex_match/ecma/char/backref.cc: New.
* testsuite/28_regex/algorithms/regex_match/ecma/char/empty_range.cc:
- New.
+ New.
* testsuite/28_regex/algorithms/regex_match/ecma/char/emptygroup.cc:
- New.
+ New.
* testsuite/28_regex/algorithms/regex_match/ecma/char/hex.cc: New.
* testsuite/28_regex/algorithms/regex_match/ecma/wchar_t/anymatcher.cc:
- New.
+ New.
* testsuite/28_regex/algorithms/regex_match/ecma/wchar_t/hex.cc: New.
2013-08-30 François Dumont <fdumont@gcc.gnu.org>
@@ -304,33 +1323,33 @@
2013-08-29 Tim Shen <timshen91@gmail.com>
* include/bits/regex.h (basic_regex<>::assign): Don't lose _M_traits.
- (regex_iterator<>::regex_iterator): Return nullptr when regex_search
- failed.
- (regex_token_iterator<>::_M_end_of_seq): Should be defined true when
- _M_result is(not isn't) nullptr.
+ (regex_iterator<>::regex_iterator): Return nullptr when regex_search
+ failed.
+ (regex_token_iterator<>::_M_end_of_seq): Should be defined true when
+ _M_result is(not isn't) nullptr.
* include/bits/regex_compiler.h: Store _Compiler::_M_traits by reference
- instead of by value.
+ instead of by value.
* include/bits/regex_executor.h (_DFSExecutor<>::_DFSExecutor): Add
- _M_traits to _DFSExecutor.
+ _M_traits to _DFSExecutor.
* include/bits/regex_executor.tcc (__get_executor<>): Pass traits to
- _DFSExecutor too.
+ _DFSExecutor too.
* testsuite/28_regex/algorithms/regex_match/extended/wstring_locale.cc:
- New.
+ New.
* testsuite/28_regex/iterators/regex_token_iterator/wchar_t/
- wstring_02.cc: New.
+ wstring_02.cc: New.
2013-08-26 Tim Shen <timshen91@gmail.com>
* include/Makefile.am: Add regex_scanner.{h,tcc}.
* include/Makefile.in: Regenerate.
* include/bits/regex.h (match_search): Handle the `__first == __last`
- situation correctly.
+ situation correctly.
* include/bits/regex_compiler.h: Move _Scanner...
* include/bits/regex_scanner.h: ...to here. New.
* include/bits/regex_compiler.tcc: Move _Scanner...
* include/bits/regex_scanner.tcc: ...to here, too. New.
* include/bits/regex_executor.tcc: Use value instead of reference for
- submatch.
+ submatch.
* include/std/regex: Add regex_scanner.h
* testsuite/28_regex/algorithms/regex_match/awk/cstring_01.cc: New.
* testsuite/28_regex/algorithms/regex_match/basic/empty_range.cc: New.
@@ -1924,7 +2943,7 @@
* config/abi/pre/gnu.ver: Add new symbols.
* config/abi/pre/gnu-versioned-namespace.ver: Add new symbols.
-2013-05-08 Andoni Morales Alastruey <ylatuya@gmail.com>
+2013-05-08 Andoni Morales Alastruey <ylatuya@gmail.com>
PR libstdc++/57212
* include/Makefile.am (_GLIBCXX___MINGW32_GLIBCXX___): Modify
diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4
index 72b90a80252..f9d12d0cd31 100644
--- a/libstdc++-v3/acinclude.m4
+++ b/libstdc++-v3/acinclude.m4
@@ -3139,6 +3139,8 @@ EOF
if AC_TRY_EVAL(ac_compile); then
if grep _Unwind_SjLj_Resume conftest.s >/dev/null 2>&1 ; then
enable_sjlj_exceptions=yes
+ elif grep _Unwind_SjLj_Register conftest.s >/dev/null 2>&1 ; then
+ enable_sjlj_exceptions=yes
elif grep _Unwind_Resume conftest.s >/dev/null 2>&1 ; then
enable_sjlj_exceptions=no
elif grep __cxa_end_cleanup conftest.s >/dev/null 2>&1 ; then
diff --git a/libstdc++-v3/config/abi/post/x86_64-linux-gnu/x32/baseline_symbols.txt b/libstdc++-v3/config/abi/post/x86_64-linux-gnu/x32/baseline_symbols.txt
index 551e738a57c..2c822bf943a 100644
--- a/libstdc++-v3/config/abi/post/x86_64-linux-gnu/x32/baseline_symbols.txt
+++ b/libstdc++-v3/config/abi/post/x86_64-linux-gnu/x32/baseline_symbols.txt
@@ -403,6 +403,7 @@ FUNC:_ZNKSt15basic_streambufIwSt11char_traitsIwEE5pbaseEv@@GLIBCXX_3.4
FUNC:_ZNKSt15basic_streambufIwSt11char_traitsIwEE6getlocEv@@GLIBCXX_3.4
FUNC:_ZNKSt15basic_stringbufIcSt11char_traitsIcESaIcEE3strEv@@GLIBCXX_3.4
FUNC:_ZNKSt15basic_stringbufIwSt11char_traitsIwESaIwEE3strEv@@GLIBCXX_3.4
+FUNC:_ZNKSt17bad_function_call4whatEv@@GLIBCXX_3.4.18
FUNC:_ZNKSt18basic_stringstreamIcSt11char_traitsIcESaIcEE3strEv@@GLIBCXX_3.4
FUNC:_ZNKSt18basic_stringstreamIcSt11char_traitsIcESaIcEE5rdbufEv@@GLIBCXX_3.4
FUNC:_ZNKSt18basic_stringstreamIwSt11char_traitsIwESaIwEE3strEv@@GLIBCXX_3.4
@@ -590,6 +591,8 @@ FUNC:_ZNKSt7num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE6do_putES3_RSt
FUNC:_ZNKSt7num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE6do_putES3_RSt8ios_basewm@@GLIBCXX_3.4
FUNC:_ZNKSt7num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE6do_putES3_RSt8ios_basewx@@GLIBCXX_3.4
FUNC:_ZNKSt7num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE6do_putES3_RSt8ios_basewy@@GLIBCXX_3.4
+FUNC:_ZNKSt8__detail20_Prime_rehash_policy11_M_next_bktEj@@GLIBCXX_3.4.18
+FUNC:_ZNKSt8__detail20_Prime_rehash_policy14_M_need_rehashEjjj@@GLIBCXX_3.4.18
FUNC:_ZNKSt8bad_cast4whatEv@@GLIBCXX_3.4.9
FUNC:_ZNKSt8ios_base7failure4whatEv@@GLIBCXX_3.4
FUNC:_ZNKSt8messagesIcE18_M_convert_to_charERKSs@@GLIBCXX_3.4
@@ -1207,6 +1210,7 @@ FUNC:_ZNSt11range_errorD2Ev@@GLIBCXX_3.4.15
FUNC:_ZNSt11regex_errorD0Ev@@GLIBCXX_3.4.15
FUNC:_ZNSt11regex_errorD1Ev@@GLIBCXX_3.4.15
FUNC:_ZNSt11regex_errorD2Ev@@GLIBCXX_3.4.15
+FUNC:_ZNSt11this_thread11__sleep_forENSt6chrono8durationIxSt5ratioILx1ELx1EEEENS1_IxS2_ILx1ELx1000000000EEEE@@GLIBCXX_3.4.18
FUNC:_ZNSt12__basic_fileIcE2fdEv@@GLIBCXX_3.4
FUNC:_ZNSt12__basic_fileIcE4fileEv@@GLIBCXX_3.4.1
FUNC:_ZNSt12__basic_fileIcE4openEPKcSt13_Ios_Openmodei@@GLIBCXX_3.4
@@ -1485,6 +1489,11 @@ FUNC:_ZNSt13basic_ostreamIwSt11char_traitsIwEElsEs@@GLIBCXX_3.4
FUNC:_ZNSt13basic_ostreamIwSt11char_traitsIwEElsEt@@GLIBCXX_3.4
FUNC:_ZNSt13basic_ostreamIwSt11char_traitsIwEElsEx@@GLIBCXX_3.4
FUNC:_ZNSt13basic_ostreamIwSt11char_traitsIwEElsEy@@GLIBCXX_3.4
+FUNC:_ZNSt13random_device14_M_init_pretr1ERKSs@@GLIBCXX_3.4.18
+FUNC:_ZNSt13random_device16_M_getval_pretr1Ev@@GLIBCXX_3.4.18
+FUNC:_ZNSt13random_device7_M_finiEv@@GLIBCXX_3.4.18
+FUNC:_ZNSt13random_device7_M_initERKSs@@GLIBCXX_3.4.18
+FUNC:_ZNSt13random_device9_M_getvalEv@@GLIBCXX_3.4.18
FUNC:_ZNSt13runtime_errorC1ERKSs@@GLIBCXX_3.4
FUNC:_ZNSt13runtime_errorC2ERKSs@@GLIBCXX_3.4
FUNC:_ZNSt13runtime_errorD0Ev@@GLIBCXX_3.4
@@ -1929,6 +1938,8 @@ FUNC:_ZNSt6__norm15_List_node_base7reverseEv@@GLIBCXX_3.4.9
FUNC:_ZNSt6__norm15_List_node_base8transferEPS0_S1_@@GLIBCXX_3.4.9
FUNC:_ZNSt6__norm15_List_node_base9_M_unhookEv@@GLIBCXX_3.4.14
FUNC:_ZNSt6chrono12system_clock3nowEv@@GLIBCXX_3.4.11
+FUNC:_ZNSt6chrono3_V212steady_clock3nowEv@@GLIBCXX_3.4.19
+FUNC:_ZNSt6chrono3_V212system_clock3nowEv@@GLIBCXX_3.4.19
FUNC:_ZNSt6gslice8_IndexerC1EjRKSt8valarrayIjES4_@@GLIBCXX_3.4
FUNC:_ZNSt6gslice8_IndexerC2EjRKSt8valarrayIjES4_@@GLIBCXX_3.4
FUNC:_ZNSt6locale11_M_coalesceERKS_S1_i@@GLIBCXX_3.4
@@ -2467,6 +2478,7 @@ FUNC:__cxa_guard_acquire@@CXXABI_1.3
FUNC:__cxa_guard_release@@CXXABI_1.3
FUNC:__cxa_pure_virtual@@CXXABI_1.3
FUNC:__cxa_rethrow@@CXXABI_1.3
+FUNC:__cxa_thread_atexit@@CXXABI_1.3.7
FUNC:__cxa_throw@@CXXABI_1.3
FUNC:__cxa_tm_cleanup@@CXXABI_TM_1
FUNC:__cxa_vec_cctor@@CXXABI_1.3
@@ -2491,6 +2503,7 @@ OBJECT:0:CXXABI_1.3.3
OBJECT:0:CXXABI_1.3.4
OBJECT:0:CXXABI_1.3.5
OBJECT:0:CXXABI_1.3.6
+OBJECT:0:CXXABI_1.3.7
OBJECT:0:CXXABI_TM_1
OBJECT:0:GLIBCXX_3.4
OBJECT:0:GLIBCXX_3.4.1
@@ -2502,6 +2515,8 @@ OBJECT:0:GLIBCXX_3.4.14
OBJECT:0:GLIBCXX_3.4.15
OBJECT:0:GLIBCXX_3.4.16
OBJECT:0:GLIBCXX_3.4.17
+OBJECT:0:GLIBCXX_3.4.18
+OBJECT:0:GLIBCXX_3.4.19
OBJECT:0:GLIBCXX_3.4.2
OBJECT:0:GLIBCXX_3.4.3
OBJECT:0:GLIBCXX_3.4.4
@@ -3033,6 +3048,8 @@ OBJECT:1:_ZNSt21__numeric_limits_base9is_iec559E@@GLIBCXX_3.4
OBJECT:1:_ZNSt21__numeric_limits_base9is_moduloE@@GLIBCXX_3.4
OBJECT:1:_ZNSt21__numeric_limits_base9is_signedE@@GLIBCXX_3.4
OBJECT:1:_ZNSt6chrono12system_clock12is_monotonicE@@GLIBCXX_3.4.11
+OBJECT:1:_ZNSt6chrono3_V212steady_clock9is_steadyE@@GLIBCXX_3.4.19
+OBJECT:1:_ZNSt6chrono3_V212system_clock9is_steadyE@@GLIBCXX_3.4.19
OBJECT:1:_ZSt10adopt_lock@@GLIBCXX_3.4.11
OBJECT:1:_ZSt10defer_lock@@GLIBCXX_3.4.11
OBJECT:1:_ZSt11try_to_lock@@GLIBCXX_3.4.11
diff --git a/libstdc++-v3/config/abi/pre/gnu.ver b/libstdc++-v3/config/abi/pre/gnu.ver
index 8972fcfca88..d3c399f6bf2 100644
--- a/libstdc++-v3/config/abi/pre/gnu.ver
+++ b/libstdc++-v3/config/abi/pre/gnu.ver
@@ -1365,6 +1365,9 @@ GLIBCXX_3.4.20 {
# std::get_unexpected()
_ZSt14get_unexpectedv;
+ # std::__throw_out_of_range_fmt(char const*, ...)
+ _ZSt24__throw_out_of_range_fmtPKcz;
+
} GLIBCXX_3.4.19;
# Symbols in the support library (libsupc++) have their own tag.
diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure
index 7459bcdf2ce..d00c38af78f 100755
--- a/libstdc++-v3/configure
+++ b/libstdc++-v3/configure
@@ -7118,7 +7118,7 @@ ia64-*-hpux*)
rm -rf conftest*
;;
-x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \
+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
@@ -7143,7 +7143,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
;;
esac
;;
- ppc64-*linux*|powerpc64-*linux*)
+ powerpc64le-*linux*)
+ LD="${LD-ld} -m elf32lppclinux"
+ ;;
+ powerpc64-*linux*)
LD="${LD-ld} -m elf32ppclinux"
;;
s390x-*linux*)
@@ -7162,7 +7165,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
x86_64-*linux*)
LD="${LD-ld} -m elf_x86_64"
;;
- ppc*-*linux*|powerpc*-*linux*)
+ powerpcle-*linux*)
+ LD="${LD-ld} -m elf64lppc"
+ ;;
+ powerpc-*linux*)
LD="${LD-ld} -m elf64ppc"
;;
s390*-*linux*|s390*-*tpf*)
@@ -11520,7 +11526,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11523 "configure"
+#line 11529 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -11626,7 +11632,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11629 "configure"
+#line 11635 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -15046,7 +15052,7 @@ fi
#
# Fake what AC_TRY_COMPILE does. XXX Look at redoing this new-style.
cat > conftest.$ac_ext << EOF
-#line 15049 "configure"
+#line 15055 "configure"
struct S { ~S(); };
void bar();
void foo()
@@ -15064,6 +15070,8 @@ EOF
test $ac_status = 0; }; then
if grep _Unwind_SjLj_Resume conftest.s >/dev/null 2>&1 ; then
enable_sjlj_exceptions=yes
+ elif grep _Unwind_SjLj_Register conftest.s >/dev/null 2>&1 ; then
+ enable_sjlj_exceptions=yes
elif grep _Unwind_Resume conftest.s >/dev/null 2>&1 ; then
enable_sjlj_exceptions=no
elif grep __cxa_end_cleanup conftest.s >/dev/null 2>&1 ; then
@@ -15396,7 +15404,7 @@ $as_echo "$glibcxx_cv_atomic_long_long" >&6; }
# Fake what AC_TRY_COMPILE does.
cat > conftest.$ac_ext << EOF
-#line 15399 "configure"
+#line 15407 "configure"
int main()
{
typedef bool atomic_type;
@@ -15431,7 +15439,7 @@ $as_echo "$glibcxx_cv_atomic_bool" >&6; }
rm -f conftest*
cat > conftest.$ac_ext << EOF
-#line 15434 "configure"
+#line 15442 "configure"
int main()
{
typedef short atomic_type;
@@ -15466,7 +15474,7 @@ $as_echo "$glibcxx_cv_atomic_short" >&6; }
rm -f conftest*
cat > conftest.$ac_ext << EOF
-#line 15469 "configure"
+#line 15477 "configure"
int main()
{
// NB: _Atomic_word not necessarily int.
@@ -15502,7 +15510,7 @@ $as_echo "$glibcxx_cv_atomic_int" >&6; }
rm -f conftest*
cat > conftest.$ac_ext << EOF
-#line 15505 "configure"
+#line 15513 "configure"
int main()
{
typedef long long atomic_type;
@@ -15581,7 +15589,7 @@ $as_echo "$as_me: WARNING: Performance of certain classes will degrade as a resu
# unnecessary for this test.
cat > conftest.$ac_ext << EOF
-#line 15584 "configure"
+#line 15592 "configure"
int main()
{
_Decimal32 d1;
@@ -15623,7 +15631,7 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
# unnecessary for this test.
cat > conftest.$ac_ext << EOF
-#line 15626 "configure"
+#line 15634 "configure"
template<typename T1, typename T2>
struct same
{ typedef T2 type; };
@@ -15657,7 +15665,7 @@ $as_echo "$enable_int128" >&6; }
rm -f conftest*
cat > conftest.$ac_ext << EOF
-#line 15660 "configure"
+#line 15668 "configure"
template<typename T1, typename T2>
struct same
{ typedef T2 type; };
@@ -18669,6 +18677,25 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
+# Check for fenv.h and complex.h before GLIBCXX_CHECK_C99_TR1
+# so that the check is done with the C compiler (not C++).
+# Checking with C++ can break a canadian cross build if either
+# file does not exist in C but does in C++.
+for ac_header in fenv.h complex.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+eval as_val=\$$as_ac_Header
+ if test "x$as_val" = x""yes; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
# For C99 support to TR1.
diff --git a/libstdc++-v3/configure.ac b/libstdc++-v3/configure.ac
index dd13b011f97..22fc840f68b 100644
--- a/libstdc++-v3/configure.ac
+++ b/libstdc++-v3/configure.ac
@@ -195,6 +195,12 @@ GLIBCXX_CHECK_S_ISREG_OR_S_IFREG
AC_CHECK_HEADERS(sys/uio.h)
GLIBCXX_CHECK_WRITEV
+# Check for fenv.h and complex.h before GLIBCXX_CHECK_C99_TR1
+# so that the check is done with the C compiler (not C++).
+# Checking with C++ can break a canadian cross build if either
+# file does not exist in C but does in C++.
+AC_CHECK_HEADERS(fenv.h complex.h)
+
# For C99 support to TR1.
GLIBCXX_CHECK_C99_TR1
diff --git a/libstdc++-v3/doc/xml/manual/status_cxx2011.xml b/libstdc++-v3/doc/xml/manual/status_cxx2011.xml
index 286a539ba76..e013c1f9eee 100644
--- a/libstdc++-v3/doc/xml/manual/status_cxx2011.xml
+++ b/libstdc++-v3/doc/xml/manual/status_cxx2011.xml
@@ -871,10 +871,11 @@ particular release.
<entry/>
</row>
<row>
+ <?dbhtml bgcolor="#B0B0B0" ?>
<entry>20.9.7.6</entry>
<entry>Other transformations</entry>
- <entry>Y</entry>
- <entry/>
+ <entry>Partial</entry>
+ <entry>Missing <code>aligned_union</code>.</entry>
</row>
<row>
<entry>20.10</entry>
@@ -2179,31 +2180,27 @@ particular release.
</entry>
</row>
<row>
- <?dbhtml bgcolor="#C8B0B0" ?>
<entry>28.1</entry>
<entry>General</entry>
- <entry>N</entry>
+ <entry>Y</entry>
<entry/>
</row>
<row>
- <?dbhtml bgcolor="#C8B0B0" ?>
<entry>28.2</entry>
<entry>Definitions</entry>
- <entry>N</entry>
+ <entry>Y</entry>
<entry/>
</row>
<row>
- <?dbhtml bgcolor="#C8B0B0" ?>
<entry>28.3</entry>
<entry>Requirements</entry>
- <entry>N</entry>
+ <entry>Y</entry>
<entry/>
</row>
<row>
- <?dbhtml bgcolor="#C8B0B0" ?>
<entry>28.4</entry>
<entry>Header <code>&lt;regex&gt;</code> synopsis</entry>
- <entry>N</entry>
+ <entry>Y</entry>
<entry/>
</row>
<row>
@@ -2223,48 +2220,43 @@ particular release.
<entry>28.7</entry>
<entry>Class template <code>regex_traits</code></entry>
<entry>Partial</entry>
+ <entry><code>transform_primary</code> is not correctly implemented</entry>
<entry/>
</row>
<row>
- <?dbhtml bgcolor="#B0B0B0" ?>
<entry>28.8</entry>
<entry>Class template <code>basic_regex</code></entry>
- <entry>Partial</entry>
+ <entry>Y</entry>
<entry/>
</row>
<row>
- <?dbhtml bgcolor="#B0B0B0" ?>
<entry>28.9</entry>
<entry>Class template <code>sub_match</code></entry>
- <entry>Partial</entry>
+ <entry>Y</entry>
<entry/>
</row>
<row>
- <?dbhtml bgcolor="#B0B0B0" ?>
<entry>28.10</entry>
<entry>Class template <code>match_results</code></entry>
- <entry>Partial</entry>
+ <entry>Y</entry>
<entry/>
</row>
<row>
- <?dbhtml bgcolor="#C8B0B0" ?>
<entry>28.11</entry>
<entry>Regular expression algorithms</entry>
- <entry>N</entry>
+ <entry>Y</entry>
<entry/>
</row>
<row>
- <?dbhtml bgcolor="#C8B0B0" ?>
<entry>28.12</entry>
<entry>Regular expression Iterators</entry>
- <entry>N</entry>
+ <entry>Y</entry>
<entry/>
</row>
<row>
- <?dbhtml bgcolor="#C8B0B0" ?>
<entry>28.13</entry>
<entry>Modified ECMAScript regular expression grammar</entry>
- <entry>N</entry>
+ <entry>Y</entry>
<entry/>
</row>
<row>
diff --git a/libstdc++-v3/doc/xml/manual/status_cxx2014.xml b/libstdc++-v3/doc/xml/manual/status_cxx2014.xml
index 1f20f0e44de..0e0ac37a9e8 100644
--- a/libstdc++-v3/doc/xml/manual/status_cxx2014.xml
+++ b/libstdc++-v3/doc/xml/manual/status_cxx2014.xml
@@ -178,15 +178,14 @@ particular release.
<row>
- <?dbhtml bgcolor="#C8C8B0" ?>
<entry>
<link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2013/n3658.html">
N3658
</link>
</entry>
<entry>Compile-time integer sequences</entry>
- <entry>WIP</entry>
- <entry>Need tests</entry>
+ <entry>Y</entry>
+ <entry/>
</row>
<row>
@@ -202,14 +201,13 @@ particular release.
<row>
- <?dbhtml bgcolor="#C8C8B0" ?>
<entry>
<link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2012/n3421.htm">
N3421
</link>
</entry>
<entry>Making Operator Functors greater&lt;&gt;</entry>
- <entry>WIP</entry>
+ <entry>Y</entry>
<entry/>
</row>
@@ -227,26 +225,24 @@ particular release.
<row>
- <?dbhtml bgcolor="#C8B0B0" ?>
<entry>
- <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2013/n3672.html">
+ <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2013/n3793.html">
N3672
</link>
</entry>
<entry>A proposal to add a utility class to represent optional objects</entry>
- <entry>N</entry>
- <entry/>
+ <entry>Y</entry>
+ <entry>Moved from C++14 to Library Fundamentals TS</entry>
</row>
<row>
- <?dbhtml bgcolor="#C8B0B0" ?>
<entry>
<link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.open-std.org/JTC1/sc22/WG21/docs/papers/2013/n3655.pdf">
N3655
</link>
</entry>
<entry>TransformationTraits Redux</entry>
- <entry>N</entry>
+ <entry>Y</entry>
<entry/>
</row>
@@ -259,7 +255,7 @@ particular release.
</entry>
<entry>C++ Dynamic Arrays</entry>
<entry>N</entry>
- <entry/>
+ <entry>Moved from C++14 to Library Fundamentals TS</entry>
</row>
<row>
diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am
index 0bceb5776a5..505679af5ae 100644
--- a/libstdc++-v3/include/Makefile.am
+++ b/libstdc++-v3/include/Makefile.am
@@ -94,6 +94,7 @@ bits_headers = \
${bits_srcdir}/concept_check.h \
${bits_srcdir}/cpp_type_traits.h \
${bits_srcdir}/deque.tcc \
+ ${bits_srcdir}/enable_special_members.h \
${bits_srcdir}/forward_list.h \
${bits_srcdir}/forward_list.tcc \
${bits_srcdir}/fstream.tcc \
@@ -121,11 +122,13 @@ bits_headers = \
${bits_srcdir}/ostream_insert.h \
${bits_srcdir}/parse_numbers.h \
${bits_srcdir}/postypes.h \
+ ${bits_srcdir}/predefined_ops.h \
${bits_srcdir}/ptr_traits.h \
${bits_srcdir}/random.h \
${bits_srcdir}/random.tcc \
${bits_srcdir}/range_access.h \
${bits_srcdir}/regex.h \
+ ${bits_srcdir}/regex.tcc \
${bits_srcdir}/regex_constants.h \
${bits_srcdir}/regex_error.h \
${bits_srcdir}/regex_scanner.h \
@@ -621,6 +624,7 @@ tr2_headers = \
${tr2_srcdir}/bool_set \
${tr2_srcdir}/bool_set.tcc \
${tr2_srcdir}/dynamic_bitset \
+ ${tr2_srcdir}/dynamic_bitset.tcc \
${tr2_srcdir}/ratio \
${tr2_srcdir}/type_traits
@@ -630,6 +634,12 @@ decimal_headers = \
${decimal_srcdir}/decimal \
${decimal_srcdir}/decimal.h
+# Post-C++11 TS's
+experimental_srcdir = ${glibcxx_srcdir}/include/experimental
+experimental_builddir = ./experimental
+experimental_headers = \
+ ${experimental_srcdir}/optional
+
# This is the common subset of C++ files that all three "C" header models use.
c_base_srcdir = $(C_INCLUDE_DIR)
c_base_builddir = .
@@ -907,8 +917,8 @@ endif
allstamped = \
stamp-std stamp-bits stamp-bits-sup stamp-c_base stamp-c_compatibility \
stamp-backward stamp-ext stamp-pb stamp-tr1 stamp-tr2 stamp-decimal \
- stamp-debug stamp-parallel stamp-profile stamp-profile-impl \
- stamp-host
+ stamp-experimental stamp-debug stamp-parallel stamp-profile \
+ stamp-profile-impl stamp-host
# List of all files that are created by explicit building, editing, or
# catenation.
@@ -1031,6 +1041,11 @@ stamp-decimal: ${decimal_headers}
@-cd ${decimal_builddir} && $(LN_S) $? . 2>/dev/null
@$(STAMP) stamp-decimal
+stamp-experimental: ${experimental_headers}
+ @-mkdir -p ${experimental_builddir}
+ @-cd ${experimental_builddir} && $(LN_S) $? . 2>/dev/null
+ @$(STAMP) stamp-experimental
+
stamp-debug: ${debug_headers}
@-mkdir -p ${debug_builddir}
@-cd ${debug_builddir} && $(LN_S) $? . 2>/dev/null
@@ -1274,6 +1289,9 @@ install-headers:
$(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${decimal_builddir}
for file in ${decimal_headers}; do \
$(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${decimal_builddir}; done
+ $(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${experimental_builddir}
+ for file in ${experimental_headers}; do \
+ $(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${experimental_builddir}; done
$(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${c_base_builddir}
for file in ${c_base_headers}; do \
$(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${c_base_builddir}; done
@@ -1319,9 +1337,10 @@ clean-local:
# directory. (This is more of an example of how this kind of rule can
# be made.)
.PRECIOUS: $(std_headers) $(c_base_headers) $(tr1_headers) $(tr2_headers)
- $(decimal_headers) $(ext_headers)
+ $(decimal_headers) $(ext_headers) $(experimental_headers)
$(std_headers): ; @:
$(c_base_headers): ; @:
$(tr1_headers): ; @:
$(decimal_headers): ; @:
$(ext_headers): ; @:
+$(experimental_headers): ; @:
diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in
index 458b08c17fb..9d8a7491b7a 100644
--- a/libstdc++-v3/include/Makefile.in
+++ b/libstdc++-v3/include/Makefile.in
@@ -383,6 +383,7 @@ bits_headers = \
${bits_srcdir}/concept_check.h \
${bits_srcdir}/cpp_type_traits.h \
${bits_srcdir}/deque.tcc \
+ ${bits_srcdir}/enable_special_members.h \
${bits_srcdir}/forward_list.h \
${bits_srcdir}/forward_list.tcc \
${bits_srcdir}/fstream.tcc \
@@ -410,11 +411,13 @@ bits_headers = \
${bits_srcdir}/ostream_insert.h \
${bits_srcdir}/parse_numbers.h \
${bits_srcdir}/postypes.h \
+ ${bits_srcdir}/predefined_ops.h \
${bits_srcdir}/ptr_traits.h \
${bits_srcdir}/random.h \
${bits_srcdir}/random.tcc \
${bits_srcdir}/range_access.h \
${bits_srcdir}/regex.h \
+ ${bits_srcdir}/regex.tcc \
${bits_srcdir}/regex_constants.h \
${bits_srcdir}/regex_error.h \
${bits_srcdir}/regex_scanner.h \
@@ -908,6 +911,7 @@ tr2_headers = \
${tr2_srcdir}/bool_set \
${tr2_srcdir}/bool_set.tcc \
${tr2_srcdir}/dynamic_bitset \
+ ${tr2_srcdir}/dynamic_bitset.tcc \
${tr2_srcdir}/ratio \
${tr2_srcdir}/type_traits
@@ -918,6 +922,13 @@ decimal_headers = \
${decimal_srcdir}/decimal.h
+# Post-C++11 TS's
+experimental_srcdir = ${glibcxx_srcdir}/include/experimental
+experimental_builddir = ./experimental
+experimental_headers = \
+ ${experimental_srcdir}/optional
+
+
# This is the common subset of C++ files that all three "C" header models use.
c_base_srcdir = $(C_INCLUDE_DIR)
c_base_builddir = .
@@ -1185,8 +1196,8 @@ PCHFLAGS = -x c++-header -nostdinc++ $(CXXFLAGS) $(VTV_PCH_CXXFLAGS)
allstamped = \
stamp-std stamp-bits stamp-bits-sup stamp-c_base stamp-c_compatibility \
stamp-backward stamp-ext stamp-pb stamp-tr1 stamp-tr2 stamp-decimal \
- stamp-debug stamp-parallel stamp-profile stamp-profile-impl \
- stamp-host
+ stamp-experimental stamp-debug stamp-parallel stamp-profile \
+ stamp-profile-impl stamp-host
# List of all files that are created by explicit building, editing, or
@@ -1477,6 +1488,11 @@ stamp-decimal: ${decimal_headers}
@-cd ${decimal_builddir} && $(LN_S) $? . 2>/dev/null
@$(STAMP) stamp-decimal
+stamp-experimental: ${experimental_headers}
+ @-mkdir -p ${experimental_builddir}
+ @-cd ${experimental_builddir} && $(LN_S) $? . 2>/dev/null
+ @$(STAMP) stamp-experimental
+
stamp-debug: ${debug_headers}
@-mkdir -p ${debug_builddir}
@-cd ${debug_builddir} && $(LN_S) $? . 2>/dev/null
@@ -1705,6 +1721,9 @@ install-headers:
$(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${decimal_builddir}
for file in ${decimal_headers}; do \
$(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${decimal_builddir}; done
+ $(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${experimental_builddir}
+ for file in ${experimental_headers}; do \
+ $(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${experimental_builddir}; done
$(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${c_base_builddir}
for file in ${c_base_headers}; do \
$(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${c_base_builddir}; done
@@ -1747,12 +1766,13 @@ clean-local:
# directory. (This is more of an example of how this kind of rule can
# be made.)
.PRECIOUS: $(std_headers) $(c_base_headers) $(tr1_headers) $(tr2_headers)
- $(decimal_headers) $(ext_headers)
+ $(decimal_headers) $(ext_headers) $(experimental_headers)
$(std_headers): ; @:
$(c_base_headers): ; @:
$(tr1_headers): ; @:
$(decimal_headers): ; @:
$(ext_headers): ; @:
+$(experimental_headers): ; @:
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
diff --git a/libstdc++-v3/include/bits/allocator.h b/libstdc++-v3/include/bits/allocator.h
index 28df242b1bc..c72859b6ed3 100644
--- a/libstdc++-v3/include/bits/allocator.h
+++ b/libstdc++-v3/include/bits/allocator.h
@@ -158,13 +158,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// To implement Option 3 of DR 431.
template<typename _Alloc, bool = __is_empty(_Alloc)>
struct __alloc_swap
- { static void _S_do_it(_Alloc&, _Alloc&) { } };
+ { static void _S_do_it(_Alloc&, _Alloc&) _GLIBCXX_NOEXCEPT { } };
template<typename _Alloc>
struct __alloc_swap<_Alloc, false>
{
static void
- _S_do_it(_Alloc& __one, _Alloc& __two)
+ _S_do_it(_Alloc& __one, _Alloc& __two) _GLIBCXX_NOEXCEPT
{
// Precondition: swappable allocators.
if (__one != __two)
@@ -194,13 +194,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
= __or_<is_copy_constructible<typename _Tp::value_type>,
is_nothrow_move_constructible<typename _Tp::value_type>>::value>
struct __shrink_to_fit_aux
- { static bool _S_do_it(_Tp&) { return false; } };
+ { static bool _S_do_it(_Tp&) noexcept { return false; } };
template<typename _Tp>
struct __shrink_to_fit_aux<_Tp, true>
{
static bool
- _S_do_it(_Tp& __c)
+ _S_do_it(_Tp& __c) noexcept
{
__try
{
diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h
index c8723ededd9..2d3edf80103 100644
--- a/libstdc++-v3/include/bits/basic_string.h
+++ b/libstdc++-v3/include/bits/basic_string.h
@@ -178,7 +178,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
static size_type _S_empty_rep_storage[];
static _Rep&
- _S_empty_rep()
+ _S_empty_rep() _GLIBCXX_NOEXCEPT
{
// NB: Mild hack to avoid strict-aliasing warnings. Note that
// _S_empty_rep_storage is never modified and the punning should
@@ -188,23 +188,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
bool
- _M_is_leaked() const
+ _M_is_leaked() const _GLIBCXX_NOEXCEPT
{ return this->_M_refcount < 0; }
bool
- _M_is_shared() const
+ _M_is_shared() const _GLIBCXX_NOEXCEPT
{ return this->_M_refcount > 0; }
void
- _M_set_leaked()
+ _M_set_leaked() _GLIBCXX_NOEXCEPT
{ this->_M_refcount = -1; }
void
- _M_set_sharable()
+ _M_set_sharable() _GLIBCXX_NOEXCEPT
{ this->_M_refcount = 0; }
void
- _M_set_length_and_sharable(size_type __n)
+ _M_set_length_and_sharable(size_type __n) _GLIBCXX_NOEXCEPT
{
#if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
if (__builtin_expect(this != &_S_empty_rep(), false))
@@ -234,7 +234,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_S_create(size_type, size_type, const _Alloc&);
void
- _M_dispose(const _Alloc& __a)
+ _M_dispose(const _Alloc& __a) _GLIBCXX_NOEXCEPT
{
#if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
if (__builtin_expect(this != &_S_empty_rep(), false))
@@ -271,7 +271,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Use empty-base optimization: http://www.cantrip.org/emptyopt.html
struct _Alloc_hider : _Alloc
{
- _Alloc_hider(_CharT* __dat, const _Alloc& __a)
+ _Alloc_hider(_CharT* __dat, const _Alloc& __a) _GLIBCXX_NOEXCEPT
: _Alloc(__a), _M_p(__dat) { }
_CharT* _M_p; // The actual data.
@@ -289,25 +289,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
mutable _Alloc_hider _M_dataplus;
_CharT*
- _M_data() const
+ _M_data() const _GLIBCXX_NOEXCEPT
{ return _M_dataplus._M_p; }
_CharT*
- _M_data(_CharT* __p)
+ _M_data(_CharT* __p) _GLIBCXX_NOEXCEPT
{ return (_M_dataplus._M_p = __p); }
_Rep*
- _M_rep() const
+ _M_rep() const _GLIBCXX_NOEXCEPT
{ return &((reinterpret_cast<_Rep*> (_M_data()))[-1]); }
// For the internal use we have functions similar to `begin'/`end'
// but they do not call _M_leak.
iterator
- _M_ibegin() const
+ _M_ibegin() const _GLIBCXX_NOEXCEPT
{ return iterator(_M_data()); }
iterator
- _M_iend() const
+ _M_iend() const _GLIBCXX_NOEXCEPT
{ return iterator(_M_data() + this->size()); }
void
@@ -321,7 +321,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_check(size_type __pos, const char* __s) const
{
if (__pos > this->size())
- __throw_out_of_range(__N(__s));
+ __throw_out_of_range_fmt(__N("%s: __pos (which is %zu) > "
+ "this->size() (which is %zu)"),
+ __s, __pos, this->size());
return __pos;
}
@@ -334,7 +336,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// NB: _M_limit doesn't check for a bad __pos value.
size_type
- _M_limit(size_type __pos, size_type __off) const
+ _M_limit(size_type __pos, size_type __off) const _GLIBCXX_NOEXCEPT
{
const bool __testoff = __off < this->size() - __pos;
return __testoff ? __off : this->size() - __pos;
@@ -342,7 +344,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// True if _Rep and source do not overlap.
bool
- _M_disjunct(const _CharT* __s) const
+ _M_disjunct(const _CharT* __s) const _GLIBCXX_NOEXCEPT
{
return (less<const _CharT*>()(__s, _M_data())
|| less<const _CharT*>()(_M_data() + this->size(), __s));
@@ -351,7 +353,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// When __n = 1 way faster than the general multichar
// traits_type::copy/move/assign.
static void
- _M_copy(_CharT* __d, const _CharT* __s, size_type __n)
+ _M_copy(_CharT* __d, const _CharT* __s, size_type __n) _GLIBCXX_NOEXCEPT
{
if (__n == 1)
traits_type::assign(*__d, *__s);
@@ -360,7 +362,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
static void
- _M_move(_CharT* __d, const _CharT* __s, size_type __n)
+ _M_move(_CharT* __d, const _CharT* __s, size_type __n) _GLIBCXX_NOEXCEPT
{
if (__n == 1)
traits_type::assign(*__d, *__s);
@@ -369,7 +371,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
static void
- _M_assign(_CharT* __d, size_type __n, _CharT __c)
+ _M_assign(_CharT* __d, size_type __n, _CharT __c) _GLIBCXX_NOEXCEPT
{
if (__n == 1)
traits_type::assign(*__d, __c);
@@ -382,29 +384,32 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<class _Iterator>
static void
_S_copy_chars(_CharT* __p, _Iterator __k1, _Iterator __k2)
+ _GLIBCXX_NOEXCEPT
{
for (; __k1 != __k2; ++__k1, ++__p)
traits_type::assign(*__p, *__k1); // These types are off.
}
static void
- _S_copy_chars(_CharT* __p, iterator __k1, iterator __k2)
+ _S_copy_chars(_CharT* __p, iterator __k1, iterator __k2) _GLIBCXX_NOEXCEPT
{ _S_copy_chars(__p, __k1.base(), __k2.base()); }
static void
_S_copy_chars(_CharT* __p, const_iterator __k1, const_iterator __k2)
+ _GLIBCXX_NOEXCEPT
{ _S_copy_chars(__p, __k1.base(), __k2.base()); }
static void
- _S_copy_chars(_CharT* __p, _CharT* __k1, _CharT* __k2)
+ _S_copy_chars(_CharT* __p, _CharT* __k1, _CharT* __k2) _GLIBCXX_NOEXCEPT
{ _M_copy(__p, __k1, __k2 - __k1); }
static void
_S_copy_chars(_CharT* __p, const _CharT* __k1, const _CharT* __k2)
+ _GLIBCXX_NOEXCEPT
{ _M_copy(__p, __k1, __k2 - __k1); }
static int
- _S_compare(size_type __n1, size_type __n2)
+ _S_compare(size_type __n1, size_type __n2) _GLIBCXX_NOEXCEPT
{
const difference_type __d = difference_type(__n1 - __n2);
@@ -423,7 +428,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_leak_hard();
static _Rep&
- _S_empty_rep()
+ _S_empty_rep() _GLIBCXX_NOEXCEPT
{ return _Rep::_S_empty_rep(); }
public:
@@ -504,7 +509,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* The newly-created string contains the exact contents of @a __str.
* @a __str is a valid, but unspecified string.
**/
- basic_string(basic_string&& __str) noexcept
+ basic_string(basic_string&& __str)
+#if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
+ noexcept // FIXME C++11: should always be noexcept.
+#endif
: _M_dataplus(__str._M_dataplus)
{
#if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
@@ -576,6 +584,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* The contents of @a str are moved into this string (without copying).
* @a str is a valid, but unspecified string.
**/
+ // PR 58265, this should be noexcept.
basic_string&
operator=(basic_string&& __str)
{
@@ -602,7 +611,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* the %string. Unshares the string.
*/
iterator
- begin() _GLIBCXX_NOEXCEPT
+ begin() // FIXME C++11: should be noexcept.
{
_M_leak();
return iterator(_M_data());
@@ -621,7 +630,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* character in the %string. Unshares the string.
*/
iterator
- end() _GLIBCXX_NOEXCEPT
+ end() // FIXME C++11: should be noexcept.
{
_M_leak();
return iterator(_M_data() + this->size());
@@ -641,7 +650,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* order. Unshares the string.
*/
reverse_iterator
- rbegin() _GLIBCXX_NOEXCEPT
+ rbegin() // FIXME C++11: should be noexcept.
{ return reverse_iterator(this->end()); }
/**
@@ -659,7 +668,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* element order. Unshares the string.
*/
reverse_iterator
- rend() _GLIBCXX_NOEXCEPT
+ rend() // FIXME C++11: should be noexcept.
{ return reverse_iterator(this->begin()); }
/**
@@ -756,7 +765,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#if __cplusplus >= 201103L
/// A non-binding request to reduce capacity() to size().
void
- shrink_to_fit()
+ shrink_to_fit() _GLIBCXX_NOEXCEPT
{
if (capacity() > size())
{
@@ -799,8 +808,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/**
* Erases the string, making it empty.
*/
+ // PR 56166: this should not throw.
void
- clear() _GLIBCXX_NOEXCEPT
+ clear()
{ _M_mutate(0, this->size(), 0); }
/**
@@ -823,7 +833,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* see at().)
*/
const_reference
- operator[] (size_type __pos) const
+ operator[] (size_type __pos) const _GLIBCXX_NOEXCEPT
{
_GLIBCXX_DEBUG_ASSERT(__pos <= size());
return _M_data()[__pos];
@@ -865,7 +875,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
at(size_type __n) const
{
if (__n >= this->size())
- __throw_out_of_range(__N("basic_string::at"));
+ __throw_out_of_range_fmt(__N("basic_string::at: __n "
+ "(which is %zu) >= this->size() "
+ "(which is %zu)"),
+ __n, this->size());
return _M_data()[__n];
}
@@ -884,7 +897,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
at(size_type __n)
{
if (__n >= size())
- __throw_out_of_range(__N("basic_string::at"));
+ __throw_out_of_range_fmt(__N("basic_string::at: __n "
+ "(which is %zu) >= this->size() "
+ "(which is %zu)"),
+ __n, this->size());
_M_leak();
return _M_data()[__n];
}
@@ -903,7 +919,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* element of the %string.
*/
const_reference
- front() const
+ front() const _GLIBCXX_NOEXCEPT
{ return operator[](0); }
/**
@@ -919,7 +935,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* last element of the %string.
*/
const_reference
- back() const
+ back() const _GLIBCXX_NOEXCEPT
{ return operator[](this->size() - 1); }
#endif
@@ -1076,6 +1092,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* This function sets this string to the exact contents of @a __str.
* @a __str is a valid, but unspecified string.
*/
+ // PR 58265, this should be noexcept.
basic_string&
assign(basic_string&& __str)
{
@@ -1405,7 +1422,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* The string must be non-empty.
*/
void
- pop_back()
+ pop_back() // FIXME C++11: should be noexcept.
{ erase(size()-1, 1); }
#endif // C++11
@@ -1787,6 +1804,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* Exchanges the contents of this string with that of @a __s in constant
* time.
*/
+ // PR 58265, this should be noexcept.
void
swap(basic_string& __s);
@@ -3112,22 +3130,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
inline basic_string<char>
- operator"" s(const char* __str, size_t __len)
+ operator""s(const char* __str, size_t __len)
{ return basic_string<char>{__str, __len}; }
#ifdef _GLIBCXX_USE_WCHAR_T
inline basic_string<wchar_t>
- operator"" s(const wchar_t* __str, size_t __len)
+ operator""s(const wchar_t* __str, size_t __len)
{ return basic_string<wchar_t>{__str, __len}; }
#endif
#ifdef _GLIBCXX_USE_C99_STDINT_TR1
inline basic_string<char16_t>
- operator"" s(const char16_t* __str, size_t __len)
+ operator""s(const char16_t* __str, size_t __len)
{ return basic_string<char16_t>{__str, __len}; }
inline basic_string<char32_t>
- operator"" s(const char32_t* __str, size_t __len)
+ operator""s(const char32_t* __str, size_t __len)
{ return basic_string<char32_t>{__str, __len}; }
#endif
diff --git a/libstdc++-v3/include/bits/enable_special_members.h b/libstdc++-v3/include/bits/enable_special_members.h
new file mode 100644
index 00000000000..eb90037e66f
--- /dev/null
+++ b/libstdc++-v3/include/bits/enable_special_members.h
@@ -0,0 +1,278 @@
+// <bits/enable_special_members.h> -*- C++ -*-
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// 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/>.
+
+/** @file bits/enable_special_members.h
+ * This is an internal header file, included by other library headers.
+ * Do not attempt to use it directly.
+ */
+
+#ifndef _ENABLE_SPECIAL_MEMBERS_H
+#define _ENABLE_SPECIAL_MEMBERS_H 1
+
+#pragma GCC system_header
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+/**
+ * @brief A mixin helper to conditionally enable or disable the default
+ * constructor.
+ * @sa _Enable_special_members
+ */
+template<bool _Switch, typename _Tag = void>
+ struct _Enable_default_constructor { };
+
+
+/**
+ * @brief A mixin helper to conditionally enable or disable the default
+ * destructor.
+ * @sa _Enable_special_members
+ */
+template<bool _Switch, typename _Tag = void>
+ struct _Enable_destructor { };
+
+/**
+ * @brief A mixin helper to conditionally enable or disable the copy/move
+ * special members.
+ * @sa _Enable_special_members
+ */
+template<bool _Copy, bool _CopyAssignment,
+ bool _Move, bool _MoveAssignment,
+ typename _Tag = void>
+ struct _Enable_copy_move { };
+
+/**
+ * @brief A mixin helper to conditionally enable or disable the special
+ * members.
+ *
+ * The @c _Tag type parameter is to make mixin bases unique and thus avoid
+ * ambiguities.
+ */
+template<bool _Default, bool _Destructor,
+ bool _Copy, bool _CopyAssignment,
+ bool _Move, bool _MoveAssignment,
+ typename _Tag = void>
+ struct _Enable_special_members
+ : private _Enable_default_constructor<_Default, _Tag>,
+ private _Enable_destructor<_Destructor, _Tag>,
+ private _Enable_copy_move<_Copy, _CopyAssignment,
+ _Move, _MoveAssignment,
+ _Tag>
+ { };
+
+// Boilerplate follows.
+
+template<typename _Tag>
+ struct _Enable_default_constructor<false, _Tag>
+ { constexpr _Enable_default_constructor() noexcept = delete; };
+
+template<typename _Tag>
+ struct _Enable_destructor<false, _Tag>
+ { ~_Enable_destructor() noexcept = delete; };
+
+template<typename _Tag>
+ struct _Enable_copy_move<false, true, true, true, _Tag>
+ {
+ constexpr _Enable_copy_move() noexcept = default;
+ constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = delete;
+ constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = default;
+ _Enable_copy_move&
+ operator=(_Enable_copy_move const&) noexcept = default;
+ _Enable_copy_move&
+ operator=(_Enable_copy_move&&) noexcept = default;
+ };
+
+template<typename _Tag>
+ struct _Enable_copy_move<true, false, true, true, _Tag>
+ {
+ constexpr _Enable_copy_move() noexcept = default;
+ constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = default;
+ constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = default;
+ _Enable_copy_move&
+ operator=(_Enable_copy_move const&) noexcept = delete;
+ _Enable_copy_move&
+ operator=(_Enable_copy_move&&) noexcept = default;
+ };
+
+template<typename _Tag>
+ struct _Enable_copy_move<false, false, true, true, _Tag>
+ {
+ constexpr _Enable_copy_move() noexcept = default;
+ constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = delete;
+ constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = default;
+ _Enable_copy_move&
+ operator=(_Enable_copy_move const&) noexcept = delete;
+ _Enable_copy_move&
+ operator=(_Enable_copy_move&&) noexcept = default;
+ };
+
+template<typename _Tag>
+ struct _Enable_copy_move<true, true, false, true, _Tag>
+ {
+ constexpr _Enable_copy_move() noexcept = default;
+ constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = default;
+ constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = delete;
+ _Enable_copy_move&
+ operator=(_Enable_copy_move const&) noexcept = default;
+ _Enable_copy_move&
+ operator=(_Enable_copy_move&&) noexcept = default;
+ };
+
+template<typename _Tag>
+ struct _Enable_copy_move<false, true, false, true, _Tag>
+ {
+ constexpr _Enable_copy_move() noexcept = default;
+ constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = delete;
+ constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = delete;
+ _Enable_copy_move&
+ operator=(_Enable_copy_move const&) noexcept = default;
+ _Enable_copy_move&
+ operator=(_Enable_copy_move&&) noexcept = default;
+ };
+
+template<typename _Tag>
+ struct _Enable_copy_move<true, false, false, true, _Tag>
+ {
+ constexpr _Enable_copy_move() noexcept = default;
+ constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = default;
+ constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = delete;
+ _Enable_copy_move&
+ operator=(_Enable_copy_move const&) noexcept = delete;
+ _Enable_copy_move&
+ operator=(_Enable_copy_move&&) noexcept = default;
+ };
+
+template<typename _Tag>
+ struct _Enable_copy_move<false, false, false, true, _Tag>
+ {
+ constexpr _Enable_copy_move() noexcept = default;
+ constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = delete;
+ constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = delete;
+ _Enable_copy_move&
+ operator=(_Enable_copy_move const&) noexcept = delete;
+ _Enable_copy_move&
+ operator=(_Enable_copy_move&&) noexcept = default;
+ };
+
+template<typename _Tag>
+ struct _Enable_copy_move<true, true, true, false, _Tag>
+ {
+ constexpr _Enable_copy_move() noexcept = default;
+ constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = default;
+ constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = default;
+ _Enable_copy_move&
+ operator=(_Enable_copy_move const&) noexcept = default;
+ _Enable_copy_move&
+ operator=(_Enable_copy_move&&) noexcept = delete;
+ };
+
+template<typename _Tag>
+ struct _Enable_copy_move<false, true, true, false, _Tag>
+ {
+ constexpr _Enable_copy_move() noexcept = default;
+ constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = delete;
+ constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = default;
+ _Enable_copy_move&
+ operator=(_Enable_copy_move const&) noexcept = default;
+ _Enable_copy_move&
+ operator=(_Enable_copy_move&&) noexcept = delete;
+ };
+
+template<typename _Tag>
+ struct _Enable_copy_move<true, false, true, false, _Tag>
+ {
+ constexpr _Enable_copy_move() noexcept = default;
+ constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = default;
+ constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = default;
+ _Enable_copy_move&
+ operator=(_Enable_copy_move const&) noexcept = delete;
+ _Enable_copy_move&
+ operator=(_Enable_copy_move&&) noexcept = delete;
+ };
+
+template<typename _Tag>
+ struct _Enable_copy_move<false, false, true, false, _Tag>
+ {
+ constexpr _Enable_copy_move() noexcept = default;
+ constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = delete;
+ constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = default;
+ _Enable_copy_move&
+ operator=(_Enable_copy_move const&) noexcept = delete;
+ _Enable_copy_move&
+ operator=(_Enable_copy_move&&) noexcept = delete;
+ };
+
+template<typename _Tag>
+ struct _Enable_copy_move<true, true, false, false, _Tag>
+ {
+ constexpr _Enable_copy_move() noexcept = default;
+ constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = default;
+ constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = delete;
+ _Enable_copy_move&
+ operator=(_Enable_copy_move const&) noexcept = default;
+ _Enable_copy_move&
+ operator=(_Enable_copy_move&&) noexcept = delete;
+ };
+
+template<typename _Tag>
+ struct _Enable_copy_move<false, true, false, false, _Tag>
+ {
+ constexpr _Enable_copy_move() noexcept = default;
+ constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = delete;
+ constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = delete;
+ _Enable_copy_move&
+ operator=(_Enable_copy_move const&) noexcept = default;
+ _Enable_copy_move&
+ operator=(_Enable_copy_move&&) noexcept = delete;
+ };
+
+template<typename _Tag>
+ struct _Enable_copy_move<true, false, false, false, _Tag>
+ {
+ constexpr _Enable_copy_move() noexcept = default;
+ constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = default;
+ constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = delete;
+ _Enable_copy_move&
+ operator=(_Enable_copy_move const&) noexcept = delete;
+ _Enable_copy_move&
+ operator=(_Enable_copy_move&&) noexcept = delete;
+ };
+
+template<typename _Tag>
+ struct _Enable_copy_move<false, false, false, false, _Tag>
+ {
+ constexpr _Enable_copy_move() noexcept = default;
+ constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = delete;
+ constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = delete;
+ _Enable_copy_move&
+ operator=(_Enable_copy_move const&) noexcept = delete;
+ _Enable_copy_move&
+ operator=(_Enable_copy_move&&) noexcept = delete;
+ };
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+
+#endif // _ENABLE_SPECIAL_MEMBERS_H
diff --git a/libstdc++-v3/include/bits/forward_list.h b/libstdc++-v3/include/bits/forward_list.h
index c3cee971399..9ac9d22523b 100644
--- a/libstdc++-v3/include/bits/forward_list.h
+++ b/libstdc++-v3/include/bits/forward_list.h
@@ -58,7 +58,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_Fwd_list_node_base*
_M_transfer_after(_Fwd_list_node_base* __begin,
- _Fwd_list_node_base* __end)
+ _Fwd_list_node_base* __end) noexcept
{
_Fwd_list_node_base* __keep = __begin->_M_next;
if (__end)
@@ -128,30 +128,30 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
typedef ptrdiff_t difference_type;
typedef std::forward_iterator_tag iterator_category;
- _Fwd_list_iterator()
+ _Fwd_list_iterator() noexcept
: _M_node() { }
explicit
- _Fwd_list_iterator(_Fwd_list_node_base* __n)
+ _Fwd_list_iterator(_Fwd_list_node_base* __n) noexcept
: _M_node(__n) { }
reference
- operator*() const
+ operator*() const noexcept
{ return *static_cast<_Node*>(this->_M_node)->_M_valptr(); }
pointer
- operator->() const
+ operator->() const noexcept
{ return static_cast<_Node*>(this->_M_node)->_M_valptr(); }
_Self&
- operator++()
+ operator++() noexcept
{
_M_node = _M_node->_M_next;
return *this;
}
_Self
- operator++(int)
+ operator++(int) noexcept
{
_Self __tmp(*this);
_M_node = _M_node->_M_next;
@@ -159,15 +159,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
bool
- operator==(const _Self& __x) const
+ operator==(const _Self& __x) const noexcept
{ return _M_node == __x._M_node; }
bool
- operator!=(const _Self& __x) const
+ operator!=(const _Self& __x) const noexcept
{ return _M_node != __x._M_node; }
_Self
- _M_next() const
+ _M_next() const noexcept
{
if (_M_node)
return _Fwd_list_iterator(_M_node->_M_next);
@@ -196,33 +196,33 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
typedef ptrdiff_t difference_type;
typedef std::forward_iterator_tag iterator_category;
- _Fwd_list_const_iterator()
+ _Fwd_list_const_iterator() noexcept
: _M_node() { }
explicit
- _Fwd_list_const_iterator(const _Fwd_list_node_base* __n)
+ _Fwd_list_const_iterator(const _Fwd_list_node_base* __n) noexcept
: _M_node(__n) { }
- _Fwd_list_const_iterator(const iterator& __iter)
+ _Fwd_list_const_iterator(const iterator& __iter) noexcept
: _M_node(__iter._M_node) { }
reference
- operator*() const
+ operator*() const noexcept
{ return *static_cast<_Node*>(this->_M_node)->_M_valptr(); }
pointer
- operator->() const
+ operator->() const noexcept
{ return static_cast<_Node*>(this->_M_node)->_M_valptr(); }
_Self&
- operator++()
+ operator++() noexcept
{
_M_node = _M_node->_M_next;
return *this;
}
_Self
- operator++(int)
+ operator++(int) noexcept
{
_Self __tmp(*this);
_M_node = _M_node->_M_next;
@@ -230,15 +230,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
bool
- operator==(const _Self& __x) const
+ operator==(const _Self& __x) const noexcept
{ return _M_node == __x._M_node; }
bool
- operator!=(const _Self& __x) const
+ operator!=(const _Self& __x) const noexcept
{ return _M_node != __x._M_node; }
_Self
- _M_next() const
+ _M_next() const noexcept
{
if (this->_M_node)
return _Fwd_list_const_iterator(_M_node->_M_next);
@@ -255,7 +255,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
template<typename _Tp>
inline bool
operator==(const _Fwd_list_iterator<_Tp>& __x,
- const _Fwd_list_const_iterator<_Tp>& __y)
+ const _Fwd_list_const_iterator<_Tp>& __y) noexcept
{ return __x._M_node == __y._M_node; }
/**
@@ -264,7 +264,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
template<typename _Tp>
inline bool
operator!=(const _Fwd_list_iterator<_Tp>& __x,
- const _Fwd_list_const_iterator<_Tp>& __y)
+ const _Fwd_list_const_iterator<_Tp>& __y) noexcept
{ return __x._M_node != __y._M_node; }
/**
diff --git a/libstdc++-v3/include/bits/functexcept.h b/libstdc++-v3/include/bits/functexcept.h
index 16140583077..03e2040d96a 100644
--- a/libstdc++-v3/include/bits/functexcept.h
+++ b/libstdc++-v3/include/bits/functexcept.h
@@ -75,6 +75,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__throw_out_of_range(const char*) __attribute__((__noreturn__));
void
+ __throw_out_of_range_fmt(const char*, ...) __attribute__((__noreturn__))
+ __attribute__((__format__(__printf__, 1, 2)));
+
+ void
__throw_runtime_error(const char*) __attribute__((__noreturn__));
void
diff --git a/libstdc++-v3/include/bits/hashtable.h b/libstdc++-v3/include/bits/hashtable.h
index 43c89b1ce51..aae146b41be 100644
--- a/libstdc++-v3/include/bits/hashtable.h
+++ b/libstdc++-v3/include/bits/hashtable.h
@@ -277,14 +277,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
"Functor used to map hash code to bucket index"
" must be default constructible");
+ // _Hash_code_base has a protected default constructor, so use this
+ // derived type to tell if it's usable.
+ struct __access_protected_ctor : __hash_code_base { };
+
// When hash codes are not cached local iterator inherits from
// __hash_code_base above to compute node bucket index so it has to be
// default constructible.
static_assert(__if_hash_not_cached<
- is_default_constructible<
- // We use _Hashtable_ebo_helper to access the protected
- // default constructor.
- __detail::_Hashtable_ebo_helper<0, __hash_code_base>>>::value,
+ is_default_constructible<__access_protected_ctor>>::value,
"Cache the hash code or make functors involved in hash code"
" and bucket index computation default constructible");
diff --git a/libstdc++-v3/include/bits/hashtable_policy.h b/libstdc++-v3/include/bits/hashtable_policy.h
index 61b852f62df..ed9e9dd870a 100644
--- a/libstdc++-v3/include/bits/hashtable_policy.h
+++ b/libstdc++-v3/include/bits/hashtable_policy.h
@@ -230,9 +230,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
_Hash_node_base* _M_nxt;
- _Hash_node_base() : _M_nxt() { }
+ _Hash_node_base() noexcept : _M_nxt() { }
- _Hash_node_base(_Hash_node_base* __next) : _M_nxt(__next) { }
+ _Hash_node_base(_Hash_node_base* __next) noexcept : _M_nxt(__next) { }
};
/**
@@ -281,7 +281,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
std::size_t _M_hash_code;
_Hash_node*
- _M_next() const { return static_cast<_Hash_node*>(this->_M_nxt); }
+ _M_next() const noexcept
+ { return static_cast<_Hash_node*>(this->_M_nxt); }
};
/**
@@ -293,7 +294,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
struct _Hash_node<_Value, false> : _Hash_node_value_base<_Value>
{
_Hash_node*
- _M_next() const { return static_cast<_Hash_node*>(this->_M_nxt); }
+ _M_next() const noexcept
+ { return static_cast<_Hash_node*>(this->_M_nxt); }
};
/// Base class for node iterators.
@@ -304,11 +306,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__node_type* _M_cur;
- _Node_iterator_base(__node_type* __p)
+ _Node_iterator_base(__node_type* __p) noexcept
: _M_cur(__p) { }
void
- _M_incr()
+ _M_incr() noexcept
{ _M_cur = _M_cur->_M_next(); }
};
@@ -316,12 +318,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
inline bool
operator==(const _Node_iterator_base<_Value, _Cache_hash_code>& __x,
const _Node_iterator_base<_Value, _Cache_hash_code >& __y)
+ noexcept
{ return __x._M_cur == __y._M_cur; }
template<typename _Value, bool _Cache_hash_code>
inline bool
operator!=(const _Node_iterator_base<_Value, _Cache_hash_code>& __x,
const _Node_iterator_base<_Value, _Cache_hash_code>& __y)
+ noexcept
{ return __x._M_cur != __y._M_cur; }
/// Node iterators, used to iterate through all the hashtable.
@@ -344,30 +348,30 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
using reference = typename std::conditional<__constant_iterators,
const _Value&, _Value&>::type;
- _Node_iterator()
+ _Node_iterator() noexcept
: __base_type(0) { }
explicit
- _Node_iterator(__node_type* __p)
+ _Node_iterator(__node_type* __p) noexcept
: __base_type(__p) { }
reference
- operator*() const
+ operator*() const noexcept
{ return this->_M_cur->_M_v(); }
pointer
- operator->() const
+ operator->() const noexcept
{ return this->_M_cur->_M_valptr(); }
_Node_iterator&
- operator++()
+ operator++() noexcept
{
this->_M_incr();
return *this;
}
_Node_iterator
- operator++(int)
+ operator++(int) noexcept
{
_Node_iterator __tmp(*this);
this->_M_incr();
@@ -392,34 +396,34 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typedef const _Value* pointer;
typedef const _Value& reference;
- _Node_const_iterator()
+ _Node_const_iterator() noexcept
: __base_type(0) { }
explicit
- _Node_const_iterator(__node_type* __p)
+ _Node_const_iterator(__node_type* __p) noexcept
: __base_type(__p) { }
_Node_const_iterator(const _Node_iterator<_Value, __constant_iterators,
- __cache>& __x)
+ __cache>& __x) noexcept
: __base_type(__x._M_cur) { }
reference
- operator*() const
+ operator*() const noexcept
{ return this->_M_cur->_M_v(); }
pointer
- operator->() const
+ operator->() const noexcept
{ return this->_M_cur->_M_valptr(); }
_Node_const_iterator&
- operator++()
+ operator++() noexcept
{
this->_M_incr();
return *this;
}
_Node_const_iterator
- operator++(int)
+ operator++(int) noexcept
{
_Node_const_iterator __tmp(*this);
this->_M_incr();
diff --git a/libstdc++-v3/include/bits/parse_numbers.h b/libstdc++-v3/include/bits/parse_numbers.h
index eaa3d27a18a..537b772e95f 100644
--- a/libstdc++-v3/include/bits/parse_numbers.h
+++ b/libstdc++-v3/include/bits/parse_numbers.h
@@ -32,7 +32,7 @@
#pragma GCC system_header
-// From n3642.pdf except I added binary literals and digit separator '`'.
+// From n3642.pdf except I added binary literals and digit separator '\''.
#if __cplusplus > 201103L
@@ -221,7 +221,7 @@ namespace __parse_int {
// Digit separator
template<unsigned _Base>
- struct _Digit<_Base, '`'>
+ struct _Digit<_Base, '\''>
{
static constexpr bool valid{false};
static constexpr unsigned value{0};
diff --git a/libstdc++-v3/include/bits/predefined_ops.h b/libstdc++-v3/include/bits/predefined_ops.h
new file mode 100644
index 00000000000..30870b76383
--- /dev/null
+++ b/libstdc++-v3/include/bits/predefined_ops.h
@@ -0,0 +1,304 @@
+// Default predicates for internal use -*- C++ -*-
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// 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/>.
+
+/** @file predefined_ops.h
+ * This is an internal header file, included by other library headers.
+ * You should not attempt to use it directly.
+ */
+
+#ifndef _GLIBCXX_PREDEFINED_OPS_H
+#define _GLIBCXX_PREDEFINED_OPS_H 1
+
+namespace __gnu_cxx
+{
+namespace __ops
+{
+ struct _Iter_less_iter
+ {
+ template<typename _Iterator1, typename _Iterator2>
+ bool
+ operator()(_Iterator1 __it1, _Iterator2 __it2) const
+ { return *__it1 < *__it2; }
+ };
+
+ inline _Iter_less_iter
+ __iter_less_iter()
+ { return _Iter_less_iter(); }
+
+ struct _Iter_less_val
+ {
+ template<typename _Iterator, typename _Value>
+ bool
+ operator()(_Iterator __it, _Value& __val) const
+ { return *__it < __val; }
+ };
+
+ inline _Iter_less_val
+ __iter_less_val()
+ { return _Iter_less_val(); }
+
+ inline _Iter_less_val
+ __iter_comp_val(_Iter_less_iter)
+ { return _Iter_less_val(); }
+
+ struct _Val_less_iter
+ {
+ template<typename _Value, typename _Iterator>
+ bool
+ operator()(_Value& __val, _Iterator __it) const
+ { return __val < *__it; }
+ };
+
+ inline _Val_less_iter
+ __val_less_iter()
+ { return _Val_less_iter(); }
+
+ inline _Val_less_iter
+ __val_comp_iter(_Iter_less_iter)
+ { return _Val_less_iter(); }
+
+ struct _Iter_equal_to_iter
+ {
+ template<typename _Iterator1, typename _Iterator2>
+ bool
+ operator()(_Iterator1 __it1, _Iterator2 __it2) const
+ { return *__it1 == *__it2; }
+ };
+
+ inline _Iter_equal_to_iter
+ __iter_equal_to_iter()
+ { return _Iter_equal_to_iter(); }
+
+ struct _Iter_equal_to_val
+ {
+ template<typename _Iterator, typename _Value>
+ bool
+ operator()(_Iterator __it, _Value& __val) const
+ { return *__it == __val; }
+ };
+
+ inline _Iter_equal_to_val
+ __iter_equal_to_val()
+ { return _Iter_equal_to_val(); }
+
+ inline _Iter_equal_to_val
+ __iter_comp_val(_Iter_equal_to_iter)
+ { return _Iter_equal_to_val(); }
+
+ template<typename _Compare>
+ struct _Iter_comp_iter
+ {
+ _Compare _M_comp;
+
+ _Iter_comp_iter(_Compare __comp)
+ : _M_comp(__comp)
+ { }
+
+ template<typename _Iterator1, typename _Iterator2>
+ bool
+ operator()(_Iterator1 __it1, _Iterator2 __it2)
+ { return bool(_M_comp(*__it1, *__it2)); }
+ };
+
+ template<typename _Compare>
+ inline _Iter_comp_iter<_Compare>
+ __iter_comp_iter(_Compare __comp)
+ { return _Iter_comp_iter<_Compare>(__comp); }
+
+ template<typename _Compare>
+ struct _Iter_comp_val
+ {
+ _Compare _M_comp;
+
+ _Iter_comp_val(_Compare __comp)
+ : _M_comp(__comp)
+ { }
+
+ template<typename _Iterator, typename _Value>
+ bool
+ operator()(_Iterator __it, _Value& __val)
+ { return bool(_M_comp(*__it, __val)); }
+ };
+
+ template<typename _Compare>
+ inline _Iter_comp_val<_Compare>
+ __iter_comp_val(_Compare __comp)
+ { return _Iter_comp_val<_Compare>(__comp); }
+
+ template<typename _Compare>
+ inline _Iter_comp_val<_Compare>
+ __iter_comp_val(_Iter_comp_iter<_Compare> __comp)
+ { return _Iter_comp_val<_Compare>(__comp._M_comp); }
+
+ template<typename _Compare>
+ struct _Val_comp_iter
+ {
+ _Compare _M_comp;
+
+ _Val_comp_iter(_Compare __comp)
+ : _M_comp(__comp)
+ { }
+
+ template<typename _Value, typename _Iterator>
+ bool
+ operator()(_Value& __val, _Iterator __it)
+ { return bool(_M_comp(__val, *__it)); }
+ };
+
+ template<typename _Compare>
+ inline _Val_comp_iter<_Compare>
+ __val_comp_iter(_Compare __comp)
+ { return _Val_comp_iter<_Compare>(__comp); }
+
+ template<typename _Compare>
+ inline _Val_comp_iter<_Compare>
+ __val_comp_iter(_Iter_comp_iter<_Compare> __comp)
+ { return _Val_comp_iter<_Compare>(__comp._M_comp); }
+
+ template<typename _Value>
+ struct _Iter_equals_val
+ {
+ _Value& _M_value;
+
+ _Iter_equals_val(_Value& __value)
+ : _M_value(__value)
+ { }
+
+ template<typename _Iterator>
+ bool
+ operator()(_Iterator __it)
+ { return *__it == _M_value; }
+ };
+
+ template<typename _Value>
+ inline _Iter_equals_val<_Value>
+ __iter_equals_val(_Value& __val)
+ { return _Iter_equals_val<_Value>(__val); }
+
+ template<typename _Iterator1>
+ struct _Iter_equals_iter
+ {
+ typename std::iterator_traits<_Iterator1>::reference _M_ref;
+
+ _Iter_equals_iter(_Iterator1 __it1)
+ : _M_ref(*__it1)
+ { }
+
+ template<typename _Iterator2>
+ bool
+ operator()(_Iterator2 __it2)
+ { return *__it2 == _M_ref; }
+ };
+
+ template<typename _Iterator>
+ inline _Iter_equals_iter<_Iterator>
+ __iter_comp_iter(_Iter_equal_to_iter, _Iterator __it)
+ { return _Iter_equals_iter<_Iterator>(__it); }
+
+ template<typename _Predicate>
+ struct _Iter_pred
+ {
+ _Predicate _M_pred;
+
+ _Iter_pred(_Predicate __pred)
+ : _M_pred(__pred)
+ { }
+
+ template<typename _Iterator>
+ bool
+ operator()(_Iterator __it)
+ { return bool(_M_pred(*__it)); }
+ };
+
+ template<typename _Predicate>
+ inline _Iter_pred<_Predicate>
+ __pred_iter(_Predicate __pred)
+ { return _Iter_pred<_Predicate>(__pred); }
+
+ template<typename _Compare, typename _Value>
+ struct _Iter_comp_to_val
+ {
+ _Compare _M_comp;
+ _Value& _M_value;
+
+ _Iter_comp_to_val(_Compare __comp, _Value& __value)
+ : _M_comp(__comp), _M_value(__value)
+ { }
+
+ template<typename _Iterator>
+ bool
+ operator()(_Iterator __it)
+ { return bool(_M_comp(*__it, _M_value)); }
+ };
+
+ template<typename _Compare, typename _Value>
+ _Iter_comp_to_val<_Compare, _Value>
+ __iter_comp_val(_Compare __comp, _Value &__val)
+ { return _Iter_comp_to_val<_Compare, _Value>(__comp, __val); }
+
+ template<typename _Compare, typename _Iterator1>
+ struct _Iter_comp_to_iter
+ {
+ _Compare _M_comp;
+ typename std::iterator_traits<_Iterator1>::reference _M_ref;
+
+ _Iter_comp_to_iter(_Compare __comp, _Iterator1 __it1)
+ : _M_comp(__comp), _M_ref(*__it1)
+ { }
+
+ template<typename _Iterator2>
+ bool
+ operator()(_Iterator2 __it2)
+ { return bool(_M_comp(*__it2, _M_ref)); }
+ };
+
+ template<typename _Compare, typename _Iterator>
+ inline _Iter_comp_to_iter<_Compare, _Iterator>
+ __iter_comp_iter(_Iter_comp_iter<_Compare> __comp, _Iterator __it)
+ { return _Iter_comp_to_iter<_Compare, _Iterator>(__comp._M_comp, __it); }
+
+ template<typename _Predicate>
+ struct _Iter_negate
+ {
+ _Predicate _M_pred;
+
+ _Iter_negate(_Predicate __pred)
+ : _M_pred(__pred)
+ { }
+
+ template<typename _Iterator>
+ bool
+ operator()(_Iterator __it)
+ { return !bool(_M_pred(*__it)); }
+ };
+
+ template<typename _Predicate>
+ inline _Iter_negate<_Predicate>
+ __negate(_Iter_pred<_Predicate> __pred)
+ { return _Iter_negate<_Predicate>(__pred._M_pred); }
+
+} // namespace __ops
+} // namespace __gnu_cxx
+
+#endif
diff --git a/libstdc++-v3/include/bits/regex.h b/libstdc++-v3/include/bits/regex.h
index 9d1438aab23..84b8cf1dd4f 100644
--- a/libstdc++-v3/include/bits/regex.h
+++ b/libstdc++-v3/include/bits/regex.h
@@ -32,6 +32,27 @@ namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
+namespace __detail
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ enum class _RegexExecutorPolicy : int
+ { _S_auto, _S_alternate };
+
+ template<typename _BiIter, typename _Alloc,
+ typename _CharT, typename _TraitsT,
+ _RegexExecutorPolicy __policy,
+ bool __match_mode>
+ bool
+ __regex_algo_impl(_BiIter __s,
+ _BiIter __e,
+ match_results<_BiIter, _Alloc>& __m,
+ const basic_regex<_CharT, _TraitsT>& __re,
+ regex_constants::match_flag_type __flags);
+
+_GLIBCXX_END_NAMESPACE_VERSION
+}
+
/**
* @addtogroup regex
* @{
@@ -214,16 +235,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* is known and can be converted into a primary sort key
* then returns that key, otherwise returns an empty string.
*
- * @todo Implement this function.
+ * @todo Implement this function correctly.
*/
template<typename _Fwd_iter>
string_type
transform_primary(_Fwd_iter __first, _Fwd_iter __last) const
{
+ // TODO : this is not entirely correct.
+ // This function requires extra support from the platform.
+ //
+ // Read http://gcc.gnu.org/ml/libstdc++/2013-09/msg00117.html and
+ // http://www.open-std.org/Jtc1/sc22/wg21/docs/papers/2003/n1429.htm
+ // for details.
typedef std::ctype<char_type> __ctype_type;
const __ctype_type& __fctyp(use_facet<__ctype_type>(_M_locale));
std::vector<char_type> __s(__first, __last);
- // FIXME : this is not entirely correct
__fctyp.tolower(__s.data(), __s.data() + __s.size());
return this->transform(__s.data(), __s.data() + __s.size());
}
@@ -343,278 +369,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
locale_type _M_locale;
};
- template<typename _Ch_type>
- template<typename _Fwd_iter>
- typename regex_traits<_Ch_type>::string_type
- regex_traits<_Ch_type>::
- lookup_collatename(_Fwd_iter __first, _Fwd_iter __last) const
- {
- typedef std::ctype<char_type> __ctype_type;
- const __ctype_type& __fctyp(use_facet<__ctype_type>(_M_locale));
-
- static const char* __collatenames[] =
- {
- "NUL",
- "SOH",
- "STX",
- "ETX",
- "EOT",
- "ENQ",
- "ACK",
- "alert",
- "backspace",
- "tab",
- "newline",
- "vertical-tab",
- "form-feed",
- "carriage-return",
- "SO",
- "SI",
- "DLE",
- "DC1",
- "DC2",
- "DC3",
- "DC4",
- "NAK",
- "SYN",
- "ETB",
- "CAN",
- "EM",
- "SUB",
- "ESC",
- "IS4",
- "IS3",
- "IS2",
- "IS1",
- "space",
- "exclamation-mark",
- "quotation-mark",
- "number-sign",
- "dollar-sign",
- "percent-sign",
- "ampersand",
- "apostrophe",
- "left-parenthesis",
- "right-parenthesis",
- "asterisk",
- "plus-sign",
- "comma",
- "hyphen",
- "period",
- "slash",
- "zero",
- "one",
- "two",
- "three",
- "four",
- "five",
- "six",
- "seven",
- "eight",
- "nine",
- "colon",
- "semicolon",
- "less-than-sign",
- "equals-sign",
- "greater-than-sign",
- "question-mark",
- "commercial-at",
- "A",
- "B",
- "C",
- "D",
- "E",
- "F",
- "G",
- "H",
- "I",
- "J",
- "K",
- "L",
- "M",
- "N",
- "O",
- "P",
- "Q",
- "R",
- "S",
- "T",
- "U",
- "V",
- "W",
- "X",
- "Y",
- "Z",
- "left-square-bracket",
- "backslash",
- "right-square-bracket",
- "circumflex",
- "underscore",
- "grave-accent",
- "a",
- "b",
- "c",
- "d",
- "e",
- "f",
- "g",
- "h",
- "i",
- "j",
- "k",
- "l",
- "m",
- "n",
- "o",
- "p",
- "q",
- "r",
- "s",
- "t",
- "u",
- "v",
- "w",
- "x",
- "y",
- "z",
- "left-curly-bracket",
- "vertical-line",
- "right-curly-bracket",
- "tilde",
- "DEL",
- ""
- };
-
- // same as boost
- static const char* __digraphs[] =
- {
- "ae",
- "Ae",
- "AE",
- "ch",
- "Ch",
- "CH",
- "ll",
- "Ll",
- "LL",
- "ss",
- "Ss",
- "SS",
- "nj",
- "Nj",
- "NJ",
- "dz",
- "Dz",
- "DZ",
- "lj",
- "Lj",
- "LJ",
- ""
- };
-
- std::string __s(__last - __first, '?');
- __fctyp.narrow(__first, __last, '?', &*__s.begin());
-
- for (unsigned int __i = 0; *__collatenames[__i]; __i++)
- if (__s == __collatenames[__i])
- return string_type(1, __fctyp.widen((char)__i));
-
- for (unsigned int __i = 0; *__digraphs[__i]; __i++)
- {
- const char* __now = __digraphs[__i];
- if (__s == __now)
- {
- string_type ret(__s.size(), __fctyp.widen('?'));
- __fctyp.widen(__now, __now + 2/* ouch */, &*ret.begin());
- return ret;
- }
- }
- return string_type();
- }
-
- template<typename _Ch_type>
- template<typename _Fwd_iter>
- typename regex_traits<_Ch_type>::char_class_type
- regex_traits<_Ch_type>::
- lookup_classname(_Fwd_iter __first, _Fwd_iter __last, bool __icase) const
- {
- typedef std::ctype<char_type> __ctype_type;
- typedef std::ctype<char> __cctype_type;
- typedef const pair<const char*, char_class_type> _ClassnameEntry;
- const __ctype_type& __fctyp(use_facet<__ctype_type>(_M_locale));
- const __cctype_type& __cctyp(use_facet<__cctype_type>(_M_locale));
-
- static _ClassnameEntry __classnames[] =
- {
- {"d", ctype_base::digit},
- {"w", {ctype_base::alnum, _RegexMask::_S_under}},
- {"s", ctype_base::space},
- {"alnum", ctype_base::alnum},
- {"alpha", ctype_base::alpha},
- {"blank", {0, _RegexMask::_S_blank}},
- {"cntrl", ctype_base::cntrl},
- {"digit", ctype_base::digit},
- {"graph", ctype_base::graph},
- {"lower", ctype_base::lower},
- {"print", ctype_base::print},
- {"punct", ctype_base::punct},
- {"space", ctype_base::space},
- {"upper", ctype_base::upper},
- {"xdigit", ctype_base::xdigit},
- };
-
- std::string __s(__last - __first, '?');
- __fctyp.narrow(__first, __last, '?', &__s[0]);
- __cctyp.tolower(&*__s.begin(), &*__s.begin() + __s.size());
- for (_ClassnameEntry* __it = __classnames;
- __it < *(&__classnames + 1);
- ++__it)
- {
- if (__s == __it->first)
- {
- if (__icase
- && ((__it->second
- & (ctype_base::lower | ctype_base::upper)) != 0))
- return ctype_base::alpha;
- return __it->second;
- }
- }
- return 0;
- }
-
- template<typename _Ch_type>
- bool
- regex_traits<_Ch_type>::
- isctype(_Ch_type __c, char_class_type __f) const
- {
- typedef std::ctype<char_type> __ctype_type;
- const __ctype_type& __fctyp(use_facet<__ctype_type>(_M_locale));
-
- return __fctyp.is(__f._M_base, __c)
- // [[:w:]]
- || ((__f._M_extended & _RegexMask::_S_under)
- && __c == __fctyp.widen('_'))
- // [[:blank:]]
- || ((__f._M_extended & _RegexMask::_S_blank)
- && (__c == __fctyp.widen(' ')
- || __c == __fctyp.widen('\t')));
- }
-
- template<typename _Ch_type>
- int
- regex_traits<_Ch_type>::
- value(_Ch_type __ch, int __radix) const
- {
- std::basic_istringstream<char_type> __is(string_type(1, __ch));
- int __v;
- if (__radix == 8)
- __is >> std::oct;
- else if (__radix == 16)
- __is >> std::hex;
- __is >> __v;
- return __is.fail() ? -1 : __v;
- }
-
// [7.8] Class basic_regex
/**
* Objects of specializations of this class represent regular expressions
@@ -623,10 +377,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* Storage for the regular expression is allocated and deallocated as
* necessary by the member functions of this class.
*/
- template<typename _Ch_type, typename _Rx_traits = regex_traits<_Ch_type> >
+ template<typename _Ch_type, typename _Rx_traits = regex_traits<_Ch_type>>
class basic_regex
{
public:
+ static_assert(is_same<_Ch_type, typename _Rx_traits::char_type>::value,
+ "regex traits class must have the same char_type");
+
// types:
typedef _Ch_type value_type;
typedef _Rx_traits traits_type;
@@ -688,8 +445,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*
* @throws regex_error if @p __p is not a valid regular expression.
*/
- basic_regex(const _Ch_type* __p,
- std::size_t __len, flag_type __f = ECMAScript)
+ basic_regex(const _Ch_type* __p, std::size_t __len,
+ flag_type __f = ECMAScript)
: basic_regex(__p, __p + __len, __f)
{ }
@@ -744,8 +501,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
basic_regex(_FwdIter __first, _FwdIter __last,
flag_type __f = ECMAScript)
: _M_flags(__f),
- _M_automaton(__detail::_Compiler<_FwdIter, _Ch_type, _Rx_traits>
- (__first, __last, _M_traits, _M_flags)._M_get_nfa())
+ _M_automaton(__detail::__compile_nfa(__first, __last, _M_traits,
+ _M_flags))
{ }
/**
@@ -756,8 +513,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*
* @throws regex_error if @p __l is not a valid regular expression.
*/
- basic_regex(initializer_list<_Ch_type> __l,
- flag_type __f = ECMAScript)
+ basic_regex(initializer_list<_Ch_type> __l, flag_type __f = ECMAScript)
: basic_regex(__l.begin(), __l.end(), __f)
{ }
@@ -881,9 +637,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
flag_type __flags = ECMAScript)
{
_M_flags = __flags;
- _M_automaton =
- __detail::_Compiler<decltype(__s.begin()), _Ch_type, _Rx_traits>
- (__s.begin(), __s.end(), _M_traits, _M_flags)._M_get_nfa();
+ _M_automaton = __detail::__compile_nfa(__s.begin(), __s.end(),
+ _M_traits, _M_flags);
return *this;
}
@@ -977,42 +732,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#endif
protected:
- typedef std::shared_ptr<__detail::_Automaton<_Ch_type, _Rx_traits>>
- _AutomatonPtr;
-
- template<typename _BiIter, typename _Alloc,
- typename _CharT, typename _TraitsT>
- friend std::unique_ptr<
- __detail::_Executor<_BiIter, _Alloc, _CharT, _TraitsT>>
- __detail::__get_executor(_BiIter,
- _BiIter,
- match_results<_BiIter, _Alloc>&,
- const basic_regex<_CharT, _TraitsT>&,
- regex_constants::match_flag_type);
-
- template<typename _Bp, typename _Ap, typename _Cp, typename _Rp>
- friend bool
- regex_match(_Bp, _Bp,
- match_results<_Bp, _Ap>&,
- const basic_regex<_Cp, _Rp>&,
- regex_constants::match_flag_type);
+ typedef std::shared_ptr<__detail::_NFA<_Rx_traits>> _AutomatonPtr;
- template<typename _Bp, typename _Ap, typename _Cp, typename _Rp>
+ template<typename _Bp, typename _Ap, typename _Cp, typename _Rp,
+ __detail::_RegexExecutorPolicy, bool>
friend bool
- regex_search(_Bp, _Bp,
- match_results<_Bp, _Ap>&,
- const basic_regex<_Cp, _Rp>&,
- regex_constants::match_flag_type);
+ __detail::__regex_algo_impl(_Bp, _Bp, match_results<_Bp, _Ap>&,
+ const basic_regex<_Cp, _Rp>&,
+ regex_constants::match_flag_type);
- template<typename, typename, typename, typename>
+ template<typename, typename, typename, bool>
friend class __detail::_Executor;
- template<typename, typename, typename, typename>
- friend class __detail::_DFSExecutor;
-
- template<typename, typename, typename, typename>
- friend class __detail::_BFSExecutor;
-
flag_type _M_flags;
_Rx_traits _M_traits;
_AutomatonPtr _M_automaton;
@@ -1766,17 +1497,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* @name 10.? Public Types
*/
//@{
- typedef _Alloc allocator_type;
typedef sub_match<_Bi_iter> value_type;
typedef const value_type& const_reference;
typedef const_reference reference;
typedef typename _Base_type::const_iterator const_iterator;
typedef const_iterator iterator;
typedef typename __iter_traits::difference_type difference_type;
- typedef typename __iter_traits::value_type char_type;
typedef typename allocator_traits<_Alloc>::size_type size_type;
-
-
+ typedef _Alloc allocator_type;
+ typedef typename __iter_traits::value_type char_type;
typedef std::basic_string<char_type> string_type;
//@}
@@ -2002,21 +1731,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*/
const_iterator
cbegin() const
- { return _Base_type::cbegin(); }
+ { return _Base_type::cbegin() + 2; }
/**
* @brief Gets an iterator to one-past-the-end of the collection.
*/
const_iterator
end() const
- { return !empty() ? _Base_type::end() - 2 : _Base_type::end(); }
+ { return _Base_type::end() - 2; }
/**
* @brief Gets an iterator to one-past-the-end of the collection.
*/
const_iterator
cend() const
- { return end(); }
+ { return _Base_type::cend(); }
//@}
@@ -2032,14 +1761,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/**
* @pre ready() == true
- * @todo Implement this function.
*/
template<typename _Out_iter>
_Out_iter
format(_Out_iter __out, const char_type* __fmt_first,
const char_type* __fmt_last,
- match_flag_type __flags = regex_constants::format_default) const
- { return __out; }
+ match_flag_type __flags = regex_constants::format_default) const;
/**
* @pre ready() == true
@@ -2111,33 +1838,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
//@}
private:
- template<typename, typename, typename, typename>
+ template<typename, typename, typename, bool>
friend class __detail::_Executor;
- template<typename, typename, typename, typename>
- friend class __detail::_DFSExecutor;
-
- template<typename, typename, typename, typename>
- friend class __detail::_BFSExecutor;
-
template<typename, typename, typename>
friend class regex_iterator;
- template<typename _Bp, typename _Ap,
- typename _Ch_type, typename _Rx_traits>
- friend bool
- regex_match(_Bp, _Bp, match_results<_Bp, _Ap>&,
- const basic_regex<_Ch_type,
- _Rx_traits>&,
- regex_constants::match_flag_type);
-
- template<typename _Bp, typename _Ap,
- typename _Ch_type, typename _Rx_traits>
+ template<typename _Bp, typename _Ap, typename _Cp, typename _Rp,
+ __detail::_RegexExecutorPolicy, bool>
friend bool
- regex_search(_Bp, _Bp, match_results<_Bp, _Ap>&,
- const basic_regex<_Ch_type,
- _Rx_traits>&,
- regex_constants::match_flag_type);
+ __detail::__regex_algo_impl(_Bp, _Bp, match_results<_Bp, _Ap>&,
+ const basic_regex<_Cp, _Rp>&,
+ regex_constants::match_flag_type);
_Bi_iter _M_begin;
bool _M_in_iterator;
@@ -2223,7 +1935,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*/
template<typename _Bi_iter, typename _Alloc,
typename _Ch_type, typename _Rx_traits>
- bool
+ inline bool
regex_match(_Bi_iter __s,
_Bi_iter __e,
match_results<_Bi_iter, _Alloc>& __m,
@@ -2231,29 +1943,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
regex_constants::match_flag_type __flags
= regex_constants::match_default)
{
- if (__re._M_automaton == nullptr)
- return false;
-
- auto __size = __re._M_automaton->_M_sub_count();
- __size += 2;
- __m.resize(__size);
- for (decltype(__size) __i = 0; __i < __size; ++__i)
- __m.at(__i).matched = false;
-
- if (__detail::__get_executor(__s, __e, __m, __re, __flags)->_M_match())
- {
- for (auto __it : __m)
- if (!__it.matched)
- __it.first = __it.second = __e;
- __m.at(__m.size()).matched = false;
- __m.at(__m.size()).first = __s;
- __m.at(__m.size()).second = __s;
- __m.at(__m.size()+1).matched = false;
- __m.at(__m.size()+1).first = __e;
- __m.at(__m.size()+1).second = __e;
- return true;
- }
- return false;
+ return __detail::__regex_algo_impl<_Bi_iter, _Alloc, _Ch_type, _Rx_traits,
+ __detail::_RegexExecutorPolicy::_S_auto, true>
+ (__s, __e, __m, __re, __flags);
}
/**
@@ -2271,7 +1963,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* @throws an exception of type regex_error.
*/
template<typename _Bi_iter, typename _Ch_type, typename _Rx_traits>
- bool
+ inline bool
regex_match(_Bi_iter __first, _Bi_iter __last,
const basic_regex<_Ch_type, _Rx_traits>& __re,
regex_constants::match_flag_type __flags
@@ -2389,38 +2081,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Bi_iter, typename _Alloc,
typename _Ch_type, typename _Rx_traits>
inline bool
- regex_search(_Bi_iter __first, _Bi_iter __last,
+ regex_search(_Bi_iter __s, _Bi_iter __e,
match_results<_Bi_iter, _Alloc>& __m,
const basic_regex<_Ch_type, _Rx_traits>& __re,
regex_constants::match_flag_type __flags
= regex_constants::match_default)
{
- if (__re._M_automaton == nullptr)
- return false;
-
- auto __size = __re._M_automaton->_M_sub_count();
- __size += 2;
- __m.resize(__size);
- for (decltype(__size) __i = 0; __i < __size; ++__i)
- __m.at(__i).matched = false;
-
- if (__detail::__get_executor(__first, __last, __m, __re, __flags)
- ->_M_search())
- {
- for (auto __it : __m)
- if (!__it.matched)
- __it.first = __it.second = __last;
- __m.at(__m.size()).first = __first;
- __m.at(__m.size()).second = __m[0].first;
- __m.at(__m.size()+1).first = __m[0].second;
- __m.at(__m.size()+1).second = __last;
- __m.at(__m.size()).matched =
- (__m.prefix().first != __m.prefix().second);
- __m.at(__m.size()+1).matched =
- (__m.suffix().first != __m.suffix().second);
- return true;
- }
- return false;
+ return __detail::__regex_algo_impl<_Bi_iter, _Alloc, _Ch_type, _Rx_traits,
+ __detail::_RegexExecutorPolicy::_S_auto, false>
+ (__s, __e, __m, __re, __flags);
}
/**
@@ -2530,51 +2199,155 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// std [28.11.4] Function template regex_replace
/**
- * @doctodo
- * @param __out
- * @param __first
- * @param __last
- * @param __e
- * @param __fmt
- * @param __flags
+ * @brief Search for a regular expression within a range for multiple times,
+ and replace the matched parts through filling a format string.
+ * @param __out [OUT] The output iterator.
+ * @param __first [IN] The start of the string to search.
+ * @param __last [IN] One-past-the-end of the string to search.
+ * @param __e [IN] The regular expression to search for.
+ * @param __fmt [IN] The format string.
+ * @param __flags [IN] Search and replace policy flags.
*
- * @returns out
+ * @returns __out
* @throws an exception of type regex_error.
+ */
+ template<typename _Out_iter, typename _Bi_iter,
+ typename _Rx_traits, typename _Ch_type,
+ typename _St, typename _Sa>
+ inline _Out_iter
+ regex_replace(_Out_iter __out, _Bi_iter __first, _Bi_iter __last,
+ const basic_regex<_Ch_type, _Rx_traits>& __e,
+ const basic_string<_Ch_type, _St, _Sa>& __fmt,
+ regex_constants::match_flag_type __flags
+ = regex_constants::match_default)
+ {
+ return regex_replace(__out, __first, __last, __e, __fmt.c_str(), __flags);
+ }
+
+ /**
+ * @brief Search for a regular expression within a range for multiple times,
+ and replace the matched parts through filling a format C-string.
+ * @param __out [OUT] The output iterator.
+ * @param __first [IN] The start of the string to search.
+ * @param __last [IN] One-past-the-end of the string to search.
+ * @param __e [IN] The regular expression to search for.
+ * @param __fmt [IN] The format C-string.
+ * @param __flags [IN] Search and replace policy flags.
*
- * @todo Implement this function.
+ * @returns __out
+ * @throws an exception of type regex_error.
*/
template<typename _Out_iter, typename _Bi_iter,
typename _Rx_traits, typename _Ch_type>
- inline _Out_iter
+ _Out_iter
regex_replace(_Out_iter __out, _Bi_iter __first, _Bi_iter __last,
const basic_regex<_Ch_type, _Rx_traits>& __e,
- const basic_string<_Ch_type>& __fmt,
+ const _Ch_type* __fmt,
+ regex_constants::match_flag_type __flags
+ = regex_constants::match_default);
+
+ /**
+ * @brief Search for a regular expression within a string for multiple times,
+ and replace the matched parts through filling a format string.
+ * @param __s [IN] The string to search and replace.
+ * @param __e [IN] The regular expression to search for.
+ * @param __fmt [IN] The format string.
+ * @param __flags [IN] Search and replace policy flags.
+ *
+ * @returns The string after replacing.
+ * @throws an exception of type regex_error.
+ */
+ template<typename _Rx_traits, typename _Ch_type,
+ typename _St, typename _Sa, typename _Fst, typename _Fsa>
+ inline basic_string<_Ch_type, _St, _Sa>
+ regex_replace(const basic_string<_Ch_type, _St, _Sa>& __s,
+ const basic_regex<_Ch_type, _Rx_traits>& __e,
+ const basic_string<_Ch_type, _Fst, _Fsa>& __fmt,
regex_constants::match_flag_type __flags
= regex_constants::match_default)
- { return __out; }
+ {
+ basic_string<_Ch_type, _St, _Sa> __result;
+ regex_replace(std::back_inserter(__result),
+ __s.begin(), __s.end(), __e, __fmt, __flags);
+ return __result;
+ }
/**
- * @doctodo
- * @param __s
- * @param __e
- * @param __fmt
- * @param __flags
+ * @brief Search for a regular expression within a string for multiple times,
+ and replace the matched parts through filling a format C-string.
+ * @param __s [IN] The string to search and replace.
+ * @param __e [IN] The regular expression to search for.
+ * @param __fmt [IN] The format C-string.
+ * @param __flags [IN] Search and replace policy flags.
*
- * @returns a copy of string @p s with replacements.
+ * @returns The string after replacing.
+ * @throws an exception of type regex_error.
+ */
+ template<typename _Rx_traits, typename _Ch_type,
+ typename _St, typename _Sa>
+ inline basic_string<_Ch_type, _St, _Sa>
+ regex_replace(const basic_string<_Ch_type, _St, _Sa>& __s,
+ const basic_regex<_Ch_type, _Rx_traits>& __e,
+ const _Ch_type* __fmt,
+ regex_constants::match_flag_type __flags
+ = regex_constants::match_default)
+ {
+ basic_string<_Ch_type, _St, _Sa> __result;
+ regex_replace(std::back_inserter(__result),
+ __s.begin(), __s.end(), __e, __fmt, __flags);
+ return __result;
+ }
+
+ /**
+ * @brief Search for a regular expression within a C-string for multiple
+ times, and replace the matched parts through filling a format string.
+ * @param __s [IN] The C-string to search and replace.
+ * @param __e [IN] The regular expression to search for.
+ * @param __fmt [IN] The format string.
+ * @param __flags [IN] Search and replace policy flags.
+ *
+ * @returns The string after replacing.
+ * @throws an exception of type regex_error.
+ */
+ template<typename _Rx_traits, typename _Ch_type,
+ typename _St, typename _Sa>
+ inline basic_string<_Ch_type>
+ regex_replace(const _Ch_type* __s,
+ const basic_regex<_Ch_type, _Rx_traits>& __e,
+ const basic_string<_Ch_type, _St, _Sa>& __fmt,
+ regex_constants::match_flag_type __flags
+ = regex_constants::match_default)
+ {
+ basic_string<_Ch_type> __result;
+ regex_replace(std::back_inserter(__result), __s,
+ __s + char_traits<_Ch_type>::length(__s),
+ __e, __fmt, __flags);
+ return __result;
+ }
+
+ /**
+ * @brief Search for a regular expression within a C-string for multiple
+ times, and replace the matched parts through filling a format C-string.
+ * @param __s [IN] The C-string to search and replace.
+ * @param __e [IN] The regular expression to search for.
+ * @param __fmt [IN] The format C-string.
+ * @param __flags [IN] Search and replace policy flags.
*
+ * @returns The string after replacing.
* @throws an exception of type regex_error.
*/
template<typename _Rx_traits, typename _Ch_type>
inline basic_string<_Ch_type>
- regex_replace(const basic_string<_Ch_type>& __s,
+ regex_replace(const _Ch_type* __s,
const basic_regex<_Ch_type, _Rx_traits>& __e,
- const basic_string<_Ch_type>& __fmt,
+ const _Ch_type* __fmt,
regex_constants::match_flag_type __flags
= regex_constants::match_default)
{
basic_string<_Ch_type> __result;
- regex_replace(std::back_inserter(__result),
- __s.begin(), __s.end(), __e, __fmt, __flags);
+ regex_replace(std::back_inserter(__result), __s,
+ __s + char_traits<_Ch_type>::length(__s),
+ __e, __fmt, __flags);
return __result;
}
@@ -2685,68 +2458,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
match_results<_Bi_iter> _M_match;
};
- template<typename _Bi_iter,
- typename _Ch_type,
- typename _Rx_traits>
- bool
- regex_iterator<_Bi_iter, _Ch_type, _Rx_traits>::
- operator==(const regex_iterator& __rhs) const
- {
- return (_M_match.empty() && __rhs._M_match.empty())
- || (_M_begin == __rhs._M_begin
- && _M_end == __rhs._M_end
- && _M_pregex == __rhs._M_pregex
- && _M_flags == __rhs._M_flags
- && _M_match[0] == __rhs._M_match[0]);
- }
-
- template<typename _Bi_iter,
- typename _Ch_type,
- typename _Rx_traits>
- regex_iterator<_Bi_iter, _Ch_type, _Rx_traits>&
- regex_iterator<_Bi_iter, _Ch_type, _Rx_traits>::
- operator++()
- {
- // In all cases in which the call to regex_search returns true,
- // match.prefix().first shall be equal to the previous value of
- // match[0].second, and for each index i in the half-open range
- // [0, match.size()) for which match[i].matched is true,
- // match[i].position() shall return distance(begin, match[i].first).
- // [28.12.1.4.5]
- if (_M_match[0].matched)
- {
- auto __start = _M_match[0].second;
- if (_M_match[0].first == _M_match[0].second)
- if (__start == _M_end)
- {
- _M_match = value_type();
- return *this;
- }
- else
- {
- if (regex_search(__start, _M_end, _M_match, *_M_pregex, _M_flags
- | regex_constants::match_not_null
- | regex_constants::match_continuous))
- {
- _M_match._M_in_iterator = true;
- _M_match._M_begin = _M_begin;
- return *this;
- }
- else
- ++__start;
- }
- _M_flags |= regex_constants::match_prev_avail;
- if (regex_search(__start, _M_end, _M_match, *_M_pregex, _M_flags))
- {
- _M_match._M_in_iterator = true;
- _M_match._M_begin = _M_begin;
- }
- else
- _M_match = value_type();
- }
- return *this;
- }
-
typedef regex_iterator<const char*> cregex_iterator;
typedef regex_iterator<string::const_iterator> sregex_iterator;
#ifdef _GLIBCXX_USE_WCHAR_T
@@ -2784,7 +2495,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* iterator of the same type.
*/
regex_token_iterator()
- : _M_position(), _M_result(nullptr), _M_suffix(), _M_n(0), _M_subs()
+ : _M_position(), _M_subs(), _M_suffix(), _M_n(0), _M_result(nullptr),
+ _M_has_m1(false)
{ }
/**
@@ -2869,8 +2581,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* @param __rhs [IN] A %regex_token_iterator to copy.
*/
regex_token_iterator(const regex_token_iterator& __rhs)
- : _M_position(__rhs.position), _M_subs(__rhs.subs), _M_n(__rhs.N),
- _M_result(__rhs.result), _M_suffix(__rhs.suffix),
+ : _M_position(__rhs._M_position), _M_subs(__rhs._M_subs),
+ _M_suffix(__rhs._M_suffix), _M_n(__rhs._M_n), _M_result(__rhs._M_result),
_M_has_m1(__rhs._M_has_m1)
{
if (__rhs._M_result == &__rhs._M_suffix)
@@ -2947,114 +2659,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_end_of_seq()
{ return _M_result == nullptr; }
- _Position _M_position;
- const value_type* _M_result;
+ _Position _M_position;
+ std::vector<int> _M_subs;
value_type _M_suffix;
std::size_t _M_n;
- std::vector<int> _M_subs;
+ const value_type* _M_result;
// Show whether _M_subs contains -1
bool _M_has_m1;
};
- template<typename _Bi_iter,
- typename _Ch_type,
- typename _Rx_traits>
- regex_token_iterator<_Bi_iter, _Ch_type, _Rx_traits>&
- regex_token_iterator<_Bi_iter, _Ch_type, _Rx_traits>::
- operator=(const regex_token_iterator& __rhs)
- {
- _M_position = __rhs._M_position;
- _M_subs = __rhs._M_subs;
- _M_n = __rhs._M_n;
- _M_result = __rhs._M_result;
- _M_suffix = __rhs._M_suffix;
- _M_has_m1 = __rhs._M_has_m1;
- if (__rhs._M_result == &__rhs._M_suffix)
- _M_result = &_M_suffix;
- }
-
- template<typename _Bi_iter,
- typename _Ch_type,
- typename _Rx_traits>
- bool
- regex_token_iterator<_Bi_iter, _Ch_type, _Rx_traits>::
- operator==(const regex_token_iterator& __rhs) const
- {
- if (_M_end_of_seq() && __rhs._M_end_of_seq())
- return true;
- if (_M_suffix.matched && __rhs._M_suffix.matched
- && _M_suffix == __rhs._M_suffix)
- return true;
- if (_M_end_of_seq() || _M_suffix.matched
- || __rhs._M_end_of_seq() || __rhs._M_suffix.matched)
- return false;
- return _M_position == __rhs._M_position
- && _M_n == __rhs._M_n
- && _M_subs == __rhs._M_subs;
- }
-
- template<typename _Bi_iter,
- typename _Ch_type,
- typename _Rx_traits>
- regex_token_iterator<_Bi_iter, _Ch_type, _Rx_traits>&
- regex_token_iterator<_Bi_iter, _Ch_type, _Rx_traits>::
- operator++()
- {
- _Position __prev = _M_position;
- if (_M_suffix.matched)
- *this = regex_token_iterator();
- else if (_M_n + 1 < _M_subs.size())
- {
- _M_n++;
- _M_result = &_M_current_match();
- }
- else
- {
- _M_n = 0;
- ++_M_position;
- if (_M_position != _Position())
- _M_result = &_M_current_match();
- else if (_M_has_m1 && __prev->suffix().length() != 0)
- {
- _M_suffix.matched = true;
- _M_suffix.first = __prev->suffix().first;
- _M_suffix.second = __prev->suffix().second;
- _M_result = &_M_suffix;
- }
- else
- *this = regex_token_iterator();
- }
- return *this;
- }
-
- template<typename _Bi_iter,
- typename _Ch_type,
- typename _Rx_traits>
- void
- regex_token_iterator<_Bi_iter, _Ch_type, _Rx_traits>::
- _M_init(_Bi_iter __a, _Bi_iter __b)
- {
- _M_has_m1 = false;
- for (auto __it : _M_subs)
- if (__it == -1)
- {
- _M_has_m1 = true;
- break;
- }
- if (_M_position != _Position())
- _M_result = &_M_current_match();
- else if (_M_has_m1)
- {
- _M_suffix.matched = true;
- _M_suffix.first = __a;
- _M_suffix.second = __b;
- _M_result = &_M_suffix;
- }
- else
- _M_result = nullptr;
- }
-
/** @brief Token iterator for C-style NULL-terminated strings. */
typedef regex_token_iterator<const char*> cregex_token_iterator;
@@ -3073,3 +2687,4 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace
+#include <bits/regex.tcc>
diff --git a/libstdc++-v3/include/bits/regex.tcc b/libstdc++-v3/include/bits/regex.tcc
new file mode 100644
index 00000000000..2ac095d9881
--- /dev/null
+++ b/libstdc++-v3/include/bits/regex.tcc
@@ -0,0 +1,709 @@
+// class template regex -*- C++ -*-
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// 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/>.
+
+/**
+ * @file bits/regex.tcc
+ * This is an internal header file, included by other library headers.
+ * Do not attempt to use it directly. @headername{regex}
+ */
+
+// See below __regex_algo_impl to get what this is talking about. The default
+// value 1 indicated a conservative optimization without giving up worst case
+// performance.
+#ifndef _GLIBCXX_REGEX_DFS_QUANTIFIERS_LIMIT
+#define _GLIBCXX_REGEX_DFS_QUANTIFIERS_LIMIT 1
+#endif
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+namespace __detail
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ // Result of merging regex_match and regex_search.
+ //
+ // __policy now can be _S_auto (auto dispatch) and _S_alternate (use
+ // the other one if possible, for test purpose).
+ //
+ // That __match_mode is true means regex_match, else regex_search.
+ template<typename _BiIter, typename _Alloc,
+ typename _CharT, typename _TraitsT,
+ _RegexExecutorPolicy __policy,
+ bool __match_mode>
+ bool
+ __regex_algo_impl(_BiIter __s,
+ _BiIter __e,
+ match_results<_BiIter, _Alloc>& __m,
+ const basic_regex<_CharT, _TraitsT>& __re,
+ regex_constants::match_flag_type __flags)
+ {
+ if (__re._M_automaton == nullptr)
+ return false;
+
+ typename match_results<_BiIter, _Alloc>::_Base_type& __res = __m;
+ __res.resize(__re._M_automaton->_M_sub_count() + 2);
+ for (auto& __it : __res)
+ __it.matched = false;
+
+ // This function decide which executor to use under given circumstances.
+ // The _S_auto policy now is the following: if a NFA has no
+ // back-references and has more than _GLIBCXX_REGEX_DFS_QUANTIFIERS_LIMIT
+ // quantifiers (*, +, ?), the BFS executor will be used, other wise
+ // DFS executor. This is because DFS executor has a exponential upper
+ // bound, but better best-case performace. Meanwhile, BFS executor can
+ // effectively prevent from exponential-long time matching (which must
+ // contains many quantifiers), but it's slower in average.
+ //
+ // For simple regex, BFS executor could be 2 or more times slower than
+ // DFS executor.
+ //
+ // Of course, BFS executor cannot handle back-references.
+ bool __ret;
+ if (!__re._M_automaton->_M_has_backref
+ && (__policy == _RegexExecutorPolicy::_S_alternate
+ || __re._M_automaton->_M_quant_count
+ > _GLIBCXX_REGEX_DFS_QUANTIFIERS_LIMIT))
+ {
+ _Executor<_BiIter, _Alloc, _TraitsT, false>
+ __executor(__s, __e, __m, __re, __flags);
+ if (__match_mode)
+ __ret = __executor._M_match();
+ else
+ __ret = __executor._M_search();
+ }
+ else
+ {
+ _Executor<_BiIter, _Alloc, _TraitsT, true>
+ __executor(__s, __e, __m, __re, __flags);
+ if (__match_mode)
+ __ret = __executor._M_match();
+ else
+ __ret = __executor._M_search();
+ }
+ if (__ret)
+ {
+ for (auto __it : __res)
+ if (!__it.matched)
+ __it.first = __it.second = __e;
+ auto& __pre = __res[__res.size()-2];
+ auto& __suf = __res[__res.size()-1];
+ if (__match_mode)
+ {
+ __pre.matched = false;
+ __pre.first = __s;
+ __pre.second = __s;
+ __suf.matched = false;
+ __suf.first = __e;
+ __suf.second = __e;
+ }
+ else
+ {
+ __pre.first = __s;
+ __pre.second = __res[0].first;
+ __pre.matched = (__pre.first != __pre.second);
+ __suf.first = __res[0].second;
+ __suf.second = __e;
+ __suf.matched = (__suf.first != __suf.second);
+ }
+ if (__re.flags() & regex_constants::nosubs)
+ __res.resize(3);
+ }
+ return __ret;
+ }
+
+_GLIBCXX_END_NAMESPACE_VERSION
+}
+
+ template<typename _Ch_type>
+ template<typename _Fwd_iter>
+ typename regex_traits<_Ch_type>::string_type
+ regex_traits<_Ch_type>::
+ lookup_collatename(_Fwd_iter __first, _Fwd_iter __last) const
+ {
+ typedef std::ctype<char_type> __ctype_type;
+ const __ctype_type& __fctyp(use_facet<__ctype_type>(_M_locale));
+
+ static const char* __collatenames[] =
+ {
+ "NUL",
+ "SOH",
+ "STX",
+ "ETX",
+ "EOT",
+ "ENQ",
+ "ACK",
+ "alert",
+ "backspace",
+ "tab",
+ "newline",
+ "vertical-tab",
+ "form-feed",
+ "carriage-return",
+ "SO",
+ "SI",
+ "DLE",
+ "DC1",
+ "DC2",
+ "DC3",
+ "DC4",
+ "NAK",
+ "SYN",
+ "ETB",
+ "CAN",
+ "EM",
+ "SUB",
+ "ESC",
+ "IS4",
+ "IS3",
+ "IS2",
+ "IS1",
+ "space",
+ "exclamation-mark",
+ "quotation-mark",
+ "number-sign",
+ "dollar-sign",
+ "percent-sign",
+ "ampersand",
+ "apostrophe",
+ "left-parenthesis",
+ "right-parenthesis",
+ "asterisk",
+ "plus-sign",
+ "comma",
+ "hyphen",
+ "period",
+ "slash",
+ "zero",
+ "one",
+ "two",
+ "three",
+ "four",
+ "five",
+ "six",
+ "seven",
+ "eight",
+ "nine",
+ "colon",
+ "semicolon",
+ "less-than-sign",
+ "equals-sign",
+ "greater-than-sign",
+ "question-mark",
+ "commercial-at",
+ "A",
+ "B",
+ "C",
+ "D",
+ "E",
+ "F",
+ "G",
+ "H",
+ "I",
+ "J",
+ "K",
+ "L",
+ "M",
+ "N",
+ "O",
+ "P",
+ "Q",
+ "R",
+ "S",
+ "T",
+ "U",
+ "V",
+ "W",
+ "X",
+ "Y",
+ "Z",
+ "left-square-bracket",
+ "backslash",
+ "right-square-bracket",
+ "circumflex",
+ "underscore",
+ "grave-accent",
+ "a",
+ "b",
+ "c",
+ "d",
+ "e",
+ "f",
+ "g",
+ "h",
+ "i",
+ "j",
+ "k",
+ "l",
+ "m",
+ "n",
+ "o",
+ "p",
+ "q",
+ "r",
+ "s",
+ "t",
+ "u",
+ "v",
+ "w",
+ "x",
+ "y",
+ "z",
+ "left-curly-bracket",
+ "vertical-line",
+ "right-curly-bracket",
+ "tilde",
+ "DEL",
+ ""
+ };
+
+ // same as boost
+ //static const char* __digraphs[] =
+ // {
+ // "ae",
+ // "Ae",
+ // "AE",
+ // "ch",
+ // "Ch",
+ // "CH",
+ // "ll",
+ // "Ll",
+ // "LL",
+ // "ss",
+ // "Ss",
+ // "SS",
+ // "nj",
+ // "Nj",
+ // "NJ",
+ // "dz",
+ // "Dz",
+ // "DZ",
+ // "lj",
+ // "Lj",
+ // "LJ",
+ // ""
+ // };
+
+ std::string __s(__last - __first, '?');
+ __fctyp.narrow(__first, __last, '?', &*__s.begin());
+
+ for (unsigned int __i = 0; *__collatenames[__i]; __i++)
+ if (__s == __collatenames[__i])
+ return string_type(1, __fctyp.widen(static_cast<char>(__i)));
+
+ //for (unsigned int __i = 0; *__digraphs[__i]; __i++)
+ // {
+ // const char* __now = __digraphs[__i];
+ // if (__s == __now)
+ // {
+ // string_type ret(__s.size(), __fctyp.widen('?'));
+ // __fctyp.widen(__now, __now + 2/* ouch */, &*ret.begin());
+ // return ret;
+ // }
+ // }
+ return string_type();
+ }
+
+ template<typename _Ch_type>
+ template<typename _Fwd_iter>
+ typename regex_traits<_Ch_type>::char_class_type
+ regex_traits<_Ch_type>::
+ lookup_classname(_Fwd_iter __first, _Fwd_iter __last, bool __icase) const
+ {
+ typedef std::ctype<char_type> __ctype_type;
+ typedef std::ctype<char> __cctype_type;
+ typedef const pair<const char*, char_class_type> _ClassnameEntry;
+ const __ctype_type& __fctyp(use_facet<__ctype_type>(_M_locale));
+ const __cctype_type& __cctyp(use_facet<__cctype_type>(_M_locale));
+
+ static _ClassnameEntry __classnames[] =
+ {
+ {"d", ctype_base::digit},
+ {"w", {ctype_base::alnum, _RegexMask::_S_under}},
+ {"s", ctype_base::space},
+ {"alnum", ctype_base::alnum},
+ {"alpha", ctype_base::alpha},
+ {"blank", {0, _RegexMask::_S_blank}},
+ {"cntrl", ctype_base::cntrl},
+ {"digit", ctype_base::digit},
+ {"graph", ctype_base::graph},
+ {"lower", ctype_base::lower},
+ {"print", ctype_base::print},
+ {"punct", ctype_base::punct},
+ {"space", ctype_base::space},
+ {"upper", ctype_base::upper},
+ {"xdigit", ctype_base::xdigit},
+ };
+
+ std::string __s(__last - __first, '?');
+ __fctyp.narrow(__first, __last, '?', &__s[0]);
+ __cctyp.tolower(&*__s.begin(), &*__s.begin() + __s.size());
+ for (_ClassnameEntry* __it = __classnames;
+ __it < *(&__classnames + 1);
+ ++__it)
+ {
+ if (__s == __it->first)
+ {
+ if (__icase
+ && ((__it->second
+ & (ctype_base::lower | ctype_base::upper)) != 0))
+ return ctype_base::alpha;
+ return __it->second;
+ }
+ }
+ return 0;
+ }
+
+ template<typename _Ch_type>
+ bool
+ regex_traits<_Ch_type>::
+ isctype(_Ch_type __c, char_class_type __f) const
+ {
+ typedef std::ctype<char_type> __ctype_type;
+ const __ctype_type& __fctyp(use_facet<__ctype_type>(_M_locale));
+
+ return __fctyp.is(__f._M_base, __c)
+ // [[:w:]]
+ || ((__f._M_extended & _RegexMask::_S_under)
+ && __c == __fctyp.widen('_'))
+ // [[:blank:]]
+ || ((__f._M_extended & _RegexMask::_S_blank)
+ && (__c == __fctyp.widen(' ')
+ || __c == __fctyp.widen('\t')));
+ }
+
+ template<typename _Ch_type>
+ int
+ regex_traits<_Ch_type>::
+ value(_Ch_type __ch, int __radix) const
+ {
+ std::basic_istringstream<char_type> __is(string_type(1, __ch));
+ long __v;
+ if (__radix == 8)
+ __is >> std::oct;
+ else if (__radix == 16)
+ __is >> std::hex;
+ __is >> __v;
+ return __is.fail() ? -1 : __v;
+ }
+
+ template<typename _Bi_iter, typename _Alloc>
+ template<typename _Out_iter>
+ _Out_iter match_results<_Bi_iter, _Alloc>::
+ format(_Out_iter __out,
+ const match_results<_Bi_iter, _Alloc>::char_type* __fmt_first,
+ const match_results<_Bi_iter, _Alloc>::char_type* __fmt_last,
+ match_flag_type __flags) const
+ {
+ _GLIBCXX_DEBUG_ASSERT( ready() );
+ regex_traits<char_type> __traits;
+ typedef std::ctype<char_type> __ctype_type;
+ const __ctype_type&
+ __fctyp(use_facet<__ctype_type>(__traits.getloc()));
+
+ auto __output = [&](size_t __idx)
+ {
+ auto& __sub = _Base_type::operator[](__idx);
+ if (__sub.matched)
+ std::copy(__sub.first, __sub.second, __out);
+ };
+
+ if (__flags & regex_constants::format_sed)
+ {
+ for (; __fmt_first != __fmt_last;)
+ if (*__fmt_first == '&')
+ {
+ __output(0);
+ ++__fmt_first;
+ }
+ else if (*__fmt_first == '\\')
+ {
+ if (++__fmt_first != __fmt_last
+ && __fctyp.is(__ctype_type::digit, *__fmt_first))
+ __output(__traits.value(*__fmt_first++, 10));
+ else
+ *__out++ = '\\';
+ }
+ else
+ *__out++ = *__fmt_first++;
+ }
+ else
+ {
+ while (1)
+ {
+ auto __next = std::find(__fmt_first, __fmt_last, '$');
+ if (__next == __fmt_last)
+ break;
+
+ std::copy(__fmt_first, __next, __out);
+
+ auto __eat = [&](char __ch) -> bool
+ {
+ if (*__next == __ch)
+ {
+ ++__next;
+ return true;
+ }
+ return false;
+ };
+
+ if (++__next == __fmt_last)
+ *__out++ = '$';
+ else if (__eat('$'))
+ *__out++ = '$';
+ else if (__eat('&'))
+ __output(0);
+ else if (__eat('`'))
+ __output(_Base_type::size()-2);
+ else if (__eat('\''))
+ __output(_Base_type::size()-1);
+ else if (__fctyp.is(__ctype_type::digit, *__next))
+ {
+ long __num = __traits.value(*__next, 10);
+ if (++__next != __fmt_last
+ && __fctyp.is(__ctype_type::digit, *__next))
+ {
+ __num *= 10;
+ __num += __traits.value(*__next++, 10);
+ }
+ if (0 <= __num && __num < this->size())
+ __output(__num);
+ }
+ else
+ *__out++ = '$';
+ __fmt_first = __next;
+ }
+ std::copy(__fmt_first, __fmt_last, __out);
+ }
+ return __out;
+ }
+
+ template<typename _Out_iter, typename _Bi_iter,
+ typename _Rx_traits, typename _Ch_type>
+ _Out_iter
+ regex_replace(_Out_iter __out, _Bi_iter __first, _Bi_iter __last,
+ const basic_regex<_Ch_type, _Rx_traits>& __e,
+ const _Ch_type* __fmt,
+ regex_constants::match_flag_type __flags)
+ {
+ typedef regex_iterator<_Bi_iter, _Ch_type, _Rx_traits> _IterT;
+ _IterT __i(__first, __last, __e, __flags);
+ _IterT __end;
+ if (__i == __end)
+ {
+ if (!(__flags & regex_constants::format_no_copy))
+ std::copy(__first, __last, __out);
+ }
+ else
+ {
+ sub_match<_Bi_iter> __last;
+ auto __len = char_traits<_Ch_type>::length(__fmt);
+ for (; __i != __end; ++__i)
+ {
+ if (!(__flags & regex_constants::format_no_copy))
+ std::copy(__i->prefix().first, __i->prefix().second, __out);
+ __out = __i->format(__out, __fmt, __fmt + __len, __flags);
+ __last = __i->suffix();
+ if (__flags & regex_constants::format_first_only)
+ break;
+ }
+ if (!(__flags & regex_constants::format_no_copy))
+ std::copy(__last.first, __last.second, __out);
+ }
+ return __out;
+ }
+
+ template<typename _Bi_iter,
+ typename _Ch_type,
+ typename _Rx_traits>
+ bool
+ regex_iterator<_Bi_iter, _Ch_type, _Rx_traits>::
+ operator==(const regex_iterator& __rhs) const
+ {
+ return (_M_match.empty() && __rhs._M_match.empty())
+ || (_M_begin == __rhs._M_begin
+ && _M_end == __rhs._M_end
+ && _M_pregex == __rhs._M_pregex
+ && _M_flags == __rhs._M_flags
+ && _M_match[0] == __rhs._M_match[0]);
+ }
+
+ template<typename _Bi_iter,
+ typename _Ch_type,
+ typename _Rx_traits>
+ regex_iterator<_Bi_iter, _Ch_type, _Rx_traits>&
+ regex_iterator<_Bi_iter, _Ch_type, _Rx_traits>::
+ operator++()
+ {
+ // In all cases in which the call to regex_search returns true,
+ // match.prefix().first shall be equal to the previous value of
+ // match[0].second, and for each index i in the half-open range
+ // [0, match.size()) for which match[i].matched is true,
+ // match[i].position() shall return distance(begin, match[i].first).
+ // [28.12.1.4.5]
+ if (_M_match[0].matched)
+ {
+ auto __start = _M_match[0].second;
+ auto __prefix_first = _M_match[0].second;
+ if (_M_match[0].first == _M_match[0].second)
+ {
+ if (__start == _M_end)
+ {
+ _M_match = value_type();
+ return *this;
+ }
+ else
+ {
+ if (regex_search(__start, _M_end, _M_match, *_M_pregex,
+ _M_flags
+ | regex_constants::match_not_null
+ | regex_constants::match_continuous))
+ {
+ _GLIBCXX_DEBUG_ASSERT(_M_match[0].matched);
+ _M_match.at(_M_match.size()).first = __prefix_first;
+ _M_match._M_in_iterator = true;
+ _M_match._M_begin = _M_begin;
+ return *this;
+ }
+ else
+ ++__start;
+ }
+ }
+ _M_flags |= regex_constants::match_prev_avail;
+ if (regex_search(__start, _M_end, _M_match, *_M_pregex, _M_flags))
+ {
+ _GLIBCXX_DEBUG_ASSERT(_M_match[0].matched);
+ _M_match.at(_M_match.size()).first = __prefix_first;
+ _M_match._M_in_iterator = true;
+ _M_match._M_begin = _M_begin;
+ }
+ else
+ _M_match = value_type();
+ }
+ return *this;
+ }
+
+ template<typename _Bi_iter,
+ typename _Ch_type,
+ typename _Rx_traits>
+ regex_token_iterator<_Bi_iter, _Ch_type, _Rx_traits>&
+ regex_token_iterator<_Bi_iter, _Ch_type, _Rx_traits>::
+ operator=(const regex_token_iterator& __rhs)
+ {
+ _M_position = __rhs._M_position;
+ _M_subs = __rhs._M_subs;
+ _M_n = __rhs._M_n;
+ _M_result = __rhs._M_result;
+ _M_suffix = __rhs._M_suffix;
+ _M_has_m1 = __rhs._M_has_m1;
+ if (__rhs._M_result == &__rhs._M_suffix)
+ _M_result = &_M_suffix;
+ return *this;
+ }
+
+ template<typename _Bi_iter,
+ typename _Ch_type,
+ typename _Rx_traits>
+ bool
+ regex_token_iterator<_Bi_iter, _Ch_type, _Rx_traits>::
+ operator==(const regex_token_iterator& __rhs) const
+ {
+ if (_M_end_of_seq() && __rhs._M_end_of_seq())
+ return true;
+ if (_M_suffix.matched && __rhs._M_suffix.matched
+ && _M_suffix == __rhs._M_suffix)
+ return true;
+ if (_M_end_of_seq() || _M_suffix.matched
+ || __rhs._M_end_of_seq() || __rhs._M_suffix.matched)
+ return false;
+ return _M_position == __rhs._M_position
+ && _M_n == __rhs._M_n
+ && _M_subs == __rhs._M_subs;
+ }
+
+ template<typename _Bi_iter,
+ typename _Ch_type,
+ typename _Rx_traits>
+ regex_token_iterator<_Bi_iter, _Ch_type, _Rx_traits>&
+ regex_token_iterator<_Bi_iter, _Ch_type, _Rx_traits>::
+ operator++()
+ {
+ _Position __prev = _M_position;
+ if (_M_suffix.matched)
+ *this = regex_token_iterator();
+ else if (_M_n + 1 < _M_subs.size())
+ {
+ _M_n++;
+ _M_result = &_M_current_match();
+ }
+ else
+ {
+ _M_n = 0;
+ ++_M_position;
+ if (_M_position != _Position())
+ _M_result = &_M_current_match();
+ else if (_M_has_m1 && __prev->suffix().length() != 0)
+ {
+ _M_suffix.matched = true;
+ _M_suffix.first = __prev->suffix().first;
+ _M_suffix.second = __prev->suffix().second;
+ _M_result = &_M_suffix;
+ }
+ else
+ *this = regex_token_iterator();
+ }
+ return *this;
+ }
+
+ template<typename _Bi_iter,
+ typename _Ch_type,
+ typename _Rx_traits>
+ void
+ regex_token_iterator<_Bi_iter, _Ch_type, _Rx_traits>::
+ _M_init(_Bi_iter __a, _Bi_iter __b)
+ {
+ _M_has_m1 = false;
+ for (auto __it : _M_subs)
+ if (__it == -1)
+ {
+ _M_has_m1 = true;
+ break;
+ }
+ if (_M_position != _Position())
+ _M_result = &_M_current_match();
+ else if (_M_has_m1)
+ {
+ _M_suffix.matched = true;
+ _M_suffix.first = __a;
+ _M_suffix.second = __b;
+ _M_result = &_M_suffix;
+ }
+ else
+ _M_result = nullptr;
+ }
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
+
diff --git a/libstdc++-v3/include/bits/regex_automaton.h b/libstdc++-v3/include/bits/regex_automaton.h
index 94a14ce96aa..1be51221ecd 100644
--- a/libstdc++-v3/include/bits/regex_automaton.h
+++ b/libstdc++-v3/include/bits/regex_automaton.h
@@ -40,7 +40,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* @{
*/
- typedef int _StateIdT;
+ typedef long _StateIdT;
typedef std::set<_StateIdT> _StateSet;
static const _StateIdT _S_invalid_state_id = -1;
@@ -49,14 +49,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/// Operation codes that define the type of transitions within the base NFA
/// that represents the regular expression.
- enum _Opcode
+ enum _Opcode : int
{
_S_opcode_unknown,
_S_opcode_alternative,
_S_opcode_backref,
_S_opcode_line_begin_assertion,
_S_opcode_line_end_assertion,
- _S_opcode_word_boundry,
+ _S_opcode_word_boundary,
_S_opcode_subexpr_lookahead,
_S_opcode_subexpr_begin,
_S_opcode_subexpr_end,
@@ -65,100 +65,114 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_S_opcode_accept,
};
- template<typename _CharT, typename _TraitsT>
- class _State
+ struct _State_base
+ {
+ _Opcode _M_opcode; // type of outgoing transition
+ _StateIdT _M_next; // outgoing transition
+ union // Since they are mutually exclusive.
{
- public:
- typedef int _OpcodeT;
- typedef _Matcher<_CharT> _MatcherT;
-
- _OpcodeT _M_opcode; // type of outgoing transition
- _StateIdT _M_next; // outgoing transition
- union // Since they are mutually exclusive.
+ size_t _M_subexpr; // for _S_opcode_subexpr_*
+ size_t _M_backref_index; // for _S_opcode_backref
+ struct
{
- unsigned int _M_subexpr; // for _S_opcode_subexpr_*
- unsigned int _M_backref_index; // for _S_opcode_backref
- struct
- {
- // for _S_opcode_alternative.
- _StateIdT _M_quant_index;
- // for _S_opcode_alternative or _S_opcode_subexpr_lookahead
- _StateIdT _M_alt;
- // for _S_opcode_word_boundry or _S_opcode_subexpr_lookahead or
- // quantifiers(ungreedy if set true)
- bool _M_neg;
- };
+ // for _S_opcode_alternative.
+ _StateIdT _M_quant_index;
+ // for _S_opcode_alternative or _S_opcode_subexpr_lookahead
+ _StateIdT _M_alt;
+ // for _S_opcode_word_boundary or _S_opcode_subexpr_lookahead or
+ // quantifiers (ungreedy if set true)
+ bool _M_neg;
};
- _MatcherT _M_matches; // for _S_opcode_match
+ };
- explicit _State(_OpcodeT __opcode)
- : _M_opcode(__opcode), _M_next(_S_invalid_state_id)
- { }
+ explicit _State_base(_Opcode __opcode)
+ : _M_opcode(__opcode), _M_next(_S_invalid_state_id)
+ { }
+
+ protected:
+ ~_State_base() = default;
+ public:
#ifdef _GLIBCXX_DEBUG
- std::ostream&
- _M_print(std::ostream& ostr) const;
+ std::ostream&
+ _M_print(std::ostream& ostr) const;
- // Prints graphviz dot commands for state.
- std::ostream&
- _M_dot(std::ostream& __ostr, _StateIdT __id) const;
+ // Prints graphviz dot commands for state.
+ std::ostream&
+ _M_dot(std::ostream& __ostr, _StateIdT __id) const;
#endif
- };
+ };
- /// Base class for, um, automata. Could be an NFA or a DFA. Your choice.
- template<typename _CharT, typename _TraitsT>
- class _Automaton
+ template<typename _TraitsT>
+ struct _State : _State_base
{
- public:
- typedef unsigned int _SizeT;
+ typedef _Matcher<typename _TraitsT::char_type> _MatcherT;
- public:
- virtual _SizeT
- _M_sub_count() const = 0;
+ _MatcherT _M_matches; // for _S_opcode_match
-#ifdef _GLIBCXX_DEBUG
- virtual std::ostream&
- _M_dot(std::ostream& __ostr) const = 0;
-#endif
+ explicit _State(_Opcode __opcode) : _State_base(__opcode) { }
};
- template<typename _CharT, typename _TraitsT>
- class _NFA
- : public _Automaton<_CharT, _TraitsT>,
- public std::vector<_State<_CharT, _TraitsT>>
- {
- public:
- typedef _State<_CharT, _TraitsT> _StateT;
- typedef const _Matcher<_CharT>& _MatcherT;
- typedef unsigned int _SizeT;
- typedef regex_constants::syntax_option_type _FlagT;
-
- _NFA(_FlagT __f)
- : _M_flags(__f), _M_start_state(0), _M_subexpr_count(0),
- _M_has_backref(false), _M_quant_count(0)
- { }
-
- _FlagT
- _M_options() const
- { return _M_flags; }
+ struct _NFA_base
+ {
+ typedef size_t _SizeT;
+ typedef regex_constants::syntax_option_type _FlagT;
+
+ explicit
+ _NFA_base(_FlagT __f)
+ : _M_flags(__f), _M_start_state(0), _M_subexpr_count(0),
+ _M_quant_count(0), _M_has_backref(false)
+ { }
+
+ _NFA_base(_NFA_base&&) = default;
+
+ protected:
+ ~_NFA_base() = default;
+
+ public:
+ _FlagT
+ _M_options() const
+ { return _M_flags; }
+
+ _StateIdT
+ _M_start() const
+ { return _M_start_state; }
+
+ const _StateSet&
+ _M_final_states() const
+ { return _M_accepting_states; }
+
+ _SizeT
+ _M_sub_count() const
+ { return _M_subexpr_count; }
+
+ std::vector<size_t> _M_paren_stack;
+ _StateSet _M_accepting_states;
+ _FlagT _M_flags;
+ _StateIdT _M_start_state;
+ _SizeT _M_subexpr_count;
+ _SizeT _M_quant_count;
+ bool _M_has_backref;
+ };
- _StateIdT
- _M_start() const
- { return _M_start_state; }
+ template<typename _TraitsT>
+ struct _NFA
+ : _NFA_base, std::vector<_State<_TraitsT>>
+ {
+ typedef _State<_TraitsT> _StateT;
+ typedef _Matcher<typename _TraitsT::char_type> _MatcherT;
- const _StateSet&
- _M_final_states() const
- { return _M_accepting_states; }
+ using _NFA_base::_NFA_base;
- _SizeT
- _M_sub_count() const
- { return _M_subexpr_count; }
+ // for performance reasons _NFA objects should only be moved not copied
+ _NFA(const _NFA&) = delete;
+ _NFA(_NFA&&) = default;
_StateIdT
_M_insert_accept()
{
auto __ret = _M_insert_state(_StateT(_S_opcode_accept));
- _M_accepting_states.insert(__ret);
+ this->_M_accepting_states.insert(__ret);
return __ret;
}
@@ -168,42 +182,42 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_StateT __tmp(_S_opcode_alternative);
// It labels every quantifier to make greedy comparison easier in BFS
// approach.
- __tmp._M_quant_index = _M_quant_count++;
+ __tmp._M_quant_index = this->_M_quant_count++;
__tmp._M_next = __next;
__tmp._M_alt = __alt;
__tmp._M_neg = __neg;
- return _M_insert_state(__tmp);
+ return _M_insert_state(std::move(__tmp));
}
_StateIdT
_M_insert_matcher(_MatcherT __m)
{
_StateT __tmp(_S_opcode_match);
- __tmp._M_matches = __m;
- return _M_insert_state(__tmp);
+ __tmp._M_matches = std::move(__m);
+ return _M_insert_state(std::move(__tmp));
}
_StateIdT
_M_insert_subexpr_begin()
{
- auto __id = _M_subexpr_count++;
- _M_paren_stack.push_back(__id);
+ auto __id = this->_M_subexpr_count++;
+ this->_M_paren_stack.push_back(__id);
_StateT __tmp(_S_opcode_subexpr_begin);
__tmp._M_subexpr = __id;
- return _M_insert_state(__tmp);
+ return _M_insert_state(std::move(__tmp));
}
_StateIdT
_M_insert_subexpr_end()
{
_StateT __tmp(_S_opcode_subexpr_end);
- __tmp._M_subexpr = _M_paren_stack.back();
- _M_paren_stack.pop_back();
- return _M_insert_state(__tmp);
+ __tmp._M_subexpr = this->_M_paren_stack.back();
+ this->_M_paren_stack.pop_back();
+ return _M_insert_state(std::move(__tmp));
}
_StateIdT
- _M_insert_backref(unsigned int __index);
+ _M_insert_backref(size_t __index);
_StateIdT
_M_insert_line_begin()
@@ -216,9 +230,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_StateIdT
_M_insert_word_bound(bool __neg)
{
- _StateT __tmp(_S_opcode_word_boundry);
+ _StateT __tmp(_S_opcode_word_boundary);
__tmp._M_neg = __neg;
- return _M_insert_state(__tmp);
+ return _M_insert_state(std::move(__tmp));
}
_StateIdT
@@ -227,7 +241,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_StateT __tmp(_S_opcode_subexpr_lookahead);
__tmp._M_alt = __alt;
__tmp._M_neg = __neg;
- return _M_insert_state(__tmp);
+ return _M_insert_state(std::move(__tmp));
}
_StateIdT
@@ -237,7 +251,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_StateIdT
_M_insert_state(_StateT __s)
{
- this->push_back(__s);
+ this->push_back(std::move(__s));
return this->size()-1;
}
@@ -249,28 +263,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
std::ostream&
_M_dot(std::ostream& __ostr) const;
#endif
-
- std::vector<unsigned int> _M_paren_stack;
- _StateSet _M_accepting_states;
- _FlagT _M_flags;
- _StateIdT _M_start_state;
- _SizeT _M_subexpr_count;
- _SizeT _M_quant_count;
- bool _M_has_backref;
};
/// Describes a sequence of one or more %_State, its current start
/// and end(s). This structure contains fragments of an NFA during
/// construction.
- template<typename _CharT, typename _TraitsT>
+ template<typename _TraitsT>
class _StateSeq
{
public:
- typedef _NFA<_CharT, _TraitsT> _RegexT;
+ typedef _NFA<_TraitsT> _RegexT;
public:
_StateSeq(_RegexT& __nfa, _StateIdT __s)
- : _StateSeq(__nfa, __s, __s)
+ : _M_nfa(__nfa), _M_start(__s), _M_end(__s)
{ }
_StateSeq(_RegexT& __nfa, _StateIdT __s, _StateIdT __end)
diff --git a/libstdc++-v3/include/bits/regex_automaton.tcc b/libstdc++-v3/include/bits/regex_automaton.tcc
index 13af984c273..b0734cf2988 100644
--- a/libstdc++-v3/include/bits/regex_automaton.tcc
+++ b/libstdc++-v3/include/bits/regex_automaton.tcc
@@ -35,118 +35,116 @@ namespace __detail
_GLIBCXX_BEGIN_NAMESPACE_VERSION
#ifdef _GLIBCXX_DEBUG
- template<typename _CharT, typename _TraitsT>
- std::ostream& _State<_CharT, _TraitsT>::
- _M_print(std::ostream& ostr) const
+ std::ostream&
+ _State_base::_M_print(std::ostream& ostr) const
+ {
+ switch (_M_opcode)
{
- switch (_M_opcode)
- {
- case _S_opcode_alternative:
- ostr << "alt next=" << _M_next << " alt=" << _M_alt;
- break;
- case _S_opcode_subexpr_begin:
- ostr << "subexpr begin next=" << _M_next << " index=" << _M_subexpr;
- break;
- case _S_opcode_subexpr_end:
- ostr << "subexpr end next=" << _M_next << " index=" << _M_subexpr;
- break;
- case _S_opcode_backref:
- ostr << "backref next=" << _M_next << " index=" << _M_backref_index;
- break;
- case _S_opcode_match:
- ostr << "match next=" << _M_next;
- break;
- case _S_opcode_accept:
- ostr << "accept next=" << _M_next;
- break;
- default:
- ostr << "unknown next=" << _M_next;
- break;
- }
- return ostr;
+ case _S_opcode_alternative:
+ ostr << "alt next=" << _M_next << " alt=" << _M_alt;
+ break;
+ case _S_opcode_subexpr_begin:
+ ostr << "subexpr begin next=" << _M_next << " index=" << _M_subexpr;
+ break;
+ case _S_opcode_subexpr_end:
+ ostr << "subexpr end next=" << _M_next << " index=" << _M_subexpr;
+ break;
+ case _S_opcode_backref:
+ ostr << "backref next=" << _M_next << " index=" << _M_backref_index;
+ break;
+ case _S_opcode_match:
+ ostr << "match next=" << _M_next;
+ break;
+ case _S_opcode_accept:
+ ostr << "accept next=" << _M_next;
+ break;
+ default:
+ ostr << "unknown next=" << _M_next;
+ break;
}
+ return ostr;
+ }
// Prints graphviz dot commands for state.
- template<typename _CharT, typename _TraitsT>
- std::ostream& _State<_CharT, _TraitsT>::
- _M_dot(std::ostream& __ostr, _StateIdT __id) const
+ std::ostream&
+ _State_base::_M_dot(std::ostream& __ostr, _StateIdT __id) const
+ {
+ switch (_M_opcode)
{
- switch (_M_opcode)
- {
- case _S_opcode_alternative:
- __ostr << __id << " [label=\"" << __id << "\\nALT\"];\n"
- << __id << " -> " << _M_next
- << " [label=\"epsilon\", tailport=\"s\"];\n"
- << __id << " -> " << _M_alt
- << " [label=\"epsilon\", tailport=\"n\"];\n";
- break;
- case _S_opcode_backref:
- __ostr << __id << " [label=\"" << __id << "\\nBACKREF "
- << _M_subexpr << "\"];\n"
- << __id << " -> " << _M_next << " [label=\"<match>\"];\n";
- break;
- case _S_opcode_line_begin_assertion:
- __ostr << __id << " [label=\"" << __id << "\\nLINE_BEGIN \"];\n"
- << __id << " -> " << _M_next << " [label=\"epsilon\"];\n";
- break;
- case _S_opcode_line_end_assertion:
- __ostr << __id << " [label=\"" << __id << "\\nLINE_END \"];\n"
- << __id << " -> " << _M_next << " [label=\"epsilon\"];\n";
- break;
- case _S_opcode_word_boundry:
- __ostr << __id << " [label=\"" << __id << "\\nWORD_BOUNDRY "
- << _M_neg << "\"];\n"
- << __id << " -> " << _M_next << " [label=\"epsilon\"];\n";
- break;
- case _S_opcode_subexpr_lookahead:
- __ostr << __id << " [label=\"" << __id << "\\nLOOK_AHEAD\"];\n"
- << __id << " -> " << _M_next
- << " [label=\"epsilon\", tailport=\"s\"];\n"
- << __id << " -> " << _M_alt
- << " [label=\"<assert>\", tailport=\"n\"];\n";
- break;
- case _S_opcode_subexpr_begin:
- __ostr << __id << " [label=\"" << __id << "\\nSBEGIN "
- << _M_subexpr << "\"];\n"
- << __id << " -> " << _M_next << " [label=\"epsilon\"];\n";
- break;
- case _S_opcode_subexpr_end:
- __ostr << __id << " [label=\"" << __id << "\\nSEND "
- << _M_subexpr << "\"];\n"
- << __id << " -> " << _M_next << " [label=\"epsilon\"];\n";
- break;
- case _S_opcode_dummy:
- break;
- case _S_opcode_match:
- __ostr << __id << " [label=\"" << __id << "\\nMATCH\"];\n"
- << __id << " -> " << _M_next << " [label=\"<match>\"];\n";
- break;
- case _S_opcode_accept:
- __ostr << __id << " [label=\"" << __id << "\\nACC\"];\n" ;
- break;
- default:
- _GLIBCXX_DEBUG_ASSERT(false);
- break;
- }
- return __ostr;
+ case _S_opcode_alternative:
+ __ostr << __id << " [label=\"" << __id << "\\nALT\"];\n"
+ << __id << " -> " << _M_next
+ << " [label=\"epsilon\", tailport=\"s\"];\n"
+ << __id << " -> " << _M_alt
+ << " [label=\"epsilon\", tailport=\"n\"];\n";
+ break;
+ case _S_opcode_backref:
+ __ostr << __id << " [label=\"" << __id << "\\nBACKREF "
+ << _M_subexpr << "\"];\n"
+ << __id << " -> " << _M_next << " [label=\"<match>\"];\n";
+ break;
+ case _S_opcode_line_begin_assertion:
+ __ostr << __id << " [label=\"" << __id << "\\nLINE_BEGIN \"];\n"
+ << __id << " -> " << _M_next << " [label=\"epsilon\"];\n";
+ break;
+ case _S_opcode_line_end_assertion:
+ __ostr << __id << " [label=\"" << __id << "\\nLINE_END \"];\n"
+ << __id << " -> " << _M_next << " [label=\"epsilon\"];\n";
+ break;
+ case _S_opcode_word_boundary:
+ __ostr << __id << " [label=\"" << __id << "\\nWORD_BOUNDRY "
+ << _M_neg << "\"];\n"
+ << __id << " -> " << _M_next << " [label=\"epsilon\"];\n";
+ break;
+ case _S_opcode_subexpr_lookahead:
+ __ostr << __id << " [label=\"" << __id << "\\nLOOK_AHEAD\"];\n"
+ << __id << " -> " << _M_next
+ << " [label=\"epsilon\", tailport=\"s\"];\n"
+ << __id << " -> " << _M_alt
+ << " [label=\"<assert>\", tailport=\"n\"];\n";
+ break;
+ case _S_opcode_subexpr_begin:
+ __ostr << __id << " [label=\"" << __id << "\\nSBEGIN "
+ << _M_subexpr << "\"];\n"
+ << __id << " -> " << _M_next << " [label=\"epsilon\"];\n";
+ break;
+ case _S_opcode_subexpr_end:
+ __ostr << __id << " [label=\"" << __id << "\\nSEND "
+ << _M_subexpr << "\"];\n"
+ << __id << " -> " << _M_next << " [label=\"epsilon\"];\n";
+ break;
+ case _S_opcode_dummy:
+ break;
+ case _S_opcode_match:
+ __ostr << __id << " [label=\"" << __id << "\\nMATCH\"];\n"
+ << __id << " -> " << _M_next << " [label=\"<match>\"];\n";
+ break;
+ case _S_opcode_accept:
+ __ostr << __id << " [label=\"" << __id << "\\nACC\"];\n" ;
+ break;
+ default:
+ _GLIBCXX_DEBUG_ASSERT(false);
+ break;
}
+ return __ostr;
+ }
- template<typename _CharT, typename _TraitsT>
- std::ostream& _NFA<_CharT, _TraitsT>::
- _M_dot(std::ostream& __ostr) const
+ template<typename _TraitsT>
+ std::ostream&
+ _NFA<_TraitsT>::_M_dot(std::ostream& __ostr) const
{
__ostr << "digraph _Nfa {\n"
- << " rankdir=LR;\n";
- for (unsigned int __i = 0; __i < this->size(); ++__i)
- { this->at(__i)._M_dot(__ostr, __i); }
+ " rankdir=LR;\n";
+ for (size_t __i = 0; __i < this->size(); ++__i)
+ (*this)[__i]._M_dot(__ostr, __i);
__ostr << "}\n";
return __ostr;
}
#endif
- template<typename _CharT, typename _TraitsT>
- _StateIdT _NFA<_CharT, _TraitsT>::
- _M_insert_backref(unsigned int __index)
+ template<typename _TraitsT>
+ _StateIdT
+ _NFA<_TraitsT>::_M_insert_backref(size_t __index)
{
// To figure out whether a backref is valid, a stack is used to store
// unfinished sub-expressions. For example, when parsing
@@ -157,25 +155,26 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// time, "\\2" is valid, but "\\1" and "\\3" are not.
if (__index >= _M_subexpr_count)
__throw_regex_error(regex_constants::error_backref);
- for (auto __it : _M_paren_stack)
+ for (auto __it : this->_M_paren_stack)
if (__index == __it)
__throw_regex_error(regex_constants::error_backref);
- _M_has_backref = true;
+ this->_M_has_backref = true;
_StateT __tmp(_S_opcode_backref);
__tmp._M_backref_index = __index;
- return _M_insert_state(__tmp);
+ return _M_insert_state(std::move(__tmp));
}
- template<typename _CharT, typename _TraitsT>
- void _NFA<_CharT, _TraitsT>::
- _M_eliminate_dummy()
+ template<typename _TraitsT>
+ void
+ _NFA<_TraitsT>::_M_eliminate_dummy()
{
for (auto& __it : *this)
{
while (__it._M_next >= 0 && (*this)[__it._M_next]._M_opcode
== _S_opcode_dummy)
__it._M_next = (*this)[__it._M_next]._M_next;
- if (__it._M_opcode == _S_opcode_alternative)
+ if (__it._M_opcode == _S_opcode_alternative
+ || __it._M_opcode == _S_opcode_subexpr_lookahead)
while (__it._M_alt >= 0 && (*this)[__it._M_alt]._M_opcode
== _S_opcode_dummy)
__it._M_alt = (*this)[__it._M_alt]._M_next;
@@ -183,9 +182,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
// Just apply DFS on the sequence and re-link their links.
- template<typename _CharT, typename _TraitsT>
- _StateSeq<_CharT, _TraitsT> _StateSeq<_CharT, _TraitsT>::
- _M_clone()
+ template<typename _TraitsT>
+ _StateSeq<_TraitsT>
+ _StateSeq<_TraitsT>::_M_clone()
{
std::map<_StateIdT, _StateIdT> __m;
std::stack<_StateIdT> __stack;
@@ -201,7 +200,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
continue;
if (__m.count(__dup._M_next) == 0)
__stack.push(__dup._M_next);
- if (__dup._M_opcode == _S_opcode_alternative)
+ if (__dup._M_opcode == _S_opcode_alternative
+ || __dup._M_opcode == _S_opcode_subexpr_lookahead)
if (__m.count(__dup._M_alt) == 0)
__stack.push(__dup._M_alt);
}
@@ -213,7 +213,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX_DEBUG_ASSERT(__m.count(__ref._M_next));
__ref._M_next = __m[__ref._M_next];
}
- if (__ref._M_opcode == _S_opcode_alternative)
+ if (__ref._M_opcode == _S_opcode_alternative
+ || __ref._M_opcode == _S_opcode_subexpr_lookahead)
if (__ref._M_alt != -1)
{
_GLIBCXX_DEBUG_ASSERT(__m.count(__ref._M_alt));
diff --git a/libstdc++-v3/include/bits/regex_compiler.h b/libstdc++-v3/include/bits/regex_compiler.h
index 3b85d3a46c3..b9f81272bb9 100644
--- a/libstdc++-v3/include/bits/regex_compiler.h
+++ b/libstdc++-v3/include/bits/regex_compiler.h
@@ -39,32 +39,32 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* @{
*/
- template<typename _CharT, typename _TraitsT>
+ template<typename _TraitsT>
struct _BracketMatcher;
/// Builds an NFA from an input iterator interval.
- template<typename _FwdIter, typename _CharT, typename _TraitsT>
+ template<typename _FwdIter, typename _TraitsT>
class _Compiler
{
public:
typedef typename _TraitsT::string_type _StringT;
- typedef _NFA<_CharT, _TraitsT> _RegexT;
+ typedef _NFA<_TraitsT> _RegexT;
typedef regex_constants::syntax_option_type _FlagT;
_Compiler(_FwdIter __b, _FwdIter __e,
const _TraitsT& __traits, _FlagT __flags);
std::shared_ptr<_RegexT>
- _M_get_nfa() const
- { return make_shared<_RegexT>(_M_nfa); }
+ _M_get_nfa()
+ { return make_shared<_RegexT>(std::move(_M_nfa)); }
private:
typedef _Scanner<_FwdIter> _ScannerT;
typedef typename _ScannerT::_TokenT _TokenT;
- typedef _StateSeq<_CharT, _TraitsT> _StateSeqT;
+ typedef _StateSeq<_TraitsT> _StateSeqT;
typedef std::stack<_StateSeqT, std::vector<_StateSeqT>> _StackT;
- typedef _BracketMatcher<_CharT, _TraitsT> _BMatcherT;
- typedef std::ctype<_CharT> _CtypeT;
+ typedef _BracketMatcher<_TraitsT> _BMatcherT;
+ typedef std::ctype<typename _TraitsT::char_type> _CtypeT;
// accepts a specific token or returns false.
bool
@@ -120,18 +120,76 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return ret;
}
+ _FlagT _M_flags;
const _TraitsT& _M_traits;
const _CtypeT& _M_ctype;
_ScannerT _M_scanner;
_RegexT _M_nfa;
_StringT _M_value;
_StackT _M_stack;
- _FlagT _M_flags;
};
- template<typename _CharT, typename _TraitsT>
+ template<typename _Tp>
+ struct __has_contiguous_iter : std::false_type { };
+
+ template<typename _Ch, typename _Tr, typename _Alloc>
+ struct __has_contiguous_iter<std::basic_string<_Ch, _Tr, _Alloc>>
+ : std::true_type // string<Ch> storage is contiguous
+ { };
+
+ template<typename _Tp, typename _Alloc>
+ struct __has_contiguous_iter<std::vector<_Tp, _Alloc>>
+ : std::true_type // vector<Tp> storage is contiguous
+ { };
+
+ template<typename _Alloc>
+ struct __has_contiguous_iter<std::vector<bool, _Alloc>>
+ : std::false_type // vector<bool> storage is not contiguous
+ { };
+
+ template<typename _Tp>
+ struct __is_contiguous_normal_iter : std::false_type { };
+
+ template<typename _Tp, typename _Cont>
+ struct
+ __is_contiguous_normal_iter<__gnu_cxx::__normal_iterator<_Tp, _Cont>>
+ : __has_contiguous_iter<_Cont>::type
+ { };
+
+ template<typename _Iter, typename _TraitsT>
+ using __enable_if_contiguous_normal_iter
+ = typename enable_if< __is_contiguous_normal_iter<_Iter>::value,
+ std::shared_ptr<_NFA<_TraitsT>> >::type;
+
+ template<typename _Iter, typename _TraitsT>
+ using __disable_if_contiguous_normal_iter
+ = typename enable_if< !__is_contiguous_normal_iter<_Iter>::value,
+ std::shared_ptr<_NFA<_TraitsT>> >::type;
+
+ template<typename _FwdIter, typename _TraitsT>
+ inline __disable_if_contiguous_normal_iter<_FwdIter, _TraitsT>
+ __compile_nfa(_FwdIter __first, _FwdIter __last, const _TraitsT& __traits,
+ regex_constants::syntax_option_type __flags)
+ {
+ using _Cmplr = _Compiler<_FwdIter, _TraitsT>;
+ return _Cmplr(__first, __last, __traits, __flags)._M_get_nfa();
+ }
+
+ template<typename _Iter, typename _TraitsT>
+ inline __enable_if_contiguous_normal_iter<_Iter, _TraitsT>
+ __compile_nfa(_Iter __first, _Iter __last, const _TraitsT& __traits,
+ regex_constants::syntax_option_type __flags)
+ {
+ size_t __len = __last - __first;
+ const auto* __cfirst = __len ? std::__addressof(*__first) : nullptr;
+ return __compile_nfa(__cfirst, __cfirst + __len, __traits, __flags);
+ }
+
+ template<typename _TraitsT>
struct _AnyMatcher
{
+ typedef typename _TraitsT::char_type _CharT;
+
explicit
_AnyMatcher(const _TraitsT& __traits)
: _M_traits(__traits)
@@ -149,14 +207,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
const _TraitsT& _M_traits;
};
- template<typename _CharT, typename _TraitsT>
+ template<typename _TraitsT>
struct _CharMatcher
{
+ typedef typename _TraitsT::char_type _CharT;
typedef regex_constants::syntax_option_type _FlagT;
explicit
_CharMatcher(_CharT __ch, const _TraitsT& __traits, _FlagT __flags)
- : _M_ch(_M_translate(__ch)), _M_traits(__traits), _M_flags(__flags)
+ : _M_traits(__traits), _M_flags(__flags), _M_ch(_M_translate(__ch))
{ }
bool
@@ -178,9 +237,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
};
/// Matches a character range (bracket expression)
- template<typename _CharT, typename _TraitsT>
+ template<typename _TraitsT>
struct _BracketMatcher
{
+ typedef typename _TraitsT::char_type _CharT;
typedef typename _TraitsT::char_class_type _CharClassT;
typedef typename _TraitsT::string_type _StringT;
typedef regex_constants::syntax_option_type _FlagT;
@@ -189,8 +249,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_BracketMatcher(bool __is_non_matching,
const _TraitsT& __traits,
_FlagT __flags)
- : _M_is_non_matching(__is_non_matching), _M_traits(__traits),
- _M_flags(__flags), _M_class_set(0)
+ : _M_traits(__traits), _M_class_set(0), _M_flags(__flags),
+ _M_is_non_matching(__is_non_matching)
{ }
bool
@@ -207,26 +267,30 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__s.data() + __s.size());
if (__st.empty())
__throw_regex_error(regex_constants::error_collate);
- // TODO: digraph
_M_char_set.insert(_M_translate(__st[0]));
}
void
_M_add_equivalence_class(const _StringT& __s)
{
- _M_add_character_class(
- _M_traits.transform_primary(__s.data(),
- __s.data() + __s.size()));
+ auto __st = _M_traits.lookup_collatename(__s.data(),
+ __s.data() + __s.size());
+ if (__st.empty())
+ __throw_regex_error(regex_constants::error_collate);
+ __st = _M_traits.transform_primary(__st.data(),
+ __st.data() + __st.size());
+ _M_equiv_set.insert(__st);
}
void
_M_add_character_class(const _StringT& __s)
{
- auto __st = _M_traits.
- lookup_classname(__s.data(), __s.data() + __s.size(), _M_is_icase());
- if (__st == 0)
+ auto __mask = _M_traits.lookup_classname(__s.data(),
+ __s.data() + __s.size(),
+ _M_is_icase());
+ if (__mask == 0)
__throw_regex_error(regex_constants::error_ctype);
- _M_class_set |= __st;
+ _M_class_set |= __mask;
}
void
@@ -261,6 +325,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
std::set<_CharT> _M_char_set;
+ std::set<_StringT> _M_equiv_set;
std::set<pair<_StringT, _StringT>> _M_range_set;
const _TraitsT& _M_traits;
_CharClassT _M_class_set;
diff --git a/libstdc++-v3/include/bits/regex_compiler.tcc b/libstdc++-v3/include/bits/regex_compiler.tcc
index 7f9a19af2d9..f89498f35ed 100644
--- a/libstdc++-v3/include/bits/regex_compiler.tcc
+++ b/libstdc++-v3/include/bits/regex_compiler.tcc
@@ -59,13 +59,23 @@ namespace __detail
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
- template<typename _FwdIter, typename _CharT, typename _TraitsT>
- _Compiler<_FwdIter, _CharT, _TraitsT>::
+ template<typename _FwdIter, typename _TraitsT>
+ _Compiler<_FwdIter, _TraitsT>::
_Compiler(_FwdIter __b, _FwdIter __e,
const _TraitsT& __traits, _FlagT __flags)
- : _M_traits(__traits), _M_scanner(__b, __e, __flags, _M_traits.getloc()),
- _M_ctype(std::use_facet<std::ctype<_CharT>>(_M_traits.getloc())),
- _M_nfa(__flags), _M_flags(__flags)
+ : _M_flags((__flags
+ & (regex_constants::ECMAScript
+ | regex_constants::basic
+ | regex_constants::extended
+ | regex_constants::grep
+ | regex_constants::egrep
+ | regex_constants::awk))
+ ? __flags
+ : __flags | regex_constants::ECMAScript),
+ _M_traits(__traits),
+ _M_ctype(std::use_facet<_CtypeT>(_M_traits.getloc())),
+ _M_scanner(__b, __e, _M_flags, _M_traits.getloc()),
+ _M_nfa(_M_flags)
{
_StateSeqT __r(_M_nfa, _M_nfa._M_start());
__r._M_append(_M_nfa._M_insert_subexpr_begin());
@@ -79,13 +89,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_nfa._M_eliminate_dummy();
}
- template<typename _FwdIter, typename _CharT, typename _TraitsT>
+ template<typename _FwdIter, typename _TraitsT>
void
- _Compiler<_FwdIter, _CharT, _TraitsT>::
+ _Compiler<_FwdIter, _TraitsT>::
_M_disjunction()
{
this->_M_alternative();
- // TODO empty alternative like, um, "(|asdf)"
while (_M_match_token(_ScannerT::_S_token_or))
{
_StateSeqT __alt1 = _M_pop();
@@ -101,9 +110,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
}
- template<typename _FwdIter, typename _CharT, typename _TraitsT>
+ template<typename _FwdIter, typename _TraitsT>
void
- _Compiler<_FwdIter, _CharT, _TraitsT>::
+ _Compiler<_FwdIter, _TraitsT>::
_M_alternative()
{
if (this->_M_term())
@@ -117,9 +126,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_stack.push(_StateSeqT(_M_nfa, _M_nfa._M_insert_dummy()));
}
- template<typename _FwdIter, typename _CharT, typename _TraitsT>
+ template<typename _FwdIter, typename _TraitsT>
bool
- _Compiler<_FwdIter, _CharT, _TraitsT>::
+ _Compiler<_FwdIter, _TraitsT>::
_M_term()
{
if (this->_M_assertion())
@@ -132,17 +141,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return false;
}
- template<typename _FwdIter, typename _CharT, typename _TraitsT>
+ template<typename _FwdIter, typename _TraitsT>
bool
- _Compiler<_FwdIter, _CharT, _TraitsT>::
+ _Compiler<_FwdIter, _TraitsT>::
_M_assertion()
{
if (_M_match_token(_ScannerT::_S_token_line_begin))
- _M_stack.push(_StateSeqT(_M_nfa, _M_nfa.
- _M_insert_line_begin()));
+ _M_stack.push(_StateSeqT(_M_nfa, _M_nfa._M_insert_line_begin()));
else if (_M_match_token(_ScannerT::_S_token_line_end))
- _M_stack.push(_StateSeqT(_M_nfa, _M_nfa.
- _M_insert_line_end()));
+ _M_stack.push(_StateSeqT(_M_nfa, _M_nfa._M_insert_line_end()));
else if (_M_match_token(_ScannerT::_S_token_word_bound))
// _M_value[0] == 'n' means it's negtive, say "not word boundary".
_M_stack.push(_StateSeqT(_M_nfa, _M_nfa.
@@ -165,12 +172,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return true;
}
- template<typename _FwdIter, typename _CharT, typename _TraitsT>
+ template<typename _FwdIter, typename _TraitsT>
void
- _Compiler<_FwdIter, _CharT, _TraitsT>::
+ _Compiler<_FwdIter, _TraitsT>::
_M_quantifier()
{
- bool __neg = regex_constants::ECMAScript;
+ bool __neg = (_M_flags & regex_constants::ECMAScript);
auto __init = [this, &__neg]()
{
if (_M_stack.empty())
@@ -207,70 +214,83 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
else if (_M_match_token(_ScannerT::_S_token_interval_begin))
{
- __init();
+ if (_M_stack.empty())
+ __throw_regex_error(regex_constants::error_badrepeat);
if (!_M_match_token(_ScannerT::_S_token_dup_count))
__throw_regex_error(regex_constants::error_badbrace);
_StateSeqT __r(_M_pop());
_StateSeqT __e(_M_nfa, _M_nfa._M_insert_dummy());
- int __min_rep = _M_cur_int_value(10);
+ long __min_rep = _M_cur_int_value(10);
+ bool __infi = false;
+ long __n;
+
// {3
- for (int __i = 0; __i < __min_rep; ++__i)
- __e._M_append(__r._M_clone());
if (_M_match_token(_ScannerT::_S_token_comma))
if (_M_match_token(_ScannerT::_S_token_dup_count)) // {3,7}
- {
- int __n = _M_cur_int_value(10) - __min_rep;
- if (__n < 0)
- __throw_regex_error(regex_constants::error_badbrace);
- auto __end = _M_nfa._M_insert_dummy();
- // _M_alt is the "match more" branch, and _M_next is the
- // "match less" one. Switch _M_alt and _M_next of all created
- // nodes. This is a hacking but IMO works well.
- std::stack<_StateIdT> __stack;
- for (int __i = 0; __i < __n; ++__i)
- {
- auto __tmp = __r._M_clone();
- auto __alt = _M_nfa._M_insert_alt(__tmp._M_start,
- __end, __neg);
- __stack.push(__alt);
- __e._M_append(_StateSeqT(_M_nfa, __alt, __tmp._M_end));
- }
- __e._M_append(__end);
- while (!__stack.empty())
- {
- auto& __tmp = _M_nfa[__stack.top()];
- __stack.pop();
- swap(__tmp._M_next, __tmp._M_alt);
- }
- }
- else // {3,}
- {
- auto __tmp = __r._M_clone();
- _StateSeqT __s(_M_nfa,
- _M_nfa._M_insert_alt(_S_invalid_state_id,
- __tmp._M_start, __neg));
- __tmp._M_append(__s);
- __e._M_append(__s);
- }
+ __n = _M_cur_int_value(10) - __min_rep;
+ else
+ __infi = true;
+ else
+ __n = 0;
if (!_M_match_token(_ScannerT::_S_token_interval_end))
__throw_regex_error(regex_constants::error_brace);
+
+ __neg = __neg && _M_match_token(_ScannerT::_S_token_opt);
+
+ for (long __i = 0; __i < __min_rep; ++__i)
+ __e._M_append(__r._M_clone());
+
+ if (__infi)
+ {
+ auto __tmp = __r._M_clone();
+ _StateSeqT __s(_M_nfa,
+ _M_nfa._M_insert_alt(_S_invalid_state_id,
+ __tmp._M_start, __neg));
+ __tmp._M_append(__s);
+ __e._M_append(__s);
+ }
+ else
+ {
+ if (__n < 0)
+ __throw_regex_error(regex_constants::error_badbrace);
+ auto __end = _M_nfa._M_insert_dummy();
+ // _M_alt is the "match more" branch, and _M_next is the
+ // "match less" one. Switch _M_alt and _M_next of all created
+ // nodes. This is a hacking but IMO works well.
+ std::stack<_StateIdT> __stack;
+ for (long __i = 0; __i < __n; ++__i)
+ {
+ auto __tmp = __r._M_clone();
+ auto __alt = _M_nfa._M_insert_alt(__tmp._M_start,
+ __end, __neg);
+ __stack.push(__alt);
+ __e._M_append(_StateSeqT(_M_nfa, __alt, __tmp._M_end));
+ }
+ __e._M_append(__end);
+ while (!__stack.empty())
+ {
+ auto& __tmp = _M_nfa[__stack.top()];
+ __stack.pop();
+ swap(__tmp._M_next, __tmp._M_alt);
+ }
+ }
_M_stack.push(__e);
}
}
- template<typename _FwdIter, typename _CharT, typename _TraitsT>
+ template<typename _FwdIter, typename _TraitsT>
bool
- _Compiler<_FwdIter, _CharT, _TraitsT>::
+ _Compiler<_FwdIter, _TraitsT>::
_M_atom()
{
if (_M_match_token(_ScannerT::_S_token_anychar))
_M_stack.push(_StateSeqT(_M_nfa,
_M_nfa._M_insert_matcher
- (_AnyMatcher<_CharT, _TraitsT>(_M_traits))));
+ (_AnyMatcher<_TraitsT>(_M_traits))));
else if (_M_try_char())
_M_stack.push(_StateSeqT(_M_nfa,
_M_nfa._M_insert_matcher
- (_CharMatcher<_CharT, _TraitsT>(_M_value[0],
+ (_CharMatcher<_TraitsT>(_M_value[0],
_M_traits,
_M_flags))));
else if (_M_match_token(_ScannerT::_S_token_backref))
@@ -283,7 +303,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_traits, _M_flags);
__matcher._M_add_character_class(_M_value);
_M_stack.push(_StateSeqT(_M_nfa,
- _M_nfa._M_insert_matcher(__matcher)));
+ _M_nfa._M_insert_matcher(std::move(__matcher))));
}
else if (_M_match_token(_ScannerT::_S_token_subexpr_no_group_begin))
{
@@ -296,7 +316,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
else if (_M_match_token(_ScannerT::_S_token_subexpr_begin))
{
- int __mark = _M_nfa._M_sub_count();
_StateSeqT __r(_M_nfa, _M_nfa._M_insert_subexpr_begin());
this->_M_disjunction();
if (!_M_match_token(_ScannerT::_S_token_subexpr_end))
@@ -310,9 +329,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return true;
}
- template<typename _FwdIter, typename _CharT, typename _TraitsT>
+ template<typename _FwdIter, typename _TraitsT>
bool
- _Compiler<_FwdIter, _CharT, _TraitsT>::
+ _Compiler<_FwdIter, _TraitsT>::
_M_bracket_expression()
{
bool __neg =
@@ -322,13 +341,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_BMatcherT __matcher(__neg, _M_traits, _M_flags);
while (!_M_match_token(_ScannerT::_S_token_bracket_end))
_M_expression_term(__matcher);
- _M_stack.push(_StateSeqT(_M_nfa, _M_nfa._M_insert_matcher(__matcher)));
+ _M_stack.push(_StateSeqT(_M_nfa,
+ _M_nfa._M_insert_matcher(std::move(__matcher))));
return true;
}
- template<typename _FwdIter, typename _CharT, typename _TraitsT>
+ template<typename _FwdIter, typename _TraitsT>
void
- _Compiler<_FwdIter, _CharT, _TraitsT>::
+ _Compiler<_FwdIter, _TraitsT>::
_M_expression_term(_BMatcherT& __matcher)
{
if (_M_match_token(_ScannerT::_S_token_collsymbol))
@@ -363,9 +383,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__throw_regex_error(regex_constants::error_brack);
}
- template<typename _FwdIter, typename _CharT, typename _TraitsT>
+ template<typename _FwdIter, typename _TraitsT>
bool
- _Compiler<_FwdIter, _CharT, _TraitsT>::
+ _Compiler<_FwdIter, _TraitsT>::
_M_try_char()
{
bool __is_char = false;
@@ -384,9 +404,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return __is_char;
}
- template<typename _FwdIter, typename _CharT, typename _TraitsT>
+ template<typename _FwdIter, typename _TraitsT>
bool
- _Compiler<_FwdIter, _CharT, _TraitsT>::
+ _Compiler<_FwdIter, _TraitsT>::
_M_match_token(_TokenT token)
{
if (token == _M_scanner._M_get_token())
@@ -398,26 +418,26 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return false;
}
- template<typename _FwdIter, typename _CharT, typename _TraitsT>
+ template<typename _FwdIter, typename _TraitsT>
int
- _Compiler<_FwdIter, _CharT, _TraitsT>::
+ _Compiler<_FwdIter, _TraitsT>::
_M_cur_int_value(int __radix)
{
- int __v = 0;
+ long __v = 0;
for (typename _StringT::size_type __i = 0;
__i < _M_value.length(); ++__i)
__v =__v * __radix + _M_traits.value(_M_value[__i], __radix);
return __v;
}
- template<typename _CharT, typename _TraitsT>
- bool _BracketMatcher<_CharT, _TraitsT>::
- operator()(_CharT __ch) const
+ template<typename _TraitsT>
+ bool
+ _BracketMatcher<_TraitsT>::operator()(_CharT __ch) const
{
bool __ret = false;
- if (_M_traits.isctype(__ch, _M_class_set))
- __ret = true;
- else if (_M_char_set.count(_M_translate(__ch)))
+ if (_M_traits.isctype(__ch, _M_class_set)
+ || _M_char_set.count(_M_translate(__ch))
+ || _M_equiv_set.count(_M_traits.transform_primary(&__ch, &__ch+1)))
__ret = true;
else
{
diff --git a/libstdc++-v3/include/bits/regex_error.h b/libstdc++-v3/include/bits/regex_error.h
index 7f06727bfae..a39a8ea1a8f 100644
--- a/libstdc++-v3/include/bits/regex_error.h
+++ b/libstdc++-v3/include/bits/regex_error.h
@@ -61,7 +61,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_S_error_badrepeat,
_S_error_complexity,
_S_error_stack,
- _S_error_last
};
/** The expression contained an invalid collating element name. */
diff --git a/libstdc++-v3/include/bits/regex_executor.h b/libstdc++-v3/include/bits/regex_executor.h
index b8e9266f910..ded77475f6f 100644
--- a/libstdc++-v3/include/bits/regex_executor.h
+++ b/libstdc++-v3/include/bits/regex_executor.h
@@ -30,10 +30,6 @@
// FIXME convert comments to doxygen format.
-// TODO Put _DFSExecutor and _BFSExecutor into one class. They are becoming
-// much more similar. Also, make grouping seperated. The
-// regex_constants::nosubs enables much more simpler execution.
-
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
@@ -56,72 +52,74 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* @{
*/
- template<typename _BiIter, typename _Alloc,
- typename _CharT, typename _TraitsT>
+ template<typename _BiIter, typename _Alloc, typename _TraitsT,
+ bool __dfs_mode>
class _Executor
{
public:
- typedef basic_regex<_CharT, _TraitsT> _RegexT;
- typedef match_results<_BiIter, _Alloc> _ResultsT;
- typedef std::vector<sub_match<_BiIter>, _Alloc> _ResultsVec;
- typedef regex_constants::match_flag_type _FlagT;
- typedef typename _TraitsT::char_class_type _ClassT;
+ typedef typename iterator_traits<_BiIter>::value_type _CharT;
+ typedef basic_regex<_CharT, _TraitsT> _RegexT;
+ typedef std::vector<sub_match<_BiIter>, _Alloc> _ResultsVec;
+ typedef regex_constants::match_flag_type _FlagT;
+ typedef typename _TraitsT::char_class_type _ClassT;
+ typedef _NFA<_TraitsT> _NFAT;
public:
_Executor(_BiIter __begin,
_BiIter __end,
- _ResultsT& __results,
+ _ResultsVec& __results,
const _RegexT& __re,
_FlagT __flags)
: _M_begin(__begin),
_M_end(__end),
- _M_results(__results),
_M_re(__re),
- _M_flags(__flags)
+ _M_nfa(*__re._M_automaton),
+ _M_results(__results),
+ _M_match_queue(__dfs_mode ? nullptr
+ : new queue<pair<_StateIdT, _ResultsVec>>()),
+ _M_visited(__dfs_mode ? nullptr : new vector<bool>(_M_nfa.size())),
+ _M_flags((__flags & regex_constants::match_prev_avail)
+ ? (__flags
+ & ~regex_constants::match_not_bol
+ & ~regex_constants::match_not_bow)
+ : __flags),
+ _M_start_state(_M_nfa._M_start())
{ }
// Set matched when string exactly match the pattern.
bool
_M_match()
{
- _M_match_mode = true;
- _M_init(_M_begin);
- return _M_main();
+ _M_current = _M_begin;
+ return _M_main<true>();
}
// Set matched when some prefix of the string matches the pattern.
bool
_M_search_from_first()
{
- _M_match_mode = false;
- _M_init(_M_begin);
- return _M_main();
+ _M_current = _M_begin;
+ return _M_main<false>();
}
bool
- _M_search()
- {
- if (_M_flags & regex_constants::match_continuous)
- return _M_search_from_first();
- auto __cur = _M_begin;
- do
- {
- _M_match_mode = false;
- _M_init(__cur);
- if (_M_main())
- return true;
- }
- // Continue when __cur == _M_end
- while (__cur++ != _M_end);
- return false;
- }
+ _M_search();
+
+ private:
+ template<bool __match_mode>
+ void
+ _M_dfs(_StateIdT __start);
+
+ template<bool __match_mode>
+ bool
+ _M_main();
bool
_M_is_word(_CharT __ch) const
{
- static const _CharT __s = 'w';
+ static const _CharT __s[2] = { 'w' };
return _M_re._M_traits.isctype
- (__ch, _M_re._M_traits.lookup_classname(&__s, &__s+1));
+ (__ch, _M_re._M_traits.lookup_classname(__s, __s+1));
}
bool
@@ -140,247 +138,31 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
bool
- _M_word_boundry(_State<_CharT, _TraitsT> __state) const;
+ _M_word_boundary(_State<_TraitsT> __state) const;
bool
- _M_lookahead(_State<_CharT, _TraitsT> __state) const;
-
- public:
- virtual void
- _M_init(_BiIter __cur) = 0;
-
- virtual void
- _M_set_start(_StateIdT __start) = 0;
-
- virtual bool
- _M_main() = 0;
-
- _BiIter _M_current;
- const _BiIter _M_begin;
- const _BiIter _M_end;
- const _RegexT& _M_re;
- _ResultsT& _M_results;
- const _FlagT _M_flags;
- bool _M_match_mode;
- };
-
- // A _DFSExecutor perform a DFS on given NFA and input string. At the very
- // beginning the executor stands in the start state, then it try every
- // possible state transition in current state recursively. Some state
- // transitions consume input string, say, a single-char-matcher or a
- // back-reference matcher; some not, like assertion or other anchor nodes.
- // When the input is exhausted and the current state is an accepting state,
- // the whole executor return true.
- //
- // TODO: This approach is exponentially slow for certain input.
- // Try to compile the NFA to a DFA.
- //
- // Time complexity: exponential
- // Space complexity: O(__end - __begin)
- template<typename _BiIter, typename _Alloc,
- typename _CharT, typename _TraitsT>
- class _DFSExecutor
- : public _Executor<_BiIter, _Alloc, _CharT, _TraitsT>
- {
- public:
- typedef _Executor<_BiIter, _Alloc, _CharT, _TraitsT> _BaseT;
- typedef _NFA<_CharT, _TraitsT> _NFAT;
- typedef typename _BaseT::_RegexT _RegexT;
- typedef typename _BaseT::_ResultsT _ResultsT;
- typedef typename _BaseT::_ResultsVec _ResultsVec;
- typedef typename _BaseT::_FlagT _FlagT;
+ _M_lookahead(_State<_TraitsT> __state);
public:
- _DFSExecutor(_BiIter __begin,
- _BiIter __end,
- _ResultsT& __results,
- const _RegexT& __re,
- _FlagT __flags)
- : _BaseT(__begin, __end, __results, __re, __flags),
- _M_nfa(*std::static_pointer_cast<_NFA<_CharT, _TraitsT>>
- (__re._M_automaton)),
- _M_start_state(_M_nfa._M_start())
- { }
-
- private:
- void
- _M_init(_BiIter __cur)
- {
- _M_cur_results.resize(_M_nfa._M_sub_count() + 2);
- this->_M_current = __cur;
- }
-
- void
- _M_set_start(_StateIdT __start)
- { _M_start_state = __start; }
-
- bool
- _M_main()
- { return _M_dfs(this->_M_start_state); }
-
- bool
- _M_dfs(_StateIdT __start);
-
+ _ResultsVec _M_cur_results;
+ _BiIter _M_current;
+ const _BiIter _M_begin;
+ const _BiIter _M_end;
+ const _RegexT& _M_re;
+ const _NFAT& _M_nfa;
+ _ResultsVec& _M_results;
+ // Used in BFS, saving states that need to be considered for the next
+ // character.
+ std::unique_ptr<queue<pair<_StateIdT, _ResultsVec>>> _M_match_queue;
+ // Used in BFS, indicating that which state is already visited.
+ std::unique_ptr<vector<bool>> _M_visited;
+ _FlagT _M_flags;
// To record current solution.
- _ResultsVec _M_cur_results;
- const _NFAT& _M_nfa;
- _StateIdT _M_start_state;
+ _StateIdT _M_start_state;
+ // Do we have a solution so far?
+ bool _M_has_sol;
};
- // Like the DFS approach, it try every possible state transition; Unlike DFS,
- // it uses a queue instead of a stack to store matching states. It's a BFS
- // approach.
- //
- // Russ Cox's article(http://swtch.com/~rsc/regexp/regexp1.html) explained
- // this algorithm clearly.
- //
- // Every entry of _M_covered saves the solution(grouping status) for every
- // matching head. When states transit, solutions will be compared and
- // deduplicated(based on which greedy mode we have).
- //
- // Time complexity: O((__end - __begin) * _M_nfa.size())
- // Space complexity: O(_M_nfa.size() * _M_nfa.mark_count())
- template<typename _BiIter, typename _Alloc,
- typename _CharT, typename _TraitsT>
- class _BFSExecutor
- : public _Executor<_BiIter, _Alloc, _CharT, _TraitsT>
- {
- public:
- typedef _Executor<_BiIter, _Alloc, _CharT, _TraitsT> _BaseT;
- typedef _NFA<_CharT, _TraitsT> _NFAT;
- typedef typename _BaseT::_RegexT _RegexT;
- typedef typename _BaseT::_ResultsT _ResultsT;
- typedef typename _BaseT::_ResultsVec _ResultsVec;
- typedef typename _BaseT::_FlagT _FlagT;
- // Here's a solution for greedy/ungreedy mode in BFS approach. We need to
- // carefully work out how to compare to conflict matching states.
- //
- // A matching state is a pair(where, when); `where` is a NFA node; `when`
- // is a _BiIter, indicating which char is the next to be matched. Two
- // matching states conflict if they have equivalent `where` and `when`.
- //
- // Now we need to drop one and keep another, because at most one of them
- // could be the final optimal solution. This behavior is affected by
- // greedy policy.
- //
- // The definition of `greedy`:
- // For the sequence of quantifiers in NFA sorted by there start position,
- // now maintain a vector in every matching state, with equal length to
- // quantifier seq, recording repeating times of every quantifier. Now to
- // compare two matching states, we just lexically compare these two
- // vectors. To win the compare(to survive), one matching state needs to
- // make its greedy quantifier count larger, and ungreedy quantifiers
- // count smaller.
- //
- // In the implementation, we recorded negtive counts for greedy
- // quantifiers and positive counts of ungreedy ones. Now the implicit
- // operator<() for lexicographical_compare will emit the answer.
- //
- // When two vectors equal, it means the `where`, `when` and quantifier
- // counts are identical, and indicates the same solution; so just return
- // false.
- struct _ResultsEntry
- : private _ResultsVec
- {
- public:
- _ResultsEntry(unsigned int __res_sz, unsigned int __sz)
- : _ResultsVec(__res_sz), _M_quant_keys(__sz)
- { }
-
- void
- resize(unsigned int __n)
- { _ResultsVec::resize(__n); }
-
- unsigned int
- size()
- { return _ResultsVec::size(); }
-
- sub_match<_BiIter>&
- operator[](unsigned int __idx)
- { return _ResultsVec::operator[](__idx); }
-
- bool
- operator<(const _ResultsEntry& __rhs) const
- {
- _GLIBCXX_DEBUG_ASSERT(_M_quant_keys.size()
- == __rhs._M_quant_keys.size());
- return lexicographical_compare(_M_quant_keys.begin(),
- _M_quant_keys.end(),
- __rhs._M_quant_keys.begin(),
- __rhs._M_quant_keys.end());
- }
-
- void
- _M_inc(unsigned int __idx, bool __neg)
- { _M_quant_keys[__idx] += __neg ? 1 : -1; }
-
- _ResultsVec
- _M_get()
- { return *this; }
-
- public:
- std::vector<int> _M_quant_keys;
- };
- typedef std::unique_ptr<_ResultsEntry> _ResultsPtr;
-
- public:
- _BFSExecutor(_BiIter __begin,
- _BiIter __end,
- _ResultsT& __results,
- const _RegexT& __re,
- _FlagT __flags)
- : _BaseT(__begin, __end, __results, __re, __flags),
- _M_nfa(*std::static_pointer_cast<_NFA<_CharT, _TraitsT>>
- (__re._M_automaton)),
- _M_start_state(_M_nfa._M_start())
- { }
-
- private:
- void
- _M_init(_BiIter __cur)
- {
- _GLIBCXX_DEBUG_ASSERT(this->_M_start_state != _S_invalid_state_id);
- this->_M_current = __cur;
- _M_covered.clear();
- _ResultsVec& __res(this->_M_results);
- _M_covered[this->_M_start_state] =
- _ResultsPtr(new _ResultsEntry(__res.size(),
- _M_nfa._M_quant_count));
- _M_e_closure();
- }
-
- void
- _M_set_start(_StateIdT __start)
- { _M_start_state = __start; }
-
- bool
- _M_main();
-
- void
- _M_e_closure();
-
- void
- _M_move();
-
- bool
- _M_includes_some();
-
- std::map<_StateIdT, _ResultsPtr> _M_covered;
- // To record global optimal solution.
- _ResultsPtr _M_cur_results;
- const _NFAT& _M_nfa;
- _StateIdT _M_start_state;
- };
-
- template<typename _BiIter, typename _Alloc,
- typename _CharT, typename _TraitsT>
- std::unique_ptr<_Executor<_BiIter, _Alloc, _CharT, _TraitsT>>
- __get_executor(_BiIter __b,
- _BiIter __e,
- match_results<_BiIter, _Alloc>& __m,
- const basic_regex<_CharT, _TraitsT>& __re,
- regex_constants::match_flag_type __flags);
-
//@} regex-detail
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace __detail
diff --git a/libstdc++-v3/include/bits/regex_executor.tcc b/libstdc++-v3/include/bits/regex_executor.tcc
index af2455b8a4e..22fd67cfa3b 100644
--- a/libstdc++-v3/include/bits/regex_executor.tcc
+++ b/libstdc++-v3/include/bits/regex_executor.tcc
@@ -34,393 +34,340 @@ namespace __detail
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
- template<typename _BiIter, typename _Alloc,
- typename _CharT, typename _TraitsT>
- bool _DFSExecutor<_BiIter, _Alloc, _CharT, _TraitsT>::
+ template<typename _BiIter, typename _Alloc, typename _TraitsT,
+ bool __dfs_mode>
+ bool _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>::
+ _M_search()
+ {
+ if (_M_flags & regex_constants::match_continuous)
+ return _M_search_from_first();
+ auto __cur = _M_begin;
+ do
+ {
+ _M_current = __cur;
+ if (_M_main<false>())
+ return true;
+ }
+ // Continue when __cur == _M_end
+ while (__cur++ != _M_end);
+ return false;
+ }
+
+ // This function operates in different modes, DFS mode or BFS mode, indicated
+ // by template parameter __dfs_mode. See _M_main for details.
+ //
+ // ------------------------------------------------------------
+ //
+ // DFS mode:
+ //
+ // It applies a Depth-First-Search (aka backtracking) on given NFA and input
+ // string.
+ // At the very beginning the executor stands in the start state, then it tries
+ // every possible state transition in current state recursively. Some state
+ // transitions consume input string, say, a single-char-matcher or a
+ // back-reference matcher; some don't, like assertion or other anchor nodes.
+ // When the input is exhausted and/or the current state is an accepting state,
+ // the whole executor returns true.
+ //
+ // TODO: This approach is exponentially slow for certain input.
+ // Try to compile the NFA to a DFA.
+ //
+ // Time complexity: o(match_length), O(2^(_M_nfa.size()))
+ // Space complexity: \theta(match_results.size() + match_length)
+ //
+ // ------------------------------------------------------------
+ //
+ // BFS mode:
+ //
+ // Russ Cox's article (http://swtch.com/~rsc/regexp/regexp1.html)
+ // explained this algorithm clearly.
+ //
+ // It first computes epsilon closure for every state that's still matching,
+ // using the same DFS algorithm, but doesn't reenter states (set true in
+ // _M_visited), nor follows _S_opcode_match.
+ //
+ // Then apply DFS using every _S_opcode_match (in _M_match_queue) as the start
+ // state.
+ //
+ // It significantly reduces potential duplicate states, so has a better
+ // upper bound; but it requires more overhead.
+ //
+ // Time complexity: o(match_length * match_results.size())
+ // O(match_length * _M_nfa.size() * match_results.size())
+ // Space complexity: o(_M_nfa.size() + match_results.size())
+ // O(_M_nfa.size() * match_results.size())
+ template<typename _BiIter, typename _Alloc, typename _TraitsT,
+ bool __dfs_mode>
+ template<bool __match_mode>
+ bool _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>::
+ _M_main()
+ {
+ if (__dfs_mode)
+ {
+ _M_has_sol = false;
+ _M_cur_results = _M_results;
+ _M_dfs<__match_mode>(_M_start_state);
+ return _M_has_sol;
+ }
+ else
+ {
+ _M_match_queue->push(make_pair(_M_start_state, _M_results));
+ bool __ret = false;
+ while (1)
+ {
+ _M_has_sol = false;
+ if (_M_match_queue->empty())
+ break;
+ _M_visited->assign(_M_visited->size(), false);
+ auto _M_old_queue = std::move(*_M_match_queue);
+ while (!_M_old_queue.empty())
+ {
+ auto __task = _M_old_queue.front();
+ _M_old_queue.pop();
+ _M_cur_results = __task.second;
+ _M_dfs<__match_mode>(__task.first);
+ }
+ if (!__match_mode)
+ __ret |= _M_has_sol;
+ if (_M_current == _M_end)
+ break;
+ ++_M_current;
+ }
+ if (__match_mode)
+ __ret = _M_has_sol;
+ return __ret;
+ }
+ }
+
+ // Return whether now match the given sub-NFA.
+ template<typename _BiIter, typename _Alloc, typename _TraitsT,
+ bool __dfs_mode>
+ bool _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>::
+ _M_lookahead(_State<_TraitsT> __state)
+ {
+ _ResultsVec __what(_M_cur_results.size());
+ auto __sub = std::unique_ptr<_Executor>(new _Executor(_M_current,
+ _M_end,
+ __what,
+ _M_re,
+ _M_flags));
+ __sub->_M_start_state = __state._M_alt;
+ if (__sub->_M_search_from_first())
+ {
+ for (size_t __i = 0; __i < __what.size(); __i++)
+ if (__what[__i].matched)
+ _M_cur_results[__i] = __what[__i];
+ return true;
+ }
+ return false;
+ }
+
+ template<typename _BiIter, typename _Alloc, typename _TraitsT,
+ bool __dfs_mode>
+ template<bool __match_mode>
+ void _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>::
_M_dfs(_StateIdT __i)
{
- if (__i == _S_invalid_state_id)
- // This is not that certain. Need deeper investigate.
- return false;
- auto& __current = this->_M_current;
+ if (!__dfs_mode)
+ {
+ if ((*_M_visited)[__i])
+ return;
+ (*_M_visited)[__i] = true;
+ }
+
const auto& __state = _M_nfa[__i];
- bool __ret = false;
+ // Every change on _M_cur_results and _M_current will be rolled back after
+ // finishing the recursion step.
switch (__state._M_opcode)
{
+ // _M_alt branch is "match once more", while _M_next is "get me out
+ // of this quantifier". Executing _M_next first or _M_alt first don't
+ // mean the same thing, and we need to choose the correct order under
+ // given greedy mode.
case _S_opcode_alternative:
- // Greedy or not, this is a question ;)
+ // Greedy.
if (!__state._M_neg)
- __ret = _M_dfs(__state._M_alt)
- || _M_dfs(__state._M_next);
- else
- __ret = _M_dfs(__state._M_next)
- || _M_dfs(__state._M_alt);
+ {
+ // "Once more" is preferred in greedy mode.
+ _M_dfs<__match_mode>(__state._M_alt);
+ // If it's DFS executor and already accepted, we're done.
+ if (!__dfs_mode || !_M_has_sol)
+ _M_dfs<__match_mode>(__state._M_next);
+ }
+ else // Non-greedy mode
+ {
+ if (__dfs_mode)
+ {
+ // vice-versa.
+ _M_dfs<__match_mode>(__state._M_next);
+ if (!_M_has_sol)
+ _M_dfs<__match_mode>(__state._M_alt);
+ }
+ else
+ {
+ // DON'T attempt anything, because there's already another
+ // state with higher priority accepted. This state cannot be
+ // better by attempting its next node.
+ if (!_M_has_sol)
+ {
+ _M_dfs<__match_mode>(__state._M_next);
+ // DON'T attempt anything if it's already accepted. An
+ // accepted state *must* be better than a solution that
+ // matches a non-greedy quantifier one more time.
+ if (!_M_has_sol)
+ _M_dfs<__match_mode>(__state._M_alt);
+ }
+ }
+ }
break;
case _S_opcode_subexpr_begin:
- // Here's the critical part: if there's nothing changed since last
- // visit, do NOT continue. This prevents the executor from get into
- // infinite loop when use "()*" to match "".
- //
- // Every change on _M_cur_results will be roll back after the
- // recursion step finished.
+ // If there's nothing changed since last visit, do NOT continue.
+ // This prevents the executor from get into infinite loop when using
+ // "()*" to match "".
if (!_M_cur_results[__state._M_subexpr].matched
- || _M_cur_results[__state._M_subexpr].first != __current)
+ || _M_cur_results[__state._M_subexpr].first != _M_current)
{
- auto __back = __current;
- _M_cur_results[__state._M_subexpr].first = __current;
- __ret = _M_dfs(__state._M_next);
- _M_cur_results[__state._M_subexpr].first = __back;
+ auto& __res = _M_cur_results[__state._M_subexpr];
+ auto __back = __res.first;
+ __res.first = _M_current;
+ _M_dfs<__match_mode>(__state._M_next);
+ __res.first = __back;
}
break;
case _S_opcode_subexpr_end:
- if (_M_cur_results[__state._M_subexpr].second != __current
+ if (_M_cur_results[__state._M_subexpr].second != _M_current
|| _M_cur_results[__state._M_subexpr].matched != true)
{
- auto __back = _M_cur_results[__state._M_subexpr];
- _M_cur_results[__state._M_subexpr].second = __current;
- _M_cur_results[__state._M_subexpr].matched = true;
- __ret = _M_dfs(__state._M_next);
- _M_cur_results[__state._M_subexpr] = __back;
+ auto& __res = _M_cur_results[__state._M_subexpr];
+ auto __back = __res;
+ __res.second = _M_current;
+ __res.matched = true;
+ _M_dfs<__match_mode>(__state._M_next);
+ __res = __back;
}
else
- __ret = _M_dfs(__state._M_next);
+ _M_dfs<__match_mode>(__state._M_next);
break;
case _S_opcode_line_begin_assertion:
- if (this->_M_at_begin())
- __ret = _M_dfs(__state._M_next);
+ if (_M_at_begin())
+ _M_dfs<__match_mode>(__state._M_next);
break;
case _S_opcode_line_end_assertion:
- if (this->_M_at_end())
- __ret = _M_dfs(__state._M_next);
+ if (_M_at_end())
+ _M_dfs<__match_mode>(__state._M_next);
break;
- case _S_opcode_word_boundry:
- if (this->_M_word_boundry(__state) == !__state._M_neg)
- __ret = _M_dfs(__state._M_next);
+ case _S_opcode_word_boundary:
+ if (_M_word_boundary(__state) == !__state._M_neg)
+ _M_dfs<__match_mode>(__state._M_next);
break;
- // Here __state._M_alt offers a single start node for a sub-NFA.
- // We recursivly invoke our algorithm to match the sub-NFA.
+ // Here __state._M_alt offers a single start node for a sub-NFA.
+ // We recursively invoke our algorithm to match the sub-NFA.
case _S_opcode_subexpr_lookahead:
- if (this->_M_lookahead(__state) == !__state._M_neg)
- __ret = _M_dfs(__state._M_next);
+ if (_M_lookahead(__state) == !__state._M_neg)
+ _M_dfs<__match_mode>(__state._M_next);
break;
case _S_opcode_match:
- if (__current != this->_M_end && __state._M_matches(*__current))
+ if (__dfs_mode)
{
- ++__current;
- __ret = _M_dfs(__state._M_next);
- --__current;
+ if (_M_current != _M_end && __state._M_matches(*_M_current))
+ {
+ ++_M_current;
+ _M_dfs<__match_mode>(__state._M_next);
+ --_M_current;
+ }
}
+ else
+ if (__state._M_matches(*_M_current))
+ _M_match_queue->push(make_pair(__state._M_next, _M_cur_results));
break;
// First fetch the matched result from _M_cur_results as __submatch;
// then compare it with
- // (__current, __current + (__submatch.second - __submatch.first))
- // If matched, keep going; else just return to try another state.
+ // (_M_current, _M_current + (__submatch.second - __submatch.first)).
+ // If matched, keep going; else just return and try another state.
case _S_opcode_backref:
{
+ _GLIBCXX_DEBUG_ASSERT(__dfs_mode);
auto& __submatch = _M_cur_results[__state._M_backref_index];
if (!__submatch.matched)
break;
- auto __last = __current;
+ auto __last = _M_current;
for (auto __tmp = __submatch.first;
- __last != this->_M_end && __tmp != __submatch.second;
+ __last != _M_end && __tmp != __submatch.second;
++__tmp)
++__last;
- if (this->_M_re._M_traits.transform(__submatch.first,
+ if (_M_re._M_traits.transform(__submatch.first,
__submatch.second)
- == this->_M_re._M_traits.transform(__current, __last))
- if (__last != __current)
- {
- auto __backup = __current;
- __current = __last;
- __ret = _M_dfs(__state._M_next);
- __current = __backup;
- }
- else
- __ret = _M_dfs(__state._M_next);
+ == _M_re._M_traits.transform(_M_current, __last))
+ {
+ if (__last != _M_current)
+ {
+ auto __backup = _M_current;
+ _M_current = __last;
+ _M_dfs<__match_mode>(__state._M_next);
+ _M_current = __backup;
+ }
+ else
+ _M_dfs<__match_mode>(__state._M_next);
+ }
}
break;
case _S_opcode_accept:
- if (this->_M_match_mode)
- __ret = __current == this->_M_end;
- else
- __ret = true;
- if (__current == this->_M_begin
- && (this->_M_flags & regex_constants::match_not_null))
- __ret = false;
- if (__ret)
+ if (__dfs_mode)
{
- _ResultsVec& __res(this->_M_results);
- if (this->_M_re.flags() & regex_constants::nosubs)
- {
- _M_cur_results.resize(3); // truncate
- __res.resize(3);
- }
- for (unsigned int __i = 0; __i < _M_cur_results.size(); ++__i)
- if (_M_cur_results[__i].matched)
- __res[__i] = _M_cur_results[__i];
+ _GLIBCXX_DEBUG_ASSERT(!_M_has_sol);
+ if (__match_mode)
+ _M_has_sol = _M_current == _M_end;
+ else
+ _M_has_sol = true;
+ if (_M_current == _M_begin
+ && (_M_flags & regex_constants::match_not_null))
+ _M_has_sol = false;
+ if (_M_has_sol)
+ _M_results = _M_cur_results;
}
- break;
- default:
- _GLIBCXX_DEBUG_ASSERT(false);
- }
- return __ret;
- }
-
- template<typename _BiIter, typename _Alloc,
- typename _CharT, typename _TraitsT>
- bool _BFSExecutor<_BiIter, _Alloc, _CharT, _TraitsT>::
- _M_main()
- {
- bool __ret = false;
- if (!this->_M_match_mode
- && !(this->_M_flags & regex_constants::match_not_null))
- __ret = _M_includes_some() || __ret;
- while (this->_M_current != this->_M_end)
- {
- _M_move();
- ++this->_M_current;
- _M_e_closure();
- if (!this->_M_match_mode)
- // To keep regex_search greedy, no "return true" here.
- __ret = _M_includes_some() || __ret;
- }
- if (this->_M_match_mode)
- __ret = _M_includes_some();
- if (__ret)
- {
- _ResultsVec& __res(this->_M_results);
- if (this->_M_re.flags() & regex_constants::nosubs)
+ else
{
- // truncate
- _M_cur_results->resize(3);
- __res.resize(3);
- }
- for (unsigned int __i = 0; __i < _M_cur_results->size(); ++__i)
- if ((*_M_cur_results)[__i].matched)
- __res[__i] = (*_M_cur_results)[__i];
- }
- return __ret;
- }
-
- template<typename _BiIter, typename _Alloc,
- typename _CharT, typename _TraitsT>
- void _BFSExecutor<_BiIter, _Alloc, _CharT, _TraitsT>::
- _M_e_closure()
- {
- std::queue<_StateIdT> __q;
- std::vector<bool> __in_q(_M_nfa.size(), false);
- auto& __current = this->_M_current;
-
- for (auto& __it : _M_covered)
- {
- __in_q[__it.first] = true;
- __q.push(__it.first);
- }
- while (!__q.empty())
- {
- auto __u = __q.front();
- __q.pop();
- __in_q[__u] = false;
- const auto& __state = _M_nfa[__u];
-
- // Can be implemented using method, but there will be too many
- // arguments. I would use macro function before C++11, but lambda is
- // a better choice, since hopefully compiler can inline it.
- auto __add_visited_state = [&](_StateIdT __v)
- {
- if (__v == _S_invalid_state_id)
- return;
- if (_M_covered.count(__u) != 0
- && (_M_covered.count(__v) == 0
- || *_M_covered[__u] < *_M_covered[__v]))
- {
- _M_covered[__v] =
- _ResultsPtr(new _ResultsEntry(*_M_covered[__u]));
- // if a state is updated, it's outgoing neighbors should be
- // reconsidered too. Push them to the queue.
- if (!__in_q[__v])
+ if (_M_current == _M_begin
+ && (_M_flags & regex_constants::match_not_null))
+ break;
+ if (!__match_mode || _M_current == _M_end)
+ if (!_M_has_sol)
{
- __in_q[__v] = true;
- __q.push(__v);
+ _M_has_sol = true;
+ _M_results = _M_cur_results;
}
- }
- };
-
- // Identical to DFS's switch part.
- switch (__state._M_opcode)
- {
- // Needs to maintain quantifier count vector here. A quantifier
- // must be concerned with a alt node.
- case _S_opcode_alternative:
- {
- __add_visited_state(__state._M_next);
- auto __back =
- _M_covered[__u]->_M_quant_keys[__state._M_quant_index];
- _M_covered[__u]->_M_inc(__state._M_quant_index,
- __state._M_neg);
- __add_visited_state(__state._M_alt);
- _M_covered[__u]->_M_quant_keys[__state._M_quant_index]
- = __back;
- }
- break;
- case _S_opcode_subexpr_begin:
- {
- auto& __sub = (*_M_covered[__u])[__state._M_subexpr];
- if (!__sub.matched || __sub.first != __current)
- {
- auto __back = __sub.first;
- __sub.first = __current;
- __add_visited_state(__state._M_next);
- __sub.first = __back;
- }
- }
- break;
- case _S_opcode_subexpr_end:
- {
- auto& __cu = *_M_covered[__u];
- auto __back = __cu[__state._M_subexpr];
- __cu[__state._M_subexpr].second = __current;
- __cu[__state._M_subexpr].matched = true;
- __add_visited_state(__state._M_next);
- __cu[__state._M_subexpr] = __back;
- }
- break;
- case _S_opcode_line_begin_assertion:
- if (this->_M_at_begin())
- __add_visited_state(__state._M_next);
- break;
- case _S_opcode_line_end_assertion:
- if (this->_M_at_end())
- __add_visited_state(__state._M_next);
- break;
- case _S_opcode_word_boundry:
- if (this->_M_word_boundry(__state) == !__state._M_neg)
- __add_visited_state(__state._M_next);
- break;
- case _S_opcode_subexpr_lookahead:
- if (this->_M_lookahead(__state) == !__state._M_neg)
- __add_visited_state(__state._M_next);
- break;
- case _S_opcode_match:
- break;
- case _S_opcode_accept:
- break;
- default:
- _GLIBCXX_DEBUG_ASSERT(false);
- }
- }
- }
-
- template<typename _BiIter, typename _Alloc,
- typename _CharT, typename _TraitsT>
- void _BFSExecutor<_BiIter, _Alloc, _CharT, _TraitsT>::
- _M_move()
- {
- decltype(_M_covered) __next;
- for (auto& __it : _M_covered)
- {
- const auto& __state = _M_nfa[__it.first];
- if (__state._M_opcode == _S_opcode_match
- && __state._M_matches(*this->_M_current))
- if (__state._M_next != _S_invalid_state_id)
- if (__next.count(__state._M_next) == 0
- || *__it.second < *__next[__state._M_next])
- __next[__state._M_next] = move(__it.second);
- }
- _M_covered = move(__next);
- }
-
- template<typename _BiIter, typename _Alloc,
- typename _CharT, typename _TraitsT>
- bool _BFSExecutor<_BiIter, _Alloc, _CharT, _TraitsT>::
- _M_includes_some()
- {
- auto& __s = _M_nfa._M_final_states();
- auto& __t = _M_covered;
- bool __succ = false;
- if (__s.size() > 0 && __t.size() > 0)
- {
- auto __first = __s.begin();
- auto __second = __t.begin();
- while (__first != __s.end() && __second != __t.end())
- {
- if (*__first < __second->first)
- ++__first;
- else if (*__first > __second->first)
- ++__second;
- else
- {
- if (_M_cur_results == nullptr
- || *__second->second < *_M_cur_results)
- _M_cur_results =
- _ResultsPtr(new _ResultsEntry(*__second->second));
- __succ = true;
- ++__first;
- ++__second;
- }
}
+ break;
+ default:
+ _GLIBCXX_DEBUG_ASSERT(false);
}
- return __succ;
}
- // Return whether now is at some word boundry.
- template<typename _BiIter, typename _Alloc,
- typename _CharT, typename _TraitsT>
- bool _Executor<_BiIter, _Alloc, _CharT, _TraitsT>::
- _M_word_boundry(_State<_CharT, _TraitsT> __state) const
+ // Return whether now is at some word boundary.
+ template<typename _BiIter, typename _Alloc, typename _TraitsT,
+ bool __dfs_mode>
+ bool _Executor<_BiIter, _Alloc, _TraitsT, __dfs_mode>::
+ _M_word_boundary(_State<_TraitsT> __state) const
{
// By definition.
bool __ans = false;
auto __pre = _M_current;
--__pre;
if (!(_M_at_begin() && _M_at_end()))
- if (_M_at_begin())
- __ans = _M_is_word(*_M_current)
- && !(_M_flags & regex_constants::match_not_bow);
- else if (_M_at_end())
- __ans = _M_is_word(*__pre)
- && !(_M_flags & regex_constants::match_not_eow);
- else
- __ans = _M_is_word(*_M_current)
- != _M_is_word(*__pre);
+ {
+ if (_M_at_begin())
+ __ans = _M_is_word(*_M_current)
+ && !(_M_flags & regex_constants::match_not_bow);
+ else if (_M_at_end())
+ __ans = _M_is_word(*__pre)
+ && !(_M_flags & regex_constants::match_not_eow);
+ else
+ __ans = _M_is_word(*_M_current)
+ != _M_is_word(*__pre);
+ }
return __ans;
}
- // Return whether now match the given sub-NFA.
- template<typename _BiIter, typename _Alloc,
- typename _CharT, typename _TraitsT>
- bool _Executor<_BiIter, _Alloc, _CharT, _TraitsT>::
- _M_lookahead(_State<_CharT, _TraitsT> __state) const
- {
- auto __sub = __get_executor(this->_M_current,
- this->_M_end,
- this->_M_results,
- this->_M_re,
- this->_M_flags);
- __sub->_M_set_start(__state._M_alt);
- return __sub->_M_search_from_first();
- }
-
- template<typename _BiIter, typename _Alloc,
- typename _CharT, typename _TraitsT>
- std::unique_ptr<_Executor<_BiIter, _Alloc, _CharT, _TraitsT>>
- __get_executor(_BiIter __b,
- _BiIter __e,
- match_results<_BiIter, _Alloc>& __m,
- const basic_regex<_CharT, _TraitsT>& __re,
- regex_constants::match_flag_type __flags)
- {
- typedef std::unique_ptr<_Executor<_BiIter, _Alloc, _CharT, _TraitsT>>
- _ExecutorPtr;
- typedef _DFSExecutor<_BiIter, _Alloc, _CharT, _TraitsT> _DFSExecutorT;
- typedef _BFSExecutor<_BiIter, _Alloc, _CharT, _TraitsT> _BFSExecutorT;
- auto __p = std::static_pointer_cast<_NFA<_CharT, _TraitsT>>
- (__re._M_automaton);
- if (__p->_M_has_backref)
- return _ExecutorPtr(new _DFSExecutorT(__b, __e, __m, __re, __flags));
- return _ExecutorPtr(new _BFSExecutorT(__b, __e, __m, __re, __flags));
- }
-
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace __detail
} // namespace
diff --git a/libstdc++-v3/include/bits/regex_scanner.tcc b/libstdc++-v3/include/bits/regex_scanner.tcc
index abdbcc64f1f..f6cef6a04c2 100644
--- a/libstdc++-v3/include/bits/regex_scanner.tcc
+++ b/libstdc++-v3/include/bits/regex_scanner.tcc
@@ -56,8 +56,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_Scanner<_FwdIter>::
_Scanner(_FwdIter __begin, _FwdIter __end,
_FlagT __flags, std::locale __loc)
- : _M_current(__begin) , _M_end(__end) , _M_flags(__flags),
- _M_ctype(std::use_facet<_CtypeT>(__loc)), _M_state(_S_state_normal),
+ : _M_state(_S_state_normal), _M_current(__begin), _M_end(__end),
+ _M_flags(__flags),
+ _M_ctype(std::use_facet<_CtypeT>(__loc)),
_M_at_bracket_start(false),
_M_token_map
{
@@ -94,9 +95,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{'t', '\t'},
{'v', '\v'},
},
- _M_escape_map(_M_is_ecma()
- ? _M_ecma_escape_map
- : _M_awk_escape_map),
_M_ecma_spec_char
{
'^',
@@ -138,14 +136,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
'^',
'$',
},
- _M_eat_escape(_M_is_ecma()
- ? &_Scanner::_M_eat_escape_ecma
- : &_Scanner::_M_eat_escape_posix),
+ _M_escape_map(_M_is_ecma()
+ ? _M_ecma_escape_map
+ : _M_awk_escape_map),
_M_spec_char(_M_is_ecma()
? _M_ecma_spec_char
: _M_is_basic()
? _M_basic_spec_char
- : _M_extended_spec_char)
+ : _M_extended_spec_char),
+ _M_eat_escape(_M_is_ecma()
+ ? &_Scanner::_M_eat_escape_ecma
+ : &_Scanner::_M_eat_escape_posix)
{ _M_advance(); }
template<typename _FwdIter>
@@ -243,9 +244,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_state = _S_state_in_brace;
_M_token = _S_token_interval_begin;
}
- else if (_M_spec_char.count(__c)
- && __c != ']'
- && __c != '}'
+ else if ((_M_spec_char.count(_M_ctype.narrow(__c, '\0'))
+ && __c != ']'
+ && __c != '}')
|| (_M_is_grep() && __c == '\n'))
_M_token = _M_token_map.at(__c);
else
@@ -345,7 +346,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
++_M_current;
}
else
- __throw_regex_error(regex_constants::error_brace);
+ __throw_regex_error(regex_constants::error_badbrace);
}
else if (__c == '}')
{
@@ -353,7 +354,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_token = _S_token_interval_end;
}
else
- __throw_regex_error(regex_constants::error_brace);
+ __throw_regex_error(regex_constants::error_badbrace);
}
template<typename _FwdIter>
@@ -366,7 +367,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
auto __c = *_M_current++;
- if (_M_escape_map.count(__c)
+ if (_M_escape_map.count(_M_ctype.narrow(__c, '\0'))
&& (__c != 'b' || _M_state == _S_state_in_bracket))
{
_M_token = _S_token_ord_char;
@@ -428,6 +429,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
}
+ // Differences between styles:
+ // 1) Extended doesn't support backref, but basic does.
template<typename _FwdIter>
void
_Scanner<_FwdIter>::
@@ -438,7 +441,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
auto __c = *_M_current;
- if (_M_spec_char.count(__c))
+ if (_M_spec_char.count(_M_ctype.narrow(__c, '\0')))
{
_M_token = _S_token_ord_char;
_M_value.assign(1, __c);
@@ -449,13 +452,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_eat_escape_awk();
return;
}
- else if (_M_ctype.is(_CtypeT::digit, __c) && __c != '0')
+ else if (_M_is_basic() && _M_ctype.is(_CtypeT::digit, __c) && __c != '0')
{
_M_token = _S_token_backref;
_M_value.assign(1, __c);
}
else
- __throw_regex_error(regex_constants::error_escape);
+ {
+#ifdef __STRICT_ANSI__
+ __throw_regex_error(regex_constants::error_escape);
+#else
+ _M_token = _S_token_ord_char;
+ _M_value.assign(1, __c);
+#endif
+ }
++_M_current;
}
@@ -466,7 +476,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
auto __c = *_M_current++;
- if (_M_escape_map.count(__c))
+ if (_M_escape_map.count(_M_ctype.narrow(__c, '\0')))
{
_M_token = _S_token_ord_char;
_M_value.assign(1, _M_escape_map.at(__c));
@@ -506,10 +516,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|| *_M_current++ != __ch
|| _M_current == _M_end // skip __ch
|| *_M_current++ != ']') // skip ']'
- if (__ch == ':')
- __throw_regex_error(regex_constants::error_ctype);
- else
- __throw_regex_error(regex_constants::error_collate);
+ {
+ if (__ch == ':')
+ __throw_regex_error(regex_constants::error_ctype);
+ else
+ __throw_regex_error(regex_constants::error_collate);
+ }
}
#ifdef _GLIBCXX_DEBUG
diff --git a/libstdc++-v3/include/bits/shared_ptr_base.h b/libstdc++-v3/include/bits/shared_ptr_base.h
index fb19d0887dc..cf90d7a7cb3 100644
--- a/libstdc++-v3/include/bits/shared_ptr_base.h
+++ b/libstdc++-v3/include/bits/shared_ptr_base.h
@@ -459,10 +459,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_get_deleter(const std::type_info& __ti) noexcept
{
#ifdef __GXX_RTTI
- return __ti == typeid(_Sp_make_shared_tag) ? _M_ptr() : nullptr;
-#else
- return nullptr;
+ if (__ti == typeid(_Sp_make_shared_tag))
+ return const_cast<typename remove_cv<_Tp>::type*>(_M_ptr());
#endif
+ return nullptr;
}
private:
@@ -495,29 +495,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
template<typename _Ptr, typename _Deleter>
- __shared_count(_Ptr __p, _Deleter __d) : _M_pi(0)
- {
- // The allocator's value_type doesn't matter, will rebind it anyway.
- typedef std::allocator<int> _Alloc;
- typedef _Sp_counted_deleter<_Ptr, _Deleter, _Alloc, _Lp> _Sp_cd_type;
- typedef typename allocator_traits<_Alloc>::template
- rebind_traits<_Sp_cd_type> _Alloc_traits;
- typename _Alloc_traits::allocator_type __a;
- _Sp_cd_type* __mem = 0;
- __try
- {
- __mem = _Alloc_traits::allocate(__a, 1);
- _Alloc_traits::construct(__a, __mem, __p, std::move(__d));
- _M_pi = __mem;
- }
- __catch(...)
- {
- __d(__p); // Call _Deleter on __p.
- if (__mem)
- _Alloc_traits::deallocate(__a, __mem, 1);
- __throw_exception_again;
- }
- }
+ __shared_count(_Ptr __p, _Deleter __d)
+ : __shared_count(__p, std::move(__d), allocator<void>())
+ { }
template<typename _Ptr, typename _Deleter, typename _Alloc>
__shared_count(_Ptr __p, _Deleter __d, _Alloc __a) : _M_pi(0)
@@ -576,16 +556,29 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Special case for unique_ptr<_Tp,_Del> to provide the strong guarantee.
template<typename _Tp, typename _Del>
explicit
- __shared_count(std::unique_ptr<_Tp, _Del>&& __r)
- : _M_pi(_S_create_from_up(std::move(__r)))
- { __r.release(); }
+ __shared_count(std::unique_ptr<_Tp, _Del>&& __r) : _M_pi(0)
+ {
+ using _Ptr = typename unique_ptr<_Tp, _Del>::pointer;
+ using _Del2 = typename conditional<is_reference<_Del>::value,
+ reference_wrapper<typename remove_reference<_Del>::type>,
+ _Del>::type;
+ using _Sp_cd_type
+ = _Sp_counted_deleter<_Ptr, _Del2, allocator<void>, _Lp>;
+ using _Alloc = allocator<_Sp_cd_type>;
+ using _Alloc_traits = allocator_traits<_Alloc>;
+ _Alloc __a;
+ _Sp_cd_type* __mem = _Alloc_traits::allocate(__a, 1);
+ _Alloc_traits::construct(__a, __mem, __r.release(),
+ __r.get_deleter()); // non-throwing
+ _M_pi = __mem;
+ }
// Throw bad_weak_ptr when __r._M_get_use_count() == 0.
explicit __shared_count(const __weak_count<_Lp>& __r);
~__shared_count() noexcept
{
- if (_M_pi != 0)
+ if (_M_pi != nullptr)
_M_pi->_M_release();
}
@@ -647,28 +640,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
private:
friend class __weak_count<_Lp>;
- template<typename _Tp, typename _Del>
- static _Sp_counted_base<_Lp>*
- _S_create_from_up(std::unique_ptr<_Tp, _Del>&& __r,
- typename std::enable_if<!std::is_reference<_Del>::value>::type* = 0)
- {
- typedef typename unique_ptr<_Tp, _Del>::pointer _Ptr;
- return new _Sp_counted_deleter<_Ptr, _Del, std::allocator<void>,
- _Lp>(__r.get(), __r.get_deleter());
- }
-
- template<typename _Tp, typename _Del>
- static _Sp_counted_base<_Lp>*
- _S_create_from_up(std::unique_ptr<_Tp, _Del>&& __r,
- typename std::enable_if<std::is_reference<_Del>::value>::type* = 0)
- {
- typedef typename unique_ptr<_Tp, _Del>::pointer _Ptr;
- typedef typename std::remove_reference<_Del>::type _Del1;
- typedef std::reference_wrapper<_Del1> _Del2;
- return new _Sp_counted_deleter<_Ptr, _Del2, std::allocator<void>,
- _Lp>(__r.get(), std::ref(__r.get_deleter()));
- }
-
_Sp_counted_base<_Lp>* _M_pi;
};
@@ -804,6 +775,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: _M_ptr(__p), _M_refcount(__p)
{
__glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
+ static_assert( !is_void<_Tp>::value, "incomplete type" );
static_assert( sizeof(_Tp1) > 0, "incomplete type" );
__enable_shared_from_this_helper(_M_refcount, __p, __p);
}
@@ -884,9 +856,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: _M_ptr(__r.get()), _M_refcount()
{
__glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
- auto __tmp = std::__addressof(*__r.get());
+ auto __raw = _S_raw_ptr(__r.get());
_M_refcount = __shared_count<_Lp>(std::move(__r));
- __enable_shared_from_this_helper(_M_refcount, __tmp, __tmp);
+ __enable_shared_from_this_helper(_M_refcount, __raw, __raw);
}
#if _GLIBCXX_USE_DEPRECATED
@@ -1077,6 +1049,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_get_deleter(const std::type_info& __ti) const noexcept
{ return _M_refcount._M_get_deleter(__ti); }
+ template<typename _Tp1>
+ static _Tp1*
+ _S_raw_ptr(_Tp1* __ptr)
+ { return __ptr; }
+
+ template<typename _Tp1>
+ static auto
+ _S_raw_ptr(_Tp1 __ptr) -> decltype(std::__addressof(*__ptr))
+ { return std::__addressof(*__ptr); }
+
template<typename _Tp1, _Lock_policy _Lp1> friend class __shared_ptr;
template<typename _Tp1, _Lock_policy _Lp1> friend class __weak_ptr;
diff --git a/libstdc++-v3/include/bits/stl_algo.h b/libstdc++-v3/include/bits/stl_algo.h
index b06211e0100..b21d748b0bd 100644
--- a/libstdc++-v3/include/bits/stl_algo.h
+++ b/libstdc++-v3/include/bits/stl_algo.h
@@ -60,10 +60,10 @@
#include <bits/algorithmfwd.h>
#include <bits/stl_heap.h>
#include <bits/stl_tempbuf.h> // for _Temporary_buffer
+#include <bits/predefined_ops.h>
#if __cplusplus >= 201103L
#include <random> // for std::uniform_int_distribution
-#include <functional> // for std::bind
#endif
// See concept_check.h for the __glibcxx_*_requires macros.
@@ -72,129 +72,41 @@ namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
- /// Swaps the median value of *__a, *__b and *__c to *__a
- template<typename _Iterator>
- void
- __move_median_first(_Iterator __a, _Iterator __b, _Iterator __c)
- {
- // concept requirements
- __glibcxx_function_requires(_LessThanComparableConcept<
- typename iterator_traits<_Iterator>::value_type>)
-
- if (*__a < *__b)
- {
- if (*__b < *__c)
- std::iter_swap(__a, __b);
- else if (*__a < *__c)
- std::iter_swap(__a, __c);
- }
- else if (*__a < *__c)
- return;
- else if (*__b < *__c)
- std::iter_swap(__a, __c);
- else
- std::iter_swap(__a, __b);
- }
-
- /// Swaps the median value of *__a, *__b and *__c under __comp to *__a
+ /// Swaps the median value of *__a, *__b and *__c under __comp to *__result
template<typename _Iterator, typename _Compare>
void
- __move_median_first(_Iterator __a, _Iterator __b, _Iterator __c,
- _Compare __comp)
+ __move_median_to_first(_Iterator __result,_Iterator __a, _Iterator __b,
+ _Iterator __c, _Compare __comp)
{
- // concept requirements
- __glibcxx_function_requires(_BinaryFunctionConcept<_Compare, bool,
- typename iterator_traits<_Iterator>::value_type,
- typename iterator_traits<_Iterator>::value_type>)
-
- if (__comp(*__a, *__b))
+ if (__comp(__a, __b))
{
- if (__comp(*__b, *__c))
- std::iter_swap(__a, __b);
- else if (__comp(*__a, *__c))
- std::iter_swap(__a, __c);
+ if (__comp(__b, __c))
+ std::iter_swap(__result, __b);
+ else if (__comp(__a, __c))
+ std::iter_swap(__result, __c);
+ else
+ std::iter_swap(__result, __a);
}
- else if (__comp(*__a, *__c))
- return;
- else if (__comp(*__b, *__c))
- std::iter_swap(__a, __c);
+ else if (__comp(__a, __c))
+ std::iter_swap(__result, __a);
+ else if (__comp(__b, __c))
+ std::iter_swap(__result, __c);
else
- std::iter_swap(__a, __b);
+ std::iter_swap(__result, __b);
}
- // for_each
-
- /// This is an overload used by find() for the Input Iterator case.
- template<typename _InputIterator, typename _Tp>
- inline _InputIterator
- __find(_InputIterator __first, _InputIterator __last,
- const _Tp& __val, input_iterator_tag)
- {
- while (__first != __last && !(*__first == __val))
- ++__first;
- return __first;
- }
-
- /// This is an overload used by find_if() for the Input Iterator case.
+ /// This is an overload used by find algos for the Input Iterator case.
template<typename _InputIterator, typename _Predicate>
inline _InputIterator
__find_if(_InputIterator __first, _InputIterator __last,
_Predicate __pred, input_iterator_tag)
{
- while (__first != __last && !bool(__pred(*__first)))
+ while (__first != __last && !__pred(__first))
++__first;
return __first;
}
- /// This is an overload used by find() for the RAI case.
- template<typename _RandomAccessIterator, typename _Tp>
- _RandomAccessIterator
- __find(_RandomAccessIterator __first, _RandomAccessIterator __last,
- const _Tp& __val, random_access_iterator_tag)
- {
- typename iterator_traits<_RandomAccessIterator>::difference_type
- __trip_count = (__last - __first) >> 2;
-
- for (; __trip_count > 0; --__trip_count)
- {
- if (*__first == __val)
- return __first;
- ++__first;
-
- if (*__first == __val)
- return __first;
- ++__first;
-
- if (*__first == __val)
- return __first;
- ++__first;
-
- if (*__first == __val)
- return __first;
- ++__first;
- }
-
- switch (__last - __first)
- {
- case 3:
- if (*__first == __val)
- return __first;
- ++__first;
- case 2:
- if (*__first == __val)
- return __first;
- ++__first;
- case 1:
- if (*__first == __val)
- return __first;
- ++__first;
- case 0:
- default:
- return __last;
- }
- }
-
- /// This is an overload used by find_if() for the RAI case.
+ /// This is an overload used by find algos for the RAI case.
template<typename _RandomAccessIterator, typename _Predicate>
_RandomAccessIterator
__find_if(_RandomAccessIterator __first, _RandomAccessIterator __last,
@@ -205,19 +117,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
for (; __trip_count > 0; --__trip_count)
{
- if (__pred(*__first))
+ if (__pred(__first))
return __first;
++__first;
- if (__pred(*__first))
+ if (__pred(__first))
return __first;
++__first;
- if (__pred(*__first))
+ if (__pred(__first))
return __first;
++__first;
- if (__pred(*__first))
+ if (__pred(__first))
return __first;
++__first;
}
@@ -225,15 +137,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
switch (__last - __first)
{
case 3:
- if (__pred(*__first))
+ if (__pred(__first))
return __first;
++__first;
case 2:
- if (__pred(*__first))
+ if (__pred(__first))
return __first;
++__first;
case 1:
- if (__pred(*__first))
+ if (__pred(__first))
return __first;
++__first;
case 0:
@@ -242,63 +154,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
}
- /// This is an overload used by find_if_not() for the Input Iterator case.
- template<typename _InputIterator, typename _Predicate>
- inline _InputIterator
- __find_if_not(_InputIterator __first, _InputIterator __last,
- _Predicate __pred, input_iterator_tag)
- {
- while (__first != __last && bool(__pred(*__first)))
- ++__first;
- return __first;
- }
-
- /// This is an overload used by find_if_not() for the RAI case.
- template<typename _RandomAccessIterator, typename _Predicate>
- _RandomAccessIterator
- __find_if_not(_RandomAccessIterator __first, _RandomAccessIterator __last,
- _Predicate __pred, random_access_iterator_tag)
+ template<typename _Iterator, typename _Predicate>
+ inline _Iterator
+ __find_if(_Iterator __first, _Iterator __last, _Predicate __pred)
{
- typename iterator_traits<_RandomAccessIterator>::difference_type
- __trip_count = (__last - __first) >> 2;
-
- for (; __trip_count > 0; --__trip_count)
- {
- if (!bool(__pred(*__first)))
- return __first;
- ++__first;
-
- if (!bool(__pred(*__first)))
- return __first;
- ++__first;
-
- if (!bool(__pred(*__first)))
- return __first;
- ++__first;
-
- if (!bool(__pred(*__first)))
- return __first;
- ++__first;
- }
-
- switch (__last - __first)
- {
- case 3:
- if (!bool(__pred(*__first)))
- return __first;
- ++__first;
- case 2:
- if (!bool(__pred(*__first)))
- return __first;
- ++__first;
- case 1:
- if (!bool(__pred(*__first)))
- return __first;
- ++__first;
- case 0:
- default:
- return __last;
- }
+ return __find_if(__first, __last, __pred,
+ std::__iterator_category(__first));
}
/// Provided for stable_partition to use.
@@ -307,8 +168,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__find_if_not(_InputIterator __first, _InputIterator __last,
_Predicate __pred)
{
- return std::__find_if_not(__first, __last, __pred,
- std::__iterator_category(__first));
+ return std::__find_if(__first, __last,
+ __gnu_cxx::__ops::__negate(__pred),
+ std::__iterator_category(__first));
}
/// Like find_if_not(), but uses and updates a count of the
@@ -319,7 +181,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__find_if_not_n(_InputIterator __first, _Distance& __len, _Predicate __pred)
{
for (; __len; --__len, ++__first)
- if (!bool(__pred(*__first)))
+ if (!__pred(__first))
break;
return __first;
}
@@ -337,98 +199,73 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// count_if
// search
- /**
- * This is an uglified
- * search_n(_ForwardIterator, _ForwardIterator, _Integer, const _Tp&)
- * overloaded for forward iterators.
- */
- template<typename _ForwardIterator, typename _Integer, typename _Tp>
- _ForwardIterator
- __search_n(_ForwardIterator __first, _ForwardIterator __last,
- _Integer __count, const _Tp& __val,
- std::forward_iterator_tag)
+ template<typename _ForwardIterator1, typename _ForwardIterator2,
+ typename _BinaryPredicate>
+ _ForwardIterator1
+ __search(_ForwardIterator1 __first1, _ForwardIterator1 __last1,
+ _ForwardIterator2 __first2, _ForwardIterator2 __last2,
+ _BinaryPredicate __predicate)
{
- __first = _GLIBCXX_STD_A::find(__first, __last, __val);
- while (__first != __last)
- {
- typename iterator_traits<_ForwardIterator>::difference_type
- __n = __count;
- _ForwardIterator __i = __first;
- ++__i;
- while (__i != __last && __n != 1 && *__i == __val)
- {
- ++__i;
- --__n;
- }
- if (__n == 1)
- return __first;
- if (__i == __last)
- return __last;
- __first = _GLIBCXX_STD_A::find(++__i, __last, __val);
- }
- return __last;
- }
+ // Test for empty ranges
+ if (__first1 == __last1 || __first2 == __last2)
+ return __first1;
- /**
- * This is an uglified
- * search_n(_ForwardIterator, _ForwardIterator, _Integer, const _Tp&)
- * overloaded for random access iterators.
- */
- template<typename _RandomAccessIter, typename _Integer, typename _Tp>
- _RandomAccessIter
- __search_n(_RandomAccessIter __first, _RandomAccessIter __last,
- _Integer __count, const _Tp& __val,
- std::random_access_iterator_tag)
- {
-
- typedef typename std::iterator_traits<_RandomAccessIter>::difference_type
- _DistanceType;
+ // Test for a pattern of length 1.
+ _ForwardIterator2 __p1(__first2);
+ if (++__p1 == __last2)
+ return std::__find_if(__first1, __last1,
+ __gnu_cxx::__ops::__iter_comp_iter(__predicate, __first2));
- _DistanceType __tailSize = __last - __first;
- _DistanceType __remainder = __count;
+ // General case.
+ _ForwardIterator2 __p;
+ _ForwardIterator1 __current = __first1;
- while (__remainder <= __tailSize) // the main loop...
+ for (;;)
{
- __first += __remainder;
- __tailSize -= __remainder;
- // __first here is always pointing to one past the last element of
- // next possible match.
- _RandomAccessIter __backTrack = __first;
- while (*--__backTrack == __val)
+ __first1 =
+ std::__find_if(__first1, __last1,
+ __gnu_cxx::__ops::__iter_comp_iter(__predicate, __first2));
+
+ if (__first1 == __last1)
+ return __last1;
+
+ __p = __p1;
+ __current = __first1;
+ if (++__current == __last1)
+ return __last1;
+
+ while (__predicate(__current, __p))
{
- if (--__remainder == 0)
- return (__first - __count); // Success
+ if (++__p == __last2)
+ return __first1;
+ if (++__current == __last1)
+ return __last1;
}
- __remainder = __count + 1 - (__first - __backTrack);
+ ++__first1;
}
- return __last; // Failure
+ return __first1;
}
// search_n
/**
- * This is an uglified
- * search_n(_ForwardIterator, _ForwardIterator, _Integer, const _Tp&,
- * _BinaryPredicate)
- * overloaded for forward iterators.
+ * This is an helper function for search_n overloaded for forward iterators.
*/
- template<typename _ForwardIterator, typename _Integer, typename _Tp,
- typename _BinaryPredicate>
+ template<typename _ForwardIterator, typename _Integer,
+ typename _UnaryPredicate>
_ForwardIterator
- __search_n(_ForwardIterator __first, _ForwardIterator __last,
- _Integer __count, const _Tp& __val,
- _BinaryPredicate __binary_pred, std::forward_iterator_tag)
+ __search_n_aux(_ForwardIterator __first, _ForwardIterator __last,
+ _Integer __count, _UnaryPredicate __unary_pred,
+ std::forward_iterator_tag)
{
- while (__first != __last && !bool(__binary_pred(*__first, __val)))
- ++__first;
-
+ __first = std::__find_if(__first, __last, __unary_pred);
while (__first != __last)
{
typename iterator_traits<_ForwardIterator>::difference_type
__n = __count;
_ForwardIterator __i = __first;
++__i;
- while (__i != __last && __n != 1 && bool(__binary_pred(*__i, __val)))
+ while (__i != __last && __n != 1 && __unary_pred(__i))
{
++__i;
--__n;
@@ -437,28 +274,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return __first;
if (__i == __last)
return __last;
- __first = ++__i;
- while (__first != __last
- && !bool(__binary_pred(*__first, __val)))
- ++__first;
+ __first = std::__find_if(++__i, __last, __unary_pred);
}
return __last;
}
/**
- * This is an uglified
- * search_n(_ForwardIterator, _ForwardIterator, _Integer, const _Tp&,
- * _BinaryPredicate)
- * overloaded for random access iterators.
+ * This is an helper function for search_n overloaded for random access
+ * iterators.
*/
- template<typename _RandomAccessIter, typename _Integer, typename _Tp,
- typename _BinaryPredicate>
+ template<typename _RandomAccessIter, typename _Integer,
+ typename _UnaryPredicate>
_RandomAccessIter
- __search_n(_RandomAccessIter __first, _RandomAccessIter __last,
- _Integer __count, const _Tp& __val,
- _BinaryPredicate __binary_pred, std::random_access_iterator_tag)
+ __search_n_aux(_RandomAccessIter __first, _RandomAccessIter __last,
+ _Integer __count, _UnaryPredicate __unary_pred,
+ std::random_access_iterator_tag)
{
-
typedef typename std::iterator_traits<_RandomAccessIter>::difference_type
_DistanceType;
@@ -472,7 +303,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// __first here is always pointing to one past the last element of
// next possible match.
_RandomAccessIter __backTrack = __first;
- while (__binary_pred(*--__backTrack, __val))
+ while (__unary_pred(--__backTrack))
{
if (--__remainder == 0)
return (__first - __count); // Success
@@ -482,34 +313,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return __last; // Failure
}
- // find_end for forward iterators.
- template<typename _ForwardIterator1, typename _ForwardIterator2>
- _ForwardIterator1
- __find_end(_ForwardIterator1 __first1, _ForwardIterator1 __last1,
- _ForwardIterator2 __first2, _ForwardIterator2 __last2,
- forward_iterator_tag, forward_iterator_tag)
+ template<typename _ForwardIterator, typename _Integer,
+ typename _UnaryPredicate>
+ _ForwardIterator
+ __search_n(_ForwardIterator __first, _ForwardIterator __last,
+ _Integer __count,
+ _UnaryPredicate __unary_pred)
{
- if (__first2 == __last2)
- return __last1;
- else
- {
- _ForwardIterator1 __result = __last1;
- while (1)
- {
- _ForwardIterator1 __new_result
- = _GLIBCXX_STD_A::search(__first1, __last1, __first2, __last2);
- if (__new_result == __last1)
- return __result;
- else
- {
- __result = __new_result;
- __first1 = __new_result;
- ++__first1;
- }
- }
- }
+ if (__count <= 0)
+ return __first;
+
+ if (__count == 1)
+ return std::__find_if(__first, __last, __unary_pred);
+
+ return std::__search_n_aux(__first, __last, __count, __unary_pred,
+ std::__iterator_category(__first));
}
+ // find_end for forward iterators.
template<typename _ForwardIterator1, typename _ForwardIterator2,
typename _BinaryPredicate>
_ForwardIterator1
@@ -520,61 +341,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
if (__first2 == __last2)
return __last1;
- else
+
+ _ForwardIterator1 __result = __last1;
+ while (1)
{
- _ForwardIterator1 __result = __last1;
- while (1)
+ _ForwardIterator1 __new_result
+ = std::__search(__first1, __last1, __first2, __last2, __comp);
+ if (__new_result == __last1)
+ return __result;
+ else
{
- _ForwardIterator1 __new_result
- = _GLIBCXX_STD_A::search(__first1, __last1, __first2,
- __last2, __comp);
- if (__new_result == __last1)
- return __result;
- else
- {
- __result = __new_result;
- __first1 = __new_result;
- ++__first1;
- }
+ __result = __new_result;
+ __first1 = __new_result;
+ ++__first1;
}
}
}
// find_end for bidirectional iterators (much faster).
- template<typename _BidirectionalIterator1, typename _BidirectionalIterator2>
- _BidirectionalIterator1
- __find_end(_BidirectionalIterator1 __first1,
- _BidirectionalIterator1 __last1,
- _BidirectionalIterator2 __first2,
- _BidirectionalIterator2 __last2,
- bidirectional_iterator_tag, bidirectional_iterator_tag)
- {
- // concept requirements
- __glibcxx_function_requires(_BidirectionalIteratorConcept<
- _BidirectionalIterator1>)
- __glibcxx_function_requires(_BidirectionalIteratorConcept<
- _BidirectionalIterator2>)
-
- typedef reverse_iterator<_BidirectionalIterator1> _RevIterator1;
- typedef reverse_iterator<_BidirectionalIterator2> _RevIterator2;
-
- _RevIterator1 __rlast1(__first1);
- _RevIterator2 __rlast2(__first2);
- _RevIterator1 __rresult = _GLIBCXX_STD_A::search(_RevIterator1(__last1),
- __rlast1,
- _RevIterator2(__last2),
- __rlast2);
-
- if (__rresult == __rlast1)
- return __last1;
- else
- {
- _BidirectionalIterator1 __result = __rresult.base();
- std::advance(__result, -std::distance(__first2, __last2));
- return __result;
- }
- }
-
template<typename _BidirectionalIterator1, typename _BidirectionalIterator2,
typename _BinaryPredicate>
_BidirectionalIterator1
@@ -596,9 +380,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_RevIterator1 __rlast1(__first1);
_RevIterator2 __rlast2(__first2);
- _RevIterator1 __rresult = std::search(_RevIterator1(__last1), __rlast1,
- _RevIterator2(__last2), __rlast2,
- __comp);
+ _RevIterator1 __rresult = std::__search(_RevIterator1(__last1), __rlast1,
+ _RevIterator2(__last2), __rlast2,
+ __comp);
if (__rresult == __rlast1)
return __last1;
@@ -627,7 +411,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* [__first2,__last2) and returns an iterator to the __first
* element of the sub-sequence, or @p __last1 if the sub-sequence
* is not found. The sub-sequence will be the last such
- * subsequence contained in [__first,__last1).
+ * subsequence contained in [__first1,__last1).
*
* Because the sub-sequence must lie completely within the range @p
* [__first1,__last1) it must start at a position less than @p
@@ -652,7 +436,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return std::__find_end(__first1, __last1, __first2, __last2,
std::__iterator_category(__first1),
- std::__iterator_category(__first2));
+ std::__iterator_category(__first2),
+ __gnu_cxx::__ops::__iter_equal_to_iter());
}
/**
@@ -702,7 +487,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return std::__find_end(__first1, __last1, __first2, __last2,
std::__iterator_category(__first1),
std::__iterator_category(__first2),
- __comp);
+ __gnu_cxx::__ops::__iter_comp_iter(__comp));
}
#if __cplusplus >= 201103L
@@ -778,7 +563,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__glibcxx_function_requires(_UnaryPredicateConcept<_Predicate,
typename iterator_traits<_InputIterator>::value_type>)
__glibcxx_requires_valid_range(__first, __last);
- return std::__find_if_not(__first, __last, __pred);
+ return std::__find_if_not(__first, __last,
+ __gnu_cxx::__ops::__pred_iter(__pred));
}
/**
@@ -847,6 +633,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
#endif
+ template<typename _InputIterator, typename _OutputIterator,
+ typename _Predicate>
+ _OutputIterator
+ __remove_copy_if(_InputIterator __first, _InputIterator __last,
+ _OutputIterator __result, _Predicate __pred)
+ {
+ for (; __first != __last; ++__first)
+ if (!__pred(__first))
+ {
+ *__result = *__first;
+ ++__result;
+ }
+ return __result;
+ }
/**
* @brief Copy a sequence, removing elements of a given value.
@@ -863,7 +663,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* are copied is unchanged.
*/
template<typename _InputIterator, typename _OutputIterator, typename _Tp>
- _OutputIterator
+ inline _OutputIterator
remove_copy(_InputIterator __first, _InputIterator __last,
_OutputIterator __result, const _Tp& __value)
{
@@ -875,13 +675,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typename iterator_traits<_InputIterator>::value_type, _Tp>)
__glibcxx_requires_valid_range(__first, __last);
- for (; __first != __last; ++__first)
- if (!(*__first == __value))
- {
- *__result = *__first;
- ++__result;
- }
- return __result;
+ return std::__remove_copy_if(__first, __last, __result,
+ __gnu_cxx::__ops::__iter_equals_val(__value));
}
/**
@@ -901,7 +696,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*/
template<typename _InputIterator, typename _OutputIterator,
typename _Predicate>
- _OutputIterator
+ inline _OutputIterator
remove_copy_if(_InputIterator __first, _InputIterator __last,
_OutputIterator __result, _Predicate __pred)
{
@@ -913,13 +708,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typename iterator_traits<_InputIterator>::value_type>)
__glibcxx_requires_valid_range(__first, __last);
- for (; __first != __last; ++__first)
- if (!bool(__pred(*__first)))
- {
- *__result = *__first;
- ++__result;
- }
- return __result;
+ return std::__remove_copy_if(__first, __last, __result,
+ __gnu_cxx::__ops::__pred_iter(__pred));
}
#if __cplusplus >= 201103L
@@ -961,7 +751,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return __result;
}
-
template<typename _InputIterator, typename _Size, typename _OutputIterator>
_OutputIterator
__copy_n(_InputIterator __first, _Size __n,
@@ -1063,6 +852,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
#endif
+ template<typename _ForwardIterator, typename _Predicate>
+ _ForwardIterator
+ __remove_if(_ForwardIterator __first, _ForwardIterator __last,
+ _Predicate __pred)
+ {
+ __first = std::__find_if(__first, __last, __pred);
+ if (__first == __last)
+ return __first;
+ _ForwardIterator __result = __first;
+ ++__first;
+ for (; __first != __last; ++__first)
+ if (!__pred(__first))
+ {
+ *__result = _GLIBCXX_MOVE(*__first);
+ ++__result;
+ }
+ return __result;
+ }
+
/**
* @brief Remove elements from a sequence.
* @ingroup mutating_algorithms
@@ -1081,7 +889,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* are still present, but their value is unspecified.
*/
template<typename _ForwardIterator, typename _Tp>
- _ForwardIterator
+ inline _ForwardIterator
remove(_ForwardIterator __first, _ForwardIterator __last,
const _Tp& __value)
{
@@ -1092,18 +900,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typename iterator_traits<_ForwardIterator>::value_type, _Tp>)
__glibcxx_requires_valid_range(__first, __last);
- __first = _GLIBCXX_STD_A::find(__first, __last, __value);
- if(__first == __last)
- return __first;
- _ForwardIterator __result = __first;
- ++__first;
- for(; __first != __last; ++__first)
- if(!(*__first == __value))
- {
- *__result = _GLIBCXX_MOVE(*__first);
- ++__result;
- }
- return __result;
+ return std::__remove_if(__first, __last,
+ __gnu_cxx::__ops::__iter_equals_val(__value));
}
/**
@@ -1124,7 +922,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* are still present, but their value is unspecified.
*/
template<typename _ForwardIterator, typename _Predicate>
- _ForwardIterator
+ inline _ForwardIterator
remove_if(_ForwardIterator __first, _ForwardIterator __last,
_Predicate __pred)
{
@@ -1135,18 +933,44 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typename iterator_traits<_ForwardIterator>::value_type>)
__glibcxx_requires_valid_range(__first, __last);
- __first = _GLIBCXX_STD_A::find_if(__first, __last, __pred);
- if(__first == __last)
- return __first;
- _ForwardIterator __result = __first;
+ return std::__remove_if(__first, __last,
+ __gnu_cxx::__ops::__pred_iter(__pred));
+ }
+
+ template<typename _ForwardIterator, typename _BinaryPredicate>
+ _ForwardIterator
+ __adjacent_find(_ForwardIterator __first, _ForwardIterator __last,
+ _BinaryPredicate __binary_pred)
+ {
+ if (__first == __last)
+ return __last;
+ _ForwardIterator __next = __first;
+ while (++__next != __last)
+ {
+ if (__binary_pred(__first, __next))
+ return __first;
+ __first = __next;
+ }
+ return __last;
+ }
+
+ template<typename _ForwardIterator, typename _BinaryPredicate>
+ _ForwardIterator
+ __unique(_ForwardIterator __first, _ForwardIterator __last,
+ _BinaryPredicate __binary_pred)
+ {
+ // Skip the beginning, if already unique.
+ __first = std::__adjacent_find(__first, __last, __binary_pred);
+ if (__first == __last)
+ return __last;
+
+ // Do the real copy work.
+ _ForwardIterator __dest = __first;
++__first;
- for(; __first != __last; ++__first)
- if(!bool(__pred(*__first)))
- {
- *__result = _GLIBCXX_MOVE(*__first);
- ++__result;
- }
- return __result;
+ while (++__first != __last)
+ if (!__binary_pred(__dest, __first))
+ *++__dest = _GLIBCXX_MOVE(*__first);
+ return ++__dest;
}
/**
@@ -1164,7 +988,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* are still present, but their value is unspecified.
*/
template<typename _ForwardIterator>
- _ForwardIterator
+ inline _ForwardIterator
unique(_ForwardIterator __first, _ForwardIterator __last)
{
// concept requirements
@@ -1174,18 +998,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typename iterator_traits<_ForwardIterator>::value_type>)
__glibcxx_requires_valid_range(__first, __last);
- // Skip the beginning, if already unique.
- __first = _GLIBCXX_STD_A::adjacent_find(__first, __last);
- if (__first == __last)
- return __last;
-
- // Do the real copy work.
- _ForwardIterator __dest = __first;
- ++__first;
- while (++__first != __last)
- if (!(*__dest == *__first))
- *++__dest = _GLIBCXX_MOVE(*__first);
- return ++__dest;
+ return std::__unique(__first, __last,
+ __gnu_cxx::__ops::__iter_equal_to_iter());
}
/**
@@ -1204,7 +1018,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* are still present, but their value is unspecified.
*/
template<typename _ForwardIterator, typename _BinaryPredicate>
- _ForwardIterator
+ inline _ForwardIterator
unique(_ForwardIterator __first, _ForwardIterator __last,
_BinaryPredicate __binary_pred)
{
@@ -1216,83 +1030,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typename iterator_traits<_ForwardIterator>::value_type>)
__glibcxx_requires_valid_range(__first, __last);
- // Skip the beginning, if already unique.
- __first = _GLIBCXX_STD_A::adjacent_find(__first, __last, __binary_pred);
- if (__first == __last)
- return __last;
-
- // Do the real copy work.
- _ForwardIterator __dest = __first;
- ++__first;
- while (++__first != __last)
- if (!bool(__binary_pred(*__dest, *__first)))
- *++__dest = _GLIBCXX_MOVE(*__first);
- return ++__dest;
- }
-
- /**
- * This is an uglified unique_copy(_InputIterator, _InputIterator,
- * _OutputIterator)
- * overloaded for forward iterators and output iterator as result.
- */
- template<typename _ForwardIterator, typename _OutputIterator>
- _OutputIterator
- __unique_copy(_ForwardIterator __first, _ForwardIterator __last,
- _OutputIterator __result,
- forward_iterator_tag, output_iterator_tag)
- {
- // concept requirements -- taken care of in dispatching function
- _ForwardIterator __next = __first;
- *__result = *__first;
- while (++__next != __last)
- if (!(*__first == *__next))
- {
- __first = __next;
- *++__result = *__first;
- }
- return ++__result;
- }
-
- /**
- * This is an uglified unique_copy(_InputIterator, _InputIterator,
- * _OutputIterator)
- * overloaded for input iterators and output iterator as result.
- */
- template<typename _InputIterator, typename _OutputIterator>
- _OutputIterator
- __unique_copy(_InputIterator __first, _InputIterator __last,
- _OutputIterator __result,
- input_iterator_tag, output_iterator_tag)
- {
- // concept requirements -- taken care of in dispatching function
- typename iterator_traits<_InputIterator>::value_type __value = *__first;
- *__result = __value;
- while (++__first != __last)
- if (!(__value == *__first))
- {
- __value = *__first;
- *++__result = __value;
- }
- return ++__result;
- }
-
- /**
- * This is an uglified unique_copy(_InputIterator, _InputIterator,
- * _OutputIterator)
- * overloaded for input iterators and forward iterator as result.
- */
- template<typename _InputIterator, typename _ForwardIterator>
- _ForwardIterator
- __unique_copy(_InputIterator __first, _InputIterator __last,
- _ForwardIterator __result,
- input_iterator_tag, forward_iterator_tag)
- {
- // concept requirements -- taken care of in dispatching function
- *__result = *__first;
- while (++__first != __last)
- if (!(*__result == *__first))
- *++__result = *__first;
- return ++__result;
+ return std::__unique(__first, __last,
+ __gnu_cxx::__ops::__iter_comp_iter(__binary_pred));
}
/**
@@ -1316,7 +1055,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_ForwardIterator __next = __first;
*__result = *__first;
while (++__next != __last)
- if (!bool(__binary_pred(*__first, *__next)))
+ if (!__binary_pred(__first, __next))
{
__first = __next;
*++__result = *__first;
@@ -1343,9 +1082,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typename iterator_traits<_InputIterator>::value_type>)
typename iterator_traits<_InputIterator>::value_type __value = *__first;
+ __decltype(__gnu_cxx::__ops::__iter_comp_val(__binary_pred))
+ __rebound_pred
+ = __gnu_cxx::__ops::__iter_comp_val(__binary_pred);
*__result = __value;
while (++__first != __last)
- if (!bool(__binary_pred(__value, *__first)))
+ if (!__rebound_pred(__first, __value))
{
__value = *__first;
*++__result = __value;
@@ -1370,10 +1112,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate,
typename iterator_traits<_ForwardIterator>::value_type,
typename iterator_traits<_InputIterator>::value_type>)
-
*__result = *__first;
while (++__first != __last)
- if (!bool(__binary_pred(*__result, *__first)))
+ if (!__binary_pred(__result, __first))
*++__result = *__first;
return ++__result;
}
@@ -1675,9 +1416,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__glibcxx_requires_valid_range(__first, __middle);
__glibcxx_requires_valid_range(__middle, __last);
- typedef typename iterator_traits<_ForwardIterator>::iterator_category
- _IterType;
- std::__rotate(__first, __middle, __last, _IterType());
+ std::__rotate(__first, __middle, __last,
+ std::__iterator_category(__first));
}
/**
@@ -1701,7 +1441,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* for each @p n in the range @p [0,__last-__first).
*/
template<typename _ForwardIterator, typename _OutputIterator>
- _OutputIterator
+ inline _OutputIterator
rotate_copy(_ForwardIterator __first, _ForwardIterator __middle,
_ForwardIterator __last, _OutputIterator __result)
{
@@ -1800,10 +1540,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
/// This is a helper function...
- /// Requires __first != __last and !__pred(*__first)
+ /// Requires __first != __last and !__pred(__first)
/// and __len == distance(__first, __last).
///
- /// !__pred(*__first) allows us to guarantee that we don't
+ /// !__pred(__first) allows us to guarantee that we don't
/// move-assign an element onto itself.
template<typename _ForwardIterator, typename _Pointer, typename _Predicate,
typename _Distance>
@@ -1818,14 +1558,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
_ForwardIterator __result1 = __first;
_Pointer __result2 = __buffer;
- // The precondition guarantees that !__pred(*__first), so
+ // The precondition guarantees that !__pred(__first), so
// move that element to the buffer before starting the loop.
// This ensures that we only call __pred once per element.
*__result2 = _GLIBCXX_MOVE(*__first);
++__result2;
++__first;
for (; __first != __last; ++__first)
- if (__pred(*__first))
+ if (__pred(__first))
{
*__result1 = _GLIBCXX_MOVE(*__first);
++__result1;
@@ -1862,6 +1602,34 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
}
+ template<typename _ForwardIterator, typename _Predicate>
+ _ForwardIterator
+ __stable_partition(_ForwardIterator __first, _ForwardIterator __last,
+ _Predicate __pred)
+ {
+ __first = std::__find_if_not(__first, __last, __pred);
+
+ if (__first == __last)
+ return __first;
+
+ typedef typename iterator_traits<_ForwardIterator>::value_type
+ _ValueType;
+ typedef typename iterator_traits<_ForwardIterator>::difference_type
+ _DistanceType;
+
+ _Temporary_buffer<_ForwardIterator, _ValueType> __buf(__first, __last);
+ if (__buf.size() > 0)
+ return
+ std::__stable_partition_adaptive(__first, __last, __pred,
+ _DistanceType(__buf.requested_size()),
+ __buf.begin(),
+ _DistanceType(__buf.size()));
+ else
+ return
+ std::__inplace_stable_partition(__first, __pred,
+ _DistanceType(__buf.requested_size()));
+ }
+
/**
* @brief Move elements for which a predicate is true to the beginning
* of a sequence, preserving relative ordering.
@@ -1880,7 +1648,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* relative ordering after calling @p stable_partition().
*/
template<typename _ForwardIterator, typename _Predicate>
- _ForwardIterator
+ inline _ForwardIterator
stable_partition(_ForwardIterator __first, _ForwardIterator __last,
_Predicate __pred)
{
@@ -1891,43 +1659,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typename iterator_traits<_ForwardIterator>::value_type>)
__glibcxx_requires_valid_range(__first, __last);
- __first = std::__find_if_not(__first, __last, __pred);
-
- if (__first == __last)
- return __first;
- else
- {
- typedef typename iterator_traits<_ForwardIterator>::value_type
- _ValueType;
- typedef typename iterator_traits<_ForwardIterator>::difference_type
- _DistanceType;
-
- _Temporary_buffer<_ForwardIterator, _ValueType> __buf(__first,
- __last);
- if (__buf.size() > 0)
- return
- std::__stable_partition_adaptive(__first, __last, __pred,
- _DistanceType(__buf.requested_size()),
- __buf.begin(),
- _DistanceType(__buf.size()));
- else
- return
- std::__inplace_stable_partition(__first, __pred,
- _DistanceType(__buf.requested_size()));
- }
- }
-
- /// This is a helper function for the sort routines.
- template<typename _RandomAccessIterator>
- void
- __heap_select(_RandomAccessIterator __first,
- _RandomAccessIterator __middle,
- _RandomAccessIterator __last)
- {
- std::make_heap(__first, __middle);
- for (_RandomAccessIterator __i = __middle; __i < __last; ++__i)
- if (*__i < *__first)
- std::__pop_heap(__first, __middle, __i);
+ return std::__stable_partition(__first, __last,
+ __gnu_cxx::__ops::__pred_iter(__pred));
}
/// This is a helper function for the sort routines.
@@ -1937,14 +1670,51 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_RandomAccessIterator __middle,
_RandomAccessIterator __last, _Compare __comp)
{
- std::make_heap(__first, __middle, __comp);
+ std::__make_heap(__first, __middle, __comp);
for (_RandomAccessIterator __i = __middle; __i < __last; ++__i)
- if (__comp(*__i, *__first))
+ if (__comp(__i, __first))
std::__pop_heap(__first, __middle, __i, __comp);
}
// partial_sort
+ template<typename _InputIterator, typename _RandomAccessIterator,
+ typename _Compare>
+ _RandomAccessIterator
+ __partial_sort_copy(_InputIterator __first, _InputIterator __last,
+ _RandomAccessIterator __result_first,
+ _RandomAccessIterator __result_last,
+ _Compare __comp)
+ {
+ typedef typename iterator_traits<_InputIterator>::value_type
+ _InputValueType;
+ typedef iterator_traits<_RandomAccessIterator> _RItTraits;
+ typedef typename _RItTraits::difference_type _DistanceType;
+
+ if (__result_first == __result_last)
+ return __result_last;
+ _RandomAccessIterator __result_real_last = __result_first;
+ while (__first != __last && __result_real_last != __result_last)
+ {
+ *__result_real_last = *__first;
+ ++__result_real_last;
+ ++__first;
+ }
+
+ std::__make_heap(__result_first, __result_real_last, __comp);
+ while (__first != __last)
+ {
+ if (__comp(__first, __result_first))
+ std::__adjust_heap(__result_first, _DistanceType(0),
+ _DistanceType(__result_real_last
+ - __result_first),
+ _InputValueType(*__first), __comp);
+ ++__first;
+ }
+ std::__sort_heap(__result_first, __result_real_last, __comp);
+ return __result_real_last;
+ }
+
/**
* @brief Copy the smallest elements of a sequence.
* @ingroup sorting_algorithms
@@ -1964,7 +1734,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* The value returned is @p __result_first+N.
*/
template<typename _InputIterator, typename _RandomAccessIterator>
- _RandomAccessIterator
+ inline _RandomAccessIterator
partial_sort_copy(_InputIterator __first, _InputIterator __last,
_RandomAccessIterator __result_first,
_RandomAccessIterator __result_last)
@@ -1986,27 +1756,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__glibcxx_requires_valid_range(__first, __last);
__glibcxx_requires_valid_range(__result_first, __result_last);
- if (__result_first == __result_last)
- return __result_last;
- _RandomAccessIterator __result_real_last = __result_first;
- while(__first != __last && __result_real_last != __result_last)
- {
- *__result_real_last = *__first;
- ++__result_real_last;
- ++__first;
- }
- std::make_heap(__result_first, __result_real_last);
- while (__first != __last)
- {
- if (*__first < *__result_first)
- std::__adjust_heap(__result_first, _DistanceType(0),
- _DistanceType(__result_real_last
- - __result_first),
- _InputValueType(*__first));
- ++__first;
- }
- std::sort_heap(__result_first, __result_real_last);
- return __result_real_last;
+ return std::__partial_sort_copy(__first, __last,
+ __result_first, __result_last,
+ __gnu_cxx::__ops::__iter_less_iter());
}
/**
@@ -2029,8 +1781,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* @p __comp(*j,*i) is false.
* The value returned is @p __result_first+N.
*/
- template<typename _InputIterator, typename _RandomAccessIterator, typename _Compare>
- _RandomAccessIterator
+ template<typename _InputIterator, typename _RandomAccessIterator,
+ typename _Compare>
+ inline _RandomAccessIterator
partial_sort_copy(_InputIterator __first, _InputIterator __last,
_RandomAccessIterator __result_first,
_RandomAccessIterator __result_last,
@@ -2056,46 +1809,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__glibcxx_requires_valid_range(__first, __last);
__glibcxx_requires_valid_range(__result_first, __result_last);
- if (__result_first == __result_last)
- return __result_last;
- _RandomAccessIterator __result_real_last = __result_first;
- while(__first != __last && __result_real_last != __result_last)
- {
- *__result_real_last = *__first;
- ++__result_real_last;
- ++__first;
- }
- std::make_heap(__result_first, __result_real_last, __comp);
- while (__first != __last)
- {
- if (__comp(*__first, *__result_first))
- std::__adjust_heap(__result_first, _DistanceType(0),
- _DistanceType(__result_real_last
- - __result_first),
- _InputValueType(*__first),
- __comp);
- ++__first;
- }
- std::sort_heap(__result_first, __result_real_last, __comp);
- return __result_real_last;
- }
-
- /// This is a helper function for the sort routine.
- template<typename _RandomAccessIterator>
- void
- __unguarded_linear_insert(_RandomAccessIterator __last)
- {
- typename iterator_traits<_RandomAccessIterator>::value_type
- __val = _GLIBCXX_MOVE(*__last);
- _RandomAccessIterator __next = __last;
- --__next;
- while (__val < *__next)
- {
- *__last = _GLIBCXX_MOVE(*__next);
- __last = __next;
- --__next;
- }
- *__last = _GLIBCXX_MOVE(__val);
+ return std::__partial_sort_copy(__first, __last,
+ __result_first, __result_last,
+ __gnu_cxx::__ops::__iter_comp_iter(__comp));
}
/// This is a helper function for the sort routine.
@@ -2108,7 +1824,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__val = _GLIBCXX_MOVE(*__last);
_RandomAccessIterator __next = __last;
--__next;
- while (__comp(__val, *__next))
+ while (__comp(__val, __next))
{
*__last = _GLIBCXX_MOVE(*__next);
__last = __next;
@@ -2118,29 +1834,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
/// This is a helper function for the sort routine.
- template<typename _RandomAccessIterator>
- void
- __insertion_sort(_RandomAccessIterator __first,
- _RandomAccessIterator __last)
- {
- if (__first == __last)
- return;
-
- for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i)
- {
- if (*__i < *__first)
- {
- typename iterator_traits<_RandomAccessIterator>::value_type
- __val = _GLIBCXX_MOVE(*__i);
- _GLIBCXX_MOVE_BACKWARD3(__first, __i, __i + 1);
- *__first = _GLIBCXX_MOVE(__val);
- }
- else
- std::__unguarded_linear_insert(__i);
- }
- }
-
- /// This is a helper function for the sort routine.
template<typename _RandomAccessIterator, typename _Compare>
void
__insertion_sort(_RandomAccessIterator __first,
@@ -2150,7 +1843,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i)
{
- if (__comp(*__i, *__first))
+ if (__comp(__i, __first))
{
typename iterator_traits<_RandomAccessIterator>::value_type
__val = _GLIBCXX_MOVE(*__i);
@@ -2158,34 +1851,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*__first = _GLIBCXX_MOVE(__val);
}
else
- std::__unguarded_linear_insert(__i, __comp);
+ std::__unguarded_linear_insert(__i,
+ __gnu_cxx::__ops::__val_comp_iter(__comp));
}
}
/// This is a helper function for the sort routine.
- template<typename _RandomAccessIterator>
- inline void
- __unguarded_insertion_sort(_RandomAccessIterator __first,
- _RandomAccessIterator __last)
- {
- typedef typename iterator_traits<_RandomAccessIterator>::value_type
- _ValueType;
-
- for (_RandomAccessIterator __i = __first; __i != __last; ++__i)
- std::__unguarded_linear_insert(__i);
- }
-
- /// This is a helper function for the sort routine.
template<typename _RandomAccessIterator, typename _Compare>
inline void
__unguarded_insertion_sort(_RandomAccessIterator __first,
_RandomAccessIterator __last, _Compare __comp)
{
- typedef typename iterator_traits<_RandomAccessIterator>::value_type
- _ValueType;
-
for (_RandomAccessIterator __i = __first; __i != __last; ++__i)
- std::__unguarded_linear_insert(__i, __comp);
+ std::__unguarded_linear_insert(__i,
+ __gnu_cxx::__ops::__val_comp_iter(__comp));
}
/**
@@ -2195,21 +1874,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
enum { _S_threshold = 16 };
/// This is a helper function for the sort routine.
- template<typename _RandomAccessIterator>
- void
- __final_insertion_sort(_RandomAccessIterator __first,
- _RandomAccessIterator __last)
- {
- if (__last - __first > int(_S_threshold))
- {
- std::__insertion_sort(__first, __first + int(_S_threshold));
- std::__unguarded_insertion_sort(__first + int(_S_threshold), __last);
- }
- else
- std::__insertion_sort(__first, __last);
- }
-
- /// This is a helper function for the sort routine.
template<typename _RandomAccessIterator, typename _Compare>
void
__final_insertion_sort(_RandomAccessIterator __first,
@@ -2226,38 +1890,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
/// This is a helper function...
- template<typename _RandomAccessIterator, typename _Tp>
- _RandomAccessIterator
- __unguarded_partition(_RandomAccessIterator __first,
- _RandomAccessIterator __last, const _Tp& __pivot)
- {
- while (true)
- {
- while (*__first < __pivot)
- ++__first;
- --__last;
- while (__pivot < *__last)
- --__last;
- if (!(__first < __last))
- return __first;
- std::iter_swap(__first, __last);
- ++__first;
- }
- }
-
- /// This is a helper function...
- template<typename _RandomAccessIterator, typename _Tp, typename _Compare>
+ template<typename _RandomAccessIterator, typename _Compare>
_RandomAccessIterator
__unguarded_partition(_RandomAccessIterator __first,
_RandomAccessIterator __last,
- const _Tp& __pivot, _Compare __comp)
+ _RandomAccessIterator __pivot, _Compare __comp)
{
while (true)
{
- while (__comp(*__first, __pivot))
+ while (__comp(__first, __pivot))
++__first;
--__last;
- while (__comp(__pivot, *__last))
+ while (__comp(__pivot, __last))
--__last;
if (!(__first < __last))
return __first;
@@ -2267,48 +1911,26 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
/// This is a helper function...
- template<typename _RandomAccessIterator>
- inline _RandomAccessIterator
- __unguarded_partition_pivot(_RandomAccessIterator __first,
- _RandomAccessIterator __last)
- {
- _RandomAccessIterator __mid = __first + (__last - __first) / 2;
- std::__move_median_first(__first, __mid, (__last - 1));
- return std::__unguarded_partition(__first + 1, __last, *__first);
- }
-
-
- /// This is a helper function...
template<typename _RandomAccessIterator, typename _Compare>
inline _RandomAccessIterator
__unguarded_partition_pivot(_RandomAccessIterator __first,
_RandomAccessIterator __last, _Compare __comp)
{
_RandomAccessIterator __mid = __first + (__last - __first) / 2;
- std::__move_median_first(__first, __mid, (__last - 1), __comp);
- return std::__unguarded_partition(__first + 1, __last, *__first, __comp);
+ std::__move_median_to_first(__first, __first + 1, __mid, __last - 1,
+ __comp);
+ return std::__unguarded_partition(__first + 1, __last, __first, __comp);
}
- /// This is a helper function for the sort routine.
- template<typename _RandomAccessIterator, typename _Size>
- void
- __introsort_loop(_RandomAccessIterator __first,
- _RandomAccessIterator __last,
- _Size __depth_limit)
+ template<typename _RandomAccessIterator, typename _Compare>
+ inline void
+ __partial_sort(_RandomAccessIterator __first,
+ _RandomAccessIterator __middle,
+ _RandomAccessIterator __last,
+ _Compare __comp)
{
- while (__last - __first > int(_S_threshold))
- {
- if (__depth_limit == 0)
- {
- _GLIBCXX_STD_A::partial_sort(__first, __last, __last);
- return;
- }
- --__depth_limit;
- _RandomAccessIterator __cut =
- std::__unguarded_partition_pivot(__first, __last);
- std::__introsort_loop(__cut, __last, __depth_limit);
- __last = __cut;
- }
+ std::__heap_select(__first, __middle, __last, __comp);
+ std::__sort_heap(__first, __middle, __comp);
}
/// This is a helper function for the sort routine.
@@ -2322,7 +1944,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
if (__depth_limit == 0)
{
- _GLIBCXX_STD_A::partial_sort(__first, __last, __last, __comp);
+ std::__partial_sort(__first, __last, __last, __comp);
return;
}
--__depth_limit;
@@ -2335,33 +1957,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// sort
- template<typename _RandomAccessIterator, typename _Size>
- void
- __introselect(_RandomAccessIterator __first, _RandomAccessIterator __nth,
- _RandomAccessIterator __last, _Size __depth_limit)
+ template<typename _RandomAccessIterator, typename _Compare>
+ inline void
+ __sort(_RandomAccessIterator __first, _RandomAccessIterator __last,
+ _Compare __comp)
{
- typedef typename iterator_traits<_RandomAccessIterator>::value_type
- _ValueType;
-
- while (__last - __first > 3)
+ if (__first != __last)
{
- if (__depth_limit == 0)
- {
- std::__heap_select(__first, __nth + 1, __last);
-
- // Place the nth largest element in its final position.
- std::iter_swap(__first, __nth);
- return;
- }
- --__depth_limit;
- _RandomAccessIterator __cut =
- std::__unguarded_partition_pivot(__first, __last);
- if (__cut <= __nth)
- __first = __cut;
- else
- __last = __cut;
+ std::__introsort_loop(__first, __last,
+ std::__lg(__last - __first) * 2,
+ __comp);
+ std::__final_insertion_sort(__first, __last, __comp);
}
- std::__insertion_sort(__first, __last);
}
template<typename _RandomAccessIterator, typename _Size, typename _Compare>
@@ -2370,9 +1977,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_RandomAccessIterator __last, _Size __depth_limit,
_Compare __comp)
{
- typedef typename iterator_traits<_RandomAccessIterator>::value_type
- _ValueType;
-
while (__last - __first > 3)
{
if (__depth_limit == 0)
@@ -2414,14 +2018,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* the function used for the initial sort.
*/
template<typename _ForwardIterator, typename _Tp, typename _Compare>
- _ForwardIterator
+ inline _ForwardIterator
lower_bound(_ForwardIterator __first, _ForwardIterator __last,
const _Tp& __val, _Compare __comp)
{
typedef typename iterator_traits<_ForwardIterator>::value_type
_ValueType;
- typedef typename iterator_traits<_ForwardIterator>::difference_type
- _DistanceType;
// concept requirements
__glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
@@ -2430,6 +2032,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__glibcxx_requires_partitioned_lower_pred(__first, __last,
__val, __comp);
+ return std::__lower_bound(__first, __last, __val,
+ __gnu_cxx::__ops::__iter_comp_val(__comp));
+ }
+
+ template<typename _ForwardIterator, typename _Tp, typename _Compare>
+ _ForwardIterator
+ __upper_bound(_ForwardIterator __first, _ForwardIterator __last,
+ const _Tp& __val, _Compare __comp)
+ {
+ typedef typename iterator_traits<_ForwardIterator>::difference_type
+ _DistanceType;
+
_DistanceType __len = std::distance(__first, __last);
while (__len > 0)
@@ -2437,14 +2051,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_DistanceType __half = __len >> 1;
_ForwardIterator __middle = __first;
std::advance(__middle, __half);
- if (__comp(*__middle, __val))
+ if (__comp(__val, __middle))
+ __len = __half;
+ else
{
__first = __middle;
++__first;
__len = __len - __half - 1;
}
- else
- __len = __half;
}
return __first;
}
@@ -2461,37 +2075,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* @ingroup binary_search_algorithms
*/
template<typename _ForwardIterator, typename _Tp>
- _ForwardIterator
+ inline _ForwardIterator
upper_bound(_ForwardIterator __first, _ForwardIterator __last,
const _Tp& __val)
{
typedef typename iterator_traits<_ForwardIterator>::value_type
_ValueType;
- typedef typename iterator_traits<_ForwardIterator>::difference_type
- _DistanceType;
// concept requirements
__glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
__glibcxx_function_requires(_LessThanOpConcept<_Tp, _ValueType>)
__glibcxx_requires_partitioned_upper(__first, __last, __val);
- _DistanceType __len = std::distance(__first, __last);
-
- while (__len > 0)
- {
- _DistanceType __half = __len >> 1;
- _ForwardIterator __middle = __first;
- std::advance(__middle, __half);
- if (__val < *__middle)
- __len = __half;
- else
- {
- __first = __middle;
- ++__first;
- __len = __len - __half - 1;
- }
- }
- return __first;
+ return std::__upper_bound(__first, __last, __val,
+ __gnu_cxx::__ops::__val_less_iter());
}
/**
@@ -2510,14 +2107,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* the function used for the initial sort.
*/
template<typename _ForwardIterator, typename _Tp, typename _Compare>
- _ForwardIterator
+ inline _ForwardIterator
upper_bound(_ForwardIterator __first, _ForwardIterator __last,
const _Tp& __val, _Compare __comp)
{
typedef typename iterator_traits<_ForwardIterator>::value_type
_ValueType;
- typedef typename iterator_traits<_ForwardIterator>::difference_type
- _DistanceType;
// concept requirements
__glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
@@ -2526,6 +2121,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__glibcxx_requires_partitioned_upper_pred(__first, __last,
__val, __comp);
+ return std::__upper_bound(__first, __last, __val,
+ __gnu_cxx::__ops::__val_comp_iter(__comp));
+ }
+
+ template<typename _ForwardIterator, typename _Tp,
+ typename _CompareItTp, typename _CompareTpIt>
+ pair<_ForwardIterator, _ForwardIterator>
+ __equal_range(_ForwardIterator __first, _ForwardIterator __last,
+ const _Tp& __val,
+ _CompareItTp __comp_it_val, _CompareTpIt __comp_val_it)
+ {
+ typedef typename iterator_traits<_ForwardIterator>::difference_type
+ _DistanceType;
+
_DistanceType __len = std::distance(__first, __last);
while (__len > 0)
@@ -2533,16 +2142,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_DistanceType __half = __len >> 1;
_ForwardIterator __middle = __first;
std::advance(__middle, __half);
- if (__comp(__val, *__middle))
- __len = __half;
- else
+ if (__comp_it_val(__middle, __val))
{
__first = __middle;
++__first;
__len = __len - __half - 1;
}
+ else if (__comp_val_it(__val, __middle))
+ __len = __half;
+ else
+ {
+ _ForwardIterator __left
+ = std::__lower_bound(__first, __middle, __val, __comp_it_val);
+ std::advance(__first, __len);
+ _ForwardIterator __right
+ = std::__upper_bound(++__middle, __first, __val, __comp_val_it);
+ return pair<_ForwardIterator, _ForwardIterator>(__left, __right);
+ }
}
- return __first;
+ return pair<_ForwardIterator, _ForwardIterator>(__first, __first);
}
/**
@@ -2563,48 +2181,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* but does not actually call those functions.
*/
template<typename _ForwardIterator, typename _Tp>
- pair<_ForwardIterator, _ForwardIterator>
+ inline pair<_ForwardIterator, _ForwardIterator>
equal_range(_ForwardIterator __first, _ForwardIterator __last,
const _Tp& __val)
{
typedef typename iterator_traits<_ForwardIterator>::value_type
_ValueType;
- typedef typename iterator_traits<_ForwardIterator>::difference_type
- _DistanceType;
// concept requirements
__glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
__glibcxx_function_requires(_LessThanOpConcept<_ValueType, _Tp>)
- __glibcxx_function_requires(_LessThanOpConcept<_Tp, _ValueType>)
+ __glibcxx_function_requires(_LessThanOpConcept<_Tp, _ValueType>)
__glibcxx_requires_partitioned_lower(__first, __last, __val);
__glibcxx_requires_partitioned_upper(__first, __last, __val);
- _DistanceType __len = std::distance(__first, __last);
-
- while (__len > 0)
- {
- _DistanceType __half = __len >> 1;
- _ForwardIterator __middle = __first;
- std::advance(__middle, __half);
- if (*__middle < __val)
- {
- __first = __middle;
- ++__first;
- __len = __len - __half - 1;
- }
- else if (__val < *__middle)
- __len = __half;
- else
- {
- _ForwardIterator __left = std::lower_bound(__first, __middle,
- __val);
- std::advance(__first, __len);
- _ForwardIterator __right = std::upper_bound(++__middle, __first,
- __val);
- return pair<_ForwardIterator, _ForwardIterator>(__left, __right);
- }
- }
- return pair<_ForwardIterator, _ForwardIterator>(__first, __first);
+ return std::__equal_range(__first, __last, __val,
+ __gnu_cxx::__ops::__iter_less_val(),
+ __gnu_cxx::__ops::__val_less_iter());
}
/**
@@ -2625,14 +2218,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* but does not actually call those functions.
*/
template<typename _ForwardIterator, typename _Tp, typename _Compare>
- pair<_ForwardIterator, _ForwardIterator>
+ inline pair<_ForwardIterator, _ForwardIterator>
equal_range(_ForwardIterator __first, _ForwardIterator __last,
const _Tp& __val, _Compare __comp)
{
typedef typename iterator_traits<_ForwardIterator>::value_type
_ValueType;
- typedef typename iterator_traits<_ForwardIterator>::difference_type
- _DistanceType;
// concept requirements
__glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
@@ -2645,32 +2236,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__glibcxx_requires_partitioned_upper_pred(__first, __last,
__val, __comp);
- _DistanceType __len = std::distance(__first, __last);
-
- while (__len > 0)
- {
- _DistanceType __half = __len >> 1;
- _ForwardIterator __middle = __first;
- std::advance(__middle, __half);
- if (__comp(*__middle, __val))
- {
- __first = __middle;
- ++__first;
- __len = __len - __half - 1;
- }
- else if (__comp(__val, *__middle))
- __len = __half;
- else
- {
- _ForwardIterator __left = std::lower_bound(__first, __middle,
- __val, __comp);
- std::advance(__first, __len);
- _ForwardIterator __right = std::upper_bound(++__middle, __first,
- __val, __comp);
- return pair<_ForwardIterator, _ForwardIterator>(__left, __right);
- }
- }
- return pair<_ForwardIterator, _ForwardIterator>(__first, __first);
+ return std::__equal_range(__first, __last, __val,
+ __gnu_cxx::__ops::__iter_comp_val(__comp),
+ __gnu_cxx::__ops::__val_comp_iter(__comp));
}
/**
@@ -2699,7 +2267,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__glibcxx_requires_partitioned_lower(__first, __last, __val);
__glibcxx_requires_partitioned_upper(__first, __last, __val);
- _ForwardIterator __i = std::lower_bound(__first, __last, __val);
+ _ForwardIterator __i
+ = std::__lower_bound(__first, __last, __val,
+ __gnu_cxx::__ops::__iter_less_val());
return __i != __last && !(__val < *__i);
}
@@ -2735,7 +2305,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__glibcxx_requires_partitioned_upper_pred(__first, __last,
__val, __comp);
- _ForwardIterator __i = std::lower_bound(__first, __last, __val, __comp);
+ _ForwardIterator __i
+ = std::__lower_bound(__first, __last, __val,
+ __gnu_cxx::__ops::__iter_comp_val(__comp));
return __i != __last && !bool(__comp(__val, *__i));
}
@@ -2743,32 +2315,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/// This is a helper function for the __merge_adaptive routines.
template<typename _InputIterator1, typename _InputIterator2,
- typename _OutputIterator>
- void
- __move_merge_adaptive(_InputIterator1 __first1, _InputIterator1 __last1,
- _InputIterator2 __first2, _InputIterator2 __last2,
- _OutputIterator __result)
- {
- while (__first1 != __last1 && __first2 != __last2)
- {
- if (*__first2 < *__first1)
- {
- *__result = _GLIBCXX_MOVE(*__first2);
- ++__first2;
- }
- else
- {
- *__result = _GLIBCXX_MOVE(*__first1);
- ++__first1;
- }
- ++__result;
- }
- if (__first1 != __last1)
- _GLIBCXX_MOVE3(__first1, __last1, __result);
- }
-
- /// This is a helper function for the __merge_adaptive routines.
- template<typename _InputIterator1, typename _InputIterator2,
typename _OutputIterator, typename _Compare>
void
__move_merge_adaptive(_InputIterator1 __first1, _InputIterator1 __last1,
@@ -2777,7 +2323,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
while (__first1 != __last1 && __first2 != __last2)
{
- if (__comp(*__first2, *__first1))
+ if (__comp(__first2, __first1))
{
*__result = _GLIBCXX_MOVE(*__first2);
++__first2;
@@ -2795,48 +2341,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/// This is a helper function for the __merge_adaptive routines.
template<typename _BidirectionalIterator1, typename _BidirectionalIterator2,
- typename _BidirectionalIterator3>
- void
- __move_merge_adaptive_backward(_BidirectionalIterator1 __first1,
- _BidirectionalIterator1 __last1,
- _BidirectionalIterator2 __first2,
- _BidirectionalIterator2 __last2,
- _BidirectionalIterator3 __result)
- {
- if (__first1 == __last1)
- {
- _GLIBCXX_MOVE_BACKWARD3(__first2, __last2, __result);
- return;
- }
- else if (__first2 == __last2)
- return;
-
- --__last1;
- --__last2;
- while (true)
- {
- if (*__last2 < *__last1)
- {
- *--__result = _GLIBCXX_MOVE(*__last1);
- if (__first1 == __last1)
- {
- _GLIBCXX_MOVE_BACKWARD3(__first2, ++__last2, __result);
- return;
- }
- --__last1;
- }
- else
- {
- *--__result = _GLIBCXX_MOVE(*__last2);
- if (__first2 == __last2)
- return;
- --__last2;
- }
- }
- }
-
- /// This is a helper function for the __merge_adaptive routines.
- template<typename _BidirectionalIterator1, typename _BidirectionalIterator2,
typename _BidirectionalIterator3, typename _Compare>
void
__move_merge_adaptive_backward(_BidirectionalIterator1 __first1,
@@ -2858,7 +2362,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
--__last2;
while (true)
{
- if (__comp(*__last2, *__last1))
+ if (__comp(__last2, __last1))
{
*--__result = _GLIBCXX_MOVE(*__last1);
if (__first1 == __last1)
@@ -2921,62 +2425,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
/// This is a helper function for the merge routines.
- template<typename _BidirectionalIterator, typename _Distance,
- typename _Pointer>
- void
- __merge_adaptive(_BidirectionalIterator __first,
- _BidirectionalIterator __middle,
- _BidirectionalIterator __last,
- _Distance __len1, _Distance __len2,
- _Pointer __buffer, _Distance __buffer_size)
- {
- if (__len1 <= __len2 && __len1 <= __buffer_size)
- {
- _Pointer __buffer_end = _GLIBCXX_MOVE3(__first, __middle, __buffer);
- std::__move_merge_adaptive(__buffer, __buffer_end, __middle, __last,
- __first);
- }
- else if (__len2 <= __buffer_size)
- {
- _Pointer __buffer_end = _GLIBCXX_MOVE3(__middle, __last, __buffer);
- std::__move_merge_adaptive_backward(__first, __middle, __buffer,
- __buffer_end, __last);
- }
- else
- {
- _BidirectionalIterator __first_cut = __first;
- _BidirectionalIterator __second_cut = __middle;
- _Distance __len11 = 0;
- _Distance __len22 = 0;
- if (__len1 > __len2)
- {
- __len11 = __len1 / 2;
- std::advance(__first_cut, __len11);
- __second_cut = std::lower_bound(__middle, __last,
- *__first_cut);
- __len22 = std::distance(__middle, __second_cut);
- }
- else
- {
- __len22 = __len2 / 2;
- std::advance(__second_cut, __len22);
- __first_cut = std::upper_bound(__first, __middle,
- *__second_cut);
- __len11 = std::distance(__first, __first_cut);
- }
- _BidirectionalIterator __new_middle =
- std::__rotate_adaptive(__first_cut, __middle, __second_cut,
- __len1 - __len11, __len22, __buffer,
- __buffer_size);
- std::__merge_adaptive(__first, __first_cut, __new_middle, __len11,
- __len22, __buffer, __buffer_size);
- std::__merge_adaptive(__new_middle, __second_cut, __last,
- __len1 - __len11,
- __len2 - __len22, __buffer, __buffer_size);
- }
- }
-
- /// This is a helper function for the merge routines.
template<typename _BidirectionalIterator, typename _Distance,
typename _Pointer, typename _Compare>
void
@@ -3009,22 +2457,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
__len11 = __len1 / 2;
std::advance(__first_cut, __len11);
- __second_cut = std::lower_bound(__middle, __last, *__first_cut,
- __comp);
+ __second_cut
+ = std::__lower_bound(__middle, __last, *__first_cut,
+ __gnu_cxx::__ops::__iter_comp_val(__comp));
__len22 = std::distance(__middle, __second_cut);
}
else
{
__len22 = __len2 / 2;
std::advance(__second_cut, __len22);
- __first_cut = std::upper_bound(__first, __middle, *__second_cut,
- __comp);
+ __first_cut
+ = std::__upper_bound(__first, __middle, *__second_cut,
+ __gnu_cxx::__ops::__val_comp_iter(__comp));
__len11 = std::distance(__first, __first_cut);
}
- _BidirectionalIterator __new_middle =
- std::__rotate_adaptive(__first_cut, __middle, __second_cut,
- __len1 - __len11, __len22, __buffer,
- __buffer_size);
+ _BidirectionalIterator __new_middle
+ = std::__rotate_adaptive(__first_cut, __middle, __second_cut,
+ __len1 - __len11, __len22, __buffer,
+ __buffer_size);
std::__merge_adaptive(__first, __first_cut, __new_middle, __len11,
__len22, __buffer, __buffer_size, __comp);
std::__merge_adaptive(__new_middle, __second_cut, __last,
@@ -3035,49 +2485,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
/// This is a helper function for the merge routines.
- template<typename _BidirectionalIterator, typename _Distance>
- void
- __merge_without_buffer(_BidirectionalIterator __first,
- _BidirectionalIterator __middle,
- _BidirectionalIterator __last,
- _Distance __len1, _Distance __len2)
- {
- if (__len1 == 0 || __len2 == 0)
- return;
- if (__len1 + __len2 == 2)
- {
- if (*__middle < *__first)
- std::iter_swap(__first, __middle);
- return;
- }
- _BidirectionalIterator __first_cut = __first;
- _BidirectionalIterator __second_cut = __middle;
- _Distance __len11 = 0;
- _Distance __len22 = 0;
- if (__len1 > __len2)
- {
- __len11 = __len1 / 2;
- std::advance(__first_cut, __len11);
- __second_cut = std::lower_bound(__middle, __last, *__first_cut);
- __len22 = std::distance(__middle, __second_cut);
- }
- else
- {
- __len22 = __len2 / 2;
- std::advance(__second_cut, __len22);
- __first_cut = std::upper_bound(__first, __middle, *__second_cut);
- __len11 = std::distance(__first, __first_cut);
- }
- std::rotate(__first_cut, __middle, __second_cut);
- _BidirectionalIterator __new_middle = __first_cut;
- std::advance(__new_middle, std::distance(__middle, __second_cut));
- std::__merge_without_buffer(__first, __first_cut, __new_middle,
- __len11, __len22);
- std::__merge_without_buffer(__new_middle, __second_cut, __last,
- __len1 - __len11, __len2 - __len22);
- }
-
- /// This is a helper function for the merge routines.
template<typename _BidirectionalIterator, typename _Distance,
typename _Compare>
void
@@ -3091,7 +2498,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return;
if (__len1 + __len2 == 2)
{
- if (__comp(*__middle, *__first))
+ if (__comp(__middle, __first))
std::iter_swap(__first, __middle);
return;
}
@@ -3103,16 +2510,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
__len11 = __len1 / 2;
std::advance(__first_cut, __len11);
- __second_cut = std::lower_bound(__middle, __last, *__first_cut,
- __comp);
+ __second_cut
+ = std::__lower_bound(__middle, __last, *__first_cut,
+ __gnu_cxx::__ops::__iter_comp_val(__comp));
__len22 = std::distance(__middle, __second_cut);
}
else
{
__len22 = __len2 / 2;
std::advance(__second_cut, __len22);
- __first_cut = std::upper_bound(__first, __middle, *__second_cut,
- __comp);
+ __first_cut
+ = std::__upper_bound(__first, __middle, *__second_cut,
+ __gnu_cxx::__ops::__val_comp_iter(__comp));
__len11 = std::distance(__first, __first_cut);
}
std::rotate(__first_cut, __middle, __second_cut);
@@ -3124,6 +2533,36 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__len1 - __len11, __len2 - __len22, __comp);
}
+ template<typename _BidirectionalIterator, typename _Compare>
+ void
+ __inplace_merge(_BidirectionalIterator __first,
+ _BidirectionalIterator __middle,
+ _BidirectionalIterator __last,
+ _Compare __comp)
+ {
+ typedef typename iterator_traits<_BidirectionalIterator>::value_type
+ _ValueType;
+ typedef typename iterator_traits<_BidirectionalIterator>::difference_type
+ _DistanceType;
+
+ if (__first == __middle || __middle == __last)
+ return;
+
+ const _DistanceType __len1 = std::distance(__first, __middle);
+ const _DistanceType __len2 = std::distance(__middle, __last);
+
+ typedef _Temporary_buffer<_BidirectionalIterator, _ValueType> _TmpBuf;
+ _TmpBuf __buf(__first, __last);
+
+ if (__buf.begin() == 0)
+ std::__merge_without_buffer
+ (__first, __middle, __last, __len1, __len2, __comp);
+ else
+ std::__merge_adaptive
+ (__first, __middle, __last, __len1, __len2, __buf.begin(),
+ _DistanceType(__buf.size()), __comp);
+ }
+
/**
* @brief Merges two sorted ranges in place.
* @ingroup sorting_algorithms
@@ -3143,36 +2582,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* distance(__first,__last).
*/
template<typename _BidirectionalIterator>
- void
+ inline void
inplace_merge(_BidirectionalIterator __first,
_BidirectionalIterator __middle,
_BidirectionalIterator __last)
{
- typedef typename iterator_traits<_BidirectionalIterator>::value_type
- _ValueType;
- typedef typename iterator_traits<_BidirectionalIterator>::difference_type
- _DistanceType;
-
// concept requirements
__glibcxx_function_requires(_Mutable_BidirectionalIteratorConcept<
_BidirectionalIterator>)
- __glibcxx_function_requires(_LessThanComparableConcept<_ValueType>)
+ __glibcxx_function_requires(_LessThanComparableConcept<
+ typename iterator_traits<_BidirectionalIterator>::value_type>)
__glibcxx_requires_sorted(__first, __middle);
__glibcxx_requires_sorted(__middle, __last);
- if (__first == __middle || __middle == __last)
- return;
-
- _DistanceType __len1 = std::distance(__first, __middle);
- _DistanceType __len2 = std::distance(__middle, __last);
-
- _Temporary_buffer<_BidirectionalIterator, _ValueType> __buf(__first,
- __last);
- if (__buf.begin() == 0)
- std::__merge_without_buffer(__first, __middle, __last, __len1, __len2);
- else
- std::__merge_adaptive(__first, __middle, __last, __len1, __len2,
- __buf.begin(), _DistanceType(__buf.size()));
+ std::__inplace_merge(__first, __middle, __last,
+ __gnu_cxx::__ops::__iter_less_iter());
}
/**
@@ -3198,81 +2622,37 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* the function used for the initial sort.
*/
template<typename _BidirectionalIterator, typename _Compare>
- void
+ inline void
inplace_merge(_BidirectionalIterator __first,
_BidirectionalIterator __middle,
_BidirectionalIterator __last,
_Compare __comp)
{
- typedef typename iterator_traits<_BidirectionalIterator>::value_type
- _ValueType;
- typedef typename iterator_traits<_BidirectionalIterator>::difference_type
- _DistanceType;
-
// concept requirements
__glibcxx_function_requires(_Mutable_BidirectionalIteratorConcept<
_BidirectionalIterator>)
__glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
- _ValueType, _ValueType>)
+ typename iterator_traits<_BidirectionalIterator>::value_type,
+ typename iterator_traits<_BidirectionalIterator>::value_type>)
__glibcxx_requires_sorted_pred(__first, __middle, __comp);
__glibcxx_requires_sorted_pred(__middle, __last, __comp);
- if (__first == __middle || __middle == __last)
- return;
-
- const _DistanceType __len1 = std::distance(__first, __middle);
- const _DistanceType __len2 = std::distance(__middle, __last);
-
- _Temporary_buffer<_BidirectionalIterator, _ValueType> __buf(__first,
- __last);
- if (__buf.begin() == 0)
- std::__merge_without_buffer(__first, __middle, __last, __len1,
- __len2, __comp);
- else
- std::__merge_adaptive(__first, __middle, __last, __len1, __len2,
- __buf.begin(), _DistanceType(__buf.size()),
- __comp);
+ std::__inplace_merge(__first, __middle, __last,
+ __gnu_cxx::__ops::__iter_comp_iter(__comp));
}
/// This is a helper function for the __merge_sort_loop routines.
- template<typename _InputIterator1, typename _InputIterator2,
- typename _OutputIterator>
- _OutputIterator
- __move_merge(_InputIterator1 __first1, _InputIterator1 __last1,
- _InputIterator2 __first2, _InputIterator2 __last2,
- _OutputIterator __result)
- {
- while (__first1 != __last1 && __first2 != __last2)
- {
- if (*__first2 < *__first1)
- {
- *__result = _GLIBCXX_MOVE(*__first2);
- ++__first2;
- }
- else
- {
- *__result = _GLIBCXX_MOVE(*__first1);
- ++__first1;
- }
- ++__result;
- }
- return _GLIBCXX_MOVE3(__first2, __last2,
- _GLIBCXX_MOVE3(__first1, __last1,
- __result));
- }
-
- /// This is a helper function for the __merge_sort_loop routines.
- template<typename _InputIterator1, typename _InputIterator2,
- typename _OutputIterator, typename _Compare>
+ template<typename _InputIterator, typename _OutputIterator,
+ typename _Compare>
_OutputIterator
- __move_merge(_InputIterator1 __first1, _InputIterator1 __last1,
- _InputIterator2 __first2, _InputIterator2 __last2,
+ __move_merge(_InputIterator __first1, _InputIterator __last1,
+ _InputIterator __first2, _InputIterator __last2,
_OutputIterator __result, _Compare __comp)
{
while (__first1 != __last1 && __first2 != __last2)
{
- if (__comp(*__first2, *__first1))
+ if (__comp(__first2, __first1))
{
*__result = _GLIBCXX_MOVE(*__first2);
++__first2;
@@ -3290,29 +2670,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
template<typename _RandomAccessIterator1, typename _RandomAccessIterator2,
- typename _Distance>
- void
- __merge_sort_loop(_RandomAccessIterator1 __first,
- _RandomAccessIterator1 __last,
- _RandomAccessIterator2 __result,
- _Distance __step_size)
- {
- const _Distance __two_step = 2 * __step_size;
-
- while (__last - __first >= __two_step)
- {
- __result = std::__move_merge(__first, __first + __step_size,
- __first + __step_size,
- __first + __two_step, __result);
- __first += __two_step;
- }
-
- __step_size = std::min(_Distance(__last - __first), __step_size);
- std::__move_merge(__first, __first + __step_size,
- __first + __step_size, __last, __result);
- }
-
- template<typename _RandomAccessIterator1, typename _RandomAccessIterator2,
typename _Distance, typename _Compare>
void
__merge_sort_loop(_RandomAccessIterator1 __first,
@@ -3332,24 +2689,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
__step_size = std::min(_Distance(__last - __first), __step_size);
- std::__move_merge(__first,__first + __step_size,
+ std::__move_merge(__first, __first + __step_size,
__first + __step_size, __last, __result, __comp);
}
- template<typename _RandomAccessIterator, typename _Distance>
- void
- __chunk_insertion_sort(_RandomAccessIterator __first,
- _RandomAccessIterator __last,
- _Distance __chunk_size)
- {
- while (__last - __first >= __chunk_size)
- {
- std::__insertion_sort(__first, __first + __chunk_size);
- __first += __chunk_size;
- }
- std::__insertion_sort(__first, __last);
- }
-
template<typename _RandomAccessIterator, typename _Distance,
typename _Compare>
void
@@ -3367,30 +2710,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
enum { _S_chunk_size = 7 };
- template<typename _RandomAccessIterator, typename _Pointer>
- void
- __merge_sort_with_buffer(_RandomAccessIterator __first,
- _RandomAccessIterator __last,
- _Pointer __buffer)
- {
- typedef typename iterator_traits<_RandomAccessIterator>::difference_type
- _Distance;
-
- const _Distance __len = __last - __first;
- const _Pointer __buffer_last = __buffer + __len;
-
- _Distance __step_size = _S_chunk_size;
- std::__chunk_insertion_sort(__first, __last, __step_size);
-
- while (__step_size < __len)
- {
- std::__merge_sort_loop(__first, __last, __buffer, __step_size);
- __step_size *= 2;
- std::__merge_sort_loop(__buffer, __buffer_last, __first, __step_size);
- __step_size *= 2;
- }
- }
-
template<typename _RandomAccessIterator, typename _Pointer, typename _Compare>
void
__merge_sort_with_buffer(_RandomAccessIterator __first,
@@ -3418,33 +2737,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
template<typename _RandomAccessIterator, typename _Pointer,
- typename _Distance>
- void
- __stable_sort_adaptive(_RandomAccessIterator __first,
- _RandomAccessIterator __last,
- _Pointer __buffer, _Distance __buffer_size)
- {
- const _Distance __len = (__last - __first + 1) / 2;
- const _RandomAccessIterator __middle = __first + __len;
- if (__len > __buffer_size)
- {
- std::__stable_sort_adaptive(__first, __middle,
- __buffer, __buffer_size);
- std::__stable_sort_adaptive(__middle, __last,
- __buffer, __buffer_size);
- }
- else
- {
- std::__merge_sort_with_buffer(__first, __middle, __buffer);
- std::__merge_sort_with_buffer(__middle, __last, __buffer);
- }
- std::__merge_adaptive(__first, __middle, __last,
- _Distance(__middle - __first),
- _Distance(__last - __middle),
- __buffer, __buffer_size);
- }
-
- template<typename _RandomAccessIterator, typename _Pointer,
typename _Distance, typename _Compare>
void
__stable_sort_adaptive(_RandomAccessIterator __first,
@@ -3474,25 +2766,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
/// This is a helper function for the stable sorting routines.
- template<typename _RandomAccessIterator>
- void
- __inplace_stable_sort(_RandomAccessIterator __first,
- _RandomAccessIterator __last)
- {
- if (__last - __first < 15)
- {
- std::__insertion_sort(__first, __last);
- return;
- }
- _RandomAccessIterator __middle = __first + (__last - __first) / 2;
- std::__inplace_stable_sort(__first, __middle);
- std::__inplace_stable_sort(__middle, __last);
- std::__merge_without_buffer(__first, __middle, __last,
- __middle - __first,
- __last - __middle);
- }
-
- /// This is a helper function for the stable sorting routines.
template<typename _RandomAccessIterator, typename _Compare>
void
__inplace_stable_sort(_RandomAccessIterator __first,
@@ -3519,6 +2792,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// that their input ranges are sorted and the postcondition that their output
// ranges are sorted.
+ template<typename _InputIterator1, typename _InputIterator2,
+ typename _Compare>
+ bool
+ __includes(_InputIterator1 __first1, _InputIterator1 __last1,
+ _InputIterator2 __first2, _InputIterator2 __last2,
+ _Compare __comp)
+ {
+ while (__first1 != __last1 && __first2 != __last2)
+ if (__comp(__first2, __first1))
+ return false;
+ else if (__comp(__first1, __first2))
+ ++__first1;
+ else
+ ++__first1, ++__first2;
+
+ return __first2 == __last2;
+ }
+
/**
* @brief Determines whether all elements of a sequence exists in a range.
* @param __first1 Start of search range.
@@ -3538,32 +2829,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* returned.
*/
template<typename _InputIterator1, typename _InputIterator2>
- bool
+ inline bool
includes(_InputIterator1 __first1, _InputIterator1 __last1,
_InputIterator2 __first2, _InputIterator2 __last2)
{
- typedef typename iterator_traits<_InputIterator1>::value_type
- _ValueType1;
- typedef typename iterator_traits<_InputIterator2>::value_type
- _ValueType2;
-
// concept requirements
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>)
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>)
- __glibcxx_function_requires(_LessThanOpConcept<_ValueType1, _ValueType2>)
- __glibcxx_function_requires(_LessThanOpConcept<_ValueType2, _ValueType1>)
+ __glibcxx_function_requires(_LessThanOpConcept<
+ typename iterator_traits<_InputIterator1>::value_type,
+ typename iterator_traits<_InputIterator2>::value_type>)
+ __glibcxx_function_requires(_LessThanOpConcept<
+ typename iterator_traits<_InputIterator2>::value_type,
+ typename iterator_traits<_InputIterator1>::value_type>)
__glibcxx_requires_sorted_set(__first1, __last1, __first2);
__glibcxx_requires_sorted_set(__first2, __last2, __first1);
- while (__first1 != __last1 && __first2 != __last2)
- if (*__first2 < *__first1)
- return false;
- else if(*__first1 < *__first2)
- ++__first1;
- else
- ++__first1, ++__first2;
-
- return __first2 == __last2;
+ return std::__includes(__first1, __last1, __first2, __last2,
+ __gnu_cxx::__ops::__iter_less_iter());
}
/**
@@ -3589,35 +2872,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*/
template<typename _InputIterator1, typename _InputIterator2,
typename _Compare>
- bool
+ inline bool
includes(_InputIterator1 __first1, _InputIterator1 __last1,
_InputIterator2 __first2, _InputIterator2 __last2,
_Compare __comp)
{
- typedef typename iterator_traits<_InputIterator1>::value_type
- _ValueType1;
- typedef typename iterator_traits<_InputIterator2>::value_type
- _ValueType2;
-
// concept requirements
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>)
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>)
__glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
- _ValueType1, _ValueType2>)
+ typename iterator_traits<_InputIterator1>::value_type,
+ typename iterator_traits<_InputIterator2>::value_type>)
__glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
- _ValueType2, _ValueType1>)
+ typename iterator_traits<_InputIterator2>::value_type,
+ typename iterator_traits<_InputIterator1>::value_type>)
__glibcxx_requires_sorted_set_pred(__first1, __last1, __first2, __comp);
__glibcxx_requires_sorted_set_pred(__first2, __last2, __first1, __comp);
- while (__first1 != __last1 && __first2 != __last2)
- if (__comp(*__first2, *__first1))
- return false;
- else if(__comp(*__first1, *__first2))
- ++__first1;
- else
- ++__first1, ++__first2;
-
- return __first2 == __last2;
+ return std::__includes(__first1, __last1, __first2, __last2,
+ __gnu_cxx::__ops::__iter_comp_iter(__comp));
}
// nth_element
@@ -3630,30 +2903,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// min_element
// max_element
- /**
- * @brief Permute range into the next @e dictionary ordering.
- * @ingroup sorting_algorithms
- * @param __first Start of range.
- * @param __last End of range.
- * @return False if wrapped to first permutation, true otherwise.
- *
- * Treats all permutations of the range as a set of @e dictionary sorted
- * sequences. Permutes the current sequence into the next one of this set.
- * Returns true if there are more sequences to generate. If the sequence
- * is the largest of the set, the smallest is generated and false returned.
- */
- template<typename _BidirectionalIterator>
+ template<typename _BidirectionalIterator, typename _Compare>
bool
- next_permutation(_BidirectionalIterator __first,
- _BidirectionalIterator __last)
+ __next_permutation(_BidirectionalIterator __first,
+ _BidirectionalIterator __last, _Compare __comp)
{
- // concept requirements
- __glibcxx_function_requires(_BidirectionalIteratorConcept<
- _BidirectionalIterator>)
- __glibcxx_function_requires(_LessThanComparableConcept<
- typename iterator_traits<_BidirectionalIterator>::value_type>)
- __glibcxx_requires_valid_range(__first, __last);
-
if (__first == __last)
return false;
_BidirectionalIterator __i = __first;
@@ -3667,24 +2921,54 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
_BidirectionalIterator __ii = __i;
--__i;
- if (*__i < *__ii)
+ if (__comp(__i, __ii))
{
_BidirectionalIterator __j = __last;
- while (!(*__i < *--__j))
+ while (!__comp(__i, --__j))
{}
std::iter_swap(__i, __j);
- std::reverse(__ii, __last);
+ std::__reverse(__ii, __last,
+ std::__iterator_category(__first));
return true;
}
if (__i == __first)
{
- std::reverse(__first, __last);
+ std::__reverse(__first, __last,
+ std::__iterator_category(__first));
return false;
}
}
}
/**
+ * @brief Permute range into the next @e dictionary ordering.
+ * @ingroup sorting_algorithms
+ * @param __first Start of range.
+ * @param __last End of range.
+ * @return False if wrapped to first permutation, true otherwise.
+ *
+ * Treats all permutations of the range as a set of @e dictionary sorted
+ * sequences. Permutes the current sequence into the next one of this set.
+ * Returns true if there are more sequences to generate. If the sequence
+ * is the largest of the set, the smallest is generated and false returned.
+ */
+ template<typename _BidirectionalIterator>
+ inline bool
+ next_permutation(_BidirectionalIterator __first,
+ _BidirectionalIterator __last)
+ {
+ // concept requirements
+ __glibcxx_function_requires(_BidirectionalIteratorConcept<
+ _BidirectionalIterator>)
+ __glibcxx_function_requires(_LessThanComparableConcept<
+ typename iterator_traits<_BidirectionalIterator>::value_type>)
+ __glibcxx_requires_valid_range(__first, __last);
+
+ return std::__next_permutation
+ (__first, __last, __gnu_cxx::__ops::__iter_less_iter());
+ }
+
+ /**
* @brief Permute range into the next @e dictionary ordering using
* comparison functor.
* @ingroup sorting_algorithms
@@ -3700,7 +2984,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* smallest is generated and false returned.
*/
template<typename _BidirectionalIterator, typename _Compare>
- bool
+ inline bool
next_permutation(_BidirectionalIterator __first,
_BidirectionalIterator __last, _Compare __comp)
{
@@ -3712,6 +2996,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typename iterator_traits<_BidirectionalIterator>::value_type>)
__glibcxx_requires_valid_range(__first, __last);
+ return std::__next_permutation
+ (__first, __last, __gnu_cxx::__ops::__iter_comp_iter(__comp));
+ }
+
+ template<typename _BidirectionalIterator, typename _Compare>
+ bool
+ __prev_permutation(_BidirectionalIterator __first,
+ _BidirectionalIterator __last, _Compare __comp)
+ {
if (__first == __last)
return false;
_BidirectionalIterator __i = __first;
@@ -3725,18 +3018,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
_BidirectionalIterator __ii = __i;
--__i;
- if (__comp(*__i, *__ii))
+ if (__comp(__ii, __i))
{
_BidirectionalIterator __j = __last;
- while (!bool(__comp(*__i, *--__j)))
+ while (!__comp(--__j, __i))
{}
std::iter_swap(__i, __j);
- std::reverse(__ii, __last);
+ std::__reverse(__ii, __last,
+ std::__iterator_category(__first));
return true;
}
if (__i == __first)
{
- std::reverse(__first, __last);
+ std::__reverse(__first, __last,
+ std::__iterator_category(__first));
return false;
}
}
@@ -3756,7 +3051,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* returned.
*/
template<typename _BidirectionalIterator>
- bool
+ inline bool
prev_permutation(_BidirectionalIterator __first,
_BidirectionalIterator __last)
{
@@ -3767,34 +3062,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typename iterator_traits<_BidirectionalIterator>::value_type>)
__glibcxx_requires_valid_range(__first, __last);
- if (__first == __last)
- return false;
- _BidirectionalIterator __i = __first;
- ++__i;
- if (__i == __last)
- return false;
- __i = __last;
- --__i;
-
- for(;;)
- {
- _BidirectionalIterator __ii = __i;
- --__i;
- if (*__ii < *__i)
- {
- _BidirectionalIterator __j = __last;
- while (!(*--__j < *__i))
- {}
- std::iter_swap(__i, __j);
- std::reverse(__ii, __last);
- return true;
- }
- if (__i == __first)
- {
- std::reverse(__first, __last);
- return false;
- }
- }
+ return std::__prev_permutation(__first, __last,
+ __gnu_cxx::__ops::__iter_less_iter());
}
/**
@@ -3813,7 +3082,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* the largest is generated and false returned.
*/
template<typename _BidirectionalIterator, typename _Compare>
- bool
+ inline bool
prev_permutation(_BidirectionalIterator __first,
_BidirectionalIterator __last, _Compare __comp)
{
@@ -3825,39 +3094,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typename iterator_traits<_BidirectionalIterator>::value_type>)
__glibcxx_requires_valid_range(__first, __last);
- if (__first == __last)
- return false;
- _BidirectionalIterator __i = __first;
- ++__i;
- if (__i == __last)
- return false;
- __i = __last;
- --__i;
-
- for(;;)
- {
- _BidirectionalIterator __ii = __i;
- --__i;
- if (__comp(*__ii, *__i))
- {
- _BidirectionalIterator __j = __last;
- while (!bool(__comp(*--__j, *__i)))
- {}
- std::iter_swap(__i, __j);
- std::reverse(__ii, __last);
- return true;
- }
- if (__i == __first)
- {
- std::reverse(__first, __last);
- return false;
- }
- }
+ return std::__prev_permutation(__first, __last,
+ __gnu_cxx::__ops::__iter_comp_iter(__comp));
}
// replace
// replace_if
+ template<typename _InputIterator, typename _OutputIterator,
+ typename _Predicate, typename _Tp>
+ _OutputIterator
+ __replace_copy_if(_InputIterator __first, _InputIterator __last,
+ _OutputIterator __result,
+ _Predicate __pred, const _Tp& __new_value)
+ {
+ for (; __first != __last; ++__first, ++__result)
+ if (__pred(__first))
+ *__result = __new_value;
+ else
+ *__result = *__first;
+ return __result;
+ }
+
/**
* @brief Copy a sequence, replacing each element of one value with another
* value.
@@ -3873,7 +3131,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* equal to @p __old_value with @p __new_value.
*/
template<typename _InputIterator, typename _OutputIterator, typename _Tp>
- _OutputIterator
+ inline _OutputIterator
replace_copy(_InputIterator __first, _InputIterator __last,
_OutputIterator __result,
const _Tp& __old_value, const _Tp& __new_value)
@@ -3886,12 +3144,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typename iterator_traits<_InputIterator>::value_type, _Tp>)
__glibcxx_requires_valid_range(__first, __last);
- for (; __first != __last; ++__first, ++__result)
- if (*__first == __old_value)
- *__result = __new_value;
- else
- *__result = *__first;
- return __result;
+ return std::__replace_copy_if(__first, __last, __result,
+ __gnu_cxx::__ops::__iter_equals_val(__old_value),
+ __new_value);
}
/**
@@ -3911,7 +3166,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*/
template<typename _InputIterator, typename _OutputIterator,
typename _Predicate, typename _Tp>
- _OutputIterator
+ inline _OutputIterator
replace_copy_if(_InputIterator __first, _InputIterator __last,
_OutputIterator __result,
_Predicate __pred, const _Tp& __new_value)
@@ -3924,12 +3179,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typename iterator_traits<_InputIterator>::value_type>)
__glibcxx_requires_valid_range(__first, __last);
- for (; __first != __last; ++__first, ++__result)
- if (__pred(*__first))
- *__result = __new_value;
- else
- *__result = *__first;
- return __result;
+ return std::__replace_copy_if(__first, __last, __result,
+ __gnu_cxx::__ops::__pred_iter(__pred),
+ __new_value);
+ }
+
+ template<typename _InputIterator, typename _Predicate>
+ typename iterator_traits<_InputIterator>::difference_type
+ __count_if(_InputIterator __first, _InputIterator __last, _Predicate __pred)
+ {
+ typename iterator_traits<_InputIterator>::difference_type __n = 0;
+ for (; __first != __last; ++__first)
+ if (__pred(__first))
+ ++__n;
+ return __n;
}
#if __cplusplus >= 201103L
@@ -3960,6 +3223,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_Compare __comp)
{ return std::is_sorted_until(__first, __last, __comp) == __last; }
+ template<typename _ForwardIterator, typename _Compare>
+ _ForwardIterator
+ __is_sorted_until(_ForwardIterator __first, _ForwardIterator __last,
+ _Compare __comp)
+ {
+ if (__first == __last)
+ return __last;
+
+ _ForwardIterator __next = __first;
+ for (++__next; __next != __last; __first = __next, ++__next)
+ if (__comp(__next, __first))
+ return __next;
+ return __next;
+ }
+
/**
* @brief Determines the end of a sorted sequence.
* @ingroup sorting_algorithms
@@ -3969,7 +3247,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* for which the range [__first, i) is sorted.
*/
template<typename _ForwardIterator>
- _ForwardIterator
+ inline _ForwardIterator
is_sorted_until(_ForwardIterator __first, _ForwardIterator __last)
{
// concept requirements
@@ -3978,14 +3256,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typename iterator_traits<_ForwardIterator>::value_type>)
__glibcxx_requires_valid_range(__first, __last);
- if (__first == __last)
- return __last;
-
- _ForwardIterator __next = __first;
- for (++__next; __next != __last; __first = __next, ++__next)
- if (*__next < *__first)
- return __next;
- return __next;
+ return std::__is_sorted_until(__first, __last,
+ __gnu_cxx::__ops::__iter_less_iter());
}
/**
@@ -3998,7 +3270,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* for which the range [__first, i) is sorted.
*/
template<typename _ForwardIterator, typename _Compare>
- _ForwardIterator
+ inline _ForwardIterator
is_sorted_until(_ForwardIterator __first, _ForwardIterator __last,
_Compare __comp)
{
@@ -4009,14 +3281,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typename iterator_traits<_ForwardIterator>::value_type>)
__glibcxx_requires_valid_range(__first, __last);
- if (__first == __last)
- return __last;
-
- _ForwardIterator __next = __first;
- for (++__next; __next != __last; __first = __next, ++__next)
- if (__comp(*__next, *__first))
- return __next;
- return __next;
+ return std::__is_sorted_until(__first, __last,
+ __gnu_cxx::__ops::__iter_comp_iter(__comp));
}
/**
@@ -4055,34 +3321,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: pair<const _Tp&, const _Tp&>(__a, __b);
}
- /**
- * @brief Return a pair of iterators pointing to the minimum and maximum
- * elements in a range.
- * @ingroup sorting_algorithms
- * @param __first Start of range.
- * @param __last End of range.
- * @return make_pair(m, M), where m is the first iterator i in
- * [__first, __last) such that no other element in the range is
- * smaller, and where M is the last iterator i in [__first, __last)
- * such that no other element in the range is larger.
- */
- template<typename _ForwardIterator>
+ template<typename _ForwardIterator, typename _Compare>
pair<_ForwardIterator, _ForwardIterator>
- minmax_element(_ForwardIterator __first, _ForwardIterator __last)
+ __minmax_element(_ForwardIterator __first, _ForwardIterator __last,
+ _Compare __comp)
{
- // concept requirements
- __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
- __glibcxx_function_requires(_LessThanComparableConcept<
- typename iterator_traits<_ForwardIterator>::value_type>)
- __glibcxx_requires_valid_range(__first, __last);
-
_ForwardIterator __next = __first;
if (__first == __last
|| ++__next == __last)
return std::make_pair(__first, __first);
_ForwardIterator __min, __max;
- if (*__next < *__first)
+ if (__comp(__next, __first))
{
__min = __next;
__max = __first;
@@ -4101,25 +3351,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__next = __first;
if (++__next == __last)
{
- if (*__first < *__min)
+ if (__comp(__first, __min))
__min = __first;
- else if (!(*__first < *__max))
+ else if (!__comp(__first, __max))
__max = __first;
break;
}
- if (*__next < *__first)
+ if (__comp(__next, __first))
{
- if (*__next < *__min)
+ if (__comp(__next, __min))
__min = __next;
- if (!(*__first < *__max))
+ if (!__comp(__first, __max))
__max = __first;
}
else
{
- if (*__first < *__min)
+ if (__comp(__first, __min))
__min = __first;
- if (!(*__next < *__max))
+ if (!__comp(__next, __max))
__max = __next;
}
@@ -4136,6 +3386,31 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* @ingroup sorting_algorithms
* @param __first Start of range.
* @param __last End of range.
+ * @return make_pair(m, M), where m is the first iterator i in
+ * [__first, __last) such that no other element in the range is
+ * smaller, and where M is the last iterator i in [__first, __last)
+ * such that no other element in the range is larger.
+ */
+ template<typename _ForwardIterator>
+ inline pair<_ForwardIterator, _ForwardIterator>
+ minmax_element(_ForwardIterator __first, _ForwardIterator __last)
+ {
+ // concept requirements
+ __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
+ __glibcxx_function_requires(_LessThanComparableConcept<
+ typename iterator_traits<_ForwardIterator>::value_type>)
+ __glibcxx_requires_valid_range(__first, __last);
+
+ return std::__minmax_element(__first, __last,
+ __gnu_cxx::__ops::__iter_less_iter());
+ }
+
+ /**
+ * @brief Return a pair of iterators pointing to the minimum and maximum
+ * elements in a range.
+ * @ingroup sorting_algorithms
+ * @param __first Start of range.
+ * @param __last End of range.
* @param __comp Comparison functor.
* @return make_pair(m, M), where m is the first iterator i in
* [__first, __last) such that no other element in the range is
@@ -4143,7 +3418,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* such that no other element in the range is larger.
*/
template<typename _ForwardIterator, typename _Compare>
- pair<_ForwardIterator, _ForwardIterator>
+ inline pair<_ForwardIterator, _ForwardIterator>
minmax_element(_ForwardIterator __first, _ForwardIterator __last,
_Compare __comp)
{
@@ -4154,58 +3429,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typename iterator_traits<_ForwardIterator>::value_type>)
__glibcxx_requires_valid_range(__first, __last);
- _ForwardIterator __next = __first;
- if (__first == __last
- || ++__next == __last)
- return std::make_pair(__first, __first);
-
- _ForwardIterator __min, __max;
- if (__comp(*__next, *__first))
- {
- __min = __next;
- __max = __first;
- }
- else
- {
- __min = __first;
- __max = __next;
- }
-
- __first = __next;
- ++__first;
-
- while (__first != __last)
- {
- __next = __first;
- if (++__next == __last)
- {
- if (__comp(*__first, *__min))
- __min = __first;
- else if (!__comp(*__first, *__max))
- __max = __first;
- break;
- }
-
- if (__comp(*__next, *__first))
- {
- if (__comp(*__next, *__min))
- __min = __next;
- if (!__comp(*__first, *__max))
- __max = __first;
- }
- else
- {
- if (__comp(*__first, *__min))
- __min = __first;
- if (!__comp(*__next, *__max))
- __max = __next;
- }
-
- __first = __next;
- ++__first;
- }
-
- return std::make_pair(__min, __max);
+ return std::__minmax_element(__first, __last,
+ __gnu_cxx::__ops::__iter_comp_iter(__comp));
}
// N2722 + DR 915.
@@ -4247,27 +3472,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return std::make_pair(*__p.first, *__p.second);
}
- /**
- * @brief Checks whether a permutaion of the second sequence is equal
- * to the first sequence.
- * @ingroup non_mutating_algorithms
- * @param __first1 Start of first range.
- * @param __last1 End of first range.
- * @param __first2 Start of second range.
- * @return true if there exists a permutation of the elements in the range
- * [__first2, __first2 + (__last1 - __first1)), beginning with
- * ForwardIterator2 begin, such that equal(__first1, __last1, begin)
- * returns true; otherwise, returns false.
- */
- template<typename _ForwardIterator1, typename _ForwardIterator2>
+ template<typename _ForwardIterator1, typename _ForwardIterator2,
+ typename _BinaryPredicate>
bool
- is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1,
- _ForwardIterator2 __first2)
+ __is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1,
+ _ForwardIterator2 __first2, _BinaryPredicate __pred)
{
// Efficiently compare identical prefixes: O(N) if sequences
// have the same elements in the same order.
for (; __first1 != __last1; ++__first1, ++__first2)
- if (!(*__first1 == *__first2))
+ if (!__pred(__first1, __first2))
break;
if (__first1 == __last1)
@@ -4279,12 +3493,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
std::advance(__last2, std::distance(__first1, __last1));
for (_ForwardIterator1 __scan = __first1; __scan != __last1; ++__scan)
{
- if (__scan != _GLIBCXX_STD_A::find(__first1, __scan, *__scan))
+ if (__scan != std::__find_if(__first1, __scan,
+ __gnu_cxx::__ops::__iter_comp_iter(__pred, __scan)))
continue; // We've seen this one before.
-
- auto __matches = std::count(__first2, __last2, *__scan);
- if (0 == __matches
- || std::count(__scan, __last1, *__scan) != __matches)
+
+ auto __matches
+ = std::__count_if(__first2, __last2,
+ __gnu_cxx::__ops::__iter_comp_iter(__pred, __scan));
+ if (0 == __matches ||
+ std::__count_if(__scan, __last1,
+ __gnu_cxx::__ops::__iter_comp_iter(__pred, __scan))
+ != __matches)
return false;
}
return true;
@@ -4297,6 +3516,35 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* @param __first1 Start of first range.
* @param __last1 End of first range.
* @param __first2 Start of second range.
+ * @return true if there exists a permutation of the elements in the range
+ * [__first2, __first2 + (__last1 - __first1)), beginning with
+ * ForwardIterator2 begin, such that equal(__first1, __last1, begin)
+ * returns true; otherwise, returns false.
+ */
+ template<typename _ForwardIterator1, typename _ForwardIterator2>
+ inline bool
+ is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1,
+ _ForwardIterator2 __first2)
+ {
+ // concept requirements
+ __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator1>)
+ __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator2>)
+ __glibcxx_function_requires(_EqualOpConcept<
+ typename iterator_traits<_ForwardIterator1>::value_type,
+ typename iterator_traits<_ForwardIterator2>::value_type>)
+ __glibcxx_requires_valid_range(__first1, __last1);
+
+ return std::__is_permutation(__first1, __last1, __first2,
+ __gnu_cxx::__ops::__iter_equal_to_iter());
+ }
+
+ /**
+ * @brief Checks whether a permutation of the second sequence is equal
+ * to the first sequence.
+ * @ingroup non_mutating_algorithms
+ * @param __first1 Start of first range.
+ * @param __last1 End of first range.
+ * @param __first2 Start of second range.
* @param __pred A binary predicate.
* @return true if there exists a permutation of the elements in
* the range [__first2, __first2 + (__last1 - __first1)),
@@ -4306,42 +3554,83 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*/
template<typename _ForwardIterator1, typename _ForwardIterator2,
typename _BinaryPredicate>
- bool
+ inline bool
is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1,
_ForwardIterator2 __first2, _BinaryPredicate __pred)
{
+ // concept requirements
+ __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator1>)
+ __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator2>)
+ __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate,
+ typename iterator_traits<_ForwardIterator1>::value_type,
+ typename iterator_traits<_ForwardIterator2>::value_type>)
+ __glibcxx_requires_valid_range(__first1, __last1);
+
+ return std::__is_permutation(__first1, __last1, __first2,
+ __gnu_cxx::__ops::__iter_comp_iter(__pred));
+ }
+
+#if __cplusplus > 201103L
+ template<typename _ForwardIterator1, typename _ForwardIterator2,
+ typename _BinaryPredicate>
+ bool
+ __is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1,
+ _ForwardIterator2 __first2, _ForwardIterator2 __last2,
+ _BinaryPredicate __pred)
+ {
+ using _Cat1
+ = typename iterator_traits<_ForwardIterator1>::iterator_category;
+ using _Cat2
+ = typename iterator_traits<_ForwardIterator2>::iterator_category;
+ using _It1_is_RA = is_same<_Cat1, random_access_iterator_tag>;
+ using _It2_is_RA = is_same<_Cat2, random_access_iterator_tag>;
+ constexpr bool __ra_iters = _It1_is_RA() && _It2_is_RA();
+ if (__ra_iters)
+ {
+ auto __d1 = std::distance(__first1, __last1);
+ auto __d2 = std::distance(__first2, __last2);
+ if (__d1 != __d2)
+ return false;
+ }
+
// Efficiently compare identical prefixes: O(N) if sequences
// have the same elements in the same order.
for (; __first1 != __last1; ++__first1, ++__first2)
- if (!bool(__pred(*__first1, *__first2)))
+ if (!__pred(__first1, __first2))
break;
- if (__first1 == __last1)
- return true;
+ if (__ra_iters)
+ {
+ if (__first1 == __last1)
+ return true;
+ }
+ else
+ {
+ auto __d1 = std::distance(__first1, __last1);
+ auto __d2 = std::distance(__first2, __last2);
+ if (__d1 == 0 && __d2 == 0)
+ return true;
+ if (__d1 != __d2)
+ return false;
+ }
- // Establish __last2 assuming equal ranges by iterating over the
- // rest of the list.
- _ForwardIterator2 __last2 = __first2;
- std::advance(__last2, std::distance(__first1, __last1));
for (_ForwardIterator1 __scan = __first1; __scan != __last1; ++__scan)
{
- using std::placeholders::_1;
-
- if (__scan != _GLIBCXX_STD_A::find_if(__first1, __scan,
- std::bind(__pred, _1, *__scan)))
+ if (__scan != std::__find_if(__first1, __scan,
+ __gnu_cxx::__ops::__iter_comp_iter(__pred, __scan)))
continue; // We've seen this one before.
-
- auto __matches = std::count_if(__first2, __last2,
- std::bind(__pred, _1, *__scan));
+
+ auto __matches = std::__count_if(__first2, __last2,
+ __gnu_cxx::__ops::__iter_comp_iter(__pred, __scan));
if (0 == __matches
- || std::count_if(__scan, __last1,
- std::bind(__pred, _1, *__scan)) != __matches)
+ || std::__count_if(__scan, __last1,
+ __gnu_cxx::__ops::__iter_comp_iter(__pred, __scan))
+ != __matches)
return false;
}
return true;
}
-#if __cplusplus > 201103L
/**
* @brief Checks whether a permutaion of the second sequence is equal
* to the first sequence.
@@ -4356,47 +3645,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* otherwise, returns false.
*/
template<typename _ForwardIterator1, typename _ForwardIterator2>
- bool
+ inline bool
is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1,
_ForwardIterator2 __first2, _ForwardIterator2 __last2)
{
- using _Cat1
- = typename iterator_traits<_ForwardIterator1>::iterator_category;
- using _Cat2
- = typename iterator_traits<_ForwardIterator2>::iterator_category;
- using _It1_is_RA = is_same<_Cat1, random_access_iterator_tag>;
- using _It2_is_RA = is_same<_Cat2, random_access_iterator_tag>;
- if (_It1_is_RA() && _It2_is_RA())
- {
- auto __d1 = std::distance(__first1, __last1);
- auto __d2 = std::distance(__first2, __last2);
- if (__d1 != __d2)
- return false;
- }
-
- // Efficiently compare identical prefixes: O(N) if sequences
- // have the same elements in the same order.
- for (; __first1 != __last1 && __first2 != __last2; ++__first1, ++__first2)
- if (!(*__first1 == *__first2))
- break;
-
- if (__first1 == __last1 && __first2 == __last2)
- return true;
-
- if (std::distance(__first1, __last1) != std::distance(__first2, __last2))
- return false;
-
- for (auto __scan = __first1; __scan != __last1; ++__scan)
- {
- if (__scan != _GLIBCXX_STD_A::find(__first1, __scan, *__scan))
- continue; // We've seen this one before.
+ __glibcxx_requires_valid_range(__first1, __last1);
+ __glibcxx_requires_valid_range(__first2, __last2);
- auto __matches = std::count(__first2, __last2, *__scan);
- if (0 == __matches
- || std::count(__scan, __last1, *__scan) != __matches)
- return false;
- }
- return true;
+ return
+ std::__is_permutation(__first1, __last1, __first2, __last2,
+ __gnu_cxx::__ops::__iter_equal_to_iter());
}
/**
@@ -4415,63 +3673,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*/
template<typename _ForwardIterator1, typename _ForwardIterator2,
typename _BinaryPredicate>
- bool
+ inline bool
is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1,
_ForwardIterator2 __first2, _ForwardIterator2 __last2,
_BinaryPredicate __pred)
{
- using _Cat1
- = typename iterator_traits<_ForwardIterator1>::iterator_category;
- using _Cat2
- = typename iterator_traits<_ForwardIterator2>::iterator_category;
- using _It1_is_RA = is_same<_Cat1, random_access_iterator_tag>;
- using _It2_is_RA = is_same<_Cat2, random_access_iterator_tag>;
- constexpr bool __ra_iters = _It1_is_RA() && _It2_is_RA();
- if (__ra_iters)
- {
- auto __d1 = std::distance(__first1, __last1);
- auto __d2 = std::distance(__first2, __last2);
- if (__d1 != __d2)
- return false;
- }
-
- // Efficiently compare identical prefixes: O(N) if sequences
- // have the same elements in the same order.
- for (; __first1 != __last1; ++__first1, ++__first2)
- if (!bool(__pred(*__first1, *__first2)))
- break;
-
- if (__ra_iters)
- {
- if (__first1 == __last1)
- return true;
- }
- else
- {
- auto __d1 = std::distance(__first1, __last1);
- auto __d2 = std::distance(__first2, __last2);
- if (__d1 == 0 && __d2 == 0)
- return true;
- if (__d1 != __d2)
- return false;
- }
-
- for (_ForwardIterator1 __scan = __first1; __scan != __last1; ++__scan)
- {
- using std::placeholders::_1;
-
- if (__scan != _GLIBCXX_STD_A::find_if(__first1, __scan,
- std::bind(__pred, _1, *__scan)))
- continue; // We've seen this one before.
+ __glibcxx_requires_valid_range(__first1, __last1);
+ __glibcxx_requires_valid_range(__first2, __last2);
- auto __matches = std::count_if(__first2, __last2,
- std::bind(__pred, _1, *__scan));
- if (0 == __matches
- || std::count_if(__scan, __last1,
- std::bind(__pred, _1, *__scan)) != __matches)
- return false;
- }
- return true;
+ return std::__is_permutation(__first1, __last1, __first2, __last2,
+ __gnu_cxx::__ops::__iter_comp_iter(__pred));
}
#endif
@@ -4564,8 +3775,8 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
__glibcxx_function_requires(_EqualOpConcept<
typename iterator_traits<_InputIterator>::value_type, _Tp>)
__glibcxx_requires_valid_range(__first, __last);
- return std::__find(__first, __last, __val,
- std::__iterator_category(__first));
+ return std::__find_if(__first, __last,
+ __gnu_cxx::__ops::__iter_equals_val(__val));
}
/**
@@ -4588,8 +3799,9 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
__glibcxx_function_requires(_UnaryPredicateConcept<_Predicate,
typename iterator_traits<_InputIterator>::value_type>)
__glibcxx_requires_valid_range(__first, __last);
- return std::__find_if(__first, __last, __pred,
- std::__iterator_category(__first));
+
+ return std::__find_if(__first, __last,
+ __gnu_cxx::__ops::__pred_iter(__pred));
}
/**
@@ -4681,7 +3893,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
* or @p __last if no such iterator exists.
*/
template<typename _ForwardIterator>
- _ForwardIterator
+ inline _ForwardIterator
adjacent_find(_ForwardIterator __first, _ForwardIterator __last)
{
// concept requirements
@@ -4689,16 +3901,9 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
__glibcxx_function_requires(_EqualityComparableConcept<
typename iterator_traits<_ForwardIterator>::value_type>)
__glibcxx_requires_valid_range(__first, __last);
- if (__first == __last)
- return __last;
- _ForwardIterator __next = __first;
- while(++__next != __last)
- {
- if (*__first == *__next)
- return __first;
- __first = __next;
- }
- return __last;
+
+ return std::__adjacent_find(__first, __last,
+ __gnu_cxx::__ops::__iter_equal_to_iter());
}
/**
@@ -4713,7 +3918,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
* exists.
*/
template<typename _ForwardIterator, typename _BinaryPredicate>
- _ForwardIterator
+ inline _ForwardIterator
adjacent_find(_ForwardIterator __first, _ForwardIterator __last,
_BinaryPredicate __binary_pred)
{
@@ -4723,16 +3928,9 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
typename iterator_traits<_ForwardIterator>::value_type,
typename iterator_traits<_ForwardIterator>::value_type>)
__glibcxx_requires_valid_range(__first, __last);
- if (__first == __last)
- return __last;
- _ForwardIterator __next = __first;
- while(++__next != __last)
- {
- if (__binary_pred(*__first, *__next))
- return __first;
- __first = __next;
- }
- return __last;
+
+ return std::__adjacent_find(__first, __last,
+ __gnu_cxx::__ops::__iter_comp_iter(__binary_pred));
}
/**
@@ -4745,19 +3943,17 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
* for which @c *i == @p __value
*/
template<typename _InputIterator, typename _Tp>
- typename iterator_traits<_InputIterator>::difference_type
+ inline typename iterator_traits<_InputIterator>::difference_type
count(_InputIterator __first, _InputIterator __last, const _Tp& __value)
{
// concept requirements
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
__glibcxx_function_requires(_EqualOpConcept<
- typename iterator_traits<_InputIterator>::value_type, _Tp>)
+ typename iterator_traits<_InputIterator>::value_type, _Tp>)
__glibcxx_requires_valid_range(__first, __last);
- typename iterator_traits<_InputIterator>::difference_type __n = 0;
- for (; __first != __last; ++__first)
- if (*__first == __value)
- ++__n;
- return __n;
+
+ return std::__count_if(__first, __last,
+ __gnu_cxx::__ops::__iter_equals_val(__value));
}
/**
@@ -4770,7 +3966,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
* for which @p __pred(*i) is true.
*/
template<typename _InputIterator, typename _Predicate>
- typename iterator_traits<_InputIterator>::difference_type
+ inline typename iterator_traits<_InputIterator>::difference_type
count_if(_InputIterator __first, _InputIterator __last, _Predicate __pred)
{
// concept requirements
@@ -4778,11 +3974,9 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
__glibcxx_function_requires(_UnaryPredicateConcept<_Predicate,
typename iterator_traits<_InputIterator>::value_type>)
__glibcxx_requires_valid_range(__first, __last);
- typename iterator_traits<_InputIterator>::difference_type __n = 0;
- for (; __first != __last; ++__first)
- if (__pred(*__first))
- ++__n;
- return __n;
+
+ return std::__count_if(__first, __last,
+ __gnu_cxx::__ops::__pred_iter(__pred));
}
/**
@@ -4812,7 +4006,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
* @p [__first1,__last1-(__last2-__first2))
*/
template<typename _ForwardIterator1, typename _ForwardIterator2>
- _ForwardIterator1
+ inline _ForwardIterator1
search(_ForwardIterator1 __first1, _ForwardIterator1 __last1,
_ForwardIterator2 __first2, _ForwardIterator2 __last2)
{
@@ -4825,40 +4019,8 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
__glibcxx_requires_valid_range(__first1, __last1);
__glibcxx_requires_valid_range(__first2, __last2);
- // Test for empty ranges
- if (__first1 == __last1 || __first2 == __last2)
- return __first1;
-
- // Test for a pattern of length 1.
- _ForwardIterator2 __p1(__first2);
- if (++__p1 == __last2)
- return _GLIBCXX_STD_A::find(__first1, __last1, *__first2);
-
- // General case.
- _ForwardIterator2 __p;
- _ForwardIterator1 __current = __first1;
-
- for (;;)
- {
- __first1 = _GLIBCXX_STD_A::find(__first1, __last1, *__first2);
- if (__first1 == __last1)
- return __last1;
-
- __p = __p1;
- __current = __first1;
- if (++__current == __last1)
- return __last1;
-
- while (*__current == *__p)
- {
- if (++__p == __last2)
- return __first1;
- if (++__current == __last1)
- return __last1;
- }
- ++__first1;
- }
- return __first1;
+ return std::__search(__first1, __last1, __first2, __last2,
+ __gnu_cxx::__ops::__iter_equal_to_iter());
}
/**
@@ -4884,7 +4046,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
*/
template<typename _ForwardIterator1, typename _ForwardIterator2,
typename _BinaryPredicate>
- _ForwardIterator1
+ inline _ForwardIterator1
search(_ForwardIterator1 __first1, _ForwardIterator1 __last1,
_ForwardIterator2 __first2, _ForwardIterator2 __last2,
_BinaryPredicate __predicate)
@@ -4898,50 +4060,10 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
__glibcxx_requires_valid_range(__first1, __last1);
__glibcxx_requires_valid_range(__first2, __last2);
- // Test for empty ranges
- if (__first1 == __last1 || __first2 == __last2)
- return __first1;
-
- // Test for a pattern of length 1.
- _ForwardIterator2 __p1(__first2);
- if (++__p1 == __last2)
- {
- while (__first1 != __last1
- && !bool(__predicate(*__first1, *__first2)))
- ++__first1;
- return __first1;
- }
-
- // General case.
- _ForwardIterator2 __p;
- _ForwardIterator1 __current = __first1;
-
- for (;;)
- {
- while (__first1 != __last1
- && !bool(__predicate(*__first1, *__first2)))
- ++__first1;
- if (__first1 == __last1)
- return __last1;
-
- __p = __p1;
- __current = __first1;
- if (++__current == __last1)
- return __last1;
-
- while (__predicate(*__current, *__p))
- {
- if (++__p == __last2)
- return __first1;
- if (++__current == __last1)
- return __last1;
- }
- ++__first1;
- }
- return __first1;
+ return std::__search(__first1, __last1, __first2, __last2,
+ __gnu_cxx::__ops::__iter_comp_iter(__predicate));
}
-
/**
* @brief Search a sequence for a number of consecutive values.
* @ingroup non_mutating_algorithms
@@ -4958,22 +4080,18 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
* equal to @p __val.
*/
template<typename _ForwardIterator, typename _Integer, typename _Tp>
- _ForwardIterator
+ inline _ForwardIterator
search_n(_ForwardIterator __first, _ForwardIterator __last,
_Integer __count, const _Tp& __val)
{
// concept requirements
__glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
__glibcxx_function_requires(_EqualOpConcept<
- typename iterator_traits<_ForwardIterator>::value_type, _Tp>)
+ typename iterator_traits<_ForwardIterator>::value_type, _Tp>)
__glibcxx_requires_valid_range(__first, __last);
- if (__count <= 0)
- return __first;
- if (__count == 1)
- return _GLIBCXX_STD_A::find(__first, __last, __val);
- return std::__search_n(__first, __last, __count, __val,
- std::__iterator_category(__first));
+ return std::__search_n(__first, __last, __count,
+ __gnu_cxx::__ops::__iter_equals_val(__val));
}
@@ -4996,7 +4114,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
*/
template<typename _ForwardIterator, typename _Integer, typename _Tp,
typename _BinaryPredicate>
- _ForwardIterator
+ inline _ForwardIterator
search_n(_ForwardIterator __first, _ForwardIterator __last,
_Integer __count, const _Tp& __val,
_BinaryPredicate __binary_pred)
@@ -5007,16 +4125,8 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
typename iterator_traits<_ForwardIterator>::value_type, _Tp>)
__glibcxx_requires_valid_range(__first, __last);
- if (__count <= 0)
- return __first;
- if (__count == 1)
- {
- while (__first != __last && !bool(__binary_pred(*__first, __val)))
- ++__first;
- return __first;
- }
- return std::__search_n(__first, __last, __count, __val, __binary_pred,
- std::__iterator_category(__first));
+ return std::__search_n(__first, __last, __count,
+ __gnu_cxx::__ops::__iter_comp_val(__binary_pred, __val));
}
@@ -5216,7 +4326,6 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
return __first;
}
-
/**
* @brief Copy a sequence, removing consecutive duplicate values.
* @ingroup mutating_algorithms
@@ -5254,6 +4363,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
if (__first == __last)
return __result;
return std::__unique_copy(__first, __last, __result,
+ __gnu_cxx::__ops::__iter_equal_to_iter(),
std::__iterator_category(__first),
std::__iterator_category(__result));
}
@@ -5292,12 +4402,12 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
if (__first == __last)
return __result;
- return std::__unique_copy(__first, __last, __result, __binary_pred,
+ return std::__unique_copy(__first, __last, __result,
+ __gnu_cxx::__ops::__iter_comp_iter(__binary_pred),
std::__iterator_category(__first),
std::__iterator_category(__result));
}
-
/**
* @brief Randomly shuffle the elements of a sequence.
* @ingroup mutating_algorithms
@@ -5390,7 +4500,6 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
}
-
/**
* @brief Sort the smallest elements of a sequence.
* @ingroup sorting_algorithms
@@ -5413,18 +4522,16 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
_RandomAccessIterator __middle,
_RandomAccessIterator __last)
{
- typedef typename iterator_traits<_RandomAccessIterator>::value_type
- _ValueType;
-
// concept requirements
__glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
_RandomAccessIterator>)
- __glibcxx_function_requires(_LessThanComparableConcept<_ValueType>)
+ __glibcxx_function_requires(_LessThanComparableConcept<
+ typename iterator_traits<_RandomAccessIterator>::value_type>)
__glibcxx_requires_valid_range(__first, __middle);
__glibcxx_requires_valid_range(__middle, __last);
- std::__heap_select(__first, __middle, __last);
- std::sort_heap(__first, __middle);
+ std::__partial_sort(__first, __middle, __last,
+ __gnu_cxx::__ops::__iter_less_iter());
}
/**
@@ -5453,19 +4560,17 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
_RandomAccessIterator __last,
_Compare __comp)
{
- typedef typename iterator_traits<_RandomAccessIterator>::value_type
- _ValueType;
-
// concept requirements
__glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
_RandomAccessIterator>)
__glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
- _ValueType, _ValueType>)
+ typename iterator_traits<_RandomAccessIterator>::value_type,
+ typename iterator_traits<_RandomAccessIterator>::value_type>)
__glibcxx_requires_valid_range(__first, __middle);
__glibcxx_requires_valid_range(__middle, __last);
- std::__heap_select(__first, __middle, __last, __comp);
- std::sort_heap(__first, __middle, __comp);
+ std::__partial_sort(__first, __middle, __last,
+ __gnu_cxx::__ops::__iter_comp_iter(__comp));
}
/**
@@ -5488,13 +4593,11 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth,
_RandomAccessIterator __last)
{
- typedef typename iterator_traits<_RandomAccessIterator>::value_type
- _ValueType;
-
// concept requirements
__glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
_RandomAccessIterator>)
- __glibcxx_function_requires(_LessThanComparableConcept<_ValueType>)
+ __glibcxx_function_requires(_LessThanComparableConcept<
+ typename iterator_traits<_RandomAccessIterator>::value_type>)
__glibcxx_requires_valid_range(__first, __nth);
__glibcxx_requires_valid_range(__nth, __last);
@@ -5502,7 +4605,8 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
return;
std::__introselect(__first, __nth, __last,
- std::__lg(__last - __first) * 2);
+ std::__lg(__last - __first) * 2,
+ __gnu_cxx::__ops::__iter_less_iter());
}
/**
@@ -5527,14 +4631,12 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth,
_RandomAccessIterator __last, _Compare __comp)
{
- typedef typename iterator_traits<_RandomAccessIterator>::value_type
- _ValueType;
-
// concept requirements
__glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
_RandomAccessIterator>)
__glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
- _ValueType, _ValueType>)
+ typename iterator_traits<_RandomAccessIterator>::value_type,
+ typename iterator_traits<_RandomAccessIterator>::value_type>)
__glibcxx_requires_valid_range(__first, __nth);
__glibcxx_requires_valid_range(__nth, __last);
@@ -5542,10 +4644,10 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
return;
std::__introselect(__first, __nth, __last,
- std::__lg(__last - __first) * 2, __comp);
+ std::__lg(__last - __first) * 2,
+ __gnu_cxx::__ops::__iter_comp_iter(__comp));
}
-
/**
* @brief Sort the elements of a sequence.
* @ingroup sorting_algorithms
@@ -5564,21 +4666,14 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
inline void
sort(_RandomAccessIterator __first, _RandomAccessIterator __last)
{
- typedef typename iterator_traits<_RandomAccessIterator>::value_type
- _ValueType;
-
// concept requirements
__glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
_RandomAccessIterator>)
- __glibcxx_function_requires(_LessThanComparableConcept<_ValueType>)
+ __glibcxx_function_requires(_LessThanComparableConcept<
+ typename iterator_traits<_RandomAccessIterator>::value_type>)
__glibcxx_requires_valid_range(__first, __last);
- if (__first != __last)
- {
- std::__introsort_loop(__first, __last,
- std::__lg(__last - __first) * 2);
- std::__final_insertion_sort(__first, __last);
- }
+ std::__sort(__first, __last, __gnu_cxx::__ops::__iter_less_iter());
}
/**
@@ -5601,22 +4696,40 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
sort(_RandomAccessIterator __first, _RandomAccessIterator __last,
_Compare __comp)
{
- typedef typename iterator_traits<_RandomAccessIterator>::value_type
- _ValueType;
-
// concept requirements
__glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
_RandomAccessIterator>)
- __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, _ValueType,
- _ValueType>)
+ __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
+ typename iterator_traits<_RandomAccessIterator>::value_type,
+ typename iterator_traits<_RandomAccessIterator>::value_type>)
__glibcxx_requires_valid_range(__first, __last);
- if (__first != __last)
+ std::__sort(__first, __last, __gnu_cxx::__ops::__iter_comp_iter(__comp));
+ }
+
+ template<typename _InputIterator1, typename _InputIterator2,
+ typename _OutputIterator, typename _Compare>
+ _OutputIterator
+ __merge(_InputIterator1 __first1, _InputIterator1 __last1,
+ _InputIterator2 __first2, _InputIterator2 __last2,
+ _OutputIterator __result, _Compare __comp)
+ {
+ while (__first1 != __last1 && __first2 != __last2)
{
- std::__introsort_loop(__first, __last,
- std::__lg(__last - __first) * 2, __comp);
- std::__final_insertion_sort(__first, __last, __comp);
+ if (__comp(__first2, __first1))
+ {
+ *__result = *__first2;
+ ++__first2;
+ }
+ else
+ {
+ *__result = *__first1;
+ ++__first1;
+ }
+ ++__result;
}
+ return std::copy(__first2, __last2,
+ std::copy(__first1, __last1, __result));
}
/**
@@ -5640,43 +4753,27 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
*/
template<typename _InputIterator1, typename _InputIterator2,
typename _OutputIterator>
- _OutputIterator
+ inline _OutputIterator
merge(_InputIterator1 __first1, _InputIterator1 __last1,
_InputIterator2 __first2, _InputIterator2 __last2,
_OutputIterator __result)
{
- typedef typename iterator_traits<_InputIterator1>::value_type
- _ValueType1;
- typedef typename iterator_traits<_InputIterator2>::value_type
- _ValueType2;
-
// concept requirements
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>)
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>)
__glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
- _ValueType1>)
+ typename iterator_traits<_InputIterator1>::value_type>)
__glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
- _ValueType2>)
- __glibcxx_function_requires(_LessThanOpConcept<_ValueType2, _ValueType1>)
+ typename iterator_traits<_InputIterator2>::value_type>)
+ __glibcxx_function_requires(_LessThanOpConcept<
+ typename iterator_traits<_InputIterator2>::value_type,
+ typename iterator_traits<_InputIterator1>::value_type>)
__glibcxx_requires_sorted_set(__first1, __last1, __first2);
__glibcxx_requires_sorted_set(__first2, __last2, __first1);
- while (__first1 != __last1 && __first2 != __last2)
- {
- if (*__first2 < *__first1)
- {
- *__result = *__first2;
- ++__first2;
- }
- else
- {
- *__result = *__first1;
- ++__first1;
- }
- ++__result;
- }
- return std::copy(__first2, __last2, std::copy(__first1, __last1,
- __result));
+ return _GLIBCXX_STD_A::__merge(__first1, __last1,
+ __first2, __last2, __result,
+ __gnu_cxx::__ops::__iter_less_iter());
}
/**
@@ -5704,46 +4801,48 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
*/
template<typename _InputIterator1, typename _InputIterator2,
typename _OutputIterator, typename _Compare>
- _OutputIterator
+ inline _OutputIterator
merge(_InputIterator1 __first1, _InputIterator1 __last1,
_InputIterator2 __first2, _InputIterator2 __last2,
_OutputIterator __result, _Compare __comp)
{
- typedef typename iterator_traits<_InputIterator1>::value_type
- _ValueType1;
- typedef typename iterator_traits<_InputIterator2>::value_type
- _ValueType2;
-
// concept requirements
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>)
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>)
__glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
- _ValueType1>)
+ typename iterator_traits<_InputIterator1>::value_type>)
__glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
- _ValueType2>)
+ typename iterator_traits<_InputIterator2>::value_type>)
__glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
- _ValueType2, _ValueType1>)
+ typename iterator_traits<_InputIterator2>::value_type,
+ typename iterator_traits<_InputIterator1>::value_type>)
__glibcxx_requires_sorted_set_pred(__first1, __last1, __first2, __comp);
__glibcxx_requires_sorted_set_pred(__first2, __last2, __first1, __comp);
- while (__first1 != __last1 && __first2 != __last2)
- {
- if (__comp(*__first2, *__first1))
- {
- *__result = *__first2;
- ++__first2;
- }
- else
- {
- *__result = *__first1;
- ++__first1;
- }
- ++__result;
- }
- return std::copy(__first2, __last2, std::copy(__first1, __last1,
- __result));
+ return _GLIBCXX_STD_A::__merge(__first1, __last1,
+ __first2, __last2, __result,
+ __gnu_cxx::__ops::__iter_comp_iter(__comp));
}
+ template<typename _RandomAccessIterator, typename _Compare>
+ inline void
+ __stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last,
+ _Compare __comp)
+ {
+ typedef typename iterator_traits<_RandomAccessIterator>::value_type
+ _ValueType;
+ typedef typename iterator_traits<_RandomAccessIterator>::difference_type
+ _DistanceType;
+
+ typedef _Temporary_buffer<_RandomAccessIterator, _ValueType> _TmpBuf;
+ _TmpBuf __buf(__first, __last);
+
+ if (__buf.begin() == 0)
+ std::__inplace_stable_sort(__first, __last, __comp);
+ else
+ std::__stable_sort_adaptive(__first, __last, __buf.begin(),
+ _DistanceType(__buf.size()), __comp);
+ }
/**
* @brief Sort the elements of a sequence, preserving the relative order
@@ -5766,24 +4865,15 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
inline void
stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last)
{
- typedef typename iterator_traits<_RandomAccessIterator>::value_type
- _ValueType;
- typedef typename iterator_traits<_RandomAccessIterator>::difference_type
- _DistanceType;
-
// concept requirements
__glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
_RandomAccessIterator>)
- __glibcxx_function_requires(_LessThanComparableConcept<_ValueType>)
+ __glibcxx_function_requires(_LessThanComparableConcept<
+ typename iterator_traits<_RandomAccessIterator>::value_type>)
__glibcxx_requires_valid_range(__first, __last);
- _Temporary_buffer<_RandomAccessIterator, _ValueType> __buf(__first,
- __last);
- if (__buf.begin() == 0)
- std::__inplace_stable_sort(__first, __last);
- else
- std::__stable_sort_adaptive(__first, __last, __buf.begin(),
- _DistanceType(__buf.size()));
+ _GLIBCXX_STD_A::__stable_sort(__first, __last,
+ __gnu_cxx::__ops::__iter_less_iter());
}
/**
@@ -5809,28 +4899,49 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last,
_Compare __comp)
{
- typedef typename iterator_traits<_RandomAccessIterator>::value_type
- _ValueType;
- typedef typename iterator_traits<_RandomAccessIterator>::difference_type
- _DistanceType;
-
// concept requirements
__glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
_RandomAccessIterator>)
__glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
- _ValueType,
- _ValueType>)
+ typename iterator_traits<_RandomAccessIterator>::value_type,
+ typename iterator_traits<_RandomAccessIterator>::value_type>)
__glibcxx_requires_valid_range(__first, __last);
- _Temporary_buffer<_RandomAccessIterator, _ValueType> __buf(__first,
- __last);
- if (__buf.begin() == 0)
- std::__inplace_stable_sort(__first, __last, __comp);
- else
- std::__stable_sort_adaptive(__first, __last, __buf.begin(),
- _DistanceType(__buf.size()), __comp);
+ _GLIBCXX_STD_A::__stable_sort(__first, __last,
+ __gnu_cxx::__ops::__iter_comp_iter(__comp));
}
+ template<typename _InputIterator1, typename _InputIterator2,
+ typename _OutputIterator,
+ typename _Compare>
+ _OutputIterator
+ __set_union(_InputIterator1 __first1, _InputIterator1 __last1,
+ _InputIterator2 __first2, _InputIterator2 __last2,
+ _OutputIterator __result, _Compare __comp)
+ {
+ while (__first1 != __last1 && __first2 != __last2)
+ {
+ if (__comp(__first1, __first2))
+ {
+ *__result = *__first1;
+ ++__first1;
+ }
+ else if (__comp(__first2, __first1))
+ {
+ *__result = *__first2;
+ ++__first2;
+ }
+ else
+ {
+ *__result = *__first1;
+ ++__first1;
+ ++__first2;
+ }
+ ++__result;
+ }
+ return std::copy(__first2, __last2,
+ std::copy(__first1, __last1, __result));
+ }
/**
* @brief Return the union of two sorted ranges.
@@ -5852,50 +4963,30 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
*/
template<typename _InputIterator1, typename _InputIterator2,
typename _OutputIterator>
- _OutputIterator
+ inline _OutputIterator
set_union(_InputIterator1 __first1, _InputIterator1 __last1,
_InputIterator2 __first2, _InputIterator2 __last2,
_OutputIterator __result)
{
- typedef typename iterator_traits<_InputIterator1>::value_type
- _ValueType1;
- typedef typename iterator_traits<_InputIterator2>::value_type
- _ValueType2;
-
// concept requirements
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>)
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>)
__glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
- _ValueType1>)
+ typename iterator_traits<_InputIterator1>::value_type>)
__glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
- _ValueType2>)
- __glibcxx_function_requires(_LessThanOpConcept<_ValueType1, _ValueType2>)
- __glibcxx_function_requires(_LessThanOpConcept<_ValueType2, _ValueType1>)
+ typename iterator_traits<_InputIterator2>::value_type>)
+ __glibcxx_function_requires(_LessThanOpConcept<
+ typename iterator_traits<_InputIterator1>::value_type,
+ typename iterator_traits<_InputIterator2>::value_type>)
+ __glibcxx_function_requires(_LessThanOpConcept<
+ typename iterator_traits<_InputIterator2>::value_type,
+ typename iterator_traits<_InputIterator1>::value_type>)
__glibcxx_requires_sorted_set(__first1, __last1, __first2);
__glibcxx_requires_sorted_set(__first2, __last2, __first1);
- while (__first1 != __last1 && __first2 != __last2)
- {
- if (*__first1 < *__first2)
- {
- *__result = *__first1;
- ++__first1;
- }
- else if (*__first2 < *__first1)
- {
- *__result = *__first2;
- ++__first2;
- }
- else
- {
- *__result = *__first1;
- ++__first1;
- ++__first2;
- }
- ++__result;
- }
- return std::copy(__first2, __last2, std::copy(__first1, __last1,
- __result));
+ return _GLIBCXX_STD_A::__set_union(__first1, __last1,
+ __first2, __last2, __result,
+ __gnu_cxx::__ops::__iter_less_iter());
}
/**
@@ -5919,52 +5010,53 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
*/
template<typename _InputIterator1, typename _InputIterator2,
typename _OutputIterator, typename _Compare>
- _OutputIterator
+ inline _OutputIterator
set_union(_InputIterator1 __first1, _InputIterator1 __last1,
_InputIterator2 __first2, _InputIterator2 __last2,
_OutputIterator __result, _Compare __comp)
{
- typedef typename iterator_traits<_InputIterator1>::value_type
- _ValueType1;
- typedef typename iterator_traits<_InputIterator2>::value_type
- _ValueType2;
-
// concept requirements
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>)
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>)
__glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
- _ValueType1>)
+ typename iterator_traits<_InputIterator1>::value_type>)
__glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
- _ValueType2>)
+ typename iterator_traits<_InputIterator2>::value_type>)
__glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
- _ValueType1, _ValueType2>)
+ typename iterator_traits<_InputIterator1>::value_type,
+ typename iterator_traits<_InputIterator2>::value_type>)
__glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
- _ValueType2, _ValueType1>)
+ typename iterator_traits<_InputIterator2>::value_type,
+ typename iterator_traits<_InputIterator1>::value_type>)
__glibcxx_requires_sorted_set_pred(__first1, __last1, __first2, __comp);
__glibcxx_requires_sorted_set_pred(__first2, __last2, __first1, __comp);
+ return _GLIBCXX_STD_A::__set_union(__first1, __last1,
+ __first2, __last2, __result,
+ __gnu_cxx::__ops::__iter_comp_iter(__comp));
+ }
+
+ template<typename _InputIterator1, typename _InputIterator2,
+ typename _OutputIterator,
+ typename _Compare>
+ _OutputIterator
+ __set_intersection(_InputIterator1 __first1, _InputIterator1 __last1,
+ _InputIterator2 __first2, _InputIterator2 __last2,
+ _OutputIterator __result, _Compare __comp)
+ {
while (__first1 != __last1 && __first2 != __last2)
- {
- if (__comp(*__first1, *__first2))
- {
- *__result = *__first1;
- ++__first1;
- }
- else if (__comp(*__first2, *__first1))
- {
- *__result = *__first2;
- ++__first2;
- }
- else
- {
- *__result = *__first1;
- ++__first1;
- ++__first2;
- }
- ++__result;
- }
- return std::copy(__first2, __last2, std::copy(__first1, __last1,
- __result));
+ if (__comp(__first1, __first2))
+ ++__first1;
+ else if (__comp(__first2, __first1))
+ ++__first2;
+ else
+ {
+ *__result = *__first1;
+ ++__first1;
+ ++__first2;
+ ++__result;
+ }
+ return __result;
}
/**
@@ -5986,39 +5078,28 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
*/
template<typename _InputIterator1, typename _InputIterator2,
typename _OutputIterator>
- _OutputIterator
+ inline _OutputIterator
set_intersection(_InputIterator1 __first1, _InputIterator1 __last1,
_InputIterator2 __first2, _InputIterator2 __last2,
_OutputIterator __result)
{
- typedef typename iterator_traits<_InputIterator1>::value_type
- _ValueType1;
- typedef typename iterator_traits<_InputIterator2>::value_type
- _ValueType2;
-
// concept requirements
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>)
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>)
__glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
- _ValueType1>)
- __glibcxx_function_requires(_LessThanOpConcept<_ValueType1, _ValueType2>)
- __glibcxx_function_requires(_LessThanOpConcept<_ValueType2, _ValueType1>)
+ typename iterator_traits<_InputIterator1>::value_type>)
+ __glibcxx_function_requires(_LessThanOpConcept<
+ typename iterator_traits<_InputIterator1>::value_type,
+ typename iterator_traits<_InputIterator2>::value_type>)
+ __glibcxx_function_requires(_LessThanOpConcept<
+ typename iterator_traits<_InputIterator2>::value_type,
+ typename iterator_traits<_InputIterator1>::value_type>)
__glibcxx_requires_sorted_set(__first1, __last1, __first2);
__glibcxx_requires_sorted_set(__first2, __last2, __first1);
- while (__first1 != __last1 && __first2 != __last2)
- if (*__first1 < *__first2)
- ++__first1;
- else if (*__first2 < *__first1)
- ++__first2;
- else
- {
- *__result = *__first1;
- ++__first1;
- ++__first2;
- ++__result;
- }
- return __result;
+ return _GLIBCXX_STD_A::__set_intersection(__first1, __last1,
+ __first2, __last2, __result,
+ __gnu_cxx::__ops::__iter_less_iter());
}
/**
@@ -6043,41 +5124,53 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
*/
template<typename _InputIterator1, typename _InputIterator2,
typename _OutputIterator, typename _Compare>
- _OutputIterator
+ inline _OutputIterator
set_intersection(_InputIterator1 __first1, _InputIterator1 __last1,
_InputIterator2 __first2, _InputIterator2 __last2,
_OutputIterator __result, _Compare __comp)
{
- typedef typename iterator_traits<_InputIterator1>::value_type
- _ValueType1;
- typedef typename iterator_traits<_InputIterator2>::value_type
- _ValueType2;
-
// concept requirements
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>)
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>)
__glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
- _ValueType1>)
+ typename iterator_traits<_InputIterator1>::value_type>)
__glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
- _ValueType1, _ValueType2>)
+ typename iterator_traits<_InputIterator1>::value_type,
+ typename iterator_traits<_InputIterator2>::value_type>)
__glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
- _ValueType2, _ValueType1>)
+ typename iterator_traits<_InputIterator2>::value_type,
+ typename iterator_traits<_InputIterator1>::value_type>)
__glibcxx_requires_sorted_set_pred(__first1, __last1, __first2, __comp);
__glibcxx_requires_sorted_set_pred(__first2, __last2, __first1, __comp);
+ return _GLIBCXX_STD_A::__set_intersection(__first1, __last1,
+ __first2, __last2, __result,
+ __gnu_cxx::__ops::__iter_comp_iter(__comp));
+ }
+
+ template<typename _InputIterator1, typename _InputIterator2,
+ typename _OutputIterator,
+ typename _Compare>
+ _OutputIterator
+ __set_difference(_InputIterator1 __first1, _InputIterator1 __last1,
+ _InputIterator2 __first2, _InputIterator2 __last2,
+ _OutputIterator __result, _Compare __comp)
+ {
while (__first1 != __last1 && __first2 != __last2)
- if (__comp(*__first1, *__first2))
- ++__first1;
- else if (__comp(*__first2, *__first1))
+ if (__comp(__first1, __first2))
+ {
+ *__result = *__first1;
+ ++__first1;
+ ++__result;
+ }
+ else if (__comp(__first2, __first1))
++__first2;
else
{
- *__result = *__first1;
++__first1;
++__first2;
- ++__result;
}
- return __result;
+ return std::copy(__first1, __last1, __result);
}
/**
@@ -6101,41 +5194,28 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
*/
template<typename _InputIterator1, typename _InputIterator2,
typename _OutputIterator>
- _OutputIterator
+ inline _OutputIterator
set_difference(_InputIterator1 __first1, _InputIterator1 __last1,
_InputIterator2 __first2, _InputIterator2 __last2,
_OutputIterator __result)
{
- typedef typename iterator_traits<_InputIterator1>::value_type
- _ValueType1;
- typedef typename iterator_traits<_InputIterator2>::value_type
- _ValueType2;
-
// concept requirements
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>)
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>)
__glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
- _ValueType1>)
- __glibcxx_function_requires(_LessThanOpConcept<_ValueType1, _ValueType2>)
- __glibcxx_function_requires(_LessThanOpConcept<_ValueType2, _ValueType1>)
+ typename iterator_traits<_InputIterator1>::value_type>)
+ __glibcxx_function_requires(_LessThanOpConcept<
+ typename iterator_traits<_InputIterator1>::value_type,
+ typename iterator_traits<_InputIterator2>::value_type>)
+ __glibcxx_function_requires(_LessThanOpConcept<
+ typename iterator_traits<_InputIterator2>::value_type,
+ typename iterator_traits<_InputIterator1>::value_type>)
__glibcxx_requires_sorted_set(__first1, __last1, __first2);
__glibcxx_requires_sorted_set(__first2, __last2, __first1);
- while (__first1 != __last1 && __first2 != __last2)
- if (*__first1 < *__first2)
- {
- *__result = *__first1;
- ++__first1;
- ++__result;
- }
- else if (*__first2 < *__first1)
- ++__first2;
- else
- {
- ++__first1;
- ++__first2;
- }
- return std::copy(__first1, __last1, __result);
+ return _GLIBCXX_STD_A::__set_difference(__first1, __last1,
+ __first2, __last2, __result,
+ __gnu_cxx::__ops::__iter_less_iter());
}
/**
@@ -6162,43 +5242,61 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
*/
template<typename _InputIterator1, typename _InputIterator2,
typename _OutputIterator, typename _Compare>
- _OutputIterator
+ inline _OutputIterator
set_difference(_InputIterator1 __first1, _InputIterator1 __last1,
_InputIterator2 __first2, _InputIterator2 __last2,
_OutputIterator __result, _Compare __comp)
{
- typedef typename iterator_traits<_InputIterator1>::value_type
- _ValueType1;
- typedef typename iterator_traits<_InputIterator2>::value_type
- _ValueType2;
-
// concept requirements
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>)
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>)
__glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
- _ValueType1>)
+ typename iterator_traits<_InputIterator1>::value_type>)
__glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
- _ValueType1, _ValueType2>)
+ typename iterator_traits<_InputIterator1>::value_type,
+ typename iterator_traits<_InputIterator2>::value_type>)
__glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
- _ValueType2, _ValueType1>)
+ typename iterator_traits<_InputIterator2>::value_type,
+ typename iterator_traits<_InputIterator1>::value_type>)
__glibcxx_requires_sorted_set_pred(__first1, __last1, __first2, __comp);
__glibcxx_requires_sorted_set_pred(__first2, __last2, __first1, __comp);
+ return _GLIBCXX_STD_A::__set_difference(__first1, __last1,
+ __first2, __last2, __result,
+ __gnu_cxx::__ops::__iter_comp_iter(__comp));
+ }
+
+ template<typename _InputIterator1, typename _InputIterator2,
+ typename _OutputIterator,
+ typename _Compare>
+ _OutputIterator
+ __set_symmetric_difference(_InputIterator1 __first1,
+ _InputIterator1 __last1,
+ _InputIterator2 __first2,
+ _InputIterator2 __last2,
+ _OutputIterator __result,
+ _Compare __comp)
+ {
while (__first1 != __last1 && __first2 != __last2)
- if (__comp(*__first1, *__first2))
+ if (__comp(__first1, __first2))
{
*__result = *__first1;
++__first1;
++__result;
}
- else if (__comp(*__first2, *__first1))
- ++__first2;
+ else if (__comp(__first2, __first1))
+ {
+ *__result = *__first2;
+ ++__first2;
+ ++__result;
+ }
else
{
++__first1;
++__first2;
}
- return std::copy(__first1, __last1, __result);
+ return std::copy(__first2, __last2,
+ std::copy(__first1, __last1, __result));
}
/**
@@ -6220,48 +5318,30 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
*/
template<typename _InputIterator1, typename _InputIterator2,
typename _OutputIterator>
- _OutputIterator
+ inline _OutputIterator
set_symmetric_difference(_InputIterator1 __first1, _InputIterator1 __last1,
_InputIterator2 __first2, _InputIterator2 __last2,
_OutputIterator __result)
{
- typedef typename iterator_traits<_InputIterator1>::value_type
- _ValueType1;
- typedef typename iterator_traits<_InputIterator2>::value_type
- _ValueType2;
-
// concept requirements
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>)
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>)
__glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
- _ValueType1>)
+ typename iterator_traits<_InputIterator1>::value_type>)
__glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
- _ValueType2>)
- __glibcxx_function_requires(_LessThanOpConcept<_ValueType1, _ValueType2>)
- __glibcxx_function_requires(_LessThanOpConcept<_ValueType2, _ValueType1>)
+ typename iterator_traits<_InputIterator2>::value_type>)
+ __glibcxx_function_requires(_LessThanOpConcept<
+ typename iterator_traits<_InputIterator1>::value_type,
+ typename iterator_traits<_InputIterator2>::value_type>)
+ __glibcxx_function_requires(_LessThanOpConcept<
+ typename iterator_traits<_InputIterator2>::value_type,
+ typename iterator_traits<_InputIterator1>::value_type>)
__glibcxx_requires_sorted_set(__first1, __last1, __first2);
__glibcxx_requires_sorted_set(__first2, __last2, __first1);
- while (__first1 != __last1 && __first2 != __last2)
- if (*__first1 < *__first2)
- {
- *__result = *__first1;
- ++__first1;
- ++__result;
- }
- else if (*__first2 < *__first1)
- {
- *__result = *__first2;
- ++__first2;
- ++__result;
- }
- else
- {
- ++__first1;
- ++__first2;
- }
- return std::copy(__first2, __last2, std::copy(__first1,
- __last1, __result));
+ return _GLIBCXX_STD_A::__set_symmetric_difference(__first1, __last1,
+ __first2, __last2, __result,
+ __gnu_cxx::__ops::__iter_less_iter());
}
/**
@@ -6286,53 +5366,46 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
*/
template<typename _InputIterator1, typename _InputIterator2,
typename _OutputIterator, typename _Compare>
- _OutputIterator
+ inline _OutputIterator
set_symmetric_difference(_InputIterator1 __first1, _InputIterator1 __last1,
_InputIterator2 __first2, _InputIterator2 __last2,
_OutputIterator __result,
_Compare __comp)
{
- typedef typename iterator_traits<_InputIterator1>::value_type
- _ValueType1;
- typedef typename iterator_traits<_InputIterator2>::value_type
- _ValueType2;
-
// concept requirements
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>)
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>)
__glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
- _ValueType1>)
+ typename iterator_traits<_InputIterator1>::value_type>)
__glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
- _ValueType2>)
+ typename iterator_traits<_InputIterator2>::value_type>)
__glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
- _ValueType1, _ValueType2>)
+ typename iterator_traits<_InputIterator1>::value_type,
+ typename iterator_traits<_InputIterator2>::value_type>)
__glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
- _ValueType2, _ValueType1>)
+ typename iterator_traits<_InputIterator2>::value_type,
+ typename iterator_traits<_InputIterator1>::value_type>)
__glibcxx_requires_sorted_set_pred(__first1, __last1, __first2, __comp);
__glibcxx_requires_sorted_set_pred(__first2, __last2, __first1, __comp);
- while (__first1 != __last1 && __first2 != __last2)
- if (__comp(*__first1, *__first2))
- {
- *__result = *__first1;
- ++__first1;
- ++__result;
- }
- else if (__comp(*__first2, *__first1))
- {
- *__result = *__first2;
- ++__first2;
- ++__result;
- }
- else
- {
- ++__first1;
- ++__first2;
- }
- return std::copy(__first2, __last2,
- std::copy(__first1, __last1, __result));
+ return _GLIBCXX_STD_A::__set_symmetric_difference(__first1, __last1,
+ __first2, __last2, __result,
+ __gnu_cxx::__ops::__iter_comp_iter(__comp));
}
+ template<typename _ForwardIterator, typename _Compare>
+ _ForwardIterator
+ __min_element(_ForwardIterator __first, _ForwardIterator __last,
+ _Compare __comp)
+ {
+ if (__first == __last)
+ return __first;
+ _ForwardIterator __result = __first;
+ while (++__first != __last)
+ if (__comp(__first, __result))
+ __result = __first;
+ return __result;
+ }
/**
* @brief Return the minimum element in a range.
@@ -6343,7 +5416,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
*/
template<typename _ForwardIterator>
_ForwardIterator
- min_element(_ForwardIterator __first, _ForwardIterator __last)
+ inline min_element(_ForwardIterator __first, _ForwardIterator __last)
{
// concept requirements
__glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
@@ -6351,13 +5424,8 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
typename iterator_traits<_ForwardIterator>::value_type>)
__glibcxx_requires_valid_range(__first, __last);
- if (__first == __last)
- return __first;
- _ForwardIterator __result = __first;
- while (++__first != __last)
- if (*__first < *__result)
- __result = __first;
- return __result;
+ return _GLIBCXX_STD_A::__min_element(__first, __last,
+ __gnu_cxx::__ops::__iter_less_iter());
}
/**
@@ -6370,7 +5438,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
* according to __comp.
*/
template<typename _ForwardIterator, typename _Compare>
- _ForwardIterator
+ inline _ForwardIterator
min_element(_ForwardIterator __first, _ForwardIterator __last,
_Compare __comp)
{
@@ -6381,11 +5449,19 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
typename iterator_traits<_ForwardIterator>::value_type>)
__glibcxx_requires_valid_range(__first, __last);
- if (__first == __last)
- return __first;
+ return _GLIBCXX_STD_A::__min_element(__first, __last,
+ __gnu_cxx::__ops::__iter_comp_iter(__comp));
+ }
+
+ template<typename _ForwardIterator, typename _Compare>
+ _ForwardIterator
+ __max_element(_ForwardIterator __first, _ForwardIterator __last,
+ _Compare __comp)
+ {
+ if (__first == __last) return __first;
_ForwardIterator __result = __first;
while (++__first != __last)
- if (__comp(*__first, *__result))
+ if (__comp(__result, __first))
__result = __first;
return __result;
}
@@ -6398,7 +5474,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
* @return Iterator referencing the first instance of the largest value.
*/
template<typename _ForwardIterator>
- _ForwardIterator
+ inline _ForwardIterator
max_element(_ForwardIterator __first, _ForwardIterator __last)
{
// concept requirements
@@ -6407,13 +5483,8 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
typename iterator_traits<_ForwardIterator>::value_type>)
__glibcxx_requires_valid_range(__first, __last);
- if (__first == __last)
- return __first;
- _ForwardIterator __result = __first;
- while (++__first != __last)
- if (*__result < *__first)
- __result = __first;
- return __result;
+ return _GLIBCXX_STD_A::__max_element(__first, __last,
+ __gnu_cxx::__ops::__iter_less_iter());
}
/**
@@ -6426,7 +5497,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
* according to __comp.
*/
template<typename _ForwardIterator, typename _Compare>
- _ForwardIterator
+ inline _ForwardIterator
max_element(_ForwardIterator __first, _ForwardIterator __last,
_Compare __comp)
{
@@ -6437,12 +5508,8 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
typename iterator_traits<_ForwardIterator>::value_type>)
__glibcxx_requires_valid_range(__first, __last);
- if (__first == __last) return __first;
- _ForwardIterator __result = __first;
- while (++__first != __last)
- if (__comp(*__result, *__first))
- __result = __first;
- return __result;
+ return _GLIBCXX_STD_A::__max_element(__first, __last,
+ __gnu_cxx::__ops::__iter_comp_iter(__comp));
}
_GLIBCXX_END_NAMESPACE_ALGO
diff --git a/libstdc++-v3/include/bits/stl_algobase.h b/libstdc++-v3/include/bits/stl_algobase.h
index 1c889356460..5c7db5b8269 100644
--- a/libstdc++-v3/include/bits/stl_algobase.h
+++ b/libstdc++-v3/include/bits/stl_algobase.h
@@ -68,6 +68,7 @@
#include <bits/concept_check.h>
#include <debug/debug.h>
#include <bits/move.h> // For std::swap and _GLIBCXX_MOVE
+#include <bits/predefined_ops.h>
namespace std _GLIBCXX_VISIBILITY(default)
{
@@ -367,6 +368,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
static _Tp*
__copy_m(const _Tp* __first, const _Tp* __last, _Tp* __result)
{
+#if __cplusplus >= 201103L
+ // trivial types can have deleted assignment
+ static_assert( is_copy_assignable<_Tp>::value,
+ "type is not assignable" );
+#endif
const ptrdiff_t _Num = __last - __first;
if (_Num)
__builtin_memmove(__result, __first, sizeof(_Tp) * _Num);
@@ -562,6 +568,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
static _Tp*
__copy_move_b(const _Tp* __first, const _Tp* __last, _Tp* __result)
{
+#if __cplusplus >= 201103L
+ // trivial types can have deleted assignment
+ static_assert( is_copy_assignable<_Tp>::value,
+ "type is not assignable" );
+#endif
const ptrdiff_t _Num = __last - __first;
if (_Num)
__builtin_memmove(__result - _Num, __first, sizeof(_Tp) * _Num);
@@ -862,6 +873,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return true; }
};
+ template<typename _II1, typename _II2, typename _Compare>
+ bool
+ __lexicographical_compare_impl(_II1 __first1, _II1 __last1,
+ _II2 __first2, _II2 __last2,
+ _Compare __comp)
+ {
+ typedef typename iterator_traits<_II1>::iterator_category _Category1;
+ typedef typename iterator_traits<_II2>::iterator_category _Category2;
+ typedef std::__lc_rai<_Category1, _Category2> __rai_type;
+
+ __last1 = __rai_type::__newlast1(__first1, __last1, __first2, __last2);
+ for (; __first1 != __last1 && __rai_type::__cnd2(__first2, __last2);
+ ++__first1, ++__first2)
+ {
+ if (__comp(__first1, __first2))
+ return true;
+ if (__comp(__first2, __first1))
+ return false;
+ }
+ return __first1 == __last1 && __first2 != __last2;
+ }
+
template<bool _BoolType>
struct __lexicographical_compare
{
@@ -875,21 +908,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__lexicographical_compare<_BoolType>::
__lc(_II1 __first1, _II1 __last1, _II2 __first2, _II2 __last2)
{
- typedef typename iterator_traits<_II1>::iterator_category _Category1;
- typedef typename iterator_traits<_II2>::iterator_category _Category2;
- typedef std::__lc_rai<_Category1, _Category2> __rai_type;
-
- __last1 = __rai_type::__newlast1(__first1, __last1,
- __first2, __last2);
- for (; __first1 != __last1 && __rai_type::__cnd2(__first2, __last2);
- ++__first1, ++__first2)
- {
- if (*__first1 < *__first2)
- return true;
- if (*__first2 < *__first1)
- return false;
- }
- return __first1 == __last1 && __first2 != __last2;
+ return std::__lexicographical_compare_impl(__first1, __last1,
+ __first2, __last2,
+ __gnu_cxx::__ops::__iter_less_iter());
}
template<>
@@ -926,34 +947,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__first2, __last2);
}
- /**
- * @brief Finds the first position in which @a val could be inserted
- * without changing the ordering.
- * @param __first An iterator.
- * @param __last Another iterator.
- * @param __val The search term.
- * @return An iterator pointing to the first element <em>not less
- * than</em> @a val, or end() if every element is less than
- * @a val.
- * @ingroup binary_search_algorithms
- */
- template<typename _ForwardIterator, typename _Tp>
+ template<typename _ForwardIterator, typename _Tp, typename _Compare>
_ForwardIterator
- lower_bound(_ForwardIterator __first, _ForwardIterator __last,
- const _Tp& __val)
+ __lower_bound(_ForwardIterator __first, _ForwardIterator __last,
+ const _Tp& __val, _Compare __comp)
{
-#ifdef _GLIBCXX_CONCEPT_CHECKS
- typedef typename iterator_traits<_ForwardIterator>::value_type
- _ValueType;
-#endif
typedef typename iterator_traits<_ForwardIterator>::difference_type
_DistanceType;
- // concept requirements
- __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
- __glibcxx_function_requires(_LessThanOpConcept<_ValueType, _Tp>)
- __glibcxx_requires_partitioned_lower(__first, __last, __val);
-
_DistanceType __len = std::distance(__first, __last);
while (__len > 0)
@@ -961,7 +962,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_DistanceType __half = __len >> 1;
_ForwardIterator __middle = __first;
std::advance(__middle, __half);
- if (*__middle < __val)
+ if (__comp(__middle, __val))
{
__first = __middle;
++__first;
@@ -973,6 +974,32 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return __first;
}
+ /**
+ * @brief Finds the first position in which @a val could be inserted
+ * without changing the ordering.
+ * @param __first An iterator.
+ * @param __last Another iterator.
+ * @param __val The search term.
+ * @return An iterator pointing to the first element <em>not less
+ * than</em> @a val, or end() if every element is less than
+ * @a val.
+ * @ingroup binary_search_algorithms
+ */
+ template<typename _ForwardIterator, typename _Tp>
+ inline _ForwardIterator
+ lower_bound(_ForwardIterator __first, _ForwardIterator __last,
+ const _Tp& __val)
+ {
+ // concept requirements
+ __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
+ __glibcxx_function_requires(_LessThanOpConcept<
+ typename iterator_traits<_ForwardIterator>::value_type, _Tp>)
+ __glibcxx_requires_partitioned_lower(__first, __last, __val);
+
+ return std::__lower_bound(__first, __last, __val,
+ __gnu_cxx::__ops::__iter_less_val());
+ }
+
/// This is a helper function for the sort routines and for random.tcc.
// Precondition: __n > 0.
inline _GLIBCXX_CONSTEXPR int
@@ -1100,7 +1127,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
auto __d2 = std::distance(__first2, __last2);
if (__d1 != __d2)
return false;
- return std::equal(__first1, __last1, __first2);
+ return _GLIBCXX_STD_A::equal(__first1, __last1, __first2);
}
for (; __first1 != __last1 && __first2 != __last2; ++__first1, ++__first2)
@@ -1146,7 +1173,8 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
auto __d2 = std::distance(__first2, __last2);
if (__d1 != __d2)
return false;
- return std::equal(__first1, __last1, __first2, __binary_pred);
+ return _GLIBCXX_STD_A::equal(__first1, __last1, __first2,
+ __binary_pred);
}
for (; __first1 != __last1 && __first2 != __last2; ++__first1, ++__first2)
@@ -1208,30 +1236,33 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
* comp parameter instead of @c <.
*/
template<typename _II1, typename _II2, typename _Compare>
- bool
+ inline bool
lexicographical_compare(_II1 __first1, _II1 __last1,
_II2 __first2, _II2 __last2, _Compare __comp)
{
- typedef typename iterator_traits<_II1>::iterator_category _Category1;
- typedef typename iterator_traits<_II2>::iterator_category _Category2;
- typedef std::__lc_rai<_Category1, _Category2> __rai_type;
-
// concept requirements
__glibcxx_function_requires(_InputIteratorConcept<_II1>)
__glibcxx_function_requires(_InputIteratorConcept<_II2>)
__glibcxx_requires_valid_range(__first1, __last1);
__glibcxx_requires_valid_range(__first2, __last2);
- __last1 = __rai_type::__newlast1(__first1, __last1, __first2, __last2);
- for (; __first1 != __last1 && __rai_type::__cnd2(__first2, __last2);
- ++__first1, ++__first2)
- {
- if (__comp(*__first1, *__first2))
- return true;
- if (__comp(*__first2, *__first1))
- return false;
- }
- return __first1 == __last1 && __first2 != __last2;
+ return std::__lexicographical_compare_impl
+ (__first1, __last1, __first2, __last2,
+ __gnu_cxx::__ops::__iter_comp_iter(__comp));
+ }
+
+ template<typename _InputIterator1, typename _InputIterator2,
+ typename _BinaryPredicate>
+ pair<_InputIterator1, _InputIterator2>
+ __mismatch(_InputIterator1 __first1, _InputIterator1 __last1,
+ _InputIterator2 __first2, _BinaryPredicate __binary_pred)
+ {
+ while (__first1 != __last1 && __binary_pred(__first1, __first2))
+ {
+ ++__first1;
+ ++__first2;
+ }
+ return pair<_InputIterator1, _InputIterator2>(__first1, __first2);
}
/**
@@ -1248,7 +1279,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
* to by the iterators are not equal.
*/
template<typename _InputIterator1, typename _InputIterator2>
- pair<_InputIterator1, _InputIterator2>
+ inline pair<_InputIterator1, _InputIterator2>
mismatch(_InputIterator1 __first1, _InputIterator1 __last1,
_InputIterator2 __first2)
{
@@ -1260,12 +1291,8 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
typename iterator_traits<_InputIterator2>::value_type>)
__glibcxx_requires_valid_range(__first1, __last1);
- while (__first1 != __last1 && *__first1 == *__first2)
- {
- ++__first1;
- ++__first2;
- }
- return pair<_InputIterator1, _InputIterator2>(__first1, __first2);
+ return _GLIBCXX_STD_A::__mismatch(__first1, __last1, __first2,
+ __gnu_cxx::__ops::__iter_equal_to_iter());
}
/**
@@ -1286,7 +1313,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
*/
template<typename _InputIterator1, typename _InputIterator2,
typename _BinaryPredicate>
- pair<_InputIterator1, _InputIterator2>
+ inline pair<_InputIterator1, _InputIterator2>
mismatch(_InputIterator1 __first1, _InputIterator1 __last1,
_InputIterator2 __first2, _BinaryPredicate __binary_pred)
{
@@ -1295,7 +1322,21 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>)
__glibcxx_requires_valid_range(__first1, __last1);
- while (__first1 != __last1 && bool(__binary_pred(*__first1, *__first2)))
+ return _GLIBCXX_STD_A::__mismatch(__first1, __last1, __first2,
+ __gnu_cxx::__ops::__iter_comp_iter(__binary_pred));
+ }
+
+#if __cplusplus > 201103L
+
+ template<typename _InputIterator1, typename _InputIterator2,
+ typename _BinaryPredicate>
+ pair<_InputIterator1, _InputIterator2>
+ __mismatch(_InputIterator1 __first1, _InputIterator1 __last1,
+ _InputIterator2 __first2, _InputIterator2 __last2,
+ _BinaryPredicate __binary_pred)
+ {
+ while (__first1 != __last1 && __first2 != __last2
+ && __binary_pred(__first1, __first2))
{
++__first1;
++__first2;
@@ -1303,7 +1344,6 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
return pair<_InputIterator1, _InputIterator2>(__first1, __first2);
}
-#if __cplusplus > 201103L
/**
* @brief Finds the places in ranges which don't match.
* @ingroup non_mutating_algorithms
@@ -1319,7 +1359,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
* to by the iterators are not equal.
*/
template<typename _InputIterator1, typename _InputIterator2>
- pair<_InputIterator1, _InputIterator2>
+ inline pair<_InputIterator1, _InputIterator2>
mismatch(_InputIterator1 __first1, _InputIterator1 __last1,
_InputIterator2 __first2, _InputIterator2 __last2)
{
@@ -1332,13 +1372,8 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
__glibcxx_requires_valid_range(__first1, __last1);
__glibcxx_requires_valid_range(__first2, __last2);
- while (__first1 != __last1 && __first2 != __last2
- && *__first1 == *__first2)
- {
- ++__first1;
- ++__first2;
- }
- return pair<_InputIterator1, _InputIterator2>(__first1, __first2);
+ return _GLIBCXX_STD_A::__mismatch(__first1, __last1, __first2, __last2,
+ __gnu_cxx::__ops::__iter_equal_to_iter());
}
/**
@@ -1360,7 +1395,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
*/
template<typename _InputIterator1, typename _InputIterator2,
typename _BinaryPredicate>
- pair<_InputIterator1, _InputIterator2>
+ inline pair<_InputIterator1, _InputIterator2>
mismatch(_InputIterator1 __first1, _InputIterator1 __last1,
_InputIterator2 __first2, _InputIterator2 __last2,
_BinaryPredicate __binary_pred)
@@ -1371,13 +1406,8 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
__glibcxx_requires_valid_range(__first1, __last1);
__glibcxx_requires_valid_range(__first2, __last2);
- while (__first1 != __last1 && __first2 != __last2
- && bool(__binary_pred(*__first1, *__first2)))
- {
- ++__first1;
- ++__first2;
- }
- return pair<_InputIterator1, _InputIterator2>(__first1, __first2);
+ return _GLIBCXX_STD_A::__mismatch(__first1, __last1, __first2, __last2,
+ __gnu_cxx::__ops::__iter_comp_iter(__binary_pred));
}
#endif
diff --git a/libstdc++-v3/include/bits/stl_bvector.h b/libstdc++-v3/include/bits/stl_bvector.h
index 468fad0dbd0..8e4b0230614 100644
--- a/libstdc++-v3/include/bits/stl_bvector.h
+++ b/libstdc++-v3/include/bits/stl_bvector.h
@@ -785,7 +785,10 @@ template<typename _Alloc>
_M_range_check(size_type __n) const
{
if (__n >= this->size())
- __throw_out_of_range(__N("vector<bool>::_M_range_check"));
+ __throw_out_of_range_fmt(__N("vector<bool>::_M_range_check: __n "
+ "(which is %zu) >= this->size() "
+ "(which is %zu)"),
+ __n, this->size());
}
public:
diff --git a/libstdc++-v3/include/bits/stl_deque.h b/libstdc++-v3/include/bits/stl_deque.h
index a4656734469..ca9e4179b06 100644
--- a/libstdc++-v3/include/bits/stl_deque.h
+++ b/libstdc++-v3/include/bits/stl_deque.h
@@ -108,7 +108,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
typedef _Deque_iterator<_Tp, _Tp&, _Tp*> iterator;
typedef _Deque_iterator<_Tp, const _Tp&, const _Tp*> const_iterator;
- static size_t _S_buffer_size()
+ static size_t _S_buffer_size() _GLIBCXX_NOEXCEPT
{ return __deque_buf_size(sizeof(_Tp)); }
typedef std::random_access_iterator_tag iterator_category;
@@ -125,31 +125,31 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_Tp* _M_last;
_Map_pointer _M_node;
- _Deque_iterator(_Tp* __x, _Map_pointer __y)
+ _Deque_iterator(_Tp* __x, _Map_pointer __y) _GLIBCXX_NOEXCEPT
: _M_cur(__x), _M_first(*__y),
_M_last(*__y + _S_buffer_size()), _M_node(__y) { }
- _Deque_iterator()
+ _Deque_iterator() _GLIBCXX_NOEXCEPT
: _M_cur(0), _M_first(0), _M_last(0), _M_node(0) { }
- _Deque_iterator(const iterator& __x)
+ _Deque_iterator(const iterator& __x) _GLIBCXX_NOEXCEPT
: _M_cur(__x._M_cur), _M_first(__x._M_first),
_M_last(__x._M_last), _M_node(__x._M_node) { }
iterator
- _M_const_cast() const
+ _M_const_cast() const _GLIBCXX_NOEXCEPT
{ return iterator(_M_cur, _M_node); }
reference
- operator*() const
+ operator*() const _GLIBCXX_NOEXCEPT
{ return *_M_cur; }
pointer
- operator->() const
+ operator->() const _GLIBCXX_NOEXCEPT
{ return _M_cur; }
_Self&
- operator++()
+ operator++() _GLIBCXX_NOEXCEPT
{
++_M_cur;
if (_M_cur == _M_last)
@@ -161,7 +161,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
_Self
- operator++(int)
+ operator++(int) _GLIBCXX_NOEXCEPT
{
_Self __tmp = *this;
++*this;
@@ -169,7 +169,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
_Self&
- operator--()
+ operator--() _GLIBCXX_NOEXCEPT
{
if (_M_cur == _M_first)
{
@@ -181,7 +181,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
_Self
- operator--(int)
+ operator--(int) _GLIBCXX_NOEXCEPT
{
_Self __tmp = *this;
--*this;
@@ -189,7 +189,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
_Self&
- operator+=(difference_type __n)
+ operator+=(difference_type __n) _GLIBCXX_NOEXCEPT
{
const difference_type __offset = __n + (_M_cur - _M_first);
if (__offset >= 0 && __offset < difference_type(_S_buffer_size()))
@@ -208,25 +208,25 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
_Self
- operator+(difference_type __n) const
+ operator+(difference_type __n) const _GLIBCXX_NOEXCEPT
{
_Self __tmp = *this;
return __tmp += __n;
}
_Self&
- operator-=(difference_type __n)
+ operator-=(difference_type __n) _GLIBCXX_NOEXCEPT
{ return *this += -__n; }
_Self
- operator-(difference_type __n) const
+ operator-(difference_type __n) const _GLIBCXX_NOEXCEPT
{
_Self __tmp = *this;
return __tmp -= __n;
}
reference
- operator[](difference_type __n) const
+ operator[](difference_type __n) const _GLIBCXX_NOEXCEPT
{ return *(*this + __n); }
/**
@@ -235,7 +235,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* immediately afterwards, based on _M_first and _M_last.
*/
void
- _M_set_node(_Map_pointer __new_node)
+ _M_set_node(_Map_pointer __new_node) _GLIBCXX_NOEXCEPT
{
_M_node = __new_node;
_M_first = *__new_node;
@@ -249,33 +249,33 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
template<typename _Tp, typename _Ref, typename _Ptr>
inline bool
operator==(const _Deque_iterator<_Tp, _Ref, _Ptr>& __x,
- const _Deque_iterator<_Tp, _Ref, _Ptr>& __y)
+ const _Deque_iterator<_Tp, _Ref, _Ptr>& __y) _GLIBCXX_NOEXCEPT
{ return __x._M_cur == __y._M_cur; }
template<typename _Tp, typename _RefL, typename _PtrL,
typename _RefR, typename _PtrR>
inline bool
operator==(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x,
- const _Deque_iterator<_Tp, _RefR, _PtrR>& __y)
+ const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) _GLIBCXX_NOEXCEPT
{ return __x._M_cur == __y._M_cur; }
template<typename _Tp, typename _Ref, typename _Ptr>
inline bool
operator!=(const _Deque_iterator<_Tp, _Ref, _Ptr>& __x,
- const _Deque_iterator<_Tp, _Ref, _Ptr>& __y)
+ const _Deque_iterator<_Tp, _Ref, _Ptr>& __y) _GLIBCXX_NOEXCEPT
{ return !(__x == __y); }
template<typename _Tp, typename _RefL, typename _PtrL,
typename _RefR, typename _PtrR>
inline bool
operator!=(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x,
- const _Deque_iterator<_Tp, _RefR, _PtrR>& __y)
+ const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) _GLIBCXX_NOEXCEPT
{ return !(__x == __y); }
template<typename _Tp, typename _Ref, typename _Ptr>
inline bool
operator<(const _Deque_iterator<_Tp, _Ref, _Ptr>& __x,
- const _Deque_iterator<_Tp, _Ref, _Ptr>& __y)
+ const _Deque_iterator<_Tp, _Ref, _Ptr>& __y) _GLIBCXX_NOEXCEPT
{ return (__x._M_node == __y._M_node) ? (__x._M_cur < __y._M_cur)
: (__x._M_node < __y._M_node); }
@@ -283,47 +283,47 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
typename _RefR, typename _PtrR>
inline bool
operator<(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x,
- const _Deque_iterator<_Tp, _RefR, _PtrR>& __y)
+ const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) _GLIBCXX_NOEXCEPT
{ return (__x._M_node == __y._M_node) ? (__x._M_cur < __y._M_cur)
: (__x._M_node < __y._M_node); }
template<typename _Tp, typename _Ref, typename _Ptr>
inline bool
operator>(const _Deque_iterator<_Tp, _Ref, _Ptr>& __x,
- const _Deque_iterator<_Tp, _Ref, _Ptr>& __y)
+ const _Deque_iterator<_Tp, _Ref, _Ptr>& __y) _GLIBCXX_NOEXCEPT
{ return __y < __x; }
template<typename _Tp, typename _RefL, typename _PtrL,
typename _RefR, typename _PtrR>
inline bool
operator>(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x,
- const _Deque_iterator<_Tp, _RefR, _PtrR>& __y)
+ const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) _GLIBCXX_NOEXCEPT
{ return __y < __x; }
template<typename _Tp, typename _Ref, typename _Ptr>
inline bool
operator<=(const _Deque_iterator<_Tp, _Ref, _Ptr>& __x,
- const _Deque_iterator<_Tp, _Ref, _Ptr>& __y)
+ const _Deque_iterator<_Tp, _Ref, _Ptr>& __y) _GLIBCXX_NOEXCEPT
{ return !(__y < __x); }
template<typename _Tp, typename _RefL, typename _PtrL,
typename _RefR, typename _PtrR>
inline bool
operator<=(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x,
- const _Deque_iterator<_Tp, _RefR, _PtrR>& __y)
+ const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) _GLIBCXX_NOEXCEPT
{ return !(__y < __x); }
template<typename _Tp, typename _Ref, typename _Ptr>
inline bool
operator>=(const _Deque_iterator<_Tp, _Ref, _Ptr>& __x,
- const _Deque_iterator<_Tp, _Ref, _Ptr>& __y)
+ const _Deque_iterator<_Tp, _Ref, _Ptr>& __y) _GLIBCXX_NOEXCEPT
{ return !(__x < __y); }
template<typename _Tp, typename _RefL, typename _PtrL,
typename _RefR, typename _PtrR>
inline bool
operator>=(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x,
- const _Deque_iterator<_Tp, _RefR, _PtrR>& __y)
+ const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) _GLIBCXX_NOEXCEPT
{ return !(__x < __y); }
// _GLIBCXX_RESOLVE_LIB_DEFECTS
@@ -333,7 +333,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
template<typename _Tp, typename _Ref, typename _Ptr>
inline typename _Deque_iterator<_Tp, _Ref, _Ptr>::difference_type
operator-(const _Deque_iterator<_Tp, _Ref, _Ptr>& __x,
- const _Deque_iterator<_Tp, _Ref, _Ptr>& __y)
+ const _Deque_iterator<_Tp, _Ref, _Ptr>& __y) _GLIBCXX_NOEXCEPT
{
return typename _Deque_iterator<_Tp, _Ref, _Ptr>::difference_type
(_Deque_iterator<_Tp, _Ref, _Ptr>::_S_buffer_size())
@@ -345,7 +345,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
typename _RefR, typename _PtrR>
inline typename _Deque_iterator<_Tp, _RefL, _PtrL>::difference_type
operator-(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x,
- const _Deque_iterator<_Tp, _RefR, _PtrR>& __y)
+ const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) _GLIBCXX_NOEXCEPT
{
return typename _Deque_iterator<_Tp, _RefL, _PtrL>::difference_type
(_Deque_iterator<_Tp, _RefL, _PtrL>::_S_buffer_size())
@@ -356,6 +356,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
template<typename _Tp, typename _Ref, typename _Ptr>
inline _Deque_iterator<_Tp, _Ref, _Ptr>
operator+(ptrdiff_t __n, const _Deque_iterator<_Tp, _Ref, _Ptr>& __x)
+ _GLIBCXX_NOEXCEPT
{ return __x + __n; }
template<typename _Tp>
@@ -466,7 +467,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_Deque_base(const allocator_type& __a)
: _M_impl(__a)
- { }
+ { _M_initialize_map(0); }
#if __cplusplus >= 201103L
_Deque_base(_Deque_base&& __x)
@@ -483,7 +484,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
#endif
- ~_Deque_base();
+ ~_Deque_base() _GLIBCXX_NOEXCEPT;
protected:
//This struct encapsulates the implementation of the std::deque
@@ -506,13 +507,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_M_start(), _M_finish()
{ }
- _Deque_impl(const _Tp_alloc_type& __a)
+ _Deque_impl(const _Tp_alloc_type& __a) _GLIBCXX_NOEXCEPT
: _Tp_alloc_type(__a), _M_map(0), _M_map_size(0),
_M_start(), _M_finish()
{ }
#if __cplusplus >= 201103L
- _Deque_impl(_Tp_alloc_type&& __a)
+ _Deque_impl(_Tp_alloc_type&& __a) _GLIBCXX_NOEXCEPT
: _Tp_alloc_type(std::move(__a)), _M_map(0), _M_map_size(0),
_M_start(), _M_finish()
{ }
@@ -538,7 +539,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
void
- _M_deallocate_node(_Tp* __p)
+ _M_deallocate_node(_Tp* __p) _GLIBCXX_NOEXCEPT
{
_M_impl._Tp_alloc_type::deallocate(__p, __deque_buf_size(sizeof(_Tp)));
}
@@ -548,13 +549,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
{ return _M_get_map_allocator().allocate(__n); }
void
- _M_deallocate_map(_Tp** __p, size_t __n)
+ _M_deallocate_map(_Tp** __p, size_t __n) _GLIBCXX_NOEXCEPT
{ _M_get_map_allocator().deallocate(__p, __n); }
protected:
void _M_initialize_map(size_t);
void _M_create_nodes(_Tp** __nstart, _Tp** __nfinish);
- void _M_destroy_nodes(_Tp** __nstart, _Tp** __nfinish);
+ void _M_destroy_nodes(_Tp** __nstart, _Tp** __nfinish) _GLIBCXX_NOEXCEPT;
enum { _S_initial_map_size = 8 };
_Deque_impl _M_impl;
@@ -562,7 +563,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
template<typename _Tp, typename _Alloc>
_Deque_base<_Tp, _Alloc>::
- ~_Deque_base()
+ ~_Deque_base() _GLIBCXX_NOEXCEPT
{
if (this->_M_impl._M_map)
{
@@ -640,7 +641,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
template<typename _Tp, typename _Alloc>
void
_Deque_base<_Tp, _Alloc>::
- _M_destroy_nodes(_Tp** __nstart, _Tp** __nfinish)
+ _M_destroy_nodes(_Tp** __nstart, _Tp** __nfinish) _GLIBCXX_NOEXCEPT
{
for (_Tp** __n = __nstart; __n < __nfinish; ++__n)
_M_deallocate_node(*__n);
@@ -758,7 +759,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
protected:
typedef pointer* _Map_pointer;
- static size_t _S_buffer_size()
+ static size_t _S_buffer_size() _GLIBCXX_NOEXCEPT
{ return __deque_buf_size(sizeof(_Tp)); }
// Functions controlling memory layout, and nothing else.
@@ -781,18 +782,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
// [23.2.1.1] construct/copy/destroy
// (assign() and get_allocator() are also listed in this section)
/**
- * @brief Default constructor creates no elements.
- */
- deque()
- : _Base() { }
-
- /**
* @brief Creates a %deque with no elements.
* @param __a An allocator object.
*/
explicit
- deque(const allocator_type& __a)
- : _Base(__a, 0) { }
+ deque(const allocator_type& __a = allocator_type())
+ : _Base(__a) { }
#if __cplusplus >= 201103L
/**
@@ -940,7 +935,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* @a __x is a valid, but unspecified %deque.
*/
deque&
- operator=(deque&& __x)
+ operator=(deque&& __x) noexcept
{
// NB: DR 1204.
// NB: DR 675.
@@ -1220,7 +1215,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
#if __cplusplus >= 201103L
/** A non-binding request to reduce memory use. */
void
- shrink_to_fit()
+ shrink_to_fit() noexcept
{ _M_shrink_to_fit(); }
#endif
@@ -1245,7 +1240,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* see at().)
*/
reference
- operator[](size_type __n)
+ operator[](size_type __n) _GLIBCXX_NOEXCEPT
{ return this->_M_impl._M_start[difference_type(__n)]; }
/**
@@ -1260,7 +1255,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* see at().)
*/
const_reference
- operator[](size_type __n) const
+ operator[](size_type __n) const _GLIBCXX_NOEXCEPT
{ return this->_M_impl._M_start[difference_type(__n)]; }
protected:
@@ -1269,7 +1264,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_M_range_check(size_type __n) const
{
if (__n >= this->size())
- __throw_out_of_range(__N("deque::_M_range_check"));
+ __throw_out_of_range_fmt(__N("deque::_M_range_check: __n "
+ "(which is %zu)>= this->size() "
+ "(which is %zu)"),
+ __n, this->size());
}
public:
@@ -1314,7 +1312,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* element of the %deque.
*/
reference
- front()
+ front() _GLIBCXX_NOEXCEPT
{ return *begin(); }
/**
@@ -1322,7 +1320,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* element of the %deque.
*/
const_reference
- front() const
+ front() const _GLIBCXX_NOEXCEPT
{ return *begin(); }
/**
@@ -1330,7 +1328,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* %deque.
*/
reference
- back()
+ back() _GLIBCXX_NOEXCEPT
{
iterator __tmp = end();
--__tmp;
@@ -1342,7 +1340,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* element of the %deque.
*/
const_reference
- back() const
+ back() const _GLIBCXX_NOEXCEPT
{
const_iterator __tmp = end();
--__tmp;
@@ -1422,7 +1420,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* needed, it should be retrieved before pop_front() is called.
*/
void
- pop_front()
+ pop_front() _GLIBCXX_NOEXCEPT
{
if (this->_M_impl._M_start._M_cur
!= this->_M_impl._M_start._M_last - 1)
@@ -1443,7 +1441,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* needed, it should be retrieved before pop_back() is called.
*/
void
- pop_back()
+ pop_back() _GLIBCXX_NOEXCEPT
{
if (this->_M_impl._M_finish._M_cur
!= this->_M_impl._M_finish._M_first)
@@ -1655,7 +1653,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* std::swap(d1,d2) will feed to this function.
*/
void
- swap(deque& __x)
+ swap(deque& __x) _GLIBCXX_NOEXCEPT
{
std::swap(this->_M_impl._M_start, __x._M_impl._M_start);
std::swap(this->_M_impl._M_finish, __x._M_impl._M_finish);
diff --git a/libstdc++-v3/include/bits/stl_function.h b/libstdc++-v3/include/bits/stl_function.h
index 23529dff30c..e5eed0698ab 100644
--- a/libstdc++-v3/include/bits/stl_function.h
+++ b/libstdc++-v3/include/bits/stl_function.h
@@ -56,6 +56,10 @@
#ifndef _STL_FUNCTION_H
#define _STL_FUNCTION_H 1
+#if __cplusplus > 201103L
+#include <bits/move.h>
+#endif
+
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
@@ -135,6 +139,29 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*
* @{
*/
+
+#if __cplusplus > 201103L
+ struct __is_transparent; // undefined
+
+ template<typename _Tp = void>
+ struct plus;
+
+ template<typename _Tp = void>
+ struct minus;
+
+ template<typename _Tp = void>
+ struct multiplies;
+
+ template<typename _Tp = void>
+ struct divides;
+
+ template<typename _Tp = void>
+ struct modulus;
+
+ template<typename _Tp = void>
+ struct negate;
+#endif
+
/// One of the @link arithmetic_functors math functors@endlink.
template<typename _Tp>
struct plus : public binary_function<_Tp, _Tp, _Tp>
@@ -188,6 +215,91 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
operator()(const _Tp& __x) const
{ return -__x; }
};
+
+#if __cplusplus > 201103L
+ template<>
+ struct plus<void>
+ {
+ template <typename _Tp, typename _Up>
+ auto
+ operator()(_Tp&& __t, _Up&& __u) const
+ noexcept(noexcept(std::forward<_Tp>(__t) + std::forward<_Up>(__u)))
+ -> decltype(std::forward<_Tp>(__t) + std::forward<_Up>(__u))
+ { return std::forward<_Tp>(__t) + std::forward<_Up>(__u); }
+
+ typedef __is_transparent is_transparent;
+ };
+
+ /// One of the @link arithmetic_functors math functors@endlink.
+ template<>
+ struct minus<void>
+ {
+ template <typename _Tp, typename _Up>
+ auto
+ operator()(_Tp&& __t, _Up&& __u) const
+ noexcept(noexcept(std::forward<_Tp>(__t) - std::forward<_Up>(__u)))
+ -> decltype(std::forward<_Tp>(__t) - std::forward<_Up>(__u))
+ { return std::forward<_Tp>(__t) - std::forward<_Up>(__u); }
+
+ typedef __is_transparent is_transparent;
+ };
+
+ /// One of the @link arithmetic_functors math functors@endlink.
+ template<>
+ struct multiplies<void>
+ {
+ template <typename _Tp, typename _Up>
+ auto
+ operator()(_Tp&& __t, _Up&& __u) const
+ noexcept(noexcept(std::forward<_Tp>(__t) * std::forward<_Up>(__u)))
+ -> decltype(std::forward<_Tp>(__t) * std::forward<_Up>(__u))
+ { return std::forward<_Tp>(__t) * std::forward<_Up>(__u); }
+
+ typedef __is_transparent is_transparent;
+ };
+
+ /// One of the @link arithmetic_functors math functors@endlink.
+ template<>
+ struct divides<void>
+ {
+ template <typename _Tp, typename _Up>
+ auto
+ operator()(_Tp&& __t, _Up&& __u) const
+ noexcept(noexcept(std::forward<_Tp>(__t) / std::forward<_Up>(__u)))
+ -> decltype(std::forward<_Tp>(__t) / std::forward<_Up>(__u))
+ { return std::forward<_Tp>(__t) / std::forward<_Up>(__u); }
+
+ typedef __is_transparent is_transparent;
+ };
+
+ /// One of the @link arithmetic_functors math functors@endlink.
+ template<>
+ struct modulus<void>
+ {
+ template <typename _Tp, typename _Up>
+ auto
+ operator()(_Tp&& __t, _Up&& __u) const
+ noexcept(noexcept(std::forward<_Tp>(__t) % std::forward<_Up>(__u)))
+ -> decltype(std::forward<_Tp>(__t) % std::forward<_Up>(__u))
+ { return std::forward<_Tp>(__t) % std::forward<_Up>(__u); }
+
+ typedef __is_transparent is_transparent;
+ };
+
+ /// One of the @link arithmetic_functors math functors@endlink.
+ template<>
+ struct negate<void>
+ {
+ template <typename _Tp>
+ auto
+ operator()(_Tp&& __t) const
+ noexcept(noexcept(-std::forward<_Tp>(__t)))
+ -> decltype(-std::forward<_Tp>(__t))
+ { return -std::forward<_Tp>(__t); }
+
+ typedef __is_transparent is_transparent;
+ };
+#endif
/** @} */
// 20.3.3 comparisons
@@ -199,6 +311,26 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*
* @{
*/
+#if __cplusplus > 201103L
+ template<typename _Tp = void>
+ struct equal_to;
+
+ template<typename _Tp = void>
+ struct not_equal_to;
+
+ template<typename _Tp = void>
+ struct greater;
+
+ template<typename _Tp = void>
+ struct less;
+
+ template<typename _Tp = void>
+ struct greater_equal;
+
+ template<typename _Tp = void>
+ struct less_equal;
+#endif
+
/// One of the @link comparison_functors comparison functors@endlink.
template<typename _Tp>
struct equal_to : public binary_function<_Tp, _Tp, bool>
@@ -252,6 +384,92 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
operator()(const _Tp& __x, const _Tp& __y) const
{ return __x <= __y; }
};
+
+#if __cplusplus > 201103L
+ /// One of the @link comparison_functors comparison functors@endlink.
+ template<>
+ struct equal_to<void>
+ {
+ template <typename _Tp, typename _Up>
+ auto
+ operator()(_Tp&& __t, _Up&& __u) const
+ noexcept(noexcept(std::forward<_Tp>(__t) == std::forward<_Up>(__u)))
+ -> decltype(std::forward<_Tp>(__t) == std::forward<_Up>(__u))
+ { return std::forward<_Tp>(__t) == std::forward<_Up>(__u); }
+
+ typedef __is_transparent is_transparent;
+ };
+
+ /// One of the @link comparison_functors comparison functors@endlink.
+ template<>
+ struct not_equal_to<void>
+ {
+ template <typename _Tp, typename _Up>
+ auto
+ operator()(_Tp&& __t, _Up&& __u) const
+ noexcept(noexcept(std::forward<_Tp>(__t) != std::forward<_Up>(__u)))
+ -> decltype(std::forward<_Tp>(__t) != std::forward<_Up>(__u))
+ { return std::forward<_Tp>(__t) != std::forward<_Up>(__u); }
+
+ typedef __is_transparent is_transparent;
+ };
+
+ /// One of the @link comparison_functors comparison functors@endlink.
+ template<>
+ struct greater<void>
+ {
+ template <typename _Tp, typename _Up>
+ auto
+ operator()(_Tp&& __t, _Up&& __u) const
+ noexcept(noexcept(std::forward<_Tp>(__t) > std::forward<_Up>(__u)))
+ -> decltype(std::forward<_Tp>(__t) > std::forward<_Up>(__u))
+ { return std::forward<_Tp>(__t) > std::forward<_Up>(__u); }
+
+ typedef __is_transparent is_transparent;
+ };
+
+ /// One of the @link comparison_functors comparison functors@endlink.
+ template<>
+ struct less<void>
+ {
+ template <typename _Tp, typename _Up>
+ auto
+ operator()(_Tp&& __t, _Up&& __u) const
+ noexcept(noexcept(std::forward<_Tp>(__t) < std::forward<_Up>(__u)))
+ -> decltype(std::forward<_Tp>(__t) < std::forward<_Up>(__u))
+ { return std::forward<_Tp>(__t) < std::forward<_Up>(__u); }
+
+ typedef __is_transparent is_transparent;
+ };
+
+ /// One of the @link comparison_functors comparison functors@endlink.
+ template<>
+ struct greater_equal<void>
+ {
+ template <typename _Tp, typename _Up>
+ auto
+ operator()(_Tp&& __t, _Up&& __u) const
+ noexcept(noexcept(std::forward<_Tp>(__t) >= std::forward<_Up>(__u)))
+ -> decltype(std::forward<_Tp>(__t) >= std::forward<_Up>(__u))
+ { return std::forward<_Tp>(__t) >= std::forward<_Up>(__u); }
+
+ typedef __is_transparent is_transparent;
+ };
+
+ /// One of the @link comparison_functors comparison functors@endlink.
+ template<>
+ struct less_equal<void>
+ {
+ template <typename _Tp, typename _Up>
+ auto
+ operator()(_Tp&& __t, _Up&& __u) const
+ noexcept(noexcept(std::forward<_Tp>(__t) <= std::forward<_Up>(__u)))
+ -> decltype(std::forward<_Tp>(__t) <= std::forward<_Up>(__u))
+ { return std::forward<_Tp>(__t) <= std::forward<_Up>(__u); }
+
+ typedef __is_transparent is_transparent;
+ };
+#endif
/** @} */
// 20.3.4 logical operations
@@ -263,6 +481,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*
* @{
*/
+#if __cplusplus > 201103L
+ template<typename _Tp = void>
+ struct logical_and;
+
+ template<typename _Tp = void>
+ struct logical_or;
+
+ template<typename _Tp = void>
+ struct logical_not;
+#endif
+
/// One of the @link logical_functors Boolean operations functors@endlink.
template<typename _Tp>
struct logical_and : public binary_function<_Tp, _Tp, bool>
@@ -289,8 +518,66 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
operator()(const _Tp& __x) const
{ return !__x; }
};
+
+#if __cplusplus > 201103L
+ /// One of the @link logical_functors Boolean operations functors@endlink.
+ template<>
+ struct logical_and<void>
+ {
+ template <typename _Tp, typename _Up>
+ auto
+ operator()(_Tp&& __t, _Up&& __u) const
+ noexcept(noexcept(std::forward<_Tp>(__t) && std::forward<_Up>(__u)))
+ -> decltype(std::forward<_Tp>(__t) && std::forward<_Up>(__u))
+ { return std::forward<_Tp>(__t) && std::forward<_Up>(__u); }
+
+ typedef __is_transparent is_transparent;
+ };
+
+ /// One of the @link logical_functors Boolean operations functors@endlink.
+ template<>
+ struct logical_or<void>
+ {
+ template <typename _Tp, typename _Up>
+ auto
+ operator()(_Tp&& __t, _Up&& __u) const
+ noexcept(noexcept(std::forward<_Tp>(__t) || std::forward<_Up>(__u)))
+ -> decltype(std::forward<_Tp>(__t) || std::forward<_Up>(__u))
+ { return std::forward<_Tp>(__t) || std::forward<_Up>(__u); }
+
+ typedef __is_transparent is_transparent;
+ };
+
+ /// One of the @link logical_functors Boolean operations functors@endlink.
+ template<>
+ struct logical_not<void>
+ {
+ template <typename _Tp>
+ auto
+ operator()(_Tp&& __t) const
+ noexcept(noexcept(!std::forward<_Tp>(__t)))
+ -> decltype(!std::forward<_Tp>(__t))
+ { return !std::forward<_Tp>(__t); }
+
+ typedef __is_transparent is_transparent;
+ };
+#endif
/** @} */
+#if __cplusplus > 201103L
+ template<typename _Tp = void>
+ struct bit_and;
+
+ template<typename _Tp = void>
+ struct bit_or;
+
+ template<typename _Tp = void>
+ struct bit_xor;
+
+ template<typename _Tp = void>
+ struct bit_not;
+#endif
+
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// DR 660. Missing Bitwise Operations.
template<typename _Tp>
@@ -317,6 +604,68 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return __x ^ __y; }
};
+ template<typename _Tp>
+ struct bit_not : public unary_function<_Tp, _Tp>
+ {
+ _Tp
+ operator()(const _Tp& __x) const
+ { return ~__x; }
+ };
+
+#if __cplusplus > 201103L
+ template <>
+ struct bit_and<void>
+ {
+ template <typename _Tp, typename _Up>
+ auto
+ operator()(_Tp&& __t, _Up&& __u) const
+ noexcept(noexcept(std::forward<_Tp>(__t) & std::forward<_Up>(__u)))
+ -> decltype(std::forward<_Tp>(__t) & std::forward<_Up>(__u))
+ { return std::forward<_Tp>(__t) & std::forward<_Up>(__u); }
+
+ typedef __is_transparent is_transparent;
+ };
+
+ template <>
+ struct bit_or<void>
+ {
+ template <typename _Tp, typename _Up>
+ auto
+ operator()(_Tp&& __t, _Up&& __u) const
+ noexcept(noexcept(std::forward<_Tp>(__t) | std::forward<_Up>(__u)))
+ -> decltype(std::forward<_Tp>(__t) | std::forward<_Up>(__u))
+ { return std::forward<_Tp>(__t) | std::forward<_Up>(__u); }
+
+ typedef __is_transparent is_transparent;
+ };
+
+ template <>
+ struct bit_xor<void>
+ {
+ template <typename _Tp, typename _Up>
+ auto
+ operator()(_Tp&& __t, _Up&& __u) const
+ noexcept(noexcept(std::forward<_Tp>(__t) ^ std::forward<_Up>(__u)))
+ -> decltype(std::forward<_Tp>(__t) ^ std::forward<_Up>(__u))
+ { return std::forward<_Tp>(__t) ^ std::forward<_Up>(__u); }
+
+ typedef __is_transparent is_transparent;
+ };
+
+ template <>
+ struct bit_not<void>
+ {
+ template <typename _Tp>
+ auto
+ operator()(_Tp&& __t) const
+ noexcept(noexcept(~std::forward<_Tp>(__t)))
+ -> decltype(~std::forward<_Tp>(__t))
+ { return ~std::forward<_Tp>(__t); }
+
+ typedef __is_transparent is_transparent;
+ };
+#endif
+
// 20.3.5 negators
/** @defgroup negators Negators
* @ingroup functors
diff --git a/libstdc++-v3/include/bits/stl_heap.h b/libstdc++-v3/include/bits/stl_heap.h
index 807a8cf0525..a0c51ff7a1f 100644
--- a/libstdc++-v3/include/bits/stl_heap.h
+++ b/libstdc++-v3/include/bits/stl_heap.h
@@ -57,6 +57,7 @@
#include <debug/debug.h>
#include <bits/move.h>
+#include <bits/predefined_ops.h>
namespace std _GLIBCXX_VISIBILITY(default)
{
@@ -67,21 +68,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* @ingroup sorting_algorithms
*/
- template<typename _RandomAccessIterator, typename _Distance>
- _Distance
- __is_heap_until(_RandomAccessIterator __first, _Distance __n)
- {
- _Distance __parent = 0;
- for (_Distance __child = 1; __child < __n; ++__child)
- {
- if (__first[__parent] < __first[__child])
- return __child;
- if ((__child & 1) == 0)
- ++__parent;
- }
- return __n;
- }
-
template<typename _RandomAccessIterator, typename _Distance,
typename _Compare>
_Distance
@@ -91,7 +77,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_Distance __parent = 0;
for (_Distance __child = 1; __child < __n; ++__child)
{
- if (__comp(__first[__parent], __first[__child]))
+ if (__comp(__first + __parent, __first + __child))
return __child;
if ((__child & 1) == 0)
++__parent;
@@ -104,13 +90,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _RandomAccessIterator, typename _Distance>
inline bool
__is_heap(_RandomAccessIterator __first, _Distance __n)
- { return std::__is_heap_until(__first, __n) == __n; }
+ {
+ return std::__is_heap_until(__first, __n,
+ __gnu_cxx::__ops::__iter_less_iter()) == __n;
+ }
template<typename _RandomAccessIterator, typename _Compare,
typename _Distance>
inline bool
__is_heap(_RandomAccessIterator __first, _Compare __comp, _Distance __n)
- { return std::__is_heap_until(__first, __n, __comp) == __n; }
+ {
+ return std::__is_heap_until(__first, __n,
+ __gnu_cxx::__ops::__iter_comp_iter(__comp)) == __n;
+ }
template<typename _RandomAccessIterator>
inline bool
@@ -126,13 +118,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Heap-manipulation functions: push_heap, pop_heap, make_heap, sort_heap,
// + is_heap and is_heap_until in C++0x.
- template<typename _RandomAccessIterator, typename _Distance, typename _Tp>
+ template<typename _RandomAccessIterator, typename _Distance, typename _Tp,
+ typename _Compare>
void
__push_heap(_RandomAccessIterator __first,
- _Distance __holeIndex, _Distance __topIndex, _Tp __value)
+ _Distance __holeIndex, _Distance __topIndex, _Tp __value,
+ _Compare __comp)
{
_Distance __parent = (__holeIndex - 1) / 2;
- while (__holeIndex > __topIndex && *(__first + __parent) < __value)
+ while (__holeIndex > __topIndex && __comp(__first + __parent, __value))
{
*(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first + __parent));
__holeIndex = __parent;
@@ -169,24 +163,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_ValueType __value = _GLIBCXX_MOVE(*(__last - 1));
std::__push_heap(__first, _DistanceType((__last - __first) - 1),
- _DistanceType(0), _GLIBCXX_MOVE(__value));
- }
-
- template<typename _RandomAccessIterator, typename _Distance, typename _Tp,
- typename _Compare>
- void
- __push_heap(_RandomAccessIterator __first, _Distance __holeIndex,
- _Distance __topIndex, _Tp __value, _Compare __comp)
- {
- _Distance __parent = (__holeIndex - 1) / 2;
- while (__holeIndex > __topIndex
- && __comp(*(__first + __parent), __value))
- {
- *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first + __parent));
- __holeIndex = __parent;
- __parent = (__holeIndex - 1) / 2;
- }
- *(__first + __holeIndex) = _GLIBCXX_MOVE(__value);
+ _DistanceType(0), _GLIBCXX_MOVE(__value),
+ __gnu_cxx::__ops::__iter_less_val());
}
/**
@@ -219,20 +197,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_ValueType __value = _GLIBCXX_MOVE(*(__last - 1));
std::__push_heap(__first, _DistanceType((__last - __first) - 1),
- _DistanceType(0), _GLIBCXX_MOVE(__value), __comp);
+ _DistanceType(0), _GLIBCXX_MOVE(__value),
+ __gnu_cxx::__ops::__iter_comp_val(__comp));
}
- template<typename _RandomAccessIterator, typename _Distance, typename _Tp>
+ template<typename _RandomAccessIterator, typename _Distance,
+ typename _Tp, typename _Compare>
void
__adjust_heap(_RandomAccessIterator __first, _Distance __holeIndex,
- _Distance __len, _Tp __value)
+ _Distance __len, _Tp __value, _Compare __comp)
{
const _Distance __topIndex = __holeIndex;
_Distance __secondChild = __holeIndex;
while (__secondChild < (__len - 1) / 2)
{
__secondChild = 2 * (__secondChild + 1);
- if (*(__first + __secondChild) < *(__first + (__secondChild - 1)))
+ if (__comp(__first + __secondChild,
+ __first + (__secondChild - 1)))
__secondChild--;
*(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first + __secondChild));
__holeIndex = __secondChild;
@@ -244,14 +225,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
+ (__secondChild - 1)));
__holeIndex = __secondChild - 1;
}
- std::__push_heap(__first, __holeIndex, __topIndex,
- _GLIBCXX_MOVE(__value));
+ std::__push_heap(__first, __holeIndex, __topIndex,
+ _GLIBCXX_MOVE(__value),
+ __gnu_cxx::__ops::__iter_comp_val(__comp));
}
- template<typename _RandomAccessIterator>
+ template<typename _RandomAccessIterator, typename _Compare>
inline void
__pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
- _RandomAccessIterator __result)
+ _RandomAccessIterator __result, _Compare __comp)
{
typedef typename iterator_traits<_RandomAccessIterator>::value_type
_ValueType;
@@ -262,7 +244,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*__result = _GLIBCXX_MOVE(*__first);
std::__adjust_heap(__first, _DistanceType(0),
_DistanceType(__last - __first),
- _GLIBCXX_MOVE(__value));
+ _GLIBCXX_MOVE(__value), __comp);
}
/**
@@ -294,55 +276,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
if (__last - __first > 1)
{
--__last;
- std::__pop_heap(__first, __last, __last);
+ std::__pop_heap(__first, __last, __last,
+ __gnu_cxx::__ops::__iter_less_iter());
}
}
- template<typename _RandomAccessIterator, typename _Distance,
- typename _Tp, typename _Compare>
- void
- __adjust_heap(_RandomAccessIterator __first, _Distance __holeIndex,
- _Distance __len, _Tp __value, _Compare __comp)
- {
- const _Distance __topIndex = __holeIndex;
- _Distance __secondChild = __holeIndex;
- while (__secondChild < (__len - 1) / 2)
- {
- __secondChild = 2 * (__secondChild + 1);
- if (__comp(*(__first + __secondChild),
- *(__first + (__secondChild - 1))))
- __secondChild--;
- *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first + __secondChild));
- __holeIndex = __secondChild;
- }
- if ((__len & 1) == 0 && __secondChild == (__len - 2) / 2)
- {
- __secondChild = 2 * (__secondChild + 1);
- *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first
- + (__secondChild - 1)));
- __holeIndex = __secondChild - 1;
- }
- std::__push_heap(__first, __holeIndex, __topIndex,
- _GLIBCXX_MOVE(__value), __comp);
- }
-
- template<typename _RandomAccessIterator, typename _Compare>
- inline void
- __pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
- _RandomAccessIterator __result, _Compare __comp)
- {
- typedef typename iterator_traits<_RandomAccessIterator>::value_type
- _ValueType;
- typedef typename iterator_traits<_RandomAccessIterator>::difference_type
- _DistanceType;
-
- _ValueType __value = _GLIBCXX_MOVE(*__result);
- *__result = _GLIBCXX_MOVE(*__first);
- std::__adjust_heap(__first, _DistanceType(0),
- _DistanceType(__last - __first),
- _GLIBCXX_MOVE(__value), __comp);
- }
-
/**
* @brief Pop an element off a heap using comparison functor.
* @param __first Start of heap.
@@ -369,33 +307,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
if (__last - __first > 1)
{
--__last;
- std::__pop_heap(__first, __last, __last, __comp);
+ std::__pop_heap(__first, __last, __last,
+ __gnu_cxx::__ops::__iter_comp_iter(__comp));
}
}
- /**
- * @brief Construct a heap over a range.
- * @param __first Start of heap.
- * @param __last End of heap.
- * @ingroup heap_algorithms
- *
- * This operation makes the elements in [__first,__last) into a heap.
- */
- template<typename _RandomAccessIterator>
+ template<typename _RandomAccessIterator, typename _Compare>
void
- make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
+ __make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
+ _Compare __comp)
{
typedef typename iterator_traits<_RandomAccessIterator>::value_type
_ValueType;
typedef typename iterator_traits<_RandomAccessIterator>::difference_type
_DistanceType;
- // concept requirements
- __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
- _RandomAccessIterator>)
- __glibcxx_function_requires(_LessThanComparableConcept<_ValueType>)
- __glibcxx_requires_valid_range(__first, __last);
-
if (__last - __first < 2)
return;
@@ -404,12 +330,36 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
while (true)
{
_ValueType __value = _GLIBCXX_MOVE(*(__first + __parent));
- std::__adjust_heap(__first, __parent, __len, _GLIBCXX_MOVE(__value));
+ std::__adjust_heap(__first, __parent, __len, _GLIBCXX_MOVE(__value),
+ __comp);
if (__parent == 0)
return;
__parent--;
}
}
+
+ /**
+ * @brief Construct a heap over a range.
+ * @param __first Start of heap.
+ * @param __last End of heap.
+ * @ingroup heap_algorithms
+ *
+ * This operation makes the elements in [__first,__last) into a heap.
+ */
+ template<typename _RandomAccessIterator>
+ inline void
+ make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
+ {
+ // concept requirements
+ __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
+ _RandomAccessIterator>)
+ __glibcxx_function_requires(_LessThanComparableConcept<
+ typename iterator_traits<_RandomAccessIterator>::value_type>)
+ __glibcxx_requires_valid_range(__first, __last);
+
+ std::__make_heap(__first, __last,
+ __gnu_cxx::__ops::__iter_less_iter());
+ }
/**
* @brief Construct a heap over a range using comparison functor.
@@ -422,33 +372,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* Comparisons are made using __comp.
*/
template<typename _RandomAccessIterator, typename _Compare>
- void
+ inline void
make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
_Compare __comp)
{
- typedef typename iterator_traits<_RandomAccessIterator>::value_type
- _ValueType;
- typedef typename iterator_traits<_RandomAccessIterator>::difference_type
- _DistanceType;
-
// concept requirements
__glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
_RandomAccessIterator>)
__glibcxx_requires_valid_range(__first, __last);
- if (__last - __first < 2)
- return;
+ std::__make_heap(__first, __last,
+ __gnu_cxx::__ops::__iter_comp_iter(__comp));
+ }
- const _DistanceType __len = __last - __first;
- _DistanceType __parent = (__len - 2) / 2;
- while (true)
+ template<typename _RandomAccessIterator, typename _Compare>
+ void
+ __sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
+ _Compare __comp)
+ {
+ while (__last - __first > 1)
{
- _ValueType __value = _GLIBCXX_MOVE(*(__first + __parent));
- std::__adjust_heap(__first, __parent, __len, _GLIBCXX_MOVE(__value),
- __comp);
- if (__parent == 0)
- return;
- __parent--;
+ --__last;
+ std::__pop_heap(__first, __last, __last, __comp);
}
}
@@ -461,7 +406,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* This operation sorts the valid heap in the range [__first,__last).
*/
template<typename _RandomAccessIterator>
- void
+ inline void
sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
{
// concept requirements
@@ -472,11 +417,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__glibcxx_requires_valid_range(__first, __last);
__glibcxx_requires_heap(__first, __last);
- while (__last - __first > 1)
- {
- --__last;
- std::__pop_heap(__first, __last, __last);
- }
+ std::__sort_heap(__first, __last,
+ __gnu_cxx::__ops::__iter_less_iter());
}
/**
@@ -490,7 +432,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* Comparisons are made using __comp.
*/
template<typename _RandomAccessIterator, typename _Compare>
- void
+ inline void
sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
_Compare __comp)
{
@@ -500,11 +442,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__glibcxx_requires_valid_range(__first, __last);
__glibcxx_requires_heap_pred(__first, __last, __comp);
- while (__last - __first > 1)
- {
- --__last;
- std::__pop_heap(__first, __last, __last, __comp);
- }
+ std::__sort_heap(__first, __last,
+ __gnu_cxx::__ops::__iter_comp_iter(__comp));
}
#if __cplusplus >= 201103L
@@ -529,8 +468,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typename iterator_traits<_RandomAccessIterator>::value_type>)
__glibcxx_requires_valid_range(__first, __last);
- return __first + std::__is_heap_until(__first, std::distance(__first,
- __last));
+ return __first +
+ std::__is_heap_until(__first, std::distance(__first, __last),
+ __gnu_cxx::__ops::__iter_less_iter());
}
/**
@@ -554,9 +494,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_RandomAccessIterator>)
__glibcxx_requires_valid_range(__first, __last);
- return __first + std::__is_heap_until(__first, std::distance(__first,
- __last),
- __comp);
+ return __first
+ + std::__is_heap_until(__first, std::distance(__first, __last),
+ __gnu_cxx::__ops::__iter_comp_iter(__comp));
}
/**
diff --git a/libstdc++-v3/include/bits/stl_uninitialized.h b/libstdc++-v3/include/bits/stl_uninitialized.h
index 310b16202ec..e45046b4999 100644
--- a/libstdc++-v3/include/bits/stl_uninitialized.h
+++ b/libstdc++-v3/include/bits/stl_uninitialized.h
@@ -111,9 +111,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_ValueType1;
typedef typename iterator_traits<_ForwardIterator>::value_type
_ValueType2;
+#if __cplusplus < 201103L
+ const bool __assignable = true;
+#else
+ // trivial types can have deleted assignment
+ typedef typename iterator_traits<_InputIterator>::reference _RefType;
+ const bool __assignable = is_assignable<_ValueType1, _RefType>::value;
+#endif
- return std::__uninitialized_copy<(__is_trivial(_ValueType1)
- && __is_trivial(_ValueType2))>::
+ return std::__uninitialized_copy<__is_trivial(_ValueType1)
+ && __is_trivial(_ValueType2)
+ && __assignable>::
__uninit_copy(__first, __last, __result);
}
@@ -166,8 +174,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
typedef typename iterator_traits<_ForwardIterator>::value_type
_ValueType;
+#if __cplusplus < 201103L
+ const bool __assignable = true;
+#else
+ // trivial types can have deleted assignment
+ const bool __assignable = is_copy_assignable<_ValueType>::value;
+#endif
- std::__uninitialized_fill<__is_trivial(_ValueType)>::
+ std::__uninitialized_fill<__is_trivial(_ValueType) && __assignable>::
__uninit_fill(__first, __last, __x);
}
@@ -219,8 +233,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
typedef typename iterator_traits<_ForwardIterator>::value_type
_ValueType;
+#if __cplusplus < 201103L
+ const bool __assignable = true;
+#else
+ // trivial types can have deleted assignment
+ const bool __assignable = is_copy_assignable<_ValueType>::value;
+#endif
- std::__uninitialized_fill_n<__is_trivial(_ValueType)>::
+ std::__uninitialized_fill_n<__is_trivial(_ValueType) && __assignable>::
__uninit_fill_n(__first, __n, __x);
}
@@ -526,8 +546,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
typedef typename iterator_traits<_ForwardIterator>::value_type
_ValueType;
+ // trivial types can have deleted assignment
+ const bool __assignable = is_copy_assignable<_ValueType>::value;
- std::__uninitialized_default_1<__is_trivial(_ValueType)>::
+ std::__uninitialized_default_1<__is_trivial(_ValueType)
+ && __assignable>::
__uninit_default(__first, __last);
}
@@ -539,8 +562,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
typedef typename iterator_traits<_ForwardIterator>::value_type
_ValueType;
+ // trivial types can have deleted assignment
+ const bool __assignable = is_copy_assignable<_ValueType>::value;
- std::__uninitialized_default_n_1<__is_trivial(_ValueType)>::
+ std::__uninitialized_default_n_1<__is_trivial(_ValueType)
+ && __assignable>::
__uninit_default_n(__first, __n);
}
diff --git a/libstdc++-v3/include/bits/stl_vector.h b/libstdc++-v3/include/bits/stl_vector.h
index 03850b5e28f..376f39af216 100644
--- a/libstdc++-v3/include/bits/stl_vector.h
+++ b/libstdc++-v3/include/bits/stl_vector.h
@@ -785,7 +785,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_M_range_check(size_type __n) const
{
if (__n >= this->size())
- __throw_out_of_range(__N("vector::_M_range_check"));
+ __throw_out_of_range_fmt(__N("vector::_M_range_check: __n "
+ "(which is %zu) >= this->size() "
+ "(which is %zu)"),
+ __n, this->size());
}
public:
diff --git a/libstdc++-v3/include/bits/unique_ptr.h b/libstdc++-v3/include/bits/unique_ptr.h
index c6c9a5a04a5..bfe40ecb931 100644
--- a/libstdc++-v3/include/bits/unique_ptr.h
+++ b/libstdc++-v3/include/bits/unique_ptr.h
@@ -69,6 +69,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
void
operator()(_Tp* __ptr) const
{
+ static_assert(!is_void<_Tp>::value,
+ "can't delete pointer to incomplete type");
static_assert(sizeof(_Tp)>0,
"can't delete pointer to incomplete type");
delete __ptr;
diff --git a/libstdc++-v3/include/c_global/cmath b/libstdc++-v3/include/c_global/cmath
index b438585eb44..2641118e7b1 100644
--- a/libstdc++-v3/include/c_global/cmath
+++ b/libstdc++-v3/include/c_global/cmath
@@ -650,9 +650,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
isnormal(_Tp __x)
{ return __x != 0 ? true : false; }
+ // The front-end doesn't provide a type generic builtin (libstdc++/58625).
constexpr bool
signbit(float __x)
- { return __builtin_signbit(__x); }
+ { return __builtin_signbitf(__x); }
constexpr bool
signbit(double __x)
@@ -660,7 +661,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
constexpr bool
signbit(long double __x)
- { return __builtin_signbit(__x); }
+ { return __builtin_signbitl(__x); }
template<typename _Tp>
constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value,
diff --git a/libstdc++-v3/include/c_global/cstdio b/libstdc++-v3/include/c_global/cstdio
index 699a0766782..b5660737776 100644
--- a/libstdc++-v3/include/c_global/cstdio
+++ b/libstdc++-v3/include/c_global/cstdio
@@ -69,6 +69,7 @@ extern "C" char* gets (char* __s) __attribute__((deprecated));
#undef ftell
#undef fwrite
#undef getc
+#undef getchar
#if __cplusplus <= 201103L
# undef gets
#endif
diff --git a/libstdc++-v3/include/debug/array b/libstdc++-v3/include/debug/array
index d3eea853856..6ee23846518 100644
--- a/libstdc++-v3/include/debug/array
+++ b/libstdc++-v3/include/debug/array
@@ -165,7 +165,10 @@ namespace __debug
at(size_type __n)
{
if (__n >= _Nm)
- std::__throw_out_of_range(__N("array::at"));
+ std::__throw_out_of_range_fmt(__N("array::at: __n "
+ "(which is %zu) >= _Nm "
+ "(which is %zu)"),
+ __n, _Nm);
return _AT_Type::_S_ref(_M_elems, __n);
}
@@ -175,7 +178,9 @@ namespace __debug
// Result of conditional expression must be an lvalue so use
// boolean ? lvalue : (throw-expr, lvalue)
return __n < _Nm ? _AT_Type::_S_ref(_M_elems, __n)
- : (std::__throw_out_of_range(__N("array::at")),
+ : (std::__throw_out_of_range_fmt(__N("array::at: __n (which is %zu) "
+ ">= _Nm (which is %zu)"),
+ __n, _Nm),
_AT_Type::_S_ref(_M_elems, 0));
}
diff --git a/libstdc++-v3/include/debug/deque b/libstdc++-v3/include/debug/deque
index e5e902dfc7b..3984f11ac6b 100644
--- a/libstdc++-v3/include/debug/deque
+++ b/libstdc++-v3/include/debug/deque
@@ -128,7 +128,7 @@ namespace __debug
#if __cplusplus >= 201103L
deque&
- operator=(deque&& __x)
+ operator=(deque&& __x) noexcept
{
// NB: DR 1204.
// NB: DR 675.
@@ -287,7 +287,7 @@ namespace __debug
#if __cplusplus >= 201103L
void
- shrink_to_fit()
+ shrink_to_fit() noexcept
{
if (_Base::_M_shrink_to_fit())
this->_M_invalidate_all();
@@ -298,14 +298,14 @@ namespace __debug
// element access:
reference
- operator[](size_type __n)
+ operator[](size_type __n) _GLIBCXX_NOEXCEPT
{
__glibcxx_check_subscript(__n);
return _M_base()[__n];
}
const_reference
- operator[](size_type __n) const
+ operator[](size_type __n) const _GLIBCXX_NOEXCEPT
{
__glibcxx_check_subscript(__n);
return _M_base()[__n];
@@ -314,28 +314,28 @@ namespace __debug
using _Base::at;
reference
- front()
+ front() _GLIBCXX_NOEXCEPT
{
__glibcxx_check_nonempty();
return _Base::front();
}
const_reference
- front() const
+ front() const _GLIBCXX_NOEXCEPT
{
__glibcxx_check_nonempty();
return _Base::front();
}
reference
- back()
+ back() _GLIBCXX_NOEXCEPT
{
__glibcxx_check_nonempty();
return _Base::back();
}
const_reference
- back() const
+ back() const _GLIBCXX_NOEXCEPT
{
__glibcxx_check_nonempty();
return _Base::back();
@@ -468,7 +468,7 @@ namespace __debug
#endif
void
- pop_front()
+ pop_front() _GLIBCXX_NOEXCEPT
{
__glibcxx_check_nonempty();
this->_M_invalidate_if(_Equal(_Base::begin()));
@@ -476,7 +476,7 @@ namespace __debug
}
void
- pop_back()
+ pop_back() _GLIBCXX_NOEXCEPT
{
__glibcxx_check_nonempty();
this->_M_invalidate_if(_Equal(--_Base::end()));
@@ -556,7 +556,7 @@ namespace __debug
}
void
- swap(deque& __x)
+ swap(deque& __x) _GLIBCXX_NOEXCEPT
{
_Base::swap(__x);
this->_M_swap(__x);
diff --git a/libstdc++-v3/include/debug/formatter.h b/libstdc++-v3/include/debug/formatter.h
index 15dd8d73797..2af169b13fc 100644
--- a/libstdc++-v3/include/debug/formatter.h
+++ b/libstdc++-v3/include/debug/formatter.h
@@ -38,7 +38,7 @@ namespace __gnu_debug
using std::type_info;
template<typename _Iterator>
- bool __check_singular(_Iterator&);
+ bool __check_singular(const _Iterator&);
class _Safe_sequence_base;
diff --git a/libstdc++-v3/include/debug/forward_list b/libstdc++-v3/include/debug/forward_list
index 4c8ac371c94..5269f3978d3 100644
--- a/libstdc++-v3/include/debug/forward_list
+++ b/libstdc++-v3/include/debug/forward_list
@@ -785,23 +785,26 @@ namespace __gnu_debug
struct _BeforeBeginHelper<std::__debug::forward_list<_Tp, _Alloc> >
{
typedef std::__debug::forward_list<_Tp, _Alloc> _Sequence;
- typedef typename _Sequence::const_iterator _It;
- typedef typename _It::iterator_type _BaseIt;
- static bool
- _S_Is(_BaseIt __it, const _Sequence* __seq)
- { return __it == __seq->_M_base().cbefore_begin(); }
+ template<typename _Iterator>
+ static bool
+ _S_Is(const _Safe_iterator<_Iterator, _Sequence>& __it)
+ {
+ return
+ __it.base() == __it._M_get_sequence()->_M_base().before_begin();
+ }
- static bool
- _S_Is_Beginnest(_BaseIt __it, const _Sequence* __seq)
- { return _S_Is(__it, __seq); }
+ template<typename _Iterator>
+ static bool
+ _S_Is_Beginnest(const _Safe_iterator<_Iterator, _Sequence>& __it)
+ { return _S_Is(__it); }
};
#ifndef _GLIBCXX_DEBUG_PEDANTIC
template<class _Tp, class _Alloc>
struct _Insert_range_from_self_is_safe<
std::__debug::forward_list<_Tp, _Alloc> >
- { enum { __value = 1 }; };
+ { enum { __value = 1 }; };
#endif
}
diff --git a/libstdc++-v3/include/debug/functions.h b/libstdc++-v3/include/debug/functions.h
index 8e76b7f2ee5..4d8fe21719c 100644
--- a/libstdc++-v3/include/debug/functions.h
+++ b/libstdc++-v3/include/debug/functions.h
@@ -45,6 +45,9 @@ namespace __gnu_debug
template<typename _Iterator, typename _Sequence>
class _Safe_iterator;
+ template<typename _Iterator, typename _Sequence>
+ class _Safe_local_iterator;
+
template<typename _Sequence>
struct _Insert_range_from_self_is_safe
{ enum { __value = 0 }; };
@@ -57,7 +60,7 @@ namespace __gnu_debug
// a _Safe_iterator.
template<typename _Iterator>
inline bool
- __check_singular(_Iterator& __x)
+ __check_singular(const _Iterator& __x)
{ return __check_singular_aux(&__x); }
/** Non-NULL pointers are nonsingular. */
@@ -66,17 +69,11 @@ namespace __gnu_debug
__check_singular(const _Tp* __ptr)
{ return __ptr == 0; }
- /** Safe iterators know if they are singular. */
- template<typename _Iterator, typename _Sequence>
- inline bool
- __check_singular(const _Safe_iterator<_Iterator, _Sequence>& __x)
- { return __x._M_singular(); }
-
/** Assume that some arbitrary iterator is dereferenceable, because we
can't prove that it isn't. */
template<typename _Iterator>
inline bool
- __check_dereferenceable(_Iterator&)
+ __check_dereferenceable(const _Iterator&)
{ return true; }
/** Non-NULL pointers are dereferenceable. */
@@ -85,12 +82,19 @@ namespace __gnu_debug
__check_dereferenceable(const _Tp* __ptr)
{ return __ptr; }
- /** Safe iterators know if they are singular. */
+ /** Safe iterators know if they are dereferenceable. */
template<typename _Iterator, typename _Sequence>
inline bool
__check_dereferenceable(const _Safe_iterator<_Iterator, _Sequence>& __x)
{ return __x._M_dereferenceable(); }
+ /** Safe local iterators know if they are dereferenceable. */
+ template<typename _Iterator, typename _Sequence>
+ inline bool
+ __check_dereferenceable(const _Safe_local_iterator<_Iterator,
+ _Sequence>& __x)
+ { return __x._M_dereferenceable(); }
+
/** If the distance between two random access iterators is
* nonnegative, assume the range is valid.
*/
diff --git a/libstdc++-v3/include/debug/safe_iterator.h b/libstdc++-v3/include/debug/safe_iterator.h
index a1f7651b1bd..59ba602e411 100644
--- a/libstdc++-v3/include/debug/safe_iterator.h
+++ b/libstdc++-v3/include/debug/safe_iterator.h
@@ -44,22 +44,20 @@ namespace __gnu_debug
template <typename _Sequence>
struct _BeforeBeginHelper
{
- typedef typename _Sequence::const_iterator _It;
- typedef typename _It::iterator_type _BaseIt;
-
- static bool
- _S_Is(_BaseIt, const _Sequence*)
- { return false; }
-
- static bool
- _S_Is_Beginnest(_BaseIt __it, const _Sequence* __seq)
- { return __it == __seq->_M_base().begin(); }
+ template<typename _Iterator>
+ static bool
+ _S_Is(const _Safe_iterator<_Iterator, _Sequence>&)
+ { return false; }
+
+ template<typename _Iterator>
+ static bool
+ _S_Is_Beginnest(const _Safe_iterator<_Iterator, _Sequence>& __it)
+ { return __it.base() == __it._M_get_sequence()->_M_base().begin(); }
};
- /** Iterators that derive from _Safe_iterator_base but that aren't
- * _Safe_iterators can be determined singular or non-singular via
- * _Safe_iterator_base.
- */
+ /** Iterators that derive from _Safe_iterator_base can be determined singular
+ * or non-singular.
+ **/
inline bool
__check_singular_aux(const _Safe_iterator_base* __x)
{ return __x->_M_singular(); }
@@ -77,26 +75,26 @@ namespace __gnu_debug
/** Determine the distance between two iterators with some known
* precision.
*/
- template<typename _Iterator1, typename _Iterator2>
- inline std::pair<typename std::iterator_traits<_Iterator1>::difference_type,
+ template<typename _Iterator>
+ inline std::pair<typename std::iterator_traits<_Iterator>::difference_type,
_Distance_precision>
- __get_distance(const _Iterator1& __lhs, const _Iterator2& __rhs,
+ __get_distance(const _Iterator& __lhs, const _Iterator& __rhs,
std::random_access_iterator_tag)
{ return std::make_pair(__rhs - __lhs, __dp_exact); }
- template<typename _Iterator1, typename _Iterator2>
- inline std::pair<typename std::iterator_traits<_Iterator1>::difference_type,
+ template<typename _Iterator>
+ inline std::pair<typename std::iterator_traits<_Iterator>::difference_type,
_Distance_precision>
- __get_distance(const _Iterator1& __lhs, const _Iterator2& __rhs,
+ __get_distance(const _Iterator& __lhs, const _Iterator& __rhs,
std::forward_iterator_tag)
{ return std::make_pair(__lhs == __rhs? 0 : 1, __dp_equality); }
- template<typename _Iterator1, typename _Iterator2>
- inline std::pair<typename std::iterator_traits<_Iterator1>::difference_type,
+ template<typename _Iterator>
+ inline std::pair<typename std::iterator_traits<_Iterator>::difference_type,
_Distance_precision>
- __get_distance(const _Iterator1& __lhs, const _Iterator2& __rhs)
+ __get_distance(const _Iterator& __lhs, const _Iterator& __rhs)
{
- typedef typename std::iterator_traits<_Iterator1>::iterator_category
+ typedef typename std::iterator_traits<_Iterator>::iterator_category
_Category;
return __get_distance(__lhs, __rhs, _Category());
}
@@ -116,6 +114,7 @@ namespace __gnu_debug
class _Safe_iterator : public _Safe_iterator_base
{
typedef _Safe_iterator _Self;
+ typedef typename _Sequence::const_iterator _Const_iterator;
/// The underlying iterator
_Iterator _M_current;
@@ -123,10 +122,7 @@ namespace __gnu_debug
/// Determine if this is a constant iterator.
bool
_M_constant() const
- {
- typedef typename _Sequence::const_iterator const_iterator;
- return std::__are_same<const_iterator, _Safe_iterator>::__value;
- }
+ { return std::__are_same<_Const_iterator, _Safe_iterator>::__value; }
typedef std::iterator_traits<_Iterator> _Traits;
@@ -139,7 +135,7 @@ namespace __gnu_debug
typedef typename _Traits::pointer pointer;
/// @post the iterator is singular and unattached
- _Safe_iterator() : _M_current() { }
+ _Safe_iterator() _GLIBCXX_NOEXCEPT : _M_current() { }
/**
* @brief Safe iterator construction from an unsafe iterator and
@@ -149,6 +145,7 @@ namespace __gnu_debug
* @post this is not singular
*/
_Safe_iterator(const _Iterator& __i, const _Sequence* __seq)
+ _GLIBCXX_NOEXCEPT
: _Safe_iterator_base(__seq, _M_constant()), _M_current(__i)
{
_GLIBCXX_DEBUG_VERIFY(! this->_M_singular(),
@@ -159,7 +156,7 @@ namespace __gnu_debug
/**
* @brief Copy construction.
*/
- _Safe_iterator(const _Safe_iterator& __x)
+ _Safe_iterator(const _Safe_iterator& __x) _GLIBCXX_NOEXCEPT
: _Safe_iterator_base(__x, _M_constant()), _M_current(__x._M_current)
{
// _GLIBCXX_RESOLVE_LIB_DEFECTS
@@ -176,7 +173,7 @@ namespace __gnu_debug
* @brief Move construction.
* @post __x is singular and unattached
*/
- _Safe_iterator(_Safe_iterator&& __x) : _M_current()
+ _Safe_iterator(_Safe_iterator&& __x) noexcept : _M_current()
{
_GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
|| __x._M_current == _Iterator(),
@@ -198,7 +195,7 @@ namespace __gnu_debug
const _Safe_iterator<_MutableIterator,
typename __gnu_cxx::__enable_if<(std::__are_same<_MutableIterator,
typename _Sequence::iterator::iterator_type>::__value),
- _Sequence>::__type>& __x)
+ _Sequence>::__type>& __x) _GLIBCXX_NOEXCEPT
: _Safe_iterator_base(__x, _M_constant()), _M_current(__x.base())
{
// _GLIBCXX_RESOLVE_LIB_DEFECTS
@@ -214,7 +211,7 @@ namespace __gnu_debug
* @brief Copy assignment.
*/
_Safe_iterator&
- operator=(const _Safe_iterator& __x)
+ operator=(const _Safe_iterator& __x) _GLIBCXX_NOEXCEPT
{
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// DR 408. Is vector<reverse_iterator<char*> > forbidden?
@@ -234,7 +231,7 @@ namespace __gnu_debug
* @post __x is singular and unattached
*/
_Safe_iterator&
- operator=(_Safe_iterator&& __x)
+ operator=(_Safe_iterator&& __x) noexcept
{
_GLIBCXX_DEBUG_VERIFY(this != &__x,
_M_message(__msg_self_move_assign)
@@ -257,7 +254,7 @@ namespace __gnu_debug
* @pre iterator is dereferenceable
*/
reference
- operator*() const
+ operator*() const _GLIBCXX_NOEXCEPT
{
_GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
_M_message(__msg_bad_deref)
@@ -271,7 +268,7 @@ namespace __gnu_debug
* @todo Make this correct w.r.t. iterators that return proxies
*/
pointer
- operator->() const
+ operator->() const _GLIBCXX_NOEXCEPT
{
_GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
_M_message(__msg_bad_deref)
@@ -285,7 +282,7 @@ namespace __gnu_debug
* @pre iterator is incrementable
*/
_Safe_iterator&
- operator++()
+ operator++() _GLIBCXX_NOEXCEPT
{
_GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
_M_message(__msg_bad_inc)
@@ -299,7 +296,7 @@ namespace __gnu_debug
* @pre iterator is incrementable
*/
_Safe_iterator
- operator++(int)
+ operator++(int) _GLIBCXX_NOEXCEPT
{
_GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
_M_message(__msg_bad_inc)
@@ -315,7 +312,7 @@ namespace __gnu_debug
* @pre iterator is decrementable
*/
_Safe_iterator&
- operator--()
+ operator--() _GLIBCXX_NOEXCEPT
{
_GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
_M_message(__msg_bad_dec)
@@ -329,7 +326,7 @@ namespace __gnu_debug
* @pre iterator is decrementable
*/
_Safe_iterator
- operator--(int)
+ operator--(int) _GLIBCXX_NOEXCEPT
{
_GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
_M_message(__msg_bad_dec)
@@ -341,7 +338,7 @@ namespace __gnu_debug
// ------ Random access iterator requirements ------
reference
- operator[](const difference_type& __n) const
+ operator[](const difference_type& __n) const _GLIBCXX_NOEXCEPT
{
_GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n)
&& this->_M_can_advance(__n+1),
@@ -352,7 +349,7 @@ namespace __gnu_debug
}
_Safe_iterator&
- operator+=(const difference_type& __n)
+ operator+=(const difference_type& __n) _GLIBCXX_NOEXCEPT
{
_GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n),
_M_message(__msg_advance_oob)
@@ -362,7 +359,7 @@ namespace __gnu_debug
}
_Safe_iterator
- operator+(const difference_type& __n) const
+ operator+(const difference_type& __n) const _GLIBCXX_NOEXCEPT
{
_Safe_iterator __tmp(*this);
__tmp += __n;
@@ -370,7 +367,7 @@ namespace __gnu_debug
}
_Safe_iterator&
- operator-=(const difference_type& __n)
+ operator-=(const difference_type& __n) _GLIBCXX_NOEXCEPT
{
_GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(-__n),
_M_message(__msg_retreat_oob)
@@ -380,7 +377,7 @@ namespace __gnu_debug
}
_Safe_iterator
- operator-(const difference_type& __n) const
+ operator-(const difference_type& __n) const _GLIBCXX_NOEXCEPT
{
_Safe_iterator __tmp(*this);
__tmp -= __n;
@@ -392,13 +389,13 @@ namespace __gnu_debug
* @brief Return the underlying iterator
*/
_Iterator
- base() const { return _M_current; }
+ base() const _GLIBCXX_NOEXCEPT { return _M_current; }
/**
* @brief Conversion to underlying non-debug iterator to allow
* better interaction with non-debug containers.
*/
- operator _Iterator() const { return _M_current; }
+ operator _Iterator() const _GLIBCXX_NOEXCEPT { return _M_current; }
/** Attach iterator to the given sequence. */
void
@@ -445,43 +442,46 @@ namespace __gnu_debug
_M_can_advance(const difference_type& __n) const;
// Is the iterator range [*this, __rhs) valid?
- template<typename _Other>
- bool
- _M_valid_range(const _Safe_iterator<_Other, _Sequence>& __rhs) const;
+ bool
+ _M_valid_range(const _Safe_iterator& __rhs) const;
// The sequence this iterator references.
- const _Sequence*
+ typename
+ __gnu_cxx::__conditional_type<std::__are_same<_Const_iterator,
+ _Safe_iterator>::__value,
+ const _Sequence*,
+ _Sequence*>::__type
_M_get_sequence() const
- { return static_cast<const _Sequence*>(_M_sequence); }
+ { return static_cast<_Sequence*>(_M_sequence); }
/// Is this iterator equal to the sequence's begin() iterator?
- bool _M_is_begin() const
+ bool
+ _M_is_begin() const
{ return base() == _M_get_sequence()->_M_base().begin(); }
/// Is this iterator equal to the sequence's end() iterator?
- bool _M_is_end() const
+ bool
+ _M_is_end() const
{ return base() == _M_get_sequence()->_M_base().end(); }
/// Is this iterator equal to the sequence's before_begin() iterator if
/// any?
- bool _M_is_before_begin() const
- {
- return _BeforeBeginHelper<_Sequence>::_S_Is(base(), _M_get_sequence());
- }
+ bool
+ _M_is_before_begin() const
+ { return _BeforeBeginHelper<_Sequence>::_S_Is(*this); }
/// Is this iterator equal to the sequence's before_begin() iterator if
/// any or begin() otherwise?
- bool _M_is_beginnest() const
- {
- return _BeforeBeginHelper<_Sequence>::_S_Is_Beginnest(base(),
- _M_get_sequence());
- }
+ bool
+ _M_is_beginnest() const
+ { return _BeforeBeginHelper<_Sequence>::_S_Is_Beginnest(*this); }
};
template<typename _IteratorL, typename _IteratorR, typename _Sequence>
inline bool
operator==(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
+ _GLIBCXX_NOEXCEPT
{
_GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
_M_message(__msg_iter_compare_bad)
@@ -498,6 +498,7 @@ namespace __gnu_debug
inline bool
operator==(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
const _Safe_iterator<_Iterator, _Sequence>& __rhs)
+ _GLIBCXX_NOEXCEPT
{
_GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
_M_message(__msg_iter_compare_bad)
@@ -514,6 +515,7 @@ namespace __gnu_debug
inline bool
operator!=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
+ _GLIBCXX_NOEXCEPT
{
_GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
_M_message(__msg_iter_compare_bad)
@@ -530,6 +532,7 @@ namespace __gnu_debug
inline bool
operator!=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
const _Safe_iterator<_Iterator, _Sequence>& __rhs)
+ _GLIBCXX_NOEXCEPT
{
_GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
_M_message(__msg_iter_compare_bad)
@@ -546,6 +549,7 @@ namespace __gnu_debug
inline bool
operator<(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
+ _GLIBCXX_NOEXCEPT
{
_GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
_M_message(__msg_iter_order_bad)
@@ -562,6 +566,7 @@ namespace __gnu_debug
inline bool
operator<(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
const _Safe_iterator<_Iterator, _Sequence>& __rhs)
+ _GLIBCXX_NOEXCEPT
{
_GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
_M_message(__msg_iter_order_bad)
@@ -578,6 +583,7 @@ namespace __gnu_debug
inline bool
operator<=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
+ _GLIBCXX_NOEXCEPT
{
_GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
_M_message(__msg_iter_order_bad)
@@ -594,6 +600,7 @@ namespace __gnu_debug
inline bool
operator<=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
const _Safe_iterator<_Iterator, _Sequence>& __rhs)
+ _GLIBCXX_NOEXCEPT
{
_GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
_M_message(__msg_iter_order_bad)
@@ -610,6 +617,7 @@ namespace __gnu_debug
inline bool
operator>(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
+ _GLIBCXX_NOEXCEPT
{
_GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
_M_message(__msg_iter_order_bad)
@@ -626,6 +634,7 @@ namespace __gnu_debug
inline bool
operator>(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
const _Safe_iterator<_Iterator, _Sequence>& __rhs)
+ _GLIBCXX_NOEXCEPT
{
_GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
_M_message(__msg_iter_order_bad)
@@ -642,6 +651,7 @@ namespace __gnu_debug
inline bool
operator>=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
+ _GLIBCXX_NOEXCEPT
{
_GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
_M_message(__msg_iter_order_bad)
@@ -658,6 +668,7 @@ namespace __gnu_debug
inline bool
operator>=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
const _Safe_iterator<_Iterator, _Sequence>& __rhs)
+ _GLIBCXX_NOEXCEPT
{
_GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
_M_message(__msg_iter_order_bad)
@@ -678,6 +689,7 @@ namespace __gnu_debug
inline typename _Safe_iterator<_IteratorL, _Sequence>::difference_type
operator-(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
+ _GLIBCXX_NOEXCEPT
{
_GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
_M_message(__msg_distance_bad)
@@ -694,6 +706,7 @@ namespace __gnu_debug
inline typename _Safe_iterator<_Iterator, _Sequence>::difference_type
operator-(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
const _Safe_iterator<_Iterator, _Sequence>& __rhs)
+ _GLIBCXX_NOEXCEPT
{
_GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
_M_message(__msg_distance_bad)
@@ -709,7 +722,7 @@ namespace __gnu_debug
template<typename _Iterator, typename _Sequence>
inline _Safe_iterator<_Iterator, _Sequence>
operator+(typename _Safe_iterator<_Iterator,_Sequence>::difference_type __n,
- const _Safe_iterator<_Iterator, _Sequence>& __i)
+ const _Safe_iterator<_Iterator, _Sequence>& __i) _GLIBCXX_NOEXCEPT
{ return __i + __n; }
} // namespace __gnu_debug
diff --git a/libstdc++-v3/include/debug/safe_iterator.tcc b/libstdc++-v3/include/debug/safe_iterator.tcc
index daa9c6bfa72..7550a1d96ba 100644
--- a/libstdc++-v3/include/debug/safe_iterator.tcc
+++ b/libstdc++-v3/include/debug/safe_iterator.tcc
@@ -36,27 +36,22 @@ namespace __gnu_debug
_Safe_iterator<_Iterator, _Sequence>::
_M_can_advance(const difference_type& __n) const
{
- typedef typename _Sequence::const_iterator const_debug_iterator;
- typedef typename const_debug_iterator::iterator_type const_iterator;
-
if (this->_M_singular())
return false;
if (__n == 0)
return true;
if (__n < 0)
{
- const_iterator __begin = _M_get_sequence()->_M_base().begin();
std::pair<difference_type, _Distance_precision> __dist =
- __get_distance(__begin, base());
+ __get_distance(_M_get_sequence()->_M_base().begin(), base());
bool __ok = ((__dist.second == __dp_exact && __dist.first >= -__n)
|| (__dist.second != __dp_exact && __dist.first > 0));
return __ok;
}
else
{
- const_iterator __end = _M_get_sequence()->_M_base().end();
std::pair<difference_type, _Distance_precision> __dist =
- __get_distance(base(), __end);
+ __get_distance(base(), _M_get_sequence()->_M_base().end());
bool __ok = ((__dist.second == __dp_exact && __dist.first >= __n)
|| (__dist.second != __dp_exact && __dist.first > 0));
return __ok;
@@ -64,42 +59,41 @@ namespace __gnu_debug
}
template<typename _Iterator, typename _Sequence>
- template<typename _Other>
- bool
- _Safe_iterator<_Iterator, _Sequence>::
- _M_valid_range(const _Safe_iterator<_Other, _Sequence>& __rhs) const
- {
- if (!_M_can_compare(__rhs))
- return false;
-
- /* Determine if we can order the iterators without the help of
- the container */
- std::pair<difference_type, _Distance_precision> __dist =
- __get_distance(base(), __rhs.base());
- switch (__dist.second) {
- case __dp_equality:
- if (__dist.first == 0)
- return true;
- break;
-
- case __dp_sign:
- case __dp_exact:
- return __dist.first >= 0;
- }
+ bool
+ _Safe_iterator<_Iterator, _Sequence>::
+ _M_valid_range(const _Safe_iterator& __rhs) const
+ {
+ if (!_M_can_compare(__rhs))
+ return false;
- /* We can only test for equality, but check if one of the
- iterators is at an extreme. */
- /* Optim for classic [begin, it) or [it, end) ranges, limit checks
- * when code is valid. Note, for the special case of forward_list,
- * before_begin replaces the role of begin. */
- if (_M_is_beginnest() || __rhs._M_is_end())
+ /* Determine if we can order the iterators without the help of
+ the container */
+ std::pair<difference_type, _Distance_precision> __dist =
+ __get_distance(base(), __rhs.base());
+ switch (__dist.second) {
+ case __dp_equality:
+ if (__dist.first == 0)
return true;
- if (_M_is_end() || __rhs._M_is_beginnest())
- return false;
+ break;
- // Assume that this is a valid range; we can't check anything else
- return true;
+ case __dp_sign:
+ case __dp_exact:
+ return __dist.first >= 0;
}
+
+ /* We can only test for equality, but check if one of the
+ iterators is at an extreme. */
+ /* Optim for classic [begin, it) or [it, end) ranges, limit checks
+ * when code is valid. Note, for the special case of forward_list,
+ * before_begin replaces the role of begin. */
+ if (_M_is_beginnest() || __rhs._M_is_end())
+ return true;
+ if (_M_is_end() || __rhs._M_is_beginnest())
+ return false;
+
+ // Assume that this is a valid range; we can't check anything else
+ return true;
+ }
} // namespace __gnu_debug
#endif
diff --git a/libstdc++-v3/include/debug/safe_local_iterator.h b/libstdc++-v3/include/debug/safe_local_iterator.h
index 82975b70722..6724798b377 100644
--- a/libstdc++-v3/include/debug/safe_local_iterator.h
+++ b/libstdc++-v3/include/debug/safe_local_iterator.h
@@ -52,6 +52,7 @@ namespace __gnu_debug
class _Safe_local_iterator : public _Safe_local_iterator_base
{
typedef _Safe_local_iterator _Self;
+ typedef typename _Sequence::const_local_iterator _Const_local_iterator;
typedef typename _Sequence::size_type size_type;
/// The underlying iterator
@@ -64,8 +65,8 @@ namespace __gnu_debug
bool
_M_constant() const
{
- typedef typename _Sequence::const_local_iterator const_iterator;
- return std::__are_same<const_iterator, _Safe_local_iterator>::__value;
+ return std::__are_same<_Const_local_iterator,
+ _Safe_local_iterator>::__value;
}
typedef std::iterator_traits<_Iterator> _Traits;
@@ -253,15 +254,17 @@ namespace __gnu_debug
{ return !this->_M_singular() && !_M_is_end(); }
// Is the iterator range [*this, __rhs) valid?
- template<typename _Other>
- bool
- _M_valid_range(const _Safe_local_iterator<_Other,
- _Sequence>& __rhs) const;
+ bool
+ _M_valid_range(const _Safe_local_iterator& __rhs) const;
// The sequence this iterator references.
- const _Sequence*
+ typename
+ __gnu_cxx::__conditional_type<std::__are_same<_Const_local_iterator,
+ _Safe_local_iterator>::__value,
+ const _Sequence*,
+ _Sequence*>::__type
_M_get_sequence() const
- { return static_cast<const _Sequence*>(_M_sequence); }
+ { return static_cast<_Sequence*>(_M_sequence); }
/// Is this iterator equal to the sequence's begin() iterator?
bool _M_is_begin() const
diff --git a/libstdc++-v3/include/debug/safe_local_iterator.tcc b/libstdc++-v3/include/debug/safe_local_iterator.tcc
index fac971ec822..6633bdb7794 100644
--- a/libstdc++-v3/include/debug/safe_local_iterator.tcc
+++ b/libstdc++-v3/include/debug/safe_local_iterator.tcc
@@ -32,21 +32,20 @@
namespace __gnu_debug
{
template<typename _Iterator, typename _Sequence>
- template<typename _Other>
- bool
- _Safe_local_iterator<_Iterator, _Sequence>::
- _M_valid_range(const _Safe_local_iterator<_Other, _Sequence>& __rhs) const
- {
- if (!_M_can_compare(__rhs))
- return false;
- if (_M_bucket != __rhs._M_bucket)
- return false;
+ bool
+ _Safe_local_iterator<_Iterator, _Sequence>::
+ _M_valid_range(const _Safe_local_iterator& __rhs) const
+ {
+ if (!_M_can_compare(__rhs))
+ return false;
+ if (_M_bucket != __rhs._M_bucket)
+ return false;
- /* Determine if we can order the iterators without the help of
- the container */
- std::pair<difference_type, _Distance_precision> __dist =
- __get_distance(base(), __rhs.base());
- switch (__dist.second)
+ /* Determine if we can order the iterators without the help of
+ the container */
+ std::pair<difference_type, _Distance_precision> __dist =
+ __get_distance(base(), __rhs.base());
+ switch (__dist.second)
{
case __dp_equality:
if (__dist.first == 0)
@@ -58,18 +57,18 @@ namespace __gnu_debug
return __dist.first >= 0;
}
- /* We can only test for equality, but check if one of the
- iterators is at an extreme. */
- /* Optim for classic [begin, it) or [it, end) ranges, limit checks
- * when code is valid. */
- if (_M_is_begin() || __rhs._M_is_end())
- return true;
- if (_M_is_end() || __rhs._M_is_begin())
- return false;
-
- // Assume that this is a valid range; we can't check anything else
+ /* We can only test for equality, but check if one of the
+ iterators is at an extreme. */
+ /* Optim for classic [begin, it) or [it, end) ranges, limit checks
+ * when code is valid. */
+ if (_M_is_begin() || __rhs._M_is_end())
return true;
- }
+ if (_M_is_end() || __rhs._M_is_begin())
+ return false;
+
+ // Assume that this is a valid range; we can't check anything else
+ return true;
+ }
} // namespace __gnu_debug
#endif
diff --git a/libstdc++-v3/include/debug/string b/libstdc++-v3/include/debug/string
index 925575e662a..6d2c5395ade 100644
--- a/libstdc++-v3/include/debug/string
+++ b/libstdc++-v3/include/debug/string
@@ -70,7 +70,7 @@ namespace __gnu_debug
// 21.3.1 construct/copy/destroy:
explicit basic_string(const _Allocator& __a = _Allocator())
- _GLIBCXX_NOEXCEPT
+ // _GLIBCXX_NOEXCEPT
: _Base(__a)
{ }
@@ -114,7 +114,7 @@ namespace __gnu_debug
{ }
#if __cplusplus >= 201103L
- basic_string(basic_string&& __str) noexcept
+ basic_string(basic_string&& __str) // noexcept
: _Base(std::move(__str))
{ }
@@ -172,7 +172,7 @@ namespace __gnu_debug
// 21.3.2 iterators:
iterator
- begin() _GLIBCXX_NOEXCEPT
+ begin() // _GLIBCXX_NOEXCEPT
{ return iterator(_Base::begin(), this); }
const_iterator
@@ -180,7 +180,7 @@ namespace __gnu_debug
{ return const_iterator(_Base::begin(), this); }
iterator
- end() _GLIBCXX_NOEXCEPT
+ end() // _GLIBCXX_NOEXCEPT
{ return iterator(_Base::end(), this); }
const_iterator
@@ -188,7 +188,7 @@ namespace __gnu_debug
{ return const_iterator(_Base::end(), this); }
reverse_iterator
- rbegin() _GLIBCXX_NOEXCEPT
+ rbegin() // _GLIBCXX_NOEXCEPT
{ return reverse_iterator(end()); }
const_reverse_iterator
@@ -196,7 +196,7 @@ namespace __gnu_debug
{ return const_reverse_iterator(end()); }
reverse_iterator
- rend() _GLIBCXX_NOEXCEPT
+ rend() // _GLIBCXX_NOEXCEPT
{ return reverse_iterator(begin()); }
const_reverse_iterator
@@ -258,7 +258,7 @@ namespace __gnu_debug
using _Base::reserve;
void
- clear() _GLIBCXX_NOEXCEPT
+ clear() // _GLIBCXX_NOEXCEPT
{
_Base::clear();
this->_M_invalidate_all();
@@ -279,7 +279,7 @@ namespace __gnu_debug
}
reference
- operator[](size_type __pos) _GLIBCXX_NOEXCEPT
+ operator[](size_type __pos) // _GLIBCXX_NOEXCEPT
{
#ifdef _GLIBCXX_DEBUG_PEDANTIC
__glibcxx_check_subscript(__pos);
@@ -583,7 +583,7 @@ namespace __gnu_debug
#if __cplusplus >= 201103L
void
- pop_back() noexcept
+ pop_back() // noexcept
{
__glibcxx_check_nonempty();
_Base::pop_back();
diff --git a/libstdc++-v3/include/decimal/decimal b/libstdc++-v3/include/decimal/decimal
index a8805378d80..c1601180e75 100644
--- a/libstdc++-v3/include/decimal/decimal
+++ b/libstdc++-v3/include/decimal/decimal
@@ -250,8 +250,11 @@ namespace decimal
/// Conforming extension: Conversion from scalar decimal type.
decimal32(__decfloat32 __z) : __val(__z) {}
- // 3.2.2.5 Conversion to integral type. (DISABLED)
- //operator long long() const { return (long long)__val; }
+#if __cplusplus >= 201103L
+ // 3.2.2.5 Conversion to integral type.
+ // Note: explicit per n3407.
+ explicit operator long long() const { return (long long)__val; }
+#endif
// 3.2.2.6 Increment and decrement operators.
decimal32& operator++()
@@ -333,8 +336,11 @@ namespace decimal
/// Conforming extension: Conversion from scalar decimal type.
decimal64(__decfloat64 __z) : __val(__z) {}
- // 3.2.3.5 Conversion to integral type. (DISABLED)
- //operator long long() const { return (long long)__val; }
+#if __cplusplus >= 201103L
+ // 3.2.3.5 Conversion to integral type.
+ // Note: explicit per n3407.
+ explicit operator long long() const { return (long long)__val; }
+#endif
// 3.2.3.6 Increment and decrement operators.
decimal64& operator++()
@@ -417,8 +423,11 @@ namespace decimal
/// Conforming extension: Conversion from scalar decimal type.
decimal128(__decfloat128 __z) : __val(__z) {}
- // 3.2.4.5 Conversion to integral type. (DISABLED)
- //operator long long() const { return (long long)__val; }
+#if __cplusplus >= 201103L
+ // 3.2.4.5 Conversion to integral type.
+ // Note: explicit per n3407.
+ explicit operator long long() const { return (long long)__val; }
+#endif
// 3.2.4.6 Increment and decrement operators.
decimal128& operator++()
diff --git a/libstdc++-v3/include/experimental/optional b/libstdc++-v3/include/experimental/optional
new file mode 100644
index 00000000000..5882ff59296
--- /dev/null
+++ b/libstdc++-v3/include/experimental/optional
@@ -0,0 +1,823 @@
+// <optional> -*- C++ -*-
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// 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/>.
+
+/** @file experimental/optional
+ * This is a TS C++ Library header.
+ */
+
+#ifndef _GLIBCXX_EXPERIMENTAL_OPTIONAL
+#define _GLIBCXX_EXPERIMENTAL_OPTIONAL 1
+
+/**
+ * @defgroup experimental Experimental
+ *
+ * Components specified by various Technical Specifications.
+ */
+
+#if __cplusplus <= 201103L
+# include <bits/c++14_warning.h>
+#else
+
+#include <utility>
+#include <type_traits>
+#include <stdexcept>
+#include <new>
+#include <initializer_list>
+#include <bits/functexcept.h>
+#include <bits/functional_hash.h>
+#include <bits/enable_special_members.h>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+namespace experimental
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ /**
+ * @defgroup optional Optional values
+ * @ingroup experimental
+ *
+ * Class template for optional values and surrounding facilities, as
+ * described in n3793 "A proposal to add a utility class to represent
+ * optional objects (Revision 5)".
+ *
+ * @{
+ */
+
+ // All subsequent [X.Y.n] references are against n3793.
+
+ // [X.Y.4]
+ template<typename _Tp>
+ class optional;
+
+ // [X.Y.5]
+ /// Tag type for in-place construction.
+ struct in_place_t { };
+
+ /// Tag for in-place construction.
+ constexpr in_place_t in_place { };
+
+ // [X.Y.6]
+ /// Tag type to disengage optional objects.
+ struct nullopt_t
+ {
+ // Do not user-declare default constructor at all for
+ // optional_value = {} syntax to work.
+ // nullopt_t() = delete;
+
+ // Used for constructing nullopt.
+ enum class _Construct { _Token };
+
+ // Must be constexpr for nullopt_t to be literal.
+ explicit constexpr nullopt_t(_Construct) { }
+ };
+
+ // [X.Y.6]
+ /// Tag to disengage optional objects.
+ constexpr nullopt_t nullopt { nullopt_t::_Construct::_Token };
+
+ // [X.Y.7]
+ /**
+ * @brief Exception class thrown when a disengaged optional object is
+ * dereferenced.
+ * @ingroup exceptions
+ */
+ class bad_optional_access : public logic_error
+ {
+ public:
+ // XXX Should not be inline
+ explicit bad_optional_access(const string& __arg) : logic_error(__arg) { }
+
+ explicit bad_optional_access(const char* __arg) : logic_error(__arg) { }
+
+ virtual ~bad_optional_access() noexcept = default;
+ };
+
+ void
+ __throw_bad_optional_access(const char*)
+ __attribute__((__noreturn__));
+
+ // XXX Does not belong here.
+ inline void
+ __throw_bad_optional_access(const char* __s)
+ { _GLIBCXX_THROW_OR_ABORT(bad_optional_access(__s)); }
+
+ template<typename _Tp, typename _Sfinae = void>
+ struct _Has_addressof_impl : std::false_type { };
+
+ template<typename _Tp>
+ struct _Has_addressof_impl<_Tp,
+ decltype( std::declval<const _Tp&>().operator&(), void() )>
+ : std::true_type { };
+
+ /**
+ * @brief Trait that detects the presence of an overloaded unary operator&.
+ *
+ * Practically speaking this detects the presence of such an operator when
+ * called on a const-qualified lvalue (i.e.
+ * declval<_Tp * const&>().operator&()).
+ */
+ template<typename _Tp>
+ struct _Has_addressof : _Has_addressof_impl<_Tp>::type { };
+
+ /**
+ * @brief An overload that attempts to take the address of an lvalue as a
+ * constant expression. Falls back to __addressof in the presence of an
+ * overloaded addressof operator (unary operator&), in which case the call
+ * will not be a constant expression.
+ */
+ template<typename _Tp, typename enable_if<!_Has_addressof<_Tp>::value,
+ int>::type...>
+ constexpr _Tp* __constexpr_addressof(_Tp& __t)
+ { return &__t; }
+
+ /**
+ * @brief Fallback overload that defers to __addressof.
+ */
+ template<typename _Tp, typename enable_if<_Has_addressof<_Tp>::value,
+ int>::type...>
+ inline _Tp* __constexpr_addressof(_Tp& __t)
+ { return std::__addressof(__t); }
+
+ /**
+ * @brief Class template that holds the necessary state for @ref optional
+ * and that has the responsibility for construction and the special members.
+ *
+ * Such a separate base class template is necessary in order to
+ * conditionally enable the special members (e.g. copy/move constructors).
+ * Note that this means that @ref _Optional_base implements the
+ * functionality for copy and move assignment, but not for converting
+ * assignment.
+ *
+ * @see optional, _Enable_special_members
+ */
+ template<typename _Tp, bool _ShouldProvideDestructor =
+ !is_trivially_destructible<_Tp>::value>
+ class _Optional_base
+ {
+ private:
+ // Remove const to avoid prohibition of reusing object storage for
+ // const-qualified types in [3.8/9]. This is strictly internal
+ // and even optional itself is oblivious to it.
+ using _Stored_type = typename remove_const<_Tp>::type;
+
+ public:
+ // [X.Y.4.1] Constructors.
+
+ // Constructors for disengaged optionals.
+ constexpr _Optional_base() noexcept
+ : _M_empty{} { }
+
+ constexpr _Optional_base(nullopt_t) noexcept
+ : _Optional_base{} { }
+
+ // Constructors for engaged optionals.
+ constexpr _Optional_base(const _Tp& __t)
+ : _M_payload(__t), _M_engaged(true) { }
+
+ constexpr _Optional_base(_Tp&& __t)
+ : _M_payload(std::move(__t)), _M_engaged(true) { }
+
+ template<typename... _Args>
+ constexpr explicit _Optional_base(in_place_t, _Args&&... __args)
+ : _M_payload(std::forward<_Args>(__args)...), _M_engaged(true) { }
+
+ template<typename _Up, typename... _Args,
+ typename enable_if<is_constructible<_Tp,
+ initializer_list<_Up>&,
+ _Args&&...>::value,
+ int>::type...>
+ constexpr explicit _Optional_base(in_place_t,
+ initializer_list<_Up> __il,
+ _Args&&... __args)
+ : _M_payload(__il, std::forward<_Args>(__args)...),
+ _M_engaged(true) { }
+
+ // Copy and move constructors.
+ _Optional_base(const _Optional_base& __other)
+ {
+ if (__other._M_engaged)
+ this->_M_construct(__other._M_get());
+ }
+
+ _Optional_base(_Optional_base&& __other)
+ noexcept(is_nothrow_move_constructible<_Tp>())
+ {
+ if (__other._M_engaged)
+ this->_M_construct(std::move(__other._M_get()));
+ }
+
+ // [X.Y.4.3] (partly) Assignment.
+ _Optional_base&
+ operator=(const _Optional_base& __other)
+ {
+ if (this->_M_engaged && __other._M_engaged)
+ this->_M_get() = __other._M_get();
+ else
+ {
+ if (__other._M_engaged)
+ this->_M_construct(__other._M_get());
+ else
+ this->_M_reset();
+ }
+
+ return *this;
+ }
+
+ _Optional_base&
+ operator=(_Optional_base&& __other)
+ noexcept(__and_<is_nothrow_move_constructible<_Tp>,
+ is_nothrow_move_assignable<_Tp>>())
+ {
+ if (this->_M_engaged && __other._M_engaged)
+ this->_M_get() = std::move(__other._M_get());
+ else
+ {
+ if (__other._M_engaged)
+ this->_M_construct(std::move(__other._M_get()));
+ else
+ this->_M_reset();
+ }
+ return *this;
+ }
+
+ // [X.Y.4.2] Destructor.
+ ~_Optional_base()
+ {
+ if (this->_M_engaged)
+ this->_M_payload.~_Stored_type();
+ }
+
+ // The following functionality is also needed by optional, hence the
+ // protected accessibility.
+ protected:
+ constexpr bool _M_is_engaged() const noexcept
+ { return this->_M_engaged; }
+
+ // The _M_get operations have _M_engaged as a precondition.
+ _Tp&
+ _M_get() noexcept
+ { return _M_payload; }
+
+ constexpr const _Tp&
+ _M_get() const noexcept
+ { return _M_payload; }
+
+ // The _M_construct operation has !_M_engaged as a precondition
+ // while _M_destruct has _M_engaged as a precondition.
+ template<typename... _Args>
+ void
+ _M_construct(_Args&&... __args)
+ noexcept(is_nothrow_constructible<_Stored_type, _Args...>())
+ {
+ ::new (std::__addressof(this->_M_payload))
+ _Stored_type(std::forward<_Args>(__args)...);
+ this->_M_engaged = true;
+ }
+
+ void
+ _M_destruct()
+ {
+ this->_M_engaged = false;
+ this->_M_payload.~_Stored_type();
+ }
+
+ // _M_reset is a 'safe' operation with no precondition.
+ void
+ _M_reset()
+ {
+ if (this->_M_engaged)
+ this->_M_destruct();
+ }
+
+ private:
+ struct _Empty_byte { };
+ union {
+ _Empty_byte _M_empty;
+ _Stored_type _M_payload;
+ };
+ bool _M_engaged = false;
+ };
+
+ /// Partial specialization that is exactly identical to the primary template
+ /// save for not providing a destructor, to fulfill triviality requirements.
+ template<typename _Tp>
+ class _Optional_base<_Tp, false>
+ {
+ private:
+ using _Stored_type = typename remove_const<_Tp>::type;
+
+ public:
+ constexpr _Optional_base() noexcept
+ : _M_empty{} { }
+
+ constexpr _Optional_base(nullopt_t) noexcept
+ : _Optional_base{} { }
+
+ constexpr _Optional_base(const _Tp& __t)
+ : _M_payload(__t), _M_engaged(true) { }
+
+ constexpr _Optional_base(_Tp&& __t)
+ : _M_payload(std::move(__t)), _M_engaged(true) { }
+
+ template<typename... _Args>
+ constexpr explicit _Optional_base(in_place_t, _Args&&... __args)
+ : _M_payload(std::forward<_Args>(__args)...), _M_engaged(true) { }
+
+ template<typename _Up, typename... _Args,
+ typename enable_if<is_constructible<_Tp,
+ initializer_list<_Up>&,
+ _Args&&...>::value,
+ int>::type...>
+ constexpr explicit _Optional_base(in_place_t,
+ initializer_list<_Up> __il,
+ _Args&&... __args)
+ : _M_payload(__il, std::forward<_Args>(__args)...),
+ _M_engaged(true) { }
+
+ _Optional_base(const _Optional_base& __other)
+ {
+ if (__other._M_engaged)
+ this->_M_construct(__other._M_get());
+ }
+
+ _Optional_base(_Optional_base&& __other)
+ noexcept(is_nothrow_move_constructible<_Tp>())
+ {
+ if (__other._M_engaged)
+ this->_M_construct(std::move(__other._M_get()));
+ }
+
+ _Optional_base&
+ operator=(const _Optional_base& __other)
+ {
+ if (this->_M_engaged && __other._M_engaged)
+ this->_M_get() = __other._M_get();
+ else
+ {
+ if (__other._M_engaged)
+ this->_M_construct(__other._M_get());
+ else
+ this->_M_reset();
+ }
+ return *this;
+ }
+
+ _Optional_base&
+ operator=(_Optional_base&& __other)
+ noexcept(__and_<is_nothrow_move_constructible<_Tp>,
+ is_nothrow_move_assignable<_Tp>>())
+ {
+ if (this->_M_engaged && __other._M_engaged)
+ this->_M_get() = std::move(__other._M_get());
+ else
+ {
+ if (__other._M_engaged)
+ this->_M_construct(std::move(__other._M_get()));
+ else
+ this->_M_reset();
+ }
+ return *this;
+ }
+
+ // Sole difference
+ // ~_Optional_base() noexcept = default;
+
+ protected:
+ constexpr bool _M_is_engaged() const noexcept
+ { return this->_M_engaged; }
+
+ _Tp&
+ _M_get() noexcept
+ { return _M_payload; }
+
+ constexpr const _Tp&
+ _M_get() const noexcept
+ { return _M_payload; }
+
+ template<typename... _Args>
+ void
+ _M_construct(_Args&&... __args)
+ noexcept(is_nothrow_constructible<_Stored_type, _Args...>())
+ {
+ ::new (std::__addressof(this->_M_payload))
+ _Stored_type(std::forward<_Args>(__args)...);
+ this->_M_engaged = true;
+ }
+
+ void
+ _M_destruct()
+ {
+ this->_M_engaged = false;
+ this->_M_payload.~_Stored_type();
+ }
+
+ void
+ _M_reset()
+ {
+ if (this->_M_engaged)
+ this->_M_destruct();
+ }
+
+ private:
+ struct _Empty_byte { };
+ union
+ {
+ _Empty_byte _M_empty;
+ _Stored_type _M_payload;
+ };
+ bool _M_engaged = false;
+ };
+
+ /**
+ * @brief Class template for optional values.
+ */
+ template<typename _Tp>
+ class optional
+ : private _Optional_base<_Tp>,
+ private _Enable_copy_move<
+ // Copy constructor.
+ is_copy_constructible<_Tp>::value,
+ // Copy assignment.
+ __and_<is_copy_constructible<_Tp>, is_copy_assignable<_Tp>>::value,
+ // Move constructor.
+ is_move_constructible<_Tp>::value,
+ // Move assignment.
+ __and_<is_move_constructible<_Tp>, is_move_assignable<_Tp>>::value,
+ // Unique tag type.
+ optional<_Tp>>
+ {
+ static_assert(__and_<__not_<is_same<typename remove_cv<_Tp>::type,
+ nullopt_t>>,
+ __not_<is_same<typename remove_cv<_Tp>::type,
+ in_place_t>>,
+ __not_<is_reference<_Tp>>>(),
+ "Invalid instantiation of optional<T>");
+
+ private:
+ using _Base = _Optional_base<_Tp>;
+
+ public:
+ using value_type = _Tp;
+
+ // _Optional_base has the responsibility for construction.
+ using _Base::_Base;
+
+ // [X.Y.4.3] (partly) Assignment.
+ optional&
+ operator=(nullopt_t) noexcept
+ {
+ this->_M_reset();
+ return *this;
+ }
+
+ template<typename _Up>
+ typename enable_if<
+ is_same<_Tp, typename decay<_Up>::type>::value,
+ optional&
+ >::type
+ operator=(_Up&& __u)
+ {
+ static_assert(__and_<is_constructible<_Tp, _Up>,
+ is_assignable<_Tp&, _Up>>(),
+ "Cannot assign to value type from argument");
+
+ if (this->_M_is_engaged())
+ this->_M_get() = std::forward<_Up>(__u);
+ else
+ this->_M_construct(std::forward<_Up>(__u));
+
+ return *this;
+ }
+
+ template<typename... _Args>
+ void
+ emplace(_Args&&... __args)
+ {
+ static_assert(is_constructible<_Tp, _Args&&...>(),
+ "Cannot emplace value type from arguments");
+
+ this->_M_reset();
+ this->_M_construct(std::forward<_Args>(__args)...);
+ }
+
+ template<typename _Up, typename... _Args>
+ typename enable_if<
+ is_constructible<_Tp,
+ initializer_list<_Up>&,
+ _Args&&...>::value
+ >::type
+ emplace(initializer_list<_Up> __il, _Args&&... __args)
+ {
+ this->_M_reset();
+ this->_M_construct(__il, std::forward<_Args>(__args)...);
+ }
+
+ // [X.Y.4.2] Destructor is implicit, implemented in _Optional_base.
+
+ // [X.Y.4.4] Swap.
+ void
+ swap(optional& __other)
+ noexcept(is_nothrow_move_constructible<_Tp>()
+ && noexcept(swap(declval<_Tp&>(), declval<_Tp&>())))
+ {
+ using std::swap;
+
+ if (this->_M_is_engaged() && __other._M_is_engaged())
+ swap(this->_M_get(), __other._M_get());
+ else if (this->_M_is_engaged())
+ {
+ __other._M_construct(std::move(this->_M_get()));
+ this->_M_destruct();
+ }
+ else if (__other._M_is_engaged())
+ {
+ this->_M_construct(std::move(__other._M_get()));
+ __other._M_destruct();
+ }
+ }
+
+ // [X.Y.4.5] Observers.
+ constexpr const _Tp*
+ operator->() const
+ { return __constexpr_addressof(this->_M_get()); }
+
+ _Tp*
+ operator->()
+ { return std::__addressof(this->_M_get()); }
+
+ constexpr const _Tp&
+ operator*() const
+ { return this->_M_get(); }
+
+ _Tp&
+ operator*()
+ { return this->_M_get(); }
+
+ constexpr explicit operator bool() const noexcept
+ { return this->_M_is_engaged(); }
+
+ constexpr const _Tp&
+ value() const
+ {
+ return this->_M_is_engaged()
+ ? this->_M_get()
+ : (__throw_bad_optional_access("Attempt to access value of a "
+ "disengaged optional object"),
+ this->_M_get());
+ }
+
+ _Tp&
+ value()
+ {
+ if (this->_M_is_engaged())
+ return this->_M_get();
+
+ __throw_bad_optional_access("Attempt to access value of a "
+ "disengaged optional object");
+ }
+
+ template<typename _Up>
+ constexpr _Tp
+ value_or(_Up&& __u) const&
+ {
+ static_assert(__and_<is_copy_constructible<_Tp>,
+ is_convertible<_Up&&, _Tp>>(),
+ "Cannot return value");
+
+ return this->_M_is_engaged()
+ ? this->_M_get()
+ : static_cast<_Tp>(std::forward<_Up>(__u));
+ }
+
+ template<typename _Up>
+ _Tp
+ value_or(_Up&& __u) &&
+ {
+ static_assert(__and_<is_move_constructible<_Tp>,
+ is_convertible<_Up&&, _Tp>>(),
+ "Cannot return value" );
+
+ return this->_M_is_engaged()
+ ? std::move(this->_M_get())
+ : static_cast<_Tp>(std::forward<_Up>(__u));
+ }
+ };
+
+ // [X.Y.8] Comparisons between optional values.
+ template<typename _Tp>
+ constexpr bool
+ operator==(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
+ {
+ return static_cast<bool>(__lhs) == static_cast<bool>(__rhs)
+ && (!__lhs || *__lhs == *__rhs);
+ }
+
+ template<typename _Tp>
+ constexpr bool
+ operator!=(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
+ { return !(__lhs == __rhs); }
+
+ template<typename _Tp>
+ constexpr bool
+ operator<(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
+ {
+ return static_cast<bool>(__rhs) && (!__lhs || *__lhs < *__rhs);
+ }
+
+ template<typename _Tp>
+ constexpr bool
+ operator>(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
+ { return __rhs < __lhs; }
+
+ template<typename _Tp>
+ constexpr bool
+ operator<=(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
+ { return !(__rhs < __lhs); }
+
+ template<typename _Tp>
+ constexpr bool
+ operator>=(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
+ { return !(__lhs < __rhs); }
+
+ // [X.Y.9] Comparisons with nullopt.
+ template<typename _Tp>
+ constexpr bool
+ operator==(const optional<_Tp>& __lhs, nullopt_t) noexcept
+ { return !__lhs; }
+
+ template<typename _Tp>
+ constexpr bool
+ operator==(nullopt_t, const optional<_Tp>& __rhs) noexcept
+ { return !__rhs; }
+
+ template<typename _Tp>
+ constexpr bool
+ operator!=(const optional<_Tp>& __lhs, nullopt_t) noexcept
+ { return static_cast<bool>(__lhs); }
+
+ template<typename _Tp>
+ constexpr bool
+ operator!=(nullopt_t, const optional<_Tp>& __rhs) noexcept
+ { return static_cast<bool>(__rhs); }
+
+ template<typename _Tp>
+ constexpr bool
+ operator<(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept
+ { return false; }
+
+ template<typename _Tp>
+ constexpr bool
+ operator<(nullopt_t, const optional<_Tp>& __rhs) noexcept
+ { return static_cast<bool>(__rhs); }
+
+ template<typename _Tp>
+ constexpr bool
+ operator>(const optional<_Tp>& __lhs, nullopt_t) noexcept
+ { return static_cast<bool>(__lhs); }
+
+ template<typename _Tp>
+ constexpr bool
+ operator>(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept
+ { return false; }
+
+ template<typename _Tp>
+ constexpr bool
+ operator<=(const optional<_Tp>& __lhs, nullopt_t) noexcept
+ { return !__lhs; }
+
+ template<typename _Tp>
+ constexpr bool
+ operator<=(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept
+ { return true; }
+
+ template<typename _Tp>
+ constexpr bool
+ operator>=(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept
+ { return true; }
+
+ template<typename _Tp>
+ constexpr bool
+ operator>=(nullopt_t, const optional<_Tp>& __rhs) noexcept
+ { return !__rhs; }
+
+ // [X.Y.10] Comparisons with value type.
+ template<typename _Tp>
+ constexpr bool
+ operator==(const optional<_Tp>& __lhs, const _Tp& __rhs)
+ { return __lhs && *__lhs == __rhs; }
+
+ template<typename _Tp>
+ constexpr bool
+ operator==(const _Tp& __lhs, const optional<_Tp>& __rhs)
+ { return __rhs && __lhs == *__rhs; }
+
+ template<typename _Tp>
+ constexpr bool
+ operator!=(const optional<_Tp>& __lhs, _Tp const& __rhs)
+ { return !__lhs || *__lhs != __rhs; }
+
+ template<typename _Tp>
+ constexpr bool
+ operator!=(const _Tp& __lhs, const optional<_Tp>& __rhs)
+ { return !__rhs || __lhs != *__rhs; }
+
+ template<typename _Tp>
+ constexpr bool
+ operator<(const optional<_Tp>& __lhs, const _Tp& __rhs)
+ { return !__lhs || *__lhs < __rhs; }
+
+ template<typename _Tp>
+ constexpr bool
+ operator<(const _Tp& __lhs, const optional<_Tp>& __rhs)
+ { return __rhs && __lhs < *__rhs; }
+
+ template<typename _Tp>
+ constexpr bool
+ operator>(const optional<_Tp>& __lhs, const _Tp& __rhs)
+ { return __lhs && __rhs < *__lhs; }
+
+ template<typename _Tp>
+ constexpr bool
+ operator>(const _Tp& __lhs, const optional<_Tp>& __rhs)
+ { return !__rhs || *__rhs < __lhs; }
+
+ template<typename _Tp>
+ constexpr bool
+ operator<=(const optional<_Tp>& __lhs, const _Tp& __rhs)
+ { return !__lhs || !(__rhs < *__lhs); }
+
+ template<typename _Tp>
+ constexpr bool
+ operator<=(const _Tp& __lhs, const optional<_Tp>& __rhs)
+ { return __rhs && !(*__rhs < __lhs); }
+
+ template<typename _Tp>
+ constexpr bool
+ operator>=(const optional<_Tp>& __lhs, const _Tp& __rhs)
+ { return __lhs && !(*__lhs < __rhs); }
+
+ template<typename _Tp>
+ constexpr bool
+ operator>=(const _Tp& __lhs, const optional<_Tp>& __rhs)
+ { return !__rhs || !(__lhs < *__rhs); }
+
+ // [X.Y.11]
+ template<typename _Tp>
+ inline void
+ swap(optional<_Tp>& __lhs, optional<_Tp>& __rhs)
+ noexcept(noexcept(__lhs.swap(__rhs)))
+ { __lhs.swap(__rhs); }
+
+ template<typename _Tp>
+ constexpr optional<typename decay<_Tp>::type>
+ make_optional(_Tp&& __t)
+ { return optional<typename decay<_Tp>::type> { std::forward<_Tp>(__t) }; }
+
+ // @} group optional
+_GLIBCXX_END_NAMESPACE_VERSION
+}
+
+ // [X.Y.12]
+ template<typename _Tp>
+ struct hash<experimental::optional<_Tp>>
+ {
+ using result_type = size_t;
+ using argument_type = experimental::optional<_Tp>;
+
+ size_t
+ operator()(const experimental::optional<_Tp>& __t) const
+ noexcept(noexcept(hash<_Tp> {}(*__t)))
+ {
+ // We pick an arbitrary hash for disengaged optionals which hopefully
+ // usual values of _Tp won't typically hash to.
+ constexpr size_t __magic_disengaged_hash = static_cast<size_t>(-3333);
+ return __t ? hash<_Tp> {}(*__t) : __magic_disengaged_hash;
+ }
+ };
+}
+
+#endif // C++14
+
+#endif // _GLIBCXX_EXPERIMENTAL_OPTIONAL
diff --git a/libstdc++-v3/include/ext/vstring.h b/libstdc++-v3/include/ext/vstring.h
index bd93c803c23..8eb8597c804 100644
--- a/libstdc++-v3/include/ext/vstring.h
+++ b/libstdc++-v3/include/ext/vstring.h
@@ -85,7 +85,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_check(size_type __pos, const char* __s) const
{
if (__pos > this->size())
- std::__throw_out_of_range(__N(__s));
+ std::__throw_out_of_range_fmt(__N("%s: __pos (which is %zu) > "
+ "this->size() (which is %zu)"),
+ __s, __pos, this->size());
return __pos;
}
@@ -575,7 +577,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
at(size_type __n) const
{
if (__n >= this->size())
- std::__throw_out_of_range(__N("__versa_string::at"));
+ std::__throw_out_of_range_fmt(__N("__versa_string::at: __n "
+ "(which is %zu) >= this->size() "
+ "(which is %zu)"),
+ __n, this->size());
return this->_M_data()[__n];
}
@@ -594,7 +599,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
at(size_type __n)
{
if (__n >= this->size())
- std::__throw_out_of_range(__N("__versa_string::at"));
+ std::__throw_out_of_range_fmt(__N("__versa_string::at: __n "
+ "(which is %zu) >= this->size() "
+ "(which is %zu)"),
+ __n, this->size());
this->_M_leak();
return this->_M_data()[__n];
}
diff --git a/libstdc++-v3/include/parallel/algo.h b/libstdc++-v3/include/parallel/algo.h
index 00c24e5638c..13a35a7e046 100644
--- a/libstdc++-v3/include/parallel/algo.h
+++ b/libstdc++-v3/include/parallel/algo.h
@@ -150,7 +150,9 @@ namespace __parallel
if (_GLIBCXX_PARALLEL_CONDITION(true))
{
- std::binder2nd<__gnu_parallel::_EqualTo<_ValueType, const _Tp&> >
+ __gnu_parallel::__binder2nd<__gnu_parallel::_EqualTo<_ValueType,
+ const _Tp&>,
+ _ValueType, const _Tp&, bool>
__comp(__gnu_parallel::_EqualTo<_ValueType, const _Tp&>(), __val);
return __gnu_parallel::__find_template(
__begin, __end, __begin, __comp,
diff --git a/libstdc++-v3/include/parallel/algobase.h b/libstdc++-v3/include/parallel/algobase.h
index e3737cc8f70..1acb63e921b 100644
--- a/libstdc++-v3/include/parallel/algobase.h
+++ b/libstdc++-v3/include/parallel/algobase.h
@@ -94,17 +94,13 @@ namespace __parallel
inline pair<_IIter1, _IIter2>
mismatch(_IIter1 __begin1, _IIter1 __end1, _IIter2 __begin2)
{
- typedef std::iterator_traits<_IIter1> _Iterator1Traits;
- typedef std::iterator_traits<_IIter2> _Iterator2Traits;
- typedef typename _Iterator1Traits::value_type _ValueType1;
- typedef typename _Iterator2Traits::value_type _ValueType2;
- typedef typename _Iterator1Traits::iterator_category _IteratorCategory1;
- typedef typename _Iterator2Traits::iterator_category _IteratorCategory2;
-
- typedef __gnu_parallel::_EqualTo<_ValueType1, _ValueType2> _EqualTo;
+ typedef __gnu_parallel::_EqualTo<
+ typename std::iterator_traits<_IIter1>::value_type,
+ typename std::iterator_traits<_IIter2>::value_type> _EqualTo;
return __mismatch_switch(__begin1, __end1, __begin2, _EqualTo(),
- _IteratorCategory1(), _IteratorCategory2());
+ std::__iterator_category(__begin1),
+ std::__iterator_category(__begin2));
}
// Public interface
@@ -113,14 +109,94 @@ namespace __parallel
mismatch(_IIter1 __begin1, _IIter1 __end1, _IIter2 __begin2,
_Predicate __pred)
{
- typedef std::iterator_traits<_IIter1> _Iterator1Traits;
- typedef std::iterator_traits<_IIter2> _Iterator2Traits;
- typedef typename _Iterator1Traits::iterator_category _IteratorCategory1;
- typedef typename _Iterator2Traits::iterator_category _IteratorCategory2;
-
return __mismatch_switch(__begin1, __end1, __begin2, __pred,
- _IteratorCategory1(), _IteratorCategory2());
+ std::__iterator_category(__begin1),
+ std::__iterator_category(__begin2));
+ }
+
+#if __cplusplus > 201103L
+ // Sequential fallback.
+ template<typename _InputIterator1, typename _InputIterator2>
+ inline pair<_InputIterator1, _InputIterator2>
+ mismatch(_InputIterator1 __first1, _InputIterator1 __last1,
+ _InputIterator2 __first2, _InputIterator2 __last2,
+ __gnu_parallel::sequential_tag)
+ { return _GLIBCXX_STD_A::mismatch(__first1, __last1, __first2, __last2); }
+
+ // Sequential fallback.
+ template<typename _InputIterator1, typename _InputIterator2,
+ typename _BinaryPredicate>
+ inline pair<_InputIterator1, _InputIterator2>
+ mismatch(_InputIterator1 __first1, _InputIterator1 __last1,
+ _InputIterator2 __first2, _InputIterator2 __last2,
+ _BinaryPredicate __binary_pred,
+ __gnu_parallel::sequential_tag)
+ {
+ return _GLIBCXX_STD_A::mismatch(__first1, __last1, __first2, __last2,
+ __binary_pred);
+ }
+
+ // Sequential fallback for input iterator case
+ template<typename _IIter1, typename _IIter2,
+ typename _Predicate, typename _IteratorTag1, typename _IteratorTag2>
+ inline pair<_IIter1, _IIter2>
+ __mismatch_switch(_IIter1 __begin1, _IIter1 __end1,
+ _IIter2 __begin2, _IIter2 __end2, _Predicate __pred,
+ _IteratorTag1, _IteratorTag2)
+ {
+ return _GLIBCXX_STD_A::mismatch(__begin1, __end1,
+ __begin2, __end2, __pred);
+ }
+
+ // Parallel mismatch for random access iterators
+ template<typename _RAIter1, typename _RAIter2, typename _Predicate>
+ pair<_RAIter1, _RAIter2>
+ __mismatch_switch(_RAIter1 __begin1, _RAIter1 __end1,
+ _RAIter2 __begin2, _RAIter2 __end2, _Predicate __pred,
+ random_access_iterator_tag, random_access_iterator_tag)
+ {
+ if (_GLIBCXX_PARALLEL_CONDITION(true))
+ {
+ if ((__end2 - __begin2) < (__end1 - __begin1))
+ __end1 = __begin1 + (__end2 - __begin2);
+
+ _RAIter1 __res =
+ __gnu_parallel::__find_template(__begin1, __end1, __begin2, __pred,
+ __gnu_parallel::
+ __mismatch_selector()).first;
+ return make_pair(__res , __begin2 + (__res - __begin1));
+ }
+ else
+ return _GLIBCXX_STD_A::mismatch(__begin1, __end1,
+ __begin2, __end2, __pred);
+ }
+
+ template<typename _IIter1, typename _IIter2>
+ inline pair<_IIter1, _IIter2>
+ mismatch(_IIter1 __begin1, _IIter1 __end1, _IIter2 __begin2, _IIter2 __end2)
+ {
+ typedef __gnu_parallel::_EqualTo<
+ typename std::iterator_traits<_IIter1>::value_type,
+ typename std::iterator_traits<_IIter2>::value_type> _EqualTo;
+
+ return __mismatch_switch(__begin1, __end1, __begin2, __end2, _EqualTo(),
+ std::__iterator_category(__begin1),
+ std::__iterator_category(__begin2));
+ }
+
+ template<typename _InputIterator1, typename _InputIterator2,
+ typename _BinaryPredicate>
+ inline pair<_InputIterator1, _InputIterator2>
+ mismatch(_InputIterator1 __begin1, _InputIterator1 __end1,
+ _InputIterator2 __begin2, _InputIterator2 __end2,
+ _BinaryPredicate __binary_pred)
+ {
+ return __mismatch_switch(__begin1, __end1, __begin2, __end2,
+ __binary_pred,
+ std::__iterator_category(__begin1),
+ std::__iterator_category(__begin2));
}
+#endif
// Sequential fallback
template<typename _IIter1, typename _IIter2>
@@ -155,6 +231,84 @@ namespace __parallel
== __end1;
}
+#if __cplusplus > 201103L
+ // Sequential fallback
+ template<typename _IIter1, typename _IIter2>
+ inline bool
+ equal(_IIter1 __begin1, _IIter1 __end1, _IIter2 __begin2, _IIter2 __end2,
+ __gnu_parallel::sequential_tag)
+ {
+ return _GLIBCXX_STD_A::equal(__begin1, __end1, __begin2, __end2);
+ }
+
+ // Sequential fallback
+ template<typename _IIter1, typename _IIter2, typename _BinaryPredicate>
+ inline bool
+ equal(_IIter1 __begin1, _IIter1 __end1,
+ _IIter2 __begin2, _IIter2 __end2, _BinaryPredicate __binary_pred,
+ __gnu_parallel::sequential_tag)
+ {
+ return _GLIBCXX_STD_A::equal(__begin1, __end1, __begin2, __end2,
+ __binary_pred);
+ }
+
+ // Sequential fallback for input iterator case
+ template<typename _IIter1, typename _IIter2,
+ typename _Predicate, typename _IteratorTag1, typename _IteratorTag2>
+ inline bool
+ __equal_switch(_IIter1 __begin1, _IIter1 __end1,
+ _IIter2 __begin2, _IIter2 __end2, _Predicate __pred,
+ _IteratorTag1, _IteratorTag2)
+ {
+ return _GLIBCXX_STD_A::equal(__begin1, __end1,
+ __begin2, __end2, __pred);
+ }
+
+ // Parallel equal for random access iterators
+ template<typename _RAIter1, typename _RAIter2, typename _Predicate>
+ inline bool
+ __equal_switch(_RAIter1 __begin1, _RAIter1 __end1,
+ _RAIter2 __begin2, _RAIter2 __end2, _Predicate __pred,
+ random_access_iterator_tag, random_access_iterator_tag)
+ {
+ if (_GLIBCXX_PARALLEL_CONDITION(true))
+ {
+ if (std::distance(__begin1, __end1)
+ != std::distance(__begin2, __end2))
+ return false;
+
+ return __gnu_parallel::mismatch(__begin1, __end1, __begin2, __end2,
+ __pred).first == __end1;
+ }
+ else
+ return _GLIBCXX_STD_A::equal(__begin1, __end1,
+ __begin2, __end2, __pred);
+ }
+
+ template<typename _IIter1, typename _IIter2>
+ inline bool
+ equal(_IIter1 __begin1, _IIter1 __end1, _IIter2 __begin2, _IIter2 __end2)
+ {
+ typedef __gnu_parallel::_EqualTo<
+ typename std::iterator_traits<_IIter1>::value_type,
+ typename std::iterator_traits<_IIter2>::value_type> _EqualTo;
+
+ return __equal_switch(__begin1, __end1, __begin2, __end2, _EqualTo(),
+ std::__iterator_category(__begin1),
+ std::__iterator_category(__begin2));
+ }
+
+ template<typename _IIter1, typename _IIter2, typename _BinaryPredicate>
+ inline bool
+ equal(_IIter1 __begin1, _IIter1 __end1,
+ _IIter2 __begin2, _IIter2 __end2, _BinaryPredicate __binary_pred)
+ {
+ return __equal_switch(__begin1, __end1, __begin2, __end2, __binary_pred,
+ std::__iterator_category(__begin1),
+ std::__iterator_category(__begin2));
+ }
+#endif
+
// Sequential fallback
template<typename _IIter1, typename _IIter2>
inline bool
diff --git a/libstdc++-v3/include/profile/array b/libstdc++-v3/include/profile/array
index 33bdc952096..138ad311ed7 100644
--- a/libstdc++-v3/include/profile/array
+++ b/libstdc++-v3/include/profile/array
@@ -138,7 +138,10 @@ namespace __profile
at(size_type __n)
{
if (__n >= _Nm)
- std::__throw_out_of_range(__N("array::at"));
+ std::__throw_out_of_range_fmt(__N("array::at: __n "
+ "(which is %zu) >= _Nm "
+ "(which is %zu)"),
+ __n, _Nm);
return _AT_Type::_S_ref(_M_elems, __n);
}
@@ -148,7 +151,9 @@ namespace __profile
// Result of conditional expression must be an lvalue so use
// boolean ? lvalue : (throw-expr, lvalue)
return __n < _Nm ? _AT_Type::_S_ref(_M_elems, __n)
- : (std::__throw_out_of_range(__N("array::at")),
+ : (std::__throw_out_of_range_fmt(__N("array::at: __n (which is %zu) "
+ ">= _Nm (which is %zu)"),
+ __n, _Nm),
_AT_Type::_S_ref(_M_elems, 0));
}
diff --git a/libstdc++-v3/include/profile/deque b/libstdc++-v3/include/profile/deque
index c46618e27e4..52d474d4c11 100644
--- a/libstdc++-v3/include/profile/deque
+++ b/libstdc++-v3/include/profile/deque
@@ -117,7 +117,7 @@ namespace __profile
#if __cplusplus >= 201103L
deque&
- operator=(deque&& __x)
+ operator=(deque&& __x) noexcept
{
// NB: DR 1204.
// NB: DR 675.
@@ -245,13 +245,13 @@ namespace __profile
// element access:
reference
- operator[](size_type __n)
+ operator[](size_type __n) _GLIBCXX_NOEXCEPT
{
return _M_base()[__n];
}
const_reference
- operator[](size_type __n) const
+ operator[](size_type __n) const _GLIBCXX_NOEXCEPT
{
return _M_base()[__n];
}
@@ -259,25 +259,25 @@ namespace __profile
using _Base::at;
reference
- front()
+ front() _GLIBCXX_NOEXCEPT
{
return _Base::front();
}
const_reference
- front() const
+ front() const _GLIBCXX_NOEXCEPT
{
return _Base::front();
}
reference
- back()
+ back() _GLIBCXX_NOEXCEPT
{
return _Base::back();
}
const_reference
- back() const
+ back() const _GLIBCXX_NOEXCEPT
{
return _Base::back();
}
@@ -375,13 +375,13 @@ namespace __profile
#endif
void
- pop_front()
+ pop_front() _GLIBCXX_NOEXCEPT
{
_Base::pop_front();
}
void
- pop_back()
+ pop_back() _GLIBCXX_NOEXCEPT
{
_Base::pop_back();
}
@@ -409,7 +409,7 @@ namespace __profile
}
void
- swap(deque& __x)
+ swap(deque& __x) _GLIBCXX_NOEXCEPT
{
_Base::swap(__x);
}
diff --git a/libstdc++-v3/include/profile/iterator_tracker.h b/libstdc++-v3/include/profile/iterator_tracker.h
index 251eff7355f..c016f20db8b 100644
--- a/libstdc++-v3/include/profile/iterator_tracker.h
+++ b/libstdc++-v3/include/profile/iterator_tracker.h
@@ -56,13 +56,14 @@ namespace __profile
typedef typename _Traits::reference reference;
typedef typename _Traits::pointer pointer;
- __iterator_tracker()
+ __iterator_tracker() _GLIBCXX_NOEXCEPT
: _M_current(), _M_ds(0) { }
- __iterator_tracker(const _Iterator& __i, const _Sequence* __seq)
+ __iterator_tracker(const _Iterator& __i, const _Sequence* __seq)
+ _GLIBCXX_NOEXCEPT
: _M_current(__i), _M_ds(__seq) { }
- __iterator_tracker(const __iterator_tracker& __x)
+ __iterator_tracker(const __iterator_tracker& __x) _GLIBCXX_NOEXCEPT
: _M_current(__x._M_current), _M_ds(__x._M_ds) { }
template<typename _MutableIterator>
@@ -70,23 +71,23 @@ namespace __profile
typename __gnu_cxx::__enable_if
<(std::__are_same<_MutableIterator, typename
_Sequence::iterator::_Base_iterator>::__value),
- _Sequence>::__type>& __x)
+ _Sequence>::__type>& __x) _GLIBCXX_NOEXCEPT
: _M_current(__x.base()), _M_ds(__x._M_get_sequence()) { }
_Iterator
- base() const { return _M_current; }
+ base() const _GLIBCXX_NOEXCEPT { return _M_current; }
/**
* @brief Conversion to underlying non-debug iterator to allow
* better interaction with non-profile containers.
*/
- operator _Iterator() const { return _M_current; }
+ operator _Iterator() const _GLIBCXX_NOEXCEPT { return _M_current; }
pointer
- operator->() const { return &*_M_current; }
+ operator->() const _GLIBCXX_NOEXCEPT { return &*_M_current; }
__iterator_tracker&
- operator++()
+ operator++() _GLIBCXX_NOEXCEPT
{
_M_ds->_M_profile_iterate();
++_M_current;
@@ -94,7 +95,7 @@ namespace __profile
}
__iterator_tracker
- operator++(int)
+ operator++(int) _GLIBCXX_NOEXCEPT
{
_M_ds->_M_profile_iterate();
__iterator_tracker __tmp(*this);
@@ -103,7 +104,7 @@ namespace __profile
}
__iterator_tracker&
- operator--()
+ operator--() _GLIBCXX_NOEXCEPT
{
_M_ds->_M_profile_iterate(1);
--_M_current;
@@ -111,7 +112,7 @@ namespace __profile
}
__iterator_tracker
- operator--(int)
+ operator--(int) _GLIBCXX_NOEXCEPT
{
_M_ds->_M_profile_iterate(1);
__iterator_tracker __tmp(*this);
@@ -120,30 +121,30 @@ namespace __profile
}
__iterator_tracker&
- operator=(const __iterator_tracker& __x)
+ operator=(const __iterator_tracker& __x) _GLIBCXX_NOEXCEPT
{
_M_current = __x._M_current;
return *this;
}
reference
- operator*() const
+ operator*() const _GLIBCXX_NOEXCEPT
{ return *_M_current; }
// ------ Random access iterator requirements ------
reference
- operator[](const difference_type& __n) const
+ operator[](const difference_type& __n) const _GLIBCXX_NOEXCEPT
{ return _M_current[__n]; }
__iterator_tracker&
- operator+=(const difference_type& __n)
+ operator+=(const difference_type& __n) _GLIBCXX_NOEXCEPT
{
_M_current += __n;
return *this;
}
__iterator_tracker
- operator+(const difference_type& __n) const
+ operator+(const difference_type& __n) const _GLIBCXX_NOEXCEPT
{
__iterator_tracker __tmp(*this);
__tmp += __n;
@@ -151,14 +152,14 @@ namespace __profile
}
__iterator_tracker&
- operator-=(const difference_type& __n)
+ operator-=(const difference_type& __n) _GLIBCXX_NOEXCEPT
{
_M_current += -__n;
return *this;
}
__iterator_tracker
- operator-(const difference_type& __n) const
+ operator-(const difference_type& __n) const _GLIBCXX_NOEXCEPT
{
__iterator_tracker __tmp(*this);
__tmp -= __n;
@@ -178,72 +179,84 @@ namespace __profile
inline bool
operator==(const __iterator_tracker<_IteratorL, _Sequence>& __lhs,
const __iterator_tracker<_IteratorR, _Sequence>& __rhs)
+ _GLIBCXX_NOEXCEPT
{ return __lhs.base() == __rhs.base(); }
template<typename _Iterator, typename _Sequence>
inline bool
operator==(const __iterator_tracker<_Iterator, _Sequence>& __lhs,
const __iterator_tracker<_Iterator, _Sequence>& __rhs)
+ _GLIBCXX_NOEXCEPT
{ return __lhs.base() == __rhs.base(); }
template<typename _IteratorL, typename _IteratorR, typename _Sequence>
inline bool
operator!=(const __iterator_tracker<_IteratorL, _Sequence>& __lhs,
const __iterator_tracker<_IteratorR, _Sequence>& __rhs)
+ _GLIBCXX_NOEXCEPT
{ return __lhs.base() != __rhs.base(); }
template<typename _Iterator, typename _Sequence>
inline bool
operator!=(const __iterator_tracker<_Iterator, _Sequence>& __lhs,
const __iterator_tracker<_Iterator, _Sequence>& __rhs)
+ _GLIBCXX_NOEXCEPT
{ return __lhs.base() != __rhs.base(); }
template<typename _IteratorL, typename _IteratorR, typename _Sequence>
inline bool
operator<(const __iterator_tracker<_IteratorL, _Sequence>& __lhs,
const __iterator_tracker<_IteratorR, _Sequence>& __rhs)
+ _GLIBCXX_NOEXCEPT
{ return __lhs.base() < __rhs.base(); }
template<typename _Iterator, typename _Sequence>
inline bool
operator<(const __iterator_tracker<_Iterator, _Sequence>& __lhs,
const __iterator_tracker<_Iterator, _Sequence>& __rhs)
+ _GLIBCXX_NOEXCEPT
{ return __lhs.base() < __rhs.base(); }
template<typename _IteratorL, typename _IteratorR, typename _Sequence>
inline bool
operator<=(const __iterator_tracker<_IteratorL, _Sequence>& __lhs,
const __iterator_tracker<_IteratorR, _Sequence>& __rhs)
+ _GLIBCXX_NOEXCEPT
{ return __lhs.base() <= __rhs.base(); }
template<typename _Iterator, typename _Sequence>
inline bool
operator<=(const __iterator_tracker<_Iterator, _Sequence>& __lhs,
const __iterator_tracker<_Iterator, _Sequence>& __rhs)
+ _GLIBCXX_NOEXCEPT
{ return __lhs.base() <= __rhs.base(); }
template<typename _IteratorL, typename _IteratorR, typename _Sequence>
inline bool
operator>(const __iterator_tracker<_IteratorL, _Sequence>& __lhs,
const __iterator_tracker<_IteratorR, _Sequence>& __rhs)
+ _GLIBCXX_NOEXCEPT
{ return __lhs.base() > __rhs.base(); }
template<typename _Iterator, typename _Sequence>
inline bool
operator>(const __iterator_tracker<_Iterator, _Sequence>& __lhs,
const __iterator_tracker<_Iterator, _Sequence>& __rhs)
+ _GLIBCXX_NOEXCEPT
{ return __lhs.base() > __rhs.base(); }
template<typename _IteratorL, typename _IteratorR, typename _Sequence>
inline bool
operator>=(const __iterator_tracker<_IteratorL, _Sequence>& __lhs,
const __iterator_tracker<_IteratorR, _Sequence>& __rhs)
+ _GLIBCXX_NOEXCEPT
{ return __lhs.base() >= __rhs.base(); }
template<typename _Iterator, typename _Sequence>
inline bool
operator>=(const __iterator_tracker<_Iterator, _Sequence>& __lhs,
const __iterator_tracker<_Iterator, _Sequence>& __rhs)
+ _GLIBCXX_NOEXCEPT
{ return __lhs.base() >= __rhs.base(); }
// _GLIBCXX_RESOLVE_LIB_DEFECTS
@@ -254,12 +267,14 @@ namespace __profile
inline typename __iterator_tracker<_IteratorL, _Sequence>::difference_type
operator-(const __iterator_tracker<_IteratorL, _Sequence>& __lhs,
const __iterator_tracker<_IteratorR, _Sequence>& __rhs)
+ _GLIBCXX_NOEXCEPT
{ return __lhs.base() - __rhs.base(); }
template<typename _Iterator, typename _Sequence>
inline typename __iterator_tracker<_Iterator, _Sequence>::difference_type
operator-(const __iterator_tracker<_Iterator, _Sequence>& __lhs,
const __iterator_tracker<_Iterator, _Sequence>& __rhs)
+ _GLIBCXX_NOEXCEPT
{ return __lhs.base() - __rhs.base(); }
template<typename _Iterator, typename _Sequence>
@@ -267,6 +282,7 @@ namespace __profile
operator+(typename __iterator_tracker<_Iterator,_Sequence>::difference_type
__n,
const __iterator_tracker<_Iterator, _Sequence>& __i)
+ _GLIBCXX_NOEXCEPT
{ return __i + __n; }
} // namespace __profile
diff --git a/libstdc++-v3/include/std/array b/libstdc++-v3/include/std/array
index 86e8aee14ba..673d0e4b18d 100644
--- a/libstdc++-v3/include/std/array
+++ b/libstdc++-v3/include/std/array
@@ -180,7 +180,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
at(size_type __n)
{
if (__n >= _Nm)
- std::__throw_out_of_range(__N("array::at"));
+ std::__throw_out_of_range_fmt(__N("array::at: __n (which is %zu) "
+ ">= _Nm (which is %zu)"),
+ __n, _Nm);
return _AT_Type::_S_ref(_M_elems, __n);
}
@@ -190,7 +192,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
// Result of conditional expression must be an lvalue so use
// boolean ? lvalue : (throw-expr, lvalue)
return __n < _Nm ? _AT_Type::_S_ref(_M_elems, __n)
- : (std::__throw_out_of_range(__N("array::at")),
+ : (std::__throw_out_of_range_fmt(__N("array::at: __n (which is %zu) "
+ ">= _Nm (which is %zu)"),
+ __n, _Nm),
_AT_Type::_S_ref(_M_elems, 0));
}
diff --git a/libstdc++-v3/include/std/bitset b/libstdc++-v3/include/std/bitset
index 1da6baf332f..708a434af9e 100644
--- a/libstdc++-v3/include/std/bitset
+++ b/libstdc++-v3/include/std/bitset
@@ -752,6 +752,26 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
typedef _Base_bitset<_GLIBCXX_BITSET_WORDS(_Nb)> _Base;
typedef unsigned long _WordT;
+ template<class _CharT, class _Traits, class _Alloc>
+ void
+ _M_check_initial_position(const std::basic_string<_CharT, _Traits, _Alloc>& __s,
+ size_t __position) const
+ {
+ if (__position > __s.size())
+ __throw_out_of_range_fmt(__N("bitset::bitset: __position "
+ "(which is %zu) > __s.size() "
+ "(which is %zu)"),
+ __position, __s.size());
+ }
+
+ void _M_check(size_t __position, const char *__s) const
+ {
+ if (__position >= _Nb)
+ __throw_out_of_range_fmt(__N("%s: __position (which is %zu) "
+ ">= _Nb (which is %zu)"),
+ __s, __position, _Nb);
+ }
+
void
_M_do_sanitize() _GLIBCXX_NOEXCEPT
{
@@ -867,9 +887,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
size_t __position = 0)
: _Base()
{
- if (__position > __s.size())
- __throw_out_of_range(__N("bitset::bitset initial position "
- "not valid"));
+ _M_check_initial_position(__s, __position);
_M_copy_from_string(__s, __position,
std::basic_string<_CharT, _Traits, _Alloc>::npos,
_CharT('0'), _CharT('1'));
@@ -890,9 +908,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
size_t __position, size_t __n)
: _Base()
{
- if (__position > __s.size())
- __throw_out_of_range(__N("bitset::bitset initial position "
- "not valid"));
+ _M_check_initial_position(__s, __position);
_M_copy_from_string(__s, __position, __n, _CharT('0'), _CharT('1'));
}
@@ -904,9 +920,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_CharT __zero, _CharT __one = _CharT('1'))
: _Base()
{
- if (__position > __s.size())
- __throw_out_of_range(__N("bitset::bitset initial position "
- "not valid"));
+ _M_check_initial_position(__s, __position);
_M_copy_from_string(__s, __position, __n, __zero, __one);
}
@@ -1067,8 +1081,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
bitset<_Nb>&
set(size_t __position, bool __val = true)
{
- if (__position >= _Nb)
- __throw_out_of_range(__N("bitset::set"));
+ this->_M_check(__position, __N("bitset::set"));
return _Unchecked_set(__position, __val);
}
@@ -1092,8 +1105,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
bitset<_Nb>&
reset(size_t __position)
{
- if (__position >= _Nb)
- __throw_out_of_range(__N("bitset::reset"));
+ this->_M_check(__position, __N("bitset::reset"));
return _Unchecked_reset(__position);
}
@@ -1116,8 +1128,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
bitset<_Nb>&
flip(size_t __position)
{
- if (__position >= _Nb)
- __throw_out_of_range(__N("bitset::flip"));
+ this->_M_check(__position, __N("bitset::flip"));
return _Unchecked_flip(__position);
}
@@ -1302,8 +1313,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
bool
test(size_t __position) const
{
- if (__position >= _Nb)
- __throw_out_of_range(__N("bitset::test"));
+ this->_M_check(__position, __N("bitset::test"));
return _Unchecked_test(__position);
}
diff --git a/libstdc++-v3/include/std/chrono b/libstdc++-v3/include/std/chrono
index d5ef984279d..b4ccca985ef 100644
--- a/libstdc++-v3/include/std/chrono
+++ b/libstdc++-v3/include/std/chrono
@@ -524,22 +524,22 @@ _GLIBCXX_END_NAMESPACE_VERSION
{ return !(__lhs < __rhs); }
/// nanoseconds
- typedef duration<int64_t, nano> nanoseconds;
+ typedef duration<int64_t, nano> nanoseconds;
/// microseconds
- typedef duration<int64_t, micro> microseconds;
+ typedef duration<int64_t, micro> microseconds;
/// milliseconds
- typedef duration<int64_t, milli> milliseconds;
+ typedef duration<int64_t, milli> milliseconds;
/// seconds
- typedef duration<int64_t> seconds;
+ typedef duration<int64_t> seconds;
/// minutes
- typedef duration<int, ratio< 60>> minutes;
+ typedef duration<int64_t, ratio< 60>> minutes;
/// hours
- typedef duration<int, ratio<3600>> hours;
+ typedef duration<int64_t, ratio<3600>> hours;
/// time_point
template<typename _Clock, typename _Dur>
@@ -810,14 +810,14 @@ _GLIBCXX_END_NAMESPACE_VERSION
} // __select_type
constexpr chrono::duration<long double, ratio<3600,1>>
- operator"" h(long double __hours)
+ operator""h(long double __hours)
{ return chrono::duration<long double, ratio<3600,1>>{__hours}; }
template <char... _Digits>
constexpr typename
__select_type::_Select_type<__select_int::_Select_int<_Digits...>::value,
chrono::hours>::type
- operator"" h()
+ operator""h()
{
return __select_type::_Select_type<
__select_int::_Select_int<_Digits...>::value,
@@ -825,14 +825,14 @@ _GLIBCXX_END_NAMESPACE_VERSION
}
constexpr chrono::duration<long double, ratio<60,1>>
- operator"" min(long double __mins)
+ operator""min(long double __mins)
{ return chrono::duration<long double, ratio<60,1>>{__mins}; }
template <char... _Digits>
constexpr typename
__select_type::_Select_type<__select_int::_Select_int<_Digits...>::value,
chrono::minutes>::type
- operator"" min()
+ operator""min()
{
return __select_type::_Select_type<
__select_int::_Select_int<_Digits...>::value,
@@ -840,14 +840,14 @@ _GLIBCXX_END_NAMESPACE_VERSION
}
constexpr chrono::duration<long double>
- operator"" s(long double __secs)
+ operator""s(long double __secs)
{ return chrono::duration<long double>{__secs}; }
template <char... _Digits>
constexpr typename
__select_type::_Select_type<__select_int::_Select_int<_Digits...>::value,
chrono::seconds>::type
- operator"" s()
+ operator""s()
{
return __select_type::_Select_type<
__select_int::_Select_int<_Digits...>::value,
@@ -855,14 +855,14 @@ _GLIBCXX_END_NAMESPACE_VERSION
}
constexpr chrono::duration<long double, milli>
- operator"" ms(long double __msecs)
+ operator""ms(long double __msecs)
{ return chrono::duration<long double, milli>{__msecs}; }
template <char... _Digits>
constexpr typename
__select_type::_Select_type<__select_int::_Select_int<_Digits...>::value,
chrono::milliseconds>::type
- operator"" ms()
+ operator""ms()
{
return __select_type::_Select_type<
__select_int::_Select_int<_Digits...>::value,
@@ -870,14 +870,14 @@ _GLIBCXX_END_NAMESPACE_VERSION
}
constexpr chrono::duration<long double, micro>
- operator"" us(long double __usecs)
+ operator""us(long double __usecs)
{ return chrono::duration<long double, micro>{__usecs}; }
template <char... _Digits>
constexpr typename
__select_type::_Select_type<__select_int::_Select_int<_Digits...>::value,
chrono::microseconds>::type
- operator"" us()
+ operator""us()
{
return __select_type::_Select_type<
__select_int::_Select_int<_Digits...>::value,
@@ -885,14 +885,14 @@ _GLIBCXX_END_NAMESPACE_VERSION
}
constexpr chrono::duration<long double, nano>
- operator"" ns(long double __nsecs)
+ operator""ns(long double __nsecs)
{ return chrono::duration<long double, nano>{__nsecs}; }
template <char... _Digits>
constexpr typename
__select_type::_Select_type<__select_int::_Select_int<_Digits...>::value,
chrono::nanoseconds>::type
- operator"" ns()
+ operator""ns()
{
return __select_type::_Select_type<
__select_int::_Select_int<_Digits...>::value,
diff --git a/libstdc++-v3/include/std/complex b/libstdc++-v3/include/std/complex
index 58edb4f54dd..ff04ae6425e 100644
--- a/libstdc++-v3/include/std/complex
+++ b/libstdc++-v3/include/std/complex
@@ -1924,6 +1924,40 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
conj(_Tp __x)
{ return __x; }
+#if __cplusplus > 201103L
+
+inline namespace literals {
+inline namespace complex_literals {
+
+ constexpr std::complex<float>
+ operator""if(long double __num)
+ { return std::complex<float>{0.0F, static_cast<float>(__num)}; }
+
+ constexpr std::complex<float>
+ operator""if(unsigned long long __num)
+ { return std::complex<float>{0.0F, static_cast<float>(__num)}; }
+
+ constexpr std::complex<double>
+ operator""i(long double __num)
+ { return std::complex<double>{0.0, static_cast<double>(__num)}; }
+
+ constexpr std::complex<double>
+ operator""i(unsigned long long __num)
+ { return std::complex<double>{0.0, static_cast<double>(__num)}; }
+
+ constexpr std::complex<long double>
+ operator""il(long double __num)
+ { return std::complex<long double>{0.0L, __num}; }
+
+ constexpr std::complex<long double>
+ operator""il(unsigned long long __num)
+ { return std::complex<long double>{0.0L, static_cast<long double>(__num)}; }
+
+} // inline namespace complex_literals
+} // inline namespace literals
+
+#endif // C++14
+
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace
diff --git a/libstdc++-v3/include/std/functional b/libstdc++-v3/include/std/functional
index 63ba77793fd..eaa4509a420 100644
--- a/libstdc++-v3/include/std/functional
+++ b/libstdc++-v3/include/std/functional
@@ -1932,7 +1932,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
template<typename _Tp>
static bool
- _M_not_empty_function(const _Tp*& __fp)
+ _M_not_empty_function(_Tp* const& __fp)
{ return __fp; }
template<typename _Class, typename _Tp>
@@ -2128,6 +2128,10 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
}
};
+ template<typename _From, typename _To>
+ using __check_func_return_type
+ = __or_<is_void<_To>, is_convertible<_From, _To>>;
+
/**
* @brief Primary class template for std::function.
* @ingroup functors
@@ -2145,16 +2149,8 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type)
using _Invoke = decltype(__callable_functor(std::declval<_Functor&>())
(std::declval<_ArgTypes>()...) );
- template<typename _CallRes, typename _Res1>
- struct _CheckResult
- : is_convertible<_CallRes, _Res1> { };
-
- template<typename _CallRes>
- struct _CheckResult<_CallRes, void>
- : true_type { };
-
template<typename _Functor>
- using _Callable = _CheckResult<_Invoke<_Functor>, _Res>;
+ using _Callable = __check_func_return_type<_Invoke<_Functor>, _Res>;
template<typename _Cond, typename _Tp>
using _Requires = typename enable_if<_Cond::value, _Tp>::type;
diff --git a/libstdc++-v3/include/std/mutex b/libstdc++-v3/include/std/mutex
index 40b2e31dc7f..da2ca0cfe94 100644
--- a/libstdc++-v3/include/std/mutex
+++ b/libstdc++-v3/include/std/mutex
@@ -203,21 +203,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
class __timed_mutex_impl
{
protected:
-#ifdef _GLIBCXX_USE_CLOCK_MONOTONIC
- typedef chrono::steady_clock __clock_t;
-#else
typedef chrono::high_resolution_clock __clock_t;
-#endif
template<typename _Rep, typename _Period>
bool
_M_try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
{
- auto __rt = chrono::duration_cast<__clock_t::duration>(__rtime);
- if (ratio_greater<__clock_t::period, _Period>())
+ using chrono::steady_clock;
+ auto __rt = chrono::duration_cast<steady_clock::duration>(__rtime);
+ if (ratio_greater<steady_clock::period, _Period>())
++__rt;
-
- return _M_try_lock_until(__clock_t::now() + __rt);
+ return _M_try_lock_until(steady_clock::now() + __rt);
}
template<typename _Duration>
@@ -225,11 +221,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_try_lock_until(const chrono::time_point<__clock_t,
_Duration>& __atime)
{
- chrono::time_point<__clock_t, chrono::seconds> __s =
- chrono::time_point_cast<chrono::seconds>(__atime);
-
- chrono::nanoseconds __ns =
- chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
+ auto __s = chrono::time_point_cast<chrono::seconds>(__atime);
+ auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
__gthread_time_t __ts = {
static_cast<std::time_t>(__s.time_since_epoch().count()),
@@ -243,7 +236,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Clock, typename _Duration>
bool
_M_try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
- { return _M_try_lock_for(__atime - _Clock::now()); }
+ {
+ auto __rtime = __atime - _Clock::now();
+ return _M_try_lock_until(__clock_t::now() + __rtime);
+ }
};
/// timed_mutex
diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple
index 063ce02e9c7..2580f7894e6 100644
--- a/libstdc++-v3/include/std/tuple
+++ b/libstdc++-v3/include/std/tuple
@@ -917,27 +917,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
<typename std::remove_reference<_Tp>::type>::type>::type
{ };
- // Stores a tuple of indices. Also used by bind() to extract the elements
- // in a tuple.
- template<std::size_t... _Indexes>
- struct _Index_tuple
- {
- typedef _Index_tuple<_Indexes..., sizeof...(_Indexes)> __next;
- };
-
- // Builds an _Index_tuple<0, 1, 2, ..., _Num-1>.
- template<std::size_t _Num>
- struct _Build_index_tuple
- {
- typedef typename _Build_index_tuple<_Num - 1>::__type::__next __type;
- };
-
- template<>
- struct _Build_index_tuple<0>
- {
- typedef _Index_tuple<> __type;
- };
-
template<std::size_t, typename, typename, std::size_t>
struct __make_tuple_impl;
diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index eef9df6998c..3239564c64e 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -1438,6 +1438,31 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
add_const<typename add_volatile<_Tp>::type>::type type;
};
+#if __cplusplus > 201103L
+ /// Alias template for remove_const
+ template<typename _Tp>
+ using remove_const_t = typename remove_const<_Tp>::type;
+
+ /// Alias template for remove_volatile
+ template<typename _Tp>
+ using remove_volatile_t = typename remove_volatile<_Tp>::type;
+
+ /// Alias template for remove_cv
+ template<typename _Tp>
+ using remove_cv_t = typename remove_cv<_Tp>::type;
+
+ /// Alias template for add_const
+ template<typename _Tp>
+ using add_const_t = typename add_const<_Tp>::type;
+
+ /// Alias template for add_volatile
+ template<typename _Tp>
+ using add_volatile_t = typename add_volatile<_Tp>::type;
+
+ /// Alias template for add_cv
+ template<typename _Tp>
+ using add_cv_t = typename add_cv<_Tp>::type;
+#endif
// Reference transformations.
@@ -1482,6 +1507,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: public __add_rvalue_reference_helper<_Tp>
{ };
+#if __cplusplus > 201103L
+ /// Alias template for remove_reference
+ template<typename _Tp>
+ using remove_reference_t = typename remove_reference<_Tp>::type;
+
+ /// Alias template for add_lvalue_reference
+ template<typename _Tp>
+ using add_lvalue_reference_t = typename add_lvalue_reference<_Tp>::type;
+
+ /// Alias template for add_rvalue_reference
+ template<typename _Tp>
+ using add_rvalue_reference_t = typename add_rvalue_reference<_Tp>::type;
+#endif
// Sign modifications.
@@ -1679,6 +1717,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<>
struct make_signed<bool>;
+#if __cplusplus > 201103L
+ /// Alias template for make_signed
+ template<typename _Tp>
+ using make_signed_t = typename make_signed<_Tp>::type;
+
+ /// Alias template for make_unsigned
+ template<typename _Tp>
+ using make_unsigned_t = typename make_unsigned<_Tp>::type;
+#endif
// Array modifications.
@@ -1708,6 +1755,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
struct remove_all_extents<_Tp[]>
{ typedef typename remove_all_extents<_Tp>::type type; };
+#if __cplusplus > 201103L
+ /// Alias template for remove_extent
+ template<typename _Tp>
+ using remove_extent_t = typename remove_extent<_Tp>::type;
+
+ /// Alias template for remove_all_extents
+ template<typename _Tp>
+ using remove_all_extents_t = typename remove_all_extents<_Tp>::type;
+#endif
// Pointer modifications.
@@ -1740,6 +1796,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: public __add_pointer_helper<_Tp>
{ };
+#if __cplusplus > 201103L
+ /// Alias template for remove_pointer
+ template<typename _Tp>
+ using remove_pointer_t = typename remove_pointer<_Tp>::type;
+
+ /// Alias template for add_pointer
+ template<typename _Tp>
+ using add_pointer_t = typename add_pointer<_Tp>::type;
+#endif
template<std::size_t _Len>
struct __aligned_storage_msa
@@ -2102,6 +2167,37 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>::type
{ };
+#if __cplusplus > 201103L
+ /// Alias template for aligned_storage
+ template<size_t _Len, size_t _Align =
+ __alignof__(typename __aligned_storage_msa<_Len>::__type)>
+ using aligned_storage_t = typename aligned_storage<_Len, _Align>::type;
+
+ /// Alias template for decay
+ template<typename _Tp>
+ using decay_t = typename decay<_Tp>::type;
+
+ /// Alias template for enable_if
+ template<bool _Cond, typename _Tp = void>
+ using enable_if_t = typename enable_if<_Cond, _Tp>::type;
+
+ /// Alias template for conditional
+ template<bool _Cond, typename _Iftrue, typename _Iffalse>
+ using conditional_t = typename conditional<_Cond, _Iftrue, _Iffalse>::type;
+
+ /// Alias template for common_type
+ template<typename... _Tp>
+ using common_type_t = typename common_type<_Tp...>::type;
+
+ /// Alias template for underlying_type
+ template<typename _Tp>
+ using underlying_type_t = typename underlying_type<_Tp>::type;
+
+ /// Alias template for result_of
+ template<typename _Tp>
+ using result_of_t = typename result_of<_Tp>::type;
+#endif
+
/// @} group metaprogramming
/**
diff --git a/libstdc++-v3/include/std/utility b/libstdc++-v3/include/std/utility
index ad30ad7a9a3..627f79b9cf1 100644
--- a/libstdc++-v3/include/std/utility
+++ b/libstdc++-v3/include/std/utility
@@ -194,6 +194,67 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
#endif
+ // Stores a tuple of indices. Used by tuple and pair, and by bind() to
+ // extract the elements in a tuple.
+ template<size_t... _Indexes>
+ struct _Index_tuple
+ {
+ typedef _Index_tuple<_Indexes..., sizeof...(_Indexes)> __next;
+ };
+
+ // Builds an _Index_tuple<0, 1, 2, ..., _Num-1>.
+ template<size_t _Num>
+ struct _Build_index_tuple
+ {
+ typedef typename _Build_index_tuple<_Num - 1>::__type::__next __type;
+ };
+
+ template<>
+ struct _Build_index_tuple<0>
+ {
+ typedef _Index_tuple<> __type;
+ };
+
+#if __cplusplus > 201103L
+ /// Class template integer_sequence
+ template<typename _Tp, _Tp... _Idx>
+ struct integer_sequence
+ {
+ typedef _Tp value_type;
+ static constexpr size_t size() { return sizeof...(_Idx); }
+ };
+
+ template<typename _Tp, _Tp _Num,
+ typename _ISeq = typename _Build_index_tuple<_Num>::__type>
+ struct _Make_integer_sequence;
+
+ template<typename _Tp, _Tp _Num, size_t... _Idx>
+ struct _Make_integer_sequence<_Tp, _Num, _Index_tuple<_Idx...>>
+ {
+ static_assert( _Num >= 0,
+ "Cannot make integer sequence of negative length" );
+
+ typedef integer_sequence<_Tp, static_cast<_Tp>(_Idx)...> __type;
+ };
+
+ /// Alias template make_integer_sequence
+ template<typename _Tp, _Tp _Num>
+ using make_integer_sequence
+ = typename _Make_integer_sequence<_Tp, _Num>::__type;
+
+ /// Alias template index_sequence
+ template<size_t... _Idx>
+ using index_sequence = integer_sequence<size_t, _Idx...>;
+
+ /// Alias template make_index_sequence
+ template<size_t _Num>
+ using make_index_sequence = make_integer_sequence<size_t, _Num>;
+
+ /// Alias template index_sequence_for
+ template<typename... _Types>
+ using index_sequence_for = make_index_sequence<sizeof...(_Types)>;
+#endif
+
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace
diff --git a/libstdc++-v3/include/std/vector b/libstdc++-v3/include/std/vector
index a01c5e72c8d..00cf8bbfd05 100644
--- a/libstdc++-v3/include/std/vector
+++ b/libstdc++-v3/include/std/vector
@@ -33,7 +33,7 @@
* that both that copyright notice and this permission notice appear
* in supporting documentation. Hewlett-Packard Company makes no
* representations about the suitability of this software for any
- ded "as is" without express or implied warranty.
+ * purpose. It is provided "as is" without express or implied warranty.
*
*
* Copyright (c) 1996
diff --git a/libstdc++-v3/include/tr2/dynamic_bitset b/libstdc++-v3/include/tr2/dynamic_bitset
index ebe9dc28095..7d4d39256e6 100644
--- a/libstdc++-v3/include/tr2/dynamic_bitset
+++ b/libstdc++-v3/include/tr2/dynamic_bitset
@@ -137,7 +137,12 @@ public:
if (__nbits % _S_bits_per_block > 0)
++__sz;
if (__sz != this->_M_w.size())
- this->_M_w.resize(__sz);
+ {
+ block_type __val = 0;
+ if (__value)
+ __val = std::numeric_limits<block_type>::max();
+ this->_M_w.resize(__sz, __val);
+ }
}
allocator_type
@@ -246,7 +251,7 @@ public:
bool
_M_is_equal(const __dynamic_bitset_base& __x) const
{
- if (__x.size() == this->size())
+ if (__x._M_w.size() == this->_M_w.size())
{
for (size_t __i = 0; __i < this->_M_w.size(); ++__i)
if (this->_M_w[__i] != __x._M_w[__i])
@@ -260,7 +265,7 @@ public:
bool
_M_is_less(const __dynamic_bitset_base& __x) const
{
- if (__x.size() == this->size())
+ if (__x._M_w.size() == this->_M_w.size())
{
for (size_t __i = this->_M_w.size(); __i > 0; --__i)
{
@@ -282,7 +287,7 @@ public:
if (_M_w[__i] != ~static_cast<block_type>(0))
return 0;
return ((this->_M_w.size() - 1) * _S_bits_per_block
- + __builtin_popcountl(this->_M_hiword()));
+ + __builtin_popcountll(this->_M_hiword()));
}
bool
@@ -297,9 +302,9 @@ public:
bool
_M_is_subset_of(const __dynamic_bitset_base& __b)
{
- if (__b.size() == this->size())
+ if (__b._M_w.size() == this->_M_w.size())
{
- for (size_t __i = 0; __i < _M_w.size(); ++__i)
+ for (size_t __i = 0; __i < this->_M_w.size(); ++__i)
if (this->_M_w[__i] != (this->_M_w[__i] | __b._M_w[__i]))
return false;
return true;
@@ -327,7 +332,7 @@ public:
{
size_t __result = 0;
for (size_t __i = 0; __i < this->_M_w.size(); ++__i)
- __result += __builtin_popcountl(this->_M_w[__i]);
+ __result += __builtin_popcountll(this->_M_w[__i]);
return __result;
}
@@ -364,140 +369,6 @@ public:
}
};
- // Definitions of non-inline functions from __dynamic_bitset_base.
- template<typename _WordT, typename _Alloc>
- void
- __dynamic_bitset_base<_WordT, _Alloc>::_M_do_left_shift(size_t __shift)
- {
- if (__builtin_expect(__shift != 0, 1))
- {
- const size_t __wshift = __shift / _S_bits_per_block;
- const size_t __offset = __shift % _S_bits_per_block;
-
- if (__offset == 0)
- for (size_t __n = this->_M_w.size() - 1; __n >= __wshift; --__n)
- this->_M_w[__n] = this->_M_w[__n - __wshift];
- else
- {
- const size_t __sub_offset = _S_bits_per_block - __offset;
- for (size_t __n = _M_w.size() - 1; __n > __wshift; --__n)
- this->_M_w[__n] = ((this->_M_w[__n - __wshift] << __offset)
- | (this->_M_w[__n - __wshift - 1] >> __sub_offset));
- this->_M_w[__wshift] = this->_M_w[0] << __offset;
- }
-
- //// std::fill(this->_M_w.begin(), this->_M_w.begin() + __wshift,
- //// static_cast<_WordT>(0));
- }
- }
-
- template<typename _WordT, typename _Alloc>
- void
- __dynamic_bitset_base<_WordT, _Alloc>::_M_do_right_shift(size_t __shift)
- {
- if (__builtin_expect(__shift != 0, 1))
- {
- const size_t __wshift = __shift / _S_bits_per_block;
- const size_t __offset = __shift % _S_bits_per_block;
- const size_t __limit = this->_M_w.size() - __wshift - 1;
-
- if (__offset == 0)
- for (size_t __n = 0; __n <= __limit; ++__n)
- this->_M_w[__n] = this->_M_w[__n + __wshift];
- else
- {
- const size_t __sub_offset = (_S_bits_per_block
- - __offset);
- for (size_t __n = 0; __n < __limit; ++__n)
- this->_M_w[__n] = ((this->_M_w[__n + __wshift] >> __offset)
- | (this->_M_w[__n + __wshift + 1] << __sub_offset));
- this->_M_w[__limit] = this->_M_w[_M_w.size()-1] >> __offset;
- }
-
- ////std::fill(this->_M_w.begin() + __limit + 1, this->_M_w.end(),
- //// static_cast<_WordT>(0));
- }
- }
-
- template<typename _WordT, typename _Alloc>
- unsigned long
- __dynamic_bitset_base<_WordT, _Alloc>::_M_do_to_ulong() const
- {
- size_t __n = sizeof(unsigned long) / sizeof(block_type);
- for (size_t __i = __n; __i < this->_M_w.size(); ++__i)
- if (this->_M_w[__i])
- __throw_overflow_error(__N("__dynamic_bitset_base::_M_do_to_ulong"));
- unsigned long __res = 0UL;
- for (size_t __i = 0; __i < __n && __i < this->_M_w.size(); ++__i)
- __res += this->_M_w[__i] << (__i * _S_bits_per_block);
- return __res;
- }
-
- template<typename _WordT, typename _Alloc>
- unsigned long long
- __dynamic_bitset_base<_WordT, _Alloc>::_M_do_to_ullong() const
- {
- size_t __n = sizeof(unsigned long long) / sizeof(block_type);
- for (size_t __i = __n; __i < this->_M_w.size(); ++__i)
- if (this->_M_w[__i])
- __throw_overflow_error(__N("__dynamic_bitset_base::_M_do_to_ullong"));
- unsigned long long __res = 0ULL;
- for (size_t __i = 0; __i < __n && __i < this->_M_w.size(); ++__i)
- __res += this->_M_w[__i] << (__i * _S_bits_per_block);
- return __res;
- }
-
- template<typename _WordT, typename _Alloc>
- size_t
- __dynamic_bitset_base<_WordT, _Alloc>
- ::_M_do_find_first(size_t __not_found) const
- {
- for (size_t __i = 0; __i < this->_M_w.size(); ++__i)
- {
- _WordT __thisword = this->_M_w[__i];
- if (__thisword != static_cast<_WordT>(0))
- return (__i * _S_bits_per_block
- + __builtin_ctzl(__thisword));
- }
- // not found, so return an indication of failure.
- return __not_found;
- }
-
- template<typename _WordT, typename _Alloc>
- size_t
- __dynamic_bitset_base<_WordT, _Alloc>
- ::_M_do_find_next(size_t __prev, size_t __not_found) const
- {
- // make bound inclusive
- ++__prev;
-
- // check out of bounds
- if (__prev >= this->_M_w.size() * _S_bits_per_block)
- return __not_found;
-
- // search first word
- size_t __i = _S_whichword(__prev);
- _WordT __thisword = this->_M_w[__i];
-
- // mask off bits below bound
- __thisword &= (~static_cast<_WordT>(0)) << _S_whichbit(__prev);
-
- if (__thisword != static_cast<_WordT>(0))
- return (__i * _S_bits_per_block
- + __builtin_ctzl(__thisword));
-
- // check subsequent words
- for (++__i; __i < this->_M_w.size(); ++__i)
- {
- __thisword = this->_M_w[__i];
- if (__thisword != static_cast<_WordT>(0))
- return (__i * _S_bits_per_block
- + __builtin_ctzl(__thisword));
- }
- // not found, so return an indication of failure.
- return __not_found;
- } // end _M_do_find_next
-
/**
* @brief The %dynamic_bitset class represents a sequence of bits.
*
@@ -594,6 +465,15 @@ public:
this->_M_hiword() &= ~((~static_cast<block_type>(0)) << __shift);
}
+ // Set the unused bits in the uppermost word.
+ void
+ _M_do_fill()
+ {
+ size_type __shift = this->_M_Nb % bits_per_block;
+ if (__shift > 0)
+ this->_M_hiword() |= ((~static_cast<block_type>(0)) << __shift);
+ }
+
/**
* These versions of single-bit set, reset, flip, and test
* do no range checking.
@@ -847,6 +727,8 @@ public:
void
resize(size_type __nbits, bool __value = false)
{
+ if (__value)
+ this->_M_do_fill();
this->_M_resize(__nbits, __value);
this->_M_Nb = __nbits;
this->_M_do_sanitize();
@@ -1240,33 +1122,21 @@ public:
bool
is_proper_subset_of(const dynamic_bitset& __b) const
{ return this->_M_is_proper_subset_of(__b); }
- };
- // Definitions of non-inline member functions.
- template<typename _WordT, typename _Alloc>
- template<typename _CharT, typename _Traits>
- void
- dynamic_bitset<_WordT, _Alloc>::
- _M_copy_from_ptr(const _CharT* __str, size_t __len,
- size_t __pos, size_t __n, _CharT __zero, _CharT __one)
- {
- reset();
- const size_t __nbits = std::min(_M_Nb, std::min(__n, __len - __pos));
- for (size_t __i = __nbits; __i > 0; --__i)
- {
- const _CharT __c = __str[__pos + __nbits - __i];
- if (_Traits::eq(__c, __zero))
- ;
- else if (_Traits::eq(__c, __one))
- _M_unchecked_set(__i - 1);
- else
- __throw_invalid_argument(__N("dynamic_bitset::_M_copy_from_ptr"));
- }
- }
+ friend bool
+ operator==(const dynamic_bitset<_WordT, _Alloc>& __lhs,
+ const dynamic_bitset<_WordT, _Alloc>& __rhs)
+ { return __lhs._M_is_equal(__rhs); }
+
+ friend bool
+ operator<(const dynamic_bitset<_WordT, _Alloc>& __lhs,
+ const dynamic_bitset<_WordT, _Alloc>& __rhs)
+ { return __lhs._M_is_less(__rhs); }
+ };
template<typename _WordT, typename _Alloc>
template<typename _CharT, typename _Traits, typename _Alloc1>
- void
+ inline void
dynamic_bitset<_WordT, _Alloc>::
_M_copy_to_string(std::basic_string<_CharT, _Traits, _Alloc1>& __str,
_CharT __zero, _CharT __one) const
@@ -1280,38 +1150,27 @@ public:
//@{
/// These comparisons for equality/inequality are, well, @e bitwise.
- template<typename _WordT, typename _Alloc>
- bool
- operator==(const dynamic_bitset<_WordT, _Alloc>& __lhs,
- const dynamic_bitset<_WordT, _Alloc>& __rhs)
- { return __lhs._M_is_equal(__rhs); }
template<typename _WordT, typename _Alloc>
- bool
+ inline bool
operator!=(const dynamic_bitset<_WordT, _Alloc>& __lhs,
const dynamic_bitset<_WordT, _Alloc>& __rhs)
- { return !__lhs._M_is_equal(__rhs); }
-
- template<typename _WordT, typename _Alloc>
- bool
- operator<(const dynamic_bitset<_WordT, _Alloc>& __lhs,
- const dynamic_bitset<_WordT, _Alloc>& __rhs)
- { return __lhs._M_is_less(__rhs); }
+ { return !(__lhs == __rhs); }
template<typename _WordT, typename _Alloc>
- bool
+ inline bool
operator<=(const dynamic_bitset<_WordT, _Alloc>& __lhs,
const dynamic_bitset<_WordT, _Alloc>& __rhs)
{ return !(__lhs > __rhs); }
template<typename _WordT, typename _Alloc>
- bool
+ inline bool
operator>(const dynamic_bitset<_WordT, _Alloc>& __lhs,
const dynamic_bitset<_WordT, _Alloc>& __rhs)
{ return __rhs < __lhs; }
template<typename _WordT, typename _Alloc>
- bool
+ inline bool
operator>=(const dynamic_bitset<_WordT, _Alloc>& __lhs,
const dynamic_bitset<_WordT, _Alloc>& __rhs)
{ return !(__lhs < __rhs); }
@@ -1368,8 +1227,9 @@ public:
}
//@}
- //@{
/**
+ * @defgroup Global I/O operators for bitsets.
+ * @{
* @brief Global I/O operators for bitsets.
*
* Direct I/O between streams and bitsets is supported. Output is
@@ -1377,81 +1237,9 @@ public:
* and '1' characters. The %dynamic_bitset will grow as necessary
* to hold the string of bits.
*/
- template<typename _CharT, typename _Traits,
- typename _WordT, typename _Alloc>
- std::basic_istream<_CharT, _Traits>&
- operator>>(std::basic_istream<_CharT, _Traits>& __is,
- dynamic_bitset<_WordT, _Alloc>& __x)
- {
- typedef typename _Traits::char_type char_type;
- typedef std::basic_istream<_CharT, _Traits> __istream_type;
- typedef typename __istream_type::ios_base __ios_base;
-
- std::basic_string<_CharT, _Traits> __tmp;
- __tmp.reserve(__x.size());
-
- const char_type __zero = __is.widen('0');
- const char_type __one = __is.widen('1');
-
- typename __ios_base::iostate __state = __ios_base::goodbit;
- typename __istream_type::sentry __sentry(__is);
- if (__sentry)
- {
- __try
- {
- while (1)
- {
- static typename _Traits::int_type __eof = _Traits::eof();
-
- typename _Traits::int_type __c1 = __is.rdbuf()->sbumpc();
- if (_Traits::eq_int_type(__c1, __eof))
- {
- __state |= __ios_base::eofbit;
- break;
- }
- else
- {
- const char_type __c2 = _Traits::to_char_type(__c1);
- if (_Traits::eq(__c2, __zero))
- __tmp.push_back(__zero);
- else if (_Traits::eq(__c2, __one))
- __tmp.push_back(__one);
- else if (_Traits::
- eq_int_type(__is.rdbuf()->sputbackc(__c2),
- __eof))
- {
- __state |= __ios_base::failbit;
- break;
- }
- else
- break;
- }
- }
- }
- __catch(__cxxabiv1::__forced_unwind&)
- {
- __is._M_setstate(__ios_base::badbit);
- __throw_exception_again;
- }
- __catch(...)
- { __is._M_setstate(__ios_base::badbit); }
- }
-
- __x.resize(__tmp.size());
-
- if (__tmp.empty() && __x.size())
- __state |= __ios_base::failbit;
- else
- __x._M_copy_from_string(__tmp, static_cast<size_t>(0), __x.size(),
- __zero, __one);
- if (__state)
- __is.setstate(__state);
- return __is;
- }
-
template <typename _CharT, typename _Traits,
typename _WordT, typename _Alloc>
- std::basic_ostream<_CharT, _Traits>&
+ inline std::basic_ostream<_CharT, _Traits>&
operator<<(std::basic_ostream<_CharT, _Traits>& __os,
const dynamic_bitset<_WordT, _Alloc>& __x)
{
@@ -1461,12 +1249,14 @@ public:
__x._M_copy_to_string(__tmp, __ct.widen('0'), __ct.widen('1'));
return __os << __tmp;
}
- //@}
+ /**
+ * @}
+ */
_GLIBCXX_END_NAMESPACE_VERSION
} // tr2
} // std
-#undef _GLIBCXX_BITSET_BITS_PER_WORD
+#include <tr2/dynamic_bitset.tcc>
#endif /* _GLIBCXX_TR2_DYNAMIC_BITSET */
diff --git a/libstdc++-v3/include/tr2/dynamic_bitset.tcc b/libstdc++-v3/include/tr2/dynamic_bitset.tcc
new file mode 100644
index 00000000000..02e647acaa5
--- /dev/null
+++ b/libstdc++-v3/include/tr2/dynamic_bitset.tcc
@@ -0,0 +1,286 @@
+// TR2 <dynamic_bitset> -*- C++ -*-
+
+// Copyright (C) 2009-2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// 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/>.
+
+/** @file tr2/dynamic_bitset.tcc
+ * This is an internal header file, included by other library headers.
+ * Do not attempt to use it directly. @headername{tr2/dynamic_bitset}
+ */
+
+#ifndef _GLIBCXX_TR2_DYNAMIC_BITSET_TCC
+#define _GLIBCXX_TR2_DYNAMIC_BITSET_TCC 1
+
+#pragma GCC system_header
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+namespace tr2
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ // Definitions of non-inline functions from __dynamic_bitset_base.
+ template<typename _WordT, typename _Alloc>
+ void
+ __dynamic_bitset_base<_WordT, _Alloc>::_M_do_left_shift(size_t __shift)
+ {
+ if (__builtin_expect(__shift != 0, 1))
+ {
+ const size_t __wshift = __shift / _S_bits_per_block;
+ const size_t __offset = __shift % _S_bits_per_block;
+
+ if (__offset == 0)
+ for (size_t __n = this->_M_w.size() - 1; __n >= __wshift; --__n)
+ this->_M_w[__n] = this->_M_w[__n - __wshift];
+ else
+ {
+ const size_t __sub_offset = _S_bits_per_block - __offset;
+ for (size_t __n = _M_w.size() - 1; __n > __wshift; --__n)
+ this->_M_w[__n] = ((this->_M_w[__n - __wshift] << __offset)
+ | (this->_M_w[__n - __wshift - 1] >> __sub_offset));
+ this->_M_w[__wshift] = this->_M_w[0] << __offset;
+ }
+
+ //// std::fill(this->_M_w.begin(), this->_M_w.begin() + __wshift,
+ //// static_cast<_WordT>(0));
+ }
+ }
+
+ template<typename _WordT, typename _Alloc>
+ void
+ __dynamic_bitset_base<_WordT, _Alloc>::_M_do_right_shift(size_t __shift)
+ {
+ if (__builtin_expect(__shift != 0, 1))
+ {
+ const size_t __wshift = __shift / _S_bits_per_block;
+ const size_t __offset = __shift % _S_bits_per_block;
+ const size_t __limit = this->_M_w.size() - __wshift - 1;
+
+ if (__offset == 0)
+ for (size_t __n = 0; __n <= __limit; ++__n)
+ this->_M_w[__n] = this->_M_w[__n + __wshift];
+ else
+ {
+ const size_t __sub_offset = (_S_bits_per_block
+ - __offset);
+ for (size_t __n = 0; __n < __limit; ++__n)
+ this->_M_w[__n] = ((this->_M_w[__n + __wshift] >> __offset)
+ | (this->_M_w[__n + __wshift + 1] << __sub_offset));
+ this->_M_w[__limit] = this->_M_w[_M_w.size()-1] >> __offset;
+ }
+
+ ////std::fill(this->_M_w.begin() + __limit + 1, this->_M_w.end(),
+ //// static_cast<_WordT>(0));
+ }
+ }
+
+ template<typename _WordT, typename _Alloc>
+ unsigned long
+ __dynamic_bitset_base<_WordT, _Alloc>::_M_do_to_ulong() const
+ {
+ size_t __n = sizeof(unsigned long) / sizeof(block_type);
+ for (size_t __i = __n; __i < this->_M_w.size(); ++__i)
+ if (this->_M_w[__i])
+ __throw_overflow_error(__N("__dynamic_bitset_base::_M_do_to_ulong"));
+ unsigned long __res = 0UL;
+ for (size_t __i = 0; __i < __n && __i < this->_M_w.size(); ++__i)
+ __res += this->_M_w[__i] << (__i * _S_bits_per_block);
+ return __res;
+ }
+
+ template<typename _WordT, typename _Alloc>
+ unsigned long long
+ __dynamic_bitset_base<_WordT, _Alloc>::_M_do_to_ullong() const
+ {
+ size_t __n = sizeof(unsigned long long) / sizeof(block_type);
+ for (size_t __i = __n; __i < this->_M_w.size(); ++__i)
+ if (this->_M_w[__i])
+ __throw_overflow_error(__N("__dynamic_bitset_base::_M_do_to_ullong"));
+ unsigned long long __res = 0ULL;
+ for (size_t __i = 0; __i < __n && __i < this->_M_w.size(); ++__i)
+ __res += this->_M_w[__i] << (__i * _S_bits_per_block);
+ return __res;
+ }
+
+ template<typename _WordT, typename _Alloc>
+ size_t
+ __dynamic_bitset_base<_WordT, _Alloc>
+ ::_M_do_find_first(size_t __not_found) const
+ {
+ for (size_t __i = 0; __i < this->_M_w.size(); ++__i)
+ {
+ _WordT __thisword = this->_M_w[__i];
+ if (__thisword != static_cast<_WordT>(0))
+ return (__i * _S_bits_per_block
+ + __builtin_ctzll(__thisword));
+ }
+ // not found, so return an indication of failure.
+ return __not_found;
+ }
+
+ template<typename _WordT, typename _Alloc>
+ size_t
+ __dynamic_bitset_base<_WordT, _Alloc>
+ ::_M_do_find_next(size_t __prev, size_t __not_found) const
+ {
+ // make bound inclusive
+ ++__prev;
+
+ // check out of bounds
+ if (__prev >= this->_M_w.size() * _S_bits_per_block)
+ return __not_found;
+
+ // search first word
+ size_t __i = _S_whichword(__prev);
+ _WordT __thisword = this->_M_w[__i];
+
+ // mask off bits below bound
+ __thisword &= (~static_cast<_WordT>(0)) << _S_whichbit(__prev);
+
+ if (__thisword != static_cast<_WordT>(0))
+ return (__i * _S_bits_per_block
+ + __builtin_ctzll(__thisword));
+
+ // check subsequent words
+ for (++__i; __i < this->_M_w.size(); ++__i)
+ {
+ __thisword = this->_M_w[__i];
+ if (__thisword != static_cast<_WordT>(0))
+ return (__i * _S_bits_per_block
+ + __builtin_ctzll(__thisword));
+ }
+ // not found, so return an indication of failure.
+ return __not_found;
+ } // end _M_do_find_next
+
+ // Definitions of non-inline member functions.
+ template<typename _WordT, typename _Alloc>
+ template<typename _CharT, typename _Traits>
+ void
+ dynamic_bitset<_WordT, _Alloc>::
+ _M_copy_from_ptr(const _CharT* __str, size_t __len,
+ size_t __pos, size_t __n, _CharT __zero, _CharT __one)
+ {
+ reset();
+ const size_t __nbits = std::min(_M_Nb, std::min(__n, __len - __pos));
+ for (size_t __i = __nbits; __i > 0; --__i)
+ {
+ const _CharT __c = __str[__pos + __nbits - __i];
+ if (_Traits::eq(__c, __zero))
+ ;
+ else if (_Traits::eq(__c, __one))
+ _M_unchecked_set(__i - 1);
+ else
+ __throw_invalid_argument(__N("dynamic_bitset::_M_copy_from_ptr"));
+ }
+ }
+
+ /**
+ * @defgroup Global I/O operators for bitsets.
+ * @{
+ * @brief Global I/O operators for bitsets.
+ *
+ * Direct I/O between streams and bitsets is supported. Output is
+ * straightforward. Input will skip whitespace and only accept '0'
+ * and '1' characters. The %dynamic_bitset will grow as necessary
+ * to hold the string of bits.
+ */
+ template<typename _CharT, typename _Traits,
+ typename _WordT, typename _Alloc>
+ std::basic_istream<_CharT, _Traits>&
+ operator>>(std::basic_istream<_CharT, _Traits>& __is,
+ dynamic_bitset<_WordT, _Alloc>& __x)
+ {
+ typedef typename _Traits::char_type char_type;
+ typedef std::basic_istream<_CharT, _Traits> __istream_type;
+ typedef typename __istream_type::ios_base __ios_base;
+
+ std::basic_string<_CharT, _Traits> __tmp;
+ __tmp.reserve(__x.size());
+
+ const char_type __zero = __is.widen('0');
+ const char_type __one = __is.widen('1');
+
+ typename __ios_base::iostate __state = __ios_base::goodbit;
+ typename __istream_type::sentry __sentry(__is);
+ if (__sentry)
+ {
+ __try
+ {
+ while (1)
+ {
+ static typename _Traits::int_type __eof = _Traits::eof();
+
+ typename _Traits::int_type __c1 = __is.rdbuf()->sbumpc();
+ if (_Traits::eq_int_type(__c1, __eof))
+ {
+ __state |= __ios_base::eofbit;
+ break;
+ }
+ else
+ {
+ const char_type __c2 = _Traits::to_char_type(__c1);
+ if (_Traits::eq(__c2, __zero))
+ __tmp.push_back(__zero);
+ else if (_Traits::eq(__c2, __one))
+ __tmp.push_back(__one);
+ else if (_Traits::
+ eq_int_type(__is.rdbuf()->sputbackc(__c2),
+ __eof))
+ {
+ __state |= __ios_base::failbit;
+ break;
+ }
+ else
+ break;
+ }
+ }
+ }
+ __catch(__cxxabiv1::__forced_unwind&)
+ {
+ __is._M_setstate(__ios_base::badbit);
+ __throw_exception_again;
+ }
+ __catch(...)
+ { __is._M_setstate(__ios_base::badbit); }
+ }
+
+ __x.resize(__tmp.size());
+
+ if (__tmp.empty() && __x.size())
+ __state |= __ios_base::failbit;
+ else
+ __x._M_copy_from_string(__tmp, static_cast<size_t>(0), __x.size(),
+ __zero, __one);
+ if (__state)
+ __is.setstate(__state);
+ return __is;
+ }
+ /**
+ * @}
+ */
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // tr2
+} // std
+
+#endif /* _GLIBCXX_TR2_DYNAMIC_BITSET_TCC */
diff --git a/libstdc++-v3/libsupc++/del_op.cc b/libstdc++-v3/libsupc++/del_op.cc
index 2d860e18622..ee446c36f14 100644
--- a/libstdc++-v3/libsupc++/del_op.cc
+++ b/libstdc++-v3/libsupc++/del_op.cc
@@ -43,6 +43,5 @@ _GLIBCXX_END_NAMESPACE_VERSION
_GLIBCXX_WEAK_DEFINITION void
operator delete(void* ptr) _GLIBCXX_USE_NOEXCEPT
{
- if (ptr)
- std::free(ptr);
+ std::free(ptr);
}
diff --git a/libstdc++-v3/libsupc++/del_opnt.cc b/libstdc++-v3/libsupc++/del_opnt.cc
index bb37191caed..a04ea401b1c 100644
--- a/libstdc++-v3/libsupc++/del_opnt.cc
+++ b/libstdc++-v3/libsupc++/del_opnt.cc
@@ -24,12 +24,24 @@
// <http://www.gnu.org/licenses/>.
#include <bits/c++config.h>
-#include "new"
-extern "C" void free (void *);
+#if !_GLIBCXX_HOSTED
+// A freestanding C runtime may not provide "free" -- but there is no
+// other reasonable way to implement "operator delete".
+namespace std
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+ extern "C" void free(void*);
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
+#else
+# include <cstdlib>
+#endif
+
+#include "new"
_GLIBCXX_WEAK_DEFINITION void
operator delete (void *ptr, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT
{
- free (ptr);
+ std::free(ptr);
}
diff --git a/libstdc++-v3/src/c++11/Makefile.am b/libstdc++-v3/src/c++11/Makefile.am
index 58d3025f0e7..7dda9483b7b 100644
--- a/libstdc++-v3/src/c++11/Makefile.am
+++ b/libstdc++-v3/src/c++11/Makefile.am
@@ -42,6 +42,7 @@ sources = \
random.cc \
regex.cc \
shared_ptr.cc \
+ snprintf_lite.cc \
system_error.cc \
thread.cc
diff --git a/libstdc++-v3/src/c++11/Makefile.in b/libstdc++-v3/src/c++11/Makefile.in
index 37f96731435..d2ccd9ca430 100644
--- a/libstdc++-v3/src/c++11/Makefile.in
+++ b/libstdc++-v3/src/c++11/Makefile.in
@@ -87,7 +87,8 @@ libc__11convenience_la_LIBADD =
am__objects_1 = chrono.lo condition_variable.lo debug.lo \
functexcept.lo functional.lo future.lo hash_c++0x.lo \
hashtable_c++0x.lo limits.lo mutex.lo placeholders.lo \
- random.lo regex.lo shared_ptr.lo system_error.lo thread.lo
+ random.lo regex.lo shared_ptr.lo snprintf_lite.lo \
+ system_error.lo thread.lo
@ENABLE_EXTERN_TEMPLATE_TRUE@am__objects_2 = fstream-inst.lo \
@ENABLE_EXTERN_TEMPLATE_TRUE@ string-inst.lo wstring-inst.lo
am_libc__11convenience_la_OBJECTS = $(am__objects_1) $(am__objects_2)
@@ -346,6 +347,7 @@ sources = \
random.cc \
regex.cc \
shared_ptr.cc \
+ snprintf_lite.cc \
system_error.cc \
thread.cc
diff --git a/libstdc++-v3/src/c++11/functexcept.cc b/libstdc++-v3/src/c++11/functexcept.cc
index b0c1804ae04..b18f8ad5706 100644
--- a/libstdc++-v3/src/c++11/functexcept.cc
+++ b/libstdc++-v3/src/c++11/functexcept.cc
@@ -31,6 +31,7 @@
#include <future>
#include <functional>
#include <bits/regex_error.h>
+#include <stdarg.h>
#ifdef _GLIBCXX_USE_NLS
# include <libintl.h>
@@ -39,6 +40,12 @@
# define _(msgid) (msgid)
#endif
+namespace __gnu_cxx
+{
+ int __snprintf_lite(char *__buf, size_t __bufsize, const char *__fmt,
+ va_list __ap);
+}
+
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
@@ -80,6 +87,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ _GLIBCXX_THROW_OR_ABORT(out_of_range(_(__s))); }
void
+ __throw_out_of_range_fmt(const char* __fmt, ...)
+ {
+ const size_t __len = __builtin_strlen(__fmt);
+ // We expect at most 2 numbers, and 1 short string. The additional
+ // 512 bytes should provide more than enough space for expansion.
+ const size_t __alloca_size = __len + 512;
+ char *const __s = static_cast<char*>(__builtin_alloca(__alloca_size));
+ va_list __ap;
+
+ va_start(__ap, __fmt);
+ __gnu_cxx::__snprintf_lite(__s, __alloca_size, __fmt, __ap);
+ _GLIBCXX_THROW_OR_ABORT(out_of_range(_(__s)));
+ va_end(__ap); // Not reached.
+ }
+
+ void
__throw_runtime_error(const char* __s __attribute__((unused)))
{ _GLIBCXX_THROW_OR_ABORT(runtime_error(_(__s))); }
diff --git a/libstdc++-v3/src/c++11/snprintf_lite.cc b/libstdc++-v3/src/c++11/snprintf_lite.cc
new file mode 100644
index 00000000000..492df316018
--- /dev/null
+++ b/libstdc++-v3/src/c++11/snprintf_lite.cc
@@ -0,0 +1,161 @@
+// Debugging support -*- C++ -*-
+
+// Copyright (C) 2013 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/>.
+
+#include <stdarg.h>
+#include <bits/functexcept.h>
+#include <bits/locale_facets.h>
+
+namespace std {
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+ template<typename _CharT, typename _ValueT>
+ int
+ __int_to_char(_CharT* __bufend, _ValueT __v, const _CharT* __lit,
+ ios_base::fmtflags __flags, bool __dec);
+_GLIBCXX_END_NAMESPACE_VERSION
+}
+
+namespace __gnu_cxx {
+
+ // Private helper to throw logic error if snprintf_lite runs out
+ // of space (which is not expected to ever happen).
+ // NUL-terminates __buf.
+ void
+ __throw_insufficient_space(const char *__buf, const char *__bufend)
+ __attribute__((__noreturn__));
+
+ void
+ __throw_insufficient_space(const char *__buf, const char *__bufend)
+ {
+ // Include space for trailing NUL.
+ const size_t __len = __bufend - __buf + 1;
+
+ const char __err[] = "not enough space for format expansion "
+ "(Please submit full bug report at http://gcc.gnu.org/bugs.html):\n ";
+ const size_t __errlen = sizeof(__err) - 1;
+
+ char *const __e
+ = static_cast<char*>(__builtin_alloca(__errlen + __len));
+
+ __builtin_memcpy(__e, __err, __errlen);
+ __builtin_memcpy(__e + __errlen, __buf, __len - 1);
+ __e[__errlen + __len - 1] = '\0';
+ std::__throw_logic_error(__e);
+ }
+
+
+ // Private routine to append decimal representation of VAL to the given
+ // BUFFER, but not more than BUFSIZE characters.
+ // Does not NUL-terminate the output buffer.
+ // Returns number of characters appended, or -1 if BUFSIZE is too small.
+ int __concat_size_t(char *__buf, size_t __bufsize, size_t __val)
+ {
+ // __int_to_char is explicitly instantiated and available only for
+ // some, but not all, types. See locale-inst.cc.
+#ifdef _GLIBCXX_USE_LONG_LONG
+ unsigned long long __val2 = __val;
+#else
+ unsigned long __val2 = __val;
+#endif
+ // Long enough for decimal representation.
+ int __ilen = 3 * sizeof(__val2);
+ char *__cs = static_cast<char*>(__builtin_alloca(__ilen));
+ size_t __len = std::__int_to_char(__cs + __ilen, __val2,
+ std::__num_base::_S_atoms_out,
+ std::ios_base::dec, true);
+ if (__bufsize < __len)
+ return -1;
+
+ __builtin_memcpy(__buf, __cs + __ilen - __len, __len);
+ return __len;
+ }
+
+
+ // Private routine to print into __buf arguments according to format,
+ // not to exceed __bufsize.
+ // Only '%%', '%s' and '%zu' format specifiers are understood.
+ // Returns number of characters printed (excluding terminating NUL).
+ // Always NUL-terminates __buf.
+ // Throws logic_error on insufficient space.
+ int __snprintf_lite(char *__buf, size_t __bufsize, const char *__fmt,
+ va_list __ap)
+ {
+ char *__d = __buf;
+ const char *__s = __fmt;
+ const char *const __limit = __d + __bufsize - 1; // Leave space for NUL.
+
+ while (__s[0] != '\0' && __d < __limit)
+ {
+ if (__s[0] == '%')
+ switch (__s[1])
+ {
+ default: // Stray '%'. Just print it.
+ break;
+ case '%': // '%%'
+ __s += 1;
+ break;
+ case 's': // '%s'.
+ {
+ const char *__v = va_arg(__ap, const char *);
+
+ while (__v[0] != '\0' && __d < __limit)
+ *__d++ = *__v++;
+
+ if (__v[0] != '\0')
+ // Not enough space for __fmt expansion.
+ __throw_insufficient_space(__buf, __d);
+
+ __s += 2; // Step over %s.
+ continue;
+ }
+ break;
+ case 'z':
+ if (__s[2] == 'u') // '%zu' -- expand next size_t arg.
+ {
+ const int __len = __concat_size_t(__d, __limit - __d,
+ va_arg(__ap, size_t));
+ if (__len > 0)
+ __d += __len;
+ else
+ // Not enough space for __fmt expansion.
+ __throw_insufficient_space(__buf, __d);
+
+ __s += 3; // Step over %zu
+ continue;
+ }
+ // Stray '%zX'. Just print it.
+ break;
+ }
+ *__d++ = *__s++;
+ }
+
+ if (__s[0] != '\0')
+ // Not enough space for __fmt expansion.
+ __throw_insufficient_space(__buf, __d);
+
+ *__d = '\0';
+ return __d - __buf;
+ }
+
+} // __gnu_cxx
diff --git a/libstdc++-v3/testsuite/20_util/add_lvalue_reference/requirements/typedefs.cc b/libstdc++-v3/testsuite/20_util/add_lvalue_reference/requirements/typedefs.cc
new file mode 100644
index 00000000000..24e73cc23f3
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/add_lvalue_reference/requirements/typedefs.cc
@@ -0,0 +1,30 @@
+// { dg-options "-std=gnu++1y" }
+// { dg-do compile }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+
+// NB: This file is for testing type_traits with NO OTHER INCLUDES.
+
+#include <type_traits>
+
+using namespace std;
+
+static_assert( is_same<typename add_lvalue_reference<long>::type,
+ add_lvalue_reference_t<long>>(),
+ "add_lvalue_reference_t" );
diff --git a/libstdc++-v3/testsuite/20_util/add_rvalue_reference/requirements/typedefs.cc b/libstdc++-v3/testsuite/20_util/add_rvalue_reference/requirements/typedefs.cc
new file mode 100644
index 00000000000..18a6964c8e3
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/add_rvalue_reference/requirements/typedefs.cc
@@ -0,0 +1,30 @@
+// { dg-options "-std=gnu++1y" }
+// { dg-do compile }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+
+// NB: This file is for testing type_traits with NO OTHER INCLUDES.
+
+#include <type_traits>
+
+using namespace std;
+
+static_assert( is_same<typename add_rvalue_reference<long>::type,
+ add_rvalue_reference_t<long>>(),
+ "add_rvalue_reference_t" );
diff --git a/libstdc++-v3/testsuite/20_util/common_type/requirements/typedefs-2.cc b/libstdc++-v3/testsuite/20_util/common_type/requirements/typedefs-2.cc
index 07a694ba4de..f662d32d5db 100644
--- a/libstdc++-v3/testsuite/20_util/common_type/requirements/typedefs-2.cc
+++ b/libstdc++-v3/testsuite/20_util/common_type/requirements/typedefs-2.cc
@@ -1,4 +1,5 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
+// { dg-do compile }
// 2009-11-12 Paolo Carlini <paolo.carlini@oracle.com>
//
// Copyright (C) 2009-2013 Free Software Foundation, Inc.
@@ -19,53 +20,53 @@
// <http://www.gnu.org/licenses/>.
#include <type_traits>
-#include <testsuite_hooks.h>
// DR 1255.
void test01()
{
- bool test __attribute__((unused)) = true;
using std::common_type;
using std::is_same;
- VERIFY( (is_same<common_type<void>::type, void>::value) );
- VERIFY( (is_same<common_type<const void>::type, void>::value) );
- VERIFY( (is_same<common_type<volatile void>::type, void>::value) );
- VERIFY( (is_same<common_type<const volatile void>::type, void>::value) );
+ static_assert( is_same<common_type<void>::type, void>(),
+ "common_type<void>" );
+ static_assert( is_same<common_type<const void>::type, void>(),
+ "common_type<const void>" );
+ static_assert( is_same<common_type<volatile void>::type, void>(),
+ "common_type<volatile void>" );
+ static_assert( is_same<common_type<const volatile void>::type, void>(),
+ "common_type<const volatile void>" );
- VERIFY( (is_same<common_type<void, void>::type, void>::value) );
- VERIFY( (is_same<common_type<void, const void>::type, void>::value) );
- VERIFY( (is_same<common_type<void, volatile void>::type, void>::value) );
- VERIFY( (is_same<common_type<void, const volatile void>::type,
- void>::value) );
- VERIFY( (is_same<common_type<const void, void>::type,
- void>::value) );
- VERIFY( (is_same<common_type<const void, const void>::type,
- void>::value) );
- VERIFY( (is_same<common_type<const void, volatile void>::type,
- void>::value) );
- VERIFY( (is_same<common_type<const void, const volatile void>::type,
- void>::value) );
- VERIFY( (is_same<common_type<volatile void, void>::type,
- void>::value) );
- VERIFY( (is_same<common_type<volatile void, volatile void>::type,
- void>::value) );
- VERIFY( (is_same<common_type<volatile void, const void>::type,
- void>::value) );
- VERIFY( (is_same<common_type<volatile void, const volatile void>::type,
- void>::value) );
- VERIFY( (is_same<common_type<const volatile void, void>::type,
- void>::value) );
- VERIFY( (is_same<common_type<const volatile void, const void>::type,
- void>::value) );
- VERIFY( (is_same<common_type<const volatile void, volatile void>::type,
- void>::value) );
- VERIFY( (is_same<common_type<const volatile void, const volatile void>::type,
- void>::value) );
- }
-
-int main()
-{
- test01();
- return 0;
+ static_assert( is_same<common_type<void, void>::type, void>(),
+ "common_type<void, void>" );
+ static_assert( is_same<common_type<void, const void>::type, void>(),
+ "common_type<void, const void>" );
+ static_assert( is_same<common_type<void, volatile void>::type, void>(),
+ "common_type<void, volatile void>" );
+ static_assert( is_same<common_type<void, const volatile void>::type, void>(),
+ "common_type<void, const volatile void>" );
+ static_assert( is_same<common_type<const void, void>::type, void>(),
+ "common_type<const void, void>" );
+ static_assert( is_same<common_type<const void, const void>::type, void>(),
+ "common_type<const void, const void>" );
+ static_assert( is_same<common_type<const void, volatile void>::type, void>(),
+ "common_type<const void, volatile void>" );
+ static_assert( is_same<common_type<const void, const volatile void>::type,
+ void>(), "common_type<const void, const volatile void>" );
+ static_assert( is_same<common_type<volatile void, void>::type, void>(),
+ "common_type<volatile void, void>" );
+ static_assert( is_same<common_type<volatile void, volatile void>::type,
+ void>(), "common_type<volatile void, volatile void>" );
+ static_assert( is_same<common_type<volatile void, const void>::type,
+ void>(), "common_type<volatile void, const void>" );
+ static_assert( is_same<common_type<volatile void, const volatile void>::type,
+ void>(), "common_type<volatile void, const volatile void>" );
+ static_assert( is_same<common_type<const volatile void, void>::type, void>(),
+ "common_type<const volatile void, const volatile void>" );
+ static_assert( is_same<common_type<const volatile void, const void>::type,
+ void>(), "common_type<const volatile void, const void>" );
+ static_assert( is_same<common_type<const volatile void, volatile void>::type,
+ void>(), "common_type<const volatile void, volatile void>" );
+ static_assert( is_same<common_type<const volatile void, const volatile void>::type,
+ void>(),
+ "common_type<const volatile void, const volatile void>" );
}
diff --git a/libstdc++-v3/testsuite/20_util/common_type/requirements/typedefs-3.cc b/libstdc++-v3/testsuite/20_util/common_type/requirements/typedefs-3.cc
new file mode 100644
index 00000000000..52852fcca76
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/common_type/requirements/typedefs-3.cc
@@ -0,0 +1,27 @@
+// { dg-options "-std=gnu++1y" }
+// { dg-do compile }
+//
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <type_traits>
+
+using namespace std;
+
+static_assert( is_same<common_type<int, long, char, unsigned>::type,
+ common_type_t<int, long, char, unsigned>>(),
+ "common_type_t" );
diff --git a/libstdc++-v3/testsuite/20_util/conditional/requirements/typedefs-2.cc b/libstdc++-v3/testsuite/20_util/conditional/requirements/typedefs-2.cc
new file mode 100644
index 00000000000..94edeea7fb3
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/conditional/requirements/typedefs-2.cc
@@ -0,0 +1,33 @@
+// { dg-options "-std=gnu++1y" }
+// { dg-do compile }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+
+// NB: This file is for testing type_traits with NO OTHER INCLUDES.
+
+#include <type_traits>
+
+using namespace std;
+
+static_assert( is_same<typename conditional<true, long, void>::type,
+ conditional_t<true, long, void>>(),
+ "conditional_t<true, ...>" );
+static_assert( is_same<typename conditional<false, long, void>::type,
+ conditional_t<false, long, void>>(),
+ "conditional_t<false, ...>" );
diff --git a/libstdc++-v3/testsuite/20_util/decay/requirements/typedefs-2.cc b/libstdc++-v3/testsuite/20_util/decay/requirements/typedefs-2.cc
new file mode 100644
index 00000000000..774e22e2ff1
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/decay/requirements/typedefs-2.cc
@@ -0,0 +1,35 @@
+// { dg-options "-std=gnu++1y" }
+// { dg-do compile }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <type_traits>
+
+using namespace std;
+
+template<typename Trait, typename Result>
+ using test = is_same<typename Trait::type, Result>;
+
+static_assert( test<decay<bool>, decay_t<bool>>(), "decay<bool>" );
+static_assert( test<decay<const int>, decay_t<const int>>(),
+ "decay<const int>" );
+static_assert( test<decay<int[4]>, decay_t<int[4]>>(), "decay<int[4]>" );
+typedef void (fn_type) ();
+static_assert( test<decay<fn_type>, decay_t<fn_type>>(), "decay<fn_type>" );
+typedef void (cfn_type) () const;
+static_assert( test<decay<cfn_type>, decay_t<cfn_type>>(), "decay<cfn_type>" );
diff --git a/libstdc++-v3/testsuite/20_util/decay/requirements/typedefs.cc b/libstdc++-v3/testsuite/20_util/decay/requirements/typedefs.cc
index 51b2c5fa0c4..11589e473f0 100644
--- a/libstdc++-v3/testsuite/20_util/decay/requirements/typedefs.cc
+++ b/libstdc++-v3/testsuite/20_util/decay/requirements/typedefs.cc
@@ -1,4 +1,5 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
+// { dg-do compile }
// 2007-05-03 Benjamin Kosnik <bkoz@redhat.com>
//
@@ -19,38 +20,31 @@
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
-#include <cstdlib>
#include <type_traits>
-#include <testsuite_hooks.h>
void test01()
{
- bool test __attribute__((unused)) = true;
using std::decay;
using std::is_same;
// Positive tests.
typedef decay<bool>::type test1_type;
- VERIFY( (is_same<test1_type, bool>::value) );
+ static_assert( is_same<test1_type, bool>(), "decay<bool>" );
// NB: DR 705.
typedef decay<const int>::type test2_type;
- VERIFY( (is_same<test2_type, int>::value) );
+ static_assert( is_same<test2_type, int>(), "decay<const int>" );
typedef decay<int[4]>::type test3_type;
- VERIFY( (is_same<test3_type, std::remove_extent<int[4]>::type*>::value) );
+ static_assert( is_same<test3_type, std::remove_extent<int[4]>::type*>(),
+ "decay<int[4]>" );
typedef void (fn_type) ();
typedef decay<fn_type>::type test4_type;
- VERIFY( (is_same<test4_type, std::add_pointer<fn_type>::type>::value) );
+ static_assert( is_same<test4_type, std::add_pointer<fn_type>::type>(),
+ "decay<fn_type>" );
typedef void (cfn_type) () const;
typedef decay<cfn_type>::type test5_type;
- VERIFY( (is_same<test5_type, cfn_type>::value) );
-}
-
-int main()
-{
- test01();
- return 0;
+ static_assert( is_same<test5_type, cfn_type>(), "decay<cfn_type>" );
}
diff --git a/libstdc++-v3/testsuite/20_util/declval/requirements/1_neg.cc b/libstdc++-v3/testsuite/20_util/declval/requirements/1_neg.cc
index 1aeba824ec5..d01bdf31fa2 100644
--- a/libstdc++-v3/testsuite/20_util/declval/requirements/1_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/declval/requirements/1_neg.cc
@@ -19,7 +19,7 @@
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
-// { dg-error "static assertion failed" "" { target *-*-* } 1938 }
+// { dg-error "static assertion failed" "" { target *-*-* } 2003 }
#include <utility>
diff --git a/libstdc++-v3/testsuite/20_util/default_delete/48631_neg.cc b/libstdc++-v3/testsuite/20_util/default_delete/48631_neg.cc
index d4c17288a99..d9ff71cd85c 100644
--- a/libstdc++-v3/testsuite/20_util/default_delete/48631_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/default_delete/48631_neg.cc
@@ -28,3 +28,4 @@ D d;
std::default_delete<B[]> db;
typedef decltype(db(&d)) type; // { dg-error "use of deleted function" }
// { dg-prune-output "declared" }
+// { dg-prune-output "invalid" }
diff --git a/libstdc++-v3/testsuite/20_util/default_delete/void_neg.cc b/libstdc++-v3/testsuite/20_util/default_delete/void_neg.cc
new file mode 100644
index 00000000000..79786cbf923
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/default_delete/void_neg.cc
@@ -0,0 +1,30 @@
+// { dg-options "-std=gnu++11" }
+// { dg-do compile }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// 20.8.1.1 Default deleters [util.ptr.dltr]
+
+#include <memory>
+
+void test01()
+{
+ std::default_delete<void> d;
+ d(nullptr); // { dg-error "here" }
+ // { dg-error "incomplete" "" { target *-*-* } 72 }
+}
diff --git a/libstdc++-v3/testsuite/20_util/duration/arithmetic/58850.cc b/libstdc++-v3/testsuite/20_util/duration/arithmetic/58850.cc
new file mode 100644
index 00000000000..2a208b19d93
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/duration/arithmetic/58850.cc
@@ -0,0 +1,42 @@
+// { dg-options "-std=gnu++11" }
+// { dg-require-cstdint "" }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <chrono>
+#include <testsuite_hooks.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+ using namespace std::chrono;
+
+ typedef duration<std::int64_t, std::ratio<36 * 24 * 36525>> Years;
+ Years galactic_empire_age( 12067 );
+
+ VERIFY( duration_cast<seconds>( galactic_empire_age ).count()
+ == duration_cast<minutes>( galactic_empire_age ).count() * 60 );
+ VERIFY( duration_cast<minutes>( galactic_empire_age ).count()
+ == duration_cast<seconds>( galactic_empire_age ).count() / 60 );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/20_util/enable_if/requirements/typedefs-2.cc b/libstdc++-v3/testsuite/20_util/enable_if/requirements/typedefs-2.cc
new file mode 100644
index 00000000000..42b7f4fe019
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/enable_if/requirements/typedefs-2.cc
@@ -0,0 +1,29 @@
+// { dg-do compile }
+// { dg-options "-std=gnu++1y" }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <type_traits>
+
+using namespace std;
+
+static_assert( is_same<enable_if<true>::type, enable_if_t<true>>(),
+ "enable_if_t<true>" );
+struct X;
+static_assert( is_same<enable_if<true, X>::type, enable_if_t<true, X>>(),
+ "enable_if_t<true, X>" );
diff --git a/libstdc++-v3/testsuite/20_util/enable_shared_from_this/members/assign.cc b/libstdc++-v3/testsuite/20_util/enable_shared_from_this/members/assign.cc
new file mode 100644
index 00000000000..24ab926ba81
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/enable_shared_from_this/members/assign.cc
@@ -0,0 +1,36 @@
+// { dg-options "-std=gnu++11" }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <memory>
+#include <testsuite_hooks.h>
+
+struct X : public std::enable_shared_from_this<X> { };
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+ auto x1 = std::make_shared<X>(), x2 = std::make_shared<X>();
+ *x1 = *x2;
+ VERIFY( x1->shared_from_this() != x2->shared_from_this() );
+}
+
+int main()
+{
+ test01();
+}
diff --git a/libstdc++-v3/testsuite/20_util/enable_shared_from_this/members/unique_ptr.cc b/libstdc++-v3/testsuite/20_util/enable_shared_from_this/members/unique_ptr.cc
new file mode 100644
index 00000000000..9f0eaa72a39
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/enable_shared_from_this/members/unique_ptr.cc
@@ -0,0 +1,62 @@
+// { dg-options "-std=gnu++11" }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <memory>
+#include <ext/pointer.h>
+#include <testsuite_hooks.h>
+
+struct X : public std::enable_shared_from_this<X> { };
+
+void test01()
+{
+ std::unique_ptr<X> up(new X);
+ X* xp = up.get();
+ std::shared_ptr<X> sp(std::move(up));
+ VERIFY( xp->shared_from_this() != nullptr );
+}
+
+using __gnu_cxx::_Pointer_adapter;
+using __gnu_cxx::_Std_pointer_impl;
+
+struct Deleter
+{
+ struct pointer : _Pointer_adapter<_Std_pointer_impl<X>>
+ {
+ using _Pointer_adapter::_Pointer_adapter;
+ operator X*() const noexcept { return this->get(); }
+ };
+
+ void operator()(pointer p) const noexcept { delete (X*)p; }
+};
+
+void test02()
+{
+ std::unique_ptr<X, Deleter> up(new X);
+ Deleter::pointer xp = up.get();
+ // Creating shared_ptr from unique_ptr with custom pointer is an extension:
+ std::shared_ptr<X> sp(std::move(up));
+ // but enable_shared_from_this should still work:
+ VERIFY( xp->shared_from_this() != nullptr );
+}
+
+int main()
+{
+ test01();
+ test02();
+}
diff --git a/libstdc++-v3/testsuite/20_util/exchange/1.cc b/libstdc++-v3/testsuite/20_util/exchange/1.cc
index d16d9e9642e..2157b69e7e9 100644
--- a/libstdc++-v3/testsuite/20_util/exchange/1.cc
+++ b/libstdc++-v3/testsuite/20_util/exchange/1.cc
@@ -55,6 +55,10 @@ test02()
VERIFY( old.value == 1 );
}
+int f(int) { return 0; }
+
+double f(double) { return 0; }
+
// Deduce type of overloaded function
void
test03()
@@ -62,8 +66,6 @@ test03()
bool test __attribute__((unused)) = true;
int (*fp)(int);
- int f(int);
- double f(double);
std::exchange(fp, &f);
VERIFY( fp != nullptr );
}
diff --git a/libstdc++-v3/testsuite/20_util/function/58569.cc b/libstdc++-v3/testsuite/20_util/function/58569.cc
new file mode 100644
index 00000000000..f1e67bc5ab9
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/function/58569.cc
@@ -0,0 +1,29 @@
+// { dg-options "-std=gnu++11" }
+// { dg-do compile }
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// libstdc++/58569
+
+#include <functional>
+
+struct foo {
+ std::function<foo (int)> x;
+ std::function<foo ()> y;
+};
+
+foo a;
diff --git a/libstdc++-v3/testsuite/20_util/function/cons/57465.cc b/libstdc++-v3/testsuite/20_util/function/cons/57465.cc
new file mode 100644
index 00000000000..44413fbd6ef
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/function/cons/57465.cc
@@ -0,0 +1,31 @@
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// libstdc++/57465
+
+// { dg-options "-std=gnu++11" }
+
+#include <functional>
+#include <testsuite_hooks.h>
+
+int main()
+{
+ using F = void();
+ F* f = nullptr;
+ std::function<F> x(f);
+ VERIFY( !x );
+}
diff --git a/libstdc++-v3/testsuite/20_util/function_objects/comparisons_void.cc b/libstdc++-v3/testsuite/20_util/function_objects/comparisons_void.cc
new file mode 100644
index 00000000000..2cea1fc8dfd
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/function_objects/comparisons_void.cc
@@ -0,0 +1,95 @@
+// { dg-options " -std=gnu++1y " }
+// { dg-do compile }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// 20.3.3 Comparisons
+
+#include <functional>
+
+struct R { };
+
+struct L
+{
+ L operator+(const R&) const { return *this; }
+ L operator-(const R&) const { return *this; }
+ L operator*(const R&) const { return *this; }
+ L operator/(const R&) const { return *this; }
+ L operator%(const R&) const { return *this; }
+ L operator-() const { return *this; }
+
+ bool operator==(const R&) const { return true; }
+ bool operator!=(const R&) const { return false; }
+ bool operator<(const R&) const { return false; }
+ bool operator<=(const R&) const { return true; }
+ bool operator>(const R&) const { return false; }
+ bool operator>=(const R&) const { return true; }
+
+ bool operator&&(const R&) const { return true; }
+ bool operator||(const R&) const { return true; }
+ bool operator!() const { return false; }
+
+ int operator&(const R&) const { return 1; }
+ int operator|(const R&) const { return 1; }
+ int operator^(const R&) const { return 0; }
+ int operator~() const { return 0; }
+};
+
+L l;
+R r;
+
+// test unary function objects
+template<typename F, typename Check = typename F::is_transparent>
+bool
+test1(F f)
+{
+ f(l);
+ return true;
+}
+
+// test binary function objects
+template<typename F, typename Check = typename F::is_transparent>
+bool
+test2(F f)
+{
+ f(l, r);
+ return true;
+}
+
+auto plus = test2( std::plus<>() );
+auto minus = test2( std::minus<>() );
+auto multiplies = test2( std::multiplies<>() );
+auto divides = test2( std::divides<>() );
+auto modulus = test2( std::modulus<>() );
+auto negate = test1( std::negate<>() );
+
+auto equal_to = test2( std::equal_to<>() );
+auto not_equal_to = test2( std::not_equal_to<>() );
+auto greater = test2( std::greater<>() );
+auto less = test2( std::less<>() );
+auto greater_equal = test2( std::greater_equal<>() );
+auto less_equal = test2( std::less_equal<>() );
+
+auto logical_and = test2( std::logical_and<>() );
+auto logical_or = test2( std::logical_or<>() );
+auto logical_not = test1( std::logical_not<>() );
+
+auto bit_and = test2( std::bit_and<>() );
+auto bit_or = test2( std::bit_or<>() );
+auto bit_xor = test2( std::bit_xor<>() );
+auto bit_not = test1( std::bit_not<>() );
diff --git a/libstdc++-v3/testsuite/20_util/integer_sequence/intseq.cc b/libstdc++-v3/testsuite/20_util/integer_sequence/intseq.cc
new file mode 100644
index 00000000000..0f3ed41ab2c
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/integer_sequence/intseq.cc
@@ -0,0 +1,27 @@
+// { dg-options "-std=gnu++1y" }
+// { dg-do compile }
+//
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <type_traits>
+#include <utility>
+
+using std::integer_sequence;
+
+static_assert( integer_sequence<int>::size() == 0, "size() == 0" );
+static_assert( integer_sequence<int, 0, 1, 2>::size() == 3, "size() == 3" );
diff --git a/libstdc++-v3/testsuite/20_util/integer_sequence/requirements/typedefs.cc b/libstdc++-v3/testsuite/20_util/integer_sequence/requirements/typedefs.cc
new file mode 100644
index 00000000000..ab26800959c
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/integer_sequence/requirements/typedefs.cc
@@ -0,0 +1,62 @@
+// { dg-options "-std=gnu++1y" }
+// { dg-do compile }
+//
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <utility>
+#include <type_traits>
+
+using std::is_same;
+using std::integer_sequence;
+using std::make_integer_sequence;
+using std::index_sequence;
+using std::make_index_sequence;
+using std::index_sequence_for;
+
+static_assert( is_same<integer_sequence<int>::value_type, int>::value,
+ "int value_type");
+
+static_assert( is_same<integer_sequence<short>::value_type, short>::value,
+ "short value_type");
+
+static_assert( is_same<make_integer_sequence<int, 0>,
+ integer_sequence<int>>::value,
+ "make empty int seq" );
+
+static_assert( is_same<make_integer_sequence<int, 2>,
+ integer_sequence<int, 0, 1>>::value,
+ "make non-empty int seq" );
+
+static_assert( is_same<make_integer_sequence<unsigned, 0>,
+ integer_sequence<unsigned>>::value,
+ "make empty unsigned seq" );
+
+static_assert( is_same<make_integer_sequence<unsigned, 2>,
+ integer_sequence<unsigned, 0, 1>>::value,
+ "make non-empty unsigned seq" );
+
+static_assert( is_same<index_sequence<0, 1>,
+ integer_sequence<std::size_t, 0, 1>>::value,
+ "index seq" );
+
+static_assert( is_same<make_index_sequence<2>, index_sequence<0, 1>>::value,
+ "make index seq" );
+
+static_assert( is_same<index_sequence_for<char, int, void, double>,
+ index_sequence<0, 1, 2, 3>>::value,
+ "index_sequence_for" );
diff --git a/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs-1.cc b/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs-1.cc
index a0e70e6db63..18791c6a9c9 100644
--- a/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs-1.cc
+++ b/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs-1.cc
@@ -1,4 +1,5 @@
-// { dg-options "-std=gnu++0x" }
+// { dg-options "-std=gnu++11" }
+// { dg-do compile }
// 2007-05-03 Benjamin Kosnik <bkoz@redhat.com>
//
@@ -20,55 +21,57 @@
// <http://www.gnu.org/licenses/>.
#include <type_traits>
-#include <testsuite_hooks.h>
enum test_enum { first_selection };
void test01()
{
- bool test __attribute__((unused)) = true;
using std::make_signed;
using std::is_same;
using std::is_signed;
// Positive tests.
typedef make_signed<const int>::type test2_type;
- VERIFY( (is_same<test2_type, const int>::value) );
+ static_assert( is_same<test2_type, const int>::value,
+ "make_signed<const int>" );
typedef make_signed<const unsigned int>::type test21c_type;
- VERIFY( (is_same<test21c_type, const signed int>::value) );
+ static_assert( is_same<test21c_type, const signed int>::value,
+ "make_signed<const unsigned int>" );
typedef make_signed<volatile unsigned int>::type test21v_type;
- VERIFY( (is_same<test21v_type, volatile signed int>::value) );
+ static_assert( is_same<test21v_type, volatile signed int>::value,
+ "make_signed<volatile unsigned int>" );
typedef make_signed<const volatile unsigned int>::type test21cv_type;
- VERIFY( (is_same<test21cv_type, const volatile signed int>::value) );
+ static_assert( is_same<test21cv_type, const volatile signed int>::value,
+ "make_signed<const volatile unsigned int>" );
typedef make_signed<const char>::type test22_type;
- VERIFY( (is_same<test22_type, const signed char>::value) );
+ static_assert( is_same<test22_type, const signed char>::value,
+ "make_signed<const char>" );
#ifdef _GLIBCXX_USE_WCHAR_T
typedef make_signed<volatile wchar_t>::type test23_type;
- VERIFY( (is_same<test23_type, volatile signed wchar_t>::value) );
+ static_assert( is_same<test23_type, volatile signed wchar_t>::value,
+ "make_signed<volatile wchar_t>" );
#endif
// Chapter 48, chapter 20. Smallest rank such that new signed type same size.
typedef make_signed<test_enum>::type test24_type;
- VERIFY( is_signed<test24_type>::value );
- VERIFY( sizeof(test24_type) == sizeof(test_enum) );
+ static_assert( is_signed<test24_type>::value,
+ "make_signed<test_enum> makes signed type" );
+ static_assert( sizeof(test24_type) == sizeof(test_enum),
+ "make_signed<test_enum> makes type of same size" );
// GNU Extensions.
#ifdef _GLIBCXX_USE_INT128
typedef make_signed<unsigned __int128>::type test25_type;
- VERIFY( (is_same<test25_type, __int128>::value) );
+ static_assert( is_same<test25_type, __int128>::value,
+ "make_signed<unsigned __int128>" );
typedef make_signed<__int128>::type test26_type;
- VERIFY( (is_same<test26_type, __int128>::value) );
+ static_assert( is_same<test26_type, __int128>::value,
+ "make_signed<__int128>" );
#endif
}
-
-int main()
-{
- test01();
- return 0;
-}
diff --git a/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs-3.cc b/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs-3.cc
new file mode 100644
index 00000000000..f7690040388
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs-3.cc
@@ -0,0 +1,35 @@
+// { dg-options "-std=gnu++1y" }
+// { dg-do compile }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <type_traits>
+
+using namespace std;
+
+template<typename Trait, typename Result>
+ using test = is_same<typename Trait::type, Result>;
+
+static_assert( test<make_signed<const int>, make_signed_t<const int>>(),
+ "make_signed_t<const int>" );
+
+static_assert( test<make_signed<unsigned>, make_signed_t<unsigned>>(),
+ "make_signed_t<unsigned>" );
+
+static_assert( test<make_signed<char>, make_signed_t<char>>(),
+ "make_signed_t<char>" );
diff --git a/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs_neg.cc b/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs_neg.cc
index 53090b34564..30a19cf0c86 100644
--- a/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs_neg.cc
@@ -48,5 +48,5 @@ void test01()
// { dg-error "required from here" "" { target *-*-* } 40 }
// { dg-error "required from here" "" { target *-*-* } 42 }
-// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1676 }
-// { dg-error "declaration of" "" { target *-*-* } 1640 }
+// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1714 }
+// { dg-error "declaration of" "" { target *-*-* } 1678 }
diff --git a/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs-3.cc b/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs-3.cc
new file mode 100644
index 00000000000..4bcabe5548d
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs-3.cc
@@ -0,0 +1,35 @@
+// { dg-options "-std=gnu++1y" }
+// { dg-do compile }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <type_traits>
+
+using namespace std;
+
+template<typename Trait, typename Result>
+ using test = is_same<typename Trait::type, Result>;
+
+static_assert( test<make_unsigned<const int>, make_unsigned_t<const int>>(),
+ "make_unsigned_t<const int>" );
+
+static_assert( test<make_unsigned<unsigned>, make_unsigned_t<unsigned>>(),
+ "make_unsigned_t<unsigned>" );
+
+static_assert( test<make_unsigned<char>, make_unsigned_t<char>>(),
+ "make_unsigned_t<char>" );
diff --git a/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc b/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc
index 7b7e59911f4..567908e43d6 100644
--- a/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc
@@ -48,5 +48,5 @@ void test01()
// { dg-error "required from here" "" { target *-*-* } 40 }
// { dg-error "required from here" "" { target *-*-* } 42 }
-// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1594 }
-// { dg-error "declaration of" "" { target *-*-* } 1558 }
+// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1632 }
+// { dg-error "declaration of" "" { target *-*-* } 1596 }
diff --git a/libstdc++-v3/testsuite/20_util/remove_reference/requirements/typedefs.cc b/libstdc++-v3/testsuite/20_util/remove_reference/requirements/typedefs.cc
new file mode 100644
index 00000000000..209cca42c21
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/remove_reference/requirements/typedefs.cc
@@ -0,0 +1,30 @@
+// { dg-options "-std=gnu++1y" }
+// { dg-do compile }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <type_traits>
+
+using namespace std;
+
+static_assert( is_same<remove_reference<int>::type, remove_reference_t<int>>(),
+ "remove_reference_t<int>" );
+static_assert( is_same<remove_reference<int&>::type, remove_reference_t<int&>>(),
+ "remove_reference_t<int&>" );
+static_assert( is_same<remove_reference<int&&>::type, remove_reference_t<int&&>>(),
+ "remove_reference_t<int&&>" );
diff --git a/libstdc++-v3/testsuite/20_util/result_of/requirements/typedefs.cc b/libstdc++-v3/testsuite/20_util/result_of/requirements/typedefs.cc
new file mode 100644
index 00000000000..7c007041160
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/result_of/requirements/typedefs.cc
@@ -0,0 +1,32 @@
+// { dg-options "-std=gnu++1y" }
+// { dg-do compile }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <type_traits>
+
+using namespace std;
+
+using F1 = char(*)(char);
+static_assert( is_same<result_of<F1(int)>::type, result_of_t<F1(int)>>(),
+ "result_of_t<F1(int)>" );
+
+struct X { };
+using F2 = int X::*;
+static_assert( is_same<result_of<F2(X)>::type, result_of_t<F2(X)>>(),
+ "result_of_t<F2(X)>" );
diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/43820_neg.cc b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/43820_neg.cc
index b6d1009d884..db3fcaced52 100644
--- a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/43820_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/43820_neg.cc
@@ -32,7 +32,7 @@ void test01()
{
X* px = 0;
std::shared_ptr<X> p1(px); // { dg-error "here" }
- // { dg-error "incomplete" "" { target *-*-* } 807 }
+ // { dg-error "incomplete" "" { target *-*-* } 779 }
std::shared_ptr<X> p9(ap()); // { dg-error "here" }
// { dg-error "incomplete" "" { target *-*-* } 307 }
diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/58659.cc b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/58659.cc
new file mode 100644
index 00000000000..9315796b240
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/58659.cc
@@ -0,0 +1,68 @@
+// { dg-options "-std=gnu++11" }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <memory>
+#include <testsuite_hooks.h>
+
+struct X { };
+
+using spcd = std::_Sp_counted_deleter<X*, std::default_delete<X>,
+std::allocator<void>, std::__default_lock_policy>;
+
+namespace std
+{
+ template<>
+ struct allocator<spcd>
+ {
+ using value_type = spcd;
+
+ allocator() = default;
+
+ template<typename U>
+ allocator(const allocator<U>&) { }
+
+ value_type* allocate(size_t n)
+ {
+ if (n != 1)
+ throw bad_alloc();
+ allocated = true;
+ return static_cast<value_type*>((void*)(storage));
+ }
+
+ void deallocate(value_type* p, size_t n)
+ {
+ VERIFY(n == 1 && p == (void*)storage && allocated);
+ allocated = false;
+ }
+
+ static char storage[sizeof(spcd)];
+ static bool allocated;
+ };
+
+ char allocator<spcd>::storage[];
+ bool allocator<spcd>::allocated = false;
+}
+
+int main()
+{
+ std::shared_ptr<X> s( std::unique_ptr<X>(new X) );
+ VERIFY( std::allocator<spcd>::allocated );
+ s.reset();
+ VERIFY( !std::allocator<spcd>::allocated );
+}
diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/58839.cc b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/58839.cc
new file mode 100644
index 00000000000..f78a07fb2c6
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/58839.cc
@@ -0,0 +1,33 @@
+// { dg-options "-std=gnu++11" }
+// { dg-do compile }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <memory>
+
+// libstdc++/58839
+
+struct D {
+ void operator()(void*) const noexcept { }
+};
+
+void test01()
+{
+ std::unique_ptr<void, D> y;
+ std::shared_ptr<void> x = std::move(y);
+}
diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/void_neg.cc b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/void_neg.cc
new file mode 100644
index 00000000000..3fd38cf2e62
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/void_neg.cc
@@ -0,0 +1,29 @@
+// { dg-options "-std=gnu++11" }
+// { dg-do compile }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// 20.8.2.2 Template class shared_ptr [util.smartptr.shared]
+
+#include <memory>
+
+void test01()
+{
+ std::shared_ptr<void> p((void*)nullptr); // { dg-error "here" }
+ // { dg-error "incomplete" "" { target *-*-* } 778 }
+}
diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/creation/58594.cc b/libstdc++-v3/testsuite/20_util/shared_ptr/creation/58594.cc
new file mode 100644
index 00000000000..d1e3a7c5ddc
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/shared_ptr/creation/58594.cc
@@ -0,0 +1,27 @@
+// { dg-options "-std=gnu++11" }
+// { dg-do compile }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <memory>
+
+// libstdc++/58594
+void test01()
+{
+ std::make_shared<const int>();
+}
diff --git a/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_copy/58982.cc b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_copy/58982.cc
new file mode 100644
index 00000000000..7e059a35b9b
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_copy/58982.cc
@@ -0,0 +1,41 @@
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// 20.7.12 specialized algorithms
+
+// { dg-options "-std=gnu++11" }
+// { dg-do compile }
+
+#include <memory>
+
+// libstdc++/58982
+
+// trivial class that is not assignable
+struct T
+{
+ T() = default;
+ ~T() = default;
+
+ T& operator=(const T&) = delete;
+};
+
+void
+test01(T* result)
+{
+ T t[1];
+ std::uninitialized_copy(t, t+1, result);
+}
diff --git a/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_copy_n/58982.cc b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_copy_n/58982.cc
new file mode 100644
index 00000000000..e10b31a70f6
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_copy_n/58982.cc
@@ -0,0 +1,41 @@
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// 20.7.12 specialized algorithms
+
+// { dg-options "-std=gnu++11" }
+// { dg-do compile }
+
+#include <memory>
+
+// libstdc++/58982
+
+// trivial class that is not assignable
+struct T
+{
+ T() = default;
+ ~T() = default;
+
+ T& operator=(const T&) = delete;
+};
+
+void
+test01(T* result)
+{
+ T t[1];
+ std::uninitialized_copy_n(t, 1, result);
+}
diff --git a/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_fill/58982.cc b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_fill/58982.cc
new file mode 100644
index 00000000000..012e2c6c88c
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_fill/58982.cc
@@ -0,0 +1,41 @@
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// 20.7.12 specialized algorithms
+
+// { dg-options "-std=gnu++11" }
+// { dg-do compile }
+
+#include <memory>
+
+// libstdc++/58982
+
+// trivial class that is not assignable
+struct T
+{
+ T() = default;
+ ~T() = default;
+
+ T& operator=(const T&) = delete;
+};
+
+void
+test01(T* first, T* last)
+{
+ T t;
+ std::uninitialized_fill(first, last, t);
+}
diff --git a/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_fill_n/58982.cc b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_fill_n/58982.cc
new file mode 100644
index 00000000000..606c63266e3
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_fill_n/58982.cc
@@ -0,0 +1,41 @@
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// 20.7.12 specialized algorithms
+
+// { dg-options "-std=gnu++11" }
+// { dg-do compile }
+
+#include <memory>
+
+// libstdc++/58982
+
+// trivial class that is not assignable
+struct T
+{
+ T() = default;
+ ~T() = default;
+
+ T& operator=(const T&) = delete;
+};
+
+void
+test01(T* first)
+{
+ T t;
+ std::uninitialized_fill_n(first, 1, t);
+}
diff --git a/libstdc++-v3/testsuite/20_util/underlying_type/requirements/typedefs-3.cc b/libstdc++-v3/testsuite/20_util/underlying_type/requirements/typedefs-3.cc
new file mode 100644
index 00000000000..a4c5257499d
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/underlying_type/requirements/typedefs-3.cc
@@ -0,0 +1,32 @@
+// { dg-options "-std=gnu++1y" }
+// { dg-do compile }
+//
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+//
+// NB: This file is for testing type_traits with NO OTHER INCLUDES.
+
+#include <type_traits>
+
+using namespace std;
+
+enum E : long { };
+
+static_assert( is_same<typename underlying_type<E>::type,
+ underlying_type_t<E>>(),
+ "underlying_type_t" );
diff --git a/libstdc++-v3/testsuite/20_util/unique_ptr/assign/48635_neg.cc b/libstdc++-v3/testsuite/20_util/unique_ptr/assign/48635_neg.cc
index c78564270f4..fdffafceadb 100644
--- a/libstdc++-v3/testsuite/20_util/unique_ptr/assign/48635_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/unique_ptr/assign/48635_neg.cc
@@ -41,10 +41,10 @@ void f()
std::unique_ptr<int, B&> ub(nullptr, b);
std::unique_ptr<int, D&> ud(nullptr, d);
ub = std::move(ud);
-// { dg-error "use of deleted function" "" { target *-*-* } 270 }
+// { dg-error "use of deleted function" "" { target *-*-* } 272 }
std::unique_ptr<int[], B&> uba(nullptr, b);
std::unique_ptr<int[], D&> uda(nullptr, d);
uba = std::move(uda);
-// { dg-error "use of deleted function" "" { target *-*-* } 515 }
+// { dg-error "use of deleted function" "" { target *-*-* } 517 }
}
diff --git a/libstdc++-v3/testsuite/23_containers/array/tuple_interface/get_debug_neg.cc b/libstdc++-v3/testsuite/23_containers/array/tuple_interface/get_debug_neg.cc
index 353577f6bbc..6667629e149 100644
--- a/libstdc++-v3/testsuite/23_containers/array/tuple_interface/get_debug_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/array/tuple_interface/get_debug_neg.cc
@@ -28,6 +28,6 @@ int n1 = std::get<1>(a);
int n2 = std::get<1>(std::move(a));
int n3 = std::get<1>(ca);
-// { dg-error "static assertion failed" "" { target *-*-* } 266 }
-// { dg-error "static assertion failed" "" { target *-*-* } 275 }
-// { dg-error "static assertion failed" "" { target *-*-* } 283 }
+// { dg-error "static assertion failed" "" { target *-*-* } 271 }
+// { dg-error "static assertion failed" "" { target *-*-* } 280 }
+// { dg-error "static assertion failed" "" { target *-*-* } 288 }
diff --git a/libstdc++-v3/testsuite/23_containers/array/tuple_interface/get_neg.cc b/libstdc++-v3/testsuite/23_containers/array/tuple_interface/get_neg.cc
index d465cd296b9..ca6f9f84e82 100644
--- a/libstdc++-v3/testsuite/23_containers/array/tuple_interface/get_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/array/tuple_interface/get_neg.cc
@@ -28,6 +28,6 @@ int n1 = std::get<1>(a);
int n2 = std::get<1>(std::move(a));
int n3 = std::get<1>(ca);
-// { dg-error "static assertion failed" "" { target *-*-* } 270 }
-// { dg-error "static assertion failed" "" { target *-*-* } 279 }
-// { dg-error "static assertion failed" "" { target *-*-* } 287 }
+// { dg-error "static assertion failed" "" { target *-*-* } 274 }
+// { dg-error "static assertion failed" "" { target *-*-* } 283 }
+// { dg-error "static assertion failed" "" { target *-*-* } 291 }
diff --git a/libstdc++-v3/testsuite/23_containers/array/tuple_interface/tuple_element_debug_neg.cc b/libstdc++-v3/testsuite/23_containers/array/tuple_interface/tuple_element_debug_neg.cc
index 76ea230b14e..a8e0624ee6e 100644
--- a/libstdc++-v3/testsuite/23_containers/array/tuple_interface/tuple_element_debug_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/array/tuple_interface/tuple_element_debug_neg.cc
@@ -23,4 +23,4 @@
typedef std::tuple_element<1, std::array<int, 1>>::type type;
-// { dg-error "static assertion failed" "" { target *-*-* } 300 }
+// { dg-error "static assertion failed" "" { target *-*-* } 305 }
diff --git a/libstdc++-v3/testsuite/23_containers/array/tuple_interface/tuple_element_neg.cc b/libstdc++-v3/testsuite/23_containers/array/tuple_interface/tuple_element_neg.cc
index 3a52607deb6..0648bc1176e 100644
--- a/libstdc++-v3/testsuite/23_containers/array/tuple_interface/tuple_element_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/array/tuple_interface/tuple_element_neg.cc
@@ -23,4 +23,4 @@
typedef std::tuple_element<1, std::array<int, 1>>::type type;
-// { dg-error "static assertion failed" "" { target *-*-* } 316 }
+// { dg-error "static assertion failed" "" { target *-*-* } 320 }
diff --git a/libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/assign_neg.cc b/libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/assign_neg.cc
index 7558ac7d855..e5917b81f60 100644
--- a/libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/assign_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/assign_neg.cc
@@ -18,7 +18,7 @@
// <http://www.gnu.org/licenses/>.
// { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1760 }
+// { dg-error "no matching" "" { target *-*-* } 1758 }
#include <deque>
diff --git a/libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/constructor_1_neg.cc b/libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/constructor_1_neg.cc
index ee6b721d9d3..fd83c0e1493 100644
--- a/libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/constructor_1_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/constructor_1_neg.cc
@@ -18,7 +18,7 @@
// <http://www.gnu.org/licenses/>.
// { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1693 }
+// { dg-error "no matching" "" { target *-*-* } 1691 }
#include <deque>
diff --git a/libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/constructor_2_neg.cc b/libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/constructor_2_neg.cc
index d36964efa4e..4dc6e8dec73 100644
--- a/libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/constructor_2_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/constructor_2_neg.cc
@@ -18,7 +18,7 @@
// <http://www.gnu.org/licenses/>.
// { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1693 }
+// { dg-error "no matching" "" { target *-*-* } 1691 }
#include <deque>
#include <utility>
diff --git a/libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/insert_neg.cc b/libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/insert_neg.cc
index cda684d29f5..dbbfbaa5c6d 100644
--- a/libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/insert_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/insert_neg.cc
@@ -18,7 +18,7 @@
// <http://www.gnu.org/licenses/>.
// { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1844 }
+// { dg-error "no matching" "" { target *-*-* } 1842 }
#include <deque>
@@ -32,4 +32,3 @@ void f()
std::deque<A> d;
d.insert(d.begin(), 10, 1);
}
-
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/debug/debug_functions.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/debug/debug_functions.cc
new file mode 100644
index 00000000000..b90249f2d70
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_set/debug/debug_functions.cc
@@ -0,0 +1,92 @@
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+//
+// { dg-options "-std=gnu++11" }
+// { dg-require-debug-mode "" }
+
+#include <unordered_set>
+#include <testsuite_hooks.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+ using namespace __gnu_debug;
+
+ std::unordered_set<int> u = { 0, 1, 2 };
+ VERIFY( __check_dereferenceable(u.begin()) );
+ auto it = u.begin();
+ VERIFY( __check_dereferenceable(it) );
+
+ VERIFY( __check_dereferenceable(u.cbegin()) );
+ auto cit = u.begin();
+ VERIFY( __check_dereferenceable(cit) );
+
+ VERIFY( !__check_dereferenceable(u.end()) );
+ it = u.end();
+ VERIFY( !__check_dereferenceable(it) );
+
+ auto bucket = u.bucket(0);
+ VERIFY( __check_dereferenceable(u.begin(bucket)) );
+ auto lit = u.begin(bucket);
+ VERIFY( __check_dereferenceable(lit) );
+
+ VERIFY( !__check_dereferenceable(u.end(bucket)) );
+}
+
+void test02()
+{
+ bool test __attribute__((unused)) = true;
+ using namespace __gnu_debug;
+
+ std::unordered_set<int> u = { 0, 1, 2 };
+
+ VERIFY( !__check_singular(u.end()) );
+ auto it = u.end();
+ VERIFY( !__check_singular(it) );
+
+ VERIFY( !__check_singular(u.begin()) );
+ it = u.begin();
+ VERIFY( !__check_singular(it) );
+
+ u.clear();
+
+ VERIFY( it._M_singular() );
+ VERIFY( __check_singular(it) );
+
+ it = u.end();
+ VERIFY( !it._M_singular() );
+ VERIFY( !__check_singular(it) );
+
+ u = { 0, 1, 2 };
+
+ auto bucket = u.bucket(0);
+ VERIFY( !__check_singular(u.begin(bucket)) );
+ auto lit = u.begin(bucket);
+ VERIFY( !__check_singular(lit) );
+
+ VERIFY( !__check_singular(u.end(bucket)) );
+
+ u.clear();
+ VERIFY( __check_singular(lit) );
+}
+
+int main()
+{
+ test01();
+ test02();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/not_default_constructible_hash_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/not_default_constructible_hash_neg.cc
index 3332cc593cd..4216b91c291 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_set/not_default_constructible_hash_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_set/not_default_constructible_hash_neg.cc
@@ -19,7 +19,7 @@
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
-// { dg-error "default constructible" "" { target *-*-* } 283 }
+// { dg-error "default constructible" "" { target *-*-* } 287 }
#include <unordered_set>
diff --git a/libstdc++-v3/testsuite/23_containers/vector/debug/debug_functions.cc b/libstdc++-v3/testsuite/23_containers/vector/debug/debug_functions.cc
new file mode 100644
index 00000000000..5568ed65cf2
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/vector/debug/debug_functions.cc
@@ -0,0 +1,75 @@
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+//
+// { dg-require-debug-mode "" }
+
+#include <vector>
+#include <testsuite_hooks.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+ using namespace __gnu_debug;
+
+ std::vector<int> v1(3, 1);
+ VERIFY( __check_dereferenceable(v1.begin()) );
+ std::vector<int>::iterator it = v1.begin();
+ VERIFY( __check_dereferenceable(it) );
+
+ VERIFY( !__check_dereferenceable(v1.end()) );
+ it = v1.end();
+ VERIFY( !__check_dereferenceable(it) );
+
+ const volatile int* pi = 0;
+ VERIFY( !__check_dereferenceable(pi) );
+
+ int i;
+ pi = &i;
+
+ VERIFY( __check_dereferenceable(pi) );
+}
+
+void test02()
+{
+ bool test __attribute__((unused)) = true;
+ using namespace __gnu_debug;
+
+ std::vector<int> v1(3, 1);
+ VERIFY( !__check_singular(v1.begin()) );
+ std::vector<int>::iterator it = v1.begin();
+ VERIFY( !__check_singular(it) );
+
+ VERIFY( !__check_singular(v1.end()) );
+ it = v1.end();
+ VERIFY( !__check_singular(it) );
+
+ v1.clear();
+
+ VERIFY( it._M_singular() );
+ VERIFY( __check_singular(it) );
+
+ it = v1.end();
+ VERIFY( !it._M_singular() );
+ VERIFY( !__check_singular(it) );
+}
+
+int main()
+{
+ test01();
+ test02();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/assign_neg.cc b/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/assign_neg.cc
index 388e57182cc..b8a6621b339 100644
--- a/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/assign_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/assign_neg.cc
@@ -18,7 +18,7 @@
// <http://www.gnu.org/licenses/>.
// { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1302 }
+// { dg-error "no matching" "" { target *-*-* } 1305 }
#include <vector>
diff --git a/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_1_neg.cc b/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_1_neg.cc
index 68cfab064f8..ec3aa5a62e8 100644
--- a/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_1_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_1_neg.cc
@@ -18,7 +18,7 @@
// <http://www.gnu.org/licenses/>.
// { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1228 }
+// { dg-error "no matching" "" { target *-*-* } 1231 }
#include <vector>
diff --git a/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_2_neg.cc b/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_2_neg.cc
index 35c03286a26..5c7d436ad34 100644
--- a/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_2_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_2_neg.cc
@@ -18,7 +18,7 @@
// <http://www.gnu.org/licenses/>.
// { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1228 }
+// { dg-error "no matching" "" { target *-*-* } 1231 }
#include <vector>
#include <utility>
diff --git a/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/insert_neg.cc b/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/insert_neg.cc
index 6ab70388b83..2daaf527197 100644
--- a/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/insert_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/insert_neg.cc
@@ -18,7 +18,7 @@
// <http://www.gnu.org/licenses/>.
// { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1343 }
+// { dg-error "no matching" "" { target *-*-* } 1346 }
#include <vector>
diff --git a/libstdc++-v3/testsuite/25_algorithms/adjacent_find/vectorbool.cc b/libstdc++-v3/testsuite/25_algorithms/adjacent_find/vectorbool.cc
new file mode 100644
index 00000000000..c5278bbe974
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/adjacent_find/vectorbool.cc
@@ -0,0 +1,44 @@
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// 25.1.5 [lib.alg.adjacent_find]
+
+#include <vector>
+#include <algorithm>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ std::vector<bool> v;
+ v.push_back(true);
+ v.push_back(false);
+ v.push_back(true);
+ v.push_back(false);
+ v.push_back(false);
+
+ VERIFY( std::adjacent_find(v.begin(), v.end()) == v.begin() + 3 );
+ VERIFY( std::adjacent_find(v.begin(), v.end() - 1) == v.end() - 1 );
+}
+
+int
+main()
+{
+ test01();
+}
diff --git a/libstdc++-v3/testsuite/25_algorithms/copy/58982.cc b/libstdc++-v3/testsuite/25_algorithms/copy/58982.cc
new file mode 100644
index 00000000000..58ece1b80f6
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/copy/58982.cc
@@ -0,0 +1,42 @@
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// 25.3.1 copy
+
+// { dg-options "-std=gnu++11" }
+// { dg-do compile }
+
+#include <algorithm>
+
+// libstdc++/58982
+
+// trivial class that is not assignable
+struct T
+{
+ T() = default;
+ ~T() = default;
+
+ T& operator=(const T&) = delete;
+};
+
+void
+test01(T* result)
+{
+ T t[1];
+ std::copy(t, t+1, result); // { dg-error "here" }
+}
+// { dg-prune-output "not assignable" }
diff --git a/libstdc++-v3/testsuite/25_algorithms/copy_n/58982.cc b/libstdc++-v3/testsuite/25_algorithms/copy_n/58982.cc
new file mode 100644
index 00000000000..f7dfa599388
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/copy_n/58982.cc
@@ -0,0 +1,42 @@
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// 25.3.1 copy
+
+// { dg-options "-std=gnu++11" }
+// { dg-do compile }
+
+#include <algorithm>
+
+// libstdc++/58982
+
+// trivial class that is not assignable
+struct T
+{
+ T() = default;
+ ~T() = default;
+
+ T& operator=(const T&) = delete;
+};
+
+void
+test01(T* result)
+{
+ T t[1];
+ std::copy_n(t, 1, result); // { dg-error "here" }
+}
+// { dg-prune-output "not assignable" }
diff --git a/libstdc++-v3/testsuite/25_algorithms/find/vectorbool.cc b/libstdc++-v3/testsuite/25_algorithms/find/vectorbool.cc
new file mode 100644
index 00000000000..13de9300c10
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/find/vectorbool.cc
@@ -0,0 +1,39 @@
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// 25.1.2 find
+
+#include <algorithm>
+#include <vector>
+#include <testsuite_hooks.h>
+
+void
+test1()
+{
+ std::vector<bool> v;
+ v.push_back(false);
+ v.push_back(false);
+ v.push_back(true);
+ v.push_back(false);
+ VERIFY( std::find(v.begin(), v.end(), true) == v.begin() + 2 );
+}
+
+int
+main()
+{
+ test1();
+}
diff --git a/libstdc++-v3/testsuite/25_algorithms/find_end/vectorbool.cc b/libstdc++-v3/testsuite/25_algorithms/find_end/vectorbool.cc
new file mode 100644
index 00000000000..eabaa4c572c
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/find_end/vectorbool.cc
@@ -0,0 +1,50 @@
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// 25.1.3 [lib.alg.find.end]
+
+#include <algorithm>
+#include <vector>
+#include <testsuite_hooks.h>
+
+void
+test1()
+{
+ std::vector<bool> v1;
+ v1.push_back(false);
+ v1.push_back(false);
+ v1.push_back(false);
+ v1.push_back(true);
+ v1.push_back(true);
+ v1.push_back(false);
+ v1.push_back(true);
+ v1.push_back(true);
+ v1.push_back(false);
+
+ std::vector<bool> v2;
+ v2.push_back(true);
+ v2.push_back(true);
+
+ VERIFY( std::find_end(v1.begin(), v1.end(), v2.begin(), v2.end())
+ == v1.begin() + 6 );
+}
+
+int
+main()
+{
+ test1();
+}
diff --git a/libstdc++-v3/testsuite/25_algorithms/find_first_of/vectorbool.cc b/libstdc++-v3/testsuite/25_algorithms/find_first_of/vectorbool.cc
new file mode 100644
index 00000000000..d43a391c843
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/find_first_of/vectorbool.cc
@@ -0,0 +1,50 @@
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// 25.1.4 [lib.alg.find.first.of]
+
+#include <algorithm>
+#include <vector>
+#include <testsuite_hooks.h>
+
+void
+test1()
+{
+ std::vector<bool> v1;
+ v1.push_back(false);
+ v1.push_back(false);
+ v1.push_back(true);
+ v1.push_back(false);
+ v1.push_back(true);
+ v1.push_back(true);
+ v1.push_back(false);
+ v1.push_back(true);
+ v1.push_back(true);
+
+ std::vector<bool> v2;
+ v2.push_back(true);
+ v2.push_back(false);
+
+ VERIFY( std::find_first_of(v1.begin(), v1.end(), v2.begin(), v2.end())
+ == v1.begin() );
+}
+
+int
+main()
+{
+ test1();
+}
diff --git a/libstdc++-v3/testsuite/25_algorithms/find_if/vectorbool.cc b/libstdc++-v3/testsuite/25_algorithms/find_if/vectorbool.cc
new file mode 100644
index 00000000000..13de9300c10
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/find_if/vectorbool.cc
@@ -0,0 +1,39 @@
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// 25.1.2 find
+
+#include <algorithm>
+#include <vector>
+#include <testsuite_hooks.h>
+
+void
+test1()
+{
+ std::vector<bool> v;
+ v.push_back(false);
+ v.push_back(false);
+ v.push_back(true);
+ v.push_back(false);
+ VERIFY( std::find(v.begin(), v.end(), true) == v.begin() + 2 );
+}
+
+int
+main()
+{
+ test1();
+}
diff --git a/libstdc++-v3/testsuite/25_algorithms/find_if_not/vectorbool.cc b/libstdc++-v3/testsuite/25_algorithms/find_if_not/vectorbool.cc
new file mode 100644
index 00000000000..f97a7e24256
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/find_if_not/vectorbool.cc
@@ -0,0 +1,40 @@
+// { dg-options "-std=gnu++0x" }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <algorithm>
+#include <vector>
+#include <testsuite_hooks.h>
+
+void
+test1()
+{
+ std::vector<bool> v;
+ v.push_back(false);
+ v.push_back(false);
+ v.push_back(true);
+ v.push_back(false);
+ VERIFY( std::find_if_not(v.begin(), v.end(), [](bool val){ return !val; })
+ == v.begin() + 2 );
+}
+
+int
+main()
+{
+ test1();
+}
diff --git a/libstdc++-v3/testsuite/25_algorithms/heap/vectorbool.cc b/libstdc++-v3/testsuite/25_algorithms/heap/vectorbool.cc
new file mode 100644
index 00000000000..7f2bc61e1a0
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/heap/vectorbool.cc
@@ -0,0 +1,146 @@
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// 25.3.6 Heap operations [lib.alg.heap.operations]
+
+#include <iterator>
+#include <vector>
+#include <algorithm>
+#include <testsuite_hooks.h>
+
+const bool A[] = { true, true, false, true, false, false, true, false };
+const int B[] = { false, false, false, false, true, true, true, true };
+const int C[] = { true, true, true, true, false, false, false, false };
+const int N = sizeof(A) / sizeof(bool);
+
+// This functor has the equivalent functionality of std::greater<>,
+// but there is no dependency on <functional> and it also tracks the
+// number of invocations since creation.
+class Gt
+{
+public:
+ static int count() { return _S_count; }
+ static void reset() { _S_count = 0; }
+
+ bool
+ operator()(bool x, bool y) const
+ {
+ ++_S_count;
+ return x > y;
+ }
+
+private:
+ static int _S_count;
+};
+
+int Gt::_S_count = 0;
+
+// Exercise all of the heap functions for operator<. The intermediate
+// results between push_heap and pop_heap and make_heap and sort_heap
+// are not checked (they could be).
+void
+test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ // sort array s1 using push_heap/pop_heap
+ std::vector<bool> s1;
+ std::copy(A, A + N, std::back_inserter(s1));
+ VERIFY( std::equal(s1.begin(), s1.begin() + N, A) );
+
+ for (int i = 2; i <= N; ++i)
+ std::push_heap(s1.begin(), s1.begin() + i);
+
+ for (int i = N; i >= 2; --i)
+ std::pop_heap(s1.begin(), s1.begin() + i);
+
+ VERIFY( std::equal(s1.begin(), s1.begin() + N, B) );
+
+ // sort array s2 using make_heap/sort_heap
+ std::vector<bool> s2;
+ std::copy(A, A + N, std::back_inserter(s2));
+ VERIFY( std::equal(s2.begin(), s2.begin() + N, A) );
+
+ std::make_heap(s2.begin(), s2.begin() + N);
+ std::sort_heap(s2.begin(), s2.begin() + N);
+ VERIFY( std::equal(s2.begin(), s2.begin() + N, B) );
+}
+
+// Perform same tests as above but with the comparison predicate
+// versions, and add complexity constraint checks.
+void
+test02()
+{
+ bool test __attribute__((unused)) = true;
+
+ Gt gt;
+
+#ifndef _GLIBCXX_DEBUG
+ //const int logN = static_cast<int>(std::log(static_cast<double>(N)) + 0.5);
+ const int logN = 3;
+#endif
+
+ std::vector<bool> s1;
+ std::copy(A, A + N, std::back_inserter(s1));
+ VERIFY(std::equal(s1.begin(), s1.begin() + N, A));
+
+ for (int i = 2; i <= N; ++i)
+ {
+ std::push_heap(s1.begin(), s1.begin() + i, gt);
+#ifndef _GLIBCXX_DEBUG
+ VERIFY(gt.count() <= logN);
+#endif
+ gt.reset();
+ }
+
+ for (int i = N; i >= 2; --i)
+ {
+ std::pop_heap(s1.begin(), s1.begin() + i, gt);
+#ifndef _GLIBCXX_DEBUG
+ VERIFY(gt.count() <= 2 * logN);
+#endif
+ gt.reset();
+ }
+
+ VERIFY(std::equal(s1.begin(), s1.begin() + N, C));
+
+ // sort array s2 using make_heap/sort_heap
+ std::vector<bool> s2;
+ std::copy(A, A + N, std::back_inserter(s2));
+ VERIFY(std::equal(s2.begin(), s2.begin() + N, A));
+
+ std::make_heap(s2.begin(), s2.begin() + N, gt);
+#ifndef _GLIBCXX_DEBUG
+ VERIFY(gt.count() <= 3 * N);
+#endif
+ gt.reset();
+
+ std::sort_heap(s2.begin(), s2.begin() + N, gt);
+#ifndef _GLIBCXX_DEBUG
+ VERIFY(gt.count() <= N * logN);
+#endif
+
+ VERIFY(std::equal(s2.begin(), s2.begin() + N, C));
+}
+
+int
+main()
+{
+ test01();
+ test02();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/25_algorithms/is_permutation/vectorbool.cc b/libstdc++-v3/testsuite/25_algorithms/is_permutation/vectorbool.cc
new file mode 100644
index 00000000000..be5b4ff531f
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/is_permutation/vectorbool.cc
@@ -0,0 +1,50 @@
+// { dg-options "-std=gnu++1y" }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// 25.2.12 [alg.is_permutation] Is permutation
+
+#include <vector>
+#include <algorithm>
+#include <testsuite_hooks.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ std::vector<bool> v1 = { true, false, true, false, true };
+ std::vector<bool> v2 = { false, true, false, true, true };
+ VERIFY( std::is_permutation(v1.begin(), v1.end(), v2.begin()) );
+ VERIFY( !std::is_permutation(v1.begin() + 1, v1.end(), v2.begin() + 1) );
+}
+
+void test02()
+{
+ bool test __attribute__((unused)) = true;
+
+ std::vector<bool> v1 = { true, false, true, false, true };
+ std::vector<bool> v2 = { false, true, false, true, true };
+ VERIFY( std::is_permutation(v1.begin(), v1.end(), v2.begin(), v2.end()) );
+ VERIFY( !std::is_permutation(v1.begin(), v1.end() - 1, v2.begin(), v2.end()) );
+}
+
+int main()
+{
+ test01();
+ test02();
+}
diff --git a/libstdc++-v3/testsuite/25_algorithms/nth_element/58800.cc b/libstdc++-v3/testsuite/25_algorithms/nth_element/58800.cc
new file mode 100644
index 00000000000..108c0e5abd1
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/nth_element/58800.cc
@@ -0,0 +1,52 @@
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// 25.3.2 [lib.alg.nth.element]
+
+// { dg-options "-std=gnu++11" }
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+using __gnu_test::test_container;
+using __gnu_test::random_access_iterator_wrapper;
+
+typedef test_container<int, random_access_iterator_wrapper> Container;
+
+void test01()
+{
+ std::vector<int> v = {
+ 207089,
+ 202585,
+ 180067,
+ 157549,
+ 211592,
+ 216096,
+ 207089
+ };
+
+ Container con(v.data(), v.data() + 7);
+
+ std::nth_element(con.begin(), con.begin() + 3, con.end());
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/25_algorithms/nth_element/random_test.cc b/libstdc++-v3/testsuite/25_algorithms/nth_element/random_test.cc
new file mode 100644
index 00000000000..ef1d0b6c4e6
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/nth_element/random_test.cc
@@ -0,0 +1,63 @@
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++11" }
+// { dg-options "-std=gnu++11 -DSIMULATOR_TEST" { target simulator } }
+// { dg-require-cstdint "" }
+
+// 25.4.2 [lib.alg.nth.element]
+
+#include <algorithm>
+#include <random>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+#include <testsuite_containergen.h>
+
+using __gnu_test::test_container;
+using __gnu_test::random_access_iterator_wrapper;
+
+typedef test_container<int, random_access_iterator_wrapper> Container;
+
+struct testNthElement
+{
+ template<typename Container, typename RandomGen>
+ void operator()(Container con, RandomGen& rg)
+ {
+ bool test __attribute__((unused)) = true;
+
+ const int size = con.end() - con.begin();
+ auto dist = std::uniform_int_distribution<>(0, size);
+ const int element = dist(rg);
+
+ std::nth_element(con.begin(), con.begin() + element, con.end());
+
+ if (element < size)
+ {
+ for (int i = 0; i < element; ++i)
+ VERIFY( con.val(i) <= con.val(element) );
+
+ for (int i = element + 1; i < size; ++i)
+ VERIFY( con.val(i) >= con.val(element) );
+ }
+ }
+};
+
+int
+main()
+{
+ __gnu_test::test_containers<Container>(testNthElement());
+}
diff --git a/libstdc++-v3/testsuite/25_algorithms/partial_sort/random_test.cc b/libstdc++-v3/testsuite/25_algorithms/partial_sort/random_test.cc
new file mode 100644
index 00000000000..855e92121b3
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/partial_sort/random_test.cc
@@ -0,0 +1,62 @@
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++11" }
+// { dg-options "-std=gnu++11 -DSIMULATOR_TEST" { target simulator } }
+// { dg-require-cstdint "" }
+
+// 25.4.1.3 [lib.alg.partial.sort]
+
+#include <algorithm>
+#include <random>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+#include <testsuite_containergen.h>
+
+using __gnu_test::test_container;
+using __gnu_test::random_access_iterator_wrapper;
+
+typedef test_container<int, random_access_iterator_wrapper> Container;
+
+struct testPartialSort
+{
+ template<typename Container, typename RandomGen>
+ void operator()(Container con, RandomGen& rg)
+ {
+ bool test __attribute__((unused)) = true;
+
+ const int size = con.end() - con.begin();
+ auto dist = std::uniform_int_distribution<>(0, size);
+ const int element = dist(rg);
+
+ std::partial_sort(con.begin(), con.begin() + element, con.end());
+
+ VERIFY( std::is_sorted(con.begin(), con.begin() + element) );
+
+ if (element > 0)
+ {
+ for (int i = element; i < size; ++i)
+ VERIFY( con.val(element - 1) <= con.val(i) );
+ }
+ }
+};
+
+int
+main()
+{
+ __gnu_test::test_containers<Container>(testPartialSort());
+}
diff --git a/libstdc++-v3/testsuite/25_algorithms/partial_sort_copy/random_test.cc b/libstdc++-v3/testsuite/25_algorithms/partial_sort_copy/random_test.cc
new file mode 100644
index 00000000000..cca4c568cbb
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/partial_sort_copy/random_test.cc
@@ -0,0 +1,67 @@
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++11" }
+// { dg-options "-std=gnu++11 -DSIMULATOR_TEST" { target simulator } }
+// { dg-require-cstdint "" }
+
+// 25.4.1.4 [lib.alg.partial.sort.copy]
+
+#include <algorithm>
+#include <random>
+#include <vector>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+#include <testsuite_containergen.h>
+
+using __gnu_test::test_container;
+using __gnu_test::random_access_iterator_wrapper;
+
+typedef test_container<int, random_access_iterator_wrapper> Container;
+
+struct testPartialSortCopy
+{
+ template<typename Container, typename RandomGen>
+ void operator()(Container con, RandomGen& rg)
+ {
+ bool test __attribute__((unused)) = true;
+
+ const int size = con.end() - con.begin();
+ auto dist = std::uniform_int_distribution<>(0, size);
+ const int element = dist(rg);
+
+ std::vector<int> outvec(element + 1); // add +1 to avoid empty issues
+
+ Container out(outvec.data(), outvec.data() + element);
+
+ std::partial_sort_copy(con.begin(), con.end(),
+ out.begin(), out.begin() + element);
+
+ VERIFY( std::is_sorted(out.begin(), out.begin() + element) );
+
+ std::sort(con.begin(), con.end());
+
+ for (int i = 0; i < element; ++i)
+ VERIFY( con.val(i) == out.val(i) );
+ }
+};
+
+int
+main()
+{
+ __gnu_test::test_containers<Container>(testPartialSortCopy());
+}
diff --git a/libstdc++-v3/testsuite/25_algorithms/sort/random_test.cc b/libstdc++-v3/testsuite/25_algorithms/sort/random_test.cc
new file mode 100644
index 00000000000..ff3d06aa35c
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/sort/random_test.cc
@@ -0,0 +1,51 @@
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++11" }
+// { dg-options "-std=gnu++11 -DSIMULATOR_TEST" { target simulator } }
+// { dg-require-cstdint "" }
+
+// 25.4.1 [lib.alg.sort]
+
+#include <algorithm>
+#include <random>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+#include <testsuite_containergen.h>
+
+using __gnu_test::test_container;
+using __gnu_test::random_access_iterator_wrapper;
+
+typedef test_container<int, random_access_iterator_wrapper> Container;
+
+struct testSort
+{
+ template<typename Container, typename RandomGen>
+ void operator()(Container con, RandomGen&)
+ {
+ bool test __attribute__((unused)) = true;
+
+ std::sort(con.begin(), con.end());
+ VERIFY( std::is_sorted(con.begin(), con.end()) );
+ }
+};
+
+int
+main()
+{
+ __gnu_test::test_containers<Container>(testSort());
+}
diff --git a/libstdc++-v3/testsuite/26_numerics/complex/literals/types.cc b/libstdc++-v3/testsuite/26_numerics/complex/literals/types.cc
new file mode 100644
index 00000000000..e5f9b8c49e4
--- /dev/null
+++ b/libstdc++-v3/testsuite/26_numerics/complex/literals/types.cc
@@ -0,0 +1,46 @@
+// { dg-options "-std=c++1y" }
+// { dg-do compile }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <complex>
+#include <type_traits>
+
+void
+test02()
+{
+ using namespace std::literals::complex_literals;
+
+ static_assert(std::is_same<decltype(1.0if), std::complex<float>>::value,
+ "1.0if is std::complex<float>");
+
+ static_assert(std::is_same<decltype(1if), std::complex<float>>::value,
+ "1if is std::complex<float>");
+
+ static_assert(std::is_same<decltype(1.0i), std::complex<double>>::value,
+ "1.0i is std::complex<double>");
+
+ static_assert(std::is_same<decltype(1i), std::complex<double>>::value,
+ "1i is std::complex<double>");
+
+ static_assert(std::is_same<decltype(1.0il), std::complex<long double>>::value,
+ "1.0il is std::complex<long double>");
+
+ static_assert(std::is_same<decltype(1il), std::complex<long double>>::value,
+ "1il is std::complex<long double>");
+}
diff --git a/libstdc++-v3/testsuite/26_numerics/complex/literals/values.cc b/libstdc++-v3/testsuite/26_numerics/complex/literals/values.cc
new file mode 100644
index 00000000000..e56727e49c8
--- /dev/null
+++ b/libstdc++-v3/testsuite/26_numerics/complex/literals/values.cc
@@ -0,0 +1,48 @@
+// { dg-options "-std=gnu++1y" }
+// { dg-do run }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <complex>
+#include <testsuite_hooks.h>
+
+void
+test02()
+{
+ using namespace std::literals::complex_literals;
+
+ std::complex<float> j1 = 1.0if;
+ std::complex<float> k1 = 1if;
+ std::complex<double> j2 = 2.0i;
+ std::complex<double> k2 = 2i;
+ std::complex<long double> j4 = 4.0il;
+ std::complex<long double> k4 = 4il;
+
+ VERIFY( j1 == std::complex<float>(0.0F, 1.0F) );
+ VERIFY( k1 == std::complex<float>(0.0F, 1.0F) );
+ VERIFY( j2 == std::complex<double>(0.0, 2.0) );
+ VERIFY( k2 == std::complex<double>(0.0, 2.0) );
+ VERIFY( j4 == std::complex<long double>(0.0L, 4.0L) );
+ VERIFY( k4 == std::complex<long double>(0.0L, 4.0L) );
+}
+
+int
+main()
+{
+ test02();
+}
diff --git a/libstdc++-v3/testsuite/26_numerics/valarray/subset_assignment.cc b/libstdc++-v3/testsuite/26_numerics/valarray/subset_assignment.cc
index 6b598c461c7..ed339fd08b0 100644
--- a/libstdc++-v3/testsuite/26_numerics/valarray/subset_assignment.cc
+++ b/libstdc++-v3/testsuite/26_numerics/valarray/subset_assignment.cc
@@ -75,4 +75,4 @@ int main()
VERIFY(check_array(val_g, ans4));
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/27_io/ios_base/types/fmtflags/bitmask_operators.cc b/libstdc++-v3/testsuite/27_io/ios_base/types/fmtflags/bitmask_operators.cc
index 3fd96493f2f..74c3f99490f 100644
--- a/libstdc++-v3/testsuite/27_io/ios_base/types/fmtflags/bitmask_operators.cc
+++ b/libstdc++-v3/testsuite/27_io/ios_base/types/fmtflags/bitmask_operators.cc
@@ -26,4 +26,4 @@
int main()
{
__gnu_test::bitmask_operators<std::ios_base::fmtflags>();
-};
+}
diff --git a/libstdc++-v3/testsuite/27_io/ios_base/types/iostate/bitmask_operators.cc b/libstdc++-v3/testsuite/27_io/ios_base/types/iostate/bitmask_operators.cc
index 3931db429e9..acfa45a8f62 100644
--- a/libstdc++-v3/testsuite/27_io/ios_base/types/iostate/bitmask_operators.cc
+++ b/libstdc++-v3/testsuite/27_io/ios_base/types/iostate/bitmask_operators.cc
@@ -26,4 +26,4 @@
int main()
{
__gnu_test::bitmask_operators<std::ios_base::iostate>();
-};
+}
diff --git a/libstdc++-v3/testsuite/27_io/ios_base/types/openmode/bitmask_operators.cc b/libstdc++-v3/testsuite/27_io/ios_base/types/openmode/bitmask_operators.cc
index cdb9b1b4055..c2e40bc06b5 100644
--- a/libstdc++-v3/testsuite/27_io/ios_base/types/openmode/bitmask_operators.cc
+++ b/libstdc++-v3/testsuite/27_io/ios_base/types/openmode/bitmask_operators.cc
@@ -26,4 +26,4 @@
int main()
{
__gnu_test::bitmask_operators<std::ios_base::openmode>();
-};
+}
diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/awk/cstring_01.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/awk/cstring_01.cc
index d4edf123e97..e2bde2216df 100644
--- a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/awk/cstring_01.cc
+++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/awk/cstring_01.cc
@@ -25,7 +25,9 @@
#include <regex>
#include <testsuite_hooks.h>
+#include <testsuite_regex.h>
+using namespace __gnu_test;
using namespace std;
void
@@ -34,12 +36,12 @@ test01()
bool test __attribute__((unused)) = true;
regex("\\[", regex_constants::awk);
- VERIFY(regex_match("\"", regex("[\\\"]", regex_constants::awk)));
- VERIFY(regex_match("/", regex("/", regex_constants::awk)));
- VERIFY(regex_match("\a", regex("\\a", regex_constants::awk)));
- VERIFY(regex_match("\"", regex("\\\"", regex_constants::awk)));
- VERIFY(regex_match("5", regex("\\65", regex_constants::awk)));
- VERIFY(regex_match("53", regex("\\0653", regex_constants::awk)));
+ VERIFY(regex_match_debug("\"", regex("[\\\"]", regex_constants::awk)));
+ VERIFY(regex_match_debug("/", regex("/", regex_constants::awk)));
+ VERIFY(regex_match_debug("\a", regex("\\a", regex_constants::awk)));
+ VERIFY(regex_match_debug("\"", regex("\\\"", regex_constants::awk)));
+ VERIFY(regex_match_debug("5", regex("\\65", regex_constants::awk)));
+ VERIFY(regex_match_debug("53", regex("\\0653", regex_constants::awk)));
}
int
diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/basic/empty_range.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/basic/empty_range.cc
index eb22569f337..dd0dac4392f 100644
--- a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/basic/empty_range.cc
+++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/basic/empty_range.cc
@@ -25,7 +25,9 @@
#include <regex>
#include <testsuite_hooks.h>
+#include <testsuite_regex.h>
+using namespace __gnu_test;
using namespace std;
void
@@ -45,8 +47,8 @@ test01()
}
FAIL("[]");
FAIL("[^]");
- VERIFY(regex_match("]", regex("[]]", regex_constants::basic)));
- VERIFY(!regex_match("]", regex("[^]]", regex_constants::basic)));
+ VERIFY(regex_match_debug ("]", regex("[]]", regex_constants::basic)));
+ VERIFY(!regex_match_debug ("]", regex("[^]]", regex_constants::basic)));
}
int
diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/basic/string_01.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/basic/string_01.cc
index 668309d8cbf..34cfa557f01 100644
--- a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/basic/string_01.cc
+++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/basic/string_01.cc
@@ -25,6 +25,10 @@
#include <regex>
#include <testsuite_hooks.h>
+#include <testsuite_regex.h>
+
+using namespace __gnu_test;
+using namespace std;
void
test01()
@@ -35,7 +39,7 @@ test01()
std::string target("aaba");
std::smatch m;
- VERIFY( std::regex_match(target, m, re) );
+ VERIFY( regex_match_debug(target, m, re) );
VERIFY( m.size() == re.mark_count()+1 );
VERIFY( m.empty() == false );
diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/basic/string_range_00_03.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/basic/string_range_00_03.cc
index 18783866f5e..36f032d7024 100644
--- a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/basic/string_range_00_03.cc
+++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/basic/string_range_00_03.cc
@@ -25,6 +25,10 @@
#include <regex>
#include <testsuite_hooks.h>
+#include <testsuite_regex.h>
+
+using namespace __gnu_test;
+using namespace std;
void
test01()
@@ -35,7 +39,7 @@ test01()
std::string target("aa");
std::smatch m;
- VERIFY( std::regex_match(target, m, re) );
+ VERIFY( regex_match_debug(target, m, re) );
VERIFY( m.size() == re.mark_count()+1 );
VERIFY( m.empty() == false );
diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/basic/string_range_01_03.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/basic/string_range_01_03.cc
index 93826a78fb3..812e3efa4d3 100644
--- a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/basic/string_range_01_03.cc
+++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/basic/string_range_01_03.cc
@@ -25,6 +25,10 @@
#include <regex>
#include <testsuite_hooks.h>
+#include <testsuite_regex.h>
+
+using namespace __gnu_test;
+using namespace std;
void
test01()
@@ -35,7 +39,7 @@ test01()
std::string target("aa");
std::smatch m;
- VERIFY( std::regex_match(target, m, re) );
+ VERIFY( regex_match_debug(target, m, re) );
VERIFY( m.size() == re.mark_count()+1 );
VERIFY( m.empty() == false );
diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/basic/string_range_02_03.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/basic/string_range_02_03.cc
index 91bc101392b..0924ed0014b 100644
--- a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/basic/string_range_02_03.cc
+++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/basic/string_range_02_03.cc
@@ -25,6 +25,10 @@
#include <regex>
#include <testsuite_hooks.h>
+#include <testsuite_regex.h>
+
+using namespace __gnu_test;
+using namespace std;
void
test01()
@@ -35,7 +39,7 @@ test01()
std::string target("aa");
std::smatch m;
- VERIFY( std::regex_match(target, m, re) );
+ VERIFY( regex_match_debug(target, m, re) );
VERIFY( m.size() == re.mark_count()+1 );
VERIFY( m.empty() == false );
diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/char/53622.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/char/53622.cc
new file mode 100644
index 00000000000..5a762ab6eb4
--- /dev/null
+++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/char/53622.cc
@@ -0,0 +1,70 @@
+// { dg-options "-std=gnu++11" }
+
+//
+// 2013-07-23 Tim Shen <timshen91@gmail.com>
+//
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// 28.11.2 regex_match
+
+#include <regex>
+#include <testsuite_hooks.h>
+#include <testsuite_regex.h>
+
+using namespace __gnu_test;
+using namespace std;
+
+// libstdc++/53622
+void
+test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ {
+ std::regex re("zxcv/(one.*)abc", std::regex::ECMAScript);
+ std::string target("zxcv/onetwoabc");
+ std::smatch m;
+
+ VERIFY( regex_match_debug(target, m, re) );
+ VERIFY( m.size() == 2 );
+ VERIFY( m[0].matched == true );
+ VERIFY( std::string(m[0].first, m[0].second) == "zxcv/onetwoabc" );
+ VERIFY( m[1].matched == true );
+ VERIFY( std::string(m[1].first, m[1].second) == "onetwo" );
+ }
+
+ {
+ std::regex re("zxcv/(one.*)abc()\\2", std::regex::ECMAScript);
+ std::string target("zxcv/onetwoabc");
+ std::smatch m;
+
+ VERIFY( regex_match_debug(target, m, re) );
+ VERIFY( m.size() == 3 );
+ VERIFY( m[0].matched == true );
+ VERIFY( std::string(m[0].first, m[0].second) == "zxcv/onetwoabc" );
+ VERIFY( m[1].matched == true );
+ VERIFY( std::string(m[1].first, m[1].second) == "onetwo" );
+ }
+}
+
+int
+main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/char/57173.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/char/57173.cc
new file mode 100644
index 00000000000..dc177e54274
--- /dev/null
+++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/char/57173.cc
@@ -0,0 +1,64 @@
+// { dg-options "-std=gnu++11" }
+
+//
+// 2013-07-23 Tim Shen <timshen91@gmail.com>
+//
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// 28.11.2 regex_match
+
+#include <regex>
+#include <testsuite_hooks.h>
+#include <testsuite_regex.h>
+
+using namespace __gnu_test;
+using namespace std;
+#include <iostream>
+
+// libstdc++/57173
+void
+test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ {
+ std::regex re("/asdf(/.*)", std::regex::ECMAScript);
+ std::string target("/asdf/qwerty");
+ std::smatch m;
+
+ VERIFY( regex_match_debug(target, m, re) );
+ VERIFY( m.size() == 2 );
+ VERIFY( std::string(m[1].first, m[1].second) == "/qwerty");
+ }
+ {
+ std::regex re("/asdf(/.*)()\\2", std::regex::ECMAScript);
+ std::string target("/asdf/qwerty");
+ std::smatch m;
+
+ VERIFY( regex_match_debug(target, m, re) );
+ VERIFY( m.size() == 3 );
+ VERIFY( std::string(m[1].first, m[1].second) == "/qwerty");
+ }
+}
+
+int
+main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/char/58576.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/char/58576.cc
new file mode 100644
index 00000000000..f745ef34e37
--- /dev/null
+++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/char/58576.cc
@@ -0,0 +1,100 @@
+// { dg-options "-std=gnu++11" }
+
+//
+// 2013-10-01 Tim Shen <timshen91@gmail.com>
+//
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// 28.11.2 regex_match
+
+#include <regex>
+#include <testsuite_hooks.h>
+#include <testsuite_regex.h>
+
+using namespace __gnu_test;
+using namespace std;
+
+// libstdc++/58576
+void
+test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ string domain_name = "valid.hostname.org";
+ /**
+ * based on http://stackoverflow.com/questions/1418423/the-hostname-regex
+ */
+ regex fqdn_regex
+ (
+ "^"
+ "(?=.{1,255}$)"
+ "[[:alnum:]]"
+ "("
+ "(([[:alnum:]]|-)"
+ "{0,61})"
+ "[[:alnum:]]"
+ ")?"
+ "("
+ "\\."
+ "[[:alnum:]]"
+ "("
+ "(([[:alnum:]]|-)"
+ "{0,61})"
+ "[[:alnum:]]"
+ ")?"
+ ")*"
+ "\\.?"
+ "$"
+ );
+
+ smatch m;
+ const char* sol[] =
+ {
+ "valid.hostname.org",
+ "alid",
+ "ali",
+ "i",
+ ".org",
+ "rg",
+ "r",
+ "r",
+ };
+ try
+ {
+ VERIFY(regex_match_debug( domain_name, m, fqdn_regex ));
+ VERIFY(m.size() == sizeof(sol) / sizeof(*sol));
+ for (size_t i = 0; i < m.size(); i++) {
+ string s(m[i].first, m[i].second);
+ VERIFY(s == sol[i]);
+ }
+ }
+ catch ( const regex_error& ex )
+ {
+ if ( ex.code() == regex_constants::error_brack )
+ {
+ throw;
+ }
+ }
+}
+
+int
+main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/char/anymatcher.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/char/anymatcher.cc
index 6e6095b8f24..866ff7fead8 100644
--- a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/char/anymatcher.cc
+++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/char/anymatcher.cc
@@ -25,7 +25,9 @@
#include <regex>
#include <testsuite_hooks.h>
+#include <testsuite_regex.h>
+using namespace __gnu_test;
using namespace std;
void
@@ -37,7 +39,7 @@ test01()
{\
regex re(res);\
string st(s);\
- VERIFY(!regex_match(st, re));\
+ VERIFY(!regex_match_debug(st, re));\
}
TEST(".", "\0");
TEST(".", "\n");
diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/char/backref.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/char/backref.cc
index 321ce35a038..05a57725d04 100644
--- a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/char/backref.cc
+++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/char/backref.cc
@@ -25,7 +25,9 @@
#include <regex>
#include <testsuite_hooks.h>
+#include <testsuite_regex.h>
+using namespace __gnu_test;
using namespace std;
void
diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/char/empty_range.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/char/empty_range.cc
index 3c48d3521a5..9f09c7463e8 100644
--- a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/char/empty_range.cc
+++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/char/empty_range.cc
@@ -25,7 +25,9 @@
#include <regex>
#include <testsuite_hooks.h>
+#include <testsuite_regex.h>
+using namespace __gnu_test;
using namespace std;
void
@@ -33,10 +35,10 @@ test01()
{
bool test __attribute__((unused)) = true;
- VERIFY(!regex_match("x", regex("[]")));
- VERIFY(regex_match("x", regex("[^]")));
- VERIFY(!regex_match("]", regex("[]]")));
- VERIFY(!regex_match("]", regex("[^]]")));
+ VERIFY(!regex_match_debug("x", regex("[]")));
+ VERIFY(regex_match_debug("x", regex("[^]")));
+ VERIFY(!regex_match_debug("]", regex("[]]")));
+ VERIFY(!regex_match_debug("]", regex("[^]]")));
}
int
diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/char/emptygroup.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/char/emptygroup.cc
index 1dc8f63f789..77fd43c0acb 100644
--- a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/char/emptygroup.cc
+++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/char/emptygroup.cc
@@ -25,7 +25,9 @@
#include <regex>
#include <testsuite_hooks.h>
+#include <testsuite_regex.h>
+using namespace __gnu_test;
using namespace std;
void
@@ -37,7 +39,7 @@ test01()
regex re("()*\\1");
cmatch m;
const char s[] = "";
- VERIFY( regex_match(s, m, re) );
+ VERIFY( regex_match_debug(s, m, re) );
VERIFY( m.size() == 2 );
VERIFY( m[0].matched );
VERIFY( m[1].matched );
@@ -46,7 +48,7 @@ test01()
regex re("()*");
cmatch m;
const char s[] = "";
- VERIFY( regex_match(s, m, re) );
+ VERIFY( regex_match_debug(s, m, re) );
}
}
diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/char/hex.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/char/hex.cc
index a73b742a5e4..b1030615ec3 100644
--- a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/char/hex.cc
+++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/char/hex.cc
@@ -25,7 +25,9 @@
#include <regex>
#include <testsuite_hooks.h>
+#include <testsuite_regex.h>
+using namespace __gnu_test;
using namespace std;
void
@@ -33,7 +35,7 @@ test01()
{
bool test __attribute__((unused)) = true;
- VERIFY(regex_match(":", regex("\\x3a")));
+ VERIFY(regex_match_debug(":", regex("\\x3a")));
try
{
regex("\\u400x");
diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/char/quoted_char.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/char/quoted_char.cc
index b54f5619a24..118c4722677 100644
--- a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/char/quoted_char.cc
+++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/char/quoted_char.cc
@@ -25,7 +25,9 @@
#include <regex>
#include <testsuite_hooks.h>
+#include <testsuite_regex.h>
+using namespace __gnu_test;
using namespace std;
void
@@ -33,15 +35,15 @@ test01()
{
bool test __attribute__((unused)) = true;
- VERIFY(regex_match("01", regex("\\d*")));
- VERIFY(regex_match("asdfjkl", regex("\\D*")));
- VERIFY(!regex_match("asdfjkl0", regex("\\D*")));
- VERIFY(regex_match("\r\t\v\f ", regex("\\s*")));
- VERIFY(regex_match("asdfjkl", regex("\\S*")));
- VERIFY(!regex_match("asdfjkl\r", regex("\\S*")));
- VERIFY(regex_match("_az", regex("\\w*")));
- VERIFY(regex_match("!@#$%", regex("\\W*")));
- VERIFY(!regex_match("_01234", regex("\\W*")));
+ VERIFY(regex_match_debug("01", regex("\\d*")));
+ VERIFY(regex_match_debug("asdfjkl", regex("\\D*")));
+ VERIFY(!regex_match_debug("asdfjkl0", regex("\\D*")));
+ VERIFY(regex_match_debug("\r\t\v\f ", regex("\\s*")));
+ VERIFY(regex_match_debug("asdfjkl", regex("\\S*")));
+ VERIFY(!regex_match_debug("asdfjkl\r", regex("\\S*")));
+ VERIFY(regex_match_debug("_az", regex("\\w*")));
+ VERIFY(regex_match_debug("!@#$%", regex("\\W*")));
+ VERIFY(!regex_match_debug("_01234", regex("\\W*")));
}
int
diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/char/ungreedy.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/char/ungreedy.cc
new file mode 100644
index 00000000000..ed26ebb89f0
--- /dev/null
+++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/char/ungreedy.cc
@@ -0,0 +1,50 @@
+// { dg-options "-std=gnu++11" }
+
+//
+// 2013-10-24 Tim Shen <timshen91@gmail.com>
+//
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// 28.11.2 regex_match
+// Tests ECMAScript ungreedy match.
+
+#include <regex>
+#include <testsuite_hooks.h>
+#include <testsuite_regex.h>
+
+using namespace __gnu_test;
+using namespace std;
+
+void
+test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ regex re("(a*?)*?");
+ cmatch m;
+ VERIFY(regex_match("a", m, re));
+ VERIFY(m.size() == 2);
+ VERIFY(string(m[0].first, m[0].second) == "a");
+}
+
+int
+main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/wchar_t/anymatcher.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/wchar_t/anymatcher.cc
index c574908d6a9..323a2ff4ed6 100644
--- a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/wchar_t/anymatcher.cc
+++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/wchar_t/anymatcher.cc
@@ -25,7 +25,9 @@
#include <regex>
#include <testsuite_hooks.h>
+#include <testsuite_regex.h>
+using namespace __gnu_test;
using namespace std;
void
@@ -37,7 +39,7 @@ test01()
{\
wregex re(res);\
wstring st(s);\
- VERIFY(!regex_match(st, re));\
+ VERIFY(!regex_match_debug(st, re));\
}
TESTL(L".", L"\u2028");
TESTL(L".", L"\u2029");
diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/wchar_t/cjk_match.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/wchar_t/cjk_match.cc
new file mode 100644
index 00000000000..15929ddc532
--- /dev/null
+++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/wchar_t/cjk_match.cc
@@ -0,0 +1,50 @@
+// { dg-options "-std=gnu++11" }
+
+//
+// 2013-10-18 Tim Shen <timshen91@gmail.com>
+//
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// 28.11.2 regex_match
+// Tests CJK support.
+
+#include <regex>
+#include <testsuite_hooks.h>
+#include <testsuite_regex.h>
+
+using namespace __gnu_test;
+using namespace std;
+
+void
+test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ const wchar_t * s = L"\u4f60\u597d\u002c\u0020\u4e16\u002b\u754c";
+
+ wregex re(s);
+ VERIFY(regex_match_debug(L"\u4f60\u597d\u002c\u0020\u4e16\u4e16\u4e16\u754c",
+ re));
+}
+
+int
+main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/wchar_t/hex.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/wchar_t/hex.cc
index f9561be70e2..876a7df1e2e 100644
--- a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/wchar_t/hex.cc
+++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/wchar_t/hex.cc
@@ -25,7 +25,9 @@
#include <regex>
#include <testsuite_hooks.h>
+#include <testsuite_regex.h>
+using namespace __gnu_test;
using namespace std;
void
@@ -33,7 +35,7 @@ test01()
{
bool test __attribute__((unused)) = true;
- VERIFY(regex_match(L"\u1234", wregex(L"\\u1234")));
+ VERIFY(regex_match_debug(L"\u1234", wregex(L"\\u1234")));
}
int
diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/53622.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/53622.cc
deleted file mode 100644
index aee1dbe15dc..00000000000
--- a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/53622.cc
+++ /dev/null
@@ -1,67 +0,0 @@
-// { dg-options "-std=gnu++11" }
-
-//
-// 2013-07-23 Tim Shen <timshen91@gmail.com>
-//
-// Copyright (C) 2013 Free Software Foundation, Inc.
-//
-// This file is part of the GNU ISO C++ Library. This library is free
-// software; you can redistribute it and/or modify it under the
-// terms of the GNU General Public License as published by the
-// Free Software Foundation; either version 3, or (at your option)
-// any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with this library; see the file COPYING3. If not see
-// <http://www.gnu.org/licenses/>.
-
-// 28.11.2 regex_match
-// Tests Extended grouping against a std::string target.
-
-#include <regex>
-#include <testsuite_hooks.h>
-
-// libstdc++/53622
-void
-test01()
-{
- bool test __attribute__((unused)) = true;
-
- {
- std::regex re("zxcv/(one.*)abc", std::regex::extended);
- std::string target("zxcv/onetwoabc");
- std::smatch m;
-
- VERIFY( std::regex_match(target, m, re) );
- VERIFY( m.size() == 2 );
- VERIFY( m[0].matched == true );
- VERIFY( std::string(m[0].first, m[0].second) == "zxcv/onetwoabc" );
- VERIFY( m[1].matched == true );
- VERIFY( std::string(m[1].first, m[1].second) == "onetwo" );
- }
-
- {
- std::regex re("zxcv/(one.*)abc()\\2", std::regex::extended);
- std::string target("zxcv/onetwoabc");
- std::smatch m;
-
- VERIFY( std::regex_match(target, m, re) );
- VERIFY( m.size() == 3 );
- VERIFY( m[0].matched == true );
- VERIFY( std::string(m[0].first, m[0].second) == "zxcv/onetwoabc" );
- VERIFY( m[1].matched == true );
- VERIFY( std::string(m[1].first, m[1].second) == "onetwo" );
- }
-}
-
-int
-main()
-{
- test01();
- return 0;
-}
diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/57173.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/57173.cc
deleted file mode 100644
index cb3a54f4d88..00000000000
--- a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/57173.cc
+++ /dev/null
@@ -1,61 +0,0 @@
-// { dg-options "-std=gnu++11" }
-
-//
-// 2013-07-23 Tim Shen <timshen91@gmail.com>
-//
-// Copyright (C) 2013 Free Software Foundation, Inc.
-//
-// This file is part of the GNU ISO C++ Library. This library is free
-// software; you can redistribute it and/or modify it under the
-// terms of the GNU General Public License as published by the
-// Free Software Foundation; either version 3, or (at your option)
-// any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with this library; see the file COPYING3. If not see
-// <http://www.gnu.org/licenses/>.
-
-// 28.11.3 regex_search
-// Tests Extended against a std::string target.
-
-#include <regex>
-#include <testsuite_hooks.h>
-#include <iostream>
-
-// libstdc++/57173
-void
-test01()
-{
- bool test __attribute__((unused)) = true;
-
- {
- std::regex re("/asdf(/.*)", std::regex::extended);
- std::string target("/asdf/qwerty");
- std::smatch m;
-
- VERIFY( std::regex_match(target, m, re) );
- VERIFY( m.size() == 2 );
- VERIFY( std::string(m[1].first, m[1].second) == "/qwerty");
- }
- {
- std::regex re("/asdf(/.*)()\\2", std::regex::extended);
- std::string target("/asdf/qwerty");
- std::smatch m;
-
- VERIFY( std::regex_match(target, m, re) );
- VERIFY( m.size() == 3 );
- VERIFY( std::string(m[1].first, m[1].second) == "/qwerty");
- }
-}
-
-int
-main()
-{
- test01();
- return 0;
-}
diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/cstring_bracket_01.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/cstring_bracket_01.cc
index 3a4ff31f104..c5f066bec81 100644
--- a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/cstring_bracket_01.cc
+++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/cstring_bracket_01.cc
@@ -25,6 +25,10 @@
#include <regex>
#include <testsuite_hooks.h>
+#include <testsuite_regex.h>
+
+using namespace __gnu_test;
+using namespace std;
void
test01()
@@ -33,28 +37,33 @@ test01()
{
std::regex re("pre/[za-x]", std::regex::extended);
- VERIFY( std::regex_match("pre/z", re) );
- VERIFY( std::regex_match("pre/a", re) );
- VERIFY( !std::regex_match("pre/y", re) );
+ VERIFY( regex_match_debug("pre/z", re) );
+ VERIFY( regex_match_debug("pre/a", re) );
+ VERIFY( !regex_match_debug("pre/y", re) );
}
{
std::regex re("pre/[[:uPPer:]]", std::regex::extended);
- VERIFY( std::regex_match("pre/Z", re) );
- VERIFY( !std::regex_match("pre/_", re) );
- VERIFY( !std::regex_match("pre/a", re) );
- VERIFY( !std::regex_match("pre/0", re) );
+ VERIFY( regex_match_debug("pre/Z", re) );
+ VERIFY( !regex_match_debug("pre/_", re) );
+ VERIFY( !regex_match_debug("pre/a", re) );
+ VERIFY( !regex_match_debug("pre/0", re) );
}
{
std::regex re("pre/[[:lOWer:]]", std::regex::extended | std::regex::icase);
- VERIFY( std::regex_match("pre/Z", re) );
- VERIFY( std::regex_match("pre/a", re) );
+ VERIFY( regex_match_debug("pre/Z", re) );
+ VERIFY( regex_match_debug("pre/a", re) );
}
{
std::regex re("pre/[[:w:][.tilde.]]", std::regex::extended);
- VERIFY( std::regex_match("pre/~", re) );
- VERIFY( std::regex_match("pre/_", re) );
- VERIFY( std::regex_match("pre/a", re) );
- VERIFY( std::regex_match("pre/0", re) );
+ VERIFY( regex_match_debug("pre/~", re) );
+ VERIFY( regex_match_debug("pre/_", re) );
+ VERIFY( regex_match_debug("pre/a", re) );
+ VERIFY( regex_match_debug("pre/0", re) );
+ }
+ {
+ std::regex re("pre/[[=a=]]", std::regex::extended);
+ VERIFY( regex_match_debug("pre/a", re) );
+ VERIFY( regex_match_debug("pre/A", re) );
}
}
diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/cstring_plus.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/cstring_plus.cc
index 375f34b8064..32bc24f9982 100644
--- a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/cstring_plus.cc
+++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/cstring_plus.cc
@@ -25,6 +25,10 @@
#include <regex>
#include <testsuite_hooks.h>
+#include <testsuite_regex.h>
+
+using namespace __gnu_test;
+using namespace std;
void
test01()
@@ -35,7 +39,7 @@ test01()
const char target[] = "aa";
std::cmatch m;
- VERIFY( std::regex_match(target, m, re) );
+ VERIFY( regex_match_debug(target, m, re) );
VERIFY( re.mark_count() == 1 );
VERIFY( m.size() == re.mark_count()+1 );
@@ -53,9 +57,9 @@ test01()
VERIFY( m[1].second == target+sizeof(target)-1 );
VERIFY( m[1].matched == true );
- VERIFY(!std::regex_match("", std::regex("a+", std::regex::extended)));
- VERIFY(std::regex_match("a", std::regex("a+", std::regex::extended)));
- VERIFY(std::regex_match("aa", std::regex("a+", std::regex::extended)));
+ VERIFY(!regex_match_debug("", std::regex("a+", std::regex::extended)));
+ VERIFY(regex_match_debug("a", std::regex("a+", std::regex::extended)));
+ VERIFY(regex_match_debug("aa", std::regex("a+", std::regex::extended)));
}
diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/cstring_questionmark.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/cstring_questionmark.cc
index 79b52a88c4f..90e9eafae60 100644
--- a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/cstring_questionmark.cc
+++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/cstring_questionmark.cc
@@ -25,6 +25,10 @@
#include <regex>
#include <testsuite_hooks.h>
+#include <testsuite_regex.h>
+
+using namespace __gnu_test;
+using namespace std;
void
test01()
@@ -35,7 +39,7 @@ test01()
char target[] = "a";
std::cmatch m;
- VERIFY( std::regex_match(target, m, re) );
+ VERIFY( regex_match_debug(target, m, re) );
VERIFY( re.mark_count() == 1 );
VERIFY( m.size() == re.mark_count()+1 );
@@ -53,9 +57,9 @@ test01()
VERIFY( m[1].second == target+sizeof(target)-1 );
VERIFY( m[1].matched == true );
- VERIFY(std::regex_match("", std::regex("a?", std::regex::extended)));
- VERIFY(std::regex_match("a", std::regex("a?", std::regex::extended)));
- VERIFY(!std::regex_match("aa", std::regex("a?", std::regex::extended)));
+ VERIFY(regex_match_debug("", std::regex("a?", std::regex::extended)));
+ VERIFY(regex_match_debug("a", std::regex("a?", std::regex::extended)));
+ VERIFY(!regex_match_debug("aa", std::regex("a?", std::regex::extended)));
}
diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/cstring_range.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/cstring_range.cc
index 62f825a0fb9..f9f7b6af1fd 100644
--- a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/cstring_range.cc
+++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/cstring_range.cc
@@ -25,7 +25,9 @@
#include <regex>
#include <testsuite_hooks.h>
+#include <testsuite_regex.h>
+using namespace __gnu_test;
using namespace std;
void
@@ -35,29 +37,29 @@ test01()
regex re;
re.assign("(ab){3}", std::regex::extended);
- VERIFY(!regex_match("abab", re));
- VERIFY(regex_match("ababab", re));
- VERIFY(!regex_match("abababab", re));
+ VERIFY(!regex_match_debug("abab", re));
+ VERIFY(regex_match_debug("ababab", re));
+ VERIFY(!regex_match_debug("abababab", re));
re.assign("(ab){3,}", std::regex::extended);
- VERIFY(!regex_match("abab", re));
- VERIFY(regex_match("ababab", re));
- VERIFY(regex_match("abababab", re));
- VERIFY(regex_match("ababababab", re));
+ VERIFY(!regex_match_debug("abab", re));
+ VERIFY(regex_match_debug("ababab", re));
+ VERIFY(regex_match_debug("abababab", re));
+ VERIFY(regex_match_debug("ababababab", re));
re.assign("(ab){0,3}", std::regex::extended);
- VERIFY(regex_match("", re));
- VERIFY(regex_match("ab", re));
- VERIFY(regex_match("abab", re));
- VERIFY(regex_match("ababab", re));
- VERIFY(!regex_match("abababab", re));
+ VERIFY(regex_match_debug("", re));
+ VERIFY(regex_match_debug("ab", re));
+ VERIFY(regex_match_debug("abab", re));
+ VERIFY(regex_match_debug("ababab", re));
+ VERIFY(!regex_match_debug("abababab", re));
re.assign("(a|b){0,2}", std::regex::extended);
- VERIFY(regex_match("", re));
- VERIFY(regex_match("a", re));
- VERIFY(regex_match("b", re));
- VERIFY(regex_match("aa", re));
- VERIFY(regex_match("ab", re));
- VERIFY(regex_match("ba", re));
- VERIFY(regex_match("bb", re));
- VERIFY(!regex_match("aaa", re));
+ VERIFY(regex_match_debug("", re));
+ VERIFY(regex_match_debug("a", re));
+ VERIFY(regex_match_debug("b", re));
+ VERIFY(regex_match_debug("aa", re));
+ VERIFY(regex_match_debug("ab", re));
+ VERIFY(regex_match_debug("ba", re));
+ VERIFY(regex_match_debug("bb", re));
+ VERIFY(!regex_match_debug("aaa", re));
}
int
diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/string_any.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/string_any.cc
index 57628f13215..cd870396781 100644
--- a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/string_any.cc
+++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/string_any.cc
@@ -25,6 +25,10 @@
#include <regex>
#include <testsuite_hooks.h>
+#include <testsuite_regex.h>
+
+using namespace __gnu_test;
+using namespace std;
void
test01()
@@ -35,7 +39,7 @@ test01()
std::string target("aaba");
std::smatch m;
- VERIFY( std::regex_match(target, m, re) );
+ VERIFY( regex_match_debug(target, m, re) );
VERIFY( m.size() == re.mark_count()+1 );
VERIFY( m.empty() == false );
diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/string_dispatch_01.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/string_dispatch_01.cc
deleted file mode 100644
index cb502eadfb4..00000000000
--- a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/string_dispatch_01.cc
+++ /dev/null
@@ -1,69 +0,0 @@
-// { dg-options "-std=gnu++11" }
-
-//
-// 2013-07-29 Tim Shen <timshen91@gmail.com>
-//
-// Copyright (C) 2013 Free Software Foundation, Inc.
-//
-// This file is part of the GNU ISO C++ Library. This library is free
-// software; you can redistribute it and/or modify it under the
-// terms of the GNU General Public License as published by the
-// Free Software Foundation; either version 3, or (at your option)
-// any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with this library; see the file COPYING3. If not see
-// <http://www.gnu.org/licenses/>.
-
-// 28.11.2 regex_match
-// Tests Extended automatic matcher dispatching against a std::string target.
-
-#include <regex>
-#include <testsuite_hooks.h>
-
-using namespace std;
-
-template<typename _Bi_iter, typename _Alloc,
- typename _Ch_type, typename _Rx_traits>
- void
- fake_match(_Bi_iter __s,
- _Bi_iter __e,
- match_results<_Bi_iter, _Alloc>& __m,
- const basic_regex<_Ch_type, _Rx_traits>& __re,
- regex_constants::match_flag_type __flags
- = regex_constants::match_default)
- {
- VERIFY( (dynamic_cast
- <__detail::_DFSExecutor<_Bi_iter, _Alloc, _Ch_type, _Rx_traits>*>
- (&*__detail::__get_executor(__s, __e, __m, __re, __flags))
- != nullptr) );
- }
-
-void
-test01()
-{
- bool test __attribute__((unused)) = true;
-
- regex re("()(one(.*))abc\\1"); // backref cause DFS
- const string target("onetwoabc");
- smatch m;
- fake_match(target.begin(), target.end(), m, re);
-
- regex_match(target, m, re);
- VERIFY( m[2].matched );
- VERIFY( m[3].matched );
- VERIFY( std::string(m[2].first, m[2].second) == "onetwo" );
- VERIFY( std::string(m[3].first, m[3].second) == "two" );
-}
-
-int
-main()
-{
- test01();
- return 0;
-}
diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/string_range_00_03.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/string_range_00_03.cc
index e10dba81ffa..e483b0abb9d 100644
--- a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/string_range_00_03.cc
+++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/string_range_00_03.cc
@@ -25,6 +25,9 @@
#include <regex>
#include <testsuite_hooks.h>
+#include <testsuite_regex.h>
+
+using namespace __gnu_test;
void
test01()
@@ -35,7 +38,7 @@ test01()
std::string target("aa");
std::smatch m;
- VERIFY( std::regex_match(target, m, re) );
+ VERIFY( regex_match_debug(target, m, re) );
VERIFY( m.size() == re.mark_count()+1 );
VERIFY( m.empty() == false );
diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/string_range_01_03.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/string_range_01_03.cc
index e715290c242..3879fc418aa 100644
--- a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/string_range_01_03.cc
+++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/string_range_01_03.cc
@@ -25,6 +25,10 @@
#include <regex>
#include <testsuite_hooks.h>
+#include <testsuite_regex.h>
+
+using namespace __gnu_test;
+using namespace std;
void
test01()
@@ -35,7 +39,7 @@ test01()
std::string target("aa");
std::smatch m;
- VERIFY( std::regex_match(target, m, re) );
+ VERIFY( regex_match_debug(target, m, re) );
VERIFY( m.size() == re.mark_count()+1 );
VERIFY( m.empty() == false );
diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/string_range_02_03.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/string_range_02_03.cc
index 62793b4a199..c2ebdf8b143 100644
--- a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/string_range_02_03.cc
+++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/string_range_02_03.cc
@@ -25,6 +25,10 @@
#include <regex>
#include <testsuite_hooks.h>
+#include <testsuite_regex.h>
+
+using namespace __gnu_test;
+using namespace std;
void
test01()
@@ -35,7 +39,7 @@ test01()
std::string target("aa");
std::smatch m;
- VERIFY( std::regex_match(target, m, re) );
+ VERIFY( regex_match_debug(target, m, re) );
VERIFY( m.size() == re.mark_count()+1 );
VERIFY( m.empty() == false );
diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/wstring_locale.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/wstring_locale.cc
index 6ab48ca6baf..ba0ecd5b4c4 100644
--- a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/wstring_locale.cc
+++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/wstring_locale.cc
@@ -26,6 +26,10 @@
#include <regex>
#include <testsuite_hooks.h>
+#include <testsuite_regex.h>
+
+using namespace __gnu_test;
+using namespace std;
void
test01()
@@ -37,7 +41,7 @@ test01()
re2.imbue(std::locale("de_DE.UTF-8"));
re2.assign(L"[[:upper:]]*", std::regex::extended);
std::wsmatch m2;
- VERIFY(std::regex_match(str2, m2, re2));
+ VERIFY(regex_match_debug(str2, m2, re2));
}
int
diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/regex_replace/char/basic_replace.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_replace/char/basic_replace.cc
new file mode 100644
index 00000000000..ca3f16f7d23
--- /dev/null
+++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_replace/char/basic_replace.cc
@@ -0,0 +1,51 @@
+// { dg-options "-std=gnu++11" }
+
+//
+// 2013-09-24 Tim Shen <timshen91@gmail.com>
+//
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// 28.11.4 regex_replace
+// Tests ECMAScript regex_replace.
+
+#include <regex>
+#include <testsuite_hooks.h>
+
+using namespace std;
+
+void
+test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ VERIFY(regex_replace(string("This is a string"), regex("\\b\\w*\\b"), "|$0|")
+ == "|This||| |is||| |a||| |string|||");
+ VERIFY(regex_replace(string("This is a string"), regex("\\b\\w*\\b"), "|$0|",
+ regex_constants::format_no_copy)
+ == "|This||||is||||a||||string|||");
+ VERIFY(regex_replace(string("This is a string"), regex("\\b\\w*\\b"), "|$0|",
+ regex_constants::format_first_only)
+ == "|This| is a string");
+}
+
+int
+main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/regex_search/basic/string_01.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_search/basic/string_01.cc
index ee487f19836..fed8e7dd17f 100644
--- a/libstdc++-v3/testsuite/28_regex/algorithms/regex_search/basic/string_01.cc
+++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_search/basic/string_01.cc
@@ -25,6 +25,10 @@
#include <regex>
#include <testsuite_hooks.h>
+#include <testsuite_regex.h>
+
+using namespace __gnu_test;
+using namespace std;
void
test01()
@@ -35,7 +39,7 @@ test01()
std::string target("xxasdfyy");
std::smatch m;
- VERIFY( std::regex_search(target, m, re) );
+ VERIFY( regex_search_debug(target, m, re) );
VERIFY( m.size() == re.mark_count()+1 );
VERIFY( m.empty() == false );
diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/regex_search/ecma/assertion.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_search/ecma/assertion.cc
index 3064b3b26e4..f7bce8023d3 100644
--- a/libstdc++-v3/testsuite/28_regex/algorithms/regex_search/ecma/assertion.cc
+++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_search/ecma/assertion.cc
@@ -25,7 +25,9 @@
#include <regex>
#include <testsuite_hooks.h>
+#include <testsuite_regex.h>
+using namespace __gnu_test;
using namespace std;
void
@@ -33,21 +35,21 @@ test01()
{
bool test __attribute__((unused)) = true;
- VERIFY(!regex_search("2123456", regex("^1234")));
- VERIFY(regex_search("123456", regex("^1234")));
- VERIFY(regex_search("123456", regex("(5|^)1234")));
- VERIFY(regex_search("5123456", regex("(5|^)1234")));
- VERIFY(!regex_search("1234562", regex("3456$")));
- VERIFY(regex_search("123456", regex("3456$")));
- VERIFY(!regex_search("123456", regex("(?=1234)56")));
- VERIFY(regex_search("123456", regex("(?=1234)123456")));
- VERIFY(regex_search("123456", regex("(?!1234)56")));
- VERIFY(!regex_search("123456", regex("(?!1234)123456")));
+ VERIFY(!regex_search_debug("2123456", regex("^1234")));
+ VERIFY(regex_search_debug("123456", regex("^1234")));
+ VERIFY(regex_search_debug("123456", regex("(5|^)1234")));
+ VERIFY(regex_search_debug("5123456", regex("(5|^)1234")));
+ VERIFY(!regex_search_debug("1234562", regex("3456$")));
+ VERIFY(regex_search_debug("123456", regex("3456$")));
+ VERIFY(!regex_search_debug("123456", regex("(?=1234)56")));
+ VERIFY(regex_search_debug("123456", regex("(?=1234)123456")));
+ VERIFY(regex_search_debug("123456", regex("(?!1234)56")));
+ VERIFY(!regex_search_debug("123456", regex("(?!1234)123456")));
- VERIFY(regex_search("a-", regex("a\\b-")));
- VERIFY(!regex_search("ab", regex("a\\bb")));
- VERIFY(!regex_search("a-", regex("a\\B-")));
- VERIFY(regex_search("ab", regex("a\\Bb")));
+ VERIFY(regex_search_debug("a-", regex("a\\b-")));
+ VERIFY(!regex_search_debug("ab", regex("a\\bb")));
+ VERIFY(!regex_search_debug("a-", regex("a\\B-")));
+ VERIFY(regex_search_debug("ab", regex("a\\Bb")));
string s("This is a regular expression");
string sol[] =
diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/regex_search/ecma/flags.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_search/ecma/flags.cc
index 4be406cb072..490ab1c9159 100644
--- a/libstdc++-v3/testsuite/28_regex/algorithms/regex_search/ecma/flags.cc
+++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_search/ecma/flags.cc
@@ -25,7 +25,9 @@
#include <regex>
#include <testsuite_hooks.h>
+#include <testsuite_regex.h>
+using namespace __gnu_test;
using namespace std;
void
@@ -35,32 +37,34 @@ test01()
cmatch m;
regex re("((as)(df))", regex_constants::ECMAScript | regex_constants::nosubs);
- VERIFY(regex_search("asdf", m, re));
+ VERIFY(regex_search_debug("asdf", m, re));
VERIFY(m.size() == 1);
VERIFY(m[0].matched && string(m[0].first, m[0].second) == "asdf");
- VERIFY( regex_search("a", regex("^a")));
- VERIFY(!regex_search("a", regex("^a"), regex_constants::match_not_bol));
- VERIFY( regex_search("a", regex("a$")));
- VERIFY(!regex_search("a", regex("a$"), regex_constants::match_not_eol));
- VERIFY( regex_search("a", regex("\\ba")));
- VERIFY(!regex_search("a", regex("\\ba"), regex_constants::match_not_bow));
- VERIFY( regex_search("a", regex("a\\b")));
- VERIFY(!regex_search("a", regex("a\\b"), regex_constants::match_not_eow));
- VERIFY( regex_search("", regex("")));
- VERIFY(!regex_search("", regex(""), regex_constants::match_not_null));
- VERIFY( regex_search("", regex("^$")));
- VERIFY(!regex_search("", regex("^$"), regex_constants::match_not_null));
- VERIFY( regex_search("aaa", m, regex("a*?"),
- regex_constants::match_not_null));
+ VERIFY( regex_search_debug("a", regex("^a")));
+ VERIFY(!regex_search_debug("a", regex("^a"), regex_constants::match_not_bol));
+ VERIFY( regex_search_debug("a", regex("a$")));
+ VERIFY(!regex_search_debug("a", regex("a$"), regex_constants::match_not_eol));
+ VERIFY( regex_search_debug("a", regex("\\ba")));
+ VERIFY(!regex_search_debug("a", regex("\\ba"),
+ regex_constants::match_not_bow));
+ VERIFY( regex_search_debug("a", regex("a\\b")));
+ VERIFY(!regex_search_debug("a", regex("a\\b"),
+ regex_constants::match_not_eow));
+ VERIFY( regex_search_debug("", regex("")));
+ VERIFY(!regex_search_debug("", regex(""), regex_constants::match_not_null));
+ VERIFY( regex_search_debug("", regex("^$")));
+ VERIFY(!regex_search_debug("", regex("^$"), regex_constants::match_not_null));
+ VERIFY( regex_search_debug("aaa", m, regex("a*?"),
+ regex_constants::match_not_null));
VERIFY(m[0].matched && string(m[0].first, m[0].second) == "a");
- VERIFY( regex_search("asdf", regex("sdf")));
- VERIFY(!regex_search("asdf", regex("sdf"),
- regex_constants::match_continuous));
- VERIFY( regex_search(" a"+1, regex("\\ba"),
- regex_constants::match_prev_avail));
- VERIFY( regex_search("ba"+1, regex("\\Ba"),
- regex_constants::match_prev_avail));
+ VERIFY( regex_search_debug("asdf", regex("sdf")));
+ VERIFY(!regex_search_debug("asdf", regex("sdf"),
+ regex_constants::match_continuous));
+ VERIFY( regex_search_debug(" a"+1, regex("\\ba"),
+ regex_constants::match_prev_avail));
+ VERIFY( regex_search_debug("ba"+1, regex("\\Ba"),
+ regex_constants::match_prev_avail));
}
int
diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/regex_search/ecma/greedy.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_search/ecma/greedy.cc
index ad37ec8649a..5821bba06b6 100644
--- a/libstdc++-v3/testsuite/28_regex/algorithms/regex_search/ecma/greedy.cc
+++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_search/ecma/greedy.cc
@@ -25,7 +25,9 @@
#include <regex>
#include <testsuite_hooks.h>
+#include <testsuite_regex.h>
+using namespace __gnu_test;
using namespace std;
void
@@ -35,30 +37,30 @@ test01()
cmatch m;
#define TEST(i, s) VERIFY(m[i].matched && string(m[i].first, m[i].second) == s)
- VERIFY(regex_search("aaaa", m, regex("a*")));
+ VERIFY(regex_search_debug("aaaa", m, regex("a*")));
TEST(0, "aaaa");
- VERIFY(regex_search("aaaa", m, regex("a*?")));
+ VERIFY(regex_search_debug("aaaa", m, regex("a*?")));
TEST(0, "");
- VERIFY(regex_search("aaaa", m, regex("a+")));
+ VERIFY(regex_search_debug("aaaa", m, regex("a+")));
TEST(0, "aaaa");
- VERIFY(regex_search("aaaa", m, regex("a+?")));
+ VERIFY(regex_search_debug("aaaa", m, regex("a+?")));
TEST(0, "a");
- VERIFY(regex_search("a", m, regex("a?")));
+ VERIFY(regex_search_debug("a", m, regex("a?")));
TEST(0, "a");
- VERIFY(regex_search("a", m, regex("a??")));
+ VERIFY(regex_search_debug("a", m, regex("a??")));
TEST(0, "");
- VERIFY(regex_search("", m, regex("a??")));
+ VERIFY(regex_search_debug("", m, regex("a??")));
TEST(0, "");
- VERIFY(regex_search("aaaa", m, regex("(a+)(a+)")));
+ VERIFY(regex_search_debug("aaaa", m, regex("(a+)(a+)")));
TEST(1, "aaa");
TEST(2, "a");
- VERIFY(regex_search("aaaa", m, regex("(a+?)(a+)")));
- TEST(1, "a");
- TEST(2, "aaa");
- VERIFY(regex_search("aaaa", m, regex("(a+?)(a+)")));
+ VERIFY(regex_search_debug("aaaa", m, regex("(a+)(a+?)")));
+ TEST(1, "aaa");
+ TEST(2, "a");
+ VERIFY(regex_search_debug("aaaa", m, regex("(a+?)(a+)")));
TEST(1, "a");
TEST(2, "aaa");
- VERIFY(regex_search("aaaa", m, regex("(a+?)(a+?)")));
+ VERIFY(regex_search_debug("aaaa", m, regex("(a+?)(a+?)")));
TEST(1, "a");
TEST(2, "a");
}
diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/regex_search/ecma/string_01.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_search/ecma/string_01.cc
index ec25875fdee..c07e7efa7d4 100644
--- a/libstdc++-v3/testsuite/28_regex/algorithms/regex_search/ecma/string_01.cc
+++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_search/ecma/string_01.cc
@@ -25,13 +25,17 @@
#include <regex>
#include <testsuite_hooks.h>
+#include <testsuite_regex.h>
+
+using namespace __gnu_test;
+using namespace std;
void
test01()
{
bool test __attribute__((unused)) = true;
- VERIFY(std::regex_search("", std::regex("")));
+ VERIFY(regex_search_debug("", std::regex("")));
}
int
diff --git a/libstdc++-v3/testsuite/28_regex/basic_regex/assign/char/cstring.cc b/libstdc++-v3/testsuite/28_regex/basic_regex/assign/char/cstring.cc
index 1b6c5327c4d..7340e7e45eb 100644
--- a/libstdc++-v3/testsuite/28_regex/basic_regex/assign/char/cstring.cc
+++ b/libstdc++-v3/testsuite/28_regex/basic_regex/assign/char/cstring.cc
@@ -41,4 +41,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/28_regex/basic_regex/assign/char/cstring_op.cc b/libstdc++-v3/testsuite/28_regex/basic_regex/assign/char/cstring_op.cc
index e7dfe8d3302..a28e95e8f83 100644
--- a/libstdc++-v3/testsuite/28_regex/basic_regex/assign/char/cstring_op.cc
+++ b/libstdc++-v3/testsuite/28_regex/basic_regex/assign/char/cstring_op.cc
@@ -40,4 +40,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/28_regex/basic_regex/assign/char/moveable.cc b/libstdc++-v3/testsuite/28_regex/basic_regex/assign/char/moveable.cc
index 18b3d5ef607..0897a0c28fc 100644
--- a/libstdc++-v3/testsuite/28_regex/basic_regex/assign/char/moveable.cc
+++ b/libstdc++-v3/testsuite/28_regex/basic_regex/assign/char/moveable.cc
@@ -30,16 +30,16 @@ void test01()
{
bool test __attribute__((unused)) = true;
- std::regex src_re("aaba");
+ std::regex src_re("aaba");
const unsigned mark_count = src_re.mark_count();
- const std::regex::flag_type flags = src_re.flags();
+ const std::regex::flag_type flags = src_re.flags();
- std::regex target_re;
+ std::regex target_re;
target_re.assign(std::move(src_re));
- VERIFY( target_re.flags() == flags );
- VERIFY( target_re.mark_count() == mark_count );
+ VERIFY( target_re.flags() == flags );
+ VERIFY( target_re.mark_count() == mark_count );
}
int
@@ -47,4 +47,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/28_regex/basic_regex/assign/char/pstring.cc b/libstdc++-v3/testsuite/28_regex/basic_regex/assign/char/pstring.cc
index f5c6ff2a1ab..63f93c2dd3b 100644
--- a/libstdc++-v3/testsuite/28_regex/basic_regex/assign/char/pstring.cc
+++ b/libstdc++-v3/testsuite/28_regex/basic_regex/assign/char/pstring.cc
@@ -40,4 +40,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/28_regex/basic_regex/assign/char/range.cc b/libstdc++-v3/testsuite/28_regex/basic_regex/assign/char/range.cc
index f871ff1111b..c08ac06d560 100644
--- a/libstdc++-v3/testsuite/28_regex/basic_regex/assign/char/range.cc
+++ b/libstdc++-v3/testsuite/28_regex/basic_regex/assign/char/range.cc
@@ -40,4 +40,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/28_regex/basic_regex/assign/char/string.cc b/libstdc++-v3/testsuite/28_regex/basic_regex/assign/char/string.cc
index 2f75c7b6254..ed3fcdf7327 100644
--- a/libstdc++-v3/testsuite/28_regex/basic_regex/assign/char/string.cc
+++ b/libstdc++-v3/testsuite/28_regex/basic_regex/assign/char/string.cc
@@ -41,4 +41,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/28_regex/basic_regex/assign/char/string_op.cc b/libstdc++-v3/testsuite/28_regex/basic_regex/assign/char/string_op.cc
index 752cf485363..a975761201f 100644
--- a/libstdc++-v3/testsuite/28_regex/basic_regex/assign/char/string_op.cc
+++ b/libstdc++-v3/testsuite/28_regex/basic_regex/assign/char/string_op.cc
@@ -41,4 +41,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/28_regex/basic_regex/assign/wchar_t/cstring.cc b/libstdc++-v3/testsuite/28_regex/basic_regex/assign/wchar_t/cstring.cc
index 00db1f33499..8ce2b3bd111 100644
--- a/libstdc++-v3/testsuite/28_regex/basic_regex/assign/wchar_t/cstring.cc
+++ b/libstdc++-v3/testsuite/28_regex/basic_regex/assign/wchar_t/cstring.cc
@@ -41,4 +41,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/28_regex/basic_regex/assign/wchar_t/cstring_op.cc b/libstdc++-v3/testsuite/28_regex/basic_regex/assign/wchar_t/cstring_op.cc
index 3da1a10fb4a..415cbb6b884 100644
--- a/libstdc++-v3/testsuite/28_regex/basic_regex/assign/wchar_t/cstring_op.cc
+++ b/libstdc++-v3/testsuite/28_regex/basic_regex/assign/wchar_t/cstring_op.cc
@@ -41,4 +41,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/28_regex/basic_regex/assign/wchar_t/pstring.cc b/libstdc++-v3/testsuite/28_regex/basic_regex/assign/wchar_t/pstring.cc
index 4664166d2f5..aaf69c6456d 100644
--- a/libstdc++-v3/testsuite/28_regex/basic_regex/assign/wchar_t/pstring.cc
+++ b/libstdc++-v3/testsuite/28_regex/basic_regex/assign/wchar_t/pstring.cc
@@ -40,4 +40,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/28_regex/basic_regex/assign/wchar_t/range.cc b/libstdc++-v3/testsuite/28_regex/basic_regex/assign/wchar_t/range.cc
index 8f65898427b..f52e675ab56 100644
--- a/libstdc++-v3/testsuite/28_regex/basic_regex/assign/wchar_t/range.cc
+++ b/libstdc++-v3/testsuite/28_regex/basic_regex/assign/wchar_t/range.cc
@@ -41,4 +41,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/28_regex/basic_regex/assign/wchar_t/string.cc b/libstdc++-v3/testsuite/28_regex/basic_regex/assign/wchar_t/string.cc
index d3c0f2daf31..1a9801ff7af 100644
--- a/libstdc++-v3/testsuite/28_regex/basic_regex/assign/wchar_t/string.cc
+++ b/libstdc++-v3/testsuite/28_regex/basic_regex/assign/wchar_t/string.cc
@@ -42,4 +42,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/28_regex/basic_regex/assign/wchar_t/string_op.cc b/libstdc++-v3/testsuite/28_regex/basic_regex/assign/wchar_t/string_op.cc
index c3e88b3f594..38645660acd 100644
--- a/libstdc++-v3/testsuite/28_regex/basic_regex/assign/wchar_t/string_op.cc
+++ b/libstdc++-v3/testsuite/28_regex/basic_regex/assign/wchar_t/string_op.cc
@@ -42,4 +42,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/47724.cc b/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/47724.cc
index cf25dd44a9c..12ab1bbc9ab 100644
--- a/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/47724.cc
+++ b/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/47724.cc
@@ -31,4 +31,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/basic/pstring_char.cc b/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/basic/pstring_char.cc
index 255f5bf5170..db5ae80b53a 100644
--- a/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/basic/pstring_char.cc
+++ b/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/basic/pstring_char.cc
@@ -39,4 +39,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/basic/pstring_wchar_t.cc b/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/basic/pstring_wchar_t.cc
index 7cf48068914..c0cc841b94f 100644
--- a/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/basic/pstring_wchar_t.cc
+++ b/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/basic/pstring_wchar_t.cc
@@ -41,4 +41,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/basic/raw_string.cc b/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/basic/raw_string.cc
index 68fd56af760..d005dc040eb 100644
--- a/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/basic/raw_string.cc
+++ b/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/basic/raw_string.cc
@@ -1,5 +1,4 @@
-// { dg-options "-std=c++0x" }
-// { dg-do run { xfail *-*-* } }
+// { dg-options "-std=gnu++11" }
// 2012-08-20 Benjamin Kosnik <bkoz@redhat.com>
//
diff --git a/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/char/cstring.cc b/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/char/cstring.cc
index a081ecbcf42..cda2ad2da44 100644
--- a/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/char/cstring.cc
+++ b/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/char/cstring.cc
@@ -39,4 +39,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/char/default.cc b/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/char/default.cc
index aa8d70c57db..ed31f38e55e 100644
--- a/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/char/default.cc
+++ b/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/char/default.cc
@@ -44,4 +44,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/char/range.cc b/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/char/range.cc
index b26151e41d1..63d32bc3a02 100644
--- a/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/char/range.cc
+++ b/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/char/range.cc
@@ -39,4 +39,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/copy_char.cc b/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/copy_char.cc
index c51bfa0c95a..228c7fd8941 100644
--- a/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/copy_char.cc
+++ b/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/copy_char.cc
@@ -42,4 +42,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/move_char.cc b/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/move_char.cc
index 3234f565be1..1311987e92f 100644
--- a/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/move_char.cc
+++ b/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/move_char.cc
@@ -46,4 +46,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/string_char.cc b/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/string_char.cc
index 50d64dbb6e5..88411e579f6 100644
--- a/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/string_char.cc
+++ b/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/string_char.cc
@@ -51,4 +51,4 @@ main()
test01();
test02();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/string_wchar_t.cc b/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/string_wchar_t.cc
index ffc9ba93c4d..c0d3b23fd95 100644
--- a/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/string_wchar_t.cc
+++ b/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/string_wchar_t.cc
@@ -53,4 +53,4 @@ main()
test01();
test02();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/wchar_t/cstring.cc b/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/wchar_t/cstring.cc
index a8f1879aab5..ad79c097b64 100644
--- a/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/wchar_t/cstring.cc
+++ b/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/wchar_t/cstring.cc
@@ -40,4 +40,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/wchar_t/default.cc b/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/wchar_t/default.cc
index 6b99b1d9beb..c2e3cc56a39 100644
--- a/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/wchar_t/default.cc
+++ b/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/wchar_t/default.cc
@@ -45,4 +45,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/wchar_t/range.cc b/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/wchar_t/range.cc
index cf8217a9a6f..a0a680c823e 100644
--- a/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/wchar_t/range.cc
+++ b/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/wchar_t/range.cc
@@ -40,4 +40,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/28_regex/match_results/format.cc b/libstdc++-v3/testsuite/28_regex/match_results/format.cc
new file mode 100644
index 00000000000..659ffdcb13b
--- /dev/null
+++ b/libstdc++-v3/testsuite/28_regex/match_results/format.cc
@@ -0,0 +1,53 @@
+// { dg-options "-std=gnu++11" }
+
+//
+// 2013-09-24 Tim Shen <timshen91@gmail.com>
+//
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// 28.10.5 formatting
+// Tests ECMAScript format()
+
+#include <regex>
+#include <testsuite_hooks.h>
+#include <testsuite_regex.h>
+
+using namespace std;
+using namespace __gnu_test;
+
+void
+test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ cmatch m;
+ VERIFY(regex_search_debug("*** this is a string !!!", m,
+ regex("(\\w+) (\\w+) (\\w+) (\\w+)")));
+ VERIFY(m.format("$&|$`|$3|$4|$2|$1|$'$$$")
+ == "this is a string|*** |a|string|is|this| !!!$$");
+ VERIFY(m.format("&|\\3|\\4|\\2|\\1|\\",
+ regex_constants::format_sed)
+ == "this is a string|a|string|is|this|\\");
+}
+
+int
+main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/28_regex/traits/char/ctor.cc b/libstdc++-v3/testsuite/28_regex/traits/char/ctor.cc
index b41e59ac5ff..e3ee30cdfa6 100644
--- a/libstdc++-v3/testsuite/28_regex/traits/char/ctor.cc
+++ b/libstdc++-v3/testsuite/28_regex/traits/char/ctor.cc
@@ -47,4 +47,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/28_regex/traits/char/lookup_collatename.cc b/libstdc++-v3/testsuite/28_regex/traits/char/lookup_collatename.cc
index 7e0b259e0b7..dba0fc357e5 100644
--- a/libstdc++-v3/testsuite/28_regex/traits/char/lookup_collatename.cc
+++ b/libstdc++-v3/testsuite/28_regex/traits/char/lookup_collatename.cc
@@ -35,12 +35,9 @@ test01()
typedef char CharT;
typedef std::regex_traits<CharT> traits;
- char name[] = "ll";
- traits t;
-
- traits::string_type sname = t.lookup_collatename(name, name+sizeof(name)-1);
-
- VERIFY( !sname.empty() );
+ traits t;
+ CharT name[] = "tilde";
+ VERIFY(t.lookup_collatename(name, name+sizeof(name)-1) == "~");
}
int main()
diff --git a/libstdc++-v3/testsuite/28_regex/traits/char/translate_nocase.cc b/libstdc++-v3/testsuite/28_regex/traits/char/translate_nocase.cc
index c805aa91e68..02e2eaefe44 100644
--- a/libstdc++-v3/testsuite/28_regex/traits/char/translate_nocase.cc
+++ b/libstdc++-v3/testsuite/28_regex/traits/char/translate_nocase.cc
@@ -43,4 +43,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/28_regex/traits/char/value.cc b/libstdc++-v3/testsuite/28_regex/traits/char/value.cc
index e68dac64e03..de0b2694121 100644
--- a/libstdc++-v3/testsuite/28_regex/traits/char/value.cc
+++ b/libstdc++-v3/testsuite/28_regex/traits/char/value.cc
@@ -46,4 +46,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/28_regex/traits/wchar_t/ctor.cc b/libstdc++-v3/testsuite/28_regex/traits/wchar_t/ctor.cc
index f2d487eb6a9..54931d01b83 100644
--- a/libstdc++-v3/testsuite/28_regex/traits/wchar_t/ctor.cc
+++ b/libstdc++-v3/testsuite/28_regex/traits/wchar_t/ctor.cc
@@ -46,4 +46,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/28_regex/traits/wchar_t/lookup_collatename.cc b/libstdc++-v3/testsuite/28_regex/traits/wchar_t/lookup_collatename.cc
index 197bb9b4a78..3d20cfaf9a0 100644
--- a/libstdc++-v3/testsuite/28_regex/traits/wchar_t/lookup_collatename.cc
+++ b/libstdc++-v3/testsuite/28_regex/traits/wchar_t/lookup_collatename.cc
@@ -33,13 +33,9 @@ test01()
typedef wchar_t CharT;
typedef std::regex_traits<CharT> traits;
- wchar_t name[] = L"ll";
- traits t;
-
- traits::string_type sname =
- t.lookup_collatename(name, name+sizeof(name)/sizeof(*name)-1);
-
- VERIFY( !sname.empty() );
+ traits t;
+ CharT name[] = L"tilde";
+ VERIFY(t.lookup_collatename(name, name+sizeof(name)/sizeof(*name)-1) == L"~");
}
int main()
diff --git a/libstdc++-v3/testsuite/28_regex/traits/wchar_t/translate_nocase.cc b/libstdc++-v3/testsuite/28_regex/traits/wchar_t/translate_nocase.cc
index 2793f8c3af7..5aa11d33978 100644
--- a/libstdc++-v3/testsuite/28_regex/traits/wchar_t/translate_nocase.cc
+++ b/libstdc++-v3/testsuite/28_regex/traits/wchar_t/translate_nocase.cc
@@ -43,4 +43,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/28_regex/traits/wchar_t/value.cc b/libstdc++-v3/testsuite/28_regex/traits/wchar_t/value.cc
index 6d5885cc627..2ad3354d6f0 100644
--- a/libstdc++-v3/testsuite/28_regex/traits/wchar_t/value.cc
+++ b/libstdc++-v3/testsuite/28_regex/traits/wchar_t/value.cc
@@ -46,4 +46,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/29_atomics/atomic/cons/49445.cc b/libstdc++-v3/testsuite/29_atomics/atomic/cons/49445.cc
index 793b58d9549..e45e777dc7b 100644
--- a/libstdc++-v3/testsuite/29_atomics/atomic/cons/49445.cc
+++ b/libstdc++-v3/testsuite/29_atomics/atomic/cons/49445.cc
@@ -1,3 +1,4 @@
+// { dg-require-atomic-builtins "" }
// { dg-options "-std=gnu++0x" }
// Copyright (C) 2012-2013 Free Software Foundation, Inc.
diff --git a/libstdc++-v3/testsuite/29_atomics/atomic/operators/pointer_partial_void.cc b/libstdc++-v3/testsuite/29_atomics/atomic/operators/pointer_partial_void.cc
index fa936a17ee2..3a4377fb6e4 100644
--- a/libstdc++-v3/testsuite/29_atomics/atomic/operators/pointer_partial_void.cc
+++ b/libstdc++-v3/testsuite/29_atomics/atomic/operators/pointer_partial_void.cc
@@ -42,28 +42,28 @@ int main(void)
a++;
void* vp3(a);
dist = reinterpret_cast<char*>(vp2) - reinterpret_cast<char*>(vp3);
- // VERIFY ( std::abs(dist) == sizeof(void*));
+ VERIFY ( std::abs(dist) == 1 );
// operator--
void* vp4(a);
a--;
void* vp5(a);
dist = reinterpret_cast<char*>(vp4) - reinterpret_cast<char*>(vp5);
- // VERIFY ( std::abs(dist) == sizeof(void*));
+ VERIFY ( std::abs(dist) == 1 );
// operator+=
void* vp6(a);
a+=n;
void* vp7(a);
dist = reinterpret_cast<char*>(vp6) - reinterpret_cast<char*>(vp7);
- // VERIFY ( std::abs(dist) == sizeof(void*) * n);
+ VERIFY ( std::abs(dist) == n );
// operator-=
void* vp8(a);
a-=n;
void* vp9(a);
dist = reinterpret_cast<char*>(vp8) - reinterpret_cast<char*>(vp9);
- //VERIFY ( std::abs(dist) == sizeof(void*) * n);
+ VERIFY ( std::abs(dist) == n );
return 0;
}
diff --git a/libstdc++-v3/testsuite/29_atomics/atomic_integral/operators/bitwise.cc b/libstdc++-v3/testsuite/29_atomics/atomic_integral/operators/bitwise.cc
index 0c2ad78528d..052afc305ce 100644
--- a/libstdc++-v3/testsuite/29_atomics/atomic_integral/operators/bitwise.cc
+++ b/libstdc++-v3/testsuite/29_atomics/atomic_integral/operators/bitwise.cc
@@ -26,4 +26,4 @@ int main()
__gnu_test::has_bitwise_operators test;
using __gnu_test::atomic_integrals_no_bool;
__gnu_cxx::typelist::apply_generator(test, atomic_integrals_no_bool::type());
-};
+}
diff --git a/libstdc++-v3/testsuite/29_atomics/atomic_integral/operators/decrement.cc b/libstdc++-v3/testsuite/29_atomics/atomic_integral/operators/decrement.cc
index 512478aa64c..891a37b0db8 100644
--- a/libstdc++-v3/testsuite/29_atomics/atomic_integral/operators/decrement.cc
+++ b/libstdc++-v3/testsuite/29_atomics/atomic_integral/operators/decrement.cc
@@ -26,4 +26,4 @@ int main()
__gnu_test::has_decrement_operators test;
using __gnu_test::atomic_integrals_no_bool;
__gnu_cxx::typelist::apply_generator(test, atomic_integrals_no_bool::type());
-};
+}
diff --git a/libstdc++-v3/testsuite/29_atomics/atomic_integral/operators/increment.cc b/libstdc++-v3/testsuite/29_atomics/atomic_integral/operators/increment.cc
index 5979cfa7273..7d269a9f29d 100644
--- a/libstdc++-v3/testsuite/29_atomics/atomic_integral/operators/increment.cc
+++ b/libstdc++-v3/testsuite/29_atomics/atomic_integral/operators/increment.cc
@@ -26,4 +26,4 @@ int main()
__gnu_test::has_increment_operators test;
using __gnu_test::atomic_integrals_no_bool;
__gnu_cxx::typelist::apply_generator(test, atomic_integrals_no_bool::type());
-};
+}
diff --git a/libstdc++-v3/testsuite/decimal/pr58815.cc b/libstdc++-v3/testsuite/decimal/pr58815.cc
new file mode 100644
index 00000000000..1924ab999bf
--- /dev/null
+++ b/libstdc++-v3/testsuite/decimal/pr58815.cc
@@ -0,0 +1,35 @@
+// { dg-options "-std=gnu++11" }
+//
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do compile }
+// { dg-require-effective-target dfp }
+
+#include <decimal/decimal>
+
+void
+test01 ()
+{
+ std::decimal::decimal32 d32(0);
+ std::decimal::decimal64 d64(0);
+ std::decimal::decimal128 d128(0);
+
+ static_cast<long long>(d32);
+ static_cast<long long>(d64);
+ static_cast<long long>(d128);
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/assignment/1.cc b/libstdc++-v3/testsuite/experimental/optional/assignment/1.cc
new file mode 100644
index 00000000000..b09e0acde74
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/assignment/1.cc
@@ -0,0 +1,195 @@
+// { dg-options "-std=gnu++1y" }
+// { dg-do run }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+struct exception {};
+
+int counter = 0;
+
+struct mixin_counter
+{
+ mixin_counter() { ++counter; }
+ mixin_counter(mixin_counter const&) { ++counter; }
+ ~mixin_counter() { --counter; }
+};
+
+struct value_type : private mixin_counter
+{
+ enum state_type
+ {
+ zero,
+ moved_from,
+ throwing_construction,
+ throwing_copy,
+ throwing_copy_assignment,
+ throwing_move,
+ throwing_move_assignment,
+ threw,
+ };
+
+ value_type() = default;
+
+ explicit value_type(state_type state_)
+ : state(state_)
+ {
+ throw_if(throwing_construction);
+ }
+
+ value_type(value_type const& other)
+ : state(other.state)
+ {
+ throw_if(throwing_copy);
+ }
+
+ value_type&
+ operator=(value_type const& other)
+ {
+ state = other.state;
+ throw_if(throwing_copy_assignment);
+ return *this;
+ }
+
+ value_type(value_type&& other)
+ : state(other.state)
+ {
+ other.state = moved_from;
+ throw_if(throwing_move);
+ }
+
+ value_type&
+ operator=(value_type&& other)
+ {
+ state = other.state;
+ other.state = moved_from;
+ throw_if(throwing_move_assignment);
+ return *this;
+ }
+
+ void throw_if(state_type match)
+ {
+ if(state == match)
+ {
+ state = threw;
+ throw exception {};
+ }
+ }
+
+ state_type state = zero;
+};
+
+int main()
+{
+ using O = std::experimental::optional<value_type>;
+ using S = value_type::state_type;
+ auto const make = [](S s = S::zero) { return O { std::experimental::in_place, s }; };
+
+ enum outcome_type { nothrow, caught, bad_catch };
+
+ // Check copy/move assignment for disengaged optional
+
+ // From disengaged optional
+ {
+ O o;
+ VERIFY( !o );
+ O p;
+ o = p;
+ VERIFY( !o );
+ VERIFY( !p );
+ }
+
+ {
+ O o;
+ VERIFY( !o );
+ O p;
+ o = std::move(p);
+ VERIFY( !o );
+ VERIFY( !p );
+ }
+
+ {
+ O o;
+ VERIFY( !o );
+ o = {};
+ VERIFY( !o );
+ }
+
+ // From engaged optional
+ {
+ O o;
+ VERIFY( !o );
+ O p = make(S::throwing_copy_assignment);
+ o = p;
+ VERIFY( o && o->state == S::throwing_copy_assignment );
+ VERIFY( p && p->state == S::throwing_copy_assignment );
+ }
+
+ {
+ O o;
+ VERIFY( !o );
+ O p = make(S::throwing_move_assignment);
+ o = std::move(p);
+ VERIFY( o && o->state == S::throwing_move_assignment );
+ VERIFY( p && p->state == S::moved_from );
+ }
+
+ {
+ outcome_type outcome {};
+ O o;
+ VERIFY( !o );
+ O p = make(S::throwing_copy);
+
+ try
+ {
+ o = p;
+ }
+ catch(exception const&)
+ { outcome = caught; }
+ catch(...)
+ { outcome = bad_catch; }
+
+ VERIFY( outcome == caught );
+ VERIFY( !o );
+ VERIFY( p && p->state == S::throwing_copy );
+ }
+
+ {
+ outcome_type outcome {};
+ O o;
+ VERIFY( !o );
+ O p = make(S::throwing_move);
+
+ try
+ {
+ o = std::move(p);
+ }
+ catch(exception const&)
+ { outcome = caught; }
+ catch(...)
+ { outcome = bad_catch; }
+
+ VERIFY( outcome == caught );
+ VERIFY( !o );
+ VERIFY( p && p->state == S::moved_from );
+ }
+
+ VERIFY( counter == 0 );
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/assignment/2.cc b/libstdc++-v3/testsuite/experimental/optional/assignment/2.cc
new file mode 100644
index 00000000000..7985fffe8f7
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/assignment/2.cc
@@ -0,0 +1,193 @@
+// { dg-options "-std=gnu++1y" }
+// { dg-do run }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+struct exception {};
+
+int counter = 0;
+
+struct mixin_counter
+{
+ mixin_counter() { ++counter; }
+ mixin_counter(mixin_counter const&) { ++counter; }
+ ~mixin_counter() { --counter; }
+};
+
+struct value_type : private mixin_counter
+{
+ enum state_type
+ {
+ zero,
+ moved_from,
+ throwing_construction,
+ throwing_copy,
+ throwing_copy_assignment,
+ throwing_move,
+ throwing_move_assignment,
+ threw,
+ };
+
+ value_type() = default;
+
+ explicit value_type(state_type state_)
+ : state(state_)
+ {
+ throw_if(throwing_construction);
+ }
+
+ value_type(value_type const& other)
+ : state(other.state)
+ {
+ throw_if(throwing_copy);
+ }
+
+ value_type&
+ operator=(value_type const& other)
+ {
+ state = other.state;
+ throw_if(throwing_copy_assignment);
+ return *this;
+ }
+
+ value_type(value_type&& other)
+ : state(other.state)
+ {
+ other.state = moved_from;
+ throw_if(throwing_move);
+ }
+
+ value_type&
+ operator=(value_type&& other)
+ {
+ state = other.state;
+ other.state = moved_from;
+ throw_if(throwing_move_assignment);
+ return *this;
+ }
+
+ void throw_if(state_type match)
+ {
+ if(state == match)
+ {
+ state = threw;
+ throw exception {};
+ }
+ }
+
+ state_type state = zero;
+};
+
+int main()
+{
+ using O = std::experimental::optional<value_type>;
+ using S = value_type::state_type;
+ auto const make = [](S s = S::zero) { return O { std::experimental::in_place, s }; };
+
+ enum outcome_type { nothrow, caught, bad_catch };
+
+ // Check copy/move assignment for engaged optional
+
+ // From disengaged optional
+ {
+ O o = make(S::zero);
+ VERIFY( o );
+ O p;
+ o = p;
+ VERIFY( !o );
+ VERIFY( !p );
+ }
+
+ {
+ O o = make(S::zero);
+ VERIFY( o );
+ O p;
+ o = std::move(p);
+ VERIFY( !o );
+ VERIFY( !p );
+ }
+
+ {
+ O o = make(S::zero);
+ VERIFY( o );
+ o = {};
+ VERIFY( !o );
+ }
+
+ // From engaged optional
+ {
+ O o = make(S::zero);
+ VERIFY( o );
+ O p = make(S::throwing_copy);
+ o = p;
+ VERIFY( o && o->state == S::throwing_copy);
+ VERIFY( p && p->state == S::throwing_copy);
+ }
+
+ {
+ O o = make(S::zero);
+ VERIFY( o );
+ O p = make(S::throwing_move);
+ o = std::move(p);
+ VERIFY( o && o->state == S::throwing_move);
+ VERIFY( p && p->state == S::moved_from);
+ }
+
+ {
+ outcome_type outcome {};
+ O o = make(S::zero);
+ VERIFY( o );
+ O p = make(S::throwing_copy_assignment);
+
+ try
+ {
+ o = p;
+ }
+ catch(exception const&)
+ { outcome = caught; }
+ catch(...)
+ { outcome = bad_catch; }
+
+ VERIFY( o && o->state == S::threw);
+ VERIFY( p && p->state == S::throwing_copy_assignment);
+ }
+
+ {
+ outcome_type outcome {};
+ O o = make(S::zero);
+ VERIFY( o );
+ O p = make(S::throwing_move_assignment);
+
+ try
+ {
+ o = std::move(p);
+ }
+ catch(exception const&)
+ { outcome = caught; }
+ catch(...)
+ { outcome = bad_catch; }
+
+ VERIFY( o && o->state == S::threw);
+ VERIFY( p && p->state == S::moved_from);
+ }
+
+ VERIFY( counter == 0 );
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/assignment/3.cc b/libstdc++-v3/testsuite/experimental/optional/assignment/3.cc
new file mode 100644
index 00000000000..d631886269c
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/assignment/3.cc
@@ -0,0 +1,158 @@
+// { dg-options "-std=gnu++1y" }
+// { dg-do run }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+struct exception {};
+
+int counter = 0;
+
+struct mixin_counter
+{
+ mixin_counter() { ++counter; }
+ mixin_counter(mixin_counter const&) { ++counter; }
+ ~mixin_counter() { --counter; }
+};
+
+struct value_type : private mixin_counter
+{
+ enum state_type
+ {
+ zero,
+ moved_from,
+ throwing_construction,
+ throwing_copy,
+ throwing_copy_assignment,
+ throwing_move,
+ throwing_move_assignment,
+ threw,
+ };
+
+ value_type() = default;
+
+ explicit value_type(state_type state_)
+ : state(state_)
+ {
+ throw_if(throwing_construction);
+ }
+
+ value_type(value_type const& other)
+ : state(other.state)
+ {
+ throw_if(throwing_copy);
+ }
+
+ value_type&
+ operator=(value_type const& other)
+ {
+ state = other.state;
+ throw_if(throwing_copy_assignment);
+ return *this;
+ }
+
+ value_type(value_type&& other)
+ : state(other.state)
+ {
+ other.state = moved_from;
+ throw_if(throwing_move);
+ }
+
+ value_type&
+ operator=(value_type&& other)
+ {
+ state = other.state;
+ other.state = moved_from;
+ throw_if(throwing_move_assignment);
+ return *this;
+ }
+
+ void throw_if(state_type match)
+ {
+ if(state == match)
+ {
+ state = threw;
+ throw exception {};
+ }
+ }
+
+ state_type state = zero;
+};
+
+int main()
+{
+ using O = std::experimental::optional<value_type>;
+ using S = value_type::state_type;
+ auto const make = [](S s = S::zero) { return value_type { s }; };
+
+ enum outcome_type { nothrow, caught, bad_catch };
+
+ // Check value assignment for disengaged optional
+
+ {
+ O o;
+ value_type v = make(S::throwing_copy_assignment);
+ o = v;
+ VERIFY( o && o->state == S::throwing_copy_assignment );
+ }
+
+ {
+ O o;
+ value_type v = make(S::throwing_move_assignment);
+ o = std::move(v);
+ VERIFY( o && o->state == S::throwing_move_assignment );
+ }
+
+ {
+ outcome_type outcome {};
+ O o;
+ value_type v = make(S::throwing_copy);
+
+ try
+ {
+ o = v;
+ }
+ catch(exception const&)
+ { outcome = caught; }
+ catch(...)
+ { outcome = bad_catch; }
+
+ VERIFY( !o );
+ }
+
+ {
+ outcome_type outcome {};
+ O o;
+ value_type v = make(S::throwing_move);
+
+ try
+ {
+ o = std::move(v);
+ }
+ catch(exception const&)
+ { outcome = caught; }
+ catch(...)
+ { outcome = bad_catch; }
+
+ VERIFY( !o );
+ }
+
+ VERIFY( counter == 0 );
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/assignment/4.cc b/libstdc++-v3/testsuite/experimental/optional/assignment/4.cc
new file mode 100644
index 00000000000..e5f1f1691cc
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/assignment/4.cc
@@ -0,0 +1,158 @@
+// { dg-options "-std=gnu++1y" }
+// { dg-do run }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+struct exception {};
+
+int counter = 0;
+
+struct mixin_counter
+{
+ mixin_counter() { ++counter; }
+ mixin_counter(mixin_counter const&) { ++counter; }
+ ~mixin_counter() { --counter; }
+};
+
+struct value_type : private mixin_counter
+{
+ enum state_type
+ {
+ zero,
+ moved_from,
+ throwing_construction,
+ throwing_copy,
+ throwing_copy_assignment,
+ throwing_move,
+ throwing_move_assignment,
+ threw,
+ };
+
+ value_type() = default;
+
+ explicit value_type(state_type state_)
+ : state(state_)
+ {
+ throw_if(throwing_construction);
+ }
+
+ value_type(value_type const& other)
+ : state(other.state)
+ {
+ throw_if(throwing_copy);
+ }
+
+ value_type&
+ operator=(value_type const& other)
+ {
+ state = other.state;
+ throw_if(throwing_copy_assignment);
+ return *this;
+ }
+
+ value_type(value_type&& other)
+ : state(other.state)
+ {
+ other.state = moved_from;
+ throw_if(throwing_move);
+ }
+
+ value_type&
+ operator=(value_type&& other)
+ {
+ state = other.state;
+ other.state = moved_from;
+ throw_if(throwing_move_assignment);
+ return *this;
+ }
+
+ void throw_if(state_type match)
+ {
+ if(state == match)
+ {
+ state = threw;
+ throw exception {};
+ }
+ }
+
+ state_type state = zero;
+};
+
+int main()
+{
+ using O = std::experimental::optional<value_type>;
+ using S = value_type::state_type;
+ auto const make = [](S s = S::zero) { return value_type { s }; };
+
+ enum outcome_type { nothrow, caught, bad_catch };
+
+ // Check value assignment for engaged optional
+
+ {
+ O o = make();
+ value_type v = make(S::throwing_copy);
+ o = v;
+ VERIFY( o && o->state == S::throwing_copy);
+ }
+
+ {
+ O o = make();
+ value_type v = make(S::throwing_move);
+ o = std::move(v);
+ VERIFY( o && o->state == S::throwing_move);
+ }
+
+ {
+ outcome_type outcome {};
+ O o = make();
+ value_type v = make(S::throwing_copy_assignment);
+
+ try
+ {
+ o = v;
+ }
+ catch(exception const&)
+ { outcome = caught; }
+ catch(...)
+ { outcome = bad_catch; }
+
+ VERIFY( o && o->state == S::threw );
+ }
+
+ {
+ outcome_type outcome {};
+ O o = make();
+ value_type v = make(S::throwing_move_assignment);
+
+ try
+ {
+ o = std::move(v);
+ }
+ catch(exception const&)
+ { outcome = caught; }
+ catch(...)
+ { outcome = bad_catch; }
+
+ VERIFY( o && o->state == S::threw );
+ }
+
+ VERIFY( counter == 0 );
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/assignment/5.cc b/libstdc++-v3/testsuite/experimental/optional/assignment/5.cc
new file mode 100644
index 00000000000..d6e268f4464
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/assignment/5.cc
@@ -0,0 +1,66 @@
+// { dg-options "-std=gnu++1y" }
+// { dg-do run }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+int counter = 0;
+
+struct mixin_counter
+{
+ mixin_counter() { ++counter; }
+ mixin_counter(mixin_counter const&) { ++counter; }
+ ~mixin_counter() { --counter; }
+};
+
+struct value_type : private mixin_counter { };
+
+int main()
+{
+ using O = std::experimental::optional<value_type>;
+
+ // Check std::experimental::nullopt_t and 'default' (= {}) assignment
+
+ {
+ O o;
+ o = std::experimental::nullopt;
+ VERIFY( !o );
+ }
+
+ {
+ O o { std::experimental::in_place };
+ o = std::experimental::nullopt;
+ VERIFY( !o );
+ }
+
+ {
+ O o;
+ o = {};
+ VERIFY( !o );
+ }
+
+ {
+ O o { std::experimental::in_place };
+ o = {};
+ VERIFY( !o );
+ }
+
+ VERIFY( counter == 0 );
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/assignment/6.cc b/libstdc++-v3/testsuite/experimental/optional/assignment/6.cc
new file mode 100644
index 00000000000..55be89d0dcf
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/assignment/6.cc
@@ -0,0 +1,83 @@
+// { dg-options "-std=gnu++1y" }
+// { dg-do run }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+int counter = 0;
+
+struct mixin_counter
+{
+ mixin_counter() { ++counter; }
+ mixin_counter(mixin_counter const&) { ++counter; }
+ ~mixin_counter() { --counter; }
+};
+
+struct value_type : private mixin_counter
+{
+ value_type() = default;
+ value_type(int) : state(1) { }
+ value_type(std::initializer_list<char>, const char*) : state(2) { }
+ int state = 0;
+};
+
+int main()
+{
+ using O = std::experimental::optional<value_type>;
+
+ // Check emplace
+
+ {
+ O o;
+ o.emplace();
+ VERIFY( o && o->state == 0 );
+ }
+ {
+ O o { std::experimental::in_place, 0 };
+ o.emplace();
+ VERIFY( o && o->state == 0 );
+ }
+
+ {
+ O o;
+ o.emplace(0);
+ VERIFY( o && o->state == 1 );
+ }
+ {
+ O o { std::experimental::in_place };
+ o.emplace(0);
+ VERIFY( o && o->state == 1 );
+ }
+
+ {
+ O o;
+ o.emplace({ 'a' }, "");
+ VERIFY( o && o->state == 2 );
+ }
+ {
+ O o { std::experimental::in_place };
+ o.emplace({ 'a' }, "");
+ VERIFY( o && o->state == 2 );
+ }
+
+ static_assert( !std::is_constructible<O, std::initializer_list<int>, int>(), "" );
+
+ VERIFY( counter == 0 );
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/cons/copy.cc b/libstdc++-v3/testsuite/experimental/optional/cons/copy.cc
new file mode 100644
index 00000000000..53c23a197ca
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/cons/copy.cc
@@ -0,0 +1,126 @@
+// { dg-options "-std=gnu++1y" }
+// { dg-do run }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+struct tracker
+{
+ tracker(int value) : value(value) { ++count; }
+ ~tracker() { --count; }
+
+ tracker(tracker const& other) : value(other.value) { ++count; }
+ tracker(tracker&& other) : value(other.value)
+ {
+ other.value = -1;
+ ++count;
+ }
+
+ tracker& operator=(tracker const&) = default;
+ tracker& operator=(tracker&&) = default;
+
+ int value;
+
+ static int count;
+};
+
+int tracker::count = 0;
+
+struct exception { };
+
+struct throwing_copy
+{
+ throwing_copy() = default;
+ throwing_copy(throwing_copy const&) { throw exception {}; }
+};
+
+int main()
+{
+ // [20.5.4.1] Constructors
+
+ {
+ std::experimental::optional<long> o;
+ auto copy = o;
+ VERIFY( !copy );
+ VERIFY( !o );
+ }
+
+ {
+ const long val = 0x1234ABCD;
+ std::experimental::optional<long> o { std::experimental::in_place, val};
+ auto copy = o;
+ VERIFY( copy );
+ VERIFY( *copy == val );
+ VERIFY( o && o == val );
+ }
+
+ {
+ std::experimental::optional<tracker> o;
+ auto copy = o;
+ VERIFY( !copy );
+ VERIFY( tracker::count == 0 );
+ VERIFY( !o );
+ }
+
+ {
+ std::experimental::optional<tracker> o { std::experimental::in_place, 333 };
+ auto copy = o;
+ VERIFY( copy );
+ VERIFY( copy->value == 333 );
+ VERIFY( tracker::count == 2 );
+ VERIFY( o && o->value == 333 );
+ }
+
+ enum outcome { nothrow, caught, bad_catch };
+
+ {
+ outcome result = nothrow;
+ std::experimental::optional<throwing_copy> o;
+
+ try
+ {
+ auto copy = o;
+ }
+ catch(exception const&)
+ { result = caught; }
+ catch(...)
+ { result = bad_catch; }
+
+ VERIFY( result == nothrow );
+ }
+
+ {
+ outcome result = nothrow;
+ std::experimental::optional<throwing_copy> o { std::experimental::in_place };
+
+ try
+ {
+ auto copy = o;
+ }
+ catch(exception const&)
+ { result = caught; }
+ catch(...)
+ { result = bad_catch; }
+
+ VERIFY( result == caught );
+ }
+
+ VERIFY( tracker::count == 0 );
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/cons/default.cc b/libstdc++-v3/testsuite/experimental/optional/cons/default.cc
new file mode 100644
index 00000000000..452f2d020bc
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/cons/default.cc
@@ -0,0 +1,60 @@
+// { dg-options "-std=gnu++1y" }
+// { dg-do run }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+struct tracker
+{
+ tracker() { ++count; }
+ ~tracker() { --count; }
+
+ tracker(tracker const&) { ++count; }
+ tracker(tracker&&) { ++count; }
+
+ tracker& operator=(tracker const&) = default;
+ tracker& operator=(tracker&&) = default;
+
+ static int count;
+};
+
+int tracker::count = 0;
+
+int main()
+{
+ // [20.5.4.1] Constructors
+
+ {
+ std::experimental::optional<tracker> o;
+ VERIFY( !o );
+ }
+
+ {
+ std::experimental::optional<tracker> o {};
+ VERIFY( !o );
+ }
+
+ {
+ std::experimental::optional<tracker> o = {};
+ VERIFY( !o );
+ }
+
+ VERIFY( tracker::count == 0 );
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/cons/move.cc b/libstdc++-v3/testsuite/experimental/optional/cons/move.cc
new file mode 100644
index 00000000000..ba316990910
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/cons/move.cc
@@ -0,0 +1,126 @@
+// { dg-options "-std=gnu++1y" }
+// { dg-do run }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+struct tracker
+{
+ tracker(int value) : value(value) { ++count; }
+ ~tracker() { --count; }
+
+ tracker(tracker const& other) : value(other.value) { ++count; }
+ tracker(tracker&& other) : value(other.value)
+ {
+ other.value = -1;
+ ++count;
+ }
+
+ tracker& operator=(tracker const&) = default;
+ tracker& operator=(tracker&&) = default;
+
+ int value;
+
+ static int count;
+};
+
+int tracker::count = 0;
+
+struct exception { };
+
+struct throwing_move
+{
+ throwing_move() = default;
+ throwing_move(throwing_move const&) { throw exception {}; }
+};
+
+int main()
+{
+ // [20.5.4.1] Constructors
+
+ {
+ std::experimental::optional<long> o;
+ auto moved_to = std::move(o);
+ VERIFY( !moved_to );
+ VERIFY( !o );
+ }
+
+ {
+ const long val = 0x1234ABCD;
+ std::experimental::optional<long> o { std::experimental::in_place, val};
+ auto moved_to = std::move(o);
+ VERIFY( moved_to );
+ VERIFY( *moved_to == val );
+ VERIFY( o && *o == val );
+ }
+
+ {
+ std::experimental::optional<tracker> o;
+ auto moved_to = std::move(o);
+ VERIFY( !moved_to );
+ VERIFY( tracker::count == 0 );
+ VERIFY( !o );
+ }
+
+ {
+ std::experimental::optional<tracker> o { std::experimental::in_place, 333 };
+ auto moved_to = std::move(o);
+ VERIFY( moved_to );
+ VERIFY( moved_to->value == 333 );
+ VERIFY( tracker::count == 2 );
+ VERIFY( o && o->value == -1 );
+ }
+
+ enum outcome { nothrow, caught, bad_catch };
+
+ {
+ outcome result = nothrow;
+ std::experimental::optional<throwing_move> o;
+
+ try
+ {
+ auto moved_to = std::move(o);
+ }
+ catch(exception const&)
+ { result = caught; }
+ catch(...)
+ { result = bad_catch; }
+
+ VERIFY( result == nothrow );
+ }
+
+ {
+ outcome result = nothrow;
+ std::experimental::optional<throwing_move> o { std::experimental::in_place };
+
+ try
+ {
+ auto moved_to = std::move(o);
+ }
+ catch(exception const&)
+ { result = caught; }
+ catch(...)
+ { result = bad_catch; }
+
+ VERIFY( result == caught );
+ }
+
+ VERIFY( tracker::count == 0 );
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/cons/value.cc b/libstdc++-v3/testsuite/experimental/optional/cons/value.cc
new file mode 100644
index 00000000000..1eba62d6d50
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/cons/value.cc
@@ -0,0 +1,239 @@
+// { dg-options "-std=gnu++1y" }
+// { dg-do run }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+#include <vector>
+
+struct tracker
+{
+ tracker(int value) : value(value) { ++count; }
+ ~tracker() { --count; }
+
+ tracker(tracker const& other) : value(other.value) { ++count; }
+ tracker(tracker&& other) : value(other.value)
+ {
+ other.value = -1;
+ ++count;
+ }
+
+ tracker& operator=(tracker const&) = default;
+ tracker& operator=(tracker&&) = default;
+
+ int value;
+
+ static int count;
+};
+
+int tracker::count = 0;
+
+struct exception { };
+
+struct throwing_construction
+{
+ explicit throwing_construction(bool propagate) : propagate(propagate) { }
+
+ throwing_construction(throwing_construction const& other)
+ : propagate(other.propagate)
+ {
+ if(propagate)
+ throw exception {};
+ }
+
+ bool propagate;
+};
+
+int main()
+{
+ // [20.5.4.1] Constructors
+
+ {
+ auto i = 0x1234ABCD;
+ std::experimental::optional<long> o { i };
+ VERIFY( o );
+ VERIFY( *o == 0x1234ABCD );
+ VERIFY( i == 0x1234ABCD );
+ }
+
+ {
+ auto i = 0x1234ABCD;
+ std::experimental::optional<long> o = i;
+ VERIFY( o );
+ VERIFY( *o == 0x1234ABCD );
+ VERIFY( i == 0x1234ABCD );
+ }
+
+ {
+ auto i = 0x1234ABCD;
+ std::experimental::optional<long> o = { i };
+ VERIFY( o );
+ VERIFY( *o == 0x1234ABCD );
+ VERIFY( i == 0x1234ABCD );
+ }
+
+ {
+ auto i = 0x1234ABCD;
+ std::experimental::optional<long> o { std::move(i) };
+ VERIFY( o );
+ VERIFY( *o == 0x1234ABCD );
+ VERIFY( i == 0x1234ABCD );
+ }
+
+ {
+ auto i = 0x1234ABCD;
+ std::experimental::optional<long> o = std::move(i);
+ VERIFY( o );
+ VERIFY( *o == 0x1234ABCD );
+ VERIFY( i == 0x1234ABCD );
+ }
+
+ {
+ auto i = 0x1234ABCD;
+ std::experimental::optional<long> o = { std::move(i) };
+ VERIFY( o );
+ VERIFY( *o == 0x1234ABCD );
+ VERIFY( i == 0x1234ABCD );
+ }
+
+ {
+ std::vector<int> v = { 0, 1, 2, 3, 4, 5 };
+ std::experimental::optional<std::vector<int>> o { v };
+ VERIFY( !v.empty() );
+ VERIFY( o->size() == 6 );
+ }
+
+ {
+ std::vector<int> v = { 0, 1, 2, 3, 4, 5 };
+ std::experimental::optional<std::vector<int>> o = v;
+ VERIFY( !v.empty() );
+ VERIFY( o->size() == 6 );
+ }
+
+ {
+ std::vector<int> v = { 0, 1, 2, 3, 4, 5 };
+ std::experimental::optional<std::vector<int>> o { v };
+ VERIFY( !v.empty() );
+ VERIFY( o->size() == 6 );
+ }
+
+ {
+ std::vector<int> v = { 0, 1, 2, 3, 4, 5 };
+ std::experimental::optional<std::vector<int>> o { std::move(v) };
+ VERIFY( v.empty() );
+ VERIFY( o->size() == 6 );
+ }
+
+ {
+ std::vector<int> v = { 0, 1, 2, 3, 4, 5 };
+ std::experimental::optional<std::vector<int>> o = std::move(v);
+ VERIFY( v.empty() );
+ VERIFY( o->size() == 6 );
+ }
+
+ {
+ std::vector<int> v = { 0, 1, 2, 3, 4, 5 };
+ std::experimental::optional<std::vector<int>> o { std::move(v) };
+ VERIFY( v.empty() );
+ VERIFY( o->size() == 6 );
+ }
+
+ {
+ tracker t { 333 };
+ std::experimental::optional<tracker> o = t;
+ VERIFY( o->value == 333 );
+ VERIFY( tracker::count == 2 );
+ VERIFY( t.value == 333 );
+ }
+
+ {
+ tracker t { 333 };
+ std::experimental::optional<tracker> o = std::move(t);
+ VERIFY( o->value == 333 );
+ VERIFY( tracker::count == 2 );
+ VERIFY( t.value == -1 );
+ }
+
+ enum outcome { nothrow, caught, bad_catch };
+
+ {
+ outcome result = nothrow;
+ throwing_construction t { false };
+
+ try
+ {
+ std::experimental::optional<throwing_construction> o { t };
+ }
+ catch(exception const&)
+ { result = caught; }
+ catch(...)
+ { result = bad_catch; }
+
+ VERIFY( result == nothrow );
+ }
+
+ {
+ outcome result = nothrow;
+ throwing_construction t { true };
+
+ try
+ {
+ std::experimental::optional<throwing_construction> o { t };
+ }
+ catch(exception const&)
+ { result = caught; }
+ catch(...)
+ { result = bad_catch; }
+
+ VERIFY( result == caught );
+ }
+
+ {
+ outcome result = nothrow;
+ throwing_construction t { false };
+
+ try
+ {
+ std::experimental::optional<throwing_construction> o { std::move(t) };
+ }
+ catch(exception const&)
+ { result = caught; }
+ catch(...)
+ { result = bad_catch; }
+
+ VERIFY( result == nothrow );
+ }
+
+ {
+ outcome result = nothrow;
+ throwing_construction t { true };
+
+ try
+ {
+ std::experimental::optional<throwing_construction> o { std::move(t) };
+ }
+ catch(exception const&)
+ { result = caught; }
+ catch(...)
+ { result = bad_catch; }
+
+ VERIFY( result == caught );
+ }
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/constexpr/cons/default.cc b/libstdc++-v3/testsuite/experimental/optional/constexpr/cons/default.cc
new file mode 100644
index 00000000000..d437cd8f439
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/constexpr/cons/default.cc
@@ -0,0 +1,42 @@
+// { dg-options "-std=gnu++1y" }
+// { dg-do compile }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+int main()
+{
+ // [20.5.4.1] Constructors
+
+ {
+ constexpr std::experimental::optional<int> o;
+ static_assert( !o, "" );
+ }
+
+ {
+ constexpr std::experimental::optional<int> o {};
+ static_assert( !o, "" );
+ }
+
+ {
+ constexpr std::experimental::optional<int> o = {};
+ static_assert( !o, "" );
+ }
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/constexpr/cons/value.cc b/libstdc++-v3/testsuite/experimental/optional/constexpr/cons/value.cc
new file mode 100644
index 00000000000..eb7233b2617
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/constexpr/cons/value.cc
@@ -0,0 +1,69 @@
+// { dg-options "-std=gnu++1y" }
+// { dg-do compile }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+int main()
+{
+ // [20.5.4.1] Constructors
+
+ {
+ constexpr long i = 0x1234ABCD;
+ constexpr std::experimental::optional<long> o { i };
+ static_assert( o, "" );
+ static_assert( *o == 0x1234ABCD, "" );
+ }
+
+ {
+ constexpr long i = 0x1234ABCD;
+ constexpr std::experimental::optional<long> o = i;
+ static_assert( o, "" );
+ static_assert( *o == 0x1234ABCD, "" );
+ }
+
+ {
+ constexpr long i = 0x1234ABCD;
+ constexpr std::experimental::optional<long> o = { i };
+ static_assert( o, "" );
+ static_assert( *o == 0x1234ABCD, "" );
+ }
+
+ {
+ constexpr long i = 0x1234ABCD;
+ constexpr std::experimental::optional<long> o { std::move(i) };
+ static_assert( o, "" );
+ static_assert( *o == 0x1234ABCD, "" );
+ }
+
+ {
+ constexpr long i = 0x1234ABCD;
+ constexpr std::experimental::optional<long> o = std::move(i);
+ static_assert( o, "" );
+ static_assert( *o == 0x1234ABCD, "" );
+ }
+
+ {
+ constexpr long i = 0x1234ABCD;
+ constexpr std::experimental::optional<long> o = { std::move(i) };
+ static_assert( o, "" );
+ static_assert( *o == 0x1234ABCD, "" );
+ }
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/constexpr/in_place.cc b/libstdc++-v3/testsuite/experimental/optional/constexpr/in_place.cc
new file mode 100644
index 00000000000..f2bb8fdc11a
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/constexpr/in_place.cc
@@ -0,0 +1,43 @@
+// { dg-options "-std=gnu++1y" }
+// { dg-do compile }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+int main()
+{
+ // [20.5.5] In-place construction
+ static_assert( std::is_same<decltype(std::experimental::in_place), const std::experimental::in_place_t>(), "" );
+ static_assert( std::is_empty<std::experimental::in_place_t>(), "" );
+
+ {
+ constexpr std::experimental::optional<int> o { std::experimental::in_place };
+ static_assert( o, "" );
+ static_assert( *o == int {}, "" );
+
+ static_assert( !std::is_convertible<std::experimental::in_place_t, std::experimental::optional<int>>(), "" );
+ }
+
+ {
+ constexpr std::experimental::optional<int> o { std::experimental::in_place, 42 };
+ static_assert( o, "" );
+ static_assert( *o == 42, "" );
+ }
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/constexpr/make_optional.cc b/libstdc++-v3/testsuite/experimental/optional/constexpr/make_optional.cc
new file mode 100644
index 00000000000..4b59ba9eb51
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/constexpr/make_optional.cc
@@ -0,0 +1,33 @@
+// { dg-options "-std=gnu++1y" }
+// XFAIL pending resolution of PR libstdc++/58777
+// { dg-do compile { xfail *-*-* } }
+// { dg-excess-errors "" }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+int main()
+{
+ constexpr int i = 42;
+ constexpr auto o = std::experimental::make_optional(i);
+ static_assert( std::is_same<decltype(o), const std::experimental::optional<int>>(), "" );
+ static_assert( o && *o == 42, "" );
+ static_assert( &*o != &i, "" );
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/constexpr/nullopt.cc b/libstdc++-v3/testsuite/experimental/optional/constexpr/nullopt.cc
new file mode 100644
index 00000000000..08566e1cb04
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/constexpr/nullopt.cc
@@ -0,0 +1,46 @@
+// { dg-options "-std=gnu++1y" }
+// { dg-do compile }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+int main()
+{
+ // [20.5.6] Disengaged state indicator
+ static_assert( std::is_same<decltype(std::experimental::nullopt), const std::experimental::nullopt_t>(), "" );
+ static_assert( std::is_empty<std::experimental::nullopt_t>(), "" );
+ static_assert( std::is_literal_type<std::experimental::nullopt_t>(), "" );
+ static_assert( !std::is_default_constructible<std::experimental::nullopt_t>(), "" );
+
+ {
+ constexpr std::experimental::optional<int> o = std::experimental::nullopt;
+ static_assert( !o, "" );
+ }
+
+ {
+ constexpr std::experimental::optional<int> o = { std::experimental::nullopt };
+ static_assert( !o, "" );
+ }
+
+ {
+ constexpr std::experimental::optional<int> o { std::experimental::nullopt };
+ static_assert( !o, "" );
+ }
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/constexpr/observers/1.cc b/libstdc++-v3/testsuite/experimental/optional/constexpr/observers/1.cc
new file mode 100644
index 00000000000..5943a352412
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/constexpr/observers/1.cc
@@ -0,0 +1,33 @@
+// { dg-options "-std=gnu++1y" }
+// { dg-do compile }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+struct value_type
+{
+ int i;
+};
+
+int main()
+{
+ constexpr std::experimental::optional<value_type> o { value_type { 51 } };
+ static_assert( (*o).i == 51, "" );
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/constexpr/observers/2.cc b/libstdc++-v3/testsuite/experimental/optional/constexpr/observers/2.cc
new file mode 100644
index 00000000000..3df68d3575d
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/constexpr/observers/2.cc
@@ -0,0 +1,37 @@
+// { dg-options "-std=gnu++1y" }
+// XFAIL pending resolution of PR libstdc++/58777
+// { dg-do compile { xfail *-*-* } }
+// { dg-excess-errors "" }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+struct value_type
+{
+ int i;
+};
+
+int main()
+{
+ constexpr std::experimental::optional<value_type> o { value_type { 51 } };
+ static_assert( o->i == 51, "" );
+ static_assert( o->i == (*o).i, "" );
+ static_assert( &o->i == &(*o).i, "" );
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/constexpr/observers/3.cc b/libstdc++-v3/testsuite/experimental/optional/constexpr/observers/3.cc
new file mode 100644
index 00000000000..6528d99c823
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/constexpr/observers/3.cc
@@ -0,0 +1,37 @@
+// { dg-options "-std=gnu++1y" }
+// XFAIL pending resolution of PR libstdc++/58777
+// { dg-do compile { xfail *-*-* } }
+// { dg-excess-errors "" }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+struct value_type
+{
+ int i;
+};
+
+int main()
+{
+ constexpr std::experimental::optional<value_type> o { value_type { 51 } };
+ static_assert( o.value().i == 51, "" );
+ static_assert( o.value().i == (*o).i, "" );
+ static_assert( &o.value().i == &(*o).i, "" );
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/constexpr/observers/4.cc b/libstdc++-v3/testsuite/experimental/optional/constexpr/observers/4.cc
new file mode 100644
index 00000000000..9098c0c5a54
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/constexpr/observers/4.cc
@@ -0,0 +1,35 @@
+// { dg-options "-std=gnu++1y" }
+// { dg-do compile }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+struct value_type
+{
+ int i;
+};
+
+int main()
+{
+ constexpr std::experimental::optional<value_type> o { value_type { 51 } };
+ constexpr value_type fallback { 3 };
+ static_assert( o.value_or(fallback).i == 51, "" );
+ static_assert( o.value_or(fallback).i == (*o).i, "" );
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/constexpr/observers/5.cc b/libstdc++-v3/testsuite/experimental/optional/constexpr/observers/5.cc
new file mode 100644
index 00000000000..e86d0408943
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/constexpr/observers/5.cc
@@ -0,0 +1,40 @@
+// { dg-options "-std=gnu++1y" }
+// { dg-do compile }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+struct value_type
+{
+ int i;
+};
+
+int main()
+{
+ {
+ constexpr std::experimental::optional<value_type> o = std::experimental::nullopt;
+ static_assert( !o, "" );
+ }
+
+ {
+ constexpr std::experimental::optional<value_type> o { value_type { 51 } };
+ static_assert( o, "" );
+ }
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/constexpr/relops/1.cc b/libstdc++-v3/testsuite/experimental/optional/constexpr/relops/1.cc
new file mode 100644
index 00000000000..591eb1346e0
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/constexpr/relops/1.cc
@@ -0,0 +1,99 @@
+// { dg-options "-std=gnu++1y" }
+// { dg-do compile }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+namespace ns
+{
+ struct value_type
+ {
+ int i;
+ const char* s;
+ };
+
+ constexpr bool
+ strcmp(const char* lhs, const char* rhs)
+ {
+ return *lhs == *rhs && (!*lhs || strcmp(lhs + 1, rhs + 1));
+ }
+
+ constexpr bool
+ strrel(const char* lhs, const char* rhs)
+ {
+ return (*rhs && (!*lhs || (*lhs < *rhs)))
+ || ((*lhs && *rhs && !(*rhs < *lhs)) && strrel(lhs + 1, rhs + 1));
+ }
+
+ constexpr bool
+ operator==(value_type const& lhs, value_type const& rhs)
+ { return (lhs.i == rhs.i) && strcmp(lhs.s, rhs.s); }
+
+ constexpr bool
+ operator!=(value_type const& lhs, value_type const& rhs)
+ { return !(lhs == rhs); }
+
+ constexpr bool
+ operator<(value_type const& lhs, value_type const& rhs)
+ { return (lhs.i < rhs.i) || (!(rhs.i < lhs.i) && strrel(lhs.s, rhs.s)); }
+
+} // namespace ns
+
+int main()
+{
+ using ns::value_type;
+ using O = std::experimental::optional<value_type>;
+
+ {
+ constexpr O o, p;
+ static_assert( o == p, "" );
+ static_assert( !(o != p), "" );
+ }
+
+ {
+ constexpr O o { value_type { 42, "forty-two" } }, p;
+ static_assert( !(o == p), "" );
+ static_assert( o != p, "" );
+ }
+
+ {
+ constexpr O o, p { value_type { 42, "forty-two" } };
+ static_assert( !(o == p), "" );
+ static_assert( o != p, "" );
+ }
+
+ {
+ constexpr O o { value_type { 11, "eleventy" } }, p { value_type { 42, "forty-two" } };
+ static_assert( !(o == p), "" );
+ static_assert( o != p, "" );
+ }
+
+ {
+ constexpr O o { value_type { 42, "forty-two" } }, p { value_type { 11, "eleventy" } };
+ static_assert( !(o == p), "" );
+ static_assert( o != p, "" );
+ }
+
+ {
+ constexpr O o { value_type { 42, "forty-two" } }, p { value_type { 42, "forty-two" } };
+ static_assert( o == p, "" );
+ static_assert( !(o != p), "" );
+ }
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/constexpr/relops/2.cc b/libstdc++-v3/testsuite/experimental/optional/constexpr/relops/2.cc
new file mode 100644
index 00000000000..9bc140dc9e5
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/constexpr/relops/2.cc
@@ -0,0 +1,111 @@
+// { dg-options "-std=gnu++1y" }
+// { dg-do compile }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+namespace ns
+{
+ struct value_type
+ {
+ int i;
+ const char* s;
+ };
+
+ constexpr bool
+ strcmp(const char* lhs, const char* rhs)
+ {
+ return *lhs == *rhs && (!*lhs || strcmp(lhs + 1, rhs + 1));
+ }
+
+ constexpr bool
+ strrel(const char* lhs, const char* rhs)
+ {
+ return (*rhs && (!*lhs || (*lhs < *rhs)))
+ || ((*lhs && *rhs && !(*rhs < *lhs)) && strrel(lhs + 1, rhs + 1));
+ }
+
+ constexpr bool
+ operator==(value_type const& lhs, value_type const& rhs)
+ { return (lhs.i == rhs.i) && strcmp(lhs.s, rhs.s); }
+
+ constexpr bool
+ operator!=(value_type const& lhs, value_type const& rhs)
+ { return !(lhs == rhs); }
+
+ constexpr bool
+ operator<(value_type const& lhs, value_type const& rhs)
+ { return (lhs.i < rhs.i) || (!(rhs.i < lhs.i) && strrel(lhs.s, rhs.s)); }
+
+} // namespace ns
+
+int main()
+{
+ using ns::value_type;
+ using O = std::experimental::optional<value_type>;
+
+ {
+ constexpr O o, p;
+ static_assert( !(o < p), "" );
+ static_assert( !(o > p), "" );
+ static_assert( o <= p, "" );
+ static_assert( o >= p, "" );
+ }
+
+ {
+ constexpr O o { value_type { 42, "forty-two" } }, p;
+ static_assert( !(o < p), "" );
+ static_assert( o > p, "" );
+ static_assert( !(o <= p), "" );
+ static_assert( o >= p, "" );
+ }
+
+ {
+ constexpr O o, p { value_type { 42, "forty-two" } };
+ static_assert( o < p, "" );
+ static_assert( !(o > p), "" );
+ static_assert( o <= p, "" );
+ static_assert( !(o >= p), "" );
+ }
+
+ {
+ constexpr O o { value_type { 11, "eleventy" } }, p { value_type { 42, "forty-two" } };
+ static_assert( o < p, "" );
+ static_assert( !(o > p), "" );
+ static_assert( o <= p, "" );
+ static_assert( !(o >= p), "" );
+ }
+
+ {
+ constexpr O o { value_type { 42, "forty-two" } }, p { value_type { 11, "eleventy" } };
+ static_assert( !(o < p), "" );
+ static_assert( o > p, "" );
+ static_assert( !(o <= p), "" );
+ static_assert( o >= p, "" );
+ }
+
+ {
+ constexpr O o { value_type { 42, "forty-two" } }, p { value_type { 42, "forty-two" } };
+ static_assert( !(o < p), "" );
+ static_assert( !(o > p), "" );
+ static_assert( o <= p, "" );
+ static_assert( o >= p, "" );
+ }
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/constexpr/relops/3.cc b/libstdc++-v3/testsuite/experimental/optional/constexpr/relops/3.cc
new file mode 100644
index 00000000000..6ffd2b6cf79
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/constexpr/relops/3.cc
@@ -0,0 +1,89 @@
+// { dg-options "-std=gnu++1y" }
+// { dg-do compile }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+namespace ns
+{
+ struct value_type
+ {
+ int i;
+ const char* s;
+ };
+
+ constexpr bool
+ strcmp(const char* lhs, const char* rhs)
+ {
+ return *lhs == *rhs && (!*lhs || strcmp(lhs + 1, rhs + 1));
+ }
+
+ constexpr bool
+ strrel(const char* lhs, const char* rhs)
+ {
+ return (*rhs && (!*lhs || (*lhs < *rhs)))
+ || ((*lhs && *rhs && !(*rhs < *lhs)) && strrel(lhs + 1, rhs + 1));
+ }
+
+ constexpr bool
+ operator==(value_type const& lhs, value_type const& rhs)
+ { return (lhs.i == rhs.i) && strcmp(lhs.s, rhs.s); }
+
+ constexpr bool
+ operator!=(value_type const& lhs, value_type const& rhs)
+ { return !(lhs == rhs); }
+
+ constexpr bool
+ operator<(value_type const& lhs, value_type const& rhs)
+ { return (lhs.i < rhs.i) || (!(rhs.i < lhs.i) && strrel(lhs.s, rhs.s)); }
+
+} // namespace ns
+
+int main()
+{
+ using ns::value_type;
+ using O = std::experimental::optional<value_type>;
+
+ constexpr value_type reference { 42, "forty-two" };
+
+ {
+ constexpr O o;
+ static_assert( !(o == reference), "" );
+ static_assert( !(reference == o), "" );
+ static_assert( o != reference, "" );
+ static_assert( reference != o, "" );
+ }
+
+ {
+ constexpr O o { value_type { 11, "eleventy" } };
+ static_assert( !(o == reference), "" );
+ static_assert( !(reference == o), "" );
+ static_assert( o != reference, "" );
+ static_assert( reference != o, "" );
+ }
+
+ {
+ constexpr O o { value_type { 42, "forty-two" } };
+ static_assert( o == reference, "" );
+ static_assert( reference == o, "" );
+ static_assert( !(o != reference), "" );
+ static_assert( !(reference != o), "" );
+ }
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/constexpr/relops/4.cc b/libstdc++-v3/testsuite/experimental/optional/constexpr/relops/4.cc
new file mode 100644
index 00000000000..8df602cb402
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/constexpr/relops/4.cc
@@ -0,0 +1,101 @@
+// { dg-options "-std=gnu++1y" }
+// { dg-do compile }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+namespace ns
+{
+ struct value_type
+ {
+ int i;
+ const char* s;
+ };
+
+ constexpr bool
+ strcmp(const char* lhs, const char* rhs)
+ {
+ return *lhs == *rhs && (!*lhs || strcmp(lhs + 1, rhs + 1));
+ }
+
+ constexpr bool
+ strrel(const char* lhs, const char* rhs)
+ {
+ return (*rhs && (!*lhs || (*lhs < *rhs)))
+ || ((*lhs && *rhs && !(*rhs < *lhs)) && strrel(lhs + 1, rhs + 1));
+ }
+
+ constexpr bool
+ operator==(value_type const& lhs, value_type const& rhs)
+ { return (lhs.i == rhs.i) && strcmp(lhs.s, rhs.s); }
+
+ constexpr bool
+ operator!=(value_type const& lhs, value_type const& rhs)
+ { return !(lhs == rhs); }
+
+ constexpr bool
+ operator<(value_type const& lhs, value_type const& rhs)
+ { return (lhs.i < rhs.i) || (!(rhs.i < lhs.i) && strrel(lhs.s, rhs.s)); }
+
+} // namespace ns
+
+int main()
+{
+ using ns::value_type;
+ using O = std::experimental::optional<value_type>;
+
+ constexpr value_type reference { 42, "forty-two" };
+
+ {
+ constexpr O o;
+ static_assert( o < reference, "" );
+ static_assert( !(reference < o), "" );
+ static_assert( !(o > reference), "" );
+ static_assert( reference > o, "" );
+ static_assert( o <= reference, "" );
+ static_assert( !(reference <= o), "" );
+ static_assert( !(o >= reference), "" );
+ static_assert( reference >= o, "" );
+ }
+
+ {
+ constexpr O o { value_type { 11, "eleventy" } };
+ static_assert( o < reference, "" );
+ static_assert( !(reference < o), "" );
+ static_assert( !(o > reference), "" );
+ static_assert( reference > o, "" );
+ static_assert( o <= reference, "" );
+ static_assert( !(reference <= o), "" );
+ static_assert( !(o >= reference), "" );
+ static_assert( reference >= o, "" );
+ }
+
+ {
+ constexpr O o { value_type { 42, "forty-two" } };
+ static_assert( !(o < reference), "" );
+ static_assert( !(reference < o), "" );
+ static_assert( !(o > reference), "" );
+ static_assert( !(reference > o), "" );
+ static_assert( o <= reference, "" );
+ static_assert( reference <= o, "" );
+ static_assert( o >= reference, "" );
+ static_assert( reference >= o, "" );
+ }
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/constexpr/relops/5.cc b/libstdc++-v3/testsuite/experimental/optional/constexpr/relops/5.cc
new file mode 100644
index 00000000000..241a71b8d10
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/constexpr/relops/5.cc
@@ -0,0 +1,80 @@
+// { dg-options "-std=gnu++1y" }
+// { dg-do compile }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+namespace ns
+{
+ struct value_type
+ {
+ int i;
+ const char* s;
+ };
+
+ constexpr bool
+ strcmp(const char* lhs, const char* rhs)
+ {
+ return *lhs == *rhs && (!*lhs || strcmp(lhs + 1, rhs + 1));
+ }
+
+ constexpr bool
+ strrel(const char* lhs, const char* rhs)
+ {
+ return (*rhs && (!*lhs || (*lhs < *rhs)))
+ || ((*lhs && *rhs && !(*rhs < *lhs)) && strrel(lhs + 1, rhs + 1));
+ }
+
+ constexpr bool
+ operator==(value_type const& lhs, value_type const& rhs)
+ { return (lhs.i == rhs.i) && strcmp(lhs.s, rhs.s); }
+
+ constexpr bool
+ operator!=(value_type const& lhs, value_type const& rhs)
+ { return !(lhs == rhs); }
+
+ constexpr bool
+ operator<(value_type const& lhs, value_type const& rhs)
+ { return (lhs.i < rhs.i) || (!(rhs.i < lhs.i) && strrel(lhs.s, rhs.s)); }
+
+} // namespace ns
+
+int main()
+{
+ using ns::value_type;
+ using O = std::experimental::optional<value_type>;
+ using std::experimental::nullopt;
+
+ {
+ constexpr O o;
+ static_assert( o == nullopt, "" );
+ static_assert( nullopt == o, "" );
+ static_assert( !(o != nullopt), "" );
+ static_assert( !(nullopt != o), "" );
+ }
+
+ {
+ constexpr O o { std::experimental::in_place };
+ static_assert( !(o == nullopt), "" );
+ static_assert( !(nullopt == o), "" );
+ static_assert( o != nullopt, "" );
+ static_assert( nullopt != o, "" );
+ }
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/constexpr/relops/6.cc b/libstdc++-v3/testsuite/experimental/optional/constexpr/relops/6.cc
new file mode 100644
index 00000000000..a4282d89e51
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/constexpr/relops/6.cc
@@ -0,0 +1,88 @@
+// { dg-options "-std=gnu++1y" }
+// { dg-do compile }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+namespace ns
+{
+ struct value_type
+ {
+ int i;
+ const char* s;
+ };
+
+ constexpr bool
+ strcmp(const char* lhs, const char* rhs)
+ {
+ return *lhs == *rhs && (!*lhs || strcmp(lhs + 1, rhs + 1));
+ }
+
+ constexpr bool
+ strrel(const char* lhs, const char* rhs)
+ {
+ return (*rhs && (!*lhs || (*lhs < *rhs)))
+ || ((*lhs && *rhs && !(*rhs < *lhs)) && strrel(lhs + 1, rhs + 1));
+ }
+
+ constexpr bool
+ operator==(value_type const& lhs, value_type const& rhs)
+ { return (lhs.i == rhs.i) && strcmp(lhs.s, rhs.s); }
+
+ constexpr bool
+ operator!=(value_type const& lhs, value_type const& rhs)
+ { return !(lhs == rhs); }
+
+ constexpr bool
+ operator<(value_type const& lhs, value_type const& rhs)
+ { return (lhs.i < rhs.i) || (!(rhs.i < lhs.i) && strrel(lhs.s, rhs.s)); }
+
+} // namespace ns
+
+int main()
+{
+ using ns::value_type;
+ using O = std::experimental::optional<value_type>;
+ using std::experimental::nullopt;
+
+ {
+ constexpr O o;
+ static_assert( !(o < nullopt), "" );
+ static_assert( !(nullopt < o), "" );
+ static_assert( !(o > nullopt), "" );
+ static_assert( !(nullopt > o), "" );
+ static_assert( o <= nullopt, "" );
+ static_assert( nullopt <= o, "" );
+ static_assert( o >= nullopt, "" );
+ static_assert( nullopt >= o, "" );
+ }
+
+ {
+ constexpr O o { std::experimental::in_place };
+ static_assert( !(o < nullopt), "" );
+ static_assert( nullopt < o, "" );
+ static_assert( o > nullopt, "" );
+ static_assert( !(nullopt > o), "" );
+ static_assert( !(o <= nullopt), "" );
+ static_assert( nullopt <= o, "" );
+ static_assert( o >= nullopt, "" );
+ static_assert( !(nullopt >= o), "" );
+ }
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/in_place.cc b/libstdc++-v3/testsuite/experimental/optional/in_place.cc
new file mode 100644
index 00000000000..ceaa97d91b3
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/in_place.cc
@@ -0,0 +1,66 @@
+// { dg-options "-std=gnu++1y" }
+// { dg-do run }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+#include <vector>
+
+int main()
+{
+ // [20.5.5] In-place construction
+ static_assert( std::is_same<decltype(std::experimental::in_place), const std::experimental::in_place_t>(), "" );
+ static_assert( std::is_empty<std::experimental::in_place_t>(), "" );
+
+ {
+ std::experimental::optional<int> o { std::experimental::in_place };
+ VERIFY( o );
+ VERIFY( *o == int() );
+
+ static_assert( !std::is_convertible<std::experimental::in_place_t, std::experimental::optional<int>>(), "" );
+ }
+
+ {
+ std::experimental::optional<int> o { std::experimental::in_place, 42 };
+ VERIFY( o );
+ VERIFY( *o == 42 );
+ }
+
+ {
+ std::experimental::optional<std::vector<int>> o { std::experimental::in_place, 18, 4 };
+ VERIFY( o );
+ VERIFY( o->size() == 18 );
+ VERIFY( (*o)[17] == 4 );
+ }
+
+ {
+ std::experimental::optional<std::vector<int>> o { std::experimental::in_place, { 18, 4 } };
+ VERIFY( o );
+ VERIFY( o->size() == 2 );
+ VERIFY( (*o)[0] == 18 );
+ }
+
+ {
+ std::experimental::optional<std::vector<int>> o { std::experimental::in_place, { 18, 4 }, std::allocator<int> {} };
+ VERIFY( o );
+ VERIFY( o->size() == 2 );
+ VERIFY( (*o)[0] == 18 );
+ }
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/make_optional.cc b/libstdc++-v3/testsuite/experimental/optional/make_optional.cc
new file mode 100644
index 00000000000..90ebe6c4bfc
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/make_optional.cc
@@ -0,0 +1,31 @@
+// { dg-options "-std=gnu++1y" }
+// { dg-do run }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+int main()
+{
+ const int i = 42;
+ auto o = std::experimental::make_optional(i);
+ static_assert( std::is_same<decltype(o), std::experimental::optional<int>>(), "" );
+ VERIFY( o && *o == 42 );
+ VERIFY( &*o != &i );
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/nullopt.cc b/libstdc++-v3/testsuite/experimental/optional/nullopt.cc
new file mode 100644
index 00000000000..f1b1bb6dcab
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/nullopt.cc
@@ -0,0 +1,46 @@
+// { dg-options "-std=gnu++1y" }
+// { dg-do run }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+int main()
+{
+ // [20.5.6] Disengaged state indicator
+ static_assert( std::is_same<decltype(std::experimental::nullopt), const std::experimental::nullopt_t>(), "" );
+ static_assert( std::is_empty<std::experimental::nullopt_t>(), "" );
+ static_assert( std::is_literal_type<std::experimental::nullopt_t>(), "" );
+ static_assert( !std::is_default_constructible<std::experimental::nullopt_t>(), "" );
+
+ {
+ std::experimental::optional<int> o = std::experimental::nullopt;
+ VERIFY( !o );
+ }
+
+ {
+ std::experimental::optional<int> o = { std::experimental::nullopt };
+ VERIFY( !o );
+ }
+
+ {
+ std::experimental::optional<int> o { std::experimental::nullopt };
+ VERIFY( !o );
+ }
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/observers/1.cc b/libstdc++-v3/testsuite/experimental/optional/observers/1.cc
new file mode 100644
index 00000000000..5ffa3a5ebc0
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/observers/1.cc
@@ -0,0 +1,33 @@
+// { dg-options "-std=gnu++1y" }
+// { dg-do run }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+struct value_type
+{
+ int i;
+};
+
+int main()
+{
+ std::experimental::optional<value_type> o { value_type { 51 } };
+ VERIFY( (*o).i == 51 );
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/observers/2.cc b/libstdc++-v3/testsuite/experimental/optional/observers/2.cc
new file mode 100644
index 00000000000..444a14157ac
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/observers/2.cc
@@ -0,0 +1,35 @@
+// { dg-options "-std=gnu++1y" }
+// { dg-do run }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+struct value_type
+{
+ int i;
+};
+
+int main()
+{
+ std::experimental::optional<value_type> o { value_type { 51 } };
+ VERIFY( o->i == 51 );
+ VERIFY( o->i == (*o).i );
+ VERIFY( &o->i == &(*o).i );
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/observers/3.cc b/libstdc++-v3/testsuite/experimental/optional/observers/3.cc
new file mode 100644
index 00000000000..b82142d0663
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/observers/3.cc
@@ -0,0 +1,58 @@
+// { dg-options "-std=gnu++1y" }
+// { dg-do run }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+struct value_type
+{
+ int i;
+};
+
+int main()
+{
+ {
+ std::experimental::optional<value_type> o { value_type { 51 } };
+ VERIFY( o.value().i == 51 );
+ VERIFY( o.value().i == (*o).i );
+ VERIFY( &o.value().i == &(*o).i );
+ }
+
+ {
+ enum outcome_type { nothrow, caught, bad_catch };
+
+ outcome_type outcome {};
+ std::experimental::optional<value_type> o = std::experimental::nullopt;
+ bool called = false;
+ auto const eat = [&called](int) { called = true; };
+
+ try
+ {
+ eat(o.value().i);
+ }
+ catch(std::experimental::bad_optional_access const&)
+ { outcome = caught; }
+ catch(...)
+ { outcome = bad_catch; }
+
+ VERIFY( outcome == caught );
+ VERIFY( !called );
+ }
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/observers/4.cc b/libstdc++-v3/testsuite/experimental/optional/observers/4.cc
new file mode 100644
index 00000000000..3b43c77d4c3
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/observers/4.cc
@@ -0,0 +1,35 @@
+// { dg-options "-std=gnu++1y" }
+// { dg-do run }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+struct value_type
+{
+ int i;
+};
+
+int main()
+{
+ std::experimental::optional<value_type> o { value_type { 51 } };
+ value_type fallback { 3 };
+ VERIFY( o.value_or(fallback).i == 51 );
+ VERIFY( o.value_or(fallback).i == (*o).i );
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/observers/5.cc b/libstdc++-v3/testsuite/experimental/optional/observers/5.cc
new file mode 100644
index 00000000000..c6957ec3295
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/observers/5.cc
@@ -0,0 +1,40 @@
+// { dg-options "-std=gnu++1y" }
+// { dg-do run }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+struct value_type
+{
+ int i;
+};
+
+int main()
+{
+ {
+ std::experimental::optional<value_type> o = std::experimental::nullopt;
+ VERIFY( !o );
+ }
+
+ {
+ std::experimental::optional<value_type> o { value_type { 51 } };
+ VERIFY( o );
+ }
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/relops/1.cc b/libstdc++-v3/testsuite/experimental/optional/relops/1.cc
new file mode 100644
index 00000000000..6f0c60f71ce
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/relops/1.cc
@@ -0,0 +1,89 @@
+// { dg-options "-std=gnu++1y" }
+// { dg-do run }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+#include <tuple>
+#include <string>
+
+namespace ns
+{
+ struct value_type
+ {
+ int i;
+ std::string s;
+ };
+
+ bool
+ operator==(value_type const& lhs, value_type const& rhs)
+ { return std::tie(lhs.i, lhs.s) == std::tie(rhs.i, rhs.s); }
+
+ bool
+ operator!=(value_type const& lhs, value_type const& rhs)
+ { return !(lhs == rhs); }
+
+ bool
+ operator<(value_type const& lhs, value_type const& rhs)
+ { return std::tie(lhs.i, lhs.s) < std::tie(rhs.i, rhs.s); }
+
+} // namespace ns
+
+int main()
+{
+ using ns::value_type;
+ using O = std::experimental::optional<value_type>;
+
+ {
+ O o, p;
+ VERIFY( o == p );
+ VERIFY( !(o != p) );
+ }
+
+ {
+ O o { value_type { 42, "forty-two" } }, p;
+ VERIFY( !(o == p) );
+ VERIFY( o != p );
+ }
+
+ {
+ O o, p { value_type { 42, "forty-two" } };
+ VERIFY( !(o == p) );
+ VERIFY( o != p );
+ }
+
+ {
+ O o { value_type { 11, "eleventy" } }, p { value_type { 42, "forty-two" } };
+ VERIFY( !(o == p) );
+ VERIFY( o != p );
+ }
+
+ {
+ O o { value_type { 42, "forty-two" } }, p { value_type { 11, "eleventy" } };
+ VERIFY( !(o == p) );
+ VERIFY( o != p );
+ }
+
+ {
+ O o { value_type { 42, "forty-two" } }, p { value_type { 42, "forty-two" } };
+ VERIFY( o == p );
+ VERIFY( !(o != p) );
+ }
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/relops/2.cc b/libstdc++-v3/testsuite/experimental/optional/relops/2.cc
new file mode 100644
index 00000000000..b1ae705bd3d
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/relops/2.cc
@@ -0,0 +1,101 @@
+// { dg-options "-std=gnu++1y" }
+// { dg-do run }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+#include <tuple>
+#include <string>
+
+namespace ns
+{
+ struct value_type
+ {
+ int i;
+ std::string s;
+ };
+
+ bool
+ operator==(value_type const& lhs, value_type const& rhs)
+ { return std::tie(lhs.i, lhs.s) == std::tie(rhs.i, rhs.s); }
+
+ bool
+ operator!=(value_type const& lhs, value_type const& rhs)
+ { return !(lhs == rhs); }
+
+ bool
+ operator<(value_type const& lhs, value_type const& rhs)
+ { return std::tie(lhs.i, lhs.s) < std::tie(rhs.i, rhs.s); }
+
+} // namespace ns
+
+int main()
+{
+ using ns::value_type;
+ using O = std::experimental::optional<value_type>;
+
+ {
+ O o, p;
+ VERIFY( !(o < p) );
+ VERIFY( !(o > p) );
+ VERIFY( o <= p );
+ VERIFY( o >= p );
+ }
+
+ {
+ O o { value_type { 42, "forty-two" } }, p;
+ VERIFY( !(o < p) );
+ VERIFY( o > p );
+ VERIFY( !(o <= p) );
+ VERIFY( o >= p );
+ }
+
+ {
+ O o, p { value_type { 42, "forty-two" } };
+ VERIFY( o < p );
+ VERIFY( !(o > p) );
+ VERIFY( o <= p );
+ VERIFY( !(o >= p) );
+ }
+
+ {
+ O o { value_type { 11, "eleventy" } }, p { value_type { 42, "forty-two" } };
+ VERIFY( o < p );
+ VERIFY( !(o > p) );
+ VERIFY( o <= p );
+ VERIFY( !(o >= p) );
+ }
+
+ {
+ O o { value_type { 42, "forty-two" } }, p { value_type { 11, "eleventy" } };
+ VERIFY( !(o < p) );
+ VERIFY( o > p );
+ VERIFY( !(o <= p) );
+ VERIFY( o >= p );
+ }
+
+ {
+ O o { value_type { 42, "forty-two" } }, p { value_type { 42, "forty-two" } };
+ VERIFY( !(o < p) );
+ VERIFY( !(o > p) );
+ VERIFY( o <= p );
+ VERIFY( o >= p );
+ }
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/relops/3.cc b/libstdc++-v3/testsuite/experimental/optional/relops/3.cc
new file mode 100644
index 00000000000..6b361dfa23e
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/relops/3.cc
@@ -0,0 +1,79 @@
+// { dg-options "-std=gnu++1y" }
+// { dg-do run }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+#include <tuple>
+#include <string>
+
+namespace ns
+{
+ struct value_type
+ {
+ int i;
+ std::string s;
+ };
+
+ bool
+ operator==(value_type const& lhs, value_type const& rhs)
+ { return std::tie(lhs.i, lhs.s) == std::tie(rhs.i, rhs.s); }
+
+ bool
+ operator!=(value_type const& lhs, value_type const& rhs)
+ { return !(lhs == rhs); }
+
+ bool
+ operator<(value_type const& lhs, value_type const& rhs)
+ { return std::tie(lhs.i, lhs.s) < std::tie(rhs.i, rhs.s); }
+
+} // namespace ns
+
+int main()
+{
+ using ns::value_type;
+ using O = std::experimental::optional<value_type>;
+
+ value_type const reference { 42, "forty-two" };
+
+ {
+ O o;
+ VERIFY( !(o == reference) );
+ VERIFY( !(reference == o) );
+ VERIFY( o != reference );
+ VERIFY( reference != o );
+ }
+
+ {
+ O o { value_type { 11, "eleventy" } };
+ VERIFY( !(o == reference) );
+ VERIFY( !(reference == o) );
+ VERIFY( o != reference );
+ VERIFY( reference != o );
+ }
+
+ {
+ O o { value_type { 42, "forty-two" } };
+ VERIFY( o == reference );
+ VERIFY( reference == o );
+ VERIFY( !(o != reference) );
+ VERIFY( !(reference != o) );
+ }
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/relops/4.cc b/libstdc++-v3/testsuite/experimental/optional/relops/4.cc
new file mode 100644
index 00000000000..9f316f1eb41
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/relops/4.cc
@@ -0,0 +1,91 @@
+// { dg-options "-std=gnu++1y" }
+// { dg-do run }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+#include <tuple>
+#include <string>
+
+namespace ns
+{
+ struct value_type
+ {
+ int i;
+ std::string s;
+ };
+
+ bool
+ operator==(value_type const& lhs, value_type const& rhs)
+ { return std::tie(lhs.i, lhs.s) == std::tie(rhs.i, rhs.s); }
+
+ bool
+ operator!=(value_type const& lhs, value_type const& rhs)
+ { return !(lhs == rhs); }
+
+ bool
+ operator<(value_type const& lhs, value_type const& rhs)
+ { return std::tie(lhs.i, lhs.s) < std::tie(rhs.i, rhs.s); }
+
+} // namespace ns
+
+int main()
+{
+ using ns::value_type;
+ using O = std::experimental::optional<value_type>;
+
+ value_type const reference { 42, "forty-two" };
+
+ {
+ O o;
+ VERIFY( o < reference );
+ VERIFY( !(reference < o) );
+ VERIFY( !(o > reference) );
+ VERIFY( reference > o );
+ VERIFY( o <= reference );
+ VERIFY( !(reference <= o) );
+ VERIFY( !(o >= reference) );
+ VERIFY( reference >= o );
+ }
+
+ {
+ O o { value_type { 11, "eleventy" } };
+ VERIFY( o < reference );
+ VERIFY( !(reference < o) );
+ VERIFY( !(o > reference) );
+ VERIFY( reference > o );
+ VERIFY( o <= reference );
+ VERIFY( !(reference <= o) );
+ VERIFY( !(o >= reference) );
+ VERIFY( reference >= o );
+ }
+
+ {
+ O o { value_type { 42, "forty-two" } };
+ VERIFY( !(o < reference) );
+ VERIFY( !(reference < o) );
+ VERIFY( !(o > reference) );
+ VERIFY( !(reference > o) );
+ VERIFY( o <= reference );
+ VERIFY( reference <= o );
+ VERIFY( o >= reference );
+ VERIFY( reference >= o );
+ }
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/relops/5.cc b/libstdc++-v3/testsuite/experimental/optional/relops/5.cc
new file mode 100644
index 00000000000..c7b27bbabbb
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/relops/5.cc
@@ -0,0 +1,70 @@
+// { dg-options "-std=gnu++1y" }
+// { dg-do run }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+#include <tuple>
+#include <string>
+
+namespace ns
+{
+ struct value_type
+ {
+ int i;
+ std::string s;
+ };
+
+ bool
+ operator==(value_type const& lhs, value_type const& rhs)
+ { return std::tie(lhs.i, lhs.s) == std::tie(rhs.i, rhs.s); }
+
+ bool
+ operator!=(value_type const& lhs, value_type const& rhs)
+ { return !(lhs == rhs); }
+
+ bool
+ operator<(value_type const& lhs, value_type const& rhs)
+ { return std::tie(lhs.i, lhs.s) < std::tie(rhs.i, rhs.s); }
+
+} // namespace ns
+
+int main()
+{
+ using ns::value_type;
+ using O = std::experimental::optional<value_type>;
+ using std::experimental::nullopt;
+
+ {
+ O o;
+ VERIFY( o == nullopt );
+ VERIFY( nullopt == o );
+ VERIFY( !(o != nullopt) );
+ VERIFY( !(nullopt != o) );
+ }
+
+ {
+ O o { std::experimental::in_place };
+ VERIFY( !(o == nullopt) );
+ VERIFY( !(nullopt == o) );
+ VERIFY( o != nullopt );
+ VERIFY( nullopt != o );
+ }
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/relops/6.cc b/libstdc++-v3/testsuite/experimental/optional/relops/6.cc
new file mode 100644
index 00000000000..d8a4f6fd057
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/relops/6.cc
@@ -0,0 +1,78 @@
+// { dg-options "-std=gnu++1y" }
+// { dg-do run }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+#include <tuple>
+#include <string>
+
+namespace ns
+{
+ struct value_type
+ {
+ int i;
+ std::string s;
+ };
+
+ bool
+ operator==(value_type const& lhs, value_type const& rhs)
+ { return std::tie(lhs.i, lhs.s) == std::tie(rhs.i, rhs.s); }
+
+ bool
+ operator!=(value_type const& lhs, value_type const& rhs)
+ { return !(lhs == rhs); }
+
+ bool
+ operator<(value_type const& lhs, value_type const& rhs)
+ { return std::tie(lhs.i, lhs.s) < std::tie(rhs.i, rhs.s); }
+
+} // namespace ns
+
+int main()
+{
+ using ns::value_type;
+ using O = std::experimental::optional<value_type>;
+ using std::experimental::nullopt;
+
+ {
+ O o;
+ VERIFY( !(o < nullopt) );
+ VERIFY( !(nullopt < o) );
+ VERIFY( !(o > nullopt) );
+ VERIFY( !(nullopt > o) );
+ VERIFY( o <= nullopt );
+ VERIFY( nullopt <= o );
+ VERIFY( o >= nullopt );
+ VERIFY( nullopt >= o );
+ }
+
+ {
+ O o { std::experimental::in_place };
+ VERIFY( !(o < nullopt) );
+ VERIFY( nullopt < o );
+ VERIFY( o > nullopt );
+ VERIFY( !(nullopt > o) );
+ VERIFY( !(o <= nullopt) );
+ VERIFY( nullopt <= o );
+ VERIFY( o >= nullopt );
+ VERIFY( !(nullopt >= o) );
+ }
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/requirements.cc b/libstdc++-v3/testsuite/experimental/optional/requirements.cc
new file mode 100644
index 00000000000..c97cde581ee
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/requirements.cc
@@ -0,0 +1,256 @@
+// { dg-options "-std=gnu++1y" }
+// { dg-do run }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+#include <tuple>
+
+struct trivially_destructible
+{
+ trivially_destructible() = delete;
+ trivially_destructible(trivially_destructible const&) = delete;
+ trivially_destructible& operator=(trivially_destructible const&) = delete;
+ trivially_destructible(trivially_destructible&&) = delete;
+ trivially_destructible& operator=(trivially_destructible&&) = delete;
+ ~trivially_destructible() noexcept = default;
+};
+
+static_assert( std::is_trivially_destructible<trivially_destructible>(), "" );
+
+struct no_default_constructor
+{
+ no_default_constructor() = delete;
+};
+
+struct no_copy_constructor
+{
+ no_copy_constructor() = default;
+ no_copy_constructor(no_copy_constructor const&) = delete;
+ no_copy_constructor& operator=(no_copy_constructor const&) = default;
+ no_copy_constructor(no_copy_constructor&&) = default;
+ no_copy_constructor& operator=(no_copy_constructor&&) = default;
+};
+
+struct no_copy_assignment
+{
+ no_copy_assignment() = default;
+ no_copy_assignment(no_copy_assignment const&) = default;
+ no_copy_assignment(no_copy_assignment&&) = default;
+ no_copy_assignment& operator=(no_copy_assignment&&) = default;
+};
+
+struct no_move_constructor
+{
+ no_move_constructor() = default;
+ no_move_constructor(no_move_constructor const&) = default;
+ no_move_constructor& operator=(no_move_constructor const&) = default;
+ no_move_constructor(no_move_constructor&&) = delete;
+ no_move_constructor& operator=(no_move_constructor&&) = default;
+};
+
+struct no_move_assignment
+{
+ no_move_assignment() = default;
+ no_move_assignment(no_move_assignment const&) = default;
+ no_move_assignment& operator=(no_move_assignment const&) = default;
+ no_move_assignment(no_move_assignment&&) = default;
+ no_move_assignment& operator=(no_move_assignment&&) = delete;
+};
+
+struct no_copy : no_copy_constructor, no_copy_assignment { };
+struct no_move : no_move_constructor, no_move_assignment { };
+
+// Laxest possible model of a value type for optional
+struct only_destructible
+{
+ only_destructible(only_destructible&&) = delete;
+};
+
+int main()
+{
+ {
+ static_assert( std::is_trivially_destructible<std::experimental::optional<trivially_destructible>>(), "" );
+ }
+
+ {
+ using T = no_default_constructor;
+ using O = std::experimental::optional<T>;
+ static_assert( std::is_same<O::value_type, T>(), "" );
+ static_assert( std::is_default_constructible<O>(), "" );
+ { O o; }
+ static_assert( std::is_copy_constructible<O>(), "" );
+ { O o; auto copy = o; }
+ static_assert( std::is_copy_assignable<O>(), "" );
+ { O o, p; p = o; }
+ static_assert( std::is_move_constructible<O>(), "" );
+ { O o; auto moved_to = std::move(o); }
+ static_assert( std::is_move_assignable<O>(), "" );
+ { O o, p; p = std::move(o); }
+ }
+
+ {
+ using T = no_copy_constructor;
+ using O = std::experimental::optional<T>;
+ static_assert( std::is_same<O::value_type, T>(), "" );
+ static_assert( std::is_default_constructible<O>(), "" );
+ { O o; }
+ static_assert( !std::is_copy_constructible<O>(), "" );
+ static_assert( !std::is_copy_assignable<O>(), "" );
+ static_assert( std::is_move_constructible<O>(), "" );
+ { O o; auto moved_to = std::move(o); }
+ static_assert( std::is_move_assignable<O>(), "" );
+ { O o, p; p = std::move(o); }
+ }
+
+ {
+ using T = no_copy_assignment;
+ using O = std::experimental::optional<T>;
+ static_assert( std::is_default_constructible<O>(), "" );
+ { O o; }
+ static_assert( std::is_copy_constructible<O>(), "" );
+ { O o; auto copy = o; }
+ static_assert( !std::is_copy_assignable<O>(), "" );
+ static_assert( std::is_move_constructible<O>(), "" );
+ { O o; auto moved_to = std::move(o); }
+ static_assert( std::is_move_assignable<O>(), "" );
+ { O o, p; p = std::move(o); }
+ }
+
+ {
+ using T = no_copy;
+ using O = std::experimental::optional<T>;
+ static_assert( std::is_same<O::value_type, T>(), "" );
+ static_assert( std::is_default_constructible<O>(), "" );
+ { O o; }
+ static_assert( !std::is_copy_constructible<O>(), "" );
+ static_assert( !std::is_copy_assignable<O>(), "" );
+ static_assert( std::is_move_constructible<O>(), "" );
+ { O o; auto moved_to = std::move(o); }
+ static_assert( std::is_move_assignable<O>(), "" );
+ { O o, p; p = std::move(o); }
+ }
+
+ {
+ using T = no_move_constructor;
+ using O = std::experimental::optional<T>;
+ static_assert( std::is_same<O::value_type, T>(), "" );
+ static_assert( std::is_default_constructible<O>(), "" );
+ { O o; }
+ static_assert( std::is_copy_constructible<O>(), "" );
+ { O o; auto copy = o; }
+ static_assert( std::is_copy_assignable<O>(), "" );
+ /*
+ * T should be move constructible due to [12.8/11], which is a new rule in C++1y
+ * not yet implemented by GCC. Because there is already a special exception in C++11
+ * for the generation of the special members that GCC implements (at least some of the
+ * time), this does not affect the std::experimental::optional implementation however. So the assertion
+ * for T should be changed (or removed altogether) when the time comes, but the rest
+ * should however remain correct and unchanged.
+ */
+ static_assert( !std::is_move_constructible<T>(), "" );
+ static_assert( std::is_move_constructible<O>(), "" );
+ { O o; auto moved_to = std::move(o); }
+ static_assert( std::is_move_assignable<O>(), "" );
+ { O o, p; p = std::move(o); }
+ }
+
+ {
+ using T = no_move_assignment;
+ using O = std::experimental::optional<T>;
+ static_assert( std::is_same<O::value_type, T>(), "" );
+ static_assert( std::is_default_constructible<O>(), "" );
+ { O o; }
+ static_assert( std::is_copy_constructible<O>(), "" );
+ { O o; auto copy = o; }
+ static_assert( std::is_copy_assignable<O>(), "" );
+ { O o, p; p = o; }
+ static_assert( std::is_move_constructible<O>(), "" );
+ { O o; auto moved_to = std::move(o); }
+ /*
+ * Paragraph 23 of same leads to a similar situation but with respect to move
+ * assignment.
+ */
+ static_assert( !std::is_move_assignable<T>(), "" );
+ static_assert( std::is_move_assignable<O>(), "" );
+ { O o, p; p = std::move(o); }
+ }
+
+ {
+ using T = no_move;
+ using O = std::experimental::optional<T>;
+ static_assert( std::is_same<O::value_type, T>(), "" );
+ static_assert( std::is_default_constructible<O>(), "" );
+ { O o; }
+ static_assert( std::is_copy_constructible<O>(), "" );
+ { O o; auto copy = o; }
+ static_assert( std::is_copy_assignable<O>(), "" );
+ { O o, p; p = o; }
+ static_assert( std::is_move_constructible<O>(), "" );
+ { O o; auto moved_to = std::move(o); }
+ static_assert( std::is_move_assignable<O>(), "" );
+ { O o, p; p = std::move(o); }
+ }
+
+ {
+ using T = only_destructible;
+ using O = std::experimental::optional<T>;
+ static_assert( std::is_same<O::value_type, T>(), "" );
+ static_assert( std::is_default_constructible<O>(), "" );
+ { O o; }
+ static_assert( !std::is_copy_constructible<O>(), "" );
+ static_assert( !std::is_copy_assignable<O>(), "" );
+ static_assert( !std::is_move_constructible<O>(), "" );
+ static_assert( !std::is_move_assignable<O>(), "" );
+ }
+
+ {
+ /*
+ * Should not complain about 'invalid' specializations as long as
+ * they're not instantiated.
+ */
+ using A = std::experimental::optional<int&>;
+ using B = std::experimental::optional<int&&>;
+ using C1 = std::experimental::optional<std::experimental::in_place_t>;
+ using C2 = std::experimental::optional<std::experimental::in_place_t const>;
+ using C3 = std::experimental::optional<std::experimental::in_place_t volatile>;
+ using C4 = std::experimental::optional<std::experimental::in_place_t const volatile>;
+ using D1 = std::experimental::optional<std::experimental::nullopt_t>;
+ using D2 = std::experimental::optional<std::experimental::nullopt_t const>;
+ using D3 = std::experimental::optional<std::experimental::nullopt_t volatile>;
+ using D4 = std::experimental::optional<std::experimental::nullopt_t const volatile>;
+
+ using X = std::tuple<A, B, C1, C2, C3, C4, D1, D2, D3, D4>;
+ }
+
+ {
+ std::experimental::optional<const int> o { 42 };
+ static_assert( std::is_same<decltype(o)::value_type, const int>(), "" );
+ VERIFY( o );
+ VERIFY( *o == 42 );
+ }
+
+ {
+ constexpr std::experimental::optional<const int> o { 33 };
+ static_assert( std::is_same<decltype(o)::value_type, const int>(), "" );
+ static_assert( o, "" );
+ static_assert( *o == 33, "" );
+ }
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/swap/1.cc b/libstdc++-v3/testsuite/experimental/optional/swap/1.cc
new file mode 100644
index 00000000000..95235b3e711
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/swap/1.cc
@@ -0,0 +1,95 @@
+// { dg-options "-std=gnu++1y" }
+// { dg-do run }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+struct exception {};
+
+int counter = 0;
+
+struct mixin_counter
+{
+ mixin_counter() { ++counter; }
+ mixin_counter(mixin_counter const&) { ++counter; }
+ ~mixin_counter() { --counter; }
+};
+
+namespace ns
+{
+
+struct value_type : private mixin_counter
+{
+ explicit value_type(int state) : state(state) { }
+ int state;
+};
+
+int swaps = 0;
+
+void
+swap(value_type& lhs, value_type& rhs)
+{
+ ++swaps;
+ using std::swap;
+ swap(lhs.state, rhs.state);
+}
+
+} // namespace ns
+
+int main()
+{
+ using O = std::experimental::optional<ns::value_type>;
+
+ VERIFY( ns::swaps == 0 );
+
+ {
+ O o, p;
+ swap(o, p);
+ VERIFY( !o );
+ VERIFY( !p );
+ }
+
+ {
+ O o { std::experimental::in_place, 45 }, p;
+ swap(o, p);
+ VERIFY( !o );
+ VERIFY( p && p->state == 45 );
+ }
+
+ {
+ O o, p { std::experimental::in_place, 45 };
+ swap(o, p);
+ VERIFY( o && o->state == 45 );
+ VERIFY( !p );
+ }
+
+ {
+ O o { std::experimental::in_place, 167 }, p { std::experimental::in_place, 999 };
+ VERIFY( ns::swaps == 0 );
+
+ swap(o, p);
+
+ VERIFY( o && o->state == 999 );
+ VERIFY( p && p->state == 167 );
+ VERIFY( ns::swaps == 1 );
+ }
+
+ VERIFY( counter == 0 );
+}
diff --git a/libstdc++-v3/testsuite/lib/libstdc++.exp b/libstdc++-v3/testsuite/lib/libstdc++.exp
index 83a3862fbd0..0dff98caa66 100644
--- a/libstdc++-v3/testsuite/lib/libstdc++.exp
+++ b/libstdc++-v3/testsuite/lib/libstdc++.exp
@@ -283,7 +283,7 @@ proc libstdc++_init { testfile } {
v3track cxxflags 2
# Always use MO files built by this test harness.
- set cxxflags "$cxxflags -DLOCALEDIR=\".\""
+ set cxxflags "-fdiagnostics-color=never $cxxflags -DLOCALEDIR=\".\""
set ccflags "$cxxflags -DLOCALEDIR=\".\""
# If a PCH file is available, use it. We must delay performing
diff --git a/libstdc++-v3/testsuite/libstdc++-dg/conformance.exp b/libstdc++-v3/testsuite/libstdc++-dg/conformance.exp
index 5e7ba3ae9d7..b6976fcb4b2 100644
--- a/libstdc++-v3/testsuite/libstdc++-dg/conformance.exp
+++ b/libstdc++-v3/testsuite/libstdc++-dg/conformance.exp
@@ -60,6 +60,7 @@ if {[info exists tests_file] && [file exists $tests_file]} {
lappend subdirs "$srcdir/tr1"
lappend subdirs "$srcdir/tr2"
lappend subdirs "$srcdir/decimal"
+ lappend subdirs "$srcdir/experimental"
verbose "subdirs are $subdirs"
# Find all the tests.
diff --git a/libstdc++-v3/testsuite/performance/25_algorithms/sort.cc b/libstdc++-v3/testsuite/performance/25_algorithms/sort.cc
new file mode 100644
index 00000000000..07062ab8b3f
--- /dev/null
+++ b/libstdc++-v3/testsuite/performance/25_algorithms/sort.cc
@@ -0,0 +1,65 @@
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <vector>
+#include <algorithm>
+#include <testsuite_performance.h>
+
+int main()
+{
+ using namespace __gnu_test;
+
+ time_counter time;
+ resource_counter resource;
+
+ const int max_size = 10000000;
+
+ std::vector<int> v(max_size);
+
+ for (int i = 0; i < max_size; ++i)
+ v[i] = -i;
+
+ start_counters(time, resource);
+ std::sort(v.begin(), v.end());
+ stop_counters(time, resource);
+
+ report_performance(__FILE__, "reverse", time, resource);
+ clear_counters(time, resource);
+
+ for (int i = 0; i < max_size; ++i)
+ v[i] = i;
+
+ start_counters(time, resource);
+ std::sort(v.begin(), v.end());
+ stop_counters(time, resource);
+
+ report_performance(__FILE__, "forwards", time, resource);
+ clear_counters(time, resource);
+
+ // a simple psuedo-random series which does not rely on rand() and friends
+ v[0] = 0;
+ for (int i = 1; i < max_size; ++i)
+ v[i] = (v[i-1] + 110211473) * 745988807;
+
+ start_counters(time, resource);
+ std::sort(v.begin(), v.end());
+ stop_counters(time, resource);
+
+ report_performance(__FILE__, "random", time, resource);
+
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/performance/25_algorithms/sort_heap.cc b/libstdc++-v3/testsuite/performance/25_algorithms/sort_heap.cc
new file mode 100644
index 00000000000..63cb2248033
--- /dev/null
+++ b/libstdc++-v3/testsuite/performance/25_algorithms/sort_heap.cc
@@ -0,0 +1,73 @@
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <vector>
+#include <algorithm>
+#include <testsuite_performance.h>
+
+int main()
+{
+ using namespace __gnu_test;
+
+ time_counter time;
+ resource_counter resource;
+
+ const int max_size = 10000000;
+
+ std::vector<int> v(max_size);
+
+ for (int i = 0; i < max_size; ++i)
+ v[i] = -i;
+
+ start_counters(time, resource);
+ std::make_heap(v.begin(), v.end());
+ stop_counters(time, resource);
+
+ report_performance(__FILE__, "make_heap_reverse", time, resource);
+ clear_counters(time, resource);
+
+ for (int i = 0; i < max_size; ++i)
+ v[i] = i;
+
+ start_counters(time, resource);
+ std::make_heap(v.begin(), v.end());
+ stop_counters(time, resource);
+
+ report_performance(__FILE__, "make_heap_forwards", time, resource);
+ clear_counters(time, resource);
+
+ // a simple psuedo-random series which does not rely on rand() and friends
+ v[0] = 0;
+ for (int i = 1; i < max_size; ++i)
+ v[i] = (v[i-1] + 110211473) * 745988807;
+
+ start_counters(time, resource);
+ std::make_heap(v.begin(), v.end());
+ stop_counters(time, resource);
+
+ report_performance(__FILE__, "make_heap_random", time, resource);
+
+
+ start_counters(time, resource);
+ std::sort_heap(v.begin(), v.end());
+ stop_counters(time, resource);
+
+ report_performance(__FILE__, "sort_heap", time, resource);
+ clear_counters(time, resource);
+
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/performance/25_algorithms/stable_sort.cc b/libstdc++-v3/testsuite/performance/25_algorithms/stable_sort.cc
new file mode 100644
index 00000000000..6440eb35f8f
--- /dev/null
+++ b/libstdc++-v3/testsuite/performance/25_algorithms/stable_sort.cc
@@ -0,0 +1,65 @@
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <vector>
+#include <algorithm>
+#include <testsuite_performance.h>
+
+int main()
+{
+ using namespace __gnu_test;
+
+ time_counter time;
+ resource_counter resource;
+
+ const int max_size = 10000000;
+
+ std::vector<int> v(max_size);
+
+ for (int i = 0; i < max_size; ++i)
+ v[i] = -i;
+
+ start_counters(time, resource);
+ std::stable_sort(v.begin(), v.end());
+ stop_counters(time, resource);
+
+ report_performance(__FILE__, "reverse", time, resource);
+ clear_counters(time, resource);
+
+ for (int i = 0; i < max_size; ++i)
+ v[i] = i;
+
+ start_counters(time, resource);
+ std::stable_sort(v.begin(), v.end());
+ stop_counters(time, resource);
+
+ report_performance(__FILE__, "forwards", time, resource);
+ clear_counters(time, resource);
+
+ // a simple psuedo-random series which does not rely on rand() and friends
+ v[0] = 0;
+ for (int i = 1; i < max_size; ++i)
+ v[i] = (v[i-1] + 110211473) * 745988807;
+
+ start_counters(time, resource);
+ std::stable_sort(v.begin(), v.end());
+ stop_counters(time, resource);
+
+ report_performance(__FILE__, "random", time, resource);
+
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/performance/27_io/ifstream_extract_int.cc b/libstdc++-v3/testsuite/performance/27_io/ifstream_extract_int.cc
index d22586663ce..4548e44b2ca 100644
--- a/libstdc++-v3/testsuite/performance/27_io/ifstream_extract_int.cc
+++ b/libstdc++-v3/testsuite/performance/27_io/ifstream_extract_int.cc
@@ -45,4 +45,4 @@ int main()
unlink("tmp_perf_int.txt");
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/performance/27_io/ofstream_insert_int.cc b/libstdc++-v3/testsuite/performance/27_io/ofstream_insert_int.cc
index 6bd90105a8b..48dcba2bccf 100644
--- a/libstdc++-v3/testsuite/performance/27_io/ofstream_insert_int.cc
+++ b/libstdc++-v3/testsuite/performance/27_io/ofstream_insert_int.cc
@@ -38,4 +38,4 @@ int main()
unlink("tmp_perf_int.txt");
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/performance/28_regex/split.cc b/libstdc++-v3/testsuite/performance/28_regex/split.cc
new file mode 100644
index 00000000000..e94e0318c32
--- /dev/null
+++ b/libstdc++-v3/testsuite/performance/28_regex/split.cc
@@ -0,0 +1,45 @@
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// 2013-10-08 Tim Shen <timshen91@gmail.com>
+
+#include <testsuite_performance.h>
+#include "split.h"
+
+using namespace __gnu_test;
+
+int main()
+{
+ time_counter time;
+ resource_counter resource;
+
+ source = source + source;
+ source = source + source;
+ source = source + source;
+ source = source + source;
+ source = source + source;
+ source = source + source;
+ source = source + source;
+ source = source + source;
+
+ start_counters(time, resource);
+ split(source);
+ stop_counters(time, resource);
+ report_performance(__FILE__, "", time, resource);
+
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/performance/28_regex/split.h b/libstdc++-v3/testsuite/performance/28_regex/split.h
new file mode 100644
index 00000000000..d016d9208bd
--- /dev/null
+++ b/libstdc++-v3/testsuite/performance/28_regex/split.h
@@ -0,0 +1,91 @@
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// 2013-10-26 Tim Shen <timshen91@gmail.com>
+
+#include <regex>
+
+using namespace std;
+
+void split(string s)
+{
+ regex re("\\s+");
+ for (auto it = sregex_token_iterator(s.begin(), s.end(), re, -1);
+ it != sregex_token_iterator();
+ ++it)
+ {
+ }
+}
+
+string source = "\
+// Copyright (C) 2013 Free Software Foundation, Inc.\n\
+//\n\
+// This file is part of the GNU ISO C++ Library. This library is free\n\
+// software; you can redistribute it and/or modify it under the\n\
+// terms of the GNU General Public License as published by the\n\
+// Free Software Foundation; either version 3, or (at your option)\n\
+// any later version.\n\
+\n\
+// This library is distributed in the hope that it will be useful,\n\
+// but WITHOUT ANY WARRANTY; without even the implied warranty of\n\
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\
+// GNU General Public License for more details.\n\
+\n\
+// You should have received a copy of the GNU General Public License along\n\
+// with this library; see the file COPYING3. If not see\n\
+// <http://www.gnu.org/licenses/>.\n\
+\n\
+// 2013-10-08 Tim Shen <timshen91@gmail.com>\n\
+\n\
+#include <testsuite_performance.h>\n\
+#include <regex>\n\
+\n\
+using namespace __gnu_test;\n\
+using namespace std;\n\
+\n\
+void split(string s)\n\
+{\n\
+ regex re(\"\\s+\");\n\
+ for (auto it = sregex_token_iterator(s.begin(), s.end(), re, -1);\n\
+ it != sregex_token_iterator();\n\
+ ++it)\n\
+ {\n\
+ }\n\
+}\n\
+\n\
+int main()\n\
+{\n\
+ string source = \"\";\n\
+ time_counter time;\n\
+ resource_counter resource;\n\
+\n\
+ source = source + source;\n\
+ source = source + source;\n\
+ source = source + source;\n\
+ source = source + source;\n\
+ source = source + source;\n\
+ source = source + source;\n\
+ source = source + source;\n\
+ source = source + source;\n\
+\n\
+ start_counters(time, resource);\n\
+ split(source);\n\
+ stop_counters(time, resource);\n\
+ report_performance(__FILE__, \"\", time, resource);\n\
+\n\
+ return 0;\n\
+}\n";
diff --git a/libstdc++-v3/testsuite/performance/28_regex/split_bfs.cc b/libstdc++-v3/testsuite/performance/28_regex/split_bfs.cc
new file mode 100644
index 00000000000..de2ef76a12f
--- /dev/null
+++ b/libstdc++-v3/testsuite/performance/28_regex/split_bfs.cc
@@ -0,0 +1,46 @@
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// 2013-10-26 Tim Shen <timshen91@gmail.com>
+
+#include <testsuite_performance.h>
+#define _GLIBCXX_REGEX_DFS_QUANTIFIERS_LIMIT 0
+#include "split.h"
+
+using namespace __gnu_test;
+
+int main()
+{
+ time_counter time;
+ resource_counter resource;
+
+ source = source + source;
+ source = source + source;
+ source = source + source;
+ source = source + source;
+ source = source + source;
+ source = source + source;
+ source = source + source;
+ source = source + source;
+
+ start_counters(time, resource);
+ split(source);
+ stop_counters(time, resource);
+ report_performance(__FILE__, "", time, resource);
+
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/char/cstring.cc b/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/char/cstring.cc
index d7589410b8f..7a8ac85544a 100644
--- a/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/char/cstring.cc
+++ b/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/char/cstring.cc
@@ -39,4 +39,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/char/cstring_op.cc b/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/char/cstring_op.cc
index a8631ba5bda..d9a52199bf1 100644
--- a/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/char/cstring_op.cc
+++ b/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/char/cstring_op.cc
@@ -39,4 +39,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/char/pstring.cc b/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/char/pstring.cc
index 1c76bac6f92..d917e45b5b5 100644
--- a/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/char/pstring.cc
+++ b/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/char/pstring.cc
@@ -39,4 +39,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/char/range.cc b/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/char/range.cc
index c18030848c0..5e7483342b3 100644
--- a/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/char/range.cc
+++ b/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/char/range.cc
@@ -39,4 +39,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/char/string.cc b/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/char/string.cc
index 481051a29af..9bb386aafbe 100644
--- a/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/char/string.cc
+++ b/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/char/string.cc
@@ -40,4 +40,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/char/string_op.cc b/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/char/string_op.cc
index 89f5f71065b..59f84595559 100644
--- a/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/char/string_op.cc
+++ b/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/char/string_op.cc
@@ -40,4 +40,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/wchar_t/cstring.cc b/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/wchar_t/cstring.cc
index c77864ab3bf..f2a914b1974 100644
--- a/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/wchar_t/cstring.cc
+++ b/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/wchar_t/cstring.cc
@@ -39,4 +39,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/wchar_t/cstring_op.cc b/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/wchar_t/cstring_op.cc
index d5a8067418f..d70a0e1c5d0 100644
--- a/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/wchar_t/cstring_op.cc
+++ b/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/wchar_t/cstring_op.cc
@@ -39,4 +39,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/wchar_t/pstring.cc b/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/wchar_t/pstring.cc
index fb7ff3bd141..b65ccdba297 100644
--- a/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/wchar_t/pstring.cc
+++ b/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/wchar_t/pstring.cc
@@ -39,4 +39,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/wchar_t/range.cc b/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/wchar_t/range.cc
index 94763f4b1a2..317217ac990 100644
--- a/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/wchar_t/range.cc
+++ b/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/wchar_t/range.cc
@@ -39,4 +39,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/wchar_t/string.cc b/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/wchar_t/string.cc
index 36312e4dca7..fe7852165d3 100644
--- a/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/wchar_t/string.cc
+++ b/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/wchar_t/string.cc
@@ -40,4 +40,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/wchar_t/string_op.cc b/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/wchar_t/string_op.cc
index 2d79962ea67..27b9583610b 100644
--- a/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/wchar_t/string_op.cc
+++ b/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/assign/wchar_t/string_op.cc
@@ -40,4 +40,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/ctors/char/cstring.cc b/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/ctors/char/cstring.cc
index c6c4760951b..adf8ec10003 100644
--- a/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/ctors/char/cstring.cc
+++ b/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/ctors/char/cstring.cc
@@ -38,4 +38,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/ctors/char/default.cc b/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/ctors/char/default.cc
index 4d8300c9daa..71103a84898 100644
--- a/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/ctors/char/default.cc
+++ b/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/ctors/char/default.cc
@@ -43,4 +43,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/ctors/char/pstring.cc b/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/ctors/char/pstring.cc
index fa86082d32b..c37f8250fa7 100644
--- a/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/ctors/char/pstring.cc
+++ b/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/ctors/char/pstring.cc
@@ -38,4 +38,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/ctors/char/range.cc b/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/ctors/char/range.cc
index 6d5f1b0942c..a41869d80bd 100644
--- a/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/ctors/char/range.cc
+++ b/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/ctors/char/range.cc
@@ -38,4 +38,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/ctors/char/string.cc b/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/ctors/char/string.cc
index c367d100778..1e8ab0f4ff9 100644
--- a/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/ctors/char/string.cc
+++ b/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/ctors/char/string.cc
@@ -50,4 +50,4 @@ main()
test01();
test02();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/ctors/wchar_t/cstring.cc b/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/ctors/wchar_t/cstring.cc
index 595ccaf17d6..bd7ffa27f9a 100644
--- a/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/ctors/wchar_t/cstring.cc
+++ b/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/ctors/wchar_t/cstring.cc
@@ -38,4 +38,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/ctors/wchar_t/default.cc b/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/ctors/wchar_t/default.cc
index 32a2a8fdc46..816ac2b160b 100644
--- a/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/ctors/wchar_t/default.cc
+++ b/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/ctors/wchar_t/default.cc
@@ -43,4 +43,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/ctors/wchar_t/pstring.cc b/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/ctors/wchar_t/pstring.cc
index 9742c9b5b56..31072ef435b 100644
--- a/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/ctors/wchar_t/pstring.cc
+++ b/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/ctors/wchar_t/pstring.cc
@@ -38,4 +38,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/ctors/wchar_t/range.cc b/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/ctors/wchar_t/range.cc
index f0c5ee2b13f..ccd16f2b608 100644
--- a/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/ctors/wchar_t/range.cc
+++ b/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/ctors/wchar_t/range.cc
@@ -38,4 +38,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/ctors/wchar_t/string.cc b/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/ctors/wchar_t/string.cc
index a67fddc9769..6064686d2d9 100644
--- a/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/ctors/wchar_t/string.cc
+++ b/libstdc++-v3/testsuite/tr1/7_regular_expressions/basic_regex/ctors/wchar_t/string.cc
@@ -50,4 +50,4 @@ main()
test01();
test02();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/tr1/7_regular_expressions/match_results/ctors/char/default.cc b/libstdc++-v3/testsuite/tr1/7_regular_expressions/match_results/ctors/char/default.cc
index 614845a196d..799c8cbef7a 100644
--- a/libstdc++-v3/testsuite/tr1/7_regular_expressions/match_results/ctors/char/default.cc
+++ b/libstdc++-v3/testsuite/tr1/7_regular_expressions/match_results/ctors/char/default.cc
@@ -54,4 +54,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/tr1/7_regular_expressions/regex_traits/char/ctor.cc b/libstdc++-v3/testsuite/tr1/7_regular_expressions/regex_traits/char/ctor.cc
index cca58b4888f..6ec7583e6e2 100644
--- a/libstdc++-v3/testsuite/tr1/7_regular_expressions/regex_traits/char/ctor.cc
+++ b/libstdc++-v3/testsuite/tr1/7_regular_expressions/regex_traits/char/ctor.cc
@@ -45,4 +45,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/tr1/7_regular_expressions/regex_traits/char/translate_nocase.cc b/libstdc++-v3/testsuite/tr1/7_regular_expressions/regex_traits/char/translate_nocase.cc
index 4a941ef3d04..4df0e507f64 100644
--- a/libstdc++-v3/testsuite/tr1/7_regular_expressions/regex_traits/char/translate_nocase.cc
+++ b/libstdc++-v3/testsuite/tr1/7_regular_expressions/regex_traits/char/translate_nocase.cc
@@ -38,4 +38,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/tr1/7_regular_expressions/regex_traits/char/value.cc b/libstdc++-v3/testsuite/tr1/7_regular_expressions/regex_traits/char/value.cc
index 0db6e5b583d..c317c3fe82e 100644
--- a/libstdc++-v3/testsuite/tr1/7_regular_expressions/regex_traits/char/value.cc
+++ b/libstdc++-v3/testsuite/tr1/7_regular_expressions/regex_traits/char/value.cc
@@ -45,4 +45,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/tr1/7_regular_expressions/regex_traits/wchar_t/ctor.cc b/libstdc++-v3/testsuite/tr1/7_regular_expressions/regex_traits/wchar_t/ctor.cc
index 5c869a8aedd..4f468b57aed 100644
--- a/libstdc++-v3/testsuite/tr1/7_regular_expressions/regex_traits/wchar_t/ctor.cc
+++ b/libstdc++-v3/testsuite/tr1/7_regular_expressions/regex_traits/wchar_t/ctor.cc
@@ -45,4 +45,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/tr1/7_regular_expressions/regex_traits/wchar_t/translate_nocase.cc b/libstdc++-v3/testsuite/tr1/7_regular_expressions/regex_traits/wchar_t/translate_nocase.cc
index 168999b4411..83b4ee2f802 100644
--- a/libstdc++-v3/testsuite/tr1/7_regular_expressions/regex_traits/wchar_t/translate_nocase.cc
+++ b/libstdc++-v3/testsuite/tr1/7_regular_expressions/regex_traits/wchar_t/translate_nocase.cc
@@ -38,4 +38,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/tr1/7_regular_expressions/regex_traits/wchar_t/value.cc b/libstdc++-v3/testsuite/tr1/7_regular_expressions/regex_traits/wchar_t/value.cc
index 0db6e5b583d..c317c3fe82e 100644
--- a/libstdc++-v3/testsuite/tr1/7_regular_expressions/regex_traits/wchar_t/value.cc
+++ b/libstdc++-v3/testsuite/tr1/7_regular_expressions/regex_traits/wchar_t/value.cc
@@ -45,4 +45,4 @@ main()
{
test01();
return 0;
-};
+}
diff --git a/libstdc++-v3/testsuite/tr2/dynamic_bitset/pr58729.cc b/libstdc++-v3/testsuite/tr2/dynamic_bitset/pr58729.cc
new file mode 100644
index 00000000000..7607e3f2c76
--- /dev/null
+++ b/libstdc++-v3/testsuite/tr2/dynamic_bitset/pr58729.cc
@@ -0,0 +1,64 @@
+// { dg-options "-std=gnu++11" }
+
+// 2013-10-15 Edward M. Smith-Rowland <3dw4rd@verizon.net>
+//
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// libstdc++/58729
+
+#include <tr2/dynamic_bitset>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+ std::tr2::dynamic_bitset<> pdb2{};
+
+ pdb2.resize(10, true);
+ VERIFY (pdb2 == std::tr2::dynamic_bitset<>{"1111111111"});
+
+ pdb2.resize(15);
+ VERIFY (pdb2 == std::tr2::dynamic_bitset<>{"000001111111111"});
+
+ pdb2.flip();
+ VERIFY (pdb2 == std::tr2::dynamic_bitset<>{"111110000000000"});
+
+ VERIFY (pdb2.size() == 15);
+ VERIFY (pdb2.count() == 5);
+
+ pdb2.resize(20, false);
+ VERIFY (pdb2 == std::tr2::dynamic_bitset<>{"00000111110000000000"});
+
+ pdb2.resize(25, true);
+ VERIFY (pdb2 == std::tr2::dynamic_bitset<>{"1111100000111110000000000"});
+
+ pdb2.resize(75, true);
+ VERIFY (pdb2 == std::tr2::dynamic_bitset<>{"1111111111111111111111111"
+ "1111111111111111111111111"
+ "1111100000111110000000000"});
+
+ VERIFY (pdb2.size() == 75);
+ VERIFY (pdb2.count() == 60);
+}
+
+int
+main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/util/exception/safety.h b/libstdc++-v3/testsuite/util/exception/safety.h
index 5ba9b13ce37..ca311797bad 100644
--- a/libstdc++-v3/testsuite/util/exception/safety.h
+++ b/libstdc++-v3/testsuite/util/exception/safety.h
@@ -47,22 +47,12 @@ namespace __gnu_test
const typename distribution_type::param_type p(0, __max_size);
size_type random = generator(p);
if (random < distribution.min() || random > distribution.max())
- {
- std::string __s("setup_base::generate");
- __s += "\n";
- __s += "random number generated is: ";
- char buf[40];
- __builtin_sprintf(buf, "%lu", (unsigned long)random);
- __s += buf;
- __s += " on range [";
- __builtin_sprintf(buf, "%lu", (unsigned long)distribution.min());
- __s += buf;
- __s += ", ";
- __builtin_sprintf(buf, "%lu", (unsigned long)distribution.max());
- __s += buf;
- __s += "]\n";
- std::__throw_out_of_range(__s.c_str());
- }
+ std::__throw_out_of_range_fmt(__N("setup_base::generate\n"
+ "random number generated is: %zu "
+ "out of range [%zu, %zu]\n"),
+ (size_t)random,
+ (size_t)distribution.min(),
+ (size_t)distribution.max());
return random;
}
diff --git a/libstdc++-v3/testsuite/util/testsuite_containergen.h b/libstdc++-v3/testsuite/util/testsuite_containergen.h
new file mode 100644
index 00000000000..ff512ac8a8e
--- /dev/null
+++ b/libstdc++-v3/testsuite/util/testsuite_containergen.h
@@ -0,0 +1,97 @@
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License as published by the Free Software
+// Foundation; either version 3, or (at your option) any later
+// version.
+
+// This library is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef _GLIBCXX_TESTSUITE_CONTAINER_GEN_H
+#define _GLIBCXX_TESTSUITE_CONTAINER_GEN_H
+
+#include <testsuite_container_traits.h>
+#include <random>
+
+namespace __gnu_test
+{
+ template<typename ContainerType, typename Tester, typename RandomGen>
+ void
+ test_single_container(Tester test, RandomGen& rg, int length, int domain)
+ {
+ std::vector<int> values;
+ auto dist = std::uniform_int_distribution<>(0, domain - 1);
+
+ for(int i = 0; i < length; ++i)
+ values.push_back(dist(rg));
+
+ ContainerType con(values.data(), values.data() + length);
+ test(con, rg);
+ }
+
+ template<typename ContainerType, typename Tester, typename RandomGen>
+ void
+ test_special_containers(Tester test, RandomGen& rg, int length)
+ {
+ std::vector<int> values(length);
+ ContainerType con(values.data(), values.data() + length);
+
+ for(int i = 0; i < length; ++i)
+ values[i] = 0;
+ test(con, rg);
+
+ for(int i = 0; i < length; ++i)
+ values[i] = i;
+ test(con, rg);
+
+ for(int i = 0; i < length; ++i)
+ values[i] = -i;
+ test(con, rg);
+ }
+
+ template<typename ContainerType, typename Tester>
+ void
+ test_containers(Tester test)
+ {
+ std::mt19937_64 random_gen;
+
+#ifdef SIMULATOR_TEST
+ int loops = 10;
+#else
+ int loops = 1000;
+#endif
+
+ for(int i = 0; i < loops; ++i)
+ test_special_containers<ContainerType>(test, random_gen, i);
+
+ for(int i = 1; i < 100; ++i)
+ for(int j = 0; j < loops; ++j)
+ test_single_container<ContainerType>(test, random_gen, i, i);
+
+ for(int i = 0; i < loops; ++i)
+ {
+ test_single_container<ContainerType>(test, random_gen, 10, 10);
+ test_single_container<ContainerType>(test, random_gen, 100, 10);
+ test_single_container<ContainerType>(test, random_gen, 1000, 10);
+ test_single_container<ContainerType>(test, random_gen, 10, 1000);
+ }
+
+#ifndef SIMULATOR_TEST
+ for(int i = 0; i < 1000; ++i)
+ {
+ test_single_container<ContainerType>(test, random_gen, 10000, 10);
+ test_single_container<ContainerType>(test, random_gen, 10000, 10000);
+ }
+#endif
+ }
+} // namespace __gnu_test
+
+#endif
diff --git a/libstdc++-v3/testsuite/util/testsuite_iterators.h b/libstdc++-v3/testsuite/util/testsuite_iterators.h
index 9bb58588651..c9dccb79227 100644
--- a/libstdc++-v3/testsuite/util/testsuite_iterators.h
+++ b/libstdc++-v3/testsuite/util/testsuite_iterators.h
@@ -539,6 +539,10 @@ namespace __gnu_test
return ItType<T>(pos, &bounds);
}
+ const T&
+ val(int pos)
+ { return (bounds.first)[pos]; }
+
ItType<T>
begin()
{ return it(bounds.first); }
diff --git a/libstdc++-v3/testsuite/util/testsuite_regex.h b/libstdc++-v3/testsuite/util/testsuite_regex.h
index ebd72a67258..596781a464b 100644
--- a/libstdc++-v3/testsuite/util/testsuite_regex.h
+++ b/libstdc++-v3/testsuite/util/testsuite_regex.h
@@ -31,9 +31,12 @@ namespace __gnu_test
// Test on a compilation of simple expressions, throw regex_error on error.
typedef std::regex regex_type;
typedef regex_type::flag_type flag_type;
+ typedef std::regex_constants::match_flag_type match_flag_type;
typedef std::regex_constants::error_type error_type;
typedef std::size_t size_type;
typedef std::string string_type;
+ using std::basic_regex;
+ using std::match_results;
// Utilities
struct regex_expected_fail { };
@@ -126,5 +129,178 @@ namespace __gnu_test
}
}
+ // regex_match_debug behaves like regex_match, but will run *two* executors
+ // (if there's no back-reference) and check if their results agree. If not,
+ // an exception throws. One can use them just in the way of using regex_match.
+ template<typename _Bi_iter, typename _Alloc,
+ typename _Ch_type, typename _Rx_traits>
+ bool
+ regex_match_debug(_Bi_iter __s,
+ _Bi_iter __e,
+ match_results<_Bi_iter, _Alloc>& __m,
+ const basic_regex<_Ch_type, _Rx_traits>& __re,
+ match_flag_type __flags
+ = std::regex_constants::match_default)
+ {
+ using namespace std::__detail;
+ auto __res1 = __regex_algo_impl<_Bi_iter, _Alloc, _Ch_type, _Rx_traits,
+ _RegexExecutorPolicy::_S_auto, true>
+ (__s, __e, __m, __re, __flags);
+ match_results<_Bi_iter, _Alloc> __mm;
+ auto __res2 = __regex_algo_impl<_Bi_iter, _Alloc, _Ch_type, _Rx_traits,
+ _RegexExecutorPolicy::_S_alternate, true>
+ (__s, __e, __mm, __re, __flags);
+ // __m is unspecified if return value is false.
+ if (__res1 == __res2 && (!__res1 || __m == __mm))
+ return __res1;
+ throw(std::exception());
+ }
+
+ // No match_results version
+ template<typename _Bi_iter, typename _Ch_type, typename _Rx_traits>
+ inline bool
+ regex_match_debug(_Bi_iter __first,
+ _Bi_iter __last,
+ const basic_regex<_Ch_type, _Rx_traits>& __re,
+ match_flag_type __flags
+ = std::regex_constants::match_default)
+ {
+ match_results<_Bi_iter> __what;
+ return regex_match_debug(__first, __last, __what, __re, __flags);
+ }
+
+ // C-string version
+ template<typename _Ch_type, typename _Alloc, typename _Rx_traits>
+ inline bool
+ regex_match_debug(const _Ch_type* __s,
+ match_results<const _Ch_type*, _Alloc>& __m,
+ const basic_regex<_Ch_type, _Rx_traits>& __re,
+ match_flag_type __f
+ = std::regex_constants::match_default)
+ { return regex_match_debug(__s, __s + _Rx_traits::length(__s),
+ __m, __re, __f); }
+
+ // C-string version without match_results
+ template<typename _Ch_type, class _Rx_traits>
+ inline bool
+ regex_match_debug(const _Ch_type* __s,
+ const basic_regex<_Ch_type, _Rx_traits>& __re,
+ match_flag_type __f
+ = std::regex_constants::match_default)
+ { return regex_match_debug(__s, __s + _Rx_traits::length(__s),
+ __re, __f); }
+
+ // std::basic_string version
+ template<typename _Ch_traits, typename _Ch_alloc,
+ typename _Alloc, typename _Ch_type, typename _Rx_traits>
+ inline bool
+ regex_match_debug(const std::basic_string<_Ch_type, _Ch_traits,
+ _Ch_alloc>& __s,
+ match_results<typename std::basic_string<_Ch_type,
+ _Ch_traits, _Ch_alloc>::const_iterator,
+ _Alloc>& __m,
+ const basic_regex<_Ch_type, _Rx_traits>& __re,
+ match_flag_type __flags
+ = std::regex_constants::match_default)
+ { return regex_match_debug(__s.begin(), __s.end(),
+ __m, __re, __flags); }
+
+ // std::basic_string version without match_results
+ template<typename _Ch_traits, typename _Str_allocator,
+ typename _Ch_type, typename _Rx_traits>
+ inline bool
+ regex_match_debug(const std::basic_string<_Ch_type, _Ch_traits,
+ _Str_allocator>& __s,
+ const basic_regex<_Ch_type, _Rx_traits>& __re,
+ match_flag_type __flags
+ = std::regex_constants::match_default)
+ { return regex_match_debug(__s.begin(), __s.end(), __re, __flags); }
+
+ // regex_match_debug behaves like regex_match, but will run *two* executors
+ // (if there's no back-reference) and check if their results agree. If not,
+ // an exception throws. One can use them just in the way of using regex_match.
+ template<typename _Bi_iter, typename _Alloc,
+ typename _Ch_type, typename _Rx_traits>
+ bool
+ regex_search_debug(_Bi_iter __s,
+ _Bi_iter __e,
+ match_results<_Bi_iter, _Alloc>& __m,
+ const basic_regex<_Ch_type, _Rx_traits>& __re,
+ match_flag_type __flags
+ = std::regex_constants::match_default)
+ {
+ using namespace std::__detail;
+ auto __res1 = __regex_algo_impl<_Bi_iter, _Alloc, _Ch_type, _Rx_traits,
+ _RegexExecutorPolicy::_S_auto, false>
+ (__s, __e, __m, __re, __flags);
+ match_results<_Bi_iter, _Alloc> __mm;
+ auto __res2 = __regex_algo_impl<_Bi_iter, _Alloc, _Ch_type, _Rx_traits,
+ _RegexExecutorPolicy::_S_alternate, false>
+ (__s, __e, __mm, __re, __flags);
+ if (__res1 == __res2 && __m == __mm)
+ return __res1;
+ throw(std::exception()); // Let test fail. Give it a name.
+ }
+
+ // No match_results version
+ template<typename _Bi_iter, typename _Ch_type, typename _Rx_traits>
+ inline bool
+ regex_search_debug(_Bi_iter __first,
+ _Bi_iter __last,
+ const basic_regex<_Ch_type, _Rx_traits>& __re,
+ match_flag_type __flags
+ = std::regex_constants::match_default)
+ {
+ match_results<_Bi_iter> __what;
+ return regex_search_debug(__first, __last, __what, __re, __flags);
+ }
+
+ // C-string version
+ template<typename _Ch_type, class _Alloc, class _Rx_traits>
+ inline bool
+ regex_search_debug(const _Ch_type* __s,
+ match_results<const _Ch_type*, _Alloc>& __m,
+ const basic_regex<_Ch_type, _Rx_traits>& __e,
+ match_flag_type __f
+ = std::regex_constants::match_default)
+ { return regex_search_debug(__s, __s + _Rx_traits::length(__s),
+ __m, __e, __f); }
+
+ // C-string version without match_results
+ template<typename _Ch_type, typename _Rx_traits>
+ inline bool
+ regex_search_debug(const _Ch_type* __s,
+ const basic_regex<_Ch_type, _Rx_traits>& __e,
+ match_flag_type __f
+ = std::regex_constants::match_default)
+ { return regex_search_debug(__s, __s + _Rx_traits::length(__s),
+ __e, __f); }
+
+ // std::basic_string version
+ template<typename _Ch_traits, typename _Ch_alloc,
+ typename _Alloc, typename _Ch_type,
+ typename _Rx_traits>
+ inline bool
+ regex_search_debug(const std::basic_string<_Ch_type, _Ch_traits,
+ _Ch_alloc>& __s,
+ match_results<typename std::basic_string<_Ch_type,
+ _Ch_traits, _Ch_alloc>::const_iterator, _Alloc>&
+ __m,
+ const basic_regex<_Ch_type, _Rx_traits>& __e,
+ match_flag_type __f
+ = std::regex_constants::match_default)
+ { return regex_search_debug(__s.begin(), __s.end(), __m, __e, __f); }
+
+ // std::basic_string version without match_results
+ template<typename _Ch_traits, typename _String_allocator,
+ typename _Ch_type, typename _Rx_traits>
+ inline bool
+ regex_search_debug(const std::basic_string<_Ch_type, _Ch_traits,
+ _String_allocator>& __s,
+ const basic_regex<_Ch_type, _Rx_traits>& __e,
+ match_flag_type __f
+ = std::regex_constants::match_default)
+ { return regex_search_debug(__s.begin(), __s.end(), __e, __f); }
+
} // namespace __gnu_test
#endif
diff --git a/libtool.m4 b/libtool.m4
index 8a14e2b22f9..797468f02a5 100644
--- a/libtool.m4
+++ b/libtool.m4
@@ -1220,7 +1220,7 @@ ia64-*-hpux*)
rm -rf conftest*
;;
-x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \
+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
@@ -1241,7 +1241,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
;;
esac
;;
- ppc64-*linux*|powerpc64-*linux*)
+ powerpc64le-*linux*)
+ LD="${LD-ld} -m elf32lppclinux"
+ ;;
+ powerpc64-*linux*)
LD="${LD-ld} -m elf32ppclinux"
;;
s390x-*linux*)
@@ -1260,7 +1263,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
x86_64-*linux*)
LD="${LD-ld} -m elf_x86_64"
;;
- ppc*-*linux*|powerpc*-*linux*)
+ powerpcle-*linux*)
+ LD="${LD-ld} -m elf64lppc"
+ ;;
+ powerpc-*linux*)
LD="${LD-ld} -m elf64ppc"
;;
s390*-*linux*|s390*-*tpf*)
diff --git a/libvtv/ChangeLog b/libvtv/ChangeLog
index f0a7471298c..fcbdc10efd1 100644
--- a/libvtv/ChangeLog
+++ b/libvtv/ChangeLog
@@ -1,3 +1,24 @@
+2013-09-25 Caroline Tice <cmtice@google.com>
+
+ * Makefile.am: Reinstate ENABLE_VTABLE_VERIFY checks, to make
+ sure testsuite is not run if libstdc++ and libgcc were not built
+ with vtable verification.
+ * Makefile.in: Regenerated.
+ * configure.ac: Reinstate checks for --enable-vtable-verify flag,
+ to make sure testsuite is not run if libstdc++ and libgcc were not
+ built with vtable verification.
+ * configure: Regenerated.
+
+2013-09-24 Caroline Tice <cmtice@google.com>
+
+ * Makefile.am: Change libvtv_includedir to the directory used by
+ the other libraries rather than the top include directory.
+ * Makefile.in: Regenerated.
+
+2013-09-20 Alan Modra <amodra@gmail.com>
+
+ * configure: Regenerate.
+
2013-09-12 Alexander Ivchenko <alexander.ivchenko@intel.com>
* configure.tgt: Remove *-*-*android* from supported targets.
@@ -119,12 +140,12 @@
for 'open'. Update function comment.
* vtv_rts.cc (log_memory_protection_data): Remove %d from file name.
-2013-08-08 Benjamin Kosnik <bkoz@rehat.com>
+2013-08-08 Benjamin Kosnik <bkoz@redhat.com>
Michael Meissner <meissner@linux.vnet.ibm.com>
* configure.tgt : Simplify, just use VTV_SUPPORTED.
-2013-08-07 Benjamin Kosnik <bkoz@rehat.com>
+2013-08-07 Benjamin Kosnik <bkoz@redhat.com>
* Makefile.am (SUBDIRS): Protect with ENABLE_VTABLE_VERIFY.
* Makefile.in: Regenerate.
diff --git a/libvtv/Makefile.am b/libvtv/Makefile.am
index c3983effb7d..886d7e6be8d 100644
--- a/libvtv/Makefile.am
+++ b/libvtv/Makefile.am
@@ -19,7 +19,11 @@
## along with this library; see the file COPYING3. If not see
## <http://www.gnu.org/licenses/>.
-SUBDIRS = testsuite
+if ENABLE_VTABLE_VERIFY
+ SUBDIRS = testsuite
+else
+ SUBDIRS=
+endif
ACLOCAL_AMFLAGS = -I .. -I ../config
@@ -51,7 +55,7 @@ vtv_sources = \
vtv_utils.cc \
vtv_end.c
-libvtv_includedir = $(includedir)
+libvtv_includedir = $(libdir)/gcc/$(target_alias)/$(gcc_version)/include
# Link in vtv_start and vtv_end.
BUILT_SOURCES = vtv_start.c vtv_end.c
@@ -63,8 +67,13 @@ vtv_end.c:
rm -f $@
$(LN_S) $(toplevel_srcdir)/libgcc/vtv_end.c $@
-libvtv_la_SOURCES = $(vtv_sources)
-libvtv_include_HEADERS = $(vtv_headers)
+if ENABLE_VTABLE_VERIFY
+ libvtv_la_SOURCES = $(vtv_sources)
+ libvtv_include_HEADERS = $(vtv_headers)
+else
+ libvtv_la_SOURCES =
+ libvtv_include_HEADERS =
+endif
# Least ordering for dependencies mean linking w/o libstdc++ for as
# long as the development of libvtv does not absolutely require it.
diff --git a/libvtv/Makefile.in b/libvtv/Makefile.in
index e021d42fd14..d77a41f0477 100644
--- a/libvtv/Makefile.in
+++ b/libvtv/Makefile.in
@@ -40,7 +40,7 @@ subdir = .
DIST_COMMON = ChangeLog $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
$(top_srcdir)/configure $(am__configure_deps) \
$(srcdir)/../mkinstalldirs $(srcdir)/../depcomp \
- $(libvtv_include_HEADERS)
+ $(am__libvtv_include_HEADERS_DIST)
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \
$(top_srcdir)/../config/depstand.m4 \
@@ -86,7 +86,7 @@ LTLIBRARIES = $(toolexeclib_LTLIBRARIES)
libvtv_la_LIBADD =
am__objects_1 = vtv_start.lo vtv_malloc.lo vtv_rts.lo vtv_utils.lo \
vtv_end.lo
-am_libvtv_la_OBJECTS = $(am__objects_1)
+@ENABLE_VTABLE_VERIFY_TRUE@am_libvtv_la_OBJECTS = $(am__objects_1)
libvtv_la_OBJECTS = $(am_libvtv_la_OBJECTS)
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/../depcomp
@@ -118,6 +118,8 @@ RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
install-pdf-recursive install-ps-recursive install-recursive \
installcheck-recursive installdirs-recursive pdf-recursive \
ps-recursive uninstall-recursive
+am__libvtv_include_HEADERS_DIST = vtv_map.h vtv_malloc.h vtv_fail.h \
+ vtv_set.h vtv_utils.h vtv_rts.h
HEADERS = $(libvtv_include_HEADERS)
RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
distclean-recursive maintainer-clean-recursive
@@ -125,7 +127,7 @@ AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
$(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS
ETAGS = etags
CTAGS = ctags
-DIST_SUBDIRS = $(SUBDIRS)
+DIST_SUBDIRS = testsuite
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AR = @AR@
@@ -263,7 +265,8 @@ top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
toplevel_builddir = @toplevel_builddir@
toplevel_srcdir = @toplevel_srcdir@
-SUBDIRS = testsuite
+@ENABLE_VTABLE_VERIFY_FALSE@SUBDIRS =
+@ENABLE_VTABLE_VERIFY_TRUE@SUBDIRS = testsuite
ACLOCAL_AMFLAGS = -I .. -I ../config
# May be used by toolexeclibdir.
@@ -289,12 +292,14 @@ vtv_sources = \
vtv_utils.cc \
vtv_end.c
-libvtv_includedir = $(includedir)
+libvtv_includedir = $(libdir)/gcc/$(target_alias)/$(gcc_version)/include
# Link in vtv_start and vtv_end.
BUILT_SOURCES = vtv_start.c vtv_end.c
-libvtv_la_SOURCES = $(vtv_sources)
-libvtv_include_HEADERS = $(vtv_headers)
+@ENABLE_VTABLE_VERIFY_FALSE@libvtv_la_SOURCES =
+@ENABLE_VTABLE_VERIFY_TRUE@libvtv_la_SOURCES = $(vtv_sources)
+@ENABLE_VTABLE_VERIFY_FALSE@libvtv_include_HEADERS =
+@ENABLE_VTABLE_VERIFY_TRUE@libvtv_include_HEADERS = $(vtv_headers)
# Least ordering for dependencies mean linking w/o libstdc++ for as
# long as the development of libvtv does not absolutely require it.
@@ -324,9 +329,9 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi
exit 1;; \
esac; \
done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign ./Makefile'; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \
$(am__cd) $(top_srcdir) && \
- $(AUTOMAKE) --foreign ./Makefile
+ $(AUTOMAKE) --foreign Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
diff --git a/libvtv/configure b/libvtv/configure
index 0bd614a0db4..5a73f26ace7 100755
--- a/libvtv/configure
+++ b/libvtv/configure
@@ -684,6 +684,8 @@ am__isrc
INSTALL_DATA
INSTALL_SCRIPT
INSTALL_PROGRAM
+ENABLE_VTABLE_VERIFY_FALSE
+ENABLE_VTABLE_VERIFY_TRUE
LIBSTDCXX_RAW_CXX_LDFLAGS
LIBSTDCXX_RAW_CXX_CXXFLAGS
target_noncanonical
@@ -741,6 +743,7 @@ ac_subst_files=''
ac_user_opts='
enable_option_checking
enable_version_specific_runtime_libs
+enable_vtable_verify
enable_multilib
enable_maintainer_mode
enable_dependency_tracking
@@ -1382,6 +1385,7 @@ Optional Features:
--disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
--enable-FEATURE[=ARG] include FEATURE [ARG=yes]
--enable-version-specific-runtime-libs Specify that runtime libraries should be installed in a compiler-specific directory
+ --enable-vtable-verify Enable vtable verification feature
--enable-multilib build many library versions (default)
--enable-maintainer-mode enable make rules and dependencies not useful
(and sometimes confusing) to the casual installer
@@ -2506,6 +2510,23 @@ esac
+# Use same top-level configure hooks in libgcc/libstdc++/libvtv.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for --enable-vtable-verify" >&5
+$as_echo_n "checking for --enable-vtable-verify... " >&6; }
+# Check whether --enable-vtable-verify was given.
+if test "${enable_vtable_verify+set}" = set; then :
+ enableval=$enable_vtable_verify; case "$enableval" in
+ yes) enable_vtable_verify=yes ;;
+ no) enable_vtable_verify=no ;;
+ *) enable_vtable_verify=no;;
+ esac
+else
+ enable_vtable_verify=no
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_vtable_verify" >&5
+$as_echo "$enable_vtable_verify" >&6; }
+
# See if supported.
unset VTV_SUPPORTED
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for host support for vtable verification" >&5
@@ -2517,10 +2538,20 @@ $as_echo "$VTV_SUPPORTED" >&6; }
# Decide if it's usable.
use_vtable_verify=no
if test "x$VTV_SUPPORTED" = "xyes"; then
- use_vtable_verify=yes
- { $as_echo "$as_me:${as_lineno-$LINENO}: using vtable verification" >&5
+ if test "x$enable_vtable_verify" = "xyes"; then
+ use_vtable_verify=yes
+ { $as_echo "$as_me:${as_lineno-$LINENO}: using vtable verification" >&5
$as_echo "$as_me: using vtable verification" >&6;}
+ fi
fi
+ if test $use_vtable_verify = yes; then
+ ENABLE_VTABLE_VERIFY_TRUE=
+ ENABLE_VTABLE_VERIFY_FALSE='#'
+else
+ ENABLE_VTABLE_VERIFY_TRUE='#'
+ ENABLE_VTABLE_VERIFY_FALSE=
+fi
+
am__api_version='1.11'
@@ -7851,7 +7882,7 @@ ia64-*-hpux*)
rm -rf conftest*
;;
-x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \
+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
@@ -7876,7 +7907,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
;;
esac
;;
- ppc64-*linux*|powerpc64-*linux*)
+ powerpc64le-*linux*)
+ LD="${LD-ld} -m elf32lppclinux"
+ ;;
+ powerpc64-*linux*)
LD="${LD-ld} -m elf32ppclinux"
;;
s390x-*linux*)
@@ -7895,7 +7929,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
x86_64-*linux*)
LD="${LD-ld} -m elf_x86_64"
;;
- ppc*-*linux*|powerpc*-*linux*)
+ powerpcle-*linux*)
+ LD="${LD-ld} -m elf64lppc"
+ ;;
+ powerpc-*linux*)
LD="${LD-ld} -m elf64ppc"
;;
s390*-*linux*|s390*-*tpf*)
@@ -12090,7 +12127,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 12093 "configure"
+#line 12099 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -12196,7 +12233,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 12199 "configure"
+#line 12205 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -15469,7 +15506,7 @@ ac_config_files="$ac_config_files Makefile"
if test "x$VTV_SUPPORTED" = "xyes"; then
- ac_config_files="$ac_config_files ./Makefile testsuite/Makefile"
+ ac_config_files="$ac_config_files testsuite/Makefile"
fi
@@ -15606,6 +15643,10 @@ LIBOBJS=$ac_libobjs
LTLIBOBJS=$ac_ltlibobjs
+if test -z "${ENABLE_VTABLE_VERIFY_TRUE}" && test -z "${ENABLE_VTABLE_VERIFY_FALSE}"; then
+ as_fn_error "conditional \"ENABLE_VTABLE_VERIFY\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
if test -n "$EXEEXT"; then
am__EXEEXT_TRUE=
am__EXEEXT_FALSE='#'
@@ -16587,7 +16628,6 @@ do
"depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
"libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;;
"Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
- "./Makefile") CONFIG_FILES="$CONFIG_FILES ./Makefile" ;;
"testsuite/Makefile") CONFIG_FILES="$CONFIG_FILES testsuite/Makefile" ;;
*) as_fn_error "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
@@ -17920,17 +17960,6 @@ compiler_lib_search_path=$lt_compiler_lib_search_path_CXX
_LT_EOF
;;
- "./Makefile":F) cat > vpsed$$ << \_EOF
-s!`test -f '$<' || echo '$(srcdir)/'`!!
-_EOF
- sed -f vpsed$$ $ac_file > tmp$$
- mv tmp$$ $ac_file
- rm vpsed$$
- echo 'MULTISUBDIR =' >> $ac_file
- ml_norecursion=yes
- . ${multi_basedir}/config-ml.in
- { ml_norecursion=; unset ml_norecursion;}
- ;;
"testsuite/Makefile":F) cat > vpsed$$ << \_EOF
s!`test -f '$<' || echo '$(srcdir)/'`!!
_EOF
diff --git a/libvtv/configure.ac b/libvtv/configure.ac
index e3fb92fc29e..12b4664de2e 100644
--- a/libvtv/configure.ac
+++ b/libvtv/configure.ac
@@ -27,6 +27,18 @@ target_alias=${target_alias-$host_alias}
AC_SUBST(target_alias)
GCC_LIBSTDCXX_RAW_CXX_FLAGS
+# Use same top-level configure hooks in libgcc/libstdc++/libvtv.
+AC_MSG_CHECKING([for --enable-vtable-verify])
+AC_ARG_ENABLE(vtable-verify,
+[ --enable-vtable-verify Enable vtable verification feature ],
+[case "$enableval" in
+ yes) enable_vtable_verify=yes ;;
+ no) enable_vtable_verify=no ;;
+ *) enable_vtable_verify=no;;
+ esac],
+[enable_vtable_verify=no])
+AC_MSG_RESULT($enable_vtable_verify)
+
# See if supported.
unset VTV_SUPPORTED
AC_MSG_CHECKING([for host support for vtable verification])
@@ -36,9 +48,12 @@ AC_MSG_RESULT($VTV_SUPPORTED)
# Decide if it's usable.
use_vtable_verify=no
if test "x$VTV_SUPPORTED" = "xyes"; then
- use_vtable_verify=yes
- AC_MSG_NOTICE(using vtable verification)
+ if test "x$enable_vtable_verify" = "xyes"; then
+ use_vtable_verify=yes
+ AC_MSG_NOTICE(using vtable verification)
+ fi
fi
+AM_CONDITIONAL(ENABLE_VTABLE_VERIFY, test $use_vtable_verify = yes)
AM_INIT_AUTOMAKE(foreign no-dist)
AM_ENABLE_MULTILIB(, ..)
@@ -126,7 +141,7 @@ fi
AC_CONFIG_FILES([Makefile])
if test "x$VTV_SUPPORTED" = "xyes"; then
- AC_CONFIG_FILES(AC_FOREACH([DIR], [. testsuite], [DIR/Makefile ]),
+ AC_CONFIG_FILES(AC_FOREACH([DIR], [testsuite], [DIR/Makefile ]),
[cat > vpsed$$ << \_EOF
s!`test -f '$<' || echo '$(srcdir)/'`!!
_EOF
diff --git a/lto-plugin/ChangeLog b/lto-plugin/ChangeLog
index c8ed0f3f6e7..09fcbb8e66e 100644
--- a/lto-plugin/ChangeLog
+++ b/lto-plugin/ChangeLog
@@ -1,3 +1,7 @@
+2013-09-20 Alan Modra <amodra@gmail.com>
+
+ * configure: Regenerate.
+
2012-09-14 David Edelsohn <dje.gcc@gmail.com>
* configure: Regenerated.
@@ -330,7 +334,7 @@
(claim_file_handler): Add n variable. Check return value of
process_symtab. Call resolve_conflicts.
-2010-07-27 Andi Kleen <ak@linux.intel.com>
+2010-07-27 Andi Kleen <ak@linux.intel.com>
* lto-plugin.c (translate): Remove debug fprintf.
@@ -339,7 +343,7 @@
PR bootstrap/45042
* lto-plugin.c (translate): Cast to unsigned long.
-2010-07-23 Andi Kleen <ak@linux.intel.com>
+2010-07-23 Andi Kleen <ak@linux.intel.com>
PR lto/44992
* lto-plugin.c (sym_aux): Add.
diff --git a/lto-plugin/configure b/lto-plugin/configure
index 77f2d61b384..ee4730d49a9 100755
--- a/lto-plugin/configure
+++ b/lto-plugin/configure
@@ -6047,7 +6047,7 @@ ia64-*-hpux*)
rm -rf conftest*
;;
-x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \
+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
@@ -6072,7 +6072,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
;;
esac
;;
- ppc64-*linux*|powerpc64-*linux*)
+ powerpc64le-*linux*)
+ LD="${LD-ld} -m elf32lppclinux"
+ ;;
+ powerpc64-*linux*)
LD="${LD-ld} -m elf32ppclinux"
;;
s390x-*linux*)
@@ -6091,7 +6094,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
x86_64-*linux*)
LD="${LD-ld} -m elf_x86_64"
;;
- ppc*-*linux*|powerpc*-*linux*)
+ powerpcle-*linux*)
+ LD="${LD-ld} -m elf64lppc"
+ ;;
+ powerpc-*linux*)
LD="${LD-ld} -m elf64ppc"
;;
s390*-*linux*|s390*-*tpf*)
@@ -10555,7 +10561,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 10558 "configure"
+#line 10564 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -10661,7 +10667,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 10664 "configure"
+#line 10670 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
diff --git a/zlib/ChangeLog.gcj b/zlib/ChangeLog.gcj
index 13b62a4a129..f32e3028496 100644
--- a/zlib/ChangeLog.gcj
+++ b/zlib/ChangeLog.gcj
@@ -1,3 +1,15 @@
+2013-10-15 David Malcolm <dmalcolm@redhat.com>
+
+ * configure.ac: Add --enable-host-shared, setting up new
+ PICFLAG variable.
+ * Makefile.am: Add PICFLAG to libz_a_CFLAGS.
+ * Makefile.in: Regenerate.
+ * configure: Regenerate.
+
+2013-09-20 Alan Modra <amodra@gmail.com>
+
+ * configure: Regenerate.
+
2012-11-16 Matthias Klose <doko@ubuntu.com>
* Imported zlib 1.2.7; merged local changes.
diff --git a/zlib/Makefile.am b/zlib/Makefile.am
index a9c42cb2cf5..82f709d9ec7 100644
--- a/zlib/Makefile.am
+++ b/zlib/Makefile.am
@@ -16,7 +16,7 @@ libzgcj_convenience_la_SOURCES = $(ZLIB_SOURCES)
else
toolexeclib_LIBRARIES = libz.a
libz_a_SOURCES = $(ZLIB_SOURCES)
-libz_a_CFLAGS = $(AM_CFLAGS)
+libz_a_CFLAGS = $(AM_CFLAGS) $(PICFLAG)
endif
# Work around what appears to be a GNU make bug handling MAKEFLAGS
diff --git a/zlib/Makefile.in b/zlib/Makefile.in
index 4d4d1e484ff..82b72a16367 100644
--- a/zlib/Makefile.in
+++ b/zlib/Makefile.in
@@ -205,6 +205,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
+PICFLAG = @PICFLAG@
RANLIB = @RANLIB@
SED = @SED@
SET_MAKE = @SET_MAKE@
@@ -283,7 +284,7 @@ zconf.h.in zlib.h zutil.c zutil.h
@TARGET_LIBRARY_TRUE@libzgcj_convenience_la_SOURCES = $(ZLIB_SOURCES)
@TARGET_LIBRARY_FALSE@toolexeclib_LIBRARIES = libz.a
@TARGET_LIBRARY_FALSE@libz_a_SOURCES = $(ZLIB_SOURCES)
-@TARGET_LIBRARY_FALSE@libz_a_CFLAGS = $(AM_CFLAGS)
+@TARGET_LIBRARY_FALSE@libz_a_CFLAGS = $(AM_CFLAGS) $(PICFLAG)
# Work around what appears to be a GNU make bug handling MAKEFLAGS
# values defined in terms of make variables, as is the case for CC and
diff --git a/zlib/configure b/zlib/configure
index 38b3b25e720..885c802bfb2 100755
--- a/zlib/configure
+++ b/zlib/configure
@@ -602,6 +602,7 @@ ac_subst_vars='am__EXEEXT_FALSE
am__EXEEXT_TRUE
LTLIBOBJS
LIBOBJS
+PICFLAG
TARGET_LIBRARY_FALSE
TARGET_LIBRARY_TRUE
toolexeclibdir
@@ -737,6 +738,7 @@ with_pic
enable_fast_install
with_gnu_ld
enable_libtool_lock
+enable_host_shared
'
ac_precious_vars='build_alias
host_alias
@@ -1371,6 +1373,7 @@ Optional Features:
--enable-fast-install[=PKGS]
optimize for fast installation [default=yes]
--disable-libtool-lock avoid locking (might break parallel builds)
+ --enable-host-shared build host code as shared libraries
Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
@@ -5856,7 +5859,7 @@ ia64-*-hpux*)
rm -rf conftest*
;;
-x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \
+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
@@ -5881,7 +5884,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
;;
esac
;;
- ppc64-*linux*|powerpc64-*linux*)
+ powerpc64le-*linux*)
+ LD="${LD-ld} -m elf32lppclinux"
+ ;;
+ powerpc64-*linux*)
LD="${LD-ld} -m elf32ppclinux"
;;
s390x-*linux*)
@@ -5900,7 +5906,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
x86_64-*linux*)
LD="${LD-ld} -m elf_x86_64"
;;
- ppc*-*linux*|powerpc*-*linux*)
+ powerpcle-*linux*)
+ LD="${LD-ld} -m elf64lppc"
+ ;;
+ powerpc-*linux*)
LD="${LD-ld} -m elf64ppc"
;;
s390*-*linux*|s390*-*tpf*)
@@ -10397,7 +10406,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 10400 "configure"
+#line 10409 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -10503,7 +10512,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 10506 "configure"
+#line 10515 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -11199,6 +11208,15 @@ else
multilib_arg=
fi
+# Check whether --enable-host-shared was given.
+if test "${enable_host_shared+set}" = set; then :
+ enableval=$enable_host_shared; PICFLAG=-fPIC
+else
+ PICFLAG=
+fi
+
+
+
ac_config_files="$ac_config_files Makefile"
cat >confcache <<\_ACEOF
diff --git a/zlib/configure.ac b/zlib/configure.ac
index 80253e4fc5d..fb8d943905e 100644
--- a/zlib/configure.ac
+++ b/zlib/configure.ac
@@ -119,5 +119,11 @@ else
multilib_arg=
fi
+AC_ARG_ENABLE(host-shared,
+[AS_HELP_STRING([--enable-host-shared],
+ [build host code as shared libraries])],
+[PICFLAG=-fPIC], [PICFLAG=])
+AC_SUBST(PICFLAG)
+
AC_CONFIG_FILES([Makefile])
AC_OUTPUT